[
  {
    "path": ".gitee/ISSUE_TEMPLATE.zh-CN.md",
    "content": "### 该问题是怎么引起的？\n\n\n\n\n### 重现步骤\n\n\n\n\n### 报错信息\n\n\n\n\n"
  },
  {
    "path": ".gitee/PULL_REQUEST_TEMPLATE.zh-CN.md",
    "content": "### 该Pull Request关联的Issue\n\n\n### 修改描述\n\n\n\n### 测试用例\n\n\n\n### 修复效果的截屏\n\n\n\n"
  },
  {
    "path": ".gitignore",
    "content": "# maven ignore\ntarget/\n*.jar\n*.war\n*.zip\n*.tar\n*.tar.gz\n*.class\n*.project\n\n# eclipse ignore\n.settings/\n.classpath\ntarget/\nbin/\nopen-cxf-service/\nopen-elasticsearch/\n\n\n# idea ignore\n.idea/\n*.ipr\n*.iml\n*.iws\n\n# temp ignore\n*.log\n*.cache\n*.diff\n*.patch\n*.tmp\n\n# system ignore\n.DS_Store\nThumbs.db\n\n# else\n.springBeans\n/open-layui-web/logs/\n"
  },
  {
    "path": ".tgitconfig",
    "content": ""
  },
  {
    "path": "LICENSE",
    "content": "Apache License\nVersion 2.0, January 2004\nhttp://www.apache.org/licenses/\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n1. Definitions.\n\n\"License\" shall mean the terms and conditions for use, reproduction, and\ndistribution as defined by Sections 1 through 9 of this document.\n\n\"Licensor\" shall mean the copyright owner or entity authorized by the copyright\nowner that is granting the License.\n\n\"Legal Entity\" shall mean the union of the acting entity and all other entities\nthat control, are controlled by, or are under common control with that entity.\nFor the purposes of this definition, \"control\" means (i) the power, direct or\nindirect, to cause the direction or management of such entity, whether by\ncontract or otherwise, or (ii) ownership of fifty percent (50%) or more of the\noutstanding shares, or (iii) beneficial ownership of such entity.\n\n\"You\" (or \"Your\") shall mean an individual or Legal Entity exercising\npermissions granted by this License.\n\n\"Source\" form shall mean the preferred form for making modifications, including\nbut not limited to software source code, documentation source, and configuration\nfiles.\n\n\"Object\" form shall mean any form resulting from mechanical transformation or\ntranslation of a Source form, including but not limited to compiled object code,\ngenerated documentation, and conversions to other media types.\n\n\"Work\" shall mean the work of authorship, whether in Source or Object form, made\navailable under the License, as indicated by a copyright notice that is included\nin or attached to the work (an example is provided in the Appendix below).\n\n\"Derivative Works\" shall mean any work, whether in Source or Object form, that\nis based on (or derived from) the Work and for which the editorial revisions,\nannotations, elaborations, or other modifications represent, as a whole, an\noriginal work of authorship. For the purposes of this License, Derivative Works\nshall not include works that remain separable from, or merely link (or bind by\nname) to the interfaces of, the Work and Derivative Works thereof.\n\n\"Contribution\" shall mean any work of authorship, including the original version\nof the Work and any modifications or additions to that Work or Derivative Works\nthereof, that is intentionally submitted to Licensor for inclusion in the Work\nby the copyright owner or by an individual or Legal Entity authorized to submit\non behalf of the copyright owner. For the purposes of this definition,\n\"submitted\" means any form of electronic, verbal, or written communication sent\nto the Licensor or its representatives, including but not limited to\ncommunication on electronic mailing lists, source code control systems, and\nissue tracking systems that are managed by, or on behalf of, the Licensor for\nthe purpose of discussing and improving the Work, but excluding communication\nthat is conspicuously marked or otherwise designated in writing by the copyright\nowner as \"Not a Contribution.\"\n\n\"Contributor\" shall mean Licensor and any individual or Legal Entity on behalf\nof whom a Contribution has been received by Licensor and subsequently\nincorporated within the Work.\n\n2. Grant of Copyright License.\n\nSubject to the terms and conditions of this License, each Contributor hereby\ngrants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,\nirrevocable copyright license to reproduce, prepare Derivative Works of,\npublicly display, publicly perform, sublicense, and distribute the Work and such\nDerivative Works in Source or Object form.\n\n3. Grant of Patent License.\n\nSubject to the terms and conditions of this License, each Contributor hereby\ngrants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,\nirrevocable (except as stated in this section) patent license to make, have\nmade, use, offer to sell, sell, import, and otherwise transfer the Work, where\nsuch license applies only to those patent claims licensable by such Contributor\nthat are necessarily infringed by their Contribution(s) alone or by combination\nof their Contribution(s) with the Work to which such Contribution(s) was\nsubmitted. If You institute patent litigation against any entity (including a\ncross-claim or counterclaim in a lawsuit) alleging that the Work or a\nContribution incorporated within the Work constitutes direct or contributory\npatent infringement, then any patent licenses granted to You under this License\nfor that Work shall terminate as of the date such litigation is filed.\n\n4. Redistribution.\n\nYou may reproduce and distribute copies of the Work or Derivative Works thereof\nin any medium, with or without modifications, and in Source or Object form,\nprovided that You meet the following conditions:\n\nYou must give any other recipients of the Work or Derivative Works a copy of\nthis License; and\nYou must cause any modified files to carry prominent notices stating that You\nchanged the files; and\nYou must retain, in the Source form of any Derivative Works that You distribute,\nall copyright, patent, trademark, and attribution notices from the Source form\nof the Work, excluding those notices that do not pertain to any part of the\nDerivative Works; and\nIf the Work includes a \"NOTICE\" text file as part of its distribution, then any\nDerivative Works that You distribute must include a readable copy of the\nattribution notices contained within such NOTICE file, excluding those notices\nthat do not pertain to any part of the Derivative Works, in at least one of the\nfollowing places: within a NOTICE text file distributed as part of the\nDerivative Works; within the Source form or documentation, if provided along\nwith the Derivative Works; or, within a display generated by the Derivative\nWorks, if and wherever such third-party notices normally appear. The contents of\nthe NOTICE file are for informational purposes only and do not modify the\nLicense. You may add Your own attribution notices within Derivative Works that\nYou distribute, alongside or as an addendum to the NOTICE text from the Work,\nprovided that such additional attribution notices cannot be construed as\nmodifying the License.\nYou may add Your own copyright statement to Your modifications and may provide\nadditional or different license terms and conditions for use, reproduction, or\ndistribution of Your modifications, or for any such Derivative Works as a whole,\nprovided Your use, reproduction, and distribution of the Work otherwise complies\nwith the conditions stated in this License.\n\n5. Submission of Contributions.\n\nUnless You explicitly state otherwise, any Contribution intentionally submitted\nfor inclusion in the Work by You to the Licensor shall be under the terms and\nconditions of this License, without any additional terms or conditions.\nNotwithstanding the above, nothing herein shall supersede or modify the terms of\nany separate license agreement you may have executed with Licensor regarding\nsuch Contributions.\n\n6. Trademarks.\n\nThis License does not grant permission to use the trade names, trademarks,\nservice marks, or product names of the Licensor, except as required for\nreasonable and customary use in describing the origin of the Work and\nreproducing the content of the NOTICE file.\n\n7. Disclaimer of Warranty.\n\nUnless required by applicable law or agreed to in writing, Licensor provides the\nWork (and each Contributor provides its Contributions) on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,\nincluding, without limitation, any warranties or conditions of TITLE,\nNON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are\nsolely responsible for determining the appropriateness of using or\nredistributing the Work and assume any risks associated with Your exercise of\npermissions under this License.\n\n8. Limitation of Liability.\n\nIn no event and under no legal theory, whether in tort (including negligence),\ncontract, or otherwise, unless required by applicable law (such as deliberate\nand grossly negligent acts) or agreed to in writing, shall any Contributor be\nliable to You for damages, including any direct, indirect, special, incidental,\nor consequential damages of any character arising as a result of this License or\nout of the use or inability to use the Work (including but not limited to\ndamages for loss of goodwill, work stoppage, computer failure or malfunction, or\nany and all other commercial damages or losses), even if such Contributor has\nbeen advised of the possibility of such damages.\n\n9. Accepting Warranty or Additional Liability.\n\nWhile redistributing the Work or Derivative Works thereof, You may choose to\noffer, and charge a fee for, acceptance of support, warranty, indemnity, or\nother liability obligations and/or rights consistent with this License. However,\nin accepting such obligations, You may act only on Your own behalf and on Your\nsole responsibility, not on behalf of any other Contributor, and only if You\nagree to indemnify, defend, and hold each Contributor harmless for any liability\nincurred by, or claims asserted against, such Contributor by reason of your\naccepting any such warranty or additional liability.\n\nEND OF TERMS AND CONDITIONS\n\nAPPENDIX: How to apply the Apache License to your work\n\nTo apply the Apache License to your work, attach the following boilerplate\nnotice, with the fields enclosed by brackets \"{}\" replaced with your own\nidentifying information. (Don't include the brackets!) The text should be\nenclosed in the appropriate comment syntax for the file format. We also\nrecommend that a file or class name and description of purpose be included on\nthe same \"printed page\" as the copyright notice for easier identification within\nthird-party archives.\n\n   Copyright 2018 owen\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."
  },
  {
    "path": "README.md",
    "content": "# <H1 align=\"center\">open-capacity-platform 微服务能力开发平台</H1 > \r\n\r\n<p align=\"center\">\r\n <img src=\"https://img.shields.io/circleci/project/vuejs/vue/dev.svg\" alt=\"Build Status\">\r\n  <img src=\"https://img.shields.io/badge/Spring%20Cloud-Edgware.SR3-blue.svg\" alt=\"Coverage Status\">\r\n  <img src=\"https://img.shields.io/badge/Spring%20Boot-1.5.9-blue.svg\" alt=\"Downloads\">\r\n  <img src=\"https://img.shields.io/npm/l/vue.svg\" alt=\"License\">\r\n</p>\r\n\r\n### 欢迎进群（群内领资料）\r\n\r\n`一键加群`\r\n\r\n<a target=\"_blank\" href=\"https://jq.qq.com/?_wv=1027&k=5JSjd5D\"><img border=\"0\" src=\"//pub.idqqimg.com/wpa/images/group.png\" alt=\"open-capacity-platform交流\" title=\"open-capacity-platform交流\"></a>\r\n\r\n![](https://i.imgur.com/kxpc628.png)\r\n\r\n\r\n\r\n### 简介\r\n\r\n​        简称ocp是基于layui+springcloud的企业级微服务框架(用户权限管理，配置中心管理，应用管理，....),其核心的设计目标是分离前后端，快速开发部署，学习简单，功能强大，提供快速接入核心接口能力，其目标是帮助企业搭建一套类似百度能力开放平台的框架。\r\n\r\n\r\n\r\n### 基于OCP的企业微服务体验地址\r\n\r\nhttp://47.94.252.160:8066\r\n\r\n用户名/密码：admin/admin\r\n\r\n\r\n\r\n### 组织结构\r\n\r\nopen-capacity-platform\r\n\r\n```\r\n├    open-db-core  -- 数据库逻辑封装    \r\n├    open-eureka-center    -- eureka服务注册发现套件   \r\n├       ├── open-eureka-server   --服务注册中心[1111]    \r\n├       └── open-eureka-client    --注册服务样例工程[7768]  \r\n├    open-config-center   -- 配置中心   \r\n├         ├──  apollo    -- 阿波罗配置中心  \r\n├         ├       ├── apollo-adminservice      --[8090]    \r\n├         ├       ├── apollo-assembly     \r\n├         ├       ├── apollo-biz   \r\n├         ├       ├── apollo-buildtools    \r\n├         ├       ├── apollo-client    \r\n├         ├       ├── apollo-common     \r\n├         ├       ├── apollo-configservice     --[8080] \r\n├         ├       ├── apollo-core  \r\n├         ├       └── apollo-demo  \r\n├         └      apollo-gateway  -- 阿波罗整合网关样例工程[9000]  \r\n├    open-oauth-center --oauth2套件   \r\n├       ├── open-oauth-server   --oauth认证中心[8000]  \r\n├       ├── open-oauth-client    --oauth资源服务器样例工程[8100]   \r\n├       ├── open-capacity-client-two  --oauth资源服务器样例工程[8200]    \r\n├       └── open-oauth-sso  --oauth sso样例工程[9997]  \r\n├    open-api-gateway  -- 服务网关[9200]  \r\n├    open-layui-web  --  基于jwt spring security的layui后台管理系统     \r\n├    open-xxl-job  -- 分布式调度任务\r\n├       ├── xxl-job-core  --核心库\r\n├       ├── xxl-job-admin   --job管理器    \r\n├       └── xxl-job-demo    --job执行器\r\n├     open-monitor-center  -- 监控中心\r\n├       ├── open-admin-server  -- spring boot admin server[9998]  \r\n├       ├    cachecloud-open-parent  -- 搜狐redis云平台   \r\n├       ├        ├── cachecloud-open-client    \r\n├       ├        ├── cachecloud-open-common   \r\n├       ├        └── cachecloud-open-web    \r\n├       └─  open-zipkin-center   -- zipkin链路跟踪[9412]  \r\n├               ├── open-zipkin-server-kafka   --zipkin链路跟踪服务端\r\n└               └── open-zipkin-client-kafka    --zipkin链路跟踪客户端  \r\n```\r\n\r\n\r\n\r\n#### 开发工具:\r\n\r\n- MySql: 数据库\r\n- Tomcat: 应用服务器\r\n- SVN|Git: 版本管理\r\n- Nginx: 反向代理服务器\r\n- IntelliJ IDEA/STS-3.8.0.RELEASE : 开发IDE/STS\r\n- Navicat for MySQL: 数据库客户端\r\n\r\n\r\n\r\n### 开发环境\r\n\r\nJDK8+  \r\n\r\nREADIS 3.X  \r\n\r\nMySQL 5.6 + \r\n\r\nMAVEN 3.3.9  \r\n\r\n\r\n\r\n\r\n###   技术介绍 \r\n![](https://i.imgur.com/29QKUkG.png)  \r\n###   框架设计\r\n![](https://i.imgur.com/vn03vIX.jpg)\r\n\r\n\r\n\r\n##  ocp项目演示\r\n\r\n![](http://img1.ph.126.net/WAraEeweVw2SyTUSG1dT6Q==/3887169428474612491.gif) \r\n\r\n\r\n## 阿波罗配置中心演示  \r\n![](http://img2.ph.126.net/-cKtj6Wia_q6YiZKV-IOsQ==/295548725646480248.gif)\r\n\r\n\r\n## oauth认证方式    \r\n![](https://i.imgur.com/MUCa4x6.gif)\r\n## oauth单点登录   \r\n![](https://i.imgur.com/PwcuvoC.gif)\r\n\r\n\r\n\r\n\r\n## 一. open-capacity-platform能力开放平台管理    \r\n\r\n01.用户登录\r\n\r\n\r\n\r\n<img src=\"https://i.imgur.com/Wpo9STn.png\" />\r\n\r\n02.用户管理\r\n\r\n![](https://i.imgur.com/Ud65k7j.png)\r\n\r\n03.角色管理\r\n\r\n![](https://i.imgur.com/Vl4n8Wr.png)\r\n\r\n04.菜单管理\r\n![](https://i.imgur.com/DXFAsUy.png)\r\n\r\n\r\n\r\n05.注册中心   \r\n![](https://i.imgur.com/L1RMEoq.png)\r\n\r\n ![](https://i.imgur.com/IKHAQ1c.png)\r\n\r\n06.配置中心   \r\n![](https://i.imgur.com/PrHbd6P.png)\r\n![](https://i.imgur.com/Zyy4XjQ.png)\r\n\r\n\r\n07.服务管理\r\n\r\n![](https://i.imgur.com/eDqMHBF.png)  \r\n\r\n08.应用管理  \r\n![](https://i.imgur.com/BKN06Te.png)\r\n\r\n\r\n09.定时任务\r\n\r\n![](https://i.imgur.com/boiJhNU.jpg)\r\n\r\n\r\n\r\n\r\n\r\n## 部署 \r\n1.cd /root/sop/eureka-server/bin/ &&  ./start.sh  启动注册中心服务   \r\n2.cd /root/sop/config-center/configservice/bin/ &&  ./start.sh 启动配置中心configservice服务     \r\n3.cd /root/sop/config-center/adminservice/bin/  &&  ./start.sh  启动配置中心adminservice 服务  \r\n4.cd /root/sop/config-center/portalservice/bin/ &&  ./start.sh 启动配置中心portalservice服务   \r\n5.cd /root/sop/apollo-zuul/bin/ &&  ./start.sh 启动演示apollo-zuul项目   \r\n\r\n\r\n启动后效果预览   \r\n![](https://i.imgur.com/H0CiqbD.jpg)\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "open-api-gateway/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\t<parent>\n\t\t<groupId>com.open.capacity</groupId>\n\t\t<artifactId>open-capacity-platform</artifactId>\n\t\t<version>0.0.1-SNAPSHOT</version>\n\t</parent>\n\t<artifactId>open-api-gateway</artifactId>\n\t<description>zuul oauth swagger集成</description>\n\n\t<properties>\n\t\t<docker.image.prefix>gitgeek</docker.image.prefix>\n\t</properties>\n\n\t<dependencies>\n\n\t\t<!-- 关系型和非关系型数据库配置 -->\n\t\t<dependency>\n\t\t\t<groupId>com.open.capacity</groupId>\n\t\t\t<artifactId>open-db-core</artifactId>\n\t\t\t<version>${core.version}</version>\n\t\t</dependency>\n\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework</groupId>\n\t\t\t<artifactId>spring-context-support</artifactId>\n\t\t</dependency>\n\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.social</groupId>\n\t\t\t<artifactId>spring-social-web</artifactId>\n\t\t</dependency>\n\t\t<!-- 加入spring security spring security oauth2的处理 -->\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-oauth2</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.security</groupId>\n\t\t\t<artifactId>spring-security-jwt</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.apache.commons</groupId>\n\t\t\t<artifactId>commons-lang3</artifactId>\n\t\t</dependency>\n\n\n\t\t <!-- swagger -->\n\t\t\t<dependency>\n\t\t\t\t<groupId>com.didispace</groupId>\n\t\t\t\t<artifactId>swagger-butler-core</artifactId>\n\t\t\t\t<version>1.1.0</version>\n\t\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.github.xiaoymin</groupId>\n\t\t\t<artifactId>swagger-bootstrap-ui</artifactId>\n\t\t\t<version>1.6</version>\n\t\t</dependency>\n\n\t\t<!-- https://mvnrepository.com/artifact/com.zyplayer/swagger-mg-ui -->\n\t\t<dependency>\n\t\t\t<groupId>com.zyplayer</groupId>\n\t\t\t<artifactId>swagger-mg-ui</artifactId>\n\t\t\t<version>1.0.1</version>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.squareup.okhttp3</groupId>\n\t\t\t<artifactId>okhttp</artifactId>\n\t\t</dependency>\n\t\t\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-zuul</artifactId>\n\t\t</dependency>\n\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-eureka</artifactId>\n\t\t</dependency>\n\n\n\t\t<dependency>\n\t\t\t<groupId>io.swagger</groupId>\n\t\t\t<artifactId>swagger-core</artifactId>\n\t\t\t<version>1.5.8</version>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>io.springfox</groupId>\n\t\t\t<artifactId>springfox-swagger2</artifactId>\n\t\t\t<version>2.4.0</version>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>io.springfox</groupId>\n\t\t\t<artifactId>springfox-swagger-ui</artifactId>\n\t\t\t<version>2.4.0</version>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-actuator</artifactId>\n\t\t</dependency>\n\n\n\t</dependencies>\n\n\t<!-- 形成带第三方jar包的可执行jar包，jar包目录结构如下 application.properties lib META-INF mybatis \n\t\torg -->\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t\t<version>1.3.3.RELEASE</version>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>repackage</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\n\t\t\t<plugin>\n\t\t\t\t<groupId>com.spotify</groupId>\n\t\t\t\t<artifactId>docker-maven-plugin</artifactId>\n\t\t\t\t<version>0.4.13</version>\n\t\t\t\t<configuration>\n\t\t\t\t\t<imageName>${docker.image.prefix}/${project.artifactId}</imageName>\n\t\t\t\t\t<dockerDirectory>src/main/docker</dockerDirectory>\n\t\t\t\t\t<resources>\n\t\t\t\t\t\t<resource>\n\t\t\t\t\t\t\t<targetPath>/</targetPath>\n\t\t\t\t\t\t\t<directory>${project.build.directory}</directory>\n\t\t\t\t\t\t\t<include>${project.build.finalName}.jar</include>\n\t\t\t\t\t\t</resource>\n\t\t\t\t\t</resources>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\n\t\t</plugins>\n\t\t<finalName>open-api-gateway</finalName>\n\t</build>\n\n</project>"
  },
  {
    "path": "open-api-gateway/src/main/docker/Dockerfile",
    "content": "FROM frolvlad/alpine-oraclejdk8\nVOLUME /tmp\nADD open-api-gateway.jar app.jar\nRUN sh -c 'touch /app.jar'\nENV JAVA_OPTS=\"\"\nENTRYPOINT [ \"sh\", \"-c\", \"java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar\" ]"
  },
  {
    "path": "open-api-gateway/src/main/java/com/open/capacity/GatewayApp.java",
    "content": "package com.open.capacity;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.client.discovery.EnableDiscoveryClient;\nimport org.springframework.cloud.client.loadbalancer.LoadBalanced;\nimport org.springframework.cloud.netflix.zuul.EnableZuulProxy;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.web.client.RestTemplate;\nimport org.springframework.web.cors.CorsConfiguration;\nimport org.springframework.web.cors.UrlBasedCorsConfigurationSource;\nimport org.springframework.web.filter.CorsFilter;\n\n/**\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2017年11月12日 上午22:57:51 类说明\n */\n\n@Configuration\n@EnableZuulProxy\n@EnableDiscoveryClient\n@SpringBootApplication\npublic class GatewayApp {\n\n    @Bean\n    @LoadBalanced\n    public RestTemplate restTemplate() {\n        return new RestTemplate();\n    }\n\n    @Bean\n    // 前后分离 ajax跨域调用处理\n    public CorsFilter corsFilter() {\n        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();\n        final CorsConfiguration config = new CorsConfiguration();\n        config.setAllowCredentials(true); // 允许cookies跨域\n        config.addAllowedOrigin(\"*\");// 允许向该服务器提交请求的URI，*表示全部允许。。这里尽量限制来源域，比如http://xxxx:8080\n        // ,以降低安全风险。。\n        config.addAllowedHeader(\"*\");// 允许访问的头信息,*表示全部\n        config.setMaxAge(18000L);// 预检请求的缓存时间（秒），即在这个时间段里，对于相同的跨域请求不会再预检了\n        config.addAllowedMethod(\"*\");// 允许提交请求的方法，*表示全部允许，也可以单独设置GET、PUT等\n        /*\n         * config.addAllowedMethod(\"HEAD\"); config.addAllowedMethod(\"GET\");//\n         * 允许Get的请求方法 config.addAllowedMethod(\"PUT\");\n         * config.addAllowedMethod(\"POST\"); config.addAllowedMethod(\"DELETE\");\n         * config.addAllowedMethod(\"PATCH\");\n         */\n        source.registerCorsConfiguration(\"/**\", config);\n        return new CorsFilter(source);\n    }\n\n    public static void main(String[] args) {\n        SpringApplication.run(GatewayApp.class, args);\n    }\n\n}\n"
  },
  {
    "path": "open-api-gateway/src/main/java/com/open/capacity/client/oauth2/OAuth2ClientConfig.java",
    "content": "\npackage com.open.capacity.client.oauth2;\n\nimport javax.annotation.Resource;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;\nimport org.springframework.security.config.annotation.web.builders.HttpSecurity;\nimport org.springframework.security.config.annotation.web.builders.WebSecurity;\nimport org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;\nimport org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;\nimport org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;\nimport org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler;\nimport org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler;\nimport org.springframework.security.oauth2.provider.token.TokenStore;\nimport org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;\nimport org.springframework.security.oauth2.provider.token.store.JwtTokenStore;\nimport org.springframework.security.web.AuthenticationEntryPoint;\nimport org.springframework.security.web.authentication.AuthenticationFailureHandler;\nimport org.springframework.security.web.context.SecurityContextPersistenceFilter;\nimport org.springframework.stereotype.Component;\n\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.open.capacity.client.oauth2.authorize.AuthorizeConfigManager;\nimport com.open.capacity.client.oauth2.filter.IPFilter;\n\n/**\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2017年11月12日 上午22:57:51\n */\n@Component\n@Configuration\n@EnableResourceServer\n@EnableGlobalMethodSecurity(prePostEnabled = true)\npublic class OAuth2ClientConfig extends ResourceServerConfigurerAdapter {\n\n\t@Resource\n\tprivate ObjectMapper objectMapper; // springmvc启动时自动装配json处理类\n\n\t@Autowired(required = false)\n\tprivate TokenStore redisTokenStore;\n\n\t@Autowired(required = false)\n\tprivate JwtTokenStore jwtTokenStore;\n\t@Autowired(required = false)\n\tprivate JwtAccessTokenConverter jwtAccessTokenConverter;\n\n\t@Autowired\n\tprivate AuthenticationEntryPoint authenticationEntryPoint;\n\t@Autowired\n\tprivate AuthenticationFailureHandler authenticationFailureHandler;\n\n\t@Autowired\n\tprivate AuthorizeConfigManager authorizeConfigManager;\n\n\t@Autowired\n\tprivate OAuth2WebSecurityExpressionHandler expressionHandler;\n\t@Autowired\n\tprivate OAuth2AccessDeniedHandler oAuth2AccessDeniedHandler;\n\t\n\tpublic void configure(WebSecurity web) throws Exception {\n\t\tweb.ignoring().antMatchers(\"/health\");\n\t}\n\t\n\t@Override\n\tpublic void configure(ResourceServerSecurityConfigurer resources) throws Exception {\n\n\t\tif (jwtTokenStore != null) {\n\t\t\tresources.tokenStore(jwtTokenStore);\n\t\t} else if (redisTokenStore != null) {\n\t\t\tresources.tokenStore(redisTokenStore);\n\t\t}\n\t\tresources.stateless(true);\n\n\t\tresources.authenticationEntryPoint(authenticationEntryPoint) ;\n\n\t\tresources.expressionHandler(expressionHandler);\n\t\tresources.accessDeniedHandler(oAuth2AccessDeniedHandler);\n\n\t}\n\n\t@Override\n\tpublic void configure(HttpSecurity http) throws Exception {\n\n\t\thttp.csrf().disable();\n\t\thttp.headers().frameOptions().disable();\n\n\t\tauthorizeConfigManager.config(http.authorizeRequests());\n\n\t\tIPFilter iPFilter = new IPFilter();\n\t\tiPFilter.setAuthenticationFailureHandler(authenticationFailureHandler);\n\t\tiPFilter.afterPropertiesSet();\n\n\t\thttp.addFilterAfter(iPFilter, SecurityContextPersistenceFilter.class);\n\n\t}\n\n}\n"
  },
  {
    "path": "open-api-gateway/src/main/java/com/open/capacity/client/oauth2/authorize/AuthorizeConfigManager.java",
    "content": "package com.open.capacity.client.oauth2.authorize;\n\nimport org.springframework.security.config.annotation.web.builders.HttpSecurity;\nimport org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;\n\n/**\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2018年2月1日 下午9:47:00\n * 类说明\n */\npublic interface AuthorizeConfigManager {\n\n    /**\n     * @param config\n     */\n    void config(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry config);\n}\n"
  },
  {
    "path": "open-api-gateway/src/main/java/com/open/capacity/client/oauth2/authorize/AuthorizeConfigProvider.java",
    "content": "package com.open.capacity.client.oauth2.authorize;\n\nimport org.springframework.security.config.annotation.web.builders.HttpSecurity;\nimport org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;\n\n/** \n* @author 作者 owen E-mail:624191343@qq.com\n* @version 创建时间：2018年2月1日 下午9:46:25 \n* 类说明 \n*/\npublic interface AuthorizeConfigProvider {\n\n\tboolean config(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry config);\n\n}\n"
  },
  {
    "path": "open-api-gateway/src/main/java/com/open/capacity/client/oauth2/authorize/OpenAuthorizeConfigManager.java",
    "content": "package com.open.capacity.client.oauth2.authorize;\n\nimport java.util.List;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.security.config.annotation.web.builders.HttpSecurity;\nimport org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;\nimport org.springframework.stereotype.Component;\n\n/** \n* @author 作者 owen E-mail: 624191343@qq.com\n* @version 创建时间：2018年2月1日 下午9:50:27 \n* 类说明 \n*/\n@Component\npublic class OpenAuthorizeConfigManager implements AuthorizeConfigManager {\n\n\t@Autowired\n\tprivate List<AuthorizeConfigProvider> authorizeConfigProviders;\n\n\t/* (non-Javadoc)\n\t * @see com.imooc.security.core.authorize.AuthorizeConfigManager#config(org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry)\n\t */\n\t@Override\n\tpublic void config(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry config) {\n\t\t \n\t\t//设置访问\n\t\tfor (AuthorizeConfigProvider authorizeConfigProvider : authorizeConfigProviders) {\n\t\t\tauthorizeConfigProvider.config(config) ;\n\t\t}\n\t\t\n\t\t//token正确登录\n\t\tconfig.anyRequest().authenticated() ;\n\t\t\n//\t\t放开则全部可以不需要认证访问\n//\t\tconfig\n//\t\t.anyRequest()\n//\t\t\t.access(\"@rbacService.hasPermission(request, authentication)\");\n\t\t\n\t\t\n\t}\n\n}\n"
  },
  {
    "path": "open-api-gateway/src/main/java/com/open/capacity/client/oauth2/authorize/provider/AuthAuthorizeConfigProvider.java",
    "content": "package com.open.capacity.client.oauth2.authorize.provider;\n\nimport com.open.capacity.client.oauth2.authorize.AuthorizeConfigProvider;\nimport org.springframework.core.annotation.Order;\nimport org.springframework.security.config.annotation.web.builders.HttpSecurity;\nimport org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;\nimport org.springframework.stereotype.Component;\n\n/**\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2018年1月31日 下午9:11:36\n * 类说明\n * 白名单\n */\n@Component\n@Order(Integer.MAX_VALUE - 1)\npublic class AuthAuthorizeConfigProvider implements AuthorizeConfigProvider {\n\n    @Override\n    public boolean config(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry config) {\n\n        //免token登录设置\n        config.antMatchers(\"/test163\").permitAll();\n        config.antMatchers(\"/auth/**\").permitAll();\n        config.antMatchers(\"/v2/api-docs\", \"/configuration/ui\", \"/swagger-resources\", \"/configuration/security\", \"/swagger-ui.html\", \"/webjars/**\").permitAll();\n        config.antMatchers(\"/**/v2/api-docs\", \"/**/configuration/ui\", \"/**/swagger-resources\", \"/**/configuration/security\", \"/**/swagger-ui.html\", \"/**/webjars/**\").permitAll();\n\n\n        return true;\n    }\n\n}\n"
  },
  {
    "path": "open-api-gateway/src/main/java/com/open/capacity/client/oauth2/config/DocumentationConfig.java",
    "content": "package com.open.capacity.client.oauth2.config;\n\nimport org.springframework.context.annotation.Primary;\nimport org.springframework.stereotype.Component;\nimport springfox.documentation.swagger.web.SwaggerResource;\nimport springfox.documentation.swagger.web.SwaggerResourcesProvider;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n@Primary\n@Component\npublic class DocumentationConfig implements SwaggerResourcesProvider {\n    @Override\n    public List<SwaggerResource> get() {\n        List resources = new ArrayList<>();\n//      zuul routes  /client/ zuul 集中管理api文档\n//      分布式文档集成  \n        resources.add(swaggerResource(\"认证中心\", \"/auth/v2/api-docs\", \"2.0\"));\n        resources.add(swaggerResource(\"erukea客户端\", \"/client/v2/api-docs\", \"2.0\"));\n        return resources;\n    }\n\n    private SwaggerResource swaggerResource(String name, String location, String version) {\n        SwaggerResource swaggerResource = new SwaggerResource();\n        swaggerResource.setName(name);\n        swaggerResource.setLocation(location);\n        swaggerResource.setSwaggerVersion(version);\n        return swaggerResource;\n    }\n}"
  },
  {
    "path": "open-api-gateway/src/main/java/com/open/capacity/client/oauth2/config/SecurityHandlerConfig.java",
    "content": "package com.open.capacity.client.oauth2.config;\n\nimport java.io.IOException;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport javax.annotation.Resource;\nimport javax.servlet.ServletException;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.security.access.AccessDeniedException;\nimport org.springframework.security.authentication.BadCredentialsException;\nimport org.springframework.security.core.AuthenticationException;\nimport org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler;\nimport org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler;\nimport org.springframework.security.web.AuthenticationEntryPoint;\nimport org.springframework.security.web.authentication.AuthenticationFailureHandler;\nimport org.springframework.stereotype.Component;\n\nimport com.fasterxml.jackson.databind.ObjectMapper;\n\n  \n/** \n* @author 作者 owen E-mail: 624191343@qq.com\n* @version 创建时间：2018年4月5日 下午7:52:21 \n* 类说明 \n*/\n@Component\n@Configuration\npublic class SecurityHandlerConfig {\n\n\t@Resource \n\tprivate ObjectMapper objectMapper ; //springmvc启动时自动装配json处理类\n\t\n\t\n\t/**\n\t * 登陆失败\n\t * \n\t * @return\n\t */\n\t@Bean\n\tpublic AuthenticationFailureHandler loginFailureHandler() {\n\t\treturn new AuthenticationFailureHandler() {\n\n\t\t\t@Override\n\t\t\tpublic void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,\n\t\t\t\t\tAuthenticationException exception) throws IOException, ServletException {\n\t\t\t\tString msg = null;\n\t\t\t\tif (exception instanceof BadCredentialsException) {\n\t\t\t\t\tmsg = \"密码错误\";\n\t\t\t\t} else {\n\t\t\t\t\tmsg = exception.getMessage();\n\t\t\t\t}\n\n\t\t\t\tMap<String, String> rsp = new HashMap<>();\n\n\t\t\t\tresponse.setStatus(HttpStatus.UNAUTHORIZED.value());\n\n\t\t\t\trsp.put(\"resp_code\", HttpStatus.UNAUTHORIZED.value() + \"\");\n\t\t\t\trsp.put(\"rsp_msg\", msg);\n\n\t\t\t\tresponse.setContentType(\"application/json;charset=UTF-8\");\n\t\t\t\tresponse.getWriter().write(objectMapper.writeValueAsString(rsp));\n\t\t\t\tresponse.getWriter().flush();\n\t\t\t\tresponse.getWriter().close();\n\n\t\t\t}\n\t\t};\n\n\t}\n \n\t \n    \n\t/**\n\t * 未登录，返回401\n\t * \n\t * @return\n\t */\n\t@Bean\n\tpublic AuthenticationEntryPoint authenticationEntryPoint() {\n\t\treturn new AuthenticationEntryPoint() {\n\n\t\t\t@Override\n\t\t\tpublic void commence(HttpServletRequest request, HttpServletResponse response,\n\t\t\t\t\tAuthenticationException authException) throws IOException, ServletException {\n\t\t\t\t\n\t\t\t\tMap<String ,String > rsp =new HashMap<>();  \n\t\t\t\t\n\t\t\t\tresponse.setStatus(HttpStatus.UNAUTHORIZED.value() );\n\t\t\t\t\n\t\t\t\trsp.put(\"resp_code\", HttpStatus.UNAUTHORIZED.value() + \"\") ;\n                rsp.put(\"resp_msg\", authException.getMessage()) ;\n                \n                response.setContentType(\"application/json;charset=UTF-8\");\n    \t\t\tresponse.getWriter().write(objectMapper.writeValueAsString(rsp));\n    \t\t\tresponse.getWriter().flush();\n    \t\t\tresponse.getWriter().close();\n                \n\t\t\t}\n\t\t};\n\t}\n\t\n\t \n    @Bean\n    public OAuth2WebSecurityExpressionHandler oAuth2WebSecurityExpressionHandler(ApplicationContext applicationContext) {\n        OAuth2WebSecurityExpressionHandler expressionHandler = new OAuth2WebSecurityExpressionHandler();\n        expressionHandler.setApplicationContext(applicationContext);\n        return expressionHandler;\n    }\n    \n    @Bean\n    public OAuth2AccessDeniedHandler oAuth2AccessDeniedHandler(){\n    \treturn new OAuth2AccessDeniedHandler(){\n    \t    \n    \t    @Override\n    \t    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException authException) throws IOException, ServletException {\n\n    \t    \tMap<String ,String > rsp =new HashMap<>();  \n    \t    \tresponse.setContentType(\"application/json;charset=UTF-8\");\n\n    \t        response.setStatus(HttpStatus.UNAUTHORIZED.value() );\n\t\t\t\t\n\t\t\t\trsp.put(\"resp_code\", HttpStatus.UNAUTHORIZED.value() + \"\") ;\n                rsp.put(\"resp_msg\", authException.getMessage()) ;\n                \n                response.setContentType(\"application/json;charset=UTF-8\");\n    \t\t\tresponse.getWriter().write(objectMapper.writeValueAsString(rsp));\n    \t\t\tresponse.getWriter().flush();\n    \t\t\tresponse.getWriter().close();\n    \t        \n    \t    }\n    \t};\n    }\n}\n"
  },
  {
    "path": "open-api-gateway/src/main/java/com/open/capacity/client/oauth2/config/SwaggerConfig.java",
    "content": "package com.open.capacity.client.oauth2.config;\n\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.stereotype.Component;\nimport springfox.documentation.builders.PathSelectors;\nimport springfox.documentation.builders.RequestHandlerSelectors;\nimport springfox.documentation.spi.DocumentationType;\nimport springfox.documentation.spring.web.plugins.Docket;\nimport springfox.documentation.swagger2.annotations.EnableSwagger2;\n\n\n@Component\n@Configuration\n@EnableSwagger2\npublic class SwaggerConfig {\n    @Bean\n    public Docket api() {\n        return new Docket(DocumentationType.SWAGGER_2)\n                .select()\n                .apis(RequestHandlerSelectors.basePackage(\"com.open.capacity\"))\n                .apis(RequestHandlerSelectors.any())\n                .paths(PathSelectors.any())\n                .build();\n    }\n\n\n}  "
  },
  {
    "path": "open-api-gateway/src/main/java/com/open/capacity/client/oauth2/dao/ServiceDao.java",
    "content": "package com.open.capacity.client.oauth2.dao;\n\nimport org.apache.ibatis.annotations.Mapper;\nimport org.apache.ibatis.annotations.Select;\n\nimport java.util.List;\nimport java.util.Map;\n\n@Mapper\npublic interface ServiceDao {\n\n\n    @Select(\"select p.* from sys_services p inner join sys_client_permission rp on p.id = rp.permissionId where rp.clientId = #{clientId} order by p.sort\")\n    List<Map> listByClientId(Long clientId);\n\n    @Select(\"select * from oauth_client_details t where t.client_id = #{clientId}\")\n    Map getClient(String clientId);\n\n\n}\n"
  },
  {
    "path": "open-api-gateway/src/main/java/com/open/capacity/client/oauth2/filter/AccessFilter.java",
    "content": "package com.open.capacity.client.oauth2.filter;\n\nimport com.netflix.zuul.ZuulFilter;\nimport com.netflix.zuul.context.RequestContext;\nimport org.springframework.security.core.Authentication;\nimport org.springframework.security.core.context.SecurityContextHolder;\nimport org.springframework.security.oauth2.provider.OAuth2Authentication;\nimport org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails;\nimport org.springframework.stereotype.Component;\n\nimport javax.servlet.http.HttpServletRequest;\n\n/**\n * Created by owen on 2017/9/10.\n */\n@Component\npublic class AccessFilter extends ZuulFilter {\n\n\n    @Override\n    public String filterType() {\n        return \"pre\";\n    }\n\n    @Override\n    public int filterOrder() {\n        return 0;\n    }\n\n    @Override\n    public boolean shouldFilter() {\n        return true;\n    }\n\n    @Override\n    public Object run() {\n        RequestContext ctx = RequestContext.getCurrentContext();\n        HttpServletRequest request = ctx.getRequest();\n\n        try {\n\n            //解决zuul token传递问题\n            Authentication user = SecurityContextHolder.getContext()\n                    .getAuthentication();\n\n\n            if (user != null) {\n\n                if (user instanceof OAuth2Authentication) {\n\n                    Authentication athentication = (Authentication) user;\n\n                    OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails) athentication.getDetails();\n                    ctx.addZuulRequestHeader(\"Authorization\", \"bearer \" + details.getTokenValue());\n                }\n\n            }\n\n\n        } catch (Exception e) {\n\n        }\n        return null;\n    }\n\n\n}\n"
  },
  {
    "path": "open-api-gateway/src/main/java/com/open/capacity/client/oauth2/filter/IPFilter.java",
    "content": "package com.open.capacity.client.oauth2.filter;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.InitializingBean;\nimport org.springframework.security.oauth2.common.OAuth2AccessToken;\nimport org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails;\nimport org.springframework.security.web.authentication.AuthenticationFailureHandler;\nimport org.springframework.util.AntPathMatcher;\nimport org.springframework.web.filter.OncePerRequestFilter;\n\nimport javax.servlet.FilterChain;\nimport javax.servlet.ServletException;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport java.io.IOException;\nimport java.util.Enumeration;\nimport java.util.HashSet;\nimport java.util.Set;\n\n/**\n * IP过滤器\n *\n * @author owen 624191343@qq.com\n * <p>\n * 2017年10月14日\n */\npublic class IPFilter extends OncePerRequestFilter implements InitializingBean {\n\n    Logger logger = LoggerFactory.getLogger(getClass());\n\n    private AuthenticationFailureHandler authenticationFailureHandler;\n\n    public AuthenticationFailureHandler getAuthenticationFailureHandler() {\n        return authenticationFailureHandler;\n    }\n\n    public void setAuthenticationFailureHandler(AuthenticationFailureHandler authenticationFailureHandler) {\n        this.authenticationFailureHandler = authenticationFailureHandler;\n    }\n\n    // 所有需要拦截的url\n    private Set<String> urls = new HashSet<>();\n    // url匹配器\n    private AntPathMatcher pathMatcher = new AntPathMatcher();\n\n    @Override\n    public void afterPropertiesSet() throws ServletException {\n        super.afterPropertiesSet(); // 初始化其他bean参数\n\n    }\n\n    @Override\n    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)\n            throws ServletException, IOException {\n\n        String accessToken = null;\n\n        accessToken = extractToken(request);\n\n\n//\t\tif(!pathMatcher.match(\"/auth/**\", request.getRequestURI())){\n//\t\t\t\n//\t\t\tif (accessToken == null) {\n//\t\t\t\tauthenticationFailureHandler.onAuthenticationFailure(request, response,\n//\t\t\t\t\t\tnew AuthenticationException(\"token 不存在\") {\n//\n//\t\t\t\t\t\t\tprivate static final long serialVersionUID = 6154557943607468780L;\n//\n//\t\t\t\t\t\t});\n//\t\t\t\treturn;\n//\t\t\t}\n//\t\t}\n\n//\t\tString ipAddr = this.getIpAddr(req);\n//\t\tlogger.info(\"请求IP地址为：[{}]\", ipAddr);\n//\t\t// 配置本地IP白名单，生产环境可放入数据库或者redis中\n//\t\tList<String> ips = new ArrayList<String>();\n//\t\tips.add(\"127.0.0.1\");\n//\n//\t\tif (!ips.contains(ipAddr)) {\n//\t\t\tlogger.info(\"IP地址校验不通过！！！\");\n//\t\t\tctx.setResponseStatusCode(401);\n//\t\t\tctx.setSendZuulResponse(false);\n//\t\t\tctx.setResponseBody(\"IpAddr is forbidden!\");\n//\t\t}\n//\t\tlogger.info(\"IP校验通过。\");\n\n\n        filterChain.doFilter(request, response);\n    }\n\n    protected String extractToken(HttpServletRequest request) {\n        // first check the header...\n        String token = extractHeaderToken(request);\n\n        // bearer type allows a request parameter as well\n        if (token == null) {\n            logger.debug(\"Token not found in headers. Trying request parameters.\");\n            token = request.getParameter(OAuth2AccessToken.ACCESS_TOKEN);\n            if (token == null) {\n                logger.debug(\"Token not found in request parameters.  Not an OAuth2 request.\");\n            } else {\n                request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_TYPE, OAuth2AccessToken.BEARER_TYPE);\n            }\n        }\n\n        return token;\n    }\n\n    /**\n     * Extract the OAuth bearer token from a header.\n     *\n     * @param request The request.\n     * @return The token, or null if no OAuth authorization header was supplied.\n     */\n    protected String extractHeaderToken(HttpServletRequest request) {\n        Enumeration<String> headers = request.getHeaders(\"Authorization\");\n        while (headers.hasMoreElements()) { // typically there is only one (most\n            // servers enforce that)\n            String value = headers.nextElement();\n            if ((value.toLowerCase().startsWith(OAuth2AccessToken.BEARER_TYPE.toLowerCase()))) {\n                String authHeaderValue = value.substring(OAuth2AccessToken.BEARER_TYPE.length()).trim();\n                // Add this here for the auth details later. Would be better to\n                // change the signature of this method.\n                request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_TYPE,\n                        value.substring(0, OAuth2AccessToken.BEARER_TYPE.length()).trim());\n                int commaIndex = authHeaderValue.indexOf(',');\n                if (commaIndex > 0) {\n                    authHeaderValue = authHeaderValue.substring(0, commaIndex);\n                }\n                return authHeaderValue;\n            }\n        }\n\n        return null;\n    }\n\n}\n"
  },
  {
    "path": "open-api-gateway/src/main/java/com/open/capacity/client/oauth2/service/RbacService.java",
    "content": "package com.open.capacity.client.oauth2.service;\n\nimport org.springframework.security.core.Authentication;\n\nimport javax.servlet.http.HttpServletRequest;\n\n/**\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2017年12月4日 下午5:32:29\n * 类说明\n */\npublic interface RbacService {\n\n    boolean hasPermission(HttpServletRequest request, Authentication authentication);\n\n}\n"
  },
  {
    "path": "open-api-gateway/src/main/java/com/open/capacity/client/oauth2/service/impl/RbacServiceImpl.java",
    "content": "package com.open.capacity.client.oauth2.service.impl;\n\nimport com.open.capacity.client.oauth2.dao.ServiceDao;\nimport com.open.capacity.client.oauth2.service.RbacService;\nimport org.springframework.security.core.Authentication;\nimport org.springframework.security.core.context.SecurityContextHolder;\nimport org.springframework.security.oauth2.provider.OAuth2Authentication;\nimport org.springframework.stereotype.Service;\nimport org.springframework.util.AntPathMatcher;\n\nimport javax.annotation.Resource;\nimport javax.servlet.http.HttpServletRequest;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * API 级别权限认证\n *\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2017年12月4日 下午5:32:29\n * 类说明\n */\n\n@Service(\"rbacService\")\npublic class RbacServiceImpl implements RbacService {\n\n    @Resource\n    private ServiceDao serviceDao;\n\n    private AntPathMatcher antPathMatcher = new AntPathMatcher();\n\n    /**\n     * @param request        HttpServletRequest\n     * @param authentication 认证信息\n     * @return 是否有权限\n     */\n    @Override\n    public boolean hasPermission(HttpServletRequest request, Authentication authentication) {\n\n        Authentication user = SecurityContextHolder.getContext()\n                .getAuthentication();\n\n\n        if (user != null) {\n\n            if (user instanceof OAuth2Authentication) {\n\n                OAuth2Authentication athentication = (OAuth2Authentication) user;\n\n                String clientId = athentication.getOAuth2Request().getClientId();\n\n                Map map = serviceDao.getClient(clientId);\n\n                if (map == null) {\n                    return false;\n                } else {\n                    List<Map> list = serviceDao.listByClientId(Long.valueOf(String.valueOf(map.get(\"id\"))));\n                    ;\n\n                    for (Iterator<Map> it = list.iterator(); it.hasNext(); ) {\n                        Map temp = it.next();\n\n                        if (antPathMatcher.match(request.getRequestURI(), String.valueOf(temp.get(\"href\")))) {\n                            return true;\n                        }\n                    }\n                    return false;\n                }\n\n\n            }\n\n        }\n\n\n        //TODO 目前都是true\n        boolean hasPermission = true;\n\n\n        return hasPermission;\n    }\n\n}\n"
  },
  {
    "path": "open-api-gateway/src/main/java/com/open/capacity/client/oauth2/token/TokenStoreConfig.java",
    "content": "package com.open.capacity.client.oauth2.token;\n\nimport javax.annotation.Resource;\nimport javax.sql.DataSource;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.data.redis.core.RedisTemplate;\nimport org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;\nimport org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;\nimport org.springframework.security.oauth2.provider.token.store.JwtTokenStore;\n\nimport com.open.capacity.client.oauth2.token.store.RedisTemplateTokenStore;\n\n/** \n* @author 作者 owen E-mail: 624191343@qq.com\n* @version 创建时间：2017年12月18日 下午3:15:22 \n* 类说明 \n* redis存储token\n*/\n@Configuration\npublic class TokenStoreConfig {\n \n\t@Resource\n\tprivate DataSource dataSource ;\n\t\n\t@Autowired(required=false)\n\tprivate RedisTemplate<String, Object>  redisTemplate ;\n\t\n\t\n\t@Bean\n\t@ConditionalOnProperty(prefix=\"security.oauth2.token.store\",name=\"type\" ,havingValue=\"jdbc\" ,matchIfMissing=true)\n\tpublic JdbcTokenStore jdbcTokenStore(){\n \n//\t\toauth_access_token oauth_refresh_token 创建两张表\n//\t\treturn new JdbcTokenStore( dataSource ) ;\n\t\treturn new JdbcTokenStore( dataSource ) ;\n\n\t}\n\t\n\t@Bean\n\t@ConditionalOnProperty(prefix=\"security.oauth2.token.store\",name=\"type\" ,havingValue=\"redis\" ,matchIfMissing=true)\n\tpublic RedisTemplateTokenStore redisTokenStore(){\n//\t\treturn new RedisTokenStore( redisTemplate.getConnectionFactory() ) ; //单台redis服务器\n\t\t\n\n\t\tRedisTemplateTokenStore redisTemplateStore = new RedisTemplateTokenStore()  ;\n\t\tredisTemplateStore.setRedisTemplate(redisTemplate);\n\t\treturn redisTemplateStore ;\n\t\t \n\n\t}\n\t\n\t//使用jwt替换原有的uuid生成token方式\n\t@Configuration\n\t@ConditionalOnProperty(prefix=\"security.oauth2.token.store\",name=\"type\" ,havingValue=\"jwt\" ,matchIfMissing=true)\n\tpublic static class JWTTokenConfig {\n\t\t@Bean\n\t\tpublic JwtTokenStore jwtTokenStore(){\n\t\t\treturn new JwtTokenStore( jwtAccessTokenConverter() ) ;\n\t\t}\n\t\t\n\t\t@Bean\n\t\tpublic JwtAccessTokenConverter jwtAccessTokenConverter(){\n\t\t\tJwtAccessTokenConverter accessTokenConverter = new JwtAccessTokenConverter();\n\t\t\taccessTokenConverter.setSigningKey(\"neusoft\");\n\t\t\treturn accessTokenConverter ;\n\t\t}\n\t}\n\t\n}\n"
  },
  {
    "path": "open-api-gateway/src/main/java/com/open/capacity/client/oauth2/token/store/RedisTemplateTokenStore.java",
    "content": "package com.open.capacity.client.oauth2.token.store;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.concurrent.TimeUnit;\n\nimport org.springframework.data.redis.core.RedisTemplate;\nimport org.springframework.security.oauth2.common.ExpiringOAuth2RefreshToken;\nimport org.springframework.security.oauth2.common.OAuth2AccessToken;\nimport org.springframework.security.oauth2.common.OAuth2RefreshToken;\nimport org.springframework.security.oauth2.provider.OAuth2Authentication;\nimport org.springframework.security.oauth2.provider.token.AuthenticationKeyGenerator;\nimport org.springframework.security.oauth2.provider.token.DefaultAuthenticationKeyGenerator;\nimport org.springframework.security.oauth2.provider.token.TokenStore;\n\n/** \n* @author owen 624191343@qq.com\n * @version 创建时间：2017年11月12日 上午22:57:51\n* 类说明 \n* redis集群存储token\n*/\n \npublic class RedisTemplateTokenStore implements TokenStore {\n\t\n\tprivate static final String ACCESS = \"access:\";\n\tprivate static final String AUTH_TO_ACCESS = \"auth_to_access:\";\n\tprivate static final String AUTH = \"auth:\";\n\tprivate static final String REFRESH_AUTH = \"refresh_auth:\";\n\tprivate static final String ACCESS_TO_REFRESH = \"access_to_refresh:\";\n\tprivate static final String REFRESH = \"refresh:\";\n\tprivate static final String REFRESH_TO_ACCESS = \"refresh_to_access:\";\n\tprivate static final String CLIENT_ID_TO_ACCESS = \"client_id_to_access:\";\n\tprivate static final String UNAME_TO_ACCESS = \"uname_to_access:\";\n\t\n\n\tprivate RedisTemplate<String,Object> redisTemplate ;\n\t\n\tpublic RedisTemplate<String,Object> getRedisTemplate() {\n\t\treturn redisTemplate;\n\t}\n\n\tpublic void setRedisTemplate(RedisTemplate<String,Object> redisTemplate) {\n\t\tthis.redisTemplate = redisTemplate;\n\t}\n\n\n\tprivate AuthenticationKeyGenerator authenticationKeyGenerator = new DefaultAuthenticationKeyGenerator();\n\n\n\n\t \n\tpublic void setAuthenticationKeyGenerator(AuthenticationKeyGenerator authenticationKeyGenerator) {\n\t\tthis.authenticationKeyGenerator = authenticationKeyGenerator;\n\t}\n\n\t \n\tpublic OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) {\n\t\tString key = authenticationKeyGenerator.extractKey(authentication);\n\t\tOAuth2AccessToken accessToken = (OAuth2AccessToken) redisTemplate.opsForValue().get(AUTH_TO_ACCESS+key);\n\t\tif (accessToken != null\n\t\t\t\t&& !key.equals(authenticationKeyGenerator.extractKey(readAuthentication(accessToken.getValue())))) {\n\t\t\t// Keep the stores consistent (maybe the same user is represented by this authentication but the details\n\t\t\t// have changed)\n\t\t\tstoreAccessToken(accessToken, authentication);\n\t\t}\n\t\treturn accessToken;\n\t}\n\tpublic OAuth2Authentication readAuthentication(OAuth2AccessToken token) {\n\t\treturn readAuthentication(token.getValue());\n\t}\n\tpublic OAuth2Authentication readAuthentication(String token) {\n\t\treturn (OAuth2Authentication) this.redisTemplate.opsForValue().get(AUTH +  token);\n\t}\n\tpublic OAuth2Authentication readAuthenticationForRefreshToken(OAuth2RefreshToken token) {\n\t\treturn readAuthenticationForRefreshToken(token.getValue());\n\t}\n\tpublic OAuth2Authentication readAuthenticationForRefreshToken(String token) {\n\t\treturn (OAuth2Authentication) this.redisTemplate.opsForValue().get( REFRESH_AUTH+token);\n\t}\n\tpublic void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) {\n\t\t\n\t\tOAuth2AccessToken existingAccessToken = this.getAccessToken(authentication);\n\t\t\n\t\tthis.redisTemplate.opsForValue().set(ACCESS+ token.getValue(), token);\n\t\tthis.redisTemplate.opsForValue().set(AUTH +token.getValue(), authentication);\n\t\tthis.redisTemplate.opsForValue().set(AUTH_TO_ACCESS+authenticationKeyGenerator.extractKey(authentication), token);\n\t\t\n\t\tif (!authentication.isClientOnly()) {\n\t\t\tif (existingAccessToken != null) {\n\t\t\t\tif (!existingAccessToken.isExpired()) {\n\t\t\t\t\tint seconds = token.getExpiresIn();\n\t\t\t\t\tredisTemplate.expire(UNAME_TO_ACCESS+authentication.getOAuth2Request().getClientId(), seconds, TimeUnit.SECONDS) ;\n\t\t\t\t}else{\n\t\t\t\t\tredisTemplate.opsForList().rightPush(UNAME_TO_ACCESS+getApprovalKey(authentication), token) ;\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\tredisTemplate.opsForList().rightPush(UNAME_TO_ACCESS+getApprovalKey(authentication), token) ;\n\t\t\t}\n\t\t\t\t\t\n\t\t\t\n\t\t\t\n\t\t}\n\t\t\n\t\t\n\t\tif (existingAccessToken != null) {\n\t\t\tif (!existingAccessToken.isExpired()) {\n\t\t\t\tint seconds = token.getExpiresIn();\n\t\t\t\tredisTemplate.expire(CLIENT_ID_TO_ACCESS+authentication.getOAuth2Request().getClientId(), seconds, TimeUnit.SECONDS) ;\n\t\t\t\t\n\t\t\t}else{\n\t\t\t\tredisTemplate.opsForList().rightPush(CLIENT_ID_TO_ACCESS+authentication.getOAuth2Request().getClientId(), token) ;\n\t\t\t}\n\t\t}else{\n\t\t\tredisTemplate.opsForList().rightPush(CLIENT_ID_TO_ACCESS+authentication.getOAuth2Request().getClientId(), token) ;\n\t\t}\n\t\t\n\t\t\n\t\t\n\t\tif (token.getExpiration() != null) {\n\t\t\t  \n\t\t\tint seconds = token.getExpiresIn();\n\t\t\tredisTemplate.expire(ACCESS+ token.getValue(), seconds, TimeUnit.SECONDS) ;\n\t\t\tredisTemplate.expire(AUTH+ token.getValue(), seconds, TimeUnit.SECONDS) ;\n\t\t\t\n\t\t\tredisTemplate.expire(AUTH_TO_ACCESS+ authenticationKeyGenerator.extractKey(authentication), seconds, TimeUnit.SECONDS) ;\n\t\t\tredisTemplate.expire(CLIENT_ID_TO_ACCESS+authentication.getOAuth2Request().getClientId(), seconds, TimeUnit.SECONDS) ;\n\t\t\tredisTemplate.expire(UNAME_TO_ACCESS+ getApprovalKey(authentication), seconds, TimeUnit.SECONDS) ;\n\t\t}\n\t\t\n\t\tOAuth2RefreshToken refreshToken = token.getRefreshToken();\n\t\t\n\t\tif (token.getRefreshToken() != null && token.getRefreshToken().getValue() != null) {\n\t\t\tthis.redisTemplate.opsForValue().set( REFRESH_TO_ACCESS+   token.getRefreshToken().getValue(), token.getValue());\n\t\t\tthis.redisTemplate.opsForValue().set(ACCESS_TO_REFRESH+token.getValue(), token.getRefreshToken().getValue());\n\t\t\t\n\t\t\t\n\t\t\tif (refreshToken instanceof ExpiringOAuth2RefreshToken) {\n\t\t\t\tExpiringOAuth2RefreshToken expiringRefreshToken = (ExpiringOAuth2RefreshToken) refreshToken;\n\t\t\t\tDate expiration = expiringRefreshToken.getExpiration();\n\t\t\t\tif (expiration != null) {\n\t\t\t\t\tint seconds = Long.valueOf((expiration.getTime() - System.currentTimeMillis()) / 1000L)\n\t\t\t\t\t\t\t.intValue();\n\t\t\t\t\t\n\t\t\t\t\tredisTemplate.expire( REFRESH_TO_ACCESS+   token.getRefreshToken().getValue() , seconds, TimeUnit.SECONDS) ;\n\t\t\t\t\tredisTemplate.expire( ACCESS_TO_REFRESH+token.getValue(), seconds, TimeUnit.SECONDS) ;\n\t \n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t\n\t\t}\n\t}\n\n\tprivate String getApprovalKey(OAuth2Authentication authentication) {\n\t\tString userName = authentication.getUserAuthentication() == null ? \"\" : authentication.getUserAuthentication()\n\t\t\t\t.getName();\n\t\treturn getApprovalKey(authentication.getOAuth2Request().getClientId(), userName);\n\t}\n\n\tprivate String getApprovalKey(String clientId, String userName) {\n\t\treturn clientId + (userName==null ? \"\" : \":\" + userName);\n\t}\n\n\t \n\n\tpublic void removeAccessToken(OAuth2AccessToken accessToken) {\n\t\tremoveAccessToken(accessToken.getValue());\n\t}\n\n\tpublic OAuth2AccessToken readAccessToken(String tokenValue) {\n\t\treturn (OAuth2AccessToken) this.redisTemplate.opsForValue().get(ACCESS+tokenValue);\n\t}\n\n\tpublic void removeAccessToken(String tokenValue) {\n\t\tOAuth2AccessToken removed = (OAuth2AccessToken) redisTemplate.opsForValue().get(ACCESS+tokenValue);\n\t\t// Don't remove the refresh token - it's up to the caller to do that\n\t\tOAuth2Authentication authentication = (OAuth2Authentication) this.redisTemplate.opsForValue().get(AUTH+tokenValue);\n\t\t\n\t\t\n\t\tthis.redisTemplate.delete(AUTH+tokenValue);\n\t\tredisTemplate.delete(ACCESS+tokenValue);\n\t\tthis.redisTemplate.delete(ACCESS_TO_REFRESH +tokenValue);\n\t\t\n\t\t\n\t\tif (authentication != null) {\n\t\t\tthis.redisTemplate.delete(AUTH_TO_ACCESS+authenticationKeyGenerator.extractKey(authentication));\n\t\t\n\t\t\tString clientId = authentication.getOAuth2Request().getClientId();\n\t\t\t\n//\t\t\tredisTemplate.opsForList().rightPush(\"UNAME_TO_ACCESS:\"+getApprovalKey(authentication), token) ;\n\t\t\tredisTemplate.opsForList().leftPop(UNAME_TO_ACCESS+getApprovalKey(clientId, authentication.getName()));\n\t\t\t\n\t\t\tredisTemplate.opsForList().leftPop(CLIENT_ID_TO_ACCESS+clientId);\n\t\t\t\n\t\t\tthis.redisTemplate.delete(AUTH_TO_ACCESS+authenticationKeyGenerator.extractKey(authentication));\n\t\t}\n\t}\n\n\tpublic void storeRefreshToken(OAuth2RefreshToken refreshToken, OAuth2Authentication authentication) {\n\t\tthis.redisTemplate.opsForValue().set(REFRESH+refreshToken.getValue(), refreshToken);\n\t\tthis.redisTemplate.opsForValue().set( REFRESH_AUTH + refreshToken.getValue(), authentication);\n\t}\n\n\tpublic OAuth2RefreshToken readRefreshToken(String tokenValue) {\n\t\treturn (OAuth2RefreshToken) this.redisTemplate.opsForValue().get(REFRESH+tokenValue);\n\t}\n\n\tpublic void removeRefreshToken(OAuth2RefreshToken refreshToken) {\n\t\tremoveRefreshToken(refreshToken.getValue());\n\t}\n\n\tpublic void removeRefreshToken(String tokenValue) {\n\t\tthis.redisTemplate.delete( REFRESH + tokenValue);\n\t\tthis.redisTemplate.delete( REFRESH_AUTH + tokenValue);\n\t\tthis.redisTemplate.delete(REFRESH_TO_ACCESS +tokenValue);\n\t}\n\n\tpublic void removeAccessTokenUsingRefreshToken(OAuth2RefreshToken refreshToken) {\n\t\tremoveAccessTokenUsingRefreshToken(refreshToken.getValue());\n\t}\n\n\tprivate void removeAccessTokenUsingRefreshToken(String refreshToken) {\n\t\t\n\t\tString token = (String) this.redisTemplate.opsForValue().get( REFRESH_TO_ACCESS  +refreshToken) ;\n\t\t\n\t\tif (token != null) {\n\t\t\tredisTemplate.delete(REFRESH_TO_ACCESS+ refreshToken);\n\t\t}\n\t}\n\n\tpublic Collection<OAuth2AccessToken> findTokensByClientIdAndUserName(String clientId, String userName) {\n\t\tList<Object> result =    redisTemplate.opsForList().range(UNAME_TO_ACCESS+ getApprovalKey(clientId, userName), 0, -1);\n\t\t\n\t\tif (result == null || result.size() == 0) {\n\t\t\treturn Collections.<OAuth2AccessToken> emptySet();\n\t\t}\n\t\tList<OAuth2AccessToken> accessTokens = new ArrayList<OAuth2AccessToken>(result.size());\n\t\t\n\t\tfor(Iterator<Object> it = result.iterator();it.hasNext();){\n\t\t\tOAuth2AccessToken accessToken = (OAuth2AccessToken) it.next();\n\t\t\taccessTokens.add(accessToken);\n\t\t}\n\t\t\n\t\treturn Collections.<OAuth2AccessToken> unmodifiableCollection(accessTokens); \n\t}\n\n\tpublic Collection<OAuth2AccessToken> findTokensByClientId(String clientId) {\n\t\tList<Object> result =    redisTemplate.opsForList().range((CLIENT_ID_TO_ACCESS+clientId), 0, -1);\n\t\t\n\t\tif (result == null || result.size() == 0) {\n\t\t\treturn Collections.<OAuth2AccessToken> emptySet();\n\t\t}\n\t\tList<OAuth2AccessToken> accessTokens = new ArrayList<OAuth2AccessToken>(result.size());\n\t\t\n\t\tfor(Iterator<Object> it = result.iterator();it.hasNext();){\n\t\t\tOAuth2AccessToken accessToken = (OAuth2AccessToken) it.next();\n\t\t\taccessTokens.add(accessToken);\n\t\t}\n\t\t\n\t\treturn Collections.<OAuth2AccessToken> unmodifiableCollection(accessTokens); \n\t}\n\n \n \n\n}\n\n"
  },
  {
    "path": "open-api-gateway/src/main/java/com/open/capacity/controller/TestController.java",
    "content": "package com.open.capacity.controller;\n\nimport javax.annotation.Resource;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.data.redis.core.RedisTemplate;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2017年11月12日 上午22:57:51\n */\n@RestController\npublic class TestController {\n\tprivate static final Logger logger = LoggerFactory.getLogger(TestController.class);\n\t\n\t@Resource\n\tprivate RedisTemplate< String, Object> redisTemplate ;\n\t\n\t \n\n\t@GetMapping(\"/test111\")\n\tpublic String hello() {\n\t\treturn \"hello\";\n\t}\n\n\t \n}\n"
  },
  {
    "path": "open-api-gateway/src/main/java/com/open/capacity/controller/UserController.java",
    "content": "package com.open.capacity.controller;\n\nimport java.security.Principal;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport javax.annotation.Resource;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.data.redis.core.RedisTemplate;\nimport org.springframework.security.core.authority.AuthorityUtils;\nimport org.springframework.security.oauth2.provider.OAuth2Authentication;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport com.open.capacity.client.oauth2.token.store.RedisTemplateTokenStore;\n\n/**\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2017年11月12日 上午22:57:51\n */\n@RestController\npublic class UserController {\n\tprivate static final Logger logger = LoggerFactory.getLogger(UserController.class);\n\t\n\t@Resource\n\tprivate RedisTemplate< String, Object> redisTemplate ;\n\t\n\t \n\n\t@GetMapping(\"/hello\")\n\tpublic String hello() {\n\t\tredisTemplate.opsForValue().set(\"hello\", \"owen\");\n\t\treturn \"hello\";\n\t}\n\n\t@RequestMapping(value = { \"/users\" }, produces = \"application/json\") // 获取用户信息。/auth/user\n\tpublic Map<String, Object> user(OAuth2Authentication user) {\n\t\tMap<String, Object> userInfo = new HashMap<>();\n\t\tuserInfo.put(\"user\", user.getUserAuthentication().getPrincipal());\n\t\tlogger.debug(\"认证详细信息:\" + user.getUserAuthentication().getPrincipal().toString());\n\t\tuserInfo.put(\"authorities\", AuthorityUtils.authorityListToSet(user.getUserAuthentication().getAuthorities()));\n\t\treturn userInfo;\n\t}\n\t\n\t@RequestMapping(value = { \"/user\" }, produces = \"application/json\") // 获取用户信息。/auth/user\n    public Principal user(Principal user) {\n        return user;\n    }\n\t\n\t\n\t@GetMapping(\"/del/{accessToken}/{refreshToken}\")\n\tpublic String hello2(@PathVariable String accessToken,@PathVariable String refreshToken) {\n\t\tRedisTemplateTokenStore redisTemplateStore = new RedisTemplateTokenStore();\n\t\tredisTemplateStore.setRedisTemplate(redisTemplate);\n\t\tredisTemplateStore.removeAccessToken(accessToken);\n\t\tredisTemplateStore.removeRefreshToken(refreshToken);\n\t\treturn \"delR\";\n\t}\n}\n"
  },
  {
    "path": "open-api-gateway/src/main/resources/application.yml",
    "content": "server:\n  port: 9200\nspring:\n  application:\n    name: open-auth-gateway\n  datasource:\n      type: com.alibaba.druid.pool.DruidDataSource\n#      driver-class-name:  oracle.jdbc.OracleDriver\n#      url: jdbc:oracle:thin:@127.0.0.1:1521:orcl\n#      username: crm_owner_user\n#      password: bss_crm_test\n#      filters: stat,wall\n################## mysql start ############################\n      driver-class-name:  com.mysql.jdbc.Driver\n      #     192.168.3.150   130.75.131.211  134.224.249.39  47.94.252.160\n      url: jdbc:mysql://192.168.3.150:3306/boot_security?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false\n      username: root\n      password: root\n      filters: stat,wall\n################### mysq end l##########################\n  redis:\n################### redis 单机版 start ########################## \n    host: 127.0.0.1\n    port: 6379    \n    timeout: 3000\n    database: 1\n################### redis 单机版 end ##########################   \n#    cluster:\n#      nodes: 192.168.3.157:7000,192.168.3.158:7000,192.168.3.159:7000,192.168.3.157:7001,192.168.3.158:7001,192.168.3.159:7001\n##        #130.75.131.237:7000,130.75.131.238:7000,130.75.131.239:7000,130.75.131.237:7001,130.75.131.238:7001,130.75.131.239:7001\n#        #192.168.3.157:7000,192.168.3.158:7000,192.168.3.159:7000,192.168.3.157:7001,192.168.3.158:7001,192.168.3.159:7001\n#    timeout: 1000 # 连接超时时间（毫秒）\n#    pool:\n#      max-active: 10  # 连接池最大连接数（使用负值表示没有限制）\n#      max-idle: 8     # 连接池中的最大空闲连接\n#      min-idle: 2     # 连接池中的最小空闲连接\n#      max-wait: 100   # 连接池最大阻塞等待时间（使用负值表示没有限制）       \n    \ndocker:\n  ipAddress: 47.94.252.160\n\nmybatis:\n  config-location: classpath:mybatis.cfg.xml\n  mapper-locations: classpath*:com/open/**/dao/*.xml  \n\n\nsecurity:\n  oauth2:\n    token:\n      store:\n        type: redis\n\n\n#设置最大超时时间\nribbon:  \n  httpclient:\n    enabled: false\n  okhttp:\n    enabled: true  \n  ReadTimeout: 90000  \n  ConnectTimeout: 90000 \n\n\n#设置最大容错超时时间\nhystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 90000\n\n\nhystrix:\n  command:\n    default:\n      execution:\n        timeout:\n          enabled: false    #设置熔断的超时时间开启 false关闭熔断功能，true开启熔断功能\n        isolation:\n          thread:\n            timeoutInMilliseconds: 90000\n\nswagger:\n  butler:\n    api-docs-path:  v2/api-docs\n    auto-generate-from-zuul-routes: true\n \nzuul:\n  retryable: false    #关闭重试\n  sensitive-headers: #/oauth/token需要请求头处理\n  add-host-header: true\n  routes:\n    baidu:  \n      path: /test163/**\n      url: http://www.163.com \n    auth:  \n      path: /auth/**\n      service-id: open-auth-server \n      strip-prefix: true   \n      custom-sensitive-headers: true  #http://blog.didispace.com/spring-cloud-zuul-cookie-redirect/ zuul授权码跳转问题\n    client:  \n      path: /client/**\n      service-id: open-eureka-client\n      strip-prefix: true  \n    auth_client: \n      path: /auth-client/**\n      service-id: open-auth-client\n      strip-prefix: true   \neureka:\n  client:\n    serviceUrl:\n      defaultZone: http://127.0.0.1:1111/eureka/\n      #http://192.168.3.170:1111/eureka,http://192.168.3.171:1111/eureka,http://192.168.3.173:1111/eureka\n      #http://130.75.131.243:1111/eureka/,http://130.75.131.244:1111/eureka/,http://130.75.131.245:1111/eureka/   \n  instance:\n    prefer-ip-address: true\n    instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}\n#    instance-id: ${spring.application.name}:${docker.ipAddress}:${spring.application.instance_id:${server.port}}\n    lease-renewal-interval-in-seconds: 5\n    #注册实例文档\n    status-page-url: http://${spring.cloud.client.ipAddress}:${server.port}/swagger-ui.html # ${server.port}为该服务的端口号\n#    status-page-url: http://${docker.ipAddress}:${server.port}/swagger-ui.html # ${server.port}为该服务的端口号\n\n  \n\n\n  \n "
  },
  {
    "path": "open-api-gateway/src/main/resources/bootstrap.yml",
    "content": "management:\n  security:\n    enabled: false\n#spring:\n#  cloud:\n#    config:\n#      discovery:\n#        enabled: true\n#        service-id: unieap-config-server\n#      name: unieap-config-server\n#      fail-fast: true  \n#      profile: dev   # eureka-config-client-dev.yml\n\n "
  },
  {
    "path": "open-commons/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" 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  <parent>\n    <groupId>com.open.capacity</groupId>\n    <artifactId>open-capacity-platform</artifactId>\n    <version>0.0.1-SNAPSHOT</version>\n  </parent>\n  <artifactId>open-commons</artifactId>\n  \n  \n  <!-- spring security 核心包 -->\n  <dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.security</groupId>\n\t\t\t<artifactId>spring-security-core</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.apache.commons</groupId>\n\t\t\t<artifactId>commons-lang3</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t    <groupId>org.apache.commons</groupId>\n\t\t    <artifactId>commons-collections4</artifactId>\n\t\t    <version>4.0</version>\n\t\t</dependency>\n  </dependencies>\n  \n  \n</project>"
  },
  {
    "path": "open-commons/src/main/java/com/open/capacity/security/dto/LoginUser.java",
    "content": "package com.open.capacity.security.dto;\n\nimport com.fasterxml.jackson.annotation.JsonIgnore;\nimport com.open.capacity.security.model.Permission;\nimport com.open.capacity.security.model.SysUser;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.security.core.GrantedAuthority;\nimport org.springframework.security.core.authority.SimpleGrantedAuthority;\nimport org.springframework.security.core.userdetails.UserDetails;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Iterator;\nimport java.util.List;\n\npublic class LoginUser extends SysUser implements UserDetails {\n\n    private static final long serialVersionUID = -1379274258881257107L;\n\n    private List<Permission> permissions;\n\n    private String jwtToken;\n\n\n    private String token;\n    /**\n     * 登陆时间戳（毫秒）\n     */\n    private Long loginTime;\n    /**\n     * 过期时间戳\n     */\n    private Long expireTime;\n\n    public List<Permission> getPermissions() {\n        return permissions;\n    }\n\n    public void setPermissions(List<Permission> permissions) {\n        this.permissions = permissions;\n    }\n\n    public String getToken() {\n        return token;\n    }\n\n    public void setToken(String token) {\n        this.token = token;\n    }\n\n    @Override\n    @JsonIgnore\n    public Collection<? extends GrantedAuthority> getAuthorities() {\n\n        List<GrantedAuthority> auths = new ArrayList<GrantedAuthority>();\n\n        for (Iterator<Permission> it = permissions.iterator(); it.hasNext(); ) {\n            Permission p = it.next();\n\n\n            if (!StringUtils.isEmpty(p.getPermission())) {\n                auths.add(new SimpleGrantedAuthority(p.getPermission()));\n            }\n        }\n\n        return auths;\n\n//\t\treturn permissions.parallelStream().filter(p -> !StringUtils.isEmpty(p.getPermission()))\n//\t\t\t\t.map(p -> new SimpleGrantedAuthority(p.getPermission())).collect(Collectors.toSet());\n    }\n\n    public void setAuthorities(Collection<? extends GrantedAuthority> authorities) {\n        // do nothing\n    }\n\n    // 账户是否未过期\n    @JsonIgnore\n    @Override\n    public boolean isAccountNonExpired() {\n        return true;\n    }\n\n    // 账户是否未锁定\n    @JsonIgnore\n    @Override\n    public boolean isAccountNonLocked() {\n        return getStatus() != Status.LOCKED;\n    }\n\n    // 密码是否未过期\n    @JsonIgnore\n    @Override\n    public boolean isCredentialsNonExpired() {\n        return true;\n    }\n\n    // 账户是否激活\n    @JsonIgnore\n    @Override\n    public boolean isEnabled() {\n        return true;\n    }\n\n    public Long getLoginTime() {\n        return loginTime;\n    }\n\n    public void setLoginTime(Long loginTime) {\n        this.loginTime = loginTime;\n    }\n\n    public Long getExpireTime() {\n        return expireTime;\n    }\n\n    public void setExpireTime(Long expireTime) {\n        this.expireTime = expireTime;\n    }\n\n    @JsonIgnore\n    public String getJwtToken() {\n        return jwtToken;\n    }\n\n    public void setJwtToken(String jwtToken) {\n        this.jwtToken = jwtToken;\n    }\n}\n"
  },
  {
    "path": "open-commons/src/main/java/com/open/capacity/security/dto/ResponseInfo.java",
    "content": "package com.open.capacity.security.dto;\n\nimport java.io.Serializable;\n\npublic class ResponseInfo implements Serializable {\n\n    private static final long serialVersionUID = -4417715614021482064L;\n\n    private String code;\n    private String message;\n\n    public ResponseInfo(String code, String message) {\n        super();\n        this.code = code;\n        this.message = message;\n    }\n\n    public String getCode() {\n        return code;\n    }\n\n    public void setCode(String code) {\n        this.code = code;\n    }\n\n    public String getMessage() {\n        return message;\n    }\n\n    public void setMessage(String message) {\n        this.message = message;\n    }\n\n}\n"
  },
  {
    "path": "open-commons/src/main/java/com/open/capacity/security/dto/RoleDto.java",
    "content": "package com.open.capacity.security.dto;\n\nimport com.open.capacity.security.model.Role;\n\nimport java.util.List;\n\npublic class RoleDto extends Role {\n\n    private static final long serialVersionUID = 4218495592167610193L;\n\n    private List<Long> permissionIds;\n\n    public List<Long> getPermissionIds() {\n        return permissionIds;\n    }\n\n    public void setPermissionIds(List<Long> permissionIds) {\n        this.permissionIds = permissionIds;\n    }\n}\n"
  },
  {
    "path": "open-commons/src/main/java/com/open/capacity/security/dto/UserDto.java",
    "content": "package com.open.capacity.security.dto;\n\nimport com.open.capacity.security.model.SysUser;\n\nimport java.util.List;\n\npublic class UserDto extends SysUser {\n\n    private static final long serialVersionUID = -184009306207076712L;\n\n    private List<Long> roleIds;\n\n    public List<Long> getRoleIds() {\n        return roleIds;\n    }\n\n    public void setRoleIds(List<Long> roleIds) {\n        this.roleIds = roleIds;\n    }\n\n}\n"
  },
  {
    "path": "open-commons/src/main/java/com/open/capacity/security/model/BaseEntity.java",
    "content": "package com.open.capacity.security.model;\n\nimport java.io.Serializable;\nimport java.util.Date;\n\npublic abstract class BaseEntity<ID extends Serializable> implements Serializable {\n\n    private static final long serialVersionUID = 2054813493011812469L;\n\n    private ID id;\n    private Date createTime = new Date();\n    private Date updateTime = new Date();\n\n    public ID getId() {\n        return id;\n    }\n\n    public void setId(ID id) {\n        this.id = id;\n    }\n\n    public Date getCreateTime() {\n        return createTime;\n    }\n\n    public void setCreateTime(Date createTime) {\n        this.createTime = createTime;\n    }\n\n    public Date getUpdateTime() {\n        return updateTime;\n    }\n\n    public void setUpdateTime(Date updateTime) {\n        this.updateTime = updateTime;\n    }\n}\n"
  },
  {
    "path": "open-commons/src/main/java/com/open/capacity/security/model/Permission.java",
    "content": "package com.open.capacity.security.model;\n\nimport java.util.List;\n\npublic class Permission extends BaseEntity<Long> {\n\n    private static final long serialVersionUID = 6180869216498363919L;\n    private Long parentId;\n    private String name;\n    private String css;\n    private String href;\n    private Integer type;\n    private String permission;\n    private Integer sort;\n\n    private List<Permission> child;\n\n    public Long getParentId() {\n        return parentId;\n    }\n\n    public void setParentId(Long parentId) {\n        this.parentId = parentId;\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 String getCss() {\n        return css;\n    }\n\n    public void setCss(String css) {\n        this.css = css;\n    }\n\n    public String getHref() {\n        return href;\n    }\n\n    public void setHref(String href) {\n        this.href = href;\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 getPermission() {\n        return permission;\n    }\n\n    public void setPermission(String permission) {\n        this.permission = permission;\n    }\n\n    public Integer getSort() {\n        return sort;\n    }\n\n    public void setSort(Integer sort) {\n        this.sort = sort;\n    }\n\n    public List<Permission> getChild() {\n        return child;\n    }\n\n    public void setChild(List<Permission> child) {\n        this.child = child;\n    }\n}\n"
  },
  {
    "path": "open-commons/src/main/java/com/open/capacity/security/model/Role.java",
    "content": "package com.open.capacity.security.model;\n\npublic class Role extends BaseEntity<Long> {\n\n    private static final long serialVersionUID = -3802292814767103648L;\n\n    private String name;\n\n    private String description;\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public String getDescription() {\n        return description;\n    }\n\n    public void setDescription(String description) {\n        this.description = description;\n    }\n}\n"
  },
  {
    "path": "open-commons/src/main/java/com/open/capacity/security/model/SysLogs.java",
    "content": "package com.open.capacity.security.model;\n\npublic class SysLogs extends BaseEntity<Long> {\n\n    private static final long serialVersionUID = -7809315432127036583L;\n    private SysUser user;\n    private String module;\n    private Boolean flag;\n    private String remark;\n\n    public SysUser getUser() {\n        return user;\n    }\n\n    public void setUser(SysUser user) {\n        this.user = user;\n    }\n\n    public String getModule() {\n        return module;\n    }\n\n    public void setModule(String module) {\n        this.module = module;\n    }\n\n    public Boolean getFlag() {\n        return flag;\n    }\n\n    public void setFlag(Boolean flag) {\n        this.flag = flag;\n    }\n\n    public String getRemark() {\n        return remark;\n    }\n\n    public void setRemark(String remark) {\n        this.remark = remark;\n    }\n\n}\n"
  },
  {
    "path": "open-commons/src/main/java/com/open/capacity/security/model/SysUser.java",
    "content": "package com.open.capacity.security.model;\n\nimport java.util.Date;\n\nimport com.fasterxml.jackson.annotation.JsonFormat;\n\npublic class SysUser extends BaseEntity<Long> {\n\n\tprivate static final long serialVersionUID = -6525908145032868837L;\n\n\tprivate String username;\n\tprivate String password;\n\tprivate String nickname;\n\tprivate String headImgUrl;\n\tprivate String phone;\n\tprivate String telephone;\n\tprivate String email;\n\t@JsonFormat(pattern = \"yyyy-MM-dd\")\n\tprivate Date birthday;\n\tprivate Integer sex;\n\tprivate Integer status;\n\tprivate String intro;\n\n\tpublic String getUsername() {\n\t\treturn username;\n\t}\n\n\tpublic void setUsername(String username) {\n\t\tthis.username = username;\n\t}\n\n\tpublic String getPassword() {\n\t\treturn password;\n\t}\n\n\tpublic void setPassword(String password) {\n\t\tthis.password = password;\n\t}\n\n\tpublic String getNickname() {\n\t\treturn nickname;\n\t}\n\n\tpublic void setNickname(String nickname) {\n\t\tthis.nickname = nickname;\n\t}\n\n\tpublic String getHeadImgUrl() {\n\t\treturn headImgUrl;\n\t}\n\n\tpublic void setHeadImgUrl(String headImgUrl) {\n\t\tthis.headImgUrl = headImgUrl;\n\t}\n\n\tpublic String getPhone() {\n\t\treturn phone;\n\t}\n\n\tpublic void setPhone(String phone) {\n\t\tthis.phone = phone;\n\t}\n\n\tpublic String getTelephone() {\n\t\treturn telephone;\n\t}\n\n\tpublic void setTelephone(String telephone) {\n\t\tthis.telephone = telephone;\n\t}\n\n\tpublic String getEmail() {\n\t\treturn email;\n\t}\n\n\tpublic void setEmail(String email) {\n\t\tthis.email = email;\n\t}\n\n\tpublic Date getBirthday() {\n\t\treturn birthday;\n\t}\n\n\tpublic void setBirthday(Date birthday) {\n\t\tthis.birthday = birthday;\n\t}\n\n\tpublic Integer getSex() {\n\t\treturn sex;\n\t}\n\n\tpublic void setSex(Integer sex) {\n\t\tthis.sex = sex;\n\t}\n\n\tpublic Integer getStatus() {\n\t\treturn status;\n\t}\n\n\tpublic void setStatus(Integer status) {\n\t\tthis.status = status;\n\t}\n\n\tpublic String getIntro() {\n\t\treturn intro;\n\t}\n\n\tpublic void setIntro(String intro) {\n\t\tthis.intro = intro;\n\t}\n\n\tpublic interface Status {\n\t\tint DISABLED = 0;\n\t\tint VALID = 1;\n\t\tint LOCKED = 2;\n\t}\n\n}\n"
  },
  {
    "path": "open-commons/src/main/java/com/open/capacity/security/model/TokenModel.java",
    "content": "package com.open.capacity.security.model;\n\nimport java.util.Date;\n\npublic class TokenModel extends BaseEntity<String> {\n\n    private static final long serialVersionUID = 4566334160572911795L;\n\n    /**\n     * 过期时间\n     */\n    private Date expireTime;\n    /**\n     * LoginUser的json串\n     */\n    private String val;\n\n    public Date getExpireTime() {\n        return expireTime;\n    }\n\n    public void setExpireTime(Date expireTime) {\n        this.expireTime = expireTime;\n    }\n\n    public String getVal() {\n        return val;\n    }\n\n    public void setVal(String val) {\n        this.val = val;\n    }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/.gitattributes",
    "content": "text=auto"
  },
  {
    "path": "open-config-center/apollo/.gitignore",
    "content": "*.class\n.DS_Store\napplication.pid\n\n# Mobile Tools for Java (J2ME)\n.mtj.tmp/\n\n# Package Files #\n*.jar\n*.war\n*.ear\n\n# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml\nhs_err_pid*\n\n# Eclipse\n.classpath\n.project\ntarget\n.settings\nbin/\ntarget/\n\n# Idea\n.idea\n*.iml\n\n# git\n*.orig\n"
  },
  {
    "path": "open-config-center/apollo/.travis.yml",
    "content": "language: java\njdk:\n  - oraclejdk8\nnotification:\n  email:\n    recipients:\n      - song_s@ctrip.com,zhanglea@ctrip.com\n    on_success: always\n    on_failure: always\n\nbefore_script:\n  - echo \"MAVEN_OPTS='-Xms1024m -Xmx3072m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=384m'\" > ~/.mavenrc\n  \nbefore_install:\n  - pip install --user codecov\n\nafter_success:\n  - mvn clean test jacoco:report coveralls:report\n  - codecov\n\nbranches:\n  only:\n    - master\n    \nenv:\n  global:\n   - secure: \"DYJkJ7ArGJuIyTJsmjvUAJRyUKXEaGFWYZFAGZq6vxbrMN3tThz7drfNhhvP2YE7hdS7YX7hZBWVQEnNR+pBN+ykQFx7TpLr311eEk2/Yy3G5qegeHMsgqYXfAp3FFpYlE6Kr3Dcf4kFSWtRi735kSo5oHicoaxbyWENgmKT+uQjYERKhDXEoenMaDpcf8WO8KARzxI1cXf69ECnYP2rzNOfkNW4IGjTcJnplXPZ9BNBRn3WfyPwEHlemETAMwJxJXolNM9qn1bDBTB/35yJrneQY/pYp9Q8PbQID2lNJu7PFKYaI9mvsKHUgxjbzsC29zlMY94pDr6sQtr7IA0dSuk+qO2tEqAStTwRI5JOcozLAslTMNnUn6HLvy0/Kkq1TL+JrIohoRD58F34SzjcnuB4w0/GCWGU4BMSbzPwHsgQZM4lkHDWv+w1OSwP3dgCFI/vYYr9xNV0zqTgyZ9ITkMZPL0wOh0DZ7Bxxm80wyHfJuRwywemMtzitgjPR4BKENbpcoGN4lcKWciksAuiyX+dedOPfGoOWfnIKh1g7yeVB84LMggCSad/9cqnYf2Sm8xSyVzNmyhSOy2Ocy40RDas2uHIK3/QPy56Le/t1LD2On/x1TZBIoSavedNYA5N54s/ZCDZOcepUMvlwtjgnx/SMjU85ZLKCcliPGdTWws=\"\n   - \"MAVEN_OPTS=-Xms1024m -Xmx3072m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=384m\"\n\naddons:\n  coverity_scan:\n    project:\n      name: \"ctripcorp/apollo\"\n      description: \"Build submitted via Travis CI\"\n    notification_email: song_s@ctrip.com,zhanglea@ctrip.com\n    build_command_prepend: \"mvn clean\"\n    build_command: \"mvn -DskipTests=true compile\"\n    branch_pattern: master\n\ncache:\n  directories:\n  - $HOME/.m2\n"
  },
  {
    "path": "open-config-center/apollo/LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"{}\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright {yyyy} {name of copyright owner}\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"
  },
  {
    "path": "open-config-center/apollo/apollo-adminservice/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\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">\n\t<parent>\n\t\t<groupId>com.ctrip.framework.apollo</groupId>\n\t\t<artifactId>apollo</artifactId>\n\t\t<version>0.10.0-SNAPSHOT</version>\n\t</parent>\n\t<modelVersion>4.0.0</modelVersion>\n\t<artifactId>apollo-adminservice</artifactId>\n\t<name>Apollo AdminService</name>\n\t<properties>\n\t\t<github.path>${project.artifactId}</github.path>\n\t</properties>\n\t<dependencies>\n\t\t<!-- apollo -->\n\t\t<dependency>\n\t\t\t<groupId>com.ctrip.framework.apollo</groupId>\n\t\t\t<artifactId>apollo-biz</artifactId>\n\t\t</dependency>\n\t\t<!-- end of apollo -->\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-eureka-server</artifactId>\n\t\t\t<scope>test</scope>\n\t\t\t<exclusions>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<artifactId>\n                        spring-cloud-starter-archaius\n                    </artifactId>\n\t\t\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t\t</exclusion>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<artifactId>spring-cloud-starter-ribbon</artifactId>\n\t\t\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t\t</exclusion>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<artifactId>ribbon-eureka</artifactId>\n\t\t\t\t\t<groupId>com.netflix.ribbon</groupId>\n\t\t\t\t</exclusion>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<artifactId>aws-java-sdk-core</artifactId>\n\t\t\t\t\t<groupId>com.amazonaws</groupId>\n\t\t\t\t</exclusion>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<artifactId>aws-java-sdk-ec2</artifactId>\n\t\t\t\t\t<groupId>com.amazonaws</groupId>\n\t\t\t\t</exclusion>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<artifactId>aws-java-sdk-autoscaling</artifactId>\n\t\t\t\t\t<groupId>com.amazonaws</groupId>\n\t\t\t\t</exclusion>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<artifactId>aws-java-sdk-sts</artifactId>\n\t\t\t\t\t<groupId>com.amazonaws</groupId>\n\t\t\t\t</exclusion>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<artifactId>aws-java-sdk-route53</artifactId>\n\t\t\t\t\t<groupId>com.amazonaws</groupId>\n\t\t\t\t</exclusion>\n\t\t\t</exclusions>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>com.h2database</groupId>\n\t\t\t<artifactId>h2</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t <dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-jdbc</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>mysql</groupId>\n\t\t\t<artifactId>mysql-connector-java</artifactId>\n\t\t</dependency>\n\t</dependencies>\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>repackage</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t</plugins>\n\t\t<finalName>apollo-adminservice</finalName>\n\t</build>\n</project>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-adminservice/src/assembly/assembly-descriptor.xml",
    "content": "<assembly\n\txmlns=\"http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3\"\n\txmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd\">\n\t<id>apollo-assembly</id>\n\t<formats>\n\t\t<format>zip</format>\n\t</formats>\n\t<includeBaseDirectory>false</includeBaseDirectory>\n\t<fileSets>\n\t\t<!--scripts -->\n\t\t<fileSet>\n\t\t\t<directory>src/main/scripts</directory>\n\t\t\t<outputDirectory>scripts</outputDirectory>\n\t\t\t<includes>\n\t\t\t\t<include>*.sh</include>\n\t\t\t</includes>\n\t\t\t<fileMode>0755</fileMode>\n\t\t\t<lineEnding>unix</lineEnding>\n\t\t</fileSet>\n\t\t<fileSet>\n\t\t\t<directory>src/main/config</directory>\n\t\t\t<outputDirectory>config</outputDirectory>\n\t\t\t<excludes>\n\t\t\t\t<exclude>apollo-adminservice.conf</exclude>\n\t\t\t</excludes>\n\t\t\t<lineEnding>unix</lineEnding>\n\t\t</fileSet>\n\t\t<fileSet>\n\t\t\t<directory>src/main/config</directory>\n\t\t\t<outputDirectory>/</outputDirectory>\n\t\t\t<includes>\n\t\t\t\t<include>apollo-adminservice.conf</include>\n\t\t\t</includes>\n\t\t\t<lineEnding>unix</lineEnding>\n\t\t</fileSet>\n\t\t<!--artifact -->\n\t\t<fileSet>\n\t\t\t<directory>target</directory>\n\t\t\t<outputDirectory>/</outputDirectory>\n\t\t\t<includes>\n\t\t\t\t<include>${project.artifactId}-*.jar</include>\n\t\t\t</includes>\n\t\t\t<fileMode>0755</fileMode>\n\t\t</fileSet>\n\t</fileSets>\n</assembly>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-adminservice/src/main/config/apollo-adminservice.conf",
    "content": "MODE=service\nPID_FOLDER=.\nLOG_FOLDER=/opt/logs/100003172/"
  },
  {
    "path": "open-config-center/apollo/apollo-adminservice/src/main/config/app.properties",
    "content": "appId=100003172\njdkVersion=1.8"
  },
  {
    "path": "open-config-center/apollo/apollo-adminservice/src/main/docker/Dockerfile",
    "content": "# Dockerfile for apollo-adminservice\n# Build with:\n# docker build -t apollo-adminservice .\n# Run with:\n# docker run -p 8090:8090 -d -v /tmp/logs:/opt/logs --name apollo-adminservice apollo-adminservice\n\nFROM openjdk:8-jre-alpine\nMAINTAINER ameizi <sxyx2008@163.com>\n\nENV VERSION 0.9.0\n\nRUN echo \"http://mirrors.aliyun.com/alpine/v3.6/main\" > /etc/apk/repositories \\\n    && echo \"http://mirrors.aliyun.com/alpine/v3.6/community\" >> /etc/apk/repositories \\\n    && apk update upgrade \\\n    && apk add --no-cache procps unzip curl bash tzdata \\\n    && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \\\n    && echo \"Asia/Shanghai\" > /etc/timezone\n\nADD apollo-adminservice-${VERSION}-github.zip /apollo-adminservice/apollo-adminservice-${VERSION}-github.zip\n\nRUN unzip /apollo-adminservice/apollo-adminservice-${VERSION}-github.zip -d /apollo-adminservice \\\n    && rm -rf /apollo-adminservice/apollo-adminservice-${VERSION}-github.zip \\\n    && sed -i '$d' /apollo-adminservice/scripts/startup.sh \\\n    && echo \"tail -f /dev/null\" >> /apollo-adminservice/scripts/startup.sh\n\nEXPOSE 8090\n\nCMD [\"/apollo-adminservice/scripts/startup.sh\"]\n"
  },
  {
    "path": "open-config-center/apollo/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/AdminServiceApplication.java",
    "content": "package com.ctrip.framework.apollo.adminservice;\n\nimport com.ctrip.framework.apollo.biz.ApolloBizConfig;\nimport com.ctrip.framework.apollo.common.ApolloCommonConfig;\n\nimport org.springframework.boot.actuate.system.ApplicationPidFileWriter;\nimport org.springframework.boot.actuate.system.EmbeddedServerPortFileWriter;\nimport org.springframework.boot.autoconfigure.EnableAutoConfiguration;\nimport org.springframework.boot.builder.SpringApplicationBuilder;\nimport org.springframework.cloud.netflix.eureka.EnableEurekaClient;\nimport org.springframework.context.ConfigurableApplicationContext;\nimport org.springframework.context.annotation.ComponentScan;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.context.annotation.EnableAspectJAutoProxy;\nimport org.springframework.context.annotation.PropertySource;\nimport org.springframework.transaction.annotation.EnableTransactionManagement;\n@EnableAspectJAutoProxy\n@EnableEurekaClient\n@Configuration\n@PropertySource(value = {\"classpath:adminservice.properties\"})\n@EnableAutoConfiguration\n@EnableTransactionManagement\n@ComponentScan(basePackageClasses = {ApolloCommonConfig.class,\n    ApolloBizConfig.class,\n    AdminServiceApplication.class})\npublic class AdminServiceApplication {\n  public static void main(String[] args) {\n    ConfigurableApplicationContext context =\n        new SpringApplicationBuilder(AdminServiceApplication.class).run(args);\n    context.addApplicationListener(new ApplicationPidFileWriter());\n    context.addApplicationListener(new EmbeddedServerPortFileWriter());\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/AdminServiceHealthIndicator.java",
    "content": "package com.ctrip.framework.apollo.adminservice;\n\nimport com.ctrip.framework.apollo.biz.service.AppService;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.actuate.health.Health;\nimport org.springframework.boot.actuate.health.HealthIndicator;\nimport org.springframework.data.domain.PageRequest;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class AdminServiceHealthIndicator implements HealthIndicator {\n\n  @Autowired\n  private AppService appService;\n\n  @Override\n  public Health health() {\n    int errorCode = check();\n    if (errorCode != 0) {\n      return Health.down().withDetail(\"Error Code\", errorCode).build();\n    }\n    return Health.up().build();\n  }\n\n  private int check() {\n    PageRequest pageable = new PageRequest(0, 1);\n    appService.findAll(pageable);\n    return 0;\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/aop/NamespaceAcquireLockAspect.java",
    "content": "package com.ctrip.framework.apollo.adminservice.aop;\n\n\nimport com.ctrip.framework.apollo.biz.config.BizConfig;\nimport com.ctrip.framework.apollo.biz.entity.Item;\nimport com.ctrip.framework.apollo.biz.entity.Namespace;\nimport com.ctrip.framework.apollo.biz.entity.NamespaceLock;\nimport com.ctrip.framework.apollo.biz.service.ItemService;\nimport com.ctrip.framework.apollo.biz.service.NamespaceLockService;\nimport com.ctrip.framework.apollo.biz.service.NamespaceService;\nimport com.ctrip.framework.apollo.common.dto.ItemChangeSets;\nimport com.ctrip.framework.apollo.common.dto.ItemDTO;\nimport com.ctrip.framework.apollo.common.exception.BadRequestException;\nimport com.ctrip.framework.apollo.common.exception.ServiceException;\n\nimport org.aspectj.lang.annotation.Aspect;\nimport org.aspectj.lang.annotation.Before;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.dao.DataIntegrityViolationException;\nimport org.springframework.stereotype.Component;\n\n\n/**\n * 一个namespace在一次发布中只能允许一个人修改配置\n * 通过数据库lock表来实现\n */\n@Aspect\n@Component\npublic class NamespaceAcquireLockAspect {\n  private static final Logger logger = LoggerFactory.getLogger(NamespaceAcquireLockAspect.class);\n\n\n  @Autowired\n  private NamespaceLockService namespaceLockService;\n  @Autowired\n  private NamespaceService namespaceService;\n  @Autowired\n  private ItemService itemService;\n  @Autowired\n  private BizConfig bizConfig;\n\n\n  //create item\n  @Before(\"@annotation(PreAcquireNamespaceLock) && args(appId, clusterName, namespaceName, item, ..)\")\n  public void requireLockAdvice(String appId, String clusterName, String namespaceName,\n                                ItemDTO item) {\n    acquireLock(appId, clusterName, namespaceName, item.getDataChangeLastModifiedBy());\n  }\n\n  //update item\n  @Before(\"@annotation(PreAcquireNamespaceLock) && args(appId, clusterName, namespaceName, itemId, item, ..)\")\n  public void requireLockAdvice(String appId, String clusterName, String namespaceName, long itemId,\n                                ItemDTO item) {\n    acquireLock(appId, clusterName, namespaceName, item.getDataChangeLastModifiedBy());\n  }\n\n  //update by change set\n  @Before(\"@annotation(PreAcquireNamespaceLock) && args(appId, clusterName, namespaceName, changeSet, ..)\")\n  public void requireLockAdvice(String appId, String clusterName, String namespaceName,\n                                ItemChangeSets changeSet) {\n    acquireLock(appId, clusterName, namespaceName, changeSet.getDataChangeLastModifiedBy());\n  }\n\n  //delete item\n  @Before(\"@annotation(PreAcquireNamespaceLock) && args(itemId, operator, ..)\")\n  public void requireLockAdvice(long itemId, String operator) {\n    Item item = itemService.findOne(itemId);\n    if (item == null){\n      throw new BadRequestException(\"item not exist.\");\n    }\n    acquireLock(item.getNamespaceId(), operator);\n  }\n\n  void acquireLock(String appId, String clusterName, String namespaceName,\n                           String currentUser) {\n    if (bizConfig.isNamespaceLockSwitchOff()) {\n      return;\n    }\n\n    Namespace namespace = namespaceService.findOne(appId, clusterName, namespaceName);\n\n    acquireLock(namespace, currentUser);\n  }\n\n  void acquireLock(long namespaceId, String currentUser) {\n    if (bizConfig.isNamespaceLockSwitchOff()) {\n      return;\n    }\n\n    Namespace namespace = namespaceService.findOne(namespaceId);\n\n    acquireLock(namespace, currentUser);\n\n  }\n\n  private void acquireLock(Namespace namespace, String currentUser) {\n    if (namespace == null) {\n      throw new BadRequestException(\"namespace not exist.\");\n    }\n\n    long namespaceId = namespace.getId();\n\n    NamespaceLock namespaceLock = namespaceLockService.findLock(namespaceId);\n    if (namespaceLock == null) {\n      try {\n        tryLock(namespaceId, currentUser);\n        //lock success\n      } catch (DataIntegrityViolationException e) {\n        //lock fail\n        namespaceLock = namespaceLockService.findLock(namespaceId);\n        checkLock(namespace, namespaceLock, currentUser);\n      } catch (Exception e) {\n        logger.error(\"try lock error\", e);\n        throw e;\n      }\n    } else {\n      //check lock owner is current user\n      checkLock(namespace, namespaceLock, currentUser);\n    }\n  }\n\n  private void tryLock(long namespaceId, String user) {\n    NamespaceLock lock = new NamespaceLock();\n    lock.setNamespaceId(namespaceId);\n    lock.setDataChangeCreatedBy(user);\n    lock.setDataChangeLastModifiedBy(user);\n    namespaceLockService.tryLock(lock);\n  }\n\n  private void checkLock(Namespace namespace, NamespaceLock namespaceLock,\n                         String currentUser) {\n    if (namespaceLock == null) {\n      throw new ServiceException(\n          String.format(\"Check lock for %s failed, please retry.\", namespace.getNamespaceName()));\n    }\n\n    String lockOwner = namespaceLock.getDataChangeCreatedBy();\n    if (!lockOwner.equals(currentUser)) {\n      throw new BadRequestException(\n          \"namespace:\" + namespace.getNamespaceName() + \" is modified by \" + lockOwner);\n    }\n  }\n\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/aop/NamespaceUnlockAspect.java",
    "content": "package com.ctrip.framework.apollo.adminservice.aop;\n\n\nimport com.google.common.collect.MapDifference;\nimport com.google.common.collect.Maps;\nimport com.google.gson.Gson;\n\nimport com.ctrip.framework.apollo.biz.config.BizConfig;\nimport com.ctrip.framework.apollo.biz.entity.Item;\nimport com.ctrip.framework.apollo.biz.entity.Namespace;\nimport com.ctrip.framework.apollo.biz.entity.Release;\nimport com.ctrip.framework.apollo.biz.service.ItemService;\nimport com.ctrip.framework.apollo.biz.service.NamespaceLockService;\nimport com.ctrip.framework.apollo.biz.service.NamespaceService;\nimport com.ctrip.framework.apollo.biz.service.ReleaseService;\nimport com.ctrip.framework.apollo.common.constants.GsonType;\nimport com.ctrip.framework.apollo.common.dto.ItemChangeSets;\nimport com.ctrip.framework.apollo.common.dto.ItemDTO;\nimport com.ctrip.framework.apollo.common.exception.BadRequestException;\nimport com.ctrip.framework.apollo.core.utils.StringUtils;\n\nimport org.aspectj.lang.annotation.After;\nimport org.aspectj.lang.annotation.Aspect;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport java.util.List;\nimport java.util.Map;\n\n\n/**\n * unlock namespace if is redo operation.\n * --------------------------------------------\n * For example: If namespace has a item K1 = v1\n * --------------------------------------------\n * First operate: change k1 = v2 (lock namespace)\n * Second operate: change k1 = v1 (unlock namespace)\n */\n@Aspect\n@Component\npublic class NamespaceUnlockAspect {\n\n  private Gson gson = new Gson();\n\n  @Autowired\n  private NamespaceLockService namespaceLockService;\n  @Autowired\n  private NamespaceService namespaceService;\n  @Autowired\n  private ItemService itemService;\n  @Autowired\n  private ReleaseService releaseService;\n  @Autowired\n  private BizConfig bizConfig;\n\n\n  //create item\n  @After(\"@annotation(PreAcquireNamespaceLock) && args(appId, clusterName, namespaceName, item, ..)\")\n  public void requireLockAdvice(String appId, String clusterName, String namespaceName,\n                                ItemDTO item) {\n    tryUnlock(namespaceService.findOne(appId, clusterName, namespaceName));\n  }\n\n  //update item\n  @After(\"@annotation(PreAcquireNamespaceLock) && args(appId, clusterName, namespaceName, itemId, item, ..)\")\n  public void requireLockAdvice(String appId, String clusterName, String namespaceName, long itemId,\n                                ItemDTO item) {\n    tryUnlock(namespaceService.findOne(appId, clusterName, namespaceName));\n  }\n\n  //update by change set\n  @After(\"@annotation(PreAcquireNamespaceLock) && args(appId, clusterName, namespaceName, changeSet, ..)\")\n  public void requireLockAdvice(String appId, String clusterName, String namespaceName,\n                                ItemChangeSets changeSet) {\n    tryUnlock(namespaceService.findOne(appId, clusterName, namespaceName));\n  }\n\n  //delete item\n  @After(\"@annotation(PreAcquireNamespaceLock) && args(itemId, operator, ..)\")\n  public void requireLockAdvice(long itemId, String operator) {\n    Item item = itemService.findOne(itemId);\n    if (item == null) {\n      throw new BadRequestException(\"item not exist.\");\n    }\n    tryUnlock(namespaceService.findOne(item.getNamespaceId()));\n  }\n\n  private void tryUnlock(Namespace namespace) {\n    if (bizConfig.isNamespaceLockSwitchOff()) {\n      return;\n    }\n\n    if (!isModified(namespace)) {\n      namespaceLockService.unlock(namespace.getId());\n    }\n\n  }\n\n  boolean isModified(Namespace namespace) {\n    Release release = releaseService.findLatestActiveRelease(namespace);\n    List<Item> items = itemService.findItemsWithoutOrdered(namespace.getId());\n\n    if (release == null) {\n      return hasNormalItems(items);\n    }\n\n    Map<String, String> releasedConfiguration = gson.fromJson(release.getConfigurations(), GsonType.CONFIG);\n    Map<String, String> configurationFromItems = generateConfigurationFromItems(namespace, items);\n\n    MapDifference<String, String> difference = Maps.difference(releasedConfiguration, configurationFromItems);\n\n    return !difference.areEqual();\n\n  }\n\n  private boolean hasNormalItems(List<Item> items) {\n    for (Item item : items) {\n      if (!StringUtils.isEmpty(item.getKey())) {\n        return true;\n      }\n    }\n\n    return false;\n  }\n\n  private Map<String, String> generateConfigurationFromItems(Namespace namespace, List<Item> namespaceItems) {\n\n    Map<String, String> configurationFromItems = Maps.newHashMap();\n\n    Namespace parentNamespace = namespaceService.findParentNamespace(namespace);\n    //parent namespace\n    if (parentNamespace == null) {\n      generateMapFromItems(namespaceItems, configurationFromItems);\n    } else {//child namespace\n      Release parentRelease = releaseService.findLatestActiveRelease(parentNamespace);\n      if (parentRelease != null) {\n        configurationFromItems = gson.fromJson(parentRelease.getConfigurations(), GsonType.CONFIG);\n      }\n      generateMapFromItems(namespaceItems, configurationFromItems);\n    }\n\n    return configurationFromItems;\n  }\n\n  private Map<String, String> generateMapFromItems(List<Item> items, Map<String, String> configurationFromItems) {\n    for (Item item : items) {\n      String key = item.getKey();\n      if (StringUtils.isBlank(key)) {\n        continue;\n      }\n      configurationFromItems.put(key, item.getValue());\n    }\n\n    return configurationFromItems;\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/aop/PreAcquireNamespaceLock.java",
    "content": "package com.ctrip.framework.apollo.adminservice.aop;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * 标识方法需要获取到namespace的lock才能执行\n */\n@Target(ElementType.METHOD)\n@Retention(RetentionPolicy.RUNTIME)\npublic @interface PreAcquireNamespaceLock {\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/AppController.java",
    "content": "package com.ctrip.framework.apollo.adminservice.controller;\n\nimport com.ctrip.framework.apollo.biz.service.AdminService;\nimport com.ctrip.framework.apollo.biz.service.AppService;\nimport com.ctrip.framework.apollo.common.dto.AppDTO;\nimport com.ctrip.framework.apollo.common.entity.App;\nimport com.ctrip.framework.apollo.common.exception.BadRequestException;\nimport com.ctrip.framework.apollo.common.exception.NotFoundException;\nimport com.ctrip.framework.apollo.common.utils.BeanUtils;\nimport com.ctrip.framework.apollo.common.utils.InputValidator;\nimport com.ctrip.framework.apollo.core.utils.StringUtils;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.data.domain.Pageable;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.List;\nimport java.util.Objects;\n\n@RestController\npublic class AppController {\n\n  @Autowired\n  private AppService appService;\n\n  @Autowired\n  private AdminService adminService;\n\n  @RequestMapping(path = \"/apps\", method = RequestMethod.POST)\n  public AppDTO create(@RequestBody AppDTO dto) {\n    if (!InputValidator.isValidClusterNamespace(dto.getAppId())) {\n      throw new BadRequestException(String.format(\"AppId格式错误: %s\", InputValidator.INVALID_CLUSTER_NAMESPACE_MESSAGE));\n    }\n    App entity = BeanUtils.transfrom(App.class, dto);\n    App managedEntity = appService.findOne(entity.getAppId());\n    if (managedEntity != null) {\n      throw new BadRequestException(\"app already exist.\");\n    }\n\n    entity = adminService.createNewApp(entity);\n\n    dto = BeanUtils.transfrom(AppDTO.class, entity);\n    return dto;\n  }\n\n  @RequestMapping(value = \"/apps/{appId:.+}\", method = RequestMethod.DELETE)\n  public void delete(@PathVariable(\"appId\") String appId, @RequestParam String operator) {\n    App entity = appService.findOne(appId);\n    if (entity == null) {\n      throw new NotFoundException(\"app not found for appId \" + appId);\n    }\n    appService.delete(entity.getId(), operator);\n  }\n\n  @RequestMapping(value = \"/apps/{appId:.+}\", method = RequestMethod.PUT)\n  public void update(@PathVariable String appId, @RequestBody App app) {\n    if (!Objects.equals(appId, app.getAppId())) {\n      throw new BadRequestException(\"The App Id of path variable and request body is different\");\n    }\n\n    appService.update(app);\n  }\n\n  @RequestMapping(value = \"/apps\", method = RequestMethod.GET)\n  public List<AppDTO> find(@RequestParam(value = \"name\", required = false) String name,\n                           Pageable pageable) {\n    List<App> app = null;\n    if (StringUtils.isBlank(name)) {\n      app = appService.findAll(pageable);\n    } else {\n      app = appService.findByName(name);\n    }\n    return BeanUtils.batchTransform(AppDTO.class, app);\n  }\n\n  @RequestMapping(value = \"/apps/{appId:.+}\", method = RequestMethod.GET)\n  public AppDTO get(@PathVariable(\"appId\") String appId) {\n    App app = appService.findOne(appId);\n    if (app == null) {\n      throw new NotFoundException(\"app not found for appId \" + appId);\n    }\n    return BeanUtils.transfrom(AppDTO.class, app);\n  }\n\n  @RequestMapping(value = \"/apps/{appId}/unique\", method = RequestMethod.GET)\n  public boolean isAppIdUnique(@PathVariable(\"appId\") String appId) {\n    return appService.isAppIdUnique(appId);\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/AppNamespaceController.java",
    "content": "package com.ctrip.framework.apollo.adminservice.controller;\n\nimport com.ctrip.framework.apollo.biz.entity.Namespace;\nimport com.ctrip.framework.apollo.biz.service.AppNamespaceService;\nimport com.ctrip.framework.apollo.biz.service.NamespaceService;\nimport com.ctrip.framework.apollo.common.dto.AppNamespaceDTO;\nimport com.ctrip.framework.apollo.common.dto.NamespaceDTO;\nimport com.ctrip.framework.apollo.common.entity.AppNamespace;\nimport com.ctrip.framework.apollo.common.exception.BadRequestException;\nimport com.ctrip.framework.apollo.common.utils.BeanUtils;\nimport com.ctrip.framework.apollo.core.enums.ConfigFileFormat;\nimport com.ctrip.framework.apollo.core.utils.StringUtils;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.data.domain.Pageable;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.List;\n\n@RestController\npublic class AppNamespaceController {\n\n  @Autowired\n  private AppNamespaceService appNamespaceService;\n  @Autowired\n  private NamespaceService namespaceService;\n\n  @RequestMapping(value = \"/apps/{appId}/appnamespaces\", method = RequestMethod.POST)\n  public AppNamespaceDTO create(@RequestBody AppNamespaceDTO appNamespace) {\n\n    AppNamespace entity = BeanUtils.transfrom(AppNamespace.class, appNamespace);\n    AppNamespace managedEntity = appNamespaceService.findOne(entity.getAppId(), entity.getName());\n\n    if (managedEntity != null) {\n      throw new BadRequestException(\"app namespaces already exist.\");\n    }\n\n    if (StringUtils.isEmpty(entity.getFormat())){\n      entity.setFormat(ConfigFileFormat.Properties.getValue());\n    }\n\n    entity = appNamespaceService.createAppNamespace(entity);\n\n    return BeanUtils.transfrom(AppNamespaceDTO.class, entity);\n\n  }\n\n  @RequestMapping(value = \"/appnamespaces/{publicNamespaceName}/namespaces\", method = RequestMethod.GET)\n  public List<NamespaceDTO> findPublicAppNamespaceAllNamespaces(@PathVariable String publicNamespaceName, Pageable pageable) {\n\n    List<Namespace> namespaces = namespaceService.findPublicAppNamespaceAllNamespaces(publicNamespaceName, pageable);\n\n    return BeanUtils.batchTransform(NamespaceDTO.class, namespaces);\n  }\n\n  @RequestMapping(value = \"/appnamespaces/{publicNamespaceName}/associated-namespaces/count\", method = RequestMethod.GET)\n  public int countPublicAppNamespaceAssociatedNamespaces(@PathVariable String publicNamespaceName) {\n    return namespaceService.countPublicAppNamespaceAssociatedNamespaces(publicNamespaceName);\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/ClusterController.java",
    "content": "package com.ctrip.framework.apollo.adminservice.controller;\n\nimport com.ctrip.framework.apollo.biz.entity.Cluster;\nimport com.ctrip.framework.apollo.biz.service.ClusterService;\nimport com.ctrip.framework.apollo.common.dto.ClusterDTO;\nimport com.ctrip.framework.apollo.common.exception.BadRequestException;\nimport com.ctrip.framework.apollo.common.exception.NotFoundException;\nimport com.ctrip.framework.apollo.common.utils.BeanUtils;\nimport com.ctrip.framework.apollo.common.utils.InputValidator;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.List;\n\n@RestController\npublic class ClusterController {\n\n  @Autowired\n  private ClusterService clusterService;\n\n  @RequestMapping(path = \"/apps/{appId}/clusters\", method = RequestMethod.POST)\n  public ClusterDTO create(@PathVariable(\"appId\") String appId,\n                           @RequestParam(value = \"autoCreatePrivateNamespace\", defaultValue = \"true\") boolean autoCreatePrivateNamespace,\n                           @RequestBody ClusterDTO dto) {\n    if (!InputValidator.isValidClusterNamespace(dto.getName())) {\n      throw new BadRequestException(String.format(\"Cluster格式错误: %s\", InputValidator.INVALID_CLUSTER_NAMESPACE_MESSAGE));\n    }\n\n    Cluster entity = BeanUtils.transfrom(Cluster.class, dto);\n    Cluster managedEntity = clusterService.findOne(appId, entity.getName());\n    if (managedEntity != null) {\n      throw new BadRequestException(\"cluster already exist.\");\n    }\n\n    if (autoCreatePrivateNamespace) {\n      entity = clusterService.saveWithInstanceOfAppNamespaces(entity);\n    } else {\n      entity = clusterService.saveWithoutInstanceOfAppNamespaces(entity);\n    }\n\n    dto = BeanUtils.transfrom(ClusterDTO.class, entity);\n    return dto;\n  }\n\n  @RequestMapping(path = \"/apps/{appId}/clusters/{clusterName:.+}\", method = RequestMethod.DELETE)\n  public void delete(@PathVariable(\"appId\") String appId,\n                     @PathVariable(\"clusterName\") String clusterName, @RequestParam String operator) {\n    Cluster entity = clusterService.findOne(appId, clusterName);\n    if (entity == null) {\n      throw new NotFoundException(\"cluster not found for clusterName \" + clusterName);\n    }\n    clusterService.delete(entity.getId(), operator);\n  }\n\n  @RequestMapping(value = \"/apps/{appId}/clusters\", method = RequestMethod.GET)\n  public List<ClusterDTO> find(@PathVariable(\"appId\") String appId) {\n    List<Cluster> clusters = clusterService.findParentClusters(appId);\n    return BeanUtils.batchTransform(ClusterDTO.class, clusters);\n  }\n\n  @RequestMapping(value = \"/apps/{appId}/clusters/{clusterName:.+}\", method = RequestMethod.GET)\n  public ClusterDTO get(@PathVariable(\"appId\") String appId,\n                        @PathVariable(\"clusterName\") String clusterName) {\n    Cluster cluster = clusterService.findOne(appId, clusterName);\n    if (cluster == null) {\n      throw new NotFoundException(\"cluster not found for name \" + clusterName);\n    }\n    return BeanUtils.transfrom(ClusterDTO.class, cluster);\n  }\n\n  @RequestMapping(value = \"/apps/{appId}/cluster/{clusterName}/unique\", method = RequestMethod.GET)\n  public boolean isAppIdUnique(@PathVariable(\"appId\") String appId,\n                               @PathVariable(\"clusterName\") String clusterName) {\n    return clusterService.isClusterNameUnique(appId, clusterName);\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/CommitController.java",
    "content": "package com.ctrip.framework.apollo.adminservice.controller;\n\nimport com.ctrip.framework.apollo.biz.entity.Commit;\nimport com.ctrip.framework.apollo.biz.service.CommitService;\nimport com.ctrip.framework.apollo.common.dto.CommitDTO;\nimport com.ctrip.framework.apollo.common.utils.BeanUtils;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.data.domain.Pageable;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.List;\n\n\n@RestController\npublic class CommitController {\n\n  @Autowired\n  private CommitService commitService;\n\n  @RequestMapping(value = \"/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/commit\", method = RequestMethod.GET)\n  public List<CommitDTO> find(@PathVariable String appId, @PathVariable String clusterName,\n                              @PathVariable String namespaceName, Pageable pageable){\n\n    List<Commit> commits = commitService.find(appId, clusterName, namespaceName, pageable);\n    return BeanUtils.batchTransform(CommitDTO.class, commits);\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/IndexController.java",
    "content": "package com.ctrip.framework.apollo.adminservice.controller;\n\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RestController;\n\n@RestController\n@RequestMapping(path = \"/\")\npublic class IndexController {\n\n  @RequestMapping(path = \"\", method = RequestMethod.GET)\n  public String index() {\n    return \"apollo-adminservice\";\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/InstanceConfigController.java",
    "content": "package com.ctrip.framework.apollo.adminservice.controller;\n\nimport com.google.common.base.Splitter;\nimport com.google.common.base.Strings;\nimport com.google.common.collect.HashMultimap;\nimport com.google.common.collect.Maps;\nimport com.google.common.collect.Multimap;\nimport com.google.common.collect.Sets;\n\nimport com.ctrip.framework.apollo.biz.entity.Instance;\nimport com.ctrip.framework.apollo.biz.entity.InstanceConfig;\nimport com.ctrip.framework.apollo.biz.entity.Release;\nimport com.ctrip.framework.apollo.biz.service.InstanceService;\nimport com.ctrip.framework.apollo.biz.service.ReleaseService;\nimport com.ctrip.framework.apollo.common.dto.InstanceConfigDTO;\nimport com.ctrip.framework.apollo.common.dto.InstanceDTO;\nimport com.ctrip.framework.apollo.common.dto.PageDTO;\nimport com.ctrip.framework.apollo.common.dto.ReleaseDTO;\nimport com.ctrip.framework.apollo.common.exception.NotFoundException;\nimport com.ctrip.framework.apollo.common.utils.BeanUtils;\n\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.util.CollectionUtils;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.stream.Collectors;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@RestController\n@RequestMapping(\"/instances\")\npublic class InstanceConfigController {\n  private static final Splitter RELEASES_SPLITTER = Splitter.on(\",\").omitEmptyStrings()\n      .trimResults();\n  @Autowired\n  private ReleaseService releaseService;\n  @Autowired\n  private InstanceService instanceService;\n\n  @RequestMapping(value = \"/by-release\", method = RequestMethod.GET)\n  public PageDTO<InstanceDTO> getByRelease(@RequestParam(\"releaseId\") long releaseId,\n                                           Pageable pageable) {\n    Release release = releaseService.findOne(releaseId);\n    if (release == null) {\n      throw new NotFoundException(String.format(\"release not found for %s\", releaseId));\n    }\n    Page<InstanceConfig> instanceConfigsPage = instanceService.findActiveInstanceConfigsByReleaseKey\n        (release.getReleaseKey(), pageable);\n\n    List<InstanceDTO> instanceDTOs = Collections.emptyList();\n\n    if (instanceConfigsPage.hasContent()) {\n      Multimap<Long, InstanceConfig> instanceConfigMap = HashMultimap.create();\n      Set<String> otherReleaseKeys = Sets.newHashSet();\n\n      for (InstanceConfig instanceConfig : instanceConfigsPage.getContent()) {\n        instanceConfigMap.put(instanceConfig.getInstanceId(), instanceConfig);\n        otherReleaseKeys.add(instanceConfig.getReleaseKey());\n      }\n\n      Set<Long> instanceIds = instanceConfigMap.keySet();\n\n      List<Instance> instances = instanceService.findInstancesByIds(instanceIds);\n\n      if (!CollectionUtils.isEmpty(instances)) {\n        instanceDTOs = BeanUtils.batchTransform(InstanceDTO.class, instances);\n      }\n\n      for (InstanceDTO instanceDTO : instanceDTOs) {\n        Collection<InstanceConfig> configs = instanceConfigMap.get(instanceDTO.getId());\n        List<InstanceConfigDTO> configDTOs = configs.stream().map(instanceConfig -> {\n          InstanceConfigDTO instanceConfigDTO = new InstanceConfigDTO();\n          //to save some space\n          instanceConfigDTO.setRelease(null);\n          instanceConfigDTO.setReleaseDeliveryTime(instanceConfig.getReleaseDeliveryTime());\n          instanceConfigDTO.setDataChangeLastModifiedTime(instanceConfig\n              .getDataChangeLastModifiedTime());\n          return instanceConfigDTO;\n        }).collect(Collectors.toList());\n        instanceDTO.setConfigs(configDTOs);\n      }\n    }\n\n    return new PageDTO<>(instanceDTOs, pageable, instanceConfigsPage.getTotalElements());\n  }\n\n  @RequestMapping(value = \"/by-namespace-and-releases-not-in\", method = RequestMethod.GET)\n  public List<InstanceDTO> getByReleasesNotIn(@RequestParam(\"appId\") String appId,\n                                              @RequestParam(\"clusterName\") String clusterName,\n                                              @RequestParam(\"namespaceName\") String namespaceName,\n                                              @RequestParam(\"releaseIds\") String releaseIds) {\n    Set<Long> releaseIdSet = RELEASES_SPLITTER.splitToList(releaseIds).stream().map(Long::parseLong)\n        .collect(Collectors.toSet());\n\n    List<Release> releases = releaseService.findByReleaseIds(releaseIdSet);\n\n    if (CollectionUtils.isEmpty(releases)) {\n      throw new NotFoundException(String.format(\"releases not found for %s\", releaseIds));\n    }\n\n    Set<String> releaseKeys = releases.stream().map(Release::getReleaseKey).collect(Collectors\n        .toSet());\n\n    List<InstanceConfig> instanceConfigs = instanceService\n        .findInstanceConfigsByNamespaceWithReleaseKeysNotIn(appId, clusterName, namespaceName,\n            releaseKeys);\n\n    Multimap<Long, InstanceConfig> instanceConfigMap = HashMultimap.create();\n    Set<String> otherReleaseKeys = Sets.newHashSet();\n\n    for (InstanceConfig instanceConfig : instanceConfigs) {\n      instanceConfigMap.put(instanceConfig.getInstanceId(), instanceConfig);\n      otherReleaseKeys.add(instanceConfig.getReleaseKey());\n    }\n\n    List<Instance> instances = instanceService.findInstancesByIds(instanceConfigMap.keySet());\n\n    if (CollectionUtils.isEmpty(instances)) {\n      return Collections.emptyList();\n    }\n\n    List<InstanceDTO> instanceDTOs = BeanUtils.batchTransform(InstanceDTO.class, instances);\n\n    List<Release> otherReleases = releaseService.findByReleaseKeys(otherReleaseKeys);\n    Map<String, ReleaseDTO> releaseMap = Maps.newHashMap();\n\n    for (Release release : otherReleases) {\n      //unset configurations to save space\n      release.setConfigurations(null);\n      ReleaseDTO releaseDTO = BeanUtils.transfrom(ReleaseDTO.class, release);\n      releaseMap.put(release.getReleaseKey(), releaseDTO);\n    }\n\n    for (InstanceDTO instanceDTO : instanceDTOs) {\n      Collection<InstanceConfig> configs = instanceConfigMap.get(instanceDTO.getId());\n      List<InstanceConfigDTO> configDTOs = configs.stream().map(instanceConfig -> {\n        InstanceConfigDTO instanceConfigDTO = new InstanceConfigDTO();\n        instanceConfigDTO.setRelease(releaseMap.get(instanceConfig.getReleaseKey()));\n        instanceConfigDTO.setReleaseDeliveryTime(instanceConfig.getReleaseDeliveryTime());\n        instanceConfigDTO.setDataChangeLastModifiedTime(instanceConfig\n            .getDataChangeLastModifiedTime());\n        return instanceConfigDTO;\n      }).collect(Collectors.toList());\n      instanceDTO.setConfigs(configDTOs);\n    }\n\n    return instanceDTOs;\n  }\n\n  @RequestMapping(value = \"/by-namespace\", method = RequestMethod.GET)\n  public PageDTO<InstanceDTO> getInstancesByNamespace(\n      @RequestParam(\"appId\") String appId, @RequestParam(\"clusterName\") String clusterName,\n      @RequestParam(\"namespaceName\") String namespaceName,\n      @RequestParam(value = \"instanceAppId\", required = false) String instanceAppId,\n      Pageable pageable) {\n    Page<Instance> instances;\n    if (Strings.isNullOrEmpty(instanceAppId)) {\n      instances = instanceService.findInstancesByNamespace(appId, clusterName,\n          namespaceName, pageable);\n    } else {\n      instances = instanceService.findInstancesByNamespaceAndInstanceAppId(instanceAppId, appId,\n          clusterName, namespaceName, pageable);\n    }\n\n    List<InstanceDTO> instanceDTOs = BeanUtils.batchTransform(InstanceDTO.class, instances.getContent());\n    return new PageDTO<>(instanceDTOs, pageable, instances.getTotalElements());\n  }\n\n  @RequestMapping(value = \"/by-namespace/count\", method = RequestMethod.GET)\n  public long getInstancesCountByNamespace(@RequestParam(\"appId\") String appId,\n                                          @RequestParam(\"clusterName\") String clusterName,\n                                          @RequestParam(\"namespaceName\") String namespaceName) {\n    Page<Instance> instances = instanceService.findInstancesByNamespace(appId, clusterName,\n        namespaceName, new PageRequest(0, 1));\n    return instances.getTotalElements();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/ItemController.java",
    "content": "package com.ctrip.framework.apollo.adminservice.controller;\n\nimport com.ctrip.framework.apollo.adminservice.aop.PreAcquireNamespaceLock;\nimport com.ctrip.framework.apollo.biz.entity.Commit;\nimport com.ctrip.framework.apollo.biz.entity.Item;\nimport com.ctrip.framework.apollo.biz.entity.Namespace;\nimport com.ctrip.framework.apollo.biz.service.CommitService;\nimport com.ctrip.framework.apollo.biz.service.ItemService;\nimport com.ctrip.framework.apollo.biz.service.NamespaceService;\nimport com.ctrip.framework.apollo.biz.utils.ConfigChangeContentBuilder;\nimport com.ctrip.framework.apollo.common.dto.ItemDTO;\nimport com.ctrip.framework.apollo.common.exception.BadRequestException;\nimport com.ctrip.framework.apollo.common.exception.NotFoundException;\nimport com.ctrip.framework.apollo.common.utils.BeanUtils;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.List;\n\n@RestController\npublic class ItemController {\n\n  @Autowired\n  private ItemService itemService;\n  @Autowired\n  private NamespaceService namespaceService;\n  @Autowired\n  private CommitService commitService;\n\n  @PreAcquireNamespaceLock\n  @RequestMapping(path = \"/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items\", method = RequestMethod.POST)\n  public ItemDTO create(@PathVariable(\"appId\") String appId,\n                        @PathVariable(\"clusterName\") String clusterName,\n                        @PathVariable(\"namespaceName\") String namespaceName, @RequestBody ItemDTO dto) {\n    Item entity = BeanUtils.transfrom(Item.class, dto);\n\n    ConfigChangeContentBuilder builder = new ConfigChangeContentBuilder();\n    Item managedEntity = itemService.findOne(appId, clusterName, namespaceName, entity.getKey());\n    if (managedEntity != null) {\n      throw new BadRequestException(\"item already exist\");\n    } else {\n      entity = itemService.save(entity);\n      builder.createItem(entity);\n    }\n    dto = BeanUtils.transfrom(ItemDTO.class, entity);\n\n    Commit commit = new Commit();\n    commit.setAppId(appId);\n    commit.setClusterName(clusterName);\n    commit.setNamespaceName(namespaceName);\n    commit.setChangeSets(builder.build());\n    commit.setDataChangeCreatedBy(dto.getDataChangeLastModifiedBy());\n    commit.setDataChangeLastModifiedBy(dto.getDataChangeLastModifiedBy());\n    commitService.save(commit);\n\n    return dto;\n  }\n\n  @PreAcquireNamespaceLock\n  @RequestMapping(path = \"/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items/{itemId}\", method = RequestMethod.PUT)\n  public ItemDTO update(@PathVariable(\"appId\") String appId,\n                        @PathVariable(\"clusterName\") String clusterName,\n                        @PathVariable(\"namespaceName\") String namespaceName,\n                        @PathVariable(\"itemId\") long itemId,\n                        @RequestBody ItemDTO itemDTO) {\n\n    Item entity = BeanUtils.transfrom(Item.class, itemDTO);\n\n    ConfigChangeContentBuilder builder = new ConfigChangeContentBuilder();\n\n    Item managedEntity = itemService.findOne(itemId);\n    if (managedEntity == null) {\n      throw new BadRequestException(\"item not exist\");\n    }\n\n    Item beforeUpdateItem = BeanUtils.transfrom(Item.class, managedEntity);\n\n    //protect. only value,comment,lastModifiedBy can be modified\n    managedEntity.setValue(entity.getValue());\n    managedEntity.setComment(entity.getComment());\n    managedEntity.setDataChangeLastModifiedBy(entity.getDataChangeLastModifiedBy());\n\n    entity = itemService.update(managedEntity);\n    builder.updateItem(beforeUpdateItem, entity);\n    itemDTO = BeanUtils.transfrom(ItemDTO.class, entity);\n\n    if (builder.hasContent()) {\n      Commit commit = new Commit();\n      commit.setAppId(appId);\n      commit.setClusterName(clusterName);\n      commit.setNamespaceName(namespaceName);\n      commit.setChangeSets(builder.build());\n      commit.setDataChangeCreatedBy(itemDTO.getDataChangeLastModifiedBy());\n      commit.setDataChangeLastModifiedBy(itemDTO.getDataChangeLastModifiedBy());\n      commitService.save(commit);\n    }\n\n    return itemDTO;\n  }\n\n  @PreAcquireNamespaceLock\n  @RequestMapping(path = \"/items/{itemId}\", method = RequestMethod.DELETE)\n  public void delete(@PathVariable(\"itemId\") long itemId, @RequestParam String operator) {\n    Item entity = itemService.findOne(itemId);\n    if (entity == null) {\n      throw new NotFoundException(\"item not found for itemId \" + itemId);\n    }\n    itemService.delete(entity.getId(), operator);\n\n    Namespace namespace = namespaceService.findOne(entity.getNamespaceId());\n\n    Commit commit = new Commit();\n    commit.setAppId(namespace.getAppId());\n    commit.setClusterName(namespace.getClusterName());\n    commit.setNamespaceName(namespace.getNamespaceName());\n    commit.setChangeSets(new ConfigChangeContentBuilder().deleteItem(entity).build());\n    commit.setDataChangeCreatedBy(operator);\n    commit.setDataChangeLastModifiedBy(operator);\n    commitService.save(commit);\n  }\n\n  @RequestMapping(value = \"/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items\", method = RequestMethod.GET)\n  public List<ItemDTO> findItems(@PathVariable(\"appId\") String appId,\n                                 @PathVariable(\"clusterName\") String clusterName,\n                                 @PathVariable(\"namespaceName\") String namespaceName) {\n    return BeanUtils.batchTransform(ItemDTO.class, itemService.findItemsWithOrdered(appId, clusterName, namespaceName));\n  }\n\n  @RequestMapping(value = \"/items/{itemId}\", method = RequestMethod.GET)\n  public ItemDTO get(@PathVariable(\"itemId\") long itemId) {\n    Item item = itemService.findOne(itemId);\n    if (item == null) {\n      throw new NotFoundException(\"item not found for itemId \" + itemId);\n    }\n    return BeanUtils.transfrom(ItemDTO.class, item);\n  }\n\n  @RequestMapping(value = \"/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items/{key:.+}\", method = RequestMethod.GET)\n  public ItemDTO get(@PathVariable(\"appId\") String appId,\n                     @PathVariable(\"clusterName\") String clusterName,\n                     @PathVariable(\"namespaceName\") String namespaceName, @PathVariable(\"key\") String key) {\n    Item item = itemService.findOne(appId, clusterName, namespaceName, key);\n    if (item == null) {\n      throw new NotFoundException(\n          String.format(\"item not found for %s %s %s %s\", appId, clusterName, namespaceName, key));\n    }\n    return BeanUtils.transfrom(ItemDTO.class, item);\n  }\n\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/ItemSetController.java",
    "content": "package com.ctrip.framework.apollo.adminservice.controller;\n\nimport com.ctrip.framework.apollo.adminservice.aop.PreAcquireNamespaceLock;\nimport com.ctrip.framework.apollo.biz.service.ItemSetService;\nimport com.ctrip.framework.apollo.common.dto.ItemChangeSets;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RestController;\n\n@RestController\npublic class ItemSetController {\n\n  @Autowired\n  private ItemSetService itemSetService;\n\n  @PreAcquireNamespaceLock\n  @RequestMapping(path = \"/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/itemset\", method = RequestMethod.POST)\n  public ResponseEntity<Void> create(@PathVariable String appId, @PathVariable String clusterName,\n                                     @PathVariable String namespaceName, @RequestBody ItemChangeSets changeSet) {\n\n    itemSetService.updateSet(appId, clusterName, namespaceName, changeSet);\n\n    return ResponseEntity.status(HttpStatus.OK).build();\n  }\n\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/NamespaceBranchController.java",
    "content": "package com.ctrip.framework.apollo.adminservice.controller;\n\nimport com.ctrip.framework.apollo.biz.entity.GrayReleaseRule;\nimport com.ctrip.framework.apollo.biz.entity.Namespace;\nimport com.ctrip.framework.apollo.biz.message.MessageSender;\nimport com.ctrip.framework.apollo.biz.message.Topics;\nimport com.ctrip.framework.apollo.biz.service.NamespaceBranchService;\nimport com.ctrip.framework.apollo.biz.service.NamespaceService;\nimport com.ctrip.framework.apollo.biz.utils.ReleaseMessageKeyGenerator;\nimport com.ctrip.framework.apollo.common.constants.NamespaceBranchStatus;\nimport com.ctrip.framework.apollo.common.dto.GrayReleaseRuleDTO;\nimport com.ctrip.framework.apollo.common.dto.NamespaceDTO;\nimport com.ctrip.framework.apollo.common.exception.BadRequestException;\nimport com.ctrip.framework.apollo.common.utils.BeanUtils;\nimport com.ctrip.framework.apollo.common.utils.GrayReleaseRuleItemTransformer;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.transaction.annotation.Transactional;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\n@RestController\npublic class NamespaceBranchController {\n\n  @Autowired\n  private MessageSender messageSender;\n  @Autowired\n  private NamespaceBranchService namespaceBranchService;\n  @Autowired\n  private NamespaceService namespaceService;\n\n\n  @RequestMapping(value = \"/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/branches\", method = RequestMethod.POST)\n  public NamespaceDTO createBranch(@PathVariable String appId,\n                                   @PathVariable String clusterName,\n                                   @PathVariable String namespaceName,\n                                   @RequestParam(\"operator\") String operator) {\n\n    checkNamespace(appId, clusterName, namespaceName);\n\n    Namespace createdBranch = namespaceBranchService.createBranch(appId, clusterName, namespaceName, operator);\n\n    return BeanUtils.transfrom(NamespaceDTO.class, createdBranch);\n  }\n\n  @RequestMapping(value = \"/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/branches/{branchName}/rules\",\n      method = RequestMethod.GET)\n  public GrayReleaseRuleDTO findBranchGrayRules(@PathVariable String appId,\n                                                @PathVariable String clusterName,\n                                                @PathVariable String namespaceName,\n                                                @PathVariable String branchName) {\n\n    checkBranch(appId, clusterName, namespaceName, branchName);\n\n    GrayReleaseRule rules = namespaceBranchService.findBranchGrayRules(appId, clusterName, namespaceName, branchName);\n    if (rules == null) {\n      return null;\n    }\n    GrayReleaseRuleDTO ruleDTO =\n        new GrayReleaseRuleDTO(rules.getAppId(), rules.getClusterName(), rules.getNamespaceName(),\n                               rules.getBranchName());\n\n    ruleDTO.setReleaseId(rules.getReleaseId());\n\n    ruleDTO.setRuleItems(GrayReleaseRuleItemTransformer.batchTransformFromJSON(rules.getRules()));\n\n    return ruleDTO;\n  }\n\n  @Transactional\n  @RequestMapping(value = \"/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/branches/{branchName}/rules\", method = RequestMethod.PUT)\n  public void updateBranchGrayRules(@PathVariable String appId, @PathVariable String clusterName,\n                                    @PathVariable String namespaceName, @PathVariable String branchName,\n                                    @RequestBody GrayReleaseRuleDTO newRuleDto) {\n\n    checkBranch(appId, clusterName, namespaceName, branchName);\n\n    GrayReleaseRule newRules = BeanUtils.transfrom(GrayReleaseRule.class, newRuleDto);\n    newRules.setRules(GrayReleaseRuleItemTransformer.batchTransformToJSON(newRuleDto.getRuleItems()));\n    newRules.setBranchStatus(NamespaceBranchStatus.ACTIVE);\n\n    namespaceBranchService.updateBranchGrayRules(appId, clusterName, namespaceName, branchName, newRules);\n\n    messageSender.sendMessage(ReleaseMessageKeyGenerator.generate(appId, clusterName, namespaceName),\n                              Topics.APOLLO_RELEASE_TOPIC);\n  }\n\n  @Transactional\n  @RequestMapping(value = \"/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/branches/{branchName}\", method = RequestMethod.DELETE)\n  public void deleteBranch(@PathVariable String appId, @PathVariable String clusterName,\n                           @PathVariable String namespaceName, @PathVariable String branchName,\n                           @RequestParam(\"operator\") String operator) {\n\n    checkBranch(appId, clusterName, namespaceName, branchName);\n\n    namespaceBranchService\n        .deleteBranch(appId, clusterName, namespaceName, branchName, NamespaceBranchStatus.DELETED, operator);\n\n    messageSender.sendMessage(ReleaseMessageKeyGenerator.generate(appId, clusterName, namespaceName),\n                              Topics.APOLLO_RELEASE_TOPIC);\n\n  }\n\n  @RequestMapping(value = \"/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/branches\", method = RequestMethod.GET)\n  public NamespaceDTO loadNamespaceBranch(@PathVariable String appId, @PathVariable String clusterName,\n                                          @PathVariable String namespaceName) {\n\n    checkNamespace(appId, clusterName, namespaceName);\n\n    Namespace childNamespace = namespaceBranchService.findBranch(appId, clusterName, namespaceName);\n    if (childNamespace == null) {\n      return null;\n    }\n\n    return BeanUtils.transfrom(NamespaceDTO.class, childNamespace);\n  }\n\n  private void checkBranch(String appId, String clusterName, String namespaceName, String branchName) {\n    //1. check parent namespace\n    checkNamespace(appId, clusterName, namespaceName);\n\n    //2. check child namespace\n    Namespace childNamespace = namespaceService.findOne(appId, branchName, namespaceName);\n    if (childNamespace == null) {\n      throw new BadRequestException(String.format(\"Namespace's branch not exist. AppId = %s, ClusterName = %s, \"\n                                                  + \"NamespaceName = %s, BranchName = %s\",\n                                                  appId, clusterName, namespaceName, branchName));\n    }\n\n  }\n\n  private void checkNamespace(String appId, String clusterName, String namespaceName) {\n    Namespace parentNamespace = namespaceService.findOne(appId, clusterName, namespaceName);\n    if (parentNamespace == null) {\n      throw new BadRequestException(String.format(\"Namespace not exist. AppId = %s, ClusterName = %s, NamespaceName = %s\", appId,\n                                                  clusterName, namespaceName));\n    }\n  }\n\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/NamespaceController.java",
    "content": "package com.ctrip.framework.apollo.adminservice.controller;\n\nimport com.ctrip.framework.apollo.biz.entity.Namespace;\nimport com.ctrip.framework.apollo.biz.service.NamespaceService;\nimport com.ctrip.framework.apollo.common.dto.NamespaceDTO;\nimport com.ctrip.framework.apollo.common.exception.BadRequestException;\nimport com.ctrip.framework.apollo.common.exception.NotFoundException;\nimport com.ctrip.framework.apollo.common.utils.BeanUtils;\nimport com.ctrip.framework.apollo.common.utils.InputValidator;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.List;\nimport java.util.Map;\n\n@RestController\npublic class NamespaceController {\n\n  @Autowired\n  private NamespaceService namespaceService;\n\n  @RequestMapping(path = \"/apps/{appId}/clusters/{clusterName}/namespaces\", method = RequestMethod.POST)\n  public NamespaceDTO create(@PathVariable(\"appId\") String appId,\n                             @PathVariable(\"clusterName\") String clusterName, @RequestBody NamespaceDTO dto) {\n    if (!InputValidator.isValidClusterNamespace(dto.getNamespaceName())) {\n      throw new BadRequestException(String.format(\"Namespace格式错误: %s\", InputValidator.INVALID_CLUSTER_NAMESPACE_MESSAGE));\n    }\n    Namespace entity = BeanUtils.transfrom(Namespace.class, dto);\n    Namespace managedEntity = namespaceService.findOne(appId, clusterName, entity.getNamespaceName());\n    if (managedEntity != null) {\n      throw new BadRequestException(\"namespace already exist.\");\n    }\n\n    entity = namespaceService.save(entity);\n\n    dto = BeanUtils.transfrom(NamespaceDTO.class, entity);\n    return dto;\n  }\n\n  @RequestMapping(path = \"/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName:.+}\", method = RequestMethod.DELETE)\n  public void delete(@PathVariable(\"appId\") String appId,\n                     @PathVariable(\"clusterName\") String clusterName,\n                     @PathVariable(\"namespaceName\") String namespaceName, @RequestParam String operator) {\n    Namespace entity = namespaceService.findOne(appId, clusterName, namespaceName);\n    if (entity == null) throw new NotFoundException(\n            String.format(\"namespace not found for %s %s %s\", appId, clusterName, namespaceName));\n\n    namespaceService.deleteNamespace(entity, operator);\n  }\n\n  @RequestMapping(value = \"/apps/{appId}/clusters/{clusterName}/namespaces\", method = RequestMethod.GET)\n  public List<NamespaceDTO> find(@PathVariable(\"appId\") String appId,\n                                 @PathVariable(\"clusterName\") String clusterName) {\n    List<Namespace> groups = namespaceService.findNamespaces(appId, clusterName);\n    return BeanUtils.batchTransform(NamespaceDTO.class, groups);\n  }\n\n  @RequestMapping(value = \"/namespaces/{namespaceId}\", method = RequestMethod.GET)\n  public NamespaceDTO get(@PathVariable(\"namespaceId\") Long namespaceId) {\n    Namespace namespace = namespaceService.findOne(namespaceId);\n    if (namespace == null)\n      throw new NotFoundException(String.format(\"namespace not found for %s\", namespaceId));\n    return BeanUtils.transfrom(NamespaceDTO.class, namespace);\n  }\n\n  @RequestMapping(value = \"/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName:.+}\", method = RequestMethod.GET)\n  public NamespaceDTO get(@PathVariable(\"appId\") String appId,\n                          @PathVariable(\"clusterName\") String clusterName,\n                          @PathVariable(\"namespaceName\") String namespaceName) {\n    Namespace namespace = namespaceService.findOne(appId, clusterName, namespaceName);\n    if (namespace == null) throw new NotFoundException(\n            String.format(\"namespace not found for %s %s %s\", appId, clusterName, namespaceName));\n    return BeanUtils.transfrom(NamespaceDTO.class, namespace);\n  }\n\n  @RequestMapping(value = \"/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/associated-public-namespace\",\n      method = RequestMethod.GET)\n  public NamespaceDTO findPublicNamespaceForAssociatedNamespace(@PathVariable String appId,\n                                                                @PathVariable String clusterName,\n                                                                @PathVariable String namespaceName) {\n    Namespace namespace = namespaceService.findPublicNamespaceForAssociatedNamespace(clusterName, namespaceName);\n\n    if (namespace == null) {\n      throw new NotFoundException(String.format(\"public namespace not found. namespace:%s\", namespaceName));\n    }\n\n    return BeanUtils.transfrom(NamespaceDTO.class, namespace);\n  }\n\n  /**\n   * cluster -> cluster has not published namespaces?\n   */\n  @RequestMapping(value = \"/apps/{appId}/namespaces/publish_info\", method = RequestMethod.GET)\n  public Map<String, Boolean> namespacePublishInfo(@PathVariable String appId) {\n    return namespaceService.namespacePublishInfo(appId);\n  }\n\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/NamespaceLockController.java",
    "content": "package com.ctrip.framework.apollo.adminservice.controller;\n\nimport com.ctrip.framework.apollo.biz.config.BizConfig;\nimport com.ctrip.framework.apollo.biz.entity.Namespace;\nimport com.ctrip.framework.apollo.biz.entity.NamespaceLock;\nimport com.ctrip.framework.apollo.biz.service.NamespaceLockService;\nimport com.ctrip.framework.apollo.biz.service.NamespaceService;\nimport com.ctrip.framework.apollo.common.dto.NamespaceLockDTO;\nimport com.ctrip.framework.apollo.common.exception.BadRequestException;\nimport com.ctrip.framework.apollo.common.utils.BeanUtils;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RestController;\n\n@RestController\npublic class NamespaceLockController {\n\n\n  @Autowired\n  private NamespaceLockService namespaceLockService;\n  @Autowired\n  private NamespaceService namespaceService;\n  @Autowired\n  private BizConfig bizConfig;\n\n  @RequestMapping(value = \"/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/lock\", method = RequestMethod.GET)\n  public NamespaceLockDTO getNamespaceLockOwner(@PathVariable String appId, @PathVariable String clusterName,\n                                                @PathVariable String namespaceName) {\n    Namespace namespace = namespaceService.findOne(appId, clusterName, namespaceName);\n    if (namespace == null) {\n      throw new BadRequestException(\"namespace not exist.\");\n    }\n\n    if (bizConfig.isNamespaceLockSwitchOff()) {\n      return null;\n    }\n\n    NamespaceLock lock = namespaceLockService.findLock(namespace.getId());\n\n    if (lock == null) {\n      return null;\n    }\n\n    return BeanUtils.transfrom(NamespaceLockDTO.class, lock);\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/ReleaseController.java",
    "content": "package com.ctrip.framework.apollo.adminservice.controller;\n\n\nimport com.google.common.base.Splitter;\n\nimport com.ctrip.framework.apollo.biz.entity.Namespace;\nimport com.ctrip.framework.apollo.biz.entity.Release;\nimport com.ctrip.framework.apollo.biz.message.MessageSender;\nimport com.ctrip.framework.apollo.biz.message.Topics;\nimport com.ctrip.framework.apollo.biz.service.NamespaceBranchService;\nimport com.ctrip.framework.apollo.biz.service.NamespaceService;\nimport com.ctrip.framework.apollo.biz.service.ReleaseService;\nimport com.ctrip.framework.apollo.biz.utils.ReleaseMessageKeyGenerator;\nimport com.ctrip.framework.apollo.common.constants.NamespaceBranchStatus;\nimport com.ctrip.framework.apollo.common.dto.ItemChangeSets;\nimport com.ctrip.framework.apollo.common.dto.ReleaseDTO;\nimport com.ctrip.framework.apollo.common.exception.NotFoundException;\nimport com.ctrip.framework.apollo.common.utils.BeanUtils;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.data.domain.Pageable;\nimport org.springframework.transaction.annotation.Transactional;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.List;\nimport java.util.Set;\nimport java.util.stream.Collectors;\n\n@RestController\npublic class ReleaseController {\n\n  private static final Splitter RELEASES_SPLITTER = Splitter.on(\",\").omitEmptyStrings()\n      .trimResults();\n\n\n  @Autowired\n  private ReleaseService releaseService;\n  @Autowired\n  private NamespaceService namespaceService;\n  @Autowired\n  private MessageSender messageSender;\n  @Autowired\n  private NamespaceBranchService namespaceBranchService;\n\n\n  @RequestMapping(value = \"/releases/{releaseId}\", method = RequestMethod.GET)\n  public ReleaseDTO get(@PathVariable(\"releaseId\") long releaseId) {\n    Release release = releaseService.findOne(releaseId);\n    if (release == null) {\n      throw new NotFoundException(String.format(\"release not found for %s\", releaseId));\n    }\n    return BeanUtils.transfrom(ReleaseDTO.class, release);\n  }\n\n  @RequestMapping(value = \"/releases\", method = RequestMethod.GET)\n  public List<ReleaseDTO> findReleaseByIds(@RequestParam(\"releaseIds\") String releaseIds) {\n    Set<Long> releaseIdSet = RELEASES_SPLITTER.splitToList(releaseIds).stream().map(Long::parseLong)\n        .collect(Collectors.toSet());\n\n    List<Release> releases = releaseService.findByReleaseIds(releaseIdSet);\n\n    return BeanUtils.batchTransform(ReleaseDTO.class, releases);\n  }\n\n  @RequestMapping(value = \"/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases/all\", method = RequestMethod.GET)\n  public List<ReleaseDTO> findAllReleases(@PathVariable(\"appId\") String appId,\n                                          @PathVariable(\"clusterName\") String clusterName,\n                                          @PathVariable(\"namespaceName\") String namespaceName,\n                                          Pageable page) {\n    List<Release> releases = releaseService.findAllReleases(appId, clusterName, namespaceName, page);\n    return BeanUtils.batchTransform(ReleaseDTO.class, releases);\n  }\n\n\n  @RequestMapping(value = \"/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases/active\", method = RequestMethod.GET)\n  public List<ReleaseDTO> findActiveReleases(@PathVariable(\"appId\") String appId,\n                                             @PathVariable(\"clusterName\") String clusterName,\n                                             @PathVariable(\"namespaceName\") String namespaceName,\n                                             Pageable page) {\n    List<Release> releases = releaseService.findActiveReleases(appId, clusterName, namespaceName, page);\n    return BeanUtils.batchTransform(ReleaseDTO.class, releases);\n  }\n\n  @RequestMapping(value = \"/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases/latest\", method = RequestMethod.GET)\n  public ReleaseDTO getLatest(@PathVariable(\"appId\") String appId,\n                              @PathVariable(\"clusterName\") String clusterName,\n                              @PathVariable(\"namespaceName\") String namespaceName) {\n    Release release = releaseService.findLatestActiveRelease(appId, clusterName, namespaceName);\n    return BeanUtils.transfrom(ReleaseDTO.class, release);\n  }\n\n  @Transactional\n  @RequestMapping(path = \"/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases\", method = RequestMethod.POST)\n  public ReleaseDTO publish(@PathVariable(\"appId\") String appId,\n                            @PathVariable(\"clusterName\") String clusterName,\n                            @PathVariable(\"namespaceName\") String namespaceName,\n                            @RequestParam(\"name\") String releaseName,\n                            @RequestParam(name = \"comment\", required = false) String releaseComment,\n                            @RequestParam(\"operator\") String operator,\n                            @RequestParam(name = \"isEmergencyPublish\", defaultValue = \"false\") boolean isEmergencyPublish) {\n    Namespace namespace = namespaceService.findOne(appId, clusterName, namespaceName);\n    if (namespace == null) {\n      throw new NotFoundException(String.format(\"Could not find namespace for %s %s %s\", appId,\n                                                clusterName, namespaceName));\n    }\n    Release release = releaseService.publish(namespace, releaseName, releaseComment, operator, isEmergencyPublish);\n\n    //send release message\n    Namespace parentNamespace = namespaceService.findParentNamespace(namespace);\n    String messageCluster;\n    if (parentNamespace != null) {\n      messageCluster = parentNamespace.getClusterName();\n    } else {\n      messageCluster = clusterName;\n    }\n    messageSender.sendMessage(ReleaseMessageKeyGenerator.generate(appId, messageCluster, namespaceName),\n                              Topics.APOLLO_RELEASE_TOPIC);\n    return BeanUtils.transfrom(ReleaseDTO.class, release);\n  }\n\n\n  /**\n   * merge branch items to master and publish master\n   *\n   * @return published result\n   */\n  @Transactional\n  @RequestMapping(path = \"/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/updateAndPublish\", method = RequestMethod.POST)\n  public ReleaseDTO updateAndPublish(@PathVariable(\"appId\") String appId,\n                                     @PathVariable(\"clusterName\") String clusterName,\n                                     @PathVariable(\"namespaceName\") String namespaceName,\n                                     @RequestParam(\"releaseName\") String releaseName,\n                                     @RequestParam(\"branchName\") String branchName,\n                                     @RequestParam(value = \"deleteBranch\", defaultValue = \"true\") boolean deleteBranch,\n                                     @RequestParam(name = \"releaseComment\", required = false) String releaseComment,\n                                     @RequestParam(name = \"isEmergencyPublish\", defaultValue = \"false\") boolean isEmergencyPublish,\n                                     @RequestBody ItemChangeSets changeSets) {\n    Namespace namespace = namespaceService.findOne(appId, clusterName, namespaceName);\n    if (namespace == null) {\n      throw new NotFoundException(String.format(\"Could not find namespace for %s %s %s\", appId,\n                                                clusterName, namespaceName));\n    }\n\n    Release release = releaseService.mergeBranchChangeSetsAndRelease(namespace, branchName, releaseName,\n                                                                     releaseComment, isEmergencyPublish, changeSets);\n\n    if (deleteBranch) {\n      namespaceBranchService.deleteBranch(appId, clusterName, namespaceName, branchName,\n                                          NamespaceBranchStatus.MERGED, changeSets.getDataChangeLastModifiedBy());\n    }\n\n    messageSender.sendMessage(ReleaseMessageKeyGenerator.generate(appId, clusterName, namespaceName),\n                              Topics.APOLLO_RELEASE_TOPIC);\n\n    return BeanUtils.transfrom(ReleaseDTO.class, release);\n\n  }\n\n  @Transactional\n  @RequestMapping(path = \"/releases/{releaseId}/rollback\", method = RequestMethod.PUT)\n  public void rollback(@PathVariable(\"releaseId\") long releaseId,\n                       @RequestParam(\"operator\") String operator) {\n\n    Release release = releaseService.rollback(releaseId, operator);\n\n    String appId = release.getAppId();\n    String clusterName = release.getClusterName();\n    String namespaceName = release.getNamespaceName();\n    //send release message\n    messageSender.sendMessage(ReleaseMessageKeyGenerator.generate(appId, clusterName, namespaceName),\n                              Topics.APOLLO_RELEASE_TOPIC);\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/ReleaseHistoryController.java",
    "content": "package com.ctrip.framework.apollo.adminservice.controller;\n\nimport com.google.gson.Gson;\nimport com.google.gson.reflect.TypeToken;\n\nimport com.ctrip.framework.apollo.biz.entity.ReleaseHistory;\nimport com.ctrip.framework.apollo.biz.service.ReleaseHistoryService;\nimport com.ctrip.framework.apollo.common.dto.PageDTO;\nimport com.ctrip.framework.apollo.common.dto.ReleaseHistoryDTO;\nimport com.ctrip.framework.apollo.common.utils.BeanUtils;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.data.domain.Page;\nimport org.springframework.data.domain.Pageable;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.lang.reflect.Type;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@RestController\npublic class ReleaseHistoryController {\n\n  private Gson gson = new Gson();\n  private Type configurationTypeReference = new TypeToken<Map<String, Object>>() {\n  }.getType();\n\n  @Autowired\n  private ReleaseHistoryService releaseHistoryService;\n\n  @RequestMapping(value = \"/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases/histories\",\n      method = RequestMethod.GET)\n  public PageDTO<ReleaseHistoryDTO> findReleaseHistoriesByNamespace(\n      @PathVariable String appId, @PathVariable String clusterName,\n      @PathVariable String namespaceName,\n      Pageable pageable) {\n\n    Page<ReleaseHistory> result = releaseHistoryService.findReleaseHistoriesByNamespace(appId, clusterName,\n                                                                                        namespaceName, pageable);\n    return transform2PageDTO(result, pageable);\n  }\n\n\n  @RequestMapping(value = \"/releases/histories/by_release_id_and_operation\", method = RequestMethod.GET)\n  public PageDTO<ReleaseHistoryDTO> findReleaseHistoryByReleaseIdAndOperation(\n      @RequestParam(\"releaseId\") long releaseId,\n      @RequestParam(\"operation\") int operation,\n      Pageable pageable) {\n\n    Page<ReleaseHistory> result = releaseHistoryService.findByReleaseIdAndOperation(releaseId, operation, pageable);\n\n    return transform2PageDTO(result, pageable);\n  }\n\n  @RequestMapping(value = \"/releases/histories/by_previous_release_id_and_operation\", method = RequestMethod.GET)\n  public PageDTO<ReleaseHistoryDTO> findReleaseHistoryByPreviousReleaseIdAndOperation(\n      @RequestParam(\"previousReleaseId\") long previousReleaseId,\n      @RequestParam(\"operation\") int operation,\n      Pageable pageable) {\n\n    Page<ReleaseHistory> result = releaseHistoryService.findByPreviousReleaseIdAndOperation(previousReleaseId, operation, pageable);\n\n    return transform2PageDTO(result, pageable);\n\n  }\n\n  private PageDTO<ReleaseHistoryDTO> transform2PageDTO(Page<ReleaseHistory> releaseHistoriesPage, Pageable pageable){\n    if (!releaseHistoriesPage.hasContent()) {\n      return null;\n    }\n\n    List<ReleaseHistory> releaseHistories = releaseHistoriesPage.getContent();\n    List<ReleaseHistoryDTO> releaseHistoryDTOs = new ArrayList<>(releaseHistories.size());\n    for (ReleaseHistory releaseHistory : releaseHistories) {\n      releaseHistoryDTOs.add(transformReleaseHistory2DTO(releaseHistory));\n    }\n\n    return new PageDTO<>(releaseHistoryDTOs, pageable, releaseHistoriesPage.getTotalElements());\n  }\n\n  private ReleaseHistoryDTO transformReleaseHistory2DTO(ReleaseHistory releaseHistory) {\n    ReleaseHistoryDTO dto = new ReleaseHistoryDTO();\n    BeanUtils.copyProperties(releaseHistory, dto, \"operationContext\");\n    dto.setOperationContext(gson.fromJson(releaseHistory.getOperationContext(),\n                                          configurationTypeReference));\n\n    return dto;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-adminservice/src/main/resources/META-INF/app.properties",
    "content": "app.id=100003172\njdkVersion=1.8\n"
  },
  {
    "path": "open-config-center/apollo/apollo-adminservice/src/main/resources/adminservice.properties",
    "content": "#Used for apollo-assembly\nspring.application.name= apollo-adminservice\nctrip.appid= 100003172\nserver.port= 8090\n#logging.file= /opt/logs/100003172/apollo-adminservice.log\n\n\napollo_profile=github\nspring.datasource.url=jdbc:mysql://47.94.252.160:3306/ApolloConfigDB?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false\nspring.datasource.username=root\nspring.datasource.password=root\n\n#spring.jpa.properties.hibernate.show_sql=true\nspring.jpa.hibernate.naming_strategy=org.hibernate.cfg.EJB3NamingStrategy\nspring.jpa.properties.hibernate.dialect= org.hibernate.dialect.MySQL5Dialect"
  },
  {
    "path": "open-config-center/apollo/apollo-adminservice/src/main/resources/application.yml",
    "content": "spring:\n  application:\n    name: apollo-adminservice\n  profiles:\n    active: ${apollo_profile}\n\nctrip:\n  appid: 100003172\n  \nserver:\n  port: 8090\n  \nlogging:\n  level:\n    com.ctrip: INFO  \n"
  },
  {
    "path": "open-config-center/apollo/apollo-adminservice/src/main/resources/bootstrap.yml",
    "content": "eureka:\n  instance:\n    hostname: ${spring.cloud.client.ipAddress}\n    preferIpAddress: true\n  client:\n    serviceUrl:\n      defaultZone: http://${eureka.instance.hostname}:8080/eureka/\n    healthcheck:\n      enabled: true\n    eurekaServiceUrlPollIntervalSeconds: 60\n\nendpoints:\n  health:\n    sensitive: false\n\n\n\nmanagement:\n  security:\n    enabled: false\n  health:\n    status:\n      order: DOWN, OUT_OF_SERVICE, UNKNOWN, UP \n"
  },
  {
    "path": "open-config-center/apollo/apollo-adminservice/src/main/resources/logback.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<configuration>\n\t<include resource=\"org/springframework/boot/logging/logback/defaults.xml\" />\n\t<property name=\"LOG_FILE\"\n\t\tvalue=\"${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}/}apollo-adminservice.log}\" />\n\t<include resource=\"org/springframework/boot/logging/logback/file-appender.xml\" />\n\t<include resource=\"org/springframework/boot/logging/logback/console-appender.xml\" />\n\t<root level=\"INFO\">\n\t\t<appender-ref ref=\"FILE\" />\n\t\t<appender-ref ref=\"CONSOLE\" />\n\t</root>\n</configuration>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-adminservice/src/main/scripts/shutdown.sh",
    "content": "#!/bin/bash\nSERVICE_NAME=apollo-adminservice\n\nif [[ -z \"$JAVA_HOME\" && -d /usr/java/latest/ ]]; then\n    export JAVA_HOME=/usr/java/latest/\nfi\n\ncd `dirname $0`/..\n\nif [[ ! -f $SERVICE_NAME\".jar\" && -d current ]]; then\n    cd current\nfi\n\nif [[ -f $SERVICE_NAME\".jar\" ]]; then\n  chmod a+x $SERVICE_NAME\".jar\"\n  ./$SERVICE_NAME\".jar\" stop\nfi\n"
  },
  {
    "path": "open-config-center/apollo/apollo-adminservice/src/main/scripts/startup.sh",
    "content": "#!/bin/bash\nSERVICE_NAME=apollo-adminservice\n## Adjust log dir if necessary\nLOG_DIR=/opt/logs/100003172\n## Adjust server port if necessary\nSERVER_PORT=8090\n\n## Adjust memory settings if necessary\n#export JAVA_OPTS=\"-Xms2560m -Xmx2560m -Xss256k -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=384m -XX:NewSize=1536m -XX:MaxNewSize=1536m -XX:SurvivorRatio=8\"\n\n## Only uncomment the following when you are using server jvm\n#export JAVA_OPTS=\"$JAVA_OPTS -server -XX:-ReduceInitialCardMarks\"\n\n########### The following is the same for configservice, adminservice, portal ###########\nexport JAVA_OPTS=\"$JAVA_OPTS -XX:+UseParNewGC -XX:ParallelGCThreads=4 -XX:MaxTenuringThreshold=9 -XX:+UseConcMarkSweepGC -XX:+DisableExplicitGC -XX:+UseCMSInitiatingOccupancyOnly -XX:+ScavengeBeforeFullGC -XX:+UseCMSCompactAtFullCollection -XX:+CMSParallelRemarkEnabled -XX:CMSFullGCsBeforeCompaction=9 -XX:CMSInitiatingOccupancyFraction=60 -XX:+CMSClassUnloadingEnabled -XX:SoftRefLRUPolicyMSPerMB=0 -XX:+CMSPermGenSweepingEnabled -XX:CMSInitiatingPermOccupancyFraction=70 -XX:+ExplicitGCInvokesConcurrent -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCApplicationConcurrentTime -XX:+PrintHeapAtGC -XX:+HeapDumpOnOutOfMemoryError -XX:-OmitStackTraceInFastThrow -Duser.timezone=Asia/Shanghai -Dclient.encoding.override=UTF-8 -Dfile.encoding=UTF-8 -Djava.security.egd=file:/dev/./urandom\"\nexport JAVA_OPTS=\"$JAVA_OPTS -Dserver.port=$SERVER_PORT -Dlogging.file=$LOG_DIR/$SERVICE_NAME.log -Xloggc:$LOG_DIR/heap_trace.txt -XX:HeapDumpPath=$LOG_DIR/HeapDumpOnOutOfMemoryError/\"\n\nPATH_TO_JAR=$SERVICE_NAME\".jar\"\nSERVER_URL=\"http://localhost:$SERVER_PORT\"\n\nfunction checkPidAlive {\n    for i in `ls -t $SERVICE_NAME*.pid 2>/dev/null`\n    do\n        read pid < $i\n\n        result=$(ps -p \"$pid\")\n        if [ \"$?\" -eq 0 ]; then\n            return 0\n        else\n            printf \"\\npid - $pid just quit unexpectedly, please check logs under $LOG_DIR and /tmp for more information!\\n\"\n            exit 1;\n        fi\n    done\n\n    printf \"\\nNo pid file found, startup may failed. Please check logs under $LOG_DIR and /tmp for more information!\\n\"\n    exit 1;\n}\n\nif [ \"$(uname)\" == \"Darwin\" ]; then\n    windows=\"0\"\nelif [ \"$(expr substr $(uname -s) 1 5)\" == \"Linux\" ]; then\n    windows=\"0\"\nelif [ \"$(expr substr $(uname -s) 1 5)\" == \"MINGW\" ]; then\n    windows=\"1\"\nelse\n    windows=\"0\"\nfi\n\n# for Windows\nif [ \"$windows\" == \"1\" ] && [[ -n \"$JAVA_HOME\" ]] && [[ -x \"$JAVA_HOME/bin/java\" ]]; then\n    tmp_java_home=`cygpath -sw \"$JAVA_HOME\"`\n    export JAVA_HOME=`cygpath -u $tmp_java_home`\n    echo \"Windows new JAVA_HOME is: $JAVA_HOME\"\nfi\n\ncd `dirname $0`/..\n\nfor i in `ls $SERVICE_NAME-*.jar 2>/dev/null`\ndo\n    if [[ ! $i == *\"-sources.jar\" ]]\n    then\n        PATH_TO_JAR=$i\n        break\n    fi\ndone\n\nif [[ ! -f PATH_TO_JAR && -d current ]]; then\n    cd current\n    for i in `ls $SERVICE_NAME-*.jar 2>/dev/null`\n    do\n        if [[ ! $i == *\"-sources.jar\" ]]\n        then\n            PATH_TO_JAR=$i\n            break\n        fi\n    done\nfi\n\nif [[ -f $SERVICE_NAME\".jar\" ]]; then\n  rm -rf $SERVICE_NAME\".jar\"\nfi\n\nprintf \"$(date) ==== Starting ==== \\n\"\n\nln $PATH_TO_JAR $SERVICE_NAME\".jar\"\nchmod a+x $SERVICE_NAME\".jar\"\n./$SERVICE_NAME\".jar\" start\n\nrc=$?;\n\nif [[ $rc != 0 ]];\nthen\n    echo \"$(date) Failed to start $SERVICE_NAME.jar, return code: $rc\"\n    exit $rc;\nfi\n\ndeclare -i counter=0\ndeclare -i max_counter=48 # 48*5=240s\ndeclare -i total_time=0\n\nprintf \"Waiting for server startup\"\nuntil [[ (( counter -ge max_counter )) || \"$(curl -X GET --silent --connect-timeout 1 --max-time 2 --head $SERVER_URL | grep \"Coyote\")\" != \"\" ]];\ndo\n    printf \".\"\n    counter+=1\n    sleep 5\n\n    checkPidAlive\ndone\n\ntotal_time=counter*5\n\nif [[ (( counter -ge max_counter )) ]];\nthen\n    printf \"\\n$(date) Server failed to start in $total_time seconds!\\n\"\n    exit 1;\nfi\n\nprintf \"\\n$(date) Server started in $total_time seconds!\\n\"\n\nexit 0;\n"
  },
  {
    "path": "open-config-center/apollo/apollo-adminservice/src/test/resources/application.properties",
    "content": "spring.datasource.url = jdbc:h2:mem:~/apolloconfigdb;mode=mysql;DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=-1\nspring.jpa.hibernate.naming_strategy=org.hibernate.cfg.EJB3NamingStrategy\nspring.jpa.properties.hibernate.show_sql=true\nspring.h2.console.enabled = true\nspring.h2.console.settings.web-allow-others=true\n\n"
  },
  {
    "path": "open-config-center/apollo/apollo-adminservice/src/test/resources/application.yml",
    "content": "spring:\n  application:\n    name: apollo-adminservice\n    \nserver:\n  port: ${port:8090}\n  \nlogging:\n  level:\n    org.springframework.cloud: 'DEBUG'\n  file: /opt/logs/${ctrip.appid}/apollo-adminservice.log\n\nctrip:\n  appid: 100003172\n"
  },
  {
    "path": "open-config-center/apollo/apollo-adminservice/src/test/resources/bootstrap.yml",
    "content": "eureka:\n  instance:\n    hostname: ${hostname:localhost}\n  client:\n    serviceUrl:\n      defaultZone: http://${eureka.instance.hostname}:8090/eureka/\n    healthcheck:\n      enabled: true\n      \n\nendpoints:\n  health:\n    sensitive: false\n\nmanagement:\n  security:\n    enabled: false\n  health:\n    status:\n      order: DOWN, OUT_OF_SERVICE, UNKNOWN, UP \n"
  },
  {
    "path": "open-config-center/apollo/apollo-adminservice/src/test/resources/controller/cleanup.sql",
    "content": "DELETE FROM Item;\nDELETE FROM Namespace;\nDELETE FROM AppNamespace;\nDELETE FROM Cluster;\nDELETE FROM App;\nDELETE FROM NamespaceLock;\nDELETE FROM ServerConfig;\n\n"
  },
  {
    "path": "open-config-center/apollo/apollo-adminservice/src/test/resources/controller/test-itemset.sql",
    "content": "INSERT INTO App (AppId, Name, OwnerName, OwnerEmail) VALUES ('someAppId','someAppName','someOwnerName','someOwnerName@ctrip.com');\n\nINSERT INTO Cluster (AppId, Name) VALUES ('someAppId', 'default');\n\nINSERT INTO AppNamespace (AppId, Name) VALUES ('someAppId', 'application');\n\nINSERT INTO Namespace (AppId, ClusterName, NamespaceName) VALUES ('someAppId', 'default', 'application');\n"
  },
  {
    "path": "open-config-center/apollo/apollo-adminservice/src/test/resources/controller/test-release.sql",
    "content": "INSERT INTO App (AppId, Name, OwnerName, OwnerEmail) VALUES ('someAppId','someAppName','someOwnerName','someOwnerName@ctrip.com');\n\nINSERT INTO Cluster (AppId, Name) VALUES ('someAppId', 'default');\n\nINSERT INTO AppNamespace (AppId, Name) VALUES ('someAppId', 'application');\n\nINSERT INTO Namespace (Id, AppId, ClusterName, NamespaceName) VALUES (100, 'someAppId', 'default', 'application');\n\nINSERT INTO Item (NamespaceId, `Key`, Value, Comment) VALUES (100, 'k1', 'v1', 'comment1');\nINSERT INTO Item (NamespaceId, `Key`, Value, Comment) VALUES (100, 'k2', 'v2', 'comment1');\nINSERT INTO Item (NamespaceId, `Key`, Value, Comment) VALUES (100, 'k3', 'v3', 'comment1');"
  },
  {
    "path": "open-config-center/apollo/apollo-adminservice/src/test/resources/data.sql",
    "content": "INSERT INTO App (AppId, Name, OwnerName, OwnerEmail) VALUES ('100003171','apollo-config-service','刘一鸣','liuym@ctrip.com');\nINSERT INTO App (AppId, Name, OwnerName, OwnerEmail) VALUES ('100003172','apollo-admin-service','宋顺','song_s@ctrip.com');\nINSERT INTO App (AppId, Name, OwnerName, OwnerEmail) VALUES ('100003173','apollo-portal','张乐','zhanglea@ctrip.com');\nINSERT INTO App (AppId, Name, OwnerName, OwnerEmail) VALUES ('fxhermesproducer','fx-hermes-producer','梁锦华','jhliang@ctrip.com');\n\nINSERT INTO Cluster (AppId, Name) VALUES ('100003171', 'default');\nINSERT INTO Cluster (AppId, Name) VALUES ('100003171', 'cluster1');\nINSERT INTO Cluster (AppId, Name) VALUES ('100003172', 'default');\nINSERT INTO Cluster (AppId, Name) VALUES ('100003172', 'cluster2');\nINSERT INTO Cluster (AppId, Name) VALUES ('100003173', 'default');\nINSERT INTO Cluster (AppId, Name) VALUES ('100003173', 'cluster3');\nINSERT INTO Cluster (AppId, Name) VALUES ('fxhermesproducer', 'default');\n\nINSERT INTO AppNamespace (AppId, Name) VALUES ('100003171', 'application');\nINSERT INTO AppNamespace (AppId, Name) VALUES ('100003171', 'fx.apollo.config');\nINSERT INTO AppNamespace (AppId, Name) VALUES ('100003172', 'application');\nINSERT INTO AppNamespace (AppId, Name) VALUES ('100003172', 'fx.apollo.admin');\nINSERT INTO AppNamespace (AppId, Name) VALUES ('100003173', 'application');\nINSERT INTO AppNamespace (AppId, Name) VALUES ('100003173', 'fx.apollo.portal');\nINSERT INTO AppNamespace (AppID, Name) VALUES ('fxhermesproducer', 'fx.hermes.producer');\n\nINSERT INTO Namespace (Id, AppId, ClusterName, NamespaceName) VALUES (1, '100003171', 'default', 'application');\nINSERT INTO Namespace (Id, AppId, ClusterName, NamespaceName) VALUES (5, '100003171', 'cluster1', 'application');\nINSERT INTO Namespace (Id, AppId, ClusterName, NamespaceName) VALUES (2, 'fxhermesproducer', 'default', 'fx.hermes.producer');\nINSERT INTO Namespace (Id, AppId, ClusterName, NamespaceName) VALUES (3, '100003172', 'default', 'application');\nINSERT INTO Namespace (Id, AppId, ClusterName, NamespaceName) VALUES (4, '100003173', 'default', 'application');\n\nINSERT INTO Item (NamespaceId, `Key`, Value, Comment) VALUES (1, 'k1', 'v1', 'comment1');\nINSERT INTO Item (NamespaceId, `Key`, Value, Comment) VALUES (1, 'k2', 'v2', 'comment2');\nINSERT INTO Item (NamespaceId, `Key`, Value, Comment) VALUES (2, 'k3', 'v3', 'comment3');\nINSERT INTO Item (NamespaceId, `Key`, Value, Comment, LineNum) VALUES (5, 'k1', 'v4', 'comment4',1);\n\nINSERT INTO RELEASE (ReleaseKey, Name, Comment, AppId, ClusterName, NamespaceName, Configurations) VALUES ('TEST-RELEASE-KEY', 'REV1','First Release','100003171', 'default', 'application', '{\"k1\":\"v1\"}');\n\n"
  },
  {
    "path": "open-config-center/apollo/apollo-adminservice/src/test/resources/logback-test.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<configuration scan=\"true\">\n\t<appender name=\"CONSOLE\" class=\"ch.qos.logback.core.ConsoleAppender\">\n\t\t<encoder>\n\t\t\t<charset>utf-8</charset>\n\t\t\t<Pattern>[%p] %c - %m%n</Pattern>\n\t\t</encoder>\n\t</appender>\n\t<logger name=\"org.springframework.test\" level=\"OFF\" />\n\n\t<root level=\"INFO\">\n\t\t<appender-ref ref=\"CONSOLE\" />\n\t</root>\n\n</configuration>"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/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\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<parent>\n\t\t<groupId>com.ctrip.framework.apollo</groupId>\n\t\t<artifactId>apollo</artifactId>\n\t\t<version>0.10.0-SNAPSHOT</version>\n\t</parent>\n\t<modelVersion>4.0.0</modelVersion>\n\t<artifactId>apollo-biz</artifactId>\n\t<name>Apollo Biz</name>\n\t<packaging>jar</packaging>\n\t<properties>\n\t\t<github.path>${project.artifactId}</github.path>\n\t</properties>\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>com.ctrip.framework.apollo</groupId>\n\t\t\t<artifactId>apollo-common</artifactId>\n\t\t</dependency>\n\t\t<!-- eureka -->\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-eureka</artifactId>\n\t\t</dependency>\n\t\t<!-- end of eureka -->\n\t\t<dependency>\n\t\t\t<groupId>com.h2database</groupId>\n\t\t\t<artifactId>h2</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n</project>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/ApolloBizConfig.java",
    "content": "package com.ctrip.framework.apollo.biz;\n\nimport org.springframework.boot.autoconfigure.EnableAutoConfiguration;\nimport org.springframework.context.annotation.ComponentScan;\nimport org.springframework.context.annotation.Configuration;\n\n@EnableAutoConfiguration\n@Configuration\n@ComponentScan(basePackageClasses = ApolloBizConfig.class)\npublic class ApolloBizConfig {\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/auth/WebSecurityConfig.java",
    "content": "package com.ctrip.framework.apollo.biz.auth;\n\nimport com.ctrip.framework.apollo.common.condition.ConditionalOnMissingProfile;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;\nimport org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;\nimport org.springframework.security.config.annotation.web.builders.HttpSecurity;\nimport org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;\nimport org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;\n\n@ConditionalOnMissingProfile(\"auth\")\n@Configuration\n@EnableWebSecurity\n@EnableGlobalMethodSecurity(prePostEnabled = true)\npublic class WebSecurityConfig extends WebSecurityConfigurerAdapter {\n\n  @Override\n  protected void configure(HttpSecurity http) throws Exception {\n    http.httpBasic();\n    http.csrf().disable();\n    http.headers().frameOptions().sameOrigin();\n  }\n\n  /**\n   * Although the authentication below is useless, we may not remove them for backward compatibility.\n   * Because if we remove them and the old clients(before 0.9.0) still send the authentication\n   * information, the server will return 401, which should cause big problems.\n   *\n   * We may remove the following once we remove spring security from Apollo.\n   */\n  @Autowired\n  public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {\n    auth.inMemoryAuthentication().withUser(\"user\").password(\"\").roles(\"USER\").and()\n        .withUser(\"apollo\").password(\"\").roles(\"USER\", \"ADMIN\");\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/config/BizConfig.java",
    "content": "package com.ctrip.framework.apollo.biz.config;\n\nimport com.google.common.base.Strings;\nimport com.google.common.collect.Maps;\nimport com.google.gson.Gson;\nimport com.google.gson.reflect.TypeToken;\n\nimport com.ctrip.framework.apollo.biz.service.BizDBPropertySource;\nimport com.ctrip.framework.apollo.common.config.RefreshableConfig;\nimport com.ctrip.framework.apollo.common.config.RefreshablePropertySource;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport java.lang.reflect.Type;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.TimeUnit;\n\n@Component\npublic class BizConfig extends RefreshableConfig {\n\n  private static final int DEFAULT_ITEM_KEY_LENGTH = 128;\n  private static final int DEFAULT_ITEM_VALUE_LENGTH = 20000;\n  private static final int DEFAULT_APPNAMESPACE_CACHE_REBUILD_INTERVAL = 60; //60s\n  private static final int DEFAULT_GRAY_RELEASE_RULE_SCAN_INTERVAL = 60; //60s\n  private static final int DEFAULT_APPNAMESPACE_CACHE_SCAN_INTERVAL = 1; //1s\n  private static final int DEFAULT_RELEASE_MESSAGE_CACHE_SCAN_INTERVAL = 1; //1s\n  private static final int DEFAULT_RELEASE_MESSAGE_SCAN_INTERVAL_IN_MS = 1000; //1000ms\n  private static final int DEFAULT_RELEASE_MESSAGE_NOTIFICATION_BATCH = 100;\n  private static final int DEFAULT_RELEASE_MESSAGE_NOTIFICATION_BATCH_INTERVAL_IN_MILLI = 100;//100ms\n\n  private Gson gson = new Gson();\n  private static final Type namespaceValueLengthOverrideTypeReference =\n      new TypeToken<Map<Long, Integer>>() {\n      }.getType();\n\n  @Autowired\n  private BizDBPropertySource propertySource;\n\n  @Override\n  protected List<RefreshablePropertySource> getRefreshablePropertySources() {\n    return Collections.singletonList(propertySource);\n  }\n\n  public List<String> eurekaServiceUrls() {\n    String configuration = getValue(\"eureka.service.url\", \"\");\n    if (Strings.isNullOrEmpty(configuration)) {\n      return Collections.emptyList();\n    }\n\n    return splitter.splitToList(configuration);\n  }\n\n  public int grayReleaseRuleScanInterval() {\n    int interval = getIntProperty(\"apollo.gray-release-rule-scan.interval\", DEFAULT_GRAY_RELEASE_RULE_SCAN_INTERVAL);\n    return checkInt(interval, 1, Integer.MAX_VALUE, DEFAULT_GRAY_RELEASE_RULE_SCAN_INTERVAL);\n  }\n\n  public int itemKeyLengthLimit() {\n    int limit = getIntProperty(\"item.key.length.limit\", DEFAULT_ITEM_KEY_LENGTH);\n    return checkInt(limit, 5, Integer.MAX_VALUE, DEFAULT_ITEM_KEY_LENGTH);\n  }\n\n  public int itemValueLengthLimit() {\n    int limit = getIntProperty(\"item.value.length.limit\", DEFAULT_ITEM_VALUE_LENGTH);\n    return checkInt(limit, 5, Integer.MAX_VALUE, DEFAULT_ITEM_VALUE_LENGTH);\n  }\n\n  public Map<Long, Integer> namespaceValueLengthLimitOverride() {\n    String namespaceValueLengthOverrideString = getValue(\"namespace.value.length.limit.override\");\n    Map<Long, Integer> namespaceValueLengthOverride = Maps.newHashMap();\n    if (!Strings.isNullOrEmpty(namespaceValueLengthOverrideString)) {\n      namespaceValueLengthOverride =\n          gson.fromJson(namespaceValueLengthOverrideString, namespaceValueLengthOverrideTypeReference);\n    }\n\n    return namespaceValueLengthOverride;\n  }\n\n  public boolean isNamespaceLockSwitchOff() {\n    return !getBooleanProperty(\"namespace.lock.switch\", false);\n  }\n\n  /**\n   * ctrip config\n   **/\n  public String cloggingUrl() {\n    return getValue(\"clogging.server.url\");\n  }\n\n  public String cloggingPort() {\n    return getValue(\"clogging.server.port\");\n  }\n\n  public int appNamespaceCacheScanInterval() {\n    int interval = getIntProperty(\"apollo.app-namespace-cache-scan.interval\", DEFAULT_APPNAMESPACE_CACHE_SCAN_INTERVAL);\n    return checkInt(interval, 1, Integer.MAX_VALUE, DEFAULT_APPNAMESPACE_CACHE_SCAN_INTERVAL);\n  }\n\n  public TimeUnit appNamespaceCacheScanIntervalTimeUnit() {\n    return TimeUnit.SECONDS;\n  }\n\n  public int appNamespaceCacheRebuildInterval() {\n    int interval = getIntProperty(\"apollo.app-namespace-cache-rebuild.interval\", DEFAULT_APPNAMESPACE_CACHE_REBUILD_INTERVAL);\n    return checkInt(interval, 1, Integer.MAX_VALUE, DEFAULT_APPNAMESPACE_CACHE_REBUILD_INTERVAL);\n  }\n\n  public TimeUnit appNamespaceCacheRebuildIntervalTimeUnit() {\n    return TimeUnit.SECONDS;\n  }\n\n  public int releaseMessageCacheScanInterval() {\n    int interval = getIntProperty(\"apollo.release-message-cache-scan.interval\", DEFAULT_RELEASE_MESSAGE_CACHE_SCAN_INTERVAL);\n    return checkInt(interval, 1, Integer.MAX_VALUE, DEFAULT_RELEASE_MESSAGE_CACHE_SCAN_INTERVAL);\n  }\n\n  public TimeUnit releaseMessageCacheScanIntervalTimeUnit() {\n    return TimeUnit.SECONDS;\n  }\n\n  public int releaseMessageScanIntervalInMilli() {\n    int interval = getIntProperty(\"apollo.message-scan.interval\", DEFAULT_RELEASE_MESSAGE_SCAN_INTERVAL_IN_MS);\n    return checkInt(interval, 100, Integer.MAX_VALUE, DEFAULT_RELEASE_MESSAGE_SCAN_INTERVAL_IN_MS);\n  }\n\n  public int releaseMessageNotificationBatch() {\n    int batch = getIntProperty(\"apollo.release-message.notification.batch\", DEFAULT_RELEASE_MESSAGE_NOTIFICATION_BATCH);\n    return checkInt(batch, 1, Integer.MAX_VALUE, DEFAULT_RELEASE_MESSAGE_NOTIFICATION_BATCH);\n  }\n\n  public int releaseMessageNotificationBatchIntervalInMilli() {\n    int interval = getIntProperty(\"apollo.release-message.notification.batch.interval\", DEFAULT_RELEASE_MESSAGE_NOTIFICATION_BATCH_INTERVAL_IN_MILLI);\n    return checkInt(interval, 10, Integer.MAX_VALUE, DEFAULT_RELEASE_MESSAGE_NOTIFICATION_BATCH_INTERVAL_IN_MILLI);\n  }\n\n  public boolean isConfigServiceCacheEnabled() {\n    return getBooleanProperty(\"config-service.cache.enabled\", false);\n  }\n\n  int checkInt(int value, int min, int max, int defaultValue) {\n    if (value >= min && value <= max) {\n      return value;\n    }\n    return defaultValue;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/customize/BizLoggingCustomizer.java",
    "content": "package com.ctrip.framework.apollo.biz.customize;\n\nimport com.ctrip.framework.apollo.biz.config.BizConfig;\nimport com.ctrip.framework.apollo.common.customize.LoggingCustomizer;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.annotation.Profile;\nimport org.springframework.stereotype.Component;\n\n@Component\n@Profile(\"ctrip\")\npublic class BizLoggingCustomizer extends LoggingCustomizer{\n\n\n  @Autowired\n  private BizConfig bizConfig;\n\n\n  @Override\n  protected String cloggingUrl() {\n    return bizConfig.cloggingUrl();\n  }\n\n  @Override\n  protected String cloggingPort() {\n    return bizConfig.cloggingPort();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/customize/package-info.java",
    "content": "/**\n * 携程内部的日志系统,第三方公司可删除\n */\npackage com.ctrip.framework.apollo.biz.customize;\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/entity/Audit.java",
    "content": "package com.ctrip.framework.apollo.biz.entity;\n\nimport com.ctrip.framework.apollo.common.entity.BaseEntity;\n\nimport org.hibernate.annotations.SQLDelete;\nimport org.hibernate.annotations.Where;\n\nimport javax.persistence.Column;\nimport javax.persistence.Entity;\nimport javax.persistence.Table;\n\n@Entity\n@Table(name = \"Audit\")\n@SQLDelete(sql = \"Update Audit set isDeleted = 1 where id = ?\")\n@Where(clause = \"isDeleted = 0\")\npublic class Audit extends BaseEntity {\n\n  public enum OP {\n    INSERT, UPDATE, DELETE\n  }\n\n  @Column(name = \"EntityName\", nullable = false)\n  private String entityName;\n\n  @Column(name = \"EntityId\")\n  private Long entityId;\n\n  @Column(name = \"OpName\", nullable = false)\n  private String opName;\n\n  @Column(name = \"Comment\")\n  private String comment;\n\n  public String getComment() {\n    return comment;\n  }\n\n  public Long getEntityId() {\n    return entityId;\n  }\n\n  public String getEntityName() {\n    return entityName;\n  }\n\n  public String getOpName() {\n    return opName;\n  }\n\n  public void setComment(String comment) {\n    this.comment = comment;\n  }\n\n  public void setEntityId(Long entityId) {\n    this.entityId = entityId;\n  }\n\n  public void setEntityName(String entityName) {\n    this.entityName = entityName;\n  }\n\n  public void setOpName(String opName) {\n    this.opName = opName;\n  }\n\n  public String toString() {\n    return toStringHelper().add(\"entityName\", entityName).add(\"entityId\", entityId)\n        .add(\"opName\", opName).add(\"comment\", comment).toString();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/entity/Cluster.java",
    "content": "package com.ctrip.framework.apollo.biz.entity;\n\nimport com.ctrip.framework.apollo.common.entity.BaseEntity;\n\nimport org.hibernate.annotations.SQLDelete;\nimport org.hibernate.annotations.Where;\n\nimport javax.persistence.Column;\nimport javax.persistence.Entity;\nimport javax.persistence.Table;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@Entity\n@Table(name = \"Cluster\")\n@SQLDelete(sql = \"Update Cluster set isDeleted = 1 where id = ?\")\n@Where(clause = \"isDeleted = 0\")\npublic class Cluster extends BaseEntity implements Comparable<Cluster> {\n\n  @Column(name = \"Name\", nullable = false)\n  private String name;\n\n  @Column(name = \"AppId\", nullable = false)\n  private String appId;\n\n  @Column(name = \"ParentClusterId\", nullable = false)\n  private long parentClusterId;\n\n  public String getAppId() {\n    return appId;\n  }\n\n  public String getName() {\n    return name;\n  }\n\n  public void setAppId(String appId) {\n    this.appId = appId;\n  }\n\n  public void setName(String name) {\n    this.name = name;\n  }\n\n  public long getParentClusterId() {\n    return parentClusterId;\n  }\n\n  public void setParentClusterId(long parentClusterId) {\n    this.parentClusterId = parentClusterId;\n  }\n\n  public String toString() {\n    return toStringHelper().add(\"name\", name).add(\"appId\", appId)\n        .add(\"parentClusterId\", parentClusterId).toString();\n  }\n\n  @Override\n  public int compareTo(Cluster o) {\n    if (o == null || getId() > o.getId()) {\n      return 1;\n    }\n\n    if (getId() == o.getId()) {\n      return 0;\n    }\n\n    return -1;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/entity/Commit.java",
    "content": "package com.ctrip.framework.apollo.biz.entity;\n\nimport com.ctrip.framework.apollo.common.entity.BaseEntity;\n\nimport org.hibernate.annotations.SQLDelete;\nimport org.hibernate.annotations.Where;\n\nimport javax.persistence.Column;\nimport javax.persistence.Entity;\nimport javax.persistence.Lob;\nimport javax.persistence.Table;\n\n@Entity\n@Table(name = \"Commit\")\n@SQLDelete(sql = \"Update Commit set isDeleted = 1 where id = ?\")\n@Where(clause = \"isDeleted = 0\")\npublic class Commit extends BaseEntity {\n\n  @Lob\n  @Column(name = \"ChangeSets\", nullable = false)\n  private String changeSets;\n\n  @Column(name = \"AppId\", nullable = false)\n  private String appId;\n\n  @Column(name = \"ClusterName\", nullable = false)\n  private String clusterName;\n\n  @Column(name = \"NamespaceName\", nullable = false)\n  private String namespaceName;\n\n  @Column(name = \"Comment\")\n  private String comment;\n\n  public String getChangeSets() {\n    return changeSets;\n  }\n\n  public void setChangeSets(String changeSets) {\n    this.changeSets = changeSets;\n  }\n\n  public String getAppId() {\n    return appId;\n  }\n\n  public void setAppId(String appId) {\n    this.appId = appId;\n  }\n\n  public String getClusterName() {\n    return clusterName;\n  }\n\n  public void setClusterName(String clusterName) {\n    this.clusterName = clusterName;\n  }\n\n  public String getNamespaceName() {\n    return namespaceName;\n  }\n\n  public void setNamespaceName(String namespaceName) {\n    this.namespaceName = namespaceName;\n  }\n\n  public String getComment() {\n    return comment;\n  }\n\n  public void setComment(String comment) {\n    this.comment = comment;\n  }\n\n  @Override\n  public String toString() {\n    return toStringHelper().add(\"changeSets\", changeSets).add(\"appId\", appId).add(\"clusterName\", clusterName)\n        .add(\"namespaceName\", namespaceName).add(\"comment\", comment).toString();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/entity/GrayReleaseRule.java",
    "content": "package com.ctrip.framework.apollo.biz.entity;\n\nimport com.ctrip.framework.apollo.common.entity.BaseEntity;\n\nimport org.hibernate.annotations.SQLDelete;\nimport org.hibernate.annotations.Where;\n\nimport javax.persistence.Column;\nimport javax.persistence.Entity;\nimport javax.persistence.Table;\n\n@Entity\n@Table(name = \"GrayReleaseRule\")\n@SQLDelete(sql = \"Update GrayReleaseRule set isDeleted = 1 where id = ?\")\n@Where(clause = \"isDeleted = 0\")\npublic class GrayReleaseRule extends BaseEntity{\n\n  @Column(name = \"appId\", nullable = false)\n  private String appId;\n\n  @Column(name = \"ClusterName\", nullable = false)\n  private String clusterName;\n\n  @Column(name = \"NamespaceName\", nullable = false)\n  private String namespaceName;\n\n  @Column(name = \"BranchName\", nullable = false)\n  private String branchName;\n\n  @Column(name = \"Rules\")\n  private String rules;\n\n  @Column(name = \"releaseId\", nullable = false)\n  private Long releaseId;\n\n  @Column(name = \"BranchStatus\", nullable = false)\n  private int branchStatus;\n\n  public String getAppId() {\n    return appId;\n  }\n\n  public void setAppId(String appId) {\n    this.appId = appId;\n  }\n\n  public String getClusterName() {\n    return clusterName;\n  }\n\n  public void setClusterName(String clusterName) {\n    this.clusterName = clusterName;\n  }\n\n  public String getNamespaceName() {\n    return namespaceName;\n  }\n\n  public void setNamespaceName(String namespaceName) {\n    this.namespaceName = namespaceName;\n  }\n\n  public String getBranchName() {\n    return branchName;\n  }\n\n  public void setBranchName(String branchName) {\n    this.branchName = branchName;\n  }\n\n  public String getRules() {\n    return rules;\n  }\n\n  public void setRules(String rules) {\n    this.rules = rules;\n  }\n\n  public Long getReleaseId() {\n    return releaseId;\n  }\n\n  public void setReleaseId(Long releaseId) {\n    this.releaseId = releaseId;\n  }\n\n  public int getBranchStatus() {\n    return branchStatus;\n  }\n\n  public void setBranchStatus(int branchStatus) {\n    this.branchStatus = branchStatus;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/entity/Instance.java",
    "content": "package com.ctrip.framework.apollo.biz.entity;\n\nimport com.google.common.base.MoreObjects;\n\nimport java.util.Date;\n\nimport javax.persistence.Column;\nimport javax.persistence.Entity;\nimport javax.persistence.GeneratedValue;\nimport javax.persistence.Id;\nimport javax.persistence.PrePersist;\nimport javax.persistence.Table;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@Entity\n@Table(name = \"Instance\")\npublic class Instance {\n  @Id\n  @GeneratedValue\n  @Column(name = \"Id\")\n  private long id;\n\n  @Column(name = \"AppId\", nullable = false)\n  private String appId;\n\n  @Column(name = \"ClusterName\", nullable = false)\n  private String clusterName;\n\n  @Column(name = \"DataCenter\", nullable = false)\n  private String dataCenter;\n\n  @Column(name = \"Ip\", nullable = false)\n  private String ip;\n\n  @Column(name = \"DataChange_CreatedTime\", nullable = false)\n  private Date dataChangeCreatedTime;\n\n  @Column(name = \"DataChange_LastTime\")\n  private Date dataChangeLastModifiedTime;\n\n  @PrePersist\n  protected void prePersist() {\n    if (this.dataChangeCreatedTime == null) {\n      dataChangeCreatedTime = new Date();\n    }\n    if (this.dataChangeLastModifiedTime == null) {\n      dataChangeLastModifiedTime = dataChangeCreatedTime;\n    }\n  }\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 getAppId() {\n    return appId;\n  }\n\n  public void setAppId(String appId) {\n    this.appId = appId;\n  }\n\n  public String getClusterName() {\n    return clusterName;\n  }\n\n  public void setClusterName(String clusterName) {\n    this.clusterName = clusterName;\n  }\n\n  public String getDataCenter() {\n    return dataCenter;\n  }\n\n  public void setDataCenter(String dataCenter) {\n    this.dataCenter = dataCenter;\n  }\n\n  public String getIp() {\n    return ip;\n  }\n\n  public void setIp(String ip) {\n    this.ip = ip;\n  }\n\n  public Date getDataChangeCreatedTime() {\n    return dataChangeCreatedTime;\n  }\n\n  public void setDataChangeCreatedTime(Date dataChangeCreatedTime) {\n    this.dataChangeCreatedTime = dataChangeCreatedTime;\n  }\n\n  public Date getDataChangeLastModifiedTime() {\n    return dataChangeLastModifiedTime;\n  }\n\n  public void setDataChangeLastModifiedTime(Date dataChangeLastModifiedTime) {\n    this.dataChangeLastModifiedTime = dataChangeLastModifiedTime;\n  }\n\n  @Override\n  public String toString() {\n    return MoreObjects.toStringHelper(this)\n        .omitNullValues()\n        .add(\"id\", id)\n        .add(\"appId\", appId)\n        .add(\"clusterName\", clusterName)\n        .add(\"dataCenter\", dataCenter)\n        .add(\"ip\", ip)\n        .add(\"dataChangeCreatedTime\", dataChangeCreatedTime)\n        .add(\"dataChangeLastModifiedTime\", dataChangeLastModifiedTime)\n        .toString();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/entity/InstanceConfig.java",
    "content": "package com.ctrip.framework.apollo.biz.entity;\n\nimport com.google.common.base.MoreObjects;\n\nimport java.util.Date;\n\nimport javax.persistence.Column;\nimport javax.persistence.Entity;\nimport javax.persistence.GeneratedValue;\nimport javax.persistence.Id;\nimport javax.persistence.PrePersist;\nimport javax.persistence.PreUpdate;\nimport javax.persistence.Table;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@Entity\n@Table(name = \"InstanceConfig\")\npublic class InstanceConfig {\n  @Id\n  @GeneratedValue\n  @Column(name = \"Id\")\n  private long id;\n\n  @Column(name = \"InstanceId\")\n  private long instanceId;\n\n  @Column(name = \"ConfigAppId\", nullable = false)\n  private String configAppId;\n\n  @Column(name = \"ConfigClusterName\", nullable = false)\n  private String configClusterName;\n\n  @Column(name = \"ConfigNamespaceName\", nullable = false)\n  private String configNamespaceName;\n\n  @Column(name = \"ReleaseKey\", nullable = false)\n  private String releaseKey;\n\n  @Column(name = \"ReleaseDeliveryTime\", nullable = false)\n  private Date releaseDeliveryTime;\n\n  @Column(name = \"DataChange_CreatedTime\", nullable = false)\n  private Date dataChangeCreatedTime;\n\n  @Column(name = \"DataChange_LastTime\")\n  private Date dataChangeLastModifiedTime;\n\n  @PrePersist\n  protected void prePersist() {\n    if (this.dataChangeCreatedTime == null) {\n      dataChangeCreatedTime = new Date();\n    }\n    if (this.dataChangeLastModifiedTime == null) {\n      dataChangeLastModifiedTime = dataChangeCreatedTime;\n    }\n  }\n\n  @PreUpdate\n  protected void preUpdate() {\n    this.dataChangeLastModifiedTime = new Date();\n  }\n\n  public long getId() {\n    return id;\n  }\n\n  public void setId(long id) {\n    this.id = id;\n  }\n\n  public long getInstanceId() {\n    return instanceId;\n  }\n\n  public void setInstanceId(long instanceId) {\n    this.instanceId = instanceId;\n  }\n\n  public String getConfigAppId() {\n    return configAppId;\n  }\n\n  public void setConfigAppId(String configAppId) {\n    this.configAppId = configAppId;\n  }\n\n  public String getConfigNamespaceName() {\n    return configNamespaceName;\n  }\n\n  public void setConfigNamespaceName(String configNamespaceName) {\n    this.configNamespaceName = configNamespaceName;\n  }\n\n  public String getReleaseKey() {\n    return releaseKey;\n  }\n\n  public void setReleaseKey(String releaseKey) {\n    this.releaseKey = releaseKey;\n  }\n\n  public Date getDataChangeCreatedTime() {\n    return dataChangeCreatedTime;\n  }\n\n  public void setDataChangeCreatedTime(Date dataChangeCreatedTime) {\n    this.dataChangeCreatedTime = dataChangeCreatedTime;\n  }\n\n  public Date getDataChangeLastModifiedTime() {\n    return dataChangeLastModifiedTime;\n  }\n\n  public void setDataChangeLastModifiedTime(Date dataChangeLastModifiedTime) {\n    this.dataChangeLastModifiedTime = dataChangeLastModifiedTime;\n  }\n\n  public String getConfigClusterName() {\n    return configClusterName;\n  }\n\n  public void setConfigClusterName(String configClusterName) {\n    this.configClusterName = configClusterName;\n  }\n\n  public Date getReleaseDeliveryTime() {\n    return releaseDeliveryTime;\n  }\n\n  public void setReleaseDeliveryTime(Date releaseDeliveryTime) {\n    this.releaseDeliveryTime = releaseDeliveryTime;\n  }\n\n  @Override\n  public String toString() {\n    return MoreObjects.toStringHelper(this)\n        .omitNullValues()\n        .add(\"id\", id)\n        .add(\"configAppId\", configAppId)\n        .add(\"configClusterName\", configClusterName)\n        .add(\"configNamespaceName\", configNamespaceName)\n        .add(\"releaseKey\", releaseKey)\n        .add(\"dataChangeCreatedTime\", dataChangeCreatedTime)\n        .add(\"dataChangeLastModifiedTime\", dataChangeLastModifiedTime)\n        .toString();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/entity/Item.java",
    "content": "package com.ctrip.framework.apollo.biz.entity;\n\nimport com.ctrip.framework.apollo.common.entity.BaseEntity;\n\nimport org.hibernate.annotations.SQLDelete;\nimport org.hibernate.annotations.Where;\n\nimport javax.persistence.Column;\nimport javax.persistence.Entity;\nimport javax.persistence.Lob;\nimport javax.persistence.Table;\n\n@Entity\n@Table(name = \"Item\")\n@SQLDelete(sql = \"Update Item set isDeleted = 1 where id = ?\")\n@Where(clause = \"isDeleted = 0\")\npublic class Item extends BaseEntity {\n\n  @Column(name = \"NamespaceId\", nullable = false)\n  private long namespaceId;\n\n  @Column(name = \"key\", nullable = false)\n  private String key;\n\n  @Column(name = \"value\")\n  @Lob\n  private String value;\n\n  @Column(name = \"comment\")\n  private String comment;\n\n  @Column(name = \"LineNum\")\n  private Integer lineNum;\n\n  public String getComment() {\n    return comment;\n  }\n\n  public String getKey() {\n    return key;\n  }\n\n  public long getNamespaceId() {\n    return namespaceId;\n  }\n\n  public String getValue() {\n    return value;\n  }\n\n  public void setComment(String comment) {\n    this.comment = comment;\n  }\n\n  public void setKey(String key) {\n    this.key = key;\n  }\n\n  public void setNamespaceId(long namespaceId) {\n    this.namespaceId = namespaceId;\n  }\n\n  public void setValue(String value) {\n    this.value = value;\n  }\n\n  public Integer getLineNum() {\n    return lineNum;\n  }\n\n  public void setLineNum(Integer lineNum) {\n    this.lineNum = lineNum;\n  }\n\n  public String toString() {\n    return toStringHelper().add(\"namespaceId\", namespaceId).add(\"key\", key).add(\"value\", value)\n        .add(\"lineNum\", lineNum).add(\"comment\", comment).toString();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/entity/Namespace.java",
    "content": "package com.ctrip.framework.apollo.biz.entity;\n\nimport com.ctrip.framework.apollo.common.entity.BaseEntity;\n\nimport org.hibernate.annotations.SQLDelete;\nimport org.hibernate.annotations.Where;\n\nimport javax.persistence.Column;\nimport javax.persistence.Entity;\nimport javax.persistence.Table;\n\n@Entity\n@Table(name = \"Namespace\")\n@SQLDelete(sql = \"Update Namespace set isDeleted = 1 where id = ?\")\n@Where(clause = \"isDeleted = 0\")\npublic class Namespace extends BaseEntity {\n\n  @Column(name = \"appId\", nullable = false)\n  private String appId;\n\n  @Column(name = \"ClusterName\", nullable = false)\n  private String clusterName;\n\n  @Column(name = \"NamespaceName\", nullable = false)\n  private String namespaceName;\n\n  public Namespace(){\n\n  }\n\n  public Namespace(String appId, String clusterName, String namespaceName) {\n    this.appId = appId;\n    this.clusterName = clusterName;\n    this.namespaceName = namespaceName;\n  }\n\n  public String getAppId() {\n    return appId;\n  }\n\n  public String getClusterName() {\n    return clusterName;\n  }\n\n  public String getNamespaceName() {\n    return namespaceName;\n  }\n\n  public void setAppId(String appId) {\n    this.appId = appId;\n  }\n\n  public void setClusterName(String clusterName) {\n    this.clusterName = clusterName;\n  }\n\n  public void setNamespaceName(String namespaceName) {\n    this.namespaceName = namespaceName;\n  }\n\n  public String toString() {\n    return toStringHelper().add(\"appId\", appId).add(\"clusterName\", clusterName)\n        .add(\"namespaceName\", namespaceName).toString();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/entity/NamespaceLock.java",
    "content": "package com.ctrip.framework.apollo.biz.entity;\n\nimport com.ctrip.framework.apollo.common.entity.BaseEntity;\n\nimport org.hibernate.annotations.Where;\n\nimport javax.persistence.Column;\nimport javax.persistence.Entity;\nimport javax.persistence.Table;\n\n@Entity\n@Table(name = \"NamespaceLock\")\n@Where(clause = \"isDeleted = 0\")\npublic class NamespaceLock extends BaseEntity{\n\n  @Column(name = \"NamespaceId\")\n  private long namespaceId;\n\n  public long getNamespaceId() {\n    return namespaceId;\n  }\n\n  public void setNamespaceId(long namespaceId) {\n    this.namespaceId = namespaceId;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/entity/Privilege.java",
    "content": "package com.ctrip.framework.apollo.biz.entity;\n\nimport com.ctrip.framework.apollo.common.entity.BaseEntity;\n\nimport org.hibernate.annotations.SQLDelete;\nimport org.hibernate.annotations.Where;\n\nimport javax.persistence.Column;\nimport javax.persistence.Entity;\nimport javax.persistence.Table;\n\n@Entity\n@Table(name = \"Privilege\")\n@SQLDelete(sql = \"Update Privilege set isDeleted = 1 where id = ?\")\n@Where(clause = \"isDeleted = 0\")\npublic class Privilege extends BaseEntity {\n\n  @Column(name = \"Name\", nullable = false)\n  private String name;\n\n  @Column(name = \"PrivilType\", nullable = false)\n  private String privilType;\n\n  @Column(name = \"NamespaceId\")\n  private long namespaceId;\n\n  public String getName() {\n    return name;\n  }\n\n  public long getNamespaceId() {\n    return namespaceId;\n  }\n\n  public String getPrivilType() {\n    return privilType;\n  }\n\n  public void setName(String name) {\n    this.name = name;\n  }\n\n  public void setNamespaceId(long namespaceId) {\n    this.namespaceId = namespaceId;\n  }\n\n  public void setPrivilType(String privilType) {\n    this.privilType = privilType;\n  }\n\n  public String toString() {\n    return toStringHelper().add(\"namespaceId\", namespaceId).add(\"privilType\", privilType)\n        .add(\"name\", name).toString();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/entity/Release.java",
    "content": "package com.ctrip.framework.apollo.biz.entity;\n\nimport com.ctrip.framework.apollo.common.entity.BaseEntity;\n\nimport org.hibernate.annotations.SQLDelete;\nimport org.hibernate.annotations.Where;\n\nimport javax.persistence.Column;\nimport javax.persistence.Entity;\nimport javax.persistence.Lob;\nimport javax.persistence.Table;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@Entity\n@Table(name = \"Release\")\n@SQLDelete(sql = \"Update Release set isDeleted = 1 where id = ?\")\n@Where(clause = \"isDeleted = 0\")\npublic class Release extends BaseEntity {\n  @Column(name = \"ReleaseKey\", nullable = false)\n  private String releaseKey;\n\n  @Column(name = \"Name\", nullable = false)\n  private String name;\n\n  @Column(name = \"AppId\", nullable = false)\n  private String appId;\n\n  @Column(name = \"ClusterName\", nullable = false)\n  private String clusterName;\n\n  @Column(name = \"NamespaceName\", nullable = false)\n  private String namespaceName;\n\n  @Column(name = \"Configurations\", nullable = false)\n  @Lob\n  private String configurations;\n\n  @Column(name = \"Comment\", nullable = false)\n  private String comment;\n\n  @Column(name = \"IsAbandoned\", columnDefinition = \"Bit default '0'\")\n  private boolean isAbandoned;\n\n  public String getReleaseKey() {\n    return releaseKey;\n  }\n\n  public String getAppId() {\n    return appId;\n  }\n\n  public String getClusterName() {\n    return clusterName;\n  }\n\n  public String getComment() {\n    return comment;\n  }\n\n  public String getConfigurations() {\n    return configurations;\n  }\n\n  public String getNamespaceName() {\n    return namespaceName;\n  }\n\n  public String getName() {\n    return name;\n  }\n\n  public void setReleaseKey(String releaseKey) {\n    this.releaseKey = releaseKey;\n  }\n\n  public void setAppId(String appId) {\n    this.appId = appId;\n  }\n\n  public void setClusterName(String clusterName) {\n    this.clusterName = clusterName;\n  }\n\n  public void setComment(String comment) {\n    this.comment = comment;\n  }\n\n  public void setConfigurations(String configurations) {\n    this.configurations = configurations;\n  }\n\n  public void setNamespaceName(String namespaceName) {\n    this.namespaceName = namespaceName;\n  }\n\n  public void setName(String name) {\n    this.name = name;\n  }\n\n  public boolean isAbandoned() {\n    return isAbandoned;\n  }\n\n  public void setAbandoned(boolean abandoned) {\n    isAbandoned = abandoned;\n  }\n\n  public String toString() {\n    return toStringHelper().add(\"name\", name).add(\"appId\", appId).add(\"clusterName\", clusterName)\n        .add(\"namespaceName\", namespaceName).add(\"configurations\", configurations)\n        .add(\"comment\", comment).add(\"isAbandoned\", isAbandoned).toString();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/entity/ReleaseHistory.java",
    "content": "package com.ctrip.framework.apollo.biz.entity;\n\nimport com.ctrip.framework.apollo.common.entity.BaseEntity;\n\nimport org.hibernate.annotations.SQLDelete;\nimport org.hibernate.annotations.Where;\n\nimport javax.persistence.Column;\nimport javax.persistence.Entity;\nimport javax.persistence.Table;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@Entity\n@Table(name = \"ReleaseHistory\")\n@SQLDelete(sql = \"Update ReleaseHistory set isDeleted = 1 where id = ?\")\n@Where(clause = \"isDeleted = 0\")\npublic class ReleaseHistory extends BaseEntity {\n  @Column(name = \"AppId\", nullable = false)\n  private String appId;\n\n  @Column(name = \"ClusterName\", nullable = false)\n  private String clusterName;\n\n  @Column(name = \"NamespaceName\", nullable = false)\n  private String namespaceName;\n\n  @Column(name = \"BranchName\", nullable = false)\n  private String branchName;\n\n  @Column(name = \"ReleaseId\")\n  private long releaseId;\n\n  @Column(name = \"PreviousReleaseId\")\n  private long previousReleaseId;\n\n  @Column(name = \"Operation\")\n  private int operation;\n\n  @Column(name = \"OperationContext\", nullable = false)\n  private String operationContext;\n\n  public String getAppId() {\n    return appId;\n  }\n\n  public void setAppId(String appId) {\n    this.appId = appId;\n  }\n\n  public String getClusterName() {\n    return clusterName;\n  }\n\n  public void setClusterName(String clusterName) {\n    this.clusterName = clusterName;\n  }\n\n  public String getNamespaceName() {\n    return namespaceName;\n  }\n\n  public void setNamespaceName(String namespaceName) {\n    this.namespaceName = namespaceName;\n  }\n\n  public String getBranchName() {\n    return branchName;\n  }\n\n  public void setBranchName(String branchName) {\n    this.branchName = branchName;\n  }\n\n  public long getReleaseId() {\n    return releaseId;\n  }\n\n  public void setReleaseId(long releaseId) {\n    this.releaseId = releaseId;\n  }\n\n  public long getPreviousReleaseId() {\n    return previousReleaseId;\n  }\n\n  public void setPreviousReleaseId(long previousReleaseId) {\n    this.previousReleaseId = previousReleaseId;\n  }\n\n  public int getOperation() {\n    return operation;\n  }\n\n  public void setOperation(int operation) {\n    this.operation = operation;\n  }\n\n  public String getOperationContext() {\n    return operationContext;\n  }\n\n  public void setOperationContext(String operationContext) {\n    this.operationContext = operationContext;\n  }\n\n  public String toString() {\n    return toStringHelper().add(\"appId\", appId).add(\"clusterName\", clusterName)\n        .add(\"namespaceName\", namespaceName).add(\"branchName\", branchName)\n        .add(\"releaseId\", releaseId).add(\"previousReleaseId\", previousReleaseId)\n        .add(\"operation\", operation).toString();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/entity/ReleaseMessage.java",
    "content": "package com.ctrip.framework.apollo.biz.entity;\n\nimport com.google.common.base.MoreObjects;\n\nimport java.util.Date;\n\nimport javax.persistence.Column;\nimport javax.persistence.Entity;\nimport javax.persistence.GeneratedValue;\nimport javax.persistence.Id;\nimport javax.persistence.PrePersist;\nimport javax.persistence.Table;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@Entity\n@Table(name = \"ReleaseMessage\")\npublic class ReleaseMessage {\n  @Id\n  @GeneratedValue\n  @Column(name = \"Id\")\n  private long id;\n\n  @Column(name = \"Message\", nullable = false)\n  private String message;\n\n  @Column(name = \"DataChange_LastTime\")\n  private Date dataChangeLastModifiedTime;\n\n  @PrePersist\n  protected void prePersist() {\n    if (this.dataChangeLastModifiedTime == null) {\n      dataChangeLastModifiedTime = new Date();\n    }\n  }\n\n  public ReleaseMessage() {\n  }\n\n  public ReleaseMessage(String message) {\n    this.message = message;\n  }\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 getMessage() {\n    return message;\n  }\n\n  public void setMessage(String message) {\n    this.message = message;\n  }\n\n  @Override\n  public String toString() {\n    return MoreObjects.toStringHelper(this)\n        .omitNullValues()\n        .add(\"id\", id)\n        .add(\"message\", message)\n        .add(\"dataChangeLastModifiedTime\", dataChangeLastModifiedTime)\n        .toString();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/entity/ServerConfig.java",
    "content": "package com.ctrip.framework.apollo.biz.entity;\n\nimport com.ctrip.framework.apollo.common.entity.BaseEntity;\n\nimport org.hibernate.annotations.SQLDelete;\nimport org.hibernate.annotations.Where;\n\nimport javax.persistence.Column;\nimport javax.persistence.Entity;\nimport javax.persistence.Table;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@Entity\n@Table(name = \"ServerConfig\")\n@SQLDelete(sql = \"Update ServerConfig set isDeleted = 1 where id = ?\")\n@Where(clause = \"isDeleted = 0\")\npublic class ServerConfig extends BaseEntity {\n  @Column(name = \"Key\", nullable = false)\n  private String key;\n\n  @Column(name = \"Cluster\", nullable = false)\n  private String cluster;\n\n  @Column(name = \"Value\", nullable = false)\n  private String value;\n\n  @Column(name = \"Comment\", nullable = false)\n  private String comment;\n\n  public String getKey() {\n    return key;\n  }\n\n  public void setKey(String key) {\n    this.key = key;\n  }\n\n  public String getValue() {\n    return value;\n  }\n\n  public void setValue(String value) {\n    this.value = value;\n  }\n\n  public String getComment() {\n    return comment;\n  }\n\n  public void setComment(String comment) {\n    this.comment = comment;\n  }\n\n  public String getCluster() {\n    return cluster;\n  }\n\n  public void setCluster(String cluster) {\n    this.cluster = cluster;\n  }\n\n  public String toString() {\n    return toStringHelper().add(\"key\", key).add(\"value\", value).add(\"comment\", comment).toString();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/eureka/ApolloEurekaClientConfig.java",
    "content": "package com.ctrip.framework.apollo.biz.eureka;\n\n\nimport com.ctrip.framework.apollo.biz.config.BizConfig;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.cloud.netflix.eureka.EurekaClientConfigBean;\nimport org.springframework.context.annotation.Primary;\nimport org.springframework.stereotype.Component;\nimport org.springframework.util.CollectionUtils;\n\nimport java.util.List;\n\n@Component\n@Primary\npublic class ApolloEurekaClientConfig extends EurekaClientConfigBean {\n\n  @Autowired\n  private BizConfig bizConfig;\n\n  /**\n   * Assert only one zone: defaultZone, but multiple environments.\n   */\n  public List<String> getEurekaServerServiceUrls(String myZone) {\n    List<String> urls = bizConfig.eurekaServiceUrls();\n    return CollectionUtils.isEmpty(urls) ? super.getEurekaServerServiceUrls(myZone) : urls;\n  }\n\n  @Override\n  public boolean equals(Object o) {\n    return super.equals(o);\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/grayReleaseRule/GrayReleaseRuleCache.java",
    "content": "package com.ctrip.framework.apollo.biz.grayReleaseRule;\n\nimport com.ctrip.framework.apollo.common.dto.GrayReleaseRuleItemDTO;\n\nimport java.util.Set;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class GrayReleaseRuleCache {\n  private long ruleId;\n  private String branchName;\n  private String namespaceName;\n  private long releaseId;\n  private long loadVersion;\n  private int branchStatus;\n  private Set<GrayReleaseRuleItemDTO> ruleItems;\n\n  public GrayReleaseRuleCache(long ruleId, String branchName, String namespaceName, long\n      releaseId, int branchStatus, long loadVersion, Set<GrayReleaseRuleItemDTO> ruleItems) {\n    this.ruleId = ruleId;\n    this.branchName = branchName;\n    this.namespaceName = namespaceName;\n    this.releaseId = releaseId;\n    this.branchStatus = branchStatus;\n    this.loadVersion = loadVersion;\n    this.ruleItems = ruleItems;\n  }\n\n  public long getRuleId() {\n    return ruleId;\n  }\n\n  public Set<GrayReleaseRuleItemDTO> getRuleItems() {\n    return ruleItems;\n  }\n\n  public String getBranchName() {\n    return branchName;\n  }\n\n  public int getBranchStatus() {\n    return branchStatus;\n  }\n\n  public long getReleaseId() {\n    return releaseId;\n  }\n\n  public long getLoadVersion() {\n    return loadVersion;\n  }\n\n  public void setLoadVersion(long loadVersion) {\n    this.loadVersion = loadVersion;\n  }\n\n  public String getNamespaceName() {\n    return namespaceName;\n  }\n\n  public boolean matches(String clientAppId, String clientIp) {\n    for (GrayReleaseRuleItemDTO ruleItem : ruleItems) {\n      if (ruleItem.matches(clientAppId, clientIp)) {\n        return true;\n      }\n    }\n    return false;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/grayReleaseRule/GrayReleaseRulesHolder.java",
    "content": "package com.ctrip.framework.apollo.biz.grayReleaseRule;\n\nimport com.google.common.base.Joiner;\nimport com.google.common.base.Splitter;\nimport com.google.common.base.Strings;\nimport com.google.common.collect.HashMultimap;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Multimap;\nimport com.google.common.collect.Multimaps;\nimport com.google.common.collect.Sets;\n\nimport com.ctrip.framework.apollo.biz.config.BizConfig;\nimport com.ctrip.framework.apollo.biz.entity.GrayReleaseRule;\nimport com.ctrip.framework.apollo.biz.entity.ReleaseMessage;\nimport com.ctrip.framework.apollo.biz.message.ReleaseMessageListener;\nimport com.ctrip.framework.apollo.biz.message.Topics;\nimport com.ctrip.framework.apollo.biz.repository.GrayReleaseRuleRepository;\nimport com.ctrip.framework.apollo.common.constants.NamespaceBranchStatus;\nimport com.ctrip.framework.apollo.common.dto.GrayReleaseRuleItemDTO;\nimport com.ctrip.framework.apollo.common.utils.GrayReleaseRuleItemTransformer;\nimport com.ctrip.framework.apollo.core.ConfigConsts;\nimport com.ctrip.framework.apollo.core.utils.ApolloThreadFactory;\nimport com.ctrip.framework.apollo.tracer.Tracer;\nimport com.ctrip.framework.apollo.tracer.spi.Transaction;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.InitializingBean;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.util.CollectionUtils;\n\nimport java.util.List;\nimport java.util.Set;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicLong;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class GrayReleaseRulesHolder implements ReleaseMessageListener, InitializingBean {\n  private static final Logger logger = LoggerFactory.getLogger(GrayReleaseRulesHolder.class);\n  private static final Joiner STRING_JOINER = Joiner.on(ConfigConsts.CLUSTER_NAMESPACE_SEPARATOR);\n  private static final Splitter STRING_SPLITTER =\n      Splitter.on(ConfigConsts.CLUSTER_NAMESPACE_SEPARATOR).omitEmptyStrings();\n\n  @Autowired\n  private GrayReleaseRuleRepository grayReleaseRuleRepository;\n  @Autowired\n  private BizConfig bizConfig;\n\n  private int databaseScanInterval;\n  private ScheduledExecutorService executorService;\n  //store configAppId+configCluster+configNamespace -> GrayReleaseRuleCache map\n  private Multimap<String, GrayReleaseRuleCache> grayReleaseRuleCache;\n  //store clientAppId+clientNamespace+ip -> ruleId map\n  private Multimap<String, Long> reversedGrayReleaseRuleCache;\n  //an auto increment version to indicate the age of rules\n  private AtomicLong loadVersion;\n\n  public GrayReleaseRulesHolder() {\n    loadVersion = new AtomicLong();\n    grayReleaseRuleCache = Multimaps.synchronizedSetMultimap(HashMultimap.create());\n    reversedGrayReleaseRuleCache = Multimaps.synchronizedSetMultimap(HashMultimap.create());\n    executorService = Executors.newScheduledThreadPool(1, ApolloThreadFactory\n        .create(\"GrayReleaseRulesHolder\", true));\n  }\n\n  @Override\n  public void afterPropertiesSet() throws Exception {\n    populateDataBaseInterval();\n    //force sync load for the first time\n    periodicScanRules();\n    executorService.scheduleWithFixedDelay(this::periodicScanRules,\n        getDatabaseScanIntervalSecond(), getDatabaseScanIntervalSecond(), getDatabaseScanTimeUnit()\n    );\n  }\n\n  @Override\n  public void handleMessage(ReleaseMessage message, String channel) {\n    logger.info(\"message received - channel: {}, message: {}\", channel, message);\n    String releaseMessage = message.getMessage();\n    if (!Topics.APOLLO_RELEASE_TOPIC.equals(channel) || Strings.isNullOrEmpty(releaseMessage)) {\n      return;\n    }\n    List<String> keys = STRING_SPLITTER.splitToList(releaseMessage);\n    //message should be appId+cluster+namespace\n    if (keys.size() != 3) {\n      logger.error(\"message format invalid - {}\", releaseMessage);\n      return;\n    }\n    String appId = keys.get(0);\n    String cluster = keys.get(1);\n    String namespace = keys.get(2);\n\n    List<GrayReleaseRule> rules = grayReleaseRuleRepository\n        .findByAppIdAndClusterNameAndNamespaceName(appId, cluster, namespace);\n\n    mergeGrayReleaseRules(rules);\n  }\n\n  private void periodicScanRules() {\n    Transaction transaction = Tracer.newTransaction(\"Apollo.GrayReleaseRulesScanner\",\n        \"scanGrayReleaseRules\");\n    try {\n      loadVersion.incrementAndGet();\n      scanGrayReleaseRules();\n      transaction.setStatus(Transaction.SUCCESS);\n    } catch (Throwable ex) {\n      transaction.setStatus(ex);\n      logger.error(\"Scan gray release rule failed\", ex);\n    } finally {\n      transaction.complete();\n    }\n  }\n\n  public Long findReleaseIdFromGrayReleaseRule(String clientAppId, String clientIp, String\n      configAppId, String configCluster, String configNamespaceName) {\n    String key = assembleGrayReleaseRuleKey(configAppId, configCluster, configNamespaceName);\n    if (!grayReleaseRuleCache.containsKey(key)) {\n      return null;\n    }\n    //create a new list to avoid ConcurrentModificationException\n    List<GrayReleaseRuleCache> rules = Lists.newArrayList(grayReleaseRuleCache.get(key));\n    for (GrayReleaseRuleCache rule : rules) {\n      //check branch status\n      if (rule.getBranchStatus() != NamespaceBranchStatus.ACTIVE) {\n        continue;\n      }\n      if (rule.matches(clientAppId, clientIp)) {\n        return rule.getReleaseId();\n      }\n    }\n    return null;\n  }\n\n  /**\n   * Check whether there are gray release rules for the clientAppId, clientIp, namespace\n   * combination. Please note that even there are gray release rules, it doesn't mean it will always\n   * load gray releases. Because gray release rules actually apply to one more dimension - cluster.\n   */\n  public boolean hasGrayReleaseRule(String clientAppId, String clientIp, String namespaceName) {\n    return reversedGrayReleaseRuleCache.containsKey(assembleReversedGrayReleaseRuleKey(clientAppId,\n        namespaceName, clientIp)) || reversedGrayReleaseRuleCache.containsKey\n        (assembleReversedGrayReleaseRuleKey(clientAppId, namespaceName, GrayReleaseRuleItemDTO\n            .ALL_IP));\n  }\n\n  private void scanGrayReleaseRules() {\n    long maxIdScanned = 0;\n    boolean hasMore = true;\n\n    while (hasMore && !Thread.currentThread().isInterrupted()) {\n      List<GrayReleaseRule> grayReleaseRules = grayReleaseRuleRepository\n          .findFirst500ByIdGreaterThanOrderByIdAsc(maxIdScanned);\n      if (CollectionUtils.isEmpty(grayReleaseRules)) {\n        break;\n      }\n      mergeGrayReleaseRules(grayReleaseRules);\n      int rulesScanned = grayReleaseRules.size();\n      maxIdScanned = grayReleaseRules.get(rulesScanned - 1).getId();\n      //batch is 500\n      hasMore = rulesScanned == 500;\n    }\n  }\n\n  private void mergeGrayReleaseRules(List<GrayReleaseRule> grayReleaseRules) {\n    if (CollectionUtils.isEmpty(grayReleaseRules)) {\n      return;\n    }\n    for (GrayReleaseRule grayReleaseRule : grayReleaseRules) {\n      if (grayReleaseRule.getReleaseId() == null || grayReleaseRule.getReleaseId() == 0) {\n        //filter rules with no release id, i.e. never released\n        continue;\n      }\n      String key = assembleGrayReleaseRuleKey(grayReleaseRule.getAppId(), grayReleaseRule\n          .getClusterName(), grayReleaseRule.getNamespaceName());\n      //create a new list to avoid ConcurrentModificationException\n      List<GrayReleaseRuleCache> rules = Lists.newArrayList(grayReleaseRuleCache.get(key));\n      GrayReleaseRuleCache oldRule = null;\n      for (GrayReleaseRuleCache ruleCache : rules) {\n        if (ruleCache.getBranchName().equals(grayReleaseRule.getBranchName())) {\n          oldRule = ruleCache;\n          break;\n        }\n      }\n\n      //if old rule is null and new rule's branch status is not active, ignore\n      if (oldRule == null && grayReleaseRule.getBranchStatus() != NamespaceBranchStatus.ACTIVE) {\n        continue;\n      }\n\n      //use id comparison to avoid synchronization\n      if (oldRule == null || grayReleaseRule.getId() > oldRule.getRuleId()) {\n        addCache(key, transformRuleToRuleCache(grayReleaseRule));\n        if (oldRule != null) {\n          removeCache(key, oldRule);\n        }\n      } else {\n        if (oldRule.getBranchStatus() == NamespaceBranchStatus.ACTIVE) {\n          //update load version\n          oldRule.setLoadVersion(loadVersion.get());\n        } else if ((loadVersion.get() - oldRule.getLoadVersion()) > 1) {\n          //remove outdated inactive branch rule after 2 update cycles\n          removeCache(key, oldRule);\n        }\n      }\n    }\n  }\n\n  private void addCache(String key, GrayReleaseRuleCache ruleCache) {\n    if (ruleCache.getBranchStatus() == NamespaceBranchStatus.ACTIVE) {\n      for (GrayReleaseRuleItemDTO ruleItemDTO : ruleCache.getRuleItems()) {\n        for (String clientIp : ruleItemDTO.getClientIpList()) {\n          reversedGrayReleaseRuleCache.put(assembleReversedGrayReleaseRuleKey(ruleItemDTO\n              .getClientAppId(), ruleCache.getNamespaceName(), clientIp), ruleCache.getRuleId());\n        }\n      }\n    }\n    grayReleaseRuleCache.put(key, ruleCache);\n  }\n\n  private void removeCache(String key, GrayReleaseRuleCache ruleCache) {\n    grayReleaseRuleCache.remove(key, ruleCache);\n    for (GrayReleaseRuleItemDTO ruleItemDTO : ruleCache.getRuleItems()) {\n      for (String clientIp : ruleItemDTO.getClientIpList()) {\n        reversedGrayReleaseRuleCache.remove(assembleReversedGrayReleaseRuleKey(ruleItemDTO\n            .getClientAppId(), ruleCache.getNamespaceName(), clientIp), ruleCache.getRuleId());\n      }\n    }\n  }\n\n  private GrayReleaseRuleCache transformRuleToRuleCache(GrayReleaseRule grayReleaseRule) {\n    Set<GrayReleaseRuleItemDTO> ruleItems;\n    try {\n      ruleItems = GrayReleaseRuleItemTransformer.batchTransformFromJSON(grayReleaseRule.getRules());\n    } catch (Throwable ex) {\n      ruleItems = Sets.newHashSet();\n      Tracer.logError(ex);\n      logger.error(\"parse rule for gray release rule {} failed\", grayReleaseRule.getId(), ex);\n    }\n\n    GrayReleaseRuleCache ruleCache = new GrayReleaseRuleCache(grayReleaseRule.getId(),\n        grayReleaseRule.getBranchName(), grayReleaseRule.getNamespaceName(), grayReleaseRule\n        .getReleaseId(), grayReleaseRule.getBranchStatus(), loadVersion.get(), ruleItems);\n\n    return ruleCache;\n  }\n\n  private void populateDataBaseInterval() {\n    databaseScanInterval = bizConfig.grayReleaseRuleScanInterval();\n  }\n\n  private int getDatabaseScanIntervalSecond() {\n    return databaseScanInterval;\n  }\n\n  private TimeUnit getDatabaseScanTimeUnit() {\n    return TimeUnit.SECONDS;\n  }\n\n  private String assembleGrayReleaseRuleKey(String configAppId, String configCluster, String\n      configNamespaceName) {\n    return STRING_JOINER.join(configAppId, configCluster, configNamespaceName);\n  }\n\n  private String assembleReversedGrayReleaseRuleKey(String clientAppId, String\n      clientNamespaceName, String clientIp) {\n    return STRING_JOINER.join(clientAppId, clientNamespaceName, clientIp);\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/message/DatabaseMessageSender.java",
    "content": "package com.ctrip.framework.apollo.biz.message;\n\nimport com.google.common.collect.Queues;\n\nimport com.ctrip.framework.apollo.biz.entity.ReleaseMessage;\nimport com.ctrip.framework.apollo.biz.repository.ReleaseMessageRepository;\nimport com.ctrip.framework.apollo.core.utils.ApolloThreadFactory;\nimport com.ctrip.framework.apollo.tracer.Tracer;\nimport com.ctrip.framework.apollo.tracer.spi.Transaction;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\nimport org.springframework.transaction.annotation.Transactional;\n\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.concurrent.BlockingQueue;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\nimport javax.annotation.PostConstruct;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@Component\npublic class DatabaseMessageSender implements MessageSender {\n  private static final Logger logger = LoggerFactory.getLogger(DatabaseMessageSender.class);\n  private static final int CLEAN_QUEUE_MAX_SIZE = 100;\n  private BlockingQueue<Long> toClean = Queues.newLinkedBlockingQueue(CLEAN_QUEUE_MAX_SIZE);\n  private final ExecutorService cleanExecutorService;\n  private final AtomicBoolean cleanStopped;\n\n  @Autowired\n  private ReleaseMessageRepository releaseMessageRepository;\n\n  public DatabaseMessageSender() {\n    cleanExecutorService = Executors.newSingleThreadExecutor(ApolloThreadFactory.create(\"DatabaseMessageSender\", true));\n    cleanStopped = new AtomicBoolean(false);\n  }\n\n  @Override\n  @Transactional\n  public void sendMessage(String message, String channel) {\n    logger.info(\"Sending message {} to channel {}\", message, channel);\n    if (!Objects.equals(channel, Topics.APOLLO_RELEASE_TOPIC)) {\n      logger.warn(\"Channel {} not supported by DatabaseMessageSender!\");\n      return;\n    }\n\n    Tracer.logEvent(\"Apollo.AdminService.ReleaseMessage\", message);\n    Transaction transaction = Tracer.newTransaction(\"Apollo.AdminService\", \"sendMessage\");\n    try {\n      ReleaseMessage newMessage = releaseMessageRepository.save(new ReleaseMessage(message));\n      toClean.offer(newMessage.getId());\n      transaction.setStatus(Transaction.SUCCESS);\n    } catch (Throwable ex) {\n      logger.error(\"Sending message to database failed\", ex);\n      transaction.setStatus(ex);\n      throw ex;\n    } finally {\n      transaction.complete();\n    }\n  }\n\n  @PostConstruct\n  private void initialize() {\n    cleanExecutorService.submit(() -> {\n      while (!cleanStopped.get() && !Thread.currentThread().isInterrupted()) {\n        try {\n          Long rm = toClean.poll(1, TimeUnit.SECONDS);\n          if (rm != null) {\n            cleanMessage(rm);\n          } else {\n            TimeUnit.SECONDS.sleep(5);\n          }\n        } catch (Throwable ex) {\n          Tracer.logError(ex);\n        }\n      }\n    });\n  }\n\n  private void cleanMessage(Long id) {\n    boolean hasMore = true;\n    //double check in case the release message is rolled back\n    ReleaseMessage releaseMessage = releaseMessageRepository.findOne(id);\n    if (releaseMessage == null) {\n      return;\n    }\n    while (hasMore && !Thread.currentThread().isInterrupted()) {\n      List<ReleaseMessage> messages = releaseMessageRepository.findFirst100ByMessageAndIdLessThanOrderByIdAsc(\n          releaseMessage.getMessage(), releaseMessage.getId());\n\n      releaseMessageRepository.delete(messages);\n      hasMore = messages.size() == 100;\n\n      messages.forEach(toRemove -> Tracer.logEvent(\n          String.format(\"ReleaseMessage.Clean.%s\", toRemove.getMessage()), String.valueOf(toRemove.getId())));\n    }\n  }\n\n  void stopClean() {\n    cleanStopped.set(true);\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/message/MessageSender.java",
    "content": "package com.ctrip.framework.apollo.biz.message;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic interface MessageSender {\n  void sendMessage(String message, String channel);\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/message/ReleaseMessageListener.java",
    "content": "package com.ctrip.framework.apollo.biz.message;\n\nimport com.ctrip.framework.apollo.biz.entity.ReleaseMessage;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic interface ReleaseMessageListener {\n  void handleMessage(ReleaseMessage message, String channel);\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/message/ReleaseMessageScanner.java",
    "content": "package com.ctrip.framework.apollo.biz.message;\n\nimport java.util.List;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.TimeUnit;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.InitializingBean;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.util.CollectionUtils;\n\nimport com.ctrip.framework.apollo.biz.config.BizConfig;\nimport com.ctrip.framework.apollo.biz.entity.ReleaseMessage;\nimport com.ctrip.framework.apollo.biz.repository.ReleaseMessageRepository;\nimport com.ctrip.framework.apollo.core.utils.ApolloThreadFactory;\nimport com.ctrip.framework.apollo.tracer.Tracer;\nimport com.ctrip.framework.apollo.tracer.spi.Transaction;\nimport com.google.common.collect.Lists;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class ReleaseMessageScanner implements InitializingBean {\n  private static final Logger logger = LoggerFactory.getLogger(ReleaseMessageScanner.class);\n  @Autowired\n  private BizConfig bizConfig;\n  @Autowired\n  private ReleaseMessageRepository releaseMessageRepository;\n  private int databaseScanInterval;\n  private List<ReleaseMessageListener> listeners;\n  private ScheduledExecutorService executorService;\n  private long maxIdScanned;\n\n  public ReleaseMessageScanner() {\n    listeners = Lists.newCopyOnWriteArrayList();\n    executorService = Executors.newScheduledThreadPool(1, ApolloThreadFactory\n        .create(\"ReleaseMessageScanner\", true));\n  }\n\n  @Override\n  public void afterPropertiesSet() throws Exception {\n    databaseScanInterval = bizConfig.releaseMessageScanIntervalInMilli();\n    maxIdScanned = loadLargestMessageId();\n    executorService.scheduleWithFixedDelay((Runnable) () -> {\n      Transaction transaction = Tracer.newTransaction(\"Apollo.ReleaseMessageScanner\", \"scanMessage\");\n      try {\n        scanMessages();\n        transaction.setStatus(Transaction.SUCCESS);\n      } catch (Throwable ex) {\n        transaction.setStatus(ex);\n        logger.error(\"Scan and send message failed\", ex);\n      } finally {\n        transaction.complete();\n      }\n    }, databaseScanInterval, databaseScanInterval, TimeUnit.MILLISECONDS);\n\n  }\n\n  /**\n   * add message listeners for release message\n   * @param listener\n   */\n  public void addMessageListener(ReleaseMessageListener listener) {\n    if (!listeners.contains(listener)) {\n      listeners.add(listener);\n    }\n  }\n\n  /**\n   * Scan messages, continue scanning until there is no more messages\n   */\n  private void scanMessages() {\n    boolean hasMoreMessages = true;\n    while (hasMoreMessages && !Thread.currentThread().isInterrupted()) {\n      hasMoreMessages = scanAndSendMessages();\n    }\n  }\n\n  /**\n   * scan messages and send\n   *\n   * @return whether there are more messages\n   */\n  private boolean scanAndSendMessages() {\n    //current batch is 500\n    List<ReleaseMessage> releaseMessages =\n        releaseMessageRepository.findFirst500ByIdGreaterThanOrderByIdAsc(maxIdScanned);\n    if (CollectionUtils.isEmpty(releaseMessages)) {\n      return false;\n    }\n    fireMessageScanned(releaseMessages);\n    int messageScanned = releaseMessages.size();\n    maxIdScanned = releaseMessages.get(messageScanned - 1).getId();\n    return messageScanned == 500;\n  }\n\n  /**\n   * find largest message id as the current start point\n   * @return current largest message id\n   */\n  private long loadLargestMessageId() {\n    ReleaseMessage releaseMessage = releaseMessageRepository.findTopByOrderByIdDesc();\n    return releaseMessage == null ? 0 : releaseMessage.getId();\n  }\n\n  /**\n   * Notify listeners with messages loaded\n   * @param messages\n   */\n  private void fireMessageScanned(List<ReleaseMessage> messages) {\n    for (ReleaseMessage message : messages) {\n      for (ReleaseMessageListener listener : listeners) {\n        try {\n          listener.handleMessage(message, Topics.APOLLO_RELEASE_TOPIC);\n        } catch (Throwable ex) {\n          Tracer.logError(ex);\n          logger.error(\"Failed to invoke message listener {}\", listener.getClass(), ex);\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/message/Topics.java",
    "content": "package com.ctrip.framework.apollo.biz.message;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class Topics {\n  public static final String APOLLO_RELEASE_TOPIC = \"apollo-release\";\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/AppNamespaceRepository.java",
    "content": "package com.ctrip.framework.apollo.biz.repository;\n\nimport com.ctrip.framework.apollo.common.entity.AppNamespace;\n\nimport org.springframework.data.repository.PagingAndSortingRepository;\n\nimport java.util.List;\nimport java.util.Set;\n\n\npublic interface AppNamespaceRepository extends PagingAndSortingRepository<AppNamespace, Long>{\n\n  AppNamespace findByAppIdAndName(String appId, String namespaceName);\n\n  List<AppNamespace> findByAppIdAndNameIn(String appId, Set<String> namespaceNames);\n\n  AppNamespace findByNameAndIsPublicTrue(String namespaceName);\n\n  List<AppNamespace> findByNameInAndIsPublicTrue(Set<String> namespaceNames);\n\n  List<AppNamespace> findByAppIdAndIsPublic(String appId, boolean isPublic);\n\n  List<AppNamespace> findByAppId(String appId);\n\n  List<AppNamespace> findFirst500ByIdGreaterThanOrderByIdAsc(long id);\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/AppRepository.java",
    "content": "package com.ctrip.framework.apollo.biz.repository;\n\nimport com.ctrip.framework.apollo.common.entity.App;\n\nimport org.springframework.data.jpa.repository.Query;\nimport org.springframework.data.repository.PagingAndSortingRepository;\nimport org.springframework.data.repository.query.Param;\n\nimport java.util.List;\n\npublic interface AppRepository extends PagingAndSortingRepository<App, Long> {\n\n  @Query(\"SELECT a from App a WHERE a.name LIKE %:name%\")\n  List<App> findByName(@Param(\"name\") String name);\n\n  App findByAppId(String appId);\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/AuditRepository.java",
    "content": "package com.ctrip.framework.apollo.biz.repository;\n\nimport com.ctrip.framework.apollo.biz.entity.Audit;\n\nimport org.springframework.data.jpa.repository.Query;\nimport org.springframework.data.repository.PagingAndSortingRepository;\nimport org.springframework.data.repository.query.Param;\n\nimport java.util.List;\n\npublic interface AuditRepository extends PagingAndSortingRepository<Audit, Long> {\n\n  @Query(\"SELECT a from Audit a WHERE a.dataChangeCreatedBy = :owner\")\n  List<Audit> findByOwner(@Param(\"owner\") String owner);\n\n  @Query(\"SELECT a from Audit a WHERE a.dataChangeCreatedBy = :owner AND a.entityName =:entity AND a.opName = :op\")\n  List<Audit> findAudits(@Param(\"owner\") String owner, @Param(\"entity\") String entity,\n      @Param(\"op\") String op);\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/ClusterRepository.java",
    "content": "package com.ctrip.framework.apollo.biz.repository;\n\n\nimport com.ctrip.framework.apollo.biz.entity.Cluster;\n\nimport org.springframework.data.repository.PagingAndSortingRepository;\n\nimport java.util.List;\n\npublic interface ClusterRepository extends PagingAndSortingRepository<Cluster, Long> {\n\n  List<Cluster> findByAppIdAndParentClusterId(String appId, Long parentClusterId);\n\n  List<Cluster> findByAppId(String appId);\n\n  Cluster findByAppIdAndName(String appId, String name);\n\n  List<Cluster> findByParentClusterId(Long parentClusterId);\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/CommitRepository.java",
    "content": "package com.ctrip.framework.apollo.biz.repository;\n\nimport com.ctrip.framework.apollo.biz.entity.Commit;\n\nimport org.springframework.data.domain.Pageable;\nimport org.springframework.data.jpa.repository.Modifying;\nimport org.springframework.data.jpa.repository.Query;\nimport org.springframework.data.repository.PagingAndSortingRepository;\n\nimport java.util.List;\n\npublic interface CommitRepository extends PagingAndSortingRepository<Commit, Long> {\n\n  List<Commit> findByAppIdAndClusterNameAndNamespaceNameOrderByIdDesc(String appId, String clusterName,\n                                                                      String namespaceName, Pageable pageable);\n\n  @Modifying\n  @Query(\"update Commit set isdeleted=1,DataChange_LastModifiedBy = ?4 where appId=?1 and clusterName=?2 and namespaceName = ?3\")\n  int batchDelete(String appId, String clusterName, String namespaceName, String operator);\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/GrayReleaseRuleRepository.java",
    "content": "package com.ctrip.framework.apollo.biz.repository;\n\nimport com.ctrip.framework.apollo.biz.entity.GrayReleaseRule;\n\nimport org.springframework.data.repository.PagingAndSortingRepository;\n\nimport java.util.List;\n\n\npublic interface GrayReleaseRuleRepository extends PagingAndSortingRepository<GrayReleaseRule, Long> {\n\n  GrayReleaseRule findTopByAppIdAndClusterNameAndNamespaceNameAndBranchNameOrderByIdDesc(String appId, String clusterName,\n                                                                                         String namespaceName, String branchName);\n\n  List<GrayReleaseRule> findByAppIdAndClusterNameAndNamespaceName(String appId,\n                                                               String clusterName, String namespaceName);\n\n  List<GrayReleaseRule> findFirst500ByIdGreaterThanOrderByIdAsc(Long id);\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/InstanceConfigRepository.java",
    "content": "package com.ctrip.framework.apollo.biz.repository;\n\nimport com.ctrip.framework.apollo.biz.entity.InstanceConfig;\n\nimport org.springframework.data.domain.Page;\nimport org.springframework.data.domain.Pageable;\nimport org.springframework.data.jpa.repository.Modifying;\nimport org.springframework.data.jpa.repository.Query;\nimport org.springframework.data.repository.PagingAndSortingRepository;\nimport org.springframework.data.repository.query.Param;\n\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Set;\n\npublic interface InstanceConfigRepository extends PagingAndSortingRepository<InstanceConfig, Long> {\n\n  InstanceConfig findByInstanceIdAndConfigAppIdAndConfigNamespaceName(long instanceId, String\n      configAppId, String configNamespaceName);\n\n  Page<InstanceConfig> findByReleaseKeyAndDataChangeLastModifiedTimeAfter(String releaseKey, Date\n      validDate, Pageable pageable);\n\n  Page<InstanceConfig> findByConfigAppIdAndConfigClusterNameAndConfigNamespaceNameAndDataChangeLastModifiedTimeAfter(\n      String appId, String clusterName, String namespaceName, Date validDate, Pageable pageable);\n\n  List<InstanceConfig> findByConfigAppIdAndConfigClusterNameAndConfigNamespaceNameAndDataChangeLastModifiedTimeAfterAndReleaseKeyNotIn(\n      String appId, String clusterName, String namespaceName, Date validDate, Set<String> releaseKey);\n\n  @Modifying\n  @Query(\"delete from InstanceConfig  where ConfigAppId=?1 and ConfigClusterName=?2 and ConfigNamespaceName = ?3\")\n  int batchDelete(String appId, String clusterName, String namespaceName);\n\n  @Query(\n      value = \"select b.Id from `InstanceConfig` a inner join `Instance` b on b.Id =\" +\n          \" a.`InstanceId` where a.`ConfigAppId` = :configAppId and a.`ConfigClusterName` = \" +\n          \":clusterName and a.`ConfigNamespaceName` = :namespaceName and a.`DataChange_LastTime` \" +\n          \"> :validDate and b.`AppId` = :instanceAppId and ?#{#pageable.pageSize} > 0\",\n      countQuery = \"select count(1) from `InstanceConfig` a inner join `Instance` b on b.id =\" +\n          \" a.`InstanceId` where a.`ConfigAppId` = :configAppId and a.`ConfigClusterName` = \" +\n          \":clusterName and a.`ConfigNamespaceName` = :namespaceName and a.`DataChange_LastTime` \" +\n          \"> :validDate and b.`AppId` = :instanceAppId\",\n      nativeQuery = true)\n  Page<Object[]> findInstanceIdsByNamespaceAndInstanceAppId(\n      @Param(\"instanceAppId\") String instanceAppId, @Param(\"configAppId\") String configAppId,\n      @Param(\"clusterName\") String clusterName, @Param(\"namespaceName\") String namespaceName,\n      @Param(\"validDate\") Date validDate, Pageable pageable);\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/InstanceRepository.java",
    "content": "package com.ctrip.framework.apollo.biz.repository;\n\nimport com.ctrip.framework.apollo.biz.entity.Instance;\n\nimport org.springframework.data.repository.PagingAndSortingRepository;\n\npublic interface InstanceRepository extends PagingAndSortingRepository<Instance, Long> {\n  Instance findByAppIdAndClusterNameAndDataCenterAndIp(String appId, String clusterName, String dataCenter, String ip);\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/ItemRepository.java",
    "content": "package com.ctrip.framework.apollo.biz.repository;\n\nimport com.ctrip.framework.apollo.biz.entity.Item;\n\nimport org.springframework.data.jpa.repository.Modifying;\nimport org.springframework.data.jpa.repository.Query;\nimport org.springframework.data.repository.PagingAndSortingRepository;\n\nimport java.util.Date;\nimport java.util.List;\n\npublic interface ItemRepository extends PagingAndSortingRepository<Item, Long> {\n\n  Item findByNamespaceIdAndKey(Long namespaceId, String key);\n\n  List<Item> findByNamespaceIdOrderByLineNumAsc(Long namespaceId);\n\n  List<Item> findByNamespaceId(Long namespaceId);\n\n  List<Item> findByNamespaceIdAndDataChangeLastModifiedTimeGreaterThan(Long namespaceId, Date date);\n\n  Item findFirst1ByNamespaceIdOrderByLineNumDesc(Long namespaceId);\n\n  @Modifying\n  @Query(\"update Item set isdeleted=1,DataChange_LastModifiedBy = ?2 where namespaceId = ?1\")\n  int deleteByNamespaceId(long namespaceId, String operator);\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/NamespaceLockRepository.java",
    "content": "package com.ctrip.framework.apollo.biz.repository;\n\nimport com.ctrip.framework.apollo.biz.entity.NamespaceLock;\n\nimport org.springframework.data.repository.PagingAndSortingRepository;\n\npublic interface NamespaceLockRepository extends PagingAndSortingRepository<NamespaceLock, Long> {\n\n  NamespaceLock findByNamespaceId(Long namespaceId);\n\n  Long deleteByNamespaceId(Long namespaceId);\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/NamespaceRepository.java",
    "content": "package com.ctrip.framework.apollo.biz.repository;\n\nimport com.ctrip.framework.apollo.biz.entity.Namespace;\n\nimport org.springframework.data.domain.Page;\nimport org.springframework.data.domain.Pageable;\nimport org.springframework.data.jpa.repository.Modifying;\nimport org.springframework.data.jpa.repository.Query;\nimport org.springframework.data.repository.PagingAndSortingRepository;\n\nimport java.util.List;\n\npublic interface NamespaceRepository extends PagingAndSortingRepository<Namespace, Long> {\n\n  List<Namespace> findByAppIdAndClusterNameOrderByIdAsc(String appId, String clusterName);\n\n  Namespace findByAppIdAndClusterNameAndNamespaceName(String appId, String clusterName, String namespaceName);\n\n  @Modifying\n  @Query(\"update Namespace set isdeleted=1,DataChange_LastModifiedBy = ?3 where appId=?1 and clusterName=?2\")\n  int batchDelete(String appId, String clusterName, String operator);\n\n  List<Namespace> findByAppIdAndNamespaceName(String appId, String namespaceName);\n\n  List<Namespace> findByNamespaceName(String namespaceName, Pageable page);\n\n  int countByNamespaceNameAndAppIdNot(String namespaceName, String appId);\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/PrivilegeRepository.java",
    "content": "package com.ctrip.framework.apollo.biz.repository;\n\nimport com.ctrip.framework.apollo.biz.entity.Privilege;\n\nimport org.springframework.data.repository.PagingAndSortingRepository;\n\nimport java.util.List;\n\npublic interface PrivilegeRepository extends PagingAndSortingRepository<Privilege, Long> {\n\n  List<Privilege> findByNamespaceId(long namespaceId);\n\n  List<Privilege> findByNamespaceIdAndPrivilType(long namespaceId, String privilType);\n\n  Privilege findByNamespaceIdAndNameAndPrivilType(long namespaceId, String name, String privilType);\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/ReleaseHistoryRepository.java",
    "content": "package com.ctrip.framework.apollo.biz.repository;\n\nimport com.ctrip.framework.apollo.biz.entity.ReleaseHistory;\n\nimport org.springframework.data.domain.Page;\nimport org.springframework.data.domain.Pageable;\nimport org.springframework.data.jpa.repository.Modifying;\nimport org.springframework.data.jpa.repository.Query;\nimport org.springframework.data.repository.PagingAndSortingRepository;\n\nimport java.util.List;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic interface ReleaseHistoryRepository extends PagingAndSortingRepository<ReleaseHistory, Long> {\n  Page<ReleaseHistory> findByAppIdAndClusterNameAndNamespaceNameOrderByIdDesc(String appId, String\n      clusterName, String namespaceName, Pageable pageable);\n\n  Page<ReleaseHistory> findByReleaseIdAndOperationOrderByIdDesc(long releaseId, int operation, Pageable pageable);\n\n  Page<ReleaseHistory> findByPreviousReleaseIdAndOperationOrderByIdDesc(long previousReleaseId, int operation, Pageable pageable);\n\n  @Modifying\n  @Query(\"update ReleaseHistory set isdeleted=1,DataChange_LastModifiedBy = ?4 where appId=?1 and clusterName=?2 and namespaceName = ?3\")\n  int batchDelete(String appId, String clusterName, String namespaceName, String operator);\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/ReleaseMessageRepository.java",
    "content": "package com.ctrip.framework.apollo.biz.repository;\n\nimport com.ctrip.framework.apollo.biz.entity.ReleaseMessage;\n\nimport org.springframework.data.jpa.repository.Query;\nimport org.springframework.data.repository.PagingAndSortingRepository;\nimport org.springframework.data.repository.query.Param;\n\nimport java.util.Collection;\nimport java.util.List;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic interface ReleaseMessageRepository extends PagingAndSortingRepository<ReleaseMessage, Long> {\n  List<ReleaseMessage> findFirst500ByIdGreaterThanOrderByIdAsc(Long id);\n\n  ReleaseMessage findTopByOrderByIdDesc();\n\n  ReleaseMessage findTopByMessageInOrderByIdDesc(Collection<String> messages);\n\n  List<ReleaseMessage> findFirst100ByMessageAndIdLessThanOrderByIdAsc(String message, Long id);\n\n  @Query(\"select message, max(id) as id from ReleaseMessage where message in :messages group by message\")\n  List<Object[]> findLatestReleaseMessagesGroupByMessages(@Param(\"messages\") Collection<String> messages);\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/ReleaseRepository.java",
    "content": "package com.ctrip.framework.apollo.biz.repository;\n\nimport com.ctrip.framework.apollo.biz.entity.Release;\n\nimport org.springframework.data.domain.Pageable;\nimport org.springframework.data.jpa.repository.Modifying;\nimport org.springframework.data.jpa.repository.Query;\nimport org.springframework.data.repository.PagingAndSortingRepository;\nimport org.springframework.data.repository.query.Param;\n\nimport java.util.List;\nimport java.util.Set;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic interface ReleaseRepository extends PagingAndSortingRepository<Release, Long> {\n\n  Release findFirstByAppIdAndClusterNameAndNamespaceNameAndIsAbandonedFalseOrderByIdDesc(@Param(\"appId\") String appId, @Param(\"clusterName\") String clusterName,\n                                                                                         @Param(\"namespaceName\") String namespaceName);\n\n  Release findByIdAndIsAbandonedFalse(long id);\n\n  List<Release> findByAppIdAndClusterNameAndNamespaceNameOrderByIdDesc(String appId, String clusterName, String namespaceName, Pageable page);\n\n  List<Release> findByAppIdAndClusterNameAndNamespaceNameAndIsAbandonedFalseOrderByIdDesc(String appId, String clusterName, String namespaceName, Pageable page);\n\n  List<Release> findByReleaseKeyIn(Set<String> releaseKey);\n\n  List<Release> findByIdIn(Set<Long> releaseIds);\n\n  @Modifying\n  @Query(\"update Release set isdeleted=1,DataChange_LastModifiedBy = ?4 where appId=?1 and clusterName=?2 and namespaceName = ?3\")\n  int batchDelete(String appId, String clusterName, String namespaceName, String operator);\n\n  // For release history conversion program, need to delete after conversion it done\n  List<Release> findByAppIdAndClusterNameAndNamespaceNameOrderByIdAsc(String appId, String clusterName, String namespaceName);\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/ServerConfigRepository.java",
    "content": "package com.ctrip.framework.apollo.biz.repository;\n\nimport com.ctrip.framework.apollo.biz.entity.ServerConfig;\n\nimport org.springframework.data.repository.PagingAndSortingRepository;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic interface ServerConfigRepository extends PagingAndSortingRepository<ServerConfig, Long> {\n  ServerConfig findTopByKeyAndCluster(String key, String cluster);\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/AdminService.java",
    "content": "package com.ctrip.framework.apollo.biz.service;\n\nimport com.ctrip.framework.apollo.common.entity.App;\nimport com.ctrip.framework.apollo.core.ConfigConsts;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\n@Service\npublic class AdminService {\n\n  @Autowired\n  private AppService appService;\n  @Autowired\n  private AppNamespaceService appNamespaceService;\n  @Autowired\n  private ClusterService clusterService;\n  @Autowired\n  private NamespaceService namespaceService;\n\n  @Transactional\n  public App createNewApp(App app) {\n    String createBy = app.getDataChangeCreatedBy();\n    App createdApp = appService.save(app);\n\n    String appId = createdApp.getAppId();\n\n    appNamespaceService.createDefaultAppNamespace(appId, createBy);\n\n    clusterService.createDefaultCluster(appId, createBy);\n\n    namespaceService.instanceOfAppNamespaces(appId, ConfigConsts.CLUSTER_NAME_DEFAULT, createBy);\n\n    return app;\n  }\n\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/AppNamespaceService.java",
    "content": "package com.ctrip.framework.apollo.biz.service;\n\nimport com.google.common.base.Preconditions;\nimport com.google.common.base.Strings;\n\nimport com.ctrip.framework.apollo.biz.entity.Audit;\nimport com.ctrip.framework.apollo.biz.entity.Cluster;\nimport com.ctrip.framework.apollo.biz.entity.Namespace;\nimport com.ctrip.framework.apollo.biz.repository.AppNamespaceRepository;\nimport com.ctrip.framework.apollo.common.entity.AppNamespace;\nimport com.ctrip.framework.apollo.common.exception.ServiceException;\nimport com.ctrip.framework.apollo.common.utils.BeanUtils;\nimport com.ctrip.framework.apollo.core.ConfigConsts;\nimport com.ctrip.framework.apollo.core.enums.ConfigFileFormat;\nimport com.ctrip.framework.apollo.core.utils.StringUtils;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.Set;\n\n@Service\npublic class AppNamespaceService {\n\n  @Autowired\n  private AppNamespaceRepository appNamespaceRepository;\n  @Autowired\n  private NamespaceService namespaceService;\n  @Autowired\n  private ClusterService clusterService;\n  @Autowired\n  private AuditService auditService;\n\n  public boolean isAppNamespaceNameUnique(String appId, String namespaceName) {\n    Objects.requireNonNull(appId, \"AppId must not be null\");\n    Objects.requireNonNull(namespaceName, \"Namespace must not be null\");\n    return Objects.isNull(appNamespaceRepository.findByAppIdAndName(appId, namespaceName));\n  }\n\n  public AppNamespace findPublicNamespaceByName(String namespaceName) {\n    Preconditions.checkArgument(namespaceName != null, \"Namespace must not be null\");\n    return appNamespaceRepository.findByNameAndIsPublicTrue(namespaceName);\n  }\n\n  public List<AppNamespace> findByAppId(String appId) {\n    return appNamespaceRepository.findByAppId(appId);\n  }\n\n  public List<AppNamespace> findPublicNamespacesByNames(Set<String> namespaceNames) {\n    if (namespaceNames == null || namespaceNames.isEmpty()) {\n      return Collections.emptyList();\n    }\n\n    return appNamespaceRepository.findByNameInAndIsPublicTrue(namespaceNames);\n  }\n\n  public List<AppNamespace> findPrivateAppNamespace(String appId) {\n    return appNamespaceRepository.findByAppIdAndIsPublic(appId, false);\n  }\n\n  public AppNamespace findOne(String appId, String namespaceName) {\n    Preconditions\n        .checkArgument(!StringUtils.isContainEmpty(appId, namespaceName), \"appId or Namespace must not be null\");\n    return appNamespaceRepository.findByAppIdAndName(appId, namespaceName);\n  }\n\n  public List<AppNamespace> findByAppIdAndNamespaces(String appId, Set<String> namespaceNames) {\n    Preconditions.checkArgument(!Strings.isNullOrEmpty(appId), \"appId must not be null\");\n    if (namespaceNames == null || namespaceNames.isEmpty()) {\n      return Collections.emptyList();\n    }\n    return appNamespaceRepository.findByAppIdAndNameIn(appId, namespaceNames);\n  }\n\n  @Transactional\n  public void createDefaultAppNamespace(String appId, String createBy) {\n    if (!isAppNamespaceNameUnique(appId, ConfigConsts.NAMESPACE_APPLICATION)) {\n      throw new ServiceException(\"appnamespace not unique\");\n    }\n    AppNamespace appNs = new AppNamespace();\n    appNs.setAppId(appId);\n    appNs.setName(ConfigConsts.NAMESPACE_APPLICATION);\n    appNs.setComment(\"default app namespace\");\n    appNs.setFormat(ConfigFileFormat.Properties.getValue());\n    appNs.setDataChangeCreatedBy(createBy);\n    appNs.setDataChangeLastModifiedBy(createBy);\n    appNamespaceRepository.save(appNs);\n\n    auditService.audit(AppNamespace.class.getSimpleName(), appNs.getId(), Audit.OP.INSERT,\n                       createBy);\n  }\n\n  @Transactional\n  public AppNamespace createAppNamespace(AppNamespace appNamespace) {\n    String createBy = appNamespace.getDataChangeCreatedBy();\n    if (!isAppNamespaceNameUnique(appNamespace.getAppId(), appNamespace.getName())) {\n      throw new ServiceException(\"appnamespace not unique\");\n    }\n    appNamespace.setId(0);//protection\n    appNamespace.setDataChangeCreatedBy(createBy);\n    appNamespace.setDataChangeLastModifiedBy(createBy);\n\n    appNamespace = appNamespaceRepository.save(appNamespace);\n\n    instanceOfAppNamespaceInAllCluster(appNamespace.getAppId(), appNamespace.getName(), createBy);\n\n    auditService.audit(AppNamespace.class.getSimpleName(), appNamespace.getId(), Audit.OP.INSERT, createBy);\n    return appNamespace;\n  }\n\n  public AppNamespace update(AppNamespace appNamespace) {\n    AppNamespace managedNs = appNamespaceRepository.findByAppIdAndName(appNamespace.getAppId(), appNamespace.getName());\n    BeanUtils.copyEntityProperties(appNamespace, managedNs);\n    managedNs = appNamespaceRepository.save(managedNs);\n\n    auditService.audit(AppNamespace.class.getSimpleName(), managedNs.getId(), Audit.OP.UPDATE,\n                       managedNs.getDataChangeLastModifiedBy());\n\n    return managedNs;\n  }\n\n  private void instanceOfAppNamespaceInAllCluster(String appId, String namespaceName, String createBy) {\n    List<Cluster> clusters = clusterService.findParentClusters(appId);\n\n    for (Cluster cluster : clusters) {\n      Namespace namespace = new Namespace();\n      namespace.setClusterName(cluster.getName());\n      namespace.setAppId(appId);\n      namespace.setNamespaceName(namespaceName);\n      namespace.setDataChangeCreatedBy(createBy);\n      namespace.setDataChangeLastModifiedBy(createBy);\n\n      namespaceService.save(namespace);\n    }\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/AppService.java",
    "content": "package com.ctrip.framework.apollo.biz.service;\n\nimport com.ctrip.framework.apollo.biz.entity.Audit;\nimport com.ctrip.framework.apollo.biz.repository.AppRepository;\nimport com.ctrip.framework.apollo.common.entity.App;\nimport com.ctrip.framework.apollo.common.exception.BadRequestException;\nimport com.ctrip.framework.apollo.common.exception.ServiceException;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.data.domain.Page;\nimport org.springframework.data.domain.Pageable;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\nimport java.util.List;\nimport java.util.Objects;\n\n@Service\npublic class AppService {\n\n  @Autowired\n  private AppRepository appRepository;\n\n  @Autowired\n  private AuditService auditService;\n\n  public boolean isAppIdUnique(String appId) {\n    Objects.requireNonNull(appId, \"AppId must not be null\");\n    return Objects.isNull(appRepository.findByAppId(appId));\n  }\n  \n  @Transactional\n  public void delete(long id, String operator) {\n    App app = appRepository.findOne(id);\n    if (app == null) {\n      return;\n    }\n\n    app.setDeleted(true);\n    app.setDataChangeLastModifiedBy(operator);\n    appRepository.save(app);\n\n    auditService.audit(App.class.getSimpleName(), id, Audit.OP.DELETE, operator);\n  }\n\n  public List<App> findAll(Pageable pageable) {\n    Page<App> page = appRepository.findAll(pageable);\n    return page.getContent();\n  }\n\n  public List<App> findByName(String name) {\n    return appRepository.findByName(name);\n  }\n\n  public App findOne(String appId) {\n    return appRepository.findByAppId(appId);\n  }\n\n  @Transactional\n  public App save(App entity) {\n    if (!isAppIdUnique(entity.getAppId())) {\n      throw new ServiceException(\"appId not unique\");\n    }\n    entity.setId(0);//protection\n    App app = appRepository.save(entity);\n    \n    auditService.audit(App.class.getSimpleName(), app.getId(), Audit.OP.INSERT,\n        app.getDataChangeCreatedBy());\n    \n    return app;\n  }\n\n  @Transactional\n  public void update(App app) {\n    String appId = app.getAppId();\n\n    App managedApp = appRepository.findByAppId(appId);\n    if (managedApp == null) {\n      throw new BadRequestException(String.format(\"App not exists. AppId = %s\", appId));\n    }\n\n    managedApp.setName(app.getName());\n    managedApp.setOrgId(app.getOrgId());\n    managedApp.setOrgName(app.getOrgName());\n    managedApp.setOwnerName(app.getOwnerName());\n    managedApp.setOwnerEmail(app.getOwnerEmail());\n    managedApp.setDataChangeLastModifiedBy(app.getDataChangeLastModifiedBy());\n\n    managedApp = appRepository.save(managedApp);\n    \n    auditService.audit(App.class.getSimpleName(), managedApp.getId(), Audit.OP.UPDATE,\n        managedApp.getDataChangeLastModifiedBy());\n    \n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/AuditService.java",
    "content": "package com.ctrip.framework.apollo.biz.service;\n\nimport com.ctrip.framework.apollo.biz.entity.Audit;\nimport com.ctrip.framework.apollo.biz.repository.AuditRepository;\n\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@Service\npublic class AuditService {\n\n  @Autowired\n  private AuditRepository auditRepository;\n\n  List<Audit> findByOwner(String owner) {\n    return auditRepository.findByOwner(owner);\n  }\n\n  List<Audit> find(String owner, String entity, String op) {\n    return auditRepository.findAudits(owner, entity, op);\n  }\n\n  @Transactional\n  void audit(String entityName, Long entityId, Audit.OP op, String owner) {\n    Audit audit = new Audit();\n    audit.setEntityName(entityName);\n    audit.setEntityId(entityId);\n    audit.setOpName(op.name());\n    audit.setDataChangeCreatedBy(owner);\n    auditRepository.save(audit);\n  }\n  \n  @Transactional\n  void audit(Audit audit){\n    auditRepository.save(audit);\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/BizDBPropertySource.java",
    "content": "package com.ctrip.framework.apollo.biz.service;\n\nimport com.google.common.base.Strings;\nimport com.google.common.collect.Maps;\n\nimport com.ctrip.framework.apollo.biz.entity.ServerConfig;\nimport com.ctrip.framework.apollo.biz.repository.ServerConfigRepository;\nimport com.ctrip.framework.apollo.common.config.RefreshablePropertySource;\nimport com.ctrip.framework.apollo.core.ConfigConsts;\nimport com.ctrip.framework.foundation.Foundation;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport java.util.Map;\nimport java.util.Objects;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@Component\npublic class BizDBPropertySource extends RefreshablePropertySource {\n\n  private static final Logger logger = LoggerFactory.getLogger(BizDBPropertySource.class);\n\n  @Autowired\n  private ServerConfigRepository serverConfigRepository;\n\n  public BizDBPropertySource(String name, Map<String, Object> source) {\n    super(name, source);\n  }\n\n  public BizDBPropertySource() {\n    super(\"DBConfig\", Maps.newConcurrentMap());\n  }\n\n  String getCurrentDataCenter() {\n    return Foundation.server().getDataCenter();\n  }\n\n  @Override\n  protected void refresh() {\n    Iterable<ServerConfig> dbConfigs = serverConfigRepository.findAll();\n\n    Map<String, Object> newConfigs = Maps.newHashMap();\n    //default cluster's configs\n    for (ServerConfig config : dbConfigs) {\n      if (Objects.equals(ConfigConsts.CLUSTER_NAME_DEFAULT, config.getCluster())) {\n        newConfigs.put(config.getKey(), config.getValue());\n      }\n    }\n\n    //data center's configs\n    String dataCenter = getCurrentDataCenter();\n    for (ServerConfig config : dbConfigs) {\n      if (Objects.equals(dataCenter, config.getCluster())) {\n        newConfigs.put(config.getKey(), config.getValue());\n      }\n    }\n\n    //cluster's config\n    if (!Strings.isNullOrEmpty(System.getProperty(ConfigConsts.APOLLO_CLUSTER_KEY))) {\n      String cluster = System.getProperty(ConfigConsts.APOLLO_CLUSTER_KEY);\n      for (ServerConfig config : dbConfigs) {\n        if (Objects.equals(cluster, config.getCluster())) {\n          newConfigs.put(config.getKey(), config.getValue());\n        }\n      }\n    }\n\n    //put to environment\n    for (Map.Entry<String, Object> config: newConfigs.entrySet()){\n      String key = config.getKey();\n      Object value = config.getValue();\n\n      if (this.source.get(key) == null) {\n        logger.info(\"Load config from DB : {} = {}\", key, value);\n      } else if (!Objects.equals(this.source.get(key), value)) {\n        logger.info(\"Load config from DB : {} = {}. Old value = {}\", key,\n                    value, this.source.get(key));\n      }\n\n      this.source.put(key, value);\n\n    }\n\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/ClusterService.java",
    "content": "package com.ctrip.framework.apollo.biz.service;\n\nimport com.google.common.base.Strings;\n\nimport com.ctrip.framework.apollo.biz.entity.Audit;\nimport com.ctrip.framework.apollo.biz.entity.Cluster;\nimport com.ctrip.framework.apollo.biz.repository.ClusterRepository;\nimport com.ctrip.framework.apollo.common.exception.BadRequestException;\nimport com.ctrip.framework.apollo.common.exception.ServiceException;\nimport com.ctrip.framework.apollo.common.utils.BeanUtils;\nimport com.ctrip.framework.apollo.core.ConfigConsts;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Objects;\n\n@Service\npublic class ClusterService {\n\n  @Autowired\n  private ClusterRepository clusterRepository;\n  @Autowired\n  private AuditService auditService;\n  @Autowired\n  private NamespaceService namespaceService;\n\n\n  public boolean isClusterNameUnique(String appId, String clusterName) {\n    Objects.requireNonNull(appId, \"AppId must not be null\");\n    Objects.requireNonNull(clusterName, \"ClusterName must not be null\");\n    return Objects.isNull(clusterRepository.findByAppIdAndName(appId, clusterName));\n  }\n\n  public Cluster findOne(String appId, String name) {\n    return clusterRepository.findByAppIdAndName(appId, name);\n  }\n\n  public Cluster findOne(long clusterId) {\n    return clusterRepository.findOne(clusterId);\n  }\n\n  public List<Cluster> findParentClusters(String appId) {\n    if (Strings.isNullOrEmpty(appId)) {\n      return Collections.emptyList();\n    }\n\n    List<Cluster> clusters = clusterRepository.findByAppIdAndParentClusterId(appId, 0L);\n    if (clusters == null) {\n      return Collections.emptyList();\n    }\n\n    Collections.sort(clusters);\n\n    return clusters;\n  }\n\n  @Transactional\n  public Cluster saveWithInstanceOfAppNamespaces(Cluster entity) {\n\n    Cluster savedCluster = saveWithoutInstanceOfAppNamespaces(entity);\n\n    namespaceService.instanceOfAppNamespaces(savedCluster.getAppId(), savedCluster.getName(),\n                                             savedCluster.getDataChangeCreatedBy());\n\n    return savedCluster;\n  }\n\n  @Transactional\n  public Cluster saveWithoutInstanceOfAppNamespaces(Cluster entity) {\n    if (!isClusterNameUnique(entity.getAppId(), entity.getName())) {\n      throw new BadRequestException(\"cluster not unique\");\n    }\n    entity.setId(0);//protection\n    Cluster cluster = clusterRepository.save(entity);\n\n    auditService.audit(Cluster.class.getSimpleName(), cluster.getId(), Audit.OP.INSERT,\n                       cluster.getDataChangeCreatedBy());\n\n    return cluster;\n  }\n\n  @Transactional\n  public void delete(long id, String operator) {\n    Cluster cluster = clusterRepository.findOne(id);\n    if (cluster == null) {\n      throw new BadRequestException(\"cluster not exist\");\n    }\n\n    //delete linked namespaces\n    namespaceService.deleteByAppIdAndClusterName(cluster.getAppId(), cluster.getName(), operator);\n\n    cluster.setDeleted(true);\n    cluster.setDataChangeLastModifiedBy(operator);\n    clusterRepository.save(cluster);\n\n    auditService.audit(Cluster.class.getSimpleName(), id, Audit.OP.DELETE, operator);\n  }\n\n  @Transactional\n  public Cluster update(Cluster cluster) {\n    Cluster managedCluster =\n        clusterRepository.findByAppIdAndName(cluster.getAppId(), cluster.getName());\n    BeanUtils.copyEntityProperties(cluster, managedCluster);\n    managedCluster = clusterRepository.save(managedCluster);\n\n    auditService.audit(Cluster.class.getSimpleName(), managedCluster.getId(), Audit.OP.UPDATE,\n                       managedCluster.getDataChangeLastModifiedBy());\n\n    return managedCluster;\n  }\n\n  @Transactional\n  public void createDefaultCluster(String appId, String createBy) {\n    if (!isClusterNameUnique(appId, ConfigConsts.CLUSTER_NAME_DEFAULT)) {\n      throw new ServiceException(\"cluster not unique\");\n    }\n    Cluster cluster = new Cluster();\n    cluster.setName(ConfigConsts.CLUSTER_NAME_DEFAULT);\n    cluster.setAppId(appId);\n    cluster.setDataChangeCreatedBy(createBy);\n    cluster.setDataChangeLastModifiedBy(createBy);\n    clusterRepository.save(cluster);\n\n    auditService.audit(Cluster.class.getSimpleName(), cluster.getId(), Audit.OP.INSERT, createBy);\n  }\n\n  public List<Cluster> findChildClusters(String appId, String parentClusterName) {\n    Cluster parentCluster = findOne(appId, parentClusterName);\n    if (parentCluster == null) {\n      throw new BadRequestException(\"parent cluster not exist\");\n    }\n\n    return clusterRepository.findByParentClusterId(parentCluster.getId());\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/CommitService.java",
    "content": "package com.ctrip.framework.apollo.biz.service;\n\nimport com.ctrip.framework.apollo.biz.entity.Commit;\nimport com.ctrip.framework.apollo.biz.repository.CommitRepository;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.data.domain.Pageable;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\nimport java.util.List;\n\n@Service\npublic class CommitService {\n\n  @Autowired\n  private CommitRepository commitRepository;\n\n  @Transactional\n  public Commit save(Commit commit){\n    commit.setId(0);//protection\n    return commitRepository.save(commit);\n  }\n\n  public List<Commit> find(String appId, String clusterName, String namespaceName, Pageable page){\n    return commitRepository.findByAppIdAndClusterNameAndNamespaceNameOrderByIdDesc(appId, clusterName, namespaceName, page);\n  }\n\n  @Transactional\n  public int batchDelete(String appId, String clusterName, String namespaceName, String operator){\n    return commitRepository.batchDelete(appId, clusterName, namespaceName, operator);\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/InstanceService.java",
    "content": "package com.ctrip.framework.apollo.biz.service;\n\nimport com.google.common.base.Preconditions;\nimport com.google.common.collect.Lists;\n\nimport com.ctrip.framework.apollo.biz.entity.Instance;\nimport com.ctrip.framework.apollo.biz.entity.InstanceConfig;\nimport com.ctrip.framework.apollo.biz.repository.InstanceConfigRepository;\nimport com.ctrip.framework.apollo.biz.repository.InstanceRepository;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.data.domain.Page;\nimport org.springframework.data.domain.PageImpl;\nimport org.springframework.data.domain.Pageable;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\nimport org.springframework.util.CollectionUtils;\n\nimport java.math.BigInteger;\nimport java.util.Calendar;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Set;\nimport java.util.stream.Collectors;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@Service\npublic class InstanceService {\n  @Autowired\n  private InstanceRepository instanceRepository;\n\n  @Autowired\n  private InstanceConfigRepository instanceConfigRepository;\n\n  public Instance findInstance(String appId, String clusterName, String dataCenter, String ip) {\n    return instanceRepository.findByAppIdAndClusterNameAndDataCenterAndIp(appId, clusterName,\n        dataCenter, ip);\n  }\n\n  public List<Instance> findInstancesByIds(Set<Long> instanceIds) {\n    Iterable<Instance> instances = instanceRepository.findAll(instanceIds);\n    if (instances == null) {\n      return Collections.emptyList();\n    }\n    return Lists.newArrayList(instances);\n  }\n\n  @Transactional\n  public Instance createInstance(Instance instance) {\n    instance.setId(0); //protection\n\n    return instanceRepository.save(instance);\n  }\n\n  public InstanceConfig findInstanceConfig(long instanceId, String configAppId, String\n      configNamespaceName) {\n    return instanceConfigRepository\n        .findByInstanceIdAndConfigAppIdAndConfigNamespaceName(\n            instanceId, configAppId, configNamespaceName);\n  }\n\n  public Page<InstanceConfig> findActiveInstanceConfigsByReleaseKey(String releaseKey, Pageable\n      pageable) {\n    Page<InstanceConfig> instanceConfigs = instanceConfigRepository\n        .findByReleaseKeyAndDataChangeLastModifiedTimeAfter(releaseKey,\n            getValidInstanceConfigDate(), pageable);\n    return instanceConfigs;\n  }\n\n  public Page<Instance> findInstancesByNamespace(String appId, String clusterName, String\n      namespaceName, Pageable pageable) {\n    Page<InstanceConfig> instanceConfigs = instanceConfigRepository.\n        findByConfigAppIdAndConfigClusterNameAndConfigNamespaceNameAndDataChangeLastModifiedTimeAfter(appId, clusterName,\n            namespaceName, getValidInstanceConfigDate(), pageable);\n\n    List<Instance> instances = Collections.emptyList();\n    if (instanceConfigs.hasContent()) {\n      Set<Long> instanceIds = instanceConfigs.getContent().stream().map\n          (InstanceConfig::getInstanceId).collect(Collectors.toSet());\n      instances = findInstancesByIds(instanceIds);\n    }\n\n    return new PageImpl<>(instances, pageable, instanceConfigs.getTotalElements());\n  }\n\n  public Page<Instance> findInstancesByNamespaceAndInstanceAppId(String instanceAppId, String\n      appId, String clusterName, String\n                                                                     namespaceName, Pageable\n                                                                     pageable) {\n    Page<Object[]> instanceIdResult = instanceConfigRepository\n        .findInstanceIdsByNamespaceAndInstanceAppId(instanceAppId, appId, clusterName,\n            namespaceName, getValidInstanceConfigDate(), pageable);\n\n    List<Instance> instances = Collections.emptyList();\n    if (instanceIdResult.hasContent()) {\n      Set<Long> instanceIds = instanceIdResult.getContent().stream().map((Object o) -> {\n        if (o == null) {\n          return null;\n        }\n\n        if (o instanceof Integer) {\n          return ((Integer)o).longValue();\n        }\n\n        if (o instanceof Long) {\n          return (Long) o;\n        }\n\n        //for h2 test\n        if (o instanceof BigInteger) {\n          return ((BigInteger) o).longValue();\n        }\n\n        return null;\n      }).filter((Long value) -> value != null).collect(Collectors.toSet());\n      instances = findInstancesByIds(instanceIds);\n    }\n\n    return new PageImpl<>(instances, pageable, instanceIdResult.getTotalElements());\n  }\n\n  public List<InstanceConfig> findInstanceConfigsByNamespaceWithReleaseKeysNotIn(String appId,\n                                                                                 String clusterName,\n                                                                                 String\n                                                                                     namespaceName,\n                                                                                 Set<String>\n                                                                                     releaseKeysNotIn) {\n    List<InstanceConfig> instanceConfigs = instanceConfigRepository.\n        findByConfigAppIdAndConfigClusterNameAndConfigNamespaceNameAndDataChangeLastModifiedTimeAfterAndReleaseKeyNotIn(appId, clusterName,\n            namespaceName, getValidInstanceConfigDate(), releaseKeysNotIn);\n\n    if (CollectionUtils.isEmpty(instanceConfigs)) {\n      return Collections.emptyList();\n    }\n\n    return instanceConfigs;\n  }\n\n  /**\n   * Currently the instance config is expired by 1 day, add one more hour to avoid possible time\n   * difference\n   */\n  private Date getValidInstanceConfigDate() {\n    Calendar cal = Calendar.getInstance();\n    cal.add(Calendar.DATE, -1);\n    cal.add(Calendar.HOUR, -1);\n    return cal.getTime();\n  }\n\n  @Transactional\n  public InstanceConfig createInstanceConfig(InstanceConfig instanceConfig) {\n    instanceConfig.setId(0); //protection\n\n    return instanceConfigRepository.save(instanceConfig);\n  }\n\n  @Transactional\n  public InstanceConfig updateInstanceConfig(InstanceConfig instanceConfig) {\n    InstanceConfig existedInstanceConfig = instanceConfigRepository.findOne(instanceConfig.getId());\n    Preconditions.checkArgument(existedInstanceConfig != null, String.format(\n        \"Instance config %d doesn't exist\", instanceConfig.getId()));\n\n    existedInstanceConfig.setConfigClusterName(instanceConfig.getConfigClusterName());\n    existedInstanceConfig.setReleaseKey(instanceConfig.getReleaseKey());\n    existedInstanceConfig.setReleaseDeliveryTime(instanceConfig.getReleaseDeliveryTime());\n    existedInstanceConfig.setDataChangeLastModifiedTime(instanceConfig\n        .getDataChangeLastModifiedTime());\n\n    return instanceConfigRepository.save(existedInstanceConfig);\n  }\n\n  @Transactional\n  public int batchDeleteInstanceConfig(String configAppId, String configClusterName, String configNamespaceName){\n    return instanceConfigRepository.batchDelete(configAppId, configClusterName, configNamespaceName);\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/ItemService.java",
    "content": "package com.ctrip.framework.apollo.biz.service;\n\n\nimport com.ctrip.framework.apollo.biz.config.BizConfig;\nimport com.ctrip.framework.apollo.biz.entity.Audit;\nimport com.ctrip.framework.apollo.biz.entity.Item;\nimport com.ctrip.framework.apollo.biz.entity.Namespace;\nimport com.ctrip.framework.apollo.biz.repository.ItemRepository;\nimport com.ctrip.framework.apollo.common.exception.BadRequestException;\nimport com.ctrip.framework.apollo.common.exception.NotFoundException;\nimport com.ctrip.framework.apollo.common.utils.BeanUtils;\nimport com.ctrip.framework.apollo.core.utils.StringUtils;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Map;\n\n@Service\npublic class ItemService {\n\n  @Autowired\n  private ItemRepository itemRepository;\n\n  @Autowired\n  private NamespaceService namespaceService;\n\n  @Autowired\n  private AuditService auditService;\n\n  @Autowired\n  private BizConfig bizConfig;\n\n\n  @Transactional\n  public Item delete(long id, String operator) {\n    Item item = itemRepository.findOne(id);\n    if (item == null) {\n      throw new IllegalArgumentException(\"item not exist. ID:\" + id);\n    }\n\n    item.setDeleted(true);\n    item.setDataChangeLastModifiedBy(operator);\n    Item deletedItem = itemRepository.save(item);\n\n    auditService.audit(Item.class.getSimpleName(), id, Audit.OP.DELETE, operator);\n    return deletedItem;\n  }\n\n  @Transactional\n  public int batchDelete(long namespaceId, String operator) {\n    return itemRepository.deleteByNamespaceId(namespaceId, operator);\n\n  }\n\n  public Item findOne(String appId, String clusterName, String namespaceName, String key) {\n    Namespace namespace = namespaceService.findOne(appId, clusterName, namespaceName);\n    if (namespace == null) {\n      throw new NotFoundException(\n          String.format(\"namespace not found for %s %s %s\", appId, clusterName, namespaceName));\n    }\n    Item item = itemRepository.findByNamespaceIdAndKey(namespace.getId(), key);\n    return item;\n  }\n\n  public Item findLastOne(String appId, String clusterName, String namespaceName) {\n    Namespace namespace = namespaceService.findOne(appId, clusterName, namespaceName);\n    if (namespace == null) {\n      throw new NotFoundException(\n          String.format(\"namespace not found for %s %s %s\", appId, clusterName, namespaceName));\n    }\n    return findLastOne(namespace.getId());\n  }\n\n  public Item findLastOne(long namespaceId) {\n    return itemRepository.findFirst1ByNamespaceIdOrderByLineNumDesc(namespaceId);\n  }\n\n  public Item findOne(long itemId) {\n    Item item = itemRepository.findOne(itemId);\n    return item;\n  }\n\n  public List<Item> findItemsWithoutOrdered(Long namespaceId) {\n    List<Item> items = itemRepository.findByNamespaceId(namespaceId);\n    if (items == null) {\n      return Collections.emptyList();\n    }\n    return items;\n  }\n\n  public List<Item> findItemsWithoutOrdered(String appId, String clusterName, String namespaceName) {\n    Namespace namespace = namespaceService.findOne(appId, clusterName, namespaceName);\n    if (namespace != null) {\n      return findItemsWithoutOrdered(namespace.getId());\n    } else {\n      return Collections.emptyList();\n    }\n  }\n\n  public List<Item> findItemsWithOrdered(Long namespaceId) {\n    List<Item> items = itemRepository.findByNamespaceIdOrderByLineNumAsc(namespaceId);\n    if (items == null) {\n      return Collections.emptyList();\n    }\n    return items;\n  }\n\n  public List<Item> findItemsWithOrdered(String appId, String clusterName, String namespaceName) {\n    Namespace namespace = namespaceService.findOne(appId, clusterName, namespaceName);\n    if (namespace != null) {\n      return findItemsWithOrdered(namespace.getId());\n    } else {\n      return Collections.emptyList();\n    }\n  }\n\n  public List<Item> findItemsModifiedAfterDate(long namespaceId, Date date) {\n    return itemRepository.findByNamespaceIdAndDataChangeLastModifiedTimeGreaterThan(namespaceId, date);\n  }\n\n  @Transactional\n  public Item save(Item entity) {\n    checkItemKeyLength(entity.getKey());\n    checkItemValueLength(entity.getNamespaceId(), entity.getValue());\n\n    entity.setId(0);//protection\n\n    if (entity.getLineNum() == 0) {\n      Item lastItem = findLastOne(entity.getNamespaceId());\n      int lineNum = lastItem == null ? 1 : lastItem.getLineNum() + 1;\n      entity.setLineNum(lineNum);\n    }\n\n    Item item = itemRepository.save(entity);\n\n    auditService.audit(Item.class.getSimpleName(), item.getId(), Audit.OP.INSERT,\n                       item.getDataChangeCreatedBy());\n\n    return item;\n  }\n\n  @Transactional\n  public Item update(Item item) {\n    checkItemValueLength(item.getNamespaceId(), item.getValue());\n    Item managedItem = itemRepository.findOne(item.getId());\n    BeanUtils.copyEntityProperties(item, managedItem);\n    managedItem = itemRepository.save(managedItem);\n\n    auditService.audit(Item.class.getSimpleName(), managedItem.getId(), Audit.OP.UPDATE,\n                       managedItem.getDataChangeLastModifiedBy());\n\n    return managedItem;\n  }\n\n  private boolean checkItemValueLength(long namespaceId, String value) {\n    int limit = getItemValueLengthLimit(namespaceId);\n    if (!StringUtils.isEmpty(value) && value.length() > limit) {\n      throw new BadRequestException(\"value too long. length limit:\" + limit);\n    }\n    return true;\n  }\n\n  private boolean checkItemKeyLength(String key) {\n    if (!StringUtils.isEmpty(key) && key.length() > bizConfig.itemKeyLengthLimit()) {\n      throw new BadRequestException(\"key too long. length limit:\" + bizConfig.itemKeyLengthLimit());\n    }\n    return true;\n  }\n\n  private int getItemValueLengthLimit(long namespaceId) {\n    Map<Long, Integer> namespaceValueLengthOverride = bizConfig.namespaceValueLengthLimitOverride();\n    if (namespaceValueLengthOverride != null && namespaceValueLengthOverride.containsKey(namespaceId)) {\n      return namespaceValueLengthOverride.get(namespaceId);\n    }\n    return bizConfig.itemValueLengthLimit();\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/ItemSetService.java",
    "content": "package com.ctrip.framework.apollo.biz.service;\n\nimport com.ctrip.framework.apollo.biz.entity.Audit;\nimport com.ctrip.framework.apollo.biz.entity.Commit;\nimport com.ctrip.framework.apollo.biz.entity.Item;\nimport com.ctrip.framework.apollo.biz.entity.Namespace;\nimport com.ctrip.framework.apollo.biz.utils.ConfigChangeContentBuilder;\nimport com.ctrip.framework.apollo.common.dto.ItemChangeSets;\nimport com.ctrip.framework.apollo.common.dto.ItemDTO;\nimport com.ctrip.framework.apollo.common.exception.NotFoundException;\nimport com.ctrip.framework.apollo.common.utils.BeanUtils;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\nimport org.springframework.util.CollectionUtils;\n\n\n@Service\npublic class ItemSetService {\n\n  @Autowired\n  private AuditService auditService;\n\n  @Autowired\n  private CommitService commitService;\n\n  @Autowired\n  private ItemService itemService;\n\n  @Transactional\n  public ItemChangeSets updateSet(Namespace namespace, ItemChangeSets changeSets){\n    return updateSet(namespace.getAppId(), namespace.getClusterName(), namespace.getNamespaceName(), changeSets);\n  }\n\n  @Transactional\n  public ItemChangeSets updateSet(String appId, String clusterName,\n                                  String namespaceName, ItemChangeSets changeSet) {\n    String operator = changeSet.getDataChangeLastModifiedBy();\n    ConfigChangeContentBuilder configChangeContentBuilder = new ConfigChangeContentBuilder();\n\n    if (!CollectionUtils.isEmpty(changeSet.getCreateItems())) {\n      for (ItemDTO item : changeSet.getCreateItems()) {\n        Item entity = BeanUtils.transfrom(Item.class, item);\n        entity.setDataChangeCreatedBy(operator);\n        entity.setDataChangeLastModifiedBy(operator);\n        Item createdItem = itemService.save(entity);\n        configChangeContentBuilder.createItem(createdItem);\n      }\n      auditService.audit(\"ItemSet\", null, Audit.OP.INSERT, operator);\n    }\n\n    if (!CollectionUtils.isEmpty(changeSet.getUpdateItems())) {\n      for (ItemDTO item : changeSet.getUpdateItems()) {\n        Item entity = BeanUtils.transfrom(Item.class, item);\n\n        Item managedItem = itemService.findOne(entity.getId());\n        if (managedItem == null) {\n          throw new NotFoundException(String.format(\"item not found.(key=%s)\", entity.getKey()));\n        }\n        Item beforeUpdateItem = BeanUtils.transfrom(Item.class, managedItem);\n\n        //protect. only value,comment,lastModifiedBy,lineNum can be modified\n        managedItem.setValue(entity.getValue());\n        managedItem.setComment(entity.getComment());\n        managedItem.setLineNum(entity.getLineNum());\n        managedItem.setDataChangeLastModifiedBy(operator);\n\n        Item updatedItem = itemService.update(managedItem);\n        configChangeContentBuilder.updateItem(beforeUpdateItem, updatedItem);\n\n      }\n      auditService.audit(\"ItemSet\", null, Audit.OP.UPDATE, operator);\n    }\n\n    if (!CollectionUtils.isEmpty(changeSet.getDeleteItems())) {\n      for (ItemDTO item : changeSet.getDeleteItems()) {\n        Item deletedItem = itemService.delete(item.getId(), operator);\n        configChangeContentBuilder.deleteItem(deletedItem);\n      }\n      auditService.audit(\"ItemSet\", null, Audit.OP.DELETE, operator);\n    }\n\n    if (configChangeContentBuilder.hasContent()){\n      createCommit(appId, clusterName, namespaceName, configChangeContentBuilder.build(),\n                   changeSet.getDataChangeLastModifiedBy());\n    }\n\n    return changeSet;\n\n  }\n\n  private void createCommit(String appId, String clusterName, String namespaceName, String configChangeContent,\n                            String operator) {\n\n    Commit commit = new Commit();\n    commit.setAppId(appId);\n    commit.setClusterName(clusterName);\n    commit.setNamespaceName(namespaceName);\n    commit.setChangeSets(configChangeContent);\n    commit.setDataChangeCreatedBy(operator);\n    commit.setDataChangeLastModifiedBy(operator);\n    commitService.save(commit);\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/NamespaceBranchService.java",
    "content": "package com.ctrip.framework.apollo.biz.service;\n\nimport com.google.common.collect.Maps;\n\nimport com.ctrip.framework.apollo.biz.entity.Audit;\nimport com.ctrip.framework.apollo.biz.entity.Cluster;\nimport com.ctrip.framework.apollo.biz.entity.GrayReleaseRule;\nimport com.ctrip.framework.apollo.biz.entity.Namespace;\nimport com.ctrip.framework.apollo.biz.entity.Release;\nimport com.ctrip.framework.apollo.biz.repository.GrayReleaseRuleRepository;\nimport com.ctrip.framework.apollo.common.constants.NamespaceBranchStatus;\nimport com.ctrip.framework.apollo.common.constants.ReleaseOperation;\nimport com.ctrip.framework.apollo.common.constants.ReleaseOperationContext;\nimport com.ctrip.framework.apollo.common.exception.BadRequestException;\nimport com.ctrip.framework.apollo.common.utils.GrayReleaseRuleItemTransformer;\nimport com.ctrip.framework.apollo.common.utils.UniqueKeyGenerator;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\nimport java.util.Map;\n\n@Service\npublic class NamespaceBranchService {\n\n  @Autowired\n  private AuditService auditService;\n  @Autowired\n  private GrayReleaseRuleRepository grayReleaseRuleRepository;\n  @Autowired\n  private ClusterService clusterService;\n  @Autowired\n  private ReleaseService releaseService;\n  @Autowired\n  private NamespaceService namespaceService;\n  @Autowired\n  private ReleaseHistoryService releaseHistoryService;\n\n  @Transactional\n  public Namespace createBranch(String appId, String parentClusterName, String namespaceName, String operator){\n    Namespace childNamespace = findBranch(appId, parentClusterName, namespaceName);\n    if (childNamespace != null){\n      throw new BadRequestException(\"namespace already has branch\");\n    }\n\n    Cluster parentCluster = clusterService.findOne(appId, parentClusterName);\n    if (parentCluster == null || parentCluster.getParentClusterId() != 0) {\n      throw new BadRequestException(\"cluster not exist or illegal cluster\");\n    }\n\n    //create child cluster\n    Cluster childCluster = createChildCluster(appId, parentCluster, namespaceName, operator);\n\n    Cluster createdChildCluster = clusterService.saveWithoutInstanceOfAppNamespaces(childCluster);\n\n    //create child namespace\n    childNamespace = createNamespaceBranch(appId, createdChildCluster.getName(),\n                                                        namespaceName, operator);\n    return namespaceService.save(childNamespace);\n  }\n\n  public Namespace findBranch(String appId, String parentClusterName, String namespaceName) {\n    return namespaceService.findChildNamespace(appId, parentClusterName, namespaceName);\n  }\n\n  public GrayReleaseRule findBranchGrayRules(String appId, String clusterName, String namespaceName,\n                                             String branchName) {\n    return grayReleaseRuleRepository\n        .findTopByAppIdAndClusterNameAndNamespaceNameAndBranchNameOrderByIdDesc(appId, clusterName, namespaceName, branchName);\n  }\n\n  @Transactional\n  public void updateBranchGrayRules(String appId, String clusterName, String namespaceName,\n                                    String branchName, GrayReleaseRule newRules) {\n    doUpdateBranchGrayRules(appId, clusterName, namespaceName, branchName, newRules, true, ReleaseOperation.APPLY_GRAY_RULES);\n  }\n\n  private void doUpdateBranchGrayRules(String appId, String clusterName, String namespaceName,\n                                              String branchName, GrayReleaseRule newRules, boolean recordReleaseHistory, int releaseOperation) {\n    GrayReleaseRule oldRules = grayReleaseRuleRepository\n        .findTopByAppIdAndClusterNameAndNamespaceNameAndBranchNameOrderByIdDesc(appId, clusterName, namespaceName, branchName);\n\n    Release latestBranchRelease = releaseService.findLatestActiveRelease(appId, branchName, namespaceName);\n\n    long latestBranchReleaseId = latestBranchRelease != null ? latestBranchRelease.getId() : 0;\n\n    newRules.setReleaseId(latestBranchReleaseId);\n\n    grayReleaseRuleRepository.save(newRules);\n\n    //delete old rules\n    if (oldRules != null) {\n      grayReleaseRuleRepository.delete(oldRules);\n    }\n\n    if (recordReleaseHistory) {\n      Map<String, Object> releaseOperationContext = Maps.newHashMap();\n      releaseOperationContext.put(ReleaseOperationContext.RULES, GrayReleaseRuleItemTransformer\n          .batchTransformFromJSON(newRules.getRules()));\n      if (oldRules != null) {\n        releaseOperationContext.put(ReleaseOperationContext.OLD_RULES,\n            GrayReleaseRuleItemTransformer.batchTransformFromJSON(oldRules.getRules()));\n      }\n      releaseHistoryService.createReleaseHistory(appId, clusterName, namespaceName, branchName, latestBranchReleaseId,\n          latestBranchReleaseId, releaseOperation, releaseOperationContext, newRules.getDataChangeLastModifiedBy());\n    }\n  }\n\n  @Transactional\n  public GrayReleaseRule updateRulesReleaseId(String appId, String clusterName,\n                                   String namespaceName, String branchName,\n                                   long latestReleaseId, String operator) {\n    GrayReleaseRule oldRules = grayReleaseRuleRepository.\n        findTopByAppIdAndClusterNameAndNamespaceNameAndBranchNameOrderByIdDesc(appId, clusterName, namespaceName, branchName);\n\n    if (oldRules == null) {\n      return null;\n    }\n\n    GrayReleaseRule newRules = new GrayReleaseRule();\n    newRules.setBranchStatus(NamespaceBranchStatus.ACTIVE);\n    newRules.setReleaseId(latestReleaseId);\n    newRules.setRules(oldRules.getRules());\n    newRules.setAppId(oldRules.getAppId());\n    newRules.setClusterName(oldRules.getClusterName());\n    newRules.setNamespaceName(oldRules.getNamespaceName());\n    newRules.setBranchName(oldRules.getBranchName());\n    newRules.setDataChangeCreatedBy(operator);\n    newRules.setDataChangeLastModifiedBy(operator);\n\n    grayReleaseRuleRepository.save(newRules);\n\n    grayReleaseRuleRepository.delete(oldRules);\n\n    return newRules;\n  }\n\n  @Transactional\n  public void deleteBranch(String appId, String clusterName, String namespaceName,\n                           String branchName, int branchStatus, String operator) {\n    Cluster toDeleteCluster = clusterService.findOne(appId, branchName);\n    if (toDeleteCluster == null) {\n      return;\n    }\n\n    Release latestBranchRelease = releaseService.findLatestActiveRelease(appId, branchName, namespaceName);\n\n    long latestBranchReleaseId = latestBranchRelease != null ? latestBranchRelease.getId() : 0;\n\n    //update branch rules\n    GrayReleaseRule deleteRule = new GrayReleaseRule();\n    deleteRule.setRules(\"[]\");\n    deleteRule.setAppId(appId);\n    deleteRule.setClusterName(clusterName);\n    deleteRule.setNamespaceName(namespaceName);\n    deleteRule.setBranchName(branchName);\n    deleteRule.setBranchStatus(branchStatus);\n    deleteRule.setDataChangeLastModifiedBy(operator);\n    deleteRule.setDataChangeCreatedBy(operator);\n\n    doUpdateBranchGrayRules(appId, clusterName, namespaceName, branchName, deleteRule, false, -1);\n\n    //delete branch cluster\n    clusterService.delete(toDeleteCluster.getId(), operator);\n\n    int releaseOperation = branchStatus == NamespaceBranchStatus.MERGED ? ReleaseOperation\n        .GRAY_RELEASE_DELETED_AFTER_MERGE : ReleaseOperation.ABANDON_GRAY_RELEASE;\n\n    releaseHistoryService.createReleaseHistory(appId, clusterName, namespaceName, branchName, latestBranchReleaseId,\n        latestBranchReleaseId, releaseOperation, null, operator);\n\n    auditService.audit(\"Branch\", toDeleteCluster.getId(), Audit.OP.DELETE, operator);\n  }\n\n  private Cluster createChildCluster(String appId, Cluster parentCluster,\n                                     String namespaceName, String operator) {\n\n    Cluster childCluster = new Cluster();\n    childCluster.setAppId(appId);\n    childCluster.setParentClusterId(parentCluster.getId());\n    childCluster.setName(UniqueKeyGenerator.generate(appId, parentCluster.getName(), namespaceName));\n    childCluster.setDataChangeCreatedBy(operator);\n    childCluster.setDataChangeLastModifiedBy(operator);\n\n    return childCluster;\n  }\n\n\n  private Namespace createNamespaceBranch(String appId, String clusterName, String namespaceName, String operator) {\n    Namespace childNamespace = new Namespace();\n    childNamespace.setAppId(appId);\n    childNamespace.setClusterName(clusterName);\n    childNamespace.setNamespaceName(namespaceName);\n    childNamespace.setDataChangeLastModifiedBy(operator);\n    childNamespace.setDataChangeCreatedBy(operator);\n    return childNamespace;\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/NamespaceLockService.java",
    "content": "package com.ctrip.framework.apollo.biz.service;\n\nimport com.ctrip.framework.apollo.biz.entity.NamespaceLock;\nimport com.ctrip.framework.apollo.biz.repository.NamespaceLockRepository;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\n@Service\npublic class NamespaceLockService {\n\n  @Autowired\n  private NamespaceLockRepository namespaceLockRepository;\n\n  public NamespaceLock findLock(Long namespaceId){\n    return namespaceLockRepository.findByNamespaceId(namespaceId);\n  }\n\n\n  @Transactional\n  public NamespaceLock tryLock(NamespaceLock lock){\n    return namespaceLockRepository.save(lock);\n  }\n\n  @Transactional\n  public void unlock(Long namespaceId){\n    namespaceLockRepository.deleteByNamespaceId(namespaceId);\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/NamespaceService.java",
    "content": "package com.ctrip.framework.apollo.biz.service;\n\nimport com.google.common.collect.Maps;\nimport com.google.gson.Gson;\n\nimport com.ctrip.framework.apollo.biz.entity.Audit;\nimport com.ctrip.framework.apollo.biz.entity.Cluster;\nimport com.ctrip.framework.apollo.biz.entity.Item;\nimport com.ctrip.framework.apollo.biz.entity.Namespace;\nimport com.ctrip.framework.apollo.biz.entity.Release;\nimport com.ctrip.framework.apollo.biz.message.MessageSender;\nimport com.ctrip.framework.apollo.biz.message.Topics;\nimport com.ctrip.framework.apollo.biz.repository.NamespaceRepository;\nimport com.ctrip.framework.apollo.biz.utils.ReleaseMessageKeyGenerator;\nimport com.ctrip.framework.apollo.common.constants.GsonType;\nimport com.ctrip.framework.apollo.common.constants.NamespaceBranchStatus;\nimport com.ctrip.framework.apollo.common.entity.AppNamespace;\nimport com.ctrip.framework.apollo.common.exception.BadRequestException;\nimport com.ctrip.framework.apollo.common.exception.ServiceException;\nimport com.ctrip.framework.apollo.common.utils.BeanUtils;\nimport com.ctrip.framework.apollo.core.ConfigConsts;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.data.domain.Pageable;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\nimport org.springframework.util.CollectionUtils;\n\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Set;\nimport java.util.stream.Collectors;\n\n@Service\npublic class NamespaceService {\n\n  private Gson gson = new Gson();\n\n  @Autowired\n  private NamespaceRepository namespaceRepository;\n  @Autowired\n  private AuditService auditService;\n  @Autowired\n  private AppNamespaceService appNamespaceService;\n  @Autowired\n  private ItemService itemService;\n  @Autowired\n  private CommitService commitService;\n  @Autowired\n  private ReleaseService releaseService;\n  @Autowired\n  private ClusterService clusterService;\n  @Autowired\n  private NamespaceBranchService namespaceBranchService;\n  @Autowired\n  private ReleaseHistoryService releaseHistoryService;\n  @Autowired\n  private NamespaceLockService namespaceLockService;\n  @Autowired\n  private InstanceService instanceService;\n  @Autowired\n  private MessageSender messageSender;\n\n\n  public Namespace findOne(Long namespaceId) {\n    return namespaceRepository.findOne(namespaceId);\n  }\n\n  public Namespace findOne(String appId, String clusterName, String namespaceName) {\n    return namespaceRepository.findByAppIdAndClusterNameAndNamespaceName(appId, clusterName,\n                                                                         namespaceName);\n  }\n\n  public Namespace findPublicNamespaceForAssociatedNamespace(String clusterName, String namespaceName) {\n    AppNamespace appNamespace = appNamespaceService.findPublicNamespaceByName(namespaceName);\n    if (appNamespace == null) {\n      throw new BadRequestException(\"namespace not exist\");\n    }\n\n    String appId = appNamespace.getAppId();\n\n    Namespace namespace = findOne(appId, clusterName, namespaceName);\n\n    //default cluster's namespace\n    if (Objects.equals(clusterName, ConfigConsts.CLUSTER_NAME_DEFAULT)) {\n      return namespace;\n    }\n\n    //custom cluster's namespace not exist.\n    //return default cluster's namespace\n    if (namespace == null) {\n      return findOne(appId, ConfigConsts.CLUSTER_NAME_DEFAULT, namespaceName);\n    }\n\n    //custom cluster's namespace exist and has published.\n    //return custom cluster's namespace\n    Release latestActiveRelease = releaseService.findLatestActiveRelease(namespace);\n    if (latestActiveRelease != null) {\n      return namespace;\n    }\n\n    Namespace defaultNamespace = findOne(appId, ConfigConsts.CLUSTER_NAME_DEFAULT, namespaceName);\n\n    //custom cluster's namespace exist but never published.\n    //and default cluster's namespace not exist.\n    //return custom cluster's namespace\n    if (defaultNamespace == null) {\n      return namespace;\n    }\n\n    //custom cluster's namespace exist but never published.\n    //and default cluster's namespace exist and has published.\n    //return default cluster's namespace\n    Release defaultNamespaceLatestActiveRelease = releaseService.findLatestActiveRelease(defaultNamespace);\n    if (defaultNamespaceLatestActiveRelease != null) {\n      return defaultNamespace;\n    }\n\n    //custom cluster's namespace exist but never published.\n    //and default cluster's namespace exist but never published.\n    //return custom cluster's namespace\n    return namespace;\n  }\n\n  public List<Namespace> findPublicAppNamespaceAllNamespaces(String namespaceName, Pageable page) {\n    AppNamespace publicAppNamespace = appNamespaceService.findPublicNamespaceByName(namespaceName);\n\n    if (publicAppNamespace == null) {\n      throw new BadRequestException(\n          String.format(\"Public appNamespace not exists. NamespaceName = %s\", namespaceName));\n    }\n\n    List<Namespace> namespaces = namespaceRepository.findByNamespaceName(namespaceName, page);\n\n    return filterChildNamespace(namespaces);\n  }\n\n  private List<Namespace> filterChildNamespace(List<Namespace> namespaces) {\n    List<Namespace> result = new LinkedList<>();\n\n    if (CollectionUtils.isEmpty(namespaces)) {\n      return result;\n    }\n\n    for (Namespace namespace : namespaces) {\n      if (!isChildNamespace(namespace)) {\n        result.add(namespace);\n      }\n    }\n\n    return result;\n  }\n\n  public int countPublicAppNamespaceAssociatedNamespaces(String publicNamespaceName) {\n    AppNamespace publicAppNamespace = appNamespaceService.findPublicNamespaceByName(publicNamespaceName);\n\n    if (publicAppNamespace == null) {\n      throw new BadRequestException(\n          String.format(\"Public appNamespace not exists. NamespaceName = %s\", publicNamespaceName));\n    }\n\n    return namespaceRepository.countByNamespaceNameAndAppIdNot(publicNamespaceName, publicAppNamespace.getAppId());\n  }\n\n  public List<Namespace> findNamespaces(String appId, String clusterName) {\n    List<Namespace> namespaces = namespaceRepository.findByAppIdAndClusterNameOrderByIdAsc(appId, clusterName);\n    if (namespaces == null) {\n      return Collections.emptyList();\n    }\n    return namespaces;\n  }\n\n  public List<Namespace> findByAppIdAndNamespaceName(String appId, String namespaceName) {\n    return namespaceRepository.findByAppIdAndNamespaceName(appId, namespaceName);\n  }\n\n  public Namespace findChildNamespace(String appId, String parentClusterName, String namespaceName) {\n    List<Namespace> namespaces = findByAppIdAndNamespaceName(appId, namespaceName);\n    if (CollectionUtils.isEmpty(namespaces) || namespaces.size() == 1) {\n      return null;\n    }\n\n    List<Cluster> childClusters = clusterService.findChildClusters(appId, parentClusterName);\n    if (CollectionUtils.isEmpty(childClusters)) {\n      return null;\n    }\n\n    Set<String> childClusterNames = childClusters.stream().map(Cluster::getName).collect(Collectors.toSet());\n    //the child namespace is the intersection of the child clusters and child namespaces\n    for (Namespace namespace : namespaces) {\n      if (childClusterNames.contains(namespace.getClusterName())) {\n        return namespace;\n      }\n    }\n\n    return null;\n  }\n\n  public Namespace findChildNamespace(Namespace parentNamespace) {\n    String appId = parentNamespace.getAppId();\n    String parentClusterName = parentNamespace.getClusterName();\n    String namespaceName = parentNamespace.getNamespaceName();\n\n    return findChildNamespace(appId, parentClusterName, namespaceName);\n\n  }\n\n  public Namespace findParentNamespace(String appId, String clusterName, String namespaceName) {\n    return findParentNamespace(new Namespace(appId, clusterName, namespaceName));\n  }\n\n  public Namespace findParentNamespace(Namespace namespace) {\n    String appId = namespace.getAppId();\n    String namespaceName = namespace.getNamespaceName();\n\n    Cluster cluster = clusterService.findOne(appId, namespace.getClusterName());\n    if (cluster != null && cluster.getParentClusterId() > 0) {\n      Cluster parentCluster = clusterService.findOne(cluster.getParentClusterId());\n      return findOne(appId, parentCluster.getName(), namespaceName);\n    }\n\n    return null;\n  }\n\n  public boolean isChildNamespace(String appId, String clusterName, String namespaceName) {\n    return isChildNamespace(new Namespace(appId, clusterName, namespaceName));\n  }\n\n  public boolean isChildNamespace(Namespace namespace) {\n    return findParentNamespace(namespace) != null;\n  }\n\n  public boolean isNamespaceUnique(String appId, String cluster, String namespace) {\n    Objects.requireNonNull(appId, \"AppId must not be null\");\n    Objects.requireNonNull(cluster, \"Cluster must not be null\");\n    Objects.requireNonNull(namespace, \"Namespace must not be null\");\n    return Objects.isNull(\n        namespaceRepository.findByAppIdAndClusterNameAndNamespaceName(appId, cluster, namespace));\n  }\n\n  @Transactional\n  public void deleteByAppIdAndClusterName(String appId, String clusterName, String operator) {\n\n    List<Namespace> toDeleteNamespaces = findNamespaces(appId, clusterName);\n\n    for (Namespace namespace : toDeleteNamespaces) {\n\n      deleteNamespace(namespace, operator);\n\n    }\n  }\n\n  @Transactional\n  public Namespace deleteNamespace(Namespace namespace, String operator) {\n    String appId = namespace.getAppId();\n    String clusterName = namespace.getClusterName();\n    String namespaceName = namespace.getNamespaceName();\n\n    itemService.batchDelete(namespace.getId(), operator);\n    commitService.batchDelete(appId, clusterName, namespace.getNamespaceName(), operator);\n\n    if (!isChildNamespace(namespace)) {\n      releaseService.batchDelete(appId, clusterName, namespace.getNamespaceName(), operator);\n    }\n\n    //delete child namespace\n    Namespace childNamespace = findChildNamespace(namespace);\n    if (childNamespace != null) {\n      namespaceBranchService.deleteBranch(appId, clusterName, namespaceName,\n                                          childNamespace.getClusterName(), NamespaceBranchStatus.DELETED, operator);\n      //delete child namespace's releases. Notice: delete child namespace will not delete child namespace's releases\n      releaseService.batchDelete(appId, childNamespace.getClusterName(), namespaceName, operator);\n    }\n\n    releaseHistoryService.batchDelete(appId, clusterName, namespaceName, operator);\n\n    instanceService.batchDeleteInstanceConfig(appId, clusterName, namespaceName);\n\n    namespaceLockService.unlock(namespace.getId());\n\n    namespace.setDeleted(true);\n    namespace.setDataChangeLastModifiedBy(operator);\n\n    auditService.audit(Namespace.class.getSimpleName(), namespace.getId(), Audit.OP.DELETE, operator);\n\n    Namespace deleted = namespaceRepository.save(namespace);\n\n    //Publish release message to do some clean up in config service, such as updating the cache\n    messageSender.sendMessage(ReleaseMessageKeyGenerator.generate(appId, clusterName, namespaceName),\n        Topics.APOLLO_RELEASE_TOPIC);\n\n    return deleted;\n  }\n\n  @Transactional\n  public Namespace save(Namespace entity) {\n    if (!isNamespaceUnique(entity.getAppId(), entity.getClusterName(), entity.getNamespaceName())) {\n      throw new ServiceException(\"namespace not unique\");\n    }\n    entity.setId(0);//protection\n    Namespace namespace = namespaceRepository.save(entity);\n\n    auditService.audit(Namespace.class.getSimpleName(), namespace.getId(), Audit.OP.INSERT,\n                       namespace.getDataChangeCreatedBy());\n\n    return namespace;\n  }\n\n  @Transactional\n  public Namespace update(Namespace namespace) {\n    Namespace managedNamespace = namespaceRepository.findByAppIdAndClusterNameAndNamespaceName(\n        namespace.getAppId(), namespace.getClusterName(), namespace.getNamespaceName());\n    BeanUtils.copyEntityProperties(namespace, managedNamespace);\n    managedNamespace = namespaceRepository.save(managedNamespace);\n\n    auditService.audit(Namespace.class.getSimpleName(), managedNamespace.getId(), Audit.OP.UPDATE,\n                       managedNamespace.getDataChangeLastModifiedBy());\n\n    return managedNamespace;\n  }\n\n  @Transactional\n  public void instanceOfAppNamespaces(String appId, String clusterName, String createBy) {\n\n    List<AppNamespace> appNamespaces = appNamespaceService.findByAppId(appId);\n\n    for (AppNamespace appNamespace : appNamespaces) {\n      Namespace ns = new Namespace();\n      ns.setAppId(appId);\n      ns.setClusterName(clusterName);\n      ns.setNamespaceName(appNamespace.getName());\n      ns.setDataChangeCreatedBy(createBy);\n      ns.setDataChangeLastModifiedBy(createBy);\n      namespaceRepository.save(ns);\n      auditService.audit(Namespace.class.getSimpleName(), ns.getId(), Audit.OP.INSERT, createBy);\n    }\n\n  }\n\n  public Map<String, Boolean> namespacePublishInfo(String appId) {\n    List<Cluster> clusters = clusterService.findParentClusters(appId);\n    if (CollectionUtils.isEmpty(clusters)) {\n      throw new BadRequestException(\"app not exist\");\n    }\n\n    Map<String, Boolean> clusterHasNotPublishedItems = Maps.newHashMap();\n\n    for (Cluster cluster : clusters) {\n      String clusterName = cluster.getName();\n      List<Namespace> namespaces = findNamespaces(appId, clusterName);\n\n      for (Namespace namespace : namespaces) {\n        boolean isNamespaceNotPublished = isNamespaceNotPublished(namespace);\n\n        if (isNamespaceNotPublished) {\n          clusterHasNotPublishedItems.put(clusterName, true);\n          break;\n        }\n      }\n\n      clusterHasNotPublishedItems.putIfAbsent(clusterName, false);\n    }\n\n    return clusterHasNotPublishedItems;\n  }\n\n  private boolean isNamespaceNotPublished(Namespace namespace) {\n\n    Release latestRelease = releaseService.findLatestActiveRelease(namespace);\n    long namespaceId = namespace.getId();\n\n    if (latestRelease == null) {\n      Item lastItem = itemService.findLastOne(namespaceId);\n      return lastItem != null;\n    }\n\n    Date lastPublishTime = latestRelease.getDataChangeLastModifiedTime();\n    List<Item> itemsModifiedAfterLastPublish = itemService.findItemsModifiedAfterDate(namespaceId, lastPublishTime);\n\n    if (CollectionUtils.isEmpty(itemsModifiedAfterLastPublish)) {\n      return false;\n    }\n\n    Map<String, String> publishedConfiguration = gson.fromJson(latestRelease.getConfigurations(), GsonType.CONFIG);\n    for (Item item : itemsModifiedAfterLastPublish) {\n      if (!Objects.equals(item.getValue(), publishedConfiguration.get(item.getKey()))) {\n        return true;\n      }\n    }\n\n    return false;\n  }\n\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/ReleaseHistoryService.java",
    "content": "package com.ctrip.framework.apollo.biz.service;\n\nimport com.google.gson.Gson;\n\nimport com.ctrip.framework.apollo.biz.entity.Audit;\nimport com.ctrip.framework.apollo.biz.entity.ReleaseHistory;\nimport com.ctrip.framework.apollo.biz.repository.ReleaseHistoryRepository;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.data.domain.Page;\nimport org.springframework.data.domain.Pageable;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\nimport java.util.Date;\nimport java.util.Map;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@Service\npublic class ReleaseHistoryService {\n  private Gson gson = new Gson();\n\n  @Autowired\n  private ReleaseHistoryRepository releaseHistoryRepository;\n  @Autowired\n  private AuditService auditService;\n\n\n  public Page<ReleaseHistory> findReleaseHistoriesByNamespace(String appId, String clusterName,\n                                                              String namespaceName, Pageable\n                                                                  pageable) {\n    return releaseHistoryRepository.findByAppIdAndClusterNameAndNamespaceNameOrderByIdDesc(appId, clusterName,\n                                                                                           namespaceName, pageable);\n  }\n\n  public Page<ReleaseHistory> findByReleaseIdAndOperation(long releaseId, int operation, Pageable page) {\n    return releaseHistoryRepository.findByReleaseIdAndOperationOrderByIdDesc(releaseId, operation, page);\n  }\n\n  public Page<ReleaseHistory> findByPreviousReleaseIdAndOperation(long previousReleaseId, int operation, Pageable page) {\n    return releaseHistoryRepository.findByPreviousReleaseIdAndOperationOrderByIdDesc(previousReleaseId, operation, page);\n  }\n\n  @Transactional\n  public ReleaseHistory createReleaseHistory(String appId, String clusterName, String\n      namespaceName, String branchName, long releaseId, long previousReleaseId, int operation,\n                                             Map<String, Object> operationContext, String operator) {\n    ReleaseHistory releaseHistory = new ReleaseHistory();\n    releaseHistory.setAppId(appId);\n    releaseHistory.setClusterName(clusterName);\n    releaseHistory.setNamespaceName(namespaceName);\n    releaseHistory.setBranchName(branchName);\n    releaseHistory.setReleaseId(releaseId);\n    releaseHistory.setPreviousReleaseId(previousReleaseId);\n    releaseHistory.setOperation(operation);\n    if (operationContext == null) {\n      releaseHistory.setOperationContext(\"{}\"); //default empty object\n    } else {\n      releaseHistory.setOperationContext(gson.toJson(operationContext));\n    }\n    releaseHistory.setDataChangeCreatedTime(new Date());\n    releaseHistory.setDataChangeCreatedBy(operator);\n    releaseHistory.setDataChangeLastModifiedBy(operator);\n\n    releaseHistoryRepository.save(releaseHistory);\n\n    auditService.audit(ReleaseHistory.class.getSimpleName(), releaseHistory.getId(),\n                       Audit.OP.INSERT, releaseHistory.getDataChangeCreatedBy());\n\n    return releaseHistory;\n  }\n\n  @Transactional\n  public int batchDelete(String appId, String clusterName, String namespaceName, String operator) {\n    return releaseHistoryRepository.batchDelete(appId, clusterName, namespaceName, operator);\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/ReleaseMessageService.java",
    "content": "package com.ctrip.framework.apollo.biz.service;\n\nimport com.google.common.collect.Lists;\n\nimport com.ctrip.framework.apollo.biz.entity.ReleaseMessage;\nimport com.ctrip.framework.apollo.biz.repository.ReleaseMessageRepository;\nimport com.ctrip.framework.apollo.tracer.Tracer;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.util.CollectionUtils;\n\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.List;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@Service\npublic class ReleaseMessageService {\n  @Autowired\n  private ReleaseMessageRepository releaseMessageRepository;\n\n  public ReleaseMessage findLatestReleaseMessageForMessages(Collection<String> messages) {\n    if (CollectionUtils.isEmpty(messages)) {\n      return null;\n    }\n    return releaseMessageRepository.findTopByMessageInOrderByIdDesc(messages);\n  }\n\n  public List<ReleaseMessage> findLatestReleaseMessagesGroupByMessages(Collection<String> messages) {\n    if (CollectionUtils.isEmpty(messages)) {\n      return Collections.emptyList();\n    }\n    List<Object[]> result =\n        releaseMessageRepository.findLatestReleaseMessagesGroupByMessages(messages);\n    List<ReleaseMessage> releaseMessages = Lists.newArrayList();\n    for (Object[] o : result) {\n      try {\n        ReleaseMessage releaseMessage = new ReleaseMessage((String) o[0]);\n        releaseMessage.setId((Long) o[1]);\n        releaseMessages.add(releaseMessage);\n      } catch (Exception ex) {\n        Tracer.logError(\"Parsing LatestReleaseMessagesGroupByMessages failed\", ex);\n      }\n    }\n    return releaseMessages;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/ReleaseService.java",
    "content": "package com.ctrip.framework.apollo.biz.service;\n\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport com.google.gson.Gson;\n\nimport com.ctrip.framework.apollo.biz.entity.Audit;\nimport com.ctrip.framework.apollo.biz.entity.GrayReleaseRule;\nimport com.ctrip.framework.apollo.biz.entity.Item;\nimport com.ctrip.framework.apollo.biz.entity.Namespace;\nimport com.ctrip.framework.apollo.biz.entity.NamespaceLock;\nimport com.ctrip.framework.apollo.biz.entity.Release;\nimport com.ctrip.framework.apollo.biz.repository.ReleaseRepository;\nimport com.ctrip.framework.apollo.biz.utils.ReleaseKeyGenerator;\nimport com.ctrip.framework.apollo.common.constants.GsonType;\nimport com.ctrip.framework.apollo.common.constants.ReleaseOperation;\nimport com.ctrip.framework.apollo.common.constants.ReleaseOperationContext;\nimport com.ctrip.framework.apollo.common.dto.ItemChangeSets;\nimport com.ctrip.framework.apollo.common.exception.BadRequestException;\nimport com.ctrip.framework.apollo.common.exception.NotFoundException;\nimport com.ctrip.framework.apollo.common.utils.GrayReleaseRuleItemTransformer;\nimport com.ctrip.framework.apollo.core.utils.StringUtils;\n\nimport org.apache.commons.lang.time.FastDateFormat;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.data.domain.PageRequest;\nimport org.springframework.data.domain.Pageable;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\nimport org.springframework.util.CollectionUtils;\n\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Set;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@Service\npublic class ReleaseService {\n\n  private static final FastDateFormat TIMESTAMP_FORMAT = FastDateFormat.getInstance(\"yyyyMMddHHmmss\");\n  private Gson gson = new Gson();\n\n  @Autowired\n  private ReleaseRepository releaseRepository;\n  @Autowired\n  private ItemService itemService;\n  @Autowired\n  private AuditService auditService;\n  @Autowired\n  private NamespaceLockService namespaceLockService;\n  @Autowired\n  private NamespaceService namespaceService;\n  @Autowired\n  private NamespaceBranchService namespaceBranchService;\n  @Autowired\n  private ReleaseHistoryService releaseHistoryService;\n  @Autowired\n  private ItemSetService itemSetService;\n\n  public Release findOne(long releaseId) {\n    return releaseRepository.findOne(releaseId);\n  }\n\n\n  public Release findActiveOne(long releaseId) {\n    return releaseRepository.findByIdAndIsAbandonedFalse(releaseId);\n  }\n\n  public List<Release> findByReleaseIds(Set<Long> releaseIds) {\n    Iterable<Release> releases = releaseRepository.findAll(releaseIds);\n    if (releases == null) {\n      return Collections.emptyList();\n    }\n    return Lists.newArrayList(releases);\n  }\n\n  public List<Release> findByReleaseKeys(Set<String> releaseKeys) {\n    return releaseRepository.findByReleaseKeyIn(releaseKeys);\n  }\n\n  public Release findLatestActiveRelease(Namespace namespace) {\n    return findLatestActiveRelease(namespace.getAppId(),\n                                   namespace.getClusterName(), namespace.getNamespaceName());\n\n  }\n\n  public Release findLatestActiveRelease(String appId, String clusterName, String namespaceName) {\n    return releaseRepository.findFirstByAppIdAndClusterNameAndNamespaceNameAndIsAbandonedFalseOrderByIdDesc(appId,\n                                                                                                            clusterName,\n                                                                                                            namespaceName);\n  }\n\n  public List<Release> findAllReleases(String appId, String clusterName, String namespaceName, Pageable page) {\n    List<Release> releases = releaseRepository.findByAppIdAndClusterNameAndNamespaceNameOrderByIdDesc(appId,\n                                                                                                      clusterName,\n                                                                                                      namespaceName,\n                                                                                                      page);\n    if (releases == null) {\n      return Collections.emptyList();\n    }\n    return releases;\n  }\n\n  public List<Release> findActiveReleases(String appId, String clusterName, String namespaceName, Pageable page) {\n    List<Release>\n        releases =\n        releaseRepository.findByAppIdAndClusterNameAndNamespaceNameAndIsAbandonedFalseOrderByIdDesc(appId, clusterName,\n                                                                                                    namespaceName,\n                                                                                                    page);\n    if (releases == null) {\n      return Collections.emptyList();\n    }\n    return releases;\n  }\n\n  @Transactional\n  public Release mergeBranchChangeSetsAndRelease(Namespace namespace, String branchName, String releaseName,\n                                                 String releaseComment, boolean isEmergencyPublish,\n                                                 ItemChangeSets changeSets) {\n\n    checkLock(namespace, isEmergencyPublish, changeSets.getDataChangeLastModifiedBy());\n\n    itemSetService.updateSet(namespace, changeSets);\n\n    Release branchRelease = findLatestActiveRelease(namespace.getAppId(), branchName, namespace\n        .getNamespaceName());\n    long branchReleaseId = branchRelease == null ? 0 : branchRelease.getId();\n\n    Map<String, String> operateNamespaceItems = getNamespaceItems(namespace);\n\n    Map<String, Object> operationContext = Maps.newHashMap();\n    operationContext.put(ReleaseOperationContext.SOURCE_BRANCH, branchName);\n    operationContext.put(ReleaseOperationContext.BASE_RELEASE_ID, branchReleaseId);\n    operationContext.put(ReleaseOperationContext.IS_EMERGENCY_PUBLISH, isEmergencyPublish);\n\n    return masterRelease(namespace, releaseName, releaseComment, operateNamespaceItems,\n                         changeSets.getDataChangeLastModifiedBy(),\n                         ReleaseOperation.GRAY_RELEASE_MERGE_TO_MASTER, operationContext);\n\n  }\n\n  @Transactional\n  public Release publish(Namespace namespace, String releaseName, String releaseComment,\n                         String operator, boolean isEmergencyPublish) {\n\n    checkLock(namespace, isEmergencyPublish, operator);\n\n    Map<String, String> operateNamespaceItems = getNamespaceItems(namespace);\n\n    Namespace parentNamespace = namespaceService.findParentNamespace(namespace);\n\n    //branch release\n    if (parentNamespace != null) {\n      return publishBranchNamespace(parentNamespace, namespace, operateNamespaceItems,\n                                    releaseName, releaseComment, operator, isEmergencyPublish);\n    }\n\n    Namespace childNamespace = namespaceService.findChildNamespace(namespace);\n\n    Release previousRelease = null;\n    if (childNamespace != null) {\n      previousRelease = findLatestActiveRelease(namespace);\n    }\n\n    //master release\n    Map<String, Object> operationContext = Maps.newHashMap();\n    operationContext.put(ReleaseOperationContext.IS_EMERGENCY_PUBLISH, isEmergencyPublish);\n\n    Release release = masterRelease(namespace, releaseName, releaseComment, operateNamespaceItems,\n                                    operator, ReleaseOperation.NORMAL_RELEASE, operationContext);\n\n    //merge to branch and auto release\n    if (childNamespace != null) {\n      mergeFromMasterAndPublishBranch(namespace, childNamespace, operateNamespaceItems,\n                                      releaseName, releaseComment, operator, previousRelease,\n                                      release, isEmergencyPublish);\n    }\n\n    return release;\n  }\n\n  private void checkLock(Namespace namespace, boolean isEmergencyPublish, String operator) {\n    if (!isEmergencyPublish) {\n      NamespaceLock lock = namespaceLockService.findLock(namespace.getId());\n      if (lock != null && lock.getDataChangeCreatedBy().equals(operator)) {\n        throw new BadRequestException(\"Config can not be published by yourself.\");\n      }\n    }\n  }\n\n  private void mergeFromMasterAndPublishBranch(Namespace parentNamespace, Namespace childNamespace,\n                                               Map<String, String> parentNamespaceItems,\n                                               String releaseName, String releaseComment,\n                                               String operator, Release masterPreviousRelease,\n                                               Release parentRelease, boolean isEmergencyPublish) {\n    //create release for child namespace\n    Map<String, String> childReleaseConfiguration = getNamespaceReleaseConfiguration(childNamespace);\n    Map<String, String> parentNamespaceOldConfiguration = masterPreviousRelease == null ?\n                                                          null : gson.fromJson(masterPreviousRelease.getConfigurations(),\n                                                                        GsonType.CONFIG);\n\n    Map<String, String> childNamespaceToPublishConfigs =\n        calculateChildNamespaceToPublishConfiguration(parentNamespaceOldConfiguration,\n                                                      parentNamespaceItems,\n                                                      childNamespace);\n    //compare\n    if (!childNamespaceToPublishConfigs.equals(childReleaseConfiguration)) {\n      branchRelease(parentNamespace, childNamespace, releaseName, releaseComment,\n                    childNamespaceToPublishConfigs, parentRelease.getId(), operator,\n                    ReleaseOperation.MASTER_NORMAL_RELEASE_MERGE_TO_GRAY, isEmergencyPublish);\n    }\n\n  }\n\n  private Release publishBranchNamespace(Namespace parentNamespace, Namespace childNamespace,\n                                         Map<String, String> childNamespaceItems,\n                                         String releaseName, String releaseComment,\n                                         String operator, boolean isEmergencyPublish) {\n    Release parentLatestRelease = findLatestActiveRelease(parentNamespace);\n    Map<String, String> parentConfigurations = parentLatestRelease != null ?\n                                               gson.fromJson(parentLatestRelease.getConfigurations(),\n                                                             GsonType.CONFIG) : new HashMap<>();\n    long baseReleaseId = parentLatestRelease == null ? 0 : parentLatestRelease.getId();\n\n    Map<String, String> childNamespaceToPublishConfigs = mergeConfiguration(parentConfigurations, childNamespaceItems);\n\n    return branchRelease(parentNamespace, childNamespace, releaseName, releaseComment,\n                         childNamespaceToPublishConfigs, baseReleaseId, operator,\n                         ReleaseOperation.GRAY_RELEASE, isEmergencyPublish);\n\n  }\n\n  private Release masterRelease(Namespace namespace, String releaseName, String releaseComment,\n                                Map<String, String> configurations, String operator,\n                                int releaseOperation, Map<String, Object> operationContext) {\n    Release lastActiveRelease = findLatestActiveRelease(namespace);\n    long previousReleaseId = lastActiveRelease == null ? 0 : lastActiveRelease.getId();\n    Release release = createRelease(namespace, releaseName, releaseComment,\n                                    configurations, operator);\n\n    releaseHistoryService.createReleaseHistory(namespace.getAppId(), namespace.getClusterName(),\n                                               namespace.getNamespaceName(), namespace.getClusterName(),\n                                               release.getId(), previousReleaseId, releaseOperation,\n                                               operationContext, operator);\n\n    return release;\n  }\n\n  private Release branchRelease(Namespace parentNamespace, Namespace childNamespace,\n                                String releaseName, String releaseComment,\n                                Map<String, String> configurations, long baseReleaseId,\n                                String operator, int releaseOperation, boolean isEmergencyPublish) {\n    Release previousRelease = findLatestActiveRelease(childNamespace.getAppId(),\n                                                      childNamespace.getClusterName(),\n                                                      childNamespace.getNamespaceName());\n    long previousReleaseId = previousRelease == null ? 0 : previousRelease.getId();\n\n    Map<String, Object> releaseOperationContext = Maps.newHashMap();\n    releaseOperationContext.put(ReleaseOperationContext.BASE_RELEASE_ID, baseReleaseId);\n    releaseOperationContext.put(ReleaseOperationContext.IS_EMERGENCY_PUBLISH, isEmergencyPublish);\n\n    Release release =\n        createRelease(childNamespace, releaseName, releaseComment, configurations, operator);\n\n    //update gray release rules\n    GrayReleaseRule grayReleaseRule = namespaceBranchService.updateRulesReleaseId(childNamespace.getAppId(),\n                                                                                  parentNamespace.getClusterName(),\n                                                                                  childNamespace.getNamespaceName(),\n                                                                                  childNamespace.getClusterName(),\n                                                                                  release.getId(), operator);\n\n    if (grayReleaseRule != null) {\n      releaseOperationContext.put(ReleaseOperationContext.RULES, GrayReleaseRuleItemTransformer\n          .batchTransformFromJSON(grayReleaseRule.getRules()));\n    }\n\n    releaseHistoryService.createReleaseHistory(parentNamespace.getAppId(), parentNamespace.getClusterName(),\n                                               parentNamespace.getNamespaceName(), childNamespace.getClusterName(),\n                                               release.getId(),\n                                               previousReleaseId, releaseOperation, releaseOperationContext, operator);\n\n    return release;\n  }\n\n  private Map<String, String> mergeConfiguration(Map<String, String> baseConfigurations,\n                                                 Map<String, String> coverConfigurations) {\n    Map<String, String> result = new HashMap<>();\n    //copy base configuration\n    for (Map.Entry<String, String> entry : baseConfigurations.entrySet()) {\n      result.put(entry.getKey(), entry.getValue());\n    }\n\n    //update and publish\n    for (Map.Entry<String, String> entry : coverConfigurations.entrySet()) {\n      result.put(entry.getKey(), entry.getValue());\n    }\n\n    return result;\n  }\n\n\n  private Map<String, String> getNamespaceItems(Namespace namespace) {\n    List<Item> items = itemService.findItemsWithoutOrdered(namespace.getId());\n    Map<String, String> configurations = new HashMap<String, String>();\n    for (Item item : items) {\n      if (StringUtils.isEmpty(item.getKey())) {\n        continue;\n      }\n      configurations.put(item.getKey(), item.getValue());\n    }\n\n    return configurations;\n  }\n\n  private Map<String, String> getNamespaceReleaseConfiguration(Namespace namespace) {\n    Release release = findLatestActiveRelease(namespace);\n    Map<String, String> configuration = new HashMap<>();\n    if (release != null) {\n      configuration = new Gson().fromJson(release.getConfigurations(), GsonType.CONFIG);\n    }\n    return configuration;\n  }\n\n  private Release createRelease(Namespace namespace, String name, String comment,\n                                Map<String, String> configurations, String operator) {\n    Release release = new Release();\n    release.setReleaseKey(ReleaseKeyGenerator.generateReleaseKey(namespace));\n    release.setDataChangeCreatedTime(new Date());\n    release.setDataChangeCreatedBy(operator);\n    release.setDataChangeLastModifiedBy(operator);\n    release.setName(name);\n    release.setComment(comment);\n    release.setAppId(namespace.getAppId());\n    release.setClusterName(namespace.getClusterName());\n    release.setNamespaceName(namespace.getNamespaceName());\n    release.setConfigurations(gson.toJson(configurations));\n    release = releaseRepository.save(release);\n\n    namespaceLockService.unlock(namespace.getId());\n    auditService.audit(Release.class.getSimpleName(), release.getId(), Audit.OP.INSERT,\n                       release.getDataChangeCreatedBy());\n\n    return release;\n  }\n\n  @Transactional\n  public Release rollback(long releaseId, String operator) {\n    Release release = findOne(releaseId);\n    if (release == null) {\n      throw new NotFoundException(\"release not found\");\n    }\n    if (release.isAbandoned()) {\n      throw new BadRequestException(\"release is not active\");\n    }\n\n    String appId = release.getAppId();\n    String clusterName = release.getClusterName();\n    String namespaceName = release.getNamespaceName();\n\n    PageRequest page = new PageRequest(0, 2);\n    List<Release> twoLatestActiveReleases = findActiveReleases(appId, clusterName, namespaceName, page);\n    if (twoLatestActiveReleases == null || twoLatestActiveReleases.size() < 2) {\n      throw new BadRequestException(String.format(\n          \"Can't rollback namespace(appId=%s, clusterName=%s, namespaceName=%s) because there is only one active release\",\n          appId,\n          clusterName,\n          namespaceName));\n    }\n\n    release.setAbandoned(true);\n    release.setDataChangeLastModifiedBy(operator);\n\n    releaseRepository.save(release);\n\n    releaseHistoryService.createReleaseHistory(appId, clusterName,\n                                               namespaceName, clusterName, twoLatestActiveReleases.get(1).getId(),\n                                               release.getId(), ReleaseOperation.ROLLBACK, null, operator);\n\n    //publish child namespace if namespace has child\n    rollbackChildNamespace(appId, clusterName, namespaceName, twoLatestActiveReleases, operator);\n\n    return release;\n  }\n\n  private void rollbackChildNamespace(String appId, String clusterName, String namespaceName,\n                                      List<Release> parentNamespaceTwoLatestActiveRelease, String operator) {\n    Namespace parentNamespace = namespaceService.findOne(appId, clusterName, namespaceName);\n    Namespace childNamespace = namespaceService.findChildNamespace(appId, clusterName, namespaceName);\n    if (parentNamespace == null || childNamespace == null) {\n      return;\n    }\n\n    Release abandonedRelease = parentNamespaceTwoLatestActiveRelease.get(0);\n    Release parentNamespaceNewLatestRelease = parentNamespaceTwoLatestActiveRelease.get(1);\n\n    Map<String, String> parentNamespaceAbandonedConfiguration = gson.fromJson(abandonedRelease.getConfigurations(),\n                                                                              GsonType.CONFIG);\n\n    Map<String, String>\n        parentNamespaceNewLatestConfiguration =\n        gson.fromJson(parentNamespaceNewLatestRelease.getConfigurations(), GsonType.CONFIG);\n\n    Map<String, String>\n        childNamespaceNewConfiguration =\n        calculateChildNamespaceToPublishConfiguration(parentNamespaceAbandonedConfiguration,\n                                                      parentNamespaceNewLatestConfiguration,\n                                                      childNamespace);\n\n    branchRelease(parentNamespace, childNamespace,\n                  TIMESTAMP_FORMAT.format(new Date()) + \"-master-rollback-merge-to-gray\", \"\",\n                  childNamespaceNewConfiguration, parentNamespaceNewLatestRelease.getId(), operator,\n                  ReleaseOperation.MATER_ROLLBACK_MERGE_TO_GRAY, false);\n  }\n\n  private Map<String, String> calculateChildNamespaceToPublishConfiguration(\n      Map<String, String> parentNamespaceOldConfiguration,\n      Map<String, String> parentNamespaceNewConfiguration,\n      Namespace childNamespace) {\n    //first. calculate child namespace modified configs\n    Release childNamespaceLatestActiveRelease = findLatestActiveRelease(childNamespace);\n\n    Map<String, String> childNamespaceLatestActiveConfiguration = childNamespaceLatestActiveRelease == null ? null :\n                                                                  gson.fromJson(childNamespaceLatestActiveRelease\n                                                                                    .getConfigurations(),\n                                                                                GsonType.CONFIG);\n\n    Map<String, String> childNamespaceModifiedConfiguration = calculateBranchModifiedItemsAccordingToRelease(\n        parentNamespaceOldConfiguration, childNamespaceLatestActiveConfiguration);\n\n    //second. append child namespace modified configs to parent namespace new latest configuration\n    return mergeConfiguration(parentNamespaceNewConfiguration, childNamespaceModifiedConfiguration);\n  }\n\n  private Map<String, String> calculateBranchModifiedItemsAccordingToRelease(\n      Map<String, String> masterReleaseConfigs,\n      Map<String, String> branchReleaseConfigs) {\n\n    Map<String, String> modifiedConfigs = new HashMap<>();\n\n    if (CollectionUtils.isEmpty(branchReleaseConfigs)) {\n      return modifiedConfigs;\n    }\n\n    if (CollectionUtils.isEmpty(masterReleaseConfigs)) {\n      return branchReleaseConfigs;\n    }\n\n    for (Map.Entry<String, String> entry : branchReleaseConfigs.entrySet()) {\n\n      if (!Objects.equals(entry.getValue(), masterReleaseConfigs.get(entry.getKey()))) {\n        modifiedConfigs.put(entry.getKey(), entry.getValue());\n      }\n    }\n\n    return modifiedConfigs;\n\n  }\n\n  @Transactional\n  public int batchDelete(String appId, String clusterName, String namespaceName, String operator) {\n    return releaseRepository.batchDelete(appId, clusterName, namespaceName, operator);\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/utils/ConfigChangeContentBuilder.java",
    "content": "package com.ctrip.framework.apollo.biz.utils;\n\nimport com.google.gson.Gson;\nimport com.google.gson.GsonBuilder;\n\nimport com.ctrip.framework.apollo.biz.entity.Item;\nimport com.ctrip.framework.apollo.core.utils.StringUtils;\n\nimport java.util.Date;\nimport java.util.LinkedList;\nimport java.util.List;\nimport org.springframework.beans.BeanUtils;\n\n\npublic class ConfigChangeContentBuilder {\n\n  private static final Gson gson = new GsonBuilder().setDateFormat(\"yyyy-MM-dd HH:mm:ss\").create();\n\n  private List<Item> createItems = new LinkedList<>();\n  private List<ItemPair> updateItems = new LinkedList<>();\n  private List<Item> deleteItems = new LinkedList<>();\n\n\n  public ConfigChangeContentBuilder createItem(Item item) {\n    if (!StringUtils.isEmpty(item.getKey())){\n      createItems.add(cloneItem(item));\n    }\n    return this;\n  }\n\n  public ConfigChangeContentBuilder updateItem(Item oldItem, Item newItem) {\n    if (!oldItem.getValue().equals(newItem.getValue())){\n      ItemPair itemPair = new ItemPair(cloneItem(oldItem), cloneItem(newItem));\n      updateItems.add(itemPair);\n    }\n    return this;\n  }\n\n  public ConfigChangeContentBuilder deleteItem(Item item) {\n    if (!StringUtils.isEmpty(item.getKey())) {\n      deleteItems.add(cloneItem(item));\n    }\n    return this;\n  }\n\n  public boolean hasContent(){\n    return !createItems.isEmpty() || !updateItems.isEmpty() || !deleteItems.isEmpty();\n  }\n\n  public String build() {\n    //因为事务第一段提交并没有更新时间,所以build时统一更新\n    Date now = new Date();\n\n    for (Item item : createItems) {\n      item.setDataChangeLastModifiedTime(now);\n    }\n\n    for (ItemPair item : updateItems) {\n      item.newItem.setDataChangeLastModifiedTime(now);\n    }\n\n    for (Item item : deleteItems) {\n      item.setDataChangeLastModifiedTime(now);\n    }\n    return gson.toJson(this);\n  }\n\n  static class ItemPair {\n\n    Item oldItem;\n    Item newItem;\n\n    public ItemPair(Item oldItem, Item newItem) {\n      this.oldItem = oldItem;\n      this.newItem = newItem;\n    }\n  }\n\n  Item cloneItem(Item source) {\n    Item target = new Item();\n\n    BeanUtils.copyProperties(source, target);\n\n    return target;\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/utils/EntityManagerUtil.java",
    "content": "package com.ctrip.framework.apollo.biz.utils;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.orm.jpa.EntityManagerFactoryAccessor;\nimport org.springframework.orm.jpa.EntityManagerFactoryUtils;\nimport org.springframework.orm.jpa.EntityManagerHolder;\nimport org.springframework.stereotype.Component;\nimport org.springframework.transaction.support.TransactionSynchronizationManager;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@Component\npublic class EntityManagerUtil extends EntityManagerFactoryAccessor {\n  private static final Logger logger = LoggerFactory.getLogger(EntityManagerUtil.class);\n  /**\n   * close the entity manager.\n   * Use it with caution! This is only intended for use with async request, which Spring won't\n   * close the entity manager until the async request is finished.\n   */\n  public void closeEntityManager() {\n    EntityManagerHolder emHolder = (EntityManagerHolder)\n        TransactionSynchronizationManager.getResource(getEntityManagerFactory());\n    if (emHolder == null) {\n      return;\n    }\n    logger.debug(\"Closing JPA EntityManager in EntityManagerUtil\");\n    EntityManagerFactoryUtils.closeEntityManager(emHolder.getEntityManager());\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/utils/ReleaseKeyGenerator.java",
    "content": "package com.ctrip.framework.apollo.biz.utils;\n\n\nimport com.ctrip.framework.apollo.biz.entity.Namespace;\nimport com.ctrip.framework.apollo.common.utils.UniqueKeyGenerator;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class ReleaseKeyGenerator extends UniqueKeyGenerator {\n\n\n  /**\n   * Generate the release key in the format: timestamp+appId+cluster+namespace+hash(ipAsInt+counter)\n   *\n   * @param namespace the namespace of the release\n   * @return the unique release key\n   */\n  public static String generateReleaseKey(Namespace namespace) {\n    return generate(namespace.getAppId(), namespace.getClusterName(), namespace.getNamespaceName());\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/utils/ReleaseMessageKeyGenerator.java",
    "content": "package com.ctrip.framework.apollo.biz.utils;\n\n\nimport com.google.common.base.Joiner;\n\nimport com.ctrip.framework.apollo.core.ConfigConsts;\n\npublic class ReleaseMessageKeyGenerator {\n\n  private static final Joiner STRING_JOINER = Joiner.on(ConfigConsts.CLUSTER_NAMESPACE_SEPARATOR);\n\n  public static String generate(String appId, String cluster, String namespace) {\n    return STRING_JOINER.join(appId, cluster, namespace);\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/test/resources/application.properties",
    "content": "spring.datasource.url = jdbc:h2:mem:~/apolloconfigdb;mode=mysql;DB_CLOSE_ON_EXIT=FALSE\nspring.jpa.hibernate.naming_strategy=org.hibernate.cfg.EJB3NamingStrategy\nspring.jpa.properties.hibernate.show_sql=true\nspring.h2.console.enabled = true\nspring.h2.console.settings.web-allow-others=true\n\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/test/resources/data.sql",
    "content": "INSERT INTO AppNamespace (AppId, Name, IsPublic) VALUES ('100003171', 'application', false);\nINSERT INTO AppNamespace (AppId, Name, IsPublic) VALUES ('100003171', 'fx.apollo.config', true);\nINSERT INTO AppNamespace (AppId, Name, IsPublic) VALUES ('100003172', 'application', false);\nINSERT INTO AppNamespace (AppId, Name, IsPublic) VALUES ('100003172', 'fx.apollo.admin', true);\nINSERT INTO AppNamespace (AppId, Name, IsPublic) VALUES ('100003173', 'application', false);\nINSERT INTO AppNamespace (AppId, Name, IsPublic) VALUES ('100003173', 'fx.apollo.portal', true);\nINSERT INTO AppNamespace (AppID, Name, IsPublic) VALUES ('fxhermesproducer', 'fx.hermes.producer', true);\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/test/resources/logback-test.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<configuration scan=\"true\">\n\t<appender name=\"CONSOLE\" class=\"ch.qos.logback.core.ConsoleAppender\">\n\t\t<encoder>\n\t\t\t<charset>utf-8</charset>\n\t\t\t<Pattern>[%p] %c - %m%n</Pattern>\n\t\t</encoder>\n\t</appender>\n\t<logger name=\"org.springframework.test\" level=\"OFF\" />\n\n\t<root level=\"INFO\">\n\t\t<appender-ref ref=\"CONSOLE\" />\n\t</root>\n\n</configuration>"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/test/resources/sql/clean.sql",
    "content": "DELETE FROM App;\nDELETE FROM AppNamespace;\nDELETE FROM Cluster;\nDELETE FROM namespace;\nDELETE FROM grayreleaserule;\nDELETE FROM release;\nDELETE FROM item;\nDELETE FROM releasemessage;\nDELETE FROM releasehistory;\nDELETE FROM namespacelock;\nDELETE FROM `commit`;\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/test/resources/sql/namespace-branch-test.sql",
    "content": "INSERT INTO `app` ( `AppId`, `Name`, `OrgId`, `OrgName`, `OwnerName`, `OwnerEmail`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES('test', 'test0620-06', 'default', 'default', 'default', 'default', 0, 'default', 'default');\nINSERT INTO `cluster` (`ID`, `Name`, `AppId`, `ParentClusterId`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`) VALUES (1, 'default', 'test', 0, 0, 'default', 'default');\nINSERT INTO `cluster` (`Name`, `AppId`, `ParentClusterId`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES('child-cluster', 'test', 1, 0, 'default', 'default');\n\nINSERT INTO `namespace` (`AppId`, `ClusterName`, `NamespaceName`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES('test', 'default', 'application', 0, 'apollo', 'apollo');\nINSERT INTO `namespace` (`AppId`, `ClusterName`, `NamespaceName`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES('test', 'child-cluster', 'application', 0, 'apollo', 'apollo');\n\n\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/test/resources/sql/namespace-test.sql",
    "content": "INSERT INTO `app` ( `AppId`, `Name`, `OrgId`, `OrgName`, `OwnerName`, `OwnerEmail`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES('testApp', 'test', 'default', 'default', 'default', 'default', 0, 'default', 'default');\n\nINSERT INTO `cluster` (`ID`, `Name`, `AppId`, `ParentClusterId`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`) VALUES (1, 'default', 'testApp', 0, 0, 'default', 'default');\nINSERT INTO `cluster` (`Name`, `AppId`, `ParentClusterId`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES('child-cluster', 'testApp', 1, 0, 'default', 'default');\n\nINSERT INTO `appnamespace` (`Name`, `AppId`, `Format`, `IsPublic`) VALUES ( 'application', 'testApp', 'properties', 0);\n\nINSERT INTO `namespace` (`ID`, `AppId`, `ClusterName`, `NamespaceName`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(1,'testApp', 'default', 'application', 0, 'apollo', 'apollo');\nINSERT INTO `namespace` (`AppId`, `ClusterName`, `NamespaceName`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES('testApp', 'child-cluster', 'application', 0, 'apollo', 'apollo');\n\nINSERT INTO `commit` (`ChangeSets`, `AppId`, `ClusterName`, `NamespaceName`)VALUES('{}', 'testApp', 'default', 'application');\n\nINSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `LineNum`)VALUES(1, 'k1', 'v1', '', 1);\n\nINSERT INTO `namespacelock` (`NamespaceId`)VALUES(1);\n\nINSERT INTO `release` (`AppId`, `ClusterName`, `NamespaceName`, `Configurations`, `IsAbandoned`)VALUES('branch-test', 'default', 'application', '{}', 0);\nINSERT INTO `release` (`AppId`, `ClusterName`, `NamespaceName`, `Configurations`, `IsAbandoned`)VALUES('branch-test', 'child-cluster', 'application', '{}', 0);\n\nINSERT INTO `releasehistory` (`AppId`, `ClusterName`, `NamespaceName`, `BranchName`, `ReleaseId`, `PreviousReleaseId`, `Operation`, `OperationContext`)VALUES('branch-test', 'default', 'application', 'default', 0, 0, 7, '{}');\n\nINSERT INTO `instanceconfig` (`ID`, `InstanceId`, `ConfigAppId`, `ConfigClusterName`, `ConfigNamespaceName`, `ReleaseKey`, `ReleaseDeliveryTime`, `DataChange_CreatedTime`, `DataChange_LastTime`)\nVALUES\n\t(1, 90, 'testApp', 'default', 'application', '20160829134524-dee271ddf9fced58', '2016-08-29 13:45:24', '2016-08-30 17:03:32', '2016-10-19 11:13:47');\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "open-config-center/apollo/apollo-biz/src/test/resources/sql/release-creation-test.sql",
    "content": "INSERT INTO `app` ( `AppId`, `Name`, `OrgId`, `OrgName`, `OwnerName`, `OwnerEmail`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES('test', 'test0620-06', 'default', 'default', 'default', 'default', 0, 'default', 'default');\n\n/* normal namespace*/\nINSERT INTO `cluster` ( `Name`, `AppId`, `ParentClusterId`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`) VALUES ( 'only-master', 'test', 0, 0, 'default', 'default');\nINSERT INTO `namespace` (ID, `AppId`, `ClusterName`, `NamespaceName`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(100, 'test', 'only-master', 'application', 0, 'apollo', 'apollo');\nINSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(100, 'k1', 'v1', '', 'apollo', 'apollo');\nINSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(100, 'k2', 'v2', '', 'apollo', 'apollo');\nINSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(100, 'k3', 'v3', '', 'apollo', 'apollo');\n\n\n/* namespace has branch. master has items but branch has not item*/\nINSERT INTO `cluster` (ID, `Name`, `AppId`, `ParentClusterId`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`) VALUES (101, 'default1', 'test', 0, 0, 'default', 'default');\nINSERT INTO `cluster` (ID, `Name`, `AppId`, `ParentClusterId`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(102, 'child-cluster1', 'test', 101, 0, 'default', 'default');\n\nINSERT INTO `namespace` (ID, `AppId`, `ClusterName`, `NamespaceName`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(101, 'test', 'default1', 'application', 0, 'apollo', 'apollo');\nINSERT INTO `namespace` (ID, `AppId`, `ClusterName`, `NamespaceName`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(102, 'test', 'child-cluster1', 'application', 0, 'apollo', 'apollo');\n\nINSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(101, 'k1', 'v1', '', 'apollo', 'apollo');\nINSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(101, 'k2', 'v2', '', 'apollo', 'apollo');\nINSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(101, 'k3', 'v3', '', 'apollo', 'apollo');\n\nINSERT INTO `grayreleaserule` (`AppId`, `ClusterName`, `NamespaceName`, `BranchName`, `Rules`, `ReleaseId`, `BranchStatus`)VALUES ('test', 'default1', 'application', 'child-cluster1', '[]', 1155, 1);\n\n\n\n/* namespace has branch. master has items and branch has item*/\nINSERT INTO `cluster` (ID, `Name`, `AppId`, `ParentClusterId`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`) VALUES (103, 'default2', 'test', 0, 0, 'default', 'default');\nINSERT INTO `cluster` (ID, `Name`, `AppId`, `ParentClusterId`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(104, 'child-cluster2', 'test', 103, 0, 'default', 'default');\n\nINSERT INTO `namespace` (ID, `AppId`, `ClusterName`, `NamespaceName`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(103, 'test', 'default2', 'application', 0, 'apollo', 'apollo');\nINSERT INTO `namespace` (ID, `AppId`, `ClusterName`, `NamespaceName`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(104, 'test', 'child-cluster2', 'application', 0, 'apollo', 'apollo');\n\nINSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(103, 'k1', 'v1', '', 'apollo', 'apollo');\nINSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(103, 'k2', 'v2', '', 'apollo', 'apollo');\nINSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(103, 'k3', 'v3', '', 'apollo', 'apollo');\nINSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(104, 'k1', 'v1-1', '', 'apollo', 'apollo');\n\nINSERT INTO `grayreleaserule` (`AppId`, `ClusterName`, `NamespaceName`, `BranchName`, `Rules`, `ReleaseId`, `BranchStatus`)VALUES ('test', 'default2', 'application', 'child-cluster2', '[]', 1155, 1);\n\n/* namespace has branch. master has items and branch has cover item */\nINSERT INTO `cluster` (ID, `Name`, `AppId`, `ParentClusterId`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`) VALUES (105, 'default3', 'test', 0, 0, 'default', 'default');\nINSERT INTO `cluster` (ID, `Name`, `AppId`, `ParentClusterId`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(106, 'child-cluster3', 'test', 105, 0, 'default', 'default');\n\nINSERT INTO `namespace` (ID, `AppId`, `ClusterName`, `NamespaceName`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(105, 'test', 'default3', 'application', 0, 'apollo', 'apollo');\nINSERT INTO `namespace` (ID, `AppId`, `ClusterName`, `NamespaceName`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(106, 'test', 'child-cluster3', 'application', 0, 'apollo', 'apollo');\n\nINSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(105, 'k1', 'v1', '', 'apollo', 'apollo');\nINSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(105, 'k2', 'v2-2', '', 'apollo', 'apollo');\nINSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(106, 'k1', 'v1-2', '', 'apollo', 'apollo');\n\nINSERT INTO `release` (`Id`, `ReleaseKey`, `Name`, `Comment`, `AppId`, `ClusterName`, `NamespaceName`, `Configurations`, `IsAbandoned`)VALUES(1, '20160823102253-fc0071ddf9fd3260', '20160823101703-release', '', 'test', 'default3', 'application', '{\"k1\":\"v1\",\"k2\":\"v2\",\"k3\":\"v3\"}', 0);\nINSERT INTO `release` (`Id`, `ReleaseKey`, `Name`, `Comment`, `AppId`, `ClusterName`, `NamespaceName`, `Configurations`, `IsAbandoned`)VALUES(2, '20160823102253-fc0071ddf9fd3260', '20160823101703-release', '', 'test', 'child-cluster3', 'application', '{\"k1\":\"v1-1\",\"k2\":\"v2\",\"k3\":\"v3\"}', 0);\n\nINSERT INTO `grayreleaserule` (`AppId`, `ClusterName`, `NamespaceName`, `BranchName`, `Rules`, `ReleaseId`, `BranchStatus`)VALUES ('test', 'default3', 'application', 'child-cluster3', '[]', 1155, 1);\n\n/*publish branch at first time */\nINSERT INTO `cluster` (ID, `Name`, `AppId`, `ParentClusterId`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`) VALUES (107, 'default4', 'test', 0, 0, 'default', 'default');\nINSERT INTO `cluster` (ID, `Name`, `AppId`, `ParentClusterId`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(108, 'child-cluster4', 'test', 107, 0, 'default', 'default');\n\nINSERT INTO `namespace` (ID, `AppId`, `ClusterName`, `NamespaceName`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(107, 'test', 'default4', 'application', 0, 'apollo', 'apollo');\nINSERT INTO `namespace` (ID, `AppId`, `ClusterName`, `NamespaceName`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(108, 'test', 'child-cluster4', 'application', 0, 'apollo', 'apollo');\n\nINSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(107, 'k1', 'v1', '', 'apollo', 'apollo');\nINSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(107, 'k2', 'v2-2', '', 'apollo', 'apollo');\nINSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(108, 'k1', 'v1-2', '', 'apollo', 'apollo');\nINSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(108, 'k4', 'v4', '', 'apollo', 'apollo');\n\nINSERT INTO `release` (`Id`, `ReleaseKey`, `Name`, `Comment`, `AppId`, `ClusterName`, `NamespaceName`, `Configurations`, `IsAbandoned`)VALUES(3, '20160823102253-fc0071ddf9fd3260', '20160823101703-release', '', 'test', 'default4', 'application', '{\"k1\":\"v1\",\"k2\":\"v2\",\"k3\":\"v3\"}', 0);\n\nINSERT INTO `grayreleaserule` (`AppId`, `ClusterName`, `NamespaceName`, `BranchName`, `Rules`, `ReleaseId`, `BranchStatus`)VALUES ('test', 'default4', 'application', 'child-cluster4', '[]', 1155, 1);\n\n/*publish branch*/\nINSERT INTO `cluster` (ID, `Name`, `AppId`, `ParentClusterId`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`) VALUES (109, 'default5', 'test', 0, 0, 'default', 'default');\nINSERT INTO `cluster` (ID, `Name`, `AppId`, `ParentClusterId`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(1010, 'child-cluster5', 'test', 109, 0, 'default', 'default');\n\nINSERT INTO `namespace` (ID, `AppId`, `ClusterName`, `NamespaceName`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(109, 'test', 'default5', 'application', 0, 'apollo', 'apollo');\nINSERT INTO `namespace` (ID, `AppId`, `ClusterName`, `NamespaceName`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(1010, 'test', 'child-cluster5', 'application', 0, 'apollo', 'apollo');\n\nINSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(109, 'k1', 'v1', '', 'apollo', 'apollo');\nINSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(109, 'k2', 'v2-2', '', 'apollo', 'apollo');\nINSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(1010, 'k1', 'v1-2', '', 'apollo', 'apollo');\nINSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(1010, 'k4', 'v4', '', 'apollo', 'apollo');\nINSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(1010, 'k6', 'v6', '', 'apollo', 'apollo');\n\nINSERT INTO `release` (`Id`, `ReleaseKey`, `Name`, `Comment`, `AppId`, `ClusterName`, `NamespaceName`, `Configurations`, `IsAbandoned`)VALUES(4, '20160823102253-fc0071ddf9fd3260', '20160823101703-release', '', 'test', 'default5', 'application', '{\"k1\":\"v1\",\"k2\":\"v2\",\"k3\":\"v3\"}', 0);\nINSERT INTO `release` (`Id`, `ReleaseKey`, `Name`, `Comment`, `AppId`, `ClusterName`, `NamespaceName`, `Configurations`, `IsAbandoned`)VALUES(5, '20160823102253-fc0071ddf9fd3260', '20160823101703-release', '', 'test', 'child-cluster5', 'application', '{\"k1\":\"v1-1\",\"k2\":\"v2\",\"k3\":\"v3\",\"k4\":\"v4\",\"k5\":\"v5\"}', 0);\n\nINSERT INTO `grayreleaserule` (`AppId`, `ClusterName`, `NamespaceName`, `BranchName`, `Rules`, `ReleaseId`, `BranchStatus`)VALUES ('test', 'default5', 'application', 'child-cluster5', '[]', 1155, 1);\n\n/* rollback */\nINSERT INTO `cluster` (ID, `Name`, `AppId`, `ParentClusterId`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`) VALUES (1011, 'default6', 'test', 0, 0, 'default', 'default');\nINSERT INTO `cluster` (ID, `Name`, `AppId`, `ParentClusterId`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(1012, 'child-cluster6', 'test', 1011, 0, 'default', 'default');\n\nINSERT INTO `namespace` (ID, `AppId`, `ClusterName`, `NamespaceName`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(1011, 'test', 'default6', 'application', 0, 'apollo', 'apollo');\nINSERT INTO `namespace` (ID, `AppId`, `ClusterName`, `NamespaceName`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(1012, 'test', 'child-cluster6', 'application', 0, 'apollo', 'apollo');\n\nINSERT INTO `release` (`Id`, `ReleaseKey`, `Name`, `Comment`, `AppId`, `ClusterName`, `NamespaceName`, `Configurations`, `IsAbandoned`)VALUES(6, '20160823102253-fc0071ddf9fd3260', '20160823101703-release', '', 'test', 'default6', 'application', '{\"k1\":\"v1-1\",\"k2\":\"v2-1\",\"k3\":\"v3\"}', 0);\nINSERT INTO `release` (`Id`, `ReleaseKey`, `Name`, `Comment`, `AppId`, `ClusterName`, `NamespaceName`, `Configurations`, `IsAbandoned`)VALUES(7, '20160823102253-fc0071ddf9fd3260', '20160823101703-release', '', 'test', 'default6', 'application', '{\"k1\":\"v1\",\"k2\":\"v2\"}', 0);\nINSERT INTO `release` (`Id`, `ReleaseKey`, `Name`, `Comment`, `AppId`, `ClusterName`, `NamespaceName`, `Configurations`, `IsAbandoned`)VALUES(8, '20160823102253-fc0071ddf9fd3260', '20160823101703-release', '', 'test', 'child-cluster6', 'application', '{\"k1\":\"v1-2\",\"k2\":\"v2-1\",\"k3\":\"v3\"}', 0);\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/README.md",
    "content": "## I. Prerequisite\n\n### I.I Requirements\n\n* Java: 1.7+\n\n### I.II Mandatory Setup\nApollo client requires `AppId` and `Environment` information available to function properly, so please read the following and configure them properly:\n\n#### 1. AppId\n\nAppId is the identity for the application, which is a key information to retrieve the config from server.\n\nAppId information should be put in `classpath:/META-INF/app.properties` with its key as `app.id`.\n\nFor example, you could place the file as the following screenshot:\n\n![app.properties example](doc/pic/app-id-location.png)\n\nAnd config the file as:\n\n> app.id=YOUR-APP-ID\n\n#### 2. Environment\n\nApollo supports config by multiple environments, so environment is another key information to retrieve the config from server.\n\nEnvironment could be configured in 3 ways:\n\n1. As Java System Property\n\t* You could specify environment as java system property `env`\n\t* For example, when starting the java application, it can be configured via `-Denv=YOUR-ENVIRONMENT`\n\t* Please note the key should be lower case\n\n2. As OS System Environment\n\t* You could also specify environment as system environment `ENV`\n\t* Please note the key should be UPPER CASE\n\n3. As Property File\n\t* You could create a file `/opt/settings/server.properties` on the target machine\n\t* And specify the environment in the file as `env=YOUR-ENVIRONMENT`\n\t* Please note the key should be lower case\n\nCurrently, `env` allows the following values (case-insensitive):\n\n* DEV\n* FWS\n* FAT\n* UAT\n* PRO\n\n### I.III Optional Setup\n\n#### Cluster\n\nApollo supports config separated by clusters, which means for one appId and one environment, you could have different configs.\n\nIf you need this functionality, you could specify the cluster as follows:\n\n1. As Java System Property\n\t* You could specify cluster as java system property `apollo.cluster`\n\t* For example, when starting the java application, it can be configured via `-Dapollo.cluster=xxx`\n\t* Please note the key should be lower case\n2. As Property file\n\t* You could create a file `/opt/settings/server.properties` on the target machine\n\t* And specify the idc cluster in the file as `idc=xxx`\n\t* Please note the key should be lower case\n\n##### Cluster Precedence\n\n1. If both `apollo.cluster` and `idc` are specified:\n\t* We will first try to load config from cluster specified as `apollo.cluster`\n\t* If not found, we will fall back to cluster specified as `idc`\n\t* If still not found, we will fall back to the default cluster `default`\n\n2. If only `apollo.cluster` is specified:\n\t* We will first try to load config from cluster specified as `apollo.cluster`\n\t* If not found, we will fall back to the default cluster `default`\n\n3. If only `idc` is specified:\n\t* We will first try to load config from cluster specified as `idc`\n\t* If not found, we will fall back to the default cluster `default`\n\n4. If neither `apollo.cluster` nor `idc` is specified:\n\t* We will load config from the default cluster `default`\n\n## II. Maven Dependency\n\t\t<dependency>\n\t\t\t<groupId>com.ctrip.framework.apollo</groupId>\n\t\t\t<artifactId>apollo-client</artifactId>\n\t\t\t<version>0.9.1</version>\n\t\t</dependency>\n\n## III. Client Usage\n\n### 1. Load config from default namespace(application)\n```java\nConfig config = ConfigService.getAppConfig();\nString someKey = \"someKeyFromDefaultNamespace\";\nString someDefaultValue = \"someDefaultValueForTheKey\";\nSystem.out.println(String.format(\"Value for key %s is %s\", someKey, config.getProperty(someKey, someDefaultValue)));\n```\n\n### 2. Register config change listener\n```java\nConfig config = ConfigService.getAppConfig();\nconfig.addChangeListener(new ConfigChangeListener() {\n\t@Override\n\tpublic void onChange(ConfigChangeEvent changeEvent) {\n\t\tSystem.out.println(\"Changes for namespace \" + changeEvent.getNamespace());\n\t\tfor (String key : changeEvent.changedKeys()) {\n\t\t\tConfigChange change = changeEvent.getChange(key);\n\t\t\tSystem.out.println(String.format(\"Found change - key: %s, oldValue: %s, newValue: %s, changeType: %s\", change.getPropertyName(), change.getOldValue(), change.getNewValue(), change.getChangeType()));\n\t\t}\n\t}\n});\n```\n\n### 3. Load config from public namespace\n```java\nString somePublicNamespace = \"CAT\";\nConfig config = ConfigService.getConfig(somePublicNamespace);\nString someKey = \"someKeyFromPublicNamespace\";\nString someDefaultValue = \"someDefaultValueForTheKey\";\nSystem.out.println(String.format(\"Value for key %s is %s\", someKey, config.getProperty(someKey, someDefaultValue)));\n```\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/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\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">\n\t<parent>\n\t\t<groupId>com.ctrip.framework.apollo</groupId>\n\t\t<artifactId>apollo</artifactId>\n\t\t<version>0.10.0-SNAPSHOT</version>\n\t</parent>\n\t<modelVersion>4.0.0</modelVersion>\n\t<artifactId>apollo-client</artifactId>\n\t<name>Apollo Client</name>\n\t<properties>\n\t\t<java.version>1.7</java.version>\n\t\t<github.path>${project.artifactId}</github.path>\n\t</properties>\n\t<dependencies>\n\t\t<!-- apollo -->\n\t\t<dependency>\n\t\t\t<groupId>com.ctrip.framework.apollo</groupId>\n\t\t\t<artifactId>apollo-core</artifactId>\n\t\t</dependency>\n\t\t<!-- end of apollo -->\n\t\t<!-- guice -->\n\t\t<dependency>\n\t\t\t<groupId>com.google.inject</groupId>\n\t\t\t<artifactId>guice</artifactId>\n\t\t</dependency>\n\t\t<!-- end of guice -->\n\t\t<!-- log -->\n\t\t<dependency>\n\t\t\t<groupId>org.slf4j</groupId>\n\t\t\t<artifactId>slf4j-api</artifactId>\n\t\t</dependency>\n\t\t<!-- optional spring dependency -->\n\t\t<dependency>\n\t\t\t<groupId>org.springframework</groupId>\n\t\t\t<artifactId>spring-context</artifactId>\n\t\t\t<optional>true</optional>\n\t\t</dependency>\n\t\t<!-- optional spring boot dependency -->\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-autoconfigure</artifactId>\n\t\t\t<optional>true</optional>\n\t\t</dependency>\n\t\t<!-- test -->\n\t\t<dependency>\n\t\t\t<groupId>org.eclipse.jetty</groupId>\n\t\t\t<artifactId>jetty-server</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<!-- take over jcl -->\n\t\t<dependency>\n\t\t\t<groupId>org.slf4j</groupId>\n\t\t\t<artifactId>jcl-over-slf4j</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.apache.logging.log4j</groupId>\n\t\t\t<artifactId>log4j-slf4j-impl</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.apache.logging.log4j</groupId>\n\t\t\t<artifactId>log4j-core</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<!-- end of test -->\n\t</dependencies>\n</project>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/Config.java",
    "content": "package com.ctrip.framework.apollo;\n\nimport java.util.Date;\nimport java.util.Locale;\nimport java.util.Set;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic interface Config {\n  /**\n   * Return the property value with the given key, or {@code defaultValue} if the key doesn't exist.\n   *\n   * @param key          the property name\n   * @param defaultValue the default value when key is not found or any error occurred\n   * @return the property value\n   */\n  public String getProperty(String key, String defaultValue);\n\n  /**\n   * Return the integer property value with the given key, or {@code defaultValue} if the key\n   * doesn't exist.\n   *\n   * @param key          the property name\n   * @param defaultValue the default value when key is not found or any error occurred\n   * @return the property value as integer\n   */\n  public Integer getIntProperty(String key, Integer defaultValue);\n\n  /**\n   * Return the long property value with the given key, or {@code defaultValue} if the key doesn't\n   * exist.\n   *\n   * @param key          the property name\n   * @param defaultValue the default value when key is not found or any error occurred\n   * @return the property value as long\n   */\n  public Long getLongProperty(String key, Long defaultValue);\n\n  /**\n   * Return the short property value with the given key, or {@code defaultValue} if the key doesn't\n   * exist.\n   *\n   * @param key          the property name\n   * @param defaultValue the default value when key is not found or any error occurred\n   * @return the property value as short\n   */\n  public Short getShortProperty(String key, Short defaultValue);\n\n  /**\n   * Return the float property value with the given key, or {@code defaultValue} if the key doesn't\n   * exist.\n   *\n   * @param key          the property name\n   * @param defaultValue the default value when key is not found or any error occurred\n   * @return the property value as float\n   */\n  public Float getFloatProperty(String key, Float defaultValue);\n\n  /**\n   * Return the double property value with the given key, or {@code defaultValue} if the key doesn't\n   * exist.\n   *\n   * @param key          the property name\n   * @param defaultValue the default value when key is not found or any error occurred\n   * @return the property value as double\n   */\n  public Double getDoubleProperty(String key, Double defaultValue);\n\n  /**\n   * Return the byte property value with the given key, or {@code defaultValue} if the key doesn't\n   * exist.\n   *\n   * @param key          the property name\n   * @param defaultValue the default value when key is not found or any error occurred\n   * @return the property value as byte\n   */\n  public Byte getByteProperty(String key, Byte defaultValue);\n\n  /**\n   * Return the boolean property value with the given key, or {@code defaultValue} if the key\n   * doesn't exist.\n   *\n   * @param key          the property name\n   * @param defaultValue the default value when key is not found or any error occurred\n   * @return the property value as boolean\n   */\n  public Boolean getBooleanProperty(String key, Boolean defaultValue);\n\n  /**\n   * Return the array property value with the given key, or {@code defaultValue} if the key doesn't exist.\n   *\n   * @param key          the property name\n   * @param delimiter    the delimiter regex\n   * @param defaultValue the default value when key is not found or any error occurred\n   */\n  public String[] getArrayProperty(String key, String delimiter, String[] defaultValue);\n\n  /**\n   * Return the Date property value with the given name, or {@code defaultValue} if the name doesn't exist.\n   * Will try to parse the date with Locale.US and formats as follows: yyyy-MM-dd HH:mm:ss.SSS,\n   * yyyy-MM-dd HH:mm:ss and yyyy-MM-dd\n   *\n   * @param key          the property name\n   * @param defaultValue the default value when name is not found or any error occurred\n   * @return the property value\n   */\n  public Date getDateProperty(String key, Date defaultValue);\n\n  /**\n   * Return the Date property value with the given name, or {@code defaultValue} if the name doesn't exist.\n   * Will parse the date with the format specified and Locale.US\n   *\n   * @param key          the property name\n   * @param format       the date format, see {@link java.text.SimpleDateFormat} for more\n   *                     information\n   * @param defaultValue the default value when name is not found or any error occurred\n   * @return the property value\n   */\n  public Date getDateProperty(String key, String format, Date defaultValue);\n\n  /**\n   * Return the Date property value with the given name, or {@code defaultValue} if the name doesn't exist.\n   *\n   * @param key          the property name\n   * @param format       the date format, see {@link java.text.SimpleDateFormat} for more\n   *                     information\n   * @param locale       the locale to use\n   * @param defaultValue the default value when name is not found or any error occurred\n   * @return the property value\n   */\n  public Date getDateProperty(String key, String format, Locale locale, Date defaultValue);\n\n  /**\n   * Return the Enum property value with the given key, or {@code defaultValue} if the key doesn't exist.\n   *\n   * @param key          the property name\n   * @param enumType     the enum class\n   * @param defaultValue the default value when key is not found or any error occurred\n   * @param <T>          the enum\n   * @return the property value\n   */\n  public <T extends Enum<T>> T getEnumProperty(String key, Class<T> enumType, T defaultValue);\n\n  /**\n   * Return the duration property value(in milliseconds) with the given name, or {@code\n   * defaultValue} if the name doesn't exist. Please note the format should comply with the follow\n   * example (case insensitive). Examples:\n   * <pre>\n   *    \"123MS\"          -- parses as \"123 milliseconds\"\n   *    \"20S\"            -- parses as \"20 seconds\"\n   *    \"15M\"            -- parses as \"15 minutes\" (where a minute is 60 seconds)\n   *    \"10H\"            -- parses as \"10 hours\" (where an hour is 3600 seconds)\n   *    \"2D\"             -- parses as \"2 days\" (where a day is 24 hours or 86400 seconds)\n   *    \"2D3H4M5S123MS\"  -- parses as \"2 days, 3 hours, 4 minutes, 5 seconds and 123 milliseconds\"\n   * </pre>\n   *\n   * @param key          the property name\n   * @param defaultValue the default value when name is not found or any error occurred\n   * @return the parsed property value(in milliseconds)\n   */\n  public long getDurationProperty(String key, long defaultValue);\n\n  /**\n   * Add change listener to this config instance.\n   *\n   * @param listener the config change listener\n   */\n  public void addChangeListener(ConfigChangeListener listener);\n\n  /**\n   * Return a set of the property names\n   *\n   * @return the property names\n   */\n  public Set<String> getPropertyNames();\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/ConfigChangeListener.java",
    "content": "package com.ctrip.framework.apollo;\n\nimport com.ctrip.framework.apollo.model.ConfigChangeEvent;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic interface ConfigChangeListener {\n  /**\n   * Invoked when there is any config change for the namespace.\n   * @param changeEvent the event for this change\n   */\n  public void onChange(ConfigChangeEvent changeEvent);\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/ConfigFile.java",
    "content": "package com.ctrip.framework.apollo;\n\nimport com.ctrip.framework.apollo.core.enums.ConfigFileFormat;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic interface ConfigFile {\n  /**\n   * Get file content of the namespace\n   * @return file content, {@code null} if there is no content\n   */\n  String getContent();\n\n  /**\n   * Whether the config file has any content\n   * @return true if it has content, false otherwise.\n   */\n  boolean hasContent();\n\n  /**\n   * Get the namespace of this config file instance\n   * @return the namespace\n   */\n  String getNamespace();\n\n  /**\n   * Get the file format of this config file instance\n   * @return the config file format enum\n   */\n  ConfigFileFormat getConfigFileFormat();\n\n  /**\n   * Add change listener to this config file instance.\n   *\n   * @param listener the config file change listener\n   */\n  void addChangeListener(ConfigFileChangeListener listener);\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/ConfigFileChangeListener.java",
    "content": "package com.ctrip.framework.apollo;\n\nimport com.ctrip.framework.apollo.model.ConfigFileChangeEvent;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic interface ConfigFileChangeListener {\n  /**\n   * Invoked when there is any config change for the namespace.\n   * @param changeEvent the event for this change\n   */\n  void onChange(ConfigFileChangeEvent changeEvent);\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/ConfigService.java",
    "content": "package com.ctrip.framework.apollo;\n\nimport com.ctrip.framework.apollo.build.ApolloInjector;\nimport com.ctrip.framework.apollo.core.ConfigConsts;\nimport com.ctrip.framework.apollo.core.enums.ConfigFileFormat;\nimport com.ctrip.framework.apollo.internals.ConfigManager;\nimport com.ctrip.framework.apollo.spi.ConfigFactory;\nimport com.ctrip.framework.apollo.spi.ConfigRegistry;\n\n/**\n * Entry point for client config use\n *\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class ConfigService {\n  private static final ConfigService s_instance = new ConfigService();\n\n  private volatile ConfigManager m_configManager;\n  private volatile ConfigRegistry m_configRegistry;\n\n  private ConfigManager getManager() {\n    if (m_configManager == null) {\n      synchronized (this) {\n        if (m_configManager == null) {\n          m_configManager = ApolloInjector.getInstance(ConfigManager.class);\n        }\n      }\n    }\n\n    return m_configManager;\n  }\n\n  private ConfigRegistry getRegistry() {\n    if (m_configRegistry == null) {\n      synchronized (this) {\n        if (m_configRegistry == null) {\n          m_configRegistry = ApolloInjector.getInstance(ConfigRegistry.class);\n        }\n      }\n    }\n\n    return m_configRegistry;\n  }\n\n  /**\n   * Get Application's config instance.\n   *\n   * @return config instance\n   */\n  public static Config getAppConfig() {\n    return getConfig(ConfigConsts.NAMESPACE_APPLICATION);\n  }\n\n  /**\n   * Get the config instance for the namespace.\n   *\n   * @param namespace the namespace of the config\n   * @return config instance\n   */\n  public static Config getConfig(String namespace) {\n    return s_instance.getManager().getConfig(namespace);\n  }\n\n  public static ConfigFile getConfigFile(String namespace, ConfigFileFormat configFileFormat) {\n    return s_instance.getManager().getConfigFile(namespace, configFileFormat);\n  }\n\n  static void setConfig(Config config) {\n    setConfig(ConfigConsts.NAMESPACE_APPLICATION, config);\n  }\n\n  /**\n   * Manually set the config for the namespace specified, use with caution.\n   *\n   * @param namespace the namespace\n   * @param config    the config instance\n   */\n  static void setConfig(String namespace, final Config config) {\n    s_instance.getRegistry().register(namespace, new ConfigFactory() {\n      @Override\n      public Config create(String namespace) {\n        return config;\n      }\n\n      @Override\n      public ConfigFile createConfigFile(String namespace, ConfigFileFormat configFileFormat) {\n        return null;\n      }\n\n    });\n  }\n\n  static void setConfigFactory(ConfigFactory factory) {\n    setConfigFactory(ConfigConsts.NAMESPACE_APPLICATION, factory);\n  }\n\n  /**\n   * Manually set the config factory for the namespace specified, use with caution.\n   *\n   * @param namespace the namespace\n   * @param factory   the factory instance\n   */\n  static void setConfigFactory(String namespace, ConfigFactory factory) {\n    s_instance.getRegistry().register(namespace, factory);\n  }\n\n  // for test only\n  static void reset() {\n    synchronized (s_instance) {\n      s_instance.m_configManager = null;\n      s_instance.m_configRegistry = null;\n    }\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/build/ApolloInjector.java",
    "content": "package com.ctrip.framework.apollo.build;\n\nimport com.ctrip.framework.apollo.exceptions.ApolloConfigException;\nimport com.ctrip.framework.apollo.internals.Injector;\nimport com.ctrip.framework.apollo.tracer.Tracer;\nimport com.ctrip.framework.foundation.internals.ServiceBootstrap;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class ApolloInjector {\n  private static volatile Injector s_injector;\n  private static Object lock = new Object();\n\n  private static Injector getInjector() {\n    if (s_injector == null) {\n      synchronized (lock) {\n        if (s_injector == null) {\n          try {\n            s_injector = ServiceBootstrap.loadFirst(Injector.class);\n          } catch (Throwable ex) {\n            ApolloConfigException exception = new ApolloConfigException(\"Unable to initialize Apollo Injector!\", ex);\n            Tracer.logError(exception);\n            throw exception;\n          }\n        }\n      }\n    }\n\n    return s_injector;\n  }\n\n  public static <T> T getInstance(Class<T> clazz) {\n    try {\n      return getInjector().getInstance(clazz);\n    } catch (Throwable ex) {\n      Tracer.logError(ex);\n      throw new ApolloConfigException(String.format(\"Unable to load instance for type %s!\", clazz.getName()), ex);\n    }\n  }\n\n  public static <T> T getInstance(Class<T> clazz, String name) {\n    try {\n      return getInjector().getInstance(clazz, name);\n    } catch (Throwable ex) {\n      Tracer.logError(ex);\n      throw new ApolloConfigException(\n          String.format(\"Unable to load instance for type %s and name %s !\", clazz.getName(), name), ex);\n    }\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/enums/PropertyChangeType.java",
    "content": "package com.ctrip.framework.apollo.enums;\n\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic enum PropertyChangeType {\n  ADDED, MODIFIED, DELETED\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/exceptions/ApolloConfigException.java",
    "content": "package com.ctrip.framework.apollo.exceptions;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class ApolloConfigException extends RuntimeException {\n  public ApolloConfigException(String message) {\n    super(message);\n  }\n\n  public ApolloConfigException(String message, Throwable cause) {\n    super(message, cause);\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/exceptions/ApolloConfigStatusCodeException.java",
    "content": "package com.ctrip.framework.apollo.exceptions;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class ApolloConfigStatusCodeException extends RuntimeException{\n  private final int m_statusCode;\n\n  public ApolloConfigStatusCodeException(int statusCode, String message) {\n    super(String.format(\"[status code: %d] %s\", statusCode, message));\n    this.m_statusCode = statusCode;\n  }\n\n  public int getStatusCode() {\n    return m_statusCode;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/AbstractConfig.java",
    "content": "package com.ctrip.framework.apollo.internals;\n\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Locale;\nimport java.util.Map;\nimport java.util.Properties;\nimport java.util.Set;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.atomic.AtomicLong;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.ctrip.framework.apollo.Config;\nimport com.ctrip.framework.apollo.ConfigChangeListener;\nimport com.ctrip.framework.apollo.build.ApolloInjector;\nimport com.ctrip.framework.apollo.core.utils.ApolloThreadFactory;\nimport com.ctrip.framework.apollo.enums.PropertyChangeType;\nimport com.ctrip.framework.apollo.exceptions.ApolloConfigException;\nimport com.ctrip.framework.apollo.model.ConfigChange;\nimport com.ctrip.framework.apollo.model.ConfigChangeEvent;\nimport com.ctrip.framework.apollo.tracer.Tracer;\nimport com.ctrip.framework.apollo.tracer.spi.Transaction;\nimport com.ctrip.framework.apollo.util.ConfigUtil;\nimport com.ctrip.framework.apollo.util.function.Functions;\nimport com.ctrip.framework.apollo.util.parser.Parsers;\nimport com.google.common.base.Function;\nimport com.google.common.base.Objects;\nimport com.google.common.cache.Cache;\nimport com.google.common.cache.CacheBuilder;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport com.google.common.collect.Sets;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic abstract class AbstractConfig implements Config {\n  private static final Logger logger = LoggerFactory.getLogger(AbstractConfig.class);\n\n  private static ExecutorService m_executorService;\n\n  private List<ConfigChangeListener> m_listeners = Lists.newCopyOnWriteArrayList();\n  private ConfigUtil m_configUtil;\n  private volatile Cache<String, Integer> m_integerCache;\n  private volatile Cache<String, Long> m_longCache;\n  private volatile Cache<String, Short> m_shortCache;\n  private volatile Cache<String, Float> m_floatCache;\n  private volatile Cache<String, Double> m_doubleCache;\n  private volatile Cache<String, Byte> m_byteCache;\n  private volatile Cache<String, Boolean> m_booleanCache;\n  private volatile Cache<String, Date> m_dateCache;\n  private volatile Cache<String, Long> m_durationCache;\n  private Map<String, Cache<String, String[]>> m_arrayCache;\n  private List<Cache> allCaches;\n  private AtomicLong m_configVersion; //indicate config version\n\n  static {\n    m_executorService = Executors.newCachedThreadPool(ApolloThreadFactory\n        .create(\"Config\", true));\n  }\n\n  public AbstractConfig() {\n      m_configUtil = ApolloInjector.getInstance(ConfigUtil.class);\n      m_configVersion = new AtomicLong();\n      m_arrayCache = Maps.newConcurrentMap();\n      allCaches = Lists.newArrayList();\n  }\n\n  @Override\n  public void addChangeListener(ConfigChangeListener listener) {\n    if (!m_listeners.contains(listener)) {\n      m_listeners.add(listener);\n    }\n  }\n\n  @Override\n  public Integer getIntProperty(String key, Integer defaultValue) {\n    try {\n      if (m_integerCache == null) {\n        synchronized (this) {\n          if (m_integerCache == null) {\n            m_integerCache = newCache();\n          }\n        }\n      }\n\n      return getValueFromCache(key, Functions.TO_INT_FUNCTION, m_integerCache, defaultValue);\n    } catch (Throwable ex) {\n      Tracer.logError(new ApolloConfigException(\n          String.format(\"getIntProperty for %s failed, return default value %d\", key,\n              defaultValue), ex));\n    }\n    return defaultValue;\n  }\n\n  @Override\n  public Long getLongProperty(String key, Long defaultValue) {\n    try {\n      if (m_longCache == null) {\n        synchronized (this) {\n          if (m_longCache == null) {\n            m_longCache = newCache();\n          }\n        }\n      }\n\n      return getValueFromCache(key, Functions.TO_LONG_FUNCTION, m_longCache, defaultValue);\n    } catch (Throwable ex) {\n      Tracer.logError(new ApolloConfigException(\n          String.format(\"getLongProperty for %s failed, return default value %d\", key,\n              defaultValue), ex));\n    }\n    return defaultValue;\n  }\n\n  @Override\n  public Short getShortProperty(String key, Short defaultValue) {\n    try {\n      if (m_shortCache == null) {\n        synchronized (this) {\n          if (m_shortCache == null) {\n            m_shortCache = newCache();\n          }\n        }\n      }\n\n      return getValueFromCache(key, Functions.TO_SHORT_FUNCTION, m_shortCache, defaultValue);\n    } catch (Throwable ex) {\n      Tracer.logError(new ApolloConfigException(\n          String.format(\"getShortProperty for %s failed, return default value %d\", key,\n              defaultValue), ex));\n    }\n    return defaultValue;\n  }\n\n  @Override\n  public Float getFloatProperty(String key, Float defaultValue) {\n    try {\n      if (m_floatCache == null) {\n        synchronized (this) {\n          if (m_floatCache == null) {\n            m_floatCache = newCache();\n          }\n        }\n      }\n\n      return getValueFromCache(key, Functions.TO_FLOAT_FUNCTION, m_floatCache, defaultValue);\n    } catch (Throwable ex) {\n      Tracer.logError(new ApolloConfigException(\n          String.format(\"getFloatProperty for %s failed, return default value %f\", key,\n              defaultValue), ex));\n    }\n    return defaultValue;\n  }\n\n  @Override\n  public Double getDoubleProperty(String key, Double defaultValue) {\n    try {\n      if (m_doubleCache == null) {\n        synchronized (this) {\n          if (m_doubleCache == null) {\n            m_doubleCache = newCache();\n          }\n        }\n      }\n\n      return getValueFromCache(key, Functions.TO_DOUBLE_FUNCTION, m_doubleCache, defaultValue);\n    } catch (Throwable ex) {\n      Tracer.logError(new ApolloConfigException(\n          String.format(\"getDoubleProperty for %s failed, return default value %f\", key,\n              defaultValue), ex));\n    }\n    return defaultValue;\n  }\n\n  @Override\n  public Byte getByteProperty(String key, Byte defaultValue) {\n    try {\n      if (m_byteCache == null) {\n        synchronized (this) {\n          if (m_byteCache == null) {\n            m_byteCache = newCache();\n          }\n        }\n      }\n\n      return getValueFromCache(key, Functions.TO_BYTE_FUNCTION, m_byteCache, defaultValue);\n    } catch (Throwable ex) {\n      Tracer.logError(new ApolloConfigException(\n          String.format(\"getByteProperty for %s failed, return default value %d\", key,\n              defaultValue), ex));\n    }\n    return defaultValue;\n  }\n\n  @Override\n  public Boolean getBooleanProperty(String key, Boolean defaultValue) {\n    try {\n      if (m_booleanCache == null) {\n        synchronized (this) {\n          if (m_booleanCache == null) {\n            m_booleanCache = newCache();\n          }\n        }\n      }\n\n      return getValueFromCache(key, Functions.TO_BOOLEAN_FUNCTION, m_booleanCache, defaultValue);\n    } catch (Throwable ex) {\n      Tracer.logError(new ApolloConfigException(\n          String.format(\"getBooleanProperty for %s failed, return default value %b\", key,\n              defaultValue), ex));\n    }\n    return defaultValue;\n  }\n\n  @Override\n  public String[] getArrayProperty(String key, final String delimiter, String[] defaultValue) {\n    try {\n      if (!m_arrayCache.containsKey(delimiter)) {\n        synchronized (this) {\n          if (!m_arrayCache.containsKey(delimiter)) {\n            m_arrayCache.put(delimiter, this.<String[]>newCache());\n          }\n        }\n      }\n\n      Cache<String, String[]> cache = m_arrayCache.get(delimiter);\n      String[] result = cache.getIfPresent(key);\n\n      if (result != null) {\n        return result;\n      }\n\n      return getValueAndStoreToCache(key, new Function<String, String[]>() {\n        @Override\n        public String[] apply(String input) {\n          return input.split(delimiter);\n        }\n      }, cache, defaultValue);\n    } catch (Throwable ex) {\n      Tracer.logError(new ApolloConfigException(\n          String.format(\"getArrayProperty for %s failed, return default value\", key), ex));\n    }\n    return defaultValue;\n  }\n\n  @Override\n  public <T extends Enum<T>> T getEnumProperty(String key, Class<T> enumType, T defaultValue) {\n    try {\n      String value = getProperty(key, null);\n\n      if (value != null) {\n        return Enum.valueOf(enumType, value);\n      }\n    } catch (Throwable ex) {\n      Tracer.logError(new ApolloConfigException(\n          String.format(\"getEnumProperty for %s failed, return default value %s\", key,\n              defaultValue), ex));\n    }\n\n    return defaultValue;\n  }\n\n  @Override\n  public Date getDateProperty(String key, Date defaultValue) {\n    try {\n      if (m_dateCache == null) {\n        synchronized (this) {\n          if (m_dateCache == null) {\n            m_dateCache = newCache();\n          }\n        }\n      }\n\n      return getValueFromCache(key, Functions.TO_DATE_FUNCTION, m_dateCache, defaultValue);\n    } catch (Throwable ex) {\n      Tracer.logError(new ApolloConfigException(\n          String.format(\"getDateProperty for %s failed, return default value %s\", key,\n              defaultValue), ex));\n    }\n\n    return defaultValue;\n  }\n\n  @Override\n  public Date getDateProperty(String key, String format, Date defaultValue) {\n    try {\n      String value = getProperty(key, null);\n\n      if (value != null) {\n        return Parsers.forDate().parse(value, format);\n      }\n    } catch (Throwable ex) {\n      Tracer.logError(new ApolloConfigException(\n          String.format(\"getDateProperty for %s failed, return default value %s\", key,\n              defaultValue), ex));\n    }\n\n    return defaultValue;\n  }\n\n  @Override\n  public Date getDateProperty(String key, String format, Locale locale, Date defaultValue) {\n    try {\n      String value = getProperty(key, null);\n\n      if (value != null) {\n        return Parsers.forDate().parse(value, format, locale);\n      }\n    } catch (Throwable ex) {\n      Tracer.logError(new ApolloConfigException(\n          String.format(\"getDateProperty for %s failed, return default value %s\", key,\n              defaultValue), ex));\n    }\n\n    return defaultValue;\n  }\n\n  @Override\n  public long getDurationProperty(String key, long defaultValue) {\n    try {\n      if (m_durationCache == null) {\n        synchronized (this) {\n          if (m_durationCache == null) {\n            m_durationCache = newCache();\n          }\n        }\n      }\n\n      return getValueFromCache(key, Functions.TO_DURATION_FUNCTION, m_durationCache, defaultValue);\n    } catch (Throwable ex) {\n      Tracer.logError(new ApolloConfigException(\n          String.format(\"getDurationProperty for %s failed, return default value %d\", key,\n              defaultValue), ex));\n    }\n\n    return defaultValue;\n  }\n\n  private <T> T getValueFromCache(String key, Function<String, T> parser, Cache<String, T> cache, T defaultValue) {\n    T result = cache.getIfPresent(key);\n\n    if (result != null) {\n      return result;\n    }\n\n    return getValueAndStoreToCache(key, parser, cache, defaultValue);\n  }\n\n  private <T> T getValueAndStoreToCache(String key, Function<String, T> parser, Cache<String, T> cache, T defaultValue) {\n    long currentConfigVersion = m_configVersion.get();\n    String value = getProperty(key, null);\n\n    if (value != null) {\n      T result = parser.apply(value);\n\n      if (result != null) {\n        synchronized (this) {\n          if (m_configVersion.get() == currentConfigVersion) {\n            cache.put(key, result);\n          }\n        }\n        return result;\n      }\n    }\n\n    return defaultValue;\n  }\n\n  private <T> Cache<String, T> newCache() {\n    Cache<String, T> cache = CacheBuilder.newBuilder()\n        .maximumSize(m_configUtil.getMaxConfigCacheSize())\n        .expireAfterAccess(m_configUtil.getConfigCacheExpireTime(), m_configUtil.getConfigCacheExpireTimeUnit())\n        .build();\n    allCaches.add(cache);\n    return cache;\n  }\n\n  /**\n   * Clear config cache\n   */\n  protected void clearConfigCache() {\n    synchronized (this) {\n      for (Cache c : allCaches) {\n        if (c != null) {\n          c.invalidateAll();\n        }\n      }\n      m_configVersion.incrementAndGet();\n    }\n  }\n\n  protected void fireConfigChange(final ConfigChangeEvent changeEvent) {\n    for (final ConfigChangeListener listener : m_listeners) {\n      m_executorService.submit(new Runnable() {\n        @Override\n        public void run() {\n          String listenerName = listener.getClass().getName();\n          Transaction transaction = Tracer.newTransaction(\"Apollo.ConfigChangeListener\", listenerName);\n          try {\n            listener.onChange(changeEvent);\n            transaction.setStatus(Transaction.SUCCESS);\n          } catch (Throwable ex) {\n            transaction.setStatus(ex);\n            Tracer.logError(ex);\n            logger.error(\"Failed to invoke config change listener {}\", listenerName, ex);\n          } finally {\n            transaction.complete();\n          }\n        }\n      });\n    }\n  }\n\n  List<ConfigChange> calcPropertyChanges(String namespace, Properties previous,\n                                         Properties current) {\n    if (previous == null) {\n      previous = new Properties();\n    }\n\n    if (current == null) {\n      current = new Properties();\n    }\n\n    Set<String> previousKeys = previous.stringPropertyNames();\n    Set<String> currentKeys = current.stringPropertyNames();\n\n    Set<String> commonKeys = Sets.intersection(previousKeys, currentKeys);\n    Set<String> newKeys = Sets.difference(currentKeys, commonKeys);\n    Set<String> removedKeys = Sets.difference(previousKeys, commonKeys);\n\n    List<ConfigChange> changes = Lists.newArrayList();\n\n    for (String newKey : newKeys) {\n      changes.add(new ConfigChange(namespace, newKey, null, current.getProperty(newKey),\n          PropertyChangeType.ADDED));\n    }\n\n    for (String removedKey : removedKeys) {\n      changes.add(new ConfigChange(namespace, removedKey, previous.getProperty(removedKey), null,\n          PropertyChangeType.DELETED));\n    }\n\n    for (String commonKey : commonKeys) {\n      String previousValue = previous.getProperty(commonKey);\n      String currentValue = current.getProperty(commonKey);\n      if (Objects.equal(previousValue, currentValue)) {\n        continue;\n      }\n      changes.add(new ConfigChange(namespace, commonKey, previousValue, currentValue,\n          PropertyChangeType.MODIFIED));\n    }\n\n    return changes;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/AbstractConfigFile.java",
    "content": "package com.ctrip.framework.apollo.internals;\n\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.Properties;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.ctrip.framework.apollo.ConfigFile;\nimport com.ctrip.framework.apollo.ConfigFileChangeListener;\nimport com.ctrip.framework.apollo.core.utils.ApolloThreadFactory;\nimport com.ctrip.framework.apollo.enums.PropertyChangeType;\nimport com.ctrip.framework.apollo.model.ConfigFileChangeEvent;\nimport com.ctrip.framework.apollo.tracer.Tracer;\nimport com.ctrip.framework.apollo.tracer.spi.Transaction;\nimport com.ctrip.framework.apollo.util.ExceptionUtil;\nimport com.google.common.collect.Lists;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic abstract class AbstractConfigFile implements ConfigFile, RepositoryChangeListener {\n  private static final Logger logger = LoggerFactory.getLogger(AbstractConfigFile.class);\n  private static ExecutorService m_executorService;\n  protected ConfigRepository m_configRepository;\n  protected String m_namespace;\n  protected AtomicReference<Properties> m_configProperties;\n  private List<ConfigFileChangeListener> m_listeners = Lists.newCopyOnWriteArrayList();\n\n  static {\n    m_executorService = Executors.newCachedThreadPool(ApolloThreadFactory\n        .create(\"ConfigFile\", true));\n  }\n\n  public AbstractConfigFile(String namespace, ConfigRepository configRepository) {\n    m_configRepository = configRepository;\n    m_namespace = namespace;\n    m_configProperties = new AtomicReference<>();\n    initialize();\n  }\n\n  private void initialize() {\n    try {\n      m_configProperties.set(m_configRepository.getConfig());\n    } catch (Throwable ex) {\n      Tracer.logError(ex);\n      logger.warn(\"Init Apollo Config File failed - namespace: {}, reason: {}.\",\n          m_namespace, ExceptionUtil.getDetailMessage(ex));\n    } finally {\n      //register the change listener no matter config repository is working or not\n      //so that whenever config repository is recovered, config could get changed\n      m_configRepository.addChangeListener(this);\n    }\n  }\n\n  @Override\n  public String getNamespace() {\n    return m_namespace;\n  }\n\n  protected abstract void update(Properties newProperties);\n\n  @Override\n  public synchronized void onRepositoryChange(String namespace, Properties newProperties) {\n    if (newProperties.equals(m_configProperties.get())) {\n      return;\n    }\n    Properties newConfigProperties = new Properties();\n    newConfigProperties.putAll(newProperties);\n\n    String oldValue = getContent();\n\n    update(newProperties);\n\n    String newValue = getContent();\n\n    PropertyChangeType changeType = PropertyChangeType.MODIFIED;\n\n    if (oldValue == null) {\n      changeType = PropertyChangeType.ADDED;\n    } else if (newValue == null) {\n      changeType = PropertyChangeType.DELETED;\n    }\n\n    this.fireConfigChange(new ConfigFileChangeEvent(m_namespace, oldValue, newValue, changeType));\n\n    Tracer.logEvent(\"Apollo.Client.ConfigChanges\", m_namespace);\n  }\n\n  @Override\n  public void addChangeListener(ConfigFileChangeListener listener) {\n    if (!m_listeners.contains(listener)) {\n      m_listeners.add(listener);\n    }\n  }\n\n  private void fireConfigChange(final ConfigFileChangeEvent changeEvent) {\n    for (final ConfigFileChangeListener listener : m_listeners) {\n      m_executorService.submit(new Runnable() {\n        @Override\n        public void run() {\n          String listenerName = listener.getClass().getName();\n          Transaction transaction = Tracer.newTransaction(\"Apollo.ConfigFileChangeListener\", listenerName);\n          try {\n            listener.onChange(changeEvent);\n            transaction.setStatus(Transaction.SUCCESS);\n          } catch (Throwable ex) {\n            transaction.setStatus(ex);\n            Tracer.logError(ex);\n            logger.error(\"Failed to invoke config file change listener {}\", listenerName, ex);\n          } finally {\n            transaction.complete();\n          }\n        }\n      });\n    }\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/AbstractConfigRepository.java",
    "content": "package com.ctrip.framework.apollo.internals;\n\nimport java.util.List;\nimport java.util.Properties;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.ctrip.framework.apollo.tracer.Tracer;\nimport com.ctrip.framework.apollo.util.ExceptionUtil;\nimport com.google.common.collect.Lists;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic abstract class AbstractConfigRepository implements ConfigRepository {\n  private static final Logger logger = LoggerFactory.getLogger(AbstractConfigRepository.class);\n  private List<RepositoryChangeListener> m_listeners = Lists.newCopyOnWriteArrayList();\n\n  protected boolean trySync() {\n    try {\n      sync();\n      return true;\n    } catch (Throwable ex) {\n      Tracer.logEvent(\"ApolloConfigException\", ExceptionUtil.getDetailMessage(ex));\n      logger\n          .warn(\"Sync config failed, will retry. Repository {}, reason: {}\", this.getClass(), ExceptionUtil\n              .getDetailMessage(ex));\n    }\n    return false;\n  }\n\n  protected abstract void sync();\n\n  @Override\n  public void addChangeListener(RepositoryChangeListener listener) {\n    if (!m_listeners.contains(listener)) {\n      m_listeners.add(listener);\n    }\n  }\n\n  @Override\n  public void removeChangeListener(RepositoryChangeListener listener) {\n    m_listeners.remove(listener);\n  }\n\n  protected void fireRepositoryChange(String namespace, Properties newProperties) {\n    for (RepositoryChangeListener listener : m_listeners) {\n      try {\n        listener.onRepositoryChange(namespace, newProperties);\n      } catch (Throwable ex) {\n        Tracer.logError(ex);\n        logger.error(\"Failed to invoke repository change listener {}\", listener.getClass(), ex);\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/ConfigManager.java",
    "content": "package com.ctrip.framework.apollo.internals;\n\nimport com.ctrip.framework.apollo.Config;\nimport com.ctrip.framework.apollo.ConfigFile;\nimport com.ctrip.framework.apollo.core.enums.ConfigFileFormat;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic interface ConfigManager {\n  /**\n   * Get the config instance for the namespace specified.\n   * @param namespace the namespace\n   * @return the config instance for the namespace\n   */\n  public Config getConfig(String namespace);\n\n  /**\n   * Get the config file instance for the namespace specified.\n   * @param namespace the namespace\n   * @param configFileFormat the config file format\n   * @return the config file instance for the namespace\n   */\n  public ConfigFile getConfigFile(String namespace, ConfigFileFormat configFileFormat);\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/ConfigRepository.java",
    "content": "package com.ctrip.framework.apollo.internals;\n\nimport java.util.Properties;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic interface ConfigRepository {\n  /**\n   * Get the config from this repository.\n   * @return config\n   */\n  public Properties getConfig();\n\n  /**\n   * Set the fallback repo for this repository.\n   * @param upstreamConfigRepository the upstream repo\n   */\n  public void setUpstreamRepository(ConfigRepository upstreamConfigRepository);\n\n  /**\n   * Add change listener.\n   * @param listener the listener to observe the changes\n   */\n  public void addChangeListener(RepositoryChangeListener listener);\n\n  /**\n   * Remove change listener.\n   * @param listener the listener to remove\n   */\n  public void removeChangeListener(RepositoryChangeListener listener);\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/ConfigServiceLocator.java",
    "content": "package com.ctrip.framework.apollo.internals;\n\nimport java.lang.reflect.Type;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.ctrip.framework.apollo.build.ApolloInjector;\nimport com.ctrip.framework.apollo.core.dto.ServiceDTO;\nimport com.ctrip.framework.apollo.core.utils.ApolloThreadFactory;\nimport com.ctrip.framework.apollo.exceptions.ApolloConfigException;\nimport com.ctrip.framework.apollo.tracer.Tracer;\nimport com.ctrip.framework.apollo.tracer.spi.Transaction;\nimport com.ctrip.framework.apollo.util.ConfigUtil;\nimport com.ctrip.framework.apollo.util.ExceptionUtil;\nimport com.ctrip.framework.apollo.util.http.HttpRequest;\nimport com.ctrip.framework.apollo.util.http.HttpResponse;\nimport com.ctrip.framework.apollo.util.http.HttpUtil;\nimport com.google.common.base.Joiner;\nimport com.google.common.base.Strings;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport com.google.common.escape.Escaper;\nimport com.google.common.net.UrlEscapers;\nimport com.google.gson.reflect.TypeToken;\n\npublic class ConfigServiceLocator {\n  private static final Logger logger = LoggerFactory.getLogger(ConfigServiceLocator.class);\n  private HttpUtil m_httpUtil;\n  private ConfigUtil m_configUtil;\n  private AtomicReference<List<ServiceDTO>> m_configServices;\n  private Type m_responseType;\n  private ScheduledExecutorService m_executorService;\n  private static final Joiner.MapJoiner MAP_JOINER = Joiner.on(\"&\").withKeyValueSeparator(\"=\");\n  private static final Escaper queryParamEscaper = UrlEscapers.urlFormParameterEscaper();\n\n  /**\n   * Create a config service locator.\n   */\n  public ConfigServiceLocator() {\n    List<ServiceDTO> initial = Lists.newArrayList();\n    m_configServices = new AtomicReference<>(initial);\n    m_responseType = new TypeToken<List<ServiceDTO>>() {\n    }.getType();\n    m_httpUtil = ApolloInjector.getInstance(HttpUtil.class);\n    m_configUtil = ApolloInjector.getInstance(ConfigUtil.class);\n    this.m_executorService = Executors.newScheduledThreadPool(1,\n        ApolloThreadFactory.create(\"ConfigServiceLocator\", true));\n    this.tryUpdateConfigServices();\n    this.schedulePeriodicRefresh();\n  }\n\n  /**\n   * Get the config service info from remote meta server.\n   *\n   * @return the services dto\n   */\n  public List<ServiceDTO> getConfigServices() {\n    if (m_configServices.get().isEmpty()) {\n      updateConfigServices();\n    }\n\n    return m_configServices.get();\n  }\n\n  private boolean tryUpdateConfigServices() {\n    try {\n      updateConfigServices();\n      return true;\n    } catch (Throwable ex) {\n      //ignore\n    }\n    return false;\n  }\n\n  private void schedulePeriodicRefresh() {\n    this.m_executorService.scheduleAtFixedRate(\n        new Runnable() {\n          @Override\n          public void run() {\n            logger.debug(\"refresh config services\");\n            Tracer.logEvent(\"Apollo.MetaService\", \"periodicRefresh\");\n            tryUpdateConfigServices();\n          }\n        }, m_configUtil.getRefreshInterval(), m_configUtil.getRefreshInterval(),\n        m_configUtil.getRefreshIntervalTimeUnit());\n  }\n\n  private synchronized void updateConfigServices() {\n    String url = assembleMetaServiceUrl();\n\n    HttpRequest request = new HttpRequest(url);\n    int maxRetries = 2;\n    Throwable exception = null;\n\n    for (int i = 0; i < maxRetries; i++) {\n      Transaction transaction = Tracer.newTransaction(\"Apollo.MetaService\", \"getConfigService\");\n      transaction.addData(\"Url\", url);\n      try {\n        HttpResponse<List<ServiceDTO>> response = m_httpUtil.doGet(request, m_responseType);\n        transaction.setStatus(Transaction.SUCCESS);\n        List<ServiceDTO> services = response.getBody();\n        if (services == null || services.isEmpty()) {\n          logConfigService(\"Empty response!\");\n          continue;\n        }\n        m_configServices.set(services);\n        logConfigServices(services);\n        return;\n      } catch (Throwable ex) {\n        Tracer.logEvent(\"ApolloConfigException\", ExceptionUtil.getDetailMessage(ex));\n        transaction.setStatus(ex);\n        exception = ex;\n      } finally {\n        transaction.complete();\n      }\n\n      try {\n        m_configUtil.getOnErrorRetryIntervalTimeUnit().sleep(m_configUtil.getOnErrorRetryInterval());\n      } catch (InterruptedException ex) {\n        //ignore\n      }\n    }\n\n    throw new ApolloConfigException(\n        String.format(\"Get config services failed from %s\", url), exception);\n  }\n\n  private String assembleMetaServiceUrl() {\n    String domainName = m_configUtil.getMetaServerDomainName();\n    String appId = m_configUtil.getAppId();\n    String localIp = m_configUtil.getLocalIp();\n\n    Map<String, String> queryParams = Maps.newHashMap();\n    queryParams.put(\"appId\", queryParamEscaper.escape(appId));\n    if (!Strings.isNullOrEmpty(localIp)) {\n      queryParams.put(\"ip\", queryParamEscaper.escape(localIp));\n    }\n\n    return domainName + \"/services/config?\" + MAP_JOINER.join(queryParams);\n  }\n\n  private void logConfigServices(List<ServiceDTO> serviceDtos) {\n    for (ServiceDTO serviceDto : serviceDtos) {\n      logConfigService(serviceDto.getHomepageUrl());\n    }\n  }\n\n  private void logConfigService(String serviceUrl) {\n    Tracer.logEvent(\"Apollo.Config.Services\", serviceUrl);\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/DefaultConfig.java",
    "content": "package com.ctrip.framework.apollo.internals;\n\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Properties;\nimport java.util.Set;\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.ctrip.framework.apollo.core.utils.ClassLoaderUtil;\nimport com.ctrip.framework.apollo.enums.PropertyChangeType;\nimport com.ctrip.framework.apollo.model.ConfigChange;\nimport com.ctrip.framework.apollo.model.ConfigChangeEvent;\nimport com.ctrip.framework.apollo.tracer.Tracer;\nimport com.ctrip.framework.apollo.util.ExceptionUtil;\nimport com.google.common.collect.ImmutableMap;\nimport com.google.common.util.concurrent.RateLimiter;\n\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class DefaultConfig extends AbstractConfig implements RepositoryChangeListener {\n  private static final Logger logger = LoggerFactory.getLogger(DefaultConfig.class);\n  private final String m_namespace;\n  private Properties m_resourceProperties;\n  private AtomicReference<Properties> m_configProperties;\n  private ConfigRepository m_configRepository;\n  private RateLimiter m_warnLogRateLimiter;\n\n  /**\n   * Constructor.\n   *\n   * @param namespace        the namespace of this config instance\n   * @param configRepository the config repository for this config instance\n   */\n  public DefaultConfig(String namespace, ConfigRepository configRepository) {\n    m_namespace = namespace;\n    m_resourceProperties = loadFromResource(m_namespace);\n    m_configRepository = configRepository;\n    m_configProperties = new AtomicReference<>();\n    m_warnLogRateLimiter = RateLimiter.create(0.017); // 1 warning log output per minute\n    initialize();\n  }\n\n  private void initialize() {\n    try {\n      m_configProperties.set(m_configRepository.getConfig());\n    } catch (Throwable ex) {\n      Tracer.logError(ex);\n      logger.warn(\"Init Apollo Local Config failed - namespace: {}, reason: {}.\",\n          m_namespace, ExceptionUtil.getDetailMessage(ex));\n    } finally {\n      //register the change listener no matter config repository is working or not\n      //so that whenever config repository is recovered, config could get changed\n      m_configRepository.addChangeListener(this);\n    }\n  }\n\n  @Override\n  public String getProperty(String key, String defaultValue) {\n    // step 1: check system properties, i.e. -Dkey=value\n    String value = System.getProperty(key);\n\n    // step 2: check local cached properties file\n    if (value == null && m_configProperties.get() != null) {\n      value = m_configProperties.get().getProperty(key);\n    }\n\n    /**\n     * step 3: check env variable, i.e. PATH=...\n     * normally system environment variables are in UPPERCASE, however there might be exceptions.\n     * so the caller should provide the key in the right case\n     */\n    if (value == null) {\n      value = System.getenv(key);\n    }\n\n    // step 4: check properties file from classpath\n    if (value == null && m_resourceProperties != null) {\n      value = (String) m_resourceProperties.get(key);\n    }\n\n    if (value == null && m_configProperties.get() == null && m_warnLogRateLimiter.tryAcquire()) {\n      logger.warn(\"Could not load config for namespace {} from Apollo, please check whether the configs are released in Apollo! Return default value now!\", m_namespace);\n    }\n\n    return value == null ? defaultValue : value;\n  }\n\n  @Override\n  public Set<String> getPropertyNames() {\n    Properties properties = m_configProperties.get();\n    if (properties == null) {\n      return Collections.emptySet();\n    }\n\n    return properties.stringPropertyNames();\n  }\n\n  @Override\n  public synchronized void onRepositoryChange(String namespace, Properties newProperties) {\n    if (newProperties.equals(m_configProperties.get())) {\n      return;\n    }\n    Properties newConfigProperties = new Properties();\n    newConfigProperties.putAll(newProperties);\n\n    Map<String, ConfigChange> actualChanges = updateAndCalcConfigChanges(newConfigProperties);\n\n    //check double checked result\n    if (actualChanges.isEmpty()) {\n      return;\n    }\n\n    this.fireConfigChange(new ConfigChangeEvent(m_namespace, actualChanges));\n\n    Tracer.logEvent(\"Apollo.Client.ConfigChanges\", m_namespace);\n  }\n\n  private Map<String, ConfigChange> updateAndCalcConfigChanges(Properties newConfigProperties) {\n    List<ConfigChange> configChanges =\n        calcPropertyChanges(m_namespace, m_configProperties.get(), newConfigProperties);\n\n    ImmutableMap.Builder<String, ConfigChange> actualChanges =\n        new ImmutableMap.Builder<>();\n\n    /** === Double check since DefaultConfig has multiple config sources ==== **/\n\n    //1. use getProperty to update configChanges's old value\n    for (ConfigChange change : configChanges) {\n      change.setOldValue(this.getProperty(change.getPropertyName(), change.getOldValue()));\n    }\n\n    //2. update m_configProperties\n    m_configProperties.set(newConfigProperties);\n    clearConfigCache();\n\n    //3. use getProperty to update configChange's new value and calc the final changes\n    for (ConfigChange change : configChanges) {\n      change.setNewValue(this.getProperty(change.getPropertyName(), change.getNewValue()));\n      switch (change.getChangeType()) {\n        case ADDED:\n          if (Objects.equals(change.getOldValue(), change.getNewValue())) {\n            break;\n          }\n          if (change.getOldValue() != null) {\n            change.setChangeType(PropertyChangeType.MODIFIED);\n          }\n          actualChanges.put(change.getPropertyName(), change);\n          break;\n        case MODIFIED:\n          if (!Objects.equals(change.getOldValue(), change.getNewValue())) {\n            actualChanges.put(change.getPropertyName(), change);\n          }\n          break;\n        case DELETED:\n          if (Objects.equals(change.getOldValue(), change.getNewValue())) {\n            break;\n          }\n          if (change.getNewValue() != null) {\n            change.setChangeType(PropertyChangeType.MODIFIED);\n          }\n          actualChanges.put(change.getPropertyName(), change);\n          break;\n        default:\n          //do nothing\n          break;\n      }\n    }\n    return actualChanges.build();\n  }\n\n  private Properties loadFromResource(String namespace) {\n    String name = String.format(\"META-INF/config/%s.properties\", namespace);\n    InputStream in = ClassLoaderUtil.getLoader().getResourceAsStream(name);\n    Properties properties = null;\n\n    if (in != null) {\n      properties = new Properties();\n\n      try {\n        properties.load(in);\n      } catch (IOException ex) {\n        Tracer.logError(ex);\n        logger.error(\"Load resource config for namespace {} failed\", namespace, ex);\n      } finally {\n        try {\n          in.close();\n        } catch (IOException ex) {\n          // ignore\n        }\n      }\n    }\n\n    return properties;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/DefaultConfigManager.java",
    "content": "package com.ctrip.framework.apollo.internals;\n\nimport java.util.Map;\n\nimport com.ctrip.framework.apollo.Config;\nimport com.ctrip.framework.apollo.ConfigFile;\nimport com.ctrip.framework.apollo.build.ApolloInjector;\nimport com.ctrip.framework.apollo.core.enums.ConfigFileFormat;\nimport com.ctrip.framework.apollo.spi.ConfigFactory;\nimport com.ctrip.framework.apollo.spi.ConfigFactoryManager;\nimport com.google.common.collect.Maps;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class DefaultConfigManager implements ConfigManager {\n  private ConfigFactoryManager m_factoryManager;\n\n  private Map<String, Config> m_configs = Maps.newConcurrentMap();\n  private Map<String, ConfigFile> m_configFiles = Maps.newConcurrentMap();\n\n  public DefaultConfigManager() {\n    m_factoryManager = ApolloInjector.getInstance(ConfigFactoryManager.class);\n  }\n\n  @Override\n  public Config getConfig(String namespace) {\n    Config config = m_configs.get(namespace);\n\n    if (config == null) {\n      synchronized (this) {\n        config = m_configs.get(namespace);\n\n        if (config == null) {\n          ConfigFactory factory = m_factoryManager.getFactory(namespace);\n\n          config = factory.create(namespace);\n          m_configs.put(namespace, config);\n        }\n      }\n    }\n\n    return config;\n  }\n\n  @Override\n  public ConfigFile getConfigFile(String namespace, ConfigFileFormat configFileFormat) {\n    String namespaceFileName = String.format(\"%s.%s\", namespace, configFileFormat.getValue());\n    ConfigFile configFile = m_configFiles.get(namespaceFileName);\n\n    if (configFile == null) {\n      synchronized (this) {\n        configFile = m_configFiles.get(namespaceFileName);\n\n        if (configFile == null) {\n          ConfigFactory factory = m_factoryManager.getFactory(namespaceFileName);\n\n          configFile = factory.createConfigFile(namespaceFileName, configFileFormat);\n          m_configFiles.put(namespaceFileName, configFile);\n        }\n      }\n    }\n\n    return configFile;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/DefaultInjector.java",
    "content": "package com.ctrip.framework.apollo.internals;\n\nimport com.ctrip.framework.apollo.exceptions.ApolloConfigException;\nimport com.ctrip.framework.apollo.spi.ConfigFactory;\nimport com.ctrip.framework.apollo.spi.ConfigFactoryManager;\nimport com.ctrip.framework.apollo.spi.ConfigRegistry;\nimport com.ctrip.framework.apollo.spi.DefaultConfigFactory;\nimport com.ctrip.framework.apollo.spi.DefaultConfigFactoryManager;\nimport com.ctrip.framework.apollo.spi.DefaultConfigRegistry;\nimport com.ctrip.framework.apollo.spring.config.ConfigPropertySourceFactory;\nimport com.ctrip.framework.apollo.spring.property.PlaceholderHelper;\nimport com.ctrip.framework.apollo.tracer.Tracer;\nimport com.ctrip.framework.apollo.util.ConfigUtil;\nimport com.ctrip.framework.apollo.util.http.HttpUtil;\n\nimport com.google.inject.AbstractModule;\nimport com.google.inject.Guice;\nimport com.google.inject.Singleton;\n\n/**\n * Guice injector\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class DefaultInjector implements Injector {\n  private com.google.inject.Injector m_injector;\n\n  public DefaultInjector() {\n    try {\n      m_injector = Guice.createInjector(new ApolloModule());\n    } catch (Throwable ex) {\n      ApolloConfigException exception = new ApolloConfigException(\"Unable to initialize Guice Injector!\", ex);\n      Tracer.logError(exception);\n      throw exception;\n    }\n  }\n\n  @Override\n  public <T> T getInstance(Class<T> clazz) {\n    try {\n      return m_injector.getInstance(clazz);\n    } catch (Throwable ex) {\n      Tracer.logError(ex);\n      throw new ApolloConfigException(\n          String.format(\"Unable to load instance for %s!\", clazz.getName()), ex);\n    }\n  }\n\n  @Override\n  public <T> T getInstance(Class<T> clazz, String name) {\n    //Guice does not support get instance by type and name\n    return null;\n  }\n\n  private static class ApolloModule extends AbstractModule {\n    @Override\n    protected void configure() {\n      bind(ConfigManager.class).to(DefaultConfigManager.class).in(Singleton.class);\n      bind(ConfigFactoryManager.class).to(DefaultConfigFactoryManager.class).in(Singleton.class);\n      bind(ConfigRegistry.class).to(DefaultConfigRegistry.class).in(Singleton.class);\n      bind(ConfigFactory.class).to(DefaultConfigFactory.class).in(Singleton.class);\n      bind(ConfigUtil.class).in(Singleton.class);\n      bind(HttpUtil.class).in(Singleton.class);\n      bind(ConfigServiceLocator.class).in(Singleton.class);\n      bind(RemoteConfigLongPollService.class).in(Singleton.class);\n      bind(PlaceholderHelper.class).in(Singleton.class);\n      bind(ConfigPropertySourceFactory.class).in(Singleton.class);\n    }\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/Injector.java",
    "content": "package com.ctrip.framework.apollo.internals;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic interface Injector {\n\n  /**\n   * Returns the appropriate instance for the given injection type\n   */\n  <T> T getInstance(Class<T> clazz);\n\n  /**\n   * Returns the appropriate instance for the given injection type and name\n   */\n  <T> T getInstance(Class<T> clazz, String name);\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/JsonConfigFile.java",
    "content": "package com.ctrip.framework.apollo.internals;\n\nimport com.ctrip.framework.apollo.core.enums.ConfigFileFormat;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class JsonConfigFile extends PlainTextConfigFile {\n  public JsonConfigFile(String namespace,\n                        ConfigRepository configRepository) {\n    super(namespace, configRepository);\n  }\n\n  @Override\n  public ConfigFileFormat getConfigFileFormat() {\n    return ConfigFileFormat.JSON;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/LocalFileConfigRepository.java",
    "content": "package com.ctrip.framework.apollo.internals;\n\nimport java.io.File;\nimport java.io.FileInputStream;\nimport java.io.FileOutputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.OutputStream;\nimport java.nio.file.Files;\nimport java.nio.file.Path;\nimport java.nio.file.Paths;\nimport java.util.Properties;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.ctrip.framework.apollo.build.ApolloInjector;\nimport com.ctrip.framework.apollo.core.ConfigConsts;\nimport com.ctrip.framework.apollo.core.utils.ClassLoaderUtil;\nimport com.ctrip.framework.apollo.exceptions.ApolloConfigException;\nimport com.ctrip.framework.apollo.tracer.Tracer;\nimport com.ctrip.framework.apollo.tracer.spi.Transaction;\nimport com.ctrip.framework.apollo.util.ConfigUtil;\nimport com.ctrip.framework.apollo.util.ExceptionUtil;\nimport com.google.common.base.Joiner;\nimport com.google.common.base.Preconditions;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class LocalFileConfigRepository extends AbstractConfigRepository\n    implements RepositoryChangeListener {\n  private static final Logger logger = LoggerFactory.getLogger(LocalFileConfigRepository.class);\n  private static final String CONFIG_DIR = \"/config-cache\";\n  private final String m_namespace;\n  private File m_baseDir;\n  private final ConfigUtil m_configUtil;\n  private volatile Properties m_fileProperties;\n  private volatile ConfigRepository m_upstream;\n\n  /**\n   * Constructor.\n   *\n   * @param namespace the namespace\n   */\n  public LocalFileConfigRepository(String namespace) {\n    this(namespace, null);\n  }\n\n  public LocalFileConfigRepository(String namespace, ConfigRepository upstream) {\n    m_namespace = namespace;\n    m_configUtil = ApolloInjector.getInstance(ConfigUtil.class);\n    this.setLocalCacheDir(findLocalCacheDir(), false);\n    this.setUpstreamRepository(upstream);\n    this.trySync();\n  }\n\n  void setLocalCacheDir(File baseDir, boolean syncImmediately) {\n    m_baseDir = baseDir;\n    this.checkLocalConfigCacheDir(m_baseDir);\n    if (syncImmediately) {\n      this.trySync();\n    }\n  }\n\n  private File findLocalCacheDir() {\n    try {\n      String defaultCacheDir = m_configUtil.getDefaultLocalCacheDir();\n      Path path = Paths.get(defaultCacheDir);\n      if (!Files.exists(path)) {\n        Files.createDirectories(path);\n      }\n      if (Files.exists(path) && Files.isWritable(path)) {\n        return new File(defaultCacheDir, CONFIG_DIR);\n      }\n    } catch (Throwable ex) {\n      //ignore\n    }\n\n    return new File(ClassLoaderUtil.getClassPath(), CONFIG_DIR);\n  }\n\n  @Override\n  public Properties getConfig() {\n    if (m_fileProperties == null) {\n      sync();\n    }\n    Properties result = new Properties();\n    result.putAll(m_fileProperties);\n    return result;\n  }\n\n  @Override\n  public void setUpstreamRepository(ConfigRepository upstreamConfigRepository) {\n    if (upstreamConfigRepository == null) {\n      return;\n    }\n    //clear previous listener\n    if (m_upstream != null) {\n      m_upstream.removeChangeListener(this);\n    }\n    m_upstream = upstreamConfigRepository;\n    trySyncFromUpstream();\n    upstreamConfigRepository.addChangeListener(this);\n  }\n\n  @Override\n  public void onRepositoryChange(String namespace, Properties newProperties) {\n    if (newProperties.equals(m_fileProperties)) {\n      return;\n    }\n    Properties newFileProperties = new Properties();\n    newFileProperties.putAll(newProperties);\n    updateFileProperties(newFileProperties);\n    this.fireRepositoryChange(namespace, newProperties);\n  }\n\n  @Override\n  protected void sync() {\n    //sync with upstream immediately\n    boolean syncFromUpstreamResultSuccess = trySyncFromUpstream();\n\n    if (syncFromUpstreamResultSuccess) {\n      return;\n    }\n\n    Transaction transaction = Tracer.newTransaction(\"Apollo.ConfigService\", \"syncLocalConfig\");\n    Throwable exception = null;\n    try {\n      transaction.addData(\"Basedir\", m_baseDir.getAbsolutePath());\n      m_fileProperties = this.loadFromLocalCacheFile(m_baseDir, m_namespace);\n      transaction.setStatus(Transaction.SUCCESS);\n    } catch (Throwable ex) {\n      Tracer.logEvent(\"ApolloConfigException\", ExceptionUtil.getDetailMessage(ex));\n      transaction.setStatus(ex);\n      exception = ex;\n      //ignore\n    } finally {\n      transaction.complete();\n    }\n\n    if (m_fileProperties == null) {\n      throw new ApolloConfigException(\n          \"Load config from local config failed!\", exception);\n    }\n  }\n\n  private boolean trySyncFromUpstream() {\n    if (m_upstream == null) {\n      return false;\n    }\n    try {\n      Properties properties = m_upstream.getConfig();\n      updateFileProperties(properties);\n      return true;\n    } catch (Throwable ex) {\n      Tracer.logError(ex);\n      logger\n          .warn(\"Sync config from upstream repository {} failed, reason: {}\", m_upstream.getClass(),\n              ExceptionUtil.getDetailMessage(ex));\n    }\n    return false;\n  }\n\n  private synchronized void updateFileProperties(Properties newProperties) {\n    if (newProperties.equals(m_fileProperties)) {\n      return;\n    }\n    this.m_fileProperties = newProperties;\n    persistLocalCacheFile(m_baseDir, m_namespace);\n  }\n\n  private Properties loadFromLocalCacheFile(File baseDir, String namespace) throws IOException {\n    Preconditions.checkNotNull(baseDir, \"Basedir cannot be null\");\n\n    File file = assembleLocalCacheFile(baseDir, namespace);\n    Properties properties = null;\n\n    if (file.isFile() && file.canRead()) {\n      InputStream in = null;\n\n      try {\n        in = new FileInputStream(file);\n\n        properties = new Properties();\n        properties.load(in);\n        logger.debug(\"Loading local config file {} successfully!\", file.getAbsolutePath());\n      } catch (IOException ex) {\n        Tracer.logError(ex);\n        throw new ApolloConfigException(String\n            .format(\"Loading config from local cache file %s failed\", file.getAbsolutePath()), ex);\n      } finally {\n        try {\n          if (in != null) {\n            in.close();\n          }\n        } catch (IOException ex) {\n          // ignore\n        }\n      }\n    } else {\n      throw new ApolloConfigException(\n          String.format(\"Cannot read from local cache file %s\", file.getAbsolutePath()));\n    }\n\n    return properties;\n  }\n\n  void persistLocalCacheFile(File baseDir, String namespace) {\n    if (baseDir == null) {\n      return;\n    }\n    File file = assembleLocalCacheFile(baseDir, namespace);\n\n    OutputStream out = null;\n\n    Transaction transaction = Tracer.newTransaction(\"Apollo.ConfigService\", \"persistLocalConfigFile\");\n    transaction.addData(\"LocalConfigFile\", file.getAbsolutePath());\n    try {\n      out = new FileOutputStream(file);\n      m_fileProperties.store(out, \"Persisted by DefaultConfig\");\n      transaction.setStatus(Transaction.SUCCESS);\n    } catch (IOException ex) {\n      ApolloConfigException exception =\n          new ApolloConfigException(\n              String.format(\"Persist local cache file %s failed\", file.getAbsolutePath()), ex);\n      Tracer.logError(exception);\n      transaction.setStatus(exception);\n      logger.warn(\"Persist local cache file {} failed, reason: {}.\", file.getAbsolutePath(),\n          ExceptionUtil.getDetailMessage(ex));\n    } finally {\n      if (out != null) {\n        try {\n          out.close();\n        } catch (IOException ex) {\n          //ignore\n        }\n      }\n      transaction.complete();\n    }\n  }\n\n  private void checkLocalConfigCacheDir(File baseDir) {\n    if (baseDir.exists()) {\n      return;\n    }\n    Transaction transaction = Tracer.newTransaction(\"Apollo.ConfigService\", \"createLocalConfigDir\");\n    transaction.addData(\"BaseDir\", baseDir.getAbsolutePath());\n    try {\n      Files.createDirectory(baseDir.toPath());\n      transaction.setStatus(Transaction.SUCCESS);\n    } catch (IOException ex) {\n      ApolloConfigException exception =\n          new ApolloConfigException(\n              String.format(\"Create local config directory %s failed\", baseDir.getAbsolutePath()),\n              ex);\n      Tracer.logError(exception);\n      transaction.setStatus(exception);\n      logger.warn(\n          \"Unable to create local config cache directory {}, reason: {}. Will not able to cache config file.\",\n          baseDir.getAbsolutePath(), ExceptionUtil.getDetailMessage(ex));\n    } finally {\n      transaction.complete();\n    }\n  }\n\n  File assembleLocalCacheFile(File baseDir, String namespace) {\n    String fileName =\n        String.format(\"%s.properties\", Joiner.on(ConfigConsts.CLUSTER_NAMESPACE_SEPARATOR)\n            .join(m_configUtil.getAppId(), m_configUtil.getCluster(), namespace));\n    return new File(baseDir, fileName);\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/PlainTextConfigFile.java",
    "content": "package com.ctrip.framework.apollo.internals;\n\nimport com.ctrip.framework.apollo.core.ConfigConsts;\nimport java.util.Properties;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic abstract class PlainTextConfigFile extends AbstractConfigFile {\n\n  public PlainTextConfigFile(String namespace, ConfigRepository configRepository) {\n    super(namespace, configRepository);\n  }\n\n  @Override\n  public String getContent() {\n    if (!this.hasContent()) {\n      return null;\n    }\n    return m_configProperties.get().getProperty(ConfigConsts.CONFIG_FILE_CONTENT_KEY);\n  }\n\n  @Override\n  public boolean hasContent() {\n    if (m_configProperties.get() == null) {\n      return false;\n    }\n    return m_configProperties.get().containsKey(ConfigConsts.CONFIG_FILE_CONTENT_KEY);\n  }\n\n  @Override\n  protected void update(Properties newProperties) {\n    m_configProperties.set(newProperties);\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/PropertiesConfigFile.java",
    "content": "package com.ctrip.framework.apollo.internals;\n\nimport java.util.Properties;\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.ctrip.framework.apollo.core.enums.ConfigFileFormat;\nimport com.ctrip.framework.apollo.core.utils.PropertiesUtil;\nimport com.ctrip.framework.apollo.exceptions.ApolloConfigException;\nimport com.ctrip.framework.apollo.tracer.Tracer;\nimport com.ctrip.framework.apollo.util.ExceptionUtil;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class PropertiesConfigFile extends AbstractConfigFile {\n  private static final Logger logger = LoggerFactory.getLogger(PropertiesConfigFile.class);\n  protected AtomicReference<String> m_contentCache;\n\n  public PropertiesConfigFile(String namespace,\n                              ConfigRepository configRepository) {\n    super(namespace, configRepository);\n    m_contentCache = new AtomicReference<>();\n  }\n\n  @Override\n  protected void update(Properties newProperties) {\n    m_configProperties.set(newProperties);\n    m_contentCache.set(null);\n  }\n\n  @Override\n  public String getContent() {\n    if (m_contentCache.get() == null) {\n      m_contentCache.set(doGetContent());\n    }\n    return m_contentCache.get();\n  }\n\n  String doGetContent() {\n    if (!this.hasContent()) {\n      return null;\n    }\n\n    try {\n      return PropertiesUtil.toString(m_configProperties.get());\n    } catch (Throwable ex) {\n      ApolloConfigException exception =\n          new ApolloConfigException(String\n              .format(\"Parse properties file content failed for namespace: %s, cause: %s\",\n                  m_namespace, ExceptionUtil.getDetailMessage(ex)));\n      Tracer.logError(exception);\n      throw exception;\n    }\n  }\n\n  @Override\n  public boolean hasContent() {\n    return m_configProperties.get() != null && !m_configProperties.get().isEmpty();\n  }\n\n  @Override\n  public ConfigFileFormat getConfigFileFormat() {\n    return ConfigFileFormat.Properties;\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/RemoteConfigLongPollService.java",
    "content": "package com.ctrip.framework.apollo.internals;\n\nimport com.google.common.base.Joiner;\nimport com.google.common.base.Strings;\nimport com.google.common.collect.HashMultimap;\nimport com.google.common.collect.ImmutableMap;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport com.google.common.collect.Multimap;\nimport com.google.common.collect.Multimaps;\nimport com.google.common.escape.Escaper;\nimport com.google.common.net.UrlEscapers;\nimport com.google.common.reflect.TypeToken;\nimport com.google.common.util.concurrent.RateLimiter;\nimport com.google.gson.Gson;\n\nimport com.ctrip.framework.apollo.build.ApolloInjector;\nimport com.ctrip.framework.apollo.core.ConfigConsts;\nimport com.ctrip.framework.apollo.core.dto.ApolloConfigNotification;\nimport com.ctrip.framework.apollo.core.dto.ApolloNotificationMessages;\nimport com.ctrip.framework.apollo.core.dto.ServiceDTO;\nimport com.ctrip.framework.apollo.core.enums.ConfigFileFormat;\nimport com.ctrip.framework.apollo.core.schedule.ExponentialSchedulePolicy;\nimport com.ctrip.framework.apollo.core.schedule.SchedulePolicy;\nimport com.ctrip.framework.apollo.core.utils.ApolloThreadFactory;\nimport com.ctrip.framework.apollo.exceptions.ApolloConfigException;\nimport com.ctrip.framework.apollo.tracer.Tracer;\nimport com.ctrip.framework.apollo.tracer.spi.Transaction;\nimport com.ctrip.framework.apollo.util.ConfigUtil;\nimport com.ctrip.framework.apollo.util.ExceptionUtil;\nimport com.ctrip.framework.apollo.util.http.HttpRequest;\nimport com.ctrip.framework.apollo.util.http.HttpResponse;\nimport com.ctrip.framework.apollo.util.http.HttpUtil;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.lang.reflect.Type;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Random;\nimport java.util.concurrent.ConcurrentMap;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class RemoteConfigLongPollService {\n  private static final Logger logger = LoggerFactory.getLogger(RemoteConfigLongPollService.class);\n  private static final Joiner STRING_JOINER = Joiner.on(ConfigConsts.CLUSTER_NAMESPACE_SEPARATOR);\n  private static final Joiner.MapJoiner MAP_JOINER = Joiner.on(\"&\").withKeyValueSeparator(\"=\");\n  private static final Escaper queryParamEscaper = UrlEscapers.urlFormParameterEscaper();\n  private static final long INIT_NOTIFICATION_ID = ConfigConsts.NOTIFICATION_ID_PLACEHOLDER;\n  private final ExecutorService m_longPollingService;\n  private final AtomicBoolean m_longPollingStopped;\n  private SchedulePolicy m_longPollFailSchedulePolicyInSecond;\n  private RateLimiter m_longPollRateLimiter;\n  private final AtomicBoolean m_longPollStarted;\n  private final Multimap<String, RemoteConfigRepository> m_longPollNamespaces;\n  private final ConcurrentMap<String, Long> m_notifications;\n  private final Map<String, ApolloNotificationMessages> m_remoteNotificationMessages;//namespaceName -> watchedKey -> notificationId\n  private Type m_responseType;\n  private Gson gson;\n  private ConfigUtil m_configUtil;\n  private HttpUtil m_httpUtil;\n  private ConfigServiceLocator m_serviceLocator;\n\n  /**\n   * Constructor.\n   */\n  public RemoteConfigLongPollService() {\n    m_longPollFailSchedulePolicyInSecond = new ExponentialSchedulePolicy(1, 120); //in second\n    m_longPollingStopped = new AtomicBoolean(false);\n    m_longPollingService = Executors.newSingleThreadExecutor(\n        ApolloThreadFactory.create(\"RemoteConfigLongPollService\", true));\n    m_longPollStarted = new AtomicBoolean(false);\n    m_longPollNamespaces =\n        Multimaps.synchronizedSetMultimap(HashMultimap.<String, RemoteConfigRepository>create());\n    m_notifications = Maps.newConcurrentMap();\n    m_remoteNotificationMessages = Maps.newConcurrentMap();\n    m_responseType = new TypeToken<List<ApolloConfigNotification>>() {\n    }.getType();\n    gson = new Gson();\n    m_configUtil = ApolloInjector.getInstance(ConfigUtil.class);\n    m_httpUtil = ApolloInjector.getInstance(HttpUtil.class);\n    m_serviceLocator = ApolloInjector.getInstance(ConfigServiceLocator.class);\n    m_longPollRateLimiter = RateLimiter.create(m_configUtil.getLongPollQPS());\n  }\n\n  public boolean submit(String namespace, RemoteConfigRepository remoteConfigRepository) {\n    boolean added = m_longPollNamespaces.put(namespace, remoteConfigRepository);\n    m_notifications.putIfAbsent(namespace, INIT_NOTIFICATION_ID);\n    if (!m_longPollStarted.get()) {\n      startLongPolling();\n    }\n    return added;\n  }\n\n  private void startLongPolling() {\n    if (!m_longPollStarted.compareAndSet(false, true)) {\n      //already started\n      return;\n    }\n    try {\n      final String appId = m_configUtil.getAppId();\n      final String cluster = m_configUtil.getCluster();\n      final String dataCenter = m_configUtil.getDataCenter();\n      final long longPollingInitialDelayInMills = m_configUtil.getLongPollingInitialDelayInMills();\n      m_longPollingService.submit(new Runnable() {\n        @Override\n        public void run() {\n          if (longPollingInitialDelayInMills > 0) {\n            try {\n              logger.debug(\"Long polling will start in {} ms.\", longPollingInitialDelayInMills);\n              TimeUnit.MILLISECONDS.sleep(longPollingInitialDelayInMills);\n            } catch (InterruptedException e) {\n              //ignore\n            }\n          }\n          doLongPollingRefresh(appId, cluster, dataCenter);\n        }\n      });\n    } catch (Throwable ex) {\n      m_longPollStarted.set(false);\n      ApolloConfigException exception =\n          new ApolloConfigException(\"Schedule long polling refresh failed\", ex);\n      Tracer.logError(exception);\n      logger.warn(ExceptionUtil.getDetailMessage(exception));\n    }\n  }\n\n  void stopLongPollingRefresh() {\n    this.m_longPollingStopped.compareAndSet(false, true);\n  }\n\n  private void doLongPollingRefresh(String appId, String cluster, String dataCenter) {\n    final Random random = new Random();\n    ServiceDTO lastServiceDto = null;\n    while (!m_longPollingStopped.get() && !Thread.currentThread().isInterrupted()) {\n      if (!m_longPollRateLimiter.tryAcquire(5, TimeUnit.SECONDS)) {\n        //wait at most 5 seconds\n        try {\n          TimeUnit.SECONDS.sleep(5);\n        } catch (InterruptedException e) {\n        }\n      }\n      Transaction transaction = Tracer.newTransaction(\"Apollo.ConfigService\", \"pollNotification\");\n      String url = null;\n      try {\n        if (lastServiceDto == null) {\n          List<ServiceDTO> configServices = getConfigServices();\n          lastServiceDto = configServices.get(random.nextInt(configServices.size()));\n        }\n\n        url =\n            assembleLongPollRefreshUrl(lastServiceDto.getHomepageUrl(), appId, cluster, dataCenter,\n                m_notifications);\n\n        logger.debug(\"Long polling from {}\", url);\n        HttpRequest request = new HttpRequest(url);\n        //longer timeout for read - 10 minutes\n        request.setReadTimeout(600000);\n\n        transaction.addData(\"Url\", url);\n\n        final HttpResponse<List<ApolloConfigNotification>> response =\n            m_httpUtil.doGet(request, m_responseType);\n\n        logger.debug(\"Long polling response: {}, url: {}\", response.getStatusCode(), url);\n        if (response.getStatusCode() == 200 && response.getBody() != null) {\n          updateNotifications(response.getBody());\n          updateRemoteNotifications(response.getBody());\n          transaction.addData(\"Result\", response.getBody().toString());\n          notify(lastServiceDto, response.getBody());\n        }\n\n        //try to load balance\n        if (response.getStatusCode() == 304 && random.nextBoolean()) {\n          lastServiceDto = null;\n        }\n\n        m_longPollFailSchedulePolicyInSecond.success();\n        transaction.addData(\"StatusCode\", response.getStatusCode());\n        transaction.setStatus(Transaction.SUCCESS);\n      } catch (Throwable ex) {\n        lastServiceDto = null;\n        Tracer.logEvent(\"ApolloConfigException\", ExceptionUtil.getDetailMessage(ex));\n        transaction.setStatus(ex);\n        long sleepTimeInSecond = m_longPollFailSchedulePolicyInSecond.fail();\n        logger.warn(\n            \"Long polling failed, will retry in {} seconds. appId: {}, cluster: {}, namespaces: {}, long polling url: {}, reason: {}\",\n            sleepTimeInSecond, appId, cluster, assembleNamespaces(), url, ExceptionUtil.getDetailMessage(ex));\n        try {\n          TimeUnit.SECONDS.sleep(sleepTimeInSecond);\n        } catch (InterruptedException ie) {\n          //ignore\n        }\n      } finally {\n        transaction.complete();\n      }\n    }\n  }\n\n  private void notify(ServiceDTO lastServiceDto, List<ApolloConfigNotification> notifications) {\n    if (notifications == null || notifications.isEmpty()) {\n      return;\n    }\n    for (ApolloConfigNotification notification : notifications) {\n      String namespaceName = notification.getNamespaceName();\n      //create a new list to avoid ConcurrentModificationException\n      List<RemoteConfigRepository> toBeNotified =\n          Lists.newArrayList(m_longPollNamespaces.get(namespaceName));\n      ApolloNotificationMessages originalMessages = m_remoteNotificationMessages.get(namespaceName);\n      ApolloNotificationMessages remoteMessages = originalMessages == null ? null : originalMessages.clone();\n      //since .properties are filtered out by default, so we need to check if there is any listener for it\n      toBeNotified.addAll(m_longPollNamespaces\n          .get(String.format(\"%s.%s\", namespaceName, ConfigFileFormat.Properties.getValue())));\n      for (RemoteConfigRepository remoteConfigRepository : toBeNotified) {\n        try {\n          remoteConfigRepository.onLongPollNotified(lastServiceDto, remoteMessages);\n        } catch (Throwable ex) {\n          Tracer.logError(ex);\n        }\n      }\n    }\n  }\n\n  private void updateNotifications(List<ApolloConfigNotification> deltaNotifications) {\n    for (ApolloConfigNotification notification : deltaNotifications) {\n      if (Strings.isNullOrEmpty(notification.getNamespaceName())) {\n        continue;\n      }\n      String namespaceName = notification.getNamespaceName();\n      if (m_notifications.containsKey(namespaceName)) {\n        m_notifications.put(namespaceName, notification.getNotificationId());\n      }\n      //since .properties are filtered out by default, so we need to check if there is notification with .properties suffix\n      String namespaceNameWithPropertiesSuffix =\n          String.format(\"%s.%s\", namespaceName, ConfigFileFormat.Properties.getValue());\n      if (m_notifications.containsKey(namespaceNameWithPropertiesSuffix)) {\n        m_notifications.put(namespaceNameWithPropertiesSuffix, notification.getNotificationId());\n      }\n    }\n  }\n\n  private void updateRemoteNotifications(List<ApolloConfigNotification> deltaNotifications) {\n    for (ApolloConfigNotification notification : deltaNotifications) {\n      if (Strings.isNullOrEmpty(notification.getNamespaceName())) {\n        continue;\n      }\n\n      if (notification.getMessages() == null || notification.getMessages().isEmpty()) {\n        continue;\n      }\n\n      ApolloNotificationMessages localRemoteMessages =\n          m_remoteNotificationMessages.get(notification.getNamespaceName());\n      if (localRemoteMessages == null) {\n        localRemoteMessages = new ApolloNotificationMessages();\n        m_remoteNotificationMessages.put(notification.getNamespaceName(), localRemoteMessages);\n      }\n\n      localRemoteMessages.mergeFrom(notification.getMessages());\n    }\n  }\n\n  private String assembleNamespaces() {\n    return STRING_JOINER.join(m_longPollNamespaces.keySet());\n  }\n\n  String assembleLongPollRefreshUrl(String uri, String appId, String cluster, String dataCenter,\n                                    Map<String, Long> notificationsMap) {\n    Map<String, String> queryParams = Maps.newHashMap();\n    queryParams.put(\"appId\", queryParamEscaper.escape(appId));\n    queryParams.put(\"cluster\", queryParamEscaper.escape(cluster));\n    queryParams\n        .put(\"notifications\", queryParamEscaper.escape(assembleNotifications(notificationsMap)));\n\n    if (!Strings.isNullOrEmpty(dataCenter)) {\n      queryParams.put(\"dataCenter\", queryParamEscaper.escape(dataCenter));\n    }\n    String localIp = m_configUtil.getLocalIp();\n    if (!Strings.isNullOrEmpty(localIp)) {\n      queryParams.put(\"ip\", queryParamEscaper.escape(localIp));\n    }\n\n    String params = MAP_JOINER.join(queryParams);\n    if (!uri.endsWith(\"/\")) {\n      uri += \"/\";\n    }\n\n    return uri + \"notifications/v2?\" + params;\n  }\n\n  String assembleNotifications(Map<String, Long> notificationsMap) {\n    List<ApolloConfigNotification> notifications = Lists.newArrayList();\n    for (Map.Entry<String, Long> entry : notificationsMap.entrySet()) {\n      ApolloConfigNotification notification = new ApolloConfigNotification(entry.getKey(), entry.getValue());\n      notifications.add(notification);\n    }\n    return gson.toJson(notifications);\n  }\n\n  private List<ServiceDTO> getConfigServices() {\n    List<ServiceDTO> services = m_serviceLocator.getConfigServices();\n    if (services.size() == 0) {\n      throw new ApolloConfigException(\"No available config service\");\n    }\n\n    return services;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/RemoteConfigRepository.java",
    "content": "package com.ctrip.framework.apollo.internals;\n\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Properties;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicBoolean;\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.ctrip.framework.apollo.Apollo;\nimport com.ctrip.framework.apollo.build.ApolloInjector;\nimport com.ctrip.framework.apollo.core.ConfigConsts;\nimport com.ctrip.framework.apollo.core.dto.ApolloConfig;\nimport com.ctrip.framework.apollo.core.dto.ApolloNotificationMessages;\nimport com.ctrip.framework.apollo.core.dto.ServiceDTO;\nimport com.ctrip.framework.apollo.core.schedule.ExponentialSchedulePolicy;\nimport com.ctrip.framework.apollo.core.schedule.SchedulePolicy;\nimport com.ctrip.framework.apollo.core.utils.ApolloThreadFactory;\nimport com.ctrip.framework.apollo.exceptions.ApolloConfigException;\nimport com.ctrip.framework.apollo.exceptions.ApolloConfigStatusCodeException;\nimport com.ctrip.framework.apollo.tracer.Tracer;\nimport com.ctrip.framework.apollo.tracer.spi.Transaction;\nimport com.ctrip.framework.apollo.util.ConfigUtil;\nimport com.ctrip.framework.apollo.util.ExceptionUtil;\nimport com.ctrip.framework.apollo.util.http.HttpRequest;\nimport com.ctrip.framework.apollo.util.http.HttpResponse;\nimport com.ctrip.framework.apollo.util.http.HttpUtil;\nimport com.google.common.base.Joiner;\nimport com.google.common.base.Strings;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport com.google.common.escape.Escaper;\nimport com.google.common.net.UrlEscapers;\nimport com.google.common.util.concurrent.RateLimiter;\nimport com.google.gson.Gson;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class RemoteConfigRepository extends AbstractConfigRepository {\n  private static final Logger logger = LoggerFactory.getLogger(RemoteConfigRepository.class);\n  private static final Joiner STRING_JOINER = Joiner.on(ConfigConsts.CLUSTER_NAMESPACE_SEPARATOR);\n  private static final Joiner.MapJoiner MAP_JOINER = Joiner.on(\"&\").withKeyValueSeparator(\"=\");\n  private ConfigServiceLocator m_serviceLocator;\n  private HttpUtil m_httpUtil;\n  private ConfigUtil m_configUtil;\n  private RemoteConfigLongPollService remoteConfigLongPollService;\n  private volatile AtomicReference<ApolloConfig> m_configCache;\n  private final String m_namespace;\n  private final static ScheduledExecutorService m_executorService;\n  private AtomicReference<ServiceDTO> m_longPollServiceDto;\n  private AtomicReference<ApolloNotificationMessages> m_remoteMessages;\n  private RateLimiter m_loadConfigRateLimiter;\n  private AtomicBoolean m_configNeedForceRefresh;\n  private SchedulePolicy m_loadConfigFailSchedulePolicy;\n  private Gson gson;\n  private static final Escaper pathEscaper = UrlEscapers.urlPathSegmentEscaper();\n  private static final Escaper queryParamEscaper = UrlEscapers.urlFormParameterEscaper();\n\n  static {\n    m_executorService = Executors.newScheduledThreadPool(1,\n        ApolloThreadFactory.create(\"RemoteConfigRepository\", true));\n  }\n\n  /**\n   * Constructor.\n   *\n   * @param namespace the namespace\n   */\n  public RemoteConfigRepository(String namespace) {\n    m_namespace = namespace;\n    m_configCache = new AtomicReference<>();\n    m_configUtil = ApolloInjector.getInstance(ConfigUtil.class);\n    m_httpUtil = ApolloInjector.getInstance(HttpUtil.class);\n    m_serviceLocator = ApolloInjector.getInstance(ConfigServiceLocator.class);\n    remoteConfigLongPollService = ApolloInjector.getInstance(RemoteConfigLongPollService.class);\n    m_longPollServiceDto = new AtomicReference<>();\n    m_remoteMessages = new AtomicReference<>();\n    m_loadConfigRateLimiter = RateLimiter.create(m_configUtil.getLoadConfigQPS());\n    m_configNeedForceRefresh = new AtomicBoolean(true);\n    m_loadConfigFailSchedulePolicy = new ExponentialSchedulePolicy(m_configUtil.getOnErrorRetryInterval(),\n        m_configUtil.getOnErrorRetryInterval() * 8);\n    gson = new Gson();\n    this.trySync();\n    this.schedulePeriodicRefresh();\n    this.scheduleLongPollingRefresh();\n  }\n\n  @Override\n  public Properties getConfig() {\n    if (m_configCache.get() == null) {\n      this.sync();\n    }\n    return transformApolloConfigToProperties(m_configCache.get());\n  }\n\n  @Override\n  public void setUpstreamRepository(ConfigRepository upstreamConfigRepository) {\n    //remote config doesn't need upstream\n  }\n\n  private void schedulePeriodicRefresh() {\n    logger.debug(\"Schedule periodic refresh with interval: {} {}\",\n        m_configUtil.getRefreshInterval(), m_configUtil.getRefreshIntervalTimeUnit());\n    m_executorService.scheduleAtFixedRate(\n        new Runnable() {\n          @Override\n          public void run() {\n            Tracer.logEvent(\"Apollo.ConfigService\", String.format(\"periodicRefresh: %s\", m_namespace));\n            logger.debug(\"refresh config for namespace: {}\", m_namespace);\n            trySync();\n            Tracer.logEvent(\"Apollo.Client.Version\", Apollo.VERSION);\n          }\n        }, m_configUtil.getRefreshInterval(), m_configUtil.getRefreshInterval(),\n        m_configUtil.getRefreshIntervalTimeUnit());\n  }\n\n  @Override\n  protected synchronized void sync() {\n    Transaction transaction = Tracer.newTransaction(\"Apollo.ConfigService\", \"syncRemoteConfig\");\n\n    try {\n      ApolloConfig previous = m_configCache.get();\n      ApolloConfig current = loadApolloConfig();\n\n      //reference equals means HTTP 304\n      if (previous != current) {\n        logger.debug(\"Remote Config refreshed!\");\n        m_configCache.set(current);\n        this.fireRepositoryChange(m_namespace, this.getConfig());\n      }\n\n      if (current != null) {\n        Tracer.logEvent(String.format(\"Apollo.Client.Configs.%s\", current.getNamespaceName()),\n            current.getReleaseKey());\n      }\n\n      transaction.setStatus(Transaction.SUCCESS);\n    } catch (Throwable ex) {\n      transaction.setStatus(ex);\n      throw ex;\n    } finally {\n      transaction.complete();\n    }\n  }\n\n  private Properties transformApolloConfigToProperties(ApolloConfig apolloConfig) {\n    Properties result = new Properties();\n    result.putAll(apolloConfig.getConfigurations());\n    return result;\n  }\n\n  private ApolloConfig loadApolloConfig() {\n    if (!m_loadConfigRateLimiter.tryAcquire(5, TimeUnit.SECONDS)) {\n      //wait at most 5 seconds\n      try {\n        TimeUnit.SECONDS.sleep(5);\n      } catch (InterruptedException e) {\n      }\n    }\n    String appId = m_configUtil.getAppId();\n    String cluster = m_configUtil.getCluster();\n    String dataCenter = m_configUtil.getDataCenter();\n    Tracer.logEvent(\"Apollo.Client.ConfigMeta\", STRING_JOINER.join(appId, cluster, m_namespace));\n    int maxRetries = m_configNeedForceRefresh.get() ? 2 : 1;\n    long onErrorSleepTime = 0; // 0 means no sleep\n    Throwable exception = null;\n\n    List<ServiceDTO> configServices = getConfigServices();\n    String url = null;\n    for (int i = 0; i < maxRetries; i++) {\n      List<ServiceDTO> randomConfigServices = Lists.newLinkedList(configServices);\n      Collections.shuffle(randomConfigServices);\n      //Access the server which notifies the client first\n      if (m_longPollServiceDto.get() != null) {\n        randomConfigServices.add(0, m_longPollServiceDto.getAndSet(null));\n      }\n\n      for (ServiceDTO configService : randomConfigServices) {\n        if (onErrorSleepTime > 0) {\n          logger.warn(\n              \"Load config failed, will retry in {} {}. appId: {}, cluster: {}, namespaces: {}\",\n              onErrorSleepTime, m_configUtil.getOnErrorRetryIntervalTimeUnit(), appId, cluster, m_namespace);\n\n          try {\n            m_configUtil.getOnErrorRetryIntervalTimeUnit().sleep(onErrorSleepTime);\n          } catch (InterruptedException e) {\n            //ignore\n          }\n        }\n\n        url = assembleQueryConfigUrl(configService.getHomepageUrl(), appId, cluster, m_namespace,\n                dataCenter, m_remoteMessages.get(), m_configCache.get());\n\n        logger.debug(\"Loading config from {}\", url);\n        HttpRequest request = new HttpRequest(url);\n\n        Transaction transaction = Tracer.newTransaction(\"Apollo.ConfigService\", \"queryConfig\");\n        transaction.addData(\"Url\", url);\n        try {\n\n          HttpResponse<ApolloConfig> response = m_httpUtil.doGet(request, ApolloConfig.class);\n          m_configNeedForceRefresh.set(false);\n          m_loadConfigFailSchedulePolicy.success();\n\n          transaction.addData(\"StatusCode\", response.getStatusCode());\n          transaction.setStatus(Transaction.SUCCESS);\n\n          if (response.getStatusCode() == 304) {\n            logger.debug(\"Config server responds with 304 HTTP status code.\");\n            return m_configCache.get();\n          }\n\n          ApolloConfig result = response.getBody();\n\n          logger.debug(\"Loaded config for {}: {}\", m_namespace, result);\n\n          return result;\n        } catch (ApolloConfigStatusCodeException ex) {\n          ApolloConfigStatusCodeException statusCodeException = ex;\n          //config not found\n          if (ex.getStatusCode() == 404) {\n            String message = String.format(\n                \"Could not find config for namespace - appId: %s, cluster: %s, namespace: %s, \" +\n                    \"please check whether the configs are released in Apollo!\",\n                appId, cluster, m_namespace);\n            statusCodeException = new ApolloConfigStatusCodeException(ex.getStatusCode(),\n                message);\n          }\n          Tracer.logEvent(\"ApolloConfigException\", ExceptionUtil.getDetailMessage(statusCodeException));\n          transaction.setStatus(statusCodeException);\n          exception = statusCodeException;\n        } catch (Throwable ex) {\n          Tracer.logEvent(\"ApolloConfigException\", ExceptionUtil.getDetailMessage(ex));\n          transaction.setStatus(ex);\n          exception = ex;\n        } finally {\n          transaction.complete();\n        }\n\n        // if force refresh, do normal sleep, if normal config load, do exponential sleep\n        onErrorSleepTime = m_configNeedForceRefresh.get() ? m_configUtil.getOnErrorRetryInterval() :\n            m_loadConfigFailSchedulePolicy.fail();\n      }\n\n    }\n    String message = String.format(\n        \"Load Apollo Config failed - appId: %s, cluster: %s, namespace: %s, url: %s\",\n        appId, cluster, m_namespace, url);\n    throw new ApolloConfigException(message, exception);\n  }\n\n  String assembleQueryConfigUrl(String uri, String appId, String cluster, String namespace,\n                                String dataCenter, ApolloNotificationMessages remoteMessages, ApolloConfig previousConfig) {\n\n    String path = \"configs/%s/%s/%s\";\n    List<String> pathParams =\n        Lists.newArrayList(pathEscaper.escape(appId), pathEscaper.escape(cluster),\n            pathEscaper.escape(namespace));\n    Map<String, String> queryParams = Maps.newHashMap();\n\n    if (previousConfig != null) {\n      queryParams.put(\"releaseKey\", queryParamEscaper.escape(previousConfig.getReleaseKey()));\n    }\n\n    if (!Strings.isNullOrEmpty(dataCenter)) {\n      queryParams.put(\"dataCenter\", queryParamEscaper.escape(dataCenter));\n    }\n\n    String localIp = m_configUtil.getLocalIp();\n    if (!Strings.isNullOrEmpty(localIp)) {\n      queryParams.put(\"ip\", queryParamEscaper.escape(localIp));\n    }\n\n    if (remoteMessages != null) {\n      queryParams.put(\"messages\", queryParamEscaper.escape(gson.toJson(remoteMessages)));\n    }\n\n    String pathExpanded = String.format(path, pathParams.toArray());\n\n    if (!queryParams.isEmpty()) {\n      pathExpanded += \"?\" + MAP_JOINER.join(queryParams);\n    }\n    if (!uri.endsWith(\"/\")) {\n      uri += \"/\";\n    }\n    return uri + pathExpanded;\n  }\n\n  private void scheduleLongPollingRefresh() {\n    remoteConfigLongPollService.submit(m_namespace, this);\n  }\n\n  public void onLongPollNotified(ServiceDTO longPollNotifiedServiceDto, ApolloNotificationMessages remoteMessages) {\n    m_longPollServiceDto.set(longPollNotifiedServiceDto);\n    m_remoteMessages.set(remoteMessages);\n    m_executorService.submit(new Runnable() {\n      @Override\n      public void run() {\n        m_configNeedForceRefresh.set(true);\n        trySync();\n      }\n    });\n  }\n\n  private List<ServiceDTO> getConfigServices() {\n    List<ServiceDTO> services = m_serviceLocator.getConfigServices();\n    if (services.size() == 0) {\n      throw new ApolloConfigException(\"No available config service\");\n    }\n\n    return services;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/RepositoryChangeListener.java",
    "content": "package com.ctrip.framework.apollo.internals;\n\nimport java.util.Properties;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic interface RepositoryChangeListener {\n  /**\n   * Invoked when config repository changes.\n   * @param namespace the namespace of this repository change\n   * @param newProperties the properties after change\n   */\n  public void onRepositoryChange(String namespace, Properties newProperties);\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/SimpleConfig.java",
    "content": "package com.ctrip.framework.apollo.internals;\n\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Properties;\nimport java.util.Set;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.ctrip.framework.apollo.model.ConfigChange;\nimport com.ctrip.framework.apollo.model.ConfigChangeEvent;\nimport com.ctrip.framework.apollo.tracer.Tracer;\nimport com.ctrip.framework.apollo.util.ExceptionUtil;\nimport com.google.common.base.Function;\nimport com.google.common.collect.Maps;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class SimpleConfig extends AbstractConfig implements RepositoryChangeListener {\n  private static final Logger logger = LoggerFactory.getLogger(SimpleConfig.class);\n  private final String m_namespace;\n  private final ConfigRepository m_configRepository;\n  private volatile Properties m_configProperties;\n\n  /**\n   * Constructor.\n   *\n   * @param namespace        the namespace for this config instance\n   * @param configRepository the config repository for this config instance\n   */\n  public SimpleConfig(String namespace, ConfigRepository configRepository) {\n    m_namespace = namespace;\n    m_configRepository = configRepository;\n    this.initialize();\n  }\n\n  private void initialize() {\n    try {\n      m_configProperties = m_configRepository.getConfig();\n    } catch (Throwable ex) {\n      Tracer.logError(ex);\n      logger.warn(\"Init Apollo Simple Config failed - namespace: {}, reason: {}\", m_namespace,\n          ExceptionUtil.getDetailMessage(ex));\n    } finally {\n      //register the change listener no matter config repository is working or not\n      //so that whenever config repository is recovered, config could get changed\n      m_configRepository.addChangeListener(this);\n    }\n  }\n\n  @Override\n  public String getProperty(String key, String defaultValue) {\n    if (m_configProperties == null) {\n      logger.warn(\"Could not load config from Apollo, always return default value!\");\n      return defaultValue;\n    }\n    return this.m_configProperties.getProperty(key, defaultValue);\n  }\n\n  @Override\n  public Set<String> getPropertyNames() {\n    if (m_configProperties == null) {\n      return Collections.emptySet();\n    }\n\n    return m_configProperties.stringPropertyNames();\n  }\n\n  @Override\n  public synchronized void onRepositoryChange(String namespace, Properties newProperties) {\n    if (newProperties.equals(m_configProperties)) {\n      return;\n    }\n    Properties newConfigProperties = new Properties();\n    newConfigProperties.putAll(newProperties);\n\n    List<ConfigChange>\n        changes =\n        calcPropertyChanges(namespace, m_configProperties, newConfigProperties);\n    Map<String, ConfigChange> changeMap = Maps.uniqueIndex(changes,\n        new Function<ConfigChange, String>() {\n          @Override\n          public String apply(ConfigChange input) {\n            return input.getPropertyName();\n          }\n        });\n\n    m_configProperties = newConfigProperties;\n    clearConfigCache();\n\n    this.fireConfigChange(new ConfigChangeEvent(m_namespace, changeMap));\n\n    Tracer.logEvent(\"Apollo.Client.ConfigChanges\", m_namespace);\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/XmlConfigFile.java",
    "content": "package com.ctrip.framework.apollo.internals;\n\nimport com.ctrip.framework.apollo.core.enums.ConfigFileFormat;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class XmlConfigFile extends PlainTextConfigFile {\n  public XmlConfigFile(String namespace,\n                       ConfigRepository configRepository) {\n    super(namespace, configRepository);\n  }\n\n  @Override\n  public ConfigFileFormat getConfigFileFormat() {\n    return ConfigFileFormat.XML;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/YamlConfigFile.java",
    "content": "package com.ctrip.framework.apollo.internals;\n\nimport com.ctrip.framework.apollo.core.enums.ConfigFileFormat;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class YamlConfigFile extends PlainTextConfigFile {\n  public YamlConfigFile(String namespace, ConfigRepository configRepository) {\n    super(namespace, configRepository);\n  }\n\n  @Override\n  public ConfigFileFormat getConfigFileFormat() {\n    return ConfigFileFormat.YAML;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/YmlConfigFile.java",
    "content": "package com.ctrip.framework.apollo.internals;\n\nimport com.ctrip.framework.apollo.core.enums.ConfigFileFormat;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class YmlConfigFile extends PlainTextConfigFile {\n  public YmlConfigFile(String namespace, ConfigRepository configRepository) {\n    super(namespace, configRepository);\n  }\n\n  @Override\n  public ConfigFileFormat getConfigFileFormat() {\n    return ConfigFileFormat.YML;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/model/ConfigChange.java",
    "content": "package com.ctrip.framework.apollo.model;\n\n\nimport com.ctrip.framework.apollo.enums.PropertyChangeType;\n\n/**\n * Holds the information for a config change.\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class ConfigChange {\n  private final String namespace;\n  private final String propertyName;\n  private String oldValue;\n  private String newValue;\n  private PropertyChangeType changeType;\n\n  /**\n   * Constructor.\n   * @param namespace the namespace of the key\n   * @param propertyName the key whose value is changed\n   * @param oldValue the value before change\n   * @param newValue the value after change\n   * @param changeType the change type\n   */\n  public ConfigChange(String namespace, String propertyName, String oldValue, String newValue,\n                      PropertyChangeType changeType) {\n    this.namespace = namespace;\n    this.propertyName = propertyName;\n    this.oldValue = oldValue;\n    this.newValue = newValue;\n    this.changeType = changeType;\n  }\n\n  public String getPropertyName() {\n    return propertyName;\n  }\n\n  public String getOldValue() {\n    return oldValue;\n  }\n\n  public String getNewValue() {\n    return newValue;\n  }\n\n  public PropertyChangeType getChangeType() {\n    return changeType;\n  }\n\n  public void setOldValue(String oldValue) {\n    this.oldValue = oldValue;\n  }\n\n  public void setNewValue(String newValue) {\n    this.newValue = newValue;\n  }\n\n  public void setChangeType(PropertyChangeType changeType) {\n    this.changeType = changeType;\n  }\n\n  public String getNamespace() {\n    return namespace;\n  }\n\n  @Override\n  public String toString() {\n    final StringBuilder sb = new StringBuilder(\"ConfigChange{\");\n    sb.append(\"namespace='\").append(namespace).append('\\'');\n    sb.append(\", propertyName='\").append(propertyName).append('\\'');\n    sb.append(\", oldValue='\").append(oldValue).append('\\'');\n    sb.append(\", newValue='\").append(newValue).append('\\'');\n    sb.append(\", changeType=\").append(changeType);\n    sb.append('}');\n    return sb.toString();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/model/ConfigChangeEvent.java",
    "content": "package com.ctrip.framework.apollo.model;\n\nimport java.util.Map;\nimport java.util.Set;\n\n/**\n * A change event when a namespace's config is changed.\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class ConfigChangeEvent {\n  private final String m_namespace;\n  private final Map<String, ConfigChange> m_changes;\n\n  /**\n   * Constructor.\n   * @param namespace the namespace of this change\n   * @param changes the actual changes\n   */\n  public ConfigChangeEvent(String namespace,\n                           Map<String, ConfigChange> changes) {\n    m_namespace = namespace;\n    m_changes = changes;\n  }\n\n  /**\n   * Get the keys changed.\n   * @return the list of the keys\n   */\n  public Set<String> changedKeys() {\n    return m_changes.keySet();\n  }\n\n  /**\n   * Get a specific change instance for the key specified.\n   * @param key the changed key\n   * @return the change instance\n   */\n  public ConfigChange getChange(String key) {\n    return m_changes.get(key);\n  }\n\n  /**\n   * Check whether the specified key is changed\n   * @param key the key\n   * @return true if the key is changed, false otherwise.\n   */\n  public boolean isChanged(String key) {\n    return m_changes.containsKey(key);\n  }\n\n  /**\n   * Get the namespace of this change event.\n   * @return the namespace\n   */\n  public String getNamespace() {\n    return m_namespace;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/model/ConfigFileChangeEvent.java",
    "content": "package com.ctrip.framework.apollo.model;\n\nimport com.ctrip.framework.apollo.enums.PropertyChangeType;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class ConfigFileChangeEvent {\n  private final String namespace;\n  private final String oldValue;\n  private final String newValue;\n  private final PropertyChangeType changeType;\n\n  /**\n   * Constructor.\n   *\n   * @param namespace the namespace of the config file change event\n   * @param oldValue the value before change\n   * @param newValue the value after change\n   * @param changeType the change type\n   */\n  public ConfigFileChangeEvent(String namespace, String oldValue, String newValue,\n      PropertyChangeType changeType) {\n    this.namespace = namespace;\n    this.oldValue = oldValue;\n    this.newValue = newValue;\n    this.changeType = changeType;\n  }\n\n  public String getNamespace() {\n    return namespace;\n  }\n\n  public String getOldValue() {\n    return oldValue;\n  }\n\n  public String getNewValue() {\n    return newValue;\n  }\n\n  public PropertyChangeType getChangeType() {\n    return changeType;\n  }\n\n  @Override\n  public String toString() {\n    final StringBuilder sb = new StringBuilder(\"ConfigFileChangeEvent{\");\n    sb.append(\"namespace='\").append(namespace).append('\\'');\n    sb.append(\", oldValue='\").append(oldValue).append('\\'');\n    sb.append(\", newValue='\").append(newValue).append('\\'');\n    sb.append(\", changeType=\").append(changeType);\n    sb.append('}');\n    return sb.toString();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spi/ConfigFactory.java",
    "content": "package com.ctrip.framework.apollo.spi;\n\nimport com.ctrip.framework.apollo.Config;\nimport com.ctrip.framework.apollo.ConfigFile;\nimport com.ctrip.framework.apollo.core.enums.ConfigFileFormat;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic interface ConfigFactory {\n  /**\n   * Create the config instance for the namespace.\n   *\n   * @param namespace the namespace\n   * @return the newly created config instance\n   */\n  public Config create(String namespace);\n\n  /**\n   * Create the config file instance for the namespace\n   * @param namespace the namespace\n   * @return the newly created config file instance\n   */\n  public ConfigFile createConfigFile(String namespace, ConfigFileFormat configFileFormat);\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spi/ConfigFactoryManager.java",
    "content": "package com.ctrip.framework.apollo.spi;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic interface ConfigFactoryManager {\n  /**\n   * Get the config factory for the namespace.\n   *\n   * @param namespace the namespace\n   * @return the config factory for this namespace\n   */\n  public ConfigFactory getFactory(String namespace);\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spi/ConfigRegistry.java",
    "content": "package com.ctrip.framework.apollo.spi;\n\n/**\n * The manually config registry, use with caution!\n *\n * @author Jason Song(song_s@ctrip.com)\n */\npublic interface ConfigRegistry {\n  /**\n   * Register the config factory for the namespace specified.\n   *\n   * @param namespace the namespace\n   * @param factory   the factory for this namespace\n   */\n  public void register(String namespace, ConfigFactory factory);\n\n  /**\n   * Get the registered config factory for the namespace.\n   *\n   * @param namespace the namespace\n   * @return the factory registered for this namespace\n   */\n  public ConfigFactory getFactory(String namespace);\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spi/DefaultConfigFactory.java",
    "content": "package com.ctrip.framework.apollo.spi;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.ctrip.framework.apollo.Config;\nimport com.ctrip.framework.apollo.ConfigFile;\nimport com.ctrip.framework.apollo.build.ApolloInjector;\nimport com.ctrip.framework.apollo.core.enums.ConfigFileFormat;\nimport com.ctrip.framework.apollo.internals.ConfigRepository;\nimport com.ctrip.framework.apollo.internals.DefaultConfig;\nimport com.ctrip.framework.apollo.internals.JsonConfigFile;\nimport com.ctrip.framework.apollo.internals.LocalFileConfigRepository;\nimport com.ctrip.framework.apollo.internals.PropertiesConfigFile;\nimport com.ctrip.framework.apollo.internals.RemoteConfigRepository;\nimport com.ctrip.framework.apollo.internals.XmlConfigFile;\nimport com.ctrip.framework.apollo.internals.YamlConfigFile;\nimport com.ctrip.framework.apollo.internals.YmlConfigFile;\nimport com.ctrip.framework.apollo.util.ConfigUtil;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class DefaultConfigFactory implements ConfigFactory {\n  private static final Logger logger = LoggerFactory.getLogger(DefaultConfigFactory.class);\n  private ConfigUtil m_configUtil;\n\n  public DefaultConfigFactory() {\n    m_configUtil = ApolloInjector.getInstance(ConfigUtil.class);\n  }\n\n  @Override\n  public Config create(String namespace) {\n    DefaultConfig defaultConfig =\n        new DefaultConfig(namespace, createLocalConfigRepository(namespace));\n    return defaultConfig;\n  }\n\n  @Override\n  public ConfigFile createConfigFile(String namespace, ConfigFileFormat configFileFormat) {\n    ConfigRepository configRepository = createLocalConfigRepository(namespace);\n    switch (configFileFormat) {\n      case Properties:\n        return new PropertiesConfigFile(namespace, configRepository);\n      case XML:\n        return new XmlConfigFile(namespace, configRepository);\n      case JSON:\n        return new JsonConfigFile(namespace, configRepository);\n      case YAML:\n        return new YamlConfigFile(namespace, configRepository);\n      case YML:\n        return new YmlConfigFile(namespace, configRepository);\n    }\n\n    return null;\n  }\n\n  LocalFileConfigRepository createLocalConfigRepository(String namespace) {\n    if (m_configUtil.isInLocalMode()) {\n      logger.warn(\n          \"==== Apollo is in local mode! Won't pull configs from remote server for namespace {} ! ====\",\n          namespace);\n      return new LocalFileConfigRepository(namespace);\n    }\n    return new LocalFileConfigRepository(namespace, createRemoteConfigRepository(namespace));\n  }\n\n  RemoteConfigRepository createRemoteConfigRepository(String namespace) {\n    return new RemoteConfigRepository(namespace);\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spi/DefaultConfigFactoryManager.java",
    "content": "package com.ctrip.framework.apollo.spi;\n\nimport java.util.Map;\n\nimport com.ctrip.framework.apollo.build.ApolloInjector;\nimport com.google.common.collect.Maps;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class DefaultConfigFactoryManager implements ConfigFactoryManager {\n  private ConfigRegistry m_registry;\n\n  private Map<String, ConfigFactory> m_factories = Maps.newConcurrentMap();\n\n  public DefaultConfigFactoryManager() {\n    m_registry = ApolloInjector.getInstance(ConfigRegistry.class);\n  }\n\n  @Override\n  public ConfigFactory getFactory(String namespace) {\n    // step 1: check hacked factory\n    ConfigFactory factory = m_registry.getFactory(namespace);\n\n    if (factory != null) {\n      return factory;\n    }\n\n    // step 2: check cache\n    factory = m_factories.get(namespace);\n\n    if (factory != null) {\n      return factory;\n    }\n\n    // step 3: check declared config factory\n    factory = ApolloInjector.getInstance(ConfigFactory.class, namespace);\n\n    if (factory != null) {\n      return factory;\n    }\n\n    // step 4: check default config factory\n    factory = ApolloInjector.getInstance(ConfigFactory.class);\n\n    m_factories.put(namespace, factory);\n\n    // factory should not be null\n    return factory;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spi/DefaultConfigRegistry.java",
    "content": "package com.ctrip.framework.apollo.spi;\n\nimport java.util.Map;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.google.common.collect.Maps;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class DefaultConfigRegistry implements ConfigRegistry {\n  private static final Logger s_logger = LoggerFactory.getLogger(DefaultConfigRegistry.class);\n  private Map<String, ConfigFactory> m_instances = Maps.newConcurrentMap();\n\n  @Override\n  public void register(String namespace, ConfigFactory factory) {\n    if (m_instances.containsKey(namespace)) {\n      s_logger.warn(\"ConfigFactory({}) is overridden by {}!\", namespace, factory.getClass());\n    }\n\n    m_instances.put(namespace, factory);\n  }\n\n  @Override\n  public ConfigFactory getFactory(String namespace) {\n    ConfigFactory config = m_instances.get(namespace);\n\n    return config;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/annotation/ApolloAnnotationProcessor.java",
    "content": "package com.ctrip.framework.apollo.spring.annotation;\n\nimport java.lang.reflect.Field;\nimport java.lang.reflect.Method;\n\nimport org.springframework.beans.BeansException;\nimport org.springframework.beans.factory.config.BeanPostProcessor;\nimport org.springframework.core.Ordered;\nimport org.springframework.core.PriorityOrdered;\nimport org.springframework.core.annotation.AnnotationUtils;\nimport org.springframework.util.ReflectionUtils;\n\nimport com.ctrip.framework.apollo.Config;\nimport com.ctrip.framework.apollo.ConfigChangeListener;\nimport com.ctrip.framework.apollo.ConfigService;\nimport com.ctrip.framework.apollo.model.ConfigChangeEvent;\nimport com.google.common.base.Preconditions;\n\n/**\n * Apollo Annotation Processor for Spring Application\n *\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class ApolloAnnotationProcessor implements BeanPostProcessor, PriorityOrdered {\n  @Override\n  public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {\n    Class clazz = bean.getClass();\n    processFields(bean, clazz.getDeclaredFields());\n    processMethods(bean, clazz.getDeclaredMethods());\n    return bean;\n  }\n\n  @Override\n  public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {\n    return bean;\n  }\n\n  private void processFields(Object bean, Field[] declaredFields) {\n    for (Field field : declaredFields) {\n      ApolloConfig annotation = AnnotationUtils.getAnnotation(field, ApolloConfig.class);\n      if (annotation == null) {\n        continue;\n      }\n\n      Preconditions.checkArgument(Config.class.isAssignableFrom(field.getType()),\n          \"Invalid type: %s for field: %s, should be Config\", field.getType(), field);\n\n      String namespace = annotation.value();\n      Config config = ConfigService.getConfig(namespace);\n\n      ReflectionUtils.makeAccessible(field);\n      ReflectionUtils.setField(field, bean, config);\n    }\n  }\n\n  private void processMethods(final Object bean, Method[] declaredMethods) {\n    for (final Method method : declaredMethods) {\n      ApolloConfigChangeListener annotation = AnnotationUtils.findAnnotation(method, ApolloConfigChangeListener.class);\n      if (annotation == null) {\n        continue;\n      }\n\n      Class<?>[] parameterTypes = method.getParameterTypes();\n      Preconditions.checkArgument(parameterTypes.length == 1,\n          \"Invalid number of parameters: %s for method: %s, should be 1\", parameterTypes.length, method);\n      Preconditions.checkArgument(ConfigChangeEvent.class.isAssignableFrom(parameterTypes[0]),\n          \"Invalid parameter type: %s for method: %s, should be ConfigChangeEvent\", parameterTypes[0], method);\n\n      ReflectionUtils.makeAccessible(method);\n      String[] namespaces = annotation.value();\n      for (String namespace : namespaces) {\n        Config config = ConfigService.getConfig(namespace);\n\n        config.addChangeListener(new ConfigChangeListener() {\n          @Override\n          public void onChange(ConfigChangeEvent changeEvent) {\n            ReflectionUtils.invokeMethod(method, bean, changeEvent);\n          }\n        });\n      }\n    }\n  }\n\n  @Override\n  public int getOrder() {\n    //make it as late as possible\n    return Ordered.LOWEST_PRECEDENCE;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/annotation/ApolloConfig.java",
    "content": "package com.ctrip.framework.apollo.spring.annotation;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\nimport com.ctrip.framework.apollo.core.ConfigConsts;\n\n/**\n * Use this annotation to inject Apollo Config Instance.\n *\n * <p>Usage example:</p>\n * <pre class=\"code\">\n * //Inject the config for \"someNamespace\"\n * &#064;ApolloConfig(\"someNamespace\")\n * private Config config;\n * </pre>\n *\n * @author Jason Song(song_s@ctrip.com)\n */\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.FIELD)\n@Documented\npublic @interface ApolloConfig {\n  /**\n   * Apollo namespace for the config, if not specified then default to application\n   */\n  String value() default ConfigConsts.NAMESPACE_APPLICATION;\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/annotation/ApolloConfigChangeListener.java",
    "content": "package com.ctrip.framework.apollo.spring.annotation;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\nimport com.ctrip.framework.apollo.core.ConfigConsts;\n\n/**\n * Use this annotation to register Apollo ConfigChangeListener.\n *\n * <p>Usage example:</p>\n * <pre class=\"code\">\n * //Listener on namespaces of \"someNamespace\" and \"anotherNamespace\"\n * &#064;ApolloConfigChangeListener({\"someNamespace\",\"anotherNamespace\"})\n * private void onChange(ConfigChangeEvent changeEvent) {\n *     //handle change event\n * }\n * </pre>\n *\n * @author Jason Song(song_s@ctrip.com)\n */\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.METHOD)\n@Documented\npublic @interface ApolloConfigChangeListener {\n  /**\n   * Apollo namespace for the config, if not specified then default to application\n   */\n  String[] value() default {ConfigConsts.NAMESPACE_APPLICATION};\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/annotation/ApolloConfigRegistrar.java",
    "content": "package com.ctrip.framework.apollo.spring.annotation;\n\nimport com.ctrip.framework.apollo.spring.property.SpringValueDefinitionProcessor;\nimport org.springframework.beans.factory.support.BeanDefinitionRegistry;\nimport org.springframework.context.annotation.ImportBeanDefinitionRegistrar;\nimport org.springframework.context.support.PropertySourcesPlaceholderConfigurer;\nimport org.springframework.core.annotation.AnnotationAttributes;\nimport org.springframework.core.type.AnnotationMetadata;\n\nimport com.ctrip.framework.apollo.spring.config.PropertySourcesProcessor;\nimport com.ctrip.framework.apollo.spring.util.BeanRegistrationUtil;\nimport com.google.common.collect.Lists;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class ApolloConfigRegistrar implements ImportBeanDefinitionRegistrar {\n  @Override\n  public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {\n    AnnotationAttributes attributes = AnnotationAttributes.fromMap(importingClassMetadata\n        .getAnnotationAttributes(EnableApolloConfig.class.getName()));\n    String[] namespaces = attributes.getStringArray(\"value\");\n    int order = attributes.getNumber(\"order\");\n    PropertySourcesProcessor.addNamespaces(Lists.newArrayList(namespaces), order);\n\n    BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, PropertySourcesPlaceholderConfigurer.class.getName(),\n        PropertySourcesPlaceholderConfigurer.class);\n\n    BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, PropertySourcesProcessor.class.getName(),\n        PropertySourcesProcessor.class);\n\n    BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, ApolloAnnotationProcessor.class.getName(),\n        ApolloAnnotationProcessor.class);\n\n    BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, SpringValueProcessor.class.getName(), SpringValueProcessor.class);\n    BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, SpringValueDefinitionProcessor.class.getName(), SpringValueDefinitionProcessor.class);\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/annotation/EnableApolloConfig.java",
    "content": "package com.ctrip.framework.apollo.spring.annotation;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\nimport org.springframework.context.annotation.Import;\nimport org.springframework.core.Ordered;\n\nimport com.ctrip.framework.apollo.core.ConfigConsts;\n\n/**\n * Use this annotation to register Apollo property sources when using Java Config.\n *\n * <p>Configuration example:</p>\n * <pre class=\"code\">\n * &#064;Configuration\n * &#064;EnableApolloConfig({\"someNamespace\",\"anotherNamespace\"})\n * public class AppConfig {\n *\n * }\n * </pre>\n *\n * @author Jason Song(song_s@ctrip.com)\n */\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.TYPE)\n@Documented\n@Import(ApolloConfigRegistrar.class)\npublic @interface EnableApolloConfig {\n  /**\n   * Apollo namespaces to inject configuration into Spring Property Sources.\n   */\n  String[] value() default {ConfigConsts.NAMESPACE_APPLICATION};\n\n  /**\n   * The order of the apollo config, default is {@link Ordered#LOWEST_PRECEDENCE}, which is Integer.MAX_VALUE.\n   * If there are properties with the same name in different apollo configs, the apollo config with smaller order wins.\n   * @return\n   */\n  int order() default Ordered.LOWEST_PRECEDENCE;\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/annotation/SpringValueProcessor.java",
    "content": "package com.ctrip.framework.apollo.spring.annotation;\n\nimport java.beans.PropertyDescriptor;\nimport java.lang.reflect.Field;\nimport java.lang.reflect.Method;\nimport java.util.Collection;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.Set;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.BeanUtils;\nimport org.springframework.beans.BeansException;\nimport org.springframework.beans.TypeConverter;\nimport org.springframework.beans.factory.BeanFactory;\nimport org.springframework.beans.factory.BeanFactoryAware;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.beans.factory.config.BeanDefinition;\nimport org.springframework.beans.factory.config.BeanExpressionContext;\nimport org.springframework.beans.factory.config.BeanFactoryPostProcessor;\nimport org.springframework.beans.factory.config.BeanPostProcessor;\nimport org.springframework.beans.factory.config.ConfigurableBeanFactory;\nimport org.springframework.beans.factory.config.ConfigurableListableBeanFactory;\nimport org.springframework.beans.factory.config.Scope;\nimport org.springframework.context.EnvironmentAware;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.core.Ordered;\nimport org.springframework.core.PriorityOrdered;\nimport org.springframework.core.env.Environment;\nimport org.springframework.util.CollectionUtils;\nimport org.springframework.util.ReflectionUtils;\n\nimport com.ctrip.framework.apollo.ConfigChangeListener;\nimport com.ctrip.framework.apollo.build.ApolloInjector;\nimport com.ctrip.framework.apollo.model.ConfigChange;\nimport com.ctrip.framework.apollo.model.ConfigChangeEvent;\nimport com.ctrip.framework.apollo.spring.config.ConfigPropertySource;\nimport com.ctrip.framework.apollo.spring.config.ConfigPropertySourceFactory;\nimport com.ctrip.framework.apollo.spring.property.PlaceholderHelper;\nimport com.ctrip.framework.apollo.spring.property.SpringValue;\nimport com.ctrip.framework.apollo.spring.property.SpringValueDefinition;\nimport com.ctrip.framework.apollo.spring.property.SpringValueDefinitionProcessor;\nimport com.ctrip.framework.apollo.util.ConfigUtil;\nimport com.google.common.collect.LinkedListMultimap;\nimport com.google.common.collect.Multimap;\n\n/**\n * Spring value processor of field or method which has @Value and xml config placeholders.\n *\n * @author github.com/zhegexiaohuozi  seimimaster@gmail.com\n * @since 2017/12/20.\n */\npublic class SpringValueProcessor implements BeanPostProcessor, PriorityOrdered, EnvironmentAware,\n    BeanFactoryAware, BeanFactoryPostProcessor {\n\n  private static final Logger logger = LoggerFactory.getLogger(SpringValueProcessor.class);\n\n  private final Multimap<String, SpringValue> monitor = LinkedListMultimap.create();\n  private final ConfigUtil configUtil;\n  private final PlaceholderHelper placeholderHelper;\n  private final ConfigPropertySourceFactory configPropertySourceFactory;\n  private final boolean typeConverterHasConvertIfNecessaryWithFieldParameter;\n\n  private Environment environment;\n  private ConfigurableBeanFactory beanFactory;\n  private TypeConverter typeConverter;\n\n  private static Multimap<String, SpringValueDefinition> beanName2SpringValueDefinitions = LinkedListMultimap.create();\n\n  public SpringValueProcessor() {\n    configUtil = ApolloInjector.getInstance(ConfigUtil.class);\n    placeholderHelper = ApolloInjector.getInstance(PlaceholderHelper.class);\n    configPropertySourceFactory = ApolloInjector.getInstance(ConfigPropertySourceFactory.class);\n    typeConverterHasConvertIfNecessaryWithFieldParameter = testTypeConverterHasConvertIfNecessaryWithFieldParameter();\n  }\n\n  @Override\n  public void setBeanFactory(BeanFactory beanFactory) throws BeansException {\n    this.beanFactory = (ConfigurableBeanFactory) beanFactory;\n    this.typeConverter = this.beanFactory.getTypeConverter();\n  }\n\n  @Override\n  public void setEnvironment(Environment env) {\n    this.environment = env;\n  }\n\n  @Override\n  public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {\n    if (configUtil.isAutoUpdateInjectedSpringPropertiesEnabled()) {\n      beanName2SpringValueDefinitions = SpringValueDefinitionProcessor.getBeanName2SpringValueDefinitions();\n      registerConfigChangeListener();\n    }\n  }\n\n  @Override\n  public Object postProcessBeforeInitialization(Object bean, String beanName)\n      throws BeansException {\n    if (configUtil.isAutoUpdateInjectedSpringPropertiesEnabled()) {\n      Class clazz = bean.getClass();\n      processFields(bean, beanName, findAllField(clazz));\n      processMethods(bean, beanName, findAllMethod(clazz));\n      processBeanPropertyValues(bean, beanName);\n    }\n    return bean;\n  }\n\n  @Override\n  public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {\n    return bean;\n  }\n\n  private void processFields(Object bean, String beanName, List<Field> declaredFields) {\n    for (Field field : declaredFields) {\n      // register @Value on field\n      Value value = field.getAnnotation(Value.class);\n      if (value == null) {\n        continue;\n      }\n      Set<String> keys = placeholderHelper.extractPlaceholderKeys(value.value());\n\n      if (keys.isEmpty()) {\n        continue;\n      }\n\n      for (String key : keys) {\n        SpringValue springValue = new SpringValue(key, value.value(), bean, beanName, field);\n        monitor.put(key, springValue);\n        logger.debug(\"Monitoring {}\", springValue);\n      }\n    }\n  }\n\n  private void processMethods(final Object bean, String beanName, List<Method> declaredMethods) {\n    for (final Method method : declaredMethods) {\n      //register @Value on method\n      Value value = method.getAnnotation(Value.class);\n      if (value == null) {\n        continue;\n      }\n      //skip Configuration bean methods\n      if (method.getAnnotation(Bean.class) != null) {\n        continue;\n      }\n      if (method.getParameterTypes().length != 1) {\n        logger.error(\"Ignore @Value setter {}.{}, expecting 1 parameter, actual {} parameters\",\n            bean.getClass().getName(), method.getName(), method.getParameterTypes().length);\n        continue;\n      }\n\n      Set<String> keys = placeholderHelper.extractPlaceholderKeys(value.value());\n\n      if (keys.isEmpty()) {\n        continue;\n      }\n\n      for (String key : keys) {\n        SpringValue springValue = new SpringValue(key, value.value(), bean, beanName, method);\n        monitor.put(key, springValue);\n        logger.debug(\"Monitoring {}\", springValue);\n      }\n    }\n  }\n\n  private void processBeanPropertyValues(Object bean, String beanName) {\n    Collection<SpringValueDefinition> propertySpringValues = beanName2SpringValueDefinitions\n        .get(beanName);\n    if (propertySpringValues == null || propertySpringValues.isEmpty()) {\n      return;\n    }\n\n    for (SpringValueDefinition definition : propertySpringValues) {\n      try {\n        PropertyDescriptor pd = BeanUtils\n            .getPropertyDescriptor(bean.getClass(), definition.getPropertyName());\n        Method method = pd.getWriteMethod();\n        if (method == null) {\n          continue;\n        }\n        SpringValue springValue = new SpringValue(definition.getKey(), definition.getPlaceholder(),\n            bean, beanName, method);\n        monitor.put(definition.getKey(), springValue);\n        logger.debug(\"Monitoring {}\", springValue);\n      } catch (Throwable ex) {\n        logger.error(\"Failed to enable auto update feature for {}.{}\", bean.getClass(),\n            definition.getPropertyName());\n      }\n    }\n\n    // clear\n    beanName2SpringValueDefinitions.removeAll(beanName);\n  }\n\n  private List<Field> findAllField(Class clazz) {\n    final List<Field> res = new LinkedList<>();\n    ReflectionUtils.doWithFields(clazz, new ReflectionUtils.FieldCallback() {\n      @Override\n      public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {\n        res.add(field);\n      }\n    });\n    return res;\n  }\n\n  private List<Method> findAllMethod(Class clazz) {\n    final List<Method> res = new LinkedList<>();\n    ReflectionUtils.doWithMethods(clazz, new ReflectionUtils.MethodCallback() {\n      @Override\n      public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {\n        res.add(method);\n      }\n    });\n    return res;\n  }\n\n  private void registerConfigChangeListener() {\n    ConfigChangeListener changeListener = new ConfigChangeListener() {\n      @Override\n      public void onChange(ConfigChangeEvent changeEvent) {\n        Set<String> keys = changeEvent.changedKeys();\n        if (CollectionUtils.isEmpty(keys)) {\n          return;\n        }\n        for (String key : keys) {\n          // 1. check whether the changed key is relevant\n          Collection<SpringValue> targetValues = monitor.get(key);\n          if (targetValues == null || targetValues.isEmpty()) {\n            continue;\n          }\n\n          // 2. check whether the value is really changed or not (since spring property sources have hierarchies)\n          ConfigChange configChange = changeEvent.getChange(key);\n          if (!Objects.equals(environment.getProperty(key), configChange.getNewValue())) {\n            continue;\n          }\n\n          // 3. update the value\n          for (SpringValue val : targetValues) {\n            updateSpringValue(val);\n          }\n        }\n      }\n    };\n\n    List<ConfigPropertySource> configPropertySources = configPropertySourceFactory.getAllConfigPropertySources();\n\n    for (ConfigPropertySource configPropertySource : configPropertySources) {\n      configPropertySource.addChangeListener(changeListener);\n    }\n  }\n\n  private void updateSpringValue(SpringValue springValue) {\n    try {\n      Object value = resolvePropertyValue(springValue);\n      springValue.update(value);\n\n      logger.debug(\"Auto update apollo changed value successfully, new value: {}, {}\", value,\n          springValue.toString());\n    } catch (Throwable ex) {\n      logger.error(\"Auto update apollo changed value failed, {}\", springValue.toString(), ex);\n    }\n  }\n\n  /**\n   * Logic transplanted from DefaultListableBeanFactory\n   * @see org.springframework.beans.factory.support.DefaultListableBeanFactory#doResolveDependency(org.springframework.beans.factory.config.DependencyDescriptor, java.lang.String, java.util.Set, org.springframework.beans.TypeConverter)\n   */\n  private Object resolvePropertyValue(SpringValue springValue) {\n    String strVal = beanFactory.resolveEmbeddedValue(springValue.getPlaceholder());\n    Object value;\n\n    BeanDefinition bd = (beanFactory.containsBean(springValue.getBeanName()) ? beanFactory\n        .getMergedBeanDefinition(springValue.getBeanName()) : null);\n    value = evaluateBeanDefinitionString(strVal, bd);\n\n    if (springValue.isField()) {\n      // org.springframework.beans.TypeConverter#convertIfNecessary(java.lang.Object, java.lang.Class, java.lang.reflect.Field) is available from Spring 3.2.0+\n      if (typeConverterHasConvertIfNecessaryWithFieldParameter) {\n        value = this.typeConverter\n            .convertIfNecessary(value, springValue.getTargetType(), springValue.getField());\n      } else {\n        value = this.typeConverter.convertIfNecessary(value, springValue.getTargetType());\n      }\n    } else {\n      value = this.typeConverter.convertIfNecessary(value, springValue.getTargetType(),\n          springValue.getMethodParameter());\n    }\n\n    return value;\n  }\n\n  private Object evaluateBeanDefinitionString(String value, BeanDefinition beanDefinition) {\n    if (beanFactory.getBeanExpressionResolver() == null) {\n      return value;\n    }\n    Scope scope = (beanDefinition != null ? beanFactory.getRegisteredScope(beanDefinition.getScope()) : null);\n    return beanFactory.getBeanExpressionResolver().evaluate(value, new BeanExpressionContext(beanFactory, scope));\n  }\n\n  private boolean testTypeConverterHasConvertIfNecessaryWithFieldParameter() {\n    try {\n      TypeConverter.class.getMethod(\"convertIfNecessary\", Object.class, Class.class, Field.class);\n    } catch (Throwable ex) {\n      return false;\n    }\n\n    return true;\n  }\n\n  @Override\n  public int getOrder() {\n    //make it as late as possible\n    return Ordered.LOWEST_PRECEDENCE;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/boot/ApolloApplicationContextInitializer.java",
    "content": "package com.ctrip.framework.apollo.spring.boot;\n\nimport com.ctrip.framework.apollo.Config;\nimport com.ctrip.framework.apollo.ConfigService;\nimport com.ctrip.framework.apollo.build.ApolloInjector;\nimport com.ctrip.framework.apollo.core.ConfigConsts;\nimport com.ctrip.framework.apollo.spring.config.ConfigPropertySourceFactory;\nimport com.ctrip.framework.apollo.spring.config.PropertySourcesConstants;\nimport com.google.common.base.Splitter;\nimport java.util.List;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.context.ApplicationContextInitializer;\nimport org.springframework.context.ConfigurableApplicationContext;\nimport org.springframework.core.env.CompositePropertySource;\nimport org.springframework.core.env.ConfigurableEnvironment;\n\n/**\n * Inject the Apollo config in Spring Boot bootstrap phase\n *\n * <p>Configuration example:</p>\n * <pre class=\"code\">\n *   # will inject 'application' namespace in bootstrap phase\n *   apollo.bootstrap.enabled = true\n * </pre>\n *\n * or\n *\n * <pre class=\"code\">\n *   apollo.bootstrap.enabled = true\n *   # will inject 'application' and 'FX.apollo' namespaces in bootstrap phase\n *   apollo.bootstrap.namespaces = application,FX.apollo\n * </pre>\n */\npublic class ApolloApplicationContextInitializer implements\n    ApplicationContextInitializer<ConfigurableApplicationContext> {\n  private static final Logger logger = LoggerFactory.getLogger(ApolloApplicationContextInitializer.class);\n  private static final Splitter NAMESPACE_SPLITTER = Splitter.on(\",\").omitEmptyStrings().trimResults();\n\n  private final ConfigPropertySourceFactory configPropertySourceFactory = ApolloInjector\n      .getInstance(ConfigPropertySourceFactory.class);\n\n  @Override\n  public void initialize(ConfigurableApplicationContext context) {\n    ConfigurableEnvironment environment = context.getEnvironment();\n    String enabled = environment.getProperty(PropertySourcesConstants.APOLLO_BOOTSTRAP_ENABLED, \"false\");\n    if (!Boolean.valueOf(enabled)) {\n      logger.debug(\"Apollo bootstrap config is not enabled for context {}, see property: ${{}}\", context, PropertySourcesConstants.APOLLO_BOOTSTRAP_ENABLED);\n      return;\n    }\n    logger.debug(\"Apollo bootstrap config is enabled for context {}\", context);\n\n    if (environment.getPropertySources().contains(PropertySourcesConstants.APOLLO_BOOTSTRAP_PROPERTY_SOURCE_NAME)) {\n      //already initialized\n      return;\n    }\n\n    String namespaces = environment.getProperty(PropertySourcesConstants.APOLLO_BOOTSTRAP_NAMESPACES, ConfigConsts.NAMESPACE_APPLICATION);\n    logger.debug(\"Apollo bootstrap namespaces: {}\", namespaces);\n    List<String> namespaceList = NAMESPACE_SPLITTER.splitToList(namespaces);\n\n    CompositePropertySource composite = new CompositePropertySource(PropertySourcesConstants.APOLLO_BOOTSTRAP_PROPERTY_SOURCE_NAME);\n    for (String namespace : namespaceList) {\n      Config config = ConfigService.getConfig(namespace);\n\n      composite.addPropertySource(configPropertySourceFactory.getConfigPropertySource(namespace, config));\n    }\n\n    environment.getPropertySources().addFirst(composite);\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/boot/ApolloAutoConfiguration.java",
    "content": "package com.ctrip.framework.apollo.spring.boot;\n\nimport com.ctrip.framework.apollo.spring.config.ConfigPropertySourcesProcessor;\nimport com.ctrip.framework.apollo.spring.config.PropertySourcesConstants;\nimport com.ctrip.framework.apollo.spring.config.PropertySourcesProcessor;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\n\n@Configuration\n@ConditionalOnProperty(PropertySourcesConstants.APOLLO_BOOTSTRAP_ENABLED)\n@ConditionalOnMissingBean(PropertySourcesProcessor.class)\npublic class ApolloAutoConfiguration {\n\n  @Bean\n  public ConfigPropertySourcesProcessor configPropertySourcesProcessor() {\n    return new ConfigPropertySourcesProcessor();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/config/ConfigPropertySource.java",
    "content": "package com.ctrip.framework.apollo.spring.config;\n\nimport com.ctrip.framework.apollo.ConfigChangeListener;\nimport java.util.Set;\n\nimport org.springframework.core.env.EnumerablePropertySource;\n\nimport com.ctrip.framework.apollo.Config;\n\n/**\n * Property source wrapper for Config\n *\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class ConfigPropertySource extends EnumerablePropertySource<Config> {\n  private static final String[] EMPTY_ARRAY = new String[0];\n\n  ConfigPropertySource(String name, Config source) {\n    super(name, source);\n  }\n\n  @Override\n  public String[] getPropertyNames() {\n    Set<String> propertyNames = this.source.getPropertyNames();\n    if (propertyNames.isEmpty()) {\n      return EMPTY_ARRAY;\n    }\n    return propertyNames.toArray(new String[propertyNames.size()]);\n  }\n\n  @Override\n  public Object getProperty(String name) {\n    return this.source.getProperty(name, null);\n  }\n\n  public void addChangeListener(ConfigChangeListener listener) {\n    this.source.addChangeListener(listener);\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/config/ConfigPropertySourceFactory.java",
    "content": "package com.ctrip.framework.apollo.spring.config;\n\nimport java.util.List;\n\nimport com.ctrip.framework.apollo.Config;\nimport com.google.common.collect.Lists;\n\npublic class ConfigPropertySourceFactory {\n\n  private final List<ConfigPropertySource> configPropertySources = Lists.newLinkedList();\n\n  public ConfigPropertySource getConfigPropertySource(String name, Config source) {\n    ConfigPropertySource configPropertySource = new ConfigPropertySource(name, source);\n\n    configPropertySources.add(configPropertySource);\n\n    return configPropertySource;\n  }\n\n  public List<ConfigPropertySource> getAllConfigPropertySources() {\n    return Lists.newLinkedList(configPropertySources);\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/config/ConfigPropertySourcesProcessor.java",
    "content": "package com.ctrip.framework.apollo.spring.config;\n\nimport com.ctrip.framework.apollo.spring.annotation.SpringValueProcessor;\nimport com.ctrip.framework.apollo.spring.property.SpringValueDefinitionProcessor;\nimport org.springframework.beans.BeansException;\nimport org.springframework.beans.factory.support.BeanDefinitionRegistry;\nimport org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;\nimport org.springframework.context.support.PropertySourcesPlaceholderConfigurer;\n\nimport com.ctrip.framework.apollo.spring.annotation.ApolloAnnotationProcessor;\nimport com.ctrip.framework.apollo.spring.util.BeanRegistrationUtil;\n\n/**\n * Apollo Property Sources processor for Spring XML Based Application\n *\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class ConfigPropertySourcesProcessor extends PropertySourcesProcessor\n    implements BeanDefinitionRegistryPostProcessor {\n\n  @Override\n  public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {\n    BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, PropertySourcesPlaceholderConfigurer.class.getName(),\n        PropertySourcesPlaceholderConfigurer.class);\n    BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, ApolloAnnotationProcessor.class.getName(),\n        ApolloAnnotationProcessor.class);\n    BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, SpringValueProcessor.class.getName(), SpringValueProcessor.class);\n\n    processSpringValueDefinition(registry);\n  }\n\n  /**\n   * For Spring 3.x versions, the BeanDefinitionRegistryPostProcessor would not be\n   * instantiated if it is added in postProcessBeanDefinitionRegistry phase, so we have to manually\n   * call the postProcessBeanDefinitionRegistry method of SpringValueDefinitionProcessor here...\n   */\n  private void processSpringValueDefinition(BeanDefinitionRegistry registry) {\n    SpringValueDefinitionProcessor springValueDefinitionProcessor = new SpringValueDefinitionProcessor();\n\n    springValueDefinitionProcessor.postProcessBeanDefinitionRegistry(registry);\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/config/NamespaceHandler.java",
    "content": "package com.ctrip.framework.apollo.spring.config;\n\nimport org.springframework.beans.factory.support.BeanDefinitionBuilder;\nimport org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;\nimport org.springframework.beans.factory.xml.NamespaceHandlerSupport;\nimport org.springframework.core.Ordered;\nimport org.w3c.dom.Element;\n\nimport com.ctrip.framework.apollo.core.ConfigConsts;\nimport com.google.common.base.Splitter;\nimport com.google.common.base.Strings;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class NamespaceHandler extends NamespaceHandlerSupport {\n  private static final Splitter NAMESPACE_SPLITTER = Splitter.on(\",\").omitEmptyStrings().trimResults();\n\n  @Override\n  public void init() {\n    registerBeanDefinitionParser(\"config\", new BeanParser());\n  }\n\n  static class BeanParser extends AbstractSingleBeanDefinitionParser {\n    @Override\n    protected Class<?> getBeanClass(Element element) {\n      return ConfigPropertySourcesProcessor.class;\n    }\n\n    @Override\n    protected boolean shouldGenerateId() {\n      return true;\n    }\n\n    @Override\n    protected void doParse(Element element, BeanDefinitionBuilder builder) {\n      String namespaces = element.getAttribute(\"namespaces\");\n      //default to application\n      if (Strings.isNullOrEmpty(namespaces)) {\n        namespaces = ConfigConsts.NAMESPACE_APPLICATION;\n      }\n\n      int order = Ordered.LOWEST_PRECEDENCE;\n      String orderAttribute = element.getAttribute(\"order\");\n\n      if (!Strings.isNullOrEmpty(orderAttribute)) {\n        try {\n          order = Integer.parseInt(orderAttribute);\n        } catch (Throwable ex) {\n          throw new IllegalArgumentException(\n              String.format(\"Invalid order: %s for namespaces: %s\", orderAttribute, namespaces));\n        }\n      }\n      PropertySourcesProcessor.addNamespaces(NAMESPACE_SPLITTER.splitToList(namespaces), order);\n    }\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/config/PropertySourcesConstants.java",
    "content": "package com.ctrip.framework.apollo.spring.config;\n\npublic interface PropertySourcesConstants {\n  String APOLLO_PROPERTY_SOURCE_NAME = \"ApolloPropertySources\";\n  String APOLLO_BOOTSTRAP_PROPERTY_SOURCE_NAME = \"ApolloBootstrapPropertySources\";\n  String APOLLO_BOOTSTRAP_ENABLED = \"apollo.bootstrap.enabled\";\n  String APOLLO_BOOTSTRAP_NAMESPACES = \"apollo.bootstrap.namespaces\";\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/config/PropertySourcesProcessor.java",
    "content": "package com.ctrip.framework.apollo.spring.config;\n\nimport com.ctrip.framework.apollo.build.ApolloInjector;\nimport com.google.common.collect.ImmutableSortedSet;\nimport com.google.common.collect.LinkedHashMultimap;\nimport com.google.common.collect.Multimap;\n\nimport com.ctrip.framework.apollo.Config;\nimport com.ctrip.framework.apollo.ConfigService;\n\nimport org.springframework.beans.BeansException;\nimport org.springframework.beans.factory.config.BeanFactoryPostProcessor;\nimport org.springframework.beans.factory.config.ConfigurableListableBeanFactory;\nimport org.springframework.context.EnvironmentAware;\nimport org.springframework.core.Ordered;\nimport org.springframework.core.PriorityOrdered;\nimport org.springframework.core.env.CompositePropertySource;\nimport org.springframework.core.env.ConfigurableEnvironment;\nimport org.springframework.core.env.Environment;\n\nimport java.util.Collection;\nimport java.util.Iterator;\n\n/**\n * Apollo Property Sources processor for Spring Annotation Based Application. <br /> <br />\n *\n * The reason why PropertySourcesProcessor implements {@link BeanFactoryPostProcessor} instead of\n * {@link org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor} is that lower versions of\n * Spring (e.g. 3.1.1) doesn't support registering BeanDefinitionRegistryPostProcessor in ImportBeanDefinitionRegistrar\n * - {@link com.ctrip.framework.apollo.spring.annotation.ApolloConfigRegistrar}\n *\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class PropertySourcesProcessor implements BeanFactoryPostProcessor, EnvironmentAware, PriorityOrdered {\n  private static final Multimap<Integer, String> NAMESPACE_NAMES = LinkedHashMultimap.create();\n\n  private final ConfigPropertySourceFactory configPropertySourceFactory = ApolloInjector\n      .getInstance(ConfigPropertySourceFactory.class);\n  private ConfigurableEnvironment environment;\n\n  public static boolean addNamespaces(Collection<String> namespaces, int order) {\n    return NAMESPACE_NAMES.putAll(order, namespaces);\n  }\n\n  @Override\n  public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {\n    initializePropertySources();\n  }\n\n  protected void initializePropertySources() {\n    if (environment.getPropertySources().contains(PropertySourcesConstants.APOLLO_PROPERTY_SOURCE_NAME)) {\n      //already initialized\n      return;\n    }\n    CompositePropertySource composite = new CompositePropertySource(PropertySourcesConstants.APOLLO_PROPERTY_SOURCE_NAME);\n\n    //sort by order asc\n    ImmutableSortedSet<Integer> orders = ImmutableSortedSet.copyOf(NAMESPACE_NAMES.keySet());\n    Iterator<Integer> iterator = orders.iterator();\n\n    while (iterator.hasNext()) {\n      int order = iterator.next();\n      for (String namespace : NAMESPACE_NAMES.get(order)) {\n        Config config = ConfigService.getConfig(namespace);\n\n        composite.addPropertySource(configPropertySourceFactory.getConfigPropertySource(namespace, config));\n      }\n    }\n\n    // add after the bootstrap property source or to the first\n    if (environment.getPropertySources()\n        .contains(PropertySourcesConstants.APOLLO_BOOTSTRAP_PROPERTY_SOURCE_NAME)) {\n      environment.getPropertySources()\n          .addAfter(PropertySourcesConstants.APOLLO_BOOTSTRAP_PROPERTY_SOURCE_NAME, composite);\n    } else {\n      environment.getPropertySources().addFirst(composite);\n    }\n  }\n\n  @Override\n  public void setEnvironment(Environment environment) {\n    //it is safe enough to cast as all known environment is derived from ConfigurableEnvironment\n    this.environment = (ConfigurableEnvironment) environment;\n  }\n\n  //only for test\n  private static void reset() {\n    NAMESPACE_NAMES.clear();\n  }\n\n  @Override\n  public int getOrder() {\n    //make it as early as possible\n    return Ordered.HIGHEST_PRECEDENCE;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/package-info.java",
    "content": "/**\n * This package contains Apollo Spring integration codes and enables the following features:<br/>\n * <p>1. Support Spring XML based configuration</p>\n * <ul>\n *   <li>&lt;apollo:config namespaces=\"someNamespace\"/&gt; to inject configurations from Apollo into Spring Property\n *   Sources so that placeholders like ${someProperty} and @Value(\"someProperty\") are supported.</li>\n * </ul>\n * <p>2. Support Spring Java based configuration</p>\n * <ul>\n *   <li>@EnableApolloConfig(namespaces={\"someNamespace\"}) to inject configurations from Apollo into Spring Property\n *   Sources so that placeholders like ${someProperty} and @Value(\"someProperty\") are supported.</li>\n * </ul>\n *\n * With the above configuration, annotations like @ApolloConfig(\"someNamespace\")\n * and @ApolloConfigChangeListener(\"someNamespace) are also supported.<br />\n * <br />\n * Requires Spring 3.1.1+\n */\npackage com.ctrip.framework.apollo.spring;"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/property/PlaceholderHelper.java",
    "content": "package com.ctrip.framework.apollo.spring.property;\n\nimport com.google.common.base.Strings;\nimport com.google.common.collect.Sets;\nimport java.util.Set;\nimport java.util.Stack;\nimport org.springframework.util.StringUtils;\n\n/**\n * Extract keys from placeholder, e.g.\n * <ul>\n * <li>${some.key} => \"some.key\"</li>\n * <li>${some.key:${some.other.key:100}} => \"some.key\", \"some.other.key\"</li>\n * <li>${${some.key}} => \"some.key\"</li>\n * <li>${${some.key:other.key}} => \"some.key\"</li>\n * <li>${${some.key}:${another.key}} => \"some.key\", \"another.key\"</li>\n * <li>#{new java.text.SimpleDateFormat('${some.key}').parse('${another.key}')} => \"some.key\", \"another.key\"</li>\n * </ul>\n */\npublic class PlaceholderHelper {\n\n  private static final String PLACEHOLDER_PREFIX = \"${\";\n  private static final String PLACEHOLDER_SUFFIX = \"}\";\n  private static final String VALUE_SEPARATOR = \":\";\n  private static final String SIMPLE_PLACEHOLDER_PREFIX = \"{\";\n  private static final String EXPRESSION_PREFIX = \"#{\";\n  private static final String EXPRESSION_SUFFIX = \"}\";\n\n  public Set<String> extractPlaceholderKeys(String propertyString) {\n    Set<String> placeholderKeys = Sets.newHashSet();\n\n    if (!isNormalizedPlaceholder(propertyString) && !isExpressionWithPlaceholder(propertyString)) {\n      return placeholderKeys;\n    }\n\n    Stack<String> stack = new Stack<>();\n    stack.push(propertyString);\n\n    while (!stack.isEmpty()) {\n      String strVal = stack.pop();\n      int startIndex = strVal.indexOf(PLACEHOLDER_PREFIX);\n      if (startIndex == -1) {\n        placeholderKeys.add(strVal);\n        continue;\n      }\n      int endIndex = findPlaceholderEndIndex(strVal, startIndex);\n      if (endIndex == -1) {\n        // invalid placeholder?\n        continue;\n      }\n\n      String placeholderCandidate = strVal.substring(startIndex + PLACEHOLDER_PREFIX.length(), endIndex);\n\n      // ${some.key:other.key}\n      if (placeholderCandidate.startsWith(PLACEHOLDER_PREFIX)) {\n        stack.push(placeholderCandidate);\n      } else {\n        // some.key:${some.other.key:100}\n        int separatorIndex = placeholderCandidate.indexOf(VALUE_SEPARATOR);\n\n        if (separatorIndex == -1) {\n          stack.push(placeholderCandidate);\n        } else {\n          stack.push(placeholderCandidate.substring(0, separatorIndex));\n          String defaultValuePart =\n              normalizeToPlaceholder(placeholderCandidate.substring(separatorIndex + VALUE_SEPARATOR.length()));\n          if (!Strings.isNullOrEmpty(defaultValuePart)) {\n            stack.push(defaultValuePart);\n          }\n        }\n      }\n\n      // has remaining part, e.g. ${a}.${b}\n      if (endIndex + PLACEHOLDER_SUFFIX.length() < strVal.length() - 1) {\n        String remainingPart = normalizeToPlaceholder(strVal.substring(endIndex + PLACEHOLDER_SUFFIX.length()));\n        if (!Strings.isNullOrEmpty(remainingPart)) {\n          stack.push(remainingPart);\n        }\n      }\n    }\n\n    return placeholderKeys;\n  }\n\n  private boolean isNormalizedPlaceholder(String propertyString) {\n    return propertyString.startsWith(PLACEHOLDER_PREFIX) && propertyString.endsWith(PLACEHOLDER_SUFFIX);\n  }\n\n  private boolean isExpressionWithPlaceholder(String propertyString) {\n    return propertyString.startsWith(EXPRESSION_PREFIX) && propertyString.endsWith(EXPRESSION_SUFFIX)\n        && propertyString.contains(PLACEHOLDER_PREFIX);\n  }\n\n  private String normalizeToPlaceholder(String strVal) {\n    int startIndex = strVal.indexOf(PLACEHOLDER_PREFIX);\n    if (startIndex == -1) {\n      return null;\n    }\n    int endIndex = strVal.lastIndexOf(PLACEHOLDER_SUFFIX);\n    if (endIndex == -1) {\n      return null;\n    }\n\n    return strVal.substring(startIndex, endIndex + PLACEHOLDER_SUFFIX.length());\n  }\n\n  private int findPlaceholderEndIndex(CharSequence buf, int startIndex) {\n    int index = startIndex + PLACEHOLDER_PREFIX.length();\n    int withinNestedPlaceholder = 0;\n    while (index < buf.length()) {\n      if (StringUtils.substringMatch(buf, index, PLACEHOLDER_SUFFIX)) {\n        if (withinNestedPlaceholder > 0) {\n          withinNestedPlaceholder--;\n          index = index + PLACEHOLDER_SUFFIX.length();\n        } else {\n          return index;\n        }\n      } else if (StringUtils.substringMatch(buf, index, SIMPLE_PLACEHOLDER_PREFIX)) {\n        withinNestedPlaceholder++;\n        index = index + SIMPLE_PLACEHOLDER_PREFIX.length();\n      } else {\n        index++;\n      }\n    }\n    return -1;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/property/SpringValue.java",
    "content": "package com.ctrip.framework.apollo.spring.property;\n\nimport java.lang.reflect.Field;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport org.springframework.core.MethodParameter;\n\n/**\n * Spring @Value method info\n *\n * @author github.com/zhegexiaohuozi  seimimaster@gmail.com\n * @since 2018/2/6.\n */\npublic class SpringValue {\n\n  private MethodParameter methodParameter;\n  private Field field;\n  private Object bean;\n  private String beanName;\n  private String key;\n  private String placeholder;\n  private Class<?> targetType;\n\n  public SpringValue(String key, String placeholder, Object bean, String beanName, Field field) {\n    this.bean = bean;\n    this.beanName = beanName;\n    this.field = field;\n    this.key = key;\n    this.placeholder = placeholder;\n    this.targetType = field.getType();\n  }\n\n  public SpringValue(String key, String placeholder, Object bean, String beanName, Method method) {\n    this.bean = bean;\n    this.beanName = beanName;\n    this.methodParameter = new MethodParameter(method, 0);\n    this.key = key;\n    this.placeholder = placeholder;\n    Class<?>[] paramTps = method.getParameterTypes();\n    this.targetType = paramTps[0];\n  }\n\n  public void update(Object newVal) throws IllegalAccessException, InvocationTargetException {\n    if (isField()) {\n      injectField(newVal);\n    } else {\n      injectMethod(newVal);\n    }\n  }\n\n  private void injectField(Object newVal) throws IllegalAccessException {\n    boolean accessible = field.isAccessible();\n    field.setAccessible(true);\n    field.set(bean, newVal);\n    field.setAccessible(accessible);\n  }\n\n  private void injectMethod(Object newVal)\n      throws InvocationTargetException, IllegalAccessException {\n    methodParameter.getMethod().invoke(bean, newVal);\n  }\n\n  public String getBeanName() {\n    return beanName;\n  }\n\n  public Class<?> getTargetType() {\n    return targetType;\n  }\n\n  public String getPlaceholder() {\n    return this.placeholder;\n  }\n\n  public MethodParameter getMethodParameter() {\n    return methodParameter;\n  }\n\n  public boolean isField() {\n    return this.field != null;\n  }\n\n  public Field getField() {\n    return field;\n  }\n\n  @Override\n  public String toString() {\n    if (isField()) {\n      return String\n          .format(\"key: %s, beanName: %s, field: %s.%s\", key, beanName, bean.getClass().getName(), field.getName());\n    }\n    return String.format(\"key: %s, beanName: %s, method: %s.%s\", key, beanName, bean.getClass().getName(),\n        methodParameter.getMethod().getName());\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/property/SpringValueDefinition.java",
    "content": "package com.ctrip.framework.apollo.spring.property;\n\npublic class SpringValueDefinition {\n\n  private final String key;\n  private final String placeholder;\n  private final String propertyName;\n\n  public SpringValueDefinition(String key, String placeholder, String propertyName) {\n    this.key = key;\n    this.placeholder = placeholder;\n    this.propertyName = propertyName;\n  }\n\n  public String getKey() {\n    return key;\n  }\n\n  public String getPlaceholder() {\n    return placeholder;\n  }\n\n  public String getPropertyName() {\n    return propertyName;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/property/SpringValueDefinitionProcessor.java",
    "content": "package com.ctrip.framework.apollo.spring.property;\n\nimport java.util.List;\nimport java.util.Set;\n\nimport java.util.concurrent.atomic.AtomicBoolean;\nimport org.springframework.beans.BeansException;\nimport org.springframework.beans.MutablePropertyValues;\nimport org.springframework.beans.PropertyValue;\nimport org.springframework.beans.factory.config.BeanDefinition;\nimport org.springframework.beans.factory.config.ConfigurableListableBeanFactory;\nimport org.springframework.beans.factory.config.TypedStringValue;\nimport org.springframework.beans.factory.support.BeanDefinitionRegistry;\nimport org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;\n\nimport com.ctrip.framework.apollo.build.ApolloInjector;\nimport com.ctrip.framework.apollo.util.ConfigUtil;\nimport com.google.common.collect.LinkedListMultimap;\nimport com.google.common.collect.Multimap;\n\n/**\n * To process xml config placeholders, e.g.\n *\n * <pre>\n *  &lt;bean class=&quot;com.ctrip.framework.apollo.demo.spring.xmlConfigDemo.bean.XmlBean&quot;&gt;\n *    &lt;property name=&quot;timeout&quot; value=&quot;${timeout:200}&quot;/&gt;\n *    &lt;property name=&quot;batch&quot; value=&quot;${batch:100}&quot;/&gt;\n *  &lt;/bean&gt;\n * </pre>\n */\npublic class SpringValueDefinitionProcessor implements BeanDefinitionRegistryPostProcessor {\n  private static final Multimap<String, SpringValueDefinition> beanName2SpringValueDefinitions =\n      LinkedListMultimap.create();\n  private static final AtomicBoolean initialized = new AtomicBoolean(false);\n\n  private final ConfigUtil configUtil;\n  private final PlaceholderHelper placeholderHelper;\n\n  public SpringValueDefinitionProcessor() {\n    configUtil = ApolloInjector.getInstance(ConfigUtil.class);\n    placeholderHelper = ApolloInjector.getInstance(PlaceholderHelper.class);\n  }\n\n  @Override\n  public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {\n    if (configUtil.isAutoUpdateInjectedSpringPropertiesEnabled()) {\n      processPropertyValues(registry);\n    }\n  }\n\n  @Override\n  public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {\n\n  }\n\n  public static Multimap<String, SpringValueDefinition> getBeanName2SpringValueDefinitions() {\n    return beanName2SpringValueDefinitions;\n  }\n\n  private void processPropertyValues(BeanDefinitionRegistry beanRegistry) {\n    if (!initialized.compareAndSet(false, true)) {\n      // already initialized\n      return;\n    }\n\n    String[] beanNames = beanRegistry.getBeanDefinitionNames();\n    for (String beanName : beanNames) {\n      BeanDefinition beanDefinition = beanRegistry.getBeanDefinition(beanName);\n      MutablePropertyValues mutablePropertyValues = beanDefinition.getPropertyValues();\n      List<PropertyValue> propertyValues = mutablePropertyValues.getPropertyValueList();\n      for (PropertyValue propertyValue : propertyValues) {\n        Object value = propertyValue.getValue();\n        if (!(value instanceof TypedStringValue)) {\n          continue;\n        }\n        String placeholder = ((TypedStringValue) value).getValue();\n        Set<String> keys = placeholderHelper.extractPlaceholderKeys(placeholder);\n\n        if (keys.isEmpty()) {\n          continue;\n        }\n\n        for (String key : keys) {\n          beanName2SpringValueDefinitions.put(beanName,\n              new SpringValueDefinition(key, placeholder, propertyValue.getName()));\n        }\n      }\n    }\n  }\n\n  //only for test\n  private static void reset() {\n    initialized.set(false);\n    beanName2SpringValueDefinitions.clear();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/util/BeanRegistrationUtil.java",
    "content": "package com.ctrip.framework.apollo.spring.util;\n\nimport java.util.Objects;\n\nimport org.springframework.beans.factory.config.BeanDefinition;\nimport org.springframework.beans.factory.support.BeanDefinitionBuilder;\nimport org.springframework.beans.factory.support.BeanDefinitionRegistry;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class BeanRegistrationUtil {\n  public static boolean registerBeanDefinitionIfNotExists(BeanDefinitionRegistry registry, String beanName,\n                                                          Class<?> beanClass) {\n    if (registry.containsBeanDefinition(beanName)) {\n      return false;\n    }\n\n    String[] candidates = registry.getBeanDefinitionNames();\n\n    for (String candidate : candidates) {\n      BeanDefinition beanDefinition = registry.getBeanDefinition(candidate);\n      if (Objects.equals(beanDefinition.getBeanClassName(), beanClass.getName())) {\n        return false;\n      }\n    }\n\n    BeanDefinition annotationProcessor = BeanDefinitionBuilder.genericBeanDefinition(beanClass).getBeanDefinition();\n    registry.registerBeanDefinition(beanName, annotationProcessor);\n\n    return true;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/util/ConfigUtil.java",
    "content": "package com.ctrip.framework.apollo.util;\n\nimport java.util.concurrent.TimeUnit;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.ctrip.framework.apollo.core.ConfigConsts;\nimport com.ctrip.framework.apollo.core.MetaDomainConsts;\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.core.enums.EnvUtils;\nimport com.ctrip.framework.apollo.exceptions.ApolloConfigException;\nimport com.ctrip.framework.foundation.Foundation;\nimport com.google.common.base.Strings;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class ConfigUtil {\n  private static final Logger logger = LoggerFactory.getLogger(ConfigUtil.class);\n  private int refreshInterval = 5;\n  private TimeUnit refreshIntervalTimeUnit = TimeUnit.MINUTES;\n  private int connectTimeout = 1000; //1 second\n  private int readTimeout = 5000; //5 seconds\n  private String cluster;\n  private int loadConfigQPS = 2; //2 times per second\n  private int longPollQPS = 2; //2 times per second\n  //for on error retry\n  private long onErrorRetryInterval = 1;//1 second\n  private TimeUnit onErrorRetryIntervalTimeUnit = TimeUnit.SECONDS;//1 second\n  //for typed config cache of parser result, e.g. integer, double, long, etc.\n  private long maxConfigCacheSize = 500;//500 cache key\n  private long configCacheExpireTime = 1;//1 minute\n  private TimeUnit configCacheExpireTimeUnit = TimeUnit.MINUTES;//1 minute\n  private long longPollingInitialDelayInMills = 2000;//2 seconds\n  private boolean autoUpdateInjectedSpringProperties = true;\n\n  public ConfigUtil() {\n    initRefreshInterval();\n    initConnectTimeout();\n    initReadTimeout();\n    initCluster();\n    initQPS();\n    initMaxConfigCacheSize();\n    initLongPollingInitialDelayInMills();\n    initAutoUpdateInjectedSpringProperties();\n  }\n\n  /**\n   * Get the app id for the current application.\n   *\n   * @return the app id or ConfigConsts.NO_APPID_PLACEHOLDER if app id is not available\n   */\n  public String getAppId() {\n    String appId = Foundation.app().getAppId();\n    if (Strings.isNullOrEmpty(appId)) {\n      appId = ConfigConsts.NO_APPID_PLACEHOLDER;\n      logger.warn(\"app.id is not set, please make sure it is set in classpath:/META-INF/app.properties, now apollo \" +\n          \"will only load public namespace configurations!\");\n    }\n    return appId;\n  }\n\n  /**\n   * Get the data center info for the current application.\n   *\n   * @return the current data center, null if there is no such info.\n   */\n  public String getDataCenter() {\n    return Foundation.server().getDataCenter();\n  }\n\n  private void initCluster() {\n    //Load data center from system property\n    cluster = System.getProperty(ConfigConsts.APOLLO_CLUSTER_KEY);\n\n    //Use data center as cluster\n    if (Strings.isNullOrEmpty(cluster)) {\n      cluster = getDataCenter();\n    }\n\n    //Use default cluster\n    if (Strings.isNullOrEmpty(cluster)) {\n      cluster = ConfigConsts.CLUSTER_NAME_DEFAULT;\n    }\n  }\n\n  /**\n   * Get the cluster name for the current application.\n   *\n   * @return the cluster name, or \"default\" if not specified\n   */\n  public String getCluster() {\n    return cluster;\n  }\n\n  /**\n   * Get the current environment.\n   *\n   * @return the env\n   * @throws ApolloConfigException if env is set\n   */\n  public Env getApolloEnv() {\n    Env env = EnvUtils.transformEnv(Foundation.server().getEnvType());\n    if (env == null) {\n      String path = isOSWindows() ? \"C:\\\\opt\\\\settings\\\\server.properties\" :\n          \"/opt/settings/server.properties\";\n      String message = String.format(\"env is not set, please make sure it is set in %s!\", path);\n      logger.error(message);\n      throw new ApolloConfigException(message);\n    }\n    return env;\n  }\n\n  public String getLocalIp() {\n    return Foundation.net().getHostAddress();\n  }\n\n  public String getMetaServerDomainName() {\n    return MetaDomainConsts.getDomain(getApolloEnv());\n  }\n\n  private void initConnectTimeout() {\n    String customizedConnectTimeout = System.getProperty(\"apollo.connectTimeout\");\n    if (!Strings.isNullOrEmpty(customizedConnectTimeout)) {\n      try {\n        connectTimeout = Integer.parseInt(customizedConnectTimeout);\n      } catch (Throwable ex) {\n        logger.error(\"Config for apollo.connectTimeout is invalid: {}\", customizedConnectTimeout);\n      }\n    }\n  }\n\n  public int getConnectTimeout() {\n    return connectTimeout;\n  }\n\n  private void initReadTimeout() {\n    String customizedReadTimeout = System.getProperty(\"apollo.readTimeout\");\n    if (!Strings.isNullOrEmpty(customizedReadTimeout)) {\n      try {\n        readTimeout = Integer.parseInt(customizedReadTimeout);\n      } catch (Throwable ex) {\n        logger.error(\"Config for apollo.readTimeout is invalid: {}\", customizedReadTimeout);\n      }\n    }\n  }\n\n  public int getReadTimeout() {\n    return readTimeout;\n  }\n\n  private void initRefreshInterval() {\n    String customizedRefreshInterval = System.getProperty(\"apollo.refreshInterval\");\n    if (!Strings.isNullOrEmpty(customizedRefreshInterval)) {\n      try {\n        refreshInterval = Integer.parseInt(customizedRefreshInterval);\n      } catch (Throwable ex) {\n        logger.error(\"Config for apollo.refreshInterval is invalid: {}\", customizedRefreshInterval);\n      }\n    }\n  }\n\n  public int getRefreshInterval() {\n    return refreshInterval;\n  }\n\n  public TimeUnit getRefreshIntervalTimeUnit() {\n    return refreshIntervalTimeUnit;\n  }\n\n  private void initQPS() {\n    String customizedLoadConfigQPS = System.getProperty(\"apollo.loadConfigQPS\");\n    if (!Strings.isNullOrEmpty(customizedLoadConfigQPS)) {\n      try {\n        loadConfigQPS = Integer.parseInt(customizedLoadConfigQPS);\n      } catch (Throwable ex) {\n        logger.error(\"Config for apollo.loadConfigQPS is invalid: {}\", customizedLoadConfigQPS);\n      }\n    }\n\n    String customizedLongPollQPS = System.getProperty(\"apollo.longPollQPS\");\n    if (!Strings.isNullOrEmpty(customizedLongPollQPS)) {\n      try {\n        longPollQPS = Integer.parseInt(customizedLongPollQPS);\n      } catch (Throwable ex) {\n        logger.error(\"Config for apollo.longPollQPS is invalid: {}\", customizedLongPollQPS);\n      }\n    }\n  }\n\n  public int getLoadConfigQPS() {\n    return loadConfigQPS;\n  }\n\n  public int getLongPollQPS() {\n    return longPollQPS;\n  }\n\n  public long getOnErrorRetryInterval() {\n    return onErrorRetryInterval;\n  }\n\n  public TimeUnit getOnErrorRetryIntervalTimeUnit() {\n    return onErrorRetryIntervalTimeUnit;\n  }\n\n  public String getDefaultLocalCacheDir() {\n    String cacheRoot = isOSWindows() ? \"C:\\\\opt\\\\data\\\\%s\" : \"/opt/data/%s\";\n    return String.format(cacheRoot, getAppId());\n  }\n\n  public boolean isInLocalMode() {\n    try {\n      Env env = getApolloEnv();\n      return env == Env.LOCAL;\n    } catch (Throwable ex) {\n      //ignore\n    }\n    return false;\n  }\n\n  public boolean isOSWindows() {\n    String osName = System.getProperty(\"os.name\");\n    if (Strings.isNullOrEmpty(osName)) {\n      return false;\n    }\n    return osName.startsWith(\"Windows\");\n  }\n\n  private void initMaxConfigCacheSize() {\n    String customizedConfigCacheSize = System.getProperty(\"apollo.configCacheSize\");\n    if (!Strings.isNullOrEmpty(customizedConfigCacheSize)) {\n      try {\n        maxConfigCacheSize = Long.valueOf(customizedConfigCacheSize);\n      } catch (Throwable ex) {\n        logger.error(\"Config for apollo.configCacheSize is invalid: {}\", customizedConfigCacheSize);\n      }\n    }\n  }\n\n  public long getMaxConfigCacheSize() {\n    return maxConfigCacheSize;\n  }\n\n  public long getConfigCacheExpireTime() {\n    return configCacheExpireTime;\n  }\n\n  public TimeUnit getConfigCacheExpireTimeUnit() {\n    return configCacheExpireTimeUnit;\n  }\n\n  private void initLongPollingInitialDelayInMills() {\n    String customizedLongPollingInitialDelay = System.getProperty(\"apollo.longPollingInitialDelayInMills\");\n    if (!Strings.isNullOrEmpty(customizedLongPollingInitialDelay)) {\n      try {\n        longPollingInitialDelayInMills = Long.valueOf(customizedLongPollingInitialDelay);\n      } catch (Throwable ex) {\n        logger.error(\"Config for apollo.longPollingInitialDelayInMills is invalid: {}\", customizedLongPollingInitialDelay);\n      }\n    }\n  }\n\n  public long getLongPollingInitialDelayInMills() {\n    return longPollingInitialDelayInMills;\n  }\n\n  private void initAutoUpdateInjectedSpringProperties() {\n    // 1. Get from System Property\n    String enableAutoUpdate = System.getProperty(\"apollo.autoUpdateInjectedSpringProperties\");\n    if (Strings.isNullOrEmpty(enableAutoUpdate)) {\n      // 2. Get from app.properties\n      enableAutoUpdate = Foundation.app().getProperty(\"apollo.autoUpdateInjectedSpringProperties\", null);\n    }\n    if (!Strings.isNullOrEmpty(enableAutoUpdate)) {\n      autoUpdateInjectedSpringProperties = Boolean.parseBoolean(enableAutoUpdate.trim());\n    }\n  }\n\n  public boolean isAutoUpdateInjectedSpringPropertiesEnabled() {\n    return autoUpdateInjectedSpringProperties;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/util/ExceptionUtil.java",
    "content": "package com.ctrip.framework.apollo.util;\n\nimport java.util.List;\n\nimport com.google.common.base.Strings;\nimport com.google.common.collect.Lists;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class ExceptionUtil {\n  /**\n   * Assemble the detail message for the throwable with all of its cause included (at most 10 causes).\n   * @param ex the exception\n   * @return the message along with its causes\n   */\n  public static String getDetailMessage(Throwable ex) {\n    if (ex == null || Strings.isNullOrEmpty(ex.getMessage())) {\n      return \"\";\n    }\n    StringBuilder builder = new StringBuilder(ex.getMessage());\n    List<Throwable> causes = Lists.newLinkedList();\n\n    int counter = 0;\n    Throwable current = ex;\n    //retrieve up to 10 causes\n    while (current.getCause() != null && counter < 10) {\n      Throwable next = current.getCause();\n      causes.add(next);\n      current = next;\n      counter++;\n    }\n\n    for (Throwable cause : causes) {\n      if (Strings.isNullOrEmpty(cause.getMessage())) {\n        counter--;\n        continue;\n      }\n      builder.append(\" [Cause: \").append(cause.getMessage());\n    }\n\n    builder.append(Strings.repeat(\"]\", counter));\n\n    return builder.toString();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/util/function/Functions.java",
    "content": "package com.ctrip.framework.apollo.util.function;\n\nimport java.util.Date;\n\nimport com.ctrip.framework.apollo.exceptions.ApolloConfigException;\nimport com.ctrip.framework.apollo.util.parser.ParserException;\nimport com.ctrip.framework.apollo.util.parser.Parsers;\nimport com.google.common.base.Function;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic interface Functions {\n  Function<String, Integer> TO_INT_FUNCTION = new Function<String, Integer>() {\n    @Override\n    public Integer apply(String input) {\n      return Integer.parseInt(input);\n    }\n  };\n  Function<String, Long> TO_LONG_FUNCTION = new Function<String, Long>() {\n    @Override\n    public Long apply(String input) {\n      return Long.parseLong(input);\n    }\n  };\n  Function<String, Short> TO_SHORT_FUNCTION = new Function<String, Short>() {\n    @Override\n    public Short apply(String input) {\n      return Short.parseShort(input);\n    }\n  };\n  Function<String, Float> TO_FLOAT_FUNCTION = new Function<String, Float>() {\n    @Override\n    public Float apply(String input) {\n      return Float.parseFloat(input);\n    }\n  };\n  Function<String, Double> TO_DOUBLE_FUNCTION = new Function<String, Double>() {\n    @Override\n    public Double apply(String input) {\n      return Double.parseDouble(input);\n    }\n  };\n  Function<String, Byte> TO_BYTE_FUNCTION = new Function<String, Byte>() {\n    @Override\n    public Byte apply(String input) {\n      return Byte.parseByte(input);\n    }\n  };\n  Function<String, Boolean> TO_BOOLEAN_FUNCTION = new Function<String, Boolean>() {\n    @Override\n    public Boolean apply(String input) {\n      return Boolean.parseBoolean(input);\n    }\n  };\n  Function<String, Date> TO_DATE_FUNCTION = new Function<String, Date>() {\n    @Override\n    public Date apply(String input) {\n      try {\n        return Parsers.forDate().parse(input);\n      } catch (ParserException ex) {\n        throw new ApolloConfigException(\"Parse date failed\", ex);\n      }\n    }\n  };\n  Function<String, Long> TO_DURATION_FUNCTION = new Function<String, Long>() {\n    @Override\n    public Long apply(String input) {\n      try {\n        return Parsers.forDuration().parseToMillis(input);\n      } catch (ParserException ex) {\n        throw new ApolloConfigException(\"Parse duration failed\", ex);\n      }\n    }\n  };\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/util/http/HttpRequest.java",
    "content": "package com.ctrip.framework.apollo.util.http;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class HttpRequest {\n  private String m_url;\n  private int m_connectTimeout;\n  private int m_readTimeout;\n\n  /**\n   * Create the request for the url.\n   * @param url the url\n   */\n  public HttpRequest(String url) {\n    this.m_url = url;\n    m_connectTimeout = -1;\n    m_readTimeout = -1;\n  }\n\n  public String getUrl() {\n    return m_url;\n  }\n\n  public int getConnectTimeout() {\n    return m_connectTimeout;\n  }\n\n  public void setConnectTimeout(int connectTimeout) {\n    this.m_connectTimeout = connectTimeout;\n  }\n\n  public int getReadTimeout() {\n    return m_readTimeout;\n  }\n\n  public void setReadTimeout(int readTimeout) {\n    this.m_readTimeout = readTimeout;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/util/http/HttpResponse.java",
    "content": "package com.ctrip.framework.apollo.util.http;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class HttpResponse<T> {\n  private final int m_statusCode;\n  private final T m_body;\n\n  public HttpResponse(int statusCode, T body) {\n    this.m_statusCode = statusCode;\n    this.m_body = body;\n  }\n\n  public int getStatusCode() {\n    return m_statusCode;\n  }\n\n  public T getBody() {\n    return m_body;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/util/http/HttpUtil.java",
    "content": "package com.ctrip.framework.apollo.util.http;\n\nimport com.ctrip.framework.apollo.build.ApolloInjector;\nimport com.ctrip.framework.apollo.exceptions.ApolloConfigException;\nimport com.ctrip.framework.apollo.exceptions.ApolloConfigStatusCodeException;\nimport com.ctrip.framework.apollo.util.ConfigUtil;\nimport com.google.common.base.Function;\nimport com.google.common.io.CharStreams;\nimport com.google.gson.Gson;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\nimport java.lang.reflect.Type;\nimport java.net.HttpURLConnection;\nimport java.net.URL;\nimport java.nio.charset.StandardCharsets;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class HttpUtil {\n  private ConfigUtil m_configUtil;\n  private Gson gson;\n\n  /**\n   * Constructor.\n   */\n  public HttpUtil() {\n    m_configUtil = ApolloInjector.getInstance(ConfigUtil.class);\n    gson = new Gson();\n  }\n\n  /**\n   * Do get operation for the http request.\n   *\n   * @param httpRequest  the request\n   * @param responseType the response type\n   * @return the response\n   * @throws ApolloConfigException if any error happened or response code is neither 200 nor 304\n   */\n  public <T> HttpResponse<T> doGet(HttpRequest httpRequest, final Class<T> responseType) {\n    Function<String, T> convertResponse = new Function<String, T>() {\n      @Override\n      public T apply(String input) {\n        return gson.fromJson(input, responseType);\n      }\n    };\n\n    return doGetWithSerializeFunction(httpRequest, convertResponse);\n  }\n\n  /**\n   * Do get operation for the http request.\n   *\n   * @param httpRequest  the request\n   * @param responseType the response type\n   * @return the response\n   * @throws ApolloConfigException if any error happened or response code is neither 200 nor 304\n   */\n  public <T> HttpResponse<T> doGet(HttpRequest httpRequest, final Type responseType) {\n    Function<String, T> convertResponse = new Function<String, T>() {\n      @Override\n      public T apply(String input) {\n        return gson.fromJson(input, responseType);\n      }\n    };\n\n    return doGetWithSerializeFunction(httpRequest, convertResponse);\n  }\n\n  private <T> HttpResponse<T> doGetWithSerializeFunction(HttpRequest httpRequest,\n                                                         Function<String, T> serializeFunction) {\n    InputStreamReader isr = null;\n    InputStreamReader esr = null;\n    int statusCode;\n    try {\n      HttpURLConnection conn = (HttpURLConnection) new URL(httpRequest.getUrl()).openConnection();\n\n      conn.setRequestMethod(\"GET\");\n\n      int connectTimeout = httpRequest.getConnectTimeout();\n      if (connectTimeout < 0) {\n        connectTimeout = m_configUtil.getConnectTimeout();\n      }\n\n      int readTimeout = httpRequest.getReadTimeout();\n      if (readTimeout < 0) {\n        readTimeout = m_configUtil.getReadTimeout();\n      }\n\n      conn.setConnectTimeout(connectTimeout);\n      conn.setReadTimeout(readTimeout);\n\n      conn.connect();\n\n      statusCode = conn.getResponseCode();\n      String response;\n\n      try {\n        isr = new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8);\n        response = CharStreams.toString(isr);\n      } catch (IOException ex) {\n        /**\n         * according to https://docs.oracle.com/javase/7/docs/technotes/guides/net/http-keepalive.html,\n         * we should clean up the connection by reading the response body so that the connection\n         * could be reused.\n         */\n        InputStream errorStream = conn.getErrorStream();\n\n        if (errorStream != null) {\n          esr = new InputStreamReader(errorStream, StandardCharsets.UTF_8);\n          try {\n            CharStreams.toString(esr);\n          } catch (IOException ioe) {\n            //ignore\n          }\n        }\n\n        throw ex;\n      }\n\n      if (statusCode == 200) {\n        return new HttpResponse<>(statusCode, serializeFunction.apply(response));\n      }\n\n      if (statusCode == 304) {\n        return new HttpResponse<>(statusCode, null);\n      }\n    } catch (Throwable ex) {\n      throw new ApolloConfigException(\"Could not complete get operation\", ex);\n    } finally {\n      if (isr != null) {\n        try {\n          isr.close();\n        } catch (IOException ex) {\n          // ignore\n        }\n      }\n\n      if (esr != null) {\n        try {\n          esr.close();\n        } catch (IOException ex) {\n          // ignore\n        }\n      }\n    }\n\n    throw new ApolloConfigStatusCodeException(statusCode,\n        String.format(\"Get operation failed for %s\", httpRequest.getUrl()));\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/util/parser/ParserException.java",
    "content": "package com.ctrip.framework.apollo.util.parser;\n\npublic class ParserException extends Exception {\n    public ParserException(String message) {\n        super(message);\n    }\n\n    public ParserException(String message, Throwable cause) {\n        super(message, cause);\n    }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/util/parser/Parsers.java",
    "content": "package com.ctrip.framework.apollo.util.parser;\n\nimport java.text.ParseException;\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\nimport java.util.Locale;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\npublic class Parsers {\n  public static DateParser forDate() {\n    return DateParser.INSTANCE;\n  }\n\n  public static DurationParser forDuration() {\n    return DurationParser.INSTANCE;\n  }\n\n  public enum DateParser {\n    INSTANCE;\n\n    private static final String LONG_DATE_FORMAT = \"yyyy-MM-dd HH:mm:ss.SSS\";\n    private static final String MEDIUM_DATE_FORMAT = \"yyyy-MM-dd HH:mm:ss\";\n    private static final String SHORT_DATE_FORMAT = \"yyyy-MM-dd\";\n\n    /**\n     * Will try to parse the date with Locale.US and formats as follows:\n     * yyyy-MM-dd HH:mm:ss.SSS, yyyy-MM-dd HH:mm:ss and yyyy-MM-dd\n     *\n     * @param text the text to parse\n     * @return the parsed date\n     * @throws ParserException if the text cannot be parsed\n     */\n    public Date parse(String text) throws ParserException {\n      text = text.trim();\n      int length = text.length();\n\n      if (length == LONG_DATE_FORMAT.length()) {\n        return parse(text, LONG_DATE_FORMAT);\n      }\n\n      if (length == MEDIUM_DATE_FORMAT.length()) {\n        return parse(text, MEDIUM_DATE_FORMAT);\n      }\n\n      return parse(text, SHORT_DATE_FORMAT);\n    }\n\n    /**\n     * Parse the text with the format specified and Locale.US\n     *\n     * @param text   the text to parse\n     * @param format the date format, see {@link java.text.SimpleDateFormat} for more information\n     * @return the parsed date\n     * @throws ParserException if the text cannot be parsed\n     */\n    public Date parse(String text, String format) throws ParserException {\n      return parse(text, format, Locale.US);\n    }\n\n    /**\n     * Parse the text with the format and locale specified\n     *\n     * @param text   the text to parse\n     * @param format the date format, see {@link java.text.SimpleDateFormat} for more information\n     * @param locale the locale\n     * @return the parsed date\n     * @throws ParserException if the text cannot be parsed\n     */\n    public Date parse(String text, String format, Locale locale) throws ParserException {\n      SimpleDateFormat dateFormat = getDateFormat(format, locale);\n\n      try {\n        return dateFormat.parse(text.trim());\n      } catch (ParseException e) {\n        throw new ParserException(\"Error when parsing date(\" + dateFormat.toPattern() + \") from \" + text, e);\n      }\n    }\n\n    private SimpleDateFormat getDateFormat(String format, Locale locale) {\n      return new SimpleDateFormat(format, locale);\n    }\n  }\n\n  public enum DurationParser {\n    INSTANCE;\n\n    private static final Pattern PATTERN =\n        Pattern.compile(\"(?:([0-9]+)D)?(?:([0-9]+)H)?(?:([0-9]+)M)?(?:([0-9]+)S)?(?:([0-9]+)(?:MS)?)?\",\n            Pattern.CASE_INSENSITIVE);\n\n    private static final int HOURS_PER_DAY = 24;\n    private static final int MINUTES_PER_HOUR = 60;\n    private static final int SECONDS_PER_MINUTE = 60;\n    private static final int MILLIS_PER_SECOND = 1000;\n    private static final int MILLIS_PER_MINUTE = MILLIS_PER_SECOND * SECONDS_PER_MINUTE;\n    private static final int MILLIS_PER_HOUR = MILLIS_PER_MINUTE * MINUTES_PER_HOUR;\n    private static final int MILLIS_PER_DAY = MILLIS_PER_HOUR * HOURS_PER_DAY;\n\n    public long parseToMillis(String text) throws ParserException {\n      Matcher matcher = PATTERN.matcher(text);\n      if (matcher.matches()) {\n        String dayMatch = matcher.group(1);\n        String hourMatch = matcher.group(2);\n        String minuteMatch = matcher.group(3);\n        String secondMatch = matcher.group(4);\n        String fractionMatch = matcher.group(5);\n        if (dayMatch != null || hourMatch != null || minuteMatch != null || secondMatch != null || fractionMatch != null) {\n          int daysAsMilliSecs = parseNumber(dayMatch, MILLIS_PER_DAY);\n          int hoursAsMilliSecs = parseNumber(hourMatch, MILLIS_PER_HOUR);\n          int minutesAsMilliSecs = parseNumber(minuteMatch, MILLIS_PER_MINUTE);\n          int secondsAsMilliSecs = parseNumber(secondMatch, MILLIS_PER_SECOND);\n          int milliseconds = parseNumber(fractionMatch, 1);\n\n          return daysAsMilliSecs + hoursAsMilliSecs + minutesAsMilliSecs + secondsAsMilliSecs + milliseconds;\n        }\n      }\n      throw new ParserException(String.format(\"Text %s cannot be parsed to duration)\", text));\n    }\n\n\n    private static int parseNumber(String parsed, int multiplier) {\n      // regex limits to [0-9]+\n      if (parsed == null || parsed.trim().isEmpty()) {\n        return 0;\n      }\n      return Integer.parseInt(parsed) * multiplier;\n    }\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/resources/META-INF/apollo-1.0.0.xsd",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<xsd:schema xmlns=\"http://www.ctrip.com/schema/apollo\"\n            xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n            targetNamespace=\"http://www.ctrip.com/schema/apollo\"\n            elementFormDefault=\"qualified\"\n            attributeFormDefault=\"unqualified\">\n\n    <xsd:annotation>\n        <xsd:documentation><![CDATA[ Namespace support for Ctrip Apollo Configuration Center. ]]></xsd:documentation>\n    </xsd:annotation>\n\n    <xsd:element name=\"config\">\n        <xsd:annotation>\n            <xsd:documentation>\n                <![CDATA[ Apollo configuration section to integrate with Spring.]]>\n            </xsd:documentation>\n        </xsd:annotation>\n        <xsd:complexType>\n            <xsd:attribute name=\"namespaces\" type=\"xsd:string\" use=\"optional\">\n                <xsd:annotation>\n                    <xsd:documentation>\n                        <![CDATA[\n                            The comma-separated list of namespace names to integrate with Spring property sources.\n                            If not specified, then default to application namespace.\n                        ]]>\n                    </xsd:documentation>\n                </xsd:annotation>\n            </xsd:attribute>\n            <xsd:attribute name=\"order\" type=\"xsd:int\" use=\"optional\">\n                <xsd:annotation>\n                    <xsd:documentation>\n                        <![CDATA[\n                            The order of the config, default to Ordered.LOWEST_PRECEDENCE, which is Integer.MAX_VALUE.\n                            If there are properties with the same name in different apollo configs, the config with smaller order wins.\n                        ]]>\n                    </xsd:documentation>\n                </xsd:annotation>\n            </xsd:attribute>\n        </xsd:complexType>\n    </xsd:element>\n</xsd:schema>"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/resources/META-INF/services/com.ctrip.framework.apollo.internals.Injector",
    "content": "com.ctrip.framework.apollo.internals.DefaultInjector"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/resources/META-INF/spring.factories",
    "content": "org.springframework.boot.autoconfigure.EnableAutoConfiguration=\\\ncom.ctrip.framework.apollo.spring.boot.ApolloAutoConfiguration\norg.springframework.context.ApplicationContextInitializer=\\\ncom.ctrip.framework.apollo.spring.boot.ApolloApplicationContextInitializer\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/resources/META-INF/spring.handlers",
    "content": "http\\://www.ctrip.com/schema/apollo=com.ctrip.framework.apollo.spring.config.NamespaceHandler"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/main/resources/META-INF/spring.schemas",
    "content": "http\\://www.ctrip.com/schema/apollo-1.0.0.xsd=/META-INF/apollo-1.0.0.xsd\nhttp\\://www.ctrip.com/schema/apollo.xsd=/META-INF/apollo-1.0.0.xsd\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/test/resources/META-INF/services/com.ctrip.framework.apollo.internals.Injector",
    "content": "com.ctrip.framework.apollo.build.MockInjector"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/test/resources/log4j2.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<configuration monitorInterval=\"60\">\n    <appenders>\n        <Console name=\"Console\" target=\"SYSTEM_OUT\">\n            <PatternLayout pattern=\"[apollo-client][%t]%d %-5p [%c] %m%n\"/>\n        </Console>\n        <Async name=\"Async\" includeLocation=\"true\">\n            <AppenderRef ref=\"Console\"/>\n        </Async>\n    </appenders>\n    <loggers>\n        <logger name=\"com.ctrip.framework.apollo\" additivity=\"false\" level=\"trace\">\n            <AppenderRef ref=\"Async\" level=\"DEBUG\"/>\n        </logger>\n        <root level=\"INFO\">\n            <AppenderRef ref=\"Async\"/>\n        </root>\n    </loggers>\n</configuration>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/test/resources/spring/XmlConfigAnnotationTest1.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:apollo=\"http://www.ctrip.com/schema/apollo\"\n       xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd\n       http://www.ctrip.com/schema/apollo http://www.ctrip.com/schema/apollo.xsd\">\n    <apollo:config/>\n\n    <bean class=\"com.ctrip.framework.apollo.spring.XMLConfigAnnotationTest.TestApolloConfigBean1\"/>\n</beans>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/test/resources/spring/XmlConfigAnnotationTest2.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:apollo=\"http://www.ctrip.com/schema/apollo\"\n       xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd\n       http://www.ctrip.com/schema/apollo http://www.ctrip.com/schema/apollo.xsd\">\n    <apollo:config/>\n\n    <bean class=\"com.ctrip.framework.apollo.spring.XMLConfigAnnotationTest.TestApolloConfigBean2\"/>\n</beans>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/test/resources/spring/XmlConfigAnnotationTest3.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:apollo=\"http://www.ctrip.com/schema/apollo\"\n       xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd\n       http://www.ctrip.com/schema/apollo http://www.ctrip.com/schema/apollo.xsd\">\n    <apollo:config/>\n\n    <bean class=\"com.ctrip.framework.apollo.spring.XMLConfigAnnotationTest.TestApolloConfigChangeListenerBean1\"/>\n</beans>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/test/resources/spring/XmlConfigAnnotationTest4.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:apollo=\"http://www.ctrip.com/schema/apollo\"\n       xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd\n       http://www.ctrip.com/schema/apollo http://www.ctrip.com/schema/apollo.xsd\">\n    <apollo:config/>\n\n    <bean class=\"com.ctrip.framework.apollo.spring.XMLConfigAnnotationTest.TestApolloConfigChangeListenerBean2\"/>\n</beans>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/test/resources/spring/XmlConfigAnnotationTest5.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:apollo=\"http://www.ctrip.com/schema/apollo\"\n       xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd\n       http://www.ctrip.com/schema/apollo http://www.ctrip.com/schema/apollo.xsd\">\n    <apollo:config/>\n\n    <bean class=\"com.ctrip.framework.apollo.spring.XMLConfigAnnotationTest.TestApolloConfigChangeListenerBean3\"/>\n</beans>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/test/resources/spring/XmlConfigPlaceholderTest1.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:apollo=\"http://www.ctrip.com/schema/apollo\"\n       xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd\n       http://www.ctrip.com/schema/apollo http://www.ctrip.com/schema/apollo.xsd\">\n    <apollo:config />\n\n    <bean class=\"com.ctrip.framework.apollo.spring.XmlConfigPlaceholderTest.TestXmlBean\">\n        <property name=\"timeout\" value=\"${timeout:100}\"/>\n        <property name=\"batch\" value=\"${batch:200}\"/>\n    </bean>\n</beans>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/test/resources/spring/XmlConfigPlaceholderTest10.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:apollo=\"http://www.ctrip.com/schema/apollo\"\n       xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd\n       http://www.ctrip.com/schema/apollo http://www.ctrip.com/schema/apollo.xsd\">\n    <apollo:config />\n\n    <bean class=\"com.ctrip.framework.apollo.spring.XmlConfigPlaceholderAutoUpdateTest.TestAllKindsOfDataTypesBean\">\n        <property name=\"intProperty\" value=\"${intProperty}\"/>\n        <property name=\"intArrayProperty\" value=\"${intArrayProperty}\"/>\n        <property name=\"longProperty\" value=\"${longProperty}\"/>\n        <property name=\"shortProperty\" value=\"${shortProperty}\"/>\n        <property name=\"floatProperty\" value=\"${floatProperty}\"/>\n        <property name=\"doubleProperty\" value=\"${doubleProperty}\"/>\n        <property name=\"byteProperty\" value=\"${byteProperty}\"/>\n        <property name=\"booleanProperty\" value=\"${booleanProperty}\"/>\n        <property name=\"stringProperty\" value=\"${stringProperty}\"/>\n        <property name=\"dateProperty\" value=\"#{new java.text.SimpleDateFormat('${dateFormat}').parse('${dateProperty}')}\"/>\n    </bean>\n</beans>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/test/resources/spring/XmlConfigPlaceholderTest2.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:apollo=\"http://www.ctrip.com/schema/apollo\"\n       xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd\n       http://www.ctrip.com/schema/apollo http://www.ctrip.com/schema/apollo.xsd\">\n    <apollo:config namespaces=\"application\"/>\n\n    <bean class=\"com.ctrip.framework.apollo.spring.XmlConfigPlaceholderTest.TestXmlBean\">\n        <property name=\"timeout\" value=\"${timeout:100}\"/>\n        <property name=\"batch\" value=\"${batch:200}\"/>\n    </bean>\n</beans>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/test/resources/spring/XmlConfigPlaceholderTest3.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:apollo=\"http://www.ctrip.com/schema/apollo\"\n       xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd\n       http://www.ctrip.com/schema/apollo http://www.ctrip.com/schema/apollo.xsd\">\n    <apollo:config namespaces=\"application,FX.apollo\"/>\n\n    <bean class=\"com.ctrip.framework.apollo.spring.XmlConfigPlaceholderTest.TestXmlBean\">\n        <property name=\"timeout\" value=\"${timeout:100}\"/>\n        <property name=\"batch\" value=\"${batch:200}\"/>\n    </bean>\n</beans>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/test/resources/spring/XmlConfigPlaceholderTest4.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:apollo=\"http://www.ctrip.com/schema/apollo\"\n       xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd\n       http://www.ctrip.com/schema/apollo http://www.ctrip.com/schema/apollo.xsd\">\n    <apollo:config namespaces=\"application\"/>\n    <apollo:config namespaces=\"FX.apollo\" order=\"10\"/>\n\n    <bean class=\"com.ctrip.framework.apollo.spring.XmlConfigPlaceholderTest.TestXmlBean\">\n        <property name=\"timeout\" value=\"${timeout:100}\"/>\n        <property name=\"batch\" value=\"${batch:200}\"/>\n    </bean>\n</beans>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/test/resources/spring/XmlConfigPlaceholderTest5.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:apollo=\"http://www.ctrip.com/schema/apollo\"\n       xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd\n       http://www.ctrip.com/schema/apollo http://www.ctrip.com/schema/apollo.xsd\">\n    <apollo:config namespaces=\"application\" order=\"abc\"/>\n\n    <bean class=\"com.ctrip.framework.apollo.spring.XmlConfigPlaceholderTest.TestXmlBean\">\n        <property name=\"timeout\" value=\"${timeout:100}\"/>\n        <property name=\"batch\" value=\"${batch:200}\"/>\n    </bean>\n</beans>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/test/resources/spring/XmlConfigPlaceholderTest6.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:apollo=\"http://www.ctrip.com/schema/apollo\"\n       xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd\n       http://www.ctrip.com/schema/apollo http://www.ctrip.com/schema/apollo.xsd\">\n    <apollo:config namespaces=\"FX.apollo,application\"/>\n\n    <bean class=\"com.ctrip.framework.apollo.spring.XmlConfigPlaceholderTest.TestXmlBean\">\n        <property name=\"timeout\" value=\"${timeout:100}\"/>\n        <property name=\"batch\" value=\"${batch:200}\"/>\n    </bean>\n</beans>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/test/resources/spring/XmlConfigPlaceholderTest7.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:apollo=\"http://www.ctrip.com/schema/apollo\"\n       xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd\n       http://www.ctrip.com/schema/apollo http://www.ctrip.com/schema/apollo.xsd\">\n    <apollo:config />\n\n    <bean class=\"com.ctrip.framework.apollo.spring.XmlConfigPlaceholderTest.TestXmlBean\">\n        <property name=\"timeout\" value=\"${timeout}\"/>\n        <property name=\"batch\" value=\"${batch}\"/>\n    </bean>\n</beans>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/test/resources/spring/XmlConfigPlaceholderTest8.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:apollo=\"http://www.ctrip.com/schema/apollo\"\n       xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd\n       http://www.ctrip.com/schema/apollo http://www.ctrip.com/schema/apollo.xsd\">\n    <apollo:config />\n\n    <bean class=\"com.ctrip.framework.apollo.spring.XmlConfigPlaceholderAutoUpdateTest.TestXmlBeanWithConstructorArgs\">\n        <constructor-arg index=\"0\" value=\"${timeout}\"/>\n        <constructor-arg index=\"1\" value=\"${batch}\"/>\n    </bean>\n</beans>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-client/src/test/resources/spring/XmlConfigPlaceholderTest9.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  xmlns:apollo=\"http://www.ctrip.com/schema/apollo\"\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.ctrip.com/schema/apollo http://www.ctrip.com/schema/apollo.xsd\">\n  <context:annotation-config />\n\n  <apollo:config/>\n\n  <bean class=\"com.ctrip.framework.apollo.spring.XmlConfigPlaceholderAutoUpdateTest.TestXmlBeanWithInjectedValue\">\n    <property name=\"batch\" value=\"${batch}\"/>\n  </bean>\n</beans>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/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/maven-v4_0_0.xsd\">\n    <parent>\n        <groupId>com.ctrip.framework.apollo</groupId>\n        <artifactId>apollo</artifactId>\n        <version>0.10.0-SNAPSHOT</version>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n    <artifactId>apollo-common</artifactId>\n    <name>Apollo Common</name>\n    <properties>\n        <github.path>${project.artifactId}</github.path>\n    </properties>\n    <dependencies>\n        <dependency>\n            <groupId>com.ctrip.framework.apollo</groupId>\n            <artifactId>apollo-core</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-actuator</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-security</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-starter-spectator</artifactId>\n            <!-- duplicated with spring-security-core -->\n            <exclusions>\n                <exclusion>\n                    <groupId>org.springframework.security</groupId>\n                    <artifactId>spring-security-crypto</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n        \n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-data-jpa</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.data</groupId>\n            <artifactId>spring-data-commons</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.apache.httpcomponents</groupId>\n            <artifactId>httpclient</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>commons-logging</groupId>\n                    <artifactId>commons-logging</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n        <dependency>\n            <groupId>ch.qos.logback</groupId>\n            <artifactId>logback-classic</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>commons-lang</groupId>\n            <artifactId>commons-lang</artifactId>\n        </dependency>\n    </dependencies>\n</project>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/ApolloCommonConfig.java",
    "content": "package com.ctrip.framework.apollo.common;\n\nimport org.springframework.boot.autoconfigure.EnableAutoConfiguration;\nimport org.springframework.context.annotation.ComponentScan;\nimport org.springframework.context.annotation.Configuration;\n\n@EnableAutoConfiguration\n@Configuration\n@ComponentScan(basePackageClasses = ApolloCommonConfig.class)\npublic class ApolloCommonConfig {\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/aop/RepositoryAspect.java",
    "content": "package com.ctrip.framework.apollo.common.aop;\n\nimport com.ctrip.framework.apollo.tracer.Tracer;\nimport com.ctrip.framework.apollo.tracer.spi.Transaction;\n\nimport org.aspectj.lang.ProceedingJoinPoint;\nimport org.aspectj.lang.annotation.Around;\nimport org.aspectj.lang.annotation.Aspect;\nimport org.aspectj.lang.annotation.Pointcut;\nimport org.springframework.stereotype.Component;\n\n@Aspect\n@Component\npublic class RepositoryAspect {\n\n  @Pointcut(\"execution(public * org.springframework.data.repository.Repository+.*(..))\")\n  public void anyRepositoryMethod() {\n  }\n\n  @Around(\"anyRepositoryMethod()\")\n  public Object invokeWithCatTransaction(ProceedingJoinPoint joinPoint) throws Throwable {\n    String name =\n        joinPoint.getSignature().getDeclaringType().getSimpleName() + \".\" + joinPoint.getSignature()\n            .getName();\n    Transaction catTransaction = Tracer.newTransaction(\"SQL\", name);\n    try {\n      Object result = joinPoint.proceed();\n      catTransaction.setStatus(Transaction.SUCCESS);\n      return result;\n    } catch (Throwable ex) {\n      catTransaction.setStatus(ex);\n      throw ex;\n    } finally {\n      catTransaction.complete();\n    }\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/condition/ConditionalOnMissingProfile.java",
    "content": "package com.ctrip.framework.apollo.common.condition;\n\nimport org.springframework.context.annotation.Conditional;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * {@link Conditional} that only matches when the specified profiles are inactive.\n *\n * @author Jason Song(song_s@ctrip.com)\n */\n@Target({ ElementType.TYPE, ElementType.METHOD })\n@Retention(RetentionPolicy.RUNTIME)\n@Documented\n@Conditional(OnProfileCondition.class)\npublic @interface ConditionalOnMissingProfile {\n  /**\n   * The profiles that should be inactive\n   * @return\n   */\n  String[] value() default {};\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/condition/ConditionalOnProfile.java",
    "content": "package com.ctrip.framework.apollo.common.condition;\n\nimport org.springframework.context.annotation.Conditional;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * {@link Conditional} that only matches when the specified profiles are active.\n *\n * @author Jason Song(song_s@ctrip.com)\n */\n@Target({ ElementType.TYPE, ElementType.METHOD })\n@Retention(RetentionPolicy.RUNTIME)\n@Documented\n@Conditional(OnProfileCondition.class)\npublic @interface ConditionalOnProfile {\n\n  /**\n   * The profiles that should be active\n   * @return\n   */\n  String[] value() default {};\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/condition/OnProfileCondition.java",
    "content": "package com.ctrip.framework.apollo.common.condition;\n\nimport com.google.common.collect.Sets;\n\nimport org.springframework.context.annotation.Condition;\nimport org.springframework.context.annotation.ConditionContext;\nimport org.springframework.core.type.AnnotatedTypeMetadata;\nimport org.springframework.util.MultiValueMap;\n\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Set;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class OnProfileCondition implements Condition {\n  @Override\n  public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {\n    Set<String> activeProfiles = Sets.newHashSet(context.getEnvironment().getActiveProfiles());\n\n    Set<String> requiredActiveProfiles = retrieveAnnotatedProfiles(metadata, ConditionalOnProfile.class.getName());\n    Set<String> requiredInactiveProfiles = retrieveAnnotatedProfiles(metadata, ConditionalOnMissingProfile.class\n        .getName());\n\n    return Sets.difference(requiredActiveProfiles, activeProfiles).isEmpty()\n        && Sets.intersection(requiredInactiveProfiles, activeProfiles).isEmpty();\n  }\n\n  private Set<String> retrieveAnnotatedProfiles(AnnotatedTypeMetadata metadata, String annotationType) {\n    if (!metadata.isAnnotated(annotationType)) {\n      return Collections.emptySet();\n    }\n\n    MultiValueMap<String, Object> attributes = metadata.getAllAnnotationAttributes(annotationType);\n\n    if (attributes == null) {\n      return Collections.emptySet();\n    }\n\n    Set<String> profiles = Sets.newHashSet();\n    List<?> values = attributes.get(\"value\");\n\n    if (values != null) {\n      for (Object value : values) {\n        if (value instanceof String[]) {\n          Collections.addAll(profiles, (String[]) value);\n        }\n        else {\n          profiles.add((String) value);\n        }\n      }\n    }\n\n    return profiles;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/config/RefreshableConfig.java",
    "content": "package com.ctrip.framework.apollo.common.config;\n\nimport com.google.common.base.Splitter;\nimport com.google.common.base.Strings;\n\nimport com.ctrip.framework.apollo.core.utils.ApolloThreadFactory;\nimport com.ctrip.framework.apollo.tracer.Tracer;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.core.env.ConfigurableEnvironment;\nimport org.springframework.util.CollectionUtils;\n\nimport java.util.List;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.TimeUnit;\n\nimport javax.annotation.PostConstruct;\n\n\npublic abstract class RefreshableConfig {\n\n  private static final Logger logger = LoggerFactory.getLogger(RefreshableConfig.class);\n\n  private static final String LIST_SEPARATOR = \",\";\n  //TimeUnit: second\n  private static final int CONFIG_REFRESH_INTERVAL = 60;\n\n  protected Splitter splitter = Splitter.on(LIST_SEPARATOR).omitEmptyStrings().trimResults();\n\n  @Autowired\n  private ConfigurableEnvironment environment;\n\n  private List<RefreshablePropertySource> propertySources;\n\n  /**\n   * register refreshable property source.\n   * Notice: The front property source has higher priority.\n   */\n  protected abstract List<RefreshablePropertySource> getRefreshablePropertySources();\n\n  @PostConstruct\n  public void setup() {\n\n    propertySources = getRefreshablePropertySources();\n    if (CollectionUtils.isEmpty(propertySources)) {\n      throw new IllegalStateException(\"Property sources can not be empty.\");\n    }\n\n    //add property source to environment\n    for (RefreshablePropertySource propertySource : propertySources) {\n      propertySource.refresh();\n      environment.getPropertySources().addLast(propertySource);\n    }\n\n    //task to update configs\n    ScheduledExecutorService\n        executorService =\n        Executors.newScheduledThreadPool(1, ApolloThreadFactory.create(\"ConfigRefresher\", true));\n\n    executorService\n        .scheduleWithFixedDelay(() -> {\n          try {\n            propertySources.forEach(RefreshablePropertySource::refresh);\n          } catch (Throwable t) {\n            logger.error(\"Refresh configs failed.\", t);\n            Tracer.logError(\"Refresh configs failed.\", t);\n          }\n        }, CONFIG_REFRESH_INTERVAL, CONFIG_REFRESH_INTERVAL, TimeUnit.SECONDS);\n  }\n\n  public int getIntProperty(String key, int defaultValue) {\n    try {\n      String value = getValue(key);\n      return value == null ? defaultValue : Integer.parseInt(value);\n    } catch (Throwable e) {\n      Tracer.logError(\"Get int property failed.\", e);\n      return defaultValue;\n    }\n  }\n\n  public boolean getBooleanProperty(String key, boolean defaultValue) {\n    try {\n      String value = getValue(key);\n      return value == null ? defaultValue : \"true\".equals(value);\n    } catch (Throwable e) {\n      Tracer.logError(\"Get boolean property failed.\", e);\n      return defaultValue;\n    }\n  }\n\n  public String[] getArrayProperty(String key, String[] defaultValue) {\n    try {\n      String value = getValue(key);\n      return Strings.isNullOrEmpty(value) ? defaultValue : value.split(LIST_SEPARATOR);\n    } catch (Throwable e) {\n      Tracer.logError(\"Get array property failed.\", e);\n      return defaultValue;\n    }\n  }\n\n  public String getValue(String key, String defaultValue) {\n    try {\n      return environment.getProperty(key, defaultValue);\n    } catch (Throwable e) {\n      Tracer.logError(\"Get value failed.\", e);\n      return defaultValue;\n    }\n  }\n\n  public String getValue(String key) {\n    return environment.getProperty(key);\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/config/RefreshablePropertySource.java",
    "content": "package com.ctrip.framework.apollo.common.config;\n\nimport org.springframework.core.env.MapPropertySource;\n\nimport java.util.Map;\n\npublic abstract class RefreshablePropertySource extends MapPropertySource {\n\n\n  public RefreshablePropertySource(String name, Map<String, Object> source) {\n    super(name, source);\n  }\n\n  @Override\n  public Object getProperty(String name) {\n    return this.source.get(name);\n  }\n\n  /**\n   * refresh property\n   */\n  protected abstract void refresh();\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/constants/GsonType.java",
    "content": "package com.ctrip.framework.apollo.common.constants;\n\nimport com.google.gson.reflect.TypeToken;\n\nimport com.ctrip.framework.apollo.common.dto.GrayReleaseRuleItemDTO;\n\nimport java.lang.reflect.Type;\nimport java.util.List;\nimport java.util.Map;\n\npublic interface GsonType {\n\n  Type CONFIG = new TypeToken<Map<String, String>>() {}.getType();\n\n  Type RULE_ITEMS = new TypeToken<List<GrayReleaseRuleItemDTO>>() {}.getType();\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/constants/NamespaceBranchStatus.java",
    "content": "package com.ctrip.framework.apollo.common.constants;\n\npublic interface NamespaceBranchStatus {\n\n  int DELETED = 0;\n\n  int ACTIVE = 1;\n\n  int MERGED = 2;\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/constants/ReleaseOperation.java",
    "content": "package com.ctrip.framework.apollo.common.constants;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic interface ReleaseOperation {\n  int NORMAL_RELEASE = 0;\n  int ROLLBACK = 1;\n  int GRAY_RELEASE = 2;\n  int APPLY_GRAY_RULES = 3;\n  int GRAY_RELEASE_MERGE_TO_MASTER = 4;\n  int MASTER_NORMAL_RELEASE_MERGE_TO_GRAY = 5;\n  int MATER_ROLLBACK_MERGE_TO_GRAY = 6;\n  int ABANDON_GRAY_RELEASE = 7;\n  int GRAY_RELEASE_DELETED_AFTER_MERGE = 8;\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/constants/ReleaseOperationContext.java",
    "content": "package com.ctrip.framework.apollo.common.constants;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic interface ReleaseOperationContext {\n  String SOURCE_BRANCH = \"sourceBranch\";\n  String RULES = \"rules\";\n  String OLD_RULES = \"oldRules\";\n  String BASE_RELEASE_ID = \"baseReleaseId\";\n  String IS_EMERGENCY_PUBLISH = \"isEmergencyPublish\";\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/controller/ApolloInfoController.java",
    "content": "package com.ctrip.framework.apollo.common.controller;\n\nimport com.ctrip.framework.apollo.Apollo;\nimport com.ctrip.framework.foundation.Foundation;\n\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n@RestController\n@RequestMapping(path = \"/apollo\")\npublic class ApolloInfoController {\n\n  @RequestMapping(\"app\")\n  public String getApp() {\n    return Foundation.app().toString();\n  }\n\n  @RequestMapping(\"net\")\n  public String getNet() {\n    return Foundation.net().toString();\n  }\n\n  @RequestMapping(\"server\")\n  public String getServer() {\n    return Foundation.server().toString();\n  }\n\n  @RequestMapping(\"version\")\n  public String getVersion() {\n    return Apollo.VERSION;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/controller/CharacterEncodingFilterConfiguration.java",
    "content": "package com.ctrip.framework.apollo.common.controller;\n\nimport org.springframework.boot.context.embedded.FilterRegistrationBean;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.web.filter.CharacterEncodingFilter;\n\nimport javax.servlet.DispatcherType;\n\n@Configuration\npublic class CharacterEncodingFilterConfiguration {\n\n  @Bean\n  public FilterRegistrationBean encodingFilter() {\n    FilterRegistrationBean bean = new FilterRegistrationBean();\n    bean.setFilter(new CharacterEncodingFilter());\n    bean.addInitParameter(\"encoding\", \"UTF-8\");\n    //FIXME: https://github.com/Netflix/eureka/issues/702\n//    bean.addInitParameter(\"forceEncoding\", \"true\");\n    bean.setName(\"encodingFilter\");\n    bean.addUrlPatterns(\"/*\");\n    bean.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.FORWARD);\n    return bean;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/controller/GlobalDefaultExceptionHandler.java",
    "content": "package com.ctrip.framework.apollo.common.controller;\n\nimport com.google.gson.Gson;\nimport com.google.gson.reflect.TypeToken;\n\nimport com.ctrip.framework.apollo.common.exception.AbstractApolloHttpException;\nimport com.ctrip.framework.apollo.tracer.Tracer;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.http.HttpHeaders;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.security.access.AccessDeniedException;\nimport org.springframework.web.HttpMediaTypeException;\nimport org.springframework.web.HttpRequestMethodNotSupportedException;\nimport org.springframework.web.bind.annotation.ControllerAdvice;\nimport org.springframework.web.bind.annotation.ExceptionHandler;\nimport org.springframework.web.client.HttpStatusCodeException;\n\nimport java.lang.reflect.Type;\nimport java.time.LocalDateTime;\nimport java.time.format.DateTimeFormatter;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport javax.servlet.ServletException;\nimport javax.servlet.http.HttpServletRequest;\n\nimport static org.springframework.http.HttpStatus.BAD_REQUEST;\nimport static org.springframework.http.HttpStatus.FORBIDDEN;\nimport static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;\nimport static org.springframework.http.MediaType.APPLICATION_JSON;\n\n@ControllerAdvice\npublic class GlobalDefaultExceptionHandler {\n  private Gson gson = new Gson();\n  private static Type mapType = new TypeToken<Map<String, Object>>() {\n  }.getType();\n\n  private static final Logger logger = LoggerFactory.getLogger(GlobalDefaultExceptionHandler.class);\n\n  //处理系统内置的Exception\n  @ExceptionHandler(Throwable.class)\n  public ResponseEntity<Map<String, Object>> exception(HttpServletRequest request, Throwable ex) {\n    return handleError(request, INTERNAL_SERVER_ERROR, ex);\n  }\n\n  @ExceptionHandler({HttpRequestMethodNotSupportedException.class, HttpMediaTypeException.class})\n  public ResponseEntity<Map<String, Object>> badRequest(HttpServletRequest request,\n                                                        ServletException ex) {\n    return handleError(request, BAD_REQUEST, ex);\n  }\n\n  @ExceptionHandler(HttpStatusCodeException.class)\n  public ResponseEntity<Map<String, Object>> restTemplateException(HttpServletRequest request,\n                                                                   HttpStatusCodeException ex) {\n    return handleError(request, ex.getStatusCode(), ex);\n  }\n\n  @ExceptionHandler(AccessDeniedException.class)\n  public ResponseEntity<Map<String, Object>> accessDeny(HttpServletRequest request,\n                                                        AccessDeniedException ex) {\n    return handleError(request, FORBIDDEN, ex);\n  }\n\n  //处理自定义Exception\n  @ExceptionHandler({AbstractApolloHttpException.class})\n  public ResponseEntity<Map<String, Object>> badRequest(HttpServletRequest request, AbstractApolloHttpException ex) {\n    return handleError(request, ex);\n  }\n\n\n  private ResponseEntity<Map<String, Object>> handleError(HttpServletRequest request,\n                                                          AbstractApolloHttpException ex) {\n    return handleError(request, ex.getHttpStatus(), ex);\n  }\n\n\n  private ResponseEntity<Map<String, Object>> handleError(HttpServletRequest request,\n                                                          HttpStatus status, Throwable ex) {\n    String message = ex.getMessage();\n\n    logger.error(message, ex);\n    Tracer.logError(ex);\n\n\n    Map<String, Object> errorAttributes = new HashMap<>();\n    boolean errorHandled = false;\n\n    if (ex instanceof HttpStatusCodeException) {\n      try {\n        //try to extract the original error info if it is thrown from apollo programs, e.g. admin service\n        errorAttributes = gson.fromJson(((HttpStatusCodeException) ex).getResponseBodyAsString(), mapType);\n        status = ((HttpStatusCodeException) ex).getStatusCode();\n        errorHandled = true;\n      } catch (Throwable th) {\n        //ignore\n      }\n    }\n\n    if (!errorHandled) {\n      errorAttributes.put(\"status\", status.value());\n      errorAttributes.put(\"message\", message);\n      errorAttributes.put(\"timestamp\",\n          LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));\n      errorAttributes.put(\"exception\", ex.getClass().getName());\n\n    }\n\n    HttpHeaders headers = new HttpHeaders();\n    headers.setContentType(APPLICATION_JSON);\n    return new ResponseEntity<>(errorAttributes, headers, status);\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/controller/HttpMessageConverterConfiguration.java",
    "content": "package com.ctrip.framework.apollo.common.controller;\n\nimport com.google.common.collect.Lists;\nimport com.google.gson.GsonBuilder;\n\nimport org.springframework.boot.autoconfigure.web.HttpMessageConverters;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.http.converter.ByteArrayHttpMessageConverter;\nimport org.springframework.http.converter.HttpMessageConverter;\nimport org.springframework.http.converter.StringHttpMessageConverter;\nimport org.springframework.http.converter.json.GsonHttpMessageConverter;\nimport org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter;\n\nimport java.util.List;\n\n/**\n * Created by Jason on 5/11/16.\n */\n@Configuration\npublic class HttpMessageConverterConfiguration {\n  @Bean\n  public HttpMessageConverters messageConverters() {\n    GsonHttpMessageConverter gsonHttpMessageConverter = new GsonHttpMessageConverter();\n    gsonHttpMessageConverter.setGson(\n            new GsonBuilder().setDateFormat(\"yyyy-MM-dd'T'HH:mm:ss.SSSZ\").create());\n    final List<HttpMessageConverter<?>> converters = Lists.newArrayList(\n            new ByteArrayHttpMessageConverter(), new StringHttpMessageConverter(),\n            new AllEncompassingFormHttpMessageConverter(), gsonHttpMessageConverter);\n    return new HttpMessageConverters() {\n      @Override\n      public List<HttpMessageConverter<?>> getConverters() {\n        return converters;\n      }\n    };\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/controller/WebMvcConfig.java",
    "content": "package com.ctrip.framework.apollo.common.controller;\n\nimport org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;\nimport org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;\nimport org.springframework.boot.context.embedded.MimeMappings;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.data.domain.PageRequest;\nimport org.springframework.data.web.PageableHandlerMethodArgumentResolver;\nimport org.springframework.http.MediaType;\nimport org.springframework.web.method.support.HandlerMethodArgumentResolver;\nimport org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;\nimport org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;\n\nimport java.util.List;\n\n@Configuration\npublic class WebMvcConfig extends WebMvcConfigurerAdapter implements EmbeddedServletContainerCustomizer {\n\n  @Override\n  public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {\n    PageableHandlerMethodArgumentResolver pageResolver =\n            new PageableHandlerMethodArgumentResolver();\n    pageResolver.setFallbackPageable(new PageRequest(0, 10));\n\n    argumentResolvers.add(pageResolver);\n  }\n\n  @Override\n  public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {\n    configurer.favorPathExtension(false);\n    configurer.ignoreAcceptHeader(true).defaultContentType(MediaType.APPLICATION_JSON);\n  }\n\n  @Override\n  public void customize(ConfigurableEmbeddedServletContainer container) {\n    MimeMappings mappings = new MimeMappings(MimeMappings.DEFAULT);\n    mappings.add(\"html\", \"text/html;charset=utf-8\");\n    container.setMimeMappings(mappings );\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/customize/LoggingCustomizer.java",
    "content": "package com.ctrip.framework.apollo.common.customize;\n\nimport com.google.common.base.Strings;\n\nimport com.ctrip.framework.apollo.tracer.Tracer;\nimport com.ctrip.framework.foundation.Foundation;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.InitializingBean;\nimport org.springframework.util.ClassUtils;\nimport org.springframework.util.ReflectionUtils;\n\nimport ch.qos.logback.classic.LoggerContext;\nimport ch.qos.logback.core.Appender;\n\n/**\n * clogging config.only used in ctrip\n * @author Jason Song(song_s@ctrip.com)\n */\npublic abstract class LoggingCustomizer implements InitializingBean {\n  private static final Logger logger = LoggerFactory.getLogger(LoggingCustomizer.class);\n  private static final String cLoggingAppenderClass =\n      \"com.ctrip.framework.clogging.agent.appender.CLoggingAppender\";\n  private static boolean cLoggingAppenderPresent =\n      ClassUtils.isPresent(cLoggingAppenderClass, LoggingCustomizer.class.getClassLoader());\n\n  @Override\n  public void afterPropertiesSet() {\n    if (!cLoggingAppenderPresent) {\n      return;\n    }\n\n    try {\n      tryConfigCLogging();\n    } catch (Throwable ex) {\n      logger.error(\"Config CLogging failed\", ex);\n      Tracer.logError(ex);\n    }\n\n  }\n\n  private void tryConfigCLogging() throws Exception {\n    String appId = Foundation.app().getAppId();\n    if (Strings.isNullOrEmpty(appId)) {\n      logger.warn(\"App id is null or empty!\");\n      return;\n    }\n\n\n    LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();\n    Class clazz = Class.forName(cLoggingAppenderClass);\n    Appender cLoggingAppender = (Appender) clazz.newInstance();\n\n    ReflectionUtils.findMethod(clazz, \"setAppId\", String.class).invoke(cLoggingAppender, appId);\n    ReflectionUtils.findMethod(clazz, \"setServerIp\", String.class)\n        .invoke(cLoggingAppender, cloggingUrl());\n    ReflectionUtils.findMethod(clazz, \"setServerPort\", int.class)\n        .invoke(cLoggingAppender, Integer.parseInt(cloggingPort()));\n\n    cLoggingAppender.setName(\"CentralLogging\");\n    cLoggingAppender.setContext(loggerContext);\n    cLoggingAppender.start();\n\n    ch.qos.logback.classic.Logger logger =\n        (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(\"root\");\n    logger.addAppender(cLoggingAppender);\n\n  }\n\n  /**\n   * clogging server url\n   * @return\n   */\n  protected abstract String cloggingUrl();\n\n  /**\n   * clogging server port\n   * @return\n   */\n  protected abstract String cloggingPort();\n\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/customize/TomcatContainerCustomizer.java",
    "content": "package com.ctrip.framework.apollo.common.customize;\n\nimport org.apache.catalina.connector.Connector;\nimport org.apache.coyote.ProtocolHandler;\nimport org.apache.coyote.http11.Http11NioProtocol;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;\nimport org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;\nimport org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer;\nimport org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;\nimport org.springframework.core.env.Environment;\nimport org.springframework.stereotype.Component;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@Component\npublic class TomcatContainerCustomizer implements EmbeddedServletContainerCustomizer {\n  private static final Logger logger = LoggerFactory.getLogger(TomcatContainerCustomizer.class);\n  private static final String TOMCAT_ACCEPTOR_COUNT = \"server.tomcat.accept-count\";\n  @Autowired\n  private Environment environment;\n\n  @Override\n  public void customize(ConfigurableEmbeddedServletContainer container) {\n    if (!(container instanceof TomcatEmbeddedServletContainerFactory)) {\n      return;\n    }\n    if (!environment.containsProperty(TOMCAT_ACCEPTOR_COUNT)) {\n      return;\n    }\n    TomcatEmbeddedServletContainerFactory tomcat =\n        (TomcatEmbeddedServletContainerFactory) container;\n    tomcat.addConnectorCustomizers(new TomcatConnectorCustomizer() {\n      @Override\n      public void customize(Connector connector) {\n        ProtocolHandler handler = connector.getProtocolHandler();\n        if (handler instanceof Http11NioProtocol) {\n          Http11NioProtocol http = (Http11NioProtocol) handler;\n          int acceptCount = Integer.parseInt(environment.getProperty(TOMCAT_ACCEPTOR_COUNT));\n          http.setBacklog(acceptCount);\n          logger.info(\"Setting tomcat accept count to {}\", acceptCount);\n        }\n\n      }\n    });\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/customize/package-info.java",
    "content": "/**\n * 携程内部的日志系统,第三方公司可删除\n */\npackage com.ctrip.framework.apollo.common.customize;\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/datasource/TitanCondition.java",
    "content": "package com.ctrip.framework.apollo.common.datasource;\n\nimport com.ctrip.framework.apollo.core.utils.StringUtils;\n\nimport org.springframework.context.annotation.Condition;\nimport org.springframework.context.annotation.ConditionContext;\nimport org.springframework.core.type.AnnotatedTypeMetadata;\n\npublic class TitanCondition implements Condition {\n\n  @Override\n  public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {\n    if (!StringUtils.isEmpty(context.getEnvironment().getProperty(\"fat.titan.url\"))) {\n      return true;\n    } else if (!StringUtils.isEmpty(context.getEnvironment().getProperty(\"uat.titan.url\"))) {\n      return true;\n    } else if (!StringUtils.isEmpty(context.getEnvironment().getProperty(\"pro.titan.url\"))) {\n      return true;\n    }\n    return false;\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/datasource/TitanEntityManager.java",
    "content": "package com.ctrip.framework.apollo.common.datasource;\n\nimport com.ctrip.framework.apollo.tracer.Tracer;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Conditional;\nimport org.springframework.stereotype.Component;\n\nimport java.lang.reflect.Method;\n\nimport javax.sql.DataSource;\n\n@Component\n@Conditional(TitanCondition.class)\npublic class TitanEntityManager {\n\n  @Autowired\n  private TitanSettings settings;\n\n  @SuppressWarnings({\"rawtypes\", \"unchecked\"})\n  @Bean\n  public DataSource datasource() throws Exception {\n    Class clazz = Class.forName(\"com.ctrip.datasource.configure.DalDataSourceFactory\");\n    Object obj = clazz.newInstance();\n    Method method = clazz.getMethod(\"createDataSource\", new Class[] {String.class, String.class});\n    DataSource ds = ((DataSource) method.invoke(obj,\n        new Object[] {settings.getTitanDbname(), settings.getTitanUrl()}));\n    Tracer.logEvent(\"Apollo.Datasource.Titan\", settings.getTitanDbname());\n    return ds;\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/datasource/TitanSettings.java",
    "content": "package com.ctrip.framework.apollo.common.datasource;\n\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.core.enums.EnvUtils;\nimport com.ctrip.framework.foundation.Foundation;\n\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class TitanSettings {\n\n  @Value(\"${fat.titan.url:}\")\n  private String fatTitanUrl;\n\n  @Value(\"${uat.titan.url:}\")\n  private String uatTitanUrl;\n\n  @Value(\"${pro.titan.url:}\")\n  private String proTitanUrl;\n\n  @Value(\"${fat.titan.dbname:}\")\n  private String fatTitanDbname;\n\n  @Value(\"${uat.titan.dbname:}\")\n  private String uatTitanDbname;\n\n  @Value(\"${pro.titan.dbname:}\")\n  private String proTitanDbname;\n\n  public String getTitanUrl() {\n    Env env = EnvUtils.transformEnv(Foundation.server().getEnvType());\n    if (env == null) {\n      return \"\";\n    }\n    switch (env) {\n      case FAT:\n      case FWS:\n        return fatTitanUrl;\n      case UAT:\n        return uatTitanUrl;\n      case TOOLS:\n      case PRO:\n        return proTitanUrl;\n      default:\n        return \"\";\n    }\n  }\n\n  public String getTitanDbname() {\n    Env env = EnvUtils.transformEnv(Foundation.server().getEnvType());\n    if (env == null) {\n      return \"\";\n    }\n    switch (env) {\n      case FAT:\n      case FWS:\n        return fatTitanDbname;\n      case UAT:\n        return uatTitanDbname;\n      case TOOLS:\n      case PRO:\n        return proTitanDbname;\n      default:\n        return \"\";\n    }\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/datasource/package-info.java",
    "content": "/**\n * 携程内部的dal,第三方公司可替换实现\n */\npackage com.ctrip.framework.apollo.common.datasource;\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/dto/AppDTO.java",
    "content": "package com.ctrip.framework.apollo.common.dto;\n\npublic class AppDTO extends BaseDTO{\n\n  private long id;\n\n  private String name;\n\n  private String appId;\n\n  private String orgId;\n\n  private String orgName;\n\n  private String ownerName;\n\n  private String ownerEmail;\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 getAppId() {\n    return appId;\n  }\n\n  public String getName() {\n    return name;\n  }\n\n  public String getOrgId() {\n    return orgId;\n  }\n\n  public String getOrgName() {\n    return orgName;\n  }\n\n  public String getOwnerEmail() {\n    return ownerEmail;\n  }\n\n  public String getOwnerName() {\n    return ownerName;\n  }\n\n  public void setAppId(String appId) {\n    this.appId = appId;\n  }\n\n  public void setName(String name) {\n    this.name = name;\n  }\n\n  public void setOrgId(String orgId) {\n    this.orgId = orgId;\n  }\n\n  public void setOrgName(String orgName) {\n    this.orgName = orgName;\n  }\n\n  public void setOwnerEmail(String ownerEmail) {\n    this.ownerEmail = ownerEmail;\n  }\n\n  public void setOwnerName(String ownerName) {\n    this.ownerName = ownerName;\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/dto/AppNamespaceDTO.java",
    "content": "package com.ctrip.framework.apollo.common.dto;\n\n\npublic class AppNamespaceDTO extends BaseDTO{\n  private long id;\n\n  private String name;\n\n  private String appId;\n\n  private String comment;\n\n  private String format;\n\n  private boolean isPublic = false;\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 String getAppId() {\n    return appId;\n  }\n\n  public void setAppId(String appId) {\n    this.appId = appId;\n  }\n\n  public String getFormat() {\n    return format;\n  }\n\n  public void setFormat(String format) {\n    this.format = format;\n  }\n\n  public boolean isPublic() {\n    return isPublic;\n  }\n\n  public void setPublic(boolean aPublic) {\n    isPublic = aPublic;\n  }\n\n  public String getComment() {\n    return comment;\n  }\n\n  public void setComment(String comment) {\n    this.comment = comment;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/dto/BaseDTO.java",
    "content": "package com.ctrip.framework.apollo.common.dto;\n\n\nimport java.util.Date;\n\npublic class BaseDTO {\n\n  protected String dataChangeCreatedBy;\n\n  protected String dataChangeLastModifiedBy;\n\n  protected Date dataChangeCreatedTime;\n\n  protected Date dataChangeLastModifiedTime;\n\n  public String getDataChangeCreatedBy() {\n    return dataChangeCreatedBy;\n  }\n\n  public void setDataChangeCreatedBy(String dataChangeCreatedBy) {\n    this.dataChangeCreatedBy = dataChangeCreatedBy;\n  }\n\n  public String getDataChangeLastModifiedBy() {\n    return dataChangeLastModifiedBy;\n  }\n\n  public void setDataChangeLastModifiedBy(String dataChangeLastModifiedBy) {\n    this.dataChangeLastModifiedBy = dataChangeLastModifiedBy;\n  }\n\n  public Date getDataChangeCreatedTime() {\n    return dataChangeCreatedTime;\n  }\n\n  public void setDataChangeCreatedTime(Date dataChangeCreatedTime) {\n    this.dataChangeCreatedTime = dataChangeCreatedTime;\n  }\n\n  public Date getDataChangeLastModifiedTime() {\n    return dataChangeLastModifiedTime;\n  }\n\n  public void setDataChangeLastModifiedTime(Date dataChangeLastModifiedTime) {\n    this.dataChangeLastModifiedTime = dataChangeLastModifiedTime;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/dto/ClusterDTO.java",
    "content": "package com.ctrip.framework.apollo.common.dto;\n\npublic class ClusterDTO extends BaseDTO{\n\n  private long id;\n\n  private String name;\n\n  private String appId;\n\n  private long parentClusterId;\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 String getAppId() {\n    return appId;\n  }\n\n  public void setAppId(String appId) {\n    this.appId = appId;\n  }\n\n  public long getParentClusterId() {\n    return parentClusterId;\n  }\n\n  public void setParentClusterId(long parentClusterId) {\n    this.parentClusterId = parentClusterId;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/dto/CommitDTO.java",
    "content": "package com.ctrip.framework.apollo.common.dto;\n\npublic class CommitDTO extends BaseDTO{\n\n  private String changeSets;\n\n  private String appId;\n\n  private String clusterName;\n\n  private String namespaceName;\n\n  private String comment;\n\n  public String getChangeSets() {\n    return changeSets;\n  }\n\n  public void setChangeSets(String changeSets) {\n    this.changeSets = changeSets;\n  }\n\n  public String getAppId() {\n    return appId;\n  }\n\n  public void setAppId(String appId) {\n    this.appId = appId;\n  }\n\n  public String getClusterName() {\n    return clusterName;\n  }\n\n  public void setClusterName(String clusterName) {\n    this.clusterName = clusterName;\n  }\n\n  public String getNamespaceName() {\n    return namespaceName;\n  }\n\n  public void setNamespaceName(String namespaceName) {\n    this.namespaceName = namespaceName;\n  }\n\n  public String getComment() {\n    return comment;\n  }\n\n  public void setComment(String comment) {\n    this.comment = comment;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/dto/GrayReleaseRuleDTO.java",
    "content": "package com.ctrip.framework.apollo.common.dto;\n\n\nimport com.google.common.collect.Sets;\n\nimport java.util.Set;\n\npublic class GrayReleaseRuleDTO extends BaseDTO {\n\n  private String appId;\n\n  private String clusterName;\n\n  private String namespaceName;\n\n  private String branchName;\n\n  private Set<GrayReleaseRuleItemDTO> ruleItems;\n\n  private Long releaseId;\n\n  public GrayReleaseRuleDTO(String appId, String clusterName, String namespaceName, String branchName) {\n    this.appId = appId;\n    this.clusterName = clusterName;\n    this.namespaceName = namespaceName;\n    this.branchName = branchName;\n    this.ruleItems = Sets.newHashSet();\n  }\n\n  public String getAppId() {\n    return appId;\n  }\n\n  public String getClusterName() {\n    return clusterName;\n  }\n\n  public String getNamespaceName() {\n    return namespaceName;\n  }\n\n  public String getBranchName() {\n    return branchName;\n  }\n\n  public Set<GrayReleaseRuleItemDTO> getRuleItems() {\n    return ruleItems;\n  }\n\n  public void setRuleItems(Set<GrayReleaseRuleItemDTO> ruleItems) {\n    this.ruleItems = ruleItems;\n  }\n\n  public void addRuleItem(GrayReleaseRuleItemDTO ruleItem) {\n    this.ruleItems.add(ruleItem);\n  }\n\n  public Long getReleaseId() {\n    return releaseId;\n  }\n\n  public void setReleaseId(Long releaseId) {\n    this.releaseId = releaseId;\n  }\n}\n\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/dto/GrayReleaseRuleItemDTO.java",
    "content": "package com.ctrip.framework.apollo.common.dto;\n\nimport com.google.common.collect.Sets;\n\nimport java.util.Set;\n\nimport static com.google.common.base.MoreObjects.toStringHelper;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class GrayReleaseRuleItemDTO {\n  public static final String ALL_IP = \"*\";\n\n  private String clientAppId;\n  private Set<String> clientIpList;\n\n  public GrayReleaseRuleItemDTO(String clientAppId) {\n    this(clientAppId, Sets.newHashSet());\n  }\n\n  public GrayReleaseRuleItemDTO(String clientAppId, Set<String> clientIpList) {\n    this.clientAppId = clientAppId;\n    this.clientIpList = clientIpList;\n  }\n\n  public String getClientAppId() {\n    return clientAppId;\n  }\n\n  public Set<String> getClientIpList() {\n    return clientIpList;\n  }\n\n  public boolean matches(String clientAppId, String clientIp) {\n    return appIdMatches(clientAppId) && ipMatches(clientIp);\n  }\n\n  private boolean appIdMatches(String clientAppId) {\n    return this.clientAppId.equals(clientAppId);\n  }\n\n  private boolean ipMatches(String clientIp) {\n    return this.clientIpList.contains(ALL_IP) || clientIpList.contains(clientIp);\n  }\n\n  @Override\n  public String toString() {\n    return toStringHelper(this).add(\"clientAppId\", clientAppId)\n        .add(\"clientIpList\", clientIpList).toString();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/dto/InstanceConfigDTO.java",
    "content": "package com.ctrip.framework.apollo.common.dto;\n\nimport java.util.Date;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class InstanceConfigDTO {\n  private ReleaseDTO release;\n  private Date releaseDeliveryTime;\n  private Date dataChangeLastModifiedTime;\n\n  public ReleaseDTO getRelease() {\n    return release;\n  }\n\n  public void setRelease(ReleaseDTO release) {\n    this.release = release;\n  }\n\n  public Date getDataChangeLastModifiedTime() {\n    return dataChangeLastModifiedTime;\n  }\n\n  public void setDataChangeLastModifiedTime(Date dataChangeLastModifiedTime) {\n    this.dataChangeLastModifiedTime = dataChangeLastModifiedTime;\n  }\n\n  public Date getReleaseDeliveryTime() {\n    return releaseDeliveryTime;\n  }\n\n  public void setReleaseDeliveryTime(Date releaseDeliveryTime) {\n    this.releaseDeliveryTime = releaseDeliveryTime;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/dto/InstanceDTO.java",
    "content": "package com.ctrip.framework.apollo.common.dto;\n\nimport java.util.Date;\nimport java.util.List;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class InstanceDTO {\n  private long id;\n\n  private String appId;\n\n  private String clusterName;\n\n  private String dataCenter;\n\n  private String ip;\n\n  private List<InstanceConfigDTO> configs;\n\n  private Date dataChangeCreatedTime;\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 getAppId() {\n    return appId;\n  }\n\n  public void setAppId(String appId) {\n    this.appId = appId;\n  }\n\n  public String getClusterName() {\n    return clusterName;\n  }\n\n  public void setClusterName(String clusterName) {\n    this.clusterName = clusterName;\n  }\n\n  public String getDataCenter() {\n    return dataCenter;\n  }\n\n  public void setDataCenter(String dataCenter) {\n    this.dataCenter = dataCenter;\n  }\n\n  public String getIp() {\n    return ip;\n  }\n\n  public void setIp(String ip) {\n    this.ip = ip;\n  }\n\n  public List<InstanceConfigDTO> getConfigs() {\n    return configs;\n  }\n\n  public void setConfigs(List<InstanceConfigDTO> configs) {\n    this.configs = configs;\n  }\n\n  public Date getDataChangeCreatedTime() {\n    return dataChangeCreatedTime;\n  }\n\n  public void setDataChangeCreatedTime(Date dataChangeCreatedTime) {\n    this.dataChangeCreatedTime = dataChangeCreatedTime;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/dto/ItemChangeSets.java",
    "content": "package com.ctrip.framework.apollo.common.dto;\n\nimport java.util.LinkedList;\nimport java.util.List;\n\n/**\n * storage cud result\n */\npublic class ItemChangeSets extends BaseDTO{\n\n  private List<ItemDTO> createItems = new LinkedList<>();\n  private List<ItemDTO> updateItems = new LinkedList<>();\n  private List<ItemDTO> deleteItems = new LinkedList<>();\n\n  public void addCreateItem(ItemDTO item) {\n    createItems.add(item);\n  }\n\n  public void addUpdateItem(ItemDTO item) {\n    updateItems.add(item);\n  }\n\n  public void addDeleteItem(ItemDTO item) {\n    deleteItems.add(item);\n  }\n\n  public boolean isEmpty(){\n    return createItems.isEmpty() && updateItems.isEmpty() && deleteItems.isEmpty();\n  }\n\n  public List<ItemDTO> getCreateItems() {\n    return createItems;\n  }\n\n  public List<ItemDTO> getUpdateItems() {\n    return updateItems;\n  }\n\n  public List<ItemDTO> getDeleteItems() {\n    return deleteItems;\n  }\n\n  public void setCreateItems(List<ItemDTO> createItems) {\n    this.createItems = createItems;\n  }\n\n  public void setUpdateItems(List<ItemDTO> updateItems) {\n    this.updateItems = updateItems;\n  }\n\n  public void setDeleteItems(List<ItemDTO> deleteItems) {\n    this.deleteItems = deleteItems;\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/dto/ItemDTO.java",
    "content": "package com.ctrip.framework.apollo.common.dto;\n\n\npublic class ItemDTO extends BaseDTO{\n\n  private long id;\n\n  private long namespaceId;\n\n  private String key;\n\n  private String value;\n\n  private String comment;\n\n  private int lineNum;\n\n  public ItemDTO() {\n\n  }\n\n  public ItemDTO(String key, String value, String comment, int lineNum) {\n    this.key = key;\n    this.value = value;\n    this.comment = comment;\n    this.lineNum = lineNum;\n  }\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 getComment() {\n    return comment;\n  }\n\n  public String getKey() {\n    return key;\n  }\n\n  public long getNamespaceId() {\n    return namespaceId;\n  }\n\n  public String getValue() {\n    return value;\n  }\n\n  public void setComment(String comment) {\n    this.comment = comment;\n  }\n\n  public void setKey(String key) {\n    this.key = key;\n  }\n\n  public void setNamespaceId(long namespaceId) {\n    this.namespaceId = namespaceId;\n  }\n\n  public void setValue(String value) {\n    this.value = value;\n  }\n\n  public int getLineNum() {\n    return lineNum;\n  }\n\n  public void setLineNum(int lineNum) {\n    this.lineNum = lineNum;\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/dto/NamespaceDTO.java",
    "content": "package com.ctrip.framework.apollo.common.dto;\n\npublic class NamespaceDTO extends BaseDTO{\n  private long id;\n\n  private String appId;\n  \n  private String clusterName;\n\n  private String namespaceName;\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 getAppId() {\n    return appId;\n  }\n\n  public String getClusterName() {\n    return clusterName;\n  }\n\n  public String getNamespaceName() {\n    return namespaceName;\n  }\n\n  public void setAppId(String appId) {\n    this.appId = appId;\n  }\n\n  public void setClusterName(String clusterName) {\n    this.clusterName = clusterName;\n  }\n\n  public void setNamespaceName(String namespaceName) {\n    this.namespaceName = namespaceName;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/dto/NamespaceLockDTO.java",
    "content": "package com.ctrip.framework.apollo.common.dto;\n\npublic class NamespaceLockDTO extends BaseDTO{\n\n  private long namespaceId;\n\n  public long getNamespaceId() {\n    return namespaceId;\n  }\n\n  public void setNamespaceId(long namespaceId) {\n    this.namespaceId = namespaceId;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/dto/PageDTO.java",
    "content": "package com.ctrip.framework.apollo.common.dto;\n\nimport org.springframework.data.domain.Pageable;\n\nimport java.util.Collections;\nimport java.util.List;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class PageDTO<T> {\n  private final long total;\n  private final List<T> content;\n  private final int page;\n  private final int size;\n\n  public PageDTO(List<T> content, Pageable pageable, long total) {\n    this.total = total;\n    this.content = content;\n    this.page = pageable.getPageNumber();\n    this.size = pageable.getPageSize();\n  }\n\n\n  public long getTotal() {\n    return total;\n  }\n\n  public List<T> getContent() {\n    return Collections.unmodifiableList(content);\n  }\n\n  public int getPage() {\n    return page;\n  }\n\n  public int getSize() {\n    return size;\n  }\n\n  public boolean hasContent(){\n    return content != null && content.size() > 0;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/dto/ReleaseDTO.java",
    "content": "package com.ctrip.framework.apollo.common.dto;\n\npublic class ReleaseDTO extends BaseDTO{\n  private long id;\n\n  private String releaseKey;\n\n  private String name;\n\n  private String appId;\n\n  private String clusterName;\n\n  private String namespaceName;\n\n  private String configurations;\n\n  private String comment;\n\n  private boolean isAbandoned;\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 getReleaseKey() {\n    return releaseKey;\n  }\n\n  public void setReleaseKey(String releaseKey) {\n    this.releaseKey = releaseKey;\n  }\n\n  public String getAppId() {\n    return appId;\n  }\n\n  public String getClusterName() {\n    return clusterName;\n  }\n\n  public String getComment() {\n    return comment;\n  }\n\n  public String getConfigurations() {\n    return configurations;\n  }\n\n  public String getName() {\n    return name;\n  }\n\n  public String getNamespaceName() {\n    return namespaceName;\n  }\n\n  public void setAppId(String appId) {\n    this.appId = appId;\n  }\n\n  public void setClusterName(String clusterName) {\n    this.clusterName = clusterName;\n  }\n\n  public void setComment(String comment) {\n    this.comment = comment;\n  }\n\n  public void setConfigurations(String configurations) {\n    this.configurations = configurations;\n  }\n\n  public void setName(String name) {\n    this.name = name;\n  }\n\n  public void setNamespaceName(String namespaceName) {\n    this.namespaceName = namespaceName;\n  }\n\n  public boolean isAbandoned() {\n    return isAbandoned;\n  }\n\n  public void setAbandoned(boolean abandoned) {\n    isAbandoned = abandoned;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/dto/ReleaseHistoryDTO.java",
    "content": "package com.ctrip.framework.apollo.common.dto;\n\n\nimport java.util.Map;\n\npublic class ReleaseHistoryDTO extends BaseDTO{\n\n  private long id;\n\n  private String appId;\n\n  private String clusterName;\n\n  private String namespaceName;\n\n  private String branchName;\n\n  private long releaseId;\n\n  private long previousReleaseId;\n\n  private int operation;\n\n  private Map<String, Object> operationContext;\n\n  public ReleaseHistoryDTO(){}\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 getAppId() {\n    return appId;\n  }\n\n  public void setAppId(String appId) {\n    this.appId = appId;\n  }\n\n  public String getClusterName() {\n    return clusterName;\n  }\n\n  public void setClusterName(String clusterName) {\n    this.clusterName = clusterName;\n  }\n\n  public String getNamespaceName() {\n    return namespaceName;\n  }\n\n  public void setNamespaceName(String namespaceName) {\n    this.namespaceName = namespaceName;\n  }\n\n  public String getBranchName() {\n    return branchName;\n  }\n\n  public void setBranchName(String branchName) {\n    this.branchName = branchName;\n  }\n\n  public long getReleaseId() {\n    return releaseId;\n  }\n\n  public void setReleaseId(long releaseId) {\n    this.releaseId = releaseId;\n  }\n\n  public long getPreviousReleaseId() {\n    return previousReleaseId;\n  }\n\n  public void setPreviousReleaseId(long previousReleaseId) {\n    this.previousReleaseId = previousReleaseId;\n  }\n\n  public int getOperation() {\n    return operation;\n  }\n\n  public void setOperation(int operation) {\n    this.operation = operation;\n  }\n\n  public Map<String, Object> getOperationContext() {\n    return operationContext;\n  }\n\n  public void setOperationContext(Map<String, Object> operationContext) {\n    this.operationContext = operationContext;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/entity/App.java",
    "content": "package com.ctrip.framework.apollo.common.entity;\n\nimport org.hibernate.annotations.SQLDelete;\nimport org.hibernate.annotations.Where;\n\nimport javax.persistence.Column;\nimport javax.persistence.Entity;\nimport javax.persistence.Table;\n\n@Entity\n@Table(name = \"App\")\n@SQLDelete(sql = \"Update App set isDeleted = 1 where id = ?\")\n@Where(clause = \"isDeleted = 0\")\npublic class App extends BaseEntity {\n\n  @Column(name = \"Name\", nullable = false)\n  private String name;\n\n  @Column(name = \"AppId\", nullable = false)\n  private String appId;\n\n  @Column(name = \"OrgId\", nullable = false)\n  private String orgId;\n\n  @Column(name = \"OrgName\", nullable = false)\n  private String orgName;\n\n  @Column(name = \"OwnerName\", nullable = false)\n  private String ownerName;\n\n  @Column(name = \"OwnerEmail\", nullable = false)\n  private String ownerEmail;\n\n  public String getAppId() {\n    return appId;\n  }\n\n  public String getName() {\n    return name;\n  }\n\n  public String getOrgId() {\n    return orgId;\n  }\n\n  public String getOrgName() {\n    return orgName;\n  }\n\n  public String getOwnerEmail() {\n    return ownerEmail;\n  }\n\n  public String getOwnerName() {\n    return ownerName;\n  }\n\n  public void setAppId(String appId) {\n    this.appId = appId;\n  }\n\n  public void setName(String name) {\n    this.name = name;\n  }\n\n  public void setOrgId(String orgId) {\n    this.orgId = orgId;\n  }\n\n  public void setOrgName(String orgName) {\n    this.orgName = orgName;\n  }\n\n  public void setOwnerEmail(String ownerEmail) {\n    this.ownerEmail = ownerEmail;\n  }\n\n  public void setOwnerName(String ownerName) {\n    this.ownerName = ownerName;\n  }\n\n  public String toString() {\n    return toStringHelper().add(\"name\", name).add(\"appId\", appId)\n        .add(\"orgId\", orgId)\n        .add(\"orgName\", orgName)\n        .add(\"ownerName\", ownerName)\n        .add(\"ownerEmail\", ownerEmail).toString();\n  }\n\n  public static class Builder {\n\n    public Builder() {\n    }\n\n    private App app = new App();\n\n    public Builder name(String name) {\n      app.setName(name);\n      return this;\n    }\n\n    public Builder appId(String appId) {\n      app.setAppId(appId);\n      return this;\n    }\n\n    public Builder orgId(String orgId) {\n      app.setOrgId(orgId);\n      return this;\n    }\n\n    public Builder orgName(String orgName) {\n      app.setOrgName(orgName);\n      return this;\n    }\n\n    public Builder ownerName(String ownerName) {\n      app.setOwnerName(ownerName);\n      return this;\n    }\n\n    public Builder ownerEmail(String ownerEmail) {\n      app.setOwnerEmail(ownerEmail);\n      return this;\n    }\n\n    public App build() {\n      return app;\n    }\n\n  }\n\n  public static Builder builder() {\n    return new Builder();\n  }\n\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/entity/AppNamespace.java",
    "content": "package com.ctrip.framework.apollo.common.entity;\n\n\nimport com.ctrip.framework.apollo.core.enums.ConfigFileFormat;\n\nimport org.hibernate.annotations.SQLDelete;\nimport org.hibernate.annotations.Where;\n\nimport javax.persistence.Column;\nimport javax.persistence.Entity;\nimport javax.persistence.Table;\n\n@Entity\n@Table(name = \"AppNamespace\")\n@SQLDelete(sql = \"Update AppNamespace set isDeleted = 1 where id = ?\")\n@Where(clause = \"isDeleted = 0\")\npublic class AppNamespace extends BaseEntity {\n\n  @Column(name = \"Name\", nullable = false)\n  private String name;\n\n  @Column(name = \"AppId\", nullable = false)\n  private String appId;\n\n  @Column(name = \"Format\", nullable = false)\n  private String format;\n\n  @Column(name = \"IsPublic\", columnDefinition = \"Bit default '0'\")\n  private boolean isPublic = false;\n\n  @Column(name = \"Comment\")\n  private String comment;\n\n  public String getAppId() {\n    return appId;\n  }\n\n  public String getComment() {\n    return comment;\n  }\n\n  public String getName() {\n    return name;\n  }\n\n  public void setAppId(String appId) {\n    this.appId = appId;\n  }\n\n  public void setComment(String comment) {\n    this.comment = comment;\n  }\n\n  public void setName(String name) {\n    this.name = name;\n  }\n\n  public boolean isPublic() {\n    return isPublic;\n  }\n\n  public void setPublic(boolean aPublic) {\n    isPublic = aPublic;\n  }\n\n  public ConfigFileFormat formatAsEnum() {\n    return ConfigFileFormat.fromString(this.format);\n  }\n\n  public String getFormat() {\n    return format;\n  }\n\n  public void setFormat(String format) {\n    this.format = format;\n  }\n\n  public String toString() {\n    return toStringHelper().add(\"name\", name).add(\"appId\", appId).add(\"comment\", comment)\n        .add(\"format\", format).add(\"isPublic\", isPublic).toString();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/entity/BaseEntity.java",
    "content": "package com.ctrip.framework.apollo.common.entity;\n\nimport com.google.common.base.MoreObjects;\nimport com.google.common.base.MoreObjects.ToStringHelper;\n\nimport java.util.Date;\n\nimport javax.persistence.Column;\nimport javax.persistence.GeneratedValue;\nimport javax.persistence.Id;\nimport javax.persistence.Inheritance;\nimport javax.persistence.InheritanceType;\nimport javax.persistence.MappedSuperclass;\nimport javax.persistence.PrePersist;\nimport javax.persistence.PreRemove;\nimport javax.persistence.PreUpdate;\n\n@MappedSuperclass\n@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)\npublic abstract class BaseEntity {\n\n  @Id\n  @GeneratedValue\n  @Column(name = \"Id\")\n  private long id;\n\n  @Column(name = \"IsDeleted\", columnDefinition = \"Bit default '0'\")\n  protected boolean isDeleted = false;\n\n  @Column(name = \"DataChange_CreatedBy\", nullable = false)\n  private String dataChangeCreatedBy;\n\n  @Column(name = \"DataChange_CreatedTime\", nullable = false)\n  private Date dataChangeCreatedTime;\n\n  @Column(name = \"DataChange_LastModifiedBy\")\n  private String dataChangeLastModifiedBy;\n\n  @Column(name = \"DataChange_LastTime\")\n  private Date dataChangeLastModifiedTime;\n\n  public String getDataChangeCreatedBy() {\n    return dataChangeCreatedBy;\n  }\n\n  public Date getDataChangeCreatedTime() {\n    return dataChangeCreatedTime;\n  }\n\n  public String getDataChangeLastModifiedBy() {\n    return dataChangeLastModifiedBy;\n  }\n\n  public Date getDataChangeLastModifiedTime() {\n    return dataChangeLastModifiedTime;\n  }\n\n  public long getId() {\n    return id;\n  }\n\n  public boolean isDeleted() {\n    return isDeleted;\n  }\n\n  public void setDataChangeCreatedBy(String dataChangeCreatedBy) {\n    this.dataChangeCreatedBy = dataChangeCreatedBy;\n  }\n\n  public void setDataChangeCreatedTime(Date dataChangeCreatedTime) {\n    this.dataChangeCreatedTime = dataChangeCreatedTime;\n  }\n\n  public void setDataChangeLastModifiedBy(String dataChangeLastModifiedBy) {\n    this.dataChangeLastModifiedBy = dataChangeLastModifiedBy;\n  }\n\n  public void setDataChangeLastModifiedTime(Date dataChangeLastModifiedTime) {\n    this.dataChangeLastModifiedTime = dataChangeLastModifiedTime;\n  }\n\n  public void setDeleted(boolean deleted) {\n    isDeleted = deleted;\n  }\n\n  public void setId(long id) {\n    this.id = id;\n  }\n\n  @PrePersist\n  protected void prePersist() {\n    if (this.dataChangeCreatedTime == null) dataChangeCreatedTime = new Date();\n    if (this.dataChangeLastModifiedTime == null) dataChangeLastModifiedTime = new Date();\n  }\n\n  @PreUpdate\n  protected void preUpdate() {\n    this.dataChangeLastModifiedTime = new Date();\n  }\n\n  @PreRemove\n  protected void preRemove() {\n    this.dataChangeLastModifiedTime = new Date();\n  }\n\n  protected ToStringHelper toStringHelper() {\n    return MoreObjects.toStringHelper(this).omitNullValues().add(\"id\", id)\n        .add(\"dataChangeCreatedBy\", dataChangeCreatedBy)\n        .add(\"dataChangeCreatedTime\", dataChangeCreatedTime)\n        .add(\"dataChangeLastModifiedBy\", dataChangeLastModifiedBy)\n        .add(\"dataChangeLastModifiedTime\", dataChangeLastModifiedTime);\n  }\n\n  public String toString(){\n    return toStringHelper().toString();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/entity/EntityPair.java",
    "content": "package com.ctrip.framework.apollo.common.entity;\n\npublic class EntityPair<E> {\n\n  private E firstEntity;\n  private E secondEntity;\n\n  public EntityPair(E firstEntity, E secondEntity){\n    this.firstEntity = firstEntity;\n    this.secondEntity = secondEntity;\n  }\n\n  public E getFirstEntity() {\n    return firstEntity;\n  }\n\n  public void setFirstEntity(E firstEntity) {\n    this.firstEntity = firstEntity;\n  }\n\n  public E getSecondEntity() {\n    return secondEntity;\n  }\n\n  public void setSecondEntity(E secondEntity) {\n    this.secondEntity = secondEntity;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/exception/AbstractApolloHttpException.java",
    "content": "package com.ctrip.framework.apollo.common.exception;\n\nimport org.springframework.http.HttpStatus;\n\npublic abstract class AbstractApolloHttpException extends RuntimeException{\n\n  private static final long serialVersionUID = -1713129594004951820L;\n  \n  protected HttpStatus httpStatus;\n\n  public AbstractApolloHttpException(String msg){\n    super(msg);\n  }\n  \n  public AbstractApolloHttpException(String msg, Exception e){\n    super(msg,e);\n  }\n\n  protected void setHttpStatus(HttpStatus httpStatus){\n    this.httpStatus = httpStatus;\n  }\n\n  public HttpStatus getHttpStatus() {\n    return httpStatus;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/exception/BadRequestException.java",
    "content": "package com.ctrip.framework.apollo.common.exception;\n\n\nimport org.springframework.http.HttpStatus;\n\npublic class BadRequestException extends AbstractApolloHttpException {\n\n\n  public BadRequestException(String str) {\n    super(str);\n    setHttpStatus(HttpStatus.BAD_REQUEST);\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/exception/BeanUtilsException.java",
    "content": "package com.ctrip.framework.apollo.common.exception;\n\npublic class BeanUtilsException extends RuntimeException{\n\n  public BeanUtilsException(Throwable e){\n    super(e);\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/exception/NotFoundException.java",
    "content": "package com.ctrip.framework.apollo.common.exception;\n\nimport org.springframework.http.HttpStatus;\n\npublic class NotFoundException extends AbstractApolloHttpException {\n\n\n  public NotFoundException(String str) {\n    super(str);\n    setHttpStatus(HttpStatus.NOT_FOUND);\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/exception/ServiceException.java",
    "content": "package com.ctrip.framework.apollo.common.exception;\n\nimport org.springframework.http.HttpStatus;\n\npublic class ServiceException extends AbstractApolloHttpException {\n\n  public ServiceException(String str) {\n    super(str);\n    setHttpStatus(HttpStatus.INTERNAL_SERVER_ERROR);\n  }\n\n  public ServiceException(String str, Exception e) {\n    super(str, e);\n    setHttpStatus(HttpStatus.INTERNAL_SERVER_ERROR);\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/http/MultiResponseEntity.java",
    "content": "package com.ctrip.framework.apollo.common.http;\n\nimport org.springframework.http.HttpStatus;\n\nimport java.util.LinkedList;\nimport java.util.List;\n\n/**\n * 一个Response中包含多个ResponseEntity\n */\npublic class MultiResponseEntity<T> {\n\n  private int code;\n\n  private List<RichResponseEntity<T>> entities = new LinkedList<>();\n\n  private MultiResponseEntity(HttpStatus httpCode) {\n    this.code = httpCode.value();\n  }\n\n  public static <T> MultiResponseEntity<T> instance(HttpStatus statusCode) {\n    return new MultiResponseEntity<>(statusCode);\n  }\n\n  public static <T> MultiResponseEntity<T> ok() {\n    return new MultiResponseEntity<>(HttpStatus.OK);\n  }\n\n  public void addResponseEntity(RichResponseEntity<T> responseEntity) {\n    if (responseEntity == null){\n      throw new IllegalArgumentException(\"sub response entity can not be null\");\n    }\n    entities.add(responseEntity);\n\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/http/RichResponseEntity.java",
    "content": "package com.ctrip.framework.apollo.common.http;\n\nimport org.springframework.http.HttpStatus;\n\npublic class RichResponseEntity<T>{\n\n  private int code;\n  private Object message;\n  private T body;\n\n  public static <T> RichResponseEntity<T> ok(T body){\n    RichResponseEntity<T> richResponseEntity = new RichResponseEntity<>();\n    richResponseEntity.message = HttpStatus.OK.getReasonPhrase();\n    richResponseEntity.code = HttpStatus.OK.value();\n    richResponseEntity.body = body;\n    return richResponseEntity;\n  }\n\n  public static <T> RichResponseEntity<T> error(HttpStatus httpCode, Object message){\n    RichResponseEntity<T> richResponseEntity = new RichResponseEntity<>();\n    richResponseEntity.message = message;\n    richResponseEntity.code = httpCode.value();\n    return richResponseEntity;\n  }\n\n  public int getCode() {\n    return code;\n  }\n\n  public Object getMessage() {\n    return message;\n  }\n\n  public T getBody() {\n    return body;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/utils/BeanUtils.java",
    "content": "package com.ctrip.framework.apollo.common.utils;\n\nimport com.ctrip.framework.apollo.common.exception.BeanUtilsException;\n\nimport org.springframework.beans.BeanWrapper;\nimport org.springframework.beans.BeanWrapperImpl;\nimport org.springframework.util.CollectionUtils;\n\nimport java.beans.PropertyDescriptor;\nimport java.lang.reflect.Field;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\n\npublic class BeanUtils {\n\n  /**\n   * <pre>\n   *     List<UserBean> userBeans = userDao.queryUsers();\n   *     List<UserDTO> userDTOs = BeanUtil.batchTransform(UserDTO.class, userBeans);\n   * </pre>\n   */\n  public static <T> List<T> batchTransform(final Class<T> clazz, List<? extends Object> srcList) {\n    if (CollectionUtils.isEmpty(srcList)) {\n      return Collections.emptyList();\n    }\n\n    List<T> result = new ArrayList<>(srcList.size());\n    for (Object srcObject : srcList) {\n      result.add(transfrom(clazz, srcObject));\n    }\n    return result;\n  }\n\n  /**\n   * 封装{@link org.springframework.beans.BeanUtils#copyProperties}，惯用与直接将转换结果返回\n   *\n   * <pre>\n   *      UserBean userBean = new UserBean(\"username\");\n   *      return BeanUtil.transform(UserDTO.class, userBean);\n   * </pre>\n   */\n  public static <T> T transfrom(Class<T> clazz, Object src) {\n    if (src == null) {\n      return null;\n    }\n    T instance = null;\n    try {\n      instance = clazz.newInstance();\n    } catch (Exception e) {\n      throw new BeanUtilsException(e);\n    }\n    org.springframework.beans.BeanUtils.copyProperties(src, instance, getNullPropertyNames(src));\n    return instance;\n  }\n\n  private static String[] getNullPropertyNames(Object source) {\n    final BeanWrapper src = new BeanWrapperImpl(source);\n    PropertyDescriptor[] pds = src.getPropertyDescriptors();\n\n    Set<String> emptyNames = new HashSet<String>();\n    for (PropertyDescriptor pd : pds) {\n      Object srcValue = src.getPropertyValue(pd.getName());\n      if (srcValue == null) emptyNames.add(pd.getName());\n    }\n    String[] result = new String[emptyNames.size()];\n    return emptyNames.toArray(result);\n  }\n\n  /**\n   * 用于将一个列表转换为列表中的对象的某个属性映射到列表中的对象\n   *\n   * <pre>\n   *      List<UserDTO> userList = userService.queryUsers();\n   *      Map<Integer, userDTO> userIdToUser = BeanUtil.mapByKey(\"userId\", userList);\n   * </pre>\n   *\n   * @param key 属性名\n   */\n  @SuppressWarnings(\"unchecked\")\n  public static <K, V> Map<K, V> mapByKey(String key, List<? extends Object> list) {\n    Map<K, V> map = new HashMap<K, V>();\n    if (CollectionUtils.isEmpty(list)) {\n      return map;\n    }\n    try {\n      Class<? extends Object> clazz = list.get(0).getClass();\n      Field field = deepFindField(clazz, key);\n      if (field == null) throw new IllegalArgumentException(\"Could not find the key\");\n      field.setAccessible(true);\n      for (Object o : list) {\n        map.put((K) field.get(o), (V) o);\n      }\n    } catch (Exception e) {\n      throw new BeanUtilsException(e);\n    }\n    return map;\n  }\n\n  /**\n   * 根据列表里面的属性聚合\n   *\n   * <pre>\n   *       List<ShopDTO> shopList = shopService.queryShops();\n   *       Map<Integer, List<ShopDTO>> city2Shops = BeanUtil.aggByKeyToList(\"cityId\", shopList);\n   * </pre>\n   */\n  @SuppressWarnings(\"unchecked\")\n  public static <K, V> Map<K, List<V>> aggByKeyToList(String key, List<? extends Object> list) {\n    Map<K, List<V>> map = new HashMap<K, List<V>>();\n    if (CollectionUtils.isEmpty(list)) {// 防止外面传入空list\n      return map;\n    }\n    try {\n      Class<? extends Object> clazz = list.get(0).getClass();\n      Field field = deepFindField(clazz, key);\n      if (field == null) throw new IllegalArgumentException(\"Could not find the key\");\n      field.setAccessible(true);\n      for (Object o : list) {\n        K k = (K) field.get(o);\n        if (map.get(k) == null) {\n          map.put(k, new ArrayList<V>());\n        }\n        map.get(k).add((V) o);\n      }\n    } catch (Exception e) {\n      throw new BeanUtilsException(e);\n    }\n    return map;\n  }\n\n  /**\n   * 用于将一个对象的列表转换为列表中对象的属性集合\n   *\n   * <pre>\n   *     List<UserDTO> userList = userService.queryUsers();\n   *     Set<Integer> userIds = BeanUtil.toPropertySet(\"userId\", userList);\n   * </pre>\n   */\n  @SuppressWarnings(\"unchecked\")\n  public static <K> Set<K> toPropertySet(String key, List<? extends Object> list) {\n    Set<K> set = new HashSet<K>();\n    if (CollectionUtils.isEmpty(list)) {// 防止外面传入空list\n      return set;\n    }\n    try {\n      Class<? extends Object> clazz = list.get(0).getClass();\n      Field field = deepFindField(clazz, key);\n      if (field == null) throw new IllegalArgumentException(\"Could not find the key\");\n      field.setAccessible(true);\n      for (Object o : list) {\n        set.add((K)field.get(o));\n      }\n    } catch (Exception e) {\n      throw new BeanUtilsException(e);\n    }\n    return set;\n  }\n\n\n  private static Field deepFindField(Class<? extends Object> clazz, String key) {\n    Field field = null;\n    while (!clazz.getName().equals(Object.class.getName())) {\n      try {\n        field = clazz.getDeclaredField(key);\n        if (field != null) {\n          break;\n        }\n      } catch (Exception e) {\n        clazz = clazz.getSuperclass();\n      }\n    }\n    return field;\n  }\n\n  /**\n   * 获取某个对象的某个属性\n   */\n  public static Object getProperty(Object obj, String fieldName) {\n    try {\n      Field field = deepFindField(obj.getClass(), fieldName);\n      if (field != null) {\n        field.setAccessible(true);\n        return field.get(obj);\n      }\n    } catch (Exception e) {\n      throw new BeanUtilsException(e);\n    }\n    return null;\n  }\n\n  /**\n   * 设置某个对象的某个属性\n   */\n  public static void setProperty(Object obj, String fieldName, Object value) {\n    try {\n      Field field = deepFindField(obj.getClass(), fieldName);\n      if (field != null) {\n        field.setAccessible(true);\n        field.set(obj, value);\n      }\n    } catch (Exception e) {\n      throw new BeanUtilsException(e);\n    }\n  }\n\n  /**\n   * \n   * @param source\n   * @param target\n   */\n  public static void copyProperties(Object source, Object target, String... ignoreProperties) {\n    org.springframework.beans.BeanUtils.copyProperties(source, target, ignoreProperties);\n  }\n\n  /**\n   * The copy will ignore <em>BaseEntity</em> field\n   *\n   * @param source\n   * @param target\n   */\n  public static void copyEntityProperties(Object source, Object target) {\n    org.springframework.beans.BeanUtils.copyProperties(source, target, COPY_IGNORED_PROPERTIES);\n  }\n  \n  private static final String[] COPY_IGNORED_PROPERTIES = {\"id\", \"dataChangeCreatedBy\", \"dataChangeCreatedTime\", \"dataChangeLastModifiedTime\"};\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/utils/ExceptionUtils.java",
    "content": "package com.ctrip.framework.apollo.common.utils;\n\nimport com.google.common.base.MoreObjects;\nimport com.google.gson.Gson;\nimport com.google.gson.reflect.TypeToken;\n\nimport org.springframework.web.client.HttpStatusCodeException;\n\nimport java.lang.reflect.Type;\nimport java.util.Map;\n\npublic final class ExceptionUtils {\n\n  private static Gson gson = new Gson();\n\n  private static Type mapType = new TypeToken<Map<String, Object>>() {}.getType();\n\n  public static String toString(HttpStatusCodeException e) {\n    Map<String, Object> errorAttributes = gson.fromJson(e.getResponseBodyAsString(), mapType);\n    if (errorAttributes != null) {\n      return MoreObjects.toStringHelper(HttpStatusCodeException.class).omitNullValues()\n          .add(\"status\", errorAttributes.get(\"status\"))\n          .add(\"message\", errorAttributes.get(\"message\"))\n          .add(\"timestamp\", errorAttributes.get(\"timestamp\"))\n          .add(\"exception\", errorAttributes.get(\"exception\"))\n          .add(\"errorCode\", errorAttributes.get(\"errorCode\"))\n          .add(\"stackTrace\", errorAttributes.get(\"stackTrace\")).toString();\n    }\n    return \"\";\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/utils/GrayReleaseRuleItemTransformer.java",
    "content": "package com.ctrip.framework.apollo.common.utils;\n\nimport com.google.gson.Gson;\nimport com.google.gson.reflect.TypeToken;\n\nimport com.ctrip.framework.apollo.common.dto.GrayReleaseRuleItemDTO;\n\nimport java.lang.reflect.Type;\nimport java.util.Set;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class GrayReleaseRuleItemTransformer {\n  private static final Gson gson = new Gson();\n  private static final Type grayReleaseRuleItemsType = new TypeToken<Set<GrayReleaseRuleItemDTO>>() {\n  }.getType();\n\n  public static Set<GrayReleaseRuleItemDTO> batchTransformFromJSON(String content) {\n    return gson.fromJson(content, grayReleaseRuleItemsType);\n  }\n\n  public static String batchTransformToJSON(Set<GrayReleaseRuleItemDTO> ruleItems) {\n    return gson.toJson(ruleItems);\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/utils/InputValidator.java",
    "content": "package com.ctrip.framework.apollo.common.utils;\n\nimport com.ctrip.framework.apollo.core.utils.StringUtils;\n\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class InputValidator {\n  public static final String INVALID_CLUSTER_NAMESPACE_MESSAGE = \"只允许输入数字，字母和符号 - _ .\";\n  public static final String INVALID_NAMESPACE_NAMESPACE_MESSAGE = \"不允许以.json, .yml, .yaml, .xml, .properties结尾\";\n  public static final String CLUSTER_NAMESPACE_VALIDATOR = \"[0-9a-zA-Z_.-]+\";\n  public static final String APP_NAMESPACE_VALIDATOR = \"[a-zA-Z0-9._-]+(?<!\\\\.(json|yml|yaml|xml|properties))$\";\n  private static final Pattern CLUSTER_NAMESPACE_PATTERN =\n      Pattern.compile(CLUSTER_NAMESPACE_VALIDATOR);\n  private static final Pattern APP_NAMESPACE_PATTERN =\n      Pattern.compile(APP_NAMESPACE_VALIDATOR);\n\n\n  public static boolean isValidClusterNamespace(String input) {\n    Matcher matcher = CLUSTER_NAMESPACE_PATTERN.matcher(input);\n    return matcher.matches();\n  }\n\n  public static boolean isValidAppNamespace(String name){\n    if (StringUtils.isEmpty(name)){\n      return false;\n    }\n    return CLUSTER_NAMESPACE_PATTERN.matcher(name).matches() && APP_NAMESPACE_PATTERN.matcher(name).matches();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/utils/RequestPrecondition.java",
    "content": "package com.ctrip.framework.apollo.common.utils;\n\n\nimport com.ctrip.framework.apollo.common.exception.BadRequestException;\nimport com.ctrip.framework.apollo.core.utils.StringUtils;\n\n\npublic class RequestPrecondition {\n\n  private static String CONTAIN_EMPTY_ARGUMENT = \"request payload should not be contain empty.\";\n\n  private static String ILLEGAL_MODEL = \"request model is invalid\";\n\n  private static String ILLEGAL_NUMBER = \"number should be positive\";\n\n\n  public static void checkArgumentsNotEmpty(String... args) {\n    checkArguments(!StringUtils.isContainEmpty(args), CONTAIN_EMPTY_ARGUMENT);\n  }\n\n  public static void checkModel(boolean valid){\n    checkArguments(valid, ILLEGAL_MODEL);\n  }\n\n  public static void checkArguments(boolean expression, Object errorMessage) {\n    if (!expression) {\n      throw new BadRequestException(String.valueOf(errorMessage));\n    }\n  }\n\n  public static void checkNumberPositive(int... args){\n    for (int num: args){\n      if (num <= 0){\n        throw new BadRequestException(ILLEGAL_NUMBER);\n      }\n    }\n  }\n\n  public static void checkNumberPositive(long... args){\n    for (long num: args){\n      if (num <= 0){\n        throw new BadRequestException(ILLEGAL_NUMBER);\n      }\n    }\n  }\n\n  public static void checkNumberNotNegative(int... args){\n    for (int num: args){\n      if (num < 0){\n        throw new BadRequestException(ILLEGAL_NUMBER);\n      }\n    }\n  }\n\n\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/utils/UniqueKeyGenerator.java",
    "content": "package com.ctrip.framework.apollo.common.utils;\n\nimport com.google.common.base.Joiner;\n\nimport com.ctrip.framework.apollo.core.utils.ByteUtil;\nimport com.ctrip.framework.apollo.core.utils.MachineUtil;\n\nimport org.apache.commons.lang.time.FastDateFormat;\n\nimport java.security.SecureRandom;\nimport java.util.Date;\nimport java.util.Objects;\nimport java.util.concurrent.atomic.AtomicInteger;\n\npublic class UniqueKeyGenerator {\n\n  private static final FastDateFormat TIMESTAMP_FORMAT = FastDateFormat.getInstance(\"yyyyMMddHHmmss\");\n  private static final AtomicInteger counter = new AtomicInteger(new SecureRandom().nextInt());\n  private static final Joiner KEY_JOINER = Joiner.on(\"-\");\n\n\n\n  public static String generate(Object... args){\n    String hexIdString =\n        ByteUtil.toHexString(toByteArray(Objects.hash(args), MachineUtil.getMachineIdentifier(),\n                                         counter.incrementAndGet()));\n\n    return KEY_JOINER.join(TIMESTAMP_FORMAT.format(new Date()), hexIdString);\n\n  }\n\n  /**\n   * Concat machine id, counter and key to byte array\n   * Only retrieve lower 3 bytes of the id and counter and 2 bytes of the keyHashCode\n   */\n  protected static byte[] toByteArray(int keyHashCode, int machineIdentifier, int counter) {\n    byte[] bytes = new byte[8];\n    bytes[0] = ByteUtil.int1(keyHashCode);\n    bytes[1] = ByteUtil.int0(keyHashCode);\n    bytes[2] = ByteUtil.int2(machineIdentifier);\n    bytes[3] = ByteUtil.int1(machineIdentifier);\n    bytes[4] = ByteUtil.int0(machineIdentifier);\n    bytes[5] = ByteUtil.int2(counter);\n    bytes[6] = ByteUtil.int1(counter);\n    bytes[7] = ByteUtil.int0(counter);\n    return bytes;\n  }\n\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/resources/application-ctrip.properties",
    "content": "# Titan Datasource (Ctrip only)\nfat.titan.url=${fat_titan_url}\nfat.titan.dbname=${fat_titan_dbname}\nuat.titan.url=${uat_titan_url}\nuat.titan.dbname=${uat_titan_dbname}\npro.titan.url=${pro_titan_url}\npro.titan.dbname=${pro_titan_dbname}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/resources/application-github.properties",
    "content": "# DataSource\nspring.datasource.url = ${spring_datasource_url}\nspring.datasource.username = ${spring_datasource_username}\nspring.datasource.password = ${spring_datasource_password}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/resources/application.properties",
    "content": "spring.http.converters.preferred-json-mapper=gson\n\n# DataSource\nspring.datasource.testWhileIdle=true\nspring.datasource.testOnBorrow=true\nspring.datasource.validationQuery=SELECT 1\nspring.datasource.validationInterval=5000\nspring.datasource.initSQL=set names utf8mb4\n\n# Naming strategy\nspring.jpa.hibernate.naming_strategy=org.hibernate.cfg.EJB3NamingStrategy\nspring.jpa.hibernate.globally_quoted_identifiers=true\nspring.jpa.properties.hibernate.globally_quoted_identifiers=true\n\n# Tomcat configuration\nserver.tomcat.accept-count=5000\n# Increase tomcat header size for longer GET query parameter, should be n * 1024\nserver.tomcat.maxHttpHeaderSize=10240\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/main/resources/datasource.xml",
    "content": "<!--\n    for ctrip datasource\n-->\n<Datasources>\n    <Datasource\n            name=\"${pro_titan_dbname}\"\n            testWhileIdle=\"true\"\n            testOnBorrow=\"true\"\n            testOnReturn=\"false\"\n            validationQuery=\"SELECT 1\"\n            initSql=\"set names utf8mb4\"\n            validationInterval=\"30000\"\n            timeBetweenEvictionRunsMillis=\"5000\"\n            maxActive=\"100\"\n            minIdle=\"10\"\n            maxWait=\"10000\"\n            initialSize=\"10\"\n            removeAbandonedTimeout=\"60\"\n            removeAbandoned=\"true\"\n            logAbandoned=\"false\"\n            minEvictableIdleTimeMillis=\"30000\"\n            option=\"sendStringParametersAsUnicode=false\"\n    />\n</Datasources>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/test/java/com/ctrip/framework/apollo/common/AllTests.java",
    "content": "package com.ctrip.framework.apollo.common;\n\nimport com.ctrip.framework.apollo.common.conditional.ConditionalOnProfileTest;\nimport com.ctrip.framework.apollo.common.utils.InputValidatorTest;\n\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Suite;\nimport org.junit.runners.Suite.SuiteClasses;\n\n@RunWith(Suite.class)\n@SuiteClasses({\n    InputValidatorTest.class, ConditionalOnProfileTest.class\n})\npublic class AllTests {\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/test/java/com/ctrip/framework/apollo/common/conditional/ConditionalOnProfileTest.java",
    "content": "package com.ctrip.framework.apollo.common.conditional;\n\nimport com.ctrip.framework.apollo.common.condition.ConditionalOnMissingProfile;\nimport com.ctrip.framework.apollo.common.condition.ConditionalOnProfile;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.test.context.ActiveProfiles;\nimport org.springframework.test.context.ContextConfiguration;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\n\nimport static com.ctrip.framework.apollo.common.conditional.ConditionalOnProfileTest.ANOTHER_PROFILE;\nimport static com.ctrip.framework.apollo.common.conditional.ConditionalOnProfileTest.SOME_PROFILE;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertTrue;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@RunWith(SpringJUnit4ClassRunner.class)\n@ContextConfiguration(classes = ConditionalOnProfileTest.TestConfiguration.class)\n@ActiveProfiles({SOME_PROFILE, ANOTHER_PROFILE})\npublic class ConditionalOnProfileTest {\n  static final String SOME_PROFILE = \"someProfile\";\n  static final String ANOTHER_PROFILE = \"anotherProfile\";\n  static final String YET_ANOTHER_PROFILE = \"yetAnotherProfile\";\n\n  static boolean someConfigurationEnabled = false;\n  static boolean anotherConfigurationEnabled = false;\n  static boolean yetAnotherConfigurationEnabled = false;\n  static boolean combinedConfigurationEnabled = false;\n  static boolean anotherCombinedConfigurationEnabled = false;\n\n  @Test\n  public void test() throws Exception {\n    assertTrue(someConfigurationEnabled);\n    assertFalse(anotherConfigurationEnabled);\n    assertTrue(yetAnotherConfigurationEnabled);\n    assertTrue(combinedConfigurationEnabled);\n    assertFalse(anotherCombinedConfigurationEnabled);\n  }\n\n  @Configuration\n  static class TestConfiguration {\n\n    @Configuration\n    @ConditionalOnProfile(SOME_PROFILE)\n    static class SomeConfiguration {\n      {\n        someConfigurationEnabled = true;\n      }\n    }\n\n    @Configuration\n    @ConditionalOnMissingProfile(ANOTHER_PROFILE)\n    static class AnotherConfiguration {\n      {\n        anotherConfigurationEnabled = true;\n      }\n    }\n\n\n    @Configuration\n    @ConditionalOnMissingProfile(YET_ANOTHER_PROFILE)\n    static class YetAnotherConfiguration {\n      {\n        yetAnotherConfigurationEnabled = true;\n      }\n    }\n\n    @Configuration\n    @ConditionalOnProfile({SOME_PROFILE, ANOTHER_PROFILE})\n    @ConditionalOnMissingProfile(YET_ANOTHER_PROFILE)\n    static class CombinedConfiguration {\n      {\n        combinedConfigurationEnabled = true;\n      }\n    }\n\n    @Configuration\n    @ConditionalOnProfile(SOME_PROFILE)\n    @ConditionalOnMissingProfile({YET_ANOTHER_PROFILE, ANOTHER_PROFILE})\n    static class AnotherCombinedConfiguration {\n      {\n        anotherCombinedConfigurationEnabled = true;\n      }\n    }\n\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-common/src/test/java/com/ctrip/framework/apollo/common/utils/InputValidatorTest.java",
    "content": "package com.ctrip.framework.apollo.common.utils;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertTrue;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class InputValidatorTest {\n\n  @Test\n  public void testIsValidClusterNamespaceWithCorrectInput() throws Exception {\n    String someValidInput = \"a1-b2_c3.d4\";\n    assertTrue(InputValidator.isValidClusterNamespace(someValidInput));\n  }\n\n  @Test\n  public void testIsValidClusterNamespaceWithInCorrectInput() throws Exception {\n    String someInvalidInput = \"中文123\";\n    assertFalse(InputValidator.isValidClusterNamespace(someInvalidInput));\n\n    String anotherInvalidInput = \"123@#{}\";\n    assertFalse(InputValidator.isValidClusterNamespace(anotherInvalidInput));\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/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\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">\n\t<parent>\n\t\t<groupId>com.ctrip.framework.apollo</groupId>\n\t\t<artifactId>apollo</artifactId>\n\t\t<version>0.10.0-SNAPSHOT</version>\n\t</parent>\n\t<modelVersion>4.0.0</modelVersion>\n\t<artifactId>apollo-configservice</artifactId>\n\t<name>Apollo ConfigService</name>\n\t<properties>\n\t\t<github.path>${project.artifactId}</github.path>\n\t</properties>\n\t<dependencies>\n\t\t<!-- apollo -->\n\t\t<dependency>\n\t\t\t<groupId>com.ctrip.framework.apollo</groupId>\n\t\t\t<artifactId>apollo-biz</artifactId>\n\t\t</dependency>\n\t\t<!-- end of apollo -->\n\t\t<!-- eureka -->\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-eureka-server</artifactId>\n\t\t\t<exclusions>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<artifactId>\n                        spring-cloud-starter-archaius\n                    </artifactId>\n\t\t\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t\t</exclusion>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<artifactId>spring-cloud-starter-ribbon</artifactId>\n\t\t\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t\t</exclusion>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<artifactId>ribbon-eureka</artifactId>\n\t\t\t\t\t<groupId>com.netflix.ribbon</groupId>\n\t\t\t\t</exclusion>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<artifactId>aws-java-sdk-core</artifactId>\n\t\t\t\t\t<groupId>com.amazonaws</groupId>\n\t\t\t\t</exclusion>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<artifactId>aws-java-sdk-ec2</artifactId>\n\t\t\t\t\t<groupId>com.amazonaws</groupId>\n\t\t\t\t</exclusion>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<artifactId>aws-java-sdk-autoscaling</artifactId>\n\t\t\t\t\t<groupId>com.amazonaws</groupId>\n\t\t\t\t</exclusion>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<artifactId>aws-java-sdk-sts</artifactId>\n\t\t\t\t\t<groupId>com.amazonaws</groupId>\n\t\t\t\t</exclusion>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<artifactId>aws-java-sdk-route53</artifactId>\n\t\t\t\t\t<groupId>com.amazonaws</groupId>\n\t\t\t\t</exclusion>\n\t\t\t\t<!-- duplicated with spring-security-core -->\n\t\t\t\t<exclusion>\n\t\t\t\t\t<groupId>org.springframework.security</groupId>\n\t\t\t\t\t<artifactId>spring-security-crypto</artifactId>\n\t\t\t\t</exclusion>\n\t\t\t</exclusions>\n\t\t</dependency>\n\t\t<!-- end of eureka -->\n\t\t<dependency>\n\t\t\t<groupId>com.h2database</groupId>\n\t\t\t<artifactId>h2</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t <dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-jdbc</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>mysql</groupId>\n\t\t\t<artifactId>mysql-connector-java</artifactId>\n\t\t</dependency>\n\t</dependencies>\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>repackage</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t</plugins>\n\t\t<finalName>apollo-configservice</finalName>\n\t</build>\n</project>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/assembly/assembly-descriptor.xml",
    "content": "<assembly\n\txmlns=\"http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3\"\n\txmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd\">\n\t<id>apollo-assembly</id>\n\t<formats>\n\t\t<format>zip</format>\n\t</formats>\n\t<includeBaseDirectory>false</includeBaseDirectory>\n\t<fileSets>\n\t\t<!--scripts -->\n\t\t<fileSet>\n\t\t\t<directory>src/main/scripts</directory>\n\t\t\t<outputDirectory>scripts</outputDirectory>\n\t\t\t<includes>\n\t\t\t\t<include>*.sh</include>\n\t\t\t</includes>\n\t\t\t<fileMode>0755</fileMode>\n\t\t\t<lineEnding>unix</lineEnding>\n\t\t</fileSet>\n\t\t<fileSet>\n\t\t\t<directory>src/main/config</directory>\n\t\t\t<outputDirectory>config</outputDirectory>\n\t\t\t<excludes>\n\t\t\t\t<exclude>apollo-configservice.conf</exclude>\n\t\t\t</excludes>\n\t\t\t<lineEnding>unix</lineEnding>\n\t\t</fileSet>\n\t\t<fileSet>\n\t\t\t<directory>src/main/config</directory>\n\t\t\t<outputDirectory>/</outputDirectory>\n\t\t\t<includes>\n\t\t\t\t<include>apollo-configservice.conf</include>\n\t\t\t</includes>\n\t\t\t<lineEnding>unix</lineEnding>\n\t\t</fileSet>\n\t\t<!--artifact -->\n\t\t<fileSet>\n\t\t\t<directory>target</directory>\n\t\t\t<outputDirectory>/</outputDirectory>\n\t\t\t<includes>\n\t\t\t\t<include>${project.artifactId}-*.jar</include>\n\t\t\t</includes>\n\t\t\t<fileMode>0755</fileMode>\n\t\t</fileSet>\n\t</fileSets>\n</assembly>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/main/config/apollo-configservice.conf",
    "content": "MODE=service\nPID_FOLDER=.\nLOG_FOLDER=/opt/logs/100003171/"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/main/config/app.properties",
    "content": "appId=100003171\njdkVersion=1.8"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/main/docker/Dockerfile",
    "content": "# Dockerfile for apollo-configservice\n# Build with:\n# docker build -t apollo-configservice .\n# Run with:\n# docker run -p 8080:8080 -d -v /tmp/logs:/opt/logs --name apollo-configservice apollo-configservice\n\nFROM openjdk:8-jre-alpine\nMAINTAINER ameizi <sxyx2008@163.com>\n\nENV VERSION 0.9.0\n\nRUN echo \"http://mirrors.aliyun.com/alpine/v3.6/main\" > /etc/apk/repositories \\\n    && echo \"http://mirrors.aliyun.com/alpine/v3.6/community\" >> /etc/apk/repositories \\\n    && apk update upgrade \\\n    && apk add --no-cache procps unzip curl bash tzdata \\\n    && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \\\n    && echo \"Asia/Shanghai\" > /etc/timezone\n\nADD apollo-configservice-${VERSION}-github.zip /apollo-configservice/apollo-configservice-${VERSION}-github.zip\n\nRUN unzip /apollo-configservice/apollo-configservice-${VERSION}-github.zip -d /apollo-configservice \\\n    && rm -rf /apollo-configservice/apollo-configservice-${VERSION}-github.zip \\\n    && sed -i '$d' /apollo-configservice/scripts/startup.sh \\\n    && echo \"tail -f /dev/null\" >> /apollo-configservice/scripts/startup.sh\n\nEXPOSE 8080\n\nCMD [\"/apollo-configservice/scripts/startup.sh\"]\n"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/ConfigServiceApplication.java",
    "content": "package com.ctrip.framework.apollo.configservice;\n\nimport com.ctrip.framework.apollo.biz.ApolloBizConfig;\nimport com.ctrip.framework.apollo.common.ApolloCommonConfig;\nimport com.ctrip.framework.apollo.metaservice.ApolloMetaServiceConfig;\n\nimport org.springframework.boot.actuate.system.ApplicationPidFileWriter;\nimport org.springframework.boot.actuate.system.EmbeddedServerPortFileWriter;\nimport org.springframework.boot.autoconfigure.EnableAutoConfiguration;\nimport org.springframework.boot.builder.SpringApplicationBuilder;\nimport org.springframework.cloud.netflix.eureka.EnableEurekaClient;\nimport org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;\nimport org.springframework.context.ConfigurableApplicationContext;\nimport org.springframework.context.annotation.ComponentScan;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.context.annotation.EnableAspectJAutoProxy;\nimport org.springframework.context.annotation.PropertySource;\nimport org.springframework.transaction.annotation.EnableTransactionManagement;\n\n/**\n * Spring boot application entry point\n *\n * @author Jason Song(song_s@ctrip.com)\n */\n\n@EnableEurekaClient\n@EnableAspectJAutoProxy\n@EnableAutoConfiguration // (exclude = EurekaClientConfigBean.class)\n@Configuration\n@EnableTransactionManagement\n@PropertySource(value = {\"classpath:configservice.properties\"})\n@ComponentScan(basePackageClasses = {ApolloCommonConfig.class,\n    ApolloBizConfig.class,\n    ConfigServiceApplication.class,\n    ApolloMetaServiceConfig.class})\npublic class ConfigServiceApplication {\n\n  public static void main(String[] args) throws Exception {\n    ConfigurableApplicationContext context =\n        new SpringApplicationBuilder(ConfigServiceApplication.class).run(args);\n    context.addApplicationListener(new ApplicationPidFileWriter());\n    context.addApplicationListener(new EmbeddedServerPortFileWriter());\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/ConfigServiceAutoConfiguration.java",
    "content": "package com.ctrip.framework.apollo.configservice;\n\nimport com.ctrip.framework.apollo.biz.config.BizConfig;\nimport com.ctrip.framework.apollo.biz.grayReleaseRule.GrayReleaseRulesHolder;\nimport com.ctrip.framework.apollo.biz.message.ReleaseMessageScanner;\nimport com.ctrip.framework.apollo.configservice.controller.ConfigFileController;\nimport com.ctrip.framework.apollo.configservice.controller.NotificationController;\nimport com.ctrip.framework.apollo.configservice.controller.NotificationControllerV2;\nimport com.ctrip.framework.apollo.configservice.service.ReleaseMessageServiceWithCache;\n\nimport com.ctrip.framework.apollo.configservice.service.config.ConfigService;\nimport com.ctrip.framework.apollo.configservice.service.config.ConfigServiceWithCache;\nimport com.ctrip.framework.apollo.configservice.service.config.DefaultConfigService;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@Configuration\npublic class ConfigServiceAutoConfiguration {\n\n  @Autowired\n  private BizConfig bizConfig;\n\n  @Bean\n  public GrayReleaseRulesHolder grayReleaseRulesHolder() {\n    return new GrayReleaseRulesHolder();\n  }\n\n  @Bean\n  public ConfigService configService() {\n    if (bizConfig.isConfigServiceCacheEnabled()) {\n      return new ConfigServiceWithCache();\n    }\n    return new DefaultConfigService();\n  }\n\n  @Configuration\n  static class MessageScannerConfiguration {\n    @Autowired\n    private NotificationController notificationController;\n    @Autowired\n    private ConfigFileController configFileController;\n    @Autowired\n    private NotificationControllerV2 notificationControllerV2;\n    @Autowired\n    private GrayReleaseRulesHolder grayReleaseRulesHolder;\n    @Autowired\n    private ReleaseMessageServiceWithCache releaseMessageServiceWithCache;\n    @Autowired\n    private ConfigService configService;\n\n    @Bean\n    public ReleaseMessageScanner releaseMessageScanner() {\n      ReleaseMessageScanner releaseMessageScanner = new ReleaseMessageScanner();\n      //0. handle release message cache\n      releaseMessageScanner.addMessageListener(releaseMessageServiceWithCache);\n      //1. handle gray release rule\n      releaseMessageScanner.addMessageListener(grayReleaseRulesHolder);\n      //2. handle server cache\n      releaseMessageScanner.addMessageListener(configService);\n      releaseMessageScanner.addMessageListener(configFileController);\n      //3. notify clients\n      releaseMessageScanner.addMessageListener(notificationControllerV2);\n      releaseMessageScanner.addMessageListener(notificationController);\n      return releaseMessageScanner;\n    }\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/ConfigServiceHealthIndicator.java",
    "content": "package com.ctrip.framework.apollo.configservice;\n\nimport com.ctrip.framework.apollo.biz.service.AppService;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.actuate.health.Health;\nimport org.springframework.boot.actuate.health.HealthIndicator;\nimport org.springframework.data.domain.PageRequest;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class ConfigServiceHealthIndicator implements HealthIndicator {\n\n  @Autowired\n  private AppService appService;\n\n  @Override\n  public Health health() {\n    int errorCode = check();\n    if (errorCode != 0) {\n      return Health.down().withDetail(\"Error Code\", errorCode).build();\n    }\n    return Health.up().build();\n  }\n\n  private int check() {\n    PageRequest pageable = new PageRequest(0, 1);\n    appService.findAll(pageable);\n    return 0;\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/ServletInitializer.java",
    "content": "package com.ctrip.framework.apollo.configservice;\n\nimport org.springframework.boot.builder.SpringApplicationBuilder;\nimport org.springframework.boot.context.web.SpringBootServletInitializer;\n\n/**\n * Entry point for traditional web app\n *\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class ServletInitializer extends SpringBootServletInitializer {\n\n  @Override\n  protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {\n    return application.sources(ConfigServiceApplication.class);\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/controller/ConfigController.java",
    "content": "package com.ctrip.framework.apollo.configservice.controller;\n\nimport java.io.IOException;\nimport java.lang.reflect.Type;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.stream.Collectors;\n\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport com.ctrip.framework.apollo.biz.entity.Release;\nimport com.ctrip.framework.apollo.common.entity.AppNamespace;\nimport com.ctrip.framework.apollo.configservice.service.AppNamespaceServiceWithCache;\nimport com.ctrip.framework.apollo.configservice.service.config.ConfigService;\nimport com.ctrip.framework.apollo.configservice.util.InstanceConfigAuditUtil;\nimport com.ctrip.framework.apollo.configservice.util.NamespaceUtil;\nimport com.ctrip.framework.apollo.core.ConfigConsts;\nimport com.ctrip.framework.apollo.core.dto.ApolloConfig;\nimport com.ctrip.framework.apollo.core.dto.ApolloNotificationMessages;\nimport com.ctrip.framework.apollo.tracer.Tracer;\nimport com.google.common.base.Splitter;\nimport com.google.common.base.Strings;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport com.google.gson.Gson;\nimport com.google.gson.reflect.TypeToken;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@RestController\n@RequestMapping(\"/configs\")\npublic class ConfigController {\n  private static final Splitter X_FORWARDED_FOR_SPLITTER = Splitter.on(\",\").omitEmptyStrings()\n      .trimResults();\n  @Autowired\n  private ConfigService configService;\n  @Autowired\n  private AppNamespaceServiceWithCache appNamespaceService;\n  @Autowired\n  private NamespaceUtil namespaceUtil;\n  @Autowired\n  private InstanceConfigAuditUtil instanceConfigAuditUtil;\n  @Autowired\n  private Gson gson;\n\n  private static final Type configurationTypeReference = new TypeToken<Map<String, String>>() {\n      }.getType();\n\n  @RequestMapping(value = \"/{appId}/{clusterName}/{namespace:.+}\", method = RequestMethod.GET)\n  public ApolloConfig queryConfig(@PathVariable String appId, @PathVariable String clusterName,\n                                  @PathVariable String namespace,\n                                  @RequestParam(value = \"dataCenter\", required = false) String dataCenter,\n                                  @RequestParam(value = \"releaseKey\", defaultValue = \"-1\") String clientSideReleaseKey,\n                                  @RequestParam(value = \"ip\", required = false) String clientIp,\n                                  @RequestParam(value = \"messages\", required = false) String messagesAsString,\n                                  HttpServletRequest request, HttpServletResponse response) throws IOException {\n    String originalNamespace = namespace;\n    //strip out .properties suffix\n    namespace = namespaceUtil.filterNamespaceName(namespace);\n    //fix the character case issue, such as FX.apollo <-> fx.apollo\n    namespace = namespaceUtil.normalizeNamespace(appId, namespace);\n\n    if (Strings.isNullOrEmpty(clientIp)) {\n      clientIp = tryToGetClientIp(request);\n    }\n\n    ApolloNotificationMessages clientMessages = transformMessages(messagesAsString);\n\n    List<Release> releases = Lists.newLinkedList();\n\n    String appClusterNameLoaded = clusterName;\n    if (!ConfigConsts.NO_APPID_PLACEHOLDER.equalsIgnoreCase(appId)) {\n      Release currentAppRelease = configService.loadConfig(appId, clientIp, appId, clusterName, namespace,\n          dataCenter, clientMessages);\n\n      if (currentAppRelease != null) {\n        releases.add(currentAppRelease);\n        //we have cluster search process, so the cluster name might be overridden\n        appClusterNameLoaded = currentAppRelease.getClusterName();\n      }\n    }\n\n    //if namespace does not belong to this appId, should check if there is a public configuration\n    if (!namespaceBelongsToAppId(appId, namespace)) {\n      Release publicRelease = this.findPublicConfig(appId, clientIp, clusterName, namespace,\n          dataCenter, clientMessages);\n      if (!Objects.isNull(publicRelease)) {\n        releases.add(publicRelease);\n      }\n    }\n\n    if (releases.isEmpty()) {\n      response.sendError(HttpServletResponse.SC_NOT_FOUND,\n          String.format(\n              \"Could not load configurations with appId: %s, clusterName: %s, namespace: %s\",\n              appId, clusterName, originalNamespace));\n      Tracer.logEvent(\"Apollo.Config.NotFound\",\n          assembleKey(appId, clusterName, originalNamespace, dataCenter));\n      return null;\n    }\n\n    auditReleases(appId, clusterName, dataCenter, clientIp, releases);\n\n    String mergedReleaseKey = releases.stream().map(Release::getReleaseKey)\n            .collect(Collectors.joining(ConfigConsts.CLUSTER_NAMESPACE_SEPARATOR));\n\n    if (mergedReleaseKey.equals(clientSideReleaseKey)) {\n      // Client side configuration is the same with server side, return 304\n      response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);\n      Tracer.logEvent(\"Apollo.Config.NotModified\",\n          assembleKey(appId, appClusterNameLoaded, originalNamespace, dataCenter));\n      return null;\n    }\n\n    ApolloConfig apolloConfig = new ApolloConfig(appId, appClusterNameLoaded, originalNamespace,\n        mergedReleaseKey);\n    apolloConfig.setConfigurations(mergeReleaseConfigurations(releases));\n\n    Tracer.logEvent(\"Apollo.Config.Found\", assembleKey(appId, appClusterNameLoaded,\n        originalNamespace, dataCenter));\n    return apolloConfig;\n  }\n\n  private boolean namespaceBelongsToAppId(String appId, String namespaceName) {\n    //Every app has an 'application' namespace\n    if (Objects.equals(ConfigConsts.NAMESPACE_APPLICATION, namespaceName)) {\n      return true;\n    }\n\n    //if no appId is present, then no other namespace belongs to it\n    if (ConfigConsts.NO_APPID_PLACEHOLDER.equalsIgnoreCase(appId)) {\n      return false;\n    }\n\n    AppNamespace appNamespace = appNamespaceService.findByAppIdAndNamespace(appId, namespaceName);\n\n    return appNamespace != null;\n  }\n\n  /**\n   * @param clientAppId the application which uses public config\n   * @param namespace   the namespace\n   * @param dataCenter  the datacenter\n   */\n  private Release findPublicConfig(String clientAppId, String clientIp, String clusterName,\n                                   String namespace, String dataCenter, ApolloNotificationMessages clientMessages) {\n    AppNamespace appNamespace = appNamespaceService.findPublicNamespaceByName(namespace);\n\n    //check whether the namespace's appId equals to current one\n    if (Objects.isNull(appNamespace) || Objects.equals(clientAppId, appNamespace.getAppId())) {\n      return null;\n    }\n\n    String publicConfigAppId = appNamespace.getAppId();\n\n    return configService.loadConfig(clientAppId, clientIp, publicConfigAppId, clusterName, namespace, dataCenter,\n        clientMessages);\n  }\n\n  /**\n   * Merge configurations of releases.\n   * Release in lower index override those in higher index\n   */\n  Map<String, String> mergeReleaseConfigurations(List<Release> releases) {\n    Map<String, String> result = Maps.newHashMap();\n    for (Release release : Lists.reverse(releases)) {\n      result.putAll(gson.fromJson(release.getConfigurations(), configurationTypeReference));\n    }\n    return result;\n  }\n\n  private String assembleKey(String appId, String cluster, String namespace, String dataCenter) {\n    List<String> keyParts = Lists.newArrayList(appId, cluster, namespace);\n    if (!Strings.isNullOrEmpty(dataCenter)) {\n      keyParts.add(dataCenter);\n    }\n    return keyParts.stream().collect(Collectors.joining(ConfigConsts.CLUSTER_NAMESPACE_SEPARATOR));\n  }\n\n  private void auditReleases(String appId, String cluster, String dataCenter, String clientIp,\n                             List<Release> releases) {\n    if (Strings.isNullOrEmpty(clientIp)) {\n      //no need to audit instance config when there is no ip\n      return;\n    }\n    for (Release release : releases) {\n      instanceConfigAuditUtil.audit(appId, cluster, dataCenter, clientIp, release.getAppId(),\n          release.getClusterName(),\n          release.getNamespaceName(), release.getReleaseKey());\n    }\n  }\n\n  private String tryToGetClientIp(HttpServletRequest request) {\n    String forwardedFor = request.getHeader(\"X-FORWARDED-FOR\");\n    if (!Strings.isNullOrEmpty(forwardedFor)) {\n      return X_FORWARDED_FOR_SPLITTER.splitToList(forwardedFor).get(0);\n    }\n    return request.getRemoteAddr();\n  }\n\n  ApolloNotificationMessages transformMessages(String messagesAsString) {\n    ApolloNotificationMessages notificationMessages = null;\n    if (!Strings.isNullOrEmpty(messagesAsString)) {\n      try {\n        notificationMessages = gson.fromJson(messagesAsString, ApolloNotificationMessages.class);\n      } catch (Throwable ex) {\n        Tracer.logError(ex);\n      }\n    }\n\n    return notificationMessages;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/controller/ConfigFileController.java",
    "content": "package com.ctrip.framework.apollo.configservice.controller;\n\nimport com.google.common.base.Joiner;\nimport com.google.common.base.Splitter;\nimport com.google.common.base.Strings;\nimport com.google.common.cache.Cache;\nimport com.google.common.cache.CacheBuilder;\nimport com.google.common.cache.RemovalListener;\nimport com.google.common.cache.RemovalNotification;\nimport com.google.common.cache.Weigher;\nimport com.google.common.collect.HashMultimap;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Multimap;\nimport com.google.common.collect.Multimaps;\nimport com.google.gson.Gson;\n\nimport com.ctrip.framework.apollo.biz.entity.ReleaseMessage;\nimport com.ctrip.framework.apollo.biz.grayReleaseRule.GrayReleaseRulesHolder;\nimport com.ctrip.framework.apollo.biz.message.ReleaseMessageListener;\nimport com.ctrip.framework.apollo.biz.message.Topics;\nimport com.ctrip.framework.apollo.configservice.util.NamespaceUtil;\nimport com.ctrip.framework.apollo.configservice.util.WatchKeysUtil;\nimport com.ctrip.framework.apollo.core.ConfigConsts;\nimport com.ctrip.framework.apollo.core.dto.ApolloConfig;\nimport com.ctrip.framework.apollo.core.utils.PropertiesUtil;\nimport com.ctrip.framework.apollo.tracer.Tracer;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.http.HttpHeaders;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Properties;\nimport java.util.Set;\nimport java.util.concurrent.TimeUnit;\n\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@RestController\n@RequestMapping(\"/configfiles\")\npublic class ConfigFileController implements ReleaseMessageListener {\n  private static final Logger logger = LoggerFactory.getLogger(ConfigFileController.class);\n  private static final Joiner STRING_JOINER = Joiner.on(ConfigConsts.CLUSTER_NAMESPACE_SEPARATOR);\n  private static final Splitter X_FORWARDED_FOR_SPLITTER = Splitter.on(\",\").omitEmptyStrings()\n      .trimResults();\n  private static final long MAX_CACHE_SIZE = 50 * 1024 * 1024; // 50MB\n  private static final long EXPIRE_AFTER_WRITE = 30;\n  private final HttpHeaders propertiesResponseHeaders;\n  private final HttpHeaders jsonResponseHeaders;\n  private final ResponseEntity<String> NOT_FOUND_RESPONSE;\n  private Cache<String, String> localCache;\n  private final Multimap<String, String>\n      watchedKeys2CacheKey = Multimaps.synchronizedSetMultimap(HashMultimap.create());\n  private final Multimap<String, String>\n      cacheKey2WatchedKeys = Multimaps.synchronizedSetMultimap(HashMultimap.create());\n  private static final Gson gson = new Gson();\n\n  @Autowired\n  private ConfigController configController;\n\n  @Autowired\n  private NamespaceUtil namespaceUtil;\n\n  @Autowired\n  private WatchKeysUtil watchKeysUtil;\n\n  @Autowired\n  private GrayReleaseRulesHolder grayReleaseRulesHolder;\n\n  public ConfigFileController() {\n    localCache = CacheBuilder.newBuilder()\n        .expireAfterWrite(EXPIRE_AFTER_WRITE, TimeUnit.MINUTES)\n        .weigher(new Weigher<String, String>() {\n          @Override\n          public int weigh(String key, String value) {\n            return value == null ? 0 : value.length();\n          }\n        })\n        .maximumWeight(MAX_CACHE_SIZE)\n        .removalListener(new RemovalListener<String, String>() {\n          @Override\n          public void onRemoval(RemovalNotification<String, String> notification) {\n            String cacheKey = notification.getKey();\n            logger.debug(\"removing cache key: {}\", cacheKey);\n            if (!cacheKey2WatchedKeys.containsKey(cacheKey)) {\n              return;\n            }\n            //create a new list to avoid ConcurrentModificationException\n            List<String> watchedKeys = new ArrayList<>(cacheKey2WatchedKeys.get(cacheKey));\n            for (String watchedKey : watchedKeys) {\n              watchedKeys2CacheKey.remove(watchedKey, cacheKey);\n            }\n            cacheKey2WatchedKeys.removeAll(cacheKey);\n            logger.debug(\"removed cache key: {}\", cacheKey);\n          }\n        })\n        .build();\n    propertiesResponseHeaders = new HttpHeaders();\n    propertiesResponseHeaders.add(\"Content-Type\", \"text/plain;charset=UTF-8\");\n    jsonResponseHeaders = new HttpHeaders();\n    jsonResponseHeaders.add(\"Content-Type\", \"application/json;charset=UTF-8\");\n    NOT_FOUND_RESPONSE = new ResponseEntity<>(HttpStatus.NOT_FOUND);\n  }\n\n  @RequestMapping(value = \"/{appId}/{clusterName}/{namespace:.+}\", method = RequestMethod.GET)\n  public ResponseEntity<String> queryConfigAsProperties(@PathVariable String appId,\n                                                        @PathVariable String clusterName,\n                                                        @PathVariable String namespace,\n                                                        @RequestParam(value = \"dataCenter\", required = false) String dataCenter,\n                                                        @RequestParam(value = \"ip\", required = false) String clientIp,\n                                                        HttpServletRequest request,\n                                                        HttpServletResponse response)\n      throws IOException {\n\n    String result =\n        queryConfig(ConfigFileOutputFormat.PROPERTIES, appId, clusterName, namespace, dataCenter,\n            clientIp, request, response);\n\n    if (result == null) {\n      return NOT_FOUND_RESPONSE;\n    }\n\n    return new ResponseEntity<>(result, propertiesResponseHeaders, HttpStatus.OK);\n  }\n\n  @RequestMapping(value = \"/json/{appId}/{clusterName}/{namespace:.+}\", method = RequestMethod.GET)\n  public ResponseEntity<String> queryConfigAsJson(@PathVariable String appId,\n                                                  @PathVariable String clusterName,\n                                                  @PathVariable String namespace,\n                                                  @RequestParam(value = \"dataCenter\", required = false) String dataCenter,\n                                                  @RequestParam(value = \"ip\", required = false) String clientIp,\n                                                  HttpServletRequest request,\n                                                  HttpServletResponse response) throws IOException {\n\n    String result =\n        queryConfig(ConfigFileOutputFormat.JSON, appId, clusterName, namespace, dataCenter,\n            clientIp, request, response);\n\n    if (result == null) {\n      return NOT_FOUND_RESPONSE;\n    }\n\n    return new ResponseEntity<>(result, jsonResponseHeaders, HttpStatus.OK);\n  }\n\n  String queryConfig(ConfigFileOutputFormat outputFormat, String appId, String clusterName,\n                     String namespace, String dataCenter, String clientIp,\n                     HttpServletRequest request,\n                     HttpServletResponse response) throws IOException {\n    //strip out .properties suffix\n    namespace = namespaceUtil.filterNamespaceName(namespace);\n    //fix the character case issue, such as FX.apollo <-> fx.apollo\n    namespace = namespaceUtil.normalizeNamespace(appId, namespace);\n\n    if (Strings.isNullOrEmpty(clientIp)) {\n      clientIp = tryToGetClientIp(request);\n    }\n\n    //1. check whether this client has gray release rules\n    boolean hasGrayReleaseRule = grayReleaseRulesHolder.hasGrayReleaseRule(appId, clientIp,\n        namespace);\n\n    String cacheKey = assembleCacheKey(outputFormat, appId, clusterName, namespace, dataCenter);\n\n    //2. try to load gray release and return\n    if (hasGrayReleaseRule) {\n      Tracer.logEvent(\"ConfigFile.Cache.GrayRelease\", cacheKey);\n      return loadConfig(outputFormat, appId, clusterName, namespace, dataCenter, clientIp,\n          request, response);\n    }\n\n    //3. if not gray release, check weather cache exists, if exists, return\n    String result = localCache.getIfPresent(cacheKey);\n\n    //4. if not exists, load from ConfigController\n    if (Strings.isNullOrEmpty(result)) {\n      Tracer.logEvent(\"ConfigFile.Cache.Miss\", cacheKey);\n      result = loadConfig(outputFormat, appId, clusterName, namespace, dataCenter, clientIp,\n          request, response);\n\n      if (result == null) {\n        return null;\n      }\n      //5. Double check if this client needs to load gray release, if yes, load from db again\n      //This step is mainly to avoid cache pollution\n      if (grayReleaseRulesHolder.hasGrayReleaseRule(appId, clientIp, namespace)) {\n        Tracer.logEvent(\"ConfigFile.Cache.GrayReleaseConflict\", cacheKey);\n        return loadConfig(outputFormat, appId, clusterName, namespace, dataCenter, clientIp,\n            request, response);\n      }\n\n      localCache.put(cacheKey, result);\n      logger.debug(\"adding cache for key: {}\", cacheKey);\n\n      Set<String> watchedKeys =\n          watchKeysUtil.assembleAllWatchKeys(appId, clusterName, namespace, dataCenter);\n\n      for (String watchedKey : watchedKeys) {\n        watchedKeys2CacheKey.put(watchedKey, cacheKey);\n      }\n\n      cacheKey2WatchedKeys.putAll(cacheKey, watchedKeys);\n      logger.debug(\"added cache for key: {}\", cacheKey);\n    } else {\n      Tracer.logEvent(\"ConfigFile.Cache.Hit\", cacheKey);\n    }\n\n    return result;\n  }\n\n  private String loadConfig(ConfigFileOutputFormat outputFormat, String appId, String clusterName,\n                            String namespace, String dataCenter, String clientIp,\n                            HttpServletRequest request,\n                            HttpServletResponse response) throws IOException {\n    ApolloConfig apolloConfig = configController.queryConfig(appId, clusterName, namespace,\n        dataCenter, \"-1\", clientIp, null, request, response);\n\n    if (apolloConfig == null || apolloConfig.getConfigurations() == null) {\n      return null;\n    }\n\n    String result = null;\n\n    switch (outputFormat) {\n      case PROPERTIES:\n        Properties properties = new Properties();\n        properties.putAll(apolloConfig.getConfigurations());\n        result = PropertiesUtil.toString(properties);\n        break;\n      case JSON:\n        result = gson.toJson(apolloConfig.getConfigurations());\n        break;\n    }\n\n    return result;\n  }\n\n  String assembleCacheKey(ConfigFileOutputFormat outputFormat, String appId, String clusterName,\n                          String namespace,\n                          String dataCenter) {\n    List<String> keyParts =\n        Lists.newArrayList(outputFormat.getValue(), appId, clusterName, namespace);\n    if (!Strings.isNullOrEmpty(dataCenter)) {\n      keyParts.add(dataCenter);\n    }\n    return STRING_JOINER.join(keyParts);\n  }\n\n  @Override\n  public void handleMessage(ReleaseMessage message, String channel) {\n    logger.info(\"message received - channel: {}, message: {}\", channel, message);\n\n    String content = message.getMessage();\n    if (!Topics.APOLLO_RELEASE_TOPIC.equals(channel) || Strings.isNullOrEmpty(content)) {\n      return;\n    }\n\n    if (!watchedKeys2CacheKey.containsKey(content)) {\n      return;\n    }\n\n    //create a new list to avoid ConcurrentModificationException\n    List<String> cacheKeys = new ArrayList<>(watchedKeys2CacheKey.get(content));\n\n    for (String cacheKey : cacheKeys) {\n      logger.debug(\"invalidate cache key: {}\", cacheKey);\n      localCache.invalidate(cacheKey);\n    }\n  }\n\n  enum ConfigFileOutputFormat {\n    PROPERTIES(\"properties\"), JSON(\"json\");\n\n    private String value;\n\n    ConfigFileOutputFormat(String value) {\n      this.value = value;\n    }\n\n    public String getValue() {\n      return value;\n    }\n  }\n\n  private String tryToGetClientIp(HttpServletRequest request) {\n    String forwardedFor = request.getHeader(\"X-FORWARDED-FOR\");\n    if (!Strings.isNullOrEmpty(forwardedFor)) {\n      return X_FORWARDED_FOR_SPLITTER.splitToList(forwardedFor).get(0);\n    }\n    return request.getRemoteAddr();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/controller/NotificationController.java",
    "content": "package com.ctrip.framework.apollo.configservice.controller;\n\nimport com.google.common.base.Splitter;\nimport com.google.common.base.Strings;\nimport com.google.common.collect.HashMultimap;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Multimap;\nimport com.google.common.collect.Multimaps;\n\nimport com.ctrip.framework.apollo.biz.entity.ReleaseMessage;\nimport com.ctrip.framework.apollo.biz.message.ReleaseMessageListener;\nimport com.ctrip.framework.apollo.biz.message.Topics;\nimport com.ctrip.framework.apollo.biz.utils.EntityManagerUtil;\nimport com.ctrip.framework.apollo.configservice.service.ReleaseMessageServiceWithCache;\nimport com.ctrip.framework.apollo.configservice.util.NamespaceUtil;\nimport com.ctrip.framework.apollo.configservice.util.WatchKeysUtil;\nimport com.ctrip.framework.apollo.core.ConfigConsts;\nimport com.ctrip.framework.apollo.core.dto.ApolloConfigNotification;\nimport com.ctrip.framework.apollo.tracer.Tracer;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\nimport org.springframework.web.context.request.async.DeferredResult;\n\nimport java.util.List;\nimport java.util.Set;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@Deprecated\n@RestController\n@RequestMapping(\"/notifications\")\npublic class NotificationController implements ReleaseMessageListener {\n  private static final Logger logger = LoggerFactory.getLogger(NotificationController.class);\n  private static final long TIMEOUT = 30 * 1000;//30 seconds\n  private final Multimap<String, DeferredResult<ResponseEntity<ApolloConfigNotification>>>\n      deferredResults = Multimaps.synchronizedSetMultimap(HashMultimap.create());\n  private static final ResponseEntity<ApolloConfigNotification>\n      NOT_MODIFIED_RESPONSE = new ResponseEntity<>(HttpStatus.NOT_MODIFIED);\n  private static final Splitter STRING_SPLITTER =\n      Splitter.on(ConfigConsts.CLUSTER_NAMESPACE_SEPARATOR).omitEmptyStrings();\n\n  @Autowired\n  private WatchKeysUtil watchKeysUtil;\n\n  @Autowired\n  private ReleaseMessageServiceWithCache releaseMessageService;\n\n  @Autowired\n  private EntityManagerUtil entityManagerUtil;\n\n  @Autowired\n  private NamespaceUtil namespaceUtil;\n\n  /**\n   * For single namespace notification, reserved for older version of apollo clients\n   *\n   * @param appId          the appId\n   * @param cluster        the cluster\n   * @param namespace      the namespace name\n   * @param dataCenter     the datacenter\n   * @param notificationId the notification id for the namespace\n   * @param clientIp       the client side ip\n   * @return a deferred result\n   */\n  @RequestMapping(method = RequestMethod.GET)\n  public DeferredResult<ResponseEntity<ApolloConfigNotification>> pollNotification(\n      @RequestParam(value = \"appId\") String appId,\n      @RequestParam(value = \"cluster\") String cluster,\n      @RequestParam(value = \"namespace\", defaultValue = ConfigConsts.NAMESPACE_APPLICATION) String namespace,\n      @RequestParam(value = \"dataCenter\", required = false) String dataCenter,\n      @RequestParam(value = \"notificationId\", defaultValue = \"-1\") long notificationId,\n      @RequestParam(value = \"ip\", required = false) String clientIp) {\n    //strip out .properties suffix\n    namespace = namespaceUtil.filterNamespaceName(namespace);\n\n    Set<String> watchedKeys = watchKeysUtil.assembleAllWatchKeys(appId, cluster, namespace, dataCenter);\n\n    DeferredResult<ResponseEntity<ApolloConfigNotification>> deferredResult =\n        new DeferredResult<>(TIMEOUT, NOT_MODIFIED_RESPONSE);\n\n    //check whether client is out-dated\n    ReleaseMessage latest = releaseMessageService.findLatestReleaseMessageForMessages(watchedKeys);\n\n    /**\n     * Manually close the entity manager.\n     * Since for async request, Spring won't do so until the request is finished,\n     * which is unacceptable since we are doing long polling - means the db connection would be hold\n     * for a very long time\n     */\n    entityManagerUtil.closeEntityManager();\n\n    if (latest != null && latest.getId() != notificationId) {\n      deferredResult.setResult(new ResponseEntity<>(\n          new ApolloConfigNotification(namespace, latest.getId()), HttpStatus.OK));\n    } else {\n      //register all keys\n      for (String key : watchedKeys) {\n        this.deferredResults.put(key, deferredResult);\n      }\n\n      deferredResult\n          .onTimeout(() -> logWatchedKeys(watchedKeys, \"Apollo.LongPoll.TimeOutKeys\"));\n\n      deferredResult.onCompletion(() -> {\n        //unregister all keys\n        for (String key : watchedKeys) {\n          deferredResults.remove(key, deferredResult);\n        }\n        logWatchedKeys(watchedKeys, \"Apollo.LongPoll.CompletedKeys\");\n      });\n\n      logWatchedKeys(watchedKeys, \"Apollo.LongPoll.RegisteredKeys\");\n      logger.debug(\"Listening {} from appId: {}, cluster: {}, namespace: {}, datacenter: {}\",\n          watchedKeys, appId, cluster, namespace, dataCenter);\n    }\n\n    return deferredResult;\n  }\n\n  @Override\n  public void handleMessage(ReleaseMessage message, String channel) {\n    logger.info(\"message received - channel: {}, message: {}\", channel, message);\n\n    String content = message.getMessage();\n    Tracer.logEvent(\"Apollo.LongPoll.Messages\", content);\n    if (!Topics.APOLLO_RELEASE_TOPIC.equals(channel) || Strings.isNullOrEmpty(content)) {\n      return;\n    }\n    List<String> keys = STRING_SPLITTER.splitToList(content);\n    //message should be appId+cluster+namespace\n    if (keys.size() != 3) {\n      logger.error(\"message format invalid - {}\", content);\n      return;\n    }\n\n    ResponseEntity<ApolloConfigNotification> notification =\n        new ResponseEntity<>(\n            new ApolloConfigNotification(keys.get(2), message.getId()), HttpStatus.OK);\n\n    if (!deferredResults.containsKey(content)) {\n      return;\n    }\n    //create a new list to avoid ConcurrentModificationException\n    List<DeferredResult<ResponseEntity<ApolloConfigNotification>>> results =\n        Lists.newArrayList(deferredResults.get(content));\n    logger.debug(\"Notify {} clients for key {}\", results.size(), content);\n\n    for (DeferredResult<ResponseEntity<ApolloConfigNotification>> result : results) {\n      result.setResult(notification);\n    }\n    logger.debug(\"Notification completed\");\n  }\n\n  private void logWatchedKeys(Set<String> watchedKeys, String eventName) {\n    for (String watchedKey : watchedKeys) {\n      Tracer.logEvent(eventName, watchedKey);\n    }\n  }\n}\n\n"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/controller/NotificationControllerV2.java",
    "content": "package com.ctrip.framework.apollo.configservice.controller;\n\nimport com.google.common.base.Function;\nimport com.google.common.base.Splitter;\nimport com.google.common.base.Strings;\nimport com.google.common.collect.HashMultimap;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport com.google.common.collect.Multimap;\nimport com.google.common.collect.Multimaps;\nimport com.google.common.collect.Sets;\nimport com.google.gson.Gson;\nimport com.google.gson.reflect.TypeToken;\n\nimport com.ctrip.framework.apollo.biz.config.BizConfig;\nimport com.ctrip.framework.apollo.biz.entity.ReleaseMessage;\nimport com.ctrip.framework.apollo.biz.message.ReleaseMessageListener;\nimport com.ctrip.framework.apollo.biz.message.Topics;\nimport com.ctrip.framework.apollo.biz.utils.EntityManagerUtil;\nimport com.ctrip.framework.apollo.common.exception.BadRequestException;\nimport com.ctrip.framework.apollo.configservice.service.ReleaseMessageServiceWithCache;\nimport com.ctrip.framework.apollo.configservice.util.NamespaceUtil;\nimport com.ctrip.framework.apollo.configservice.util.WatchKeysUtil;\nimport com.ctrip.framework.apollo.configservice.wrapper.DeferredResultWrapper;\nimport com.ctrip.framework.apollo.core.ConfigConsts;\nimport com.ctrip.framework.apollo.core.dto.ApolloConfigNotification;\nimport com.ctrip.framework.apollo.core.utils.ApolloThreadFactory;\nimport com.ctrip.framework.apollo.tracer.Tracer;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.util.CollectionUtils;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\nimport org.springframework.web.context.request.async.DeferredResult;\n\nimport java.lang.reflect.Type;\nimport java.util.Collection;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Set;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@RestController\n@RequestMapping(\"/notifications/v2\")\npublic class NotificationControllerV2 implements ReleaseMessageListener {\n  private static final Logger logger = LoggerFactory.getLogger(NotificationControllerV2.class);\n  private final Multimap<String, DeferredResultWrapper> deferredResults =\n      Multimaps.synchronizedSetMultimap(HashMultimap.create());\n  private static final Splitter STRING_SPLITTER =\n      Splitter.on(ConfigConsts.CLUSTER_NAMESPACE_SEPARATOR).omitEmptyStrings();\n  private static final Type notificationsTypeReference =\n      new TypeToken<List<ApolloConfigNotification>>() {\n      }.getType();\n\n  private final ExecutorService largeNotificationBatchExecutorService;\n\n  @Autowired\n  private WatchKeysUtil watchKeysUtil;\n\n  @Autowired\n  private ReleaseMessageServiceWithCache releaseMessageService;\n\n  @Autowired\n  private EntityManagerUtil entityManagerUtil;\n\n  @Autowired\n  private NamespaceUtil namespaceUtil;\n\n  @Autowired\n  private Gson gson;\n\n  @Autowired\n  private BizConfig bizConfig;\n\n  public NotificationControllerV2() {\n    largeNotificationBatchExecutorService = Executors.newSingleThreadExecutor(ApolloThreadFactory.create\n        (\"NotificationControllerV2\", true));\n  }\n\n  @RequestMapping(method = RequestMethod.GET)\n  public DeferredResult<ResponseEntity<List<ApolloConfigNotification>>> pollNotification(\n      @RequestParam(value = \"appId\") String appId,\n      @RequestParam(value = \"cluster\") String cluster,\n      @RequestParam(value = \"notifications\") String notificationsAsString,\n      @RequestParam(value = \"dataCenter\", required = false) String dataCenter,\n      @RequestParam(value = \"ip\", required = false) String clientIp) {\n    List<ApolloConfigNotification> notifications = null;\n\n    try {\n      notifications =\n          gson.fromJson(notificationsAsString, notificationsTypeReference);\n    } catch (Throwable ex) {\n      Tracer.logError(ex);\n    }\n\n    if (CollectionUtils.isEmpty(notifications)) {\n      throw new BadRequestException(\"Invalid format of notifications: \" + notificationsAsString);\n    }\n\n    DeferredResultWrapper deferredResultWrapper = new DeferredResultWrapper();\n    Set<String> namespaces = Sets.newHashSet();\n    Map<String, Long> clientSideNotifications = Maps.newHashMap();\n    Map<String, ApolloConfigNotification> filteredNotifications = filterNotifications(appId, notifications);\n\n    for (Map.Entry<String, ApolloConfigNotification> notificationEntry : filteredNotifications.entrySet()) {\n      String normalizedNamespace = notificationEntry.getKey();\n      ApolloConfigNotification notification = notificationEntry.getValue();\n      namespaces.add(normalizedNamespace);\n      clientSideNotifications.put(normalizedNamespace, notification.getNotificationId());\n      if (!Objects.equals(notification.getNamespaceName(), normalizedNamespace)) {\n        deferredResultWrapper.recordNamespaceNameNormalizedResult(notification.getNamespaceName(), normalizedNamespace);\n      }\n    }\n\n    if (CollectionUtils.isEmpty(namespaces)) {\n      throw new BadRequestException(\"Invalid format of notifications: \" + notificationsAsString);\n    }\n\n    Multimap<String, String> watchedKeysMap =\n        watchKeysUtil.assembleAllWatchKeys(appId, cluster, namespaces, dataCenter);\n\n    Set<String> watchedKeys = Sets.newHashSet(watchedKeysMap.values());\n\n    List<ReleaseMessage> latestReleaseMessages =\n        releaseMessageService.findLatestReleaseMessagesGroupByMessages(watchedKeys);\n\n    /**\n     * Manually close the entity manager.\n     * Since for async request, Spring won't do so until the request is finished,\n     * which is unacceptable since we are doing long polling - means the db connection would be hold\n     * for a very long time\n     */\n    entityManagerUtil.closeEntityManager();\n\n    List<ApolloConfigNotification> newNotifications =\n        getApolloConfigNotifications(namespaces, clientSideNotifications, watchedKeysMap,\n            latestReleaseMessages);\n\n    if (!CollectionUtils.isEmpty(newNotifications)) {\n      deferredResultWrapper.setResult(newNotifications);\n    } else {\n      deferredResultWrapper\n          .onTimeout(() -> logWatchedKeys(watchedKeys, \"Apollo.LongPoll.TimeOutKeys\"));\n\n      deferredResultWrapper.onCompletion(() -> {\n        //unregister all keys\n        for (String key : watchedKeys) {\n          deferredResults.remove(key, deferredResultWrapper);\n        }\n        logWatchedKeys(watchedKeys, \"Apollo.LongPoll.CompletedKeys\");\n      });\n\n      //register all keys\n      for (String key : watchedKeys) {\n        this.deferredResults.put(key, deferredResultWrapper);\n      }\n\n      logWatchedKeys(watchedKeys, \"Apollo.LongPoll.RegisteredKeys\");\n      logger.debug(\"Listening {} from appId: {}, cluster: {}, namespace: {}, datacenter: {}\",\n          watchedKeys, appId, cluster, namespaces, dataCenter);\n    }\n\n    return deferredResultWrapper.getResult();\n  }\n\n  private Map<String, ApolloConfigNotification> filterNotifications(String appId,\n                                                                    List<ApolloConfigNotification> notifications) {\n    Map<String, ApolloConfigNotification> filteredNotifications = Maps.newHashMap();\n    for (ApolloConfigNotification notification : notifications) {\n      if (Strings.isNullOrEmpty(notification.getNamespaceName())) {\n        continue;\n      }\n      //strip out .properties suffix\n      String originalNamespace = namespaceUtil.filterNamespaceName(notification.getNamespaceName());\n      notification.setNamespaceName(originalNamespace);\n      //fix the character case issue, such as FX.apollo <-> fx.apollo\n      String normalizedNamespace = namespaceUtil.normalizeNamespace(appId, originalNamespace);\n\n      // in case client side namespace name has character case issue and has difference notification ids\n      // such as FX.apollo = 1 but fx.apollo = 2, we should let FX.apollo have the chance to update its notification id\n      // which means we should record FX.apollo = 1 here and ignore fx.apollo = 2\n      if (filteredNotifications.containsKey(normalizedNamespace) &&\n          filteredNotifications.get(normalizedNamespace).getNotificationId() < notification.getNotificationId()) {\n        continue;\n      }\n\n      filteredNotifications.put(normalizedNamespace, notification);\n    }\n    return filteredNotifications;\n  }\n\n  private List<ApolloConfigNotification> getApolloConfigNotifications(Set<String> namespaces,\n                                                                      Map<String, Long> clientSideNotifications,\n                                                                      Multimap<String, String> watchedKeysMap,\n                                                                      List<ReleaseMessage> latestReleaseMessages) {\n    List<ApolloConfigNotification> newNotifications = Lists.newArrayList();\n    if (!CollectionUtils.isEmpty(latestReleaseMessages)) {\n      Map<String, Long> latestNotifications = Maps.newHashMap();\n      for (ReleaseMessage releaseMessage : latestReleaseMessages) {\n        latestNotifications.put(releaseMessage.getMessage(), releaseMessage.getId());\n      }\n\n      for (String namespace : namespaces) {\n        long clientSideId = clientSideNotifications.get(namespace);\n        long latestId = ConfigConsts.NOTIFICATION_ID_PLACEHOLDER;\n        Collection<String> namespaceWatchedKeys = watchedKeysMap.get(namespace);\n        for (String namespaceWatchedKey : namespaceWatchedKeys) {\n          long namespaceNotificationId =\n              latestNotifications.getOrDefault(namespaceWatchedKey, ConfigConsts.NOTIFICATION_ID_PLACEHOLDER);\n          if (namespaceNotificationId > latestId) {\n            latestId = namespaceNotificationId;\n          }\n        }\n        if (latestId > clientSideId) {\n          ApolloConfigNotification notification = new ApolloConfigNotification(namespace, latestId);\n          namespaceWatchedKeys.stream().filter(latestNotifications::containsKey).forEach(namespaceWatchedKey ->\n              notification.addMessage(namespaceWatchedKey, latestNotifications.get(namespaceWatchedKey)));\n          newNotifications.add(notification);\n        }\n      }\n    }\n    return newNotifications;\n  }\n\n  @Override\n  public void handleMessage(ReleaseMessage message, String channel) {\n    logger.info(\"message received - channel: {}, message: {}\", channel, message);\n\n    String content = message.getMessage();\n    Tracer.logEvent(\"Apollo.LongPoll.Messages\", content);\n    if (!Topics.APOLLO_RELEASE_TOPIC.equals(channel) || Strings.isNullOrEmpty(content)) {\n      return;\n    }\n\n    String changedNamespace = retrieveNamespaceFromReleaseMessage.apply(content);\n\n    if (Strings.isNullOrEmpty(changedNamespace)) {\n      logger.error(\"message format invalid - {}\", content);\n      return;\n    }\n\n    if (!deferredResults.containsKey(content)) {\n      return;\n    }\n\n    //create a new list to avoid ConcurrentModificationException\n    List<DeferredResultWrapper> results = Lists.newArrayList(deferredResults.get(content));\n\n    ApolloConfigNotification configNotification = new ApolloConfigNotification(changedNamespace, message.getId());\n    configNotification.addMessage(content, message.getId());\n\n    //do async notification if too many clients\n    if (results.size() > bizConfig.releaseMessageNotificationBatch()) {\n      largeNotificationBatchExecutorService.submit(() -> {\n        logger.debug(\"Async notify {} clients for key {} with batch {}\", results.size(), content,\n            bizConfig.releaseMessageNotificationBatch());\n        for (int i = 0; i < results.size(); i++) {\n          if (i > 0 && i % bizConfig.releaseMessageNotificationBatch() == 0) {\n            try {\n              TimeUnit.MILLISECONDS.sleep(bizConfig.releaseMessageNotificationBatchIntervalInMilli());\n            } catch (InterruptedException e) {\n              //ignore\n            }\n          }\n          logger.debug(\"Async notify {}\", results.get(i));\n          results.get(i).setResult(configNotification);\n        }\n      });\n      return;\n    }\n\n    logger.debug(\"Notify {} clients for key {}\", results.size(), content);\n\n    for (DeferredResultWrapper result : results) {\n      result.setResult(configNotification);\n    }\n    logger.debug(\"Notification completed\");\n  }\n\n  private static final Function<String, String> retrieveNamespaceFromReleaseMessage =\n      releaseMessage -> {\n        if (Strings.isNullOrEmpty(releaseMessage)) {\n          return null;\n        }\n        List<String> keys = STRING_SPLITTER.splitToList(releaseMessage);\n        //message should be appId+cluster+namespace\n        if (keys.size() != 3) {\n          logger.error(\"message format invalid - {}\", releaseMessage);\n          return null;\n        }\n        return keys.get(2);\n      };\n\n  private void logWatchedKeys(Set<String> watchedKeys, String eventName) {\n    for (String watchedKey : watchedKeys) {\n      Tracer.logEvent(eventName, watchedKey);\n    }\n  }\n}\n\n"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/service/AppNamespaceServiceWithCache.java",
    "content": "package com.ctrip.framework.apollo.configservice.service;\n\nimport com.ctrip.framework.apollo.configservice.wrapper.CaseInsensitiveMapWrapper;\nimport com.ctrip.framework.apollo.core.utils.StringUtils;\nimport com.google.common.base.Joiner;\nimport com.google.common.base.Preconditions;\nimport com.google.common.base.Strings;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport com.google.common.collect.Sets;\n\nimport com.ctrip.framework.apollo.biz.config.BizConfig;\nimport com.ctrip.framework.apollo.biz.repository.AppNamespaceRepository;\nimport com.ctrip.framework.apollo.common.entity.AppNamespace;\nimport com.ctrip.framework.apollo.core.ConfigConsts;\nimport com.ctrip.framework.apollo.core.utils.ApolloThreadFactory;\nimport com.ctrip.framework.apollo.tracer.Tracer;\nimport com.ctrip.framework.apollo.tracer.spi.Transaction;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.InitializingBean;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.util.CollectionUtils;\n\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@Service\npublic class AppNamespaceServiceWithCache implements InitializingBean {\n  private static final Logger logger = LoggerFactory.getLogger(AppNamespaceServiceWithCache.class);\n  private static final Joiner STRING_JOINER = Joiner.on(ConfigConsts.CLUSTER_NAMESPACE_SEPARATOR)\n      .skipNulls();\n  @Autowired\n  private AppNamespaceRepository appNamespaceRepository;\n\n  @Autowired\n  private BizConfig bizConfig;\n\n  private int scanInterval;\n  private TimeUnit scanIntervalTimeUnit;\n  private int rebuildInterval;\n  private TimeUnit rebuildIntervalTimeUnit;\n  private ScheduledExecutorService scheduledExecutorService;\n  private long maxIdScanned;\n\n  //store namespaceName -> AppNamespace\n  private CaseInsensitiveMapWrapper<AppNamespace> publicAppNamespaceCache;\n\n  //store appId+namespaceName -> AppNamespace\n  private CaseInsensitiveMapWrapper<AppNamespace> appNamespaceCache;\n\n  //store id -> AppNamespace\n  private Map<Long, AppNamespace> appNamespaceIdCache;\n\n  public AppNamespaceServiceWithCache() {\n    initialize();\n  }\n\n  private void initialize() {\n    maxIdScanned = 0;\n    publicAppNamespaceCache = new CaseInsensitiveMapWrapper<>(Maps.newConcurrentMap());\n    appNamespaceCache = new CaseInsensitiveMapWrapper<>(Maps.newConcurrentMap());\n    appNamespaceIdCache = Maps.newConcurrentMap();\n    scheduledExecutorService = Executors.newScheduledThreadPool(1, ApolloThreadFactory\n        .create(\"AppNamespaceServiceWithCache\", true));\n  }\n\n  public AppNamespace findByAppIdAndNamespace(String appId, String namespaceName) {\n    Preconditions.checkArgument(!StringUtils.isContainEmpty(appId, namespaceName), \"appId and namespaceName must not be empty\");\n    return appNamespaceCache.get(STRING_JOINER.join(appId, namespaceName));\n  }\n\n  public List<AppNamespace> findByAppIdAndNamespaces(String appId, Set<String> namespaceNames) {\n    Preconditions.checkArgument(!Strings.isNullOrEmpty(appId), \"appId must not be null\");\n    if (namespaceNames == null || namespaceNames.isEmpty()) {\n      return Collections.emptyList();\n    }\n    List<AppNamespace> result = Lists.newArrayList();\n    for (String namespaceName : namespaceNames) {\n      AppNamespace appNamespace = appNamespaceCache.get(STRING_JOINER.join(appId, namespaceName));\n      if (appNamespace != null) {\n        result.add(appNamespace);\n      }\n    }\n    return result;\n  }\n\n  public AppNamespace findPublicNamespaceByName(String namespaceName) {\n    Preconditions.checkArgument(!Strings.isNullOrEmpty(namespaceName), \"namespaceName must not be empty\");\n    return publicAppNamespaceCache.get(namespaceName);\n  }\n\n  public List<AppNamespace> findPublicNamespacesByNames(Set<String> namespaceNames) {\n    if (namespaceNames == null || namespaceNames.isEmpty()) {\n      return Collections.emptyList();\n    }\n\n    List<AppNamespace> result = Lists.newArrayList();\n    for (String namespaceName : namespaceNames) {\n      AppNamespace appNamespace = publicAppNamespaceCache.get(namespaceName);\n      if (appNamespace != null) {\n        result.add(appNamespace);\n      }\n    }\n    return result;\n  }\n\n  @Override\n  public void afterPropertiesSet() throws Exception {\n    populateDataBaseInterval();\n    scanNewAppNamespaces(); //block the startup process until load finished\n    scheduledExecutorService.scheduleAtFixedRate(() -> {\n      Transaction transaction = Tracer.newTransaction(\"Apollo.AppNamespaceServiceWithCache\",\n          \"rebuildCache\");\n      try {\n        this.updateAndDeleteCache();\n        transaction.setStatus(Transaction.SUCCESS);\n      } catch (Throwable ex) {\n        transaction.setStatus(ex);\n        logger.error(\"Rebuild cache failed\", ex);\n      } finally {\n        transaction.complete();\n      }\n    }, rebuildInterval, rebuildInterval, rebuildIntervalTimeUnit);\n    scheduledExecutorService.scheduleWithFixedDelay(this::scanNewAppNamespaces, scanInterval,\n        scanInterval, scanIntervalTimeUnit);\n  }\n\n  private void scanNewAppNamespaces() {\n    Transaction transaction = Tracer.newTransaction(\"Apollo.AppNamespaceServiceWithCache\",\n        \"scanNewAppNamespaces\");\n    try {\n      this.loadNewAppNamespaces();\n      transaction.setStatus(Transaction.SUCCESS);\n    } catch (Throwable ex) {\n      transaction.setStatus(ex);\n      logger.error(\"Load new app namespaces failed\", ex);\n    } finally {\n      transaction.complete();\n    }\n  }\n\n  //for those new app namespaces\n  private void loadNewAppNamespaces() {\n    boolean hasMore = true;\n    while (hasMore && !Thread.currentThread().isInterrupted()) {\n      //current batch is 500\n      List<AppNamespace> appNamespaces = appNamespaceRepository\n          .findFirst500ByIdGreaterThanOrderByIdAsc(maxIdScanned);\n      if (CollectionUtils.isEmpty(appNamespaces)) {\n        break;\n      }\n      mergeAppNamespaces(appNamespaces);\n      int scanned = appNamespaces.size();\n      maxIdScanned = appNamespaces.get(scanned - 1).getId();\n      hasMore = scanned == 500;\n      logger.info(\"Loaded {} new app namespaces with startId {}\", scanned, maxIdScanned);\n    }\n  }\n\n  private void mergeAppNamespaces(List<AppNamespace> appNamespaces) {\n    for (AppNamespace appNamespace : appNamespaces) {\n      appNamespaceCache.put(assembleAppNamespaceKey(appNamespace), appNamespace);\n      appNamespaceIdCache.put(appNamespace.getId(), appNamespace);\n      if (appNamespace.isPublic()) {\n        publicAppNamespaceCache.put(appNamespace.getName(), appNamespace);\n      }\n    }\n  }\n\n  //for those updated or deleted app namespaces\n  private void updateAndDeleteCache() {\n    List<Long> ids = Lists.newArrayList(appNamespaceIdCache.keySet());\n    if (CollectionUtils.isEmpty(ids)) {\n      return;\n    }\n    List<List<Long>> partitionIds = Lists.partition(ids, 500);\n    for (List<Long> toRebuild : partitionIds) {\n      Iterable<AppNamespace> appNamespaces = appNamespaceRepository.findAll(toRebuild);\n\n      if (appNamespaces == null) {\n        continue;\n      }\n\n      //handle updated\n      Set<Long> foundIds = handleUpdatedAppNamespaces(appNamespaces);\n\n      //handle deleted\n      handleDeletedAppNamespaces(Sets.difference(Sets.newHashSet(toRebuild), foundIds));\n    }\n  }\n\n  //for those updated app namespaces\n  private Set<Long> handleUpdatedAppNamespaces(Iterable<AppNamespace> appNamespaces) {\n    Set<Long> foundIds = Sets.newHashSet();\n    for (AppNamespace appNamespace : appNamespaces) {\n      foundIds.add(appNamespace.getId());\n      AppNamespace thatInCache = appNamespaceIdCache.get(appNamespace.getId());\n      if (thatInCache != null && appNamespace.getDataChangeLastModifiedTime().after(thatInCache\n          .getDataChangeLastModifiedTime())) {\n        appNamespaceIdCache.put(appNamespace.getId(), appNamespace);\n        String oldKey = assembleAppNamespaceKey(thatInCache);\n        String newKey = assembleAppNamespaceKey(appNamespace);\n        appNamespaceCache.put(newKey, appNamespace);\n\n        //in case appId or namespaceName changes\n        if (!newKey.equals(oldKey)) {\n          appNamespaceCache.remove(oldKey);\n        }\n\n        if (appNamespace.isPublic()) {\n          publicAppNamespaceCache.put(appNamespace.getName(), appNamespace);\n\n          //in case namespaceName changes\n          if (!appNamespace.getName().equals(thatInCache.getName()) && thatInCache.isPublic()) {\n            publicAppNamespaceCache.remove(thatInCache.getName());\n          }\n        } else if (thatInCache.isPublic()) {\n          //just in case isPublic changes\n          publicAppNamespaceCache.remove(thatInCache.getName());\n        }\n        logger.info(\"Found AppNamespace changes, old: {}, new: {}\", thatInCache, appNamespace);\n      }\n    }\n    return foundIds;\n  }\n\n  //for those deleted app namespaces\n  private void handleDeletedAppNamespaces(Set<Long> deletedIds) {\n    if (CollectionUtils.isEmpty(deletedIds)) {\n      return;\n    }\n    for (Long deletedId : deletedIds) {\n      AppNamespace deleted = appNamespaceIdCache.remove(deletedId);\n      if (deleted == null) {\n        continue;\n      }\n      appNamespaceCache.remove(assembleAppNamespaceKey(deleted));\n      if (deleted.isPublic()) {\n        publicAppNamespaceCache.remove(deleted.getName());\n      }\n      logger.info(\"Found AppNamespace deleted, {}\", deleted);\n    }\n  }\n\n  private String assembleAppNamespaceKey(AppNamespace appNamespace) {\n    return STRING_JOINER.join(appNamespace.getAppId(), appNamespace.getName());\n  }\n\n  private void populateDataBaseInterval() {\n    scanInterval = bizConfig.appNamespaceCacheScanInterval();\n    scanIntervalTimeUnit = bizConfig.appNamespaceCacheScanIntervalTimeUnit();\n    rebuildInterval = bizConfig.appNamespaceCacheRebuildInterval();\n    rebuildIntervalTimeUnit = bizConfig.appNamespaceCacheRebuildIntervalTimeUnit();\n  }\n\n  //only for test use\n  private void reset() throws Exception {\n    scheduledExecutorService.shutdownNow();\n    initialize();\n    afterPropertiesSet();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/service/ReleaseMessageServiceWithCache.java",
    "content": "package com.ctrip.framework.apollo.configservice.service;\n\nimport com.google.common.base.Strings;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\n\nimport com.ctrip.framework.apollo.biz.config.BizConfig;\nimport com.ctrip.framework.apollo.biz.entity.ReleaseMessage;\nimport com.ctrip.framework.apollo.biz.message.ReleaseMessageListener;\nimport com.ctrip.framework.apollo.biz.message.Topics;\nimport com.ctrip.framework.apollo.biz.repository.ReleaseMessageRepository;\nimport com.ctrip.framework.apollo.core.utils.ApolloThreadFactory;\nimport com.ctrip.framework.apollo.tracer.Tracer;\nimport com.ctrip.framework.apollo.tracer.spi.Transaction;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.InitializingBean;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.util.CollectionUtils;\n\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Set;\nimport java.util.concurrent.ConcurrentMap;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@Service\npublic class ReleaseMessageServiceWithCache implements ReleaseMessageListener, InitializingBean {\n  private static final Logger logger = LoggerFactory.getLogger(ReleaseMessageServiceWithCache\n      .class);\n  @Autowired\n  private ReleaseMessageRepository releaseMessageRepository;\n\n  @Autowired\n  private BizConfig bizConfig;\n\n  private int scanInterval;\n  private TimeUnit scanIntervalTimeUnit;\n\n  private volatile long maxIdScanned;\n\n  private ConcurrentMap<String, ReleaseMessage> releaseMessageCache;\n\n  private AtomicBoolean doScan;\n  private ExecutorService executorService;\n\n  public ReleaseMessageServiceWithCache() {\n    initialize();\n  }\n\n  private void initialize() {\n    releaseMessageCache = Maps.newConcurrentMap();\n    doScan = new AtomicBoolean(true);\n    executorService = Executors.newSingleThreadExecutor(ApolloThreadFactory\n        .create(\"ReleaseMessageServiceWithCache\", true));\n  }\n\n  public ReleaseMessage findLatestReleaseMessageForMessages(Set<String> messages) {\n    if (CollectionUtils.isEmpty(messages)) {\n      return null;\n    }\n\n    long maxReleaseMessageId = 0;\n    ReleaseMessage result = null;\n    for (String message : messages) {\n      ReleaseMessage releaseMessage = releaseMessageCache.get(message);\n      if (releaseMessage != null && releaseMessage.getId() > maxReleaseMessageId) {\n        maxReleaseMessageId = releaseMessage.getId();\n        result = releaseMessage;\n      }\n    }\n\n    return result;\n  }\n\n  public List<ReleaseMessage> findLatestReleaseMessagesGroupByMessages(Set<String> messages) {\n    if (CollectionUtils.isEmpty(messages)) {\n      return Collections.emptyList();\n    }\n    List<ReleaseMessage> releaseMessages = Lists.newArrayList();\n\n    for (String message : messages) {\n      ReleaseMessage releaseMessage = releaseMessageCache.get(message);\n      if (releaseMessage != null) {\n        releaseMessages.add(releaseMessage);\n      }\n    }\n\n    return releaseMessages;\n  }\n\n  @Override\n  public void handleMessage(ReleaseMessage message, String channel) {\n    //Could stop once the ReleaseMessageScanner starts to work\n    doScan.set(false);\n    logger.info(\"message received - channel: {}, message: {}\", channel, message);\n\n    String content = message.getMessage();\n    Tracer.logEvent(\"Apollo.ReleaseMessageService.UpdateCache\", String.valueOf(message.getId()));\n    if (!Topics.APOLLO_RELEASE_TOPIC.equals(channel) || Strings.isNullOrEmpty(content)) {\n      return;\n    }\n\n    long gap = message.getId() - maxIdScanned;\n    if (gap == 1) {\n      mergeReleaseMessage(message);\n    } else if (gap > 1) {\n      //gap found!\n      loadReleaseMessages(maxIdScanned);\n    }\n  }\n\n  @Override\n  public void afterPropertiesSet() throws Exception {\n    populateDataBaseInterval();\n    //block the startup process until load finished\n    //this should happen before ReleaseMessageScanner due to autowire\n    loadReleaseMessages(0);\n\n    executorService.submit(() -> {\n      while (doScan.get() && !Thread.currentThread().isInterrupted()) {\n        Transaction transaction = Tracer.newTransaction(\"Apollo.ReleaseMessageServiceWithCache\",\n            \"scanNewReleaseMessages\");\n        try {\n          loadReleaseMessages(maxIdScanned);\n          transaction.setStatus(Transaction.SUCCESS);\n        } catch (Throwable ex) {\n          transaction.setStatus(ex);\n          logger.error(\"Scan new release messages failed\", ex);\n        } finally {\n          transaction.complete();\n        }\n        try {\n          scanIntervalTimeUnit.sleep(scanInterval);\n        } catch (InterruptedException e) {\n          //ignore\n        }\n      }\n    });\n  }\n\n  private synchronized void mergeReleaseMessage(ReleaseMessage releaseMessage) {\n    ReleaseMessage old = releaseMessageCache.get(releaseMessage.getMessage());\n    if (old == null || releaseMessage.getId() > old.getId()) {\n      releaseMessageCache.put(releaseMessage.getMessage(), releaseMessage);\n      maxIdScanned = releaseMessage.getId();\n    }\n  }\n\n  private void loadReleaseMessages(long startId) {\n    boolean hasMore = true;\n    while (hasMore && !Thread.currentThread().isInterrupted()) {\n      //current batch is 500\n      List<ReleaseMessage> releaseMessages = releaseMessageRepository\n          .findFirst500ByIdGreaterThanOrderByIdAsc(startId);\n      if (CollectionUtils.isEmpty(releaseMessages)) {\n        break;\n      }\n      releaseMessages.forEach(this::mergeReleaseMessage);\n      int scanned = releaseMessages.size();\n      startId = releaseMessages.get(scanned - 1).getId();\n      hasMore = scanned == 500;\n      logger.info(\"Loaded {} release messages with startId {}\", scanned, startId);\n    }\n  }\n\n  private void populateDataBaseInterval() {\n    scanInterval = bizConfig.releaseMessageCacheScanInterval();\n    scanIntervalTimeUnit = bizConfig.releaseMessageCacheScanIntervalTimeUnit();\n  }\n\n  //only for test use\n  private void reset() throws Exception {\n    executorService.shutdownNow();\n    initialize();\n    afterPropertiesSet();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/service/config/AbstractConfigService.java",
    "content": "package com.ctrip.framework.apollo.configservice.service.config;\n\nimport com.ctrip.framework.apollo.biz.entity.Release;\nimport com.ctrip.framework.apollo.biz.grayReleaseRule.GrayReleaseRulesHolder;\nimport com.ctrip.framework.apollo.core.ConfigConsts;\nimport com.ctrip.framework.apollo.core.dto.ApolloNotificationMessages;\n\nimport com.google.common.base.Strings;\n\nimport java.util.Map;\nimport java.util.Objects;\nimport org.springframework.beans.factory.annotation.Autowired;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic abstract class AbstractConfigService implements ConfigService {\n  @Autowired\n  private GrayReleaseRulesHolder grayReleaseRulesHolder;\n\n  @Override\n  public Release loadConfig(String clientAppId, String clientIp, String configAppId, String configClusterName,\n      String configNamespace, String dataCenter, ApolloNotificationMessages clientMessages) {\n    // load from specified cluster fist\n    if (!Objects.equals(ConfigConsts.CLUSTER_NAME_DEFAULT, configClusterName)) {\n      Release clusterRelease = findRelease(clientAppId, clientIp, configAppId, configClusterName, configNamespace,\n          clientMessages);\n\n      if (!Objects.isNull(clusterRelease)) {\n        return clusterRelease;\n      }\n    }\n\n    // try to load via data center\n    if (!Strings.isNullOrEmpty(dataCenter) && !Objects.equals(dataCenter, configClusterName)) {\n      Release dataCenterRelease = findRelease(clientAppId, clientIp, configAppId, dataCenter, configNamespace,\n          clientMessages);\n      if (!Objects.isNull(dataCenterRelease)) {\n        return dataCenterRelease;\n      }\n    }\n\n    // fallback to default release\n    return findRelease(clientAppId, clientIp, configAppId, ConfigConsts.CLUSTER_NAME_DEFAULT, configNamespace,\n        clientMessages);\n  }\n\n  /**\n   * Find release\n   * \n   * @param clientAppId the client's app id\n   * @param clientIp the client ip\n   * @param configAppId the requested config's app id\n   * @param configClusterName the requested config's cluster name\n   * @param configNamespace the requested config's namespace name\n   * @param clientMessages the messages received in client side\n   * @return the release\n   */\n  private Release findRelease(String clientAppId, String clientIp, String configAppId, String configClusterName,\n      String configNamespace, ApolloNotificationMessages clientMessages) {\n    Long grayReleaseId = grayReleaseRulesHolder.findReleaseIdFromGrayReleaseRule(clientAppId, clientIp, configAppId,\n        configClusterName, configNamespace);\n\n    Release release = null;\n\n    if (grayReleaseId != null) {\n      release = findActiveOne(grayReleaseId, clientMessages);\n    }\n\n    if (release == null) {\n      release = findLatestActiveRelease(configAppId, configClusterName, configNamespace, clientMessages);\n    }\n\n    return release;\n  }\n\n  /**\n   * Find active release by id\n   */\n  protected abstract Release findActiveOne(long id, ApolloNotificationMessages clientMessages);\n\n  /**\n   * Find active release by app id, cluster name and namespace name\n   */\n  protected abstract Release findLatestActiveRelease(String configAppId, String configClusterName,\n      String configNamespaceName, ApolloNotificationMessages clientMessages);\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/service/config/ConfigService.java",
    "content": "package com.ctrip.framework.apollo.configservice.service.config;\n\nimport com.ctrip.framework.apollo.biz.entity.Release;\nimport com.ctrip.framework.apollo.biz.message.ReleaseMessageListener;\nimport com.ctrip.framework.apollo.core.dto.ApolloNotificationMessages;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic interface ConfigService extends ReleaseMessageListener {\n\n  /**\n   * Load config\n   *\n   * @param clientAppId the client's app id\n   * @param clientIp the client ip\n   * @param configAppId the requested config's app id\n   * @param configClusterName the requested config's cluster name\n   * @param configNamespace the requested config's namespace name\n   * @param dataCenter the client data center\n   * @param clientMessages the messages received in client side\n   * @return the Release\n   */\n  Release loadConfig(String clientAppId, String clientIp, String configAppId, String\n      configClusterName, String configNamespace, String dataCenter, ApolloNotificationMessages clientMessages);\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/service/config/ConfigServiceWithCache.java",
    "content": "package com.ctrip.framework.apollo.configservice.service.config;\n\nimport com.google.common.base.Splitter;\nimport com.google.common.base.Strings;\nimport com.google.common.cache.CacheBuilder;\nimport com.google.common.cache.CacheLoader;\nimport com.google.common.cache.LoadingCache;\nimport com.google.common.collect.Lists;\n\nimport com.ctrip.framework.apollo.biz.entity.Release;\nimport com.ctrip.framework.apollo.biz.entity.ReleaseMessage;\nimport com.ctrip.framework.apollo.biz.message.Topics;\nimport com.ctrip.framework.apollo.biz.service.ReleaseMessageService;\nimport com.ctrip.framework.apollo.biz.service.ReleaseService;\nimport com.ctrip.framework.apollo.biz.utils.ReleaseMessageKeyGenerator;\nimport com.ctrip.framework.apollo.core.ConfigConsts;\nimport com.ctrip.framework.apollo.core.dto.ApolloNotificationMessages;\nimport com.ctrip.framework.apollo.tracer.Tracer;\nimport com.ctrip.framework.apollo.tracer.spi.Transaction;\n\nimport java.util.Optional;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\n\nimport java.util.List;\nimport java.util.concurrent.TimeUnit;\n\nimport javax.annotation.PostConstruct;\n\n/**\n * config service with guava cache\n *\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class ConfigServiceWithCache extends AbstractConfigService {\n  private static final Logger logger = LoggerFactory.getLogger(ConfigServiceWithCache.class);\n  private static final long DEFAULT_EXPIRED_AFTER_ACCESS_IN_MINUTES = 60;//1 hour\n  private static final String TRACER_EVENT_CACHE_INVALIDATE = \"ConfigCache.Invalidate\";\n  private static final String TRACER_EVENT_CACHE_LOAD = \"ConfigCache.LoadFromDB\";\n  private static final String TRACER_EVENT_CACHE_LOAD_ID = \"ConfigCache.LoadFromDBById\";\n  private static final String TRACER_EVENT_CACHE_GET = \"ConfigCache.Get\";\n  private static final String TRACER_EVENT_CACHE_GET_ID = \"ConfigCache.GetById\";\n  private static final Splitter STRING_SPLITTER =\n      Splitter.on(ConfigConsts.CLUSTER_NAMESPACE_SEPARATOR).omitEmptyStrings();\n\n  @Autowired\n  private ReleaseService releaseService;\n\n  @Autowired\n  private ReleaseMessageService releaseMessageService;\n\n  private LoadingCache<String, ConfigCacheEntry> configCache;\n\n  private LoadingCache<Long, Optional<Release>> configIdCache;\n\n  private ConfigCacheEntry nullConfigCacheEntry;\n\n  public ConfigServiceWithCache() {\n    nullConfigCacheEntry = new ConfigCacheEntry(ConfigConsts.NOTIFICATION_ID_PLACEHOLDER, null);\n  }\n\n  @PostConstruct\n  void initialize() {\n    configCache = CacheBuilder.newBuilder()\n        .expireAfterAccess(DEFAULT_EXPIRED_AFTER_ACCESS_IN_MINUTES, TimeUnit.MINUTES)\n        .build(new CacheLoader<String, ConfigCacheEntry>() {\n          @Override\n          public ConfigCacheEntry load(String key) throws Exception {\n            List<String> namespaceInfo = STRING_SPLITTER.splitToList(key);\n            if (namespaceInfo.size() != 3) {\n              Tracer.logError(\n                  new IllegalArgumentException(String.format(\"Invalid cache load key %s\", key)));\n              return nullConfigCacheEntry;\n            }\n\n            Transaction transaction = Tracer.newTransaction(TRACER_EVENT_CACHE_LOAD, key);\n            try {\n              ReleaseMessage latestReleaseMessage = releaseMessageService.findLatestReleaseMessageForMessages(Lists\n                  .newArrayList(key));\n              Release latestRelease = releaseService.findLatestActiveRelease(namespaceInfo.get(0), namespaceInfo.get(1),\n                  namespaceInfo.get(2));\n\n              transaction.setStatus(Transaction.SUCCESS);\n\n              long notificationId = latestReleaseMessage == null ? ConfigConsts.NOTIFICATION_ID_PLACEHOLDER : latestReleaseMessage\n                  .getId();\n\n              if (notificationId == ConfigConsts.NOTIFICATION_ID_PLACEHOLDER && latestRelease == null) {\n                return nullConfigCacheEntry;\n              }\n\n              return new ConfigCacheEntry(notificationId, latestRelease);\n            } catch (Throwable ex) {\n              transaction.setStatus(ex);\n              throw ex;\n            } finally {\n              transaction.complete();\n            }\n          }\n        });\n    configIdCache = CacheBuilder.newBuilder()\n        .expireAfterAccess(DEFAULT_EXPIRED_AFTER_ACCESS_IN_MINUTES, TimeUnit.MINUTES)\n        .build(new CacheLoader<Long, Optional<Release>>() {\n          @Override\n          public Optional<Release> load(Long key) throws Exception {\n            Transaction transaction = Tracer.newTransaction(TRACER_EVENT_CACHE_LOAD_ID, String.valueOf(key));\n            try {\n              Release release = releaseService.findActiveOne(key);\n\n              transaction.setStatus(Transaction.SUCCESS);\n\n              return Optional.ofNullable(release);\n            } catch (Throwable ex) {\n              transaction.setStatus(ex);\n              throw ex;\n            } finally {\n              transaction.complete();\n            }\n          }\n        });\n  }\n\n  @Override\n  protected Release findActiveOne(long id, ApolloNotificationMessages clientMessages) {\n    Tracer.logEvent(TRACER_EVENT_CACHE_GET_ID, String.valueOf(id));\n    return configIdCache.getUnchecked(id).orElse(null);\n  }\n\n  @Override\n  protected Release findLatestActiveRelease(String appId, String clusterName, String namespaceName,\n                                            ApolloNotificationMessages clientMessages) {\n    String key = ReleaseMessageKeyGenerator.generate(appId, clusterName, namespaceName);\n\n    Tracer.logEvent(TRACER_EVENT_CACHE_GET, key);\n\n    ConfigCacheEntry cacheEntry = configCache.getUnchecked(key);\n\n    //cache is out-dated\n    if (clientMessages != null && clientMessages.has(key) &&\n        clientMessages.get(key) > cacheEntry.getNotificationId()) {\n      //invalidate the cache and try to load from db again\n      invalidate(key);\n      cacheEntry = configCache.getUnchecked(key);\n    }\n\n    return cacheEntry.getRelease();\n  }\n\n  private void invalidate(String key) {\n    configCache.invalidate(key);\n    Tracer.logEvent(TRACER_EVENT_CACHE_INVALIDATE, key);\n  }\n\n  @Override\n  public void handleMessage(ReleaseMessage message, String channel) {\n    logger.info(\"message received - channel: {}, message: {}\", channel, message);\n    if (!Topics.APOLLO_RELEASE_TOPIC.equals(channel) || Strings.isNullOrEmpty(message.getMessage())) {\n      return;\n    }\n\n    try {\n      invalidate(message.getMessage());\n\n      //warm up the cache\n      configCache.getUnchecked(message.getMessage());\n    } catch (Throwable ex) {\n      //ignore\n    }\n  }\n\n  private static class ConfigCacheEntry {\n    private final long notificationId;\n    private final Release release;\n\n    public ConfigCacheEntry(long notificationId, Release release) {\n      this.notificationId = notificationId;\n      this.release = release;\n    }\n\n    public long getNotificationId() {\n      return notificationId;\n    }\n\n    public Release getRelease() {\n      return release;\n    }\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/service/config/DefaultConfigService.java",
    "content": "package com.ctrip.framework.apollo.configservice.service.config;\n\nimport com.ctrip.framework.apollo.biz.entity.Release;\nimport com.ctrip.framework.apollo.biz.entity.ReleaseMessage;\nimport com.ctrip.framework.apollo.biz.service.ReleaseService;\nimport com.ctrip.framework.apollo.core.dto.ApolloNotificationMessages;\n\nimport org.springframework.beans.factory.annotation.Autowired;\n\n/**\n * config service with no cache\n *\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class DefaultConfigService extends AbstractConfigService {\n\n  @Autowired\n  private ReleaseService releaseService;\n\n  @Override\n  protected Release findActiveOne(long id, ApolloNotificationMessages clientMessages) {\n    return releaseService.findActiveOne(id);\n  }\n\n  @Override\n  protected Release findLatestActiveRelease(String configAppId, String configClusterName, String configNamespace,\n                                            ApolloNotificationMessages clientMessages) {\n    return releaseService.findLatestActiveRelease(configAppId, configClusterName,\n        configNamespace);\n  }\n\n  @Override\n  public void handleMessage(ReleaseMessage message, String channel) {\n    // since there is no cache, so do nothing\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/util/InstanceConfigAuditUtil.java",
    "content": "package com.ctrip.framework.apollo.configservice.util;\n\nimport com.google.common.base.Joiner;\nimport com.google.common.base.Strings;\nimport com.google.common.cache.Cache;\nimport com.google.common.cache.CacheBuilder;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Queues;\n\nimport com.ctrip.framework.apollo.biz.entity.Instance;\nimport com.ctrip.framework.apollo.biz.entity.InstanceConfig;\nimport com.ctrip.framework.apollo.biz.service.InstanceService;\nimport com.ctrip.framework.apollo.core.ConfigConsts;\nimport com.ctrip.framework.apollo.core.utils.ApolloThreadFactory;\nimport com.ctrip.framework.apollo.tracer.Tracer;\n\nimport org.springframework.beans.factory.InitializingBean;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.dao.DataIntegrityViolationException;\nimport org.springframework.stereotype.Service;\n\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.concurrent.BlockingQueue;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@Service\npublic class InstanceConfigAuditUtil implements InitializingBean {\n  private static final int INSTANCE_CONFIG_AUDIT_MAX_SIZE = 10000;\n  private static final int INSTANCE_CACHE_MAX_SIZE = 50000;\n  private static final int INSTANCE_CONFIG_CACHE_MAX_SIZE = 50000;\n  private static final long OFFER_TIME_LAST_MODIFIED_TIME_THRESHOLD_IN_MILLI = TimeUnit.MINUTES.toMillis(10);//10 minutes\n  private static final Joiner STRING_JOINER = Joiner.on(ConfigConsts.CLUSTER_NAMESPACE_SEPARATOR);\n  private final ExecutorService auditExecutorService;\n  private final AtomicBoolean auditStopped;\n  private BlockingQueue<InstanceConfigAuditModel> audits = Queues.newLinkedBlockingQueue\n      (INSTANCE_CONFIG_AUDIT_MAX_SIZE);\n  private Cache<String, Long> instanceCache;\n  private Cache<String, String> instanceConfigReleaseKeyCache;\n\n  @Autowired\n  private InstanceService instanceService;\n\n  public InstanceConfigAuditUtil() {\n    auditExecutorService = Executors.newSingleThreadExecutor(\n        ApolloThreadFactory.create(\"InstanceConfigAuditUtil\", true));\n    auditStopped = new AtomicBoolean(false);\n    instanceCache = CacheBuilder.newBuilder().expireAfterAccess(1, TimeUnit.HOURS)\n        .maximumSize(INSTANCE_CACHE_MAX_SIZE).build();\n    instanceConfigReleaseKeyCache = CacheBuilder.newBuilder().expireAfterWrite(1, TimeUnit.DAYS)\n        .maximumSize(INSTANCE_CONFIG_CACHE_MAX_SIZE).build();\n  }\n\n  public boolean audit(String appId, String clusterName, String dataCenter, String\n      ip, String configAppId, String configClusterName, String configNamespace, String releaseKey) {\n    return this.audits.offer(new InstanceConfigAuditModel(appId, clusterName, dataCenter, ip,\n        configAppId, configClusterName, configNamespace, releaseKey));\n  }\n\n  void doAudit(InstanceConfigAuditModel auditModel) {\n    String instanceCacheKey = assembleInstanceKey(auditModel.getAppId(), auditModel\n        .getClusterName(), auditModel.getIp(), auditModel.getDataCenter());\n    Long instanceId = instanceCache.getIfPresent(instanceCacheKey);\n    if (instanceId == null) {\n      instanceId = prepareInstanceId(auditModel);\n      instanceCache.put(instanceCacheKey, instanceId);\n    }\n\n    //load instance config release key from cache, and check if release key is the same\n    String instanceConfigCacheKey = assembleInstanceConfigKey(instanceId, auditModel\n        .getConfigAppId(), auditModel.getConfigNamespace());\n    String cacheReleaseKey = instanceConfigReleaseKeyCache.getIfPresent(instanceConfigCacheKey);\n\n    //if release key is the same, then skip audit\n    if (cacheReleaseKey != null && Objects.equals(cacheReleaseKey, auditModel.getReleaseKey())) {\n      return;\n    }\n\n    instanceConfigReleaseKeyCache.put(instanceConfigCacheKey, auditModel.getReleaseKey());\n\n    //if release key is not the same or cannot find in cache, then do audit\n    InstanceConfig instanceConfig = instanceService.findInstanceConfig(instanceId, auditModel\n        .getConfigAppId(), auditModel.getConfigNamespace());\n\n    if (instanceConfig != null) {\n      if (!Objects.equals(instanceConfig.getReleaseKey(), auditModel.getReleaseKey())) {\n        instanceConfig.setConfigClusterName(auditModel.getConfigClusterName());\n        instanceConfig.setReleaseKey(auditModel.getReleaseKey());\n        instanceConfig.setReleaseDeliveryTime(auditModel.getOfferTime());\n      } else if (offerTimeAndLastModifiedTimeCloseEnough(auditModel.getOfferTime(),\n          instanceConfig.getDataChangeLastModifiedTime())) {\n        //when releaseKey is the same, optimize to reduce writes if the record was updated not long ago\n        return;\n      }\n      //we need to update no matter the release key is the same or not, to ensure the\n      //last modified time is updated each day\n      instanceConfig.setDataChangeLastModifiedTime(auditModel.getOfferTime());\n      instanceService.updateInstanceConfig(instanceConfig);\n      return;\n    }\n\n    instanceConfig = new InstanceConfig();\n    instanceConfig.setInstanceId(instanceId);\n    instanceConfig.setConfigAppId(auditModel.getConfigAppId());\n    instanceConfig.setConfigClusterName(auditModel.getConfigClusterName());\n    instanceConfig.setConfigNamespaceName(auditModel.getConfigNamespace());\n    instanceConfig.setReleaseKey(auditModel.getReleaseKey());\n    instanceConfig.setReleaseDeliveryTime(auditModel.getOfferTime());\n    instanceConfig.setDataChangeCreatedTime(auditModel.getOfferTime());\n\n    try {\n      instanceService.createInstanceConfig(instanceConfig);\n    } catch (DataIntegrityViolationException ex) {\n      //concurrent insertion, safe to ignore\n    }\n  }\n\n  private boolean offerTimeAndLastModifiedTimeCloseEnough(Date offerTime, Date lastModifiedTime) {\n    return (offerTime.getTime() - lastModifiedTime.getTime()) <\n        OFFER_TIME_LAST_MODIFIED_TIME_THRESHOLD_IN_MILLI;\n  }\n\n  private long prepareInstanceId(InstanceConfigAuditModel auditModel) {\n    Instance instance = instanceService.findInstance(auditModel.getAppId(), auditModel\n        .getClusterName(), auditModel.getDataCenter(), auditModel.getIp());\n    if (instance != null) {\n      return instance.getId();\n    }\n    instance = new Instance();\n    instance.setAppId(auditModel.getAppId());\n    instance.setClusterName(auditModel.getClusterName());\n    instance.setDataCenter(auditModel.getDataCenter());\n    instance.setIp(auditModel.getIp());\n\n\n    try {\n      return instanceService.createInstance(instance).getId();\n    } catch (DataIntegrityViolationException ex) {\n      //return the one exists\n      return instanceService.findInstance(instance.getAppId(), instance.getClusterName(),\n          instance.getDataCenter(), instance.getIp()).getId();\n    }\n  }\n\n  @Override\n  public void afterPropertiesSet() throws Exception {\n    auditExecutorService.submit(() -> {\n      while (!auditStopped.get() && !Thread.currentThread().isInterrupted()) {\n        try {\n          InstanceConfigAuditModel model = audits.poll();\n          if (model == null) {\n            TimeUnit.SECONDS.sleep(1);\n            continue;\n          }\n          doAudit(model);\n        } catch (Throwable ex) {\n          Tracer.logError(ex);\n        }\n      }\n    });\n  }\n\n  private String assembleInstanceKey(String appId, String cluster, String ip, String datacenter) {\n    List<String> keyParts = Lists.newArrayList(appId, cluster, ip);\n    if (!Strings.isNullOrEmpty(datacenter)) {\n      keyParts.add(datacenter);\n    }\n    return STRING_JOINER.join(keyParts);\n  }\n\n  private String assembleInstanceConfigKey(long instanceId, String configAppId, String configNamespace) {\n    return STRING_JOINER.join(instanceId, configAppId, configNamespace);\n  }\n\n  public static class InstanceConfigAuditModel {\n    private String appId;\n    private String clusterName;\n    private String dataCenter;\n    private String ip;\n    private String configAppId;\n    private String configClusterName;\n    private String configNamespace;\n    private String releaseKey;\n    private Date offerTime;\n\n    public InstanceConfigAuditModel(String appId, String clusterName, String dataCenter, String\n        clientIp, String configAppId, String configClusterName, String configNamespace, String\n                                        releaseKey) {\n      this.offerTime = new Date();\n      this.appId = appId;\n      this.clusterName = clusterName;\n      this.dataCenter = Strings.isNullOrEmpty(dataCenter) ? \"\" : dataCenter;\n      this.ip = clientIp;\n      this.configAppId = configAppId;\n      this.configClusterName = configClusterName;\n      this.configNamespace = configNamespace;\n      this.releaseKey = releaseKey;\n    }\n\n    public String getAppId() {\n      return appId;\n    }\n\n    public String getClusterName() {\n      return clusterName;\n    }\n\n    public String getDataCenter() {\n      return dataCenter;\n    }\n\n    public String getIp() {\n      return ip;\n    }\n\n    public String getConfigAppId() {\n      return configAppId;\n    }\n\n    public String getConfigNamespace() {\n      return configNamespace;\n    }\n\n    public String getReleaseKey() {\n      return releaseKey;\n    }\n\n    public String getConfigClusterName() {\n      return configClusterName;\n    }\n\n    public Date getOfferTime() {\n      return offerTime;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n      if (this == o) return true;\n      if (o == null || getClass() != o.getClass()) return false;\n      InstanceConfigAuditModel model = (InstanceConfigAuditModel) o;\n      return Objects.equals(appId, model.appId) &&\n          Objects.equals(clusterName, model.clusterName) &&\n          Objects.equals(dataCenter, model.dataCenter) &&\n          Objects.equals(ip, model.ip) &&\n          Objects.equals(configAppId, model.configAppId) &&\n          Objects.equals(configClusterName, model.configClusterName) &&\n          Objects.equals(configNamespace, model.configNamespace) &&\n          Objects.equals(releaseKey, model.releaseKey);\n    }\n\n    @Override\n    public int hashCode() {\n      return Objects.hash(appId, clusterName, dataCenter, ip, configAppId, configClusterName,\n          configNamespace,\n          releaseKey);\n    }\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/util/NamespaceUtil.java",
    "content": "package com.ctrip.framework.apollo.configservice.util;\n\nimport com.ctrip.framework.apollo.common.entity.AppNamespace;\nimport com.ctrip.framework.apollo.configservice.service.AppNamespaceServiceWithCache;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@Component\npublic class NamespaceUtil {\n\n  @Autowired\n  private AppNamespaceServiceWithCache appNamespaceServiceWithCache;\n\n  public String filterNamespaceName(String namespaceName) {\n    if (namespaceName.toLowerCase().endsWith(\".properties\")) {\n      int dotIndex = namespaceName.lastIndexOf(\".\");\n      return namespaceName.substring(0, dotIndex);\n    }\n\n    return namespaceName;\n  }\n\n  public String normalizeNamespace(String appId, String namespaceName) {\n    AppNamespace appNamespace = appNamespaceServiceWithCache.findByAppIdAndNamespace(appId, namespaceName);\n    if (appNamespace != null) {\n      return appNamespace.getName();\n    }\n\n    appNamespace = appNamespaceServiceWithCache.findPublicNamespaceByName(namespaceName);\n    if (appNamespace != null) {\n      return appNamespace.getName();\n    }\n\n    return namespaceName;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/util/WatchKeysUtil.java",
    "content": "package com.ctrip.framework.apollo.configservice.util;\n\nimport com.google.common.base.Joiner;\nimport com.google.common.base.Strings;\nimport com.google.common.collect.FluentIterable;\nimport com.google.common.collect.HashMultimap;\nimport com.google.common.collect.Multimap;\nimport com.google.common.collect.Sets;\n\nimport com.ctrip.framework.apollo.configservice.service.AppNamespaceServiceWithCache;\nimport com.ctrip.framework.apollo.common.entity.AppNamespace;\nimport com.ctrip.framework.apollo.core.ConfigConsts;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.Set;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@Component\npublic class WatchKeysUtil {\n  private static final Joiner STRING_JOINER = Joiner.on(ConfigConsts.CLUSTER_NAMESPACE_SEPARATOR);\n  @Autowired\n  private AppNamespaceServiceWithCache appNamespaceService;\n\n  /**\n   * Assemble watch keys for the given appId, cluster, namespace, dataCenter combination\n   */\n  public Set<String> assembleAllWatchKeys(String appId, String clusterName, String namespace,\n                                          String dataCenter) {\n    Multimap<String, String> watchedKeysMap =\n        assembleAllWatchKeys(appId, clusterName, Sets.newHashSet(namespace), dataCenter);\n    return Sets.newHashSet(watchedKeysMap.get(namespace));\n  }\n\n  /**\n   * Assemble watch keys for the given appId, cluster, namespaces, dataCenter combination\n   *\n   * @return a multimap with namespace as the key and watch keys as the value\n   */\n  public Multimap<String, String> assembleAllWatchKeys(String appId, String clusterName,\n                                                       Set<String> namespaces,\n                                                       String dataCenter) {\n    Multimap<String, String> watchedKeysMap =\n        assembleWatchKeys(appId, clusterName, namespaces, dataCenter);\n\n    //Every app has an 'application' namespace\n    if (!(namespaces.size() == 1 && namespaces.contains(ConfigConsts.NAMESPACE_APPLICATION))) {\n      Set<String> namespacesBelongToAppId = namespacesBelongToAppId(appId, namespaces);\n      Set<String> publicNamespaces = Sets.difference(namespaces, namespacesBelongToAppId);\n\n      //Listen on more namespaces if it's a public namespace\n      if (!publicNamespaces.isEmpty()) {\n        watchedKeysMap\n            .putAll(findPublicConfigWatchKeys(appId, clusterName, publicNamespaces, dataCenter));\n      }\n    }\n\n    return watchedKeysMap;\n  }\n\n  private Multimap<String, String> findPublicConfigWatchKeys(String applicationId,\n                                                             String clusterName,\n                                                             Set<String> namespaces,\n                                                             String dataCenter) {\n    Multimap<String, String> watchedKeysMap = HashMultimap.create();\n    List<AppNamespace> appNamespaces = appNamespaceService.findPublicNamespacesByNames(namespaces);\n\n    for (AppNamespace appNamespace : appNamespaces) {\n      //check whether the namespace's appId equals to current one\n      if (Objects.equals(applicationId, appNamespace.getAppId())) {\n        continue;\n      }\n\n      String publicConfigAppId = appNamespace.getAppId();\n\n      watchedKeysMap.putAll(appNamespace.getName(),\n          assembleWatchKeys(publicConfigAppId, clusterName, appNamespace.getName(), dataCenter));\n    }\n\n    return watchedKeysMap;\n  }\n\n  private String assembleKey(String appId, String cluster, String namespace) {\n    return STRING_JOINER.join(appId, cluster, namespace);\n  }\n\n  private Set<String> assembleWatchKeys(String appId, String clusterName, String namespace,\n                                        String dataCenter) {\n    if (ConfigConsts.NO_APPID_PLACEHOLDER.equalsIgnoreCase(appId)) {\n      return Collections.emptySet();\n    }\n    Set<String> watchedKeys = Sets.newHashSet();\n\n    //watch specified cluster config change\n    if (!Objects.equals(ConfigConsts.CLUSTER_NAME_DEFAULT, clusterName)) {\n      watchedKeys.add(assembleKey(appId, clusterName, namespace));\n    }\n\n    //watch data center config change\n    if (!Strings.isNullOrEmpty(dataCenter) && !Objects.equals(dataCenter, clusterName)) {\n      watchedKeys.add(assembleKey(appId, dataCenter, namespace));\n    }\n\n    //watch default cluster config change\n    watchedKeys.add(assembleKey(appId, ConfigConsts.CLUSTER_NAME_DEFAULT, namespace));\n\n    return watchedKeys;\n  }\n\n  private Multimap<String, String> assembleWatchKeys(String appId, String clusterName,\n                                                     Set<String> namespaces,\n                                                     String dataCenter) {\n    Multimap<String, String> watchedKeysMap = HashMultimap.create();\n\n    for (String namespace : namespaces) {\n      watchedKeysMap\n          .putAll(namespace, assembleWatchKeys(appId, clusterName, namespace, dataCenter));\n    }\n\n    return watchedKeysMap;\n  }\n\n  private Set<String> namespacesBelongToAppId(String appId, Set<String> namespaces) {\n    if (ConfigConsts.NO_APPID_PLACEHOLDER.equalsIgnoreCase(appId)) {\n      return Collections.emptySet();\n    }\n    List<AppNamespace> appNamespaces =\n        appNamespaceService.findByAppIdAndNamespaces(appId, namespaces);\n\n    if (appNamespaces == null || appNamespaces.isEmpty()) {\n      return Collections.emptySet();\n    }\n\n    return FluentIterable.from(appNamespaces).transform(AppNamespace::getName).toSet();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/wrapper/CaseInsensitiveMapWrapper.java",
    "content": "package com.ctrip.framework.apollo.configservice.wrapper;\n\nimport java.util.Map;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class CaseInsensitiveMapWrapper<T> {\n  private final Map<String, T> delegate;\n\n  public CaseInsensitiveMapWrapper(Map<String, T> delegate) {\n    this.delegate = delegate;\n  }\n\n  public T get(String key) {\n    return delegate.get(key.toLowerCase());\n  }\n\n  public T put(String key, T value) {\n    return delegate.put(key.toLowerCase(), value);\n  }\n\n  public T remove(String key) {\n    return delegate.remove(key.toLowerCase());\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/wrapper/DeferredResultWrapper.java",
    "content": "package com.ctrip.framework.apollo.configservice.wrapper;\n\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\n\nimport com.ctrip.framework.apollo.core.dto.ApolloConfig;\nimport com.ctrip.framework.apollo.core.dto.ApolloConfigNotification;\n\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.web.context.request.async.DeferredResult;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class DeferredResultWrapper {\n  private static final long TIMEOUT = 30 * 1000;//30 seconds\n  private static final ResponseEntity<List<ApolloConfigNotification>>\n      NOT_MODIFIED_RESPONSE_LIST = new ResponseEntity<>(HttpStatus.NOT_MODIFIED);\n\n  private Map<String, String> normalizedNamespaceNameToOriginalNamespaceName;\n  private DeferredResult<ResponseEntity<List<ApolloConfigNotification>>> result;\n\n\n  public DeferredResultWrapper() {\n    result = new DeferredResult<>(TIMEOUT, NOT_MODIFIED_RESPONSE_LIST);\n  }\n\n  public void recordNamespaceNameNormalizedResult(String originalNamespaceName, String normalizedNamespaceName) {\n    if (normalizedNamespaceNameToOriginalNamespaceName == null) {\n      normalizedNamespaceNameToOriginalNamespaceName = Maps.newHashMap();\n    }\n    normalizedNamespaceNameToOriginalNamespaceName.put(normalizedNamespaceName, originalNamespaceName);\n  }\n\n\n  public void onTimeout(Runnable timeoutCallback) {\n    result.onTimeout(timeoutCallback);\n  }\n\n  public void onCompletion(Runnable completionCallback) {\n    result.onCompletion(completionCallback);\n  }\n\n\n  public void setResult(ApolloConfigNotification notification) {\n    setResult(Lists.newArrayList(notification));\n  }\n\n  /**\n   * The namespace name is used as a key in client side, so we have to return the original one instead of the correct one\n   */\n  public void setResult(List<ApolloConfigNotification> notifications) {\n    if (normalizedNamespaceNameToOriginalNamespaceName != null) {\n      notifications.stream().filter(notification -> normalizedNamespaceNameToOriginalNamespaceName.containsKey\n          (notification.getNamespaceName())).forEach(notification -> notification.setNamespaceName(\n              normalizedNamespaceNameToOriginalNamespaceName.get(notification.getNamespaceName())));\n    }\n\n    result.setResult(new ResponseEntity<>(notifications, HttpStatus.OK));\n  }\n\n  public DeferredResult<ResponseEntity<List<ApolloConfigNotification>>> getResult() {\n    return result;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/metaservice/ApolloMetaServiceConfig.java",
    "content": "package com.ctrip.framework.apollo.metaservice;\n\nimport org.springframework.boot.autoconfigure.EnableAutoConfiguration;\nimport org.springframework.context.annotation.ComponentScan;\nimport org.springframework.context.annotation.Configuration;\n\n@EnableAutoConfiguration\n@Configuration\n@ComponentScan(basePackageClasses = ApolloMetaServiceConfig.class)\npublic class ApolloMetaServiceConfig {\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/metaservice/controller/ServiceController.java",
    "content": "package com.ctrip.framework.apollo.metaservice.controller;\n\nimport com.ctrip.framework.apollo.core.dto.ServiceDTO;\nimport com.ctrip.framework.apollo.metaservice.service.DiscoveryService;\nimport com.netflix.appinfo.InstanceInfo;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.List;\nimport java.util.function.Function;\nimport java.util.stream.Collectors;\n\n@RestController\n@RequestMapping(\"/services\")\npublic class ServiceController {\n\n  @Autowired\n  private DiscoveryService discoveryService;\n\n\n  @RequestMapping(\"/meta\")\n  public List<ServiceDTO> getMetaService() {\n    List<InstanceInfo> instances = discoveryService.getMetaServiceInstances();\n    List<ServiceDTO> result = instances.stream().map(new Function<InstanceInfo, ServiceDTO>() {\n\n      @Override\n      public ServiceDTO apply(InstanceInfo instance) {\n        ServiceDTO service = new ServiceDTO();\n        service.setAppName(instance.getAppName());\n        service.setInstanceId(instance.getInstanceId());\n        service.setHomepageUrl(instance.getHomePageUrl());\n        return service;\n      }\n\n    }).collect(Collectors.toList());\n    return result;\n  }\n\n  @RequestMapping(\"/config\")\n  public List<ServiceDTO> getConfigService(\n      @RequestParam(value = \"appId\", defaultValue = \"\") String appId,\n      @RequestParam(value = \"ip\", required = false) String clientIp) {\n    List<InstanceInfo> instances = discoveryService.getConfigServiceInstances();\n    List<ServiceDTO> result = instances.stream().map(new Function<InstanceInfo, ServiceDTO>() {\n\n      @Override\n      public ServiceDTO apply(InstanceInfo instance) {\n        ServiceDTO service = new ServiceDTO();\n        service.setAppName(instance.getAppName());\n        service.setInstanceId(instance.getInstanceId());\n        service.setHomepageUrl(instance.getHomePageUrl());\n        return service;\n      }\n\n    }).collect(Collectors.toList());\n    return result;\n  }\n\n  @RequestMapping(\"/admin\")\n  public List<ServiceDTO> getAdminService() {\n    List<InstanceInfo> instances = discoveryService.getAdminServiceInstances();\n    List<ServiceDTO> result = instances.stream().map(new Function<InstanceInfo, ServiceDTO>() {\n\n      @Override\n      public ServiceDTO apply(InstanceInfo instance) {\n        ServiceDTO service = new ServiceDTO();\n        service.setAppName(instance.getAppName());\n        service.setInstanceId(instance.getInstanceId());\n        service.setHomepageUrl(instance.getHomePageUrl());\n        return service;\n      }\n\n    }).collect(Collectors.toList());\n    return result;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/metaservice/service/DiscoveryService.java",
    "content": "package com.ctrip.framework.apollo.metaservice.service;\n\nimport com.ctrip.framework.apollo.core.ServiceNameConsts;\nimport com.ctrip.framework.apollo.tracer.Tracer;\nimport com.netflix.appinfo.InstanceInfo;\nimport com.netflix.discovery.EurekaClient;\nimport com.netflix.discovery.shared.Application;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.Collections;\nimport java.util.List;\n\n@Service\npublic class DiscoveryService {\n\n  @Autowired\n  private EurekaClient eurekaClient;\n\n  public List<InstanceInfo> getConfigServiceInstances() {\n    Application application = eurekaClient.getApplication(ServiceNameConsts.APOLLO_CONFIGSERVICE);\n    if (application == null) {\n      Tracer.logEvent(\"Apollo.EurekaDiscovery.NotFound\", ServiceNameConsts.APOLLO_CONFIGSERVICE);\n    }\n    return application != null ? application.getInstances() : Collections.emptyList();\n  }\n\n  public List<InstanceInfo> getMetaServiceInstances() {\n    Application application = eurekaClient.getApplication(ServiceNameConsts.APOLLO_METASERVICE);\n    if (application == null) {\n      Tracer.logEvent(\"Apollo.EurekaDiscovery.NotFound\", ServiceNameConsts.APOLLO_METASERVICE);\n    }\n    return application != null ? application.getInstances() : Collections.emptyList();\n  }\n\n  public List<InstanceInfo> getAdminServiceInstances() {\n    Application application = eurekaClient.getApplication(ServiceNameConsts.APOLLO_ADMINSERVICE);\n    if (application == null) {\n      Tracer.logEvent(\"Apollo.EurekaDiscovery.NotFound\", ServiceNameConsts.APOLLO_ADMINSERVICE);\n    }\n    return application != null ? application.getInstances() : Collections.emptyList();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/main/resources/META-INF/app.properties",
    "content": "app.id=100003171\njdkVersion=1.8\n"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/main/resources/application.yml",
    "content": "spring:\n  application:\n    name: apollo-configservice\n  profiles:\n    active: ${apollo_profile}\n\nctrip:\n  appid: 100003171\n  \nserver:\n  port: 8080\n  \nlogging:\n  level:\n    com.ctrip: INFO  \n"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/main/resources/bootstrap.yml",
    "content": "eureka:\n  instance:\n    hostname: ${spring.cloud.client.ipAddress}\n    instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}\n    prefer-ip-address: true\n  server:\n    peerEurekaNodesUpdateIntervalMs: 60000\n    enableSelfPreservation: false\n  client:\n    serviceUrl:\n      defaultZone: http://${eureka.instance.hostname}:8080/eureka/\n    healthcheck:\n      enabled: true\n    eurekaServiceUrlPollIntervalSeconds: 60\n\nendpoints:\n  health:\n    sensitive: false\n\nmanagement:\n  security:\n    enabled: false\n  health:\n    status:\n      order: DOWN, OUT_OF_SERVICE, UNKNOWN, UP\n"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/main/resources/configservice.properties",
    "content": "#Used for apollo-assembly\nspring.application.name= apollo-configservice\nctrip.appid= 100003171\nserver.port= 8080\n#logging.file= /opt/logs/100003171/apollo-configservice.log\n\napollo_profile=github\n#192.168.3.150 \nspring.datasource.url=jdbc:mysql://47.94.252.160:3306/ApolloConfigDB?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false\nspring.datasource.username=root\nspring.datasource.password=root\n\n#spring.jpa.properties.hibernate.show_sql=true\nspring.jpa.hibernate.naming_strategy=org.hibernate.cfg.EJB3NamingStrategy\n"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/main/resources/logback.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<configuration>\n\t<include resource=\"org/springframework/boot/logging/logback/defaults.xml\" />\n\t<property name=\"LOG_FILE\"\n\t\tvalue=\"${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}/}apollo-configservice.log}\" />\n\t<include resource=\"org/springframework/boot/logging/logback/file-appender.xml\" />\n\t<include resource=\"org/springframework/boot/logging/logback/console-appender.xml\" />\n\t<root level=\"INFO\">\n\t\t<appender-ref ref=\"FILE\" />\n\t\t<appender-ref ref=\"CONSOLE\" />\n\t</root>\n</configuration>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/main/scripts/shutdown.sh",
    "content": "#!/bin/bash\nSERVICE_NAME=apollo-configservice\n\nif [[ -z \"$JAVA_HOME\" && -d /usr/java/latest/ ]]; then\n    export JAVA_HOME=/usr/java/latest/\nfi\n\ncd `dirname $0`/..\n\nif [[ ! -f $SERVICE_NAME\".jar\" && -d current ]]; then\n    cd current\nfi\n\nif [[ -f $SERVICE_NAME\".jar\" ]]; then\n  chmod a+x $SERVICE_NAME\".jar\"\n  ./$SERVICE_NAME\".jar\" stop\nfi\n"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/main/scripts/startup.sh",
    "content": "#!/bin/bash\nSERVICE_NAME=apollo-configservice\n## Adjust log dir if necessary\nLOG_DIR=/opt/logs/100003171\n## Adjust server port if necessary\nSERVER_PORT=8080\n\n## Adjust memory settings if necessary\n#export JAVA_OPTS=\"-Xms6144m -Xmx6144m -Xss256k -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=384m -XX:NewSize=4096m -XX:MaxNewSize=4096m -XX:SurvivorRatio=8\"\n\n## Only uncomment the following when you are using server jvm\n#export JAVA_OPTS=\"$JAVA_OPTS -server -XX:-ReduceInitialCardMarks\"\n\n########### The following is the same for configservice, adminservice, portal ###########\nexport JAVA_OPTS=\"$JAVA_OPTS -XX:+UseParNewGC -XX:ParallelGCThreads=4 -XX:MaxTenuringThreshold=9 -XX:+UseConcMarkSweepGC -XX:+DisableExplicitGC -XX:+UseCMSInitiatingOccupancyOnly -XX:+ScavengeBeforeFullGC -XX:+UseCMSCompactAtFullCollection -XX:+CMSParallelRemarkEnabled -XX:CMSFullGCsBeforeCompaction=9 -XX:CMSInitiatingOccupancyFraction=60 -XX:+CMSClassUnloadingEnabled -XX:SoftRefLRUPolicyMSPerMB=0 -XX:+CMSPermGenSweepingEnabled -XX:CMSInitiatingPermOccupancyFraction=70 -XX:+ExplicitGCInvokesConcurrent -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCApplicationConcurrentTime -XX:+PrintHeapAtGC -XX:+HeapDumpOnOutOfMemoryError -XX:-OmitStackTraceInFastThrow -Duser.timezone=Asia/Shanghai -Dclient.encoding.override=UTF-8 -Dfile.encoding=UTF-8 -Djava.security.egd=file:/dev/./urandom\"\nexport JAVA_OPTS=\"$JAVA_OPTS -Dserver.port=$SERVER_PORT -Dlogging.file=$LOG_DIR/$SERVICE_NAME.log -Xloggc:$LOG_DIR/heap_trace.txt -XX:HeapDumpPath=$LOG_DIR/HeapDumpOnOutOfMemoryError/\"\n\nPATH_TO_JAR=$SERVICE_NAME\".jar\"\nSERVER_URL=\"http://localhost:$SERVER_PORT\"\n\nfunction checkPidAlive {\n    for i in `ls -t $SERVICE_NAME*.pid 2>/dev/null`\n    do\n        read pid < $i\n\n        result=$(ps -p \"$pid\")\n        if [ \"$?\" -eq 0 ]; then\n            return 0\n        else\n            printf \"\\npid - $pid just quit unexpectedly, please check logs under $LOG_DIR and /tmp for more information!\\n\"\n            exit 1;\n        fi\n    done\n\n    printf \"\\nNo pid file found, startup may failed. Please check logs under $LOG_DIR and /tmp for more information!\\n\"\n    exit 1;\n}\n\nif [ \"$(uname)\" == \"Darwin\" ]; then\n    windows=\"0\"\nelif [ \"$(expr substr $(uname -s) 1 5)\" == \"Linux\" ]; then\n    windows=\"0\"\nelif [ \"$(expr substr $(uname -s) 1 5)\" == \"MINGW\" ]; then\n    windows=\"1\"\nelse\n    windows=\"0\"\nfi\n\n# for Windows\nif [ \"$windows\" == \"1\" ] && [[ -n \"$JAVA_HOME\" ]] && [[ -x \"$JAVA_HOME/bin/java\" ]]; then\n    tmp_java_home=`cygpath -sw \"$JAVA_HOME\"`\n    export JAVA_HOME=`cygpath -u $tmp_java_home`\n    echo \"Windows new JAVA_HOME is: $JAVA_HOME\"\nfi\n\ncd `dirname $0`/..\n\nfor i in `ls $SERVICE_NAME-*.jar 2>/dev/null`\ndo\n    if [[ ! $i == *\"-sources.jar\" ]]\n    then\n        PATH_TO_JAR=$i\n        break\n    fi\ndone\n\nif [[ ! -f PATH_TO_JAR && -d current ]]; then\n    cd current\n    for i in `ls $SERVICE_NAME-*.jar 2>/dev/null`\n    do\n        if [[ ! $i == *\"-sources.jar\" ]]\n        then\n            PATH_TO_JAR=$i\n            break\n        fi\n    done\nfi\n\nif [[ -f $SERVICE_NAME\".jar\" ]]; then\n  rm -rf $SERVICE_NAME\".jar\"\nfi\n\nprintf \"$(date) ==== Starting ==== \\n\"\n\nln $PATH_TO_JAR $SERVICE_NAME\".jar\"\nchmod a+x $SERVICE_NAME\".jar\"\n./$SERVICE_NAME\".jar\" start\n\nrc=$?;\n\nif [[ $rc != 0 ]];\nthen\n    echo \"$(date) Failed to start $SERVICE_NAME.jar, return code: $rc\"\n    exit $rc;\nfi\n\ndeclare -i counter=0\ndeclare -i max_counter=48 # 48*5=240s\ndeclare -i total_time=0\n\nprintf \"Waiting for server startup\"\nuntil [[ (( counter -ge max_counter )) || \"$(curl -X GET --silent --connect-timeout 1 --max-time 2 --head $SERVER_URL | grep \"Coyote\")\" != \"\" ]];\ndo\n    printf \".\"\n    counter+=1\n    sleep 5\n\n    checkPidAlive\ndone\n\ntotal_time=counter*5\n\nif [[ (( counter -ge max_counter )) ]];\nthen\n    printf \"\\n$(date) Server failed to start in $total_time seconds!\\n\"\n    exit 1;\nfi\n\nprintf \"\\n$(date) Server started in $total_time seconds!\\n\"\n\nexit 0;\n"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/test/resources/application.properties",
    "content": "spring.datasource.url = jdbc:h2:mem:~/apolloconfigdb;mode=mysql;DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=-1\nspring.jpa.hibernate.naming_strategy=org.hibernate.cfg.EJB3NamingStrategy\nspring.h2.console.enabled = true\nspring.h2.console.settings.web-allow-others=true\nspring.jpa.properties.hibernate.show_sql=true\n\n# for ReleaseMessageScanner test\napollo.message-scan.interval=100\n"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/test/resources/application.yml",
    "content": "spring:\n  application:\n    name: apollo-configservice\n\nserver:\n  port: ${port:8080}\n  \nlogging:\n  level:\n    org.springframework.cloud: 'DEBUG'\n  file: /opt/logs/${ctrip.appid}/apollo-configservice.log\n\nctrip:\n  appid: 100003171"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/test/resources/bootstrap.yml",
    "content": "eureka:\n  instance:\n    hostname: ${hostname:localhost}\n    preferIpAddress: true\n  client:\n    serviceUrl:\n      defaultZone: http://${eureka.instance.hostname}:8080/eureka/\n    healthcheck:\n      enabled: true\n      \n      \nendpoints:\n  health:\n    sensitive: false\n\nmanagement:\n  security:\n    enabled: false\n  health:\n    status:\n      order: DOWN, OUT_OF_SERVICE, UNKNOWN, UP \n"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/test/resources/data.sql",
    "content": "INSERT INTO App (AppId, Name, OwnerName, OwnerEmail) VALUES ('100003171','apollo-config-service','刘一鸣','liuym@ctrip.com');\nINSERT INTO App (AppId, Name, OwnerName, OwnerEmail) VALUES ('100003172','apollo-admin-service','宋顺','song_s@ctrip.com');\nINSERT INTO App (AppId, Name, OwnerName, OwnerEmail) VALUES ('100003173','apollo-portal','张乐','zhanglea@ctrip.com');\nINSERT INTO App (AppId, Name, OwnerName, OwnerEmail) VALUES ('fxhermesproducer','fx-hermes-producer','梁锦华','jhliang@ctrip.com');\n\nINSERT INTO Cluster (AppId, Name) VALUES ('100003171', 'default');\nINSERT INTO Cluster (AppId, Name) VALUES ('100003171', 'cluster1');\nINSERT INTO Cluster (AppId, Name) VALUES ('100003172', 'default');\nINSERT INTO Cluster (AppId, Name) VALUES ('100003172', 'cluster2');\nINSERT INTO Cluster (AppId, Name) VALUES ('100003173', 'default');\nINSERT INTO Cluster (AppId, Name) VALUES ('100003173', 'cluster3');\nINSERT INTO Cluster (AppId, Name) VALUES ('fxhermesproducer', 'default');\n\nINSERT INTO AppNamespace (AppId, Name) VALUES ('100003171', 'application');\nINSERT INTO AppNamespace (AppId, Name) VALUES ('100003171', 'fx.apollo.config');\nINSERT INTO AppNamespace (AppId, Name) VALUES ('100003172', 'application');\nINSERT INTO AppNamespace (AppId, Name) VALUES ('100003172', 'fx.apollo.admin');\nINSERT INTO AppNamespace (AppId, Name) VALUES ('100003173', 'application');\nINSERT INTO AppNamespace (AppId, Name) VALUES ('100003173', 'fx.apollo.portal');\nINSERT INTO AppNamespace (AppID, Name) VALUES ('fxhermesproducer', 'fx.hermes.producer');\n\nINSERT INTO Namespace (Id, AppId, ClusterName, NamespaceName) VALUES (1, '100003171', 'default', 'application');\nINSERT INTO Namespace (Id, AppId, ClusterName, NamespaceName) VALUES (2, 'fxhermesproducer', 'default', 'fx.hermes.producer');\nINSERT INTO Namespace (Id, AppId, ClusterName, NamespaceName) VALUES (3, '100003172', 'default', 'application');\nINSERT INTO Namespace (Id, AppId, ClusterName, NamespaceName) VALUES (4, '100003173', 'default', 'application');\nINSERT INTO Namespace (Id, AppId, ClusterName, NamespaceName) VALUES (5, '100003171', 'default', 'application');\n\nINSERT INTO Item (NamespaceId, `Key`, Value, Comment) VALUES (1, 'k1', 'v1', 'comment1');\nINSERT INTO Item (NamespaceId, `Key`, Value, Comment) VALUES (1, 'k2', 'v2', 'comment2');\nINSERT INTO Item (NamespaceId, `Key`, Value, Comment) VALUES (2, 'k3', 'v3', 'comment3');\nINSERT INTO Item (NamespaceId, `Key`, Value, Comment) VALUES (5, 'k3', 'v4', 'comment4');\n\nINSERT INTO RELEASE (ReleaseKey, Name, Comment, AppId, ClusterName, NamespaceName, Configurations) VALUES ('TEST-RELEASE-KEY', 'REV1','First Release','100003171', 'default', 'application', '{\"k1\":\"v1\"}');\n\n"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/test/resources/integration-test/cleanup.sql",
    "content": "DELETE FROM Release;\nDELETE FROM Namespace;\nDELETE FROM AppNamespace;\nDELETE FROM Cluster;\nDELETE FROM App;\nDELETE FROM ReleaseMessage;\nDELETE FROM GrayReleaseRule;\n\n\n"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/test/resources/integration-test/test-gray-release.sql",
    "content": "INSERT INTO GrayReleaseRule (`Id`, `AppId`, `ClusterName`, `NamespaceName`, `BranchName`, `Rules`, `ReleaseId`, `BranchStatus`)\nVALUES\n\t(1, 'someAppId', 'default', 'application', 'gray-branch-1', '[{\"clientAppId\":\"someAppId\",\"clientIpList\":[\"1.1.1.1\"]}]', 986, 1);\nINSERT INTO GrayReleaseRule (`Id`, `AppId`, `ClusterName`, `NamespaceName`, `BranchName`, `Rules`, `ReleaseId`, `BranchStatus`)\nVALUES\n\t(2, 'somePublicAppId', 'default', 'somePublicNamespace', 'gray-branch-2', '[{\"clientAppId\":\"someAppId\",\"clientIpList\":[\"1.1.1.1\"]}]', 985, 1);\n"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/test/resources/integration-test/test-release-message.sql",
    "content": "INSERT INTO `releasemessage` (`Id`, `Message`)\nVALUES\n\t(10, 'someAppId+default+application');\nINSERT INTO `releasemessage` (`Id`, `Message`)\nVALUES\n\t(20, 'somePublicAppId+default+somePublicNamespace');\n"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/test/resources/integration-test/test-release-public-dc-override.sql",
    "content": "INSERT INTO RELEASE (id, ReleaseKey, Name, Comment, AppId, ClusterName, NamespaceName, Configurations)\n VALUES (995, 'TEST-RELEASE-KEY6', 'INTEGRATION-TEST-DEFAULT-OVERRIDE-PUBLIC-DC','First Release','someAppId', 'someDC', 'somePublicNamespace', '{\"k1\":\"override-someDC-v1\"}');\n"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/test/resources/integration-test/test-release-public-default-override.sql",
    "content": "INSERT INTO RELEASE (id, ReleaseKey, Name, Comment, AppId, ClusterName, NamespaceName, Configurations)\n VALUES (994, 'TEST-RELEASE-KEY5', 'INTEGRATION-TEST-DEFAULT-OVERRIDE-PUBLIC','First Release','someAppId', 'default', 'somePublicNamespace', '{\"k1\":\"override-v1\"}');\n"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/test/resources/integration-test/test-release.sql",
    "content": "INSERT INTO App (AppId, Name, OwnerName, OwnerEmail) VALUES ('someAppId','someAppName','someOwnerName','someOwnerName@ctrip.com');\nINSERT INTO App (AppId, Name, OwnerName, OwnerEmail) VALUES ('somePublicAppId','somePublicAppName','someOwnerName','someOwnerName@ctrip.com');\n\nINSERT INTO Cluster (AppId, Name) VALUES ('someAppId', 'default');\nINSERT INTO Cluster (AppId, Name) VALUES ('someAppId', 'someCluster');\nINSERT INTO Cluster (AppId, Name) VALUES ('somePublicAppId', 'default');\nINSERT INTO Cluster (AppId, Name) VALUES ('somePublicAppId', 'someDC');\n\nINSERT INTO AppNamespace (AppId, Name, IsPublic) VALUES ('someAppId', 'application', false);\nINSERT INTO AppNamespace (AppId, Name, IsPublic) VALUES ('someAppId', 'someNamespace', true);\nINSERT INTO AppNamespace (AppId, Name, IsPublic) VALUES ('someAppId', 'someNamespace.xml', false);\nINSERT INTO AppNamespace (AppId, Name, IsPublic) VALUES ('someAppId', 'anotherNamespace', false);\nINSERT INTO AppNamespace (AppId, Name, IsPublic) VALUES ('somePublicAppId', 'application', false);\nINSERT INTO AppNamespace (AppId, Name, IsPublic) VALUES ('somePublicAppId', 'somePublicNamespace', true);\nINSERT INTO AppNamespace (AppId, Name, IsPublic) VALUES ('somePublicAppId', 'anotherNamespace', true);\n\nINSERT INTO Namespace (AppId, ClusterName, NamespaceName) VALUES ('someAppId', 'default', 'application');\nINSERT INTO Namespace (AppId, ClusterName, NamespaceName) VALUES ('someAppId', 'default', 'someNamespace.xml');\nINSERT INTO Namespace (AppId, ClusterName, NamespaceName) VALUES ('someAppId', 'default', 'anotherNamespace');\nINSERT INTO Namespace (AppId, ClusterName, NamespaceName) VALUES ('someAppId', 'someCluster', 'someNamespace');\nINSERT INTO Namespace (AppId, ClusterName, NamespaceName) VALUES ('somePublicAppId', 'default', 'application');\nINSERT INTO Namespace (AppId, ClusterName, NamespaceName) VALUES ('somePublicAppId', 'someDC', 'somePublicNamespace');\nINSERT INTO Namespace (AppId, ClusterName, NamespaceName) VALUES ('someAppId', 'default', 'somePublicNamespace');\nINSERT INTO Namespace (AppId, ClusterName, NamespaceName) VALUES ('somePublicAppId', 'default', 'anotherNamespace');\n\nINSERT INTO RELEASE (id, ReleaseKey, Name, Comment, AppId, ClusterName, NamespaceName, Configurations)\n  VALUES (990, 'TEST-RELEASE-KEY1', 'INTEGRATION-TEST-DEFAULT','First Release','someAppId', 'default', 'application', '{\"k1\":\"v1\"}');\nINSERT INTO RELEASE (id, ReleaseKey, Name, Comment, AppId, ClusterName, NamespaceName, Configurations)\n  VALUES (991, 'TEST-RELEASE-KEY2', 'INTEGRATION-TEST-NAMESPACE','First Release','someAppId', 'someCluster', 'someNamespace', '{\"k2\":\"v2\"}');\nINSERT INTO RELEASE (id, ReleaseKey, Name, Comment, AppId, ClusterName, NamespaceName, Configurations)\n  VALUES (992, 'TEST-RELEASE-KEY3', 'INTEGRATION-TEST-PUBLIC-DEFAULT','First Release','somePublicAppId', 'default', 'somePublicNamespace', '{\"k1\":\"default-v1\", \"k2\":\"default-v2\"}');\nINSERT INTO RELEASE (id, ReleaseKey, Name, Comment, AppId, ClusterName, NamespaceName, Configurations)\n VALUES (993, 'TEST-RELEASE-KEY4', 'INTEGRATION-TEST-PUBLIC-NAMESPACE','First Release','somePublicAppId', 'someDC', 'somePublicNamespace', '{\"k1\":\"someDC-v1\", \"k2\":\"someDC-v2\"}');\nINSERT INTO RELEASE (id, ReleaseKey, Name, Comment, AppId, ClusterName, NamespaceName, Configurations)\n VALUES (989, 'TEST-RELEASE-KEY5', 'INTEGRATION-TEST-PRIVATE-CONFIG-FILE','First Release','someAppId', 'default', 'someNamespace.xml', '{\"k1\":\"v1-file\", \"k2\":\"v2-file\"}');\nINSERT INTO RELEASE (id, ReleaseKey, Name, Comment, AppId, ClusterName, NamespaceName, Configurations)\n VALUES (988, 'TEST-RELEASE-KEY6', 'INTEGRATION-TEST-PRIVATE-CONFIG-FILE','First Release','someAppId', 'default', 'anotherNamespace', '{\"k1\":\"v1-file\"}');\nINSERT INTO RELEASE (id, ReleaseKey, Name, Comment, AppId, ClusterName, NamespaceName, Configurations)\n VALUES (987, 'TEST-RELEASE-KEY7', 'INTEGRATION-TEST-PUBLIC-CONFIG-FILE','First Release','somePublicAppId', 'default', 'anotherNamespace', '{\"k2\":\"v2-file\"}');\nINSERT INTO RELEASE (id, ReleaseKey, Name, Comment, AppId, ClusterName, NamespaceName, Configurations)\n  VALUES (986, 'TEST-GRAY-RELEASE-KEY1', 'INTEGRATION-TEST-DEFAULT','Gray Release','someAppId', 'gray-branch-1', 'application', '{\"k1\":\"v1-gray\"}');\nINSERT INTO RELEASE (id, ReleaseKey, Name, Comment, AppId, ClusterName, NamespaceName, Configurations)\n  VALUES (985, 'TEST-GRAY-RELEASE-KEY2', 'INTEGRATION-TEST-NAMESPACE','Gray Release','somePublicAppId', 'gray-branch-2', 'somePublicNamespace', '{\"k1\":\"gray-v1\", \"k2\":\"gray-v2\"}');"
  },
  {
    "path": "open-config-center/apollo/apollo-configservice/src/test/resources/logback-test.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<configuration scan=\"true\">\n\t<appender name=\"CONSOLE\" class=\"ch.qos.logback.core.ConsoleAppender\">\n\t\t<encoder>\n\t\t\t<charset>utf-8</charset>\n\t\t\t<Pattern>[%p] %c - %m%n</Pattern>\n\t\t</encoder>\n\t</appender>\n\t<logger name=\"org.springframework.test\" level=\"OFF\" />\n\n\t<root level=\"INFO\">\n\t\t<appender-ref ref=\"CONSOLE\" />\n\t</root>\n\n</configuration>"
  },
  {
    "path": "open-config-center/apollo/apollo-core/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\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">\n\t<parent>\n\t\t<groupId>com.ctrip.framework.apollo</groupId>\n\t\t<artifactId>apollo</artifactId>\n\t\t<version>0.10.0-SNAPSHOT</version>\n\t</parent>\n\t<modelVersion>4.0.0</modelVersion>\n\t<artifactId>apollo-core</artifactId>\n\t<name>Apollo Core</name>\n\t<packaging>jar</packaging>\n\t<properties>\n\t\t<java.version>1.7</java.version>\n\t\t<github.path>${project.artifactId}</github.path>\n\t</properties>\n\t<dependencies>\n\t\t<!-- json -->\n\t\t<dependency>\n\t\t\t<groupId>com.google.code.gson</groupId>\n\t\t\t<artifactId>gson</artifactId>\n\t\t</dependency>\n\t\t<!-- end of json -->\n\t\t<!-- util -->\n\t\t<dependency>\n\t\t\t<groupId>com.google.guava</groupId>\n\t\t\t<artifactId>guava</artifactId>\n\t\t</dependency>\n\t\t<!-- end of util -->\n\t\t<!-- log -->\n\t\t<dependency>\n\t\t\t<groupId>org.slf4j</groupId>\n\t\t\t<artifactId>slf4j-api</artifactId>\n\t\t</dependency>\n\t\t<!-- end of log -->\n\t\t<!-- test -->\n\t\t<dependency>\n\t\t\t<groupId>org.apache.logging.log4j</groupId>\n\t\t\t<artifactId>log4j-slf4j-impl</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.apache.logging.log4j</groupId>\n\t\t\t<artifactId>log4j-core</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<!-- end of test -->\n\t</dependencies>\n</project>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/Apollo.java",
    "content": "package com.ctrip.framework.apollo;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class Apollo {\n  public final static String VERSION =\n      \"java-\" + Apollo.class.getPackage().getImplementationVersion();\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/core/ConfigConsts.java",
    "content": "package com.ctrip.framework.apollo.core;\n\npublic interface ConfigConsts {\n  String NAMESPACE_APPLICATION = \"application\";\n  String CLUSTER_NAME_DEFAULT = \"default\";\n  String CLUSTER_NAMESPACE_SEPARATOR = \"+\";\n  String APOLLO_CLUSTER_KEY = \"apollo.cluster\";\n  String CONFIG_FILE_CONTENT_KEY = \"content\";\n  String NO_APPID_PLACEHOLDER = \"ApolloNoAppIdPlaceHolder\";\n  long NOTIFICATION_ID_PLACEHOLDER = -1;\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/core/MetaDomainConsts.java",
    "content": "package com.ctrip.framework.apollo.core;\n\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.core.utils.ResourceUtils;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Properties;\n\n/**\n * The meta domain will load the meta server from System environment first, if not exist, will load\n * from apollo-env.properties. If neither exists, will load the default meta url.\n * \n * Currently, apollo supports local/dev/fat/uat/lpt/pro environments.\n */\npublic class MetaDomainConsts {\n\n  private static Map<Env, Object> domains = new HashMap<>();\n\n  public static final String DEFAULT_META_URL = \"http://config.local\";\n\n  static {\n    Properties prop = new Properties();\n    prop = ResourceUtils.readConfigFile(\"apollo-env.properties\", prop);\n    Properties env = System.getProperties();\n    domains.put(Env.LOCAL,\n        env.getProperty(\"local_meta\", prop.getProperty(\"local.meta\", DEFAULT_META_URL)));\n    domains.put(Env.DEV,\n        env.getProperty(\"dev_meta\", prop.getProperty(\"dev.meta\", DEFAULT_META_URL)));\n    domains.put(Env.FAT,\n        env.getProperty(\"fat_meta\", prop.getProperty(\"fat.meta\", DEFAULT_META_URL)));\n    domains.put(Env.UAT,\n        env.getProperty(\"uat_meta\", prop.getProperty(\"uat.meta\", DEFAULT_META_URL)));\n    domains.put(Env.LPT,\n        env.getProperty(\"lpt_meta\", prop.getProperty(\"lpt.meta\", DEFAULT_META_URL)));\n    domains.put(Env.PRO,\n        env.getProperty(\"pro_meta\", prop.getProperty(\"pro.meta\", DEFAULT_META_URL)));\n  }\n\n  public static String getDomain(Env env) {\n    return String.valueOf(domains.get(env));\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/core/ServiceNameConsts.java",
    "content": "package com.ctrip.framework.apollo.core;\n\npublic interface ServiceNameConsts {\n\n  String APOLLO_METASERVICE = \"apollo-metaservice\";\n\n  String APOLLO_CONFIGSERVICE = \"apollo-configservice\";\n\n  String APOLLO_ADMINSERVICE = \"apollo-adminservice\";\n\n  String APOLLO_PORTAL = \"apollo-portal\";\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/core/dto/ApolloConfig.java",
    "content": "package com.ctrip.framework.apollo.core.dto;\n\nimport java.util.Map;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class ApolloConfig {\n\n  private String appId;\n\n  private String cluster;\n\n  private String namespaceName;\n\n  private Map<String, String> configurations;\n\n  private String releaseKey;\n\n  public ApolloConfig() {\n  }\n\n  public ApolloConfig(String appId,\n                      String cluster,\n                      String namespaceName,\n                      String releaseKey) {\n    this.appId = appId;\n    this.cluster = cluster;\n    this.namespaceName = namespaceName;\n    this.releaseKey = releaseKey;\n  }\n\n  public String getAppId() {\n    return appId;\n  }\n\n  public String getCluster() {\n    return cluster;\n  }\n\n  public String getNamespaceName() {\n    return namespaceName;\n  }\n\n  public String getReleaseKey() {\n    return releaseKey;\n  }\n\n  public Map<String, String> getConfigurations() {\n    return configurations;\n  }\n\n  public void setAppId(String appId) {\n    this.appId = appId;\n  }\n\n  public void setCluster(String cluster) {\n    this.cluster = cluster;\n  }\n\n  public void setNamespaceName(String namespaceName) {\n    this.namespaceName = namespaceName;\n  }\n\n  public void setReleaseKey(String releaseKey) {\n    this.releaseKey = releaseKey;\n  }\n\n  public void setConfigurations(Map<String, String> configurations) {\n    this.configurations = configurations;\n  }\n\n  @Override\n  public String toString() {\n    final StringBuilder sb = new StringBuilder(\"ApolloConfig{\");\n    sb.append(\"appId='\").append(appId).append('\\'');\n    sb.append(\", cluster='\").append(cluster).append('\\'');\n    sb.append(\", namespaceName='\").append(namespaceName).append('\\'');\n    sb.append(\", configurations=\").append(configurations);\n    sb.append(\", releaseKey='\").append(releaseKey).append('\\'');\n    sb.append('}');\n    return sb.toString();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/core/dto/ApolloConfigNotification.java",
    "content": "package com.ctrip.framework.apollo.core.dto;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class ApolloConfigNotification {\n  private String namespaceName;\n  private long notificationId;\n  private volatile ApolloNotificationMessages messages;\n\n  //for json converter\n  public ApolloConfigNotification() {\n  }\n\n  public ApolloConfigNotification(String namespaceName, long notificationId) {\n    this.namespaceName = namespaceName;\n    this.notificationId = notificationId;\n  }\n\n  public String getNamespaceName() {\n    return namespaceName;\n  }\n\n  public long getNotificationId() {\n    return notificationId;\n  }\n\n  public void setNamespaceName(String namespaceName) {\n    this.namespaceName = namespaceName;\n  }\n\n  public ApolloNotificationMessages getMessages() {\n    return messages;\n  }\n\n  public void setMessages(ApolloNotificationMessages messages) {\n    this.messages = messages;\n  }\n\n  public void addMessage(String key, long notificationId) {\n    if (this.messages == null) {\n      synchronized (this) {\n        if (this.messages == null) {\n          this.messages = new ApolloNotificationMessages();\n        }\n      }\n    }\n    this.messages.put(key, notificationId);\n  }\n\n  @Override\n  public String toString() {\n    return \"ApolloConfigNotification{\" +\n        \"namespaceName='\" + namespaceName + '\\'' +\n        \", notificationId=\" + notificationId +\n        '}';\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/core/dto/ApolloNotificationMessages.java",
    "content": "package com.ctrip.framework.apollo.core.dto;\n\nimport com.google.common.collect.ImmutableMap;\nimport com.google.common.collect.Maps;\n\nimport java.util.Map;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class ApolloNotificationMessages {\n  private Map<String, Long> details;\n\n  public ApolloNotificationMessages() {\n    this(Maps.<String, Long>newHashMap());\n  }\n\n  private ApolloNotificationMessages(Map<String, Long> details) {\n    this.details = details;\n  }\n\n  public void put(String key, long notificationId) {\n    details.put(key, notificationId);\n  }\n\n  public Long get(String key) {\n    return this.details.get(key);\n  }\n\n  public boolean has(String key) {\n    return this.details.containsKey(key);\n  }\n\n  public boolean isEmpty() {\n    return this.details.isEmpty();\n  }\n\n  public Map<String, Long> getDetails() {\n    return details;\n  }\n\n  public void setDetails(Map<String, Long> details) {\n    this.details = details;\n  }\n\n  public void mergeFrom(ApolloNotificationMessages source) {\n    if (source == null) {\n      return;\n    }\n\n    for (Map.Entry<String, Long> entry : source.getDetails().entrySet()) {\n      //to make sure the notification id always grows bigger\n      if (this.has(entry.getKey()) &&\n          this.get(entry.getKey()) >= entry.getValue()) {\n        continue;\n      }\n      this.put(entry.getKey(), entry.getValue());\n    }\n  }\n\n  public ApolloNotificationMessages clone() {\n    return new ApolloNotificationMessages(ImmutableMap.copyOf(this.details));\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/core/dto/ServiceDTO.java",
    "content": "package com.ctrip.framework.apollo.core.dto;\n\npublic class ServiceDTO {\n\n  private String appName;\n\n  private String instanceId;\n\n  private String homepageUrl;\n\n  public String getAppName() {\n    return appName;\n  }\n\n  public String getHomepageUrl() {\n    return homepageUrl;\n  }\n\n  public String getInstanceId() {\n    return instanceId;\n  }\n\n  public void setAppName(String appName) {\n    this.appName = appName;\n  }\n\n  public void setHomepageUrl(String homepageUrl) {\n    this.homepageUrl = homepageUrl;\n  }\n\n  public void setInstanceId(String instanceId) {\n    this.instanceId = instanceId;\n  }\n\n  @Override\n  public String toString() {\n    final StringBuilder sb = new StringBuilder(\"ServiceDTO{\");\n    sb.append(\"appName='\").append(appName).append('\\'');\n    sb.append(\", instanceId='\").append(instanceId).append('\\'');\n    sb.append(\", homepageUrl='\").append(homepageUrl).append('\\'');\n    sb.append('}');\n    return sb.toString();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/core/enums/ConfigFileFormat.java",
    "content": "package com.ctrip.framework.apollo.core.enums;\n\nimport com.ctrip.framework.apollo.core.utils.StringUtils;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic enum ConfigFileFormat {\n  Properties(\"properties\"), XML(\"xml\"), JSON(\"json\"), YML(\"yml\"), YAML(\"yaml\");\n\n  private String value;\n\n  ConfigFileFormat(String value) {\n    this.value = value;\n  }\n\n  public String getValue() {\n    return value;\n  }\n\n  public static ConfigFileFormat fromString(String value) {\n    if (StringUtils.isEmpty(value)) {\n      throw new IllegalArgumentException(\"value can not be empty\");\n    }\n    switch (value) {\n      case \"properties\":\n        return Properties;\n      case \"xml\":\n        return XML;\n      case \"json\":\n        return JSON;\n      case \"yml\":\n        return YML;\n      case \"yaml\":\n        return YAML;\n    }\n    throw new IllegalArgumentException(value + \" can not map enum\");\n  }\n\n  public static boolean isValidFormat(String value) {\n    try {\n      fromString(value);\n      return true;\n    } catch (IllegalArgumentException e) {\n      return false;\n    }\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/core/enums/Env.java",
    "content": "package com.ctrip.framework.apollo.core.enums;\n\nimport com.google.common.base.Preconditions;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic enum Env{\n  LOCAL, DEV, FWS, FAT, UAT, LPT, PRO, TOOLS;\n\n  public static Env fromString(String env) {\n    Env environment = EnvUtils.transformEnv(env);\n    Preconditions.checkArgument(environment != null, String.format(\"Env %s is invalid\", env));\n    return environment;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/core/enums/EnvUtils.java",
    "content": "package com.ctrip.framework.apollo.core.enums;\n\nimport com.ctrip.framework.apollo.core.utils.StringUtils;\n\npublic final class EnvUtils {\n  \n  public static Env transformEnv(String envName) {\n    if (StringUtils.isBlank(envName)) {\n      return null;\n    }\n    switch (envName.trim().toUpperCase()) {\n      case \"LPT\":\n        return Env.LPT;\n      case \"FAT\":\n      case \"FWS\":\n        return Env.FAT;\n      case \"UAT\":\n        return Env.UAT;\n      case \"PRO\":\n      case \"PROD\": //just in case\n        return Env.PRO;\n      case \"DEV\":\n        return Env.DEV;\n      case \"LOCAL\":\n        return Env.LOCAL;\n      case \"TOOLS\":\n        return Env.TOOLS;\n      default:\n        return null;\n    }\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/core/schedule/ExponentialSchedulePolicy.java",
    "content": "package com.ctrip.framework.apollo.core.schedule;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class ExponentialSchedulePolicy implements SchedulePolicy {\n  private final long delayTimeLowerBound;\n  private final long delayTimeUpperBound;\n  private long lastDelayTime;\n\n  public ExponentialSchedulePolicy(long delayTimeLowerBound, long delayTimeUpperBound) {\n    this.delayTimeLowerBound = delayTimeLowerBound;\n    this.delayTimeUpperBound = delayTimeUpperBound;\n  }\n\n  @Override\n  public long fail() {\n    long delayTime = lastDelayTime;\n\n    if (delayTime == 0) {\n      delayTime = delayTimeLowerBound;\n    } else {\n      delayTime = Math.min(lastDelayTime << 1, delayTimeUpperBound);\n    }\n\n    lastDelayTime = delayTime;\n\n    return delayTime;\n  }\n\n  @Override\n  public void success() {\n    lastDelayTime = 0;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/core/schedule/SchedulePolicy.java",
    "content": "package com.ctrip.framework.apollo.core.schedule;\n\n/**\n * Schedule policy\n * @author Jason Song(song_s@ctrip.com)\n */\npublic interface SchedulePolicy {\n  long fail();\n\n  void success();\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/core/utils/ApolloThreadFactory.java",
    "content": "package com.ctrip.framework.apollo.core.utils;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.Arrays;\nimport java.util.HashSet;\nimport java.util.Set;\nimport java.util.concurrent.ThreadFactory;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicLong;\n\npublic class ApolloThreadFactory implements ThreadFactory {\n  private static Logger log = LoggerFactory.getLogger(ApolloThreadFactory.class);\n\n  private final AtomicLong threadNumber = new AtomicLong(1);\n\n  private final String namePrefix;\n\n  private final boolean daemon;\n\n  private static final ThreadGroup threadGroup = new ThreadGroup(\"Apollo\");\n\n  public static ThreadGroup getThreadGroup() {\n    return threadGroup;\n  }\n\n  public static ThreadFactory create(String namePrefix, boolean daemon) {\n    return new ApolloThreadFactory(namePrefix, daemon);\n  }\n\n  public static boolean waitAllShutdown(int timeoutInMillis) {\n    ThreadGroup group = getThreadGroup();\n    Thread[] activeThreads = new Thread[group.activeCount()];\n    group.enumerate(activeThreads);\n    Set<Thread> alives = new HashSet<Thread>(Arrays.asList(activeThreads));\n    Set<Thread> dies = new HashSet<Thread>();\n    log.info(\"Current ACTIVE thread count is: {}\", alives.size());\n    long expire = System.currentTimeMillis() + timeoutInMillis;\n    while (System.currentTimeMillis() < expire) {\n      classify(alives, dies, new ClassifyStandard<Thread>() {\n        @Override\n        public boolean satisfy(Thread thread) {\n          return !thread.isAlive() || thread.isInterrupted() || thread.isDaemon();\n        }\n      });\n      if (alives.size() > 0) {\n        log.info(\"Alive apollo threads: {}\", alives);\n        try {\n          TimeUnit.SECONDS.sleep(2);\n        } catch (InterruptedException ex) {\n          // ignore\n        }\n      } else {\n        log.info(\"All apollo threads are shutdown.\");\n        return true;\n      }\n    }\n    log.warn(\"Some apollo threads are still alive but expire time has reached, alive threads: {}\",\n        alives);\n    return false;\n  }\n\n  private static interface ClassifyStandard<T> {\n    boolean satisfy(T thread);\n  }\n\n  private static <T> void classify(Set<T> src, Set<T> des, ClassifyStandard<T> standard) {\n    Set<T> set = new HashSet<>();\n    for (T t : src) {\n      if (standard.satisfy(t)) {\n        set.add(t);\n      }\n    }\n    src.removeAll(set);\n    des.addAll(set);\n  }\n\n  private ApolloThreadFactory(String namePrefix, boolean daemon) {\n    this.namePrefix = namePrefix;\n    this.daemon = daemon;\n  }\n\n  public Thread newThread(Runnable runnable) {\n    Thread thread = new Thread(threadGroup, runnable,//\n        threadGroup.getName() + \"-\" + namePrefix + \"-\" + threadNumber.getAndIncrement());\n    thread.setDaemon(daemon);\n    if (thread.getPriority() != Thread.NORM_PRIORITY) {\n      thread.setPriority(Thread.NORM_PRIORITY);\n    }\n    return thread;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/core/utils/ByteUtil.java",
    "content": "package com.ctrip.framework.apollo.core.utils;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class ByteUtil {\n  private static final char[] HEX_CHARS = new char[] {\n      '0', '1', '2', '3', '4', '5', '6', '7',\n      '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };\n\n  public static byte int3(final int x) {\n    return (byte) (x >> 24);\n  }\n\n  public static byte int2(final int x) {\n    return (byte) (x >> 16);\n  }\n\n  public static byte int1(final int x) {\n    return (byte) (x >> 8);\n  }\n\n  public static byte int0(final int x) {\n    return (byte) (x);\n  }\n\n  public static String toHexString(byte[] bytes) {\n    char[] chars = new char[bytes.length * 2];\n    int i = 0;\n    for (byte b : bytes) {\n      chars[i++] = HEX_CHARS[b >> 4 & 0xF];\n      chars[i++] = HEX_CHARS[b & 0xF];\n    }\n    return new String(chars);\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/core/utils/ClassLoaderUtil.java",
    "content": "package com.ctrip.framework.apollo.core.utils;\n\nimport com.google.common.base.Strings;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.net.URL;\nimport java.net.URLDecoder;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class ClassLoaderUtil {\n  private static final Logger logger = LoggerFactory.getLogger(ClassLoaderUtil.class);\n\n  private static ClassLoader loader = Thread.currentThread().getContextClassLoader();\n  private static String classPath = \"\";\n\n  static {\n    if (loader == null) {\n      logger.warn(\"Using system class loader\");\n      loader = ClassLoader.getSystemClassLoader();\n    }\n\n    try {\n      URL url = loader.getResource(\"\");\n      // get class path\n      if (url != null) {\n        classPath = url.getPath();\n        classPath = URLDecoder.decode(classPath, \"utf-8\");\n      }\n\n      // 如果是jar包内的，则返回当前路径\n      if (Strings.isNullOrEmpty(classPath) || classPath.contains(\".jar!\")) {\n        classPath = System.getProperty(\"user.dir\");\n      }\n    } catch (Throwable ex) {\n      classPath = System.getProperty(\"user.dir\");\n      logger.warn(\"Failed to locate class path, fallback to user.dir: {}\", classPath, ex);\n    }\n  }\n\n  public static ClassLoader getLoader() {\n    return loader;\n  }\n\n\n  public static String getClassPath() {\n    return classPath;\n  }\n\n  public static boolean isClassPresent(String className) {\n    try {\n      Class.forName(className);\n      return true;\n    } catch (ClassNotFoundException ex) {\n      return false;\n    }\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/core/utils/DNSUtil.java",
    "content": "package com.ctrip.framework.apollo.core.utils;\n\nimport java.net.InetAddress;\nimport java.net.UnknownHostException;\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class DNSUtil {\n\n  public static List<String> resolve(String domainName) throws UnknownHostException {\n    List<String> result = new ArrayList<String>();\n\n    InetAddress[] addresses = InetAddress.getAllByName(domainName);\n    if (addresses != null) {\n      for (InetAddress addr : addresses) {\n        result.add(addr.getHostAddress());\n      }\n    }\n\n    return result;\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/core/utils/MachineUtil.java",
    "content": "package com.ctrip.framework.apollo.core.utils;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.net.NetworkInterface;\nimport java.nio.BufferUnderflowException;\nimport java.nio.ByteBuffer;\nimport java.security.SecureRandom;\nimport java.util.Enumeration;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class MachineUtil {\n  private static final Logger logger = LoggerFactory.getLogger(MachineUtil.class);\n  private static final int MACHINE_IDENTIFIER = createMachineIdentifier();\n\n  public static int getMachineIdentifier() {\n    return MACHINE_IDENTIFIER;\n  }\n\n  /**\n   * Get the machine identifier from mac address\n   *\n   * @see <a href=https://github.com/mongodb/mongo-java-driver/blob/master/bson/src/main/org/bson/types/ObjectId.java>ObjectId.java</a>\n   */\n  private static int createMachineIdentifier() {\n    // build a 2-byte machine piece based on NICs info\n    int machinePiece;\n    try {\n      StringBuilder sb = new StringBuilder();\n      Enumeration<NetworkInterface> e = NetworkInterface.getNetworkInterfaces();\n\n      if (e != null){\n        while (e.hasMoreElements()) {\n          NetworkInterface ni = e.nextElement();\n          sb.append(ni.toString());\n          byte[] mac = ni.getHardwareAddress();\n          if (mac != null) {\n            ByteBuffer bb = ByteBuffer.wrap(mac);\n            try {\n              sb.append(bb.getChar());\n              sb.append(bb.getChar());\n              sb.append(bb.getChar());\n            } catch (BufferUnderflowException shortHardwareAddressException) { //NOPMD\n              // mac with less than 6 bytes. continue\n            }\n          }\n        }\n      }\n\n      machinePiece = sb.toString().hashCode();\n    } catch (Throwable ex) {\n      // exception sometimes happens with IBM JVM, use random\n      machinePiece = (new SecureRandom().nextInt());\n      logger.warn(\n          \"Failed to get machine identifier from network interface, using random number instead\",\n          ex);\n    }\n    return machinePiece;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/core/utils/PropertiesUtil.java",
    "content": "package com.ctrip.framework.apollo.core.utils;\n\nimport java.io.IOException;\nimport java.io.StringWriter;\nimport java.util.Properties;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class PropertiesUtil {\n  /**\n   * Transform the properties to string format\n   * @param properties the properties object\n   * @return the string containing the properties\n   * @throws IOException\n   */\n  public static String toString(Properties properties) throws IOException {\n    StringWriter writer = new StringWriter();\n    properties.store(writer, null);\n    StringBuffer stringBuffer = writer.getBuffer();\n    filterPropertiesComment(stringBuffer);\n    return stringBuffer.toString();\n  }\n\n  /**\n   * filter out the first comment line\n   * @param stringBuffer the string buffer\n   * @return true if filtered successfully, false otherwise\n   */\n  static boolean filterPropertiesComment(StringBuffer stringBuffer) {\n    //check whether has comment in the first line\n    if (stringBuffer.charAt(0) != '#') {\n      return false;\n    }\n    int commentLineIndex = stringBuffer.indexOf(\"\\n\");\n    if (commentLineIndex == -1) {\n      return false;\n    }\n    stringBuffer.delete(0, commentLineIndex + 1);\n    return true;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/core/utils/ResourceUtils.java",
    "content": "package com.ctrip.framework.apollo.core.utils;\n\nimport java.net.URL;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.io.File;\nimport java.io.FileInputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.FileNotFoundException;\nimport java.nio.file.Paths;\nimport java.util.Properties;\n\npublic class ResourceUtils {\n\n  private static final Logger logger = LoggerFactory.getLogger(ResourceUtils.class);\n  private static final String[] DEFAULT_FILE_SEARCH_LOCATIONS = new String[]{\"./config/\", \"./\"};\n\n  @SuppressWarnings(\"unchecked\")\n  public static Properties readConfigFile(String configPath, Properties defaults) {\n    Properties props = new Properties();\n    if (defaults != null) {\n      props.putAll(defaults);\n    }\n\n    InputStream in = loadConfigFileFromDefaultSearchLocations(configPath);\n\n    try {\n      if (in != null) {\n        props.load(in);\n      }\n    } catch (IOException ex) {\n      logger.warn(\"Reading config failed: {}\", ex.getMessage());\n    } finally {\n      if (in != null) {\n        try {\n          in.close();\n        } catch (IOException ex) {\n          logger.warn(\"Close config failed: {}\", ex.getMessage());\n        }\n      }\n    }\n\n    if (logger.isDebugEnabled()) {\n      StringBuilder sb = new StringBuilder();\n      for (String propertyName : props.stringPropertyNames()) {\n        sb.append(propertyName).append('=').append(props.getProperty(propertyName)).append('\\n');\n\n      }\n      if (sb.length() > 0) {\n        logger.debug(\"Reading properties: \\n\" + sb.toString());\n      } else {\n        logger.warn(\"No available properties\");\n      }\n    }\n    return props;\n  }\n\n  private static InputStream loadConfigFileFromDefaultSearchLocations(String configPath) {\n    try {\n      // load from default search locations\n      for (String searchLocation : DEFAULT_FILE_SEARCH_LOCATIONS) {\n        File candidate = Paths.get(searchLocation, configPath).toFile();\n        if (candidate.exists() && candidate.isFile() && candidate.canRead()) {\n          logger.debug(\"Reading config from resource {}\", candidate.getAbsolutePath());\n          return new FileInputStream(candidate);\n        }\n      }\n\n      // load from classpath\n      URL url = ClassLoaderUtil.getLoader().getResource(configPath);\n\n      if (url != null) {\n        InputStream in = getResourceAsStream(url);\n\n        if (in != null) {\n          logger.debug(\"Reading config from resource {}\", url.getPath());\n          return in;\n        }\n      }\n\n      // load outside resource under current user path\n      File candidate = new File(System.getProperty(\"user.dir\"), configPath);\n      if (candidate.exists() && candidate.isFile() && candidate.canRead()) {\n        logger.debug(\"Reading config from resource {}\", candidate.getAbsolutePath());\n        return new FileInputStream(candidate);\n      }\n    } catch (FileNotFoundException e) {\n      //ignore\n    }\n    return null;\n  }\n\n  private static InputStream getResourceAsStream(URL url) {\n    try {\n      return url != null ? url.openStream() : null;\n    } catch (IOException e) {\n      return null;\n    }\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/core/utils/StringUtils.java",
    "content": "package com.ctrip.framework.apollo.core.utils;\n\nimport java.util.Collection;\nimport java.util.Iterator;\n\npublic class StringUtils {\n\n  public static final String EMPTY = \"\";\n\n  /**\n   * <p>\n   * Checks if a String is empty (\"\") or null.\n   * </p>\n   *\n   * <pre>\n   * StringUtils.isEmpty(null)      = true\n   * StringUtils.isEmpty(\"\")        = true\n   * StringUtils.isEmpty(\" \")       = false\n   * StringUtils.isEmpty(\"bob\")     = false\n   * StringUtils.isEmpty(\"  bob  \") = false\n   * </pre>\n   *\n   * <p>\n   * NOTE: This method changed in Lang version 2.0. It no longer trims the String. That functionality is available in isBlank().\n   * </p>\n   *\n   * @param str the String to check, may be null\n   * @return <code>true</code> if the String is empty or null\n   */\n  public static boolean isEmpty(String str) {\n    return str == null || str.length() == 0;\n  }\n\n\n  public static boolean isContainEmpty(String... args){\n    if (args == null){\n      return false;\n    }\n\n    for (String arg: args){\n      if (arg == null || \"\".equals(arg)){\n        return true;\n      }\n    }\n\n    return false;\n  }\n  /**\n   * <p>\n   * Checks if a String is whitespace, empty (\"\") or null.\n   * </p>\n   *\n   * <pre>\n   * StringUtils.isBlank(null)      = true\n   * StringUtils.isBlank(\"\")        = true\n   * StringUtils.isBlank(\" \")       = true\n   * StringUtils.isBlank(\"bob\")     = false\n   * StringUtils.isBlank(\"  bob  \") = false\n   * </pre>\n   *\n   * @param str the String to check, may be null\n   * @return <code>true</code> if the String is null, empty or whitespace\n   */\n  public static boolean isBlank(String str) {\n    int strLen;\n    if (str == null || (strLen = str.length()) == 0) {\n      return true;\n    }\n    for (int i = 0; i < strLen; i++) {\n      if (Character.isWhitespace(str.charAt(i)) == false) {\n        return false;\n      }\n    }\n    return true;\n  }\n\n  /**\n   * <p>\n   * Removes control characters (char &lt;= 32) from both ends of this String returning <code>null</code> if the String is empty\n   * (\"\") after the trim or if it is <code>null</code>.\n   *\n   * <p>\n   * The String is trimmed using {@link String#trim()}. Trim removes start and end characters &lt;= 32. To strip whitespace use\n   * {@link #stripToNull(String)}.\n   * </p>\n   *\n   * <pre>\n   * StringUtils.trimToNull(null)          = null\n   * StringUtils.trimToNull(\"\")            = null\n   * StringUtils.trimToNull(\"     \")       = null\n   * StringUtils.trimToNull(\"abc\")         = \"abc\"\n   * StringUtils.trimToNull(\"    abc    \") = \"abc\"\n   * </pre>\n   *\n   * @param str the String to be trimmed, may be null\n   * @return the trimmed String, <code>null</code> if only chars &lt;= 32, empty or null String input\n   * @since 2.0\n   */\n  public static String trimToNull(String str) {\n    String ts = trim(str);\n    return isEmpty(ts) ? null : ts;\n  }\n\n  /**\n   * <p>\n   * Removes control characters (char &lt;= 32) from both ends of this String returning an empty String (\"\") if the String is empty\n   * (\"\") after the trim or if it is <code>null</code>.\n   *\n   * <p>\n   * The String is trimmed using {@link String#trim()}. Trim removes start and end characters &lt;= 32. To strip whitespace use\n   * {@link #stripToEmpty(String)}.\n   * </p>\n   *\n   * <pre>\n   * StringUtils.trimToEmpty(null)          = \"\"\n   * StringUtils.trimToEmpty(\"\")            = \"\"\n   * StringUtils.trimToEmpty(\"     \")       = \"\"\n   * StringUtils.trimToEmpty(\"abc\")         = \"abc\"\n   * StringUtils.trimToEmpty(\"    abc    \") = \"abc\"\n   * </pre>\n   *\n   * @param str the String to be trimmed, may be null\n   * @return the trimmed String, or an empty String if <code>null</code> input\n   * @since 2.0\n   */\n  public static String trimToEmpty(String str) {\n    return str == null ? EMPTY : str.trim();\n  }\n\n  /**\n   * <p>\n   * Removes control characters (char &lt;= 32) from both ends of this String, handling <code>null</code> by returning\n   * <code>null</code>.\n   * </p>\n   *\n   * <p>\n   * The String is trimmed using {@link String#trim()}. Trim removes start and end characters &lt;= 32. To strip whitespace use\n   * {@link #strip(String)}.\n   * </p>\n   *\n   * <p>\n   * To trim your choice of characters, use the {@link #strip(String, String)} methods.\n   * </p>\n   *\n   * <pre>\n   * StringUtils.trim(null)          = null\n   * StringUtils.trim(\"\")            = \"\"\n   * StringUtils.trim(\"     \")       = \"\"\n   * StringUtils.trim(\"abc\")         = \"abc\"\n   * StringUtils.trim(\"    abc    \") = \"abc\"\n   * </pre>\n   *\n   * @param str the String to be trimmed, may be null\n   * @return the trimmed string, <code>null</code> if null String input\n   */\n  public static String trim(String str) {\n    return str == null ? null : str.trim();\n  }\n\n  /**\n   * <p>\n   * Compares two Strings, returning <code>true</code> if they are equal.\n   * </p>\n   *\n   * <p>\n   * <code>null</code>s are handled without exceptions. Two <code>null</code> references are considered to be equal. The comparison\n   * is case sensitive.\n   * </p>\n   *\n   * <pre>\n   * StringUtils.equals(null, null)   = true\n   * StringUtils.equals(null, \"abc\")  = false\n   * StringUtils.equals(\"abc\", null)  = false\n   * StringUtils.equals(\"abc\", \"abc\") = true\n   * StringUtils.equals(\"abc\", \"ABC\") = false\n   * </pre>\n   *\n   * @param str1 the first String, may be null\n   * @param str2 the second String, may be null\n   * @return <code>true</code> if the Strings are equal, case sensitive, or both <code>null</code>\n   * @see java.lang.String#equals(Object)\n   */\n  public static boolean equals(String str1, String str2) {\n    return str1 == null ? str2 == null : str1.equals(str2);\n  }\n\n  /**\n   * <p>\n   * Compares two Strings, returning <code>true</code> if they are equal ignoring the case.\n   * </p>\n   *\n   * <p>\n   * <code>null</code>s are handled without exceptions. Two <code>null</code> references are considered equal. Comparison is case\n   * insensitive.\n   * </p>\n   *\n   * <pre>\n   * StringUtils.equalsIgnoreCase(null, null)   = true\n   * StringUtils.equalsIgnoreCase(null, \"abc\")  = false\n   * StringUtils.equalsIgnoreCase(\"abc\", null)  = false\n   * StringUtils.equalsIgnoreCase(\"abc\", \"abc\") = true\n   * StringUtils.equalsIgnoreCase(\"abc\", \"ABC\") = true\n   * </pre>\n   *\n   * @param str1 the first String, may be null\n   * @param str2 the second String, may be null\n   * @return <code>true</code> if the Strings are equal, case insensitive, or both <code>null</code>\n   * @see java.lang.String#equalsIgnoreCase(String)\n   */\n  public static boolean equalsIgnoreCase(String str1, String str2) {\n    return str1 == null ? str2 == null : str1.equalsIgnoreCase(str2);\n  }\n\n  /**\n   * <p>\n   * Check if a String starts with a specified prefix.\n   * </p>\n   *\n   * <p>\n   * <code>null</code>s are handled without exceptions. Two <code>null</code> references are considered to be equal. The comparison\n   * is case sensitive.\n   * </p>\n   *\n   * <pre>\n   * StringUtils.startsWith(null, null)      = true\n   * StringUtils.startsWith(null, \"abc\")     = false\n   * StringUtils.startsWith(\"abcdef\", null)  = false\n   * StringUtils.startsWith(\"abcdef\", \"abc\") = true\n   * StringUtils.startsWith(\"ABCDEF\", \"abc\") = false\n   * </pre>\n   *\n   * @param str    the String to check, may be null\n   * @param prefix the prefix to find, may be null\n   * @return <code>true</code> if the String starts with the prefix, case sensitive, or both <code>null</code>\n   * @see java.lang.String#startsWith(String)\n   * @since 2.4\n   */\n  public static boolean startsWith(String str, String prefix) {\n    return startsWith(str, prefix, false);\n  }\n\n  /**\n   * <p>\n   * Check if a String starts with a specified prefix (optionally case insensitive).\n   * </p>\n   *\n   * @param str        the String to check, may be null\n   * @param prefix     the prefix to find, may be null\n   * @param ignoreCase inidicates whether the compare should ignore case (case insensitive) or not.\n   * @return <code>true</code> if the String starts with the prefix or both <code>null</code>\n   * @see java.lang.String#startsWith(String)\n   */\n  private static boolean startsWith(String str, String prefix, boolean ignoreCase) {\n    if (str == null || prefix == null) {\n      return str == null && prefix == null;\n    }\n    if (prefix.length() > str.length()) {\n      return false;\n    }\n    return str.regionMatches(ignoreCase, 0, prefix, 0, prefix.length());\n  }\n\n  /**\n   * <p>\n   * Case insensitive check if a String starts with a specified prefix.\n   * </p>\n   *\n   * <p>\n   * <code>null</code>s are handled without exceptions. Two <code>null</code> references are considered to be equal. The comparison\n   * is case insensitive.\n   * </p>\n   *\n   * <pre>\n   * StringUtils.startsWithIgnoreCase(null, null)      = true\n   * StringUtils.startsWithIgnoreCase(null, \"abc\")     = false\n   * StringUtils.startsWithIgnoreCase(\"abcdef\", null)  = false\n   * StringUtils.startsWithIgnoreCase(\"abcdef\", \"abc\") = true\n   * StringUtils.startsWithIgnoreCase(\"ABCDEF\", \"abc\") = true\n   * </pre>\n   *\n   * @param str    the String to check, may be null\n   * @param prefix the prefix to find, may be null\n   * @return <code>true</code> if the String starts with the prefix, case insensitive, or both <code>null</code>\n   * @see java.lang.String#startsWith(String)\n   * @since 2.4\n   */\n  public static boolean startsWithIgnoreCase(String str, String prefix) {\n    return startsWith(str, prefix, true);\n  }\n\n  /**\n   * <p>\n   * Checks if the String contains only unicode digits. A decimal point is not a unicode digit and returns false.\n   * </p>\n   *\n   * <p>\n   * <code>null</code> will return <code>false</code>. An empty String (length()=0) will return <code>true</code>.\n   * </p>\n   *\n   * <pre>\n   * StringUtils.isNumeric(null)   = false\n   * StringUtils.isNumeric(\"\")     = true\n   * StringUtils.isNumeric(\"  \")   = false\n   * StringUtils.isNumeric(\"123\")  = true\n   * StringUtils.isNumeric(\"12 3\") = false\n   * StringUtils.isNumeric(\"ab2c\") = false\n   * StringUtils.isNumeric(\"12-3\") = false\n   * StringUtils.isNumeric(\"12.3\") = false\n   * </pre>\n   *\n   * @param str the String to check, may be null\n   * @return <code>true</code> if only contains digits, and is non-null\n   */\n  public static boolean isNumeric(String str) {\n    if (str == null) {\n      return false;\n    }\n    int sz = str.length();\n    for (int i = 0; i < sz; i++) {\n      if (Character.isDigit(str.charAt(i)) == false) {\n        return false;\n      }\n    }\n    return true;\n  }\n\n  public static interface StringFormatter<T> {\n    String format(T obj);\n  }\n\n  public static <T> String join(Collection<T> collection, String separator) {\n    return join(collection, separator, new StringFormatter<T>() {\n      @Override\n      public String format(T obj) {\n        return obj.toString();\n      }\n    });\n  }\n\n  public static <T> String join(Collection<T> collection, String separator,\n                                StringFormatter<T> formatter) {\n    Iterator<T> iterator = collection.iterator();\n    // handle null, zero and one elements before building a buffer\n    if (iterator == null) {\n      return null;\n    }\n    if (!iterator.hasNext()) {\n      return EMPTY;\n    }\n    T first = iterator.next();\n    if (!iterator.hasNext()) {\n      return first == null ? \"\" : formatter.format(first);\n    }\n\n    // two or more elements\n    StringBuilder buf = new StringBuilder(256); // Java default is 16, probably too small\n    if (first != null) {\n      buf.append(formatter.format(first));\n    }\n\n    while (iterator.hasNext()) {\n      buf.append(separator);\n      T obj = iterator.next();\n      if (obj != null) {\n        buf.append(formatter.format(obj));\n      }\n    }\n\n    return buf.toString();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/tracer/Tracer.java",
    "content": "package com.ctrip.framework.apollo.tracer;\n\nimport com.ctrip.framework.apollo.tracer.internals.NullMessageProducerManager;\nimport com.ctrip.framework.apollo.tracer.spi.MessageProducer;\nimport com.ctrip.framework.apollo.tracer.spi.MessageProducerManager;\nimport com.ctrip.framework.apollo.tracer.spi.Transaction;\n\nimport com.ctrip.framework.foundation.internals.ServiceBootstrap;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic abstract class Tracer {\n  private static final Logger logger = LoggerFactory.getLogger(Tracer.class);\n  private static final MessageProducerManager NULL_MESSAGE_PRODUCER_MANAGER =\n      new NullMessageProducerManager();\n  private static volatile MessageProducerManager producerManager;\n  private static Object lock = new Object();\n\n  static {\n    getProducer();\n  }\n\n  private static MessageProducer getProducer() {\n    try {\n      if (producerManager == null) {\n        synchronized (lock) {\n          if (producerManager == null) {\n            producerManager = ServiceBootstrap.loadFirst(MessageProducerManager.class);\n          }\n        }\n      }\n    } catch (Throwable ex) {\n      logger.error(\n          \"Failed to initialize message producer manager, use null message producer manager.\", ex);\n      producerManager = NULL_MESSAGE_PRODUCER_MANAGER;\n    }\n    return producerManager.getProducer();\n  }\n\n  public static void logError(String message, Throwable cause) {\n    try {\n      getProducer().logError(message, cause);\n    } catch (Throwable ex) {\n      logger.warn(\"Failed to log error for message: {}, cause: {}\", message, cause, ex);\n    }\n  }\n\n  public static void logError(Throwable cause) {\n    try {\n      getProducer().logError(cause);\n    } catch (Throwable ex) {\n      logger.warn(\"Failed to log error for cause: {}\", cause, ex);\n    }\n  }\n\n  public static void logEvent(String type, String name) {\n    try {\n      getProducer().logEvent(type, name);\n    } catch (Throwable ex) {\n      logger.warn(\"Failed to log event for type: {}, name: {}\", type, name, ex);\n    }\n  }\n\n  public static void logEvent(String type, String name, String status, String nameValuePairs) {\n    try {\n      getProducer().logEvent(type, name, status, nameValuePairs);\n    } catch (Throwable ex) {\n      logger.warn(\"Failed to log event for type: {}, name: {}, status: {}, nameValuePairs: {}\",\n          type, name, status, nameValuePairs, ex);\n    }\n  }\n\n  public static Transaction newTransaction(String type, String name) {\n    try {\n      return getProducer().newTransaction(type, name);\n    } catch (Throwable ex) {\n      logger.warn(\"Failed to create transaction for type: {}, name: {}\", type, name, ex);\n      return NULL_MESSAGE_PRODUCER_MANAGER.getProducer().newTransaction(type, name);\n    }\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/tracer/internals/DefaultMessageProducerManager.java",
    "content": "package com.ctrip.framework.apollo.tracer.internals;\n\nimport com.ctrip.framework.apollo.core.utils.ClassLoaderUtil;\nimport com.ctrip.framework.apollo.tracer.internals.cat.CatMessageProducer;\nimport com.ctrip.framework.apollo.tracer.internals.cat.CatNames;\nimport com.ctrip.framework.apollo.tracer.spi.MessageProducer;\nimport com.ctrip.framework.apollo.tracer.spi.MessageProducerManager;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class DefaultMessageProducerManager implements MessageProducerManager {\n  private static MessageProducer producer;\n\n  public DefaultMessageProducerManager() {\n    if (ClassLoaderUtil.isClassPresent(CatNames.CAT_CLASS)) {\n      producer = new CatMessageProducer();\n    } else {\n      producer = new NullMessageProducerManager().getProducer();\n    }\n  }\n\n  @Override\n  public MessageProducer getProducer() {\n    return producer;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/tracer/internals/NullMessageProducer.java",
    "content": "package com.ctrip.framework.apollo.tracer.internals;\n\nimport com.ctrip.framework.apollo.tracer.spi.MessageProducer;\nimport com.ctrip.framework.apollo.tracer.spi.Transaction;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class NullMessageProducer implements MessageProducer {\n  private static final Transaction NULL_TRANSACTION = new NullTransaction();\n\n  @Override\n  public void logError(Throwable cause) {\n  }\n\n  @Override\n  public void logError(String message, Throwable cause) {\n  }\n\n  @Override\n  public void logEvent(String type, String name) {\n  }\n\n  @Override\n  public void logEvent(String type, String name, String status, String nameValuePairs) {\n  }\n\n  @Override\n  public Transaction newTransaction(String type, String name) {\n    return NULL_TRANSACTION;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/tracer/internals/NullMessageProducerManager.java",
    "content": "package com.ctrip.framework.apollo.tracer.internals;\n\nimport com.ctrip.framework.apollo.tracer.spi.MessageProducer;\nimport com.ctrip.framework.apollo.tracer.spi.MessageProducerManager;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class NullMessageProducerManager implements MessageProducerManager {\n  private static final MessageProducer producer = new NullMessageProducer();\n\n  @Override\n  public MessageProducer getProducer() {\n    return producer;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/tracer/internals/NullTransaction.java",
    "content": "package com.ctrip.framework.apollo.tracer.internals;\n\nimport com.ctrip.framework.apollo.tracer.spi.Transaction;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class NullTransaction implements Transaction {\n  @Override\n  public void setStatus(String status) {\n  }\n\n  @Override\n  public void setStatus(Throwable e) {\n  }\n\n  @Override\n  public void addData(String key, Object value) {\n  }\n\n  @Override\n  public void complete() {\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/tracer/internals/cat/CatMessageProducer.java",
    "content": "package com.ctrip.framework.apollo.tracer.internals.cat;\n\nimport com.ctrip.framework.apollo.tracer.spi.MessageProducer;\nimport com.ctrip.framework.apollo.tracer.spi.Transaction;\n\nimport java.lang.reflect.Method;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class CatMessageProducer implements MessageProducer {\n  private static Class CAT_CLASS;\n  private static Method LOG_ERROR_WITH_CAUSE;\n  private static Method LOG_ERROR_WITH_MESSAGE_AND_CAUSE;\n  private static Method LOG_EVENT_WITH_TYPE_AND_NAME;\n  private static Method LOG_EVENT_WITH_TYPE_AND_NAME_AND_STATUS_AND_NAME_VALUE_PAIRS;\n  private static Method NEW_TRANSACTION_WITH_TYPE_AND_NAME;\n\n  static {\n    try {\n      CAT_CLASS = Class.forName(CatNames.CAT_CLASS);\n      LOG_ERROR_WITH_CAUSE = CAT_CLASS.getMethod(CatNames.LOG_ERROR_METHOD, Throwable.class);\n      LOG_ERROR_WITH_MESSAGE_AND_CAUSE = CAT_CLASS.getMethod(CatNames.LOG_ERROR_METHOD,\n          String.class, Throwable.class);\n      LOG_EVENT_WITH_TYPE_AND_NAME = CAT_CLASS.getMethod(CatNames.LOG_EVENT_METHOD,\n          String.class, String.class);\n      LOG_EVENT_WITH_TYPE_AND_NAME_AND_STATUS_AND_NAME_VALUE_PAIRS =\n          CAT_CLASS.getMethod(CatNames.LOG_EVENT_METHOD, String.class, String.class,\n              String.class, String.class);\n      NEW_TRANSACTION_WITH_TYPE_AND_NAME = CAT_CLASS.getMethod(\n          CatNames.NEW_TRANSACTION_METHOD, String.class, String.class);\n      //eager init CatTransaction\n      CatTransaction.init();\n    } catch (Throwable ex) {\n      throw new IllegalStateException(\"Initialize Cat message producer failed\", ex);\n    }\n  }\n\n  @Override\n  public void logError(Throwable cause) {\n    try {\n      LOG_ERROR_WITH_CAUSE.invoke(null, cause);\n    } catch (Throwable ex) {\n      throw new IllegalStateException(ex);\n    }\n  }\n\n  @Override\n  public void logError(String message, Throwable cause) {\n    try {\n      LOG_ERROR_WITH_MESSAGE_AND_CAUSE.invoke(null, message, cause);\n    } catch (Throwable ex) {\n      throw new IllegalStateException(ex);\n    }\n  }\n\n  @Override\n  public void logEvent(String type, String name) {\n    try {\n      LOG_EVENT_WITH_TYPE_AND_NAME.invoke(null, type, name);\n    } catch (Throwable ex) {\n      throw new IllegalStateException(ex);\n    }\n  }\n\n  @Override\n  public void logEvent(String type, String name, String status, String nameValuePairs) {\n    try {\n      LOG_EVENT_WITH_TYPE_AND_NAME_AND_STATUS_AND_NAME_VALUE_PAIRS.invoke(null, type, name,\n          status, nameValuePairs);\n    } catch (Throwable ex) {\n      throw new IllegalStateException(ex);\n    }\n  }\n\n  @Override\n  public Transaction newTransaction(String type, String name) {\n    try {\n      return new CatTransaction(NEW_TRANSACTION_WITH_TYPE_AND_NAME.invoke(null, type, name));\n    } catch (Throwable ex) {\n      throw new IllegalStateException(ex);\n    }\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/tracer/internals/cat/CatNames.java",
    "content": "package com.ctrip.framework.apollo.tracer.internals.cat;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic interface CatNames {\n  String CAT_CLASS = \"com.dianping.cat.Cat\";\n  String LOG_ERROR_METHOD = \"logError\";\n  String LOG_EVENT_METHOD = \"logEvent\";\n  String NEW_TRANSACTION_METHOD = \"newTransaction\";\n\n  String CAT_TRANSACTION_CLASS = \"com.dianping.cat.message.Transaction\";\n  String SET_STATUS_METHOD = \"setStatus\";\n  String ADD_DATA_METHOD = \"addData\";\n  String COMPLETE_METHOD = \"complete\";\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/tracer/internals/cat/CatTransaction.java",
    "content": "package com.ctrip.framework.apollo.tracer.internals.cat;\n\nimport com.ctrip.framework.apollo.tracer.spi.Transaction;\n\nimport java.lang.reflect.Method;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class CatTransaction implements Transaction {\n  private static Class CAT_TRANSACTION_CLASS;\n  private static Method SET_STATUS_WITH_STRING;\n  private static Method SET_STATUS_WITH_THROWABLE;\n  private static Method ADD_DATA_WITH_KEY_AND_VALUE;\n  private static Method COMPLETE;\n\n  private Object catTransaction;\n\n  static {\n    try {\n      CAT_TRANSACTION_CLASS = Class.forName(CatNames.CAT_TRANSACTION_CLASS);\n      SET_STATUS_WITH_STRING = CAT_TRANSACTION_CLASS.getMethod(CatNames.SET_STATUS_METHOD, String.class);\n      SET_STATUS_WITH_THROWABLE = CAT_TRANSACTION_CLASS.getMethod(CatNames.SET_STATUS_METHOD,\n          Throwable.class);\n      ADD_DATA_WITH_KEY_AND_VALUE = CAT_TRANSACTION_CLASS.getMethod(CatNames.ADD_DATA_METHOD,\n          String.class, Object.class);\n      COMPLETE = CAT_TRANSACTION_CLASS.getMethod(CatNames.COMPLETE_METHOD);\n    } catch (Throwable ex) {\n      throw new IllegalStateException(\"Initialize Cat transaction failed\", ex);\n    }\n  }\n\n  static void init() {\n    //do nothing, just to initialize the static variables\n  }\n\n  public CatTransaction(Object catTransaction) {\n    this.catTransaction = catTransaction;\n  }\n\n  @Override\n  public void setStatus(String status) {\n    try {\n      SET_STATUS_WITH_STRING.invoke(catTransaction, status);\n    } catch (Throwable ex) {\n      throw new IllegalStateException(ex);\n    }\n  }\n\n  @Override\n  public void setStatus(Throwable status) {\n    try {\n      SET_STATUS_WITH_THROWABLE.invoke(catTransaction, status);\n    } catch (Throwable ex) {\n      throw new IllegalStateException(ex);\n    }\n  }\n\n  @Override\n  public void addData(String key, Object value) {\n    try {\n      ADD_DATA_WITH_KEY_AND_VALUE.invoke(catTransaction, key, value);\n    } catch (Throwable ex) {\n      throw new IllegalStateException(ex);\n    }\n  }\n\n  @Override\n  public void complete() {\n    try {\n      COMPLETE.invoke(catTransaction);\n    } catch (Throwable ex) {\n      throw new IllegalStateException(ex);\n    }\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/tracer/spi/MessageProducer.java",
    "content": "package com.ctrip.framework.apollo.tracer.spi;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic interface MessageProducer {\n  /**\n   * Log an error.\n   *\n   * @param cause root cause exception\n   */\n  public void logError(Throwable cause);\n\n  /**\n   * Log an error.\n   *\n   * @param cause root cause exception\n   */\n  public void logError(String message, Throwable cause);\n\n  /**\n   * Log an event in one shot with SUCCESS status.\n   *\n   * @param type event type\n   * @param name event name\n   */\n  public void logEvent(String type, String name);\n\n  /**\n   * Log an event in one shot.\n   *\n   * @param type           event type\n   * @param name           event name\n   * @param status         \"0\" means success, otherwise means error code\n   * @param nameValuePairs name value pairs in the format of \"a=1&b=2&...\"\n   */\n  public void logEvent(String type, String name, String status, String nameValuePairs);\n\n  /**\n   * Create a new transaction with given type and name.\n   *\n   * @param type transaction type\n   * @param name transaction name\n   */\n  public Transaction newTransaction(String type, String name);\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/tracer/spi/MessageProducerManager.java",
    "content": "package com.ctrip.framework.apollo.tracer.spi;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic interface MessageProducerManager {\n  /**\n   * @return the message producer\n   */\n  MessageProducer getProducer();\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/tracer/spi/Transaction.java",
    "content": "package com.ctrip.framework.apollo.tracer.spi;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic interface Transaction {\n  String SUCCESS = \"0\";\n\n  /**\n   * Set the message status.\n   *\n   * @param status message status. \"0\" means success, otherwise error code.\n   */\n  public void setStatus(String status);\n\n  /**\n   * Set the message status with exception class name.\n   *\n   * @param e exception.\n   */\n  public void setStatus(Throwable e);\n\n  /**\n   * add one key-value pair to the message.\n   */\n  public void addData(String key, Object value);\n\n  /**\n   * Complete the message construction.\n   */\n  public void complete();\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/foundation/Foundation.java",
    "content": "package com.ctrip.framework.foundation;\n\nimport com.ctrip.framework.foundation.internals.NullProviderManager;\nimport com.ctrip.framework.foundation.internals.ServiceBootstrap;\nimport com.ctrip.framework.foundation.spi.ProviderManager;\nimport com.ctrip.framework.foundation.spi.provider.ApplicationProvider;\nimport com.ctrip.framework.foundation.spi.provider.NetworkProvider;\nimport com.ctrip.framework.foundation.spi.provider.ServerProvider;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\npublic abstract class Foundation {\n  private static final Logger logger = LoggerFactory.getLogger(Foundation.class);\n  private static Object lock = new Object();\n\n  private static volatile ProviderManager s_manager;\n\n  // Encourage early initialization and fail early if it happens.\n  static {\n    getManager();\n  }\n\n  private static ProviderManager getManager() {\n    try {\n      if (s_manager == null) {\n        // Double locking to make sure only one thread initializes ProviderManager.\n        synchronized (lock) {\n          if (s_manager == null) {\n            s_manager = ServiceBootstrap.loadFirst(ProviderManager.class);\n          }\n        }\n      }\n\n      return s_manager;\n    } catch (Throwable ex) {\n      s_manager = new NullProviderManager();\n      logger.error(\"Initialize ProviderManager failed.\", ex);\n      return s_manager;\n    }\n  }\n\n  public static String getProperty(String name, String defaultValue) {\n    try {\n      return getManager().getProperty(name, defaultValue);\n    } catch (Throwable ex) {\n      logger.error(\"getProperty for {} failed.\", name, ex);\n      return defaultValue;\n    }\n  }\n\n  public static NetworkProvider net() {\n    try {\n      return getManager().provider(NetworkProvider.class);\n    } catch (Exception ex) {\n      logger.error(\"Initialize NetworkProvider failed.\", ex);\n      return NullProviderManager.provider;\n    }\n  }\n\n  public static ServerProvider server() {\n    try {\n      return getManager().provider(ServerProvider.class);\n    } catch (Exception ex) {\n      logger.error(\"Initialize ServerProvider failed.\", ex);\n      return NullProviderManager.provider;\n    }\n  }\n\n  public static ApplicationProvider app() {\n    try {\n      return getManager().provider(ApplicationProvider.class);\n    } catch (Exception ex) {\n      logger.error(\"Initialize ApplicationProvider failed.\", ex);\n      return NullProviderManager.provider;\n    }\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/foundation/internals/DefaultProviderManager.java",
    "content": "package com.ctrip.framework.foundation.internals;\n\nimport java.util.LinkedHashMap;\nimport java.util.Map;\n\nimport com.ctrip.framework.foundation.internals.provider.DefaultApplicationProvider;\nimport com.ctrip.framework.foundation.internals.provider.DefaultNetworkProvider;\nimport com.ctrip.framework.foundation.internals.provider.DefaultServerProvider;\nimport com.ctrip.framework.foundation.spi.ProviderManager;\nimport com.ctrip.framework.foundation.spi.provider.Provider;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\npublic class DefaultProviderManager implements ProviderManager {\n  private static final Logger logger = LoggerFactory.getLogger(DefaultProviderManager.class);\n  private Map<Class<? extends Provider>, Provider> m_providers =\n      new LinkedHashMap<Class<? extends Provider>, Provider>();\n\n  public DefaultProviderManager() {\n    // Load per-application configuration, like app id, from classpath://META-INF/app.properties\n    Provider applicationProvider = new DefaultApplicationProvider();\n    applicationProvider.initialize();\n    register(applicationProvider);\n\n    // Load network parameters\n    Provider networkProvider = new DefaultNetworkProvider();\n    networkProvider.initialize();\n    register(networkProvider);\n\n    // Load environment (fat, fws, uat, prod ...) and dc, from /opt/settings/server.properties, JVM property and/or OS\n    // environment variables.\n    Provider serverProvider = new DefaultServerProvider();\n    serverProvider.initialize();\n    register(serverProvider);\n  }\n\n  public synchronized void register(Provider provider) {\n    m_providers.put(provider.getType(), provider);\n  }\n\n  @Override\n  @SuppressWarnings(\"unchecked\")\n  public <T extends Provider> T provider(Class<T> clazz) {\n    Provider provider = m_providers.get(clazz);\n\n    if (provider != null) {\n      return (T) provider;\n    } else {\n      logger.error(\"No provider [{}] found in DefaultProviderManager, please make sure it is registered in DefaultProviderManager \",\n          clazz.getName());\n      return (T) NullProviderManager.provider;\n    }\n  }\n\n  @Override\n  public String getProperty(String name, String defaultValue) {\n    for (Provider provider : m_providers.values()) {\n      String value = provider.getProperty(name, null);\n\n      if (value != null) {\n        return value;\n      }\n    }\n\n    return defaultValue;\n  }\n\n  @Override\n  public String toString() {\n    StringBuilder sb = new StringBuilder(512);\n    if (null != m_providers) {\n      for (Map.Entry<Class<? extends Provider>, Provider> entry : m_providers.entrySet()) {\n        sb.append(entry.getValue()).append(\"\\n\");\n      }\n    }\n    sb.append(\"(DefaultProviderManager)\").append(\"\\n\");\n    return sb.toString();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/foundation/internals/NetworkInterfaceManager.java",
    "content": "package com.ctrip.framework.foundation.internals;\n\nimport java.net.Inet4Address;\nimport java.net.InetAddress;\nimport java.net.NetworkInterface;\nimport java.net.SocketException;\nimport java.net.UnknownHostException;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.Enumeration;\nimport java.util.List;\nimport java.util.Objects;\n\npublic enum NetworkInterfaceManager {\n  INSTANCE;\n\n  private InetAddress m_local;\n\n  private InetAddress m_localHost;\n\n  private NetworkInterfaceManager() {\n    load();\n  }\n\n  public InetAddress findValidateIp(List<InetAddress> addresses) {\n    InetAddress local = null;\n    int maxWeight = -1;\n    for (InetAddress address : addresses) {\n      if (address instanceof Inet4Address) {\n        int weight = 0;\n\n        if (address.isSiteLocalAddress()) {\n          weight += 8;\n        }\n\n        if (address.isLinkLocalAddress()) {\n          weight += 4;\n        }\n\n        if (address.isLoopbackAddress()) {\n          weight += 2;\n        }\n\n        // has host name\n        // TODO fix performance issue when calling getHostName\n        if (!Objects.equals(address.getHostName(), address.getHostAddress())) {\n          weight += 1;\n        }\n\n        if (weight > maxWeight) {\n          maxWeight = weight;\n          local = address;\n        }\n      }\n    }\n    return local;\n  }\n\n  public String getLocalHostAddress() {\n    return m_local.getHostAddress();\n  }\n\n  public String getLocalHostName() {\n    try {\n      if (null == m_localHost) {\n        m_localHost = InetAddress.getLocalHost();\n      }\n      return m_localHost.getHostName();\n    } catch (UnknownHostException e) {\n      return m_local.getHostName();\n    }\n  }\n\n  private String getProperty(String name) {\n    String value = null;\n\n    value = System.getProperty(name);\n\n    if (value == null) {\n      value = System.getenv(name);\n    }\n\n    return value;\n  }\n\n  private void load() {\n    String ip = getProperty(\"host.ip\");\n\n    if (ip != null) {\n      try {\n        m_local = InetAddress.getByName(ip);\n        return;\n      } catch (Exception e) {\n        System.err.println(e);\n        // ignore\n      }\n    }\n\n    try {\n      Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();\n      List<NetworkInterface> nis = interfaces == null ? Collections.<NetworkInterface>emptyList() : Collections.list(interfaces);\n      List<InetAddress> addresses = new ArrayList<InetAddress>();\n      InetAddress local = null;\n\n      try {\n        for (NetworkInterface ni : nis) {\n          if (ni.isUp() && !ni.isLoopback()) {\n            addresses.addAll(Collections.list(ni.getInetAddresses()));\n          }\n        }\n        local = findValidateIp(addresses);\n      } catch (Exception e) {\n        // ignore\n      }\n      if (local != null) {\n        m_local = local;\n        return;\n      }\n    } catch (SocketException e) {\n      // ignore it\n    }\n\n    m_local = InetAddress.getLoopbackAddress();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/foundation/internals/NullProviderManager.java",
    "content": "package com.ctrip.framework.foundation.internals;\n\nimport com.ctrip.framework.foundation.internals.provider.NullProvider;\nimport com.ctrip.framework.foundation.spi.ProviderManager;\n\npublic class NullProviderManager implements ProviderManager {\n  public static final NullProvider provider = new NullProvider();\n\n  @Override\n  public String getProperty(String name, String defaultValue) {\n    return defaultValue;\n  }\n\n  @Override\n  public NullProvider provider(Class clazz) {\n    return provider;\n  }\n\n  @Override\n  public String toString() {\n    return provider.toString();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/foundation/internals/ServiceBootstrap.java",
    "content": "package com.ctrip.framework.foundation.internals;\n\nimport java.util.Iterator;\nimport java.util.ServiceLoader;\n\npublic class ServiceBootstrap {\n  public static <S> S loadFirst(Class<S> clazz) {\n    Iterator<S> iterator = loadAll(clazz);\n    if (!iterator.hasNext()) {\n      throw new IllegalStateException(String.format(\n          \"No implementation defined in /META-INF/services/%s, please check whether the file exists and has the right implementation class!\",\n          clazz.getName()));\n    }\n    return iterator.next();\n  }\n\n  private static <S> Iterator<S> loadAll(Class<S> clazz) {\n    ServiceLoader<S> loader = ServiceLoader.load(clazz);\n\n    return loader.iterator();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/foundation/internals/Utils.java",
    "content": "package com.ctrip.framework.foundation.internals;\n\nimport com.google.common.base.Strings;\n\npublic class Utils {\n  public static boolean isBlank(String str) {\n    return Strings.nullToEmpty(str).trim().isEmpty();\n  }\n\n  public static boolean isOSWindows() {\n    String osName = System.getProperty(\"os.name\");\n    if (Utils.isBlank(osName)) {\n      return false;\n    }\n    return osName.startsWith(\"Windows\");\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/foundation/internals/io/BOMInputStream.java",
    "content": "/*\n * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE\n * file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file\n * to You under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance with the\n * License. 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 distributed under the License is distributed on\n * an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the\n * specific language governing permissions and limitations under the License.\n */\npackage com.ctrip.framework.foundation.internals.io;\n\n\nimport static com.ctrip.framework.foundation.internals.io.IOUtils.EOF;\n\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.util.Arrays;\nimport java.util.Comparator;\nimport java.util.List;\n\n/**\n * This class is used to wrap a stream that includes an encoded {@link ByteOrderMark} as its first bytes.\n *\n * This class detects these bytes and, if required, can automatically skip them and return the subsequent byte as the\n * first byte in the stream.\n *\n * The {@link ByteOrderMark} implementation has the following pre-defined BOMs:\n * <ul>\n * <li>UTF-8 - {@link ByteOrderMark#UTF_8}</li>\n * <li>UTF-16BE - {@link ByteOrderMark#UTF_16LE}</li>\n * <li>UTF-16LE - {@link ByteOrderMark#UTF_16BE}</li>\n * <li>UTF-32BE - {@link ByteOrderMark#UTF_32LE}</li>\n * <li>UTF-32LE - {@link ByteOrderMark#UTF_32BE}</li>\n * </ul>\n *\n *\n * <h3>Example 1 - Detect and exclude a UTF-8 BOM</h3>\n *\n * <pre>\n * BOMInputStream bomIn = new BOMInputStream(in);\n * if (bomIn.hasBOM()) {\n *   // has a UTF-8 BOM\n * }\n * </pre>\n *\n * <h3>Example 2 - Detect a UTF-8 BOM (but don't exclude it)</h3>\n *\n * <pre>\n * boolean include = true;\n * BOMInputStream bomIn = new BOMInputStream(in, include);\n * if (bomIn.hasBOM()) {\n *   // has a UTF-8 BOM\n * }\n * </pre>\n *\n * <h3>Example 3 - Detect Multiple BOMs</h3>\n *\n * <pre>\n * BOMInputStream bomIn = new BOMInputStream(in, ByteOrderMark.UTF_16LE, ByteOrderMark.UTF_16BE, ByteOrderMark.UTF_32LE,\n *     ByteOrderMark.UTF_32BE);\n * if (bomIn.hasBOM() == false) {\n *   // No BOM found\n * } else if (bomIn.hasBOM(ByteOrderMark.UTF_16LE)) {\n *   // has a UTF-16LE BOM\n * } else if (bomIn.hasBOM(ByteOrderMark.UTF_16BE)) {\n *   // has a UTF-16BE BOM\n * } else if (bomIn.hasBOM(ByteOrderMark.UTF_32LE)) {\n *   // has a UTF-32LE BOM\n * } else if (bomIn.hasBOM(ByteOrderMark.UTF_32BE)) {\n *   // has a UTF-32BE BOM\n * }\n * </pre>\n *\n * @see ByteOrderMark\n * @see <a href=\"http://en.wikipedia.org/wiki/Byte_order_mark\">Wikipedia - Byte Order Mark</a>\n * @version $Id: BOMInputStream.java 1686527 2015-06-20 06:31:39Z krosenvold $\n * @since 2.0\n */\npublic class BOMInputStream extends ProxyInputStream {\n  private final boolean include;\n  /**\n   * BOMs are sorted from longest to shortest.\n   */\n  private final List<ByteOrderMark> boms;\n  private ByteOrderMark byteOrderMark;\n  private int[] firstBytes;\n  private int fbLength;\n  private int fbIndex;\n  private int markFbIndex;\n  private boolean markedAtStart;\n\n  /**\n   * Constructs a new BOM InputStream that excludes a {@link ByteOrderMark#UTF_8} BOM.\n   *\n   * @param delegate the InputStream to delegate to\n   */\n  public BOMInputStream(final InputStream delegate) {\n    this(delegate, false, ByteOrderMark.UTF_8);\n  }\n\n  /**\n   * Constructs a new BOM InputStream that detects a a {@link ByteOrderMark#UTF_8} and optionally includes it.\n   *\n   * @param delegate the InputStream to delegate to\n   * @param include true to include the UTF-8 BOM or false to exclude it\n   */\n  public BOMInputStream(final InputStream delegate, final boolean include) {\n    this(delegate, include, ByteOrderMark.UTF_8);\n  }\n\n  /**\n   * Constructs a new BOM InputStream that excludes the specified BOMs.\n   *\n   * @param delegate the InputStream to delegate to\n   * @param boms The BOMs to detect and exclude\n   */\n  public BOMInputStream(final InputStream delegate, final ByteOrderMark... boms) {\n    this(delegate, false, boms);\n  }\n\n  /**\n   * Compares ByteOrderMark objects in descending length order.\n   */\n  private static final Comparator<ByteOrderMark> ByteOrderMarkLengthComparator = new Comparator<ByteOrderMark>() {\n\n    public int compare(final ByteOrderMark bom1, final ByteOrderMark bom2) {\n      final int len1 = bom1.length();\n      final int len2 = bom2.length();\n      if (len1 > len2) {\n        return EOF;\n      }\n      if (len2 > len1) {\n        return 1;\n      }\n      return 0;\n    }\n  };\n\n  /**\n   * Constructs a new BOM InputStream that detects the specified BOMs and optionally includes them.\n   *\n   * @param delegate the InputStream to delegate to\n   * @param include true to include the specified BOMs or false to exclude them\n   * @param boms The BOMs to detect and optionally exclude\n   */\n  public BOMInputStream(final InputStream delegate, final boolean include, final ByteOrderMark... boms) {\n    super(delegate);\n    if (boms == null || boms.length == 0) {\n      throw new IllegalArgumentException(\"No BOMs specified\");\n    }\n    this.include = include;\n    // Sort the BOMs to match the longest BOM first because some BOMs have the same starting two bytes.\n    Arrays.sort(boms, ByteOrderMarkLengthComparator);\n    this.boms = Arrays.asList(boms);\n\n  }\n\n  /**\n   * Indicates whether the stream contains one of the specified BOMs.\n   *\n   * @return true if the stream has one of the specified BOMs, otherwise false if it does not\n   * @throws IOException if an error reading the first bytes of the stream occurs\n   */\n  public boolean hasBOM() throws IOException {\n    return getBOM() != null;\n  }\n\n  /**\n   * Indicates whether the stream contains the specified BOM.\n   *\n   * @param bom The BOM to check for\n   * @return true if the stream has the specified BOM, otherwise false if it does not\n   * @throws IllegalArgumentException if the BOM is not one the stream is configured to detect\n   * @throws IOException if an error reading the first bytes of the stream occurs\n   */\n  public boolean hasBOM(final ByteOrderMark bom) throws IOException {\n    if (!boms.contains(bom)) {\n      throw new IllegalArgumentException(\"Stream not configure to detect \" + bom);\n    }\n    return byteOrderMark != null && getBOM().equals(bom);\n  }\n\n  /**\n   * Return the BOM (Byte Order Mark).\n   *\n   * @return The BOM or null if none\n   * @throws IOException if an error reading the first bytes of the stream occurs\n   */\n  public ByteOrderMark getBOM() throws IOException {\n    if (firstBytes == null) {\n      fbLength = 0;\n      // BOMs are sorted from longest to shortest\n      final int maxBomSize = boms.get(0).length();\n      firstBytes = new int[maxBomSize];\n      // Read first maxBomSize bytes\n      for (int i = 0; i < firstBytes.length; i++) {\n        firstBytes[i] = in.read();\n        fbLength++;\n        if (firstBytes[i] < 0) {\n          break;\n        }\n      }\n      // match BOM in firstBytes\n      byteOrderMark = find();\n      if (byteOrderMark != null) {\n        if (!include) {\n          if (byteOrderMark.length() < firstBytes.length) {\n            fbIndex = byteOrderMark.length();\n          } else {\n            fbLength = 0;\n          }\n        }\n      }\n    }\n    return byteOrderMark;\n  }\n\n  /**\n   * Return the BOM charset Name - {@link ByteOrderMark#getCharsetName()}.\n   *\n   * @return The BOM charset Name or null if no BOM found\n   * @throws IOException if an error reading the first bytes of the stream occurs\n   *\n   */\n  public String getBOMCharsetName() throws IOException {\n    getBOM();\n    return byteOrderMark == null ? null : byteOrderMark.getCharsetName();\n  }\n\n  /**\n   * This method reads and either preserves or skips the first bytes in the stream. It behaves like the single-byte\n   * <code>read()</code> method, either returning a valid byte or -1 to indicate that the initial bytes have been\n   * processed already.\n   *\n   * @return the byte read (excluding BOM) or -1 if the end of stream\n   * @throws IOException if an I/O error occurs\n   */\n  private int readFirstBytes() throws IOException {\n    getBOM();\n    return fbIndex < fbLength ? firstBytes[fbIndex++] : EOF;\n  }\n\n  /**\n   * Find a BOM with the specified bytes.\n   *\n   * @return The matched BOM or null if none matched\n   */\n  private ByteOrderMark find() {\n    for (final ByteOrderMark bom : boms) {\n      if (matches(bom)) {\n        return bom;\n      }\n    }\n    return null;\n  }\n\n  /**\n   * Check if the bytes match a BOM.\n   *\n   * @param bom The BOM\n   * @return true if the bytes match the bom, otherwise false\n   */\n  private boolean matches(final ByteOrderMark bom) {\n    // if (bom.length() != fbLength) {\n    // return false;\n    // }\n    // firstBytes may be bigger than the BOM bytes\n    for (int i = 0; i < bom.length(); i++) {\n      if (bom.get(i) != firstBytes[i]) {\n        return false;\n      }\n    }\n    return true;\n  }\n\n  // ----------------------------------------------------------------------------\n  // Implementation of InputStream\n  // ----------------------------------------------------------------------------\n\n  /**\n   * Invokes the delegate's <code>read()</code> method, detecting and optionally skipping BOM.\n   *\n   * @return the byte read (excluding BOM) or -1 if the end of stream\n   * @throws IOException if an I/O error occurs\n   */\n  @Override\n  public int read() throws IOException {\n    final int b = readFirstBytes();\n    return b >= 0 ? b : in.read();\n  }\n\n  /**\n   * Invokes the delegate's <code>read(byte[], int, int)</code> method, detecting and optionally skipping BOM.\n   *\n   * @param buf the buffer to read the bytes into\n   * @param off The start offset\n   * @param len The number of bytes to read (excluding BOM)\n   * @return the number of bytes read or -1 if the end of stream\n   * @throws IOException if an I/O error occurs\n   */\n  @Override\n  public int read(final byte[] buf, int off, int len) throws IOException {\n    int firstCount = 0;\n    int b = 0;\n    while (len > 0 && b >= 0) {\n      b = readFirstBytes();\n      if (b >= 0) {\n        buf[off++] = (byte) (b & 0xFF);\n        len--;\n        firstCount++;\n      }\n    }\n    final int secondCount = in.read(buf, off, len);\n    return secondCount < 0 ? firstCount > 0 ? firstCount : EOF : firstCount + secondCount;\n  }\n\n  /**\n   * Invokes the delegate's <code>read(byte[])</code> method, detecting and optionally skipping BOM.\n   *\n   * @param buf the buffer to read the bytes into\n   * @return the number of bytes read (excluding BOM) or -1 if the end of stream\n   * @throws IOException if an I/O error occurs\n   */\n  @Override\n  public int read(final byte[] buf) throws IOException {\n    return read(buf, 0, buf.length);\n  }\n\n  /**\n   * Invokes the delegate's <code>mark(int)</code> method.\n   *\n   * @param readlimit read ahead limit\n   */\n  @Override\n  public synchronized void mark(final int readlimit) {\n    markFbIndex = fbIndex;\n    markedAtStart = firstBytes == null;\n    in.mark(readlimit);\n  }\n\n  /**\n   * Invokes the delegate's <code>reset()</code> method.\n   *\n   * @throws IOException if an I/O error occurs\n   */\n  @Override\n  public synchronized void reset() throws IOException {\n    fbIndex = markFbIndex;\n    if (markedAtStart) {\n      firstBytes = null;\n    }\n\n    in.reset();\n  }\n\n  /**\n   * Invokes the delegate's <code>skip(long)</code> method, detecting and optionallyskipping BOM.\n   *\n   * @param n the number of bytes to skip\n   * @return the number of bytes to skipped or -1 if the end of stream\n   * @throws IOException if an I/O error occurs\n   */\n  @Override\n  public long skip(long n) throws IOException {\n    int skipped = 0;\n    while ((n > skipped) && (readFirstBytes() >= 0)) {\n      skipped++;\n    }\n    return in.skip(n - skipped) + skipped;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/foundation/internals/io/ByteOrderMark.java",
    "content": "/*\n * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE\n * file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file\n * to You under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance with the\n * License. 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 distributed under the License is distributed on\n * an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the\n * specific language governing permissions and limitations under the License.\n */\npackage com.ctrip.framework.foundation.internals.io;\n\nimport java.io.Serializable;\n\n/**\n * Byte Order Mark (BOM) representation - see {@link BOMInputStream}.\n *\n * @see BOMInputStream\n * @see <a href=\"http://en.wikipedia.org/wiki/Byte_order_mark\">Wikipedia: Byte Order Mark</a>\n * @see <a href=\"http://www.w3.org/TR/2006/REC-xml-20060816/#sec-guessing\">W3C: Autodetection of Character Encodings\n *      (Non-Normative)</a>\n * @version $Id: ByteOrderMark.java 1586504 2014-04-10 23:34:37Z ggregory $\n * @since 2.0\n */\npublic class ByteOrderMark implements Serializable {\n\n  private static final long serialVersionUID = 1L;\n\n  /** UTF-8 BOM */\n  public static final ByteOrderMark UTF_8 = new ByteOrderMark(\"UTF-8\", 0xEF, 0xBB, 0xBF);\n\n  /** UTF-16BE BOM (Big-Endian) */\n  public static final ByteOrderMark UTF_16BE = new ByteOrderMark(\"UTF-16BE\", 0xFE, 0xFF);\n\n  /** UTF-16LE BOM (Little-Endian) */\n  public static final ByteOrderMark UTF_16LE = new ByteOrderMark(\"UTF-16LE\", 0xFF, 0xFE);\n\n  /**\n   * UTF-32BE BOM (Big-Endian)\n   * \n   * @since 2.2\n   */\n  public static final ByteOrderMark UTF_32BE = new ByteOrderMark(\"UTF-32BE\", 0x00, 0x00, 0xFE, 0xFF);\n\n  /**\n   * UTF-32LE BOM (Little-Endian)\n   * \n   * @since 2.2\n   */\n  public static final ByteOrderMark UTF_32LE = new ByteOrderMark(\"UTF-32LE\", 0xFF, 0xFE, 0x00, 0x00);\n\n  /**\n   * Unicode BOM character; external form depends on the encoding.\n   * \n   * @see <a href=\"http://unicode.org/faq/utf_bom.html#BOM\">Byte Order Mark (BOM) FAQ</a>\n   * @since 2.5\n   */\n  public static final char UTF_BOM = '\\uFEFF';\n\n  private final String charsetName;\n  private final int[] bytes;\n\n  /**\n   * Construct a new BOM.\n   *\n   * @param charsetName The name of the charset the BOM represents\n   * @param bytes The BOM's bytes\n   * @throws IllegalArgumentException if the charsetName is null or zero length\n   * @throws IllegalArgumentException if the bytes are null or zero length\n   */\n  public ByteOrderMark(final String charsetName, final int... bytes) {\n    if (charsetName == null || charsetName.isEmpty()) {\n      throw new IllegalArgumentException(\"No charsetName specified\");\n    }\n    if (bytes == null || bytes.length == 0) {\n      throw new IllegalArgumentException(\"No bytes specified\");\n    }\n    this.charsetName = charsetName;\n    this.bytes = new int[bytes.length];\n    System.arraycopy(bytes, 0, this.bytes, 0, bytes.length);\n  }\n\n  /**\n   * Return the name of the {@link java.nio.charset.Charset} the BOM represents.\n   *\n   * @return the character set name\n   */\n  public String getCharsetName() {\n    return charsetName;\n  }\n\n  /**\n   * Return the length of the BOM's bytes.\n   *\n   * @return the length of the BOM's bytes\n   */\n  public int length() {\n    return bytes.length;\n  }\n\n  /**\n   * The byte at the specified position.\n   *\n   * @param pos The position\n   * @return The specified byte\n   */\n  public int get(final int pos) {\n    return bytes[pos];\n  }\n\n  /**\n   * Return a copy of the BOM's bytes.\n   *\n   * @return a copy of the BOM's bytes\n   */\n  public byte[] getBytes() {\n    final byte[] copy = new byte[bytes.length];\n    for (int i = 0; i < bytes.length; i++) {\n      copy[i] = (byte) bytes[i];\n    }\n    return copy;\n  }\n\n  /**\n   * Indicates if this BOM's bytes equals another.\n   *\n   * @param obj The object to compare to\n   * @return true if the bom's bytes are equal, otherwise false\n   */\n  @Override\n  public boolean equals(final Object obj) {\n    if (!(obj instanceof ByteOrderMark)) {\n      return false;\n    }\n    final ByteOrderMark bom = (ByteOrderMark) obj;\n    if (bytes.length != bom.length()) {\n      return false;\n    }\n    for (int i = 0; i < bytes.length; i++) {\n      if (bytes[i] != bom.get(i)) {\n        return false;\n      }\n    }\n    return true;\n  }\n\n  /**\n   * Return the hashcode for this BOM.\n   *\n   * @return the hashcode for this BOM.\n   * @see Object#hashCode()\n   */\n  @Override\n  public int hashCode() {\n    int hashCode = getClass().hashCode();\n    for (final int b : bytes) {\n      hashCode += b;\n    }\n    return hashCode;\n  }\n\n  /**\n   * Provide a String representation of the BOM.\n   *\n   * @return the length of the BOM's bytes\n   */\n  @Override\n  public String toString() {\n    final StringBuilder builder = new StringBuilder();\n    builder.append(getClass().getSimpleName());\n    builder.append('[');\n    builder.append(charsetName);\n    builder.append(\": \");\n    for (int i = 0; i < bytes.length; i++) {\n      if (i > 0) {\n        builder.append(\",\");\n      }\n      builder.append(\"0x\");\n      builder.append(Integer.toHexString(0xFF & bytes[i]).toUpperCase());\n    }\n    builder.append(']');\n    return builder.toString();\n  }\n\n}\n\n\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/foundation/internals/io/IOUtils.java",
    "content": "package com.ctrip.framework.foundation.internals.io;\n\npublic class IOUtils {\n  public static final int EOF = -1;\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/foundation/internals/io/ProxyInputStream.java",
    "content": "/*\n * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE\n * file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file\n * to You under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance with the\n * License. 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 distributed under the License is distributed on\n * an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the\n * specific language governing permissions and limitations under the License.\n */\npackage com.ctrip.framework.foundation.internals.io;\n\nimport static com.ctrip.framework.foundation.internals.io.IOUtils.EOF;\n\nimport java.io.FilterInputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\n\n/**\n * A Proxy stream which acts as expected, that is it passes the method calls on to the proxied stream and doesn't change\n * which methods are being called.\n * <p>\n * It is an alternative base class to FilterInputStream to increase reusability, because FilterInputStream changes the\n * methods being called, such as read(byte[]) to read(byte[], int, int).\n * <p>\n * See the protected methods for ways in which a subclass can easily decorate a stream with custom pre-, post- or error\n * processing functionality.\n *\n * @version $Id: ProxyInputStream.java 1603493 2014-06-18 15:46:07Z ggregory $\n */\npublic abstract class ProxyInputStream extends FilterInputStream {\n\n  /**\n   * Constructs a new ProxyInputStream.\n   *\n   * @param proxy the InputStream to delegate to\n   */\n  public ProxyInputStream(final InputStream proxy) {\n    super(proxy);\n    // the proxy is stored in a protected superclass variable named 'in'\n  }\n\n  /**\n   * Invokes the delegate's <code>read()</code> method.\n   * \n   * @return the byte read or -1 if the end of stream\n   * @throws IOException if an I/O error occurs\n   */\n  @Override\n  public int read() throws IOException {\n    try {\n      beforeRead(1);\n      final int b = in.read();\n      afterRead(b != EOF ? 1 : EOF);\n      return b;\n    } catch (final IOException e) {\n      handleIOException(e);\n      return EOF;\n    }\n  }\n\n  /**\n   * Invokes the delegate's <code>read(byte[])</code> method.\n   * \n   * @param bts the buffer to read the bytes into\n   * @return the number of bytes read or EOF if the end of stream\n   * @throws IOException if an I/O error occurs\n   */\n  @Override\n  public int read(final byte[] bts) throws IOException {\n    try {\n      beforeRead(bts != null ? bts.length : 0);\n      final int n = in.read(bts);\n      afterRead(n);\n      return n;\n    } catch (final IOException e) {\n      handleIOException(e);\n      return EOF;\n    }\n  }\n\n  /**\n   * Invokes the delegate's <code>read(byte[], int, int)</code> method.\n   * \n   * @param bts the buffer to read the bytes into\n   * @param off The start offset\n   * @param len The number of bytes to read\n   * @return the number of bytes read or -1 if the end of stream\n   * @throws IOException if an I/O error occurs\n   */\n  @Override\n  public int read(final byte[] bts, final int off, final int len) throws IOException {\n    try {\n      beforeRead(len);\n      final int n = in.read(bts, off, len);\n      afterRead(n);\n      return n;\n    } catch (final IOException e) {\n      handleIOException(e);\n      return EOF;\n    }\n  }\n\n  /**\n   * Invokes the delegate's <code>skip(long)</code> method.\n   * \n   * @param ln the number of bytes to skip\n   * @return the actual number of bytes skipped\n   * @throws IOException if an I/O error occurs\n   */\n  @Override\n  public long skip(final long ln) throws IOException {\n    try {\n      return in.skip(ln);\n    } catch (final IOException e) {\n      handleIOException(e);\n      return 0;\n    }\n  }\n\n  /**\n   * Invokes the delegate's <code>available()</code> method.\n   * \n   * @return the number of available bytes\n   * @throws IOException if an I/O error occurs\n   */\n  @Override\n  public int available() throws IOException {\n    try {\n      return super.available();\n    } catch (final IOException e) {\n      handleIOException(e);\n      return 0;\n    }\n  }\n\n  /**\n   * Invokes the delegate's <code>close()</code> method.\n   * \n   * @throws IOException if an I/O error occurs\n   */\n  @Override\n  public void close() throws IOException {\n    try {\n      in.close();\n    } catch (final IOException e) {\n      handleIOException(e);\n    }\n  }\n\n  /**\n   * Invokes the delegate's <code>mark(int)</code> method.\n   * \n   * @param readlimit read ahead limit\n   */\n  @Override\n  public synchronized void mark(final int readlimit) {\n    in.mark(readlimit);\n  }\n\n  /**\n   * Invokes the delegate's <code>reset()</code> method.\n   * \n   * @throws IOException if an I/O error occurs\n   */\n  @Override\n  public synchronized void reset() throws IOException {\n    try {\n      in.reset();\n    } catch (final IOException e) {\n      handleIOException(e);\n    }\n  }\n\n  /**\n   * Invokes the delegate's <code>markSupported()</code> method.\n   * \n   * @return true if mark is supported, otherwise false\n   */\n  @Override\n  public boolean markSupported() {\n    return in.markSupported();\n  }\n\n  /**\n   * Invoked by the read methods before the call is proxied. The number of bytes that the caller wanted to read (1 for\n   * the {@link #read()} method, buffer length for {@link #read(byte[])}, etc.) is given as an argument.\n   * <p>\n   * Subclasses can override this method to add common pre-processing functionality without having to override all the\n   * read methods. The default implementation does nothing.\n   * <p>\n   * Note this method is <em>not</em> called from {@link #skip(long)} or {@link #reset()}. You need to explicitly\n   * override those methods if you want to add pre-processing steps also to them.\n   *\n   * @since 2.0\n   * @param n number of bytes that the caller asked to be read\n   * @throws IOException if the pre-processing fails\n   */\n  protected void beforeRead(final int n) throws IOException {\n    // no-op\n  }\n\n  /**\n   * Invoked by the read methods after the proxied call has returned successfully. The number of bytes returned to the\n   * caller (or -1 if the end of stream was reached) is given as an argument.\n   * <p>\n   * Subclasses can override this method to add common post-processing functionality without having to override all the\n   * read methods. The default implementation does nothing.\n   * <p>\n   * Note this method is <em>not</em> called from {@link #skip(long)} or {@link #reset()}. You need to explicitly\n   * override those methods if you want to add post-processing steps also to them.\n   *\n   * @since 2.0\n   * @param n number of bytes read, or -1 if the end of stream was reached\n   * @throws IOException if the post-processing fails\n   */\n  protected void afterRead(final int n) throws IOException {\n    // no-op\n  }\n\n  /**\n   * Handle any IOExceptions thrown.\n   * <p>\n   * This method provides a point to implement custom exception handling. The default behaviour is to re-throw the\n   * exception.\n   * \n   * @param e The IOException thrown\n   * @throws IOException if an I/O error occurs\n   * @since 2.0\n   */\n  protected void handleIOException(final IOException e) throws IOException {\n    throw e;\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/foundation/internals/provider/DefaultApplicationProvider.java",
    "content": "package com.ctrip.framework.foundation.internals.provider;\n\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\nimport java.nio.charset.StandardCharsets;\nimport java.util.Properties;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.ctrip.framework.foundation.internals.Utils;\nimport com.ctrip.framework.foundation.internals.io.BOMInputStream;\nimport com.ctrip.framework.foundation.spi.provider.ApplicationProvider;\nimport com.ctrip.framework.foundation.spi.provider.Provider;\n\npublic class DefaultApplicationProvider implements ApplicationProvider {\n  private static final Logger logger = LoggerFactory.getLogger(DefaultApplicationProvider.class);\n  public static final String APP_PROPERTIES_CLASSPATH = \"/META-INF/app.properties\";\n  private Properties m_appProperties = new Properties();\n\n  private String m_appId;\n\n  @Override\n  public void initialize() {\n    try {\n      InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(APP_PROPERTIES_CLASSPATH);\n      if (in == null) {\n        in = DefaultApplicationProvider.class.getResourceAsStream(APP_PROPERTIES_CLASSPATH);\n      }\n\n      if (in == null) {\n        logger.warn(\"{} not found from classpath!\", APP_PROPERTIES_CLASSPATH);\n      }\n      initialize(in);\n    } catch (Throwable ex) {\n      logger.error(\"Initialize DefaultApplicationProvider failed.\", ex);\n    }\n  }\n\n  @Override\n  public void initialize(InputStream in) {\n    try {\n      if (in != null) {\n        try {\n          m_appProperties.load(new InputStreamReader(new BOMInputStream(in), StandardCharsets.UTF_8));\n        } finally {\n          in.close();\n        }\n      }\n\n      initAppId();\n    } catch (Throwable ex) {\n      logger.error(\"Initialize DefaultApplicationProvider failed.\", ex);\n    }\n  }\n\n  @Override\n  public String getAppId() {\n    return m_appId;\n  }\n\n  @Override\n  public boolean isAppIdSet() {\n    return !Utils.isBlank(m_appId);\n  }\n\n  @Override\n  public String getProperty(String name, String defaultValue) {\n    if (\"app.id\".equals(name)) {\n      String val = getAppId();\n      return val == null ? defaultValue : val;\n    } else {\n      String val = m_appProperties.getProperty(name, defaultValue);\n      return val == null ? defaultValue : val;\n    }\n  }\n\n  @Override\n  public Class<? extends Provider> getType() {\n    return ApplicationProvider.class;\n  }\n\n  private void initAppId() {\n    // 1. Get app.id from System Property\n    m_appId = System.getProperty(\"app.id\");\n    if (!Utils.isBlank(m_appId)) {\n      m_appId = m_appId.trim();\n      logger.info(\"App ID is set to {} by app.id property from System Property\", m_appId);\n      return;\n    }\n\n    // 2. Try to get app id from app.properties.\n    m_appId = m_appProperties.getProperty(\"app.id\");\n    if (!Utils.isBlank(m_appId)) {\n      m_appId = m_appId.trim();\n      logger.info(\"App ID is set to {} by app.id property from {}\", m_appId, APP_PROPERTIES_CLASSPATH);\n      return;\n    }\n\n    m_appId = null;\n    logger.warn(\"app.id is not available from System Property and {}. It is set to null\", APP_PROPERTIES_CLASSPATH);\n  }\n\n  @Override\n  public String toString() {\n    return \"appId [\" + getAppId() + \"] properties: \" + m_appProperties + \" (DefaultApplicationProvider)\";\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/foundation/internals/provider/DefaultNetworkProvider.java",
    "content": "package com.ctrip.framework.foundation.internals.provider;\n\nimport com.ctrip.framework.foundation.internals.NetworkInterfaceManager;\nimport com.ctrip.framework.foundation.spi.provider.NetworkProvider;\nimport com.ctrip.framework.foundation.spi.provider.Provider;\n\npublic class DefaultNetworkProvider implements NetworkProvider {\n  @Override\n  public String getProperty(String name, String defaultValue) {\n    if (\"host.address\".equalsIgnoreCase(name)) {\n      String val = getHostAddress();\n      return val == null ? defaultValue : val;\n    } else if (\"host.name\".equalsIgnoreCase(name)) {\n      String val = getHostName();\n      return val == null ? defaultValue : val;\n    } else {\n      return defaultValue;\n    }\n  }\n\n  @Override\n  public void initialize() {\n\n  }\n\n  @Override\n  public String getHostAddress() {\n    return NetworkInterfaceManager.INSTANCE.getLocalHostAddress();\n  }\n\n  @Override\n  public String getHostName() {\n    return NetworkInterfaceManager.INSTANCE.getLocalHostName();\n  }\n\n  @Override\n  public Class<? extends Provider> getType() {\n    return NetworkProvider.class;\n  }\n\n  @Override\n  public String toString() {\n    return \"hostName [\" + getHostName() + \"] hostIP [\" + getHostAddress() + \"] (DefaultNetworkProvider)\";\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/foundation/internals/provider/DefaultServerProvider.java",
    "content": "package com.ctrip.framework.foundation.internals.provider;\n\nimport java.io.File;\nimport java.io.FileInputStream;\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\nimport java.nio.charset.StandardCharsets;\nimport java.util.Properties;\n\nimport com.ctrip.framework.foundation.internals.Utils;\nimport com.ctrip.framework.foundation.internals.io.BOMInputStream;\nimport com.ctrip.framework.foundation.spi.provider.Provider;\nimport com.ctrip.framework.foundation.spi.provider.ServerProvider;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\npublic class DefaultServerProvider implements ServerProvider {\n  private static final Logger logger = LoggerFactory.getLogger(DefaultServerProvider.class);\n  private static final String SERVER_PROPERTIES_LINUX = \"/opt/settings/server.properties\";\n  private static final String SERVER_PROPERTIES_WINDOWS = \"C:/opt/settings/server.properties\";\n\n  private String m_env;\n  private String m_dc;\n\n  private Properties m_serverProperties = new Properties();\n\n  @Override\n  public void initialize() {\n    try {\n      String path = Utils.isOSWindows() ? SERVER_PROPERTIES_WINDOWS : SERVER_PROPERTIES_LINUX;\n\n      File file = new File(path);\n      if (file.exists() && file.canRead()) {\n        logger.info(\"Loading {}\", file.getAbsolutePath());\n        FileInputStream fis = new FileInputStream(file);\n        initialize(fis);\n        return;\n      }\n\n      logger.warn(\"{} does not exist or is not readable.\", path);\n      initialize(null);\n    } catch (Throwable ex) {\n      logger.error(\"Initialize DefaultServerProvider failed.\", ex);\n    }\n  }\n\n  @Override\n  public void initialize(InputStream in) {\n    try {\n      if (in != null) {\n        try {\n          m_serverProperties.load(new InputStreamReader(new BOMInputStream(in), StandardCharsets.UTF_8));\n        } finally {\n          in.close();\n        }\n      }\n\n      initEnvType();\n      initDataCenter();\n    } catch (Throwable ex) {\n      logger.error(\"Initialize DefaultServerProvider failed.\", ex);\n    }\n  }\n\n  @Override\n  public String getDataCenter() {\n    return m_dc;\n  }\n\n  @Override\n  public boolean isDataCenterSet() {\n    return m_dc != null;\n  }\n\n  @Override\n  public String getEnvType() {\n    return m_env;\n  }\n\n  @Override\n  public boolean isEnvTypeSet() {\n    return m_env != null;\n  }\n\n  @Override\n  public String getProperty(String name, String defaultValue) {\n    if (\"env\".equalsIgnoreCase(name)) {\n      String val = getEnvType();\n      return val == null ? defaultValue : val;\n    } else if (\"dc\".equalsIgnoreCase(name)) {\n      String val = getDataCenter();\n      return val == null ? defaultValue : val;\n    } else {\n      String val = m_serverProperties.getProperty(name, defaultValue);\n      return val == null ? defaultValue : val.trim();\n    }\n  }\n\n  @Override\n  public Class<? extends Provider> getType() {\n    return ServerProvider.class;\n  }\n\n  private void initEnvType() {\n    // 1. Try to get environment from JVM system property\n    m_env = System.getProperty(\"env\");\n    if (!Utils.isBlank(m_env)) {\n      m_env = m_env.trim();\n      logger.info(\"Environment is set to [{}] by JVM system property 'env'.\", m_env);\n      return;\n    }\n\n    // 2. Try to get environment from OS environment variable\n    m_env = System.getenv(\"ENV\");\n    if (!Utils.isBlank(m_env)) {\n      m_env = m_env.trim();\n      logger.info(\"Environment is set to [{}] by OS env variable 'ENV'.\", m_env);\n      return;\n    }\n\n    // 3. Try to get environment from file \"server.properties\"\n    m_env = m_serverProperties.getProperty(\"env\");\n    if (!Utils.isBlank(m_env)) {\n      m_env = m_env.trim();\n      logger.info(\"Environment is set to [{}] by property 'env' in server.properties.\", m_env);\n      return;\n    }\n\n    // 4. Set environment to null.\n    m_env = null;\n    logger.warn(\"Environment is set to null. Because it is not available in either (1) JVM system property 'env', (2) OS env variable 'ENV' nor (3) property 'env' from the properties InputStream.\");\n  }\n\n  private void initDataCenter() {\n    // 1. Try to get environment from JVM system property\n    m_dc = System.getProperty(\"idc\");\n    if (!Utils.isBlank(m_dc)) {\n      m_dc = m_dc.trim();\n      logger.info(\"Data Center is set to [{}] by JVM system property 'idc'.\", m_dc);\n      return;\n    }\n\n    // 2. Try to get idc from OS environment variable\n    m_dc = System.getenv(\"IDC\");\n    if (!Utils.isBlank(m_dc)) {\n      m_dc = m_dc.trim();\n      logger.info(\"Data Center is set to [{}] by OS env variable 'IDC'.\", m_dc);\n      return;\n    }\n\n    // 3. Try to get idc from from file \"server.properties\"\n    m_dc = m_serverProperties.getProperty(\"idc\");\n    if (!Utils.isBlank(m_dc)) {\n      m_dc = m_dc.trim();\n      logger.info(\"Data Center is set to [{}] by property 'idc' in server.properties.\", m_dc);\n      return;\n    }\n\n    // 4. Set Data Center to null.\n    m_dc = null;\n    logger.debug(\"Data Center is set to null. Because it is not available in either (1) JVM system property 'idc', (2) OS env variable 'IDC' nor (3) property 'idc' from the properties InputStream.\");\n  }\n\n  @Override\n  public String toString() {\n    return \"environment [\" + getEnvType() + \"] data center [\" + getDataCenter() + \"] properties: \" + m_serverProperties\n        + \" (DefaultServerProvider)\";\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/foundation/internals/provider/NullProvider.java",
    "content": "package com.ctrip.framework.foundation.internals.provider;\n\nimport java.io.InputStream;\n\nimport com.ctrip.framework.foundation.spi.provider.ApplicationProvider;\nimport com.ctrip.framework.foundation.spi.provider.NetworkProvider;\nimport com.ctrip.framework.foundation.spi.provider.Provider;\nimport com.ctrip.framework.foundation.spi.provider.ServerProvider;\n\npublic class NullProvider implements ApplicationProvider, NetworkProvider, ServerProvider {\n  @Override\n  public Class<? extends Provider> getType() {\n    return null;\n  }\n\n  @Override\n  public String getProperty(String name, String defaultValue) {\n    return defaultValue;\n  }\n\n  @Override\n  public void initialize() {\n\n  }\n\n  @Override\n  public String getAppId() {\n    return null;\n  }\n\n  @Override\n  public boolean isAppIdSet() {\n    return false;\n  }\n\n  @Override\n  public String getEnvType() {\n    return null;\n  }\n\n  @Override\n  public boolean isEnvTypeSet() {\n    return false;\n  }\n\n  @Override\n  public String getDataCenter() {\n    return null;\n  }\n\n  @Override\n  public boolean isDataCenterSet() {\n    return false;\n  }\n\n  @Override\n  public void initialize(InputStream in) {\n\n  }\n\n  @Override\n  public String getHostAddress() {\n    return null;\n  }\n\n  @Override\n  public String getHostName() {\n    return null;\n  }\n\n  @Override\n  public String toString() {\n    return \"(NullProvider)\";\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/foundation/spi/ProviderManager.java",
    "content": "package com.ctrip.framework.foundation.spi;\n\nimport com.ctrip.framework.foundation.spi.provider.Provider;\n\npublic interface ProviderManager {\n  public String getProperty(String name, String defaultValue);\n\n  public <T extends Provider> T provider(Class<T> clazz);\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/foundation/spi/provider/ApplicationProvider.java",
    "content": "package com.ctrip.framework.foundation.spi.provider;\n\nimport java.io.InputStream;\n\n/**\n * Provider for application related properties\n */\npublic interface ApplicationProvider extends Provider {\n  /**\n   * @return the application's app id\n   */\n  public String getAppId();\n\n  /**\n   * @return whether the application's app id is set or not\n   */\n  public boolean isAppIdSet();\n\n  /**\n   * Initialize the application provider with the specified input stream\n   */\n  public void initialize(InputStream in);\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/foundation/spi/provider/NetworkProvider.java",
    "content": "package com.ctrip.framework.foundation.spi.provider;\n\n/**\n * Provider for network related properties\n */\npublic interface NetworkProvider extends Provider {\n  /**\n   * @return the host address, i.e. ip\n   */\n  public String getHostAddress();\n\n  /**\n   * @return the host name\n   */\n  public String getHostName();\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/foundation/spi/provider/Provider.java",
    "content": "package com.ctrip.framework.foundation.spi.provider;\n\npublic interface Provider {\n  /**\n   * @return the current provider's type\n   */\n  public Class<? extends Provider> getType();\n\n  /**\n   * Return the property value with the given name, or {@code defaultValue} if the name doesn't exist.\n   *\n   * @param name the property name\n   * @param defaultValue the default value when name is not found or any error occurred\n   * @return the property value\n   */\n  public String getProperty(String name, String defaultValue);\n\n  /**\n   * Initialize the provider\n   */\n  public void initialize();\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/foundation/spi/provider/ServerProvider.java",
    "content": "package com.ctrip.framework.foundation.spi.provider;\n\nimport java.io.IOException;\nimport java.io.InputStream;\n\n/**\n * Provider for server related properties\n */\npublic interface ServerProvider extends Provider {\n  /**\n   * @return current environment or {@code null} if not set\n   */\n  public String getEnvType();\n\n  /**\n   * @return whether current environment is set or not\n   */\n  public boolean isEnvTypeSet();\n\n  /**\n   * @return current data center or {@code null} if not set\n   */\n  public String getDataCenter();\n\n  /**\n   * @return whether data center is set or not\n   */\n  public boolean isDataCenterSet();\n\n  /**\n   * Initialize server provider with the specified input stream\n   *\n   * @throws IOException\n   */\n  public void initialize(InputStream in) throws IOException;\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/resources/META-INF/services/com.ctrip.framework.apollo.tracer.spi.MessageProducerManager",
    "content": "com.ctrip.framework.apollo.tracer.internals.DefaultMessageProducerManager"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/resources/META-INF/services/com.ctrip.framework.foundation.spi.ProviderManager",
    "content": "com.ctrip.framework.foundation.internals.DefaultProviderManager"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/main/resources/apollo-env.properties",
    "content": "local.meta=http://localhost:8080\n#\\u6307\\u5411http://localhost:8080/services/config\\u5730\\u5740\ndev.meta=http://127.0.0.1:8080\nfat.meta=${fat_meta}\nuat.meta=${uat_meta}\nlpt.meta=${lpt_meta}\npro.meta=${pro_meta}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/test/resources/META-INF/app-with-utf8bom.properties",
    "content": "﻿app.id=110402\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/test/resources/META-INF/app.properties",
    "content": "app.id=110402\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/test/resources/META-INF/services/com.ctrip.framework.apollo.foundation.internals.ServiceBootstrapTest$Interface1",
    "content": "com.ctrip.framework.apollo.foundation.internals.ServiceBootstrapTest$Interface1Impl"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/test/resources/META-INF/services/com.ctrip.framework.apollo.foundation.internals.ServiceBootstrapTest$Interface3",
    "content": ""
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/test/resources/META-INF/services/com.ctrip.framework.apollo.foundation.internals.ServiceBootstrapTest$Interface4",
    "content": "com.ctrip.framework.apollo.foundation.internals.ServiceBootstrapTest$Interface1Impl"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/test/resources/META-INF/services/com.ctrip.framework.apollo.foundation.internals.ServiceBootstrapTest$Interface5",
    "content": "com.ctrip.framework.apollo.foundation.internals.ServiceBootstrapTest$SomeImplNotExists"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/test/resources/META-INF/services/com.ctrip.framework.apollo.tracer.spi.MessageProducerManager",
    "content": "com.ctrip.framework.apollo.tracer.internals.MockMessageProducerManager"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/test/resources/META-INF/some-invalid-app.properties",
    "content": "appid=110402\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/test/resources/apollo-env.properties",
    "content": "local.meta=http://localhost:8080\ndev.meta=http://dev:8080"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/test/resources/log4j2.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<configuration monitorInterval=\"60\">\n    <appenders>\n        <Console name=\"Console\" target=\"SYSTEM_OUT\">\n            <PatternLayout pattern=\"[apollo-client][%t]%d %-5p [%c] %m%n\"/>\n        </Console>\n        <Async name=\"Async\" includeLocation=\"true\">\n            <AppenderRef ref=\"Console\"/>\n        </Async>\n    </appenders>\n    <loggers>\n        <logger name=\"com.ctrip.framework.apollo\" additivity=\"false\" level=\"trace\">\n            <AppenderRef ref=\"Async\" level=\"DEBUG\"/>\n        </logger>\n        <root level=\"INFO\">\n            <AppenderRef ref=\"Async\"/>\n        </root>\n    </loggers>\n</configuration>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/test/resources/properties/server-with-utf8bom.properties",
    "content": "﻿idc=SHAJQ\nenv=DEV\nsubenv=Dev123\nbigdata=true\ntooling=true\npci=true\n"
  },
  {
    "path": "open-config-center/apollo/apollo-core/src/test/resources/properties/server.properties",
    "content": "idc=SHAJQ\nenv=DEV\nsubenv=Dev123\nbigdata=true\ntooling=true\npci=true\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/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\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">\n\t<parent>\n\t\t<groupId>com.ctrip.framework.apollo</groupId>\n\t\t<artifactId>apollo</artifactId>\n\t\t<version>0.10.0-SNAPSHOT</version>\n\t</parent>\n\t<modelVersion>4.0.0</modelVersion>\n\t<artifactId>apollo-portal</artifactId>\n\t<name>Apollo Portal</name>\n\t<properties>\n\t\t<github.path>${project.artifactId}</github.path>\n\t</properties>\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>com.ctrip.framework.apollo</groupId>\n\t\t\t<artifactId>apollo-common</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>com.h2database</groupId>\n\t\t\t<artifactId>h2</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>mysql</groupId>\n\t\t\t<artifactId>mysql-connector-java</artifactId>\n\t\t</dependency>\n\t</dependencies>\n\t <build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>repackage</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t</plugins>\n\t\t<finalName>apollo-portal</finalName>\n\t</build>\n\t<profiles>\n\t\t<profile>\n\t\t\t<id>ctrip</id>\n\t\t\t<dependencies>\n\t\t\t\t<dependency>\n\t\t\t\t\t<groupId>com.ctrip.framework.apollo-sso</groupId>\n\t\t\t\t\t<artifactId>apollo-sso-ctrip</artifactId>\n\t\t\t\t</dependency>\n\t\t\t\t<dependency>\n\t\t\t\t\t<groupId>com.ctrip.framework.apollo-ctrip-service</groupId>\n\t\t\t\t\t<artifactId>apollo-email-service</artifactId>\n\t\t\t\t</dependency>\n\t\t\t</dependencies>\n\t\t</profile>\n\t</profiles>\n</project>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/assembly/assembly-descriptor.xml",
    "content": "<assembly\n\txmlns=\"http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3\"\n\txmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd\">\n\t<id>apollo-assembly</id>\n\t<formats>\n\t\t<format>zip</format>\n\t</formats>\n\t<includeBaseDirectory>false</includeBaseDirectory>\n\t<fileSets>\n\t\t<!--scripts -->\n\t\t<fileSet>\n\t\t\t<directory>src/main/scripts</directory>\n\t\t\t<outputDirectory>scripts</outputDirectory>\n\t\t\t<includes>\n\t\t\t\t<include>*.sh</include>\n\t\t\t</includes>\n\t\t\t<fileMode>0755</fileMode>\n\t\t\t<lineEnding>unix</lineEnding>\n\t\t</fileSet>\n\t\t<fileSet>\n\t\t\t<directory>src/main/config</directory>\n\t\t\t<outputDirectory>config</outputDirectory>\n\t\t\t<excludes>\n\t\t\t\t<exclude>apollo-portal.conf</exclude>\n\t\t\t</excludes>\n\t\t\t<lineEnding>unix</lineEnding>\n\t\t</fileSet>\n\t\t<fileSet>\n\t\t\t<directory>src/main/config</directory>\n\t\t\t<outputDirectory>/</outputDirectory>\n\t\t\t<includes>\n\t\t\t\t<include>apollo-portal.conf</include>\n\t\t\t</includes>\n\t\t\t<lineEnding>unix</lineEnding>\n\t\t</fileSet>\n\t\t<!--artifact -->\n\t\t<fileSet>\n\t\t\t<directory>target</directory>\n\t\t\t<outputDirectory>/</outputDirectory>\n\t\t\t<includes>\n\t\t\t\t<include>${project.artifactId}-*.jar</include>\n\t\t\t</includes>\n\t\t\t<fileMode>0755</fileMode>\n\t\t</fileSet>\n\t</fileSets>\n</assembly>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/config/apollo-portal.conf",
    "content": "MODE=service\nPID_FOLDER=.\nLOG_FOLDER=/opt/logs/100003173/"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/config/app.properties",
    "content": "appId=100003173\njdkVersion=1.8"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/docker/Dockerfile",
    "content": "# Dockerfile for apollo-portal\n# Build with:\n# docker build -t apollo-portal .\n# Run with:\n# docker run -p 8080:8080 -d -v /tmp/logs:/opt/logs --name apollo-portal apollo-portal\n# Or if 8080 was taken:\n# docker run -p 8070:8080 -d -v /tmp/logs:/opt/logs --name apollo-portal apollo-portal\n\nFROM openjdk:8-jre-alpine\nMAINTAINER ameizi <sxyx2008@163.com>\n\nENV VERSION 0.9.0\n\nRUN echo \"http://mirrors.aliyun.com/alpine/v3.6/main\" > /etc/apk/repositories \\\n    && echo \"http://mirrors.aliyun.com/alpine/v3.6/community\" >> /etc/apk/repositories \\\n    && apk update upgrade \\\n    && apk add --no-cache procps unzip curl bash tzdata \\\n    && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \\\n    && echo \"Asia/Shanghai\" > /etc/timezone\n\nADD apollo-portal-${VERSION}-github.zip /apollo-portal/apollo-portal-${VERSION}-github.zip\n\nRUN unzip /apollo-portal/apollo-portal-${VERSION}-github.zip -d /apollo-portal \\\n    && rm -rf /apollo-portal/apollo-portal-${VERSION}-github.zip \\\n    && sed -i '$d' /apollo-portal/scripts/startup.sh \\\n    && echo \"tail -f /dev/null\" >> /apollo-portal/scripts/startup.sh\n\nEXPOSE 8080\n\nCMD [\"/apollo-portal/scripts/startup.sh\"]\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/PortalOpenApiConfig.java",
    "content": "package com.ctrip.framework.apollo.openapi;\n\nimport org.springframework.boot.autoconfigure.EnableAutoConfiguration;\nimport org.springframework.context.annotation.ComponentScan;\nimport org.springframework.context.annotation.Configuration;\n\n@EnableAutoConfiguration\n@Configuration\n@ComponentScan(basePackageClasses = PortalOpenApiConfig.class)\npublic class PortalOpenApiConfig {\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/auth/ConsumerPermissionValidator.java",
    "content": "package com.ctrip.framework.apollo.openapi.auth;\n\nimport com.ctrip.framework.apollo.openapi.service.ConsumerRolePermissionService;\nimport com.ctrip.framework.apollo.openapi.util.ConsumerAuthUtil;\nimport com.ctrip.framework.apollo.portal.constant.PermissionType;\nimport com.ctrip.framework.apollo.portal.util.RoleUtils;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport javax.servlet.http.HttpServletRequest;\n\n@Component\npublic class ConsumerPermissionValidator {\n\n  @Autowired\n  private ConsumerRolePermissionService permissionService;\n  @Autowired\n  private ConsumerAuthUtil consumerAuthUtil;\n\n\n  public boolean hasModifyNamespacePermission(HttpServletRequest request, String appId, String\n      namespaceName) {\n\n    if (hasCreateNamespacePermission(request, appId)) {\n      return true;\n    }\n    return permissionService.consumerHasPermission(consumerAuthUtil.retrieveConsumerId(request),\n        PermissionType.MODIFY_NAMESPACE,\n        RoleUtils.buildNamespaceTargetId(appId, namespaceName));\n\n  }\n\n  public boolean hasReleaseNamespacePermission(HttpServletRequest request, String appId, String\n      namespaceName) {\n    if (hasCreateNamespacePermission(request, appId)) {\n      return true;\n    }\n    return permissionService.consumerHasPermission(consumerAuthUtil.retrieveConsumerId(request),\n        PermissionType.RELEASE_NAMESPACE,\n        RoleUtils.buildNamespaceTargetId(appId, namespaceName));\n\n  }\n\n  public boolean hasCreateNamespacePermission(HttpServletRequest request, String appId) {\n    return permissionService.consumerHasPermission(consumerAuthUtil.retrieveConsumerId(request),\n                                                   PermissionType.CREATE_NAMESPACE,\n                                                   appId);\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/dto/OpenAppNamespaceDTO.java",
    "content": "package com.ctrip.framework.apollo.openapi.dto;\n\n\nimport com.ctrip.framework.apollo.common.dto.BaseDTO;\n\npublic class OpenAppNamespaceDTO extends BaseDTO {\n\n    private String name;\n\n    private String appId;\n\n    private String format;\n\n    private boolean isPublic;\n\n    private String comment;\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public String getAppId() {\n        return appId;\n    }\n\n    public void setAppId(String appId) {\n        this.appId = appId;\n    }\n\n    public String getFormat() {\n        return format;\n    }\n\n    public void setFormat(String format) {\n        this.format = format;\n    }\n\n    public boolean isPublic() {\n        return isPublic;\n    }\n\n    public void setPublic(boolean aPublic) {\n        isPublic = aPublic;\n    }\n\n    public String getComment() {\n        return comment;\n    }\n\n    public void setComment(String comment) {\n        this.comment = comment;\n    }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/dto/OpenEnvClusterDTO.java",
    "content": "package com.ctrip.framework.apollo.openapi.dto;\n\nimport java.util.Set;\n\npublic class OpenEnvClusterDTO {\n\n  private String env;\n  private Set<String> clusters;\n\n  public String getEnv() {\n    return env;\n  }\n\n  public void setEnv(String env) {\n    this.env = env;\n  }\n\n  public Set<String> getClusters() {\n    return clusters;\n  }\n\n  public void setClusters(Set<String> clusters) {\n    this.clusters = clusters;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/dto/OpenItemDTO.java",
    "content": "package com.ctrip.framework.apollo.openapi.dto;\n\nimport com.ctrip.framework.apollo.common.dto.BaseDTO;\n\npublic class OpenItemDTO extends BaseDTO {\n\n  private String key;\n\n  private String value;\n\n  private String comment;\n\n  public String getKey() {\n    return key;\n  }\n\n  public void setKey(String key) {\n    this.key = key;\n  }\n\n  public String getValue() {\n    return value;\n  }\n\n  public void setValue(String value) {\n    this.value = value;\n  }\n\n  public String getComment() {\n    return comment;\n  }\n\n  public void setComment(String comment) {\n    this.comment = comment;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/dto/OpenNamespaceDTO.java",
    "content": "package com.ctrip.framework.apollo.openapi.dto;\n\nimport com.ctrip.framework.apollo.common.dto.BaseDTO;\n\nimport java.util.List;\n\npublic class OpenNamespaceDTO extends BaseDTO {\n\n  private String appId;\n\n  private String clusterName;\n\n  private String namespaceName;\n\n  private String comment;\n\n  private String format;\n\n  private boolean isPublic;\n\n  private List<OpenItemDTO> items;\n\n  public String getAppId() {\n    return appId;\n  }\n\n  public void setAppId(String appId) {\n    this.appId = appId;\n  }\n\n  public String getClusterName() {\n    return clusterName;\n  }\n\n  public void setClusterName(String clusterName) {\n    this.clusterName = clusterName;\n  }\n\n  public String getNamespaceName() {\n    return namespaceName;\n  }\n\n  public void setNamespaceName(String namespaceName) {\n    this.namespaceName = namespaceName;\n  }\n\n  public String getComment() {\n    return comment;\n  }\n\n  public void setComment(String comment) {\n    this.comment = comment;\n  }\n\n  public String getFormat() {\n    return format;\n  }\n\n  public void setFormat(String format) {\n    this.format = format;\n  }\n\n  public boolean isPublic() {\n    return isPublic;\n  }\n\n  public void setPublic(boolean aPublic) {\n    isPublic = aPublic;\n  }\n\n  public List<OpenItemDTO> getItems() {\n    return items;\n  }\n\n  public void setItems(List<OpenItemDTO> items) {\n    this.items = items;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/dto/OpenNamespaceLockDTO.java",
    "content": "package com.ctrip.framework.apollo.openapi.dto;\n\npublic class OpenNamespaceLockDTO {\n\n  private String namespaceName;\n  private boolean isLocked;\n  private String lockedBy;\n\n  public String getNamespaceName() {\n    return namespaceName;\n  }\n\n  public void setNamespaceName(String namespaceName) {\n    this.namespaceName = namespaceName;\n  }\n\n  public boolean isLocked() {\n    return isLocked;\n  }\n\n  public void setLocked(boolean locked) {\n    isLocked = locked;\n  }\n\n  public String getLockedBy() {\n    return lockedBy;\n  }\n\n  public void setLockedBy(String lockedBy) {\n    this.lockedBy = lockedBy;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/dto/OpenReleaseDTO.java",
    "content": "package com.ctrip.framework.apollo.openapi.dto;\n\nimport com.ctrip.framework.apollo.common.dto.BaseDTO;\n\nimport java.util.Map;\n\npublic class OpenReleaseDTO extends BaseDTO {\n\n  private String appId;\n\n  private String clusterName;\n\n  private String namespaceName;\n\n  private String name;\n\n  private Map<String, String> configurations;\n\n  private String comment;\n\n  public String getName() {\n    return name;\n  }\n\n  public void setName(String name) {\n    this.name = name;\n  }\n\n  public String getAppId() {\n    return appId;\n  }\n\n  public void setAppId(String appId) {\n    this.appId = appId;\n  }\n\n  public String getClusterName() {\n    return clusterName;\n  }\n\n  public void setClusterName(String clusterName) {\n    this.clusterName = clusterName;\n  }\n\n  public String getNamespaceName() {\n    return namespaceName;\n  }\n\n  public void setNamespaceName(String namespaceName) {\n    this.namespaceName = namespaceName;\n  }\n\n  public Map<String, String> getConfigurations() {\n    return configurations;\n  }\n\n  public void setConfigurations(Map<String, String> configurations) {\n    this.configurations = configurations;\n  }\n\n  public String getComment() {\n    return comment;\n  }\n\n  public void setComment(String comment) {\n    this.comment = comment;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/entity/Consumer.java",
    "content": "package com.ctrip.framework.apollo.openapi.entity;\n\nimport com.ctrip.framework.apollo.common.entity.BaseEntity;\n\nimport org.hibernate.annotations.SQLDelete;\nimport org.hibernate.annotations.Where;\n\nimport javax.persistence.Column;\nimport javax.persistence.Entity;\nimport javax.persistence.Table;\n\n@Entity\n@Table(name = \"Consumer\")\n@SQLDelete(sql = \"Update Consumer set isDeleted = 1 where id = ?\")\n@Where(clause = \"isDeleted = 0\")\npublic class Consumer extends BaseEntity {\n\n  @Column(name = \"Name\", nullable = false)\n  private String name;\n\n  @Column(name = \"AppId\", nullable = false)\n  private String appId;\n\n  @Column(name = \"OrgId\", nullable = false)\n  private String orgId;\n\n  @Column(name = \"OrgName\", nullable = false)\n  private String orgName;\n\n  @Column(name = \"OwnerName\", nullable = false)\n  private String ownerName;\n\n  @Column(name = \"OwnerEmail\", nullable = false)\n  private String ownerEmail;\n\n  public String getAppId() {\n    return appId;\n  }\n\n  public String getName() {\n    return name;\n  }\n\n  public String getOrgId() {\n    return orgId;\n  }\n\n  public String getOrgName() {\n    return orgName;\n  }\n\n  public String getOwnerEmail() {\n    return ownerEmail;\n  }\n\n  public String getOwnerName() {\n    return ownerName;\n  }\n\n  public void setAppId(String appId) {\n    this.appId = appId;\n  }\n\n  public void setName(String name) {\n    this.name = name;\n  }\n\n  public void setOrgId(String orgId) {\n    this.orgId = orgId;\n  }\n\n  public void setOrgName(String orgName) {\n    this.orgName = orgName;\n  }\n\n  public void setOwnerEmail(String ownerEmail) {\n    this.ownerEmail = ownerEmail;\n  }\n\n  public void setOwnerName(String ownerName) {\n    this.ownerName = ownerName;\n  }\n\n  @Override\n  public String toString() {\n    return toStringHelper().add(\"name\", name).add(\"appId\", appId)\n        .add(\"orgId\", orgId)\n        .add(\"orgName\", orgName)\n        .add(\"ownerName\", ownerName)\n        .add(\"ownerEmail\", ownerEmail).toString();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/entity/ConsumerAudit.java",
    "content": "package com.ctrip.framework.apollo.openapi.entity;\n\nimport com.google.common.base.MoreObjects;\n\nimport java.util.Date;\n\nimport javax.persistence.Column;\nimport javax.persistence.Entity;\nimport javax.persistence.GeneratedValue;\nimport javax.persistence.Id;\nimport javax.persistence.PrePersist;\nimport javax.persistence.Table;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@Entity\n@Table(name = \"ConsumerAudit\")\npublic class ConsumerAudit {\n  @Id\n  @GeneratedValue\n  @Column(name = \"Id\")\n  private long id;\n\n  @Column(name = \"ConsumerId\", nullable = false)\n  private long consumerId;\n\n  @Column(name = \"Uri\", nullable = false)\n  private String uri;\n\n  @Column(name = \"Method\", nullable = false)\n  private String method;\n\n  @Column(name = \"DataChange_CreatedTime\")\n  private Date dataChangeCreatedTime;\n\n  @Column(name = \"DataChange_LastTime\")\n  private Date dataChangeLastModifiedTime;\n\n  @PrePersist\n  protected void prePersist() {\n    if (this.dataChangeCreatedTime == null) {\n      this.dataChangeCreatedTime = new Date();\n    }\n    if (this.dataChangeLastModifiedTime == null) {\n      dataChangeLastModifiedTime = this.dataChangeCreatedTime;\n    }\n  }\n\n  public long getId() {\n    return id;\n  }\n\n  public void setId(long id) {\n    this.id = id;\n  }\n\n  public long getConsumerId() {\n    return consumerId;\n  }\n\n  public void setConsumerId(long consumerId) {\n    this.consumerId = consumerId;\n  }\n\n  public String getUri() {\n    return uri;\n  }\n\n  public void setUri(String uri) {\n    this.uri = uri;\n  }\n\n  public String getMethod() {\n    return method;\n  }\n\n  public void setMethod(String method) {\n    this.method = method;\n  }\n\n  public Date getDataChangeCreatedTime() {\n    return dataChangeCreatedTime;\n  }\n\n  public void setDataChangeCreatedTime(Date dataChangeCreatedTime) {\n    this.dataChangeCreatedTime = dataChangeCreatedTime;\n  }\n\n  public Date getDataChangeLastModifiedTime() {\n    return dataChangeLastModifiedTime;\n  }\n\n  public void setDataChangeLastModifiedTime(Date dataChangeLastModifiedTime) {\n    this.dataChangeLastModifiedTime = dataChangeLastModifiedTime;\n  }\n\n  @Override\n  public String toString() {\n    return MoreObjects.toStringHelper(this)\n        .omitNullValues()\n        .add(\"id\", id)\n        .add(\"consumerId\", consumerId)\n        .add(\"uri\", uri)\n        .add(\"method\", method)\n        .add(\"dataChangeCreatedTime\", dataChangeCreatedTime)\n        .add(\"dataChangeLastModifiedTime\", dataChangeLastModifiedTime)\n        .toString();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/entity/ConsumerRole.java",
    "content": "package com.ctrip.framework.apollo.openapi.entity;\n\nimport com.ctrip.framework.apollo.common.entity.BaseEntity;\n\nimport org.hibernate.annotations.SQLDelete;\nimport org.hibernate.annotations.Where;\n\nimport javax.persistence.Column;\nimport javax.persistence.Entity;\nimport javax.persistence.Table;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@Entity\n@Table(name = \"ConsumerRole\")\n@SQLDelete(sql = \"Update ConsumerRole set isDeleted = 1 where id = ?\")\n@Where(clause = \"isDeleted = 0\")\npublic class ConsumerRole extends BaseEntity {\n  @Column(name = \"ConsumerId\", nullable = false)\n  private long consumerId;\n\n  @Column(name = \"RoleId\", nullable = false)\n  private long roleId;\n\n  public long getConsumerId() {\n    return consumerId;\n  }\n\n  public void setConsumerId(long consumerId) {\n    this.consumerId = consumerId;\n  }\n\n  public long getRoleId() {\n    return roleId;\n  }\n\n  public void setRoleId(long roleId) {\n    this.roleId = roleId;\n  }\n\n  @Override\n  public String toString() {\n    return toStringHelper().add(\"consumerId\", consumerId).add(\"roleId\", roleId).toString();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/entity/ConsumerToken.java",
    "content": "package com.ctrip.framework.apollo.openapi.entity;\n\nimport com.ctrip.framework.apollo.common.entity.BaseEntity;\n\nimport org.hibernate.annotations.SQLDelete;\nimport org.hibernate.annotations.Where;\n\nimport java.util.Date;\n\nimport javax.persistence.Column;\nimport javax.persistence.Entity;\nimport javax.persistence.Table;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@Entity\n@Table(name = \"ConsumerToken\")\n@SQLDelete(sql = \"Update ConsumerToken set isDeleted = 1 where id = ?\")\n@Where(clause = \"isDeleted = 0\")\npublic class ConsumerToken extends BaseEntity {\n  @Column(name = \"ConsumerId\", nullable = false)\n  private long consumerId;\n\n  @Column(name = \"token\", nullable = false)\n  private String token;\n\n  @Column(name = \"Expires\", nullable = false)\n  private Date expires;\n\n  public long getConsumerId() {\n    return consumerId;\n  }\n\n  public void setConsumerId(long consumerId) {\n    this.consumerId = consumerId;\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 Date getExpires() {\n    return expires;\n  }\n\n  public void setExpires(Date expires) {\n    this.expires = expires;\n  }\n\n  @Override\n  public String toString() {\n    return toStringHelper().add(\"consumerId\", consumerId).add(\"token\", token)\n        .add(\"expires\", expires).toString();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/filter/ConsumerAuthenticationFilter.java",
    "content": "package com.ctrip.framework.apollo.openapi.filter;\n\nimport com.ctrip.framework.apollo.openapi.util.ConsumerAuditUtil;\nimport com.ctrip.framework.apollo.openapi.util.ConsumerAuthUtil;\n\nimport java.io.IOException;\n\nimport javax.servlet.Filter;\nimport javax.servlet.FilterChain;\nimport javax.servlet.FilterConfig;\nimport javax.servlet.ServletException;\nimport javax.servlet.ServletRequest;\nimport javax.servlet.ServletResponse;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class ConsumerAuthenticationFilter implements Filter {\n  private ConsumerAuthUtil consumerAuthUtil;\n  private ConsumerAuditUtil consumerAuditUtil;\n\n  public ConsumerAuthenticationFilter(ConsumerAuthUtil consumerAuthUtil, ConsumerAuditUtil consumerAuditUtil) {\n    this.consumerAuthUtil = consumerAuthUtil;\n    this.consumerAuditUtil = consumerAuditUtil;\n  }\n\n  @Override\n  public void init(FilterConfig filterConfig) throws ServletException {\n    //nothing\n  }\n\n  @Override\n  public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws\n      IOException, ServletException {\n    HttpServletRequest request = (HttpServletRequest) req;\n    HttpServletResponse response = (HttpServletResponse) resp;\n\n    String token = request.getHeader(\"Authorization\");\n\n    Long consumerId = consumerAuthUtil.getConsumerId(token);\n\n    if (consumerId == null) {\n      response.sendError(HttpServletResponse.SC_UNAUTHORIZED, \"Unauthorized\");\n      return;\n    }\n\n    consumerAuthUtil.storeConsumerId(request, consumerId);\n    consumerAuditUtil.audit(request, consumerId);\n\n    chain.doFilter(req, resp);\n  }\n\n  @Override\n  public void destroy() {\n    //nothing\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/repository/ConsumerAuditRepository.java",
    "content": "package com.ctrip.framework.apollo.openapi.repository;\n\nimport com.ctrip.framework.apollo.openapi.entity.ConsumerAudit;\n\nimport org.springframework.data.repository.PagingAndSortingRepository;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic interface ConsumerAuditRepository extends PagingAndSortingRepository<ConsumerAudit, Long> {\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/repository/ConsumerRepository.java",
    "content": "package com.ctrip.framework.apollo.openapi.repository;\n\nimport com.ctrip.framework.apollo.openapi.entity.Consumer;\n\nimport org.springframework.data.repository.PagingAndSortingRepository;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic interface ConsumerRepository extends PagingAndSortingRepository<Consumer, Long> {\n\n  Consumer findByAppId(String appId);\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/repository/ConsumerRoleRepository.java",
    "content": "package com.ctrip.framework.apollo.openapi.repository;\n\nimport com.ctrip.framework.apollo.openapi.entity.ConsumerRole;\n\nimport org.springframework.data.repository.PagingAndSortingRepository;\n\nimport java.util.List;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic interface ConsumerRoleRepository extends PagingAndSortingRepository<ConsumerRole, Long> {\n  /**\n   * find consumer roles by userId\n   *\n   * @param consumerId consumer id\n   */\n  List<ConsumerRole> findByConsumerId(long consumerId);\n\n  /**\n   * find consumer roles by roleId\n   */\n  List<ConsumerRole> findByRoleId(long roleId);\n\n  ConsumerRole findByConsumerIdAndRoleId(long consumerId, long roleId);\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/repository/ConsumerTokenRepository.java",
    "content": "package com.ctrip.framework.apollo.openapi.repository;\n\nimport com.ctrip.framework.apollo.openapi.entity.ConsumerToken;\n\nimport org.springframework.data.repository.PagingAndSortingRepository;\n\nimport java.util.Date;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic interface ConsumerTokenRepository extends PagingAndSortingRepository<ConsumerToken, Long> {\n  /**\n   * find consumer token by token\n   *\n   * @param token     the token\n   * @param validDate the date when the token is valid\n   */\n  ConsumerToken findTopByTokenAndExpiresAfter(String token, Date validDate);\n\n  ConsumerToken findByConsumerId(Long consumerId);\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/service/ConsumerRolePermissionService.java",
    "content": "package com.ctrip.framework.apollo.openapi.service;\n\nimport com.google.common.collect.FluentIterable;\n\nimport com.ctrip.framework.apollo.openapi.entity.ConsumerRole;\nimport com.ctrip.framework.apollo.openapi.repository.ConsumerRoleRepository;\nimport com.ctrip.framework.apollo.portal.entity.po.Permission;\nimport com.ctrip.framework.apollo.portal.entity.po.RolePermission;\nimport com.ctrip.framework.apollo.portal.repository.PermissionRepository;\nimport com.ctrip.framework.apollo.portal.repository.RolePermissionRepository;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.util.CollectionUtils;\n\nimport java.util.List;\nimport java.util.Set;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@Service\npublic class ConsumerRolePermissionService {\n  @Autowired\n  private PermissionRepository permissionRepository;\n  @Autowired\n  private ConsumerRoleRepository consumerRoleRepository;\n  @Autowired\n  private RolePermissionRepository rolePermissionRepository;\n\n  /**\n   * Check whether user has the permission\n   */\n  public boolean consumerHasPermission(long consumerId, String permissionType, String targetId) {\n    Permission permission =\n        permissionRepository.findTopByPermissionTypeAndTargetId(permissionType, targetId);\n    if (permission == null) {\n      return false;\n    }\n\n    List<ConsumerRole> consumerRoles = consumerRoleRepository.findByConsumerId(consumerId);\n    if (CollectionUtils.isEmpty(consumerRoles)) {\n      return false;\n    }\n\n    Set<Long> roleIds =\n        FluentIterable.from(consumerRoles).transform(consumerRole -> consumerRole.getRoleId())\n            .toSet();\n    List<RolePermission> rolePermissions = rolePermissionRepository.findByRoleIdIn(roleIds);\n    if (CollectionUtils.isEmpty(rolePermissions)) {\n      return false;\n    }\n\n    for (RolePermission rolePermission : rolePermissions) {\n      if (rolePermission.getPermissionId() == permission.getId()) {\n        return true;\n      }\n    }\n\n    return false;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/service/ConsumerService.java",
    "content": "package com.ctrip.framework.apollo.openapi.service;\n\nimport com.google.common.base.Charsets;\nimport com.google.common.base.Joiner;\nimport com.google.common.base.Preconditions;\nimport com.google.common.base.Strings;\nimport com.google.common.hash.Hashing;\n\nimport com.ctrip.framework.apollo.common.exception.BadRequestException;\nimport com.ctrip.framework.apollo.openapi.entity.Consumer;\nimport com.ctrip.framework.apollo.openapi.entity.ConsumerAudit;\nimport com.ctrip.framework.apollo.openapi.entity.ConsumerRole;\nimport com.ctrip.framework.apollo.openapi.entity.ConsumerToken;\nimport com.ctrip.framework.apollo.openapi.repository.ConsumerAuditRepository;\nimport com.ctrip.framework.apollo.openapi.repository.ConsumerRepository;\nimport com.ctrip.framework.apollo.openapi.repository.ConsumerRoleRepository;\nimport com.ctrip.framework.apollo.openapi.repository.ConsumerTokenRepository;\nimport com.ctrip.framework.apollo.portal.component.config.PortalConfig;\nimport com.ctrip.framework.apollo.portal.entity.bo.UserInfo;\nimport com.ctrip.framework.apollo.portal.entity.po.Role;\nimport com.ctrip.framework.apollo.portal.service.RolePermissionService;\nimport com.ctrip.framework.apollo.portal.spi.UserInfoHolder;\nimport com.ctrip.framework.apollo.portal.spi.UserService;\nimport com.ctrip.framework.apollo.portal.util.RoleUtils;\n\nimport org.apache.commons.lang.time.FastDateFormat;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\nimport java.util.Arrays;\nimport java.util.Date;\nimport java.util.List;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@Service\npublic class ConsumerService {\n\n  private static final FastDateFormat TIMESTAMP_FORMAT = FastDateFormat.getInstance(\"yyyyMMddHHmmss\");\n  private static final Joiner KEY_JOINER = Joiner.on(\"|\");\n\n  @Autowired\n  private UserInfoHolder userInfoHolder;\n  @Autowired\n  private ConsumerTokenRepository consumerTokenRepository;\n  @Autowired\n  private ConsumerRepository consumerRepository;\n  @Autowired\n  private ConsumerAuditRepository consumerAuditRepository;\n  @Autowired\n  private ConsumerRoleRepository consumerRoleRepository;\n  @Autowired\n  private PortalConfig portalConfig;\n  @Autowired\n  private RolePermissionService rolePermissionService;\n  @Autowired\n  private UserService userService;\n\n\n  public Consumer createConsumer(Consumer consumer) {\n    String appId = consumer.getAppId();\n\n    Consumer managedConsumer = consumerRepository.findByAppId(appId);\n    if (managedConsumer != null) {\n      throw new BadRequestException(\"Consumer already exist\");\n    }\n\n    String ownerName = consumer.getOwnerName();\n    UserInfo owner = userService.findByUserId(ownerName);\n    if (owner == null) {\n      throw new BadRequestException(String.format(\"User does not exist. UserId = %s\", ownerName));\n    }\n    consumer.setOwnerEmail(owner.getEmail());\n\n    String operator = userInfoHolder.getUser().getUserId();\n    consumer.setDataChangeCreatedBy(operator);\n    consumer.setDataChangeLastModifiedBy(operator);\n\n    return consumerRepository.save(consumer);\n  }\n\n  public ConsumerToken generateAndSaveConsumerToken(Consumer consumer, Date expires) {\n    Preconditions.checkArgument(consumer != null, \"Consumer can not be null\");\n\n    ConsumerToken consumerToken = generateConsumerToken(consumer, expires);\n    consumerToken.setId(0);\n\n    return consumerTokenRepository.save(consumerToken);\n  }\n\n  public ConsumerToken getConsumerTokenByAppId(String appId) {\n    Consumer consumer = consumerRepository.findByAppId(appId);\n    if (consumer == null) {\n      return null;\n    }\n\n    return consumerTokenRepository.findByConsumerId(consumer.getId());\n  }\n\n  public Long getConsumerIdByToken(String token) {\n    if (Strings.isNullOrEmpty(token)) {\n      return null;\n    }\n    ConsumerToken consumerToken = consumerTokenRepository.findTopByTokenAndExpiresAfter(token,\n                                                                                        new Date());\n    return consumerToken == null ? null : consumerToken.getConsumerId();\n  }\n\n  public Consumer getConsumerByConsumerId(long consumerId) {\n    return consumerRepository.findOne(consumerId);\n  }\n\n  @Transactional\n  public List<ConsumerRole> assignNamespaceRoleToConsumer(String token, String appId, String namespaceName) {\n    Long consumerId = getConsumerIdByToken(token);\n    if (consumerId == null) {\n      throw new BadRequestException(\"Token is Illegal\");\n    }\n\n    Role namespaceModifyRole =\n        rolePermissionService.findRoleByRoleName(RoleUtils.buildModifyNamespaceRoleName(appId, namespaceName));\n    Role namespaceReleaseRole =\n        rolePermissionService.findRoleByRoleName(RoleUtils.buildReleaseNamespaceRoleName(appId, namespaceName));\n\n    if (namespaceModifyRole == null || namespaceReleaseRole == null) {\n      throw new BadRequestException(\"Namespace's role does not exist. Please check whether namespace has created.\");\n    }\n\n    long namespaceModifyRoleId = namespaceModifyRole.getId();\n    long namespaceReleaseRoleId = namespaceReleaseRole.getId();\n\n    ConsumerRole managedModifyRole = consumerRoleRepository.findByConsumerIdAndRoleId(consumerId, namespaceModifyRoleId);\n    ConsumerRole managedReleaseRole = consumerRoleRepository.findByConsumerIdAndRoleId(consumerId, namespaceReleaseRoleId);\n    if (managedModifyRole != null && managedReleaseRole != null) {\n      return Arrays.asList(managedModifyRole, managedReleaseRole);\n    }\n\n    String operator = userInfoHolder.getUser().getUserId();\n\n    ConsumerRole namespaceModifyConsumerRole = createConsumerRole(consumerId, namespaceModifyRoleId, operator);\n    ConsumerRole namespaceReleaseConsumerRole = createConsumerRole(consumerId, namespaceReleaseRoleId, operator);\n\n    ConsumerRole createdModifyConsumerRole = consumerRoleRepository.save(namespaceModifyConsumerRole);\n    ConsumerRole createdReleaseConsumerRole = consumerRoleRepository.save(namespaceReleaseConsumerRole);\n\n    return Arrays.asList(createdModifyConsumerRole, createdReleaseConsumerRole);\n  }\n\n  @Transactional\n  public ConsumerRole assignAppRoleToConsumer(String token, String appId) {\n    Long consumerId = getConsumerIdByToken(token);\n    if (consumerId == null) {\n      throw new BadRequestException(\"Token is Illegal\");\n    }\n\n    Role masterRole = rolePermissionService.findRoleByRoleName(RoleUtils.buildAppMasterRoleName(appId));\n    if (masterRole == null) {\n      throw new BadRequestException(\"App's role does not exist. Please check whether app has created.\");\n    }\n\n    long roleId = masterRole.getId();\n    ConsumerRole managedModifyRole = consumerRoleRepository.findByConsumerIdAndRoleId(consumerId, roleId);\n    if (managedModifyRole != null) {\n      return managedModifyRole;\n    }\n\n    String operator = userInfoHolder.getUser().getUserId();\n    ConsumerRole consumerRole = createConsumerRole(consumerId, roleId, operator);\n    return consumerRoleRepository.save(consumerRole);\n  }\n\n  @Transactional\n  public void createConsumerAudits(Iterable<ConsumerAudit> consumerAudits) {\n    consumerAuditRepository.save(consumerAudits);\n  }\n\n  @Transactional\n  public ConsumerToken createConsumerToken(ConsumerToken entity) {\n    entity.setId(0); //for protection\n\n    return consumerTokenRepository.save(entity);\n  }\n\n  private ConsumerToken generateConsumerToken(Consumer consumer, Date expires) {\n    long consumerId = consumer.getId();\n    String createdBy = userInfoHolder.getUser().getUserId();\n    Date createdTime = new Date();\n\n    ConsumerToken consumerToken = new ConsumerToken();\n    consumerToken.setConsumerId(consumerId);\n    consumerToken.setExpires(expires);\n    consumerToken.setDataChangeCreatedBy(createdBy);\n    consumerToken.setDataChangeCreatedTime(createdTime);\n    consumerToken.setDataChangeLastModifiedBy(createdBy);\n    consumerToken.setDataChangeLastModifiedTime(createdTime);\n\n    generateAndEnrichToken(consumer, consumerToken);\n\n    return consumerToken;\n  }\n\n  void generateAndEnrichToken(Consumer consumer, ConsumerToken consumerToken) {\n\n    Preconditions.checkArgument(consumer != null);\n\n    if (consumerToken.getDataChangeCreatedTime() == null) {\n      consumerToken.setDataChangeCreatedTime(new Date());\n    }\n    consumerToken.setToken(generateToken(consumer.getAppId(), consumerToken\n        .getDataChangeCreatedTime(), portalConfig.consumerTokenSalt()));\n  }\n\n  String generateToken(String consumerAppId, Date generationTime, String\n      consumerTokenSalt) {\n    return Hashing.sha1().hashString(KEY_JOINER.join(consumerAppId, TIMESTAMP_FORMAT.format\n        (generationTime), consumerTokenSalt), Charsets.UTF_8).toString();\n  }\n\n    ConsumerRole createConsumerRole(Long consumerId, Long roleId, String operator) {\n    ConsumerRole consumerRole = new ConsumerRole();\n\n    consumerRole.setConsumerId(consumerId);\n    consumerRole.setRoleId(roleId);\n    consumerRole.setDataChangeCreatedBy(operator);\n    consumerRole.setDataChangeLastModifiedBy(operator);\n\n    return consumerRole;\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/util/ConsumerAuditUtil.java",
    "content": "package com.ctrip.framework.apollo.openapi.util;\n\nimport com.google.common.base.Strings;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Queues;\n\nimport com.ctrip.framework.apollo.core.utils.ApolloThreadFactory;\nimport com.ctrip.framework.apollo.openapi.entity.ConsumerAudit;\nimport com.ctrip.framework.apollo.openapi.service.ConsumerService;\nimport com.ctrip.framework.apollo.tracer.Tracer;\n\nimport org.springframework.beans.factory.InitializingBean;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.Date;\nimport java.util.List;\nimport java.util.concurrent.BlockingQueue;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\nimport javax.servlet.http.HttpServletRequest;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@Service\npublic class ConsumerAuditUtil implements InitializingBean {\n  private static final int CONSUMER_AUDIT_MAX_SIZE = 10000;\n  private BlockingQueue<ConsumerAudit> audits = Queues.newLinkedBlockingQueue(CONSUMER_AUDIT_MAX_SIZE);\n  private final ExecutorService auditExecutorService;\n  private final AtomicBoolean auditStopped;\n  private int BATCH_SIZE = 100;\n  private long BATCH_TIMEOUT = 5;\n  private TimeUnit BATCH_TIMEUNIT = TimeUnit.SECONDS;\n\n  @Autowired\n  private ConsumerService consumerService;\n\n  public ConsumerAuditUtil() {\n    auditExecutorService = Executors.newSingleThreadExecutor(\n        ApolloThreadFactory.create(\"ConsumerAuditUtil\", true));\n    auditStopped = new AtomicBoolean(false);\n  }\n\n  public boolean audit(HttpServletRequest request, long consumerId) {\n    //ignore GET request\n    if (\"GET\".equalsIgnoreCase(request.getMethod())) {\n      return true;\n    }\n    String uri = request.getRequestURI();\n    if (!Strings.isNullOrEmpty(request.getQueryString())) {\n      uri += \"?\" + request.getQueryString();\n    }\n\n    ConsumerAudit consumerAudit = new ConsumerAudit();\n    Date now = new Date();\n    consumerAudit.setConsumerId(consumerId);\n    consumerAudit.setUri(uri);\n    consumerAudit.setMethod(request.getMethod());\n    consumerAudit.setDataChangeCreatedTime(now);\n    consumerAudit.setDataChangeLastModifiedTime(now);\n\n    //throw away audits if exceeds the max size\n    return this.audits.offer(consumerAudit);\n  }\n\n  @Override\n  public void afterPropertiesSet() throws Exception {\n    auditExecutorService.submit(() -> {\n      while (!auditStopped.get() && !Thread.currentThread().isInterrupted()) {\n        List<ConsumerAudit> toAudit = Lists.newArrayList();\n        try {\n          Queues.drain(audits, toAudit, BATCH_SIZE, BATCH_TIMEOUT, BATCH_TIMEUNIT);\n          if (!toAudit.isEmpty()) {\n            consumerService.createConsumerAudits(toAudit);\n          }\n        } catch (Throwable ex) {\n          Tracer.logError(ex);\n        }\n      }\n    });\n  }\n\n  public void stopAudit() {\n    auditStopped.set(true);\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/util/ConsumerAuthUtil.java",
    "content": "package com.ctrip.framework.apollo.openapi.util;\n\nimport com.ctrip.framework.apollo.openapi.service.ConsumerService;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport javax.servlet.http.HttpServletRequest;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@Service\npublic class ConsumerAuthUtil {\n  static final String CONSUMER_ID = \"ApolloConsumerId\";\n  @Autowired\n  private ConsumerService consumerService;\n\n  public Long getConsumerId(String token) {\n    return consumerService.getConsumerIdByToken(token);\n  }\n\n  public void storeConsumerId(HttpServletRequest request, Long consumerId) {\n    request.setAttribute(CONSUMER_ID, consumerId);\n  }\n\n  public long retrieveConsumerId(HttpServletRequest request) {\n    Object value = request.getAttribute(CONSUMER_ID);\n\n    try {\n      return Long.parseLong(value.toString());\n    } catch (Throwable ex) {\n      throw new IllegalStateException(\"No consumer id!\", ex);\n    }\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/util/OpenApiBeanUtils.java",
    "content": "package com.ctrip.framework.apollo.openapi.util;\n\nimport com.google.common.base.Preconditions;\nimport com.google.common.reflect.TypeToken;\nimport com.google.gson.Gson;\n\nimport com.ctrip.framework.apollo.common.dto.AppNamespaceDTO;\nimport com.ctrip.framework.apollo.common.dto.ItemDTO;\nimport com.ctrip.framework.apollo.common.dto.NamespaceLockDTO;\nimport com.ctrip.framework.apollo.common.dto.ReleaseDTO;\nimport com.ctrip.framework.apollo.common.entity.AppNamespace;\nimport com.ctrip.framework.apollo.common.utils.BeanUtils;\nimport com.ctrip.framework.apollo.openapi.dto.OpenAppNamespaceDTO;\nimport com.ctrip.framework.apollo.openapi.dto.OpenItemDTO;\nimport com.ctrip.framework.apollo.openapi.dto.OpenNamespaceDTO;\nimport com.ctrip.framework.apollo.openapi.dto.OpenNamespaceLockDTO;\nimport com.ctrip.framework.apollo.openapi.dto.OpenReleaseDTO;\nimport com.ctrip.framework.apollo.portal.entity.bo.ItemBO;\nimport com.ctrip.framework.apollo.portal.entity.bo.NamespaceBO;\n\nimport org.springframework.util.CollectionUtils;\n\nimport java.lang.reflect.Type;\nimport java.util.Collections;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.stream.Collectors;\n\npublic class OpenApiBeanUtils {\n\n  private static Gson gson = new Gson();\n  private static Type type = new TypeToken<Map<String, String>>() {\n  }.getType();\n\n  public static OpenItemDTO transformFromItemDTO(ItemDTO item) {\n    Preconditions.checkArgument(item != null);\n    return BeanUtils.transfrom(OpenItemDTO.class, item);\n  }\n\n  public static ItemDTO transformToItemDTO(OpenItemDTO openItemDTO) {\n    Preconditions.checkArgument(openItemDTO != null);\n    return BeanUtils.transfrom(ItemDTO.class, openItemDTO);\n  }\n\n  public static OpenAppNamespaceDTO transformToOpenAppNamespaceDTO(AppNamespace appNamespace) {\n    Preconditions.checkArgument(appNamespace != null);\n    return BeanUtils.transfrom(OpenAppNamespaceDTO.class, appNamespace);\n  }\n\n  public static AppNamespace transformToAppNamespace(OpenAppNamespaceDTO openAppNamespaceDTO) {\n    Preconditions.checkArgument(openAppNamespaceDTO != null);\n    return BeanUtils.transfrom(AppNamespace.class, openAppNamespaceDTO);\n  }\n\n  public static OpenReleaseDTO transformFromReleaseDTO(ReleaseDTO release) {\n    Preconditions.checkArgument(release != null);\n\n    OpenReleaseDTO openReleaseDTO = BeanUtils.transfrom(OpenReleaseDTO.class, release);\n\n    Map<String, String> configs = gson.fromJson(release.getConfigurations(), type);\n\n    openReleaseDTO.setConfigurations(configs);\n    return openReleaseDTO;\n  }\n\n  public static OpenNamespaceDTO transformFromNamespaceBO(NamespaceBO namespaceBO) {\n    Preconditions.checkArgument(namespaceBO != null);\n\n    OpenNamespaceDTO openNamespaceDTO = BeanUtils.transfrom(OpenNamespaceDTO.class, namespaceBO\n        .getBaseInfo());\n\n    //app namespace info\n    openNamespaceDTO.setFormat(namespaceBO.getFormat());\n    openNamespaceDTO.setComment(namespaceBO.getComment());\n    openNamespaceDTO.setPublic(namespaceBO.isPublic());\n\n    //items\n    List<OpenItemDTO> items = new LinkedList<>();\n    List<ItemBO> itemBOs = namespaceBO.getItems();\n    if (!CollectionUtils.isEmpty(itemBOs)) {\n      items.addAll(itemBOs.stream().map(itemBO -> transformFromItemDTO(itemBO.getItem())).collect\n          (Collectors.toList()));\n    }\n    openNamespaceDTO.setItems(items);\n    return openNamespaceDTO;\n\n  }\n\n  public static List<OpenNamespaceDTO> batchTransformFromNamespaceBOs(List<NamespaceBO>\n                                                                          namespaceBOs) {\n    if (CollectionUtils.isEmpty(namespaceBOs)) {\n      return Collections.emptyList();\n    }\n\n    List<OpenNamespaceDTO> openNamespaceDTOs =\n        namespaceBOs.stream().map(OpenApiBeanUtils::transformFromNamespaceBO)\n            .collect(Collectors.toCollection(LinkedList::new));\n\n    return openNamespaceDTOs;\n  }\n\n  public static OpenNamespaceLockDTO transformFromNamespaceLockDTO(String namespaceName,\n                                                                   NamespaceLockDTO\n                                                                       namespaceLock) {\n    OpenNamespaceLockDTO lock = new OpenNamespaceLockDTO();\n\n    lock.setNamespaceName(namespaceName);\n\n    if (namespaceLock == null) {\n      lock.setLocked(false);\n    } else {\n      lock.setLocked(true);\n      lock.setLockedBy(namespaceLock.getDataChangeCreatedBy());\n    }\n\n    return lock;\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/v1/controller/AppController.java",
    "content": "package com.ctrip.framework.apollo.openapi.v1.controller;\n\nimport com.ctrip.framework.apollo.common.dto.ClusterDTO;\nimport com.ctrip.framework.apollo.common.utils.BeanUtils;\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.openapi.dto.OpenEnvClusterDTO;\nimport com.ctrip.framework.apollo.portal.component.PortalSettings;\nimport com.ctrip.framework.apollo.portal.service.ClusterService;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.LinkedList;\nimport java.util.List;\n\n@RestController(\"openapiAppController\")\n@RequestMapping(\"/openapi/v1\")\npublic class AppController {\n\n  @Autowired\n  private PortalSettings portalSettings;\n  @Autowired\n  private ClusterService clusterService;\n\n  @RequestMapping(value = \"/apps/{appId}/envclusters\", method = RequestMethod.GET)\n  public List<OpenEnvClusterDTO> loadEnvClusterInfo(@PathVariable String appId){\n\n    List<OpenEnvClusterDTO> envClusters = new LinkedList<>();\n\n    List<Env> envs = portalSettings.getActiveEnvs();\n    for (Env env : envs) {\n      OpenEnvClusterDTO envCluster = new OpenEnvClusterDTO();\n\n      envCluster.setEnv(env.name());\n      List<ClusterDTO> clusterDTOs = clusterService.findClusters(env, appId);\n      envCluster.setClusters(BeanUtils.toPropertySet(\"name\", clusterDTOs));\n\n      envClusters.add(envCluster);\n    }\n\n    return envClusters;\n\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/v1/controller/ItemController.java",
    "content": "package com.ctrip.framework.apollo.openapi.v1.controller;\n\nimport com.ctrip.framework.apollo.common.dto.ItemDTO;\nimport com.ctrip.framework.apollo.common.exception.BadRequestException;\nimport com.ctrip.framework.apollo.common.utils.RequestPrecondition;\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.core.utils.StringUtils;\nimport com.ctrip.framework.apollo.openapi.dto.OpenItemDTO;\nimport com.ctrip.framework.apollo.openapi.util.OpenApiBeanUtils;\nimport com.ctrip.framework.apollo.portal.service.ItemService;\nimport com.ctrip.framework.apollo.portal.spi.UserService;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.security.access.prepost.PreAuthorize;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport javax.servlet.http.HttpServletRequest;\n\n\n@RestController(\"openapiItemController\")\n@RequestMapping(\"/openapi/v1/envs/{env}\")\npublic class ItemController {\n\n  @Autowired\n  private ItemService itemService;\n  @Autowired\n  private UserService userService;\n\n\n  @PreAuthorize(value = \"@consumerPermissionValidator.hasModifyNamespacePermission(#request, #appId, #namespaceName)\")\n  @RequestMapping(value = \"/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items\", method = RequestMethod.POST)\n  public OpenItemDTO createItem(@PathVariable String appId, @PathVariable String env,\n                                @PathVariable String clusterName, @PathVariable String namespaceName,\n                                @RequestBody OpenItemDTO item, HttpServletRequest request) {\n\n    RequestPrecondition.checkArguments(\n        !StringUtils.isContainEmpty(item.getKey(), item.getValue(), item.getDataChangeCreatedBy()),\n        \"key,value,dataChangeCreatedBy 字段不能为空\");\n\n    if (userService.findByUserId(item.getDataChangeCreatedBy()) == null) {\n      throw new BadRequestException(\"用户不存在.\");\n    }\n\n    ItemDTO toCreate = OpenApiBeanUtils.transformToItemDTO(item);\n\n    //protect\n    toCreate.setLineNum(0);\n    toCreate.setId(0);\n    toCreate.setDataChangeLastModifiedBy(toCreate.getDataChangeCreatedBy());\n    toCreate.setDataChangeLastModifiedTime(null);\n    toCreate.setDataChangeCreatedTime(null);\n\n    ItemDTO createdItem = itemService.createItem(appId, Env.fromString(env),\n        clusterName, namespaceName, toCreate);\n    return OpenApiBeanUtils.transformFromItemDTO(createdItem);\n  }\n\n  @PreAuthorize(value = \"@consumerPermissionValidator.hasModifyNamespacePermission(#request, #appId, #namespaceName)\")\n  @RequestMapping(value = \"/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items/{key:.+}\", method = RequestMethod.PUT)\n  public void updateItem(@PathVariable String appId, @PathVariable String env,\n                         @PathVariable String clusterName, @PathVariable String namespaceName,\n                         @PathVariable String key, @RequestBody OpenItemDTO item, HttpServletRequest request) {\n\n    RequestPrecondition.checkArguments(item != null, \"item payload can not be empty\");\n\n    RequestPrecondition.checkArguments(\n        !StringUtils.isContainEmpty(item.getKey(), item.getValue(), item.getDataChangeLastModifiedBy()),\n        \"key,value,dataChangeLastModifiedBy can not be empty\");\n\n    RequestPrecondition.checkArguments(item.getKey().equals(key), \"Key in path and payload is not consistent\");\n\n    if (userService.findByUserId(item.getDataChangeLastModifiedBy()) == null) {\n      throw new BadRequestException(\"user(dataChangeLastModifiedBy) not exists\");\n    }\n\n    ItemDTO toUpdateItem = itemService.loadItem(Env.fromString(env), appId, clusterName, namespaceName, item.getKey());\n    if (toUpdateItem == null) {\n      throw new BadRequestException(\"item not exists\");\n    }\n    //protect. only value,comment,lastModifiedBy can be modified\n    toUpdateItem.setComment(item.getComment());\n    toUpdateItem.setValue(item.getValue());\n    toUpdateItem.setDataChangeLastModifiedBy(item.getDataChangeLastModifiedBy());\n\n    itemService.updateItem(appId, Env.fromString(env), clusterName, namespaceName, toUpdateItem);\n  }\n\n\n  @PreAuthorize(value = \"@consumerPermissionValidator.hasModifyNamespacePermission(#request, #appId, #namespaceName)\")\n  @RequestMapping(value = \"/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items/{key:.+}\", method = RequestMethod.DELETE)\n  public void deleteItem(@PathVariable String appId, @PathVariable String env,\n                         @PathVariable String clusterName, @PathVariable String namespaceName,\n                         @PathVariable String key, @RequestParam String operator,\n                         HttpServletRequest request) {\n\n    if (userService.findByUserId(operator) == null) {\n      throw new BadRequestException(\"user(operator) not exists\");\n    }\n\n    ItemDTO toDeleteItem = itemService.loadItem(Env.fromString(env), appId, clusterName, namespaceName, key);\n    if (toDeleteItem == null){\n      throw new BadRequestException(\"item not exists\");\n    }\n\n    itemService.deleteItem(Env.fromString(env), toDeleteItem.getId(), operator);\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/v1/controller/NamespaceController.java",
    "content": "package com.ctrip.framework.apollo.openapi.v1.controller;\n\n\nimport com.ctrip.framework.apollo.common.dto.NamespaceDTO;\nimport com.ctrip.framework.apollo.common.dto.NamespaceLockDTO;\nimport com.ctrip.framework.apollo.common.entity.AppNamespace;\nimport com.ctrip.framework.apollo.common.exception.BadRequestException;\nimport com.ctrip.framework.apollo.common.utils.InputValidator;\nimport com.ctrip.framework.apollo.common.utils.RequestPrecondition;\nimport com.ctrip.framework.apollo.core.enums.ConfigFileFormat;\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.openapi.dto.OpenAppNamespaceDTO;\nimport com.ctrip.framework.apollo.openapi.dto.OpenNamespaceDTO;\nimport com.ctrip.framework.apollo.openapi.dto.OpenNamespaceLockDTO;\nimport com.ctrip.framework.apollo.openapi.util.OpenApiBeanUtils;\nimport com.ctrip.framework.apollo.portal.entity.bo.NamespaceBO;\nimport com.ctrip.framework.apollo.portal.listener.AppNamespaceCreationEvent;\nimport com.ctrip.framework.apollo.portal.service.AppNamespaceService;\nimport com.ctrip.framework.apollo.portal.service.NamespaceLockService;\nimport com.ctrip.framework.apollo.portal.service.NamespaceService;\nimport com.ctrip.framework.apollo.portal.spi.UserService;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.ApplicationEventPublisher;\nimport org.springframework.security.access.prepost.PreAuthorize;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.List;\nimport java.util.Objects;\n\nimport javax.servlet.http.HttpServletRequest;\n\n@RestController(\"openapiNamespaceController\")\npublic class NamespaceController {\n\n  @Autowired\n  private NamespaceLockService namespaceLockService;\n  @Autowired\n  private NamespaceService namespaceService;\n  @Autowired\n  private AppNamespaceService appNamespaceService;\n  @Autowired\n  private ApplicationEventPublisher publisher;\n  @Autowired\n  private UserService userService;\n\n\n  @PreAuthorize(value = \"@consumerPermissionValidator.hasCreateNamespacePermission(#request, #appId)\")\n  @RequestMapping(value = \"/openapi/v1/apps/{appId}/appnamespaces\", method = RequestMethod.POST)\n  public OpenAppNamespaceDTO createNamespace(@PathVariable String appId, @RequestBody OpenAppNamespaceDTO appNamespaceDTO,\n                                         HttpServletRequest request) {\n\n    if (!Objects.equals(appId, appNamespaceDTO.getAppId())) {\n      throw new BadRequestException(String.format(\"AppId not equal. AppId in path = %s, AppId in payload = %s\", appId,\n                                                  appNamespaceDTO.getAppId()));\n    }\n    RequestPrecondition.checkArgumentsNotEmpty(appNamespaceDTO.getAppId(), appNamespaceDTO.getName(),\n                                               appNamespaceDTO.getFormat(), appNamespaceDTO.getDataChangeCreatedBy());\n\n    if (!InputValidator.isValidAppNamespace(appNamespaceDTO.getName())) {\n      throw new BadRequestException(String.format(\"Namespace格式错误: %s\",\n                                                  InputValidator.INVALID_CLUSTER_NAMESPACE_MESSAGE + \" & \"\n                                                  + InputValidator.INVALID_NAMESPACE_NAMESPACE_MESSAGE));\n    }\n\n    if (!ConfigFileFormat.isValidFormat(appNamespaceDTO.getFormat())) {\n      throw new BadRequestException(String.format(\"Invalid namespace format. format = %s\", appNamespaceDTO.getFormat()));\n    }\n\n    String operator = appNamespaceDTO.getDataChangeCreatedBy();\n    if (userService.findByUserId(operator) == null) {\n      throw new BadRequestException(String.format(\"Illegal user. user = %s\", operator));\n    }\n\n    AppNamespace appNamespace = OpenApiBeanUtils.transformToAppNamespace(appNamespaceDTO);\n    AppNamespace createdAppNamespace = appNamespaceService.createAppNamespaceInLocal(appNamespace);\n\n    publisher.publishEvent(new AppNamespaceCreationEvent(createdAppNamespace));\n\n    return OpenApiBeanUtils.transformToOpenAppNamespaceDTO(createdAppNamespace);\n  }\n\n  @RequestMapping(value = \"/openapi/v1/envs/{env}/apps/{appId}/clusters/{clusterName}/namespaces\", method = RequestMethod.GET)\n  public List<OpenNamespaceDTO> findNamespaces(@PathVariable String appId, @PathVariable String env,\n                                               @PathVariable String clusterName) {\n\n    return OpenApiBeanUtils\n        .batchTransformFromNamespaceBOs(namespaceService.findNamespaceBOs(appId, Env\n            .fromString(env), clusterName));\n  }\n\n  @RequestMapping(value = \"/openapi/v1/envs/{env}/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName:.+}\", method = RequestMethod.GET)\n  public OpenNamespaceDTO loadNamespace(@PathVariable String appId, @PathVariable String env,\n                                        @PathVariable String clusterName, @PathVariable String\n                                            namespaceName) {\n    NamespaceBO namespaceBO = namespaceService.loadNamespaceBO(appId, Env.fromString\n        (env), clusterName, namespaceName);\n    if (namespaceBO == null) {\n      return null;\n    }\n    return OpenApiBeanUtils.transformFromNamespaceBO(namespaceBO);\n  }\n\n  @RequestMapping(value = \"/openapi/v1/envs/{env}/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/lock\", method = RequestMethod.GET)\n  public OpenNamespaceLockDTO getNamespaceLock(@PathVariable String appId, @PathVariable String env,\n                                               @PathVariable String clusterName, @PathVariable\n                                                   String namespaceName) {\n\n    NamespaceDTO namespace = namespaceService.loadNamespaceBaseInfo(appId, Env\n        .fromString(env), clusterName, namespaceName);\n    NamespaceLockDTO lockDTO = namespaceLockService.getNamespaceLock(appId, Env\n        .fromString(env), clusterName, namespaceName);\n    return OpenApiBeanUtils.transformFromNamespaceLockDTO(namespace.getNamespaceName(), lockDTO);\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/v1/controller/ReleaseController.java",
    "content": "package com.ctrip.framework.apollo.openapi.v1.controller;\n\n\nimport com.ctrip.framework.apollo.common.dto.ReleaseDTO;\nimport com.ctrip.framework.apollo.common.exception.BadRequestException;\nimport com.ctrip.framework.apollo.common.utils.RequestPrecondition;\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.core.utils.StringUtils;\nimport com.ctrip.framework.apollo.openapi.dto.OpenReleaseDTO;\nimport com.ctrip.framework.apollo.openapi.util.OpenApiBeanUtils;\nimport com.ctrip.framework.apollo.portal.entity.model.NamespaceReleaseModel;\nimport com.ctrip.framework.apollo.portal.service.ReleaseService;\nimport com.ctrip.framework.apollo.portal.spi.UserService;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.security.access.prepost.PreAuthorize;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport javax.servlet.http.HttpServletRequest;\n\nimport static com.ctrip.framework.apollo.common.utils.RequestPrecondition.checkModel;\n\n@RestController(\"openapiReleaseController\")\n@RequestMapping(\"/openapi/v1/envs/{env}\")\npublic class ReleaseController {\n\n  @Autowired\n  private ReleaseService releaseService;\n  @Autowired\n  private UserService userService;\n\n  @PreAuthorize(value = \"@consumerPermissionValidator.hasReleaseNamespacePermission(#request, #appId, #namespaceName)\")\n  @RequestMapping(value = \"/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases\", method = RequestMethod.POST)\n  public OpenReleaseDTO createRelease(@PathVariable String appId, @PathVariable String env,\n                                      @PathVariable String clusterName,\n                                      @PathVariable String namespaceName,\n                                      @RequestBody NamespaceReleaseModel model,\n                                      HttpServletRequest request) {\n\n    checkModel(model != null);\n    RequestPrecondition.checkArguments(!StringUtils.isContainEmpty(model.getReleasedBy(), model\n            .getReleaseTitle()),\n        \"Params(releaseTitle and releasedBy) can not be empty\");\n\n    if (userService.findByUserId(model.getReleasedBy()) == null) {\n      throw new BadRequestException(\"user(releaseBy) not exists\");\n    }\n\n    model.setAppId(appId);\n    model.setEnv(Env.fromString(env).toString());\n    model.setClusterName(clusterName);\n    model.setNamespaceName(namespaceName);\n\n    return OpenApiBeanUtils.transformFromReleaseDTO(releaseService.publish(model));\n  }\n\n  @RequestMapping(value = \"/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases/latest\", method = RequestMethod.GET)\n  public OpenReleaseDTO loadLatestActiveRelease(@PathVariable String appId, @PathVariable String env,\n                                                @PathVariable String clusterName, @PathVariable\n                                                    String namespaceName) {\n    ReleaseDTO releaseDTO = releaseService.loadLatestRelease(appId, Env.fromString\n        (env), clusterName, namespaceName);\n    if (releaseDTO == null) {\n      return null;\n    }\n\n    return OpenApiBeanUtils.transformFromReleaseDTO(releaseDTO);\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/PortalApplication.java",
    "content": "package com.ctrip.framework.apollo.portal;\n\nimport com.ctrip.framework.apollo.common.ApolloCommonConfig;\nimport com.ctrip.framework.apollo.openapi.PortalOpenApiConfig;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.actuate.system.ApplicationPidFileWriter;\nimport org.springframework.boot.actuate.system.EmbeddedServerPortFileWriter;\nimport org.springframework.boot.autoconfigure.EnableAutoConfiguration;\nimport org.springframework.context.ConfigurableApplicationContext;\nimport org.springframework.context.annotation.ComponentScan;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.context.annotation.EnableAspectJAutoProxy;\nimport org.springframework.context.annotation.PropertySource;\nimport org.springframework.transaction.annotation.EnableTransactionManagement;\n\n@EnableAspectJAutoProxy\n@Configuration\n@PropertySource(value = {\"classpath:portal.properties\"})\n@EnableAutoConfiguration\n@EnableTransactionManagement\n@ComponentScan(basePackageClasses = {ApolloCommonConfig.class,\n    PortalApplication.class, PortalOpenApiConfig.class})\npublic class PortalApplication {\n\n  public static void main(String[] args) throws Exception {\n    ConfigurableApplicationContext context = SpringApplication.run(PortalApplication.class, args);\n    context.addApplicationListener(new ApplicationPidFileWriter());\n    context.addApplicationListener(new EmbeddedServerPortFileWriter());\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/api/API.java",
    "content": "package com.ctrip.framework.apollo.portal.api;\n\n\nimport com.ctrip.framework.apollo.portal.component.RetryableRestTemplate;\n\nimport org.springframework.beans.factory.annotation.Autowired;\n\npublic abstract class API {\n\n  @Autowired\n  protected RetryableRestTemplate restTemplate;\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/api/AdminServiceAPI.java",
    "content": "package com.ctrip.framework.apollo.portal.api;\n\n\nimport com.google.common.base.Joiner;\n\nimport com.ctrip.framework.apollo.common.dto.AppDTO;\nimport com.ctrip.framework.apollo.common.dto.AppNamespaceDTO;\nimport com.ctrip.framework.apollo.common.dto.ClusterDTO;\nimport com.ctrip.framework.apollo.common.dto.CommitDTO;\nimport com.ctrip.framework.apollo.common.dto.GrayReleaseRuleDTO;\nimport com.ctrip.framework.apollo.common.dto.InstanceDTO;\nimport com.ctrip.framework.apollo.common.dto.ItemChangeSets;\nimport com.ctrip.framework.apollo.common.dto.ItemDTO;\nimport com.ctrip.framework.apollo.common.dto.NamespaceDTO;\nimport com.ctrip.framework.apollo.common.dto.NamespaceLockDTO;\nimport com.ctrip.framework.apollo.common.dto.PageDTO;\nimport com.ctrip.framework.apollo.common.dto.ReleaseDTO;\nimport com.ctrip.framework.apollo.common.dto.ReleaseHistoryDTO;\nimport com.ctrip.framework.apollo.core.enums.Env;\n\nimport org.springframework.boot.actuate.health.Health;\nimport org.springframework.core.ParameterizedTypeReference;\nimport org.springframework.data.domain.Pageable;\nimport org.springframework.http.HttpEntity;\nimport org.springframework.http.HttpHeaders;\nimport org.springframework.http.MediaType;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.stereotype.Service;\nimport org.springframework.util.CollectionUtils;\nimport org.springframework.util.LinkedMultiValueMap;\nimport org.springframework.util.MultiValueMap;\n\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\n\n@Service\npublic class AdminServiceAPI {\n\n  @Service\n  public static class HealthAPI extends API {\n\n    public Health health(Env env) {\n      return restTemplate.get(env, \"/health\", Health.class);\n    }\n  }\n\n  @Service\n  public static class AppAPI extends API {\n\n    public AppDTO loadApp(Env env, String appId) {\n      return restTemplate.get(env, \"apps/{appId}\", AppDTO.class, appId);\n    }\n\n    public AppDTO createApp(Env env, AppDTO app) {\n      return restTemplate.post(env, \"apps\", app, AppDTO.class);\n    }\n\n    public void updateApp(Env env, AppDTO app) {\n      restTemplate.put(env, \"apps/{appId}\", app, app.getAppId());\n    }\n  }\n\n\n  @Service\n  public static class NamespaceAPI extends API {\n\n    private ParameterizedTypeReference<Map<String, Boolean>>\n        typeReference = new ParameterizedTypeReference<Map<String, Boolean>>() {\n    };\n\n    public List<NamespaceDTO> findNamespaceByCluster(String appId, Env env, String clusterName) {\n      NamespaceDTO[] namespaceDTOs = restTemplate.get(env, \"apps/{appId}/clusters/{clusterName}/namespaces\",\n                                                      NamespaceDTO[].class, appId,\n                                                      clusterName);\n      return Arrays.asList(namespaceDTOs);\n    }\n\n    public NamespaceDTO loadNamespace(String appId, Env env, String clusterName,\n                                      String namespaceName) {\n      return\n          restTemplate.get(env, \"apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}\",\n                           NamespaceDTO.class, appId, clusterName, namespaceName);\n    }\n\n    public NamespaceDTO findPublicNamespaceForAssociatedNamespace(Env env, String appId, String clusterName,\n                                                                  String namespaceName) {\n      return\n          restTemplate\n              .get(env, \"apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/associated-public-namespace\",\n                   NamespaceDTO.class, appId, clusterName, namespaceName);\n    }\n\n    public NamespaceDTO createNamespace(Env env, NamespaceDTO namespace) {\n      return restTemplate\n          .post(env, \"apps/{appId}/clusters/{clusterName}/namespaces\", namespace, NamespaceDTO.class,\n                namespace.getAppId(), namespace.getClusterName());\n    }\n\n    public AppNamespaceDTO createAppNamespace(Env env, AppNamespaceDTO appNamespace) {\n      return restTemplate\n          .post(env, \"apps/{appId}/appnamespaces\", appNamespace, AppNamespaceDTO.class, appNamespace.getAppId());\n    }\n\n    public void deleteNamespace(Env env, String appId, String clusterName, String namespaceName, String operator) {\n      restTemplate\n          .delete(env, \"apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}?operator={operator}\", appId,\n                  clusterName,\n                  namespaceName, operator);\n    }\n\n    public Map<String, Boolean> getNamespacePublishInfo(Env env, String appId) {\n      return restTemplate.get(env, \"apps/{appId}/namespaces/publish_info\", typeReference, appId).getBody();\n    }\n\n    public List<NamespaceDTO> getPublicAppNamespaceAllNamespaces(Env env, String publicNamespaceName,\n                                                                 int page, int size) {\n      NamespaceDTO[] namespaceDTOs =\n          restTemplate.get(env, \"/appnamespaces/{publicNamespaceName}/namespaces?page={page}&size={size}\",\n                           NamespaceDTO[].class, publicNamespaceName, page, size);\n      return Arrays.asList(namespaceDTOs);\n    }\n\n    public int countPublicAppNamespaceAssociatedNamespaces(Env env, String publicNamesapceName) {\n      Integer count =\n          restTemplate.get(env, \"/appnamespaces/{publicNamespaceName}/associated-namespaces/count\", Integer.class,\n                           publicNamesapceName);\n\n      return count == null ? 0 : count;\n    }\n\n  }\n\n  @Service\n  public static class ItemAPI extends API {\n\n    public List<ItemDTO> findItems(String appId, Env env, String clusterName, String namespaceName) {\n      ItemDTO[] itemDTOs =\n          restTemplate.get(env, \"apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items\",\n                           ItemDTO[].class, appId, clusterName, namespaceName);\n      return Arrays.asList(itemDTOs);\n    }\n\n    public ItemDTO loadItem(Env env, String appId, String clusterName, String namespaceName, String key) {\n      return restTemplate.get(env, \"apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items/{key}\",\n                              ItemDTO.class, appId, clusterName, namespaceName, key);\n    }\n\n    public void updateItemsByChangeSet(String appId, Env env, String clusterName, String namespace,\n                                       ItemChangeSets changeSets) {\n      restTemplate.post(env, \"apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/itemset\",\n                        changeSets, Void.class, appId, clusterName, namespace);\n    }\n\n    public void updateItem(String appId, Env env, String clusterName, String namespace, long itemId, ItemDTO item) {\n      restTemplate.put(env, \"apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items/{itemId}\",\n                       item, appId, clusterName, namespace, itemId);\n\n    }\n\n    public ItemDTO createItem(String appId, Env env, String clusterName, String namespace, ItemDTO item) {\n      return restTemplate.post(env, \"apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items\",\n                               item, ItemDTO.class, appId, clusterName, namespace);\n    }\n\n    public void deleteItem(Env env, long itemId, String operator) {\n\n      restTemplate.delete(env, \"items/{itemId}?operator={operator}\", itemId, operator);\n    }\n  }\n\n  @Service\n  public static class ClusterAPI extends API {\n\n    public List<ClusterDTO> findClustersByApp(String appId, Env env) {\n      ClusterDTO[] clusterDTOs = restTemplate.get(env, \"apps/{appId}/clusters\", ClusterDTO[].class,\n                                                  appId);\n      return Arrays.asList(clusterDTOs);\n    }\n\n    public ClusterDTO loadCluster(String appId, Env env, String clusterName) {\n      return restTemplate.get(env, \"apps/{appId}/clusters/{clusterName}\", ClusterDTO.class,\n                              appId, clusterName);\n    }\n\n    public boolean isClusterUnique(String appId, Env env, String clusterName) {\n      return restTemplate\n          .get(env, \"apps/{appId}/cluster/{clusterName}/unique\", Boolean.class,\n               appId, clusterName);\n\n    }\n\n    public ClusterDTO create(Env env, ClusterDTO cluster) {\n      return restTemplate.post(env, \"apps/{appId}/clusters\", cluster, ClusterDTO.class,\n                               cluster.getAppId());\n    }\n\n\n    public void delete(Env env, String appId, String clusterName, String operator) {\n      restTemplate.delete(env, \"apps/{appId}/clusters/{clusterName}?operator={operator}\", appId, clusterName, operator);\n    }\n  }\n\n  @Service\n  public static class ReleaseAPI extends API {\n\n    private static final Joiner JOINER = Joiner.on(\",\");\n\n    public ReleaseDTO loadRelease(Env env, long releaseId) {\n      return restTemplate.get(env, \"releases/{releaseId}\", ReleaseDTO.class, releaseId);\n    }\n\n    public List<ReleaseDTO> findReleaseByIds(Env env, Set<Long> releaseIds) {\n      if (CollectionUtils.isEmpty(releaseIds)) {\n        return Collections.emptyList();\n      }\n\n      ReleaseDTO[]\n          releases =\n          restTemplate.get(env, \"/releases?releaseIds={releaseIds}\", ReleaseDTO[].class, JOINER.join(releaseIds));\n      return Arrays.asList(releases);\n\n    }\n\n    public List<ReleaseDTO> findAllReleases(String appId, Env env, String clusterName, String namespaceName, int page,\n                                            int size) {\n      ReleaseDTO[] releaseDTOs = restTemplate.get(\n          env, \"apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases/all?page={page}&size={size}\",\n          ReleaseDTO[].class,\n          appId, clusterName, namespaceName, page, size);\n      return Arrays.asList(releaseDTOs);\n    }\n\n    public List<ReleaseDTO> findActiveReleases(String appId, Env env, String clusterName, String namespaceName,\n                                               int page,\n                                               int size) {\n      ReleaseDTO[] releaseDTOs = restTemplate.get(\n          env, \"apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases/active?page={page}&size={size}\",\n          ReleaseDTO[].class,\n          appId, clusterName, namespaceName, page, size);\n      return Arrays.asList(releaseDTOs);\n    }\n\n    public ReleaseDTO loadLatestRelease(String appId, Env env, String clusterName,\n                                        String namespace) {\n      ReleaseDTO releaseDTO = restTemplate\n          .get(env, \"apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases/latest\",\n               ReleaseDTO.class, appId, clusterName, namespace);\n      return releaseDTO;\n    }\n\n    public ReleaseDTO createRelease(String appId, Env env, String clusterName, String namespace,\n                                    String releaseName, String releaseComment, String operator,\n                                    boolean isEmergencyPublish) {\n      HttpHeaders headers = new HttpHeaders();\n      headers.setContentType(MediaType.parseMediaType(MediaType.APPLICATION_FORM_URLENCODED_VALUE + \";charset=UTF-8\"));\n      MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();\n      parameters.add(\"name\", releaseName);\n      parameters.add(\"comment\", releaseComment);\n      parameters.add(\"operator\", operator);\n      parameters.add(\"isEmergencyPublish\", String.valueOf(isEmergencyPublish));\n      HttpEntity<MultiValueMap<String, String>> entity =\n          new HttpEntity<>(parameters, headers);\n      ReleaseDTO response = restTemplate.post(\n          env, \"apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases\", entity,\n          ReleaseDTO.class, appId, clusterName, namespace);\n      return response;\n    }\n\n    public ReleaseDTO updateAndPublish(String appId, Env env, String clusterName, String namespace,\n                                       String releaseName, String releaseComment, String branchName,\n                                       boolean isEmergencyPublish, boolean deleteBranch, ItemChangeSets changeSets) {\n\n      return restTemplate.post(env,\n                               \"apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/updateAndPublish?\"\n                               + \"releaseName={releaseName}&releaseComment={releaseComment}&branchName={branchName}\"\n                               + \"&deleteBranch={deleteBranch}&isEmergencyPublish={isEmergencyPublish}\",\n                               changeSets, ReleaseDTO.class, appId, clusterName, namespace,\n                               releaseName, releaseComment, branchName, deleteBranch, isEmergencyPublish);\n\n    }\n\n    public void rollback(Env env, long releaseId, String operator) {\n      restTemplate.put(env,\n                       \"releases/{releaseId}/rollback?operator={operator}\",\n                       null, releaseId, operator);\n    }\n  }\n\n  @Service\n  public static class CommitAPI extends API {\n\n    public List<CommitDTO> find(String appId, Env env, String clusterName, String namespaceName, int page, int size) {\n\n      CommitDTO[] commitDTOs = restTemplate.get(env,\n                                                \"apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/commit?page={page}&size={size}\",\n                                                CommitDTO[].class,\n                                                appId, clusterName, namespaceName, page, size);\n\n      return Arrays.asList(commitDTOs);\n    }\n  }\n\n  @Service\n  public static class NamespaceLockAPI extends API {\n\n    public NamespaceLockDTO getNamespaceLockOwner(String appId, Env env, String clusterName, String namespaceName) {\n      return restTemplate.get(env, \"apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/lock\",\n                              NamespaceLockDTO.class,\n                              appId, clusterName, namespaceName);\n\n    }\n  }\n\n  @Service\n  public static class InstanceAPI extends API {\n\n    private Joiner joiner = Joiner.on(\",\");\n    private ParameterizedTypeReference<PageDTO<InstanceDTO>>\n        pageInstanceDtoType =\n        new ParameterizedTypeReference<PageDTO<InstanceDTO>>() {\n        };\n\n    public PageDTO<InstanceDTO> getByRelease(Env env, long releaseId, int page, int size) {\n      ResponseEntity<PageDTO<InstanceDTO>>\n          entity =\n          restTemplate\n              .get(env, \"/instances/by-release?releaseId={releaseId}&page={page}&size={size}\", pageInstanceDtoType,\n                   releaseId, page, size);\n      return entity.getBody();\n\n    }\n\n    public List<InstanceDTO> getByReleasesNotIn(String appId, Env env, String clusterName, String namespaceName,\n                                                Set<Long> releaseIds) {\n\n      InstanceDTO[]\n          instanceDTOs =\n          restTemplate.get(env,\n                           \"/instances/by-namespace-and-releases-not-in?appId={appId}&clusterName={clusterName}&namespaceName={namespaceName}&releaseIds={releaseIds}\",\n                           InstanceDTO[].class, appId, clusterName, namespaceName, joiner.join(releaseIds));\n\n      return Arrays.asList(instanceDTOs);\n    }\n\n    public PageDTO<InstanceDTO> getByNamespace(String appId, Env env, String clusterName, String namespaceName,\n                                               String instanceAppId,\n                                               int page, int size) {\n      ResponseEntity<PageDTO<InstanceDTO>>\n          entity =\n          restTemplate.get(env,\n                           \"/instances/by-namespace?appId={appId}\"\n                           + \"&clusterName={clusterName}&namespaceName={namespaceName}&instanceAppId={instanceAppId}\"\n                           + \"&page={page}&size={size}\",\n                           pageInstanceDtoType, appId, clusterName, namespaceName, instanceAppId, page, size);\n      return entity.getBody();\n    }\n\n    public int getInstanceCountByNamespace(String appId, Env env, String clusterName, String namespaceName) {\n      Integer\n          count =\n          restTemplate.get(env,\n                           \"/instances/by-namespace/count?appId={appId}&clusterName={clusterName}&namespaceName={namespaceName}\",\n                           Integer.class, appId, clusterName, namespaceName);\n      if (count == null) {\n        return 0;\n      }\n      return count;\n    }\n  }\n\n  @Service\n  public static class NamespaceBranchAPI extends API {\n\n    public NamespaceDTO createBranch(String appId, Env env, String clusterName,\n                                     String namespaceName, String operator) {\n      return restTemplate\n          .post(env, \"/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/branches?operator={operator}\",\n                null, NamespaceDTO.class, appId, clusterName, namespaceName, operator);\n    }\n\n    public NamespaceDTO findBranch(String appId, Env env, String clusterName,\n                                   String namespaceName) {\n      return restTemplate.get(env, \"/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/branches\",\n                              NamespaceDTO.class, appId, clusterName, namespaceName);\n    }\n\n    public GrayReleaseRuleDTO findBranchGrayRules(String appId, Env env, String clusterName,\n                                                  String namespaceName, String branchName) {\n      return restTemplate\n          .get(env, \"/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/branches/{branchName}/rules\",\n               GrayReleaseRuleDTO.class, appId, clusterName, namespaceName, branchName);\n\n    }\n\n    public void updateBranchGrayRules(String appId, Env env, String clusterName,\n                                      String namespaceName, String branchName, GrayReleaseRuleDTO rules) {\n      restTemplate\n          .put(env, \"/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/branches/{branchName}/rules\",\n               rules, appId, clusterName, namespaceName, branchName);\n\n    }\n\n    public void deleteBranch(String appId, Env env, String clusterName,\n                             String namespaceName, String branchName, String operator) {\n      restTemplate.delete(env,\n                          \"/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/branches/{branchName}?operator={operator}\",\n                          appId, clusterName, namespaceName, branchName, operator);\n    }\n  }\n\n  @Service\n  public static class ReleaseHistoryAPI extends API {\n\n    private ParameterizedTypeReference<PageDTO<ReleaseHistoryDTO>> type =\n        new ParameterizedTypeReference<PageDTO<ReleaseHistoryDTO>>() {\n        };\n\n\n    public PageDTO<ReleaseHistoryDTO> findReleaseHistoriesByNamespace(String appId, Env env, String clusterName,\n                                                                      String namespaceName, int page, int size) {\n      return restTemplate.get(env,\n                              \"/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases/histories?page={page}&size={size}\",\n                              type, appId, clusterName, namespaceName, page, size).getBody();\n    }\n\n    public PageDTO<ReleaseHistoryDTO> findByReleaseIdAndOperation(Env env, long releaseId, int operation, int page,\n                                                                  int size) {\n      return restTemplate.get(env,\n                              \"/releases/histories/by_release_id_and_operation?releaseId={releaseId}&operation={operation}&page={page}&size={size}\",\n                              type, releaseId, operation, page, size).getBody();\n    }\n\n    public PageDTO<ReleaseHistoryDTO> findByPreviousReleaseIdAndOperation(Env env, long previousReleaseId,\n                                                                          int operation, int page, int size) {\n      return restTemplate.get(env,\n                              \"/releases/histories/by_previous_release_id_and_operation?previousReleaseId={releaseId}&operation={operation}&page={page}&size={size}\",\n                              type, previousReleaseId, operation, page, size).getBody();\n    }\n\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/component/AdminServiceAddressLocator.java",
    "content": "package com.ctrip.framework.apollo.portal.component;\n\nimport com.google.common.collect.Lists;\n\nimport com.ctrip.framework.apollo.core.MetaDomainConsts;\nimport com.ctrip.framework.apollo.core.dto.ServiceDTO;\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.core.utils.ApolloThreadFactory;\nimport com.ctrip.framework.apollo.tracer.Tracer;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.autoconfigure.web.HttpMessageConverters;\nimport org.springframework.http.client.HttpComponentsClientHttpRequestFactory;\nimport org.springframework.http.client.SimpleClientHttpRequestFactory;\nimport org.springframework.stereotype.Component;\nimport org.springframework.util.CollectionUtils;\nimport org.springframework.web.client.RestTemplate;\n\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.TimeUnit;\n\nimport javax.annotation.PostConstruct;\n\n@Component\npublic class AdminServiceAddressLocator {\n\n  private static final long NORMAL_REFRESH_INTERVAL = 5 * 60 * 1000;\n  private static final long OFFLINE_REFRESH_INTERVAL = 10 * 1000;\n  private static final int RETRY_TIMES = 3;\n  private static final String ADMIN_SERVICE_URL_PATH = \"/services/admin\";\n  private static final Logger logger = LoggerFactory.getLogger(AdminServiceAddressLocator.class);\n\n  private ScheduledExecutorService refreshServiceAddressService;\n  private RestTemplate restTemplate;\n  private List<Env> allEnvs;\n  private Map<Env, List<ServiceDTO>> cache = new ConcurrentHashMap<>();\n\n  @Autowired\n  private HttpMessageConverters httpMessageConverters;\n  @Autowired\n  private PortalSettings portalSettings;\n  @Autowired\n  private RestTemplateFactory restTemplateFactory;\n\n  @PostConstruct\n  public void init() {\n    allEnvs = portalSettings.getAllEnvs();\n\n    //init restTemplate\n    restTemplate = restTemplateFactory.getObject();\n\n    refreshServiceAddressService =\n        Executors.newScheduledThreadPool(1, ApolloThreadFactory.create(\"ServiceLocator\", true));\n\n    refreshServiceAddressService.schedule(new RefreshAdminServerAddressTask(), 1, TimeUnit.MILLISECONDS);\n  }\n\n  public List<ServiceDTO> getServiceList(Env env) {\n    List<ServiceDTO> services = cache.get(env);\n    if (CollectionUtils.isEmpty(services)) {\n      return Collections.emptyList();\n    }\n    List<ServiceDTO> randomConfigServices = Lists.newArrayList(services);\n    Collections.shuffle(randomConfigServices);\n    return randomConfigServices;\n  }\n\n  //maintain admin server address\n  private class RefreshAdminServerAddressTask implements Runnable {\n\n    @Override\n    public void run() {\n      boolean refreshSuccess = true;\n      //refresh fail if get any env address fail\n      for (Env env : allEnvs) {\n        boolean currentEnvRefreshResult = refreshServerAddressCache(env);\n        refreshSuccess = refreshSuccess && currentEnvRefreshResult;\n      }\n\n      if (refreshSuccess) {\n        refreshServiceAddressService\n            .schedule(new RefreshAdminServerAddressTask(), NORMAL_REFRESH_INTERVAL, TimeUnit.MILLISECONDS);\n      } else {\n        refreshServiceAddressService\n            .schedule(new RefreshAdminServerAddressTask(), OFFLINE_REFRESH_INTERVAL, TimeUnit.MILLISECONDS);\n      }\n    }\n  }\n\n  private boolean refreshServerAddressCache(Env env) {\n\n    for (int i = 0; i < RETRY_TIMES; i++) {\n\n      try {\n        ServiceDTO[] services = getAdminServerAddress(env);\n        if (services == null || services.length == 0) {\n          continue;\n        }\n        cache.put(env, Arrays.asList(services));\n        return true;\n      } catch (Throwable e) {\n        logger.error(String.format(\"Get admin server address from meta server failed. env: %s, meta server address:%s\",\n                                   env, MetaDomainConsts.getDomain(env)), e);\n        Tracer\n            .logError(String.format(\"Get admin server address from meta server failed. env: %s, meta server address:%s\",\n                                    env, MetaDomainConsts.getDomain(env)), e);\n      }\n    }\n    return false;\n  }\n\n  private ServiceDTO[] getAdminServerAddress(Env env) {\n    String domainName = MetaDomainConsts.getDomain(env);\n    String url = domainName + ADMIN_SERVICE_URL_PATH;\n    return restTemplate.getForObject(url, ServiceDTO[].class);\n  }\n\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/component/ItemsComparator.java",
    "content": "package com.ctrip.framework.apollo.portal.component;\n\nimport com.ctrip.framework.apollo.common.dto.ItemChangeSets;\nimport com.ctrip.framework.apollo.common.dto.ItemDTO;\nimport com.ctrip.framework.apollo.common.utils.BeanUtils;\nimport com.ctrip.framework.apollo.core.utils.StringUtils;\n\nimport org.springframework.stereotype.Component;\nimport org.springframework.util.CollectionUtils;\n\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\n\n@Component\npublic class ItemsComparator {\n\n\n  public ItemChangeSets compareIgnoreBlankAndCommentItem(long baseNamespaceId, List<ItemDTO> baseItems, List<ItemDTO> targetItems){\n    List<ItemDTO> filteredSourceItems = filterBlankAndCommentItem(baseItems);\n    List<ItemDTO> filteredTargetItems = filterBlankAndCommentItem(targetItems);\n\n    Map<String, ItemDTO> sourceItemMap = BeanUtils.mapByKey(\"key\", filteredSourceItems);\n    Map<String, ItemDTO> targetItemMap = BeanUtils.mapByKey(\"key\", filteredTargetItems);\n\n    ItemChangeSets changeSets = new ItemChangeSets();\n\n    for (ItemDTO item: targetItems){\n      String key = item.getKey();\n\n      ItemDTO sourceItem = sourceItemMap.get(key);\n      if (sourceItem == null){//add\n        ItemDTO copiedItem = copyItem(item);\n        copiedItem.setNamespaceId(baseNamespaceId);\n        changeSets.addCreateItem(copiedItem);\n      }else if (!Objects.equals(sourceItem.getValue(), item.getValue())){//update\n        //only value & comment can be update\n        sourceItem.setValue(item.getValue());\n        sourceItem.setComment(item.getComment());\n        changeSets.addUpdateItem(sourceItem);\n      }\n    }\n\n    for (ItemDTO item: baseItems){\n      String key = item.getKey();\n\n      ItemDTO targetItem = targetItemMap.get(key);\n      if(targetItem == null){//delete\n        changeSets.addDeleteItem(item);\n      }\n    }\n\n    return changeSets;\n  }\n\n  private List<ItemDTO> filterBlankAndCommentItem(List<ItemDTO> items){\n\n    List<ItemDTO> result = new LinkedList<>();\n\n    if (CollectionUtils.isEmpty(items)){\n      return result;\n    }\n\n    for (ItemDTO item: items){\n      if (!StringUtils.isEmpty(item.getKey())){\n        result.add(item);\n      }\n    }\n\n    return result;\n  }\n\n  private ItemDTO copyItem(ItemDTO sourceItem){\n    ItemDTO copiedItem = new ItemDTO();\n    copiedItem.setKey(sourceItem.getKey());\n    copiedItem.setValue(sourceItem.getValue());\n    copiedItem.setComment(sourceItem.getComment());\n    return copiedItem;\n\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/component/PermissionValidator.java",
    "content": "package com.ctrip.framework.apollo.portal.component;\n\nimport com.ctrip.framework.apollo.common.entity.AppNamespace;\nimport com.ctrip.framework.apollo.portal.component.config.PortalConfig;\nimport com.ctrip.framework.apollo.portal.constant.PermissionType;\nimport com.ctrip.framework.apollo.portal.service.RolePermissionService;\nimport com.ctrip.framework.apollo.portal.spi.UserInfoHolder;\nimport com.ctrip.framework.apollo.portal.util.RoleUtils;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\n@Component(\"permissionValidator\")\npublic class PermissionValidator {\n\n  @Autowired\n  private UserInfoHolder userInfoHolder;\n  @Autowired\n  private RolePermissionService rolePermissionService;\n  @Autowired\n  private PortalConfig portalConfig;\n\n  public boolean hasModifyNamespacePermission(String appId, String namespaceName) {\n    return rolePermissionService.userHasPermission(userInfoHolder.getUser().getUserId(),\n                                                   PermissionType.MODIFY_NAMESPACE,\n                                                   RoleUtils.buildNamespaceTargetId(appId, namespaceName));\n  }\n\n  public boolean hasReleaseNamespacePermission(String appId, String namespaceName) {\n    return rolePermissionService.userHasPermission(userInfoHolder.getUser().getUserId(),\n                                                   PermissionType.RELEASE_NAMESPACE,\n                                                   RoleUtils.buildNamespaceTargetId(appId, namespaceName));\n  }\n\n  public boolean hasDeleteNamespacePermission(String appId) {\n    return hasAssignRolePermission(appId) || isSuperAdmin();\n  }\n\n  public boolean hasOperateNamespacePermission(String appId, String namespaceName) {\n    return hasModifyNamespacePermission(appId, namespaceName) || hasReleaseNamespacePermission(appId, namespaceName);\n  }\n\n  public boolean hasAssignRolePermission(String appId) {\n    return rolePermissionService.userHasPermission(userInfoHolder.getUser().getUserId(),\n                                                   PermissionType.ASSIGN_ROLE,\n                                                   appId);\n  }\n\n  public boolean hasCreateNamespacePermission(String appId) {\n\n    return rolePermissionService.userHasPermission(userInfoHolder.getUser().getUserId(),\n                                                   PermissionType.CREATE_NAMESPACE,\n                                                   appId);\n  }\n\n  public boolean hasCreateAppNamespacePermission(String appId, AppNamespace appNamespace) {\n\n    boolean isPublicAppNamespace = appNamespace.isPublic();\n\n    if (portalConfig.canAppAdminCreatePrivateNamespace() || isPublicAppNamespace) {\n      return hasCreateNamespacePermission(appId);\n    }\n\n    return isSuperAdmin();\n  }\n\n  public boolean hasCreateClusterPermission(String appId) {\n    return rolePermissionService.userHasPermission(userInfoHolder.getUser().getUserId(),\n                                                   PermissionType.CREATE_CLUSTER,\n                                                   appId);\n  }\n\n  public boolean isAppAdmin(String appId) {\n    return isSuperAdmin() || hasAssignRolePermission(appId);\n  }\n\n  public boolean isSuperAdmin() {\n    return rolePermissionService.isSuperAdmin(userInfoHolder.getUser().getUserId());\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/component/PortalSettings.java",
    "content": "package com.ctrip.framework.apollo.portal.component;\n\n\nimport com.ctrip.framework.apollo.core.MetaDomainConsts;\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.core.utils.ApolloThreadFactory;\nimport com.ctrip.framework.apollo.portal.api.AdminServiceAPI;\nimport com.ctrip.framework.apollo.portal.component.config.PortalConfig;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.actuate.health.Health;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.stereotype.Component;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.TimeUnit;\n\nimport javax.annotation.PostConstruct;\n\n@Component\npublic class PortalSettings {\n\n  private static final Logger logger = LoggerFactory.getLogger(PortalSettings.class);\n  private static final int HEALTH_CHECK_INTERVAL = 10 * 1000;\n\n  @Autowired\n  ApplicationContext applicationContext;\n\n  @Autowired\n  private PortalConfig portalConfig;\n\n  private List<Env> allEnvs = new ArrayList<>();\n\n  //mark env up or down\n  private Map<Env, Boolean> envStatusMark = new ConcurrentHashMap<>();\n\n  @PostConstruct\n  private void postConstruct() {\n\n    allEnvs = portalConfig.portalSupportedEnvs();\n\n    for (Env env : allEnvs) {\n      envStatusMark.put(env, true);\n    }\n\n    ScheduledExecutorService\n        healthCheckService =\n        Executors.newScheduledThreadPool(1, ApolloThreadFactory.create(\"EnvHealthChecker\", true));\n\n    healthCheckService\n        .scheduleWithFixedDelay(new HealthCheckTask(applicationContext), 1000, HEALTH_CHECK_INTERVAL,\n                                TimeUnit.MILLISECONDS);\n\n  }\n\n  public List<Env> getAllEnvs() {\n    return allEnvs;\n  }\n\n  public List<Env> getActiveEnvs() {\n    List<Env> activeEnvs = new LinkedList<>();\n    for (Env env : allEnvs) {\n      if (envStatusMark.get(env)) {\n        activeEnvs.add(env);\n      }\n    }\n    return activeEnvs;\n  }\n\n  public boolean isEnvActive(Env env) {\n    Boolean mark = envStatusMark.get(env);\n    return mark == null ? false : mark;\n  }\n\n  private class HealthCheckTask implements Runnable {\n\n    private static final int ENV_DOWN_THRESHOLD = 2;\n\n    private Map<Env, Integer> healthCheckFailedCounter = new HashMap<>();\n\n    private AdminServiceAPI.HealthAPI healthAPI;\n\n    public HealthCheckTask(ApplicationContext context) {\n      healthAPI = context.getBean(AdminServiceAPI.HealthAPI.class);\n      for (Env env : allEnvs) {\n        healthCheckFailedCounter.put(env, 0);\n      }\n    }\n\n    public void run() {\n\n      for (Env env : allEnvs) {\n        try {\n          if (isUp(env)) {\n            //revive\n            if (!envStatusMark.get(env)) {\n              envStatusMark.put(env, true);\n              healthCheckFailedCounter.put(env, 0);\n              logger.info(\"Env revived because env health check success. env: {}\", env);\n            }\n          } else {\n            logger.error(\"Env health check failed, maybe because of admin server down. env: {}, meta server address: {}\", env,\n                        MetaDomainConsts.getDomain(env));\n            handleEnvDown(env);\n          }\n\n        } catch (Exception e) {\n          logger.error(\"Env health check failed, maybe because of meta server down \"\n                       + \"or configure wrong meta server address. env: {}, meta server address: {}\", env,\n                       MetaDomainConsts.getDomain(env), e);\n          handleEnvDown(env);\n        }\n      }\n\n    }\n\n    private boolean isUp(Env env) {\n      Health health = healthAPI.health(env);\n      return \"UP\".equals(health.getStatus().getCode());\n    }\n\n    private void handleEnvDown(Env env) {\n      int failedTimes = healthCheckFailedCounter.get(env);\n      healthCheckFailedCounter.put(env, ++failedTimes);\n\n      if (!envStatusMark.get(env)) {\n        logger.error(\"Env is down. env: {}, failed times: {}, meta server address: {}\", env, failedTimes,\n                     MetaDomainConsts.getDomain(env));\n      } else {\n        if (failedTimes >= ENV_DOWN_THRESHOLD) {\n          envStatusMark.put(env, false);\n          logger.error(\"Env is down because health check failed for {} times, \"\n                       + \"which equals to down threshold. env: {}, meta server address: {}\", ENV_DOWN_THRESHOLD, env,\n                       MetaDomainConsts.getDomain(env));\n        } else {\n          logger.error(\n              \"Env health check failed for {} times which less than down threshold. down threshold:{}, env: {}, meta server address: {}\",\n              failedTimes, ENV_DOWN_THRESHOLD, env, MetaDomainConsts.getDomain(env));\n        }\n      }\n\n    }\n\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/component/RestTemplateFactory.java",
    "content": "package com.ctrip.framework.apollo.portal.component;\n\nimport com.ctrip.framework.apollo.portal.component.config.PortalConfig;\n\nimport org.apache.http.impl.client.CloseableHttpClient;\nimport org.apache.http.impl.client.HttpClientBuilder;\nimport org.springframework.beans.factory.FactoryBean;\nimport org.springframework.beans.factory.InitializingBean;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.autoconfigure.web.HttpMessageConverters;\nimport org.springframework.http.client.HttpComponentsClientHttpRequestFactory;\nimport org.springframework.stereotype.Component;\nimport org.springframework.web.client.RestTemplate;\n\nimport java.io.UnsupportedEncodingException;\n\n@Component\npublic class RestTemplateFactory implements FactoryBean<RestTemplate>, InitializingBean {\n\n  @Autowired\n  private HttpMessageConverters httpMessageConverters;\n  @Autowired\n  private PortalConfig portalConfig;\n\n  private RestTemplate restTemplate;\n\n  public RestTemplate getObject() {\n    return restTemplate;\n  }\n\n  public Class<RestTemplate> getObjectType() {\n    return RestTemplate.class;\n  }\n\n  public boolean isSingleton() {\n    return true;\n  }\n\n  public void afterPropertiesSet() throws UnsupportedEncodingException {\n    CloseableHttpClient httpClient = HttpClientBuilder.create().build();\n\n    restTemplate = new RestTemplate(httpMessageConverters.getConverters());\n    HttpComponentsClientHttpRequestFactory requestFactory =\n        new HttpComponentsClientHttpRequestFactory(httpClient);\n    requestFactory.setConnectTimeout(portalConfig.connectTimeout());\n    requestFactory.setReadTimeout(portalConfig.readTimeout());\n\n    restTemplate.setRequestFactory(requestFactory);\n  }\n\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/component/RetryableRestTemplate.java",
    "content": "package com.ctrip.framework.apollo.portal.component;\n\nimport com.ctrip.framework.apollo.common.exception.ServiceException;\nimport com.ctrip.framework.apollo.core.MetaDomainConsts;\nimport com.ctrip.framework.apollo.core.dto.ServiceDTO;\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.portal.constant.TracerEventType;\nimport com.ctrip.framework.apollo.tracer.Tracer;\nimport com.ctrip.framework.apollo.tracer.spi.Transaction;\n\nimport org.apache.http.conn.ConnectTimeoutException;\nimport org.apache.http.conn.HttpHostConnectException;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.core.ParameterizedTypeReference;\nimport org.springframework.http.HttpMethod;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.stereotype.Component;\nimport org.springframework.util.CollectionUtils;\nimport org.springframework.web.client.RestClientException;\nimport org.springframework.web.client.RestTemplate;\nimport org.springframework.web.util.DefaultUriTemplateHandler;\nimport org.springframework.web.util.UriTemplateHandler;\n\nimport java.net.SocketTimeoutException;\nimport java.util.List;\n\nimport javax.annotation.PostConstruct;\n\n/**\n * 封装RestTemplate. admin server集群在某些机器宕机或者超时的情况下轮询重试\n */\n@Component\npublic class RetryableRestTemplate {\n\n  private Logger logger = LoggerFactory.getLogger(RetryableRestTemplate.class);\n\n  private UriTemplateHandler uriTemplateHandler = new DefaultUriTemplateHandler();\n\n  private RestTemplate restTemplate;\n\n  @Autowired\n  private RestTemplateFactory restTemplateFactory;\n  @Autowired\n  private AdminServiceAddressLocator adminServiceAddressLocator;\n\n\n  @PostConstruct\n  private void postConstruct() {\n    restTemplate = restTemplateFactory.getObject();\n  }\n\n  public <T> T get(Env env, String path, Class<T> responseType, Object... urlVariables)\n      throws RestClientException {\n    return execute(HttpMethod.GET, env, path, null, responseType, urlVariables);\n  }\n\n  public <T> ResponseEntity<T> get(Env env, String path, ParameterizedTypeReference<T> reference,\n                                   Object... uriVariables)\n      throws RestClientException {\n\n    return exchangeGet(env, path, reference, uriVariables);\n  }\n\n  public <T> T post(Env env, String path, Object request, Class<T> responseType, Object... uriVariables)\n      throws RestClientException {\n    return execute(HttpMethod.POST, env, path, request, responseType, uriVariables);\n  }\n\n  public void put(Env env, String path, Object request, Object... urlVariables) throws RestClientException {\n    execute(HttpMethod.PUT, env, path, request, null, urlVariables);\n  }\n\n  public void delete(Env env, String path, Object... urlVariables) throws RestClientException {\n    execute(HttpMethod.DELETE, env, path, null, null, urlVariables);\n  }\n\n  private <T> T execute(HttpMethod method, Env env, String path, Object request, Class<T> responseType,\n                        Object... uriVariables) {\n\n    if (path.startsWith(\"/\")) {\n      path = path.substring(1, path.length());\n    }\n\n    String uri = uriTemplateHandler.expand(path, uriVariables).getPath();\n    Transaction ct = Tracer.newTransaction(\"AdminAPI\", uri);\n    ct.addData(\"Env\", env);\n\n    List<ServiceDTO> services = getAdminServices(env, ct);\n\n    for (ServiceDTO serviceDTO : services) {\n      try {\n\n        T result = doExecute(method, serviceDTO, path, request, responseType, uriVariables);\n\n        ct.setStatus(Transaction.SUCCESS);\n        ct.complete();\n        return result;\n      } catch (Throwable t) {\n        logger.error(\"Http request failed, uri: {}, method: {}\", uri, method, t);\n        Tracer.logError(t);\n        if (canRetry(t, method)) {\n          Tracer.logEvent(TracerEventType.API_RETRY, uri);\n        } else {//biz exception rethrow\n          ct.setStatus(t);\n          ct.complete();\n          throw t;\n        }\n      }\n    }\n\n    //all admin server down\n    ServiceException e =\n        new ServiceException(String.format(\"Admin servers are unresponsive. meta server address: %s, admin servers: %s\",\n                                           MetaDomainConsts.getDomain(env), services));\n    ct.setStatus(e);\n    ct.complete();\n    throw e;\n  }\n\n  private <T> ResponseEntity<T> exchangeGet(Env env, String path, ParameterizedTypeReference<T> reference,\n                                            Object... uriVariables) {\n    if (path.startsWith(\"/\")) {\n      path = path.substring(1, path.length());\n    }\n\n    String uri = uriTemplateHandler.expand(path, uriVariables).getPath();\n    Transaction ct = Tracer.newTransaction(\"AdminAPI\", uri);\n    ct.addData(\"Env\", env);\n\n    List<ServiceDTO> services = getAdminServices(env, ct);\n\n    for (ServiceDTO serviceDTO : services) {\n      try {\n\n        ResponseEntity<T> result =\n            restTemplate.exchange(parseHost(serviceDTO) + path, HttpMethod.GET, null, reference, uriVariables);\n\n        ct.setStatus(Transaction.SUCCESS);\n        ct.complete();\n        return result;\n      } catch (Throwable t) {\n        logger.error(\"Http request failed, uri: {}, method: {}\", uri, HttpMethod.GET, t);\n        Tracer.logError(t);\n        if (canRetry(t, HttpMethod.GET)) {\n          Tracer.logEvent(TracerEventType.API_RETRY, uri);\n        } else {// biz exception rethrow\n          ct.setStatus(t);\n          ct.complete();\n          throw t;\n        }\n\n      }\n    }\n\n    //all admin server down\n    ServiceException e =\n        new ServiceException(String.format(\"Admin servers are unresponsive. meta server address: %s, admin servers: %s\",\n                                           MetaDomainConsts.getDomain(env), services));\n    ct.setStatus(e);\n    ct.complete();\n    throw e;\n\n  }\n\n  private List<ServiceDTO> getAdminServices(Env env, Transaction ct) {\n\n    List<ServiceDTO> services = adminServiceAddressLocator.getServiceList(env);\n\n    if (CollectionUtils.isEmpty(services)) {\n      ServiceException e = new ServiceException(String.format(\"No available admin server.\"\n                                                              + \" Maybe because of meta server down or all admin server down. \"\n                                                              + \"Meta server address: %s\",\n                                                              MetaDomainConsts.getDomain(env)));\n      ct.setStatus(e);\n      ct.complete();\n      throw e;\n    }\n\n    return services;\n  }\n\n  private <T> T doExecute(HttpMethod method, ServiceDTO service, String path, Object request,\n                          Class<T> responseType,\n                          Object... uriVariables) {\n    T result = null;\n    switch (method) {\n      case GET:\n        result = restTemplate.getForObject(parseHost(service) + path, responseType, uriVariables);\n        break;\n      case POST:\n        result =\n            restTemplate.postForEntity(parseHost(service) + path, request, responseType, uriVariables).getBody();\n        break;\n      case PUT:\n        restTemplate.put(parseHost(service) + path, request, uriVariables);\n        break;\n      case DELETE:\n        restTemplate.delete(parseHost(service) + path, uriVariables);\n        break;\n      default:\n        throw new UnsupportedOperationException(String.format(\"unsupported http method(method=%s)\", method));\n    }\n    return result;\n  }\n\n  private String parseHost(ServiceDTO serviceAddress) {\n    return serviceAddress.getHomepageUrl() + \"/\";\n  }\n\n  //post,delete,put请求在admin server处理超时情况下不重试\n  private boolean canRetry(Throwable e, HttpMethod method) {\n    Throwable nestedException = e.getCause();\n    if (method == HttpMethod.GET) {\n      return nestedException instanceof SocketTimeoutException\n             || nestedException instanceof HttpHostConnectException\n             || nestedException instanceof ConnectTimeoutException;\n    } else {\n      return nestedException instanceof HttpHostConnectException\n             || nestedException instanceof ConnectTimeoutException;\n    }\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/component/config/PortalConfig.java",
    "content": "package com.ctrip.framework.apollo.portal.component.config;\n\n\nimport com.google.common.base.Strings;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Sets;\nimport com.google.gson.Gson;\nimport com.google.gson.reflect.TypeToken;\n\nimport com.ctrip.framework.apollo.common.config.RefreshableConfig;\nimport com.ctrip.framework.apollo.common.config.RefreshablePropertySource;\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.portal.entity.vo.Organization;\nimport com.ctrip.framework.apollo.portal.service.PortalDBPropertySource;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport java.lang.reflect.Type;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.Set;\n\n@Component\npublic class PortalConfig extends RefreshableConfig {\n\n  private Gson gson = new Gson();\n  private static final Type ORGANIZATION = new TypeToken<List<Organization>>() {\n  }.getType();\n\n  @Autowired\n  private PortalDBPropertySource portalDBPropertySource;\n\n  @Override\n  public List<RefreshablePropertySource> getRefreshablePropertySources() {\n    return Collections.singletonList(portalDBPropertySource);\n  }\n\n  /***\n   * Level: important\n   **/\n  public List<Env> portalSupportedEnvs() {\n    String[] configurations = getArrayProperty(\"apollo.portal.envs\", new String[]{\"FAT\", \"UAT\", \"PRO\"});\n    List<Env> envs = Lists.newLinkedList();\n\n    for (String env : configurations) {\n      envs.add(Env.fromString(env));\n    }\n\n    return envs;\n  }\n\n  public List<String> superAdmins() {\n    String superAdminConfig = getValue(\"superAdmin\", \"\");\n    if (Strings.isNullOrEmpty(superAdminConfig)) {\n      return Collections.emptyList();\n    }\n    return splitter.splitToList(superAdminConfig);\n  }\n\n  public Set<Env> emailSupportedEnvs() {\n    String[] configurations = getArrayProperty(\"email.supported.envs\", null);\n\n    Set<Env> result = Sets.newHashSet();\n    if (configurations == null || configurations.length == 0) {\n      return result;\n    }\n\n    for (String env : configurations) {\n      result.add(Env.fromString(env));\n    }\n\n    return result;\n  }\n\n  /***\n   * Level: normal\n   **/\n  public int connectTimeout() {\n    return getIntProperty(\"api.connectTimeout\", 3000);\n  }\n\n  public int readTimeout() {\n    return getIntProperty(\"api.readTimeout\", 10000);\n  }\n\n  public List<Organization> organizations() {\n\n    String organizations = getValue(\"organizations\");\n    return organizations == null ? Collections.emptyList() : gson.fromJson(organizations, ORGANIZATION);\n  }\n\n  public String portalAddress() {\n    return getValue(\"apollo.portal.address\");\n  }\n\n  public boolean isEmergencyPublishAllowed(Env env) {\n    String targetEnv = env.name();\n\n    String[] emergencyPublishSupportedEnvs = getArrayProperty(\"emergencyPublish.supported.envs\", new String[0]);\n\n    for (String supportedEnv : emergencyPublishSupportedEnvs) {\n      if (Objects.equals(targetEnv, supportedEnv.toUpperCase().trim())) {\n        return true;\n      }\n    }\n\n    return false;\n  }\n\n  /***\n   * Level: low\n   **/\n  public Set<Env> publishTipsSupportedEnvs() {\n    String[] configurations = getArrayProperty(\"namespace.publish.tips.supported.envs\", null);\n\n    Set<Env> result = Sets.newHashSet();\n    if (configurations == null || configurations.length == 0) {\n      return result;\n    }\n\n    for (String env : configurations) {\n      result.add(Env.fromString(env));\n    }\n\n    return result;\n  }\n\n  public String consumerTokenSalt() {\n    return getValue(\"consumer.token.salt\", \"apollo-portal\");\n  }\n\n  public String emailSender() {\n    return getValue(\"email.sender\");\n  }\n\n  public String emailTemplateFramework() {\n    return getValue(\"email.template.framework\", \"\");\n  }\n\n  public String emailReleaseDiffModuleTemplate() {\n    return getValue(\"email.template.release.module.diff\", \"\");\n  }\n\n  public String emailRollbackDiffModuleTemplate() {\n    return getValue(\"email.template.rollback.module.diff\", \"\");\n  }\n\n  public String emailGrayRulesModuleTemplate() {\n    return getValue(\"email.template.release.module.rules\", \"\");\n  }\n\n  public String wikiAddress() {\n    return getValue(\"wiki.address\", \"https://github.com/ctripcorp/apollo/wiki\");\n  }\n\n  public boolean canAppAdminCreatePrivateNamespace() {\n    return getBooleanProperty(\"admin.createPrivateNamespace.switch\", true);\n  }\n\n  /***\n   * The following configurations are used in ctrip profile\n   **/\n\n  public int appId() {\n    return getIntProperty(\"ctrip.appid\", 0);\n  }\n\n  //send code & template id. apply from ewatch\n  public String sendCode() {\n    return getValue(\"ctrip.email.send.code\");\n  }\n\n  public int templateId() {\n    return getIntProperty(\"ctrip.email.template.id\", 0);\n  }\n\n  //email retention time in email server queue.TimeUnit: hour\n  public int survivalDuration() {\n    return getIntProperty(\"ctrip.email.survival.duration\", 5);\n  }\n\n  public boolean isSendEmailAsync() {\n    return getBooleanProperty(\"email.send.async\", true);\n  }\n\n  public String portalServerName() {\n    return getValue(\"serverName\");\n  }\n\n  public String casServerLoginUrl() {\n    return getValue(\"casServerLoginUrl\");\n  }\n\n  public String casServerUrlPrefix() {\n    return getValue(\"casServerUrlPrefix\");\n  }\n\n  public String credisServiceUrl() {\n    return getValue(\"credisServiceUrl\");\n  }\n\n  public String userServiceUrl() {\n    return getValue(\"userService.url\");\n  }\n\n  public String userServiceAccessToken() {\n    return getValue(\"userService.accessToken\");\n  }\n\n  public String soaServerAddress() {\n    return getValue(\"soa.server.address\");\n  }\n\n  public String cloggingUrl() {\n    return getValue(\"clogging.server.url\");\n  }\n\n  public String cloggingPort() {\n    return getValue(\"clogging.server.port\");\n  }\n\n  public String hermesServerAddress() {\n    return getValue(\"hermes.server.address\");\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/component/emailbuilder/ConfigPublishEmailBuilder.java",
    "content": "package com.ctrip.framework.apollo.portal.component.emailbuilder;\n\n\nimport com.google.common.collect.Lists;\n\nimport com.ctrip.framework.apollo.common.constants.ReleaseOperation;\nimport com.ctrip.framework.apollo.common.constants.ReleaseOperationContext;\nimport com.ctrip.framework.apollo.common.dto.ReleaseDTO;\nimport com.ctrip.framework.apollo.common.entity.AppNamespace;\nimport com.ctrip.framework.apollo.core.enums.ConfigFileFormat;\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.portal.component.config.PortalConfig;\nimport com.ctrip.framework.apollo.portal.constant.RoleType;\nimport com.ctrip.framework.apollo.portal.entity.bo.Email;\nimport com.ctrip.framework.apollo.portal.entity.bo.ReleaseHistoryBO;\nimport com.ctrip.framework.apollo.portal.entity.bo.UserInfo;\nimport com.ctrip.framework.apollo.portal.entity.vo.Change;\nimport com.ctrip.framework.apollo.portal.entity.vo.ReleaseCompareResult;\nimport com.ctrip.framework.apollo.portal.service.AppNamespaceService;\nimport com.ctrip.framework.apollo.portal.service.ReleaseService;\nimport com.ctrip.framework.apollo.portal.service.RolePermissionService;\nimport com.ctrip.framework.apollo.portal.spi.UserService;\nimport com.ctrip.framework.apollo.portal.util.RoleUtils;\n\nimport org.apache.commons.lang.time.FastDateFormat;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.util.CollectionUtils;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.regex.Matcher;\n\n\npublic abstract class ConfigPublishEmailBuilder {\n\n  private static final String EMERGENCY_PUBLISH_TAG = \"<span style='color:red'>(紧急发布)</span>\";\n\n  //email content common field placeholder\n  private static final String EMAIL_CONTENT_FIELD_APPID = \"#\\\\{appId\\\\}\";\n  private static final String EMAIL_CONTENT_FIELD_ENV = \"#\\\\{env}\";\n  private static final String EMAIL_CONTENT_FIELD_CLUSTER = \"#\\\\{clusterName}\";\n  private static final String EMAIL_CONTENT_FIELD_NAMESPACE = \"#\\\\{namespaceName}\";\n  private static final String EMAIL_CONTENT_FIELD_OPERATOR = \"#\\\\{operator}\";\n  private static final String EMAIL_CONTENT_FIELD_RELEASE_TIME = \"#\\\\{releaseTime}\";\n  private static final String EMAIL_CONTENT_FIELD_RELEASE_ID = \"#\\\\{releaseId}\";\n  private static final String EMAIL_CONTENT_FIELD_RELEASE_HISTORY_ID = \"#\\\\{releaseHistoryId}\";\n  private static final String EMAIL_CONTENT_FIELD_RELEASE_TITLE = \"#\\\\{releaseTitle}\";\n  private static final String EMAIL_CONTENT_FIELD_RELEASE_COMMENT = \"#\\\\{releaseComment}\";\n  private static final String EMAIL_CONTENT_FIELD_APOLLO_SERVER_ADDRESS = \"#\\\\{apollo.portal.address}\";\n  private static final String EMAIL_CONTENT_FIELD_DIFF_CONTENT = \"#\\\\{diffContent}\";\n  private static final String EMAIL_CONTENT_FIELD_EMERGENCY_PUBLISH = \"#\\\\{emergencyPublish}\";\n\n  private static final String EMAIL_CONTENT_DIFF_MODULE = \"#\\\\{diffModule}\";\n  protected static final String EMAIL_CONTENT_GRAY_RULES_MODULE = \"#\\\\{rulesModule}\";\n\n  //email content special field placeholder\n  protected static final String EMAIL_CONTENT_GRAY_RULES_CONTENT = \"#\\\\{rulesContent}\";\n\n  //set config's value max length to protect email.\n  protected static final int VALUE_MAX_LENGTH = 100;\n\n  protected FastDateFormat dateFormat = FastDateFormat.getInstance(\"yyyy-MM-dd HH:mm:ss\");\n\n\n  @Autowired\n  private RolePermissionService rolePermissionService;\n  @Autowired\n  private ReleaseService releaseService;\n  @Autowired\n  private AppNamespaceService appNamespaceService;\n  @Autowired\n  private UserService userService;\n  @Autowired\n  protected PortalConfig portalConfig;\n\n  /**\n   * email subject\n   */\n  protected abstract String subject();\n\n  /**\n   * email body content\n   */\n  protected abstract String emailContent(Env env, ReleaseHistoryBO releaseHistory);\n\n  /**\n   * email body template framework\n   */\n  protected abstract String getTemplateFramework();\n\n  /**\n   * email body diff module template\n   */\n  protected abstract String getDiffModuleTemplate();\n\n\n  public Email build(Env env, ReleaseHistoryBO releaseHistory) {\n\n    Email email = new Email();\n\n    email.setSubject(subject());\n    email.setSenderEmailAddress(portalConfig.emailSender());\n    email.setRecipients(recipients(releaseHistory.getAppId(), releaseHistory.getNamespaceName()));\n\n    String emailBody = emailContent(env, releaseHistory);\n    //clear not used module\n    emailBody = emailBody.replaceAll(EMAIL_CONTENT_DIFF_MODULE, \"\");\n    emailBody = emailBody.replaceAll(EMAIL_CONTENT_GRAY_RULES_MODULE, \"\");\n    email.setBody(emailBody);\n\n    return email;\n  }\n\n  protected String renderEmailCommonContent(Env env, ReleaseHistoryBO releaseHistory) {\n    String template = getTemplateFramework();\n    String renderResult = renderReleaseBasicInfo(template, env, releaseHistory);\n    renderResult = renderDiffModule(renderResult, env, releaseHistory);\n    return renderResult;\n  }\n\n  private String renderReleaseBasicInfo(String template, Env env, ReleaseHistoryBO releaseHistory) {\n    String renderResult = template;\n\n    Map<String, Object> operationContext = releaseHistory.getOperationContext();\n    boolean isEmergencyPublish = operationContext.containsKey(ReleaseOperationContext.IS_EMERGENCY_PUBLISH) &&\n                                 (boolean) operationContext.get(ReleaseOperationContext.IS_EMERGENCY_PUBLISH);\n    if (isEmergencyPublish) {\n      renderResult = renderResult.replaceAll(EMAIL_CONTENT_FIELD_EMERGENCY_PUBLISH, Matcher.quoteReplacement(EMERGENCY_PUBLISH_TAG));\n    } else {\n      renderResult = renderResult.replaceAll(EMAIL_CONTENT_FIELD_EMERGENCY_PUBLISH, \"\");\n    }\n\n    renderResult = renderResult.replaceAll(EMAIL_CONTENT_FIELD_APPID, Matcher.quoteReplacement(releaseHistory.getAppId()));\n    renderResult = renderResult.replaceAll(EMAIL_CONTENT_FIELD_ENV, Matcher.quoteReplacement(env.toString()));\n    renderResult = renderResult.replaceAll(EMAIL_CONTENT_FIELD_CLUSTER, Matcher.quoteReplacement(releaseHistory.getClusterName()));\n    renderResult = renderResult.replaceAll(EMAIL_CONTENT_FIELD_NAMESPACE, Matcher.quoteReplacement(releaseHistory.getNamespaceName()));\n    renderResult = renderResult.replaceAll(EMAIL_CONTENT_FIELD_OPERATOR, Matcher.quoteReplacement(releaseHistory.getOperator()));\n    renderResult = renderResult.replaceAll(EMAIL_CONTENT_FIELD_RELEASE_TITLE, Matcher.quoteReplacement(releaseHistory.getReleaseTitle()));\n    renderResult =\n            renderResult.replaceAll(EMAIL_CONTENT_FIELD_RELEASE_ID, String.valueOf(releaseHistory.getReleaseId()));\n    renderResult =\n            renderResult.replaceAll(EMAIL_CONTENT_FIELD_RELEASE_HISTORY_ID, String.valueOf(releaseHistory.getId()));\n    renderResult = renderResult.replaceAll(EMAIL_CONTENT_FIELD_RELEASE_COMMENT, Matcher.quoteReplacement(releaseHistory.getReleaseComment()));\n    renderResult = renderResult.replaceAll(EMAIL_CONTENT_FIELD_APOLLO_SERVER_ADDRESS, getApolloPortalAddress());\n    return renderResult\n            .replaceAll(EMAIL_CONTENT_FIELD_RELEASE_TIME, dateFormat.format(releaseHistory.getReleaseTime()));\n  }\n\n  private String renderDiffModule(String bodyTemplate, Env env, ReleaseHistoryBO releaseHistory) {\n    String appId = releaseHistory.getAppId();\n    String namespaceName = releaseHistory.getNamespaceName();\n\n    AppNamespace appNamespace = appNamespaceService.findByAppIdAndName(appId, namespaceName);\n    if (appNamespace == null) {\n      appNamespace = appNamespaceService.findPublicAppNamespace(namespaceName);\n    }\n\n    //don't show diff content if namespace's format is file\n    if (appNamespace == null ||\n            !appNamespace.getFormat().equals(ConfigFileFormat.Properties.getValue())) {\n\n      return bodyTemplate.replaceAll(EMAIL_CONTENT_DIFF_MODULE, \"<br><h4>变更内容请点击链接到Apollo上查看</h4>\");\n    }\n\n    ReleaseCompareResult result = getReleaseCompareResult(env, releaseHistory);\n\n    if (!result.hasContent()) {\n      return bodyTemplate.replaceAll(EMAIL_CONTENT_DIFF_MODULE, \"<br><h4>无配置变更</h4>\");\n    }\n\n    List<Change> changes = result.getChanges();\n    StringBuilder changesHtmlBuilder = new StringBuilder();\n    for (Change change : changes) {\n      String key = change.getEntity().getFirstEntity().getKey();\n      String oldValue = change.getEntity().getFirstEntity().getValue();\n      String newValue = change.getEntity().getSecondEntity().getValue();\n      newValue = newValue == null ? \"\" : newValue;\n\n      changesHtmlBuilder.append(\"<tr>\");\n      changesHtmlBuilder.append(\"<td width=\\\"10%\\\">\").append(change.getType().toString()).append(\"</td>\");\n      changesHtmlBuilder.append(\"<td width=\\\"20%\\\">\").append(cutOffString(key)).append(\"</td>\");\n      changesHtmlBuilder.append(\"<td width=\\\"35%\\\">\").append(cutOffString(oldValue)).append(\"</td>\");\n      changesHtmlBuilder.append(\"<td width=\\\"35%\\\">\").append(cutOffString(newValue)).append(\"</td>\");\n\n      changesHtmlBuilder.append(\"</tr>\");\n    }\n\n    String diffContent = Matcher.quoteReplacement(changesHtmlBuilder.toString());\n    String diffModuleTemplate = getDiffModuleTemplate();\n    String diffModuleRenderResult = diffModuleTemplate.replaceAll(EMAIL_CONTENT_FIELD_DIFF_CONTENT, diffContent);\n    return bodyTemplate.replaceAll(EMAIL_CONTENT_DIFF_MODULE, diffModuleRenderResult);\n  }\n\n  private ReleaseCompareResult getReleaseCompareResult(Env env, ReleaseHistoryBO releaseHistory) {\n    if (releaseHistory.getOperation() == ReleaseOperation.GRAY_RELEASE\n            && releaseHistory.getPreviousReleaseId() == 0) {\n      ReleaseDTO masterLatestActiveRelease = releaseService.loadLatestRelease(\n              releaseHistory.getAppId(), env, releaseHistory.getClusterName(), releaseHistory.getNamespaceName());\n      ReleaseDTO branchLatestActiveRelease = releaseService.findReleaseById(env, releaseHistory.getReleaseId());\n\n      return releaseService.compare(masterLatestActiveRelease, branchLatestActiveRelease);\n    }\n\n    return releaseService.compare(env, releaseHistory.getPreviousReleaseId(), releaseHistory.getReleaseId());\n  }\n\n  private List<String> recipients(String appId, String namespaceName) {\n    Set<UserInfo> modifyRoleUsers =\n            rolePermissionService\n                    .queryUsersWithRole(RoleUtils.buildNamespaceRoleName(appId, namespaceName, RoleType.MODIFY_NAMESPACE));\n    Set<UserInfo> releaseRoleUsers =\n            rolePermissionService\n                    .queryUsersWithRole(RoleUtils.buildNamespaceRoleName(appId, namespaceName, RoleType.RELEASE_NAMESPACE));\n    Set<UserInfo> owners = rolePermissionService.queryUsersWithRole(RoleUtils.buildAppMasterRoleName(appId));\n\n    Set<String> userIds = new HashSet<>(modifyRoleUsers.size() + releaseRoleUsers.size() + owners.size());\n\n    for (UserInfo userInfo : modifyRoleUsers) {\n      userIds.add(userInfo.getUserId());\n    }\n\n    for (UserInfo userInfo : releaseRoleUsers) {\n      userIds.add(userInfo.getUserId());\n    }\n\n    for (UserInfo userInfo : owners) {\n      userIds.add(userInfo.getUserId());\n    }\n\n    List<UserInfo> userInfos = userService.findByUserIds(Lists.newArrayList(userIds));\n\n    if (CollectionUtils.isEmpty(userInfos)) {\n      return Collections.emptyList();\n    }\n\n    List<String> recipients = new ArrayList<>(userInfos.size());\n    for (UserInfo userInfo : userInfos) {\n      recipients.add(userInfo.getEmail());\n    }\n\n    return recipients;\n  }\n\n  protected String getApolloPortalAddress() {\n    return portalConfig.portalAddress();\n  }\n\n  private String cutOffString(String source) {\n    if (source.length() > VALUE_MAX_LENGTH) {\n      return source.substring(0, VALUE_MAX_LENGTH) + \"...\";\n    }\n    return source;\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/component/emailbuilder/GrayPublishEmailBuilder.java",
    "content": "package com.ctrip.framework.apollo.portal.component.emailbuilder;\n\nimport com.google.common.base.Joiner;\nimport com.google.gson.Gson;\n\nimport com.ctrip.framework.apollo.common.constants.GsonType;\nimport com.ctrip.framework.apollo.common.dto.GrayReleaseRuleItemDTO;\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.portal.entity.bo.ReleaseHistoryBO;\n\nimport org.springframework.stereotype.Component;\nimport org.springframework.util.CollectionUtils;\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.regex.Matcher;\n\n@Component\npublic class GrayPublishEmailBuilder extends ConfigPublishEmailBuilder {\n\n  private static final String EMAIL_SUBJECT = \"[Apollo] 灰度发布\";\n\n  private Gson gson = new Gson();\n  private Joiner IP_JOINER = Joiner.on(\", \");\n\n  @Override\n  protected String subject() {\n    return EMAIL_SUBJECT;\n  }\n\n  @Override\n  public String emailContent(Env env, ReleaseHistoryBO releaseHistory) {\n    String result = renderEmailCommonContent(env, releaseHistory);\n    return renderGrayReleaseRuleContent(result, releaseHistory);\n  }\n\n  @Override\n  protected String getTemplateFramework() {\n    return portalConfig.emailTemplateFramework();\n  }\n\n  @Override\n  protected String getDiffModuleTemplate() {\n    return portalConfig.emailReleaseDiffModuleTemplate();\n  }\n\n  private String renderGrayReleaseRuleContent(String bodyTemplate, ReleaseHistoryBO releaseHistory) {\n\n    Map<String, Object> context = releaseHistory.getOperationContext();\n    Object rules = context.get(\"rules\");\n    List<GrayReleaseRuleItemDTO>\n            ruleItems = rules == null ?\n            null : gson.fromJson(rules.toString(), GsonType.RULE_ITEMS);\n\n\n    if (CollectionUtils.isEmpty(ruleItems)) {\n      return bodyTemplate.replaceAll(EMAIL_CONTENT_GRAY_RULES_MODULE, \"<br><h4>无灰度规则</h4>\");\n    } else {\n      StringBuilder rulesHtmlBuilder = new StringBuilder();\n      for (GrayReleaseRuleItemDTO ruleItem : ruleItems) {\n        String clientAppId = ruleItem.getClientAppId();\n        Set<String> ips = ruleItem.getClientIpList();\n\n        rulesHtmlBuilder.append(\"<b>AppId:&nbsp;</b>\")\n                .append(clientAppId)\n                .append(\"&nbsp;&nbsp; <b>IP:&nbsp;</b>\");\n\n        IP_JOINER.appendTo(rulesHtmlBuilder, ips);\n      }\n      String grayRulesModuleContent = portalConfig.emailGrayRulesModuleTemplate().replaceAll(EMAIL_CONTENT_GRAY_RULES_CONTENT,\n              Matcher.quoteReplacement(rulesHtmlBuilder.toString()));\n\n      return bodyTemplate.replaceAll(EMAIL_CONTENT_GRAY_RULES_MODULE, Matcher.quoteReplacement(grayRulesModuleContent));\n    }\n\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/component/emailbuilder/MergeEmailBuilder.java",
    "content": "package com.ctrip.framework.apollo.portal.component.emailbuilder;\n\n\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.portal.entity.bo.ReleaseHistoryBO;\n\nimport org.springframework.stereotype.Component;\n\n\n@Component\npublic class MergeEmailBuilder extends ConfigPublishEmailBuilder {\n\n  private static final String EMAIL_SUBJECT = \"[Apollo] 全量发布\";\n\n\n  @Override\n  protected String subject() {\n    return EMAIL_SUBJECT;\n  }\n\n  @Override\n  protected String emailContent(Env env, ReleaseHistoryBO releaseHistory) {\n    return renderEmailCommonContent(env, releaseHistory);\n  }\n\n  @Override\n  protected String getTemplateFramework() {\n    return portalConfig.emailTemplateFramework();\n  }\n\n  @Override\n  protected String getDiffModuleTemplate() {\n    return portalConfig.emailReleaseDiffModuleTemplate();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/component/emailbuilder/NormalPublishEmailBuilder.java",
    "content": "package com.ctrip.framework.apollo.portal.component.emailbuilder;\n\n\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.portal.entity.bo.ReleaseHistoryBO;\n\nimport org.springframework.stereotype.Component;\n\n\n@Component\npublic class NormalPublishEmailBuilder extends ConfigPublishEmailBuilder {\n\n  private static final String EMAIL_SUBJECT = \"[Apollo] 配置发布\";\n\n\n  @Override\n  protected String subject() {\n    return EMAIL_SUBJECT;\n  }\n\n  @Override\n  protected String emailContent(Env env, ReleaseHistoryBO releaseHistory) {\n    return renderEmailCommonContent(env, releaseHistory);\n  }\n\n  @Override\n  protected String getTemplateFramework() {\n    return portalConfig.emailTemplateFramework();\n  }\n\n  @Override\n  protected String getDiffModuleTemplate() {\n    return portalConfig.emailReleaseDiffModuleTemplate();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/component/emailbuilder/RollbackEmailBuilder.java",
    "content": "package com.ctrip.framework.apollo.portal.component.emailbuilder;\n\n\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.portal.entity.bo.ReleaseHistoryBO;\n\nimport org.springframework.stereotype.Component;\n\n\n@Component\npublic class RollbackEmailBuilder extends ConfigPublishEmailBuilder {\n\n  private static final String EMAIL_SUBJECT = \"[Apollo] 配置回滚\";\n\n\n  @Override\n  protected String subject() {\n    return EMAIL_SUBJECT;\n  }\n\n  @Override\n  protected String emailContent(Env env, ReleaseHistoryBO releaseHistory) {\n    return renderEmailCommonContent(env, releaseHistory);\n  }\n\n  @Override\n  protected String getTemplateFramework() {\n    return portalConfig.emailTemplateFramework();\n  }\n\n  @Override\n  protected String getDiffModuleTemplate() {\n    return portalConfig.emailRollbackDiffModuleTemplate();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/component/txtresolver/ConfigTextResolver.java",
    "content": "package com.ctrip.framework.apollo.portal.component.txtresolver;\n\nimport com.ctrip.framework.apollo.common.dto.ItemChangeSets;\nimport com.ctrip.framework.apollo.common.dto.ItemDTO;\n\nimport java.util.List;\n\n/**\n * users can modify config in text mode.so need resolve text.\n */\npublic interface ConfigTextResolver {\n\n  ItemChangeSets resolve(long namespaceId, String configText, List<ItemDTO> baseItems);\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/component/txtresolver/FileTextResolver.java",
    "content": "package com.ctrip.framework.apollo.portal.component.txtresolver;\n\nimport com.ctrip.framework.apollo.common.dto.ItemChangeSets;\nimport com.ctrip.framework.apollo.common.dto.ItemDTO;\nimport com.ctrip.framework.apollo.core.ConfigConsts;\nimport com.ctrip.framework.apollo.core.utils.StringUtils;\n\nimport org.springframework.stereotype.Component;\nimport org.springframework.util.CollectionUtils;\n\nimport java.util.List;\n\n@Component(\"fileTextResolver\")\npublic class FileTextResolver implements ConfigTextResolver {\n\n\n  @Override\n  public ItemChangeSets resolve(long namespaceId, String configText, List<ItemDTO> baseItems) {\n    ItemChangeSets changeSets = new ItemChangeSets();\n    if (StringUtils.isEmpty(configText)) {\n      return changeSets;\n    }\n    if (CollectionUtils.isEmpty(baseItems)) {\n      changeSets.addCreateItem(createItem(namespaceId, 0, configText));\n    } else {\n      ItemDTO beforeItem = baseItems.get(0);\n      if (!configText.equals(beforeItem.getValue())) {//update\n        changeSets.addUpdateItem(createItem(namespaceId, beforeItem.getId(), configText));\n      }\n    }\n\n    return changeSets;\n  }\n\n  private ItemDTO createItem(long namespaceId, long itemId, String value) {\n    ItemDTO item = new ItemDTO();\n    item.setId(itemId);\n    item.setNamespaceId(namespaceId);\n    item.setValue(value);\n    item.setLineNum(1);\n    item.setKey(ConfigConsts.CONFIG_FILE_CONTENT_KEY);\n    return item;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/component/txtresolver/PropertyResolver.java",
    "content": "package com.ctrip.framework.apollo.portal.component.txtresolver;\n\nimport com.ctrip.framework.apollo.common.dto.ItemChangeSets;\nimport com.ctrip.framework.apollo.common.dto.ItemDTO;\nimport com.ctrip.framework.apollo.common.exception.BadRequestException;\nimport com.ctrip.framework.apollo.common.utils.BeanUtils;\n\nimport org.springframework.stereotype.Component;\n\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\n/**\n * normal property file resolver.\n * update comment and blank item implement by create new item and delete old item.\n * update normal key/value item implement by update.\n */\n@Component(\"propertyResolver\")\npublic class PropertyResolver implements ConfigTextResolver {\n\n  private static final String KV_SEPARATOR = \"=\";\n  private static final String ITEM_SEPARATOR = \"\\n\";\n\n  @Override\n  public ItemChangeSets resolve(long namespaceId, String configText, List<ItemDTO> baseItems) {\n\n    Map<Integer, ItemDTO> oldLineNumMapItem = BeanUtils.mapByKey(\"lineNum\", baseItems);\n    Map<String, ItemDTO> oldKeyMapItem = BeanUtils.mapByKey(\"key\", baseItems);\n\n    //remove comment and blank item map.\n    oldKeyMapItem.remove(\"\");\n\n    String[] newItems = configText.split(ITEM_SEPARATOR);\n\n    if (isHasRepeatKey(newItems)) {\n      throw new BadRequestException(\"config text has repeat key please check.\");\n    }\n\n    ItemChangeSets changeSets = new ItemChangeSets();\n    Map<Integer, String> newLineNumMapItem = new HashMap<Integer, String>();//use for delete blank and comment item\n    int lineCounter = 1;\n    for (String newItem : newItems) {\n      newItem = newItem.trim();\n      newLineNumMapItem.put(lineCounter, newItem);\n      ItemDTO oldItemByLine = oldLineNumMapItem.get(lineCounter);\n\n      //comment item\n      if (isCommentItem(newItem)) {\n\n        handleCommentLine(namespaceId, oldItemByLine, newItem, lineCounter, changeSets);\n\n        //blank item\n      } else if (isBlankItem(newItem)) {\n\n        handleBlankLine(namespaceId, oldItemByLine, lineCounter, changeSets);\n\n        //normal item\n      } else {\n        handleNormalLine(namespaceId, oldKeyMapItem, newItem, lineCounter, changeSets);\n      }\n\n      lineCounter++;\n    }\n\n    deleteCommentAndBlankItem(oldLineNumMapItem, newLineNumMapItem, changeSets);\n    deleteNormalKVItem(oldKeyMapItem, changeSets);\n\n    return changeSets;\n  }\n\n  private boolean isHasRepeatKey(String[] newItems) {\n    Set<String> keys = new HashSet<>();\n    int lineCounter = 1;\n    int keyCount = 0;\n    for (String item : newItems) {\n      if (!isCommentItem(item) && !isBlankItem(item)) {\n        keyCount++;\n        String[] kv = parseKeyValueFromItem(item);\n        if (kv != null) {\n          keys.add(kv[0]);\n        } else {\n          throw new BadRequestException(\"line:\" + lineCounter + \" key value must separate by '='\");\n        }\n      }\n      lineCounter++;\n    }\n\n    return keyCount > keys.size();\n  }\n\n  private String[] parseKeyValueFromItem(String item) {\n    int kvSeparator = item.indexOf(KV_SEPARATOR);\n    if (kvSeparator == -1) {\n      return null;\n    }\n\n    String[] kv = new String[2];\n    kv[0] = item.substring(0, kvSeparator).trim();\n    kv[1] = item.substring(kvSeparator + 1, item.length()).trim();\n    return kv;\n  }\n\n  private void handleCommentLine(Long namespaceId, ItemDTO oldItemByLine, String newItem, int lineCounter, ItemChangeSets changeSets) {\n    String oldComment = oldItemByLine == null ? \"\" : oldItemByLine.getComment();\n    //create comment. implement update comment by delete old comment and create new comment\n    if (!(isCommentItem(oldItemByLine) && newItem.equals(oldComment))) {\n      changeSets.addCreateItem(buildCommentItem(0l, namespaceId, newItem, lineCounter));\n    }\n  }\n\n  private void handleBlankLine(Long namespaceId, ItemDTO oldItem, int lineCounter, ItemChangeSets changeSets) {\n    if (!isBlankItem(oldItem)) {\n      changeSets.addCreateItem(buildBlankItem(0l, namespaceId, lineCounter));\n    }\n  }\n\n  private void handleNormalLine(Long namespaceId, Map<String, ItemDTO> keyMapOldItem, String newItem,\n                                int lineCounter, ItemChangeSets changeSets) {\n\n    String[] kv = parseKeyValueFromItem(newItem);\n\n    if (kv == null) {\n      throw new BadRequestException(\"line:\" + lineCounter + \" key value must separate by '='\");\n    }\n\n    String newKey = kv[0];\n    String newValue = kv[1].replace(\"\\\\n\", \"\\n\"); //handle user input \\n\n\n    ItemDTO oldItem = keyMapOldItem.get(newKey);\n\n    if (oldItem == null) {//new item\n      changeSets.addCreateItem(buildNormalItem(0l, namespaceId, newKey, newValue, \"\", lineCounter));\n    } else if (!newValue.equals(oldItem.getValue()) || lineCounter != oldItem.getLineNum()) {//update item\n      changeSets.addUpdateItem(\n          buildNormalItem(oldItem.getId(), namespaceId, newKey, newValue, oldItem.getComment(),\n              lineCounter));\n    }\n    keyMapOldItem.remove(newKey);\n  }\n\n  private boolean isCommentItem(ItemDTO item) {\n    return item != null && \"\".equals(item.getKey())\n        && (item.getComment().startsWith(\"#\") || item.getComment().startsWith(\"!\"));\n  }\n\n  private boolean isCommentItem(String line) {\n    return line != null && (line.startsWith(\"#\") || line.startsWith(\"!\"));\n  }\n\n  private boolean isBlankItem(ItemDTO item) {\n    return item != null && \"\".equals(item.getKey()) && \"\".equals(item.getComment());\n  }\n\n  private boolean isBlankItem(String line) {\n    return \"\".equals(line);\n  }\n\n  private void deleteNormalKVItem(Map<String, ItemDTO> baseKeyMapItem, ItemChangeSets changeSets) {\n    //surplus item is to be deleted\n    for (Map.Entry<String, ItemDTO> entry : baseKeyMapItem.entrySet()) {\n      changeSets.addDeleteItem(entry.getValue());\n    }\n  }\n\n  private void deleteCommentAndBlankItem(Map<Integer, ItemDTO> oldLineNumMapItem,\n                                         Map<Integer, String> newLineNumMapItem,\n                                         ItemChangeSets changeSets) {\n\n    for (Map.Entry<Integer, ItemDTO> entry : oldLineNumMapItem.entrySet()) {\n      int lineNum = entry.getKey();\n      ItemDTO oldItem = entry.getValue();\n      String newItem = newLineNumMapItem.get(lineNum);\n\n      //1. old is blank by now is not\n      //2.old is comment by now is not exist or modified\n      if ((isBlankItem(oldItem) && !isBlankItem(newItem))\n          || isCommentItem(oldItem) && (newItem == null || !newItem.equals(oldItem.getComment()))) {\n        changeSets.addDeleteItem(oldItem);\n      }\n    }\n  }\n\n  private ItemDTO buildCommentItem(Long id, Long namespaceId, String comment, int lineNum) {\n    return buildNormalItem(id, namespaceId, \"\", \"\", comment, lineNum);\n  }\n\n  private ItemDTO buildBlankItem(Long id, Long namespaceId, int lineNum) {\n    return buildNormalItem(id, namespaceId, \"\", \"\", \"\", lineNum);\n  }\n\n  private ItemDTO buildNormalItem(Long id, Long namespaceId, String key, String value, String comment, int lineNum) {\n    ItemDTO item = new ItemDTO(key, value, comment, lineNum);\n    item.setId(id);\n    item.setNamespaceId(namespaceId);\n    return item;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/constant/PermissionType.java",
    "content": "package com.ctrip.framework.apollo.portal.constant;\n\npublic interface PermissionType {\n\n  /**\n   * APP level permission\n   */\n\n  String CREATE_NAMESPACE = \"CreateNamespace\";\n\n  String CREATE_CLUSTER = \"CreateCluster\";\n\n  /**\n   * 分配用户权限的权限\n   */\n  String ASSIGN_ROLE = \"AssignRole\";\n\n  /**\n   * namespace level permission\n   */\n\n  String MODIFY_NAMESPACE = \"ModifyNamespace\";\n\n  String RELEASE_NAMESPACE = \"ReleaseNamespace\";\n\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/constant/RoleType.java",
    "content": "package com.ctrip.framework.apollo.portal.constant;\n\npublic class RoleType {\n\n  public static final String MASTER = \"Master\";\n\n  public static final String MODIFY_NAMESPACE = \"ModifyNamespace\";\n\n  public static final String RELEASE_NAMESPACE = \"ReleaseNamespace\";\n\n  public static boolean isValidRoleType(String roleType) {\n    return MASTER.equals(roleType) || MODIFY_NAMESPACE.equals(roleType) || RELEASE_NAMESPACE.equals(roleType);\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/constant/TracerEventType.java",
    "content": "package com.ctrip.framework.apollo.portal.constant;\n\npublic interface TracerEventType {\n\n  String RELEASE_NAMESPACE = \"Namespace.Release\";\n\n  String MODIFY_NAMESPACE_BY_TEXT = \"Namespace.Modify.Text\";\n\n  String MODIFY_NAMESPACE = \"Namespace.Modify\";\n\n  String SYNC_NAMESPACE = \"Namespace.Sync\";\n\n  String CREATE_APP = \"App.Create\";\n\n  String CREATE_CLUSTER = \"Cluster.Create\";\n\n  String CREATE_NAMESPACE = \"Namespace.Create\";\n\n  String API_RETRY = \"API.Retry\";\n\n  String USER_ACCESS = \"User.Access\";\n\n  String CREATE_GRAY_RELEASE = \"GrayRelease.Create\";\n\n  String DELETE_GRAY_RELEASE = \"GrayRelease.Delete\";\n\n  String MERGE_GRAY_RELEASE = \"GrayRelease.Merge\";\n\n  String UPDATE_GRAY_RELEASE_RULE = \"GrayReleaseRule.Update\";\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/AppController.java",
    "content": "package com.ctrip.framework.apollo.portal.controller;\n\n\nimport com.google.common.collect.Sets;\n\nimport com.ctrip.framework.apollo.common.entity.App;\nimport com.ctrip.framework.apollo.common.exception.BadRequestException;\nimport com.ctrip.framework.apollo.common.http.MultiResponseEntity;\nimport com.ctrip.framework.apollo.common.http.RichResponseEntity;\nimport com.ctrip.framework.apollo.common.utils.InputValidator;\nimport com.ctrip.framework.apollo.common.utils.RequestPrecondition;\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.portal.component.PortalSettings;\nimport com.ctrip.framework.apollo.portal.entity.model.AppModel;\nimport com.ctrip.framework.apollo.portal.entity.vo.EnvClusterInfo;\nimport com.ctrip.framework.apollo.portal.listener.AppCreationEvent;\nimport com.ctrip.framework.apollo.portal.listener.AppInfoChangedEvent;\nimport com.ctrip.framework.apollo.portal.service.AppService;\nimport com.ctrip.framework.apollo.portal.service.RolePermissionService;\nimport com.ctrip.framework.apollo.portal.spi.UserInfoHolder;\nimport com.ctrip.framework.apollo.portal.util.RoleUtils;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.ApplicationEventPublisher;\nimport org.springframework.data.domain.Pageable;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.security.access.prepost.PreAuthorize;\nimport org.springframework.util.CollectionUtils;\nimport org.springframework.util.StringUtils;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\nimport org.springframework.web.client.HttpClientErrorException;\n\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.Set;\n\n\n@RestController\n@RequestMapping(\"/apps\")\npublic class AppController {\n\n  @Autowired\n  private UserInfoHolder userInfoHolder;\n  @Autowired\n  private AppService appService;\n  @Autowired\n  private PortalSettings portalSettings;\n  @Autowired\n  private ApplicationEventPublisher publisher;\n  @Autowired\n  private RolePermissionService rolePermissionService;\n\n  @RequestMapping(value = \"\", method = RequestMethod.GET)\n  public List<App> findApps(@RequestParam(value = \"appIds\", required = false) String appIds) {\n    if (StringUtils.isEmpty(appIds)) {\n      return appService.findAll();\n    } else {\n      return appService.findByAppIds(Sets.newHashSet(appIds.split(\",\")));\n    }\n\n  }\n\n  @RequestMapping(value = \"/by-owner\", method = RequestMethod.GET)\n  public List<App> findAppsByOwner(@RequestParam(\"owner\") String owner, Pageable page) {\n    return appService.findByOwnerName(owner, page);\n  }\n\n  @RequestMapping(value = \"\", method = RequestMethod.POST)\n  public App create(@RequestBody AppModel appModel) {\n\n    App app = transformToApp(appModel);\n\n    App createdApp = appService.createAppInLocal(app);\n\n    publisher.publishEvent(new AppCreationEvent(createdApp));\n\n    Set<String> admins = appModel.getAdmins();\n    if (!CollectionUtils.isEmpty(admins)) {\n      rolePermissionService.assignRoleToUsers(RoleUtils.buildAppMasterRoleName(createdApp.getAppId()),\n                                              admins, userInfoHolder.getUser().getUserId());\n    }\n\n    return createdApp;\n  }\n\n  @PreAuthorize(value = \"@permissionValidator.isAppAdmin(#appId)\")\n  @RequestMapping(value = \"/{appId:.+}\", method = RequestMethod.PUT)\n  public void update(@PathVariable String appId, @RequestBody AppModel appModel) {\n    if (!Objects.equals(appId, appModel.getAppId())) {\n      throw new BadRequestException(\"The App Id of path variable and request body is different\");\n    }\n\n    App app = transformToApp(appModel);\n\n    App updatedApp = appService.updateAppInLocal(app);\n\n    publisher.publishEvent(new AppInfoChangedEvent(updatedApp));\n  }\n\n  @RequestMapping(value = \"/{appId}/navtree\", method = RequestMethod.GET)\n  public MultiResponseEntity<EnvClusterInfo> nav(@PathVariable String appId) {\n\n    MultiResponseEntity<EnvClusterInfo> response = MultiResponseEntity.ok();\n    List<Env> envs = portalSettings.getActiveEnvs();\n    for (Env env : envs) {\n      try {\n        response.addResponseEntity(RichResponseEntity.ok(appService.createEnvNavNode(env, appId)));\n      } catch (Exception e) {\n        response.addResponseEntity(RichResponseEntity.error(HttpStatus.INTERNAL_SERVER_ERROR,\n                                                            \"load env:\" + env.name() + \" cluster error.\" + e\n                                                                .getMessage()));\n      }\n    }\n    return response;\n  }\n\n  @RequestMapping(value = \"/envs/{env}\", method = RequestMethod.POST, consumes = {\n      \"application/json\"})\n  public ResponseEntity<Void> create(@PathVariable String env, @RequestBody App app) {\n\n    RequestPrecondition.checkArgumentsNotEmpty(app.getName(), app.getAppId(), app.getOwnerEmail(), app.getOwnerName(),\n                                               app.getOrgId(), app.getOrgName());\n    if (!InputValidator.isValidClusterNamespace(app.getAppId())) {\n      throw new BadRequestException(InputValidator.INVALID_CLUSTER_NAMESPACE_MESSAGE);\n    }\n\n    appService.createAppInRemote(Env.valueOf(env), app);\n\n    return ResponseEntity.ok().build();\n  }\n\n  @RequestMapping(value = \"/{appId:.+}\", method = RequestMethod.GET)\n  public App load(@PathVariable String appId) {\n\n    return appService.load(appId);\n  }\n\n  @RequestMapping(value = \"/{appId}/miss_envs\", method = RequestMethod.GET)\n  public MultiResponseEntity<Env> findMissEnvs(@PathVariable String appId) {\n\n    MultiResponseEntity<Env> response = MultiResponseEntity.ok();\n    for (Env env : portalSettings.getActiveEnvs()) {\n      try {\n        appService.load(env, appId);\n      } catch (Exception e) {\n        if (e instanceof HttpClientErrorException &&\n            ((HttpClientErrorException) e).getStatusCode() == HttpStatus.NOT_FOUND) {\n          response.addResponseEntity(RichResponseEntity.ok(env));\n        } else {\n          response.addResponseEntity(RichResponseEntity.error(HttpStatus.INTERNAL_SERVER_ERROR,\n                                                              String.format(\"load appId:%s from env %s error.\", appId,\n                                                                            env)\n                                                              + e.getMessage()));\n        }\n      }\n    }\n\n    return response;\n\n  }\n\n  private App transformToApp(AppModel appModel) {\n    String appId = appModel.getAppId();\n    String appName = appModel.getName();\n    String ownerName = appModel.getOwnerName();\n    String orgId = appModel.getOrgId();\n    String orgName = appModel.getOrgName();\n\n    RequestPrecondition.checkArgumentsNotEmpty(appId, appName, ownerName, orgId, orgName);\n\n    if (!InputValidator.isValidClusterNamespace(appModel.getAppId())) {\n      throw new BadRequestException(String.format(\"AppId格式错误: %s\", InputValidator.INVALID_CLUSTER_NAMESPACE_MESSAGE));\n    }\n\n    return App.builder()\n            .appId(appId)\n            .name(appName)\n            .ownerName(ownerName)\n            .orgId(orgId)\n            .orgName(orgName)\n            .build();\n\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/ClusterController.java",
    "content": "package com.ctrip.framework.apollo.portal.controller;\n\nimport com.ctrip.framework.apollo.common.dto.ClusterDTO;\nimport com.ctrip.framework.apollo.common.exception.BadRequestException;\nimport com.ctrip.framework.apollo.common.utils.InputValidator;\nimport com.ctrip.framework.apollo.common.utils.RequestPrecondition;\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.portal.service.ClusterService;\nimport com.ctrip.framework.apollo.portal.spi.UserInfoHolder;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.security.access.prepost.PreAuthorize;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.Objects;\n\nimport static com.ctrip.framework.apollo.common.utils.RequestPrecondition.checkModel;\n\n@RestController\npublic class ClusterController {\n\n  @Autowired\n  private ClusterService clusterService;\n  @Autowired\n  private UserInfoHolder userInfoHolder;\n\n  @PreAuthorize(value = \"@permissionValidator.hasCreateClusterPermission(#appId)\")\n  @RequestMapping(value = \"apps/{appId}/envs/{env}/clusters\", method = RequestMethod.POST)\n  public ClusterDTO createCluster(@PathVariable String appId, @PathVariable String env,\n                                  @RequestBody ClusterDTO cluster) {\n\n    checkModel(Objects.nonNull(cluster));\n    RequestPrecondition.checkArgumentsNotEmpty(cluster.getAppId(), cluster.getName());\n\n    if (!InputValidator.isValidClusterNamespace(cluster.getName())) {\n      throw new BadRequestException(String.format(\"Cluster格式错误: %s\", InputValidator.INVALID_CLUSTER_NAMESPACE_MESSAGE));\n    }\n\n    String operator = userInfoHolder.getUser().getUserId();\n    cluster.setDataChangeLastModifiedBy(operator);\n    cluster.setDataChangeCreatedBy(operator);\n\n    return clusterService.createCluster(Env.valueOf(env), cluster);\n  }\n\n  @PreAuthorize(value = \"@permissionValidator.isSuperAdmin()\")\n  @RequestMapping(value = \"apps/{appId}/envs/{env}/clusters/{clusterName:.+}\", method = RequestMethod.DELETE)\n  public ResponseEntity<Void> deleteCluster(@PathVariable String appId, @PathVariable String env,\n                                            @PathVariable String clusterName){\n    clusterService.deleteCluster(Env.valueOf(env), appId, clusterName);\n    return ResponseEntity.ok().build();\n  }\n\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/CommitController.java",
    "content": "package com.ctrip.framework.apollo.portal.controller;\n\nimport com.ctrip.framework.apollo.common.dto.CommitDTO;\nimport com.ctrip.framework.apollo.common.utils.RequestPrecondition;\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.portal.service.CommitService;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.List;\n\n\n@RestController\npublic class CommitController {\n\n  @Autowired\n  private CommitService commitService;\n\n  @RequestMapping(value = \"/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/commits\", method = RequestMethod.GET)\n  public List<CommitDTO> find(@PathVariable String appId, @PathVariable String env,\n                              @PathVariable String clusterName, @PathVariable String namespaceName,\n                              @RequestParam(defaultValue = \"0\") int page, @RequestParam(defaultValue = \"10\") int size) {\n\n    RequestPrecondition.checkNumberPositive(size);\n    RequestPrecondition.checkNumberNotNegative(page);\n\n    return commitService.find(appId, Env.valueOf(env), clusterName, namespaceName, page, size);\n\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/ConsumerController.java",
    "content": "package com.ctrip.framework.apollo.portal.controller;\n\nimport com.ctrip.framework.apollo.common.dto.NamespaceDTO;\nimport com.ctrip.framework.apollo.common.exception.BadRequestException;\nimport com.ctrip.framework.apollo.core.utils.StringUtils;\nimport com.ctrip.framework.apollo.openapi.entity.Consumer;\nimport com.ctrip.framework.apollo.openapi.entity.ConsumerRole;\nimport com.ctrip.framework.apollo.openapi.entity.ConsumerToken;\nimport com.ctrip.framework.apollo.openapi.service.ConsumerService;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.format.annotation.DateTimeFormat;\nimport org.springframework.security.access.prepost.PreAuthorize;\nimport org.springframework.transaction.annotation.Transactional;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.Calendar;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.GregorianCalendar;\nimport java.util.List;\nimport java.util.Objects;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@RestController\npublic class ConsumerController {\n\n  private static final Date DEFAULT_EXPIRES = new GregorianCalendar(2099, Calendar.JANUARY, 1).getTime();\n\n  @Autowired\n  private ConsumerService consumerService;\n\n\n  @Transactional\n  @PreAuthorize(value = \"@permissionValidator.isSuperAdmin()\")\n  @RequestMapping(value = \"/consumers\", method = RequestMethod.POST)\n  public ConsumerToken createConsumer(@RequestBody Consumer consumer,\n                                      @RequestParam(value = \"expires\", required = false)\n                                      @DateTimeFormat(pattern = \"yyyyMMddHHmmss\") Date\n                                          expires) {\n\n    if (StringUtils.isContainEmpty(consumer.getAppId(), consumer.getName(),\n                                   consumer.getOwnerName(), consumer.getOrgId())) {\n      throw new BadRequestException(\"Params(appId、name、ownerName、orgId) can not be empty.\");\n    }\n\n    Consumer createdConsumer = consumerService.createConsumer(consumer);\n\n    if (Objects.isNull(expires)) {\n      expires = DEFAULT_EXPIRES;\n    }\n\n    return consumerService.generateAndSaveConsumerToken(createdConsumer, expires);\n  }\n\n  @RequestMapping(value = \"/consumers/by-appId\", method = RequestMethod.GET)\n  public ConsumerToken getConsumerTokenByAppId(@RequestParam String appId) {\n    return consumerService.getConsumerTokenByAppId(appId);\n  }\n\n  @PreAuthorize(value = \"@permissionValidator.isSuperAdmin()\")\n  @RequestMapping(value = \"/consumers/{token}/assign-role\", method = RequestMethod.POST)\n  public List<ConsumerRole> assignNamespaceRoleToConsumer(@PathVariable String token,\n                                                          @RequestParam String type,\n                                                          @RequestBody NamespaceDTO namespace) {\n\n    String appId = namespace.getAppId();\n    String namespaceName = namespace.getNamespaceName();\n\n    if (StringUtils.isEmpty(appId)) {\n      throw new BadRequestException(\"Params(AppId) can not be empty.\");\n    }\n\n    if (Objects.equals(\"AppRole\", type)) {\n      return Collections.singletonList(consumerService.assignAppRoleToConsumer(token, appId));\n    } else {\n      if (StringUtils.isEmpty(namespaceName)) {\n        throw new BadRequestException(\"Params(NamespaceName) can not be empty.\");\n      }\n      return consumerService.assignNamespaceRoleToConsumer(token, appId, namespaceName);\n    }\n  }\n\n\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/EnvController.java",
    "content": "package com.ctrip.framework.apollo.portal.controller;\n\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.portal.component.PortalSettings;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.List;\n\n@RestController\n@RequestMapping(\"/envs\")\npublic class EnvController {\n\n  @Autowired\n  private PortalSettings portalSettings;\n\n  @RequestMapping(value = \"\", method = RequestMethod.GET)\n  public List<Env> envs() {\n    return portalSettings.getActiveEnvs();\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/FavoriteController.java",
    "content": "package com.ctrip.framework.apollo.portal.controller;\n\nimport com.ctrip.framework.apollo.portal.entity.po.Favorite;\nimport com.ctrip.framework.apollo.portal.service.FavoriteService;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.data.domain.Pageable;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.List;\n\n@RestController\npublic class FavoriteController {\n\n  @Autowired\n  private FavoriteService favoriteService;\n\n\n  @RequestMapping(value = \"/favorites\", method = RequestMethod.POST)\n  public Favorite addFavorite(@RequestBody Favorite favorite) {\n    return favoriteService.addFavorite(favorite);\n  }\n\n\n  @RequestMapping(value = \"/favorites\", method = RequestMethod.GET)\n  public List<Favorite> findFavorites(@RequestParam(value = \"userId\", required = false) String userId,\n                                      @RequestParam(value = \"appId\", required = false) String appId,\n                                      Pageable page) {\n    return favoriteService.search(userId, appId, page);\n  }\n\n\n  @RequestMapping(value = \"/favorites/{favoriteId}\", method = RequestMethod.DELETE)\n  public void deleteFavorite(@PathVariable long favoriteId) {\n    favoriteService.deleteFavorite(favoriteId);\n  }\n\n\n  @RequestMapping(value = \"/favorites/{favoriteId}\", method = RequestMethod.PUT)\n  public void toTop(@PathVariable long favoriteId) {\n    favoriteService.adjustFavoriteToFirst(favoriteId);\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/InstanceController.java",
    "content": "package com.ctrip.framework.apollo.portal.controller;\n\nimport com.google.common.base.Splitter;\n\nimport com.ctrip.framework.apollo.common.dto.InstanceDTO;\nimport com.ctrip.framework.apollo.common.dto.PageDTO;\nimport com.ctrip.framework.apollo.common.exception.BadRequestException;\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.portal.entity.vo.Number;\nimport com.ctrip.framework.apollo.portal.service.InstanceService;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.util.CollectionUtils;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.List;\nimport java.util.Set;\nimport java.util.stream.Collectors;\n\n@RestController\npublic class InstanceController {\n\n    private static final Splitter RELEASES_SPLITTER = Splitter.on(\",\").omitEmptyStrings()\n        .trimResults();\n\n    @Autowired\n    private InstanceService instanceService;\n\n    @RequestMapping(value = \"/envs/{env}/instances/by-release\", method = RequestMethod.GET)\n    public PageDTO<InstanceDTO> getByRelease(@PathVariable String env, @RequestParam long releaseId,\n                                             @RequestParam(defaultValue = \"0\") int page,\n                                             @RequestParam(defaultValue = \"20\") int size) {\n\n        return instanceService.getByRelease(Env.valueOf(env), releaseId, page, size);\n    }\n\n    @RequestMapping(value = \"/envs/{env}/instances/by-namespace\", method = RequestMethod.GET)\n    public PageDTO<InstanceDTO> getByNamespace(@PathVariable String env, @RequestParam String appId,\n                                               @RequestParam String clusterName, @RequestParam String namespaceName,\n                                               @RequestParam(required = false) String instanceAppId,\n                                               @RequestParam(defaultValue = \"0\") int page,\n                                               @RequestParam(defaultValue = \"20\") int size) {\n\n        return instanceService.getByNamespace(Env.valueOf(env), appId, clusterName, namespaceName, instanceAppId, page, size);\n    }\n\n    @RequestMapping(value = \"/envs/{env}/instances/by-namespace/count\", method = RequestMethod.GET)\n    public ResponseEntity<Number> getInstanceCountByNamespace(@PathVariable String env, @RequestParam String appId,\n                                                              @RequestParam String clusterName,\n                                                              @RequestParam String namespaceName) {\n\n        int count = instanceService.getInstanceCountByNamepsace(appId, Env.valueOf(env), clusterName, namespaceName);\n        return ResponseEntity.ok(new Number(count));\n    }\n\n    @RequestMapping(value = \"/envs/{env}/instances/by-namespace-and-releases-not-in\", method = RequestMethod.GET)\n    public List<InstanceDTO> getByReleasesNotIn(@PathVariable String env, @RequestParam String appId,\n                                                @RequestParam String clusterName, @RequestParam String namespaceName,\n                                                @RequestParam String releaseIds) {\n\n        Set<Long> releaseIdSet = RELEASES_SPLITTER.splitToList(releaseIds).stream().map(Long::parseLong)\n            .collect(Collectors.toSet());\n\n        if (CollectionUtils.isEmpty(releaseIdSet)) {\n            throw new BadRequestException(\"release ids can not be empty\");\n        }\n\n        return instanceService.getByReleasesNotIn(Env.valueOf(env), appId, clusterName, namespaceName, releaseIdSet);\n    }\n\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/ItemController.java",
    "content": "package com.ctrip.framework.apollo.portal.controller;\n\nimport com.ctrip.framework.apollo.common.dto.ItemDTO;\nimport com.ctrip.framework.apollo.common.exception.BadRequestException;\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.core.utils.StringUtils;\nimport com.ctrip.framework.apollo.portal.entity.model.NamespaceSyncModel;\nimport com.ctrip.framework.apollo.portal.entity.model.NamespaceTextModel;\nimport com.ctrip.framework.apollo.portal.entity.vo.ItemDiffs;\nimport com.ctrip.framework.apollo.portal.service.ItemService;\nimport com.ctrip.framework.apollo.portal.spi.UserInfoHolder;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.security.access.prepost.PreAuthorize;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Objects;\n\nimport static com.ctrip.framework.apollo.common.utils.RequestPrecondition.checkModel;\n\n@RestController\npublic class ItemController {\n\n  @Autowired\n  private ItemService configService;\n  @Autowired\n  private UserInfoHolder userInfoHolder;\n\n  @PreAuthorize(value = \"@permissionValidator.hasModifyNamespacePermission(#appId, #namespaceName)\")\n  @RequestMapping(value = \"/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/items\", method = RequestMethod.PUT, consumes = {\n      \"application/json\"})\n  public void modifyItemsByText(@PathVariable String appId, @PathVariable String env,\n                                @PathVariable String clusterName, @PathVariable String namespaceName,\n                                @RequestBody NamespaceTextModel model) {\n\n    checkModel(model != null);\n\n    model.setAppId(appId);\n    model.setClusterName(clusterName);\n    model.setEnv(env);\n    model.setNamespaceName(namespaceName);\n\n    configService.updateConfigItemByText(model);\n  }\n\n  @PreAuthorize(value = \"@permissionValidator.hasModifyNamespacePermission(#appId, #namespaceName)\")\n  @RequestMapping(value = \"/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/item\", method = RequestMethod.POST)\n  public ItemDTO createItem(@PathVariable String appId, @PathVariable String env,\n                            @PathVariable String clusterName, @PathVariable String namespaceName,\n                            @RequestBody ItemDTO item) {\n    checkModel(isValidItem(item));\n\n    //protect\n    item.setLineNum(0);\n    item.setId(0);\n    String userId = userInfoHolder.getUser().getUserId();\n    item.setDataChangeCreatedBy(userId);\n    item.setDataChangeLastModifiedBy(userId);\n    item.setDataChangeCreatedTime(null);\n    item.setDataChangeLastModifiedTime(null);\n\n    return configService.createItem(appId, Env.valueOf(env), clusterName, namespaceName, item);\n  }\n\n  @PreAuthorize(value = \"@permissionValidator.hasModifyNamespacePermission(#appId, #namespaceName)\")\n  @RequestMapping(value = \"/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/item\", method = RequestMethod.PUT)\n  public void updateItem(@PathVariable String appId, @PathVariable String env,\n                         @PathVariable String clusterName, @PathVariable String namespaceName,\n                         @RequestBody ItemDTO item) {\n    checkModel(isValidItem(item));\n\n    String username = userInfoHolder.getUser().getUserId();\n    item.setDataChangeLastModifiedBy(username);\n\n    configService.updateItem(appId, Env.valueOf(env), clusterName, namespaceName, item);\n  }\n\n\n  @PreAuthorize(value = \"@permissionValidator.hasModifyNamespacePermission(#appId, #namespaceName)\")\n  @RequestMapping(value = \"/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/items/{itemId}\", method = RequestMethod.DELETE)\n  public void deleteItem(@PathVariable String appId, @PathVariable String env,\n                         @PathVariable String clusterName, @PathVariable String namespaceName,\n                         @PathVariable long itemId) {\n    if (itemId <= 0) {\n      throw new BadRequestException(\"item id invalid\");\n    }\n    configService.deleteItem(Env.valueOf(env), itemId, userInfoHolder.getUser().getUserId());\n  }\n\n\n  @RequestMapping(value = \"/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/items\", method = RequestMethod.GET)\n  public List<ItemDTO> findItems(@PathVariable String appId, @PathVariable String env,\n                                 @PathVariable String clusterName, @PathVariable String namespaceName,\n                                 @RequestParam(defaultValue = \"lineNum\") String orderBy) {\n\n    List<ItemDTO> items = configService.findItems(appId, Env.valueOf(env), clusterName, namespaceName);\n    if (\"lastModifiedTime\".equals(orderBy)) {\n      Collections.sort(items, (o1, o2) -> {\n        if (o1.getDataChangeLastModifiedTime().after(o2.getDataChangeLastModifiedTime())) {\n          return -1;\n        }\n        if (o1.getDataChangeLastModifiedTime().before(o2.getDataChangeLastModifiedTime())) {\n          return 1;\n        }\n        return 0;\n      });\n    }\n    return items;\n  }\n\n  @RequestMapping(value = \"/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/branches/{branchName}/items\", method = RequestMethod.GET)\n  public List<ItemDTO> findBranchItems(@PathVariable(\"appId\") String appId, @PathVariable String env,\n                                       @PathVariable(\"clusterName\") String clusterName,\n                                       @PathVariable(\"namespaceName\") String namespaceName,\n                                       @PathVariable(\"branchName\") String branchName) {\n\n    return findItems(appId, env, branchName, namespaceName, \"lastModifiedTime\");\n  }\n\n  @RequestMapping(value = \"/namespaces/{namespaceName}/diff\", method = RequestMethod.POST, consumes = {\n      \"application/json\"})\n  public List<ItemDiffs> diff(@RequestBody NamespaceSyncModel model) {\n    checkModel(Objects.nonNull(model) && !model.isInvalid());\n\n    return configService.compare(model.getSyncToNamespaces(), model.getSyncItems());\n  }\n\n  @PreAuthorize(value = \"@permissionValidator.hasModifyNamespacePermission(#appId, #namespaceName)\")\n  @RequestMapping(value = \"/apps/{appId}/namespaces/{namespaceName}/items\", method = RequestMethod.PUT, consumes = {\n      \"application/json\"})\n  public ResponseEntity<Void> update(@PathVariable String appId, @PathVariable String namespaceName,\n                                     @RequestBody NamespaceSyncModel model) {\n    checkModel(Objects.nonNull(model) && !model.isInvalid());\n\n    configService.syncItems(model.getSyncToNamespaces(), model.getSyncItems());\n    return ResponseEntity.status(HttpStatus.OK).build();\n  }\n\n  private boolean isValidItem(ItemDTO item) {\n    return Objects.nonNull(item) && !StringUtils.isContainEmpty(item.getKey());\n  }\n\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/NamespaceBranchController.java",
    "content": "package com.ctrip.framework.apollo.portal.controller;\n\nimport com.ctrip.framework.apollo.common.dto.GrayReleaseRuleDTO;\nimport com.ctrip.framework.apollo.common.dto.NamespaceDTO;\nimport com.ctrip.framework.apollo.common.dto.ReleaseDTO;\nimport com.ctrip.framework.apollo.common.exception.BadRequestException;\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.portal.component.PermissionValidator;\nimport com.ctrip.framework.apollo.portal.component.config.PortalConfig;\nimport com.ctrip.framework.apollo.portal.entity.model.NamespaceReleaseModel;\nimport com.ctrip.framework.apollo.portal.entity.bo.NamespaceBO;\nimport com.ctrip.framework.apollo.portal.listener.ConfigPublishEvent;\nimport com.ctrip.framework.apollo.portal.service.NamespaceBranchService;\nimport com.ctrip.framework.apollo.portal.service.ReleaseService;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.ApplicationEventPublisher;\nimport org.springframework.security.access.AccessDeniedException;\nimport org.springframework.security.access.prepost.PreAuthorize;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\n@RestController\npublic class NamespaceBranchController {\n\n  @Autowired\n  private PermissionValidator permissionValidator;\n  @Autowired\n  private ReleaseService releaseService;\n  @Autowired\n  private NamespaceBranchService namespaceBranchService;\n  @Autowired\n  private ApplicationEventPublisher publisher;\n  @Autowired\n  private PortalConfig portalConfig;\n\n  @RequestMapping(value = \"/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/branches\", method = RequestMethod.GET)\n  public NamespaceBO findBranch(@PathVariable String appId,\n                                @PathVariable String env,\n                                @PathVariable String clusterName,\n                                @PathVariable String namespaceName) {\n    return namespaceBranchService.findBranch(appId, Env.valueOf(env), clusterName, namespaceName);\n  }\n\n  @PreAuthorize(value = \"@permissionValidator.hasModifyNamespacePermission(#appId, #namespaceName)\")\n  @RequestMapping(value = \"/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/branches\", method = RequestMethod.POST)\n  public NamespaceDTO createBranch(@PathVariable String appId,\n                                   @PathVariable String env,\n                                   @PathVariable String clusterName,\n                                   @PathVariable String namespaceName) {\n\n    return namespaceBranchService.createBranch(appId, Env.valueOf(env), clusterName, namespaceName);\n  }\n\n  @RequestMapping(value = \"/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/branches/{branchName}\", method = RequestMethod.DELETE)\n  public void deleteBranch(@PathVariable String appId,\n                           @PathVariable String env,\n                           @PathVariable String clusterName,\n                           @PathVariable String namespaceName,\n                           @PathVariable String branchName) {\n\n    boolean canDelete = permissionValidator.hasReleaseNamespacePermission(appId, namespaceName) ||\n                        (permissionValidator.hasModifyNamespacePermission(appId, namespaceName) &&\n                         releaseService.loadLatestRelease(appId, Env.valueOf(env), branchName, namespaceName) == null);\n\n\n    if (!canDelete) {\n      throw new AccessDeniedException(\"Forbidden operation. \"\n                                      + \"Caused by: 1.you don't have release permission \"\n                                      + \"or 2. you don't have modification permission \"\n                                      + \"or 3. you have modification permission but branch has been released\");\n    }\n\n    namespaceBranchService.deleteBranch(appId, Env.valueOf(env), clusterName, namespaceName, branchName);\n\n  }\n\n\n\n  @PreAuthorize(value = \"@permissionValidator.hasReleaseNamespacePermission(#appId, #namespaceName)\")\n  @RequestMapping(value = \"/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/branches/{branchName}/merge\", method = RequestMethod.POST)\n  public ReleaseDTO merge(@PathVariable String appId, @PathVariable String env,\n                          @PathVariable String clusterName, @PathVariable String namespaceName,\n                          @PathVariable String branchName, @RequestParam(value = \"deleteBranch\", defaultValue = \"true\") boolean deleteBranch,\n                          @RequestBody NamespaceReleaseModel model) {\n\n    if (model.isEmergencyPublish() && !portalConfig.isEmergencyPublishAllowed(Env.fromString(env))) {\n      throw new BadRequestException(String.format(\"Env: %s is not supported emergency publish now\", env));\n    }\n\n    ReleaseDTO createdRelease = namespaceBranchService.merge(appId, Env.valueOf(env), clusterName, namespaceName, branchName,\n                                                             model.getReleaseTitle(), model.getReleaseComment(),\n                                                             model.isEmergencyPublish(), deleteBranch);\n\n    ConfigPublishEvent event = ConfigPublishEvent.instance();\n    event.withAppId(appId)\n        .withCluster(clusterName)\n        .withNamespace(namespaceName)\n        .withReleaseId(createdRelease.getId())\n        .setMergeEvent(true)\n        .setEnv(Env.valueOf(env));\n\n    publisher.publishEvent(event);\n\n    return createdRelease;\n  }\n\n\n  @RequestMapping(value = \"/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/branches/{branchName}/rules\", method = RequestMethod.GET)\n  public GrayReleaseRuleDTO getBranchGrayRules(@PathVariable String appId, @PathVariable String env,\n                                                     @PathVariable String clusterName,\n                                                     @PathVariable String namespaceName,\n                                                     @PathVariable String branchName) {\n\n    return namespaceBranchService.findBranchGrayRules(appId, Env.valueOf(env), clusterName, namespaceName, branchName);\n  }\n\n\n  @PreAuthorize(value = \"@permissionValidator.hasOperateNamespacePermission(#appId, #namespaceName)\")\n  @RequestMapping(value = \"/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/branches/{branchName}/rules\", method = RequestMethod.PUT)\n  public void updateBranchRules(@PathVariable String appId, @PathVariable String env,\n                                @PathVariable String clusterName, @PathVariable String namespaceName,\n                                @PathVariable String branchName, @RequestBody GrayReleaseRuleDTO rules) {\n\n    namespaceBranchService\n        .updateBranchGrayRules(appId, Env.valueOf(env), clusterName, namespaceName, branchName, rules);\n\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/NamespaceController.java",
    "content": "package com.ctrip.framework.apollo.portal.controller;\n\nimport com.google.common.collect.Sets;\n\nimport com.ctrip.framework.apollo.common.dto.NamespaceDTO;\nimport com.ctrip.framework.apollo.common.entity.AppNamespace;\nimport com.ctrip.framework.apollo.common.exception.BadRequestException;\nimport com.ctrip.framework.apollo.common.utils.InputValidator;\nimport com.ctrip.framework.apollo.common.utils.RequestPrecondition;\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.portal.component.config.PortalConfig;\nimport com.ctrip.framework.apollo.portal.constant.RoleType;\nimport com.ctrip.framework.apollo.portal.entity.bo.NamespaceBO;\nimport com.ctrip.framework.apollo.portal.entity.model.NamespaceCreationModel;\nimport com.ctrip.framework.apollo.portal.listener.AppNamespaceCreationEvent;\nimport com.ctrip.framework.apollo.portal.service.AppNamespaceService;\nimport com.ctrip.framework.apollo.portal.service.NamespaceService;\nimport com.ctrip.framework.apollo.portal.service.RoleInitializationService;\nimport com.ctrip.framework.apollo.portal.service.RolePermissionService;\nimport com.ctrip.framework.apollo.portal.spi.UserInfoHolder;\nimport com.ctrip.framework.apollo.portal.util.RoleUtils;\nimport com.ctrip.framework.apollo.tracer.Tracer;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.ApplicationEventPublisher;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.security.access.prepost.PreAuthorize;\nimport org.springframework.util.CollectionUtils;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.List;\nimport java.util.Map;\n\nimport static com.ctrip.framework.apollo.common.utils.RequestPrecondition.checkModel;\n\n@RestController\npublic class NamespaceController {\n\n  private static final Logger logger = LoggerFactory.getLogger(NamespaceController.class);\n\n  @Autowired\n  private ApplicationEventPublisher publisher;\n  @Autowired\n  private UserInfoHolder userInfoHolder;\n  @Autowired\n  private NamespaceService namespaceService;\n  @Autowired\n  private AppNamespaceService appNamespaceService;\n  @Autowired\n  private RoleInitializationService roleInitializationService;\n  @Autowired\n  private RolePermissionService rolePermissionService;\n  @Autowired\n  private PortalConfig portalConfig;\n\n\n  @RequestMapping(value = \"/appnamespaces/public\", method = RequestMethod.GET)\n  public List<AppNamespace> findPublicAppNamespaces() {\n    return appNamespaceService.findPublicAppNamespaces();\n  }\n\n  @RequestMapping(value = \"/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces\", method = RequestMethod.GET)\n  public List<NamespaceBO> findNamespaces(@PathVariable String appId, @PathVariable String env,\n                                          @PathVariable String clusterName) {\n\n    return namespaceService.findNamespaceBOs(appId, Env.valueOf(env), clusterName);\n  }\n\n  @RequestMapping(value = \"/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName:.+}\", method = RequestMethod.GET)\n  public NamespaceBO findNamespace(@PathVariable String appId, @PathVariable String env,\n                                   @PathVariable String clusterName, @PathVariable String namespaceName) {\n\n    return namespaceService.loadNamespaceBO(appId, Env.valueOf(env), clusterName, namespaceName);\n  }\n\n  @RequestMapping(value = \"/envs/{env}/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/associated-public-namespace\",\n      method = RequestMethod.GET)\n  public NamespaceBO findPublicNamespaceForAssociatedNamespace(@PathVariable String env,\n                                                               @PathVariable String appId,\n                                                               @PathVariable String namespaceName,\n                                                               @PathVariable String clusterName) {\n\n    return namespaceService.findPublicNamespaceForAssociatedNamespace(Env.valueOf(env), appId, clusterName, namespaceName);\n  }\n\n  @PreAuthorize(value = \"@permissionValidator.hasCreateNamespacePermission(#appId)\")\n  @RequestMapping(value = \"/apps/{appId}/namespaces\", method = RequestMethod.POST)\n  public ResponseEntity<Void> createNamespace(@PathVariable String appId,\n                                              @RequestBody List<NamespaceCreationModel> models) {\n\n    checkModel(!CollectionUtils.isEmpty(models));\n\n    String namespaceName = models.get(0).getNamespace().getNamespaceName();\n    String operator = userInfoHolder.getUser().getUserId();\n\n    roleInitializationService.initNamespaceRoles(appId, namespaceName, operator);\n\n    for (NamespaceCreationModel model : models) {\n      NamespaceDTO namespace = model.getNamespace();\n      RequestPrecondition.checkArgumentsNotEmpty(model.getEnv(), namespace.getAppId(),\n                                                 namespace.getClusterName(), namespace.getNamespaceName());\n\n      try {\n        namespaceService.createNamespace(Env.valueOf(model.getEnv()), namespace);\n      } catch (Exception e) {\n        logger.error(\"create namespace fail.\", e);\n        Tracer.logError(\n                String.format(\"create namespace fail. (env=%s namespace=%s)\", model.getEnv(),\n                        namespace.getNamespaceName()), e);\n      }\n    }\n\n    assignNamespaceRoleToOperator(appId, namespaceName);\n\n    return ResponseEntity.ok().build();\n  }\n\n  @PreAuthorize(value = \"@permissionValidator.hasDeleteNamespacePermission(#appId)\")\n  @RequestMapping(value = \"/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName:.+}\", method = RequestMethod.DELETE)\n  public ResponseEntity<Void> deleteNamespace(@PathVariable String appId, @PathVariable String env,\n                                              @PathVariable String clusterName, @PathVariable String namespaceName) {\n\n    namespaceService.deleteNamespace(appId, Env.valueOf(env), clusterName, namespaceName);\n\n    return ResponseEntity.ok().build();\n  }\n\n  @PreAuthorize(value = \"@permissionValidator.hasCreateAppNamespacePermission(#appId, #appNamespace)\")\n  @RequestMapping(value = \"/apps/{appId}/appnamespaces\", method = RequestMethod.POST)\n  public AppNamespace createAppNamespace(@PathVariable String appId, @RequestBody AppNamespace appNamespace) {\n\n    RequestPrecondition.checkArgumentsNotEmpty(appNamespace.getAppId(), appNamespace.getName());\n    if (!InputValidator.isValidAppNamespace(appNamespace.getName())) {\n      throw new BadRequestException(String.format(\"Namespace格式错误: %s\",\n              InputValidator.INVALID_CLUSTER_NAMESPACE_MESSAGE + \" & \"\n                      + InputValidator.INVALID_NAMESPACE_NAMESPACE_MESSAGE));\n    }\n\n    AppNamespace createdAppNamespace = appNamespaceService.createAppNamespaceInLocal(appNamespace);\n\n    if (portalConfig.canAppAdminCreatePrivateNamespace() || createdAppNamespace.isPublic()) {\n      assignNamespaceRoleToOperator(appId, appNamespace.getName());\n    }\n\n    publisher.publishEvent(new AppNamespaceCreationEvent(createdAppNamespace));\n\n    return createdAppNamespace;\n  }\n\n  /**\n   * env -> cluster -> cluster has not published namespace?\n   * Example:\n   * dev ->\n   *  default -> true   (default cluster has not published namespace)\n   *  customCluster -> false (customCluster cluster's all namespaces had published)\n   */\n  @RequestMapping(value = \"/apps/{appId}/namespaces/publish_info\", method = RequestMethod.GET)\n  public Map<String, Map<String, Boolean>> getNamespacesPublishInfo(@PathVariable String appId) {\n    return namespaceService.getNamespacesPublishInfo(appId);\n  }\n\n  @RequestMapping(value = \"/envs/{env}/appnamespaces/{publicNamespaceName}/namespaces\", method = RequestMethod.GET)\n  public List<NamespaceDTO> getPublicAppNamespaceAllNamespaces(@PathVariable String env,\n                                                               @PathVariable String publicNamespaceName,\n                                                               @RequestParam(name = \"page\", defaultValue = \"0\") int page,\n                                                               @RequestParam(name = \"size\", defaultValue = \"10\") int size) {\n\n    return namespaceService.getPublicAppNamespaceAllNamespaces(Env.fromString(env), publicNamespaceName, page, size);\n\n  }\n\n  private void assignNamespaceRoleToOperator(String appId, String namespaceName) {\n    //default assign modify、release namespace role to namespace creator\n    String operator = userInfoHolder.getUser().getUserId();\n\n    rolePermissionService\n        .assignRoleToUsers(RoleUtils.buildNamespaceRoleName(appId, namespaceName, RoleType.MODIFY_NAMESPACE),\n                           Sets.newHashSet(operator), operator);\n    rolePermissionService\n        .assignRoleToUsers(RoleUtils.buildNamespaceRoleName(appId, namespaceName, RoleType.RELEASE_NAMESPACE),\n                           Sets.newHashSet(operator), operator);\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/NamespaceLockController.java",
    "content": "package com.ctrip.framework.apollo.portal.controller;\n\nimport com.ctrip.framework.apollo.common.dto.NamespaceLockDTO;\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.portal.entity.vo.LockInfo;\nimport com.ctrip.framework.apollo.portal.service.NamespaceLockService;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RestController;\n\n@RestController\npublic class NamespaceLockController {\n\n  @Autowired\n  private NamespaceLockService namespaceLockService;\n\n  @Deprecated\n  @RequestMapping(value = \"/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/lock\", method = RequestMethod.GET)\n  public NamespaceLockDTO getNamespaceLock(@PathVariable String appId, @PathVariable String env,\n                                           @PathVariable String clusterName, @PathVariable String namespaceName) {\n\n    return namespaceLockService.getNamespaceLock(appId, Env.valueOf(env), clusterName, namespaceName);\n  }\n\n  @RequestMapping(value = \"/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/lock-info\", method = RequestMethod.GET)\n  public LockInfo getNamespaceLockInfo(@PathVariable String appId, @PathVariable String env,\n                                       @PathVariable String clusterName, @PathVariable String namespaceName) {\n\n    return namespaceLockService.getNamespaceLockInfo(appId, Env.fromString(env), clusterName, namespaceName);\n\n  }\n\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/OrganizationController.java",
    "content": "package com.ctrip.framework.apollo.portal.controller;\n\n\nimport com.ctrip.framework.apollo.portal.component.config.PortalConfig;\nimport com.ctrip.framework.apollo.portal.entity.vo.Organization;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.List;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@RestController\n@RequestMapping(\"/organizations\")\npublic class OrganizationController {\n\n  @Autowired\n  private PortalConfig portalConfig;\n\n\n  @RequestMapping\n  public List<Organization> loadOrganization() {\n    return portalConfig.organizations();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/PageSettingController.java",
    "content": "package com.ctrip.framework.apollo.portal.controller;\n\nimport com.ctrip.framework.apollo.portal.component.config.PortalConfig;\nimport com.ctrip.framework.apollo.portal.entity.vo.PageSetting;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RestController;\n\n@RestController\npublic class PageSettingController {\n\n  @Autowired\n  private PortalConfig portalConfig;\n\n  @RequestMapping(value = \"/page-settings\", method = RequestMethod.GET)\n  public PageSetting getPageSetting() {\n    PageSetting setting = new PageSetting();\n\n    setting.setWikiAddress(portalConfig.wikiAddress());\n    setting.setCanAppAdminCreatePrivateNamespace(portalConfig.canAppAdminCreatePrivateNamespace());\n\n    return setting;\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/PermissionController.java",
    "content": "package com.ctrip.framework.apollo.portal.controller;\n\nimport com.google.common.collect.Sets;\n\nimport com.ctrip.framework.apollo.common.exception.BadRequestException;\nimport com.ctrip.framework.apollo.common.utils.RequestPrecondition;\nimport com.ctrip.framework.apollo.portal.constant.RoleType;\nimport com.ctrip.framework.apollo.portal.entity.bo.UserInfo;\nimport com.ctrip.framework.apollo.portal.entity.vo.AppRolesAssignedUsers;\nimport com.ctrip.framework.apollo.portal.entity.vo.NamespaceRolesAssignedUsers;\nimport com.ctrip.framework.apollo.portal.entity.vo.PermissionCondition;\nimport com.ctrip.framework.apollo.portal.service.RolePermissionService;\nimport com.ctrip.framework.apollo.portal.spi.UserInfoHolder;\nimport com.ctrip.framework.apollo.portal.spi.UserService;\nimport com.ctrip.framework.apollo.portal.util.RoleUtils;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.security.access.prepost.PreAuthorize;\nimport org.springframework.util.CollectionUtils;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.Set;\n\n\n@RestController\npublic class PermissionController {\n\n  @Autowired\n  private UserInfoHolder userInfoHolder;\n  @Autowired\n  private RolePermissionService rolePermissionService;\n  @Autowired\n  private UserService userService;\n\n  @RequestMapping(value = \"/apps/{appId}/permissions/{permissionType}\", method = RequestMethod.GET)\n  public ResponseEntity<PermissionCondition> hasPermission(@PathVariable String appId, @PathVariable String permissionType) {\n    PermissionCondition permissionCondition = new PermissionCondition();\n\n    permissionCondition.setHasPermission(\n        rolePermissionService.userHasPermission(userInfoHolder.getUser().getUserId(), permissionType, appId));\n\n    return ResponseEntity.ok().body(permissionCondition);\n  }\n\n  @RequestMapping(value = \"/apps/{appId}/namespaces/{namespaceName}/permissions/{permissionType}\", method = RequestMethod.GET)\n  public ResponseEntity<PermissionCondition> hasPermission(@PathVariable String appId, @PathVariable String namespaceName,\n                                                           @PathVariable String permissionType) {\n    PermissionCondition permissionCondition = new PermissionCondition();\n\n    permissionCondition.setHasPermission(\n        rolePermissionService.userHasPermission(userInfoHolder.getUser().getUserId(), permissionType,\n            RoleUtils.buildNamespaceTargetId(appId, namespaceName)));\n\n    return ResponseEntity.ok().body(permissionCondition);\n  }\n\n  @RequestMapping(value = \"/permissions/root\", method = RequestMethod.GET)\n  public ResponseEntity<PermissionCondition> hasRootPermission() {\n    PermissionCondition permissionCondition = new PermissionCondition();\n\n    permissionCondition.setHasPermission(rolePermissionService.isSuperAdmin(userInfoHolder.getUser().getUserId()));\n\n    return ResponseEntity.ok().body(permissionCondition);\n  }\n\n\n  @RequestMapping(value = \"/apps/{appId}/namespaces/{namespaceName}/role_users\", method = RequestMethod.GET)\n  public NamespaceRolesAssignedUsers getNamespaceRoles(@PathVariable String appId, @PathVariable String namespaceName) {\n\n    NamespaceRolesAssignedUsers assignedUsers = new NamespaceRolesAssignedUsers();\n    assignedUsers.setNamespaceName(namespaceName);\n    assignedUsers.setAppId(appId);\n\n    Set<UserInfo> releaseNamespaceUsers =\n        rolePermissionService.queryUsersWithRole(RoleUtils.buildReleaseNamespaceRoleName(appId, namespaceName));\n    assignedUsers.setReleaseRoleUsers(releaseNamespaceUsers);\n\n    Set<UserInfo> modifyNamespaceUsers =\n        rolePermissionService.queryUsersWithRole(RoleUtils.buildModifyNamespaceRoleName(appId, namespaceName));\n    assignedUsers.setModifyRoleUsers(modifyNamespaceUsers);\n\n    return assignedUsers;\n  }\n\n  @PreAuthorize(value = \"@permissionValidator.hasAssignRolePermission(#appId)\")\n  @RequestMapping(value = \"/apps/{appId}/namespaces/{namespaceName}/roles/{roleType}\", method = RequestMethod.POST)\n  public ResponseEntity<Void> assignNamespaceRoleToUser(@PathVariable String appId, @PathVariable String namespaceName,\n                                                        @PathVariable String roleType, @RequestBody String user) {\n    checkUserExists(user);\n    RequestPrecondition.checkArgumentsNotEmpty(user);\n\n    if (!RoleType.isValidRoleType(roleType)) {\n      throw new BadRequestException(\"role type is illegal\");\n    }\n    Set<String> assignedUser = rolePermissionService.assignRoleToUsers(RoleUtils.buildNamespaceRoleName(appId, namespaceName, roleType),\n        Sets.newHashSet(user), userInfoHolder.getUser().getUserId());\n    if (CollectionUtils.isEmpty(assignedUser)) {\n      throw new BadRequestException(user + \"已授权\");\n    }\n\n    return ResponseEntity.ok().build();\n  }\n\n  @PreAuthorize(value = \"@permissionValidator.hasAssignRolePermission(#appId)\")\n  @RequestMapping(value = \"/apps/{appId}/namespaces/{namespaceName}/roles/{roleType}\", method = RequestMethod.DELETE)\n  public ResponseEntity<Void> removeNamespaceRoleFromUser(@PathVariable String appId, @PathVariable String namespaceName,\n                                                          @PathVariable String roleType, @RequestParam String user) {\n    RequestPrecondition.checkArgumentsNotEmpty(user);\n\n    if (!RoleType.isValidRoleType(roleType)) {\n      throw new BadRequestException(\"role type is illegal\");\n    }\n    rolePermissionService.removeRoleFromUsers(RoleUtils.buildNamespaceRoleName(appId, namespaceName, roleType),\n        Sets.newHashSet(user), userInfoHolder.getUser().getUserId());\n    return ResponseEntity.ok().build();\n  }\n\n  @RequestMapping(value = \"/apps/{appId}/role_users\", method = RequestMethod.GET)\n  public AppRolesAssignedUsers getAppRoles(@PathVariable String appId) {\n    AppRolesAssignedUsers users = new AppRolesAssignedUsers();\n    users.setAppId(appId);\n\n    Set<UserInfo> masterUsers = rolePermissionService.queryUsersWithRole(RoleUtils.buildAppMasterRoleName(appId));\n    users.setMasterUsers(masterUsers);\n\n    return users;\n  }\n\n  @PreAuthorize(value = \"@permissionValidator.hasAssignRolePermission(#appId)\")\n  @RequestMapping(value = \"/apps/{appId}/roles/{roleType}\", method = RequestMethod.POST)\n  public ResponseEntity<Void> assignAppRoleToUser(@PathVariable String appId, @PathVariable String roleType,\n                                                  @RequestBody String user) {\n    checkUserExists(user);\n    RequestPrecondition.checkArgumentsNotEmpty(user);\n\n    if (!RoleType.isValidRoleType(roleType)) {\n      throw new BadRequestException(\"role type is illegal\");\n    }\n    Set<String> assignedUsers = rolePermissionService.assignRoleToUsers(RoleUtils.buildAppRoleName(appId, roleType),\n        Sets.newHashSet(user), userInfoHolder.getUser().getUserId());\n    if (CollectionUtils.isEmpty(assignedUsers)) {\n      throw new BadRequestException(user + \"已授权\");\n    }\n\n    return ResponseEntity.ok().build();\n  }\n\n  @PreAuthorize(value = \"@permissionValidator.hasAssignRolePermission(#appId)\")\n  @RequestMapping(value = \"/apps/{appId}/roles/{roleType}\", method = RequestMethod.DELETE)\n  public ResponseEntity<Void> removeAppRoleFromUser(@PathVariable String appId, @PathVariable String roleType,\n                                                    @RequestParam String user) {\n    RequestPrecondition.checkArgumentsNotEmpty(user);\n\n    if (!RoleType.isValidRoleType(roleType)) {\n      throw new BadRequestException(\"role type is illegal\");\n    }\n    rolePermissionService.removeRoleFromUsers(RoleUtils.buildAppRoleName(appId, roleType),\n        Sets.newHashSet(user), userInfoHolder.getUser().getUserId());\n    return ResponseEntity.ok().build();\n  }\n\n  private void checkUserExists(String userId) {\n    if (userService.findByUserId(userId) == null) {\n      throw new BadRequestException(String.format(\"User %s does not exist!\", userId));\n    }\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/ReleaseController.java",
    "content": "package com.ctrip.framework.apollo.portal.controller;\n\nimport com.ctrip.framework.apollo.common.dto.ReleaseDTO;\nimport com.ctrip.framework.apollo.common.exception.BadRequestException;\nimport com.ctrip.framework.apollo.common.utils.RequestPrecondition;\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.portal.component.config.PortalConfig;\nimport com.ctrip.framework.apollo.portal.entity.model.NamespaceReleaseModel;\nimport com.ctrip.framework.apollo.portal.entity.vo.ReleaseCompareResult;\nimport com.ctrip.framework.apollo.portal.entity.bo.ReleaseBO;\nimport com.ctrip.framework.apollo.portal.listener.ConfigPublishEvent;\nimport com.ctrip.framework.apollo.portal.service.ReleaseService;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.ApplicationEventPublisher;\nimport org.springframework.security.access.prepost.PreAuthorize;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.List;\nimport java.util.Objects;\n\nimport static com.ctrip.framework.apollo.common.utils.RequestPrecondition.checkModel;\n\n@RestController\npublic class ReleaseController {\n\n  @Autowired\n  private ReleaseService releaseService;\n  @Autowired\n  private ApplicationEventPublisher publisher;\n  @Autowired\n  private PortalConfig portalConfig;\n\n  @PreAuthorize(value = \"@permissionValidator.hasReleaseNamespacePermission(#appId, #namespaceName)\")\n  @RequestMapping(value = \"/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/releases\", method = RequestMethod.POST)\n  public ReleaseDTO createRelease(@PathVariable String appId,\n                                  @PathVariable String env, @PathVariable String clusterName,\n                                  @PathVariable String namespaceName, @RequestBody NamespaceReleaseModel model) {\n\n    checkModel(Objects.nonNull(model));\n    model.setAppId(appId);\n    model.setEnv(env);\n    model.setClusterName(clusterName);\n    model.setNamespaceName(namespaceName);\n\n    if (model.isEmergencyPublish() && !portalConfig.isEmergencyPublishAllowed(Env.valueOf(env))) {\n      throw new BadRequestException(String.format(\"Env: %s is not supported emergency publish now\", env));\n    }\n\n    ReleaseDTO createdRelease = releaseService.publish(model);\n\n    ConfigPublishEvent event = ConfigPublishEvent.instance();\n    event.withAppId(appId)\n        .withCluster(clusterName)\n        .withNamespace(namespaceName)\n        .withReleaseId(createdRelease.getId())\n        .setNormalPublishEvent(true)\n        .setEnv(Env.valueOf(env));\n\n    publisher.publishEvent(event);\n\n    return createdRelease;\n  }\n\n  @PreAuthorize(value = \"@permissionValidator.hasReleaseNamespacePermission(#appId, #namespaceName)\")\n  @RequestMapping(value = \"/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/branches/{branchName}/releases\",\n      method = RequestMethod.POST)\n  public ReleaseDTO createGrayRelease(@PathVariable String appId,\n                                      @PathVariable String env, @PathVariable String clusterName,\n                                      @PathVariable String namespaceName, @PathVariable String branchName,\n                                      @RequestBody NamespaceReleaseModel model) {\n\n    checkModel(Objects.nonNull(model));\n    model.setAppId(appId);\n    model.setEnv(env);\n    model.setClusterName(branchName);\n    model.setNamespaceName(namespaceName);\n\n    if (model.isEmergencyPublish() && !portalConfig.isEmergencyPublishAllowed(Env.valueOf(env))) {\n      throw new BadRequestException(String.format(\"Env: %s is not supported emergency publish now\", env));\n    }\n\n    ReleaseDTO createdRelease = releaseService.publish(model);\n\n    ConfigPublishEvent event = ConfigPublishEvent.instance();\n    event.withAppId(appId)\n        .withCluster(clusterName)\n        .withNamespace(namespaceName)\n        .withReleaseId(createdRelease.getId())\n        .setGrayPublishEvent(true)\n        .setEnv(Env.valueOf(env));\n\n    publisher.publishEvent(event);\n\n    return createdRelease;\n  }\n\n\n  @RequestMapping(value = \"/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/releases/all\", method = RequestMethod.GET)\n  public List<ReleaseBO> findAllReleases(@PathVariable String appId,\n                                         @PathVariable String env,\n                                         @PathVariable String clusterName,\n                                         @PathVariable String namespaceName,\n                                         @RequestParam(defaultValue = \"0\") int page,\n                                         @RequestParam(defaultValue = \"5\") int size) {\n\n    RequestPrecondition.checkNumberPositive(size);\n    RequestPrecondition.checkNumberNotNegative(page);\n\n    return releaseService.findAllReleases(appId, Env.valueOf(env), clusterName, namespaceName, page, size);\n  }\n\n  @RequestMapping(value = \"/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/releases/active\", method = RequestMethod.GET)\n  public List<ReleaseDTO> findActiveReleases(@PathVariable String appId,\n                                             @PathVariable String env,\n                                             @PathVariable String clusterName,\n                                             @PathVariable String namespaceName,\n                                             @RequestParam(defaultValue = \"0\") int page,\n                                             @RequestParam(defaultValue = \"5\") int size) {\n\n    RequestPrecondition.checkNumberPositive(size);\n    RequestPrecondition.checkNumberNotNegative(page);\n\n    return releaseService.findActiveReleases(appId, Env.valueOf(env), clusterName, namespaceName, page, size);\n  }\n\n  @RequestMapping(value = \"/envs/{env}/releases/compare\", method = RequestMethod.GET)\n  public ReleaseCompareResult compareRelease(@PathVariable String env,\n                                             @RequestParam long baseReleaseId,\n                                             @RequestParam long toCompareReleaseId) {\n\n    return releaseService.compare(Env.valueOf(env), baseReleaseId, toCompareReleaseId);\n  }\n\n\n  @RequestMapping(path = \"/envs/{env}/releases/{releaseId}/rollback\", method = RequestMethod.PUT)\n  public void rollback(@PathVariable String env,\n                       @PathVariable long releaseId) {\n    releaseService.rollback(Env.valueOf(env), releaseId);\n    ReleaseDTO release = releaseService.findReleaseById(Env.valueOf(env), releaseId);\n    if (Objects.isNull(release)) {\n      return;\n    }\n\n    ConfigPublishEvent event = ConfigPublishEvent.instance();\n    event.withAppId(release.getAppId())\n        .withCluster(release.getClusterName())\n        .withNamespace(release.getNamespaceName())\n        .withPreviousReleaseId(releaseId)\n        .setRollbackEvent(true)\n        .setEnv(Env.valueOf(env));\n\n    publisher.publishEvent(event);\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/ReleaseHistoryController.java",
    "content": "package com.ctrip.framework.apollo.portal.controller;\n\n\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.portal.entity.bo.ReleaseHistoryBO;\nimport com.ctrip.framework.apollo.portal.service.ReleaseHistoryService;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.List;\n\n@RestController\npublic class ReleaseHistoryController {\n\n  @Autowired\n  private ReleaseHistoryService releaseHistoryService;\n\n  @RequestMapping(value = \"/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/releases/histories\",\n      method = RequestMethod.GET)\n  public List<ReleaseHistoryBO> findReleaseHistoriesByNamespace(@PathVariable String appId,\n                                                                @PathVariable String env,\n                                                                @PathVariable String clusterName,\n                                                                @PathVariable String namespaceName,\n                                                                @RequestParam(value = \"page\", defaultValue = \"0\") int page,\n                                                                @RequestParam(value = \"size\", defaultValue = \"10\") int size) {\n\n   return releaseHistoryService.findNamespaceReleaseHistory(appId, Env.valueOf(env), clusterName ,namespaceName, page, size);\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/ServerConfigController.java",
    "content": "package com.ctrip.framework.apollo.portal.controller;\n\n\nimport com.ctrip.framework.apollo.common.utils.BeanUtils;\nimport com.ctrip.framework.apollo.common.utils.RequestPrecondition;\nimport com.ctrip.framework.apollo.portal.entity.po.ServerConfig;\nimport com.ctrip.framework.apollo.portal.repository.ServerConfigRepository;\nimport com.ctrip.framework.apollo.portal.spi.UserInfoHolder;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.security.access.prepost.PreAuthorize;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.Objects;\n\nimport static com.ctrip.framework.apollo.common.utils.RequestPrecondition.checkModel;\n\n/**\n * 配置中心本身需要一些配置,这些配置放在数据库里面\n */\n@RestController\npublic class ServerConfigController {\n\n  @Autowired\n  private ServerConfigRepository serverConfigRepository;\n  @Autowired\n  private UserInfoHolder userInfoHolder;\n\n  @PreAuthorize(value = \"@permissionValidator.isSuperAdmin()\")\n  @RequestMapping(value = \"/server/config\", method = RequestMethod.POST)\n  public ServerConfig createOrUpdate(@RequestBody ServerConfig serverConfig) {\n\n    checkModel(Objects.nonNull(serverConfig));\n    RequestPrecondition.checkArgumentsNotEmpty(serverConfig.getKey(), serverConfig.getValue());\n\n    String modifiedBy = userInfoHolder.getUser().getUserId();\n\n    ServerConfig storedConfig = serverConfigRepository.findByKey(serverConfig.getKey());\n\n    if (Objects.isNull(storedConfig)) {//create\n      serverConfig.setDataChangeCreatedBy(modifiedBy);\n      serverConfig.setDataChangeLastModifiedBy(modifiedBy);\n      return serverConfigRepository.save(serverConfig);\n    } else {//update\n      BeanUtils.copyEntityProperties(serverConfig, storedConfig);\n      storedConfig.setDataChangeLastModifiedBy(modifiedBy);\n      return serverConfigRepository.save(storedConfig);\n    }\n\n  }\n\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/SignInController.java",
    "content": "package com.ctrip.framework.apollo.portal.controller;\n\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RequestParam;\n\n/**\n * @author lepdou 2017-08-30\n */\n@Controller\npublic class SignInController {\n\n  @RequestMapping(value = \"/signin\", method = RequestMethod.GET)\n  public String login(@RequestParam(value = \"error\", required = false) String error,\n                      @RequestParam(value = \"logout\", required = false) String logout) {\n    return \"login.html\";\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/SsoHeartbeatController.java",
    "content": "package com.ctrip.framework.apollo.portal.controller;\n\nimport com.ctrip.framework.apollo.portal.spi.SsoHeartbeatHandler;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\n\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\n/**\n * Since sso auth information has a limited expiry time, so we need to do sso heartbeat to keep the\n * information refreshed when unavailable\n *\n * @author Jason Song(song_s@ctrip.com)\n */\n@Controller\n@RequestMapping(\"/sso_heartbeat\")\npublic class SsoHeartbeatController {\n  @Autowired\n  private SsoHeartbeatHandler handler;\n\n  @RequestMapping(value = \"\", method = RequestMethod.GET)\n  public void heartbeat(HttpServletRequest request, HttpServletResponse response) {\n    handler.doHeartbeat(request, response);\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/UserInfoController.java",
    "content": "package com.ctrip.framework.apollo.portal.controller;\n\nimport com.ctrip.framework.apollo.common.exception.BadRequestException;\nimport com.ctrip.framework.apollo.core.utils.StringUtils;\nimport com.ctrip.framework.apollo.portal.entity.bo.UserInfo;\nimport com.ctrip.framework.apollo.portal.entity.po.UserPO;\nimport com.ctrip.framework.apollo.portal.spi.LogoutHandler;\nimport com.ctrip.framework.apollo.portal.spi.UserInfoHolder;\nimport com.ctrip.framework.apollo.portal.spi.UserService;\nimport com.ctrip.framework.apollo.portal.spi.springsecurity.SpringSecurityUserService;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.security.access.prepost.PreAuthorize;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.io.IOException;\nimport java.util.List;\n\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\n@RestController\npublic class UserInfoController {\n\n  @Autowired\n  private UserInfoHolder userInfoHolder;\n  @Autowired\n  private LogoutHandler logoutHandler;\n\n  @Autowired\n  private UserService userService;\n\n\n  @PreAuthorize(value = \"@permissionValidator.isSuperAdmin()\")\n  @RequestMapping(value = \"/users\", method = RequestMethod.POST)\n  public void createOrUpdateUser(@RequestBody UserPO user) {\n    if (StringUtils.isContainEmpty(user.getUsername(), user.getPassword())) {\n      throw new BadRequestException(\"Username and password can not be empty.\");\n    }\n\n    if (userService instanceof SpringSecurityUserService) {\n      ((SpringSecurityUserService) userService).createOrUpdate(user);\n    } else {\n      throw new UnsupportedOperationException(\"Create or update user operation is unsupported\");\n    }\n\n  }\n\n  @RequestMapping(value = \"/user\", method = RequestMethod.GET)\n  public UserInfo getCurrentUserName() {\n    return userInfoHolder.getUser();\n  }\n\n  @RequestMapping(value = \"/user/logout\", method = RequestMethod.GET)\n  public void logout(HttpServletRequest request, HttpServletResponse response) throws IOException {\n    logoutHandler.logout(request, response);\n  }\n\n  @RequestMapping(value = \"/users\", method = RequestMethod.GET)\n  public List<UserInfo> searchUsersByKeyword(@RequestParam(value = \"keyword\") String keyword,\n                                             @RequestParam(value = \"offset\", defaultValue = \"0\") int offset,\n                                             @RequestParam(value = \"limit\", defaultValue = \"10\") int limit) {\n    return userService.searchUsers(keyword, offset, limit);\n  }\n\n  @RequestMapping(value = \"/users/{userId}\", method = RequestMethod.GET)\n  public UserInfo getUserByUserId(@PathVariable String userId) {\n    return userService.findByUserId(userId);\n  }\n\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/bo/Email.java",
    "content": "package com.ctrip.framework.apollo.portal.entity.bo;\n\nimport java.util.List;\n\npublic class Email {\n\n  private String senderEmailAddress;\n  private List<String> recipients;\n  private String subject;\n  private String body;\n\n  public String getSenderEmailAddress() {\n    return senderEmailAddress;\n  }\n\n  public void setSenderEmailAddress(String senderEmailAddress) {\n    this.senderEmailAddress = senderEmailAddress;\n  }\n\n  public List<String> getRecipients() {\n    return recipients;\n  }\n\n  public void setRecipients(List<String> recipients) {\n    this.recipients = recipients;\n  }\n\n  public String getSubject() {\n    return subject;\n  }\n\n  public void setSubject(String subject) {\n    this.subject = subject;\n  }\n\n  public String getBody() {\n    return body;\n  }\n\n  public void setBody(String body) {\n    this.body = body;\n  }\n\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/bo/ItemBO.java",
    "content": "package com.ctrip.framework.apollo.portal.entity.bo;\n\nimport com.ctrip.framework.apollo.common.dto.ItemDTO;\n\npublic  class ItemBO {\n    private ItemDTO item;\n    private boolean isModified;\n    private boolean isDeleted;\n    private String oldValue;\n    private String newValue;\n\n    public ItemDTO getItem() {\n      return item;\n    }\n\n    public void setItem(ItemDTO item) {\n      this.item = item;\n    }\n\n    public boolean isDeleted() {\n      return isDeleted;\n    }\n\n    public void setDeleted(boolean deleted) {\n      isDeleted = deleted;\n    }\n\n    public boolean isModified() {\n      return isModified;\n    }\n\n    public void setModified(boolean isModified) {\n      this.isModified = isModified;\n    }\n\n    public String getOldValue() {\n      return oldValue;\n    }\n\n    public void setOldValue(String oldValue) {\n      this.oldValue = oldValue;\n    }\n\n    public String getNewValue() {\n      return newValue;\n    }\n\n    public void setNewValue(String newValue) {\n      this.newValue = newValue;\n    }\n\n\n  }\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/bo/KVEntity.java",
    "content": "package com.ctrip.framework.apollo.portal.entity.bo;\n\npublic class KVEntity {\n\n  private String key;\n  private String value;\n\n  public KVEntity(String key, String value) {\n    this.key = key;\n    this.value = value;\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 String getValue() {\n    return value;\n  }\n\n  public void setValue(String value) {\n    this.value = value;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/bo/NamespaceBO.java",
    "content": "package com.ctrip.framework.apollo.portal.entity.bo;\n\nimport com.ctrip.framework.apollo.common.dto.NamespaceDTO;\n\nimport java.util.List;\n\npublic class NamespaceBO {\n  private NamespaceDTO baseInfo;\n  private int itemModifiedCnt;\n  private List<ItemBO> items;\n  private String format;\n  private boolean isPublic;\n  private String parentAppId;\n  private String comment;\n\n\n  public NamespaceDTO getBaseInfo() {\n    return baseInfo;\n  }\n\n  public void setBaseInfo(NamespaceDTO baseInfo) {\n    this.baseInfo = baseInfo;\n  }\n\n  public int getItemModifiedCnt() {\n    return itemModifiedCnt;\n  }\n\n  public void setItemModifiedCnt(int itemModifiedCnt) {\n    this.itemModifiedCnt = itemModifiedCnt;\n  }\n\n  public List<ItemBO> getItems() {\n    return items;\n  }\n\n  public void setItems(List<ItemBO> items) {\n    this.items = items;\n  }\n\n  public String getFormat() {\n    return format;\n  }\n\n  public void setFormat(String format) {\n    this.format = format;\n  }\n\n  public boolean isPublic() {\n    return isPublic;\n  }\n\n  public void setPublic(boolean aPublic) {\n    isPublic = aPublic;\n  }\n\n  public String getParentAppId() {\n    return parentAppId;\n  }\n\n  public void setParentAppId(String parentAppId) {\n    this.parentAppId = parentAppId;\n  }\n\n  public String getComment() {\n    return comment;\n  }\n\n  public void setComment(String comment) {\n    this.comment = comment;\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/bo/ReleaseBO.java",
    "content": "package com.ctrip.framework.apollo.portal.entity.bo;\n\nimport com.ctrip.framework.apollo.common.dto.ReleaseDTO;\nimport com.ctrip.framework.apollo.portal.entity.bo.KVEntity;\n\nimport java.util.Set;\n\npublic class ReleaseBO {\n\n  private ReleaseDTO baseInfo;\n\n  private Set<KVEntity> items;\n\n  public ReleaseDTO getBaseInfo() {\n    return baseInfo;\n  }\n\n  public void setBaseInfo(ReleaseDTO baseInfo) {\n    this.baseInfo = baseInfo;\n  }\n\n  public Set<KVEntity> getItems() {\n    return items;\n  }\n\n  public void setItems(Set<KVEntity> items) {\n    this.items = items;\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/bo/ReleaseHistoryBO.java",
    "content": "package com.ctrip.framework.apollo.portal.entity.bo;\n\nimport com.ctrip.framework.apollo.common.entity.EntityPair;\n\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Map;\n\npublic class ReleaseHistoryBO {\n\n  private long id;\n\n  private String appId;\n\n  private String clusterName;\n\n  private String namespaceName;\n\n  private String branchName;\n\n  private String operator;\n\n  private long releaseId;\n\n  private String releaseTitle;\n\n  private String releaseComment;\n\n  private Date releaseTime;\n\n  private String releaseTimeFormatted;\n\n  private List<EntityPair<String>> configuration;\n\n  private long previousReleaseId;\n\n  private int operation;\n\n  private Map<String, Object> operationContext;\n\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 getAppId() {\n    return appId;\n  }\n\n  public void setAppId(String appId) {\n    this.appId = appId;\n  }\n\n  public String getClusterName() {\n    return clusterName;\n  }\n\n  public void setClusterName(String clusterName) {\n    this.clusterName = clusterName;\n  }\n\n  public String getNamespaceName() {\n    return namespaceName;\n  }\n\n  public void setNamespaceName(String namespaceName) {\n    this.namespaceName = namespaceName;\n  }\n\n  public String getBranchName() {\n    return branchName;\n  }\n\n  public void setBranchName(String branchName) {\n    this.branchName = branchName;\n  }\n\n  public long getReleaseId() {\n    return releaseId;\n  }\n\n  public void setReleaseId(long releaseId) {\n    this.releaseId = releaseId;\n  }\n\n  public long getPreviousReleaseId() {\n    return previousReleaseId;\n  }\n\n  public void setPreviousReleaseId(long previousReleaseId) {\n    this.previousReleaseId = previousReleaseId;\n  }\n\n  public int getOperation() {\n    return operation;\n  }\n\n  public void setOperation(int operation) {\n    this.operation = operation;\n  }\n\n  public Map<String, Object> getOperationContext() {\n    return operationContext;\n  }\n\n  public void setOperationContext(Map<String, Object> operationContext) {\n    this.operationContext = operationContext;\n  }\n\n  public String getOperator() {\n    return operator;\n  }\n\n  public void setOperator(String operator) {\n    this.operator = operator;\n  }\n\n  public String getReleaseTitle() {\n    return releaseTitle;\n  }\n\n  public void setReleaseTitle(String releaseTitle) {\n    this.releaseTitle = releaseTitle;\n  }\n\n  public String getReleaseComment() {\n    return releaseComment;\n  }\n\n  public void setReleaseComment(String releaseComment) {\n    this.releaseComment = releaseComment;\n  }\n\n  public Date getReleaseTime() {\n    return releaseTime;\n  }\n\n  public void setReleaseTime(Date releaseTime) {\n    this.releaseTime = releaseTime;\n  }\n\n  public String getReleaseTimeFormatted() {\n    return releaseTimeFormatted;\n  }\n\n  public void setReleaseTimeFormatted(String releaseTimeFormatted) {\n    this.releaseTimeFormatted = releaseTimeFormatted;\n  }\n\n  public List<EntityPair<String>> getConfiguration() {\n    return configuration;\n  }\n\n  public void setConfiguration(\n      List<EntityPair<String>> configuration) {\n    this.configuration = configuration;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/bo/UserInfo.java",
    "content": "package com.ctrip.framework.apollo.portal.entity.bo;\n\npublic class UserInfo {\n\n  private String userId;\n  private String name;\n  private String email;\n\n  public UserInfo() {\n\n  }\n\n  public UserInfo(String userId) {\n    this.userId = userId;\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 String getName() {\n    return name;\n  }\n\n  public void setName(String name) {\n    this.name = name;\n  }\n\n  public String getEmail() {\n    return email;\n  }\n\n  public void setEmail(String email) {\n    this.email = email;\n  }\n\n  @Override\n  public boolean equals(Object o) {\n    if (o instanceof UserInfo) {\n\n      if (o == this){\n        return true;\n      }\n\n      UserInfo anotherUser = (UserInfo) o;\n      return userId.equals(anotherUser.userId);\n    } else {\n      return false;\n    }\n\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/model/AppModel.java",
    "content": "package com.ctrip.framework.apollo.portal.entity.model;\n\n\nimport java.util.Set;\n\npublic class AppModel {\n\n  private String name;\n\n  private String appId;\n\n  private String orgId;\n\n  private String orgName;\n\n  private String ownerName;\n\n  private Set<String> admins;\n\n  public String getName() {\n    return name;\n  }\n\n  public void setName(String name) {\n    this.name = name;\n  }\n\n  public String getAppId() {\n    return appId;\n  }\n\n  public void setAppId(String appId) {\n    this.appId = appId;\n  }\n\n  public String getOrgId() {\n    return orgId;\n  }\n\n  public void setOrgId(String orgId) {\n    this.orgId = orgId;\n  }\n\n  public String getOrgName() {\n    return orgName;\n  }\n\n  public void setOrgName(String orgName) {\n    this.orgName = orgName;\n  }\n\n  public String getOwnerName() {\n    return ownerName;\n  }\n\n  public void setOwnerName(String ownerName) {\n    this.ownerName = ownerName;\n  }\n\n  public Set<String> getAdmins() {\n    return admins;\n  }\n\n  public void setAdmins(Set<String> admins) {\n    this.admins = admins;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/model/NamespaceCreationModel.java",
    "content": "package com.ctrip.framework.apollo.portal.entity.model;\n\nimport com.ctrip.framework.apollo.common.dto.NamespaceDTO;\n\n\npublic class NamespaceCreationModel {\n\n  private String env;\n\n  private NamespaceDTO namespace;\n\n  public String getEnv() {\n    return env;\n  }\n\n  public void setEnv(String env) {\n    this.env = env;\n  }\n\n  public NamespaceDTO getNamespace() {\n    return namespace;\n  }\n\n  public void setNamespace(NamespaceDTO namespace) {\n    this.namespace = namespace;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/model/NamespaceReleaseModel.java",
    "content": "package com.ctrip.framework.apollo.portal.entity.model;\n\n\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.core.utils.StringUtils;\n\npublic class NamespaceReleaseModel implements Verifiable {\n\n  private String appId;\n  private String env;\n  private String clusterName;\n  private String namespaceName;\n  private String releaseTitle;\n  private String releaseComment;\n  private String releasedBy;\n  private boolean isEmergencyPublish;\n\n  @Override\n  public boolean isInvalid() {\n    return StringUtils.isContainEmpty(appId, env, clusterName, namespaceName, releaseTitle);\n  }\n\n  public String getAppId() {\n    return appId;\n  }\n\n  public void setAppId(String appId) {\n    this.appId = appId;\n  }\n\n  public Env getEnv() {\n    return Env.valueOf(env);\n  }\n\n  public void setEnv(String env) {\n    this.env = env;\n  }\n\n  public String getClusterName() {\n    return clusterName;\n  }\n\n  public void setClusterName(String clusterName) {\n    this.clusterName = clusterName;\n  }\n\n  public String getNamespaceName() {\n    return namespaceName;\n  }\n\n  public void setNamespaceName(String namespaceName) {\n    this.namespaceName = namespaceName;\n  }\n\n  public String getReleaseTitle() {\n    return releaseTitle;\n  }\n\n  public void setReleaseTitle(String releaseTitle) {\n    this.releaseTitle = releaseTitle;\n  }\n\n  public String getReleaseComment() {\n    return releaseComment;\n  }\n\n  public void setReleaseComment(String releaseComment) {\n    this.releaseComment = releaseComment;\n  }\n\n  public String getReleasedBy() {\n    return releasedBy;\n  }\n\n  public void setReleasedBy(String releasedBy) {\n    this.releasedBy = releasedBy;\n  }\n\n  public boolean isEmergencyPublish() {\n    return isEmergencyPublish;\n  }\n\n  public void setEmergencyPublish(boolean emergencyPublish) {\n    isEmergencyPublish = emergencyPublish;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/model/NamespaceSyncModel.java",
    "content": "package com.ctrip.framework.apollo.portal.entity.model;\n\nimport com.ctrip.framework.apollo.common.dto.ItemDTO;\nimport com.ctrip.framework.apollo.portal.entity.vo.NamespaceIdentifier;\n\nimport org.springframework.util.CollectionUtils;\n\nimport java.util.List;\n\npublic class NamespaceSyncModel implements Verifiable {\n\n  private List<NamespaceIdentifier> syncToNamespaces;\n  private List<ItemDTO> syncItems;\n\n  @Override\n  public boolean isInvalid() {\n    if (CollectionUtils.isEmpty(syncToNamespaces) || CollectionUtils.isEmpty(syncItems)) {\n      return true;\n    }\n    for (NamespaceIdentifier namespaceIdentifier : syncToNamespaces) {\n      if (namespaceIdentifier.isInvalid()) {\n        return true;\n      }\n    }\n    return false;\n  }\n\n  public List<NamespaceIdentifier> getSyncToNamespaces() {\n    return syncToNamespaces;\n  }\n\n  public void setSyncToNamespaces(List<NamespaceIdentifier> syncToNamespaces) {\n    this.syncToNamespaces = syncToNamespaces;\n  }\n\n  public List<ItemDTO> getSyncItems() {\n    return syncItems;\n  }\n\n  public void setSyncItems(List<ItemDTO> syncItems) {\n    this.syncItems = syncItems;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/model/NamespaceTextModel.java",
    "content": "package com.ctrip.framework.apollo.portal.entity.model;\n\n\nimport com.ctrip.framework.apollo.core.enums.ConfigFileFormat;\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.core.utils.StringUtils;\n\npublic class NamespaceTextModel implements Verifiable {\n\n  private String appId;\n  private String env;\n  private String clusterName;\n  private String namespaceName;\n  private int namespaceId;\n  private String format;\n  private String configText;\n\n\n  @Override\n  public boolean isInvalid() {\n    return StringUtils.isContainEmpty(appId, env, clusterName, namespaceName) || namespaceId <= 0;\n  }\n\n  public String getAppId() {\n    return appId;\n  }\n\n  public void setAppId(String appId) {\n    this.appId = appId;\n  }\n\n  public Env getEnv() {\n    return Env.valueOf(env);\n  }\n\n  public void setEnv(String env) {\n    this.env = env;\n  }\n\n  public String getClusterName() {\n    return clusterName;\n  }\n\n  public void setClusterName(String clusterName) {\n    this.clusterName = clusterName;\n  }\n\n  public String getNamespaceName() {\n    return namespaceName;\n  }\n\n  public void setNamespaceName(String namespaceName) {\n    this.namespaceName = namespaceName;\n  }\n\n  public int getNamespaceId() {\n    return namespaceId;\n  }\n\n  public void setNamespaceId(int namespaceId) {\n    this.namespaceId = namespaceId;\n  }\n\n  public String getConfigText() {\n    return configText;\n  }\n\n  public void setConfigText(String configText) {\n    this.configText = configText;\n  }\n\n  public ConfigFileFormat getFormat() {\n    return ConfigFileFormat.fromString(this.format);\n  }\n\n  public void setFormat(String format) {\n    this.format = format;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/model/Verifiable.java",
    "content": "package com.ctrip.framework.apollo.portal.entity.model;\n\npublic interface Verifiable {\n\n  boolean isInvalid();\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/po/Favorite.java",
    "content": "package com.ctrip.framework.apollo.portal.entity.po;\n\nimport com.ctrip.framework.apollo.common.entity.BaseEntity;\n\nimport org.hibernate.annotations.SQLDelete;\nimport org.hibernate.annotations.Where;\n\nimport javax.persistence.Column;\nimport javax.persistence.Entity;\nimport javax.persistence.Table;\n\n@Entity\n@Table(name = \"Favorite\")\n@SQLDelete(sql = \"Update Favorite set isDeleted = 1 where id = ?\")\n@Where(clause = \"isDeleted = 0\")\npublic class Favorite extends BaseEntity {\n\n  @Column(name = \"AppId\", nullable = false)\n  private String appId;\n\n  @Column(name = \"UserId\", nullable = false)\n  private String userId;\n\n  @Column(name = \"Position\")\n  private long position;\n\n  public String getAppId() {\n    return appId;\n  }\n\n  public void setAppId(String appId) {\n    this.appId = appId;\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 long getPosition() {\n    return position;\n  }\n\n  public void setPosition(long position) {\n    this.position = position;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/po/Permission.java",
    "content": "package com.ctrip.framework.apollo.portal.entity.po;\n\nimport com.ctrip.framework.apollo.common.entity.BaseEntity;\n\nimport org.hibernate.annotations.SQLDelete;\nimport org.hibernate.annotations.Where;\n\nimport javax.persistence.Column;\nimport javax.persistence.Entity;\nimport javax.persistence.Table;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@Entity\n@Table(name = \"Permission\")\n@SQLDelete(sql = \"Update Permission set isDeleted = 1 where id = ?\")\n@Where(clause = \"isDeleted = 0\")\npublic class Permission extends BaseEntity {\n  @Column(name = \"PermissionType\", nullable = false)\n  private String permissionType;\n\n  @Column(name = \"TargetId\", nullable = false)\n  private String targetId;\n\n  public String getPermissionType() {\n    return permissionType;\n  }\n\n  public void setPermissionType(String permissionType) {\n    this.permissionType = permissionType;\n  }\n\n  public String getTargetId() {\n    return targetId;\n  }\n\n  public void setTargetId(String targetId) {\n    this.targetId = targetId;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/po/Role.java",
    "content": "package com.ctrip.framework.apollo.portal.entity.po;\n\nimport com.ctrip.framework.apollo.common.entity.BaseEntity;\n\nimport org.hibernate.annotations.SQLDelete;\nimport org.hibernate.annotations.Where;\n\nimport javax.persistence.Column;\nimport javax.persistence.Entity;\nimport javax.persistence.Table;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@Entity\n@Table(name = \"Role\")\n@SQLDelete(sql = \"Update Role set isDeleted = 1 where id = ?\")\n@Where(clause = \"isDeleted = 0\")\npublic class Role extends BaseEntity {\n  @Column(name = \"RoleName\", nullable = false)\n  private String roleName;\n\n  public String getRoleName() {\n    return roleName;\n  }\n\n  public void setRoleName(String roleName) {\n    this.roleName = roleName;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/po/RolePermission.java",
    "content": "package com.ctrip.framework.apollo.portal.entity.po;\n\nimport com.ctrip.framework.apollo.common.entity.BaseEntity;\n\nimport org.hibernate.annotations.SQLDelete;\nimport org.hibernate.annotations.Where;\n\nimport javax.persistence.Column;\nimport javax.persistence.Entity;\nimport javax.persistence.Table;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@Entity\n@Table(name = \"RolePermission\")\n@SQLDelete(sql = \"Update RolePermission set isDeleted = 1 where id = ?\")\n@Where(clause = \"isDeleted = 0\")\npublic class RolePermission extends BaseEntity {\n  @Column(name = \"RoleId\", nullable = false)\n  private long roleId;\n\n  @Column(name = \"PermissionId\", nullable = false)\n  private long permissionId;\n\n  public long getRoleId() {\n    return roleId;\n  }\n\n  public void setRoleId(long roleId) {\n    this.roleId = roleId;\n  }\n\n  public long getPermissionId() {\n    return permissionId;\n  }\n\n  public void setPermissionId(long permissionId) {\n    this.permissionId = permissionId;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/po/ServerConfig.java",
    "content": "package com.ctrip.framework.apollo.portal.entity.po;\n\nimport com.ctrip.framework.apollo.common.entity.BaseEntity;\n\nimport org.hibernate.annotations.SQLDelete;\nimport org.hibernate.annotations.Where;\n\nimport javax.persistence.Column;\nimport javax.persistence.Entity;\nimport javax.persistence.Table;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@Entity\n@Table(name = \"ServerConfig\")\n@SQLDelete(sql = \"Update ServerConfig set isDeleted = 1 where id = ?\")\n@Where(clause = \"isDeleted = 0\")\npublic class ServerConfig extends BaseEntity {\n  @Column(name = \"Key\", nullable = false)\n  private String key;\n\n  @Column(name = \"Value\", nullable = false)\n  private String value;\n\n  @Column(name = \"Comment\", nullable = false)\n  private String comment;\n\n  public String getKey() {\n    return key;\n  }\n\n  public void setKey(String key) {\n    this.key = key;\n  }\n\n  public String getValue() {\n    return value;\n  }\n\n  public void setValue(String value) {\n    this.value = value;\n  }\n\n  public String getComment() {\n    return comment;\n  }\n\n  public void setComment(String comment) {\n    this.comment = comment;\n  }\n\n  public String toString() {\n    return toStringHelper().add(\"key\", key).add(\"value\", value).add(\"comment\", comment).toString();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/po/UserPO.java",
    "content": "package com.ctrip.framework.apollo.portal.entity.po;\n\nimport com.ctrip.framework.apollo.portal.entity.bo.UserInfo;\n\nimport javax.persistence.Column;\nimport javax.persistence.Entity;\nimport javax.persistence.GeneratedValue;\nimport javax.persistence.Id;\nimport javax.persistence.Table;\n\n/**\n * @author lepdou 2017-04-08\n */\n@Entity\n@Table(name = \"Users\")\npublic class UserPO {\n\n  @Id\n  @GeneratedValue\n  @Column(name = \"Id\")\n  private long id;\n  @Column(name = \"Username\", nullable = false)\n  private String username;\n  @Column(name = \"Password\", nullable = false)\n  private String password;\n  @Column(name = \"Email\", nullable = false)\n  private String email;\n  @Column(name = \"Enabled\", nullable = false)\n  private int enabled;\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 getUsername() {\n    return username;\n  }\n\n  public void setUsername(String username) {\n    this.username = username;\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 getPassword() {\n    return password;\n  }\n\n  public void setPassword(String password) {\n    this.password = password;\n  }\n\n  public int getEnabled() {\n    return enabled;\n  }\n\n  public void setEnabled(int enabled) {\n    this.enabled = enabled;\n  }\n\n  public UserInfo toUserInfo() {\n    UserInfo userInfo = new UserInfo();\n    userInfo.setName(this.getUsername());\n    userInfo.setUserId(this.getUsername());\n    userInfo.setEmail(this.getEmail());\n    return userInfo;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/po/UserRole.java",
    "content": "package com.ctrip.framework.apollo.portal.entity.po;\n\nimport com.ctrip.framework.apollo.common.entity.BaseEntity;\n\nimport org.hibernate.annotations.SQLDelete;\nimport org.hibernate.annotations.Where;\n\nimport javax.persistence.Column;\nimport javax.persistence.Entity;\nimport javax.persistence.Table;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@Entity\n@Table(name = \"UserRole\")\n@SQLDelete(sql = \"Update UserRole set isDeleted = 1 where id = ?\")\n@Where(clause = \"isDeleted = 0\")\npublic class UserRole extends BaseEntity {\n  @Column(name = \"UserId\", nullable = false)\n  private String userId;\n\n  @Column(name = \"RoleId\", nullable = false)\n  private long roleId;\n\n  public String getUserId() {\n    return userId;\n  }\n\n  public void setUserId(String userId) {\n    this.userId = userId;\n  }\n\n  public long getRoleId() {\n    return roleId;\n  }\n\n  public void setRoleId(long roleId) {\n    this.roleId = roleId;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/vo/AppRolesAssignedUsers.java",
    "content": "package com.ctrip.framework.apollo.portal.entity.vo;\n\nimport com.ctrip.framework.apollo.portal.entity.bo.UserInfo;\n\nimport java.util.Set;\n\npublic class AppRolesAssignedUsers {\n\n  private String appId;\n  private Set<UserInfo> masterUsers;\n\n  public String getAppId() {\n    return appId;\n  }\n\n  public void setAppId(String appId) {\n    this.appId = appId;\n  }\n\n  public Set<UserInfo> getMasterUsers() {\n    return masterUsers;\n  }\n\n  public void setMasterUsers(Set<UserInfo> masterUsers) {\n    this.masterUsers = masterUsers;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/vo/Change.java",
    "content": "package com.ctrip.framework.apollo.portal.entity.vo;\n\nimport com.ctrip.framework.apollo.common.entity.EntityPair;\nimport com.ctrip.framework.apollo.portal.entity.bo.KVEntity;\nimport com.ctrip.framework.apollo.portal.enums.ChangeType;\n\npublic class Change {\n\n  private ChangeType type;\n  private EntityPair<KVEntity> entity;\n\n  public Change(ChangeType type, EntityPair<KVEntity> entity) {\n    this.type = type;\n    this.entity = entity;\n  }\n\n  public ChangeType getType() {\n    return type;\n  }\n\n  public void setType(ChangeType type) {\n    this.type = type;\n  }\n\n  public EntityPair<KVEntity> getEntity() {\n    return entity;\n  }\n\n  public void setEntity(EntityPair<KVEntity> entity) {\n    this.entity = entity;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/vo/EnvClusterInfo.java",
    "content": "package com.ctrip.framework.apollo.portal.entity.vo;\n\nimport com.ctrip.framework.apollo.common.dto.ClusterDTO;\nimport com.ctrip.framework.apollo.core.enums.Env;\n\nimport java.util.List;\n\npublic class EnvClusterInfo {\n  private Env env;\n  private List<ClusterDTO> clusters;\n\n  public EnvClusterInfo(Env env) {\n    this.env = env;\n  }\n\n  public Env getEnv() {\n    return env;\n  }\n\n  public void setEnv(Env env) {\n    this.env = env;\n  }\n\n  public List<ClusterDTO> getClusters() {\n    return clusters;\n  }\n\n  public void setClusters(List<ClusterDTO> clusters) {\n    this.clusters = clusters;\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/vo/ItemDiffs.java",
    "content": "package com.ctrip.framework.apollo.portal.entity.vo;\n\nimport com.ctrip.framework.apollo.common.dto.ItemChangeSets;\n\npublic class ItemDiffs {\n  private NamespaceIdentifier namespace;\n  private ItemChangeSets diffs;\n  private String extInfo;\n\n  public ItemDiffs(NamespaceIdentifier namespace) {\n    this.namespace = namespace;\n  }\n\n  public NamespaceIdentifier getNamespace() {\n    return namespace;\n  }\n\n  public void setNamespace(NamespaceIdentifier namespace) {\n    this.namespace = namespace;\n  }\n\n  public ItemChangeSets getDiffs() {\n    return diffs;\n  }\n\n  public void setDiffs(ItemChangeSets diffs) {\n    this.diffs = diffs;\n  }\n\n  public String getExtInfo() {\n    return extInfo;\n  }\n\n  public void setExtInfo(String extInfo) {\n    this.extInfo = extInfo;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/vo/LockInfo.java",
    "content": "package com.ctrip.framework.apollo.portal.entity.vo;\n\npublic class LockInfo {\n\n  private String lockOwner;\n  private boolean isEmergencyPublishAllowed;\n\n  public String getLockOwner() {\n    return lockOwner;\n  }\n\n  public void setLockOwner(String lockOwner) {\n    this.lockOwner = lockOwner;\n  }\n\n  public boolean isEmergencyPublishAllowed() {\n    return isEmergencyPublishAllowed;\n  }\n\n  public void setEmergencyPublishAllowed(boolean emergencyPublishAllowed) {\n    isEmergencyPublishAllowed = emergencyPublishAllowed;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/vo/NamespaceIdentifier.java",
    "content": "package com.ctrip.framework.apollo.portal.entity.vo;\n\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.core.utils.StringUtils;\nimport com.ctrip.framework.apollo.portal.entity.model.Verifiable;\n\npublic class NamespaceIdentifier implements Verifiable {\n  private String appId;\n  private String env;\n  private String clusterName;\n  private String namespaceName;\n\n  public String getAppId() {\n    return appId;\n  }\n\n  public void setAppId(String appId) {\n    this.appId = appId;\n  }\n\n  public Env getEnv() {\n    return Env.valueOf(env);\n  }\n\n  public void setEnv(String env) {\n    this.env = env;\n  }\n\n  public String getClusterName() {\n    return clusterName;\n  }\n\n  public void setClusterName(String clusterName) {\n    this.clusterName = clusterName;\n  }\n\n  public String getNamespaceName() {\n    return namespaceName;\n  }\n\n  public void setNamespaceName(String namespaceName) {\n    this.namespaceName = namespaceName;\n  }\n\n\n  @Override\n  public boolean isInvalid() {\n    return StringUtils.isContainEmpty(env, clusterName, namespaceName);\n  }\n\n  @Override\n  public String toString() {\n    return \"NamespaceIdentifer{\" +\n        \"appId='\" + appId + '\\'' +\n        \", env='\" + env + '\\'' +\n        \", clusterName='\" + clusterName + '\\'' +\n        \", namespaceName='\" + namespaceName + '\\'' +\n        '}';\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/vo/NamespaceRolesAssignedUsers.java",
    "content": "package com.ctrip.framework.apollo.portal.entity.vo;\n\nimport com.ctrip.framework.apollo.portal.entity.bo.UserInfo;\n\nimport java.util.Set;\n\npublic class NamespaceRolesAssignedUsers {\n\n  private String appId;\n  private String namespaceName;\n\n  private Set<UserInfo> modifyRoleUsers;\n  private Set<UserInfo> releaseRoleUsers;\n\n  public String getAppId() {\n    return appId;\n  }\n\n  public void setAppId(String appId) {\n    this.appId = appId;\n  }\n\n  public String getNamespaceName() {\n    return namespaceName;\n  }\n\n  public void setNamespaceName(String namespaceName) {\n    this.namespaceName = namespaceName;\n  }\n\n  public Set<UserInfo> getModifyRoleUsers() {\n    return modifyRoleUsers;\n  }\n\n  public void setModifyRoleUsers(\n      Set<UserInfo> modifyRoleUsers) {\n    this.modifyRoleUsers = modifyRoleUsers;\n  }\n\n  public Set<UserInfo> getReleaseRoleUsers() {\n    return releaseRoleUsers;\n  }\n\n  public void setReleaseRoleUsers(\n      Set<UserInfo> releaseRoleUsers) {\n    this.releaseRoleUsers = releaseRoleUsers;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/vo/Number.java",
    "content": "package com.ctrip.framework.apollo.portal.entity.vo;\n\npublic class Number {\n  private int num;\n\n  public Number(int num){\n    this.num = num;\n  }\n\n  public int getNum() {\n    return num;\n  }\n\n  public void setNum(int num) {\n    this.num = num;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/vo/Organization.java",
    "content": "package com.ctrip.framework.apollo.portal.entity.vo;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class Organization {\n  private String orgId;\n  private String orgName;\n\n  public String getOrgId() {\n    return orgId;\n  }\n\n  public void setOrgId(String orgId) {\n    this.orgId = orgId;\n  }\n\n  public String getOrgName() {\n    return orgName;\n  }\n\n  public void setOrgName(String orgName) {\n    this.orgName = orgName;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/vo/PageSetting.java",
    "content": "package com.ctrip.framework.apollo.portal.entity.vo;\n\npublic class PageSetting {\n\n  private String wikiAddress;\n\n  private boolean canAppAdminCreatePrivateNamespace;\n\n  public String getWikiAddress() {\n    return wikiAddress;\n  }\n\n  public void setWikiAddress(String wikiAddress) {\n    this.wikiAddress = wikiAddress;\n  }\n\n  public boolean isCanAppAdminCreatePrivateNamespace() {\n    return canAppAdminCreatePrivateNamespace;\n  }\n\n  public void setCanAppAdminCreatePrivateNamespace(boolean canAppAdminCreatePrivateNamespace) {\n    this.canAppAdminCreatePrivateNamespace = canAppAdminCreatePrivateNamespace;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/vo/PermissionCondition.java",
    "content": "package com.ctrip.framework.apollo.portal.entity.vo;\n\npublic class PermissionCondition {\n\n  private boolean hasPermission;\n\n  public boolean hasPermission() {\n    return hasPermission;\n  }\n\n  public void setHasPermission(boolean hasPermission) {\n    this.hasPermission = hasPermission;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/vo/ReleaseCompareResult.java",
    "content": "package com.ctrip.framework.apollo.portal.entity.vo;\n\nimport com.ctrip.framework.apollo.common.entity.EntityPair;\nimport com.ctrip.framework.apollo.portal.entity.bo.KVEntity;\nimport com.ctrip.framework.apollo.portal.enums.ChangeType;\n\nimport java.util.LinkedList;\nimport java.util.List;\n\npublic class ReleaseCompareResult {\n\n  private List<Change> changes = new LinkedList<>();\n\n  public void addEntityPair(ChangeType type, KVEntity firstEntity, KVEntity secondEntity) {\n    changes.add(new Change(type, new EntityPair<>(firstEntity, secondEntity)));\n  }\n\n  public boolean hasContent(){\n    return !changes.isEmpty();\n  }\n\n  public List<Change> getChanges() {\n    return changes;\n  }\n\n  public void setChanges(List<Change> changes) {\n    this.changes = changes;\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/enums/ChangeType.java",
    "content": "package com.ctrip.framework.apollo.portal.enums;\n\npublic enum ChangeType {\n  ADDED, MODIFIED, DELETED\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/listener/AppCreationEvent.java",
    "content": "package com.ctrip.framework.apollo.portal.listener;\n\nimport com.google.common.base.Preconditions;\n\nimport com.ctrip.framework.apollo.common.entity.App;\n\nimport org.springframework.context.ApplicationEvent;\n\npublic class AppCreationEvent extends ApplicationEvent {\n\n  public AppCreationEvent(Object source) {\n    super(source);\n  }\n\n  public App getApp() {\n    Preconditions.checkState(source != null);\n    return (App) this.source;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/listener/AppInfoChangedEvent.java",
    "content": "package com.ctrip.framework.apollo.portal.listener;\n\nimport com.google.common.base.Preconditions;\n\nimport com.ctrip.framework.apollo.common.entity.App;\n\nimport org.springframework.context.ApplicationEvent;\n\npublic class AppInfoChangedEvent extends ApplicationEvent{\n\n  public AppInfoChangedEvent(Object source) {\n    super(source);\n  }\n\n  public App getApp() {\n    Preconditions.checkState(source != null);\n    return (App) this.source;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/listener/AppInfoChangedListener.java",
    "content": "package com.ctrip.framework.apollo.portal.listener;\n\nimport com.ctrip.framework.apollo.common.dto.AppDTO;\nimport com.ctrip.framework.apollo.common.utils.BeanUtils;\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.portal.api.AdminServiceAPI;\nimport com.ctrip.framework.apollo.portal.component.PortalSettings;\nimport com.ctrip.framework.apollo.tracer.Tracer;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.event.EventListener;\nimport org.springframework.stereotype.Component;\n\nimport java.util.List;\n\n@Component\npublic class AppInfoChangedListener {\n  private static final Logger logger = LoggerFactory.getLogger(AppInfoChangedListener.class);\n\n  @Autowired\n  private AdminServiceAPI.AppAPI appAPI;\n  @Autowired\n  private PortalSettings portalSettings;\n\n\n  @EventListener\n  public void onAppInfoChange(AppInfoChangedEvent event) {\n    AppDTO appDTO = BeanUtils.transfrom(AppDTO.class, event.getApp());\n    String appId = appDTO.getAppId();\n\n    List<Env> envs = portalSettings.getActiveEnvs();\n    for (Env env : envs) {\n      try {\n        appAPI.updateApp(env, appDTO);\n      } catch (Throwable e) {\n        logger.error(\"Update app's info failed. Env = {}, AppId = {}\", env, appId, e);\n        Tracer.logError(String.format(\"Update app's info failed. Env = %s, AppId = %s\", env, appId), e);\n      }\n    }\n\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/listener/AppNamespaceCreationEvent.java",
    "content": "package com.ctrip.framework.apollo.portal.listener;\n\nimport com.google.common.base.Preconditions;\n\nimport com.ctrip.framework.apollo.common.entity.AppNamespace;\n\nimport org.springframework.context.ApplicationEvent;\n\npublic class AppNamespaceCreationEvent extends ApplicationEvent {\n\n  public AppNamespaceCreationEvent(Object source) {\n    super(source);\n  }\n\n  public AppNamespace getAppNamespace() {\n    Preconditions.checkState(source != null);\n    return (AppNamespace) this.source;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/listener/ConfigPublishEvent.java",
    "content": "package com.ctrip.framework.apollo.portal.listener;\n\nimport com.ctrip.framework.apollo.core.enums.Env;\n\nimport org.springframework.context.ApplicationEvent;\n\npublic class ConfigPublishEvent extends ApplicationEvent {\n\n  private ConfigPublishInfo configPublishInfo;\n\n  public ConfigPublishEvent(Object source) {\n    super(source);\n    configPublishInfo = (ConfigPublishInfo) source;\n  }\n\n  public static ConfigPublishEvent instance() {\n    ConfigPublishInfo info = new ConfigPublishInfo();\n    return new ConfigPublishEvent(info);\n  }\n\n  public ConfigPublishInfo getConfigPublishInfo(){\n    return configPublishInfo;\n  }\n\n  public ConfigPublishEvent withAppId(String appId) {\n    configPublishInfo.setAppId(appId);\n    return this;\n  }\n\n  public ConfigPublishEvent withCluster(String clusterName) {\n    configPublishInfo.setClusterName(clusterName);\n    return this;\n  }\n\n  public ConfigPublishEvent withNamespace(String namespaceName) {\n    configPublishInfo.setNamespaceName(namespaceName);\n    return this;\n  }\n\n  public ConfigPublishEvent withReleaseId(long releaseId){\n    configPublishInfo.setReleaseId(releaseId);\n    return this;\n  }\n\n  public ConfigPublishEvent withPreviousReleaseId(long previousReleaseId){\n    configPublishInfo.setPreviousReleaseId(previousReleaseId);\n    return this;\n  }\n\n  public ConfigPublishEvent setNormalPublishEvent(boolean isNormalPublishEvent) {\n    configPublishInfo.setNormalPublishEvent(isNormalPublishEvent);\n    return this;\n  }\n\n  public ConfigPublishEvent setGrayPublishEvent(boolean isGrayPublishEvent) {\n    configPublishInfo.setGrayPublishEvent(isGrayPublishEvent);\n    return this;\n  }\n\n  public ConfigPublishEvent setRollbackEvent(boolean isRollbackEvent) {\n    configPublishInfo.setRollbackEvent(isRollbackEvent);\n    return this;\n  }\n\n  public ConfigPublishEvent setMergeEvent(boolean isMergeEvent) {\n    configPublishInfo.setMergeEvent(isMergeEvent);\n    return this;\n  }\n\n  public ConfigPublishEvent setEnv(Env env) {\n    configPublishInfo.setEnv(env);\n    return this;\n  }\n\n\n  public static class ConfigPublishInfo {\n\n    private Env env;\n    private String appId;\n    private String clusterName;\n    private String namespaceName;\n    private long releaseId;\n    private long previousReleaseId;\n    private boolean isRollbackEvent;\n    private boolean isMergeEvent;\n    private boolean isNormalPublishEvent;\n    private boolean isGrayPublishEvent;\n\n    public Env getEnv() {\n      return env;\n    }\n\n    public void setEnv(Env env) {\n      this.env = env;\n    }\n\n    public String getAppId() {\n      return appId;\n    }\n\n    public void setAppId(String appId) {\n      this.appId = appId;\n    }\n\n    public String getClusterName() {\n      return clusterName;\n    }\n\n    public void setClusterName(String clusterName) {\n      this.clusterName = clusterName;\n    }\n\n    public String getNamespaceName() {\n      return namespaceName;\n    }\n\n    public void setNamespaceName(String namespaceName) {\n      this.namespaceName = namespaceName;\n    }\n\n    public long getReleaseId() {\n      return releaseId;\n    }\n\n    public void setReleaseId(long releaseId) {\n      this.releaseId = releaseId;\n    }\n\n    public long getPreviousReleaseId() {\n      return previousReleaseId;\n    }\n\n    public void setPreviousReleaseId(long previousReleaseId) {\n      this.previousReleaseId = previousReleaseId;\n    }\n\n    public boolean isRollbackEvent() {\n      return isRollbackEvent;\n    }\n\n    public void setRollbackEvent(boolean rollbackEvent) {\n      isRollbackEvent = rollbackEvent;\n    }\n\n    public boolean isMergeEvent() {\n      return isMergeEvent;\n    }\n\n    public void setMergeEvent(boolean mergeEvent) {\n      isMergeEvent = mergeEvent;\n    }\n\n    public boolean isNormalPublishEvent() {\n      return isNormalPublishEvent;\n    }\n\n    public void setNormalPublishEvent(boolean normalPublishEvent) {\n      isNormalPublishEvent = normalPublishEvent;\n    }\n\n    public boolean isGrayPublishEvent() {\n      return isGrayPublishEvent;\n    }\n\n    public void setGrayPublishEvent(boolean grayPublishEvent) {\n      isGrayPublishEvent = grayPublishEvent;\n    }\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/listener/ConfigPublishListener.java",
    "content": "package com.ctrip.framework.apollo.portal.listener;\n\nimport com.ctrip.framework.apollo.common.constants.ReleaseOperation;\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.core.utils.ApolloThreadFactory;\nimport com.ctrip.framework.apollo.portal.component.config.PortalConfig;\nimport com.ctrip.framework.apollo.portal.component.emailbuilder.GrayPublishEmailBuilder;\nimport com.ctrip.framework.apollo.portal.component.emailbuilder.MergeEmailBuilder;\nimport com.ctrip.framework.apollo.portal.component.emailbuilder.NormalPublishEmailBuilder;\nimport com.ctrip.framework.apollo.portal.component.emailbuilder.RollbackEmailBuilder;\nimport com.ctrip.framework.apollo.portal.entity.bo.Email;\nimport com.ctrip.framework.apollo.portal.entity.bo.ReleaseHistoryBO;\nimport com.ctrip.framework.apollo.portal.service.ReleaseHistoryService;\nimport com.ctrip.framework.apollo.portal.spi.EmailService;\nimport com.ctrip.framework.apollo.portal.spi.MQService;\nimport com.ctrip.framework.apollo.tracer.Tracer;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.event.EventListener;\nimport org.springframework.stereotype.Component;\n\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\n\nimport javax.annotation.PostConstruct;\n\n@Component\npublic class ConfigPublishListener {\n\n  @Autowired\n  private ReleaseHistoryService releaseHistoryService;\n  @Autowired\n  private EmailService emailService;\n  @Autowired\n  private NormalPublishEmailBuilder normalPublishEmailBuilder;\n  @Autowired\n  private GrayPublishEmailBuilder grayPublishEmailBuilder;\n  @Autowired\n  private RollbackEmailBuilder rollbackEmailBuilder;\n  @Autowired\n  private MergeEmailBuilder mergeEmailBuilder;\n  @Autowired\n  private PortalConfig portalConfig;\n  @Autowired\n  private MQService mqService;\n\n  private ExecutorService executorService;\n\n  @PostConstruct\n  public void init() {\n    executorService = Executors.newSingleThreadExecutor(ApolloThreadFactory.create(\"ConfigPublishNotify\", true));\n  }\n\n  @EventListener\n  public void onConfigPublish(ConfigPublishEvent event) {\n    executorService.submit(new ConfigPublishNotifyTask(event.getConfigPublishInfo()));\n  }\n\n\n  private class ConfigPublishNotifyTask implements Runnable {\n\n    private ConfigPublishEvent.ConfigPublishInfo publishInfo;\n\n    ConfigPublishNotifyTask(ConfigPublishEvent.ConfigPublishInfo publishInfo) {\n      this.publishInfo = publishInfo;\n    }\n\n    @Override\n    public void run() {\n      ReleaseHistoryBO releaseHistory = getReleaseHistory();\n      if (releaseHistory == null) {\n        Tracer.logError(\"Load release history failed\", null);\n        return;\n      }\n\n      sendPublishEmail(releaseHistory);\n\n      sendPublishMsg(releaseHistory);\n    }\n\n    private ReleaseHistoryBO getReleaseHistory() {\n      Env env = publishInfo.getEnv();\n\n      int operation = publishInfo.isMergeEvent() ? ReleaseOperation.GRAY_RELEASE_MERGE_TO_MASTER :\n                      publishInfo.isRollbackEvent() ? ReleaseOperation.ROLLBACK :\n                      publishInfo.isNormalPublishEvent() ? ReleaseOperation.NORMAL_RELEASE :\n                      publishInfo.isGrayPublishEvent() ? ReleaseOperation.GRAY_RELEASE : -1;\n\n      if (operation == -1) {\n        return null;\n      }\n\n      if (publishInfo.isRollbackEvent()) {\n        return releaseHistoryService\n            .findLatestByPreviousReleaseIdAndOperation(env, publishInfo.getPreviousReleaseId(), operation);\n      } else {\n        return releaseHistoryService.findLatestByReleaseIdAndOperation(env, publishInfo.getReleaseId(), operation);\n      }\n\n    }\n\n    private void sendPublishEmail(ReleaseHistoryBO releaseHistory) {\n      Env env = publishInfo.getEnv();\n\n      if (!portalConfig.emailSupportedEnvs().contains(env)) {\n        return;\n      }\n\n      int realOperation = releaseHistory.getOperation();\n\n      Email email = null;\n      try {\n        email = buildEmail(env, releaseHistory, realOperation);\n      } catch (Throwable e) {\n        Tracer.logError(\"build email failed.\", e);\n      }\n\n      if (email != null) {\n        emailService.send(email);\n      }\n    }\n\n    private void sendPublishMsg(ReleaseHistoryBO releaseHistory) {\n      mqService.sendPublishMsg(publishInfo.getEnv(), releaseHistory);\n    }\n\n    private Email buildEmail(Env env, ReleaseHistoryBO releaseHistory, int operation) {\n      switch (operation) {\n        case ReleaseOperation.GRAY_RELEASE: {\n          return grayPublishEmailBuilder.build(env, releaseHistory);\n        }\n        case ReleaseOperation.NORMAL_RELEASE: {\n          return normalPublishEmailBuilder.build(env, releaseHistory);\n        }\n        case ReleaseOperation.ROLLBACK: {\n          return rollbackEmailBuilder.build(env, releaseHistory);\n        }\n        case ReleaseOperation.GRAY_RELEASE_MERGE_TO_MASTER: {\n          return mergeEmailBuilder.build(env, releaseHistory);\n        }\n        default:\n          return null;\n      }\n    }\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/listener/CreationListener.java",
    "content": "package com.ctrip.framework.apollo.portal.listener;\n\nimport com.ctrip.framework.apollo.common.dto.AppDTO;\nimport com.ctrip.framework.apollo.common.dto.AppNamespaceDTO;\nimport com.ctrip.framework.apollo.common.utils.BeanUtils;\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.portal.api.AdminServiceAPI;\nimport com.ctrip.framework.apollo.portal.component.PortalSettings;\nimport com.ctrip.framework.apollo.tracer.Tracer;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.event.EventListener;\nimport org.springframework.stereotype.Component;\n\nimport java.util.List;\n\n@Component\npublic class CreationListener {\n\n  private static Logger logger = LoggerFactory.getLogger(CreationListener.class);\n\n  @Autowired\n  private PortalSettings portalSettings;\n  @Autowired\n  private AdminServiceAPI.AppAPI appAPI;\n  @Autowired\n  private AdminServiceAPI.NamespaceAPI namespaceAPI;\n\n  @EventListener\n  public void onAppCreationEvent(AppCreationEvent event) {\n    AppDTO appDTO = BeanUtils.transfrom(AppDTO.class, event.getApp());\n    List<Env> envs = portalSettings.getActiveEnvs();\n    for (Env env : envs) {\n      try {\n        appAPI.createApp(env, appDTO);\n      } catch (Throwable e) {\n        logger.error(\"Create app failed. appId = {}, env = {})\", appDTO.getAppId(), env, e);\n        Tracer.logError(String.format(\"Create app failed. appId = %s, env = %s\", appDTO.getAppId(), env), e);\n      }\n    }\n  }\n\n  @EventListener\n  public void onAppNamespaceCreationEvent(AppNamespaceCreationEvent event) {\n    AppNamespaceDTO appNamespace = BeanUtils.transfrom(AppNamespaceDTO.class, event.getAppNamespace());\n    List<Env> envs = portalSettings.getActiveEnvs();\n    for (Env env : envs) {\n      try {\n        namespaceAPI.createAppNamespace(env, appNamespace);\n      } catch (Throwable e) {\n        logger.error(\"Create appNamespace failed. appId = {}, env = {}\", appNamespace.getAppId(), env, e);\n        Tracer.logError(String.format(\"Create appNamespace failed. appId = %s, env = %s\", appNamespace.getAppId(), env), e);\n      }\n    }\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/AppNamespaceRepository.java",
    "content": "package com.ctrip.framework.apollo.portal.repository;\n\nimport com.ctrip.framework.apollo.common.entity.AppNamespace;\n\nimport org.springframework.data.repository.PagingAndSortingRepository;\n\nimport java.util.List;\n\npublic interface AppNamespaceRepository extends PagingAndSortingRepository<AppNamespace, Long> {\n\n  AppNamespace findByAppIdAndName(String appId, String namespaceName);\n\n  AppNamespace findByName(String namespaceName);\n\n  AppNamespace findByNameAndIsPublic(String namespaceName, boolean isPublic);\n\n  List<AppNamespace> findByIsPublicTrue();\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/AppRepository.java",
    "content": "package com.ctrip.framework.apollo.portal.repository;\n\nimport com.ctrip.framework.apollo.common.entity.App;\n\nimport org.springframework.data.domain.Pageable;\nimport org.springframework.data.repository.PagingAndSortingRepository;\n\nimport java.util.List;\nimport java.util.Set;\n\n\npublic interface AppRepository extends PagingAndSortingRepository<App, Long> {\n\n  App findByAppId(String appId);\n\n  List<App> findByOwnerName(String ownerName, Pageable page);\n\n  List<App> findByAppIdIn(Set<String> appIds);\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/FavoriteRepository.java",
    "content": "package com.ctrip.framework.apollo.portal.repository;\n\nimport com.ctrip.framework.apollo.portal.entity.po.Favorite;\n\nimport org.springframework.data.domain.Pageable;\nimport org.springframework.data.repository.PagingAndSortingRepository;\n\nimport java.util.List;\n\npublic interface FavoriteRepository extends PagingAndSortingRepository<Favorite, Long> {\n\n  List<Favorite> findByUserIdOrderByPositionAscDataChangeCreatedTimeAsc(String userId, Pageable page);\n\n  List<Favorite> findByAppIdOrderByPositionAscDataChangeCreatedTimeAsc(String appId, Pageable page);\n\n  Favorite findFirstByUserIdOrderByPositionAscDataChangeCreatedTimeAsc(String userId);\n\n  Favorite findByUserIdAndAppId(String userId, String appId);\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/PermissionRepository.java",
    "content": "package com.ctrip.framework.apollo.portal.repository;\n\nimport com.ctrip.framework.apollo.portal.entity.po.Permission;\n\nimport org.springframework.data.repository.PagingAndSortingRepository;\n\nimport java.util.Collection;\nimport java.util.List;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic interface PermissionRepository extends PagingAndSortingRepository<Permission, Long> {\n  /**\n   * find permission by permission type and targetId\n   */\n  Permission findTopByPermissionTypeAndTargetId(String permissionType, String targetId);\n\n  /**\n   * find permissions by permission types and targetId\n   */\n  List<Permission> findByPermissionTypeInAndTargetId(Collection<String> permissionTypes,\n                                                     String targetId);\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/RolePermissionRepository.java",
    "content": "package com.ctrip.framework.apollo.portal.repository;\n\nimport com.ctrip.framework.apollo.portal.entity.po.RolePermission;\n\nimport org.springframework.data.repository.PagingAndSortingRepository;\n\nimport java.util.Collection;\nimport java.util.List;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic interface RolePermissionRepository extends PagingAndSortingRepository<RolePermission, Long> {\n\n  /**\n   * find role permissions by role ids\n   */\n  List<RolePermission> findByRoleIdIn(Collection<Long> roleId);\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/RoleRepository.java",
    "content": "package com.ctrip.framework.apollo.portal.repository;\n\nimport com.ctrip.framework.apollo.portal.entity.po.Role;\n\nimport org.springframework.data.repository.PagingAndSortingRepository;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic interface RoleRepository extends PagingAndSortingRepository<Role, Long> {\n  /**\n   * find role by role name\n   */\n  Role findTopByRoleName(String roleName);\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/ServerConfigRepository.java",
    "content": "package com.ctrip.framework.apollo.portal.repository;\n\n\nimport com.ctrip.framework.apollo.portal.entity.po.ServerConfig;\n\nimport org.springframework.data.repository.PagingAndSortingRepository;\n\npublic interface ServerConfigRepository extends PagingAndSortingRepository<ServerConfig, Long> {\n  ServerConfig findByKey(String key);\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/UserRepository.java",
    "content": "package com.ctrip.framework.apollo.portal.repository;\n\nimport com.ctrip.framework.apollo.portal.entity.po.UserPO;\n\nimport org.springframework.data.repository.PagingAndSortingRepository;\n\nimport java.util.List;\n\n/**\n * @author lepdou 2017-04-08\n */\npublic interface UserRepository extends PagingAndSortingRepository<UserPO, Long> {\n\n  List<UserPO> findFirst20ByEnabled(int enabled);\n\n  List<UserPO> findByUsernameLikeAndEnabled(String username, int enabled);\n\n  UserPO findByUsername(String username);\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/UserRoleRepository.java",
    "content": "package com.ctrip.framework.apollo.portal.repository;\n\nimport com.ctrip.framework.apollo.portal.entity.po.UserRole;\n\nimport org.springframework.data.repository.PagingAndSortingRepository;\n\nimport java.util.Collection;\nimport java.util.List;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic interface UserRoleRepository extends PagingAndSortingRepository<UserRole, Long> {\n  /**\n   * find user roles by userId\n   */\n  List<UserRole> findByUserId(String userId);\n\n  /**\n   * find user roles by roleId\n   */\n  List<UserRole> findByRoleId(long roleId);\n\n  /**\n   * find user roles by userIds and roleId\n   */\n  List<UserRole> findByUserIdInAndRoleId(Collection<String> userId, long roleId);\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/AppNamespaceService.java",
    "content": "package com.ctrip.framework.apollo.portal.service;\n\nimport com.ctrip.framework.apollo.common.entity.App;\nimport com.ctrip.framework.apollo.common.entity.AppNamespace;\nimport com.ctrip.framework.apollo.common.exception.BadRequestException;\nimport com.ctrip.framework.apollo.common.exception.ServiceException;\nimport com.ctrip.framework.apollo.core.ConfigConsts;\nimport com.ctrip.framework.apollo.core.enums.ConfigFileFormat;\nimport com.ctrip.framework.apollo.core.utils.StringUtils;\nimport com.ctrip.framework.apollo.portal.repository.AppNamespaceRepository;\nimport com.ctrip.framework.apollo.portal.spi.UserInfoHolder;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\nimport java.util.List;\nimport java.util.Objects;\n\n@Service\npublic class AppNamespaceService {\n\n  @Autowired\n  private UserInfoHolder userInfoHolder;\n  @Autowired\n  private AppNamespaceRepository appNamespaceRepository;\n  @Autowired\n  private RoleInitializationService roleInitializationService;\n  @Autowired\n  private AppService appService;\n\n  /**\n   * 公共的app ns,能被其它项目关联到的app ns\n   */\n  public List<AppNamespace> findPublicAppNamespaces() {\n    return appNamespaceRepository.findByIsPublicTrue();\n  }\n\n  public AppNamespace findPublicAppNamespace(String namespaceName) {\n    return appNamespaceRepository.findByNameAndIsPublic(namespaceName, true);\n  }\n\n  public AppNamespace findByAppIdAndName(String appId, String namespaceName) {\n    return appNamespaceRepository.findByAppIdAndName(appId, namespaceName);\n  }\n\n  @Transactional\n  public void createDefaultAppNamespace(String appId) {\n    if (!isAppNamespaceNameUnique(appId, ConfigConsts.NAMESPACE_APPLICATION)) {\n      throw new BadRequestException(String.format(\"App already has application namespace. AppId = %s\", appId));\n    }\n\n    AppNamespace appNs = new AppNamespace();\n    appNs.setAppId(appId);\n    appNs.setName(ConfigConsts.NAMESPACE_APPLICATION);\n    appNs.setComment(\"default app namespace\");\n    appNs.setFormat(ConfigFileFormat.Properties.getValue());\n    String userId = userInfoHolder.getUser().getUserId();\n    appNs.setDataChangeCreatedBy(userId);\n    appNs.setDataChangeLastModifiedBy(userId);\n\n    appNamespaceRepository.save(appNs);\n  }\n\n  public boolean isAppNamespaceNameUnique(String appId, String namespaceName) {\n    Objects.requireNonNull(appId, \"AppId must not be null\");\n    Objects.requireNonNull(namespaceName, \"Namespace must not be null\");\n    return Objects.isNull(appNamespaceRepository.findByAppIdAndName(appId, namespaceName));\n  }\n\n  @Transactional\n  public AppNamespace createAppNamespaceInLocal(AppNamespace appNamespace) {\n    String appId = appNamespace.getAppId();\n\n    //add app org id as prefix\n    App app = appService.load(appId);\n    if (app == null) {\n      throw new BadRequestException(\"App not exist. AppId = \" + appId);\n    }\n\n    StringBuilder appNamespaceName = new StringBuilder();\n    //add prefix postfix\n    appNamespaceName\n        .append(appNamespace.isPublic() ? app.getOrgId() + \".\" : \"\")\n        .append(appNamespace.getName())\n        .append(appNamespace.formatAsEnum() == ConfigFileFormat.Properties ? \"\" : \".\" + appNamespace.getFormat());\n    appNamespace.setName(appNamespaceName.toString());\n\n    if (appNamespace.getComment() == null) {\n      appNamespace.setComment(\"\");\n    }\n\n    if (!ConfigFileFormat.isValidFormat(appNamespace.getFormat())) {\n     throw new BadRequestException(\"Invalid namespace format. format must be properties、json、yaml、yml、xml\");\n    }\n\n    String operator = appNamespace.getDataChangeCreatedBy();\n    if (StringUtils.isEmpty(operator)) {\n      operator = userInfoHolder.getUser().getUserId();\n      appNamespace.setDataChangeCreatedBy(operator);\n    }\n\n    appNamespace.setDataChangeLastModifiedBy(operator);\n\n    // unique check\n    if (appNamespace.isPublic() && findPublicAppNamespace(appNamespace.getName()) != null) {\n      throw new BadRequestException(appNamespace.getName() + \"已存在\");\n    }\n\n    if (!appNamespace.isPublic() &&\n        appNamespaceRepository.findByAppIdAndName(appNamespace.getAppId(), appNamespace.getName()) != null) {\n      throw new BadRequestException(appNamespace.getName() + \"已存在\");\n    }\n\n    AppNamespace createdAppNamespace = appNamespaceRepository.save(appNamespace);\n\n    roleInitializationService.initNamespaceRoles(appNamespace.getAppId(), appNamespace.getName(), operator);\n\n    return createdAppNamespace;\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/AppService.java",
    "content": "package com.ctrip.framework.apollo.portal.service;\n\nimport com.google.common.collect.Lists;\n\nimport com.ctrip.framework.apollo.common.dto.AppDTO;\nimport com.ctrip.framework.apollo.common.entity.App;\nimport com.ctrip.framework.apollo.common.exception.BadRequestException;\nimport com.ctrip.framework.apollo.common.utils.BeanUtils;\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.portal.api.AdminServiceAPI;\nimport com.ctrip.framework.apollo.portal.constant.TracerEventType;\nimport com.ctrip.framework.apollo.portal.entity.bo.UserInfo;\nimport com.ctrip.framework.apollo.portal.entity.vo.EnvClusterInfo;\nimport com.ctrip.framework.apollo.portal.repository.AppRepository;\nimport com.ctrip.framework.apollo.portal.spi.UserInfoHolder;\nimport com.ctrip.framework.apollo.portal.spi.UserService;\nimport com.ctrip.framework.apollo.tracer.Tracer;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.data.domain.Pageable;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Set;\n\n@Service\npublic class AppService {\n\n  @Autowired\n  private UserInfoHolder userInfoHolder;\n  @Autowired\n  private AdminServiceAPI.AppAPI appAPI;\n  @Autowired\n  private AppRepository appRepository;\n  @Autowired\n  private ClusterService clusterService;\n  @Autowired\n  private AppNamespaceService appNamespaceService;\n  @Autowired\n  private RoleInitializationService roleInitializationService;\n  @Autowired\n  private UserService userService;\n\n\n  public List<App> findAll() {\n    Iterable<App> apps = appRepository.findAll();\n    if (apps == null) {\n      return Collections.emptyList();\n    }\n    return Lists.newArrayList((apps));\n  }\n\n  public List<App> findByAppIds(Set<String> appIds) {\n    return appRepository.findByAppIdIn(appIds);\n  }\n\n  public List<App> findByOwnerName(String ownerName, Pageable page) {\n    return appRepository.findByOwnerName(ownerName, page);\n  }\n\n  public App load(String appId) {\n    return appRepository.findByAppId(appId);\n  }\n\n  public AppDTO load(Env env, String appId) {\n    return appAPI.loadApp(env, appId);\n  }\n\n  public void createAppInRemote(Env env, App app) {\n    String username = userInfoHolder.getUser().getUserId();\n    app.setDataChangeCreatedBy(username);\n    app.setDataChangeLastModifiedBy(username);\n\n    AppDTO appDTO = BeanUtils.transfrom(AppDTO.class, app);\n    appAPI.createApp(env, appDTO);\n  }\n\n  @Transactional\n  public App createAppInLocal(App app) {\n    String appId = app.getAppId();\n    App managedApp = appRepository.findByAppId(appId);\n\n    if (managedApp != null) {\n      throw new BadRequestException(String.format(\"App already exists. AppId = %s\", appId));\n    }\n\n    UserInfo owner = userService.findByUserId(app.getOwnerName());\n    if (owner == null) {\n      throw new BadRequestException(\"Application's owner not exist.\");\n    }\n    app.setOwnerEmail(owner.getEmail());\n\n    String operator = userInfoHolder.getUser().getUserId();\n    app.setDataChangeCreatedBy(operator);\n    app.setDataChangeLastModifiedBy(operator);\n\n    App createdApp = appRepository.save(app);\n\n    appNamespaceService.createDefaultAppNamespace(appId);\n    roleInitializationService.initAppRoles(createdApp);\n\n    Tracer.logEvent(TracerEventType.CREATE_APP, appId);\n\n    return createdApp;\n  }\n\n  @Transactional\n  public App updateAppInLocal(App app) {\n    String appId = app.getAppId();\n\n    App managedApp = appRepository.findByAppId(appId);\n    if (managedApp == null) {\n      throw new BadRequestException(String.format(\"App not exists. AppId = %s\", appId));\n    }\n\n    managedApp.setName(app.getName());\n    managedApp.setOrgId(app.getOrgId());\n    managedApp.setOrgName(app.getOrgName());\n\n    String ownerName = app.getOwnerName();\n    UserInfo owner = userService.findByUserId(ownerName);\n    if (owner == null) {\n      throw new BadRequestException(String.format(\"App's owner not exists. owner = %s\", ownerName));\n    }\n    managedApp.setOwnerName(owner.getUserId());\n    managedApp.setOwnerEmail(owner.getEmail());\n\n    String operator = userInfoHolder.getUser().getUserId();\n    managedApp.setDataChangeLastModifiedBy(operator);\n\n    return appRepository.save(managedApp);\n  }\n\n  public EnvClusterInfo createEnvNavNode(Env env, String appId) {\n    EnvClusterInfo node = new EnvClusterInfo(env);\n    node.setClusters(clusterService.findClusters(env, appId));\n    return node;\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/ClusterService.java",
    "content": "package com.ctrip.framework.apollo.portal.service;\n\nimport com.ctrip.framework.apollo.common.dto.ClusterDTO;\nimport com.ctrip.framework.apollo.common.exception.BadRequestException;\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.portal.api.AdminServiceAPI;\nimport com.ctrip.framework.apollo.portal.constant.TracerEventType;\nimport com.ctrip.framework.apollo.portal.spi.UserInfoHolder;\nimport com.ctrip.framework.apollo.tracer.Tracer;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\n\n@Service\npublic class ClusterService {\n\n  @Autowired\n  private UserInfoHolder userInfoHolder;\n  @Autowired\n  private AdminServiceAPI.ClusterAPI clusterAPI;\n\n  public List<ClusterDTO> findClusters(Env env, String appId) {\n    return clusterAPI.findClustersByApp(appId, env);\n  }\n\n  public ClusterDTO createCluster(Env env, ClusterDTO cluster) {\n    if (!clusterAPI.isClusterUnique(cluster.getAppId(), env, cluster.getName())) {\n      throw new BadRequestException(String.format(\"cluster %s already exists.\", cluster.getName()));\n    }\n    ClusterDTO clusterDTO = clusterAPI.create(env, cluster);\n\n    Tracer.logEvent(TracerEventType.CREATE_CLUSTER, cluster.getAppId(), \"0\", cluster.getName());\n\n    return clusterDTO;\n  }\n\n  public void deleteCluster(Env env, String appId, String clusterName){\n    clusterAPI.delete(env, appId, clusterName, userInfoHolder.getUser().getUserId());\n  }\n\n  public ClusterDTO loadCluster(String appId, Env env, String clusterName){\n    return clusterAPI.loadCluster(appId, env, clusterName);\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/CommitService.java",
    "content": "package com.ctrip.framework.apollo.portal.service;\n\nimport com.ctrip.framework.apollo.common.dto.CommitDTO;\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.portal.api.AdminServiceAPI;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\n\n@Service\npublic class CommitService {\n\n\n  @Autowired\n  private AdminServiceAPI.CommitAPI commitAPI;\n\n  public List<CommitDTO> find(String appId, Env env, String clusterName, String namespaceName, int page, int size) {\n    return commitAPI.find(appId, env, clusterName, namespaceName, page, size);\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/FavoriteService.java",
    "content": "package com.ctrip.framework.apollo.portal.service;\n\nimport com.ctrip.framework.apollo.common.exception.BadRequestException;\nimport com.ctrip.framework.apollo.portal.entity.po.Favorite;\nimport com.ctrip.framework.apollo.portal.entity.bo.UserInfo;\nimport com.ctrip.framework.apollo.portal.repository.FavoriteRepository;\nimport com.ctrip.framework.apollo.portal.spi.UserInfoHolder;\nimport com.ctrip.framework.apollo.portal.spi.UserService;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.data.domain.Pageable;\nimport org.springframework.stereotype.Service;\nimport org.springframework.util.StringUtils;\n\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Objects;\n\n@Service\npublic class FavoriteService {\n\n  public static final long POSITION_DEFAULT = 10000;\n\n  @Autowired\n  private UserInfoHolder userInfoHolder;\n  @Autowired\n  private FavoriteRepository favoriteRepository;\n  @Autowired\n  private UserService userService;\n\n\n  public Favorite addFavorite(Favorite favorite) {\n    UserInfo user = userService.findByUserId(favorite.getUserId());\n    if (user == null) {\n      throw new BadRequestException(\"user not exist\");\n    }\n\n    UserInfo loginUser = userInfoHolder.getUser();\n    //user can only add himself favorite app\n    if (!loginUser.equals(user)) {\n      throw new BadRequestException(\"add favorite fail. \"\n                                    + \"because favorite's user is not current login user.\");\n    }\n\n    Favorite checkedFavorite = favoriteRepository.findByUserIdAndAppId(loginUser.getUserId(), favorite.getAppId());\n    if (checkedFavorite != null) {\n      return checkedFavorite;\n    }\n\n    favorite.setPosition(POSITION_DEFAULT);\n    favorite.setDataChangeCreatedBy(user.getUserId());\n    favorite.setDataChangeLastModifiedBy(user.getUserId());\n\n    return favoriteRepository.save(favorite);\n  }\n\n\n  public List<Favorite> search(String userId, String appId, Pageable page) {\n    boolean isUserIdEmpty = StringUtils.isEmpty(userId);\n    boolean isAppIdEmpty = StringUtils.isEmpty(appId);\n\n    if (isAppIdEmpty && isUserIdEmpty) {\n      throw new BadRequestException(\"user id and app id can't be empty at the same time\");\n    }\n\n    //search by userId\n    if (isAppIdEmpty && !isUserIdEmpty) {\n      return favoriteRepository.findByUserIdOrderByPositionAscDataChangeCreatedTimeAsc(userId, page);\n    }\n\n    //search by appId\n    if (!isAppIdEmpty && isUserIdEmpty) {\n      return favoriteRepository.findByAppIdOrderByPositionAscDataChangeCreatedTimeAsc(appId, page);\n    }\n\n    //search by userId and appId\n    return Arrays.asList(favoriteRepository.findByUserIdAndAppId(userId, appId));\n  }\n\n\n  public void deleteFavorite(long favoriteId) {\n    Favorite favorite = favoriteRepository.findOne(favoriteId);\n\n    checkUserOperatePermission(favorite);\n\n    favoriteRepository.delete(favorite);\n  }\n\n  public void adjustFavoriteToFirst(long favoriteId) {\n    Favorite favorite = favoriteRepository.findOne(favoriteId);\n\n    checkUserOperatePermission(favorite);\n\n    String userId = favorite.getUserId();\n    Favorite firstFavorite = favoriteRepository.findFirstByUserIdOrderByPositionAscDataChangeCreatedTimeAsc(userId);\n    long minPosition = firstFavorite.getPosition();\n\n    favorite.setPosition(minPosition - 1);\n\n    favoriteRepository.save(favorite);\n  }\n\n  private void checkUserOperatePermission(Favorite favorite) {\n    if (favorite == null) {\n      throw new BadRequestException(\"favorite not exist\");\n    }\n\n    if (!Objects.equals(userInfoHolder.getUser().getUserId(), favorite.getUserId())) {\n      throw new BadRequestException(\"can not operate other person's favorite\");\n    }\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/InstanceService.java",
    "content": "package com.ctrip.framework.apollo.portal.service;\n\nimport com.ctrip.framework.apollo.common.dto.InstanceDTO;\nimport com.ctrip.framework.apollo.common.dto.PageDTO;\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.portal.api.AdminServiceAPI;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\nimport java.util.Set;\n\n@Service\npublic class InstanceService {\n\n\n  @Autowired\n  private AdminServiceAPI.InstanceAPI instanceAPI;\n\n  public PageDTO<InstanceDTO> getByRelease(Env env, long releaseId, int page, int size){\n    return instanceAPI.getByRelease(env, releaseId, page, size);\n  }\n\n  public PageDTO<InstanceDTO> getByNamespace(Env env, String appId, String clusterName, String namespaceName,\n                                             String instanceAppId, int page, int size){\n    return instanceAPI.getByNamespace(appId, env, clusterName, namespaceName, instanceAppId, page, size);\n  }\n\n  public int getInstanceCountByNamepsace(String appId, Env env, String clusterName, String namespaceName){\n    return instanceAPI.getInstanceCountByNamespace(appId, env, clusterName, namespaceName);\n  }\n\n  public List<InstanceDTO> getByReleasesNotIn(Env env, String appId, String clusterName, String namespaceName, Set<Long> releaseIds){\n    return instanceAPI.getByReleasesNotIn(appId, env, clusterName, namespaceName, releaseIds);\n  }\n\n\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/ItemService.java",
    "content": "package com.ctrip.framework.apollo.portal.service;\n\n\nimport com.ctrip.framework.apollo.common.dto.ItemChangeSets;\nimport com.ctrip.framework.apollo.common.dto.ItemDTO;\nimport com.ctrip.framework.apollo.common.dto.NamespaceDTO;\nimport com.ctrip.framework.apollo.common.exception.BadRequestException;\nimport com.ctrip.framework.apollo.common.utils.BeanUtils;\nimport com.ctrip.framework.apollo.core.enums.ConfigFileFormat;\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.core.utils.StringUtils;\nimport com.ctrip.framework.apollo.portal.api.AdminServiceAPI;\nimport com.ctrip.framework.apollo.portal.component.txtresolver.ConfigTextResolver;\nimport com.ctrip.framework.apollo.portal.constant.TracerEventType;\nimport com.ctrip.framework.apollo.portal.entity.model.NamespaceTextModel;\nimport com.ctrip.framework.apollo.portal.entity.vo.ItemDiffs;\nimport com.ctrip.framework.apollo.portal.entity.vo.NamespaceIdentifier;\nimport com.ctrip.framework.apollo.portal.spi.UserInfoHolder;\nimport com.ctrip.framework.apollo.tracer.Tracer;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Qualifier;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.stereotype.Service;\nimport org.springframework.util.CollectionUtils;\nimport org.springframework.web.client.HttpClientErrorException;\n\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\n\n@Service\npublic class ItemService {\n\n  @Autowired\n  private UserInfoHolder userInfoHolder;\n  @Autowired\n  private AdminServiceAPI.NamespaceAPI namespaceAPI;\n  @Autowired\n  private AdminServiceAPI.ItemAPI itemAPI;\n\n  @Autowired\n  @Qualifier(\"fileTextResolver\")\n  private ConfigTextResolver fileTextResolver;\n\n  @Autowired\n  @Qualifier(\"propertyResolver\")\n  private ConfigTextResolver propertyResolver;\n\n\n  /**\n   * parse config text and update config items\n   *\n   * @return parse result\n   */\n  public void updateConfigItemByText(NamespaceTextModel model) {\n    String appId = model.getAppId();\n    Env env = model.getEnv();\n    String clusterName = model.getClusterName();\n    String namespaceName = model.getNamespaceName();\n    long namespaceId = model.getNamespaceId();\n    String configText = model.getConfigText();\n\n    ConfigTextResolver resolver =\n        model.getFormat() == ConfigFileFormat.Properties ? propertyResolver : fileTextResolver;\n\n    ItemChangeSets changeSets = resolver.resolve(namespaceId, configText,\n        itemAPI.findItems(appId, env, clusterName, namespaceName));\n    if (changeSets.isEmpty()) {\n      return;\n    }\n\n    changeSets.setDataChangeLastModifiedBy(userInfoHolder.getUser().getUserId());\n    updateItems(appId, env, clusterName, namespaceName, changeSets);\n\n    Tracer.logEvent(TracerEventType.MODIFY_NAMESPACE_BY_TEXT,\n        String.format(\"%s+%s+%s+%s\", appId, env, clusterName, namespaceName));\n    Tracer.logEvent(TracerEventType.MODIFY_NAMESPACE, String.format(\"%s+%s+%s+%s\", appId, env, clusterName, namespaceName));\n  }\n\n  public void updateItems(String appId, Env env, String clusterName, String namespaceName, ItemChangeSets changeSets){\n    itemAPI.updateItemsByChangeSet(appId, env, clusterName, namespaceName, changeSets);\n  }\n\n\n  public ItemDTO createItem(String appId, Env env, String clusterName, String namespaceName, ItemDTO item) {\n    NamespaceDTO namespace = namespaceAPI.loadNamespace(appId, env, clusterName, namespaceName);\n    if (namespace == null) {\n      throw new BadRequestException(\n          \"namespace:\" + namespaceName + \" not exist in env:\" + env + \", cluster:\" + clusterName);\n    }\n    item.setNamespaceId(namespace.getId());\n\n    ItemDTO itemDTO = itemAPI.createItem(appId, env, clusterName, namespaceName, item);\n    Tracer.logEvent(TracerEventType.MODIFY_NAMESPACE, String.format(\"%s+%s+%s+%s\", appId, env, clusterName, namespaceName));\n    return itemDTO;\n  }\n\n  public void updateItem(String appId, Env env, String clusterName, String namespaceName, ItemDTO item) {\n    itemAPI.updateItem(appId, env, clusterName, namespaceName, item.getId(), item);\n  }\n\n  public void deleteItem(Env env, long itemId, String userId) {\n    itemAPI.deleteItem(env, itemId, userId);\n  }\n\n  public List<ItemDTO> findItems(String appId, Env env, String clusterName, String namespaceName) {\n    return itemAPI.findItems(appId, env, clusterName, namespaceName);\n  }\n\n  public ItemDTO loadItem(Env env, String appId, String clusterName, String namespaceName, String key) {\n    return itemAPI.loadItem(env, appId, clusterName, namespaceName, key);\n  }\n\n  public void syncItems(List<NamespaceIdentifier> comparedNamespaces, List<ItemDTO> sourceItems) {\n    List<ItemDiffs> itemDiffs = compare(comparedNamespaces, sourceItems);\n    for (ItemDiffs itemDiff : itemDiffs) {\n      NamespaceIdentifier namespaceIdentifier = itemDiff.getNamespace();\n      ItemChangeSets changeSets = itemDiff.getDiffs();\n      changeSets.setDataChangeLastModifiedBy(userInfoHolder.getUser().getUserId());\n\n      String appId = namespaceIdentifier.getAppId();\n      Env env = namespaceIdentifier.getEnv();\n      String clusterName = namespaceIdentifier.getClusterName();\n      String namespaceName = namespaceIdentifier.getNamespaceName();\n\n      itemAPI.updateItemsByChangeSet(appId, env, clusterName, namespaceName, changeSets);\n\n      Tracer.logEvent(TracerEventType.SYNC_NAMESPACE, String.format(\"%s+%s+%s+%s\", appId, env, clusterName, namespaceName));\n    }\n  }\n\n  public List<ItemDiffs> compare(List<NamespaceIdentifier> comparedNamespaces, List<ItemDTO> sourceItems) {\n\n    List<ItemDiffs> result = new LinkedList<>();\n\n    for (NamespaceIdentifier namespace : comparedNamespaces) {\n\n      ItemDiffs itemDiffs = new ItemDiffs(namespace);\n      try {\n        itemDiffs.setDiffs(parseChangeSets(namespace, sourceItems));\n      } catch (BadRequestException e) {\n        itemDiffs.setDiffs(new ItemChangeSets());\n        itemDiffs.setExtInfo(\"该集群下没有名为 \" + namespace.getNamespaceName() + \" 的namespace\");\n      }\n      result.add(itemDiffs);\n    }\n\n    return result;\n  }\n\n  private long getNamespaceId(NamespaceIdentifier namespaceIdentifier) {\n    String appId = namespaceIdentifier.getAppId();\n    String clusterName = namespaceIdentifier.getClusterName();\n    String namespaceName = namespaceIdentifier.getNamespaceName();\n    Env env = namespaceIdentifier.getEnv();\n    NamespaceDTO namespaceDTO = null;\n    try {\n      namespaceDTO = namespaceAPI.loadNamespace(appId, env, clusterName, namespaceName);\n    } catch (HttpClientErrorException e) {\n      if (e.getStatusCode() == HttpStatus.NOT_FOUND) {\n        throw new BadRequestException(String.format(\n            \"namespace not exist. appId:%s, env:%s, clusterName:%s, namespaceName:%s\", appId, env, clusterName,\n            namespaceName));\n      }\n    }\n    return namespaceDTO.getId();\n  }\n\n  private ItemChangeSets parseChangeSets(NamespaceIdentifier namespace, List<ItemDTO> sourceItems) {\n    ItemChangeSets changeSets = new ItemChangeSets();\n    List<ItemDTO>\n        targetItems =\n        itemAPI.findItems(namespace.getAppId(), namespace.getEnv(),\n            namespace.getClusterName(), namespace.getNamespaceName());\n\n    long namespaceId = getNamespaceId(namespace);\n\n    if (CollectionUtils.isEmpty(targetItems)) {//all source items is added\n      int lineNum = 1;\n      for (ItemDTO sourceItem : sourceItems) {\n        changeSets.addCreateItem(buildItem(namespaceId, lineNum++, sourceItem));\n      }\n    } else {\n      Map<String, ItemDTO> targetItemMap = BeanUtils.mapByKey(\"key\", targetItems);\n      String key, sourceValue, sourceComment;\n      ItemDTO targetItem = null;\n      int maxLineNum = targetItems.size();//append to last\n      for (ItemDTO sourceItem : sourceItems) {\n        key = sourceItem.getKey();\n        sourceValue = sourceItem.getValue();\n        sourceComment = sourceItem.getComment();\n        targetItem = targetItemMap.get(key);\n\n        if (targetItem == null) {//added items\n\n          changeSets.addCreateItem(buildItem(namespaceId, ++maxLineNum, sourceItem));\n\n        } else if (isModified(sourceValue, targetItem.getValue(), sourceComment,\n            targetItem.getComment())) {//modified items\n          targetItem.setValue(sourceValue);\n          targetItem.setComment(sourceComment);\n          changeSets.addUpdateItem(targetItem);\n        }\n      }\n    }\n\n    return changeSets;\n  }\n\n  private ItemDTO buildItem(long namespaceId, int lineNum, ItemDTO sourceItem) {\n    ItemDTO createdItem = new ItemDTO();\n    BeanUtils.copyEntityProperties(sourceItem, createdItem);\n    createdItem.setLineNum(lineNum);\n    createdItem.setNamespaceId(namespaceId);\n    return createdItem;\n  }\n\n  private boolean isModified(String sourceValue, String targetValue, String sourceComment, String targetComment) {\n\n    if (!sourceValue.equals(targetValue)) {\n      return true;\n    }\n\n    if (sourceComment == null) {\n      return !StringUtils.isEmpty(targetComment);\n    } else if (targetComment != null) {\n      return !sourceComment.equals(targetComment);\n    } else {\n      return false;\n    }\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/NamespaceBranchService.java",
    "content": "package com.ctrip.framework.apollo.portal.service;\n\nimport com.ctrip.framework.apollo.common.dto.GrayReleaseRuleDTO;\nimport com.ctrip.framework.apollo.common.dto.ItemChangeSets;\nimport com.ctrip.framework.apollo.common.dto.ItemDTO;\nimport com.ctrip.framework.apollo.common.dto.NamespaceDTO;\nimport com.ctrip.framework.apollo.common.dto.ReleaseDTO;\nimport com.ctrip.framework.apollo.common.exception.BadRequestException;\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.portal.api.AdminServiceAPI;\nimport com.ctrip.framework.apollo.portal.component.ItemsComparator;\nimport com.ctrip.framework.apollo.portal.constant.TracerEventType;\nimport com.ctrip.framework.apollo.portal.entity.bo.NamespaceBO;\nimport com.ctrip.framework.apollo.portal.spi.UserInfoHolder;\nimport com.ctrip.framework.apollo.tracer.Tracer;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\nimport java.util.Collections;\nimport java.util.List;\n\n@Service\npublic class NamespaceBranchService {\n\n  @Autowired\n  private ItemsComparator itemsComparator;\n  @Autowired\n  private UserInfoHolder userInfoHolder;\n  @Autowired\n  private NamespaceService namespaceService;\n  @Autowired\n  private ItemService itemService;\n  @Autowired\n  private AdminServiceAPI.NamespaceBranchAPI namespaceBranchAPI;\n  @Autowired\n  private ReleaseService releaseService;\n\n\n  @Transactional\n  public NamespaceDTO createBranch(String appId, Env env, String parentClusterName, String namespaceName) {\n    NamespaceDTO createdBranch = namespaceBranchAPI.createBranch(appId, env, parentClusterName, namespaceName,\n                                                                 userInfoHolder.getUser().getUserId());\n\n    Tracer.logEvent(TracerEventType.CREATE_GRAY_RELEASE, String.format(\"%s+%s+%s+%s\", appId, env, parentClusterName,\n                                                                 namespaceName));\n    return createdBranch;\n\n  }\n\n  public GrayReleaseRuleDTO findBranchGrayRules(String appId, Env env, String clusterName,\n                                                String namespaceName, String branchName) {\n    return namespaceBranchAPI.findBranchGrayRules(appId, env, clusterName, namespaceName, branchName);\n\n  }\n\n  public void updateBranchGrayRules(String appId, Env env, String clusterName, String namespaceName,\n                                    String branchName, GrayReleaseRuleDTO rules) {\n\n    String operator = userInfoHolder.getUser().getUserId();\n    rules.setDataChangeCreatedBy(operator);\n    rules.setDataChangeLastModifiedBy(operator);\n\n    namespaceBranchAPI.updateBranchGrayRules(appId, env, clusterName, namespaceName, branchName, rules);\n\n    Tracer.logEvent(TracerEventType.UPDATE_GRAY_RELEASE_RULE,\n                 String.format(\"%s+%s+%s+%s\", appId, env, clusterName, namespaceName));\n  }\n\n  public void deleteBranch(String appId, Env env, String clusterName, String namespaceName,\n                           String branchName) {\n\n    String operator = userInfoHolder.getUser().getUserId();\n\n    namespaceBranchAPI.deleteBranch(appId, env, clusterName, namespaceName, branchName, operator);\n\n    Tracer.logEvent(TracerEventType.DELETE_GRAY_RELEASE,\n                 String.format(\"%s+%s+%s+%s\", appId, env, clusterName, namespaceName));\n  }\n\n\n  public ReleaseDTO merge(String appId, Env env, String clusterName, String namespaceName,\n                          String branchName, String title, String comment,\n                          boolean isEmergencyPublish, boolean deleteBranch) {\n\n    ItemChangeSets changeSets = calculateBranchChangeSet(appId, env, clusterName, namespaceName, branchName);\n\n    ReleaseDTO mergedResult =\n        releaseService.updateAndPublish(appId, env, clusterName, namespaceName, title, comment,\n                                        branchName, isEmergencyPublish, deleteBranch, changeSets);\n\n    Tracer.logEvent(TracerEventType.MERGE_GRAY_RELEASE,\n                 String.format(\"%s+%s+%s+%s\", appId, env, clusterName, namespaceName));\n\n    return mergedResult;\n  }\n\n  private ItemChangeSets calculateBranchChangeSet(String appId, Env env, String clusterName, String namespaceName,\n                                                  String branchName) {\n    NamespaceBO parentNamespace = namespaceService.loadNamespaceBO(appId, env, clusterName, namespaceName);\n\n    if (parentNamespace == null) {\n      throw new BadRequestException(\"base namespace not existed\");\n    }\n\n    if (parentNamespace.getItemModifiedCnt() > 0) {\n      throw new BadRequestException(\"Merge operation failed. Because master has modified items\");\n    }\n\n    List<ItemDTO> masterItems = itemService.findItems(appId, env, clusterName, namespaceName);\n\n    List<ItemDTO> branchItems = itemService.findItems(appId, env, branchName, namespaceName);\n\n    ItemChangeSets changeSets = itemsComparator.compareIgnoreBlankAndCommentItem(parentNamespace.getBaseInfo().getId(),\n                                                                                 masterItems, branchItems);\n    changeSets.setDeleteItems(Collections.emptyList());\n    changeSets.setDataChangeLastModifiedBy(userInfoHolder.getUser().getUserId());\n    return changeSets;\n  }\n\n  public NamespaceDTO findBranchBaseInfo(String appId, Env env, String clusterName, String namespaceName) {\n    return namespaceBranchAPI.findBranch(appId, env, clusterName, namespaceName);\n  }\n\n  public NamespaceBO findBranch(String appId, Env env, String clusterName, String namespaceName) {\n    NamespaceDTO namespaceDTO = findBranchBaseInfo(appId, env, clusterName, namespaceName);\n    if (namespaceDTO == null) {\n      return null;\n    }\n    return namespaceService.loadNamespaceBO(appId, env, namespaceDTO.getClusterName(), namespaceName);\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/NamespaceLockService.java",
    "content": "package com.ctrip.framework.apollo.portal.service;\n\nimport com.ctrip.framework.apollo.common.dto.NamespaceLockDTO;\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.portal.api.AdminServiceAPI;\nimport com.ctrip.framework.apollo.portal.component.config.PortalConfig;\nimport com.ctrip.framework.apollo.portal.entity.vo.LockInfo;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n@Service\npublic class NamespaceLockService {\n\n  @Autowired\n  private AdminServiceAPI.NamespaceLockAPI namespaceLockAPI;\n  @Autowired\n  private PortalConfig portalConfig;\n\n\n  public NamespaceLockDTO getNamespaceLock(String appId, Env env, String clusterName, String namespaceName) {\n    return namespaceLockAPI.getNamespaceLockOwner(appId, env, clusterName, namespaceName);\n  }\n\n  public LockInfo getNamespaceLockInfo(String appId, Env env, String clusterName, String namespaceName) {\n    LockInfo lockInfo = new LockInfo();\n\n    NamespaceLockDTO namespaceLockDTO = namespaceLockAPI.getNamespaceLockOwner(appId, env, clusterName, namespaceName);\n    String lockOwner = namespaceLockDTO == null ? \"\" : namespaceLockDTO.getDataChangeCreatedBy();\n    lockInfo.setLockOwner(lockOwner);\n\n    lockInfo.setEmergencyPublishAllowed(portalConfig.isEmergencyPublishAllowed(env));\n\n    return lockInfo;\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/NamespaceService.java",
    "content": "package com.ctrip.framework.apollo.portal.service;\n\nimport com.ctrip.framework.apollo.portal.component.config.PortalConfig;\n\nimport com.google.common.collect.Maps;\nimport com.google.gson.Gson;\n\nimport com.ctrip.framework.apollo.common.constants.GsonType;\nimport com.ctrip.framework.apollo.common.dto.ItemDTO;\nimport com.ctrip.framework.apollo.common.dto.NamespaceDTO;\nimport com.ctrip.framework.apollo.common.dto.ReleaseDTO;\nimport com.ctrip.framework.apollo.common.entity.AppNamespace;\nimport com.ctrip.framework.apollo.common.exception.BadRequestException;\nimport com.ctrip.framework.apollo.common.utils.BeanUtils;\nimport com.ctrip.framework.apollo.core.enums.ConfigFileFormat;\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.core.utils.StringUtils;\nimport com.ctrip.framework.apollo.portal.api.AdminServiceAPI;\nimport com.ctrip.framework.apollo.portal.component.PortalSettings;\nimport com.ctrip.framework.apollo.portal.constant.TracerEventType;\nimport com.ctrip.framework.apollo.portal.entity.bo.ItemBO;\nimport com.ctrip.framework.apollo.portal.entity.bo.NamespaceBO;\nimport com.ctrip.framework.apollo.portal.spi.UserInfoHolder;\nimport com.ctrip.framework.apollo.tracer.Tracer;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\nimport java.util.*;\n\n@Service\npublic class NamespaceService {\n\n  private Logger logger = LoggerFactory.getLogger(NamespaceService.class);\n  private Gson gson = new Gson();\n\n  @Autowired\n  private PortalConfig portalConfig;\n  @Autowired\n  private PortalSettings portalSettings;\n  @Autowired\n  private UserInfoHolder userInfoHolder;\n  @Autowired\n  private AdminServiceAPI.NamespaceAPI namespaceAPI;\n  @Autowired\n  private ItemService itemService;\n  @Autowired\n  private ReleaseService releaseService;\n  @Autowired\n  private AppNamespaceService appNamespaceService;\n  @Autowired\n  private InstanceService instanceService;\n  @Autowired\n  private NamespaceBranchService branchService;\n\n\n  public NamespaceDTO createNamespace(Env env, NamespaceDTO namespace) {\n    if (StringUtils.isEmpty(namespace.getDataChangeCreatedBy())) {\n      namespace.setDataChangeCreatedBy(userInfoHolder.getUser().getUserId());\n    }\n    namespace.setDataChangeLastModifiedBy(userInfoHolder.getUser().getUserId());\n    NamespaceDTO createdNamespace = namespaceAPI.createNamespace(env, namespace);\n\n    Tracer.logEvent(TracerEventType.CREATE_NAMESPACE,\n                    String.format(\"%s+%s+%s+%s\", namespace.getAppId(), env, namespace.getClusterName(),\n                                  namespace.getNamespaceName()));\n    return createdNamespace;\n  }\n\n\n  @Transactional\n  public void deleteNamespace(String appId, Env env, String clusterName, String namespaceName) {\n\n    //1. check private namespace\n    AppNamespace appNamespace = appNamespaceService.findByAppIdAndName(appId, namespaceName);\n    if (appNamespace != null && !appNamespace.isPublic()) {\n      throw new BadRequestException(\"Private namespace can not be deleted\");\n    }\n\n    //2. check parent namespace has not instances\n    if (namespaceHasInstances(appId, env, clusterName, namespaceName)) {\n      throw new BadRequestException(\"Can not delete namespace because namespace has active instances\");\n    }\n\n    //3. check child namespace has not instances\n    NamespaceDTO childNamespace = branchService.findBranchBaseInfo(appId, env, clusterName, namespaceName);\n    if (childNamespace != null &&\n        namespaceHasInstances(appId, env, childNamespace.getClusterName(), namespaceName)) {\n      throw new BadRequestException(\"Can not delete namespace because namespace's branch has active instances\");\n    }\n\n    //4. check public namespace has not associated namespace\n    if (appNamespace != null && publicAppNamespaceHasAssociatedNamespace(namespaceName, env)) {\n      throw new BadRequestException(\"Can not delete public namespace which has associated namespaces\");\n    }\n\n    String operator = userInfoHolder.getUser().getUserId();\n\n    namespaceAPI.deleteNamespace(env, appId, clusterName, namespaceName, operator);\n  }\n\n  public NamespaceDTO loadNamespaceBaseInfo(String appId, Env env, String clusterName, String namespaceName) {\n    NamespaceDTO namespace = namespaceAPI.loadNamespace(appId, env, clusterName, namespaceName);\n    if (namespace == null) {\n      throw new BadRequestException(\"namespaces not exist\");\n    }\n    return namespace;\n  }\n\n  /**\n   * load cluster all namespace info with items\n   */\n  public List<NamespaceBO> findNamespaceBOs(String appId, Env env, String clusterName) {\n\n    List<NamespaceDTO> namespaces = namespaceAPI.findNamespaceByCluster(appId, env, clusterName);\n    if (namespaces == null || namespaces.size() == 0) {\n      throw new BadRequestException(\"namespaces not exist\");\n    }\n\n    List<NamespaceBO> namespaceBOs = new LinkedList<>();\n    for (NamespaceDTO namespace : namespaces) {\n\n      NamespaceBO namespaceBO;\n      try {\n        namespaceBO = transformNamespace2BO(env, namespace);\n        namespaceBOs.add(namespaceBO);\n      } catch (Exception e) {\n        logger.error(\"parse namespace error. app id:{}, env:{}, clusterName:{}, namespace:{}\",\n                     appId, env, clusterName, namespace.getNamespaceName(), e);\n        throw e;\n      }\n    }\n\n    return namespaceBOs;\n  }\n\n  public List<NamespaceDTO> getPublicAppNamespaceAllNamespaces(Env env, String publicNamespaceName, int page,\n                                                               int size) {\n    return namespaceAPI.getPublicAppNamespaceAllNamespaces(env, publicNamespaceName, page, size);\n  }\n\n  public NamespaceBO loadNamespaceBO(String appId, Env env, String clusterName, String namespaceName) {\n    NamespaceDTO namespace = namespaceAPI.loadNamespace(appId, env, clusterName, namespaceName);\n    if (namespace == null) {\n      throw new BadRequestException(\"namespaces not exist\");\n    }\n    return transformNamespace2BO(env, namespace);\n  }\n\n  public boolean namespaceHasInstances(String appId, Env env, String clusterName, String namespaceName) {\n    return instanceService.getInstanceCountByNamepsace(appId, env, clusterName, namespaceName) > 0;\n  }\n\n  public boolean publicAppNamespaceHasAssociatedNamespace(String publicNamespaceName, Env env) {\n    return namespaceAPI.countPublicAppNamespaceAssociatedNamespaces(env, publicNamespaceName) > 0;\n  }\n\n  public NamespaceBO findPublicNamespaceForAssociatedNamespace(Env env, String appId,\n                                                               String clusterName, String namespaceName) {\n    NamespaceDTO namespace =\n        namespaceAPI.findPublicNamespaceForAssociatedNamespace(env, appId, clusterName, namespaceName);\n\n    return transformNamespace2BO(env, namespace);\n  }\n\n  public Map<String, Map<String, Boolean>> getNamespacesPublishInfo(String appId) {\n    Map<String, Map<String, Boolean>> result = Maps.newHashMap();\n\n    Set<Env> envs = portalConfig.publishTipsSupportedEnvs();\n    for (Env env : envs) {\n      if (portalSettings.isEnvActive(env)) {\n        result.put(env.toString(), namespaceAPI.getNamespacePublishInfo(env, appId));\n      }\n    }\n\n    return result;\n  }\n\n  private NamespaceBO transformNamespace2BO(Env env, NamespaceDTO namespace) {\n    NamespaceBO namespaceBO = new NamespaceBO();\n    namespaceBO.setBaseInfo(namespace);\n\n    String appId = namespace.getAppId();\n    String clusterName = namespace.getClusterName();\n    String namespaceName = namespace.getNamespaceName();\n\n    fillAppNamespaceProperties(namespaceBO);\n\n    List<ItemBO> itemBOs = new LinkedList<>();\n    namespaceBO.setItems(itemBOs);\n\n    //latest Release\n    ReleaseDTO latestRelease;\n    Map<String, String> releaseItems = new HashMap<>();\n    latestRelease = releaseService.loadLatestRelease(appId, env, clusterName, namespaceName);\n    if (latestRelease != null) {\n      releaseItems = gson.fromJson(latestRelease.getConfigurations(), GsonType.CONFIG);\n    }\n\n    //not Release config items\n    List<ItemDTO> items = itemService.findItems(appId, env, clusterName, namespaceName);\n    int modifiedItemCnt = 0;\n    for (ItemDTO itemDTO : items) {\n\n      ItemBO itemBO = transformItem2BO(itemDTO, releaseItems);\n\n      if (itemBO.isModified()) {\n        modifiedItemCnt++;\n      }\n\n      itemBOs.add(itemBO);\n    }\n\n    //deleted items\n    List<ItemBO> deletedItems = parseDeletedItems(items, releaseItems);\n    itemBOs.addAll(deletedItems);\n    modifiedItemCnt += deletedItems.size();\n\n    namespaceBO.setItemModifiedCnt(modifiedItemCnt);\n\n    return namespaceBO;\n  }\n\n  private void fillAppNamespaceProperties(NamespaceBO namespace) {\n\n    NamespaceDTO namespaceDTO = namespace.getBaseInfo();\n    //先从当前appId下面找,包含私有的和公共的\n    AppNamespace appNamespace =\n        appNamespaceService.findByAppIdAndName(namespaceDTO.getAppId(), namespaceDTO.getNamespaceName());\n    //再从公共的app namespace里面找\n    if (appNamespace == null) {\n      appNamespace = appNamespaceService.findPublicAppNamespace(namespaceDTO.getNamespaceName());\n    }\n\n    String format;\n    boolean isPublic;\n    if (appNamespace == null) {\n      format = ConfigFileFormat.Properties.getValue();\n      isPublic = false;\n    } else {\n      format = appNamespace.getFormat();\n      isPublic = appNamespace.isPublic();\n      namespace.setParentAppId(appNamespace.getAppId());\n      namespace.setComment(appNamespace.getComment());\n    }\n    namespace.setFormat(format);\n    namespace.setPublic(isPublic);\n  }\n\n  private List<ItemBO> parseDeletedItems(List<ItemDTO> newItems, Map<String, String> releaseItems) {\n    Map<String, ItemDTO> newItemMap = BeanUtils.mapByKey(\"key\", newItems);\n\n    List<ItemBO> deletedItems = new LinkedList<>();\n    for (Map.Entry<String, String> entry : releaseItems.entrySet()) {\n      String key = entry.getKey();\n      if (newItemMap.get(key) == null) {\n        ItemBO deletedItem = new ItemBO();\n\n        deletedItem.setDeleted(true);\n        ItemDTO deletedItemDto = new ItemDTO();\n        deletedItemDto.setKey(key);\n        String oldValue = entry.getValue();\n        deletedItem.setItem(deletedItemDto);\n\n        deletedItemDto.setValue(oldValue);\n        deletedItem.setModified(true);\n        deletedItem.setOldValue(oldValue);\n        deletedItem.setNewValue(\"\");\n        deletedItems.add(deletedItem);\n      }\n    }\n    return deletedItems;\n  }\n\n  private ItemBO transformItem2BO(ItemDTO itemDTO, Map<String, String> releaseItems) {\n    String key = itemDTO.getKey();\n    ItemBO itemBO = new ItemBO();\n    itemBO.setItem(itemDTO);\n    String newValue = itemDTO.getValue();\n    String oldValue = releaseItems.get(key);\n    //new item or modified\n    if (!StringUtils.isEmpty(key) && (oldValue == null || !newValue.equals(oldValue))) {\n      itemBO.setModified(true);\n      itemBO.setOldValue(oldValue == null ? \"\" : oldValue);\n      itemBO.setNewValue(newValue);\n    }\n    return itemBO;\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/PortalDBPropertySource.java",
    "content": "package com.ctrip.framework.apollo.portal.service;\n\nimport com.google.common.collect.Maps;\n\nimport com.ctrip.framework.apollo.common.config.RefreshablePropertySource;\nimport com.ctrip.framework.apollo.portal.entity.po.ServerConfig;\nimport com.ctrip.framework.apollo.portal.repository.ServerConfigRepository;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport java.util.Map;\nimport java.util.Objects;\n\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\n@Component\npublic class PortalDBPropertySource extends RefreshablePropertySource {\n  private static final Logger logger = LoggerFactory.getLogger(PortalDBPropertySource.class);\n\n  @Autowired\n  private ServerConfigRepository serverConfigRepository;\n\n\n  public PortalDBPropertySource(String name, Map<String, Object> source) {\n    super(name, source);\n  }\n\n  public PortalDBPropertySource() {\n    super(\"DBConfig\", Maps.newConcurrentMap());\n  }\n\n  @Override\n  protected void refresh() {\n    Iterable<ServerConfig> dbConfigs = serverConfigRepository.findAll();\n\n    for (ServerConfig config: dbConfigs) {\n      String key = config.getKey();\n      Object value = config.getValue();\n\n      if (this.source.isEmpty()) {\n        logger.info(\"Load config from DB : {} = {}\", key, value);\n      } else if (!Objects.equals(this.source.get(key), value)) {\n        logger.info(\"Load config from DB : {} = {}. Old value = {}\", key,\n                    value, this.source.get(key));\n      }\n\n      this.source.put(key, value);\n    }\n  }\n\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/ReleaseHistoryService.java",
    "content": "package com.ctrip.framework.apollo.portal.service;\n\nimport com.google.gson.Gson;\n\nimport com.ctrip.framework.apollo.common.constants.GsonType;\nimport com.ctrip.framework.apollo.common.dto.PageDTO;\nimport com.ctrip.framework.apollo.common.dto.ReleaseDTO;\nimport com.ctrip.framework.apollo.common.dto.ReleaseHistoryDTO;\nimport com.ctrip.framework.apollo.common.entity.EntityPair;\nimport com.ctrip.framework.apollo.common.utils.BeanUtils;\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.portal.api.AdminServiceAPI;\nimport com.ctrip.framework.apollo.portal.entity.bo.ReleaseHistoryBO;\nimport com.ctrip.framework.apollo.portal.util.RelativeDateFormat;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\n@Service\npublic class ReleaseHistoryService {\n\n  private Gson gson = new Gson();\n\n\n  @Autowired\n  private AdminServiceAPI.ReleaseHistoryAPI releaseHistoryAPI;\n  @Autowired\n  private ReleaseService releaseService;\n\n\n  public ReleaseHistoryBO findLatestByReleaseIdAndOperation(Env env, long releaseId, int operation){\n    PageDTO<ReleaseHistoryDTO> pageDTO = releaseHistoryAPI.findByReleaseIdAndOperation(env, releaseId, operation, 0, 1);\n    if (pageDTO != null && pageDTO.hasContent()){\n      ReleaseHistoryDTO releaseHistory = pageDTO.getContent().get(0);\n      ReleaseDTO release = releaseService.findReleaseById(env, releaseHistory.getReleaseId());\n      return transformReleaseHistoryDTO2BO(releaseHistory, release);\n    }\n\n    return null;\n  }\n\n  public ReleaseHistoryBO findLatestByPreviousReleaseIdAndOperation(Env env, long previousReleaseId, int operation){\n    PageDTO<ReleaseHistoryDTO> pageDTO = releaseHistoryAPI.findByPreviousReleaseIdAndOperation(env, previousReleaseId, operation, 0, 1);\n    if (pageDTO != null && pageDTO.hasContent()){\n      ReleaseHistoryDTO releaseHistory = pageDTO.getContent().get(0);\n      ReleaseDTO release = releaseService.findReleaseById(env, releaseHistory.getReleaseId());\n      return transformReleaseHistoryDTO2BO(releaseHistory, release);\n    }\n\n    return null;\n  }\n\n  public List<ReleaseHistoryBO> findNamespaceReleaseHistory(String appId, Env env, String clusterName,\n                                                            String namespaceName, int page, int size) {\n    PageDTO<ReleaseHistoryDTO> result = releaseHistoryAPI.findReleaseHistoriesByNamespace(appId, env, clusterName,\n                                                                                          namespaceName, page, size);\n    if (result == null || !result.hasContent()) {\n      return Collections.emptyList();\n    }\n\n    List<ReleaseHistoryDTO> content = result.getContent();\n    Set<Long> releaseIds = new HashSet<>();\n    for (ReleaseHistoryDTO releaseHistoryDTO : content) {\n      long releaseId = releaseHistoryDTO.getReleaseId();\n      if (releaseId != 0) {\n        releaseIds.add(releaseId);\n      }\n    }\n\n    List<ReleaseDTO> releases = releaseService.findReleaseByIds(env, releaseIds);\n\n    return transformReleaseHistoryDTO2BO(content, releases);\n  }\n\n  private List<ReleaseHistoryBO> transformReleaseHistoryDTO2BO(List<ReleaseHistoryDTO> source,\n                                                               List<ReleaseDTO> releases) {\n\n    Map<Long, ReleaseDTO> releasesMap = BeanUtils.mapByKey(\"id\", releases);\n\n    List<ReleaseHistoryBO> bos = new ArrayList<>(source.size());\n    for (ReleaseHistoryDTO dto : source) {\n      ReleaseDTO release = releasesMap.get(dto.getReleaseId());\n      bos.add(transformReleaseHistoryDTO2BO(dto, release));\n    }\n\n    return bos;\n  }\n\n  private ReleaseHistoryBO transformReleaseHistoryDTO2BO(ReleaseHistoryDTO dto, ReleaseDTO release){\n    ReleaseHistoryBO bo = new ReleaseHistoryBO();\n    bo.setId(dto.getId());\n    bo.setAppId(dto.getAppId());\n    bo.setClusterName(dto.getClusterName());\n    bo.setNamespaceName(dto.getNamespaceName());\n    bo.setBranchName(dto.getBranchName());\n    bo.setReleaseId(dto.getReleaseId());\n    bo.setPreviousReleaseId(dto.getPreviousReleaseId());\n    bo.setOperator(dto.getDataChangeCreatedBy());\n    bo.setOperation(dto.getOperation());\n    Date releaseTime = dto.getDataChangeLastModifiedTime();\n    bo.setReleaseTime(releaseTime);\n    bo.setReleaseTimeFormatted(RelativeDateFormat.format(releaseTime));\n    bo.setOperationContext(dto.getOperationContext());\n    //set release info\n    setReleaseInfoToReleaseHistoryBO(bo, release);\n\n    return bo;\n  }\n  private void setReleaseInfoToReleaseHistoryBO(ReleaseHistoryBO bo, ReleaseDTO release) {\n    if (release != null) {\n      bo.setReleaseTitle(release.getName());\n      bo.setReleaseComment(release.getComment());\n\n      Map<String, String> configuration = gson.fromJson(release.getConfigurations(), GsonType.CONFIG);\n      List<EntityPair<String>> items = new ArrayList<>(configuration.size());\n      for (Map.Entry<String, String> entry : configuration.entrySet()) {\n        EntityPair<String> entityPair = new EntityPair<>(entry.getKey(), entry.getValue());\n        items.add(entityPair);\n      }\n      bo.setConfiguration(items);\n\n    } else {\n      bo.setReleaseTitle(\"no release information\");\n      bo.setConfiguration(null);\n    }\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/ReleaseService.java",
    "content": "package com.ctrip.framework.apollo.portal.service;\n\nimport com.google.common.base.Objects;\nimport com.google.gson.Gson;\n\nimport com.ctrip.framework.apollo.common.constants.GsonType;\nimport com.ctrip.framework.apollo.common.dto.ItemChangeSets;\nimport com.ctrip.framework.apollo.common.dto.ReleaseDTO;\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.core.utils.StringUtils;\nimport com.ctrip.framework.apollo.portal.api.AdminServiceAPI;\nimport com.ctrip.framework.apollo.portal.constant.TracerEventType;\nimport com.ctrip.framework.apollo.portal.entity.model.NamespaceReleaseModel;\nimport com.ctrip.framework.apollo.portal.entity.bo.KVEntity;\nimport com.ctrip.framework.apollo.portal.entity.vo.ReleaseCompareResult;\nimport com.ctrip.framework.apollo.portal.entity.bo.ReleaseBO;\nimport com.ctrip.framework.apollo.portal.enums.ChangeType;\nimport com.ctrip.framework.apollo.portal.spi.UserInfoHolder;\nimport com.ctrip.framework.apollo.tracer.Tracer;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.util.CollectionUtils;\n\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.LinkedHashSet;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\n@Service\npublic class ReleaseService {\n\n  private static final Gson gson = new Gson();\n\n  @Autowired\n  private UserInfoHolder userInfoHolder;\n  @Autowired\n  private AdminServiceAPI.ReleaseAPI releaseAPI;\n\n  public ReleaseDTO publish(NamespaceReleaseModel model) {\n    Env env = model.getEnv();\n    boolean isEmergencyPublish = model.isEmergencyPublish();\n    String appId = model.getAppId();\n    String clusterName = model.getClusterName();\n    String namespaceName = model.getNamespaceName();\n    String releaseBy = StringUtils.isEmpty(model.getReleasedBy()) ?\n                       userInfoHolder.getUser().getUserId() : model.getReleasedBy();\n\n    ReleaseDTO releaseDTO = releaseAPI.createRelease(appId, env, clusterName, namespaceName,\n                                                     model.getReleaseTitle(), model.getReleaseComment(),\n                                                     releaseBy, isEmergencyPublish);\n\n    Tracer.logEvent(TracerEventType.RELEASE_NAMESPACE,\n                    String.format(\"%s+%s+%s+%s\", appId, env, clusterName, namespaceName));\n\n    return releaseDTO;\n  }\n\n  public ReleaseDTO updateAndPublish(String appId, Env env, String clusterName, String namespaceName,\n                                     String releaseTitle, String releaseComment, String branchName,\n                                     boolean isEmergencyPublish, boolean deleteBranch, ItemChangeSets changeSets) {\n\n    return releaseAPI.updateAndPublish(appId, env, clusterName, namespaceName, releaseTitle, releaseComment, branchName,\n                                       isEmergencyPublish, deleteBranch, changeSets);\n  }\n\n  public List<ReleaseBO> findAllReleases(String appId, Env env, String clusterName, String namespaceName, int page,\n                                         int size) {\n    List<ReleaseDTO> releaseDTOs = releaseAPI.findAllReleases(appId, env, clusterName, namespaceName, page, size);\n\n    if (CollectionUtils.isEmpty(releaseDTOs)) {\n      return Collections.emptyList();\n    }\n\n    List<ReleaseBO> releases = new LinkedList<>();\n    for (ReleaseDTO releaseDTO : releaseDTOs) {\n      ReleaseBO release = new ReleaseBO();\n      release.setBaseInfo(releaseDTO);\n\n      Set<KVEntity> kvEntities = new LinkedHashSet<>();\n      Map<String, String> configurations = gson.fromJson(releaseDTO.getConfigurations(), GsonType.CONFIG);\n      Set<Map.Entry<String, String>> entries = configurations.entrySet();\n      for (Map.Entry<String, String> entry : entries) {\n        kvEntities.add(new KVEntity(entry.getKey(), entry.getValue()));\n      }\n      release.setItems(kvEntities);\n      //为了减少数据量\n      releaseDTO.setConfigurations(\"\");\n      releases.add(release);\n    }\n\n    return releases;\n  }\n\n  public List<ReleaseDTO> findActiveReleases(String appId, Env env, String clusterName, String namespaceName, int page,\n                                             int size) {\n    return releaseAPI.findActiveReleases(appId, env, clusterName, namespaceName, page, size);\n  }\n\n  public ReleaseDTO findReleaseById(Env env, long releaseId) {\n    Set<Long> releaseIds = new HashSet<>(1);\n    releaseIds.add(releaseId);\n    List<ReleaseDTO> releases = findReleaseByIds(env, releaseIds);\n    if (CollectionUtils.isEmpty(releases)) {\n      return null;\n    } else {\n      return releases.get(0);\n    }\n\n  }\n\n  public List<ReleaseDTO> findReleaseByIds(Env env, Set<Long> releaseIds) {\n    return releaseAPI.findReleaseByIds(env, releaseIds);\n  }\n\n  public ReleaseDTO loadLatestRelease(String appId, Env env, String clusterName, String namespaceName) {\n    return releaseAPI.loadLatestRelease(appId, env, clusterName, namespaceName);\n  }\n\n  public void rollback(Env env, long releaseId) {\n    releaseAPI.rollback(env, releaseId, userInfoHolder.getUser().getUserId());\n  }\n\n  public ReleaseCompareResult compare(Env env, long baseReleaseId, long toCompareReleaseId) {\n\n    ReleaseDTO baseRelease = null;\n    ReleaseDTO toCompareRelease = null;\n    if (baseReleaseId != 0) {\n      baseRelease = releaseAPI.loadRelease(env, baseReleaseId);\n    }\n\n    if (toCompareReleaseId != 0) {\n      toCompareRelease = releaseAPI.loadRelease(env, toCompareReleaseId);\n    }\n\n    return compare(baseRelease, toCompareRelease);\n  }\n\n  public ReleaseCompareResult compare(ReleaseDTO baseRelease, ReleaseDTO toCompareRelease) {\n    Map<String, String> baseReleaseConfiguration = baseRelease == null ? new HashMap<>() :\n                                                   gson.fromJson(baseRelease.getConfigurations(), GsonType.CONFIG);\n    Map<String, String> toCompareReleaseConfiguration = toCompareRelease == null ? new HashMap<>() :\n                                                        gson.fromJson(toCompareRelease.getConfigurations(),\n                                                                      GsonType.CONFIG);\n\n    ReleaseCompareResult compareResult = new ReleaseCompareResult();\n\n    //added and modified in firstRelease\n    for (Map.Entry<String, String> entry : baseReleaseConfiguration.entrySet()) {\n      String key = entry.getKey();\n      String firstValue = entry.getValue();\n      String secondValue = toCompareReleaseConfiguration.get(key);\n      //added\n      if (secondValue == null) {\n        compareResult.addEntityPair(ChangeType.DELETED, new KVEntity(key, firstValue),\n                                    new KVEntity(key, null));\n      } else if (!Objects.equal(firstValue, secondValue)) {\n        compareResult.addEntityPair(ChangeType.MODIFIED, new KVEntity(key, firstValue),\n                                    new KVEntity(key, secondValue));\n      }\n\n    }\n\n    //deleted in firstRelease\n    for (Map.Entry<String, String> entry : toCompareReleaseConfiguration.entrySet()) {\n      String key = entry.getKey();\n      String value = entry.getValue();\n      if (baseReleaseConfiguration.get(key) == null) {\n        compareResult\n            .addEntityPair(ChangeType.ADDED, new KVEntity(key, \"\"), new KVEntity(key, value));\n      }\n\n    }\n\n    return compareResult;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/RoleInitializationService.java",
    "content": "package com.ctrip.framework.apollo.portal.service;\n\nimport com.ctrip.framework.apollo.common.entity.App;\n\npublic interface RoleInitializationService {\n\n  public void initAppRoles(App app);\n\n  public void initNamespaceRoles(String appId, String namespaceName, String operator);\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/RolePermissionService.java",
    "content": "package com.ctrip.framework.apollo.portal.service;\n\nimport com.ctrip.framework.apollo.portal.entity.bo.UserInfo;\nimport com.ctrip.framework.apollo.portal.entity.po.Permission;\nimport com.ctrip.framework.apollo.portal.entity.po.Role;\n\nimport java.util.Set;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic interface RolePermissionService {\n\n  /**\n   * Create role with permissions, note that role name should be unique\n   */\n  public Role createRoleWithPermissions(Role role, Set<Long> permissionIds);\n\n  /**\n   * Assign role to users\n   *\n   * @return the users assigned roles\n   */\n  public Set<String> assignRoleToUsers(String roleName, Set<String> userIds,\n                                       String operatorUserId);\n\n  /**\n   * Remove role from users\n   */\n  public void removeRoleFromUsers(String roleName, Set<String> userIds, String operatorUserId);\n\n  /**\n   * Query users with role\n   */\n  public Set<UserInfo> queryUsersWithRole(String roleName);\n\n  /**\n   * Find role by role name, note that roleName should be unique\n   */\n  public Role findRoleByRoleName(String roleName);\n\n  /**\n   * Check whether user has the permission\n   */\n  public boolean userHasPermission(String userId, String permissionType, String targetId);\n\n  public boolean isSuperAdmin(String userId);\n\n  /**\n   * Create permission, note that permissionType + targetId should be unique\n   */\n  public Permission createPermission(Permission permission);\n\n  /**\n   * Create permissions, note that permissionType + targetId should be unique\n   */\n  public Set<Permission> createPermissions(Set<Permission> permissions);\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/EmailService.java",
    "content": "package com.ctrip.framework.apollo.portal.spi;\n\nimport com.ctrip.framework.apollo.portal.entity.bo.Email;\n\npublic interface EmailService {\n\n  void send(Email email);\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/LogoutHandler.java",
    "content": "package com.ctrip.framework.apollo.portal.spi;\n\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\npublic interface LogoutHandler {\n\n  void logout(HttpServletRequest request, HttpServletResponse response);\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/MQService.java",
    "content": "package com.ctrip.framework.apollo.portal.spi;\n\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.portal.entity.bo.ReleaseHistoryBO;\n\npublic interface MQService {\n\n  void sendPublishMsg(Env env, ReleaseHistoryBO releaseHistory);\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/SsoHeartbeatHandler.java",
    "content": "package com.ctrip.framework.apollo.portal.spi;\n\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic interface SsoHeartbeatHandler {\n  void doHeartbeat(HttpServletRequest request, HttpServletResponse response);\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/UserInfoHolder.java",
    "content": "package com.ctrip.framework.apollo.portal.spi;\n\nimport com.ctrip.framework.apollo.portal.entity.bo.UserInfo;\n\n/**\n * Get access to the user's information,\n * different companies should have a different implementation\n */\npublic interface UserInfoHolder {\n\n  UserInfo getUser();\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/UserService.java",
    "content": "package com.ctrip.framework.apollo.portal.spi;\n\nimport com.ctrip.framework.apollo.portal.entity.bo.UserInfo;\n\nimport java.util.List;\nimport java.util.Set;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic interface UserService {\n  List<UserInfo> searchUsers(String keyword, int offset, int limit);\n\n  UserInfo findByUserId(String userId);\n\n  List<UserInfo> findByUserIds(List<String> userIds);\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/configuration/AuthConfiguration.java",
    "content": "package com.ctrip.framework.apollo.portal.spi.configuration;\n\nimport com.google.common.collect.Maps;\n\nimport com.ctrip.framework.apollo.common.condition.ConditionalOnMissingProfile;\nimport com.ctrip.framework.apollo.portal.component.config.PortalConfig;\nimport com.ctrip.framework.apollo.portal.spi.LogoutHandler;\nimport com.ctrip.framework.apollo.portal.spi.SsoHeartbeatHandler;\nimport com.ctrip.framework.apollo.portal.spi.UserInfoHolder;\nimport com.ctrip.framework.apollo.portal.spi.UserService;\nimport com.ctrip.framework.apollo.portal.spi.ctrip.CtripLogoutHandler;\nimport com.ctrip.framework.apollo.portal.spi.ctrip.CtripSsoHeartbeatHandler;\nimport com.ctrip.framework.apollo.portal.spi.ctrip.CtripUserInfoHolder;\nimport com.ctrip.framework.apollo.portal.spi.ctrip.CtripUserService;\nimport com.ctrip.framework.apollo.portal.spi.defaultimpl.DefaultLogoutHandler;\nimport com.ctrip.framework.apollo.portal.spi.defaultimpl.DefaultSsoHeartbeatHandler;\nimport com.ctrip.framework.apollo.portal.spi.defaultimpl.DefaultUserInfoHolder;\nimport com.ctrip.framework.apollo.portal.spi.defaultimpl.DefaultUserService;\nimport com.ctrip.framework.apollo.portal.spi.springsecurity.SpringSecurityUserInfoHolder;\nimport com.ctrip.framework.apollo.portal.spi.springsecurity.SpringSecurityUserService;\n\nimport org.apache.tomcat.jdbc.pool.DataSource;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.boot.context.embedded.FilterRegistrationBean;\nimport org.springframework.boot.context.embedded.ServletListenerRegistrationBean;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.context.annotation.Profile;\nimport org.springframework.core.annotation.Order;\nimport org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;\nimport org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;\nimport org.springframework.security.config.annotation.web.builders.HttpSecurity;\nimport org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;\nimport org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;\nimport org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;\nimport org.springframework.security.provisioning.JdbcUserDetailsManager;\nimport org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;\n\nimport javax.servlet.Filter;\nimport java.util.EventListener;\nimport java.util.Map;\n\n\n@Configuration\npublic class AuthConfiguration {\n\n  /**\n   * spring.profiles.active = ctrip\n   */\n  @Configuration\n  @Profile(\"ctrip\")\n  static class CtripAuthAutoConfiguration {\n\n    @Autowired\n    private PortalConfig portalConfig;\n\n    @Bean\n    public ServletListenerRegistrationBean redisAppSettingListner() {\n      ServletListenerRegistrationBean redisAppSettingListener = new ServletListenerRegistrationBean();\n      redisAppSettingListener.setListener(listener(\"org.jasig.cas.client.credis.CRedisAppSettingListner\"));\n      return redisAppSettingListener;\n    }\n\n    @Bean\n    public ServletListenerRegistrationBean singleSignOutHttpSessionListener() {\n      ServletListenerRegistrationBean singleSignOutHttpSessionListener = new ServletListenerRegistrationBean();\n      singleSignOutHttpSessionListener\n          .setListener(listener(\"org.jasig.cas.client.session.SingleSignOutHttpSessionListener\"));\n      return singleSignOutHttpSessionListener;\n    }\n\n    @Bean\n    public FilterRegistrationBean casFilter() {\n      FilterRegistrationBean singleSignOutFilter = new FilterRegistrationBean();\n      singleSignOutFilter.setFilter(filter(\"org.jasig.cas.client.session.SingleSignOutFilter\"));\n      singleSignOutFilter.addUrlPatterns(\"/*\");\n      singleSignOutFilter.setOrder(1);\n      return singleSignOutFilter;\n    }\n\n    @Bean\n    public FilterRegistrationBean authenticationFilter() {\n      FilterRegistrationBean casFilter = new FilterRegistrationBean();\n\n      Map<String, String> filterInitParam = Maps.newHashMap();\n      filterInitParam.put(\"redisClusterName\", \"casClientPrincipal\");\n      filterInitParam.put(\"serverName\", portalConfig.portalServerName());\n      filterInitParam.put(\"casServerLoginUrl\", portalConfig.casServerLoginUrl());\n      //we don't want to use session to store login information, since we will be deployed to a cluster, not a single instance\n      filterInitParam.put(\"useSession\", \"false\");\n      filterInitParam.put(\"/openapi.*\", \"exclude\");\n\n      casFilter.setInitParameters(filterInitParam);\n      casFilter.setFilter(filter(\"com.ctrip.framework.apollo.sso.filter.ApolloAuthenticationFilter\"));\n      casFilter.addUrlPatterns(\"/*\");\n      casFilter.setOrder(2);\n\n      return casFilter;\n    }\n\n    @Bean\n    public FilterRegistrationBean casValidationFilter() {\n      FilterRegistrationBean casValidationFilter = new FilterRegistrationBean();\n      Map<String, String> filterInitParam = Maps.newHashMap();\n      filterInitParam.put(\"casServerUrlPrefix\", portalConfig.casServerUrlPrefix());\n      filterInitParam.put(\"serverName\", portalConfig.portalServerName());\n      filterInitParam.put(\"encoding\", \"UTF-8\");\n      //we don't want to use session to store login information, since we will be deployed to a cluster, not a single instance\n      filterInitParam.put(\"useSession\", \"false\");\n      filterInitParam.put(\"useRedis\", \"true\");\n      filterInitParam.put(\"redisClusterName\", \"casClientPrincipal\");\n\n      casValidationFilter\n          .setFilter(filter(\"org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter\"));\n      casValidationFilter.setInitParameters(filterInitParam);\n      casValidationFilter.addUrlPatterns(\"/*\");\n      casValidationFilter.setOrder(3);\n\n      return casValidationFilter;\n\n    }\n\n\n    @Bean\n    public FilterRegistrationBean assertionHolder() {\n      FilterRegistrationBean assertionHolderFilter = new FilterRegistrationBean();\n\n      Map<String, String> filterInitParam = Maps.newHashMap();\n      filterInitParam.put(\"/openapi.*\", \"exclude\");\n\n      assertionHolderFilter.setInitParameters(filterInitParam);\n\n      assertionHolderFilter.setFilter(filter(\"com.ctrip.framework.apollo.sso.filter.ApolloAssertionThreadLocalFilter\"));\n      assertionHolderFilter.addUrlPatterns(\"/*\");\n      assertionHolderFilter.setOrder(4);\n\n      return assertionHolderFilter;\n    }\n\n    @Bean\n    public CtripUserInfoHolder ctripUserInfoHolder() {\n      return new CtripUserInfoHolder();\n    }\n\n    @Bean\n    public CtripLogoutHandler logoutHandler() {\n      return new CtripLogoutHandler();\n    }\n\n    private Filter filter(String className) {\n      Class clazz = null;\n      try {\n        clazz = Class.forName(className);\n        Object obj = clazz.newInstance();\n        return (Filter) obj;\n      } catch (Exception e) {\n        throw new RuntimeException(\"instance filter fail\", e);\n      }\n\n    }\n\n    private EventListener listener(String className) {\n      Class clazz = null;\n      try {\n        clazz = Class.forName(className);\n        Object obj = clazz.newInstance();\n        return (EventListener) obj;\n      } catch (Exception e) {\n        throw new RuntimeException(\"instance listener fail\", e);\n      }\n    }\n\n    @Bean\n    public UserService ctripUserService(PortalConfig portalConfig) {\n      return new CtripUserService(portalConfig);\n    }\n\n    @Bean\n    public SsoHeartbeatHandler ctripSsoHeartbeatHandler() {\n      return new CtripSsoHeartbeatHandler();\n    }\n\n  }\n\n\n  /**\n   * spring.profiles.active = auth\n   */\n  @Configuration\n  @Profile(\"auth\")\n  static class SpringSecurityAuthAutoConfiguration {\n\n    @Bean\n    @ConditionalOnMissingBean(SsoHeartbeatHandler.class)\n    public SsoHeartbeatHandler defaultSsoHeartbeatHandler() {\n      return new DefaultSsoHeartbeatHandler();\n    }\n\n    @Bean\n    @ConditionalOnMissingBean(UserInfoHolder.class)\n    public UserInfoHolder springSecurityUserInfoHolder() {\n      return new SpringSecurityUserInfoHolder();\n    }\n\n    @Bean\n    @ConditionalOnMissingBean(LogoutHandler.class)\n    public LogoutHandler logoutHandler() {\n      return new DefaultLogoutHandler();\n    }\n\n    @Bean\n    public JdbcUserDetailsManager jdbcUserDetailsManager(AuthenticationManagerBuilder auth, DataSource datasource) throws Exception {\n      JdbcUserDetailsManager jdbcUserDetailsManager = auth.jdbcAuthentication().passwordEncoder(new BCryptPasswordEncoder()).dataSource(datasource)\n          .usersByUsernameQuery(\"select Username,Password,Enabled from `Users` where Username = ?\")\n          .authoritiesByUsernameQuery(\"select Username,Authority from `Authorities` where Username = ?\")\n          .getUserDetailsService();\n\n      jdbcUserDetailsManager.setUserExistsSql(\"select Username from `Users` where Username = ?\");\n      jdbcUserDetailsManager.setCreateUserSql(\"insert into `Users` (Username, Password, Enabled) values (?,?,?)\");\n      jdbcUserDetailsManager.setUpdateUserSql(\"update `Users` set Password = ?, Enabled = ? where Username = ?\");\n      jdbcUserDetailsManager.setDeleteUserSql(\"delete from `Users` where Username = ?\");\n      jdbcUserDetailsManager.setCreateAuthoritySql(\"insert into `Authorities` (Username, Authority) values (?,?)\");\n      jdbcUserDetailsManager.setDeleteUserAuthoritiesSql(\"delete from `Authorities` where Username = ?\");\n      jdbcUserDetailsManager.setChangePasswordSql(\"update `Users` set Password = ? where Username = ?\");\n\n      return jdbcUserDetailsManager;\n    }\n\n    @Bean\n    @ConditionalOnMissingBean(UserService.class)\n    public UserService springSecurityUserService() {\n      return new SpringSecurityUserService();\n    }\n\n  }\n\n  @Order(99)\n  @Profile(\"auth\")\n  @Configuration\n  @EnableWebSecurity\n  @EnableGlobalMethodSecurity(prePostEnabled = true)\n  static class SpringSecurityConfigurer extends WebSecurityConfigurerAdapter {\n\n    public static final String USER_ROLE = \"user\";\n\n    @Override\n    protected void configure(HttpSecurity http) throws Exception {\n      http.csrf().disable();\n      http.headers().frameOptions().disable();\n      http.authorizeRequests().antMatchers(\"/openapi/**\", \"/vendor/**\", \"/styles/**\", \"/scripts/**\", \"/views/**\", \"/img/**\",\"/**\").permitAll()\n      .antMatchers(\"/**\").hasAnyRole(USER_ROLE);\n      http.formLogin().loginPage(\"/signin\").permitAll().failureUrl(\"/signin?#/error\").and().httpBasic();\n      http.logout().invalidateHttpSession(true).clearAuthentication(true).logoutSuccessUrl(\"/signin?#/logout\");\n      http.exceptionHandling().authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint(\"/signin\"));\n    }\n\n  }\n\n  /**\n   * default profile\n   */\n  @Configuration\n  @ConditionalOnMissingProfile({\"ctrip\", \"auth\"})\n  static class DefaultAuthAutoConfiguration {\n\n    @Bean\n    @ConditionalOnMissingBean(SsoHeartbeatHandler.class)\n    public SsoHeartbeatHandler defaultSsoHeartbeatHandler() {\n      return new DefaultSsoHeartbeatHandler();\n    }\n\n    @Bean\n    @ConditionalOnMissingBean(UserInfoHolder.class)\n    public DefaultUserInfoHolder defaultUserInfoHolder() {\n      return new DefaultUserInfoHolder();\n    }\n\n    @Bean\n    @ConditionalOnMissingBean(LogoutHandler.class)\n    public DefaultLogoutHandler logoutHandler() {\n      return new DefaultLogoutHandler();\n    }\n\n    @Bean\n    @ConditionalOnMissingBean(UserService.class)\n    public UserService defaultUserService() {\n      return new DefaultUserService();\n    }\n  }\n\n  @ConditionalOnMissingProfile(\"auth\")\n  @Configuration\n  @EnableWebSecurity\n  @EnableGlobalMethodSecurity(prePostEnabled = true)\n  static class DefaultWebSecurityConfig extends WebSecurityConfigurerAdapter {\n\n    @Override\n    protected void configure(HttpSecurity http) throws Exception {\n      http.csrf().disable();\n      http.headers().frameOptions().disable();\n    }\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/configuration/AuthFilterConfiguration.java",
    "content": "package com.ctrip.framework.apollo.portal.spi.configuration;\n\nimport com.ctrip.framework.apollo.openapi.filter.ConsumerAuthenticationFilter;\nimport com.ctrip.framework.apollo.openapi.util.ConsumerAuditUtil;\nimport com.ctrip.framework.apollo.openapi.util.ConsumerAuthUtil;\n\nimport org.springframework.boot.context.embedded.FilterRegistrationBean;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\n\n@Configuration\npublic class AuthFilterConfiguration {\n\n  @Bean\n  public FilterRegistrationBean openApiAuthenticationFilter(ConsumerAuthUtil consumerAuthUtil,\n                                                            ConsumerAuditUtil consumerAuditUtil) {\n    FilterRegistrationBean openApiFilter = new FilterRegistrationBean();\n\n    openApiFilter.setFilter(new ConsumerAuthenticationFilter(consumerAuthUtil, consumerAuditUtil));\n    openApiFilter.addUrlPatterns(\"/openapi/*\");\n\n    return openApiFilter;\n  }\n\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/configuration/EmailConfiguration.java",
    "content": "package com.ctrip.framework.apollo.portal.spi.configuration;\n\n\nimport com.ctrip.framework.apollo.common.condition.ConditionalOnMissingProfile;\nimport com.ctrip.framework.apollo.portal.spi.EmailService;\nimport com.ctrip.framework.apollo.portal.spi.ctrip.CtripEmailService;\nimport com.ctrip.framework.apollo.portal.spi.ctrip.CtripEmailRequestBuilder;\nimport com.ctrip.framework.apollo.portal.spi.defaultimpl.DefaultEmailService;\n\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.context.annotation.Profile;\n\n@Configuration\npublic class EmailConfiguration {\n\n  /**\n   * spring.profiles.active = ctrip\n   */\n  @Configuration\n  @Profile(\"ctrip\")\n  public static class CtripEmailConfiguration {\n\n    @Bean\n    public EmailService ctripEmailService() {\n      return new CtripEmailService();\n    }\n\n    @Bean\n    public CtripEmailRequestBuilder emailRequestBuilder() {\n      return new CtripEmailRequestBuilder();\n    }\n  }\n\n  /**\n   * spring.profiles.active != ctrip\n   */\n  @Configuration\n  @ConditionalOnMissingProfile({\"ctrip\"})\n  public static class DefaultEmailConfiguration {\n    @Bean\n    @ConditionalOnMissingBean(EmailService.class)\n    public EmailService defaultEmailService() {\n      return new DefaultEmailService();\n    }\n  }\n\n\n\n}\n\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/configuration/MQConfiguration.java",
    "content": "package com.ctrip.framework.apollo.portal.spi.configuration;\n\nimport com.ctrip.framework.apollo.common.condition.ConditionalOnMissingProfile;\nimport com.ctrip.framework.apollo.portal.spi.ctrip.CtripMQService;\nimport com.ctrip.framework.apollo.portal.spi.defaultimpl.DefaultMQService;\n\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.context.annotation.Profile;\n\n@Configuration\npublic class MQConfiguration {\n\n  @Configuration\n  @Profile(\"ctrip\")\n  public static class CtripMQConfiguration {\n\n    @Bean\n    public CtripMQService mqService() {\n      return new CtripMQService();\n    }\n  }\n\n  /**\n   * spring.profiles.active != ctrip\n   */\n  @Configuration\n  @ConditionalOnMissingProfile({\"ctrip\"})\n  public static class DefaultMQConfiguration {\n\n    @Bean\n    public DefaultMQService mqService() {\n      return new DefaultMQService();\n    }\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/configuration/RoleConfiguration.java",
    "content": "package com.ctrip.framework.apollo.portal.spi.configuration;\n\nimport com.ctrip.framework.apollo.portal.service.RoleInitializationService;\nimport com.ctrip.framework.apollo.portal.service.RolePermissionService;\nimport com.ctrip.framework.apollo.portal.spi.defaultimpl.DefaultRoleInitializationService;\nimport com.ctrip.framework.apollo.portal.spi.defaultimpl.DefaultRolePermissionService;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\n\n/**\n * @author Timothy Liu(timothy.liu@cvte.com)\n */\n@Configuration\npublic class RoleConfiguration {\n    @Bean\n    public RoleInitializationService roleInitializationService() {\n        return new DefaultRoleInitializationService();\n    }\n\n    @Bean\n    public RolePermissionService rolePermissionService() {\n        return new DefaultRolePermissionService();\n    }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/ctrip/BizLoggingCustomizer.java",
    "content": "package com.ctrip.framework.apollo.portal.spi.ctrip;\n\nimport com.ctrip.framework.apollo.common.customize.LoggingCustomizer;\nimport com.ctrip.framework.apollo.portal.component.config.PortalConfig;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.annotation.Profile;\nimport org.springframework.stereotype.Component;\n\n@Component\n@Profile(\"ctrip\")\npublic class BizLoggingCustomizer extends LoggingCustomizer {\n\n  @Autowired\n  private PortalConfig portalConfig;\n\n  @Override\n  protected String cloggingUrl() {\n    return portalConfig.cloggingUrl();\n  }\n\n  @Override\n  protected String cloggingPort() {\n    return portalConfig.cloggingPort();\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/ctrip/CtripEmailRequestBuilder.java",
    "content": "package com.ctrip.framework.apollo.portal.spi.ctrip;\n\nimport com.ctrip.framework.apollo.portal.component.config.PortalConfig;\nimport com.ctrip.framework.apollo.portal.entity.bo.Email;\nimport com.ctrip.framework.apollo.tracer.Tracer;\n\nimport org.apache.commons.lang.time.DateUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\n\nimport java.lang.reflect.Method;\nimport java.util.Calendar;\nimport java.util.Date;\nimport java.util.List;\n\nimport javax.annotation.PostConstruct;\n\npublic class CtripEmailRequestBuilder {\n\n  private static final Logger logger = LoggerFactory.getLogger(CtripEmailRequestBuilder.class);\n\n  private static Class sendEmailRequestClazz;\n  private static Method setBodyContent;\n  private static Method setRecipient;\n  private static Method setSendCode;\n  private static Method setBodyTemplateID;\n  private static Method setSender;\n  private static Method setSubject;\n  private static Method setIsBodyHtml;\n  private static Method setCharset;\n  private static Method setExpiredTime;\n  private static Method setAppID;\n\n  @Autowired\n  private PortalConfig portalConfig;\n\n\n  @PostConstruct\n  public void init() {\n    try {\n      sendEmailRequestClazz = Class.forName(\"com.ctrip.framework.apolloctripservice.emailservice.SendEmailRequest\");\n\n      setSendCode = sendEmailRequestClazz.getMethod(\"setSendCode\", String.class);\n      setBodyTemplateID = sendEmailRequestClazz.getMethod(\"setBodyTemplateID\", Integer.class);\n      setSender = sendEmailRequestClazz.getMethod(\"setSender\", String.class);\n      setBodyContent = sendEmailRequestClazz.getMethod(\"setBodyContent\", String.class);\n      setRecipient = sendEmailRequestClazz.getMethod(\"setRecipient\", List.class);\n      setSubject = sendEmailRequestClazz.getMethod(\"setSubject\", String.class);\n      setIsBodyHtml = sendEmailRequestClazz.getMethod(\"setIsBodyHtml\", Boolean.class);\n      setCharset = sendEmailRequestClazz.getMethod(\"setCharset\", String.class);\n      setExpiredTime = sendEmailRequestClazz.getMethod(\"setExpiredTime\", Calendar.class);\n      setAppID = sendEmailRequestClazz.getMethod(\"setAppID\", Integer.class);\n\n    } catch (Throwable e) {\n      logger.error(\"init email request build failed\", e);\n      Tracer.logError(\"init email request build failed\", e);\n    }\n  }\n\n\n  public Object buildEmailRequest(Email email) throws Exception {\n\n    Object emailRequest = createBasicEmailRequest();\n\n    setSender.invoke(emailRequest, email.getSenderEmailAddress());\n    setSubject.invoke(emailRequest, email.getSubject());\n    String emailBodyBuilder = \"<entry><content><![CDATA[<!DOCTYPE html>\" +\n            email.getBody() +\n            \"]]></content></entry>\";\n    setBodyContent.invoke(emailRequest, emailBodyBuilder);\n    setRecipient.invoke(emailRequest, email.getRecipients());\n\n    return emailRequest;\n  }\n\n  private Object createBasicEmailRequest() throws Exception {\n    Object request = sendEmailRequestClazz.newInstance();\n\n    setSendCode.invoke(request, portalConfig.sendCode());\n    setBodyTemplateID.invoke(request, portalConfig.templateId());\n    setIsBodyHtml.invoke(request, true);\n    setCharset.invoke(request, \"UTF-8\");\n    setExpiredTime.invoke(request, calExpiredTime());\n    setAppID.invoke(request, portalConfig.appId());\n\n    return request;\n  }\n\n\n  private Calendar calExpiredTime() {\n\n    Calendar calendar = Calendar.getInstance();\n    calendar.setTime(DateUtils.addHours(new Date(), portalConfig.survivalDuration()));\n\n    return calendar;\n  }\n\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/ctrip/CtripEmailService.java",
    "content": "package com.ctrip.framework.apollo.portal.spi.ctrip;\n\nimport com.ctrip.framework.apollo.portal.component.config.PortalConfig;\nimport com.ctrip.framework.apollo.portal.entity.bo.Email;\nimport com.ctrip.framework.apollo.portal.spi.EmailService;\nimport com.ctrip.framework.apollo.tracer.Tracer;\n\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\n\nimport java.lang.reflect.Method;\n\nimport javax.annotation.PostConstruct;\n\n\npublic class CtripEmailService implements EmailService {\n\n  private static final Logger logger = LoggerFactory.getLogger(CtripEmailService.class);\n\n  private Object emailServiceClient;\n  private Method sendEmailAsync;\n  private Method sendEmail;\n\n  @Autowired\n  private CtripEmailRequestBuilder emailRequestBuilder;\n  @Autowired\n  private PortalConfig portalConfig;\n\n  @PostConstruct\n  public void init() {\n    try {\n      initServiceClientConfig();\n\n      Class emailServiceClientClazz =\n              Class.forName(\"com.ctrip.framework.apolloctripservice.emailservice.EmailServiceClient\");\n\n      Method getInstanceMethod = emailServiceClientClazz.getMethod(\"getInstance\");\n      emailServiceClient = getInstanceMethod.invoke(null);\n\n      Class sendEmailRequestClazz =\n              Class.forName(\"com.ctrip.framework.apolloctripservice.emailservice.SendEmailRequest\");\n      sendEmailAsync = emailServiceClientClazz.getMethod(\"sendEmailAsync\", sendEmailRequestClazz);\n      sendEmail = emailServiceClientClazz.getMethod(\"sendEmail\", sendEmailRequestClazz);\n    } catch (Throwable e) {\n      logger.error(\"init ctrip email service failed\", e);\n      Tracer.logError(\"init ctrip email service failed\", e);\n    }\n  }\n\n  private void initServiceClientConfig() throws Exception {\n\n    Class serviceClientConfigClazz = Class.forName(\"com.ctriposs.baiji.rpc.client.ServiceClientConfig\");\n    Object serviceClientConfig = serviceClientConfigClazz.newInstance();\n    Method setFxConfigServiceUrlMethod = serviceClientConfigClazz.getMethod(\"setFxConfigServiceUrl\", String.class);\n\n    setFxConfigServiceUrlMethod.invoke(serviceClientConfig, portalConfig.soaServerAddress());\n\n    Class serviceClientBaseClazz = Class.forName(\"com.ctriposs.baiji.rpc.client.ServiceClientBase\");\n    Method initializeMethod = serviceClientBaseClazz.getMethod(\"initialize\", serviceClientConfigClazz);\n    initializeMethod.invoke(null, serviceClientConfig);\n  }\n\n  @Override\n  public void send(Email email) {\n\n    try {\n      Object emailRequest = emailRequestBuilder.buildEmailRequest(email);\n\n      Object sendResponse = portalConfig.isSendEmailAsync() ?\n              sendEmailAsync.invoke(emailServiceClient, emailRequest) :\n              sendEmail.invoke(emailServiceClient, emailRequest);\n\n      logger.info(\"Email server response: \" + sendResponse);\n\n    } catch (Throwable e) {\n      logger.error(\"send email failed\", e);\n      Tracer.logError(\"send email failed\", e);\n    }\n\n\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/ctrip/CtripLogoutHandler.java",
    "content": "package com.ctrip.framework.apollo.portal.spi.ctrip;\n\nimport com.ctrip.framework.apollo.portal.component.config.PortalConfig;\nimport com.ctrip.framework.apollo.portal.spi.LogoutHandler;\n\nimport org.springframework.beans.factory.annotation.Autowired;\n\nimport java.io.IOException;\n\nimport javax.servlet.http.Cookie;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport javax.servlet.http.HttpSession;\n\npublic class CtripLogoutHandler implements LogoutHandler {\n\n  @Autowired\n  private PortalConfig portalConfig;\n\n  @Override\n  public void logout(HttpServletRequest request, HttpServletResponse response) {\n    //将session销毁\n    HttpSession session = request.getSession(false);\n    if (session != null) {\n      session.invalidate();\n    }\n\n    Cookie cookie = new Cookie(\"memCacheAssertionID\", null);\n    //将cookie的有效期设置为0，命令浏览器删除该cookie\n    cookie.setMaxAge(0);\n    cookie.setPath(request.getContextPath() + \"/\");\n    response.addCookie(cookie);\n\n    //重定向到SSO的logout地址\n    String casServerUrl = portalConfig.casServerUrlPrefix();\n    String serverName = portalConfig.portalServerName();\n\n    try {\n      response.sendRedirect(casServerUrl + \"/logout?service=\" + serverName);\n    } catch (IOException e) {\n      throw new RuntimeException(e);\n    }\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/ctrip/CtripMQService.java",
    "content": "package com.ctrip.framework.apollo.portal.spi.ctrip;\n\nimport com.google.gson.Gson;\n\nimport com.ctrip.framework.apollo.common.entity.App;\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.portal.component.config.PortalConfig;\nimport com.ctrip.framework.apollo.portal.entity.bo.ReleaseHistoryBO;\nimport com.ctrip.framework.apollo.portal.service.AppService;\nimport com.ctrip.framework.apollo.portal.service.ReleaseService;\nimport com.ctrip.framework.apollo.portal.spi.MQService;\nimport com.ctrip.framework.apollo.tracer.Tracer;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.http.HttpEntity;\nimport org.springframework.http.HttpHeaders;\nimport org.springframework.http.MediaType;\nimport org.springframework.http.client.SimpleClientHttpRequestFactory;\nimport org.springframework.http.converter.FormHttpMessageConverter;\nimport org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;\nimport org.springframework.web.client.RestTemplate;\n\nimport java.util.Arrays;\n\nimport javax.annotation.PostConstruct;\n\n\npublic class CtripMQService implements MQService {\n\n  private static final org.apache.commons.lang.time.FastDateFormat\n      TIMESTAMP_FORMAT = org.apache.commons.lang.time.FastDateFormat.getInstance(\"yyyy-MM-dd hh:mm:ss\");\n  private static final String CONFIG_PUBLISH_NOTIFY_TO_NOC_TOPIC = \"ops.noc.record.created\";\n\n  private Gson gson = new Gson();\n\n  @Autowired\n  private AppService appService;\n  @Autowired\n  private ReleaseService releaseService;\n  @Autowired\n  private PortalConfig portalConfig;\n\n  private RestTemplate restTemplate;\n\n  @PostConstruct\n  public void init() {\n    restTemplate = new RestTemplate();\n\n    SimpleClientHttpRequestFactory rf = (SimpleClientHttpRequestFactory) restTemplate.getRequestFactory();\n    rf.setReadTimeout(portalConfig.readTimeout());\n    rf.setConnectTimeout(portalConfig.connectTimeout());\n\n    MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();\n    converter.setSupportedMediaTypes(\n        Arrays.asList(MediaType.APPLICATION_JSON, MediaType.APPLICATION_OCTET_STREAM));\n\n    restTemplate.setMessageConverters(Arrays.asList(converter, new FormHttpMessageConverter()));\n\n  }\n\n  @Override\n  public void sendPublishMsg(Env env, ReleaseHistoryBO releaseHistory) {\n    if (releaseHistory == null) {\n      return;\n    }\n\n    PublishMsg msg = buildPublishMsg(env, releaseHistory);\n\n    sendMsg(portalConfig.hermesServerAddress(), CONFIG_PUBLISH_NOTIFY_TO_NOC_TOPIC, msg);\n  }\n\n  private PublishMsg buildPublishMsg(Env env, ReleaseHistoryBO releaseHistory) {\n\n    PublishMsg msg = new PublishMsg();\n\n    msg.setPriority(\"中\");\n    msg.setTool_origin(\"Apollo\");\n\n    String appId = releaseHistory.getAppId();\n    App app = appService.load(appId);\n    msg.setInfluence_bu(app.getOrgName());\n    msg.setAppid(appId);\n    msg.setAssginee(releaseHistory.getOperator());\n    msg.setOperation_time(TIMESTAMP_FORMAT.format(releaseHistory.getReleaseTime()));\n    msg.setDesc(gson.toJson(releaseService.compare(env, releaseHistory.getPreviousReleaseId(),\n                                                   releaseHistory.getReleaseId())));\n\n    return msg;\n  }\n\n  private void sendMsg(String serverAddress, String topic, Object msg) {\n    HttpHeaders headers = new HttpHeaders();\n    headers.setContentType(MediaType.parseMediaType(MediaType.APPLICATION_OCTET_STREAM + \";charset=UTF-8\"));\n    HttpEntity<Object> request = new HttpEntity<>(msg, headers);\n\n    try {\n      //send msg by hermes RestAPI\n      restTemplate.postForObject(serverAddress + \"/topics/\" + topic, request, Object.class);\n\n    } catch (Exception e) {\n      Tracer.logError(\"Send publish msg to hermes failed\", e);\n    }\n\n  }\n\n  private class PublishMsg {\n\n    private String assginee;\n    private String desc;\n    private String operation_time;\n    private String tool_origin;\n    private String priority;\n    private String influence_bu;\n    private String appid;\n\n\n    public String getAssginee() {\n      return assginee;\n    }\n\n    public void setAssginee(String assginee) {\n      this.assginee = assginee;\n    }\n\n    public String getDesc() {\n      return desc;\n    }\n\n    public void setDesc(String desc) {\n      this.desc = desc;\n    }\n\n    public String getOperation_time() {\n      return operation_time;\n    }\n\n    public void setOperation_time(String operation_time) {\n      this.operation_time = operation_time;\n    }\n\n    public String getTool_origin() {\n      return tool_origin;\n    }\n\n    public void setTool_origin(String tool_origin) {\n      this.tool_origin = tool_origin;\n    }\n\n    public String getPriority() {\n      return priority;\n    }\n\n    public void setPriority(String priority) {\n      this.priority = priority;\n    }\n\n    public String getInfluence_bu() {\n      return influence_bu;\n    }\n\n    public void setInfluence_bu(String influence_bu) {\n      this.influence_bu = influence_bu;\n    }\n\n    public String getAppid() {\n      return appid;\n    }\n\n    public void setAppid(String appid) {\n      this.appid = appid;\n    }\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/ctrip/CtripSsoHeartbeatHandler.java",
    "content": "package com.ctrip.framework.apollo.portal.spi.ctrip;\n\nimport com.ctrip.framework.apollo.portal.spi.SsoHeartbeatHandler;\n\nimport java.io.IOException;\n\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class CtripSsoHeartbeatHandler implements SsoHeartbeatHandler {\n\n  @Override\n  public void doHeartbeat(HttpServletRequest request, HttpServletResponse response) {\n    try {\n      response.sendRedirect(\"ctrip_sso_heartbeat.html\");\n    } catch (IOException e) {\n    }\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/ctrip/CtripUserInfoHolder.java",
    "content": "package com.ctrip.framework.apollo.portal.spi.ctrip;\n\nimport com.ctrip.framework.apollo.portal.spi.UserInfoHolder;\nimport com.ctrip.framework.apollo.portal.entity.bo.UserInfo;\n\nimport java.lang.reflect.Method;\n\n/**\n * ctrip内部实现的获取用户信息\n */\npublic class CtripUserInfoHolder implements UserInfoHolder {\n\n  private Object assertionHolder;\n\n  private Method getAssertion;\n\n\n  public CtripUserInfoHolder() {\n    Class clazz = null;\n    try {\n      clazz = Class.forName(\"org.jasig.cas.client.util.AssertionHolder\");\n      assertionHolder = clazz.newInstance();\n      getAssertion = assertionHolder.getClass().getMethod(\"getAssertion\");\n    } catch (Exception e) {\n      throw new RuntimeException(\"init AssertionHolder fail\", e);\n    }\n  }\n\n  @Override\n  public UserInfo getUser() {\n    try {\n\n      Object assertion = getAssertion.invoke(assertionHolder);\n      Method getPrincipal = assertion.getClass().getMethod(\"getPrincipal\");\n      Object principal = getPrincipal.invoke(assertion);\n      Method getName = principal.getClass().getMethod(\"getName\");\n      String name = (String) getName.invoke(principal);\n\n      UserInfo userInfo = new UserInfo();\n      userInfo.setUserId(name);\n\n      return userInfo;\n    } catch (Exception e) {\n      throw new RuntimeException(\"get user info from assertion holder error\", e);\n    }\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/ctrip/CtripUserService.java",
    "content": "package com.ctrip.framework.apollo.portal.spi.ctrip;\n\nimport com.google.common.collect.ImmutableMap;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\n\nimport com.ctrip.framework.apollo.portal.component.config.PortalConfig;\nimport com.ctrip.framework.apollo.portal.entity.bo.UserInfo;\nimport com.ctrip.framework.apollo.portal.spi.UserService;\n\nimport org.springframework.core.ParameterizedTypeReference;\nimport org.springframework.http.HttpEntity;\nimport org.springframework.http.HttpMethod;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.http.client.ClientHttpRequestFactory;\nimport org.springframework.http.client.SimpleClientHttpRequestFactory;\nimport org.springframework.util.CollectionUtils;\nimport org.springframework.web.client.RestTemplate;\n\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.stream.Collectors;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class CtripUserService implements UserService {\n  private RestTemplate restTemplate;\n  private List<String> searchUserMatchFields;\n  private ParameterizedTypeReference<Map<String, List<UserServiceResponse>>> responseType;\n  private PortalConfig portalConfig;\n\n  public CtripUserService(PortalConfig portalConfig) {\n    this.portalConfig = portalConfig;\n    this.restTemplate = new RestTemplate(clientHttpRequestFactory());\n    this.searchUserMatchFields =\n        Lists.newArrayList(\"empcode\", \"empaccount\", \"displayname\", \"c_name\", \"pinyin\");\n    this.responseType = new ParameterizedTypeReference<Map<String, List<UserServiceResponse>>>() {\n    };\n  }\n\n  private ClientHttpRequestFactory clientHttpRequestFactory() {\n    SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();\n    factory.setConnectTimeout(portalConfig.connectTimeout());\n    factory.setReadTimeout(portalConfig.readTimeout());\n\n    return factory;\n  }\n\n  @Override\n  public List<UserInfo> searchUsers(String keyword, int offset, int limit) {\n    UserServiceRequest request = assembleSearchUserRequest(keyword, offset, limit);\n\n    HttpEntity<UserServiceRequest> entity = new HttpEntity<>(request);\n    ResponseEntity<Map<String, List<UserServiceResponse>>> response =\n        restTemplate.exchange(portalConfig.userServiceUrl(), HttpMethod.POST, entity, responseType);\n\n    if (!response.getBody().containsKey(\"result\")) {\n      return Collections.emptyList();\n    }\n\n    List<UserInfo> result = Lists.newArrayList();\n    result.addAll(\n        response.getBody().get(\"result\").stream().map(this::transformUserServiceResponseToUserInfo)\n            .collect(Collectors.toList()));\n\n    return result;\n  }\n\n  @Override\n  public UserInfo findByUserId(String userId) {\n    List<UserInfo> userInfoList = this.findByUserIds(Lists.newArrayList(userId));\n    if (CollectionUtils.isEmpty(userInfoList)) {\n      return null;\n    }\n    return userInfoList.get(0);\n  }\n\n  public List<UserInfo> findByUserIds(List<String> userIds) {\n    UserServiceRequest request = assembleFindUserRequest(Lists.newArrayList(userIds));\n\n    HttpEntity<UserServiceRequest> entity = new HttpEntity<>(request);\n    ResponseEntity<Map<String, List<UserServiceResponse>>> response =\n        restTemplate.exchange(portalConfig.userServiceUrl(), HttpMethod.POST, entity, responseType);\n\n    if (!response.getBody().containsKey(\"result\")) {\n      return Collections.emptyList();\n    }\n\n    List<UserInfo> result = Lists.newArrayList();\n    result.addAll(\n        response.getBody().get(\"result\").stream().map(this::transformUserServiceResponseToUserInfo)\n            .collect(Collectors.toList()));\n\n    return result;\n  }\n\n  private UserInfo transformUserServiceResponseToUserInfo(UserServiceResponse userServiceResponse) {\n    UserInfo userInfo = new UserInfo();\n    userInfo.setUserId(userServiceResponse.getEmpaccount());\n    userInfo.setName(userServiceResponse.getDisplayname());\n    userInfo.setEmail(userServiceResponse.getEmail());\n    return userInfo;\n  }\n\n  UserServiceRequest assembleSearchUserRequest(String keyword, int offset, int limit) {\n    Map<String, Object> query = Maps.newHashMap();\n    Map<String, Object> multiMatchMap = Maps.newHashMap();\n    multiMatchMap.put(\"fields\", searchUserMatchFields);\n    multiMatchMap.put(\"operator\", \"and\");\n    multiMatchMap.put(\"query\", keyword);\n    multiMatchMap.put(\"type\", \"best_fields\");\n    query.put(\"multi_match\", multiMatchMap);\n\n    return assembleUserServiceRequest(query, offset, limit);\n  }\n\n  UserServiceRequest assembleFindUserRequest(List<String> userIds) {\n    Map<String, Object>\n        query =\n        ImmutableMap.of(\"filtered\", ImmutableMap\n            .of(\"filter\", ImmutableMap.of(\"terms\", ImmutableMap.of(\"empaccount\", userIds))));\n\n    return assembleUserServiceRequest(query, 0, userIds.size());\n  }\n\n  private UserServiceRequest assembleUserServiceRequest(Map<String, Object> query, int offset,\n                                                        int limit) {\n    UserServiceRequest request = new UserServiceRequest();\n    request.setAccess_token(portalConfig.userServiceAccessToken());\n\n    UserServiceRequestBody requestBody = new UserServiceRequestBody();\n    requestBody.setIndexAlias(\"itdb_emloyee\");\n    requestBody.setType(\"emloyee\");\n    request.setRequest_body(requestBody);\n\n    Map<String, Object> queryJson = Maps.newHashMap();\n    requestBody.setQueryJson(queryJson);\n\n    queryJson.put(\"query\", query);\n\n    queryJson.put(\"from\", offset);\n    queryJson.put(\"size\", limit);\n\n    return request;\n  }\n\n\n  static class UserServiceRequest {\n    private String access_token;\n    private UserServiceRequestBody request_body;\n\n    public String getAccess_token() {\n      return access_token;\n    }\n\n    public void setAccess_token(String access_token) {\n      this.access_token = access_token;\n    }\n\n    public UserServiceRequestBody getRequest_body() {\n      return request_body;\n    }\n\n    public void setRequest_body(\n        UserServiceRequestBody request_body) {\n      this.request_body = request_body;\n    }\n  }\n\n  static class UserServiceRequestBody {\n    private String indexAlias;\n    private String type;\n    private Map<String, Object> queryJson;\n\n    public String getType() {\n      return type;\n    }\n\n    public void setType(String type) {\n      this.type = type;\n    }\n\n    public String getIndexAlias() {\n      return indexAlias;\n    }\n\n    public void setIndexAlias(String indexAlias) {\n      this.indexAlias = indexAlias;\n    }\n\n    public Map<String, Object> getQueryJson() {\n      return queryJson;\n    }\n\n    public void setQueryJson(Map<String, Object> queryJson) {\n      this.queryJson = queryJson;\n    }\n  }\n\n  static class UserServiceResponse {\n    private String empaccount;\n    private String displayname;\n    private String email;\n\n    public String getEmpaccount() {\n      return empaccount;\n    }\n\n    public void setEmpaccount(String empaccount) {\n      this.empaccount = empaccount;\n    }\n\n    public String getDisplayname() {\n      return displayname;\n    }\n\n    public void setDisplayname(String displayname) {\n      this.displayname = displayname;\n    }\n\n    public String getEmail() {\n      return email;\n    }\n\n    public void setEmail(String email) {\n      this.email = email;\n    }\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/ctrip/WebContextConfiguration.java",
    "content": "package com.ctrip.framework.apollo.portal.spi.ctrip;\n\nimport com.ctrip.framework.apollo.portal.spi.ctrip.filters.UserAccessFilter;\nimport com.google.common.base.Strings;\n\nimport com.ctrip.framework.apollo.portal.component.config.PortalConfig;\nimport com.ctrip.framework.apollo.portal.spi.UserInfoHolder;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.context.embedded.FilterRegistrationBean;\nimport org.springframework.boot.context.embedded.ServletContextInitializer;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.context.annotation.Profile;\n\nimport javax.servlet.ServletContext;\nimport javax.servlet.ServletException;\n\n@Configuration\n@Profile(\"ctrip\")\npublic class WebContextConfiguration {\n\n  @Autowired\n  private PortalConfig portalConfig;\n  @Autowired\n  private UserInfoHolder userInfoHolder;\n\n  @Bean\n  public ServletContextInitializer servletContextInitializer() {\n\n    return new ServletContextInitializer() {\n\n      @Override\n      public void onStartup(ServletContext servletContext) throws ServletException {\n        String loggingServerIP = portalConfig.cloggingUrl();\n        String loggingServerPort = portalConfig.cloggingPort();\n        String credisServiceUrl = portalConfig.credisServiceUrl();\n\n        servletContext.setInitParameter(\"loggingServerIP\",\n            Strings.isNullOrEmpty(loggingServerIP) ? \"\" : loggingServerIP);\n        servletContext.setInitParameter(\"loggingServerPort\",\n            Strings.isNullOrEmpty(loggingServerPort) ? \"\" : loggingServerPort);\n        servletContext.setInitParameter(\"credisServiceUrl\",\n            Strings.isNullOrEmpty(credisServiceUrl) ? \"\" : credisServiceUrl);\n      }\n    };\n  }\n\n  @Bean\n  public FilterRegistrationBean userAccessFilter() {\n    FilterRegistrationBean filter = new FilterRegistrationBean();\n    filter.setFilter(new UserAccessFilter(userInfoHolder));\n    filter.addUrlPatterns(\"/*\");\n    return filter;\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/ctrip/filters/UserAccessFilter.java",
    "content": "package com.ctrip.framework.apollo.portal.spi.ctrip.filters;\n\nimport com.ctrip.framework.apollo.portal.constant.TracerEventType;\nimport com.ctrip.framework.apollo.portal.entity.bo.UserInfo;\nimport com.ctrip.framework.apollo.portal.spi.UserInfoHolder;\nimport com.ctrip.framework.apollo.tracer.Tracer;\n\nimport com.google.common.base.Strings;\n\nimport javax.servlet.*;\nimport javax.servlet.http.HttpServletRequest;\n\nimport java.io.IOException;\n\npublic class UserAccessFilter implements Filter {\n\n  private static final String STATIC_RESOURCE_REGEX = \".*\\\\.(js|html|htm|png|css|woff2)$\";\n\n  private UserInfoHolder userInfoHolder;\n\n  public UserAccessFilter(UserInfoHolder userInfoHolder) {\n    this.userInfoHolder = userInfoHolder;\n  }\n\n  @Override\n  public void init(FilterConfig filterConfig) throws ServletException {\n\n  }\n\n  @Override\n  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)\n      throws IOException, ServletException {\n\n    String requestUri = ((HttpServletRequest) request).getRequestURI();\n\n    try {\n      if (!isOpenAPIRequest(requestUri) && !isStaticResource(requestUri)) {\n        UserInfo userInfo = userInfoHolder.getUser();\n        if (userInfo != null) {\n          Tracer.logEvent(TracerEventType.USER_ACCESS, userInfo.getUserId());\n        }\n      }\n    } catch (Throwable e) {\n      Tracer.logError(\"Record user access info error.\", e);\n    }\n\n    chain.doFilter(request, response);\n  }\n\n  @Override\n  public void destroy() {\n\n  }\n\n  private boolean isOpenAPIRequest(String uri) {\n    return !Strings.isNullOrEmpty(uri) && uri.startsWith(\"/openapi\");\n  }\n\n  private boolean isStaticResource(String uri) {\n    return !Strings.isNullOrEmpty(uri) && uri.matches(STATIC_RESOURCE_REGEX);\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/defaultimpl/DefaultEmailService.java",
    "content": "package com.ctrip.framework.apollo.portal.spi.defaultimpl;\n\nimport com.ctrip.framework.apollo.portal.entity.bo.Email;\nimport com.ctrip.framework.apollo.portal.spi.EmailService;\n\npublic class DefaultEmailService implements EmailService{\n\n  @Override\n  public void send(Email email){\n    //do nothing\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/defaultimpl/DefaultLogoutHandler.java",
    "content": "package com.ctrip.framework.apollo.portal.spi.defaultimpl;\n\nimport com.ctrip.framework.apollo.portal.spi.LogoutHandler;\n\nimport java.io.IOException;\n\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\npublic class DefaultLogoutHandler implements LogoutHandler {\n\n  @Override\n  public void logout(HttpServletRequest request, HttpServletResponse response) {\n    try {\n      response.sendRedirect(\"/\");\n    } catch (IOException e) {\n      throw new RuntimeException(e);\n    }\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/defaultimpl/DefaultMQService.java",
    "content": "package com.ctrip.framework.apollo.portal.spi.defaultimpl;\n\nimport com.ctrip.framework.apollo.core.enums.Env;\nimport com.ctrip.framework.apollo.portal.entity.bo.ReleaseHistoryBO;\nimport com.ctrip.framework.apollo.portal.spi.MQService;\n\npublic class DefaultMQService implements MQService{\n\n  @Override\n  public void sendPublishMsg(Env env, ReleaseHistoryBO releaseHistory) {\n    //do nothing\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/defaultimpl/DefaultRoleInitializationService.java",
    "content": "package com.ctrip.framework.apollo.portal.spi.defaultimpl;\n\nimport com.google.common.collect.FluentIterable;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Sets;\n\nimport com.ctrip.framework.apollo.common.entity.App;\nimport com.ctrip.framework.apollo.core.ConfigConsts;\nimport com.ctrip.framework.apollo.portal.constant.PermissionType;\nimport com.ctrip.framework.apollo.portal.constant.RoleType;\nimport com.ctrip.framework.apollo.portal.entity.po.Permission;\nimport com.ctrip.framework.apollo.portal.entity.po.Role;\nimport com.ctrip.framework.apollo.portal.service.RoleInitializationService;\nimport com.ctrip.framework.apollo.portal.service.RolePermissionService;\nimport com.ctrip.framework.apollo.portal.spi.UserInfoHolder;\nimport com.ctrip.framework.apollo.portal.util.RoleUtils;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.transaction.annotation.Transactional;\n\nimport java.util.Set;\n\n/**\n * Created by timothy on 2017/4/26.\n */\npublic class DefaultRoleInitializationService implements RoleInitializationService {\n\n  @Autowired\n  private UserInfoHolder userInfoHolder;\n  @Autowired\n  private RolePermissionService rolePermissionService;\n\n  @Transactional\n  public void initAppRoles(App app) {\n    String appId = app.getAppId();\n\n    String appMasterRoleName = RoleUtils.buildAppMasterRoleName(appId);\n\n    //has created before\n    if (rolePermissionService.findRoleByRoleName(appMasterRoleName) != null) {\n      return;\n    }\n    String operator = app.getDataChangeCreatedBy();\n    //create app permissions\n    createAppMasterRole(appId, operator);\n\n    //assign master role to user\n    rolePermissionService\n        .assignRoleToUsers(RoleUtils.buildAppMasterRoleName(appId), Sets.newHashSet(app.getOwnerName()),\n                           operator);\n\n    initNamespaceRoles(appId, ConfigConsts.NAMESPACE_APPLICATION, operator);\n\n    //assign modify、release namespace role to user\n    rolePermissionService.assignRoleToUsers(\n        RoleUtils.buildNamespaceRoleName(appId, ConfigConsts.NAMESPACE_APPLICATION, RoleType.MODIFY_NAMESPACE),\n        Sets.newHashSet(operator), operator);\n    rolePermissionService.assignRoleToUsers(\n        RoleUtils.buildNamespaceRoleName(appId, ConfigConsts.NAMESPACE_APPLICATION, RoleType.RELEASE_NAMESPACE),\n        Sets.newHashSet(operator), operator);\n\n  }\n\n  @Transactional\n  public void initNamespaceRoles(String appId, String namespaceName, String operator) {\n\n    String modifyNamespaceRoleName = RoleUtils.buildModifyNamespaceRoleName(appId, namespaceName);\n    if (rolePermissionService.findRoleByRoleName(modifyNamespaceRoleName) == null) {\n      createNamespaceRole(appId, namespaceName, PermissionType.MODIFY_NAMESPACE,\n                          RoleUtils.buildModifyNamespaceRoleName(appId, namespaceName), operator);\n    }\n\n    String releaseNamespaceRoleName = RoleUtils.buildReleaseNamespaceRoleName(appId, namespaceName);\n    if (rolePermissionService.findRoleByRoleName(releaseNamespaceRoleName) == null) {\n      createNamespaceRole(appId, namespaceName, PermissionType.RELEASE_NAMESPACE,\n                          RoleUtils.buildReleaseNamespaceRoleName(appId, namespaceName), operator);\n    }\n  }\n\n  private void createAppMasterRole(String appId, String operator) {\n    Set<Permission> appPermissions =\n        FluentIterable.from(Lists.newArrayList(\n            PermissionType.CREATE_CLUSTER, PermissionType.CREATE_NAMESPACE, PermissionType.ASSIGN_ROLE))\n            .transform(permissionType -> createPermission(appId, permissionType, operator)).toSet();\n    Set<Permission> createdAppPermissions = rolePermissionService.createPermissions(appPermissions);\n    Set<Long>\n        appPermissionIds =\n        FluentIterable.from(createdAppPermissions).transform(permission -> permission.getId()).toSet();\n\n    //create app master role\n    Role appMasterRole = createRole(RoleUtils.buildAppMasterRoleName(appId), operator);\n\n    rolePermissionService.createRoleWithPermissions(appMasterRole, appPermissionIds);\n  }\n\n  private Permission createPermission(String targetId, String permissionType, String operator) {\n    Permission permission = new Permission();\n    permission.setPermissionType(permissionType);\n    permission.setTargetId(targetId);\n    permission.setDataChangeCreatedBy(operator);\n    permission.setDataChangeLastModifiedBy(operator);\n    return permission;\n  }\n\n  private Role createRole(String roleName, String operator) {\n    Role role = new Role();\n    role.setRoleName(roleName);\n    role.setDataChangeCreatedBy(operator);\n    role.setDataChangeLastModifiedBy(operator);\n    return role;\n  }\n\n  private void createNamespaceRole(String appId, String namespaceName, String permissionType,\n                                   String roleName, String operator) {\n\n    Permission permission =\n        createPermission(RoleUtils.buildNamespaceTargetId(appId, namespaceName), permissionType, operator);\n    Permission createdPermission = rolePermissionService.createPermission(permission);\n\n    Role role = createRole(roleName, operator);\n    rolePermissionService\n        .createRoleWithPermissions(role, Sets.newHashSet(createdPermission.getId()));\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/defaultimpl/DefaultRolePermissionService.java",
    "content": "package com.ctrip.framework.apollo.portal.spi.defaultimpl;\n\nimport com.ctrip.framework.apollo.portal.component.config.PortalConfig;\nimport com.ctrip.framework.apollo.portal.entity.bo.UserInfo;\nimport com.ctrip.framework.apollo.portal.entity.po.Permission;\nimport com.ctrip.framework.apollo.portal.entity.po.Role;\nimport com.ctrip.framework.apollo.portal.entity.po.RolePermission;\nimport com.ctrip.framework.apollo.portal.entity.po.UserRole;\nimport com.ctrip.framework.apollo.portal.repository.PermissionRepository;\nimport com.ctrip.framework.apollo.portal.repository.RolePermissionRepository;\nimport com.ctrip.framework.apollo.portal.repository.RoleRepository;\nimport com.ctrip.framework.apollo.portal.repository.UserRoleRepository;\nimport com.ctrip.framework.apollo.portal.service.RolePermissionService;\nimport com.google.common.base.Preconditions;\nimport com.google.common.collect.FluentIterable;\nimport com.google.common.collect.HashMultimap;\nimport com.google.common.collect.Multimap;\nimport com.google.common.collect.Sets;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.transaction.annotation.Transactional;\nimport org.springframework.util.CollectionUtils;\n\nimport java.util.*;\n\n/**\n * Created by timothy on 2017/4/26.\n */\npublic class DefaultRolePermissionService implements RolePermissionService {\n    @Autowired\n    private RoleRepository roleRepository;\n    @Autowired\n    private RolePermissionRepository rolePermissionRepository;\n    @Autowired\n    private UserRoleRepository userRoleRepository;\n    @Autowired\n    private PermissionRepository permissionRepository;\n    @Autowired\n    private PortalConfig portalConfig;\n\n\n    /**\n     * Create role with permissions, note that role name should be unique\n     */\n    @Transactional\n    public Role createRoleWithPermissions(Role role, Set<Long> permissionIds) {\n        Role current = findRoleByRoleName(role.getRoleName());\n        Preconditions.checkState(current == null, \"Role %s already exists!\", role.getRoleName());\n\n        Role createdRole = roleRepository.save(role);\n\n        if (!CollectionUtils.isEmpty(permissionIds)) {\n            Iterable<RolePermission> rolePermissions = FluentIterable.from(permissionIds).transform(\n                    permissionId -> {\n                        RolePermission rolePermission = new RolePermission();\n                        rolePermission.setRoleId(createdRole.getId());\n                        rolePermission.setPermissionId(permissionId);\n                        rolePermission.setDataChangeCreatedBy(createdRole.getDataChangeCreatedBy());\n                        rolePermission.setDataChangeLastModifiedBy(createdRole.getDataChangeLastModifiedBy());\n                        return rolePermission;\n                    });\n            rolePermissionRepository.save(rolePermissions);\n        }\n\n        return createdRole;\n    }\n\n    /**\n     * Assign role to users\n     *\n     * @return the users assigned roles\n     */\n    @Transactional\n    public Set<String> assignRoleToUsers(String roleName, Set<String> userIds,\n                                         String operatorUserId) {\n        Role role = findRoleByRoleName(roleName);\n        Preconditions.checkState(role != null, \"Role %s doesn't exist!\", roleName);\n\n        List<UserRole> existedUserRoles =\n                userRoleRepository.findByUserIdInAndRoleId(userIds, role.getId());\n        Set<String> existedUserIds =\n                FluentIterable.from(existedUserRoles).transform(userRole -> userRole.getUserId()).toSet();\n\n        Set<String> toAssignUserIds = Sets.difference(userIds, existedUserIds);\n\n        Iterable<UserRole> toCreate = FluentIterable.from(toAssignUserIds).transform(userId -> {\n            UserRole userRole = new UserRole();\n            userRole.setRoleId(role.getId());\n            userRole.setUserId(userId);\n            userRole.setDataChangeCreatedBy(operatorUserId);\n            userRole.setDataChangeLastModifiedBy(operatorUserId);\n            return userRole;\n        });\n\n        userRoleRepository.save(toCreate);\n        return toAssignUserIds;\n    }\n\n    /**\n     * Remove role from users\n     */\n    @Transactional\n    public void removeRoleFromUsers(String roleName, Set<String> userIds, String operatorUserId) {\n        Role role = findRoleByRoleName(roleName);\n        Preconditions.checkState(role != null, \"Role %s doesn't exist!\", roleName);\n\n        List<UserRole> existedUserRoles =\n                userRoleRepository.findByUserIdInAndRoleId(userIds, role.getId());\n\n        for (UserRole userRole : existedUserRoles) {\n            userRole.setDeleted(true);\n            userRole.setDataChangeLastModifiedTime(new Date());\n            userRole.setDataChangeLastModifiedBy(operatorUserId);\n        }\n\n        userRoleRepository.save(existedUserRoles);\n    }\n\n    /**\n     * Query users with role\n     */\n    public Set<UserInfo> queryUsersWithRole(String roleName) {\n        Role role = findRoleByRoleName(roleName);\n\n        if (role == null) {\n            return Collections.emptySet();\n        }\n\n        List<UserRole> userRoles = userRoleRepository.findByRoleId(role.getId());\n\n        Set<UserInfo> users = FluentIterable.from(userRoles).transform(userRole -> {\n            UserInfo userInfo = new UserInfo();\n            userInfo.setUserId(userRole.getUserId());\n            return userInfo;\n        }).toSet();\n\n        return users;\n    }\n\n    /**\n     * Find role by role name, note that roleName should be unique\n     */\n    public Role findRoleByRoleName(String roleName) {\n        return roleRepository.findTopByRoleName(roleName);\n    }\n\n    /**\n     * Check whether user has the permission\n     */\n    public boolean userHasPermission(String userId, String permissionType, String targetId) {\n        Permission permission =\n                permissionRepository.findTopByPermissionTypeAndTargetId(permissionType, targetId);\n        if (permission == null) {\n            return false;\n        }\n\n        if (isSuperAdmin(userId)) {\n            return true;\n        }\n\n        List<UserRole> userRoles = userRoleRepository.findByUserId(userId);\n        if (CollectionUtils.isEmpty(userRoles)) {\n            return false;\n        }\n\n        Set<Long> roleIds =\n                FluentIterable.from(userRoles).transform(userRole -> userRole.getRoleId()).toSet();\n        List<RolePermission> rolePermissions = rolePermissionRepository.findByRoleIdIn(roleIds);\n        if (CollectionUtils.isEmpty(rolePermissions)) {\n            return false;\n        }\n\n        for (RolePermission rolePermission : rolePermissions) {\n            if (rolePermission.getPermissionId() == permission.getId()) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    public boolean isSuperAdmin(String userId) {\n        return portalConfig.superAdmins().contains(userId);\n    }\n\n    /**\n     * Create permission, note that permissionType + targetId should be unique\n     */\n    @Transactional\n    public Permission createPermission(Permission permission) {\n        String permissionType = permission.getPermissionType();\n        String targetId = permission.getTargetId();\n        Permission current =\n                permissionRepository.findTopByPermissionTypeAndTargetId(permissionType, targetId);\n        Preconditions.checkState(current == null,\n                \"Permission with permissionType %s targetId %s already exists!\", permissionType, targetId);\n\n        return permissionRepository.save(permission);\n    }\n\n    /**\n     * Create permissions, note that permissionType + targetId should be unique\n     */\n    @Transactional\n    public Set<Permission> createPermissions(Set<Permission> permissions) {\n        Multimap<String, String> targetIdPermissionTypes = HashMultimap.create();\n        for (Permission permission : permissions) {\n            targetIdPermissionTypes.put(permission.getTargetId(), permission.getPermissionType());\n        }\n\n        for (String targetId : targetIdPermissionTypes.keySet()) {\n            Collection<String> permissionTypes = targetIdPermissionTypes.get(targetId);\n            List<Permission> current =\n                    permissionRepository.findByPermissionTypeInAndTargetId(permissionTypes, targetId);\n            Preconditions.checkState(CollectionUtils.isEmpty(current),\n                    \"Permission with permissionType %s targetId %s already exists!\", permissionTypes,\n                    targetId);\n        }\n\n        Iterable<Permission> results = permissionRepository.save(permissions);\n        return FluentIterable.from(results).toSet();\n    }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/defaultimpl/DefaultSsoHeartbeatHandler.java",
    "content": "package com.ctrip.framework.apollo.portal.spi.defaultimpl;\n\nimport com.ctrip.framework.apollo.portal.spi.SsoHeartbeatHandler;\n\nimport java.io.IOException;\n\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class DefaultSsoHeartbeatHandler implements SsoHeartbeatHandler {\n\n  @Override\n  public void doHeartbeat(HttpServletRequest request, HttpServletResponse response) {\n    try {\n        response.sendRedirect(\"default_sso_heartbeat.html\");\n    } catch (IOException e) {\n    }\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/defaultimpl/DefaultUserInfoHolder.java",
    "content": "package com.ctrip.framework.apollo.portal.spi.defaultimpl;\n\nimport com.ctrip.framework.apollo.portal.spi.UserInfoHolder;\nimport com.ctrip.framework.apollo.portal.entity.bo.UserInfo;\n\n/**\n * 不是ctrip的公司默认提供一个假用户\n */\npublic class DefaultUserInfoHolder implements UserInfoHolder {\n\n\n  public DefaultUserInfoHolder() {\n\n  }\n\n  @Override\n  public UserInfo getUser() {\n    UserInfo userInfo = new UserInfo();\n    userInfo.setUserId(\"apollo\");\n    return userInfo;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/defaultimpl/DefaultUserService.java",
    "content": "package com.ctrip.framework.apollo.portal.spi.defaultimpl;\n\nimport com.google.common.collect.Lists;\n\nimport com.ctrip.framework.apollo.portal.entity.bo.UserInfo;\nimport com.ctrip.framework.apollo.portal.spi.UserService;\n\nimport java.util.Arrays;\nimport java.util.List;\n\n/**\n * @author Jason Song(song_s@ctrip.com)\n */\npublic class DefaultUserService implements UserService {\n\n  @Override\n  public List<UserInfo> searchUsers(String keyword, int offset, int limit) {\n    return Arrays.asList(assembleDefaultUser());\n  }\n\n  @Override\n  public UserInfo findByUserId(String userId) {\n    if (userId.equals(\"apollo\")) {\n      return assembleDefaultUser();\n    }\n    return null;\n  }\n\n  @Override\n  public List<UserInfo> findByUserIds(List<String> userIds) {\n    if (userIds.contains(\"apollo\")) {\n      return Lists.newArrayList(assembleDefaultUser());\n    }\n    return null;\n  }\n\n  private UserInfo assembleDefaultUser() {\n    UserInfo defaultUser = new UserInfo();\n    defaultUser.setUserId(\"apollo\");\n    defaultUser.setName(\"apollo\");\n    defaultUser.setEmail(\"apollo@acme.com\");\n\n    return defaultUser;\n  }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/package-info.java",
    "content": "/**\n * This package defines common interfaces so that each company could provide their own implementations.<br/>\n * Currently we provide 2 implementations: Ctrip and Default.<br/>\n * Ctrip implementation will be activated only when spring.profiles.active = ctrip.\n * So if spring.profiles.active is not ctrip, the default implementation will be activated.\n * You may refer com.ctrip.framework.apollo.portal.spi.configuration.AuthConfiguration when providing your own implementation.\n *\n * @see com.ctrip.framework.apollo.portal.spi.configuration.AuthConfiguration\n */\npackage com.ctrip.framework.apollo.portal.spi;\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/springsecurity/SpringSecurityUserInfoHolder.java",
    "content": "package com.ctrip.framework.apollo.portal.spi.springsecurity;\n\nimport com.ctrip.framework.apollo.portal.entity.bo.UserInfo;\nimport com.ctrip.framework.apollo.portal.spi.UserInfoHolder;\n\nimport org.springframework.security.core.context.SecurityContextHolder;\nimport org.springframework.security.core.userdetails.UserDetails;\n\nimport java.security.Principal;\n\npublic class SpringSecurityUserInfoHolder implements UserInfoHolder {\n\n  @Override\n  public UserInfo getUser() {\n    UserInfo userInfo = new UserInfo();\n    userInfo.setUserId(getCurrentUsername());\n    return userInfo;\n  }\n\n  private String getCurrentUsername() {\n    Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();\n    if (principal instanceof UserDetails) {\n      return ((UserDetails) principal).getUsername();\n    }\n    if (principal instanceof Principal) {\n      return ((Principal) principal).getName();\n    }\n    return String.valueOf(principal);\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/springsecurity/SpringSecurityUserService.java",
    "content": "package com.ctrip.framework.apollo.portal.spi.springsecurity;\n\nimport com.google.common.collect.Lists;\n\nimport com.ctrip.framework.apollo.core.utils.StringUtils;\nimport com.ctrip.framework.apollo.portal.entity.bo.UserInfo;\nimport com.ctrip.framework.apollo.portal.entity.po.UserPO;\nimport com.ctrip.framework.apollo.portal.repository.UserRepository;\nimport com.ctrip.framework.apollo.portal.spi.UserService;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.security.core.GrantedAuthority;\nimport org.springframework.security.core.authority.SimpleGrantedAuthority;\nimport org.springframework.security.core.userdetails.User;\nimport org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;\nimport org.springframework.security.crypto.password.PasswordEncoder;\nimport org.springframework.security.provisioning.JdbcUserDetailsManager;\nimport org.springframework.transaction.annotation.Transactional;\nimport org.springframework.util.CollectionUtils;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.stream.Collectors;\n\nimport javax.annotation.PostConstruct;\n\n/**\n * @author lepdou 2017-03-10\n */\npublic class SpringSecurityUserService implements UserService {\n\n  private PasswordEncoder encoder = new BCryptPasswordEncoder();\n  private List<GrantedAuthority> authorities;\n\n  @Autowired\n  private JdbcUserDetailsManager userDetailsManager;\n  @Autowired\n  private UserRepository userRepository;\n\n  @PostConstruct\n  public void init() {\n    authorities = new ArrayList<>();\n    authorities.add(new SimpleGrantedAuthority(\"ROLE_user\"));\n  }\n\n  @Transactional\n  public void createOrUpdate(UserPO user) {\n    String username = user.getUsername();\n\n    User userDetails = new User(username, encoder.encode(user.getPassword()), authorities);\n\n    if (userDetailsManager.userExists(username)) {\n      userDetailsManager.updateUser(userDetails);\n    } else {\n      userDetailsManager.createUser(userDetails);\n    }\n\n    UserPO managedUser = userRepository.findByUsername(username);\n    managedUser.setEmail(user.getEmail());\n\n    userRepository.save(managedUser);\n  }\n\n  @Override\n  public List<UserInfo> searchUsers(String keyword, int offset, int limit) {\n    List<UserPO> users;\n    if (StringUtils.isEmpty(keyword)) {\n      users = userRepository.findFirst20ByEnabled(1);\n    } else {\n      users = userRepository.findByUsernameLikeAndEnabled(\"%\" + keyword + \"%\", 1);\n    }\n\n    List<UserInfo> result = Lists.newArrayList();\n    if (CollectionUtils.isEmpty(users)) {\n      return result;\n    }\n\n    result.addAll(users.stream().map(UserPO::toUserInfo).collect(Collectors.toList()));\n\n    return result;\n  }\n\n  @Override\n  public UserInfo findByUserId(String userId) {\n    UserPO userPO = userRepository.findByUsername(userId);\n    return userPO == null ? null : userPO.toUserInfo();\n  }\n\n  @Override\n  public List<UserInfo> findByUserIds(List<String> userIds) {\n    return null;\n  }\n\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/util/RelativeDateFormat.java",
    "content": "package com.ctrip.framework.apollo.portal.util;\n\nimport org.apache.commons.lang.time.FastDateFormat;\n\nimport java.util.Calendar;\nimport java.util.Date;\n\n\npublic class RelativeDateFormat {\n  private static final FastDateFormat TIMESTAMP_FORMAT = FastDateFormat.getInstance(\"yyyy-MM-dd\");\n  private static final long ONE_MINUTE = 60000L;\n  private static final long ONE_HOUR = 3600000L;\n  private static final long ONE_DAY = 86400000L;\n\n  private static final String ONE_SECOND_AGO = \"秒前\";\n  private static final String ONE_MINUTE_AGO = \"分钟前\";\n  private static final String ONE_HOUR_AGO = \"小时前\";\n  private static final String ONE_DAY_AGO = \"天前\";\n  private static final String ONE_MONTH_AGO = \"月前\";\n\n  public static String format(Date date) {\n    if (date.after(new Date())) {\n      return \"now\";\n    }\n\n    long delta = new Date().getTime() - date.getTime();\n    if (delta < ONE_MINUTE) {\n      long seconds = toSeconds(delta);\n      return (seconds <= 0 ? 1 : seconds) + ONE_SECOND_AGO;\n    }\n    if (delta < 45L * ONE_MINUTE) {\n      long minutes = toMinutes(delta);\n      return (minutes <= 0 ? 1 : minutes) + ONE_MINUTE_AGO;\n    }\n    if (delta < 24L * ONE_HOUR) {\n      long hours = toHours(delta);\n      return (hours <= 0 ? 1 : hours) + ONE_HOUR_AGO;\n    }\n\n    Date lastDayBeginTime = getDateOffset(-1);\n    if (date.after(lastDayBeginTime)) {\n      return \"昨天\";\n    }\n    Date lastTwoDaysBeginTime = getDateOffset(-2);\n    if (date.after(lastTwoDaysBeginTime)) {\n      return \"前天\";\n    }\n    if (delta < 30L * ONE_DAY) {\n      long days = toDays(delta);\n      return (days <= 0 ? 1 : days) + ONE_DAY_AGO;\n    }\n\n    long months = toMonths(delta);\n    if (months <= 3) {\n      return (months <= 0 ? 1 : months) + ONE_MONTH_AGO;\n    } else {\n      return TIMESTAMP_FORMAT.format(date);\n    }\n  }\n\n  private static long toSeconds(long date) {\n    return date / 1000L;\n  }\n\n  private static long toMinutes(long date) {\n    return toSeconds(date) / 60L;\n  }\n\n  private static long toHours(long date) {\n    return toMinutes(date) / 60L;\n  }\n\n  private static long toDays(long date) {\n    return toHours(date) / 24L;\n  }\n\n  private static long toMonths(long date) {\n    return toDays(date) / 30L;\n  }\n\n  public static Date getDateOffset(int offset) {\n    Calendar calendar = Calendar.getInstance();\n    calendar.setTime(new Date());\n    calendar.add(calendar.DATE, offset);\n\n    return getDayBeginTime(calendar.getTime());\n  }\n\n  private static Date getDayBeginTime(Date date) {\n    Calendar calendar = Calendar.getInstance();\n    calendar.setTime(date);\n    calendar.set(Calendar.HOUR, 0);\n    calendar.set(Calendar.MINUTE, 0);\n    calendar.set(Calendar.SECOND, 0);\n    calendar.set(Calendar.MILLISECOND, 0);\n    return new Date(calendar.getTime().getTime());\n  }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/util/RoleUtils.java",
    "content": "package com.ctrip.framework.apollo.portal.util;\n\nimport com.google.common.base.Joiner;\n\nimport com.ctrip.framework.apollo.core.ConfigConsts;\nimport com.ctrip.framework.apollo.portal.constant.RoleType;\n\npublic class RoleUtils {\n\n  private static final Joiner STRING_JOINER = Joiner.on(ConfigConsts.CLUSTER_NAMESPACE_SEPARATOR);\n\n  public static String buildAppMasterRoleName(String appId) {\n    return STRING_JOINER.join(RoleType.MASTER, appId);\n  }\n\n  public static String buildAppRoleName(String appId, String roleType) {\n    return STRING_JOINER.join(roleType, appId);\n  }\n\n  public static String buildModifyNamespaceRoleName(String appId, String namespaceName) {\n    return STRING_JOINER.join(RoleType.MODIFY_NAMESPACE, appId, namespaceName);\n  }\n\n  public static String buildModifyDefaultNamespaceRoleName(String appId) {\n    return STRING_JOINER.join(RoleType.MODIFY_NAMESPACE, appId, ConfigConsts.NAMESPACE_APPLICATION);\n  }\n\n  public static String buildReleaseNamespaceRoleName(String appId, String namespaceName) {\n    return STRING_JOINER.join(RoleType.RELEASE_NAMESPACE, appId, namespaceName);\n  }\n\n  public static String buildNamespaceRoleName(String appId, String namespaceName, String roleType) {\n    return STRING_JOINER.join(roleType, appId, namespaceName);\n  }\n\n  public static String buildReleaseDefaultNamespaceRoleName(String appId) {\n    return STRING_JOINER.join(RoleType.RELEASE_NAMESPACE, appId, ConfigConsts.NAMESPACE_APPLICATION);\n  }\n\n  public static String buildNamespaceTargetId(String appId, String namespaceName) {\n    return STRING_JOINER.join(appId, namespaceName);\n  }\n\n  public static String buildDefaultNamespaceTargetId(String appId) {\n    return STRING_JOINER.join(appId, ConfigConsts.NAMESPACE_APPLICATION);\n  }\n\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/META-INF/app.properties",
    "content": "app.id=100003173\njdkVersion=1.8\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/application-ctrip.yml",
    "content": "ctrip:\n  appid: 100003173\n  email:\n    send:\n      code: 37030033\n    template:\n      id: 37030033\n    survival:\n      duration: 5\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/application.yml",
    "content": "spring:\n  application:\n    name: apollo-portal\n  profiles:\n    active: ${apollo_profile} \n  \nserver:\n  port: 8070\n  \nlogging:\n  level:\n    com.ctrip: INFO  \n\n  \nendpoints:\n  health:\n    sensitive: false\nmanagement:\n  security:\n    enabled: false\n  health:\n    status:\n      order: DOWN, OUT_OF_SERVICE, UNKNOWN, UP \n\n\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/logback.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<configuration>\n\t<include resource=\"org/springframework/boot/logging/logback/defaults.xml\" />\n\t<property name=\"LOG_FILE\"\n\t\tvalue=\"${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}/}apollo-portal.log}\" />\n\t<include resource=\"org/springframework/boot/logging/logback/file-appender.xml\" />\n\t<include resource=\"org/springframework/boot/logging/logback/console-appender.xml\" />\n\t<root level=\"INFO\">\n\t\t<appender-ref ref=\"FILE\" />\n\t\t<appender-ref ref=\"CONSOLE\" />\n\t</root>\n</configuration>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/portal.properties",
    "content": "apollo_profile=github,auth \ndev_meta=http://134.224.240.170:8080\nserver.port=8070 \nspring.datasource.url=jdbc:mysql://47.94.252.160:3306/ApolloPortalDB?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false\nspring.datasource.username=root\nspring.datasource.password=root\n\n\n#spring.jpa.properties.hibernate.show_sql=true\nspring.jpa.properties.hibernate.dialect= org.hibernate.dialect.MySQL5Dialect\nspring.jpa.hibernate.naming_strategy=org.hibernate.cfg.EJB3NamingStrategy"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/app/setting.html",
    "content": "<!doctype html>\n<html ng-app=\"setting\">\n<head>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n    <link rel=\"icon\" href=\"../img/config.png\">\n    <!-- styles -->\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"../vendor/bootstrap/css/bootstrap.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"../vendor/angular/angular-toastr-1.4.1.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" media='all' href=\"../vendor/angular/loading-bar.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"../styles/common-style.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"../vendor/select2/select2.min.css\">\n    <title>项目管理</title>\n</head>\n\n<body>\n\n<apollonav></apollonav>\n\n<div class=\"container-fluid apollo-container project-setting\" ng-controller=\"SettingController\">\n    <section class=\"col-md-10 col-md-offset-1 panel hidden\">\n        <header class=\"panel-heading\">\n            <div class=\"row\">\n                <div class=\"col-md-7\">\n                    <h4 class=\"modal-title\">项目管理 ( AppId:<label ng-bind=\"pageContext.appId\"></label> )\n                    </h4>\n                </div>\n                <div class=\"col-md-5 text-right\">\n                    <a type=\"button\" class=\"btn btn-info\" data-dismiss=\"modal\"\n                       href=\"/config.html?#appid={{pageContext.appId}}\">返回到项目首页\n                    </a>\n                </div>\n            </div>\n        </header>\n\n        <div class=\"panel-body row\">\n\n            <section class=\"context\" ng-show=\"hasAssignUserPermission\">\n                <!--project admin-->\n                <section class=\"form-horizontal\">\n                    <h5>管理员\n                        <small>\n                            (项目管理员具有以下权限: 1. 创建Namespace 2. 创建集群 3. 管理项目、Namespace权限)\n                        </small>\n                    </h5>\n                    <hr>\n\n                    <div class=\"col-md-offset-1\">\n                        <form class=\"form-inline\" ng-submit=\"assignMasterRoleToUser()\">\n                            <div class=\"form-group\" style=\"padding-left: 15px\">\n                                <apollouserselector apollo-id=\"userSelectWidgetId\"></apollouserselector>\n                            </div>\n                            <button type=\"submit\" class=\"btn btn-default\" style=\"margin-left: 20px;\"\n                                    ng-disabled=\"submitBtnDisabled\">添加\n                            </button>\n                        </form>\n                        <!-- Split button -->\n                        <div class=\"item-container\">\n\n                            <div class=\"btn-group item-info\" ng-repeat=\"user in appRoleUsers.masterUsers\">\n                                <button type=\"button\" class=\"btn btn-default\" ng-bind=\"user.userId\"></button>\n                                <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                        aria-haspopup=\"true\" aria-expanded=\"false\"\n                                        ng-click=\"removeMasterRoleFromUser(user.userId)\">\n                                    <span class=\"glyphicon glyphicon-remove\"></span>\n                                </button>\n                            </div>\n                        </div>\n\n                    </div>\n\n\n                </section>\n\n                <!--application info-->\n                <section>\n                    <h5>基本信息</h5>\n                    <hr>\n                    <form class=\"form-horizontal\" name=\"appForm\" valdr-type=\"App\"\n                          ng-submit=\"updateAppInfo()\">\n\n                        <div class=\"form-group\" valdr-form-group>\n                            <label class=\"col-sm-2 control-label\">\n                                <apollorequiredfield></apollorequiredfield>\n                                AppId</label>\n                            <div class=\"col-sm-3\">\n                                <label class=\"form-control-static\" ng-bind=\"pageContext.appId\">\n                                </label>\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-2 control-label\">\n                                <apollorequiredfield></apollorequiredfield>\n                                部门</label>\n                            <div class=\"col-sm-3\">\n                                <select id=\"organization\" ng-disabled=\"!display.app.edit\">\n                                    <option></option>\n                                </select>\n                            </div>\n                        </div>\n\n                        <div class=\"form-group\" valdr-form-group>\n                            <label class=\"col-sm-2 control-label\">\n                                <apollorequiredfield></apollorequiredfield>\n                                项目名称</label>\n                            <div class=\"col-sm-4\">\n                                <input type=\"text\" class=\"form-control\" name=\"appName\" ng-model=\"viewApp.name\"\n                                       ng-disabled=\"!display.app.edit\">\n                                <small>(建议格式 xx-yy-zz 例:apollo-server)</small>\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-2 control-label\">\n                                <apollorequiredfield></apollorequiredfield>\n                                项目负责人</label>\n                            <div class=\"col-sm-6 J_ownerSelectorPanel\">\n                                <apollouserselector apollo-id=\"'ownerSelector'\"\n                                                    disabled=\"!display.app.edit\"></apollouserselector>\n                            </div>\n                        </div>\n\n                        <div class=\"form-group\">\n                            <div class=\"col-sm-offset-2 col-sm-9\">\n                                <button type=\"button\" class=\"btn btn-primary\"\n                                        ng-show=\"!display.app.edit\"\n                                        ng-click=\"toggleEditStatus()\">\n                                    修改项目信息\n                                </button>\n                                <button type=\"button\" class=\"btn btn-warning\"\n                                        ng-show=\"display.app.edit\"\n                                        ng-click=\"toggleEditStatus()\">\n                                    取消修改\n                                </button>\n                                <button type=\"submit\" class=\"btn btn-primary\"\n                                        ng-show=\"display.app.edit\"\n                                        ng-disabled=\"appForm.$invalid || submitBtnDisabled\">\n                                    提交\n                                </button>\n                            </div>\n                        </div>\n                    </form>\n                </section>\n\n\n            </section>\n\n            <section class=\"context\" ng-show=\"!hasAssignUserPermission\">\n                <div class=\"panel-body text-center\">\n                    <h4>您没有权限操作，请找 [{{admins.join(',')}}] 开通权限</h4>\n                </div>\n            </section>\n        </div>\n\n        <apolloconfirmdialog apollo-dialog-id=\"'warning'\" apollo-title=\"'删除管理员'\"\n                             apollo-detail=\"'不能删除所有的管理员'\"\n                             apollo-show-cancel-btn=\"false\"></apolloconfirmdialog>\n    </section>\n</div>\n\n<div ng-include=\"'../views/common/footer.html'\"></div>\n\n<!-- jquery.js -->\n<script src=\"../vendor/jquery.min.js\" type=\"text/javascript\"></script>\n\n<!--angular-->\n<script src=\"../vendor/angular/angular.min.js\"></script>\n<script src=\"../vendor/angular/angular-route.min.js\"></script>\n<script src=\"../vendor/angular/angular-resource.min.js\"></script>\n<script src=\"../vendor/angular/angular-toastr-1.4.1.tpls.min.js\"></script>\n<script src=\"../vendor/angular/loading-bar.min.js\"></script>\n\n<!--valdr-->\n<script src=\"../vendor/valdr/valdr.min.js\" type=\"text/javascript\"></script>\n<script src=\"../vendor/valdr/valdr-message.min.js\" type=\"text/javascript\"></script>\n\n<!-- bootstrap.js -->\n<script src=\"../vendor/bootstrap/js/bootstrap.min.js\" type=\"text/javascript\"></script>\n\n<!--nicescroll-->\n<script src=\"../vendor/jquery.nicescroll.min.js\"></script>\n<script src=\"../vendor/lodash.min.js\"></script>\n\n<script src=\"../vendor/select2/select2.min.js\" type=\"text/javascript\"></script>\n<!--biz-->\n<!--must import-->\n<script type=\"application/javascript\" src=\"../scripts/app.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/services/AppService.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/services/EnvService.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/services/UserService.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/services/CommonService.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/services/PermissionService.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/services/OrganizationService.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/services/PermissionService.js\"></script>\n\n<script type=\"application/javascript\" src=\"../scripts/AppUtils.js\"></script>\n\n<script type=\"application/javascript\" src=\"../scripts/PageCommon.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/directive/directive.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/valdr.js\"></script>\n\n<script type=\"application/javascript\" src=\"../scripts/controller/SettingController.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/app.html",
    "content": "<!doctype html>\n<html ng-app=\"create_app\">\n<head>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n    <link rel=\"icon\" href=\"./img/config.png\">\n    <!-- styles -->\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"vendor/bootstrap/css/bootstrap.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"vendor/angular/angular-toastr-1.4.1.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"vendor/select2/select2.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" media='all' href=\"vendor/angular/loading-bar.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"styles/common-style.css\">\n\n    <title>新建项目</title>\n</head>\n\n<body>\n\n<apollonav></apollonav>\n<div class=\"container-fluid apollo-container\">\n\n    <div class=\"row\">\n        <div class=\"col-md-8 col-md-offset-2\">\n            <div class=\"panel\">\n                <header class=\"panel-heading\">\n                    创建项目\n                </header>\n\n                <form class=\"form-horizontal panel-body\" name=\"appForm\" ng-controller=\"CreateAppController\"\n                      valdr-type=\"App\"\n                      ng-submit=\"create()\">\n                    <div class=\"form-group\">\n                        <label class=\"col-sm-3 control-label\">\n                            <apollorequiredfield></apollorequiredfield>\n                            部门</label>\n                        <div class=\"col-sm-3\">\n                            <select id=\"organization\">\n                                <option></option>\n                            </select>\n                        </div>\n                    </div>\n                    <div class=\"form-group\" valdr-form-group>\n                        <label class=\"col-sm-3 control-label\">\n                            <apollorequiredfield></apollorequiredfield>\n                            应用Id</label>\n                        <div class=\"col-sm-3\">\n                            <input type=\"text\" class=\"form-control\" name=\"appId\" ng-model=\"app.appId\">\n                            <small>（应用唯一标识）</small>\n                        </div>\n                    </div>\n                    <div class=\"form-group\" valdr-form-group>\n                        <label class=\"col-sm-3 control-label\">\n                            <apollorequiredfield></apollorequiredfield>\n                            应用名称</label>\n                        <div class=\"col-sm-5\">\n                            <input type=\"text\" class=\"form-control\" name=\"appName\" ng-model=\"app.name\">\n                            <small>(建议格式 xx-yy-zz 例:apollo-server)</small>\n                        </div>\n                    </div>\n                    <div class=\"form-group\">\n                        <label class=\"col-sm-3 control-label\">\n                            <apollorequiredfield></apollorequiredfield>\n                            应用负责人</label>\n                        <div class=\"col-sm-6 J_ownerSelectorPanel\">\n                            <apollouserselector apollo-id=\"'ownerSelector'\"></apollouserselector>\n                        </div>\n                    </div>\n\n                    <div class=\"form-group\">\n                        <label class=\"col-sm-3 control-label\">项目管理员<br>\n\n                        </label>\n                        <div class=\"col-sm-9 J_adminSelectorPanel\">\n\n                            <apollomultipleuserselector apollo-id=\"'adminSelector'\"></apollomultipleuserselector>\n                            <br>\n                            <small>(应用负责人默认具有项目管理员权限，</small>\n                            <br>\n                            <small>项目管理员可以创建Namespace和集群、分配用户权限)</small>\n\n                        </div>\n                    </div>\n\n                    <div class=\"form-group\">\n                        <div class=\"col-sm-offset-3 col-sm-9\">\n\n                            <button type=\"submit\" class=\"btn btn-primary\"\n                                    ng-disabled=\"appForm.$invalid || submitBtnDisabled\">提交\n                            </button>\n                        </div>\n                    </div>\n                </form>\n\n            </div>\n        </div>\n    </div>\n</div>\n\n<div ng-include=\"'views/common/footer.html'\"></div>\n\n<!--angular-->\n<script src=\"vendor/angular/angular.min.js\"></script>\n<script src=\"vendor/angular/angular-resource.min.js\"></script>\n<script src=\"vendor/angular/angular-toastr-1.4.1.tpls.min.js\"></script>\n<script src=\"vendor/angular/loading-bar.min.js\"></script>\n\n<!-- jquery.js -->\n<script src=\"vendor/jquery.min.js\" type=\"text/javascript\"></script>\n<script src=\"vendor/select2/select2.min.js\" type=\"text/javascript\"></script>\n\n<!-- bootstrap.js -->\n<script src=\"vendor/bootstrap/js/bootstrap.min.js\" type=\"text/javascript\"></script>\n\n<!--valdr-->\n<script src=\"vendor/valdr/valdr.min.js\" type=\"text/javascript\"></script>\n<script src=\"vendor/valdr/valdr-message.min.js\" type=\"text/javascript\"></script>\n\n<script type=\"application/javascript\" src=\"scripts/app.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/AppService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/EnvService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/UserService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/CommonService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/PermissionService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/OrganizationService.js\"></script>\n\n<script type=\"application/javascript\" src=\"scripts/AppUtils.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/directive/directive.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/controller/AppController.js\"></script>\n\n<script src=\"scripts/valdr.js\" type=\"text/javascript\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/cluster.html",
    "content": "<!doctype html>\n<html ng-app=\"cluster\">\n<head>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n    <link rel=\"icon\" href=\"./img/config.png\">\n    <!-- styles -->\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"vendor/bootstrap/css/bootstrap.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"vendor/angular/angular-toastr-1.4.1.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"vendor/select2/select2.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" media='all' href=\"vendor/angular/loading-bar.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"styles/common-style.css\">\n    <title>新建集群</title>\n</head>\n\n<body>\n\n<apollonav></apollonav>\n<div class=\"container-fluid apollo-container hidden\" ng-controller=\"ClusterController\">\n\n    <div class=\"row\">\n        <div class=\"col-md-8 col-md-offset-2\">\n            <div class=\"panel\">\n                <header class=\"panel-heading\">\n                    <div class=\"row\">\n                        <div class=\"col-md-6\">\n                            <h4>创建集群</h4>\n                        </div>\n                        <div class=\"col-md-6 text-right\">\n                            <a type=\"button\" class=\"btn btn-info\" href=\"/config.html?#/appid={{appId}}\">返回到项目首页\n                            </a>\n                        </div>\n                    </div>\n\n                </header>\n\n                <div class=\"panel-body\">\n\n\n                    <div class=\"alert alert-info no-radius\" role=\"alert\">\n                        <strong>Tips:</strong>\n                        <ul>\n                            <li>通过添加集群，可以使同一份程序在不同的集群（如不同的数据中心）使用不同的配置</li>\n                            <li>如果不同集群使用一样的配置，则没有必要创建集群</li>\n                            <li>\n                                Apollo默认会读取机器上/opt/settings/server.properties(linux)或C:\\opt\\settings\\server.properties(windows)文件中的idc属性作为集群名字，\n                                如SHAJQ（金桥数据中心）、SHAOY（欧阳数据中心)\n                            </li>\n                            <li>在这里创建的集群名字需要和机器上server.properties中的idc属性一致</li>\n                        </ul>\n                    </div>\n                    <form class=\"form-horizontal\" name=\"clusterForm\" valdr-type=\"Cluster\" ng-show=\"step == 1\"\n                          ng-submit=\"create()\">\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-2 control-label\">\n                                <apollorequiredfield></apollorequiredfield>\n                                应用AppId</label>\n                            <div class=\"col-sm-6\">\n                                <label class=\"form-control-static\" ng-bind=\"appId\"></label>\n                            </div>\n                        </div>\n                        <div class=\"form-group\" valdr-form-group>\n                            <label class=\"col-sm-2 control-label\">\n                                <apollorequiredfield></apollorequiredfield>\n                                集群名称</label>\n                            <div class=\"col-sm-6\">\n                                <input type=\"text\" class=\"form-control\" name=\"clusterName\" ng-model=\"clusterName\">\n                                <small>(部署集群如:SHAJQ,SHAOY 或自定义集群如:SHAJQ-xx,SHAJQ-yy)</small>\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-2 control-label\">\n                                <apollorequiredfield></apollorequiredfield>\n                                选择环境</label>\n                            <div class=\"col-sm-5\">\n                                <table class=\"table table-hover\" style=\"width: 100px\">\n                                    <tbody>\n                                    <tr style=\"cursor: pointer\" ng-repeat=\"env in envs\"\n                                        ng-click=\"toggleEnvCheckedStatus(env)\">\n                                        <td width=\"10%\"><input type=\"checkbox\" ng-checked=\"env.checked\"\n                                                               ng-click=\"switchChecked(env, $event)\"></td>\n                                        <td width=\"30%\" ng-bind=\"env.name\"></td>\n                                    </tr>\n                                    </tbody>\n                                </table>\n\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <div class=\"col-sm-offset-2 col-sm-10\">\n\n                                <button type=\"submit\" class=\"btn btn-primary\"\n                                        ng-disabled=\"clusterForm.$invalid || submitBtnDisabled\">提交\n                                </button>\n                            </div>\n                        </div>\n                    </form>\n                    <div class=\"row text-center\" ng-show=\"step == 2\">\n                        <img src=\"img/sync-succ.png\" style=\"height: 100px; width: 100px\">\n                        <h3>创建成功!</h3>\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>\n\n<div ng-include=\"'views/common/footer.html'\"></div>\n\n<!--angular-->\n<script src=\"vendor/angular/angular.min.js\"></script>\n<script src=\"vendor/angular/angular-resource.min.js\"></script>\n<script src=\"vendor/angular/angular-toastr-1.4.1.tpls.min.js\"></script>\n<script src=\"vendor/angular/loading-bar.min.js\"></script>\n\n<!-- jquery.js -->\n<script src=\"vendor/jquery.min.js\" type=\"text/javascript\"></script>\n<script src=\"vendor/select2/select2.min.js\" type=\"text/javascript\"></script>\n\n<!-- bootstrap.js -->\n<script src=\"vendor/bootstrap/js/bootstrap.min.js\" type=\"text/javascript\"></script>\n\n<!--valdr-->\n<script src=\"vendor/valdr/valdr.min.js\" type=\"text/javascript\"></script>\n<script src=\"vendor/valdr/valdr-message.min.js\" type=\"text/javascript\"></script>\n\n<script type=\"application/javascript\" src=\"scripts/app.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/AppService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/EnvService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/UserService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/CommonService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/ClusterService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/AppUtils.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/directive/directive.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/PermissionService.js\"></script>\n\n<script type=\"application/javascript\" src=\"scripts/controller/ClusterController.js\"></script>\n\n<script src=\"scripts/valdr.js\" type=\"text/javascript\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/config/history.html",
    "content": "<!doctype html >\n<html ng-app=\"release_history\">\n<head>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n    <link rel=\"icon\" href=\"../img/config.png\">\n    <!-- styles -->\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"../vendor/bootstrap/css/bootstrap.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"../vendor/angular/angular-toastr-1.4.1.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" media='all' href=\"../vendor/angular/loading-bar.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"../styles/common-style.css\">\n    <title>发布历史</title>\n</head>\n\n<body>\n\n<apollonav></apollonav>\n\n<div class=\"container-fluid apollo-container\" ng-controller=\"ReleaseHistoryController\">\n    <section class=\"release-history panel col-md-12 no-radius hidden\">\n        <div class=\"panel-heading row\">\n\n            <div class=\"operation-caption-container col-md-3\">\n                <div class=\"operation-caption release-operation-normal text-center\"\n                     style=\"left:0;\">\n                    <small>主版本发布</small>\n                </div>\n                <div class=\"operation-caption release-operation-rollback text-center\"\n                     style=\"left: 80px;\">\n                    <small>主版本回滚</small>\n                </div>\n                <div class=\"operation-caption release-operation-gray text-center\"\n                     style=\"left: 160px;\">\n                    <small>灰度操作</small>\n                </div>\n            </div>\n\n            <div class=\"col-md-6 text-center\">\n                <h4>发布历史</h4>\n                <small>(AppId:{{pageContext.appId}}, ENV:{{pageContext.env}}, Cluster:{{pageContext.clusterName}},\n                    Namespace:{{pageContext.namespaceName}})\n                </small>\n            </div>\n\n            <div class=\"pull-right back-btn\">\n                <a type=\"button\" class=\"btn btn-info\" href=\"/config.html?#/appid={{pageContext.appId}}\">返回到项目首页\n                </a>\n            </div>\n\n        </div>\n\n        <div class=\"release-history-container panel-body row\" ng-show=\"releaseHistories && releaseHistories.length > 0\">\n            <div class=\"release-history-list col-md-3\">\n\n                <div class=\"media hover\" ng-class=\"{'active': releaseHistory.id == selectedReleaseHistory}\"\n                     ng-repeat=\"releaseHistory in releaseHistories\"\n                     ng-click=\"showReleaseHistoryDetail(releaseHistory)\">\n                    <div class=\"release-operation\"\n                         ng-class=\"{'release-operation-normal': releaseHistory.operation == 0  || releaseHistory.operation == 5,\n                               'release-operation-gray': releaseHistory.operation == 2 || releaseHistory.operation == 3 ||\n                               releaseHistory.operation == 4 || releaseHistory.operation == 7 || releaseHistory.operation == 8,\n                               'release-operation-rollback': releaseHistory.operation == 1 || releaseHistory.operation == 6}\">\n                    </div>\n                    <h4 class=\"media-left text-center\" ng-bind=\"releaseHistory.operator\">\n                    </h4>\n                    <div class=\"media-body\">\n\n                        <h5 class=\"col-md-7 word-break\" ng-show=\"releaseHistory.operation == 0\">普通发布</h5>\n                        <h5 class=\"col-md-7 word-break\" ng-show=\"releaseHistory.operation == 1\">回滚</h5>\n                        <h5 class=\"col-md-7 word-break\" ng-show=\"releaseHistory.operation == 2\">灰度发布</h5>\n                        <h5 class=\"col-md-7 word-break\" ng-show=\"releaseHistory.operation == 3\">更新灰度规则</h5>\n                        <h5 class=\"col-md-7 word-break\" ng-show=\"releaseHistory.operation == 4\">灰度全量发布</h5>\n                        <h5 class=\"col-md-7 word-break\" ng-show=\"releaseHistory.operation == 5\">灰度发布(主版本发布)</h5>\n                        <h5 class=\"col-md-7 word-break\" ng-show=\"releaseHistory.operation == 6\">灰度发布(主版本回滚)</h5>\n                        <h5 class=\"col-md-7 word-break\" ng-show=\"releaseHistory.operation == 7\">放弃灰度</h5>\n                        <h5 class=\"col-md-7 word-break\" ng-show=\"releaseHistory.operation == 8\">删除灰度(全量发布)</h5>\n\n                        <h6 class=\"col-md-5 text-right\" ng-bind=\"releaseHistory.releaseTimeFormatted\"></h6>\n                        <span class=\"label label-warning no-radius emergency-publish\"\n                              ng-if=\"releaseHistory.operationContext.isEmergencyPublish\">紧急发布</span>\n                    </div>\n                </div>\n\n                <div class=\"load-more media panel-heading text-center hover\"\n                     ng-show=\"!hasLoadAll\"\n                     ng-click=\"findReleaseHistory()\">\n                    加载更多\n                </div>\n\n            </div>\n\n            <!--properties mode info-->\n            <div class=\"release-info col-md-9 panel panel-default no-radius\"\n                 ng-show=\"!isTextNamespace\">\n                <div class=\"panel-heading\">\n\n                    <span ng-bind=\"history.releaseTitle\"></span>\n                    <span class=\"pull-right\" ng-bind=\"history.releaseTime | date: 'yyyy-MM-dd HH:mm:ss'\"></span>\n\n                    <div class=\"row\" style=\"padding-top: 10px;\">\n                        <div class=\"col-md-5\">\n                            <small ng-show=\"history.releaseComment\" ng-bind=\"history.releaseComment\"></small>\n                        </div>\n                        <div class=\"col-md-7 text-right\">\n                            <div class=\"btn-group\">\n                                <button type=\"button\" class=\"btn btn-default btn-sm\"\n                                        ng-class=\"{'active':history.viewType == 'diff'}\"\n                                        data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"查看此次发布与上次版本的变更\"\n                                        ng-click=\"switchConfigViewType(history, 'diff')\">变更的配置\n                                </button>\n                                <button type=\"button\" class=\"btn btn-default btn-sm\"\n                                        ng-class=\"{'active':history.viewType == 'all'}\"\n                                        data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"查看此次发布的所有配置信息\"\n                                        ng-click=\"switchConfigViewType(history, 'all')\">全部配置\n                                </button>\n                            </div>\n                        </div>\n\n                    </div>\n                </div>\n\n                <div class=\"panel-body config\">\n                    <section ng-show=\"history.viewType=='diff'\">\n                        <h4 class=\"section-title\">变更的配置</h4>\n                        <div ng-show=\"history.changes && history.changes.length > 0\">\n                            <table class=\"no-margin table table-striped table-hover table-bordered\">\n                                <thead>\n                                <tr>\n                                    <th>Type</th>\n                                    <th>Key</th>\n                                    <th>Old Value</th>\n                                    <th>New Value</th>\n                                </tr>\n                                </thead>\n                                <tbody>\n                                <tr ng-repeat=\"change in history.changes\">\n                                    <td width=\"10%\">\n                                        <span ng-show=\"change.type == 'ADDED'\">新增</span>\n                                        <span ng-show=\"change.type == 'MODIFIED'\">修改</span>\n                                        <span ng-show=\"change.type == 'DELETED'\">删除</span>\n                                    </td>\n                                    <td class=\"cursor-pointer\" width=\"20%\"\n                                        ng-click=\"showText(change.entity.firstEntity.key)\">\n                                        <span ng-bind=\"change.entity.firstEntity.key | limitTo: 250\"></span>\n                                        <span ng-bind=\"change.entity.firstEntity.key.length > 250 ? '...' :''\"></span>\n                                    </td>\n                                    <td class=\"cursor-pointer\" width=\"35%\"\n                                        ng-click=\"showText(change.entity.firstEntity.value)\">\n                                        <span ng-bind=\"change.entity.firstEntity.value | limitTo: 250\"></span>\n                                        <span ng-bind=\"change.entity.firstEntity.value.length > 250 ? '...' :''\"></span>\n                                    </td>\n                                    <td class=\"cursor-pointer\" width=\"35%\"\n                                        ng-click=\"showText(change.entity.secondEntity.value)\">\n                                        <span ng-bind=\"change.entity.secondEntity.value | limitTo: 250\"></span>\n                                        <span ng-bind=\"change.entity.secondEntity.value.length > 250 ? '...' :''\"></span>\n                                    </td>\n                                </tr>\n                                </tbody>\n                            </table>\n                        </div>\n                        <div class=\"text-center empty-container\"\n                             ng-show=\"!history.changes || history.changes.length == 0\">\n                            <h5>无配置更改</h5>\n                        </div>\n                    </section>\n\n\n                    <section ng-show=\"history.viewType=='all'\">\n                        <h4 class=\"section-title\">全部配置</h4>\n                        <table class=\"no-margin table table-striped table-hover table-bordered\"\n                               ng-show=\"history.configuration && history.configuration.length > 0\">\n                            <thead>\n                            <tr>\n                                <th>Key</th>\n                                <th>Value</th>\n                            </tr>\n                            </thead>\n                            <tbody>\n                            <tr ng-repeat=\"item in history.configuration\">\n                                <td class=\"cursor-pointer\" width=\"30%\" ng-click=\"showText(item.firstEntity)\">\n                                    <span ng-bind=\"item.firstEntity | limitTo: 250\"></span>\n                                    <span ng-bind=\"item.firstEntity.length > 250 ? '...' :''\"></span>\n                                </td>\n                                <td class=\"cursor-pointer\" width=\"70%\" ng-click=\"showText(item.secondEntity)\">\n                                    <span ng-bind=\"item.secondEntity | limitTo: 250\"></span>\n                                    <span ng-bind=\"item.secondEntity.length > 250 ? '...' :''\"></span>\n                                </td>\n                            </tr>\n                            </tbody>\n                        </table>\n                        <div class=\"text-center empty-container\"\n                             ng-show=\"history.viewType=='all' && (!history.configuration || history.configuration.length == 0)\">\n                            <h5>无配置</h5>\n                        </div>\n                    </section>\n\n\n                    <section ng-show=\"history.branchName != history.clusterName && history.operation != 8 && history.operation != 7\">\n                        <hr>\n                        <h4 class=\"section-title\">灰度规则</h4>\n                        <table class=\"no-margin table table-striped table-hover table-bordered\"\n                               ng-show=\"history.operationContext.rules\">\n                            <thead>\n                            <tr>\n                                <th>灰度的AppId</th>\n                                <th>灰度的IP</th>\n                            </tr>\n                            </thead>\n                            <tbody>\n                            <tr ng-repeat=\"rule in history.operationContext.rules\">\n                                <td width=\"20%\" ng-bind=\"rule.clientAppId\"></td>\n                                <td width=\"80%\" ng-bind=\"rule.clientIpList.join(', ')\"></td>\n                            </tr>\n                            </tbody>\n                        </table>\n                        <h5 class=\"text-center empty-container\" ng-show=\"!history.operationContext.rules\">\n                            无灰度规则\n                        </h5>\n                    </section>\n\n                </div>\n            </div>\n\n            <!--text mode-->\n            <div class=\"release-info col-md-9\"\n                 ng-show=\"isTextNamespace && history.changes && history.changes.length > 0\">\n                <apollodiff ng-repeat=\"change in history.changes\"\n                            old-str=\"change.entity.firstEntity.value\"\n                            new-str=\"change.entity.secondEntity.value\"\n                            apollo-id=\"'releaseStrDiff'\">\n                </apollodiff>\n            </div>\n\n        </div>\n\n        <div class=\"panel-body\" ng-show=\"!releaseHistories || releaseHistories.length == 0\">\n            <h4 class=\"text-center empty-container\">无发布历史信息</h4>\n        </div>\n    </section>\n\n    <showtextmodal text=\"text\"></showtextmodal>\n</div>\n\n\n<div ng-include=\"'../views/common/footer.html'\"></div>\n\n<!-- jquery.js -->\n<script src=\"../vendor/jquery.min.js\" type=\"text/javascript\"></script>\n\n<!--angular-->\n<script src=\"../vendor/angular/angular.min.js\"></script>\n<script src=\"../vendor/angular/angular-resource.min.js\"></script>\n<script src=\"../vendor/angular/angular-toastr-1.4.1.tpls.min.js\"></script>\n<script src=\"../vendor/angular/loading-bar.min.js\"></script>\n\n\n<!-- bootstrap.js -->\n<script src=\"../vendor/bootstrap/js/bootstrap.min.js\" type=\"text/javascript\"></script>\n\n<!--nicescroll-->\n<script src=\"../vendor/jquery.nicescroll.min.js\"></script>\n\n<script src=\"../vendor/diff.min.js\" type=\"text/javascript\"></script>\n\n<!--biz-->\n<script type=\"application/javascript\" src=\"../scripts/app.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/services/AppService.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/services/EnvService.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/services/ReleaseService.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/services/UserService.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/services/CommonService.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/services/ReleaseHistoryService.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/services/ConfigService.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/services/PermissionService.js\"></script>\n\n<script type=\"application/javascript\" src=\"../scripts/AppUtils.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/controller/config/ReleaseHistoryController.js\"></script>\n\n<script type=\"application/javascript\" src=\"../scripts/PageCommon.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/directive/directive.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/directive/show-text-modal-directive.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/directive/diff-directive.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/config/sync.html",
    "content": "<!doctype html>\n<html ng-app=\"sync_item\">\n<head>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n    <link rel=\"icon\" href=\"../img/config.png\">\n    <!-- styles -->\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"../vendor/bootstrap/css/bootstrap.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"../vendor/angular/angular-toastr-1.4.1.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" media='all' href=\"../vendor/angular/loading-bar.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"../styles/common-style.css\">\n    <title>同步配置</title>\n</head>\n\n<body>\n\n<apollonav></apollonav>\n\n<div class=\"container-fluid apollo-container hidden\" ng-controller=\"SyncItemController\">\n    <section class=\"panel col-md-offset-1 col-md-10\">\n        <header class=\"panel-heading\">\n            <div class=\"row\">\n                <div class=\"col-md-7\">\n                    <h4 class=\"modal-title\">同步配置\n                        <small ng-show=\"syncItemStep == 1\">(第一步:选择同步信息)</small>\n                        <small ng-show=\"syncItemStep == 2\">(第二步:检查Diff)</small>\n                    </h4>\n                </div>\n                <div class=\"col-md-5 text-right\">\n                    <button type=\"button\" class=\"btn btn-primary\" ng-show=\"syncItemStep > 1 && syncItemStep < 3\"\n                            ng-click=\"syncItemNextStep(-1)\">上一步\n                    </button>\n                    <button type=\"button\" class=\"btn btn-primary\" ng-show=\"syncItemStep < 2\"\n                            ng-click=\"diff()\">下一步\n                    </button>\n                    <button type=\"button\" class=\"btn btn-success\" ng-show=\"syncItemStep == 2 && hasDiff\"\n                            ng-click=\"syncItems()\" ng-disabled=\"syncBtnDisabled\">同步\n                    </button>\n                    <button type=\"button\" class=\"btn btn-info\" data-dismiss=\"modal\"\n                            ng-click=\"backToAppHomePage()\">返回到项目首页\n                    </button>\n                </div>\n            </div>\n        </header>\n        <div class=\"panel-body\">\n            <div class=\"row\" ng-show=\"syncItemStep == 1\">\n                <div class=\"alert-info alert no-radius\">\n                    <strong>Tips:</strong>\n                    <ul>\n                        <li>通过同步配置功能，可以使多个环境、集群间的配置保持一致</li>\n                        <li>需要注意的是，同步完之后需要发布后才会对应用生效</li>\n                    </ul>\n                </div>\n                <div class=\"form-horizontal\">\n                    <div class=\"form-group\">\n                        <label class=\"col-sm-2 control-label\">同步的Namespace</label>\n                        <div class=\"col-sm-6\">\n                            <h4 ng-bind=\"pageContext.namespaceName\"></h4>\n                        </div>\n                    </div>\n                </div>\n                <div class=\"form-horizontal\">\n                    <div class=\"form-group\">\n                        <label class=\"col-sm-2 control-label\">同步到那个集群</label>\n                        <div class=\"col-sm-6\">\n                            <apolloclusterselector apollo-app-id=\"pageContext.appId\" apollo-default-all-checked=\"true\"\n                                                   apollo-select=\"collectSelectedClusters\"\n                                                   apollo-not-checked-env=\"pageContext.env\"\n                                                   apollo-not-checked-cluster=\"pageContext.clusterName\"></apolloclusterselector>\n                        </div>\n                    </div>\n                </div>\n                <hr>\n            </div>\n\n            <div class=\"row\" ng-show=\"syncItemStep == 1\" style=\"margin-top: 10px;\">\n                <div class=\"form-horizontal\">\n                    <div class=\"col-sm-2 text-right\">\n                        <label class=\"control-label\">需要同步的配置</label>\n                    </div>\n                    <div class=\"col-sm-10\">\n                        <div class=\"row text-right\" style=\"margin-bottom: 5px; margin-right: 0px;\">\n                            按最后更新时间过滤\n                            开始时间:<input type=\"date\" ng-model=\"filterBeginTime\"> 结束时间:  <input type=\"date\" ng-model=\"filterEndTime\">\n                            <button class=\"btn btn-sm btn-primary\" ng-click=\"filter()\">过滤</button>\n                            <button class=\"btn btn-sm btn-default\" ng-click=\"resetFilter()\">重置</button>\n                        </div>\n                        <table class=\"table table-bordered table-striped table-hover\">\n                            <thead>\n                            <tr>\n                                <td><input type=\"checkbox\" ng-click=\"toggleItemsCheckedStatus()\"></td>\n                                <td class=\"hover\" ng-click=\"col='key';desc=!desc;\">\n                                    Key\n                                    <span class=\"glyphicon glyphicon-sort\"></span>\n                                </td>\n                                <td>Value</td>\n                                <td class=\"hover\" ng-click=\"col='dataChangeCreatedTime';desc=!desc;\">\n                                    Create Time\n                                    <span class=\"glyphicon glyphicon-sort\"></span>\n                                </td>\n                                <td class=\"hover\" ng-click=\"col='dataChangeLastModifiedTime';desc=!desc;\">\n                                    Update Time\n                                    <span class=\"glyphicon glyphicon-sort\"></span>\n                                </td>\n                            </tr>\n                            </thead>\n                            <tbody>\n                            <tr ng-repeat=\"item in viewItems|orderBy:col:desc\">\n                                <td width=\"10%\"><input type=\"checkbox\" ng-checked=\"item.checked\"\n                                                       ng-click=\"switchSelect(item)\"></td>\n                                <td width=\"20%\">\n                                    <span ng-bind=\"item.key | limitTo: 250\"></span>\n                                    <span ng-bind=\"item.key.length > 250 ? '...' : ''\"></span>\n                                </td>\n                                <td class=\"cursor-pointer\" width=\"40%\" ng-click=\"showText(item.value)\">\n                                    <span ng-bind=\"item.value | limitTo: 250\"></span>\n                                    <span ng-bind=\"item.value.length > 250 ? '...' : ''\"></span>\n                                </td>\n                                <td width=\"15%\">\n                                    <span ng-bind=\"item.dataChangeCreatedTime  | date: 'yyyy-MM-dd HH:mm:ss'\"></span>\n                                </td>\n                                <td width=\"15%\">\n                                    <span ng-bind=\"item.dataChangeLastModifiedTime  | date: 'yyyy-MM-dd HH:mm:ss'\"></span>\n                                </td>\n                            </tr>\n                            </tbody>\n                        </table>\n\n                    </div>\n                </div>\n\n            </div>\n\n            <!--step 2-->\n            <div class=\"row\" ng-show=\"syncItemStep == 2\" ng-repeat=\"clusterDiff in clusterDiffs\">\n                <h4 class=\"text-center\">\n                    环境:<span ng-bind=\"clusterDiff.namespace.env\"></span>\n                    集群:<span ng-bind=\"clusterDiff.namespace.clusterName\"></span>\n                    <span ng-show=\"!clusterDiff.extInfo\">Namespace:{{pageContext.namespaceName}}</span>\n                </h4>\n                <div class=\"text-center\"\n                     ng-show=\"clusterDiff.diffs.createItems.length + clusterDiff.diffs.updateItems.length == 0 || clusterDiff.extInfo\">\n                    <span ng-show=\"clusterDiff.diffs.createItems.length + clusterDiff.diffs.updateItems.length == 0 && !clusterDiff.extInfo\">没有更新的配置</span>\n                    <span ng-show=\"clusterDiff.extInfo\" ng-bind=\"clusterDiff.extInfo\"></span>\n                    ,忽略同步\n                </div>\n\n                <div class=\"row\" style=\"margin-top: 10px;\"\n                     ng-show=\"clusterDiff.diffs.updateItems.length + clusterDiff.diffs.createItems.length > 0\">\n                    <div class=\"form-horizontal\">\n                        <div class=\"col-sm-12\">\n                            <table class=\"table table-bordered table-striped table-hover\">\n                                <thead>\n                                <tr>\n                                    <td>Type</td>\n                                    <td>Key</td>\n                                    <td>同步前</td>\n                                    <td>同步后</td>\n                                    <td>Comment</td>\n                                    <td>操作</td>\n                                </tr>\n                                </thead>\n                                <tbody>\n                                <tr ng-repeat=\"createItem in clusterDiff.diffs.createItems\">\n                                    <td width=\"5%\">新增</td>\n                                    <td width=\"15%\" ng-bind=\"createItem.key\"></td>\n                                    <td width=\"30%\"></td>\n                                    <td width=\"30%\" ng-bind=\"createItem.value\"></td>\n                                    <td width=\"15%\" ng-bind=\"createItem.comment\"></td>\n                                    <td width=\"5%\">\n                                        <a data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"不同步该配置\"\n                                           ng-click=\"removeItem(clusterDiff.diffs, 'create', createItem)\">删除</a>\n                                    </td>\n                                </tr>\n                                <tr ng-repeat=\"updateItem in clusterDiff.diffs.updateItems\">\n                                    <td width=\"5%\">更新</td>\n                                    <td width=\"15%\" ng-bind=\"updateItem.key\"></td>\n                                    <td width=\"30%\" ng-bind=\"updateItem.oldValue\"></td>\n                                    <td width=\"30%\" ng-bind=\"updateItem.value\"></td>\n                                    <td width=\"15%\" ng-bind=\"updateItem.comment\"></td>\n                                    <td width=\"5%\">\n                                        <a data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"不同步该配置\"\n                                           ng-click=\"removeItem(clusterDiff.diffs, 'update', updateItem)\">删除</a>\n                                    </td>\n                                </tr>\n                                </tbody>\n                            </table>\n\n                        </div>\n                    </div>\n                </div>\n            </div>\n\n\n            <!--step 3-->\n            <div class=\"row text-center\" ng-show=\"syncItemStep == 3 && syncSuccess\">\n                <img src=\"../img/sync-succ.png\" style=\"height: 100px; width: 100px\">\n                <h3>同步成功!</h3>\n            </div>\n            <div class=\"row text-center\" ng-show=\"syncItemStep == 3 && !syncSuccess\">\n                <img src=\"../img/sync-error.png\" style=\"height: 100px; width: 100px\">\n                <h3>同步失败!</h3>\n            </div>\n\n        </div>\n    </section>\n\n    <showtextmodal text=\"text\"/>\n</div>\n\n\n\n<div ng-include=\"'../views/common/footer.html'\"></div>\n\n<!-- jquery.js -->\n<script src=\"../vendor/jquery.min.js\" type=\"text/javascript\"></script>\n\n<!--angular-->\n<script src=\"../vendor/angular/angular.min.js\"></script>\n<script src=\"../vendor/angular/angular-resource.min.js\"></script>\n<script src=\"../vendor/angular/angular-toastr-1.4.1.tpls.min.js\"></script>\n<script src=\"../vendor/angular/loading-bar.min.js\"></script>\n\n\n<!-- bootstrap.js -->\n<script src=\"../vendor/bootstrap/js/bootstrap.min.js\" type=\"text/javascript\"></script>\n\n<!--nicescroll-->\n<script src=\"../vendor/jquery.nicescroll.min.js\"></script>\n\n<script src=\"../vendor/clipboard.min.js\" type=\"text/javascript\"></script>\n<!--biz-->\n<script type=\"application/javascript\" src=\"../scripts/app.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/services/AppService.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/services/EnvService.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/services/ConfigService.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/services/UserService.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/services/CommonService.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/services/PermissionService.js\"></script>\n\n<script type=\"application/javascript\" src=\"../scripts/AppUtils.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/controller/config/SyncConfigController.js\"></script>\n\n<script type=\"application/javascript\" src=\"../scripts/PageCommon.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/directive/directive.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/directive/show-text-modal-directive.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/config.html",
    "content": "<!DOCTYPE html>\n<html data-ng-app=\"application\">\n\n<head>\n    <meta charset=\"UTF-8\">\n    <title>Apollo配置中心</title>\n    <link rel=\"icon\" href=\"./img/config.png\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"vendor/bootstrap/css/bootstrap.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"vendor/angular/angular-toastr-1.4.1.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"vendor/select2/select2.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" media='all' href=\"vendor/angular/loading-bar.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"styles/common-style.css\">\n</head>\n\n<body>\n\n<apollonav></apollonav>\n\n<div id=\"config-info\" class=\"apollo-container app\">\n    <div ng-controller=\"ConfigBaseInfoController\">\n        <div class=\"J_appNotFound hidden row text-center app-not-found\" ng-show=\"notFoundApp\">\n            <img src=\"img/404.png\">\n            <br>\n            <p>\n                <span ng-bind=\"pageContext.appId\"></span> 不存在，<a href=\"/app.html\">点击创建</a>\n            </p>\n        </div>\n\n        <div class=\"side-bar\"\n             ng-class=\"{'position-absolute': viewMode == 1, 'position-fixed': viewMode == 2}\">\n            <div class=\"J_appFound hidden\"\n                 ng-show=\"!notFoundApp && (viewMode == 1 || (viewMode == 2 && showSideBar))\">\n\n                <!--env list-->\n                <section class=\"panel\">\n                    <header class=\"panel-heading\">\n                        环境列表\n                        <span class=\"pull-right\"\n                              data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"通过切换环境、集群来管理不同环境、集群的配置\">\n                                    <img src=\"img/question.png\" class=\"i-20\"/>\n                            </span>\n                    </header>\n                    <div id=\"treeview\" class=\"no-radius\"></div>\n                </section>\n\n\n                <!--app info-->\n                <section class=\"panel\">\n                    <header class=\"panel-heading\">\n                        项目信息\n                            <span class=\"pull-right\">\n\n                                <a href=\"/app/setting.html?#/appid={{pageContext.appId}}\"\n                                   style=\"margin-right: 5px;text-decoration:none;\">\n                                    <img src=\"img/edit.png\" class=\"i-20 cursor-pointer\"\n                                         data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"修改项目基本信息\"/>\n                                </a>\n\n                                <img src=\"img/unlike.png\" class=\"i-20 cursor-pointer\"\n                                     ng-if=\"!favoriteId\" ng-click=\"addFavorite()\"\n                                     data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"收藏\"/>\n\n                                <img src=\"img/like.png\" class=\"i-20 cursor-pointer\"\n                                     ng-if=\"favoriteId\" ng-click=\"deleteFavorite()\"\n                                     data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"取消收藏\"/>\n                            </span>\n                    </header>\n                    <div class=\"panel-body\">\n                        <table class=\"project-info\">\n                            <tbody class=\"text-left\">\n                            <tr>\n                                <th>AppId:</th>\n                                <td ng-bind=\"appBaseInfo.appId\"></td>\n                            </tr>\n                            <tr>\n                                <th>应用名:</th>\n                                <td>\n                                    <small ng-bind=\"appBaseInfo.name\"></small>\n                                </td>\n                            </tr>\n                            <tr>\n                                <th>部门:</th>\n                                <td ng-bind=\"appBaseInfo.orgInfo\"></td>\n                            </tr>\n                            <tr>\n                                <th>负责人:</th>\n                                <td ng-bind=\"appBaseInfo.ownerName\"></td>\n                            </tr>\n                            <tr>\n                                <th>邮箱:</th>\n                                <td>\n                                    <small ng-bind=\"appBaseInfo.ownerEmail\"></small>\n                                </td>\n                            </tr>\n                            <tr ng-show=\"missEnvs.length > 0\">\n                                <th>缺失的环境:</th>\n                                <td>\n                                <span ng-repeat=\"env in missEnvs\" ng-bind=\"env\">\n                                </span>\n                                </td>\n                            </tr>\n                            </tbody>\n                        </table>\n\n                    </div>\n                </section>\n\n                <!--operation entrance-->\n                <section>\n                    <apolloentrance apollo-title=\"'管理项目'\" apollo-img-src=\"'project-manage'\"\n                                    apollo-href=\"'/app/setting.html?#/appid=' + pageContext.appId\"></apolloentrance>\n\n                    <a class=\"list-group-item\" ng-show=\"missEnvs.length > 0\" ng-click=\"createAppInMissEnv()\">\n                        <div class=\"row icon-text icon-plus-orange\">\n                            <p class=\"btn-title ng-binding\">补缺环境</p>\n                        </div>\n                    </a>\n\n                    <apolloentrance apollo-title=\"'添加集群'\" apollo-img-src=\"'plus-orange'\"\n                                    apollo-href=\"'cluster.html?#/appid=' + pageContext.appId\"\n                                    ng-show=\"hasCreateClusterPermission\"></apolloentrance>\n\n                    <div class=\"list-group-item cursor-pointer hover\" ng-click=\"showMasterPermissionTips()\"\n                         ng-show=\"!hasCreateClusterPermission\">\n                        <div class=\"row icon-text icon-plus-orange\">\n                            <p class=\"btn-title\">添加集群</p>\n                        </div>\n                    </div>\n\n                    <apolloentrance apollo-title=\"'添加Namespace'\" apollo-img-src=\"'plus-orange'\"\n                                    apollo-href=\"'namespace.html?#/appid=' + pageContext.appId\"\n                                    ng-show=\"hasCreateNamespacePermission\"></apolloentrance>\n\n                    <div class=\"list-group-item cursor-pointer hover\" ng-click=\"showMasterPermissionTips()\"\n                         ng-show=\"!hasCreateNamespacePermission\">\n                        <div class=\"row icon-text icon-plus-orange\">\n                            <p class=\"btn-title\">添加Namespace</p>\n                        </div>\n                    </div>\n\n\n                </section>\n\n            </div>\n        </div>\n    </div>\n\n    <!--具体配置信息-->\n    <!--namespaces-->\n    <div class=\"config-item-container hide\"\n         ng-class=\"{'view-mode-1': viewMode == 1, 'view-mode-2': viewMode == 2}\"\n         ng-controller=\"ConfigNamespaceController\">\n\n        <h4 class=\"text-center\" ng-show=\"viewMode == 2\">\n            当前操作环境:{{pageContext.env}}， 集群:{{pageContext.clusterName}}\n        </h4>\n        <div class=\"alert alert-info alert-dismissible\" role=\"alert\"\n             ng-show=\"(!hideTip || !hideTip[pageContext.appId][pageContext.clusterName]) && envMapClusters[pageContext.env]\">\n\n            <button class=\"btn btn-sm btn-default pull-right\" style=\"margin-top: -7px;margin-right:-15px;\"\n                    ng-click=\"closeTip(pageContext.clusterName)\">不再提示\n            </button>\n\n            <!--default cluster tip -->\n            <div ng-show=\"pageContext.clusterName == 'default'\">\n                <strong>注意: </strong>所有不属于\n                <span ng-bind=\"envMapClusters[pageContext.env]\"></span>\n                集群的实例会使用default集群（当前页面）的配置，属于\n                <span ng-bind=\"envMapClusters[pageContext.env]\"></span>\n                的实例会使用对应集群的配置！\n            </div>\n\n            <!--custom cluster tip-->\n            <div ng-show=\"pageContext.clusterName != 'default'\">\n                <strong>注意:</strong>属于\n                <span ng-bind=\"pageContext.clusterName\"></span>\n                集群的实例只会使用\n                <span ng-bind=\"pageContext.clusterName\"></span>\n                集群（当前页面）的配置，只有当对应namespace在当前集群没有发布过配置时，才会使用default集群的配置。\n            </div>\n\n        </div>\n\n        <div class=\"alert alert-info\"\n             ng-if=\"hasNotPublishNamespace\">\n            <p><b>注意:</b> 以下环境/集群有未发布的配置，客户端获取不到未发布的配置，请及时发布。</p>\n            <p>\n                <mark ng-bind=\"namespacePublishInfo.join('，')\"></mark>\n            </p>\n        </div>\n\n        <apollonspanel ng-repeat=\"namespace in namespaces\"\n                       namespace=\"namespace\"\n                       app-id=\"pageContext.appId\"\n                       env=\"pageContext.env\"\n                       lock-check=\"lockCheck\"\n                       cluster=\"pageContext.clusterName\"\n                       user=\"currentUser\"\n                       pre-release-ns=\"prepareReleaseNamespace\"\n                       create-item=\"createItem\" edit-item=\"editItem\"\n                       pre-delete-item=\"preDeleteItem\"\n                       show-text=\"showText\"\n                       show-no-modify-permission-dialog=\"showNoModifyPermissionDialog\"\n                       pre-create-branch=\"preCreateBranch\"\n                       pre-delete-branch=\"preDeleteBranch\">\n        </apollonspanel>\n\n        <releasemodal app-id=\"pageContext.appId\"\n                      env=\"pageContext.env\"\n                      cluster=\"pageContext.clusterName\">\n        </releasemodal>\n\n        <itemmodal to-operation-namespace=\"toOperationNamespace\"\n                   app-id=\"pageContext.appId\"\n                   env=\"pageContext.env\"\n                   cluster=\"pageContext.clusterName\"\n                   item=\"item\">\n        </itemmodal>\n\n        <showtextmodal text=\"text\"></showtextmodal>\n\n        <rollbackmodal app-id=\"pageContext.appId\"\n                       env=\"pageContext.env\"\n                       cluster=\"pageContext.clusterName\">\n        </rollbackmodal>\n\n        <rulesmodal app-id=\"pageContext.appId\"\n                    env=\"pageContext.env\"\n                    cluster=\"pageContext.clusterName\">\n\n        </rulesmodal>\n\n\n        <mergeandpublishmodal app-id=\"pageContext.appId\"\n                              env=\"pageContext.env\"\n                              cluster=\"pageContext.clusterName\">\n        </mergeandpublishmodal>\n\n        <publishdenymodal env=\"pageContext.env\"></publishdenymodal>\n\n        <deletenamespacemodal env=\"pageContext.env\"></deletenamespacemodal>\n\n        <apolloconfirmdialog apollo-dialog-id=\"'deleteConfirmDialog'\" apollo-title=\"'删除配置'\"\n                             apollo-detail=\"'确定要删除配置吗?'\"\n                             apollo-show-cancel-btn=\"true\" apollo-confirm=\"deleteItem\"></apolloconfirmdialog>\n\n        <apolloconfirmdialog apollo-dialog-id=\"'releaseNoPermissionDialog'\" apollo-title=\"'发布'\"\n                             apollo-detail=\"'您没有发布权限哦~ 请找项目管理员 ' + masterUsers + ' 分配发布权限'\"\n                             apollo-show-cancel-btn=\"false\"></apolloconfirmdialog>\n\n        <apolloconfirmdialog apollo-dialog-id=\"'modifyNoPermissionDialog'\" apollo-title=\"'申请配置权限'\"\n                             apollo-detail=\"'请找项目管理员 ' + masterUsers + ' 分配编辑或发布权限'\"\n                             apollo-show-cancel-btn=\"false\"></apolloconfirmdialog>\n\n        <apolloconfirmdialog apollo-dialog-id=\"'masterNoPermissionDialog'\" apollo-title=\"'申请配置权限'\"\n                             apollo-detail=\"'您不是项目管理员， 只有项目管理员才有添加集群、namespace的权限。\n                                 如需管理员权限，请找项目管理员 ' + masterUsers + ' 分配管理员权限'\"\n                             apollo-show-cancel-btn=\"false\"></apolloconfirmdialog>\n\n        <apolloconfirmdialog apollo-dialog-id=\"'namespaceLockedDialog'\" apollo-title=\"'编辑受限'\"\n                             apollo-detail=\"'当前namespace正在被 ' + lockOwner + ' 编辑，一次发布只能被一个人修改.'\"\n                             apollo-show-cancel-btn=\"false\"></apolloconfirmdialog>\n\n        <apolloconfirmdialog apollo-dialog-id=\"'rollbackAlertDialog'\" apollo-title=\"'回滚'\"\n                             apollo-detail=\"'确定要回滚吗?'\"\n                             apollo-show-cancel-btn=\"true\" apollo-confirm=\"rollback\"></apolloconfirmdialog>\n\n        <apolloconfirmdialog apollo-dialog-id=\"'emergencyPublishAlertDialog'\" apollo-title=\"'紧急发布'\"\n                             apollo-detail=\"'确定要紧急发布吗?'\"\n                             apollo-show-cancel-btn=\"true\" apollo-confirm=\"emergencyPublish\"></apolloconfirmdialog>\n\n        <apolloconfirmdialog apollo-dialog-id=\"'deleteBranchDialog'\" apollo-title=\"'删除灰度'\"\n                             apollo-detail=\"'删除灰度会丢失灰度的配置，确定要删除吗?'\"\n                             apollo-show-cancel-btn=\"true\" apollo-confirm=\"deleteBranch\"></apolloconfirmdialog>\n\n        <apolloconfirmdialog apollo-dialog-id=\"'updateRuleTips'\" apollo-title=\"'更新灰度规则提示'\"\n                             apollo-detail=\"'灰度规则已生效，但发现灰度版本有未发布的配置，这些配置需要手动灰度发布才会生效'\"></apolloconfirmdialog>\n\n        <apolloconfirmdialog apollo-dialog-id=\"'mergeAndReleaseDenyDialog'\" apollo-title=\"'全量发布'\"\n                             apollo-detail=\"'namespace主版本有未发布的配置，请先发布主版本配置'\"></apolloconfirmdialog>\n\n        <apolloconfirmdialog apollo-dialog-id=\"'grayReleaseWithoutRulesTips'\" apollo-title=\"'缺失灰度规则提示'\"\n                             apollo-detail=\"'灰度版本还没有配置任何灰度规则，请配置灰度规则'\">\n        </apolloconfirmdialog>\n\n        <apolloconfirmdialog apollo-dialog-id=\"'deleteNamespaceDenyForMasterInstanceDialog'\"\n                             apollo-title=\"'删除Namespace警告信息'\"\n                             apollo-detail=\"'发现有 <b>' + deleteNamespaceContext.namespace.instancesCount +\n                             '</b> 个实例正在使用Namespace(' + deleteNamespaceContext.namespace.baseInfo.namespaceName +\n                             ')，删除Namespace将导致实例获取不到配置。<br>\n                             请到 <ins>“实例列表”</ins> 确认实例信息，如已确认删除Namespace将不会导致实例异常，\n                             请联系Apollo相关负责人删除Namespace'\"\n                             apollo-confirm=\"continueDeleteNamespace\">\n        </apolloconfirmdialog>\n\n        <apolloconfirmdialog apollo-dialog-id=\"'deleteNamespaceDenyForBranchInstanceDialog'\"\n                             apollo-title=\"'删除Namespace警告信息'\"\n                             apollo-detail=\"'发现有 <b>' + deleteNamespaceContext.namespace.branch.latestReleaseInstances.total\n                             + '</b> 个实例正在使用Namespace(' + deleteNamespaceContext.namespace.baseInfo.namespaceName +\n                             ')灰度版本的配置，删除Namespace将导致实例获取不到配置。<br>\n                             请到 <ins>“灰度版本” => “实例列表”</ins> 确认实例信息，如已确认删除Namespace将不会导致实例异常，\n                             请联系Apollo相关负责人删除Namespace'\"\n                             apollo-confirm=\"continueDeleteNamespace\">\n        </apolloconfirmdialog>\n\n        <apolloconfirmdialog apollo-dialog-id=\"'deleteNamespaceDenyForPublicNamespaceDialog'\"\n                             apollo-title=\"'删除Namespace失败提示'\"\n                             apollo-detail=\"deleteNamespaceContext.detailReason\">\n        </apolloconfirmdialog>\n\n\n        <div class=\"modal fade\" id=\"createBranchTips\" tabindex=\"-1\" role=\"dialog\">\n            <div class=\"modal-dialog\" role=\"document\">\n                <div class=\"modal-content\">\n                    <div class=\"modal-header panel-primary\">\n                        <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\"><span\n                                aria-hidden=\"true\">&times;</span></button>\n                        <h4 class=\"modal-title\">创建灰度须知</h4>\n                    </div>\n                    <div class=\"modal-body\">\n                        通过创建灰度版本，您可以对某些配置做灰度测试<br>\n                        灰度流程为:<br>\n                        &nbsp;&nbsp;1.创建灰度版本 <br>\n                        &nbsp;&nbsp;2.配置灰度配置项<br>\n                        &nbsp;&nbsp;3.配置灰度规则.如果是私有的namespace可以按照客户端的IP进行灰度，如果是公共的namespace则可以同时按AppId和客户端的IP进行灰度<br>\n                        &nbsp;&nbsp;4.灰度发布<br>\n                        灰度版本最终有两种结果:<b>全量发布和放弃灰度</b><br>\n                        <b>全量发布</b>:灰度的配置合到主版本并发布，所有的客户端都会使用合并后的配置<br>\n                        <b>放弃灰度</b>:删除灰度版本，所有的客户端都会使用回主版本的配置<br>\n                        注意事项:<br>\n                        &nbsp;&nbsp;1.如果灰度版本已经有灰度发布过，那么修改灰度规则后，无需再次灰度发布就立即生效<br>\n                    </div>\n                    <div class=\"modal-footer\">\n                        <button type=\"button\" class=\"btn btn-default\" data-dismiss=\"modal\">取消</button>\n                        <button type=\"button\" class=\"btn btn-primary\" data-dismiss=\"modal\"\n                                ng-click=\"createBranch()\">\n                            确定\n                        </button>\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>\n\n\n<div ng-include=\"'views/common/footer.html'\"></div>\n\n\n<!-- jquery.js -->\n<script src=\"vendor/jquery.min.js\" type=\"text/javascript\"></script>\n\n<script src=\"vendor/select2/select2.min.js\" type=\"text/javascript\"></script>\n\n<!--lodash.js-->\n<script src=\"vendor/lodash.min.js\" type=\"text/javascript\"></script>\n\n<!--nicescroll-->\n<script src=\"vendor/jquery.nicescroll.min.js\"></script>\n\n<!--angular-->\n<script src=\"vendor/angular/angular.min.js\"></script>\n<script src=\"vendor/angular/angular-resource.min.js\"></script>\n<script src=\"vendor/angular/angular-toastr-1.4.1.tpls.min.js\"></script>\n<script src=\"vendor/angular/loading-bar.min.js\"></script>\n\n<!-- bootstrap.js -->\n<script src=\"vendor/bootstrap/js/bootstrap.min.js\" type=\"text/javascript\"></script>\n<script src=\"vendor/bootstrap/js/bootstrap-treeview.min.js\" type=\"text/javascript\"></script>\n\n<script src=\"vendor/diff.min.js\" type=\"text/javascript\"></script>\n\n<script src=\"vendor/clipboard.min.js\" type=\"text/javascript\"></script>\n\n<script src=\"vendor/ui-ace/ace.js\" type=\"text/javascript\"></script>\n<script src=\"vendor/ui-ace/ui-ace.min.js\" type=\"text/javascript\"></script>\n<script src=\"vendor/ui-ace/mode-properties.js\" type=\"text/javascript\"></script>\n<script src=\"vendor/ui-ace/mode-xml.js\" type=\"text/javascript\"></script>\n<script src=\"vendor/ui-ace/mode-yaml.js\" type=\"text/javascript\"></script>\n<script src=\"vendor/ui-ace/mode-json.js\" type=\"text/javascript\"></script>\n<script src=\"vendor/ui-ace/worker-json.js\" type=\"text/javascript\"></script>\n<script src=\"vendor/ui-ace/worker-xml.js\" type=\"text/javascript\"></script>\n\n\n\n<!--valdr-->\n<script src=\"vendor/valdr/valdr.min.js\" type=\"text/javascript\"></script>\n<script src=\"vendor/valdr/valdr-message.min.js\" type=\"text/javascript\"></script>\n\n<!--biz script-->\n<script type=\"application/javascript\" src=\"scripts/app.js\"></script>\n\n<!--service-->\n<script type=\"application/javascript\" src=\"scripts/services/AppService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/EnvService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/UserService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/ConfigService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/ReleaseService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/PermissionService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/NamespaceService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/CommitService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/CommonService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/NamespaceLockService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/InstanceService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/FavoriteService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/NamespaceBranchService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/EventManager.js\"></script>\n\n\n<script type=\"application/javascript\" src=\"scripts/AppUtils.js\"></script>\n\n<!--directive-->\n<script type=\"application/javascript\" src=\"scripts/directive/directive.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/directive/namespace-panel-directive.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/directive/diff-directive.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/directive/release-modal-directive.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/directive/item-modal-directive.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/directive/show-text-modal-directive.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/directive/rollback-modal-directive.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/directive/gray-release-rules-modal-directive.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/directive/merge-and-publish-modal-directive.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/directive/publish-deny-modal-directive.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/directive/delete-namespace-modal-directive.js\"></script>\n\n<!--controller-->\n<script type=\"application/javascript\" src=\"scripts/controller/config/ConfigNamespaceController.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/controller/config/ConfigBaseInfoController.js\"></script>\n\n<script type=\"application/javascript\" src=\"scripts/PageCommon.js\"></script>\n\n<script src=\"scripts/valdr.js\" type=\"text/javascript\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/ctrip_sso_heartbeat.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>SSO Heartbeat</title>\n    <script type=\"text/javascript\">\n        var reloading = false;\n        setInterval(function () {\n            if (document.cookie.indexOf('memCacheAssertionID=') == -1) {\n                if (reloading) {\n                    return;\n                }\n                reloading = true;\n                console.log(\"sso memCacheAssertionID expires, try reloading\");\n                location.reload(true);\n            }\n        }, 1000);\n    </script>\n</head>\n<body>\n</body>\n</html>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/default_sso_heartbeat.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>SSO Heartbeat</title>\n    <script type=\"text/javascript\">\n        var reloading = false;\n        setInterval(function () {\n            if (reloading) {\n                return;\n            }\n            reloading = true;\n            location.reload(true);\n        }, 60000);\n    </script>\n</head>\n<body>\n</body>\n</html>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/index.html",
    "content": "<!doctype html>\n<html ng-app=\"index\">\n<head>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n    <link rel=\"icon\" href=\"./img/config.png\">\n    <!-- styles -->\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"vendor/bootstrap/css/bootstrap.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"vendor/angular/angular-toastr-1.4.1.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" media='all' href=\"vendor/angular/loading-bar.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" media='all' href=\"vendor/font-awesome.min.css\">\n\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"styles/common-style.css\">\n    <title>Apollo配置中心</title>\n</head>\n\n<body>\n\n<apollonav></apollonav>\n\n<div id=\"app-list\" class=\"hidden\" ng-controller=\"IndexController\">\n\n    <section class=\"media create-app-list\">\n        <aside class=\"media-left text-center\">\n            <h5>我的项目</h5>\n        </aside>\n        <aside class=\"media-body\">\n            <div class=\"app-panel col-md-2 text-center\" ng-click=\"goToCreateAppPage()\">\n                <div href=\"#\" class=\"thumbnail create-btn hover cursor-pointer\">\n                    <img src=\"img/plus-white.png\"/>\n                    <h5>创建项目</h5>\n                </div>\n            </div>\n            <div class=\"app-panel col-md-2 text-center\" ng-repeat=\"app in createdApps\"\n                 ng-click=\"goToAppHomePage(app.appId)\">\n                <div href=\"#\" class=\"thumbnail hover cursor-pointer\">\n                    <h4 ng-bind=\"app.appId\"></h4>\n                    <h5 ng-bind=\"app.name\"></h5>\n                </div>\n            </div>\n            <div class=\"app-panel col-md-2 text-center\" ng-show=\"hasMoreCreatedApps\"\n                 ng-click=\"getUserCreatedApps()\">\n                <div href=\"#\" class=\"thumbnail hover cursor-pointer\">\n                    <img class=\"more-img\" src=\"img/more.png\"/>\n                    <h5>加载更多</h5>\n                </div>\n            </div>\n        </aside>\n    </section>\n\n    <section class=\"media favorites-app-list\">\n        <aside class=\"media-left text-center\">\n            <h5>收藏的项目</h5>\n        </aside>\n        <aside class=\"media-body\">\n            <div class=\"app-panel col-md-2 text-center\"\n                 ng-repeat=\"app in favorites\"\n                 ng-click=\"goToAppHomePage(app.appId)\"\n                 ng-mouseover=\"toggleOperationBtn(app)\"\n                 ng-mouseout=\"toggleOperationBtn(app)\">\n                <div class=\"thumbnail hover\">\n                    <h4 ng-bind=\"app.appId\"></h4>\n                    <h5 ng-bind=\"app.name\"></h5>\n\n                    <p class=\"operate-panel\" ng-show=\"app.showOperationBtn\">\n                        <button class=\"btn btn-default btn-xs\" title=\"置顶\"\n                                ng-click=\"toTop(app.favoriteId);$event.stopPropagation();\">\n                            <img src=\"img/top.png\" class=\"i-15\">\n                        </button>\n                        <button class=\"btn btn-default btn-xs\" title=\"取消收藏\"\n                                ng-click=\"deleteFavorite(app.favoriteId);$event.stopPropagation();\">\n                            <img src=\"img/like.png\" class=\"i-15\">\n                        </button>\n                    </p>\n                </div>\n            </div>\n            <div class=\"col-md-2 text-center\" ng-show=\"hasMoreFavorites\"\n                 ng-click=\"getUserFavorites()\">\n                <div href=\"#\" class=\"thumbnail hover cursor-pointer\">\n                    <img class=\"more-img\" src=\"img/more.png\"/>\n                    <h5>加载更多</h5>\n                </div>\n            </div>\n            <div class=\"no-favorites text-center\" ng-show=\"!favorites || favorites.length == 0\">\n                <h4>您还没有收藏过任何项目，在项目主页可以收藏项目哟~</h4>\n            </div>\n\n        </aside>\n    </section>\n\n    <section class=\"media visit-app-list\" ng-show=\"visitedApps && visitedApps.length\">\n        <aside class=\"media-left text-center\">\n            <h5>最近浏览的项目</h5>\n        </aside>\n        <aside class=\"media-body\">\n            <div class=\"app-panel col-md-2 text-center\"\n                 ng-repeat=\"app in visitedApps\"\n                 ng-click=\"goToAppHomePage(app.appId)\">\n                <div class=\"thumbnail hover\">\n                    <h4 ng-bind=\"app.appId\"></h4>\n                    <h5 ng-bind=\"app.name\"></h5>\n                </div>\n            </div>\n        </aside>\n    </section>\n</div>\n\n\n<div ng-include=\"'views/common/footer.html'\"></div>\n\n<!--angular-->\n<script src=\"vendor/angular/angular.min.js\"></script>\n<script src=\"vendor/angular/angular-resource.min.js\"></script>\n<script src=\"vendor/angular/angular-toastr-1.4.1.tpls.min.js\"></script>\n<script src=\"vendor/angular/loading-bar.min.js\"></script>\n\n<!-- jquery.js -->\n<script src=\"vendor/jquery.min.js\" type=\"text/javascript\"></script>\n\n<!-- bootstrap.js -->\n<script src=\"vendor/bootstrap/js/bootstrap.min.js\" type=\"text/javascript\"></script>\n\n<!--nicescroll-->\n<script src=\"vendor/jquery.nicescroll.min.js\"></script>\n\n<script type=\"application/javascript\" src=\"scripts/app.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/AppService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/EnvService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/UserService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/CommonService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/FavoriteService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/PermissionService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/AppUtils.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/directive/directive.js\"></script>\n\n<script type=\"application/javascript\" src=\"scripts/controller/IndexController.js\"></script>\n\n</body>\n</html>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/java/com/example/demo/EcvoicesystemDemoApplicationTests.java",
    "content": "package com.example.demo;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit4.SpringRunner;\n\n@RunWith(SpringRunner.class)\n@SpringBootTest\npublic class EcvoicesystemDemoApplicationTests {\n\n\t@Test\n\tpublic void contextLoads() {\n\t}\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/login.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\" ng-app=\"login\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>Apollo配置中心</title>\n    <link rel=\"icon\" href=\"./img/config.png\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"vendor/bootstrap/css/bootstrap.min.css\">\n    <link rel=\"stylesheet\" href=\"vendor/font-awesome.min.css\">\n    <style type=\"text/css\">\n        @import url(https://fonts.googleapis.com/css?family=Roboto:400,300,100,700,500);\n\n        body {\n            padding-top: 90px;\n            background: #F7F7F7;\n            color: #666666;\n            font-family: 'Roboto', sans-serif;\n            font-weight: 100;\n        }\n\n        body {\n            width: 100%;\n            background: -webkit-linear-gradient(left, #22d686, #24d3d3, #22d686, #24d3d3);\n            background: linear-gradient(to right, #22d686, #24d3d3, #22d686, #24d3d3);\n            background-size: 600% 100%;\n            -webkit-animation: HeroBG 20s ease infinite;\n            animation: HeroBG 20s ease infinite;\n        }\n\n        @-webkit-keyframes HeroBG {\n            0% {\n                background-position: 0 0;\n            }\n            50% {\n                background-position: 100% 0;\n            }\n            100% {\n                background-position: 0 0;\n            }\n        }\n\n        @keyframes HeroBG {\n            0% {\n                background-position: 0 0;\n            }\n            50% {\n                background-position: 100% 0;\n            }\n            100% {\n                background-position: 0 0;\n            }\n        }\n\n        .panel {\n            border-radius: 5px;\n        }\n\n        label {\n            font-weight: 300;\n        }\n\n        .panel-login {\n            border: none;\n            -webkit-box-shadow: 0px 0px 49px 14px rgba(188, 190, 194, 0.39);\n            -moz-box-shadow: 0px 0px 49px 14px rgba(188, 190, 194, 0.39);\n            box-shadow: 0px 0px 49px 14px rgba(188, 190, 194, 0.39);\n        }\n\n        .panel-login .checkbox input[type=checkbox] {\n            margin-left: 0px;\n        }\n\n        .panel-login .checkbox label {\n            padding-left: 25px;\n            font-weight: 300;\n            display: inline-block;\n            position: relative;\n        }\n\n        .panel-login .checkbox {\n            padding-left: 20px;\n        }\n\n        .panel-login .checkbox label::before {\n            content: \"\";\n            display: inline-block;\n            position: absolute;\n            width: 17px;\n            height: 17px;\n            left: 0;\n            margin-left: 0px;\n            border: 1px solid #cccccc;\n            border-radius: 3px;\n            background-color: #fff;\n            -webkit-transition: border 0.15s ease-in-out, color 0.15s ease-in-out;\n            -o-transition: border 0.15s ease-in-out, color 0.15s ease-in-out;\n            transition: border 0.15s ease-in-out, color 0.15s ease-in-out;\n        }\n\n        .panel-login .checkbox label::after {\n            display: inline-block;\n            position: absolute;\n            width: 16px;\n            height: 16px;\n            left: 0;\n            top: 0;\n            margin-left: 0px;\n            padding-left: 3px;\n            padding-top: 1px;\n            font-size: 11px;\n            color: #555555;\n        }\n\n        .panel-login .checkbox input[type=\"checkbox\"] {\n            opacity: 0;\n        }\n\n        .panel-login .checkbox input[type=\"checkbox\"]:focus + label::before {\n            outline: thin dotted;\n            outline: 5px auto -webkit-focus-ring-color;\n            outline-offset: -2px;\n        }\n\n        .panel-login .checkbox input[type=\"checkbox\"]:checked + label::after {\n            font-family: 'FontAwesome';\n            content: \"\\f00c\";\n        }\n\n        .panel-login > .panel-heading .tabs {\n            padding: 0;\n        }\n\n        .panel-login h2 {\n            font-size: 20px;\n            font-weight: 300;\n            margin: 30px;\n        }\n\n        .panel-login > .panel-heading {\n            color: #848c9d;\n            background-color: #e8e9ec;\n            border-color: #fff;\n            text-align: center;\n            border-bottom-left-radius: 5px;\n            border-bottom-right-radius: 5px;\n            border-top-left-radius: 0px;\n            border-top-right-radius: 0px;\n            border-bottom: 0px;\n            padding: 0px 15px;\n        }\n\n        .panel-login .form-group {\n            padding: 0 30px;\n        }\n\n        .panel-login > .panel-heading .login {\n            padding: 20px 30px;\n            border-bottom-leftt-radius: 5px;\n        }\n\n        .panel-login > .panel-heading .register {\n            padding: 20px 30px;\n            background: #2d3b55;\n            border-bottom-right-radius: 5px;\n        }\n\n        .panel-login > .panel-heading a {\n            text-decoration: none;\n            color: #666;\n            font-weight: 300;\n            font-size: 16px;\n            -webkit-transition: all 0.1s linear;\n            -moz-transition: all 0.1s linear;\n            transition: all 0.1s linear;\n        }\n\n        .panel-login > .panel-heading a#register-form-link {\n            color: #fff;\n            width: 100%;\n            text-align: right;\n        }\n\n        .panel-login > .panel-heading a#login-form-link {\n            width: 100%;\n            text-align: left;\n        }\n\n        .panel-login input[type=\"text\"], .panel-login input[type=\"email\"], .panel-login input[type=\"password\"] {\n            height: 45px;\n            border: 0;\n            font-size: 16px;\n            -webkit-transition: all 0.1s linear;\n            -moz-transition: all 0.1s linear;\n            transition: all 0.1s linear;\n            -webkit-box-shadow: none;\n            box-shadow: none;\n            border-bottom: 1px solid #e7e7e7;\n            border-radius: 0px;\n            padding: 6px 0px;\n        }\n\n        .panel-login input:hover,\n        .panel-login input:focus {\n            outline: none;\n            -webkit-box-shadow: none;\n            -moz-box-shadow: none;\n            box-shadow: none;\n            border-color: #ccc;\n        }\n\n        .btn-login {\n            background-color: #E8E9EC;\n            outline: none;\n            color: #2D3B55;\n            font-size: 14px;\n            height: auto;\n            font-weight: normal;\n            padding: 14px 0;\n            text-transform: uppercase;\n            border: none;\n            border-radius: 0px;\n            box-shadow: none;\n        }\n\n        .btn-login:hover,\n        .btn-login:focus {\n            color: #fff;\n            background-color: #2D3B55;\n        }\n\n        .forgot-password {\n            text-decoration: underline;\n            color: #888;\n        }\n\n        .forgot-password:hover,\n        .forgot-password:focus {\n            text-decoration: underline;\n            color: #666;\n        }\n\n        .btn-register {\n            background-color: #E8E9EC;\n            outline: none;\n            color: #2D3B55;\n            font-size: 14px;\n            height: auto;\n            font-weight: normal;\n            padding: 14px 0;\n            text-transform: uppercase;\n            border: none;\n            border-radius: 0px;\n            box-shadow: none;\n        }\n\n        .btn-register:hover,\n        .btn-register:focus {\n            color: #fff;\n            background-color: #2D3B55;\n        }\n\n    </style>\n</head>\n<body>\n\n<div class=\"container\" ng-controller=\"LoginController\">\n    <div class=\"row\">\n        <div class=\"col-md-6 col-md-offset-3\">\n            <div class=\"panel panel-login\">\n                <div class=\"panel-body\">\n                    <div class=\"row\">\n                        <div class=\"col-lg-12\">\n                            <form id=\"login-form\" action=\"/signin\" method=\"post\" role=\"form\" style=\"display: block;\">\n                                <h2 class=\"text-center\">Apollo配置中心</h2>\n\n                                <div class=\"form-group\">\n                                    <input type=\"text\" name=\"username\" tabindex=\"1\" class=\"form-control\"\n                                           placeholder=\"Username\" value=\"\">\n                                </div>\n                                <div class=\"form-group\">\n                                    <input type=\"password\" name=\"password\" tabindex=\"2\"\n                                           class=\"form-control\" placeholder=\"Password\">\n                                </div>\n                                <div class=\"form-group\" style=\"color: red\">\n                                    <small ng-bind=\"info\"></small>\n                                </div>\n                                <div class=\"col-xs-12 form-group pull-right\">\n                                    <input type=\"submit\" name=\"login-submit\" id=\"login-submit\" tabindex=\"4\"\n                                           class=\"form-control btn btn-login\" value=\"登录\">\n                                </div>\n                            </form>\n                        </div>\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>\n<!-- jquery.js -->\n<script src=\"vendor/jquery.min.js\" type=\"text/javascript\"></script>\n<!-- bootstrap.js -->\n<script src=\"vendor/bootstrap/js/bootstrap.min.js\" type=\"text/javascript\"></script>\n\n<!--angular-->\n<script src=\"vendor/angular/angular.min.js\"></script>\n<script src=\"vendor/angular/angular-resource.min.js\"></script>\n<script src=\"vendor/angular/angular-toastr-1.4.1.tpls.min.js\"></script>\n<script src=\"vendor/angular/loading-bar.min.js\"></script>\n\n<script type=\"application/javascript\" src=\"scripts/app.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/AppUtils.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/directive/directive.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/controller/LoginController.js\"></script>\n\n\n<script type=\"application/javascript\">\n    $(function () {\n        $('#login-form-link').click(function (e) {\n            $(\"#login-form\").delay(100).fadeIn(100);\n            $(\"#register-form\").fadeOut(100);\n            $('#register-form-link').removeClass('active');\n            $(this).addClass('active');\n            e.preventDefault();\n        });\n        $('#register-form-link').click(function (e) {\n            $(\"#register-form\").delay(100).fadeIn(100);\n            $(\"#login-form\").fadeOut(100);\n            $('#login-form-link').removeClass('active');\n            $(this).addClass('active');\n            e.preventDefault();\n        });\n\n    });\n\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/namespace/role.html",
    "content": "<!doctype html>\n<html ng-app=\"role\">\n<head>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n    <link rel=\"icon\" href=\"../img/config.png\">\n    <!-- styles -->\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"../vendor/bootstrap/css/bootstrap.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"../vendor/angular/angular-toastr-1.4.1.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" media='all' href=\"../vendor/angular/loading-bar.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"../styles/common-style.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"../vendor/select2/select2.min.css\">\n    <title>权限管理</title>\n</head>\n\n<body>\n\n<apollonav></apollonav>\n\n<div class=\"container-fluid apollo-container\">\n    <section class=\"panel col-md-offset-1 col-md-10\" ng-controller=\"NamespaceRoleController\">\n        <header class=\"panel-heading\">\n            <div class=\"row\">\n                <div class=\"col-md-7\">\n                    <h4 class=\"modal-title\">权限管理<small>(AppId:<label ng-bind=\"pageContext.appId\"></label> Namespace:<label ng-bind=\"pageContext.namespaceName\"></label>)</small>\n                    </h4>\n                </div>\n                <div class=\"col-md-5 text-right\">\n                    <a type=\"button\" class=\"btn btn-info\" data-dismiss=\"modal\"\n                            href=\"/config.html?#appid={{pageContext.appId}}\">返回到项目首页\n                    </a>\n                </div>\n            </div>\n        </header>\n        <div class=\"panel-body\" ng-show=\"hasAssignUserPermission\">\n            <div class=\"row\">\n                <div class=\"form-horizontal\">\n                    <div class=\"form-group\">\n                        <label class=\"col-sm-2 control-label\">修改权<br><small>(可以修改配置)</small></label>\n                        <div class=\"col-sm-8\">\n                            <form class=\"form-inline\" ng-submit=\"assignRoleToUser('ModifyNamespace')\">\n                                <div class=\"form-group\">\n                                    <apollouserselector apollo-id=\"modifyRoleWidgetId\"></apollouserselector>\n                                </div>\n                                <button type=\"submit\" class=\"btn btn-default\" style=\"margin-left: 20px;\" ng-disabled=\"modifyRoleSubmitBtnDisabled\">添加</button>\n                            </form>\n                            <!-- Split button -->\n                            <div class=\"item-container\">\n\n                                <div class=\"btn-group item-info\" ng-repeat=\"user in rolesAssignedUsers.modifyRoleUsers\">\n                                    <button type=\"button\" class=\"btn btn-default\" ng-bind=\"user.userId\"></button>\n                                    <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                            aria-haspopup=\"true\" aria-expanded=\"false\" ng-click=\"removeUserRole('ModifyNamespace', user.userId)\">\n                                        <span class=\"glyphicon glyphicon-remove\"></span>\n                                    </button>\n                                </div>\n                            </div>\n\n                        </div>\n                    </div>\n                </div>\n                <hr>\n\n                <div class=\"row\" style=\"margin-top: 10px;\">\n                    <div class=\"form-horizontal\">\n                        <div class=\"col-sm-2 text-right\">\n                            <label class=\"control-label\">发布权<br><small>(可以发布配置)</small></label>\n                        </div>\n                        <div class=\"col-sm-8\">\n                            <form class=\"form-inline\" ng-submit=\"assignRoleToUser('ReleaseNamespace')\">\n                                <div class=\"form-group\">\n                                    <apollouserselector apollo-id=\"releaseRoleWidgetId\"></apollouserselector>\n\n                                </div>\n                                <button type=\"submit\" class=\"btn btn-default\" style=\"margin-left: 20px;\" ng-disabled=\"ReleaseRoleSubmitBtnDisabled\">添加</button>\n                            </form>\n                            <!-- Split button -->\n                            <div class=\"item-container\">\n                                <div class=\"btn-group item-info\" ng-repeat=\"user in rolesAssignedUsers.releaseRoleUsers\">\n                                    <button type=\"button\" class=\"btn btn-default\" ng-bind=\"user.userId\"></button>\n                                    <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\"\n                                            aria-haspopup=\"true\" aria-expanded=\"false\" ng-click=\"removeUserRole('ReleaseNamespace', user.userId)\">\n                                        <span class=\"glyphicon glyphicon-remove\"></span>\n                                    </button>\n                                </div>\n                            </div>\n\n                        </div>\n                    </div>\n\n                </div>\n\n            </div>\n\n\n        </div>\n        <div class=\"panel-body text-center\" ng-show=\"!hasAssignUserPermission\">\n            <h2>您没有权限哟!</h2>\n        </div>\n\n    </section>\n</div>\n\n<div ng-include=\"'../views/common/footer.html'\"></div>\n\n<!-- jquery.js -->\n<script src=\"../vendor/jquery.min.js\" type=\"text/javascript\"></script>\n\n<!--angular-->\n<script src=\"../vendor/angular/angular.min.js\"></script>\n<script src=\"../vendor/angular/angular-resource.min.js\"></script>\n<script src=\"../vendor/angular/angular-toastr-1.4.1.tpls.min.js\"></script>\n<script src=\"../vendor/angular/loading-bar.min.js\"></script>\n\n\n<!-- bootstrap.js -->\n<script src=\"../vendor/bootstrap/js/bootstrap.min.js\" type=\"text/javascript\"></script>\n\n<!--nicescroll-->\n<script src=\"../vendor/jquery.nicescroll.min.js\"></script>\n\n<script src=\"../vendor/select2/select2.min.js\" type=\"text/javascript\"></script>\n\n<!--biz-->\n<!--must import-->\n<script type=\"application/javascript\" src=\"../scripts/app.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/services/AppService.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/services/EnvService.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/services/UserService.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/services/CommonService.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/services/PermissionService.js\"></script>\n\n<script type=\"application/javascript\" src=\"../scripts/AppUtils.js\"></script>\n\n<script type=\"application/javascript\" src=\"../scripts/PageCommon.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/directive/directive.js\"></script>\n\n<script type=\"application/javascript\" src=\"../scripts/controller/role/NamespaceRoleController.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/namespace.html",
    "content": "<!doctype html>\n<html ng-app=\"namespace\">\n<head>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n    <link rel=\"icon\" href=\"./img/config.png\">\n    <!-- styles -->\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"vendor/bootstrap/css/bootstrap.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"vendor/angular/angular-toastr-1.4.1.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"vendor/select2/select2.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" media='all' href=\"vendor/angular/loading-bar.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"styles/common-style.css\">\n    <title>新建Namespace</title>\n</head>\n\n<body>\n\n<apollonav></apollonav>\n\n<div class=\"container-fluid apollo-container hidden\" ng-controller=\"LinkNamespaceController\">\n\n    <div class=\"row\">\n        <div class=\"col-md-8 col-md-offset-2\">\n            <div class=\"panel\">\n                <header class=\"panel-heading\">\n                    <div class=\"row\">\n                        <div class=\"col-md-6\">新建Namespace\n                        <small><a target=\"_blank\" href=\"https://github.com/ctripcorp/apollo/wiki/Apollo%E6%A0%B8%E5%BF%83%E6%A6%82%E5%BF%B5%E4%B9%8B%E2%80%9CNamespace%E2%80%9D\">\n                            (点击了解更多Namespace相关知识)\n                        </a> </small>\n                        </div>\n                        <div class=\"col-md-6 text-right\">\n                            <button type=\"button\" class=\"btn btn-info\" ng-click=\"back()\">返回到项目首页\n                            </button>\n                        </div>\n                    </div>\n\n                </header>\n\n                <div class=\"panel-body\">\n\n                    <div class=\"alert alert-info no-radius\">\n                        <strong>Tips:</strong>\n                        <ul ng-show=\"type == 'link'\">\n                            <li>应用可以通过关联公共namespace来覆盖公共Namespace的配置</li>\n                            <li>如果应用不需要覆盖公共Namespace的配置，那么无需关联公共Namespace</li>\n                        </ul>\n                        <ul ng-show=\"type == 'create' && appNamespace.isPublic\">\n                            <li>公共的Namespace的配置能被任何项目读取</li>\n                            <li>\n                                通过创建公共Namespace可以实现公共组件的配置，或多个应用共享同一份配置的需求\n                            </li>\n                            <li>如果其它应用需要覆盖公共部分的配置，可以在其它应用那里关联公共Namespace，然后在关联的Namespace里面配置需要覆盖的配置即可</li>\n                            <li>如果其它应用不需要覆盖公共部分的配置，那么就不需要在其它应用那里关联公共Namespace</li>\n                        </ul>\n                        <ul ng-show=\"type == 'create' && !appNamespace.isPublic\">\n                            <li>私有Namespace的配置只能被所属的应用获取到</li>\n                            <li>\n                                通过创建一个私有的Namespace可以实现分组管理配置\n                            </li>\n                            <li>私有Namespace的格式可以是xml、yml、yaml、json. 您可以通过Apollo-client中ConfigFile接口来获取非properties格式Namespace的内容</li>\n                        </ul>\n                    </div>\n                    <div class=\"row text-right\" style=\"padding-right: 20px;\">\n                        <div class=\"btn-group btn-group-sm\" role=\"group\" aria-label=\"...\">\n                            <button type=\"button\" class=\"btn btn-default\" ng-class=\"{active:type=='link'}\"\n                                    ng-click=\"switchType('link')\">关联公共Namespace\n                            </button>\n                            <button type=\"button\" class=\"btn btn-default\" ng-class=\"{active:type=='create'}\"\n                                    ng-click=\"switchType('create')\">创建Namespace\n                            </button>\n                        </div>\n                    </div>\n\n\n                    <form class=\"form-horizontal\" name=\"namespaceForm\" valdr-type=\"AppNamespace\"\n                          style=\"margin-top: 30px;\" ng-show=\"step == 1\" ng-submit=\"createNamespace()\">\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-3 control-label\">AppId</label>\n                            <div class=\"col-sm-6\" valdr-form-group>\n                                <label class=\"form-control-static\" ng-bind=\"appId\"></label>\n                            </div>\n                        </div>\n                        <div class=\"form-horizontal\" ng-show=\"type == 'link'\">\n                            <div class=\"form-group\">\n                                <label class=\"col-sm-3 control-label\">\n                                    <apollorequiredfield></apollorequiredfield>\n                                    选择集群</label>\n                                <div class=\"col-sm-6\" valdr-form-group>\n                                    <apolloclusterselector apollo-app-id=\"appId\" apollo-default-all-checked=\"true\"\n                                                           apollo-select=\"collectSelectedClusters\"></apolloclusterselector>\n                                </div>\n                            </div>\n                        </div>\n                        <div class=\"form-group\" ng-show=\"type == 'create'\">\n                            <label class=\"col-sm-3 control-label\">\n                                <apollorequiredfield></apollorequiredfield>\n                                名称</label>\n                            <div class=\"col-sm-4\" valdr-form-group>\n                                <div ng-class=\"{'input-group':appNamespace.isPublic}\">\n                                    <span class=\"input-group-addon\" ng-show=\"appNamespace.isPublic\"\n                                          ng-bind=\"appBaseInfo.namespacePrefix\"></span>\n                                    <input type=\"text\" name=\"namespaceName\" class=\"form-control\"\n                                           ng-model=\"appNamespace.name\">\n                                </div>\n                            </div>\n\n                            <!--public namespace can only be properties -->\n                            <div class=\"col-sm-2\" ng-show=\"!appNamespace.isPublic\">\n                                <select class=\"form-control\" name=\"format\" ng-model=\"appNamespace.format\">\n                                    <option value=\"properties\">properties</option>\n                                    <option value=\"xml\">xml</option>\n                                    <option value=\"json\">json</option>\n                                    <option value=\"yml\">yml</option>\n                                    <option value=\"yaml\">yaml</option>\n                                </select>\n                            </div>\n\n                            &nbsp;&nbsp;\n                            <span ng-show=\"appNamespace.isPublic\" ng-bind=\"concatNamespace()\"\n                                  style=\"line-height: 34px;\"></span>\n                        </div>\n                        <div class=\"form-group\" ng-show=\"type == 'create' && (pageSetting.canAppAdminCreatePrivateNamespace || hasRootPermission)\">\n                            <label class=\"col-sm-3 control-label\">\n                                <apollorequiredfield></apollorequiredfield>\n                                类型</label>\n                            <div class=\"col-sm-4\" valdr-form-group>\n                                <label class=\"radio-inline\">\n                                    <input type=\"radio\" name=\"namespaceType\" value=\"true\" ng-value=\"true\"\n                                           ng-model=\"appNamespace.isPublic\"> public\n                                </label>\n                                <label class=\"radio-inline\">\n                                    <input type=\"radio\" name=\"namespaceType\" value=\"false\" ng-value=\"false\"\n                                           ng-model=\"appNamespace.isPublic\"> private\n                                </label>\n                            </div>\n                        </div>\n                        <div class=\"form-group\" ng-show=\"type == 'create'\" valdr-form-group>\n                            <label class=\"col-sm-3 control-label\">备注</label>\n                            <div class=\"col-sm-7\" valdr-form-group>\n                                <textarea class=\"form-control\" rows=\"3\" name=\"comment\"\n                                          ng-model=\"appNamespace.comment\"></textarea>\n                            </div>\n                        </div>\n                        <div class=\"form-group\" ng-show=\"type == 'link'\">\n                            <label class=\"col-sm-3 control-label\">\n                                <apollorequiredfield></apollorequiredfield>\n                                namespace</label>\n                            <div class=\"col-sm-4\" valdr-form-group>\n                                <select id=\"namespaces\">\n                                    <option></option>\n                                </select>\n                            </div>\n                        </div>\n\n                        <div class=\"form-group\">\n                            <div class=\"col-sm-offset-3 col-sm-10\">\n                                <button type=\"submit\" class=\"btn btn-primary\"\n                                        ng-disabled=\"(type == 'create' && namespaceForm.$invalid) || submitBtnDisabled\">\n                                    提交\n                                </button>\n                            </div>\n                        </div>\n                    </form>\n\n                    <div class=\"row text-center\" ng-show=\"step == 2\">\n                        <img src=\"img/sync-succ.png\" style=\"height: 100px; width: 100px\">\n                        <h3>创建成功!</h3>\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>\n\n\n<div ng-include=\"'views/common/footer.html'\"></div>\n\n<!--angular-->\n<script src=\"vendor/angular/angular.min.js\"></script>\n<script src=\"vendor/angular/angular-resource.min.js\"></script>\n<script src=\"vendor/angular/angular-toastr-1.4.1.tpls.min.js\"></script>\n<script src=\"vendor/angular/loading-bar.min.js\"></script>\n\n<!-- jquery.js -->\n<script src=\"vendor/jquery.min.js\" type=\"text/javascript\"></script>\n\n<script src=\"vendor/select2/select2.min.js\" type=\"text/javascript\"></script>\n\n\n<!-- bootstrap.js -->\n<script src=\"vendor/bootstrap/js/bootstrap.min.js\" type=\"text/javascript\"></script>\n\n<script src=\"vendor/valdr/valdr.min.js\" type=\"text/javascript\"></script>\n<script src=\"vendor/valdr/valdr-message.min.js\" type=\"text/javascript\"></script>\n\n<script type=\"application/javascript\" src=\"scripts/app.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/AppService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/EnvService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/UserService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/CommonService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/NamespaceService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/PermissionService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/AppUtils.js\"></script>\n\n<!--directive-->\n<script type=\"application/javascript\" src=\"scripts/directive/directive.js\"></script>\n\n<script type=\"application/javascript\" src=\"scripts/controller/NamespaceController.js\"></script>\n\n<script src=\"scripts/valdr.js\" type=\"text/javascript\"></script>\n\n</body>\n</html>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/open/manage.html",
    "content": "<!doctype html>\n<html ng-app=\"open_manage\">\n<head>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n    <link rel=\"icon\" href=\"../img/config.png\">\n    <!-- styles -->\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"../vendor/bootstrap/css/bootstrap.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"../vendor/angular/angular-toastr-1.4.1.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" media='all' href=\"../vendor/angular/loading-bar.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"../styles/common-style.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"../vendor/select2/select2.min.css\">\n    <title>开放平台</title>\n</head>\n\n<body>\n\n<apollonav></apollonav>\n\n\n<div class=\"container-fluid\" ng-controller=\"OpenManageController\">\n    <div class=\"col-md-10 col-md-offset-1 panel\">\n\n        <section class=\"panel-body\" ng-show=\"isRootUser\">\n            <!--project admin-->\n            <section class=\"row\">\n                <h5>创建第三方应用\n                    <small>\n                        (说明: 第三方应用可以通过Apollo开放平台来对配置进行管理)\n                    </small>\n                </h5>\n                <hr>\n                <form class=\"form-horizontal\">\n                    <div class=\"form-group\" valdr-form-group>\n                        <label class=\"col-sm-2 control-label\">\n                            <apollorequiredfield></apollorequiredfield>\n                            第三方应用ID</label>\n                        <div class=\"col-sm-3\">\n                            <input type=\"text\" class=\"form-control\" ng-model=\"consumer.appId\">\n                            <small>(创建前请先查询第三方应用是否已经申请过)</small>\n                        </div>\n                        <div class=\"col-sm-1\">\n                            <button class=\"btn btn-info\" ng-click=\"getTokenByAppId()\">查询</button>\n                        </div>\n                        <div class=\"col-sm-6\">\n                            <h4 style=\"color: red\"\n                                ng-show=\"consumerToken\"\n                                ng-bind=\"'Token: ' + consumerToken.token\"></h4>\n                        </div>\n                    </div>\n                    <div class=\"form-group\">\n                        <label class=\"col-sm-2 control-label\">\n                            <apollorequiredfield></apollorequiredfield>\n                            部门</label>\n                        <div class=\"col-sm-3\">\n                            <select id=\"organization\">\n                                <option></option>\n                            </select>\n                        </div>\n                    </div>\n                    <div class=\"form-group\" valdr-form-group>\n                        <label class=\"col-sm-2 control-label\">\n                            <apollorequiredfield></apollorequiredfield>\n                            第三方应用名称</label>\n                        <div class=\"col-sm-3\">\n                            <input type=\"text\" class=\"form-control\" ng-model=\"consumer.name\">\n                            <small>(建议格式 xx-yy-zz 例:apollo-server)</small>\n                        </div>\n                    </div>\n                    <div class=\"form-group\">\n                        <label class=\"col-sm-2 control-label\">\n                            <apollorequiredfield></apollorequiredfield>\n                            项目负责人</label>\n                        <div class=\"col-sm-6 J_ownerSelectorPanel\">\n                            <apollouserselector apollo-id=\"'ownerSelector'\"></apollouserselector>\n                        </div>\n                    </div>\n\n                    <div class=\"form-group\">\n                        <div class=\"col-sm-offset-2 col-sm-9\">\n                            <button type=\"submit\" class=\"btn btn-primary\"\n                                    ng-disabled=\"submitBtnDisabled\"\n                                    ng-click=\"createConsumer()\">\n                                创建\n                            </button>\n                        </div>\n                    </div>\n                </form>\n            </section>\n\n            <section class=\"row\">\n                <h5>赋权\n                    <small>\n                        (Namespace级别权限包括: 修改、发布Namespace。应用级别权限包括: 创建Namespace、修改或发布应用下任何Namespace)\n                    </small>\n                </h5>\n                <hr>\n                <form class=\"form-horizontal\" ng-submit=\"assignRoleToConsumer()\">\n\n                    <div class=\"form-group\" valdr-form-group>\n                        <label class=\"col-sm-2 control-label\">\n                            <apollorequiredfield></apollorequiredfield>\n                            token</label>\n                        <div class=\"col-sm-5\">\n                            <input type=\"text\" class=\"form-control\" ng-model=\"consumerRole.token\" required>\n                        </div>\n                    </div>\n                    <div class=\"form-group\" valdr-form-group>\n                        <label class=\"col-sm-2 control-label\">\n                            <apollorequiredfield></apollorequiredfield>\n                            被管理的AppId</label>\n                        <div class=\"col-sm-3\">\n                            <input type=\"text\" class=\"form-control\" ng-model=\"consumerRole.appId\" required>\n                        </div>\n                    </div>\n                    <div class=\"form-group\" valdr-form-group>\n                        <label class=\"col-sm-2 control-label\">\n                            被管理的Namespace</label>\n                        <div class=\"col-sm-3\">\n                            <input type=\"text\" class=\"form-control\" ng-model=\"consumerRole.namespaceName\">\n                            <small>(非properties类型的namespace请加上类型后缀，例如apollo.xml)</small>\n                        </div>\n                    </div>\n                    <div class=\"form-group\" valdr-form-group>\n                        <label class=\"col-sm-2 control-label\">\n                            授权类型\n                        </label>\n                        <div class=\"col-sm-3\">\n                            <label class=\"radio-inline\">\n                                <input type=\"radio\" name=\"inlineRadioOptions\"  ng-value=\"'NamespaceRole'\" ng-model=\"consumerRole.type\">\n                                Namespace\n                            </label>\n                            <label class=\"radio-inline\">\n                                <input type=\"radio\" name=\"inlineRadioOptions\"  ng-value=\"'AppRole'\" ng-model=\"consumerRole.type\">\n                                App\n                            </label>\n                        </div>\n                    </div>\n                    <div class=\"form-group\">\n                        <div class=\"col-sm-offset-2 col-sm-9\">\n                            <button type=\"submit\" class=\"btn btn-primary\"\n                                    ng-disabled=\"submitBtnDisabled\">\n                                提交\n                            </button>\n                        </div>\n                    </div>\n                </form>\n\n            </section>\n\n        </section>\n\n        <section class=\"panel-body text-center\" ng-if=\"!isRootUser\">\n            <h4>当前页面只对Apollo管理员开放</h4>\n        </section>\n\n    </div>\n</div>\n\n<div ng-include=\"'../views/common/footer.html'\"></div>\n\n<!-- jquery.js -->\n<script src=\"../vendor/jquery.min.js\" type=\"text/javascript\"></script>\n\n<!--angular-->\n<script src=\"../vendor/angular/angular.min.js\"></script>\n<script src=\"../vendor/angular/angular-route.min.js\"></script>\n<script src=\"../vendor/angular/angular-resource.min.js\"></script>\n<script src=\"../vendor/angular/angular-toastr-1.4.1.tpls.min.js\"></script>\n<script src=\"../vendor/angular/loading-bar.min.js\"></script>\n\n<!--valdr-->\n<script src=\"../vendor/valdr/valdr.min.js\" type=\"text/javascript\"></script>\n<script src=\"../vendor/valdr/valdr-message.min.js\" type=\"text/javascript\"></script>\n\n<!-- bootstrap.js -->\n<script src=\"../vendor/bootstrap/js/bootstrap.min.js\" type=\"text/javascript\"></script>\n\n<!--nicescroll-->\n<script src=\"../vendor/jquery.nicescroll.min.js\"></script>\n<script src=\"../vendor/lodash.min.js\"></script>\n\n<script src=\"../vendor/select2/select2.min.js\" type=\"text/javascript\"></script>\n<!--biz-->\n<!--must import-->\n<script type=\"application/javascript\" src=\"../scripts/app.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/services/AppService.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/services/EnvService.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/services/UserService.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/services/CommonService.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/services/PermissionService.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/services/OrganizationService.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/services/ConsumerService.js\"></script>\n\n<script type=\"application/javascript\" src=\"../scripts/AppUtils.js\"></script>\n\n<script type=\"application/javascript\" src=\"../scripts/PageCommon.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/directive/directive.js\"></script>\n<script type=\"application/javascript\" src=\"../scripts/valdr.js\"></script>\n\n<script type=\"application/javascript\" src=\"../scripts/controller/open/OpenManageController.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/AppUtils.js",
    "content": "appUtil.service('AppUtil', ['toastr', '$window', '$q', function (toastr, $window, $q) {\n\n    function parseErrorMsg(response) {\n        if (response.status == -1) {\n            return \"您的登录信息已过期,请刷新页面后重试\";\n        }\n        var msg = \"Code:\" + response.status;\n        if (response.data.message != null) {\n            msg += \" Msg:\" + response.data.message;\n        }\n        return msg;\n    }\n\n    function ajax(resource, requestParams, requestBody) {\n        var d = $q.defer();\n        if (requestBody) {\n            resource(requestParams, requestBody, function (result) {\n                         d.resolve(result);\n                     },\n                     function (result) {\n                         d.reject(result);\n                     });\n        } else {\n            resource(requestParams, function (result) {\n                         d.resolve(result);\n                     },\n                     function (result) {\n                         d.reject(result);\n                     });\n        }\n\n        return d.promise;\n    }\n    \n    return {\n        errorMsg: parseErrorMsg,\n        ajax: ajax,\n        showErrorMsg: function (response, title) {\n            toastr.error(parseErrorMsg(response), title);\n        },\n        parseParams: function (query, notJumpToHomePage) {\n            if (!query) {\n                //如果不传这个参数或者false则返回到首页(参数出错)\n                if (!notJumpToHomePage) {\n                    $window.location.href = '/index.html';\n                } else {\n                    return {};\n                }\n            }\n            if (query.indexOf('/') == 0) {\n                query = query.substring(1, query.length);\n            }\n\n            var anchorIndex = query.indexOf('#');\n            if (anchorIndex >= 0) {\n                query = query.substring(0, anchorIndex);\n            }\n\n            var params = query.split(\"&\");\n            var result = {};\n            params.forEach(function (param) {\n                var kv = param.split(\"=\");\n                result[kv[0]] = decodeURIComponent(kv[1]);\n            });\n            return result;\n        },\n        collectData: function (response) {\n            var data = [];\n            response.entities.forEach(function (entity) {\n                if (entity.code == 200) {\n                    data.push(entity.body);\n                } else {\n                    toastr.warning(entity.message);\n                }\n            });\n            return data;\n        },\n        showModal: function (modal) {\n            $(modal).modal(\"show\");\n        },\n        hideModal: function (modal) {\n            $(modal).modal(\"hide\");\n        },\n        checkIPV4:function (ip) {\n            return /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$|^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\\-]*[a-zA-Z0-9])\\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\\-]*[A-Za-z0-9])$|^\\s*((([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}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?\\s*$/.test(ip);\n        }\n    }\n}]);\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/PageCommon.js",
    "content": "$(document).ready(function () {\n\n    // nicescroll\n    $(\"html\").niceScroll({\n                             styler: \"fb\",\n                             cursorcolor: \"#e8403f\",\n                             cursorwidth: '6',\n                             cursorborderradius: '10px',\n                             background: '#404040',\n                             spacebarenabled: false,\n                             cursorborder: '',\n                             zindex: '1000'\n                         });\n\n    // bootstrap tooltip & textarea scroll\n    setInterval(function () {\n        $('[data-tooltip=\"tooltip\"]').tooltip({\n                                                  trigger : 'hover'\n                                              });\n        $(\"textarea\").niceScroll({cursoropacitymax: 0});\n        $(\"pre\").niceScroll({cursoropacitymax: 0});\n    }, 1000);\n\n    setTimeout(function () {\n\n        $(\".release-history-list\").niceScroll({cursoropacitymax: 0});\n\n    }, 2500);\n});\n\n// (new Date()).Format(\"yyyy-MM-dd hh:mm:ss.S\") ==> 2006-07-02 08:09:04.423\n// (new Date()).Format(\"yyyy-M-d h:m:s.S\")      ==> 2006-7-2 8:9:4.18 \nDate.prototype.Format = function (fmt) {\n    var o = {\n        \"M+\": this.getMonth() + 1, //月份 \n        \"d+\": this.getDate(), //日 \n        \"h+\": this.getHours(), //小时 \n        \"m+\": this.getMinutes(), //分 \n        \"s+\": this.getSeconds(), //秒 \n        \"q+\": Math.floor((this.getMonth() + 3) / 3), //季度 \n        \"S\": this.getMilliseconds() //毫秒 \n    };\n    if (/(y+)/.test(fmt)) {\n        fmt = fmt.replace(RegExp.$1, (this.getFullYear() + \"\").substr(4 - RegExp.$1.length));\n    }\n    for (var k in o) {\n        if (new RegExp(\"(\" + k + \")\").test(fmt)) {\n            fmt =\n                fmt.replace(RegExp.$1,\n                            (RegExp.$1.length == 1) ? (o[k]) : ((\"00\" + o[k]).substr((\"\" + o[k]).length)));\n        }\n    }\n    return fmt;\n};\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/app.js",
    "content": "/**utils*/\nvar appUtil = angular.module('app.util', ['toastr']);\n\n/**service module 定义*/\nvar appService = angular.module('app.service', ['ngResource']);\n\n/** directive */\nvar directive_module = angular.module('apollo.directive', ['app.service', 'app.util', 'toastr']);\n\n/** page module 定义*/\n// 首页\nvar index_module = angular.module('index', ['toastr', 'app.service', 'apollo.directive', 'app.util', 'angular-loading-bar']);\n//项目主页\nvar application_module = angular.module('application', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar', 'valdr', 'ui.ace']);\n//创建项目页面\nvar app_module = angular.module('create_app', ['apollo.directive', 'toastr', 'app.service', 'app.util', 'angular-loading-bar', 'valdr']);\n//配置同步页面\nvar sync_item_module = angular.module('sync_item', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar']);\n//namespace\nvar namespace_module = angular.module('namespace', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar', 'valdr']);\n//server config\nvar server_config_module = angular.module('server_config', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar']);\n//setting\nvar setting_module = angular.module('setting', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar', 'valdr']);\n//role\nvar role_module = angular.module('role', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar']);\n//cluster\nvar cluster_module = angular.module('cluster', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar' , 'valdr']);\n//release history\nvar release_history_module = angular.module('release_history', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar']);\n//open manage\nvar open_manage_module = angular.module('open_manage', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar']);\n//user\nvar user_module = angular.module('user', ['apollo.directive', 'toastr', 'app.service', 'app.util', 'angular-loading-bar', 'valdr']);\n//login\nvar login_module = angular.module('login', ['toastr', 'app.util']);\n\n\n\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/controller/AppController.js",
    "content": "app_module.controller('CreateAppController',\n                      ['$scope', '$window', 'toastr', 'AppService', 'AppUtil', 'OrganizationService',\n                       createAppController]);\n\nfunction createAppController($scope, $window, toastr, AppService, AppUtil, OrganizationService) {\n\n    $scope.app = {};\n    $scope.submitBtnDisabled = false;\n\n    $scope.create = create;\n\n    init();\n\n    function init() {\n        initOrganization();\n    }\n\n    function initOrganization() {\n        OrganizationService.find_organizations().then(function (result) {\n            var organizations = [];\n            result.forEach(function (item) {\n                var org = {};\n                org.id = item.orgId;\n                org.text = item.orgName + '(' + item.orgId + ')';\n                org.name = item.orgName;\n                organizations.push(org);\n            });\n            $('#organization').select2({\n                                           placeholder: '请选择部门',\n                                           width: '100%',\n                                           data: organizations\n                                       });\n        }, function (result) {\n            toastr.error(AppUtil.errorMsg(result), \"load organizations error\");\n        });\n    }\n\n    function create() {\n        $scope.submitBtnDisabled = true;\n\n        var selectedOrg = $('#organization').select2('data')[0];\n\n        if (!selectedOrg.id) {\n            toastr.warning(\"请选择部门\");\n            return;\n        }\n\n        $scope.app.orgId = selectedOrg.id;\n        $scope.app.orgName = selectedOrg.name;\n\n        // owner\n        var owner = $('.ownerSelector').select2('data')[0];\n        if (!owner) {\n            toastr.warning(\"请选择应用负责人\");\n            return;\n        }\n        $scope.app.ownerName = owner.id;\n\n        //admins\n        $scope.app.admins = [];\n        var admins = $(\".adminSelector\").select2('data');\n        if (admins) {\n            admins.forEach(function (admin) {\n                $scope.app.admins.push(admin.id);\n            })\n        }\n\n        AppService.create($scope.app).then(function (result) {\n            toastr.success('创建成功!');\n            setInterval(function () {\n                $scope.submitBtnDisabled = false;\n                $window.location.href = '/config.html?#appid=' + result.appId;\n            }, 1000);\n        }, function (result) {\n            $scope.submitBtnDisabled = false;\n            toastr.error(AppUtil.errorMsg(result), '创建失败!');\n        });\n    }\n\n\n    $(\".J_ownerSelectorPanel\").on(\"select2:select\", \".ownerSelector\", selectEventHandler);\n    var $adminSelectorPanel = $(\".J_adminSelectorPanel\");\n    $adminSelectorPanel.on(\"select2:select\", \".adminSelector\", selectEventHandler);\n    $adminSelectorPanel.on(\"select2:unselect\", \".adminSelector\", selectEventHandler);\n\n    function selectEventHandler() {\n        $('.J_owner').remove();\n\n        var owner = $('.ownerSelector').select2('data')[0];\n\n        if (owner) {\n            $(\".adminSelector\").parent().find(\".select2-selection__rendered\").prepend(\n                '<li class=\"select2-selection__choice J_owner\">'\n                + owner.text + '</li>')\n        }\n    }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/controller/ClusterController.js",
    "content": "cluster_module.controller('ClusterController',\n                          ['$scope', '$location', '$window', 'toastr', 'AppService', 'EnvService', 'ClusterService',\n                           'AppUtil',\n                           function ($scope, $location, $window, toastr, AppService, EnvService, ClusterService,\n                                     AppUtil) {\n\n                               var params = AppUtil.parseParams($location.$$url);\n                               $scope.appId = params.appid;\n\n                               $scope.step = 1;\n                               \n                               $scope.submitBtnDisabled = false;\n                               \n                               EnvService.find_all_envs().then(function (result) {\n                                   $scope.envs = [];\n                                   result.forEach(function (env) {\n                                       $scope.envs.push({name: env, checked: false});\n\n                                   });\n                                   $(\".apollo-container\").removeClass(\"hidden\");\n                               }, function (result) {\n                                   toastr.error(AppUtil.errorMsg(result), \"加载环境信息出错\");\n                               });\n\n                               $scope.clusterName = '';\n\n                               $scope.switchChecked = function (env,  $event) {\n                                   env.checked = !env.checked;\n                                   $event.stopPropagation();\n                               };\n\n                               $scope.toggleEnvCheckedStatus = function (env) {\n                                   env.checked = !env.checked;\n                               };\n\n                               $scope.create = function () {\n\n                                   var noEnvChecked = true;\n                                   $scope.envs.forEach(function (env) {\n                                       if (env.checked) {\n                                           noEnvChecked = false;\n                                           $scope.submitBtnDisabled = true;\n                                           ClusterService.create_cluster($scope.appId, env.name,\n                                                                         {\n                                                                             name: $scope.clusterName,\n                                                                             appId: $scope.appId\n                                                                         }).then(function (result) {\n                                               toastr.success(env.name, \"集群创建成功\");\n                                               $scope.step = 2;\n                                               $scope.submitBtnDisabled = false;\n                                           }, function (result) {\n                                               toastr.error(AppUtil.errorMsg(result), \"集群创建失败\");\n                                               $scope.submitBtnDisabled = false;\n                                           })\n                                       }\n                                   });\n\n                                   if (noEnvChecked){\n                                       toastr.warning(\"请选择环境\");\n                                   }\n\n                               };\n\n                           }]);\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/controller/IndexController.js",
    "content": "index_module.controller('IndexController', ['$scope', '$window', 'toastr', 'AppUtil', 'AppService',\n                                            'UserService', 'FavoriteService',\n                                            IndexController]);\n\nfunction IndexController($scope, $window, toastr, AppUtil, AppService, UserService, FavoriteService) {\n\n    $scope.userId = '';\n\n    $scope.getUserCreatedApps = getUserCreatedApps;\n    $scope.getUserFavorites = getUserFavorites;\n\n    $scope.goToAppHomePage = goToAppHomePage;\n    $scope.goToCreateAppPage = goToCreateAppPage;\n    $scope.toggleOperationBtn = toggleOperationBtn;\n    $scope.toTop = toTop;\n    $scope.deleteFavorite = deleteFavorite;\n\n    UserService.load_user().then(function (result) {\n        $scope.userId = result.userId;\n\n        $scope.createdAppPage = 0;\n        $scope.createdApps = [];\n        $scope.hasMoreCreatedApps = true;\n        $scope.favoritesPage = 0;\n        $scope.favorites = [];\n        $scope.hasMoreFavorites = true;\n        $scope.visitedApps = [];\n\n        getUserCreatedApps();\n\n        getUserFavorites();\n\n        initUserVisitedApps();\n    });\n\n    function getUserCreatedApps() {\n        var size = 10;\n        AppService.find_app_by_owner($scope.userId, $scope.createdAppPage, size)\n            .then(function (result) {\n                $scope.createdAppPage += 1;\n                $scope.hasMoreCreatedApps = result.length == size;\n\n                if (!result || result.length == 0) {\n                    return;\n                }\n                result.forEach(function (app) {\n                    $scope.createdApps.push(app);\n                });\n\n            })\n    }\n\n    function getUserFavorites() {\n        var size = 11;\n        FavoriteService.findFavorites($scope.userId, '', $scope.favoritesPage, size)\n            .then(function (result) {\n                $scope.favoritesPage += 1;\n                $scope.hasMoreFavorites = result.length == size;\n\n                if ($scope.favoritesPage == 1){\n                    $(\"#app-list\").removeClass(\"hidden\");\n                }\n\n                if (!result || result.length == 0) {\n                    return;\n                }\n                var appIds = [];\n                result.forEach(function (favorite) {\n                    appIds.push(favorite.appId);\n                });\n\n\n                AppService.find_apps(appIds.join(\",\"))\n                    .then(function (apps) {\n                        //sort\n                        var appIdMapApp = {};\n                        apps.forEach(function (app) {\n                            appIdMapApp[app.appId] = app;\n                        });\n                        result.forEach(function (favorite) {\n                            var app = appIdMapApp[favorite.appId];\n                            if (!app){\n                                return;\n                            }\n                            app.favoriteId = favorite.id;\n                            $scope.favorites.push(app);\n                        });\n\n                    });\n            })\n    }\n\n    function initUserVisitedApps() {\n        var VISITED_APPS_STORAGE_KEY = \"VisitedAppsV2\";\n        var visitedAppsObject = JSON.parse(localStorage.getItem(VISITED_APPS_STORAGE_KEY));\n        if (!visitedAppsObject) {\n            visitedAppsObject = {};\n        }\n\n        var userVisitedApps = visitedAppsObject[$scope.userId];\n        if (userVisitedApps && userVisitedApps.length > 0) {\n            AppService.find_apps(userVisitedApps.join(\",\"))\n                .then(function (apps) {\n                    //sort\n                    var appIdMapApp = {};\n                    apps.forEach(function (app) {\n                        appIdMapApp[app.appId] = app;\n                    });\n\n                    userVisitedApps.forEach(function (appId) {\n                        var app = appIdMapApp[appId];\n                        if (app){\n                            $scope.visitedApps.push(app);\n                        }\n                    });\n                });\n        }\n\n    }\n\n    function goToCreateAppPage() {\n        $window.location.href = \"/app.html\";\n    }\n\n    function goToAppHomePage(appId) {\n        $window.location.href = \"/config.html?#/appid=\" + appId;\n    }\n\n    function toggleOperationBtn(app) {\n        app.showOperationBtn = !app.showOperationBtn;\n    }\n\n    function toTop(favoriteId) {\n        FavoriteService.toTop(favoriteId).then(function () {\n            toastr.success(\"置顶成功\");\n            refreshFavorites();\n\n        })\n    }\n\n    function deleteFavorite(favoriteId) {\n        FavoriteService.deleteFavorite(favoriteId).then(function () {\n            toastr.success(\"取消收藏成功\");\n            refreshFavorites();\n        })\n    }\n\n    function refreshFavorites() {\n        $scope.favoritesPage = 0;\n        $scope.favorites = [];\n        $scope.hasMoreFavorites = true;\n\n        getUserFavorites();\n    }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/controller/LoginController.js",
    "content": "login_module.controller('LoginController',\n                       ['$scope', '$window', '$location', 'toastr', 'AppUtil',\n                        LoginController]);\n\nfunction LoginController($scope, $window, $location, toastr, AppUtil) {\n    if ($location.$$url) {\n        var params = AppUtil.parseParams($location.$$url);\n        if (params.error) {\n            $scope.info = \"用户名或密码错误\";\n        }\n        if (params.logout) {\n            $scope.info = \"登出成功\";\n        }\n    }\n\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/controller/NamespaceController.js",
    "content": "namespace_module.controller(\"LinkNamespaceController\",\n                            ['$scope', '$location', '$window', 'toastr', 'AppService', 'AppUtil', 'NamespaceService',\n                             'PermissionService', 'CommonService',\n                             function ($scope, $location, $window, toastr, AppService, AppUtil, NamespaceService,\n                                       PermissionService, CommonService) {\n\n                                 var params = AppUtil.parseParams($location.$$url);\n                                 $scope.appId = params.appid;\n                                 $scope.type = 'link';\n\n                                 $scope.step = 1;\n\n                                 $scope.submitBtnDisabled = false;\n\n                                 PermissionService.has_root_permission().then(function (result) {\n                                     $scope.hasRootPermission = result.hasPermission;\n                                 });\n\n                                 CommonService.getPageSetting().then(function (setting) {\n                                    $scope.pageSetting = setting;\n                                 });\n\n                                 NamespaceService.find_public_namespaces().then(function (result) {\n                                     var publicNamespaces = [];\n                                     result.forEach(function (item) {\n                                         var namespace = {};\n                                         namespace.id = item.name;\n                                         namespace.text = item.name;\n                                         publicNamespaces.push(namespace);\n                                     });\n                                     $('#namespaces').select2({\n                                                                  placeholder: '请选择Namespace',\n                                                                  width: '100%',\n                                                                  data: publicNamespaces\n                                                              });\n                                     $(\".apollo-container\").removeClass(\"hidden\");\n                                 }, function (result) {\n                                     toastr.error(AppUtil.errorMsg(result), \"load public namespace error\");\n                                 });\n\n                                 AppService.load($scope.appId).then(function (result) {\n                                     $scope.appBaseInfo = result;\n                                     $scope.appBaseInfo.namespacePrefix = result.orgId + '.';\n                                 }, function (result) {\n                                     toastr.error(AppUtil.errorMsg(result), \"加载App信息出错\");\n                                 });\n\n                                 $scope.appNamespace = {\n                                     appId: $scope.appId,\n                                     name: '',\n                                     comment: '',\n                                     isPublic: true,\n                                     format: 'properties'\n                                 };\n\n                                 $scope.switchNSType = function (type) {\n                                     $scope.appNamespace.isPublic = type;\n                                 };\n\n                                 $scope.concatNamespace = function () {\n                                     if (!$scope.appBaseInfo) {\n                                         return '';\n                                     }\n                                     return $scope.appBaseInfo.namespacePrefix +\n                                            ($scope.appNamespace.name ? $scope.appNamespace.name : '');\n                                 };\n\n                                 var selectedClusters = [];\n                                 $scope.collectSelectedClusters = function (data) {\n                                     selectedClusters = data;\n                                 };\n                                 $scope.createNamespace = function () {\n                                     if ($scope.type == 'link') {\n                                         if (selectedClusters.length == 0) {\n                                             toastr.warning(\"请选择集群\");\n                                             return;\n                                         }\n\n                                         if ($scope.namespaceType == 1) {\n                                             var selectedNamespaceName = $('#namespaces').select2('data')[0].id;\n                                             if (!selectedNamespaceName) {\n                                                 toastr.warning(\"请选择Namespace\");\n                                                 return;\n                                             }\n\n                                             $scope.namespaceName = selectedNamespaceName;\n                                         }\n\n                                         var namespaceCreationModels = [];\n                                         selectedClusters.forEach(function (cluster) {\n                                             namespaceCreationModels.push({\n                                                                              env: cluster.env,\n                                                                              namespace: {\n                                                                                  appId: $scope.appId,\n                                                                                  clusterName: cluster.clusterName,\n                                                                                  namespaceName: $scope.namespaceName\n                                                                              }\n                                                                          });\n                                         });\n\n                                         $scope.submitBtnDisabled = true;\n                                         NamespaceService.createNamespace($scope.appId, namespaceCreationModels)\n                                             .then(function (result) {\n                                                 toastr.success(\"创建成功\");\n                                                 $scope.step = 2;\n                                                 setInterval(function () {\n                                                     $scope.submitBtnDisabled = false;\n                                                     $window.location.href =\n                                                         '/namespace/role.html?#appid=' + $scope.appId\n                                                         + \"&namespaceName=\" + $scope.namespaceName;\n                                                 }, 1000);\n                                             }, function (result) {\n                                                 $scope.submitBtnDisabled = false;\n                                                 toastr.error(AppUtil.errorMsg(result));\n                                             });\n                                     } else {\n\n                                         var namespaceNameLength = $scope.concatNamespace().length;\n                                         if (namespaceNameLength > 32) {\n                                             toastr.error(\"namespace名称不能大于32个字符. 部门前缀\"\n                                                          + (namespaceNameLength - $scope.appNamespace.name.length)\n                                                          + \"个字符, 名称\" + $scope.appNamespace.name.length + \"个字符\"\n                                             );\n                                             return;\n                                         }\n\n                                         $scope.submitBtnDisabled = true;\n                                         NamespaceService.createAppNamespace($scope.appId, $scope.appNamespace).then(\n                                             function (result) {\n                                                 $scope.step = 2;\n                                                 setTimeout(function () {\n                                                     $scope.submitBtnDisabled = false;\n                                                     $window.location.href =\n                                                         \"/namespace/role.html?#/appid=\" + $scope.appId\n                                                         + \"&namespaceName=\" + result.name;\n                                                 }, 1000);\n                                             }, function (result) {\n                                                 $scope.submitBtnDisabled = false;\n                                                 toastr.error(AppUtil.errorMsg(result), \"创建失败\");\n                                             });\n                                     }\n\n                                 };\n\n                                 $scope.namespaceType = 1;\n                                 $scope.selectNamespaceType = function (type) {\n                                     $scope.namespaceType = type;\n                                 };\n\n                                 $scope.back = function () {\n                                     $window.location.href = '/config.html?#appid=' + $scope.appId;\n                                 };\n\n                                 $scope.switchType = function (type) {\n                                     $scope.type = type;\n                                 };\n                             }]);\n\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/controller/ServerConfigController.js",
    "content": "server_config_module.controller('ServerConfigController',\n                                ['$scope', '$window', 'toastr', 'ServerConfigService', 'AppUtil',\n                                 function ($scope, $window, toastr, ServerConfigService, AppUtil) {\n\n                                     $scope.serverConfig = {};\n\n                                     $scope.create = function () {\n                                         ServerConfigService.create($scope.serverConfig).then(function (result) {\n                                             toastr.success(\"添加成功\");\n                                         }, function (result) {\n                                             toastr.error(AppUtil.errorMsg(result), \"添加失败\");\n                                         });\n                                     };\n\n                                 }]);\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/controller/SettingController.js",
    "content": "setting_module.controller('SettingController',\n                          ['$scope', '$location', 'toastr',\n                           'AppService', 'AppUtil', 'PermissionService',\n                           'OrganizationService',\n                           SettingController]);\n\nfunction SettingController($scope, $location, toastr,\n                           AppService, AppUtil, PermissionService,\n                           OrganizationService) {\n\n    var params = AppUtil.parseParams($location.$$url);\n    var $orgWidget = $('#organization');\n\n    $scope.pageContext = {\n        appId: params.appid\n    };\n    $scope.display = {\n        app: {\n            edit: false\n        }\n    };\n\n    $scope.submitBtnDisabled = false;\n    $scope.userSelectWidgetId = 'toAssignMasterRoleUser';\n\n    $scope.assignMasterRoleToUser = assignMasterRoleToUser;\n    $scope.removeMasterRoleFromUser = removeMasterRoleFromUser;\n    $scope.toggleEditStatus = toggleEditStatus;\n    $scope.updateAppInfo = updateAppInfo;\n\n    init();\n\n    function init() {\n        initOrganization();\n        initPermission();\n        initAdmins();\n        initApplication();\n\n    }\n\n    function initOrganization() {\n        OrganizationService.find_organizations().then(function (result) {\n            var organizations = [];\n            result.forEach(function (item) {\n                var org = {};\n                org.id = item.orgId;\n                org.text = item.orgName + '(' + item.orgId + ')';\n                org.name = item.orgName;\n                organizations.push(org);\n            });\n            $orgWidget.select2({\n                                   placeholder: '请选择部门',\n                                   width: '100%',\n                                   data: organizations\n                               });\n        }, function (result) {\n            toastr.error(AppUtil.errorMsg(result), \"load organizations error\");\n        });\n    }\n\n    function initPermission() {\n        PermissionService.has_assign_user_permission($scope.pageContext.appId)\n            .then(function (result) {\n                $scope.hasAssignUserPermission = result.hasPermission;\n            });\n    }\n\n    function initAdmins() {\n        PermissionService.get_app_role_users($scope.pageContext.appId)\n            .then(function (result) {\n                $scope.appRoleUsers = result;\n                $scope.admins = [];\n                $scope.appRoleUsers.masterUsers.forEach(function (user) {\n                    $scope.admins.push(user.userId);\n                });\n\n            });\n    }\n\n    function initApplication() {\n        AppService.load($scope.pageContext.appId).then(function (app) {\n            $scope.app = app;\n            $scope.viewApp = _.clone(app);\n            initAppForm(app);\n            $('.project-setting .panel').removeClass('hidden');\n        })\n\n    }\n\n    function initAppForm(app) {\n        $orgWidget.val(app.orgId).trigger(\"change\");\n\n        var $ownerSelector = $('.ownerSelector');\n        var defaultSelectedDOM = '<option value=\"' + app.ownerName + '\" selected=\"selected\">' + app.ownerName\n                                 + '</option>';\n        $ownerSelector.append(defaultSelectedDOM);\n        $ownerSelector.trigger('change');\n    }\n\n    function assignMasterRoleToUser() {\n        var user = $('.' + $scope.userSelectWidgetId).select2('data')[0];\n        if (!user) {\n            toastr.warning(\"请选择用户\");\n            return;\n        }\n        var toAssignMasterRoleUser = user.id;\n        $scope.submitBtnDisabled = true;\n        PermissionService.assign_master_role($scope.pageContext.appId,\n                                             toAssignMasterRoleUser)\n            .then(function (result) {\n                $scope.submitBtnDisabled = false;\n                toastr.success(\"添加成功\");\n                $scope.appRoleUsers.masterUsers.push({userId: toAssignMasterRoleUser});\n                $('.' + $scope.userSelectWidgetId).select2(\"val\", \"\");\n            }, function (result) {\n                $scope.submitBtnDisabled = false;\n                toastr.error(AppUtil.errorMsg(result), \"添加失败\");\n            });\n    }\n\n    function removeMasterRoleFromUser(user) {\n        if ($scope.appRoleUsers.masterUsers.length <= 1) {\n            $('#warning').modal('show');\n            return;\n        }\n        PermissionService.remove_master_role($scope.pageContext.appId, user)\n            .then(function (result) {\n                toastr.success(\"删除成功\");\n                removeUserFromList($scope.appRoleUsers.masterUsers, user);\n            }, function (result) {\n                toastr.error(AppUtil.errorMsg(result), \"删除失败\");\n            });\n    }\n\n    function removeUserFromList(list, user) {\n        var index = 0;\n        for (var i = 0; i < list.length; i++) {\n            if (list[i].userId == user) {\n                index = i;\n                break;\n            }\n        }\n        list.splice(index, 1);\n    }\n\n    function toggleEditStatus() {\n        if ($scope.display.app.edit) {//cancel edit\n            $scope.viewApp = _.clone($scope.app);\n            initAppForm($scope.viewApp);\n        } else {//edit\n\n        }\n\n        $scope.display.app.edit = !$scope.display.app.edit;\n\n    }\n\n    function updateAppInfo() {\n        $scope.submitBtnDisabled = true;\n        var app = $scope.viewApp;\n\n        var selectedOrg = $orgWidget.select2('data')[0];\n\n        if (!selectedOrg.id) {\n            toastr.warning(\"请选择部门\");\n            return;\n        }\n\n        app.orgId = selectedOrg.id;\n        app.orgName = selectedOrg.name;\n\n        // owner\n        var owner = $('.ownerSelector').select2('data')[0];\n        if (!owner) {\n            toastr.warning(\"请选择应用负责人\");\n            return;\n        }\n        app.ownerName = owner.id;\n\n        AppService.update(app).then(function (app) {\n            toastr.success(\"修改成功\");\n            initApplication();\n            $scope.display.app.edit = false;\n            $scope.submitBtnDisabled = false;\n        }, function (result) {\n            AppUtil.showErrorMsg(result);\n            $scope.submitBtnDisabled = false;\n        })\n\n    }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/controller/UserController.js",
    "content": "user_module.controller('UserController',\n                      ['$scope', '$window', 'toastr', 'AppUtil', 'UserService',\n                       UserController]);\n\nfunction UserController($scope, $window, toastr, AppUtil, UserService) {\n\n    $scope.user = {};\n    \n    $scope.createOrUpdateUser = function () {\n        UserService.createOrUpdateUser($scope.user).then(function (result) {\n            toastr.success(\"创建用户成功\");\n        }, function (result) {\n            AppUtil.showErrorMsg(result, \"创建用户失败\");\n        })\n\n    }\n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/controller/config/ConfigBaseInfoController.js",
    "content": "application_module.controller(\"ConfigBaseInfoController\",\n                              ['$rootScope', '$scope', '$window', '$location', 'toastr', 'EventManager', 'UserService',\n                               'AppService',\n                               'FavoriteService',\n                               'PermissionService',\n                               'AppUtil', ConfigBaseInfoController]);\n\nfunction ConfigBaseInfoController($rootScope, $scope, $window, $location, toastr, EventManager, UserService, AppService,\n                                  FavoriteService,\n                                  PermissionService,\n                                  AppUtil) {\n\n    var urlParams = AppUtil.parseParams($location.$$url);\n    var appId = urlParams.appid;\n\n    if (!appId) {\n        $window.location.href = '/index.html';\n        return;\n    }\n\n    initPage();\n\n    function initPage() {\n        $rootScope.hideTip = JSON.parse(localStorage.getItem(\"hideTip\"));\n\n        //load session storage to recovery scene\n        var scene = JSON.parse(sessionStorage.getItem(appId));\n\n        $rootScope.pageContext = {\n            appId: appId,\n            env: urlParams.env ? urlParams.env : (scene ? scene.env : ''),\n            clusterName: urlParams.cluster ? urlParams.cluster : (scene ? scene.cluster : 'default')\n        };\n\n        //storage page context to session storage\n        sessionStorage.setItem(\n            $rootScope.pageContext.appId,\n            JSON.stringify({\n                               env: $rootScope.pageContext.env,\n                               cluster: $rootScope.pageContext.clusterName\n                           }));\n\n        UserService.load_user().then(function (result) {\n            $rootScope.pageContext.userId = result.userId;\n            loadAppInfo();\n            handleFavorite();\n        }, function (result) {\n            toastr.error(AppUtil.errorMsg(result), \"获取用户登录信息失败\");\n        });\n\n        handlePermission();\n    }\n\n    function loadAppInfo() {\n\n        $scope.notFoundApp = true;\n        AppService.load($rootScope.pageContext.appId).then(function (result) {\n            $scope.notFoundApp = false;\n\n            $scope.appBaseInfo = result;\n            $scope.appBaseInfo.orgInfo = result.orgName + '(' + result.orgId + ')';\n\n            loadNavTree();\n            recordVisitApp();\n            findMissEnvs();\n\n            $(\".J_appFound\").removeClass(\"hidden\");\n        }, function (result) {\n            $(\".J_appNotFound\").removeClass(\"hidden\");\n        });\n    }\n\n    $scope.createAppInMissEnv = function () {\n        var count = 0;\n        $scope.missEnvs.forEach(function (env) {\n            AppService.create_remote(env, $scope.appBaseInfo).then(function (result) {\n                toastr.success(env, '创建成功');\n                count++;\n                if (count == $scope.missEnvs.length) {\n                    location.reload(true);\n                }\n            }, function (result) {\n                toastr.error(AppUtil.errorMsg(result), '创建失败:' + env);\n                count++;\n                if (count == $scope.missEnvs.length) {\n                    location.reload(true);\n                }\n            });\n        });\n    };\n\n    function findMissEnvs() {\n        $scope.missEnvs = [];\n        AppService.find_miss_envs($rootScope.pageContext.appId).then(function (result) {\n            $scope.missEnvs = AppUtil.collectData(result);\n        });\n\n    }\n    function recordVisitApp() {\n        //save user recent visited apps\n        var VISITED_APPS_STORAGE_KEY = \"VisitedAppsV2\";\n        var visitedAppsObject = JSON.parse(localStorage.getItem(VISITED_APPS_STORAGE_KEY));\n        var hasSaved = false;\n\n        if (!visitedAppsObject) {\n            visitedAppsObject = {};\n        }\n\n        if (!visitedAppsObject[$rootScope.pageContext.userId]) {\n            visitedAppsObject[$rootScope.pageContext.userId] = [];\n        }\n\n        var visitedApps = visitedAppsObject[$rootScope.pageContext.userId];\n        if (visitedApps && visitedApps.length > 0) {\n            visitedApps.forEach(function (app) {\n                if (app == appId) {\n                    hasSaved = true;\n                    return;\n                }\n            });\n        }\n\n        var currentUserVisitedApps = visitedAppsObject[$rootScope.pageContext.userId];\n        if (!hasSaved) {\n            //if queue's length bigger than 6 will remove oldest app\n            if (currentUserVisitedApps.length >= 6) {\n                currentUserVisitedApps.splice(0, 1);\n            }\n            currentUserVisitedApps.push($rootScope.pageContext.appId);\n\n            localStorage.setItem(VISITED_APPS_STORAGE_KEY,\n                                 JSON.stringify(visitedAppsObject));\n        }\n\n    }\n\n    function loadNavTree() {\n\n        AppService.load_nav_tree($rootScope.pageContext.appId).then(function (result) {\n            var navTree = [];\n            var nodes = AppUtil.collectData(result);\n\n            if (!nodes || nodes.length == 0) {\n                toastr.error(\"系统出错,请重试或联系系统负责人\");\n                return;\n            }\n            //default first env if session storage is empty\n            if (!$rootScope.pageContext.env) {\n                $rootScope.pageContext.env = nodes[0].env;\n            }\n\n            EventManager.emit(EventManager.EventType.REFRESH_NAMESPACE);\n\n            nodes.forEach(function (env) {\n                if (!env.clusters || env.clusters.length == 0) {\n                    return;\n                }\n                var node = {};\n                node.text = env.env;\n\n                var clusterNodes = [];\n\n                //如果env下面只有一个default集群则不显示集群列表\n                if (env.clusters && env.clusters.length == 1 && env.clusters[0].name\n                                                                == 'default') {\n                    if ($rootScope.pageContext.env == env.env) {\n                        node.state = {};\n                        node.state.selected = true;\n                    }\n                    node.selectable = true;\n\n                } else {\n                    node.selectable = false;\n                    //cluster list\n                    env.clusters.forEach(function (cluster) {\n                        var clusterNode = {},\n                            parentNode = [];\n\n                        //default selection from session storage or first env & first cluster\n                        if ($rootScope.pageContext.env == env.env && $rootScope.pageContext.clusterName\n                                                                     == cluster.name) {\n                            clusterNode.state = {};\n                            clusterNode.state.selected = true;\n                        }\n\n                        clusterNode.text = cluster.name;\n                        parentNode.push(node.text);\n                        clusterNode.tags = ['集群'];\n                        clusterNode.parentNode = parentNode;\n                        clusterNodes.push(clusterNode);\n\n                    });\n                }\n                node.nodes = clusterNodes;\n                navTree.push(node);\n            });\n\n            //init treeview\n            $('#treeview').treeview({\n                                        color: \"#797979\",\n                                        showBorder: true,\n                                        data: navTree,\n                                        levels: 99,\n                                        expandIcon: '',\n                                        collapseIcon: '',\n                                        showTags: true,\n                                        onNodeSelected: function (event, data) {\n                                            if (!data.parentNode) {//first nav node\n                                                $rootScope.pageContext.env = data.text;\n                                                $rootScope.pageContext.clusterName =\n                                                    'default';\n                                            } else {//second cluster node\n                                                $rootScope.pageContext.env =\n                                                    data.parentNode[0];\n                                                $rootScope.pageContext.clusterName =\n                                                    data.text;\n                                            }\n                                            //storage scene\n                                            sessionStorage.setItem(\n                                                $rootScope.pageContext.appId,\n                                                JSON.stringify({\n                                                                   env: $rootScope.pageContext.env,\n                                                                   cluster: $rootScope.pageContext.clusterName\n                                                               }));\n\n                                            $window.location.href = \"/config.html#/appid=\"\n                                                                    + $rootScope.pageContext.appId\n                                                                    + \"&env=\" + $rootScope.pageContext.env\n                                                                    + \"&cluster=\" + $rootScope.pageContext.clusterName;\n\n                                            EventManager.emit(EventManager.EventType.REFRESH_NAMESPACE);\n                                            $rootScope.showSideBar = false;\n                                        }\n                                    });\n\n            var envMapClusters = {};\n            navTree.forEach(function (node) {\n                if (node.nodes && node.nodes.length > 0) {\n\n                    var clusterNames = [];\n                    node.nodes.forEach(function (cluster) {\n                        if (cluster.text != 'default') {\n                            clusterNames.push(cluster.text);\n                        }\n\n                    });\n\n                    envMapClusters[node.text] = clusterNames.join(\",\");\n\n                }\n            });\n\n            $rootScope.envMapClusters = envMapClusters;\n\n        }, function (result) {\n            toastr.error(AppUtil.errorMsg(result), \"系统出错,请重试或联系系统负责人\");\n        });\n\n    }\n\n    function handleFavorite() {\n\n        FavoriteService.findFavorites($rootScope.pageContext.userId,\n                                      $rootScope.pageContext.appId)\n            .then(function (result) {\n                if (result && result.length) {\n                    $scope.favoriteId = result[0].id;\n                }\n\n            });\n\n        $scope.addFavorite = function () {\n            var favorite = {\n                userId: $rootScope.pageContext.userId,\n                appId: $rootScope.pageContext.appId\n            };\n\n            FavoriteService.addFavorite(favorite)\n                .then(function (result) {\n                    $scope.favoriteId = result.id;\n                    toastr.success(\"收藏成功\");\n                }, function (result) {\n                    toastr.error(AppUtil.errorMsg(result), \"收藏失败\");\n                })\n        };\n\n        $scope.deleteFavorite = function () {\n            FavoriteService.deleteFavorite($scope.favoriteId)\n                .then(function (result) {\n                    $scope.favoriteId = 0;\n                    toastr.success(\"取消收藏成功\");\n                }, function (result) {\n                    toastr.error(AppUtil.errorMsg(result), \"取消收藏失败\");\n                })\n        };\n    }\n\n    function handlePermission() {\n        //permission\n        PermissionService.has_create_namespace_permission(appId).then(function (result) {\n            $scope.hasCreateNamespacePermission = result.hasPermission;\n        }, function (result) {\n\n        });\n\n        PermissionService.has_create_cluster_permission(appId).then(function (result) {\n            $scope.hasCreateClusterPermission = result.hasPermission;\n        }, function (result) {\n\n        });\n\n        PermissionService.has_assign_user_permission(appId).then(function (result) {\n            $scope.hasAssignUserPermission = result.hasPermission;\n        }, function (result) {\n\n        });\n\n        $scope.showMasterPermissionTips = function () {\n            $(\"#masterNoPermissionDialog\").modal('show');\n        };\n    }\n\n    var VIEW_MODE_SWITCH_WIDTH = 1156;\n    if (window.innerWidth <= VIEW_MODE_SWITCH_WIDTH) {\n        $rootScope.viewMode = 2;\n        $rootScope.showSideBar = false;\n    } else {\n        $rootScope.viewMode = 1;\n    }\n\n    $rootScope.adaptScreenSize = function () {\n        if (window.innerWidth <= VIEW_MODE_SWITCH_WIDTH) {\n            $rootScope.viewMode = 2;\n        } else {\n            $rootScope.viewMode = 1;\n            $rootScope.showSideBar = false;\n        }\n\n    };\n\n    $(window).resize(function () {\n        $scope.$apply(function () {\n            $rootScope.adaptScreenSize();\n        });\n    });\n\n}\n\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/controller/config/ConfigNamespaceController.js",
    "content": "application_module.controller(\"ConfigNamespaceController\",\n                              ['$rootScope', '$scope', 'toastr', 'AppUtil', 'EventManager', 'ConfigService',\n                               'PermissionService', 'UserService', 'NamespaceBranchService', 'NamespaceService',\n                               controller]);\n\nfunction controller($rootScope, $scope, toastr, AppUtil, EventManager, ConfigService,\n                    PermissionService, UserService, NamespaceBranchService, NamespaceService) {\n\n    $scope.rollback = rollback;\n    $scope.preDeleteItem = preDeleteItem;\n    $scope.deleteItem = deleteItem;\n    $scope.editItem = editItem;\n    $scope.createItem = createItem;\n    $scope.closeTip = closeTip;\n    $scope.showText = showText;\n    $scope.createBranch = createBranch;\n    $scope.preCreateBranch = preCreateBranch;\n    $scope.preDeleteBranch = preDeleteBranch;\n    $scope.deleteBranch = deleteBranch;\n    $scope.showNoModifyPermissionDialog = showNoModifyPermissionDialog;\n    $scope.lockCheck = lockCheck;\n    $scope.emergencyPublish = emergencyPublish;\n\n    init();\n\n    function init() {\n\n        initRole();\n        initUser();\n        initPublishInfo();\n    }\n\n    function initRole() {\n        PermissionService.get_app_role_users($rootScope.pageContext.appId)\n            .then(function (result) {\n                var masterUsers = '';\n                result.masterUsers.forEach(function (user) {\n                    masterUsers += user.userId + ',';\n                });\n                $scope.masterUsers = masterUsers.substring(0, masterUsers.length - 1);\n            }, function (result) {\n\n            });\n    }\n\n    function initUser() {\n        UserService.load_user().then(function (result) {\n            $scope.currentUser = result.userId;\n        });\n\n    }\n\n    function initPublishInfo() {\n        NamespaceService.getNamespacePublishInfo($rootScope.pageContext.appId)\n            .then(function (result) {\n                if (!result) {\n                    return;\n                }\n                $scope.hasNotPublishNamespace = false;\n                var namespacePublishInfo = [];\n\n                Object.keys(result).forEach(function (env) {\n                    if (env.indexOf(\"$\") >= 0) {\n                        return;\n                    }\n\n                    var envPublishInfo = result[env];\n                    Object.keys(envPublishInfo).forEach(function (cluster) {\n\n                        var clusterPublishInfo = envPublishInfo[cluster];\n                        if (clusterPublishInfo) {\n                            $scope.hasNotPublishNamespace = true;\n\n                            if (Object.keys(envPublishInfo).length > 1) {\n                                namespacePublishInfo.push(\"[\" + env + \", \" + cluster + \"]\");\n                            } else {\n                                namespacePublishInfo.push(\"[\" + env + \"]\");\n                            }\n\n                        }\n                    })\n                });\n\n                $scope.namespacePublishInfo = namespacePublishInfo;\n            });\n\n    }\n\n    EventManager.subscribe(EventManager.EventType.REFRESH_NAMESPACE,\n                           function (context) {\n                               if (context.namespace) {\n                                   refreshSingleNamespace(context.namespace);\n                               } else {\n                                   refreshAllNamespaces();\n                               }\n\n                           });\n\n    function refreshAllNamespaces() {\n        if ($rootScope.pageContext.env == '') {\n            return;\n        }\n\n        ConfigService.load_all_namespaces($rootScope.pageContext.appId,\n                                          $rootScope.pageContext.env,\n                                          $rootScope.pageContext.clusterName).then(\n            function (result) {\n\n                $scope.namespaces = result;\n                $('.config-item-container').removeClass('hide');\n\n                initPublishInfo();\n            }, function (result) {\n                toastr.error(AppUtil.errorMsg(result), \"加载配置信息出错\");\n            });\n    }\n\n    function refreshSingleNamespace(namespace) {\n        if ($rootScope.pageContext.env == '') {\n            return;\n        }\n\n        ConfigService.load_namespace($rootScope.pageContext.appId,\n                                     $rootScope.pageContext.env,\n                                     $rootScope.pageContext.clusterName,\n                                     namespace.baseInfo.namespaceName).then(\n            function (result) {\n\n                $scope.namespaces.forEach(function (namespace, index) {\n                    if (namespace.baseInfo.namespaceName == result.baseInfo.namespaceName) {\n                        $scope.namespaces[index] = result;\n                    }\n                });\n\n                initPublishInfo();\n\n            }, function (result) {\n                toastr.error(AppUtil.errorMsg(result), \"加载配置信息出错\");\n            });\n    }\n\n    function rollback() {\n        EventManager.emit(EventManager.EventType.ROLLBACK_NAMESPACE);\n    }\n\n    $scope.tableViewOperType = '', $scope.item = {};\n    $scope.toOperationNamespace;\n\n    var toDeleteItemId = 0;\n\n    function preDeleteItem(namespace, itemId) {\n        if (!lockCheck(namespace)) {\n            return;\n        }\n\n        $scope.toOperationNamespace = namespace;\n        toDeleteItemId = itemId;\n\n        $(\"#deleteConfirmDialog\").modal(\"show\");\n    }\n\n    function deleteItem() {\n        ConfigService.delete_item($rootScope.pageContext.appId,\n                                  $rootScope.pageContext.env,\n                                  $rootScope.pageContext.clusterName,\n                                  $scope.toOperationNamespace.baseInfo.namespaceName,\n                                  toDeleteItemId).then(\n            function (result) {\n                toastr.success(\"删除成功!\");\n                EventManager.emit(EventManager.EventType.REFRESH_NAMESPACE,\n                                  {\n                                      namespace: $scope.toOperationNamespace\n                                  });\n            }, function (result) {\n                toastr.error(AppUtil.errorMsg(result), \"删除失败\");\n            });\n    }\n\n    //修改配置\n    function editItem(namespace, toEditItem) {\n        if (!lockCheck(namespace)) {\n            return;\n        }\n\n        $scope.item = _.clone(toEditItem);\n\n        if (namespace.isBranch || namespace.isLinkedNamespace) {\n            var existedItem = false;\n            namespace.items.forEach(function (item) {\n                if (!item.isDeleted && item.item.key == toEditItem.key) {\n                    existedItem = true;\n                }\n            });\n            if (!existedItem) {\n                $scope.item.lineNum = 0;\n                $scope.item.tableViewOperType = 'create';\n            } else {\n                $scope.item.tableViewOperType = 'update';\n            }\n\n        } else {\n            $scope.item.tableViewOperType = 'update';\n        }\n\n        $scope.toOperationNamespace = namespace;\n\n        AppUtil.showModal('#itemModal');\n    }\n\n    //新增配置\n    function createItem(namespace) {\n        if (!lockCheck(namespace)) {\n            return;\n        }\n\n        $scope.item = {\n            tableViewOperType: 'create'\n        };\n\n        $scope.toOperationNamespace = namespace;\n        AppUtil.showModal('#itemModal');\n    }\n\n    var selectedClusters = [];\n    $scope.collectSelectedClusters = function (data) {\n        selectedClusters = data;\n    };\n\n    function lockCheck(namespace) {\n        if (namespace.lockOwner && $scope.currentUser != namespace.lockOwner) {\n            $scope.lockOwner = namespace.lockOwner;\n            $('#namespaceLockedDialog').modal('show');\n            return false;\n        }\n        return true;\n    }\n\n    function closeTip(clusterName) {\n        var hideTip = JSON.parse(localStorage.getItem(\"hideTip\"));\n        if (!hideTip) {\n            hideTip = {};\n            hideTip[$rootScope.pageContext.appId] = {};\n        }\n\n        if (!hideTip[$rootScope.pageContext.appId]) {\n            hideTip[$rootScope.pageContext.appId] = {};\n        }\n\n        hideTip[$rootScope.pageContext.appId][clusterName] = true;\n\n        $rootScope.hideTip = hideTip;\n\n        localStorage.setItem(\"hideTip\", JSON.stringify(hideTip));\n\n    }\n\n    function showText(text) {\n        $scope.text = text;\n        $('#showTextModal').modal('show');\n    }\n\n    function showNoModifyPermissionDialog() {\n        $(\"#modifyNoPermissionDialog\").modal('show');\n    }\n\n    var toCreateBranchNamespace = {};\n\n    function preCreateBranch(namespace) {\n        toCreateBranchNamespace = namespace;\n        AppUtil.showModal(\"#createBranchTips\");\n    }\n\n    function createBranch() {\n        NamespaceBranchService.createBranch($rootScope.pageContext.appId,\n                                            $rootScope.pageContext.env,\n                                            $rootScope.pageContext.clusterName,\n                                            toCreateBranchNamespace.baseInfo.namespaceName)\n            .then(function (result) {\n                toastr.success(\"创建灰度成功\");\n                EventManager.emit(EventManager.EventType.REFRESH_NAMESPACE,\n                                  {\n                                      namespace: toCreateBranchNamespace\n                                  });\n            }, function (result) {\n                toastr.error(AppUtil.errorMsg(result), \"创建灰度失败\");\n            })\n\n    }\n\n    function preDeleteBranch(branch) {\n        //normal delete\n        branch.branchStatus = 0;\n        $scope.toDeleteBranch = branch;\n        AppUtil.showModal('#deleteBranchDialog');\n    }\n\n    function deleteBranch() {\n        NamespaceBranchService.deleteBranch($rootScope.pageContext.appId,\n                                            $rootScope.pageContext.env,\n                                            $rootScope.pageContext.clusterName,\n                                            $scope.toDeleteBranch.baseInfo.namespaceName,\n                                            $scope.toDeleteBranch.baseInfo.clusterName\n            )\n            .then(function (result) {\n                toastr.success(\"删除成功\");\n                EventManager.emit(EventManager.EventType.REFRESH_NAMESPACE,\n                                  {\n                                      namespace: $scope.toDeleteBranch.parentNamespace\n                                  });\n            }, function (result) {\n                toastr.error(AppUtil.errorMsg(result), \"删除分支失败\");\n            })\n\n    }\n\n    EventManager.subscribe(EventManager.EventType.EMERGENCY_PUBLISH,\n                           function (context) {\n                               AppUtil.showModal(\"#emergencyPublishAlertDialog\");\n                               $scope.emergencyPublishContext = context;\n                           });\n\n    function emergencyPublish() {\n        if ($scope.emergencyPublishContext.mergeAndPublish) {\n\n            EventManager.emit(EventManager.EventType.MERGE_AND_PUBLISH_NAMESPACE,\n                              {\n                                  branch: $scope.emergencyPublishContext.namespace,\n                                  isEmergencyPublish: true\n                              });\n        } else {\n            EventManager.emit(EventManager.EventType.PUBLISH_NAMESPACE,\n                              {\n                                  namespace: $scope.emergencyPublishContext.namespace,\n                                  isEmergencyPublish: true\n                              });\n        }\n\n    }\n\n    EventManager.subscribe(EventManager.EventType.DELETE_NAMESPACE_FAILED, function (context) {\n        $scope.deleteNamespaceContext = context;\n\n        if (context.reason == 'master_instance') {\n            AppUtil.showModal('#deleteNamespaceDenyForMasterInstanceDialog');\n        } else if (context.reason == 'branch_instance') {\n            AppUtil.showModal('#deleteNamespaceDenyForBranchInstanceDialog');\n        } else if (context.reason == 'public_namespace') {\n            var otherAppAssociatedNamespaces = context.otherAppAssociatedNamespaces;\n            var namespaceTips = [];\n            otherAppAssociatedNamespaces.forEach(function (namespace) {\n                var appId = namespace.appId;\n                var clusterName = namespace.clusterName;\n                var url = '/config.html?#/appid=' + appId + '&env=' + $scope.pageContext.env + '&cluster='\n                          + clusterName;\n\n                namespaceTips.push(\"<a target='_blank' href=\\'\" + url + \"\\'>AppId = \" + appId + \", 集群 = \" + clusterName\n                                   + \", Namespace = \" + namespace.namespaceName + \"</a>\");\n            });\n\n            $scope.deleteNamespaceContext.detailReason =\n                \"以下应用已关联此公共Namespace，必须先删除全部已关联的Namespace才能删除公共Namespace。<br>\"\n                + namespaceTips.join(\"<br>\");\n\n            AppUtil.showModal('#deleteNamespaceDenyForPublicNamespaceDialog');\n        }\n\n    });\n\n\n    new Clipboard('.clipboard');\n\n\n}\n\n\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/controller/config/ReleaseHistoryController.js",
    "content": "release_history_module.controller(\"ReleaseHistoryController\",\n                                  ['$scope', '$location', 'AppUtil',\n                                   'ReleaseService', 'ConfigService', 'ReleaseHistoryService', releaseHistoryController\n                                  ]);\n\nfunction releaseHistoryController($scope, $location, AppUtil,\n                                  ReleaseService, ConfigService, ReleaseHistoryService) {\n\n    var params = AppUtil.parseParams($location.$$url);\n    $scope.pageContext = {\n        appId: params.appid,\n        env: params.env,\n        clusterName: params.clusterName,\n        namespaceName: params.namespaceName,\n        releaseId: params.releaseId,\n        releaseHistoryId: params.releaseHistoryId\n    };\n    var PAGE_SIZE = 10;\n    var CONFIG_VIEW_TYPE = {\n        DIFF: 'diff',\n        ALL: 'all'\n    };\n\n    $scope.page = 0;\n    $scope.releaseHistories = [];\n    $scope.hasLoadAll = false;\n    $scope.selectedReleaseHistory = 0;\n    $scope.isTextNamespace = false;\n\n    $scope.showReleaseHistoryDetail = showReleaseHistoryDetail;\n    $scope.switchConfigViewType = switchConfigViewType;\n    $scope.findReleaseHistory = findReleaseHistory;\n    $scope.showText = showText;\n\n    init();\n\n    function init() {\n\n        findReleaseHistory();\n\n        loadNamespace();\n    }\n\n    function findReleaseHistory() {\n        if ($scope.hasLoadAll) {\n            return;\n        }\n        ReleaseHistoryService.findReleaseHistoryByNamespace($scope.pageContext.appId,\n                                                            $scope.pageContext.env,\n                                                            $scope.pageContext.clusterName,\n                                                            $scope.pageContext.namespaceName,\n                                                            $scope.page, PAGE_SIZE)\n            .then(function (result) {\n                if ($scope.page == 0) {\n                    $(\".release-history\").removeClass('hidden');\n                }\n\n                if (!result || result.length < PAGE_SIZE) {\n                    $scope.hasLoadAll = true;\n                }\n\n                if (result.length == 0) {\n                    return;\n                }\n\n                $scope.releaseHistories = $scope.releaseHistories.concat(result);\n\n                if ($scope.page == 0) {\n                    var defaultToShowReleaseHistory = result[0];\n                    $scope.releaseHistories.forEach(function (history) {\n                        if ($scope.pageContext.releaseHistoryId == history.id) {\n                            defaultToShowReleaseHistory = history;\n                        } else if ($scope.pageContext.releaseId == history.releaseId) {\n                            // text namespace doesn't support ALL view\n                            if (!$scope.isTextNamespace) {\n                              history.viewType = CONFIG_VIEW_TYPE.ALL;\n                            }\n                            defaultToShowReleaseHistory = history;\n                        }\n                    });\n\n                    showReleaseHistoryDetail(defaultToShowReleaseHistory);\n                }\n\n                $scope.page = $scope.page + 1;\n\n            }, function (result) {\n                AppUtil.showErrorMsg(result, \"加载发布历史信息出错\");\n            });\n    }\n\n    function loadNamespace() {\n        ConfigService.load_namespace($scope.pageContext.appId,\n                                     $scope.pageContext.env,\n                                     $scope.pageContext.clusterName,\n                                     $scope.pageContext.namespaceName)\n            .then(function (result) {\n                $scope.isTextNamespace = result.format != \"properties\";\n                if ($scope.isTextNamespace) {\n                  fixTextNamespaceViewType();\n                }\n            })\n    }\n\n    function showReleaseHistoryDetail(history) {\n\n        $scope.history = history;\n        $scope.selectedReleaseHistory = history.id;\n        if (!history.viewType) {//default view type\n            history.viewType = CONFIG_VIEW_TYPE.DIFF;\n            getReleaseDiffConfiguration(history);\n        }\n\n    }\n\n    function fixTextNamespaceViewType() {\n      $scope.releaseHistories.forEach(function (history) {\n          // text namespace doesn't support ALL view\n          if (history.viewType == CONFIG_VIEW_TYPE.ALL) {\n            switchConfigViewType(history, CONFIG_VIEW_TYPE.DIFF);\n          }\n      });\n    }\n\n    function switchConfigViewType(history, viewType) {\n        history.viewType = viewType;\n\n        if (viewType == CONFIG_VIEW_TYPE.DIFF) {\n            getReleaseDiffConfiguration(history);\n        }\n\n    }\n\n    function getReleaseDiffConfiguration(history) {\n\n        if (!history.changes) {\n\n            //Set previous release id to master latest release id when branch first gray release.\n            if (history.operation == 2 && history.previousReleaseId == 0) {\n                history.previousReleaseId = history.operationContext.baseReleaseId;\n            }\n\n            ReleaseService.compare($scope.pageContext.env,\n                                   history.previousReleaseId,\n                                   history.releaseId)\n                .then(function (result) {\n                    history.changes = result.changes;\n                })\n        }\n    }\n\n    function showText(text) {\n        $scope.text = text;\n        AppUtil.showModal(\"#showTextModal\");\n    }\n}\n\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/controller/config/SyncConfigController.js",
    "content": "sync_item_module.controller(\"SyncItemController\",\n                            ['$scope', '$location', '$window', 'toastr', 'AppService', 'AppUtil', 'ConfigService',\n                             function ($scope, $location, $window, toastr, AppService, AppUtil, ConfigService) {\n\n                                 var params = AppUtil.parseParams($location.$$url);\n                                 $scope.pageContext = {\n                                     appId: params.appid,\n                                     env: params.env,\n                                     clusterName: params.clusterName,\n                                     namespaceName: params.namespaceName\n                                 };\n                                 var sourceItems = [];\n\n                                 $scope.syncBtnDisabled = false;\n                                 $scope.viewItems = [];\n\n                                 $scope.toggleItemsCheckedStatus = toggleItemsCheckedStatus;\n                                 $scope.diff = diff;\n                                 $scope.removeItem = removeItem;\n                                 $scope.syncItems = syncItems;\n                                 $scope.collectSelectedClusters = collectSelectedClusters;\n\n                                 $scope.syncItemNextStep = syncItemNextStep;\n                                 $scope.backToAppHomePage = backToAppHomePage;\n                                 $scope.switchSelect = switchSelect;\n\n                                 $scope.filter = filter;\n                                 $scope.resetFilter = resetFilter;\n                                 \n                                 $scope.showText = showText;\n\n                                 init();\n\n                                 function init() {\n                                     ////// load items //////\n                                     ConfigService.find_items($scope.pageContext.appId, $scope.pageContext.env,\n                                                              $scope.pageContext.clusterName,\n                                                              $scope.pageContext.namespaceName,\n                                                              \"lastModifiedTime\")\n                                         .then(function (result) {\n\n                                             sourceItems = [];\n                                             result.forEach(function (item) {\n                                                 if (item.key) {\n                                                     item.checked = false;\n                                                     sourceItems.push(item);\n                                                 }\n                                             });\n\n                                             $scope.viewItems = sourceItems;\n                                             $(\".apollo-container\").removeClass(\"hidden\");\n                                         }, function (result) {\n                                             toastr.error(AppUtil.errorMsg(result), \"加载配置出错\");\n                                         });\n                                 }\n\n                                 var itemAllSelected = false;\n\n                                 function toggleItemsCheckedStatus() {\n                                     itemAllSelected = !itemAllSelected;\n                                     $scope.viewItems.forEach(function (item) {\n                                         item.checked = itemAllSelected;\n                                     })\n                                 }\n\n                                 var syncData = {\n                                     syncToNamespaces: [],\n                                     syncItems: []\n                                 };\n\n                                 function diff() {\n                                     parseSyncSourceData();\n                                     if (syncData.syncItems.length == 0) {\n                                         toastr.warning(\"请选择需要同步的配置\");\n                                         return;\n                                     }\n                                     if (syncData.syncToNamespaces.length == 0) {\n                                         toastr.warning(\"请选择集群\");\n                                         return;\n                                     }\n                                     $scope.hasDiff = false;\n                                     ConfigService.diff($scope.pageContext.namespaceName, syncData).then(\n                                         function (result) {\n\n                                             $scope.clusterDiffs = result;\n\n                                             $scope.clusterDiffs.forEach(function (clusterDiff) {\n                                                 if (!$scope.hasDiff) {\n                                                     $scope.hasDiff =\n                                                         clusterDiff.diffs.createItems.length\n                                                         + clusterDiff.diffs.updateItems.length\n                                                         > 0;\n                                                 }\n\n                                                 if (clusterDiff.diffs.updateItems.length > 0) {\n                                                     //赋予同步前的值\n                                                     ConfigService.find_items(clusterDiff.namespace.appId,\n                                                                              clusterDiff.namespace.env,\n                                                                              clusterDiff.namespace.clusterName,\n                                                                              clusterDiff.namespace.namespaceName)\n                                                         .then(function (result) {\n                                                             var oldItemMap = {};\n                                                             result.forEach(function (item) {\n                                                                 oldItemMap[item.key] = item.value;\n                                                             });\n                                                             clusterDiff.diffs.updateItems.forEach(function (item) {\n                                                                 item.oldValue = oldItemMap[item.key];\n                                                             })\n                                                         });\n                                                 }\n\n                                             });\n                                             $scope.syncItemNextStep(1);\n                                         }, function (result) {\n                                             toastr.error(AppUtil.errorMsg(result));\n                                         });\n                                 }\n\n                                 function removeItem(diff, type, toRemoveItem) {\n                                     var syncDataResult = [],\n                                         diffSetResult = [],\n                                         diffSet;\n                                     if (type == 'create') {\n                                         diffSet = diff.createItems;\n                                     } else {\n                                         diffSet = diff.updateItems;\n                                     }\n                                     diffSet.forEach(function (item) {\n                                         if (item.key != toRemoveItem.key) {\n                                             diffSetResult.push(item);\n                                         }\n                                     });\n                                     if (type == 'create') {\n                                         diff.createItems = diffSetResult;\n                                     } else {\n                                         diff.updateItems = diffSetResult;\n                                     }\n\n                                     syncData.syncItems.forEach(function (item) {\n                                         if (item.key != toRemoveItem.key) {\n                                             syncDataResult.push(item);\n                                         }\n                                     });\n                                     syncData.syncItems = syncDataResult;\n                                 }\n\n                                 function syncItems() {\n                                     $scope.syncBtnDisabled = true;\n                                     ConfigService.sync_items($scope.pageContext.appId,\n                                                              $scope.pageContext.namespaceName,\n                                                              syncData).then(function (result) {\n                                         $scope.syncItemStep += 1;\n                                         $scope.syncSuccess = true;\n                                         $scope.syncBtnDisabled = false;\n                                     }, function (result) {\n                                         $scope.syncSuccess = false;\n                                         $scope.syncBtnDisabled = false;\n                                         toastr.error(AppUtil.errorMsg(result));\n                                     });\n                                 }\n\n                                 var selectedClusters = [];\n\n                                 function collectSelectedClusters(data) {\n                                     selectedClusters = data;\n                                 }\n\n                                 function parseSyncSourceData() {\n                                     syncData = {\n                                         syncToNamespaces: [],\n                                         syncItems: []\n                                     };\n                                     var namespaceName = $scope.pageContext.namespaceName;\n                                     selectedClusters.forEach(function (cluster) {\n                                         if (cluster.checked) {\n                                             cluster.clusterName = cluster.name;\n                                             cluster.namespaceName = namespaceName;\n                                             syncData.syncToNamespaces.push(cluster);\n                                         }\n                                     });\n\n                                     $scope.viewItems.forEach(function (item) {\n                                         if (item.checked) {\n                                             syncData.syncItems.push(item);\n                                         }\n                                     });\n                                     return syncData;\n                                 }\n\n                                 ////// flow control ///////\n\n                                 $scope.syncItemStep = 1;\n                                 function syncItemNextStep(offset) {\n                                     $scope.syncItemStep += offset;\n                                 }\n\n                                 function backToAppHomePage() {\n                                     $window.location.href = '/config.html?#appid=' + $scope.pageContext.appId;\n                                 }\n\n                                 function switchSelect(o) {\n                                     o.checked = !o.checked;\n                                 }\n\n                                 function filter() {\n                                     var beginTime = $scope.filterBeginTime;\n                                     var endTime = $scope.filterEndTime;\n\n                                     var result = [];\n                                     sourceItems.forEach(function (item) {\n                                         var updateTime = new Date(item.dataChangeLastModifiedTime);\n                                         if ((!beginTime || updateTime > beginTime)\n                                             && (!endTime || updateTime < endTime)) {\n                                             result.push(item);\n                                         }\n                                     });\n\n                                     $scope.viewItems = result;\n                                 }\n\n                                 function resetFilter() {\n                                     $scope.filterBeginTime = null;\n                                     $scope.filterEndTime = null;\n                                     filter();\n                                 }\n\n                                 function showText(text) {\n                                     $scope.text = text;\n                                     AppUtil.showModal('#showTextModal');\n                                 }\n\n\n                             }]);\n\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/controller/open/OpenManageController.js",
    "content": "open_manage_module.controller('OpenManageController',\n                              ['$scope', 'toastr', 'AppUtil', 'OrganizationService', 'ConsumerService', 'PermissionService',\n                               OpenManageController]);\n\nfunction OpenManageController($scope, toastr, AppUtil, OrganizationService, ConsumerService, PermissionService) {\n\n    var $orgWidget = $('#organization');\n\n    $scope.consumer = {};\n    $scope.consumerRole = {\n        type: 'NamespaceRole'\n    };\n\n    $scope.submitBtnDisabled = false;\n    $scope.userSelectWidgetId = 'toAssignMasterRoleUser';\n\n    $scope.getTokenByAppId = getTokenByAppId;\n    $scope.createConsumer = createConsumer;\n    $scope.assignRoleToConsumer = assignRoleToConsumer;\n\n    init();\n\n    function init() {\n        initOrganization();\n        initPermission();\n\n    }\n\n    function initOrganization() {\n        OrganizationService.find_organizations().then(function (result) {\n            var organizations = [];\n            result.forEach(function (item) {\n                var org = {};\n                org.id = item.orgId;\n                org.text = item.orgName + '(' + item.orgId + ')';\n                org.name = item.orgName;\n                organizations.push(org);\n            });\n            $orgWidget.select2({\n                                   placeholder: '请选择部门',\n                                   width: '100%',\n                                   data: organizations\n                               });\n        }, function (result) {\n            toastr.error(AppUtil.errorMsg(result), \"load organizations error\");\n        });\n    }\n\n    function initPermission() {\n        PermissionService.has_root_permission()\n            .then(function (result) {\n                  $scope.isRootUser = result.hasPermission;\n            })\n    }\n\n    function getTokenByAppId() {\n        if (!$scope.consumer.appId) {\n            toastr.warning(\"请输入appId\");\n            return;\n        }\n\n        ConsumerService.getConsumerTokenByAppId($scope.consumer.appId)\n            .then(function (consumerToken) {\n\n                if (consumerToken.token) {\n                    $scope.consumerToken = consumerToken;\n                    $scope.consumerRole.token = consumerToken.token;\n                } else {\n                    $scope.consumerToken = {token: 'App(' + $scope.consumer.appId + ')未创建，请先创建'};\n                }\n            })\n    }\n\n    function createConsumer() {\n        $scope.submitBtnDisabled = true;\n\n        if (!$scope.consumer.appId) {\n            toastr.warning(\"请输入appId\");\n            return;\n        }\n        var selectedOrg = $orgWidget.select2('data')[0];\n\n        if (!selectedOrg.id) {\n            toastr.warning(\"请选择部门\");\n            return;\n        }\n\n        $scope.consumer.orgId = selectedOrg.id;\n        $scope.consumer.orgName = selectedOrg.name;\n\n        // owner\n        var owner = $('.ownerSelector').select2('data')[0];\n        if (!owner) {\n            toastr.warning(\"请选择应用负责人\");\n            return;\n        }\n        $scope.consumer.ownerName = owner.id;\n\n        ConsumerService.createConsumer($scope.consumer)\n            .then(function (consumerToken) {\n                toastr.success(\"创建成功\");\n                $scope.consumerToken = consumerToken;\n                $scope.consumerRole.token = consumerToken.token;\n                $scope.submitBtnDisabled = false;\n                $scope.consumer = {};\n            }, function (response) {\n                AppUtil.showErrorMsg(response, \"创建失败\");\n                $scope.submitBtnDisabled = false;\n            })\n\n    }\n\n    function assignRoleToConsumer() {\n        ConsumerService.assignRoleToConsumer($scope.consumerRole.token,\n                                             $scope.consumerRole.type,\n                                             $scope.consumerRole.appId,\n                                             $scope.consumerRole.namespaceName)\n            .then(function (consumerRoles) {\n                toastr.success(\"赋权成功\");\n            }, function (response) {\n                AppUtil.showErrorMsg(response, \"赋权失败\");\n            })\n    }\n    \n}\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/controller/role/NamespaceRoleController.js",
    "content": "role_module.controller('NamespaceRoleController',\n                       ['$scope', '$location', '$window', 'toastr', 'AppService', 'UserService', 'AppUtil',\n                        'PermissionService',\n                        function ($scope, $location, $window, toastr, AppService, UserService, AppUtil,\n                                  PermissionService) {\n\n                            var params = AppUtil.parseParams($location.$$url);\n                            $scope.pageContext = {\n                                appId: params.appid,\n                                namespaceName: params.namespaceName\n                            };\n\n                            $scope.modifyRoleSubmitBtnDisabled = false;\n                            $scope.ReleaseRoleSubmitBtnDisabled = false;\n\n                            $scope.releaseRoleWidgetId = 'releaseRoleWidgetId';\n                            $scope.modifyRoleWidgetId = 'modifyRoleWidgetId';\n\n                            PermissionService.has_assign_user_permission($scope.pageContext.appId)\n                                .then(function (result) {\n                                    $scope.hasAssignUserPermission = result.hasPermission;\n                                }, function (reslt) {\n\n                                });\n\n                            PermissionService.get_namespace_role_users($scope.pageContext.appId,\n                                                                       $scope.pageContext.namespaceName)\n                                .then(function (result) {\n                                    $scope.rolesAssignedUsers = result;\n                                }, function (result) {\n                                    toastr.error(AppUtil.errorMsg(result), \"加载授权用户出错\");\n                                });\n\n                            $scope.assignRoleToUser = function (roleType) {\n                                if ('ReleaseNamespace' == roleType) {\n                                    var user = $('.' + $scope.releaseRoleWidgetId).select2('data')[0];\n                                    if (!user) {\n                                        toastr.warning(\"请选择用户\");\n                                        return;\n                                    }\n                                    $scope.ReleaseRoleSubmitBtnDisabled = true;\n                                    var toAssignReleaseNamespaceRoleUser = user.id;\n                                    PermissionService.assign_release_namespace_role($scope.pageContext.appId,\n                                                                                    $scope.pageContext.namespaceName,\n                                                                                    toAssignReleaseNamespaceRoleUser)\n                                        .then(function (result) {\n                                            toastr.success(\"添加成功\");\n                                            $scope.ReleaseRoleSubmitBtnDisabled = false;\n                                            $scope.rolesAssignedUsers.releaseRoleUsers.push(\n                                                {userId: toAssignReleaseNamespaceRoleUser});\n                                            $('.' + $scope.releaseRoleWidgetId).select2(\"val\", \"\");\n                                        }, function (result) {\n                                            $scope.ReleaseRoleSubmitBtnDisabled = false;\n                                            toastr.error(AppUtil.errorMsg(result), \"添加失败\");\n                                        });\n                                } else {\n                                    var user = $('.' + $scope.modifyRoleWidgetId).select2('data')[0];\n                                    if (!user) {\n                                        toastr.warning(\"请选择用户\");\n                                        return;\n                                    }\n                                    $scope.modifyRoleSubmitBtnDisabled = true;\n                                    var toAssignModifyNamespaceRoleUser = user.id;\n                                    PermissionService.assign_modify_namespace_role($scope.pageContext.appId,\n                                                                                   $scope.pageContext.namespaceName,\n                                                                                   toAssignModifyNamespaceRoleUser)\n                                        .then(function (result) {\n                                            toastr.success(\"添加成功\");\n                                            $scope.modifyRoleSubmitBtnDisabled = false;\n                                            $scope.rolesAssignedUsers.modifyRoleUsers.push(\n                                                {userId: toAssignModifyNamespaceRoleUser});\n                                            $('.' + $scope.modifyRoleWidgetId).select2(\"val\", \"\");\n                                        }, function (result) {\n                                            $scope.modifyRoleSubmitBtnDisabled = false;\n                                            toastr.error(AppUtil.errorMsg(result), \"添加失败\");\n                                        });\n                                }\n                            };\n\n                            $scope.removeUserRole = function (roleType, user) {\n                                if ('ReleaseNamespace' == roleType) {\n                                    PermissionService.remove_release_namespace_role($scope.pageContext.appId,\n                                                                                    $scope.pageContext.namespaceName,\n                                                                                    user)\n                                        .then(function (result) {\n                                            toastr.success(\"删除成功\");\n                                            removeUserFromList($scope.rolesAssignedUsers.releaseRoleUsers, user);\n                                        }, function (result) {\n                                            toastr.error(AppUtil.errorMsg(result), \"删除失败\");\n                                        });\n                                } else {\n                                    PermissionService.remove_modify_namespace_role($scope.pageContext.appId,\n                                                                                   $scope.pageContext.namespaceName,\n                                                                                   user)\n                                        .then(function (result) {\n                                            toastr.success(\"删除成功\");\n                                            removeUserFromList($scope.rolesAssignedUsers.modifyRoleUsers, user);\n                                        }, function (result) {\n                                            toastr.error(AppUtil.errorMsg(result), \"删除失败\");\n                                        });\n                                }\n                            };\n\n                            function removeUserFromList(list, user) {\n                                var index = 0;\n                                for (var i = 0; i < list.length; i++) {\n                                    if (list[i].userId == user) {\n                                        index = i;\n                                        break;\n                                    }\n                                }\n                                list.splice(index, 1);\n                            }\n\n                        }]);\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/directive/delete-namespace-modal-directive.js",
    "content": "directive_module.directive('deletenamespacemodal', deleteNamespaceModalDirective);\n\nfunction deleteNamespaceModalDirective($window, $q, toastr, AppUtil, EventManager,\n                                       PermissionService, UserService, NamespaceService) {\n    return {\n        restrict: 'E',\n        templateUrl: '../../views/component/delete-namespace-modal.html',\n        transclude: true,\n        replace: true,\n        scope: {\n            env: '='\n        },\n        link: function (scope) {\n\n            scope.doDeleteNamespace = doDeleteNamespace;\n\n            EventManager.subscribe(EventManager.EventType.PRE_DELETE_NAMESPACE, function (context) {\n                var toDeleteNamespace = context.namespace;\n                scope.toDeleteNamespace = toDeleteNamespace;\n\n                //1. check namespace is not private\n                if (!checkNotPrivateNamespace(toDeleteNamespace)) {\n                    return;\n                }\n\n                //2. check operator has master permission\n                checkPermission(toDeleteNamespace).then(function () {\n\n                    //3. check namespace's master branch has not instances\n                    if (!checkMasterInstance(toDeleteNamespace)) {\n                        return;\n                    }\n\n                    //4. check namespace's gray branch has not instances\n                    if (!checkBranchInstance(toDeleteNamespace)) {\n                        return;\n                    }\n\n                    if (toDeleteNamespace.isLinkedNamespace) {\n                        showDeleteNamespaceConfirmDialog();\n                    } else {\n                        //5. check public namespace has not associated namespace\n                        checkPublicNamespace(toDeleteNamespace).then(function () {\n                            showDeleteNamespaceConfirmDialog();\n                        });\n                    }\n                })\n\n            });\n\n            function checkNotPrivateNamespace(namespace) {\n                if (!namespace.isPublic) {\n                    toastr.error(\"不能删除私有的Namespace\", \"删除失败\");\n                    return false;\n                }\n\n                return true;\n            }\n\n            function checkPermission(namespace) {\n                var d = $q.defer();\n\n                UserService.load_user().then(function (currentUser) {\n\n                    var isAppMasterUser = false;\n\n                    PermissionService.get_app_role_users(namespace.baseInfo.appId)\n                        .then(function (appRoleUsers) {\n\n                            var masterUsers = [];\n\n                            appRoleUsers.masterUsers.forEach(function (user) {\n                                masterUsers.push(user.userId);\n\n                                if (currentUser.userId == user.userId) {\n                                    isAppMasterUser = true;\n                                }\n                            });\n\n                            scope.masterUsers = masterUsers;\n                            scope.isAppMasterUser = isAppMasterUser;\n\n                            if (!isAppMasterUser) {\n                                toastr.error(\"您没有项目管理员权限，只有管理员才能删除Namespace，请找项目管理员 [\" + scope.masterUsers.join(\"，\")\n                                             + \"] 删除Namespace\", \"删除失败\");\n                                d.reject();\n                            } else {\n                                d.resolve();\n                            }\n                        });\n                });\n\n                return d.promise;\n            }\n\n            function checkMasterInstance(namespace) {\n                if (namespace.instancesCount > 0) {\n                    EventManager.emit(EventManager.EventType.DELETE_NAMESPACE_FAILED, {\n                        namespace: namespace,\n                        reason: 'master_instance'\n                    });\n\n                    return false;\n                }\n\n                return true;\n            }\n\n            function checkBranchInstance(namespace) {\n                if (namespace.hasBranch && namespace.branch.latestReleaseInstances.total > 0) {\n                    EventManager.emit(EventManager.EventType.DELETE_NAMESPACE_FAILED, {\n                        namespace: namespace,\n                        reason: 'branch_instance'\n                    });\n\n                    return false;\n                }\n\n                return true;\n            }\n\n            function checkPublicNamespace(namespace) {\n                var d = $q.defer();\n\n                var publicAppId = namespace.baseInfo.appId;\n                NamespaceService.getPublicAppNamespaceAllNamespaces(scope.env,\n                                                                    namespace.baseInfo.namespaceName,\n                                                                    0, 20)\n                    .then(function (associatedNamespaces) {\n                        var otherAppAssociatedNamespaces = [];\n                        associatedNamespaces.forEach(function (associatedNamespace) {\n                            if (associatedNamespace.appId != publicAppId) {\n                                otherAppAssociatedNamespaces.push(associatedNamespace);\n                            }\n                        });\n\n                        if (otherAppAssociatedNamespaces.length) {\n                            EventManager.emit(EventManager.EventType.DELETE_NAMESPACE_FAILED, {\n                                namespace: namespace,\n                                reason: 'public_namespace',\n                                otherAppAssociatedNamespaces: otherAppAssociatedNamespaces\n                            });\n                            d.reject();\n                        } else {\n                            d.resolve();\n                        }\n\n                    });\n\n                return d.promise;\n\n            }\n\n            function showDeleteNamespaceConfirmDialog() {\n                AppUtil.showModal('#deleteNamespaceModal');\n\n            }\n\n            function doDeleteNamespace() {\n                var toDeleteNamespace = scope.toDeleteNamespace;\n                NamespaceService.deleteNamespace(toDeleteNamespace.baseInfo.appId, scope.env,\n                                                 toDeleteNamespace.baseInfo.clusterName,\n                                                 toDeleteNamespace.baseInfo.namespaceName)\n                    .then(function () {\n                        toastr.success(\"删除成功\");\n\n                        setTimeout(function () {\n                            $window.location.reload();\n                        }, 1000);\n\n                    }, function (result) {\n                        AppUtil.showErrorMsg(result, \"删除失败\");\n                    })\n\n            }\n\n        }\n    }\n}\n\n\n\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/directive/diff-directive.js",
    "content": "directive_module.directive('apollodiff',\n                           function ($compile, $window) {\n                               return {\n                                   restrict: 'E',\n                                   templateUrl: '../../views/component/diff.html',\n                                   transclude: true,\n                                   replace: true,\n                                   scope: {\n                                       oldStr: '=',\n                                       newStr: '=',\n                                       apolloId: '='\n                                   },\n                                   link: function (scope, element, attrs) {\n\n                                       scope.$watch('oldStr', makeDiff);\n                                       scope.$watch('newStr', makeDiff);\n\n\n\n                                       function makeDiff() {\n                                           var displayArea = document.getElementById(scope.apolloId);\n                                           if (!displayArea){\n                                               return;\n                                           }\n                                           //clear\n                                           displayArea.innerHTML = '';\n\n                                           var color = '',\n                                               span = null,\n                                               pre = '';\n\n                                           var oldStr = scope.oldStr == undefined ? '' : scope.oldStr;\n                                           var newStr = scope.newStr == undefined ? '' : scope.newStr;\n\n                                           var diff = JsDiff.diffLines(oldStr, newStr),\n                                               fragment = document.createDocumentFragment();\n\n                                           diff.forEach(function (part) {\n                                               // green for additions, red for deletions\n                                               // grey for common parts\n                                               color = part.added ? 'green' :\n                                                       part.removed ? 'red' : 'grey';\n                                               span = document.createElement('span');\n                                               span.style.color = color;\n                                               pre = part.added ? '+' :\n                                                   part.removed ? '-' : '';\n                                               span.appendChild(document.createTextNode(pre + part.value));\n                                               fragment.appendChild(span);\n                                           });\n\n                                           displayArea.appendChild(fragment);\n\n                                       }\n\n                                   }\n                               }\n\n                           });\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/directive/directive.js",
    "content": "/** navbar */\ndirective_module.directive('apollonav',\n                           function ($compile, $window, toastr, AppUtil, AppService, EnvService,\n                           UserService, CommonService, PermissionService) {\n                               return {\n                                   restrict: 'E',\n                                   templateUrl: '../../views/common/nav.html',\n                                   transclude: true,\n                                   replace: true,\n                                   link: function (scope, element, attrs) {\n\n                                       CommonService.getPageSetting().then(function (setting) {\n                                           scope.pageSetting = setting;\n                                       });\n\n                                       scope.sourceApps = [];\n                                       scope.copyedApps = [];\n\n                                       AppService.find_apps().then(function (result) {\n                                           result.forEach(function (app) {\n                                               app.selected = false;\n                                               scope.sourceApps.push(app);\n                                           });\n                                           scope.copyedApps = angular.copy(scope.sourceApps);\n                                       }, function (result) {\n                                           toastr.error(AppUtil.errorMsg(result), \"load apps error\");\n                                       });\n\n                                       scope.searchKey = '';\n                                       scope.shouldShowAppList = false;\n\n                                       var selectedApp = {};\n                                       scope.selectApp = function (app) {\n                                           select(app);\n                                           scope.jumpToConfigPage();\n                                       };\n\n                                       scope.changeSearchKey = function () {\n                                           scope.copyedApps = [];\n                                           var searchKey = scope.searchKey.toLocaleLowerCase();\n                                           scope.sourceApps.forEach(function (app) {\n                                               if (app.name.toLocaleLowerCase().indexOf(searchKey) > -1\n                                                   || app.appId.toLocaleLowerCase().indexOf(searchKey) > -1) {\n                                                   scope.copyedApps.push(app);\n                                               }\n                                           });\n                                           scope.shouldShowAppList = true;\n                                       };\n\n                                       scope.jumpToConfigPage = function () {\n                                           if (selectedApp.appId) {\n                                               if ($window.location.href.indexOf(\"config.html\") > -1) {\n                                                   $window.location.hash = \"appid=\" + selectedApp.appId;\n                                                   $window.location.reload();\n                                               } else {\n                                                   $window.location.href = '/config.html?#appid=' + selectedApp.appId;\n                                               }\n                                           }\n                                       };\n\n                                       //up:38 down:40 enter:13\n                                       var selectedAppIdx = -1;\n                                       element.bind(\"keydown keypress\", function (event) {\n\n                                           if (event.keyCode == 40) {\n                                               if (selectedAppIdx < scope.copyedApps.length - 1) {\n                                                   clearAppsSelectedStatus();\n                                                   scope.copyedApps[++selectedAppIdx].selected = true;\n                                               }\n                                           } else if (event.keyCode == 38) {\n                                               if (selectedAppIdx >= 1) {\n                                                   clearAppsSelectedStatus();\n                                                   scope.copyedApps[--selectedAppIdx].selected = true;\n                                               }\n                                           } else if (event.keyCode == 13) {\n                                               if (scope.shouldShowAppList && selectedAppIdx > -1) {\n                                                   select(scope.copyedApps[selectedAppIdx]);\n                                                   event.preventDefault();\n                                               } else {\n                                                   scope.jumpToConfigPage();\n                                               }\n\n                                           }\n                                           //强制刷新\n                                           scope.$apply(function () {\n                                               scope.copiedApps = scope.copiedApps;\n                                           });\n                                       });\n\n                                       $(\".search-input\").on(\"click\", function (event) {\n                                           event.stopPropagation();\n                                       });\n\n                                       $(document).on('click', function () {\n                                           scope.$apply(function () {\n                                               scope.shouldShowAppList = false;\n                                           });\n                                       });\n\n                                       function clearAppsSelectedStatus() {\n                                           scope.copiedApps.forEach(function (app) {\n                                               app.selected = false;\n                                           })\n\n                                       }\n\n                                       function select(app) {\n                                           selectedApp = app;\n                                           scope.searchKey = app.name;\n                                           scope.shouldShowAppList = false;\n                                           clearAppsSelectedStatus();\n                                           selectedAppIdx = -1;\n\n                                       }\n\n                                       UserService.load_user().then(function (result) {\n                                           scope.userName = result.userId;\n                                       }, function (result) {\n\n                                       });\n\n                                       PermissionService.has_root_permission().then(function(result) {\n                                           scope.hasRootPermission = result.hasPermission;\n                                       })\n                                   }\n                               }\n\n                           });\n\n/** env cluster selector*/\ndirective_module.directive('apolloclusterselector', function ($compile, $window, AppService, AppUtil, toastr) {\n    return {\n        restrict: 'E',\n        templateUrl: '../../views/component/env-selector.html',\n        transclude: true,\n        replace: true,\n        scope: {\n            appId: '=apolloAppId',\n            defaultAllChecked: '=apolloDefaultAllChecked',\n            select: '=apolloSelect',\n            defaultCheckedEnv: '=apolloDefaultCheckedEnv',\n            defaultCheckedCluster: '=apolloDefaultCheckedCluster',\n            notCheckedEnv: '=apolloNotCheckedEnv',\n            notCheckedCluster: '=apolloNotCheckedCluster'\n        },\n        link: function (scope, element, attrs) {\n\n            scope.$watch(\"defaultCheckedEnv\", refreshClusterList);\n            scope.$watch(\"defaultCheckedCluster\", refreshClusterList);\n\n            refreshClusterList();\n\n            function refreshClusterList() {\n                AppService.load_nav_tree(scope.appId).then(function (result) {\n                    scope.clusters = [];\n                    var envClusterInfo = AppUtil.collectData(result);\n                    envClusterInfo.forEach(function (node) {\n                        var env = node.env;\n                        node.clusters.forEach(function (cluster) {\n                            cluster.env = env;\n                            //default checked\n                            cluster.checked = scope.defaultAllChecked ||\n                                              (cluster.env == scope.defaultCheckedEnv && cluster.name\n                                                                                         == scope.defaultCheckedCluster);\n                            //not checked\n                            if (cluster.env == scope.notCheckedEnv && cluster.name == scope.notCheckedCluster) {\n                                cluster.checked = false;\n                            }\n\n                            scope.clusters.push(cluster);\n                        })\n                    });\n                    scope.select(collectSelectedClusters());\n                });\n            }\n\n            scope.envAllSelected = scope.defaultAllChecked;\n\n            scope.toggleEnvsCheckedStatus = function () {\n                scope.envAllSelected = !scope.envAllSelected;\n                scope.clusters.forEach(function (cluster) {\n                    cluster.checked = scope.envAllSelected;\n                });\n                scope.select(collectSelectedClusters());\n            };\n\n            scope.switchSelect = function (o, $event) {\n                o.checked = !o.checked;\n                $event.stopPropagation();\n                scope.select(collectSelectedClusters());\n            };\n\n            scope.toggleClusterCheckedStatus = function (cluster) {\n                cluster.checked = !cluster.checked;\n                scope.select(collectSelectedClusters());\n            };\n\n            function collectSelectedClusters() {\n                var selectedClusters = [];\n                scope.clusters.forEach(function (cluster) {\n                    if (cluster.checked) {\n                        cluster.clusterName = cluster.name;\n                        selectedClusters.push(cluster);\n                    }\n                });\n                return selectedClusters;\n            }\n\n        }\n    }\n\n});\n\n/** 必填项*/\ndirective_module.directive('apollorequiredfield', function ($compile, $window) {\n    return {\n        restrict: 'E',\n        template: '<strong style=\"color: red\">*</strong>',\n        transclude: true,\n        replace: true\n    }\n});\n\n/**  确认框 */\ndirective_module.directive('apolloconfirmdialog', function ($compile, $window, $sce) {\n    return {\n        restrict: 'E',\n        templateUrl: '../../views/component/confirm-dialog.html',\n        transclude: true,\n        replace: true,\n        scope: {\n            dialogId: '=apolloDialogId',\n            title: '=apolloTitle',\n            detail: '=apolloDetail',\n            showCancelBtn: '=apolloShowCancelBtn',\n            doConfirm: '=apolloConfirm',\n            confirmBtnText: '=?',\n            cancel: '='\n        },\n        link: function (scope, element, attrs) {\n\n            scope.$watch(\"detail\", function () {\n                scope.detailAsHtml = $sce.trustAsHtml(scope.detail);\n            });\n\n            if (!scope.confirmBtnText) {\n                scope.confirmBtnText = '确认';\n            }\n            \n            scope.confirm = function () {\n                if (scope.doConfirm) {\n                    scope.doConfirm();\n                }\n            };\n            \n\n\n        }\n    }\n});\n\n/** entrance */\ndirective_module.directive('apolloentrance', function ($compile, $window) {\n    return {\n        restrict: 'E',\n        templateUrl: '../../views/component/entrance.html',\n        transclude: true,\n        replace: true,\n        scope: {\n            imgSrc: '=apolloImgSrc',\n            title: '=apolloTitle',\n            href: '=apolloHref'\n        },\n        link: function (scope, element, attrs) {\n        }\n    }\n});\n\n/** entrance */\ndirective_module.directive('apollouserselector', function ($compile, $window) {\n    return {\n        restrict: 'E',\n        templateUrl: '../../views/component/user-selector.html',\n        transclude: true,\n        replace: true,\n        scope: {\n            id: '=apolloId',\n            disabled: '='\n        },\n        link: function (scope, element, attrs) {\n\n            scope.$watch(\"id\", initSelect2);\n\n            var select2Options = {\n                ajax: {\n                    url: '/users',\n                    dataType: 'json',\n                    delay: 250,\n                    data: function (params) {\n                        return {\n                            keyword: params.term ? params.term : '',\n                            limit: 100\n                        }\n                    },\n                    processResults: function (data, params) {\n                        var users = [];\n                        data.forEach(function (user) {\n                            users.push({\n                                           id: user.userId,\n                                           text: user.userId + \" | \" + user.name\n                                       })\n                        });\n                        return {\n                            results: users\n                        }\n\n                    },\n                    cache: true,\n                    minimumInputLength: 5\n                }\n            };\n\n            function initSelect2() {\n                $('.' + scope.id).select2(select2Options);\n            }\n            \n\n        }\n    }\n});\n\ndirective_module.directive('apollomultipleuserselector', function ($compile, $window) {\n    return {\n        restrict: 'E',\n        templateUrl: '../../views/component/multiple-user-selector.html',\n        transclude: true,\n        replace: true,\n        scope: {\n            id: '=apolloId'\n        },\n        link: function (scope, element, attrs) {\n\n            scope.$watch(\"id\", initSelect2);\n\n            var searchUsersAjax = {\n                ajax: {\n                    url: '/users',\n                    dataType: 'json',\n                    delay: 250,\n                    data: function (params) {\n                        return {\n                            keyword: params.term ? params.term : '',\n                            limit: 100\n                        }\n                    },\n                    processResults: function (data, params) {\n                        var users = [];\n                        data.forEach(function (user) {\n                            users.push({\n                                           id: user.userId,\n                                           text: user.userId + \" | \" + user.name\n                                       })\n                        });\n                        return {\n                            results: users\n                        }\n\n                    },\n                    cache: true,\n                    minimumInputLength: 5\n                }\n            };\n\n            function initSelect2() {\n                $('.' + scope.id).select2(searchUsersAjax);\n            }\n        }\n    }\n});\n\n\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/directive/gray-release-rules-modal-directive.js",
    "content": "directive_module.directive('rulesmodal', rulesModalDirective);\n\nfunction rulesModalDirective(toastr, AppUtil, EventManager, InstanceService) {\n    return {\n        restrict: 'E',\n        templateUrl: '../../views/component/gray-release-rules-modal.html',\n        transclude: true,\n        replace: true,\n        scope: {\n            appId: '=',\n            env: '=',\n            cluster: '='\n        },\n        link: function (scope) {\n\n            scope.completeEditBtnDisable = false;\n\n            scope.batchAddIPs = batchAddIPs;\n            scope.addRules = addRules;\n            scope.removeRule = removeRule;\n            scope.completeEditItem = completeEditItem;\n            scope.cancelEditItem = cancelEditItem;\n            scope.initSelectIps = initSelectIps;\n\n            EventManager.subscribe(EventManager.EventType.EDIT_GRAY_RELEASE_RULES,\n                                   function (context) {\n                                       var branch = context.branch;\n                                       scope.branch = branch;\n\n                                       if (branch.editingRuleItem.clientIpList && branch.editingRuleItem.clientIpList[0] == '*'){\n                                           branch.editingRuleItem.ApplyToAllInstances = true;\n                                       }else {\n                                           branch.editingRuleItem.ApplyToAllInstances = false;\n                                       }\n\n\n                                       $('.rules-ip-selector').select2({\n                                                                           placeholder: \"从实例列表中选择\",\n                                                                           allowClear: true\n                                                                       });\n\n                                       AppUtil.showModal('#rulesModal');\n                                   });\n\n            $('.rules-ip-selector').on('select2:select', function () {\n                addRules(scope.branch);\n            });\n\n            function addRules(branch) {\n                var newRules, selector = $('.rules-ip-selector');\n\n                newRules = selector.select2('data');\n\n                var parsedIPs = [];\n                newRules.forEach(function (rule) {\n                    parsedIPs.push(rule.text);\n                });\n\n                selector.select2(\"val\", \"\");\n                addRuleItemIP(branch, parsedIPs);\n                scope.$apply();\n            }\n\n            function batchAddIPs(branch, newIPs) {\n                if (!newIPs) {\n                    return;\n                }\n                addRuleItemIP(branch, newIPs.split(','));\n            }\n\n            function addRuleItemIP(branch, newIps) {\n                var oldIPs = branch.editingRuleItem.draftIpList;\n                if (newIps && newIps.length > 0) {\n                    newIps.forEach(function (IP) {\n                        if (!AppUtil.checkIPV4(IP)) {\n                            toastr.error(\"不合法的IP地址:\" + IP);\n                        } else if (oldIPs.indexOf(IP) < 0) {\n                            oldIPs.push(IP);\n                        }\n                    })\n                }\n                //remove IP:all\n                oldIPs.forEach(function (IP, index) {\n                    if (IP == \"*\") {\n                        oldIPs.splice(index, 1);\n                    }\n                });\n\n            }\n\n            function removeRule(ruleItem, IP) {\n\n                ruleItem.draftIpList.forEach(function (existedRule, index) {\n                    if (existedRule == IP) {\n                        ruleItem.draftIpList.splice(index, 1);\n                    }\n                })\n\n            }\n\n            function completeEditItem(branch) {\n                scope.completeEditBtnDisable = true;\n\n                if (!branch.editingRuleItem.clientAppId) {\n                    toastr.error(\"灰度的AppId不能为空\");\n                    scope.completeEditBtnDisable = false;\n                    return;\n                }\n\n                if (branch.editingRuleItem.isNew && branch.rules && branch.rules.ruleItems) {\n                    var errorRuleItem = false;\n                    branch.rules.ruleItems.forEach(function (ruleItem) {\n                        if (ruleItem.clientAppId == branch.editingRuleItem.clientAppId) {\n                            toastr.error(\"已经存在AppId=\" + branch.editingRuleItem.clientAppId + \"的规则\");\n                            errorRuleItem = true;\n                        }\n                    });\n                    if (errorRuleItem) {\n                        scope.completeEditBtnDisable = false;\n                        return;\n                    }\n                }\n\n                if (!branch.editingRuleItem.ApplyToAllInstances) {\n                    if (branch.editingRuleItem.draftIpList.length == 0) {\n                        toastr.error(\"IP列表不能为空\");\n                        scope.completeEditBtnDisable = false;\n                        return;\n                    } else {\n                        branch.editingRuleItem.clientIpList = branch.editingRuleItem.draftIpList;\n                    }\n                } else {\n                    branch.editingRuleItem.clientIpList = ['*'];\n                }\n\n                if (!branch.rules) {\n                    branch.rules = {\n                        appId: scope.appId,\n                        clusterName: scope.cluster,\n                        namespaceName: branch.baseInfo.namespaceName,\n                        branchName: branch.baseInfo.clusterName\n                    };\n                }\n\n                if (!branch.rules.ruleItems) {\n                    branch.rules.ruleItems = [];\n                }\n\n                if (branch.editingRuleItem.isNew) {\n                    branch.rules.ruleItems.push(branch.editingRuleItem);\n                }\n\n                branch.editingRuleItem = undefined;\n                scope.toAddIPs = '';\n\n                AppUtil.hideModal('#rulesModal');\n\n                EventManager.emit(EventManager.EventType.UPDATE_GRAY_RELEASE_RULES,\n                                  {\n                                      branch: branch\n                                  }, branch.baseInfo.namespaceName);\n                scope.completeEditBtnDisable = false;\n            }\n\n            function cancelEditItem(branch) {\n                branch.editingRuleItem.isEdit = false;\n                branch.editingRuleItem = undefined;\n                scope.toAddIPs = '';\n                AppUtil.hideModal('#rulesModal');\n            }\n\n            $('#rulesModal').on('shown.bs.modal', function (e) {\n                initSelectIps();\n            });\n\n            function initSelectIps() {\n                scope.selectIps = [];\n                if (!scope.branch.parentNamespace.isPublic ||\n                    scope.branch.parentNamespace.isLinkedNamespace) {\n\n                    scope.branch.editingRuleItem.clientAppId = scope.branch.baseInfo.appId;\n                }\n\n                if (!scope.branch.editingRuleItem.clientAppId) {\n                    return;\n                }\n                InstanceService.findInstancesByNamespace(scope.appId,\n                                                         scope.env,\n                                                         scope.cluster,\n                                                         scope.branch.baseInfo.namespaceName,\n                                                         scope.branch.editingRuleItem.clientAppId,\n                                                         0,\n                                                         2000)\n                    .then(function (result) {\n                        scope.selectIps = result.content;\n                    });\n            }\n\n        }\n    }\n}\n\n\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/directive/item-modal-directive.js",
    "content": "directive_module.directive('itemmodal', itemModalDirective);\n\nfunction itemModalDirective(toastr, $sce, AppUtil, EventManager, ConfigService) {\n    return {\n        restrict: 'E',\n        templateUrl: '../../views/component/item-modal.html',\n        transclude: true,\n        replace: true,\n        scope: {\n            appId: '=',\n            env: '=',\n            cluster: '=',\n            toOperationNamespace: '=',\n            item: '='\n        },\n        link: function (scope) {\n\n            var TABLE_VIEW_OPER_TYPE = {\n                CREATE: 'create',\n                UPDATE: 'update'\n            };\n\n            scope.doItem = doItem;\n            scope.collectSelectedClusters = collectSelectedClusters;\n            scope.showHiddenChars = showHiddenChars;\n\n            $('#itemModal').on('show.bs.modal', function (e) {\n                scope.showHiddenCharsContext = false;\n                scope.hiddenCharCounter = 0;\n                scope.valueWithHiddenChars = $sce.trustAsHtml('');\n            });\n\n            function doItem() {\n\n                if (!scope.item.value) {\n                    scope.item.value = \"\";\n                }\n\n                if (scope.item.tableViewOperType == TABLE_VIEW_OPER_TYPE.CREATE) {\n\n                    //check key unique\n                    var hasRepeatKey = false;\n                    scope.toOperationNamespace.items.forEach(function (item) {\n                        if (!item.isDeleted && scope.item.key == item.item.key) {\n                            toastr.error(\"key=\" + scope.item.key + \" 已存在\");\n                            hasRepeatKey = true;\n                        }\n                    });\n                    if (hasRepeatKey) {\n                        return;\n                    }\n\n                    scope.item.addItemBtnDisabled = true;\n\n                    if (scope.toOperationNamespace.isBranch) {\n                        ConfigService.create_item(scope.appId,\n                                                  scope.env,\n                                                  scope.toOperationNamespace.baseInfo.clusterName,\n                                                  scope.toOperationNamespace.baseInfo.namespaceName,\n                                                  scope.item).then(\n                            function (result) {\n                                toastr.success(\"添加成功,如需生效请发布\");\n                                scope.item.addItemBtnDisabled = false;\n                                AppUtil.hideModal('#itemModal');\n                                EventManager.emit(EventManager.EventType.REFRESH_NAMESPACE,\n                                                  {\n                                                      namespace: scope.toOperationNamespace\n                                                  });\n\n                            }, function (result) {\n                                toastr.error(AppUtil.errorMsg(result), \"添加失败\");\n                                scope.item.addItemBtnDisabled = false;\n                            });\n                    } else {\n                        if (selectedClusters.length == 0) {\n                            toastr.error(\"请选择集群\");\n                            scope.item.addItemBtnDisabled = false;\n                            return;\n                        }\n\n                        selectedClusters.forEach(function (cluster) {\n                            ConfigService.create_item(scope.appId,\n                                                      cluster.env,\n                                                      cluster.name,\n                                                      scope.toOperationNamespace.baseInfo.namespaceName,\n                                                      scope.item).then(\n                                function (result) {\n                                    scope.item.addItemBtnDisabled = false;\n                                    AppUtil.hideModal('#itemModal');\n                                    toastr.success(cluster.env + \" , \" + scope.item.key, \"添加成功,如需生效请发布\");\n                                    if (cluster.env == scope.env &&\n                                        cluster.name == scope.cluster) {\n\n                                        EventManager.emit(EventManager.EventType.REFRESH_NAMESPACE,\n                                                          {\n                                                              namespace: scope.toOperationNamespace\n                                                          });\n                                    }\n                                }, function (result) {\n                                    toastr.error(AppUtil.errorMsg(result), \"添加失败\");\n                                    scope.item.addItemBtnDisabled = false;\n                                });\n                        });\n                    }\n\n                } else {\n\n                    if (!scope.item.comment) {\n                        scope.item.comment = \"\";\n                    }\n\n                    ConfigService.update_item(scope.appId,\n                                              scope.env,\n                                              scope.toOperationNamespace.baseInfo.clusterName,\n                                              scope.toOperationNamespace.baseInfo.namespaceName,\n                                              scope.item).then(\n                        function (result) {\n                            EventManager.emit(EventManager.EventType.REFRESH_NAMESPACE,\n                                              {\n                                                  namespace: scope.toOperationNamespace\n                                              });\n\n                            AppUtil.hideModal('#itemModal');\n\n                            toastr.success(\"更新成功, 如需生效请发布\");\n                        }, function (result) {\n                            toastr.error(AppUtil.errorMsg(result), \"更新失败\");\n                        });\n                }\n\n            }\n\n            var selectedClusters = [];\n\n            function collectSelectedClusters(data) {\n                selectedClusters = data;\n            }\n\n            function showHiddenChars() {\n                var value = scope.item.value;\n                if (!value) {\n                    return;\n                }\n\n                var hiddenCharCounter = 0, valueWithHiddenChars = value;\n\n                for (var i = 0; i < valueWithHiddenChars.length; i++) {\n                    var c = valueWithHiddenChars[i];\n                    if (isHiddenChar(c)) {\n                        valueWithHiddenChars = valueWithHiddenChars.replace(c, viewHiddenChar);\n                        hiddenCharCounter++;\n                    }\n                }\n\n                scope.showHiddenCharsContext = true;\n                scope.hiddenCharCounter = hiddenCharCounter;\n                scope.valueWithHiddenChars = $sce.trustAsHtml(valueWithHiddenChars);\n\n            }\n\n            function isHiddenChar(c) {\n                return c == '\\t' || c == '\\n' || c == ' ';\n            }\n\n            function viewHiddenChar(c) {\n\n                if (c == '\\t') {\n                    return '<mark>#制表符#</mark>';\n                } else if (c == '\\n') {\n                    return '<mark>#换行符#</mark>';\n                } else if (c == ' ') {\n                    return '<mark>#空格#</mark>';\n                }\n\n            }\n        }\n    }\n}\n\n\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/directive/merge-and-publish-modal-directive.js",
    "content": "directive_module.directive('mergeandpublishmodal', mergeAndPublishDirective);\n\nfunction mergeAndPublishDirective(AppUtil, EventManager) {\n    return {\n        restrict: 'E',\n        templateUrl: '../../views/component/merge-and-publish-modal.html',\n        transclude: true,\n        replace: true,\n        scope: {\n            appId: '=',\n            env: '=',\n            cluster: '='\n        },\n        link: function (scope) {\n\n            scope.showReleaseModal = showReleaseModal;\n\n            EventManager.subscribe(EventManager.EventType.MERGE_AND_PUBLISH_NAMESPACE,\n                                   function (context) {\n                                       var branch = context.branch;\n                                       scope.toReleaseNamespace = branch;\n                                       scope.toDeleteBranch = branch;\n                                       scope.isEmergencyPublish =\n                                           context.isEmergencyPublish ? context.isEmergencyPublish : false;\n\n                                       var branchStatusMerge = 2;\n                                       branch.branchStatus = branchStatusMerge;\n                                       branch.mergeAndPublish = true;\n\n                                       AppUtil.showModal('#mergeAndPublishModal');\n                                   });\n\n            function showReleaseModal() {\n                EventManager.emit(EventManager.EventType.PUBLISH_NAMESPACE,\n                                  {\n                                      namespace: scope.toReleaseNamespace,\n                                      isEmergencyPublish: scope.isEmergencyPublish\n                                  });\n            }\n\n        }\n    }\n}\n\n\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/directive/namespace-panel-directive.js",
    "content": "directive_module.directive('apollonspanel', directive);\n\nfunction directive($window, toastr, AppUtil, EventManager, PermissionService, NamespaceLockService,\n                   UserService, CommitService, ReleaseService, InstanceService, NamespaceBranchService, ConfigService) {\n    return {\n        restrict: 'E',\n        templateUrl: '../../views/component/namespace-panel.html',\n        transclude: true,\n        replace: true,\n        scope: {\n            namespace: '=',\n            appId: '=',\n            env: '=',\n            cluster: '=',\n            user: '=',\n            lockCheck: '=',\n            createItem: '=',\n            editItem: '=',\n            preDeleteItem: '=',\n            showText: '=',\n            showNoModifyPermissionDialog: '=',\n            preCreateBranch: '=',\n            preDeleteBranch: '=',\n            showMergeAndPublishGrayTips: '='\n        },\n        link: function (scope) {\n\n            //constants\n            var namespace_view_type = {\n                TEXT: 'text',\n                TABLE: 'table',\n                HISTORY: 'history',\n                INSTANCE: 'instance',\n                RULE: 'rule'\n            };\n\n            var namespace_instance_view_type = {\n                LATEST_RELEASE: 'latest_release',\n                NOT_LATEST_RELEASE: 'not_latest_release',\n                ALL: 'all'\n            };\n\n            var operate_branch_storage_key = 'OperateBranch';\n\n            scope.switchView = switchView;\n            scope.toggleItemSearchInput = toggleItemSearchInput;\n            scope.searchItems = searchItems;\n            scope.loadCommitHistory = loadCommitHistory;\n            scope.toggleTextEditStatus = toggleTextEditStatus;\n            scope.goToSyncPage = goToSyncPage;\n            scope.modifyByText = modifyByText;\n            scope.goToParentAppConfigPage = goToParentAppConfigPage;\n            scope.switchInstanceViewType = switchInstanceViewType;\n            scope.switchBranch = switchBranch;\n            scope.loadInstanceInfo = loadInstanceInfo;\n            scope.refreshInstancesInfo = refreshInstancesInfo;\n            scope.deleteRuleItem = deleteRuleItem;\n            scope.rollback = rollback;\n\n            scope.publish = publish;\n            scope.mergeAndPublish = mergeAndPublish;\n            scope.addRuleItem = addRuleItem;\n            scope.editRuleItem = editRuleItem;\n\n            scope.deleteNamespace = deleteNamespace;\n\n            var subscriberId = EventManager.subscribe(EventManager.EventType.UPDATE_GRAY_RELEASE_RULES,\n                                                      function (context) {\n                                                          useRules(context.branch);\n                                                      }, scope.namespace.baseInfo.namespaceName);\n\n            scope.$on('$destroy', function () {\n                EventManager.unsubscribe(EventManager.EventType.UPDATE_GRAY_RELEASE_RULES,\n                                         subscriberId, scope.namespace.baseInfo.namespaceName);\n            });\n\n            init();\n\n            function init() {\n                initNamespace(scope.namespace);\n                initOther();\n            }\n\n            function initNamespace(namespace, viewType) {\n                namespace.hasBranch = false;\n                namespace.isBranch = false;\n                namespace.isLinkedNamespace =\n                    namespace.isPublic ? namespace.parentAppId != namespace.baseInfo.appId : false;\n                namespace.displayControl = {\n                    currentOperateBranch: 'master',\n                    showSearchInput: false,\n                    show: true\n                };\n                namespace.viewItems = namespace.items;\n                namespace.isPropertiesFormat = namespace.format == 'properties';\n                namespace.isTextEditing = false;\n                namespace.instanceViewType = namespace_instance_view_type.LATEST_RELEASE;\n                namespace.latestReleaseInstancesPage = 0;\n                namespace.allInstances = [];\n                namespace.allInstancesPage = 0;\n                namespace.commitChangeBtnDisabled = false;\n\n                generateNamespaceId(namespace);\n                initNamespaceBranch(namespace);\n                initNamespaceViewName(namespace);\n                initNamespaceLock(namespace);\n                initNamespaceInstancesCount(namespace);\n                initPermission(namespace);\n                initLinkedNamespace(namespace);\n                loadInstanceInfo(namespace);\n\n                function initNamespaceBranch(namespace) {\n                    NamespaceBranchService.findNamespaceBranch(scope.appId, scope.env,\n                                                               namespace.baseInfo.clusterName,\n                                                               namespace.baseInfo.namespaceName)\n                        .then(function (result) {\n\n                            if (!result.baseInfo) {\n                                return;\n                            }\n\n                            //namespace has branch\n                            namespace.hasBranch = true;\n                            namespace.branchName = result.baseInfo.clusterName;\n                            //init branch\n                            namespace.branch = result;\n                            namespace.branch.isBranch = true;\n                            namespace.branch.parentNamespace = namespace;\n                            namespace.branch.viewType = namespace_view_type.TABLE;\n                            namespace.branch.isPropertiesFormat = namespace.format == 'properties';\n                            namespace.branch.allInstances = [];//master namespace all instances\n                            namespace.branch.latestReleaseInstances = [];\n                            namespace.branch.latestReleaseInstancesPage = 0;\n                            namespace.branch.instanceViewType = namespace_instance_view_type.LATEST_RELEASE;\n                            namespace.branch.hasLoadInstances = false;\n                            namespace.branch.displayControl = {\n                                show: true\n                            };\n\n                            generateNamespaceId(namespace.branch);\n                            initBranchItems(namespace.branch);\n                            initRules(namespace.branch);\n                            loadInstanceInfo(namespace.branch);\n                            initNamespaceLock(namespace.branch);\n                            initPermission(namespace);\n                            initUserOperateBranchScene(namespace);\n                        });\n\n                    function initBranchItems(branch) {\n                        branch.masterItems = [];\n                        branch.branchItems = [];\n\n                        var masterItemsMap = {};\n                        branch.parentNamespace.items.forEach(function (item) {\n                            if (item.item.key) {\n                                masterItemsMap[item.item.key] = item;\n                            }\n                        });\n\n                        var branchItemsMap = {};\n\n                        var itemModifiedCnt = 0;\n                        branch.items.forEach(function (item) {\n                            var key = item.item.key;\n                            var masterItem = masterItemsMap[key];\n\n                            //modify master item and set item's masterReleaseValue\n                            if (masterItem) {\n                                if (masterItem.isModified && masterItem.oldValue) {\n                                    item.masterReleaseValue = masterItem.oldValue;\n                                } else if (masterItem.item.value) {\n                                    item.masterReleaseValue = masterItem.item.value;\n                                }\n\n                            } else {//delete branch item\n                                item.masterReleaseValue = '';\n                            }\n\n                            //delete master item. ignore\n                            if (item.isDeleted && masterItem) {\n                                if (item.masterReleaseValue != item.oldValue) {\n                                    itemModifiedCnt++;\n                                    branch.branchItems.push(item);\n                                }\n                            } else {//branch's item\n                                branchItemsMap[key] = item;\n\n                                if (item.isModified) {\n                                    itemModifiedCnt++;\n                                }\n                                branch.branchItems.push(item);\n                            }\n\n                        });\n                        branch.itemModifiedCnt = itemModifiedCnt;\n\n                        branch.parentNamespace.items.forEach(function (item) {\n                            if (item.item.key) {\n                                if (!branchItemsMap[item.item.key]) {\n                                    branch.masterItems.push(item);\n                                } else {\n                                    item.hasBranchValue = true;\n                                }\n                            }\n                        })\n\n                    }\n                }\n\n                function generateNamespaceId(namespace) {\n                    namespace.id = Math.random().toString(36).substr(2);\n                }\n\n                function initPermission(namespace) {\n\n                    PermissionService.has_modify_namespace_permission(\n                        scope.appId,\n                        namespace.baseInfo.namespaceName)\n                        .then(function (result) {\n                            //branch has same permission\n                            namespace.hasModifyPermission = result.hasPermission;\n                            if (namespace.branch) {\n                                namespace.branch.hasModifyPermission = result.hasPermission;\n                            }\n                        });\n\n                    PermissionService.has_release_namespace_permission(\n                        scope.appId,\n                        namespace.baseInfo.namespaceName)\n                        .then(function (result) {\n                            //branch has same permission\n                            namespace.hasReleasePermission = result.hasPermission;\n                            if (namespace.branch) {\n                                namespace.branch.hasReleasePermission = result.hasPermission;\n                            }\n                        });\n                }\n\n                function initLinkedNamespace(namespace) {\n                    if (!namespace.isPublic || !namespace.isLinkedNamespace || namespace.format != 'properties') {\n                        return;\n                    }\n                    //load public namespace\n                    ConfigService.load_public_namespace_for_associated_namespace(scope.env, scope.appId, scope.cluster,\n                                                                                 namespace.baseInfo.namespaceName)\n                        .then(function (result) {\n                            var publicNamespace = result;\n                            namespace.publicNamespace = publicNamespace;\n\n                            var linkNamespaceItemKeys = [];\n                            namespace.items.forEach(function (item) {\n                                var key = item.item.key;\n                                linkNamespaceItemKeys.push(key);\n                            });\n\n                            publicNamespace.viewItems = [];\n                            publicNamespace.items.forEach(function (item) {\n                                var key = item.item.key;\n\n                                if (key) {\n                                    publicNamespace.viewItems.push(item);\n                                }\n\n                                item.covered = linkNamespaceItemKeys.indexOf(key) >= 0;\n\n                                if (item.isModified || item.isDeleted) {\n                                    publicNamespace.isModified = true;\n                                } else if (key) {\n                                    publicNamespace.hasPublishedItem = true;\n                                }\n                            });\n\n                        });\n\n                }\n\n                function initNamespaceViewName(namespace) {\n                    //namespace view name hide suffix\n                    namespace.viewName =\n                        namespace.baseInfo.namespaceName.replace(\".xml\", \"\").replace(\n                            \".properties\", \"\").replace(\".json\", \"\").replace(\".yml\", \"\")\n                            .replace(\".yaml\", \"\");\n\n                    if (!viewType) {\n                        if (namespace.isPropertiesFormat) {\n                            switchView(namespace, namespace_view_type.TABLE);\n                        } else {\n                            switchView(namespace, namespace_view_type.TEXT);\n                        }\n                    } else if (viewType == namespace_view_type.TABLE) {\n                        namespace.viewType = namespace_view_type.TABLE;\n                    }\n                }\n\n                function initNamespaceLock(namespace) {\n                    NamespaceLockService.get_namespace_lock(scope.appId, scope.env,\n                                                            namespace.baseInfo.clusterName,\n                                                            namespace.baseInfo.namespaceName)\n                        .then(function (result) {\n                            namespace.lockOwner = result.lockOwner;\n                            namespace.isEmergencyPublishAllowed = result.isEmergencyPublishAllowed;\n                        });\n\n                }\n\n                function initUserOperateBranchScene(namespace) {\n                    var operateBranchStorage = JSON.parse(localStorage.getItem(operate_branch_storage_key));\n                    var namespaceId = [scope.appId, scope.env, scope.cluster, namespace.baseInfo.namespaceName].join(\n                        \"+\");\n                    if (!operateBranchStorage) {\n                        operateBranchStorage = {};\n                    }\n                    if (!operateBranchStorage[namespaceId]) {\n                        operateBranchStorage[namespaceId] = namespace.branchName;\n                    }\n\n                    localStorage.setItem(operate_branch_storage_key, JSON.stringify(operateBranchStorage));\n\n                    switchBranch(operateBranchStorage[namespaceId]);\n\n                }\n\n            }\n\n            function initNamespaceInstancesCount(namespace) {\n                InstanceService.getInstanceCountByNamespace(scope.appId,\n                                                            scope.env,\n                                                            scope.cluster,\n                                                            namespace.baseInfo.namespaceName)\n                    .then(function (result) {\n                        namespace.instancesCount = result.num;\n                    })\n            }\n\n            function initOther() {\n\n                UserService.load_user().then(function (result) {\n                    scope.currentUser = result.userId;\n                });\n\n                PermissionService.has_assign_user_permission(scope.appId)\n                    .then(function (result) {\n                        scope.hasAssignUserPermission = result.hasPermission;\n                    }, function (result) {\n\n                    });\n            }\n\n            function switchBranch(branchName) {\n                if (branchName != 'master') {\n                    scope.namespace.branch.displayControl.show = true;\n                    initRules(scope.namespace.branch);\n                } else {\n                    scope.namespace.displayControl.show = true;\n                }\n                scope.namespace.displayControl.currentOperateBranch = branchName;\n\n                //save to local storage\n                var operateBranchStorage = JSON.parse(localStorage.getItem(operate_branch_storage_key));\n                if (!operateBranchStorage) {\n                    return;\n                }\n                var namespaceId = [scope.appId, scope.env, scope.cluster, scope.namespace.baseInfo.namespaceName].join(\n                    \"+\");\n                operateBranchStorage[namespaceId] = branchName;\n                localStorage.setItem(operate_branch_storage_key, JSON.stringify(operateBranchStorage));\n\n            }\n\n            function switchView(namespace, viewType) {\n                namespace.viewType = viewType;\n                if (namespace_view_type.TEXT == viewType) {\n                    namespace.text = parseModel2Text(namespace);\n                } else if (namespace_view_type.TABLE == viewType) {\n\n                } else if (namespace_view_type.HISTORY == viewType) {\n                    loadCommitHistory(namespace);\n                } else if (namespace_view_type.INSTANCE == viewType) {\n                    refreshInstancesInfo(namespace);\n                }\n            }\n\n            function switchInstanceViewType(namespace, type) {\n                namespace.instanceViewType = type;\n                loadInstanceInfo(namespace);\n            }\n\n            function loadCommitHistory(namespace) {\n                if (!namespace.commits) {\n                    namespace.commits = [];\n                    namespace.commitPage = 0;\n                }\n\n                var size = 10;\n                CommitService.find_commits(scope.appId,\n                                           scope.env,\n                                           namespace.baseInfo.clusterName,\n                                           namespace.baseInfo.namespaceName,\n                                           namespace.commitPage,\n                                           size)\n                    .then(function (result) {\n                        if (result.length < size) {\n                            namespace.hasLoadAllCommit = true;\n                        }\n\n                        for (var i = 0; i < result.length; i++) {\n                            //to json\n                            result[i].changeSets = JSON.parse(result[i].changeSets);\n                            namespace.commits.push(result[i]);\n                        }\n                        namespace.commitPage += 1;\n                    }, function (result) {\n                        toastr.error(AppUtil.errorMsg(result), \"加载修改历史记录出错\");\n                    });\n            }\n\n            function loadInstanceInfo(namespace) {\n\n                var size = 20;\n                if (namespace.isBranch) {\n                    size = 2000;\n                }\n\n                var type = namespace.instanceViewType;\n\n                if (namespace_instance_view_type.LATEST_RELEASE == type) {\n                    if (!namespace.latestRelease) {\n                        ReleaseService.findLatestActiveRelease(scope.appId,\n                                                               scope.env,\n                                                               namespace.baseInfo.clusterName,\n                                                               namespace.baseInfo.namespaceName)\n                            .then(function (result) {\n                                namespace.isLatestReleaseLoaded = true;\n\n                                if (!result) {\n                                    namespace.latestReleaseInstances = {};\n                                    namespace.latestReleaseInstances.total = 0;\n                                    return;\n                                }\n                                namespace.latestRelease = result;\n                                InstanceService.findInstancesByRelease(scope.env,\n                                                                       namespace.latestRelease.id,\n                                                                       namespace.latestReleaseInstancesPage,\n                                                                       size)\n                                    .then(function (result) {\n                                        namespace.latestReleaseInstances = result;\n                                        namespace.latestReleaseInstancesPage++;\n                                    })\n                            });\n                    } else {\n                        InstanceService.findInstancesByRelease(scope.env,\n                                                               namespace.latestRelease.id,\n                                                               namespace.latestReleaseInstancesPage,\n                                                               size)\n                            .then(function (result) {\n                                if (result && result.content.length) {\n                                    namespace.latestReleaseInstancesPage++;\n                                    result.content.forEach(function (instance) {\n                                        namespace.latestReleaseInstances.content.push(\n                                            instance);\n                                    })\n                                }\n\n                            })\n                    }\n\n                } else if (namespace_instance_view_type.NOT_LATEST_RELEASE == type) {\n                    if (!namespace.latestRelease) {\n                        return;\n                    }\n                    InstanceService.findByReleasesNotIn(scope.appId,\n                                                        scope.env,\n                                                        scope.cluster,\n                                                        namespace.baseInfo.namespaceName,\n                                                        namespace.latestRelease.id)\n                        .then(function (result) {\n                            if (!result || result.length == 0) {\n                                return\n                            }\n\n                            var groupedInstances = {},\n                                notLatestReleases = [];\n\n                            result.forEach(function (instance) {\n                                var configs = instance.configs;\n                                if (configs && configs.length > 0) {\n                                    configs.forEach(function (instanceConfig) {\n                                        var release = instanceConfig.release;\n                                        //filter dirty data\n                                        if (!release) {\n                                            return;\n                                        }\n                                        if (!groupedInstances[release.id]) {\n                                            groupedInstances[release.id] = [];\n                                            notLatestReleases.push(release);\n                                        }\n                                        groupedInstances[release.id].push(instance);\n                                    })\n                                }\n                            });\n\n                            namespace.notLatestReleases = notLatestReleases;\n                            namespace.notLatestReleaseInstances = groupedInstances;\n                        })\n\n                } else {\n                    InstanceService.findInstancesByNamespace(scope.appId,\n                                                             scope.env,\n                                                             scope.cluster,\n                                                             namespace.baseInfo.namespaceName,\n                                                             '',\n                                                             namespace.allInstancesPage)\n                        .then(function (result) {\n                            if (result && result.content.length) {\n                                namespace.allInstancesPage++;\n                                result.content.forEach(function (instance) {\n                                    namespace.allInstances.push(instance);\n                                })\n                            }\n                        });\n                }\n\n            }\n\n            function refreshInstancesInfo(namespace) {\n\n                namespace.instanceViewType = namespace_instance_view_type.LATEST_RELEASE;\n\n                namespace.latestReleaseInstancesPage = 0;\n                namespace.latestReleaseInstances = [];\n                namespace.latestRelease = undefined;\n\n                if (!namespace.isBranch) {\n                    namespace.notLatestReleaseNames = [];\n                    namespace.notLatestReleaseInstances = {};\n\n                    namespace.allInstancesPage = 0;\n                    namespace.allInstances = [];\n                }\n\n                initNamespaceInstancesCount(namespace);\n                loadInstanceInfo(namespace);\n            }\n\n            function initRules(branch) {\n\n                NamespaceBranchService.findBranchGrayRules(scope.appId,\n                                                           scope.env,\n                                                           scope.cluster,\n                                                           scope.namespace.baseInfo.namespaceName,\n                                                           branch.baseInfo.clusterName)\n                    .then(function (result) {\n\n                        if (result.appId) {\n                            branch.rules = result;\n                        }\n\n                    }, function (result) {\n                        toastr.error(AppUtil.errorMsg(result), \"加载灰度规则出错\");\n                    });\n\n            }\n\n            function addRuleItem(branch) {\n                var newRuleItem = {\n                    clientAppId: !branch.parentNamespace.isPublic ? branch.baseInfo.appId : '',\n                    clientIpList: [],\n                    draftIpList: [],\n                    isNew: true\n                };\n\n                branch.editingRuleItem = newRuleItem;\n\n                EventManager.emit(EventManager.EventType.EDIT_GRAY_RELEASE_RULES, {\n                    branch: branch\n                });\n            }\n\n            function editRuleItem(branch, ruleItem) {\n                ruleItem.isNew = false;\n                ruleItem.draftIpList = _.clone(ruleItem.clientIpList);\n                branch.editingRuleItem = ruleItem;\n\n                EventManager.emit(EventManager.EventType.EDIT_GRAY_RELEASE_RULES, {\n                    branch: branch\n                });\n            }\n\n            function deleteRuleItem(branch, ruleItem) {\n                branch.rules.ruleItems.forEach(function (item, index) {\n                    if (item.clientAppId == ruleItem.clientAppId) {\n                        branch.rules.ruleItems.splice(index, 1);\n                        toastr.success(\"删除成功\");\n                    }\n                });\n\n                useRules(branch);\n            }\n\n            function useRules(branch) {\n                NamespaceBranchService.updateBranchGrayRules(scope.appId,\n                                                             scope.env,\n                                                             scope.cluster,\n                                                             scope.namespace.baseInfo.namespaceName,\n                                                             branch.baseInfo.clusterName,\n                                                             branch.rules\n                )\n                    .then(function (result) {\n                        toastr.success('灰度规则更新成功');\n\n                        //show tips if branch has not release configs\n                        if (branch.itemModifiedCnt) {\n                            AppUtil.showModal(\"#updateRuleTips\");\n                        }\n\n                        setTimeout(function () {\n                            refreshInstancesInfo(branch);\n                        }, 1500);\n\n                    }, function (result) {\n                        AppUtil.showErrorMsg(result, \"灰度规则更新失败\");\n                    })\n            }\n\n            function toggleTextEditStatus(namespace) {\n                if (!scope.lockCheck(namespace)) {\n                    return;\n                }\n                namespace.isTextEditing = !namespace.isTextEditing;\n                if (namespace.isTextEditing) {//切换为编辑状态\n                    namespace.commited = false;\n                    namespace.backupText = namespace.text;\n                    namespace.editText = parseModel2Text(namespace);\n\n                } else {\n                    if (!namespace.commited) {//取消编辑,则复原\n                        namespace.text = namespace.backupText;\n                    }\n                }\n            }\n\n            function goToSyncPage(namespace) {\n                if (!scope.lockCheck(namespace)) {\n                    return false;\n                }\n                $window.location.href =\n                    \"config/sync.html?#/appid=\" + scope.appId + \"&env=\"\n                    + scope.env + \"&clusterName=\"\n                    + scope.cluster\n                    + \"&namespaceName=\" + namespace.baseInfo.namespaceName;\n            }\n\n            function modifyByText(namespace) {\n                var model = {\n                    configText: namespace.editText,\n                    namespaceId: namespace.baseInfo.id,\n                    format: namespace.format\n                };\n\n                //prevent repeat submit\n                if (namespace.commitChangeBtnDisabled) {\n                    return;\n                }\n                namespace.commitChangeBtnDisabled = true;\n                ConfigService.modify_items(scope.appId,\n                                           scope.env,\n                                           scope.cluster,\n                                           namespace.baseInfo.namespaceName,\n                                           model).then(\n                    function (result) {\n                        toastr.success(\"更新成功, 如需生效请发布\");\n                        //refresh all namespace items\n                        EventManager.emit(EventManager.EventType.REFRESH_NAMESPACE,\n                                          {\n                                              namespace: namespace\n                                          });\n                        return true;\n\n                    }, function (result) {\n                        toastr.error(AppUtil.errorMsg(result), \"更新失败\");\n                        namespace.commitChangeBtnDisabled = false;\n                        return false;\n                    }\n                );\n                namespace.commited = true;\n                toggleTextEditStatus(namespace);\n            }\n\n            function goToParentAppConfigPage(namespace) {\n                $window.location.href = \"/config.html?#/appid=\" + namespace.parentAppId;\n                $window.location.reload();\n            }\n\n            function parseModel2Text(namespace) {\n\n                if (namespace.items.length == 0) {\n                    namespace.itemCnt = 0;\n                    return \"\";\n                }\n\n                //文件模式\n                if (!namespace.isPropertiesFormat) {\n                    return parseNotPropertiesText(namespace);\n                } else {\n                    return parsePropertiesText(namespace);\n                }\n\n            }\n\n            function parseNotPropertiesText(namespace) {\n                var text = namespace.items[0].item.value;\n                var lineNum = text.split(\"\\n\").length;\n                namespace.itemCnt = lineNum;\n                return text;\n            }\n\n            function parsePropertiesText(namespace) {\n                var result = \"\";\n                var itemCnt = 0;\n                namespace.items.forEach(function (item) {\n                    //deleted key\n                    if (!item.item.dataChangeLastModifiedBy) {\n                        return;\n                    }\n                    if (item.item.key) {\n                        //use string \\n to display as new line\n                        var itemValue = item.item.value.replace(/\\n/g, \"\\\\n\");\n\n                        result +=\n                            item.item.key + \" = \" + itemValue + \"\\n\";\n                    } else {\n                        result += item.item.comment + \"\\n\";\n                    }\n                    itemCnt++;\n                });\n\n                namespace.itemCnt = itemCnt;\n                return result;\n            }\n\n            function toggleItemSearchInput(namespace) {\n                namespace.displayControl.showSearchInput = !namespace.displayControl.showSearchInput;\n            }\n\n            function searchItems(namespace) {\n                var searchKey = namespace.searchKey.toLowerCase();\n                var items = [];\n                namespace.items.forEach(function (item) {\n                    var key = item.item.key;\n                    if (key && key.toLowerCase().indexOf(searchKey) >= 0) {\n                        items.push(item);\n                    }\n                });\n                namespace.viewItems = items;\n            }\n\n            //normal release and gray release\n            function publish(namespace) {\n\n                if (!namespace.hasReleasePermission) {\n                    AppUtil.showModal('#releaseNoPermissionDialog');\n                    return;\n                } else if (namespace.lockOwner && scope.user == namespace.lockOwner) {\n                    //can not publish if config modified by himself\n                    EventManager.emit(EventManager.EventType.PUBLISH_DENY, {\n                        namespace: namespace,\n                        mergeAndPublish: false\n                    });\n                    return;\n                }\n\n                if (namespace.isBranch) {\n                    namespace.mergeAndPublish = false;\n                }\n\n                EventManager.emit(EventManager.EventType.PUBLISH_NAMESPACE,\n                                  {\n                                      namespace: namespace\n                                  });\n            }\n\n            function mergeAndPublish(branch) {\n                var parentNamespace = branch.parentNamespace;\n                if (!parentNamespace.hasReleasePermission) {\n                    AppUtil.showModal('#releaseNoPermissionDialog');\n                } else if (parentNamespace.itemModifiedCnt > 0) {\n                    AppUtil.showModal('#mergeAndReleaseDenyDialog');\n                } else if (branch.lockOwner && scope.user == branch.lockOwner) {\n                    EventManager.emit(EventManager.EventType.PUBLISH_DENY, {\n                        namespace: branch,\n                        mergeAndPublish: true\n                    });\n                } else {\n                    EventManager.emit(EventManager.EventType.MERGE_AND_PUBLISH_NAMESPACE, {branch: branch});\n                }\n            }\n\n            function rollback(namespace) {\n                EventManager.emit(EventManager.EventType.PRE_ROLLBACK_NAMESPACE, {namespace: namespace});\n            }\n\n            function deleteNamespace(namespace) {\n                EventManager.emit(EventManager.EventType.PRE_DELETE_NAMESPACE, {namespace: namespace});\n            }\n\n            //theme: https://github.com/ajaxorg/ace-builds/tree/ba3b91e04a5aa559d56ac70964f9054baa0f4caf/src-min\n            scope.aceConfig = {\n                $blockScrolling: Infinity,\n                showPrintMargin: false,\n                theme: 'eclipse',\n                mode: scope.namespace.format === 'yml' ? 'yaml' : scope.namespace.format,\n                onLoad: function (_editor) {\n                    _editor.$blockScrolling = Infinity;\n                    _editor.setOptions({\n                                           fontSize: 13,\n                                           minLines: 10,\n                                           maxLines: 20\n                                       })\n                }\n            };\n\n            setTimeout(function () {\n                scope.namespace.show = true;\n            }, 70);\n\n\n        }\n    }\n}\n\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/directive/publish-deny-modal-directive.js",
    "content": "directive_module.directive('publishdenymodal', publishDenyDirective);\n\nfunction publishDenyDirective(AppUtil, EventManager) {\n    return {\n        restrict: 'E',\n        templateUrl: '../../views/component/publish-deny-modal.html',\n        transclude: true,\n        replace: true,\n        scope: {\n            env: \"=\"\n        },\n        link: function (scope) {\n            var MODAL_ID = \"#publishDenyModal\";\n\n            EventManager.subscribe(EventManager.EventType.PUBLISH_DENY, function (context) {\n                scope.toReleaseNamespace = context.namespace;\n                scope.mergeAndPublish = !!context.mergeAndPublish;\n                AppUtil.showModal(MODAL_ID);\n            });\n\n            scope.emergencyPublish = emergencyPublish;\n\n            function emergencyPublish() {\n                AppUtil.hideModal(MODAL_ID);\n\n                EventManager.emit(EventManager.EventType.EMERGENCY_PUBLISH,\n                                  {\n                                      mergeAndPublish: scope.mergeAndPublish,\n                                      namespace: scope.toReleaseNamespace\n                                  });\n\n            }\n        }\n    }\n}\n\n\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/directive/release-modal-directive.js",
    "content": "directive_module.directive('releasemodal', releaseModalDirective);\n\nfunction releaseModalDirective(toastr, AppUtil, EventManager, ReleaseService, NamespaceBranchService) {\n    return {\n        restrict: 'E',\n        templateUrl: '../../views/component/release-modal.html',\n        transclude: true,\n        replace: true,\n        scope: {\n            appId: '=',\n            env: '=',\n            cluster: '='\n        },\n        link: function (scope) {\n\n            scope.switchReleaseChangeViewType = switchReleaseChangeViewType;\n            scope.release = release;\n\n            scope.releaseBtnDisabled = false;\n            scope.releaseChangeViewType = 'change';\n            scope.releaseComment = '';\n            scope.isEmergencyPublish = false;\n            \n            EventManager.subscribe(EventManager.EventType.PUBLISH_NAMESPACE,\n                                   function (context) {\n\n                                       var namespace = context.namespace;\n                                       scope.toReleaseNamespace = context.namespace;\n                                       scope.isEmergencyPublish = !!context.isEmergencyPublish;\n\n                                       var date = new Date().Format(\"yyyyMMddhhmmss\");\n                                       if (namespace.mergeAndPublish) {\n                                           namespace.releaseTitle = date + \"-gray-release-merge-to-master\";\n                                       } else if (namespace.isBranch) {\n                                           namespace.releaseTitle = date + \"-gray\";\n                                       } else {\n                                           namespace.releaseTitle = date + \"-release\";\n                                       }\n\n                                       AppUtil.showModal('#releaseModal');\n                                   });\n\n            function release() {\n                if (scope.toReleaseNamespace.mergeAndPublish) {\n                    mergeAndPublish();\n                } else if (scope.toReleaseNamespace.isBranch) {\n                    grayPublish();\n                } else {\n                    publish();\n                }\n\n            }\n\n            function publish() {\n                scope.releaseBtnDisabled = true;\n                ReleaseService.publish(scope.appId, scope.env,\n                                       scope.toReleaseNamespace.baseInfo.clusterName,\n                                       scope.toReleaseNamespace.baseInfo.namespaceName,\n                                       scope.toReleaseNamespace.releaseTitle,\n                                       scope.releaseComment,\n                                       scope.isEmergencyPublish).then(\n                    function (result) {\n                        AppUtil.hideModal('#releaseModal');\n                        toastr.success(\"发布成功\");\n\n                        scope.releaseBtnDisabled = false;\n\n                        EventManager.emit(EventManager.EventType.REFRESH_NAMESPACE,\n                                          {\n                                              namespace: scope.toReleaseNamespace\n                                          })\n\n                    }, function (result) {\n                        scope.releaseBtnDisabled = false;\n                        toastr.error(AppUtil.errorMsg(result), \"发布失败\");\n\n                    }\n                );\n\n            }\n\n            function grayPublish() {\n                scope.releaseBtnDisabled = true;\n                ReleaseService.grayPublish(scope.appId, scope.env,\n                                           scope.toReleaseNamespace.parentNamespace.baseInfo.clusterName,\n                                           scope.toReleaseNamespace.baseInfo.namespaceName,\n                                           scope.toReleaseNamespace.baseInfo.clusterName,\n                                           scope.toReleaseNamespace.releaseTitle,\n                                           scope.releaseComment,\n                                           scope.isEmergencyPublish).then(\n                    function (result) {\n                        AppUtil.hideModal('#releaseModal');\n                        toastr.success(\"灰度发布成功\");\n\n                        scope.releaseBtnDisabled = false;\n\n                        //refresh item status\n                        scope.toReleaseNamespace.branchItems.forEach(function (item, index) {\n                            if (item.isDeleted) {\n                                scope.toReleaseNamespace.branchItems.splice(index, 1);\n                            } else {\n                                item.isModified = false;\n                            }\n                        });\n                        //reset namespace status\n                        scope.toReleaseNamespace.itemModifiedCnt = 0;\n                        scope.toReleaseNamespace.lockOwner = undefined;\n\n                        //check rules\n                        if (!scope.toReleaseNamespace.rules\n                            || !scope.toReleaseNamespace.rules.ruleItems\n                            || !scope.toReleaseNamespace.rules.ruleItems.length) {\n\n                            scope.toReleaseNamespace.viewType = 'rule';\n                            AppUtil.showModal('#grayReleaseWithoutRulesTips');\n                        }\n\n                    }, function (result) {\n                        scope.releaseBtnDisabled = false;\n                        toastr.error(AppUtil.errorMsg(result), \"灰度发布失败\");\n\n                    });\n            }\n\n            function mergeAndPublish() {\n\n                NamespaceBranchService.mergeAndReleaseBranch(scope.appId,\n                                                             scope.env,\n                                                             scope.cluster,\n                                                             scope.toReleaseNamespace.baseInfo.namespaceName,\n                                                             scope.toReleaseNamespace.baseInfo.clusterName,\n                                                             scope.toReleaseNamespace.releaseTitle,\n                                                             scope.releaseComment,\n                                                             scope.isEmergencyPublish,\n                                                             scope.toReleaseNamespace.mergeAfterDeleteBranch)\n                    .then(function (result) {\n\n                        toastr.success(\"全量发布成功\");\n\n                        EventManager.emit(EventManager.EventType.REFRESH_NAMESPACE,\n                                          {\n                                              namespace: scope.toReleaseNamespace\n                                          })\n\n                    }, function (result) {\n                        toastr.error(AppUtil.errorMsg(result), \"全量发布失败\");\n                    });\n\n                AppUtil.hideModal('#releaseModal');\n            }\n\n            function switchReleaseChangeViewType(type) {\n                scope.releaseChangeViewType = type;\n            }\n        }\n    }\n}\n\n\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/directive/rollback-modal-directive.js",
    "content": "directive_module.directive('rollbackmodal', rollbackModalDirective);\n\nfunction rollbackModalDirective(AppUtil, EventManager, ReleaseService, toastr) {\n    return {\n        restrict: 'E',\n        templateUrl: '../../views/component/rollback-modal.html',\n        transclude: true,\n        replace: true,\n        scope: {\n            appId: '=',\n            env: '=',\n            cluster: '='\n        },\n        link: function (scope) {\n\n            scope.showRollbackAlertDialog = showRollbackAlertDialog;\n\n            EventManager.subscribe(EventManager.EventType.PRE_ROLLBACK_NAMESPACE,\n            function (context) {\n                preRollback(context.namespace);\n            });\n\n            EventManager.subscribe(EventManager.EventType.ROLLBACK_NAMESPACE,\n                                   function (context) {\n                                       rollback();\n                                   });\n\n            function preRollback(namespace) {\n                scope.toRollbackNamespace = namespace;\n                //load latest two active releases\n                ReleaseService.findActiveReleases(scope.appId,\n                                                  scope.env,\n                                                  scope.cluster,\n                                                  scope.toRollbackNamespace.baseInfo.namespaceName,\n                                                  0, 2)\n                    .then(function (result) {\n                        if (result.length <= 1) {\n                            toastr.error(\"没有可以回滚的发布历史\");\n                            return;\n                        }\n                        scope.toRollbackNamespace.firstRelease = result[0];\n                        scope.toRollbackNamespace.secondRelease = result[1];\n\n                        ReleaseService.compare(scope.env,\n                                               scope.toRollbackNamespace.firstRelease.id,\n                                               scope.toRollbackNamespace.secondRelease.id)\n                            .then(function (result) {\n                                scope.toRollbackNamespace.releaseCompareResult = result.changes;\n\n                                AppUtil.showModal('#rollbackModal');\n                            })\n                    });\n            }\n\n            function rollback() {\n                scope.toRollbackNamespace.rollbackBtnDisabled = true;\n                ReleaseService.rollback(scope.env,\n                                        scope.toRollbackNamespace.firstRelease.id)\n                    .then(function (result) {\n                        toastr.success(\"回滚成功\");\n                        scope.toRollbackNamespace.rollbackBtnDisabled = false;\n                        AppUtil.hideModal('#rollbackModal');\n                        EventManager.emit(EventManager.EventType.REFRESH_NAMESPACE,\n                                          {\n                                              namespace:scope.toRollbackNamespace\n                                          });\n                    }, function (result) {\n                        scope.toRollbackNamespace.rollbackBtnDisabled = false;\n                        AppUtil.showErrorMsg(result, \"回滚失败\");\n                    })\n            }\n\n            function showRollbackAlertDialog() {\n                AppUtil.hideModal(\"#rollbackModal\");\n                AppUtil.showModal(\"#rollbackAlertDialog\");\n            }\n        }\n    }\n}\n\n\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/directive/show-text-modal-directive.js",
    "content": "directive_module.directive('showtextmodal', showTextModalDirective);\n\nfunction showTextModalDirective() {\n    return {\n        restrict: 'E',\n        templateUrl: '../../views/component/show-text-modal.html',\n        transclude: true,\n        replace: true,\n        scope: {\n            text: '='\n        },\n        link: function (scope) {\n            scope.$watch('text', init);\n\n            function init() {\n                scope.jsonObject = undefined;\n                if (isJsonText(scope.text)) {\n                    scope.jsonObject = JSON.parse(scope.text);\n                }\n            }\n\n            function isJsonText(text) {\n                try {\n                    JSON.parse(text);\n                } catch (e) {\n                    return false;\n                }\n                return true;\n            }\n        }\n    }\n}\n\n\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/services/AppService.js",
    "content": "appService.service('AppService', ['$resource', '$q', function ($resource, $q) {\n    var app_resource = $resource('/apps/:appId', {}, {\n        find_apps: {\n            method: 'GET',\n            isArray: true,\n            url: '/apps'\n        },\n        find_app_by_owner: {\n            method: 'GET',\n            isArray: true,\n            url: '/apps/by-owner'\n        },\n        load_navtree: {\n            method: 'GET',\n            isArray: false,\n            url: '/apps/:appId/navtree'\n        },\n        load_app: {\n            method: 'GET',\n            isArray: false\n        },\n        create_app: {\n            method: 'POST',\n            url: '/apps'\n        },\n        update_app: {\n            method: 'PUT',\n            url: '/apps/:appId'\n        },\n        create_app_remote: {\n            method: 'POST',\n            url: '/apps/envs/:env'\n        },\n        find_miss_envs: {\n            method: 'GET',\n            url: '/apps/:appId/miss_envs'\n        }\n    });\n    return {\n        find_apps: function (appIds) {\n            if (!appIds) {\n                appIds = '';\n            }\n            var d = $q.defer();\n            app_resource.find_apps({appIds: appIds}, function (result) {\n                d.resolve(result);\n            }, function (result) {\n                d.reject(result);\n            });\n            return d.promise;\n        },\n        find_app_by_owner: function (owner, page, size) {\n            var d = $q.defer();\n            app_resource.find_app_by_owner({\n                                               owner: owner,\n                                               page: page,\n                                               size: size\n                                           }, function (result) {\n                d.resolve(result);\n            }, function (result) {\n                d.reject(result);\n            });\n            return d.promise;\n        },\n        load_nav_tree: function (appId) {\n            var d = $q.defer();\n            app_resource.load_navtree({\n                                          appId: appId\n                                      }, function (result) {\n                d.resolve(result);\n            }, function (result) {\n                d.reject(result);\n            });\n            return d.promise;\n        },\n        create: function (app) {\n            var d = $q.defer();\n            app_resource.create_app({}, app, function (result) {\n                d.resolve(result);\n            }, function (result) {\n                d.reject(result);\n            });\n            return d.promise;\n        },\n        update: function (app) {\n            var d = $q.defer();\n            app_resource.update_app({\n                                        appId: app.appId\n                                    }, app, function (result) {\n                d.resolve(result);\n            }, function (result) {\n                d.reject(result);\n            });\n            return d.promise;\n        },\n        create_remote: function (env, app) {\n            var d = $q.defer();\n            app_resource.create_app_remote({env: env}, app, function (result) {\n                d.resolve(result);\n            }, function (result) {\n                d.reject(result);\n            });\n            return d.promise;\n        },\n        load: function (appId) {\n            var d = $q.defer();\n            app_resource.load_app({\n                                      appId: appId\n                                  }, function (result) {\n                d.resolve(result);\n            }, function (result) {\n                d.reject(result);\n            });\n            return d.promise;\n        },\n        find_miss_envs: function (appId) {\n            var d = $q.defer();\n            app_resource.find_miss_envs({\n                                            appId: appId\n                                        }, function (result) {\n                d.resolve(result);\n            }, function (result) {\n                d.reject(result);\n            });\n            return d.promise;\n        }\n    }\n}]);\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/services/ClusterService.js",
    "content": "appService.service('ClusterService', ['$resource', '$q', function ($resource, $q) {\n    var cluster_resource = $resource('', {}, {\n        create_cluster: {\n            method: 'POST',\n            url: 'apps/:appId/envs/:env/clusters'\n        }\n    });\n    return {\n        create_cluster: function (appId, env, cluster) {\n            var d = $q.defer();\n            cluster_resource.create_cluster({\n                                                appId: appId,\n                                                env: env\n                                            }, cluster,\n                                            function (result) {\n                                                d.resolve(result);\n                                            }, function (result) {\n                    d.reject(result);\n                });\n            return d.promise;\n        }\n    }\n}]);\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/services/CommitService.js",
    "content": "appService.service('CommitService', ['$resource', '$q', function ($resource, $q) {\n    var commit_resource = $resource('', {}, {\n        find_commits: {\n            method: 'GET',\n            isArray: true,\n            url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/commits?page=:page'\n        }\n    });\n    return {\n        find_commits: function (appId, env, clusterName, namespaceName, page, size) {\n            var d = $q.defer();\n            commit_resource.find_commits({\n                                             appId: appId,\n                                             env: env,\n                                             clusterName: clusterName,\n                                             namespaceName: namespaceName,\n                                             page: page,\n                                             size: size\n                                         },\n                                         function (result) {\n                                             d.resolve(result);\n                                         }, function (result) {\n                    d.reject(result);\n                });\n            return d.promise;\n        }\n    }\n}]);\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/services/CommonService.js",
    "content": "appService.service('CommonService', ['$resource', '$q', 'AppUtil',\n                                       function ($resource, $q, AppUtil) {\n    var resource = $resource('', {}, {\n        page_setting: {\n            method: 'GET',\n            isArray: false,\n            url: '/page-settings'\n        }\n    });\n\n                                           \n    return {\n        getPageSetting: function () {\n            return AppUtil.ajax(resource.page_setting, {});\n        }\n    }\n}]);\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/services/ConfigService.js",
    "content": "appService.service(\"ConfigService\", ['$resource', '$q', function ($resource, $q) {\n    var config_source = $resource(\"\", {}, {\n        load_namespace: {\n            method: 'GET',\n            isArray: false,\n            url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName'\n        },\n        load_public_namespace_for_associated_namespace: {\n            method: 'GET',\n            isArray: false,\n            url: '/envs/:env/apps/:appId/clusters/:clusterName/namespaces/:namespaceName/associated-public-namespace'\n        },\n        load_all_namespaces: {\n            method: 'GET',\n            isArray: true,\n            url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces'\n        },\n        find_items: {\n            method: 'GET',\n            isArray: true,\n            url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/items'\n        },\n        modify_items: {\n            method: 'PUT',\n            url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/items'\n        },\n        diff: {\n            method: 'POST',\n            url: '/namespaces/:namespaceName/diff',\n            isArray: true\n        },\n        sync_item: {\n            method: 'PUT',\n            url: '/apps/:appId/namespaces/:namespaceName/items',\n            isArray: false\n        },\n        create_item: {\n            method: 'POST',\n            url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/item'\n        },\n        update_item: {\n            method: 'PUT',\n            url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/item'\n        },\n        delete_item: {\n            method: 'DELETE',\n            url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/items/:itemId'\n        }\n    });\n\n    return {\n        load_namespace: function (appId, env, clusterName, namespaceName) {\n            var d = $q.defer();\n            config_source.load_namespace({\n                                             appId: appId,\n                                             env: env,\n                                             clusterName: clusterName,\n                                             namespaceName: namespaceName\n                                         }, function (result) {\n                d.resolve(result);\n            }, function (result) {\n                d.reject(result);\n            });\n            return d.promise;\n        },\n        load_public_namespace_for_associated_namespace: function (env, appId, clusterName, namespaceName) {\n            var d = $q.defer();\n            config_source.load_public_namespace_for_associated_namespace({\n                                                                             env: env,\n                                                                             appId: appId,\n                                                                             clusterName: clusterName,\n                                                                             namespaceName: namespaceName\n                                                                         }, function (result) {\n                d.resolve(result);\n            }, function (result) {\n                d.reject(result);\n            });\n            return d.promise;\n        },\n        load_all_namespaces: function (appId, env, clusterName) {\n            var d = $q.defer();\n            config_source.load_all_namespaces({\n                                                  appId: appId,\n                                                  env: env,\n                                                  clusterName: clusterName\n                                              }, function (result) {\n                d.resolve(result);\n            }, function (result) {\n                d.reject(result);\n            });\n            return d.promise;\n        },\n\n        find_items: function (appId, env, clusterName, namespaceName, orderBy) {\n            var d = $q.defer();\n            config_source.find_items({\n                                         appId: appId,\n                                         env: env,\n                                         clusterName: clusterName,\n                                         namespaceName: namespaceName,\n                                         orderBy: orderBy\n                                     }, function (result) {\n                d.resolve(result);\n            }, function (result) {\n                d.reject(result);\n            });\n            return d.promise;\n        },\n\n        modify_items: function (appId, env, clusterName, namespaceName, model) {\n            var d = $q.defer();\n            config_source.modify_items({\n                                           appId: appId,\n                                           env: env,\n                                           clusterName: clusterName,\n                                           namespaceName: namespaceName\n                                       },\n                                       model, function (result) {\n                    d.resolve(result);\n\n                }, function (result) {\n                    d.reject(result);\n                });\n            return d.promise;\n        },\n\n        diff: function (namespaceName, sourceData) {\n            var d = $q.defer();\n            config_source.diff({\n                                   namespaceName: namespaceName\n                               }, sourceData, function (result) {\n                d.resolve(result);\n            }, function (result) {\n                d.reject(result);\n            });\n            return d.promise;\n        },\n\n        sync_items: function (appId, namespaceName, sourceData) {\n            var d = $q.defer();\n            config_source.sync_item({\n                                        appId: appId,\n                                        namespaceName: namespaceName\n                                    }, sourceData, function (result) {\n                d.resolve(result);\n            }, function (result) {\n                d.reject(result);\n            });\n            return d.promise;\n        },\n\n        create_item: function (appId, env, clusterName, namespaceName, item) {\n            var d = $q.defer();\n            config_source.create_item({\n                                          appId: appId,\n                                          env: env,\n                                          clusterName: clusterName,\n                                          namespaceName: namespaceName\n                                      }, item, function (result) {\n                d.resolve(result);\n            }, function (result) {\n                d.reject(result);\n            });\n            return d.promise;\n        },\n\n        update_item: function (appId, env, clusterName, namespaceName, item) {\n            var d = $q.defer();\n            config_source.update_item({\n                                          appId: appId,\n                                          env: env,\n                                          clusterName: clusterName,\n                                          namespaceName: namespaceName\n                                      }, item, function (result) {\n                d.resolve(result);\n            }, function (result) {\n                d.reject(result);\n            });\n            return d.promise;\n        },\n\n        delete_item: function (appId, env, clusterName, namespaceName, itemId) {\n            var d = $q.defer();\n            config_source.delete_item({\n                                          appId: appId,\n                                          env: env,\n                                          clusterName: clusterName,\n                                          namespaceName: namespaceName,\n                                          itemId: itemId\n                                      }, function (result) {\n                d.resolve(result);\n            }, function (result) {\n                d.reject(result);\n            });\n            return d.promise;\n        }\n    }\n\n}]);\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/services/ConsumerService.js",
    "content": "appService.service('ConsumerService', ['$resource', '$q', 'AppUtil', \n                                       function ($resource, $q, AppUtil) {\n    var resource = $resource('', {}, {\n        create_consumer: {\n            method: 'POST',\n            isArray: false,\n            url: '/consumers'\n        },\n        get_consumer_token_by_appId: {\n            method: 'GET',\n            isArray: false,\n            url: '/consumers/by-appId'\n        },\n        assign_role_to_consumer: {\n            method: 'POST',\n            isArray: true,\n            url: '/consumers/:token/assign-role'\n        }\n\n    });\n\n                                           \n    return {\n        createConsumer: function (consumer) {\n            return AppUtil.ajax(resource.create_consumer, {}, consumer);\n        },\n        getConsumerTokenByAppId: function (appId) {\n            return AppUtil.ajax(resource.get_consumer_token_by_appId, {\n                appId: appId\n            });\n        },\n        assignRoleToConsumer: function (token, type, appId, namespaceName) {\n            return AppUtil.ajax(resource.assign_role_to_consumer, \n                                {\n                                    token: token,\n                                    type: type \n                                },\n                                {\n                                    appId: appId,\n                                    namespaceName: namespaceName\n                                }\n            )\n        }\n    }\n}]);\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/services/EnvService.js",
    "content": "appService.service('EnvService', ['$resource', '$q', function ($resource, $q) {\n    var env_resource = $resource('/envs', {}, {\n        find_all_envs:{\n            method: 'GET',\n            isArray: true,\n            url:'/envs'\n        }\n    });\n    return {\n        find_all_envs: function () {\n            var d = $q.defer();\n            env_resource.find_all_envs({\n                                      },\n                                      function (result) {\n                                          d.resolve(result);\n                                      }, function (result) {\n                    d.reject(result);\n                });\n            return d.promise;\n        }\n    }\n}]);\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/services/EventManager.js",
    "content": "appService.service('EventManager', [function () {\n\n    /**\n     * subscribe EventType with any object\n     * @type {string}\n     */\n    var ALL_OBJECT = '*';\n\n    var eventRegistry = {};\n\n    /**\n     *\n     * @param eventType acquired. event type\n     * @param context   optional. event execute context\n     * @param objectId  optional. subscribe object id and empty value means subscribe event type with all object\n     */\n    function emit(eventType, context, objectId) {\n        if (!eventType) {\n            return;\n        }\n\n        if (!eventRegistry[eventType]) {\n            return;\n        }\n\n        if (!context) {\n            context = {};\n        }\n\n        if (!objectId) {\n            objectId = ALL_OBJECT;\n        }\n\n        var subscribers = eventRegistry[eventType][objectId];\n        emitEventToSubscribers(subscribers, context);\n\n        if (objectId == ALL_OBJECT) {\n            return;\n        }\n\n        //emit event to subscriber which subscribed all object\n        subscribers = eventRegistry[eventType][ALL_OBJECT];\n        emitEventToSubscribers(subscribers);\n    }\n\n    function emitEventToSubscribers(subscribers, context) {\n        if (subscribers) {\n            subscribers.forEach(function (subscriber) {\n                subscriber.callback(context);\n            })\n        }\n    }\n\n    /**\n     *\n     * @param eventType acquired. event type\n     * @param callback  acquired. callback function when event emitted\n     * @param objectId  optional. subscribe object id and empty value means subscribe event type with all object\n     */\n    function subscribe(eventType, callback, objectId) {\n        if (!eventType || !callback) {\n            return;\n        }\n\n        if (!objectId) {\n            objectId = ALL_OBJECT;\n        }\n\n        var subscribedObjects = eventRegistry[eventType];\n        if (!subscribedObjects) {\n            subscribedObjects = {};\n            eventRegistry[eventType] = subscribedObjects;\n        }\n\n        var callbacks = subscribedObjects[objectId];\n        if (!callbacks) {\n            callbacks = [];\n            subscribedObjects[objectId] = callbacks;\n        }\n\n        var subscriber = {\n            id: Math.random() * Math.random(),\n            callback: callback\n        };\n        callbacks.push(subscriber);\n\n        return subscriber.id;\n    }\n\n    /**\n     * \n     * @param eventType  acquired. event type\n     * @param subscriberId acquired. subscriber id which get from event manager when subscribe\n     * @param objectId optional.    subscribe object id and empty value means subscribe event type with all object\n     */\n    function unsubscribe(eventType, subscriberId, objectId) {\n        if (!eventType || !subscriberId) {\n            return;\n        }\n\n        if (!objectId) {\n            objectId = ALL_OBJECT;\n        }\n\n        var subscribers = eventRegistry[eventType] ?\n                          eventRegistry[eventType][objectId] : undefined;\n\n        if (!subscribers) {\n            return;\n        }\n\n        subscribers.forEach(function (subscriber, index) {\n            if (subscriber.id == subscriberId) {\n                subscribers.splice(index, 1);\n            }\n        })\n\n    }\n\n    return {\n        ALL_OBJECT: ALL_OBJECT,\n\n        emit: emit,\n        subscribe: subscribe,\n        unsubscribe: unsubscribe,\n\n        EventType: {\n            REFRESH_NAMESPACE: 'refresh_namespace',\n            PUBLISH_NAMESPACE: 'pre_public_namespace',\n            MERGE_AND_PUBLISH_NAMESPACE: 'merge_and_publish_namespace',\n            PRE_ROLLBACK_NAMESPACE: 'pre_rollback_namespace',\n            ROLLBACK_NAMESPACE: 'rollback_namespace',\n            EDIT_GRAY_RELEASE_RULES: 'edit_gray_release_rules',\n            UPDATE_GRAY_RELEASE_RULES: 'update_gray_release_rules',\n            PUBLISH_DENY: 'publish_deny',\n            EMERGENCY_PUBLISH: 'emergency_publish',\n            PRE_DELETE_NAMESPACE: 'pre_delete_namespace',\n            DELETE_NAMESPACE: 'delete_namespace',\n            DELETE_NAMESPACE_FAILED: 'delete_namespace_failed'\n        }\n\n    }\n}]);\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/services/FavoriteService.js",
    "content": "appService.service('FavoriteService', ['$resource', '$q', function ($resource, $q) {\n    var resource = $resource('', {}, {\n        find_favorites: {\n            method: 'GET',\n            url: '/favorites',\n            isArray: true\n        },\n        add_favorite: {\n            method: 'POST',\n            url: '/favorites'\n        },\n        delete_favorite: {\n            method: 'DELETE',\n            url: '/favorites/:favoriteId'\n        },\n        to_top: {\n            method: 'PUT',\n            url: '/favorites/:favoriteId'\n        }\n    });\n    return {\n        findFavorites: function (userId, appId, page, size) {\n            var d = $q.defer();\n            resource.find_favorites({\n                                        userId: userId,\n                                        appId: appId,\n                                        page: page,\n                                        size: size\n                                    }, function (result) {\n                d.resolve(result);\n            }, function (result) {\n                d.reject(result);\n            });\n            return d.promise;\n        },\n        addFavorite: function (favorite) {\n            var d = $q.defer();\n            resource.add_favorite({}, favorite, function (result) {\n                d.resolve(result);\n            }, function (result) {\n                d.reject(result);\n            });\n            return d.promise;\n        },\n        deleteFavorite: function (favoriteId) {\n            var d = $q.defer();\n            resource.delete_favorite({\n                                          favoriteId: favoriteId\n                                      }, function (result) {\n                d.resolve(result);\n            }, function (result) {\n                d.reject(result);\n            });\n            return d.promise;\n        },\n        toTop: function (favoriteId) {\n            var d = $q.defer();\n            resource.to_top({\n                                favoriteId: favoriteId\n                            }, {}, function (result) {\n                d.resolve(result);\n            }, function (result) {\n                d.reject(result);\n            });\n            return d.promise;\n        }\n    }\n}]);\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/services/InstanceService.js",
    "content": "appService.service('InstanceService', ['$resource', '$q', function ($resource, $q) {\n    var resource = $resource('', {}, {\n        find_instances_by_release: {\n            method: 'GET',\n            url: '/envs/:env/instances/by-release'\n        },\n        find_instances_by_namespace: {\n            method: 'GET',\n            isArray: false,\n            url: '/envs/:env/instances/by-namespace'\n        },\n        find_by_releases_not_in: {\n            method: 'GET',\n            isArray: true,\n            url: '/envs/:env/instances/by-namespace-and-releases-not-in'\n        },\n        get_instance_count_by_namespace: {\n            method: 'GET',\n            isArray: false,\n            url: \"envs/:env/instances/by-namespace/count\"\n        }\n    });\n\n    var instanceService = {\n        findInstancesByRelease: function (env, releaseId, page, size) {\n            if (!size) {\n                size = 20;\n            }\n            var d = $q.defer();\n            resource.find_instances_by_release({\n                                                   env: env,\n                                                   releaseId: releaseId,\n                                                   page: page,\n                                                   size: size\n                                               },\n                                               function (result) {\n                                                   d.resolve(result);\n                                               }, function (result) {\n                    d.reject(result);\n                });\n            return d.promise;\n        },\n        findInstancesByNamespace: function (appId, env, clusterName, namespaceName, instanceAppId, page, size) {\n            if (!size) {\n                size = 20;\n            }\n            var d = $q.defer();\n            var instanceAppIdRequest = instanceAppId;\n            instanceService.lastInstanceAppIdRequest = instanceAppIdRequest;\n            resource.find_instances_by_namespace({\n                                                     env: env,\n                                                     appId: appId,\n                                                     clusterName: clusterName,\n                                                     namespaceName: namespaceName,\n                                                     instanceAppId: instanceAppId,\n                                                     page: page,\n                                                     size: size\n                                                 },\n                                                 function (result) {\n                                                     if (instanceAppIdRequest\n                                                         != instanceService.lastInstanceAppIdRequest) {\n                                                         return;\n                                                     }\n                                                     d.resolve(result);\n                                                 }, function (result) {\n                    if (instanceAppIdRequest != instanceService.lastInstanceAppIdRequest) {\n                        return;\n                    }\n                    d.reject(result);\n                });\n            return d.promise;\n        },\n        findByReleasesNotIn: function (appId, env, clusterName, namespaceName, releaseIds) {\n            var d = $q.defer();\n            resource.find_by_releases_not_in({\n                                                 env: env,\n                                                 appId: appId,\n                                                 clusterName: clusterName,\n                                                 namespaceName: namespaceName,\n                                                 releaseIds: releaseIds\n                                             },\n                                             function (result) {\n                                                 d.resolve(result);\n                                             }, function (result) {\n                    d.reject(result);\n                });\n            return d.promise;\n        },\n        getInstanceCountByNamespace: function (appId, env, clusterName, namespaceName) {\n            var d = $q.defer();\n            resource.get_instance_count_by_namespace({\n                                                         env: env,\n                                                         appId: appId,\n                                                         clusterName: clusterName,\n                                                         namespaceName: namespaceName\n                                                     },\n                                                     function (result) {\n                                                         d.resolve(result);\n                                                     }, function (result) {\n                    d.reject(result);\n                });\n            return d.promise;\n        }\n\n    };\n\n    return instanceService;\n}]);\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/services/NamespaceBranchService.js",
    "content": "appService.service('NamespaceBranchService', ['$resource', '$q', function ($resource, $q) {\n    var resource = $resource('', {}, {\n        find_namespace_branch: {\n            method: 'GET',\n            isArray: false,\n            url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/branches'\n        },\n        create_branch: {\n            method: 'POST',\n            isArray: false,\n            url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/branches'\n        },\n        delete_branch: {\n            method: 'DELETE',\n            isArray: false,\n            url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/branches/:branchName'\n        },\n        merge_and_release_branch: {\n            method: 'POST',\n            isArray: false,\n            url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/branches/:branchName/merge'\n        },\n        find_branch_gray_rules: {\n            method: 'GET',\n            isArray: false,\n            url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/branches/:branchName/rules'\n        },\n        update_branch_gray_rules: {\n            method: 'PUT',\n            isArray: false,\n            url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/branches/:branchName/rules'\n        }\n\n    });\n\n    function find_namespace_branch(appId, env, clusterName, namespaceName) {\n        var d = $q.defer();\n        resource.find_namespace_branch({\n                                           appId: appId,\n                                           env: env,\n                                           clusterName: clusterName,\n                                           namespaceName: namespaceName\n                                       },\n                                       function (result) {\n                                           d.resolve(result);\n                                       }, function (result) {\n                d.reject(result);\n            });\n        return d.promise;\n    }\n\n    function create_branch(appId, env, clusterName, namespaceName) {\n        var d = $q.defer();\n        resource.create_branch({\n                                   appId: appId,\n                                   env: env,\n                                   clusterName: clusterName,\n                                   namespaceName: namespaceName\n                               }, {},\n                               function (result) {\n                                   d.resolve(result);\n                               }, function (result) {\n                d.reject(result);\n            });\n        return d.promise;\n    }\n\n    function delete_branch(appId, env, clusterName, namespaceName, branchName) {\n        var d = $q.defer();\n        resource.delete_branch({\n                                   appId: appId,\n                                   env: env,\n                                   clusterName: clusterName,\n                                   namespaceName: namespaceName,\n                                   branchName: branchName\n                               },\n                               function (result) {\n                                   d.resolve(result);\n                               }, function (result) {\n                d.reject(result);\n            });\n        return d.promise;\n    }\n\n    function merge_and_release_branch(appId, env, clusterName, namespaceName,\n                                      branchName, title, comment, isEmergencyPublish, deleteBranch) {\n        var d = $q.defer();\n        resource.merge_and_release_branch({\n                                              appId: appId,\n                                              env: env,\n                                              clusterName: clusterName,\n                                              namespaceName: namespaceName,\n                                              branchName: branchName,\n                                              deleteBranch:deleteBranch\n                                          }, {\n                                              releaseTitle: title,\n                                              releaseComment: comment,\n                                              isEmergencyPublish: isEmergencyPublish\n                                          },\n                                          function (result) {\n                                              d.resolve(result);\n                                          }, function (result) {\n                d.reject(result);\n            });\n        return d.promise;\n    }\n\n    function find_branch_gray_rules(appId, env, clusterName, namespaceName, branchName) {\n        var d = $q.defer();\n        resource.find_branch_gray_rules({\n                                            appId: appId,\n                                            env: env,\n                                            clusterName: clusterName,\n                                            namespaceName: namespaceName,\n                                            branchName: branchName\n                                        },\n                                        function (result) {\n                                            d.resolve(result);\n                                        }, function (result) {\n                d.reject(result);\n            });\n        return d.promise;\n    }\n\n    function update_branch_gray_rules(appId, env, clusterName,\n                                      namespaceName, branchName, newRules) {\n        var d = $q.defer();\n        resource.update_branch_gray_rules({\n                                              appId: appId,\n                                              env: env,\n                                              clusterName: clusterName,\n                                              namespaceName: namespaceName,\n                                              branchName: branchName\n                                          }, newRules,\n                                          function (result) {\n                                              d.resolve(result);\n                                          }, function (result) {\n                d.reject(result);\n            });\n        return d.promise;\n    }\n\n    return {\n        findNamespaceBranch: find_namespace_branch,\n        createBranch: create_branch,\n        deleteBranch: delete_branch,\n        mergeAndReleaseBranch: merge_and_release_branch,\n        findBranchGrayRules: find_branch_gray_rules,\n        updateBranchGrayRules: update_branch_gray_rules\n    }\n}]);\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/services/NamespaceLockService.js",
    "content": "appService.service('NamespaceLockService', ['$resource', '$q', function ($resource, $q) {\n    var resource = $resource('', {}, {\n        get_namespace_lock: {\n            method: 'GET',\n            url: 'apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/lock-info'\n        }\n    });\n\n    return {\n        get_namespace_lock: function (appId, env, clusterName, namespaceName) {\n            var d = $q.defer();\n            resource.get_namespace_lock({\n                                            appId: appId,\n                                            env: env,\n                                            clusterName: clusterName,\n                                            namespaceName: namespaceName\n                                        }, function (result) {\n                d.resolve(result);\n            }, function (result) {\n                d.reject(result);\n            });\n            return d.promise;\n        }\n    }\n}]);\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/services/NamespaceService.js",
    "content": "appService.service(\"NamespaceService\", ['$resource', '$q', function ($resource, $q) {\n    var namespace_source = $resource(\"\", {}, {\n        find_public_namespaces: {\n            method: 'GET',\n            isArray: true,\n            url: '/appnamespaces/public'\n        },\n        createNamespace: {\n            method: 'POST',\n            url: '/apps/:appId/namespaces',\n            isArray: false\n        },\n        createAppNamespace: {\n            method: 'POST',\n            url: '/apps/:appId/appnamespaces',\n            isArray: false\n        },\n        getNamespacePublishInfo: {\n            method: 'GET',\n            url: '/apps/:appId/namespaces/publish_info'\n        },\n        deleteNamespace: {\n            method: 'DELETE',\n            url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName'\n        },\n        getPublicAppNamespaceAllNamespaces: {\n            method: 'GET',\n            url: '/envs/:env/appnamespaces/:publicNamespaceName/namespaces',\n            isArray: true\n        }\n    });\n\n    function find_public_namespaces() {\n        var d = $q.defer();\n        namespace_source.find_public_namespaces({}, function (result) {\n            d.resolve(result);\n        }, function (result) {\n            d.reject(result);\n        });\n        return d.promise;\n    }\n\n    function createNamespace(appId, namespaceCreationModel) {\n        var d = $q.defer();\n        namespace_source.createNamespace({\n                                             appId: appId\n                                         }, namespaceCreationModel, function (result) {\n            d.resolve(result);\n        }, function (result) {\n            d.reject(result);\n        });\n        return d.promise;\n    }\n\n    function createAppNamespace(appId, appnamespace) {\n        var d = $q.defer();\n        namespace_source.createAppNamespace({\n                                                appId: appId\n                                            }, appnamespace, function (result) {\n            d.resolve(result);\n        }, function (result) {\n            d.reject(result);\n        });\n        return d.promise;\n    }\n\n    function getNamespacePublishInfo(appId) {\n        var d = $q.defer();\n        namespace_source.getNamespacePublishInfo({\n                                                     appId: appId\n                                                 }, function (result) {\n            d.resolve(result);\n        }, function (result) {\n            d.reject(result);\n        });\n\n        return d.promise;\n    }\n\n    function deleteNamespace(appId, env, clusterName, namespaceName) {\n        var d = $q.defer();\n        namespace_source.deleteNamespace({\n                                             appId: appId,\n                                             env: env,\n                                             clusterName: clusterName,\n                                             namespaceName: namespaceName\n                                         },\n                                         function (result) {\n                                             d.resolve(result);\n                                         },\n                                         function (result) {\n                                             d.reject(result);\n                                         });\n\n        return d.promise;\n    }\n\n    function getPublicAppNamespaceAllNamespaces(env, publicNamespaceName, page, size) {\n        var d = $q.defer();\n        namespace_source.getPublicAppNamespaceAllNamespaces({\n                                                                env: env,\n                                                                publicNamespaceName: publicNamespaceName,\n                                                                page: page,\n                                                                size: size\n                                                            }, function (result) {\n            d.resolve(result);\n        }, function (result) {\n            d.reject(result);\n        });\n\n        return d.promise;\n\n    }\n\n    return {\n        find_public_namespaces: find_public_namespaces,\n        createNamespace: createNamespace,\n        createAppNamespace: createAppNamespace,\n        getNamespacePublishInfo: getNamespacePublishInfo,\n        deleteNamespace: deleteNamespace,\n        getPublicAppNamespaceAllNamespaces: getPublicAppNamespaceAllNamespaces\n    }\n\n}]);\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/services/OrganizationService.js",
    "content": "appService.service(\"OrganizationService\", ['$resource', '$q', function ($resource, $q) {\n    var organization_source = $resource(\"\", {}, {\n        find_organizations: {\n            method: 'GET',\n            isArray: true,\n            url: '/organizations'\n        }\n    });\n\n    return {\n        find_organizations: function () {\n            var d = $q.defer();\n            organization_source.find_organizations({}, function (result) {\n                d.resolve(result);\n            }, function (result) {\n                d.reject(result);\n            });\n            return d.promise;\n        }\n    }\n\n}]);\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/services/PermissionService.js",
    "content": "appService.service('PermissionService', ['$resource', '$q', function ($resource, $q) {\n    var permission_resource = $resource('', {}, {\n        has_app_permission: {\n            method: 'GET',\n            url: '/apps/:appId/permissions/:permissionType'\n        },\n        has_namespace_permission: {\n            method: 'GET',\n            url: '/apps/:appId/namespaces/:namespaceName/permissions/:permissionType'\n        },\n        has_root_permission:{\n            method: 'GET',\n            url: '/permissions/root'\n        },\n        get_namespace_role_users: {\n            method: 'GET',\n            url: '/apps/:appId/namespaces/:namespaceName/role_users'\n        },\n        assign_namespace_role_to_user: {\n            method: 'POST',\n            url: '/apps/:appId/namespaces/:namespaceName/roles/:roleType'\n        },\n        remove_namespace_role_from_user: {\n            method: 'DELETE',\n            url: '/apps/:appId/namespaces/:namespaceName/roles/:roleType?user=:user'\n        },\n        get_app_role_users: {\n            method: 'GET',\n            url: '/apps/:appId/role_users'    \n        },\n        assign_app_role_to_user: {\n            method: 'POST',\n            url: '/apps/:appId/roles/:roleType'\n        },\n        remove_app_role_from_user: {\n            method: 'DELETE',\n            url: '/apps/:appId/roles/:roleType?user=:user'\n        }\n    });\n\n    function hasAppPermission(appId, permissionType) {\n        var d = $q.defer();\n        permission_resource.has_app_permission({\n                                                   appId: appId,\n                                                   permissionType: permissionType\n                                               },\n                                               function (result) {\n                                                   d.resolve(result);\n                                               }, function (result) {\n                d.reject(result);\n            });\n        return d.promise;\n    }\n\n    function hasNamespacePermission(appId, namespaceName, permissionType) {\n        var d = $q.defer();\n        permission_resource.has_namespace_permission({\n                                                         appId: appId,\n                                                         namespaceName: namespaceName,\n                                                         permissionType: permissionType\n                                                     },\n                                                     function (result) {\n                                                         d.resolve(result);\n                                                     }, function (result) {\n                d.reject(result);\n            });\n        return d.promise;\n    }\n\n    function assignNamespaceRoleToUser(appId, namespaceName, roleType, user) {\n        var d = $q.defer();\n        permission_resource.assign_namespace_role_to_user({\n                                                              appId: appId,\n                                                              namespaceName: namespaceName,\n                                                              roleType: roleType\n                                                          }, user,\n                                                          function (result) {\n                                                              d.resolve(result);\n                                                          }, function (result) {\n                d.reject(result);\n            });\n        return d.promise;\n    }\n\n    function removeRoleFromUser(appId, namespaceName, roleType, user) {\n        var d = $q.defer();\n        permission_resource.remove_namespace_role_from_user({\n                                                                appId: appId,\n                                                                namespaceName: namespaceName,\n                                                                roleType: roleType,\n                                                                user: user\n                                                            },\n                                                            function (result) {\n                                                                d.resolve(result);\n                                                            }, function (result) {\n                d.reject(result);\n            });\n        return d.promise;\n    }\n\n    return {\n        has_create_namespace_permission: function (appId) {\n            return hasAppPermission(appId, 'CreateNamespace');\n        },\n        has_create_cluster_permission: function (appId) {\n            return hasAppPermission(appId, 'CreateCluster');\n        },\n        has_assign_user_permission: function (appId) {\n            return hasAppPermission(appId, 'AssignRole');\n        },\n        has_modify_namespace_permission: function (appId, namespaceName) {\n            return hasNamespacePermission(appId, namespaceName, 'ModifyNamespace');\n        },\n        has_release_namespace_permission: function (appId, namespaceName) {\n            return hasNamespacePermission(appId, namespaceName, 'ReleaseNamespace');\n        },\n        has_root_permission: function () {\n            var d = $q.defer();\n            permission_resource.has_root_permission({ },\n                                                         function (result) {\n                                                             d.resolve(result);\n                                                         }, function (result) {\n                    d.reject(result);\n                });\n            return d.promise;    \n            \n        },\n        assign_modify_namespace_role: function (appId, namespaceName, user) {\n            return assignNamespaceRoleToUser(appId, namespaceName, 'ModifyNamespace', user);\n        },\n        assign_release_namespace_role: function (appId, namespaceName, user) {\n            return assignNamespaceRoleToUser(appId, namespaceName, 'ReleaseNamespace', user);\n        },\n        remove_modify_namespace_role: function (appId, namespaceName, user) {\n            return removeRoleFromUser(appId, namespaceName, 'ModifyNamespace', user);\n        },\n        remove_release_namespace_role: function (appId, namespaceName, user) {\n            return removeRoleFromUser(appId, namespaceName, 'ReleaseNamespace', user);\n        },\n        get_namespace_role_users: function (appId, namespaceName) {\n            var d = $q.defer();\n            permission_resource.get_namespace_role_users({\n                                                              appId: appId,\n                                                              namespaceName: namespaceName,\n                                                          },\n                                                         function (result) {\n                                                              d.resolve(result);\n                                                          }, function (result) {\n                    d.reject(result);\n                });\n            return d.promise;\n        },\n        get_app_role_users: function (appId) {\n            var d = $q.defer();\n            permission_resource.get_app_role_users({\n                                                        appId: appId\n                                                    },\n                                                   function (result) {\n                                                        d.resolve(result);\n                                                    }, function (result) {\n                    d.reject(result);\n                });\n            return d.promise;    \n        },\n        assign_master_role: function (appId, user) {\n            var d = $q.defer();\n            permission_resource.assign_app_role_to_user({\n                                                            appId: appId,\n                                                            roleType: 'Master'\n                                                        }, user,\n                                                        function (result) {\n                                                            d.resolve(result);\n                                                        }, function (result) {\n                    d.reject(result);\n                });\n            return d.promise;\n        },\n        remove_master_role: function (appId, user) {\n            var d = $q.defer();\n            permission_resource.remove_app_role_from_user({\n                                                              appId: appId,\n                                                              roleType: 'Master',\n                                                              user: user\n                                                          },\n                                                          function (result) {\n                                                              d.resolve(result);\n                                                          }, function (result) {\n                    d.reject(result);\n                });\n            return d.promise;\n        }\n    }\n}]);\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/services/ReleaseHistoryService.js",
    "content": "appService.service('ReleaseHistoryService', ['$resource', '$q', function ($resource, $q) {\n    var resource = $resource('', {}, {\n        find_release_history_by_namespace: {\n            method: 'GET',\n            url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/releases/histories',\n            isArray: true\n        }\n    });\n\n    function findReleaseHistoryByNamespace(appId, env, clusterName, namespaceName, page, size) {\n        var d = $q.defer();\n        resource.find_release_history_by_namespace({\n                                                       appId: appId,\n                                                       env: env,\n                                                       clusterName: clusterName,\n                                                       namespaceName: namespaceName,\n                                                       page: page,\n                                                       size: size\n                                                   }, function (result) {\n            d.resolve(result);\n        }, function (result) {\n            d.reject(result);\n        });\n        return d.promise;\n    }\n\n    \n    return {\n        findReleaseHistoryByNamespace: findReleaseHistoryByNamespace\n    }\n}]);\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/services/ReleaseService.js",
    "content": "appService.service('ReleaseService', ['$resource', '$q', function ($resource, $q) {\n    var resource = $resource('', {}, {\n        find_all_releases: {\n            method: 'GET',\n            url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/releases/all',\n            isArray: true\n        },\n        find_active_releases: {\n            method: 'GET',\n            url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/releases/active',\n            isArray: true\n        },\n        compare: {\n            method: 'GET',\n            url: '/envs/:env/releases/compare'\n        },\n        release: {\n            method: 'POST',\n            url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/releases'\n        },\n        gray_release: {\n            method: 'POST',\n            url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/branches/:branchName/releases'\n        },\n        rollback: {\n            method: 'PUT',\n            url: \"envs/:env/releases/:releaseId/rollback\"\n        }\n    });\n\n    function createRelease(appId, env, clusterName, namespaceName, releaseTitle, comment, isEmergencyPublish) {\n        var d = $q.defer();\n        resource.release({\n                             appId: appId,\n                             env: env,\n                             clusterName: clusterName,\n                             namespaceName: namespaceName\n                         }, {\n                             releaseTitle: releaseTitle,\n                             releaseComment: comment,\n                             isEmergencyPublish: isEmergencyPublish\n                         }, function (result) {\n            d.resolve(result);\n        }, function (result) {\n            d.reject(result);\n        });\n        return d.promise;\n    }\n\n    function createGrayRelease(appId, env, clusterName, namespaceName, branchName, releaseTitle, comment, isEmergencyPublish) {\n        var d = $q.defer();\n        resource.gray_release({\n                                  appId: appId,\n                                  env: env,\n                                  clusterName: clusterName,\n                                  namespaceName: namespaceName,\n                                  branchName: branchName\n                              }, {\n                                  releaseTitle: releaseTitle,\n                                  releaseComment: comment,\n                                  isEmergencyPublish: isEmergencyPublish\n                              }, function (result) {\n            d.resolve(result);\n        }, function (result) {\n            d.reject(result);\n        });\n        return d.promise;\n    }\n\n    function findAllReleases(appId, env, clusterName, namespaceName, page, size) {\n        var d = $q.defer();\n        resource.find_all_releases({\n                                       appId: appId,\n                                       env: env,\n                                       clusterName: clusterName,\n                                       namespaceName: namespaceName,\n                                       page: page,\n                                       size: size\n                                   }, function (result) {\n            d.resolve(result);\n        }, function (result) {\n            d.reject(result);\n        });\n        return d.promise;\n    }\n\n    function findActiveReleases(appId, env, clusterName, namespaceName, page, size) {\n        var d = $q.defer();\n        resource.find_active_releases({\n                                          appId: appId,\n                                          env: env,\n                                          clusterName: clusterName,\n                                          namespaceName: namespaceName,\n                                          page: page,\n                                          size: size\n                                      }, function (result) {\n            d.resolve(result);\n        }, function (result) {\n            d.reject(result);\n        });\n        return d.promise;\n    }\n\n    function findLatestActiveRelease(appId, env, clusterName, namespaceName) {\n        var d = $q.defer();\n        resource.find_active_releases({\n                                          appId: appId,\n                                          env: env,\n                                          clusterName: clusterName,\n                                          namespaceName: namespaceName,\n                                          page: 0,\n                                          size: 1\n                                      }, function (result) {\n            if (result && result.length) {\n                d.resolve(result[0]);\n            }\n\n            d.resolve(undefined);\n\n        }, function (result) {\n            d.reject(result);\n        });\n        return d.promise;\n\n    }\n\n    function compare(env, baseReleaseId, toCompareReleaseId) {\n        var d = $q.defer();\n        resource.compare({\n                             env: env,\n                             baseReleaseId: baseReleaseId,\n                             toCompareReleaseId: toCompareReleaseId\n                         }, function (result) {\n            d.resolve(result);\n        }, function (result) {\n            d.reject(result);\n        });\n        return d.promise;\n    }\n\n    function rollback(env, releaseId) {\n        var d = $q.defer();\n        resource.rollback({\n                              env: env,\n                              releaseId: releaseId\n                          }, {}, function (result) {\n                              d.resolve(result);\n                          }, function (result) {\n                              d.reject(result);\n                          }\n        );\n        return d.promise;\n\n    }\n\n    return {\n        publish: createRelease,\n        grayPublish: createGrayRelease,\n        findAllRelease: findAllReleases,\n        findActiveReleases: findActiveReleases,\n        findLatestActiveRelease: findLatestActiveRelease,\n        compare: compare,\n        rollback: rollback\n    }\n}]);\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/services/ServerConfigService.js",
    "content": "appService.service('ServerConfigService', ['$resource', '$q', function ($resource, $q) {\n    var server_config_resource = $resource('', {}, {\n        create_server_config: {\n            method: 'POST',\n            url: '/server/config'\n        }\n    });\n    return {\n        create: function (serverConfig) {\n            var d = $q.defer();\n            server_config_resource.create_server_config({}, serverConfig, function (result) {\n                d.resolve(result);\n            }, function (result) {\n                d.reject(result);\n            });\n            return d.promise;\n        }\n    }\n}]);\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/services/UserService.js",
    "content": "appService.service('UserService', ['$resource', '$q', function ($resource, $q) {\n    var user_resource = $resource('', {}, {\n        load_user: {\n            method: 'GET',\n            url: '/user'\n        },\n        find_users: {\n            method: 'GET',\n            url: '/users'\n        },\n        create_or_update_user: {\n            method: 'POST',\n            url: '/users'\n        }\n    });\n    return {\n        load_user: function () {\n            var finished = false;\n            var d = $q.defer();\n            user_resource.load_user({},\n                                    function (result) {\n                                        finished = true;\n                                        d.resolve(result);\n                                    },\n                                    function (result) {\n                                        finished = true;\n                                        d.reject(result);\n                                    });\n            return d.promise;\n        },\n        find_users: function (keyword) {\n            var d = $q.defer();\n            user_resource.find_users({\n                                         keyword: keyword\n                                     },\n                                     function (result) {\n                                         d.resolve(result);\n                                     },\n                                     function (result) {\n                                         d.reject(result);\n                                     });\n            return d.promise;\n        },\n        createOrUpdateUser: function (user) {\n            var d = $q.defer();\n            user_resource.create_or_update_user({}, user,\n                                     function (result) {\n                                         d.resolve(result);\n                                     },\n                                     function (result) {\n                                         d.reject(result);\n                                     });\n            return d.promise;   \n        }\n    }\n}]);\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/valdr.js",
    "content": "app_module.config(appValdr);\nsetting_module.config(appValdr);\n\nfunction appValdr(valdrProvider) {\n    valdrProvider.addConstraints({\n                                     'App': {\n                                         'appId': {\n                                             'size': {\n                                                 'max': 32,\n                                                 'message': 'AppId长度不能多于32个字符'\n                                             },\n                                             'required': {\n                                                 'message': 'AppId不能为空'\n                                             }\n                                         },\n                                         'appName': {\n                                             'size': {\n                                                 'max': 128,\n                                                 'message': '应用名称长度不能多于128个字符'\n                                             },\n                                             'required': {\n                                                 'message': '应用名称不能为空'\n                                             }\n                                         }\n                                     }\n                                 })\n}\n\ncluster_module.config(function (valdrProvider) {\n    valdrProvider.addConstraints({\n                                     'Cluster': {\n                                         'clusterName': {\n                                             'size': {\n                                                 'max': 32,\n                                                 'message': '集群名称长度不能多于32个字符'\n                                             },\n                                             'required': {\n                                                 'message': '集群名称不能为空'\n                                             }\n                                         }\n                                     }\n                                 })\n});\n\nnamespace_module.config(function (valdrProvider) {\n    valdrProvider.addConstraints({\n                                     'AppNamespace': {\n                                         'namespaceName': {\n                                             'size': {\n                                                 'max': 32,\n                                                 'message': 'Namespace名称长度不能多于32个字符'\n                                             },\n                                             'required': {\n                                                 'message': 'Namespace名称不能为空'\n                                             }\n                                         },\n                                         'comment': {\n                                             'size': {\n                                                 'max': 64,\n                                                 'message': '备注长度不能多于64个字符'\n                                             }\n                                         }\n                                     }\n                                 })\n});\n\napplication_module.config(function (valdrProvider) {\n    valdrProvider.addConstraints({\n                                     'Item': {\n                                         'key': {\n                                             'size': {\n                                                 'max': 128,\n                                                 'message': 'Key长度不能多于128个字符'\n                                             },\n                                             'required': {\n                                                 'message': 'Key不能为空'\n                                             }\n                                         }, \n                                         'value': {\n                                             'required': {\n                                                 'message': 'value不能为空'\n                                             }\n                                         },\n                                         'comment': {\n                                             'size': {\n                                                 'max': 64,\n                                                 'message': '备注长度不能多于64个字符'\n                                             }\n                                         }\n                                     },\n                                     'Release': {\n                                         'releaseName': {\n                                             'size': {\n                                                 'max': 64,\n                                                 'message': 'Release Name长度不能多于64个字符'\n                                             },\n                                             'required': {\n                                                 'message': 'Release Name不能为空'\n                                             }\n                                         },\n                                         'comment': {\n                                             'size': {\n                                                 'max': 64,\n                                                 'message': '备注长度不能多于64个字符'\n                                             }\n                                         }\n                                     }\n                                 })\n});\n\n\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/server_config.html",
    "content": "<!doctype html>\n<html ng-app=\"server_config\">\n<head>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n    <link rel=\"icon\" href=\"./img/config.png\">\n    <!-- styles -->\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"vendor/bootstrap/css/bootstrap.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"vendor/angular/angular-toastr-1.4.1.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" media='all' href=\"vendor/angular/loading-bar.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"styles/common-style.css\">\n    <title>应用配置</title>\n</head>\n\n<body>\n\n<apollonav></apollonav>\n<div class=\"container-fluid apollo-container\">\n\n    <div class=\"row\">\n        <div class=\"col-md-8 col-md-offset-2\">\n            <div class=\"panel\">\n                <header class=\"panel-heading\">\n                    应用配置\n                    <small>（维护ServerConfig表数据，如果已存在配置项则会覆盖，否则会创建配置项。配置更新后，一分钟后自动生效）</small>\n                </header>\n\n                <div class=\"panel-body\">\n                    <form class=\"form-horizontal\" ng-controller=\"ServerConfigController\" ng-submit=\"create()\">\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-2 control-label\">\n                                <apollorequiredfield></apollorequiredfield>\n                                key</label>\n                            <div class=\"col-sm-9\">\n                                <input type=\"text\" class=\"form-control\" name=\"key\" ng-model=\"serverConfig.key\"\n                                       required>\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-2 control-label\">\n                                <apollorequiredfield></apollorequiredfield>\n                                value</label>\n                            <div class=\"col-sm-9\">\n                                <textarea class=\"form-control\" rows=\"4\" name=\"comment\" ng-model=\"serverConfig.value\"></textarea>\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label class=\"col-sm-2 control-label\">\n                                comment</label>\n                            <div class=\"col-sm-9\">\n                                <textarea class=\"form-control\" rows=\"4\" name=\"comment\" ng-model=\"serverConfig.comment\"></textarea>\n                            </div>\n                        </div>\n\n                        <div class=\"form-group\">\n                            <div class=\"col-sm-offset-2 col-sm-10\">\n\n                                <button type=\"submit\" class=\"btn btn-primary\">提交</button>\n                            </div>\n                        </div>\n                    </form>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>\n\n<div ng-include=\"'views/common/footer.html'\"></div>\n\n<!--angular-->\n<script src=\"vendor/angular/angular.min.js\"></script>\n<script src=\"vendor/angular/angular-resource.min.js\"></script>\n<script src=\"vendor/angular/angular-toastr-1.4.1.tpls.min.js\"></script>\n<script src=\"vendor/angular/loading-bar.min.js\"></script>\n\n<!-- jquery.js -->\n<script src=\"vendor/jquery.min.js\" type=\"text/javascript\"></script>\n\n<!-- bootstrap.js -->\n<script src=\"vendor/bootstrap/js/bootstrap.min.js\" type=\"text/javascript\"></script>\n\n<script type=\"application/javascript\" src=\"scripts/app.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/directive/directive.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/AppUtils.js\"></script>\n\n<script type=\"application/javascript\" src=\"scripts/services/AppService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/EnvService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/UserService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/CommonService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/ServerConfigService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/PermissionService.js\"></script>\n\n<script type=\"application/javascript\" src=\"scripts/controller/ServerConfigController.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/styles/common-style.css",
    "content": "html, body {\n    height: 100%\n}\n\nbody {\n    min-width: 960px;\n    color: #797979;\n    padding: 0 !important;\n    margin: 0 !important;\n    font-size: 13px;\n    background: #f1f2f7;\n    font-family: 'Open Sans', sans-serif;\n}\n\nbody.modal-open {\n    overflow: visible;\n}\n\na {\n    cursor: pointer;\n}\n\np, td, span {\n    word-wrap: break-word;\n    word-break: break-all;\n}\n\n.modal {\n    overflow-y: scroll\n}\n\n.no-radius {\n    border-radius: 0;\n}\n\n.no-border {\n    border: 0;\n}\n\n.no-margin {\n    margin: 0;\n}\n\n.cursor-pointer {\n    cursor: pointer;\n}\n\n.word-break {\n    word-wrap: break-word;\n    word-break: break-all;\n}\n\n.border {\n    border: solid 1px #c3c3c3;\n}\n\n.padding-top-5 {\n    padding-top: 5px;\n}\n\n.border-top {\n    border-top: 1px solid #ddd;\n}\n\n.bg-info, .bg-primary, .bg-warning, .bg-danger, .bg-success {\n    padding: 10px;\n}\n\n.active {\n    background: #f5f5f5;\n}\n\n.label-default-light {\n    background: #A4A4A4\n}\n\n.panel-default .panel-heading {\n    color: #797979;\n}\n\npre {\n    white-space: pre-wrap; /* Since CSS 2.1 */\n    white-space: -moz-pre-wrap; /* Mozilla, since 1999 */\n    white-space: -pre-wrap; /* Opera 4-6 */\n    white-space: -o-pre-wrap; /* Opera 7 */\n    word-wrap: break-word; /* Internet Explorer 5.5+ */\n}\n\n.hover:hover {\n    background: #f5f5f5;\n    cursor: pointer\n}\n\n.highlight {\n    background: #ffa;\n}\n\n.hide-border-top {\n    border-top: 0;\n}\n\n.logo {\n    font-size: 25px;\n}\n\n.i-20 {\n    height: 20px;\n    width: 20px;\n}\n\n.i-25-20 {\n    height: 20px;\n    width: 25px;\n}\n\n.i-15 {\n    height: 15px;\n    width: 15px;\n}\n\n.badge {\n    padding: 1px 4px;\n}\n\n.badge-grey {\n    background: #777;\n    color: #fff;\n}\n\n.badge-white {\n    background: #ffffff;\n    color: #6c6c6c;\n}\n\n.modal-dialog {\n    width: 960px;\n}\n\n.apollo-container {\n    min-height: 90%;\n}\n\n.navbar-default {\n    background-color: #ffffff;\n    border: none;\n}\n\n.footer {\n    width: 100%;\n    height: 75px;\n    margin-top: 50px;\n    padding-top: 25px;\n}\n\n/*panel*/\n.panel {\n    border: 1px solid #ddd;\n}\n\ntable th {\n    text-align: center;\n}\n\n/*首页*/\n.site-notice {\n    padding: 5px 0;\n    text-align: center;\n    background-color: #208d4e;\n}\n\n.site-notice {\n    color: #eee;\n}\n\n.site-notice a {\n    color: #ffffff;\n}\n\n.site-notice a:hover {\n    text-underline: none;\n}\n\n.site-notice .selected {\n    color: #000000;\n}\n\n.site-header {\n    position: relative;\n    text-align: center;\n    background-color: #27AE60;\n    color: #fff;\n    margin-bottom: 0;\n}\n\n.site-header .search {\n    border: 2px solid #27AE60;\n    -webkit-box-shadow: none;\n    box-shadow: none;\n    font-size: 16px;\n    padding: 13px 30px;\n    border-radius: 0;\n    height: auto;\n    text-align: center;\n}\n\n.site-header h1 {\n    font-size: 56px;\n    text-shadow: -5px 5px 0 rgba(0, 0, 0, 0.1);\n}\n\n.site-header span {\n    font-size: 14px;\n}\n\n.list-group {\n    margin-top: 20px;\n}\n\n.side-bar {\n    position: absolute;\n    width: 195px;\n    top: 85px;\n    left: 15px;\n    margin-bottom: 25px;\n    background: #f1f2f7;\n    z-index: 2;\n}\n\n.position-absolute {\n    position: absolute;\n}\n\n.position-fix {\n    position: fixed;\n}\n\n.view-mode-1 {\n    margin-left: 235px;\n    padding-right: 15px;\n}\n\n.view-mode-2 {\n    padding: 0 15px;\n}\n\n.side-bar-switch {\n    padding: 10px 10px;\n    margin-right: 30px;\n}\n\n.node-treeview {\n    color: #797979;\n}\n\n.apps .apps-description {\n    color: gray;\n    font-size: 16px;\n}\n\n.app {\n    padding-bottom: 75px;\n    overflow: hidden;\n}\n\n.app td, th {\n    display: table-cell;\n    vertical-align: inherit;\n}\n\n.project-info {\n    width: 100%;\n}\n\n.panel-heading {\n    border-color: #eff2f7;\n    font-size: 16px;\n    font-weight: 300;\n}\n\n.panel-heading .header-namespace {\n    min-width: 415px;\n}\n\n.panel-heading .header-buttons {\n    min-width: 405px;\n}\n\n#treeview .list-group {\n    margin: 0;\n\n}\n\n#treeview .list-group .list-group-item {\n    border: 0;\n    border-top: 1px solid #eff2f7;\n}\n\n.project-info th {\n    text-align: right;\n    padding: 4px 6px;\n    white-space: nowrap;\n}\n\n.project-info td {\n    border-bottom: 1px dotted gray;\n    padding: 4px 6px;\n}\n\n#config-info {\n    min-height: 500px;\n}\n\n#config-edit {\n    border: 1px solid #ddd;\n    border-radius: 3px;\n}\n\n#config-edit .panel-heading {\n    border-bottom: 1px solid #ddd;\n}\n\n.tocify-header {\n    font-size: 14px;\n}\n\n.tocify-subheader {\n    font-size: 13px;\n}\n\n.config-item-container .panel {\n    border-radius: 0;\n}\n\n.config-item-container .panel-heading b {\n    font-size: 18px;\n}\n\n.config-item-container .form-control[disabled] {\n    background: #ffffff;\n    border: 0;\n}\n\n.config-item-container .second-panel-heading .ns_btn {\n    width: 25px;\n    height: 25px;\n    border-top: solid 1px #ffffff;\n}\n\n.config-item-container .second-panel-heading .nav-tabs .node_active {\n    border-bottom: 3px #1b6d85 solid;\n\n}\n\n.config-item-container .config-items {\n    height: 500px;\n    overflow: scroll;\n}\n\n.config-item-container .panel-heading button img {\n    width: 12px;\n    height: 12px;\n}\n\n.config-item-container .panel-heading a img {\n    width: 12px;\n    height: 12px;\n}\n\n.config-item-container .panel-heading li img {\n    width: 12px;\n    height: 12px;\n}\n\n.config-item-container .second-panel-heading {\n    height: 45px;\n}\n\n.config-item-container .second-panel-heading a {\n    height: 35px;\n    color: #555;\n    font-size: 13px;\n    margin-bottom: 2px;\n}\n\n.namespace-panel {\n    border-top: 0;\n    border-bottom: 0;\n}\n\n.namespace-panel .namespace-name {\n    font-size: 20px;\n}\n\n.namespace-panel .namespace-label {\n    margin-left: 5px;\n}\n\n.namespace-panel .namespace-attribute-panel {\n    margin-left: 0;\n    color: #fff;\n    border-top: 0;\n    background: #f1f2f7;\n}\n\n.namespace-panel .namespace-attribute-public {\n    background: #31708f;\n    width: 40px;\n    cursor: pointer;\n}\n\n.namespace-panel .second-panel-heading .nav-tabs {\n    border-bottom: 0;\n}\n\n.namespace-panel .namespace-view-table td img {\n    cursor: pointer;\n    width: 23px;\n    height: 23px;\n\n}\n\n.namespace-panel .namespace-view-table table {\n    table-layout: inherit;\n}\n\n.namespace-panel .namespace-view-table td {\n    word-wrap: break-word;\n}\n\n.namespace-panel .namespace-view-table .glyphicon {\n    cursor: pointer;\n}\n\n.namespace-panel .namespace-view-table .search-input {\n    padding: 15px 0 15px 10px;\n}\n\n.namespace-panel .namespace-view-table .search-input input {\n    width: 350px;\n}\n\n.namespace-panel .no-config-panel {\n    padding: 15px 0;\n}\n\n.namespace-panel .history-view {\n    padding: 10px 20px;\n\n}\n\n.namespace-panel .instance-view .btn-primary .badge {\n    color: #337ab7;\n    background-color: #fff;\n}\n\n.namespace-panel .instance-view .btn-default .badge {\n    background: #777;\n    color: #fff;\n}\n\n.namespace-panel .rules-manage-view {\n    padding: 45px 20px;\n}\n\n.line {\n    width: 20px;\n    border: 1px solid #ddd;\n}\n\n.editable-table > tbody > tr > td {\n    padding: 4px\n}\n\n.editable-text {\n    padding-left: 4px;\n    padding-top: 4px;\n    padding-bottom: 4px;\n    display: inline-block;\n}\n\n.editable-table tbody > tr > td > .controls {\n/ / width: 100 %\n}\n\n.editable-input {\n    padding-left: 3px;\n}\n\n.editable-input.input-sm {\n    height: 30px;\n    font-size: 14px;\n    padding-top: 4px;\n    padding-bottom: 4px;\n}\n\n.list-group-item .btn-title {\n    color: gray;\n    font-size: 14px;\n    margin: 0;\n}\n\n.list-group-item .icon-project-manage {\n    background: url(../img/manage.png) no-repeat;\n}\n\n.list-group-item .icon-plus-orange {\n    background: url(../img/add.png) no-repeat;\n}\n\n.list-group-item .icon-text {\n    background-size: 20px;\n    background-position: 5% 50%;\n    padding: 5px 0 5px 50px;\n}\n\n/*搜索框*/\n::-webkit-scrollbar {\n    width: 0;\n    height: 0;\n    background: rgba(255, 255, 255, 0);\n}\n\n::-webkit-scrollbar-thumb:vertical {\n    background: rgba(255, 255, 255, 0);\n    border-radius: 10px;\n}\n\n::-webkit-scrollbar-thumb:vertical:hover {\n    background: rgba(255, 255, 255, 0);\n}\n\n.app-list {\n    width: 350px;\n    height: 200px;\n    position: absolute;\n    margin-left: 0;\n    cursor: pointer;\n    background: #ffffff;\n    border: 1px solid #ddd;\n    overflow-y: scroll;\n    z-index: 1000;\n}\n\n.app-list .app-item {\n    font-size: medium;\n    padding: 5px 10px;\n\n}\n\n.app-list .app-item:hover {\n    color: #ffffff;\n    background: #C3C3C3;\n}\n\n.app-list .app-selected {\n    color: #ffffff;\n    background: #c3c3c3;\n}\n\n.item-container {\n    border: solid 1px #f1f2f7;\n    margin-top: 15px;\n    padding: 20px 15px\n}\n\n.item-container .item-info {\n    margin-left: 5px;\n}\n\n.change-type-mark {\n    width: 5px;\n    height: 5px;\n}\n\n.release-history .media-body {\n    padding-left: 20px;\n}\n\n.release-history .panel-body .load-more {\n    margin-top: 20px;\n}\n\n.release-history .media-body textarea {\n    margin-top: 10px;\n}\n\n.release-history .release-history-container {\n    padding: 0;\n}\n\n.release-history .release-history-list {\n    max-height: 750px;\n    padding: 0;\n    border-right: solid 1px #eff2f7;\n    overflow: scroll;\n}\n\n.release-history .release-history-list .media {\n    position: relative;\n    margin: 0;\n    padding: 10px;\n    border-bottom: solid 1px #eff2f7;\n}\n\n.release-history .release-history-list .release-operation {\n    position: absolute;\n    right: 0;\n    top: 0;\n    width: 5px;\n    height: 100%;\n}\n\n.release-history .release-history-list .media .media-left {\n    padding-top: 10px;\n}\n\n.release-history .release-history-list .media .media-body .release-title {\n    padding: 0;\n}\n\n.release-history .release-history-list .emergency-publish {\n    position: absolute;\n    left: 0;\n    top: 0;\n}\n\n.release-history .release-history-list .load-more {\n    height: 45px;\n    background: #f5f5f5;\n}\n\n.release-history .release-operation-normal {\n    background: #316510;\n}\n\n.release-history .release-operation-rollback {\n    background: #997f1c;\n}\n\n.release-history .release-operation-gray {\n    background: #999999;\n}\n\n.release-history .operation-caption-container {\n    position: relative;\n}\n\n.release-history .section-title {\n    padding: 15px 10px 0 10px;\n}\n\n.release-history .operation-caption {\n    position: absolute;\n    top: 45px;\n    width: 75px;\n    height: 18px;\n    color: #fff;\n    font-size: 12px;\n}\n\n.release-history .panel-heading .back-btn {\n    position: absolute;\n    top: 45px;\n    right: 10px;\n}\n\n.release-history .release-info {\n    padding: 0;\n    border: 0;\n}\n\n.release-history .panel-heading {\n    padding: 15px;\n}\n\n.empty-container {\n    padding: 15px;\n}\n\n.valdr-message {\n    display: none;\n}\n\n.valdr-message.ng-dirty.ng-invalid.ng-touched {\n    display: inline;\n    color: #a94442;\n}\n\n.form-group .form-control.ng-invalid.ng-dirty.ng-touched {\n    border-color: #a94442;\n}\n\n.app-not-found {\n    padding-top: 50px;\n    font-size: 18px;\n}\n\n/*index page*/\n#app-list h5 {\n    word-wrap: break-word;\n    word-break: break-all;\n}\n\n#app-list .media-body {\n    padding-top: 15px;\n}\n\n#app-list .media {\n    background: #fff;\n    display: table;\n}\n\n#app-list .media-left {\n    width: 1000px;\n    color: #fff;\n    display: table-cell;\n    vertical-align: middle;\n}\n\n#app-list .more-img {\n    width: 30px;\n    height: 30px;\n}\n\n#app-list .app-panel {\n    position: relative;\n    height: 100px;\n}\n\n#app-list .operate-panel {\n    position: absolute;\n    top: 5px;\n    right: 20px;\n}\n\n.create-app-list .media-left {\n    background: #a9d96c;\n}\n\n.create-app-list .create-btn {\n    background: #a9d96c;\n    color: #fff\n}\n\n.create-app-list .create-btn:hover {\n    background: #81AB56;\n}\n\n.create-app-list .create-btn img {\n    width: 26px;\n    height: 26px\n}\n\n.favorites-app-list .media-left {\n    background: #57c8f2;\n}\n\n.favorites-app-list .no-favorites {\n    padding-bottom: 15px;\n}\n\n.visit-app-list .media-left {\n    background: #41cac0;\n}\n\n#rulesModal .rules-ip-selector {\n    width: 500px;\n    height: 50px;\n}\n\n#rulesModal textarea {\n    width: 500px;\n    margin-bottom: 5px;\n}\n\n#rulesModal .rule-edit-panel {\n    padding: 15px 0;\n}\n\n#rulesModal .add-rule {\n    margin-left: 15px;\n}\n\n#rulesModal .select2-container .select2-search__field:not([placeholder='']) {\n    width: auto !important;\n}\n\n.search-onblur {\n    width: 165px;\n    background: #f5f5f5;\n}\n\n.search-focus {\n    width: 165px;\n    background: #fff;\n}\n\n.project-setting .panel-body {\n    padding-top: 35px\n}\n\n.project-setting .panel-body .context {\n    padding-left: 30px;\n}\n\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/user-manage.html",
    "content": "<!doctype html>\n<html ng-app=\"user\">\n<head>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n    <link rel=\"icon\" href=\"./img/config.png\">\n    <!-- styles -->\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"vendor/bootstrap/css/bootstrap.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"vendor/angular/angular-toastr-1.4.1.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"vendor/select2/select2.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" media='all' href=\"vendor/angular/loading-bar.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"styles/common-style.css\">\n\n    <title>用户管理</title>\n</head>\n\n<body>\n\n<apollonav></apollonav>\n<div class=\"container-fluid apollo-container\">\n\n    <div class=\"row\">\n        <div class=\"col-md-8 col-md-offset-2\">\n            <div class=\"panel\">\n                <header class=\"panel-heading\">\n                    用户管理\n                </header>\n\n                <form class=\"form-horizontal panel-body\" name=\"appForm\" ng-controller=\"UserController\"\n                      valdr-type=\"App\"\n                      ng-submit=\"createOrUpdateUser()\">\n                    <div class=\"form-group\" valdr-form-group>\n                        <label class=\"col-sm-2 control-label\">\n                            <apollorequiredfield></apollorequiredfield>\n                            用户名</label>\n                        <div class=\"col-sm-4\">\n                            <input type=\"text\" class=\"form-control\" name=\"username\" ng-model=\"user.username\">\n                        </div>\n                    </div>\n                    <div class=\"form-group\" valdr-form-group>\n                        <label class=\"col-sm-2 control-label\">\n                            <apollorequiredfield></apollorequiredfield>\n                            密码</label>\n                        <div class=\"col-sm-4\">\n                            <input type=\"text\" class=\"form-control\" name=\"password\" ng-model=\"user.password\">\n                        </div>\n                    </div>\n                    <div class=\"form-group\" valdr-form-group>\n                        <label class=\"col-sm-2 control-label\">\n                            <apollorequiredfield></apollorequiredfield>\n                            邮箱</label>\n                        <div class=\"col-sm-4\">\n                            <input type=\"text\" class=\"form-control\" name=\"password\" ng-model=\"user.email\">\n                        </div>\n                    </div>\n\n                    <div class=\"form-group\">\n                        <div class=\"col-sm-offset-2 col-sm-9\">\n\n                            <button type=\"submit\" class=\"btn btn-primary\"\n                                    ng-disabled=\"appForm.$invalid || submitBtnDisabled\">提交\n                            </button>\n                        </div>\n                    </div>\n                </form>\n\n            </div>\n        </div>\n    </div>\n</div>\n\n<div ng-include=\"'views/common/footer.html'\"></div>\n\n<!--angular-->\n<script src=\"vendor/angular/angular.min.js\"></script>\n<script src=\"vendor/angular/angular-resource.min.js\"></script>\n<script src=\"vendor/angular/angular-toastr-1.4.1.tpls.min.js\"></script>\n<script src=\"vendor/angular/loading-bar.min.js\"></script>\n\n<!-- jquery.js -->\n<script src=\"vendor/jquery.min.js\" type=\"text/javascript\"></script>\n<script src=\"vendor/select2/select2.min.js\" type=\"text/javascript\"></script>\n\n<!-- bootstrap.js -->\n<script src=\"vendor/bootstrap/js/bootstrap.min.js\" type=\"text/javascript\"></script>\n\n<!--valdr-->\n<script src=\"vendor/valdr/valdr.min.js\" type=\"text/javascript\"></script>\n<script src=\"vendor/valdr/valdr-message.min.js\" type=\"text/javascript\"></script>\n\n<script type=\"application/javascript\" src=\"scripts/app.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/AppService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/EnvService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/UserService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/CommonService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/AppUtils.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/OrganizationService.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/directive/directive.js\"></script>\n<script type=\"application/javascript\" src=\"scripts/services/PermissionService.js\"></script>\n\n<script type=\"application/javascript\" src=\"scripts/controller/UserController.js\"></script>\n\n<script src=\"scripts/valdr.js\" type=\"text/javascript\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/vendor/ui-ace/ace.js",
    "content": "(function(){function o(n){var i=e;n&&(e[n]||(e[n]={}),i=e[n]);if(!i.define||!i.define.packaged)t.original=i.define,i.define=t,i.define.packaged=!0;if(!i.require||!i.require.packaged)r.original=i.require,i.require=r,i.require.packaged=!0}var ACE_NAMESPACE=\"\",e=function(){return this}();!e&&typeof window!=\"undefined\"&&(e=window);if(!ACE_NAMESPACE&&typeof requirejs!=\"undefined\")return;var t=function(e,n,r){if(typeof e!=\"string\"){t.original?t.original.apply(this,arguments):(console.error(\"dropping module because define wasn't a string.\"),console.trace());return}arguments.length==2&&(r=n),t.modules[e]||(t.payloads[e]=r,t.modules[e]=null)};t.modules={},t.payloads={};var n=function(e,t,n){if(typeof t==\"string\"){var i=s(e,t);if(i!=undefined)return n&&n(),i}else if(Object.prototype.toString.call(t)===\"[object Array]\"){var o=[];for(var u=0,a=t.length;u<a;++u){var f=s(e,t[u]);if(f==undefined&&r.original)return;o.push(f)}return n&&n.apply(null,o)||!0}},r=function(e,t){var i=n(\"\",e,t);return i==undefined&&r.original?r.original.apply(this,arguments):i},i=function(e,t){if(t.indexOf(\"!\")!==-1){var n=t.split(\"!\");return i(e,n[0])+\"!\"+i(e,n[1])}if(t.charAt(0)==\".\"){var r=e.split(\"/\").slice(0,-1).join(\"/\");t=r+\"/\"+t;while(t.indexOf(\".\")!==-1&&s!=t){var s=t;t=t.replace(/\\/\\.\\//,\"/\").replace(/[^\\/]+\\/\\.\\.\\//,\"\")}}return t},s=function(e,r){r=i(e,r);var s=t.modules[r];if(!s){s=t.payloads[r];if(typeof s==\"function\"){var o={},u={id:r,uri:\"\",exports:o,packaged:!0},a=function(e,t){return n(r,e,t)},f=s(a,o,u);o=f||u.exports,t.modules[r]=o,delete t.payloads[r]}s=t.modules[r]=o||s}return s};o(ACE_NAMESPACE)})(),define(\"ace/lib/regexp\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";function o(e){return(e.global?\"g\":\"\")+(e.ignoreCase?\"i\":\"\")+(e.multiline?\"m\":\"\")+(e.extended?\"x\":\"\")+(e.sticky?\"y\":\"\")}function u(e,t,n){if(Array.prototype.indexOf)return e.indexOf(t,n);for(var r=n||0;r<e.length;r++)if(e[r]===t)return r;return-1}var r={exec:RegExp.prototype.exec,test:RegExp.prototype.test,match:String.prototype.match,replace:String.prototype.replace,split:String.prototype.split},i=r.exec.call(/()??/,\"\")[1]===undefined,s=function(){var e=/^/g;return r.test.call(e,\"\"),!e.lastIndex}();if(s&&i)return;RegExp.prototype.exec=function(e){var t=r.exec.apply(this,arguments),n,a;if(typeof e==\"string\"&&t){!i&&t.length>1&&u(t,\"\")>-1&&(a=RegExp(this.source,r.replace.call(o(this),\"g\",\"\")),r.replace.call(e.slice(t.index),a,function(){for(var e=1;e<arguments.length-2;e++)arguments[e]===undefined&&(t[e]=undefined)}));if(this._xregexp&&this._xregexp.captureNames)for(var f=1;f<t.length;f++)n=this._xregexp.captureNames[f-1],n&&(t[n]=t[f]);!s&&this.global&&!t[0].length&&this.lastIndex>t.index&&this.lastIndex--}return t},s||(RegExp.prototype.test=function(e){var t=r.exec.call(this,e);return t&&this.global&&!t[0].length&&this.lastIndex>t.index&&this.lastIndex--,!!t})}),define(\"ace/lib/es5-shim\",[\"require\",\"exports\",\"module\"],function(e,t,n){function r(){}function w(e){try{return Object.defineProperty(e,\"sentinel\",{}),\"sentinel\"in e}catch(t){}}function H(e){return e=+e,e!==e?e=0:e!==0&&e!==1/0&&e!==-1/0&&(e=(e>0||-1)*Math.floor(Math.abs(e))),e}function B(e){var t=typeof e;return e===null||t===\"undefined\"||t===\"boolean\"||t===\"number\"||t===\"string\"}function j(e){var t,n,r;if(B(e))return e;n=e.valueOf;if(typeof n==\"function\"){t=n.call(e);if(B(t))return t}r=e.toString;if(typeof r==\"function\"){t=r.call(e);if(B(t))return t}throw new TypeError}Function.prototype.bind||(Function.prototype.bind=function(t){var n=this;if(typeof n!=\"function\")throw new TypeError(\"Function.prototype.bind called on incompatible \"+n);var i=u.call(arguments,1),s=function(){if(this instanceof s){var e=n.apply(this,i.concat(u.call(arguments)));return Object(e)===e?e:this}return n.apply(t,i.concat(u.call(arguments)))};return n.prototype&&(r.prototype=n.prototype,s.prototype=new r,r.prototype=null),s});var i=Function.prototype.call,s=Array.prototype,o=Object.prototype,u=s.slice,a=i.bind(o.toString),f=i.bind(o.hasOwnProperty),l,c,h,p,d;if(d=f(o,\"__defineGetter__\"))l=i.bind(o.__defineGetter__),c=i.bind(o.__defineSetter__),h=i.bind(o.__lookupGetter__),p=i.bind(o.__lookupSetter__);if([1,2].splice(0).length!=2)if(!function(){function e(e){var t=new Array(e+2);return t[0]=t[1]=0,t}var t=[],n;t.splice.apply(t,e(20)),t.splice.apply(t,e(26)),n=t.length,t.splice(5,0,\"XXX\"),n+1==t.length;if(n+1==t.length)return!0}())Array.prototype.splice=function(e,t){var n=this.length;e>0?e>n&&(e=n):e==void 0?e=0:e<0&&(e=Math.max(n+e,0)),e+t<n||(t=n-e);var r=this.slice(e,e+t),i=u.call(arguments,2),s=i.length;if(e===n)s&&this.push.apply(this,i);else{var o=Math.min(t,n-e),a=e+o,f=a+s-o,l=n-a,c=n-o;if(f<a)for(var h=0;h<l;++h)this[f+h]=this[a+h];else if(f>a)for(h=l;h--;)this[f+h]=this[a+h];if(s&&e===c)this.length=c,this.push.apply(this,i);else{this.length=c+s;for(h=0;h<s;++h)this[e+h]=i[h]}}return r};else{var v=Array.prototype.splice;Array.prototype.splice=function(e,t){return arguments.length?v.apply(this,[e===void 0?0:e,t===void 0?this.length-e:t].concat(u.call(arguments,2))):[]}}Array.isArray||(Array.isArray=function(t){return a(t)==\"[object Array]\"});var m=Object(\"a\"),g=m[0]!=\"a\"||!(0 in m);Array.prototype.forEach||(Array.prototype.forEach=function(t){var n=F(this),r=g&&a(this)==\"[object String]\"?this.split(\"\"):n,i=arguments[1],s=-1,o=r.length>>>0;if(a(t)!=\"[object Function]\")throw new TypeError;while(++s<o)s in r&&t.call(i,r[s],s,n)}),Array.prototype.map||(Array.prototype.map=function(t){var n=F(this),r=g&&a(this)==\"[object String]\"?this.split(\"\"):n,i=r.length>>>0,s=Array(i),o=arguments[1];if(a(t)!=\"[object Function]\")throw new TypeError(t+\" is not a function\");for(var u=0;u<i;u++)u in r&&(s[u]=t.call(o,r[u],u,n));return s}),Array.prototype.filter||(Array.prototype.filter=function(t){var n=F(this),r=g&&a(this)==\"[object String]\"?this.split(\"\"):n,i=r.length>>>0,s=[],o,u=arguments[1];if(a(t)!=\"[object Function]\")throw new TypeError(t+\" is not a function\");for(var f=0;f<i;f++)f in r&&(o=r[f],t.call(u,o,f,n)&&s.push(o));return s}),Array.prototype.every||(Array.prototype.every=function(t){var n=F(this),r=g&&a(this)==\"[object String]\"?this.split(\"\"):n,i=r.length>>>0,s=arguments[1];if(a(t)!=\"[object Function]\")throw new TypeError(t+\" is not a function\");for(var o=0;o<i;o++)if(o in r&&!t.call(s,r[o],o,n))return!1;return!0}),Array.prototype.some||(Array.prototype.some=function(t){var n=F(this),r=g&&a(this)==\"[object String]\"?this.split(\"\"):n,i=r.length>>>0,s=arguments[1];if(a(t)!=\"[object Function]\")throw new TypeError(t+\" is not a function\");for(var o=0;o<i;o++)if(o in r&&t.call(s,r[o],o,n))return!0;return!1}),Array.prototype.reduce||(Array.prototype.reduce=function(t){var n=F(this),r=g&&a(this)==\"[object String]\"?this.split(\"\"):n,i=r.length>>>0;if(a(t)!=\"[object Function]\")throw new TypeError(t+\" is not a function\");if(!i&&arguments.length==1)throw new TypeError(\"reduce of empty array with no initial value\");var s=0,o;if(arguments.length>=2)o=arguments[1];else do{if(s in r){o=r[s++];break}if(++s>=i)throw new TypeError(\"reduce of empty array with no initial value\")}while(!0);for(;s<i;s++)s in r&&(o=t.call(void 0,o,r[s],s,n));return o}),Array.prototype.reduceRight||(Array.prototype.reduceRight=function(t){var n=F(this),r=g&&a(this)==\"[object String]\"?this.split(\"\"):n,i=r.length>>>0;if(a(t)!=\"[object Function]\")throw new TypeError(t+\" is not a function\");if(!i&&arguments.length==1)throw new TypeError(\"reduceRight of empty array with no initial value\");var s,o=i-1;if(arguments.length>=2)s=arguments[1];else do{if(o in r){s=r[o--];break}if(--o<0)throw new TypeError(\"reduceRight of empty array with no initial value\")}while(!0);do o in this&&(s=t.call(void 0,s,r[o],o,n));while(o--);return s});if(!Array.prototype.indexOf||[0,1].indexOf(1,2)!=-1)Array.prototype.indexOf=function(t){var n=g&&a(this)==\"[object String]\"?this.split(\"\"):F(this),r=n.length>>>0;if(!r)return-1;var i=0;arguments.length>1&&(i=H(arguments[1])),i=i>=0?i:Math.max(0,r+i);for(;i<r;i++)if(i in n&&n[i]===t)return i;return-1};if(!Array.prototype.lastIndexOf||[0,1].lastIndexOf(0,-3)!=-1)Array.prototype.lastIndexOf=function(t){var n=g&&a(this)==\"[object String]\"?this.split(\"\"):F(this),r=n.length>>>0;if(!r)return-1;var i=r-1;arguments.length>1&&(i=Math.min(i,H(arguments[1]))),i=i>=0?i:r-Math.abs(i);for(;i>=0;i--)if(i in n&&t===n[i])return i;return-1};Object.getPrototypeOf||(Object.getPrototypeOf=function(t){return t.__proto__||(t.constructor?t.constructor.prototype:o)});if(!Object.getOwnPropertyDescriptor){var y=\"Object.getOwnPropertyDescriptor called on a non-object: \";Object.getOwnPropertyDescriptor=function(t,n){if(typeof t!=\"object\"&&typeof t!=\"function\"||t===null)throw new TypeError(y+t);if(!f(t,n))return;var r,i,s;r={enumerable:!0,configurable:!0};if(d){var u=t.__proto__;t.__proto__=o;var i=h(t,n),s=p(t,n);t.__proto__=u;if(i||s)return i&&(r.get=i),s&&(r.set=s),r}return r.value=t[n],r}}Object.getOwnPropertyNames||(Object.getOwnPropertyNames=function(t){return Object.keys(t)});if(!Object.create){var b;Object.prototype.__proto__===null?b=function(){return{__proto__:null}}:b=function(){var e={};for(var t in e)e[t]=null;return e.constructor=e.hasOwnProperty=e.propertyIsEnumerable=e.isPrototypeOf=e.toLocaleString=e.toString=e.valueOf=e.__proto__=null,e},Object.create=function(t,n){var r;if(t===null)r=b();else{if(typeof t!=\"object\")throw new TypeError(\"typeof prototype[\"+typeof t+\"] != 'object'\");var i=function(){};i.prototype=t,r=new i,r.__proto__=t}return n!==void 0&&Object.defineProperties(r,n),r}}if(Object.defineProperty){var E=w({}),S=typeof document==\"undefined\"||w(document.createElement(\"div\"));if(!E||!S)var x=Object.defineProperty}if(!Object.defineProperty||x){var T=\"Property description must be an object: \",N=\"Object.defineProperty called on non-object: \",C=\"getters & setters can not be defined on this javascript engine\";Object.defineProperty=function(t,n,r){if(typeof t!=\"object\"&&typeof t!=\"function\"||t===null)throw new TypeError(N+t);if(typeof r!=\"object\"&&typeof r!=\"function\"||r===null)throw new TypeError(T+r);if(x)try{return x.call(Object,t,n,r)}catch(i){}if(f(r,\"value\"))if(d&&(h(t,n)||p(t,n))){var s=t.__proto__;t.__proto__=o,delete t[n],t[n]=r.value,t.__proto__=s}else t[n]=r.value;else{if(!d)throw new TypeError(C);f(r,\"get\")&&l(t,n,r.get),f(r,\"set\")&&c(t,n,r.set)}return t}}Object.defineProperties||(Object.defineProperties=function(t,n){for(var r in n)f(n,r)&&Object.defineProperty(t,r,n[r]);return t}),Object.seal||(Object.seal=function(t){return t}),Object.freeze||(Object.freeze=function(t){return t});try{Object.freeze(function(){})}catch(k){Object.freeze=function(t){return function(n){return typeof n==\"function\"?n:t(n)}}(Object.freeze)}Object.preventExtensions||(Object.preventExtensions=function(t){return t}),Object.isSealed||(Object.isSealed=function(t){return!1}),Object.isFrozen||(Object.isFrozen=function(t){return!1}),Object.isExtensible||(Object.isExtensible=function(t){if(Object(t)===t)throw new TypeError;var n=\"\";while(f(t,n))n+=\"?\";t[n]=!0;var r=f(t,n);return delete t[n],r});if(!Object.keys){var L=!0,A=[\"toString\",\"toLocaleString\",\"valueOf\",\"hasOwnProperty\",\"isPrototypeOf\",\"propertyIsEnumerable\",\"constructor\"],O=A.length;for(var M in{toString:null})L=!1;Object.keys=function I(e){if(typeof e!=\"object\"&&typeof e!=\"function\"||e===null)throw new TypeError(\"Object.keys called on a non-object\");var I=[];for(var t in e)f(e,t)&&I.push(t);if(L)for(var n=0,r=O;n<r;n++){var i=A[n];f(e,i)&&I.push(i)}return I}}Date.now||(Date.now=function(){return(new Date).getTime()});var _=\"\t\\n\u000b\\f\\r \\u00a0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029\\ufeff\";if(!String.prototype.trim||_.trim()){_=\"[\"+_+\"]\";var D=new RegExp(\"^\"+_+_+\"*\"),P=new RegExp(_+_+\"*$\");String.prototype.trim=function(){return String(this).replace(D,\"\").replace(P,\"\")}}var F=function(e){if(e==null)throw new TypeError(\"can't convert \"+e+\" to object\");return Object(e)}}),define(\"ace/lib/fixoldbrowsers\",[\"require\",\"exports\",\"module\",\"ace/lib/regexp\",\"ace/lib/es5-shim\"],function(e,t,n){\"use strict\";e(\"./regexp\"),e(\"./es5-shim\")}),define(\"ace/lib/dom\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";var r=\"http://www.w3.org/1999/xhtml\";t.getDocumentHead=function(e){return e||(e=document),e.head||e.getElementsByTagName(\"head\")[0]||e.documentElement},t.createElement=function(e,t){return document.createElementNS?document.createElementNS(t||r,e):document.createElement(e)},t.hasCssClass=function(e,t){var n=(e.className+\"\").split(/\\s+/g);return n.indexOf(t)!==-1},t.addCssClass=function(e,n){t.hasCssClass(e,n)||(e.className+=\" \"+n)},t.removeCssClass=function(e,t){var n=e.className.split(/\\s+/g);for(;;){var r=n.indexOf(t);if(r==-1)break;n.splice(r,1)}e.className=n.join(\" \")},t.toggleCssClass=function(e,t){var n=e.className.split(/\\s+/g),r=!0;for(;;){var i=n.indexOf(t);if(i==-1)break;r=!1,n.splice(i,1)}return r&&n.push(t),e.className=n.join(\" \"),r},t.setCssClass=function(e,n,r){r?t.addCssClass(e,n):t.removeCssClass(e,n)},t.hasCssString=function(e,t){var n=0,r;t=t||document;if(t.createStyleSheet&&(r=t.styleSheets)){while(n<r.length)if(r[n++].owningElement.id===e)return!0}else if(r=t.getElementsByTagName(\"style\"))while(n<r.length)if(r[n++].id===e)return!0;return!1},t.importCssString=function(n,r,i){i=i||document;if(r&&t.hasCssString(r,i))return null;var s;r&&(n+=\"\\n/*# sourceURL=ace/css/\"+r+\" */\"),i.createStyleSheet?(s=i.createStyleSheet(),s.cssText=n,r&&(s.owningElement.id=r)):(s=t.createElement(\"style\"),s.appendChild(i.createTextNode(n)),r&&(s.id=r),t.getDocumentHead(i).appendChild(s))},t.importCssStylsheet=function(e,n){if(n.createStyleSheet)n.createStyleSheet(e);else{var r=t.createElement(\"link\");r.rel=\"stylesheet\",r.href=e,t.getDocumentHead(n).appendChild(r)}},t.getInnerWidth=function(e){return parseInt(t.computedStyle(e,\"paddingLeft\"),10)+parseInt(t.computedStyle(e,\"paddingRight\"),10)+e.clientWidth},t.getInnerHeight=function(e){return parseInt(t.computedStyle(e,\"paddingTop\"),10)+parseInt(t.computedStyle(e,\"paddingBottom\"),10)+e.clientHeight},t.scrollbarWidth=function(e){var n=t.createElement(\"ace_inner\");n.style.width=\"100%\",n.style.minWidth=\"0px\",n.style.height=\"200px\",n.style.display=\"block\";var r=t.createElement(\"ace_outer\"),i=r.style;i.position=\"absolute\",i.left=\"-10000px\",i.overflow=\"hidden\",i.width=\"200px\",i.minWidth=\"0px\",i.height=\"150px\",i.display=\"block\",r.appendChild(n);var s=e.documentElement;s.appendChild(r);var o=n.offsetWidth;i.overflow=\"scroll\";var u=n.offsetWidth;return o==u&&(u=r.clientWidth),s.removeChild(r),o-u};if(typeof document==\"undefined\"){t.importCssString=function(){};return}window.pageYOffset!==undefined?(t.getPageScrollTop=function(){return window.pageYOffset},t.getPageScrollLeft=function(){return window.pageXOffset}):(t.getPageScrollTop=function(){return document.body.scrollTop},t.getPageScrollLeft=function(){return document.body.scrollLeft}),window.getComputedStyle?t.computedStyle=function(e,t){return t?(window.getComputedStyle(e,\"\")||{})[t]||\"\":window.getComputedStyle(e,\"\")||{}}:t.computedStyle=function(e,t){return t?e.currentStyle[t]:e.currentStyle},t.setInnerHtml=function(e,t){var n=e.cloneNode(!1);return n.innerHTML=t,e.parentNode.replaceChild(n,e),n},\"textContent\"in document.documentElement?(t.setInnerText=function(e,t){e.textContent=t},t.getInnerText=function(e){return e.textContent}):(t.setInnerText=function(e,t){e.innerText=t},t.getInnerText=function(e){return e.innerText}),t.getParentWindow=function(e){return e.defaultView||e.parentWindow}}),define(\"ace/lib/oop\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";t.inherits=function(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})},t.mixin=function(e,t){for(var n in t)e[n]=t[n];return e},t.implement=function(e,n){t.mixin(e,n)}}),define(\"ace/lib/keys\",[\"require\",\"exports\",\"module\",\"ace/lib/fixoldbrowsers\",\"ace/lib/oop\"],function(e,t,n){\"use strict\";e(\"./fixoldbrowsers\");var r=e(\"./oop\"),i=function(){var e={MODIFIER_KEYS:{16:\"Shift\",17:\"Ctrl\",18:\"Alt\",224:\"Meta\"},KEY_MODS:{ctrl:1,alt:2,option:2,shift:4,\"super\":8,meta:8,command:8,cmd:8},FUNCTION_KEYS:{8:\"Backspace\",9:\"Tab\",13:\"Return\",19:\"Pause\",27:\"Esc\",32:\"Space\",33:\"PageUp\",34:\"PageDown\",35:\"End\",36:\"Home\",37:\"Left\",38:\"Up\",39:\"Right\",40:\"Down\",44:\"Print\",45:\"Insert\",46:\"Delete\",96:\"Numpad0\",97:\"Numpad1\",98:\"Numpad2\",99:\"Numpad3\",100:\"Numpad4\",101:\"Numpad5\",102:\"Numpad6\",103:\"Numpad7\",104:\"Numpad8\",105:\"Numpad9\",\"-13\":\"NumpadEnter\",112:\"F1\",113:\"F2\",114:\"F3\",115:\"F4\",116:\"F5\",117:\"F6\",118:\"F7\",119:\"F8\",120:\"F9\",121:\"F10\",122:\"F11\",123:\"F12\",144:\"Numlock\",145:\"Scrolllock\"},PRINTABLE_KEYS:{32:\" \",48:\"0\",49:\"1\",50:\"2\",51:\"3\",52:\"4\",53:\"5\",54:\"6\",55:\"7\",56:\"8\",57:\"9\",59:\";\",61:\"=\",65:\"a\",66:\"b\",67:\"c\",68:\"d\",69:\"e\",70:\"f\",71:\"g\",72:\"h\",73:\"i\",74:\"j\",75:\"k\",76:\"l\",77:\"m\",78:\"n\",79:\"o\",80:\"p\",81:\"q\",82:\"r\",83:\"s\",84:\"t\",85:\"u\",86:\"v\",87:\"w\",88:\"x\",89:\"y\",90:\"z\",107:\"+\",109:\"-\",110:\".\",186:\";\",187:\"=\",188:\",\",189:\"-\",190:\".\",191:\"/\",192:\"`\",219:\"[\",220:\"\\\\\",221:\"]\",222:\"'\",111:\"/\",106:\"*\"}},t,n;for(n in e.FUNCTION_KEYS)t=e.FUNCTION_KEYS[n].toLowerCase(),e[t]=parseInt(n,10);for(n in e.PRINTABLE_KEYS)t=e.PRINTABLE_KEYS[n].toLowerCase(),e[t]=parseInt(n,10);return r.mixin(e,e.MODIFIER_KEYS),r.mixin(e,e.PRINTABLE_KEYS),r.mixin(e,e.FUNCTION_KEYS),e.enter=e[\"return\"],e.escape=e.esc,e.del=e[\"delete\"],e[173]=\"-\",function(){var t=[\"cmd\",\"ctrl\",\"alt\",\"shift\"];for(var n=Math.pow(2,t.length);n--;)e.KEY_MODS[n]=t.filter(function(t){return n&e.KEY_MODS[t]}).join(\"-\")+\"-\"}(),e.KEY_MODS[0]=\"\",e.KEY_MODS[-1]=\"input-\",e}();r.mixin(t,i),t.keyCodeToString=function(e){var t=i[e];return typeof t!=\"string\"&&(t=String.fromCharCode(e)),t.toLowerCase()}}),define(\"ace/lib/useragent\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";t.OS={LINUX:\"LINUX\",MAC:\"MAC\",WINDOWS:\"WINDOWS\"},t.getOS=function(){return t.isMac?t.OS.MAC:t.isLinux?t.OS.LINUX:t.OS.WINDOWS};if(typeof navigator!=\"object\")return;var r=(navigator.platform.match(/mac|win|linux/i)||[\"other\"])[0].toLowerCase(),i=navigator.userAgent;t.isWin=r==\"win\",t.isMac=r==\"mac\",t.isLinux=r==\"linux\",t.isIE=navigator.appName==\"Microsoft Internet Explorer\"||navigator.appName.indexOf(\"MSAppHost\")>=0?parseFloat((i.match(/(?:MSIE |Trident\\/[0-9]+[\\.0-9]+;.*rv:)([0-9]+[\\.0-9]+)/)||[])[1]):parseFloat((i.match(/(?:Trident\\/[0-9]+[\\.0-9]+;.*rv:)([0-9]+[\\.0-9]+)/)||[])[1]),t.isOldIE=t.isIE&&t.isIE<9,t.isGecko=t.isMozilla=(window.Controllers||window.controllers)&&window.navigator.product===\"Gecko\",t.isOldGecko=t.isGecko&&parseInt((i.match(/rv:(\\d+)/)||[])[1],10)<4,t.isOpera=window.opera&&Object.prototype.toString.call(window.opera)==\"[object Opera]\",t.isWebKit=parseFloat(i.split(\"WebKit/\")[1])||undefined,t.isChrome=parseFloat(i.split(\" Chrome/\")[1])||undefined,t.isAIR=i.indexOf(\"AdobeAIR\")>=0,t.isIPad=i.indexOf(\"iPad\")>=0,t.isChromeOS=i.indexOf(\" CrOS \")>=0,t.isIOS=/iPad|iPhone|iPod/.test(i)&&!window.MSStream,t.isIOS&&(t.isMac=!0)}),define(\"ace/lib/event\",[\"require\",\"exports\",\"module\",\"ace/lib/keys\",\"ace/lib/useragent\"],function(e,t,n){\"use strict\";function a(e,t,n){var a=u(t);if(!i.isMac&&s){t.getModifierState&&(t.getModifierState(\"OS\")||t.getModifierState(\"Win\"))&&(a|=8);if(s.altGr){if((3&a)==3)return;s.altGr=0}if(n===18||n===17){var f=\"location\"in t?t.location:t.keyLocation;if(n===17&&f===1)s[n]==1&&(o=t.timeStamp);else if(n===18&&a===3&&f===2){var l=t.timeStamp-o;l<50&&(s.altGr=!0)}}}n in r.MODIFIER_KEYS&&(n=-1),a&8&&n>=91&&n<=93&&(n=-1);if(!a&&n===13){var f=\"location\"in t?t.location:t.keyLocation;if(f===3){e(t,a,-n);if(t.defaultPrevented)return}}if(i.isChromeOS&&a&8){e(t,a,n);if(t.defaultPrevented)return;a&=-9}return!!a||n in r.FUNCTION_KEYS||n in r.PRINTABLE_KEYS?e(t,a,n):!1}function f(){s=Object.create(null)}var r=e(\"./keys\"),i=e(\"./useragent\"),s=null,o=0;t.addListener=function(e,t,n){if(e.addEventListener)return e.addEventListener(t,n,!1);if(e.attachEvent){var r=function(){n.call(e,window.event)};n._wrapper=r,e.attachEvent(\"on\"+t,r)}},t.removeListener=function(e,t,n){if(e.removeEventListener)return e.removeEventListener(t,n,!1);e.detachEvent&&e.detachEvent(\"on\"+t,n._wrapper||n)},t.stopEvent=function(e){return t.stopPropagation(e),t.preventDefault(e),!1},t.stopPropagation=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},t.preventDefault=function(e){e.preventDefault?e.preventDefault():e.returnValue=!1},t.getButton=function(e){return e.type==\"dblclick\"?0:e.type==\"contextmenu\"||i.isMac&&e.ctrlKey&&!e.altKey&&!e.shiftKey?2:e.preventDefault?e.button:{1:0,2:2,4:1}[e.button]},t.capture=function(e,n,r){function i(e){n&&n(e),r&&r(e),t.removeListener(document,\"mousemove\",n,!0),t.removeListener(document,\"mouseup\",i,!0),t.removeListener(document,\"dragstart\",i,!0)}return t.addListener(document,\"mousemove\",n,!0),t.addListener(document,\"mouseup\",i,!0),t.addListener(document,\"dragstart\",i,!0),i},t.addTouchMoveListener=function(e,n){var r,i;t.addListener(e,\"touchstart\",function(e){var t=e.touches,n=t[0];r=n.clientX,i=n.clientY}),t.addListener(e,\"touchmove\",function(e){var t=e.touches;if(t.length>1)return;var s=t[0];e.wheelX=r-s.clientX,e.wheelY=i-s.clientY,r=s.clientX,i=s.clientY,n(e)})},t.addMouseWheelListener=function(e,n){\"onmousewheel\"in e?t.addListener(e,\"mousewheel\",function(e){var t=8;e.wheelDeltaX!==undefined?(e.wheelX=-e.wheelDeltaX/t,e.wheelY=-e.wheelDeltaY/t):(e.wheelX=0,e.wheelY=-e.wheelDelta/t),n(e)}):\"onwheel\"in e?t.addListener(e,\"wheel\",function(e){var t=.35;switch(e.deltaMode){case e.DOM_DELTA_PIXEL:e.wheelX=e.deltaX*t||0,e.wheelY=e.deltaY*t||0;break;case e.DOM_DELTA_LINE:case e.DOM_DELTA_PAGE:e.wheelX=(e.deltaX||0)*5,e.wheelY=(e.deltaY||0)*5}n(e)}):t.addListener(e,\"DOMMouseScroll\",function(e){e.axis&&e.axis==e.HORIZONTAL_AXIS?(e.wheelX=(e.detail||0)*5,e.wheelY=0):(e.wheelX=0,e.wheelY=(e.detail||0)*5),n(e)})},t.addMultiMouseDownListener=function(e,n,r,s){function c(e){t.getButton(e)!==0?o=0:e.detail>1?(o++,o>4&&(o=1)):o=1;if(i.isIE){var c=Math.abs(e.clientX-u)>5||Math.abs(e.clientY-a)>5;if(!f||c)o=1;f&&clearTimeout(f),f=setTimeout(function(){f=null},n[o-1]||600),o==1&&(u=e.clientX,a=e.clientY)}e._clicks=o,r[s](\"mousedown\",e);if(o>4)o=0;else if(o>1)return r[s](l[o],e)}function h(e){o=2,f&&clearTimeout(f),f=setTimeout(function(){f=null},n[o-1]||600),r[s](\"mousedown\",e),r[s](l[o],e)}var o=0,u,a,f,l={2:\"dblclick\",3:\"tripleclick\",4:\"quadclick\"};Array.isArray(e)||(e=[e]),e.forEach(function(e){t.addListener(e,\"mousedown\",c),i.isOldIE&&t.addListener(e,\"dblclick\",h)})};var u=!i.isMac||!i.isOpera||\"KeyboardEvent\"in window?function(e){return 0|(e.ctrlKey?1:0)|(e.altKey?2:0)|(e.shiftKey?4:0)|(e.metaKey?8:0)}:function(e){return 0|(e.metaKey?1:0)|(e.altKey?2:0)|(e.shiftKey?4:0)|(e.ctrlKey?8:0)};t.getModifierString=function(e){return r.KEY_MODS[u(e)]},t.addCommandKeyListener=function(e,n){var r=t.addListener;if(i.isOldGecko||i.isOpera&&!(\"KeyboardEvent\"in window)){var o=null;r(e,\"keydown\",function(e){o=e.keyCode}),r(e,\"keypress\",function(e){return a(n,e,o)})}else{var u=null;r(e,\"keydown\",function(e){s[e.keyCode]=(s[e.keyCode]||0)+1;var t=a(n,e,e.keyCode);return u=e.defaultPrevented,t}),r(e,\"keypress\",function(e){u&&(e.ctrlKey||e.altKey||e.shiftKey||e.metaKey)&&(t.stopEvent(e),u=null)}),r(e,\"keyup\",function(e){s[e.keyCode]=null}),s||(f(),r(window,\"focus\",f))}};if(typeof window==\"object\"&&window.postMessage&&!i.isOldIE){var l=1;t.nextTick=function(e,n){n=n||window;var r=\"zero-timeout-message-\"+l;t.addListener(n,\"message\",function i(s){s.data==r&&(t.stopPropagation(s),t.removeListener(n,\"message\",i),e())}),n.postMessage(r,\"*\")}}t.nextFrame=typeof window==\"object\"&&(window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame||window.oRequestAnimationFrame),t.nextFrame?t.nextFrame=t.nextFrame.bind(window):t.nextFrame=function(e){setTimeout(e,17)}}),define(\"ace/lib/lang\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";t.last=function(e){return e[e.length-1]},t.stringReverse=function(e){return e.split(\"\").reverse().join(\"\")},t.stringRepeat=function(e,t){var n=\"\";while(t>0){t&1&&(n+=e);if(t>>=1)e+=e}return n};var r=/^\\s\\s*/,i=/\\s\\s*$/;t.stringTrimLeft=function(e){return e.replace(r,\"\")},t.stringTrimRight=function(e){return e.replace(i,\"\")},t.copyObject=function(e){var t={};for(var n in e)t[n]=e[n];return t},t.copyArray=function(e){var t=[];for(var n=0,r=e.length;n<r;n++)e[n]&&typeof e[n]==\"object\"?t[n]=this.copyObject(e[n]):t[n]=e[n];return t},t.deepCopy=function s(e){if(typeof e!=\"object\"||!e)return e;var t;if(Array.isArray(e)){t=[];for(var n=0;n<e.length;n++)t[n]=s(e[n]);return t}if(Object.prototype.toString.call(e)!==\"[object Object]\")return e;t={};for(var n in e)t[n]=s(e[n]);return t},t.arrayToMap=function(e){var t={};for(var n=0;n<e.length;n++)t[e[n]]=1;return t},t.createMap=function(e){var t=Object.create(null);for(var n in e)t[n]=e[n];return t},t.arrayRemove=function(e,t){for(var n=0;n<=e.length;n++)t===e[n]&&e.splice(n,1)},t.escapeRegExp=function(e){return e.replace(/([.*+?^${}()|[\\]\\/\\\\])/g,\"\\\\$1\")},t.escapeHTML=function(e){return e.replace(/&/g,\"&#38;\").replace(/\"/g,\"&#34;\").replace(/'/g,\"&#39;\").replace(/</g,\"&#60;\")},t.getMatchOffsets=function(e,t){var n=[];return e.replace(t,function(e){n.push({offset:arguments[arguments.length-2],length:e.length})}),n},t.deferredCall=function(e){var t=null,n=function(){t=null,e()},r=function(e){return r.cancel(),t=setTimeout(n,e||0),r};return r.schedule=r,r.call=function(){return this.cancel(),e(),r},r.cancel=function(){return clearTimeout(t),t=null,r},r.isPending=function(){return t},r},t.delayedCall=function(e,t){var n=null,r=function(){n=null,e()},i=function(e){n==null&&(n=setTimeout(r,e||t))};return i.delay=function(e){n&&clearTimeout(n),n=setTimeout(r,e||t)},i.schedule=i,i.call=function(){this.cancel(),e()},i.cancel=function(){n&&clearTimeout(n),n=null},i.isPending=function(){return n},i}}),define(\"ace/keyboard/textinput_ios\",[\"require\",\"exports\",\"module\",\"ace/lib/event\",\"ace/lib/useragent\",\"ace/lib/dom\",\"ace/lib/lang\",\"ace/lib/keys\"],function(e,t,n){\"use strict\";var r=e(\"../lib/event\"),i=e(\"../lib/useragent\"),s=e(\"../lib/dom\"),o=e(\"../lib/lang\"),u=e(\"../lib/keys\"),a=u.KEY_MODS,f=i.isChrome<18,l=i.isIE,c=function(e,t){function x(e){if(m)return;m=!0;if(k)t=0,n=e?0:c.value.length-1;else var t=4,n=5;try{c.setSelectionRange(t,n)}catch(r){}m=!1}function T(){if(m)return;c.value=h,i.isWebKit&&S.schedule()}function R(){clearTimeout(q),q=setTimeout(function(){g&&(c.style.cssText=g,g=\"\"),t.renderer.$keepTextAreaAtCursor==null&&(t.renderer.$keepTextAreaAtCursor=!0,t.renderer.$moveTextAreaToCursor())},0)}var n=this,c=s.createElement(\"textarea\");c.className=i.isIOS?\"ace_text-input ace_text-input-ios\":\"ace_text-input\",i.isTouchPad&&c.setAttribute(\"x-palm-disable-auto-cap\",!0),c.setAttribute(\"wrap\",\"off\"),c.setAttribute(\"autocorrect\",\"off\"),c.setAttribute(\"autocapitalize\",\"off\"),c.setAttribute(\"spellcheck\",!1),c.style.opacity=\"0\",e.insertBefore(c,e.firstChild);var h=\"\\n aaaa a\\n\",p=!1,d=!1,v=!1,m=!1,g=\"\",y=!0;try{var b=document.activeElement===c}catch(w){}r.addListener(c,\"blur\",function(e){t.onBlur(e),b=!1}),r.addListener(c,\"focus\",function(e){b=!0,t.onFocus(e),x()}),this.focus=function(){if(g)return c.focus();c.style.position=\"fixed\",c.focus()},this.blur=function(){c.blur()},this.isFocused=function(){return b};var E=o.delayedCall(function(){b&&x(y)}),S=o.delayedCall(function(){m||(c.value=h,b&&x())});i.isWebKit||t.addEventListener(\"changeSelection\",function(){t.selection.isEmpty()!=y&&(y=!y,E.schedule())}),T(),b&&t.onFocus();var N=function(e){return e.selectionStart===0&&e.selectionEnd===e.value.length},C=function(e){N(c)?(t.selectAll(),x()):k&&x(t.selection.isEmpty())},k=null;this.setInputHandler=function(e){k=e},this.getInputHandler=function(){return k};var L=!1,A=function(e){if(c.selectionStart===4&&c.selectionEnd===5)return;k&&(e=k(e),k=null),v?(x(),e&&t.onPaste(e),v=!1):e==h.substr(0)&&c.selectionStart===4?L?t.execCommand(\"del\",{source:\"ace\"}):t.execCommand(\"backspace\",{source:\"ace\"}):p||(e.substring(0,9)==h&&e.length>h.length?e=e.substr(9):e.substr(0,4)==h.substr(0,4)?e=e.substr(4,e.length-h.length+1):e.charAt(e.length-1)==h.charAt(0)&&(e=e.slice(0,-1)),e!=h.charAt(0)&&e.charAt(e.length-1)==h.charAt(0)&&(e=e.slice(0,-1)),e&&t.onTextInput(e)),p&&(p=!1),L&&(L=!1)},O=function(e){if(m)return;var t=c.value;A(t),T()},M=function(e,t,n){var r=e.clipboardData||window.clipboardData;if(!r||f)return;var i=l||n?\"Text\":\"text/plain\";try{return t?r.setData(i,t)!==!1:r.getData(i)}catch(e){if(!n)return M(e,t,!0)}},_=function(e,n){var s=t.getCopyText();if(!s)return r.preventDefault(e);M(e,s)?(i.isIOS&&(d=n,c.value=\"\\n aa\"+s+\"a a\\n\",c.setSelectionRange(4,4+s.length),p={value:s}),n?t.onCut():t.onCopy(),i.isIOS||r.preventDefault(e)):(p=!0,c.value=s,c.select(),setTimeout(function(){p=!1,T(),x(),n?t.onCut():t.onCopy()}))},D=function(e){_(e,!0)},P=function(e){_(e,!1)},H=function(e){var n=M(e);typeof n==\"string\"?(n&&t.onPaste(n,e),i.isIE&&setTimeout(x),r.preventDefault(e)):(c.value=\"\",v=!0)};r.addCommandKeyListener(c,t.onCommandKey.bind(t)),r.addListener(c,\"select\",C),r.addListener(c,\"input\",O),r.addListener(c,\"cut\",D),r.addListener(c,\"copy\",P),r.addListener(c,\"paste\",H);var B=function(e){if(m||!t.onCompositionStart||t.$readOnly)return;m={},m.canUndo=t.session.$undoManager,t.onCompositionStart(),setTimeout(j,0),t.on(\"mousedown\",F),m.canUndo&&!t.selection.isEmpty()&&(t.insert(\"\"),t.session.markUndoGroup(),t.selection.clearSelection()),t.session.markUndoGroup()},j=function(){if(!m||!t.onCompositionUpdate||t.$readOnly)return;var e=c.value.replace(/\\x01/g,\"\");if(m.lastValue===e)return;t.onCompositionUpdate(e),m.lastValue&&t.undo(),m.canUndo&&(m.lastValue=e);if(m.lastValue){var n=t.selection.getRange();t.insert(m.lastValue),t.session.markUndoGroup(),m.range=t.selection.getRange(),t.selection.setRange(n),t.selection.clearSelection()}},F=function(e){if(!t.onCompositionEnd||t.$readOnly)return;var n=m;m=!1;var r=setTimeout(function(){r=null;var e=c.value.replace(/\\x01/g,\"\");if(m)return;e==n.lastValue?T():!n.lastValue&&e&&(T(),A(e))});k=function(i){return r&&clearTimeout(r),i=i.replace(/\\x01/g,\"\"),i==n.lastValue?\"\":(n.lastValue&&r&&t.undo(),i)},t.onCompositionEnd(),t.removeListener(\"mousedown\",F),e.type==\"compositionend\"&&n.range&&t.selection.setRange(n.range);var s=!!i.isChrome&&i.isChrome>=53||!!i.isWebKit&&i.isWebKit>=603;s&&O()},I=o.delayedCall(j,50);r.addListener(c,\"compositionstart\",B),i.isGecko?r.addListener(c,\"text\",function(){I.schedule()}):(r.addListener(c,\"keyup\",function(){I.schedule()}),r.addListener(c,\"keydown\",function(){I.schedule()})),r.addListener(c,\"compositionend\",F),this.getElement=function(){return c},this.setReadOnly=function(e){c.readOnly=e},this.onContextMenu=function(e){L=!0,x(t.selection.isEmpty()),t._emit(\"nativecontextmenu\",{target:t,domEvent:e}),this.moveToMouse(e,!0)},this.moveToMouse=function(e,n){g||(g=c.style.cssText),c.style.cssText=(n?\"z-index:100000;\":\"\")+\"height:\"+c.style.height+\";\"+(i.isIE?\"opacity:0.1;\":\"\");var o=t.container.getBoundingClientRect(),u=s.computedStyle(t.container),a=o.top+(parseInt(u.borderTopWidth)||0),f=o.left+(parseInt(o.borderLeftWidth)||0),l=o.bottom-a-c.clientHeight-2,h=function(e){c.style.left=e.clientX-f-2+\"px\",c.style.top=Math.min(e.clientY-a-2,l)+\"px\"};h(e);if(e.type!=\"mousedown\")return;t.renderer.$keepTextAreaAtCursor&&(t.renderer.$keepTextAreaAtCursor=null),clearTimeout(q),i.isWin&&r.capture(t.container,h,R)},this.onContextMenuClose=R;var q,U=function(e){t.textInput.onContextMenu(e),R()};r.addListener(c,\"mouseup\",U),r.addListener(c,\"mousedown\",function(e){e.preventDefault(),R()}),r.addListener(t.renderer.scroller,\"contextmenu\",U),r.addListener(c,\"contextmenu\",U);if(i.isIOS){var z=null,W=!1;e.addEventListener(\"keydown\",function(e){z&&clearTimeout(z),W=!0}),e.addEventListener(\"keyup\",function(e){z=setTimeout(function(){W=!1},100)});var X=function(e){if(document.activeElement!==c)return;if(W)return;if(d)return setTimeout(function(){d=!1},100);var n=c.selectionStart,r=c.selectionEnd;c.setSelectionRange(4,5);if(n==r)switch(n){case 0:t.onCommandKey(null,0,u.up);break;case 1:t.onCommandKey(null,0,u.home);break;case 2:t.onCommandKey(null,a.option,u.left);break;case 4:t.onCommandKey(null,0,u.left);break;case 5:t.onCommandKey(null,0,u.right);break;case 7:t.onCommandKey(null,a.option,u.right);break;case 8:t.onCommandKey(null,0,u.end);break;case 9:t.onCommandKey(null,0,u.down)}else{switch(r){case 6:t.onCommandKey(null,a.shift,u.right);break;case 7:t.onCommandKey(null,a.shift|a.option,u.right);break;case 8:t.onCommandKey(null,a.shift,u.end);break;case 9:t.onCommandKey(null,a.shift,u.down)}switch(n){case 0:t.onCommandKey(null,a.shift,u.up);break;case 1:t.onCommandKey(null,a.shift,u.home);break;case 2:t.onCommandKey(null,a.shift|a.option,u.left);break;case 3:t.onCommandKey(null,a.shift,u.left)}}};document.addEventListener(\"selectionchange\",X),t.on(\"destroy\",function(){document.removeEventListener(\"selectionchange\",X)})}};t.TextInput=c}),define(\"ace/keyboard/textinput\",[\"require\",\"exports\",\"module\",\"ace/lib/event\",\"ace/lib/useragent\",\"ace/lib/dom\",\"ace/lib/lang\",\"ace/keyboard/textinput_ios\"],function(e,t,n){\"use strict\";var r=e(\"../lib/event\"),i=e(\"../lib/useragent\"),s=e(\"../lib/dom\"),o=e(\"../lib/lang\"),u=i.isChrome<18,a=i.isIE,f=e(\"./textinput_ios\").TextInput,l=function(e,t){function w(e){if(p)return;p=!0;if(T)var t=0,r=e?0:n.value.length-1;else var t=e?2:1,r=2;try{n.setSelectionRange(t,r)}catch(i){}p=!1}function E(){if(p)return;n.value=l,i.isWebKit&&b.schedule()}function F(){clearTimeout(j),j=setTimeout(function(){d&&(n.style.cssText=d,d=\"\"),t.renderer.$keepTextAreaAtCursor==null&&(t.renderer.$keepTextAreaAtCursor=!0,t.renderer.$moveTextAreaToCursor())},0)}if(i.isIOS)return f.call(this,e,t);var n=s.createElement(\"textarea\");n.className=\"ace_text-input\",n.setAttribute(\"wrap\",\"off\"),n.setAttribute(\"autocorrect\",\"off\"),n.setAttribute(\"autocapitalize\",\"off\"),n.setAttribute(\"spellcheck\",!1),n.style.opacity=\"0\",e.insertBefore(n,e.firstChild);var l=\"\\u2028\\u2028\",c=!1,h=!1,p=!1,d=\"\",v=!0;try{var m=document.activeElement===n}catch(g){}r.addListener(n,\"blur\",function(e){t.onBlur(e),m=!1}),r.addListener(n,\"focus\",function(e){m=!0,t.onFocus(e),w()}),this.focus=function(){if(d)return n.focus();var e=n.style.top;n.style.position=\"fixed\",n.style.top=\"0px\",n.focus(),setTimeout(function(){n.style.position=\"\",n.style.top==\"0px\"&&(n.style.top=e)},0)},this.blur=function(){n.blur()},this.isFocused=function(){return m};var y=o.delayedCall(function(){m&&w(v)}),b=o.delayedCall(function(){p||(n.value=l,m&&w())});i.isWebKit||t.addEventListener(\"changeSelection\",function(){t.selection.isEmpty()!=v&&(v=!v,y.schedule())}),E(),m&&t.onFocus();var S=function(e){return e.selectionStart===0&&e.selectionEnd===e.value.length},x=function(e){c?c=!1:S(n)?(t.selectAll(),w()):T&&w(t.selection.isEmpty())},T=null;this.setInputHandler=function(e){T=e},this.getInputHandler=function(){return T};var N=!1,C=function(e){T&&(e=T(e),T=null),h?(w(),e&&t.onPaste(e),h=!1):e==l.charAt(0)?N?t.execCommand(\"del\",{source:\"ace\"}):t.execCommand(\"backspace\",{source:\"ace\"}):(e.substring(0,2)==l?e=e.substr(2):e.charAt(0)==l.charAt(0)?e=e.substr(1):e.charAt(e.length-1)==l.charAt(0)&&(e=e.slice(0,-1)),e.charAt(e.length-1)==l.charAt(0)&&(e=e.slice(0,-1)),e&&t.onTextInput(e)),N&&(N=!1)},k=function(e){if(p)return;var t=n.value;C(t),E()},L=function(e,t,n){var r=e.clipboardData||window.clipboardData;if(!r||u)return;var i=a||n?\"Text\":\"text/plain\";try{return t?r.setData(i,t)!==!1:r.getData(i)}catch(e){if(!n)return L(e,t,!0)}},A=function(e,i){var s=t.getCopyText();if(!s)return r.preventDefault(e);L(e,s)?(i?t.onCut():t.onCopy(),r.preventDefault(e)):(c=!0,n.value=s,n.select(),setTimeout(function(){c=!1,E(),w(),i?t.onCut():t.onCopy()}))},O=function(e){A(e,!0)},M=function(e){A(e,!1)},_=function(e){var s=L(e);typeof s==\"string\"?(s&&t.onPaste(s,e),i.isIE&&setTimeout(w),r.preventDefault(e)):(n.value=\"\",h=!0)};r.addCommandKeyListener(n,t.onCommandKey.bind(t)),r.addListener(n,\"select\",x),r.addListener(n,\"input\",k),r.addListener(n,\"cut\",O),r.addListener(n,\"copy\",M),r.addListener(n,\"paste\",_),(!(\"oncut\"in n)||!(\"oncopy\"in n)||!(\"onpaste\"in n))&&r.addListener(e,\"keydown\",function(e){if(i.isMac&&!e.metaKey||!e.ctrlKey)return;switch(e.keyCode){case 67:M(e);break;case 86:_(e);break;case 88:O(e)}});var D=function(e){if(p||!t.onCompositionStart||t.$readOnly)return;p={},p.canUndo=t.session.$undoManager,t.onCompositionStart(),setTimeout(P,0),t.on(\"mousedown\",H),p.canUndo&&!t.selection.isEmpty()&&(t.insert(\"\"),t.session.markUndoGroup(),t.selection.clearSelection()),t.session.markUndoGroup()},P=function(){if(!p||!t.onCompositionUpdate||t.$readOnly)return;var e=n.value.replace(/\\u2028/g,\"\");if(p.lastValue===e)return;t.onCompositionUpdate(e),p.lastValue&&t.undo(),p.canUndo&&(p.lastValue=e);if(p.lastValue){var r=t.selection.getRange();t.insert(p.lastValue),t.session.markUndoGroup(),p.range=t.selection.getRange(),t.selection.setRange(r),t.selection.clearSelection()}},H=function(e){if(!t.onCompositionEnd||t.$readOnly)return;var r=p;p=!1;var s=setTimeout(function(){s=null;var e=n.value.replace(/\\u2028/g,\"\");if(p)return;e==r.lastValue?E():!r.lastValue&&e&&(E(),C(e))});T=function(n){return s&&clearTimeout(s),n=n.replace(/\\u2028/g,\"\"),n==r.lastValue?\"\":(r.lastValue&&s&&t.undo(),n)},t.onCompositionEnd(),t.removeListener(\"mousedown\",H),e.type==\"compositionend\"&&r.range&&t.selection.setRange(r.range);var o=!!i.isChrome&&i.isChrome>=53||!!i.isWebKit&&i.isWebKit>=603;o&&k()},B=o.delayedCall(P,50);r.addListener(n,\"compositionstart\",D),i.isGecko?r.addListener(n,\"text\",function(){B.schedule()}):(r.addListener(n,\"keyup\",function(){B.schedule()}),r.addListener(n,\"keydown\",function(){B.schedule()})),r.addListener(n,\"compositionend\",H),this.getElement=function(){return n},this.setReadOnly=function(e){n.readOnly=e},this.onContextMenu=function(e){N=!0,w(t.selection.isEmpty()),t._emit(\"nativecontextmenu\",{target:t,domEvent:e}),this.moveToMouse(e,!0)},this.moveToMouse=function(e,o){d||(d=n.style.cssText),n.style.cssText=(o?\"z-index:100000;\":\"\")+\"height:\"+n.style.height+\";\"+(i.isIE?\"opacity:0.1;\":\"\");var u=t.container.getBoundingClientRect(),a=s.computedStyle(t.container),f=u.top+(parseInt(a.borderTopWidth)||0),l=u.left+(parseInt(u.borderLeftWidth)||0),c=u.bottom-f-n.clientHeight-2,h=function(e){n.style.left=e.clientX-l-2+\"px\",n.style.top=Math.min(e.clientY-f-2,c)+\"px\"};h(e);if(e.type!=\"mousedown\")return;t.renderer.$keepTextAreaAtCursor&&(t.renderer.$keepTextAreaAtCursor=null),clearTimeout(j),i.isWin&&r.capture(t.container,h,F)},this.onContextMenuClose=F;var j,I=function(e){t.textInput.onContextMenu(e),F()};r.addListener(n,\"mouseup\",I),r.addListener(n,\"mousedown\",function(e){e.preventDefault(),F()}),r.addListener(t.renderer.scroller,\"contextmenu\",I),r.addListener(n,\"contextmenu\",I)};t.TextInput=l}),define(\"ace/mouse/default_handlers\",[\"require\",\"exports\",\"module\",\"ace/lib/dom\",\"ace/lib/event\",\"ace/lib/useragent\"],function(e,t,n){\"use strict\";function a(e){e.$clickSelection=null;var t=e.editor;t.setDefaultHandler(\"mousedown\",this.onMouseDown.bind(e)),t.setDefaultHandler(\"dblclick\",this.onDoubleClick.bind(e)),t.setDefaultHandler(\"tripleclick\",this.onTripleClick.bind(e)),t.setDefaultHandler(\"quadclick\",this.onQuadClick.bind(e)),t.setDefaultHandler(\"mousewheel\",this.onMouseWheel.bind(e)),t.setDefaultHandler(\"touchmove\",this.onTouchMove.bind(e));var n=[\"select\",\"startSelect\",\"selectEnd\",\"selectAllEnd\",\"selectByWordsEnd\",\"selectByLinesEnd\",\"dragWait\",\"dragWaitEnd\",\"focusWait\"];n.forEach(function(t){e[t]=this[t]},this),e.selectByLines=this.extendSelectionBy.bind(e,\"getLineRange\"),e.selectByWords=this.extendSelectionBy.bind(e,\"getWordRange\")}function f(e,t,n,r){return Math.sqrt(Math.pow(n-e,2)+Math.pow(r-t,2))}function l(e,t){if(e.start.row==e.end.row)var n=2*t.column-e.start.column-e.end.column;else if(e.start.row==e.end.row-1&&!e.start.column&&!e.end.column)var n=t.column-4;else var n=2*t.row-e.start.row-e.end.row;return n<0?{cursor:e.start,anchor:e.end}:{cursor:e.end,anchor:e.start}}var r=e(\"../lib/dom\"),i=e(\"../lib/event\"),s=e(\"../lib/useragent\"),o=0,u=250;(function(){this.onMouseDown=function(e){var t=e.inSelection(),n=e.getDocumentPosition();this.mousedownEvent=e;var r=this.editor,i=e.getButton();if(i!==0){var o=r.getSelectionRange(),u=o.isEmpty();r.$blockScrolling++,(u||i==1)&&r.selection.moveToPosition(n),r.$blockScrolling--,i==2&&(r.textInput.onContextMenu(e.domEvent),s.isMozilla||e.preventDefault());return}this.mousedownEvent.time=Date.now();if(t&&!r.isFocused()){r.focus();if(this.$focusTimout&&!this.$clickSelection&&!r.inMultiSelectMode){this.setState(\"focusWait\"),this.captureMouse(e);return}}return this.captureMouse(e),this.startSelect(n,e.domEvent._clicks>1),e.preventDefault()},this.startSelect=function(e,t){e=e||this.editor.renderer.screenToTextCoordinates(this.x,this.y);var n=this.editor;n.$blockScrolling++,this.mousedownEvent.getShiftKey()?n.selection.selectToPosition(e):t||n.selection.moveToPosition(e),t||this.select(),n.renderer.scroller.setCapture&&n.renderer.scroller.setCapture(),n.setStyle(\"ace_selecting\"),this.setState(\"select\"),n.$blockScrolling--},this.select=function(){var e,t=this.editor,n=t.renderer.screenToTextCoordinates(this.x,this.y);t.$blockScrolling++;if(this.$clickSelection){var r=this.$clickSelection.comparePoint(n);if(r==-1)e=this.$clickSelection.end;else if(r==1)e=this.$clickSelection.start;else{var i=l(this.$clickSelection,n);n=i.cursor,e=i.anchor}t.selection.setSelectionAnchor(e.row,e.column)}t.selection.selectToPosition(n),t.$blockScrolling--,t.renderer.scrollCursorIntoView()},this.extendSelectionBy=function(e){var t,n=this.editor,r=n.renderer.screenToTextCoordinates(this.x,this.y),i=n.selection[e](r.row,r.column);n.$blockScrolling++;if(this.$clickSelection){var s=this.$clickSelection.comparePoint(i.start),o=this.$clickSelection.comparePoint(i.end);if(s==-1&&o<=0){t=this.$clickSelection.end;if(i.end.row!=r.row||i.end.column!=r.column)r=i.start}else if(o==1&&s>=0){t=this.$clickSelection.start;if(i.start.row!=r.row||i.start.column!=r.column)r=i.end}else if(s==-1&&o==1)r=i.end,t=i.start;else{var u=l(this.$clickSelection,r);r=u.cursor,t=u.anchor}n.selection.setSelectionAnchor(t.row,t.column)}n.selection.selectToPosition(r),n.$blockScrolling--,n.renderer.scrollCursorIntoView()},this.selectEnd=this.selectAllEnd=this.selectByWordsEnd=this.selectByLinesEnd=function(){this.$clickSelection=null,this.editor.unsetStyle(\"ace_selecting\"),this.editor.renderer.scroller.releaseCapture&&this.editor.renderer.scroller.releaseCapture()},this.focusWait=function(){var e=f(this.mousedownEvent.x,this.mousedownEvent.y,this.x,this.y),t=Date.now();(e>o||t-this.mousedownEvent.time>this.$focusTimout)&&this.startSelect(this.mousedownEvent.getDocumentPosition())},this.onDoubleClick=function(e){var t=e.getDocumentPosition(),n=this.editor,r=n.session,i=r.getBracketRange(t);i?(i.isEmpty()&&(i.start.column--,i.end.column++),this.setState(\"select\")):(i=n.selection.getWordRange(t.row,t.column),this.setState(\"selectByWords\")),this.$clickSelection=i,this.select()},this.onTripleClick=function(e){var t=e.getDocumentPosition(),n=this.editor;this.setState(\"selectByLines\");var r=n.getSelectionRange();r.isMultiLine()&&r.contains(t.row,t.column)?(this.$clickSelection=n.selection.getLineRange(r.start.row),this.$clickSelection.end=n.selection.getLineRange(r.end.row).end):this.$clickSelection=n.selection.getLineRange(t.row),this.select()},this.onQuadClick=function(e){var t=this.editor;t.selectAll(),this.$clickSelection=t.getSelectionRange(),this.setState(\"selectAll\")},this.onMouseWheel=function(e){if(e.getAccelKey())return;e.getShiftKey()&&e.wheelY&&!e.wheelX&&(e.wheelX=e.wheelY,e.wheelY=0);var t=this.editor;this.$lastScroll||(this.$lastScroll={t:0,vx:0,vy:0,allowed:0});var n=this.$lastScroll,r=e.domEvent.timeStamp,i=r-n.t,s=e.wheelX/i,o=e.wheelY/i;i<u&&(s=(s+n.vx)/2,o=(o+n.vy)/2);var a=Math.abs(s/o),f=!1;a>=1&&t.renderer.isScrollableBy(e.wheelX*e.speed,0)&&(f=!0),a<=1&&t.renderer.isScrollableBy(0,e.wheelY*e.speed)&&(f=!0);if(f)n.allowed=r;else if(r-n.allowed<u){var l=Math.abs(s)<=1.1*Math.abs(n.vx)&&Math.abs(o)<=1.1*Math.abs(n.vy);l?(f=!0,n.allowed=r):n.allowed=0}n.t=r,n.vx=s,n.vy=o;if(f)return t.renderer.scrollBy(e.wheelX*e.speed,e.wheelY*e.speed),e.stop()},this.onTouchMove=function(e){this.editor._emit(\"mousewheel\",e)}}).call(a.prototype),t.DefaultHandlers=a}),define(\"ace/tooltip\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/dom\"],function(e,t,n){\"use strict\";function s(e){this.isOpen=!1,this.$element=null,this.$parentNode=e}var r=e(\"./lib/oop\"),i=e(\"./lib/dom\");(function(){this.$init=function(){return this.$element=i.createElement(\"div\"),this.$element.className=\"ace_tooltip\",this.$element.style.display=\"none\",this.$parentNode.appendChild(this.$element),this.$element},this.getElement=function(){return this.$element||this.$init()},this.setText=function(e){i.setInnerText(this.getElement(),e)},this.setHtml=function(e){this.getElement().innerHTML=e},this.setPosition=function(e,t){this.getElement().style.left=e+\"px\",this.getElement().style.top=t+\"px\"},this.setClassName=function(e){i.addCssClass(this.getElement(),e)},this.show=function(e,t,n){e!=null&&this.setText(e),t!=null&&n!=null&&this.setPosition(t,n),this.isOpen||(this.getElement().style.display=\"block\",this.isOpen=!0)},this.hide=function(){this.isOpen&&(this.getElement().style.display=\"none\",this.isOpen=!1)},this.getHeight=function(){return this.getElement().offsetHeight},this.getWidth=function(){return this.getElement().offsetWidth},this.destroy=function(){this.isOpen=!1,this.$element&&this.$element.parentNode&&this.$element.parentNode.removeChild(this.$element)}}).call(s.prototype),t.Tooltip=s}),define(\"ace/mouse/default_gutter_handler\",[\"require\",\"exports\",\"module\",\"ace/lib/dom\",\"ace/lib/oop\",\"ace/lib/event\",\"ace/tooltip\"],function(e,t,n){\"use strict\";function u(e){function l(){var r=u.getDocumentPosition().row,s=n.$annotations[r];if(!s)return c();var o=t.session.getLength();if(r==o){var a=t.renderer.pixelToScreenCoordinates(0,u.y).row,l=u.$pos;if(a>t.session.documentToScreenRow(l.row,l.column))return c()}if(f==s)return;f=s.text.join(\"<br/>\"),i.setHtml(f),i.show(),t._signal(\"showGutterTooltip\",i),t.on(\"mousewheel\",c);if(e.$tooltipFollowsMouse)h(u);else{var p=u.domEvent.target,d=p.getBoundingClientRect(),v=i.getElement().style;v.left=d.right+\"px\",v.top=d.bottom+\"px\"}}function c(){o&&(o=clearTimeout(o)),f&&(i.hide(),f=null,t._signal(\"hideGutterTooltip\",i),t.removeEventListener(\"mousewheel\",c))}function h(e){i.setPosition(e.x,e.y)}var t=e.editor,n=t.renderer.$gutterLayer,i=new a(t.container);e.editor.setDefaultHandler(\"guttermousedown\",function(r){if(!t.isFocused()||r.getButton()!=0)return;var i=n.getRegion(r);if(i==\"foldWidgets\")return;var s=r.getDocumentPosition().row,o=t.session.selection;if(r.getShiftKey())o.selectTo(s,0);else{if(r.domEvent.detail==2)return t.selectAll(),r.preventDefault();e.$clickSelection=t.selection.getLineRange(s)}return e.setState(\"selectByLines\"),e.captureMouse(r),r.preventDefault()});var o,u,f;e.editor.setDefaultHandler(\"guttermousemove\",function(t){var n=t.domEvent.target||t.domEvent.srcElement;if(r.hasCssClass(n,\"ace_fold-widget\"))return c();f&&e.$tooltipFollowsMouse&&h(t),u=t;if(o)return;o=setTimeout(function(){o=null,u&&!e.isMousePressed?l():c()},50)}),s.addListener(t.renderer.$gutter,\"mouseout\",function(e){u=null;if(!f||o)return;o=setTimeout(function(){o=null,c()},50)}),t.on(\"changeSession\",c)}function a(e){o.call(this,e)}var r=e(\"../lib/dom\"),i=e(\"../lib/oop\"),s=e(\"../lib/event\"),o=e(\"../tooltip\").Tooltip;i.inherits(a,o),function(){this.setPosition=function(e,t){var n=window.innerWidth||document.documentElement.clientWidth,r=window.innerHeight||document.documentElement.clientHeight,i=this.getWidth(),s=this.getHeight();e+=15,t+=15,e+i>n&&(e-=e+i-n),t+s>r&&(t-=20+s),o.prototype.setPosition.call(this,e,t)}}.call(a.prototype),t.GutterHandler=u}),define(\"ace/mouse/mouse_event\",[\"require\",\"exports\",\"module\",\"ace/lib/event\",\"ace/lib/useragent\"],function(e,t,n){\"use strict\";var r=e(\"../lib/event\"),i=e(\"../lib/useragent\"),s=t.MouseEvent=function(e,t){this.domEvent=e,this.editor=t,this.x=this.clientX=e.clientX,this.y=this.clientY=e.clientY,this.$pos=null,this.$inSelection=null,this.propagationStopped=!1,this.defaultPrevented=!1};(function(){this.stopPropagation=function(){r.stopPropagation(this.domEvent),this.propagationStopped=!0},this.preventDefault=function(){r.preventDefault(this.domEvent),this.defaultPrevented=!0},this.stop=function(){this.stopPropagation(),this.preventDefault()},this.getDocumentPosition=function(){return this.$pos?this.$pos:(this.$pos=this.editor.renderer.screenToTextCoordinates(this.clientX,this.clientY),this.$pos)},this.inSelection=function(){if(this.$inSelection!==null)return this.$inSelection;var e=this.editor,t=e.getSelectionRange();if(t.isEmpty())this.$inSelection=!1;else{var n=this.getDocumentPosition();this.$inSelection=t.contains(n.row,n.column)}return this.$inSelection},this.getButton=function(){return r.getButton(this.domEvent)},this.getShiftKey=function(){return this.domEvent.shiftKey},this.getAccelKey=i.isMac?function(){return this.domEvent.metaKey}:function(){return this.domEvent.ctrlKey}}).call(s.prototype)}),define(\"ace/mouse/dragdrop_handler\",[\"require\",\"exports\",\"module\",\"ace/lib/dom\",\"ace/lib/event\",\"ace/lib/useragent\"],function(e,t,n){\"use strict\";function f(e){function T(e,n){var r=Date.now(),i=!n||e.row!=n.row,s=!n||e.column!=n.column;if(!S||i||s)t.$blockScrolling+=1,t.moveCursorToPosition(e),t.$blockScrolling-=1,S=r,x={x:p,y:d};else{var o=l(x.x,x.y,p,d);o>a?S=null:r-S>=u&&(t.renderer.scrollCursorIntoView(),S=null)}}function N(e,n){var r=Date.now(),i=t.renderer.layerConfig.lineHeight,s=t.renderer.layerConfig.characterWidth,u=t.renderer.scroller.getBoundingClientRect(),a={x:{left:p-u.left,right:u.right-p},y:{top:d-u.top,bottom:u.bottom-d}},f=Math.min(a.x.left,a.x.right),l=Math.min(a.y.top,a.y.bottom),c={row:e.row,column:e.column};f/s<=2&&(c.column+=a.x.left<a.x.right?-3:2),l/i<=1&&(c.row+=a.y.top<a.y.bottom?-1:1);var h=e.row!=c.row,v=e.column!=c.column,m=!n||e.row!=n.row;h||v&&!m?E?r-E>=o&&t.renderer.scrollCursorIntoView(c):E=r:E=null}function C(){var e=g;g=t.renderer.screenToTextCoordinates(p,d),T(g,e),N(g,e)}function k(){m=t.selection.toOrientedRange(),h=t.session.addMarker(m,\"ace_selection\",t.getSelectionStyle()),t.clearSelection(),t.isFocused()&&t.renderer.$cursorLayer.setBlinking(!1),clearInterval(v),C(),v=setInterval(C,20),y=0,i.addListener(document,\"mousemove\",O)}function L(){clearInterval(v),t.session.removeMarker(h),h=null,t.$blockScrolling+=1,t.selection.fromOrientedRange(m),t.$blockScrolling-=1,t.isFocused()&&!w&&t.renderer.$cursorLayer.setBlinking(!t.getReadOnly()),m=null,g=null,y=0,E=null,S=null,i.removeListener(document,\"mousemove\",O)}function O(){A==null&&(A=setTimeout(function(){A!=null&&h&&L()},20))}function M(e){var t=e.types;return!t||Array.prototype.some.call(t,function(e){return e==\"text/plain\"||e==\"Text\"})}function _(e){var t=[\"copy\",\"copymove\",\"all\",\"uninitialized\"],n=[\"move\",\"copymove\",\"linkmove\",\"all\",\"uninitialized\"],r=s.isMac?e.altKey:e.ctrlKey,i=\"uninitialized\";try{i=e.dataTransfer.effectAllowed.toLowerCase()}catch(e){}var o=\"none\";return r&&t.indexOf(i)>=0?o=\"copy\":n.indexOf(i)>=0?o=\"move\":t.indexOf(i)>=0&&(o=\"copy\"),o}var t=e.editor,n=r.createElement(\"img\");n.src=\"data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\",s.isOpera&&(n.style.cssText=\"width:1px;height:1px;position:fixed;top:0;left:0;z-index:2147483647;opacity:0;\");var f=[\"dragWait\",\"dragWaitEnd\",\"startDrag\",\"dragReadyEnd\",\"onMouseDrag\"];f.forEach(function(t){e[t]=this[t]},this),t.addEventListener(\"mousedown\",this.onMouseDown.bind(e));var c=t.container,h,p,d,v,m,g,y=0,b,w,E,S,x;this.onDragStart=function(e){if(this.cancelDrag||!c.draggable){var r=this;return setTimeout(function(){r.startSelect(),r.captureMouse(e)},0),e.preventDefault()}m=t.getSelectionRange();var i=e.dataTransfer;i.effectAllowed=t.getReadOnly()?\"copy\":\"copyMove\",s.isOpera&&(t.container.appendChild(n),n.scrollTop=0),i.setDragImage&&i.setDragImage(n,0,0),s.isOpera&&t.container.removeChild(n),i.clearData(),i.setData(\"Text\",t.session.getTextRange()),w=!0,this.setState(\"drag\")},this.onDragEnd=function(e){c.draggable=!1,w=!1,this.setState(null);if(!t.getReadOnly()){var n=e.dataTransfer.dropEffect;!b&&n==\"move\"&&t.session.remove(t.getSelectionRange()),t.renderer.$cursorLayer.setBlinking(!0)}this.editor.unsetStyle(\"ace_dragging\"),this.editor.renderer.setCursorStyle(\"\")},this.onDragEnter=function(e){if(t.getReadOnly()||!M(e.dataTransfer))return;return p=e.clientX,d=e.clientY,h||k(),y++,e.dataTransfer.dropEffect=b=_(e),i.preventDefault(e)},this.onDragOver=function(e){if(t.getReadOnly()||!M(e.dataTransfer))return;return p=e.clientX,d=e.clientY,h||(k(),y++),A!==null&&(A=null),e.dataTransfer.dropEffect=b=_(e),i.preventDefault(e)},this.onDragLeave=function(e){y--;if(y<=0&&h)return L(),b=null,i.preventDefault(e)},this.onDrop=function(e){if(!g)return;var n=e.dataTransfer;if(w)switch(b){case\"move\":m.contains(g.row,g.column)?m={start:g,end:g}:m=t.moveText(m,g);break;case\"copy\":m=t.moveText(m,g,!0)}else{var r=n.getData(\"Text\");m={start:g,end:t.session.insert(g,r)},t.focus(),b=null}return L(),i.preventDefault(e)},i.addListener(c,\"dragstart\",this.onDragStart.bind(e)),i.addListener(c,\"dragend\",this.onDragEnd.bind(e)),i.addListener(c,\"dragenter\",this.onDragEnter.bind(e)),i.addListener(c,\"dragover\",this.onDragOver.bind(e)),i.addListener(c,\"dragleave\",this.onDragLeave.bind(e)),i.addListener(c,\"drop\",this.onDrop.bind(e));var A=null}function l(e,t,n,r){return Math.sqrt(Math.pow(n-e,2)+Math.pow(r-t,2))}var r=e(\"../lib/dom\"),i=e(\"../lib/event\"),s=e(\"../lib/useragent\"),o=200,u=200,a=5;(function(){this.dragWait=function(){var e=Date.now()-this.mousedownEvent.time;e>this.editor.getDragDelay()&&this.startDrag()},this.dragWaitEnd=function(){var e=this.editor.container;e.draggable=!1,this.startSelect(this.mousedownEvent.getDocumentPosition()),this.selectEnd()},this.dragReadyEnd=function(e){this.editor.renderer.$cursorLayer.setBlinking(!this.editor.getReadOnly()),this.editor.unsetStyle(\"ace_dragging\"),this.editor.renderer.setCursorStyle(\"\"),this.dragWaitEnd()},this.startDrag=function(){this.cancelDrag=!1;var e=this.editor,t=e.container;t.draggable=!0,e.renderer.$cursorLayer.setBlinking(!1),e.setStyle(\"ace_dragging\");var n=s.isWin?\"default\":\"move\";e.renderer.setCursorStyle(n),this.setState(\"dragReady\")},this.onMouseDrag=function(e){var t=this.editor.container;if(s.isIE&&this.state==\"dragReady\"){var n=l(this.mousedownEvent.x,this.mousedownEvent.y,this.x,this.y);n>3&&t.dragDrop()}if(this.state===\"dragWait\"){var n=l(this.mousedownEvent.x,this.mousedownEvent.y,this.x,this.y);n>0&&(t.draggable=!1,this.startSelect(this.mousedownEvent.getDocumentPosition()))}},this.onMouseDown=function(e){if(!this.$dragEnabled)return;this.mousedownEvent=e;var t=this.editor,n=e.inSelection(),r=e.getButton(),i=e.domEvent.detail||1;if(i===1&&r===0&&n){if(e.editor.inMultiSelectMode&&(e.getAccelKey()||e.getShiftKey()))return;this.mousedownEvent.time=Date.now();var o=e.domEvent.target||e.domEvent.srcElement;\"unselectable\"in o&&(o.unselectable=\"on\");if(t.getDragDelay()){if(s.isWebKit){this.cancelDrag=!0;var u=t.container;u.draggable=!0}this.setState(\"dragWait\")}else this.startDrag();this.captureMouse(e,this.onMouseDrag.bind(this)),e.defaultPrevented=!0}}}).call(f.prototype),t.DragdropHandler=f}),define(\"ace/lib/net\",[\"require\",\"exports\",\"module\",\"ace/lib/dom\"],function(e,t,n){\"use strict\";var r=e(\"./dom\");t.get=function(e,t){var n=new XMLHttpRequest;n.open(\"GET\",e,!0),n.onreadystatechange=function(){n.readyState===4&&t(n.responseText)},n.send(null)},t.loadScript=function(e,t){var n=r.getDocumentHead(),i=document.createElement(\"script\");i.src=e,n.appendChild(i),i.onload=i.onreadystatechange=function(e,n){if(n||!i.readyState||i.readyState==\"loaded\"||i.readyState==\"complete\")i=i.onload=i.onreadystatechange=null,n||t()}},t.qualifyURL=function(e){var t=document.createElement(\"a\");return t.href=e,t.href}}),define(\"ace/lib/event_emitter\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";var r={},i=function(){this.propagationStopped=!0},s=function(){this.defaultPrevented=!0};r._emit=r._dispatchEvent=function(e,t){this._eventRegistry||(this._eventRegistry={}),this._defaultHandlers||(this._defaultHandlers={});var n=this._eventRegistry[e]||[],r=this._defaultHandlers[e];if(!n.length&&!r)return;if(typeof t!=\"object\"||!t)t={};t.type||(t.type=e),t.stopPropagation||(t.stopPropagation=i),t.preventDefault||(t.preventDefault=s),n=n.slice();for(var o=0;o<n.length;o++){n[o](t,this);if(t.propagationStopped)break}if(r&&!t.defaultPrevented)return r(t,this)},r._signal=function(e,t){var n=(this._eventRegistry||{})[e];if(!n)return;n=n.slice();for(var r=0;r<n.length;r++)n[r](t,this)},r.once=function(e,t){var n=this;t&&this.addEventListener(e,function r(){n.removeEventListener(e,r),t.apply(null,arguments)})},r.setDefaultHandler=function(e,t){var n=this._defaultHandlers;n||(n=this._defaultHandlers={_disabled_:{}});if(n[e]){var r=n[e],i=n._disabled_[e];i||(n._disabled_[e]=i=[]),i.push(r);var s=i.indexOf(t);s!=-1&&i.splice(s,1)}n[e]=t},r.removeDefaultHandler=function(e,t){var n=this._defaultHandlers;if(!n)return;var r=n._disabled_[e];if(n[e]==t){var i=n[e];r&&this.setDefaultHandler(e,r.pop())}else if(r){var s=r.indexOf(t);s!=-1&&r.splice(s,1)}},r.on=r.addEventListener=function(e,t,n){this._eventRegistry=this._eventRegistry||{};var r=this._eventRegistry[e];return r||(r=this._eventRegistry[e]=[]),r.indexOf(t)==-1&&r[n?\"unshift\":\"push\"](t),t},r.off=r.removeListener=r.removeEventListener=function(e,t){this._eventRegistry=this._eventRegistry||{};var n=this._eventRegistry[e];if(!n)return;var r=n.indexOf(t);r!==-1&&n.splice(r,1)},r.removeAllListeners=function(e){this._eventRegistry&&(this._eventRegistry[e]=[])},t.EventEmitter=r}),define(\"ace/lib/app_config\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/event_emitter\"],function(e,t,n){\"no use strict\";function o(e){typeof console!=\"undefined\"&&console.warn&&console.warn.apply(console,arguments)}function u(e,t){var n=new Error(e);n.data=t,typeof console==\"object\"&&console.error&&console.error(n),setTimeout(function(){throw n})}var r=e(\"./oop\"),i=e(\"./event_emitter\").EventEmitter,s={setOptions:function(e){Object.keys(e).forEach(function(t){this.setOption(t,e[t])},this)},getOptions:function(e){var t={};return e?Array.isArray(e)||(t=e,e=Object.keys(t)):e=Object.keys(this.$options),e.forEach(function(e){t[e]=this.getOption(e)},this),t},setOption:function(e,t){if(this[\"$\"+e]===t)return;var n=this.$options[e];if(!n)return o('misspelled option \"'+e+'\"');if(n.forwardTo)return this[n.forwardTo]&&this[n.forwardTo].setOption(e,t);n.handlesSet||(this[\"$\"+e]=t),n&&n.set&&n.set.call(this,t)},getOption:function(e){var t=this.$options[e];return t?t.forwardTo?this[t.forwardTo]&&this[t.forwardTo].getOption(e):t&&t.get?t.get.call(this):this[\"$\"+e]:o('misspelled option \"'+e+'\"')}},a=function(){this.$defaultOptions={}};(function(){r.implement(this,i),this.defineOptions=function(e,t,n){return e.$options||(this.$defaultOptions[t]=e.$options={}),Object.keys(n).forEach(function(t){var r=n[t];typeof r==\"string\"&&(r={forwardTo:r}),r.name||(r.name=t),e.$options[r.name]=r,\"initialValue\"in r&&(e[\"$\"+r.name]=r.initialValue)}),r.implement(e,s),this},this.resetOptions=function(e){Object.keys(e.$options).forEach(function(t){var n=e.$options[t];\"value\"in n&&e.setOption(t,n.value)})},this.setDefaultValue=function(e,t,n){var r=this.$defaultOptions[e]||(this.$defaultOptions[e]={});r[t]&&(r.forwardTo?this.setDefaultValue(r.forwardTo,t,n):r[t].value=n)},this.setDefaultValues=function(e,t){Object.keys(t).forEach(function(n){this.setDefaultValue(e,n,t[n])},this)},this.warn=o,this.reportError=u}).call(a.prototype),t.AppConfig=a}),define(\"ace/config\",[\"require\",\"exports\",\"module\",\"ace/lib/lang\",\"ace/lib/oop\",\"ace/lib/net\",\"ace/lib/app_config\"],function(e,t,n){\"no use strict\";function f(r){if(!u||!u.document)return;a.packaged=r||e.packaged||n.packaged||u.define&&define.packaged;var i={},s=\"\",o=document.currentScript||document._currentScript,f=o&&o.ownerDocument||document,c=f.getElementsByTagName(\"script\");for(var h=0;h<c.length;h++){var p=c[h],d=p.src||p.getAttribute(\"src\");if(!d)continue;var v=p.attributes;for(var m=0,g=v.length;m<g;m++){var y=v[m];y.name.indexOf(\"data-ace-\")===0&&(i[l(y.name.replace(/^data-ace-/,\"\"))]=y.value)}var b=d.match(/^(.*)\\/ace(\\-\\w+)?\\.js(\\?|$)/);b&&(s=b[1])}s&&(i.base=i.base||s,i.packaged=!0),i.basePath=i.base,i.workerPath=i.workerPath||i.base,i.modePath=i.modePath||i.base,i.themePath=i.themePath||i.base,delete i.base;for(var w in i)typeof i[w]!=\"undefined\"&&t.set(w,i[w])}function l(e){return e.replace(/-(.)/g,function(e,t){return t.toUpperCase()})}var r=e(\"./lib/lang\"),i=e(\"./lib/oop\"),s=e(\"./lib/net\"),o=e(\"./lib/app_config\").AppConfig;n.exports=t=new o;var u=function(){return this||typeof window!=\"undefined\"&&window}(),a={packaged:!1,workerPath:null,modePath:null,themePath:null,basePath:\"\",suffix:\".js\",$moduleUrls:{}};t.get=function(e){if(!a.hasOwnProperty(e))throw new Error(\"Unknown config key: \"+e);return a[e]},t.set=function(e,t){if(!a.hasOwnProperty(e))throw new Error(\"Unknown config key: \"+e);a[e]=t},t.all=function(){return r.copyObject(a)},t.moduleUrl=function(e,t){if(a.$moduleUrls[e])return a.$moduleUrls[e];var n=e.split(\"/\");t=t||n[n.length-2]||\"\";var r=t==\"snippets\"?\"/\":\"-\",i=n[n.length-1];if(t==\"worker\"&&r==\"-\"){var s=new RegExp(\"^\"+t+\"[\\\\-_]|[\\\\-_]\"+t+\"$\",\"g\");i=i.replace(s,\"\")}(!i||i==t)&&n.length>1&&(i=n[n.length-2]);var o=a[t+\"Path\"];return o==null?o=a.basePath:r==\"/\"&&(t=r=\"\"),o&&o.slice(-1)!=\"/\"&&(o+=\"/\"),o+t+r+i+this.get(\"suffix\")},t.setModuleUrl=function(e,t){return a.$moduleUrls[e]=t},t.$loading={},t.loadModule=function(n,r){var i,o;Array.isArray(n)&&(o=n[0],n=n[1]);try{i=e(n)}catch(u){}if(i&&!t.$loading[n])return r&&r(i);t.$loading[n]||(t.$loading[n]=[]),t.$loading[n].push(r);if(t.$loading[n].length>1)return;var a=function(){e([n],function(e){t._emit(\"load.module\",{name:n,module:e});var r=t.$loading[n];t.$loading[n]=null,r.forEach(function(t){t&&t(e)})})};if(!t.get(\"packaged\"))return a();s.loadScript(t.moduleUrl(n,o),a)},t.init=f}),define(\"ace/mouse/mouse_handler\",[\"require\",\"exports\",\"module\",\"ace/lib/event\",\"ace/lib/useragent\",\"ace/mouse/default_handlers\",\"ace/mouse/default_gutter_handler\",\"ace/mouse/mouse_event\",\"ace/mouse/dragdrop_handler\",\"ace/config\"],function(e,t,n){\"use strict\";var r=e(\"../lib/event\"),i=e(\"../lib/useragent\"),s=e(\"./default_handlers\").DefaultHandlers,o=e(\"./default_gutter_handler\").GutterHandler,u=e(\"./mouse_event\").MouseEvent,a=e(\"./dragdrop_handler\").DragdropHandler,f=e(\"../config\"),l=function(e){var t=this;this.editor=e,new s(this),new o(this),new a(this);var n=function(t){var n=!document.hasFocus||!document.hasFocus()||!e.isFocused()&&document.activeElement==(e.textInput&&e.textInput.getElement());n&&window.focus(),e.focus()},u=e.renderer.getMouseEventTarget();r.addListener(u,\"click\",this.onMouseEvent.bind(this,\"click\")),r.addListener(u,\"mousemove\",this.onMouseMove.bind(this,\"mousemove\")),r.addMultiMouseDownListener([u,e.renderer.scrollBarV&&e.renderer.scrollBarV.inner,e.renderer.scrollBarH&&e.renderer.scrollBarH.inner,e.textInput&&e.textInput.getElement()].filter(Boolean),[400,300,250],this,\"onMouseEvent\"),r.addMouseWheelListener(e.container,this.onMouseWheel.bind(this,\"mousewheel\")),r.addTouchMoveListener(e.container,this.onTouchMove.bind(this,\"touchmove\"));var f=e.renderer.$gutter;r.addListener(f,\"mousedown\",this.onMouseEvent.bind(this,\"guttermousedown\")),r.addListener(f,\"click\",this.onMouseEvent.bind(this,\"gutterclick\")),r.addListener(f,\"dblclick\",this.onMouseEvent.bind(this,\"gutterdblclick\")),r.addListener(f,\"mousemove\",this.onMouseEvent.bind(this,\"guttermousemove\")),r.addListener(u,\"mousedown\",n),r.addListener(f,\"mousedown\",n),i.isIE&&e.renderer.scrollBarV&&(r.addListener(e.renderer.scrollBarV.element,\"mousedown\",n),r.addListener(e.renderer.scrollBarH.element,\"mousedown\",n)),e.on(\"mousemove\",function(n){if(t.state||t.$dragDelay||!t.$dragEnabled)return;var r=e.renderer.screenToTextCoordinates(n.x,n.y),i=e.session.selection.getRange(),s=e.renderer;!i.isEmpty()&&i.insideStart(r.row,r.column)?s.setCursorStyle(\"default\"):s.setCursorStyle(\"\")})};(function(){this.onMouseEvent=function(e,t){this.editor._emit(e,new u(t,this.editor))},this.onMouseMove=function(e,t){var n=this.editor._eventRegistry&&this.editor._eventRegistry.mousemove;if(!n||!n.length)return;this.editor._emit(e,new u(t,this.editor))},this.onMouseWheel=function(e,t){var n=new u(t,this.editor);n.speed=this.$scrollSpeed*2,n.wheelX=t.wheelX,n.wheelY=t.wheelY,this.editor._emit(e,n)},this.onTouchMove=function(e,t){var n=new u(t,this.editor);n.speed=1,n.wheelX=t.wheelX,n.wheelY=t.wheelY,this.editor._emit(e,n)},this.setState=function(e){this.state=e},this.captureMouse=function(e,t){this.x=e.x,this.y=e.y,this.isMousePressed=!0;var n=this.editor.renderer;n.$keepTextAreaAtCursor&&(n.$keepTextAreaAtCursor=null);var s=this,o=function(e){if(!e)return;if(i.isWebKit&&!e.which&&s.releaseMouse)return s.releaseMouse();s.x=e.clientX,s.y=e.clientY,t&&t(e),s.mouseEvent=new u(e,s.editor),s.$mouseMoved=!0},a=function(e){clearInterval(l),f(),s[s.state+\"End\"]&&s[s.state+\"End\"](e),s.state=\"\",n.$keepTextAreaAtCursor==null&&(n.$keepTextAreaAtCursor=!0,n.$moveTextAreaToCursor()),s.isMousePressed=!1,s.$onCaptureMouseMove=s.releaseMouse=null,e&&s.onMouseEvent(\"mouseup\",e)},f=function(){s[s.state]&&s[s.state](),s.$mouseMoved=!1};if(i.isOldIE&&e.domEvent.type==\"dblclick\")return setTimeout(function(){a(e)});s.$onCaptureMouseMove=o,s.releaseMouse=r.capture(this.editor.container,o,a);var l=setInterval(f,20)},this.releaseMouse=null,this.cancelContextMenu=function(){var e=function(t){if(t&&t.domEvent&&t.domEvent.type!=\"contextmenu\")return;this.editor.off(\"nativecontextmenu\",e),t&&t.domEvent&&r.stopEvent(t.domEvent)}.bind(this);setTimeout(e,10),this.editor.on(\"nativecontextmenu\",e)}}).call(l.prototype),f.defineOptions(l.prototype,\"mouseHandler\",{scrollSpeed:{initialValue:2},dragDelay:{initialValue:i.isMac?150:0},dragEnabled:{initialValue:!0},focusTimout:{initialValue:0},tooltipFollowsMouse:{initialValue:!0}}),t.MouseHandler=l}),define(\"ace/mouse/fold_handler\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";function r(e){e.on(\"click\",function(t){var n=t.getDocumentPosition(),r=e.session,i=r.getFoldAt(n.row,n.column,1);i&&(t.getAccelKey()?r.removeFold(i):r.expandFold(i),t.stop())}),e.on(\"gutterclick\",function(t){var n=e.renderer.$gutterLayer.getRegion(t);if(n==\"foldWidgets\"){var r=t.getDocumentPosition().row,i=e.session;i.foldWidgets&&i.foldWidgets[r]&&e.session.onFoldWidgetClick(r,t),e.isFocused()||e.focus(),t.stop()}}),e.on(\"gutterdblclick\",function(t){var n=e.renderer.$gutterLayer.getRegion(t);if(n==\"foldWidgets\"){var r=t.getDocumentPosition().row,i=e.session,s=i.getParentFoldRangeData(r,!0),o=s.range||s.firstRange;if(o){r=o.start.row;var u=i.getFoldAt(r,i.getLine(r).length,1);u?i.removeFold(u):(i.addFold(\"...\",o),e.renderer.scrollCursorIntoView({row:o.start.row,column:0}))}t.stop()}})}t.FoldHandler=r}),define(\"ace/keyboard/keybinding\",[\"require\",\"exports\",\"module\",\"ace/lib/keys\",\"ace/lib/event\"],function(e,t,n){\"use strict\";var r=e(\"../lib/keys\"),i=e(\"../lib/event\"),s=function(e){this.$editor=e,this.$data={editor:e},this.$handlers=[],this.setDefaultHandler(e.commands)};(function(){this.setDefaultHandler=function(e){this.removeKeyboardHandler(this.$defaultHandler),this.$defaultHandler=e,this.addKeyboardHandler(e,0)},this.setKeyboardHandler=function(e){var t=this.$handlers;if(t[t.length-1]==e)return;while(t[t.length-1]&&t[t.length-1]!=this.$defaultHandler)this.removeKeyboardHandler(t[t.length-1]);this.addKeyboardHandler(e,1)},this.addKeyboardHandler=function(e,t){if(!e)return;typeof e==\"function\"&&!e.handleKeyboard&&(e.handleKeyboard=e);var n=this.$handlers.indexOf(e);n!=-1&&this.$handlers.splice(n,1),t==undefined?this.$handlers.push(e):this.$handlers.splice(t,0,e),n==-1&&e.attach&&e.attach(this.$editor)},this.removeKeyboardHandler=function(e){var t=this.$handlers.indexOf(e);return t==-1?!1:(this.$handlers.splice(t,1),e.detach&&e.detach(this.$editor),!0)},this.getKeyboardHandler=function(){return this.$handlers[this.$handlers.length-1]},this.getStatusText=function(){var e=this.$data,t=e.editor;return this.$handlers.map(function(n){return n.getStatusText&&n.getStatusText(t,e)||\"\"}).filter(Boolean).join(\" \")},this.$callKeyboardHandlers=function(e,t,n,r){var s,o=!1,u=this.$editor.commands;for(var a=this.$handlers.length;a--;){s=this.$handlers[a].handleKeyboard(this.$data,e,t,n,r);if(!s||!s.command)continue;s.command==\"null\"?o=!0:o=u.exec(s.command,this.$editor,s.args,r),o&&r&&e!=-1&&s.passEvent!=1&&s.command.passEvent!=1&&i.stopEvent(r);if(o)break}return!o&&e==-1&&(s={command:\"insertstring\"},o=u.exec(\"insertstring\",this.$editor,t)),o&&this.$editor._signal&&this.$editor._signal(\"keyboardActivity\",s),o},this.onCommandKey=function(e,t,n){var i=r.keyCodeToString(n);this.$callKeyboardHandlers(t,i,n,e)},this.onTextInput=function(e){this.$callKeyboardHandlers(-1,e)}}).call(s.prototype),t.KeyBinding=s}),define(\"ace/lib/bidiutil\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";function F(e,t,n,r){var i=s?d:p,c=null,h=null,v=null,m=0,g=null,y=null,b=-1,w=null,E=null,T=[];if(!r)for(w=0,r=[];w<n;w++)r[w]=R(e[w]);o=s,u=!1,a=!1,f=!1,l=!1;for(E=0;E<n;E++){c=m,T[E]=h=q(e,r,T,E),m=i[c][h],g=m&240,m&=15,t[E]=v=i[m][5];if(g>0)if(g==16){for(w=b;w<E;w++)t[w]=1;b=-1}else b=-1;y=i[m][6];if(y)b==-1&&(b=E);else if(b>-1){for(w=b;w<E;w++)t[w]=v;b=-1}r[E]==S&&(t[E]=0),o|=v}if(l)for(w=0;w<n;w++)if(r[w]==x){t[w]=s;for(var C=w-1;C>=0;C--){if(r[C]!=N)break;t[C]=s}}}function I(e,t,n){if(o<e)return;if(e==1&&s==m&&!f){n.reverse();return}var r=n.length,i=0,u,a,l,c;while(i<r){if(t[i]>=e){u=i+1;while(u<r&&t[u]>=e)u++;for(a=i,l=u-1;a<l;a++,l--)c=n[a],n[a]=n[l],n[l]=c;i=u}i++}}function q(e,t,n,r){var i=t[r],o,c,h,p;switch(i){case g:case y:u=!1;case E:case w:return i;case b:return u?w:b;case T:return u=!0,a=!0,y;case N:return E;case C:if(r<1||r+1>=t.length||(o=n[r-1])!=b&&o!=w||(c=t[r+1])!=b&&c!=w)return E;return u&&(c=w),c==o?c:E;case k:o=r>0?n[r-1]:S;if(o==b&&r+1<t.length&&t[r+1]==b)return b;return E;case L:if(r>0&&n[r-1]==b)return b;if(u)return E;p=r+1,h=t.length;while(p<h&&t[p]==L)p++;if(p<h&&t[p]==b)return b;return E;case A:h=t.length,p=r+1;while(p<h&&t[p]==A)p++;if(p<h){var d=e[r],v=d>=1425&&d<=2303||d==64286;o=t[p];if(v&&(o==y||o==T))return y}if(r<1||(o=t[r-1])==S)return E;return n[r-1];case S:return u=!1,f=!0,s;case x:return l=!0,E;case O:case M:case D:case P:case _:u=!1;case H:return E}}function R(e){var t=e.charCodeAt(0),n=t>>8;return n==0?t>191?g:B[t]:n==5?/[\\u0591-\\u05f4]/.test(e)?y:g:n==6?/[\\u0610-\\u061a\\u064b-\\u065f\\u06d6-\\u06e4\\u06e7-\\u06ed]/.test(e)?A:/[\\u0660-\\u0669\\u066b-\\u066c]/.test(e)?w:t==1642?L:/[\\u06f0-\\u06f9]/.test(e)?b:T:n==32&&t<=8287?j[t&255]:n==254?t>=65136?T:E:E}function U(e){return e>=\"\\u064b\"&&e<=\"\\u0655\"}var r=[\"\\u0621\",\"\\u0641\"],i=[\"\\u063a\",\"\\u064a\"],s=0,o=0,u=!1,a=!1,f=!1,l=!1,c=!1,h=!1,p=[[0,3,0,1,0,0,0],[0,3,0,1,2,2,0],[0,3,0,17,2,0,1],[0,3,5,5,4,1,0],[0,3,21,21,4,0,1],[0,3,5,5,4,2,0]],d=[[2,0,1,1,0,1,0],[2,0,1,1,0,2,0],[2,0,2,1,3,2,0],[2,0,2,33,3,1,1]],v=0,m=1,g=0,y=1,b=2,w=3,E=4,S=5,x=6,T=7,N=8,C=9,k=10,L=11,A=12,O=13,M=14,_=15,D=16,P=17,H=18,B=[H,H,H,H,H,H,H,H,H,x,S,x,N,S,H,H,H,H,H,H,H,H,H,H,H,H,H,H,S,S,S,x,N,E,E,L,L,L,E,E,E,E,E,k,C,k,C,C,b,b,b,b,b,b,b,b,b,b,C,E,E,E,E,E,E,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,E,E,E,E,E,E,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,E,E,E,E,H,H,H,H,H,H,S,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,C,E,L,L,L,L,E,E,E,E,g,E,E,H,E,E,L,L,b,b,E,g,E,E,E,b,g,E,E,E,E,E],j=[N,N,N,N,N,N,N,N,N,N,N,H,H,H,g,y,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,N,S,O,M,_,D,P,C,L,L,L,L,L,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,C,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,N];t.L=g,t.R=y,t.EN=b,t.ON_R=3,t.AN=4,t.R_H=5,t.B=6,t.DOT=\"\\u00b7\",t.doBidiReorder=function(e,n,r){if(e.length<2)return{};var i=e.split(\"\"),o=new Array(i.length),u=new Array(i.length),a=[];s=r?m:v,F(i,a,i.length,n);for(var f=0;f<o.length;o[f]=f,f++);I(2,a,o),I(1,a,o);for(var f=0;f<o.length-1;f++)n[f]===w?a[f]=t.AN:a[f]===y&&(n[f]>T&&n[f]<O||n[f]===E||n[f]===H)?a[f]=t.ON_R:f>0&&i[f-1]===\"\\u0644\"&&/\\u0622|\\u0623|\\u0625|\\u0627/.test(i[f])&&(a[f-1]=a[f]=t.R_H,f++);i[i.length-1]===t.DOT&&(a[i.length-1]=t.B);for(var f=0;f<o.length;f++)u[f]=a[o[f]];return{logicalFromVisual:o,bidiLevels:u}},t.hasBidiCharacters=function(e,t){var n=!1;for(var r=0;r<e.length;r++)t[r]=R(e.charAt(r)),!n&&(t[r]==y||t[r]==T)&&(n=!0);return n},t.getVisualFromLogicalIdx=function(e,t){for(var n=0;n<t.logicalFromVisual.length;n++)if(t.logicalFromVisual[n]==e)return n;return 0}}),define(\"ace/bidihandler\",[\"require\",\"exports\",\"module\",\"ace/lib/bidiutil\",\"ace/lib/lang\",\"ace/lib/useragent\"],function(e,t,n){\"use strict\";var r=e(\"./lib/bidiutil\"),i=e(\"./lib/lang\"),s=e(\"./lib/useragent\"),o=/[\\u0590-\\u05f4\\u0600-\\u06ff\\u0700-\\u08ac]/,u=function(e){this.session=e,this.bidiMap={},this.currentRow=null,this.bidiUtil=r,this.charWidths=[],this.EOL=\"\\u00ac\",this.showInvisibles=!0,this.isRtlDir=!1,this.line=\"\",this.wrapIndent=0,this.isLastRow=!1,this.EOF=\"\\u00b6\",this.seenBidi=!1};(function(){this.isBidiRow=function(e,t,n){return this.seenBidi?(e!==this.currentRow&&(this.currentRow=e,this.updateRowLine(t,n),this.updateBidiMap()),this.bidiMap.bidiLevels):!1},this.onChange=function(e){this.seenBidi?this.currentRow=null:e.action==\"insert\"&&o.test(e.lines.join(\"\\n\"))&&(this.seenBidi=!0,this.currentRow=null)},this.getDocumentRow=function(){var e=0,t=this.session.$screenRowCache;if(t.length){var n=this.session.$getRowCacheIndex(t,this.currentRow);n>=0&&(e=this.session.$docRowCache[n])}return e},this.getSplitIndex=function(){var e=0,t=this.session.$screenRowCache;if(t.length){var n,r=this.session.$getRowCacheIndex(t,this.currentRow);while(this.currentRow-e>0){n=this.session.$getRowCacheIndex(t,this.currentRow-e-1);if(n!==r)break;r=n,e++}}return e},this.updateRowLine=function(e,t){e===undefined&&(e=this.getDocumentRow()),this.wrapIndent=0,this.isLastRow=e===this.session.getLength()-1,this.line=this.session.getLine(e);if(this.session.$useWrapMode){var n=this.session.$wrapData[e];n&&(t===undefined&&(t=this.getSplitIndex()),t>0&&n.length?(this.wrapIndent=n.indent,this.line=t<n.length?this.line.substring(n[t-1],n[n.length-1]):this.line.substring(n[n.length-1])):this.line=this.line.substring(0,n[t]))}var s=this.session,o=0,u;this.line=this.line.replace(/\\t|[\\u1100-\\u2029, \\u202F-\\uFFE6]/g,function(e,t){return e===\"\t\"||s.isFullWidth(e.charCodeAt(0))?(u=e===\"\t\"?s.getScreenTabSize(t+o):2,o+=u-1,i.stringRepeat(r.DOT,u)):e})},this.updateBidiMap=function(){var e=[],t=this.isLastRow?this.EOF:this.EOL,n=this.line+(this.showInvisibles?t:r.DOT);r.hasBidiCharacters(n,e)?this.bidiMap=r.doBidiReorder(n,e,this.isRtlDir):this.bidiMap={}},this.markAsDirty=function(){this.currentRow=null},this.updateCharacterWidths=function(e){if(!this.seenBidi)return;if(this.characterWidth===e.$characterSize.width)return;var t=this.characterWidth=e.$characterSize.width,n=e.$measureCharWidth(\"\\u05d4\");this.charWidths[r.L]=this.charWidths[r.EN]=this.charWidths[r.ON_R]=t,this.charWidths[r.R]=this.charWidths[r.AN]=n,this.charWidths[r.R_H]=s.isChrome?n:n*.45,this.charWidths[r.B]=0,this.currentRow=null},this.getShowInvisibles=function(){return this.showInvisibles},this.setShowInvisibles=function(e){this.showInvisibles=e,this.currentRow=null},this.setEolChar=function(e){this.EOL=e},this.setTextDir=function(e){this.isRtlDir=e},this.getPosLeft=function(e){e-=this.wrapIndent;var t=r.getVisualFromLogicalIdx(e>0?e-1:0,this.bidiMap),n=this.bidiMap.bidiLevels,i=0;e===0&&n[t]%2!==0&&t++;for(var s=0;s<t;s++)i+=this.charWidths[n[s]];return e!==0&&n[t]%2===0&&(i+=this.charWidths[n[t]]),this.wrapIndent&&(i+=this.wrapIndent*this.charWidths[r.L]),i},this.getSelections=function(e,t){var n=this.bidiMap,i=n.bidiLevels,s,o=this.wrapIndent*this.charWidths[r.L],u=[],a=Math.min(e,t)-this.wrapIndent,f=Math.max(e,t)-this.wrapIndent,l=!1,c=!1,h=0;for(var p,d=0;d<i.length;d++)p=n.logicalFromVisual[d],s=i[d],l=p>=a&&p<f,l&&!c?h=o:!l&&c&&u.push({left:h,width:o-h}),o+=this.charWidths[s],c=l;return l&&d===i.length&&u.push({left:h,width:o-h}),u},this.offsetToCol=function(e){var t=0,e=Math.max(e,0),n=0,i=0,s=this.bidiMap.bidiLevels,o=this.charWidths[s[i]];this.wrapIndent&&(e-=this.wrapIndent*this.charWidths[r.L]);while(e>n+o/2){n+=o;if(i===s.length-1){o=0;break}o=this.charWidths[s[++i]]}return i>0&&s[i-1]%2!==0&&s[i]%2===0?(e<n&&i--,t=this.bidiMap.logicalFromVisual[i]):i>0&&s[i-1]%2===0&&s[i]%2!==0?t=1+(e>n?this.bidiMap.logicalFromVisual[i]:this.bidiMap.logicalFromVisual[i-1]):this.isRtlDir&&i===s.length-1&&o===0&&s[i-1]%2===0||!this.isRtlDir&&i===0&&s[i]%2!==0?t=1+this.bidiMap.logicalFromVisual[i]:(i>0&&s[i-1]%2!==0&&o!==0&&i--,t=this.bidiMap.logicalFromVisual[i]),t+this.wrapIndent}}).call(u.prototype),t.BidiHandler=u}),define(\"ace/range\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";var r=function(e,t){return e.row-t.row||e.column-t.column},i=function(e,t,n,r){this.start={row:e,column:t},this.end={row:n,column:r}};(function(){this.isEqual=function(e){return this.start.row===e.start.row&&this.end.row===e.end.row&&this.start.column===e.start.column&&this.end.column===e.end.column},this.toString=function(){return\"Range: [\"+this.start.row+\"/\"+this.start.column+\"] -> [\"+this.end.row+\"/\"+this.end.column+\"]\"},this.contains=function(e,t){return this.compare(e,t)==0},this.compareRange=function(e){var t,n=e.end,r=e.start;return t=this.compare(n.row,n.column),t==1?(t=this.compare(r.row,r.column),t==1?2:t==0?1:0):t==-1?-2:(t=this.compare(r.row,r.column),t==-1?-1:t==1?42:0)},this.comparePoint=function(e){return this.compare(e.row,e.column)},this.containsRange=function(e){return this.comparePoint(e.start)==0&&this.comparePoint(e.end)==0},this.intersects=function(e){var t=this.compareRange(e);return t==-1||t==0||t==1},this.isEnd=function(e,t){return this.end.row==e&&this.end.column==t},this.isStart=function(e,t){return this.start.row==e&&this.start.column==t},this.setStart=function(e,t){typeof e==\"object\"?(this.start.column=e.column,this.start.row=e.row):(this.start.row=e,this.start.column=t)},this.setEnd=function(e,t){typeof e==\"object\"?(this.end.column=e.column,this.end.row=e.row):(this.end.row=e,this.end.column=t)},this.inside=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)||this.isStart(e,t)?!1:!0:!1},this.insideStart=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)?!1:!0:!1},this.insideEnd=function(e,t){return this.compare(e,t)==0?this.isStart(e,t)?!1:!0:!1},this.compare=function(e,t){return!this.isMultiLine()&&e===this.start.row?t<this.start.column?-1:t>this.end.column?1:0:e<this.start.row?-1:e>this.end.row?1:this.start.row===e?t>=this.start.column?0:-1:this.end.row===e?t<=this.end.column?0:1:0},this.compareStart=function(e,t){return this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.compareEnd=function(e,t){return this.end.row==e&&this.end.column==t?1:this.compare(e,t)},this.compareInside=function(e,t){return this.end.row==e&&this.end.column==t?1:this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.clipRows=function(e,t){if(this.end.row>t)var n={row:t+1,column:0};else if(this.end.row<e)var n={row:e,column:0};if(this.start.row>t)var r={row:t+1,column:0};else if(this.start.row<e)var r={row:e,column:0};return i.fromPoints(r||this.start,n||this.end)},this.extend=function(e,t){var n=this.compare(e,t);if(n==0)return this;if(n==-1)var r={row:e,column:t};else var s={row:e,column:t};return i.fromPoints(r||this.start,s||this.end)},this.isEmpty=function(){return this.start.row===this.end.row&&this.start.column===this.end.column},this.isMultiLine=function(){return this.start.row!==this.end.row},this.clone=function(){return i.fromPoints(this.start,this.end)},this.collapseRows=function(){return this.end.column==0?new i(this.start.row,0,Math.max(this.start.row,this.end.row-1),0):new i(this.start.row,0,this.end.row,0)},this.toScreenRange=function(e){var t=e.documentToScreenPosition(this.start),n=e.documentToScreenPosition(this.end);return new i(t.row,t.column,n.row,n.column)},this.moveBy=function(e,t){this.start.row+=e,this.start.column+=t,this.end.row+=e,this.end.column+=t}}).call(i.prototype),i.fromPoints=function(e,t){return new i(e.row,e.column,t.row,t.column)},i.comparePoints=r,i.comparePoints=function(e,t){return e.row-t.row||e.column-t.column},t.Range=i}),define(\"ace/selection\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/lang\",\"ace/lib/event_emitter\",\"ace/range\"],function(e,t,n){\"use strict\";var r=e(\"./lib/oop\"),i=e(\"./lib/lang\"),s=e(\"./lib/event_emitter\").EventEmitter,o=e(\"./range\").Range,u=function(e){this.session=e,this.doc=e.getDocument(),this.clearSelection(),this.lead=this.selectionLead=this.doc.createAnchor(0,0),this.anchor=this.selectionAnchor=this.doc.createAnchor(0,0);var t=this;this.lead.on(\"change\",function(e){t._emit(\"changeCursor\"),t.$isEmpty||t._emit(\"changeSelection\"),!t.$keepDesiredColumnOnChange&&e.old.column!=e.value.column&&(t.$desiredColumn=null)}),this.selectionAnchor.on(\"change\",function(){t.$isEmpty||t._emit(\"changeSelection\")})};(function(){r.implement(this,s),this.isEmpty=function(){return this.$isEmpty||this.anchor.row==this.lead.row&&this.anchor.column==this.lead.column},this.isMultiLine=function(){return this.isEmpty()?!1:this.getRange().isMultiLine()},this.getCursor=function(){return this.lead.getPosition()},this.setSelectionAnchor=function(e,t){this.anchor.setPosition(e,t),this.$isEmpty&&(this.$isEmpty=!1,this._emit(\"changeSelection\"))},this.getSelectionAnchor=function(){return this.$isEmpty?this.getSelectionLead():this.anchor.getPosition()},this.getSelectionLead=function(){return this.lead.getPosition()},this.shiftSelection=function(e){if(this.$isEmpty){this.moveCursorTo(this.lead.row,this.lead.column+e);return}var t=this.getSelectionAnchor(),n=this.getSelectionLead(),r=this.isBackwards();(!r||t.column!==0)&&this.setSelectionAnchor(t.row,t.column+e),(r||n.column!==0)&&this.$moveSelection(function(){this.moveCursorTo(n.row,n.column+e)})},this.isBackwards=function(){var e=this.anchor,t=this.lead;return e.row>t.row||e.row==t.row&&e.column>t.column},this.getRange=function(){var e=this.anchor,t=this.lead;return this.isEmpty()?o.fromPoints(t,t):this.isBackwards()?o.fromPoints(t,e):o.fromPoints(e,t)},this.clearSelection=function(){this.$isEmpty||(this.$isEmpty=!0,this._emit(\"changeSelection\"))},this.selectAll=function(){var e=this.doc.getLength()-1;this.setSelectionAnchor(0,0),this.moveCursorTo(e,this.doc.getLine(e).length)},this.setRange=this.setSelectionRange=function(e,t){t?(this.setSelectionAnchor(e.end.row,e.end.column),this.selectTo(e.start.row,e.start.column)):(this.setSelectionAnchor(e.start.row,e.start.column),this.selectTo(e.end.row,e.end.column)),this.getRange().isEmpty()&&(this.$isEmpty=!0),this.$desiredColumn=null},this.$moveSelection=function(e){var t=this.lead;this.$isEmpty&&this.setSelectionAnchor(t.row,t.column),e.call(this)},this.selectTo=function(e,t){this.$moveSelection(function(){this.moveCursorTo(e,t)})},this.selectToPosition=function(e){this.$moveSelection(function(){this.moveCursorToPosition(e)})},this.moveTo=function(e,t){this.clearSelection(),this.moveCursorTo(e,t)},this.moveToPosition=function(e){this.clearSelection(),this.moveCursorToPosition(e)},this.selectUp=function(){this.$moveSelection(this.moveCursorUp)},this.selectDown=function(){this.$moveSelection(this.moveCursorDown)},this.selectRight=function(){this.$moveSelection(this.moveCursorRight)},this.selectLeft=function(){this.$moveSelection(this.moveCursorLeft)},this.selectLineStart=function(){this.$moveSelection(this.moveCursorLineStart)},this.selectLineEnd=function(){this.$moveSelection(this.moveCursorLineEnd)},this.selectFileEnd=function(){this.$moveSelection(this.moveCursorFileEnd)},this.selectFileStart=function(){this.$moveSelection(this.moveCursorFileStart)},this.selectWordRight=function(){this.$moveSelection(this.moveCursorWordRight)},this.selectWordLeft=function(){this.$moveSelection(this.moveCursorWordLeft)},this.getWordRange=function(e,t){if(typeof t==\"undefined\"){var n=e||this.lead;e=n.row,t=n.column}return this.session.getWordRange(e,t)},this.selectWord=function(){this.setSelectionRange(this.getWordRange())},this.selectAWord=function(){var e=this.getCursor(),t=this.session.getAWordRange(e.row,e.column);this.setSelectionRange(t)},this.getLineRange=function(e,t){var n=typeof e==\"number\"?e:this.lead.row,r,i=this.session.getFoldLine(n);return i?(n=i.start.row,r=i.end.row):r=n,t===!0?new o(n,0,r,this.session.getLine(r).length):new o(n,0,r+1,0)},this.selectLine=function(){this.setSelectionRange(this.getLineRange())},this.moveCursorUp=function(){this.moveCursorBy(-1,0)},this.moveCursorDown=function(){this.moveCursorBy(1,0)},this.wouldMoveIntoSoftTab=function(e,t,n){var r=e.column,i=e.column+t;return n<0&&(r=e.column-t,i=e.column),this.session.isTabStop(e)&&this.doc.getLine(e.row).slice(r,i).split(\" \").length-1==t},this.moveCursorLeft=function(){var e=this.lead.getPosition(),t;if(t=this.session.getFoldAt(e.row,e.column,-1))this.moveCursorTo(t.start.row,t.start.column);else if(e.column===0)e.row>0&&this.moveCursorTo(e.row-1,this.doc.getLine(e.row-1).length);else{var n=this.session.getTabSize();this.wouldMoveIntoSoftTab(e,n,-1)&&!this.session.getNavigateWithinSoftTabs()?this.moveCursorBy(0,-n):this.moveCursorBy(0,-1)}},this.moveCursorRight=function(){var e=this.lead.getPosition(),t;if(t=this.session.getFoldAt(e.row,e.column,1))this.moveCursorTo(t.end.row,t.end.column);else if(this.lead.column==this.doc.getLine(this.lead.row).length)this.lead.row<this.doc.getLength()-1&&this.moveCursorTo(this.lead.row+1,0);else{var n=this.session.getTabSize(),e=this.lead;this.wouldMoveIntoSoftTab(e,n,1)&&!this.session.getNavigateWithinSoftTabs()?this.moveCursorBy(0,n):this.moveCursorBy(0,1)}},this.moveCursorLineStart=function(){var e=this.lead.row,t=this.lead.column,n=this.session.documentToScreenRow(e,t),r=this.session.screenToDocumentPosition(n,0),i=this.session.getDisplayLine(e,null,r.row,r.column),s=i.match(/^\\s*/);s[0].length!=t&&!this.session.$useEmacsStyleLineStart&&(r.column+=s[0].length),this.moveCursorToPosition(r)},this.moveCursorLineEnd=function(){var e=this.lead,t=this.session.getDocumentLastRowColumnPosition(e.row,e.column);if(this.lead.column==t.column){var n=this.session.getLine(t.row);if(t.column==n.length){var r=n.search(/\\s+$/);r>0&&(t.column=r)}}this.moveCursorTo(t.row,t.column)},this.moveCursorFileEnd=function(){var e=this.doc.getLength()-1,t=this.doc.getLine(e).length;this.moveCursorTo(e,t)},this.moveCursorFileStart=function(){this.moveCursorTo(0,0)},this.moveCursorLongWordRight=function(){var e=this.lead.row,t=this.lead.column,n=this.doc.getLine(e),r=n.substring(t),i;this.session.nonTokenRe.lastIndex=0,this.session.tokenRe.lastIndex=0;var s=this.session.getFoldAt(e,t,1);if(s){this.moveCursorTo(s.end.row,s.end.column);return}if(i=this.session.nonTokenRe.exec(r))t+=this.session.nonTokenRe.lastIndex,this.session.nonTokenRe.lastIndex=0,r=n.substring(t);if(t>=n.length){this.moveCursorTo(e,n.length),this.moveCursorRight(),e<this.doc.getLength()-1&&this.moveCursorWordRight();return}if(i=this.session.tokenRe.exec(r))t+=this.session.tokenRe.lastIndex,this.session.tokenRe.lastIndex=0;this.moveCursorTo(e,t)},this.moveCursorLongWordLeft=function(){var e=this.lead.row,t=this.lead.column,n;if(n=this.session.getFoldAt(e,t,-1)){this.moveCursorTo(n.start.row,n.start.column);return}var r=this.session.getFoldStringAt(e,t,-1);r==null&&(r=this.doc.getLine(e).substring(0,t));var s=i.stringReverse(r),o;this.session.nonTokenRe.lastIndex=0,this.session.tokenRe.lastIndex=0;if(o=this.session.nonTokenRe.exec(s))t-=this.session.nonTokenRe.lastIndex,s=s.slice(this.session.nonTokenRe.lastIndex),this.session.nonTokenRe.lastIndex=0;if(t<=0){this.moveCursorTo(e,0),this.moveCursorLeft(),e>0&&this.moveCursorWordLeft();return}if(o=this.session.tokenRe.exec(s))t-=this.session.tokenRe.lastIndex,this.session.tokenRe.lastIndex=0;this.moveCursorTo(e,t)},this.$shortWordEndIndex=function(e){var t,n=0,r,i=/\\s/,s=this.session.tokenRe;s.lastIndex=0;if(t=this.session.tokenRe.exec(e))n=this.session.tokenRe.lastIndex;else{while((r=e[n])&&i.test(r))n++;if(n<1){s.lastIndex=0;while((r=e[n])&&!s.test(r)){s.lastIndex=0,n++;if(i.test(r)){if(n>2){n--;break}while((r=e[n])&&i.test(r))n++;if(n>2)break}}}}return s.lastIndex=0,n},this.moveCursorShortWordRight=function(){var e=this.lead.row,t=this.lead.column,n=this.doc.getLine(e),r=n.substring(t),i=this.session.getFoldAt(e,t,1);if(i)return this.moveCursorTo(i.end.row,i.end.column);if(t==n.length){var s=this.doc.getLength();do e++,r=this.doc.getLine(e);while(e<s&&/^\\s*$/.test(r));/^\\s+/.test(r)||(r=\"\"),t=0}var o=this.$shortWordEndIndex(r);this.moveCursorTo(e,t+o)},this.moveCursorShortWordLeft=function(){var e=this.lead.row,t=this.lead.column,n;if(n=this.session.getFoldAt(e,t,-1))return this.moveCursorTo(n.start.row,n.start.column);var r=this.session.getLine(e).substring(0,t);if(t===0){do e--,r=this.doc.getLine(e);while(e>0&&/^\\s*$/.test(r));t=r.length,/\\s+$/.test(r)||(r=\"\")}var s=i.stringReverse(r),o=this.$shortWordEndIndex(s);return this.moveCursorTo(e,t-o)},this.moveCursorWordRight=function(){this.session.$selectLongWords?this.moveCursorLongWordRight():this.moveCursorShortWordRight()},this.moveCursorWordLeft=function(){this.session.$selectLongWords?this.moveCursorLongWordLeft():this.moveCursorShortWordLeft()},this.moveCursorBy=function(e,t){var n=this.session.documentToScreenPosition(this.lead.row,this.lead.column),r;t===0&&(e!==0&&(this.session.$bidiHandler.isBidiRow(n.row,this.lead.row)?(r=this.session.$bidiHandler.getPosLeft(n.column),n.column=Math.round(r/this.session.$bidiHandler.charWidths[0])):r=n.column*this.session.$bidiHandler.charWidths[0]),this.$desiredColumn?n.column=this.$desiredColumn:this.$desiredColumn=n.column);var i=this.session.screenToDocumentPosition(n.row+e,n.column,r);e!==0&&t===0&&i.row===this.lead.row&&i.column===this.lead.column&&this.session.lineWidgets&&this.session.lineWidgets[i.row]&&(i.row>0||e>0)&&i.row++,this.moveCursorTo(i.row,i.column+t,t===0)},this.moveCursorToPosition=function(e){this.moveCursorTo(e.row,e.column)},this.moveCursorTo=function(e,t,n){var r=this.session.getFoldAt(e,t,1);r&&(e=r.start.row,t=r.start.column),this.$keepDesiredColumnOnChange=!0;var i=this.session.getLine(e);/[\\uDC00-\\uDFFF]/.test(i.charAt(t))&&i.charAt(t-1)&&(this.lead.row==e&&this.lead.column==t+1?t-=1:t+=1),this.lead.setPosition(e,t),this.$keepDesiredColumnOnChange=!1,n||(this.$desiredColumn=null)},this.moveCursorToScreen=function(e,t,n){var r=this.session.screenToDocumentPosition(e,t);this.moveCursorTo(r.row,r.column,n)},this.detach=function(){this.lead.detach(),this.anchor.detach(),this.session=this.doc=null},this.fromOrientedRange=function(e){this.setSelectionRange(e,e.cursor==e.start),this.$desiredColumn=e.desiredColumn||this.$desiredColumn},this.toOrientedRange=function(e){var t=this.getRange();return e?(e.start.column=t.start.column,e.start.row=t.start.row,e.end.column=t.end.column,e.end.row=t.end.row):e=t,e.cursor=this.isBackwards()?e.start:e.end,e.desiredColumn=this.$desiredColumn,e},this.getRangeOfMovements=function(e){var t=this.getCursor();try{e(this);var n=this.getCursor();return o.fromPoints(t,n)}catch(r){return o.fromPoints(t,t)}finally{this.moveCursorToPosition(t)}},this.toJSON=function(){if(this.rangeCount)var e=this.ranges.map(function(e){var t=e.clone();return t.isBackwards=e.cursor==e.start,t});else{var e=this.getRange();e.isBackwards=this.isBackwards()}return e},this.fromJSON=function(e){if(e.start==undefined){if(this.rangeList){this.toSingleRange(e[0]);for(var t=e.length;t--;){var n=o.fromPoints(e[t].start,e[t].end);e[t].isBackwards&&(n.cursor=n.start),this.addRange(n,!0)}return}e=e[0]}this.rangeList&&this.toSingleRange(e),this.setSelectionRange(e,e.isBackwards)},this.isEqual=function(e){if((e.length||this.rangeCount)&&e.length!=this.rangeCount)return!1;if(!e.length||!this.ranges)return this.getRange().isEqual(e);for(var t=this.ranges.length;t--;)if(!this.ranges[t].isEqual(e[t]))return!1;return!0}}).call(u.prototype),t.Selection=u}),define(\"ace/tokenizer\",[\"require\",\"exports\",\"module\",\"ace/config\"],function(e,t,n){\"use strict\";var r=e(\"./config\"),i=2e3,s=function(e){this.states=e,this.regExps={},this.matchMappings={};for(var t in this.states){var n=this.states[t],r=[],i=0,s=this.matchMappings[t]={defaultToken:\"text\"},o=\"g\",u=[];for(var a=0;a<n.length;a++){var f=n[a];f.defaultToken&&(s.defaultToken=f.defaultToken),f.caseInsensitive&&(o=\"gi\");if(f.regex==null)continue;f.regex instanceof RegExp&&(f.regex=f.regex.toString().slice(1,-1));var l=f.regex,c=(new RegExp(\"(?:(\"+l+\")|(.))\")).exec(\"a\").length-2;Array.isArray(f.token)?f.token.length==1||c==1?f.token=f.token[0]:c-1!=f.token.length?(this.reportError(\"number of classes and regexp groups doesn't match\",{rule:f,groupCount:c-1}),f.token=f.token[0]):(f.tokenArray=f.token,f.token=null,f.onMatch=this.$arrayTokens):typeof f.token==\"function\"&&!f.onMatch&&(c>1?f.onMatch=this.$applyToken:f.onMatch=f.token),c>1&&(/\\\\\\d/.test(f.regex)?l=f.regex.replace(/\\\\([0-9]+)/g,function(e,t){return\"\\\\\"+(parseInt(t,10)+i+1)}):(c=1,l=this.removeCapturingGroups(f.regex)),!f.splitRegex&&typeof f.token!=\"string\"&&u.push(f)),s[i]=a,i+=c,r.push(l),f.onMatch||(f.onMatch=null)}r.length||(s[0]=0,r.push(\"$\")),u.forEach(function(e){e.splitRegex=this.createSplitterRegexp(e.regex,o)},this),this.regExps[t]=new RegExp(\"(\"+r.join(\")|(\")+\")|($)\",o)}};(function(){this.$setMaxTokenCount=function(e){i=e|0},this.$applyToken=function(e){var t=this.splitRegex.exec(e).slice(1),n=this.token.apply(this,t);if(typeof n==\"string\")return[{type:n,value:e}];var r=[];for(var i=0,s=n.length;i<s;i++)t[i]&&(r[r.length]={type:n[i],value:t[i]});return r},this.$arrayTokens=function(e){if(!e)return[];var t=this.splitRegex.exec(e);if(!t)return\"text\";var n=[],r=this.tokenArray;for(var i=0,s=r.length;i<s;i++)t[i+1]&&(n[n.length]={type:r[i],value:t[i+1]});return n},this.removeCapturingGroups=function(e){var t=e.replace(/\\[(?:\\\\.|[^\\]])*?\\]|\\\\.|\\(\\?[:=!]|(\\()/g,function(e,t){return t?\"(?:\":e});return t},this.createSplitterRegexp=function(e,t){if(e.indexOf(\"(?=\")!=-1){var n=0,r=!1,i={};e.replace(/(\\\\.)|(\\((?:\\?[=!])?)|(\\))|([\\[\\]])/g,function(e,t,s,o,u,a){return r?r=u!=\"]\":u?r=!0:o?(n==i.stack&&(i.end=a+1,i.stack=-1),n--):s&&(n++,s.length!=1&&(i.stack=n,i.start=a)),e}),i.end!=null&&/^\\)*$/.test(e.substr(i.end))&&(e=e.substring(0,i.start)+e.substr(i.end))}return e.charAt(0)!=\"^\"&&(e=\"^\"+e),e.charAt(e.length-1)!=\"$\"&&(e+=\"$\"),new RegExp(e,(t||\"\").replace(\"g\",\"\"))},this.getLineTokens=function(e,t){if(t&&typeof t!=\"string\"){var n=t.slice(0);t=n[0],t===\"#tmp\"&&(n.shift(),t=n.shift())}else var n=[];var r=t||\"start\",s=this.states[r];s||(r=\"start\",s=this.states[r]);var o=this.matchMappings[r],u=this.regExps[r];u.lastIndex=0;var a,f=[],l=0,c=0,h={type:null,value:\"\"};while(a=u.exec(e)){var p=o.defaultToken,d=null,v=a[0],m=u.lastIndex;if(m-v.length>l){var g=e.substring(l,m-v.length);h.type==p?h.value+=g:(h.type&&f.push(h),h={type:p,value:g})}for(var y=0;y<a.length-2;y++){if(a[y+1]===undefined)continue;d=s[o[y]],d.onMatch?p=d.onMatch(v,r,n,e):p=d.token,d.next&&(typeof d.next==\"string\"?r=d.next:r=d.next(r,n),s=this.states[r],s||(this.reportError(\"state doesn't exist\",r),r=\"start\",s=this.states[r]),o=this.matchMappings[r],l=m,u=this.regExps[r],u.lastIndex=m),d.consumeLineEnd&&(l=m);break}if(v)if(typeof p==\"string\")!!d&&d.merge===!1||h.type!==p?(h.type&&f.push(h),h={type:p,value:v}):h.value+=v;else if(p){h.type&&f.push(h),h={type:null,value:\"\"};for(var y=0;y<p.length;y++)f.push(p[y])}if(l==e.length)break;l=m;if(c++>i){c>2*e.length&&this.reportError(\"infinite loop with in ace tokenizer\",{startState:t,line:e});while(l<e.length)h.type&&f.push(h),h={value:e.substring(l,l+=2e3),type:\"overflow\"};r=\"start\",n=[];break}}return h.type&&f.push(h),n.length>1&&n[0]!==r&&n.unshift(\"#tmp\",r),{tokens:f,state:n.length?n:r}},this.reportError=r.reportError}).call(s.prototype),t.Tokenizer=s}),define(\"ace/mode/text_highlight_rules\",[\"require\",\"exports\",\"module\",\"ace/lib/lang\"],function(e,t,n){\"use strict\";var r=e(\"../lib/lang\"),i=function(){this.$rules={start:[{token:\"empty_line\",regex:\"^$\"},{defaultToken:\"text\"}]}};(function(){this.addRules=function(e,t){if(!t){for(var n in e)this.$rules[n]=e[n];return}for(var n in e){var r=e[n];for(var i=0;i<r.length;i++){var s=r[i];if(s.next||s.onMatch)typeof s.next==\"string\"&&s.next.indexOf(t)!==0&&(s.next=t+s.next),s.nextState&&s.nextState.indexOf(t)!==0&&(s.nextState=t+s.nextState)}this.$rules[t+n]=r}},this.getRules=function(){return this.$rules},this.embedRules=function(e,t,n,i,s){var o=typeof e==\"function\"?(new e).getRules():e;if(i)for(var u=0;u<i.length;u++)i[u]=t+i[u];else{i=[];for(var a in o)i.push(t+a)}this.addRules(o,t);if(n){var f=Array.prototype[s?\"push\":\"unshift\"];for(var u=0;u<i.length;u++)f.apply(this.$rules[i[u]],r.deepCopy(n))}this.$embeds||(this.$embeds=[]),this.$embeds.push(t)},this.getEmbeds=function(){return this.$embeds};var e=function(e,t){return(e!=\"start\"||t.length)&&t.unshift(this.nextState,e),this.nextState},t=function(e,t){return t.shift(),t.shift()||\"start\"};this.normalizeRules=function(){function i(s){var o=r[s];o.processed=!0;for(var u=0;u<o.length;u++){var a=o[u],f=null;Array.isArray(a)&&(f=a,a={}),!a.regex&&a.start&&(a.regex=a.start,a.next||(a.next=[]),a.next.push({defaultToken:a.token},{token:a.token+\".end\",regex:a.end||a.start,next:\"pop\"}),a.token=a.token+\".start\",a.push=!0);var l=a.next||a.push;if(l&&Array.isArray(l)){var c=a.stateName;c||(c=a.token,typeof c!=\"string\"&&(c=c[0]||\"\"),r[c]&&(c+=n++)),r[c]=l,a.next=c,i(c)}else l==\"pop\"&&(a.next=t);a.push&&(a.nextState=a.next||a.push,a.next=e,delete a.push);if(a.rules)for(var h in a.rules)r[h]?r[h].push&&r[h].push.apply(r[h],a.rules[h]):r[h]=a.rules[h];var p=typeof a==\"string\"?a:a.include;p&&(Array.isArray(p)?f=p.map(function(e){return r[e]}):f=r[p]);if(f){var d=[u,1].concat(f);a.noEscape&&(d=d.filter(function(e){return!e.next})),o.splice.apply(o,d),u--}a.keywordMap&&(a.token=this.createKeywordMapper(a.keywordMap,a.defaultToken||\"text\",a.caseInsensitive),delete a.defaultToken)}}var n=0,r=this.$rules;Object.keys(r).forEach(i,this)},this.createKeywordMapper=function(e,t,n,r){var i=Object.create(null);return Object.keys(e).forEach(function(t){var s=e[t];n&&(s=s.toLowerCase());var o=s.split(r||\"|\");for(var u=o.length;u--;)i[o[u]]=t}),Object.getPrototypeOf(i)&&(i.__proto__=null),this.$keywordList=Object.keys(i),e=null,n?function(e){return i[e.toLowerCase()]||t}:function(e){return i[e]||t}},this.getKeywords=function(){return this.$keywords}}).call(i.prototype),t.TextHighlightRules=i}),define(\"ace/mode/behaviour\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";var r=function(){this.$behaviours={}};(function(){this.add=function(e,t,n){switch(undefined){case this.$behaviours:this.$behaviours={};case this.$behaviours[e]:this.$behaviours[e]={}}this.$behaviours[e][t]=n},this.addBehaviours=function(e){for(var t in e)for(var n in e[t])this.add(t,n,e[t][n])},this.remove=function(e){this.$behaviours&&this.$behaviours[e]&&delete this.$behaviours[e]},this.inherit=function(e,t){if(typeof e==\"function\")var n=(new e).getBehaviours(t);else var n=e.getBehaviours(t);this.addBehaviours(n)},this.getBehaviours=function(e){if(!e)return this.$behaviours;var t={};for(var n=0;n<e.length;n++)this.$behaviours[e[n]]&&(t[e[n]]=this.$behaviours[e[n]]);return t}}).call(r.prototype),t.Behaviour=r}),define(\"ace/token_iterator\",[\"require\",\"exports\",\"module\",\"ace/range\"],function(e,t,n){\"use strict\";var r=e(\"./range\").Range,i=function(e,t,n){this.$session=e,this.$row=t,this.$rowTokens=e.getTokens(t);var r=e.getTokenAt(t,n);this.$tokenIndex=r?r.index:-1};(function(){this.stepBackward=function(){this.$tokenIndex-=1;while(this.$tokenIndex<0){this.$row-=1;if(this.$row<0)return this.$row=0,null;this.$rowTokens=this.$session.getTokens(this.$row),this.$tokenIndex=this.$rowTokens.length-1}return this.$rowTokens[this.$tokenIndex]},this.stepForward=function(){this.$tokenIndex+=1;var e;while(this.$tokenIndex>=this.$rowTokens.length){this.$row+=1,e||(e=this.$session.getLength());if(this.$row>=e)return this.$row=e-1,null;this.$rowTokens=this.$session.getTokens(this.$row),this.$tokenIndex=0}return this.$rowTokens[this.$tokenIndex]},this.getCurrentToken=function(){return this.$rowTokens[this.$tokenIndex]},this.getCurrentTokenRow=function(){return this.$row},this.getCurrentTokenColumn=function(){var e=this.$rowTokens,t=this.$tokenIndex,n=e[t].start;if(n!==undefined)return n;n=0;while(t>0)t-=1,n+=e[t].value.length;return n},this.getCurrentTokenPosition=function(){return{row:this.$row,column:this.getCurrentTokenColumn()}},this.getCurrentTokenRange=function(){var e=this.$rowTokens[this.$tokenIndex],t=this.getCurrentTokenColumn();return new r(this.$row,t,this.$row,t+e.value.length)}}).call(i.prototype),t.TokenIterator=i}),define(\"ace/mode/behaviour/cstyle\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/mode/behaviour\",\"ace/token_iterator\",\"ace/lib/lang\"],function(e,t,n){\"use strict\";var r=e(\"../../lib/oop\"),i=e(\"../behaviour\").Behaviour,s=e(\"../../token_iterator\").TokenIterator,o=e(\"../../lib/lang\"),u=[\"text\",\"paren.rparen\",\"punctuation.operator\"],a=[\"text\",\"paren.rparen\",\"punctuation.operator\",\"comment\"],f,l={},c={'\"':'\"',\"'\":\"'\"},h=function(e){var t=-1;e.multiSelect&&(t=e.selection.index,l.rangeCount!=e.multiSelect.rangeCount&&(l={rangeCount:e.multiSelect.rangeCount}));if(l[t])return f=l[t];f=l[t]={autoInsertedBrackets:0,autoInsertedRow:-1,autoInsertedLineEnd:\"\",maybeInsertedBrackets:0,maybeInsertedRow:-1,maybeInsertedLineStart:\"\",maybeInsertedLineEnd:\"\"}},p=function(e,t,n,r){var i=e.end.row-e.start.row;return{text:n+t+r,selection:[0,e.start.column+1,i,e.end.column+(i?0:1)]}},d=function(e){this.add(\"braces\",\"insertion\",function(t,n,r,i,s){var u=r.getCursorPosition(),a=i.doc.getLine(u.row);if(s==\"{\"){h(r);var l=r.getSelectionRange(),c=i.doc.getTextRange(l);if(c!==\"\"&&c!==\"{\"&&r.getWrapBehavioursEnabled())return p(l,c,\"{\",\"}\");if(d.isSaneInsertion(r,i))return/[\\]\\}\\)]/.test(a[u.column])||r.inMultiSelectMode||e&&e.braces?(d.recordAutoInsert(r,i,\"}\"),{text:\"{}\",selection:[1,1]}):(d.recordMaybeInsert(r,i,\"{\"),{text:\"{\",selection:[1,1]})}else if(s==\"}\"){h(r);var v=a.substring(u.column,u.column+1);if(v==\"}\"){var m=i.$findOpeningBracket(\"}\",{column:u.column+1,row:u.row});if(m!==null&&d.isAutoInsertedClosing(u,a,s))return d.popAutoInsertedClosing(),{text:\"\",selection:[1,1]}}}else{if(s==\"\\n\"||s==\"\\r\\n\"){h(r);var g=\"\";d.isMaybeInsertedClosing(u,a)&&(g=o.stringRepeat(\"}\",f.maybeInsertedBrackets),d.clearMaybeInsertedClosing());var v=a.substring(u.column,u.column+1);if(v===\"}\"){var y=i.findMatchingBracket({row:u.row,column:u.column+1},\"}\");if(!y)return null;var b=this.$getIndent(i.getLine(y.row))}else{if(!g){d.clearMaybeInsertedClosing();return}var b=this.$getIndent(a)}var w=b+i.getTabString();return{text:\"\\n\"+w+\"\\n\"+b+g,selection:[1,w.length,1,w.length]}}d.clearMaybeInsertedClosing()}}),this.add(\"braces\",\"deletion\",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s==\"{\"){h(n);var o=r.doc.getLine(i.start.row),u=o.substring(i.end.column,i.end.column+1);if(u==\"}\")return i.end.column++,i;f.maybeInsertedBrackets--}}),this.add(\"parens\",\"insertion\",function(e,t,n,r,i){if(i==\"(\"){h(n);var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==\"\"&&n.getWrapBehavioursEnabled())return p(s,o,\"(\",\")\");if(d.isSaneInsertion(n,r))return d.recordAutoInsert(n,r,\")\"),{text:\"()\",selection:[1,1]}}else if(i==\")\"){h(n);var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==\")\"){var l=r.$findOpeningBracket(\")\",{column:u.column+1,row:u.row});if(l!==null&&d.isAutoInsertedClosing(u,a,i))return d.popAutoInsertedClosing(),{text:\"\",selection:[1,1]}}}}),this.add(\"parens\",\"deletion\",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s==\"(\"){h(n);var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==\")\")return i.end.column++,i}}),this.add(\"brackets\",\"insertion\",function(e,t,n,r,i){if(i==\"[\"){h(n);var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==\"\"&&n.getWrapBehavioursEnabled())return p(s,o,\"[\",\"]\");if(d.isSaneInsertion(n,r))return d.recordAutoInsert(n,r,\"]\"),{text:\"[]\",selection:[1,1]}}else if(i==\"]\"){h(n);var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==\"]\"){var l=r.$findOpeningBracket(\"]\",{column:u.column+1,row:u.row});if(l!==null&&d.isAutoInsertedClosing(u,a,i))return d.popAutoInsertedClosing(),{text:\"\",selection:[1,1]}}}}),this.add(\"brackets\",\"deletion\",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s==\"[\"){h(n);var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==\"]\")return i.end.column++,i}}),this.add(\"string_dquotes\",\"insertion\",function(e,t,n,r,i){var s=r.$mode.$quotes||c;if(i.length==1&&s[i]){if(this.lineCommentStart&&this.lineCommentStart.indexOf(i)!=-1)return;h(n);var o=i,u=n.getSelectionRange(),a=r.doc.getTextRange(u);if(a!==\"\"&&(a.length!=1||!s[a])&&n.getWrapBehavioursEnabled())return p(u,a,o,o);if(!a){var f=n.getCursorPosition(),l=r.doc.getLine(f.row),d=l.substring(f.column-1,f.column),v=l.substring(f.column,f.column+1),m=r.getTokenAt(f.row,f.column),g=r.getTokenAt(f.row,f.column+1);if(d==\"\\\\\"&&m&&/escape/.test(m.type))return null;var y=m&&/string|escape/.test(m.type),b=!g||/string|escape/.test(g.type),w;if(v==o)w=y!==b,w&&/string\\.end/.test(g.type)&&(w=!1);else{if(y&&!b)return null;if(y&&b)return null;var E=r.$mode.tokenRe;E.lastIndex=0;var S=E.test(d);E.lastIndex=0;var x=E.test(d);if(S||x)return null;if(v&&!/[\\s;,.})\\]\\\\]/.test(v))return null;w=!0}return{text:w?o+o:\"\",selection:[1,1]}}}}),this.add(\"string_dquotes\",\"deletion\",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&(s=='\"'||s==\"'\")){h(n);var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==s)return i.end.column++,i}})};d.isSaneInsertion=function(e,t){var n=e.getCursorPosition(),r=new s(t,n.row,n.column);if(!this.$matchTokenType(r.getCurrentToken()||\"text\",u)){var i=new s(t,n.row,n.column+1);if(!this.$matchTokenType(i.getCurrentToken()||\"text\",u))return!1}return r.stepForward(),r.getCurrentTokenRow()!==n.row||this.$matchTokenType(r.getCurrentToken()||\"text\",a)},d.$matchTokenType=function(e,t){return t.indexOf(e.type||e)>-1},d.recordAutoInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,i,f.autoInsertedLineEnd[0])||(f.autoInsertedBrackets=0),f.autoInsertedRow=r.row,f.autoInsertedLineEnd=n+i.substr(r.column),f.autoInsertedBrackets++},d.recordMaybeInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isMaybeInsertedClosing(r,i)||(f.maybeInsertedBrackets=0),f.maybeInsertedRow=r.row,f.maybeInsertedLineStart=i.substr(0,r.column)+n,f.maybeInsertedLineEnd=i.substr(r.column),f.maybeInsertedBrackets++},d.isAutoInsertedClosing=function(e,t,n){return f.autoInsertedBrackets>0&&e.row===f.autoInsertedRow&&n===f.autoInsertedLineEnd[0]&&t.substr(e.column)===f.autoInsertedLineEnd},d.isMaybeInsertedClosing=function(e,t){return f.maybeInsertedBrackets>0&&e.row===f.maybeInsertedRow&&t.substr(e.column)===f.maybeInsertedLineEnd&&t.substr(0,e.column)==f.maybeInsertedLineStart},d.popAutoInsertedClosing=function(){f.autoInsertedLineEnd=f.autoInsertedLineEnd.substr(1),f.autoInsertedBrackets--},d.clearMaybeInsertedClosing=function(){f&&(f.maybeInsertedBrackets=0,f.maybeInsertedRow=-1)},r.inherits(d,i),t.CstyleBehaviour=d}),define(\"ace/unicode\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";function r(e){var n=/\\w{4}/g;for(var r in e)t.packages[r]=e[r].replace(n,\"\\\\u$&\")}t.packages={},r({L:\"0041-005A0061-007A00AA00B500BA00C0-00D600D8-00F600F8-02C102C6-02D102E0-02E402EC02EE0370-037403760377037A-037D03860388-038A038C038E-03A103A3-03F503F7-0481048A-05250531-055605590561-058705D0-05EA05F0-05F20621-064A066E066F0671-06D306D506E506E606EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA07F407F507FA0800-0815081A082408280904-0939093D09500958-0961097109720979-097F0985-098C098F09900993-09A809AA-09B009B209B6-09B909BD09CE09DC09DD09DF-09E109F009F10A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A59-0A5C0A5E0A72-0A740A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD0AD00AE00AE10B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D0B5C0B5D0B5F-0B610B710B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BD00C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D0C580C590C600C610C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD0CDE0CE00CE10D05-0D0C0D0E-0D100D12-0D280D2A-0D390D3D0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E460E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EC60EDC0EDD0F000F40-0F470F49-0F6C0F88-0F8B1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10A0-10C510D0-10FA10FC1100-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A1380-138F13A0-13F41401-166C166F-167F1681-169A16A0-16EA1700-170C170E-17111720-17311740-17511760-176C176E-17701780-17B317D717DC1820-18771880-18A818AA18B0-18F51900-191C1950-196D1970-19741980-19AB19C1-19C71A00-1A161A20-1A541AA71B05-1B331B45-1B4B1B83-1BA01BAE1BAF1C00-1C231C4D-1C4F1C5A-1C7D1CE9-1CEC1CEE-1CF11D00-1DBF1E00-1F151F18-1F1D1F20-1F451F48-1F4D1F50-1F571F591F5B1F5D1F5F-1F7D1F80-1FB41FB6-1FBC1FBE1FC2-1FC41FC6-1FCC1FD0-1FD31FD6-1FDB1FE0-1FEC1FF2-1FF41FF6-1FFC2071207F2090-209421022107210A-211321152119-211D212421262128212A-212D212F-2139213C-213F2145-2149214E218321842C00-2C2E2C30-2C5E2C60-2CE42CEB-2CEE2D00-2D252D30-2D652D6F2D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE2E2F300530063031-3035303B303C3041-3096309D-309F30A1-30FA30FC-30FF3105-312D3131-318E31A0-31B731F0-31FF3400-4DB54E00-9FCBA000-A48CA4D0-A4FDA500-A60CA610-A61FA62AA62BA640-A65FA662-A66EA67F-A697A6A0-A6E5A717-A71FA722-A788A78BA78CA7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2A9CFAA00-AA28AA40-AA42AA44-AA4BAA60-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADB-AADDABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA2DFA30-FA6DFA70-FAD9FB00-FB06FB13-FB17FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF21-FF3AFF41-FF5AFF66-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC\",Ll:\"0061-007A00AA00B500BA00DF-00F600F8-00FF01010103010501070109010B010D010F01110113011501170119011B011D011F01210123012501270129012B012D012F01310133013501370138013A013C013E014001420144014601480149014B014D014F01510153015501570159015B015D015F01610163016501670169016B016D016F0171017301750177017A017C017E-0180018301850188018C018D019201950199-019B019E01A101A301A501A801AA01AB01AD01B001B401B601B901BA01BD-01BF01C601C901CC01CE01D001D201D401D601D801DA01DC01DD01DF01E101E301E501E701E901EB01ED01EF01F001F301F501F901FB01FD01FF02010203020502070209020B020D020F02110213021502170219021B021D021F02210223022502270229022B022D022F02310233-0239023C023F0240024202470249024B024D024F-02930295-02AF037103730377037B-037D039003AC-03CE03D003D103D5-03D703D903DB03DD03DF03E103E303E503E703E903EB03ED03EF-03F303F503F803FB03FC0430-045F04610463046504670469046B046D046F04710473047504770479047B047D047F0481048B048D048F04910493049504970499049B049D049F04A104A304A504A704A904AB04AD04AF04B104B304B504B704B904BB04BD04BF04C204C404C604C804CA04CC04CE04CF04D104D304D504D704D904DB04DD04DF04E104E304E504E704E904EB04ED04EF04F104F304F504F704F904FB04FD04FF05010503050505070509050B050D050F05110513051505170519051B051D051F0521052305250561-05871D00-1D2B1D62-1D771D79-1D9A1E011E031E051E071E091E0B1E0D1E0F1E111E131E151E171E191E1B1E1D1E1F1E211E231E251E271E291E2B1E2D1E2F1E311E331E351E371E391E3B1E3D1E3F1E411E431E451E471E491E4B1E4D1E4F1E511E531E551E571E591E5B1E5D1E5F1E611E631E651E671E691E6B1E6D1E6F1E711E731E751E771E791E7B1E7D1E7F1E811E831E851E871E891E8B1E8D1E8F1E911E931E95-1E9D1E9F1EA11EA31EA51EA71EA91EAB1EAD1EAF1EB11EB31EB51EB71EB91EBB1EBD1EBF1EC11EC31EC51EC71EC91ECB1ECD1ECF1ED11ED31ED51ED71ED91EDB1EDD1EDF1EE11EE31EE51EE71EE91EEB1EED1EEF1EF11EF31EF51EF71EF91EFB1EFD1EFF-1F071F10-1F151F20-1F271F30-1F371F40-1F451F50-1F571F60-1F671F70-1F7D1F80-1F871F90-1F971FA0-1FA71FB0-1FB41FB61FB71FBE1FC2-1FC41FC61FC71FD0-1FD31FD61FD71FE0-1FE71FF2-1FF41FF61FF7210A210E210F2113212F21342139213C213D2146-2149214E21842C30-2C5E2C612C652C662C682C6A2C6C2C712C732C742C76-2C7C2C812C832C852C872C892C8B2C8D2C8F2C912C932C952C972C992C9B2C9D2C9F2CA12CA32CA52CA72CA92CAB2CAD2CAF2CB12CB32CB52CB72CB92CBB2CBD2CBF2CC12CC32CC52CC72CC92CCB2CCD2CCF2CD12CD32CD52CD72CD92CDB2CDD2CDF2CE12CE32CE42CEC2CEE2D00-2D25A641A643A645A647A649A64BA64DA64FA651A653A655A657A659A65BA65DA65FA663A665A667A669A66BA66DA681A683A685A687A689A68BA68DA68FA691A693A695A697A723A725A727A729A72BA72DA72F-A731A733A735A737A739A73BA73DA73FA741A743A745A747A749A74BA74DA74FA751A753A755A757A759A75BA75DA75FA761A763A765A767A769A76BA76DA76FA771-A778A77AA77CA77FA781A783A785A787A78CFB00-FB06FB13-FB17FF41-FF5A\",Lu:\"0041-005A00C0-00D600D8-00DE01000102010401060108010A010C010E01100112011401160118011A011C011E01200122012401260128012A012C012E01300132013401360139013B013D013F0141014301450147014A014C014E01500152015401560158015A015C015E01600162016401660168016A016C016E017001720174017601780179017B017D018101820184018601870189-018B018E-0191019301940196-0198019C019D019F01A001A201A401A601A701A901AC01AE01AF01B1-01B301B501B701B801BC01C401C701CA01CD01CF01D101D301D501D701D901DB01DE01E001E201E401E601E801EA01EC01EE01F101F401F6-01F801FA01FC01FE02000202020402060208020A020C020E02100212021402160218021A021C021E02200222022402260228022A022C022E02300232023A023B023D023E02410243-02460248024A024C024E03700372037603860388-038A038C038E038F0391-03A103A3-03AB03CF03D2-03D403D803DA03DC03DE03E003E203E403E603E803EA03EC03EE03F403F703F903FA03FD-042F04600462046404660468046A046C046E04700472047404760478047A047C047E0480048A048C048E04900492049404960498049A049C049E04A004A204A404A604A804AA04AC04AE04B004B204B404B604B804BA04BC04BE04C004C104C304C504C704C904CB04CD04D004D204D404D604D804DA04DC04DE04E004E204E404E604E804EA04EC04EE04F004F204F404F604F804FA04FC04FE05000502050405060508050A050C050E05100512051405160518051A051C051E0520052205240531-055610A0-10C51E001E021E041E061E081E0A1E0C1E0E1E101E121E141E161E181E1A1E1C1E1E1E201E221E241E261E281E2A1E2C1E2E1E301E321E341E361E381E3A1E3C1E3E1E401E421E441E461E481E4A1E4C1E4E1E501E521E541E561E581E5A1E5C1E5E1E601E621E641E661E681E6A1E6C1E6E1E701E721E741E761E781E7A1E7C1E7E1E801E821E841E861E881E8A1E8C1E8E1E901E921E941E9E1EA01EA21EA41EA61EA81EAA1EAC1EAE1EB01EB21EB41EB61EB81EBA1EBC1EBE1EC01EC21EC41EC61EC81ECA1ECC1ECE1ED01ED21ED41ED61ED81EDA1EDC1EDE1EE01EE21EE41EE61EE81EEA1EEC1EEE1EF01EF21EF41EF61EF81EFA1EFC1EFE1F08-1F0F1F18-1F1D1F28-1F2F1F38-1F3F1F48-1F4D1F591F5B1F5D1F5F1F68-1F6F1FB8-1FBB1FC8-1FCB1FD8-1FDB1FE8-1FEC1FF8-1FFB21022107210B-210D2110-211221152119-211D212421262128212A-212D2130-2133213E213F214521832C00-2C2E2C602C62-2C642C672C692C6B2C6D-2C702C722C752C7E-2C802C822C842C862C882C8A2C8C2C8E2C902C922C942C962C982C9A2C9C2C9E2CA02CA22CA42CA62CA82CAA2CAC2CAE2CB02CB22CB42CB62CB82CBA2CBC2CBE2CC02CC22CC42CC62CC82CCA2CCC2CCE2CD02CD22CD42CD62CD82CDA2CDC2CDE2CE02CE22CEB2CEDA640A642A644A646A648A64AA64CA64EA650A652A654A656A658A65AA65CA65EA662A664A666A668A66AA66CA680A682A684A686A688A68AA68CA68EA690A692A694A696A722A724A726A728A72AA72CA72EA732A734A736A738A73AA73CA73EA740A742A744A746A748A74AA74CA74EA750A752A754A756A758A75AA75CA75EA760A762A764A766A768A76AA76CA76EA779A77BA77DA77EA780A782A784A786A78BFF21-FF3A\",Lt:\"01C501C801CB01F21F88-1F8F1F98-1F9F1FA8-1FAF1FBC1FCC1FFC\",Lm:\"02B0-02C102C6-02D102E0-02E402EC02EE0374037A0559064006E506E607F407F507FA081A0824082809710E460EC610FC17D718431AA71C78-1C7D1D2C-1D611D781D9B-1DBF2071207F2090-20942C7D2D6F2E2F30053031-3035303B309D309E30FC-30FEA015A4F8-A4FDA60CA67FA717-A71FA770A788A9CFAA70AADDFF70FF9EFF9F\",Lo:\"01BB01C0-01C3029405D0-05EA05F0-05F20621-063F0641-064A066E066F0671-06D306D506EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA0800-08150904-0939093D09500958-096109720979-097F0985-098C098F09900993-09A809AA-09B009B209B6-09B909BD09CE09DC09DD09DF-09E109F009F10A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A59-0A5C0A5E0A72-0A740A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD0AD00AE00AE10B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D0B5C0B5D0B5F-0B610B710B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BD00C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D0C580C590C600C610C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD0CDE0CE00CE10D05-0D0C0D0E-0D100D12-0D280D2A-0D390D3D0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E450E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EDC0EDD0F000F40-0F470F49-0F6C0F88-0F8B1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10D0-10FA1100-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A1380-138F13A0-13F41401-166C166F-167F1681-169A16A0-16EA1700-170C170E-17111720-17311740-17511760-176C176E-17701780-17B317DC1820-18421844-18771880-18A818AA18B0-18F51900-191C1950-196D1970-19741980-19AB19C1-19C71A00-1A161A20-1A541B05-1B331B45-1B4B1B83-1BA01BAE1BAF1C00-1C231C4D-1C4F1C5A-1C771CE9-1CEC1CEE-1CF12135-21382D30-2D652D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE3006303C3041-3096309F30A1-30FA30FF3105-312D3131-318E31A0-31B731F0-31FF3400-4DB54E00-9FCBA000-A014A016-A48CA4D0-A4F7A500-A60BA610-A61FA62AA62BA66EA6A0-A6E5A7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2AA00-AA28AA40-AA42AA44-AA4BAA60-AA6FAA71-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADBAADCABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA2DFA30-FA6DFA70-FAD9FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF66-FF6FFF71-FF9DFFA0-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC\",M:\"0300-036F0483-04890591-05BD05BF05C105C205C405C505C70610-061A064B-065E067006D6-06DC06DE-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0900-0903093C093E-094E0951-0955096209630981-098309BC09BE-09C409C709C809CB-09CD09D709E209E30A01-0A030A3C0A3E-0A420A470A480A4B-0A4D0A510A700A710A750A81-0A830ABC0ABE-0AC50AC7-0AC90ACB-0ACD0AE20AE30B01-0B030B3C0B3E-0B440B470B480B4B-0B4D0B560B570B620B630B820BBE-0BC20BC6-0BC80BCA-0BCD0BD70C01-0C030C3E-0C440C46-0C480C4A-0C4D0C550C560C620C630C820C830CBC0CBE-0CC40CC6-0CC80CCA-0CCD0CD50CD60CE20CE30D020D030D3E-0D440D46-0D480D4A-0D4D0D570D620D630D820D830DCA0DCF-0DD40DD60DD8-0DDF0DF20DF30E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F3E0F3F0F71-0F840F860F870F90-0F970F99-0FBC0FC6102B-103E1056-1059105E-10601062-10641067-106D1071-10741082-108D108F109A-109D135F1712-17141732-1734175217531772177317B6-17D317DD180B-180D18A91920-192B1930-193B19B0-19C019C819C91A17-1A1B1A55-1A5E1A60-1A7C1A7F1B00-1B041B34-1B441B6B-1B731B80-1B821BA1-1BAA1C24-1C371CD0-1CD21CD4-1CE81CED1CF21DC0-1DE61DFD-1DFF20D0-20F02CEF-2CF12DE0-2DFF302A-302F3099309AA66F-A672A67CA67DA6F0A6F1A802A806A80BA823-A827A880A881A8B4-A8C4A8E0-A8F1A926-A92DA947-A953A980-A983A9B3-A9C0AA29-AA36AA43AA4CAA4DAA7BAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1ABE3-ABEAABECABEDFB1EFE00-FE0FFE20-FE26\",Mn:\"0300-036F0483-04870591-05BD05BF05C105C205C405C505C70610-061A064B-065E067006D6-06DC06DF-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0900-0902093C0941-0948094D0951-095509620963098109BC09C1-09C409CD09E209E30A010A020A3C0A410A420A470A480A4B-0A4D0A510A700A710A750A810A820ABC0AC1-0AC50AC70AC80ACD0AE20AE30B010B3C0B3F0B41-0B440B4D0B560B620B630B820BC00BCD0C3E-0C400C46-0C480C4A-0C4D0C550C560C620C630CBC0CBF0CC60CCC0CCD0CE20CE30D41-0D440D4D0D620D630DCA0DD2-0DD40DD60E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F71-0F7E0F80-0F840F860F870F90-0F970F99-0FBC0FC6102D-10301032-10371039103A103D103E10581059105E-10601071-1074108210851086108D109D135F1712-17141732-1734175217531772177317B7-17BD17C617C9-17D317DD180B-180D18A91920-19221927192819321939-193B1A171A181A561A58-1A5E1A601A621A65-1A6C1A73-1A7C1A7F1B00-1B031B341B36-1B3A1B3C1B421B6B-1B731B801B811BA2-1BA51BA81BA91C2C-1C331C361C371CD0-1CD21CD4-1CE01CE2-1CE81CED1DC0-1DE61DFD-1DFF20D0-20DC20E120E5-20F02CEF-2CF12DE0-2DFF302A-302F3099309AA66FA67CA67DA6F0A6F1A802A806A80BA825A826A8C4A8E0-A8F1A926-A92DA947-A951A980-A982A9B3A9B6-A9B9A9BCAA29-AA2EAA31AA32AA35AA36AA43AA4CAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1ABE5ABE8ABEDFB1EFE00-FE0FFE20-FE26\",Mc:\"0903093E-09400949-094C094E0982098309BE-09C009C709C809CB09CC09D70A030A3E-0A400A830ABE-0AC00AC90ACB0ACC0B020B030B3E0B400B470B480B4B0B4C0B570BBE0BBF0BC10BC20BC6-0BC80BCA-0BCC0BD70C01-0C030C41-0C440C820C830CBE0CC0-0CC40CC70CC80CCA0CCB0CD50CD60D020D030D3E-0D400D46-0D480D4A-0D4C0D570D820D830DCF-0DD10DD8-0DDF0DF20DF30F3E0F3F0F7F102B102C10311038103B103C105610571062-10641067-106D108310841087-108C108F109A-109C17B617BE-17C517C717C81923-19261929-192B193019311933-193819B0-19C019C819C91A19-1A1B1A551A571A611A631A641A6D-1A721B041B351B3B1B3D-1B411B431B441B821BA11BA61BA71BAA1C24-1C2B1C341C351CE11CF2A823A824A827A880A881A8B4-A8C3A952A953A983A9B4A9B5A9BAA9BBA9BD-A9C0AA2FAA30AA33AA34AA4DAA7BABE3ABE4ABE6ABE7ABE9ABEAABEC\",Me:\"0488048906DE20DD-20E020E2-20E4A670-A672\",N:\"0030-003900B200B300B900BC-00BE0660-066906F0-06F907C0-07C90966-096F09E6-09EF09F4-09F90A66-0A6F0AE6-0AEF0B66-0B6F0BE6-0BF20C66-0C6F0C78-0C7E0CE6-0CEF0D66-0D750E50-0E590ED0-0ED90F20-0F331040-10491090-10991369-137C16EE-16F017E0-17E917F0-17F91810-18191946-194F19D0-19DA1A80-1A891A90-1A991B50-1B591BB0-1BB91C40-1C491C50-1C5920702074-20792080-20892150-21822185-21892460-249B24EA-24FF2776-27932CFD30073021-30293038-303A3192-31953220-32293251-325F3280-328932B1-32BFA620-A629A6E6-A6EFA830-A835A8D0-A8D9A900-A909A9D0-A9D9AA50-AA59ABF0-ABF9FF10-FF19\",Nd:\"0030-00390660-066906F0-06F907C0-07C90966-096F09E6-09EF0A66-0A6F0AE6-0AEF0B66-0B6F0BE6-0BEF0C66-0C6F0CE6-0CEF0D66-0D6F0E50-0E590ED0-0ED90F20-0F291040-10491090-109917E0-17E91810-18191946-194F19D0-19DA1A80-1A891A90-1A991B50-1B591BB0-1BB91C40-1C491C50-1C59A620-A629A8D0-A8D9A900-A909A9D0-A9D9AA50-AA59ABF0-ABF9FF10-FF19\",Nl:\"16EE-16F02160-21822185-218830073021-30293038-303AA6E6-A6EF\",No:\"00B200B300B900BC-00BE09F4-09F90BF0-0BF20C78-0C7E0D70-0D750F2A-0F331369-137C17F0-17F920702074-20792080-20892150-215F21892460-249B24EA-24FF2776-27932CFD3192-31953220-32293251-325F3280-328932B1-32BFA830-A835\",P:\"0021-00230025-002A002C-002F003A003B003F0040005B-005D005F007B007D00A100AB00B700BB00BF037E0387055A-055F0589058A05BE05C005C305C605F305F40609060A060C060D061B061E061F066A-066D06D40700-070D07F7-07F90830-083E0964096509700DF40E4F0E5A0E5B0F04-0F120F3A-0F3D0F850FD0-0FD4104A-104F10FB1361-13681400166D166E169B169C16EB-16ED1735173617D4-17D617D8-17DA1800-180A1944194519DE19DF1A1E1A1F1AA0-1AA61AA8-1AAD1B5A-1B601C3B-1C3F1C7E1C7F1CD32010-20272030-20432045-20512053-205E207D207E208D208E2329232A2768-277527C527C627E6-27EF2983-299829D8-29DB29FC29FD2CF9-2CFC2CFE2CFF2E00-2E2E2E302E313001-30033008-30113014-301F3030303D30A030FBA4FEA4FFA60D-A60FA673A67EA6F2-A6F7A874-A877A8CEA8CFA8F8-A8FAA92EA92FA95FA9C1-A9CDA9DEA9DFAA5C-AA5FAADEAADFABEBFD3EFD3FFE10-FE19FE30-FE52FE54-FE61FE63FE68FE6AFE6BFF01-FF03FF05-FF0AFF0C-FF0FFF1AFF1BFF1FFF20FF3B-FF3DFF3FFF5BFF5DFF5F-FF65\",Pd:\"002D058A05BE140018062010-20152E172E1A301C303030A0FE31FE32FE58FE63FF0D\",Ps:\"0028005B007B0F3A0F3C169B201A201E2045207D208D23292768276A276C276E27702772277427C527E627E827EA27EC27EE2983298529872989298B298D298F299129932995299729D829DA29FC2E222E242E262E283008300A300C300E3010301430163018301A301DFD3EFE17FE35FE37FE39FE3BFE3DFE3FFE41FE43FE47FE59FE5BFE5DFF08FF3BFF5BFF5FFF62\",Pe:\"0029005D007D0F3B0F3D169C2046207E208E232A2769276B276D276F27712773277527C627E727E927EB27ED27EF298429862988298A298C298E2990299229942996299829D929DB29FD2E232E252E272E293009300B300D300F3011301530173019301B301E301FFD3FFE18FE36FE38FE3AFE3CFE3EFE40FE42FE44FE48FE5AFE5CFE5EFF09FF3DFF5DFF60FF63\",Pi:\"00AB2018201B201C201F20392E022E042E092E0C2E1C2E20\",Pf:\"00BB2019201D203A2E032E052E0A2E0D2E1D2E21\",Pc:\"005F203F20402054FE33FE34FE4D-FE4FFF3F\",Po:\"0021-00230025-0027002A002C002E002F003A003B003F0040005C00A100B700BF037E0387055A-055F058905C005C305C605F305F40609060A060C060D061B061E061F066A-066D06D40700-070D07F7-07F90830-083E0964096509700DF40E4F0E5A0E5B0F04-0F120F850FD0-0FD4104A-104F10FB1361-1368166D166E16EB-16ED1735173617D4-17D617D8-17DA1800-18051807-180A1944194519DE19DF1A1E1A1F1AA0-1AA61AA8-1AAD1B5A-1B601C3B-1C3F1C7E1C7F1CD3201620172020-20272030-2038203B-203E2041-20432047-205120532055-205E2CF9-2CFC2CFE2CFF2E002E012E06-2E082E0B2E0E-2E162E182E192E1B2E1E2E1F2E2A-2E2E2E302E313001-3003303D30FBA4FEA4FFA60D-A60FA673A67EA6F2-A6F7A874-A877A8CEA8CFA8F8-A8FAA92EA92FA95FA9C1-A9CDA9DEA9DFAA5C-AA5FAADEAADFABEBFE10-FE16FE19FE30FE45FE46FE49-FE4CFE50-FE52FE54-FE57FE5F-FE61FE68FE6AFE6BFF01-FF03FF05-FF07FF0AFF0CFF0EFF0FFF1AFF1BFF1FFF20FF3CFF61FF64FF65\",S:\"0024002B003C-003E005E0060007C007E00A2-00A900AC00AE-00B100B400B600B800D700F702C2-02C502D2-02DF02E5-02EB02ED02EF-02FF03750384038503F604820606-0608060B060E060F06E906FD06FE07F609F209F309FA09FB0AF10B700BF3-0BFA0C7F0CF10CF20D790E3F0F01-0F030F13-0F170F1A-0F1F0F340F360F380FBE-0FC50FC7-0FCC0FCE0FCF0FD5-0FD8109E109F13601390-139917DB194019E0-19FF1B61-1B6A1B74-1B7C1FBD1FBF-1FC11FCD-1FCF1FDD-1FDF1FED-1FEF1FFD1FFE20442052207A-207C208A-208C20A0-20B8210021012103-21062108210921142116-2118211E-2123212521272129212E213A213B2140-2144214A-214D214F2190-2328232B-23E82400-24262440-244A249C-24E92500-26CD26CF-26E126E326E8-26FF2701-27042706-2709270C-27272729-274B274D274F-27522756-275E2761-276727942798-27AF27B1-27BE27C0-27C427C7-27CA27CC27D0-27E527F0-29822999-29D729DC-29FB29FE-2B4C2B50-2B592CE5-2CEA2E80-2E992E9B-2EF32F00-2FD52FF0-2FFB300430123013302030363037303E303F309B309C319031913196-319F31C0-31E33200-321E322A-32503260-327F328A-32B032C0-32FE3300-33FF4DC0-4DFFA490-A4C6A700-A716A720A721A789A78AA828-A82BA836-A839AA77-AA79FB29FDFCFDFDFE62FE64-FE66FE69FF04FF0BFF1C-FF1EFF3EFF40FF5CFF5EFFE0-FFE6FFE8-FFEEFFFCFFFD\",Sm:\"002B003C-003E007C007E00AC00B100D700F703F60606-060820442052207A-207C208A-208C2140-2144214B2190-2194219A219B21A021A321A621AE21CE21CF21D221D421F4-22FF2308-230B23202321237C239B-23B323DC-23E125B725C125F8-25FF266F27C0-27C427C7-27CA27CC27D0-27E527F0-27FF2900-29822999-29D729DC-29FB29FE-2AFF2B30-2B442B47-2B4CFB29FE62FE64-FE66FF0BFF1C-FF1EFF5CFF5EFFE2FFE9-FFEC\",Sc:\"002400A2-00A5060B09F209F309FB0AF10BF90E3F17DB20A0-20B8A838FDFCFE69FF04FFE0FFE1FFE5FFE6\",Sk:\"005E006000A800AF00B400B802C2-02C502D2-02DF02E5-02EB02ED02EF-02FF0375038403851FBD1FBF-1FC11FCD-1FCF1FDD-1FDF1FED-1FEF1FFD1FFE309B309CA700-A716A720A721A789A78AFF3EFF40FFE3\",So:\"00A600A700A900AE00B000B60482060E060F06E906FD06FE07F609FA0B700BF3-0BF80BFA0C7F0CF10CF20D790F01-0F030F13-0F170F1A-0F1F0F340F360F380FBE-0FC50FC7-0FCC0FCE0FCF0FD5-0FD8109E109F13601390-1399194019E0-19FF1B61-1B6A1B74-1B7C210021012103-21062108210921142116-2118211E-2123212521272129212E213A213B214A214C214D214F2195-2199219C-219F21A121A221A421A521A7-21AD21AF-21CD21D021D121D321D5-21F32300-2307230C-231F2322-2328232B-237B237D-239A23B4-23DB23E2-23E82400-24262440-244A249C-24E92500-25B625B8-25C025C2-25F72600-266E2670-26CD26CF-26E126E326E8-26FF2701-27042706-2709270C-27272729-274B274D274F-27522756-275E2761-276727942798-27AF27B1-27BE2800-28FF2B00-2B2F2B452B462B50-2B592CE5-2CEA2E80-2E992E9B-2EF32F00-2FD52FF0-2FFB300430123013302030363037303E303F319031913196-319F31C0-31E33200-321E322A-32503260-327F328A-32B032C0-32FE3300-33FF4DC0-4DFFA490-A4C6A828-A82BA836A837A839AA77-AA79FDFDFFE4FFE8FFEDFFEEFFFCFFFD\",Z:\"002000A01680180E2000-200A20282029202F205F3000\",Zs:\"002000A01680180E2000-200A202F205F3000\",Zl:\"2028\",Zp:\"2029\",C:\"0000-001F007F-009F00AD03780379037F-0383038B038D03A20526-05300557055805600588058B-059005C8-05CF05EB-05EF05F5-0605061C061D0620065F06DD070E070F074B074C07B2-07BF07FB-07FF082E082F083F-08FF093A093B094F095609570973-097809800984098D098E0991099209A909B109B3-09B509BA09BB09C509C609C909CA09CF-09D609D8-09DB09DE09E409E509FC-0A000A040A0B-0A0E0A110A120A290A310A340A370A3A0A3B0A3D0A43-0A460A490A4A0A4E-0A500A52-0A580A5D0A5F-0A650A76-0A800A840A8E0A920AA90AB10AB40ABA0ABB0AC60ACA0ACE0ACF0AD1-0ADF0AE40AE50AF00AF2-0B000B040B0D0B0E0B110B120B290B310B340B3A0B3B0B450B460B490B4A0B4E-0B550B58-0B5B0B5E0B640B650B72-0B810B840B8B-0B8D0B910B96-0B980B9B0B9D0BA0-0BA20BA5-0BA70BAB-0BAD0BBA-0BBD0BC3-0BC50BC90BCE0BCF0BD1-0BD60BD8-0BE50BFB-0C000C040C0D0C110C290C340C3A-0C3C0C450C490C4E-0C540C570C5A-0C5F0C640C650C70-0C770C800C810C840C8D0C910CA90CB40CBA0CBB0CC50CC90CCE-0CD40CD7-0CDD0CDF0CE40CE50CF00CF3-0D010D040D0D0D110D290D3A-0D3C0D450D490D4E-0D560D58-0D5F0D640D650D76-0D780D800D810D840D97-0D990DB20DBC0DBE0DBF0DC7-0DC90DCB-0DCE0DD50DD70DE0-0DF10DF5-0E000E3B-0E3E0E5C-0E800E830E850E860E890E8B0E8C0E8E-0E930E980EA00EA40EA60EA80EA90EAC0EBA0EBE0EBF0EC50EC70ECE0ECF0EDA0EDB0EDE-0EFF0F480F6D-0F700F8C-0F8F0F980FBD0FCD0FD9-0FFF10C6-10CF10FD-10FF1249124E124F12571259125E125F1289128E128F12B112B612B712BF12C112C612C712D7131113161317135B-135E137D-137F139A-139F13F5-13FF169D-169F16F1-16FF170D1715-171F1737-173F1754-175F176D17711774-177F17B417B517DE17DF17EA-17EF17FA-17FF180F181A-181F1878-187F18AB-18AF18F6-18FF191D-191F192C-192F193C-193F1941-1943196E196F1975-197F19AC-19AF19CA-19CF19DB-19DD1A1C1A1D1A5F1A7D1A7E1A8A-1A8F1A9A-1A9F1AAE-1AFF1B4C-1B4F1B7D-1B7F1BAB-1BAD1BBA-1BFF1C38-1C3A1C4A-1C4C1C80-1CCF1CF3-1CFF1DE7-1DFC1F161F171F1E1F1F1F461F471F4E1F4F1F581F5A1F5C1F5E1F7E1F7F1FB51FC51FD41FD51FDC1FF01FF11FF51FFF200B-200F202A-202E2060-206F20722073208F2095-209F20B9-20CF20F1-20FF218A-218F23E9-23FF2427-243F244B-245F26CE26E226E4-26E727002705270A270B2728274C274E2753-2755275F27602795-279727B027BF27CB27CD-27CF2B4D-2B4F2B5A-2BFF2C2F2C5F2CF2-2CF82D26-2D2F2D66-2D6E2D70-2D7F2D97-2D9F2DA72DAF2DB72DBF2DC72DCF2DD72DDF2E32-2E7F2E9A2EF4-2EFF2FD6-2FEF2FFC-2FFF3040309730983100-3104312E-3130318F31B8-31BF31E4-31EF321F32FF4DB6-4DBF9FCC-9FFFA48D-A48FA4C7-A4CFA62C-A63FA660A661A674-A67BA698-A69FA6F8-A6FFA78D-A7FAA82C-A82FA83A-A83FA878-A87FA8C5-A8CDA8DA-A8DFA8FC-A8FFA954-A95EA97D-A97FA9CEA9DA-A9DDA9E0-A9FFAA37-AA3FAA4EAA4FAA5AAA5BAA7C-AA7FAAC3-AADAAAE0-ABBFABEEABEFABFA-ABFFD7A4-D7AFD7C7-D7CAD7FC-F8FFFA2EFA2FFA6EFA6FFADA-FAFFFB07-FB12FB18-FB1CFB37FB3DFB3FFB42FB45FBB2-FBD2FD40-FD4FFD90FD91FDC8-FDEFFDFEFDFFFE1A-FE1FFE27-FE2FFE53FE67FE6C-FE6FFE75FEFD-FF00FFBF-FFC1FFC8FFC9FFD0FFD1FFD8FFD9FFDD-FFDFFFE7FFEF-FFFBFFFEFFFF\",Cc:\"0000-001F007F-009F\",Cf:\"00AD0600-060306DD070F17B417B5200B-200F202A-202E2060-2064206A-206FFEFFFFF9-FFFB\",Co:\"E000-F8FF\",Cs:\"D800-DFFF\",Cn:\"03780379037F-0383038B038D03A20526-05300557055805600588058B-059005C8-05CF05EB-05EF05F5-05FF06040605061C061D0620065F070E074B074C07B2-07BF07FB-07FF082E082F083F-08FF093A093B094F095609570973-097809800984098D098E0991099209A909B109B3-09B509BA09BB09C509C609C909CA09CF-09D609D8-09DB09DE09E409E509FC-0A000A040A0B-0A0E0A110A120A290A310A340A370A3A0A3B0A3D0A43-0A460A490A4A0A4E-0A500A52-0A580A5D0A5F-0A650A76-0A800A840A8E0A920AA90AB10AB40ABA0ABB0AC60ACA0ACE0ACF0AD1-0ADF0AE40AE50AF00AF2-0B000B040B0D0B0E0B110B120B290B310B340B3A0B3B0B450B460B490B4A0B4E-0B550B58-0B5B0B5E0B640B650B72-0B810B840B8B-0B8D0B910B96-0B980B9B0B9D0BA0-0BA20BA5-0BA70BAB-0BAD0BBA-0BBD0BC3-0BC50BC90BCE0BCF0BD1-0BD60BD8-0BE50BFB-0C000C040C0D0C110C290C340C3A-0C3C0C450C490C4E-0C540C570C5A-0C5F0C640C650C70-0C770C800C810C840C8D0C910CA90CB40CBA0CBB0CC50CC90CCE-0CD40CD7-0CDD0CDF0CE40CE50CF00CF3-0D010D040D0D0D110D290D3A-0D3C0D450D490D4E-0D560D58-0D5F0D640D650D76-0D780D800D810D840D97-0D990DB20DBC0DBE0DBF0DC7-0DC90DCB-0DCE0DD50DD70DE0-0DF10DF5-0E000E3B-0E3E0E5C-0E800E830E850E860E890E8B0E8C0E8E-0E930E980EA00EA40EA60EA80EA90EAC0EBA0EBE0EBF0EC50EC70ECE0ECF0EDA0EDB0EDE-0EFF0F480F6D-0F700F8C-0F8F0F980FBD0FCD0FD9-0FFF10C6-10CF10FD-10FF1249124E124F12571259125E125F1289128E128F12B112B612B712BF12C112C612C712D7131113161317135B-135E137D-137F139A-139F13F5-13FF169D-169F16F1-16FF170D1715-171F1737-173F1754-175F176D17711774-177F17DE17DF17EA-17EF17FA-17FF180F181A-181F1878-187F18AB-18AF18F6-18FF191D-191F192C-192F193C-193F1941-1943196E196F1975-197F19AC-19AF19CA-19CF19DB-19DD1A1C1A1D1A5F1A7D1A7E1A8A-1A8F1A9A-1A9F1AAE-1AFF1B4C-1B4F1B7D-1B7F1BAB-1BAD1BBA-1BFF1C38-1C3A1C4A-1C4C1C80-1CCF1CF3-1CFF1DE7-1DFC1F161F171F1E1F1F1F461F471F4E1F4F1F581F5A1F5C1F5E1F7E1F7F1FB51FC51FD41FD51FDC1FF01FF11FF51FFF2065-206920722073208F2095-209F20B9-20CF20F1-20FF218A-218F23E9-23FF2427-243F244B-245F26CE26E226E4-26E727002705270A270B2728274C274E2753-2755275F27602795-279727B027BF27CB27CD-27CF2B4D-2B4F2B5A-2BFF2C2F2C5F2CF2-2CF82D26-2D2F2D66-2D6E2D70-2D7F2D97-2D9F2DA72DAF2DB72DBF2DC72DCF2DD72DDF2E32-2E7F2E9A2EF4-2EFF2FD6-2FEF2FFC-2FFF3040309730983100-3104312E-3130318F31B8-31BF31E4-31EF321F32FF4DB6-4DBF9FCC-9FFFA48D-A48FA4C7-A4CFA62C-A63FA660A661A674-A67BA698-A69FA6F8-A6FFA78D-A7FAA82C-A82FA83A-A83FA878-A87FA8C5-A8CDA8DA-A8DFA8FC-A8FFA954-A95EA97D-A97FA9CEA9DA-A9DDA9E0-A9FFAA37-AA3FAA4EAA4FAA5AAA5BAA7C-AA7FAAC3-AADAAAE0-ABBFABEEABEFABFA-ABFFD7A4-D7AFD7C7-D7CAD7FC-D7FFFA2EFA2FFA6EFA6FFADA-FAFFFB07-FB12FB18-FB1CFB37FB3DFB3FFB42FB45FBB2-FBD2FD40-FD4FFD90FD91FDC8-FDEFFDFEFDFFFE1A-FE1FFE27-FE2FFE53FE67FE6C-FE6FFE75FEFDFEFEFF00FFBF-FFC1FFC8FFC9FFD0FFD1FFD8FFD9FFDD-FFDFFFE7FFEF-FFF8FFFEFFFF\"})}),define(\"ace/mode/text\",[\"require\",\"exports\",\"module\",\"ace/tokenizer\",\"ace/mode/text_highlight_rules\",\"ace/mode/behaviour/cstyle\",\"ace/unicode\",\"ace/lib/lang\",\"ace/token_iterator\",\"ace/range\"],function(e,t,n){\"use strict\";var r=e(\"../tokenizer\").Tokenizer,i=e(\"./text_highlight_rules\").TextHighlightRules,s=e(\"./behaviour/cstyle\").CstyleBehaviour,o=e(\"../unicode\"),u=e(\"../lib/lang\"),a=e(\"../token_iterator\").TokenIterator,f=e(\"../range\").Range,l=function(){this.HighlightRules=i};(function(){this.$defaultBehaviour=new s,this.tokenRe=new RegExp(\"^[\"+o.packages.L+o.packages.Mn+o.packages.Mc+o.packages.Nd+o.packages.Pc+\"\\\\$_]+\",\"g\"),this.nonTokenRe=new RegExp(\"^(?:[^\"+o.packages.L+o.packages.Mn+o.packages.Mc+o.packages.Nd+o.packages.Pc+\"\\\\$_]|\\\\s])+\",\"g\"),this.getTokenizer=function(){return this.$tokenizer||(this.$highlightRules=this.$highlightRules||new this.HighlightRules(this.$highlightRuleConfig),this.$tokenizer=new r(this.$highlightRules.getRules())),this.$tokenizer},this.lineCommentStart=\"\",this.blockComment=\"\",this.toggleCommentLines=function(e,t,n,r){function w(e){for(var t=n;t<=r;t++)e(i.getLine(t),t)}var i=t.doc,s=!0,o=!0,a=Infinity,f=t.getTabSize(),l=!1;if(!this.lineCommentStart){if(!this.blockComment)return!1;var c=this.blockComment.start,h=this.blockComment.end,p=new RegExp(\"^(\\\\s*)(?:\"+u.escapeRegExp(c)+\")\"),d=new RegExp(\"(?:\"+u.escapeRegExp(h)+\")\\\\s*$\"),v=function(e,t){if(g(e,t))return;if(!s||/\\S/.test(e))i.insertInLine({row:t,column:e.length},h),i.insertInLine({row:t,column:a},c)},m=function(e,t){var n;(n=e.match(d))&&i.removeInLine(t,e.length-n[0].length,e.length),(n=e.match(p))&&i.removeInLine(t,n[1].length,n[0].length)},g=function(e,n){if(p.test(e))return!0;var r=t.getTokens(n);for(var i=0;i<r.length;i++)if(r[i].type===\"comment\")return!0}}else{if(Array.isArray(this.lineCommentStart))var p=this.lineCommentStart.map(u.escapeRegExp).join(\"|\"),c=this.lineCommentStart[0];else var p=u.escapeRegExp(this.lineCommentStart),c=this.lineCommentStart;p=new RegExp(\"^(\\\\s*)(?:\"+p+\") ?\"),l=t.getUseSoftTabs();var m=function(e,t){var n=e.match(p);if(!n)return;var r=n[1].length,s=n[0].length;!b(e,r,s)&&n[0][s-1]==\" \"&&s--,i.removeInLine(t,r,s)},y=c+\" \",v=function(e,t){if(!s||/\\S/.test(e))b(e,a,a)?i.insertInLine({row:t,column:a},y):i.insertInLine({row:t,column:a},c)},g=function(e,t){return p.test(e)},b=function(e,t,n){var r=0;while(t--&&e.charAt(t)==\" \")r++;if(r%f!=0)return!1;var r=0;while(e.charAt(n++)==\" \")r++;return f>2?r%f!=f-1:r%f==0}}var E=Infinity;w(function(e,t){var n=e.search(/\\S/);n!==-1?(n<a&&(a=n),o&&!g(e,t)&&(o=!1)):E>e.length&&(E=e.length)}),a==Infinity&&(a=E,s=!1,o=!1),l&&a%f!=0&&(a=Math.floor(a/f)*f),w(o?m:v)},this.toggleBlockComment=function(e,t,n,r){var i=this.blockComment;if(!i)return;!i.start&&i[0]&&(i=i[0]);var s=new a(t,r.row,r.column),o=s.getCurrentToken(),u=t.selection,l=t.selection.toOrientedRange(),c,h;if(o&&/comment/.test(o.type)){var p,d;while(o&&/comment/.test(o.type)){var v=o.value.indexOf(i.start);if(v!=-1){var m=s.getCurrentTokenRow(),g=s.getCurrentTokenColumn()+v;p=new f(m,g,m,g+i.start.length);break}o=s.stepBackward()}var s=new a(t,r.row,r.column),o=s.getCurrentToken();while(o&&/comment/.test(o.type)){var v=o.value.indexOf(i.end);if(v!=-1){var m=s.getCurrentTokenRow(),g=s.getCurrentTokenColumn()+v;d=new f(m,g,m,g+i.end.length);break}o=s.stepForward()}d&&t.remove(d),p&&(t.remove(p),c=p.start.row,h=-i.start.length)}else h=i.start.length,c=n.start.row,t.insert(n.end,i.end),t.insert(n.start,i.start);l.start.row==c&&(l.start.column+=h),l.end.row==c&&(l.end.column+=h),t.selection.fromOrientedRange(l)},this.getNextLineIndent=function(e,t,n){return this.$getIndent(t)},this.checkOutdent=function(e,t,n){return!1},this.autoOutdent=function(e,t,n){},this.$getIndent=function(e){return e.match(/^\\s*/)[0]},this.createWorker=function(e){return null},this.createModeDelegates=function(e){this.$embeds=[],this.$modes={};for(var t in e)e[t]&&(this.$embeds.push(t),this.$modes[t]=new e[t]);var n=[\"toggleBlockComment\",\"toggleCommentLines\",\"getNextLineIndent\",\"checkOutdent\",\"autoOutdent\",\"transformAction\",\"getCompletions\"];for(var t=0;t<n.length;t++)(function(e){var r=n[t],i=e[r];e[n[t]]=function(){return this.$delegator(r,arguments,i)}})(this)},this.$delegator=function(e,t,n){var r=t[0];typeof r!=\"string\"&&(r=r[0]);for(var i=0;i<this.$embeds.length;i++){if(!this.$modes[this.$embeds[i]])continue;var s=r.split(this.$embeds[i]);if(!s[0]&&s[1]){t[0]=s[1];var o=this.$modes[this.$embeds[i]];return o[e].apply(o,t)}}var u=n.apply(this,t);return n?u:undefined},this.transformAction=function(e,t,n,r,i){if(this.$behaviour){var s=this.$behaviour.getBehaviours();for(var o in s)if(s[o][t]){var u=s[o][t].apply(this,arguments);if(u)return u}}},this.getKeywords=function(e){if(!this.completionKeywords){var t=this.$tokenizer.rules,n=[];for(var r in t){var i=t[r];for(var s=0,o=i.length;s<o;s++)if(typeof i[s].token==\"string\")/keyword|support|storage/.test(i[s].token)&&n.push(i[s].regex);else if(typeof i[s].token==\"object\")for(var u=0,a=i[s].token.length;u<a;u++)if(/keyword|support|storage/.test(i[s].token[u])){var r=i[s].regex.match(/\\(.+?\\)/g)[u];n.push(r.substr(1,r.length-2))}}this.completionKeywords=n}return e?n.concat(this.$keywordList||[]):this.$keywordList},this.$createKeywordList=function(){return this.$highlightRules||this.getTokenizer(),this.$keywordList=this.$highlightRules.$keywordList||[]},this.getCompletions=function(e,t,n,r){var i=this.$keywordList||this.$createKeywordList();return i.map(function(e){return{name:e,value:e,score:0,meta:\"keyword\"}})},this.$id=\"ace/mode/text\"}).call(l.prototype),t.Mode=l}),define(\"ace/apply_delta\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";function r(e,t){throw console.log(\"Invalid Delta:\",e),\"Invalid Delta: \"+t}function i(e,t){return t.row>=0&&t.row<e.length&&t.column>=0&&t.column<=e[t.row].length}function s(e,t){t.action!=\"insert\"&&t.action!=\"remove\"&&r(t,\"delta.action must be 'insert' or 'remove'\"),t.lines instanceof Array||r(t,\"delta.lines must be an Array\"),(!t.start||!t.end)&&r(t,\"delta.start/end must be an present\");var n=t.start;i(e,t.start)||r(t,\"delta.start must be contained in document\");var s=t.end;t.action==\"remove\"&&!i(e,s)&&r(t,\"delta.end must contained in document for 'remove' actions\");var o=s.row-n.row,u=s.column-(o==0?n.column:0);(o!=t.lines.length-1||t.lines[o].length!=u)&&r(t,\"delta.range must match delta lines\")}t.applyDelta=function(e,t,n){var r=t.start.row,i=t.start.column,s=e[r]||\"\";switch(t.action){case\"insert\":var o=t.lines;if(o.length===1)e[r]=s.substring(0,i)+t.lines[0]+s.substring(i);else{var u=[r,1].concat(t.lines);e.splice.apply(e,u),e[r]=s.substring(0,i)+e[r],e[r+t.lines.length-1]+=s.substring(i)}break;case\"remove\":var a=t.end.column,f=t.end.row;r===f?e[r]=s.substring(0,i)+s.substring(a):e.splice(r,f-r+1,s.substring(0,i)+e[f].substring(a))}}}),define(\"ace/anchor\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/event_emitter\"],function(e,t,n){\"use strict\";var r=e(\"./lib/oop\"),i=e(\"./lib/event_emitter\").EventEmitter,s=t.Anchor=function(e,t,n){this.$onChange=this.onChange.bind(this),this.attach(e),typeof n==\"undefined\"?this.setPosition(t.row,t.column):this.setPosition(t,n)};(function(){function e(e,t,n){var r=n?e.column<=t.column:e.column<t.column;return e.row<t.row||e.row==t.row&&r}function t(t,n,r){var i=t.action==\"insert\",s=(i?1:-1)*(t.end.row-t.start.row),o=(i?1:-1)*(t.end.column-t.start.column),u=t.start,a=i?u:t.end;return e(n,u,r)?{row:n.row,column:n.column}:e(a,n,!r)?{row:n.row+s,column:n.column+(n.row==a.row?o:0)}:{row:u.row,column:u.column}}r.implement(this,i),this.getPosition=function(){return this.$clipPositionToDocument(this.row,this.column)},this.getDocument=function(){return this.document},this.$insertRight=!1,this.onChange=function(e){if(e.start.row==e.end.row&&e.start.row!=this.row)return;if(e.start.row>this.row)return;var n=t(e,{row:this.row,column:this.column},this.$insertRight);this.setPosition(n.row,n.column,!0)},this.setPosition=function(e,t,n){var r;n?r={row:e,column:t}:r=this.$clipPositionToDocument(e,t);if(this.row==r.row&&this.column==r.column)return;var i={row:this.row,column:this.column};this.row=r.row,this.column=r.column,this._signal(\"change\",{old:i,value:r})},this.detach=function(){this.document.removeEventListener(\"change\",this.$onChange)},this.attach=function(e){this.document=e||this.document,this.document.on(\"change\",this.$onChange)},this.$clipPositionToDocument=function(e,t){var n={};return e>=this.document.getLength()?(n.row=Math.max(0,this.document.getLength()-1),n.column=this.document.getLine(n.row).length):e<0?(n.row=0,n.column=0):(n.row=e,n.column=Math.min(this.document.getLine(n.row).length,Math.max(0,t))),t<0&&(n.column=0),n}}).call(s.prototype)}),define(\"ace/document\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/apply_delta\",\"ace/lib/event_emitter\",\"ace/range\",\"ace/anchor\"],function(e,t,n){\"use strict\";var r=e(\"./lib/oop\"),i=e(\"./apply_delta\").applyDelta,s=e(\"./lib/event_emitter\").EventEmitter,o=e(\"./range\").Range,u=e(\"./anchor\").Anchor,a=function(e){this.$lines=[\"\"],e.length===0?this.$lines=[\"\"]:Array.isArray(e)?this.insertMergedLines({row:0,column:0},e):this.insert({row:0,column:0},e)};(function(){r.implement(this,s),this.setValue=function(e){var t=this.getLength()-1;this.remove(new o(0,0,t,this.getLine(t).length)),this.insert({row:0,column:0},e)},this.getValue=function(){return this.getAllLines().join(this.getNewLineCharacter())},this.createAnchor=function(e,t){return new u(this,e,t)},\"aaa\".split(/a/).length===0?this.$split=function(e){return e.replace(/\\r\\n|\\r/g,\"\\n\").split(\"\\n\")}:this.$split=function(e){return e.split(/\\r\\n|\\r|\\n/)},this.$detectNewLine=function(e){var t=e.match(/^.*?(\\r\\n|\\r|\\n)/m);this.$autoNewLine=t?t[1]:\"\\n\",this._signal(\"changeNewLineMode\")},this.getNewLineCharacter=function(){switch(this.$newLineMode){case\"windows\":return\"\\r\\n\";case\"unix\":return\"\\n\";default:return this.$autoNewLine||\"\\n\"}},this.$autoNewLine=\"\",this.$newLineMode=\"auto\",this.setNewLineMode=function(e){if(this.$newLineMode===e)return;this.$newLineMode=e,this._signal(\"changeNewLineMode\")},this.getNewLineMode=function(){return this.$newLineMode},this.isNewLine=function(e){return e==\"\\r\\n\"||e==\"\\r\"||e==\"\\n\"},this.getLine=function(e){return this.$lines[e]||\"\"},this.getLines=function(e,t){return this.$lines.slice(e,t+1)},this.getAllLines=function(){return this.getLines(0,this.getLength())},this.getLength=function(){return this.$lines.length},this.getTextRange=function(e){return this.getLinesForRange(e).join(this.getNewLineCharacter())},this.getLinesForRange=function(e){var t;if(e.start.row===e.end.row)t=[this.getLine(e.start.row).substring(e.start.column,e.end.column)];else{t=this.getLines(e.start.row,e.end.row),t[0]=(t[0]||\"\").substring(e.start.column);var n=t.length-1;e.end.row-e.start.row==n&&(t[n]=t[n].substring(0,e.end.column))}return t},this.insertLines=function(e,t){return console.warn(\"Use of document.insertLines is deprecated. Use the insertFullLines method instead.\"),this.insertFullLines(e,t)},this.removeLines=function(e,t){return console.warn(\"Use of document.removeLines is deprecated. Use the removeFullLines method instead.\"),this.removeFullLines(e,t)},this.insertNewLine=function(e){return console.warn(\"Use of document.insertNewLine is deprecated. Use insertMergedLines(position, ['', '']) instead.\"),this.insertMergedLines(e,[\"\",\"\"])},this.insert=function(e,t){return this.getLength()<=1&&this.$detectNewLine(t),this.insertMergedLines(e,this.$split(t))},this.insertInLine=function(e,t){var n=this.clippedPos(e.row,e.column),r=this.pos(e.row,e.column+t.length);return this.applyDelta({start:n,end:r,action:\"insert\",lines:[t]},!0),this.clonePos(r)},this.clippedPos=function(e,t){var n=this.getLength();e===undefined?e=n:e<0?e=0:e>=n&&(e=n-1,t=undefined);var r=this.getLine(e);return t==undefined&&(t=r.length),t=Math.min(Math.max(t,0),r.length),{row:e,column:t}},this.clonePos=function(e){return{row:e.row,column:e.column}},this.pos=function(e,t){return{row:e,column:t}},this.$clipPosition=function(e){var t=this.getLength();return e.row>=t?(e.row=Math.max(0,t-1),e.column=this.getLine(t-1).length):(e.row=Math.max(0,e.row),e.column=Math.min(Math.max(e.column,0),this.getLine(e.row).length)),e},this.insertFullLines=function(e,t){e=Math.min(Math.max(e,0),this.getLength());var n=0;e<this.getLength()?(t=t.concat([\"\"]),n=0):(t=[\"\"].concat(t),e--,n=this.$lines[e].length),this.insertMergedLines({row:e,column:n},t)},this.insertMergedLines=function(e,t){var n=this.clippedPos(e.row,e.column),r={row:n.row+t.length-1,column:(t.length==1?n.column:0)+t[t.length-1].length};return this.applyDelta({start:n,end:r,action:\"insert\",lines:t}),this.clonePos(r)},this.remove=function(e){var t=this.clippedPos(e.start.row,e.start.column),n=this.clippedPos(e.end.row,e.end.column);return this.applyDelta({start:t,end:n,action:\"remove\",lines:this.getLinesForRange({start:t,end:n})}),this.clonePos(t)},this.removeInLine=function(e,t,n){var r=this.clippedPos(e,t),i=this.clippedPos(e,n);return this.applyDelta({start:r,end:i,action:\"remove\",lines:this.getLinesForRange({start:r,end:i})},!0),this.clonePos(r)},this.removeFullLines=function(e,t){e=Math.min(Math.max(0,e),this.getLength()-1),t=Math.min(Math.max(0,t),this.getLength()-1);var n=t==this.getLength()-1&&e>0,r=t<this.getLength()-1,i=n?e-1:e,s=n?this.getLine(i).length:0,u=r?t+1:t,a=r?0:this.getLine(u).length,f=new o(i,s,u,a),l=this.$lines.slice(e,t+1);return this.applyDelta({start:f.start,end:f.end,action:\"remove\",lines:this.getLinesForRange(f)}),l},this.removeNewLine=function(e){e<this.getLength()-1&&e>=0&&this.applyDelta({start:this.pos(e,this.getLine(e).length),end:this.pos(e+1,0),action:\"remove\",lines:[\"\",\"\"]})},this.replace=function(e,t){e instanceof o||(e=o.fromPoints(e.start,e.end));if(t.length===0&&e.isEmpty())return e.start;if(t==this.getTextRange(e))return e.end;this.remove(e);var n;return t?n=this.insert(e.start,t):n=e.start,n},this.applyDeltas=function(e){for(var t=0;t<e.length;t++)this.applyDelta(e[t])},this.revertDeltas=function(e){for(var t=e.length-1;t>=0;t--)this.revertDelta(e[t])},this.applyDelta=function(e,t){var n=e.action==\"insert\";if(n?e.lines.length<=1&&!e.lines[0]:!o.comparePoints(e.start,e.end))return;n&&e.lines.length>2e4&&this.$splitAndapplyLargeDelta(e,2e4),i(this.$lines,e,t),this._signal(\"change\",e)},this.$splitAndapplyLargeDelta=function(e,t){var n=e.lines,r=n.length,i=e.start.row,s=e.start.column,o=0,u=0;do{o=u,u+=t-1;var a=n.slice(o,u);if(u>r){e.lines=a,e.start.row=i+o,e.start.column=s;break}a.push(\"\"),this.applyDelta({start:this.pos(i+o,s),end:this.pos(i+u,s=0),action:e.action,lines:a},!0)}while(!0)},this.revertDelta=function(e){this.applyDelta({start:this.clonePos(e.start),end:this.clonePos(e.end),action:e.action==\"insert\"?\"remove\":\"insert\",lines:e.lines.slice()})},this.indexToPosition=function(e,t){var n=this.$lines||this.getAllLines(),r=this.getNewLineCharacter().length;for(var i=t||0,s=n.length;i<s;i++){e-=n[i].length+r;if(e<0)return{row:i,column:e+n[i].length+r}}return{row:s-1,column:n[s-1].length}},this.positionToIndex=function(e,t){var n=this.$lines||this.getAllLines(),r=this.getNewLineCharacter().length,i=0,s=Math.min(e.row,n.length);for(var o=t||0;o<s;++o)i+=n[o].length+r;return i+e.column}}).call(a.prototype),t.Document=a}),define(\"ace/background_tokenizer\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/event_emitter\"],function(e,t,n){\"use strict\";var r=e(\"./lib/oop\"),i=e(\"./lib/event_emitter\").EventEmitter,s=function(e,t){this.running=!1,this.lines=[],this.states=[],this.currentLine=0,this.tokenizer=e;var n=this;this.$worker=function(){if(!n.running)return;var e=new Date,t=n.currentLine,r=-1,i=n.doc,s=t;while(n.lines[t])t++;var o=i.getLength(),u=0;n.running=!1;while(t<o){n.$tokenizeRow(t),r=t;do t++;while(n.lines[t]);u++;if(u%5===0&&new Date-e>20){n.running=setTimeout(n.$worker,20);break}}n.currentLine=t,r==-1&&(r=t),s<=r&&n.fireUpdateEvent(s,r)}};(function(){r.implement(this,i),this.setTokenizer=function(e){this.tokenizer=e,this.lines=[],this.states=[],this.start(0)},this.setDocument=function(e){this.doc=e,this.lines=[],this.states=[],this.stop()},this.fireUpdateEvent=function(e,t){var n={first:e,last:t};this._signal(\"update\",{data:n})},this.start=function(e){this.currentLine=Math.min(e||0,this.currentLine,this.doc.getLength()),this.lines.splice(this.currentLine,this.lines.length),this.states.splice(this.currentLine,this.states.length),this.stop(),this.running=setTimeout(this.$worker,700)},this.scheduleStart=function(){this.running||(this.running=setTimeout(this.$worker,700))},this.$updateOnChange=function(e){var t=e.start.row,n=e.end.row-t;if(n===0)this.lines[t]=null;else if(e.action==\"remove\")this.lines.splice(t,n+1,null),this.states.splice(t,n+1,null);else{var r=Array(n+1);r.unshift(t,1),this.lines.splice.apply(this.lines,r),this.states.splice.apply(this.states,r)}this.currentLine=Math.min(t,this.currentLine,this.doc.getLength()),this.stop()},this.stop=function(){this.running&&clearTimeout(this.running),this.running=!1},this.getTokens=function(e){return this.lines[e]||this.$tokenizeRow(e)},this.getState=function(e){return this.currentLine==e&&this.$tokenizeRow(e),this.states[e]||\"start\"},this.$tokenizeRow=function(e){var t=this.doc.getLine(e),n=this.states[e-1],r=this.tokenizer.getLineTokens(t,n,e);return this.states[e]+\"\"!=r.state+\"\"?(this.states[e]=r.state,this.lines[e+1]=null,this.currentLine>e+1&&(this.currentLine=e+1)):this.currentLine==e&&(this.currentLine=e+1),this.lines[e]=r.tokens}}).call(s.prototype),t.BackgroundTokenizer=s}),define(\"ace/search_highlight\",[\"require\",\"exports\",\"module\",\"ace/lib/lang\",\"ace/lib/oop\",\"ace/range\"],function(e,t,n){\"use strict\";var r=e(\"./lib/lang\"),i=e(\"./lib/oop\"),s=e(\"./range\").Range,o=function(e,t,n){this.setRegexp(e),this.clazz=t,this.type=n||\"text\"};(function(){this.MAX_RANGES=500,this.setRegexp=function(e){if(this.regExp+\"\"==e+\"\")return;this.regExp=e,this.cache=[]},this.update=function(e,t,n,i){if(!this.regExp)return;var o=i.firstRow,u=i.lastRow;for(var a=o;a<=u;a++){var f=this.cache[a];f==null&&(f=r.getMatchOffsets(n.getLine(a),this.regExp),f.length>this.MAX_RANGES&&(f=f.slice(0,this.MAX_RANGES)),f=f.map(function(e){return new s(a,e.offset,a,e.offset+e.length)}),this.cache[a]=f.length?f:\"\");for(var l=f.length;l--;)t.drawSingleLineMarker(e,f[l].toScreenRange(n),this.clazz,i)}}}).call(o.prototype),t.SearchHighlight=o}),define(\"ace/edit_session/fold_line\",[\"require\",\"exports\",\"module\",\"ace/range\"],function(e,t,n){\"use strict\";function i(e,t){this.foldData=e,Array.isArray(t)?this.folds=t:t=this.folds=[t];var n=t[t.length-1];this.range=new r(t[0].start.row,t[0].start.column,n.end.row,n.end.column),this.start=this.range.start,this.end=this.range.end,this.folds.forEach(function(e){e.setFoldLine(this)},this)}var r=e(\"../range\").Range;(function(){this.shiftRow=function(e){this.start.row+=e,this.end.row+=e,this.folds.forEach(function(t){t.start.row+=e,t.end.row+=e})},this.addFold=function(e){if(e.sameRow){if(e.start.row<this.startRow||e.endRow>this.endRow)throw new Error(\"Can't add a fold to this FoldLine as it has no connection\");this.folds.push(e),this.folds.sort(function(e,t){return-e.range.compareEnd(t.start.row,t.start.column)}),this.range.compareEnd(e.start.row,e.start.column)>0?(this.end.row=e.end.row,this.end.column=e.end.column):this.range.compareStart(e.end.row,e.end.column)<0&&(this.start.row=e.start.row,this.start.column=e.start.column)}else if(e.start.row==this.end.row)this.folds.push(e),this.end.row=e.end.row,this.end.column=e.end.column;else{if(e.end.row!=this.start.row)throw new Error(\"Trying to add fold to FoldRow that doesn't have a matching row\");this.folds.unshift(e),this.start.row=e.start.row,this.start.column=e.start.column}e.foldLine=this},this.containsRow=function(e){return e>=this.start.row&&e<=this.end.row},this.walk=function(e,t,n){var r=0,i=this.folds,s,o,u,a=!0;t==null&&(t=this.end.row,n=this.end.column);for(var f=0;f<i.length;f++){s=i[f],o=s.range.compareStart(t,n);if(o==-1){e(null,t,n,r,a);return}u=e(null,s.start.row,s.start.column,r,a),u=!u&&e(s.placeholder,s.start.row,s.start.column,r);if(u||o===0)return;a=!s.sameRow,r=s.end.column}e(null,t,n,r,a)},this.getNextFoldTo=function(e,t){var n,r;for(var i=0;i<this.folds.length;i++){n=this.folds[i],r=n.range.compareEnd(e,t);if(r==-1)return{fold:n,kind:\"after\"};if(r===0)return{fold:n,kind:\"inside\"}}return null},this.addRemoveChars=function(e,t,n){var r=this.getNextFoldTo(e,t),i,s;if(r){i=r.fold;if(r.kind==\"inside\"&&i.start.column!=t&&i.start.row!=e)window.console&&window.console.log(e,t,i);else if(i.start.row==e){s=this.folds;var o=s.indexOf(i);o===0&&(this.start.column+=n);for(o;o<s.length;o++){i=s[o],i.start.column+=n;if(!i.sameRow)return;i.end.column+=n}this.end.column+=n}}},this.split=function(e,t){var n=this.getNextFoldTo(e,t);if(!n||n.kind==\"inside\")return null;var r=n.fold,s=this.folds,o=this.foldData,u=s.indexOf(r),a=s[u-1];this.end.row=a.end.row,this.end.column=a.end.column,s=s.splice(u,s.length-u);var f=new i(o,s);return o.splice(o.indexOf(this)+1,0,f),f},this.merge=function(e){var t=e.folds;for(var n=0;n<t.length;n++)this.addFold(t[n]);var r=this.foldData;r.splice(r.indexOf(e),1)},this.toString=function(){var e=[this.range.toString()+\": [\"];return this.folds.forEach(function(t){e.push(\"  \"+t.toString())}),e.push(\"]\"),e.join(\"\\n\")},this.idxToPosition=function(e){var t=0;for(var n=0;n<this.folds.length;n++){var r=this.folds[n];e-=r.start.column-t;if(e<0)return{row:r.start.row,column:r.start.column+e};e-=r.placeholder.length;if(e<0)return r.start;t=r.end.column}return{row:this.end.row,column:this.end.column+e}}}).call(i.prototype),t.FoldLine=i}),define(\"ace/range_list\",[\"require\",\"exports\",\"module\",\"ace/range\"],function(e,t,n){\"use strict\";var r=e(\"./range\").Range,i=r.comparePoints,s=function(){this.ranges=[]};(function(){this.comparePoints=i,this.pointIndex=function(e,t,n){var r=this.ranges;for(var s=n||0;s<r.length;s++){var o=r[s],u=i(e,o.end);if(u>0)continue;var a=i(e,o.start);return u===0?t&&a!==0?-s-2:s:a>0||a===0&&!t?s:-s-1}return-s-1},this.add=function(e){var t=!e.isEmpty(),n=this.pointIndex(e.start,t);n<0&&(n=-n-1);var r=this.pointIndex(e.end,t,n);return r<0?r=-r-1:r++,this.ranges.splice(n,r-n,e)},this.addList=function(e){var t=[];for(var n=e.length;n--;)t.push.apply(t,this.add(e[n]));return t},this.substractPoint=function(e){var t=this.pointIndex(e);if(t>=0)return this.ranges.splice(t,1)},this.merge=function(){var e=[],t=this.ranges;t=t.sort(function(e,t){return i(e.start,t.start)});var n=t[0],r;for(var s=1;s<t.length;s++){r=n,n=t[s];var o=i(r.end,n.start);if(o<0)continue;if(o==0&&!r.isEmpty()&&!n.isEmpty())continue;i(r.end,n.end)<0&&(r.end.row=n.end.row,r.end.column=n.end.column),t.splice(s,1),e.push(n),n=r,s--}return this.ranges=t,e},this.contains=function(e,t){return this.pointIndex({row:e,column:t})>=0},this.containsPoint=function(e){return this.pointIndex(e)>=0},this.rangeAtPoint=function(e){var t=this.pointIndex(e);if(t>=0)return this.ranges[t]},this.clipRows=function(e,t){var n=this.ranges;if(n[0].start.row>t||n[n.length-1].start.row<e)return[];var r=this.pointIndex({row:e,column:0});r<0&&(r=-r-1);var i=this.pointIndex({row:t,column:0},r);i<0&&(i=-i-1);var s=[];for(var o=r;o<i;o++)s.push(n[o]);return s},this.removeAll=function(){return this.ranges.splice(0,this.ranges.length)},this.attach=function(e){this.session&&this.detach(),this.session=e,this.onChange=this.$onChange.bind(this),this.session.on(\"change\",this.onChange)},this.detach=function(){if(!this.session)return;this.session.removeListener(\"change\",this.onChange),this.session=null},this.$onChange=function(e){if(e.action==\"insert\")var t=e.start,n=e.end;else var n=e.start,t=e.end;var r=t.row,i=n.row,s=i-r,o=-t.column+n.column,u=this.ranges;for(var a=0,f=u.length;a<f;a++){var l=u[a];if(l.end.row<r)continue;if(l.start.row>r)break;l.start.row==r&&l.start.column>=t.column&&(l.start.column!=t.column||!this.$insertRight)&&(l.start.column+=o,l.start.row+=s);if(l.end.row==r&&l.end.column>=t.column){if(l.end.column==t.column&&this.$insertRight)continue;l.end.column==t.column&&o>0&&a<f-1&&l.end.column>l.start.column&&l.end.column==u[a+1].start.column&&(l.end.column-=o),l.end.column+=o,l.end.row+=s}}if(s!=0&&a<f)for(;a<f;a++){var l=u[a];l.start.row+=s,l.end.row+=s}}}).call(s.prototype),t.RangeList=s}),define(\"ace/edit_session/fold\",[\"require\",\"exports\",\"module\",\"ace/range\",\"ace/range_list\",\"ace/lib/oop\"],function(e,t,n){\"use strict\";function u(e,t){e.row-=t.row,e.row==0&&(e.column-=t.column)}function a(e,t){u(e.start,t),u(e.end,t)}function f(e,t){e.row==0&&(e.column+=t.column),e.row+=t.row}function l(e,t){f(e.start,t),f(e.end,t)}var r=e(\"../range\").Range,i=e(\"../range_list\").RangeList,s=e(\"../lib/oop\"),o=t.Fold=function(e,t){this.foldLine=null,this.placeholder=t,this.range=e,this.start=e.start,this.end=e.end,this.sameRow=e.start.row==e.end.row,this.subFolds=this.ranges=[]};s.inherits(o,i),function(){this.toString=function(){return'\"'+this.placeholder+'\" '+this.range.toString()},this.setFoldLine=function(e){this.foldLine=e,this.subFolds.forEach(function(t){t.setFoldLine(e)})},this.clone=function(){var e=this.range.clone(),t=new o(e,this.placeholder);return this.subFolds.forEach(function(e){t.subFolds.push(e.clone())}),t.collapseChildren=this.collapseChildren,t},this.addSubFold=function(e){if(this.range.isEqual(e))return;if(!this.range.containsRange(e))throw new Error(\"A fold can't intersect already existing fold\"+e.range+this.range);a(e,this.start);var t=e.start.row,n=e.start.column;for(var r=0,i=-1;r<this.subFolds.length;r++){i=this.subFolds[r].range.compare(t,n);if(i!=1)break}var s=this.subFolds[r];if(i==0)return s.addSubFold(e);var t=e.range.end.row,n=e.range.end.column;for(var o=r,i=-1;o<this.subFolds.length;o++){i=this.subFolds[o].range.compare(t,n);if(i!=1)break}var u=this.subFolds[o];if(i==0)throw new Error(\"A fold can't intersect already existing fold\"+e.range+this.range);var f=this.subFolds.splice(r,o-r,e);return e.setFoldLine(this.foldLine),e},this.restoreRange=function(e){return l(e,this.start)}}.call(o.prototype)}),define(\"ace/edit_session/folding\",[\"require\",\"exports\",\"module\",\"ace/range\",\"ace/edit_session/fold_line\",\"ace/edit_session/fold\",\"ace/token_iterator\"],function(e,t,n){\"use strict\";function u(){this.getFoldAt=function(e,t,n){var r=this.getFoldLine(e);if(!r)return null;var i=r.folds;for(var s=0;s<i.length;s++){var o=i[s];if(o.range.contains(e,t)){if(n==1&&o.range.isEnd(e,t))continue;if(n==-1&&o.range.isStart(e,t))continue;return o}}},this.getFoldsInRange=function(e){var t=e.start,n=e.end,r=this.$foldData,i=[];t.column+=1,n.column-=1;for(var s=0;s<r.length;s++){var o=r[s].range.compareRange(e);if(o==2)continue;if(o==-2)break;var u=r[s].folds;for(var a=0;a<u.length;a++){var f=u[a];o=f.range.compareRange(e);if(o==-2)break;if(o==2)continue;if(o==42)break;i.push(f)}}return t.column-=1,n.column+=1,i},this.getFoldsInRangeList=function(e){if(Array.isArray(e)){var t=[];e.forEach(function(e){t=t.concat(this.getFoldsInRange(e))},this)}else var t=this.getFoldsInRange(e);return t},this.getAllFolds=function(){var e=[],t=this.$foldData;for(var n=0;n<t.length;n++)for(var r=0;r<t[n].folds.length;r++)e.push(t[n].folds[r]);return e},this.getFoldStringAt=function(e,t,n,r){r=r||this.getFoldLine(e);if(!r)return null;var i={end:{column:0}},s,o;for(var u=0;u<r.folds.length;u++){o=r.folds[u];var a=o.range.compareEnd(e,t);if(a==-1){s=this.getLine(o.start.row).substring(i.end.column,o.start.column);break}if(a===0)return null;i=o}return s||(s=this.getLine(o.start.row).substring(i.end.column)),n==-1?s.substring(0,t-i.end.column):n==1?s.substring(t-i.end.column):s},this.getFoldLine=function(e,t){var n=this.$foldData,r=0;t&&(r=n.indexOf(t)),r==-1&&(r=0);for(r;r<n.length;r++){var i=n[r];if(i.start.row<=e&&i.end.row>=e)return i;if(i.end.row>e)return null}return null},this.getNextFoldLine=function(e,t){var n=this.$foldData,r=0;t&&(r=n.indexOf(t)),r==-1&&(r=0);for(r;r<n.length;r++){var i=n[r];if(i.end.row>=e)return i}return null},this.getFoldedRowCount=function(e,t){var n=this.$foldData,r=t-e+1;for(var i=0;i<n.length;i++){var s=n[i],o=s.end.row,u=s.start.row;if(o>=t){u<t&&(u>=e?r-=t-u:r=0);break}o>=e&&(u>=e?r-=o-u:r-=o-e+1)}return r},this.$addFoldLine=function(e){return this.$foldData.push(e),this.$foldData.sort(function(e,t){return e.start.row-t.start.row}),e},this.addFold=function(e,t){var n=this.$foldData,r=!1,o;e instanceof s?o=e:(o=new s(t,e),o.collapseChildren=t.collapseChildren),this.$clipRangeToDocument(o.range);var u=o.start.row,a=o.start.column,f=o.end.row,l=o.end.column;if(u<f||u==f&&a<=l-2){var c=this.getFoldAt(u,a,1),h=this.getFoldAt(f,l,-1);if(c&&h==c)return c.addSubFold(o);c&&!c.range.isStart(u,a)&&this.removeFold(c),h&&!h.range.isEnd(f,l)&&this.removeFold(h);var p=this.getFoldsInRange(o.range);p.length>0&&(this.removeFolds(p),p.forEach(function(e){o.addSubFold(e)}));for(var d=0;d<n.length;d++){var v=n[d];if(f==v.start.row){v.addFold(o),r=!0;break}if(u==v.end.row){v.addFold(o),r=!0;if(!o.sameRow){var m=n[d+1];if(m&&m.start.row==f){v.merge(m);break}}break}if(f<=v.start.row)break}return r||(v=this.$addFoldLine(new i(this.$foldData,o))),this.$useWrapMode?this.$updateWrapData(v.start.row,v.start.row):this.$updateRowLengthCache(v.start.row,v.start.row),this.$modified=!0,this._signal(\"changeFold\",{data:o,action:\"add\"}),o}throw new Error(\"The range has to be at least 2 characters width\")},this.addFolds=function(e){e.forEach(function(e){this.addFold(e)},this)},this.removeFold=function(e){var t=e.foldLine,n=t.start.row,r=t.end.row,i=this.$foldData,s=t.folds;if(s.length==1)i.splice(i.indexOf(t),1);else if(t.range.isEnd(e.end.row,e.end.column))s.pop(),t.end.row=s[s.length-1].end.row,t.end.column=s[s.length-1].end.column;else if(t.range.isStart(e.start.row,e.start.column))s.shift(),t.start.row=s[0].start.row,t.start.column=s[0].start.column;else if(e.sameRow)s.splice(s.indexOf(e),1);else{var o=t.split(e.start.row,e.start.column);s=o.folds,s.shift(),o.start.row=s[0].start.row,o.start.column=s[0].start.column}this.$updating||(this.$useWrapMode?this.$updateWrapData(n,r):this.$updateRowLengthCache(n,r)),this.$modified=!0,this._signal(\"changeFold\",{data:e,action:\"remove\"})},this.removeFolds=function(e){var t=[];for(var n=0;n<e.length;n++)t.push(e[n]);t.forEach(function(e){this.removeFold(e)},this),this.$modified=!0},this.expandFold=function(e){this.removeFold(e),e.subFolds.forEach(function(t){e.restoreRange(t),this.addFold(t)},this),e.collapseChildren>0&&this.foldAll(e.start.row+1,e.end.row,e.collapseChildren-1),e.subFolds=[]},this.expandFolds=function(e){e.forEach(function(e){this.expandFold(e)},this)},this.unfold=function(e,t){var n,i;e==null?(n=new r(0,0,this.getLength(),0),t=!0):typeof e==\"number\"?n=new r(e,0,e,this.getLine(e).length):\"row\"in e?n=r.fromPoints(e,e):n=e,i=this.getFoldsInRangeList(n);if(t)this.removeFolds(i);else{var s=i;while(s.length)this.expandFolds(s),s=this.getFoldsInRangeList(n)}if(i.length)return i},this.isRowFolded=function(e,t){return!!this.getFoldLine(e,t)},this.getRowFoldEnd=function(e,t){var n=this.getFoldLine(e,t);return n?n.end.row:e},this.getRowFoldStart=function(e,t){var n=this.getFoldLine(e,t);return n?n.start.row:e},this.getFoldDisplayLine=function(e,t,n,r,i){r==null&&(r=e.start.row),i==null&&(i=0),t==null&&(t=e.end.row),n==null&&(n=this.getLine(t).length);var s=this.doc,o=\"\";return e.walk(function(e,t,n,u){if(t<r)return;if(t==r){if(n<i)return;u=Math.max(i,u)}e!=null?o+=e:o+=s.getLine(t).substring(u,n)},t,n),o},this.getDisplayLine=function(e,t,n,r){var i=this.getFoldLine(e);if(!i){var s;return s=this.doc.getLine(e),s.substring(r||0,t||s.length)}return this.getFoldDisplayLine(i,e,t,n,r)},this.$cloneFoldData=function(){var e=[];return e=this.$foldData.map(function(t){var n=t.folds.map(function(e){return e.clone()});return new i(e,n)}),e},this.toggleFold=function(e){var t=this.selection,n=t.getRange(),r,i;if(n.isEmpty()){var s=n.start;r=this.getFoldAt(s.row,s.column);if(r){this.expandFold(r);return}(i=this.findMatchingBracket(s))?n.comparePoint(i)==1?n.end=i:(n.start=i,n.start.column++,n.end.column--):(i=this.findMatchingBracket({row:s.row,column:s.column+1}))?(n.comparePoint(i)==1?n.end=i:n.start=i,n.start.column++):n=this.getCommentFoldRange(s.row,s.column)||n}else{var o=this.getFoldsInRange(n);if(e&&o.length){this.expandFolds(o);return}o.length==1&&(r=o[0])}r||(r=this.getFoldAt(n.start.row,n.start.column));if(r&&r.range.toString()==n.toString()){this.expandFold(r);return}var u=\"...\";if(!n.isMultiLine()){u=this.getTextRange(n);if(u.length<4)return;u=u.trim().substring(0,2)+\"..\"}this.addFold(u,n)},this.getCommentFoldRange=function(e,t,n){var i=new o(this,e,t),s=i.getCurrentToken(),u=s.type;if(s&&/^comment|string/.test(u)){u=u.match(/comment|string/)[0],u==\"comment\"&&(u+=\"|doc-start\");var a=new RegExp(u),f=new r;if(n!=1){do s=i.stepBackward();while(s&&a.test(s.type));i.stepForward()}f.start.row=i.getCurrentTokenRow(),f.start.column=i.getCurrentTokenColumn()+2,i=new o(this,e,t);if(n!=-1){var l=-1;do{s=i.stepForward();if(l==-1){var c=this.getState(i.$row);a.test(c)||(l=i.$row)}else if(i.$row>l)break}while(s&&a.test(s.type));s=i.stepBackward()}else s=i.getCurrentToken();return f.end.row=i.getCurrentTokenRow(),f.end.column=i.getCurrentTokenColumn()+s.value.length-2,f}},this.foldAll=function(e,t,n){n==undefined&&(n=1e5);var r=this.foldWidgets;if(!r)return;t=t||this.getLength(),e=e||0;for(var i=e;i<t;i++){r[i]==null&&(r[i]=this.getFoldWidget(i));if(r[i]!=\"start\")continue;var s=this.getFoldWidgetRange(i);if(s&&s.isMultiLine()&&s.end.row<=t&&s.start.row>=e){i=s.end.row;try{var o=this.addFold(\"...\",s);o&&(o.collapseChildren=n)}catch(u){}}}},this.$foldStyles={manual:1,markbegin:1,markbeginend:1},this.$foldStyle=\"markbegin\",this.setFoldStyle=function(e){if(!this.$foldStyles[e])throw new Error(\"invalid fold style: \"+e+\"[\"+Object.keys(this.$foldStyles).join(\", \")+\"]\");if(this.$foldStyle==e)return;this.$foldStyle=e,e==\"manual\"&&this.unfold();var t=this.$foldMode;this.$setFolding(null),this.$setFolding(t)},this.$setFolding=function(e){if(this.$foldMode==e)return;this.$foldMode=e,this.off(\"change\",this.$updateFoldWidgets),this.off(\"tokenizerUpdate\",this.$tokenizerUpdateFoldWidgets),this._signal(\"changeAnnotation\");if(!e||this.$foldStyle==\"manual\"){this.foldWidgets=null;return}this.foldWidgets=[],this.getFoldWidget=e.getFoldWidget.bind(e,this,this.$foldStyle),this.getFoldWidgetRange=e.getFoldWidgetRange.bind(e,this,this.$foldStyle),this.$updateFoldWidgets=this.updateFoldWidgets.bind(this),this.$tokenizerUpdateFoldWidgets=this.tokenizerUpdateFoldWidgets.bind(this),this.on(\"change\",this.$updateFoldWidgets),this.on(\"tokenizerUpdate\",this.$tokenizerUpdateFoldWidgets)},this.getParentFoldRangeData=function(e,t){var n=this.foldWidgets;if(!n||t&&n[e])return{};var r=e-1,i;while(r>=0){var s=n[r];s==null&&(s=n[r]=this.getFoldWidget(r));if(s==\"start\"){var o=this.getFoldWidgetRange(r);i||(i=o);if(o&&o.end.row>=e)break}r--}return{range:r!==-1&&o,firstRange:i}},this.onFoldWidgetClick=function(e,t){t=t.domEvent;var n={children:t.shiftKey,all:t.ctrlKey||t.metaKey,siblings:t.altKey},r=this.$toggleFoldWidget(e,n);if(!r){var i=t.target||t.srcElement;i&&/ace_fold-widget/.test(i.className)&&(i.className+=\" ace_invalid\")}},this.$toggleFoldWidget=function(e,t){if(!this.getFoldWidget)return;var n=this.getFoldWidget(e),r=this.getLine(e),i=n===\"end\"?-1:1,s=this.getFoldAt(e,i===-1?0:r.length,i);if(s)return t.children||t.all?this.removeFold(s):this.expandFold(s),s;var o=this.getFoldWidgetRange(e,!0);if(o&&!o.isMultiLine()){s=this.getFoldAt(o.start.row,o.start.column,1);if(s&&o.isEqual(s.range))return this.removeFold(s),s}if(t.siblings){var u=this.getParentFoldRangeData(e);if(u.range)var a=u.range.start.row+1,f=u.range.end.row;this.foldAll(a,f,t.all?1e4:0)}else t.children?(f=o?o.end.row:this.getLength(),this.foldAll(e+1,f,t.all?1e4:0)):o&&(t.all&&(o.collapseChildren=1e4),this.addFold(\"...\",o));return o},this.toggleFoldWidget=function(e){var t=this.selection.getCursor().row;t=this.getRowFoldStart(t);var n=this.$toggleFoldWidget(t,{});if(n)return;var r=this.getParentFoldRangeData(t,!0);n=r.range||r.firstRange;if(n){t=n.start.row;var i=this.getFoldAt(t,this.getLine(t).length,1);i?this.removeFold(i):this.addFold(\"...\",n)}},this.updateFoldWidgets=function(e){var t=e.start.row,n=e.end.row-t;if(n===0)this.foldWidgets[t]=null;else if(e.action==\"remove\")this.foldWidgets.splice(t,n+1,null);else{var r=Array(n+1);r.unshift(t,1),this.foldWidgets.splice.apply(this.foldWidgets,r)}},this.tokenizerUpdateFoldWidgets=function(e){var t=e.data;t.first!=t.last&&this.foldWidgets.length>t.first&&this.foldWidgets.splice(t.first,this.foldWidgets.length)}}var r=e(\"../range\").Range,i=e(\"./fold_line\").FoldLine,s=e(\"./fold\").Fold,o=e(\"../token_iterator\").TokenIterator;t.Folding=u}),define(\"ace/edit_session/bracket_match\",[\"require\",\"exports\",\"module\",\"ace/token_iterator\",\"ace/range\"],function(e,t,n){\"use strict\";function s(){this.findMatchingBracket=function(e,t){if(e.column==0)return null;var n=t||this.getLine(e.row).charAt(e.column-1);if(n==\"\")return null;var r=n.match(/([\\(\\[\\{])|([\\)\\]\\}])/);return r?r[1]?this.$findClosingBracket(r[1],e):this.$findOpeningBracket(r[2],e):null},this.getBracketRange=function(e){var t=this.getLine(e.row),n=!0,r,s=t.charAt(e.column-1),o=s&&s.match(/([\\(\\[\\{])|([\\)\\]\\}])/);o||(s=t.charAt(e.column),e={row:e.row,column:e.column+1},o=s&&s.match(/([\\(\\[\\{])|([\\)\\]\\}])/),n=!1);if(!o)return null;if(o[1]){var u=this.$findClosingBracket(o[1],e);if(!u)return null;r=i.fromPoints(e,u),n||(r.end.column++,r.start.column--),r.cursor=r.end}else{var u=this.$findOpeningBracket(o[2],e);if(!u)return null;r=i.fromPoints(u,e),n||(r.start.column++,r.end.column--),r.cursor=r.start}return r},this.$brackets={\")\":\"(\",\"(\":\")\",\"]\":\"[\",\"[\":\"]\",\"{\":\"}\",\"}\":\"{\"},this.$findOpeningBracket=function(e,t,n){var i=this.$brackets[e],s=1,o=new r(this,t.row,t.column),u=o.getCurrentToken();u||(u=o.stepForward());if(!u)return;n||(n=new RegExp(\"(\\\\.?\"+u.type.replace(\".\",\"\\\\.\").replace(\"rparen\",\".paren\").replace(/\\b(?:end)\\b/,\"(?:start|begin|end)\")+\")+\"));var a=t.column-o.getCurrentTokenColumn()-2,f=u.value;for(;;){while(a>=0){var l=f.charAt(a);if(l==i){s-=1;if(s==0)return{row:o.getCurrentTokenRow(),column:a+o.getCurrentTokenColumn()}}else l==e&&(s+=1);a-=1}do u=o.stepBackward();while(u&&!n.test(u.type));if(u==null)break;f=u.value,a=f.length-1}return null},this.$findClosingBracket=function(e,t,n){var i=this.$brackets[e],s=1,o=new r(this,t.row,t.column),u=o.getCurrentToken();u||(u=o.stepForward());if(!u)return;n||(n=new RegExp(\"(\\\\.?\"+u.type.replace(\".\",\"\\\\.\").replace(\"lparen\",\".paren\").replace(/\\b(?:start|begin)\\b/,\"(?:start|begin|end)\")+\")+\"));var a=t.column-o.getCurrentTokenColumn();for(;;){var f=u.value,l=f.length;while(a<l){var c=f.charAt(a);if(c==i){s-=1;if(s==0)return{row:o.getCurrentTokenRow(),column:a+o.getCurrentTokenColumn()}}else c==e&&(s+=1);a+=1}do u=o.stepForward();while(u&&!n.test(u.type));if(u==null)break;a=0}return null}}var r=e(\"../token_iterator\").TokenIterator,i=e(\"../range\").Range;t.BracketMatch=s}),define(\"ace/edit_session\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/lang\",\"ace/bidihandler\",\"ace/config\",\"ace/lib/event_emitter\",\"ace/selection\",\"ace/mode/text\",\"ace/range\",\"ace/document\",\"ace/background_tokenizer\",\"ace/search_highlight\",\"ace/edit_session/folding\",\"ace/edit_session/bracket_match\"],function(e,t,n){\"use strict\";var r=e(\"./lib/oop\"),i=e(\"./lib/lang\"),s=e(\"./bidihandler\").BidiHandler,o=e(\"./config\"),u=e(\"./lib/event_emitter\").EventEmitter,a=e(\"./selection\").Selection,f=e(\"./mode/text\").Mode,l=e(\"./range\").Range,c=e(\"./document\").Document,h=e(\"./background_tokenizer\").BackgroundTokenizer,p=e(\"./search_highlight\").SearchHighlight,d=function(e,t){this.$breakpoints=[],this.$decorations=[],this.$frontMarkers={},this.$backMarkers={},this.$markerId=1,this.$undoSelect=!0,this.$foldData=[],this.id=\"session\"+ ++d.$uid,this.$foldData.toString=function(){return this.join(\"\\n\")},this.on(\"changeFold\",this.onChangeFold.bind(this)),this.$onChange=this.onChange.bind(this);if(typeof e!=\"object\"||!e.getLine)e=new c(e);this.$bidiHandler=new s(this),this.setDocument(e),this.selection=new a(this),o.resetOptions(this),this.setMode(t),o._signal(\"session\",this)};d.$uid=0,function(){function m(e){return e<4352?!1:e>=4352&&e<=4447||e>=4515&&e<=4519||e>=4602&&e<=4607||e>=9001&&e<=9002||e>=11904&&e<=11929||e>=11931&&e<=12019||e>=12032&&e<=12245||e>=12272&&e<=12283||e>=12288&&e<=12350||e>=12353&&e<=12438||e>=12441&&e<=12543||e>=12549&&e<=12589||e>=12593&&e<=12686||e>=12688&&e<=12730||e>=12736&&e<=12771||e>=12784&&e<=12830||e>=12832&&e<=12871||e>=12880&&e<=13054||e>=13056&&e<=19903||e>=19968&&e<=42124||e>=42128&&e<=42182||e>=43360&&e<=43388||e>=44032&&e<=55203||e>=55216&&e<=55238||e>=55243&&e<=55291||e>=63744&&e<=64255||e>=65040&&e<=65049||e>=65072&&e<=65106||e>=65108&&e<=65126||e>=65128&&e<=65131||e>=65281&&e<=65376||e>=65504&&e<=65510}r.implement(this,u),this.setDocument=function(e){this.doc&&this.doc.removeListener(\"change\",this.$onChange),this.doc=e,e.on(\"change\",this.$onChange),this.bgTokenizer&&this.bgTokenizer.setDocument(this.getDocument()),this.resetCaches()},this.getDocument=function(){return this.doc},this.$resetRowCache=function(e){if(!e){this.$docRowCache=[],this.$screenRowCache=[];return}var t=this.$docRowCache.length,n=this.$getRowCacheIndex(this.$docRowCache,e)+1;t>n&&(this.$docRowCache.splice(n,t),this.$screenRowCache.splice(n,t))},this.$getRowCacheIndex=function(e,t){var n=0,r=e.length-1;while(n<=r){var i=n+r>>1,s=e[i];if(t>s)n=i+1;else{if(!(t<s))return i;r=i-1}}return n-1},this.resetCaches=function(){this.$modified=!0,this.$wrapData=[],this.$rowLengthCache=[],this.$resetRowCache(0),this.bgTokenizer&&this.bgTokenizer.start(0)},this.onChangeFold=function(e){var t=e.data;this.$resetRowCache(t.start.row)},this.onChange=function(e){this.$modified=!0,this.$bidiHandler.onChange(e),this.$resetRowCache(e.start.row);var t=this.$updateInternalDataOnChange(e);!this.$fromUndo&&this.$undoManager&&!e.ignore&&(this.$deltasDoc.push(e),t&&t.length!=0&&this.$deltasFold.push({action:\"removeFolds\",folds:t}),this.$informUndoManager.schedule()),this.bgTokenizer&&this.bgTokenizer.$updateOnChange(e),this._signal(\"change\",e)},this.setValue=function(e){this.doc.setValue(e),this.selection.moveTo(0,0),this.$resetRowCache(0),this.$deltas=[],this.$deltasDoc=[],this.$deltasFold=[],this.setUndoManager(this.$undoManager),this.getUndoManager().reset()},this.getValue=this.toString=function(){return this.doc.getValue()},this.getSelection=function(){return this.selection},this.getState=function(e){return this.bgTokenizer.getState(e)},this.getTokens=function(e){return this.bgTokenizer.getTokens(e)},this.getTokenAt=function(e,t){var n=this.bgTokenizer.getTokens(e),r,i=0;if(t==null){var s=n.length-1;i=this.getLine(e).length}else for(var s=0;s<n.length;s++){i+=n[s].value.length;if(i>=t)break}return r=n[s],r?(r.index=s,r.start=i-r.value.length,r):null},this.setUndoManager=function(e){this.$undoManager=e,this.$deltas=[],this.$deltasDoc=[],this.$deltasFold=[],this.$informUndoManager&&this.$informUndoManager.cancel();if(e){var t=this;this.$syncInformUndoManager=function(){t.$informUndoManager.cancel(),t.$deltasFold.length&&(t.$deltas.push({group:\"fold\",deltas:t.$deltasFold}),t.$deltasFold=[]),t.$deltasDoc.length&&(t.$deltas.push({group:\"doc\",deltas:t.$deltasDoc}),t.$deltasDoc=[]),t.$deltas.length>0&&e.execute({action:\"aceupdate\",args:[t.$deltas,t],merge:t.mergeUndoDeltas}),t.mergeUndoDeltas=!1,t.$deltas=[]},this.$informUndoManager=i.delayedCall(this.$syncInformUndoManager)}},this.markUndoGroup=function(){this.$syncInformUndoManager&&this.$syncInformUndoManager()},this.$defaultUndoManager={undo:function(){},redo:function(){},reset:function(){}},this.getUndoManager=function(){return this.$undoManager||this.$defaultUndoManager},this.getTabString=function(){return this.getUseSoftTabs()?i.stringRepeat(\" \",this.getTabSize()):\"\t\"},this.setUseSoftTabs=function(e){this.setOption(\"useSoftTabs\",e)},this.getUseSoftTabs=function(){return this.$useSoftTabs&&!this.$mode.$indentWithTabs},this.setTabSize=function(e){this.setOption(\"tabSize\",e)},this.getTabSize=function(){return this.$tabSize},this.isTabStop=function(e){return this.$useSoftTabs&&e.column%this.$tabSize===0},this.setNavigateWithinSoftTabs=function(e){this.setOption(\"navigateWithinSoftTabs\",e)},this.getNavigateWithinSoftTabs=function(){return this.$navigateWithinSoftTabs},this.$overwrite=!1,this.setOverwrite=function(e){this.setOption(\"overwrite\",e)},this.getOverwrite=function(){return this.$overwrite},this.toggleOverwrite=function(){this.setOverwrite(!this.$overwrite)},this.addGutterDecoration=function(e,t){this.$decorations[e]||(this.$decorations[e]=\"\"),this.$decorations[e]+=\" \"+t,this._signal(\"changeBreakpoint\",{})},this.removeGutterDecoration=function(e,t){this.$decorations[e]=(this.$decorations[e]||\"\").replace(\" \"+t,\"\"),this._signal(\"changeBreakpoint\",{})},this.getBreakpoints=function(){return this.$breakpoints},this.setBreakpoints=function(e){this.$breakpoints=[];for(var t=0;t<e.length;t++)this.$breakpoints[e[t]]=\"ace_breakpoint\";this._signal(\"changeBreakpoint\",{})},this.clearBreakpoints=function(){this.$breakpoints=[],this._signal(\"changeBreakpoint\",{})},this.setBreakpoint=function(e,t){t===undefined&&(t=\"ace_breakpoint\"),t?this.$breakpoints[e]=t:delete this.$breakpoints[e],this._signal(\"changeBreakpoint\",{})},this.clearBreakpoint=function(e){delete this.$breakpoints[e],this._signal(\"changeBreakpoint\",{})},this.addMarker=function(e,t,n,r){var i=this.$markerId++,s={range:e,type:n||\"line\",renderer:typeof n==\"function\"?n:null,clazz:t,inFront:!!r,id:i};return r?(this.$frontMarkers[i]=s,this._signal(\"changeFrontMarker\")):(this.$backMarkers[i]=s,this._signal(\"changeBackMarker\")),i},this.addDynamicMarker=function(e,t){if(!e.update)return;var n=this.$markerId++;return e.id=n,e.inFront=!!t,t?(this.$frontMarkers[n]=e,this._signal(\"changeFrontMarker\")):(this.$backMarkers[n]=e,this._signal(\"changeBackMarker\")),e},this.removeMarker=function(e){var t=this.$frontMarkers[e]||this.$backMarkers[e];if(!t)return;var n=t.inFront?this.$frontMarkers:this.$backMarkers;t&&(delete n[e],this._signal(t.inFront?\"changeFrontMarker\":\"changeBackMarker\"))},this.getMarkers=function(e){return e?this.$frontMarkers:this.$backMarkers},this.highlight=function(e){if(!this.$searchHighlight){var t=new p(null,\"ace_selected-word\",\"text\");this.$searchHighlight=this.addDynamicMarker(t)}this.$searchHighlight.setRegexp(e)},this.highlightLines=function(e,t,n,r){typeof t!=\"number\"&&(n=t,t=e),n||(n=\"ace_step\");var i=new l(e,0,t,Infinity);return i.id=this.addMarker(i,n,\"fullLine\",r),i},this.setAnnotations=function(e){this.$annotations=e,this._signal(\"changeAnnotation\",{})},this.getAnnotations=function(){return this.$annotations||[]},this.clearAnnotations=function(){this.setAnnotations([])},this.$detectNewLine=function(e){var t=e.match(/^.*?(\\r?\\n)/m);t?this.$autoNewLine=t[1]:this.$autoNewLine=\"\\n\"},this.getWordRange=function(e,t){var n=this.getLine(e),r=!1;t>0&&(r=!!n.charAt(t-1).match(this.tokenRe)),r||(r=!!n.charAt(t).match(this.tokenRe));if(r)var i=this.tokenRe;else if(/^\\s+$/.test(n.slice(t-1,t+1)))var i=/\\s/;else var i=this.nonTokenRe;var s=t;if(s>0){do s--;while(s>=0&&n.charAt(s).match(i));s++}var o=t;while(o<n.length&&n.charAt(o).match(i))o++;return new l(e,s,e,o)},this.getAWordRange=function(e,t){var n=this.getWordRange(e,t),r=this.getLine(n.end.row);while(r.charAt(n.end.column).match(/[ \\t]/))n.end.column+=1;return n},this.setNewLineMode=function(e){this.doc.setNewLineMode(e)},this.getNewLineMode=function(){return this.doc.getNewLineMode()},this.setUseWorker=function(e){this.setOption(\"useWorker\",e)},this.getUseWorker=function(){return this.$useWorker},this.onReloadTokenizer=function(e){var t=e.data;this.bgTokenizer.start(t.first),this._signal(\"tokenizerUpdate\",e)},this.$modes={},this.$mode=null,this.$modeId=null,this.setMode=function(e,t){if(e&&typeof e==\"object\"){if(e.getTokenizer)return this.$onChangeMode(e);var n=e,r=n.path}else r=e||\"ace/mode/text\";this.$modes[\"ace/mode/text\"]||(this.$modes[\"ace/mode/text\"]=new f);if(this.$modes[r]&&!n){this.$onChangeMode(this.$modes[r]),t&&t();return}this.$modeId=r,o.loadModule([\"mode\",r],function(e){if(this.$modeId!==r)return t&&t();this.$modes[r]&&!n?this.$onChangeMode(this.$modes[r]):e&&e.Mode&&(e=new e.Mode(n),n||(this.$modes[r]=e,e.$id=r),this.$onChangeMode(e)),t&&t()}.bind(this)),this.$mode||this.$onChangeMode(this.$modes[\"ace/mode/text\"],!0)},this.$onChangeMode=function(e,t){t||(this.$modeId=e.$id);if(this.$mode===e)return;this.$mode=e,this.$stopWorker(),this.$useWorker&&this.$startWorker();var n=e.getTokenizer();if(n.addEventListener!==undefined){var r=this.onReloadTokenizer.bind(this);n.addEventListener(\"update\",r)}if(!this.bgTokenizer){this.bgTokenizer=new h(n);var i=this;this.bgTokenizer.addEventListener(\"update\",function(e){i._signal(\"tokenizerUpdate\",e)})}else this.bgTokenizer.setTokenizer(n);this.bgTokenizer.setDocument(this.getDocument()),this.tokenRe=e.tokenRe,this.nonTokenRe=e.nonTokenRe,t||(e.attachToSession&&e.attachToSession(this),this.$options.wrapMethod.set.call(this,this.$wrapMethod),this.$setFolding(e.foldingRules),this.bgTokenizer.start(0),this._emit(\"changeMode\"))},this.$stopWorker=function(){this.$worker&&(this.$worker.terminate(),this.$worker=null)},this.$startWorker=function(){try{this.$worker=this.$mode.createWorker(this)}catch(e){o.warn(\"Could not load worker\",e),this.$worker=null}},this.getMode=function(){return this.$mode},this.$scrollTop=0,this.setScrollTop=function(e){if(this.$scrollTop===e||isNaN(e))return;this.$scrollTop=e,this._signal(\"changeScrollTop\",e)},this.getScrollTop=function(){return this.$scrollTop},this.$scrollLeft=0,this.setScrollLeft=function(e){if(this.$scrollLeft===e||isNaN(e))return;this.$scrollLeft=e,this._signal(\"changeScrollLeft\",e)},this.getScrollLeft=function(){return this.$scrollLeft},this.getScreenWidth=function(){return this.$computeWidth(),this.lineWidgets?Math.max(this.getLineWidgetMaxWidth(),this.screenWidth):this.screenWidth},this.getLineWidgetMaxWidth=function(){if(this.lineWidgetsWidth!=null)return this.lineWidgetsWidth;var e=0;return this.lineWidgets.forEach(function(t){t&&t.screenWidth>e&&(e=t.screenWidth)}),this.lineWidgetWidth=e},this.$computeWidth=function(e){if(this.$modified||e){this.$modified=!1;if(this.$useWrapMode)return this.screenWidth=this.$wrapLimit;var t=this.doc.getAllLines(),n=this.$rowLengthCache,r=0,i=0,s=this.$foldData[i],o=s?s.start.row:Infinity,u=t.length;for(var a=0;a<u;a++){if(a>o){a=s.end.row+1;if(a>=u)break;s=this.$foldData[i++],o=s?s.start.row:Infinity}n[a]==null&&(n[a]=this.$getStringScreenWidth(t[a])[0]),n[a]>r&&(r=n[a])}this.screenWidth=r}},this.getLine=function(e){return this.doc.getLine(e)},this.getLines=function(e,t){return this.doc.getLines(e,t)},this.getLength=function(){return this.doc.getLength()},this.getTextRange=function(e){return this.doc.getTextRange(e||this.selection.getRange())},this.insert=function(e,t){return this.doc.insert(e,t)},this.remove=function(e){return this.doc.remove(e)},this.removeFullLines=function(e,t){return this.doc.removeFullLines(e,t)},this.undoChanges=function(e,t){if(!e.length)return;this.$fromUndo=!0;var n=null;for(var r=e.length-1;r!=-1;r--){var i=e[r];i.group==\"doc\"?(this.doc.revertDeltas(i.deltas),n=this.$getUndoSelection(i.deltas,!0,n)):i.deltas.forEach(function(e){this.addFolds(e.folds)},this)}return this.$fromUndo=!1,n&&this.$undoSelect&&!t&&this.selection.setSelectionRange(n),n},this.redoChanges=function(e,t){if(!e.length)return;this.$fromUndo=!0;var n=null;for(var r=0;r<e.length;r++){var i=e[r];i.group==\"doc\"&&(this.doc.applyDeltas(i.deltas),n=this.$getUndoSelection(i.deltas,!1,n))}return this.$fromUndo=!1,n&&this.$undoSelect&&!t&&this.selection.setSelectionRange(n),n},this.setUndoSelect=function(e){this.$undoSelect=e},this.$getUndoSelection=function(e,t,n){function r(e){return t?e.action!==\"insert\":e.action===\"insert\"}var i=e[0],s,o,u=!1;r(i)?(s=l.fromPoints(i.start,i.end),u=!0):(s=l.fromPoints(i.start,i.start),u=!1);for(var a=1;a<e.length;a++)i=e[a],r(i)?(o=i.start,s.compare(o.row,o.column)==-1&&s.setStart(o),o=i.end,s.compare(o.row,o.column)==1&&s.setEnd(o),u=!0):(o=i.start,s.compare(o.row,o.column)==-1&&(s=l.fromPoints(i.start,i.start)),u=!1);if(n!=null){l.comparePoints(n.start,s.start)===0&&(n.start.column+=s.end.column-s.start.column,n.end.column+=s.end.column-s.start.column);var f=n.compareRange(s);f==1?s.setStart(n.start):f==-1&&s.setEnd(n.end)}return s},this.replace=function(e,t){return this.doc.replace(e,t)},this.moveText=function(e,t,n){var r=this.getTextRange(e),i=this.getFoldsInRange(e),s=l.fromPoints(t,t);if(!n){this.remove(e);var o=e.start.row-e.end.row,u=o?-e.end.column:e.start.column-e.end.column;u&&(s.start.row==e.end.row&&s.start.column>e.end.column&&(s.start.column+=u),s.end.row==e.end.row&&s.end.column>e.end.column&&(s.end.column+=u)),o&&s.start.row>=e.end.row&&(s.start.row+=o,s.end.row+=o)}s.end=this.insert(s.start,r);if(i.length){var a=e.start,f=s.start,o=f.row-a.row,u=f.column-a.column;this.addFolds(i.map(function(e){return e=e.clone(),e.start.row==a.row&&(e.start.column+=u),e.end.row==a.row&&(e.end.column+=u),e.start.row+=o,e.end.row+=o,e}))}return s},this.indentRows=function(e,t,n){n=n.replace(/\\t/g,this.getTabString());for(var r=e;r<=t;r++)this.doc.insertInLine({row:r,column:0},n)},this.outdentRows=function(e){var t=e.collapseRows(),n=new l(0,0,0,0),r=this.getTabSize();for(var i=t.start.row;i<=t.end.row;++i){var s=this.getLine(i);n.start.row=i,n.end.row=i;for(var o=0;o<r;++o)if(s.charAt(o)!=\" \")break;o<r&&s.charAt(o)==\"\t\"?(n.start.column=o,n.end.column=o+1):(n.start.column=0,n.end.column=o),this.remove(n)}},this.$moveLines=function(e,t,n){e=this.getRowFoldStart(e),t=this.getRowFoldEnd(t);if(n<0){var r=this.getRowFoldStart(e+n);if(r<0)return 0;var i=r-e}else if(n>0){var r=this.getRowFoldEnd(t+n);if(r>this.doc.getLength()-1)return 0;var i=r-t}else{e=this.$clipRowToDocument(e),t=this.$clipRowToDocument(t);var i=t-e+1}var s=new l(e,0,t,Number.MAX_VALUE),o=this.getFoldsInRange(s).map(function(e){return e=e.clone(),e.start.row+=i,e.end.row+=i,e}),u=n==0?this.doc.getLines(e,t):this.doc.removeFullLines(e,t);return this.doc.insertFullLines(e+i,u),o.length&&this.addFolds(o),i},this.moveLinesUp=function(e,t){return this.$moveLines(e,t,-1)},this.moveLinesDown=function(e,t){return this.$moveLines(e,t,1)},this.duplicateLines=function(e,t){return this.$moveLines(e,t,0)},this.$clipRowToDocument=function(e){return Math.max(0,Math.min(e,this.doc.getLength()-1))},this.$clipColumnToRow=function(e,t){return t<0?0:Math.min(this.doc.getLine(e).length,t)},this.$clipPositionToDocument=function(e,t){t=Math.max(0,t);if(e<0)e=0,t=0;else{var n=this.doc.getLength();e>=n?(e=n-1,t=this.doc.getLine(n-1).length):t=Math.min(this.doc.getLine(e).length,t)}return{row:e,column:t}},this.$clipRangeToDocument=function(e){e.start.row<0?(e.start.row=0,e.start.column=0):e.start.column=this.$clipColumnToRow(e.start.row,e.start.column);var t=this.doc.getLength()-1;return e.end.row>t?(e.end.row=t,e.end.column=this.doc.getLine(t).length):e.end.column=this.$clipColumnToRow(e.end.row,e.end.column),e},this.$wrapLimit=80,this.$useWrapMode=!1,this.$wrapLimitRange={min:null,max:null},this.setUseWrapMode=function(e){if(e!=this.$useWrapMode){this.$useWrapMode=e,this.$modified=!0,this.$resetRowCache(0);if(e){var t=this.getLength();this.$wrapData=Array(t),this.$updateWrapData(0,t-1)}this._signal(\"changeWrapMode\")}},this.getUseWrapMode=function(){return this.$useWrapMode},this.setWrapLimitRange=function(e,t){if(this.$wrapLimitRange.min!==e||this.$wrapLimitRange.max!==t)this.$wrapLimitRange={min:e,max:t},this.$modified=!0,this.$bidiHandler.markAsDirty(),this.$useWrapMode&&this._signal(\"changeWrapMode\")},this.adjustWrapLimit=function(e,t){var n=this.$wrapLimitRange;n.max<0&&(n={min:t,max:t});var r=this.$constrainWrapLimit(e,n.min,n.max);return r!=this.$wrapLimit&&r>1?(this.$wrapLimit=r,this.$modified=!0,this.$useWrapMode&&(this.$updateWrapData(0,this.getLength()-1),this.$resetRowCache(0),this._signal(\"changeWrapLimit\")),!0):!1},this.$constrainWrapLimit=function(e,t,n){return t&&(e=Math.max(t,e)),n&&(e=Math.min(n,e)),e},this.getWrapLimit=function(){return this.$wrapLimit},this.setWrapLimit=function(e){this.setWrapLimitRange(e,e)},this.getWrapLimitRange=function(){return{min:this.$wrapLimitRange.min,max:this.$wrapLimitRange.max}},this.$updateInternalDataOnChange=function(e){var t=this.$useWrapMode,n=e.action,r=e.start,i=e.end,s=r.row,o=i.row,u=o-s,a=null;this.$updating=!0;if(u!=0)if(n===\"remove\"){this[t?\"$wrapData\":\"$rowLengthCache\"].splice(s,u);var f=this.$foldData;a=this.getFoldsInRange(e),this.removeFolds(a);var l=this.getFoldLine(i.row),c=0;if(l){l.addRemoveChars(i.row,i.column,r.column-i.column),l.shiftRow(-u);var h=this.getFoldLine(s);h&&h!==l&&(h.merge(l),l=h),c=f.indexOf(l)+1}for(c;c<f.length;c++){var l=f[c];l.start.row>=i.row&&l.shiftRow(-u)}o=s}else{var p=Array(u);p.unshift(s,0);var d=t?this.$wrapData:this.$rowLengthCache;d.splice.apply(d,p);var f=this.$foldData,l=this.getFoldLine(s),c=0;if(l){var v=l.range.compareInside(r.row,r.column);v==0?(l=l.split(r.row,r.column),l&&(l.shiftRow(u),l.addRemoveChars(o,0,i.column-r.column))):v==-1&&(l.addRemoveChars(s,0,i.column-r.column),l.shiftRow(u)),c=f.indexOf(l)+1}for(c;c<f.length;c++){var l=f[c];l.start.row>=s&&l.shiftRow(u)}}else{u=Math.abs(e.start.column-e.end.column),n===\"remove\"&&(a=this.getFoldsInRange(e),this.removeFolds(a),u=-u);var l=this.getFoldLine(s);l&&l.addRemoveChars(s,r.column,u)}return t&&this.$wrapData.length!=this.doc.getLength()&&console.error(\"doc.getLength() and $wrapData.length have to be the same!\"),this.$updating=!1,t?this.$updateWrapData(s,o):this.$updateRowLengthCache(s,o),a},this.$updateRowLengthCache=function(e,t,n){this.$rowLengthCache[e]=null,this.$rowLengthCache[t]=null},this.$updateWrapData=function(e,t){var r=this.doc.getAllLines(),i=this.getTabSize(),o=this.$wrapData,u=this.$wrapLimit,a,f,l=e;t=Math.min(t,r.length-1);while(l<=t)f=this.getFoldLine(l,f),f?(a=[],f.walk(function(e,t,i,o){var u;if(e!=null){u=this.$getDisplayTokens(e,a.length),u[0]=n;for(var f=1;f<u.length;f++)u[f]=s}else u=this.$getDisplayTokens(r[t].substring(o,i),a.length);a=a.concat(u)}.bind(this),f.end.row,r[f.end.row].length+1),o[f.start.row]=this.$computeWrapSplits(a,u,i),l=f.end.row+1):(a=this.$getDisplayTokens(r[l]),o[l]=this.$computeWrapSplits(a,u,i),l++)};var e=1,t=2,n=3,s=4,a=9,c=10,d=11,v=12;this.$computeWrapSplits=function(e,r,i){function g(){var t=0;if(m===0)return t;if(p)for(var n=0;n<e.length;n++){var r=e[n];if(r==c)t+=1;else{if(r!=d){if(r==v)continue;break}t+=i}}return h&&p!==!1&&(t+=i),Math.min(t,m)}function y(t){var n=e.slice(f,t),r=n.length;n.join(\"\").replace(/12/g,function(){r-=1}).replace(/2/g,function(){r-=1}),o.length||(b=g(),o.indent=b),l+=r,o.push(l),f=t}if(e.length==0)return[];var o=[],u=e.length,f=0,l=0,h=this.$wrapAsCode,p=this.$indentedSoftWrap,m=r<=Math.max(2*i,8)||p===!1?0:Math.floor(r/2),b=0;while(u-f>r-b){var w=f+r-b;if(e[w-1]>=c&&e[w]>=c){y(w);continue}if(e[w]==n||e[w]==s){for(w;w!=f-1;w--)if(e[w]==n)break;if(w>f){y(w);continue}w=f+r;for(w;w<e.length;w++)if(e[w]!=s)break;if(w==e.length)break;y(w);continue}var E=Math.max(w-(r-(r>>2)),f-1);while(w>E&&e[w]<n)w--;if(h){while(w>E&&e[w]<n)w--;while(w>E&&e[w]==a)w--}else while(w>E&&e[w]<c)w--;if(w>E){y(++w);continue}w=f+r,e[w]==t&&w--,y(w-b)}return o},this.$getDisplayTokens=function(n,r){var i=[],s;r=r||0;for(var o=0;o<n.length;o++){var u=n.charCodeAt(o);if(u==9){s=this.getScreenTabSize(i.length+r),i.push(d);for(var f=1;f<s;f++)i.push(v)}else u==32?i.push(c):u>39&&u<48||u>57&&u<64?i.push(a):u>=4352&&m(u)?i.push(e,t):i.push(e)}return i},this.$getStringScreenWidth=function(e,t,n){if(t==0)return[0,0];t==null&&(t=Infinity),n=n||0;var r,i;for(i=0;i<e.length;i++){r=e.charCodeAt(i),r==9?n+=this.getScreenTabSize(n):r>=4352&&m(r)?n+=2:n+=1;if(n>t)break}return[n,i]},this.lineWidgets=null,this.getRowLength=function(e){if(this.lineWidgets)var t=this.lineWidgets[e]&&this.lineWidgets[e].rowCount||0;else t=0;return!this.$useWrapMode||!this.$wrapData[e]?1+t:this.$wrapData[e].length+1+t},this.getRowLineCount=function(e){return!this.$useWrapMode||!this.$wrapData[e]?1:this.$wrapData[e].length+1},this.getRowWrapIndent=function(e){if(this.$useWrapMode){var t=this.screenToDocumentPosition(e,Number.MAX_VALUE),n=this.$wrapData[t.row];return n.length&&n[0]<t.column?n.indent:0}return 0},this.getScreenLastRowColumn=function(e){var t=this.screenToDocumentPosition(e,Number.MAX_VALUE);return this.documentToScreenColumn(t.row,t.column)},this.getDocumentLastRowColumn=function(e,t){var n=this.documentToScreenRow(e,t);return this.getScreenLastRowColumn(n)},this.getDocumentLastRowColumnPosition=function(e,t){var n=this.documentToScreenRow(e,t);return this.screenToDocumentPosition(n,Number.MAX_VALUE/10)},this.getRowSplitData=function(e){return this.$useWrapMode?this.$wrapData[e]:undefined},this.getScreenTabSize=function(e){return this.$tabSize-e%this.$tabSize},this.screenToDocumentRow=function(e,t){return this.screenToDocumentPosition(e,t).row},this.screenToDocumentColumn=function(e,t){return this.screenToDocumentPosition(e,t).column},this.screenToDocumentPosition=function(e,t,n){if(e<0)return{row:0,column:0};var r,i=0,s=0,o,u=0,a=0,f=this.$screenRowCache,l=this.$getRowCacheIndex(f,e),c=f.length;if(c&&l>=0)var u=f[l],i=this.$docRowCache[l],h=e>f[c-1];else var h=!c;var p=this.getLength()-1,d=this.getNextFoldLine(i),v=d?d.start.row:Infinity;while(u<=e){a=this.getRowLength(i);if(u+a>e||i>=p)break;u+=a,i++,i>v&&(i=d.end.row+1,d=this.getNextFoldLine(i,d),v=d?d.start.row:Infinity),h&&(this.$docRowCache.push(i),this.$screenRowCache.push(u))}if(d&&d.start.row<=i)r=this.getFoldDisplayLine(d),i=d.start.row;else{if(u+a<=e||i>p)return{row:p,column:this.getLine(p).length};r=this.getLine(i),d=null}var m=0,g=Math.floor(e-u);if(this.$useWrapMode){var y=this.$wrapData[i];y&&(o=y[g],g>0&&y.length&&(m=y.indent,s=y[g-1]||y[y.length-1],r=r.substring(s)))}return n!==undefined&&this.$bidiHandler.isBidiRow(u+g,i,g)&&(t=this.$bidiHandler.offsetToCol(n)),s+=this.$getStringScreenWidth(r,t-m)[1],this.$useWrapMode&&s>=o&&(s=o-1),d?d.idxToPosition(s):{row:i,column:s}},this.documentToScreenPosition=function(e,t){if(typeof t==\"undefined\")var n=this.$clipPositionToDocument(e.row,e.column);else n=this.$clipPositionToDocument(e,t);e=n.row,t=n.column;var r=0,i=null,s=null;s=this.getFoldAt(e,t,1),s&&(e=s.start.row,t=s.start.column);var o,u=0,a=this.$docRowCache,f=this.$getRowCacheIndex(a,e),l=a.length;if(l&&f>=0)var u=a[f],r=this.$screenRowCache[f],c=e>a[l-1];else var c=!l;var h=this.getNextFoldLine(u),p=h?h.start.row:Infinity;while(u<e){if(u>=p){o=h.end.row+1;if(o>e)break;h=this.getNextFoldLine(o,h),p=h?h.start.row:Infinity}else o=u+1;r+=this.getRowLength(u),u=o,c&&(this.$docRowCache.push(u),this.$screenRowCache.push(r))}var d=\"\";h&&u>=p?(d=this.getFoldDisplayLine(h,e,t),i=h.start.row):(d=this.getLine(e).substring(0,t),i=e);var v=0;if(this.$useWrapMode){var m=this.$wrapData[i];if(m){var g=0;while(d.length>=m[g])r++,g++;d=d.substring(m[g-1]||0,d.length),v=g>0?m.indent:0}}return{row:r,column:v+this.$getStringScreenWidth(d)[0]}},this.documentToScreenColumn=function(e,t){return this.documentToScreenPosition(e,t).column},this.documentToScreenRow=function(e,t){return this.documentToScreenPosition(e,t).row},this.getScreenLength=function(){var e=0,t=null;if(!this.$useWrapMode){e=this.getLength();var n=this.$foldData;for(var r=0;r<n.length;r++)t=n[r],e-=t.end.row-t.start.row}else{var i=this.$wrapData.length,s=0,r=0,t=this.$foldData[r++],o=t?t.start.row:Infinity;while(s<i){var u=this.$wrapData[s];e+=u?u.length+1:1,s++,s>o&&(s=t.end.row+1,t=this.$foldData[r++],o=t?t.start.row:Infinity)}}return this.lineWidgets&&(e+=this.$getWidgetScreenLength()),e},this.$setFontMetrics=function(e){if(!this.$enableVarChar)return;this.$getStringScreenWidth=function(t,n,r){if(n===0)return[0,0];n||(n=Infinity),r=r||0;var i,s;for(s=0;s<t.length;s++){i=t.charAt(s),i===\"\t\"?r+=this.getScreenTabSize(r):r+=e.getCharacterWidth(i);if(r>n)break}return[r,s]}},this.destroy=function(){this.bgTokenizer&&(this.bgTokenizer.setDocument(null),this.bgTokenizer=null),this.$stopWorker()},this.isFullWidth=m}.call(d.prototype),e(\"./edit_session/folding\").Folding.call(d.prototype),e(\"./edit_session/bracket_match\").BracketMatch.call(d.prototype),o.defineOptions(d.prototype,\"session\",{wrap:{set:function(e){!e||e==\"off\"?e=!1:e==\"free\"?e=!0:e==\"printMargin\"?e=-1:typeof e==\"string\"&&(e=parseInt(e,10)||!1);if(this.$wrap==e)return;this.$wrap=e;if(!e)this.setUseWrapMode(!1);else{var t=typeof e==\"number\"?e:null;this.setWrapLimitRange(t,t),this.setUseWrapMode(!0)}},get:function(){return this.getUseWrapMode()?this.$wrap==-1?\"printMargin\":this.getWrapLimitRange().min?this.$wrap:\"free\":\"off\"},handlesSet:!0},wrapMethod:{set:function(e){e=e==\"auto\"?this.$mode.type!=\"text\":e!=\"text\",e!=this.$wrapAsCode&&(this.$wrapAsCode=e,this.$useWrapMode&&(this.$modified=!0,this.$resetRowCache(0),this.$updateWrapData(0,this.getLength()-1)))},initialValue:\"auto\"},indentedSoftWrap:{initialValue:!0},firstLineNumber:{set:function(){this._signal(\"changeBreakpoint\")},initialValue:1},useWorker:{set:function(e){this.$useWorker=e,this.$stopWorker(),e&&this.$startWorker()},initialValue:!0},useSoftTabs:{initialValue:!0},tabSize:{set:function(e){if(isNaN(e)||this.$tabSize===e)return;this.$modified=!0,this.$rowLengthCache=[],this.$tabSize=e,this._signal(\"changeTabSize\")},initialValue:4,handlesSet:!0},navigateWithinSoftTabs:{initialValue:!1},overwrite:{set:function(e){this._signal(\"changeOverwrite\")},initialValue:!1},newLineMode:{set:function(e){this.doc.setNewLineMode(e)},get:function(){return this.doc.getNewLineMode()},handlesSet:!0},mode:{set:function(e){this.setMode(e)},get:function(){return this.$modeId}}}),t.EditSession=d}),define(\"ace/search\",[\"require\",\"exports\",\"module\",\"ace/lib/lang\",\"ace/lib/oop\",\"ace/range\"],function(e,t,n){\"use strict\";function u(e,t){function n(e){return/\\w/.test(e)||t.regExp?\"\\\\b\":\"\"}return n(e[0])+e+n(e[e.length-1])}var r=e(\"./lib/lang\"),i=e(\"./lib/oop\"),s=e(\"./range\").Range,o=function(){this.$options={}};(function(){this.set=function(e){return i.mixin(this.$options,e),this},this.getOptions=function(){return r.copyObject(this.$options)},this.setOptions=function(e){this.$options=e},this.find=function(e){var t=this.$options,n=this.$matchIterator(e,t);if(!n)return!1;var r=null;return n.forEach(function(e,n,i,o){return r=new s(e,n,i,o),n==o&&t.start&&t.start.start&&t.skipCurrent!=0&&r.isEqual(t.start)?(r=null,!1):!0}),r},this.findAll=function(e){var t=this.$options;if(!t.needle)return[];this.$assembleRegExp(t);var n=t.range,i=n?e.getLines(n.start.row,n.end.row):e.doc.getAllLines(),o=[],u=t.re;if(t.$isMultiLine){var a=u.length,f=i.length-a,l;e:for(var c=u.offset||0;c<=f;c++){for(var h=0;h<a;h++)if(i[c+h].search(u[h])==-1)continue e;var p=i[c],d=i[c+a-1],v=p.length-p.match(u[0])[0].length,m=d.match(u[a-1])[0].length;if(l&&l.end.row===c&&l.end.column>v)continue;o.push(l=new s(c,v,c+a-1,m)),a>2&&(c=c+a-2)}}else for(var g=0;g<i.length;g++){var y=r.getMatchOffsets(i[g],u);for(var h=0;h<y.length;h++){var b=y[h];o.push(new s(g,b.offset,g,b.offset+b.length))}}if(n){var w=n.start.column,E=n.start.column,g=0,h=o.length-1;while(g<h&&o[g].start.column<w&&o[g].start.row==n.start.row)g++;while(g<h&&o[h].end.column>E&&o[h].end.row==n.end.row)h--;o=o.slice(g,h+1);for(g=0,h=o.length;g<h;g++)o[g].start.row+=n.start.row,o[g].end.row+=n.start.row}return o},this.replace=function(e,t){var n=this.$options,r=this.$assembleRegExp(n);if(n.$isMultiLine)return t;if(!r)return;var i=r.exec(e);if(!i||i[0].length!=e.length)return null;t=e.replace(r,t);if(n.preserveCase){t=t.split(\"\");for(var s=Math.min(e.length,e.length);s--;){var o=e[s];o&&o.toLowerCase()!=o?t[s]=t[s].toUpperCase():t[s]=t[s].toLowerCase()}t=t.join(\"\")}return t},this.$assembleRegExp=function(e,t){if(e.needle instanceof RegExp)return e.re=e.needle;var n=e.needle;if(!e.needle)return e.re=!1;e.regExp||(n=r.escapeRegExp(n)),e.wholeWord&&(n=u(n,e));var i=e.caseSensitive?\"gm\":\"gmi\";e.$isMultiLine=!t&&/[\\n\\r]/.test(n);if(e.$isMultiLine)return e.re=this.$assembleMultilineRegExp(n,i);try{var s=new RegExp(n,i)}catch(o){s=!1}return e.re=s},this.$assembleMultilineRegExp=function(e,t){var n=e.replace(/\\r\\n|\\r|\\n/g,\"$\\n^\").split(\"\\n\"),r=[];for(var i=0;i<n.length;i++)try{r.push(new RegExp(n[i],t))}catch(s){return!1}return r},this.$matchIterator=function(e,t){var n=this.$assembleRegExp(t);if(!n)return!1;var r=t.backwards==1,i=t.skipCurrent!=0,s=t.range,o=t.start;o||(o=s?s[r?\"end\":\"start\"]:e.selection.getRange()),o.start&&(o=o[i!=r?\"end\":\"start\"]);var u=s?s.start.row:0,a=s?s.end.row:e.getLength()-1;if(r)var f=function(e){var n=o.row;if(c(n,o.column,e))return;for(n--;n>=u;n--)if(c(n,Number.MAX_VALUE,e))return;if(t.wrap==0)return;for(n=a,u=o.row;n>=u;n--)if(c(n,Number.MAX_VALUE,e))return};else var f=function(e){var n=o.row;if(c(n,o.column,e))return;for(n+=1;n<=a;n++)if(c(n,0,e))return;if(t.wrap==0)return;for(n=u,a=o.row;n<=a;n++)if(c(n,0,e))return};if(t.$isMultiLine)var l=n.length,c=function(t,i,s){var o=r?t-l+1:t;if(o<0)return;var u=e.getLine(o),a=u.search(n[0]);if(!r&&a<i||a===-1)return;for(var f=1;f<l;f++){u=e.getLine(o+f);if(u.search(n[f])==-1)return}var c=u.match(n[l-1])[0].length;if(r&&c>i)return;if(s(o,a,o+l-1,c))return!0};else if(r)var c=function(t,r,i){var s=e.getLine(t),o=[],u,a=0;n.lastIndex=0;while(u=n.exec(s)){var f=u[0].length;a=u.index;if(!f){if(a>=s.length)break;n.lastIndex=a+=1}if(u.index+f>r)break;o.push(u.index,f)}for(var l=o.length-1;l>=0;l-=2){var c=o[l-1],f=o[l];if(i(t,c,t,c+f))return!0}};else var c=function(t,r,i){var s=e.getLine(t),o,u=r;n.lastIndex=r;while(o=n.exec(s)){var a=o[0].length;u=o.index;if(i(t,u,t,u+a))return!0;if(!a){n.lastIndex=u+=1;if(u>=s.length)return!1}}};return{forEach:f}}}).call(o.prototype),t.Search=o}),define(\"ace/keyboard/hash_handler\",[\"require\",\"exports\",\"module\",\"ace/lib/keys\",\"ace/lib/useragent\"],function(e,t,n){\"use strict\";function o(e,t){this.platform=t||(i.isMac?\"mac\":\"win\"),this.commands={},this.commandKeyBinding={},this.addCommands(e),this.$singleCommand=!0}function u(e,t){o.call(this,e,t),this.$singleCommand=!1}var r=e(\"../lib/keys\"),i=e(\"../lib/useragent\"),s=r.KEY_MODS;u.prototype=o.prototype,function(){function e(e){return typeof e==\"object\"&&e.bindKey&&e.bindKey.position||(e.isDefault?-100:0)}this.addCommand=function(e){this.commands[e.name]&&this.removeCommand(e),this.commands[e.name]=e,e.bindKey&&this._buildKeyHash(e)},this.removeCommand=function(e,t){var n=e&&(typeof e==\"string\"?e:e.name);e=this.commands[n],t||delete this.commands[n];var r=this.commandKeyBinding;for(var i in r){var s=r[i];if(s==e)delete r[i];else if(Array.isArray(s)){var o=s.indexOf(e);o!=-1&&(s.splice(o,1),s.length==1&&(r[i]=s[0]))}}},this.bindKey=function(e,t,n){typeof e==\"object\"&&e&&(n==undefined&&(n=e.position),e=e[this.platform]);if(!e)return;if(typeof t==\"function\")return this.addCommand({exec:t,bindKey:e,name:t.name||e});e.split(\"|\").forEach(function(e){var r=\"\";if(e.indexOf(\" \")!=-1){var i=e.split(/\\s+/);e=i.pop(),i.forEach(function(e){var t=this.parseKeys(e),n=s[t.hashId]+t.key;r+=(r?\" \":\"\")+n,this._addCommandToBinding(r,\"chainKeys\")},this),r+=\" \"}var o=this.parseKeys(e),u=s[o.hashId]+o.key;this._addCommandToBinding(r+u,t,n)},this)},this._addCommandToBinding=function(t,n,r){var i=this.commandKeyBinding,s;if(!n)delete i[t];else if(!i[t]||this.$singleCommand)i[t]=n;else{Array.isArray(i[t])?(s=i[t].indexOf(n))!=-1&&i[t].splice(s,1):i[t]=[i[t]],typeof r!=\"number\"&&(r=e(n));var o=i[t];for(s=0;s<o.length;s++){var u=o[s],a=e(u);if(a>r)break}o.splice(s,0,n)}},this.addCommands=function(e){e&&Object.keys(e).forEach(function(t){var n=e[t];if(!n)return;if(typeof n==\"string\")return this.bindKey(n,t);typeof n==\"function\"&&(n={exec:n});if(typeof n!=\"object\")return;n.name||(n.name=t),this.addCommand(n)},this)},this.removeCommands=function(e){Object.keys(e).forEach(function(t){this.removeCommand(e[t])},this)},this.bindKeys=function(e){Object.keys(e).forEach(function(t){this.bindKey(t,e[t])},this)},this._buildKeyHash=function(e){this.bindKey(e.bindKey,e)},this.parseKeys=function(e){var t=e.toLowerCase().split(/[\\-\\+]([\\-\\+])?/).filter(function(e){return e}),n=t.pop(),i=r[n];if(r.FUNCTION_KEYS[i])n=r.FUNCTION_KEYS[i].toLowerCase();else{if(!t.length)return{key:n,hashId:-1};if(t.length==1&&t[0]==\"shift\")return{key:n.toUpperCase(),hashId:-1}}var s=0;for(var o=t.length;o--;){var u=r.KEY_MODS[t[o]];if(u==null)return typeof console!=\"undefined\"&&console.error(\"invalid modifier \"+t[o]+\" in \"+e),!1;s|=u}return{key:n,hashId:s}},this.findKeyCommand=function(t,n){var r=s[t]+n;return this.commandKeyBinding[r]},this.handleKeyboard=function(e,t,n,r){if(r<0)return;var i=s[t]+n,o=this.commandKeyBinding[i];e.$keyChain&&(e.$keyChain+=\" \"+i,o=this.commandKeyBinding[e.$keyChain]||o);if(o)if(o==\"chainKeys\"||o[o.length-1]==\"chainKeys\")return e.$keyChain=e.$keyChain||i,{command:\"null\"};if(e.$keyChain)if(!!t&&t!=4||n.length!=1){if(t==-1||r>0)e.$keyChain=\"\"}else e.$keyChain=e.$keyChain.slice(0,-i.length-1);return{command:o}},this.getStatusText=function(e,t){return t.$keyChain||\"\"}}.call(o.prototype),t.HashHandler=o,t.MultiHashHandler=u}),define(\"ace/commands/command_manager\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/keyboard/hash_handler\",\"ace/lib/event_emitter\"],function(e,t,n){\"use strict\";var r=e(\"../lib/oop\"),i=e(\"../keyboard/hash_handler\").MultiHashHandler,s=e(\"../lib/event_emitter\").EventEmitter,o=function(e,t){i.call(this,t,e),this.byName=this.commands,this.setDefaultHandler(\"exec\",function(e){return e.command.exec(e.editor,e.args||{})})};r.inherits(o,i),function(){r.implement(this,s),this.exec=function(e,t,n){if(Array.isArray(e)){for(var r=e.length;r--;)if(this.exec(e[r],t,n))return!0;return!1}typeof e==\"string\"&&(e=this.commands[e]);if(!e)return!1;if(t&&t.$readOnly&&!e.readOnly)return!1;if(e.isAvailable&&!e.isAvailable(t))return!1;var i={editor:t,command:e,args:n};return i.returnValue=this._emit(\"exec\",i),this._signal(\"afterExec\",i),i.returnValue===!1?!1:!0},this.toggleRecording=function(e){if(this.$inReplay)return;return e&&e._emit(\"changeStatus\"),this.recording?(this.macro.pop(),this.removeEventListener(\"exec\",this.$addCommandToMacro),this.macro.length||(this.macro=this.oldMacro),this.recording=!1):(this.$addCommandToMacro||(this.$addCommandToMacro=function(e){this.macro.push([e.command,e.args])}.bind(this)),this.oldMacro=this.macro,this.macro=[],this.on(\"exec\",this.$addCommandToMacro),this.recording=!0)},this.replay=function(e){if(this.$inReplay||!this.macro)return;if(this.recording)return this.toggleRecording(e);try{this.$inReplay=!0,this.macro.forEach(function(t){typeof t==\"string\"?this.exec(t,e):this.exec(t[0],e,t[1])},this)}finally{this.$inReplay=!1}},this.trimMacro=function(e){return e.map(function(e){return typeof e[0]!=\"string\"&&(e[0]=e[0].name),e[1]||(e=e[0]),e})}}.call(o.prototype),t.CommandManager=o}),define(\"ace/commands/default_commands\",[\"require\",\"exports\",\"module\",\"ace/lib/lang\",\"ace/config\",\"ace/range\"],function(e,t,n){\"use strict\";function o(e,t){return{win:e,mac:t}}var r=e(\"../lib/lang\"),i=e(\"../config\"),s=e(\"../range\").Range;t.commands=[{name:\"showSettingsMenu\",bindKey:o(\"Ctrl-,\",\"Command-,\"),exec:function(e){i.loadModule(\"ace/ext/settings_menu\",function(t){t.init(e),e.showSettingsMenu()})},readOnly:!0},{name:\"goToNextError\",bindKey:o(\"Alt-E\",\"F4\"),exec:function(e){i.loadModule(\"ace/ext/error_marker\",function(t){t.showErrorMarker(e,1)})},scrollIntoView:\"animate\",readOnly:!0},{name:\"goToPreviousError\",bindKey:o(\"Alt-Shift-E\",\"Shift-F4\"),exec:function(e){i.loadModule(\"ace/ext/error_marker\",function(t){t.showErrorMarker(e,-1)})},scrollIntoView:\"animate\",readOnly:!0},{name:\"selectall\",bindKey:o(\"Ctrl-A\",\"Command-A\"),exec:function(e){e.selectAll()},readOnly:!0},{name:\"centerselection\",bindKey:o(null,\"Ctrl-L\"),exec:function(e){e.centerSelection()},readOnly:!0},{name:\"gotoline\",bindKey:o(\"Ctrl-L\",\"Command-L\"),exec:function(e){var t=parseInt(prompt(\"Enter line number:\"),10);isNaN(t)||e.gotoLine(t)},readOnly:!0},{name:\"fold\",bindKey:o(\"Alt-L|Ctrl-F1\",\"Command-Alt-L|Command-F1\"),exec:function(e){e.session.toggleFold(!1)},multiSelectAction:\"forEach\",scrollIntoView:\"center\",readOnly:!0},{name:\"unfold\",bindKey:o(\"Alt-Shift-L|Ctrl-Shift-F1\",\"Command-Alt-Shift-L|Command-Shift-F1\"),exec:function(e){e.session.toggleFold(!0)},multiSelectAction:\"forEach\",scrollIntoView:\"center\",readOnly:!0},{name:\"toggleFoldWidget\",bindKey:o(\"F2\",\"F2\"),exec:function(e){e.session.toggleFoldWidget()},multiSelectAction:\"forEach\",scrollIntoView:\"center\",readOnly:!0},{name:\"toggleParentFoldWidget\",bindKey:o(\"Alt-F2\",\"Alt-F2\"),exec:function(e){e.session.toggleFoldWidget(!0)},multiSelectAction:\"forEach\",scrollIntoView:\"center\",readOnly:!0},{name:\"foldall\",bindKey:o(null,\"Ctrl-Command-Option-0\"),exec:function(e){e.session.foldAll()},scrollIntoView:\"center\",readOnly:!0},{name:\"foldOther\",bindKey:o(\"Alt-0\",\"Command-Option-0\"),exec:function(e){e.session.foldAll(),e.session.unfold(e.selection.getAllRanges())},scrollIntoView:\"center\",readOnly:!0},{name:\"unfoldall\",bindKey:o(\"Alt-Shift-0\",\"Command-Option-Shift-0\"),exec:function(e){e.session.unfold()},scrollIntoView:\"center\",readOnly:!0},{name:\"findnext\",bindKey:o(\"Ctrl-K\",\"Command-G\"),exec:function(e){e.findNext()},multiSelectAction:\"forEach\",scrollIntoView:\"center\",readOnly:!0},{name:\"findprevious\",bindKey:o(\"Ctrl-Shift-K\",\"Command-Shift-G\"),exec:function(e){e.findPrevious()},multiSelectAction:\"forEach\",scrollIntoView:\"center\",readOnly:!0},{name:\"selectOrFindNext\",bindKey:o(\"Alt-K\",\"Ctrl-G\"),exec:function(e){e.selection.isEmpty()?e.selection.selectWord():e.findNext()},readOnly:!0},{name:\"selectOrFindPrevious\",bindKey:o(\"Alt-Shift-K\",\"Ctrl-Shift-G\"),exec:function(e){e.selection.isEmpty()?e.selection.selectWord():e.findPrevious()},readOnly:!0},{name:\"find\",bindKey:o(\"Ctrl-F\",\"Command-F\"),exec:function(e){i.loadModule(\"ace/ext/searchbox\",function(t){t.Search(e)})},readOnly:!0},{name:\"overwrite\",bindKey:\"Insert\",exec:function(e){e.toggleOverwrite()},readOnly:!0},{name:\"selecttostart\",bindKey:o(\"Ctrl-Shift-Home\",\"Command-Shift-Home|Command-Shift-Up\"),exec:function(e){e.getSelection().selectFileStart()},multiSelectAction:\"forEach\",readOnly:!0,scrollIntoView:\"animate\",aceCommandGroup:\"fileJump\"},{name:\"gotostart\",bindKey:o(\"Ctrl-Home\",\"Command-Home|Command-Up\"),exec:function(e){e.navigateFileStart()},multiSelectAction:\"forEach\",readOnly:!0,scrollIntoView:\"animate\",aceCommandGroup:\"fileJump\"},{name:\"selectup\",bindKey:o(\"Shift-Up\",\"Shift-Up|Ctrl-Shift-P\"),exec:function(e){e.getSelection().selectUp()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"golineup\",bindKey:o(\"Up\",\"Up|Ctrl-P\"),exec:function(e,t){e.navigateUp(t.times)},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"selecttoend\",bindKey:o(\"Ctrl-Shift-End\",\"Command-Shift-End|Command-Shift-Down\"),exec:function(e){e.getSelection().selectFileEnd()},multiSelectAction:\"forEach\",readOnly:!0,scrollIntoView:\"animate\",aceCommandGroup:\"fileJump\"},{name:\"gotoend\",bindKey:o(\"Ctrl-End\",\"Command-End|Command-Down\"),exec:function(e){e.navigateFileEnd()},multiSelectAction:\"forEach\",readOnly:!0,scrollIntoView:\"animate\",aceCommandGroup:\"fileJump\"},{name:\"selectdown\",bindKey:o(\"Shift-Down\",\"Shift-Down|Ctrl-Shift-N\"),exec:function(e){e.getSelection().selectDown()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"golinedown\",bindKey:o(\"Down\",\"Down|Ctrl-N\"),exec:function(e,t){e.navigateDown(t.times)},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"selectwordleft\",bindKey:o(\"Ctrl-Shift-Left\",\"Option-Shift-Left\"),exec:function(e){e.getSelection().selectWordLeft()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"gotowordleft\",bindKey:o(\"Ctrl-Left\",\"Option-Left\"),exec:function(e){e.navigateWordLeft()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"selecttolinestart\",bindKey:o(\"Alt-Shift-Left\",\"Command-Shift-Left|Ctrl-Shift-A\"),exec:function(e){e.getSelection().selectLineStart()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"gotolinestart\",bindKey:o(\"Alt-Left|Home\",\"Command-Left|Home|Ctrl-A\"),exec:function(e){e.navigateLineStart()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"selectleft\",bindKey:o(\"Shift-Left\",\"Shift-Left|Ctrl-Shift-B\"),exec:function(e){e.getSelection().selectLeft()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"gotoleft\",bindKey:o(\"Left\",\"Left|Ctrl-B\"),exec:function(e,t){e.navigateLeft(t.times)},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"selectwordright\",bindKey:o(\"Ctrl-Shift-Right\",\"Option-Shift-Right\"),exec:function(e){e.getSelection().selectWordRight()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"gotowordright\",bindKey:o(\"Ctrl-Right\",\"Option-Right\"),exec:function(e){e.navigateWordRight()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"selecttolineend\",bindKey:o(\"Alt-Shift-Right\",\"Command-Shift-Right|Shift-End|Ctrl-Shift-E\"),exec:function(e){e.getSelection().selectLineEnd()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"gotolineend\",bindKey:o(\"Alt-Right|End\",\"Command-Right|End|Ctrl-E\"),exec:function(e){e.navigateLineEnd()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"selectright\",bindKey:o(\"Shift-Right\",\"Shift-Right\"),exec:function(e){e.getSelection().selectRight()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"gotoright\",bindKey:o(\"Right\",\"Right|Ctrl-F\"),exec:function(e,t){e.navigateRight(t.times)},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"selectpagedown\",bindKey:\"Shift-PageDown\",exec:function(e){e.selectPageDown()},readOnly:!0},{name:\"pagedown\",bindKey:o(null,\"Option-PageDown\"),exec:function(e){e.scrollPageDown()},readOnly:!0},{name:\"gotopagedown\",bindKey:o(\"PageDown\",\"PageDown|Ctrl-V\"),exec:function(e){e.gotoPageDown()},readOnly:!0},{name:\"selectpageup\",bindKey:\"Shift-PageUp\",exec:function(e){e.selectPageUp()},readOnly:!0},{name:\"pageup\",bindKey:o(null,\"Option-PageUp\"),exec:function(e){e.scrollPageUp()},readOnly:!0},{name:\"gotopageup\",bindKey:\"PageUp\",exec:function(e){e.gotoPageUp()},readOnly:!0},{name:\"scrollup\",bindKey:o(\"Ctrl-Up\",null),exec:function(e){e.renderer.scrollBy(0,-2*e.renderer.layerConfig.lineHeight)},readOnly:!0},{name:\"scrolldown\",bindKey:o(\"Ctrl-Down\",null),exec:function(e){e.renderer.scrollBy(0,2*e.renderer.layerConfig.lineHeight)},readOnly:!0},{name:\"selectlinestart\",bindKey:\"Shift-Home\",exec:function(e){e.getSelection().selectLineStart()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"selectlineend\",bindKey:\"Shift-End\",exec:function(e){e.getSelection().selectLineEnd()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"togglerecording\",bindKey:o(\"Ctrl-Alt-E\",\"Command-Option-E\"),exec:function(e){e.commands.toggleRecording(e)},readOnly:!0},{name:\"replaymacro\",bindKey:o(\"Ctrl-Shift-E\",\"Command-Shift-E\"),exec:function(e){e.commands.replay(e)},readOnly:!0},{name:\"jumptomatching\",bindKey:o(\"Ctrl-P\",\"Ctrl-P\"),exec:function(e){e.jumpToMatching()},multiSelectAction:\"forEach\",scrollIntoView:\"animate\",readOnly:!0},{name:\"selecttomatching\",bindKey:o(\"Ctrl-Shift-P\",\"Ctrl-Shift-P\"),exec:function(e){e.jumpToMatching(!0)},multiSelectAction:\"forEach\",scrollIntoView:\"animate\",readOnly:!0},{name:\"expandToMatching\",bindKey:o(\"Ctrl-Shift-M\",\"Ctrl-Shift-M\"),exec:function(e){e.jumpToMatching(!0,!0)},multiSelectAction:\"forEach\",scrollIntoView:\"animate\",readOnly:!0},{name:\"passKeysToBrowser\",bindKey:o(null,null),exec:function(){},passEvent:!0,readOnly:!0},{name:\"copy\",exec:function(e){},readOnly:!0},{name:\"cut\",exec:function(e){var t=e.getSelectionRange();e._emit(\"cut\",t),e.selection.isEmpty()||(e.session.remove(t),e.clearSelection())},scrollIntoView:\"cursor\",multiSelectAction:\"forEach\"},{name:\"paste\",exec:function(e,t){e.$handlePaste(t)},scrollIntoView:\"cursor\"},{name:\"removeline\",bindKey:o(\"Ctrl-D\",\"Command-D\"),exec:function(e){e.removeLines()},scrollIntoView:\"cursor\",multiSelectAction:\"forEachLine\"},{name:\"duplicateSelection\",bindKey:o(\"Ctrl-Shift-D\",\"Command-Shift-D\"),exec:function(e){e.duplicateSelection()},scrollIntoView:\"cursor\",multiSelectAction:\"forEach\"},{name:\"sortlines\",bindKey:o(\"Ctrl-Alt-S\",\"Command-Alt-S\"),exec:function(e){e.sortLines()},scrollIntoView:\"selection\",multiSelectAction:\"forEachLine\"},{name:\"togglecomment\",bindKey:o(\"Ctrl-/\",\"Command-/\"),exec:function(e){e.toggleCommentLines()},multiSelectAction:\"forEachLine\",scrollIntoView:\"selectionPart\"},{name:\"toggleBlockComment\",bindKey:o(\"Ctrl-Shift-/\",\"Command-Shift-/\"),exec:function(e){e.toggleBlockComment()},multiSelectAction:\"forEach\",scrollIntoView:\"selectionPart\"},{name:\"modifyNumberUp\",bindKey:o(\"Ctrl-Shift-Up\",\"Alt-Shift-Up\"),exec:function(e){e.modifyNumber(1)},scrollIntoView:\"cursor\",multiSelectAction:\"forEach\"},{name:\"modifyNumberDown\",bindKey:o(\"Ctrl-Shift-Down\",\"Alt-Shift-Down\"),exec:function(e){e.modifyNumber(-1)},scrollIntoView:\"cursor\",multiSelectAction:\"forEach\"},{name:\"replace\",bindKey:o(\"Ctrl-H\",\"Command-Option-F\"),exec:function(e){i.loadModule(\"ace/ext/searchbox\",function(t){t.Search(e,!0)})}},{name:\"undo\",bindKey:o(\"Ctrl-Z\",\"Command-Z\"),exec:function(e){e.undo()}},{name:\"redo\",bindKey:o(\"Ctrl-Shift-Z|Ctrl-Y\",\"Command-Shift-Z|Command-Y\"),exec:function(e){e.redo()}},{name:\"copylinesup\",bindKey:o(\"Alt-Shift-Up\",\"Command-Option-Up\"),exec:function(e){e.copyLinesUp()},scrollIntoView:\"cursor\"},{name:\"movelinesup\",bindKey:o(\"Alt-Up\",\"Option-Up\"),exec:function(e){e.moveLinesUp()},scrollIntoView:\"cursor\"},{name:\"copylinesdown\",bindKey:o(\"Alt-Shift-Down\",\"Command-Option-Down\"),exec:function(e){e.copyLinesDown()},scrollIntoView:\"cursor\"},{name:\"movelinesdown\",bindKey:o(\"Alt-Down\",\"Option-Down\"),exec:function(e){e.moveLinesDown()},scrollIntoView:\"cursor\"},{name:\"del\",bindKey:o(\"Delete\",\"Delete|Ctrl-D|Shift-Delete\"),exec:function(e){e.remove(\"right\")},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"backspace\",bindKey:o(\"Shift-Backspace|Backspace\",\"Ctrl-Backspace|Shift-Backspace|Backspace|Ctrl-H\"),exec:function(e){e.remove(\"left\")},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"cut_or_delete\",bindKey:o(\"Shift-Delete\",null),exec:function(e){if(!e.selection.isEmpty())return!1;e.remove(\"left\")},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"removetolinestart\",bindKey:o(\"Alt-Backspace\",\"Command-Backspace\"),exec:function(e){e.removeToLineStart()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"removetolineend\",bindKey:o(\"Alt-Delete\",\"Ctrl-K|Command-Delete\"),exec:function(e){e.removeToLineEnd()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"removetolinestarthard\",bindKey:o(\"Ctrl-Shift-Backspace\",null),exec:function(e){var t=e.selection.getRange();t.start.column=0,e.session.remove(t)},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"removetolineendhard\",bindKey:o(\"Ctrl-Shift-Delete\",null),exec:function(e){var t=e.selection.getRange();t.end.column=Number.MAX_VALUE,e.session.remove(t)},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"removewordleft\",bindKey:o(\"Ctrl-Backspace\",\"Alt-Backspace|Ctrl-Alt-Backspace\"),exec:function(e){e.removeWordLeft()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"removewordright\",bindKey:o(\"Ctrl-Delete\",\"Alt-Delete\"),exec:function(e){e.removeWordRight()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"outdent\",bindKey:o(\"Shift-Tab\",\"Shift-Tab\"),exec:function(e){e.blockOutdent()},multiSelectAction:\"forEach\",scrollIntoView:\"selectionPart\"},{name:\"indent\",bindKey:o(\"Tab\",\"Tab\"),exec:function(e){e.indent()},multiSelectAction:\"forEach\",scrollIntoView:\"selectionPart\"},{name:\"blockoutdent\",bindKey:o(\"Ctrl-[\",\"Ctrl-[\"),exec:function(e){e.blockOutdent()},multiSelectAction:\"forEachLine\",scrollIntoView:\"selectionPart\"},{name:\"blockindent\",bindKey:o(\"Ctrl-]\",\"Ctrl-]\"),exec:function(e){e.blockIndent()},multiSelectAction:\"forEachLine\",scrollIntoView:\"selectionPart\"},{name:\"insertstring\",exec:function(e,t){e.insert(t)},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"inserttext\",exec:function(e,t){e.insert(r.stringRepeat(t.text||\"\",t.times||1))},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"splitline\",bindKey:o(null,\"Ctrl-O\"),exec:function(e){e.splitLine()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"transposeletters\",bindKey:o(\"Alt-Shift-X\",\"Ctrl-T\"),exec:function(e){e.transposeLetters()},multiSelectAction:function(e){e.transposeSelections(1)},scrollIntoView:\"cursor\"},{name:\"touppercase\",bindKey:o(\"Ctrl-U\",\"Ctrl-U\"),exec:function(e){e.toUpperCase()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"tolowercase\",bindKey:o(\"Ctrl-Shift-U\",\"Ctrl-Shift-U\"),exec:function(e){e.toLowerCase()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"expandtoline\",bindKey:o(\"Ctrl-Shift-L\",\"Command-Shift-L\"),exec:function(e){var t=e.selection.getRange();t.start.column=t.end.column=0,t.end.row++,e.selection.setRange(t,!1)},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"joinlines\",bindKey:o(null,null),exec:function(e){var t=e.selection.isBackwards(),n=t?e.selection.getSelectionLead():e.selection.getSelectionAnchor(),i=t?e.selection.getSelectionAnchor():e.selection.getSelectionLead(),o=e.session.doc.getLine(n.row).length,u=e.session.doc.getTextRange(e.selection.getRange()),a=u.replace(/\\n\\s*/,\" \").length,f=e.session.doc.getLine(n.row);for(var l=n.row+1;l<=i.row+1;l++){var c=r.stringTrimLeft(r.stringTrimRight(e.session.doc.getLine(l)));c.length!==0&&(c=\" \"+c),f+=c}i.row+1<e.session.doc.getLength()-1&&(f+=e.session.doc.getNewLineCharacter()),e.clearSelection(),e.session.doc.replace(new s(n.row,0,i.row+2,0),f),a>0?(e.selection.moveCursorTo(n.row,n.column),e.selection.selectTo(n.row,n.column+a)):(o=e.session.doc.getLine(n.row).length>o?o+1:o,e.selection.moveCursorTo(n.row,o))},multiSelectAction:\"forEach\",readOnly:!0},{name:\"invertSelection\",bindKey:o(null,null),exec:function(e){var t=e.session.doc.getLength()-1,n=e.session.doc.getLine(t).length,r=e.selection.rangeList.ranges,i=[];r.length<1&&(r=[e.selection.getRange()]);for(var o=0;o<r.length;o++)o==r.length-1&&(r[o].end.row!==t||r[o].end.column!==n)&&i.push(new s(r[o].end.row,r[o].end.column,t,n)),o===0?(r[o].start.row!==0||r[o].start.column!==0)&&i.push(new s(0,0,r[o].start.row,r[o].start.column)):i.push(new s(r[o-1].end.row,r[o-1].end.column,r[o].start.row,r[o].start.column));e.exitMultiSelectMode(),e.clearSelection();for(var o=0;o<i.length;o++)e.selection.addRange(i[o],!1)},readOnly:!0,scrollIntoView:\"none\"}]}),define(\"ace/editor\",[\"require\",\"exports\",\"module\",\"ace/lib/fixoldbrowsers\",\"ace/lib/oop\",\"ace/lib/dom\",\"ace/lib/lang\",\"ace/lib/useragent\",\"ace/keyboard/textinput\",\"ace/mouse/mouse_handler\",\"ace/mouse/fold_handler\",\"ace/keyboard/keybinding\",\"ace/edit_session\",\"ace/search\",\"ace/range\",\"ace/lib/event_emitter\",\"ace/commands/command_manager\",\"ace/commands/default_commands\",\"ace/config\",\"ace/token_iterator\"],function(e,t,n){\"use strict\";e(\"./lib/fixoldbrowsers\");var r=e(\"./lib/oop\"),i=e(\"./lib/dom\"),s=e(\"./lib/lang\"),o=e(\"./lib/useragent\"),u=e(\"./keyboard/textinput\").TextInput,a=e(\"./mouse/mouse_handler\").MouseHandler,f=e(\"./mouse/fold_handler\").FoldHandler,l=e(\"./keyboard/keybinding\").KeyBinding,c=e(\"./edit_session\").EditSession,h=e(\"./search\").Search,p=e(\"./range\").Range,d=e(\"./lib/event_emitter\").EventEmitter,v=e(\"./commands/command_manager\").CommandManager,m=e(\"./commands/default_commands\").commands,g=e(\"./config\"),y=e(\"./token_iterator\").TokenIterator,b=function(e,t){var n=e.getContainerElement();this.container=n,this.renderer=e,this.id=\"editor\"+ ++b.$uid,this.commands=new v(o.isMac?\"mac\":\"win\",m),typeof document==\"object\"&&(this.textInput=new u(e.getTextAreaContainer(),this),this.renderer.textarea=this.textInput.getElement(),this.$mouseHandler=new a(this),new f(this)),this.keyBinding=new l(this),this.$blockScrolling=0,this.$search=(new h).set({wrap:!0}),this.$historyTracker=this.$historyTracker.bind(this),this.commands.on(\"exec\",this.$historyTracker),this.$initOperationListeners(),this._$emitInputEvent=s.delayedCall(function(){this._signal(\"input\",{}),this.session&&this.session.bgTokenizer&&this.session.bgTokenizer.scheduleStart()}.bind(this)),this.on(\"change\",function(e,t){t._$emitInputEvent.schedule(31)}),this.setSession(t||new c(\"\")),g.resetOptions(this),g._signal(\"editor\",this)};b.$uid=0,function(){r.implement(this,d),this.$initOperationListeners=function(){function e(e){return e[e.length-1]}this.selections=[],this.commands.on(\"exec\",this.startOperation.bind(this),!0),this.commands.on(\"afterExec\",this.endOperation.bind(this),!0),this.$opResetTimer=s.delayedCall(this.endOperation.bind(this)),this.on(\"change\",function(){this.curOp||this.startOperation(),this.curOp.docChanged=!0}.bind(this),!0),this.on(\"changeSelection\",function(){this.curOp||this.startOperation(),this.curOp.selectionChanged=!0}.bind(this),!0)},this.curOp=null,this.prevOp={},this.startOperation=function(e){if(this.curOp){if(!e||this.curOp.command)return;this.prevOp=this.curOp}e||(this.previousCommand=null,e={}),this.$opResetTimer.schedule(),this.curOp={command:e.command||{},args:e.args,scrollTop:this.renderer.scrollTop},this.curOp.command.name&&this.curOp.command.scrollIntoView!==undefined&&this.$blockScrolling++},this.endOperation=function(e){if(this.curOp){if(e&&e.returnValue===!1)return this.curOp=null;this._signal(\"beforeEndOperation\");var t=this.curOp.command;t.name&&this.$blockScrolling>0&&this.$blockScrolling--;var n=t&&t.scrollIntoView;if(n){switch(n){case\"center-animate\":n=\"animate\";case\"center\":this.renderer.scrollCursorIntoView(null,.5);break;case\"animate\":case\"cursor\":this.renderer.scrollCursorIntoView();break;case\"selectionPart\":var r=this.selection.getRange(),i=this.renderer.layerConfig;(r.start.row>=i.lastRow||r.end.row<=i.firstRow)&&this.renderer.scrollSelectionIntoView(this.selection.anchor,this.selection.lead);break;default:}n==\"animate\"&&this.renderer.animateScrolling(this.curOp.scrollTop)}this.prevOp=this.curOp,this.curOp=null}},this.$mergeableCommands=[\"backspace\",\"del\",\"insertstring\"],this.$historyTracker=function(e){if(!this.$mergeUndoDeltas)return;var t=this.prevOp,n=this.$mergeableCommands,r=t.command&&e.command.name==t.command.name;if(e.command.name==\"insertstring\"){var i=e.args;this.mergeNextCommand===undefined&&(this.mergeNextCommand=!0),r=r&&this.mergeNextCommand&&(!/\\s/.test(i)||/\\s/.test(t.args)),this.mergeNextCommand=!0}else r=r&&n.indexOf(e.command.name)!==-1;this.$mergeUndoDeltas!=\"always\"&&Date.now()-this.sequenceStartTime>2e3&&(r=!1),r?this.session.mergeUndoDeltas=!0:n.indexOf(e.command.name)!==-1&&(this.sequenceStartTime=Date.now())},this.setKeyboardHandler=function(e,t){if(e&&typeof e==\"string\"){this.$keybindingId=e;var n=this;g.loadModule([\"keybinding\",e],function(r){n.$keybindingId==e&&n.keyBinding.setKeyboardHandler(r&&r.handler),t&&t()})}else this.$keybindingId=null,this.keyBinding.setKeyboardHandler(e),t&&t()},this.getKeyboardHandler=function(){return this.keyBinding.getKeyboardHandler()},this.setSession=function(e){if(this.session==e)return;this.curOp&&this.endOperation(),this.curOp={};var t=this.session;if(t){this.session.off(\"change\",this.$onDocumentChange),this.session.off(\"changeMode\",this.$onChangeMode),this.session.off(\"tokenizerUpdate\",this.$onTokenizerUpdate),this.session.off(\"changeTabSize\",this.$onChangeTabSize),this.session.off(\"changeWrapLimit\",this.$onChangeWrapLimit),this.session.off(\"changeWrapMode\",this.$onChangeWrapMode),this.session.off(\"changeFold\",this.$onChangeFold),this.session.off(\"changeFrontMarker\",this.$onChangeFrontMarker),this.session.off(\"changeBackMarker\",this.$onChangeBackMarker),this.session.off(\"changeBreakpoint\",this.$onChangeBreakpoint),this.session.off(\"changeAnnotation\",this.$onChangeAnnotation),this.session.off(\"changeOverwrite\",this.$onCursorChange),this.session.off(\"changeScrollTop\",this.$onScrollTopChange),this.session.off(\"changeScrollLeft\",this.$onScrollLeftChange);var n=this.session.getSelection();n.off(\"changeCursor\",this.$onCursorChange),n.off(\"changeSelection\",this.$onSelectionChange)}this.session=e,e?(this.$onDocumentChange=this.onDocumentChange.bind(this),e.on(\"change\",this.$onDocumentChange),this.renderer.setSession(e),this.$onChangeMode=this.onChangeMode.bind(this),e.on(\"changeMode\",this.$onChangeMode),this.$onTokenizerUpdate=this.onTokenizerUpdate.bind(this),e.on(\"tokenizerUpdate\",this.$onTokenizerUpdate),this.$onChangeTabSize=this.renderer.onChangeTabSize.bind(this.renderer),e.on(\"changeTabSize\",this.$onChangeTabSize),this.$onChangeWrapLimit=this.onChangeWrapLimit.bind(this),e.on(\"changeWrapLimit\",this.$onChangeWrapLimit),this.$onChangeWrapMode=this.onChangeWrapMode.bind(this),e.on(\"changeWrapMode\",this.$onChangeWrapMode),this.$onChangeFold=this.onChangeFold.bind(this),e.on(\"changeFold\",this.$onChangeFold),this.$onChangeFrontMarker=this.onChangeFrontMarker.bind(this),this.session.on(\"changeFrontMarker\",this.$onChangeFrontMarker),this.$onChangeBackMarker=this.onChangeBackMarker.bind(this),this.session.on(\"changeBackMarker\",this.$onChangeBackMarker),this.$onChangeBreakpoint=this.onChangeBreakpoint.bind(this),this.session.on(\"changeBreakpoint\",this.$onChangeBreakpoint),this.$onChangeAnnotation=this.onChangeAnnotation.bind(this),this.session.on(\"changeAnnotation\",this.$onChangeAnnotation),this.$onCursorChange=this.onCursorChange.bind(this),this.session.on(\"changeOverwrite\",this.$onCursorChange),this.$onScrollTopChange=this.onScrollTopChange.bind(this),this.session.on(\"changeScrollTop\",this.$onScrollTopChange),this.$onScrollLeftChange=this.onScrollLeftChange.bind(this),this.session.on(\"changeScrollLeft\",this.$onScrollLeftChange),this.selection=e.getSelection(),this.selection.on(\"changeCursor\",this.$onCursorChange),this.$onSelectionChange=this.onSelectionChange.bind(this),this.selection.on(\"changeSelection\",this.$onSelectionChange),this.onChangeMode(),this.$blockScrolling+=1,this.onCursorChange(),this.$blockScrolling-=1,this.onScrollTopChange(),this.onScrollLeftChange(),this.onSelectionChange(),this.onChangeFrontMarker(),this.onChangeBackMarker(),this.onChangeBreakpoint(),this.onChangeAnnotation(),this.session.getUseWrapMode()&&this.renderer.adjustWrapLimit(),this.renderer.updateFull()):(this.selection=null,this.renderer.setSession(e)),this._signal(\"changeSession\",{session:e,oldSession:t}),this.curOp=null,t&&t._signal(\"changeEditor\",{oldEditor:this}),e&&e._signal(\"changeEditor\",{editor:this}),e&&e.bgTokenizer&&e.bgTokenizer.scheduleStart()},this.getSession=function(){return this.session},this.setValue=function(e,t){return this.session.doc.setValue(e),t?t==1?this.navigateFileEnd():t==-1&&this.navigateFileStart():this.selectAll(),e},this.getValue=function(){return this.session.getValue()},this.getSelection=function(){return this.selection},this.resize=function(e){this.renderer.onResize(e)},this.setTheme=function(e,t){this.renderer.setTheme(e,t)},this.getTheme=function(){return this.renderer.getTheme()},this.setStyle=function(e){this.renderer.setStyle(e)},this.unsetStyle=function(e){this.renderer.unsetStyle(e)},this.getFontSize=function(){return this.getOption(\"fontSize\")||i.computedStyle(this.container,\"fontSize\")},this.setFontSize=function(e){this.setOption(\"fontSize\",e)},this.$highlightBrackets=function(){this.session.$bracketHighlight&&(this.session.removeMarker(this.session.$bracketHighlight),this.session.$bracketHighlight=null);if(this.$highlightPending)return;var e=this;this.$highlightPending=!0,setTimeout(function(){e.$highlightPending=!1;var t=e.session;if(!t||!t.bgTokenizer)return;var n=t.findMatchingBracket(e.getCursorPosition());if(n)var r=new p(n.row,n.column,n.row,n.column+1);else if(t.$mode.getMatching)var r=t.$mode.getMatching(e.session);r&&(t.$bracketHighlight=t.addMarker(r,\"ace_bracket\",\"text\"))},50)},this.$highlightTags=function(){if(this.$highlightTagPending)return;var e=this;this.$highlightTagPending=!0,setTimeout(function(){e.$highlightTagPending=!1;var t=e.session;if(!t||!t.bgTokenizer)return;var n=e.getCursorPosition(),r=new y(e.session,n.row,n.column),i=r.getCurrentToken();if(!i||!/\\b(?:tag-open|tag-name)/.test(i.type)){t.removeMarker(t.$tagHighlight),t.$tagHighlight=null;return}if(i.type.indexOf(\"tag-open\")!=-1){i=r.stepForward();if(!i)return}var s=i.value,o=0,u=r.stepBackward();if(u.value==\"<\"){do u=i,i=r.stepForward(),i&&i.value===s&&i.type.indexOf(\"tag-name\")!==-1&&(u.value===\"<\"?o++:u.value===\"</\"&&o--);while(i&&o>=0)}else{do i=u,u=r.stepBackward(),i&&i.value===s&&i.type.indexOf(\"tag-name\")!==-1&&(u.value===\"<\"?o++:u.value===\"</\"&&o--);while(u&&o<=0);r.stepForward()}if(!i){t.removeMarker(t.$tagHighlight),t.$tagHighlight=null;return}var a=r.getCurrentTokenRow(),f=r.getCurrentTokenColumn(),l=new p(a,f,a,f+i.value.length),c=t.$backMarkers[t.$tagHighlight];t.$tagHighlight&&c!=undefined&&l.compareRange(c.range)!==0&&(t.removeMarker(t.$tagHighlight),t.$tagHighlight=null),l&&!t.$tagHighlight&&(t.$tagHighlight=t.addMarker(l,\"ace_bracket\",\"text\"))},50)},this.focus=function(){var e=this;setTimeout(function(){e.textInput.focus()}),this.textInput.focus()},this.isFocused=function(){return this.textInput.isFocused()},this.blur=function(){this.textInput.blur()},this.onFocus=function(e){if(this.$isFocused)return;this.$isFocused=!0,this.renderer.showCursor(),this.renderer.visualizeFocus(),this._emit(\"focus\",e)},this.onBlur=function(e){if(!this.$isFocused)return;this.$isFocused=!1,this.renderer.hideCursor(),this.renderer.visualizeBlur(),this._emit(\"blur\",e)},this.$cursorChange=function(){this.renderer.updateCursor()},this.onDocumentChange=function(e){var t=this.session.$useWrapMode,n=e.start.row==e.end.row?e.end.row:Infinity;this.renderer.updateLines(e.start.row,n,t),this._signal(\"change\",e),this.$cursorChange(),this.$updateHighlightActiveLine()},this.onTokenizerUpdate=function(e){var t=e.data;this.renderer.updateLines(t.first,t.last)},this.onScrollTopChange=function(){this.renderer.scrollToY(this.session.getScrollTop())},this.onScrollLeftChange=function(){this.renderer.scrollToX(this.session.getScrollLeft())},this.onCursorChange=function(){this.$cursorChange(),this.$blockScrolling||(g.warn(\"Automatically scrolling cursor into view after selection change\",\"this will be disabled in the next version\",\"set editor.$blockScrolling = Infinity to disable this message\"),this.renderer.scrollCursorIntoView()),this.$highlightBrackets(),this.$highlightTags(),this.$updateHighlightActiveLine(),this._signal(\"changeSelection\")},this.$updateHighlightActiveLine=function(){var e=this.getSession(),t;if(this.$highlightActiveLine){if(this.$selectionStyle!=\"line\"||!this.selection.isMultiLine())t=this.getCursorPosition();this.renderer.$maxLines&&this.session.getLength()===1&&!(this.renderer.$minLines>1)&&(t=!1)}if(e.$highlightLineMarker&&!t)e.removeMarker(e.$highlightLineMarker.id),e.$highlightLineMarker=null;else if(!e.$highlightLineMarker&&t){var n=new p(t.row,t.column,t.row,Infinity);n.id=e.addMarker(n,\"ace_active-line\",\"screenLine\"),e.$highlightLineMarker=n}else t&&(e.$highlightLineMarker.start.row=t.row,e.$highlightLineMarker.end.row=t.row,e.$highlightLineMarker.start.column=t.column,e._signal(\"changeBackMarker\"))},this.onSelectionChange=function(e){var t=this.session;t.$selectionMarker&&t.removeMarker(t.$selectionMarker),t.$selectionMarker=null;if(!this.selection.isEmpty()){var n=this.selection.getRange(),r=this.getSelectionStyle();t.$selectionMarker=t.addMarker(n,\"ace_selection\",r)}else this.$updateHighlightActiveLine();var i=this.$highlightSelectedWord&&this.$getSelectionHighLightRegexp();this.session.highlight(i),this._signal(\"changeSelection\")},this.$getSelectionHighLightRegexp=function(){var e=this.session,t=this.getSelectionRange();if(t.isEmpty()||t.isMultiLine())return;var n=t.start.column-1,r=t.end.column+1,i=e.getLine(t.start.row),s=i.length,o=i.substring(Math.max(n,0),Math.min(r,s));if(n>=0&&/^[\\w\\d]/.test(o)||r<=s&&/[\\w\\d]$/.test(o))return;o=i.substring(t.start.column,t.end.column);if(!/^[\\w\\d]+$/.test(o))return;var u=this.$search.$assembleRegExp({wholeWord:!0,caseSensitive:!0,needle:o});return u},this.onChangeFrontMarker=function(){this.renderer.updateFrontMarkers()},this.onChangeBackMarker=function(){this.renderer.updateBackMarkers()},this.onChangeBreakpoint=function(){this.renderer.updateBreakpoints()},this.onChangeAnnotation=function(){this.renderer.setAnnotations(this.session.getAnnotations())},this.onChangeMode=function(e){this.renderer.updateText(),this._emit(\"changeMode\",e)},this.onChangeWrapLimit=function(){this.renderer.updateFull()},this.onChangeWrapMode=function(){this.renderer.onResize(!0)},this.onChangeFold=function(){this.$updateHighlightActiveLine(),this.renderer.updateFull()},this.getSelectedText=function(){return this.session.getTextRange(this.getSelectionRange())},this.getCopyText=function(){var e=this.getSelectedText();return this._signal(\"copy\",e),e},this.onCopy=function(){this.commands.exec(\"copy\",this)},this.onCut=function(){this.commands.exec(\"cut\",this)},this.onPaste=function(e,t){var n={text:e,event:t};this.commands.exec(\"paste\",this,n)},this.$handlePaste=function(e){typeof e==\"string\"&&(e={text:e}),this._signal(\"paste\",e);var t=e.text;if(!this.inMultiSelectMode||this.inVirtualSelectionMode)this.insert(t);else{var n=t.split(/\\r\\n|\\r|\\n/),r=this.selection.rangeList.ranges;if(n.length>r.length||n.length<2||!n[1])return this.commands.exec(\"insertstring\",this,t);for(var i=r.length;i--;){var s=r[i];s.isEmpty()||this.session.remove(s),this.session.insert(s.start,n[i])}}},this.execCommand=function(e,t){return this.commands.exec(e,this,t)},this.insert=function(e,t){var n=this.session,r=n.getMode(),i=this.getCursorPosition();if(this.getBehavioursEnabled()&&!t){var s=r.transformAction(n.getState(i.row),\"insertion\",this,n,e);s&&(e!==s.text&&(this.session.mergeUndoDeltas=!1,this.$mergeNextCommand=!1),e=s.text)}e==\"\t\"&&(e=this.session.getTabString());if(!this.selection.isEmpty()){var o=this.getSelectionRange();i=this.session.remove(o),this.clearSelection()}else if(this.session.getOverwrite()&&e.indexOf(\"\\n\")==-1){var o=new p.fromPoints(i,i);o.end.column+=e.length,this.session.remove(o)}if(e==\"\\n\"||e==\"\\r\\n\"){var u=n.getLine(i.row);if(i.column>u.search(/\\S|$/)){var a=u.substr(i.column).search(/\\S|$/);n.doc.removeInLine(i.row,i.column,i.column+a)}}this.clearSelection();var f=i.column,l=n.getState(i.row),u=n.getLine(i.row),c=r.checkOutdent(l,u,e),h=n.insert(i,e);s&&s.selection&&(s.selection.length==2?this.selection.setSelectionRange(new p(i.row,f+s.selection[0],i.row,f+s.selection[1])):this.selection.setSelectionRange(new p(i.row+s.selection[0],s.selection[1],i.row+s.selection[2],s.selection[3])));if(n.getDocument().isNewLine(e)){var d=r.getNextLineIndent(l,u.slice(0,i.column),n.getTabString());n.insert({row:i.row+1,column:0},d)}c&&r.autoOutdent(l,n,i.row)},this.onTextInput=function(e){this.keyBinding.onTextInput(e)},this.onCommandKey=function(e,t,n){this.keyBinding.onCommandKey(e,t,n)},this.setOverwrite=function(e){this.session.setOverwrite(e)},this.getOverwrite=function(){return this.session.getOverwrite()},this.toggleOverwrite=function(){this.session.toggleOverwrite()},this.setScrollSpeed=function(e){this.setOption(\"scrollSpeed\",e)},this.getScrollSpeed=function(){return this.getOption(\"scrollSpeed\")},this.setDragDelay=function(e){this.setOption(\"dragDelay\",e)},this.getDragDelay=function(){return this.getOption(\"dragDelay\")},this.setSelectionStyle=function(e){this.setOption(\"selectionStyle\",e)},this.getSelectionStyle=function(){return this.getOption(\"selectionStyle\")},this.setHighlightActiveLine=function(e){this.setOption(\"highlightActiveLine\",e)},this.getHighlightActiveLine=function(){return this.getOption(\"highlightActiveLine\")},this.setHighlightGutterLine=function(e){this.setOption(\"highlightGutterLine\",e)},this.getHighlightGutterLine=function(){return this.getOption(\"highlightGutterLine\")},this.setHighlightSelectedWord=function(e){this.setOption(\"highlightSelectedWord\",e)},this.getHighlightSelectedWord=function(){return this.$highlightSelectedWord},this.setAnimatedScroll=function(e){this.renderer.setAnimatedScroll(e)},this.getAnimatedScroll=function(){return this.renderer.getAnimatedScroll()},this.setShowInvisibles=function(e){this.renderer.setShowInvisibles(e)},this.getShowInvisibles=function(){return this.renderer.getShowInvisibles()},this.setDisplayIndentGuides=function(e){this.renderer.setDisplayIndentGuides(e)},this.getDisplayIndentGuides=function(){return this.renderer.getDisplayIndentGuides()},this.setShowPrintMargin=function(e){this.renderer.setShowPrintMargin(e)},this.getShowPrintMargin=function(){return this.renderer.getShowPrintMargin()},this.setPrintMarginColumn=function(e){this.renderer.setPrintMarginColumn(e)},this.getPrintMarginColumn=function(){return this.renderer.getPrintMarginColumn()},this.setReadOnly=function(e){this.setOption(\"readOnly\",e)},this.getReadOnly=function(){return this.getOption(\"readOnly\")},this.setBehavioursEnabled=function(e){this.setOption(\"behavioursEnabled\",e)},this.getBehavioursEnabled=function(){return this.getOption(\"behavioursEnabled\")},this.setWrapBehavioursEnabled=function(e){this.setOption(\"wrapBehavioursEnabled\",e)},this.getWrapBehavioursEnabled=function(){return this.getOption(\"wrapBehavioursEnabled\")},this.setShowFoldWidgets=function(e){this.setOption(\"showFoldWidgets\",e)},this.getShowFoldWidgets=function(){return this.getOption(\"showFoldWidgets\")},this.setFadeFoldWidgets=function(e){this.setOption(\"fadeFoldWidgets\",e)},this.getFadeFoldWidgets=function(){return this.getOption(\"fadeFoldWidgets\")},this.remove=function(e){this.selection.isEmpty()&&(e==\"left\"?this.selection.selectLeft():this.selection.selectRight());var t=this.getSelectionRange();if(this.getBehavioursEnabled()){var n=this.session,r=n.getState(t.start.row),i=n.getMode().transformAction(r,\"deletion\",this,n,t);if(t.end.column===0){var s=n.getTextRange(t);if(s[s.length-1]==\"\\n\"){var o=n.getLine(t.end.row);/^\\s+$/.test(o)&&(t.end.column=o.length)}}i&&(t=i)}this.session.remove(t),this.clearSelection()},this.removeWordRight=function(){this.selection.isEmpty()&&this.selection.selectWordRight(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeWordLeft=function(){this.selection.isEmpty()&&this.selection.selectWordLeft(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeToLineStart=function(){this.selection.isEmpty()&&this.selection.selectLineStart(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeToLineEnd=function(){this.selection.isEmpty()&&this.selection.selectLineEnd();var e=this.getSelectionRange();e.start.column==e.end.column&&e.start.row==e.end.row&&(e.end.column=0,e.end.row++),this.session.remove(e),this.clearSelection()},this.splitLine=function(){this.selection.isEmpty()||(this.session.remove(this.getSelectionRange()),this.clearSelection());var e=this.getCursorPosition();this.insert(\"\\n\"),this.moveCursorToPosition(e)},this.transposeLetters=function(){if(!this.selection.isEmpty())return;var e=this.getCursorPosition(),t=e.column;if(t===0)return;var n=this.session.getLine(e.row),r,i;t<n.length?(r=n.charAt(t)+n.charAt(t-1),i=new p(e.row,t-1,e.row,t+1)):(r=n.charAt(t-1)+n.charAt(t-2),i=new p(e.row,t-2,e.row,t)),this.session.replace(i,r),this.session.selection.moveToPosition(i.end)},this.toLowerCase=function(){var e=this.getSelectionRange();this.selection.isEmpty()&&this.selection.selectWord();var t=this.getSelectionRange(),n=this.session.getTextRange(t);this.session.replace(t,n.toLowerCase()),this.selection.setSelectionRange(e)},this.toUpperCase=function(){var e=this.getSelectionRange();this.selection.isEmpty()&&this.selection.selectWord();var t=this.getSelectionRange(),n=this.session.getTextRange(t);this.session.replace(t,n.toUpperCase()),this.selection.setSelectionRange(e)},this.indent=function(){var e=this.session,t=this.getSelectionRange();if(t.start.row<t.end.row){var n=this.$getSelectedRows();e.indentRows(n.first,n.last,\"\t\");return}if(t.start.column<t.end.column){var r=e.getTextRange(t);if(!/^\\s+$/.test(r)){var n=this.$getSelectedRows();e.indentRows(n.first,n.last,\"\t\");return}}var i=e.getLine(t.start.row),o=t.start,u=e.getTabSize(),a=e.documentToScreenColumn(o.row,o.column);if(this.session.getUseSoftTabs())var f=u-a%u,l=s.stringRepeat(\" \",f);else{var f=a%u;while(i[t.start.column-1]==\" \"&&f)t.start.column--,f--;this.selection.setSelectionRange(t),l=\"\t\"}return this.insert(l)},this.blockIndent=function(){var e=this.$getSelectedRows();this.session.indentRows(e.first,e.last,\"\t\")},this.blockOutdent=function(){var e=this.session.getSelection();this.session.outdentRows(e.getRange())},this.sortLines=function(){var e=this.$getSelectedRows(),t=this.session,n=[];for(var r=e.first;r<=e.last;r++)n.push(t.getLine(r));n.sort(function(e,t){return e.toLowerCase()<t.toLowerCase()?-1:e.toLowerCase()>t.toLowerCase()?1:0});var i=new p(0,0,0,0);for(var r=e.first;r<=e.last;r++){var s=t.getLine(r);i.start.row=r,i.end.row=r,i.end.column=s.length,t.replace(i,n[r-e.first])}},this.toggleCommentLines=function(){var e=this.session.getState(this.getCursorPosition().row),t=this.$getSelectedRows();this.session.getMode().toggleCommentLines(e,this.session,t.first,t.last)},this.toggleBlockComment=function(){var e=this.getCursorPosition(),t=this.session.getState(e.row),n=this.getSelectionRange();this.session.getMode().toggleBlockComment(t,this.session,n,e)},this.getNumberAt=function(e,t){var n=/[\\-]?[0-9]+(?:\\.[0-9]+)?/g;n.lastIndex=0;var r=this.session.getLine(e);while(n.lastIndex<t){var i=n.exec(r);if(i.index<=t&&i.index+i[0].length>=t){var s={value:i[0],start:i.index,end:i.index+i[0].length};return s}}return null},this.modifyNumber=function(e){var t=this.selection.getCursor().row,n=this.selection.getCursor().column,r=new p(t,n-1,t,n),i=this.session.getTextRange(r);if(!isNaN(parseFloat(i))&&isFinite(i)){var s=this.getNumberAt(t,n);if(s){var o=s.value.indexOf(\".\")>=0?s.start+s.value.indexOf(\".\")+1:s.end,u=s.start+s.value.length-o,a=parseFloat(s.value);a*=Math.pow(10,u),o!==s.end&&n<o?e*=Math.pow(10,s.end-n-1):e*=Math.pow(10,s.end-n),a+=e,a/=Math.pow(10,u);var f=a.toFixed(u),l=new p(t,s.start,t,s.end);this.session.replace(l,f),this.moveCursorTo(t,Math.max(s.start+1,n+f.length-s.value.length))}}},this.removeLines=function(){var e=this.$getSelectedRows();this.session.removeFullLines(e.first,e.last),this.clearSelection()},this.duplicateSelection=function(){var e=this.selection,t=this.session,n=e.getRange(),r=e.isBackwards();if(n.isEmpty()){var i=n.start.row;t.duplicateLines(i,i)}else{var s=r?n.start:n.end,o=t.insert(s,t.getTextRange(n),!1);n.start=s,n.end=o,e.setSelectionRange(n,r)}},this.moveLinesDown=function(){this.$moveLines(1,!1)},this.moveLinesUp=function(){this.$moveLines(-1,!1)},this.moveText=function(e,t,n){return this.session.moveText(e,t,n)},this.copyLinesUp=function(){this.$moveLines(-1,!0)},this.copyLinesDown=function(){this.$moveLines(1,!0)},this.$moveLines=function(e,t){var n,r,i=this.selection;if(!i.inMultiSelectMode||this.inVirtualSelectionMode){var s=i.toOrientedRange();n=this.$getSelectedRows(s),r=this.session.$moveLines(n.first,n.last,t?0:e),t&&e==-1&&(r=0),s.moveBy(r,0),i.fromOrientedRange(s)}else{var o=i.rangeList.ranges;i.rangeList.detach(this.session),this.inVirtualSelectionMode=!0;var u=0,a=0,f=o.length;for(var l=0;l<f;l++){var c=l;o[l].moveBy(u,0),n=this.$getSelectedRows(o[l]);var h=n.first,p=n.last;while(++l<f){a&&o[l].moveBy(a,0);var d=this.$getSelectedRows(o[l]);if(t&&d.first!=p)break;if(!t&&d.first>p+1)break;p=d.last}l--,u=this.session.$moveLines(h,p,t?0:e),t&&e==-1&&(c=l+1);while(c<=l)o[c].moveBy(u,0),c++;t||(u=0),a+=u}i.fromOrientedRange(i.ranges[0]),i.rangeList.attach(this.session),this.inVirtualSelectionMode=!1}},this.$getSelectedRows=function(e){return e=(e||this.getSelectionRange()).collapseRows(),{first:this.session.getRowFoldStart(e.start.row),last:this.session.getRowFoldEnd(e.end.row)}},this.onCompositionStart=function(e){this.renderer.showComposition(this.getCursorPosition())},this.onCompositionUpdate=function(e){this.renderer.setCompositionText(e)},this.onCompositionEnd=function(){this.renderer.hideComposition()},this.getFirstVisibleRow=function(){return this.renderer.getFirstVisibleRow()},this.getLastVisibleRow=function(){return this.renderer.getLastVisibleRow()},this.isRowVisible=function(e){return e>=this.getFirstVisibleRow()&&e<=this.getLastVisibleRow()},this.isRowFullyVisible=function(e){return e>=this.renderer.getFirstFullyVisibleRow()&&e<=this.renderer.getLastFullyVisibleRow()},this.$getVisibleRowCount=function(){return this.renderer.getScrollBottomRow()-this.renderer.getScrollTopRow()+1},this.$moveByPage=function(e,t){var n=this.renderer,r=this.renderer.layerConfig,i=e*Math.floor(r.height/r.lineHeight);this.$blockScrolling++,t===!0?this.selection.$moveSelection(function(){this.moveCursorBy(i,0)}):t===!1&&(this.selection.moveCursorBy(i,0),this.selection.clearSelection()),this.$blockScrolling--;var s=n.scrollTop;n.scrollBy(0,i*r.lineHeight),t!=null&&n.scrollCursorIntoView(null,.5),n.animateScrolling(s)},this.selectPageDown=function(){this.$moveByPage(1,!0)},this.selectPageUp=function(){this.$moveByPage(-1,!0)},this.gotoPageDown=function(){this.$moveByPage(1,!1)},this.gotoPageUp=function(){this.$moveByPage(-1,!1)},this.scrollPageDown=function(){this.$moveByPage(1)},this.scrollPageUp=function(){this.$moveByPage(-1)},this.scrollToRow=function(e){this.renderer.scrollToRow(e)},this.scrollToLine=function(e,t,n,r){this.renderer.scrollToLine(e,t,n,r)},this.centerSelection=function(){var e=this.getSelectionRange(),t={row:Math.floor(e.start.row+(e.end.row-e.start.row)/2),column:Math.floor(e.start.column+(e.end.column-e.start.column)/2)};this.renderer.alignCursor(t,.5)},this.getCursorPosition=function(){return this.selection.getCursor()},this.getCursorPositionScreen=function(){return this.session.documentToScreenPosition(this.getCursorPosition())},this.getSelectionRange=function(){return this.selection.getRange()},this.selectAll=function(){this.$blockScrolling+=1,this.selection.selectAll(),this.$blockScrolling-=1},this.clearSelection=function(){this.selection.clearSelection()},this.moveCursorTo=function(e,t){this.selection.moveCursorTo(e,t)},this.moveCursorToPosition=function(e){this.selection.moveCursorToPosition(e)},this.jumpToMatching=function(e,t){var n=this.getCursorPosition(),r=new y(this.session,n.row,n.column),i=r.getCurrentToken(),s=i||r.stepForward();if(!s)return;var o,u=!1,a={},f=n.column-s.start,l,c={\")\":\"(\",\"(\":\"(\",\"]\":\"[\",\"[\":\"[\",\"{\":\"{\",\"}\":\"{\"};do{if(s.value.match(/[{}()\\[\\]]/g))for(;f<s.value.length&&!u;f++){if(!c[s.value[f]])continue;l=c[s.value[f]]+\".\"+s.type.replace(\"rparen\",\"lparen\"),isNaN(a[l])&&(a[l]=0);switch(s.value[f]){case\"(\":case\"[\":case\"{\":a[l]++;break;case\")\":case\"]\":case\"}\":a[l]--,a[l]===-1&&(o=\"bracket\",u=!0)}}else s&&s.type.indexOf(\"tag-name\")!==-1&&(isNaN(a[s.value])&&(a[s.value]=0),i.value===\"<\"?a[s.value]++:i.value===\"</\"&&a[s.value]--,a[s.value]===-1&&(o=\"tag\",u=!0));u||(i=s,s=r.stepForward(),f=0)}while(s&&!u);if(!o)return;var h,d;if(o===\"bracket\"){h=this.session.getBracketRange(n);if(!h){h=new p(r.getCurrentTokenRow(),r.getCurrentTokenColumn()+f-1,r.getCurrentTokenRow(),r.getCurrentTokenColumn()+f-1),d=h.start;if(t||d.row===n.row&&Math.abs(d.column-n.column)<2)h=this.session.getBracketRange(d)}}else if(o===\"tag\"){if(!s||s.type.indexOf(\"tag-name\")===-1)return;var v=s.value;h=new p(r.getCurrentTokenRow(),r.getCurrentTokenColumn()-2,r.getCurrentTokenRow(),r.getCurrentTokenColumn()-2);if(h.compare(n.row,n.column)===0){u=!1;do s=i,i=r.stepBackward(),i&&(i.type.indexOf(\"tag-close\")!==-1&&h.setEnd(r.getCurrentTokenRow(),r.getCurrentTokenColumn()+1),s.value===v&&s.type.indexOf(\"tag-name\")!==-1&&(i.value===\"<\"?a[v]++:i.value===\"</\"&&a[v]--,a[v]===0&&(u=!0)));while(i&&!u)}s&&s.type.indexOf(\"tag-name\")&&(d=h.start,d.row==n.row&&Math.abs(d.column-n.column)<2&&(d=h.end))}d=h&&h.cursor||d,d&&(e?h&&t?this.selection.setRange(h):h&&h.isEqual(this.getSelectionRange())?this.clearSelection():this.selection.selectTo(d.row,d.column):this.selection.moveTo(d.row,d.column))},this.gotoLine=function(e,t,n){this.selection.clearSelection(),this.session.unfold({row:e-1,column:t||0}),this.$blockScrolling+=1,this.exitMultiSelectMode&&this.exitMultiSelectMode(),this.moveCursorTo(e-1,t||0),this.$blockScrolling-=1,this.isRowFullyVisible(e-1)||this.scrollToLine(e-1,!0,n)},this.navigateTo=function(e,t){this.selection.moveTo(e,t)},this.navigateUp=function(e){if(this.selection.isMultiLine()&&!this.selection.isBackwards()){var t=this.selection.anchor.getPosition();return this.moveCursorToPosition(t)}this.selection.clearSelection(),this.selection.moveCursorBy(-e||-1,0)},this.navigateDown=function(e){if(this.selection.isMultiLine()&&this.selection.isBackwards()){var t=this.selection.anchor.getPosition();return this.moveCursorToPosition(t)}this.selection.clearSelection(),this.selection.moveCursorBy(e||1,0)},this.navigateLeft=function(e){if(!this.selection.isEmpty()){var t=this.getSelectionRange().start;this.moveCursorToPosition(t)}else{e=e||1;while(e--)this.selection.moveCursorLeft()}this.clearSelection()},this.navigateRight=function(e){if(!this.selection.isEmpty()){var t=this.getSelectionRange().end;this.moveCursorToPosition(t)}else{e=e||1;while(e--)this.selection.moveCursorRight()}this.clearSelection()},this.navigateLineStart=function(){this.selection.moveCursorLineStart(),this.clearSelection()},this.navigateLineEnd=function(){this.selection.moveCursorLineEnd(),this.clearSelection()},this.navigateFileEnd=function(){this.selection.moveCursorFileEnd(),this.clearSelection()},this.navigateFileStart=function(){this.selection.moveCursorFileStart(),this.clearSelection()},this.navigateWordRight=function(){this.selection.moveCursorWordRight(),this.clearSelection()},this.navigateWordLeft=function(){this.selection.moveCursorWordLeft(),this.clearSelection()},this.replace=function(e,t){t&&this.$search.set(t);var n=this.$search.find(this.session),r=0;return n?(this.$tryReplace(n,e)&&(r=1),n!==null&&(this.selection.setSelectionRange(n),this.renderer.scrollSelectionIntoView(n.start,n.end)),r):r},this.replaceAll=function(e,t){t&&this.$search.set(t);var n=this.$search.findAll(this.session),r=0;if(!n.length)return r;this.$blockScrolling+=1;var i=this.getSelectionRange();this.selection.moveTo(0,0);for(var s=n.length-1;s>=0;--s)this.$tryReplace(n[s],e)&&r++;return this.selection.setSelectionRange(i),this.$blockScrolling-=1,r},this.$tryReplace=function(e,t){var n=this.session.getTextRange(e);return t=this.$search.replace(n,t),t!==null?(e.end=this.session.replace(e,t),e):null},this.getLastSearchOptions=function(){return this.$search.getOptions()},this.find=function(e,t,n){t||(t={}),typeof e==\"string\"||e instanceof RegExp?t.needle=e:typeof e==\"object\"&&r.mixin(t,e);var i=this.selection.getRange();t.needle==null&&(e=this.session.getTextRange(i)||this.$search.$options.needle,e||(i=this.session.getWordRange(i.start.row,i.start.column),e=this.session.getTextRange(i)),this.$search.set({needle:e})),this.$search.set(t),t.start||this.$search.set({start:i});var s=this.$search.find(this.session);if(t.preventScroll)return s;if(s)return this.revealRange(s,n),s;t.backwards?i.start=i.end:i.end=i.start,this.selection.setRange(i)},this.findNext=function(e,t){this.find({skipCurrent:!0,backwards:!1},e,t)},this.findPrevious=function(e,t){this.find(e,{skipCurrent:!0,backwards:!0},t)},this.revealRange=function(e,t){this.$blockScrolling+=1,this.session.unfold(e),this.selection.setSelectionRange(e),this.$blockScrolling-=1;var n=this.renderer.scrollTop;this.renderer.scrollSelectionIntoView(e.start,e.end,.5),t!==!1&&this.renderer.animateScrolling(n)},this.undo=function(){this.$blockScrolling++,this.session.getUndoManager().undo(),this.$blockScrolling--,this.renderer.scrollCursorIntoView(null,.5)},this.redo=function(){this.$blockScrolling++,this.session.getUndoManager().redo(),this.$blockScrolling--,this.renderer.scrollCursorIntoView(null,.5)},this.destroy=function(){this.renderer.destroy(),this._signal(\"destroy\",this),this.session&&this.session.destroy()},this.setAutoScrollEditorIntoView=function(e){if(!e)return;var t,n=this,r=!1;this.$scrollAnchor||(this.$scrollAnchor=document.createElement(\"div\"));var i=this.$scrollAnchor;i.style.cssText=\"position:absolute\",this.container.insertBefore(i,this.container.firstChild);var s=this.on(\"changeSelection\",function(){r=!0}),o=this.renderer.on(\"beforeRender\",function(){r&&(t=n.renderer.container.getBoundingClientRect())}),u=this.renderer.on(\"afterRender\",function(){if(r&&t&&(n.isFocused()||n.searchBox&&n.searchBox.isFocused())){var e=n.renderer,s=e.$cursorLayer.$pixelPos,o=e.layerConfig,u=s.top-o.offset;s.top>=0&&u+t.top<0?r=!0:s.top<o.height&&s.top+t.top+o.lineHeight>window.innerHeight?r=!1:r=null,r!=null&&(i.style.top=u+\"px\",i.style.left=s.left+\"px\",i.style.height=o.lineHeight+\"px\",i.scrollIntoView(r)),r=t=null}});this.setAutoScrollEditorIntoView=function(e){if(e)return;delete this.setAutoScrollEditorIntoView,this.off(\"changeSelection\",s),this.renderer.off(\"afterRender\",u),this.renderer.off(\"beforeRender\",o)}},this.$resetCursorStyle=function(){var e=this.$cursorStyle||\"ace\",t=this.renderer.$cursorLayer;if(!t)return;t.setSmoothBlinking(/smooth/.test(e)),t.isBlinking=!this.$readOnly&&e!=\"wide\",i.setCssClass(t.element,\"ace_slim-cursors\",/slim/.test(e))}}.call(b.prototype),g.defineOptions(b.prototype,\"editor\",{selectionStyle:{set:function(e){this.onSelectionChange(),this._signal(\"changeSelectionStyle\",{data:e})},initialValue:\"line\"},highlightActiveLine:{set:function(){this.$updateHighlightActiveLine()},initialValue:!0},highlightSelectedWord:{set:function(e){this.$onSelectionChange()},initialValue:!0},readOnly:{set:function(e){this.$resetCursorStyle()},initialValue:!1},cursorStyle:{set:function(e){this.$resetCursorStyle()},values:[\"ace\",\"slim\",\"smooth\",\"wide\"],initialValue:\"ace\"},mergeUndoDeltas:{values:[!1,!0,\"always\"],initialValue:!0},behavioursEnabled:{initialValue:!0},wrapBehavioursEnabled:{initialValue:!0},autoScrollEditorIntoView:{set:function(e){this.setAutoScrollEditorIntoView(e)}},keyboardHandler:{set:function(e){this.setKeyboardHandler(e)},get:function(){return this.keybindingId},handlesSet:!0},hScrollBarAlwaysVisible:\"renderer\",vScrollBarAlwaysVisible:\"renderer\",highlightGutterLine:\"renderer\",animatedScroll:\"renderer\",showInvisibles:\"renderer\",showPrintMargin:\"renderer\",printMarginColumn:\"renderer\",printMargin:\"renderer\",fadeFoldWidgets:\"renderer\",showFoldWidgets:\"renderer\",showLineNumbers:\"renderer\",showGutter:\"renderer\",displayIndentGuides:\"renderer\",fontSize:\"renderer\",fontFamily:\"renderer\",maxLines:\"renderer\",minLines:\"renderer\",scrollPastEnd:\"renderer\",fixedWidthGutter:\"renderer\",theme:\"renderer\",scrollSpeed:\"$mouseHandler\",dragDelay:\"$mouseHandler\",dragEnabled:\"$mouseHandler\",focusTimout:\"$mouseHandler\",tooltipFollowsMouse:\"$mouseHandler\",firstLineNumber:\"session\",overwrite:\"session\",newLineMode:\"session\",useWorker:\"session\",useSoftTabs:\"session\",tabSize:\"session\",wrap:\"session\",indentedSoftWrap:\"session\",foldStyle:\"session\",mode:\"session\"}),t.Editor=b}),define(\"ace/undomanager\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";var r=function(){this.reset()};(function(){function e(e){return{action:e.action,start:e.start,end:e.end,lines:e.lines.length==1?null:e.lines,text:e.lines.length==1?e.lines[0]:null}}function t(e){return{action:e.action,start:e.start,end:e.end,lines:e.lines||[e.text]}}function n(e,t){var n=new Array(e.length);for(var r=0;r<e.length;r++){var i=e[r],s={group:i.group,deltas:new Array(i.length)};for(var o=0;o<i.deltas.length;o++){var u=i.deltas[o];s.deltas[o]=t(u)}n[r]=s}return n}this.execute=function(e){var t=e.args[0];this.$doc=e.args[1],e.merge&&this.hasUndo()&&(this.dirtyCounter--,t=this.$undoStack.pop().concat(t)),this.$undoStack.push(t),this.$redoStack=[],this.dirtyCounter<0&&(this.dirtyCounter=NaN),this.dirtyCounter++},this.undo=function(e){var t=this.$undoStack.pop(),n=null;return t&&(n=this.$doc.undoChanges(t,e),this.$redoStack.push(t),this.dirtyCounter--),n},this.redo=function(e){var t=this.$redoStack.pop(),n=null;return t&&(n=this.$doc.redoChanges(this.$deserializeDeltas(t),e),this.$undoStack.push(t),this.dirtyCounter++),n},this.reset=function(){this.$undoStack=[],this.$redoStack=[],this.dirtyCounter=0},this.hasUndo=function(){return this.$undoStack.length>0},this.hasRedo=function(){return this.$redoStack.length>0},this.markClean=function(){this.dirtyCounter=0},this.isClean=function(){return this.dirtyCounter===0},this.$serializeDeltas=function(t){return n(t,e)},this.$deserializeDeltas=function(e){return n(e,t)}}).call(r.prototype),t.UndoManager=r}),define(\"ace/layer/gutter\",[\"require\",\"exports\",\"module\",\"ace/lib/dom\",\"ace/lib/oop\",\"ace/lib/lang\",\"ace/lib/event_emitter\"],function(e,t,n){\"use strict\";var r=e(\"../lib/dom\"),i=e(\"../lib/oop\"),s=e(\"../lib/lang\"),o=e(\"../lib/event_emitter\").EventEmitter,u=function(e){this.element=r.createElement(\"div\"),this.element.className=\"ace_layer ace_gutter-layer\",e.appendChild(this.element),this.setShowFoldWidgets(this.$showFoldWidgets),this.gutterWidth=0,this.$annotations=[],this.$updateAnnotations=this.$updateAnnotations.bind(this),this.$cells=[]};(function(){i.implement(this,o),this.setSession=function(e){this.session&&this.session.removeEventListener(\"change\",this.$updateAnnotations),this.session=e,e&&e.on(\"change\",this.$updateAnnotations)},this.addGutterDecoration=function(e,t){window.console&&console.warn&&console.warn(\"deprecated use session.addGutterDecoration\"),this.session.addGutterDecoration(e,t)},this.removeGutterDecoration=function(e,t){window.console&&console.warn&&console.warn(\"deprecated use session.removeGutterDecoration\"),this.session.removeGutterDecoration(e,t)},this.setAnnotations=function(e){this.$annotations=[];for(var t=0;t<e.length;t++){var n=e[t],r=n.row,i=this.$annotations[r];i||(i=this.$annotations[r]={text:[]});var o=n.text;o=o?s.escapeHTML(o):n.html||\"\",i.text.indexOf(o)===-1&&i.text.push(o);var u=n.type;u==\"error\"?i.className=\" ace_error\":u==\"warning\"&&i.className!=\" ace_error\"?i.className=\" ace_warning\":u==\"info\"&&!i.className&&(i.className=\" ace_info\")}},this.$updateAnnotations=function(e){if(!this.$annotations.length)return;var t=e.start.row,n=e.end.row-t;if(n!==0)if(e.action==\"remove\")this.$annotations.splice(t,n+1,null);else{var r=new Array(n+1);r.unshift(t,1),this.$annotations.splice.apply(this.$annotations,r)}},this.update=function(e){var t=this.session,n=e.firstRow,i=Math.min(e.lastRow+e.gutterOffset,t.getLength()-1),s=t.getNextFoldLine(n),o=s?s.start.row:Infinity,u=this.$showFoldWidgets&&t.foldWidgets,a=t.$breakpoints,f=t.$decorations,l=t.$firstLineNumber,c=0,h=t.gutterRenderer||this.$renderer,p=null,d=-1,v=n;for(;;){v>o&&(v=s.end.row+1,s=t.getNextFoldLine(v,s),o=s?s.start.row:Infinity);if(v>i){while(this.$cells.length>d+1)p=this.$cells.pop(),this.element.removeChild(p.element);break}p=this.$cells[++d],p||(p={element:null,textNode:null,foldWidget:null},p.element=r.createElement(\"div\"),p.textNode=document.createTextNode(\"\"),p.element.appendChild(p.textNode),this.element.appendChild(p.element),this.$cells[d]=p);var m=\"ace_gutter-cell \";a[v]&&(m+=a[v]),f[v]&&(m+=f[v]),this.$annotations[v]&&(m+=this.$annotations[v].className),p.element.className!=m&&(p.element.className=m);var g=t.getRowLength(v)*e.lineHeight+\"px\";g!=p.element.style.height&&(p.element.style.height=g);if(u){var y=u[v];y==null&&(y=u[v]=t.getFoldWidget(v))}if(y){p.foldWidget||(p.foldWidget=r.createElement(\"span\"),p.element.appendChild(p.foldWidget));var m=\"ace_fold-widget ace_\"+y;y==\"start\"&&v==o&&v<s.end.row?m+=\" ace_closed\":m+=\" ace_open\",p.foldWidget.className!=m&&(p.foldWidget.className=m);var g=e.lineHeight+\"px\";p.foldWidget.style.height!=g&&(p.foldWidget.style.height=g)}else p.foldWidget&&(p.element.removeChild(p.foldWidget),p.foldWidget=null);var b=c=h?h.getText(t,v):v+l;b!==p.textNode.data&&(p.textNode.data=b),v++}this.element.style.height=e.minHeight+\"px\";if(this.$fixedWidth||t.$useWrapMode)c=t.getLength()+l;var w=h?h.getWidth(t,c,e):c.toString().length*e.characterWidth,E=this.$padding||this.$computePadding();w+=E.left+E.right,w!==this.gutterWidth&&!isNaN(w)&&(this.gutterWidth=w,this.element.style.width=Math.ceil(this.gutterWidth)+\"px\",this._emit(\"changeGutterWidth\",w))},this.$fixedWidth=!1,this.$showLineNumbers=!0,this.$renderer=\"\",this.setShowLineNumbers=function(e){this.$renderer=!e&&{getWidth:function(){return\"\"},getText:function(){return\"\"}}},this.getShowLineNumbers=function(){return this.$showLineNumbers},this.$showFoldWidgets=!0,this.setShowFoldWidgets=function(e){e?r.addCssClass(this.element,\"ace_folding-enabled\"):r.removeCssClass(this.element,\"ace_folding-enabled\"),this.$showFoldWidgets=e,this.$padding=null},this.getShowFoldWidgets=function(){return this.$showFoldWidgets},this.$computePadding=function(){if(!this.element.firstChild)return{left:0,right:0};var e=r.computedStyle(this.element.firstChild);return this.$padding={},this.$padding.left=parseInt(e.paddingLeft)+1||0,this.$padding.right=parseInt(e.paddingRight)||0,this.$padding},this.getRegion=function(e){var t=this.$padding||this.$computePadding(),n=this.element.getBoundingClientRect();if(e.x<t.left+n.left)return\"markers\";if(this.$showFoldWidgets&&e.x>n.right-t.right)return\"foldWidgets\"}}).call(u.prototype),t.Gutter=u}),define(\"ace/layer/marker\",[\"require\",\"exports\",\"module\",\"ace/range\",\"ace/lib/dom\"],function(e,t,n){\"use strict\";var r=e(\"../range\").Range,i=e(\"../lib/dom\"),s=function(e){this.element=i.createElement(\"div\"),this.element.className=\"ace_layer ace_marker-layer\",e.appendChild(this.element)};(function(){function e(e,t,n,r){return(e?1:0)|(t?2:0)|(n?4:0)|(r?8:0)}this.$padding=0,this.setPadding=function(e){this.$padding=e},this.setSession=function(e){this.session=e},this.setMarkers=function(e){this.markers=e},this.update=function(e){if(!e)return;this.config=e;var t=[];for(var n in this.markers){var r=this.markers[n];if(!r.range){r.update(t,this,this.session,e);continue}var i=r.range.clipRows(e.firstRow,e.lastRow);if(i.isEmpty())continue;i=i.toScreenRange(this.session);if(r.renderer){var s=this.$getTop(i.start.row,e),o=this.$padding+(this.session.$bidiHandler.isBidiRow(i.start.row)?this.session.$bidiHandler.getPosLeft(i.start.column):i.start.column*e.characterWidth);r.renderer(t,i,o,s,e)}else r.type==\"fullLine\"?this.drawFullLineMarker(t,i,r.clazz,e):r.type==\"screenLine\"?this.drawScreenLineMarker(t,i,r.clazz,e):i.isMultiLine()?r.type==\"text\"?this.drawTextMarker(t,i,r.clazz,e):this.drawMultiLineMarker(t,i,r.clazz,e):this.session.$bidiHandler.isBidiRow(i.start.row)?this.drawBidiSingleLineMarker(t,i,r.clazz+\" ace_start\"+\" ace_br15\",e):this.drawSingleLineMarker(t,i,r.clazz+\" ace_start\"+\" ace_br15\",e)}this.element.innerHTML=t.join(\"\")},this.$getTop=function(e,t){return(e-t.firstRowScreen)*t.lineHeight},this.drawTextMarker=function(t,n,i,s,o){var u=this.session,a=n.start.row,f=n.end.row,l=a,c=0,h=0,p=u.getScreenLastRowColumn(l),d=null,v=new r(l,n.start.column,l,h);for(;l<=f;l++)v.start.row=v.end.row=l,v.start.column=l==a?n.start.column:u.getRowWrapIndent(l),v.end.column=p,c=h,h=p,p=l+1<f?u.getScreenLastRowColumn(l+1):l==f?0:n.end.column,d=i+(l==a?\" ace_start\":\"\")+\" ace_br\"+e(l==a||l==a+1&&n.start.column,c<h,h>p,l==f),this.session.$bidiHandler.isBidiRow(l)?this.drawBidiSingleLineMarker(t,v,d,s,l==f?0:1,o):this.drawSingleLineMarker(t,v,d,s,l==f?0:1,o)},this.drawMultiLineMarker=function(e,t,n,r,i){var s=this.$padding,o,u,a;i=i||\"\";if(this.session.$bidiHandler.isBidiRow(t.start.row)){var f=t.clone();f.end.row=f.start.row,f.end.column=this.session.getLine(f.start.row).length,this.drawBidiSingleLineMarker(e,f,n+\" ace_br1 ace_start\",r,null,i)}else o=r.lineHeight,u=this.$getTop(t.start.row,r),a=s+t.start.column*r.characterWidth,e.push(\"<div class='\",n,\" ace_br1 ace_start' style='\",\"height:\",o,\"px;\",\"right:0;\",\"top:\",u,\"px;\",\"left:\",a,\"px;\",i,\"'></div>\");if(this.session.$bidiHandler.isBidiRow(t.end.row)){var f=t.clone();f.start.row=f.end.row,f.start.column=0,this.drawBidiSingleLineMarker(e,f,n+\" ace_br12\",r,null,i)}else{var l=t.end.column*r.characterWidth;o=r.lineHeight,u=this.$getTop(t.end.row,r),e.push(\"<div class='\",n,\" ace_br12' style='\",\"height:\",o,\"px;\",\"width:\",l,\"px;\",\"top:\",u,\"px;\",\"left:\",s,\"px;\",i,\"'></div>\")}o=(t.end.row-t.start.row-1)*r.lineHeight;if(o<=0)return;u=this.$getTop(t.start.row+1,r);var c=(t.start.column?1:0)|(t.end.column?0:8);e.push(\"<div class='\",n,c?\" ace_br\"+c:\"\",\"' style='\",\"height:\",o,\"px;\",\"right:0;\",\"top:\",u,\"px;\",\"left:\",s,\"px;\",i,\"'></div>\")},this.drawSingleLineMarker=function(e,t,n,r,i,s){var o=r.lineHeight,u=(t.end.column+(i||0)-t.start.column)*r.characterWidth,a=this.$getTop(t.start.row,r),f=this.$padding+t.start.column*r.characterWidth;e.push(\"<div class='\",n,\"' style='\",\"height:\",o,\"px;\",\"width:\",u,\"px;\",\"top:\",a,\"px;\",\"left:\",f,\"px;\",s||\"\",\"'></div>\")},this.drawBidiSingleLineMarker=function(e,t,n,r,i,s){var o=r.lineHeight,u=this.$getTop(t.start.row,r),a=this.$padding,f=this.session.$bidiHandler.getSelections(t.start.column,t.end.column);f.forEach(function(t){e.push(\"<div class='\",n,\"' style='\",\"height:\",o,\"px;\",\"width:\",t.width+(i||0),\"px;\",\"top:\",u,\"px;\",\"left:\",a+t.left,\"px;\",s||\"\",\"'></div>\")})},this.drawFullLineMarker=function(e,t,n,r,i){var s=this.$getTop(t.start.row,r),o=r.lineHeight;t.start.row!=t.end.row&&(o+=this.$getTop(t.end.row,r)-s),e.push(\"<div class='\",n,\"' style='\",\"height:\",o,\"px;\",\"top:\",s,\"px;\",\"left:0;right:0;\",i||\"\",\"'></div>\")},this.drawScreenLineMarker=function(e,t,n,r,i){var s=this.$getTop(t.start.row,r),o=r.lineHeight;e.push(\"<div class='\",n,\"' style='\",\"height:\",o,\"px;\",\"top:\",s,\"px;\",\"left:0;right:0;\",i||\"\",\"'></div>\")}}).call(s.prototype),t.Marker=s}),define(\"ace/layer/text\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/dom\",\"ace/lib/lang\",\"ace/lib/useragent\",\"ace/lib/event_emitter\"],function(e,t,n){\"use strict\";var r=e(\"../lib/oop\"),i=e(\"../lib/dom\"),s=e(\"../lib/lang\"),o=e(\"../lib/useragent\"),u=e(\"../lib/event_emitter\").EventEmitter,a=function(e){this.element=i.createElement(\"div\"),this.element.className=\"ace_layer ace_text-layer\",e.appendChild(this.element),this.$updateEolChar=this.$updateEolChar.bind(this)};(function(){r.implement(this,u),this.EOF_CHAR=\"\\u00b6\",this.EOL_CHAR_LF=\"\\u00ac\",this.EOL_CHAR_CRLF=\"\\u00a4\",this.EOL_CHAR=this.EOL_CHAR_LF,this.TAB_CHAR=\"\\u2014\",this.SPACE_CHAR=\"\\u00b7\",this.$padding=0,this.$updateEolChar=function(){var e=this.session.doc.getNewLineCharacter()==\"\\n\"?this.EOL_CHAR_LF:this.EOL_CHAR_CRLF;if(this.EOL_CHAR!=e)return this.EOL_CHAR=e,!0},this.setPadding=function(e){this.$padding=e,this.element.style.padding=\"0 \"+e+\"px\"},this.getLineHeight=function(){return this.$fontMetrics.$characterSize.height||0},this.getCharacterWidth=function(){return this.$fontMetrics.$characterSize.width||0},this.$setFontMetrics=function(e){this.$fontMetrics=e,this.$fontMetrics.on(\"changeCharacterSize\",function(e){this._signal(\"changeCharacterSize\",e)}.bind(this)),this.$pollSizeChanges()},this.checkForSizeChanges=function(){this.$fontMetrics.checkForSizeChanges()},this.$pollSizeChanges=function(){return this.$pollSizeChangesTimer=this.$fontMetrics.$pollSizeChanges()},this.setSession=function(e){this.session=e,e&&this.$computeTabString()},this.showInvisibles=!1,this.setShowInvisibles=function(e){return this.showInvisibles==e?!1:(this.showInvisibles=e,this.$computeTabString(),!0)},this.displayIndentGuides=!0,this.setDisplayIndentGuides=function(e){return this.displayIndentGuides==e?!1:(this.displayIndentGuides=e,this.$computeTabString(),!0)},this.$tabStrings=[],this.onChangeTabSize=this.$computeTabString=function(){var e=this.session.getTabSize();this.tabSize=e;var t=this.$tabStrings=[0];for(var n=1;n<e+1;n++)this.showInvisibles?t.push(\"<span class='ace_invisible ace_invisible_tab'>\"+s.stringRepeat(this.TAB_CHAR,n)+\"</span>\"):t.push(s.stringRepeat(\" \",n));if(this.displayIndentGuides){this.$indentGuideRe=/\\s\\S| \\t|\\t |\\s$/;var r=\"ace_indent-guide\",i=\"\",o=\"\";if(this.showInvisibles){r+=\" ace_invisible\",i=\" ace_invisible_space\",o=\" ace_invisible_tab\";var u=s.stringRepeat(this.SPACE_CHAR,this.tabSize),a=s.stringRepeat(this.TAB_CHAR,this.tabSize)}else var u=s.stringRepeat(\" \",this.tabSize),a=u;this.$tabStrings[\" \"]=\"<span class='\"+r+i+\"'>\"+u+\"</span>\",this.$tabStrings[\"\t\"]=\"<span class='\"+r+o+\"'>\"+a+\"</span>\"}},this.updateLines=function(e,t,n){(this.config.lastRow!=e.lastRow||this.config.firstRow!=e.firstRow)&&this.scrollLines(e),this.config=e;var r=Math.max(t,e.firstRow),i=Math.min(n,e.lastRow),s=this.element.childNodes,o=0;for(var u=e.firstRow;u<r;u++){var a=this.session.getFoldLine(u);if(a){if(a.containsRow(r)){r=a.start.row;break}u=a.end.row}o++}var u=r,a=this.session.getNextFoldLine(u),f=a?a.start.row:Infinity;for(;;){u>f&&(u=a.end.row+1,a=this.session.getNextFoldLine(u,a),f=a?a.start.row:Infinity);if(u>i)break;var l=s[o++];if(l){var c=[];this.$renderLine(c,u,!this.$useLineGroups(),u==f?a:!1),l.style.height=e.lineHeight*this.session.getRowLength(u)+\"px\",l.innerHTML=c.join(\"\")}u++}},this.scrollLines=function(e){var t=this.config;this.config=e;if(!t||t.lastRow<e.firstRow)return this.update(e);if(e.lastRow<t.firstRow)return this.update(e);var n=this.element;if(t.firstRow<e.firstRow)for(var r=this.session.getFoldedRowCount(t.firstRow,e.firstRow-1);r>0;r--)n.removeChild(n.firstChild);if(t.lastRow>e.lastRow)for(var r=this.session.getFoldedRowCount(e.lastRow+1,t.lastRow);r>0;r--)n.removeChild(n.lastChild);if(e.firstRow<t.firstRow){var i=this.$renderLinesFragment(e,e.firstRow,t.firstRow-1);n.firstChild?n.insertBefore(i,n.firstChild):n.appendChild(i)}if(e.lastRow>t.lastRow){var i=this.$renderLinesFragment(e,t.lastRow+1,e.lastRow);n.appendChild(i)}},this.$renderLinesFragment=function(e,t,n){var r=this.element.ownerDocument.createDocumentFragment(),s=t,o=this.session.getNextFoldLine(s),u=o?o.start.row:Infinity;for(;;){s>u&&(s=o.end.row+1,o=this.session.getNextFoldLine(s,o),u=o?o.start.row:Infinity);if(s>n)break;var a=i.createElement(\"div\"),f=[];this.$renderLine(f,s,!1,s==u?o:!1),a.innerHTML=f.join(\"\");if(this.$useLineGroups())a.className=\"ace_line_group\",r.appendChild(a),a.style.height=e.lineHeight*this.session.getRowLength(s)+\"px\";else while(a.firstChild)r.appendChild(a.firstChild);s++}return r},this.update=function(e){this.config=e;var t=[],n=e.firstRow,r=e.lastRow,i=n,s=this.session.getNextFoldLine(i),o=s?s.start.row:Infinity;for(;;){i>o&&(i=s.end.row+1,s=this.session.getNextFoldLine(i,s),o=s?s.start.row:Infinity);if(i>r)break;this.$useLineGroups()&&t.push(\"<div class='ace_line_group' style='height:\",e.lineHeight*this.session.getRowLength(i),\"px'>\"),this.$renderLine(t,i,!1,i==o?s:!1),this.$useLineGroups()&&t.push(\"</div>\"),i++}this.element.innerHTML=t.join(\"\")},this.$textToken={text:!0,rparen:!0,lparen:!0},this.$renderToken=function(e,t,n,r){var i=this,o=/\\t|&|<|>|( +)|([\\x00-\\x1f\\x80-\\xa0\\xad\\u1680\\u180E\\u2000-\\u200f\\u2028\\u2029\\u202F\\u205F\\u3000\\uFEFF\\uFFF9-\\uFFFC])|[\\u1100-\\u115F\\u11A3-\\u11A7\\u11FA-\\u11FF\\u2329-\\u232A\\u2E80-\\u2E99\\u2E9B-\\u2EF3\\u2F00-\\u2FD5\\u2FF0-\\u2FFB\\u3000-\\u303E\\u3041-\\u3096\\u3099-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u3190-\\u31BA\\u31C0-\\u31E3\\u31F0-\\u321E\\u3220-\\u3247\\u3250-\\u32FE\\u3300-\\u4DBF\\u4E00-\\uA48C\\uA490-\\uA4C6\\uA960-\\uA97C\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFAFF\\uFE10-\\uFE19\\uFE30-\\uFE52\\uFE54-\\uFE66\\uFE68-\\uFE6B\\uFF01-\\uFF60\\uFFE0-\\uFFE6]|[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]/g,u=function(e,n,r,o,u){if(n)return i.showInvisibles?\"<span class='ace_invisible ace_invisible_space'>\"+s.stringRepeat(i.SPACE_CHAR,e.length)+\"</span>\":e;if(e==\"&\")return\"&#38;\";if(e==\"<\")return\"&#60;\";if(e==\">\")return\"&#62;\";if(e==\"\t\"){var a=i.session.getScreenTabSize(t+o);return t+=a-1,i.$tabStrings[a]}if(e==\"\\u3000\"){var f=i.showInvisibles?\"ace_cjk ace_invisible ace_invisible_space\":\"ace_cjk\",l=i.showInvisibles?i.SPACE_CHAR:\"\";return t+=1,\"<span class='\"+f+\"' style='width:\"+i.config.characterWidth*2+\"px'>\"+l+\"</span>\"}return r?\"<span class='ace_invisible ace_invisible_space ace_invalid'>\"+i.SPACE_CHAR+\"</span>\":(t+=1,\"<span class='ace_cjk' style='width:\"+i.config.characterWidth*2+\"px'>\"+e+\"</span>\")},a=r.replace(o,u);if(!this.$textToken[n.type]){var f=\"ace_\"+n.type.replace(/\\./g,\" ace_\"),l=\"\";n.type==\"fold\"&&(l=\" style='width:\"+n.value.length*this.config.characterWidth+\"px;' \"),e.push(\"<span class='\",f,\"'\",l,\">\",a,\"</span>\")}else e.push(a);return t+r.length},this.renderIndentGuide=function(e,t,n){var r=t.search(this.$indentGuideRe);return r<=0||r>=n?t:t[0]==\" \"?(r-=r%this.tabSize,e.push(s.stringRepeat(this.$tabStrings[\" \"],r/this.tabSize)),t.substr(r)):t[0]==\"\t\"?(e.push(s.stringRepeat(this.$tabStrings[\"\t\"],r)),t.substr(r)):t},this.$renderWrappedLine=function(e,t,n,r){var i=0,o=0,u=n[0],a=0;for(var f=0;f<t.length;f++){var l=t[f],c=l.value;if(f==0&&this.displayIndentGuides){i=c.length,c=this.renderIndentGuide(e,c,u);if(!c)continue;i-=c.length}if(i+c.length<u)a=this.$renderToken(e,a,l,c),i+=c.length;else{while(i+c.length>=u)a=this.$renderToken(e,a,l,c.substring(0,u-i)),c=c.substring(u-i),i=u,r||e.push(\"</div>\",\"<div class='ace_line' style='height:\",this.config.lineHeight,\"px'>\"),e.push(s.stringRepeat(\"\\u00a0\",n.indent)),o++,a=0,u=n[o]||Number.MAX_VALUE;c.length!=0&&(i+=c.length,a=this.$renderToken(e,a,l,c))}}},this.$renderSimpleLine=function(e,t){var n=0,r=t[0],i=r.value;this.displayIndentGuides&&(i=this.renderIndentGuide(e,i)),i&&(n=this.$renderToken(e,n,r,i));for(var s=1;s<t.length;s++)r=t[s],i=r.value,n=this.$renderToken(e,n,r,i)},this.$renderLine=function(e,t,n,r){!r&&r!=0&&(r=this.session.getFoldLine(t));if(r)var i=this.$getFoldLineTokens(t,r);else var i=this.session.getTokens(t);n||e.push(\"<div class='ace_line' style='height:\",this.config.lineHeight*(this.$useLineGroups()?1:this.session.getRowLength(t)),\"px'>\");if(i.length){var s=this.session.getRowSplitData(t);s&&s.length?this.$renderWrappedLine(e,i,s,n):this.$renderSimpleLine(e,i)}this.showInvisibles&&(r&&(t=r.end.row),e.push(\"<span class='ace_invisible ace_invisible_eol'>\",t==this.session.getLength()-1?this.EOF_CHAR:this.EOL_CHAR,\"</span>\")),n||e.push(\"</div>\")},this.$getFoldLineTokens=function(e,t){function i(e,t,n){var i=0,s=0;while(s+e[i].value.length<t){s+=e[i].value.length,i++;if(i==e.length)return}if(s!=t){var o=e[i].value.substring(t-s);o.length>n-t&&(o=o.substring(0,n-t)),r.push({type:e[i].type,value:o}),s=t+o.length,i+=1}while(s<n&&i<e.length){var o=e[i].value;o.length+s>n?r.push({type:e[i].type,value:o.substring(0,n-s)}):r.push(e[i]),s+=o.length,i+=1}}var n=this.session,r=[],s=n.getTokens(e);return t.walk(function(e,t,o,u,a){e!=null?r.push({type:\"fold\",value:e}):(a&&(s=n.getTokens(t)),s.length&&i(s,u,o))},t.end.row,this.session.getLine(t.end.row).length),r},this.$useLineGroups=function(){return this.session.getUseWrapMode()},this.destroy=function(){clearInterval(this.$pollSizeChangesTimer),this.$measureNode&&this.$measureNode.parentNode.removeChild(this.$measureNode),delete this.$measureNode}}).call(a.prototype),t.Text=a}),define(\"ace/layer/cursor\",[\"require\",\"exports\",\"module\",\"ace/lib/dom\"],function(e,t,n){\"use strict\";var r=e(\"../lib/dom\"),i,s=function(e){this.element=r.createElement(\"div\"),this.element.className=\"ace_layer ace_cursor-layer\",e.appendChild(this.element),i===undefined&&(i=!(\"opacity\"in this.element.style)),this.isVisible=!1,this.isBlinking=!0,this.blinkInterval=1e3,this.smoothBlinking=!1,this.cursors=[],this.cursor=this.addCursor(),r.addCssClass(this.element,\"ace_hidden-cursors\"),this.$updateCursors=(i?this.$updateVisibility:this.$updateOpacity).bind(this)};(function(){this.$updateVisibility=function(e){var t=this.cursors;for(var n=t.length;n--;)t[n].style.visibility=e?\"\":\"hidden\"},this.$updateOpacity=function(e){var t=this.cursors;for(var n=t.length;n--;)t[n].style.opacity=e?\"\":\"0\"},this.$padding=0,this.setPadding=function(e){this.$padding=e},this.setSession=function(e){this.session=e},this.setBlinking=function(e){e!=this.isBlinking&&(this.isBlinking=e,this.restartTimer())},this.setBlinkInterval=function(e){e!=this.blinkInterval&&(this.blinkInterval=e,this.restartTimer())},this.setSmoothBlinking=function(e){e!=this.smoothBlinking&&!i&&(this.smoothBlinking=e,r.setCssClass(this.element,\"ace_smooth-blinking\",e),this.$updateCursors(!0),this.$updateCursors=this.$updateOpacity.bind(this),this.restartTimer())},this.addCursor=function(){var e=r.createElement(\"div\");return e.className=\"ace_cursor\",this.element.appendChild(e),this.cursors.push(e),e},this.removeCursor=function(){if(this.cursors.length>1){var e=this.cursors.pop();return e.parentNode.removeChild(e),e}},this.hideCursor=function(){this.isVisible=!1,r.addCssClass(this.element,\"ace_hidden-cursors\"),this.restartTimer()},this.showCursor=function(){this.isVisible=!0,r.removeCssClass(this.element,\"ace_hidden-cursors\"),this.restartTimer()},this.restartTimer=function(){var e=this.$updateCursors;clearInterval(this.intervalId),clearTimeout(this.timeoutId),this.smoothBlinking&&r.removeCssClass(this.element,\"ace_smooth-blinking\"),e(!0);if(!this.isBlinking||!this.blinkInterval||!this.isVisible)return;this.smoothBlinking&&setTimeout(function(){r.addCssClass(this.element,\"ace_smooth-blinking\")}.bind(this));var t=function(){this.timeoutId=setTimeout(function(){e(!1)},.6*this.blinkInterval)}.bind(this);this.intervalId=setInterval(function(){e(!0),t()},this.blinkInterval),t()},this.getPixelPosition=function(e,t){if(!this.config||!this.session)return{left:0,top:0};e||(e=this.session.selection.getCursor());var n=this.session.documentToScreenPosition(e),r=this.$padding+(this.session.$bidiHandler.isBidiRow(n.row,e.row)?this.session.$bidiHandler.getPosLeft(n.column):n.column*this.config.characterWidth),i=(n.row-(t?this.config.firstRowScreen:0))*this.config.lineHeight;return{left:r,top:i}},this.update=function(e){this.config=e;var t=this.session.$selectionMarkers,n=0,r=0;if(t===undefined||t.length===0)t=[{cursor:null}];for(var n=0,i=t.length;n<i;n++){var s=this.getPixelPosition(t[n].cursor,!0);if((s.top>e.height+e.offset||s.top<0)&&n>1)continue;var o=(this.cursors[r++]||this.addCursor()).style;this.drawCursor?this.drawCursor(o,s,e,t[n],this.session):(o.left=s.left+\"px\",o.top=s.top+\"px\",o.width=e.characterWidth+\"px\",o.height=e.lineHeight+\"px\")}while(this.cursors.length>r)this.removeCursor();var u=this.session.getOverwrite();this.$setOverwrite(u),this.$pixelPos=s,this.restartTimer()},this.drawCursor=null,this.$setOverwrite=function(e){e!=this.overwrite&&(this.overwrite=e,e?r.addCssClass(this.element,\"ace_overwrite-cursors\"):r.removeCssClass(this.element,\"ace_overwrite-cursors\"))},this.destroy=function(){clearInterval(this.intervalId),clearTimeout(this.timeoutId)}}).call(s.prototype),t.Cursor=s}),define(\"ace/scrollbar\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/dom\",\"ace/lib/event\",\"ace/lib/event_emitter\"],function(e,t,n){\"use strict\";var r=e(\"./lib/oop\"),i=e(\"./lib/dom\"),s=e(\"./lib/event\"),o=e(\"./lib/event_emitter\").EventEmitter,u=32768,a=function(e){this.element=i.createElement(\"div\"),this.element.className=\"ace_scrollbar ace_scrollbar\"+this.classSuffix,this.inner=i.createElement(\"div\"),this.inner.className=\"ace_scrollbar-inner\",this.element.appendChild(this.inner),e.appendChild(this.element),this.setVisible(!1),this.skipEvent=!1,s.addListener(this.element,\"scroll\",this.onScroll.bind(this)),s.addListener(this.element,\"mousedown\",s.preventDefault)};(function(){r.implement(this,o),this.setVisible=function(e){this.element.style.display=e?\"\":\"none\",this.isVisible=e,this.coeff=1}}).call(a.prototype);var f=function(e,t){a.call(this,e),this.scrollTop=0,this.scrollHeight=0,t.$scrollbarWidth=this.width=i.scrollbarWidth(e.ownerDocument),this.inner.style.width=this.element.style.width=(this.width||15)+5+\"px\",this.$minWidth=0};r.inherits(f,a),function(){this.classSuffix=\"-v\",this.onScroll=function(){if(!this.skipEvent){this.scrollTop=this.element.scrollTop;if(this.coeff!=1){var e=this.element.clientHeight/this.scrollHeight;this.scrollTop=this.scrollTop*(1-e)/(this.coeff-e)}this._emit(\"scroll\",{data:this.scrollTop})}this.skipEvent=!1},this.getWidth=function(){return Math.max(this.isVisible?this.width:0,this.$minWidth||0)},this.setHeight=function(e){this.element.style.height=e+\"px\"},this.setInnerHeight=this.setScrollHeight=function(e){this.scrollHeight=e,e>u?(this.coeff=u/e,e=u):this.coeff!=1&&(this.coeff=1),this.inner.style.height=e+\"px\"},this.setScrollTop=function(e){this.scrollTop!=e&&(this.skipEvent=!0,this.scrollTop=e,this.element.scrollTop=e*this.coeff)}}.call(f.prototype);var l=function(e,t){a.call(this,e),this.scrollLeft=0,this.height=t.$scrollbarWidth,this.inner.style.height=this.element.style.height=(this.height||15)+5+\"px\"};r.inherits(l,a),function(){this.classSuffix=\"-h\",this.onScroll=function(){this.skipEvent||(this.scrollLeft=this.element.scrollLeft,this._emit(\"scroll\",{data:this.scrollLeft})),this.skipEvent=!1},this.getHeight=function(){return this.isVisible?this.height:0},this.setWidth=function(e){this.element.style.width=e+\"px\"},this.setInnerWidth=function(e){this.inner.style.width=e+\"px\"},this.setScrollWidth=function(e){this.inner.style.width=e+\"px\"},this.setScrollLeft=function(e){this.scrollLeft!=e&&(this.skipEvent=!0,this.scrollLeft=this.element.scrollLeft=e)}}.call(l.prototype),t.ScrollBar=f,t.ScrollBarV=f,t.ScrollBarH=l,t.VScrollBar=f,t.HScrollBar=l}),define(\"ace/renderloop\",[\"require\",\"exports\",\"module\",\"ace/lib/event\"],function(e,t,n){\"use strict\";var r=e(\"./lib/event\"),i=function(e,t){this.onRender=e,this.pending=!1,this.changes=0,this.window=t||window};(function(){this.schedule=function(e){this.changes=this.changes|e;if(!this.pending&&this.changes){this.pending=!0;var t=this;r.nextFrame(function(){t.pending=!1;var e;while(e=t.changes)t.changes=0,t.onRender(e)},this.window)}}}).call(i.prototype),t.RenderLoop=i}),define(\"ace/layer/font_metrics\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/dom\",\"ace/lib/lang\",\"ace/lib/useragent\",\"ace/lib/event_emitter\"],function(e,t,n){var r=e(\"../lib/oop\"),i=e(\"../lib/dom\"),s=e(\"../lib/lang\"),o=e(\"../lib/useragent\"),u=e(\"../lib/event_emitter\").EventEmitter,a=0,f=t.FontMetrics=function(e){this.el=i.createElement(\"div\"),this.$setMeasureNodeStyles(this.el.style,!0),this.$main=i.createElement(\"div\"),this.$setMeasureNodeStyles(this.$main.style),this.$measureNode=i.createElement(\"div\"),this.$setMeasureNodeStyles(this.$measureNode.style),this.el.appendChild(this.$main),this.el.appendChild(this.$measureNode),e.appendChild(this.el),a||this.$testFractionalRect(),this.$measureNode.innerHTML=s.stringRepeat(\"X\",a),this.$characterSize={width:0,height:0},this.checkForSizeChanges()};(function(){r.implement(this,u),this.$characterSize={width:0,height:0},this.$testFractionalRect=function(){var e=i.createElement(\"div\");this.$setMeasureNodeStyles(e.style),e.style.width=\"0.2px\",document.documentElement.appendChild(e);var t=e.getBoundingClientRect().width;t>0&&t<1?a=50:a=100,e.parentNode.removeChild(e)},this.$setMeasureNodeStyles=function(e,t){e.width=e.height=\"auto\",e.left=e.top=\"0px\",e.visibility=\"hidden\",e.position=\"absolute\",e.whiteSpace=\"pre\",o.isIE<8?e[\"font-family\"]=\"inherit\":e.font=\"inherit\",e.overflow=t?\"hidden\":\"visible\"},this.checkForSizeChanges=function(){var e=this.$measureSizes();if(e&&(this.$characterSize.width!==e.width||this.$characterSize.height!==e.height)){this.$measureNode.style.fontWeight=\"bold\";var t=this.$measureSizes();this.$measureNode.style.fontWeight=\"\",this.$characterSize=e,this.charSizes=Object.create(null),this.allowBoldFonts=t&&t.width===e.width&&t.height===e.height,this._emit(\"changeCharacterSize\",{data:e})}},this.$pollSizeChanges=function(){if(this.$pollSizeChangesTimer)return this.$pollSizeChangesTimer;var e=this;return this.$pollSizeChangesTimer=setInterval(function(){e.checkForSizeChanges()},500)},this.setPolling=function(e){e?this.$pollSizeChanges():this.$pollSizeChangesTimer&&(clearInterval(this.$pollSizeChangesTimer),this.$pollSizeChangesTimer=0)},this.$measureSizes=function(){if(a===50){var e=null;try{e=this.$measureNode.getBoundingClientRect()}catch(t){e={width:0,height:0}}var n={height:e.height,width:e.width/a}}else var n={height:this.$measureNode.clientHeight,width:this.$measureNode.clientWidth/a};return n.width===0||n.height===0?null:n},this.$measureCharWidth=function(e){this.$main.innerHTML=s.stringRepeat(e,a);var t=this.$main.getBoundingClientRect();return t.width/a},this.getCharacterWidth=function(e){var t=this.charSizes[e];return t===undefined&&(t=this.charSizes[e]=this.$measureCharWidth(e)/this.$characterSize.width),t},this.destroy=function(){clearInterval(this.$pollSizeChangesTimer),this.el&&this.el.parentNode&&this.el.parentNode.removeChild(this.el)}}).call(f.prototype)}),define(\"ace/virtual_renderer\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/dom\",\"ace/config\",\"ace/lib/useragent\",\"ace/layer/gutter\",\"ace/layer/marker\",\"ace/layer/text\",\"ace/layer/cursor\",\"ace/scrollbar\",\"ace/scrollbar\",\"ace/renderloop\",\"ace/layer/font_metrics\",\"ace/lib/event_emitter\"],function(e,t,n){\"use strict\";var r=e(\"./lib/oop\"),i=e(\"./lib/dom\"),s=e(\"./config\"),o=e(\"./lib/useragent\"),u=e(\"./layer/gutter\").Gutter,a=e(\"./layer/marker\").Marker,f=e(\"./layer/text\").Text,l=e(\"./layer/cursor\").Cursor,c=e(\"./scrollbar\").HScrollBar,h=e(\"./scrollbar\").VScrollBar,p=e(\"./renderloop\").RenderLoop,d=e(\"./layer/font_metrics\").FontMetrics,v=e(\"./lib/event_emitter\").EventEmitter,m='.ace_editor {position: relative;overflow: hidden;font: 12px/normal \\'Monaco\\', \\'Menlo\\', \\'Ubuntu Mono\\', \\'Consolas\\', \\'source-code-pro\\', monospace;direction: ltr;text-align: left;-webkit-tap-highlight-color: rgba(0, 0, 0, 0);}.ace_scroller {position: absolute;overflow: hidden;top: 0;bottom: 0;background-color: inherit;-ms-user-select: none;-moz-user-select: none;-webkit-user-select: none;user-select: none;cursor: text;}.ace_content {position: absolute;-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;min-width: 100%;}.ace_dragging .ace_scroller:before{position: absolute;top: 0;left: 0;right: 0;bottom: 0;content: \\'\\';background: rgba(250, 250, 250, 0.01);z-index: 1000;}.ace_dragging.ace_dark .ace_scroller:before{background: rgba(0, 0, 0, 0.01);}.ace_selecting, .ace_selecting * {cursor: text !important;}.ace_gutter {position: absolute;overflow : hidden;width: auto;top: 0;bottom: 0;left: 0;cursor: default;z-index: 4;-ms-user-select: none;-moz-user-select: none;-webkit-user-select: none;user-select: none;}.ace_gutter-active-line {position: absolute;left: 0;right: 0;}.ace_scroller.ace_scroll-left {box-shadow: 17px 0 16px -16px rgba(0, 0, 0, 0.4) inset;}.ace_gutter-cell {padding-left: 19px;padding-right: 6px;background-repeat: no-repeat;}.ace_gutter-cell.ace_error {background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAABOFBMVEX/////////QRswFAb/Ui4wFAYwFAYwFAaWGAfDRymzOSH/PxswFAb/SiUwFAYwFAbUPRvjQiDllog5HhHdRybsTi3/Tyv9Tir+Syj/UC3////XurebMBIwFAb/RSHbPx/gUzfdwL3kzMivKBAwFAbbvbnhPx66NhowFAYwFAaZJg8wFAaxKBDZurf/RB6mMxb/SCMwFAYwFAbxQB3+RB4wFAb/Qhy4Oh+4QifbNRcwFAYwFAYwFAb/QRzdNhgwFAYwFAbav7v/Uy7oaE68MBK5LxLewr/r2NXewLswFAaxJw4wFAbkPRy2PyYwFAaxKhLm1tMwFAazPiQwFAaUGAb/QBrfOx3bvrv/VC/maE4wFAbRPBq6MRO8Qynew8Dp2tjfwb0wFAbx6eju5+by6uns4uH9/f36+vr/GkHjAAAAYnRSTlMAGt+64rnWu/bo8eAA4InH3+DwoN7j4eLi4xP99Nfg4+b+/u9B/eDs1MD1mO7+4PHg2MXa347g7vDizMLN4eG+Pv7i5evs/v79yu7S3/DV7/498Yv24eH+4ufQ3Ozu/v7+y13sRqwAAADLSURBVHjaZc/XDsFgGIBhtDrshlitmk2IrbHFqL2pvXf/+78DPokj7+Fz9qpU/9UXJIlhmPaTaQ6QPaz0mm+5gwkgovcV6GZzd5JtCQwgsxoHOvJO15kleRLAnMgHFIESUEPmawB9ngmelTtipwwfASilxOLyiV5UVUyVAfbG0cCPHig+GBkzAENHS0AstVF6bacZIOzgLmxsHbt2OecNgJC83JERmePUYq8ARGkJx6XtFsdddBQgZE2nPR6CICZhawjA4Fb/chv+399kfR+MMMDGOQAAAABJRU5ErkJggg==\");background-repeat: no-repeat;background-position: 2px center;}.ace_gutter-cell.ace_warning {background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAmVBMVEX///8AAAD///8AAAAAAABPSzb/5sAAAAB/blH/73z/ulkAAAAAAAD85pkAAAAAAAACAgP/vGz/rkDerGbGrV7/pkQICAf////e0IsAAAD/oED/qTvhrnUAAAD/yHD/njcAAADuv2r/nz//oTj/p064oGf/zHAAAAA9Nir/tFIAAAD/tlTiuWf/tkIAAACynXEAAAAAAAAtIRW7zBpBAAAAM3RSTlMAABR1m7RXO8Ln31Z36zT+neXe5OzooRDfn+TZ4p3h2hTf4t3k3ucyrN1K5+Xaks52Sfs9CXgrAAAAjklEQVR42o3PbQ+CIBQFYEwboPhSYgoYunIqqLn6/z8uYdH8Vmdnu9vz4WwXgN/xTPRD2+sgOcZjsge/whXZgUaYYvT8QnuJaUrjrHUQreGczuEafQCO/SJTufTbroWsPgsllVhq3wJEk2jUSzX3CUEDJC84707djRc5MTAQxoLgupWRwW6UB5fS++NV8AbOZgnsC7BpEAAAAABJRU5ErkJggg==\");background-position: 2px center;}.ace_gutter-cell.ace_info {background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAAAAAA6mKC9AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAJ0Uk5TAAB2k804AAAAPklEQVQY02NgIB68QuO3tiLznjAwpKTgNyDbMegwisCHZUETUZV0ZqOquBpXj2rtnpSJT1AEnnRmL2OgGgAAIKkRQap2htgAAAAASUVORK5CYII=\");background-position: 2px center;}.ace_dark .ace_gutter-cell.ace_info {background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAJFBMVEUAAAChoaGAgIAqKiq+vr6tra1ZWVmUlJSbm5s8PDxubm56enrdgzg3AAAAAXRSTlMAQObYZgAAAClJREFUeNpjYMAPdsMYHegyJZFQBlsUlMFVCWUYKkAZMxZAGdxlDMQBAG+TBP4B6RyJAAAAAElFTkSuQmCC\");}.ace_scrollbar {position: absolute;right: 0;bottom: 0;z-index: 6;}.ace_scrollbar-inner {position: absolute;cursor: text;left: 0;top: 0;}.ace_scrollbar-v{overflow-x: hidden;overflow-y: scroll;top: 0;}.ace_scrollbar-h {overflow-x: scroll;overflow-y: hidden;left: 0;}.ace_print-margin {position: absolute;height: 100%;}.ace_text-input {position: absolute;z-index: 0;width: 0.5em;height: 1em;opacity: 0;background: transparent;-moz-appearance: none;appearance: none;border: none;resize: none;outline: none;overflow: hidden;font: inherit;padding: 0 1px;margin: 0 -1px;text-indent: -1em;-ms-user-select: text;-moz-user-select: text;-webkit-user-select: text;user-select: text;white-space: pre!important;}.ace_text-input.ace_composition {background: inherit;color: inherit;z-index: 1000;opacity: 1;text-indent: 0;}.ace_layer {z-index: 1;position: absolute;overflow: hidden;word-wrap: normal;white-space: pre;height: 100%;width: 100%;-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;pointer-events: none;}.ace_gutter-layer {position: relative;width: auto;text-align: right;pointer-events: auto;}.ace_text-layer {font: inherit !important;}.ace_cjk {display: inline-block;text-align: center;}.ace_cursor-layer {z-index: 4;}.ace_cursor {z-index: 4;position: absolute;-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;border-left: 2px solid;transform: translatez(0);}.ace_multiselect .ace_cursor {border-left-width: 1px;}.ace_slim-cursors .ace_cursor {border-left-width: 1px;}.ace_overwrite-cursors .ace_cursor {border-left-width: 0;border-bottom: 1px solid;}.ace_hidden-cursors .ace_cursor {opacity: 0.2;}.ace_smooth-blinking .ace_cursor {-webkit-transition: opacity 0.18s;transition: opacity 0.18s;}.ace_marker-layer .ace_step, .ace_marker-layer .ace_stack {position: absolute;z-index: 3;}.ace_marker-layer .ace_selection {position: absolute;z-index: 5;}.ace_marker-layer .ace_bracket {position: absolute;z-index: 6;}.ace_marker-layer .ace_active-line {position: absolute;z-index: 2;}.ace_marker-layer .ace_selected-word {position: absolute;z-index: 4;-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;}.ace_line .ace_fold {-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;display: inline-block;height: 11px;margin-top: -2px;vertical-align: middle;background-image:url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII=\"),url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACJJREFUeNpi+P//fxgTAwPDBxDxD078RSX+YeEyDFMCIMAAI3INmXiwf2YAAAAASUVORK5CYII=\");background-repeat: no-repeat, repeat-x;background-position: center center, top left;color: transparent;border: 1px solid black;border-radius: 2px;cursor: pointer;pointer-events: auto;}.ace_dark .ace_fold {}.ace_fold:hover{background-image:url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII=\"),url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACBJREFUeNpi+P//fz4TAwPDZxDxD5X4i5fLMEwJgAADAEPVDbjNw87ZAAAAAElFTkSuQmCC\");}.ace_tooltip {background-color: #FFF;background-image: -webkit-linear-gradient(top, transparent, rgba(0, 0, 0, 0.1));background-image: linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.1));border: 1px solid gray;border-radius: 1px;box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);color: black;max-width: 100%;padding: 3px 4px;position: fixed;z-index: 999999;-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;cursor: default;white-space: pre;word-wrap: break-word;line-height: normal;font-style: normal;font-weight: normal;letter-spacing: normal;pointer-events: none;}.ace_folding-enabled > .ace_gutter-cell {padding-right: 13px;}.ace_fold-widget {-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;margin: 0 -12px 0 1px;display: none;width: 11px;vertical-align: top;background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42mWKsQ0AMAzC8ixLlrzQjzmBiEjp0A6WwBCSPgKAXoLkqSot7nN3yMwR7pZ32NzpKkVoDBUxKAAAAABJRU5ErkJggg==\");background-repeat: no-repeat;background-position: center;border-radius: 3px;border: 1px solid transparent;cursor: pointer;}.ace_folding-enabled .ace_fold-widget {display: inline-block;   }.ace_fold-widget.ace_end {background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42m3HwQkAMAhD0YzsRchFKI7sAikeWkrxwScEB0nh5e7KTPWimZki4tYfVbX+MNl4pyZXejUO1QAAAABJRU5ErkJggg==\");}.ace_fold-widget.ace_closed {background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAGCAYAAAAG5SQMAAAAOUlEQVR42jXKwQkAMAgDwKwqKD4EwQ26sSOkVWjgIIHAzPiCgaqiqnJHZnKICBERHN194O5b9vbLuAVRL+l0YWnZAAAAAElFTkSuQmCCXA==\");}.ace_fold-widget:hover {border: 1px solid rgba(0, 0, 0, 0.3);background-color: rgba(255, 255, 255, 0.2);box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);}.ace_fold-widget:active {border: 1px solid rgba(0, 0, 0, 0.4);background-color: rgba(0, 0, 0, 0.05);box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);}.ace_dark .ace_fold-widget {background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHklEQVQIW2P4//8/AzoGEQ7oGCaLLAhWiSwB146BAQCSTPYocqT0AAAAAElFTkSuQmCC\");}.ace_dark .ace_fold-widget.ace_end {background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAH0lEQVQIW2P4//8/AxQ7wNjIAjDMgC4AxjCVKBirIAAF0kz2rlhxpAAAAABJRU5ErkJggg==\");}.ace_dark .ace_fold-widget.ace_closed {background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAHElEQVQIW2P4//+/AxAzgDADlOOAznHAKgPWAwARji8UIDTfQQAAAABJRU5ErkJggg==\");}.ace_dark .ace_fold-widget:hover {box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);background-color: rgba(255, 255, 255, 0.1);}.ace_dark .ace_fold-widget:active {box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);}.ace_fold-widget.ace_invalid {background-color: #FFB4B4;border-color: #DE5555;}.ace_fade-fold-widgets .ace_fold-widget {-webkit-transition: opacity 0.4s ease 0.05s;transition: opacity 0.4s ease 0.05s;opacity: 0;}.ace_fade-fold-widgets:hover .ace_fold-widget {-webkit-transition: opacity 0.05s ease 0.05s;transition: opacity 0.05s ease 0.05s;opacity:1;}.ace_underline {text-decoration: underline;}.ace_bold {font-weight: bold;}.ace_nobold .ace_bold {font-weight: normal;}.ace_italic {font-style: italic;}.ace_error-marker {background-color: rgba(255, 0, 0,0.2);position: absolute;z-index: 9;}.ace_highlight-marker {background-color: rgba(255, 255, 0,0.2);position: absolute;z-index: 8;}.ace_br1 {border-top-left-radius    : 3px;}.ace_br2 {border-top-right-radius   : 3px;}.ace_br3 {border-top-left-radius    : 3px; border-top-right-radius:    3px;}.ace_br4 {border-bottom-right-radius: 3px;}.ace_br5 {border-top-left-radius    : 3px; border-bottom-right-radius: 3px;}.ace_br6 {border-top-right-radius   : 3px; border-bottom-right-radius: 3px;}.ace_br7 {border-top-left-radius    : 3px; border-top-right-radius:    3px; border-bottom-right-radius: 3px;}.ace_br8 {border-bottom-left-radius : 3px;}.ace_br9 {border-top-left-radius    : 3px; border-bottom-left-radius:  3px;}.ace_br10{border-top-right-radius   : 3px; border-bottom-left-radius:  3px;}.ace_br11{border-top-left-radius    : 3px; border-top-right-radius:    3px; border-bottom-left-radius:  3px;}.ace_br12{border-bottom-right-radius: 3px; border-bottom-left-radius:  3px;}.ace_br13{border-top-left-radius    : 3px; border-bottom-right-radius: 3px; border-bottom-left-radius:  3px;}.ace_br14{border-top-right-radius   : 3px; border-bottom-right-radius: 3px; border-bottom-left-radius:  3px;}.ace_br15{border-top-left-radius    : 3px; border-top-right-radius:    3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}.ace_text-input-ios {position: absolute !important;top: -100000px !important;left: -100000px !important;}';i.importCssString(m,\"ace_editor.css\");var g=function(e,t){var n=this;this.container=e||i.createElement(\"div\"),this.$keepTextAreaAtCursor=!o.isOldIE,i.addCssClass(this.container,\"ace_editor\"),this.setTheme(t),this.$gutter=i.createElement(\"div\"),this.$gutter.className=\"ace_gutter\",this.container.appendChild(this.$gutter),this.$gutter.setAttribute(\"aria-hidden\",!0),this.scroller=i.createElement(\"div\"),this.scroller.className=\"ace_scroller\",this.container.appendChild(this.scroller),this.content=i.createElement(\"div\"),this.content.className=\"ace_content\",this.scroller.appendChild(this.content),this.$gutterLayer=new u(this.$gutter),this.$gutterLayer.on(\"changeGutterWidth\",this.onGutterResize.bind(this)),this.$markerBack=new a(this.content);var r=this.$textLayer=new f(this.content);this.canvas=r.element,this.$markerFront=new a(this.content),this.$cursorLayer=new l(this.content),this.$horizScroll=!1,this.$vScroll=!1,this.scrollBar=this.scrollBarV=new h(this.container,this),this.scrollBarH=new c(this.container,this),this.scrollBarV.addEventListener(\"scroll\",function(e){n.$scrollAnimation||n.session.setScrollTop(e.data-n.scrollMargin.top)}),this.scrollBarH.addEventListener(\"scroll\",function(e){n.$scrollAnimation||n.session.setScrollLeft(e.data-n.scrollMargin.left)}),this.scrollTop=0,this.scrollLeft=0,this.cursorPos={row:0,column:0},this.$fontMetrics=new d(this.container),this.$textLayer.$setFontMetrics(this.$fontMetrics),this.$textLayer.addEventListener(\"changeCharacterSize\",function(e){n.updateCharacterSize(),n.onResize(!0,n.gutterWidth,n.$size.width,n.$size.height),n._signal(\"changeCharacterSize\",e)}),this.$size={width:0,height:0,scrollerHeight:0,scrollerWidth:0,$dirty:!0},this.layerConfig={width:1,padding:0,firstRow:0,firstRowScreen:0,lastRow:0,lineHeight:0,characterWidth:0,minHeight:1,maxHeight:1,offset:0,height:1,gutterOffset:1},this.scrollMargin={left:0,right:0,top:0,bottom:0,v:0,h:0},this.$loop=new p(this.$renderChanges.bind(this),this.container.ownerDocument.defaultView),this.$loop.schedule(this.CHANGE_FULL),this.updateCharacterSize(),this.setPadding(4),s.resetOptions(this),s._emit(\"renderer\",this)};(function(){this.CHANGE_CURSOR=1,this.CHANGE_MARKER=2,this.CHANGE_GUTTER=4,this.CHANGE_SCROLL=8,this.CHANGE_LINES=16,this.CHANGE_TEXT=32,this.CHANGE_SIZE=64,this.CHANGE_MARKER_BACK=128,this.CHANGE_MARKER_FRONT=256,this.CHANGE_FULL=512,this.CHANGE_H_SCROLL=1024,r.implement(this,v),this.updateCharacterSize=function(){this.$textLayer.allowBoldFonts!=this.$allowBoldFonts&&(this.$allowBoldFonts=this.$textLayer.allowBoldFonts,this.setStyle(\"ace_nobold\",!this.$allowBoldFonts)),this.layerConfig.characterWidth=this.characterWidth=this.$textLayer.getCharacterWidth(),this.layerConfig.lineHeight=this.lineHeight=this.$textLayer.getLineHeight(),this.$updatePrintMargin()},this.setSession=function(e){this.session&&this.session.doc.off(\"changeNewLineMode\",this.onChangeNewLineMode),this.session=e,e&&this.scrollMargin.top&&e.getScrollTop()<=0&&e.setScrollTop(-this.scrollMargin.top),this.$cursorLayer.setSession(e),this.$markerBack.setSession(e),this.$markerFront.setSession(e),this.$gutterLayer.setSession(e),this.$textLayer.setSession(e);if(!e)return;this.$loop.schedule(this.CHANGE_FULL),this.session.$setFontMetrics(this.$fontMetrics),this.scrollBarH.scrollLeft=this.scrollBarV.scrollTop=null,this.onChangeNewLineMode=this.onChangeNewLineMode.bind(this),this.onChangeNewLineMode(),this.session.doc.on(\"changeNewLineMode\",this.onChangeNewLineMode)},this.updateLines=function(e,t,n){t===undefined&&(t=Infinity),this.$changedLines?(this.$changedLines.firstRow>e&&(this.$changedLines.firstRow=e),this.$changedLines.lastRow<t&&(this.$changedLines.lastRow=t)):this.$changedLines={firstRow:e,lastRow:t};if(this.$changedLines.lastRow<this.layerConfig.firstRow){if(!n)return;this.$changedLines.lastRow=this.layerConfig.lastRow}if(this.$changedLines.firstRow>this.layerConfig.lastRow)return;this.$loop.schedule(this.CHANGE_LINES)},this.onChangeNewLineMode=function(){this.$loop.schedule(this.CHANGE_TEXT),this.$textLayer.$updateEolChar(),this.session.$bidiHandler.setEolChar(this.$textLayer.EOL_CHAR)},this.onChangeTabSize=function(){this.$loop.schedule(this.CHANGE_TEXT|this.CHANGE_MARKER),this.$textLayer.onChangeTabSize()},this.updateText=function(){this.$loop.schedule(this.CHANGE_TEXT)},this.updateFull=function(e){e?this.$renderChanges(this.CHANGE_FULL,!0):this.$loop.schedule(this.CHANGE_FULL)},this.updateFontSize=function(){this.$textLayer.checkForSizeChanges()},this.$changes=0,this.$updateSizeAsync=function(){this.$loop.pending?this.$size.$dirty=!0:this.onResize()},this.onResize=function(e,t,n,r){if(this.resizing>2)return;this.resizing>0?this.resizing++:this.resizing=e?1:0;var i=this.container;r||(r=i.clientHeight||i.scrollHeight),n||(n=i.clientWidth||i.scrollWidth);var s=this.$updateCachedSize(e,t,n,r);if(!this.$size.scrollerHeight||!n&&!r)return this.resizing=0;e&&(this.$gutterLayer.$padding=null),e?this.$renderChanges(s|this.$changes,!0):this.$loop.schedule(s|this.$changes),this.resizing&&(this.resizing=0),this.scrollBarV.scrollLeft=this.scrollBarV.scrollTop=null},this.$updateCachedSize=function(e,t,n,r){r-=this.$extraHeight||0;var i=0,s=this.$size,o={width:s.width,height:s.height,scrollerHeight:s.scrollerHeight,scrollerWidth:s.scrollerWidth};r&&(e||s.height!=r)&&(s.height=r,i|=this.CHANGE_SIZE,s.scrollerHeight=s.height,this.$horizScroll&&(s.scrollerHeight-=this.scrollBarH.getHeight()),this.scrollBarV.element.style.bottom=this.scrollBarH.getHeight()+\"px\",i|=this.CHANGE_SCROLL);if(n&&(e||s.width!=n)){i|=this.CHANGE_SIZE,s.width=n,t==null&&(t=this.$showGutter?this.$gutter.offsetWidth:0),this.gutterWidth=t,this.scrollBarH.element.style.left=this.scroller.style.left=t+\"px\",s.scrollerWidth=Math.max(0,n-t-this.scrollBarV.getWidth()),this.scrollBarH.element.style.right=this.scroller.style.right=this.scrollBarV.getWidth()+\"px\",this.scroller.style.bottom=this.scrollBarH.getHeight()+\"px\";if(this.session&&this.session.getUseWrapMode()&&this.adjustWrapLimit()||e)i|=this.CHANGE_FULL}return s.$dirty=!n||!r,i&&this._signal(\"resize\",o),i},this.onGutterResize=function(){var e=this.$showGutter?this.$gutter.offsetWidth:0;e!=this.gutterWidth&&(this.$changes|=this.$updateCachedSize(!0,e,this.$size.width,this.$size.height)),this.session.getUseWrapMode()&&this.adjustWrapLimit()?this.$loop.schedule(this.CHANGE_FULL):this.$size.$dirty?this.$loop.schedule(this.CHANGE_FULL):(this.$computeLayerConfig(),this.$loop.schedule(this.CHANGE_MARKER))},this.adjustWrapLimit=function(){var e=this.$size.scrollerWidth-this.$padding*2,t=Math.floor(e/this.characterWidth);return this.session.adjustWrapLimit(t,this.$showPrintMargin&&this.$printMarginColumn)},this.setAnimatedScroll=function(e){this.setOption(\"animatedScroll\",e)},this.getAnimatedScroll=function(){return this.$animatedScroll},this.setShowInvisibles=function(e){this.setOption(\"showInvisibles\",e),this.session.$bidiHandler.setShowInvisibles(e)},this.getShowInvisibles=function(){return this.getOption(\"showInvisibles\")},this.getDisplayIndentGuides=function(){return this.getOption(\"displayIndentGuides\")},this.setDisplayIndentGuides=function(e){this.setOption(\"displayIndentGuides\",e)},this.setShowPrintMargin=function(e){this.setOption(\"showPrintMargin\",e)},this.getShowPrintMargin=function(){return this.getOption(\"showPrintMargin\")},this.setPrintMarginColumn=function(e){this.setOption(\"printMarginColumn\",e)},this.getPrintMarginColumn=function(){return this.getOption(\"printMarginColumn\")},this.getShowGutter=function(){return this.getOption(\"showGutter\")},this.setShowGutter=function(e){return this.setOption(\"showGutter\",e)},this.getFadeFoldWidgets=function(){return this.getOption(\"fadeFoldWidgets\")},this.setFadeFoldWidgets=function(e){this.setOption(\"fadeFoldWidgets\",e)},this.setHighlightGutterLine=function(e){this.setOption(\"highlightGutterLine\",e)},this.getHighlightGutterLine=function(){return this.getOption(\"highlightGutterLine\")},this.$updateGutterLineHighlight=function(){var e=this.$cursorLayer.$pixelPos,t=this.layerConfig.lineHeight;if(this.session.getUseWrapMode()){var n=this.session.selection.getCursor();n.column=0,e=this.$cursorLayer.getPixelPosition(n,!0),t*=this.session.getRowLength(n.row)}this.$gutterLineHighlight.style.top=e.top-this.layerConfig.offset+\"px\",this.$gutterLineHighlight.style.height=t+\"px\"},this.$updatePrintMargin=function(){if(!this.$showPrintMargin&&!this.$printMarginEl)return;if(!this.$printMarginEl){var e=i.createElement(\"div\");e.className=\"ace_layer ace_print-margin-layer\",this.$printMarginEl=i.createElement(\"div\"),this.$printMarginEl.className=\"ace_print-margin\",e.appendChild(this.$printMarginEl),this.content.insertBefore(e,this.content.firstChild)}var t=this.$printMarginEl.style;t.left=this.characterWidth*this.$printMarginColumn+this.$padding+\"px\",t.visibility=this.$showPrintMargin?\"visible\":\"hidden\",this.session&&this.session.$wrap==-1&&this.adjustWrapLimit()},this.getContainerElement=function(){return this.container},this.getMouseEventTarget=function(){return this.scroller},this.getTextAreaContainer=function(){return this.container},this.$moveTextAreaToCursor=function(){if(!this.$keepTextAreaAtCursor)return;var e=this.layerConfig,t=this.$cursorLayer.$pixelPos.top,n=this.$cursorLayer.$pixelPos.left;t-=e.offset;var r=this.textarea.style,i=this.lineHeight;if(t<0||t>e.height-i){r.top=r.left=\"0\";return}var s=this.characterWidth;if(this.$composition){var o=this.textarea.value.replace(/^\\x01+/,\"\");s*=this.session.$getStringScreenWidth(o)[0]+2,i+=2}n-=this.scrollLeft,n>this.$size.scrollerWidth-s&&(n=this.$size.scrollerWidth-s),n+=this.gutterWidth,r.height=i+\"px\",r.width=s+\"px\",r.left=Math.min(n,this.$size.scrollerWidth-s)+\"px\",r.top=Math.min(t,this.$size.height-i)+\"px\"},this.getFirstVisibleRow=function(){return this.layerConfig.firstRow},this.getFirstFullyVisibleRow=function(){return this.layerConfig.firstRow+(this.layerConfig.offset===0?0:1)},this.getLastFullyVisibleRow=function(){var e=this.layerConfig,t=e.lastRow,n=this.session.documentToScreenRow(t,0)*e.lineHeight;return n-this.session.getScrollTop()>e.height-e.lineHeight?t-1:t},this.getLastVisibleRow=function(){return this.layerConfig.lastRow},this.$padding=null,this.setPadding=function(e){this.$padding=e,this.$textLayer.setPadding(e),this.$cursorLayer.setPadding(e),this.$markerFront.setPadding(e),this.$markerBack.setPadding(e),this.$loop.schedule(this.CHANGE_FULL),this.$updatePrintMargin()},this.setScrollMargin=function(e,t,n,r){var i=this.scrollMargin;i.top=e|0,i.bottom=t|0,i.right=r|0,i.left=n|0,i.v=i.top+i.bottom,i.h=i.left+i.right,i.top&&this.scrollTop<=0&&this.session&&this.session.setScrollTop(-i.top),this.updateFull()},this.getHScrollBarAlwaysVisible=function(){return this.$hScrollBarAlwaysVisible},this.setHScrollBarAlwaysVisible=function(e){this.setOption(\"hScrollBarAlwaysVisible\",e)},this.getVScrollBarAlwaysVisible=function(){return this.$vScrollBarAlwaysVisible},this.setVScrollBarAlwaysVisible=function(e){this.setOption(\"vScrollBarAlwaysVisible\",e)},this.$updateScrollBarV=function(){var e=this.layerConfig.maxHeight,t=this.$size.scrollerHeight;!this.$maxLines&&this.$scrollPastEnd&&(e-=(t-this.lineHeight)*this.$scrollPastEnd,this.scrollTop>e-t&&(e=this.scrollTop+t,this.scrollBarV.scrollTop=null)),this.scrollBarV.setScrollHeight(e+this.scrollMargin.v),this.scrollBarV.setScrollTop(this.scrollTop+this.scrollMargin.top)},this.$updateScrollBarH=function(){this.scrollBarH.setScrollWidth(this.layerConfig.width+2*this.$padding+this.scrollMargin.h),this.scrollBarH.setScrollLeft(this.scrollLeft+this.scrollMargin.left)},this.$frozen=!1,this.freeze=function(){this.$frozen=!0},this.unfreeze=function(){this.$frozen=!1},this.$renderChanges=function(e,t){this.$changes&&(e|=this.$changes,this.$changes=0);if(!this.session||!this.container.offsetWidth||this.$frozen||!e&&!t){this.$changes|=e;return}if(this.$size.$dirty)return this.$changes|=e,this.onResize(!0);this.lineHeight||this.$textLayer.checkForSizeChanges(),this._signal(\"beforeRender\"),this.session&&this.session.$bidiHandler&&this.session.$bidiHandler.updateCharacterWidths(this.$fontMetrics);var n=this.layerConfig;if(e&this.CHANGE_FULL||e&this.CHANGE_SIZE||e&this.CHANGE_TEXT||e&this.CHANGE_LINES||e&this.CHANGE_SCROLL||e&this.CHANGE_H_SCROLL){e|=this.$computeLayerConfig();if(n.firstRow!=this.layerConfig.firstRow&&n.firstRowScreen==this.layerConfig.firstRowScreen){var r=this.scrollTop+(n.firstRow-this.layerConfig.firstRow)*this.lineHeight;r>0&&(this.scrollTop=r,e|=this.CHANGE_SCROLL,e|=this.$computeLayerConfig())}n=this.layerConfig,this.$updateScrollBarV(),e&this.CHANGE_H_SCROLL&&this.$updateScrollBarH(),this.$gutterLayer.element.style.marginTop=-n.offset+\"px\",this.content.style.marginTop=-n.offset+\"px\",this.content.style.width=n.width+2*this.$padding+\"px\",this.content.style.height=n.minHeight+\"px\"}e&this.CHANGE_H_SCROLL&&(this.content.style.marginLeft=-this.scrollLeft+\"px\",this.scroller.className=this.scrollLeft<=0?\"ace_scroller\":\"ace_scroller ace_scroll-left\");if(e&this.CHANGE_FULL){this.$textLayer.update(n),this.$showGutter&&this.$gutterLayer.update(n),this.$markerBack.update(n),this.$markerFront.update(n),this.$cursorLayer.update(n),this.$moveTextAreaToCursor(),this.$highlightGutterLine&&this.$updateGutterLineHighlight(),this._signal(\"afterRender\");return}if(e&this.CHANGE_SCROLL){e&this.CHANGE_TEXT||e&this.CHANGE_LINES?this.$textLayer.update(n):this.$textLayer.scrollLines(n),this.$showGutter&&this.$gutterLayer.update(n),this.$markerBack.update(n),this.$markerFront.update(n),this.$cursorLayer.update(n),this.$highlightGutterLine&&this.$updateGutterLineHighlight(),this.$moveTextAreaToCursor(),this._signal(\"afterRender\");return}e&this.CHANGE_TEXT?(this.$textLayer.update(n),this.$showGutter&&this.$gutterLayer.update(n)):e&this.CHANGE_LINES?(this.$updateLines()||e&this.CHANGE_GUTTER&&this.$showGutter)&&this.$gutterLayer.update(n):(e&this.CHANGE_TEXT||e&this.CHANGE_GUTTER)&&this.$showGutter&&this.$gutterLayer.update(n),e&this.CHANGE_CURSOR&&(this.$cursorLayer.update(n),this.$moveTextAreaToCursor(),this.$highlightGutterLine&&this.$updateGutterLineHighlight()),e&(this.CHANGE_MARKER|this.CHANGE_MARKER_FRONT)&&this.$markerFront.update(n),e&(this.CHANGE_MARKER|this.CHANGE_MARKER_BACK)&&this.$markerBack.update(n),this._signal(\"afterRender\")},this.$autosize=function(){var e=this.session.getScreenLength()*this.lineHeight,t=this.$maxLines*this.lineHeight,n=Math.min(t,Math.max((this.$minLines||1)*this.lineHeight,e))+this.scrollMargin.v+(this.$extraHeight||0);this.$horizScroll&&(n+=this.scrollBarH.getHeight()),this.$maxPixelHeight&&n>this.$maxPixelHeight&&(n=this.$maxPixelHeight);var r=e>t;if(n!=this.desiredHeight||this.$size.height!=this.desiredHeight||r!=this.$vScroll){r!=this.$vScroll&&(this.$vScroll=r,this.scrollBarV.setVisible(r));var i=this.container.clientWidth;this.container.style.height=n+\"px\",this.$updateCachedSize(!0,this.$gutterWidth,i,n),this.desiredHeight=n,this._signal(\"autosize\")}},this.$computeLayerConfig=function(){var e=this.session,t=this.$size,n=t.height<=2*this.lineHeight,r=this.session.getScreenLength(),i=r*this.lineHeight,s=this.$getLongestLine(),o=!n&&(this.$hScrollBarAlwaysVisible||t.scrollerWidth-s-2*this.$padding<0),u=this.$horizScroll!==o;u&&(this.$horizScroll=o,this.scrollBarH.setVisible(o));var a=this.$vScroll;this.$maxLines&&this.lineHeight>1&&this.$autosize();var f=this.scrollTop%this.lineHeight,l=t.scrollerHeight+this.lineHeight,c=!this.$maxLines&&this.$scrollPastEnd?(t.scrollerHeight-this.lineHeight)*this.$scrollPastEnd:0;i+=c;var h=this.scrollMargin;this.session.setScrollTop(Math.max(-h.top,Math.min(this.scrollTop,i-t.scrollerHeight+h.bottom))),this.session.setScrollLeft(Math.max(-h.left,Math.min(this.scrollLeft,s+2*this.$padding-t.scrollerWidth+h.right)));var p=!n&&(this.$vScrollBarAlwaysVisible||t.scrollerHeight-i+c<0||this.scrollTop>h.top),d=a!==p;d&&(this.$vScroll=p,this.scrollBarV.setVisible(p));var v=Math.ceil(l/this.lineHeight)-1,m=Math.max(0,Math.round((this.scrollTop-f)/this.lineHeight)),g=m+v,y,b,w=this.lineHeight;m=e.screenToDocumentRow(m,0);var E=e.getFoldLine(m);E&&(m=E.start.row),y=e.documentToScreenRow(m,0),b=e.getRowLength(m)*w,g=Math.min(e.screenToDocumentRow(g,0),e.getLength()-1),l=t.scrollerHeight+e.getRowLength(g)*w+b,f=this.scrollTop-y*w;var S=0;this.layerConfig.width!=s&&(S=this.CHANGE_H_SCROLL);if(u||d)S=this.$updateCachedSize(!0,this.gutterWidth,t.width,t.height),this._signal(\"scrollbarVisibilityChanged\"),d&&(s=this.$getLongestLine());return this.layerConfig={width:s,padding:this.$padding,firstRow:m,firstRowScreen:y,lastRow:g,lineHeight:w,characterWidth:this.characterWidth,minHeight:l,maxHeight:i,offset:f,gutterOffset:w?Math.max(0,Math.ceil((f+t.height-t.scrollerHeight)/w)):0,height:this.$size.scrollerHeight},S},this.$updateLines=function(){if(!this.$changedLines)return;var e=this.$changedLines.firstRow,t=this.$changedLines.lastRow;this.$changedLines=null;var n=this.layerConfig;if(e>n.lastRow+1)return;if(t<n.firstRow)return;if(t===Infinity){this.$showGutter&&this.$gutterLayer.update(n),this.$textLayer.update(n);return}return this.$textLayer.updateLines(n,e,t),!0},this.$getLongestLine=function(){var e=this.session.getScreenWidth();return this.showInvisibles&&!this.session.$useWrapMode&&(e+=1),Math.max(this.$size.scrollerWidth-2*this.$padding,Math.round(e*this.characterWidth))},this.updateFrontMarkers=function(){this.$markerFront.setMarkers(this.session.getMarkers(!0)),this.$loop.schedule(this.CHANGE_MARKER_FRONT)},this.updateBackMarkers=function(){this.$markerBack.setMarkers(this.session.getMarkers()),this.$loop.schedule(this.CHANGE_MARKER_BACK)},this.addGutterDecoration=function(e,t){this.$gutterLayer.addGutterDecoration(e,t)},this.removeGutterDecoration=function(e,t){this.$gutterLayer.removeGutterDecoration(e,t)},this.updateBreakpoints=function(e){this.$loop.schedule(this.CHANGE_GUTTER)},this.setAnnotations=function(e){this.$gutterLayer.setAnnotations(e),this.$loop.schedule(this.CHANGE_GUTTER)},this.updateCursor=function(){this.$loop.schedule(this.CHANGE_CURSOR)},this.hideCursor=function(){this.$cursorLayer.hideCursor()},this.showCursor=function(){this.$cursorLayer.showCursor()},this.scrollSelectionIntoView=function(e,t,n){this.scrollCursorIntoView(e,n),this.scrollCursorIntoView(t,n)},this.scrollCursorIntoView=function(e,t,n){if(this.$size.scrollerHeight===0)return;var r=this.$cursorLayer.getPixelPosition(e),i=r.left,s=r.top,o=n&&n.top||0,u=n&&n.bottom||0,a=this.$scrollAnimation?this.session.getScrollTop():this.scrollTop;a+o>s?(t&&a+o>s+this.lineHeight&&(s-=t*this.$size.scrollerHeight),s===0&&(s=-this.scrollMargin.top),this.session.setScrollTop(s)):a+this.$size.scrollerHeight-u<s+this.lineHeight&&(t&&a+this.$size.scrollerHeight-u<s-this.lineHeight&&(s+=t*this.$size.scrollerHeight),this.session.setScrollTop(s+this.lineHeight-this.$size.scrollerHeight));var f=this.scrollLeft;f>i?(i<this.$padding+2*this.layerConfig.characterWidth&&(i=-this.scrollMargin.left),this.session.setScrollLeft(i)):f+this.$size.scrollerWidth<i+this.characterWidth?this.session.setScrollLeft(Math.round(i+this.characterWidth-this.$size.scrollerWidth)):f<=this.$padding&&i-f<this.characterWidth&&this.session.setScrollLeft(0)},this.getScrollTop=function(){return this.session.getScrollTop()},this.getScrollLeft=function(){return this.session.getScrollLeft()},this.getScrollTopRow=function(){return this.scrollTop/this.lineHeight},this.getScrollBottomRow=function(){return Math.max(0,Math.floor((this.scrollTop+this.$size.scrollerHeight)/this.lineHeight)-1)},this.scrollToRow=function(e){this.session.setScrollTop(e*this.lineHeight)},this.alignCursor=function(e,t){typeof e==\"number\"&&(e={row:e,column:0});var n=this.$cursorLayer.getPixelPosition(e),r=this.$size.scrollerHeight-this.lineHeight,i=n.top-r*(t||0);return this.session.setScrollTop(i),i},this.STEPS=8,this.$calcSteps=function(e,t){var n=0,r=this.STEPS,i=[],s=function(e,t,n){return n*(Math.pow(e-1,3)+1)+t};for(n=0;n<r;++n)i.push(s(n/this.STEPS,e,t-e));return i},this.scrollToLine=function(e,t,n,r){var i=this.$cursorLayer.getPixelPosition({row:e,column:0}),s=i.top;t&&(s-=this.$size.scrollerHeight/2);var o=this.scrollTop;this.session.setScrollTop(s),n!==!1&&this.animateScrolling(o,r)},this.animateScrolling=function(e,t){var n=this.scrollTop;if(!this.$animatedScroll)return;var r=this;if(e==n)return;if(this.$scrollAnimation){var i=this.$scrollAnimation.steps;if(i.length){e=i[0];if(e==n)return}}var s=r.$calcSteps(e,n);this.$scrollAnimation={from:e,to:n,steps:s},clearInterval(this.$timer),r.session.setScrollTop(s.shift()),r.session.$scrollTop=n,this.$timer=setInterval(function(){s.length?(r.session.setScrollTop(s.shift()),r.session.$scrollTop=n):n!=null?(r.session.$scrollTop=-1,r.session.setScrollTop(n),n=null):(r.$timer=clearInterval(r.$timer),r.$scrollAnimation=null,t&&t())},10)},this.scrollToY=function(e){this.scrollTop!==e&&(this.$loop.schedule(this.CHANGE_SCROLL),this.scrollTop=e)},this.scrollToX=function(e){this.scrollLeft!==e&&(this.scrollLeft=e),this.$loop.schedule(this.CHANGE_H_SCROLL)},this.scrollTo=function(e,t){this.session.setScrollTop(t),this.session.setScrollLeft(t)},this.scrollBy=function(e,t){t&&this.session.setScrollTop(this.session.getScrollTop()+t),e&&this.session.setScrollLeft(this.session.getScrollLeft()+e)},this.isScrollableBy=function(e,t){if(t<0&&this.session.getScrollTop()>=1-this.scrollMargin.top)return!0;if(t>0&&this.session.getScrollTop()+this.$size.scrollerHeight-this.layerConfig.maxHeight<-1+this.scrollMargin.bottom)return!0;if(e<0&&this.session.getScrollLeft()>=1-this.scrollMargin.left)return!0;if(e>0&&this.session.getScrollLeft()+this.$size.scrollerWidth-this.layerConfig.width<-1+this.scrollMargin.right)return!0},this.pixelToScreenCoordinates=function(e,t){var n=this.scroller.getBoundingClientRect(),r=e+this.scrollLeft-n.left-this.$padding,i=r/this.characterWidth,s=Math.floor((t+this.scrollTop-n.top)/this.lineHeight),o=Math.round(i);return{row:s,column:o,side:i-o>0?1:-1,offsetX:r}},this.screenToTextCoordinates=function(e,t){var n=this.scroller.getBoundingClientRect(),r=e+this.scrollLeft-n.left-this.$padding,i=Math.round(r/this.characterWidth),s=(t+this.scrollTop-n.top)/this.lineHeight;return this.session.screenToDocumentPosition(s,Math.max(i,0),r)},this.textToScreenCoordinates=function(e,t){var n=this.scroller.getBoundingClientRect(),r=this.session.documentToScreenPosition(e,t),i=this.$padding+(this.session.$bidiHandler.isBidiRow(r.row,e)?this.session.$bidiHandler.getPosLeft(r.column):Math.round(r.column*this.characterWidth)),s=r.row*this.lineHeight;return{pageX:n.left+i-this.scrollLeft,pageY:n.top+s-this.scrollTop}},this.visualizeFocus=function(){i.addCssClass(this.container,\"ace_focus\")},this.visualizeBlur=function(){i.removeCssClass(this.container,\"ace_focus\")},this.showComposition=function(e){this.$composition||(this.$composition={keepTextAreaAtCursor:this.$keepTextAreaAtCursor,cssText:this.textarea.style.cssText}),this.$keepTextAreaAtCursor=!0,i.addCssClass(this.textarea,\"ace_composition\"),this.textarea.style.cssText=\"\",this.$moveTextAreaToCursor()},this.setCompositionText=function(e){this.$moveTextAreaToCursor()},this.hideComposition=function(){if(!this.$composition)return;i.removeCssClass(this.textarea,\"ace_composition\"),this.$keepTextAreaAtCursor=this.$composition.keepTextAreaAtCursor,this.textarea.style.cssText=this.$composition.cssText,this.$composition=null},this.setTheme=function(e,t){function o(r){if(n.$themeId!=e)return t&&t();if(!r||!r.cssClass)throw new Error(\"couldn't load module \"+e+\" or it didn't call define\");i.importCssString(r.cssText,r.cssClass,n.container.ownerDocument),n.theme&&i.removeCssClass(n.container,n.theme.cssClass);var s=\"padding\"in r?r.padding:\"padding\"in(n.theme||{})?4:n.$padding;n.$padding&&s!=n.$padding&&n.setPadding(s),n.$theme=r.cssClass,n.theme=r,i.addCssClass(n.container,r.cssClass),i.setCssClass(n.container,\"ace_dark\",r.isDark),n.$size&&(n.$size.width=0,n.$updateSizeAsync()),n._dispatchEvent(\"themeLoaded\",{theme:r}),t&&t()}var n=this;this.$themeId=e,n._dispatchEvent(\"themeChange\",{theme:e});if(!e||typeof e==\"string\"){var r=e||this.$options.theme.initialValue;s.loadModule([\"theme\",r],o)}else o(e)},this.getTheme=function(){return this.$themeId},this.setStyle=function(e,t){i.setCssClass(this.container,e,t!==!1)},this.unsetStyle=function(e){i.removeCssClass(this.container,e)},this.setCursorStyle=function(e){this.scroller.style.cursor!=e&&(this.scroller.style.cursor=e)},this.setMouseCursor=function(e){this.scroller.style.cursor=e},this.destroy=function(){this.$textLayer.destroy(),this.$cursorLayer.destroy()}}).call(g.prototype),s.defineOptions(g.prototype,\"renderer\",{animatedScroll:{initialValue:!1},showInvisibles:{set:function(e){this.$textLayer.setShowInvisibles(e)&&this.$loop.schedule(this.CHANGE_TEXT)},initialValue:!1},showPrintMargin:{set:function(){this.$updatePrintMargin()},initialValue:!0},printMarginColumn:{set:function(){this.$updatePrintMargin()},initialValue:80},printMargin:{set:function(e){typeof e==\"number\"&&(this.$printMarginColumn=e),this.$showPrintMargin=!!e,this.$updatePrintMargin()},get:function(){return this.$showPrintMargin&&this.$printMarginColumn}},showGutter:{set:function(e){this.$gutter.style.display=e?\"block\":\"none\",this.$loop.schedule(this.CHANGE_FULL),this.onGutterResize()},initialValue:!0},fadeFoldWidgets:{set:function(e){i.setCssClass(this.$gutter,\"ace_fade-fold-widgets\",e)},initialValue:!1},showFoldWidgets:{set:function(e){this.$gutterLayer.setShowFoldWidgets(e)},initialValue:!0},showLineNumbers:{set:function(e){this.$gutterLayer.setShowLineNumbers(e),this.$loop.schedule(this.CHANGE_GUTTER)},initialValue:!0},displayIndentGuides:{set:function(e){this.$textLayer.setDisplayIndentGuides(e)&&this.$loop.schedule(this.CHANGE_TEXT)},initialValue:!0},highlightGutterLine:{set:function(e){if(!this.$gutterLineHighlight){this.$gutterLineHighlight=i.createElement(\"div\"),this.$gutterLineHighlight.className=\"ace_gutter-active-line\",this.$gutter.appendChild(this.$gutterLineHighlight);return}this.$gutterLineHighlight.style.display=e?\"\":\"none\",this.$cursorLayer.$pixelPos&&this.$updateGutterLineHighlight()},initialValue:!1,value:!0},hScrollBarAlwaysVisible:{set:function(e){(!this.$hScrollBarAlwaysVisible||!this.$horizScroll)&&this.$loop.schedule(this.CHANGE_SCROLL)},initialValue:!1},vScrollBarAlwaysVisible:{set:function(e){(!this.$vScrollBarAlwaysVisible||!this.$vScroll)&&this.$loop.schedule(this.CHANGE_SCROLL)},initialValue:!1},fontSize:{set:function(e){typeof e==\"number\"&&(e+=\"px\"),this.container.style.fontSize=e,this.updateFontSize()},initialValue:12},fontFamily:{set:function(e){this.container.style.fontFamily=e,this.updateFontSize()}},maxLines:{set:function(e){this.updateFull()}},minLines:{set:function(e){this.updateFull()}},maxPixelHeight:{set:function(e){this.updateFull()},initialValue:0},scrollPastEnd:{set:function(e){e=+e||0;if(this.$scrollPastEnd==e)return;this.$scrollPastEnd=e,this.$loop.schedule(this.CHANGE_SCROLL)},initialValue:0,handlesSet:!0},fixedWidthGutter:{set:function(e){this.$gutterLayer.$fixedWidth=!!e,this.$loop.schedule(this.CHANGE_GUTTER)}},theme:{set:function(e){this.setTheme(e)},get:function(){return this.$themeId||this.theme},initialValue:\"./theme/textmate\",handlesSet:!0}}),t.VirtualRenderer=g}),define(\"ace/worker/worker_client\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/net\",\"ace/lib/event_emitter\",\"ace/config\"],function(e,t,n){\"use strict\";function u(e){var t=\"importScripts('\"+i.qualifyURL(e)+\"');\";try{return new Blob([t],{type:\"application/javascript\"})}catch(n){var r=window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder,s=new r;return s.append(t),s.getBlob(\"application/javascript\")}}function a(e){var t=u(e),n=window.URL||window.webkitURL,r=n.createObjectURL(t);return new Worker(r)}var r=e(\"../lib/oop\"),i=e(\"../lib/net\"),s=e(\"../lib/event_emitter\").EventEmitter,o=e(\"../config\"),f=function(t,n,r,i,s){this.$sendDeltaQueue=this.$sendDeltaQueue.bind(this),this.changeListener=this.changeListener.bind(this),this.onMessage=this.onMessage.bind(this),e.nameToUrl&&!e.toUrl&&(e.toUrl=e.nameToUrl);if(o.get(\"packaged\")||!e.toUrl)i=i||o.moduleUrl(n,\"worker\");else{var u=this.$normalizePath;i=i||u(e.toUrl(\"ace/worker/worker.js\",null,\"_\"));var f={};t.forEach(function(t){f[t]=u(e.toUrl(t,null,\"_\").replace(/(\\.js)?(\\?.*)?$/,\"\"))})}this.$worker=a(i),s&&this.send(\"importScripts\",s),this.$worker.postMessage({init:!0,tlns:f,module:n,classname:r}),this.callbackId=1,this.callbacks={},this.$worker.onmessage=this.onMessage};(function(){r.implement(this,s),this.onMessage=function(e){var t=e.data;switch(t.type){case\"event\":this._signal(t.name,{data:t.data});break;case\"call\":var n=this.callbacks[t.id];n&&(n(t.data),delete this.callbacks[t.id]);break;case\"error\":this.reportError(t.data);break;case\"log\":window.console&&console.log&&console.log.apply(console,t.data)}},this.reportError=function(e){window.console&&console.error&&console.error(e)},this.$normalizePath=function(e){return i.qualifyURL(e)},this.terminate=function(){this._signal(\"terminate\",{}),this.deltaQueue=null,this.$worker.terminate(),this.$worker=null,this.$doc&&this.$doc.off(\"change\",this.changeListener),this.$doc=null},this.send=function(e,t){this.$worker.postMessage({command:e,args:t})},this.call=function(e,t,n){if(n){var r=this.callbackId++;this.callbacks[r]=n,t.push(r)}this.send(e,t)},this.emit=function(e,t){try{this.$worker.postMessage({event:e,data:{data:t.data}})}catch(n){console.error(n.stack)}},this.attachToDocument=function(e){this.$doc&&this.terminate(),this.$doc=e,this.call(\"setValue\",[e.getValue()]),e.on(\"change\",this.changeListener)},this.changeListener=function(e){this.deltaQueue||(this.deltaQueue=[],setTimeout(this.$sendDeltaQueue,0)),e.action==\"insert\"?this.deltaQueue.push(e.start,e.lines):this.deltaQueue.push(e.start,e.end)},this.$sendDeltaQueue=function(){var e=this.deltaQueue;if(!e)return;this.deltaQueue=null,e.length>50&&e.length>this.$doc.getLength()>>1?this.call(\"setValue\",[this.$doc.getValue()]):this.emit(\"change\",{data:e})}}).call(f.prototype);var l=function(e,t,n){this.$sendDeltaQueue=this.$sendDeltaQueue.bind(this),this.changeListener=this.changeListener.bind(this),this.callbackId=1,this.callbacks={},this.messageBuffer=[];var r=null,i=!1,u=Object.create(s),a=this;this.$worker={},this.$worker.terminate=function(){},this.$worker.postMessage=function(e){a.messageBuffer.push(e),r&&(i?setTimeout(f):f())},this.setEmitSync=function(e){i=e};var f=function(){var e=a.messageBuffer.shift();e.command?r[e.command].apply(r,e.args):e.event&&u._signal(e.event,e.data)};u.postMessage=function(e){a.onMessage({data:e})},u.callback=function(e,t){this.postMessage({type:\"call\",id:t,data:e})},u.emit=function(e,t){this.postMessage({type:\"event\",name:e,data:t})},o.loadModule([\"worker\",t],function(e){r=new e[n](u);while(a.messageBuffer.length)f()})};l.prototype=f.prototype,t.UIWorkerClient=l,t.WorkerClient=f,t.createWorker=a}),define(\"ace/placeholder\",[\"require\",\"exports\",\"module\",\"ace/range\",\"ace/lib/event_emitter\",\"ace/lib/oop\"],function(e,t,n){\"use strict\";var r=e(\"./range\").Range,i=e(\"./lib/event_emitter\").EventEmitter,s=e(\"./lib/oop\"),o=function(e,t,n,r,i,s){var o=this;this.length=t,this.session=e,this.doc=e.getDocument(),this.mainClass=i,this.othersClass=s,this.$onUpdate=this.onUpdate.bind(this),this.doc.on(\"change\",this.$onUpdate),this.$others=r,this.$onCursorChange=function(){setTimeout(function(){o.onCursorChange()})},this.$pos=n;var u=e.getUndoManager().$undoStack||e.getUndoManager().$undostack||{length:-1};this.$undoStackDepth=u.length,this.setup(),e.selection.on(\"changeCursor\",this.$onCursorChange)};(function(){s.implement(this,i),this.setup=function(){var e=this,t=this.doc,n=this.session;this.selectionBefore=n.selection.toJSON(),n.selection.inMultiSelectMode&&n.selection.toSingleRange(),this.pos=t.createAnchor(this.$pos.row,this.$pos.column);var i=this.pos;i.$insertRight=!0,i.detach(),i.markerId=n.addMarker(new r(i.row,i.column,i.row,i.column+this.length),this.mainClass,null,!1),this.others=[],this.$others.forEach(function(n){var r=t.createAnchor(n.row,n.column);r.$insertRight=!0,r.detach(),e.others.push(r)}),n.setUndoSelect(!1)},this.showOtherMarkers=function(){if(this.othersActive)return;var e=this.session,t=this;this.othersActive=!0,this.others.forEach(function(n){n.markerId=e.addMarker(new r(n.row,n.column,n.row,n.column+t.length),t.othersClass,null,!1)})},this.hideOtherMarkers=function(){if(!this.othersActive)return;this.othersActive=!1;for(var e=0;e<this.others.length;e++)this.session.removeMarker(this.others[e].markerId)},this.onUpdate=function(e){if(this.$updating)return this.updateAnchors(e);var t=e;if(t.start.row!==t.end.row)return;if(t.start.row!==this.pos.row)return;this.$updating=!0;var n=e.action===\"insert\"?t.end.column-t.start.column:t.start.column-t.end.column,i=t.start.column>=this.pos.column&&t.start.column<=this.pos.column+this.length+1,s=t.start.column-this.pos.column;this.updateAnchors(e),i&&(this.length+=n);if(i&&!this.session.$fromUndo)if(e.action===\"insert\")for(var o=this.others.length-1;o>=0;o--){var u=this.others[o],a={row:u.row,column:u.column+s};this.doc.insertMergedLines(a,e.lines)}else if(e.action===\"remove\")for(var o=this.others.length-1;o>=0;o--){var u=this.others[o],a={row:u.row,column:u.column+s};this.doc.remove(new r(a.row,a.column,a.row,a.column-n))}this.$updating=!1,this.updateMarkers()},this.updateAnchors=function(e){this.pos.onChange(e);for(var t=this.others.length;t--;)this.others[t].onChange(e);this.updateMarkers()},this.updateMarkers=function(){if(this.$updating)return;var e=this,t=this.session,n=function(n,i){t.removeMarker(n.markerId),n.markerId=t.addMarker(new r(n.row,n.column,n.row,n.column+e.length),i,null,!1)};n(this.pos,this.mainClass);for(var i=this.others.length;i--;)n(this.others[i],this.othersClass)},this.onCursorChange=function(e){if(this.$updating||!this.session)return;var t=this.session.selection.getCursor();t.row===this.pos.row&&t.column>=this.pos.column&&t.column<=this.pos.column+this.length?(this.showOtherMarkers(),this._emit(\"cursorEnter\",e)):(this.hideOtherMarkers(),this._emit(\"cursorLeave\",e))},this.detach=function(){this.session.removeMarker(this.pos&&this.pos.markerId),this.hideOtherMarkers(),this.doc.removeEventListener(\"change\",this.$onUpdate),this.session.selection.removeEventListener(\"changeCursor\",this.$onCursorChange),this.session.setUndoSelect(!0),this.session=null},this.cancel=function(){if(this.$undoStackDepth===-1)return;var e=this.session.getUndoManager(),t=(e.$undoStack||e.$undostack).length-this.$undoStackDepth;for(var n=0;n<t;n++)e.undo(!0);this.selectionBefore&&this.session.selection.fromJSON(this.selectionBefore)}}).call(o.prototype),t.PlaceHolder=o}),define(\"ace/mouse/multi_select_handler\",[\"require\",\"exports\",\"module\",\"ace/lib/event\",\"ace/lib/useragent\"],function(e,t,n){function s(e,t){return e.row==t.row&&e.column==t.column}function o(e){var t=e.domEvent,n=t.altKey,o=t.shiftKey,u=t.ctrlKey,a=e.getAccelKey(),f=e.getButton();u&&i.isMac&&(f=t.button);if(e.editor.inMultiSelectMode&&f==2){e.editor.textInput.onContextMenu(e.domEvent);return}if(!u&&!n&&!a){f===0&&e.editor.inMultiSelectMode&&e.editor.exitMultiSelectMode();return}if(f!==0)return;var l=e.editor,c=l.selection,h=l.inMultiSelectMode,p=e.getDocumentPosition(),d=c.getCursor(),v=e.inSelection()||c.isEmpty()&&s(p,d),m=e.x,g=e.y,y=function(e){m=e.clientX,g=e.clientY},b=l.session,w=l.renderer.pixelToScreenCoordinates(m,g),E=w,S;if(l.$mouseHandler.$enableJumpToDef)u&&n||a&&n?S=o?\"block\":\"add\":n&&l.$blockSelectEnabled&&(S=\"block\");else if(a&&!n){S=\"add\";if(!h&&o)return}else n&&l.$blockSelectEnabled&&(S=\"block\");S&&i.isMac&&t.ctrlKey&&l.$mouseHandler.cancelContextMenu();if(S==\"add\"){if(!h&&v)return;if(!h){var x=c.toOrientedRange();l.addSelectionMarker(x)}var T=c.rangeList.rangeAtPoint(p);l.$blockScrolling++,l.inVirtualSelectionMode=!0,o&&(T=null,x=c.ranges[0]||x,l.removeSelectionMarker(x)),l.once(\"mouseup\",function(){var e=c.toOrientedRange();T&&e.isEmpty()&&s(T.cursor,e.cursor)?c.substractPoint(e.cursor):(o?c.substractPoint(x.cursor):x&&(l.removeSelectionMarker(x),c.addRange(x)),c.addRange(e)),l.$blockScrolling--,l.inVirtualSelectionMode=!1})}else if(S==\"block\"){e.stop(),l.inVirtualSelectionMode=!0;var N,C=[],k=function(){var e=l.renderer.pixelToScreenCoordinates(m,g),t=b.screenToDocumentPosition(e.row,e.column,e.offsetX);if(s(E,e)&&s(t,c.lead))return;E=e,l.$blockScrolling++,l.selection.moveToPosition(t),l.renderer.scrollCursorIntoView(),l.removeSelectionMarkers(C),C=c.rectangularRangeBlock(E,w),l.$mouseHandler.$clickSelection&&C.length==1&&C[0].isEmpty()&&(C[0]=l.$mouseHandler.$clickSelection.clone()),C.forEach(l.addSelectionMarker,l),l.updateSelectionMarkers(),l.$blockScrolling--};l.$blockScrolling++,h&&!a?c.toSingleRange():!h&&a&&(N=c.toOrientedRange(),l.addSelectionMarker(N)),o?w=b.documentToScreenPosition(c.lead):c.moveToPosition(p),l.$blockScrolling--,E={row:-1,column:-1};var L=function(e){clearInterval(O),l.removeSelectionMarkers(C),C.length||(C=[c.toOrientedRange()]),l.$blockScrolling++,N&&(l.removeSelectionMarker(N),c.toSingleRange(N));for(var t=0;t<C.length;t++)c.addRange(C[t]);l.inVirtualSelectionMode=!1,l.$mouseHandler.$clickSelection=null,l.$blockScrolling--},A=k;r.capture(l.container,y,L);var O=setInterval(function(){A()},20);return e.preventDefault()}}var r=e(\"../lib/event\"),i=e(\"../lib/useragent\");t.onMouseDown=o}),define(\"ace/commands/multi_select_commands\",[\"require\",\"exports\",\"module\",\"ace/keyboard/hash_handler\"],function(e,t,n){t.defaultCommands=[{name:\"addCursorAbove\",exec:function(e){e.selectMoreLines(-1)},bindKey:{win:\"Ctrl-Alt-Up\",mac:\"Ctrl-Alt-Up\"},scrollIntoView:\"cursor\",readOnly:!0},{name:\"addCursorBelow\",exec:function(e){e.selectMoreLines(1)},bindKey:{win:\"Ctrl-Alt-Down\",mac:\"Ctrl-Alt-Down\"},scrollIntoView:\"cursor\",readOnly:!0},{name:\"addCursorAboveSkipCurrent\",exec:function(e){e.selectMoreLines(-1,!0)},bindKey:{win:\"Ctrl-Alt-Shift-Up\",mac:\"Ctrl-Alt-Shift-Up\"},scrollIntoView:\"cursor\",readOnly:!0},{name:\"addCursorBelowSkipCurrent\",exec:function(e){e.selectMoreLines(1,!0)},bindKey:{win:\"Ctrl-Alt-Shift-Down\",mac:\"Ctrl-Alt-Shift-Down\"},scrollIntoView:\"cursor\",readOnly:!0},{name:\"selectMoreBefore\",exec:function(e){e.selectMore(-1)},bindKey:{win:\"Ctrl-Alt-Left\",mac:\"Ctrl-Alt-Left\"},scrollIntoView:\"cursor\",readOnly:!0},{name:\"selectMoreAfter\",exec:function(e){e.selectMore(1)},bindKey:{win:\"Ctrl-Alt-Right\",mac:\"Ctrl-Alt-Right\"},scrollIntoView:\"cursor\",readOnly:!0},{name:\"selectNextBefore\",exec:function(e){e.selectMore(-1,!0)},bindKey:{win:\"Ctrl-Alt-Shift-Left\",mac:\"Ctrl-Alt-Shift-Left\"},scrollIntoView:\"cursor\",readOnly:!0},{name:\"selectNextAfter\",exec:function(e){e.selectMore(1,!0)},bindKey:{win:\"Ctrl-Alt-Shift-Right\",mac:\"Ctrl-Alt-Shift-Right\"},scrollIntoView:\"cursor\",readOnly:!0},{name:\"splitIntoLines\",exec:function(e){e.multiSelect.splitIntoLines()},bindKey:{win:\"Ctrl-Alt-L\",mac:\"Ctrl-Alt-L\"},readOnly:!0},{name:\"alignCursors\",exec:function(e){e.alignCursors()},bindKey:{win:\"Ctrl-Alt-A\",mac:\"Ctrl-Alt-A\"},scrollIntoView:\"cursor\"},{name:\"findAll\",exec:function(e){e.findAll()},bindKey:{win:\"Ctrl-Alt-K\",mac:\"Ctrl-Alt-G\"},scrollIntoView:\"cursor\",readOnly:!0}],t.multiSelectCommands=[{name:\"singleSelection\",bindKey:\"esc\",exec:function(e){e.exitMultiSelectMode()},scrollIntoView:\"cursor\",readOnly:!0,isAvailable:function(e){return e&&e.inMultiSelectMode}}];var r=e(\"../keyboard/hash_handler\").HashHandler;t.keyboardHandler=new r(t.multiSelectCommands)}),define(\"ace/multi_select\",[\"require\",\"exports\",\"module\",\"ace/range_list\",\"ace/range\",\"ace/selection\",\"ace/mouse/multi_select_handler\",\"ace/lib/event\",\"ace/lib/lang\",\"ace/commands/multi_select_commands\",\"ace/search\",\"ace/edit_session\",\"ace/editor\",\"ace/config\"],function(e,t,n){function h(e,t,n){return c.$options.wrap=!0,c.$options.needle=t,c.$options.backwards=n==-1,c.find(e)}function v(e,t){return e.row==t.row&&e.column==t.column}function m(e){if(e.$multiselectOnSessionChange)return;e.$onAddRange=e.$onAddRange.bind(e),e.$onRemoveRange=e.$onRemoveRange.bind(e),e.$onMultiSelect=e.$onMultiSelect.bind(e),e.$onSingleSelect=e.$onSingleSelect.bind(e),e.$multiselectOnSessionChange=t.onSessionChange.bind(e),e.$checkMultiselectChange=e.$checkMultiselectChange.bind(e),e.$multiselectOnSessionChange(e),e.on(\"changeSession\",e.$multiselectOnSessionChange),e.on(\"mousedown\",o),e.commands.addCommands(f.defaultCommands),g(e)}function g(e){function r(t){n&&(e.renderer.setMouseCursor(\"\"),n=!1)}var t=e.textInput.getElement(),n=!1;u.addListener(t,\"keydown\",function(t){var i=t.keyCode==18&&!(t.ctrlKey||t.shiftKey||t.metaKey);e.$blockSelectEnabled&&i?n||(e.renderer.setMouseCursor(\"crosshair\"),n=!0):n&&r()}),u.addListener(t,\"keyup\",r),u.addListener(t,\"blur\",r)}var r=e(\"./range_list\").RangeList,i=e(\"./range\").Range,s=e(\"./selection\").Selection,o=e(\"./mouse/multi_select_handler\").onMouseDown,u=e(\"./lib/event\"),a=e(\"./lib/lang\"),f=e(\"./commands/multi_select_commands\");t.commands=f.defaultCommands.concat(f.multiSelectCommands);var l=e(\"./search\").Search,c=new l,p=e(\"./edit_session\").EditSession;(function(){this.getSelectionMarkers=function(){return this.$selectionMarkers}}).call(p.prototype),function(){this.ranges=null,this.rangeList=null,this.addRange=function(e,t){if(!e)return;if(!this.inMultiSelectMode&&this.rangeCount===0){var n=this.toOrientedRange();this.rangeList.add(n),this.rangeList.add(e);if(this.rangeList.ranges.length!=2)return this.rangeList.removeAll(),t||this.fromOrientedRange(e);this.rangeList.removeAll(),this.rangeList.add(n),this.$onAddRange(n)}e.cursor||(e.cursor=e.end);var r=this.rangeList.add(e);return this.$onAddRange(e),r.length&&this.$onRemoveRange(r),this.rangeCount>1&&!this.inMultiSelectMode&&(this._signal(\"multiSelect\"),this.inMultiSelectMode=!0,this.session.$undoSelect=!1,this.rangeList.attach(this.session)),t||this.fromOrientedRange(e)},this.toSingleRange=function(e){e=e||this.ranges[0];var t=this.rangeList.removeAll();t.length&&this.$onRemoveRange(t),e&&this.fromOrientedRange(e)},this.substractPoint=function(e){var t=this.rangeList.substractPoint(e);if(t)return this.$onRemoveRange(t),t[0]},this.mergeOverlappingRanges=function(){var e=this.rangeList.merge();e.length?this.$onRemoveRange(e):this.ranges[0]&&this.fromOrientedRange(this.ranges[0])},this.$onAddRange=function(e){this.rangeCount=this.rangeList.ranges.length,this.ranges.unshift(e),this._signal(\"addRange\",{range:e})},this.$onRemoveRange=function(e){this.rangeCount=this.rangeList.ranges.length;if(this.rangeCount==1&&this.inMultiSelectMode){var t=this.rangeList.ranges.pop();e.push(t),this.rangeCount=0}for(var n=e.length;n--;){var r=this.ranges.indexOf(e[n]);this.ranges.splice(r,1)}this._signal(\"removeRange\",{ranges:e}),this.rangeCount===0&&this.inMultiSelectMode&&(this.inMultiSelectMode=!1,this._signal(\"singleSelect\"),this.session.$undoSelect=!0,this.rangeList.detach(this.session)),t=t||this.ranges[0],t&&!t.isEqual(this.getRange())&&this.fromOrientedRange(t)},this.$initRangeList=function(){if(this.rangeList)return;this.rangeList=new r,this.ranges=[],this.rangeCount=0},this.getAllRanges=function(){return this.rangeCount?this.rangeList.ranges.concat():[this.getRange()]},this.splitIntoLines=function(){if(this.rangeCount>1){var e=this.rangeList.ranges,t=e[e.length-1],n=i.fromPoints(e[0].start,t.end);this.toSingleRange(),this.setSelectionRange(n,t.cursor==t.start)}else{var n=this.getRange(),r=this.isBackwards(),s=n.start.row,o=n.end.row;if(s==o){if(r)var u=n.end,a=n.start;else var u=n.start,a=n.end;this.addRange(i.fromPoints(a,a)),this.addRange(i.fromPoints(u,u));return}var f=[],l=this.getLineRange(s,!0);l.start.column=n.start.column,f.push(l);for(var c=s+1;c<o;c++)f.push(this.getLineRange(c,!0));l=this.getLineRange(o,!0),l.end.column=n.end.column,f.push(l),f.forEach(this.addRange,this)}},this.toggleBlockSelection=function(){if(this.rangeCount>1){var e=this.rangeList.ranges,t=e[e.length-1],n=i.fromPoints(e[0].start,t.end);this.toSingleRange(),this.setSelectionRange(n,t.cursor==t.start)}else{var r=this.session.documentToScreenPosition(this.selectionLead),s=this.session.documentToScreenPosition(this.selectionAnchor),o=this.rectangularRangeBlock(r,s);o.forEach(this.addRange,this)}},this.rectangularRangeBlock=function(e,t,n){var r=[],s=e.column<t.column;if(s)var o=e.column,u=t.column,a=e.offsetX,f=t.offsetX;else var o=t.column,u=e.column,a=t.offsetX,f=e.offsetX;var l=e.row<t.row;if(l)var c=e.row,h=t.row;else var c=t.row,h=e.row;o<0&&(o=0),c<0&&(c=0),c==h&&(n=!0);for(var p=c;p<=h;p++){var d=i.fromPoints(this.session.screenToDocumentPosition(p,o,a),this.session.screenToDocumentPosition(p,u,f));if(d.isEmpty()){if(m&&v(d.end,m))break;var m=d.end}d.cursor=s?d.start:d.end,r.push(d)}l&&r.reverse();if(!n){var g=r.length-1;while(r[g].isEmpty()&&g>0)g--;if(g>0){var y=0;while(r[y].isEmpty())y++}for(var b=g;b>=y;b--)r[b].isEmpty()&&r.splice(b,1)}return r}}.call(s.prototype);var d=e(\"./editor\").Editor;(function(){this.updateSelectionMarkers=function(){this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.addSelectionMarker=function(e){e.cursor||(e.cursor=e.end);var t=this.getSelectionStyle();return e.marker=this.session.addMarker(e,\"ace_selection\",t),this.session.$selectionMarkers.push(e),this.session.selectionMarkerCount=this.session.$selectionMarkers.length,e},this.removeSelectionMarker=function(e){if(!e.marker)return;this.session.removeMarker(e.marker);var t=this.session.$selectionMarkers.indexOf(e);t!=-1&&this.session.$selectionMarkers.splice(t,1),this.session.selectionMarkerCount=this.session.$selectionMarkers.length},this.removeSelectionMarkers=function(e){var t=this.session.$selectionMarkers;for(var n=e.length;n--;){var r=e[n];if(!r.marker)continue;this.session.removeMarker(r.marker);var i=t.indexOf(r);i!=-1&&t.splice(i,1)}this.session.selectionMarkerCount=t.length},this.$onAddRange=function(e){this.addSelectionMarker(e.range),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onRemoveRange=function(e){this.removeSelectionMarkers(e.ranges),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onMultiSelect=function(e){if(this.inMultiSelectMode)return;this.inMultiSelectMode=!0,this.setStyle(\"ace_multiselect\"),this.keyBinding.addKeyboardHandler(f.keyboardHandler),this.commands.setDefaultHandler(\"exec\",this.$onMultiSelectExec),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onSingleSelect=function(e){if(this.session.multiSelect.inVirtualMode)return;this.inMultiSelectMode=!1,this.unsetStyle(\"ace_multiselect\"),this.keyBinding.removeKeyboardHandler(f.keyboardHandler),this.commands.removeDefaultHandler(\"exec\",this.$onMultiSelectExec),this.renderer.updateCursor(),this.renderer.updateBackMarkers(),this._emit(\"changeSelection\")},this.$onMultiSelectExec=function(e){var t=e.command,n=e.editor;if(!n.multiSelect)return;if(!t.multiSelectAction){var r=t.exec(n,e.args||{});n.multiSelect.addRange(n.multiSelect.toOrientedRange()),n.multiSelect.mergeOverlappingRanges()}else t.multiSelectAction==\"forEach\"?r=n.forEachSelection(t,e.args):t.multiSelectAction==\"forEachLine\"?r=n.forEachSelection(t,e.args,!0):t.multiSelectAction==\"single\"?(n.exitMultiSelectMode(),r=t.exec(n,e.args||{})):r=t.multiSelectAction(n,e.args||{});return r},this.forEachSelection=function(e,t,n){if(this.inVirtualSelectionMode)return;var r=n&&n.keepOrder,i=n==1||n&&n.$byLines,o=this.session,u=this.selection,a=u.rangeList,f=(r?u:a).ranges,l;if(!f.length)return e.exec?e.exec(this,t||{}):e(this,t||{});var c=u._eventRegistry;u._eventRegistry={};var h=new s(o);this.inVirtualSelectionMode=!0;for(var p=f.length;p--;){if(i)while(p>0&&f[p].start.row==f[p-1].end.row)p--;h.fromOrientedRange(f[p]),h.index=p,this.selection=o.selection=h;var d=e.exec?e.exec(this,t||{}):e(this,t||{});!l&&d!==undefined&&(l=d),h.toOrientedRange(f[p])}h.detach(),this.selection=o.selection=u,this.inVirtualSelectionMode=!1,u._eventRegistry=c,u.mergeOverlappingRanges();var v=this.renderer.$scrollAnimation;return this.onCursorChange(),this.onSelectionChange(),v&&v.from==v.to&&this.renderer.animateScrolling(v.from),l},this.exitMultiSelectMode=function(){if(!this.inMultiSelectMode||this.inVirtualSelectionMode)return;this.multiSelect.toSingleRange()},this.getSelectedText=function(){var e=\"\";if(this.inMultiSelectMode&&!this.inVirtualSelectionMode){var t=this.multiSelect.rangeList.ranges,n=[];for(var r=0;r<t.length;r++)n.push(this.session.getTextRange(t[r]));var i=this.session.getDocument().getNewLineCharacter();e=n.join(i),e.length==(n.length-1)*i.length&&(e=\"\")}else this.selection.isEmpty()||(e=this.session.getTextRange(this.getSelectionRange()));return e},this.$checkMultiselectChange=function(e,t){if(this.inMultiSelectMode&&!this.inVirtualSelectionMode){var n=this.multiSelect.ranges[0];if(this.multiSelect.isEmpty()&&t==this.multiSelect.anchor)return;var r=t==this.multiSelect.anchor?n.cursor==n.start?n.end:n.start:n.cursor;(r.row!=t.row||this.session.$clipPositionToDocument(r.row,r.column).column!=t.column)&&this.multiSelect.toSingleRange(this.multiSelect.toOrientedRange())}},this.findAll=function(e,t,n){t=t||{},t.needle=e||t.needle;if(t.needle==undefined){var r=this.selection.isEmpty()?this.selection.getWordRange():this.selection.getRange();t.needle=this.session.getTextRange(r)}this.$search.set(t);var i=this.$search.findAll(this.session);if(!i.length)return 0;this.$blockScrolling+=1;var s=this.multiSelect;n||s.toSingleRange(i[0]);for(var o=i.length;o--;)s.addRange(i[o],!0);return r&&s.rangeList.rangeAtPoint(r.start)&&s.addRange(r,!0),this.$blockScrolling-=1,i.length},this.selectMoreLines=function(e,t){var n=this.selection.toOrientedRange(),r=n.cursor==n.end,s=this.session.documentToScreenPosition(n.cursor);this.selection.$desiredColumn&&(s.column=this.selection.$desiredColumn);var o=this.session.screenToDocumentPosition(s.row+e,s.column);if(!n.isEmpty())var u=this.session.documentToScreenPosition(r?n.end:n.start),a=this.session.screenToDocumentPosition(u.row+e,u.column);else var a=o;if(r){var f=i.fromPoints(o,a);f.cursor=f.start}else{var f=i.fromPoints(a,o);f.cursor=f.end}f.desiredColumn=s.column;if(!this.selection.inMultiSelectMode)this.selection.addRange(n);else if(t)var l=n.cursor;this.selection.addRange(f),l&&this.selection.substractPoint(l)},this.transposeSelections=function(e){var t=this.session,n=t.multiSelect,r=n.ranges;for(var i=r.length;i--;){var s=r[i];if(s.isEmpty()){var o=t.getWordRange(s.start.row,s.start.column);s.start.row=o.start.row,s.start.column=o.start.column,s.end.row=o.end.row,s.end.column=o.end.column}}n.mergeOverlappingRanges();var u=[];for(var i=r.length;i--;){var s=r[i];u.unshift(t.getTextRange(s))}e<0?u.unshift(u.pop()):u.push(u.shift());for(var i=r.length;i--;){var s=r[i],o=s.clone();t.replace(s,u[i]),s.start.row=o.start.row,s.start.column=o.start.column}},this.selectMore=function(e,t,n){var r=this.session,i=r.multiSelect,s=i.toOrientedRange();if(s.isEmpty()){s=r.getWordRange(s.start.row,s.start.column),s.cursor=e==-1?s.start:s.end,this.multiSelect.addRange(s);if(n)return}var o=r.getTextRange(s),u=h(r,o,e);u&&(u.cursor=e==-1?u.start:u.end,this.$blockScrolling+=1,this.session.unfold(u),this.multiSelect.addRange(u),this.$blockScrolling-=1,this.renderer.scrollCursorIntoView(null,.5)),t&&this.multiSelect.substractPoint(s.cursor)},this.alignCursors=function(){var e=this.session,t=e.multiSelect,n=t.ranges,r=-1,s=n.filter(function(e){if(e.cursor.row==r)return!0;r=e.cursor.row});if(!n.length||s.length==n.length-1){var o=this.selection.getRange(),u=o.start.row,f=o.end.row,l=u==f;if(l){var c=this.session.getLength(),h;do h=this.session.getLine(f);while(/[=:]/.test(h)&&++f<c);do h=this.session.getLine(u);while(/[=:]/.test(h)&&--u>0);u<0&&(u=0),f>=c&&(f=c-1)}var p=this.session.removeFullLines(u,f);p=this.$reAlignText(p,l),this.session.insert({row:u,column:0},p.join(\"\\n\")+\"\\n\"),l||(o.start.column=0,o.end.column=p[p.length-1].length),this.selection.setRange(o)}else{s.forEach(function(e){t.substractPoint(e.cursor)});var d=0,v=Infinity,m=n.map(function(t){var n=t.cursor,r=e.getLine(n.row),i=r.substr(n.column).search(/\\S/g);return i==-1&&(i=0),n.column>d&&(d=n.column),i<v&&(v=i),i});n.forEach(function(t,n){var r=t.cursor,s=d-r.column,o=m[n]-v;s>o?e.insert(r,a.stringRepeat(\" \",s-o)):e.remove(new i(r.row,r.column,r.row,r.column-s+o)),t.start.column=t.end.column=d,t.start.row=t.end.row=r.row,t.cursor=t.end}),t.fromOrientedRange(n[0]),this.renderer.updateCursor(),this.renderer.updateBackMarkers()}},this.$reAlignText=function(e,t){function u(e){return a.stringRepeat(\" \",e)}function f(e){return e[2]?u(i)+e[2]+u(s-e[2].length+o)+e[4].replace(/^([=:])\\s+/,\"$1 \"):e[0]}function l(e){return e[2]?u(i+s-e[2].length)+e[2]+u(o,\" \")+e[4].replace(/^([=:])\\s+/,\"$1 \"):e[0]}function c(e){return e[2]?u(i)+e[2]+u(o)+e[4].replace(/^([=:])\\s+/,\"$1 \"):e[0]}var n=!0,r=!0,i,s,o;return e.map(function(e){var t=e.match(/(\\s*)(.*?)(\\s*)([=:].*)/);return t?i==null?(i=t[1].length,s=t[2].length,o=t[3].length,t):(i+s+o!=t[1].length+t[2].length+t[3].length&&(r=!1),i!=t[1].length&&(n=!1),i>t[1].length&&(i=t[1].length),s<t[2].length&&(s=t[2].length),o>t[3].length&&(o=t[3].length),t):[e]}).map(t?f:n?r?l:f:c)}}).call(d.prototype),t.onSessionChange=function(e){var t=e.session;t&&!t.multiSelect&&(t.$selectionMarkers=[],t.selection.$initRangeList(),t.multiSelect=t.selection),this.multiSelect=t&&t.multiSelect;var n=e.oldSession;n&&(n.multiSelect.off(\"addRange\",this.$onAddRange),n.multiSelect.off(\"removeRange\",this.$onRemoveRange),n.multiSelect.off(\"multiSelect\",this.$onMultiSelect),n.multiSelect.off(\"singleSelect\",this.$onSingleSelect),n.multiSelect.lead.off(\"change\",this.$checkMultiselectChange),n.multiSelect.anchor.off(\"change\",this.$checkMultiselectChange)),t&&(t.multiSelect.on(\"addRange\",this.$onAddRange),t.multiSelect.on(\"removeRange\",this.$onRemoveRange),t.multiSelect.on(\"multiSelect\",this.$onMultiSelect),t.multiSelect.on(\"singleSelect\",this.$onSingleSelect),t.multiSelect.lead.on(\"change\",this.$checkMultiselectChange),t.multiSelect.anchor.on(\"change\",this.$checkMultiselectChange)),t&&this.inMultiSelectMode!=t.selection.inMultiSelectMode&&(t.selection.inMultiSelectMode?this.$onMultiSelect():this.$onSingleSelect())},t.MultiSelect=m,e(\"./config\").defineOptions(d.prototype,\"editor\",{enableMultiselect:{set:function(e){m(this),e?(this.on(\"changeSession\",this.$multiselectOnSessionChange),this.on(\"mousedown\",o)):(this.off(\"changeSession\",this.$multiselectOnSessionChange),this.off(\"mousedown\",o))},value:!0},enableBlockSelect:{set:function(e){this.$blockSelectEnabled=e},value:!0}})}),define(\"ace/mode/folding/fold_mode\",[\"require\",\"exports\",\"module\",\"ace/range\"],function(e,t,n){\"use strict\";var r=e(\"../../range\").Range,i=t.FoldMode=function(){};(function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(e,t,n){var r=e.getLine(n);return this.foldingStartMarker.test(r)?\"start\":t==\"markbeginend\"&&this.foldingStopMarker&&this.foldingStopMarker.test(r)?\"end\":\"\"},this.getFoldWidgetRange=function(e,t,n){return null},this.indentationBlock=function(e,t,n){var i=/\\S/,s=e.getLine(t),o=s.search(i);if(o==-1)return;var u=n||s.length,a=e.getLength(),f=t,l=t;while(++t<a){var c=e.getLine(t).search(i);if(c==-1)continue;if(c<=o)break;l=t}if(l>f){var h=e.getLine(l).length;return new r(f,u,l,h)}},this.openingBracketBlock=function(e,t,n,i,s){var o={row:n,column:i+1},u=e.$findClosingBracket(t,o,s);if(!u)return;var a=e.foldWidgets[u.row];return a==null&&(a=e.getFoldWidget(u.row)),a==\"start\"&&u.row>o.row&&(u.row--,u.column=e.getLine(u.row).length),r.fromPoints(o,u)},this.closingBracketBlock=function(e,t,n,i,s){var o={row:n,column:i},u=e.$findOpeningBracket(t,o);if(!u)return;return u.column++,o.column--,r.fromPoints(u,o)}}).call(i.prototype)}),define(\"ace/theme/textmate\",[\"require\",\"exports\",\"module\",\"ace/lib/dom\"],function(e,t,n){\"use strict\";t.isDark=!1,t.cssClass=\"ace-tm\",t.cssText='.ace-tm .ace_gutter {background: #f0f0f0;color: #333;}.ace-tm .ace_print-margin {width: 1px;background: #e8e8e8;}.ace-tm .ace_fold {background-color: #6B72E6;}.ace-tm {background-color: #FFFFFF;color: black;}.ace-tm .ace_cursor {color: black;}.ace-tm .ace_invisible {color: rgb(191, 191, 191);}.ace-tm .ace_storage,.ace-tm .ace_keyword {color: blue;}.ace-tm .ace_constant {color: rgb(197, 6, 11);}.ace-tm .ace_constant.ace_buildin {color: rgb(88, 72, 246);}.ace-tm .ace_constant.ace_language {color: rgb(88, 92, 246);}.ace-tm .ace_constant.ace_library {color: rgb(6, 150, 14);}.ace-tm .ace_invalid {background-color: rgba(255, 0, 0, 0.1);color: red;}.ace-tm .ace_support.ace_function {color: rgb(60, 76, 114);}.ace-tm .ace_support.ace_constant {color: rgb(6, 150, 14);}.ace-tm .ace_support.ace_type,.ace-tm .ace_support.ace_class {color: rgb(109, 121, 222);}.ace-tm .ace_keyword.ace_operator {color: rgb(104, 118, 135);}.ace-tm .ace_string {color: rgb(3, 106, 7);}.ace-tm .ace_comment {color: rgb(76, 136, 107);}.ace-tm .ace_comment.ace_doc {color: rgb(0, 102, 255);}.ace-tm .ace_comment.ace_doc.ace_tag {color: rgb(128, 159, 191);}.ace-tm .ace_constant.ace_numeric {color: rgb(0, 0, 205);}.ace-tm .ace_variable {color: rgb(49, 132, 149);}.ace-tm .ace_xml-pe {color: rgb(104, 104, 91);}.ace-tm .ace_entity.ace_name.ace_function {color: #0000A2;}.ace-tm .ace_heading {color: rgb(12, 7, 255);}.ace-tm .ace_list {color:rgb(185, 6, 144);}.ace-tm .ace_meta.ace_tag {color:rgb(0, 22, 142);}.ace-tm .ace_string.ace_regex {color: rgb(255, 0, 0)}.ace-tm .ace_marker-layer .ace_selection {background: rgb(181, 213, 255);}.ace-tm.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px white;}.ace-tm .ace_marker-layer .ace_step {background: rgb(252, 255, 0);}.ace-tm .ace_marker-layer .ace_stack {background: rgb(164, 229, 101);}.ace-tm .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid rgb(192, 192, 192);}.ace-tm .ace_marker-layer .ace_active-line {background: rgba(0, 0, 0, 0.07);}.ace-tm .ace_gutter-active-line {background-color : #dcdcdc;}.ace-tm .ace_marker-layer .ace_selected-word {background: rgb(250, 250, 255);border: 1px solid rgb(200, 200, 250);}.ace-tm .ace_indent-guide {background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==\") right repeat-y;}';var r=e(\"../lib/dom\");r.importCssString(t.cssText,t.cssClass)}),define(\"ace/line_widgets\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/dom\",\"ace/range\"],function(e,t,n){\"use strict\";function o(e){this.session=e,this.session.widgetManager=this,this.session.getRowLength=this.getRowLength,this.session.$getWidgetScreenLength=this.$getWidgetScreenLength,this.updateOnChange=this.updateOnChange.bind(this),this.renderWidgets=this.renderWidgets.bind(this),this.measureWidgets=this.measureWidgets.bind(this),this.session._changedWidgets=[],this.$onChangeEditor=this.$onChangeEditor.bind(this),this.session.on(\"change\",this.updateOnChange),this.session.on(\"changeFold\",this.updateOnFold),this.session.on(\"changeEditor\",this.$onChangeEditor)}var r=e(\"./lib/oop\"),i=e(\"./lib/dom\"),s=e(\"./range\").Range;(function(){this.getRowLength=function(e){var t;return this.lineWidgets?t=this.lineWidgets[e]&&this.lineWidgets[e].rowCount||0:t=0,!this.$useWrapMode||!this.$wrapData[e]?1+t:this.$wrapData[e].length+1+t},this.$getWidgetScreenLength=function(){var e=0;return this.lineWidgets.forEach(function(t){t&&t.rowCount&&!t.hidden&&(e+=t.rowCount)}),e},this.$onChangeEditor=function(e){this.attach(e.editor)},this.attach=function(e){e&&e.widgetManager&&e.widgetManager!=this&&e.widgetManager.detach();if(this.editor==e)return;this.detach(),this.editor=e,e&&(e.widgetManager=this,e.renderer.on(\"beforeRender\",this.measureWidgets),e.renderer.on(\"afterRender\",this.renderWidgets))},this.detach=function(e){var t=this.editor;if(!t)return;this.editor=null,t.widgetManager=null,t.renderer.off(\"beforeRender\",this.measureWidgets),t.renderer.off(\"afterRender\",this.renderWidgets);var n=this.session.lineWidgets;n&&n.forEach(function(e){e&&e.el&&e.el.parentNode&&(e._inDocument=!1,e.el.parentNode.removeChild(e.el))})},this.updateOnFold=function(e,t){var n=t.lineWidgets;if(!n||!e.action)return;var r=e.data,i=r.start.row,s=r.end.row,o=e.action==\"add\";for(var u=i+1;u<s;u++)n[u]&&(n[u].hidden=o);n[s]&&(o?n[i]?n[s].hidden=o:n[i]=n[s]:(n[i]==n[s]&&(n[i]=undefined),n[s].hidden=o))},this.updateOnChange=function(e){var t=this.session.lineWidgets;if(!t)return;var n=e.start.row,r=e.end.row-n;if(r!==0)if(e.action==\"remove\"){var i=t.splice(n+1,r);i.forEach(function(e){e&&this.removeLineWidget(e)},this),this.$updateRows()}else{var s=new Array(r);s.unshift(n,0),t.splice.apply(t,s),this.$updateRows()}},this.$updateRows=function(){var e=this.session.lineWidgets;if(!e)return;var t=!0;e.forEach(function(e,n){if(e){t=!1,e.row=n;while(e.$oldWidget)e.$oldWidget.row=n,e=e.$oldWidget}}),t&&(this.session.lineWidgets=null)},this.addLineWidget=function(e){this.session.lineWidgets||(this.session.lineWidgets=new Array(this.session.getLength()));var t=this.session.lineWidgets[e.row];t&&(e.$oldWidget=t,t.el&&t.el.parentNode&&(t.el.parentNode.removeChild(t.el),t._inDocument=!1)),this.session.lineWidgets[e.row]=e,e.session=this.session;var n=this.editor.renderer;e.html&&!e.el&&(e.el=i.createElement(\"div\"),e.el.innerHTML=e.html),e.el&&(i.addCssClass(e.el,\"ace_lineWidgetContainer\"),e.el.style.position=\"absolute\",e.el.style.zIndex=5,n.container.appendChild(e.el),e._inDocument=!0),e.coverGutter||(e.el.style.zIndex=3),e.pixelHeight==null&&(e.pixelHeight=e.el.offsetHeight),e.rowCount==null&&(e.rowCount=e.pixelHeight/n.layerConfig.lineHeight);var r=this.session.getFoldAt(e.row,0);e.$fold=r;if(r){var s=this.session.lineWidgets;e.row==r.end.row&&!s[r.start.row]?s[r.start.row]=e:e.hidden=!0}return this.session._emit(\"changeFold\",{data:{start:{row:e.row}}}),this.$updateRows(),this.renderWidgets(null,n),this.onWidgetChanged(e),e},this.removeLineWidget=function(e){e._inDocument=!1,e.session=null,e.el&&e.el.parentNode&&e.el.parentNode.removeChild(e.el);if(e.editor&&e.editor.destroy)try{e.editor.destroy()}catch(t){}if(this.session.lineWidgets){var n=this.session.lineWidgets[e.row];if(n==e)this.session.lineWidgets[e.row]=e.$oldWidget,e.$oldWidget&&this.onWidgetChanged(e.$oldWidget);else while(n){if(n.$oldWidget==e){n.$oldWidget=e.$oldWidget;break}n=n.$oldWidget}}this.session._emit(\"changeFold\",{data:{start:{row:e.row}}}),this.$updateRows()},this.getWidgetsAtRow=function(e){var t=this.session.lineWidgets,n=t&&t[e],r=[];while(n)r.push(n),n=n.$oldWidget;return r},this.onWidgetChanged=function(e){this.session._changedWidgets.push(e),this.editor&&this.editor.renderer.updateFull()},this.measureWidgets=function(e,t){var n=this.session._changedWidgets,r=t.layerConfig;if(!n||!n.length)return;var i=Infinity;for(var s=0;s<n.length;s++){var o=n[s];if(!o||!o.el)continue;if(o.session!=this.session)continue;if(!o._inDocument){if(this.session.lineWidgets[o.row]!=o)continue;o._inDocument=!0,t.container.appendChild(o.el)}o.h=o.el.offsetHeight,o.fixedWidth||(o.w=o.el.offsetWidth,o.screenWidth=Math.ceil(o.w/r.characterWidth));var u=o.h/r.lineHeight;o.coverLine&&(u-=this.session.getRowLineCount(o.row),u<0&&(u=0)),o.rowCount!=u&&(o.rowCount=u,o.row<i&&(i=o.row))}i!=Infinity&&(this.session._emit(\"changeFold\",{data:{start:{row:i}}}),this.session.lineWidgetWidth=null),this.session._changedWidgets=[]},this.renderWidgets=function(e,t){var n=t.layerConfig,r=this.session.lineWidgets;if(!r)return;var i=Math.min(this.firstRow,n.firstRow),s=Math.max(this.lastRow,n.lastRow,r.length);while(i>0&&!r[i])i--;this.firstRow=n.firstRow,this.lastRow=n.lastRow,t.$cursorLayer.config=n;for(var o=i;o<=s;o++){var u=r[o];if(!u||!u.el)continue;if(u.hidden){u.el.style.top=-100-(u.pixelHeight||0)+\"px\";continue}u._inDocument||(u._inDocument=!0,t.container.appendChild(u.el));var a=t.$cursorLayer.getPixelPosition({row:o,column:0},!0).top;u.coverLine||(a+=n.lineHeight*this.session.getRowLineCount(u.row)),u.el.style.top=a-n.offset+\"px\";var f=u.coverGutter?0:t.gutterWidth;u.fixedWidth||(f-=t.scrollLeft),u.el.style.left=f+\"px\",u.fullWidth&&u.screenWidth&&(u.el.style.minWidth=n.width+2*n.padding+\"px\"),u.fixedWidth?u.el.style.right=t.scrollBar.getWidth()+\"px\":u.el.style.right=\"\"}}}).call(o.prototype),t.LineWidgets=o}),define(\"ace/ext/error_marker\",[\"require\",\"exports\",\"module\",\"ace/line_widgets\",\"ace/lib/dom\",\"ace/range\"],function(e,t,n){\"use strict\";function o(e,t,n){var r=0,i=e.length-1;while(r<=i){var s=r+i>>1,o=n(t,e[s]);if(o>0)r=s+1;else{if(!(o<0))return s;i=s-1}}return-(r+1)}function u(e,t,n){var r=e.getAnnotations().sort(s.comparePoints);if(!r.length)return;var i=o(r,{row:t,column:-1},s.comparePoints);i<0&&(i=-i-1),i>=r.length?i=n>0?0:r.length-1:i===0&&n<0&&(i=r.length-1);var u=r[i];if(!u||!n)return;if(u.row===t){do u=r[i+=n];while(u&&u.row===t);if(!u)return r.slice()}var a=[];t=u.row;do a[n<0?\"unshift\":\"push\"](u),u=r[i+=n];while(u&&u.row==t);return a.length&&a}var r=e(\"../line_widgets\").LineWidgets,i=e(\"../lib/dom\"),s=e(\"../range\").Range;t.showErrorMarker=function(e,t){var n=e.session;n.widgetManager||(n.widgetManager=new r(n),n.widgetManager.attach(e));var s=e.getCursorPosition(),o=s.row,a=n.widgetManager.getWidgetsAtRow(o).filter(function(e){return e.type==\"errorMarker\"})[0];a?a.destroy():o-=t;var f=u(n,o,t),l;if(f){var c=f[0];s.column=(c.pos&&typeof c.column!=\"number\"?c.pos.sc:c.column)||0,s.row=c.row,l=e.renderer.$gutterLayer.$annotations[s.row]}else{if(a)return;l={text:[\"Looks good!\"],className:\"ace_ok\"}}e.session.unfold(s.row),e.selection.moveToPosition(s);var h={row:s.row,fixedWidth:!0,coverGutter:!0,el:i.createElement(\"div\"),type:\"errorMarker\"},p=h.el.appendChild(i.createElement(\"div\")),d=h.el.appendChild(i.createElement(\"div\"));d.className=\"error_widget_arrow \"+l.className;var v=e.renderer.$cursorLayer.getPixelPosition(s).left;d.style.left=v+e.renderer.gutterWidth-5+\"px\",h.el.className=\"error_widget_wrapper\",p.className=\"error_widget \"+l.className,p.innerHTML=l.text.join(\"<br>\"),p.appendChild(i.createElement(\"div\"));var m=function(e,t,n){if(t===0&&(n===\"esc\"||n===\"return\"))return h.destroy(),{command:\"null\"}};h.destroy=function(){if(e.$mouseHandler.isMousePressed)return;e.keyBinding.removeKeyboardHandler(m),n.widgetManager.removeLineWidget(h),e.off(\"changeSelection\",h.destroy),e.off(\"changeSession\",h.destroy),e.off(\"mouseup\",h.destroy),e.off(\"change\",h.destroy)},e.keyBinding.addKeyboardHandler(m),e.on(\"changeSelection\",h.destroy),e.on(\"changeSession\",h.destroy),e.on(\"mouseup\",h.destroy),e.on(\"change\",h.destroy),e.session.widgetManager.addLineWidget(h),h.el.onmousedown=e.focus.bind(e),e.renderer.scrollCursorIntoView(null,.5,{bottom:h.el.offsetHeight})},i.importCssString(\"    .error_widget_wrapper {        background: inherit;        color: inherit;        border:none    }    .error_widget {        border-top: solid 2px;        border-bottom: solid 2px;        margin: 5px 0;        padding: 10px 40px;        white-space: pre-wrap;    }    .error_widget.ace_error, .error_widget_arrow.ace_error{        border-color: #ff5a5a    }    .error_widget.ace_warning, .error_widget_arrow.ace_warning{        border-color: #F1D817    }    .error_widget.ace_info, .error_widget_arrow.ace_info{        border-color: #5a5a5a    }    .error_widget.ace_ok, .error_widget_arrow.ace_ok{        border-color: #5aaa5a    }    .error_widget_arrow {        position: absolute;        border: solid 5px;        border-top-color: transparent!important;        border-right-color: transparent!important;        border-left-color: transparent!important;        top: -5px;    }\",\"\")}),define(\"ace/ace\",[\"require\",\"exports\",\"module\",\"ace/lib/fixoldbrowsers\",\"ace/lib/dom\",\"ace/lib/event\",\"ace/editor\",\"ace/edit_session\",\"ace/undomanager\",\"ace/virtual_renderer\",\"ace/worker/worker_client\",\"ace/keyboard/hash_handler\",\"ace/placeholder\",\"ace/multi_select\",\"ace/mode/folding/fold_mode\",\"ace/theme/textmate\",\"ace/ext/error_marker\",\"ace/config\"],function(e,t,n){\"use strict\";e(\"./lib/fixoldbrowsers\");var r=e(\"./lib/dom\"),i=e(\"./lib/event\"),s=e(\"./editor\").Editor,o=e(\"./edit_session\").EditSession,u=e(\"./undomanager\").UndoManager,a=e(\"./virtual_renderer\").VirtualRenderer;e(\"./worker/worker_client\"),e(\"./keyboard/hash_handler\"),e(\"./placeholder\"),e(\"./multi_select\"),e(\"./mode/folding/fold_mode\"),e(\"./theme/textmate\"),e(\"./ext/error_marker\"),t.config=e(\"./config\"),t.require=e,typeof define==\"function\"&&(t.define=define),t.edit=function(e){if(typeof e==\"string\"){var n=e;e=document.getElementById(n);if(!e)throw new Error(\"ace.edit can't find div #\"+n)}if(e&&e.env&&e.env.editor instanceof s)return e.env.editor;var o=\"\";if(e&&/input|textarea/i.test(e.tagName)){var u=e;o=u.value,e=r.createElement(\"pre\"),u.parentNode.replaceChild(e,u)}else e&&(o=r.getInnerText(e),e.innerHTML=\"\");var f=t.createEditSession(o),l=new s(new a(e));l.setSession(f);var c={document:f,editor:l,onResize:l.resize.bind(l,null)};return u&&(c.textarea=u),i.addListener(window,\"resize\",c.onResize),l.on(\"destroy\",function(){i.removeListener(window,\"resize\",c.onResize),c.editor.container.env=null}),l.container.env=l.env=c,l},t.createEditSession=function(e,t){var n=new o(e,t);return n.setUndoManager(new u),n},t.EditSession=o,t.UndoManager=u,t.version=\"1.2.9\"});\n(function() {\n    window.require([\"ace/ace\"], function(a) {\n        if (a) {\n            a.config.init(true);\n            a.define = window.define;\n        }\n        if (!window.ace)\n            window.ace = a;\n        for (var key in a) if (a.hasOwnProperty(key))\n            window.ace[key] = a[key];\n    });\n})();\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/vendor/ui-ace/mode-json.js",
    "content": "define(\"ace/mode/json_highlight_rules\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/mode/text_highlight_rules\"],function(e,t,n){\"use strict\";var r=e(\"../lib/oop\"),i=e(\"./text_highlight_rules\").TextHighlightRules,s=function(){this.$rules={start:[{token:\"variable\",regex:'[\"](?:(?:\\\\\\\\.)|(?:[^\"\\\\\\\\]))*?[\"]\\\\s*(?=:)'},{token:\"string\",regex:'\"',next:\"string\"},{token:\"constant.numeric\",regex:\"0[xX][0-9a-fA-F]+\\\\b\"},{token:\"constant.numeric\",regex:\"[+-]?\\\\d+(?:(?:\\\\.\\\\d*)?(?:[eE][+-]?\\\\d+)?)?\\\\b\"},{token:\"constant.language.boolean\",regex:\"(?:true|false)\\\\b\"},{token:\"text\",regex:\"['](?:(?:\\\\\\\\.)|(?:[^'\\\\\\\\]))*?[']\"},{token:\"comment\",regex:\"\\\\/\\\\/.*$\"},{token:\"comment.start\",regex:\"\\\\/\\\\*\",next:\"comment\"},{token:\"paren.lparen\",regex:\"[[({]\"},{token:\"paren.rparen\",regex:\"[\\\\])}]\"},{token:\"text\",regex:\"\\\\s+\"}],string:[{token:\"constant.language.escape\",regex:/\\\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|[\"\\\\\\/bfnrt])/},{token:\"string\",regex:'\"|$',next:\"start\"},{defaultToken:\"string\"}],comment:[{token:\"comment.end\",regex:\"\\\\*\\\\/\",next:\"start\"},{defaultToken:\"comment\"}]}};r.inherits(s,i),t.JsonHighlightRules=s}),define(\"ace/mode/matching_brace_outdent\",[\"require\",\"exports\",\"module\",\"ace/range\"],function(e,t,n){\"use strict\";var r=e(\"../range\").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\\s+$/.test(e)?/^\\s*\\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\\s*\\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){return e.match(/^\\s*/)[0]}}).call(i.prototype),t.MatchingBraceOutdent=i}),define(\"ace/mode/folding/cstyle\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/range\",\"ace/mode/folding/fold_mode\"],function(e,t,n){\"use strict\";var r=e(\"../../lib/oop\"),i=e(\"../../range\").Range,s=e(\"./fold_mode\").FoldMode,o=t.FoldMode=function(e){e&&(this.foldingStartMarker=new RegExp(this.foldingStartMarker.source.replace(/\\|[^|]*?$/,\"|\"+e.start)),this.foldingStopMarker=new RegExp(this.foldingStopMarker.source.replace(/\\|[^|]*?$/,\"|\"+e.end)))};r.inherits(o,s),function(){this.foldingStartMarker=/([\\{\\[\\(])[^\\}\\]\\)]*$|^\\s*(\\/\\*)/,this.foldingStopMarker=/^[^\\[\\{\\(]*([\\}\\]\\)])|^[\\s\\*]*(\\*\\/)/,this.singleLineBlockCommentRe=/^\\s*(\\/\\*).*\\*\\/\\s*$/,this.tripleStarBlockCommentRe=/^\\s*(\\/\\*\\*\\*).*\\*\\/\\s*$/,this.startRegionRe=/^\\s*(\\/\\*|\\/\\/)#?region\\b/,this._getFoldWidgetBase=this.getFoldWidget,this.getFoldWidget=function(e,t,n){var r=e.getLine(n);if(this.singleLineBlockCommentRe.test(r)&&!this.startRegionRe.test(r)&&!this.tripleStarBlockCommentRe.test(r))return\"\";var i=this._getFoldWidgetBase(e,t,n);return!i&&this.startRegionRe.test(r)?\"start\":i},this.getFoldWidgetRange=function(e,t,n,r){var i=e.getLine(n);if(this.startRegionRe.test(i))return this.getCommentRegionBlock(e,i,n);var s=i.match(this.foldingStartMarker);if(s){var o=s.index;if(s[1])return this.openingBracketBlock(e,s[1],n,o);var u=e.getCommentFoldRange(n,o+s[0].length,1);return u&&!u.isMultiLine()&&(r?u=this.getSectionRange(e,n):t!=\"all\"&&(u=null)),u}if(t===\"markbegin\")return;var s=i.match(this.foldingStopMarker);if(s){var o=s.index+s[0].length;return s[1]?this.closingBracketBlock(e,s[1],n,o):e.getCommentFoldRange(n,o,-1)}},this.getSectionRange=function(e,t){var n=e.getLine(t),r=n.search(/\\S/),s=t,o=n.length;t+=1;var u=t,a=e.getLength();while(++t<a){n=e.getLine(t);var f=n.search(/\\S/);if(f===-1)continue;if(r>f)break;var l=this.getFoldWidgetRange(e,\"all\",t);if(l){if(l.start.row<=s)break;if(l.isMultiLine())t=l.end.row;else if(r==f)break}u=t}return new i(s,o,u,e.getLine(u).length)},this.getCommentRegionBlock=function(e,t,n){var r=t.search(/\\s*$/),s=e.getLength(),o=n,u=/^\\s*(?:\\/\\*|\\/\\/|--)#?(end)?region\\b/,a=1;while(++n<s){t=e.getLine(n);var f=u.exec(t);if(!f)continue;f[1]?a--:a++;if(!a)break}var l=n;if(l>o)return new i(o,r,l,t.length)}}.call(o.prototype)}),define(\"ace/mode/json\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/mode/text\",\"ace/mode/json_highlight_rules\",\"ace/mode/matching_brace_outdent\",\"ace/mode/behaviour/cstyle\",\"ace/mode/folding/cstyle\",\"ace/worker/worker_client\"],function(e,t,n){\"use strict\";var r=e(\"../lib/oop\"),i=e(\"./text\").Mode,s=e(\"./json_highlight_rules\").JsonHighlightRules,o=e(\"./matching_brace_outdent\").MatchingBraceOutdent,u=e(\"./behaviour/cstyle\").CstyleBehaviour,a=e(\"./folding/cstyle\").FoldMode,f=e(\"../worker/worker_client\").WorkerClient,l=function(){this.HighlightRules=s,this.$outdent=new o,this.$behaviour=new u,this.foldingRules=new a};r.inherits(l,i),function(){this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t);if(e==\"start\"){var i=t.match(/^.*[\\{\\(\\[]\\s*$/);i&&(r+=n)}return r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.createWorker=function(e){var t=new f([\"ace\"],\"ace/mode/json_worker\",\"JsonWorker\");return t.attachToDocument(e.getDocument()),t.on(\"annotate\",function(t){e.setAnnotations(t.data)}),t.on(\"terminate\",function(){e.clearAnnotations()}),t},this.$id=\"ace/mode/json\"}.call(l.prototype),t.Mode=l})\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/vendor/ui-ace/mode-properties.js",
    "content": "define(\"ace/mode/properties_highlight_rules\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/mode/text_highlight_rules\"],function(e,t,n){\"use strict\";var r=e(\"../lib/oop\"),i=e(\"./text_highlight_rules\").TextHighlightRules,s=function(){var e=/\\\\u[0-9a-fA-F]{4}|\\\\/;this.$rules={start:[{token:\"comment\",regex:/[!#].*$/},{token:\"keyword\",regex:/[=:]$/},{token:\"keyword\",regex:/[=:]/,next:\"value\"},{token:\"constant.language.escape\",regex:e},{defaultToken:\"variable\"}],value:[{regex:/\\\\$/,token:\"string\",next:\"value\"},{regex:/$/,token:\"string\",next:\"start\"},{token:\"constant.language.escape\",regex:e},{defaultToken:\"string\"}]}};r.inherits(s,i),t.PropertiesHighlightRules=s}),define(\"ace/mode/properties\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/mode/text\",\"ace/mode/properties_highlight_rules\"],function(e,t,n){\"use strict\";var r=e(\"../lib/oop\"),i=e(\"./text\").Mode,s=e(\"./properties_highlight_rules\").PropertiesHighlightRules,o=function(){this.HighlightRules=s,this.$behaviour=this.$defaultBehaviour};r.inherits(o,i),function(){this.$id=\"ace/mode/properties\"}.call(o.prototype),t.Mode=o})\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/vendor/ui-ace/mode-xml.js",
    "content": "define(\"ace/mode/xml_highlight_rules\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/mode/text_highlight_rules\"],function(e,t,n){\"use strict\";var r=e(\"../lib/oop\"),i=e(\"./text_highlight_rules\").TextHighlightRules,s=function(e){var t=\"[_:a-zA-Z\\u00c0-\\uffff][-_:.a-zA-Z0-9\\u00c0-\\uffff]*\";this.$rules={start:[{token:\"string.cdata.xml\",regex:\"<\\\\!\\\\[CDATA\\\\[\",next:\"cdata\"},{token:[\"punctuation.instruction.xml\",\"keyword.instruction.xml\"],regex:\"(<\\\\?)(\"+t+\")\",next:\"processing_instruction\"},{token:\"comment.start.xml\",regex:\"<\\\\!--\",next:\"comment\"},{token:[\"xml-pe.doctype.xml\",\"xml-pe.doctype.xml\"],regex:\"(<\\\\!)(DOCTYPE)(?=[\\\\s])\",next:\"doctype\",caseInsensitive:!0},{include:\"tag\"},{token:\"text.end-tag-open.xml\",regex:\"</\"},{token:\"text.tag-open.xml\",regex:\"<\"},{include:\"reference\"},{defaultToken:\"text.xml\"}],processing_instruction:[{token:\"entity.other.attribute-name.decl-attribute-name.xml\",regex:t},{token:\"keyword.operator.decl-attribute-equals.xml\",regex:\"=\"},{include:\"whitespace\"},{include:\"string\"},{token:\"punctuation.xml-decl.xml\",regex:\"\\\\?>\",next:\"start\"}],doctype:[{include:\"whitespace\"},{include:\"string\"},{token:\"xml-pe.doctype.xml\",regex:\">\",next:\"start\"},{token:\"xml-pe.xml\",regex:\"[-_a-zA-Z0-9:]+\"},{token:\"punctuation.int-subset\",regex:\"\\\\[\",push:\"int_subset\"}],int_subset:[{token:\"text.xml\",regex:\"\\\\s+\"},{token:\"punctuation.int-subset.xml\",regex:\"]\",next:\"pop\"},{token:[\"punctuation.markup-decl.xml\",\"keyword.markup-decl.xml\"],regex:\"(<\\\\!)(\"+t+\")\",push:[{token:\"text\",regex:\"\\\\s+\"},{token:\"punctuation.markup-decl.xml\",regex:\">\",next:\"pop\"},{include:\"string\"}]}],cdata:[{token:\"string.cdata.xml\",regex:\"\\\\]\\\\]>\",next:\"start\"},{token:\"text.xml\",regex:\"\\\\s+\"},{token:\"text.xml\",regex:\"(?:[^\\\\]]|\\\\](?!\\\\]>))+\"}],comment:[{token:\"comment.end.xml\",regex:\"-->\",next:\"start\"},{defaultToken:\"comment.xml\"}],reference:[{token:\"constant.language.escape.reference.xml\",regex:\"(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\\\.-]+;)\"}],attr_reference:[{token:\"constant.language.escape.reference.attribute-value.xml\",regex:\"(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\\\.-]+;)\"}],tag:[{token:[\"meta.tag.punctuation.tag-open.xml\",\"meta.tag.punctuation.end-tag-open.xml\",\"meta.tag.tag-name.xml\"],regex:\"(?:(<)|(</))((?:\"+t+\":)?\"+t+\")\",next:[{include:\"attributes\"},{token:\"meta.tag.punctuation.tag-close.xml\",regex:\"/?>\",next:\"start\"}]}],tag_whitespace:[{token:\"text.tag-whitespace.xml\",regex:\"\\\\s+\"}],whitespace:[{token:\"text.whitespace.xml\",regex:\"\\\\s+\"}],string:[{token:\"string.xml\",regex:\"'\",push:[{token:\"string.xml\",regex:\"'\",next:\"pop\"},{defaultToken:\"string.xml\"}]},{token:\"string.xml\",regex:'\"',push:[{token:\"string.xml\",regex:'\"',next:\"pop\"},{defaultToken:\"string.xml\"}]}],attributes:[{token:\"entity.other.attribute-name.xml\",regex:t},{token:\"keyword.operator.attribute-equals.xml\",regex:\"=\"},{include:\"tag_whitespace\"},{include:\"attribute_value\"}],attribute_value:[{token:\"string.attribute-value.xml\",regex:\"'\",push:[{token:\"string.attribute-value.xml\",regex:\"'\",next:\"pop\"},{include:\"attr_reference\"},{defaultToken:\"string.attribute-value.xml\"}]},{token:\"string.attribute-value.xml\",regex:'\"',push:[{token:\"string.attribute-value.xml\",regex:'\"',next:\"pop\"},{include:\"attr_reference\"},{defaultToken:\"string.attribute-value.xml\"}]}]},this.constructor===s&&this.normalizeRules()};(function(){this.embedTagRules=function(e,t,n){this.$rules.tag.unshift({token:[\"meta.tag.punctuation.tag-open.xml\",\"meta.tag.\"+n+\".tag-name.xml\"],regex:\"(<)(\"+n+\"(?=\\\\s|>|$))\",next:[{include:\"attributes\"},{token:\"meta.tag.punctuation.tag-close.xml\",regex:\"/?>\",next:t+\"start\"}]}),this.$rules[n+\"-end\"]=[{include:\"attributes\"},{token:\"meta.tag.punctuation.tag-close.xml\",regex:\"/?>\",next:\"start\",onMatch:function(e,t,n){return n.splice(0),this.token}}],this.embedRules(e,t,[{token:[\"meta.tag.punctuation.end-tag-open.xml\",\"meta.tag.\"+n+\".tag-name.xml\"],regex:\"(</)(\"+n+\"(?=\\\\s|>|$))\",next:n+\"-end\"},{token:\"string.cdata.xml\",regex:\"<\\\\!\\\\[CDATA\\\\[\"},{token:\"string.cdata.xml\",regex:\"\\\\]\\\\]>\"}])}}).call(i.prototype),r.inherits(s,i),t.XmlHighlightRules=s}),define(\"ace/mode/behaviour/xml\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/mode/behaviour\",\"ace/token_iterator\",\"ace/lib/lang\"],function(e,t,n){\"use strict\";function u(e,t){return e.type.lastIndexOf(t+\".xml\")>-1}var r=e(\"../../lib/oop\"),i=e(\"../behaviour\").Behaviour,s=e(\"../../token_iterator\").TokenIterator,o=e(\"../../lib/lang\"),a=function(){this.add(\"string_dquotes\",\"insertion\",function(e,t,n,r,i){if(i=='\"'||i==\"'\"){var o=i,a=r.doc.getTextRange(n.getSelectionRange());if(a!==\"\"&&a!==\"'\"&&a!='\"'&&n.getWrapBehavioursEnabled())return{text:o+a+o,selection:!1};var f=n.getCursorPosition(),l=r.doc.getLine(f.row),c=l.substring(f.column,f.column+1),h=new s(r,f.row,f.column),p=h.getCurrentToken();if(c==o&&(u(p,\"attribute-value\")||u(p,\"string\")))return{text:\"\",selection:[1,1]};p||(p=h.stepBackward());if(!p)return;while(u(p,\"tag-whitespace\")||u(p,\"whitespace\"))p=h.stepBackward();var d=!c||c.match(/\\s/);if(u(p,\"attribute-equals\")&&(d||c==\">\")||u(p,\"decl-attribute-equals\")&&(d||c==\"?\"))return{text:o+o,selection:[1,1]}}}),this.add(\"string_dquotes\",\"deletion\",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&(s=='\"'||s==\"'\")){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==s)return i.end.column++,i}}),this.add(\"autoclosing\",\"insertion\",function(e,t,n,r,i){if(i==\">\"){var o=n.getSelectionRange().start,a=new s(r,o.row,o.column),f=a.getCurrentToken()||a.stepBackward();if(!f||!(u(f,\"tag-name\")||u(f,\"tag-whitespace\")||u(f,\"attribute-name\")||u(f,\"attribute-equals\")||u(f,\"attribute-value\")))return;if(u(f,\"reference.attribute-value\"))return;if(u(f,\"attribute-value\")){var l=f.value.charAt(0);if(l=='\"'||l==\"'\"){var c=f.value.charAt(f.value.length-1),h=a.getCurrentTokenColumn()+f.value.length;if(h>o.column||h==o.column&&l!=c)return}}while(!u(f,\"tag-name\")){f=a.stepBackward();if(f.value==\"<\"){f=a.stepForward();break}}var p=a.getCurrentTokenRow(),d=a.getCurrentTokenColumn();if(u(a.stepBackward(),\"end-tag-open\"))return;var v=f.value;p==o.row&&(v=v.substring(0,o.column-d));if(this.voidElements.hasOwnProperty(v.toLowerCase()))return;return{text:\"></\"+v+\">\",selection:[1,1]}}}),this.add(\"autoindent\",\"insertion\",function(e,t,n,r,i){if(i==\"\\n\"){var o=n.getCursorPosition(),u=r.getLine(o.row),a=new s(r,o.row,o.column),f=a.getCurrentToken();if(f&&f.type.indexOf(\"tag-close\")!==-1){if(f.value==\"/>\")return;while(f&&f.type.indexOf(\"tag-name\")===-1)f=a.stepBackward();if(!f)return;var l=f.value,c=a.getCurrentTokenRow();f=a.stepBackward();if(!f||f.type.indexOf(\"end-tag\")!==-1)return;if(this.voidElements&&!this.voidElements[l]){var h=r.getTokenAt(o.row,o.column+1),u=r.getLine(c),p=this.$getIndent(u),d=p+r.getTabString();return h&&h.value===\"</\"?{text:\"\\n\"+d+\"\\n\"+p,selection:[1,d.length,1,d.length]}:{text:\"\\n\"+d}}}}})};r.inherits(a,i),t.XmlBehaviour=a}),define(\"ace/mode/folding/xml\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/lang\",\"ace/range\",\"ace/mode/folding/fold_mode\",\"ace/token_iterator\"],function(e,t,n){\"use strict\";function l(e,t){return e.type.lastIndexOf(t+\".xml\")>-1}var r=e(\"../../lib/oop\"),i=e(\"../../lib/lang\"),s=e(\"../../range\").Range,o=e(\"./fold_mode\").FoldMode,u=e(\"../../token_iterator\").TokenIterator,a=t.FoldMode=function(e,t){o.call(this),this.voidElements=e||{},this.optionalEndTags=r.mixin({},this.voidElements),t&&r.mixin(this.optionalEndTags,t)};r.inherits(a,o);var f=function(){this.tagName=\"\",this.closing=!1,this.selfClosing=!1,this.start={row:0,column:0},this.end={row:0,column:0}};(function(){this.getFoldWidget=function(e,t,n){var r=this._getFirstTagInLine(e,n);return r?r.closing||!r.tagName&&r.selfClosing?t==\"markbeginend\"?\"end\":\"\":!r.tagName||r.selfClosing||this.voidElements.hasOwnProperty(r.tagName.toLowerCase())?\"\":this._findEndTagInLine(e,n,r.tagName,r.end.column)?\"\":\"start\":this.getCommentFoldWidget(e,n)},this.getCommentFoldWidget=function(e,t){return/comment/.test(e.getState(t))&&/<!-/.test(e.getLine(t))?\"start\":\"\"},this._getFirstTagInLine=function(e,t){var n=e.getTokens(t),r=new f;for(var i=0;i<n.length;i++){var s=n[i];if(l(s,\"tag-open\")){r.end.column=r.start.column+s.value.length,r.closing=l(s,\"end-tag-open\"),s=n[++i];if(!s)return null;r.tagName=s.value,r.end.column+=s.value.length;for(i++;i<n.length;i++){s=n[i],r.end.column+=s.value.length;if(l(s,\"tag-close\")){r.selfClosing=s.value==\"/>\";break}}return r}if(l(s,\"tag-close\"))return r.selfClosing=s.value==\"/>\",r;r.start.column+=s.value.length}return null},this._findEndTagInLine=function(e,t,n,r){var i=e.getTokens(t),s=0;for(var o=0;o<i.length;o++){var u=i[o];s+=u.value.length;if(s<r)continue;if(l(u,\"end-tag-open\")){u=i[o+1];if(u&&u.value==n)return!0}}return!1},this._readTagForward=function(e){var t=e.getCurrentToken();if(!t)return null;var n=new f;do if(l(t,\"tag-open\"))n.closing=l(t,\"end-tag-open\"),n.start.row=e.getCurrentTokenRow(),n.start.column=e.getCurrentTokenColumn();else if(l(t,\"tag-name\"))n.tagName=t.value;else if(l(t,\"tag-close\"))return n.selfClosing=t.value==\"/>\",n.end.row=e.getCurrentTokenRow(),n.end.column=e.getCurrentTokenColumn()+t.value.length,e.stepForward(),n;while(t=e.stepForward());return null},this._readTagBackward=function(e){var t=e.getCurrentToken();if(!t)return null;var n=new f;do{if(l(t,\"tag-open\"))return n.closing=l(t,\"end-tag-open\"),n.start.row=e.getCurrentTokenRow(),n.start.column=e.getCurrentTokenColumn(),e.stepBackward(),n;l(t,\"tag-name\")?n.tagName=t.value:l(t,\"tag-close\")&&(n.selfClosing=t.value==\"/>\",n.end.row=e.getCurrentTokenRow(),n.end.column=e.getCurrentTokenColumn()+t.value.length)}while(t=e.stepBackward());return null},this._pop=function(e,t){while(e.length){var n=e[e.length-1];if(!t||n.tagName==t.tagName)return e.pop();if(this.optionalEndTags.hasOwnProperty(n.tagName)){e.pop();continue}return null}},this.getFoldWidgetRange=function(e,t,n){var r=this._getFirstTagInLine(e,n);if(!r)return this.getCommentFoldWidget(e,n)&&e.getCommentFoldRange(n,e.getLine(n).length);var i=r.closing||r.selfClosing,o=[],a;if(!i){var f=new u(e,n,r.start.column),l={row:n,column:r.start.column+r.tagName.length+2};r.start.row==r.end.row&&(l.column=r.end.column);while(a=this._readTagForward(f)){if(a.selfClosing){if(!o.length)return a.start.column+=a.tagName.length+2,a.end.column-=2,s.fromPoints(a.start,a.end);continue}if(a.closing){this._pop(o,a);if(o.length==0)return s.fromPoints(l,a.start)}else o.push(a)}}else{var f=new u(e,n,r.end.column),c={row:n,column:r.start.column};while(a=this._readTagBackward(f)){if(a.selfClosing){if(!o.length)return a.start.column+=a.tagName.length+2,a.end.column-=2,s.fromPoints(a.start,a.end);continue}if(!a.closing){this._pop(o,a);if(o.length==0)return a.start.column+=a.tagName.length+2,a.start.row==a.end.row&&a.start.column<a.end.column&&(a.start.column=a.end.column),s.fromPoints(a.start,c)}else o.push(a)}}}}).call(a.prototype)}),define(\"ace/mode/xml\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/lang\",\"ace/mode/text\",\"ace/mode/xml_highlight_rules\",\"ace/mode/behaviour/xml\",\"ace/mode/folding/xml\",\"ace/worker/worker_client\"],function(e,t,n){\"use strict\";var r=e(\"../lib/oop\"),i=e(\"../lib/lang\"),s=e(\"./text\").Mode,o=e(\"./xml_highlight_rules\").XmlHighlightRules,u=e(\"./behaviour/xml\").XmlBehaviour,a=e(\"./folding/xml\").FoldMode,f=e(\"../worker/worker_client\").WorkerClient,l=function(){this.HighlightRules=o,this.$behaviour=new u,this.foldingRules=new a};r.inherits(l,s),function(){this.voidElements=i.arrayToMap([]),this.blockComment={start:\"<!--\",end:\"-->\"},this.createWorker=function(e){var t=new f([\"ace\"],\"ace/mode/xml_worker\",\"Worker\");return t.attachToDocument(e.getDocument()),t.on(\"error\",function(t){e.setAnnotations(t.data)}),t.on(\"terminate\",function(){e.clearAnnotations()}),t},this.$id=\"ace/mode/xml\"}.call(l.prototype),t.Mode=l})\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/vendor/ui-ace/mode-yaml.js",
    "content": "define(\"ace/mode/yaml_highlight_rules\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/mode/text_highlight_rules\"],function(e,t,n){\"use strict\";var r=e(\"../lib/oop\"),i=e(\"./text_highlight_rules\").TextHighlightRules,s=function(){this.$rules={start:[{token:\"comment\",regex:\"#.*$\"},{token:\"list.markup\",regex:/^(?:-{3}|\\.{3})\\s*(?=#|$)/},{token:\"list.markup\",regex:/^\\s*[\\-?](?:$|\\s)/},{token:\"constant\",regex:\"!![\\\\w//]+\"},{token:\"constant.language\",regex:\"[&\\\\*][a-zA-Z0-9-_]+\"},{token:[\"meta.tag\",\"keyword\"],regex:/^(\\s*\\w.*?)(:(?=\\s|$))/},{token:[\"meta.tag\",\"keyword\"],regex:/(\\w+?)(\\s*:(?=\\s|$))/},{token:\"keyword.operator\",regex:\"<<\\\\w*:\\\\w*\"},{token:\"keyword.operator\",regex:\"-\\\\s*(?=[{])\"},{token:\"string\",regex:'[\"](?:(?:\\\\\\\\.)|(?:[^\"\\\\\\\\]))*?[\"]'},{token:\"string\",regex:/[|>][-+\\d\\s]*$/,onMatch:function(e,t,n,r){var i=/^\\s*/.exec(r)[0];return n.length<1?n.push(this.next):n[0]=\"mlString\",n.length<2?n.push(i.length):n[1]=i.length,this.token},next:\"mlString\"},{token:\"string\",regex:\"['](?:(?:\\\\\\\\.)|(?:[^'\\\\\\\\]))*?[']\"},{token:\"constant.numeric\",regex:/(\\b|[+\\-\\.])[\\d_]+(?:(?:\\.[\\d_]*)?(?:[eE][+\\-]?[\\d_]+)?)(?=[^\\d-\\w]|$)/},{token:\"constant.numeric\",regex:/[+\\-]?\\.inf\\b|NaN\\b|0x[\\dA-Fa-f_]+|0b[10_]+/},{token:\"constant.language.boolean\",regex:\"\\\\b(?:true|false|TRUE|FALSE|True|False|yes|no)\\\\b\"},{token:\"paren.lparen\",regex:\"[[({]\"},{token:\"paren.rparen\",regex:\"[\\\\])}]\"},{token:\"text\",regex:/[^\\s,:\\[\\]\\{\\}]+/}],mlString:[{token:\"indent\",regex:/^\\s*$/},{token:\"indent\",regex:/^\\s*/,onMatch:function(e,t,n){var r=n[1];return r>=e.length?(this.next=\"start\",n.splice(0)):this.next=\"mlString\",this.token},next:\"mlString\"},{token:\"string\",regex:\".+\"}]},this.normalizeRules()};r.inherits(s,i),t.YamlHighlightRules=s}),define(\"ace/mode/matching_brace_outdent\",[\"require\",\"exports\",\"module\",\"ace/range\"],function(e,t,n){\"use strict\";var r=e(\"../range\").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\\s+$/.test(e)?/^\\s*\\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\\s*\\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){return e.match(/^\\s*/)[0]}}).call(i.prototype),t.MatchingBraceOutdent=i}),define(\"ace/mode/folding/coffee\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/mode/folding/fold_mode\",\"ace/range\"],function(e,t,n){\"use strict\";var r=e(\"../../lib/oop\"),i=e(\"./fold_mode\").FoldMode,s=e(\"../../range\").Range,o=t.FoldMode=function(){};r.inherits(o,i),function(){this.getFoldWidgetRange=function(e,t,n){var r=this.indentationBlock(e,n);if(r)return r;var i=/\\S/,o=e.getLine(n),u=o.search(i);if(u==-1||o[u]!=\"#\")return;var a=o.length,f=e.getLength(),l=n,c=n;while(++n<f){o=e.getLine(n);var h=o.search(i);if(h==-1)continue;if(o[h]!=\"#\")break;c=n}if(c>l){var p=e.getLine(c).length;return new s(l,a,c,p)}},this.getFoldWidget=function(e,t,n){var r=e.getLine(n),i=r.search(/\\S/),s=e.getLine(n+1),o=e.getLine(n-1),u=o.search(/\\S/),a=s.search(/\\S/);if(i==-1)return e.foldWidgets[n-1]=u!=-1&&u<a?\"start\":\"\",\"\";if(u==-1){if(i==a&&r[i]==\"#\"&&s[i]==\"#\")return e.foldWidgets[n-1]=\"\",e.foldWidgets[n+1]=\"\",\"start\"}else if(u==i&&r[i]==\"#\"&&o[i]==\"#\"&&e.getLine(n-2).search(/\\S/)==-1)return e.foldWidgets[n-1]=\"start\",e.foldWidgets[n+1]=\"\",\"\";return u!=-1&&u<i?e.foldWidgets[n-1]=\"start\":e.foldWidgets[n-1]=\"\",i<a?\"start\":\"\"}}.call(o.prototype)}),define(\"ace/mode/yaml\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/mode/text\",\"ace/mode/yaml_highlight_rules\",\"ace/mode/matching_brace_outdent\",\"ace/mode/folding/coffee\"],function(e,t,n){\"use strict\";var r=e(\"../lib/oop\"),i=e(\"./text\").Mode,s=e(\"./yaml_highlight_rules\").YamlHighlightRules,o=e(\"./matching_brace_outdent\").MatchingBraceOutdent,u=e(\"./folding/coffee\").FoldMode,a=function(){this.HighlightRules=s,this.$outdent=new o,this.foldingRules=new u,this.$behaviour=this.$defaultBehaviour};r.inherits(a,i),function(){this.lineCommentStart=[\"#\",\"//\"],this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t);if(e==\"start\"){var i=t.match(/^.*[\\{\\(\\[]\\s*$/);i&&(r+=n)}return r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.$id=\"ace/mode/yaml\"}.call(a.prototype),t.Mode=a})\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/vendor/ui-ace/theme-eclipse.js",
    "content": "define(\"ace/theme/eclipse\",[\"require\",\"exports\",\"module\",\"ace/lib/dom\"],function(e,t,n){\"use strict\";t.isDark=!1,t.cssText='.ace-eclipse .ace_gutter {background: #ebebeb;border-right: 1px solid rgb(159, 159, 159);color: rgb(136, 136, 136);}.ace-eclipse .ace_print-margin {width: 1px;background: #ebebeb;}.ace-eclipse {background-color: #FFFFFF;color: black;}.ace-eclipse .ace_fold {background-color: rgb(60, 76, 114);}.ace-eclipse .ace_cursor {color: black;}.ace-eclipse .ace_storage,.ace-eclipse .ace_keyword,.ace-eclipse .ace_variable {color: rgb(127, 0, 85);}.ace-eclipse .ace_constant.ace_buildin {color: rgb(88, 72, 246);}.ace-eclipse .ace_constant.ace_library {color: rgb(6, 150, 14);}.ace-eclipse .ace_function {color: rgb(60, 76, 114);}.ace-eclipse .ace_string {color: rgb(42, 0, 255);}.ace-eclipse .ace_comment {color: rgb(113, 150, 130);}.ace-eclipse .ace_comment.ace_doc {color: rgb(63, 95, 191);}.ace-eclipse .ace_comment.ace_doc.ace_tag {color: rgb(127, 159, 191);}.ace-eclipse .ace_constant.ace_numeric {color: darkblue;}.ace-eclipse .ace_tag {color: rgb(25, 118, 116);}.ace-eclipse .ace_type {color: rgb(127, 0, 127);}.ace-eclipse .ace_xml-pe {color: rgb(104, 104, 91);}.ace-eclipse .ace_marker-layer .ace_selection {background: rgb(181, 213, 255);}.ace-eclipse .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid rgb(192, 192, 192);}.ace-eclipse .ace_meta.ace_tag {color:rgb(25, 118, 116);}.ace-eclipse .ace_invisible {color: #ddd;}.ace-eclipse .ace_entity.ace_other.ace_attribute-name {color:rgb(127, 0, 127);}.ace-eclipse .ace_marker-layer .ace_step {background: rgb(255, 255, 0);}.ace-eclipse .ace_active-line {background: rgb(232, 242, 254);}.ace-eclipse .ace_gutter-active-line {background-color : #DADADA;}.ace-eclipse .ace_marker-layer .ace_selected-word {border: 1px solid rgb(181, 213, 255);}.ace-eclipse .ace_indent-guide {background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==\") right repeat-y;}',t.cssClass=\"ace-eclipse\";var r=e(\"../lib/dom\");r.importCssString(t.cssText,t.cssClass)})\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/vendor/ui-ace/worker-json.js",
    "content": "\"no use strict\";!function(e){function t(e,t){var n=e,r=\"\";while(n){var i=t[n];if(typeof i==\"string\")return i+r;if(i)return i.location.replace(/\\/*$/,\"/\")+(r||i.main||i.name);if(i===!1)return\"\";var s=n.lastIndexOf(\"/\");if(s===-1)break;r=n.substr(s)+r,n=n.slice(0,s)}return e}if(typeof e.window!=\"undefined\"&&e.document)return;if(e.require&&e.define)return;e.console||(e.console=function(){var e=Array.prototype.slice.call(arguments,0);postMessage({type:\"log\",data:e})},e.console.error=e.console.warn=e.console.log=e.console.trace=e.console),e.window=e,e.ace=e,e.onerror=function(e,t,n,r,i){postMessage({type:\"error\",data:{message:e,data:i.data,file:t,line:n,col:r,stack:i.stack}})},e.normalizeModule=function(t,n){if(n.indexOf(\"!\")!==-1){var r=n.split(\"!\");return e.normalizeModule(t,r[0])+\"!\"+e.normalizeModule(t,r[1])}if(n.charAt(0)==\".\"){var i=t.split(\"/\").slice(0,-1).join(\"/\");n=(i?i+\"/\":\"\")+n;while(n.indexOf(\".\")!==-1&&s!=n){var s=n;n=n.replace(/^\\.\\//,\"\").replace(/\\/\\.\\//,\"/\").replace(/[^\\/]+\\/\\.\\.\\//,\"\")}}return n},e.require=function(r,i){i||(i=r,r=null);if(!i.charAt)throw new Error(\"worker.js require() accepts only (parentId, id) as arguments\");i=e.normalizeModule(r,i);var s=e.require.modules[i];if(s)return s.initialized||(s.initialized=!0,s.exports=s.factory().exports),s.exports;if(!e.require.tlns)return console.log(\"unable to load \"+i);var o=t(i,e.require.tlns);return o.slice(-3)!=\".js\"&&(o+=\".js\"),e.require.id=i,e.require.modules[i]={},importScripts(o),e.require(r,i)},e.require.modules={},e.require.tlns={},e.define=function(t,n,r){arguments.length==2?(r=n,typeof t!=\"string\"&&(n=t,t=e.require.id)):arguments.length==1&&(r=t,n=[],t=e.require.id);if(typeof r!=\"function\"){e.require.modules[t]={exports:r,initialized:!0};return}n.length||(n=[\"require\",\"exports\",\"module\"]);var i=function(n){return e.require(t,n)};e.require.modules[t]={exports:{},factory:function(){var e=this,t=r.apply(this,n.map(function(t){switch(t){case\"require\":return i;case\"exports\":return e.exports;case\"module\":return e;default:return i(t)}}));return t&&(e.exports=t),e}}},e.define.amd={},require.tlns={},e.initBaseUrls=function(t){for(var n in t)require.tlns[n]=t[n]},e.initSender=function(){var n=e.require(\"ace/lib/event_emitter\").EventEmitter,r=e.require(\"ace/lib/oop\"),i=function(){};return function(){r.implement(this,n),this.callback=function(e,t){postMessage({type:\"call\",id:t,data:e})},this.emit=function(e,t){postMessage({type:\"event\",name:e,data:t})}}.call(i.prototype),new i};var n=e.main=null,r=e.sender=null;e.onmessage=function(t){var i=t.data;if(i.event&&r)r._signal(i.event,i.data);else if(i.command)if(n[i.command])n[i.command].apply(n,i.args);else{if(!e[i.command])throw new Error(\"Unknown command:\"+i.command);e[i.command].apply(e,i.args)}else if(i.init){e.initBaseUrls(i.tlns),require(\"ace/lib/es5-shim\"),r=e.sender=e.initSender();var s=require(i.module)[i.classname];n=e.main=new s(r)}}}(this),define(\"ace/lib/oop\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";t.inherits=function(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})},t.mixin=function(e,t){for(var n in t)e[n]=t[n];return e},t.implement=function(e,n){t.mixin(e,n)}}),define(\"ace/range\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";var r=function(e,t){return e.row-t.row||e.column-t.column},i=function(e,t,n,r){this.start={row:e,column:t},this.end={row:n,column:r}};(function(){this.isEqual=function(e){return this.start.row===e.start.row&&this.end.row===e.end.row&&this.start.column===e.start.column&&this.end.column===e.end.column},this.toString=function(){return\"Range: [\"+this.start.row+\"/\"+this.start.column+\"] -> [\"+this.end.row+\"/\"+this.end.column+\"]\"},this.contains=function(e,t){return this.compare(e,t)==0},this.compareRange=function(e){var t,n=e.end,r=e.start;return t=this.compare(n.row,n.column),t==1?(t=this.compare(r.row,r.column),t==1?2:t==0?1:0):t==-1?-2:(t=this.compare(r.row,r.column),t==-1?-1:t==1?42:0)},this.comparePoint=function(e){return this.compare(e.row,e.column)},this.containsRange=function(e){return this.comparePoint(e.start)==0&&this.comparePoint(e.end)==0},this.intersects=function(e){var t=this.compareRange(e);return t==-1||t==0||t==1},this.isEnd=function(e,t){return this.end.row==e&&this.end.column==t},this.isStart=function(e,t){return this.start.row==e&&this.start.column==t},this.setStart=function(e,t){typeof e==\"object\"?(this.start.column=e.column,this.start.row=e.row):(this.start.row=e,this.start.column=t)},this.setEnd=function(e,t){typeof e==\"object\"?(this.end.column=e.column,this.end.row=e.row):(this.end.row=e,this.end.column=t)},this.inside=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)||this.isStart(e,t)?!1:!0:!1},this.insideStart=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)?!1:!0:!1},this.insideEnd=function(e,t){return this.compare(e,t)==0?this.isStart(e,t)?!1:!0:!1},this.compare=function(e,t){return!this.isMultiLine()&&e===this.start.row?t<this.start.column?-1:t>this.end.column?1:0:e<this.start.row?-1:e>this.end.row?1:this.start.row===e?t>=this.start.column?0:-1:this.end.row===e?t<=this.end.column?0:1:0},this.compareStart=function(e,t){return this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.compareEnd=function(e,t){return this.end.row==e&&this.end.column==t?1:this.compare(e,t)},this.compareInside=function(e,t){return this.end.row==e&&this.end.column==t?1:this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.clipRows=function(e,t){if(this.end.row>t)var n={row:t+1,column:0};else if(this.end.row<e)var n={row:e,column:0};if(this.start.row>t)var r={row:t+1,column:0};else if(this.start.row<e)var r={row:e,column:0};return i.fromPoints(r||this.start,n||this.end)},this.extend=function(e,t){var n=this.compare(e,t);if(n==0)return this;if(n==-1)var r={row:e,column:t};else var s={row:e,column:t};return i.fromPoints(r||this.start,s||this.end)},this.isEmpty=function(){return this.start.row===this.end.row&&this.start.column===this.end.column},this.isMultiLine=function(){return this.start.row!==this.end.row},this.clone=function(){return i.fromPoints(this.start,this.end)},this.collapseRows=function(){return this.end.column==0?new i(this.start.row,0,Math.max(this.start.row,this.end.row-1),0):new i(this.start.row,0,this.end.row,0)},this.toScreenRange=function(e){var t=e.documentToScreenPosition(this.start),n=e.documentToScreenPosition(this.end);return new i(t.row,t.column,n.row,n.column)},this.moveBy=function(e,t){this.start.row+=e,this.start.column+=t,this.end.row+=e,this.end.column+=t}}).call(i.prototype),i.fromPoints=function(e,t){return new i(e.row,e.column,t.row,t.column)},i.comparePoints=r,i.comparePoints=function(e,t){return e.row-t.row||e.column-t.column},t.Range=i}),define(\"ace/apply_delta\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";function r(e,t){throw console.log(\"Invalid Delta:\",e),\"Invalid Delta: \"+t}function i(e,t){return t.row>=0&&t.row<e.length&&t.column>=0&&t.column<=e[t.row].length}function s(e,t){t.action!=\"insert\"&&t.action!=\"remove\"&&r(t,\"delta.action must be 'insert' or 'remove'\"),t.lines instanceof Array||r(t,\"delta.lines must be an Array\"),(!t.start||!t.end)&&r(t,\"delta.start/end must be an present\");var n=t.start;i(e,t.start)||r(t,\"delta.start must be contained in document\");var s=t.end;t.action==\"remove\"&&!i(e,s)&&r(t,\"delta.end must contained in document for 'remove' actions\");var o=s.row-n.row,u=s.column-(o==0?n.column:0);(o!=t.lines.length-1||t.lines[o].length!=u)&&r(t,\"delta.range must match delta lines\")}t.applyDelta=function(e,t,n){var r=t.start.row,i=t.start.column,s=e[r]||\"\";switch(t.action){case\"insert\":var o=t.lines;if(o.length===1)e[r]=s.substring(0,i)+t.lines[0]+s.substring(i);else{var u=[r,1].concat(t.lines);e.splice.apply(e,u),e[r]=s.substring(0,i)+e[r],e[r+t.lines.length-1]+=s.substring(i)}break;case\"remove\":var a=t.end.column,f=t.end.row;r===f?e[r]=s.substring(0,i)+s.substring(a):e.splice(r,f-r+1,s.substring(0,i)+e[f].substring(a))}}}),define(\"ace/lib/event_emitter\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";var r={},i=function(){this.propagationStopped=!0},s=function(){this.defaultPrevented=!0};r._emit=r._dispatchEvent=function(e,t){this._eventRegistry||(this._eventRegistry={}),this._defaultHandlers||(this._defaultHandlers={});var n=this._eventRegistry[e]||[],r=this._defaultHandlers[e];if(!n.length&&!r)return;if(typeof t!=\"object\"||!t)t={};t.type||(t.type=e),t.stopPropagation||(t.stopPropagation=i),t.preventDefault||(t.preventDefault=s),n=n.slice();for(var o=0;o<n.length;o++){n[o](t,this);if(t.propagationStopped)break}if(r&&!t.defaultPrevented)return r(t,this)},r._signal=function(e,t){var n=(this._eventRegistry||{})[e];if(!n)return;n=n.slice();for(var r=0;r<n.length;r++)n[r](t,this)},r.once=function(e,t){var n=this;t&&this.addEventListener(e,function r(){n.removeEventListener(e,r),t.apply(null,arguments)})},r.setDefaultHandler=function(e,t){var n=this._defaultHandlers;n||(n=this._defaultHandlers={_disabled_:{}});if(n[e]){var r=n[e],i=n._disabled_[e];i||(n._disabled_[e]=i=[]),i.push(r);var s=i.indexOf(t);s!=-1&&i.splice(s,1)}n[e]=t},r.removeDefaultHandler=function(e,t){var n=this._defaultHandlers;if(!n)return;var r=n._disabled_[e];if(n[e]==t){var i=n[e];r&&this.setDefaultHandler(e,r.pop())}else if(r){var s=r.indexOf(t);s!=-1&&r.splice(s,1)}},r.on=r.addEventListener=function(e,t,n){this._eventRegistry=this._eventRegistry||{};var r=this._eventRegistry[e];return r||(r=this._eventRegistry[e]=[]),r.indexOf(t)==-1&&r[n?\"unshift\":\"push\"](t),t},r.off=r.removeListener=r.removeEventListener=function(e,t){this._eventRegistry=this._eventRegistry||{};var n=this._eventRegistry[e];if(!n)return;var r=n.indexOf(t);r!==-1&&n.splice(r,1)},r.removeAllListeners=function(e){this._eventRegistry&&(this._eventRegistry[e]=[])},t.EventEmitter=r}),define(\"ace/anchor\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/event_emitter\"],function(e,t,n){\"use strict\";var r=e(\"./lib/oop\"),i=e(\"./lib/event_emitter\").EventEmitter,s=t.Anchor=function(e,t,n){this.$onChange=this.onChange.bind(this),this.attach(e),typeof n==\"undefined\"?this.setPosition(t.row,t.column):this.setPosition(t,n)};(function(){function e(e,t,n){var r=n?e.column<=t.column:e.column<t.column;return e.row<t.row||e.row==t.row&&r}function t(t,n,r){var i=t.action==\"insert\",s=(i?1:-1)*(t.end.row-t.start.row),o=(i?1:-1)*(t.end.column-t.start.column),u=t.start,a=i?u:t.end;return e(n,u,r)?{row:n.row,column:n.column}:e(a,n,!r)?{row:n.row+s,column:n.column+(n.row==a.row?o:0)}:{row:u.row,column:u.column}}r.implement(this,i),this.getPosition=function(){return this.$clipPositionToDocument(this.row,this.column)},this.getDocument=function(){return this.document},this.$insertRight=!1,this.onChange=function(e){if(e.start.row==e.end.row&&e.start.row!=this.row)return;if(e.start.row>this.row)return;var n=t(e,{row:this.row,column:this.column},this.$insertRight);this.setPosition(n.row,n.column,!0)},this.setPosition=function(e,t,n){var r;n?r={row:e,column:t}:r=this.$clipPositionToDocument(e,t);if(this.row==r.row&&this.column==r.column)return;var i={row:this.row,column:this.column};this.row=r.row,this.column=r.column,this._signal(\"change\",{old:i,value:r})},this.detach=function(){this.document.removeEventListener(\"change\",this.$onChange)},this.attach=function(e){this.document=e||this.document,this.document.on(\"change\",this.$onChange)},this.$clipPositionToDocument=function(e,t){var n={};return e>=this.document.getLength()?(n.row=Math.max(0,this.document.getLength()-1),n.column=this.document.getLine(n.row).length):e<0?(n.row=0,n.column=0):(n.row=e,n.column=Math.min(this.document.getLine(n.row).length,Math.max(0,t))),t<0&&(n.column=0),n}}).call(s.prototype)}),define(\"ace/document\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/apply_delta\",\"ace/lib/event_emitter\",\"ace/range\",\"ace/anchor\"],function(e,t,n){\"use strict\";var r=e(\"./lib/oop\"),i=e(\"./apply_delta\").applyDelta,s=e(\"./lib/event_emitter\").EventEmitter,o=e(\"./range\").Range,u=e(\"./anchor\").Anchor,a=function(e){this.$lines=[\"\"],e.length===0?this.$lines=[\"\"]:Array.isArray(e)?this.insertMergedLines({row:0,column:0},e):this.insert({row:0,column:0},e)};(function(){r.implement(this,s),this.setValue=function(e){var t=this.getLength()-1;this.remove(new o(0,0,t,this.getLine(t).length)),this.insert({row:0,column:0},e)},this.getValue=function(){return this.getAllLines().join(this.getNewLineCharacter())},this.createAnchor=function(e,t){return new u(this,e,t)},\"aaa\".split(/a/).length===0?this.$split=function(e){return e.replace(/\\r\\n|\\r/g,\"\\n\").split(\"\\n\")}:this.$split=function(e){return e.split(/\\r\\n|\\r|\\n/)},this.$detectNewLine=function(e){var t=e.match(/^.*?(\\r\\n|\\r|\\n)/m);this.$autoNewLine=t?t[1]:\"\\n\",this._signal(\"changeNewLineMode\")},this.getNewLineCharacter=function(){switch(this.$newLineMode){case\"windows\":return\"\\r\\n\";case\"unix\":return\"\\n\";default:return this.$autoNewLine||\"\\n\"}},this.$autoNewLine=\"\",this.$newLineMode=\"auto\",this.setNewLineMode=function(e){if(this.$newLineMode===e)return;this.$newLineMode=e,this._signal(\"changeNewLineMode\")},this.getNewLineMode=function(){return this.$newLineMode},this.isNewLine=function(e){return e==\"\\r\\n\"||e==\"\\r\"||e==\"\\n\"},this.getLine=function(e){return this.$lines[e]||\"\"},this.getLines=function(e,t){return this.$lines.slice(e,t+1)},this.getAllLines=function(){return this.getLines(0,this.getLength())},this.getLength=function(){return this.$lines.length},this.getTextRange=function(e){return this.getLinesForRange(e).join(this.getNewLineCharacter())},this.getLinesForRange=function(e){var t;if(e.start.row===e.end.row)t=[this.getLine(e.start.row).substring(e.start.column,e.end.column)];else{t=this.getLines(e.start.row,e.end.row),t[0]=(t[0]||\"\").substring(e.start.column);var n=t.length-1;e.end.row-e.start.row==n&&(t[n]=t[n].substring(0,e.end.column))}return t},this.insertLines=function(e,t){return console.warn(\"Use of document.insertLines is deprecated. Use the insertFullLines method instead.\"),this.insertFullLines(e,t)},this.removeLines=function(e,t){return console.warn(\"Use of document.removeLines is deprecated. Use the removeFullLines method instead.\"),this.removeFullLines(e,t)},this.insertNewLine=function(e){return console.warn(\"Use of document.insertNewLine is deprecated. Use insertMergedLines(position, ['', '']) instead.\"),this.insertMergedLines(e,[\"\",\"\"])},this.insert=function(e,t){return this.getLength()<=1&&this.$detectNewLine(t),this.insertMergedLines(e,this.$split(t))},this.insertInLine=function(e,t){var n=this.clippedPos(e.row,e.column),r=this.pos(e.row,e.column+t.length);return this.applyDelta({start:n,end:r,action:\"insert\",lines:[t]},!0),this.clonePos(r)},this.clippedPos=function(e,t){var n=this.getLength();e===undefined?e=n:e<0?e=0:e>=n&&(e=n-1,t=undefined);var r=this.getLine(e);return t==undefined&&(t=r.length),t=Math.min(Math.max(t,0),r.length),{row:e,column:t}},this.clonePos=function(e){return{row:e.row,column:e.column}},this.pos=function(e,t){return{row:e,column:t}},this.$clipPosition=function(e){var t=this.getLength();return e.row>=t?(e.row=Math.max(0,t-1),e.column=this.getLine(t-1).length):(e.row=Math.max(0,e.row),e.column=Math.min(Math.max(e.column,0),this.getLine(e.row).length)),e},this.insertFullLines=function(e,t){e=Math.min(Math.max(e,0),this.getLength());var n=0;e<this.getLength()?(t=t.concat([\"\"]),n=0):(t=[\"\"].concat(t),e--,n=this.$lines[e].length),this.insertMergedLines({row:e,column:n},t)},this.insertMergedLines=function(e,t){var n=this.clippedPos(e.row,e.column),r={row:n.row+t.length-1,column:(t.length==1?n.column:0)+t[t.length-1].length};return this.applyDelta({start:n,end:r,action:\"insert\",lines:t}),this.clonePos(r)},this.remove=function(e){var t=this.clippedPos(e.start.row,e.start.column),n=this.clippedPos(e.end.row,e.end.column);return this.applyDelta({start:t,end:n,action:\"remove\",lines:this.getLinesForRange({start:t,end:n})}),this.clonePos(t)},this.removeInLine=function(e,t,n){var r=this.clippedPos(e,t),i=this.clippedPos(e,n);return this.applyDelta({start:r,end:i,action:\"remove\",lines:this.getLinesForRange({start:r,end:i})},!0),this.clonePos(r)},this.removeFullLines=function(e,t){e=Math.min(Math.max(0,e),this.getLength()-1),t=Math.min(Math.max(0,t),this.getLength()-1);var n=t==this.getLength()-1&&e>0,r=t<this.getLength()-1,i=n?e-1:e,s=n?this.getLine(i).length:0,u=r?t+1:t,a=r?0:this.getLine(u).length,f=new o(i,s,u,a),l=this.$lines.slice(e,t+1);return this.applyDelta({start:f.start,end:f.end,action:\"remove\",lines:this.getLinesForRange(f)}),l},this.removeNewLine=function(e){e<this.getLength()-1&&e>=0&&this.applyDelta({start:this.pos(e,this.getLine(e).length),end:this.pos(e+1,0),action:\"remove\",lines:[\"\",\"\"]})},this.replace=function(e,t){e instanceof o||(e=o.fromPoints(e.start,e.end));if(t.length===0&&e.isEmpty())return e.start;if(t==this.getTextRange(e))return e.end;this.remove(e);var n;return t?n=this.insert(e.start,t):n=e.start,n},this.applyDeltas=function(e){for(var t=0;t<e.length;t++)this.applyDelta(e[t])},this.revertDeltas=function(e){for(var t=e.length-1;t>=0;t--)this.revertDelta(e[t])},this.applyDelta=function(e,t){var n=e.action==\"insert\";if(n?e.lines.length<=1&&!e.lines[0]:!o.comparePoints(e.start,e.end))return;n&&e.lines.length>2e4&&this.$splitAndapplyLargeDelta(e,2e4),i(this.$lines,e,t),this._signal(\"change\",e)},this.$splitAndapplyLargeDelta=function(e,t){var n=e.lines,r=n.length,i=e.start.row,s=e.start.column,o=0,u=0;do{o=u,u+=t-1;var a=n.slice(o,u);if(u>r){e.lines=a,e.start.row=i+o,e.start.column=s;break}a.push(\"\"),this.applyDelta({start:this.pos(i+o,s),end:this.pos(i+u,s=0),action:e.action,lines:a},!0)}while(!0)},this.revertDelta=function(e){this.applyDelta({start:this.clonePos(e.start),end:this.clonePos(e.end),action:e.action==\"insert\"?\"remove\":\"insert\",lines:e.lines.slice()})},this.indexToPosition=function(e,t){var n=this.$lines||this.getAllLines(),r=this.getNewLineCharacter().length;for(var i=t||0,s=n.length;i<s;i++){e-=n[i].length+r;if(e<0)return{row:i,column:e+n[i].length+r}}return{row:s-1,column:n[s-1].length}},this.positionToIndex=function(e,t){var n=this.$lines||this.getAllLines(),r=this.getNewLineCharacter().length,i=0,s=Math.min(e.row,n.length);for(var o=t||0;o<s;++o)i+=n[o].length+r;return i+e.column}}).call(a.prototype),t.Document=a}),define(\"ace/lib/lang\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";t.last=function(e){return e[e.length-1]},t.stringReverse=function(e){return e.split(\"\").reverse().join(\"\")},t.stringRepeat=function(e,t){var n=\"\";while(t>0){t&1&&(n+=e);if(t>>=1)e+=e}return n};var r=/^\\s\\s*/,i=/\\s\\s*$/;t.stringTrimLeft=function(e){return e.replace(r,\"\")},t.stringTrimRight=function(e){return e.replace(i,\"\")},t.copyObject=function(e){var t={};for(var n in e)t[n]=e[n];return t},t.copyArray=function(e){var t=[];for(var n=0,r=e.length;n<r;n++)e[n]&&typeof e[n]==\"object\"?t[n]=this.copyObject(e[n]):t[n]=e[n];return t},t.deepCopy=function s(e){if(typeof e!=\"object\"||!e)return e;var t;if(Array.isArray(e)){t=[];for(var n=0;n<e.length;n++)t[n]=s(e[n]);return t}if(Object.prototype.toString.call(e)!==\"[object Object]\")return e;t={};for(var n in e)t[n]=s(e[n]);return t},t.arrayToMap=function(e){var t={};for(var n=0;n<e.length;n++)t[e[n]]=1;return t},t.createMap=function(e){var t=Object.create(null);for(var n in e)t[n]=e[n];return t},t.arrayRemove=function(e,t){for(var n=0;n<=e.length;n++)t===e[n]&&e.splice(n,1)},t.escapeRegExp=function(e){return e.replace(/([.*+?^${}()|[\\]\\/\\\\])/g,\"\\\\$1\")},t.escapeHTML=function(e){return e.replace(/&/g,\"&#38;\").replace(/\"/g,\"&#34;\").replace(/'/g,\"&#39;\").replace(/</g,\"&#60;\")},t.getMatchOffsets=function(e,t){var n=[];return e.replace(t,function(e){n.push({offset:arguments[arguments.length-2],length:e.length})}),n},t.deferredCall=function(e){var t=null,n=function(){t=null,e()},r=function(e){return r.cancel(),t=setTimeout(n,e||0),r};return r.schedule=r,r.call=function(){return this.cancel(),e(),r},r.cancel=function(){return clearTimeout(t),t=null,r},r.isPending=function(){return t},r},t.delayedCall=function(e,t){var n=null,r=function(){n=null,e()},i=function(e){n==null&&(n=setTimeout(r,e||t))};return i.delay=function(e){n&&clearTimeout(n),n=setTimeout(r,e||t)},i.schedule=i,i.call=function(){this.cancel(),e()},i.cancel=function(){n&&clearTimeout(n),n=null},i.isPending=function(){return n},i}}),define(\"ace/worker/mirror\",[\"require\",\"exports\",\"module\",\"ace/range\",\"ace/document\",\"ace/lib/lang\"],function(e,t,n){\"use strict\";var r=e(\"../range\").Range,i=e(\"../document\").Document,s=e(\"../lib/lang\"),o=t.Mirror=function(e){this.sender=e;var t=this.doc=new i(\"\"),n=this.deferredUpdate=s.delayedCall(this.onUpdate.bind(this)),r=this;e.on(\"change\",function(e){var i=e.data;if(i[0].start)t.applyDeltas(i);else for(var s=0;s<i.length;s+=2){if(Array.isArray(i[s+1]))var o={action:\"insert\",start:i[s],lines:i[s+1]};else var o={action:\"remove\",start:i[s],end:i[s+1]};t.applyDelta(o,!0)}if(r.$timeout)return n.schedule(r.$timeout);r.onUpdate()})};(function(){this.$timeout=500,this.setTimeout=function(e){this.$timeout=e},this.setValue=function(e){this.doc.setValue(e),this.deferredUpdate.schedule(this.$timeout)},this.getValue=function(e){this.sender.callback(this.doc.getValue(),e)},this.onUpdate=function(){},this.isPending=function(){return this.deferredUpdate.isPending()}}).call(o.prototype)}),define(\"ace/mode/json/json_parse\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";var r,i,s={'\"':'\"',\"\\\\\":\"\\\\\",\"/\":\"/\",b:\"\\b\",f:\"\\f\",n:\"\\n\",r:\"\\r\",t:\"\t\"},o,u=function(e){throw{name:\"SyntaxError\",message:e,at:r,text:o}},a=function(e){return e&&e!==i&&u(\"Expected '\"+e+\"' instead of '\"+i+\"'\"),i=o.charAt(r),r+=1,i},f=function(){var e,t=\"\";i===\"-\"&&(t=\"-\",a(\"-\"));while(i>=\"0\"&&i<=\"9\")t+=i,a();if(i===\".\"){t+=\".\";while(a()&&i>=\"0\"&&i<=\"9\")t+=i}if(i===\"e\"||i===\"E\"){t+=i,a();if(i===\"-\"||i===\"+\")t+=i,a();while(i>=\"0\"&&i<=\"9\")t+=i,a()}e=+t;if(!isNaN(e))return e;u(\"Bad number\")},l=function(){var e,t,n=\"\",r;if(i==='\"')while(a()){if(i==='\"')return a(),n;if(i===\"\\\\\"){a();if(i===\"u\"){r=0;for(t=0;t<4;t+=1){e=parseInt(a(),16);if(!isFinite(e))break;r=r*16+e}n+=String.fromCharCode(r)}else{if(typeof s[i]!=\"string\")break;n+=s[i]}}else n+=i}u(\"Bad string\")},c=function(){while(i&&i<=\" \")a()},h=function(){switch(i){case\"t\":return a(\"t\"),a(\"r\"),a(\"u\"),a(\"e\"),!0;case\"f\":return a(\"f\"),a(\"a\"),a(\"l\"),a(\"s\"),a(\"e\"),!1;case\"n\":return a(\"n\"),a(\"u\"),a(\"l\"),a(\"l\"),null}u(\"Unexpected '\"+i+\"'\")},p,d=function(){var e=[];if(i===\"[\"){a(\"[\"),c();if(i===\"]\")return a(\"]\"),e;while(i){e.push(p()),c();if(i===\"]\")return a(\"]\"),e;a(\",\"),c()}}u(\"Bad array\")},v=function(){var e,t={};if(i===\"{\"){a(\"{\"),c();if(i===\"}\")return a(\"}\"),t;while(i){e=l(),c(),a(\":\"),Object.hasOwnProperty.call(t,e)&&u('Duplicate key \"'+e+'\"'),t[e]=p(),c();if(i===\"}\")return a(\"}\"),t;a(\",\"),c()}}u(\"Bad object\")};return p=function(){c();switch(i){case\"{\":return v();case\"[\":return d();case'\"':return l();case\"-\":return f();default:return i>=\"0\"&&i<=\"9\"?f():h()}},function(e,t){var n;return o=e,r=0,i=\" \",n=p(),c(),i&&u(\"Syntax error\"),typeof t==\"function\"?function s(e,n){var r,i,o=e[n];if(o&&typeof o==\"object\")for(r in o)Object.hasOwnProperty.call(o,r)&&(i=s(o,r),i!==undefined?o[r]=i:delete o[r]);return t.call(e,n,o)}({\"\":n},\"\"):n}}),define(\"ace/mode/json_worker\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/worker/mirror\",\"ace/mode/json/json_parse\"],function(e,t,n){\"use strict\";var r=e(\"../lib/oop\"),i=e(\"../worker/mirror\").Mirror,s=e(\"./json/json_parse\"),o=t.JsonWorker=function(e){i.call(this,e),this.setTimeout(200)};r.inherits(o,i),function(){this.onUpdate=function(){var e=this.doc.getValue(),t=[];try{e&&s(e)}catch(n){var r=this.doc.indexToPosition(n.at-1);t.push({row:r.row,column:r.column,text:n.message,type:\"error\"})}this.sender.emit(\"annotate\",t)}}.call(o.prototype)}),define(\"ace/lib/es5-shim\",[\"require\",\"exports\",\"module\"],function(e,t,n){function r(){}function w(e){try{return Object.defineProperty(e,\"sentinel\",{}),\"sentinel\"in e}catch(t){}}function H(e){return e=+e,e!==e?e=0:e!==0&&e!==1/0&&e!==-1/0&&(e=(e>0||-1)*Math.floor(Math.abs(e))),e}function B(e){var t=typeof e;return e===null||t===\"undefined\"||t===\"boolean\"||t===\"number\"||t===\"string\"}function j(e){var t,n,r;if(B(e))return e;n=e.valueOf;if(typeof n==\"function\"){t=n.call(e);if(B(t))return t}r=e.toString;if(typeof r==\"function\"){t=r.call(e);if(B(t))return t}throw new TypeError}Function.prototype.bind||(Function.prototype.bind=function(t){var n=this;if(typeof n!=\"function\")throw new TypeError(\"Function.prototype.bind called on incompatible \"+n);var i=u.call(arguments,1),s=function(){if(this instanceof s){var e=n.apply(this,i.concat(u.call(arguments)));return Object(e)===e?e:this}return n.apply(t,i.concat(u.call(arguments)))};return n.prototype&&(r.prototype=n.prototype,s.prototype=new r,r.prototype=null),s});var i=Function.prototype.call,s=Array.prototype,o=Object.prototype,u=s.slice,a=i.bind(o.toString),f=i.bind(o.hasOwnProperty),l,c,h,p,d;if(d=f(o,\"__defineGetter__\"))l=i.bind(o.__defineGetter__),c=i.bind(o.__defineSetter__),h=i.bind(o.__lookupGetter__),p=i.bind(o.__lookupSetter__);if([1,2].splice(0).length!=2)if(!function(){function e(e){var t=new Array(e+2);return t[0]=t[1]=0,t}var t=[],n;t.splice.apply(t,e(20)),t.splice.apply(t,e(26)),n=t.length,t.splice(5,0,\"XXX\"),n+1==t.length;if(n+1==t.length)return!0}())Array.prototype.splice=function(e,t){var n=this.length;e>0?e>n&&(e=n):e==void 0?e=0:e<0&&(e=Math.max(n+e,0)),e+t<n||(t=n-e);var r=this.slice(e,e+t),i=u.call(arguments,2),s=i.length;if(e===n)s&&this.push.apply(this,i);else{var o=Math.min(t,n-e),a=e+o,f=a+s-o,l=n-a,c=n-o;if(f<a)for(var h=0;h<l;++h)this[f+h]=this[a+h];else if(f>a)for(h=l;h--;)this[f+h]=this[a+h];if(s&&e===c)this.length=c,this.push.apply(this,i);else{this.length=c+s;for(h=0;h<s;++h)this[e+h]=i[h]}}return r};else{var v=Array.prototype.splice;Array.prototype.splice=function(e,t){return arguments.length?v.apply(this,[e===void 0?0:e,t===void 0?this.length-e:t].concat(u.call(arguments,2))):[]}}Array.isArray||(Array.isArray=function(t){return a(t)==\"[object Array]\"});var m=Object(\"a\"),g=m[0]!=\"a\"||!(0 in m);Array.prototype.forEach||(Array.prototype.forEach=function(t){var n=F(this),r=g&&a(this)==\"[object String]\"?this.split(\"\"):n,i=arguments[1],s=-1,o=r.length>>>0;if(a(t)!=\"[object Function]\")throw new TypeError;while(++s<o)s in r&&t.call(i,r[s],s,n)}),Array.prototype.map||(Array.prototype.map=function(t){var n=F(this),r=g&&a(this)==\"[object String]\"?this.split(\"\"):n,i=r.length>>>0,s=Array(i),o=arguments[1];if(a(t)!=\"[object Function]\")throw new TypeError(t+\" is not a function\");for(var u=0;u<i;u++)u in r&&(s[u]=t.call(o,r[u],u,n));return s}),Array.prototype.filter||(Array.prototype.filter=function(t){var n=F(this),r=g&&a(this)==\"[object String]\"?this.split(\"\"):n,i=r.length>>>0,s=[],o,u=arguments[1];if(a(t)!=\"[object Function]\")throw new TypeError(t+\" is not a function\");for(var f=0;f<i;f++)f in r&&(o=r[f],t.call(u,o,f,n)&&s.push(o));return s}),Array.prototype.every||(Array.prototype.every=function(t){var n=F(this),r=g&&a(this)==\"[object String]\"?this.split(\"\"):n,i=r.length>>>0,s=arguments[1];if(a(t)!=\"[object Function]\")throw new TypeError(t+\" is not a function\");for(var o=0;o<i;o++)if(o in r&&!t.call(s,r[o],o,n))return!1;return!0}),Array.prototype.some||(Array.prototype.some=function(t){var n=F(this),r=g&&a(this)==\"[object String]\"?this.split(\"\"):n,i=r.length>>>0,s=arguments[1];if(a(t)!=\"[object Function]\")throw new TypeError(t+\" is not a function\");for(var o=0;o<i;o++)if(o in r&&t.call(s,r[o],o,n))return!0;return!1}),Array.prototype.reduce||(Array.prototype.reduce=function(t){var n=F(this),r=g&&a(this)==\"[object String]\"?this.split(\"\"):n,i=r.length>>>0;if(a(t)!=\"[object Function]\")throw new TypeError(t+\" is not a function\");if(!i&&arguments.length==1)throw new TypeError(\"reduce of empty array with no initial value\");var s=0,o;if(arguments.length>=2)o=arguments[1];else do{if(s in r){o=r[s++];break}if(++s>=i)throw new TypeError(\"reduce of empty array with no initial value\")}while(!0);for(;s<i;s++)s in r&&(o=t.call(void 0,o,r[s],s,n));return o}),Array.prototype.reduceRight||(Array.prototype.reduceRight=function(t){var n=F(this),r=g&&a(this)==\"[object String]\"?this.split(\"\"):n,i=r.length>>>0;if(a(t)!=\"[object Function]\")throw new TypeError(t+\" is not a function\");if(!i&&arguments.length==1)throw new TypeError(\"reduceRight of empty array with no initial value\");var s,o=i-1;if(arguments.length>=2)s=arguments[1];else do{if(o in r){s=r[o--];break}if(--o<0)throw new TypeError(\"reduceRight of empty array with no initial value\")}while(!0);do o in this&&(s=t.call(void 0,s,r[o],o,n));while(o--);return s});if(!Array.prototype.indexOf||[0,1].indexOf(1,2)!=-1)Array.prototype.indexOf=function(t){var n=g&&a(this)==\"[object String]\"?this.split(\"\"):F(this),r=n.length>>>0;if(!r)return-1;var i=0;arguments.length>1&&(i=H(arguments[1])),i=i>=0?i:Math.max(0,r+i);for(;i<r;i++)if(i in n&&n[i]===t)return i;return-1};if(!Array.prototype.lastIndexOf||[0,1].lastIndexOf(0,-3)!=-1)Array.prototype.lastIndexOf=function(t){var n=g&&a(this)==\"[object String]\"?this.split(\"\"):F(this),r=n.length>>>0;if(!r)return-1;var i=r-1;arguments.length>1&&(i=Math.min(i,H(arguments[1]))),i=i>=0?i:r-Math.abs(i);for(;i>=0;i--)if(i in n&&t===n[i])return i;return-1};Object.getPrototypeOf||(Object.getPrototypeOf=function(t){return t.__proto__||(t.constructor?t.constructor.prototype:o)});if(!Object.getOwnPropertyDescriptor){var y=\"Object.getOwnPropertyDescriptor called on a non-object: \";Object.getOwnPropertyDescriptor=function(t,n){if(typeof t!=\"object\"&&typeof t!=\"function\"||t===null)throw new TypeError(y+t);if(!f(t,n))return;var r,i,s;r={enumerable:!0,configurable:!0};if(d){var u=t.__proto__;t.__proto__=o;var i=h(t,n),s=p(t,n);t.__proto__=u;if(i||s)return i&&(r.get=i),s&&(r.set=s),r}return r.value=t[n],r}}Object.getOwnPropertyNames||(Object.getOwnPropertyNames=function(t){return Object.keys(t)});if(!Object.create){var b;Object.prototype.__proto__===null?b=function(){return{__proto__:null}}:b=function(){var e={};for(var t in e)e[t]=null;return e.constructor=e.hasOwnProperty=e.propertyIsEnumerable=e.isPrototypeOf=e.toLocaleString=e.toString=e.valueOf=e.__proto__=null,e},Object.create=function(t,n){var r;if(t===null)r=b();else{if(typeof t!=\"object\")throw new TypeError(\"typeof prototype[\"+typeof t+\"] != 'object'\");var i=function(){};i.prototype=t,r=new i,r.__proto__=t}return n!==void 0&&Object.defineProperties(r,n),r}}if(Object.defineProperty){var E=w({}),S=typeof document==\"undefined\"||w(document.createElement(\"div\"));if(!E||!S)var x=Object.defineProperty}if(!Object.defineProperty||x){var T=\"Property description must be an object: \",N=\"Object.defineProperty called on non-object: \",C=\"getters & setters can not be defined on this javascript engine\";Object.defineProperty=function(t,n,r){if(typeof t!=\"object\"&&typeof t!=\"function\"||t===null)throw new TypeError(N+t);if(typeof r!=\"object\"&&typeof r!=\"function\"||r===null)throw new TypeError(T+r);if(x)try{return x.call(Object,t,n,r)}catch(i){}if(f(r,\"value\"))if(d&&(h(t,n)||p(t,n))){var s=t.__proto__;t.__proto__=o,delete t[n],t[n]=r.value,t.__proto__=s}else t[n]=r.value;else{if(!d)throw new TypeError(C);f(r,\"get\")&&l(t,n,r.get),f(r,\"set\")&&c(t,n,r.set)}return t}}Object.defineProperties||(Object.defineProperties=function(t,n){for(var r in n)f(n,r)&&Object.defineProperty(t,r,n[r]);return t}),Object.seal||(Object.seal=function(t){return t}),Object.freeze||(Object.freeze=function(t){return t});try{Object.freeze(function(){})}catch(k){Object.freeze=function(t){return function(n){return typeof n==\"function\"?n:t(n)}}(Object.freeze)}Object.preventExtensions||(Object.preventExtensions=function(t){return t}),Object.isSealed||(Object.isSealed=function(t){return!1}),Object.isFrozen||(Object.isFrozen=function(t){return!1}),Object.isExtensible||(Object.isExtensible=function(t){if(Object(t)===t)throw new TypeError;var n=\"\";while(f(t,n))n+=\"?\";t[n]=!0;var r=f(t,n);return delete t[n],r});if(!Object.keys){var L=!0,A=[\"toString\",\"toLocaleString\",\"valueOf\",\"hasOwnProperty\",\"isPrototypeOf\",\"propertyIsEnumerable\",\"constructor\"],O=A.length;for(var M in{toString:null})L=!1;Object.keys=function I(e){if(typeof e!=\"object\"&&typeof e!=\"function\"||e===null)throw new TypeError(\"Object.keys called on a non-object\");var I=[];for(var t in e)f(e,t)&&I.push(t);if(L)for(var n=0,r=O;n<r;n++){var i=A[n];f(e,i)&&I.push(i)}return I}}Date.now||(Date.now=function(){return(new Date).getTime()});var _=\"\t\\n\u000b\\f\\r \\u00a0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029\\ufeff\";if(!String.prototype.trim||_.trim()){_=\"[\"+_+\"]\";var D=new RegExp(\"^\"+_+_+\"*\"),P=new RegExp(_+_+\"*$\");String.prototype.trim=function(){return String(this).replace(D,\"\").replace(P,\"\")}}var F=function(e){if(e==null)throw new TypeError(\"can't convert \"+e+\" to object\");return Object(e)}})\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/vendor/ui-ace/worker-xml.js",
    "content": "\"no use strict\";!function(e){function t(e,t){var n=e,r=\"\";while(n){var i=t[n];if(typeof i==\"string\")return i+r;if(i)return i.location.replace(/\\/*$/,\"/\")+(r||i.main||i.name);if(i===!1)return\"\";var s=n.lastIndexOf(\"/\");if(s===-1)break;r=n.substr(s)+r,n=n.slice(0,s)}return e}if(typeof e.window!=\"undefined\"&&e.document)return;if(e.require&&e.define)return;e.console||(e.console=function(){var e=Array.prototype.slice.call(arguments,0);postMessage({type:\"log\",data:e})},e.console.error=e.console.warn=e.console.log=e.console.trace=e.console),e.window=e,e.ace=e,e.onerror=function(e,t,n,r,i){postMessage({type:\"error\",data:{message:e,data:i.data,file:t,line:n,col:r,stack:i.stack}})},e.normalizeModule=function(t,n){if(n.indexOf(\"!\")!==-1){var r=n.split(\"!\");return e.normalizeModule(t,r[0])+\"!\"+e.normalizeModule(t,r[1])}if(n.charAt(0)==\".\"){var i=t.split(\"/\").slice(0,-1).join(\"/\");n=(i?i+\"/\":\"\")+n;while(n.indexOf(\".\")!==-1&&s!=n){var s=n;n=n.replace(/^\\.\\//,\"\").replace(/\\/\\.\\//,\"/\").replace(/[^\\/]+\\/\\.\\.\\//,\"\")}}return n},e.require=function(r,i){i||(i=r,r=null);if(!i.charAt)throw new Error(\"worker.js require() accepts only (parentId, id) as arguments\");i=e.normalizeModule(r,i);var s=e.require.modules[i];if(s)return s.initialized||(s.initialized=!0,s.exports=s.factory().exports),s.exports;if(!e.require.tlns)return console.log(\"unable to load \"+i);var o=t(i,e.require.tlns);return o.slice(-3)!=\".js\"&&(o+=\".js\"),e.require.id=i,e.require.modules[i]={},importScripts(o),e.require(r,i)},e.require.modules={},e.require.tlns={},e.define=function(t,n,r){arguments.length==2?(r=n,typeof t!=\"string\"&&(n=t,t=e.require.id)):arguments.length==1&&(r=t,n=[],t=e.require.id);if(typeof r!=\"function\"){e.require.modules[t]={exports:r,initialized:!0};return}n.length||(n=[\"require\",\"exports\",\"module\"]);var i=function(n){return e.require(t,n)};e.require.modules[t]={exports:{},factory:function(){var e=this,t=r.apply(this,n.map(function(t){switch(t){case\"require\":return i;case\"exports\":return e.exports;case\"module\":return e;default:return i(t)}}));return t&&(e.exports=t),e}}},e.define.amd={},require.tlns={},e.initBaseUrls=function(t){for(var n in t)require.tlns[n]=t[n]},e.initSender=function(){var n=e.require(\"ace/lib/event_emitter\").EventEmitter,r=e.require(\"ace/lib/oop\"),i=function(){};return function(){r.implement(this,n),this.callback=function(e,t){postMessage({type:\"call\",id:t,data:e})},this.emit=function(e,t){postMessage({type:\"event\",name:e,data:t})}}.call(i.prototype),new i};var n=e.main=null,r=e.sender=null;e.onmessage=function(t){var i=t.data;if(i.event&&r)r._signal(i.event,i.data);else if(i.command)if(n[i.command])n[i.command].apply(n,i.args);else{if(!e[i.command])throw new Error(\"Unknown command:\"+i.command);e[i.command].apply(e,i.args)}else if(i.init){e.initBaseUrls(i.tlns),require(\"ace/lib/es5-shim\"),r=e.sender=e.initSender();var s=require(i.module)[i.classname];n=e.main=new s(r)}}}(this),define(\"ace/lib/oop\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";t.inherits=function(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})},t.mixin=function(e,t){for(var n in t)e[n]=t[n];return e},t.implement=function(e,n){t.mixin(e,n)}}),define(\"ace/lib/lang\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";t.last=function(e){return e[e.length-1]},t.stringReverse=function(e){return e.split(\"\").reverse().join(\"\")},t.stringRepeat=function(e,t){var n=\"\";while(t>0){t&1&&(n+=e);if(t>>=1)e+=e}return n};var r=/^\\s\\s*/,i=/\\s\\s*$/;t.stringTrimLeft=function(e){return e.replace(r,\"\")},t.stringTrimRight=function(e){return e.replace(i,\"\")},t.copyObject=function(e){var t={};for(var n in e)t[n]=e[n];return t},t.copyArray=function(e){var t=[];for(var n=0,r=e.length;n<r;n++)e[n]&&typeof e[n]==\"object\"?t[n]=this.copyObject(e[n]):t[n]=e[n];return t},t.deepCopy=function s(e){if(typeof e!=\"object\"||!e)return e;var t;if(Array.isArray(e)){t=[];for(var n=0;n<e.length;n++)t[n]=s(e[n]);return t}if(Object.prototype.toString.call(e)!==\"[object Object]\")return e;t={};for(var n in e)t[n]=s(e[n]);return t},t.arrayToMap=function(e){var t={};for(var n=0;n<e.length;n++)t[e[n]]=1;return t},t.createMap=function(e){var t=Object.create(null);for(var n in e)t[n]=e[n];return t},t.arrayRemove=function(e,t){for(var n=0;n<=e.length;n++)t===e[n]&&e.splice(n,1)},t.escapeRegExp=function(e){return e.replace(/([.*+?^${}()|[\\]\\/\\\\])/g,\"\\\\$1\")},t.escapeHTML=function(e){return e.replace(/&/g,\"&#38;\").replace(/\"/g,\"&#34;\").replace(/'/g,\"&#39;\").replace(/</g,\"&#60;\")},t.getMatchOffsets=function(e,t){var n=[];return e.replace(t,function(e){n.push({offset:arguments[arguments.length-2],length:e.length})}),n},t.deferredCall=function(e){var t=null,n=function(){t=null,e()},r=function(e){return r.cancel(),t=setTimeout(n,e||0),r};return r.schedule=r,r.call=function(){return this.cancel(),e(),r},r.cancel=function(){return clearTimeout(t),t=null,r},r.isPending=function(){return t},r},t.delayedCall=function(e,t){var n=null,r=function(){n=null,e()},i=function(e){n==null&&(n=setTimeout(r,e||t))};return i.delay=function(e){n&&clearTimeout(n),n=setTimeout(r,e||t)},i.schedule=i,i.call=function(){this.cancel(),e()},i.cancel=function(){n&&clearTimeout(n),n=null},i.isPending=function(){return n},i}}),define(\"ace/range\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";var r=function(e,t){return e.row-t.row||e.column-t.column},i=function(e,t,n,r){this.start={row:e,column:t},this.end={row:n,column:r}};(function(){this.isEqual=function(e){return this.start.row===e.start.row&&this.end.row===e.end.row&&this.start.column===e.start.column&&this.end.column===e.end.column},this.toString=function(){return\"Range: [\"+this.start.row+\"/\"+this.start.column+\"] -> [\"+this.end.row+\"/\"+this.end.column+\"]\"},this.contains=function(e,t){return this.compare(e,t)==0},this.compareRange=function(e){var t,n=e.end,r=e.start;return t=this.compare(n.row,n.column),t==1?(t=this.compare(r.row,r.column),t==1?2:t==0?1:0):t==-1?-2:(t=this.compare(r.row,r.column),t==-1?-1:t==1?42:0)},this.comparePoint=function(e){return this.compare(e.row,e.column)},this.containsRange=function(e){return this.comparePoint(e.start)==0&&this.comparePoint(e.end)==0},this.intersects=function(e){var t=this.compareRange(e);return t==-1||t==0||t==1},this.isEnd=function(e,t){return this.end.row==e&&this.end.column==t},this.isStart=function(e,t){return this.start.row==e&&this.start.column==t},this.setStart=function(e,t){typeof e==\"object\"?(this.start.column=e.column,this.start.row=e.row):(this.start.row=e,this.start.column=t)},this.setEnd=function(e,t){typeof e==\"object\"?(this.end.column=e.column,this.end.row=e.row):(this.end.row=e,this.end.column=t)},this.inside=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)||this.isStart(e,t)?!1:!0:!1},this.insideStart=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)?!1:!0:!1},this.insideEnd=function(e,t){return this.compare(e,t)==0?this.isStart(e,t)?!1:!0:!1},this.compare=function(e,t){return!this.isMultiLine()&&e===this.start.row?t<this.start.column?-1:t>this.end.column?1:0:e<this.start.row?-1:e>this.end.row?1:this.start.row===e?t>=this.start.column?0:-1:this.end.row===e?t<=this.end.column?0:1:0},this.compareStart=function(e,t){return this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.compareEnd=function(e,t){return this.end.row==e&&this.end.column==t?1:this.compare(e,t)},this.compareInside=function(e,t){return this.end.row==e&&this.end.column==t?1:this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.clipRows=function(e,t){if(this.end.row>t)var n={row:t+1,column:0};else if(this.end.row<e)var n={row:e,column:0};if(this.start.row>t)var r={row:t+1,column:0};else if(this.start.row<e)var r={row:e,column:0};return i.fromPoints(r||this.start,n||this.end)},this.extend=function(e,t){var n=this.compare(e,t);if(n==0)return this;if(n==-1)var r={row:e,column:t};else var s={row:e,column:t};return i.fromPoints(r||this.start,s||this.end)},this.isEmpty=function(){return this.start.row===this.end.row&&this.start.column===this.end.column},this.isMultiLine=function(){return this.start.row!==this.end.row},this.clone=function(){return i.fromPoints(this.start,this.end)},this.collapseRows=function(){return this.end.column==0?new i(this.start.row,0,Math.max(this.start.row,this.end.row-1),0):new i(this.start.row,0,this.end.row,0)},this.toScreenRange=function(e){var t=e.documentToScreenPosition(this.start),n=e.documentToScreenPosition(this.end);return new i(t.row,t.column,n.row,n.column)},this.moveBy=function(e,t){this.start.row+=e,this.start.column+=t,this.end.row+=e,this.end.column+=t}}).call(i.prototype),i.fromPoints=function(e,t){return new i(e.row,e.column,t.row,t.column)},i.comparePoints=r,i.comparePoints=function(e,t){return e.row-t.row||e.column-t.column},t.Range=i}),define(\"ace/apply_delta\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";function r(e,t){throw console.log(\"Invalid Delta:\",e),\"Invalid Delta: \"+t}function i(e,t){return t.row>=0&&t.row<e.length&&t.column>=0&&t.column<=e[t.row].length}function s(e,t){t.action!=\"insert\"&&t.action!=\"remove\"&&r(t,\"delta.action must be 'insert' or 'remove'\"),t.lines instanceof Array||r(t,\"delta.lines must be an Array\"),(!t.start||!t.end)&&r(t,\"delta.start/end must be an present\");var n=t.start;i(e,t.start)||r(t,\"delta.start must be contained in document\");var s=t.end;t.action==\"remove\"&&!i(e,s)&&r(t,\"delta.end must contained in document for 'remove' actions\");var o=s.row-n.row,u=s.column-(o==0?n.column:0);(o!=t.lines.length-1||t.lines[o].length!=u)&&r(t,\"delta.range must match delta lines\")}t.applyDelta=function(e,t,n){var r=t.start.row,i=t.start.column,s=e[r]||\"\";switch(t.action){case\"insert\":var o=t.lines;if(o.length===1)e[r]=s.substring(0,i)+t.lines[0]+s.substring(i);else{var u=[r,1].concat(t.lines);e.splice.apply(e,u),e[r]=s.substring(0,i)+e[r],e[r+t.lines.length-1]+=s.substring(i)}break;case\"remove\":var a=t.end.column,f=t.end.row;r===f?e[r]=s.substring(0,i)+s.substring(a):e.splice(r,f-r+1,s.substring(0,i)+e[f].substring(a))}}}),define(\"ace/lib/event_emitter\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";var r={},i=function(){this.propagationStopped=!0},s=function(){this.defaultPrevented=!0};r._emit=r._dispatchEvent=function(e,t){this._eventRegistry||(this._eventRegistry={}),this._defaultHandlers||(this._defaultHandlers={});var n=this._eventRegistry[e]||[],r=this._defaultHandlers[e];if(!n.length&&!r)return;if(typeof t!=\"object\"||!t)t={};t.type||(t.type=e),t.stopPropagation||(t.stopPropagation=i),t.preventDefault||(t.preventDefault=s),n=n.slice();for(var o=0;o<n.length;o++){n[o](t,this);if(t.propagationStopped)break}if(r&&!t.defaultPrevented)return r(t,this)},r._signal=function(e,t){var n=(this._eventRegistry||{})[e];if(!n)return;n=n.slice();for(var r=0;r<n.length;r++)n[r](t,this)},r.once=function(e,t){var n=this;t&&this.addEventListener(e,function r(){n.removeEventListener(e,r),t.apply(null,arguments)})},r.setDefaultHandler=function(e,t){var n=this._defaultHandlers;n||(n=this._defaultHandlers={_disabled_:{}});if(n[e]){var r=n[e],i=n._disabled_[e];i||(n._disabled_[e]=i=[]),i.push(r);var s=i.indexOf(t);s!=-1&&i.splice(s,1)}n[e]=t},r.removeDefaultHandler=function(e,t){var n=this._defaultHandlers;if(!n)return;var r=n._disabled_[e];if(n[e]==t){var i=n[e];r&&this.setDefaultHandler(e,r.pop())}else if(r){var s=r.indexOf(t);s!=-1&&r.splice(s,1)}},r.on=r.addEventListener=function(e,t,n){this._eventRegistry=this._eventRegistry||{};var r=this._eventRegistry[e];return r||(r=this._eventRegistry[e]=[]),r.indexOf(t)==-1&&r[n?\"unshift\":\"push\"](t),t},r.off=r.removeListener=r.removeEventListener=function(e,t){this._eventRegistry=this._eventRegistry||{};var n=this._eventRegistry[e];if(!n)return;var r=n.indexOf(t);r!==-1&&n.splice(r,1)},r.removeAllListeners=function(e){this._eventRegistry&&(this._eventRegistry[e]=[])},t.EventEmitter=r}),define(\"ace/anchor\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/event_emitter\"],function(e,t,n){\"use strict\";var r=e(\"./lib/oop\"),i=e(\"./lib/event_emitter\").EventEmitter,s=t.Anchor=function(e,t,n){this.$onChange=this.onChange.bind(this),this.attach(e),typeof n==\"undefined\"?this.setPosition(t.row,t.column):this.setPosition(t,n)};(function(){function e(e,t,n){var r=n?e.column<=t.column:e.column<t.column;return e.row<t.row||e.row==t.row&&r}function t(t,n,r){var i=t.action==\"insert\",s=(i?1:-1)*(t.end.row-t.start.row),o=(i?1:-1)*(t.end.column-t.start.column),u=t.start,a=i?u:t.end;return e(n,u,r)?{row:n.row,column:n.column}:e(a,n,!r)?{row:n.row+s,column:n.column+(n.row==a.row?o:0)}:{row:u.row,column:u.column}}r.implement(this,i),this.getPosition=function(){return this.$clipPositionToDocument(this.row,this.column)},this.getDocument=function(){return this.document},this.$insertRight=!1,this.onChange=function(e){if(e.start.row==e.end.row&&e.start.row!=this.row)return;if(e.start.row>this.row)return;var n=t(e,{row:this.row,column:this.column},this.$insertRight);this.setPosition(n.row,n.column,!0)},this.setPosition=function(e,t,n){var r;n?r={row:e,column:t}:r=this.$clipPositionToDocument(e,t);if(this.row==r.row&&this.column==r.column)return;var i={row:this.row,column:this.column};this.row=r.row,this.column=r.column,this._signal(\"change\",{old:i,value:r})},this.detach=function(){this.document.removeEventListener(\"change\",this.$onChange)},this.attach=function(e){this.document=e||this.document,this.document.on(\"change\",this.$onChange)},this.$clipPositionToDocument=function(e,t){var n={};return e>=this.document.getLength()?(n.row=Math.max(0,this.document.getLength()-1),n.column=this.document.getLine(n.row).length):e<0?(n.row=0,n.column=0):(n.row=e,n.column=Math.min(this.document.getLine(n.row).length,Math.max(0,t))),t<0&&(n.column=0),n}}).call(s.prototype)}),define(\"ace/document\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/apply_delta\",\"ace/lib/event_emitter\",\"ace/range\",\"ace/anchor\"],function(e,t,n){\"use strict\";var r=e(\"./lib/oop\"),i=e(\"./apply_delta\").applyDelta,s=e(\"./lib/event_emitter\").EventEmitter,o=e(\"./range\").Range,u=e(\"./anchor\").Anchor,a=function(e){this.$lines=[\"\"],e.length===0?this.$lines=[\"\"]:Array.isArray(e)?this.insertMergedLines({row:0,column:0},e):this.insert({row:0,column:0},e)};(function(){r.implement(this,s),this.setValue=function(e){var t=this.getLength()-1;this.remove(new o(0,0,t,this.getLine(t).length)),this.insert({row:0,column:0},e)},this.getValue=function(){return this.getAllLines().join(this.getNewLineCharacter())},this.createAnchor=function(e,t){return new u(this,e,t)},\"aaa\".split(/a/).length===0?this.$split=function(e){return e.replace(/\\r\\n|\\r/g,\"\\n\").split(\"\\n\")}:this.$split=function(e){return e.split(/\\r\\n|\\r|\\n/)},this.$detectNewLine=function(e){var t=e.match(/^.*?(\\r\\n|\\r|\\n)/m);this.$autoNewLine=t?t[1]:\"\\n\",this._signal(\"changeNewLineMode\")},this.getNewLineCharacter=function(){switch(this.$newLineMode){case\"windows\":return\"\\r\\n\";case\"unix\":return\"\\n\";default:return this.$autoNewLine||\"\\n\"}},this.$autoNewLine=\"\",this.$newLineMode=\"auto\",this.setNewLineMode=function(e){if(this.$newLineMode===e)return;this.$newLineMode=e,this._signal(\"changeNewLineMode\")},this.getNewLineMode=function(){return this.$newLineMode},this.isNewLine=function(e){return e==\"\\r\\n\"||e==\"\\r\"||e==\"\\n\"},this.getLine=function(e){return this.$lines[e]||\"\"},this.getLines=function(e,t){return this.$lines.slice(e,t+1)},this.getAllLines=function(){return this.getLines(0,this.getLength())},this.getLength=function(){return this.$lines.length},this.getTextRange=function(e){return this.getLinesForRange(e).join(this.getNewLineCharacter())},this.getLinesForRange=function(e){var t;if(e.start.row===e.end.row)t=[this.getLine(e.start.row).substring(e.start.column,e.end.column)];else{t=this.getLines(e.start.row,e.end.row),t[0]=(t[0]||\"\").substring(e.start.column);var n=t.length-1;e.end.row-e.start.row==n&&(t[n]=t[n].substring(0,e.end.column))}return t},this.insertLines=function(e,t){return console.warn(\"Use of document.insertLines is deprecated. Use the insertFullLines method instead.\"),this.insertFullLines(e,t)},this.removeLines=function(e,t){return console.warn(\"Use of document.removeLines is deprecated. Use the removeFullLines method instead.\"),this.removeFullLines(e,t)},this.insertNewLine=function(e){return console.warn(\"Use of document.insertNewLine is deprecated. Use insertMergedLines(position, ['', '']) instead.\"),this.insertMergedLines(e,[\"\",\"\"])},this.insert=function(e,t){return this.getLength()<=1&&this.$detectNewLine(t),this.insertMergedLines(e,this.$split(t))},this.insertInLine=function(e,t){var n=this.clippedPos(e.row,e.column),r=this.pos(e.row,e.column+t.length);return this.applyDelta({start:n,end:r,action:\"insert\",lines:[t]},!0),this.clonePos(r)},this.clippedPos=function(e,t){var n=this.getLength();e===undefined?e=n:e<0?e=0:e>=n&&(e=n-1,t=undefined);var r=this.getLine(e);return t==undefined&&(t=r.length),t=Math.min(Math.max(t,0),r.length),{row:e,column:t}},this.clonePos=function(e){return{row:e.row,column:e.column}},this.pos=function(e,t){return{row:e,column:t}},this.$clipPosition=function(e){var t=this.getLength();return e.row>=t?(e.row=Math.max(0,t-1),e.column=this.getLine(t-1).length):(e.row=Math.max(0,e.row),e.column=Math.min(Math.max(e.column,0),this.getLine(e.row).length)),e},this.insertFullLines=function(e,t){e=Math.min(Math.max(e,0),this.getLength());var n=0;e<this.getLength()?(t=t.concat([\"\"]),n=0):(t=[\"\"].concat(t),e--,n=this.$lines[e].length),this.insertMergedLines({row:e,column:n},t)},this.insertMergedLines=function(e,t){var n=this.clippedPos(e.row,e.column),r={row:n.row+t.length-1,column:(t.length==1?n.column:0)+t[t.length-1].length};return this.applyDelta({start:n,end:r,action:\"insert\",lines:t}),this.clonePos(r)},this.remove=function(e){var t=this.clippedPos(e.start.row,e.start.column),n=this.clippedPos(e.end.row,e.end.column);return this.applyDelta({start:t,end:n,action:\"remove\",lines:this.getLinesForRange({start:t,end:n})}),this.clonePos(t)},this.removeInLine=function(e,t,n){var r=this.clippedPos(e,t),i=this.clippedPos(e,n);return this.applyDelta({start:r,end:i,action:\"remove\",lines:this.getLinesForRange({start:r,end:i})},!0),this.clonePos(r)},this.removeFullLines=function(e,t){e=Math.min(Math.max(0,e),this.getLength()-1),t=Math.min(Math.max(0,t),this.getLength()-1);var n=t==this.getLength()-1&&e>0,r=t<this.getLength()-1,i=n?e-1:e,s=n?this.getLine(i).length:0,u=r?t+1:t,a=r?0:this.getLine(u).length,f=new o(i,s,u,a),l=this.$lines.slice(e,t+1);return this.applyDelta({start:f.start,end:f.end,action:\"remove\",lines:this.getLinesForRange(f)}),l},this.removeNewLine=function(e){e<this.getLength()-1&&e>=0&&this.applyDelta({start:this.pos(e,this.getLine(e).length),end:this.pos(e+1,0),action:\"remove\",lines:[\"\",\"\"]})},this.replace=function(e,t){e instanceof o||(e=o.fromPoints(e.start,e.end));if(t.length===0&&e.isEmpty())return e.start;if(t==this.getTextRange(e))return e.end;this.remove(e);var n;return t?n=this.insert(e.start,t):n=e.start,n},this.applyDeltas=function(e){for(var t=0;t<e.length;t++)this.applyDelta(e[t])},this.revertDeltas=function(e){for(var t=e.length-1;t>=0;t--)this.revertDelta(e[t])},this.applyDelta=function(e,t){var n=e.action==\"insert\";if(n?e.lines.length<=1&&!e.lines[0]:!o.comparePoints(e.start,e.end))return;n&&e.lines.length>2e4&&this.$splitAndapplyLargeDelta(e,2e4),i(this.$lines,e,t),this._signal(\"change\",e)},this.$splitAndapplyLargeDelta=function(e,t){var n=e.lines,r=n.length,i=e.start.row,s=e.start.column,o=0,u=0;do{o=u,u+=t-1;var a=n.slice(o,u);if(u>r){e.lines=a,e.start.row=i+o,e.start.column=s;break}a.push(\"\"),this.applyDelta({start:this.pos(i+o,s),end:this.pos(i+u,s=0),action:e.action,lines:a},!0)}while(!0)},this.revertDelta=function(e){this.applyDelta({start:this.clonePos(e.start),end:this.clonePos(e.end),action:e.action==\"insert\"?\"remove\":\"insert\",lines:e.lines.slice()})},this.indexToPosition=function(e,t){var n=this.$lines||this.getAllLines(),r=this.getNewLineCharacter().length;for(var i=t||0,s=n.length;i<s;i++){e-=n[i].length+r;if(e<0)return{row:i,column:e+n[i].length+r}}return{row:s-1,column:n[s-1].length}},this.positionToIndex=function(e,t){var n=this.$lines||this.getAllLines(),r=this.getNewLineCharacter().length,i=0,s=Math.min(e.row,n.length);for(var o=t||0;o<s;++o)i+=n[o].length+r;return i+e.column}}).call(a.prototype),t.Document=a}),define(\"ace/worker/mirror\",[\"require\",\"exports\",\"module\",\"ace/range\",\"ace/document\",\"ace/lib/lang\"],function(e,t,n){\"use strict\";var r=e(\"../range\").Range,i=e(\"../document\").Document,s=e(\"../lib/lang\"),o=t.Mirror=function(e){this.sender=e;var t=this.doc=new i(\"\"),n=this.deferredUpdate=s.delayedCall(this.onUpdate.bind(this)),r=this;e.on(\"change\",function(e){var i=e.data;if(i[0].start)t.applyDeltas(i);else for(var s=0;s<i.length;s+=2){if(Array.isArray(i[s+1]))var o={action:\"insert\",start:i[s],lines:i[s+1]};else var o={action:\"remove\",start:i[s],end:i[s+1]};t.applyDelta(o,!0)}if(r.$timeout)return n.schedule(r.$timeout);r.onUpdate()})};(function(){this.$timeout=500,this.setTimeout=function(e){this.$timeout=e},this.setValue=function(e){this.doc.setValue(e),this.deferredUpdate.schedule(this.$timeout)},this.getValue=function(e){this.sender.callback(this.doc.getValue(),e)},this.onUpdate=function(){},this.isPending=function(){return this.deferredUpdate.isPending()}}).call(o.prototype)}),define(\"ace/mode/xml/sax\",[\"require\",\"exports\",\"module\"],function(e,t,n){function d(){}function v(e,t,n,r,i){function s(e){if(e>65535){e-=65536;var t=55296+(e>>10),n=56320+(e&1023);return String.fromCharCode(t,n)}return String.fromCharCode(e)}function o(e){var t=e.slice(1,-1);return t in n?n[t]:t.charAt(0)===\"#\"?s(parseInt(t.substr(1).replace(\"x\",\"0x\"))):(i.error(\"entity not found:\"+e),e)}function u(t){var n=e.substring(v,t).replace(/&#?\\w+;/g,o);h&&a(v),r.characters(n,0,t-v),v=t}function a(t,n){while(t>=l&&(n=c.exec(e)))f=n.index,l=f+n[0].length,h.lineNumber++;h.columnNumber=t-f+1}var f=0,l=0,c=/.+(?:\\r\\n?|\\n)|.*$/g,h=r.locator,p=[{currentNSMap:t}],d={},v=0;for(;;){var E=e.indexOf(\"<\",v);if(E<0){if(!e.substr(v).match(/^\\s*$/)){var N=r.document,C=N.createTextNode(e.substr(v));N.appendChild(C),r.currentElement=C}return}E>v&&u(E);switch(e.charAt(E+1)){case\"/\":var k=e.indexOf(\">\",E+3),L=e.substring(E+2,k),A;if(!(p.length>1)){i.fatalError(\"end tag name not found for: \"+L);break}A=p.pop();var O=A.localNSMap;A.tagName!=L&&i.fatalError(\"end tag name: \"+L+\" does not match the current start tagName: \"+A.tagName),r.endElement(A.uri,A.localName,L);if(O)for(var M in O)r.endPrefixMapping(M);k++;break;case\"?\":h&&a(E),k=x(e,E,r);break;case\"!\":h&&a(E),k=S(e,E,r,i);break;default:try{h&&a(E);var _=new T,k=g(e,E,_,o,i),D=_.length;if(D&&h){var P=m(h,{});for(var E=0;E<D;E++){var H=_[E];a(H.offset),H.offset=m(h,{})}m(P,h)}!_.closed&&w(e,k,_.tagName,d)&&(_.closed=!0,n.nbsp||i.warning(\"unclosed xml attribute\")),y(_,r,p),_.uri===\"http://www.w3.org/1999/xhtml\"&&!_.closed?k=b(e,k,_.tagName,o,r):k++}catch(B){i.error(\"element parse error: \"+B),k=-1}}k<0?u(E+1):v=k}}function m(e,t){return t.lineNumber=e.lineNumber,t.columnNumber=e.columnNumber,t}function g(e,t,n,r,i){var s,d,v=++t,m=o;for(;;){var g=e.charAt(v);switch(g){case\"=\":if(m===u)s=e.slice(t,v),m=f;else{if(m!==a)throw new Error(\"attribute equal must after attrName\");m=f}break;case\"'\":case'\"':if(m===f){t=v+1,v=e.indexOf(g,t);if(!(v>0))throw new Error(\"attribute value no end '\"+g+\"' match\");d=e.slice(t,v).replace(/&#?\\w+;/g,r),n.add(s,d,t-1),m=c}else{if(m!=l)throw new Error('attribute value must after \"=\"');d=e.slice(t,v).replace(/&#?\\w+;/g,r),n.add(s,d,t),i.warning('attribute \"'+s+'\" missed start quot('+g+\")!!\"),t=v+1,m=c}break;case\"/\":switch(m){case o:n.setTagName(e.slice(t,v));case c:case h:case p:m=p,n.closed=!0;case l:case u:case a:break;default:throw new Error(\"attribute invalid close char('/')\")}break;case\"\":i.error(\"unexpected end of input\");case\">\":switch(m){case o:n.setTagName(e.slice(t,v));case c:case h:case p:break;case l:case u:d=e.slice(t,v),d.slice(-1)===\"/\"&&(n.closed=!0,d=d.slice(0,-1));case a:m===a&&(d=s),m==l?(i.warning('attribute \"'+d+'\" missed quot(\")!!'),n.add(s,d.replace(/&#?\\w+;/g,r),t)):(i.warning('attribute \"'+d+'\" missed value!! \"'+d+'\" instead!!'),n.add(d,d,t));break;case f:throw new Error(\"attribute value missed!!\")}return v;case\"\\u0080\":g=\" \";default:if(g<=\" \")switch(m){case o:n.setTagName(e.slice(t,v)),m=h;break;case u:s=e.slice(t,v),m=a;break;case l:var d=e.slice(t,v).replace(/&#?\\w+;/g,r);i.warning('attribute \"'+d+'\" missed quot(\")!!'),n.add(s,d,t);case c:m=h}else switch(m){case a:i.warning('attribute \"'+s+'\" missed value!! \"'+s+'\" instead!!'),n.add(s,s,t),t=v,m=u;break;case c:i.warning('attribute space is required\"'+s+'\"!!');case h:m=u,t=v;break;case f:m=l,t=v;break;case p:throw new Error(\"elements closed character '/' and '>' must be connected to\")}}v++}}function y(e,t,n){var r=e.tagName,i=null,s=n[n.length-1].currentNSMap,o=e.length;while(o--){var u=e[o],a=u.qName,f=u.value,l=a.indexOf(\":\");if(l>0)var c=u.prefix=a.slice(0,l),h=a.slice(l+1),p=c===\"xmlns\"&&h;else h=a,c=null,p=a===\"xmlns\"&&\"\";u.localName=h,p!==!1&&(i==null&&(i={},E(s,s={})),s[p]=i[p]=f,u.uri=\"http://www.w3.org/2000/xmlns/\",t.startPrefixMapping(p,f))}var o=e.length;while(o--){u=e[o];var c=u.prefix;c&&(c===\"xml\"&&(u.uri=\"http://www.w3.org/XML/1998/namespace\"),c!==\"xmlns\"&&(u.uri=s[c]))}var l=r.indexOf(\":\");l>0?(c=e.prefix=r.slice(0,l),h=e.localName=r.slice(l+1)):(c=null,h=e.localName=r);var d=e.uri=s[c||\"\"];t.startElement(d,h,r,e);if(e.closed){t.endElement(d,h,r);if(i)for(c in i)t.endPrefixMapping(c)}else e.currentNSMap=s,e.localNSMap=i,n.push(e)}function b(e,t,n,r,i){if(/^(?:script|textarea)$/i.test(n)){var s=e.indexOf(\"</\"+n+\">\",t),o=e.substring(t+1,s);if(/[&<]/.test(o))return/^script$/i.test(n)?(i.characters(o,0,o.length),s):(o=o.replace(/&#?\\w+;/g,r),i.characters(o,0,o.length),s)}return t+1}function w(e,t,n,r){var i=r[n];return i==null&&(i=r[n]=e.lastIndexOf(\"</\"+n+\">\")),i<t}function E(e,t){for(var n in e)t[n]=e[n]}function S(e,t,n,r){var i=e.charAt(t+2);switch(i){case\"-\":if(e.charAt(t+3)===\"-\"){var s=e.indexOf(\"-->\",t+4);return s>t?(n.comment(e,t+4,s-t-4),s+3):(r.error(\"Unclosed comment\"),-1)}return-1;default:if(e.substr(t+3,6)==\"CDATA[\"){var s=e.indexOf(\"]]>\",t+9);return n.startCDATA(),n.characters(e,t+9,s-t-9),n.endCDATA(),s+3}var o=C(e,t),u=o.length;if(u>1&&/!doctype/i.test(o[0][0])){var a=o[1][0],f=u>3&&/^public$/i.test(o[2][0])&&o[3][0],l=u>4&&o[4][0],c=o[u-1];return n.startDTD(a,f&&f.replace(/^(['\"])(.*?)\\1$/,\"$2\"),l&&l.replace(/^(['\"])(.*?)\\1$/,\"$2\")),n.endDTD(),c.index+c[0].length}}return-1}function x(e,t,n){var r=e.indexOf(\"?>\",t);if(r){var i=e.substring(t,r).match(/^<\\?(\\S*)\\s*([\\s\\S]*?)\\s*$/);if(i){var s=i[0].length;return n.processingInstruction(i[1],i[2]),r+2}return-1}return-1}function T(e){}function N(e,t){return e.__proto__=t,e}function C(e,t){var n,r=[],i=/'[^']+'|\"[^\"]+\"|[^\\s<>\\/=]+=?|(\\/?\\s*>|<)/g;i.lastIndex=t,i.exec(e);while(n=i.exec(e)){r.push(n);if(n[1])return r}}var r=/[A-Z_a-z\\xC0-\\xD6\\xD8-\\xF6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD]/,i=new RegExp(\"[\\\\-\\\\.0-9\"+r.source.slice(1,-1)+\"\\u00b7\\u0300-\\u036f\\\\ux203F-\\u2040]\"),s=new RegExp(\"^\"+r.source+i.source+\"*(?::\"+r.source+i.source+\"*)?$\"),o=0,u=1,a=2,f=3,l=4,c=5,h=6,p=7;return d.prototype={parse:function(e,t,n){var r=this.domBuilder;r.startDocument(),E(t,t={}),v(e,t,n,r,this.errorHandler),r.endDocument()}},T.prototype={setTagName:function(e){if(!s.test(e))throw new Error(\"invalid tagName:\"+e);this.tagName=e},add:function(e,t,n){if(!s.test(e))throw new Error(\"invalid attribute:\"+e);this[this.length++]={qName:e,value:t,offset:n}},length:0,getLocalName:function(e){return this[e].localName},getOffset:function(e){return this[e].offset},getQName:function(e){return this[e].qName},getURI:function(e){return this[e].uri},getValue:function(e){return this[e].value}},N({},N.prototype)instanceof N||(N=function(e,t){function n(){}n.prototype=t,n=new n;for(t in e)n[t]=e[t];return n}),d}),define(\"ace/mode/xml/dom\",[\"require\",\"exports\",\"module\"],function(e,t,n){function r(e,t){for(var n in e)t[n]=e[n]}function i(e,t){var n=e.prototype;if(Object.create){var i=Object.create(t.prototype);n.__proto__=i}if(!(n instanceof t)){function s(){}s.prototype=t.prototype,s=new s,r(n,s),e.prototype=n=s}n.constructor!=e&&(typeof e!=\"function\"&&console.error(\"unknow Class:\"+e),n.constructor=e)}function B(e,t){if(t instanceof Error)var n=t;else n=this,Error.call(this,w[e]),this.message=w[e],Error.captureStackTrace&&Error.captureStackTrace(this,B);return n.code=e,t&&(this.message=this.message+\": \"+t),n}function j(){}function F(e,t){this._node=e,this._refresh=t,I(this)}function I(e){var t=e._node._inc||e._node.ownerDocument._inc;if(e._inc!=t){var n=e._refresh(e._node);gt(e,\"length\",n.length),r(n,e),e._inc=t}}function q(){}function R(e,t){var n=e.length;while(n--)if(e[n]===t)return n}function U(e,t,n,r){r?t[R(t,r)]=n:t[t.length++]=n;if(e){n.ownerElement=e;var i=e.ownerDocument;i&&(r&&Q(i,e,r),K(i,e,n))}}function z(e,t,n){var r=R(t,n);if(!(r>=0))throw B(L,new Error);var i=t.length-1;while(r<i)t[r]=t[++r];t.length=i;if(e){var s=e.ownerDocument;s&&(Q(s,e,n),n.ownerElement=null)}}function W(e){this._features={};if(e)for(var t in e)this._features=e[t]}function X(){}function V(e){return e==\"<\"&&\"&lt;\"||e==\">\"&&\"&gt;\"||e==\"&\"&&\"&amp;\"||e=='\"'&&\"&quot;\"||\"&#\"+e.charCodeAt()+\";\"}function $(e,t){if(t(e))return!0;if(e=e.firstChild)do if($(e,t))return!0;while(e=e.nextSibling)}function J(){}function K(e,t,n){e&&e._inc++;var r=n.namespaceURI;r==\"http://www.w3.org/2000/xmlns/\"&&(t._nsMap[n.prefix?n.localName:\"\"]=n.value)}function Q(e,t,n,r){e&&e._inc++;var i=n.namespaceURI;i==\"http://www.w3.org/2000/xmlns/\"&&delete t._nsMap[n.prefix?n.localName:\"\"]}function G(e,t,n){if(e&&e._inc){e._inc++;var r=t.childNodes;if(n)r[r.length++]=n;else{var i=t.firstChild,s=0;while(i)r[s++]=i,i=i.nextSibling;r.length=s}}}function Y(e,t){var n=t.previousSibling,r=t.nextSibling;return n?n.nextSibling=r:e.firstChild=r,r?r.previousSibling=n:e.lastChild=n,G(e.ownerDocument,e),t}function Z(e,t,n){var r=t.parentNode;r&&r.removeChild(t);if(t.nodeType===g){var i=t.firstChild;if(i==null)return t;var s=t.lastChild}else i=s=t;var o=n?n.previousSibling:e.lastChild;i.previousSibling=o,s.nextSibling=n,o?o.nextSibling=i:e.firstChild=i,n==null?e.lastChild=s:n.previousSibling=s;do i.parentNode=e;while(i!==s&&(i=i.nextSibling));return G(e.ownerDocument||e,e),t.nodeType==g&&(t.firstChild=t.lastChild=null),t}function et(e,t){var n=t.parentNode;if(n){var r=e.lastChild;n.removeChild(t);var r=e.lastChild}var r=e.lastChild;return t.parentNode=e,t.previousSibling=r,t.nextSibling=null,r?r.nextSibling=t:e.firstChild=t,e.lastChild=t,G(e.ownerDocument,e,t),t}function tt(){this._nsMap={}}function nt(){}function rt(){}function it(){}function st(){}function ot(){}function ut(){}function at(){}function ft(){}function lt(){}function ct(){}function ht(){}function pt(){}function dt(e,t){switch(e.nodeType){case u:var n=e.attributes,r=n.length,i=e.firstChild,o=e.tagName,h=s===e.namespaceURI;t.push(\"<\",o);for(var y=0;y<r;y++)dt(n.item(y),t,h);if(i||h&&!/^(?:meta|link|img|br|hr|input|button)$/i.test(o)){t.push(\">\");if(h&&/^script$/i.test(o))i&&t.push(i.data);else while(i)dt(i,t),i=i.nextSibling;t.push(\"</\",o,\">\")}else t.push(\"/>\");return;case v:case g:var i=e.firstChild;while(i)dt(i,t),i=i.nextSibling;return;case a:return t.push(\" \",e.name,'=\"',e.value.replace(/[<&\"]/g,V),'\"');case f:return t.push(e.data.replace(/[<&]/g,V));case l:return t.push(\"<![CDATA[\",e.data,\"]]>\");case d:return t.push(\"<!--\",e.data,\"-->\");case m:var b=e.publicId,w=e.systemId;t.push(\"<!DOCTYPE \",e.name);if(b)t.push(' PUBLIC \"',b),w&&w!=\".\"&&t.push('\" \"',w),t.push('\">');else if(w&&w!=\".\")t.push(' SYSTEM \"',w,'\">');else{var E=e.internalSubset;E&&t.push(\" [\",E,\"]\"),t.push(\">\")}return;case p:return t.push(\"<?\",e.target,\" \",e.data,\"?>\");case c:return t.push(\"&\",e.nodeName,\";\");default:t.push(\"??\",e.nodeName)}}function vt(e,t,n){var r;switch(t.nodeType){case u:r=t.cloneNode(!1),r.ownerDocument=e;case g:break;case a:n=!0}r||(r=t.cloneNode(!1)),r.ownerDocument=e,r.parentNode=null;if(n){var i=t.firstChild;while(i)r.appendChild(vt(e,i,n)),i=i.nextSibling}return r}function mt(e,t,n){var r=new t.constructor;for(var i in t){var s=t[i];typeof s!=\"object\"&&s!=r[i]&&(r[i]=s)}t.childNodes&&(r.childNodes=new j),r.ownerDocument=e;switch(r.nodeType){case u:var o=t.attributes,f=r.attributes=new q,l=o.length;f._ownerElement=r;for(var c=0;c<l;c++)r.setAttributeNode(mt(e,o.item(c),!0));break;case a:n=!0}if(n){var h=t.firstChild;while(h)r.appendChild(mt(e,h,n)),h=h.nextSibling}return r}function gt(e,t,n){e[t]=n}var s=\"http://www.w3.org/1999/xhtml\",o={},u=o.ELEMENT_NODE=1,a=o.ATTRIBUTE_NODE=2,f=o.TEXT_NODE=3,l=o.CDATA_SECTION_NODE=4,c=o.ENTITY_REFERENCE_NODE=5,h=o.ENTITY_NODE=6,p=o.PROCESSING_INSTRUCTION_NODE=7,d=o.COMMENT_NODE=8,v=o.DOCUMENT_NODE=9,m=o.DOCUMENT_TYPE_NODE=10,g=o.DOCUMENT_FRAGMENT_NODE=11,y=o.NOTATION_NODE=12,b={},w={},E=b.INDEX_SIZE_ERR=(w[1]=\"Index size error\",1),S=b.DOMSTRING_SIZE_ERR=(w[2]=\"DOMString size error\",2),x=b.HIERARCHY_REQUEST_ERR=(w[3]=\"Hierarchy request error\",3),T=b.WRONG_DOCUMENT_ERR=(w[4]=\"Wrong document\",4),N=b.INVALID_CHARACTER_ERR=(w[5]=\"Invalid character\",5),C=b.NO_DATA_ALLOWED_ERR=(w[6]=\"No data allowed\",6),k=b.NO_MODIFICATION_ALLOWED_ERR=(w[7]=\"No modification allowed\",7),L=b.NOT_FOUND_ERR=(w[8]=\"Not found\",8),A=b.NOT_SUPPORTED_ERR=(w[9]=\"Not supported\",9),O=b.INUSE_ATTRIBUTE_ERR=(w[10]=\"Attribute in use\",10),M=b.INVALID_STATE_ERR=(w[11]=\"Invalid state\",11),_=b.SYNTAX_ERR=(w[12]=\"Syntax error\",12),D=b.INVALID_MODIFICATION_ERR=(w[13]=\"Invalid modification\",13),P=b.NAMESPACE_ERR=(w[14]=\"Invalid namespace\",14),H=b.INVALID_ACCESS_ERR=(w[15]=\"Invalid access\",15);B.prototype=Error.prototype,r(b,B),j.prototype={length:0,item:function(e){return this[e]||null}},F.prototype.item=function(e){return I(this),this[e]},i(F,j),q.prototype={length:0,item:j.prototype.item,getNamedItem:function(e){var t=this.length;while(t--){var n=this[t];if(n.nodeName==e)return n}},setNamedItem:function(e){var t=e.ownerElement;if(t&&t!=this._ownerElement)throw new B(O);var n=this.getNamedItem(e.nodeName);return U(this._ownerElement,this,e,n),n},setNamedItemNS:function(e){var t=e.ownerElement,n;if(t&&t!=this._ownerElement)throw new B(O);return n=this.getNamedItemNS(e.namespaceURI,e.localName),U(this._ownerElement,this,e,n),n},removeNamedItem:function(e){var t=this.getNamedItem(e);return z(this._ownerElement,this,t),t},removeNamedItemNS:function(e,t){var n=this.getNamedItemNS(e,t);return z(this._ownerElement,this,n),n},getNamedItemNS:function(e,t){var n=this.length;while(n--){var r=this[n];if(r.localName==t&&r.namespaceURI==e)return r}return null}},W.prototype={hasFeature:function(e,t){var n=this._features[e.toLowerCase()];return n&&(!t||t in n)?!0:!1},createDocument:function(e,t,n){var r=new J;r.implementation=this,r.childNodes=new j,r.doctype=n,n&&r.appendChild(n);if(t){var i=r.createElementNS(e,t);r.appendChild(i)}return r},createDocumentType:function(e,t,n){var r=new ut;return r.name=e,r.nodeName=e,r.publicId=t,r.systemId=n,r}},X.prototype={firstChild:null,lastChild:null,previousSibling:null,nextSibling:null,attributes:null,parentNode:null,childNodes:null,ownerDocument:null,nodeValue:null,namespaceURI:null,prefix:null,localName:null,insertBefore:function(e,t){return Z(this,e,t)},replaceChild:function(e,t){this.insertBefore(e,t),t&&this.removeChild(t)},removeChild:function(e){return Y(this,e)},appendChild:function(e){return this.insertBefore(e,null)},hasChildNodes:function(){return this.firstChild!=null},cloneNode:function(e){return mt(this.ownerDocument||this,this,e)},normalize:function(){var e=this.firstChild;while(e){var t=e.nextSibling;t&&t.nodeType==f&&e.nodeType==f?(this.removeChild(t),e.appendData(t.data)):(e.normalize(),e=t)}},isSupported:function(e,t){return this.ownerDocument.implementation.hasFeature(e,t)},hasAttributes:function(){return this.attributes.length>0},lookupPrefix:function(e){var t=this;while(t){var n=t._nsMap;if(n)for(var r in n)if(n[r]==e)return r;t=t.nodeType==2?t.ownerDocument:t.parentNode}return null},lookupNamespaceURI:function(e){var t=this;while(t){var n=t._nsMap;if(n&&e in n)return n[e];t=t.nodeType==2?t.ownerDocument:t.parentNode}return null},isDefaultNamespace:function(e){var t=this.lookupPrefix(e);return t==null}},r(o,X),r(o,X.prototype),J.prototype={nodeName:\"#document\",nodeType:v,doctype:null,documentElement:null,_inc:1,insertBefore:function(e,t){if(e.nodeType==g){var n=e.firstChild;while(n){var r=n.nextSibling;this.insertBefore(n,t),n=r}return e}return this.documentElement==null&&e.nodeType==1&&(this.documentElement=e),Z(this,e,t),e.ownerDocument=this,e},removeChild:function(e){return this.documentElement==e&&(this.documentElement=null),Y(this,e)},importNode:function(e,t){return vt(this,e,t)},getElementById:function(e){var t=null;return $(this.documentElement,function(n){if(n.nodeType==1&&n.getAttribute(\"id\")==e)return t=n,!0}),t},createElement:function(e){var t=new tt;t.ownerDocument=this,t.nodeName=e,t.tagName=e,t.childNodes=new j;var n=t.attributes=new q;return n._ownerElement=t,t},createDocumentFragment:function(){var e=new ct;return e.ownerDocument=this,e.childNodes=new j,e},createTextNode:function(e){var t=new it;return t.ownerDocument=this,t.appendData(e),t},createComment:function(e){var t=new st;return t.ownerDocument=this,t.appendData(e),t},createCDATASection:function(e){var t=new ot;return t.ownerDocument=this,t.appendData(e),t},createProcessingInstruction:function(e,t){var n=new ht;return n.ownerDocument=this,n.tagName=n.target=e,n.nodeValue=n.data=t,n},createAttribute:function(e){var t=new nt;return t.ownerDocument=this,t.name=e,t.nodeName=e,t.localName=e,t.specified=!0,t},createEntityReference:function(e){var t=new lt;return t.ownerDocument=this,t.nodeName=e,t},createElementNS:function(e,t){var n=new tt,r=t.split(\":\"),i=n.attributes=new q;return n.childNodes=new j,n.ownerDocument=this,n.nodeName=t,n.tagName=t,n.namespaceURI=e,r.length==2?(n.prefix=r[0],n.localName=r[1]):n.localName=t,i._ownerElement=n,n},createAttributeNS:function(e,t){var n=new nt,r=t.split(\":\");return n.ownerDocument=this,n.nodeName=t,n.name=t,n.namespaceURI=e,n.specified=!0,r.length==2?(n.prefix=r[0],n.localName=r[1]):n.localName=t,n}},i(J,X),tt.prototype={nodeType:u,hasAttribute:function(e){return this.getAttributeNode(e)!=null},getAttribute:function(e){var t=this.getAttributeNode(e);return t&&t.value||\"\"},getAttributeNode:function(e){return this.attributes.getNamedItem(e)},setAttribute:function(e,t){var n=this.ownerDocument.createAttribute(e);n.value=n.nodeValue=\"\"+t,this.setAttributeNode(n)},removeAttribute:function(e){var t=this.getAttributeNode(e);t&&this.removeAttributeNode(t)},appendChild:function(e){return e.nodeType===g?this.insertBefore(e,null):et(this,e)},setAttributeNode:function(e){return this.attributes.setNamedItem(e)},setAttributeNodeNS:function(e){return this.attributes.setNamedItemNS(e)},removeAttributeNode:function(e){return this.attributes.removeNamedItem(e.nodeName)},removeAttributeNS:function(e,t){var n=this.getAttributeNodeNS(e,t);n&&this.removeAttributeNode(n)},hasAttributeNS:function(e,t){return this.getAttributeNodeNS(e,t)!=null},getAttributeNS:function(e,t){var n=this.getAttributeNodeNS(e,t);return n&&n.value||\"\"},setAttributeNS:function(e,t,n){var r=this.ownerDocument.createAttributeNS(e,t);r.value=r.nodeValue=\"\"+n,this.setAttributeNode(r)},getAttributeNodeNS:function(e,t){return this.attributes.getNamedItemNS(e,t)},getElementsByTagName:function(e){return new F(this,function(t){var n=[];return $(t,function(r){r!==t&&r.nodeType==u&&(e===\"*\"||r.tagName==e)&&n.push(r)}),n})},getElementsByTagNameNS:function(e,t){return new F(this,function(n){var r=[];return $(n,function(i){i!==n&&i.nodeType===u&&(e===\"*\"||i.namespaceURI===e)&&(t===\"*\"||i.localName==t)&&r.push(i)}),r})}},J.prototype.getElementsByTagName=tt.prototype.getElementsByTagName,J.prototype.getElementsByTagNameNS=tt.prototype.getElementsByTagNameNS,i(tt,X),nt.prototype.nodeType=a,i(nt,X),rt.prototype={data:\"\",substringData:function(e,t){return this.data.substring(e,e+t)},appendData:function(e){e=this.data+e,this.nodeValue=this.data=e,this.length=e.length},insertData:function(e,t){this.replaceData(e,0,t)},appendChild:function(e){throw new Error(w[3])},deleteData:function(e,t){this.replaceData(e,t,\"\")},replaceData:function(e,t,n){var r=this.data.substring(0,e),i=this.data.substring(e+t);n=r+n+i,this.nodeValue=this.data=n,this.length=n.length}},i(rt,X),it.prototype={nodeName:\"#text\",nodeType:f,splitText:function(e){var t=this.data,n=t.substring(e);t=t.substring(0,e),this.data=this.nodeValue=t,this.length=t.length;var r=this.ownerDocument.createTextNode(n);return this.parentNode&&this.parentNode.insertBefore(r,this.nextSibling),r}},i(it,rt),st.prototype={nodeName:\"#comment\",nodeType:d},i(st,rt),ot.prototype={nodeName:\"#cdata-section\",nodeType:l},i(ot,rt),ut.prototype.nodeType=m,i(ut,X),at.prototype.nodeType=y,i(at,X),ft.prototype.nodeType=h,i(ft,X),lt.prototype.nodeType=c,i(lt,X),ct.prototype.nodeName=\"#document-fragment\",ct.prototype.nodeType=g,i(ct,X),ht.prototype.nodeType=p,i(ht,X),pt.prototype.serializeToString=function(e){var t=[];return dt(e,t),t.join(\"\")},X.prototype.toString=function(){return pt.prototype.serializeToString(this)};try{if(Object.defineProperty){Object.defineProperty(F.prototype,\"length\",{get:function(){return I(this),this.$$length}}),Object.defineProperty(X.prototype,\"textContent\",{get:function(){return yt(this)},set:function(e){switch(this.nodeType){case 1:case 11:while(this.firstChild)this.removeChild(this.firstChild);(e||String(e))&&this.appendChild(this.ownerDocument.createTextNode(e));break;default:this.data=e,this.value=value,this.nodeValue=e}}});function yt(e){switch(e.nodeType){case 1:case 11:var t=[];e=e.firstChild;while(e)e.nodeType!==7&&e.nodeType!==8&&t.push(yt(e)),e=e.nextSibling;return t.join(\"\");default:return e.nodeValue}}gt=function(e,t,n){e[\"$$\"+t]=n}}}catch(bt){}return W}),define(\"ace/mode/xml/dom-parser\",[\"require\",\"exports\",\"module\",\"ace/mode/xml/sax\",\"ace/mode/xml/dom\"],function(e,t,n){\"use strict\";function s(e){this.options=e||{locator:{}}}function o(e,t,n){function s(t){var s=e[t];if(!s)if(i)s=e.length==2?function(n){e(t,n)}:e;else{var o=arguments.length;while(--o)if(s=e[arguments[o]])break}r[t]=s&&function(e){s(e+f(n),e,n)}||function(){}}if(!e){if(t instanceof u)return t;e=t}var r={},i=e instanceof Function;return n=n||{},s(\"warning\",\"warn\"),s(\"error\",\"warn\",\"warning\"),s(\"fatalError\",\"warn\",\"warning\",\"error\"),r}function u(){this.cdata=!1}function a(e,t){t.lineNumber=e.lineNumber,t.columnNumber=e.columnNumber}function f(e){if(e)return\"\\n@\"+(e.systemId||\"\")+\"#[line:\"+e.lineNumber+\",col:\"+e.columnNumber+\"]\"}function l(e,t,n){return typeof e==\"string\"?e.substr(t,n):e.length>=t+n||t?new java.lang.String(e,t,n)+\"\":e}function c(e,t){e.currentElement?e.currentElement.appendChild(t):e.document.appendChild(t)}var r=e(\"./sax\"),i=e(\"./dom\");return s.prototype.parseFromString=function(e,t){var n=this.options,i=new r,s=n.domBuilder||new u,a=n.errorHandler,f=n.locator,l=n.xmlns||{},c={lt:\"<\",gt:\">\",amp:\"&\",quot:'\"',apos:\"'\"};return f&&s.setDocumentLocator(f),i.errorHandler=o(a,s,f),i.domBuilder=n.domBuilder||s,/\\/x?html?$/.test(t)&&(c.nbsp=\"\\u00a0\",c.copy=\"\\u00a9\",l[\"\"]=\"http://www.w3.org/1999/xhtml\"),e?i.parse(e,l,c):i.errorHandler.error(\"invalid document source\"),s.document},u.prototype={startDocument:function(){this.document=(new i).createDocument(null,null,null),this.locator&&(this.document.documentURI=this.locator.systemId)},startElement:function(e,t,n,r){var i=this.document,s=i.createElementNS(e,n||t),o=r.length;c(this,s),this.currentElement=s,this.locator&&a(this.locator,s);for(var u=0;u<o;u++){var e=r.getURI(u),f=r.getValue(u),n=r.getQName(u),l=i.createAttributeNS(e,n);l.getOffset&&a(l.getOffset(1),l),l.value=l.nodeValue=f,s.setAttributeNode(l)}},endElement:function(e,t,n){var r=this.currentElement,i=r.tagName;this.currentElement=r.parentNode},startPrefixMapping:function(e,t){},endPrefixMapping:function(e){},processingInstruction:function(e,t){var n=this.document.createProcessingInstruction(e,t);this.locator&&a(this.locator,n),c(this,n)},ignorableWhitespace:function(e,t,n){},characters:function(e,t,n){e=l.apply(this,arguments);if(this.currentElement&&e){if(this.cdata){var r=this.document.createCDATASection(e);this.currentElement.appendChild(r)}else{var r=this.document.createTextNode(e);this.currentElement.appendChild(r)}this.locator&&a(this.locator,r)}},skippedEntity:function(e){},endDocument:function(){this.document.normalize()},setDocumentLocator:function(e){if(this.locator=e)e.lineNumber=0},comment:function(e,t,n){e=l.apply(this,arguments);var r=this.document.createComment(e);this.locator&&a(this.locator,r),c(this,r)},startCDATA:function(){this.cdata=!0},endCDATA:function(){this.cdata=!1},startDTD:function(e,t,n){var r=this.document.implementation;if(r&&r.createDocumentType){var i=r.createDocumentType(e,t,n);this.locator&&a(this.locator,i),c(this,i)}},warning:function(e){console.warn(e,f(this.locator))},error:function(e){console.error(e,f(this.locator))},fatalError:function(e){throw console.error(e,f(this.locator)),e}},\"endDTD,startEntity,endEntity,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,resolveEntity,getExternalSubset,notationDecl,unparsedEntityDecl\".replace(/\\w+/g,function(e){u.prototype[e]=function(){return null}}),{DOMParser:s}}),define(\"ace/mode/xml_worker\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/lang\",\"ace/worker/mirror\",\"ace/mode/xml/dom-parser\"],function(e,t,n){\"use strict\";var r=e(\"../lib/oop\"),i=e(\"../lib/lang\"),s=e(\"../worker/mirror\").Mirror,o=e(\"./xml/dom-parser\").DOMParser,u=t.Worker=function(e){s.call(this,e),this.setTimeout(400),this.context=null};r.inherits(u,s),function(){this.setOptions=function(e){this.context=e.context},this.onUpdate=function(){var e=this.doc.getValue();if(!e)return;var t=new o,n=[];t.options.errorHandler={fatalError:function(e,t,r){n.push({row:r.lineNumber,column:r.columnNumber,text:t,type:\"error\"})},error:function(e,t,r){n.push({row:r.lineNumber,column:r.columnNumber,text:t,type:\"error\"})},warning:function(e,t,r){n.push({row:r.lineNumber,column:r.columnNumber,text:t,type:\"warning\"})}},t.parseFromString(e),this.sender.emit(\"error\",n)}}.call(u.prototype)}),define(\"ace/lib/es5-shim\",[\"require\",\"exports\",\"module\"],function(e,t,n){function r(){}function w(e){try{return Object.defineProperty(e,\"sentinel\",{}),\"sentinel\"in e}catch(t){}}function H(e){return e=+e,e!==e?e=0:e!==0&&e!==1/0&&e!==-1/0&&(e=(e>0||-1)*Math.floor(Math.abs(e))),e}function B(e){var t=typeof e;return e===null||t===\"undefined\"||t===\"boolean\"||t===\"number\"||t===\"string\"}function j(e){var t,n,r;if(B(e))return e;n=e.valueOf;if(typeof n==\"function\"){t=n.call(e);if(B(t))return t}r=e.toString;if(typeof r==\"function\"){t=r.call(e);if(B(t))return t}throw new TypeError}Function.prototype.bind||(Function.prototype.bind=function(t){var n=this;if(typeof n!=\"function\")throw new TypeError(\"Function.prototype.bind called on incompatible \"+n);var i=u.call(arguments,1),s=function(){if(this instanceof s){var e=n.apply(this,i.concat(u.call(arguments)));return Object(e)===e?e:this}return n.apply(t,i.concat(u.call(arguments)))};return n.prototype&&(r.prototype=n.prototype,s.prototype=new r,r.prototype=null),s});var i=Function.prototype.call,s=Array.prototype,o=Object.prototype,u=s.slice,a=i.bind(o.toString),f=i.bind(o.hasOwnProperty),l,c,h,p,d;if(d=f(o,\"__defineGetter__\"))l=i.bind(o.__defineGetter__),c=i.bind(o.__defineSetter__),h=i.bind(o.__lookupGetter__),p=i.bind(o.__lookupSetter__);if([1,2].splice(0).length!=2)if(!function(){function e(e){var t=new Array(e+2);return t[0]=t[1]=0,t}var t=[],n;t.splice.apply(t,e(20)),t.splice.apply(t,e(26)),n=t.length,t.splice(5,0,\"XXX\"),n+1==t.length;if(n+1==t.length)return!0}())Array.prototype.splice=function(e,t){var n=this.length;e>0?e>n&&(e=n):e==void 0?e=0:e<0&&(e=Math.max(n+e,0)),e+t<n||(t=n-e);var r=this.slice(e,e+t),i=u.call(arguments,2),s=i.length;if(e===n)s&&this.push.apply(this,i);else{var o=Math.min(t,n-e),a=e+o,f=a+s-o,l=n-a,c=n-o;if(f<a)for(var h=0;h<l;++h)this[f+h]=this[a+h];else if(f>a)for(h=l;h--;)this[f+h]=this[a+h];if(s&&e===c)this.length=c,this.push.apply(this,i);else{this.length=c+s;for(h=0;h<s;++h)this[e+h]=i[h]}}return r};else{var v=Array.prototype.splice;Array.prototype.splice=function(e,t){return arguments.length?v.apply(this,[e===void 0?0:e,t===void 0?this.length-e:t].concat(u.call(arguments,2))):[]}}Array.isArray||(Array.isArray=function(t){return a(t)==\"[object Array]\"});var m=Object(\"a\"),g=m[0]!=\"a\"||!(0 in m);Array.prototype.forEach||(Array.prototype.forEach=function(t){var n=F(this),r=g&&a(this)==\"[object String]\"?this.split(\"\"):n,i=arguments[1],s=-1,o=r.length>>>0;if(a(t)!=\"[object Function]\")throw new TypeError;while(++s<o)s in r&&t.call(i,r[s],s,n)}),Array.prototype.map||(Array.prototype.map=function(t){var n=F(this),r=g&&a(this)==\"[object String]\"?this.split(\"\"):n,i=r.length>>>0,s=Array(i),o=arguments[1];if(a(t)!=\"[object Function]\")throw new TypeError(t+\" is not a function\");for(var u=0;u<i;u++)u in r&&(s[u]=t.call(o,r[u],u,n));return s}),Array.prototype.filter||(Array.prototype.filter=function(t){var n=F(this),r=g&&a(this)==\"[object String]\"?this.split(\"\"):n,i=r.length>>>0,s=[],o,u=arguments[1];if(a(t)!=\"[object Function]\")throw new TypeError(t+\" is not a function\");for(var f=0;f<i;f++)f in r&&(o=r[f],t.call(u,o,f,n)&&s.push(o));return s}),Array.prototype.every||(Array.prototype.every=function(t){var n=F(this),r=g&&a(this)==\"[object String]\"?this.split(\"\"):n,i=r.length>>>0,s=arguments[1];if(a(t)!=\"[object Function]\")throw new TypeError(t+\" is not a function\");for(var o=0;o<i;o++)if(o in r&&!t.call(s,r[o],o,n))return!1;return!0}),Array.prototype.some||(Array.prototype.some=function(t){var n=F(this),r=g&&a(this)==\"[object String]\"?this.split(\"\"):n,i=r.length>>>0,s=arguments[1];if(a(t)!=\"[object Function]\")throw new TypeError(t+\" is not a function\");for(var o=0;o<i;o++)if(o in r&&t.call(s,r[o],o,n))return!0;return!1}),Array.prototype.reduce||(Array.prototype.reduce=function(t){var n=F(this),r=g&&a(this)==\"[object String]\"?this.split(\"\"):n,i=r.length>>>0;if(a(t)!=\"[object Function]\")throw new TypeError(t+\" is not a function\");if(!i&&arguments.length==1)throw new TypeError(\"reduce of empty array with no initial value\");var s=0,o;if(arguments.length>=2)o=arguments[1];else do{if(s in r){o=r[s++];break}if(++s>=i)throw new TypeError(\"reduce of empty array with no initial value\")}while(!0);for(;s<i;s++)s in r&&(o=t.call(void 0,o,r[s],s,n));return o}),Array.prototype.reduceRight||(Array.prototype.reduceRight=function(t){var n=F(this),r=g&&a(this)==\"[object String]\"?this.split(\"\"):n,i=r.length>>>0;if(a(t)!=\"[object Function]\")throw new TypeError(t+\" is not a function\");if(!i&&arguments.length==1)throw new TypeError(\"reduceRight of empty array with no initial value\");var s,o=i-1;if(arguments.length>=2)s=arguments[1];else do{if(o in r){s=r[o--];break}if(--o<0)throw new TypeError(\"reduceRight of empty array with no initial value\")}while(!0);do o in this&&(s=t.call(void 0,s,r[o],o,n));while(o--);return s});if(!Array.prototype.indexOf||[0,1].indexOf(1,2)!=-1)Array.prototype.indexOf=function(t){var n=g&&a(this)==\"[object String]\"?this.split(\"\"):F(this),r=n.length>>>0;if(!r)return-1;var i=0;arguments.length>1&&(i=H(arguments[1])),i=i>=0?i:Math.max(0,r+i);for(;i<r;i++)if(i in n&&n[i]===t)return i;return-1};if(!Array.prototype.lastIndexOf||[0,1].lastIndexOf(0,-3)!=-1)Array.prototype.lastIndexOf=function(t){var n=g&&a(this)==\"[object String]\"?this.split(\"\"):F(this),r=n.length>>>0;if(!r)return-1;var i=r-1;arguments.length>1&&(i=Math.min(i,H(arguments[1]))),i=i>=0?i:r-Math.abs(i);for(;i>=0;i--)if(i in n&&t===n[i])return i;return-1};Object.getPrototypeOf||(Object.getPrototypeOf=function(t){return t.__proto__||(t.constructor?t.constructor.prototype:o)});if(!Object.getOwnPropertyDescriptor){var y=\"Object.getOwnPropertyDescriptor called on a non-object: \";Object.getOwnPropertyDescriptor=function(t,n){if(typeof t!=\"object\"&&typeof t!=\"function\"||t===null)throw new TypeError(y+t);if(!f(t,n))return;var r,i,s;r={enumerable:!0,configurable:!0};if(d){var u=t.__proto__;t.__proto__=o;var i=h(t,n),s=p(t,n);t.__proto__=u;if(i||s)return i&&(r.get=i),s&&(r.set=s),r}return r.value=t[n],r}}Object.getOwnPropertyNames||(Object.getOwnPropertyNames=function(t){return Object.keys(t)});if(!Object.create){var b;Object.prototype.__proto__===null?b=function(){return{__proto__:null}}:b=function(){var e={};for(var t in e)e[t]=null;return e.constructor=e.hasOwnProperty=e.propertyIsEnumerable=e.isPrototypeOf=e.toLocaleString=e.toString=e.valueOf=e.__proto__=null,e},Object.create=function(t,n){var r;if(t===null)r=b();else{if(typeof t!=\"object\")throw new TypeError(\"typeof prototype[\"+typeof t+\"] != 'object'\");var i=function(){};i.prototype=t,r=new i,r.__proto__=t}return n!==void 0&&Object.defineProperties(r,n),r}}if(Object.defineProperty){var E=w({}),S=typeof document==\"undefined\"||w(document.createElement(\"div\"));if(!E||!S)var x=Object.defineProperty}if(!Object.defineProperty||x){var T=\"Property description must be an object: \",N=\"Object.defineProperty called on non-object: \",C=\"getters & setters can not be defined on this javascript engine\";Object.defineProperty=function(t,n,r){if(typeof t!=\"object\"&&typeof t!=\"function\"||t===null)throw new TypeError(N+t);if(typeof r!=\"object\"&&typeof r!=\"function\"||r===null)throw new TypeError(T+r);if(x)try{return x.call(Object,t,n,r)}catch(i){}if(f(r,\"value\"))if(d&&(h(t,n)||p(t,n))){var s=t.__proto__;t.__proto__=o,delete t[n],t[n]=r.value,t.__proto__=s}else t[n]=r.value;else{if(!d)throw new TypeError(C);f(r,\"get\")&&l(t,n,r.get),f(r,\"set\")&&c(t,n,r.set)}return t}}Object.defineProperties||(Object.defineProperties=function(t,n){for(var r in n)f(n,r)&&Object.defineProperty(t,r,n[r]);return t}),Object.seal||(Object.seal=function(t){return t}),Object.freeze||(Object.freeze=function(t){return t});try{Object.freeze(function(){})}catch(k){Object.freeze=function(t){return function(n){return typeof n==\"function\"?n:t(n)}}(Object.freeze)}Object.preventExtensions||(Object.preventExtensions=function(t){return t}),Object.isSealed||(Object.isSealed=function(t){return!1}),Object.isFrozen||(Object.isFrozen=function(t){return!1}),Object.isExtensible||(Object.isExtensible=function(t){if(Object(t)===t)throw new TypeError;var n=\"\";while(f(t,n))n+=\"?\";t[n]=!0;var r=f(t,n);return delete t[n],r});if(!Object.keys){var L=!0,A=[\"toString\",\"toLocaleString\",\"valueOf\",\"hasOwnProperty\",\"isPrototypeOf\",\"propertyIsEnumerable\",\"constructor\"],O=A.length;for(var M in{toString:null})L=!1;Object.keys=function I(e){if(typeof e!=\"object\"&&typeof e!=\"function\"||e===null)throw new TypeError(\"Object.keys called on a non-object\");var I=[];for(var t in e)f(e,t)&&I.push(t);if(L)for(var n=0,r=O;n<r;n++){var i=A[n];f(e,i)&&I.push(i)}return I}}Date.now||(Date.now=function(){return(new Date).getTime()});var _=\"\t\\n\u000b\\f\\r \\u00a0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029\\ufeff\";if(!String.prototype.trim||_.trim()){_=\"[\"+_+\"]\";var D=new RegExp(\"^\"+_+_+\"*\"),P=new RegExp(_+_+\"*$\");String.prototype.trim=function(){return String(this).replace(D,\"\").replace(P,\"\")}}var F=function(e){if(e==null)throw new TypeError(\"can't convert \"+e+\" to object\");return Object(e)}})\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/views/common/footer.html",
    "content": ""
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/views/common/nav.html",
    "content": "<nav class=\"navbar navbar-default\">\n    <div class=\"container-fluid\">\n        <div class=\"navbar-header\">\n            <img class=\"navbar-brand side-bar-switch cursor-pointer\" src=\"../../img/show_sidebar.png\"\n                 onMouseOver=\"this.style.background='#f1f2f7'\"\n                 onMouseOut=\"this.style.background='#fff'\"\n                 data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"显示导航栏\"\n                 ng-show=\"viewMode == 2 && !showSideBar\"\n                 ng-click=\"showSideBar = !showSideBar\">\n            <img class=\"navbar-brand side-bar-switch cursor-pointer\" src=\"../../img/hide_sidebar.png\"\n                 onMouseOver=\"this.style.background='#f1f2f7'\"\n                 onMouseOut=\"this.style.background='#fff'\"\n                 data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"隐藏导航栏\"\n                 ng-show=\"viewMode == 2 && showSideBar\"\n                 ng-click=\"showSideBar = !showSideBar\">\n            <a class=\"navbar-brand logo\" href=\"/\">\n                <b>配置中心</b>\n            </a>\n        </div>\n        <div class=\"collapse navbar-collapse\" id=\"bs-example-navbar-collapse-1\">\n\n            <ul class=\"nav navbar-nav navbar-right\">\n                <li>\n                    <a href=\"{{pageSetting.wikiAddress}}\" target=\"_blank\">\n                        <span class=\"glyphicon glyphicon-question-sign\"></span> 帮助\n                    </a>\n                </li>\n\n            </ul>\n\n            <div class=\"navbar-form navbar-right form-inline\" role=\"search\">\n                <div class=\"form-group\">\n                    <input type=\"text\" class=\"form-control search-input\" placeholder=\"搜索项目(AppId、项目名)\"\n                           style=\"width: 350px\"\n                           ng-model=\"searchKey\" ng-change=\"changeSearchKey()\" ng-focus=\"changeSearchKey()\">\n\n                    <div class=\"row app-list\" ng-show=\"shouldShowAppList\">\n                        <div ng-repeat=\"app in copyedApps\" class=\"app-item\" ng-class=\"{'app-selected':app.selected}\"\n                             ng-click=\"selectApp(app)\">{{app.appId}} / {{app.name}}\n                        </div>\n                    </div>\n                </div>\n            </div>\n\n        </div>\n    </div>\n</nav>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/views/component/confirm-dialog.html",
    "content": "<div class=\"modal fade\" id=\"{{dialogId}}\" tabindex=\"-1\" role=\"dialog\">\n    <div class=\"modal-dialog\" role=\"document\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header panel-primary\">\n                <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\"><span\n                        aria-hidden=\"true\">&times;</span></button>\n                <h4 class=\"modal-title\">{{title}}</h4>\n            </div>\n            <div class=\"modal-body\" ng-bind-html=\"detailAsHtml\">\n            </div>\n            <div class=\"modal-footer\">\n                <button type=\"button\" class=\"btn btn-default\" data-dismiss=\"modal\"\n                        ng-show=\"showCancelBtn\" ng-click=\"cancel()\">取消</button>\n                <button type=\"button\" class=\"btn btn-danger\" data-dismiss=\"modal\"\n                        ng-click=\"confirm()\">\n                    {{confirmBtnText}}\n                </button>\n            </div>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/views/component/delete-namespace-modal.html",
    "content": "<div id=\"deleteNamespaceModal\" class=\"modal fade\">\n    <div class=\"modal-dialog\" role=\"document\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header panel-primary\">\n                <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\"><span\n                        aria-hidden=\"true\">&times;</span></button>\n                <h4 class=\"modal-title\">\n                    删除Namespace\n                </h4>\n            </div>\n            <div class=\"modal-body form-horizontal\">\n                删除Namespace将导致实例获取不到此Namespace的配置，确定要删除吗?\n            </div>\n            <div class=\"modal-footer\">\n                <button type=\"button\" class=\"btn btn-default\" data-dismiss=\"modal\">\n                    取消\n                </button>\n                <button type=\"button\" class=\"btn btn-danger\" data-dismiss=\"modal\"\n                ng-click=\"doDeleteNamespace()\">\n                    确认\n                </button>\n            </div>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/views/component/diff.html",
    "content": "<pre class=\"no-radius\" id=\"{{apolloId}}\">\n\n</pre>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/views/component/entrance.html",
    "content": "<a class=\"list-group-item hover\" href=\"{{href}}\">\n    <div class=\"row icon-text icon-{{imgSrc}}\">\n        <p class=\"btn-title\">{{title}}</p>\n    </div>\n</a>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/views/component/env-selector.html",
    "content": "<table class=\"table table-hover\" style=\"width: 250px\">\n    <thead>\n    <tr>\n        <td><input type=\"checkbox\" ng-checked=\"envAllSelected\" ng-click=\"toggleEnvsCheckedStatus()\"></td>\n        </td>\n        <td>环境</td>\n        <td>集群</td>\n    </tr>\n    </thead>\n    <tbody>\n    <tr style=\"cursor: pointer\" ng-repeat=\"cluster in clusters\" ng-click=\"toggleClusterCheckedStatus(cluster)\">\n        <td width=\"10%\"><input type=\"checkbox\" ng-checked=\"cluster.checked\"\n                               ng-click=\"switchSelect(cluster, $event)\"></td>\n        <td width=\"30%\" ng-bind=\"cluster.env\"></td>\n        <td width=\"60%\" ng-bind=\"cluster.name\"></td>\n    </tr>\n    </tbody>\n</table>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/views/component/gray-release-rules-modal.html",
    "content": "<form id=\"rulesModal\" class=\"modal fade\" role=\"dialog\" aria-hidden=\"true\">\n    <div class=\"modal-dialog\" role=\"document\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header panel-primary\">\n                <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\"><span\n                        aria-hidden=\"true\">&times;</span>\n                </button>\n                <h4 class=\"modal-title\">\n                    编辑灰度规则\n                </h4>\n            </div>\n            <div class=\"modal-body form-horizontal\">\n                <div class=\"form-group\"\n                     ng-show=\"branch.parentNamespace.isPublic && !branch.parentNamespace.isLinkedNamespace\">\n                    <label class=\"control-label col-md-3 text-right\">\n                        <apollorequiredfield></apollorequiredfield>\n                        灰度的AppId</label>\n                    <div class=\"col-md-4\">\n                        <input type=\"text\" class=\"form-control\"\n                               ng-model=\"branch.editingRuleItem.clientAppId\"\n                               ng-model-options='{ debounce: 300 }'\n                               ng-change='initSelectIps()'\n                        >\n                    </div>\n                </div>\n                <div class=\"form-group\"\n                     ng-show=\"branch.parentNamespace.isPublic && !branch.parentNamespace.isLinkedNamespace\">\n                    <label class=\"control-label col-md-3 text-right\">灰度应用规则</label>\n                    <div class=\"col-md-9\">\n                        <label class=\"form-control-static radio-inline\">\n                            <input type=\"radio\" name=\"ApplyToAllInstances\" value=\"false\"\n                                   ng-checked=\"!branch.editingRuleItem.ApplyToAllInstances\"\n                                   ng-click=\"branch.editingRuleItem.ApplyToAllInstances = false\">\n                            应用到部分实例\n                        </label>\n                        <label class=\"form-control-static radio-inline\">\n                            <input type=\"radio\" name=\"ApplyToAllInstances\" value=\"true\"\n                                   ng-checked=\"branch.editingRuleItem.ApplyToAllInstances\"\n                                   ng-click=\"branch.editingRuleItem.ApplyToAllInstances = true\">\n                            应用到所有的实例\n                        </label>\n                    </div>\n                </div>\n                <div class=\"form-group\" ng-show=\"!branch.editingRuleItem.ApplyToAllInstances\">\n                    <label class=\"control-label col-md-3 text-right\">\n                        <apollorequiredfield></apollorequiredfield>\n                        灰度的IP</label>\n                    <div class=\"col-md-9\">\n                        <div class=\"form-inline\">\n                            <div class=\"form-group\">\n                                <select class=\"rules-ip-selector\" multiple=\"multiple\">\n                                    <option ng-repeat=\"instance in selectIps\"\n                                            ng-bind=\"instance.ip\">\n                                    </option>\n                                </select>\n                                <div ng-show=\"branch.parentNamespace.isPublic && !branch.parentNamespace.isLinkedNamespace\">\n                                    <small>(实例列表会根据输入的AppId自动过滤)</small>\n                                </div>\n                                <div style=\"margin-top: 5px\">\n                                    <small>没找到你想要的IP？可以<a ng-click=\"manual =! manual\">手动输入IP</a></small>\n                                </div>\n                            </div>\n                        </div>\n                        <div class=\"form-inline\" ng-show=\"manual\">\n                            <div class=\"form-group\">\n                                    <textarea class=\"form-control\" ng-model=\"toAddIPs\" rows=\"3\"\n                                              placeholder=\"输入IP列表，英文逗号隔开，输入完后点击添加按钮\"></textarea>\n                            </div>\n                            <button class=\"btn-default btn add-rule\"\n                                    ng-click=\"batchAddIPs(branch, toAddIPs)\">\n                                添加\n                            </button>\n                        </div>\n                    </div>\n                </div>\n\n\n                <div class=\"form-group\" ng-show=\"!branch.editingRuleItem.ApplyToAllInstances\">\n                    <div class=\"col-md-offset-1 col-md-10 item-container\">\n                        <section class=\"btn-group item-info\"\n                                 ng-repeat=\"ip in branch.editingRuleItem.draftIpList\">\n                            <button type=\"button\" class=\"btn btn-default\" ng-bind=\"ip\"></button>\n                            <button type=\"button\" class=\"btn btn-default dropdown-toggle\"\n                                    data-toggle=\"dropdown\"\n                                    ng-click=\"removeRule(branch.editingRuleItem, ip)\">\n                                <span class=\"glyphicon glyphicon-remove\"></span>\n                            </button>\n                        </section>\n                    </div>\n                </div>\n\n            </div>\n            <div class=\"modal-footer\">\n                <button class=\"btn btn-default\" ng-click=\"cancelEditItem(branch)\">取消</button>\n                <button class=\"btn btn-primary\" ng-disabled=\"completeEditBtnDisable\"\n                        ng-click=\"completeEditItem(branch)\">完成\n                </button>\n            </div>\n        </div>\n    </div>\n\n\n</form>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/views/component/item-modal.html",
    "content": "<form id=\"itemModal\" class=\"modal fade\" valdr-type=\"Item\" name=\"itemForm\"\n      ng-submit=\"doItem()\">\n    <div class=\"modal-dialog\" role=\"document\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header panel-primary\">\n                <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\"><span\n                        aria-hidden=\"true\">&times;</span></button>\n                <h4 class=\"modal-title\">\n                    <span ng-show=\"item.tableViewOperType == 'create' && !toOperationNamespace.isBranch\">\n                        添加配置项 <small class=\"text-info\">(温馨提示: 可以通过文本模式批量添加配置)</small>\n                    </span>\n                    <span ng-show=\"item.tableViewOperType == 'create' && toOperationNamespace.isBranch\"> 添加灰度配置项</span>\n                    <span ng-show=\"item.tableViewOperType == 'update'\"> 修改配置项</span>\n                </h4>\n            </div>\n            <div class=\"modal-body form-horizontal\">\n                <div class=\"form-group\">\n                    <label class=\"col-sm-2 control-label\">\n                        <apollorequiredfield\n                                ng-show=\"item.tableViewOperType == 'create'\"></apollorequiredfield>\n                        Key\n                    </label>\n                    <div class=\"col-sm-10\" valdr-form-group>\n                        <input type=\"text\" name=\"key\" class=\"form-control\" ng-model=\"item.key\" tabindex=\"1\"\n                               ng-required=\"true\" ng-disabled=\"item.tableViewOperType != 'create'\"/>\n                    </div>\n                </div>\n                <div class=\"form-group\">\n                    <label class=\"col-sm-2 control-label\">\n                        <apollorequiredfield></apollorequiredfield>\n                        Value\n                    </label>\n                    <div class=\"col-sm-10\" valdr-form-group>\n                        <textarea name=\"value\" class=\"form-control\" rows=\"6\" tabindex=\"2\"\n                                  ng-required=\"true\"\n                                  ng-model=\"item.value\">\n                            </textarea>\n                        注意: 隐藏字符(空格、换行符、制表符Tab)容易导致配置出错，如果需要检测Value中隐藏字符请点击 <a ng-click=\"showHiddenChars()\">检测隐藏字符</a>\n                        <br>\n                        <div class=\"bg-info\" ng-show=\"showHiddenCharsContext && hiddenCharCounter == 0\">无隐藏字符</div>\n                        <div class=\"bg-info\" ng-bind-html=\"valueWithHiddenChars\" ng-show=\"showHiddenCharsContext && hiddenCharCounter > 0\"></div>\n                    </div>\n\n\n                </div>\n                <div class=\"form-group\">\n                    <label class=\"col-sm-2 control-label\">Comment</label>\n                    <div class=\"col-sm-10\" valdr-form-group>\n                        <textarea class=\"form-control\" name=\"comment\" ng-model=\"item.comment\" tabindex=\"3\"\n                                  rows=\"2\">\n                        </textarea>\n                    </div>\n                </div>\n                <div class=\"form-group\"\n                     ng-show=\"item.tableViewOperType == 'create' && !toOperationNamespace.isBranch\">\n                    <label class=\"col-sm-2 control-label\">\n                        <apollorequiredfield></apollorequiredfield>\n                        选择集群</label>\n                    <div class=\"col-sm-10\">\n                        <apolloclusterselector apollo-app-id=\"appId\"\n                                               apollo-default-all-checked=\"false\"\n                                               apollo-default-checked-env=\"env\"\n                                               apollo-default-checked-cluster=\"cluster\"\n                                               apollo-select=\"collectSelectedClusters\">\n\n                        </apolloclusterselector>\n                    </div>\n                </div>\n            </div>\n            <div class=\"modal-footer\">\n                <button type=\"button\" class=\"btn btn-default\" data-dismiss=\"modal\">\n                    取消\n                </button>\n                <button type=\"submit\" class=\"btn btn-primary\"\n                        ng-disabled=\"itemForm.$invalid || (item.addItemBtnDisabled && item.tableViewOperType == 'create')\">\n                    提交\n                </button>\n            </div>\n        </div>\n    </div>\n</form>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/views/component/merge-and-publish-modal.html",
    "content": "<div class=\"modal fade\" id=\"mergeAndPublishModal\" tabindex=\"-1\" role=\"dialog\">\n    <div class=\"modal-dialog\" role=\"document\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header panel-primary\">\n                <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\"><span\n                        aria-hidden=\"true\">&times;</span></button>\n                <h4 class=\"modal-title\">全量发布</h4>\n            </div>\n            <div class=\"modal-body\">\n                全量发布将会把灰度版本的配置合并到主分支，并发布。\n                <br>\n                <h5>全量发布后,您希望</h5>\n                <div class=\"radio\">\n                    <label ng-click=\"toReleaseNamespace.mergeAfterDeleteBranch = 'true'\">\n                        <input type=\"radio\" name=\"deleteBranch\"\n                               ng-checked=\"!toReleaseNamespace.mergeAfterDeleteBranch ||\n                                           toReleaseNamespace.mergeAfterDeleteBranch == 'true'\">\n                        删除灰度版本\n                    </label>\n                </div>\n                <div class=\"radio\">\n                    <label ng-click=\"toReleaseNamespace.mergeAfterDeleteBranch = 'false'\">\n                        <input type=\"radio\" name=\"deleteBranch\"\n                               ng-checked=\"toReleaseNamespace.mergeAfterDeleteBranch == 'false'\">\n                        保留灰度版本\n                    </label>\n                </div>\n            </div>\n            <div class=\"modal-footer\">\n                <button type=\"button\" class=\"btn btn-default\" data-dismiss=\"modal\">取消</button>\n                <button type=\"button\" class=\"btn btn-primary\" data-dismiss=\"modal\"\n                        ng-click=\"showReleaseModal()\">\n                    确定\n                </button>\n            </div>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/views/component/multiple-user-selector.html",
    "content": "<select class=\"{{id}}\" style=\"width: 450px;\" multiple=\"multiple\">\n</select>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/views/component/namespace-panel-branch-tab.html",
    "content": "<section class=\"branch-panel-body\"\n         ng-if=\"namespace.hasBranch && namespace.displayControl.currentOperateBranch != 'master'\">\n    <!--main header-->\n    <header class=\"panel-heading\">\n\n        <div class=\"row\">\n            <div class=\"col-md-6 col-sm-6 header-namespace\">\n                <span class=\"cursor-pointer\"\n                      data-toggle=\"collapse\" data-target=\"#BODY{{namespace.branch.id}}\" aria-expanded=\"false\"\n                      ng-click=\"namespace.branch.displayControl.show = !namespace.branch.displayControl.show\">\n                    <span class=\"glyphicon glyphicon-triangle-bottom small\"\n                          ng-show=\"namespace.branch.displayControl.show\"></span>\n                    <span class=\"glyphicon glyphicon-triangle-top small\"\n                          ng-show=\"!namespace.branch.displayControl.show\"></span>\n                    <b class=\"namespace-name\" ng-bind=\"namespace.viewName\"\n                       data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"点击展开/收缩Namespace\"></b>\n                    </span>\n                <span class=\"label label-info no-radius namespace-label\" ng-bind=\"namespace.format\"></span>\n                    <span class=\"label label-warning no-radius namespace-label\"\n                          ng-show=\"namespace.branch.itemModifiedCnt > 0\">有修改\n                    <span class=\"badge label badge-white namespace-label\"\n                          ng-bind=\"namespace.branch.itemModifiedCnt\"></span>\n                </span>\n                    <span class=\"label label-primary no-radius namespace-label\"\n                          ng-show=\"namespace.branch.lockOwner\">当前修改者:\n                            <span ng-bind=\"namespace.branch.lockOwner\"></span>\n                    </span>\n            </div>\n\n            <div class=\"col-md-6 col-sm-6 text-right header-buttons\">\n                <a type=\"button\" class=\"btn btn-success btn-sm\"\n                   data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"继续灰度发布\"\n                   ng-show=\"(namespace.hasReleasePermission || namespace.hasModifyPermission)\"\n                   ng-click=\"publish(namespace.branch)\">\n                    灰度发布\n                </a>\n                <a type=\"button\" class=\"btn btn-primary btn-sm\"\n                   data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"合并到主版本并发布主版本配置\"\n                   ng-show=\"(namespace.hasReleasePermission || namespace.hasModifyPermission)\"\n                   ng-click=\"mergeAndPublish(namespace.branch)\">\n                    全量发布\n                </a>\n                <a type=\"button\" class=\"btn btn-warning btn-sm\"\n                   data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"废弃灰度版本\"\n                   ng-show=\"(namespace.hasReleasePermission\n                       || (!namespace.branch.latestRelease && namespace.hasModifyPermission))\"\n                   ng-click=\"preDeleteBranch(namespace.branch)\">\n                    放弃灰度\n                </a>\n            </div>\n        </div>\n\n    </header>\n\n    <div id=\"BODY{{namespace.branch.id}}\" class=\"collapse in\">\n        <!--second header-->\n        <header class=\"panel-heading second-panel-heading\">\n            <div class=\"row\">\n                <div class=\"col-md-12 pull-left\">\n                    <ul class=\"nav nav-tabs\">\n                        <li role=\"presentation\" ng-click=\"switchView(namespace.branch, 'table')\"\n                            ng-show=\"namespace.isPropertiesFormat\">\n                            <a ng-class=\"{node_active:namespace.branch.viewType == 'table'}\">\n                                <img src=\"img/table.png\">\n                                配置\n                            </a>\n                        </li>\n                        <li role=\"presentation\" ng-click=\"switchView(namespace.branch, 'rule')\">\n                            <a ng-class=\"{node_active:namespace.branch.viewType == 'rule'}\">\n                                <img src=\"img/rule.png\">\n                                灰度规则\n                                <span class=\"badge badge-grey\"\n                                      ng-bind=\"namespace.branch.grayIps.length + namespace.branch.grayApps.length\"></span>\n                            </a>\n                        </li>\n                        <li role=\"presentation\" ng-click=\"switchView(namespace.branch, 'instance')\">\n                            <a ng-class=\"{node_active:namespace.branch.viewType == 'instance'}\">\n                                <img src=\"img/machine.png\">\n                                灰度实例列表\n                                <span class=\"badge badge-grey\"\n                                      ng-bind=\"namespace.branch.latestReleaseInstances.total\"></span>\n                            </a>\n                        </li>\n                        <li role=\"presentation\" ng-click=\"switchView(namespace.branch, 'history')\">\n                            <a ng-class=\"{node_active:namespace.branch.viewType == 'history'}\">\n                                <img src=\"img/change.png\">\n                                更改历史\n                            </a>\n                        </li>\n                    </ul>\n                </div>\n            </div>\n        </header>\n        <!--namespace body-->\n        <section>\n            <!--items-->\n            <div class=\"namespace-view-table\" ng-show=\"namespace.branch.viewType == 'table'\">\n\n                <div class=\"panel panel-default\" ng-if=\"namespace.hasBranch\">\n                    <div class=\"panel-heading\">\n                        灰度的配置\n                        <button type=\"button\" class=\"btn btn-primary btn-sm pull-right\" style=\"margin-top: -4px;\"\n                                ng-show=\"namespace.hasModifyPermission\"\n                                ng-click=\"createItem(namespace.branch)\">\n                            <img src=\"img/plus.png\">\n                            新增灰度配置\n                        </button>\n                    </div>\n                    <table class=\"table table-bordered table-striped table-hover\">\n                        <thead>\n                        <tr>\n                            <th>发布状态</th>\n                            <th class=\"hover\" title=\"排序\"\n                                ng-click=\"col='item.key';desc=!desc;\">\n                                Key&nbsp;\n                                <span class=\"glyphicon glyphicon-sort\"></span>\n\n                            </th>\n                            <th>\n                                主版本的值\n                            </th>\n                            <th>\n                                灰度的值\n                            </th>\n                            <th>\n                                备注\n                            </th>\n                            <th class=\"hover\" title=\"排序\"\n                                ng-click=\"col='item.dataChangeLastModifiedBy';desc=!desc;\">\n                                最后修改人\n                                <span class=\"glyphicon glyphicon-sort\"></span>\n\n                            </th>\n                            <th class=\"hover\" title=\"排序\"\n                                ng-click=\"col='item.dataChangeLastModifiedTime';desc=!desc;\">\n                                最后修改时间\n                                <span class=\"glyphicon glyphicon-sort\"></span>\n                            </th>\n                            <th>\n                                操作\n                            </th>\n                        </tr>\n                        </thead>\n                        <tbody>\n\n                        <tr ng-repeat=\"config in namespace.branch.branchItems |orderBy:col:desc\"\n                            ng-if=\"config.item.key\">\n                            <td width=\"7%\" class=\"text-center\">\n                                <span class=\"label label-warning no-radius cursor-pointer\"\n                                      data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"点击查看已发布的值\"\n                                      ng-if=\"config.isModified || config.isDeleted\"\n                                      ng-click=\"showText(config.oldValue)\">未发布</span>\n                                <span class=\"label label-default-light no-radius\"\n                                      data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"已生效的配置\"\n                                      ng-if=\"!config.isModified\">已发布</span>\n                            </td>\n                            <td width=\"15%\" class=\"cursor-pointer\" title=\"点击查看\" ng-click=\"showText(config.item.key)\">\n                                <span ng-bind=\"config.item.key | limitTo: 250\"></span>\n                                <span ng-bind=\"config.item.key.length > 250 ? '...' :''\"></span>\n                                <span class=\"label label-danger\" ng-if=\"config.isDeleted\"\n                                      data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"删除的配置\">删</span>\n                                <span class=\"label label-info\" ng-if=\"!config.isDeleted && config.masterReleaseValue\"\n                                      data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"修改主版本的配置\">改</span>\n                                <span class=\"label label-success\"\n                                      ng-if=\"!config.isDeleted && !config.masterReleaseValue\"\n                                      data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"灰度版本特有的配置\">新</span>\n                            </td>\n                            <td width=\"20%\" class=\"cursor-pointer\" title=\"点击查看\"\n                                ng-click=\"showText(config.masterReleaseValue)\">\n                                <span ng-bind=\"config.masterReleaseValue | limitTo: 250\"></span>\n                                <span ng-bind=\"config.item.value.length > 250 ? '...': ''\"></span>\n                            </td>\n                            <td width=\"20%\" class=\"cursor-pointer\" title=\"点击查看\" ng-click=\"showText(config.item.value)\">\n                                <span ng-bind=\"config.item.value | limitTo: 250\"></span>\n                                <span ng-bind=\"config.item.value.length > 250 ? '...': ''\"></span>\n                            </td>\n                            <td width=\"10%\" title=\"{{config.item.comment}}\">\n                                <span ng-bind=\"config.item.comment | limitTo: 250\"></span>\n                                <span ng-bind=\"config.item.comment.length > 250 ?'...' : ''\"></span>\n                            </td>\n                            <td width=\"10%\" ng-bind=\"config.item.dataChangeLastModifiedBy\">\n                            </td>\n                            <td width=\"10%\"\n                                ng-bind=\"config.item.dataChangeLastModifiedTime | date: 'yyyy-MM-dd HH:mm:ss'\">\n                            </td>\n\n                            <td width=\"9%\" class=\"text-center\">\n                                <img src=\"img/edit.png\"\n                                     data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"修改\"\n                                     ng-if=\"!config.isDeleted\"\n                                     ng-click=\"editItem(namespace.branch, config.item)\"\n                                     ng-show=\"namespace.hasModifyPermission\">\n                                <img style=\"margin-left: 5px;\" src=\"img/cancel.png\"\n                                     data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"删除\"\n                                     ng-if=\"!config.isDeleted\"\n                                     ng-click=\"preDeleteItem(namespace.branch, config.item.id)\"\n                                     ng-show=\"namespace.hasModifyPermission\">\n                            </td>\n\n                        </tr>\n                        </tbody>\n                    </table>\n                </div>\n\n                <div class=\"panel panel-default\"\n                     ng-if=\"namespace.branch.masterItems && namespace.branch.masterItems.length > 0\">\n                    <div class=\"panel-heading\">\n                        主版本的配置\n                    </div>\n                    <table class=\"table table-bordered table-striped table-hover\">\n                        <thead>\n                        <tr>\n                            <th>发布状态</th>\n                            <th class=\"hover\" title=\"排序\"\n                                ng-click=\"col='item.key';desc=!desc;\">\n                                Key&nbsp;\n                                <span class=\"glyphicon glyphicon-sort\"></span>\n\n                            </th>\n                            <th>\n                                Value\n                            </th>\n                            <th>\n                                备注\n                            </th>\n                            <th class=\"hover\" title=\"排序\"\n                                ng-click=\"col='item.dataChangeLastModifiedBy';desc=!desc;\">\n                                最后修改人\n                                <span class=\"glyphicon glyphicon-sort\"></span>\n\n                            </th>\n                            <th class=\"hover\" title=\"排序\"\n                                ng-click=\"col='item.dataChangeLastModifiedTime';desc=!desc;\">\n                                最后修改时间\n                                <span class=\"glyphicon glyphicon-sort\"></span>\n                            </th>\n                            <th>\n                                操作\n                            </th>\n                        </tr>\n                        </thead>\n                        <tbody>\n\n                        <tr ng-repeat=\"config in namespace.branch.masterItems |orderBy:col:desc\"\n                            ng-if=\"config.item.key\">\n                            <td width=\"8%\" class=\"text-center\">\n                                <span class=\"label label-warning no-radius cursor-pointer\"\n                                      data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"点击查看已发布的值\"\n                                      ng-if=\"config.isModified || config.isDeleted\"\n                                      ng-click=\"showText(config.oldValue)\">未发布</span>\n                                <span class=\"label label-default-light no-radius\"\n                                      data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"已生效的配置\"\n                                      ng-if=\"!config.isModified\">已发布</span>\n                            </td>\n                            <td width=\"15%\" class=\"cursor-pointer\" title=\"点击查看\" ng-click=\"showText(config.item.key)\">\n                                <span ng-bind=\"config.item.key | limitTo: 250\"></span>\n                                <span ng-bind=\"config.item.key.length > 250 ? '...' :''\"></span>\n                                <span class=\"label label-success\" ng-if=\"config.isModified && !config.oldValue\"\n                                      data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"新增的配置\">新</span>\n                            <span class=\"label label-info\"\n                                  ng-if=\"config.isModified && config.oldValue && !config.isDeleted\"\n                                  data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"修改的配置\">改</span>\n                            <span class=\"label label-danger\" ng-if=\"config.isDeleted\"\n                                  data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"删除的配置\">删</span>\n                            </td>\n                            <td width=\"35%\" class=\"cursor-pointer\" title=\"点击查看\" ng-click=\"showText(config.item.value)\">\n                                <span ng-bind=\"config.item.value | limitTo: 250\"></span>\n                                <span ng-bind=\"config.item.value.length > 250 ? '...': ''\"></span>\n                            </td>\n                            <td width=\"12%\" title=\"{{config.item.comment}}\">\n                                <span ng-bind=\"config.item.comment | limitTo: 250\"></span>\n                                <span ng-bind=\"config.item.comment.length > 250 ?'...' : ''\"></span>\n                            </td>\n                            <td width=\"10%\" ng-bind=\"config.item.dataChangeLastModifiedBy\">\n                            </td>\n                            <td width=\"15%\"\n                                ng-bind=\"config.item.dataChangeLastModifiedTime | date: 'yyyy-MM-dd HH:mm:ss'\">\n                            </td>\n\n                            <td width=\"5%\" class=\"text-center\">\n                                <img src=\"img/gray.png\"\n                                     data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"对此配置灰度\"\n                                     ng-if=\"!config.isDeleted\"\n                                     ng-click=\"editItem(namespace.branch, config.item)\"\n                                     ng-show=\"namespace.hasModifyPermission\">\n                            </td>\n\n                        </tr>\n                        </tbody>\n                    </table>\n                </div>\n            </div>\n            <!--gray rules-->\n            <div class=\"rules-manage-view row\" ng-show=\"namespace.branch.viewType == 'rule'\">\n\n                <div class=\"alert alert-warning no-radius\"\n                     ng-show=\"!namespace.hasModifyPermission && !namespace.hasReleasePermission\">\n                    <strong>Tips:</strong>\n                    您没有权限编辑灰度规则, 具有namespace修改权或者发布权的人员才可以编辑灰度规则. 如需要编辑灰度规则,请找项目管理员申请权限.\n                </div>\n\n                <table class=\"table table-bordered table-hover\">\n                    <thead>\n                    <tr>\n                        <th>灰度的AppId</th>\n                        <th>灰度的IP列表</th>\n                        <th>操作</th>\n                    </tr>\n                    </thead>\n                    <tbody>\n                    <tr ng-repeat=\"ruleItem in namespace.branch.rules.ruleItems\">\n                        <td width=\"20%\" ng-bind=\"ruleItem.clientAppId\"></td>\n                        <td width=\"70%\" ng-show=\"!ruleItem.ApplyToAllInstances\"\n                            ng-bind=\"ruleItem.clientIpList.join(', ')\"></td>\n                        <td width=\"70%\" ng-show=\"ruleItem.ApplyToAllInstances\">ALL</td>\n                        <td class=\"text-center\" width=\"10%\">\n                            <img src=\"img/edit.png\" class=\"i-20 hover\"\n                                 data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"修改\"\n                                 ng-show=\"namespace.hasModifyPermission || namespace.hasReleasePermission\"\n                                 ng-click=\"editRuleItem(namespace.branch, ruleItem)\">\n                            <img src=\"img/cancel.png\" class=\"i-20 hover\" style=\"margin-left: 5px;\"\n                                 data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"删除\"\n                                 ng-show=\"namespace.hasModifyPermission || namespace.hasReleasePermission\"\n                                 ng-click=\"deleteRuleItem(namespace.branch, ruleItem)\">\n                        </td>\n                    </tr>\n\n                    </tbody>\n                </table>\n                <button class=\"btn btn-primary\"\n                        ng-if=\"namespace.hasModifyPermission || namespace.hasReleasePermission\"\n                        ng-show=\"(namespace.isPublic && !namespace.isLinkedNamespace) ||\n                        ((!namespace.isPublic || namespace.isLinkedNamespace)\n                        && (!namespace.branch.rules\n                            || !namespace.branch.rules.ruleItems\n                            || !namespace.branch.rules.ruleItems.length))\"\n                        ng-click=\"addRuleItem(namespace.branch)\">新增规则\n                </button>\n\n\n            </div>\n\n\n            <!--instances -->\n            <div class=\"panel panel-default\" ng-show=\"namespace.branch.viewType == 'instance'\">\n                <div class=\"panel-heading text-right\">\n                    <button class=\"btn btn-default btn-sm\"\n                            data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"刷新列表\"\n                            ng-click=\"refreshInstancesInfo(namespace.branch)\">\n                        <img src=\"../../img/refresh.png\"/>\n                    </button>\n                </div>\n                <div class=\"panel-body\">\n                    <div class=\"panel-default\" ng-if=\"namespace.branch.latestReleaseInstances.total > 0\">\n                        <div class=\"panel-heading\">\n                            <a target=\"_blank\" data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"查看配置\"\n                               href=\"/config/history.html?#/appid={{appId}}&env={{env}}&clusterName={{namespace.baseInfo.clusterName}}&namespaceName={{namespace.baseInfo.namespaceName}}&releaseId={{namespace.branch.latestRelease.id}}\">\n                                {{namespace.branch.latestRelease.name}}\n                            </a>\n                        </div>\n                        <table class=\"table table-bordered table-striped\">\n                            <thead>\n                            <tr>\n                                <td>App ID</td>\n                                <td>Cluster Name</td>\n                                <td>Data Center</td>\n                                <td>IP</td>\n                                <td>配置获取时间</td>\n                            </tr>\n                            </thead>\n                            <tbody>\n                            <tr ng-repeat=\"instance in namespace.branch.latestReleaseInstances.content\">\n                                <td width=\"20%\" ng-bind=\"instance.appId\"></td>\n                                <td width=\"20%\" ng-bind=\"instance.clusterName\"></td>\n                                <td width=\"20%\" ng-bind=\"instance.dataCenter\"></td>\n                                <td width=\"20%\" ng-bind=\"instance.ip\"></td>\n                                <td width=\"20%\">{{instance.configs && instance.configs.length ?\n                                    (instance.configs[0].releaseDeliveryTime | date: 'yyyy-MM-dd HH:mm:ss') : ''}}\n                                </td>\n                            </tr>\n                            </tbody>\n                        </table>\n                        <div class=\"row text-center\"\n                             ng-show=\"namespace.branch.latestReleaseInstances.content.length < namespace.branch.latestReleaseInstances.total\">\n                            <button class=\"btn btn-default\" ng-click=\"loadInstanceInfo(namespace.branch)\">加载更多</button>\n\n                        </div>\n                    </div>\n                    <div class=\"text-center\" ng-if=\"namespace.branch.latestReleaseInstances.total == 0\">\n                        无实例信息\n                    </div>\n                </div>\n\n\n            </div>\n            <!--history view-->\n            <div class=\"J_historyview history-view\" ng-show=\"namespace.branch.viewType == 'history'\">\n                <div class=\"media\"\n                     ng-show=\"namespace.branch.commits && namespace.branch.commits.length\"\n                     ng-repeat=\"commits in namespace.branch.commits\">\n                    <div class=\"media-body\">\n                        <div class=\"row\">\n                            <div class=\"col-md-6 col-sm-6 \"><h3 class=\"media-heading\"\n                                                                ng-bind=\"commits.dataChangeCreatedBy\"></h3>\n                            </div>\n                            <div class=\"col-md-6 col-sm-6 text-right\">\n                                <h5 class=\"media-heading\"\n                                    ng-bind=\"commits.dataChangeCreatedTime  | date: 'yyyy-MM-dd HH:mm:ss'\"></h5>\n                            </div>\n                        </div>\n\n\n                        <!--properties format-->\n                        <table class=\"table table-bordered table-striped text-center table-hover\"\n                               style=\"margin-top: 5px;\"\n                               ng-if=\"namespace.isPropertiesFormat\">\n                            <thead>\n                            <tr>\n                                <th>\n                                    Type\n                                </th>\n                                <th>\n                                    Key\n                                </th>\n                                <th>\n                                    Old Value\n                                </th>\n                                <th>\n                                    New Value\n                                </th>\n                                <th>\n                                    Comment\n                                </th>\n                            </tr>\n                            </thead>\n                            <tbody>\n\n                            <!--兼容老数据,不显示item类型为空行和注释的item-->\n                            <tr ng-repeat=\"item in commits.changeSets.createItems\" ng-show=\"item.key\">\n                                <td width=\"2%\">\n                                    新增\n                                </td>\n                                <td width=\"20%\" title=\"{{item.key}}\">\n\n                                    <span ng-bind=\"item.key | limitTo: 250\"></span>\n                                    <span ng-bind=\"item.key.length > 250 ? '...' :''\"></span>\n                                </td>\n                                <td width=\"30%\">\n                                </td>\n                                <td width=\"30%\" class=\"cursor-pointer\" title=\"{{item.value}}\"\n                                    ng-click=\"showText(item.value)\">\n                                    <span ng-bind=\"item.value | limitTo: 250\"></span>\n                                    <span ng-bind=\"item.value.length > 250 ? '...': ''\"></span>\n                                </td>\n                                <td width=\"18%\" title=\"{{item.comment}}\">\n                                    <span ng-bind=\"item.comment | limitTo: 250\"></span>\n                                    <span ng-bind=\"item.comment.length > 250 ?'...' : ''\"></span>\n                                </td>\n                            </tr>\n                            <tr ng-repeat=\"item in commits.changeSets.updateItems\">\n                                <td width=\"2%\">\n                                    更新\n                                </td>\n                                <td width=\"20%\" title=\"{{item.newItem.key}}\">\n                                    <span ng-bind=\"item.newItem.key | limitTo: 250\"></span>\n                                    <span ng-bind=\"item.newItem.key.length > 250 ? '...' :''\"></span>\n                                </td>\n                                <td width=\"30%\" class=\"cursor-pointer\" title=\"{{item.oldItem.value}}\"\n                                    ng-click=\"showText(item.oldItem.value)\">\n                                    <span ng-bind=\"item.oldItem.value | limitTo: 250\"></span>\n                                    <span ng-bind=\"item.oldItem.value.length > 250 ? '...': ''\"></span>\n                                </td>\n                                <td width=\"30%\" class=\"cursor-pointer\" title=\"{{item.newItem.value}}\"\n                                    ng-click=\"showText(item.newItem.value)\">\n                                    <span ng-bind=\"item.newItem.value | limitTo: 250\"></span>\n                                    <span ng-bind=\"item.newItem.value.length > 250 ? '...': ''\"></span>\n                                </td>\n                                <td width=\"18%\" title=\"{{item.newItem.comment}}\">\n                                    <span ng-bind=\"item.newItem.comment | limitTo: 250\"></span>\n                                    <span ng-bind=\"item.newItem.comment.length > 250 ?'...' : ''\"></span>\n                                </td>\n                            </tr>\n                            <tr ng-repeat=\"item in commits.changeSets.deleteItems\"\n                                ng-show=\"item.key || item.comment\">\n                                <td width=\"2%\">\n                                    删除\n                                </td>\n                                <td width=\"20%\" title=\"{{item.key}}\">\n                                    <span ng-bind=\"item.key | limitTo: 250\"></span>\n                                    <span ng-bind=\"item.key.length > 250 ? '...' :''\"></span>\n                                </td>\n                                <td width=\"30%\" title=\"{{item.value}}\">\n                                    <span ng-bind=\"item.value | limitTo: 250\"></span>\n                                    <span ng-bind=\"item.value.length > 250 ? '...': ''\"></span>\n                                </td>\n                                <td width=\"30%\">\n                                </td>\n                                <td width=\"18%\" title=\"{{item.comment}}\">\n                                    <span ng-bind=\"item.comment | limitTo: 250\"></span>\n                                    <span ng-bind=\"item.comment.length > 250 ?'...' : ''\"></span>\n                                </td>\n                            </tr>\n                            </tbody>\n                        </table>\n\n                        <!--not properties format-->\n                        <div ng-if=\"!namespace.isPropertiesFormat\">\n                            <div ng-repeat=\"item in commits.changeSets.createItems\">\n                                <textarea class=\"form-control no-radius\" rows=\"20\"\n                                          ng-disabled=\"true\" ng-bind=\"item.value\">\n                                </textarea>\n                            </div>\n\n                            <div ng-repeat=\"item in commits.changeSets.updateItems\">\n                                <textarea class=\"form-control no-radius\" rows=\"20\"\n                                          ng-disabled=\"true\" ng-bind=\"item.newItem.value\">\n                                </textarea>\n                            </div>\n                        </div>\n\n\n                    </div>\n                    <hr>\n                </div>\n                <div class=\"text-center\">\n                    <button type=\"button\" class=\"btn btn-default\" ng-show=\"!namespace.branch.hasLoadAllCommit\"\n                            ng-click=\"loadCommitHistory(namespace.branch)\">加载更多\n                        <span class=\"glyphicon glyphicon-menu-down\"></span></button>\n                </div>\n                <div class=\"empty-container text-center\"\n                     ng-show=\"!namespace.branch.commits || !namespace.branch.commits.length\">\n                    无更改历史\n                </div>\n            </div>\n        </section>\n    </div>\n</section>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/views/component/namespace-panel-header.html",
    "content": "<header class=\"row namespace-attribute-panel\">\n    <div class=\"text-center namespace-attribute-public\">\n            <span data-tooltip=\"tooltip\" data-placement=\"bottom\"\n                  title=\"私有namespace({{namespace.baseInfo.namespaceName}})的配置只能被AppId为{{appId}}的客户端读取到\"\n                  ng-show=\"!namespace.isPublic\">私有</span>\n\n            <span data-tooltip=\"tooltip\" data-placement=\"top\"\n                  title=\"namespace({{namespace.baseInfo.namespaceName}})的配置能被任何客户端读取到\"\n                  ng-show=\"namespace.isPublic && namespace.parentAppId == namespace.baseInfo.appId\">公共</span>\n\n            <span data-tooltip=\"tooltip\" data-placement=\"top\"\n                  title=\"namespace({{namespace.baseInfo.namespaceName}})的配置将会覆盖公共namespace的配置, 且合并之后的配置只能被AppId为{{appId}}的客户端读取到\"\n                  ng-show=\"namespace.isPublic && namespace.isLinkedNamespace\"\n                  ng-click=\"goToParentAppConfigPage(namespace)\">关联</span>\n    </div>\n</header>\n\n<!--branch nav-->\n<header class=\"panel-heading second-panel-heading\" ng-show=\"namespace.hasBranch\">\n    <div class=\"row\">\n        <div class=\"col-md-8 pull-left\">\n            <ul class=\"nav nav-tabs\">\n                <li role=\"presentation\">\n                    <a ng-class=\"{'node_active': namespace.displayControl.currentOperateBranch == 'master'}\"\n                       ng-click=\"switchBranch('master')\">\n                        <img src=\"img/branch.png\">\n                        主版本\n                    </a>\n                </li>\n                <li role=\"presentation\">\n                    <a ng-class=\"{'node_active': namespace.displayControl.currentOperateBranch != 'master'}\"\n                       ng-click=\"switchBranch(namespace.branchName)\">\n                        <img src=\"img/branch.png\">\n                        灰度版本\n                    </a>\n                </li>\n\n            </ul>\n        </div>\n    </div>\n</header>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/views/component/namespace-panel-master-tab.html",
    "content": "<!--master panel body-->\n<section class=\"master-panel-body\"\n         ng-if=\"namespace.hasBranch\n         && namespace.displayControl.currentOperateBranch == 'master' ||\n          !namespace.hasBranch\">\n    <!--main header-->\n    <header class=\"panel-heading\">\n        <div class=\"row\">\n            <div class=\"col-md-6 col-sm-6 header-namespace\">\n                <span class=\"cursor-pointer\"\n                      data-toggle=\"collapse\" data-target=\"#BODY{{namespace.id}}\" aria-expanded=\"false\"\n                      ng-click=\"namespace.displayControl.show = !namespace.displayControl.show\">\n                    <span class=\"glyphicon glyphicon-triangle-bottom small\"\n                          ng-show=\"namespace.displayControl.show\"></span>\n                    <span class=\"glyphicon glyphicon-triangle-top small\"\n                          ng-show=\"!namespace.displayControl.show\"></span>\n                    <b class=\"namespace-name\" ng-bind=\"namespace.viewName\"\n                       data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"点击展开/收缩Namespace\"></b>\n\n                </span>\n                <span class=\"label label-info no-radius namespace-label\" ng-bind=\"namespace.format\"></span>\n                <span class=\"label label-warning no-radius namespace-label modify-tip\"\n                      ng-show=\"namespace.itemModifiedCnt > 0\">\n                    有修改\n                    <span class=\"badge label badge-white namespace-label\" ng-bind=\"namespace.itemModifiedCnt\"></span>\n                </span>\n                <span class=\"label label-primary no-radius namespace-label\"\n                      ng-show=\"namespace.lockOwner\">当前修改者:{{namespace.lockOwner}}</span>\n            </div>\n\n            <div class=\"col-md-6 col-sm-6 text-right header-buttons\">\n\n                <button type=\"button\" class=\"btn btn-success btn-sm\"\n                        data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"发布配置\"\n                        ng-show=\"(namespace.hasReleasePermission || namespace.hasModifyPermission)\"\n                        ng-disabled=\"namespace.isTextEditing\"\n                        ng-click=\"publish(namespace)\">\n                    <img src=\"img/release.png\">\n                    发布\n                </button>\n                <button type=\"button\" class=\"btn btn-default btn-sm\"\n                        data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"回滚已发布配置\"\n                        ng-show=\"namespace.hasReleasePermission\"\n                        ng-click=\"rollback(namespace)\">\n                    <img src=\"img/rollback.png\">\n                    回滚\n                </button>\n                <a type=\"button\" class=\"btn btn-default btn-sm\"\n                   data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"查看发布历史\"\n                   href=\"/config/history.html?#/appid={{appId}}&env={{env}}&clusterName={{cluster}}&namespaceName={{namespace.baseInfo.namespaceName}}\">\n                    <img src=\"img/release-history.png\">\n                    发布历史\n                </a>\n                <a type=\"button\" class=\"btn btn-default btn-sm\"\n                   data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"配置修改、发布权限\"\n                   href=\"/namespace/role.html?#/appid={{appId}}&namespaceName={{namespace.baseInfo.namespaceName}}\"\n                   ng-show=\"hasAssignUserPermission\">\n                    <img src=\"img/assign.png\">\n                    授权\n                </a>\n\n                <a type=\"button\" class=\"btn btn-default btn-sm\"\n                   data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"创建测试版本\"\n                   ng-show=\"!namespace.hasBranch && namespace.isPropertiesFormat && namespace.hasModifyPermission\"\n                   ng-click=\"preCreateBranch(namespace)\">\n                    <img src=\"img/test.png\">\n                    灰度\n                </a>\n\n                <a type=\"button\" class=\"btn btn-default btn-sm J_tableview_btn\"\n                   data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"您没有任何配置权限,请申请\"\n                   ng-click=\"showNoModifyPermissionDialog()\"\n                   ng-show=\"!namespace.hasModifyPermission && !namespace.hasReleasePermission\">\n                    申请配置权限\n                </a>\n\n                <div class=\"btn-group\"\n                     ng-show=\"namespace.hasModifyPermission || namespace.hasReleasePermission || hasAssignUserPermission\">\n                    <button type=\"button\" class=\"btn btn-default btn-sm dropdown-toggle\"\n                            data-toggle=\"dropdown\"\n                            aria-haspopup=\"true\" aria-expanded=\"false\">\n                        <img src=\"img/operate.png\"> <span class=\"caret\"></span>\n                    </button>\n                    <ul class=\"dropdown-menu\" style=\"right: 0; left: -160px;\">\n                        <li ng-click=\"deleteNamespace(namespace)\">\n                            <a style=\"color: red\">\n                                <img src=\"img/delete.png\"> 删除Namespace</a>\n                        </li>\n                    </ul>\n                </div>\n            </div>\n        </div>\n    </header>\n\n    <div id=\"BODY{{namespace.id}}\" class=\"collapse in\">\n        <!--second header-->\n        <header class=\"panel-heading second-panel-heading\">\n            <div class=\"row\">\n                <div class=\"col-md-6 col-sm-6 pull-left\">\n                    <!--master branch nav tabs-->\n                    <ul class=\"nav nav-tabs\">\n                        <li role=\"presentation\" ng-click=\"switchView(namespace, 'table')\"\n                            ng-show=\"namespace.isPropertiesFormat\">\n                            <a ng-class=\"{node_active:namespace.viewType == 'table'}\">\n                                <img src=\"img/table.png\">\n                                表格\n                            </a>\n                        </li>\n                        <li role=\"presentation\"\n                            ng-click=\"switchView(namespace, 'text')\">\n                            <a ng-class=\"{node_active:namespace.viewType == 'text'}\">\n                                <img src=\"img/text.png\">\n                                文本\n                            </a>\n                        </li>\n                        <li role=\"presentation\" ng-click=\"switchView(namespace, 'history')\">\n                            <a ng-class=\"{node_active:namespace.viewType == 'history'}\">\n                                <img src=\"img/change.png\">\n                                更改历史\n                            </a>\n                        </li>\n                        <li role=\"presentation\" ng-click=\"switchView(namespace, 'instance')\">\n                            <a ng-class=\"{node_active:namespace.viewType == 'instance'}\">\n                                <img src=\"img/machine.png\">\n                                实例列表\n                                <span class=\"badge badge-grey\" ng-bind=\"namespace.instancesCount\"></span>\n                            </a>\n                        </li>\n                    </ul>\n                </div>\n                <div class=\"col-md-6 col-sm-6 text-right\">\n                    <img src=\"img/copy.png\" class=\"ns_btn clipboard cursor-pointer\"\n                         data-clipboard-text=\"{{namespace.text}}\"\n                         data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"复制文本\"\n                         ng-show=\"!namespace.isTextEditing && namespace.viewType == 'text' && namespace.hasModifyPermission\">\n                    &nbsp;\n                    <img src=\"img/cancel.png\" class=\"ns_btn cursor-pointer\"\n                         data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"取消修改\"\n                         ng-show=\"namespace.isTextEditing && namespace.viewType == 'text'\"\n                         ng-click=\"toggleTextEditStatus(namespace)\">\n                    <img src=\"img/edit.png\" class=\"ns_btn cursor-pointer\"\n                         data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"修改配置\"\n                         ng-show=\"!namespace.isTextEditing && namespace.viewType == 'text' && namespace.hasModifyPermission\"\n                         ng-click=\"toggleTextEditStatus(namespace)\">\n\n                    &nbsp;\n                    <img src=\"img/submit.png\" class=\"ns_btn cursor-pointer\"\n                         data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"提交修改\"\n                         data-toggle=\"modal\" data-target=\"#commitModal\"\n                         ng-show=\"namespace.isTextEditing && namespace.viewType == 'text'\"\n                         ng-click=\"modifyByText(namespace)\">\n\n                    <button type=\"button\" class=\"btn btn-default btn-sm\"\n                            data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"按Key过滤配置\"\n                            ng-show=\"namespace.viewType == 'table' && namespace.displayControl.currentOperateBranch == 'master'\n                        && !namespace.isLinkedNamespace\"\n                            ng-click=\"toggleItemSearchInput(namespace)\">\n                        <span class=\"glyphicon glyphicon-filter\"></span>\n                        过滤配置\n                    </button>\n\n                    <button type=\"button\" class=\"btn btn-default btn-sm J_tableview_btn\"\n                            data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"同步各环境间配置\"\n                            ng-click=\"goToSyncPage(namespace)\"\n                            ng-show=\"namespace.viewType == 'table' && namespace.displayControl.currentOperateBranch == 'master'\n                             && namespace.hasModifyPermission && namespace.isPropertiesFormat\">\n                        <img src=\"img/sync.png\">\n                        同步配置\n                    </button>\n\n                    <button type=\"button\" class=\"btn btn-primary btn-sm\"\n                            ng-show=\"!namespace.isLinkedNamespace\n                             && namespace.viewType == 'table'\n                             && namespace.displayControl.currentOperateBranch == 'master'\n                             && namespace.hasModifyPermission\"\n                            ng-click=\"createItem(namespace)\">\n                        <img src=\"img/plus.png\">\n                        新增配置\n                    </button>\n                </div>\n            </div>\n        </header>\n\n        <!--namespace body-->\n        <section>\n            <!--table view-->\n            <div class=\"namespace-view-table\" ng-show=\"namespace.viewType == 'table'\">\n\n                <div class=\"J_namespace-release-tip well well-sm no-radius text-center\"\n                     ng-show=\"namespace.isLatestReleaseLoaded && !namespace.isLinkedNamespace && !namespace.latestRelease\">\n                    <span style=\"color: red\"> Tips: 此namespace从来没有发布过，Apollo客户端将获取不到配置并记录404日志信息，请及时发布。</span>\n                </div>\n                <!--not link namespace-->\n                <div ng-if=\"!namespace.isLinkedNamespace\">\n                    <div class=\"search-input\" ng-show=\"namespace.displayControl.showSearchInput\">\n                        <input type=\"text\" class=\"form-control\" placeholder=\"输入key过滤\"\n                               ng-model=\"namespace.searchKey\"\n                               ng-change=\"searchItems(namespace)\">\n                    </div>\n\n                    <table class=\"table table-bordered table-striped table-hover\">\n                        <thead>\n                        <tr>\n                            <th>发布状态</th>\n                            <th class=\"hover\" title=\"排序\"\n                                ng-click=\"col='item.key';desc=!desc;\">\n                                Key&nbsp;\n                                <span class=\"glyphicon glyphicon-sort\"></span>\n\n                            </th>\n                            <th>\n                                Value\n                            </th>\n                            <th>\n                                备注\n                            </th>\n                            <th class=\"hover\" title=\"排序\"\n                                ng-click=\"col='item.dataChangeLastModifiedBy';desc=!desc;\">\n                                最后修改人\n                                <span class=\"glyphicon glyphicon-sort\"></span>\n\n                            </th>\n                            <th class=\"hover\" title=\"排序\"\n                                ng-click=\"col='item.dataChangeLastModifiedTime';desc=!desc;\">\n                                最后修改时间\n                                <span class=\"glyphicon glyphicon-sort\"></span>\n                            </th>\n\n                            <th>\n                                操作\n                            </th>\n                        </tr>\n                        </thead>\n                        <tbody>\n                        <tr ng-repeat=\"config in namespace.viewItems |orderBy:col:desc\"\n                            ng-if=\"config.item.key\"\n                            ng-class=\"{'warning': !config.item.value}\">\n                            <td width=\"8%\" class=\"text-center\">\n                            <span class=\"label label-warning no-radius cursor-pointer\" ng-if=\"config.isModified\"\n                                  data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"点击查看已发布的值\"\n                                  ng-click=\"showText(config.oldValue?config.oldValue:'新增的配置,无发布的值')\">未发布</span>\n                                <span class=\"label label-default-light no-radius\"\n                                      data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"已生效的配置\"\n                                      ng-if=\"!config.isModified\">已发布</span>\n                            </td>\n                            <td width=\"15%\" class=\"cursor-pointer\" title=\"点击查看\" ng-click=\"showText(config.item.key)\">\n                                <span ng-bind=\"config.item.key | limitTo: 250\"></span>\n                                <span ng-bind=\"config.item.key.length > 250 ? '...' :''\"></span>\n                                <span class=\"label label-default cursor-pointer\" ng-if=\"config.hasBranchValue\"\n                                      data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"该配置有灰度配置,点击查看灰度的值\"\n                                      ng-click=\"namespace.displayControl.currentOperateBranch=namespace.branchName;namespace.branch.viewType='table'\">灰</span>\n                                <span class=\"label label-success\" ng-if=\"config.isModified && !config.oldValue\"\n                                      data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"新增的配置\">新</span>\n                                <span class=\"label label-info\"\n                                      ng-if=\"config.isModified && config.oldValue && !config.isDeleted\"\n                                      data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"修改的配置\">改</span>\n                                <span class=\"label label-danger\" ng-if=\"config.isDeleted\"\n                                      data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"删除的配置\">删</span>\n                            </td>\n                            <td width=\"30%\" class=\"cursor-pointer\" title=\"点击查看\" ng-click=\"showText(config.item.value)\">\n                                <span ng-bind=\"config.item.value | limitTo: 250\"></span>\n                                <span ng-bind=\"config.item.value.length > 250 ? '...': ''\"></span>\n                            </td>\n                            <td width=\"13%\" title=\"{{config.item.comment}}\">\n                                <span ng-bind=\"config.item.comment | limitTo: 250\"></span>\n                                <span ng-bind=\"config.item.comment.length > 250 ?'...' : ''\"></span>\n                            </td>\n                            <td width=\"10%\" ng-bind=\"config.item.dataChangeLastModifiedBy\">\n                            </td>\n                            <td width=\"16%\"\n                                ng-bind=\"config.item.dataChangeLastModifiedTime | date: 'yyyy-MM-dd HH:mm:ss'\">\n                            </td>\n\n                            <td width=\"8%\" class=\"text-center\" ng-if=\"!config.isDeleted\">\n                                <img src=\"img/edit.png\" data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"修改\"\n                                     ng-click=\"editItem(namespace, config.item)\"\n                                     ng-show=\"namespace.hasModifyPermission\">\n                                <img style=\"margin-left: 5px;\" src=\"img/cancel.png\"\n                                     data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"删除\"\n                                     ng-click=\"preDeleteItem(namespace, config.item.id)\"\n                                     ng-show=\"namespace.hasModifyPermission\">\n                            </td>\n                            <td width=\"6%\" class=\"text-center\" ng-if=\"config.isDeleted\">\n                            </td>\n\n                        </tr>\n                        </tbody>\n                    </table>\n                </div>\n\n                <!--link namespace-->\n                <div class=\"panel panel-default\" ng-if=\"namespace.isLinkedNamespace\">\n                    <div class=\"panel-heading\">\n                        <div class=\"row\">\n                            <div class=\"padding-top-5 col-md-4 col-sm-4\">\n                                覆盖的配置\n                            </div>\n                            <div class=\"col-md-8 col-sm-8\">\n                                <input type=\"text\" class=\"form-control pull-right\" placeholder=\"filter by key ...\"\n                                       ng-class=\"{'search-onblur': namespace.searchStatus == 'OFF' || !namespace.searchStatus,\n                                    'search-focus': namespace.searchStatus == 'ON'}\"\n                                       ng-model=\"namespace.searchKey\"\n                                       ng-change=\"searchItems(namespace)\"\n                                       ng-focus=\"namespace.searchStatus='ON'\"\n                                       ng-blur=\"namespace.searchStatus='OFF'\">\n                            </div>\n                        </div>\n                    </div>\n\n                    <table class=\"table table-bordered table-striped table-hover\"\n                           ng-if=\"namespace.viewItems && namespace.viewItems.length\">\n                        <thead>\n                        <tr>\n                            <th>发布状态</th>\n                            <th class=\"hover\" title=\"排序\"\n                                ng-click=\"col='item.key';desc=!desc;\">\n                                Key&nbsp;\n                                <span class=\"glyphicon glyphicon-sort\"></span>\n\n                            </th>\n                            <th>\n                                Value\n                            </th>\n                            <th>\n                                备注\n                            </th>\n                            <th class=\"hover\" title=\"排序\"\n                                ng-click=\"col='item.dataChangeLastModifiedBy';desc=!desc;\">\n                                最后修改人\n                                <span class=\"glyphicon glyphicon-sort\"></span>\n\n                            </th>\n                            <th class=\"hover\" title=\"排序\"\n                                ng-click=\"col='item.dataChangeLastModifiedTime';desc=!desc;\">\n                                最后修改时间\n                                <span class=\"glyphicon glyphicon-sort\"></span>\n                            </th>\n\n                            <th>\n                                操作\n                            </th>\n                        </tr>\n                        </thead>\n                        <tbody>\n                        <tr ng-repeat=\"config in namespace.viewItems |orderBy:col:desc\"\n                            ng-if=\"config.item.key\">\n                            <td width=\"8%\" class=\"text-center\">\n                            <span class=\"label label-warning no-radius cursor-pointer\" ng-if=\"config.isModified\"\n                                  data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"点击查看已发布的值\"\n                                  ng-click=\"showText(config.oldValue?config.oldValue:'新增的配置,无发布的值')\">未发布</span>\n                                <span class=\"label label-default-light no-radius\"\n                                      data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"已生效的配置\"\n                                      ng-if=\"!config.isModified\">已发布</span>\n                            </td>\n                            <td width=\"15%\" class=\"cursor-pointer\" title=\"点击查看\" ng-click=\"showText(config.item.key)\">\n                                <span ng-bind=\"config.item.key | limitTo: 250\"></span>\n                                <span ng-bind=\"config.item.key.length > 250 ? '...' :''\"></span>\n                                <span class=\"label label-default cursor-pointer\" ng-if=\"config.hasBranchValue\"\n                                      data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"该配置有灰度配置,点击查看灰度的值\"\n                                      ng-click=\"namespace.displayControl.currentOperateBranch=namespace.branchName;namespace.branch.viewType='table'\">灰</span>\n                                <span class=\"label label-success\" ng-if=\"config.isModified && !config.oldValue\"\n                                      data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"新增的配置\">新</span>\n                                <span class=\"label label-info\"\n                                      ng-if=\"config.isModified && config.oldValue && !config.isDeleted\"\n                                      data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"修改的配置\">改</span>\n                                <span class=\"label label-danger\" ng-if=\"config.isDeleted\"\n                                      data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"删除的配置\">删</span>\n                            </td>\n                            <td width=\"30%\" class=\"cursor-pointer\" title=\"点击查看\" ng-click=\"showText(config.item.value)\">\n                                <span ng-bind=\"config.item.value | limitTo: 250\"></span>\n                                <span ng-bind=\"config.item.value.length > 250 ? '...': ''\"></span>\n                            </td>\n                            <td width=\"13%\" title=\"{{config.item.comment}}\">\n                                <span ng-bind=\"config.item.comment | limitTo: 250\"></span>\n                                <span ng-bind=\"config.item.comment.length > 250 ?'...' : ''\"></span>\n                            </td>\n                            <td width=\"10%\" ng-bind=\"config.item.dataChangeLastModifiedBy\">\n                            </td>\n                            <td width=\"16%\"\n                                ng-bind=\"config.item.dataChangeLastModifiedTime | date: 'yyyy-MM-dd HH:mm:ss'\">\n                            </td>\n\n                            <td width=\"8%\" class=\"text-center\" ng-if=\"!config.isDeleted\">\n                                <img src=\"img/edit.png\" data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"修改\"\n                                     ng-click=\"editItem(namespace, config.item)\"\n                                     ng-show=\"namespace.hasModifyPermission\">\n                                <img style=\"margin-left: 5px;\" src=\"img/cancel.png\"\n                                     data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"删除\"\n                                     ng-click=\"preDeleteItem(namespace, config.item.id)\"\n                                     ng-show=\"namespace.hasModifyPermission\">\n                            </td>\n                            <td width=\"6%\" class=\"text-center\" ng-if=\"config.isDeleted\">\n                            </td>\n\n                        </tr>\n                        </tbody>\n                    </table>\n\n                    <div class=\"text-center no-config-panel\"\n                         ng-if=\"!namespace.viewItems || !namespace.viewItems.length\">\n                        <h5>无覆盖的配置</h5>\n                    </div>\n                </div>\n\n                <!--link namespace's public namespace-->\n                <div ng-if=\"namespace.isLinkedNamespace\">\n                    <div class=\"panel panel-default\" ng-if=\"namespace.publicNamespace\">\n                        <div class=\"panel-heading\">\n                            <div class=\"row\">\n                                <div class=\"padding-top-5 col-md-4 col-sm-4\">\n                                    公共的配置\n                                    <a href=\"/config.html?#/appid={{namespace.publicNamespace.baseInfo.appId}}&env={{env}}&cluster={{namespace.publicNamespace.baseInfo.clusterName}}\"\n                                       target=\"_blank\">\n                                        <small>\n                                            (AppId:{{namespace.publicNamespace.baseInfo.appId}},\n                                            Cluster:{{namespace.publicNamespace.baseInfo.clusterName}})\n                                        </small>\n                                    </a>\n                                </div>\n\n                                <div class=\"col-md-4 col-sm-4 text-center\">\n                                    <div class=\"btn-group btn-group-sm\" role=\"group\"\n                                         ng-show=\"namespace.publicNamespace.isModified\">\n                                        <button type=\"button\" class=\"btn btn-default\"\n                                                ng-class=\"{'active':namespace.publicNamespaceViewType == 'RELEASE'\n                                        || !namespace.publicNamespaceViewType}\"\n                                                ng-click=\"namespace.publicNamespaceViewType = 'RELEASE'\">\n                                            已发布的配置\n                                        </button>\n                                        <button type=\"button\" class=\"btn btn-default\"\n                                                ng-class=\"{'active':namespace.publicNamespaceViewType == 'NOT_RELEASE'}\"\n                                                ng-click=\"namespace.publicNamespaceViewType = 'NOT_RELEASE'\">\n                                            未发布的配置\n                                        </button>\n                                    </div>\n                                </div>\n\n                                <div class=\"col-md-4 col-sm-4\">\n                                    <input type=\"text\" class=\"form-control pull-right\" placeholder=\"filter by key ...\"\n                                           ng-class=\"{'search-onblur': namespace.publicNamespace.searchStatus == 'OFF'\n                                   || !namespace.publicNamespace.searchStatus,\n                                    'search-focus': namespace.publicNamespace.searchStatus == 'ON'}\"\n                                           ng-model=\"namespace.publicNamespace.searchKey\"\n                                           ng-change=\"searchItems(namespace.publicNamespace)\"\n                                           ng-blur=\"namespace.publicNamespace.searchStatus='OFF'\"\n                                           ng-focus=\"namespace.publicNamespace.searchStatus='ON'\"/>\n                                </div>\n                            </div>\n                        </div>\n\n\n                        <!--published items-->\n                        <div ng-show=\"!namespace.publicNamespaceViewType || namespace.publicNamespaceViewType == 'RELEASE'\">\n                            <table class=\"table table-bordered table-striped table-hover\"\n                                   ng-show=\"namespace.publicNamespace.hasPublishedItem\">\n                                <thead>\n                                <tr>\n                                    <th class=\"hover\" title=\"排序\"\n                                        ng-click=\"col='item.key';desc=!desc;\">\n                                        Key&nbsp;\n                                        <span class=\"glyphicon glyphicon-sort\"></span>\n\n                                    </th>\n                                    <th>\n                                        Value\n                                    </th>\n                                    <th>\n                                        备注\n                                    </th>\n                                    <th class=\"hover\" title=\"排序\"\n                                        ng-click=\"col='item.dataChangeLastModifiedBy';desc=!desc;\">\n                                        最后修改人\n                                        <span class=\"glyphicon glyphicon-sort\"></span>\n\n                                    </th>\n                                    <th class=\"hover\" title=\"排序\"\n                                        ng-click=\"col='item.dataChangeLastModifiedTime';desc=!desc;\">\n                                        最后修改时间\n                                        <span class=\"glyphicon glyphicon-sort\"></span>\n                                    </th>\n\n                                    <th>\n                                        操作\n                                    </th>\n                                </tr>\n                                </thead>\n                                <tbody>\n                                <tr ng-repeat=\"config in namespace.publicNamespace.viewItems |orderBy:col:desc\"\n                                    ng-if=\"config.item.key && !config.isModified && !config.isDeleted\">\n                                    <td width=\"15%\" class=\"cursor-pointer\" title=\"点击查看\"\n                                        ng-click=\"showText(config.item.key)\">\n                                        <span ng-bind=\"config.item.key | limitTo: 250\"></span>\n                                        <span ng-bind=\"config.item.key.length > 250 ? '...' :''\"></span>\n                                    </td>\n                                    <td width=\"35%\" class=\"cursor-pointer\" title=\"点击查看\"\n                                        ng-click=\"showText(config.item.value)\">\n                                        <span ng-bind=\"config.item.value | limitTo: 250\"></span>\n                                        <span ng-bind=\"config.item.value.length > 250 ? '...': ''\"></span>\n                                    </td>\n                                    <td width=\"15%\" title=\"{{config.item.comment}}\">\n                                        <span ng-bind=\"config.item.comment | limitTo: 250\"></span>\n                                        <span ng-bind=\"config.item.comment.length > 250 ?'...' : ''\"></span>\n                                    </td>\n                                    <td width=\"10%\" ng-bind=\"config.item.dataChangeLastModifiedBy\">\n                                    </td>\n                                    <td width=\"15%\"\n                                        ng-bind=\"config.item.dataChangeLastModifiedTime | date: 'yyyy-MM-dd HH:mm:ss'\">\n                                    </td>\n\n                                    <td width=\"10%\" class=\"text-center\" ng-if=\"!config.isDeleted\">\n                                        <img src=\"img/gray.png\" data-tooltip=\"tooltip\" data-placement=\"bottom\"\n                                             title=\"覆盖此配置\"\n                                             ng-click=\"editItem(namespace, config.item)\"\n                                             ng-show=\"namespace.hasModifyPermission && !config.covered\">\n                                    </td>\n                                    <td width=\"6%\" class=\"text-center\" ng-if=\"config.isDeleted\">\n                                    </td>\n\n                                </tr>\n                                </tbody>\n                            </table>\n\n                            <div class=\"text-center no-config-panel\"\n                                 ng-if=\"namespace.publicNamespace.viewItems\n                     && namespace.publicNamespace.viewItems.length\n                     && !namespace.publicNamespace.hasPublishedItem\">\n                                <h5>无发布的配置</h5>\n                            </div>\n                        </div>\n\n                        <!--not published items-->\n                        <table class=\"table table-bordered table-striped table-hover\"\n                               ng-show=\"namespace.publicNamespaceViewType == 'NOT_RELEASE'\">\n                            <thead>\n                            <tr>\n                                <th class=\"hover\" title=\"排序\"\n                                    ng-click=\"col='item.key';desc=!desc;\">\n                                    Key&nbsp;\n                                    <span class=\"glyphicon glyphicon-sort\"></span>\n\n                                </th>\n                                <th>\n                                    已发布的值\n                                </th>\n                                <th>\n                                    未发布的值\n                                </th>\n                                <th>\n                                    备注\n                                </th>\n                                <th class=\"hover\" title=\"排序\"\n                                    ng-click=\"col='item.dataChangeLastModifiedTime';desc=!desc;\">\n                                    最后修改时间\n                                    <span class=\"glyphicon glyphicon-sort\"></span>\n                                </th>\n\n                                <th>\n                                    操作\n                                </th>\n                            </tr>\n                            </thead>\n                            <tbody>\n                            <tr ng-repeat=\"config in namespace.publicNamespace.viewItems |orderBy:col:desc\"\n                                ng-if=\"config.item.key && (config.isModified || config.isDeleted)\">\n                                <td width=\"20%\" class=\"cursor-pointer\" title=\"点击查看\"\n                                    ng-click=\"showText(config.item.key)\">\n                                    <span ng-bind=\"config.item.key | limitTo: 250\"></span>\n                                    <span ng-bind=\"config.item.key.length > 250 ? '...' :''\"></span>\n                                    <span class=\"label label-success\" ng-if=\"config.isModified && !config.oldValue\"\n                                          data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"新增的配置\">新</span>\n                                    <span class=\"label label-info\"\n                                          ng-if=\"config.isModified && config.oldValue && !config.isDeleted\"\n                                          data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"修改的配置\">改</span>\n                                    <span class=\"label label-danger\" ng-if=\"config.isDeleted\"\n                                          data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"删除的配置\">删</span>\n                                </td>\n                                <td width=\"25%\" class=\"cursor-pointer\" title=\"点击查看\"\n                                    ng-click=\"showText(config.oldValue)\">\n                                    <span ng-bind=\"config.oldValue | limitTo: 250\"></span>\n                                    <span ng-bind=\"config.oldValue.length > 250 ? '...': ''\"></span>\n                                </td>\n                                <td width=\"25%\" class=\"cursor-pointer\" title=\"点击查看\"\n                                    ng-click=\"showText(config.item.value)\">\n                                    <span ng-bind=\"config.item.value | limitTo: 250\"></span>\n                                    <span ng-bind=\"config.item.value.length > 250 ? '...': ''\"></span>\n                                </td>\n                                <td width=\"10%\" title=\"{{config.item.comment}}\">\n                                    <span ng-bind=\"config.item.comment | limitTo: 250\"></span>\n                                    <span ng-bind=\"config.item.comment.length > 250 ?'...' : ''\"></span>\n                                </td>\n                                <td width=\"15%\"\n                                    ng-bind=\"config.item.dataChangeLastModifiedTime | date: 'yyyy-MM-dd HH:mm:ss'\">\n                                </td>\n\n                                <td width=\"5%\" class=\"text-center\" ng-if=\"!config.isDeleted\">\n                                    <img src=\"img/gray.png\" data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"覆盖此配置\"\n                                         ng-click=\"editItem(namespace, config.item)\"\n                                         ng-show=\"namespace.hasModifyPermission && !config.covered\">\n                                </td>\n\n                            </tr>\n                            </tbody>\n                        </table>\n                        <div class=\"text-center no-config-panel\"\n                             ng-if=\"!namespace.publicNamespace.viewItems || !namespace.publicNamespace.viewItems.length\">\n                            <h5>无公共的配置</h5>\n                        </div>\n                    </div>\n                    <div class=\"panel panel-default\" ng-if=\"!namespace.publicNamespace\">\n                        <div class=\"panel-heading\">\n                            公共的配置\n                        </div>\n                        <div class=\"panel-body text-center\">\n                            当前公共namespace的所有者\n                            <a href=\"/config.html?#/appid={{namespace.parentAppId}}\" target=\"_blank\">{{namespace.parentAppId}}</a>\n                            没有关联此namespace,请联系{{namespace.parentAppId}}的所有者在{{namespace.parentAppId}}项目里关联此namespace\n                        </div>\n                    </div>\n                </div>\n\n            </div>\n\n            <!--text view-->\n            <!--只读模式下的文本内容,不替换换行符-->\n            <div ui-ace=\"aceConfig\" readonly=\"true\"\n                 class=\"form-control no-radius\"\n                 rows=\"{{namespace.itemCnt < 10 ? 10: namespace.itemCnt>20 ? 20:namespace.itemCnt}}\"\n                 ng-show=\"namespace.viewType == 'text' && !namespace.isTextEditing\"\n                 ng-model=\"namespace.text\">\n            </div>\n            <!--编辑状态下的文本内容,会过滤掉换行符-->\n            <div ui-ace=\"aceConfig\"\n                 class=\"form-control no-radius\"\n                 rows=\"{{namespace.itemCnt < 10 ? 10: namespace.itemCnt>20 ? 20:namespace.itemCnt}}\"\n                 ng-show=\"namespace.viewType == 'text' && namespace.isTextEditing\"\n                 ng-disabled=\"!namespace.isTextEditing\" ng-model=\"namespace.editText\">\n            </div>\n\n            <!--history view-->\n            <div class=\"J_historyview history-view\" ng-show=\"namespace.viewType == 'history'\">\n                <div class=\"media\"\n                     ng-show=\"namespace.commits && namespace.commits.length\"\n                     ng-repeat=\"commits in namespace.commits\">\n                    <div class=\"media-body\">\n                        <div class=\"row\">\n                            <div class=\"col-md-6 col-sm-6\"><h3 class=\"media-heading\"\n                                                               ng-bind=\"commits.dataChangeCreatedBy\"></h3>\n                            </div>\n                            <div class=\"col-md-6 col-sm-6 text-right\"><h5 class=\"media-heading\"\n                                                                          ng-bind=\"commits.dataChangeCreatedTime  | date: 'yyyy-MM-dd HH:mm:ss'\"></h5>\n                            </div>\n                        </div>\n\n\n                        <!--properties format-->\n                        <table class=\"table table-bordered table-striped text-center table-hover\"\n                               style=\"margin-top: 5px;\"\n                               ng-if=\"namespace.isPropertiesFormat\">\n                            <thead>\n                            <tr>\n                                <th>\n                                    Type\n                                </th>\n                                <th>\n                                    Key\n                                </th>\n                                <th>\n                                    Old Value\n                                </th>\n                                <th>\n                                    New Value\n                                </th>\n                                <th>\n                                    Comment\n                                </th>\n                            </tr>\n                            </thead>\n                            <tbody>\n\n                            <!--兼容老数据,不显示item类型为空行和注释的item-->\n                            <tr ng-repeat=\"item in commits.changeSets.createItems\" ng-show=\"item.key\">\n                                <td width=\"2%\">\n                                    新增\n                                </td>\n                                <td width=\"20%\" title=\"{{item.key}}\">\n\n                                    <span ng-bind=\"item.key | limitTo: 250\"></span>\n                                    <span ng-bind=\"item.key.length > 250 ? '...' :''\"></span>\n                                </td>\n                                <td width=\"30%\">\n                                </td>\n                                <td width=\"30%\" class=\"cursor-pointer\" title=\"{{item.value}}\"\n                                    ng-click=\"showText(item.value)\">\n                                    <span ng-bind=\"item.value | limitTo: 250\"></span>\n                                    <span ng-bind=\"item.value.length > 250 ? '...': ''\"></span>\n                                </td>\n                                <td width=\"18%\" title=\"{{item.comment}}\">\n                                    <span ng-bind=\"item.comment | limitTo: 250\"></span>\n                                    <span ng-bind=\"item.comment.length > 250 ?'...' : ''\"></span>\n                                </td>\n                            </tr>\n                            <tr ng-repeat=\"item in commits.changeSets.updateItems\">\n                                <td width=\"2%\">\n                                    更新\n                                </td>\n                                <td width=\"20%\" title=\"{{item.newItem.key}}\">\n                                    <span ng-bind=\"item.newItem.key | limitTo: 250\"></span>\n                                    <span ng-bind=\"item.newItem.key.length > 250 ? '...' :''\"></span>\n                                </td>\n                                <td width=\"30%\" class=\"cursor-pointer\" title=\"{{item.oldItem.value}}\"\n                                    ng-click=\"showText(item.oldItem.value)\">\n                                    <span ng-bind=\"item.oldItem.value | limitTo: 250\"></span>\n                                    <span ng-bind=\"item.oldItem.value.length > 250 ? '...': ''\"></span>\n                                </td>\n                                <td width=\"30%\" class=\"cursor-pointer\" title=\"{{item.newItem.value}}\"\n                                    ng-click=\"showText(item.newItem.value)\">\n                                    <span ng-bind=\"item.newItem.value | limitTo: 250\"></span>\n                                    <span ng-bind=\"item.newItem.value.length > 250 ? '...': ''\"></span>\n                                </td>\n                                <td width=\"18%\" title=\"{{item.newItem.comment}}\">\n                                    <span ng-bind=\"item.newItem.comment | limitTo: 250\"></span>\n                                    <span ng-bind=\"item.newItem.comment.length > 250 ?'...' : ''\"></span>\n                                </td>\n                            </tr>\n                            <tr ng-repeat=\"item in commits.changeSets.deleteItems\"\n                                ng-show=\"item.key || item.comment\">\n                                <td width=\"2%\">\n                                    删除\n                                </td>\n                                <td width=\"20%\" title=\"{{item.key}}\">\n                                    <span ng-bind=\"item.key | limitTo: 250\"></span>\n                                    <span ng-bind=\"item.key.length > 250 ? '...' :''\"></span>\n                                </td>\n                                <td width=\"30%\" title=\"{{item.value}}\">\n                                    <span ng-bind=\"item.value | limitTo: 250\"></span>\n                                    <span ng-bind=\"item.value.length > 250 ? '...': ''\"></span>\n                                </td>\n                                <td width=\"30%\">\n                                </td>\n                                <td width=\"18%\" title=\"{{item.comment}}\">\n                                    <span ng-bind=\"item.comment | limitTo: 250\"></span>\n                                    <span ng-bind=\"item.comment.length > 250 ?'...' : ''\"></span>\n                                </td>\n                            </tr>\n                            </tbody>\n                        </table>\n\n                        <!--not properties format-->\n                        <div ng-if=\"!namespace.isPropertiesFormat\">\n                            <div ng-repeat=\"item in commits.changeSets.createItems\">\n                    <textarea class=\"form-control no-radius\" rows=\"20\"\n                              ng-disabled=\"true\" ng-bind=\"item.value\">\n                                </textarea>\n                            </div>\n\n                            <div ng-repeat=\"item in commits.changeSets.updateItems\">\n                    <textarea class=\"form-control no-radius\" rows=\"20\"\n                              ng-disabled=\"true\" ng-bind=\"item.newItem.value\">\n                                </textarea>\n                            </div>\n                        </div>\n\n\n                    </div>\n                    <hr>\n                </div>\n                <div class=\"text-center\">\n                    <button type=\"button\" class=\"btn btn-default\" ng-show=\"!namespace.hasLoadAllCommit\"\n                            ng-click=\"loadCommitHistory(namespace)\">加载更多\n                        <span class=\"glyphicon glyphicon-menu-down\"></span></button>\n                </div>\n                <div class=\"empty-container text-center\" ng-show=\"!namespace.commits || !namespace.commits.length\">\n                    无更改历史\n                </div>\n            </div>\n            <!--instance view-->\n            <div class=\"panel panel-default instance-view\" ng-show=\"namespace.viewType == 'instance'\">\n                <div class=\"panel-heading\">\n                    <div class=\"row\">\n\n                        <div class=\"col-md-5 col-sm-5\">\n                            <small>实例说明:只展示最近一天访问过Apollo的实例</small>\n                        </div>\n                        <div class=\"col-md-7 col-sm-7 text-right\">\n                            <div class=\"btn-group btn-group-sm\" role=\"group\">\n                                <button type=\"button\" class=\"btn btn-default\"\n                                        ng-class=\"{'btn-primary':namespace.instanceViewType == 'latest_release'}\"\n                                        ng-click=\"switchInstanceViewType(namespace, 'latest_release')\"> 使用最新配置的实例\n                                    <span class=\"badge\" ng-bind=\"namespace.latestReleaseInstances.total\"></span>\n                                </button>\n                                <button type=\"button\" class=\"btn btn-default\"\n                                        ng-class=\"{'btn-primary':namespace.instanceViewType == 'not_latest_release'}\"\n                                        ng-click=\"switchInstanceViewType(namespace, 'not_latest_release')\">使用非最新配置的实例\n                                    <span class=\"badge\"\n                                          ng-bind=\"namespace.instancesCount - namespace.latestReleaseInstances.total\"></span>\n                                </button>\n                                <button type=\"button\" class=\"btn btn-default\"\n                                        ng-class=\"{'btn-primary':namespace.instanceViewType == 'all'}\"\n                                        ng-click=\"switchInstanceViewType(namespace, 'all')\">所有实例\n                                    <span class=\"badge\" ng-bind=\"namespace.instancesCount\"></span>\n                                </button>\n                            </div>\n                            <button class=\"btn btn-default btn-sm\"\n                                    data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"刷新列表\"\n                                    ng-click=\"refreshInstancesInfo(namespace)\">\n                                <img src=\"../../img/refresh.png\"/>\n                            </button>\n                        </div>\n\n                    </div>\n                </div>\n\n                <!--latest release instances-->\n                <div class=\"panel-body\" ng-show=\"namespace.instanceViewType == 'latest_release'\">\n\n                    <div class=\"panel-default\" ng-if=\"namespace.latestReleaseInstances.total > 0\">\n                        <div class=\"panel-heading\">\n                            <a target=\"_blank\" data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"查看配置\"\n                               href=\"/config/history.html?#/appid={{appId}}&env={{env}}&clusterName={{cluster}}&namespaceName={{namespace.baseInfo.namespaceName}}&releaseId={{namespace.latestRelease.id}}\">\n                                {{namespace.latestRelease.name}}\n                            </a>\n                        </div>\n                        <table class=\"table table-bordered table-striped\">\n                            <thead>\n                            <tr>\n                                <td>App ID</td>\n                                <td>Cluster Name</td>\n                                <td>Data Center</td>\n                                <td>IP</td>\n                                <td>配置获取时间</td>\n                            </tr>\n                            </thead>\n                            <tbody>\n                            <tr ng-repeat=\"instance in namespace.latestReleaseInstances.content\">\n                                <td width=\"20%\" ng-bind=\"instance.appId\"></td>\n                                <td width=\"20%\" ng-bind=\"instance.clusterName\"></td>\n                                <td width=\"20%\" ng-bind=\"instance.dataCenter\"></td>\n                                <td width=\"20%\" ng-bind=\"instance.ip\"></td>\n                                <td width=\"20%\">{{instance.configs && instance.configs.length ?\n                                    (instance.configs[0].releaseDeliveryTime | date: 'yyyy-MM-dd HH:mm:ss') : ''}}\n                                </td>\n                            </tr>\n                            </tbody>\n                        </table>\n                        <div class=\"row text-center\"\n                             ng-show=\"namespace.latestReleaseInstances.content.length < namespace.latestReleaseInstances.total\">\n                            <button class=\"btn btn-default\" ng-click=\"loadInstanceInfo(namespace)\">加载更多</button>\n\n                        </div>\n                    </div>\n\n                    <div class=\"text-center\" ng-if=\"namespace.latestReleaseInstances.total == 0\">\n                        无实例信息\n                    </div>\n                </div>\n\n                <!--not latest release instances-->\n                <div class=\"panel-body\" ng-show=\"namespace.instanceViewType == 'not_latest_release'\">\n                    <div class=\"panel-default\"\n                         ng-if=\"namespace.instancesCount - namespace.latestReleaseInstances.total > 0\"\n                         ng-repeat=\"release in namespace.notLatestReleases\">\n                        <div class=\"panel-heading\">\n                            <a target=\"_blank\" data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"查看配置\"\n                               href=\"/config/history.html?#/appid={{appId}}&env={{env}}&clusterName={{cluster}}&namespaceName={{namespace.baseInfo.namespaceName}}&releaseId={{release.id}}\">\n                                {{release.name}}\n                            </a>\n\n                        </div>\n                        <table class=\"table table-bordered table-striped\">\n                            <thead>\n                            <tr>\n                                <td>App ID</td>\n                                <td>Cluster Name</td>\n                                <td>Data Center</td>\n                                <td>IP</td>\n                                <td>配置获取时间</td>\n                            </tr>\n                            </thead>\n                            <tbody>\n                            <tr ng-repeat=\"instance in namespace.notLatestReleaseInstances[release.id]\">\n                                <td width=\"20%\" ng-bind=\"instance.appId\"></td>\n                                <td width=\"20%\" ng-bind=\"instance.clusterName\"></td>\n                                <td width=\"20%\" ng-bind=\"instance.dataCenter\"></td>\n                                <td width=\"20%\" ng-bind=\"instance.ip\"></td>\n                                <td width=\"20%\">{{instance.configs && instance.configs.length ?\n                                    (instance.configs[0].releaseDeliveryTime | date: 'yyyy-MM-dd HH:mm:ss') : ''}}\n                                </td>\n                            </tr>\n                            </tbody>\n                        </table>\n                    </div>\n                    <div class=\"text-center\"\n                         ng-if=\"namespace.instancesCount - namespace.latestReleaseInstances.total == 0\">\n                        无实例信息\n                    </div>\n                </div>\n\n                <!--all instances-->\n                <div class=\"panel-body\" ng-show=\"namespace.instanceViewType == 'all'\">\n                    <div class=\"panel-default\" ng-if=\"namespace.instancesCount > 0\">\n                        <table class=\"table table-bordered table-striped\" ng-if=\"namespace.allInstances\">\n                            <thead>\n                            <tr>\n                                <td>App ID</td>\n                                <td>Cluster Name</td>\n                                <td>Data Center</td>\n                                <td>IP</td>\n                            </tr>\n                            </thead>\n                            <tbody>\n                            <tr ng-repeat=\"instance in namespace.allInstances\">\n                                <td width=\"25%\" ng-bind=\"instance.appId\"></td>\n                                <td width=\"25%\" ng-bind=\"instance.clusterName\"></td>\n                                <td width=\"25%\" ng-bind=\"instance.dataCenter\"></td>\n                                <td width=\"25%\" ng-bind=\"instance.ip\"></td>\n                            </tr>\n                            </tbody>\n                        </table>\n                        <div class=\"row text-center\" ng-show=\"namespace.allInstances.length < namespace.instancesCount\">\n                            <button class=\"btn btn-default\" ng-click=\"loadInstanceInfo(namespace)\">加载更多</button>\n                        </div>\n                    </div>\n                    <div class=\"text-center\" ng-if=\"namespace.instancesCount == 0\">\n                        无实例信息\n                    </div>\n                </div>\n            </div>\n        </section>\n    </div>\n\n</section>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/views/component/namespace-panel.html",
    "content": "<section class=\"panel namespace-panel\" ng-class=\"{'hidden': !namespace.show}\">\n    <!--public or link label-->\n    <ng-include src=\"'views/component/namespace-panel-header.html'\"></ng-include>\n\n    <ng-include src=\"'views/component/namespace-panel-master-tab.html'\"></ng-include>\n\n    <!--branch panel body-->\n    <ng-include src=\"'views/component/namespace-panel-branch-tab.html'\"></ng-include>\n\n</section>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/views/component/publish-deny-modal.html",
    "content": "<div class=\"modal fade\" id=\"publishDenyModal\" tabindex=\"-1\" role=\"dialog\">\n    <div class=\"modal-dialog\" role=\"document\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header panel-primary\">\n                <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\">\n                    <span aria-hidden=\"true\">&times;</span></button>\n                <h4 class=\"modal-title\">发布受限</h4>\n            </div>\n            <div class=\"modal-body\">\n                您不能发布哟~{{env}}环境配置的编辑和发布必须为不同的人，请找另一个具有当前namespace发布权的人操作发布~\n                <span ng-if=\"toReleaseNamespace.isEmergencyPublishAllowed\">\n                    <br><br><small>（如果是非工作时间或者特殊情况，您可以通过点击<mark>紧急发布</mark>按钮进行发布）</small>\n                </span>\n\n            </div>\n            <div class=\"modal-footer\">\n                <button type=\"button\" class=\"btn btn-danger\" data-dismiss=\"modal\"\n                        ng-if=\"toReleaseNamespace.isEmergencyPublishAllowed\"\n                        ng-click=\"emergencyPublish()\">\n                    紧急发布\n                </button>\n                <button type=\"button\" class=\"btn btn-primary\" data-dismiss=\"modal\">\n                    关闭\n                </button>\n            </div>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/views/component/release-modal.html",
    "content": "<form id=\"releaseModal\" class=\"modal fade form-horizontal\" name=\"releaseForm\" valdr-type=\"Release\"\n      ng-submit=\"release()\">\n    <div class=\"modal-dialog\" role=\"document\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header panel-primary\">\n                <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\"><span\n                        aria-hidden=\"true\">&times;</span></button>\n                <h4 class=\"modal-title\" ng-show=\"!toReleaseNamespace.isBranch\">发布\n                    <small>(只有发布过的配置才会被客户端获取到，此次发布只会作用于当前环境:{{env}})</small>\n                </h4>\n                <h4 class=\"modal-title\" ng-show=\"toReleaseNamespace.isBranch && !toReleaseNamespace.mergeAndPublish\">\n                    灰度发布\n                    <small>(灰度发布的配置只会作用于在灰度规则中配置的实例)</small>\n                </h4>\n                <h4 class=\"modal-title\" ng-show=\"toReleaseNamespace.isBranch && toReleaseNamespace.mergeAndPublish\">\n                    全量发布\n                    <small>(全量发布的配置会作用于全部的实例)</small>\n                </h4>\n\n            </div>\n\n            <div class=\"release modal-body\">\n\n                <div class=\"form-group\">\n                    <div class=\"col-sm-2 control-label\" ng-if=\"!toReleaseNamespace.isPropertiesFormat\">\n                        <div class=\"row\">\n                            <div class=\"btn-group btn-group-xs\" style=\"padding-right: 10px\" role=\"group\">\n                                <button type=\"button\" class=\"btn btn-default\"\n                                        ng-class=\"{active:releaseChangeViewType=='change'}\"\n                                        ng-click=\"switchReleaseChangeViewType('change')\">查看变更\n                                </button>\n                                <button type=\"button\" class=\"btn btn-default\"\n                                        ng-class=\"{active:releaseChangeViewType=='release'}\"\n                                        ng-click=\"switchReleaseChangeViewType('release')\">发布的值\n                                </button>\n                            </div>\n                        </div>\n                    </div>\n                    <label class=\"col-sm-2 control-label\" ng-if=\"toReleaseNamespace.isPropertiesFormat\">Changes</label>\n\n                    <div class=\"col-sm-10\"\n                         ng-if=\"(!toReleaseNamespace.isBranch && toReleaseNamespace.itemModifiedCnt)\n                                    || (toReleaseNamespace.isBranch && toReleaseNamespace.itemModifiedCnt)\n                                    || (toReleaseNamespace.isBranch && toReleaseNamespace.mergeAndPublish && toReleaseNamespace.branchItems.length)\"\n                         valdr-form-group>\n\n                        <!--properties format-->\n                        <!--normal release-->\n                        <table class=\"table table-bordered table-striped text-center table-hover\"\n                               ng-if=\"toReleaseNamespace.isPropertiesFormat && !toReleaseNamespace.isBranch\">\n                            <thead>\n                            <tr>\n                                <th>\n                                    Key\n                                </th>\n                                <th>\n                                    发布的值\n                                </th>\n                                <th>\n                                    未发布的值\n                                </th>\n                                <th>\n                                    修改人\n                                </th>\n                                <th>\n                                    修改时间\n                                </th>\n                            </tr>\n                            </thead>\n                            <tbody>\n                            <tr ng-repeat=\"config in toReleaseNamespace.items\"\n                                ng-if=\"config.item.key && config.isModified\">\n                                <td width=\"20%\" title=\"{{config.item.key}}\">\n                                    <span ng-bind=\"config.item.key\"></span>\n                                     <span class=\"label label-success\" ng-if=\"config.isModified && !config.oldValue\"\n                                           data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"新增的配置\">新</span>\n                                    <span class=\"label label-info\"\n                                          ng-if=\"config.isModified && config.oldValue && !config.isDeleted\"\n                                          data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"修改的配置\">改</span>\n                                    <span class=\"label label-danger\" ng-if=\"config.isDeleted\"\n                                          data-tooltip=\"tooltip\" data-placement=\"bottom\" title=\"删除的配置\">删</span>\n                                </td>\n                                <td width=\"25%\" title=\"{{config.oldValue}}\">\n                                    <span ng-bind=\"config.oldValue\"></span>\n                                </td>\n                                <td width=\"25%\" title=\"{{config.newValue}}\">\n                                    <span ng-bind=\"config.newValue\"></span>\n                                </td>\n                                <td width=\"15%\" ng-bind=\"config.item.dataChangeLastModifiedBy\">\n                                </td>\n                                <td width=\"15%\"\n                                    ng-bind=\"config.item.dataChangeLastModifiedTime | date: 'yyyy-MM-dd HH:mm:ss'\">\n                                </td>\n                            </tr>\n                            </tbody>\n                        </table>\n\n                        <!--branch gray release-->\n                        <table class=\"table table-bordered table-striped text-center table-hover\"\n                               ng-if=\"toReleaseNamespace.isPropertiesFormat &&\n                               toReleaseNamespace.isBranch && !toReleaseNamespace.mergeAndPublish\">\n                            <thead>\n                            <tr>\n                                <th>\n                                    Key\n                                </th>\n                                <th>\n                                    主版本值\n                                </th>\n                                <th>\n                                    灰度版本发布的值\n                                </th>\n                                <th>\n                                    灰度版本未发布的值\n                                </th>\n                                <th>\n                                    修改人\n                                </th>\n                                <th>\n                                    修改时间\n                                </th>\n                            </tr>\n                            </thead>\n                            <tbody>\n                            <tr ng-repeat=\"config in toReleaseNamespace.branchItems\"\n                                ng-if=\"config.isModified || config.isDeleted\">\n                                <td width=\"15%\" title=\"{{config.item.key}}\">\n                                    <span ng-bind=\"config.item.key\"></span>\n                                        <span class=\"label label-danger\"\n                                              ng-show=\"config.isDeleted\">删</span>\n                                </td>\n                                <td width=\"20%\" title=\"{{config.masterReleaseValue}}\">\n                                    <span ng-bind=\"config.masterReleaseValue\"></span>\n                                </td>\n                                <td width=\"20%\" title=\"{{config.oldValue}}\">\n                                    <span ng-bind=\"config.oldValue\"></span>\n                                </td>\n                                <td width=\"20%\" title=\"{{config.newValue}}\">\n                                    <span ng-bind=\"config.newValue\"></span>\n                                </td>\n                                <td width=\"10%\" ng-bind=\"config.item.dataChangeLastModifiedBy\">\n                                </td>\n                                <td width=\"15%\"\n                                    ng-bind=\"config.item.dataChangeLastModifiedTime | date: 'yyyy-MM-dd HH:mm:ss'\">\n                                </td>\n                            </tr>\n                            </tbody>\n                        </table>\n\n                        <!--branch updateAndPublish and publish-->\n                        <table class=\"table table-bordered table-striped text-center table-hover\"\n                               ng-if=\"toReleaseNamespace.isPropertiesFormat &&\n                               toReleaseNamespace.isBranch && toReleaseNamespace.mergeAndPublish\">\n                            <thead>\n                            <tr>\n                                <th>\n                                    Key\n                                </th>\n                                <th ng-if=\"toReleaseNamespace.isBranch\">\n                                    主版本值\n                                </th>\n                                <th ng-if=\"toReleaseNamespace.isBranch && toReleaseNamespace.mergeAndPublish\">\n                                    灰度版本的值\n                                </th>\n                                <th ng-if=\"!toReleaseNamespace.isBranch || !toReleaseNamespace.mergeAndPublish\">\n                                    发布的值\n                                </th>\n                                <th ng-if=\"!toReleaseNamespace.isBranch || !toReleaseNamespace.mergeAndPublish\">\n                                    未发布的值\n                                </th>\n                                <th>\n                                    修改人\n                                </th>\n                                <th>\n                                    修改时间\n                                </th>\n                            </tr>\n                            </thead>\n                            <tbody>\n                            <tr ng-repeat=\"config in toReleaseNamespace.branchItems\"\n                                ng-if=\"!config.isDeleted\">\n                                <td width=\"20%\" title=\"{{config.item.key}}\">\n                                    <span ng-bind=\"config.item.key\"></span>\n                                </td>\n                                <td width=\"25%\" title=\"{{config.masterReleaseValue}}\">\n                                    <span ng-bind=\"config.masterReleaseValue\"></span>\n                                </td>\n                                <td width=\"25%\" title=\"{{config.item.value}}\">\n                                    <span ng-bind=\"config.item.value\"></span>\n                                </td>\n                                <td width=\"15%\" ng-bind=\"config.item.dataChangeLastModifiedBy\">\n                                </td>\n                                <td width=\"15%\"\n                                    ng-bind=\"config.item.dataChangeLastModifiedTime | date: 'yyyy-MM-dd HH:mm:ss'\">\n                                </td>\n                            </tr>\n                            </tbody>\n                        </table>\n\n                        <!--file format -->\n                        <div ng-repeat=\"item in toReleaseNamespace.items\"\n                             ng-if=\"!toReleaseNamespace.isPropertiesFormat\"\n                             ng-show=\"releaseChangeViewType=='change'\">\n                            <apollodiff old-str=\"item.oldValue\" new-str=\"item.newValue\"\n                                        apollo-id=\"'releaseStrDiff'\"></apollodiff>\n                        </div>\n                        <div ng-repeat=\"item in toReleaseNamespace.items\"\n                             ng-if=\"!toReleaseNamespace.isPropertiesFormat\"\n                             ng-show=\"releaseChangeViewType=='release'\">\n                                        <textarea class=\"form-control no-radius\" rows=\"20\"\n                                                  ng-disabled=\"true\" ng-show=\"item.newValue\" ng-bind=\"item.newValue\">\n                                        </textarea>\n                        </div>\n\n                    </div>\n                    <div class=\"col-sm-5\"\n                         ng-show=\"(!toReleaseNamespace.isBranch && !toReleaseNamespace.itemModifiedCnt)\"\n                         valdr-form-group>\n                        <label class=\"form-control-static\">\n                            配置没有变化\n                        </label>\n                    </div>\n                    <div class=\"col-sm-5\"\n                         ng-show=\"(toReleaseNamespace.isBranch && !toReleaseNamespace.mergeAndPublish && !toReleaseNamespace.itemModifiedCnt)\"\n                         valdr-form-group>\n                        <label class=\"form-control-static\">\n                            灰度配置没有变化\n                        </label>\n                    </div>\n                    <div class=\"col-sm-5\"\n                         ng-show=\"(toReleaseNamespace.isBranch && toReleaseNamespace.mergeAndPublish && toReleaseNamespace.branchItems.length == 0)\"\n                         valdr-form-group>\n                        <label class=\"form-control-static\">\n                            没有灰度的配置项\n                        </label>\n                    </div>\n\n                </div>\n                <div class=\"form-group\">\n                    <label class=\"col-sm-2 control-label\">\n                        <apollorequiredfield></apollorequiredfield>\n                        Release Name</label>\n                    <div class=\"col-sm-5\" valdr-form-group>\n                        <input type=\"text\" name=\"releaseName\" class=\"form-control\"\n                               placeholder=\"input release name\"\n                               ng-model=\"toReleaseNamespace.releaseTitle\" ng-required=\"true\">\n                    </div>\n                </div>\n                <div class=\"form-group\">\n                    <label class=\"col-sm-2 control-label\">Comment</label>\n                    <div class=\"col-sm-10\" valdr-form-group>\n                                            <textarea rows=\"4\" name=\"comment\" class=\"form-control\"\n                                                      style=\"margin-top: 15px;\"\n                                                      ng-model=\"releaseComment\"\n                                                      placeholder=\"Add an optional extended description...\"></textarea>\n                    </div>\n                </div>\n\n\n            </div>\n\n            <div class=\"modal-footer\">\n                <button type=\"button\" class=\"btn btn-default\" data-dismiss=\"modal\">取消</button>\n                <button type=\"submit\" class=\"btn btn-primary\"\n                        ng-disabled=\"releaseForm.$invalid || releaseBtnDisabled\n                        || (toReleaseNamespace.isBranch && toReleaseNamespace.mergeAndPublish && toReleaseNamespace.branchItems.length == 0)\">\n                    发布\n                </button>\n            </div>\n        </div>\n    </div>\n</form>\n\n\n\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/views/component/rollback-modal.html",
    "content": "<form id=\"rollbackModal\" class=\"modal fade form-horizontal\"\n      ng-submit=\"showRollbackAlertDialog()\">\n    <div class=\"modal-dialog\" role=\"document\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header panel-primary\">\n                <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\"><span\n                        aria-hidden=\"true\">&times;</span></button>\n                <div class=\"modal-title text-center\">\n                    <span style=\"font-size: 18px;\" ng-bind=\"toRollbackNamespace.firstRelease.name\"></span>\n                    <span style=\"font-size: 18px;\"> &nbsp;回滚到&nbsp;</span>\n                    <span style=\"font-size: 18px;\" ng-bind=\"toRollbackNamespace.secondRelease.name\"></span>\n                </div>\n            </div>\n            <div class=\"modal-body\">\n                <div class=\"alert alert-warning\" role=\"alert\">\n                    此操作将会回滚到上一个发布版本，且当前版本作废，但不影响正在修改的配置。可在发布历史页面查看当前生效的版本\n                    <a target=\"_blank\"\n                       href=\"/config/history.html?#/appid={{appId}}&env={{env}}&clusterName={{toRollbackNamespace.baseInfo.clusterName}}&namespaceName={{toRollbackNamespace.baseInfo.namespaceName}}\">点击查看</a>\n                </div>\n\n                <div class=\"form-group\" style=\"margin-top: 15px;\">\n                    <!--properties format-->\n                    <div class=\"col-sm-12\"\n                         ng-if=\"toRollbackNamespace.releaseCompareResult.length > 0 && toRollbackNamespace.isPropertiesFormat\">\n                        <table class=\"table table-bordered table-striped text-center table-hover\"\n                               ng-if=\"toRollbackNamespace.isPropertiesFormat\">\n                            <thead>\n                            <tr>\n                                <th>\n                                    Type\n                                </th>\n                                <th>\n                                    Key\n                                </th>\n                                <th>\n                                    回滚前\n                                </th>\n                                <th>\n                                    回滚后\n                                </th>\n                            </tr>\n                            </thead>\n                            <tbody>\n\n                            <tr ng-repeat=\"change in toRollbackNamespace.releaseCompareResult\">\n                                <td width=\"10%\">\n                                    <span ng-show=\"change.type == 'ADDED'\">新增</span>\n                                    <span ng-show=\"change.type == 'MODIFIED'\">更新</span>\n                                    <span ng-show=\"change.type == 'DELETED'\">删除</span>\n                                </td>\n                                <td width=\"20%\" ng-bind=\"change.entity.firstEntity.key\">\n\n                                </td>\n                                <td width=\"35%\" ng-bind=\"change.entity.firstEntity.value\">\n                                </td>\n                                <td width=\"35%\" ng-bind=\"change.entity.secondEntity.value\">\n                                </td>\n                            </tr>\n                            </tbody>\n                        </table>\n                    </div>\n\n                    <!--file format -->\n                    <div class=\"col-sm-12\"\n                         ng-if=\"toRollbackNamespace.releaseCompareResult.length > 0 && !toRollbackNamespace.isPropertiesFormat\">\n                        <div ng-repeat=\"change in toRollbackNamespace.releaseCompareResult\"\n                             ng-if=\"!toRollbackNamespace.isPropertiesFormat\">\n                            <h5>回滚前</h5>\n                                        <textarea class=\"form-control no-radius\" rows=\"20\"\n                                                  ng-disabled=\"true\" ng-bind=\"change.entity.firstEntity.value\">\n                                            </textarea>\n                            <hr>\n                            <h5>回滚后</h5>\n                                        <textarea class=\"form-control no-radius\" rows=\"20\"\n                                                  ng-disabled=\"true\" ng-bind=\"change.entity.secondEntity.value\">\n                                            </textarea>\n                        </div>\n\n                    </div>\n                    <div class=\"col-sm-12 text-center\" ng-if=\"toRollbackNamespace.releaseCompareResult.length == 0\">\n                        <h4>\n                            配置没有变化\n                        </h4>\n                    </div>\n                </div>\n\n\n            </div>\n            <div class=\"modal-footer\">\n                <button type=\"button\" class=\"btn btn-default\" data-dismiss=\"modal\">取消</button>\n                <button type=\"submit\" class=\"btn btn-danger\"\n                        ng-disabled=\"toRollbackNamespace.rollbackBtnDisabled\">回滚\n                </button>\n            </div>\n        </div>\n    </div>\n\n</form>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/views/component/show-text-modal.html",
    "content": "<div id=\"showTextModal\" class=\"modal fade\" tabindex=\"-1\" role=\"dialog\">\n    <div class=\"modal-dialog\">\n        <div class=\"modal-content no-radius\">\n            <div class=\"modal-header panel-primary\">\n                <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\"><span\n                        aria-hidden=\"true\">&times;</span></button>\n\n                <h4 class=\"modal-title\">查看</h4>\n            </div>\n            <pre class=\"modal-body no-radius\" style=\"margin-bottom: 0\"\n                 ng-show=\"!jsonObject\" ng-bind=\"text\">\n            </pre>\n            <pre class=\"modal-body no-radius\" style=\"margin-bottom: 0\"\n                 ng-show=\"jsonObject\" ng-bind=\"jsonObject | json:4\">\n            </pre>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/resources/static/views/component/user-selector.html",
    "content": "<select class=\"{{id}}\" style=\"width: 450px;\" ng-disabled=\"disabled\">\n</select>\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/scripts/shutdown.sh",
    "content": "#!/bin/bash\nSERVICE_NAME=apollo-portal\n\nif [[ -z \"$JAVA_HOME\" && -d /usr/java/latest/ ]]; then\n    export JAVA_HOME=/usr/java/latest/\nfi\n\ncd `dirname $0`/..\n\nif [[ ! -f $SERVICE_NAME\".jar\" && -d current ]]; then\n    cd current\nfi\n\nif [[ -f $SERVICE_NAME\".jar\" ]]; then\n  chmod a+x $SERVICE_NAME\".jar\"\n  ./$SERVICE_NAME\".jar\" stop\nfi\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/main/scripts/startup.sh",
    "content": "#!/bin/bash\nSERVICE_NAME=apollo-portal\n## Adjust log dir if necessary\nLOG_DIR=/opt/logs/100003173\n## Adjust server port if necessary\nSERVER_PORT=8080\n\n## Adjust memory settings if necessary\n#export JAVA_OPTS=\"-Xms2560m -Xmx2560m -Xss256k -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=384m -XX:NewSize=1536m -XX:MaxNewSize=1536m -XX:SurvivorRatio=8\"\n\n## Only uncomment the following when you are using server jvm\n#export JAVA_OPTS=\"$JAVA_OPTS -server -XX:-ReduceInitialCardMarks\"\n\n########### The following is the same for configservice, adminservice, portal ###########\nexport JAVA_OPTS=\"$JAVA_OPTS -XX:+UseParNewGC -XX:ParallelGCThreads=4 -XX:MaxTenuringThreshold=9 -XX:+UseConcMarkSweepGC -XX:+DisableExplicitGC -XX:+UseCMSInitiatingOccupancyOnly -XX:+ScavengeBeforeFullGC -XX:+UseCMSCompactAtFullCollection -XX:+CMSParallelRemarkEnabled -XX:CMSFullGCsBeforeCompaction=9 -XX:CMSInitiatingOccupancyFraction=60 -XX:+CMSClassUnloadingEnabled -XX:SoftRefLRUPolicyMSPerMB=0 -XX:+CMSPermGenSweepingEnabled -XX:CMSInitiatingPermOccupancyFraction=70 -XX:+ExplicitGCInvokesConcurrent -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCApplicationConcurrentTime -XX:+PrintHeapAtGC -XX:+HeapDumpOnOutOfMemoryError -XX:-OmitStackTraceInFastThrow -Duser.timezone=Asia/Shanghai -Dclient.encoding.override=UTF-8 -Dfile.encoding=UTF-8 -Djava.security.egd=file:/dev/./urandom\"\nexport JAVA_OPTS=\"$JAVA_OPTS -Dserver.port=$SERVER_PORT -Dlogging.file=$LOG_DIR/$SERVICE_NAME.log -Xloggc:$LOG_DIR/heap_trace.txt -XX:HeapDumpPath=$LOG_DIR/HeapDumpOnOutOfMemoryError/\"\n\nPATH_TO_JAR=$SERVICE_NAME\".jar\"\nSERVER_URL=\"http://localhost:$SERVER_PORT\"\n\nfunction checkPidAlive {\n    for i in `ls -t $SERVICE_NAME*.pid 2>/dev/null`\n    do\n        read pid < $i\n\n        result=$(ps -p \"$pid\")\n        if [ \"$?\" -eq 0 ]; then\n            return 0\n        else\n            printf \"\\npid - $pid just quit unexpectedly, please check logs under $LOG_DIR and /tmp for more information!\\n\"\n            exit 1;\n        fi\n    done\n\n    printf \"\\nNo pid file found, startup may failed. Please check logs under $LOG_DIR and /tmp for more information!\\n\"\n    exit 1;\n}\n\nif [ \"$(uname)\" == \"Darwin\" ]; then\n    windows=\"0\"\nelif [ \"$(expr substr $(uname -s) 1 5)\" == \"Linux\" ]; then\n    windows=\"0\"\nelif [ \"$(expr substr $(uname -s) 1 5)\" == \"MINGW\" ]; then\n    windows=\"1\"\nelse\n    windows=\"0\"\nfi\n\n# for Windows\nif [ \"$windows\" == \"1\" ] && [[ -n \"$JAVA_HOME\" ]] && [[ -x \"$JAVA_HOME/bin/java\" ]]; then\n    tmp_java_home=`cygpath -sw \"$JAVA_HOME\"`\n    export JAVA_HOME=`cygpath -u $tmp_java_home`\n    echo \"Windows new JAVA_HOME is: $JAVA_HOME\"\nfi\n\ncd `dirname $0`/..\n\nfor i in `ls $SERVICE_NAME-*.jar 2>/dev/null`\ndo\n    if [[ ! $i == *\"-sources.jar\" ]]\n    then\n        PATH_TO_JAR=$i\n        break\n    fi\ndone\n\nif [[ ! -f PATH_TO_JAR && -d current ]]; then\n    cd current\n    for i in `ls $SERVICE_NAME-*.jar 2>/dev/null`\n    do\n        if [[ ! $i == *\"-sources.jar\" ]]\n        then\n            PATH_TO_JAR=$i\n            break\n        fi\n    done\nfi\n\nif [[ -f $SERVICE_NAME\".jar\" ]]; then\n  rm -rf $SERVICE_NAME\".jar\"\nfi\n\nprintf \"$(date) ==== Starting ==== \\n\"\n\nln $PATH_TO_JAR $SERVICE_NAME\".jar\"\nchmod a+x $SERVICE_NAME\".jar\"\n./$SERVICE_NAME\".jar\" start\n\nrc=$?;\n\nif [[ $rc != 0 ]];\nthen\n    echo \"$(date) Failed to start $SERVICE_NAME.jar, return code: $rc\"\n    exit $rc;\nfi\n\ndeclare -i counter=0\ndeclare -i max_counter=48 # 48*5=240s\ndeclare -i total_time=0\n\nprintf \"Waiting for server startup\"\nuntil [[ (( counter -ge max_counter )) || \"$(curl -X GET --silent --connect-timeout 1 --max-time 2 --head $SERVER_URL | grep \"Coyote\")\" != \"\" ]];\ndo\n    printf \".\"\n    counter+=1\n    sleep 5\n\n    checkPidAlive\ndone\n\ntotal_time=counter*5\n\nif [[ (( counter -ge max_counter )) ]];\nthen\n    printf \"\\n$(date) Server failed to start in $total_time seconds!\\n\"\n    exit 1;\nfi\n\nprintf \"\\n$(date) Server started in $total_time seconds!\\n\"\n\nexit 0;\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/test/resources/application.properties",
    "content": "spring.datasource.url = jdbc:h2:mem:~/apolloportaldb;mode=mysql;DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=-1\nspring.jpa.hibernate.naming_strategy=org.hibernate.cfg.EJB3NamingStrategy\nspring.jpa.properties.hibernate.show_sql=true\nspring.h2.console.enabled = true\nspring.h2.console.settings.web-allow-others=true\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/test/resources/application.yml",
    "content": "server:\n  port: 8070\n  \nspring:\n  application:\n    name: apollo-portal\n\nlogging:\n  level:\n    org.springframework.cloud: 'DEBUG'\n  file: /opt/logs/100003173/apollo-portal.log\n  \napollo:\n  portal:\n    envs: local\n\n    \nendpoints:\n  health:\n    sensitive: false\n\nmanagement:\n  security:\n    enabled: false\n  health:\n    status:\n      order: DOWN, OUT_OF_SERVICE, UNKNOWN, UP \n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/test/resources/logback-test.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<configuration scan=\"true\">\n\t<appender name=\"CONSOLE\" class=\"ch.qos.logback.core.ConsoleAppender\">\n\t\t<encoder>\n\t\t\t<charset>utf-8</charset>\n\t\t\t<Pattern>[%p] %c - %m%n</Pattern>\n\t\t</encoder>\n\t</appender>\n\t<logger name=\"org.springframework.test\" level=\"OFF\" />\n\n\t<root level=\"INFO\">\n\t\t<appender-ref ref=\"CONSOLE\" />\n\t</root>\n\n</configuration>"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/test/resources/sql/appnamespaceservice/init-appnamespace.sql",
    "content": "INSERT INTO `appnamespace` (`Id`, `Name`, `AppId`, `Format`, `IsPublic`, `Comment`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_CreatedTime`, `DataChange_LastModifiedBy`, `DataChange_LastTime`)\nVALUES\n\t(139, 'FX.old.xml', '100003173', 'properties', 1, '', 0, 'zhanglea', '2016-07-11 10:00:58', 'zhanglea', '2016-07-11 10:00:58'),\n\t(140, 'SCC.song0711-03', 'song0711-01', 'properties', 1, '', 0, 'song_s', '2016-07-11 10:04:09', 'song_s', '2016-07-11 10:04:09'),\n\t(141, 'SCC.song0711-04', 'song0711-01', 'properties', 1, '', 0, 'song_s', '2016-07-11 10:06:29', 'song_s', '2016-07-11 10:06:29'),\n\t(142, 'application', 'song0711-02', 'properties', 1, 'default app namespace', 0, 'song_s', '2016-07-11 11:18:24', 'song_s', '2016-07-11 11:18:24'),\n\t(143, 'TFF.song0711-02', 'song0711-02', 'properties', 0, '', 0, 'song_s', '2016-07-11 11:15:11', 'song_s', '2016-07-11 11:15:11'),\n\t(144, 'datasourcexml', '100003173', 'xml', 1, '', 0, 'apollo', '2016-07-11 12:08:29', 'apollo', '2016-07-11 12:08:29'),\n\t(145, 'datasource.xml', '100003173', 'xml', 0, '', 0, 'apollo', '2016-07-11 12:09:30', 'apollo', '2016-07-11 12:09:30');\n\nINSERT INTO `app` (`AppId`, `Name`, `OrgId`, `OrgName`, `OwnerName`, `OwnerEmail`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)\nVALUES\n\t('1000', 'apollo-portal', 'FX', '框架', 'song_s', 'song_s@ctrip.com', 0, 'song_s', 'song_s');\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/test/resources/sql/cleanup.sql",
    "content": "delete from Permission;\ndelete from Role;\ndelete from RolePermission;\ndelete from UserRole;\ndelete from AppNamespace;\nDELETE FROM Favorite;\nDELETE FROM ServerConfig;\nDELETE FROM App;\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/test/resources/sql/favorites/favorites.sql",
    "content": "INSERT INTO `favorite` (`Id`, `UserId`, `AppId`, `Position`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_CreatedTime`, `DataChange_LastModifiedBy`, `DataChange_LastTime`)\nVALUES\n\t(18, 'apollo', 'test0621-03', 10000, 0, 'apollo', '2016-10-10 17:45:30', 'apollo', '2016-10-10 17:45:30'),\n\t(19, 'apollo', '100003173', 9999, 0, 'apollo', '2016-10-10 17:45:42', 'apollo', '2016-10-10 17:51:12'),\n\t(20, 'apollo', 'test0621-01', 10000, 00000000, 'apollo', '2016-10-10 17:50:57', 'apollo', '2016-10-10 17:50:57'),\n\t(21, 'apollo', 'test0621-04', 10000, 00000000, 'apollo', '2016-10-10 17:55:03', 'apollo', '2016-10-10 17:55:03'),\n\t(22, 'apollo2', 'test0621-04', 10000, 00000000, 'apollo', '2016-10-10 17:55:21', 'apollo', '2016-10-10 17:55:21'),\n\t(23, 'apollo3', 'test0621-04', 10000, 00000000, 'apollo', '2016-10-10 17:55:21', 'apollo', '2016-10-10 17:55:21');\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/test/resources/sql/permission/insert-test-consumerroles.sql",
    "content": "INSERT INTO `consumerrole` (`Id`, `ConsumerId`, `RoleId`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)\n  VALUES (890, 1, 990, 'someOperator', 'someOperator');\nINSERT INTO `consumerrole` (`Id`, `ConsumerId`, `RoleId`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)\n  VALUES (891, 2, 990, 'someOperator', 'someOperator');\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/test/resources/sql/permission/insert-test-permissions.sql",
    "content": "INSERT INTO `permission` (`Id`, `PermissionType`, `TargetId`) VALUES (990, 'somePermissionType', 'someTargetId');\nINSERT INTO `permission` (`Id`, `PermissionType`, `TargetId`) VALUES (991, 'anotherPermissionType', 'anotherTargetId');\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/test/resources/sql/permission/insert-test-rolepermissions.sql",
    "content": "INSERT INTO `rolepermission` (`Id`, `RoleId`, `PermissionId`) VALUES (990, 990, 990);\nINSERT INTO `rolepermission` (`Id`, `RoleId`, `PermissionId`) VALUES (991, 990, 991);\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/test/resources/sql/permission/insert-test-roles.sql",
    "content": "INSERT INTO `role` (`Id`, `RoleName`) VALUES (990, 'someRoleName');\nINSERT INTO `role` (`Id`, `RoleName`) VALUES (991, 'anotherRoleName');\n"
  },
  {
    "path": "open-config-center/apollo/apollo-portal/src/test/resources/sql/permission/insert-test-userroles.sql",
    "content": "INSERT INTO `userrole` (`Id`, `UserId`, `RoleId`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)\n  VALUES (990, 'someUser', 990, 'someOperator', 'someOperator');\nINSERT INTO `userrole` (`Id`, `UserId`, `RoleId`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)\n  VALUES (991, 'anotherUser', 990, 'someOperator', 'someOperator');\n"
  },
  {
    "path": "open-config-center/apollo/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" 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  <parent>\n    <groupId>com.open.capacity</groupId>\n    <artifactId>open-config-center</artifactId>\n    <version>0.0.1-SNAPSHOT</version>\n  </parent>\n  <groupId>com.ctrip.framework.apollo</groupId>\n  <artifactId>apollo</artifactId>\n  <packaging>pom</packaging>\n  <version>0.10.0-SNAPSHOT</version>\n  \n\t<properties>\n\t\t<java.version>1.8</java.version>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<spring-boot.version>1.3.8.RELEASE</spring-boot.version>\n\t\t<spring-cloud.version>1.2.3.RELEASE</spring-cloud.version>\n\t\t<!-- Plugins Version -->\n\t\t<maven-compiler-plugin.version>3.6.0</maven-compiler-plugin.version>\n\t\t<maven-surefire-plugin.version>2.19.1</maven-surefire-plugin.version>\n\t\t<maven-source-plugin.version>3.0.1</maven-source-plugin.version>\n\t\t<maven-jar-plugin.version>3.0.2</maven-jar-plugin.version>\n\t\t<maven-install-plugin.version>2.5.2</maven-install-plugin.version>\n\t\t<maven-deploy-plugin.version>2.8.2</maven-deploy-plugin.version>\n\t</properties>\n\n\t<modules>\n\t\t<module>apollo-core</module>\n\t\t<module>apollo-client</module>\n\t\t<module>apollo-common</module>\n\t\t<module>apollo-biz</module>\n\t\t<module>apollo-configservice</module>\n\t\t<module>apollo-adminservice</module>\n\t\t<module>apollo-portal</module>\n\t</modules>\n\n\t<dependencyManagement>\n\t\t<dependencies>\n\t\t\t<dependency>\n\t\t\t\t<groupId>com.ctrip.framework.apollo</groupId>\n\t\t\t\t<artifactId>apollo-core</artifactId>\n\t\t\t\t<version>${project.version}</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>com.ctrip.framework.apollo</groupId>\n\t\t\t\t<artifactId>apollo-common</artifactId>\n\t\t\t\t<version>${project.version}</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>com.ctrip.framework.apollo</groupId>\n\t\t\t\t<artifactId>apollo-biz</artifactId>\n\t\t\t\t<version>${project.version}</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>com.ctrip.framework.apollo</groupId>\n\t\t\t\t<artifactId>apollo-buildtools</artifactId>\n\t\t\t\t<version>${project.version}</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>com.ctrip.framework.apollo</groupId>\n\t\t\t\t<artifactId>apollo-configservice</artifactId>\n\t\t\t\t<version>${project.version}</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>com.ctrip.framework.apollo</groupId>\n\t\t\t\t<artifactId>apollo-adminservice</artifactId>\n\t\t\t\t<version>${project.version}</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>com.ctrip.framework.apollo</groupId>\n\t\t\t\t<artifactId>apollo-portal</artifactId>\n\t\t\t\t<version>${project.version}</version>\n\t\t\t</dependency>\n\t\t\t<!-- ctrip internal dependencies, only used when ctrip profiles are enabled -->\n\t\t\t<dependency>\n\t\t\t\t<groupId>com.dianping.cat</groupId>\n\t\t\t\t<artifactId>cat-client</artifactId>\n\t\t\t\t<version>2.2.3</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>com.ctrip.platform</groupId>\n\t\t\t\t<artifactId>ctrip-dal-client</artifactId>\n\t\t\t\t<version>1.0.2</version>\n\t\t\t\t<exclusions>\n\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t<artifactId>logback-core</artifactId>\n\t\t\t\t\t\t<groupId>ch.qos.logback</groupId>\n\t\t\t\t\t</exclusion>\n\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t<artifactId>logback-classic</artifactId>\n\t\t\t\t\t\t<groupId>ch.qos.logback</groupId>\n\t\t\t\t\t</exclusion>\n\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t<groupId>commons-logging</groupId>\n\t\t\t\t\t\t<artifactId>commons-logging</artifactId>\n\t\t\t\t\t</exclusion>\n\t\t\t\t\t<!-- duplicated with xpp3:xpp3_min -->\n\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t<groupId>xmlpull</groupId>\n\t\t\t\t\t\t<artifactId>xmlpull</artifactId>\n\t\t\t\t\t</exclusion>\n\t\t\t\t\t<!-- duplicated with bcpkix-jdk15on -->\n\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t<groupId>org.bouncycastle</groupId>\n\t\t\t\t\t\t<artifactId>bcprov-jdk16</artifactId>\n\t\t\t\t\t</exclusion>\n\t\t\t\t\t<!-- duplicated with hibernate-jpa-2.1-api -->\n\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t<groupId>javax.persistence</groupId>\n\t\t\t\t\t\t<artifactId>persistence-api</artifactId>\n\t\t\t\t\t</exclusion>\n\t\t\t\t</exclusions>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>com.ctrip.framework.clogging</groupId>\n\t\t\t\t<artifactId>clogging-agent</artifactId>\n\t\t\t\t<version>3.5.2</version>\n\t\t\t\t<exclusions>\n\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t<artifactId>logback-core</artifactId>\n\t\t\t\t\t\t<groupId>ch.qos.logback</groupId>\n\t\t\t\t\t</exclusion>\n\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t<artifactId>logback-classic</artifactId>\n\t\t\t\t\t\t<groupId>ch.qos.logback</groupId>\n\t\t\t\t\t</exclusion>\n\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t<groupId>commons-logging</groupId>\n\t\t\t\t\t\t<artifactId>commons-logging</artifactId>\n\t\t\t\t\t</exclusion>\n\t\t\t\t</exclusions>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>com.ctrip.credis</groupId>\n\t\t\t\t<artifactId>credis</artifactId>\n\t\t\t\t<version>2.4.11</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>com.ctrip.framework</groupId>\n\t\t\t\t<artifactId>vi</artifactId>\n\t\t\t\t<version>0.9.1</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>com.ctrip.framework.apollo-sso</groupId>\n\t\t\t\t<artifactId>apollo-sso-ctrip</artifactId>\n\t\t\t\t<version>1.1.0</version>\n\t\t\t\t<exclusions>\n\t\t\t\t\t<!-- partially duplicated with org.ow2.asm:asm -->\n\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t<groupId>asm</groupId>\n\t\t\t\t\t\t<artifactId>asm</artifactId>\n\t\t\t\t\t</exclusion>\n\t\t\t\t</exclusions>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>com.ctrip.framework.apollo-ctrip-service</groupId>\n\t\t\t\t<artifactId>apollo-email-service</artifactId>\n\t\t\t\t<version>1.0.0</version>\n\t\t\t\t<exclusions>\n\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t<groupId>javax.servlet</groupId>\n\t\t\t\t\t\t<artifactId>javax.servlet-api</artifactId>\n\t\t\t\t\t</exclusion>\n\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t<groupId>commons-logging</groupId>\n\t\t\t\t\t\t<artifactId>commons-logging</artifactId>\n\t\t\t\t\t</exclusion>\n\t\t\t\t\t<!-- duplicated with commons-collections and commons-beanutils -->\n\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t<groupId>commons-beanutils</groupId>\n\t\t\t\t\t\t<artifactId>commons-beanutils-core</artifactId>\n\t\t\t\t\t</exclusion>\n\t\t\t\t</exclusions>\n\t\t\t</dependency>\n\t\t\t<!--third party -->\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.slf4j</groupId>\n\t\t\t\t<artifactId>slf4j-api</artifactId>\n\t\t\t\t<version>1.7.21</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>com.google.guava</groupId>\n\t\t\t\t<artifactId>guava</artifactId>\n\t\t\t\t<version>19.0</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>com.google.code.gson</groupId>\n\t\t\t\t<artifactId>gson</artifactId>\n\t\t\t\t<version>2.8.0</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>mysql</groupId>\n\t\t\t\t<artifactId>mysql-connector-java</artifactId>\n\t\t\t\t<version>5.1.39</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>com.google.inject</groupId>\n\t\t\t\t<artifactId>guice</artifactId>\n\t\t\t\t<version>4.1.0</version>\n\t\t\t</dependency>\n\t\t\t<!--for test -->\n\t\t\t<dependency>\n\t\t\t\t<groupId>com.h2database</groupId>\n\t\t\t\t<artifactId>h2</artifactId>\n\t\t\t\t<version>1.4.191</version>\n\t\t\t</dependency>\n\t\t\t<!-- declare Spring BOMs in order -->\n\t\t\t<dependency>\n\t\t\t\t<groupId>io.spring.platform</groupId>\n\t\t\t\t<artifactId>platform-bom</artifactId>\n\t\t\t\t<version>2.0.8.RELEASE</version>\n\t\t\t\t<type>pom</type>\n\t\t\t\t<scope>import</scope>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t\t<artifactId>spring-cloud-netflix</artifactId>\n\t\t\t\t<version>1.2.3.RELEASE</version>\n\t\t\t\t<type>pom</type>\n\t\t\t\t<scope>import</scope>\n\t\t\t</dependency>\n\t\t\t<!-- ctrip modified -->\n\t\t\t<!-- removed duplicated javax/persistence classes -->\n\t\t\t<dependency>\n\t\t\t\t<groupId>com.ctrip.3rdparty.tomcat.embed</groupId>\n\t\t\t\t<artifactId>tomcat-embed-core</artifactId>\n\t\t\t\t<version>8.0.37</version>\n\t\t\t\t<exclusions>\n\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t<groupId>org.apache.tomcat.embed</groupId>\n\t\t\t\t\t\t<artifactId>tomcat-embed-logging-juli</artifactId>\n\t\t\t\t\t</exclusion>\n\t\t\t\t</exclusions>\n\t\t\t</dependency>\n\t\t</dependencies>\n\t</dependencyManagement>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<pluginManagement>\n\t\t\t<plugins>\n\t\t\t\t<plugin>\n\t\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t\t<artifactId>maven-compiler-plugin</artifactId>\n\t\t\t\t\t<version>${maven-compiler-plugin.version}</version>\n\t\t\t\t\t<configuration>\n\t\t\t\t\t\t<source>${java.version}</source>\n\t\t\t\t\t\t<target>${java.version}</target>\n\t\t\t\t\t\t<encoding>${project.build.sourceEncoding}</encoding>\n\t\t\t\t\t</configuration>\n\t\t\t\t</plugin>\n \n\t\t\t\t<plugin>\n\t\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t\t\t<version>1.3.5.RELEASE</version>\n\t\t\t\t\t<executions>\n\t\t\t\t\t\t<execution>\n\t\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t\t<goal>repackage</goal>\n\t\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t</execution>\n\t\t\t\t\t</executions>\n\t\t\t\t</plugin>\n\t\t\t\t \n\t\t\t\t   \n\t\t\t\t<plugin>\n\t\t\t\t\t<groupId>org.codehaus.mojo</groupId>\n\t\t\t\t\t<artifactId>versions-maven-plugin</artifactId>\n\t\t\t\t\t<version>2.2</version>\n\t\t\t\t</plugin>\n\t\t\t\t<!-- Need to set releases.repo and snapshots.repo properties in your \n\t\t\t\t\t.m2/settings.xml -->\n\t\t\t</plugins>\n\t\t</pluginManagement>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-compiler-plugin</artifactId>\n\t\t\t</plugin>\n\t\t\t \n\t\t</plugins>\n\t\t<resources>\n\t\t\t<resource>\n\t\t\t\t<directory>src/main/resources</directory>\n\t\t\t\t<filtering>true</filtering>\n\t\t\t\t<includes>\n\t\t\t\t\t<include>**/*.yml</include>\n\t\t\t\t\t<include>**/*.yaml</include>\n\t\t\t\t\t<include>**/*.properties</include>\n\t\t\t\t\t<include>**/*.xml</include>\n\t\t\t\t</includes>\n\t\t\t</resource>\n\t\t\t<resource>\n\t\t\t\t<directory>src/main/resources</directory>\n\t\t\t\t<filtering>false</filtering>\n\t\t\t\t<excludes>\n\t\t\t\t\t<exclude>**/*.yml</exclude>\n\t\t\t\t\t<exclude>**/*.yaml</exclude>\n\t\t\t\t\t<exclude>**/*.properties</exclude>\n\t\t\t\t\t<exclude>**/*.xml</exclude>\n\t\t\t\t</excludes>\n\t\t\t</resource>\n\t\t</resources>\n\t</build>\n\t<profiles>\n\t\t<profile>\n\t\t\t<!-- for ctrip development -->\n\t\t\t<id>ctrip-dev</id>\n\t\t\t<properties>\n\t\t\t\t<package.environment>ctrip</package.environment>\n\t\t\t</properties>\n\t\t\t<dependencyManagement>\n\t\t\t\t<dependencies>\n\t\t\t\t\t<dependency>\n\t\t\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t\t\t\t\t<version>${spring-boot.version}</version>\n\t\t\t\t\t\t<exclusions>\n\t\t\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t\t\t<groupId>org.apache.tomcat.embed</groupId>\n\t\t\t\t\t\t\t\t<artifactId>tomcat-embed-logging-juli</artifactId>\n\t\t\t\t\t\t\t</exclusion>\n\t\t\t\t\t\t\t<!-- use ctrip modified version instead -->\n\t\t\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t\t\t<groupId>org.apache.tomcat.embed</groupId>\n\t\t\t\t\t\t\t\t<artifactId>tomcat-embed-core</artifactId>\n\t\t\t\t\t\t\t</exclusion>\n\t\t\t\t\t\t</exclusions>\n\t\t\t\t\t</dependency>\n\t\t\t\t\t<!-- eureka -->\n\t\t\t\t\t<dependency>\n\t\t\t\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t\t\t\t<artifactId>spring-cloud-starter-eureka</artifactId>\n\t\t\t\t\t\t<version>${spring-cloud.version}</version>\n\t\t\t\t\t\t<exclusions>\n\t\t\t\t\t\t\t<!-- already in java -->\n\t\t\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t\t\t<groupId>stax</groupId>\n\t\t\t\t\t\t\t\t<artifactId>stax-api</artifactId>\n\t\t\t\t\t\t\t</exclusion>\n\t\t\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t\t\t<groupId>javax.xml.stream</groupId>\n\t\t\t\t\t\t\t\t<artifactId>stax-api</artifactId>\n\t\t\t\t\t\t\t</exclusion>\n\t\t\t\t\t\t\t<!-- duplicated with spring-security-core -->\n\t\t\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t\t\t<groupId>org.springframework.security</groupId>\n\t\t\t\t\t\t\t\t<artifactId>spring-security-crypto</artifactId>\n\t\t\t\t\t\t\t</exclusion>\n\t\t\t\t\t\t\t<!-- duplicated with xpp3:xpp3_min -->\n\t\t\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t\t\t<groupId>xmlpull</groupId>\n\t\t\t\t\t\t\t\t<artifactId>xmlpull</artifactId>\n\t\t\t\t\t\t\t</exclusion>\n\t\t\t\t\t\t\t<!-- duplicated with netty-all -->\n\t\t\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t\t\t<groupId>io.netty</groupId>\n\t\t\t\t\t\t\t\t<artifactId>netty-codec-http</artifactId>\n\t\t\t\t\t\t\t</exclusion>\n\t\t\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t\t\t<groupId>io.netty</groupId>\n\t\t\t\t\t\t\t\t<artifactId>netty-buffer</artifactId>\n\t\t\t\t\t\t\t</exclusion>\n\t\t\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t\t\t<groupId>io.netty</groupId>\n\t\t\t\t\t\t\t\t<artifactId>netty-common</artifactId>\n\t\t\t\t\t\t\t</exclusion>\n\t\t\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t\t\t<groupId>io.netty</groupId>\n\t\t\t\t\t\t\t\t<artifactId>netty-transport-native-epoll</artifactId>\n\t\t\t\t\t\t\t</exclusion>\n\t\t\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t\t\t<groupId>io.netty</groupId>\n\t\t\t\t\t\t\t\t<artifactId>netty-transport</artifactId>\n\t\t\t\t\t\t\t</exclusion>\n\t\t\t\t\t\t\t<!-- duplicated with commons-collections and commons-beanutils -->\n\t\t\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t\t\t<groupId>commons-beanutils</groupId>\n\t\t\t\t\t\t\t\t<artifactId>commons-beanutils-core</artifactId>\n\t\t\t\t\t\t\t</exclusion>\n\t\t\t\t\t\t\t<!-- duplicated with spring-aop -->\n\t\t\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t\t\t<groupId>aopalliance</groupId>\n\t\t\t\t\t\t\t\t<artifactId>aopalliance</artifactId>\n\t\t\t\t\t\t\t</exclusion>\n\t\t\t\t\t\t</exclusions>\n\t\t\t\t\t</dependency>\n\t\t\t\t\t<!-- end of eureka -->\n\t\t\t\t</dependencies>\n\t\t\t</dependencyManagement>\n\t\t\t<dependencies>\n\t\t\t\t<dependency>\n\t\t\t\t\t<groupId>com.ctrip.3rdparty.tomcat.embed</groupId>\n\t\t\t\t\t<artifactId>tomcat-embed-core</artifactId>\n\t\t\t\t</dependency>\n\t\t\t</dependencies>\n\t\t</profile>\n\t \n\t\t<profile>\n\t\t \n\t\t\t<dependencyManagement>\n\t\t\t\t<dependencies>\n\t\t\t\t\t<dependency>\n\t\t\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t\t\t\t\t<version>${spring-boot.version}</version>\n\t\t\t\t\t\t<exclusions>\n\t\t\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t\t\t<groupId>org.apache.tomcat.embed</groupId>\n\t\t\t\t\t\t\t\t<artifactId>tomcat-embed-logging-juli</artifactId>\n\t\t\t\t\t\t\t</exclusion>\n\t\t\t\t\t\t\t<!-- use ctrip modified version instead -->\n\t\t\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t\t\t<groupId>org.apache.tomcat.embed</groupId>\n\t\t\t\t\t\t\t\t<artifactId>tomcat-embed-core</artifactId>\n\t\t\t\t\t\t\t</exclusion>\n\t\t\t\t\t\t</exclusions>\n\t\t\t\t\t</dependency>\n\t\t\t\t\t<!-- eureka -->\n\t\t\t\t\t<dependency>\n\t\t\t\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t\t\t\t<artifactId>spring-cloud-starter-eureka</artifactId>\n\t\t\t\t\t\t<version>${spring-cloud.version}</version>\n\t\t\t\t\t\t<exclusions>\n\t\t\t\t\t\t\t<!-- already in java -->\n\t\t\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t\t\t<groupId>stax</groupId>\n\t\t\t\t\t\t\t\t<artifactId>stax-api</artifactId>\n\t\t\t\t\t\t\t</exclusion>\n\t\t\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t\t\t<groupId>javax.xml.stream</groupId>\n\t\t\t\t\t\t\t\t<artifactId>stax-api</artifactId>\n\t\t\t\t\t\t\t</exclusion>\n\t\t\t\t\t\t\t<!-- duplicated with spring-security-core -->\n\t\t\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t\t\t<groupId>org.springframework.security</groupId>\n\t\t\t\t\t\t\t\t<artifactId>spring-security-crypto</artifactId>\n\t\t\t\t\t\t\t</exclusion>\n\t\t\t\t\t\t\t<!-- duplicated with xpp3:xpp3_min -->\n\t\t\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t\t\t<groupId>xmlpull</groupId>\n\t\t\t\t\t\t\t\t<artifactId>xmlpull</artifactId>\n\t\t\t\t\t\t\t</exclusion>\n\t\t\t\t\t\t\t<!-- duplicated with netty-all -->\n\t\t\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t\t\t<groupId>io.netty</groupId>\n\t\t\t\t\t\t\t\t<artifactId>netty-codec-http</artifactId>\n\t\t\t\t\t\t\t</exclusion>\n\t\t\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t\t\t<groupId>io.netty</groupId>\n\t\t\t\t\t\t\t\t<artifactId>netty-buffer</artifactId>\n\t\t\t\t\t\t\t</exclusion>\n\t\t\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t\t\t<groupId>io.netty</groupId>\n\t\t\t\t\t\t\t\t<artifactId>netty-common</artifactId>\n\t\t\t\t\t\t\t</exclusion>\n\t\t\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t\t\t<groupId>io.netty</groupId>\n\t\t\t\t\t\t\t\t<artifactId>netty-transport-native-epoll</artifactId>\n\t\t\t\t\t\t\t</exclusion>\n\t\t\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t\t\t<groupId>io.netty</groupId>\n\t\t\t\t\t\t\t\t<artifactId>netty-transport</artifactId>\n\t\t\t\t\t\t\t</exclusion>\n\t\t\t\t\t\t\t<!-- duplicated with commons-collections and commons-beanutils -->\n\t\t\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t\t\t<groupId>commons-beanutils</groupId>\n\t\t\t\t\t\t\t\t<artifactId>commons-beanutils-core</artifactId>\n\t\t\t\t\t\t\t</exclusion>\n\t\t\t\t\t\t\t<!-- duplicated with spring-aop -->\n\t\t\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t\t\t<groupId>aopalliance</groupId>\n\t\t\t\t\t\t\t\t<artifactId>aopalliance</artifactId>\n\t\t\t\t\t\t\t</exclusion>\n\t\t\t\t\t\t</exclusions>\n\t\t\t\t\t</dependency>\n\t\t\t\t\t<!-- end of eureka -->\n\t\t\t\t</dependencies>\n\t\t\t</dependencyManagement>\n\t\t\t<dependencies>\n\t\t\t\t<dependency>\n\t\t\t\t\t<groupId>com.dianping.cat</groupId>\n\t\t\t\t\t<artifactId>cat-client</artifactId>\n\t\t\t\t</dependency>\n\t\t\t\t<dependency>\n\t\t\t\t\t<groupId>com.ctrip.3rdparty.tomcat.embed</groupId>\n\t\t\t\t\t<artifactId>tomcat-embed-core</artifactId>\n\t\t\t\t</dependency>\n\t\t\t\t<dependency>\n\t\t\t\t\t<groupId>com.ctrip.framework.clogging</groupId>\n\t\t\t\t\t<artifactId>clogging-agent</artifactId>\n\t\t\t\t</dependency>\n\t\t\t\t<dependency>\n\t\t\t\t\t<groupId>com.ctrip.platform</groupId>\n\t\t\t\t\t<artifactId>ctrip-dal-client</artifactId>\n\t\t\t\t</dependency>\n\t\t\t</dependencies>\n\t\t</profile>\n\t</profiles>\n \n  \n</project>"
  },
  {
    "path": "open-config-center/apollo/scripts/build.bat",
    "content": "@echo off\n\nrem apollo config db info\nset apollo_config_db_url=\"jdbc:mysql://localhost:3306/ApolloConfigDB?characterEncoding=utf8\"\nset apollo_config_db_username=\"root\"\nset apollo_config_db_password=\"\"\n\nrem apollo portal db info\nset apollo_portal_db_url=\"jdbc:mysql://localhost:3306/ApolloPortalDB?characterEncoding=utf8\"\nset apollo_portal_db_username=\"root\"\nset apollo_portal_db_password=\"\"\n\nrem meta server url, different environments should have different meta server addresses\nset dev_meta=\"http://localhost:8080\"\nset fat_meta=\"http://someIp:8080\"\nset uat_meta=\"http://anotherIp:8080\"\nset pro_meta=\"http://yetAnotherIp:8080\"\n\nset META_SERVERS_OPTS=-Ddev_meta=%dev_meta% -Dfat_meta=%fat_meta% -Duat_meta=%uat_meta% -Dpro_meta=%pro_meta%\n\nrem =============== Please do not modify the following content =============== \nrem go to script directory\ncd \"%~dp0\"\n\ncd ..\n\nrem package config-service and admin-service\necho \"==== starting to build config-service and admin-service ====\"\n\ncall mvn clean package -DskipTests -pl apollo-configservice,apollo-adminservice -am -Dapollo_profile=github -Dspring_datasource_url=%apollo_config_db_url% -Dspring_datasource_username=%apollo_config_db_username% -Dspring_datasource_password=%apollo_config_db_password%\n\necho \"==== building config-service and admin-service finished ====\"\n\necho \"==== starting to build portal ====\"\n\ncall mvn clean package -DskipTests -pl apollo-portal -am -Dapollo_profile=github,auth -Dspring_datasource_url=%apollo_portal_db_url% -Dspring_datasource_username=%apollo_portal_db_username% -Dspring_datasource_password=%apollo_portal_db_password% %META_SERVERS_OPTS%\n\necho \"==== building portal finished ====\"\n\necho \"==== starting to build client ====\"\n\ncall mvn clean install -DskipTests -pl apollo-client -am %META_SERVERS_OPTS%\n\necho \"==== building client finished ====\"\n\npause\n"
  },
  {
    "path": "open-config-center/apollo/scripts/build.sh",
    "content": "#!/bin/sh\n\n# apollo config db info\napollo_config_db_url=jdbc:mysql://localhost:3306/ApolloConfigDB?characterEncoding=utf8\napollo_config_db_username=root\napollo_config_db_password=\n\n# apollo portal db info\napollo_portal_db_url=jdbc:mysql://localhost:3306/ApolloPortalDB?characterEncoding=utf8\napollo_portal_db_username=root\napollo_portal_db_password=\n\n# meta server url, different environments should have different meta server addresses\ndev_meta=http://localhost:8080\nfat_meta=http://someIp:8080\nuat_meta=http://anotherIp:8080\npro_meta=http://yetAnotherIp:8080\n\nMETA_SERVERS_OPTS=\"-Ddev_meta=$dev_meta -Dfat_meta=$fat_meta -Duat_meta=$uat_meta -Dpro_meta=$pro_meta\"\n\n# =============== Please do not modify the following content =============== #\n# go to script directory\ncd \"${0%/*}\"\n\ncd ..\n\n# package config-service and admin-service\necho \"==== starting to build config-service and admin-service ====\"\n\nmvn clean package -DskipTests -pl apollo-configservice,apollo-adminservice -am -Dapollo_profile=github -Dspring_datasource_url=$apollo_config_db_url -Dspring_datasource_username=$apollo_config_db_username -Dspring_datasource_password=$apollo_config_db_password\n\necho \"==== building config-service and admin-service finished ====\"\n\necho \"==== starting to build portal ====\"\n\nmvn clean package -DskipTests -pl apollo-portal -am -Dapollo_profile=github,auth -Dspring_datasource_url=$apollo_portal_db_url -Dspring_datasource_username=$apollo_portal_db_username -Dspring_datasource_password=$apollo_portal_db_password $META_SERVERS_OPTS\n\necho \"==== building portal finished ====\"\n\necho \"==== starting to build client ====\"\n\nmvn clean install -DskipTests -pl apollo-client -am $META_SERVERS_OPTS\n\necho \"==== building client finished ====\"\n\n"
  },
  {
    "path": "open-config-center/apollo/scripts/docker-quick-start/docker-compose.yml",
    "content": "version: '2'\n\nservices:\n  apollo-quick-start:\n    image: nobodyiam/apollo-quick-start\n    container_name: apollo-quick-start\n    depends_on:\n      - apollo-db\n    ports:\n      - \"8080:8080\"\n      - \"8070:8070\"\n    links:\n      - apollo-db\n\n  apollo-db:\n    image: mysql:5.7\n    container_name: apollo-db\n    environment:\n      TZ: Asia/Shanghai\n      MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'\n    depends_on:\n      - apollo-dbdata\n    ports:\n      - \"13306:3306\"\n    volumes:\n      - ./sql:/docker-entrypoint-initdb.d\n    volumes_from:\n      - apollo-dbdata\n\n  apollo-dbdata:\n    image: alpine:latest\n    container_name: apollo-dbdata\n    volumes:\n      - /var/lib/mysql\n"
  },
  {
    "path": "open-config-center/apollo/scripts/docker-quick-start/sql/apolloconfigdb.sql",
    "content": "/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;\n/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;\n/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;\n/*!40101 SET NAMES utf8 */;\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 */;\n\n# Create Database\n# ------------------------------------------------------------\nCREATE DATABASE IF NOT EXISTS ApolloConfigDB DEFAULT CHARACTER SET = utf8mb4;\n\nUse ApolloConfigDB;\n\n# Dump of table app\n# ------------------------------------------------------------\n\nDROP TABLE IF EXISTS `App`;\n\nCREATE TABLE `App` (\n  `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',\n  `AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID',\n  `Name` varchar(500) NOT NULL DEFAULT 'default' COMMENT '应用名',\n  `OrgId` varchar(32) NOT NULL DEFAULT 'default' COMMENT '部门Id',\n  `OrgName` varchar(64) NOT NULL DEFAULT 'default' COMMENT '部门名字',\n  `OwnerName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ownerName',\n  `OwnerEmail` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ownerEmail',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `AppId` (`AppId`(191)),\n  KEY `DataChange_LastTime` (`DataChange_LastTime`),\n  KEY `IX_Name` (`Name`(191))\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='应用表';\n\n\n\n# Dump of table appnamespace\n# ------------------------------------------------------------\n\nDROP TABLE IF EXISTS `AppNamespace`;\n\nCREATE TABLE `AppNamespace` (\n  `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',\n  `Name` varchar(32) NOT NULL DEFAULT '' COMMENT 'namespace名字，注意，需要全局唯一',\n  `AppId` varchar(32) NOT NULL DEFAULT '' COMMENT 'app id',\n  `Format` varchar(32) NOT NULL DEFAULT 'properties' COMMENT 'namespace的format类型',\n  `IsPublic` bit(1) NOT NULL DEFAULT b'0' COMMENT 'namespace是否为公共',\n  `Comment` varchar(64) NOT NULL DEFAULT '' COMMENT '注释',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT '' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `IX_AppId` (`AppId`),\n  KEY `Name_AppId` (`Name`,`AppId`),\n  KEY `DataChange_LastTime` (`DataChange_LastTime`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='应用namespace定义';\n\n\n\n# Dump of table audit\n# ------------------------------------------------------------\n\nDROP TABLE IF EXISTS `Audit`;\n\nCREATE TABLE `Audit` (\n  `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',\n  `EntityName` varchar(50) NOT NULL DEFAULT 'default' COMMENT '表名',\n  `EntityId` int(10) unsigned DEFAULT NULL COMMENT '记录ID',\n  `OpName` varchar(50) NOT NULL DEFAULT 'default' COMMENT '操作类型',\n  `Comment` varchar(500) DEFAULT NULL COMMENT '备注',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `DataChange_LastTime` (`DataChange_LastTime`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='日志审计表';\n\n\n\n# Dump of table cluster\n# ------------------------------------------------------------\n\nDROP TABLE IF EXISTS `Cluster`;\n\nCREATE TABLE `Cluster` (\n  `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',\n  `Name` varchar(32) NOT NULL DEFAULT '' COMMENT '集群名字',\n  `AppId` varchar(32) NOT NULL DEFAULT '' COMMENT 'App id',\n  `ParentClusterId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '父cluster',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT '' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `IX_AppId_Name` (`AppId`,`Name`),\n  KEY `IX_ParentClusterId` (`ParentClusterId`),\n  KEY `DataChange_LastTime` (`DataChange_LastTime`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='集群';\n\n\n\n# Dump of table commit\n# ------------------------------------------------------------\n\nDROP TABLE IF EXISTS `Commit`;\n\nCREATE TABLE `Commit` (\n  `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',\n  `ChangeSets` longtext NOT NULL COMMENT '修改变更集',\n  `AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID',\n  `ClusterName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ClusterName',\n  `NamespaceName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'namespaceName',\n  `Comment` varchar(500) DEFAULT NULL COMMENT '备注',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `DataChange_LastTime` (`DataChange_LastTime`),\n  KEY `AppId` (`AppId`(191)),\n  KEY `ClusterName` (`ClusterName`(191)),\n  KEY `NamespaceName` (`NamespaceName`(191))\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='commit 历史表';\n\n# Dump of table grayreleaserule\n# ------------------------------------------------------------\n\nDROP TABLE IF EXISTS `GrayReleaseRule`;\n\nCREATE TABLE `GrayReleaseRule` (\n  `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',\n  `AppId` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'AppID',\n  `ClusterName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'Cluster Name',\n  `NamespaceName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'Namespace Name',\n  `BranchName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'branch name',\n  `Rules` varchar(16000) DEFAULT '[]' COMMENT '灰度规则',\n  `ReleaseId` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '灰度对应的release',\n  `BranchStatus` tinyint(2) DEFAULT '1' COMMENT '灰度分支状态: 0:删除分支,1:正在使用的规则 2：全量发布',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `DataChange_LastTime` (`DataChange_LastTime`),\n  KEY `IX_Namespace` (`AppId`,`ClusterName`,`NamespaceName`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='灰度规则表';\n\n\n# Dump of table instance\n# ------------------------------------------------------------\n\nDROP TABLE IF EXISTS `Instance`;\n\nCREATE TABLE `Instance` (\n  `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',\n  `AppId` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'AppID',\n  `ClusterName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'ClusterName',\n  `DataCenter` varchar(64) NOT NULL DEFAULT 'default' COMMENT 'Data Center Name',\n  `Ip` varchar(32) NOT NULL DEFAULT '' COMMENT 'instance ip',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  UNIQUE KEY `IX_UNIQUE_KEY` (`AppId`,`ClusterName`,`Ip`,`DataCenter`),\n  KEY `IX_IP` (`Ip`),\n  KEY `IX_DataChange_LastTime` (`DataChange_LastTime`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='使用配置的应用实例';\n\n\n\n# Dump of table instanceconfig\n# ------------------------------------------------------------\n\nDROP TABLE IF EXISTS `InstanceConfig`;\n\nCREATE TABLE `InstanceConfig` (\n  `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',\n  `InstanceId` int(11) unsigned DEFAULT NULL COMMENT 'Instance Id',\n  `ConfigAppId` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'Config App Id',\n  `ConfigClusterName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'Config Cluster Name',\n  `ConfigNamespaceName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'Config Namespace Name',\n  `ReleaseKey` varchar(64) NOT NULL DEFAULT '' COMMENT '发布的Key',\n  `ReleaseDeliveryTime` timestamp NULL DEFAULT NULL COMMENT '配置获取时间',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  UNIQUE KEY `IX_UNIQUE_KEY` (`InstanceId`,`ConfigAppId`,`ConfigNamespaceName`),\n  KEY `IX_ReleaseKey` (`ReleaseKey`),\n  KEY `IX_DataChange_LastTime` (`DataChange_LastTime`),\n  KEY `IX_Valid_Namespace` (`ConfigAppId`,`ConfigClusterName`,`ConfigNamespaceName`,`DataChange_LastTime`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='应用实例的配置信息';\n\n\n\n# Dump of table item\n# ------------------------------------------------------------\n\nDROP TABLE IF EXISTS `Item`;\n\nCREATE TABLE `Item` (\n  `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',\n  `NamespaceId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '集群NamespaceId',\n  `Key` varchar(128) NOT NULL DEFAULT 'default' COMMENT '配置项Key',\n  `Value` longtext NOT NULL COMMENT '配置项值',\n  `Comment` varchar(1024) DEFAULT '' COMMENT '注释',\n  `LineNum` int(10) unsigned DEFAULT '0' COMMENT '行号',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `IX_GroupId` (`NamespaceId`),\n  KEY `DataChange_LastTime` (`DataChange_LastTime`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='配置项目';\n\n\n\n# Dump of table namespace\n# ------------------------------------------------------------\n\nDROP TABLE IF EXISTS `Namespace`;\n\nCREATE TABLE `Namespace` (\n  `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',\n  `AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID',\n  `ClusterName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'Cluster Name',\n  `NamespaceName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'Namespace Name',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `AppId_ClusterName_NamespaceName` (`AppId`(191),`ClusterName`(191),`NamespaceName`(191)),\n  KEY `DataChange_LastTime` (`DataChange_LastTime`),\n  KEY `IX_NamespaceName` (`NamespaceName`(191))\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='命名空间';\n\n\n\n# Dump of table namespacelock\n# ------------------------------------------------------------\n\nDROP TABLE IF EXISTS `NamespaceLock`;\n\nCREATE TABLE `NamespaceLock` (\n  `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id',\n  `NamespaceId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '集群NamespaceId',\n  `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT 'default' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  `IsDeleted` bit(1) DEFAULT b'0' COMMENT '软删除',\n  PRIMARY KEY (`Id`),\n  UNIQUE KEY `IX_NamespaceId` (`NamespaceId`),\n  KEY `DataChange_LastTime` (`DataChange_LastTime`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='namespace的编辑锁';\n\n\n\n# Dump of table release\n# ------------------------------------------------------------\n\nDROP TABLE IF EXISTS `Release`;\n\nCREATE TABLE `Release` (\n  `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',\n  `ReleaseKey` varchar(64) NOT NULL DEFAULT '' COMMENT '发布的Key',\n  `Name` varchar(64) NOT NULL DEFAULT 'default' COMMENT '发布名字',\n  `Comment` varchar(256) DEFAULT NULL COMMENT '发布说明',\n  `AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID',\n  `ClusterName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ClusterName',\n  `NamespaceName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'namespaceName',\n  `Configurations` longtext NOT NULL COMMENT '发布配置',\n  `IsAbandoned` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否废弃',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `AppId_ClusterName_GroupName` (`AppId`(191),`ClusterName`(191),`NamespaceName`(191)),\n  KEY `DataChange_LastTime` (`DataChange_LastTime`),\n  KEY `IX_ReleaseKey` (`ReleaseKey`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='发布';\n\n\n# Dump of table releasehistory\n# ------------------------------------------------------------\n\nDROP TABLE IF EXISTS `ReleaseHistory`;\n\nCREATE TABLE `ReleaseHistory` (\n  `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',\n  `AppId` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'AppID',\n  `ClusterName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'ClusterName',\n  `NamespaceName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'namespaceName',\n  `BranchName` varchar(32) NOT NULL DEFAULT 'default' COMMENT '发布分支名',\n  `ReleaseId` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '关联的Release Id',\n  `PreviousReleaseId` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '前一次发布的ReleaseId',\n  `Operation` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '发布类型，0: 普通发布，1: 回滚，2: 灰度发布，3: 灰度规则更新，4: 灰度合并回主分支发布，5: 主分支发布灰度自动发布，6: 主分支回滚灰度自动发布，7: 放弃灰度',\n  `OperationContext` longtext NOT NULL COMMENT '发布上下文信息',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `IX_Namespace` (`AppId`,`ClusterName`,`NamespaceName`,`BranchName`),\n  KEY `IX_ReleaseId` (`ReleaseId`),\n  KEY `IX_DataChange_LastTime` (`DataChange_LastTime`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='发布历史';\n\n\n# Dump of table releasemessage\n# ------------------------------------------------------------\n\nDROP TABLE IF EXISTS `ReleaseMessage`;\n\nCREATE TABLE `ReleaseMessage` (\n  `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',\n  `Message` varchar(1024) NOT NULL DEFAULT '' COMMENT '发布的消息内容',\n  `DataChange_LastTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `DataChange_LastTime` (`DataChange_LastTime`),\n  KEY `IX_Message` (`Message`(191))\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='发布消息';\n\n\n\n# Dump of table serverconfig\n# ------------------------------------------------------------\n\nDROP TABLE IF EXISTS `ServerConfig`;\n\nCREATE TABLE `ServerConfig` (\n  `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',\n  `Key` varchar(64) NOT NULL DEFAULT 'default' COMMENT '配置项Key',\n  `Cluster` varchar(32) NOT NULL DEFAULT 'default' COMMENT '配置对应的集群，default为不针对特定的集群',\n  `Value` varchar(2048) NOT NULL DEFAULT 'default' COMMENT '配置项值',\n  `Comment` varchar(1024) DEFAULT '' COMMENT '注释',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `IX_Key` (`Key`),\n  KEY `DataChange_LastTime` (`DataChange_LastTime`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='配置服务自身配置';\n\n# Config\n# ------------------------------------------------------------\nINSERT INTO `ServerConfig` (`Key`, `Cluster`, `Value`, `Comment`)\nVALUES\n    ('eureka.service.url', 'default', 'http://localhost:8080/eureka/', 'Eureka服务Url，多个service以英文逗号分隔'),\n    ('namespace.lock.switch', 'default', 'false', '一次发布只能有一个人修改开关'),\n    ('item.value.length.limit', 'default', '20000', 'item value最大长度限制'),\n    ('config-service.cache.enabled', 'default', 'false', 'ConfigService是否开启缓存，开启后能提高性能，但是会增大内存消耗！'),\n    ('item.key.length.limit', 'default', '128', 'item key 最大长度限制');\n\n# Sample Data\n# ------------------------------------------------------------\nINSERT INTO `App` (`AppId`, `Name`, `OrgId`, `OrgName`, `OwnerName`, `OwnerEmail`)\nVALUES\n\t('SampleApp', 'Sample App', 'TEST1', '样例部门1', 'apollo', 'apollo@acme.com');\n\nINSERT INTO `AppNamespace` (`Name`, `AppId`, `Format`, `IsPublic`, `Comment`)\nVALUES\n\t('application', 'SampleApp', 'properties', 0, 'default app namespace');\n\nINSERT INTO `Cluster` (`Name`, `AppId`)\nVALUES\n\t('default', 'SampleApp');\n\nINSERT INTO `Namespace` (`Id`, `AppId`, `ClusterName`, `NamespaceName`)\nVALUES\n\t(1, 'SampleApp', 'default', 'application');\n\n\nINSERT INTO `Item` (`NamespaceId`, `Key`, `Value`, `Comment`, `LineNum`)\nVALUES\n\t(1, 'timeout', '100', 'sample timeout配置', 1);\n\nINSERT INTO `Release` (`ReleaseKey`, `Name`, `Comment`, `AppId`, `ClusterName`, `NamespaceName`, `Configurations`)\nVALUES\n\t('20161009155425-d3a0749c6e20bc15', '20161009155424-release', 'Sample发布', 'SampleApp', 'default', 'application', '{\\\"timeout\\\":\\\"100\\\"}');\n\nINSERT INTO `ReleaseHistory` (`AppId`, `ClusterName`, `NamespaceName`, `BranchName`, `ReleaseId`, `PreviousReleaseId`, `Operation`, `OperationContext`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)\nVALUES\n  ('SampleApp', 'default', 'application', 'default', 1, 0, 0, '{}', 'apollo', 'apollo');\n\n\n/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;\n/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;\n/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;\n/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\n/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\n"
  },
  {
    "path": "open-config-center/apollo/scripts/docker-quick-start/sql/apolloportaldb.sql",
    "content": "/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;\n/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;\n/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;\n/*!40101 SET NAMES utf8 */;\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 */;\n\n# Create Database\n# ------------------------------------------------------------\nCREATE DATABASE IF NOT EXISTS ApolloPortalDB DEFAULT CHARACTER SET = utf8mb4;\n\nUse ApolloPortalDB;\n\n# Dump of table app\n# ------------------------------------------------------------\n\nDROP TABLE IF EXISTS `App`;\n\nCREATE TABLE `App` (\n  `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',\n  `AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID',\n  `Name` varchar(500) NOT NULL DEFAULT 'default' COMMENT '应用名',\n  `OrgId` varchar(32) NOT NULL DEFAULT 'default' COMMENT '部门Id',\n  `OrgName` varchar(64) NOT NULL DEFAULT 'default' COMMENT '部门名字',\n  `OwnerName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ownerName',\n  `OwnerEmail` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ownerEmail',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `AppId` (`AppId`(191)),\n  KEY `DataChange_LastTime` (`DataChange_LastTime`),\n  KEY `IX_Name` (`Name`(191))\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='应用表';\n\n\n\n# Dump of table appnamespace\n# ------------------------------------------------------------\n\nDROP TABLE IF EXISTS `AppNamespace`;\n\nCREATE TABLE `AppNamespace` (\n  `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',\n  `Name` varchar(32) NOT NULL DEFAULT '' COMMENT 'namespace名字，注意，需要全局唯一',\n  `AppId` varchar(32) NOT NULL DEFAULT '' COMMENT 'app id',\n  `Format` varchar(32) NOT NULL DEFAULT 'properties' COMMENT 'namespace的format类型',\n  `IsPublic` bit(1) NOT NULL DEFAULT b'0' COMMENT 'namespace是否为公共',\n  `Comment` varchar(64) NOT NULL DEFAULT '' COMMENT '注释',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT '' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `IX_AppId` (`AppId`),\n  KEY `Name_AppId` (`Name`,`AppId`),\n  KEY `DataChange_LastTime` (`DataChange_LastTime`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='应用namespace定义';\n\n\n\n# Dump of table consumer\n# ------------------------------------------------------------\n\nDROP TABLE IF EXISTS `Consumer`;\n\nCREATE TABLE `Consumer` (\n  `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',\n  `AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID',\n  `Name` varchar(500) NOT NULL DEFAULT 'default' COMMENT '应用名',\n  `OrgId` varchar(32) NOT NULL DEFAULT 'default' COMMENT '部门Id',\n  `OrgName` varchar(64) NOT NULL DEFAULT 'default' COMMENT '部门名字',\n  `OwnerName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ownerName',\n  `OwnerEmail` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ownerEmail',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `AppId` (`AppId`(191)),\n  KEY `DataChange_LastTime` (`DataChange_LastTime`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='开放API消费者';\n\n\n\n# Dump of table consumeraudit\n# ------------------------------------------------------------\n\nDROP TABLE IF EXISTS `ConsumerAudit`;\n\nCREATE TABLE `ConsumerAudit` (\n  `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',\n  `ConsumerId` int(11) unsigned DEFAULT NULL COMMENT 'Consumer Id',\n  `Uri` varchar(1024) NOT NULL DEFAULT '' COMMENT '访问的Uri',\n  `Method` varchar(16) NOT NULL DEFAULT '' COMMENT '访问的Method',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `IX_DataChange_LastTime` (`DataChange_LastTime`),\n  KEY `IX_ConsumerId` (`ConsumerId`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='consumer审计表';\n\n\n\n# Dump of table consumerrole\n# ------------------------------------------------------------\n\nDROP TABLE IF EXISTS `ConsumerRole`;\n\nCREATE TABLE `ConsumerRole` (\n  `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',\n  `ConsumerId` int(11) unsigned DEFAULT NULL COMMENT 'Consumer Id',\n  `RoleId` int(10) unsigned DEFAULT NULL COMMENT 'Role Id',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) DEFAULT '' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `IX_DataChange_LastTime` (`DataChange_LastTime`),\n  KEY `IX_RoleId` (`RoleId`),\n  KEY `IX_ConsumerId_RoleId` (`ConsumerId`,`RoleId`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='consumer和role的绑定表';\n\n\n\n# Dump of table consumertoken\n# ------------------------------------------------------------\n\nDROP TABLE IF EXISTS `ConsumerToken`;\n\nCREATE TABLE `ConsumerToken` (\n  `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',\n  `ConsumerId` int(11) unsigned DEFAULT NULL COMMENT 'ConsumerId',\n  `Token` varchar(128) NOT NULL DEFAULT '' COMMENT 'token',\n  `Expires` datetime NOT NULL DEFAULT '2099-01-01 00:00:00' COMMENT 'token失效时间',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  UNIQUE KEY `IX_Token` (`Token`),\n  KEY `DataChange_LastTime` (`DataChange_LastTime`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='consumer token表';\n\n# Dump of table favorite\n# ------------------------------------------------------------\n\nDROP TABLE IF EXISTS `Favorite`;\n\nCREATE TABLE `Favorite` (\n  `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',\n  `UserId` varchar(32) NOT NULL DEFAULT 'default' COMMENT '收藏的用户',\n  `AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID',\n  `Position` int(32) NOT NULL DEFAULT '10000' COMMENT '收藏顺序',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `AppId` (`AppId`(191)),\n  KEY `IX_UserId` (`UserId`),\n  KEY `DataChange_LastTime` (`DataChange_LastTime`)\n) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=utf8mb4 COMMENT='应用收藏表';\n\n# Dump of table permission\n# ------------------------------------------------------------\n\nDROP TABLE IF EXISTS `Permission`;\n\nCREATE TABLE `Permission` (\n  `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',\n  `PermissionType` varchar(32) NOT NULL DEFAULT '' COMMENT '权限类型',\n  `TargetId` varchar(256) NOT NULL DEFAULT '' COMMENT '权限对象类型',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT '' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `IX_TargetId_PermissionType` (`TargetId`(191),`PermissionType`),\n  KEY `IX_DataChange_LastTime` (`DataChange_LastTime`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='permission表';\n\n\n\n# Dump of table role\n# ------------------------------------------------------------\n\nDROP TABLE IF EXISTS `Role`;\n\nCREATE TABLE `Role` (\n  `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',\n  `RoleName` varchar(256) NOT NULL DEFAULT '' COMMENT 'Role name',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `IX_RoleName` (`RoleName`(191)),\n  KEY `IX_DataChange_LastTime` (`DataChange_LastTime`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色表';\n\n\n\n# Dump of table rolepermission\n# ------------------------------------------------------------\n\nDROP TABLE IF EXISTS `RolePermission`;\n\nCREATE TABLE `RolePermission` (\n  `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',\n  `RoleId` int(10) unsigned DEFAULT NULL COMMENT 'Role Id',\n  `PermissionId` int(10) unsigned DEFAULT NULL COMMENT 'Permission Id',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) DEFAULT '' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `IX_DataChange_LastTime` (`DataChange_LastTime`),\n  KEY `IX_RoleId` (`RoleId`),\n  KEY `IX_PermissionId` (`PermissionId`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色和权限的绑定表';\n\n\n\n# Dump of table serverconfig\n# ------------------------------------------------------------\n\nDROP TABLE IF EXISTS `ServerConfig`;\n\nCREATE TABLE `ServerConfig` (\n  `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',\n  `Key` varchar(64) NOT NULL DEFAULT 'default' COMMENT '配置项Key',\n  `Value` varchar(2048) NOT NULL DEFAULT 'default' COMMENT '配置项值',\n  `Comment` varchar(1024) DEFAULT '' COMMENT '注释',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `IX_Key` (`Key`),\n  KEY `DataChange_LastTime` (`DataChange_LastTime`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='配置服务自身配置';\n\n\n\n# Dump of table userrole\n# ------------------------------------------------------------\n\nDROP TABLE IF EXISTS `UserRole`;\n\nCREATE TABLE `UserRole` (\n  `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',\n  `UserId` varchar(128) DEFAULT '' COMMENT '用户身份标识',\n  `RoleId` int(10) unsigned DEFAULT NULL COMMENT 'Role Id',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) DEFAULT '' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `IX_DataChange_LastTime` (`DataChange_LastTime`),\n  KEY `IX_RoleId` (`RoleId`),\n  KEY `IX_UserId_RoleId` (`UserId`,`RoleId`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户和role的绑定表';\n\n# Dump of table Users\n# ------------------------------------------------------------\n\nDROP TABLE IF EXISTS `Users`;\n\nCREATE TABLE `Users` (\n  `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',\n  `Username` varchar(64) NOT NULL DEFAULT 'default' COMMENT '用户名',\n  `Password` varchar(64) NOT NULL DEFAULT 'default' COMMENT '密码',\n  `Email` varchar(64) NOT NULL DEFAULT 'default' COMMENT '邮箱地址',\n  `Enabled` tinyint(4) DEFAULT NULL COMMENT '是否有效',\n  PRIMARY KEY (`Id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';\n\n\n# Dump of table Authorities\n# ------------------------------------------------------------\n\nDROP TABLE IF EXISTS `Authorities`;\n\nCREATE TABLE `Authorities` (\n  `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',\n  `Username` varchar(50) NOT NULL,\n  `Authority` varchar(50) NOT NULL,\n  PRIMARY KEY (`Id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;\n\n\n# Config\n# ------------------------------------------------------------\nINSERT INTO `ServerConfig` (`Key`, `Value`, `Comment`)\nVALUES\n    ('apollo.portal.envs', 'dev', '可支持的环境列表'),\n    ('organizations', '[{\\\"orgId\\\":\\\"TEST1\\\",\\\"orgName\\\":\\\"样例部门1\\\"},{\\\"orgId\\\":\\\"TEST2\\\",\\\"orgName\\\":\\\"样例部门2\\\"}]', '部门列表'),\n    ('superAdmin', 'apollo', 'Portal超级管理员'),\n    ('api.readTimeout', '10000', 'http接口read timeout'),\n    ('consumer.token.salt', 'someSalt', 'consumer token salt'),\n    ('admin.createPrivateNamespace.switch', 'false', '是否允许项目管理员创建私有namespace');\n\nINSERT INTO `Users` (`Username`, `Password`, `Email`, `Enabled`)\nVALUES\n\t('apollo', '$2a$10$7r20uS.BQ9uBpf3Baj3uQOZvMVvB1RN3PYoKE94gtz2.WAOuiiwXS', 'apollo@acme.com', 1);\n\nINSERT INTO `Authorities` (`Username`, `Authority`) VALUES ('apollo', 'ROLE_user');\n\n# Sample Data\n# ------------------------------------------------------------\nINSERT INTO `App` (`AppId`, `Name`, `OrgId`, `OrgName`, `OwnerName`, `OwnerEmail`)\nVALUES\n\t('SampleApp', 'Sample App', 'TEST1', '样例部门1', 'apollo', 'apollo@acme.com');\n\nINSERT INTO `AppNamespace` (`Name`, `AppId`, `Format`, `IsPublic`, `Comment`)\nVALUES\n\t('application', 'SampleApp', 'properties', 0, 'default app namespace');\n\nINSERT INTO `Permission` (`Id`, `PermissionType`, `TargetId`)\nVALUES\n\t(1, 'CreateCluster', 'SampleApp'),\n\t(2, 'CreateNamespace', 'SampleApp'),\n\t(3, 'AssignRole', 'SampleApp'),\n\t(4, 'ModifyNamespace', 'SampleApp+application'),\n\t(5, 'ReleaseNamespace', 'SampleApp+application');\n\nINSERT INTO `Role` (`Id`, `RoleName`)\nVALUES\n\t(1, 'Master+SampleApp'),\n\t(2, 'ModifyNamespace+SampleApp+application'),\n\t(3, 'ReleaseNamespace+SampleApp+application');\n\nINSERT INTO `RolePermission` (`RoleId`, `PermissionId`)\nVALUES\n\t(1, 1),\n\t(1, 2),\n\t(1, 3),\n\t(2, 4),\n\t(3, 5);\n\nINSERT INTO `UserRole` (`UserId`, `RoleId`)\nVALUES\n\t('apollo', 1),\n\t('apollo', 2),\n\t('apollo', 3);\n\n/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;\n/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;\n/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;\n/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\n/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\n"
  },
  {
    "path": "open-config-center/apollo/scripts/sql/apolloconfigdb.sql",
    "content": " \n\n# Create Database\n# ------------------------------------------------------------\nCREATE DATABASE IF NOT EXISTS ApolloConfigDB DEFAULT CHARACTER SET = utf8mb4;\n\nUse ApolloConfigDB;\n\n# Host: 47.94.252.160  (Version 5.7.22)\n# Date: 2018-06-26 20:02:25\n# Generator: MySQL-Front 5.4  (Build 4.153) - http://www.mysqlfront.de/\n\n/*!40101 SET NAMES utf8 */;\n\n#\n# Structure for table \"app\"\n#\n\nDROP TABLE IF EXISTS `app`;\nCREATE TABLE `app` (\n  `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',\n  `AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID',\n  `Name` varchar(500) NOT NULL DEFAULT 'default' COMMENT '应用名',\n  `OrgId` varchar(32) NOT NULL DEFAULT 'default' COMMENT '部门Id',\n  `OrgName` varchar(64) NOT NULL DEFAULT 'default' COMMENT '部门名字',\n  `OwnerName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ownerName',\n  `OwnerEmail` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ownerEmail',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `AppId` (`AppId`(191)),\n  KEY `DataChange_LastTime` (`DataChange_LastTime`),\n  KEY `IX_Name` (`Name`(191))\n) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COMMENT='应用表';\n\n#\n# Data for table \"app\"\n#\n\nINSERT INTO `app` VALUES (1,'SampleApp','Sample App','TEST1','样例部门1','apollo','apollo@acme.com',b'0','default','2018-04-03 23:19:15','','2018-04-03 23:19:15'),(2,'zuulservice','zuulservice-dev','TEST1','样例部门1','apollo','apollo@acme.com',b'0','apollo','2018-04-04 00:09:41','apollo','2018-04-04 00:09:41');\n\n#\n# Structure for table \"appnamespace\"\n#\n\nDROP TABLE IF EXISTS `appnamespace`;\nCREATE TABLE `appnamespace` (\n  `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',\n  `Name` varchar(32) NOT NULL DEFAULT '' COMMENT 'namespace名字，注意，需要全局唯一',\n  `AppId` varchar(32) NOT NULL DEFAULT '' COMMENT 'app id',\n  `Format` varchar(32) NOT NULL DEFAULT 'properties' COMMENT 'namespace的format类型',\n  `IsPublic` bit(1) NOT NULL DEFAULT b'0' COMMENT 'namespace是否为公共',\n  `Comment` varchar(64) NOT NULL DEFAULT '' COMMENT '注释',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT '' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `IX_AppId` (`AppId`),\n  KEY `Name_AppId` (`Name`,`AppId`),\n  KEY `DataChange_LastTime` (`DataChange_LastTime`)\n) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COMMENT='应用namespace定义';\n\n#\n# Data for table \"appnamespace\"\n#\n\nINSERT INTO `appnamespace` VALUES (1,'application','SampleApp','properties',b'0','default app namespace',b'0','','2018-04-03 23:19:15','','2018-04-03 23:19:15'),(2,'application','zuulservice','properties',b'0','default app namespace',b'0','apollo','2018-04-04 00:09:43','apollo','2018-04-04 00:09:43');\n\n#\n# Structure for table \"audit\"\n#\n\nDROP TABLE IF EXISTS `audit`;\nCREATE TABLE `audit` (\n  `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',\n  `EntityName` varchar(50) NOT NULL DEFAULT 'default' COMMENT '表名',\n  `EntityId` int(10) unsigned DEFAULT NULL COMMENT '记录ID',\n  `OpName` varchar(50) NOT NULL DEFAULT 'default' COMMENT '操作类型',\n  `Comment` varchar(500) DEFAULT NULL COMMENT '备注',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `DataChange_LastTime` (`DataChange_LastTime`)\n) ENGINE=InnoDB AUTO_INCREMENT=107 DEFAULT CHARSET=utf8mb4 COMMENT='日志审计表';\n\n#\n# Data for table \"audit\"\n#\n\nINSERT INTO `audit` VALUES (1,'App',2,'INSERT',NULL,b'0','apollo','2018-04-04 00:09:43',NULL,'2018-04-04 00:09:43'),(2,'AppNamespace',2,'INSERT',NULL,b'0','apollo','2018-04-04 00:09:43',NULL,'2018-04-04 00:09:43'),(3,'Cluster',2,'INSERT',NULL,b'0','apollo','2018-04-04 00:09:43',NULL,'2018-04-04 00:09:43'),(4,'Namespace',2,'INSERT',NULL,b'0','apollo','2018-04-04 00:09:43',NULL,'2018-04-04 00:09:43'),(5,'Item',2,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(6,'Item',3,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(7,'Item',4,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(8,'Item',5,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(9,'Item',6,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(10,'Item',7,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(11,'Item',8,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(12,'Item',9,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(13,'Item',10,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(14,'Item',11,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(15,'Item',12,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(16,'Item',13,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(17,'Item',14,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(18,'Item',15,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(19,'Item',16,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(20,'Item',17,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(21,'Item',18,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(22,'Item',19,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(23,'Item',20,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(24,'Item',21,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(25,'Item',22,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(26,'Item',23,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(27,'Item',24,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(28,'Item',25,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(29,'Item',26,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(30,'Item',27,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(31,'ItemSet',NULL,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(32,'Item',8,'UPDATE',NULL,b'0','apollo','2018-04-04 00:12:13',NULL,'2018-04-04 00:12:13'),(33,'Item',16,'UPDATE',NULL,b'0','apollo','2018-04-04 00:12:13',NULL,'2018-04-04 00:12:13'),(34,'Item',20,'UPDATE',NULL,b'0','apollo','2018-04-04 00:12:13',NULL,'2018-04-04 00:12:13'),(35,'Item',21,'UPDATE',NULL,b'0','apollo','2018-04-04 00:12:13',NULL,'2018-04-04 00:12:13'),(36,'Item',26,'UPDATE',NULL,b'0','apollo','2018-04-04 00:12:13',NULL,'2018-04-04 00:12:13'),(37,'ItemSet',NULL,'UPDATE',NULL,b'0','apollo','2018-04-04 00:12:13',NULL,'2018-04-04 00:12:13'),(38,'Release',2,'INSERT',NULL,b'0','apollo','2018-04-04 00:12:29',NULL,'2018-04-04 00:12:29'),(39,'ReleaseHistory',2,'INSERT',NULL,b'0','apollo','2018-04-04 00:12:29',NULL,'2018-04-04 00:12:29'),(40,'Item',21,'UPDATE',NULL,b'0','apollo','2018-04-04 00:22:18',NULL,'2018-04-04 00:22:18'),(41,'ItemSet',NULL,'UPDATE',NULL,b'0','apollo','2018-04-04 00:22:19',NULL,'2018-04-04 00:22:19'),(42,'Release',3,'INSERT',NULL,b'0','apollo','2018-04-04 00:22:21',NULL,'2018-04-04 00:22:21'),(43,'ReleaseHistory',3,'INSERT',NULL,b'0','apollo','2018-04-04 00:22:21',NULL,'2018-04-04 00:22:21'),(44,'Item',28,'INSERT',NULL,b'0','apollo','2018-04-04 00:55:46',NULL,'2018-04-04 00:55:46'),(45,'Item',29,'INSERT',NULL,b'0','apollo','2018-04-04 00:55:46',NULL,'2018-04-04 00:55:46'),(46,'Item',30,'INSERT',NULL,b'0','apollo','2018-04-04 00:55:46',NULL,'2018-04-04 00:55:46'),(47,'Item',31,'INSERT',NULL,b'0','apollo','2018-04-04 00:55:46',NULL,'2018-04-04 00:55:46'),(48,'Item',32,'INSERT',NULL,b'0','apollo','2018-04-04 00:55:46',NULL,'2018-04-04 00:55:46'),(49,'Item',33,'INSERT',NULL,b'0','apollo','2018-04-04 00:55:46',NULL,'2018-04-04 00:55:46'),(50,'Item',34,'INSERT',NULL,b'0','apollo','2018-04-04 00:55:46',NULL,'2018-04-04 00:55:46'),(51,'Item',35,'INSERT',NULL,b'0','apollo','2018-04-04 00:55:46',NULL,'2018-04-04 00:55:46'),(52,'Item',36,'INSERT',NULL,b'0','apollo','2018-04-04 00:55:46',NULL,'2018-04-04 00:55:46'),(53,'ItemSet',NULL,'INSERT',NULL,b'0','apollo','2018-04-04 00:55:46',NULL,'2018-04-04 00:55:46'),(54,'Item',13,'UPDATE',NULL,b'0','apollo','2018-04-04 00:55:46',NULL,'2018-04-04 00:55:46'),(55,'Item',18,'UPDATE',NULL,b'0','apollo','2018-04-04 00:55:46',NULL,'2018-04-04 00:55:46'),(56,'Item',11,'UPDATE',NULL,b'0','apollo','2018-04-04 00:55:46',NULL,'2018-04-04 00:55:46'),(57,'Item',12,'UPDATE',NULL,b'0','apollo','2018-04-04 00:55:46',NULL,'2018-04-04 00:55:46'),(58,'Item',19,'UPDATE',NULL,b'0','apollo','2018-04-04 00:55:46',NULL,'2018-04-04 00:55:46'),(59,'Item',23,'UPDATE',NULL,b'0','apollo','2018-04-04 00:55:46',NULL,'2018-04-04 00:55:46'),(60,'Item',24,'UPDATE',NULL,b'0','apollo','2018-04-04 00:55:47',NULL,'2018-04-04 00:55:47'),(61,'Item',14,'UPDATE',NULL,b'0','apollo','2018-04-04 00:55:47',NULL,'2018-04-04 00:55:47'),(62,'Item',15,'UPDATE',NULL,b'0','apollo','2018-04-04 00:55:47',NULL,'2018-04-04 00:55:47'),(63,'Item',17,'UPDATE',NULL,b'0','apollo','2018-04-04 00:55:47',NULL,'2018-04-04 00:55:47'),(64,'Item',7,'UPDATE',NULL,b'0','apollo','2018-04-04 00:55:47',NULL,'2018-04-04 00:55:47'),(65,'Item',9,'UPDATE',NULL,b'0','apollo','2018-04-04 00:55:47',NULL,'2018-04-04 00:55:47'),(66,'Item',10,'UPDATE',NULL,b'0','apollo','2018-04-04 00:55:47',NULL,'2018-04-04 00:55:47'),(67,'Item',20,'UPDATE',NULL,b'0','apollo','2018-04-04 00:55:47',NULL,'2018-04-04 00:55:47'),(68,'Item',22,'UPDATE',NULL,b'0','apollo','2018-04-04 00:55:47',NULL,'2018-04-04 00:55:47'),(69,'Item',25,'UPDATE',NULL,b'0','apollo','2018-04-04 00:55:47',NULL,'2018-04-04 00:55:47'),(70,'Item',21,'UPDATE',NULL,b'0','apollo','2018-04-04 00:55:47',NULL,'2018-04-04 00:55:47'),(71,'ItemSet',NULL,'UPDATE',NULL,b'0','apollo','2018-04-04 00:55:47',NULL,'2018-04-04 00:55:47'),(72,'Item',8,'DELETE',NULL,b'0','apollo','2018-04-04 00:55:47',NULL,'2018-04-04 00:55:47'),(73,'Item',27,'DELETE',NULL,b'0','apollo','2018-04-04 00:55:47',NULL,'2018-04-04 00:55:47'),(74,'Item',5,'DELETE',NULL,b'0','apollo','2018-04-04 00:55:47',NULL,'2018-04-04 00:55:47'),(75,'Item',16,'DELETE',NULL,b'0','apollo','2018-04-04 00:55:47',NULL,'2018-04-04 00:55:47'),(76,'Item',2,'DELETE',NULL,b'0','apollo','2018-04-04 00:55:47',NULL,'2018-04-04 00:55:47'),(77,'Item',26,'DELETE',NULL,b'0','apollo','2018-04-04 00:55:47',NULL,'2018-04-04 00:55:47'),(78,'ItemSet',NULL,'DELETE',NULL,b'0','apollo','2018-04-04 00:55:47',NULL,'2018-04-04 00:55:47'),(79,'Release',4,'INSERT',NULL,b'0','apollo','2018-04-04 00:55:50',NULL,'2018-04-04 00:55:50'),(80,'ReleaseHistory',4,'INSERT',NULL,b'0','apollo','2018-04-04 00:55:50',NULL,'2018-04-04 00:55:50'),(81,'Item',21,'UPDATE',NULL,b'0','apollo','2018-04-03 19:25:16',NULL,'2018-04-03 19:25:16'),(82,'Release',5,'INSERT',NULL,b'0','apollo','2018-04-03 19:25:22',NULL,'2018-04-03 19:25:22'),(83,'ReleaseHistory',5,'INSERT',NULL,b'0','apollo','2018-04-03 19:25:22',NULL,'2018-04-03 19:25:22'),(84,'Item',21,'UPDATE',NULL,b'0','apollo','2018-04-04 17:53:27',NULL,'2018-04-04 17:53:27'),(85,'Release',6,'INSERT',NULL,b'0','apollo','2018-04-04 17:53:31',NULL,'2018-04-04 17:53:31'),(86,'ReleaseHistory',6,'INSERT',NULL,b'0','apollo','2018-04-04 17:53:31',NULL,'2018-04-04 17:53:31'),(87,'Item',37,'INSERT',NULL,b'0','apollo','2018-04-04 17:56:31',NULL,'2018-04-04 17:56:31'),(88,'ItemSet',NULL,'INSERT',NULL,b'0','apollo','2018-04-04 17:56:31',NULL,'2018-04-04 17:56:31'),(89,'Item',21,'UPDATE',NULL,b'0','apollo','2018-04-04 17:56:31',NULL,'2018-04-04 17:56:31'),(90,'ItemSet',NULL,'UPDATE',NULL,b'0','apollo','2018-04-04 17:56:31',NULL,'2018-04-04 17:56:31'),(91,'Release',7,'INSERT',NULL,b'0','apollo','2018-04-04 17:56:35',NULL,'2018-04-04 17:56:35'),(92,'ReleaseHistory',7,'INSERT',NULL,b'0','apollo','2018-04-04 17:56:35',NULL,'2018-04-04 17:56:35'),(93,'Item',37,'DELETE',NULL,b'0','apollo','2018-04-04 19:38:49',NULL,'2018-04-04 19:38:49'),(94,'Release',8,'INSERT',NULL,b'0','apollo','2018-04-04 19:39:15',NULL,'2018-04-04 19:39:15'),(95,'ReleaseHistory',8,'INSERT',NULL,b'0','apollo','2018-04-04 19:39:15',NULL,'2018-04-04 19:39:15'),(96,'Item',38,'INSERT',NULL,b'0','apollo','2018-04-04 19:41:46',NULL,'2018-04-04 19:41:46'),(97,'ItemSet',NULL,'INSERT',NULL,b'0','apollo','2018-04-04 19:41:46',NULL,'2018-04-04 19:41:46'),(98,'Release',9,'INSERT',NULL,b'0','apollo','2018-04-04 19:41:50',NULL,'2018-04-04 19:41:50'),(99,'ReleaseHistory',9,'INSERT',NULL,b'0','apollo','2018-04-04 19:41:50',NULL,'2018-04-04 19:41:50'),(100,'Item',24,'UPDATE',NULL,b'0','apollo','2018-06-26 19:59:13',NULL,'2018-06-26 19:59:13'),(101,'ItemSet',NULL,'UPDATE',NULL,b'0','apollo','2018-06-26 19:59:14',NULL,'2018-06-26 19:59:14'),(102,'Release',10,'INSERT',NULL,b'0','apollo','2018-06-26 19:59:20',NULL,'2018-06-26 19:59:20'),(103,'ReleaseHistory',10,'INSERT',NULL,b'0','apollo','2018-06-26 19:59:20',NULL,'2018-06-26 19:59:20'),(104,'Item',21,'UPDATE',NULL,b'0','apollo','2018-06-26 20:00:37',NULL,'2018-06-26 20:00:37'),(105,'Release',11,'INSERT',NULL,b'0','apollo','2018-06-26 20:00:42',NULL,'2018-06-26 20:00:42'),(106,'ReleaseHistory',11,'INSERT',NULL,b'0','apollo','2018-06-26 20:00:42',NULL,'2018-06-26 20:00:42');\n\n#\n# Structure for table \"cluster\"\n#\n\nDROP TABLE IF EXISTS `cluster`;\nCREATE TABLE `cluster` (\n  `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',\n  `Name` varchar(32) NOT NULL DEFAULT '' COMMENT '集群名字',\n  `AppId` varchar(32) NOT NULL DEFAULT '' COMMENT 'App id',\n  `ParentClusterId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '父cluster',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT '' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `IX_AppId_Name` (`AppId`,`Name`),\n  KEY `IX_ParentClusterId` (`ParentClusterId`),\n  KEY `DataChange_LastTime` (`DataChange_LastTime`)\n) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COMMENT='集群';\n\n#\n# Data for table \"cluster\"\n#\n\nINSERT INTO `cluster` VALUES (1,'default','SampleApp',0,b'0','','2018-04-03 23:19:15','','2018-04-03 23:19:15'),(2,'default','zuulservice',0,b'0','apollo','2018-04-04 00:09:43','apollo','2018-04-04 00:09:43');\n\n#\n# Structure for table \"commit\"\n#\n\nDROP TABLE IF EXISTS `commit`;\nCREATE TABLE `commit` (\n  `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',\n  `ChangeSets` longtext NOT NULL COMMENT '修改变更集',\n  `AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID',\n  `ClusterName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ClusterName',\n  `NamespaceName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'namespaceName',\n  `Comment` varchar(500) DEFAULT NULL COMMENT '备注',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `DataChange_LastTime` (`DataChange_LastTime`),\n  KEY `AppId` (`AppId`(191)),\n  KEY `ClusterName` (`ClusterName`(191)),\n  KEY `NamespaceName` (`NamespaceName`(191))\n) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COMMENT='commit 历史表';\n\n#\n# Data for table \"commit\"\n#\n\nINSERT INTO `commit` VALUES (1,'{\\\"createItems\\\":[{\\\"namespaceId\\\":2,\\\"key\\\":\\\"zuul.routes.test165.path\\\",\\\"value\\\":\\\"/test165/**\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":1,\\\"id\\\":2,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:26\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:11:27\\\"},{\\\"namespaceId\\\":2,\\\"key\\\":\\\"ribbon.ConnectTimeout\\\",\\\"value\\\":\\\"10000\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":2,\\\"id\\\":3,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:26\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:11:27\\\"},{\\\"namespaceId\\\":2,\\\"key\\\":\\\"ribbon.OkToRetryOnAllOperations\\\",\\\"value\\\":\\\"true\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":3,\\\"id\\\":4,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:26\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:11:27\\\"},{\\\"namespaceId\\\":2,\\\"key\\\":\\\"zuul.routes.test166.path\\\",\\\"value\\\":\\\"/test166/**\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":4,\\\"id\\\":5,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:26\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:11:27\\\"},{\\\"namespaceId\\\":2,\\\"key\\\":\\\"ribbon.MaxAutoRetriesNextServer\\\",\\\"value\\\":\\\"2\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":5,\\\"id\\\":6,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:26\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:11:27\\\"},{\\\"namespaceId\\\":2,\\\"key\\\":\\\"zuul.host.connect-timeout-millis\\\",\\\"value\\\":\\\"10000\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":6,\\\"id\\\":7,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:26\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:11:27\\\"},{\\\"namespaceId\\\":2,\\\"key\\\":\\\"zuul.routes.test164.url\\\",\\\"value\\\":\\\"http\\\\\\\\://www.163.com\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":7,\\\"id\\\":8,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:26\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:11:27\\\"},{\\\"namespaceId\\\":2,\\\"key\\\":\\\"zuul.host.maxTotalConnections\\\",\\\"value\\\":\\\"1024\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":8,\\\"id\\\":9,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:26\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:11:27\\\"},{\\\"namespaceId\\\":2,\\\"key\\\":\\\"zuul.host.maxPerRouteConnections\\\",\\\"value\\\":\\\"512\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":9,\\\"id\\\":10,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:26\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:11:27\\\"},{\\\"namespaceId\\\":2,\\\"key\\\":\\\"management.security.enabled\\\",\\\"value\\\":\\\"false\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":10,\\\"id\\\":11,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:26\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:11:27\\\"},{\\\"namespaceId\\\":2,\\\"key\\\":\\\"spring.application.name\\\",\\\"value\\\":\\\"sop-api-gateway\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":11,\\\"id\\\":12,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:26\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:11:27\\\"},{\\\"namespaceId\\\":2,\\\"key\\\":\\\"ribbon.MaxAutoRetries\\\",\\\"value\\\":\\\"1\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":12,\\\"id\\\":13,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:26\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:11:27\\\"},{\\\"namespaceId\\\":2,\\\"key\\\":\\\"zuul.semaphore.max-semaphores\\\",\\\"value\\\":\\\"1024\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":13,\\\"id\\\":14,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:26\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:11:27\\\"},{\\\"namespaceId\\\":2,\\\"key\\\":\\\"zuul.host.socket-timeout-millis\\\",\\\"value\\\":\\\"10000\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":14,\\\"id\\\":15,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:26\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:11:27\\\"},{\\\"namespaceId\\\":2,\\\"key\\\":\\\"zuul.routes.test166.url\\\",\\\"value\\\":\\\"http\\\\\\\\://www.163.com\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":15,\\\"id\\\":16,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:26\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:11:27\\\"},{\\\"namespaceId\\\":2,\\\"key\\\":\\\"zuul.ignored-services\\\",\\\"value\\\":\\\"\\\\\\\"*\\\\\\\"\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":16,\\\"id\\\":17,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:27\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:11:27\\\"},{\\\"namespaceId\\\":2,\\\"key\\\":\\\"ribbon.ReadTimeout\\\",\\\"value\\\":\\\"10000\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":17,\\\"id\\\":18,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:27\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:11:27\\\"},{\\\"namespaceId\\\":2,\\\"key\\\":\\\"hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds\\\",\\\"value\\\":\\\"10000\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":18,\\\"id\\\":19,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:27\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:11:27\\\"},{\\\"namespaceId\\\":2,\\\"key\\\":\\\"zuul.routes.test163.url\\\",\\\"value\\\":\\\"http\\\\\\\\://www.163.com\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":19,\\\"id\\\":20,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:27\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:11:27\\\"},{\\\"namespaceId\\\":2,\\\"key\\\":\\\"eureka.client.serviceUrl.defaultZone\\\",\\\"value\\\":\\\"http\\\\\\\\://130.75.131.236\\\\\\\\:1111/eureka/\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":20,\\\"id\\\":21,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:27\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:11:27\\\"},{\\\"namespaceId\\\":2,\\\"key\\\":\\\"zuul.routes.test163.path\\\",\\\"value\\\":\\\"/test163/**\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":21,\\\"id\\\":22,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:27\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:11:27\\\"},{\\\"namespaceId\\\":2,\\\"key\\\":\\\"hystrix.command.default.execution.timeout.enabled\\\",\\\"value\\\":\\\"true\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":22,\\\"id\\\":23,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:27\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:11:27\\\"},{\\\"namespaceId\\\":2,\\\"key\\\":\\\"server.port\\\",\\\"value\\\":\\\"9000\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":23,\\\"id\\\":24,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:27\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:11:27\\\"},{\\\"namespaceId\\\":2,\\\"key\\\":\\\"eureka.instance.prefer-ip-address\\\",\\\"value\\\":\\\"true\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":24,\\\"id\\\":25,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:27\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:11:27\\\"},{\\\"namespaceId\\\":2,\\\"key\\\":\\\"zuul.routes.test165.url\\\",\\\"value\\\":\\\"http\\\\\\\\://www.163.com\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":25,\\\"id\\\":26,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:27\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:11:27\\\"},{\\\"namespaceId\\\":2,\\\"key\\\":\\\"zuul.routes.test164.path\\\",\\\"value\\\":\\\"/test164/**\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":26,\\\"id\\\":27,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:27\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:11:27\\\"}],\\\"updateItems\\\":[],\\\"deleteItems\\\":[]}','zuulservice','default','application',NULL,b'0','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:11:27'),(2,'{\\\"createItems\\\":[],\\\"updateItems\\\":[{\\\"oldItem\\\":{\\\"namespaceId\\\":2,\\\"key\\\":\\\"zuul.routes.test164.url\\\",\\\"value\\\":\\\"http\\\\\\\\://www.163.com\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":7,\\\"id\\\":8,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:27\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:11:27\\\"},\\\"newItem\\\":{\\\"namespaceId\\\":2,\\\"key\\\":\\\"zuul.routes.test164.url\\\",\\\"value\\\":\\\"http://www.163.com\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":7,\\\"id\\\":8,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:27\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:12:13\\\"}},{\\\"oldItem\\\":{\\\"namespaceId\\\":2,\\\"key\\\":\\\"zuul.routes.test166.url\\\",\\\"value\\\":\\\"http\\\\\\\\://www.163.com\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":15,\\\"id\\\":16,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:27\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:11:27\\\"},\\\"newItem\\\":{\\\"namespaceId\\\":2,\\\"key\\\":\\\"zuul.routes.test166.url\\\",\\\"value\\\":\\\"http://www.163.com\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":15,\\\"id\\\":16,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:27\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:12:13\\\"}},{\\\"oldItem\\\":{\\\"namespaceId\\\":2,\\\"key\\\":\\\"zuul.routes.test163.url\\\",\\\"value\\\":\\\"http\\\\\\\\://www.163.com\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":19,\\\"id\\\":20,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:27\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:11:27\\\"},\\\"newItem\\\":{\\\"namespaceId\\\":2,\\\"key\\\":\\\"zuul.routes.test163.url\\\",\\\"value\\\":\\\"http://www.163.com\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":19,\\\"id\\\":20,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:27\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:12:13\\\"}},{\\\"oldItem\\\":{\\\"namespaceId\\\":2,\\\"key\\\":\\\"eureka.client.serviceUrl.defaultZone\\\",\\\"value\\\":\\\"http\\\\\\\\://130.75.131.236\\\\\\\\:1111/eureka/\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":20,\\\"id\\\":21,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:27\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:11:27\\\"},\\\"newItem\\\":{\\\"namespaceId\\\":2,\\\"key\\\":\\\"eureka.client.serviceUrl.defaultZone\\\",\\\"value\\\":\\\"http://130.75.131.236\\\\\\\\:1111/eureka/\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":20,\\\"id\\\":21,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:27\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:12:13\\\"}},{\\\"oldItem\\\":{\\\"namespaceId\\\":2,\\\"key\\\":\\\"zuul.routes.test165.url\\\",\\\"value\\\":\\\"http\\\\\\\\://www.163.com\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":25,\\\"id\\\":26,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:27\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:11:27\\\"},\\\"newItem\\\":{\\\"namespaceId\\\":2,\\\"key\\\":\\\"zuul.routes.test165.url\\\",\\\"value\\\":\\\"http://www.163.com\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":25,\\\"id\\\":26,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:27\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:12:13\\\"}}],\\\"deleteItems\\\":[]}','zuulservice','default','application',NULL,b'0','apollo','2018-04-04 00:12:13','apollo','2018-04-04 00:12:13'),(3,'{\\\"createItems\\\":[],\\\"updateItems\\\":[{\\\"oldItem\\\":{\\\"namespaceId\\\":2,\\\"key\\\":\\\"eureka.client.serviceUrl.defaultZone\\\",\\\"value\\\":\\\"http://130.75.131.236\\\\\\\\:1111/eureka/\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":20,\\\"id\\\":21,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:27\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:12:13\\\"},\\\"newItem\\\":{\\\"namespaceId\\\":2,\\\"key\\\":\\\"eureka.client.serviceUrl.defaultZone\\\",\\\"value\\\":\\\"http://130.75.131.236:1111/eureka/\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":20,\\\"id\\\":21,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:27\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:22:18\\\"}}],\\\"deleteItems\\\":[]}','zuulservice','default','application',NULL,b'0','apollo','2018-04-04 00:22:19','apollo','2018-04-04 00:22:19'),(4,'{\\\"createItems\\\":[],\\\"updateItems\\\":[{\\\"oldItem\\\":{\\\"namespaceId\\\":2,\\\"key\\\":\\\"eureka.client.serviceUrl.defaultZone\\\",\\\"value\\\":\\\"http://130.75.131.236:1111/eureka/\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":20,\\\"id\\\":21,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:27\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:22:19\\\"},\\\"newItem\\\":{\\\"namespaceId\\\":2,\\\"key\\\":\\\"eureka.client.serviceUrl.defaultZone\\\",\\\"value\\\":\\\"http://130.75.131.236:1111/eureka\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":29,\\\"id\\\":21,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:27\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:55:46\\\"}}],\\\"deleteItems\\\":[{\\\"namespaceId\\\":2,\\\"key\\\":\\\"zuul.routes.test164.url\\\",\\\"value\\\":\\\"http://www.163.com\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":7,\\\"id\\\":8,\\\"isDeleted\\\":true,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:27\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:55:46\\\"},{\\\"namespaceId\\\":2,\\\"key\\\":\\\"zuul.routes.test164.path\\\",\\\"value\\\":\\\"/test164/**\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":26,\\\"id\\\":27,\\\"isDeleted\\\":true,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:27\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:55:46\\\"},{\\\"namespaceId\\\":2,\\\"key\\\":\\\"zuul.routes.test166.path\\\",\\\"value\\\":\\\"/test166/**\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":4,\\\"id\\\":5,\\\"isDeleted\\\":true,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:27\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:55:46\\\"},{\\\"namespaceId\\\":2,\\\"key\\\":\\\"zuul.routes.test166.url\\\",\\\"value\\\":\\\"http://www.163.com\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":15,\\\"id\\\":16,\\\"isDeleted\\\":true,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:27\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:55:46\\\"},{\\\"namespaceId\\\":2,\\\"key\\\":\\\"zuul.routes.test165.path\\\",\\\"value\\\":\\\"/test165/**\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":1,\\\"id\\\":2,\\\"isDeleted\\\":true,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:27\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:55:46\\\"},{\\\"namespaceId\\\":2,\\\"key\\\":\\\"zuul.routes.test165.url\\\",\\\"value\\\":\\\"http://www.163.com\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":25,\\\"id\\\":26,\\\"isDeleted\\\":true,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:27\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:55:46\\\"}]}','zuulservice','default','application',NULL,b'0','apollo','2018-04-04 00:55:47','apollo','2018-04-04 00:55:47'),(5,'{\\\"createItems\\\":[],\\\"updateItems\\\":[{\\\"oldItem\\\":{\\\"namespaceId\\\":2,\\\"key\\\":\\\"eureka.client.serviceUrl.defaultZone\\\",\\\"value\\\":\\\"http://130.75.131.236:1111/eureka\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":29,\\\"id\\\":21,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:27\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:55:47\\\"},\\\"newItem\\\":{\\\"namespaceId\\\":2,\\\"key\\\":\\\"eureka.client.serviceUrl.defaultZone\\\",\\\"value\\\":\\\"http://192.168.3.151:1111/eureka\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":29,\\\"id\\\":21,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:27\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-03 19:25:16\\\"}}],\\\"deleteItems\\\":[]}','zuulservice','default','application',NULL,b'0','apollo','2018-04-03 19:25:16','apollo','2018-04-03 19:25:16'),(6,'{\\\"createItems\\\":[],\\\"updateItems\\\":[{\\\"oldItem\\\":{\\\"namespaceId\\\":2,\\\"key\\\":\\\"eureka.client.serviceUrl.defaultZone\\\",\\\"value\\\":\\\"http://192.168.3.151:1111/eureka\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":29,\\\"id\\\":21,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:27\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-03 19:25:16\\\"},\\\"newItem\\\":{\\\"namespaceId\\\":2,\\\"key\\\":\\\"eureka.client.serviceUrl.defaultZone\\\",\\\"value\\\":\\\"http://130.75.131.236:1111/eureka\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":29,\\\"id\\\":21,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:27\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 17:53:26\\\"}}],\\\"deleteItems\\\":[]}','zuulservice','default','application',NULL,b'0','apollo','2018-04-04 17:53:27','apollo','2018-04-04 17:53:27'),(7,'{\\\"createItems\\\":[{\\\"namespaceId\\\":2,\\\"key\\\":\\\"eureka.client.register-with-eureka\\\",\\\"value\\\":\\\"false\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":29,\\\"id\\\":37,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 17:56:31\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 17:56:31\\\"}],\\\"updateItems\\\":[],\\\"deleteItems\\\":[]}','zuulservice','default','application',NULL,b'0','apollo','2018-04-04 17:56:31','apollo','2018-04-04 17:56:31'),(8,'{\\\"createItems\\\":[],\\\"updateItems\\\":[],\\\"deleteItems\\\":[{\\\"namespaceId\\\":2,\\\"key\\\":\\\"eureka.client.register-with-eureka\\\",\\\"value\\\":\\\"false\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":29,\\\"id\\\":37,\\\"isDeleted\\\":true,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 17:56:31\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 19:38:49\\\"}]}','zuulservice','default','application',NULL,b'0','apollo','2018-04-04 19:38:49','apollo','2018-04-04 19:38:49'),(9,'{\\\"createItems\\\":[{\\\"namespaceId\\\":2,\\\"key\\\":\\\"eureka.instance.instance-id\\\",\\\"value\\\":\\\"${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":29,\\\"id\\\":38,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 19:41:46\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 19:41:46\\\"}],\\\"updateItems\\\":[],\\\"deleteItems\\\":[]}','zuulservice','default','application',NULL,b'0','apollo','2018-04-04 19:41:46','apollo','2018-04-04 19:41:46'),(10,'{\\\"createItems\\\":[],\\\"updateItems\\\":[{\\\"oldItem\\\":{\\\"namespaceId\\\":2,\\\"key\\\":\\\"server.port\\\",\\\"value\\\":\\\"9999\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":15,\\\"id\\\":24,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:27\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 00:55:47\\\"},\\\"newItem\\\":{\\\"namespaceId\\\":2,\\\"key\\\":\\\"server.port\\\",\\\"value\\\":\\\"9000\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":15,\\\"id\\\":24,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:27\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-06-26 19:59:13\\\"}}],\\\"deleteItems\\\":[]}','zuulservice','default','application',NULL,b'0','apollo','2018-06-26 19:59:14','apollo','2018-06-26 19:59:14'),(11,'{\\\"createItems\\\":[],\\\"updateItems\\\":[{\\\"oldItem\\\":{\\\"namespaceId\\\":2,\\\"key\\\":\\\"eureka.client.serviceUrl.defaultZone\\\",\\\"value\\\":\\\"http://130.75.131.236:1111/eureka\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":30,\\\"id\\\":21,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:27\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-04-04 17:56:31\\\"},\\\"newItem\\\":{\\\"namespaceId\\\":2,\\\"key\\\":\\\"eureka.client.serviceUrl.defaultZone\\\",\\\"value\\\":\\\"http://127.0.0.1:1111/eureka\\\",\\\"comment\\\":\\\"\\\",\\\"lineNum\\\":30,\\\"id\\\":21,\\\"isDeleted\\\":false,\\\"dataChangeCreatedBy\\\":\\\"apollo\\\",\\\"dataChangeCreatedTime\\\":\\\"2018-04-04 00:11:27\\\",\\\"dataChangeLastModifiedBy\\\":\\\"apollo\\\",\\\"dataChangeLastModifiedTime\\\":\\\"2018-06-26 20:00:37\\\"}}],\\\"deleteItems\\\":[]}','zuulservice','default','application',NULL,b'0','apollo','2018-06-26 20:00:37','apollo','2018-06-26 20:00:37');\n\n#\n# Structure for table \"grayreleaserule\"\n#\n\nDROP TABLE IF EXISTS `grayreleaserule`;\nCREATE TABLE `grayreleaserule` (\n  `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',\n  `AppId` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'AppID',\n  `ClusterName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'Cluster Name',\n  `NamespaceName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'Namespace Name',\n  `BranchName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'branch name',\n  `Rules` varchar(16000) DEFAULT '[]' COMMENT '灰度规则',\n  `ReleaseId` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '灰度对应的release',\n  `BranchStatus` tinyint(2) DEFAULT '1' COMMENT '灰度分支状态: 0:删除分支,1:正在使用的规则 2：全量发布',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `DataChange_LastTime` (`DataChange_LastTime`),\n  KEY `IX_Namespace` (`AppId`,`ClusterName`,`NamespaceName`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='灰度规则表';\n\n#\n# Data for table \"grayreleaserule\"\n#\n\n\n#\n# Structure for table \"instance\"\n#\n\nDROP TABLE IF EXISTS `instance`;\nCREATE TABLE `instance` (\n  `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',\n  `AppId` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'AppID',\n  `ClusterName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'ClusterName',\n  `DataCenter` varchar(64) NOT NULL DEFAULT 'default' COMMENT 'Data Center Name',\n  `Ip` varchar(32) NOT NULL DEFAULT '' COMMENT 'instance ip',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  UNIQUE KEY `IX_UNIQUE_KEY` (`AppId`,`ClusterName`,`Ip`,`DataCenter`),\n  KEY `IX_IP` (`Ip`),\n  KEY `IX_DataChange_LastTime` (`DataChange_LastTime`)\n) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COMMENT='使用配置的应用实例';\n\n#\n# Data for table \"instance\"\n#\n\nINSERT INTO `instance` VALUES (1,'zuulservice','default','','192.168.249.1','2018-04-04 00:21:12','2018-04-04 00:21:12'),(2,'zuulservice','default','','192.168.3.151','2018-04-03 19:28:09','2018-04-03 19:28:09'),(3,'zuulservice','default','','130.75.131.236','2018-04-04 19:34:26','2018-04-04 19:34:26');\n\n#\n# Structure for table \"instanceconfig\"\n#\n\nDROP TABLE IF EXISTS `instanceconfig`;\nCREATE TABLE `instanceconfig` (\n  `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',\n  `InstanceId` int(11) unsigned DEFAULT NULL COMMENT 'Instance Id',\n  `ConfigAppId` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'Config App Id',\n  `ConfigClusterName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'Config Cluster Name',\n  `ConfigNamespaceName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'Config Namespace Name',\n  `ReleaseKey` varchar(64) NOT NULL DEFAULT '' COMMENT '发布的Key',\n  `ReleaseDeliveryTime` timestamp NULL DEFAULT NULL COMMENT '配置获取时间',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  UNIQUE KEY `IX_UNIQUE_KEY` (`InstanceId`,`ConfigAppId`,`ConfigNamespaceName`),\n  KEY `IX_ReleaseKey` (`ReleaseKey`),\n  KEY `IX_DataChange_LastTime` (`DataChange_LastTime`),\n  KEY `IX_Valid_Namespace` (`ConfigAppId`,`ConfigClusterName`,`ConfigNamespaceName`,`DataChange_LastTime`)\n) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COMMENT='应用实例的配置信息';\n\n#\n# Data for table \"instanceconfig\"\n#\n\nINSERT INTO `instanceconfig` VALUES (1,1,'zuulservice','default','application','20180626200041-7231d6ad3e03c09a','2018-06-26 20:00:42','2018-04-04 00:21:11','2018-06-26 20:00:43'),(2,2,'zuulservice','default','application','20180403192522-723164972d4b5883','2018-04-03 19:28:08','2018-04-03 19:28:08','2018-04-03 19:28:08'),(3,3,'zuulservice','default','application','20180404194149-723164972d357e8a','2018-04-04 19:41:50','2018-04-04 19:34:26','2018-04-04 19:41:51');\n\n#\n# Structure for table \"item\"\n#\n\nDROP TABLE IF EXISTS `item`;\nCREATE TABLE `item` (\n  `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',\n  `NamespaceId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '集群NamespaceId',\n  `Key` varchar(128) NOT NULL DEFAULT 'default' COMMENT '配置项Key',\n  `Value` longtext NOT NULL COMMENT '配置项值',\n  `Comment` varchar(1024) DEFAULT '' COMMENT '注释',\n  `LineNum` int(10) unsigned DEFAULT '0' COMMENT '行号',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `IX_GroupId` (`NamespaceId`),\n  KEY `DataChange_LastTime` (`DataChange_LastTime`)\n) ENGINE=InnoDB AUTO_INCREMENT=39 DEFAULT CHARSET=utf8mb4 COMMENT='配置项目';\n\n#\n# Data for table \"item\"\n#\n\nINSERT INTO `item` VALUES (1,1,'timeout','100','sample timeout配置',1,b'0','default','2018-04-03 23:19:15','','2018-04-03 23:19:15'),(2,2,'zuul.routes.test165.path','/test165/**','',1,b'1','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(3,2,'ribbon.ConnectTimeout','10000','',2,b'0','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:11:27'),(4,2,'ribbon.OkToRetryOnAllOperations','true','',3,b'0','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:11:27'),(5,2,'zuul.routes.test166.path','/test166/**','',4,b'1','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(6,2,'ribbon.MaxAutoRetriesNextServer','2','',5,b'0','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:11:27'),(7,2,'zuul.host.connect-timeout-millis','10000','',22,b'0','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(8,2,'zuul.routes.test164.url','http://www.163.com','',7,b'1','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(9,2,'zuul.host.maxTotalConnections','1024','',23,b'0','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(10,2,'zuul.host.maxPerRouteConnections','512','',24,b'0','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(11,2,'management.security.enabled','false','',6,b'0','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(12,2,'spring.application.name','sop-api-gateway','',8,b'0','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(13,2,'ribbon.MaxAutoRetries','1','',1,b'0','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(14,2,'zuul.semaphore.max-semaphores','1024','',19,b'0','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(15,2,'zuul.host.socket-timeout-millis','10000','',20,b'0','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(16,2,'zuul.routes.test166.url','http://www.163.com','',15,b'1','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(17,2,'zuul.ignored-services','\\\"*\\\"','',21,b'0','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(18,2,'ribbon.ReadTimeout','10000','',4,b'0','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(19,2,'hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds','10000','',10,b'0','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(20,2,'zuul.routes.test163.url','http://www.163.com','',25,b'0','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(21,2,'eureka.client.serviceUrl.defaultZone','http://127.0.0.1:1111/eureka','',30,b'0','apollo','2018-04-04 00:11:27','apollo','2018-06-26 20:00:37'),(22,2,'zuul.routes.test163.path','/test163/**','',26,b'0','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(23,2,'hystrix.command.default.execution.timeout.enabled','true','',11,b'0','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(24,2,'server.port','9000','',15,b'0','apollo','2018-04-04 00:11:27','apollo','2018-06-26 19:59:14'),(25,2,'eureka.instance.prefer-ip-address','true','',28,b'0','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(26,2,'zuul.routes.test165.url','http://www.163.com','',25,b'1','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(27,2,'zuul.routes.test164.path','/test164/**','',26,b'1','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(28,2,'','','',7,b'0','apollo','2018-04-04 00:55:46','apollo','2018-04-04 00:55:46'),(29,2,'','','',9,b'0','apollo','2018-04-04 00:55:46','apollo','2018-04-04 00:55:46'),(30,2,'','','',12,b'0','apollo','2018-04-04 00:55:46','apollo','2018-04-04 00:55:46'),(31,2,'','','',13,b'0','apollo','2018-04-04 00:55:46','apollo','2018-04-04 00:55:46'),(32,2,'','','',14,b'0','apollo','2018-04-04 00:55:46','apollo','2018-04-04 00:55:46'),(33,2,'','','',16,b'0','apollo','2018-04-04 00:55:46','apollo','2018-04-04 00:55:46'),(34,2,'','','',17,b'0','apollo','2018-04-04 00:55:46','apollo','2018-04-04 00:55:46'),(35,2,'','','',18,b'0','apollo','2018-04-04 00:55:46','apollo','2018-04-04 00:55:46'),(36,2,'','','',27,b'0','apollo','2018-04-04 00:55:46','apollo','2018-04-04 00:55:46'),(37,2,'eureka.client.register-with-eureka','false','',29,b'1','apollo','2018-04-04 17:56:31','apollo','2018-04-04 19:38:49'),(38,2,'eureka.instance.instance-id','${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}','',29,b'0','apollo','2018-04-04 19:41:46','apollo','2018-04-04 19:41:46');\n\n#\n# Structure for table \"namespace\"\n#\n\nDROP TABLE IF EXISTS `namespace`;\nCREATE TABLE `namespace` (\n  `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',\n  `AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID',\n  `ClusterName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'Cluster Name',\n  `NamespaceName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'Namespace Name',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `AppId_ClusterName_NamespaceName` (`AppId`(191),`ClusterName`(191),`NamespaceName`(191)),\n  KEY `DataChange_LastTime` (`DataChange_LastTime`),\n  KEY `IX_NamespaceName` (`NamespaceName`(191))\n) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COMMENT='命名空间';\n\n#\n# Data for table \"namespace\"\n#\n\nINSERT INTO `namespace` VALUES (1,'SampleApp','default','application',b'0','default','2018-04-03 23:19:15','','2018-04-03 23:19:15'),(2,'zuulservice','default','application',b'0','apollo','2018-04-04 00:09:43','apollo','2018-04-04 00:09:43');\n\n#\n# Structure for table \"namespacelock\"\n#\n\nDROP TABLE IF EXISTS `namespacelock`;\nCREATE TABLE `namespacelock` (\n  `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id',\n  `NamespaceId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '集群NamespaceId',\n  `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT 'default' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  `IsDeleted` bit(1) DEFAULT b'0' COMMENT '软删除',\n  PRIMARY KEY (`Id`),\n  UNIQUE KEY `IX_NamespaceId` (`NamespaceId`),\n  KEY `DataChange_LastTime` (`DataChange_LastTime`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='namespace的编辑锁';\n\n#\n# Data for table \"namespacelock\"\n#\n\n\n#\n# Structure for table \"release\"\n#\n\nDROP TABLE IF EXISTS `release`;\nCREATE TABLE `release` (\n  `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',\n  `ReleaseKey` varchar(64) NOT NULL DEFAULT '' COMMENT '发布的Key',\n  `Name` varchar(64) NOT NULL DEFAULT 'default' COMMENT '发布名字',\n  `Comment` varchar(256) DEFAULT NULL COMMENT '发布说明',\n  `AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID',\n  `ClusterName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ClusterName',\n  `NamespaceName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'namespaceName',\n  `Configurations` longtext NOT NULL COMMENT '发布配置',\n  `IsAbandoned` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否废弃',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `AppId_ClusterName_GroupName` (`AppId`(191),`ClusterName`(191),`NamespaceName`(191)),\n  KEY `DataChange_LastTime` (`DataChange_LastTime`),\n  KEY `IX_ReleaseKey` (`ReleaseKey`)\n) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COMMENT='发布';\n\n#\n# Data for table \"release\"\n#\n\nINSERT INTO `release` VALUES (1,'20161009155425-d3a0749c6e20bc15','20161009155424-release','Sample发布','SampleApp','default','application','{\\\"timeout\\\":\\\"100\\\"}',b'0',b'0','default','2018-04-03 23:19:15','','2018-04-03 23:19:15'),(2,'20180404001228-7231d1afd3efc760','20180403161355-release','','zuulservice','default','application','{\\\"zuul.routes.test164.url\\\":\\\"http://www.163.com\\\",\\\"zuul.routes.test164.path\\\":\\\"/test164/**\\\",\\\"zuul.host.maxPerRouteConnections\\\":\\\"512\\\",\\\"zuul.host.socket-timeout-millis\\\":\\\"10000\\\",\\\"zuul.ignored-services\\\":\\\"\\\\\\\"*\\\\\\\"\\\",\\\"ribbon.ReadTimeout\\\":\\\"10000\\\",\\\"zuul.routes.test163.url\\\":\\\"http://www.163.com\\\",\\\"zuul.host.maxTotalConnections\\\":\\\"1024\\\",\\\"management.security.enabled\\\":\\\"false\\\",\\\"server.port\\\":\\\"9999\\\",\\\"zuul.routes.test163.path\\\":\\\"/test163/**\\\",\\\"ribbon.MaxAutoRetriesNextServer\\\":\\\"2\\\",\\\"eureka.client.serviceUrl.defaultZone\\\":\\\"http://130.75.131.236\\\\\\\\:1111/eureka/\\\",\\\"zuul.routes.test166.path\\\":\\\"/test166/**\\\",\\\"hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds\\\":\\\"10000\\\",\\\"ribbon.MaxAutoRetries\\\":\\\"1\\\",\\\"spring.application.name\\\":\\\"sop-api-gateway\\\",\\\"ribbon.ConnectTimeout\\\":\\\"10000\\\",\\\"hystrix.command.default.execution.timeout.enabled\\\":\\\"true\\\",\\\"zuul.routes.test166.url\\\":\\\"http://www.163.com\\\",\\\"zuul.host.connect-timeout-millis\\\":\\\"10000\\\",\\\"ribbon.OkToRetryOnAllOperations\\\":\\\"true\\\",\\\"eureka.instance.prefer-ip-address\\\":\\\"true\\\",\\\"zuul.routes.test165.path\\\":\\\"/test165/**\\\",\\\"zuul.routes.test165.url\\\":\\\"http://www.163.com\\\",\\\"zuul.semaphore.max-semaphores\\\":\\\"1024\\\"}',b'0',b'0','apollo','2018-04-04 00:12:29','apollo','2018-04-04 00:12:29'),(3,'20180404002220-7231d1afd3efc761','20180403162348-release','','zuulservice','default','application','{\\\"zuul.routes.test164.url\\\":\\\"http://www.163.com\\\",\\\"zuul.routes.test164.path\\\":\\\"/test164/**\\\",\\\"zuul.host.maxPerRouteConnections\\\":\\\"512\\\",\\\"zuul.host.socket-timeout-millis\\\":\\\"10000\\\",\\\"zuul.ignored-services\\\":\\\"\\\\\\\"*\\\\\\\"\\\",\\\"ribbon.ReadTimeout\\\":\\\"10000\\\",\\\"zuul.routes.test163.url\\\":\\\"http://www.163.com\\\",\\\"zuul.host.maxTotalConnections\\\":\\\"1024\\\",\\\"management.security.enabled\\\":\\\"false\\\",\\\"server.port\\\":\\\"9999\\\",\\\"zuul.routes.test163.path\\\":\\\"/test163/**\\\",\\\"ribbon.MaxAutoRetriesNextServer\\\":\\\"2\\\",\\\"eureka.client.serviceUrl.defaultZone\\\":\\\"http://130.75.131.236:1111/eureka/\\\",\\\"zuul.routes.test166.path\\\":\\\"/test166/**\\\",\\\"hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds\\\":\\\"10000\\\",\\\"ribbon.MaxAutoRetries\\\":\\\"1\\\",\\\"spring.application.name\\\":\\\"sop-api-gateway\\\",\\\"ribbon.ConnectTimeout\\\":\\\"10000\\\",\\\"hystrix.command.default.execution.timeout.enabled\\\":\\\"true\\\",\\\"zuul.routes.test166.url\\\":\\\"http://www.163.com\\\",\\\"zuul.host.connect-timeout-millis\\\":\\\"10000\\\",\\\"ribbon.OkToRetryOnAllOperations\\\":\\\"true\\\",\\\"eureka.instance.prefer-ip-address\\\":\\\"true\\\",\\\"zuul.routes.test165.path\\\":\\\"/test165/**\\\",\\\"zuul.routes.test165.url\\\":\\\"http://www.163.com\\\",\\\"zuul.semaphore.max-semaphores\\\":\\\"1024\\\"}',b'0',b'0','apollo','2018-04-04 00:22:20','apollo','2018-04-04 00:22:20'),(4,'20180404005550-7231d1afd3efc762','20180403165718-release','','zuulservice','default','application','{\\\"ribbon.MaxAutoRetries\\\":\\\"1\\\",\\\"spring.application.name\\\":\\\"sop-api-gateway\\\",\\\"ribbon.ConnectTimeout\\\":\\\"10000\\\",\\\"hystrix.command.default.execution.timeout.enabled\\\":\\\"true\\\",\\\"zuul.host.connect-timeout-millis\\\":\\\"10000\\\",\\\"ribbon.OkToRetryOnAllOperations\\\":\\\"true\\\",\\\"zuul.host.maxPerRouteConnections\\\":\\\"512\\\",\\\"eureka.instance.prefer-ip-address\\\":\\\"true\\\",\\\"zuul.host.socket-timeout-millis\\\":\\\"10000\\\",\\\"zuul.ignored-services\\\":\\\"\\\\\\\"*\\\\\\\"\\\",\\\"ribbon.ReadTimeout\\\":\\\"10000\\\",\\\"zuul.routes.test163.url\\\":\\\"http://www.163.com\\\",\\\"zuul.host.maxTotalConnections\\\":\\\"1024\\\",\\\"management.security.enabled\\\":\\\"false\\\",\\\"server.port\\\":\\\"9999\\\",\\\"zuul.semaphore.max-semaphores\\\":\\\"1024\\\",\\\"zuul.routes.test163.path\\\":\\\"/test163/**\\\",\\\"ribbon.MaxAutoRetriesNextServer\\\":\\\"2\\\",\\\"eureka.client.serviceUrl.defaultZone\\\":\\\"http://130.75.131.236:1111/eureka\\\",\\\"hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds\\\":\\\"10000\\\"}',b'0',b'0','apollo','2018-04-04 00:55:50','apollo','2018-04-04 00:55:50'),(5,'20180403192522-723164972d4b5883','20180403192755-release','','zuulservice','default','application','{\\\"ribbon.MaxAutoRetries\\\":\\\"1\\\",\\\"spring.application.name\\\":\\\"sop-api-gateway\\\",\\\"ribbon.ConnectTimeout\\\":\\\"10000\\\",\\\"hystrix.command.default.execution.timeout.enabled\\\":\\\"true\\\",\\\"zuul.host.connect-timeout-millis\\\":\\\"10000\\\",\\\"ribbon.OkToRetryOnAllOperations\\\":\\\"true\\\",\\\"zuul.host.maxPerRouteConnections\\\":\\\"512\\\",\\\"eureka.instance.prefer-ip-address\\\":\\\"true\\\",\\\"zuul.host.socket-timeout-millis\\\":\\\"10000\\\",\\\"zuul.ignored-services\\\":\\\"\\\\\\\"*\\\\\\\"\\\",\\\"ribbon.ReadTimeout\\\":\\\"10000\\\",\\\"zuul.routes.test163.url\\\":\\\"http://www.163.com\\\",\\\"zuul.host.maxTotalConnections\\\":\\\"1024\\\",\\\"management.security.enabled\\\":\\\"false\\\",\\\"server.port\\\":\\\"9999\\\",\\\"zuul.semaphore.max-semaphores\\\":\\\"1024\\\",\\\"zuul.routes.test163.path\\\":\\\"/test163/**\\\",\\\"ribbon.MaxAutoRetriesNextServer\\\":\\\"2\\\",\\\"eureka.client.serviceUrl.defaultZone\\\":\\\"http://192.168.3.151:1111/eureka\\\",\\\"hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds\\\":\\\"10000\\\"}',b'0',b'0','apollo','2018-04-03 19:25:22','apollo','2018-04-03 19:25:22'),(6,'20180404175330-723164972d189c81','20180404095329-release','','zuulservice','default','application','{\\\"ribbon.MaxAutoRetries\\\":\\\"1\\\",\\\"spring.application.name\\\":\\\"sop-api-gateway\\\",\\\"ribbon.ConnectTimeout\\\":\\\"10000\\\",\\\"hystrix.command.default.execution.timeout.enabled\\\":\\\"true\\\",\\\"zuul.host.connect-timeout-millis\\\":\\\"10000\\\",\\\"ribbon.OkToRetryOnAllOperations\\\":\\\"true\\\",\\\"zuul.host.maxPerRouteConnections\\\":\\\"512\\\",\\\"eureka.instance.prefer-ip-address\\\":\\\"true\\\",\\\"zuul.host.socket-timeout-millis\\\":\\\"10000\\\",\\\"zuul.ignored-services\\\":\\\"\\\\\\\"*\\\\\\\"\\\",\\\"ribbon.ReadTimeout\\\":\\\"10000\\\",\\\"zuul.routes.test163.url\\\":\\\"http://www.163.com\\\",\\\"zuul.host.maxTotalConnections\\\":\\\"1024\\\",\\\"management.security.enabled\\\":\\\"false\\\",\\\"server.port\\\":\\\"9999\\\",\\\"zuul.semaphore.max-semaphores\\\":\\\"1024\\\",\\\"zuul.routes.test163.path\\\":\\\"/test163/**\\\",\\\"ribbon.MaxAutoRetriesNextServer\\\":\\\"2\\\",\\\"eureka.client.serviceUrl.defaultZone\\\":\\\"http://130.75.131.236:1111/eureka\\\",\\\"hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds\\\":\\\"10000\\\"}',b'0',b'0','apollo','2018-04-04 17:53:30','apollo','2018-04-04 17:53:30'),(7,'20180404175634-723164972d189c82','20180404095633-release','','zuulservice','default','application','{\\\"ribbon.MaxAutoRetries\\\":\\\"1\\\",\\\"eureka.client.register-with-eureka\\\":\\\"false\\\",\\\"spring.application.name\\\":\\\"sop-api-gateway\\\",\\\"ribbon.ConnectTimeout\\\":\\\"10000\\\",\\\"hystrix.command.default.execution.timeout.enabled\\\":\\\"true\\\",\\\"zuul.host.connect-timeout-millis\\\":\\\"10000\\\",\\\"ribbon.OkToRetryOnAllOperations\\\":\\\"true\\\",\\\"zuul.host.maxPerRouteConnections\\\":\\\"512\\\",\\\"eureka.instance.prefer-ip-address\\\":\\\"true\\\",\\\"zuul.host.socket-timeout-millis\\\":\\\"10000\\\",\\\"zuul.ignored-services\\\":\\\"\\\\\\\"*\\\\\\\"\\\",\\\"ribbon.ReadTimeout\\\":\\\"10000\\\",\\\"zuul.routes.test163.url\\\":\\\"http://www.163.com\\\",\\\"zuul.host.maxTotalConnections\\\":\\\"1024\\\",\\\"management.security.enabled\\\":\\\"false\\\",\\\"server.port\\\":\\\"9999\\\",\\\"zuul.semaphore.max-semaphores\\\":\\\"1024\\\",\\\"zuul.routes.test163.path\\\":\\\"/test163/**\\\",\\\"ribbon.MaxAutoRetriesNextServer\\\":\\\"2\\\",\\\"eureka.client.serviceUrl.defaultZone\\\":\\\"http://130.75.131.236:1111/eureka\\\",\\\"hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds\\\":\\\"10000\\\"}',b'0',b'0','apollo','2018-04-04 17:56:35','apollo','2018-04-04 17:56:35'),(8,'20180404193915-723164972d357e89','20180404113911-release','','zuulservice','default','application','{\\\"ribbon.MaxAutoRetries\\\":\\\"1\\\",\\\"spring.application.name\\\":\\\"sop-api-gateway\\\",\\\"ribbon.ConnectTimeout\\\":\\\"10000\\\",\\\"hystrix.command.default.execution.timeout.enabled\\\":\\\"true\\\",\\\"zuul.host.connect-timeout-millis\\\":\\\"10000\\\",\\\"ribbon.OkToRetryOnAllOperations\\\":\\\"true\\\",\\\"zuul.host.maxPerRouteConnections\\\":\\\"512\\\",\\\"eureka.instance.prefer-ip-address\\\":\\\"true\\\",\\\"zuul.host.socket-timeout-millis\\\":\\\"10000\\\",\\\"zuul.ignored-services\\\":\\\"\\\\\\\"*\\\\\\\"\\\",\\\"ribbon.ReadTimeout\\\":\\\"10000\\\",\\\"zuul.routes.test163.url\\\":\\\"http://www.163.com\\\",\\\"zuul.host.maxTotalConnections\\\":\\\"1024\\\",\\\"management.security.enabled\\\":\\\"false\\\",\\\"server.port\\\":\\\"9999\\\",\\\"zuul.semaphore.max-semaphores\\\":\\\"1024\\\",\\\"zuul.routes.test163.path\\\":\\\"/test163/**\\\",\\\"ribbon.MaxAutoRetriesNextServer\\\":\\\"2\\\",\\\"eureka.client.serviceUrl.defaultZone\\\":\\\"http://130.75.131.236:1111/eureka\\\",\\\"hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds\\\":\\\"10000\\\"}',b'0',b'0','apollo','2018-04-04 19:39:15','apollo','2018-04-04 19:39:15'),(9,'20180404194149-723164972d357e8a','20180404114148-release','','zuulservice','default','application','{\\\"ribbon.MaxAutoRetries\\\":\\\"1\\\",\\\"eureka.instance.instance-id\\\":\\\"${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}\\\",\\\"spring.application.name\\\":\\\"sop-api-gateway\\\",\\\"ribbon.ConnectTimeout\\\":\\\"10000\\\",\\\"hystrix.command.default.execution.timeout.enabled\\\":\\\"true\\\",\\\"zuul.host.connect-timeout-millis\\\":\\\"10000\\\",\\\"ribbon.OkToRetryOnAllOperations\\\":\\\"true\\\",\\\"zuul.host.maxPerRouteConnections\\\":\\\"512\\\",\\\"eureka.instance.prefer-ip-address\\\":\\\"true\\\",\\\"zuul.host.socket-timeout-millis\\\":\\\"10000\\\",\\\"zuul.ignored-services\\\":\\\"\\\\\\\"*\\\\\\\"\\\",\\\"ribbon.ReadTimeout\\\":\\\"10000\\\",\\\"zuul.routes.test163.url\\\":\\\"http://www.163.com\\\",\\\"zuul.host.maxTotalConnections\\\":\\\"1024\\\",\\\"management.security.enabled\\\":\\\"false\\\",\\\"server.port\\\":\\\"9999\\\",\\\"zuul.semaphore.max-semaphores\\\":\\\"1024\\\",\\\"zuul.routes.test163.path\\\":\\\"/test163/**\\\",\\\"ribbon.MaxAutoRetriesNextServer\\\":\\\"2\\\",\\\"eureka.client.serviceUrl.defaultZone\\\":\\\"http://130.75.131.236:1111/eureka\\\",\\\"hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds\\\":\\\"10000\\\"}',b'0',b'0','apollo','2018-04-04 19:41:50','apollo','2018-04-04 19:41:50'),(10,'20180626195919-7231d6ad3e03c099','20180626195916-release','','zuulservice','default','application','{\\\"ribbon.MaxAutoRetries\\\":\\\"1\\\",\\\"eureka.instance.instance-id\\\":\\\"${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}\\\",\\\"spring.application.name\\\":\\\"sop-api-gateway\\\",\\\"ribbon.ConnectTimeout\\\":\\\"10000\\\",\\\"hystrix.command.default.execution.timeout.enabled\\\":\\\"true\\\",\\\"zuul.host.connect-timeout-millis\\\":\\\"10000\\\",\\\"ribbon.OkToRetryOnAllOperations\\\":\\\"true\\\",\\\"zuul.host.maxPerRouteConnections\\\":\\\"512\\\",\\\"eureka.instance.prefer-ip-address\\\":\\\"true\\\",\\\"zuul.host.socket-timeout-millis\\\":\\\"10000\\\",\\\"zuul.ignored-services\\\":\\\"\\\\\\\"*\\\\\\\"\\\",\\\"ribbon.ReadTimeout\\\":\\\"10000\\\",\\\"zuul.routes.test163.url\\\":\\\"http://www.163.com\\\",\\\"zuul.host.maxTotalConnections\\\":\\\"1024\\\",\\\"management.security.enabled\\\":\\\"false\\\",\\\"server.port\\\":\\\"9000\\\",\\\"zuul.semaphore.max-semaphores\\\":\\\"1024\\\",\\\"zuul.routes.test163.path\\\":\\\"/test163/**\\\",\\\"ribbon.MaxAutoRetriesNextServer\\\":\\\"2\\\",\\\"eureka.client.serviceUrl.defaultZone\\\":\\\"http://130.75.131.236:1111/eureka\\\",\\\"hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds\\\":\\\"10000\\\"}',b'0',b'0','apollo','2018-06-26 19:59:20','apollo','2018-06-26 19:59:20'),(11,'20180626200041-7231d6ad3e03c09a','20180626200039-release','','zuulservice','default','application','{\\\"ribbon.MaxAutoRetries\\\":\\\"1\\\",\\\"eureka.instance.instance-id\\\":\\\"${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}\\\",\\\"spring.application.name\\\":\\\"sop-api-gateway\\\",\\\"ribbon.ConnectTimeout\\\":\\\"10000\\\",\\\"hystrix.command.default.execution.timeout.enabled\\\":\\\"true\\\",\\\"zuul.host.connect-timeout-millis\\\":\\\"10000\\\",\\\"ribbon.OkToRetryOnAllOperations\\\":\\\"true\\\",\\\"zuul.host.maxPerRouteConnections\\\":\\\"512\\\",\\\"eureka.instance.prefer-ip-address\\\":\\\"true\\\",\\\"zuul.host.socket-timeout-millis\\\":\\\"10000\\\",\\\"zuul.ignored-services\\\":\\\"\\\\\\\"*\\\\\\\"\\\",\\\"ribbon.ReadTimeout\\\":\\\"10000\\\",\\\"zuul.routes.test163.url\\\":\\\"http://www.163.com\\\",\\\"zuul.host.maxTotalConnections\\\":\\\"1024\\\",\\\"management.security.enabled\\\":\\\"false\\\",\\\"server.port\\\":\\\"9000\\\",\\\"zuul.semaphore.max-semaphores\\\":\\\"1024\\\",\\\"zuul.routes.test163.path\\\":\\\"/test163/**\\\",\\\"ribbon.MaxAutoRetriesNextServer\\\":\\\"2\\\",\\\"eureka.client.serviceUrl.defaultZone\\\":\\\"http://127.0.0.1:1111/eureka\\\",\\\"hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds\\\":\\\"10000\\\"}',b'0',b'0','apollo','2018-06-26 20:00:41','apollo','2018-06-26 20:00:41');\n\n#\n# Structure for table \"releasehistory\"\n#\n\nDROP TABLE IF EXISTS `releasehistory`;\nCREATE TABLE `releasehistory` (\n  `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',\n  `AppId` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'AppID',\n  `ClusterName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'ClusterName',\n  `NamespaceName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'namespaceName',\n  `BranchName` varchar(32) NOT NULL DEFAULT 'default' COMMENT '发布分支名',\n  `ReleaseId` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '关联的Release Id',\n  `PreviousReleaseId` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '前一次发布的ReleaseId',\n  `Operation` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '发布类型，0: 普通发布，1: 回滚，2: 灰度发布，3: 灰度规则更新，4: 灰度合并回主分支发布，5: 主分支发布灰度自动发布，6: 主分支回滚灰度自动发布，7: 放弃灰度',\n  `OperationContext` longtext NOT NULL COMMENT '发布上下文信息',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `IX_Namespace` (`AppId`,`ClusterName`,`NamespaceName`,`BranchName`),\n  KEY `IX_ReleaseId` (`ReleaseId`),\n  KEY `IX_DataChange_LastTime` (`DataChange_LastTime`)\n) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COMMENT='发布历史';\n\n#\n# Data for table \"releasehistory\"\n#\n\nINSERT INTO `releasehistory` VALUES (1,'SampleApp','default','application','default',1,0,0,'{}',b'0','apollo','2018-04-03 23:19:15','apollo','2018-04-03 23:19:15'),(2,'zuulservice','default','application','default',2,0,0,'{\\\"isEmergencyPublish\\\":false}',b'0','apollo','2018-04-04 00:12:29','apollo','2018-04-04 00:12:29'),(3,'zuulservice','default','application','default',3,2,0,'{\\\"isEmergencyPublish\\\":false}',b'0','apollo','2018-04-04 00:22:21','apollo','2018-04-04 00:22:21'),(4,'zuulservice','default','application','default',4,3,0,'{\\\"isEmergencyPublish\\\":false}',b'0','apollo','2018-04-04 00:55:50','apollo','2018-04-04 00:55:50'),(5,'zuulservice','default','application','default',5,4,0,'{\\\"isEmergencyPublish\\\":false}',b'0','apollo','2018-04-03 19:25:22','apollo','2018-04-03 19:25:22'),(6,'zuulservice','default','application','default',6,5,0,'{\\\"isEmergencyPublish\\\":false}',b'0','apollo','2018-04-04 17:53:31','apollo','2018-04-04 17:53:31'),(7,'zuulservice','default','application','default',7,6,0,'{\\\"isEmergencyPublish\\\":false}',b'0','apollo','2018-04-04 17:56:35','apollo','2018-04-04 17:56:35'),(8,'zuulservice','default','application','default',8,7,0,'{\\\"isEmergencyPublish\\\":false}',b'0','apollo','2018-04-04 19:39:15','apollo','2018-04-04 19:39:15'),(9,'zuulservice','default','application','default',9,8,0,'{\\\"isEmergencyPublish\\\":false}',b'0','apollo','2018-04-04 19:41:50','apollo','2018-04-04 19:41:50'),(10,'zuulservice','default','application','default',10,9,0,'{\\\"isEmergencyPublish\\\":false}',b'0','apollo','2018-06-26 19:59:20','apollo','2018-06-26 19:59:20'),(11,'zuulservice','default','application','default',11,10,0,'{\\\"isEmergencyPublish\\\":false}',b'0','apollo','2018-06-26 20:00:42','apollo','2018-06-26 20:00:42');\n\n#\n# Structure for table \"releasemessage\"\n#\n\nDROP TABLE IF EXISTS `releasemessage`;\nCREATE TABLE `releasemessage` (\n  `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',\n  `Message` varchar(1024) NOT NULL DEFAULT '' COMMENT '发布的消息内容',\n  `DataChange_LastTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `DataChange_LastTime` (`DataChange_LastTime`),\n  KEY `IX_Message` (`Message`(191))\n) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COMMENT='发布消息';\n\n#\n# Data for table \"releasemessage\"\n#\n\nINSERT INTO `releasemessage` VALUES (10,'zuulservice+default+application','2018-06-26 20:00:42');\n\n#\n# Structure for table \"serverconfig\"\n#\n\nDROP TABLE IF EXISTS `serverconfig`;\nCREATE TABLE `serverconfig` (\n  `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',\n  `Key` varchar(64) NOT NULL DEFAULT 'default' COMMENT '配置项Key',\n  `Cluster` varchar(32) NOT NULL DEFAULT 'default' COMMENT '配置对应的集群，default为不针对特定的集群',\n  `Value` varchar(2048) NOT NULL DEFAULT 'default' COMMENT '配置项值',\n  `Comment` varchar(1024) DEFAULT '' COMMENT '注释',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `IX_Key` (`Key`),\n  KEY `DataChange_LastTime` (`DataChange_LastTime`)\n) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COMMENT='配置服务自身配置';\n\n#\n# Data for table \"serverconfig\"\n#\n\nINSERT INTO `serverconfig` VALUES (1,'eureka.service.url','default','http://134.224.240.170:1111/eureka/','Eureka服务Url，多个service以英文逗号分隔 http://130.75.131.236:1111/eureka/  http://192.168.3.151:1111/eureka/',b'0','default','2018-04-03 23:19:15','','2018-06-26 11:52:52'),(2,'namespace.lock.switch','default','false','一次发布只能有一个人修改开关',b'0','default','2018-04-03 23:19:15','','2018-04-03 23:19:15'),(3,'item.value.length.limit','default','20000','item value最大长度限制',b'0','default','2018-04-03 23:19:15','','2018-04-03 23:19:15'),(4,'config-service.cache.enabled','default','false','ConfigService是否开启缓存，开启后能提高性能，但是会增大内存消耗！',b'0','default','2018-04-03 23:19:15','','2018-04-03 23:19:15'),(5,'item.key.length.limit','default','128','item key 最大长度限制',b'0','default','2018-04-03 23:19:15','','2018-04-03 23:19:15');\n"
  },
  {
    "path": "open-config-center/apollo/scripts/sql/apolloportaldb.sql",
    "content": " \n# Create Database\n# ------------------------------------------------------------\nCREATE DATABASE IF NOT EXISTS ApolloPortalDB DEFAULT CHARACTER SET = utf8mb4;\n\nUse ApolloPortalDB;\n\n# Host: 47.94.252.160  (Version 5.7.22)\n# Date: 2018-06-26 20:03:34\n# Generator: MySQL-Front 5.4  (Build 4.153) - http://www.mysqlfront.de/\n\n/*!40101 SET NAMES utf8 */;\n\n#\n# Structure for table \"app\"\n#\n\nDROP TABLE IF EXISTS `app`;\nCREATE TABLE `app` (\n  `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',\n  `AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID',\n  `Name` varchar(500) NOT NULL DEFAULT 'default' COMMENT '应用名',\n  `OrgId` varchar(32) NOT NULL DEFAULT 'default' COMMENT '部门Id',\n  `OrgName` varchar(64) NOT NULL DEFAULT 'default' COMMENT '部门名字',\n  `OwnerName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ownerName',\n  `OwnerEmail` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ownerEmail',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `AppId` (`AppId`(191)),\n  KEY `DataChange_LastTime` (`DataChange_LastTime`),\n  KEY `IX_Name` (`Name`(191))\n) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COMMENT='应用表';\n\n#\n# Data for table \"app\"\n#\n\nINSERT INTO `app` VALUES (1,'SampleApp','Sample App','TEST1','样例部门1','apollo','apollo@acme.com',b'0','default','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(2,'zuulservice','zuulservice-dev','TEST1','样例部门1','apollo','apollo@acme.com',b'0','apollo','2018-04-04 00:09:41','apollo','2018-04-04 00:09:41');\n\n#\n# Structure for table \"appnamespace\"\n#\n\nDROP TABLE IF EXISTS `appnamespace`;\nCREATE TABLE `appnamespace` (\n  `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',\n  `Name` varchar(32) NOT NULL DEFAULT '' COMMENT 'namespace名字，注意，需要全局唯一',\n  `AppId` varchar(32) NOT NULL DEFAULT '' COMMENT 'app id',\n  `Format` varchar(32) NOT NULL DEFAULT 'properties' COMMENT 'namespace的format类型',\n  `IsPublic` bit(1) NOT NULL DEFAULT b'0' COMMENT 'namespace是否为公共',\n  `Comment` varchar(64) NOT NULL DEFAULT '' COMMENT '注释',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT '' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `IX_AppId` (`AppId`),\n  KEY `Name_AppId` (`Name`,`AppId`),\n  KEY `DataChange_LastTime` (`DataChange_LastTime`)\n) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COMMENT='应用namespace定义';\n\n#\n# Data for table \"appnamespace\"\n#\n\nINSERT INTO `appnamespace` VALUES (1,'application','SampleApp','properties',b'0','default app namespace',b'0','','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(2,'application','zuulservice','properties',b'0','default app namespace',b'0','apollo','2018-04-04 00:09:41','apollo','2018-04-04 00:09:41');\n\n#\n# Structure for table \"authorities\"\n#\n\nDROP TABLE IF EXISTS `authorities`;\nCREATE TABLE `authorities` (\n  `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',\n  `Username` varchar(50) NOT NULL,\n  `Authority` varchar(50) NOT NULL,\n  PRIMARY KEY (`Id`)\n) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;\n\n#\n# Data for table \"authorities\"\n#\n\nINSERT INTO `authorities` VALUES (1,'apollo','ROLE_user');\n\n#\n# Structure for table \"consumer\"\n#\n\nDROP TABLE IF EXISTS `consumer`;\nCREATE TABLE `consumer` (\n  `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',\n  `AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID',\n  `Name` varchar(500) NOT NULL DEFAULT 'default' COMMENT '应用名',\n  `OrgId` varchar(32) NOT NULL DEFAULT 'default' COMMENT '部门Id',\n  `OrgName` varchar(64) NOT NULL DEFAULT 'default' COMMENT '部门名字',\n  `OwnerName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ownerName',\n  `OwnerEmail` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ownerEmail',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `AppId` (`AppId`(191)),\n  KEY `DataChange_LastTime` (`DataChange_LastTime`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='开放API消费者';\n\n#\n# Data for table \"consumer\"\n#\n\n\n#\n# Structure for table \"consumeraudit\"\n#\n\nDROP TABLE IF EXISTS `consumeraudit`;\nCREATE TABLE `consumeraudit` (\n  `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',\n  `ConsumerId` int(11) unsigned DEFAULT NULL COMMENT 'Consumer Id',\n  `Uri` varchar(1024) NOT NULL DEFAULT '' COMMENT '访问的Uri',\n  `Method` varchar(16) NOT NULL DEFAULT '' COMMENT '访问的Method',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `IX_DataChange_LastTime` (`DataChange_LastTime`),\n  KEY `IX_ConsumerId` (`ConsumerId`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='consumer审计表';\n\n#\n# Data for table \"consumeraudit\"\n#\n\n\n#\n# Structure for table \"consumerrole\"\n#\n\nDROP TABLE IF EXISTS `consumerrole`;\nCREATE TABLE `consumerrole` (\n  `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',\n  `ConsumerId` int(11) unsigned DEFAULT NULL COMMENT 'Consumer Id',\n  `RoleId` int(10) unsigned DEFAULT NULL COMMENT 'Role Id',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) DEFAULT '' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `IX_DataChange_LastTime` (`DataChange_LastTime`),\n  KEY `IX_RoleId` (`RoleId`),\n  KEY `IX_ConsumerId_RoleId` (`ConsumerId`,`RoleId`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='consumer和role的绑定表';\n\n#\n# Data for table \"consumerrole\"\n#\n\n\n#\n# Structure for table \"consumertoken\"\n#\n\nDROP TABLE IF EXISTS `consumertoken`;\nCREATE TABLE `consumertoken` (\n  `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',\n  `ConsumerId` int(11) unsigned DEFAULT NULL COMMENT 'ConsumerId',\n  `Token` varchar(128) NOT NULL DEFAULT '' COMMENT 'token',\n  `Expires` datetime NOT NULL DEFAULT '2099-01-01 00:00:00' COMMENT 'token失效时间',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  UNIQUE KEY `IX_Token` (`Token`),\n  KEY `DataChange_LastTime` (`DataChange_LastTime`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='consumer token表';\n\n#\n# Data for table \"consumertoken\"\n#\n\n\n#\n# Structure for table \"favorite\"\n#\n\nDROP TABLE IF EXISTS `favorite`;\nCREATE TABLE `favorite` (\n  `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',\n  `UserId` varchar(32) NOT NULL DEFAULT 'default' COMMENT '收藏的用户',\n  `AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID',\n  `Position` int(32) NOT NULL DEFAULT '10000' COMMENT '收藏顺序',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `AppId` (`AppId`(191)),\n  KEY `IX_UserId` (`UserId`),\n  KEY `DataChange_LastTime` (`DataChange_LastTime`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='应用收藏表';\n\n#\n# Data for table \"favorite\"\n#\n\n\n#\n# Structure for table \"permission\"\n#\n\nDROP TABLE IF EXISTS `permission`;\nCREATE TABLE `permission` (\n  `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',\n  `PermissionType` varchar(32) NOT NULL DEFAULT '' COMMENT '权限类型',\n  `TargetId` varchar(256) NOT NULL DEFAULT '' COMMENT '权限对象类型',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT '' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `IX_TargetId_PermissionType` (`TargetId`(191),`PermissionType`),\n  KEY `IX_DataChange_LastTime` (`DataChange_LastTime`)\n) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COMMENT='permission表';\n\n#\n# Data for table \"permission\"\n#\n\nINSERT INTO `permission` VALUES (1,'CreateCluster','SampleApp',b'0','','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(2,'CreateNamespace','SampleApp',b'0','','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(3,'AssignRole','SampleApp',b'0','','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(4,'ModifyNamespace','SampleApp+application',b'0','','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(5,'ReleaseNamespace','SampleApp+application',b'0','','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(6,'CreateCluster','zuulservice',b'0','apollo','2018-04-04 00:09:41','apollo','2018-04-04 00:09:41'),(7,'CreateNamespace','zuulservice',b'0','apollo','2018-04-04 00:09:41','apollo','2018-04-04 00:09:41'),(8,'AssignRole','zuulservice',b'0','apollo','2018-04-04 00:09:41','apollo','2018-04-04 00:09:41'),(9,'ModifyNamespace','zuulservice+application',b'0','apollo','2018-04-04 00:09:41','apollo','2018-04-04 00:09:41'),(10,'ReleaseNamespace','zuulservice+application',b'0','apollo','2018-04-04 00:09:41','apollo','2018-04-04 00:09:41');\n\n#\n# Structure for table \"role\"\n#\n\nDROP TABLE IF EXISTS `role`;\nCREATE TABLE `role` (\n  `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',\n  `RoleName` varchar(256) NOT NULL DEFAULT '' COMMENT 'Role name',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `IX_RoleName` (`RoleName`(191)),\n  KEY `IX_DataChange_LastTime` (`DataChange_LastTime`)\n) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COMMENT='角色表';\n\n#\n# Data for table \"role\"\n#\n\nINSERT INTO `role` VALUES (1,'Master+SampleApp',b'0','default','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(2,'ModifyNamespace+SampleApp+application',b'0','default','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(3,'ReleaseNamespace+SampleApp+application',b'0','default','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(4,'Master+zuulservice',b'0','apollo','2018-04-04 00:09:41','apollo','2018-04-04 00:09:41'),(5,'ModifyNamespace+zuulservice+application',b'0','apollo','2018-04-04 00:09:41','apollo','2018-04-04 00:09:41'),(6,'ReleaseNamespace+zuulservice+application',b'0','apollo','2018-04-04 00:09:41','apollo','2018-04-04 00:09:41');\n\n#\n# Structure for table \"rolepermission\"\n#\n\nDROP TABLE IF EXISTS `rolepermission`;\nCREATE TABLE `rolepermission` (\n  `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',\n  `RoleId` int(10) unsigned DEFAULT NULL COMMENT 'Role Id',\n  `PermissionId` int(10) unsigned DEFAULT NULL COMMENT 'Permission Id',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) DEFAULT '' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `IX_DataChange_LastTime` (`DataChange_LastTime`),\n  KEY `IX_RoleId` (`RoleId`),\n  KEY `IX_PermissionId` (`PermissionId`)\n) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COMMENT='角色和权限的绑定表';\n\n#\n# Data for table \"rolepermission\"\n#\n\nINSERT INTO `rolepermission` VALUES (1,1,1,b'0','','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(2,1,2,b'0','','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(3,1,3,b'0','','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(4,2,4,b'0','','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(5,3,5,b'0','','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(6,4,6,b'0','apollo','2018-04-04 00:09:41','apollo','2018-04-04 00:09:41'),(7,4,7,b'0','apollo','2018-04-04 00:09:41','apollo','2018-04-04 00:09:41'),(8,4,8,b'0','apollo','2018-04-04 00:09:41','apollo','2018-04-04 00:09:41'),(9,5,9,b'0','apollo','2018-04-04 00:09:41','apollo','2018-04-04 00:09:41'),(10,6,10,b'0','apollo','2018-04-04 00:09:41','apollo','2018-04-04 00:09:41');\n\n#\n# Structure for table \"serverconfig\"\n#\n\nDROP TABLE IF EXISTS `serverconfig`;\nCREATE TABLE `serverconfig` (\n  `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',\n  `Key` varchar(64) NOT NULL DEFAULT 'default' COMMENT '配置项Key',\n  `Value` varchar(2048) NOT NULL DEFAULT 'default' COMMENT '配置项值',\n  `Comment` varchar(1024) DEFAULT '' COMMENT '注释',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `IX_Key` (`Key`),\n  KEY `DataChange_LastTime` (`DataChange_LastTime`)\n) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COMMENT='配置服务自身配置';\n\n#\n# Data for table \"serverconfig\"\n#\n\nINSERT INTO `serverconfig` VALUES (1,'apollo.portal.envs','dev','可支持的环境列表',b'0','default','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(2,'organizations','[{\\\"orgId\\\":\\\"TEST1\\\",\\\"orgName\\\":\\\"样例部门1\\\"},{\\\"orgId\\\":\\\"TEST2\\\",\\\"orgName\\\":\\\"样例部门2\\\"}]','部门列表',b'0','default','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(3,'superAdmin','apollo','Portal超级管理员',b'0','default','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(4,'api.readTimeout','10000','http接口read timeout',b'0','default','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(5,'consumer.token.salt','someSalt','consumer token salt',b'0','default','2018-04-03 23:21:10','','2018-04-03 23:21:10');\n\n#\n# Structure for table \"userrole\"\n#\n\nDROP TABLE IF EXISTS `userrole`;\nCREATE TABLE `userrole` (\n  `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',\n  `UserId` varchar(128) DEFAULT '' COMMENT '用户身份标识',\n  `RoleId` int(10) unsigned DEFAULT NULL COMMENT 'Role Id',\n  `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',\n  `DataChange_CreatedBy` varchar(32) DEFAULT '' COMMENT '创建人邮箱前缀',\n  `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',\n  `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',\n  PRIMARY KEY (`Id`),\n  KEY `IX_DataChange_LastTime` (`DataChange_LastTime`),\n  KEY `IX_RoleId` (`RoleId`),\n  KEY `IX_UserId_RoleId` (`UserId`,`RoleId`)\n) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COMMENT='用户和role的绑定表';\n\n#\n# Data for table \"userrole\"\n#\n\nINSERT INTO `userrole` VALUES (1,'apollo',1,b'0','','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(2,'apollo',2,b'0','','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(3,'apollo',3,b'0','','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(4,'apollo',4,b'0','apollo','2018-04-04 00:09:41','apollo','2018-04-04 00:09:41'),(5,'apollo',5,b'0','apollo','2018-04-04 00:09:41','apollo','2018-04-04 00:09:41'),(6,'apollo',6,b'0','apollo','2018-04-04 00:09:41','apollo','2018-04-04 00:09:41');\n\n#\n# Structure for table \"users\"\n#\n\nDROP TABLE IF EXISTS `users`;\nCREATE TABLE `users` (\n  `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',\n  `Username` varchar(64) NOT NULL DEFAULT 'default' COMMENT '用户名',\n  `Password` varchar(64) NOT NULL DEFAULT 'default' COMMENT '密码',\n  `Email` varchar(64) NOT NULL DEFAULT 'default' COMMENT '邮箱地址',\n  `Enabled` tinyint(4) DEFAULT NULL COMMENT '是否有效',\n  PRIMARY KEY (`Id`)\n) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COMMENT='用户表';\n\n#\n# Data for table \"users\"\n#\n\nINSERT INTO `users` VALUES (1,'apollo','$2a$10$7r20uS.BQ9uBpf3Baj3uQOZvMVvB1RN3PYoKE94gtz2.WAOuiiwXS','apollo@acme.com',1);\n"
  },
  {
    "path": "open-config-center/apollo-gateway/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" 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  <parent>\n    <groupId>com.open.capacity</groupId>\n    <artifactId>open-config-center</artifactId>\n    <version>0.0.1-SNAPSHOT</version>\n  </parent>\n  <artifactId>apollo-gateway</artifactId>\n   <description>阿波罗整合网关</description>\n  <dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-eureka</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>com.ctrip.framework.apollo</groupId>\n\t\t\t<artifactId>apollo-client</artifactId>\n\t\t\t<version>0.10.0-SNAPSHOT</version>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-actuator</artifactId>\n\t\t\t<scope>true</scope>\n\t\t</dependency>\n\t\t<dependency>\n   \t\t\t <groupId>org.springframework.cloud</groupId>\n    \t\t\t <artifactId>spring-cloud-starter-zuul</artifactId>\n\t\t</dependency>\n\t</dependencies>\n \n \n  \n  <build>\n\t\t<plugins>\n\t\t\t<plugin>  \n                <groupId>org.apache.maven.plugins</groupId>  \n                <artifactId>maven-jar-plugin</artifactId>  \n                <configuration>  \n                    <archive>  \n                        <addMavenDescriptor>false</addMavenDescriptor>  \n                    </archive>  \n                </configuration>  \n            </plugin>  \n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>repackage</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t</plugins>\n\t\t<finalName>apollo-zuul</finalName>\n\t</build>\n  \n</project>"
  },
  {
    "path": "open-config-center/apollo-gateway/src/main/java/com/open/capacity/ApiGateWayApp.java",
    "content": "package com.open.capacity; \n\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.client.discovery.EnableDiscoveryClient;\nimport org.springframework.cloud.netflix.eureka.EnableEurekaClient;\nimport org.springframework.cloud.netflix.zuul.EnableZuulProxy;\nimport org.springframework.context.annotation.PropertySource;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport com.ctrip.framework.apollo.spring.annotation.EnableApolloConfig;\n/** \n* @author 作者 owen E-mail: 624191343@qq.com\n* @version 创建时间：2018年3月7日 下午4:44:46 \n* 类说明 \n*/\n\n\n@RestController\n@EnableZuulProxy\n@EnableDiscoveryClient\n@SpringBootApplication\npublic class ApiGateWayApp {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(ApiGateWayApp.class, args);\n\t}\n}\n\n\n \n\n "
  },
  {
    "path": "open-config-center/apollo-gateway/src/main/java/com/open/capacity/config/ZuulConfig.java",
    "content": "package com.open.capacity.config;\n\nimport org.springframework.boot.context.properties.ConfigurationProperties;\nimport org.springframework.cloud.context.config.annotation.RefreshScope;\nimport org.springframework.cloud.netflix.zuul.filters.ZuulProperties;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.context.annotation.Primary;\n\nimport com.ctrip.framework.apollo.spring.annotation.EnableApolloConfig;\n\n/** \n* @author 作者 owen E-mail: 624191343@qq.com\n* @version 创建时间：2018年2月23日 下午10:29:25 \n* 类说明 \n*/\n@Configuration\n@EnableApolloConfig\npublic class ZuulConfig  {\n\n    @Bean(name=\"zuul.CONFIGURATION_PROPERTIES\")\n    @RefreshScope\n    @ConfigurationProperties(\"zuul\")\n    @Primary\n    public ZuulProperties zuulProperties() {\n        return new ZuulProperties();\n    }\n}\n"
  },
  {
    "path": "open-config-center/apollo-gateway/src/main/java/com/open/capacity/config/ZuulConfigRreshConfig.java",
    "content": "package com.open.capacity.config;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.cloud.context.scope.refresh.RefreshScope;\nimport org.springframework.stereotype.Component;\n\nimport com.ctrip.framework.apollo.core.dto.ApolloConfig;\nimport com.ctrip.framework.apollo.model.ConfigChangeEvent;\nimport com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener;\n\n/** \n* @author 作者 owen E-mail: 624191343@qq.com\n* @version 创建时间：2018年3月7日 下午10:56:13 \n* 类说明 \n*/\n@Component\npublic class ZuulConfigRreshConfig {\n\n\t@Autowired\n\tprivate ZuulConfig  zuulConfig ;\n\t\n\t@Autowired\n\tprivate RefreshScope  refreshScope ;\n\t\n\t\n\t@ApolloConfigChangeListener\n\tpublic void onChange(ConfigChangeEvent changEvent){\n\t\trefreshScope.refresh(\"zuul.CONFIGURATION_PROPERTIES\") ;\n\t}\n}\n"
  },
  {
    "path": "open-config-center/apollo-gateway/src/main/resources/META-INF/app.properties",
    "content": "# test\napp.id=zuulservice\n"
  },
  {
    "path": "open-config-center/apollo-gateway/src/main/resources/bootstrap.yml",
    "content": "management:\n  security:\n    enabled: false\n    \n"
  },
  {
    "path": "open-config-center/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" 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  <parent>\n    <groupId>com.open.capacity</groupId>\n    <artifactId>open-capacity-platform</artifactId>\n    <version>0.0.1-SNAPSHOT</version>\n  </parent>\n  <artifactId>open-config-center</artifactId>\n  <packaging>pom</packaging>\n  <modules>\n  <!-- 阿波罗配置中心 -->\n\t\t<module>apollo</module>\n\t\t<module>apollo-gateway</module>\n  </modules>\t\t\n</project>"
  },
  {
    "path": "open-db-core/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" 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  <parent>\n    <groupId>com.open.capacity</groupId>\n    <artifactId>open-capacity-platform</artifactId>\n    <version>0.0.1-SNAPSHOT</version>\n  </parent>\n  <artifactId>open-db-core</artifactId>\n  \n  <dependencies> \n  \t<!-- 加入redis的处理 -->\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-data-redis</artifactId>\n\t\t</dependency>\n\t\t\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-cache</artifactId>\n        </dependency>\n\t\t<!-- 使用jasypt对springboot的datasource密码加密 -->\n\t\t<dependency>\n    \t\t<groupId>com.github.ulisesbocchio</groupId>\n    \t\t<artifactId>jasypt-spring-boot-starter</artifactId>\n    \t\t<version>1.8</version>\n\t\t</dependency>\n\t\t\n\t\t<!-- 增加jdbc的支持 -->\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-jdbc</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>mysql</groupId>\n\t\t\t<artifactId>mysql-connector-java</artifactId>\n\t\t</dependency>\n\n\t\t<!-- owen加入druid数据源 -->\n\t\t<dependency>\n\t\t\t<groupId>com.alibaba</groupId>\n\t\t\t<artifactId>druid</artifactId>\n\t\t\t<version>1.0.31</version>\n\t\t</dependency>\n\t\t<!-- owen增加oracle的支持 -->\n\t\t<dependency>\n\t\t\t<groupId>com.oracle</groupId>\n\t\t\t<artifactId>ojdbc6</artifactId>\n\t\t\t<version>11.2.0.3</version>\n\t\t</dependency>\n\n\t\t<!-- owen增加mybatis的支持 -->\n\t\t<dependency>\n\t\t\t<groupId>org.mybatis.spring.boot</groupId>\n\t\t\t<artifactId>mybatis-spring-boot-starter</artifactId>\n\t\t\t<version>1.3.0</version>\n\t\t</dependency>\n\t\t\n\t\t<dependency>\n            <groupId>com.alibaba</groupId>\n            <artifactId>fastjson</artifactId>\n            <version>1.2.32</version>\n        </dependency>\n\t\t\n\t\t\t<dependency>\n\t\t\t<groupId>commons-lang</groupId>\n\t\t\t<artifactId>commons-lang</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>commons-collections</groupId>\n\t\t\t<artifactId>commons-collections</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>commons-beanutils</groupId>\n\t\t\t<artifactId>commons-beanutils</artifactId>\n\t\t</dependency>\n\t\t <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-aop</artifactId>\n        </dependency>\n  \t</dependencies>\n  \t\n  \t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<finalName>${project.name}</finalName>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n  \t\n</project>"
  },
  {
    "path": "open-db-core/src/main/java/com/open/capacity/db/config/DruidConfig.java",
    "content": "package com.open.capacity.db.config;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.support.http.StatViewServlet;\nimport com.alibaba.druid.support.http.WebStatFilter;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;\nimport org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;\nimport org.springframework.boot.context.properties.ConfigurationProperties;\nimport org.springframework.boot.web.servlet.FilterRegistrationBean;\nimport org.springframework.boot.web.servlet.ServletRegistrationBean;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\n\nimport javax.sql.DataSource;\n\n/**\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2017年04月23日 下午20:01:06 类说明 *\n */\n\n@Configuration\n@ConditionalOnProperty(name = {\"spring.datasource.enable.dynamic\"}, matchIfMissing = true)\npublic class DruidConfig {\n\n    // 将druid纳入监控步骤如下\n    // 1通过springboot配置文件注入datasource中\n    @Bean\n    @ConfigurationProperties(prefix = \"spring.datasource\")\n    @ConditionalOnProperty(name = \"spring.datasource.type\", havingValue = \"com.alibaba.druid.pool.DruidDataSource\", matchIfMissing = false)\n    public DataSource druidDataSource() {\n        return DataSourceBuilder.create().type(DruidDataSource.class).build();\n    }\n\n    // 2.StatViewServlet注入到spring中\n    // Druid内置提供了一个StatViewServlet用于展示Druid的统计信息。\n    // 这个StatViewServlet的用途包括：\n    // 提供监控信息展示的html页面\n    // 提供监控信息的JSON API\n    // 注意：使用StatViewServlet，建议使用druid 0.2.6以上版本。\n    // 注入第三方没有注解的servlet\n    @Bean\n    @ConditionalOnProperty(name = \"spring.datasource.type\", havingValue = \"com.alibaba.druid.pool.DruidDataSource\", matchIfMissing = false)\n    public ServletRegistrationBean druidServlet() { // 主要实现WEB监控的配置处理\n        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new StatViewServlet(),\n                \"/druid/*\"); // 现在要进行druid监控的配置处理操作\n        servletRegistrationBean.addInitParameter(\"allow\", \"127.0.0.1,130.75.131.208,134.224.249.39,134.224.249.33\"); // 白名单\n        servletRegistrationBean.addInitParameter(\"deny\", \"192.168.28.200\"); // 黑名单\n        servletRegistrationBean.addInitParameter(\"loginUsername\", \"owen\"); // 用户名\n        servletRegistrationBean.addInitParameter(\"loginPassword\", \"1q2w3e4r\"); // 密码\n        servletRegistrationBean.addInitParameter(\"resetEnable\", \"false\"); // 是否可以重置数据源\n        return servletRegistrationBean;\n    }\n\n    // 3.对请求进行过滤\n    // WebStatFilter注入到spring容器中\n    // 注入第三方没有注解的过滤器\n    @Bean\n    @ConditionalOnProperty(name = \"spring.datasource.type\", havingValue = \"com.alibaba.druid.pool.DruidDataSource\", matchIfMissing = false)\n    public FilterRegistrationBean filterRegistrationBean() {\n        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();\n        filterRegistrationBean.setFilter(new WebStatFilter());\n        filterRegistrationBean.addUrlPatterns(\"/*\"); // 所有请求进行监控处理\n        filterRegistrationBean.addInitParameter(\"exclusions\", \"*.js,*.gif,*.jpg,*.css,/druid/*\");\n        return filterRegistrationBean;\n    }\n\n}\n"
  },
  {
    "path": "open-db-core/src/main/java/com/open/capacity/db/config/dynamic/annotation/DataSource.java",
    "content": "package com.open.capacity.db.config.dynamic.annotation;\n\nimport java.lang.annotation.*;\n\n/**\n * 数据源选择\n *\n * @author owen\n * @create 2017年7月2日\n */\n@Target({ElementType.METHOD, ElementType.TYPE})\n@Retention(RetentionPolicy.RUNTIME)\n@Documented\npublic @interface DataSource {\n    String name();\n}"
  },
  {
    "path": "open-db-core/src/main/java/com/open/capacity/db/config/dynamic/aop/DataSourceAspect.java",
    "content": "package com.open.capacity.db.config.dynamic.aop;\n\nimport com.open.capacity.db.config.dynamic.annotation.DataSource;\nimport com.open.capacity.db.config.dynamic.config.util.DataSourceHolder;\nimport com.open.capacity.db.config.dynamic.config.util.DataSourceKey;\nimport org.aspectj.lang.JoinPoint;\nimport org.aspectj.lang.annotation.After;\nimport org.aspectj.lang.annotation.Aspect;\nimport org.aspectj.lang.annotation.Before;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.core.annotation.Order;\n\n/**\n * 切换数据源Advice\n */\n@Aspect\n@Order(-1) // 保证该AOP在@Transactional之前执行\npublic class DataSourceAspect {\n\n    private static final Logger logger = LoggerFactory.getLogger(DataSourceAspect.class);\n\n    @Before(\"@annotation(ds)\")\n    public void changeDataSource(JoinPoint point, DataSource ds) throws Throwable {\n        String dsId = ds.name();\n        try {\n            DataSourceKey dataSourceKey = DataSourceKey.valueOf(dsId);\n            logger.debug(\"Use DataSource : {}\", ds.name(), point.getSignature());\n            DataSourceHolder.setDataSourceKey(dataSourceKey);\n        } catch (Exception e) {\n            logger.error(\"数据源[{}]不存在，使用默认数据源 > {}\", ds.name(), point.getSignature());\n        }\n\n\n    }\n\n    @After(\"@annotation(ds)\")\n    public void restoreDataSource(JoinPoint point, DataSource ds) {\n        logger.debug(\"Revert DataSource : \", ds.name(), point.getSignature());\n        DataSourceHolder.clearDataSourceKey();\n    }\n\n}"
  },
  {
    "path": "open-db-core/src/main/java/com/open/capacity/db/config/dynamic/config/DynamicDataSourceConfig.java",
    "content": "package com.open.capacity.db.config.dynamic.config;\n\nimport com.alibaba.druid.filter.Filter;\nimport com.alibaba.druid.filter.stat.StatFilter;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.support.http.StatViewServlet;\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallFilter;\nimport com.open.capacity.db.config.dynamic.config.util.DataSourceKey;\nimport com.open.capacity.db.config.dynamic.config.util.DynamicDataSource;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;\nimport org.springframework.boot.web.servlet.ServletRegistrationBean;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.context.annotation.Primary;\nimport org.springframework.context.annotation.PropertySource;\nimport org.springframework.jdbc.core.JdbcTemplate;\nimport org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;\nimport org.springframework.jdbc.datasource.DataSourceTransactionManager;\nimport org.springframework.transaction.PlatformTransactionManager;\n\nimport javax.sql.DataSource;\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * 定义数据源\n *\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2017年04月23日 下午20:01:06 类说明\n */\n@Configuration\n@PropertySource(\"classpath:jdbc.test.properties\")\n@ConditionalOnProperty(name = {\"spring.datasource.enable.dynamic\"}, matchIfMissing = false, havingValue = \"true\")\npublic class DynamicDataSourceConfig {\n\n    private Logger logger = LoggerFactory.getLogger(DynamicDataSourceConfig.class);\n\n    // crm库\n    @Value(\"${spring.datasource.primary.url:#{null}}\")\n    private String primaryDbUrl;\n    @Value(\"${spring.datasource.primary.username: #{null}}\")\n    private String primaryUsername;\n    @Value(\"${spring.datasource.primary.password:#{null}}\")\n    private String primaryPassword;\n\n    // bill库\n    @Value(\"${spring.datasource.secondary.url:#{null}}\")\n    private String secondaryDbUrl;\n    @Value(\"${spring.datasource.secondary.username: #{null}}\")\n    private String secondaryUsername;\n    @Value(\"${spring.datasource.secondary.password:#{null}}\")\n    private String secondaryPassword;\n\n    // 公共配置\n    @Value(\"${spring.datasource.driverClassName:#{null}}\")\n    private String driverClassName;\n    @Value(\"${spring.datasource.initialSize:#{null}}\")\n    private Integer initialSize;\n    @Value(\"${spring.datasource.minIdle:#{null}}\")\n    private Integer minIdle;\n    @Value(\"${spring.datasource.maxActive:#{null}}\")\n    private Integer maxActive;\n    @Value(\"${spring.datasource.maxWait:#{null}}\")\n    private Integer maxWait;\n    @Value(\"${spring.datasource.timeBetweenEvictionRunsMillis:#{null}}\")\n    private Integer timeBetweenEvictionRunsMillis;\n    @Value(\"${spring.datasource.minEvictableIdleTimeMillis:#{null}}\")\n    private Integer minEvictableIdleTimeMillis;\n    @Value(\"${spring.datasource.validationQuery:#{null}}\")\n    private String validationQuery;\n    @Value(\"${spring.datasource.testWhileIdle:#{null}}\")\n    private Boolean testWhileIdle;\n    @Value(\"${spring.datasource.testOnBorrow:#{null}}\")\n    private Boolean testOnBorrow;\n    @Value(\"${spring.datasource.testOnReturn:#{null}}\")\n    private Boolean testOnReturn;\n    @Value(\"${spring.datasource.poolPreparedStatements:#{null}}\")\n    private Boolean poolPreparedStatements;\n    @Value(\"${spring.datasource.maxPoolPreparedStatementPerConnectionSize:#{null}}\")\n    private Integer maxPoolPreparedStatementPerConnectionSize;\n    @Value(\"${spring.datasource.filters:#{null}}\")\n    private String filters;\n    @Value(\"{spring.datasource.connectionProperties:#{null}}\")\n    private String connectionProperties;\n\n    // 不需要纳入spring容器\n    public DataSource crmDataSource() {\n        DruidDataSource crmDataSource = new DruidDataSource();\n        crmDataSource.setUrl(this.primaryDbUrl);\n        crmDataSource.setUsername(this.primaryUsername);// 用户名\n        crmDataSource.setPassword(this.primaryPassword);// 密码\n        crmDataSource.setDriverClassName(driverClassName);\n        this.setCommons(crmDataSource);\n        return crmDataSource;\n    }\n\n    // 不需要纳入spring容器\n    public DataSource billDataSource() {\n        DruidDataSource billDataSource = new DruidDataSource();\n        billDataSource.setUrl(secondaryDbUrl);\n        billDataSource.setUsername(secondaryUsername);// 用户名\n        billDataSource.setPassword(secondaryPassword);// 密码\n        billDataSource.setDriverClassName(driverClassName);\n\n        this.setCommons(billDataSource);\n\n        return billDataSource;\n    }\n\n    @Bean // 只需要纳入动态数据源到spring容器\n    @Primary\n    public DataSource dataSource() {\n        DynamicDataSource dataSource = new DynamicDataSource();\n        DataSource crmDataSource = this.crmDataSource();\n        DataSource billDataSource = this.billDataSource();\n        dataSource.addDataSource(DataSourceKey.crm, crmDataSource);\n        dataSource.addDataSource(DataSourceKey.bill, billDataSource);\n        dataSource.setDefaultTargetDataSource(crmDataSource);\n\n        return dataSource;\n    }\n\n    @Bean\n    public StatFilter statFilter() {\n        StatFilter statFilter = new StatFilter();\n        statFilter.setLogSlowSql(true);\n        statFilter.setMergeSql(true);\n        statFilter.setSlowSqlMillis(1000);\n\n        return statFilter;\n    }\n\n    @Bean\n    public WallFilter wallFilter() {\n        WallFilter wallFilter = new WallFilter();\n\n        // 允许执行多条SQL\n        WallConfig config = new WallConfig();\n        config.setMultiStatementAllow(true);\n        wallFilter.setConfig(config);\n\n        return wallFilter;\n    }\n\n    @Bean\n    public ServletRegistrationBean druidServlet() {\n        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean();\n        servletRegistrationBean.setServlet(new StatViewServlet());\n        servletRegistrationBean.addUrlMappings(\"/druid/*\");\n        return servletRegistrationBean;\n    }\n\n    @Bean\n    public JdbcTemplate jdbcTemplate(DataSource dataSource) {\n\n        return new JdbcTemplate(dataSource);\n    }\n\n    @Bean\n    public NamedParameterJdbcTemplate namedParameterJdbcTemplate(DataSource dataSource) {\n\n        return new NamedParameterJdbcTemplate(dataSource);\n    }\n\n    private void setCommons(DruidDataSource dataSource) {\n        // configuration\n        if (initialSize != null) {\n            dataSource.setInitialSize(initialSize);\n        }\n        if (minIdle != null) {\n            dataSource.setMinIdle(minIdle);\n        }\n        if (maxActive != null) {\n            dataSource.setMaxActive(maxActive);\n        }\n        if (maxWait != null) {\n            dataSource.setMaxWait(maxWait);\n        }\n        if (timeBetweenEvictionRunsMillis != null) {\n            dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);\n        }\n        if (minEvictableIdleTimeMillis != null) {\n            dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);\n        }\n        if (validationQuery != null) {\n            dataSource.setValidationQuery(validationQuery);\n        }\n        if (testWhileIdle != null) {\n            dataSource.setTestWhileIdle(testWhileIdle);\n        }\n        if (testOnBorrow != null) {\n            dataSource.setTestOnBorrow(testOnBorrow);\n        }\n        if (testOnReturn != null) {\n            dataSource.setTestOnReturn(testOnReturn);\n        }\n        if (poolPreparedStatements != null) {\n            dataSource.setPoolPreparedStatements(poolPreparedStatements);\n        }\n        if (maxPoolPreparedStatementPerConnectionSize != null) {\n            dataSource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);\n        }\n\n        if (connectionProperties != null) {\n            dataSource.setConnectionProperties(connectionProperties);\n        }\n\n        List<Filter> filters = new ArrayList<>();\n        filters.add(statFilter());\n        filters.add(wallFilter());\n        dataSource.setProxyFilters(filters);\n    }\n\n    @Bean // 将数据源纳入spring事物管理\n    @Primary\n    public DataSourceTransactionManager transactionManager(DataSource dataSource) {\n        return new DataSourceTransactionManager(dataSource);\n    }\n\n    @Bean\n    public PlatformTransactionManager annotationDrivenTransactionManager(DataSource dataSource) {\n        return new DataSourceTransactionManager(dataSource);\n    }\n\n}\n"
  },
  {
    "path": "open-db-core/src/main/java/com/open/capacity/db/config/dynamic/config/util/DataSourceHolder.java",
    "content": "package com.open.capacity.db.config.dynamic.config.util;\n\n/**\n * 用于数据源切换\n *\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2017年04月23日 下午20:01:06 类说明\n */\npublic class DataSourceHolder {\n    private static final ThreadLocal<DataSourceKey> dataSourceKey = new ThreadLocal<>();\n\n    public static DataSourceKey getDataSourceKey() {\n        return dataSourceKey.get();\n    }\n\n    public static void setDataSourceKey(DataSourceKey type) {\n        dataSourceKey.set(type);\n    }\n\n    public static void clearDataSourceKey() {\n        dataSourceKey.remove();\n    }\n\n}"
  },
  {
    "path": "open-db-core/src/main/java/com/open/capacity/db/config/dynamic/config/util/DataSourceKey.java",
    "content": "package com.open.capacity.db.config.dynamic.config.util;\n\n/**\n * 数据源定义\n *\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2017年04月23日 下午20:01:06 类说明\n */\npublic enum DataSourceKey {\n    crm, bill\n}"
  },
  {
    "path": "open-db-core/src/main/java/com/open/capacity/db/config/dynamic/config/util/DynamicDataSource.java",
    "content": "package com.open.capacity.db.config.dynamic.config.util;\n\nimport org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;\n\nimport javax.sql.DataSource;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2017年04月23日 下午20:01:06 类说明 类说明\n */\npublic class DynamicDataSource extends AbstractRoutingDataSource {\n\n    private Map<Object, Object> datasources;\n\n    public DynamicDataSource() {\n        datasources = new HashMap<>();\n\n        super.setTargetDataSources(datasources);\n\n    }\n\n    public <T extends DataSource> void addDataSource(DataSourceKey key, T data) {\n        datasources.put(key, data);\n    }\n\n    @Override\n    protected Object determineCurrentLookupKey() {\n        return DataSourceHolder.getDataSourceKey();\n    }\n\n}\n"
  },
  {
    "path": "open-db-core/src/main/java/com/open/capacity/redis/config/RedisConfig.java",
    "content": "package com.open.capacity.redis.config;\n\nimport com.open.capacity.redis.config.util.RedisObjectSerializer;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.context.annotation.Primary;\nimport org.springframework.data.redis.connection.RedisConnectionFactory;\nimport org.springframework.data.redis.core.RedisTemplate;\nimport org.springframework.data.redis.serializer.RedisSerializer;\nimport org.springframework.data.redis.serializer.StringRedisSerializer;\n\n/**\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2017年04月23日 下午20:01:06 类说明\n */\n@Configuration\npublic class RedisConfig {\n\n    @Primary\n    @Bean(\"redisTemplate\")\n    // 没有此属性就不会装配bean 如果是单个redis 将此注解注释掉\n    @ConditionalOnProperty(name = \"spring.redis.cluster.nodes\", matchIfMissing = false)\n    public RedisTemplate<String, Object> getRedisTemplate(RedisConnectionFactory factory) {\n        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();\n        redisTemplate.setConnectionFactory(factory);\n\n        RedisSerializer stringSerializer = new StringRedisSerializer();\n        // RedisSerializer redisObjectSerializer = new RedisObjectSerializer();\n        RedisSerializer redisObjectSerializer = new RedisObjectSerializer();\n        redisTemplate.setKeySerializer(stringSerializer); // key的序列化类型\n        redisTemplate.setHashKeySerializer(stringSerializer);\n        redisTemplate.setValueSerializer(redisObjectSerializer); // value的序列化类型\n        redisTemplate.afterPropertiesSet();\n\n        redisTemplate.opsForValue().set(\"hello\", \"wolrd\");\n        return redisTemplate;\n    }\n\n    @Primary\n    @Bean(\"redisTemplate\")\n    @ConditionalOnProperty(name = \"spring.redis.host\", matchIfMissing = true)\n    public RedisTemplate<String, Object> getSingleRedisTemplate(RedisConnectionFactory factory) {\n        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();\n        redisTemplate.setConnectionFactory(factory);\n        redisTemplate.setKeySerializer(new StringRedisSerializer()); // key的序列化类型\n        redisTemplate.setValueSerializer(new RedisObjectSerializer()); // value的序列化类型\n        redisTemplate.afterPropertiesSet();\n        return redisTemplate;\n    }\n\n}\n"
  },
  {
    "path": "open-db-core/src/main/java/com/open/capacity/redis/config/util/FastJson2JsonRedisSerializer.java",
    "content": "package com.open.capacity.redis.config.util;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.serializer.SerializerFeature;\nimport org.springframework.data.redis.serializer.RedisSerializer;\nimport org.springframework.data.redis.serializer.SerializationException;\n\nimport java.nio.charset.Charset;\n\n/**\n * * @author 作者 owen E-mail: 624191343@qq.com\n *\n * @version 创建时间：2017年04月23日 下午20:01:06 类说明 类说明\n */\npublic class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T> {\n\n    public static final Charset DEFAULT_CHARSET = Charset.forName(\"UTF-8\");\n\n    private Class<T> clazz;\n\n    public FastJson2JsonRedisSerializer(Class<T> clazz) {\n        super();\n        this.clazz = clazz;\n    }\n\n    public byte[] serialize(T t) throws SerializationException {\n        if (t == null) {\n            return new byte[0];\n        }\n        return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);\n    }\n\n    public T deserialize(byte[] bytes) throws SerializationException {\n        if (bytes == null || bytes.length <= 0) {\n            return null;\n        }\n        String str = new String(bytes, DEFAULT_CHARSET);\n\n        return (T) JSON.parseObject(str, clazz);\n    }\n\n}\n"
  },
  {
    "path": "open-db-core/src/main/java/com/open/capacity/redis/config/util/RedisObjectSerializer.java",
    "content": "package com.open.capacity.redis.config.util;\n\nimport org.springframework.core.convert.converter.Converter;\nimport org.springframework.core.serializer.support.DeserializingConverter;\nimport org.springframework.core.serializer.support.SerializingConverter;\nimport org.springframework.data.redis.serializer.RedisSerializer;\nimport org.springframework.data.redis.serializer.SerializationException;\n\n/**\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2017年04月23日 下午20:01:06 类说明\n * 类说明\n */\n\n// 此时定义的序列化操作表示可以序列化所有类的对象，当然，这个对象所在的类一定要实现序列化接口\npublic class RedisObjectSerializer implements RedisSerializer<Object> {\n    private static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; // 做一个空数组，不是null\n    // 为了方便进行对象与字节数组的转换，所以应该首先准备出两个转换器\n    private Converter<Object, byte[]> serializingConverter = new SerializingConverter();\n    private Converter<byte[], Object> deserializingConverter = new DeserializingConverter();\n\n    @Override\n    public byte[] serialize(Object obj) throws SerializationException {\n        if (obj == null) { // 这个时候没有要序列化的对象出现，所以返回的字节数组应该就是一个空数组\n            return EMPTY_BYTE_ARRAY;\n        }\n        return this.serializingConverter.convert(obj); // 将对象变为字节数组\n    }\n\n    @Override\n    public Object deserialize(byte[] data) throws SerializationException {\n        if (data == null || data.length == 0) { // 此时没有对象的内容信息\n            return null;\n        }\n        return this.deserializingConverter.convert(data);\n    }\n\n}"
  },
  {
    "path": "open-db-core/src/main/java/mybatis.cfg.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE configuration   \n    PUBLIC \"-//mybatis.org//DTD Config 3.0//EN\"   \n    \"http://mybatis.org/dtd/mybatis-3-config.dtd\">\n<configuration>\n\t<!-- 进行Mybatis的相应的环境的属性定义 -->\n\t<settings>\t<!-- 在本项目之中开启二级缓存 -->\n\t\t<setting name=\"cacheEnabled\" value=\"false\"/>\n\t</settings>\n</configuration>\n"
  },
  {
    "path": "open-db-core/src/main/resources/jdbc.bcv.properties",
    "content": "################################common param##############################################\nspring.datasource.type=com.alibaba.druid.pool.DruidDataSource\nspring.datasource.driverClassName=oracle.jdbc.OracleDriver\n#spring.datasource.driverClassName=com.mysql.jdbc.Driver\nspring.datasource.initialSize=5\nspring.datasource.minIdle=5\nspring.datasource.maxActive=20\nspring.datasource.maxWait=60000\nspring.datasource.timeBetweenEvictionRunsMillis=60000\nspring.datasource.minEvictableIdleTimeMillis=300000\nspring.datasource.validationQuery=SELECT 1 FROM DUAL\nspring.datasource.testWhileIdle=true\nspring.datasource.testOnBorrow=false\nspring.datasource.testOnReturn=false\nspring.datasource.poolPreparedStatements=true\nspring.datasource.maxPoolPreparedStatementPerConnectionSize=20\nspring.datasource.filters=stat,wall,log4j\nspring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000\n################################crm##############################################\nspring.datasource.primary.driver-class-name=oracle.jdbc.OracleDriver\nspring.datasource.primary.url=jdbc:oracle:thin:@192.168.1.11:2268:jxcrm\nspring.datasource.primary.username=111111111\nspring.datasource.primary.password=111111111\n################################bill##############################################\nspring.datasource.secondary.driver-class-name=oracle.jdbc.OracleDriver\nspring.datasource.secondary.url=jdbc:oracle:thin:@192.168.1.11:3361:jxbill\nspring.datasource.secondary.username=111111111\nspring.datasource.secondary.password=111111111\n\n#spring.datasource.secondary.driver-class-name=com.mysql.jdbc.Driver\n#spring.datasource.secondary.url=jdbc:mysql://localhost:3306/myspringcloud?useSSL=false\n#spring.datasource.secondary.username=root\n#spring.datasource.secondary.password=123456\n\n\n\n\n"
  },
  {
    "path": "open-eureka-center/README.md",
    "content": "#  服务注册中心\n\n\n## 什么是服务治理 \n\n\t服务治理可以说是微服务架构中最为核心和基础的模块，它主要用来实现各个微服务实例的自动化注册与发现。\n## 为什么需要服务治理模块 \n\n\t在最初构建微服务系统的时候可能服务并不多，我们可以通过做一些静态配置来完成服务调用\n\n![](https://i.imgur.com/ASRyYWJ.png)\n\n此时看着一切都还正常。\n\n随着项目逐渐接近尾声，维护人员需要维护的服务越来越多，越来越复杂，最终形成大量的配置文件，维护将会变得越来越困难。此时，微服务应用实例自动化管理框架变得至关重要。\n\n## 服务治理框架需要完成什么任务 \n\n  ● 服务注册：在服务治理框架中，通常都会构建一个注册中心，每个服务单元向注册中心登记自己提供的服务，将主机与端口号、版本号、通信协议等一些附加信息告知注册中心，注册中心按服务名分类组织服务清单。\n\t![](https://i.imgur.com/lFXx64x.png)\n\n  ● 服务发现：我们的所有服务都已经注册到注册中心，并且在注册中心是按照服务名分类，并且由注册中心维护者服务的具体位置。所以调用方需要调用某个服务时，需要先和注册中心咨询，注册中心会返回被调用方服务的所有具体位置，调用方在根据某种轮询策略选择一个具体位置进行服务调用。\n\t![](https://i.imgur.com/tvnjhZD.png)\n\n## Netflix Eureka \n\n　　Spring Cloud Eureka,使用Netflix Eureka来实现服务注册与发现，它既包含了服务端组件，也包含了客户端组件。\n\n## Eureka服务端 \n\n　　Eureka服务端，我们也称为服务注册中心，他同其他服务注册中心一样，支持高可用配置。它依托于强一致性提供良好的服务实例可用性，可以应对多种不同的故障场景。\n　　如果Eureka以集群方式部署，当集群中有分片出现故障时，那么Eureka就转入自我保护模式。它允许在分片故障期间继续提供服务的发现和注册，当故障分片恢复运行时，集群中的其他分片会把它们的状态再次同步回来。\n\n## Eureka客户端 \n\n　　Eureka客户端，主要处理服务的注册与发现。客户端服务通过注解和参数配置的方式，嵌入在客户端应用程序的代码中，在应用程序运行时，Eureka客户端向注册中心注册自身提供的服务并周期性地发送心跳来更新它的服务租约。同时，他也能从服务端查询当前注册的服务信息并把它们缓存到本地并周期性地刷新服务状态。\n\n## 服务端与客户端的关系 \n\t![](https://i.imgur.com/oPDCh7u.png)\n\n## 搭建服务注册中心 \n\n1.创建Spring Boot工程，命名为open-eureka-center,并在pom中加入必要依赖，如下图：\n\t![](https://i.imgur.com/pFbNOUi.jpg)\n\n\n2.通过@EnableEurekaServer注解启动一个服务注册中心提供给其他应用进行对话。在Spring boot应用中添加这个注解就能开启此功能。\n\n ![](https://i.imgur.com/MlKBKTX.png)\n\n在默认情况下，该服务注册中心也会将自己作为客户端来尝试注册它自己，所以我们需要禁用它的客户端注册行为，只需在application.properties中增加如下配置：\n\nspring.application.name=open-eureka-server     \nserver.port=1111   \neureka.client.register-with-eureka=false   \neureka.client.fetch-registry=false  \neureka.client.serviceUrl.defaultZone=http://127.0.0.1:1111/eureka    \n\n● spring.application.name是服务名称，会在服务注册中心中看到这个属性的值，也是服务间调用时使用的名字。  \n● server.port是该服务启动时所使用的端口号。   \n● eureka.client.register-with-eureka因为该应用为注册中心，所以设置为false,代表不向服务注册中心注册自己。  \n● eureka.client.fetch-registry因为服务注册中心的职责就是维护服务服务实例，它并不需要去检索服务，所以设置为false。  \n\n\n完成上面的配置，在浏览器中输入http://127.0.0.1:1111/,如图：\n![](https://i.imgur.com/IC0omfS.jpg)\n\n此时的Instances currently registered with Eureka栏是空的，因为还没有服务注册到注册中心。   \n\n\n## 注册服务提供者（Eureka客户端）   \n1.创建eureka客户端工程\n\t\t![](https://i.imgur.com/PhjRZIj.png) \n2.修改HelloController类 在日志中打印服务的相关内容：  \n@RestController  \npublic class HelloController{  \n     \n     private final Logger logger = Logger.getLogger(getClass());  \n     @Autowired  \n     private DiscoveryClient client;  \n     \n     @RequestMapping(value=\"/hello\",method = RequestMethod.GET)  \n     public String index() {  \n         ServiceInstance instance = client.getLocalServiceInstance();  \n         logger.info(\"/hello , host:\"+ instance.getHost() + \", service_id:\" +   instance.getServiceId());  \n         return \"hello world\";  \n     }  \n}  \n    \n3.修改application.properties文件：\nspring.application.name=open-eureka-client\neureka.client.serviceUrl.defaultZone=http://127.0.0.1:1111/eureka/ \n● eureka.client.serviceUrl.defaultZone属性指定服务注册中心的地址。\n4.分别启动服务注册中心和open-eureka-client服务。结果如下图：\n![](https://i.imgur.com/lVxUsmu.jpg)\n\n通过访问http://127.0.0.1:7760/client/hello,直接向该服务发起请求  \n## 什么叫高可用   \n    高可用一般指服务的冗余，一个服务挂了，可以自动切换到另一个服务上，不会影响到客户体验。  \n高可用注册中心  \n    在微服务架构这样的分布式环境中，我们需要充分考虑发生故障的情况，所以在生产环境中必须对各个组件进行高可用部署，对于微服务如此，对于服务中心也一样。\n    Eureka Server的设计一开始就考虑了高可用问题，在Eureka的服务治理设计中，所有节点既是服务提供方，也是服务消费方，服务注册中心也不例外。在前一篇随笔中用到过这样的配置：  \neureka.client.register-with-eureka=false    \neureka.client.fetch-registry=false    \n现在回顾一下上面提到的这两个属性的作用：  \n  ● eureka.client.register-with-eureka=false设置为不将自己注册到服务注册中心（默认是true）  \n  ● eureka.client.fetch-registry=false设置为不检索服务（默认是true,在单节点服务注册中心的情况下，服务注册中心并不需要检索自己的服务）  \n    Eureka server的高可用实际上就是将自己作为服务向其他服务注册中心注册自己，这样就可以形成一组互相注册的服务注册中心，以实现服务清单的互相同步，达到高可用的效果。  \n![](https://i.imgur.com/pphn4Gw.png)\n\n## 常见问题   \n![](https://i.imgur.com/fUC3dXN.png)\n\n## eureka restful api  \n查看eureka的状态   \nhttp://127.0.0.1:7768/eureka/status  \n查看有多少服务  \nhttp://127.0.0.1:7778/eureka/apps   \n\n查看某个服务多少实例   \nhttp://127.0.0.1:7768/eureka/apps?name=OPEN-EUREKA-CLIENT  \n查看某个实例的状态  \nhttp://127.0.0.1:7768/eureka/apps/OPEN-EUREKA-CLIENT/open-eureka-client:192.168.45.1:7778  \n\n\n暂停微服务  \nhttp://127.0.0.1:7768/pause  \n查看某个实例的状态  \nhttp://127.0.0.1:7768/resume  \n\n\n\n \n "
  },
  {
    "path": "open-eureka-center/open-eureka-client/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\t<parent>\n\t\t<groupId>com.open.capacity</groupId>\n\t\t<artifactId>open-eureka-center</artifactId>\n\t\t<version>0.0.1-SNAPSHOT</version>\n\t</parent>\n\t<artifactId>open-eureka-client</artifactId>\n\n\t<properties>\n\t\t<docker.image.prefix>gitgeek</docker.image.prefix>\n\t</properties>\n\n\n\t<dependencies>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-eureka</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-actuator</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>com.fasterxml.jackson.dataformat</groupId>\n\t\t\t<artifactId>jackson-dataformat-xml</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>io.swagger</groupId>\n\t\t\t<artifactId>swagger-core</artifactId>\n\t\t\t<version>1.5.8</version>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>io.springfox</groupId>\n\t\t\t<artifactId>springfox-swagger2</artifactId>\n\t\t\t<version>2.4.0</version>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>io.springfox</groupId>\n\t\t\t<artifactId>springfox-swagger-ui</artifactId>\n\t\t\t<version>2.4.0</version>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>com.github.xiaoymin</groupId>\n\t\t\t<artifactId>swagger-bootstrap-ui</artifactId>\n\t\t\t<version>1.6</version>\n\t\t</dependency>\n\t</dependencies>\n\t<!-- 形成带第三方jar包的可执行jar包，jar包目录结构如下 application.properties lib META-INF mybatis \n\t\torg -->\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t\t<version>1.3.3.RELEASE</version>\n\t\t\t\t<configuration>\n\t\t\t\t</configuration>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>repackage</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\n\n\t\t\t<plugin>\n\t\t\t\t<groupId>com.spotify</groupId>\n\t\t\t\t<artifactId>docker-maven-plugin</artifactId>\n\t\t\t\t<version>0.4.13</version>\n\t\t\t\t<configuration>\n\t\t\t\t\t<imageName>${docker.image.prefix}/${project.artifactId}</imageName>\n\t\t\t\t\t<dockerDirectory>src/main/docker</dockerDirectory>\n\t\t\t\t\t<resources>\n\t\t\t\t\t\t<resource>\n\t\t\t\t\t\t\t<targetPath>/</targetPath>\n\t\t\t\t\t\t\t<directory>${project.build.directory}</directory>\n\t\t\t\t\t\t\t<include>${project.build.finalName}.jar</include>\n\t\t\t\t\t\t</resource>\n\t\t\t\t\t</resources>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t</plugins>\n\t\t<finalName>eureka-client</finalName>\n\t</build>\n\n</project>"
  },
  {
    "path": "open-eureka-center/open-eureka-client/src/main/docker/Dockerfile",
    "content": "FROM frolvlad/alpine-oraclejdk8\nVOLUME /tmp\nADD eureka-client.jar app.jar\nRUN sh -c 'touch /app.jar'\nENV JAVA_OPTS=\"\"\nENTRYPOINT [ \"sh\", \"-c\", \"java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar\" ]"
  },
  {
    "path": "open-eureka-center/open-eureka-client/src/main/java/com/open/capacity/EurekaClientApplication.java",
    "content": "package com.open.capacity;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.client.discovery.EnableDiscoveryClient;\nimport org.springframework.cloud.client.loadbalancer.LoadBalanced;\nimport org.springframework.cloud.netflix.eureka.EnableEurekaClient;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.web.client.RestTemplate;\n\n/**\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2017年11月28日 下午21:52:43\n * 类说明\n * 服务提供商 eureka的客户端程序\n */\n\n@EnableEurekaClient\n@EnableDiscoveryClient\n@SpringBootApplication\npublic class EurekaClientApplication {\n\n    public static void main(String[] args) {\n        SpringApplication.run(EurekaClientApplication.class, args);\n    }\n\n    /**\n     * 使用ribbon负载均衡器，用于服务提供商的负载均衡\n     *\n     * @return\n     */\n    @Bean\n    @LoadBalanced\n    public RestTemplate restTemplate() {\n        return new RestTemplate();\n    }\n}\n"
  },
  {
    "path": "open-eureka-center/open-eureka-client/src/main/java/com/open/capacity/config/SwaggerConfig.java",
    "content": "package com.open.capacity.config;\n\nimport org.springframework.context.MessageSource;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.context.support.ResourceBundleMessageSource;\nimport org.springframework.stereotype.Component;\nimport org.springframework.web.servlet.ViewResolver;\nimport org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;\nimport org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;\nimport org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;\nimport org.springframework.web.servlet.view.InternalResourceViewResolver;\nimport org.springframework.web.servlet.view.JstlView;\nimport springfox.documentation.builders.ParameterBuilder;\nimport springfox.documentation.builders.PathSelectors;\nimport springfox.documentation.builders.RequestHandlerSelectors;\nimport springfox.documentation.schema.ModelRef;\nimport springfox.documentation.service.Parameter;\nimport springfox.documentation.spi.DocumentationType;\nimport springfox.documentation.spring.web.plugins.Docket;\nimport springfox.documentation.swagger2.annotations.EnableSwagger2;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n\n@Component\n@Configuration\n@EnableSwagger2\npublic class SwaggerConfig extends WebMvcConfigurerAdapter {\n    @Bean\n    public Docket api() {\n\n        ParameterBuilder tokenPar = new ParameterBuilder();\n        List<Parameter> pars = new ArrayList<>();\n        tokenPar.name(\"Authorization\").description(\"令牌\").\n                modelRef(new ModelRef(\"string\")).\n                parameterType(\"header\").required(false).build();\n\n        pars.add(tokenPar.build());\n        return new Docket(DocumentationType.SWAGGER_2)\n                .select()\n                .apis(RequestHandlerSelectors.basePackage(\"com.open.capacity\"))\n                .apis(RequestHandlerSelectors.any())\n                .paths(PathSelectors.any())\n                .build().globalOperationParameters(pars);\n    }\n\n\n    @Bean\n    public ViewResolver viewResolver() {\n        InternalResourceViewResolver resolver = new InternalResourceViewResolver();\n        resolver.setViewClass(JstlView.class);\n        resolver.setPrefix(\"/\");\n        resolver.setSuffix(\".html\");\n        return resolver;\n\n    }\n\n    @Bean\n    public MessageSource messageSource() {\n        ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();\n        messageSource.setBasename(\"messages\");\n        return messageSource;\n    }\n\n    @Override\n    public void addResourceHandlers(ResourceHandlerRegistry registry) {\n        super.addResourceHandlers(registry);\n        registry.addResourceHandler(\"swagger-ui.html\")\n                .addResourceLocations(\"classpath:/META-INF/resources/\");\n        registry.addResourceHandler(\"/webjars/**\")\n                .addResourceLocations(\"classpath:/META-INF/resources/webjars/\");\n    }\n\n    @Override\n    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {\n        configurer.enable();\n    }\n}  "
  },
  {
    "path": "open-eureka-center/open-eureka-client/src/main/java/com/open/capacity/controller/EurekaController.java",
    "content": "package com.open.capacity.controller;\n\nimport com.fasterxml.jackson.core.JsonGenerator;\nimport com.fasterxml.jackson.core.JsonParser;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.fasterxml.jackson.dataformat.xml.XmlMapper;\nimport org.apache.http.client.config.RequestConfig;\nimport org.apache.http.client.methods.*;\nimport org.apache.http.entity.StringEntity;\nimport org.apache.http.impl.client.CloseableHttpClient;\nimport org.apache.http.impl.client.HttpClientBuilder;\nimport org.apache.http.message.BasicHeader;\nimport org.apache.http.util.EntityUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.cloud.client.ServiceInstance;\nimport org.springframework.cloud.client.discovery.DiscoveryClient;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.io.StringWriter;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2017年11月28日 下午21:52:43\n */\n@Controller\n@RequestMapping(\"/eureka/\")\npublic class EurekaController {\n\n\n    private static final Logger LOGGER = LoggerFactory.getLogger(EurekaController.class);\n\n    @Autowired\n    private DiscoveryClient discoveryClient;\n\n    private static String getoperate(String url, int post2get, String... str) {\n\n        String bodyAsString = \"\";\n        CloseableHttpClient httpClient = HttpClientBuilder.create().build();\n        try {\n            RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(10 * 1000)\n                    .setConnectTimeout(10 * 1000).setSocketTimeout(10 * 1000).build();\n            if (post2get == 1) {\n                HttpGet po = new HttpGet(url);\n\n                po.setConfig(requestConfig);\n                CloseableHttpResponse response = httpClient.execute(po);\n                bodyAsString = EntityUtils.toString(response.getEntity());\n                LOGGER.info(bodyAsString.toString());\n                return bodyAsString.toString();\n            }\n            if (post2get == 3) {\n\n                HttpPost po = new HttpPost(url);\n                po.addHeader(new BasicHeader(\"Cookie\", \"JSESSIONID=\" + str[0]));\n                po.setConfig(requestConfig);\n                String queryCase = \"name=admin&password=admin&remember=0\";\n                StringEntity reqEntity = new StringEntity(queryCase);\n                reqEntity.setContentType(\"application/x-www-form-urlencoded\");\n                po.setEntity(reqEntity);\n                CloseableHttpResponse response = httpClient.execute(po);\n                bodyAsString = EntityUtils.toString(response.getEntity());\n                LOGGER.info(bodyAsString.toString());\n                return bodyAsString;\n\n            }\n            if (post2get == 4) {\n                HttpGet po = new HttpGet(url);\n                po.addHeader(new BasicHeader(\"Cookie\", \"JSESSIONID=\" + str[0] + \";DISCONF=\" + str[1]));\n                po.setConfig(requestConfig);\n                CloseableHttpResponse response = httpClient.execute(po);\n                bodyAsString = EntityUtils.toString(response.getEntity());\n                LOGGER.info(bodyAsString.toString());\n                return bodyAsString;\n            }\n            if (post2get == 5) {\n\n                HttpPut po = new HttpPut(url);\n                po.addHeader(new BasicHeader(\"Cookie\", \"JSESSIONID=\" + str[0] + \";DISCONF=\" + str[1]));\n                po.setConfig(requestConfig);\n                String text = \"fileContent=\" + str[2];\n                StringEntity reqEntity = new StringEntity(text);\n                reqEntity.setContentType(\"application/x-www-form-urlencoded; charset=UTF-8\");\n                po.setEntity(reqEntity);\n                CloseableHttpResponse response = httpClient.execute(po);\n                bodyAsString = EntityUtils.toString(response.getEntity());\n                LOGGER.info(bodyAsString.toString());\n                return bodyAsString;\n            }\n            if (post2get == 6) {\n\n                HttpPost po = new HttpPost(url);\n                po.setConfig(requestConfig);\n                StringEntity reqEntity = new StringEntity(str[0]);\n                reqEntity.setContentType(\"application/json;charset=utf-8\");\n                po.setEntity(reqEntity);\n                CloseableHttpResponse response = httpClient.execute(po);\n                bodyAsString = EntityUtils.toString(response.getEntity());\n                LOGGER.info(bodyAsString.toString());\n                return bodyAsString;\n\n            } else {\n                HttpPost po = new HttpPost(url);\n                if (str != null && str.length > 0) {\n                    po.addHeader(new BasicHeader(\"Cookie\", \"JSESSIONID=\" + str[0]));\n                }\n                StringEntity reqEntity = new StringEntity(\"\");\n                reqEntity.setContentType(\"application/x-www-form-urlencoded; charset=UTF-8\");\n                po.setEntity(reqEntity);\n\n                po.setConfig(requestConfig);\n                CloseableHttpResponse response = httpClient.execute(po);\n                bodyAsString = EntityUtils.toString(response.getEntity());\n                LOGGER.info(bodyAsString.toString());\n                return bodyAsString;\n            }\n\n        } catch (Exception e) {\n            // TODO Auto-generated catch block\n            e.printStackTrace();\n        }\n        return \"{}\";\n    }\n\n    private static String getinfo(String url) {\n\n        String bodyAsString = \"\";\n        CloseableHttpClient httpClient = HttpClientBuilder.create().build();\n        try {\n            RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(50 * 1000)\n                    .setConnectTimeout(50 * 1000).setSocketTimeout(50 * 1000).build();\n            HttpGet po = new HttpGet(url);\n            if (url.indexOf(\"apps\") > 0) {\n                po.setHeader(\"Accept\", \"application/json\");\n            }\n            po.setConfig(requestConfig);\n            CloseableHttpResponse response = httpClient.execute(po);\n            bodyAsString = EntityUtils.toString(response.getEntity());\n            if (url.indexOf(\"apps\") > 0) {\n                LOGGER.info(bodyAsString.toString());\n                return bodyAsString;\n            }\n            ObjectMapper objectMapper = new ObjectMapper();\n            XmlMapper xmlMapper = new XmlMapper();\n            StringWriter w = new StringWriter();\n            JsonParser jp;\n            try {\n                jp = xmlMapper.getFactory().createParser(bodyAsString);\n                JsonGenerator jg = objectMapper.getFactory().createGenerator(w);\n                while (jp.nextToken() != null) {\n                    jg.copyCurrentEvent(jp);\n                }\n                jp.close();\n                jg.close();\n            } catch (Exception e) {\n                e.printStackTrace();\n            }\n\n            LOGGER.info(w.toString());\n            return w.toString();\n            // logger.info(\"RestContr \"+bodyAsString);\n        } catch (Exception e) {\n            // TODO Auto-generated catch block\n            e.printStackTrace();\n        }\n        return \"{}\";\n    }\n\n    private static String getinfo_put(String url) {\n\n        String bodyAsString = \"\";\n        CloseableHttpClient httpClient = HttpClientBuilder.create().build();\n        try {\n            RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(50 * 1000)\n                    .setConnectTimeout(50 * 1000).setSocketTimeout(50 * 1000).build();\n            HttpPut po = new HttpPut(url);\n\n            po.setConfig(requestConfig);\n            CloseableHttpResponse response = httpClient.execute(po);\n            bodyAsString = EntityUtils.toString(response.getEntity());\n\n            // LOGGER.info(w.toString());\n            return \"{}\";\n            // logger.info(\"RestContr \"+bodyAsString);\n        } catch (Exception e) {\n            // TODO Auto-generated catch block\n            e.printStackTrace();\n        }\n        return \"{}\";\n    }\n\n    private static String getinfo_del(String url) {\n        String bodyAsString = \"\";\n        CloseableHttpClient httpClient = HttpClientBuilder.create().build();\n        try {\n            RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(50000)\n                    .setConnectTimeout(50000).setSocketTimeout(50000).build();\n            HttpDelete po = new HttpDelete(url);\n\n            po.setConfig(requestConfig);\n            CloseableHttpResponse response = httpClient.execute(po);\n            bodyAsString = EntityUtils.toString(response.getEntity());\n\n            return \"{}\";\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n        return \"{}\";\n    }\n\n    @ResponseBody\n    @RequestMapping(value = \"status\", method = RequestMethod.GET)\n    public String status() {\n        String url = \"http://127.0.0.1:1111/eureka/status\";\n        return getinfo(url);\n    }\n\n    @ResponseBody\n    @RequestMapping(value = \"apps\", method = RequestMethod.GET)\n    public String apps() {\n        String url = \"http://127.0.0.1:1111/eureka/apps\";\n        return getinfo(url);\n    }\n\n    @ResponseBody\n    @RequestMapping(value = \"list\", method = RequestMethod.GET)\n    public Map list() {\n\n        List<String> list = discoveryClient.getServices();\n        Map res = new HashMap<>();\n        for (Iterator<String> it = list.iterator(); it.hasNext(); ) {\n            String serviceName = it.next();\n\n            List<ServiceInstance> instances = discoveryClient.getInstances(serviceName);\n\n            for (Iterator<ServiceInstance> its = instances.iterator(); its.hasNext(); ) {\n                ServiceInstance instance = its.next();\n\n                res.putAll(instance.getMetadata());\n\n            }\n\n        }\n\n        return res;\n    }\n\n    @ResponseBody\n    @RequestMapping(value = \"appsmd\", method = RequestMethod.POST)\n    public String appsmd(@RequestParam(value = \"name\", required = false) String str) {\n        String url = \"http://127.0.0.1:1111/eureka/apps/\" + str;\n        return getinfo(url);\n    }\n\n    @ResponseBody\n    @RequestMapping(value = {\"appsmddel\"}, method = RequestMethod.POST)\n    public String appsmddel(@RequestParam(value = \"name\", required = false) String str) {\n        String url = \"http://127.0.0.1:1111/metadata/apps/\" + str;\n        return getinfo_del(url);\n    }\n\n    @ResponseBody\n    @RequestMapping(value = \"operate\", method = RequestMethod.POST)\n    public String operate(@RequestBody HashMap<String, String> inmap) {\n        LOGGER.info(inmap.toString());\n        String op = \"\";\n        int post2get = 0;\n        if (inmap.get(\"operate\").equals(\"1\")) {// 暂停\n            op = \"pause\";\n        }\n        if (inmap.get(\"operate\").equals(\"2\")) {// 挂起\n            op = \"pause\";\n        }\n        if (inmap.get(\"operate\").equals(\"3\")) {// 恢复\n            op = \"resume\";\n        }\n        if (inmap.get(\"operate\").equals(\"4\")) {// 刷新\n            op = \"refresh\";\n        }\n        if (inmap.get(\"operate\").equals(\"5\")) {// 主机性能指标\n            op = \"metrics\";\n            post2get = 1;\n        }\n\n        String url = \"http://\" + inmap.get(\"ip\") + \":\" + inmap.get(\"port\") + \"/\" + op;\n\n        return getoperate(url, post2get, \"\", \"\");\n    }\n}\n"
  },
  {
    "path": "open-eureka-center/open-eureka-client/src/main/java/com/open/capacity/controller/EurekaManageController.java",
    "content": "package com.open.capacity.controller;\n\nimport com.netflix.appinfo.ApplicationInfoManager;\nimport com.netflix.appinfo.InstanceInfo.InstanceStatus;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport javax.annotation.Resource;\n\n/**\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2017年11月28日 下午21:52:43\n * 类说明\n */\n@RestController\npublic class EurekaManageController {\n\n    //手工启停标识\n    public static boolean upOrDown = true;\n    @Resource\n    private ApplicationInfoManager applicationInfoManager;\n\n    @RequestMapping(value = \"/resume\", method = RequestMethod.POST)\n    public void up() {\n        applicationInfoManager.getInfo().setStatus(InstanceStatus.UP);\n        upOrDown = true;\n    }\n\n\n    @RequestMapping(value = \"/pause\", method = RequestMethod.POST)\n    public void down() {\n        applicationInfoManager.getInfo().setStatus(InstanceStatus.DOWN);\n        upOrDown = false;\n    }\n\n}\n"
  },
  {
    "path": "open-eureka-center/open-eureka-client/src/main/java/com/open/capacity/controller/HelloController.java",
    "content": "package com.open.capacity.controller;\n\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RestController;\nimport org.springframework.web.client.RestTemplate;\n\nimport javax.annotation.Resource;\nimport javax.servlet.http.HttpServletRequest;\n\n/**\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2017年11月28日 下午21:52:43\n * 类说明\n */\n@RestController\npublic class HelloController {\n\n    @Resource\n    private RestTemplate restTemplate;\n\n    @GetMapping(\"/hello\")\n    public String hello(HttpServletRequest request) {\n\n        return \"hello:\t\" + request.getHeader(\"Authorization\");\n    }\n\n    @GetMapping(\"/route\")\n    public String hello1() {\n        String resp = this.restTemplate.getForObject(\"http://open-eureka-client/client/hello\", String.class);\n        return resp;\n    }\n}\n"
  },
  {
    "path": "open-eureka-center/open-eureka-client/src/main/java/com/open/capacity/health/EurekaClientHealthIndicator.java",
    "content": "package com.open.capacity.health;\n\nimport com.open.capacity.controller.EurekaManageController;\nimport org.springframework.boot.actuate.health.Health;\nimport org.springframework.boot.actuate.health.HealthIndicator;\nimport org.springframework.boot.actuate.health.Status;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class EurekaClientHealthIndicator implements HealthIndicator {\n\n\n    public Health health() {\n        if (EurekaManageController.upOrDown) {\n            return new Health.Builder(Status.UP).withDetail(\"details\", \"\").withDetail(\"status\", Status.UP).build();\n        } else {\n            return new Health.Builder(Status.DOWN).withDetail(\"details\", \"\").withDetail(\"status\", Status.DOWN).build();\n        }\n    }\n\n}  "
  },
  {
    "path": "open-eureka-center/open-eureka-client/src/main/java/com/open/capacity/health/EurekaHealthCheckHandler.java",
    "content": "package com.open.capacity.health;\n\nimport com.netflix.appinfo.HealthCheckHandler;\nimport com.netflix.appinfo.InstanceInfo.InstanceStatus;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.actuate.health.Status;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class EurekaHealthCheckHandler implements HealthCheckHandler {\n\n    @Autowired\n    private EurekaClientHealthIndicator halthIndicator;\n\n    public InstanceStatus getStatus(InstanceStatus currentStatus) {\n        Status status = halthIndicator.health().getStatus();\n        if (status.equals(Status.UP)) {\n            return InstanceStatus.UP;\n        } else {\n            return InstanceStatus.DOWN;\n        }\n    }\n\n}\n"
  },
  {
    "path": "open-eureka-center/open-eureka-client/src/main/resources/application.yml",
    "content": "server:\n  port: 7768\n  tomcat:\n    uri-encoding: UTF-8\nmanagement:\n  security:\n    enabled: false    \nspring:\n  application:\n    name: open-eureka-client\n  http:\n    encoding:\n      charset:  utf8\n      force: true\n      enabled: true\ndocker:\n  ipAddress: 47.94.252.160\n           \n           \neureka:\n  client:\n    healthcheck:\n      enabled: true\n    instance-info-replication-interval-seconds: 10  \n    serviceUrl:\n      defaultZone:  http://127.0.0.1:1111/eureka\n      #http://130.75.131.241:8761/eureka,http://130.75.131.248:8762/eureka\n      #http://134.224.249.33:1111/eureka/  正式库\n      #http://134.224.249.33:1111/eureka/  测试库\n      #http://127.0.0.1:8761/eureka,http://127.0.0.1:8762/eureka\n  instance:\n    prefer-ip-address: true\n    instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}\n#    instance-id: ${spring.application.name}:${docker.ipAddress}:${spring.application.instance_id:${server.port}}\n    lease-renewal-interval-in-seconds: 5  #每隔几秒告诉eureka服务器我还存活，用于心跳检测\n    lease-expiration-duration-in-seconds: 15 #如果心跳检测一直没有发送，10秒后会从eureka服务器中将此服务剔除\n    #注册实例文档\n    status-page-url: http://${spring.cloud.client.ipAddress}:${server.port}/doc.html # ${server.port}为该服务的端口号\n#    status-page-url: http://${docker.ipAddress}:${server.port}/client/doc.html # ${server.port}为该服务的端口号\n\n\nlogging:\n  level:\n    root: INFO\n    org.hibernate: INFO\n    org.hibernate.type.descriptor.sql.BasicBinder: TRACE\n    org.hibernate.type.descriptor.sql.BasicExtractor: TRACE\n    com.neusoft: DEBUG     \n    com.netflix: DEBUG                    #用于心跳检测输出的日志\n    \n\n\n"
  },
  {
    "path": "open-eureka-center/open-eureka-client/src/main/resources/logback.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<configuration scan=\"true\" scanPeriod=\"30 seconds\">\n    <appender name=\"STDOUT\" class=\"ch.qos.logback.core.ConsoleAppender\">\n        <encoder>\n            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>\n        </encoder>\n    </appender>\n    <appender name=\"ERROR\" class=\"ch.qos.logback.core.rolling.RollingFileAppender\">\n        <rollingPolicy class=\"ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy\">\n            <fileNamePattern>../logs/eureka-server-error.%d{yyyy-MM-dd}.%i.log</fileNamePattern>\n            <maxFileSize>100MB</maxFileSize>\n            <maxHistory>60</maxHistory>\n        </rollingPolicy>\n        <encoder>\n            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>\n        </encoder>\n        <triggeringPolicy class=\"ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy\">\n            <MaxFileSize>100MB</MaxFileSize>\n        </triggeringPolicy>\n        <filter class=\"ch.qos.logback.classic.filter.LevelFilter\"><!-- 只打印错误日志 -->\n            <level>ERROR</level>\n            <onMatch>ACCEPT</onMatch>\n            <onMismatch>DENY</onMismatch>\n        </filter>\n    </appender>\n    <appender name=\"INFO\" class=\"ch.qos.logback.core.rolling.RollingFileAppender\">\n        <rollingPolicy class=\"ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy\">\n            <fileNamePattern>../logs/eureka-server-info.%d{yyyy-MM-dd}.%i.log</fileNamePattern>\n            <maxFileSize>100MB</maxFileSize>\n            <maxHistory>60</maxHistory>\n        </rollingPolicy>\n        <encoder>\n            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>\n        </encoder>\n        <filter class=\"ch.qos.logback.classic.filter.LevelFilter\">\n            <level>INFO</level>\n            <onMatch>ACCEPT</onMatch>\n            <onMismatch>DENY</onMismatch>\n        </filter>\n    </appender>\n\n    <root level=\"info\">\n        <appender-ref ref=\"STDOUT\"/>\n        <appender-ref ref=\"ERROR\"/>\n        <appender-ref ref=\"INFO\"/>\n    </root>\n</configuration>\n"
  },
  {
    "path": "open-eureka-center/open-eureka-server/pom.xml",
    "content": "﻿<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\t<parent>\n\t\t<groupId>com.open.capacity</groupId>\n\t\t<artifactId>open-eureka-center</artifactId>\n\t\t<version>0.0.1-SNAPSHOT</version>\n\t</parent>\n\t<artifactId>open-eureka-server</artifactId>\n\n\n\t<properties>\n\t\t<docker.image.prefix>gitgeek</docker.image.prefix>\n\t</properties>\n\n\t<dependencies>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\t\t<!-- 注册eureka服务注册中心 -->\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-eureka-server</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-actuator</artifactId>\n\t\t</dependency>\n\n\n\t</dependencies>\n\t<!-- 形成带第三方jar包的可执行jar包，jar包目录结构如下 application.properties lib META-INF mybatis \n\t\torg -->\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>repackage</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\n\n\t\t\t<!-- 首先加入pom\n\n\t\t\t\t${docker.image.prefix} ： 这个是你的dockerhub注册上面的名字 gitgeek 这个是我注册的\n\t\t\t\t${project.artifactId}  ： 项目的名称\n\t\t\t\tdockerDirectory ： dockerfile的文件路径\n\n\t\t\t  -->\n            <plugin>\n                <groupId>com.spotify</groupId>\n                <artifactId>docker-maven-plugin</artifactId>\n                <version>0.4.13</version>\n                <configuration>\n                    <imageName>${docker.image.prefix}/${project.artifactId}</imageName>\n                    <dockerDirectory>src/main/docker</dockerDirectory>\n                    <resources>\n                        <resource>\n                            <targetPath>/</targetPath>\n                            <directory>${project.build.directory}</directory>\n                            <include>${project.build.finalName}.jar</include>\n                        </resource>\n                    </resources>\n                </configuration>\n            </plugin>\n\n\t\t</plugins>\n\t\t<finalName>eureka-server</finalName>\n\t</build>\n\n</project>"
  },
  {
    "path": "open-eureka-center/open-eureka-server/src/main/docker/Dockerfile",
    "content": "FROM frolvlad/alpine-oraclejdk8\nVOLUME /tmp\nADD eureka-server.jar app.jar\nRUN sh -c 'touch /app.jar'\nENV JAVA_OPTS=\"\"\nENTRYPOINT [ \"sh\", \"-c\", \"java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar\" ]"
  },
  {
    "path": "open-eureka-center/open-eureka-server/src/main/java/com/open/capacity/EurekaServerApp.java",
    "content": "package com.open.capacity;\n\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.boot.builder.SpringApplicationBuilder;\nimport org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;\nimport org.springframework.context.ConfigurableApplicationContext;\n\n/**\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2017年11月28日 下午22:50:29\n * 类说明\n * eureka高可用三台机器\n */\n@EnableEurekaServer\n//@EnableEurekaClient\n@SpringBootApplication\npublic class EurekaServerApp {\n    public static void main(String[] args) {\n\n//    \t1本地启动采用此方法加载profiles文件\n//\t\tConfigurableApplicationContext context = new SpringApplicationBuilder(UnieapEurekaServerApplication.class).\n//\t\t\t\tprofiles(\"slave3\").run(args);\n\n//    \t2服务器采用此方法 java -jar   --spring.profiles.active=slave3;\n//    \t SpringApplication.run(DreiEurekaServerApp.class, args);\n        ConfigurableApplicationContext context = new SpringApplicationBuilder(EurekaServerApp.class).\n                profiles(\"slave0\").run(args);\n    }\n}\n"
  },
  {
    "path": "open-eureka-center/open-eureka-server/src/main/java/com/open/capacity/controller/EurekaController.java",
    "content": "package com.open.capacity.controller;\n\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2017年11月28日 下午22:50:29\n * 类说明\n */\n@RestController\npublic class EurekaController {\n\n    @GetMapping(\"/hello\")\n    public String hello() {\n        return \"hello\";\n    }\n\n}\n"
  },
  {
    "path": "open-eureka-center/open-eureka-server/src/main/java/com/open/capacity/listener/EurekaInstanceCanceledListener.java",
    "content": "package com.open.capacity.listener;\n\nimport com.netflix.discovery.shared.Applications;\nimport com.netflix.eureka.EurekaServerContextHolder;\nimport com.netflix.eureka.registry.PeerAwareInstanceRegistry;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.cloud.netflix.eureka.server.event.EurekaInstanceCanceledEvent;\nimport org.springframework.cloud.netflix.eureka.server.event.EurekaInstanceRegisteredEvent;\nimport org.springframework.cloud.netflix.eureka.server.event.EurekaInstanceRenewedEvent;\nimport org.springframework.cloud.netflix.eureka.server.event.EurekaRegistryAvailableEvent;\nimport org.springframework.context.ApplicationEvent;\nimport org.springframework.context.ApplicationListener;\nimport org.springframework.context.annotation.Configuration;\n\n/**\n * 用于监听eureka服务停机通知\n * Created by ace on 2017/7/8.\n */\n@Configuration\npublic class EurekaInstanceCanceledListener implements ApplicationListener {\n    private Logger log = LoggerFactory.getLogger(EurekaInstanceCanceledListener.class);\n\n    @Override\n    public void onApplicationEvent(ApplicationEvent applicationEvent) {\n        // 服务挂掉事件\n        if (applicationEvent instanceof EurekaInstanceCanceledEvent) {\n            EurekaInstanceCanceledEvent event = (EurekaInstanceCanceledEvent) applicationEvent;\n            // 获取当前Eureka实例中的节点信息\n            PeerAwareInstanceRegistry registry = EurekaServerContextHolder.getInstance().getServerContext().getRegistry();\n            Applications applications = registry.getApplications();\n            // 遍历获取已注册节点中与当前失效节点ID一致的节点信息\n            applications.getRegisteredApplications().forEach((registeredApplication) -> {\n                registeredApplication.getInstances().forEach((instance) -> {\n                    if (instance.getInstanceId().equals(event.getServerId())) {\n                        log.debug(\"服务：\" + instance.getAppName() + \" 挂啦。。。\");\n                        // // TODO: 2017/9/3 扩展消息提醒 邮件、手机短信、微信等\n                    }\n                });\n            });\n\n\n        }\n        if (applicationEvent instanceof EurekaInstanceRegisteredEvent) {\n            EurekaInstanceRegisteredEvent event = (EurekaInstanceRegisteredEvent) applicationEvent;\n            log.debug(\"服务：\" + event.getInstanceInfo().getAppName() + \" 注册成功啦。。。\");\n        }\n        if (applicationEvent instanceof EurekaInstanceRenewedEvent) {\n            EurekaInstanceRenewedEvent event = (EurekaInstanceRenewedEvent) applicationEvent;\n            log.debug(\"心跳检测服务：\" + event.getInstanceInfo().getAppName() + \"。。\");\n        }\n        if (applicationEvent instanceof EurekaRegistryAvailableEvent) {\n            log.debug(\"服务 Aualiable。。\");\n        }\n\n    }\n\n\n}\n\n"
  },
  {
    "path": "open-eureka-center/open-eureka-server/src/main/resources/application.yml",
    "content": "server:\n  port: 1111\nspring:\n  application:\n    name: open-eureka-server\n  profiles: slave0\nmanagement:\n  security:\n    enabled: false  \neureka:\n  server:\n    shouldUseReadOnlyResponseCache: true #eureka是CAP理论种基于AP策略，为了保证强一致性关闭此切换CP 默认不关闭 false关闭\n    enable-self-preservation: false    #关闭服务器自我保护，客户端心跳检测15分钟内错误达到80%服务会保护，导致别人还认为是好用的服务\n    eviction-interval-timer-in-ms: 60000 #清理间隔（单位毫秒，默认是60*1000）5秒将客户端剔除的服务在服务注册列表中剔除# \n    response-cache-update-interval-ms: 3000  ##eureka server刷新readCacheMap的时间，注意，client读取的是readCacheMap，这个时间决定了多久会把readWriteCacheMap的缓存更新到readCacheMap上 #eureka server刷新readCacheMap的时间，注意，client读取的是readCacheMap，这个时间决定了多久会把readWriteCacheMap的缓存更新到readCacheMap上默认30s\n    response-cache-auto-expiration-in-seconds: 180   ##eureka server缓存readWriteCacheMap失效时间，这个只有在这个时间过去后缓存才会失效，失效前不会更新，过期后从registry重新读取注册服务信息，registry是一个ConcurrentHashMap。\n  client: \n    register-with-eureka: false  #false:不作为一个客户端注册到注册中心\n    fetch-registry: false      #为true时，可以启动，但报异常：Cannot execute request on any known server\n    instance-info-replication-interval-seconds: 10 \n    service-url:\n      defaultZone: http://127.0.0.1:1111/eureka\n  instance:\n    prefer-ip-address: true\n    instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}\n    lease-renewal-interval-in-seconds: 30    ## 续约更新时间间隔（默认30秒）\n    lease-expiration-duration-in-seconds: 90 # 续约到期时间（默认90秒）  \nribbon:\n  ServerListRefreshInterval: 1000    \nlogging:\n  level:\n#    root: INFO\n    com.open: INFO  \n    org.hibernate: INFO\n    org.hibernate.type.descriptor.sql.BasicBinder: TRACE\n    org.hibernate.type.descriptor.sql.BasicExtractor: TRACE\n    \n---\nserver:\n  port: 1111\nspring:\n  application:\n    name: open-eureka-server\n  profiles: slave1\nmanagement:\n  security:\n    enabled: false   \neureka:\n  server:\n    enable-self-preservation: true    #关闭服务器自我保护，客户端心跳检测15分钟内错误达到80%服务会保护，导致别人还认为是好用的服务\n    eviction-interval-timer-in-ms: 15000 #清理间隔（单位毫秒，默认是60*1000）5秒将客户端剔除的服务在服务注册列表中剔除# \n  client: \n    register-with-eureka: true  #false:不作为一个客户端注册到注册中心\n    fetch-registry: true      #为true时，可以启动，但报异常：Cannot execute request on any known server\n    serviceUrl:\n      defaultZone: http://127.0.0.1:1111/eureka,http://127.0.0.1:1112/eureka,http://127.0.0.1:1113/eureka\n  instance:\n    prefer-ip-address: true\n    instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}\n    lease-renewal-interval-in-seconds: 30    ## 续约更新时间间隔（默认30秒）\n    lease-expiration-duration-in-seconds: 90 # 续约到期时间（默认90秒）  \nlogging:\n  level:\n    root: INFO\n    com.drei: DEBUG    \n    org.springframework.web: INFO\n    org.hibernate: INFO\n    org.hibernate.type.descriptor.sql.BasicBinder: TRACE\n    org.hibernate.type.descriptor.sql.BasicExtractor: TRACE\n    \n---\n\nserver:\n  port: 1112\nspring:\n  application:\n    name: open-eureka-server\n  profiles: slave2\nmanagement:\n  security:\n    enabled: false   \neureka:\n  server:\n    enable-self-preservation: true    #关闭服务器自我保护，客户端心跳检测15分钟内错误达到80%服务会保护，导致别人还认为是好用的服务\n    eviction-interval-timer-in-ms: 15000 #5秒将客户端剔除的服务在服务注册列表中剔除\n  client: \n    register-with-eureka: true  #false:不作为一个客户端注册到注册中心\n    fetch-registry: true      #为true时，可以启动，但报异常：Cannot execute request on any known server\n    serviceUrl:\n      defaultZone: http://127.0.0.1:1111/eureka,http://127.0.0.1:1112/eureka,http://127.0.0.1:1113/eureka\n  instance:\n    prefer-ip-address: true\n    instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}\n    lease-renewal-interval-in-seconds: 30    ## 续约更新时间间隔（默认30秒）\n    lease-expiration-duration-in-seconds: 90 # 续约到期时间（默认90秒）\nlogging:\n  level:\n    root: INFO\n    com.drei: DEBUG    \n    org.springframework.web: INFO\n    org.hibernate: INFO\n    org.hibernate.type.descriptor.sql.BasicBinder: TRACE\n    org.hibernate.type.descriptor.sql.BasicExtractor: TRACE\n---\n\nserver:\n  port: 1113\nspring:\n  application:\n    name: open-eureka-server\n  profiles: slave3\nmanagement:\n  security:\n    enabled: false   \neureka:\n  server:\n    enable-self-preservation: true    #关闭服务器自我保护，客户端心跳检测15分钟内错误达到80%服务会保护，导致别人还认为是好用的服务\n    eviction-interval-timer-in-ms: 15000 #5秒将客户端剔除的服务在服务注册列表中剔除\n  client: \n    register-with-eureka: true  #false:不作为一个客户端注册到注册中心\n    fetch-registry: true      #为true时，可以启动，但报异常：Cannot execute request on any known server\n    serviceUrl:\n      defaultZone: http://127.0.0.1:1111/eureka,http://127.0.0.1:1112/eureka,http://127.0.0.1:1113/eureka      \n  instance:\n    prefer-ip-address: true\n    instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}\n    lease-renewal-interval-in-seconds: 30    ## 续约更新时间间隔（默认30秒）\n    lease-expiration-duration-in-seconds: 90 # 续约到期时间（默认90秒）\nlogging:\n  level:\n    root: INFO\n    com.drei: DEBUG    \n    org.springframework.web: INFO\n    org.hibernate: INFO\n    org.hibernate.type.descriptor.sql.BasicBinder: TRACE\n    org.hibernate.type.descriptor.sql.BasicExtractor: TRACE\n"
  },
  {
    "path": "open-eureka-center/open-eureka-server/src/main/resources/templates/.keep",
    "content": ""
  },
  {
    "path": "open-eureka-center/open-eureka-server/src/main/resources/templates/eureka/.keep",
    "content": ""
  },
  {
    "path": "open-eureka-center/open-eureka-server/src/main/resources/templates/eureka/header.ftl",
    "content": "<#import \"/spring.ftl\" as spring />\n<nav class=\"navbar navbar-default\" role=\"navigation\" >\n  <div class=\"container\">\n    <div class=\"navbar-header\">\n      <a class=\"navbar-brand\" href=\"<@spring.url dashboardPath/>\"><span></span></a>\n      <button type=\"button\" class=\"navbar-toggle\" data-toggle=\"collapse\" data-target=\"#bs-example-navbar-collapse-1\">\n        <span class=\"sr-only\">切换导航</span>\n        <span class=\"icon-bar\"></span>\n        <span class=\"icon-bar\"></span>\n        <span class=\"icon-bar\"></span>\n      </button>\n    </div>\n    <div class=\"collapse navbar-collapse\" id=\"bs-example-navbar-collapse-1\">\n      <ul class=\"nav navbar-nav navbar-right\">\n        <li>\n          <a href=\"<@spring.url dashboardPath/>\">主页</a>\n        </li>\n        <li>\n          <a href=\"<@spring.url dashboardPath/>/lastn\">最近启动的1000个服务</a>\n        </li>\n      </ul>\n    </div>\n  </div>\n</nav>\n\n\n"
  },
  {
    "path": "open-eureka-center/open-eureka-server/src/main/resources/templates/eureka/lastn.ftl",
    "content": "<#import \"/spring.ftl\" as spring />\n<!doctype html>\n<!--[if lt IE 7]>      <html class=\"no-js lt-ie9 lt-ie8 lt-ie7\"> <![endif]-->\n<!--[if IE 7]>         <html class=\"no-js lt-ie9 lt-ie8\"> <![endif]-->\n<!--[if IE 8]>         <html class=\"no-js lt-ie9\"> <![endif]-->\n<!--[if gt IE 8]><!--> <html class=\"no-js\"> <!--<![endif]-->\n  <head>\n    <base href=\"<@spring.url basePath/>\">\n    <title>注册中心-事件</title>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"eureka/css/wro.css\">\n  </head>\n  <body id=\"three\">\n\n    <!--[if lt IE 7]>\n    <p>您使用的是旧版本的浏览器。请升级您的浏览器以改善您的体验。</p>\n    <![endif]-->\n\n    <#include \"header.ftl\">\n\n    <div class=\"container-fluid xd-container\">\n      <#include \"navbar.ftl\">\n\n    <div id=\"xd-jobs\" class=\"tab-pane active col-md-12\">\n        <ul class=\"nav nav-tabs\" role=\"tablist\" id=\"myTab\">\n          <li class=\"active\"><a data-toggle=\"tab\" href=\"#cancelled\">最后1000个取消的租约</a></li>\n          <li><a data-toggle=\"tab\" href=\"#registered\">最近1000份新注册租约</a></li>\n        </ul>\n        <div class=\"tab-content\">\n          <div class=\"tab-pane\" id=\"cancelled\">\n            <table id='lastNCanceled' class=\"table table-striped table-hover\">\n              <thead>\n                <tr><th>租约</th><th>时间戳</th></tr>\n              </thead>\n              <tbody>\n                <#if lastNCanceled?has_content>\n\t                <#list lastNCanceled as entry>\n\t                  <tr><td>${entry.date?datetime}</td><td>${entry.id}</td></tr>\n\t                </#list>\n\t            <#else>\n\t              <tr><td colspan=\"2\">没有可用的资源</td></tr>\n\t            </#if>\n              <tbody>\n            </table>\n          </div>\n          <div class=\"tab-pane\" id=\"registered\">\n            <table id='lastNRegistered' class=\"table table-striped table-hover\">\n              <thead>\n                <tr><th>租约</th><th>时间戳</th></tr>\n              </thead>\n              <tbody>\n                <#if lastNRegistered?has_content>\n                  <#list lastNRegistered as entry>\n                    <tr><td>${entry.date?datetime}</td><td>${entry.id}</td></tr>\n                  </#list>\n                <#else>\n\t              <tr><td colspan=\"2\">没有可用的资源</td></tr>\n\t            </#if>\n              </tbody>\n            </table>\n          </div>\n      </div>\n    </div>\n    </div>\n    <script type=\"text/javascript\" src=\"eureka/js/wro.js\" ></script>\n    <script type=\"text/javascript\">\n      $(function () {\n        $('#myTab a:last').tab('show')\n      })\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "open-eureka-center/open-eureka-server/src/main/resources/templates/eureka/navbar.ftl",
    "content": "<h1>系统状态</h1>\n<div class=\"row\">\n  <div class=\"col-md-6\">\n    <table id='instances' class=\"table table-condensed table-striped table-hover\">\n      <#if amazonInfo??>\n        <tr>\n          <td>服务注册和发现</td>\n          <td>AMI: ${amiId!}</td>\n        </tr>\n        <tr>\n          <td>空间</td>\n          <td>${availabilityZone!}</td>\n        </tr>\n        <tr>\n          <td>示例Id</td>\n          <td>${instanceId!}</td>\n        </tr>\n      </#if>\n      <tr>\n        <td>环境</td>\n        <td>${environment!}</td>\n      </tr>\n      <tr>\n        <td>数据中心</td>\n        <td>${datacenter!}</td>\n      </tr>\n    </table>\n  </div>\n  <div class=\"col-md-6\">\n    <table id='instances' class=\"table table-condensed table-striped table-hover\">\n      <tr>\n        <td>当前时间</td>\n        <td>${currentTime}</td>\n      </tr>\n      <tr>\n        <td>运行</td>\n        <td>${upTime}</td>\n      </tr>\n      <tr>\n        <td>启用租约到期时间</td>\n        <td>${registry.leaseExpirationEnabled?c}</td>\n      </tr>\n      <tr>\n        <td>续订阈值</td>\n        <td>${registry.numOfRenewsPerMinThreshold}</td>\n      </tr>\n      <tr>\n        <td>续订 (最后一分钟)</td>\n        <td>${registry.numOfRenewsInLastMin}</td>\n      </tr>\n    </table>\n  </div>\n</div>\n\n<#if isBelowRenewThresold>\n    <#if !registry.selfPreservationModeEnabled>\n        <h4 id=\"uptime\"><font size=\"+1\" color=\"red\"><b>续订小于阈值。自保存模式已关闭。如果出现网络/其他问题, 这可能不会保护实例过期。</b></font></h4>\n    <#else>\n        <h4 id=\"uptime\"><font size=\"+1\" color=\"red\"><b> 紧急!注册中心可能不正确地验证身份, 当他们没有的情况下。续订小于阈值, 因此实例不会过期, 只是为了安全起见。</b></font></h4>\n    </#if>\n<#elseif !registry.selfPreservationModeEnabled>\n    <h4 id=\"uptime\"><font size=\"+1\" color=\"red\"><b>自保存模式已关闭。如果出现网络/其他问题, 这可能不会保护实例过期。</b></font></h4>\n</#if>\n\n<h1>服务副本</h1>\n<ul class=\"list-group\">\n  <#list replicas as replica>\n    <li class=\"list-group-item\"><a href=\"${replica.value}\">${replica.key}</a></li>\n  </#list>\n</ul>\n\n"
  },
  {
    "path": "open-eureka-center/open-eureka-server/src/main/resources/templates/eureka/status.ftl",
    "content": "<#import \"/spring.ftl\" as spring />\n<!doctype html>\n<!--[if lt IE 7]>      <html class=\"no-js lt-ie9 lt-ie8 lt-ie7\"> <![endif]-->\n<!--[if IE 7]>         <html class=\"no-js lt-ie9 lt-ie8\"> <![endif]-->\n<!--[if IE 8]>         <html class=\"no-js lt-ie9\"> <![endif]-->\n<!--[if gt IE 8]><!--> <html class=\"no-js\"> <!--<![endif]-->\n  <head>\n    <base href=\"<@spring.url basePath/>\">\n    <meta charset=\"utf-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n    <title>服务注册和发现</title>\n    <meta name=\"description\" content=\"\">\n    <meta name=\"viewport\" content=\"width=device-width\">\n\n    <link rel=\"stylesheet\" href=\"eureka/css/wro.css\">\n\n  </head>\n\n  <body id=\"one\">\n    <#include \"header.ftl\">\n    <div class=\"container-fluid xd-container\">\n      <#include \"navbar.ftl\">\n      <h1>当前注册的服务实例</h1>\n      <table id='instances' class=\"table table-striped table-hover\">\n        <thead  style=\"background-color: #328eba\">\n          <tr><th>应用</th><th>申请</th><th>可用性区域</th><th>状态</th></tr>\n        </thead>\n        <tbody>\n          <#if apps?has_content>\n            <#list apps as app>\n              <tr>\n                <td><b>${app.name}</b></td>\n                <td>\n                  <#list app.amiCounts as amiCount>\n                    <b>${amiCount.key}</b> (${amiCount.value})<#if amiCount_has_next>,</#if>\n                  </#list>\n                </td>\n                <td>\n                  <#list app.zoneCounts as zoneCount>\n                    <b>${zoneCount.key}</b> (${zoneCount.value})<#if zoneCount_has_next>,</#if>\n                  </#list>\n                </td>\n                <td>\n                  <#list app.instanceInfos as instanceInfo>\n                    <#if instanceInfo.isNotUp>\n                      <font color=red size=+1><b>\n                    </#if>\n                    <b>${instanceInfo.status}</b> (${instanceInfo.instances?size}) -\n                    <#if instanceInfo.isNotUp>\n                      </b></font>\n                    </#if>\n                    <#list instanceInfo.instances as instance>\n                      <#if instance.isHref>\n                        <a href=\"${instance.url}\" target=\"_blank\">${instance.id}</a>\n                      <#else>\n                        ${instance.id}\n                      </#if><#if instance_has_next>,</#if>\n                    </#list>\n                  </#list>\n                </td>\n              </tr>\n            </#list>\n          <#else>\n            <tr><td colspan=\"4\">没有可用的实例</td></tr>\n          </#if>\n\n        </tbody>\n      </table>\n\n      <h1>一般信息</h1>\n\n      <table id='generalInfo' class=\"table table-striped table-hover\">\n        <thead>\n          <tr><th>名称</th><th>值</th></tr>\n        </thead>\n        <tbody>\n          <#list statusInfo.generalStats?keys as stat>\n            <tr>\n              <td>${stat}</td><td>${statusInfo.generalStats[stat]!\"\"}</td>\n            </tr>\n          </#list>\n          <#list statusInfo.applicationStats?keys as stat>\n            <tr>\n              <td>${stat}</td><td>${statusInfo.applicationStats[stat]!\"\"}</td>\n            </tr>\n          </#list>\n        </tbody>\n      </table>\n\n      <h1>示例信息</h1>\n\n      <table id='instanceInfo' class=\"table table-striped table-hover\">\n        <thead>\n          <tr><th>名称</th><th>值</th></tr>\n        <thead>\n        <tbody>\n          <#list instanceInfo?keys as key>\n            <tr>\n              <td>${key}</td><td>${instanceInfo[key]!\"\"}</td>\n            </tr>\n          </#list>\n        </tbody>\n      </table>\n    </div>\n    <script type=\"text/javascript\" src=\"eureka/js/wro.js\" ></script>\n    <script type=\"text/javascript\">\n       $(document).ready(function() {\n         $('table.stripeable tr:odd').addClass('odd');\n         $('table.stripeable tr:even').addClass('even');\n       });\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "open-eureka-center/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" 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  <parent>\n    <groupId>com.open.capacity</groupId>\n    <artifactId>open-capacity-platform</artifactId>\n    <version>0.0.1-SNAPSHOT</version>\n  </parent>\n  <artifactId>open-eureka-center</artifactId>\n  <packaging>pom</packaging>\n  <modules>\n  \t<module>open-eureka-client</module>\n  \t<module>open-eureka-server</module>\n  </modules>\n</project>"
  },
  {
    "path": "open-layui-web/.gitignore",
    "content": "/bin/\n"
  },
  {
    "path": "open-layui-web/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\t<parent>\n\t\t<groupId>com.open.capacity</groupId>\n\t\t<artifactId>open-capacity-platform</artifactId>\n\t\t<version>0.0.1-SNAPSHOT</version>\n\t</parent>\n\t<artifactId>open-layui-web</artifactId>\n\n\t<properties>\n\t\t<java.version>1.8</java.version>\n\t\t<swagger.version>2.8.0</swagger.version>\n\t\t<google.guava>23.0</google.guava>\n\t\t<fastjson.version>1.2.46</fastjson.version>\n\t\t<poi.version>3.17</poi.version>\n\t\t<jwt.version>0.9.0</jwt.version>\n\t\t<maven.compiler.source>1.8</maven.compiler.source>\n\t\t<maven.compiler.target>1.8</maven.compiler.target>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<activiti.version>5.22.0</activiti.version>\n\t\t<docker.image.prefix>gitgeek</docker.image.prefix>\n\n\t\t<thymeleaf.version>3.0.9.RELEASE</thymeleaf.version>\n\t\t<!-- 布局功能的支持程序  thymeleaf3主程序  layout2以上版本 -->\n\t\t<!-- thymeleaf2   layout1-->\n\t\t<thymeleaf-layout-dialect.version>2.2.2</thymeleaf-layout-dialect.version>\n\t</properties>\n\n\t<dependencies>\n\n\t\t<dependency>\n\t\t\t<groupId>com.open.capacity</groupId>\n\t\t\t<artifactId>open-db-core</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-aop</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-actuator</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>com.google.guava</groupId>\n\t\t\t<artifactId>guava</artifactId>\n\t\t\t<version>${google.guava}</version>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.apache.commons</groupId>\n\t\t\t<artifactId>commons-lang3</artifactId>\n\t\t</dependency>\n\t\t<!-- <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> \n\t\t\t</dependency> -->\n\t\t<dependency>\n\t\t\t<groupId>com.fasterxml.jackson.core</groupId>\n\t\t\t<artifactId>jackson-databind</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>com.fasterxml.jackson.core</groupId>\n\t\t\t<artifactId>jackson-annotations</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>commons-codec</groupId>\n\t\t\t<artifactId>commons-codec</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>com.alibaba</groupId>\n\t\t\t<artifactId>fastjson</artifactId>\n\t\t\t<version>${fastjson.version}</version>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\t\t<!-- 加入spring security spring security oauth2的处理 -->\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-oauth2</artifactId>\n\t\t</dependency>\n\n\t\t<!-- druid需要此日志包 -->\n\t\t<dependency>\n\t\t\t<groupId>log4j</groupId>\n\t\t\t<artifactId>log4j</artifactId>\n\t\t\t<version>1.2.17</version>\n\t\t</dependency>\n\t\t\n\t\t<dependency>\n\t\t\t<groupId>io.springfox</groupId>\n\t\t\t<artifactId>springfox-bean-validators</artifactId>\n\t\t\t<version>${swagger.version}</version>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>io.springfox</groupId>\n\t\t\t<artifactId>springfox-swagger2</artifactId>\n\t\t\t<version>${swagger.version}</version>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>io.springfox</groupId>\n\t\t\t<artifactId>springfox-swagger-ui</artifactId>\n\t\t\t<version>${swagger.version}</version>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-mail</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.quartz-scheduler</groupId>\n\t\t\t<artifactId>quartz</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework</groupId>\n\t\t\t<artifactId>spring-context-support</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.apache.poi</groupId>\n\t\t\t<artifactId>poi</artifactId>\n\t\t\t<version>${poi.version}</version>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>io.jsonwebtoken</groupId>\n\t\t\t<artifactId>jjwt</artifactId>\n\t\t\t<version>${jwt.version}</version>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>com.fasterxml.jackson.dataformat</groupId>\n\t\t\t<artifactId>jackson-dataformat-xml</artifactId>\n\t\t</dependency>\n\t\t<!-- owen <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> \n\t\t\t<exclusions> <exclusion> <groupId>org.codehaus.groovy</groupId> <artifactId>groovy</artifactId> \n\t\t\t</exclusion> </exclusions> </dependency> <dependency> <groupId>org.thymeleaf.extras</groupId> \n\t\t\t<artifactId>thymeleaf-extras-springsecurity4</artifactId> </dependency> -->\n\n\t\t<!-- actviti begin-->\n\t\t<dependency>\n\t\t\t<groupId>org.activiti</groupId>\n\t\t\t<artifactId>activiti-engine</artifactId>\n\t\t\t<version>${activiti.version}</version>\n\t\t\t<exclusions>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<groupId>org.mybatis</groupId>\n\t\t\t\t\t<artifactId>mybatis</artifactId>\n\t\t\t\t</exclusion>\n\t\t\t</exclusions>\n\t\t</dependency>\n\n\n\t\t<dependency>\n\t\t\t<groupId>org.activiti</groupId>\n\t\t\t<artifactId>activiti-spring</artifactId>\n\t\t\t<version>${activiti.version}</version>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.activiti</groupId>\n\t\t\t<artifactId>activiti-modeler</artifactId>\n\t\t\t<version>${activiti.version}</version>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.activiti</groupId>\n\t\t\t<artifactId>activiti-diagram-rest</artifactId>\n\t\t\t<version>${activiti.version}</version>\n\t\t</dependency>\n\t\t<!-- actviti end-->\n\n\n\t\t<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t\t<version>1.16.10</version>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-thymeleaf</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>net.sourceforge.nekohtml</groupId>\n\t\t\t<artifactId>nekohtml</artifactId>\n\t\t\t<version>1.9.22</version>\n\t\t</dependency>\n\n\t</dependencies>\n\n\n\t<build>\n        <resources>\n            <resource>\n                <directory>src/main/resources</directory>\n                <includes>\n                    <include>**/*.properties</include>\n                    <include>**/*.yml</include>\n                    <include>**/*.xml</include>\n                    <include>**/*.tld</include>\n                    <include>**/*.p12</include>\n                    <include>**/*.conf</include>\n                    <include>**/*.txt</include>\n                    <include>**/*.wsdl</include>\n                    <include>**/*.xsd</include>\n                    <include>**/*.ftl</include>\n                    <include>**/*.json</include>\n                </includes>\n                <filtering>false</filtering>\n            </resource>\n            <resource>\n                <directory>src/main/java</directory>\n                <includes>\n                    <include>**/*.properties</include>\n                    <include>**/*.xml</include>\n                    <include>**/*.tld</include>\n                </includes>\n                <filtering>false</filtering>\n            </resource>\n            <resource>\n                <directory>src/main/view</directory>\n                <includes>\n                    <include>**/*.*</include>\n                </includes>\n                <filtering>false</filtering>\n            </resource>\n        </resources>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>repackage</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\n\t\t\t<plugin>\n\t\t\t\t<groupId>com.spotify</groupId>\n\t\t\t\t<artifactId>docker-maven-plugin</artifactId>\n\t\t\t\t<version>0.4.13</version>\n\t\t\t\t<configuration>\n\t\t\t\t\t<imageName>${docker.image.prefix}/${project.artifactId}</imageName>\n\t\t\t\t\t<dockerDirectory>src/main/docker</dockerDirectory>\n\t\t\t\t\t<resources>\n\t\t\t\t\t\t<resource>\n\t\t\t\t\t\t\t<targetPath>/</targetPath>\n\t\t\t\t\t\t\t<directory>${project.build.directory}</directory>\n\t\t\t\t\t\t\t<include>${project.build.finalName}.jar</include>\n\t\t\t\t\t\t</resource>\n\t\t\t\t\t</resources>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\n\t\t</plugins>\n\t\t<finalName>open-layui-web</finalName>\n\t</build>\n</project>"
  },
  {
    "path": "open-layui-web/src/main/docker/Dockerfile",
    "content": "FROM frolvlad/alpine-oraclejdk8\nVOLUME /tmp\nADD open-layui-web.jar app.jar\nRUN sh -c 'touch /app.jar'\nENV JAVA_OPTS=\"\"\nENTRYPOINT [ \"sh\", \"-c\", \"java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar\" ]"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/SecurityApplication.java",
    "content": "package com.open.capacity;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n * 启动类\n *\n * @author owen 624191343@qq.com\n */\n@SpringBootApplication\npublic class SecurityApplication {\n\n    public static void main(String[] args) {\n        SpringApplication.run(SecurityApplication.class, args);\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/activiti/config/ActPropertiesConfig.java",
    "content": "package com.open.capacity.activiti.config;\n\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.context.annotation.PropertySource;\n\n/**\n * @Author: [gitgeek]\n * @Date: [2018-05-14 20:23]\n * @Description: [ ]\n * @Version: [1.0.0]\n * @Copy: [com.zzg]\n */\n@Configuration\n@PropertySource(\"classpath:activiti.properties\")\npublic class ActPropertiesConfig {\n    @Value(\"${modelId}\")\n    private String modelId;\n\n    public String getModelId() {\n        return modelId;\n    }\n\n    public void setModelId(String modelId) {\n        this.modelId = modelId;\n    }\n\n    @Bean\n    public ActPropertiesConfig getActPropertiesConfig() {\n        return new ActPropertiesConfig();\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/activiti/config/ActivitiConfig.java",
    "content": "package com.open.capacity.activiti.config;\n\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.activiti.engine.*;\nimport org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;\nimport org.activiti.spring.ProcessEngineFactoryBean;\nimport org.activiti.spring.SpringProcessEngineConfiguration;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.transaction.PlatformTransactionManager;\n\nimport javax.sql.DataSource;\n\n/**\n * @Author: [gitgeek]\n * @Date: [2018-05-14 20:21]\n * @Description: [ activiti工作流配置 ]\n * @Version: [1.0.0]\n * @Copy: [com.zzg]\n */\n@Configuration\npublic class ActivitiConfig {\n\n    /**\n     * spring 集成 activiti\n     */\n    @Bean\n    public ProcessEngineConfiguration processEngineConfiguration(DataSource dataSource, PlatformTransactionManager transactionManager) {\n        SpringProcessEngineConfiguration processEngineConfiguration = new SpringProcessEngineConfiguration();\n        processEngineConfiguration.setDataSource(dataSource);\n        //表不存在创建表\n        processEngineConfiguration.setDatabaseSchemaUpdate(\"true\");\n        //指定数据库\n        processEngineConfiguration.setDatabaseType(\"mysql\");\n        processEngineConfiguration.setTransactionManager(transactionManager);\n        //历史变量\n        processEngineConfiguration.setHistory(\"full\");\n        //指定字体\n        processEngineConfiguration.setActivityFontName(\"宋体\");\n        processEngineConfiguration.setAnnotationFontName(\"宋体\");\n        processEngineConfiguration.setLabelFontName(\"宋体\");\n\n        return processEngineConfiguration;\n    }\n\n    //流程引擎，与spring整合使用factoryBean\n    @Bean\n    public ProcessEngineFactoryBean processEngine(ProcessEngineConfiguration processEngineConfiguration) {\n        ProcessEngineFactoryBean processEngineFactoryBean = new ProcessEngineFactoryBean();\n        processEngineFactoryBean.setProcessEngineConfiguration((ProcessEngineConfigurationImpl) processEngineConfiguration);\n        return processEngineFactoryBean;\n    }\n\n    @Bean\n    public RepositoryService repositoryService(ProcessEngine processEngine) {\n        return processEngine.getRepositoryService();\n    }\n\n    @Bean\n    public RuntimeService runtimeService(ProcessEngine processEngine) {\n        return processEngine.getRuntimeService();\n    }\n\n    @Bean\n    public TaskService taskService(ProcessEngine processEngine) {\n        return processEngine.getTaskService();\n    }\n\n    @Bean\n    public HistoryService historyService(ProcessEngine processEngine) {\n        return processEngine.getHistoryService();\n    }\n\n    @Bean\n    public FormService formService(ProcessEngine processEngine) {\n        return processEngine.getFormService();\n    }\n\n    @Bean\n    public IdentityService identityService(ProcessEngine processEngine) {\n        return processEngine.getIdentityService();\n    }\n\n    @Bean\n    public ManagementService managementService(ProcessEngine processEngine) {\n        return processEngine.getManagementService();\n    }\n\n    @Bean\n    public DynamicBpmnService dynamicBpmnService(ProcessEngine processEngine) {\n        return processEngine.getDynamicBpmnService();\n    }\n\n    @Bean\n    public ObjectMapper objectMapper() {\n        return new ObjectMapper();\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/activiti/controller/ActivitiController.java",
    "content": "package com.open.capacity.activiti.controller;\n\nimport com.alibaba.fastjson.JSON;\nimport com.fasterxml.jackson.databind.JsonNode;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.fasterxml.jackson.databind.node.ObjectNode;\nimport com.open.capacity.activiti.config.ActPropertiesConfig;\nimport com.open.capacity.activiti.entity.ActAssignee;\nimport com.open.capacity.activiti.entity.ActModel;\nimport com.open.capacity.activiti.entity.ProcessDefinition;\nimport com.open.capacity.activiti.service.ActAssigneeService;\nimport com.open.capacity.activiti.util.Checkbox;\nimport com.open.capacity.activiti.util.JsonUtil;\nimport com.open.capacity.activiti.util.ResultType;\nimport com.open.capacity.security.dao.RoleDao;\nimport com.open.capacity.security.model.Role;\nimport io.swagger.annotations.ApiOperation;\nimport org.activiti.bpmn.converter.BpmnXMLConverter;\nimport org.activiti.bpmn.model.BpmnModel;\nimport org.activiti.editor.constants.ModelDataJsonConstants;\nimport org.activiti.editor.language.json.converter.BpmnJsonConverter;\nimport org.activiti.engine.IdentityService;\nimport org.activiti.engine.RepositoryService;\nimport org.activiti.engine.RuntimeService;\nimport org.activiti.engine.impl.RepositoryServiceImpl;\nimport org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;\nimport org.activiti.engine.impl.pvm.process.ActivityImpl;\nimport org.activiti.engine.repository.Deployment;\nimport org.activiti.engine.repository.Model;\nimport org.activiti.engine.repository.ModelQuery;\nimport org.activiti.engine.repository.ProcessDefinitionQuery;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.*;\n\nimport javax.servlet.http.HttpServletRequest;\nimport java.io.FileInputStream;\nimport java.io.UnsupportedEncodingException;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * @Author: [gitgeek]\n * @Date: [2018-05-14 19:06]\n * @Description: [ ]\n * @Version: [1.0.0]\n * @Copy: [com.zzg]\n */\n@Controller\n@RequestMapping(value = \"/activiti\")\npublic class ActivitiController {\n\n    @Autowired\n    RepositoryService repositoryService;\n\n    @Autowired\n    RuntimeService runtimeService;\n\n    @Autowired\n    IdentityService identityService;\n\n    @Autowired\n    ActAssigneeService actAssigneeService;\n\n    @Autowired\n    ActPropertiesConfig actPropertiesConfig;\n\n    @Autowired\n    ObjectMapper objectMapper;\n\n    @Autowired\n    private RoleDao roleDao;\n\n    /**\n     * 部署列表\n     */\n    @GetMapping(value = \"/showAct\")\n    @ApiOperation(value = \"列表\")\n    @ResponseBody\n    public String showAct(org.springframework.ui.Model model, ProcessDefinition definition,\n                          String page, String limit) {\n        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();\n\n        List<org.activiti.engine.repository.ProcessDefinition> processDefinitionList = null;\n        if (definition != null) {\n            if (!StringUtils.isEmpty(definition.getDeploymentId())) {\n                processDefinitionQuery.deploymentId(definition.getDeploymentId());\n            }\n            if (!StringUtils.isEmpty(definition.getName())) {\n                processDefinitionQuery.processDefinitionNameLike(\"%\" + definition.getName() + \"%\");\n\n            }\n        }\n        processDefinitionList = processDefinitionQuery.listPage(Integer.valueOf(limit) * (Integer.valueOf(page) - 1), Integer.valueOf(limit));\n        long count = repositoryService.createDeploymentQuery().count();\n        List<ProcessDefinition> list = new ArrayList<>();\n        processDefinitionList.forEach(processDefinition -> list.add(new ProcessDefinition(processDefinition)));\n\n        ResultType resultType = new ResultType(count, list);\n        return JSON.toJSONString(resultType);\n    }\n\n    public List<ActivityImpl> getActivityList(String deploymentId) {\n        org.activiti.engine.repository.ProcessDefinition processDefinition = repositoryService\n                .createProcessDefinitionQuery().deploymentId(deploymentId).singleResult();\n        ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)\n                .getDeployedProcessDefinition(processDefinition.getId());\n        return processDefinitionEntity.getActivities();\n    }\n\n    /**\n     * 删除流程定义 级联 删除 流程节点绑定信息\n     *\n     * @param model\n     * @param id\n     * @return\n     */\n    @PostMapping(\"delDeploy\")\n    @ResponseBody\n    public JsonUtil delDeploy(org.springframework.ui.Model model, String id) {\n        JsonUtil j = new JsonUtil();\n        try {\n            List<ActivityImpl> activityList = getActivityList(id);\n            for (ActivityImpl activity : activityList) {\n                String nodeId = activity.getId();\n                if (StringUtils.isEmpty(nodeId) || \"start\".equals(nodeId) || \"end\".equals(nodeId)) {\n                    continue;\n                }\n                /**接触节点和代办关联*/\n                actAssigneeService.deleteByNodeId(nodeId);\n            }\n            repositoryService.deleteDeployment(id, true);\n            j.setMsg(\"删除成功\");\n        } catch (Exception e) {\n            j.setMsg(\"删除失败\");\n            j.setFlag(false);\n        }\n        return j;\n    }\n\n    /**\n     * 模型列表\n     */\n    @GetMapping(value = \"showAm\")\n    @ResponseBody\n    public String showModel(org.springframework.ui.Model model, ActModel actModel, String page,\n                            String limit) {\n        ModelQuery modelQuery = repositoryService.createModelQuery();\n        if (actModel != null) {\n            if (!StringUtils.isEmpty(actModel.getKey())) {\n                modelQuery.modelKey(actModel.getKey());\n            }\n            if (!StringUtils.isEmpty(actModel.getName())) {\n                modelQuery.modelNameLike(\"%\" + actModel.getName() + \"%\");\n            }\n        }\n        List<Model> models = modelQuery\n                .listPage(Integer.valueOf(limit) * (Integer.valueOf(page) - 1), Integer.valueOf(limit));\n        long count = repositoryService.createModelQuery().count();\n        List<ActModel> list = new ArrayList<>();\n        models.forEach(mo -> list.add(new ActModel(mo)));\n        ResultType resultType = new ResultType(count, list);\n        return JSON.toJSONString(resultType);\n    }\n\n\n    /**\n     * 发布流程\n     */\n    @PostMapping(value = \"open\")\n    @ResponseBody\n    public JsonUtil open(String id) {\n        String msg = \"发布成功\";\n        JsonUtil j = new JsonUtil();\n        try {\n            Model modelData = repositoryService.getModel(id);\n            byte[] bytes = repositoryService.getModelEditorSource(modelData.getId());\n\n            if (bytes == null) {\n                return JsonUtil.error(\"模型为空\");\n            }\n            JsonNode modelNode = null;\n            modelNode = new ObjectMapper().readTree(bytes);\n            BpmnModel model = new BpmnJsonConverter().convertToBpmnModel(modelNode);\n            if (model.getProcesses().size() == 0) {\n                return JsonUtil.error(\"数据不符合要求\");\n            }\n            byte[] bpmnBytes = new BpmnXMLConverter().convertToXML(model);\n            //发布流程\n            String processName = modelData.getName() + \".bpmn20.xml\";\n            String convertToXML = new String(bpmnBytes);\n\n            System.out.println(convertToXML);\n            Deployment deployment = repositoryService.createDeployment()\n                    .name(modelData.getName())\n                    .addString(processName, new String(bpmnBytes, \"UTF-8\"))\n                    .deploy();\n            modelData.setDeploymentId(deployment.getId());\n            repositoryService.saveModel(modelData);\n        } catch (Exception e) {\n            msg = \"发布数失败\";\n            j.setFlag(false);\n        }\n        j.setMsg(msg);\n        return j;\n    }\n\n\n    @PostMapping(\"delModel\")\n    @ResponseBody\n    public JsonUtil delModel(org.springframework.ui.Model model, String id) {\n        FileInputStream inputStream = null;\n        String modelId = actPropertiesConfig.getModelId();\n        if (id.equals(modelId)) {\n            return JsonUtil.error(\"演示禁止删除\");\n        }\n        JsonUtil j = new JsonUtil();\n        try {\n            repositoryService.deleteModel(id);\n            j.setMsg(\"删除成功\");\n        } catch (Exception e) {\n            j.setMsg(\"删除失败\");\n            j.setFlag(false);\n            e.printStackTrace();\n        }\n        return j;\n    }\n\n    @GetMapping(\"actUpdate/{id}\")\n    public String actUpdate(@PathVariable String id, String token) {\n        return \"redirect:/pages/activiti/modeler.html?modelId=\" + id + \"&token=\" + token;\n    }\n\n    /**\n     * 方法此有所参考 感谢我参考原作者：liuruijie\n     */\n    @GetMapping(value = \"goActiviti\")\n    public String goActiviti(String token) throws UnsupportedEncodingException {\n        Model model = repositoryService.newModel();\n\n        String name = \"新建流程\";\n        String description = \"\";\n        int revision = 1;\n        String key = \"processKey\";\n\n        ObjectNode modelNode = objectMapper.createObjectNode();\n        modelNode.put(ModelDataJsonConstants.MODEL_NAME, name);\n        modelNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, description);\n        modelNode.put(ModelDataJsonConstants.MODEL_REVISION, revision);\n\n        model.setName(name);\n        model.setKey(key);\n        model.setMetaInfo(modelNode.toString());\n\n        repositoryService.saveModel(model);\n        String id = model.getId();\n\n        //完善ModelEditorSource\n        ObjectNode editorNode = objectMapper.createObjectNode();\n        editorNode.put(\"id\", \"canvas\");\n        editorNode.put(\"resourceId\", \"canvas\");\n        ObjectNode stencilSetNode = objectMapper.createObjectNode();\n        stencilSetNode.put(\"namespace\",\n                \"http://b3mn.org/stencilset/bpmn2.0#\");\n        editorNode.put(\"stencilset\", stencilSetNode);\n        repositoryService.addModelEditorSource(id, editorNode.toString().getBytes(\"utf-8\"));\n        return \"redirect:/pages/activiti/modeler.html?modelId=\" + id;\n    }\n\n\n    /**\n     * 根据流程部署id获取节点并且传到前端\n     *\n     * @param deploymentId 部署id\n     * @param model\n     * @return\n     */\n    @GetMapping(\"goAssignee/{id}\")\n    public String goAssignee(@PathVariable(\"id\") String deploymentId, String token,\n                             org.springframework.ui.Model model) {\n\n        /**根据流程实例id查询出所有流程节点*/\n        List<ActivityImpl> activityList = getActivityList(deploymentId);\n\n        /**角色和节点关系封装成list*/\n        Map<String, Object> params = new HashMap<>();\n\n        List<Role> list = roleDao.list(params, null, null);\n        List<Checkbox> checkboxes = new ArrayList<>();\n        Checkbox checkbox = null;\n        Map<String, Object> map = null;\n        List<Map<String, Object>> mapList = new ArrayList<>();\n        List<ActAssignee> assigneeList = null;\n        List<Checkbox> checkboxList = null;\n        for (ActivityImpl activiti : activityList) {\n            map = new HashMap<>();\n            String name = (String) activiti.getProperty(\"name\");\n            if (StringUtils.isEmpty(name) || \"start\".equals(name) || \"end\".equals(name)) {\n                continue;\n            }\n            //节点id 、name、节点目前关联的角色 封装成进map\n            String nodeId = activiti.getId();\n            assigneeList = actAssigneeService.selectListByPage(new ActAssignee(nodeId));\n            List<String> strings = new ArrayList<>();\n            assigneeList.forEach(actAssignee1 -> strings.add(actAssignee1.getRoleId()));\n            map.put(\"id\", nodeId);\n            map.put(\"name\", name);\n            checkboxList = new ArrayList<>();\n            for (Role role : list) {\n                checkbox = new Checkbox();\n                checkbox.setId(role.getId().toString());\n                checkbox.setName(role.getName());\n                if (strings.contains(role.getId().toString())) {\n                    checkbox.setCheck(true);\n                }\n                checkboxList.add(checkbox);\n            }\n            map.put(\"boxJson\", checkboxList);\n            mapList.add(map);\n        }\n        model.addAttribute(\"actList\", mapList);\n\n        return \"activiti/deploy/act-node\";\n    }\n\n    /**\n     * 节点更新配置办理者(人/组)\n     *\n     * @param request\n     * @return\n     */\n    @PostMapping(\"goAssignee/updateNode\")\n    @ResponseBody\n    public JsonUtil updateNode(HttpServletRequest request) {\n        JsonUtil j = new JsonUtil();\n\n        Map<String, String[]> map = request.getParameterMap();\n        List<ActAssignee> assigneeList = new ArrayList<>();\n        ActAssignee assignee = null;\n        for (Map.Entry<String, String[]> entry : map.entrySet()) {\n            assignee = new ActAssignee();\n            int sub = entry.getKey().lastIndexOf(\"_\");\n            String nodeId = entry.getKey().substring(0, sub);\n            nodeId = nodeId.substring(nodeId.lastIndexOf(\"_\") + 1, nodeId.length());\n            String nodeName = entry.getKey().substring(entry.getKey().lastIndexOf(\"_\") + 1, entry.getKey().length());\n            //更新进list\n            assignee.setAssigneeType(3);\n            assignee.setRoleId(entry.getValue()[0]);\n            assignee.setSid(nodeId);\n            assignee.setActivtiName(nodeName);\n            //先清除\n            actAssigneeService.deleteByNodeId(nodeId);\n            assigneeList.add(assignee);\n        }\n        //后添加 在map循环里添加 多角色会导致添加了的再次被删除 so 要拿出来\n        for (ActAssignee actAssignee : assigneeList) {\n            actAssigneeService.insertSelective(actAssignee);\n        }\n        j.setMsg(\"更新成功\");\n        return j;\n    }\n\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/activiti/entity/ActAssignee.java",
    "content": "package com.open.capacity.activiti.entity;\n\nimport java.io.Serializable;\n\n/**\n * @Author: [gitgeek]\n * @Date: [2018-05-14 19:17]\n * @Description: [ 任务节点和代理人、候选人、候选组的绑定实体 ]\n * @Version: [1.0.0]\n * @Copy: [com.zzg]\n */\npublic class ActAssignee implements Serializable {\n\n    private static final long serialVersionUID = 1L;\n    private String id;\n    private String sid;\n    private String assignee;\n    private String roleId;\n    private Integer assigneeType;\n    private String activtiName;\n\n    public ActAssignee() {\n    }\n\n    public ActAssignee(String sid) {\n        this.sid = sid;\n    }\n\n    public String getId() {\n        return id;\n    }\n\n    public void setId(String id) {\n        this.id = id == null ? null : id.trim();\n    }\n\n    public String getSid() {\n        return sid;\n    }\n\n    public void setSid(String sid) {\n        this.sid = sid == null ? null : sid.trim();\n    }\n\n    public String getAssignee() {\n        return assignee;\n    }\n\n    public void setAssignee(String assignee) {\n        this.assignee = assignee == null ? null : assignee.trim();\n    }\n\n    public String getRoleId() {\n        return roleId;\n    }\n\n    public void setRoleId(String roleId) {\n        this.roleId = roleId == null ? null : roleId.trim();\n    }\n\n    public Integer getAssigneeType() {\n        return assigneeType;\n    }\n\n    public void setAssigneeType(Integer assigneeType) {\n        this.assigneeType = assigneeType;\n    }\n\n    public String getActivtiName() {\n        return activtiName;\n    }\n\n    public void setActivtiName(String activtiName) {\n        this.activtiName = activtiName == null ? null : activtiName.trim();\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/activiti/entity/ActDeployment.java",
    "content": "package com.open.capacity.activiti.entity;\n\n\nimport lombok.Getter;\nimport lombok.Setter;\nimport org.activiti.engine.repository.Deployment;\n\nimport java.io.Serializable;\nimport java.util.Date;\n\n/**\n * @Author: [gitgeek]\n * @Date: [2018-05-14 19:18]\n * @Description: [ 流程部署表 ]\n * @Version: [1.0.0]\n * @Copy: [com.zzg]\n */\n@Getter\n@Setter\npublic class ActDeployment implements Serializable {\n    private String id;\n    private String name;\n    private Date deploymentTime;\n    private String category;\n    private String tenantId;\n\n    public ActDeployment() {\n    }\n\n    public ActDeployment(Deployment deployment) {\n        this.id = deployment.getId();\n        this.name = deployment.getName();\n        this.deploymentTime = deployment.getDeploymentTime();\n        this.category = deployment.getCategory();\n        this.tenantId = deployment.getTenantId();\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/activiti/entity/ActModel.java",
    "content": "package com.open.capacity.activiti.entity;\n\n\nimport lombok.Getter;\nimport lombok.Setter;\nimport org.activiti.engine.repository.Model;\n\nimport java.util.Date;\n\n/**\n * @Author: [gitgeek]\n * @Date: [2018-05-14 19:19]\n * @Description: [ 模型列表 ]\n * @Version: [1.0.0]\n * @Copy: [com.zzg]\n */\n@Getter\n@Setter\npublic class ActModel {\n\n    private String id;\n    private String name;\n    private String key;\n    private String category;\n    private Date createTime;\n    private Date lastUpdateTime;\n    private Integer version;\n    private String metaInfo;\n    private String deploymentId;\n    private String tenantId;\n    private boolean hasEditorSource;\n\n\n    public ActModel() {\n    }\n\n    public ActModel(Model model) {\n        this.id = model.getId();\n        this.name = model.getName();\n        this.key = model.getKey();\n        this.category = model.getCategory();\n        this.createTime = model.getCreateTime();\n        this.lastUpdateTime = model.getLastUpdateTime();\n        this.version = model.getVersion();\n        this.metaInfo = model.getMetaInfo();\n        this.deploymentId = model.getDeploymentId();\n        this.tenantId = model.getTenantId();\n        this.hasEditorSource = model.hasEditorSource();\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/activiti/entity/LeaveOpinion.java",
    "content": "package com.open.capacity.activiti.entity;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport java.io.Serializable;\nimport java.util.Date;\n\n/**\n * @Author: [gitgeek]\n * @Date: [2018-05-14 19:22]\n * @Description: [ 请假流程 审批信息 ]\n * @Version: [1.0.0]\n * @Copy: [com.zzg]\n */\n@Getter\n@Setter\npublic class LeaveOpinion implements Serializable {\n\n    //审批人id\n    private String opId;\n    //审批人姓名\n    private String opName;\n    //审批意见\n    private String opinion;\n    //审批时间\n    private Date createTime;\n    //是否通过\n    private boolean flag;\n    //流程id\n    private String taskId;\n\n}"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/activiti/entity/ProcessDefinition.java",
    "content": "package com.open.capacity.activiti.entity;\n\nimport lombok.Getter;\nimport lombok.Setter;\nimport lombok.ToString;\n\n/**\n * @Author: [gitgeek]\n * @Date: [2018-05-14 19:23]\n * @Description: [ 流程定义实体 ]\n * @Version: [1.0.0]\n * @Copy: [com.zzg]\n */\n@Getter\n@Setter\n@ToString\npublic class ProcessDefinition {\n    private String id;\n    private String category;\n    private String name;\n    private String key;\n    private String description;\n    private int version;\n    private String resourceName;\n    private String deploymentId;\n    private String diagramResourceName;\n    private boolean hasStartFormKey;\n    private boolean hasGraphicalNotation;\n    private boolean isSuspended;\n    private String tenantId;\n\n    public ProcessDefinition() {\n    }\n\n    public ProcessDefinition(org.activiti.engine.repository.ProcessDefinition p) {\n        this.id = p.getId();\n        this.category = p.getCategory();\n        this.name = p.getName();\n        this.key = p.getKey();\n        this.description = p.getDescription();\n        this.version = p.getVersion();\n        this.resourceName = p.getResourceName();\n        this.deploymentId = p.getDeploymentId();\n        this.diagramResourceName = p.getDiagramResourceName();\n        this.hasStartFormKey = p.hasStartFormKey();\n        this.hasGraphicalNotation = p.hasGraphicalNotation();\n        this.isSuspended = p.isSuspended();\n        this.tenantId = p.getTenantId();\n\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/activiti/entity/Task.java",
    "content": "package com.open.capacity.activiti.entity;\n\nimport lombok.Getter;\nimport lombok.Setter;\nimport lombok.ToString;\n\nimport java.util.Date;\n\n/**\n * @Author: [gitgeek]\n * @Date: [2018-05-14 19:23]\n * @Description: [ ]\n * @Version: [1.0.0]\n * @Copy: [com.zzg]\n */\n\n@Getter\n@Setter\n@ToString\npublic class Task {\n    private String id;\n    private String name;\n    private Date createTime;\n    private String assignee;\n    private String processInstanceId;//流程实例id\n    private String processDefinitionId;//流程定义id\n    private String description;\n    private String category;\n\n    private String userName;\n    private String reason;\n\n    public Task() {\n    }\n\n    public Task(org.activiti.engine.task.Task t) {\n        this.id = t.getId();\n        this.name = t.getName();\n        this.createTime = t.getCreateTime();\n        this.assignee = t.getAssignee();\n        this.processInstanceId = t.getProcessInstanceId();\n        this.processDefinitionId = t.getProcessDefinitionId();\n        this.description = t.getDescription();\n        this.category = t.getCategory();\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/activiti/entity/UserLeave.java",
    "content": "package com.open.capacity.activiti.entity;\n\nimport java.util.ArrayList;\nimport java.util.Date;\nimport java.util.List;\n\n/**\n * @Author: [gitgeek]\n * @Date: [2018-05-14 19:24]\n * @Description: [ ]\n * @Version: [1.0.0]\n * @Copy: [com.zzg]\n */\npublic class UserLeave {\n    private static final long serialVersionUID = 1L;\n    private String id;\n    private String userId;\n    private String userName;\n    private Date beginTime;\n    private Date endTime;\n    private String reason;\n    private Integer days;\n    private String processInstanceId;\n    private String status;\n    private Date createDate;\n    private String createBy;\n    private Date updateDate;\n    private String updateBy;\n    //***实时节点信息\n    private String taskName;\n    //请假单审核信息\n    private List<LeaveOpinion> opinionList = new ArrayList<>();\n\n    public String getTaskName() {\n        return taskName;\n    }\n\n    public void setTaskName(String taskName) {\n        this.taskName = taskName;\n    }\n\n    public void leaveOpAdd(LeaveOpinion leaveOpinion) {\n        this.opinionList.add(leaveOpinion);\n    }\n\n    public void leaveOpAddAll(List<LeaveOpinion> leaveOpinionList) {\n        this.opinionList.addAll(leaveOpinionList);\n    }\n\n    public List<LeaveOpinion> getOpinionList() {\n        return opinionList;\n    }\n\n    public void setOpinionList(List<LeaveOpinion> opinionList) {\n        this.opinionList = opinionList;\n    }\n\n    public String getId() {\n        return id;\n    }\n\n    public void setId(String id) {\n        this.id = id == null ? null : id.trim();\n    }\n\n    public String getUserId() {\n        return userId;\n    }\n\n    public void setUserId(String userId) {\n        this.userId = userId == null ? null : userId.trim();\n    }\n\n    public String getUserName() {\n        return userName;\n    }\n\n    public void setUserName(String userName) {\n        this.userName = userName == null ? null : userName.trim();\n    }\n\n    public Date getBeginTime() {\n        return beginTime;\n    }\n\n    public void setBeginTime(Date beginTime) {\n        this.beginTime = beginTime;\n    }\n\n    public Date getEndTime() {\n        return endTime;\n    }\n\n    public void setEndTime(Date endTime) {\n        this.endTime = endTime;\n    }\n\n    public String getReason() {\n        return reason;\n    }\n\n    public void setReason(String reason) {\n        this.reason = reason == null ? null : reason.trim();\n    }\n\n    public Integer getDays() {\n        return days;\n    }\n\n    public void setDays(Integer days) {\n        this.days = days;\n    }\n\n    public String getProcessInstanceId() {\n        return processInstanceId;\n    }\n\n    public void setProcessInstanceId(String processInstanceId) {\n        this.processInstanceId = processInstanceId == null ? null : processInstanceId.trim();\n    }\n\n    public String getStatus() {\n        return status;\n    }\n\n    public void setStatus(String status) {\n        this.status = status == null ? null : status.trim();\n    }\n\n    public Date getCreateDate() {\n        return createDate;\n    }\n\n    public void setCreateDate(Date createDate) {\n        this.createDate = createDate;\n    }\n\n    public String getCreateBy() {\n        return createBy;\n    }\n\n    public void setCreateBy(String createBy) {\n        this.createBy = createBy == null ? null : createBy.trim();\n    }\n\n    public Date getUpdateDate() {\n        return updateDate;\n    }\n\n    public void setUpdateDate(Date updateDate) {\n        this.updateDate = updateDate;\n    }\n\n    public String getUpdateBy() {\n        return updateBy;\n    }\n\n    public void setUpdateBy(String updateBy) {\n        this.updateBy = updateBy == null ? null : updateBy.trim();\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/activiti/mapper/ActAssigneeMapper.java",
    "content": "package com.open.capacity.activiti.mapper;\n\nimport com.open.capacity.activiti.entity.ActAssignee;\nimport org.apache.ibatis.annotations.Mapper;\n\nimport java.util.List;\n\n/**\n * @Author: [gitgeek]\n * @Date: [2018-05-14 19:53]\n * @Description: [ ]\n * @Version: [1.0.0]\n * @Copy: [com.zzg]\n */\n@Mapper\npublic interface ActAssigneeMapper {\n\n    int deleteByPrimaryKey(String id);\n\n    int insert(ActAssignee record);\n\n    int insertSelective(ActAssignee record);\n\n    ActAssignee selectByPrimaryKey(String id);\n\n    int updateByPrimaryKeySelective(ActAssignee record);\n\n    int updateByPrimaryKey(ActAssignee record);\n\n    int deleteByNodeId(String nodeId);\n\n    List<ActAssignee> selectListByPage(ActAssignee record);\n\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/activiti/mapper/ActAssigneeMapper.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.open.capacity.activiti.mapper.ActAssigneeMapper\">\n\n    <resultMap id=\"BaseResultMap\" type=\"com.open.capacity.activiti.entity.ActAssignee\">\n        <id column=\"id\" jdbcType=\"VARCHAR\" property=\"id\"/>\n        <result column=\"sid\" jdbcType=\"VARCHAR\" property=\"sid\"/>\n        <result column=\"assignee\" jdbcType=\"VARCHAR\" property=\"assignee\"/>\n        <result column=\"role_id\" jdbcType=\"VARCHAR\" property=\"roleId\"/>\n        <result column=\"assignee_type\" jdbcType=\"INTEGER\" property=\"assigneeType\"/>\n        <result column=\"activti_name\" jdbcType=\"VARCHAR\" property=\"activtiName\"/>\n    </resultMap>\n\n    <sql id=\"Base_Column_List\">\n    id, sid, assignee, role_id, assignee_type, activti_name\n  </sql>\n\n    <select id=\"selectByPrimaryKey\" parameterType=\"java.lang.String\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from act_assignee\n        where id = #{id,jdbcType=VARCHAR}\n    </select>\n\n    <delete id=\"deleteByPrimaryKey\" parameterType=\"java.lang.String\">\n    delete from act_assignee\n    where id = #{id,jdbcType=VARCHAR}\n  </delete>\n\n    <delete id=\"deleteByNodeId\" parameterType=\"java.lang.String\">\n    delete from act_assignee\n    where sid = #{sid,jdbcType=VARCHAR}\n  </delete>\n\n    <insert id=\"insert\" parameterType=\"com.open.capacity.activiti.entity.ActAssignee\">\n        <selectKey resultType=\"String\" keyProperty=\"id\" order=\"BEFORE\">\n            select replace(uuid(),\"-\",\"\") from dual\n        </selectKey>\n        insert into act_assignee (id, sid, assignee,\n        role_id, assignee_type, activti_name\n        )\n        values (#{id,jdbcType=VARCHAR}, #{sid,jdbcType=VARCHAR}, #{assignee,jdbcType=VARCHAR},\n        #{roleId,jdbcType=VARCHAR}, #{assigneeType,jdbcType=INTEGER}, #{activtiName,jdbcType=VARCHAR}\n        )\n    </insert>\n\n    <insert id=\"insertSelective\" parameterType=\"com.open.capacity.activiti.entity.ActAssignee\">\n        <selectKey resultType=\"String\" keyProperty=\"id\" order=\"BEFORE\">\n            select replace(uuid(),\"-\",\"\") from dual\n        </selectKey>\n        insert into act_assignee\n        <trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">\n            <if test=\"id != null\">\n                id,\n            </if>\n            <if test=\"sid != null\">\n                sid,\n            </if>\n            <if test=\"assignee != null\">\n                assignee,\n            </if>\n            <if test=\"roleId != null\">\n                role_id,\n            </if>\n            <if test=\"assigneeType != null\">\n                assignee_type,\n            </if>\n            <if test=\"activtiName != null\">\n                activti_name,\n            </if>\n        </trim>\n        <trim prefix=\"values (\" suffix=\")\" suffixOverrides=\",\">\n            <if test=\"id != null\">\n                #{id,jdbcType=VARCHAR},\n            </if>\n            <if test=\"sid != null\">\n                #{sid,jdbcType=VARCHAR},\n            </if>\n            <if test=\"assignee != null\">\n                #{assignee,jdbcType=VARCHAR},\n            </if>\n            <if test=\"roleId != null\">\n                #{roleId,jdbcType=VARCHAR},\n            </if>\n            <if test=\"assigneeType != null\">\n                #{assigneeType,jdbcType=INTEGER},\n            </if>\n            <if test=\"activtiName != null\">\n                #{activtiName,jdbcType=VARCHAR},\n            </if>\n        </trim>\n    </insert>\n\n\n    <update id=\"updateByPrimaryKeySelective\" parameterType=\"com.open.capacity.activiti.entity.ActAssignee\">\n        update act_assignee\n        <set>\n            <if test=\"sid != null\">\n                sid = #{sid,jdbcType=VARCHAR},\n            </if>\n            <if test=\"assignee != null\">\n                assignee = #{assignee,jdbcType=VARCHAR},\n            </if>\n            <if test=\"roleId != null\">\n                role_id = #{roleId,jdbcType=VARCHAR},\n            </if>\n            <if test=\"assigneeType != null\">\n                assignee_type = #{assigneeType,jdbcType=INTEGER},\n            </if>\n            <if test=\"activtiName != null\">\n                activti_name = #{activtiName,jdbcType=VARCHAR},\n            </if>\n        </set>\n        where id = #{id,jdbcType=VARCHAR}\n    </update>\n\n\n    <update id=\"updateByPrimaryKey\" parameterType=\"com.open.capacity.activiti.entity.ActAssignee\">\n    update act_assignee\n    set sid = #{sid,jdbcType=VARCHAR},\n      assignee = #{assignee,jdbcType=VARCHAR},\n      role_id = #{roleId,jdbcType=VARCHAR},\n      assignee_type = #{assigneeType,jdbcType=INTEGER},\n      activti_name = #{activtiName,jdbcType=VARCHAR}\n    where id = #{id,jdbcType=VARCHAR}\n  </update>\n\n\n    <select id=\"selectListByPage\" parameterType=\"com.open.capacity.activiti.entity.ActAssignee\"\n            resultMap=\"BaseResultMap\">\n        SELECT\n        <include refid=\"Base_Column_List\"/>\n        from act_assignee\n        <where>\n            <if test=\"sid!=null and sid!=''\">and sid = #{sid}</if>\n            <if test=\"roleId!=null and roleId!=''\">and role_id = #{roleId}</if>\n        </where>\n    </select>\n\n\n</mapper>"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/activiti/mapper/UserLeaveMapper.java",
    "content": "package com.open.capacity.activiti.mapper;\n\nimport com.open.capacity.activiti.entity.UserLeave;\nimport org.apache.ibatis.annotations.Mapper;\n\nimport java.util.List;\n\n/**\n * @Author: [gitgeek]\n * @Date: [2018-05-14 20:05]\n * @Description: [ ]\n * @Version: [1.0.0]\n * @Copy: [com.zzg]\n */\n@Mapper\npublic interface UserLeaveMapper {\n\n    int deleteByPrimaryKey(String id);\n\n    int insert(UserLeave record);\n\n    int insertSelective(UserLeave record);\n\n    UserLeave selectByPrimaryKey(String id);\n\n    int updateByPrimaryKeySelective(UserLeave record);\n\n    int updateByPrimaryKey(UserLeave record);\n\n    List<UserLeave> selectListByPage(UserLeave userLeave);\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/activiti/mapper/UserLeaveMapper.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.open.capacity.activiti.mapper.UserLeaveMapper\">\n    <resultMap id=\"BaseResultMap\" type=\"com.open.capacity.activiti.entity.UserLeave\">\n        <id column=\"id\" jdbcType=\"VARCHAR\" property=\"id\"/>\n        <result column=\"user_id\" jdbcType=\"VARCHAR\" property=\"userId\"/>\n        <result column=\"user_name\" jdbcType=\"VARCHAR\" property=\"userName\"/>\n        <result column=\"begin_time\" jdbcType=\"TIMESTAMP\" property=\"beginTime\"/>\n        <result column=\"end_time\" jdbcType=\"TIMESTAMP\" property=\"endTime\"/>\n        <result column=\"reason\" jdbcType=\"VARCHAR\" property=\"reason\"/>\n        <result column=\"days\" jdbcType=\"INTEGER\" property=\"days\"/>\n        <result column=\"process_instance_Id\" jdbcType=\"VARCHAR\" property=\"processInstanceId\"/>\n        <result column=\"status\" jdbcType=\"VARCHAR\" property=\"status\"/>\n        <result column=\"create_date\" jdbcType=\"TIMESTAMP\" property=\"createDate\"/>\n        <result column=\"create_by\" jdbcType=\"VARCHAR\" property=\"createBy\"/>\n        <result column=\"update_date\" jdbcType=\"TIMESTAMP\" property=\"updateDate\"/>\n        <result column=\"update_by\" jdbcType=\"VARCHAR\" property=\"updateBy\"/>\n    </resultMap>\n    <sql id=\"Base_Column_List\">\n    id, user_id, user_name, begin_time, end_time, reason, days, process_instance_Id, \n    status, create_date, create_by, update_date, update_by\n  </sql>\n    <select id=\"selectByPrimaryKey\" parameterType=\"java.lang.String\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from user_leave\n        where id = #{id,jdbcType=VARCHAR}\n    </select>\n    <delete id=\"deleteByPrimaryKey\" parameterType=\"java.lang.String\">\n    delete from user_leave\n    where id = #{id,jdbcType=VARCHAR}\n  </delete>\n    <insert id=\"insert\" parameterType=\"com.open.capacity.activiti.entity.UserLeave\">\n        <selectKey resultType=\"String\" keyProperty=\"id\" order=\"BEFORE\">\n            select replace(uuid(),\"-\",\"\") from dual\n        </selectKey>\n        insert into user_leave (id, user_id, user_name,\n        begin_time, end_time, reason,\n        days, process_instance_Id, status,\n        create_date, create_by, update_date,\n        update_by)\n        values (#{id,jdbcType=VARCHAR}, #{userId,jdbcType=VARCHAR}, #{userName,jdbcType=VARCHAR},\n        #{beginTime,jdbcType=TIMESTAMP}, #{endTime,jdbcType=TIMESTAMP}, #{reason,jdbcType=VARCHAR},\n        #{days,jdbcType=INTEGER}, #{processInstanceId,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR},\n        #{createDate,jdbcType=TIMESTAMP}, #{createBy,jdbcType=VARCHAR}, #{updateDate,jdbcType=TIMESTAMP},\n        #{updateBy,jdbcType=VARCHAR})\n    </insert>\n    <insert id=\"insertSelective\" parameterType=\"com.open.capacity.activiti.entity.UserLeave\">\n        <selectKey resultType=\"String\" keyProperty=\"id\" order=\"BEFORE\">\n            select replace(uuid(),\"-\",\"\") from dual\n        </selectKey>\n        insert into user_leave\n        <trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">\n            <if test=\"id != null\">\n                id,\n            </if>\n            <if test=\"userId != null\">\n                user_id,\n            </if>\n            <if test=\"userName != null\">\n                user_name,\n            </if>\n            <if test=\"beginTime != null\">\n                begin_time,\n            </if>\n            <if test=\"endTime != null\">\n                end_time,\n            </if>\n            <if test=\"reason != null\">\n                reason,\n            </if>\n            <if test=\"days != null\">\n                days,\n            </if>\n            <if test=\"processInstanceId != null\">\n                process_instance_Id,\n            </if>\n            <if test=\"status != null\">\n                status,\n            </if>\n            <if test=\"createDate != null\">\n                create_date,\n            </if>\n            <if test=\"createBy != null\">\n                create_by,\n            </if>\n            <if test=\"updateDate != null\">\n                update_date,\n            </if>\n            <if test=\"updateBy != null\">\n                update_by,\n            </if>\n        </trim>\n        <trim prefix=\"values (\" suffix=\")\" suffixOverrides=\",\">\n            <if test=\"id != null\">\n                #{id,jdbcType=VARCHAR},\n            </if>\n            <if test=\"userId != null\">\n                #{userId,jdbcType=VARCHAR},\n            </if>\n            <if test=\"userName != null\">\n                #{userName,jdbcType=VARCHAR},\n            </if>\n            <if test=\"beginTime != null\">\n                #{beginTime,jdbcType=TIMESTAMP},\n            </if>\n            <if test=\"endTime != null\">\n                #{endTime,jdbcType=TIMESTAMP},\n            </if>\n            <if test=\"reason != null\">\n                #{reason,jdbcType=VARCHAR},\n            </if>\n            <if test=\"days != null\">\n                #{days,jdbcType=INTEGER},\n            </if>\n            <if test=\"processInstanceId != null\">\n                #{processInstanceId,jdbcType=VARCHAR},\n            </if>\n            <if test=\"status != null\">\n                #{status,jdbcType=VARCHAR},\n            </if>\n            <if test=\"createDate != null\">\n                #{createDate,jdbcType=TIMESTAMP},\n            </if>\n            <if test=\"createBy != null\">\n                #{createBy,jdbcType=VARCHAR},\n            </if>\n            <if test=\"updateDate != null\">\n                #{updateDate,jdbcType=TIMESTAMP},\n            </if>\n            <if test=\"updateBy != null\">\n                #{updateBy,jdbcType=VARCHAR},\n            </if>\n        </trim>\n    </insert>\n    <update id=\"updateByPrimaryKeySelective\" parameterType=\"com.open.capacity.activiti.entity.UserLeave\">\n        update user_leave\n        <set>\n            <if test=\"userId != null\">\n                user_id = #{userId,jdbcType=VARCHAR},\n            </if>\n            <if test=\"userName != null\">\n                user_name = #{userName,jdbcType=VARCHAR},\n            </if>\n            <if test=\"beginTime != null\">\n                begin_time = #{beginTime,jdbcType=TIMESTAMP},\n            </if>\n            <if test=\"endTime != null\">\n                end_time = #{endTime,jdbcType=TIMESTAMP},\n            </if>\n            <if test=\"reason != null\">\n                reason = #{reason,jdbcType=VARCHAR},\n            </if>\n            <if test=\"days != null\">\n                days = #{days,jdbcType=INTEGER},\n            </if>\n            <if test=\"processInstanceId != null\">\n                process_instance_Id = #{processInstanceId,jdbcType=VARCHAR},\n            </if>\n            <if test=\"status != null\">\n                status = #{status,jdbcType=VARCHAR},\n            </if>\n            <if test=\"createDate != null\">\n                create_date = #{createDate,jdbcType=TIMESTAMP},\n            </if>\n            <if test=\"createBy != null\">\n                create_by = #{createBy,jdbcType=VARCHAR},\n            </if>\n            <if test=\"updateDate != null\">\n                update_date = #{updateDate,jdbcType=TIMESTAMP},\n            </if>\n            <if test=\"updateBy != null\">\n                update_by = #{updateBy,jdbcType=VARCHAR},\n            </if>\n        </set>\n        where id = #{id,jdbcType=VARCHAR}\n    </update>\n    <update id=\"updateByPrimaryKey\" parameterType=\"com.open.capacity.activiti.entity.UserLeave\">\n    update user_leave\n    set user_id = #{userId,jdbcType=VARCHAR},\n      user_name = #{userName,jdbcType=VARCHAR},\n      begin_time = #{beginTime,jdbcType=TIMESTAMP},\n      end_time = #{endTime,jdbcType=TIMESTAMP},\n      reason = #{reason,jdbcType=VARCHAR},\n      days = #{days,jdbcType=INTEGER},\n      process_instance_Id = #{processInstanceId,jdbcType=VARCHAR},\n      status = #{status,jdbcType=VARCHAR},\n      create_date = #{createDate,jdbcType=TIMESTAMP},\n      create_by = #{createBy,jdbcType=VARCHAR},\n      update_date = #{updateDate,jdbcType=TIMESTAMP},\n      update_by = #{updateBy,jdbcType=VARCHAR}\n    where id = #{id,jdbcType=VARCHAR}\n  </update>\n    <select id=\"selectListByPage\" parameterType=\"com.open.capacity.activiti.entity.UserLeave\" resultMap=\"BaseResultMap\">\n        SELECT\n        <include refid=\"Base_Column_List\"/>\n        from user_leave\n        <where>\n            <if test=\"userId!=null and userId!=''\">and user_id=#{userId}</if>\n            <if test=\"beginTime!=null\">\n                <![CDATA[   and DATE_FORMAT(begin_time, '%Y-%m-%d')>=  DATE_FORMAT(#{beginTime}, '%Y-%m-%d')   ]]>\n            </if>\n            <if test=\"endTime!=null\">\n                <![CDATA[  and DATE_FORMAT(end_time, '%Y-%m-%d') <= DATE_FORMAT(#{endTime}, '%Y-%m-%d')    ]]>\n            </if>\n        </where>\n    </select>\n\n</mapper>"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/activiti/rest/editor/main/StencilsetRestResource.java",
    "content": "package com.open.capacity.activiti.rest.editor.main;\n\nimport org.activiti.engine.ActivitiException;\nimport org.apache.commons.io.IOUtils;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.ResponseBody;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.io.InputStream;\n\n/**\n * @author Tijs Rademakers\n */\n@RestController\n@RequestMapping(\"service\")\npublic class StencilsetRestResource {\n\n    @RequestMapping(value = \"/editor/stencilset\", method = RequestMethod.GET, produces = \"application/json;charset=utf-8\")\n    @ResponseBody\n    public String getStencilset() {\n        InputStream stencilsetStream = this.getClass().getClassLoader().getResourceAsStream(\"stencilset.json\");\n        try {\n            return IOUtils.toString(stencilsetStream, \"utf-8\");\n        } catch (Exception e) {\n            throw new ActivitiException(\"Error while loading stencil set\", e);\n        }\n    }\n}\n\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/activiti/rest/editor/model/ModelEditorJsonRestResource.java",
    "content": "package com.open.capacity.activiti.rest.editor.model;\n\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.fasterxml.jackson.databind.node.ObjectNode;\nimport lombok.extern.slf4j.Slf4j;\nimport org.activiti.editor.constants.ModelDataJsonConstants;\nimport org.activiti.engine.ActivitiException;\nimport org.activiti.engine.RepositoryService;\nimport org.activiti.engine.repository.Model;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * @author Tijs Rademakers\n */\n@RestController\n@RequestMapping(\"service\")\n@Slf4j\npublic class ModelEditorJsonRestResource implements ModelDataJsonConstants {\n\n    @Autowired\n    private RepositoryService repositoryService;\n\n    @Autowired\n    private ObjectMapper objectMapper;\n\n    @RequestMapping(value = \"/model/{modelId}/json\", method = RequestMethod.GET, produces = \"application/json\")\n    public ObjectNode getEditorJson(@PathVariable String modelId) {\n        ObjectNode modelNode = null;\n\n        Model model = repositoryService.getModel(modelId);\n\n        if (model != null) {\n            try {\n                if (StringUtils.isNotEmpty(model.getMetaInfo())) {\n                    modelNode = (ObjectNode) objectMapper.readTree(model.getMetaInfo());\n                } else {\n                    modelNode = objectMapper.createObjectNode();\n                    modelNode.put(MODEL_NAME, model.getName());\n                }\n                modelNode.put(MODEL_ID, model.getId());\n                ObjectNode editorJsonNode = (ObjectNode) objectMapper.readTree(\n                        new String(repositoryService.getModelEditorSource(model.getId()), \"utf-8\"));\n                modelNode.set(\"model\", editorJsonNode);\n\n            } catch (Exception e) {\n                log.error(\"Error creating model JSON\", e);\n                throw new ActivitiException(\"Error creating model JSON\", e);\n            }\n        }\n        return modelNode;\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/activiti/rest/editor/model/ModelSaveRestResource.java",
    "content": "package com.open.capacity.activiti.rest.editor.model;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport lombok.extern.slf4j.Slf4j;\nimport org.activiti.editor.constants.ModelDataJsonConstants;\nimport org.activiti.engine.ActivitiException;\nimport org.activiti.engine.RepositoryService;\nimport org.activiti.engine.repository.Model;\nimport org.apache.batik.transcoder.TranscoderInput;\nimport org.apache.batik.transcoder.TranscoderOutput;\nimport org.apache.batik.transcoder.image.PNGTranscoder;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.web.bind.annotation.*;\n\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport java.io.ByteArrayInputStream;\nimport java.io.ByteArrayOutputStream;\nimport java.io.InputStream;\nimport java.util.Map;\n\n/**\n * @author Tijs Rademakers\n */\n@RestController\n@RequestMapping(\"service\")\n@Slf4j\npublic class ModelSaveRestResource implements ModelDataJsonConstants {\n\n    @Autowired\n    private RepositoryService repositoryService;\n\n\n    @PostMapping(value = \"/model/{modelId}/save\")\n    @ResponseStatus(value = HttpStatus.OK)\n    public void saveModel(@PathVariable String modelId\n            , String name, String description\n            , String json_xml, String svg_xml, HttpServletRequest request, HttpServletResponse response) {\n        try {\n            Map<String, String[]> map = request.getParameterMap();\n            JSONObject jsonObject = new JSONObject();\n            //全跑到key了，可取方案\n            for (Map.Entry<String, String[]> entry : map.entrySet()) {\n                if (entry.getKey().equals(\"token\")) {\n                    continue;\n                }\n                String data = entry.getKey() + \"=\" + (entry.getValue()[0]);\n                jsonObject = JSON.parseObject(data);\n            }\n            name = (String) jsonObject.get(\"name\");\n            description = (String) jsonObject.get(\"description\");\n            json_xml = (String) jsonObject.get(\"json_xml\");\n            svg_xml = (String) jsonObject.get(\"svg_xml\");\n\n            Model model = repositoryService.getModel(modelId);\n            JSONObject object = new JSONObject();\n            object.put(MODEL_NAME, name);\n            object.put(MODEL_DESCRIPTION, description);\n            model.setMetaInfo(object.toString());\n            model.setName(name);\n            repositoryService.saveModel(model);\n\n            repositoryService.addModelEditorSource(model.getId(), json_xml.getBytes(\"utf-8\"));\n\n            InputStream svgStream = new ByteArrayInputStream(svg_xml.getBytes(\"utf-8\"));\n            TranscoderInput input = new TranscoderInput(svgStream);\n\n            PNGTranscoder transcoder = new PNGTranscoder();\n            // Setup output\n            ByteArrayOutputStream outStream = new ByteArrayOutputStream();\n            TranscoderOutput output = new TranscoderOutput(outStream);\n\n            // Do the transformation\n            transcoder.transcode(input, output);\n            final byte[] result = outStream.toByteArray();\n            repositoryService.addModelEditorSourceExtra(model.getId(), result);\n            outStream.close();\n\n        } catch (Exception e) {\n            log.error(\"Error saving model\", e);\n            throw new ActivitiException(\"Error saving model\", e);\n        }\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/activiti/service/ActAssigneeService.java",
    "content": "package com.open.capacity.activiti.service;\n\nimport com.open.capacity.activiti.entity.ActAssignee;\n\nimport java.util.List;\n\n/**\n * @Author: [gitgeek]\n * @Date: [2018-05-14 20:14]\n * @Description: [ ]\n * @Version: [1.0.0]\n * @Copy: [com.zzg]\n */\npublic interface ActAssigneeService {\n    int deleteByNodeId(String nodeId);\n\n    List<ActAssignee> selectListByPage(ActAssignee record);\n\n\n    int insertSelective(ActAssignee record);\n\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/activiti/service/UserLeaveService.java",
    "content": "package com.open.capacity.activiti.service;\n\n/**\n * @Author: [gitgeek]\n * @Date: [2018-05-14 20:14]\n * @Description: [ ]\n * @Version: [1.0.0]\n * @Copy: [com.zzg]\n */\npublic interface UserLeaveService {\n\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/activiti/service/impl/ActAssigneeServiceImpl.java",
    "content": "package com.open.capacity.activiti.service.impl;\n\nimport com.open.capacity.activiti.entity.ActAssignee;\nimport com.open.capacity.activiti.mapper.ActAssigneeMapper;\nimport com.open.capacity.activiti.service.ActAssigneeService;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\n\n/**\n * @Author: [gitgeek]\n * @Date: [2018-05-14 20:15]\n * @Description: [ ]\n * @Version: [1.0.0]\n * @Copy: [com.zzg]\n */\n@Service\npublic class ActAssigneeServiceImpl implements ActAssigneeService {\n    @Autowired\n    ActAssigneeMapper actAssigneeMapper;\n\n    @Override\n    public int deleteByNodeId(String nodeId) {\n        return actAssigneeMapper.deleteByNodeId(nodeId);\n    }\n\n    @Override\n    public List<ActAssignee> selectListByPage(ActAssignee record) {\n        return actAssigneeMapper.selectListByPage(record);\n    }\n\n    @Override\n    public int insertSelective(ActAssignee record) {\n        return actAssigneeMapper.insertSelective(record);\n    }\n\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/activiti/service/impl/UserLeaveServiceImpl.java",
    "content": "package com.open.capacity.activiti.service.impl;\n\nimport com.open.capacity.activiti.service.UserLeaveService;\nimport org.springframework.stereotype.Service;\n\n/**\n * @Author: [gitgeek]\n * @Date: [2018-05-14 20:16]\n * @Description: [ ]\n * @Version: [1.0.0]\n * @Copy: [com.zzg]\n */\n@Service\npublic class UserLeaveServiceImpl implements UserLeaveService {\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/activiti/util/AssigneeType.java",
    "content": "package com.open.capacity.activiti.util;\n\n/**\n * @Author: [gitgeek]\n * @Date: [2018-05-14 20:16]\n * @Description: [ 工作流节点绑定类型 ]\n * @Version: [1.0.0]\n * @Copy: [com.zzg]\n */\npublic class AssigneeType {\n    public static final int USER_TYPE = 1;\n    public static final int USER_S_TYPE = 2;\n    public static final int GROUP_TYPE = 3;\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/activiti/util/Checkbox.java",
    "content": "package com.open.capacity.activiti.util;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\n/**\n * @Author: [gitgeek]\n * @Date: [2018-05-17 21:18]\n * @Description: [ 复选框类 ]\n * @Version: [1.0.0]\n * @Copy: [com.zzg]\n */\n@Getter\n@Setter\npublic class Checkbox {\n    private String id;\n    private String name;\n    /**\n     * 默认未选择\n     */\n    private boolean check = false;\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/activiti/util/JsonUtil.java",
    "content": "package com.open.capacity.activiti.util;\n\nimport com.alibaba.fastjson.JSONObject;\n\n/**\n * @Author: [gitgeek]\n * @Date: [2018-05-15 20:12]\n * @Description: [ ]\n * @Version: [1.0.0]\n * @Copy: [com.zzg]\n */\npublic class JsonUtil {\n\n    //默认成功\n    private boolean flag = true;\n    private String msg;\n    private JSONObject josnObj;\n\n    public JsonUtil() {\n    }\n\n    public JsonUtil(boolean flag, String msg) {\n        this.flag = flag;\n        this.msg = msg;\n    }\n\n    /**\n     * restful 返回\n     */\n    public static JsonUtil error(String msg) {\n        return new JsonUtil(false, msg);\n    }\n\n    public static JsonUtil sucess(String msg) {\n        return new JsonUtil(true, msg);\n    }\n\n    public boolean isFlag() {\n        return flag;\n    }\n\n    public void setFlag(boolean flag) {\n        this.flag = flag;\n    }\n\n    public String getMsg() {\n        return msg;\n    }\n\n    public void setMsg(String msg) {\n        this.msg = msg;\n    }\n\n    public JSONObject getJosnObj() {\n        return josnObj;\n    }\n\n    public void setJosnObj(JSONObject josnObj) {\n        this.josnObj = josnObj;\n    }\n}"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/activiti/util/ResultType.java",
    "content": "package com.open.capacity.activiti.util;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\n\nimport java.io.Serializable;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * @Author: [gitgeek]\n * @Date: [2018-05-15 19:23]\n * @Description: [ ]\n * @Version: [1.0.0]\n * @Copy: [com.zzg]\n */\npublic class ResultType implements Serializable {\n    /**\n     * 状态\n     */\n    public int code = 0;\n    /**\n     * 状态信息\n     */\n    public String msg = \"\";\n    /**\n     * 数据总数\n     */\n    public long count;\n\n    public List<?> data;\n\n    public ResultType() {\n    }\n\n    public ResultType(long count, List<?> data) {\n        this.count = count;\n        this.data = data;\n    }\n\n    /**\n     * 动态添加属性 map 用法可以参考 activiti 模块中 com.len.JsonTest 测试类中用法\n     *\n     * @param count\n     * @param data\n     * @param map\n     * @param node  绑定节点字符串 这样可以更加灵活\n     * @return\n     */\n    public static String jsonStrng(long count, List<?> data, Map<String, Map<String, Object>> map, String node) {\n        JSONArray jsonArray = JSONArray.parseArray(JSON.toJSONString(data));\n        JSONObject object = new JSONObject();\n        for (int i = 0; i < jsonArray.size(); i++) {\n            JSONObject jsonData = (JSONObject) jsonArray.get(i);\n            jsonData.putAll(map.get(jsonData.get(node)));\n        }\n        object.put(\"count\", count);\n        object.put(\"data\", jsonArray);\n        object.put(\"code\", 0);\n        object.put(\"msg\", \"\");\n        return object.toJSONString();\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/advice/ExceptionHandlerAdvice.java",
    "content": "package com.open.capacity.security.advice;\n\nimport com.open.capacity.security.dto.ResponseInfo;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.converter.HttpMessageNotReadableException;\nimport org.springframework.security.access.AccessDeniedException;\nimport org.springframework.web.bind.MissingServletRequestParameterException;\nimport org.springframework.web.bind.UnsatisfiedServletRequestParameterException;\nimport org.springframework.web.bind.annotation.ExceptionHandler;\nimport org.springframework.web.bind.annotation.ResponseStatus;\nimport org.springframework.web.bind.annotation.RestControllerAdvice;\nimport org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;\n\n/**\n * springmvc异常处理\n * * @author 作者 owen E-mail: 624191343@qq.com\n *\n * @version 创建时间：2018年3月20日 下午10:13:18 类说明\n */\n@RestControllerAdvice\npublic class ExceptionHandlerAdvice {\n\n    private static final Logger log = LoggerFactory.getLogger(ExceptionHandlerAdvice.class);\n\n    @ExceptionHandler({IllegalArgumentException.class})\n    @ResponseStatus(HttpStatus.BAD_REQUEST)\n    public ResponseInfo badRequestException(IllegalArgumentException exception) {\n        return new ResponseInfo(HttpStatus.BAD_REQUEST.value() + \"\", exception.getMessage());\n    }\n\n    @ExceptionHandler({AccessDeniedException.class})\n    @ResponseStatus(HttpStatus.FORBIDDEN)\n    public ResponseInfo badRequestException(AccessDeniedException exception) {\n        return new ResponseInfo(HttpStatus.FORBIDDEN.value() + \"\", exception.getMessage());\n    }\n\n    @ExceptionHandler({MissingServletRequestParameterException.class, HttpMessageNotReadableException.class,\n            UnsatisfiedServletRequestParameterException.class, MethodArgumentTypeMismatchException.class})\n    @ResponseStatus(HttpStatus.BAD_REQUEST)\n    public ResponseInfo badRequestException(Exception exception) {\n        return new ResponseInfo(HttpStatus.BAD_REQUEST.value() + \"\", exception.getMessage());\n    }\n\n    @ExceptionHandler(Throwable.class)\n    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)\n    public ResponseInfo exception(Throwable throwable) {\n        log.error(\"系统异常\", throwable);\n        return new ResponseInfo(HttpStatus.INTERNAL_SERVER_ERROR.value() + \"\", throwable.getMessage());\n\n    }\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/advice/LogAdvice.java",
    "content": "package com.open.capacity.security.advice;\n\nimport com.open.capacity.security.annotation.LogAnnotation;\nimport com.open.capacity.security.model.SysLogs;\nimport com.open.capacity.security.service.SysLogService;\nimport io.swagger.annotations.ApiOperation;\nimport org.aspectj.lang.ProceedingJoinPoint;\nimport org.aspectj.lang.annotation.Around;\nimport org.aspectj.lang.annotation.Aspect;\nimport org.aspectj.lang.reflect.MethodSignature;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\nimport org.springframework.util.StringUtils;\n\n/**\n * 统一日志处理\n *\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2018年3月20日 下午10:13:18 类说明\n */\n@Aspect\n@Component\npublic class LogAdvice {\n\n    @Autowired\n    private SysLogService logService;\n\n    @Around(value = \"@annotation(com.open.capacity.security.annotation.LogAnnotation)\")\n    public Object logSave(ProceedingJoinPoint joinPoint) throws Throwable {\n        SysLogs sysLogs = new SysLogs();\n        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();\n\n        String module = null;\n        LogAnnotation logAnnotation = methodSignature.getMethod().getDeclaredAnnotation(LogAnnotation.class);\n        module = logAnnotation.module();\n        if (StringUtils.isEmpty(module)) {\n            ApiOperation apiOperation = methodSignature.getMethod().getDeclaredAnnotation(ApiOperation.class);\n            if (apiOperation != null) {\n                module = apiOperation.value();\n            }\n        }\n\n        if (StringUtils.isEmpty(module)) {\n            throw new RuntimeException(\"没有指定日志module\");\n        }\n        sysLogs.setModule(module);\n\n        try {\n            Object object = joinPoint.proceed();\n\n            sysLogs.setFlag(true);\n            logService.save(sysLogs);\n\n            return object;\n        } catch (Exception e) {\n            sysLogs.setFlag(false);\n            sysLogs.setRemark(e.getMessage());\n            logService.save(sysLogs);\n            throw e;\n        }\n\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/annotation/LogAnnotation.java",
    "content": "package com.open.capacity.security.annotation;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * 日志注解\n * * @author 作者 owen E-mail: 624191343@qq.com\n *\n * @version 创建时间：2018年3月20日 下午10:13:18 类说明\n */\n@Target({ElementType.METHOD})\n@Retention(RetentionPolicy.RUNTIME)\npublic @interface LogAnnotation {\n    String module() default \"\";\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/config/AsycTaskExecutorConfig.java",
    "content": "package com.open.capacity.security.config;\n\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.core.task.TaskExecutor;\nimport org.springframework.scheduling.annotation.EnableAsync;\nimport org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;\n\n/**\n * 线程池配置、启用异步\n *\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2018年3月20日 下午10:13:18 类说明\n */\n@EnableAsync(proxyTargetClass = true)\n@Configuration\npublic class AsycTaskExecutorConfig {\n\n    @Bean\n    public TaskExecutor taskExecutor() {\n        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();\n        taskExecutor.setCorePoolSize(50);\n        taskExecutor.setMaxPoolSize(100);\n\n        return taskExecutor;\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/config/LoginPageConfig.java",
    "content": "package com.open.capacity.security.config;\n\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.servlet.view.RedirectView;\n\n@Controller\npublic class LoginPageConfig {\n\n    @RequestMapping(\"/\")\n    public RedirectView loginPage() {\n        return new RedirectView(\"/login.html\");\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/config/SecurityConfig.java",
    "content": "package com.open.capacity.security.config;\n\nimport com.open.capacity.security.filter.TokenFilter;\nimport com.open.capacity.security.service.TokenService;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.http.HttpMethod;\nimport org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;\nimport org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;\nimport org.springframework.security.config.annotation.web.builders.HttpSecurity;\nimport org.springframework.security.config.annotation.web.builders.WebSecurity;\nimport org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;\nimport org.springframework.security.config.http.SessionCreationPolicy;\nimport org.springframework.security.core.userdetails.UserDetailsService;\nimport org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;\nimport org.springframework.security.web.AuthenticationEntryPoint;\nimport org.springframework.security.web.authentication.AuthenticationFailureHandler;\nimport org.springframework.security.web.authentication.AuthenticationSuccessHandler;\nimport org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;\nimport org.springframework.security.web.authentication.logout.LogoutSuccessHandler;\n\n/**\n * spring security配置\n *\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2018年3月20日 下午10:13:18 类说明\n * 类说明\n */\n//开启spring security 注解\n@EnableGlobalMethodSecurity(prePostEnabled = true)\npublic class SecurityConfig extends WebSecurityConfigurerAdapter {\n\n    @Autowired\n    private AuthenticationSuccessHandler authenticationSuccessHandler;\n    @Autowired\n    private AuthenticationFailureHandler authenticationFailureHandler;\n    @Autowired\n    private LogoutSuccessHandler logoutSuccessHandler;\n    @Autowired\n    private AuthenticationEntryPoint authenticationEntryPoint;\n    @Autowired\n    private UserDetailsService userDetailsService;\n\n    @Autowired\n    private TokenService tokenService;\n\n    @Bean\n    public BCryptPasswordEncoder bCryptPasswordEncoder() {\n        return new BCryptPasswordEncoder();\n    }\n\n    @Override\n    public void configure(WebSecurity web) throws Exception {\n        web.ignoring().antMatchers(\"/js/**\");\n        web.ignoring().antMatchers(\"/css/**\");\n        web.ignoring().antMatchers(\"/layui/**\");\n        web.ignoring().antMatchers(\"/img/**\");\n        web.ignoring().antMatchers(\"/fonts/**\");\n        web.ignoring().antMatchers(\"/lib/**\");\n        web.ignoring().antMatchers(\"/pages/**\");\n        web.ignoring().antMatchers(\"/assets/**\");\n        web.ignoring().antMatchers(\"/base-component/**\");\n        // 忽略登录界面\n        web.ignoring().antMatchers(\"/login.html\");\n    }\n\n    @Override\n    protected void configure(HttpSecurity http) throws Exception {\n        http.csrf().disable();\n\n        // 基于token，所以不需要session\n        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);\n\n        //前后分离时需要带上\n        http.authorizeRequests().antMatchers(HttpMethod.OPTIONS).permitAll();\n        \n        http.authorizeRequests()\n                .antMatchers(\"/\", \"/*.html\", \"/favicon.ico\", \"/css/**\", \"/js/**\", \"/fonts/**\", \"/lib/**\", \"/img/**\",\n                        \"/v2/api-docs/**\", \"/swagger-resources/**\", \"/webjars/**\", \"/pages/**\", \"/druid/**\",\n                        \"/statics/**\")\n                .permitAll().anyRequest().authenticated();\n        http.formLogin().loginPage(\"/login.html\").loginProcessingUrl(\"/login\")\n                .successHandler(authenticationSuccessHandler).failureHandler(authenticationFailureHandler).and()\n                .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint);\n        http.logout().logoutUrl(\"/logout\").logoutSuccessHandler(logoutSuccessHandler);\n        // 解决不允许显示在iframe的问题\n        http.headers().frameOptions().disable();\n        http.headers().cacheControl();\n\n        //新增token过滤器\n        TokenFilter tokenFilter = new TokenFilter();\n        tokenFilter.setTokenService(tokenService);\n        tokenFilter.setUserDetailsService(userDetailsService);\n        tokenFilter.afterPropertiesSet();\n        http.addFilterBefore(tokenFilter, UsernamePasswordAuthenticationFilter.class);\n    }\n\n\n    @Override\n    protected void configure(AuthenticationManagerBuilder auth) throws Exception {\n        auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());\n    }\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/config/SecurityHandlerConfig.java",
    "content": "package com.open.capacity.security.config;\n\nimport com.open.capacity.security.dto.LoginUser;\nimport com.open.capacity.security.dto.ResponseInfo;\nimport com.open.capacity.security.dto.Token;\nimport com.open.capacity.security.filter.TokenFilter;\nimport com.open.capacity.security.service.TokenService;\nimport com.open.capacity.security.utils.ResponseUtil;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.security.authentication.BadCredentialsException;\nimport org.springframework.security.core.Authentication;\nimport org.springframework.security.core.AuthenticationException;\nimport org.springframework.security.web.AuthenticationEntryPoint;\nimport org.springframework.security.web.authentication.AuthenticationFailureHandler;\nimport org.springframework.security.web.authentication.AuthenticationSuccessHandler;\nimport org.springframework.security.web.authentication.logout.LogoutSuccessHandler;\n\nimport javax.servlet.ServletException;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport java.io.IOException;\n\n/**\n * spring security处理器\n *\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2018年3月20日 下午10:13:18 类说明\n */\n@Configuration\npublic class SecurityHandlerConfig {\n\n    @Autowired\n    private TokenService tokenService;\n\n    /**\n     * 登陆成功，返回Token\n     *\n     * @return\n     */\n    @Bean\n    public AuthenticationSuccessHandler loginSuccessHandler() {\n        return new AuthenticationSuccessHandler() {\n\n            @Override\n            public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,\n                                                Authentication authentication) throws IOException, ServletException {\n                LoginUser loginUser = (LoginUser) authentication.getPrincipal();\n\n                Token token = tokenService.saveToken(loginUser);\n                ResponseUtil.responseJson(response, HttpStatus.OK.value(), token);\n            }\n        };\n    }\n\n    /**\n     * 登陆失败\n     *\n     * @return\n     */\n    @Bean\n    public AuthenticationFailureHandler loginFailureHandler() {\n        return new AuthenticationFailureHandler() {\n\n            @Override\n            public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,\n                                                AuthenticationException exception) throws IOException, ServletException {\n                String msg = null;\n                if (exception instanceof BadCredentialsException) {\n                    msg = \"密码错误\";\n                } else {\n                    msg = exception.getMessage();\n                }\n                ResponseInfo info = new ResponseInfo(HttpStatus.UNAUTHORIZED.value() + \"\", msg);\n                ResponseUtil.responseJson(response, HttpStatus.UNAUTHORIZED.value(), info);\n            }\n        };\n\n    }\n\n    /**\n     * 未登录，返回401\n     *\n     * @return\n     */\n    @Bean\n    public AuthenticationEntryPoint authenticationEntryPoint() {\n        return new AuthenticationEntryPoint() {\n\n            @Override\n            public void commence(HttpServletRequest request, HttpServletResponse response,\n                                 AuthenticationException authException) throws IOException, ServletException {\n                ResponseInfo info = new ResponseInfo(HttpStatus.UNAUTHORIZED.value() + \"\", \"请先登录\");\n                ResponseUtil.responseJson(response, HttpStatus.UNAUTHORIZED.value(), info);\n            }\n        };\n    }\n\n    /**\n     * 退出处理\n     *\n     * @return\n     */\n    @Bean\n    public LogoutSuccessHandler logoutSussHandler() {\n        return new LogoutSuccessHandler() {\n\n            @Override\n            public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,\n                                        Authentication authentication) throws IOException, ServletException {\n                ResponseInfo info = new ResponseInfo(HttpStatus.OK.value() + \"\", \"退出成功\");\n\n                String token = TokenFilter.getToken(request);\n                tokenService.deleteToken(token);\n\n                ResponseUtil.responseJson(response, HttpStatus.OK.value(), info);\n            }\n        };\n\n    }\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/config/SwaggerConfig.java",
    "content": "package com.open.capacity.security.config;\n\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport springfox.documentation.builders.ApiInfoBuilder;\nimport springfox.documentation.builders.PathSelectors;\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 * swagger文档\n *\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2018年3月20日 下午10:13:18 类说明\n */\n@Configuration\n@EnableSwagger2\npublic class SwaggerConfig {\n\n    @Bean\n    public Docket docket() {\n        return new Docket(DocumentationType.SWAGGER_2).groupName(\"swagger接口文档\")\n                .apiInfo(new ApiInfoBuilder().title(\"swagger接口文档\")\n                        .contact(new Contact(\"owen\", \"\", \"624191343@qq.com\")).version(\"1.0\").build())\n                .select().paths(PathSelectors.any()).build();\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/config/WebMvcConfig.java",
    "content": "package com.open.capacity.security.config;\n\nimport com.open.capacity.security.page.table.PageTableArgumentResolver;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.stereotype.Component;\nimport org.springframework.util.ResourceUtils;\nimport org.springframework.web.context.request.RequestContextListener;\nimport org.springframework.web.cors.CorsConfiguration;\nimport org.springframework.web.cors.UrlBasedCorsConfigurationSource;\nimport org.springframework.web.filter.CorsFilter;\nimport org.springframework.web.method.support.HandlerMethodArgumentResolver;\nimport org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;\nimport org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;\n\nimport java.io.File;\nimport java.util.List;\n\n@Component\n@Configuration\npublic class WebMvcConfig extends WebMvcConfigurerAdapter {\n\n    /**\n     * 上传文件根路径\n     */\n    @Value(\"${files.path}\")\n    private String filesPath;\n\n    /**\n     * 跨域支持\n     *\n     * @return\n     */\n    @Bean\n    // 前后分离 ajax跨域调用处理\n    public CorsFilter corsFilter() {\n        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();\n        final CorsConfiguration config = new CorsConfiguration();\n        config.setAllowCredentials(true); // 允许cookies跨域\n        config.addAllowedOrigin(\"*\");// 允许向该服务器提交请求的URI，*表示全部允许。。这里尽量限制来源域，比如http://xxxx:8080\n        // ,以降低安全风险。。\n        config.addAllowedHeader(\"*\");// 允许访问的头信息,*表示全部\n        config.setMaxAge(18000L);// 预检请求的缓存时间（秒），即在这个时间段里，对于相同的跨域请求不会再预检了\n        config.addAllowedMethod(\"*\");// 允许提交请求的方法，*表示全部允许，也可以单独设置GET、PUT等\n        /*\n         * config.addAllowedMethod(\"HEAD\"); config.addAllowedMethod(\"GET\");//\n         * 允许Get的请求方法 config.addAllowedMethod(\"PUT\");\n         * config.addAllowedMethod(\"POST\"); config.addAllowedMethod(\"DELETE\");\n         * config.addAllowedMethod(\"PATCH\");\n         */\n        source.registerCorsConfiguration(\"/**\", config);\n        return new CorsFilter(source);\n    }\n\n    @Bean\n    public RequestContextListener requestContextListener() {\n        return new RequestContextListener();\n    }\n\n    /**\n     * datatable分页解析\n     *\n     * @return\n     */\n    @Bean\n    public PageTableArgumentResolver tableHandlerMethodArgumentResolver() {\n        return new PageTableArgumentResolver();\n    }\n\n    @Override\n    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {\n        argumentResolvers.add(tableHandlerMethodArgumentResolver());\n    }\n\n    /**\n     * 外部文件访问\n     */\n    @Override\n    public void addResourceHandlers(ResourceHandlerRegistry registry) {\n        registry.addResourceHandler(\"/statics/**\")\n                .addResourceLocations(ResourceUtils.FILE_URL_PREFIX + filesPath + File.separator);\n    }\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/controller/ClientController.java",
    "content": "package com.open.capacity.security.controller;\n\nimport com.google.common.collect.Maps;\nimport com.open.capacity.security.annotation.LogAnnotation;\nimport com.open.capacity.security.dao.ClientDao;\nimport com.open.capacity.security.dto.ClientDto;\nimport com.open.capacity.security.model.Client;\nimport com.open.capacity.security.page.table.PageTableHandler;\nimport com.open.capacity.security.page.table.PageTableHandler.CountHandler;\nimport com.open.capacity.security.page.table.PageTableHandler.ListHandler;\nimport com.open.capacity.security.page.table.PageTableRequest;\nimport com.open.capacity.security.page.table.PageTableResponse;\nimport com.open.capacity.security.service.ClientService;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.security.access.prepost.PreAuthorize;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.List;\n\n/**\n * 角色相关接口\n *\n * @author owen 624191343@qq.com\n */\n@Api(tags = \"应用\")\n@RestController\n@RequestMapping(\"/clients\")\npublic class ClientController {\n\n    @Autowired\n    private ClientService clientService;\n    @Autowired\n    private ClientDao clientDao;\n\n    @LogAnnotation\n    @PostMapping\n    @ApiOperation(value = \"保存应用\")\n    @PreAuthorize(\"hasAuthority('sys:role:add')\")\n    public void saveRole(@RequestBody ClientDto clientDto) {\n        clientService.saveClient(clientDto);\n    }\n\n    @GetMapping\n    @ApiOperation(value = \"应用列表\")\n    @PreAuthorize(\"hasAuthority('sys:role:query')\")\n    public PageTableResponse listRoles(PageTableRequest request) {\n        return new PageTableHandler(new CountHandler() {\n\n            @Override\n            public int count(PageTableRequest request) {\n                return clientDao.count(request.getParams());\n            }\n        }, new ListHandler() {\n\n            @Override\n            public List<Client> list(PageTableRequest request) {\n                List<Client> list = clientDao.list(request.getParams(), request.getOffset(), request.getLimit());\n                return list;\n            }\n        }).handle(request);\n    }\n\n    @GetMapping(\"/{id}\")\n    @ApiOperation(value = \"根据id获取应用\")\n    @PreAuthorize(\"hasAuthority('sys:role:query')\")\n    public Client get(@PathVariable Long id) {\n        return clientDao.getById(id);\n    }\n\n    @GetMapping(\"/all\")\n    @ApiOperation(value = \"所有应用\")\n    @PreAuthorize(\"hasAnyAuthority('sys:user:query','sys:role:query')\")\n    public List<Client> roles() {\n        return clientDao.list(Maps.newHashMap(), null, null);\n    }\n\n    @GetMapping(params = \"userId\")\n    @ApiOperation(value = \"根据用户id获取拥有的角色\")\n    @PreAuthorize(\"hasAnyAuthority('sys:user:query','sys:role:query')\")\n    public List<Client> roles(Long userId) {\n        return clientDao.listByUserId(userId);\n    }\n\n    @LogAnnotation\n    @DeleteMapping(\"/{id}\")\n    @ApiOperation(value = \"删除应用\")\n    @PreAuthorize(\"hasAuthority('sys:role:del')\")\n    public void delete(@PathVariable Long id) {\n        clientService.deleteClient(id);\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/controller/DictController.java",
    "content": "package com.open.capacity.security.controller;\n\nimport com.open.capacity.security.dao.DictDao;\nimport com.open.capacity.security.model.Dict;\nimport com.open.capacity.security.page.table.PageTableHandler;\nimport com.open.capacity.security.page.table.PageTableHandler.CountHandler;\nimport com.open.capacity.security.page.table.PageTableHandler.ListHandler;\nimport com.open.capacity.security.page.table.PageTableRequest;\nimport com.open.capacity.security.page.table.PageTableResponse;\nimport io.swagger.annotations.ApiOperation;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.security.access.prepost.PreAuthorize;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.List;\n\n@RestController\n@RequestMapping(\"/dicts\")\npublic class DictController {\n\n    @Autowired\n    private DictDao dictDao;\n\n    @PreAuthorize(\"hasAuthority('dict:add')\")\n    @PostMapping\n    @ApiOperation(value = \"保存\")\n    public Dict save(@RequestBody Dict dict) {\n        Dict d = dictDao.getByTypeAndK(dict.getType(), dict.getK());\n        if (d != null) {\n            throw new IllegalArgumentException(\"类型和key已存在\");\n        }\n        dictDao.save(dict);\n\n        return dict;\n    }\n\n    @GetMapping(\"/{id}\")\n    @ApiOperation(value = \"根据id获取\")\n    public Dict get(@PathVariable Long id) {\n        return dictDao.getById(id);\n    }\n\n    @PreAuthorize(\"hasAuthority('dict:add')\")\n    @PutMapping\n    @ApiOperation(value = \"修改\")\n    public Dict update(@RequestBody Dict dict) {\n        dictDao.update(dict);\n\n        return dict;\n    }\n\n    @PreAuthorize(\"hasAuthority('dict:query')\")\n    @GetMapping(params = {\"start\", \"length\"})\n    @ApiOperation(value = \"列表\")\n    public PageTableResponse list(PageTableRequest request) {\n        return new PageTableHandler(new CountHandler() {\n\n            @Override\n            public int count(PageTableRequest request) {\n                return dictDao.count(request.getParams());\n            }\n        }, new ListHandler() {\n\n            @Override\n            public List<Dict> list(PageTableRequest request) {\n                return dictDao.list(request.getParams(), request.getOffset(), request.getLimit());\n            }\n        }).handle(request);\n    }\n\n    @PreAuthorize(\"hasAuthority('dict:del')\")\n    @DeleteMapping(\"/{id}\")\n    @ApiOperation(value = \"删除\")\n    public void delete(@PathVariable Long id) {\n        dictDao.delete(id);\n    }\n\n    @GetMapping(params = \"type\")\n    public List<Dict> listByType(String type) {\n        return dictDao.listByType(type);\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/controller/EurekaController.java",
    "content": "package com.open.capacity.security.controller;\n\nimport com.fasterxml.jackson.core.JsonGenerator;\nimport com.fasterxml.jackson.core.JsonParser;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.fasterxml.jackson.dataformat.xml.XmlMapper;\nimport org.apache.http.client.config.RequestConfig;\nimport org.apache.http.client.methods.*;\nimport org.apache.http.entity.StringEntity;\nimport org.apache.http.impl.client.CloseableHttpClient;\nimport org.apache.http.impl.client.HttpClientBuilder;\nimport org.apache.http.message.BasicHeader;\nimport org.apache.http.util.EntityUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.cloud.client.ServiceInstance;\nimport org.springframework.cloud.client.discovery.DiscoveryClient;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.io.StringWriter;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2018年3月20日 下午10:13:18 类说明\n */\n@Controller\n@RequestMapping(\"/eureka/\")\npublic class EurekaController {\n\n    private static final Logger LOGGER = LoggerFactory.getLogger(EurekaController.class);\n\n    @Autowired\n    private DiscoveryClient discoveryClient;\n\n    private static String getoperate(String url, int post2get, String... str) {\n\n        String bodyAsString = \"\";\n        CloseableHttpClient httpClient = HttpClientBuilder.create().build();\n        try {\n            RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(10 * 1000)\n                    .setConnectTimeout(10 * 1000).setSocketTimeout(10 * 1000).build();\n\n            if (post2get == -1) {\n                HttpPut po = new HttpPut(url);\n\n                po.setConfig(requestConfig);\n                CloseableHttpResponse response = httpClient.execute(po);\n                bodyAsString = EntityUtils.toString(response.getEntity());\n                LOGGER.info(bodyAsString.toString());\n                return bodyAsString.toString();\n            }\n            if (post2get == 1) {\n                HttpGet po = new HttpGet(url);\n\n                po.setConfig(requestConfig);\n                CloseableHttpResponse response = httpClient.execute(po);\n                bodyAsString = EntityUtils.toString(response.getEntity());\n                LOGGER.info(bodyAsString.toString());\n                return bodyAsString.toString();\n            }\n            if (post2get == 3) {\n\n                HttpPost po = new HttpPost(url);\n                po.addHeader(new BasicHeader(\"Cookie\", \"JSESSIONID=\" + str[0]));\n                po.setConfig(requestConfig);\n                String queryCase = \"name=admin&password=admin&remember=0\";\n                StringEntity reqEntity = new StringEntity(queryCase);\n                reqEntity.setContentType(\"application/x-www-form-urlencoded\");\n                po.setEntity(reqEntity);\n                CloseableHttpResponse response = httpClient.execute(po);\n                bodyAsString = EntityUtils.toString(response.getEntity());\n                LOGGER.info(bodyAsString.toString());\n                return bodyAsString;\n\n            }\n            if (post2get == 4) {\n                HttpGet po = new HttpGet(url);\n                po.addHeader(new BasicHeader(\"Cookie\", \"JSESSIONID=\" + str[0] + \";DISCONF=\" + str[1]));\n                po.setConfig(requestConfig);\n                CloseableHttpResponse response = httpClient.execute(po);\n                bodyAsString = EntityUtils.toString(response.getEntity());\n                LOGGER.info(bodyAsString.toString());\n                return bodyAsString;\n            }\n            if (post2get == 5) {\n\n                HttpPut po = new HttpPut(url);\n                po.addHeader(new BasicHeader(\"Cookie\", \"JSESSIONID=\" + str[0] + \";DISCONF=\" + str[1]));\n                po.setConfig(requestConfig);\n                String text = \"fileContent=\" + str[2];\n                StringEntity reqEntity = new StringEntity(text);\n                reqEntity.setContentType(\"application/x-www-form-urlencoded; charset=UTF-8\");\n                po.setEntity(reqEntity);\n                CloseableHttpResponse response = httpClient.execute(po);\n                bodyAsString = EntityUtils.toString(response.getEntity());\n                LOGGER.info(bodyAsString.toString());\n                return bodyAsString;\n            }\n            if (post2get == 6) {\n\n                HttpPost po = new HttpPost(url);\n                po.setConfig(requestConfig);\n                StringEntity reqEntity = new StringEntity(str[0]);\n                reqEntity.setContentType(\"application/json;charset=utf-8\");\n                po.setEntity(reqEntity);\n                CloseableHttpResponse response = httpClient.execute(po);\n                bodyAsString = EntityUtils.toString(response.getEntity());\n                LOGGER.info(bodyAsString.toString());\n                return bodyAsString;\n\n            } else {\n                HttpPost po = new HttpPost(url);\n                if (str != null && str.length > 0) {\n                    po.addHeader(new BasicHeader(\"Cookie\", \"JSESSIONID=\" + str[0]));\n                }\n                StringEntity reqEntity = new StringEntity(\"\");\n                reqEntity.setContentType(\"application/x-www-form-urlencoded; charset=UTF-8\");\n                po.setEntity(reqEntity);\n\n                po.setConfig(requestConfig);\n                CloseableHttpResponse response = httpClient.execute(po);\n                bodyAsString = EntityUtils.toString(response.getEntity());\n                LOGGER.info(bodyAsString.toString());\n                return bodyAsString;\n            }\n\n        } catch (Exception e) {\n            // TODO Auto-generated catch block\n            e.printStackTrace();\n        }\n        return \"{}\";\n    }\n\n    private static String getinfo(String url) {\n\n        String bodyAsString = \"\";\n        CloseableHttpClient httpClient = HttpClientBuilder.create().build();\n        try {\n            RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(50 * 1000)\n                    .setConnectTimeout(50 * 1000).setSocketTimeout(50 * 1000).build();\n            HttpGet po = new HttpGet(url);\n            if (url.indexOf(\"apps\") > 0) {\n                po.setHeader(\"Accept\", \"application/json\");\n            }\n            po.setConfig(requestConfig);\n            CloseableHttpResponse response = httpClient.execute(po);\n            bodyAsString = EntityUtils.toString(response.getEntity());\n            if (url.indexOf(\"apps\") > 0) {\n                LOGGER.info(bodyAsString.toString());\n                return bodyAsString;\n            }\n            ObjectMapper objectMapper = new ObjectMapper();\n            XmlMapper xmlMapper = new XmlMapper();\n            StringWriter w = new StringWriter();\n            JsonParser jp;\n            try {\n                jp = xmlMapper.getFactory().createParser(bodyAsString);\n                JsonGenerator jg = objectMapper.getFactory().createGenerator(w);\n                while (jp.nextToken() != null) {\n                    jg.copyCurrentEvent(jp);\n                }\n                jp.close();\n                jg.close();\n            } catch (Exception e) {\n                e.printStackTrace();\n            }\n\n            LOGGER.info(w.toString());\n            return w.toString();\n            // logger.info(\"RestContr \"+bodyAsString);\n        } catch (Exception e) {\n            // TODO Auto-generated catch block\n            e.printStackTrace();\n        }\n        return \"{}\";\n    }\n\n    private static String getinfo_put(String url) {\n\n        String bodyAsString = \"\";\n        CloseableHttpClient httpClient = HttpClientBuilder.create().build();\n        try {\n            RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(50 * 1000)\n                    .setConnectTimeout(50 * 1000).setSocketTimeout(50 * 1000).build();\n            HttpPut po = new HttpPut(url);\n\n            po.setConfig(requestConfig);\n            CloseableHttpResponse response = httpClient.execute(po);\n            bodyAsString = EntityUtils.toString(response.getEntity());\n\n            // LOGGER.info(w.toString());\n            return \"{}\";\n            // logger.info(\"RestContr \"+bodyAsString);\n        } catch (Exception e) {\n            // TODO Auto-generated catch block\n            e.printStackTrace();\n        }\n        return \"{}\";\n    }\n\n    private static String getinfo_del(String url) {\n        String bodyAsString = \"\";\n        CloseableHttpClient httpClient = HttpClientBuilder.create().build();\n        try {\n            RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(50000)\n                    .setConnectTimeout(50000).setSocketTimeout(50000).build();\n            HttpDelete po = new HttpDelete(url);\n\n            po.setConfig(requestConfig);\n            CloseableHttpResponse response = httpClient.execute(po);\n            bodyAsString = EntityUtils.toString(response.getEntity());\n\n            return \"{}\";\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n        return \"{}\";\n    }\n\n    @ResponseBody\n    @RequestMapping(value = \"status\", method = RequestMethod.GET)\n    public String status() {\n        String url = \"http://127.0.0.1:1111/eureka/status\";\n        return getinfo(url);\n    }\n\n    @ResponseBody\n    @RequestMapping(value = \"apps\", method = RequestMethod.GET)\n    public String apps() {\n        String url = \"http://127.0.0.1:1111/eureka/apps\";\n        return getinfo(url);\n    }\n\n    @ResponseBody\n    @RequestMapping(value = \"list\", method = RequestMethod.GET)\n    public Map list() {\n\n        List<String> list = discoveryClient.getServices();\n        Map res = new HashMap<>();\n        for (Iterator<String> it = list.iterator(); it.hasNext(); ) {\n            String serviceName = it.next();\n\n            List<ServiceInstance> instances = discoveryClient.getInstances(serviceName);\n\n            for (Iterator<ServiceInstance> its = instances.iterator(); its.hasNext(); ) {\n                ServiceInstance instance = its.next();\n\n                res.putAll(instance.getMetadata());\n\n            }\n\n        }\n\n        return res;\n    }\n\n    @ResponseBody\n    @RequestMapping(value = \"appsmd\", method = RequestMethod.POST)\n    public String appsmd(@RequestParam(value = \"name\", required = false) String str) {\n        String url = \"http://127.0.0.1:1111/eureka/apps/\" + str;\n        return getinfo(url);\n    }\n\n    @ResponseBody\n    @RequestMapping(value = {\"appsmddel\"}, method = RequestMethod.POST)\n    public String appsmddel(@RequestParam(value = \"name\", required = false) String str) {\n        String url = \"http://127.0.0.1:1111/metadata/apps/\" + str;\n        return getinfo_del(url);\n    }\n\n    @ResponseBody\n    @RequestMapping(value = \"operate\", method = RequestMethod.POST)\n    public String operate(@RequestBody HashMap<String, String> inmap) {\n        LOGGER.info(inmap.toString());\n        String op = \"\";\n        int post2get = 0;\n        if (inmap.get(\"operate\").equals(\"1\")) {// 暂停\n            op = \"DOWN\";\n            post2get = -1;\n        }\n        if (inmap.get(\"operate\").equals(\"2\")) {// 挂起\n            op = \"OUT_OF_SERVICE\";\n            post2get = -1;\n        }\n        if (inmap.get(\"operate\").equals(\"3\")) {// 恢复\n            op = \"UP\";\n            post2get = -1;\n        }\n        if (inmap.get(\"operate\").equals(\"4\")) {// 刷新\n            op = \"refresh\";\n        }\n        if (inmap.get(\"operate\").equals(\"5\")) {// 主机性能指标\n            op = \"metrics\";\n            post2get = 1;\n        }\n\n\n        String name = inmap.get(\"app\");\n        String instance = inmap.get(\"instanceId\");\n\n        String path = \"\";\n        if (\"OPEN-EUREKA-CLIENT\".equals(name)) {\n            path = \"/client\";\n        }\n\n        String url = null;\n\n        switch (post2get) {\n            case -1:\n                url = \"http://127.0.0.1:1111/eureka/apps/\" + name + \"/\" + instance + \"\" + \"/status?value=\" + op;\n                break;\n            default:\n                url = \"http://\" + inmap.get(\"ip\") + \":\" + inmap.get(\"port\") + path + \"/\" + op;\n                break;\n        }\n\n        return getoperate(url, post2get, \"\", \"\");\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/controller/ExcelController.java",
    "content": "package com.open.capacity.security.controller;\n\nimport com.open.capacity.security.annotation.LogAnnotation;\nimport com.open.capacity.security.utils.ExcelUtil;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport org.apache.commons.codec.digest.DigestUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.jdbc.core.JdbcTemplate;\nimport org.springframework.security.access.prepost.PreAuthorize;\nimport org.springframework.util.CollectionUtils;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport javax.servlet.http.HttpServletResponse;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\n\n@Api(tags = \"excel下载\")\n@RestController\n@RequestMapping(\"/excels\")\npublic class ExcelController {\n\n    private static final Logger log = LoggerFactory.getLogger(ExcelController.class);\n\n    @Autowired\n    private JdbcTemplate jdbcTemplate;\n\n    @ApiOperation(\"校验sql，并返回sql返回的数量\")\n    @PostMapping(\"/sql-count\")\n    public Integer checkSql(String sql) {\n        log.info(sql);\n        sql = getAndCheckSql(sql);\n\n        Integer count = 0;\n        try {\n            count = jdbcTemplate.queryForObject(\"select count(1) from (\" + sql + \") t\", Integer.class);\n        } catch (Exception e) {\n            throw new IllegalArgumentException(e.getMessage());\n        }\n\n        return count;\n    }\n\n    private String getAndCheckSql(String sql) {\n        sql = sql.trim().toLowerCase();\n        if (sql.endsWith(\";\") || sql.endsWith(\"；\")) {\n            sql = sql.substring(0, sql.length() - 1);\n        }\n        if (!sql.startsWith(\"select\")) {\n            throw new IllegalArgumentException(\"仅支持select语句\");\n        }\n        return sql;\n    }\n\n    @LogAnnotation\n    @ApiOperation(\"根据sql导出excel\")\n    @PostMapping\n    @PreAuthorize(\"hasAuthority('excel:down')\")\n    public void downloadExcel(String sql, String fileName, HttpServletResponse response) {\n        sql = getAndCheckSql(sql);\n        List<Map<String, Object>> list = jdbcTemplate.queryForList(sql);\n\n        if (!CollectionUtils.isEmpty(list)) {\n            Map<String, Object> map = list.get(0);\n\n            String[] headers = new String[map.size()];\n            int i = 0;\n            for (String key : map.keySet()) {\n                headers[i++] = key;\n            }\n\n            List<Object[]> datas = new ArrayList<>(list.size());\n            for (Map<String, Object> m : list) {\n                Object[] objects = new Object[headers.length];\n                for (int j = 0; j < headers.length; j++) {\n                    objects[j] = m.get(headers[j]);\n                }\n\n                datas.add(objects);\n            }\n\n            ExcelUtil.excelExport(\n                    fileName == null || fileName.trim().length() <= 0 ? DigestUtils.md5Hex(sql) : fileName, headers,\n                    datas, response);\n        }\n    }\n\n    @LogAnnotation\n    @ApiOperation(\"根据sql在页面显示结果\")\n    @PostMapping(\"/show-datas\")\n    @PreAuthorize(\"hasAuthority('excel:show:datas')\")\n    public List<Object[]> showData(String sql) {\n        sql = getAndCheckSql(sql);\n        List<Map<String, Object>> list = jdbcTemplate.queryForList(sql);\n\n        if (!CollectionUtils.isEmpty(list)) {\n            Map<String, Object> map = list.get(0);\n\n            String[] headers = new String[map.size()];\n            int i = 0;\n            for (String key : map.keySet()) {\n                headers[i++] = key;\n            }\n\n            List<Object[]> datas = new ArrayList<>(list.size());\n            datas.add(headers);\n            for (Map<String, Object> m : list) {\n                Object[] objects = new Object[headers.length];\n                for (int j = 0; j < headers.length; j++) {\n                    objects[j] = m.get(headers[j]);\n                }\n\n                datas.add(objects);\n            }\n\n            return datas;\n        }\n\n        return Collections.emptyList();\n    }\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/controller/FileController.java",
    "content": "package com.open.capacity.security.controller;\n\nimport com.open.capacity.security.annotation.LogAnnotation;\nimport com.open.capacity.security.dao.FileInfoDao;\nimport com.open.capacity.security.dto.LayuiFile;\nimport com.open.capacity.security.dto.LayuiFile.LayuiFileData;\nimport com.open.capacity.security.model.FileInfo;\nimport com.open.capacity.security.page.table.PageTableHandler;\nimport com.open.capacity.security.page.table.PageTableHandler.CountHandler;\nimport com.open.capacity.security.page.table.PageTableHandler.ListHandler;\nimport com.open.capacity.security.page.table.PageTableRequest;\nimport com.open.capacity.security.page.table.PageTableResponse;\nimport com.open.capacity.security.service.FileService;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.security.access.prepost.PreAuthorize;\nimport org.springframework.web.bind.annotation.*;\nimport org.springframework.web.multipart.MultipartFile;\n\nimport java.io.IOException;\nimport java.util.List;\n\n@Api(tags = \"文件\")\n@RestController\n@RequestMapping(\"/files\")\npublic class FileController {\n\n    @Autowired\n    private FileService fileService;\n    @Autowired\n    private FileInfoDao fileInfoDao;\n\n    @LogAnnotation\n    @PostMapping\n    @ApiOperation(value = \"文件上传\")\n    public FileInfo uploadFile(MultipartFile file) throws IOException {\n        return fileService.save(file);\n    }\n\n    /**\n     * layui富文本文件自定义上传\n     *\n     * @param file\n     * @param domain\n     * @return\n     * @throws IOException\n     */\n    @LogAnnotation\n    @PostMapping(\"/layui\")\n    @ApiOperation(value = \"layui富文本文件自定义上传\")\n    public LayuiFile uploadLayuiFile(MultipartFile file, String domain) throws IOException {\n        FileInfo fileInfo = fileService.save(file);\n\n        LayuiFile layuiFile = new LayuiFile();\n        layuiFile.setCode(0);\n        LayuiFileData data = new LayuiFileData();\n        layuiFile.setData(data);\n        data.setSrc(domain + \"/statics\" + fileInfo.getUrl());\n        data.setTitle(file.getOriginalFilename());\n\n        return layuiFile;\n    }\n\n    @GetMapping\n    @ApiOperation(value = \"文件查询\")\n    @PreAuthorize(\"hasAuthority('sys:file:query')\")\n    public PageTableResponse listFiles(PageTableRequest request) {\n        return new PageTableHandler(new CountHandler() {\n\n            @Override\n            public int count(PageTableRequest request) {\n                return fileInfoDao.count(request.getParams());\n            }\n        }, new ListHandler() {\n\n            @Override\n            public List<FileInfo> list(PageTableRequest request) {\n                List<FileInfo> list = fileInfoDao.list(request.getParams(), request.getOffset(), request.getLimit());\n                return list;\n            }\n        }).handle(request);\n    }\n\n    @LogAnnotation\n    @DeleteMapping(\"/{id}\")\n    @ApiOperation(value = \"文件删除\")\n    @PreAuthorize(\"hasAuthority('sys:file:del')\")\n    public void delete(@PathVariable String id) {\n        fileService.delete(id);\n    }\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/controller/GenerateController.java",
    "content": "package com.open.capacity.security.controller;\n\nimport com.open.capacity.security.annotation.LogAnnotation;\nimport com.open.capacity.security.dto.BeanField;\nimport com.open.capacity.security.dto.GenerateDetail;\nimport com.open.capacity.security.dto.GenerateInput;\nimport com.open.capacity.security.service.GenerateService;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.security.access.prepost.PreAuthorize;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.List;\n\n/**\n * 代码生成接口\n *\n * @author owen 624191343@qq.com\n */\n@Api(tags = \"代码生成\")\n@RestController\n@RequestMapping(\"/generate\")\npublic class GenerateController {\n\n    @Autowired\n    private GenerateService generateService;\n\n    @ApiOperation(\"根据表名显示表信息\")\n    @GetMapping(params = {\"tableName\"})\n    @PreAuthorize(\"hasAuthority('generate:edit')\")\n    public GenerateDetail generateByTableName(String tableName) {\n        GenerateDetail detail = new GenerateDetail();\n        detail.setBeanName(generateService.upperFirstChar(tableName));\n        List<BeanField> fields = generateService.listBeanField(tableName);\n        detail.setFields(fields);\n\n        return detail;\n    }\n\n    @LogAnnotation\n    @ApiOperation(\"生成代码\")\n    @PostMapping\n    @PreAuthorize(\"hasAuthority('generate:edit')\")\n    public void save(@RequestBody GenerateInput input) {\n        generateService.saveCode(input);\n    }\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/controller/MailController.java",
    "content": "package com.open.capacity.security.controller;\n\nimport com.open.capacity.security.annotation.LogAnnotation;\nimport com.open.capacity.security.dao.MailDao;\nimport com.open.capacity.security.model.Mail;\nimport com.open.capacity.security.model.MailTo;\nimport com.open.capacity.security.page.table.PageTableHandler;\nimport com.open.capacity.security.page.table.PageTableHandler.CountHandler;\nimport com.open.capacity.security.page.table.PageTableHandler.ListHandler;\nimport com.open.capacity.security.page.table.PageTableRequest;\nimport com.open.capacity.security.page.table.PageTableResponse;\nimport com.open.capacity.security.service.MailService;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.security.access.prepost.PreAuthorize;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.stream.Collectors;\n\n@Api(tags = \"邮件\")\n@RestController\n@RequestMapping(\"/mails\")\npublic class MailController {\n\n    @Autowired\n    private MailDao mailDao;\n    @Autowired\n    private MailService mailService;\n\n    @LogAnnotation\n    @PostMapping\n    @ApiOperation(value = \"保存邮件\")\n    @PreAuthorize(\"hasAuthority('mail:send')\")\n    public Mail save(@RequestBody Mail mail) {\n        String toUsers = mail.getToUsers().trim();\n        if (StringUtils.isBlank(toUsers)) {\n            throw new IllegalArgumentException(\"收件人不能为空\");\n        }\n\n        toUsers = toUsers.replace(\" \", \"\");\n        toUsers = toUsers.replace(\"；\", \";\");\n        String[] strings = toUsers.split(\";\");\n\n        List<String> toUser = Arrays.asList(strings);\n        toUser = toUser.stream().filter(u -> !StringUtils.isBlank(u)).map(u -> u.trim()).collect(Collectors.toList());\n        mailService.save(mail, toUser);\n\n        return mail;\n    }\n\n    @GetMapping(\"/{id}\")\n    @ApiOperation(value = \"根据id获取邮件\")\n    @PreAuthorize(\"hasAuthority('mail:all:query')\")\n    public Mail get(@PathVariable Long id) {\n        return mailDao.getById(id);\n    }\n\n    @GetMapping(\"/{id}/to\")\n    @ApiOperation(value = \"根据id获取邮件发送详情\")\n    @PreAuthorize(\"hasAuthority('mail:all:query')\")\n    public List<MailTo> getMailTo(@PathVariable Long id) {\n        return mailDao.getToUsers(id);\n    }\n\n    @GetMapping\n    @ApiOperation(value = \"邮件列表\")\n    @PreAuthorize(\"hasAuthority('mail:all:query')\")\n    public PageTableResponse list(PageTableRequest request) {\n        return new PageTableHandler(new CountHandler() {\n\n            @Override\n            public int count(PageTableRequest request) {\n                return mailDao.count(request.getParams());\n            }\n        }, new ListHandler() {\n\n            @Override\n            public List<Mail> list(PageTableRequest request) {\n                return mailDao.list(request.getParams(), request.getOffset(), request.getLimit());\n            }\n        }).handle(request);\n    }\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/controller/NoticeController.java",
    "content": "package com.open.capacity.security.controller;\n\nimport com.open.capacity.security.annotation.LogAnnotation;\nimport com.open.capacity.security.dao.NoticeDao;\nimport com.open.capacity.security.dto.NoticeReadVO;\nimport com.open.capacity.security.dto.NoticeVO;\nimport com.open.capacity.security.model.Notice;\nimport com.open.capacity.security.model.Notice.Status;\nimport com.open.capacity.security.model.SysUser;\nimport com.open.capacity.security.page.table.PageTableHandler;\nimport com.open.capacity.security.page.table.PageTableHandler.CountHandler;\nimport com.open.capacity.security.page.table.PageTableHandler.ListHandler;\nimport com.open.capacity.security.page.table.PageTableRequest;\nimport com.open.capacity.security.page.table.PageTableResponse;\nimport com.open.capacity.security.utils.UserUtil;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.security.access.prepost.PreAuthorize;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.List;\n\n@Api(tags = \"公告\")\n@RestController\n@RequestMapping(\"/notices\")\npublic class NoticeController {\n\n    @Autowired\n    private NoticeDao noticeDao;\n\n    @LogAnnotation\n    @PostMapping\n    @ApiOperation(value = \"保存公告\")\n    @PreAuthorize(\"hasAuthority('notice:add')\")\n    public Notice saveNotice(@RequestBody Notice notice) {\n        noticeDao.save(notice);\n\n        return notice;\n    }\n\n    @GetMapping(\"/{id}\")\n    @ApiOperation(value = \"根据id获取公告\")\n    @PreAuthorize(\"hasAuthority('notice:query')\")\n    public Notice get(@PathVariable Long id) {\n        return noticeDao.getById(id);\n    }\n\n    @GetMapping(params = \"id\")\n    public NoticeVO readNotice(Long id) {\n        NoticeVO vo = new NoticeVO();\n\n        Notice notice = noticeDao.getById(id);\n        if (notice == null || notice.getStatus() == Status.DRAFT) {\n            return vo;\n        }\n        vo.setNotice(notice);\n\n        noticeDao.saveReadRecord(notice.getId(), UserUtil.getLoginUser().getId());\n\n        List<SysUser> users = noticeDao.listReadUsers(id);\n        vo.setUsers(users);\n\n        return vo;\n    }\n\n    @LogAnnotation\n    @PutMapping\n    @ApiOperation(value = \"修改公告\")\n    @PreAuthorize(\"hasAuthority('notice:add')\")\n    public Notice updateNotice(@RequestBody Notice notice) {\n        Notice no = noticeDao.getById(notice.getId());\n        if (no.getStatus() == Status.PUBLISH) {\n            throw new IllegalArgumentException(\"发布状态的不能修改\");\n        }\n        noticeDao.update(notice);\n\n        return notice;\n    }\n\n    @GetMapping\n    @ApiOperation(value = \"公告管理列表\")\n    @PreAuthorize(\"hasAuthority('notice:query')\")\n    public PageTableResponse listNotice(PageTableRequest request) {\n        return new PageTableHandler(new CountHandler() {\n\n            @Override\n            public int count(PageTableRequest request) {\n                return noticeDao.count(request.getParams());\n            }\n        }, new ListHandler() {\n\n            @Override\n            public List<Notice> list(PageTableRequest request) {\n                return noticeDao.list(request.getParams(), request.getOffset(), request.getLimit());\n            }\n        }).handle(request);\n    }\n\n    @LogAnnotation\n    @DeleteMapping(\"/{id}\")\n    @ApiOperation(value = \"删除公告\")\n    @PreAuthorize(\"hasAuthority('notice:del')\")\n    public void delete(@PathVariable Long id) {\n        noticeDao.delete(id);\n    }\n\n    @ApiOperation(value = \"未读公告数\")\n    @GetMapping(\"/count-unread\")\n    public Integer countUnread() {\n        SysUser user = UserUtil.getLoginUser();\n        return noticeDao.countUnread(user.getId());\n    }\n\n    @GetMapping(\"/published\")\n    @ApiOperation(value = \"公告列表\")\n    public PageTableResponse listNoticeReadVO(PageTableRequest request) {\n        request.getParams().put(\"userId\", UserUtil.getLoginUser().getId());\n\n        return new PageTableHandler(new CountHandler() {\n\n            @Override\n            public int count(PageTableRequest request) {\n                return noticeDao.countNotice(request.getParams());\n            }\n        }, new ListHandler() {\n\n            @Override\n            public List<NoticeReadVO> list(PageTableRequest request) {\n                return noticeDao.listNotice(request.getParams(), request.getOffset(), request.getLimit());\n            }\n        }).handle(request);\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/controller/PermissionController.java",
    "content": "package com.open.capacity.security.controller;\n\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\nimport com.google.common.collect.Lists;\nimport com.open.capacity.security.annotation.LogAnnotation;\nimport com.open.capacity.security.dao.PermissionDao;\nimport com.open.capacity.security.dto.LoginUser;\nimport com.open.capacity.security.model.Permission;\nimport com.open.capacity.security.service.PermissionService;\nimport com.open.capacity.security.utils.UserUtil;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.security.access.prepost.PreAuthorize;\nimport org.springframework.util.CollectionUtils;\nimport org.springframework.util.StringUtils;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Set;\nimport java.util.stream.Collectors;\n\n/**\n * 权限相关接口\n *\n * @author owen 624191343@qq.com\n */\n@Api(tags = \"权限\")\n@RestController\n@RequestMapping(\"/permissions\")\npublic class PermissionController {\n\n    @Autowired\n    private PermissionDao permissionDao;\n    @Autowired\n    private PermissionService permissionService;\n\n    @ApiOperation(value = \"当前登录用户拥有的权限\")\n    @GetMapping(\"/current\")\n    public List<Permission> permissionsCurrent() {\n        LoginUser loginUser = UserUtil.getLoginUser();\n        List<Permission> list = loginUser.getPermissions();\n        final List<Permission> permissions = list.stream().filter(l -> l.getType().equals(1))\n                .collect(Collectors.toList());\n\n        setChild(permissions);\n\n        return permissions.stream().filter(p -> p.getParentId().equals(0L)).collect(Collectors.toList());\n    }\n\n    private void setChild(List<Permission> permissions) {\n        permissions.parallelStream().forEach(per -> {\n            List<Permission> child = permissions.stream().filter(p -> p.getParentId().equals(per.getId()))\n                    .collect(Collectors.toList());\n            per.setChild(child);\n        });\n    }\n\n    /**\n     * 菜单列表\n     *\n     * @param pId\n     * @param permissionsAll\n     * @param list\n     */\n    private void setPermissionsList(Long pId, List<Permission> permissionsAll, List<Permission> list) {\n        for (Permission per : permissionsAll) {\n            if (per.getParentId().equals(pId)) {\n                list.add(per);\n                if (permissionsAll.stream().filter(p -> p.getParentId().equals(per.getId())).findAny() != null) {\n                    setPermissionsList(per.getId(), permissionsAll, list);\n                }\n            }\n        }\n    }\n\n    @GetMapping\n    @ApiOperation(value = \"菜单列表\")\n    @PreAuthorize(\"hasAuthority('sys:menu:query')\")\n    public List<Permission> permissionsList() {\n        List<Permission> permissionsAll = permissionDao.listAll();\n\n        List<Permission> list = Lists.newArrayList();\n        setPermissionsList(0L, permissionsAll, list);\n\n        return list;\n    }\n\n    @GetMapping(\"/all\")\n    @ApiOperation(value = \"所有菜单\")\n    @PreAuthorize(\"hasAuthority('sys:menu:query')\")\n    public JSONArray permissionsAll() {\n        List<Permission> permissionsAll = permissionDao.listAll();\n        JSONArray array = new JSONArray();\n        setPermissionsTree(0L, permissionsAll, array);\n\n        return array;\n    }\n\n    @GetMapping(\"/parents\")\n    @ApiOperation(value = \"一级菜单\")\n    @PreAuthorize(\"hasAuthority('sys:menu:query')\")\n    public List<Permission> parentMenu() {\n        List<Permission> parents = permissionDao.listParents();\n\n        return parents;\n    }\n\n    /**\n     * 菜单树\n     *\n     * @param pId\n     * @param permissionsAll\n     * @param array\n     */\n    private void setPermissionsTree(Long pId, List<Permission> permissionsAll, JSONArray array) {\n        for (Permission per : permissionsAll) {\n            if (per.getParentId().equals(pId)) {\n                String string = JSONObject.toJSONString(per);\n                JSONObject parent = (JSONObject) JSONObject.parse(string);\n                array.add(parent);\n\n                if (permissionsAll.stream().filter(p -> p.getParentId().equals(per.getId())).findAny() != null) {\n                    JSONArray child = new JSONArray();\n                    parent.put(\"child\", child);\n                    setPermissionsTree(per.getId(), permissionsAll, child);\n                }\n            }\n        }\n    }\n\n    @GetMapping(params = \"roleId\")\n    @ApiOperation(value = \"根据角色id删除权限\")\n    @PreAuthorize(\"hasAnyAuthority('sys:menu:query','sys:role:query')\")\n    public List<Permission> listByRoleId(Long roleId) {\n        return permissionDao.listByRoleId(roleId);\n    }\n\n    @LogAnnotation\n    @PostMapping\n    @ApiOperation(value = \"保存菜单\")\n    @PreAuthorize(\"hasAuthority('sys:menu:add')\")\n    public void save(@RequestBody Permission permission) {\n        permissionDao.save(permission);\n    }\n\n    @GetMapping(\"/{id}\")\n    @ApiOperation(value = \"根据菜单id获取菜单\")\n    @PreAuthorize(\"hasAuthority('sys:menu:query')\")\n    public Permission get(@PathVariable Long id) {\n        return permissionDao.getById(id);\n    }\n\n    @LogAnnotation\n    @PutMapping\n    @ApiOperation(value = \"修改菜单\")\n    @PreAuthorize(\"hasAuthority('sys:menu:add')\")\n    public void update(@RequestBody Permission permission) {\n        permissionService.update(permission);\n    }\n\n    /**\n     * 校验权限\n     *\n     * @return\n     */\n    @GetMapping(\"/owns\")\n    @ApiOperation(value = \"校验当前用户的权限\")\n    public Set<String> ownsPermission() {\n        List<Permission> permissions = UserUtil.getLoginUser().getPermissions();\n        if (CollectionUtils.isEmpty(permissions)) {\n            return Collections.emptySet();\n        }\n\n        return permissions.parallelStream().filter(p -> !StringUtils.isEmpty(p.getPermission()))\n                .map(Permission::getPermission).collect(Collectors.toSet());\n    }\n\n    @LogAnnotation\n    @DeleteMapping(\"/{id}\")\n    @ApiOperation(value = \"删除菜单\")\n    @PreAuthorize(\"hasAuthority('sys:menu:del')\")\n    public void delete(@PathVariable Long id) {\n        permissionService.delete(id);\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/controller/RoleController.java",
    "content": "package com.open.capacity.security.controller;\n\nimport com.google.common.collect.Maps;\nimport com.open.capacity.security.annotation.LogAnnotation;\nimport com.open.capacity.security.dao.RoleDao;\nimport com.open.capacity.security.dto.RoleDto;\nimport com.open.capacity.security.model.Role;\nimport com.open.capacity.security.page.table.PageTableHandler;\nimport com.open.capacity.security.page.table.PageTableHandler.CountHandler;\nimport com.open.capacity.security.page.table.PageTableHandler.ListHandler;\nimport com.open.capacity.security.page.table.PageTableRequest;\nimport com.open.capacity.security.page.table.PageTableResponse;\nimport com.open.capacity.security.service.RoleService;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.security.access.prepost.PreAuthorize;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.List;\n\n/**\n * 角色相关接口\n *\n * @author owen 624191343@qq.com\n */\n@Api(tags = \"角色\")\n@RestController\n@RequestMapping(\"/roles\")\npublic class RoleController {\n\n    @Autowired\n    private RoleService roleService;\n    @Autowired\n    private RoleDao roleDao;\n\n    @LogAnnotation\n    @PostMapping\n    @ApiOperation(value = \"保存角色\")\n    @PreAuthorize(\"hasAuthority('sys:role:add')\")\n    public void saveRole(@RequestBody RoleDto roleDto) {\n        roleService.saveRole(roleDto);\n    }\n\n    @GetMapping\n    @ApiOperation(value = \"角色列表\")\n    @PreAuthorize(\"hasAuthority('sys:role:query')\")\n    public PageTableResponse listRoles(PageTableRequest request) {\n        return new PageTableHandler(new CountHandler() {\n\n            @Override\n            public int count(PageTableRequest request) {\n                return roleDao.count(request.getParams());\n            }\n        }, new ListHandler() {\n\n            @Override\n            public List<Role> list(PageTableRequest request) {\n                List<Role> list = roleDao.list(request.getParams(), request.getOffset(), request.getLimit());\n                return list;\n            }\n        }).handle(request);\n    }\n\n    @GetMapping(\"/{id}\")\n    @ApiOperation(value = \"根据id获取角色\")\n    @PreAuthorize(\"hasAuthority('sys:role:query')\")\n    public Role get(@PathVariable Long id) {\n        return roleDao.getById(id);\n    }\n\n    @GetMapping(\"/all\")\n    @ApiOperation(value = \"所有角色\")\n    @PreAuthorize(\"hasAnyAuthority('sys:user:query','sys:role:query')\")\n    public List<Role> roles() {\n        return roleDao.list(Maps.newHashMap(), null, null);\n    }\n\n    @GetMapping(params = \"userId\")\n    @ApiOperation(value = \"根据用户id获取拥有的角色\")\n    @PreAuthorize(\"hasAnyAuthority('sys:user:query','sys:role:query')\")\n    public List<Role> roles(Long userId) {\n        return roleDao.listByUserId(userId);\n    }\n\n    @LogAnnotation\n    @DeleteMapping(\"/{id}\")\n    @ApiOperation(value = \"删除角色\")\n    @PreAuthorize(\"hasAuthority('sys:role:del')\")\n    public void delete(@PathVariable Long id) {\n        roleService.deleteRole(id);\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/controller/ServiceController.java",
    "content": "package com.open.capacity.security.controller;\n\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\nimport com.google.common.collect.Lists;\nimport com.open.capacity.security.annotation.LogAnnotation;\nimport com.open.capacity.security.dao.ServiceDao;\nimport com.open.capacity.security.dto.LoginUser;\nimport com.open.capacity.security.model.Permission;\nimport com.open.capacity.security.service.MicroServiceService;\nimport com.open.capacity.security.utils.UserUtil;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.security.access.prepost.PreAuthorize;\nimport org.springframework.util.CollectionUtils;\nimport org.springframework.util.StringUtils;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Set;\nimport java.util.stream.Collectors;\n\n/**\n * 权限相关接口\n *\n * @author owen 624191343@qq.com\n */\n@Api(tags = \"服务\")\n@RestController\n@RequestMapping(\"/services\")\npublic class ServiceController {\n\n    @Autowired\n    private ServiceDao serviceDao;\n    @Autowired\n    private MicroServiceService microServiceService;\n\n    @ApiOperation(value = \"当前登录用户拥有的权限\")\n    @GetMapping(\"/current\")\n    public List<Permission> permissionsCurrent() {\n        LoginUser loginUser = UserUtil.getLoginUser();\n        List<Permission> list = loginUser.getPermissions();\n        final List<Permission> permissions = list.stream().filter(l -> l.getType().equals(1))\n                .collect(Collectors.toList());\n\n        setChild(permissions);\n\n        return permissions.stream().filter(p -> p.getParentId().equals(0L)).collect(Collectors.toList());\n    }\n\n    private void setChild(List<Permission> permissions) {\n        permissions.parallelStream().forEach(per -> {\n            List<Permission> child = permissions.stream().filter(p -> p.getParentId().equals(per.getId()))\n                    .collect(Collectors.toList());\n            per.setChild(child);\n        });\n    }\n\n    /**\n     * 菜单列表\n     *\n     * @param pId\n     * @param permissionsAll\n     * @param list\n     */\n    private void setPermissionsList(Long pId, List<Permission> permissionsAll, List<Permission> list) {\n        for (Permission per : permissionsAll) {\n            if (per.getParentId().equals(pId)) {\n                list.add(per);\n                if (permissionsAll.stream().filter(p -> p.getParentId().equals(per.getId())).findAny() != null) {\n                    setPermissionsList(per.getId(), permissionsAll, list);\n                }\n            }\n        }\n    }\n\n    @GetMapping\n    @ApiOperation(value = \"服务列表\")\n    @PreAuthorize(\"hasAuthority('sys:menu:query')\")\n    public List<Permission> permissionsList() {\n        List<Permission> permissionsAll = serviceDao.listAll();\n\n        List<Permission> list = Lists.newArrayList();\n        setPermissionsList(0L, permissionsAll, list);\n\n        return list;\n    }\n\n    @GetMapping(\"/all\")\n    @ApiOperation(value = \"所有服务\")\n    @PreAuthorize(\"hasAuthority('sys:menu:query')\")\n    public JSONArray permissionsAll() {\n        List<Permission> permissionsAll = serviceDao.listAll();\n        JSONArray array = new JSONArray();\n        setPermissionsTree(0L, permissionsAll, array);\n\n        return array;\n    }\n\n    @GetMapping(\"/parents\")\n    @ApiOperation(value = \"一级服务\")\n    @PreAuthorize(\"hasAuthority('sys:menu:query')\")\n    public List<Permission> parentMenu() {\n        List<Permission> parents = serviceDao.listParents();\n\n        return parents;\n    }\n\n    /**\n     * 菜单树\n     *\n     * @param pId\n     * @param permissionsAll\n     * @param array\n     */\n    private void setPermissionsTree(Long pId, List<Permission> permissionsAll, JSONArray array) {\n        for (Permission per : permissionsAll) {\n            if (per.getParentId().equals(pId)) {\n                String string = JSONObject.toJSONString(per);\n                JSONObject parent = (JSONObject) JSONObject.parse(string);\n                array.add(parent);\n\n                if (permissionsAll.stream().filter(p -> p.getParentId().equals(per.getId())).findAny() != null) {\n                    JSONArray child = new JSONArray();\n                    parent.put(\"child\", child);\n                    setPermissionsTree(per.getId(), permissionsAll, child);\n                }\n            }\n        }\n    }\n\n    @GetMapping(params = \"clientId\")\n    @ApiOperation(value = \"根据应用id查询权限\")\n    @PreAuthorize(\"hasAnyAuthority('sys:menu:query','sys:role:query')\")\n    public List<Permission> listByRoleId(Long clientId) {\n        return serviceDao.listByClientId(clientId);\n    }\n\n    @LogAnnotation\n    @PostMapping\n    @ApiOperation(value = \"保存服务\")\n    @PreAuthorize(\"hasAuthority('sys:menu:add')\")\n    public void save(@RequestBody Permission permission) {\n        serviceDao.save(permission);\n    }\n\n    @GetMapping(\"/{id}\")\n    @ApiOperation(value = \"根据服务id获取服务\")\n    @PreAuthorize(\"hasAuthority('sys:menu:query')\")\n    public Permission get(@PathVariable Long id) {\n        return serviceDao.getById(id);\n    }\n\n    @LogAnnotation\n    @PutMapping\n    @ApiOperation(value = \"修改服务\")\n    @PreAuthorize(\"hasAuthority('sys:menu:add')\")\n    public void update(@RequestBody Permission permission) {\n        microServiceService.update(permission);\n    }\n\n    /**\n     * 校验权限\n     *\n     * @return\n     */\n    @GetMapping(\"/owns\")\n    @ApiOperation(value = \"校验当前用户的权限\")\n    public Set<String> ownsPermission() {\n        List<Permission> permissions = UserUtil.getLoginUser().getPermissions();\n        if (CollectionUtils.isEmpty(permissions)) {\n            return Collections.emptySet();\n        }\n\n        return permissions.parallelStream().filter(p -> !StringUtils.isEmpty(p.getPermission()))\n                .map(Permission::getPermission).collect(Collectors.toSet());\n    }\n\n    @LogAnnotation\n    @DeleteMapping(\"/{id}\")\n    @ApiOperation(value = \"删除服务\")\n    @PreAuthorize(\"hasAuthority('sys:menu:del')\")\n    public void delete(@PathVariable Long id) {\n        microServiceService.delete(id);\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/controller/SysLogsController.java",
    "content": "package com.open.capacity.security.controller;\n\nimport com.open.capacity.security.dao.SysLogsDao;\nimport com.open.capacity.security.model.SysLogs;\nimport com.open.capacity.security.page.table.PageTableHandler;\nimport com.open.capacity.security.page.table.PageTableHandler.CountHandler;\nimport com.open.capacity.security.page.table.PageTableHandler.ListHandler;\nimport com.open.capacity.security.page.table.PageTableRequest;\nimport com.open.capacity.security.page.table.PageTableResponse;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.security.access.prepost.PreAuthorize;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.List;\n\n@Api(tags = \"日志\")\n@RestController\n@RequestMapping(\"/logs\")\npublic class SysLogsController {\n\n    @Autowired\n    private SysLogsDao sysLogsDao;\n\n    @GetMapping\n    @PreAuthorize(\"hasAuthority('sys:log:query')\")\n    @ApiOperation(value = \"日志列表\")\n    public PageTableResponse list(PageTableRequest request) {\n        return new PageTableHandler(new CountHandler() {\n\n            @Override\n            public int count(PageTableRequest request) {\n                return sysLogsDao.count(request.getParams());\n            }\n        }, new ListHandler() {\n\n            @Override\n            public List<SysLogs> list(PageTableRequest request) {\n                return sysLogsDao.list(request.getParams(), request.getOffset(), request.getLimit());\n            }\n        }).handle(request);\n    }\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/controller/UserController.java",
    "content": "package com.open.capacity.security.controller;\n\nimport com.open.capacity.security.annotation.LogAnnotation;\nimport com.open.capacity.security.dao.UserDao;\nimport com.open.capacity.security.dto.UserDto;\nimport com.open.capacity.security.model.SysUser;\nimport com.open.capacity.security.page.table.PageTableHandler;\nimport com.open.capacity.security.page.table.PageTableHandler.CountHandler;\nimport com.open.capacity.security.page.table.PageTableHandler.ListHandler;\nimport com.open.capacity.security.page.table.PageTableRequest;\nimport com.open.capacity.security.page.table.PageTableResponse;\nimport com.open.capacity.security.service.UserService;\nimport com.open.capacity.security.utils.UserUtil;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.BeanUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.security.access.prepost.PreAuthorize;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.List;\n\n/**\n * 用户相关接口\n *\n * @author 624191343@qq.com\n */\n@Api(tags = \"用户\")\n\n@RestController\n@RequestMapping(\"/users\")\npublic class UserController {\n\n    private static final Logger log = LoggerFactory.getLogger(UserController.class);\n\n    @Autowired\n    private UserService userService;\n    @Autowired\n    private UserDao userDao;\n\n    @LogAnnotation\n    @PostMapping\n    @ApiOperation(value = \"保存用户\")\n    @PreAuthorize(\"hasAuthority('sys:user:add')\")\n    public SysUser saveUser(@RequestBody UserDto userDto) {\n        SysUser u = userService.getUser(userDto.getUsername());\n        if (u != null) {\n            throw new IllegalArgumentException(userDto.getUsername() + \"已存在\");\n        }\n\n        return userService.saveUser(userDto);\n    }\n\n    @LogAnnotation\n    @PutMapping\n    @ApiOperation(value = \"修改用户\")\n    @PreAuthorize(\"hasAuthority('sys:user:add')\")\n    public SysUser updateUser(@RequestBody UserDto userDto) {\n        return userService.updateUser(userDto);\n    }\n\n    @LogAnnotation\n    @PutMapping(params = \"headImgUrl\")\n    @ApiOperation(value = \"修改头像\")\n    public void updateHeadImgUrl(String headImgUrl) {\n        SysUser user = UserUtil.getLoginUser();\n        UserDto userDto = new UserDto();\n        BeanUtils.copyProperties(user, userDto);\n        userDto.setHeadImgUrl(headImgUrl);\n\n        userService.updateUser(userDto);\n        log.debug(\"{}修改了头像\", user.getUsername());\n    }\n\n    @LogAnnotation\n    @PutMapping(\"/{username}\")\n    @ApiOperation(value = \"修改密码\")\n    @PreAuthorize(\"hasAuthority('sys:user:password')\")\n    public void changePassword(@PathVariable String username, String oldPassword, String newPassword) {\n        userService.changePassword(username, oldPassword, newPassword);\n    }\n\n    @GetMapping\n    @ApiOperation(value = \"用户列表\")\n    @PreAuthorize(\"hasAuthority('sys:user:query')\")\n    public PageTableResponse listUsers(PageTableRequest request) {\n        return new PageTableHandler(new CountHandler() {\n\n            @Override\n            public int count(PageTableRequest request) {\n                return userDao.count(request.getParams());\n            }\n        }, new ListHandler() {\n\n            @Override\n            public List<SysUser> list(PageTableRequest request) {\n                List<SysUser> list = userDao.list(request.getParams(), request.getOffset(), request.getLimit());\n                return list;\n            }\n        }).handle(request);\n    }\n\n    @ApiOperation(value = \"当前登录用户\")\n    @GetMapping(\"/current\")\n    public SysUser currentUser() {\n        return UserUtil.getLoginUser();\n    }\n\n    @ApiOperation(value = \"根据用户id获取用户\")\n    @GetMapping(\"/{id}\")\n    @PreAuthorize(\"hasAuthority('sys:user:query')\")\n    public SysUser user(@PathVariable Long id) {\n        return userDao.getById(id);\n    }\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/dao/ClientDao.java",
    "content": "package com.open.capacity.security.dao;\n\nimport com.open.capacity.security.model.Client;\nimport org.apache.ibatis.annotations.*;\n\nimport java.util.List;\nimport java.util.Map;\n\n@Mapper\npublic interface ClientDao {\n\n    @Options(useGeneratedKeys = true, keyProperty = \"id\")\n    @Insert(\"insert into oauth_client_details(client_id, resource_ids, client_secret, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove) values(#{clientId}, #{resourceIds}, #{clientSecret}, #{scope}, #{authorizedGrantTypes}, #{webServerRedirectUri}, #{authorities}, #{accessTokenValidity}, #{refreshTokenValidity}, #{additionalInformation}, #{autoapprove})\")\n    int save(Client client);\n\n    int count(@Param(\"params\") Map<String, Object> params);\n\n    List<Client> list(@Param(\"params\") Map<String, Object> params, @Param(\"offset\") Integer offset,\n                      @Param(\"limit\") Integer limit);\n\n    @Select(\"select id id , client_id clientId , resource_ids resourceIds ,client_secret clientSecret ,web_server_redirect_uri webServerRedirectUri  from oauth_client_details t where t.id = #{id}\")\n    Client getById(Long id);\n\n    @Select(\"select * from oauth_client_details t where t.client_id = #{clientId}\")\n    Client getClient(String clientId);\n\n    @Update(\"update oauth_client_details t set t.client_secret = #{clientSecret}  where t.id = #{id}\")\n    int update(Client client);\n\n    @Select(\"select * from sys_role r inner join sys_role_user ru on r.id = ru.roleId where ru.userId = #{userId}\")\n    List<Client> listByUserId(Long userId);\n\n    @Delete(\"delete from sys_client_permission where clientId = #{clientId}\")\n    int deleteClientPermission(Long clientId);\n\n    int saveClientPermission(@Param(\"clientId\") Long clientId, @Param(\"permissionIds\") List<Long> permissionIds);\n\n    @Delete(\"delete from oauth_client_details where id = #{id}\")\n    int delete(Long id);\n\n    @Delete(\"delete from sys_role_user where roleId = #{clientId}\")\n    int deleteRoleUser(Long clientId);\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/dao/ClientDao.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.open.capacity.security.dao.ClientDao\">\n\n    <sql id=\"where\">\n        <where>\n            <if test=\"params.clientId!= null and params.clientId != ''\">\n                and client_id = #{params.clientId}\n            </if>\n            <if test=\"params.resourceIds != null and params.resourceIds != ''\">\n                and resource_ids = #{params.resourceIds}\n            </if>\n            <if test=\"params.clientSecret != null and params.clientSecret != ''\">\n                and client_secret = #{params.clientSecret}\n            </if>\n            <if test=\"params.scope != null and params.scope != ''\">\n                and scope = #{params.scope}\n            </if>\n            <if\n                    test=\"params.authorizedGrantTypes != null and params.authorizedGrantTypes != ''\">\n                and authorized_grant_types = #{params.authorizedGrantTypes}\n            </if>\n            <if\n                    test=\"params.webServerRedirectUri != null and params.webServerRedirectUri != ''\">\n                and web_server_redirect_uri = #{params.webServerRedirectUri}\n            </if>\n            <if test=\"params.authorities != null and params.authorities != ''\">\n                and authorities = #{params.authorities}\n            </if>\n            <if\n                    test=\"params.accessTokenValidity != null and params.accessTokenValidity != ''\">\n                and access_token_validity = #{params.accessTokenValidity}\n            </if>\n            <if\n                    test=\"params.refreshTokenValidity != null and params.refreshTokenValidity != ''\">\n                and refresh_token_validity = #{params.refreshTokenValidity}\n            </if>\n            <if\n                    test=\"params.additionalInformation != null and params.additionalInformation != ''\">\n                and additional_information = #{params.additionalInformation}\n            </if>\n            <if test=\"params.autoapprove != null and params.autoapprove != ''\">\n                and autoapprove = #{params.autoapprove}\n            </if>\n\n        </where>\n    </sql>\n\n    <select id=\"count\" resultType=\"int\">\n        select count(1) from oauth_client_details t\n        <include refid=\"where\"/>\n    </select>\n\n    <select id=\"list\" resultType=\"com.open.capacity.security.model.Client\">\n        select id id , client_id clientId , resource_ids resourceIds ,\n        client_secret clientSecret ,\n        web_server_redirect_uri\n        webServerRedirectUri from oauth_client_details t\n        <include refid=\"where\"/>\n        ${params.orderBy}\n        limit #{offset}, #{limit}\n    </select>\n\n\n    <insert id=\"saveClientPermission\">\n        insert into sys_client_permission(clientId, permissionId) values\n        <foreach collection=\"permissionIds\" item=\"permissionId\"\n                 separator=\",\">\n            (#{clientId}, #{permissionId})\n        </foreach>\n    </insert>\n\n</mapper>"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/dao/DictDao.java",
    "content": "package com.open.capacity.security.dao;\n\nimport com.open.capacity.security.model.Dict;\nimport org.apache.ibatis.annotations.*;\n\nimport java.util.List;\nimport java.util.Map;\n\n@Mapper\npublic interface DictDao {\n\n    @Select(\"select * from t_dict t where t.id = #{id}\")\n    Dict getById(Long id);\n\n    @Delete(\"delete from t_dict where id = #{id}\")\n    int delete(Long id);\n\n    int update(Dict dict);\n\n    @Options(useGeneratedKeys = true, keyProperty = \"id\")\n    @Insert(\"insert into t_dict(type, k, val, createTime, updateTime) values(#{type}, #{k}, #{val}, now(), now())\")\n    int save(Dict dict);\n\n    int count(@Param(\"params\") Map<String, Object> params);\n\n    List<Dict> list(@Param(\"params\") Map<String, Object> params, @Param(\"offset\") Integer offset,\n                    @Param(\"limit\") Integer limit);\n\n    @Select(\"select * from t_dict t where t.type = #{type} and k = #{k}\")\n    Dict getByTypeAndK(@Param(\"type\") String type, @Param(\"k\") String k);\n\n    @Select(\"select * from t_dict t where t.type = #{type}\")\n    List<Dict> listByType(String type);\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/dao/DictDaoxml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.open.capacity.security.dao.DictDao\">\n\n\t<sql id=\"where\">\n\t\t<where>\n\t\t\t<if test=\"params.id != null and params.id != ''\">\n\t\t\t\tand id = #{params.id}\n\t\t\t</if>\n\t\t\t<if test=\"params.type != null and params.type != ''\">\n\t\t\t\tand type = #{params.type}\n\t\t\t</if>\n\t\t\t<if test=\"params.k != null and params.k != ''\">\n\t\t\t\tand k = #{params.k}\n\t\t\t</if>\n\t\t\t<if test=\"params.val != null and params.val != ''\">\n\t\t\t\tand val = #{params.val}\n\t\t\t</if>\n\n\t\t</where>\n\t</sql>\n\n\t<select id=\"count\" resultType=\"int\">\n\t\tselect count(1) from t_dict t\n\t\t<include refid=\"where\" />\n\t</select>\n\n\t<select id=\"list\" resultType=\"com.open.capacity.security.model.Dict\">\n\t\tselect * from t_dict t\n\t\t<include refid=\"where\" />\n\t\t${params.orderBy}\n\t\tlimit #{offset}, #{limit}\n\t</select>\n\n\t<update id=\"update\">\n\t\tupdate t_dict t\n\t\t<set>\n\t\t\t<if test=\"type != null\">\n\t\t\t\ttype = #{type},\n\t\t\t</if>\n\t\t\t<if test=\"k != null\">\n\t\t\t\tk = #{k},\n\t\t\t</if>\n\t\t\t<if test=\"val != null\">\n\t\t\t\tval = #{val},\n\t\t\t</if>\n\t\t\tupdateTime = now()\n\n\t\t</set>\n\n\t\twhere t.id = #{id}\n\t</update>\n\n</mapper>\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/dao/FileDao.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.open.capacity.security.dao.FileInfoDao\">\n\n    <sql id=\"where\">\n        <where>\n        </where>\n    </sql>\n\n    <select id=\"count\" resultType=\"int\">\n        select count(1) from file_info t\n        <include refid=\"where\"/>\n    </select>\n\n    <select id=\"list\" resultType=\"com.open.capacity.security.model.FileInfo\">\n        select * from file_info t\n        <include refid=\"where\"/>\n        ${params.orderBy}\n        limit #{offset}, #{limit}\n    </select>\n\n</mapper>"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/dao/FileInfoDao.java",
    "content": "package com.open.capacity.security.dao;\n\nimport com.open.capacity.security.model.FileInfo;\nimport org.apache.ibatis.annotations.*;\n\nimport java.util.List;\nimport java.util.Map;\n\n@Mapper\npublic interface FileInfoDao {\n\n    @Select(\"select * from file_info t where t.id = #{id}\")\n    FileInfo getById(String id);\n\n    @Insert(\"insert into file_info(id, contentType, size, path, url, type, createTime, updateTime) values(#{id}, #{contentType}, #{size}, #{path}, #{url}, #{type}, now(), now())\")\n    int save(FileInfo fileInfo);\n\n    @Update(\"update file_info t set t.updateTime = now(),t.path=#{path},t.url=#{url} where t.id = #{id}\")\n    int update(FileInfo fileInfo);\n\n    @Delete(\"delete from file_info where id = #{id}\")\n    int delete(String id);\n\n    int count(@Param(\"params\") Map<String, Object> params);\n\n    List<FileInfo> list(@Param(\"params\") Map<String, Object> params, @Param(\"offset\") Integer offset,\n                        @Param(\"limit\") Integer limit);\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/dao/MailDao.java",
    "content": "package com.open.capacity.security.dao;\n\nimport com.open.capacity.security.model.Mail;\nimport com.open.capacity.security.model.MailTo;\nimport org.apache.ibatis.annotations.*;\n\nimport java.util.List;\nimport java.util.Map;\n\n@Mapper\npublic interface MailDao {\n\n    @Select(\"select * from t_mail t where t.id = #{id}\")\n    Mail getById(Long id);\n\n//\t@Delete(\"delete from t_mail where id = #{id}\")\n//\tint delete(Long id);\n\n//\t@Update(\"update t_mail t set subject = #{subject}, content = #{content}, updateTime = now() where t.id = #{id}\")\n//\tint update(Mail mail);\n\n    @Options(useGeneratedKeys = true, keyProperty = \"id\")\n    @Insert(\"insert into t_mail(userId, subject, content, createTime, updateTime) values(#{userId}, #{subject}, #{content}, now(), now())\")\n    int save(Mail mail);\n\n    @Insert(\"insert into t_mail_to(mailId, toUser, status) values(#{mailId}, #{toUser}, #{status})\")\n    int saveToUser(@Param(\"mailId\") Long mailId, @Param(\"toUser\") String toUser, @Param(\"status\") int status);\n\n    @Select(\"select t.* from t_mail_to t where t.mailId = #{mailId}\")\n    List<MailTo> getToUsers(Long mailId);\n\n    int count(@Param(\"params\") Map<String, Object> params);\n\n    List<Mail> list(@Param(\"params\") Map<String, Object> params, @Param(\"offset\") Integer offset,\n                    @Param(\"limit\") Integer limit);\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/dao/MailDao.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.open.capacity.security.dao.MailDao\">\n\n    <sql id=\"where\">\n        <where>\n            <if test=\"params.subject != null and params.subject != ''\">\n                and t.subject like concat('%', #{params.subject}, '%')\n            </if>\n            <if test=\"params.beginTime != null and params.beginTime != ''\">\n                and t.createTime &gt;= #{params.beginTime}\n            </if>\n\n            <if test=\"params.endTime != null and params.endTime != ''\">\n                and DATE(t.createTime) &lt;= #{params.endTime}\n            </if>\n        </where>\n    </sql>\n\n    <select id=\"count\" resultType=\"int\">\n        select count(1) from t_mail t\n        <include refid=\"where\"/>\n    </select>\n\n    <select id=\"list\" resultType=\"com.open.capacity.security.model.Mail\">\n        select * from t_mail t\n        <include refid=\"where\"/>\n        ${params.orderBy}\n        limit #{offset}, #{limit}\n    </select>\n\n</mapper>\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/dao/NoticeDao.java",
    "content": "package com.open.capacity.security.dao;\n\nimport com.open.capacity.security.dto.NoticeReadVO;\nimport com.open.capacity.security.model.Notice;\nimport com.open.capacity.security.model.SysUser;\nimport org.apache.ibatis.annotations.*;\n\nimport java.util.List;\nimport java.util.Map;\n\n@Mapper\npublic interface NoticeDao {\n\n    @Select(\"select * from t_notice t where t.id = #{id}\")\n    Notice getById(Long id);\n\n    @Delete(\"delete from t_notice where id = #{id}\")\n    int delete(Long id);\n\n    @Update(\"update t_notice t set title = #{title}, content = #{content}, status = #{status}, updateTime = #{updateTime} where t.id = #{id}\")\n    int update(Notice notice);\n\n    @Options(useGeneratedKeys = true, keyProperty = \"id\")\n    @Insert(\"insert into t_notice(title, content, status, createTime, updateTime) values(#{title}, #{content}, #{status}, #{createTime}, #{updateTime})\")\n    int save(Notice notice);\n\n    int count(@Param(\"params\") Map<String, Object> params);\n\n    List<Notice> list(@Param(\"params\") Map<String, Object> params, @Param(\"offset\") Integer offset,\n                      @Param(\"limit\") Integer limit);\n\n    @Insert(\"insert ignore into t_notice_read(noticeId, userId, createTime) values(#{noticeId}, #{userId}, now())\")\n    int saveReadRecord(@Param(\"noticeId\") Long noticeId, @Param(\"userId\") Long userId);\n\n    List<SysUser> listReadUsers(Long noticeId);\n\n    @Select(\"select count(1) from t_notice t left join t_notice_read r on r.noticeId = t.id and r.userId = #{userId} where t.status = 1 and r.userId is null\")\n    int countUnread(Long userId);\n\n    int countNotice(@Param(\"params\") Map<String, Object> params);\n\n    List<NoticeReadVO> listNotice(@Param(\"params\") Map<String, Object> params, @Param(\"offset\") Integer offset,\n                                  @Param(\"limit\") Integer limit);\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/dao/NoticeDao.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.open.capacity.security.dao.NoticeDao\">\n\n    <sql id=\"where\">\n        <where>\n            <if test=\"params.title != null and params.title != ''\">\n                and t.title like concat('%', #{params.title}, '%')\n            </if>\n            <if test=\"params.status != null and params.status != ''\">\n                and t.status = #{params.status}\n            </if>\n            <if test=\"params.beginTime != null and params.beginTime != ''\">\n                and t.updateTime &gt;= #{params.beginTime}\n            </if>\n\n            <if test=\"params.endTime != null and params.endTime != ''\">\n                and DATE(t.updateTime) &lt;= #{params.endTime}\n            </if>\n        </where>\n    </sql>\n\n    <select id=\"count\" resultType=\"int\">\n        select count(1) from t_notice t\n        <include refid=\"where\"/>\n    </select>\n\n    <select id=\"list\" resultType=\"com.open.capacity.security.model.Notice\">\n        select * from t_notice t\n        <include refid=\"where\"/>\n        ${params.orderBy}\n        limit #{offset}, #{limit}\n    </select>\n\n    <select id=\"listReadUsers\" resultType=\"com.open.capacity.security.model.SysUser\">\n\t\tselect u.* from\n\t\tt_notice_read r inner join sys_user u\n\t\ton u.id = r.userId\n\t\twhere\n\t\tr.noticeId = #{noticeId}\n\t\torder by r.createTime desc\n\t</select>\n\n    <sql id=\"whereNotice\">\n        <where>\n            t.status = 1\n            <if test=\"params.title != null and params.title != ''\">\n                and t.title like concat('%', #{params.title}, '%')\n            </if>\n\n            <if test=\"params.beginTime != null and params.beginTime != ''\">\n                and t.updateTime &gt;= #{params.beginTime}\n            </if>\n\n            <if test=\"params.endTime != null and params.endTime != ''\">\n                and DATE(t.updateTime) &lt;= #{params.endTime}\n            </if>\n            <if test=\"params.isRead != null and params.isRead != ''\">\n                <if test=\"params.isRead == 0\">\n                    and r.createTime is null\n                </if>\n                <if test=\"params.isRead == 1\">\n                    and r.createTime is not null\n                </if>\n            </if>\n        </where>\n    </sql>\n\n    <select id=\"countNotice\" resultType=\"int\">\n        select count(1) from t_notice t left join\n        t_notice_read r on\n        r.noticeId = t.id and r.userId = #{params.userId}\n        <include refid=\"whereNotice\"/>\n    </select>\n\n    <select id=\"listNotice\" resultType=\"com.open.capacity.security.dto.NoticeReadVO\">\n        select t.*,r.createTime readTime,\n        if(r.createTime is null, 0, 1) isRead,r.userId\n        from t_notice t left join\n        t_notice_read r on r.noticeId = t.id and r.userId = #{params.userId}\n        <include refid=\"whereNotice\"/>\n        ${params.orderBy}\n        limit #{offset}, #{limit}\n    </select>\n</mapper>"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/dao/PermissionDao.java",
    "content": "package com.open.capacity.security.dao;\n\nimport com.open.capacity.security.model.Permission;\nimport org.apache.ibatis.annotations.*;\n\nimport java.util.List;\nimport java.util.Set;\n\n@Mapper\npublic interface PermissionDao {\n\n    @Select(\"select * from sys_permission t order by t.sort\")\n    List<Permission> listAll();\n\n    @Select(\"select * from sys_permission t where t.type = 1 order by t.sort\")\n    List<Permission> listParents();\n\n    @Select(\"select distinct p.* from sys_permission p inner join sys_role_permission rp on p.id = rp.permissionId inner join sys_role_user ru on ru.roleId = rp.roleId where ru.userId = #{userId} order by p.sort\")\n    List<Permission> listByUserId(Long userId);\n\n    @Select(\"select p.* from sys_permission p inner join sys_role_permission rp on p.id = rp.permissionId where rp.roleId = #{roleId} order by p.sort\")\n    List<Permission> listByRoleId(Long roleId);\n\n    @Select(\"select * from sys_permission t where t.id = #{id}\")\n    Permission getById(Long id);\n\n    @Insert(\"insert into sys_permission(parentId, name, css, href, type, permission, sort) values(#{parentId}, #{name}, #{css}, #{href}, #{type}, #{permission}, #{sort})\")\n    int save(Permission permission);\n\n    @Update(\"update sys_permission t set parentId = #{parentId}, name = #{name}, css = #{css}, href = #{href}, type = #{type}, permission = #{permission}, sort = #{sort} where t.id = #{id}\")\n    int update(Permission permission);\n\n    @Delete(\"delete from sys_permission where id = #{id}\")\n    int delete(Long id);\n\n    @Delete(\"delete from sys_permission where parentId = #{id}\")\n    int deleteByParentId(Long id);\n\n    @Delete(\"delete from sys_role_permission where permissionId = #{permissionId}\")\n    int deleteRolePermission(Long permissionId);\n\n    @Select(\"select ru.userId from sys_role_permission rp inner join sys_role_user ru on ru.roleId = rp.roleId where rp.permissionId = #{permissionId}\")\n    Set<Long> listUserIds(Long permissionId);\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/dao/RoleDao.java",
    "content": "package com.open.capacity.security.dao;\n\nimport com.open.capacity.security.model.Role;\nimport org.apache.ibatis.annotations.*;\n\nimport java.util.List;\nimport java.util.Map;\n\n@Mapper\npublic interface RoleDao {\n\n    @Options(useGeneratedKeys = true, keyProperty = \"id\")\n    @Insert(\"insert into sys_role(name, description, createTime, updateTime) values(#{name}, #{description}, now(),now())\")\n    int save(Role role);\n\n    int count(@Param(\"params\") Map<String, Object> params);\n\n    List<Role> list(@Param(\"params\") Map<String, Object> params, @Param(\"offset\") Integer offset,\n                    @Param(\"limit\") Integer limit);\n\n    @Select(\"select * from sys_role t where t.id = #{id}\")\n    Role getById(Long id);\n\n    @Select(\"select * from sys_role t where t.name = #{name}\")\n    Role getRole(String name);\n\n    @Update(\"update sys_role t set t.name = #{name}, t.description = #{description}, updateTime = now() where t.id = #{id}\")\n    int update(Role role);\n\n    @Select(\"select * from sys_role r inner join sys_role_user ru on r.id = ru.roleId where ru.userId = #{userId}\")\n    List<Role> listByUserId(Long userId);\n\n    @Delete(\"delete from sys_role_permission where roleId = #{roleId}\")\n    int deleteRolePermission(Long roleId);\n\n    int saveRolePermission(@Param(\"roleId\") Long roleId, @Param(\"permissionIds\") List<Long> permissionIds);\n\n    @Delete(\"delete from sys_role where id = #{id}\")\n    int delete(Long id);\n\n    @Delete(\"delete from sys_role_user where roleId = #{roleId}\")\n    int deleteRoleUser(Long roleId);\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/dao/RoleDao.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.open.capacity.security.dao.RoleDao\">\n\n    <sql id=\"where\">\n        <where>\n            <if test=\"params.name != null and params.name != ''\">\n                and t.name like concat('%', #{params.name}, '%')\n            </if>\n        </where>\n    </sql>\n\n    <select id=\"count\" resultType=\"int\">\n        select count(1) from sys_role t\n        <include refid=\"where\"/>\n    </select>\n\n    <select id=\"list\" resultType=\"com.open.capacity.security.model.Role\">\n        select * from sys_role t\n        <include refid=\"where\"/>\n        ${params.orderBy}\n        <if test=\"offset != null and offset >= 0 and limit != null and limit >= 0\">\n            limit #{offset}, #{limit}\n        </if>\n    </select>\n\n    <insert id=\"saveRolePermission\">\n        insert into sys_role_permission(roleId, permissionId) values\n        <foreach collection=\"permissionIds\" item=\"permissionId\"\n                 separator=\",\">\n            (#{roleId}, #{permissionId})\n        </foreach>\n    </insert>\n\n</mapper>"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/dao/ServiceDao.java",
    "content": "package com.open.capacity.security.dao;\n\nimport com.open.capacity.security.model.Permission;\nimport org.apache.ibatis.annotations.*;\n\nimport java.util.List;\nimport java.util.Set;\n\n@Mapper\npublic interface ServiceDao {\n\n    @Select(\"select * from sys_services t order by t.sort\")\n    List<Permission> listAll();\n\n    @Select(\"select * from sys_services t where t.type = 1 order by t.sort\")\n    List<Permission> listParents();\n\n    @Select(\"select distinct p.* from sys_services p inner join sys_client_permission rp on p.id = rp.permissionId inner join sys_role_user ru on ru.roleId = rp.roleId where ru.userId = #{userId} order by p.sort\")\n    List<Permission> listByUserId(Long userId);\n\n    @Select(\"select p.* from sys_services p inner join sys_client_permission rp on p.id = rp.permissionId where rp.clientId = #{clientId} order by p.sort\")\n    List<Permission> listByClientId(Long clientId);\n\n    @Select(\"select * from sys_services t where t.id = #{id}\")\n    Permission getById(Long id);\n\n    @Insert(\"insert into sys_services(parentId, name, css, href, type, permission, sort) values(#{parentId}, #{name}, #{css}, #{href}, #{type}, #{permission}, #{sort})\")\n    int save(Permission permission);\n\n    @Update(\"update sys_services t set parentId = #{parentId}, name = #{name}, css = #{css}, href = #{href}, type = #{type}, permission = #{permission}, sort = #{sort} where t.id = #{id}\")\n    int update(Permission permission);\n\n    @Delete(\"delete from sys_services where id = #{id}\")\n    int delete(Long id);\n\n    @Delete(\"delete from sys_services where parentId = #{id}\")\n    int deleteByParentId(Long id);\n\n    @Select(\"select ru.userId from sys_role_permission rp inner join sys_role_user ru on ru.roleId = rp.roleId where rp.permissionId = #{permissionId}\")\n    Set<Long> listUserIds(Long permissionId);\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/dao/SysLogsDao.java",
    "content": "package com.open.capacity.security.dao;\n\nimport com.open.capacity.security.model.SysLogs;\nimport org.apache.ibatis.annotations.Delete;\nimport org.apache.ibatis.annotations.Insert;\nimport org.apache.ibatis.annotations.Mapper;\nimport org.apache.ibatis.annotations.Param;\n\nimport java.util.List;\nimport java.util.Map;\n\n@Mapper\npublic interface SysLogsDao {\n\n    @Insert(\"insert into sys_logs(userId, module, flag, remark, createTime) values(#{user.id}, #{module}, #{flag}, #{remark}, now())\")\n    int save(SysLogs sysLogs);\n\n    int count(@Param(\"params\") Map<String, Object> params);\n\n    List<SysLogs> list(@Param(\"params\") Map<String, Object> params, @Param(\"offset\") Integer offset,\n                       @Param(\"limit\") Integer limit);\n\n    @Delete(\"delete from sys_logs where createTime <= #{time}\")\n    int deleteLogs(String time);\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/dao/SysLogsDao.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.open.capacity.security.dao.SysLogsDao\">\n\n    <resultMap id=\"BaseResultMap\" type=\"com.open.capacity.security.model.SysLogs\">\n        <id column=\"id\" property=\"id\"/>\n        <result column=\"module\" property=\"module\"/>\n        <result column=\"remark\" property=\"remark\"/>\n        <result column=\"flag\" property=\"flag\"/>\n        <result column=\"createTime\" property=\"createTime\"/>\n        <association property=\"user\" javaType=\"com.open.capacity.security.model.SysUser\">\n            <result property=\"id\" column=\"userId\"/>\n            <result property=\"username\" column=\"username\"/>\n            <result property=\"nickname\" column=\"nickname\"/>\n        </association>\n    </resultMap>\n\n    <sql id=\"where\">\n        <where>\n            <if test=\"params.flag != null and params.flag != ''\">\n                and t.flag = #{params.flag}\n            </if>\n            <if test=\"params.nickname != null and params.nickname != ''\">\n                and u.nickname like concat('%', #{params.nickname}, '%')\n            </if>\n            <if test=\"params.beginTime != null and params.beginTime != ''\">\n                and t.createTime &gt;= #{params.beginTime}\n            </if>\n            <if test=\"params.endTime != null and params.endTime != ''\">\n                and DATE(t.createTime) &lt;= #{params.endTime}\n            </if>\n        </where>\n    </sql>\n\n    <select id=\"count\" resultType=\"int\">\n        select count(1) from sys_logs t left join sys_user\n        u on\n        u.id = t.userId\n        <include refid=\"where\"/>\n    </select>\n\n    <select id=\"list\" resultMap=\"BaseResultMap\">\n        select t.*, u.username, u.nickname from sys_logs t left join sys_user\n        u on\n        u.id = t.userId\n        <include refid=\"where\"/>\n        ${params.orderBy}\n        limit #{offset}, #{limit}\n    </select>\n\n</mapper>\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/dao/TokenDao.java",
    "content": "package com.open.capacity.security.dao;\n\nimport com.open.capacity.security.model.TokenModel;\nimport org.apache.ibatis.annotations.*;\n\n@Mapper\npublic interface TokenDao {\n\n    @Insert(\"insert into t_token(id, val, expireTime, createTime, updateTime) values (#{id}, #{val}, #{expireTime}, #{createTime}, #{updateTime})\")\n    int save(TokenModel model);\n\n    @Select(\"select * from t_token t where t.id = #{id}\")\n    TokenModel getById(String id);\n\n    @Update(\"update t_token t set t.val = #{val}, t.expireTime = #{expireTime}, t.updateTime = #{updateTime} where t.id = #{id}\")\n    int update(TokenModel model);\n\n    @Delete(\"delete from t_token where id = #{id}\")\n    int delete(String id);\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/dao/UserDao.java",
    "content": "package com.open.capacity.security.dao;\n\nimport com.open.capacity.security.model.SysUser;\nimport org.apache.ibatis.annotations.*;\n\nimport java.util.List;\nimport java.util.Map;\n\n@Mapper\npublic interface UserDao {\n\n    @Options(useGeneratedKeys = true, keyProperty = \"id\")\n    @Insert(\"insert into sys_user(username, password, nickname, headImgUrl, phone, telephone, email, birthday, sex, status, createTime, updateTime) values(#{username}, #{password}, #{nickname}, #{headImgUrl}, #{phone}, #{telephone}, #{email}, #{birthday}, #{sex}, #{status}, now(), now())\")\n    int save(SysUser user);\n\n    @Select(\"select * from sys_user t where t.id = #{id}\")\n    SysUser getById(Long id);\n\n    @Select(\"select * from sys_user t where t.username = #{username}\")\n    SysUser getUser(String username);\n\n    @Update(\"update sys_user t set t.password = #{password} where t.id = #{id}\")\n    int changePassword(@Param(\"id\") Long id, @Param(\"password\") String password);\n\n    Integer count(@Param(\"params\") Map<String, Object> params);\n\n    List<SysUser> list(@Param(\"params\") Map<String, Object> params, @Param(\"offset\") Integer offset,\n                       @Param(\"limit\") Integer limit);\n\n    @Delete(\"delete from sys_role_user where userId = #{userId}\")\n    int deleteUserRole(Long userId);\n\n    int saveUserRoles(@Param(\"userId\") Long userId, @Param(\"roleIds\") List<Long> roleIds);\n\n    int update(SysUser user);\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/dao/UserDao.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.open.capacity.security.dao.UserDao\">\n\n    <sql id=\"where\">\n        <where>\n            <if test=\"params.username != null and params.username != ''\">\n                and t.username like concat('%', #{params.username}, '%')\n            </if>\n            <if test=\"params.nickname != null and params.nickname != ''\">\n                and t.nickname like concat('%', #{params.nickname}, '%')\n            </if>\n            <if test=\"params.status != null and params.status != ''\">\n                and t.status = #{params.status}\n            </if>\n        </where>\n    </sql>\n\n    <select id=\"count\" resultType=\"int\">\n        select count(1) from sys_user t\n        <include refid=\"where\"/>\n    </select>\n\n    <select id=\"list\" resultType=\"com.open.capacity.security.model.SysUser\">\n        select * from sys_user t\n        <include refid=\"where\"/>\n        ${params.orderBy}\n        limit #{offset}, #{limit}\n    </select>\n\n    <insert id=\"saveUserRoles\">\n        insert into sys_role_user(roleId, userId) values\n        <foreach collection=\"roleIds\" item=\"roleId\" separator=\",\">\n            (#{roleId}, #{userId})\n        </foreach>\n    </insert>\n\n    <update id=\"update\">\n        update sys_user t\n        <set>\n            <if test=\"username != null\">\n                username = #{username},\n            </if>\n            <if test=\"nickname != null\">\n                nickname = #{nickname},\n            </if>\n            <if test=\"headImgUrl != null\">\n                headImgUrl = #{headImgUrl},\n            </if>\n            <if test=\"phone != null\">\n                phone = #{phone},\n            </if>\n            <if test=\"telephone != null\">\n                telephone = #{telephone},\n            </if>\n            <if test=\"email != null\">\n                email = #{email},\n            </if>\n            <if test=\"birthday != null\">\n                birthday = #{birthday},\n            </if>\n            <if test=\"sex != null\">\n                sex = #{sex},\n            </if>\n            <if test=\"status != null\">\n                status = #{status},\n            </if>\n            updateTime = #{updateTime}\n        </set>\n        where t.id = #{id}\n    </update>\n</mapper>"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/dto/BeanField.java",
    "content": "package com.open.capacity.security.dto;\n\nimport java.io.Serializable;\n\npublic class BeanField implements Serializable {\n\n    private static final long serialVersionUID = 4279960350136806659L;\n\n    private String columnName;\n\n    private String columnType;\n\n    private String columnComment;\n\n    private String columnDefault;\n\n    private String name;\n\n    private String type;\n\n    public String getColumnName() {\n        return columnName;\n    }\n\n    public void setColumnName(String columnName) {\n        this.columnName = columnName;\n    }\n\n    public String getColumnType() {\n        return columnType;\n    }\n\n    public void setColumnType(String columnType) {\n        this.columnType = columnType;\n    }\n\n    public String getColumnComment() {\n        return columnComment;\n    }\n\n    public void setColumnComment(String columnComment) {\n        this.columnComment = columnComment;\n    }\n\n    public String getColumnDefault() {\n        return columnDefault;\n    }\n\n    public void setColumnDefault(String columnDefault) {\n        this.columnDefault = columnDefault;\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 String getType() {\n        return type;\n    }\n\n    public void setType(String type) {\n        this.type = type;\n    }\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/dto/ClientDto.java",
    "content": "package com.open.capacity.security.dto;\n\nimport com.open.capacity.security.model.Client;\n\nimport java.util.List;\n\npublic class ClientDto extends Client {\n\n    private static final long serialVersionUID = 1475637288060027265L;\n\n    private List<Long> permissionIds;\n\n    public List<Long> getPermissionIds() {\n        return permissionIds;\n    }\n\n    public void setPermissionIds(List<Long> permissionIds) {\n        this.permissionIds = permissionIds;\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/dto/GenerateDetail.java",
    "content": "package com.open.capacity.security.dto;\n\nimport java.io.Serializable;\nimport java.util.List;\n\npublic class GenerateDetail implements Serializable {\n\n    private static final long serialVersionUID = -164567294469931676L;\n\n    private String beanName;\n\n    private List<BeanField> fields;\n\n    public String getBeanName() {\n        return beanName;\n    }\n\n    public void setBeanName(String beanName) {\n        this.beanName = beanName;\n    }\n\n    public List<BeanField> getFields() {\n        return fields;\n    }\n\n    public void setFields(List<BeanField> fields) {\n        this.fields = fields;\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/dto/GenerateInput.java",
    "content": "package com.open.capacity.security.dto;\n\nimport java.io.Serializable;\nimport java.util.List;\n\npublic class GenerateInput implements Serializable {\n\n    private static final long serialVersionUID = -2870071259702969061L;\n\n    /**\n     * 保存路径\n     */\n    private String path;\n\n    private String tableName;\n\n    /**\n     * bean包名\n     */\n    private String beanPackageName;\n\n    /**\n     * java类名\n     */\n    private String beanName;\n    /**\n     * dao包名\n     */\n    private String daoPackageName;\n\n    /**\n     * dao类名\n     */\n    private String daoName;\n    /**\n     * controller包名\n     */\n    private String controllerPkgName;\n    /**\n     * controller类名\n     */\n    private String controllerName;\n    /**\n     * 字段名\n     */\n    private List<String> columnNames;\n    /**\n     * 属性名\n     */\n    private List<String> beanFieldName;\n    /**\n     * 成员变量类型\n     */\n    private List<String> beanFieldType;\n    /**\n     * 默认值\n     */\n    private List<String> beanFieldValue;\n\n    public String getPath() {\n        return path;\n    }\n\n    public void setPath(String path) {\n        this.path = path;\n    }\n\n    public String getTableName() {\n        return tableName;\n    }\n\n    public void setTableName(String tableName) {\n        this.tableName = tableName;\n    }\n\n    public String getBeanPackageName() {\n        return beanPackageName;\n    }\n\n    public void setBeanPackageName(String beanPackageName) {\n        this.beanPackageName = beanPackageName;\n    }\n\n    public String getBeanName() {\n        return beanName;\n    }\n\n    public void setBeanName(String beanName) {\n        this.beanName = beanName;\n    }\n\n    public String getDaoPackageName() {\n        return daoPackageName;\n    }\n\n    public void setDaoPackageName(String daoPackageName) {\n        this.daoPackageName = daoPackageName;\n    }\n\n    public String getDaoName() {\n        return daoName;\n    }\n\n    public void setDaoName(String daoName) {\n        this.daoName = daoName;\n    }\n\n    public String getControllerPkgName() {\n        return controllerPkgName;\n    }\n\n    public void setControllerPkgName(String controllerPkgName) {\n        this.controllerPkgName = controllerPkgName;\n    }\n\n    public String getControllerName() {\n        return controllerName;\n    }\n\n    public void setControllerName(String controllerName) {\n        this.controllerName = controllerName;\n    }\n\n    public List<String> getColumnNames() {\n        return columnNames;\n    }\n\n    public void setColumnNames(List<String> columnNames) {\n        this.columnNames = columnNames;\n    }\n\n    public List<String> getBeanFieldName() {\n        return beanFieldName;\n    }\n\n    public void setBeanFieldName(List<String> beanFieldName) {\n        this.beanFieldName = beanFieldName;\n    }\n\n    public List<String> getBeanFieldType() {\n        return beanFieldType;\n    }\n\n    public void setBeanFieldType(List<String> beanFieldType) {\n        this.beanFieldType = beanFieldType;\n    }\n\n    public List<String> getBeanFieldValue() {\n        return beanFieldValue;\n    }\n\n    public void setBeanFieldValue(List<String> beanFieldValue) {\n        this.beanFieldValue = beanFieldValue;\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/dto/LayuiFile.java",
    "content": "package com.open.capacity.security.dto;\n\nimport java.io.Serializable;\n\npublic class LayuiFile implements Serializable {\n\n    private static final long serialVersionUID = 35435494737590569L;\n\n    private Integer code;\n    private String msg;\n    private LayuiFileData data;\n\n    public Integer getCode() {\n        return code;\n    }\n\n    public void setCode(Integer code) {\n        this.code = code;\n    }\n\n    public String getMsg() {\n        return msg;\n    }\n\n    public void setMsg(String msg) {\n        this.msg = msg;\n    }\n\n    public LayuiFileData getData() {\n        return data;\n    }\n\n    public void setData(LayuiFileData data) {\n        this.data = data;\n    }\n\n    public static class LayuiFileData implements Serializable {\n\n        private static final long serialVersionUID = 7907356434695924597L;\n        private String src;\n        private String title;\n\n        public String getSrc() {\n            return src;\n        }\n\n        public void setSrc(String src) {\n            this.src = src;\n        }\n\n        public String getTitle() {\n            return title;\n        }\n\n        public void setTitle(String title) {\n            this.title = title;\n        }\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/dto/LoginUser.java",
    "content": "package com.open.capacity.security.dto;\n\nimport com.fasterxml.jackson.annotation.JsonIgnore;\nimport com.open.capacity.security.model.Permission;\nimport com.open.capacity.security.model.SysUser;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.security.core.GrantedAuthority;\nimport org.springframework.security.core.authority.SimpleGrantedAuthority;\nimport org.springframework.security.core.userdetails.UserDetails;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Iterator;\nimport java.util.List;\n\npublic class LoginUser extends SysUser implements UserDetails {\n\n    private static final long serialVersionUID = -1379274258881257107L;\n\n    private List<Permission> permissions;\n\n    private String jwtToken;\n\n\n    private String token;\n    /**\n     * 登陆时间戳（毫秒）\n     */\n    private Long loginTime;\n    /**\n     * 过期时间戳\n     */\n    private Long expireTime;\n\n    public List<Permission> getPermissions() {\n        return permissions;\n    }\n\n    public void setPermissions(List<Permission> permissions) {\n        this.permissions = permissions;\n    }\n\n    public String getToken() {\n        return token;\n    }\n\n    public void setToken(String token) {\n        this.token = token;\n    }\n\n    @Override\n    @JsonIgnore\n    public Collection<? extends GrantedAuthority> getAuthorities() {\n\n        List<GrantedAuthority> auths = new ArrayList<GrantedAuthority>();\n\n        for (Iterator<Permission> it = permissions.iterator(); it.hasNext(); ) {\n            Permission p = it.next();\n\n\n            if (!StringUtils.isEmpty(p.getPermission())) {\n                auths.add(new SimpleGrantedAuthority(p.getPermission()));\n            }\n        }\n\n        return auths;\n\n//\t\treturn permissions.parallelStream().filter(p -> !StringUtils.isEmpty(p.getPermission()))\n//\t\t\t\t.map(p -> new SimpleGrantedAuthority(p.getPermission())).collect(Collectors.toSet());\n    }\n\n    public void setAuthorities(Collection<? extends GrantedAuthority> authorities) {\n        // do nothing\n    }\n\n    // 账户是否未过期\n    @JsonIgnore\n    @Override\n    public boolean isAccountNonExpired() {\n        return true;\n    }\n\n    // 账户是否未锁定\n    @JsonIgnore\n    @Override\n    public boolean isAccountNonLocked() {\n        return getStatus() != Status.LOCKED;\n    }\n\n    // 密码是否未过期\n    @JsonIgnore\n    @Override\n    public boolean isCredentialsNonExpired() {\n        return true;\n    }\n\n    // 账户是否激活\n    @JsonIgnore\n    @Override\n    public boolean isEnabled() {\n        return true;\n    }\n\n    public Long getLoginTime() {\n        return loginTime;\n    }\n\n    public void setLoginTime(Long loginTime) {\n        this.loginTime = loginTime;\n    }\n\n    public Long getExpireTime() {\n        return expireTime;\n    }\n\n    public void setExpireTime(Long expireTime) {\n        this.expireTime = expireTime;\n    }\n\n    @JsonIgnore\n    public String getJwtToken() {\n        return jwtToken;\n    }\n\n    public void setJwtToken(String jwtToken) {\n        this.jwtToken = jwtToken;\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/dto/NoticeReadVO.java",
    "content": "package com.open.capacity.security.dto;\n\nimport com.open.capacity.security.model.Notice;\n\nimport java.util.Date;\n\npublic class NoticeReadVO extends Notice {\n\n    private static final long serialVersionUID = -3842182350180882396L;\n\n    private Long userId;\n    private Date readTime;\n    private Boolean isRead;\n\n    public Long getUserId() {\n        return userId;\n    }\n\n    public void setUserId(Long userId) {\n        this.userId = userId;\n    }\n\n    public Date getReadTime() {\n        return readTime;\n    }\n\n    public void setReadTime(Date readTime) {\n        this.readTime = readTime;\n    }\n\n    public Boolean getIsRead() {\n        return isRead;\n    }\n\n    public void setIsRead(Boolean isRead) {\n        this.isRead = isRead;\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/dto/NoticeVO.java",
    "content": "package com.open.capacity.security.dto;\n\nimport com.open.capacity.security.model.Notice;\nimport com.open.capacity.security.model.SysUser;\n\nimport java.io.Serializable;\nimport java.util.List;\n\npublic class NoticeVO implements Serializable {\n\n    private static final long serialVersionUID = 7363353918096951799L;\n\n    private Notice notice;\n\n    private List<SysUser> users;\n\n    public Notice getNotice() {\n        return notice;\n    }\n\n    public void setNotice(Notice notice) {\n        this.notice = notice;\n    }\n\n    public List<SysUser> getUsers() {\n        return users;\n    }\n\n    public void setUsers(List<SysUser> users) {\n        this.users = users;\n    }\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/dto/ResponseInfo.java",
    "content": "package com.open.capacity.security.dto;\n\nimport java.io.Serializable;\n\npublic class ResponseInfo implements Serializable {\n\n    private static final long serialVersionUID = -4417715614021482064L;\n\n    private String code;\n    private String message;\n\n    public ResponseInfo(String code, String message) {\n        super();\n        this.code = code;\n        this.message = message;\n    }\n\n    public String getCode() {\n        return code;\n    }\n\n    public void setCode(String code) {\n        this.code = code;\n    }\n\n    public String getMessage() {\n        return message;\n    }\n\n    public void setMessage(String message) {\n        this.message = message;\n    }\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/dto/RoleDto.java",
    "content": "package com.open.capacity.security.dto;\n\nimport com.open.capacity.security.model.Role;\n\nimport java.util.List;\n\npublic class RoleDto extends Role {\n\n    private static final long serialVersionUID = 4218495592167610193L;\n\n    private List<Long> permissionIds;\n\n    public List<Long> getPermissionIds() {\n        return permissionIds;\n    }\n\n    public void setPermissionIds(List<Long> permissionIds) {\n        this.permissionIds = permissionIds;\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/dto/Token.java",
    "content": "package com.open.capacity.security.dto;\n\nimport java.io.Serializable;\n\n/**\n * Restful方式登陆token\n *\n * @author owen 624191343@qq.com\n * <p>\n * 2017年8月4日\n */\npublic class Token implements Serializable {\n\n    private static final long serialVersionUID = 6314027741784310221L;\n\n    private String token;\n    /**\n     * 登陆时间戳（毫秒）\n     */\n    private Long loginTime;\n\n    public Token(String token, Long loginTime) {\n        super();\n        this.token = token;\n        this.loginTime = loginTime;\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 Long getLoginTime() {\n        return loginTime;\n    }\n\n    public void setLoginTime(Long loginTime) {\n        this.loginTime = loginTime;\n    }\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/dto/UserDto.java",
    "content": "package com.open.capacity.security.dto;\n\nimport com.open.capacity.security.model.SysUser;\n\nimport java.util.List;\n\npublic class UserDto extends SysUser {\n\n    private static final long serialVersionUID = -184009306207076712L;\n\n    private List<Long> roleIds;\n\n    public List<Long> getRoleIds() {\n        return roleIds;\n    }\n\n    public void setRoleIds(List<Long> roleIds) {\n        this.roleIds = roleIds;\n    }\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/filter/TokenFilter.java",
    "content": "package com.open.capacity.security.filter;\n\nimport com.open.capacity.security.dto.LoginUser;\nimport com.open.capacity.security.service.TokenService;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.security.authentication.UsernamePasswordAuthenticationToken;\nimport org.springframework.security.core.context.SecurityContextHolder;\nimport org.springframework.security.core.userdetails.UserDetailsService;\nimport org.springframework.web.filter.OncePerRequestFilter;\n\nimport javax.servlet.FilterChain;\nimport javax.servlet.ServletException;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport java.io.IOException;\n\n/**\n * Token过滤器\n *\n * @author owen 624191343@qq.com\n * <p>\n * 2017年10月14日\n */\npublic class TokenFilter extends OncePerRequestFilter {\n\n    private static final String TOKEN_KEY = \"access_token\";\n    private static final Long MINUTES_10 = 10 * 60 * 1000L;\n    private TokenService tokenService;\n    private UserDetailsService userDetailsService;\n\n    /**\n     * 根据参数或者header获取token\n     *\n     * @param request\n     * @return\n     */\n    public static String getToken(HttpServletRequest request) {\n        String token = request.getParameter(TOKEN_KEY);\n        if (StringUtils.isBlank(token)) {\n            token = request.getHeader(TOKEN_KEY);\n        }\n\n        return token;\n    }\n\n    public TokenService getTokenService() {\n        return tokenService;\n    }\n\n    public void setTokenService(TokenService tokenService) {\n        this.tokenService = tokenService;\n    }\n\n    public UserDetailsService getUserDetailsService() {\n        return userDetailsService;\n    }\n\n    public void setUserDetailsService(UserDetailsService userDetailsService) {\n        this.userDetailsService = userDetailsService;\n    }\n\n    @Override\n    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)\n            throws ServletException, IOException {\n        String token = getToken(request);\n        if (StringUtils.isNotBlank(token)) {\n            LoginUser loginUser = tokenService.getLoginUser(token);\n            if (loginUser != null) {\n                loginUser = checkLoginTime(loginUser);\n                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(loginUser,\n                        null, loginUser.getAuthorities());\n                SecurityContextHolder.getContext().setAuthentication(authentication);\n            }\n        }\n\n        filterChain.doFilter(request, response);\n    }\n\n    /**\n     * 校验时间<br>\n     * 过期时间与当前时间对比，临近过期10分钟内的话，自动刷新缓存\n     *\n     * @param loginUser\n     * @return\n     */\n    private LoginUser checkLoginTime(LoginUser loginUser) {\n        long expireTime = loginUser.getExpireTime();\n        long currentTime = System.currentTimeMillis();\n        if (expireTime - currentTime <= MINUTES_10) {\n            String token = loginUser.getToken();\n            loginUser = (LoginUser) userDetailsService.loadUserByUsername(loginUser.getUsername());\n            loginUser.setToken(token);\n            tokenService.refresh(loginUser);\n        }\n        return loginUser;\n    }\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/model/BaseEntity.java",
    "content": "package com.open.capacity.security.model;\n\nimport java.io.Serializable;\nimport java.util.Date;\n\npublic abstract class BaseEntity<ID extends Serializable> implements Serializable {\n\n    private static final long serialVersionUID = 2054813493011812469L;\n\n    private ID id;\n    private Date createTime = new Date();\n    private Date updateTime = new Date();\n\n    public ID getId() {\n        return id;\n    }\n\n    public void setId(ID id) {\n        this.id = id;\n    }\n\n    public Date getCreateTime() {\n        return createTime;\n    }\n\n    public void setCreateTime(Date createTime) {\n        this.createTime = createTime;\n    }\n\n    public Date getUpdateTime() {\n        return updateTime;\n    }\n\n    public void setUpdateTime(Date updateTime) {\n        this.updateTime = updateTime;\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/model/Client.java",
    "content": "package com.open.capacity.security.model;\n\n\npublic class Client extends BaseEntity<Long> {\n\n    /**\n     *\n     */\n    private static final long serialVersionUID = -8185413579135897885L;\n    private Long id;\n    private String clientId;\n    private String resourceIds = \"\";\n    private String clientSecret;\n    private String scope = \"all\";\n    private String authorizedGrantTypes = \"authorization_code,password,refresh_token,client_credentials\";\n    private String webServerRedirectUri;\n    private String authorities = \"\";\n    private Integer accessTokenValidity = 18000;\n    private Integer refreshTokenValidity = 18000;\n    private String additionalInformation = \"{}\";\n    private String autoapprove = \"true\";\n\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 getClientId() {\n        return clientId;\n    }\n\n    public String setClientId() {\n        return clientId;\n    }\n\n    public String getResourceIds() {\n        return resourceIds;\n    }\n\n    public String setResourceIds() {\n        return resourceIds;\n    }\n\n    public String getClientSecret() {\n        return clientSecret;\n    }\n\n    public String setClientSecret() {\n        return clientSecret;\n    }\n\n    public String getScope() {\n        return scope;\n    }\n\n    public String setScope() {\n        return scope;\n    }\n\n    public String getAuthorizedGrantTypes() {\n        return authorizedGrantTypes;\n    }\n\n    public String setAuthorizedGrantTypes() {\n        return authorizedGrantTypes;\n    }\n\n    public String getWebServerRedirectUri() {\n        return webServerRedirectUri;\n    }\n\n    public String setWebServerRedirectUri() {\n        return webServerRedirectUri;\n    }\n\n    public String getAuthorities() {\n        return authorities;\n    }\n\n    public String setAuthorities() {\n        return authorities;\n    }\n\n    public Integer getAccessTokenValidity() {\n        return accessTokenValidity;\n    }\n\n    public Integer setAccessTokenValidity() {\n        return accessTokenValidity;\n    }\n\n    public Integer getRefreshTokenValidity() {\n        return refreshTokenValidity;\n    }\n\n    public Integer setRefreshTokenValidity() {\n        return refreshTokenValidity;\n    }\n\n    public String getAdditionalInformation() {\n        return additionalInformation;\n    }\n\n    public String setAdditionalInformation() {\n        return additionalInformation;\n    }\n\n    public String getAutoapprove() {\n        return autoapprove;\n    }\n\n    public String setAutoapprove() {\n        return autoapprove;\n    }\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/model/Dict.java",
    "content": "package com.open.capacity.security.model;\n\npublic class Dict extends BaseEntity<Long> {\n\n    private static final long serialVersionUID = -2431140186410912787L;\n    private String type;\n    private String k;\n    private String val;\n\n    public String getType() {\n        return type;\n    }\n\n    public String setType() {\n        return type;\n    }\n\n    public String getK() {\n        return k;\n    }\n\n    public String setK() {\n        return k;\n    }\n\n    public String getVal() {\n        return val;\n    }\n\n    public String setVal() {\n        return val;\n    }\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/model/FileInfo.java",
    "content": "package com.open.capacity.security.model;\n\npublic class FileInfo extends BaseEntity<String> {\n\n    private static final long serialVersionUID = -5761547882766615438L;\n\n    private String contentType;\n    private long size;\n    private String path;\n    private String url;\n    private Integer type;\n\n    public String getContentType() {\n        return contentType;\n    }\n\n    public void setContentType(String contentType) {\n        this.contentType = contentType;\n    }\n\n    public long getSize() {\n        return size;\n    }\n\n    public void setSize(long size) {\n        this.size = size;\n    }\n\n    public String getPath() {\n        return path;\n    }\n\n    public void setPath(String path) {\n        this.path = path;\n    }\n\n    public String getUrl() {\n        return url;\n    }\n\n    public void setUrl(String url) {\n        this.url = url;\n    }\n\n    public Integer getType() {\n        return type;\n    }\n\n    public void setType(Integer type) {\n        this.type = type;\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/model/Mail.java",
    "content": "package com.open.capacity.security.model;\n\npublic class Mail extends BaseEntity<Long> {\n\n    private static final long serialVersionUID = 5613231124043303948L;\n\n    private Long userId;\n    private String toUsers;\n    private String subject;\n    private String content;\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 getToUsers() {\n        return toUsers;\n    }\n\n    public void setToUsers(String toUsers) {\n        this.toUsers = toUsers;\n    }\n\n    public String getSubject() {\n        return subject;\n    }\n\n    public void setSubject(String subject) {\n        this.subject = subject;\n    }\n\n    public String getContent() {\n        return content;\n    }\n\n    public void setContent(String content) {\n        this.content = content;\n    }\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/model/MailTo.java",
    "content": "package com.open.capacity.security.model;\n\npublic class MailTo extends BaseEntity<Long> {\n\n    private static final long serialVersionUID = -8238779033956731073L;\n\n    private Long mailId;\n    private String toUser;\n    private Boolean status;\n\n    public Long getMailId() {\n        return mailId;\n    }\n\n    public void setMailId(Long mailId) {\n        this.mailId = mailId;\n    }\n\n    public String getToUser() {\n        return toUser;\n    }\n\n    public void setToUser(String toUser) {\n        this.toUser = toUser;\n    }\n\n    public Boolean getStatus() {\n        return status;\n    }\n\n    public void setStatus(Boolean status) {\n        this.status = status;\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/model/Notice.java",
    "content": "package com.open.capacity.security.model;\n\npublic class Notice extends BaseEntity<Long> {\n\n    private static final long serialVersionUID = -4401913568806243090L;\n\n    private String title;\n    private String content;\n    private Integer status;\n\n    public String getTitle() {\n        return title;\n    }\n\n    public void setTitle(String title) {\n        this.title = title;\n    }\n\n    public String getContent() {\n        return content;\n    }\n\n    public void setContent(String content) {\n        this.content = content;\n    }\n\n    public Integer getStatus() {\n        return status;\n    }\n\n    public void setStatus(Integer status) {\n        this.status = status;\n    }\n\n    public interface Status {\n        int DRAFT = 0;\n        int PUBLISH = 1;\n    }\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/model/Permission.java",
    "content": "package com.open.capacity.security.model;\n\nimport java.util.List;\n\npublic class Permission extends BaseEntity<Long> {\n\n    private static final long serialVersionUID = 6180869216498363919L;\n    private Long parentId;\n    private String name;\n    private String css;\n    private String href;\n    private Integer type;\n    private String permission;\n    private Integer sort;\n\n    private List<Permission> child;\n\n    public Long getParentId() {\n        return parentId;\n    }\n\n    public void setParentId(Long parentId) {\n        this.parentId = parentId;\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 String getCss() {\n        return css;\n    }\n\n    public void setCss(String css) {\n        this.css = css;\n    }\n\n    public String getHref() {\n        return href;\n    }\n\n    public void setHref(String href) {\n        this.href = href;\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 getPermission() {\n        return permission;\n    }\n\n    public void setPermission(String permission) {\n        this.permission = permission;\n    }\n\n    public Integer getSort() {\n        return sort;\n    }\n\n    public void setSort(Integer sort) {\n        this.sort = sort;\n    }\n\n    public List<Permission> getChild() {\n        return child;\n    }\n\n    public void setChild(List<Permission> child) {\n        this.child = child;\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/model/Role.java",
    "content": "package com.open.capacity.security.model;\n\npublic class Role extends BaseEntity<Long> {\n\n    private static final long serialVersionUID = -3802292814767103648L;\n\n    private String name;\n\n    private String description;\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public String getDescription() {\n        return description;\n    }\n\n    public void setDescription(String description) {\n        this.description = description;\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/model/SysLogs.java",
    "content": "package com.open.capacity.security.model;\n\npublic class SysLogs extends BaseEntity<Long> {\n\n    private static final long serialVersionUID = -7809315432127036583L;\n    private SysUser user;\n    private String module;\n    private Boolean flag;\n    private String remark;\n\n    public SysUser getUser() {\n        return user;\n    }\n\n    public void setUser(SysUser user) {\n        this.user = user;\n    }\n\n    public String getModule() {\n        return module;\n    }\n\n    public void setModule(String module) {\n        this.module = module;\n    }\n\n    public Boolean getFlag() {\n        return flag;\n    }\n\n    public void setFlag(Boolean flag) {\n        this.flag = flag;\n    }\n\n    public String getRemark() {\n        return remark;\n    }\n\n    public void setRemark(String remark) {\n        this.remark = remark;\n    }\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/model/SysUser.java",
    "content": "package com.open.capacity.security.model;\n\nimport com.fasterxml.jackson.annotation.JsonFormat;\n\nimport java.util.Date;\n\npublic class SysUser extends BaseEntity<Long> {\n\n    private static final long serialVersionUID = -6525908145032868837L;\n\n    private String username;\n    private String password;\n    private String nickname;\n    private String headImgUrl;\n    private String phone;\n    private String telephone;\n    private String email;\n    @JsonFormat(pattern = \"yyyy-MM-dd\")\n    private Date birthday;\n    private Integer sex;\n    private Integer status;\n    private String intro;\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 getPassword() {\n        return password;\n    }\n\n    public void setPassword(String password) {\n        this.password = password;\n    }\n\n    public String getNickname() {\n        return nickname;\n    }\n\n    public void setNickname(String nickname) {\n        this.nickname = nickname;\n    }\n\n    public String getHeadImgUrl() {\n        return headImgUrl;\n    }\n\n    public void setHeadImgUrl(String headImgUrl) {\n        this.headImgUrl = headImgUrl;\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 getTelephone() {\n        return telephone;\n    }\n\n    public void setTelephone(String telephone) {\n        this.telephone = telephone;\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 Date getBirthday() {\n        return birthday;\n    }\n\n    public void setBirthday(Date birthday) {\n        this.birthday = birthday;\n    }\n\n    public Integer getSex() {\n        return sex;\n    }\n\n    public void setSex(Integer sex) {\n        this.sex = sex;\n    }\n\n    public Integer getStatus() {\n        return status;\n    }\n\n    public void setStatus(Integer status) {\n        this.status = status;\n    }\n\n    public String getIntro() {\n        return intro;\n    }\n\n    public void setIntro(String intro) {\n        this.intro = intro;\n    }\n\n    public interface Status {\n        int DISABLED = 0;\n        int VALID = 1;\n        int LOCKED = 2;\n    }\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/model/TokenModel.java",
    "content": "package com.open.capacity.security.model;\n\nimport java.util.Date;\n\npublic class TokenModel extends BaseEntity<String> {\n\n    private static final long serialVersionUID = 4566334160572911795L;\n\n    /**\n     * 过期时间\n     */\n    private Date expireTime;\n    /**\n     * LoginUser的json串\n     */\n    private String val;\n\n    public Date getExpireTime() {\n        return expireTime;\n    }\n\n    public void setExpireTime(Date expireTime) {\n        this.expireTime = expireTime;\n    }\n\n    public String getVal() {\n        return val;\n    }\n\n    public void setVal(String val) {\n        this.val = val;\n    }\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/page/table/PageTableArgumentResolver.java",
    "content": "package com.open.capacity.security.page.table;\n\nimport com.google.common.collect.Maps;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.core.MethodParameter;\nimport org.springframework.util.CollectionUtils;\nimport org.springframework.web.bind.support.WebDataBinderFactory;\nimport org.springframework.web.context.request.NativeWebRequest;\nimport org.springframework.web.method.support.HandlerMethodArgumentResolver;\nimport org.springframework.web.method.support.ModelAndViewContainer;\n\nimport javax.servlet.http.HttpServletRequest;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * 分页、查询参数解析\n *\n * @author 624191343@qq.com\n */\npublic class PageTableArgumentResolver implements HandlerMethodArgumentResolver {\n\n    @Override\n    public boolean supportsParameter(MethodParameter parameter) {\n        Class<?> cla = parameter.getParameterType();\n\n        return cla.isAssignableFrom(PageTableRequest.class);\n    }\n\n    @Override\n    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,\n                                  NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {\n        HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);\n\n        PageTableRequest tableRequest = new PageTableRequest();\n        Map<String, String[]> param = request.getParameterMap();\n        if (param.containsKey(\"start\")) {\n            tableRequest.setOffset(Integer.parseInt(request.getParameter(\"start\")));\n        }\n\n        if (param.containsKey(\"length\")) {\n            tableRequest.setLimit(Integer.parseInt(request.getParameter(\"length\")));\n        }\n\n        Map<String, Object> map = Maps.newHashMap();\n        tableRequest.setParams(map);\n\n        param.forEach((k, v) -> {\n            if (v.length == 1) {\n                map.put(k, v[0]);\n            } else {\n                map.put(k, Arrays.asList(v));\n            }\n        });\n\n        setOrderBy(tableRequest, map);\n        removeParam(tableRequest);\n\n        return tableRequest;\n    }\n\n    /**\n     * 去除datatables分页带的一些复杂参数\n     *\n     * @param tableRequest\n     */\n    private void removeParam(PageTableRequest tableRequest) {\n        Map<String, Object> map = tableRequest.getParams();\n\n        if (!CollectionUtils.isEmpty(map)) {\n            Map<String, Object> param = new HashMap<>();\n            map.forEach((k, v) -> {\n                if (k.indexOf(\"[\") < 0 && k.indexOf(\"]\") < 0 && !\"_\".equals(k)) {\n                    param.put(k, v);\n                }\n            });\n\n            tableRequest.setParams(param);\n        }\n    }\n\n    /**\n     * 从datatables分页请求数据中解析排序\n     *\n     * @param tableRequest\n     * @param map\n     */\n    private void setOrderBy(PageTableRequest tableRequest, Map<String, Object> map) {\n        StringBuilder orderBy = new StringBuilder();\n        int size = map.size();\n        for (int i = 0; i < size; i++) {\n            String index = (String) map.get(\"order[\" + i + \"][column]\");\n            if (StringUtils.isEmpty(index)) {\n                break;\n            }\n            String column = (String) map.get(\"columns[\" + index + \"][data]\");\n            if (StringUtils.isBlank(column)) {\n                continue;\n            }\n            String sort = (String) map.get(\"order[\" + i + \"][dir]\");\n\n            orderBy.append(column).append(\" \").append(sort).append(\", \");\n        }\n\n        if (orderBy.length() > 0) {\n            tableRequest.getParams().put(\"orderBy\",\n                    \" order by \" + StringUtils.substringBeforeLast(orderBy.toString(), \",\"));\n        }\n    }\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/page/table/PageTableHandler.java",
    "content": "package com.open.capacity.security.page.table;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * 分页查询处理器\n *\n * @author 624191343@qq.com\n */\n\npublic class PageTableHandler {\n\n    private CountHandler countHandler;\n    private ListHandler listHandler;\n    private OrderHandler orderHandler;\n\n    public PageTableHandler(CountHandler countHandler, ListHandler listHandler) {\n        super();\n        this.countHandler = countHandler;\n        this.listHandler = listHandler;\n    }\n\n    public PageTableHandler(CountHandler countHandler, ListHandler listHandler, OrderHandler orderHandler) {\n        this(countHandler, listHandler);\n        this.orderHandler = orderHandler;\n    }\n\n    public PageTableResponse handle(PageTableRequest dtRequest) {\n        int count = 0;\n        List<?> list = null;\n\n        count = this.countHandler.count(dtRequest);\n        if (count > 0) {\n            if (orderHandler != null) {\n                dtRequest = orderHandler.order(dtRequest);\n            }\n            list = this.listHandler.list(dtRequest);\n        }\n\n        if (list == null) {\n            list = new ArrayList<>();\n        }\n\n        return new PageTableResponse(count, count, list);\n    }\n\n    public interface ListHandler {\n        List<?> list(PageTableRequest request);\n    }\n\n    public interface CountHandler {\n        int count(PageTableRequest request);\n    }\n\n    public interface OrderHandler {\n        PageTableRequest order(PageTableRequest request);\n    }\n}"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/page/table/PageTableRequest.java",
    "content": "package com.open.capacity.security.page.table;\n\nimport java.io.Serializable;\nimport java.util.Map;\n\n/**\n * 分页查询参数\n *\n * @author 624191343@qq.com\n */\npublic class PageTableRequest implements Serializable {\n\n    private static final long serialVersionUID = 7328071045193618467L;\n\n    private Integer offset;\n    private Integer limit;\n    private Map<String, Object> params;\n\n    public Integer getOffset() {\n        return offset;\n    }\n\n    public void setOffset(Integer offset) {\n        this.offset = offset;\n    }\n\n    public Integer getLimit() {\n        return limit;\n    }\n\n    public void setLimit(Integer limit) {\n        this.limit = limit;\n    }\n\n    public Map<String, Object> getParams() {\n        return params;\n    }\n\n    public void setParams(Map<String, Object> params) {\n        this.params = params;\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/page/table/PageTableResponse.java",
    "content": "package com.open.capacity.security.page.table;\n\nimport java.io.Serializable;\nimport java.util.List;\n\n/**\n * 分页查询返回\n *\n * @author 624191343@qq.com\n */\npublic class PageTableResponse implements Serializable {\n\n    private static final long serialVersionUID = 620421858510718076L;\n\n    private Integer recordsTotal;\n    private Integer recordsFiltered;\n    private List<?> data;\n\n    public PageTableResponse(Integer recordsTotal, Integer recordsFiltered, List<?> data) {\n        super();\n        this.recordsTotal = recordsTotal;\n        this.recordsFiltered = recordsFiltered;\n        this.data = data;\n    }\n\n    public Integer getRecordsTotal() {\n        return recordsTotal;\n    }\n\n    public void setRecordsTotal(Integer recordsTotal) {\n        this.recordsTotal = recordsTotal;\n    }\n\n    public Integer getRecordsFiltered() {\n        return recordsFiltered;\n    }\n\n    public void setRecordsFiltered(Integer recordsFiltered) {\n        this.recordsFiltered = recordsFiltered;\n    }\n\n    public List<?> getData() {\n        return data;\n    }\n\n    public void setData(List<?> data) {\n        this.data = data;\n    }\n\n}"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/service/ClientService.java",
    "content": "package com.open.capacity.security.service;\n\nimport com.open.capacity.security.dto.ClientDto;\n\npublic interface ClientService {\n\n    void saveClient(ClientDto clientDto);\n\n    void deleteClient(Long id);\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/service/FileService.java",
    "content": "package com.open.capacity.security.service;\n\nimport com.open.capacity.security.model.FileInfo;\nimport org.springframework.web.multipart.MultipartFile;\n\nimport java.io.IOException;\n\npublic interface FileService {\n\n    FileInfo save(MultipartFile file) throws IOException;\n\n    void delete(String id);\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/service/GenerateService.java",
    "content": "package com.open.capacity.security.service;\n\nimport com.open.capacity.security.dto.BeanField;\nimport com.open.capacity.security.dto.GenerateInput;\n\nimport java.util.List;\n\npublic interface GenerateService {\n\n    /**\n     * 获取数据库表信息\n     *\n     * @param tableName\n     * @return\n     */\n    List<BeanField> listBeanField(String tableName);\n\n    /**\n     * 转成驼峰并大写第一个字母\n     *\n     * @param string\n     * @return\n     */\n    String upperFirstChar(String string);\n\n    /**\n     * 生成代码\n     *\n     * @param input\n     */\n    void saveCode(GenerateInput input);\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/service/MailService.java",
    "content": "package com.open.capacity.security.service;\n\nimport com.open.capacity.security.model.Mail;\n\nimport java.util.List;\n\npublic interface MailService {\n\n    void save(Mail mail, List<String> toUser);\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/service/MicroServiceService.java",
    "content": "package com.open.capacity.security.service;\n\nimport com.open.capacity.security.model.Permission;\n\npublic interface MicroServiceService {\n\n    void save(Permission permission);\n\n    void update(Permission permission);\n\n    void delete(Long id);\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/service/PermissionService.java",
    "content": "package com.open.capacity.security.service;\n\nimport com.open.capacity.security.model.Permission;\n\npublic interface PermissionService {\n\n    void save(Permission permission);\n\n    void update(Permission permission);\n\n    void delete(Long id);\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/service/RoleService.java",
    "content": "package com.open.capacity.security.service;\n\nimport com.open.capacity.security.dto.RoleDto;\n\npublic interface RoleService {\n\n    void saveRole(RoleDto roleDto);\n\n    void deleteRole(Long id);\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/service/SendMailSevice.java",
    "content": "package com.open.capacity.security.service;\n\nimport javax.mail.MessagingException;\nimport java.util.List;\n\npublic interface SendMailSevice {\n\n    /**\n     * @param toUser\n     * @param subject 标题\n     * @param text    内容（支持html格式）\n     */\n    void sendMail(List<String> toUser, String subject, String text);\n\n    void sendMail(String toUser, String subject, String text) throws MessagingException;\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/service/SysLogService.java",
    "content": "package com.open.capacity.security.service;\n\nimport com.open.capacity.security.model.SysLogs;\n\n/**\n * 日志service\n *\n * @author 624191343@qq.com\n * <p>\n * 2017年8月19日\n */\npublic interface SysLogService {\n\n    void save(SysLogs sysLogs);\n\n    void save(Long userId, String module, Boolean flag, String remark);\n\n    void deleteLogs();\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/service/TokenService.java",
    "content": "package com.open.capacity.security.service;\n\nimport com.open.capacity.security.dto.LoginUser;\nimport com.open.capacity.security.dto.Token;\n\n/**\n * Token管理器<br>\n * 可存储到redis或者数据库<br>\n * 具体可看实现类<br>\n * 默认基于redis，实现类为 com.boot.security.server.service.impl.TokenServiceJWTImpl<br>\n * 如要换成数据库存储，将TokenServiceImpl类上的注解@Primary挪到com.boot.security.server.service.impl.TokenServiceDbImpl\n *\n * @author 624191343@qq.com\n * <p>\n * 2017年10月14日\n */\npublic interface TokenService {\n\n    Token saveToken(LoginUser loginUser);\n\n    void refresh(LoginUser loginUser);\n\n    LoginUser getLoginUser(String token);\n\n    boolean deleteToken(String token);\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/service/UserService.java",
    "content": "package com.open.capacity.security.service;\n\nimport com.open.capacity.security.dto.UserDto;\nimport com.open.capacity.security.model.SysUser;\n\npublic interface UserService {\n\n    SysUser saveUser(UserDto userDto);\n\n    SysUser updateUser(UserDto userDto);\n\n    SysUser getUser(String username);\n\n    void changePassword(String username, String oldPassword, String newPassword);\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/service/impl/ClientServiceImpl.java",
    "content": "package com.open.capacity.security.service.impl;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.open.capacity.security.dao.ClientDao;\nimport com.open.capacity.security.dto.ClientDto;\nimport com.open.capacity.security.model.Client;\nimport com.open.capacity.security.service.ClientService;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.data.redis.core.RedisTemplate;\nimport org.springframework.security.oauth2.provider.client.BaseClientDetails;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\nimport org.springframework.util.CollectionUtils;\n\nimport java.util.List;\n\n@Service\npublic class ClientServiceImpl implements ClientService {\n\n    private static final Logger log = LoggerFactory.getLogger(ClientServiceImpl.class);\n\n    /**\n     * 缓存client的redis key，这里是hash结构存储\n     */\n    private static final String CACHE_CLIENT_KEY = \"oauth_client_details\";\n\n    @Autowired\n    private ClientDao clientDao;\n\n    @Autowired\n    private RedisTemplate<String, Object> redisTemplate;\n\n    @Override\n    @Transactional\n    public void saveClient(ClientDto clientDto) {\n        Client client = clientDto;\n        List<Long> permissionIds = clientDto.getPermissionIds();\n        permissionIds.remove(0L);\n\n        if (client.getId() != null) {// 修改\n            updateClient(client, permissionIds);\n        } else {// 新增\n            saveClient(client, permissionIds);\n        }\n    }\n\n    private void saveClient(Client client, List<Long> permissionIds) {\n        Client r = clientDao.getClient(client.getClientId());\n        if (r != null) {\n            throw new IllegalArgumentException(client.getClientId() + \"已存在\");\n        }\n\n        clientDao.save(client);\n        if (!CollectionUtils.isEmpty(permissionIds)) {\n            clientDao.saveClientPermission(client.getId(), permissionIds);\n        }\n        log.debug(\"新增应用{}\", client.getClientId());\n    }\n\n    private void updateClient(Client client, List<Long> permissionIds) {\n//\t\tClient r = clientDao.getClient(client.getClientId());\n//\t\tif (r != null && r.getId() != client.getId()) {\n//\t\t\tthrow new IllegalArgumentException(client.getClientId() + \"已存在\");\n//\t\t}\n\n        clientDao.update(client);\n\n\n        clientDao.deleteClientPermission(client.getId());\n        if (!CollectionUtils.isEmpty(permissionIds)) {\n            clientDao.saveClientPermission(client.getId(), permissionIds);\n        }\n\n        String clientId = clientDao.getById(client.getId()).getClientId();\n\n        BaseClientDetails clientDetails = null;\n\n        // 先从redis获取\n        try {\n            String value = (String) redisTemplate.boundHashOps(CACHE_CLIENT_KEY).get(clientId);\n            clientDetails = JSONObject.parseObject(value, BaseClientDetails.class);\n            clientDetails.setClientSecret(client.getClientSecret());\n            redisTemplate.boundHashOps(CACHE_CLIENT_KEY).put(clientId, JSONObject.toJSONString(clientDetails));\n\n\n        } catch (Exception e) {\n\n        }\n\n\n        log.debug(\"修改应用{}\", client.getClientId());\n    }\n\n    @Override\n    @Transactional\n    public void deleteClient(Long id) {\n        clientDao.deleteClientPermission(id);\n        clientDao.delete(id);\n\n        log.debug(\"删除应用id:{}\", id);\n    }\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/service/impl/FileServiceImpl.java",
    "content": "package com.open.capacity.security.service.impl;\n\nimport com.open.capacity.security.dao.FileInfoDao;\nimport com.open.capacity.security.model.FileInfo;\nimport com.open.capacity.security.service.FileService;\nimport com.open.capacity.security.utils.FileUtil;\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.stereotype.Service;\nimport org.springframework.web.multipart.MultipartFile;\n\nimport java.io.IOException;\n\n@Service\npublic class FileServiceImpl implements FileService {\n\n    private static final Logger log = LoggerFactory.getLogger(FileServiceImpl.class);\n\n    @Value(\"${files.path}\")\n    private String filesPath;\n    @Autowired\n    private FileInfoDao fileInfoDao;\n\n    @Override\n    public FileInfo save(MultipartFile file) throws IOException {\n        String fileOrigName = file.getOriginalFilename();\n\n        if (!fileOrigName.contains(\".\")) {\n            throw new IllegalArgumentException(\"缺少后缀名\");\n        }\n\n        String md5 = FileUtil.fileMd5(file.getInputStream());\n        FileInfo fileInfo = fileInfoDao.getById(md5);\n\n        fileOrigName = fileOrigName.substring(fileOrigName.lastIndexOf(\".\"));\n        String pathname = FileUtil.getPath() + md5 + fileOrigName;\n        String fullPath = filesPath + pathname;\n        FileUtil.saveFile(file, fullPath);\n\n        if (fileInfo != null) {\n            fileInfo.setPath(fullPath);\n            fileInfo.setUrl(pathname);\n            fileInfoDao.update(fileInfo);\n            return fileInfo;\n        }\n\n        long size = file.getSize();\n        String contentType = file.getContentType();\n\n        fileInfo = new FileInfo();\n        fileInfo.setId(md5);\n        fileInfo.setContentType(contentType);\n        fileInfo.setSize(size);\n        fileInfo.setPath(fullPath);\n        fileInfo.setUrl(pathname);\n        fileInfo.setType(contentType.startsWith(\"image/\") ? 1 : 0);\n\n        fileInfoDao.save(fileInfo);\n\n        log.debug(\"上传文件{}\", fullPath);\n\n        return fileInfo;\n\n    }\n\n    @Override\n    public void delete(String id) {\n        FileInfo fileInfo = fileInfoDao.getById(id);\n        if (fileInfo != null) {\n            String fullPath = fileInfo.getPath();\n            FileUtil.deleteFile(fullPath);\n\n            fileInfoDao.delete(id);\n            log.debug(\"删除文件：{}\", fileInfo.getPath());\n        }\n    }\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/service/impl/GenerateServiceImpl.java",
    "content": "package com.open.capacity.security.service.impl;\n\nimport com.google.common.collect.Maps;\nimport com.open.capacity.security.dto.BeanField;\nimport com.open.capacity.security.dto.GenerateInput;\nimport com.open.capacity.security.service.GenerateService;\nimport com.open.capacity.security.utils.StrUtil;\nimport com.open.capacity.security.utils.TemplateUtil;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.jdbc.core.JdbcTemplate;\nimport org.springframework.jdbc.core.RowMapper;\nimport org.springframework.stereotype.Service;\nimport org.springframework.util.CollectionUtils;\n\nimport java.math.BigDecimal;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Map;\n\n@Service\npublic class GenerateServiceImpl implements GenerateService {\n\n    /**\n     * mysql类型与java类型部分对应关系\n     */\n    private static Map<String, String> map = Maps.newHashMap();\n\n    static {\n        map.put(\"int\", Integer.class.getSimpleName());\n        map.put(\"tinyint\", Integer.class.getSimpleName());\n        map.put(\"double\", Double.class.getSimpleName());\n        map.put(\"float\", Float.class.getSimpleName());\n        map.put(\"decimal\", BigDecimal.class.getSimpleName());\n        map.put(\"date\", Date.class.getSimpleName());\n        map.put(\"timestamp\", Date.class.getSimpleName());\n        map.put(\"datetime\", Date.class.getSimpleName());\n        map.put(\"varchar\", String.class.getSimpleName());\n        map.put(\"text\", String.class.getSimpleName());\n        map.put(\"longtext\", String.class.getSimpleName());\n\n    }\n\n    @Autowired\n    private JdbcTemplate jdbcTemplate;\n    private RowMapper<BeanField> beanFieldMapper = new RowMapper<BeanField>() {\n\n        @Override\n        public BeanField mapRow(ResultSet rs, int paramInt) throws SQLException {\n            BeanField beanField = new BeanField();\n            beanField.setColumnName(rs.getString(\"column_name\"));\n            beanField.setColumnType(rs.getString(\"data_type\"));\n            beanField.setColumnComment(rs.getString(\"column_comment\"));\n            beanField.setColumnDefault(rs.getString(\"column_default\"));\n\n            return beanField;\n        }\n    };\n\n    @Override\n    public List<BeanField> listBeanField(String tableName) {\n        List<BeanField> beanFields = jdbcTemplate.query(\n                \"select column_name, data_type, column_comment, column_default FROM information_schema.columns WHERE table_name= ? and table_schema = (select database())\",\n                new String[]{tableName}, beanFieldMapper);\n        if (CollectionUtils.isEmpty(beanFields)) {\n            throw new IllegalArgumentException(\"表\" + tableName + \"不存在\");\n        }\n\n        beanFields.parallelStream().forEach(b -> {\n            b.setName(StrUtil.str2hump(b.getColumnName()));\n            String type = map.get(b.getColumnType());\n            if (type == null) {\n                type = String.class.getSimpleName();\n            }\n            b.setType(type);\n            if (\"id\".equals(b.getName())) {\n                b.setType(Long.class.getSimpleName());\n            }\n\n            b.setColumnDefault(b.getColumnDefault() == null ? \"\" : b.getColumnDefault());\n        });\n\n        return beanFields;\n    }\n\n    @Override\n    public String upperFirstChar(String string) {\n        String name = StrUtil.str2hump(string);\n        String firstChar = name.substring(0, 1);\n        name = name.replaceFirst(firstChar, firstChar.toUpperCase());\n\n        return name;\n    }\n\n    @Override\n    public void saveCode(GenerateInput input) {\n        TemplateUtil.saveJava(input);\n        TemplateUtil.saveJavaDao(input);\n        TemplateUtil.saveController(input);\n        TemplateUtil.saveHtmlList(input);\n    }\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/service/impl/MailServiceImpl.java",
    "content": "package com.open.capacity.security.service.impl;\n\nimport com.open.capacity.security.dao.MailDao;\nimport com.open.capacity.security.model.Mail;\nimport com.open.capacity.security.service.MailService;\nimport com.open.capacity.security.service.SendMailSevice;\nimport com.open.capacity.security.utils.UserUtil;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\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@Service\npublic class MailServiceImpl implements MailService {\n\n    private static final Logger log = LoggerFactory.getLogger(MailServiceImpl.class);\n\n    @Autowired\n    private SendMailSevice sendMailSevice;\n    @Autowired\n    private MailDao mailDao;\n\n    @Override\n    @Transactional\n    public void save(Mail mail, List<String> toUser) {\n        mail.setUserId(UserUtil.getLoginUser().getId());\n        mailDao.save(mail);\n\n        toUser.forEach(u -> {\n            int status = 1;\n            try {\n                sendMailSevice.sendMail(u, mail.getSubject(), mail.getContent());\n            } catch (Exception e) {\n                log.error(\"发送邮件失败\", e);\n                status = 0;\n            }\n\n            mailDao.saveToUser(mail.getId(), u, status);\n        });\n\n    }\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/service/impl/MicroServicesServiceImpl.java",
    "content": "package com.open.capacity.security.service.impl;\n\nimport com.open.capacity.security.dao.ServiceDao;\nimport com.open.capacity.security.model.Permission;\nimport com.open.capacity.security.service.MicroServiceService;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\n@Service\npublic class MicroServicesServiceImpl implements MicroServiceService {\n\n    private static final Logger log = LoggerFactory.getLogger(MicroServicesServiceImpl.class);\n\n    @Autowired\n    private ServiceDao serviceDao;\n\n    @Override\n    public void save(Permission permission) {\n        serviceDao.save(permission);\n\n        log.debug(\"新增服务{}\", permission.getName());\n    }\n\n    @Override\n    public void update(Permission permission) {\n        serviceDao.update(permission);\n    }\n\n    @Override\n    @Transactional\n    public void delete(Long id) {\n        serviceDao.delete(id);\n        serviceDao.deleteByParentId(id);\n\n        log.debug(\"删除菜单id:{}\", id);\n    }\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/service/impl/PermissionServiceImpl.java",
    "content": "package com.open.capacity.security.service.impl;\n\nimport com.open.capacity.security.dao.PermissionDao;\nimport com.open.capacity.security.model.Permission;\nimport com.open.capacity.security.service.PermissionService;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\n@Service\npublic class PermissionServiceImpl implements PermissionService {\n\n    private static final Logger log = LoggerFactory.getLogger(PermissionServiceImpl.class);\n\n    @Autowired\n    private PermissionDao permissionDao;\n\n    @Override\n    public void save(Permission permission) {\n        permissionDao.save(permission);\n\n        log.debug(\"新增菜单{}\", permission.getName());\n    }\n\n    @Override\n    public void update(Permission permission) {\n        permissionDao.update(permission);\n    }\n\n    @Override\n    @Transactional\n    public void delete(Long id) {\n        permissionDao.deleteRolePermission(id);\n        permissionDao.delete(id);\n        permissionDao.deleteByParentId(id);\n\n        log.debug(\"删除菜单id:{}\", id);\n    }\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/service/impl/RoleServiceImpl.java",
    "content": "package com.open.capacity.security.service.impl;\n\nimport com.open.capacity.security.dao.RoleDao;\nimport com.open.capacity.security.dto.RoleDto;\nimport com.open.capacity.security.model.Role;\nimport com.open.capacity.security.service.RoleService;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\nimport org.springframework.util.CollectionUtils;\n\nimport java.util.List;\n\n@Service\npublic class RoleServiceImpl implements RoleService {\n\n    private static final Logger log = LoggerFactory.getLogger(RoleServiceImpl.class);\n\n    @Autowired\n    private RoleDao roleDao;\n\n    @Override\n    @Transactional\n    public void saveRole(RoleDto roleDto) {\n        Role role = roleDto;\n        List<Long> permissionIds = roleDto.getPermissionIds();\n        permissionIds.remove(0L);\n\n        if (role.getId() != null) {// 修改\n            updateRole(role, permissionIds);\n        } else {// 新增\n            saveRole(role, permissionIds);\n        }\n    }\n\n    private void saveRole(Role role, List<Long> permissionIds) {\n        Role r = roleDao.getRole(role.getName());\n        if (r != null) {\n            throw new IllegalArgumentException(role.getName() + \"已存在\");\n        }\n\n        roleDao.save(role);\n        if (!CollectionUtils.isEmpty(permissionIds)) {\n            roleDao.saveRolePermission(role.getId(), permissionIds);\n        }\n        log.debug(\"新增角色{}\", role.getName());\n    }\n\n    private void updateRole(Role role, List<Long> permissionIds) {\n        Role r = roleDao.getRole(role.getName());\n        if (r != null && r.getId() != role.getId()) {\n            throw new IllegalArgumentException(role.getName() + \"已存在\");\n        }\n\n        roleDao.update(role);\n\n        roleDao.deleteRolePermission(role.getId());\n        if (!CollectionUtils.isEmpty(permissionIds)) {\n            roleDao.saveRolePermission(role.getId(), permissionIds);\n        }\n        log.debug(\"修改角色{}\", role.getName());\n    }\n\n    @Override\n    @Transactional\n    public void deleteRole(Long id) {\n        roleDao.deleteRolePermission(id);\n        roleDao.deleteRoleUser(id);\n        roleDao.delete(id);\n\n        log.debug(\"删除角色id:{}\", id);\n    }\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/service/impl/SendMailSeviceImpl.java",
    "content": "package com.open.capacity.security.service.impl;\n\nimport com.open.capacity.security.service.SendMailSevice;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.mail.javamail.JavaMailSender;\nimport org.springframework.mail.javamail.MimeMessageHelper;\nimport org.springframework.stereotype.Service;\n\nimport javax.mail.MessagingException;\nimport javax.mail.internet.MimeMessage;\nimport java.util.List;\n\n@Service\npublic class SendMailSeviceImpl implements SendMailSevice {\n\n    @Autowired\n    private JavaMailSender javaMailSender;\n\n    @Value(\"${spring.mail.username}\")\n    private String serverMail;\n\n    @Override\n    public void sendMail(List<String> toUser, String subject, String text) {\n        MimeMessage message = javaMailSender.createMimeMessage();\n\n        try {\n            MimeMessageHelper helper = new MimeMessageHelper(message, true);\n            helper.setFrom(serverMail);\n            helper.setTo(toUser.toArray(new String[toUser.size()]));\n            helper.setSubject(subject);\n            helper.setText(text, true);\n\n            javaMailSender.send(message);\n        } catch (MessagingException e) {\n            e.printStackTrace();\n        }\n\n    }\n\n    @Override\n    public void sendMail(String toUser, String subject, String text) throws MessagingException {\n        MimeMessage message = javaMailSender.createMimeMessage();\n\n        MimeMessageHelper helper = new MimeMessageHelper(message, true);\n        helper.setFrom(serverMail);\n        helper.setTo(toUser);\n        helper.setSubject(subject);\n        helper.setText(text, true);\n\n        javaMailSender.send(message);\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/service/impl/SysLogServiceImpl.java",
    "content": "package com.open.capacity.security.service.impl;\n\nimport com.open.capacity.security.dao.SysLogsDao;\nimport com.open.capacity.security.model.SysLogs;\nimport com.open.capacity.security.model.SysUser;\nimport com.open.capacity.security.service.SysLogService;\nimport com.open.capacity.security.utils.UserUtil;\nimport org.apache.commons.lang3.time.DateFormatUtils;\nimport org.apache.commons.lang3.time.DateUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.scheduling.annotation.Async;\nimport org.springframework.stereotype.Service;\n\nimport java.util.Date;\n\n@Service\npublic class SysLogServiceImpl implements SysLogService {\n\n    private static final Logger log = LoggerFactory.getLogger(SysLogServiceImpl.class);\n\n    @Autowired\n    private SysLogsDao sysLogsDao;\n\n    @Override\n    public void save(SysLogs sysLogs) {\n        SysUser user = UserUtil.getLoginUser();\n        if (user == null || user.getId() == null) {\n            return;\n        }\n\n        sysLogs.setUser(user);\n        sysLogsDao.save(sysLogs);\n    }\n\n    @Async\n    @Override\n    public void save(Long userId, String module, Boolean flag, String remark) {\n        SysLogs sysLogs = new SysLogs();\n        sysLogs.setFlag(flag);\n        sysLogs.setModule(module);\n        sysLogs.setRemark(remark);\n\n        SysUser user = new SysUser();\n        user.setId(userId);\n        sysLogs.setUser(user);\n\n        sysLogsDao.save(sysLogs);\n\n    }\n\n    @Override\n    public void deleteLogs() {\n        Date date = DateUtils.addMonths(new Date(), -3);\n        String time = DateFormatUtils.format(date, DateFormatUtils.ISO_8601_EXTENDED_DATE_FORMAT.getPattern());\n\n        int n = sysLogsDao.deleteLogs(time);\n        log.info(\"删除{}之前日志{}条\", time, n);\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/service/impl/TokenServiceImpl.java",
    "content": "package com.open.capacity.security.service.impl;\n\nimport com.open.capacity.security.dto.LoginUser;\nimport com.open.capacity.security.dto.Token;\nimport com.open.capacity.security.service.SysLogService;\nimport com.open.capacity.security.service.TokenService;\nimport io.jsonwebtoken.ExpiredJwtException;\nimport io.jsonwebtoken.Jwts;\nimport io.jsonwebtoken.SignatureAlgorithm;\nimport org.apache.commons.collections4.MapUtils;\nimport org.apache.commons.lang3.StringUtils;\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.context.annotation.Primary;\nimport org.springframework.data.redis.core.RedisTemplate;\nimport org.springframework.stereotype.Service;\n\nimport javax.crypto.spec.SecretKeySpec;\nimport javax.xml.bind.DatatypeConverter;\nimport java.security.Key;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.UUID;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * token存到redis的实现类<br>\n * jwt实现的token\n *\n * @author owen 624191343@qq.com\n */\n@Primary\n@Service\npublic class TokenServiceImpl implements TokenService {\n\n    private static final Logger log = LoggerFactory.getLogger(TokenServiceImpl.class);\n    private static final String LOGIN_USER_KEY = \"LOGIN_USER_KEY\";\n    private static Key KEY = null;\n    /**\n     * token过期秒数\n     */\n    @Value(\"${token.expire.seconds}\")\n    private Integer expireSeconds;\n    @Autowired\n    private RedisTemplate<String, Object> redisTemplate;\n    @Autowired\n    private SysLogService logService;\n    /**\n     * 私钥\n     */\n    @Value(\"${token.jwtSecret}\")\n    private String jwtSecret;\n\n    @Override\n    public Token saveToken(LoginUser loginUser) {\n        loginUser.setToken(UUID.randomUUID().toString());\n        String jwtToken = createJWTToken(loginUser);\n        loginUser.setJwtToken(jwtToken);\n        cacheLoginUser(loginUser);\n        // 登陆日志\n        logService.save(loginUser.getId(), \"登陆\", true, null);\n        return new Token(jwtToken, loginUser.getLoginTime());\n    }\n\n    /**\n     * 生成jwt\n     *\n     * @param loginUser\n     * @return\n     */\n    private String createJWTToken(LoginUser loginUser) {\n        Map<String, Object> claims = new HashMap<>();\n        claims.put(LOGIN_USER_KEY, loginUser.getToken());// 放入一个随机字符串，通过该串可找到登陆用户\n\n        String jwtToken = Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.HS256, getKeyInstance())\n                .compact();\n\n        return jwtToken;\n    }\n\n    private void cacheLoginUser(LoginUser loginUser) {\n        loginUser.setLoginTime(System.currentTimeMillis());\n        loginUser.setExpireTime(loginUser.getLoginTime() + expireSeconds * 1000);\n        // 根据uuid将loginUser缓存\n        redisTemplate.boundValueOps(getTokenKey(loginUser.getToken())).set(loginUser, expireSeconds, TimeUnit.SECONDS);\n    }\n\n    /**\n     * 更新缓存的用户信息\n     */\n    @Override\n    public void refresh(LoginUser loginUser) {\n        cacheLoginUser(loginUser);\n    }\n\n    @Override\n    public LoginUser getLoginUser(String jwtToken) {\n        String uuid = getUUIDFromJWT(jwtToken);\n        if (uuid != null) {\n            return (LoginUser) redisTemplate.boundValueOps(getTokenKey(uuid)).get();\n        }\n\n        return null;\n    }\n\n    @Override\n    public boolean deleteToken(String jwtToken) {\n        String uuid = getUUIDFromJWT(jwtToken);\n        if (uuid != null) {\n            String key = getTokenKey(uuid);\n            LoginUser loginUser = (LoginUser) redisTemplate.opsForValue().get(key);\n            if (loginUser != null) {\n                redisTemplate.delete(key);\n                // 退出日志\n                logService.save(loginUser.getId(), \"退出\", true, null);\n\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    private String getTokenKey(String uuid) {\n        return \"tokens:\" + uuid;\n    }\n\n    private Key getKeyInstance() {\n        if (KEY == null) {\n            synchronized (TokenServiceImpl.class) {\n                if (KEY == null) {// 双重锁\n                    byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(jwtSecret);\n                    KEY = new SecretKeySpec(apiKeySecretBytes, SignatureAlgorithm.HS256.getJcaName());\n                }\n            }\n        }\n\n        return KEY;\n    }\n\n    private String getUUIDFromJWT(String jwtToken) {\n        if (\"null\".equals(jwtToken) || StringUtils.isBlank(jwtToken)) {\n            return null;\n        }\n\n        Map<String, Object> jwtClaims = null;\n        try {\n            jwtClaims = Jwts.parser().setSigningKey(getKeyInstance()).parseClaimsJws(jwtToken).getBody();\n            return MapUtils.getString(jwtClaims, LOGIN_USER_KEY);\n        } catch (ExpiredJwtException e) {\n            log.error(\"{}已过期\", jwtToken);\n        } catch (Exception e) {\n            log.error(\"{}\", e);\n        }\n\n        return null;\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/service/impl/UserDetailsServiceImpl.java",
    "content": "package com.open.capacity.security.service.impl;\n\nimport com.open.capacity.security.dao.PermissionDao;\nimport com.open.capacity.security.dto.LoginUser;\nimport com.open.capacity.security.model.Permission;\nimport com.open.capacity.security.model.SysUser;\nimport com.open.capacity.security.model.SysUser.Status;\nimport com.open.capacity.security.service.UserService;\nimport org.springframework.beans.BeanUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;\nimport org.springframework.security.authentication.DisabledException;\nimport org.springframework.security.authentication.LockedException;\nimport org.springframework.security.core.userdetails.UserDetails;\nimport org.springframework.security.core.userdetails.UserDetailsService;\nimport org.springframework.security.core.userdetails.UsernameNotFoundException;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\n\n/**\n * spring security登陆处理\n *\n * @author owen 624191343@qq.com\n */\n@Service\npublic class UserDetailsServiceImpl implements UserDetailsService {\n\n    @Autowired\n    private UserService userService;\n    @Autowired\n    private PermissionDao permissionDao;\n\n    @Override\n    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {\n        SysUser sysUser = userService.getUser(username);\n        if (sysUser == null) {\n            throw new AuthenticationCredentialsNotFoundException(\"用户名不存在\");\n        } else if (sysUser.getStatus() == Status.LOCKED) {\n            throw new LockedException(\"用户被锁定,请联系管理员\");\n        } else if (sysUser.getStatus() == Status.DISABLED) {\n            throw new DisabledException(\"用户已作废\");\n        }\n\n        LoginUser loginUser = new LoginUser();\n        BeanUtils.copyProperties(sysUser, loginUser);\n\n        List<Permission> permissions = permissionDao.listByUserId(sysUser.getId());\n        loginUser.setPermissions(permissions);\n\n        return loginUser;\n    }\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/service/impl/UserServiceImpl.java",
    "content": "package com.open.capacity.security.service.impl;\n\nimport com.open.capacity.security.dao.UserDao;\nimport com.open.capacity.security.dto.UserDto;\nimport com.open.capacity.security.model.SysUser;\nimport com.open.capacity.security.model.SysUser.Status;\nimport com.open.capacity.security.service.UserService;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\nimport org.springframework.util.CollectionUtils;\n\nimport java.util.List;\n\n@Service\npublic class UserServiceImpl implements UserService {\n\n    private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class);\n\n    @Autowired\n    private UserDao userDao;\n    @Autowired\n    private BCryptPasswordEncoder passwordEncoder;\n\n    @Override\n    @Transactional\n    public SysUser saveUser(UserDto userDto) {\n        SysUser user = userDto;\n        user.setPassword(passwordEncoder.encode(user.getPassword()));\n        user.setStatus(Status.VALID);\n        userDao.save(user);\n        saveUserRoles(user.getId(), userDto.getRoleIds());\n\n        log.debug(\"新增用户{}\", user.getUsername());\n        return user;\n    }\n\n    private void saveUserRoles(Long userId, List<Long> roleIds) {\n        if (roleIds != null) {\n            userDao.deleteUserRole(userId);\n            if (!CollectionUtils.isEmpty(roleIds)) {\n                userDao.saveUserRoles(userId, roleIds);\n            }\n        }\n    }\n\n    @Override\n    public SysUser getUser(String username) {\n        return userDao.getUser(username);\n    }\n\n    @Override\n    public void changePassword(String username, String oldPassword, String newPassword) {\n        SysUser u = userDao.getUser(username);\n        if (u == null) {\n            throw new IllegalArgumentException(\"用户不存在\");\n        }\n\n        if (!passwordEncoder.matches(oldPassword, u.getPassword())) {\n            throw new IllegalArgumentException(\"旧密码错误\");\n        }\n\n        userDao.changePassword(u.getId(), passwordEncoder.encode(newPassword));\n\n        log.debug(\"修改{}的密码\", username);\n    }\n\n    @Override\n    @Transactional\n    public SysUser updateUser(UserDto userDto) {\n        userDao.update(userDto);\n        saveUserRoles(userDto.getId(), userDto.getRoleIds());\n\n        return userDto;\n    }\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/utils/ExcelUtil.java",
    "content": "package com.open.capacity.security.utils;\n\nimport org.apache.poi.hssf.usermodel.HSSFWorkbook;\nimport org.apache.poi.ss.usermodel.*;\n\nimport javax.servlet.http.HttpServletResponse;\nimport java.io.*;\nimport java.util.List;\n\n/**\n * excel工具类\n *\n * @author 624191343@qq.com\n */\npublic class ExcelUtil {\n\n    public static void excelLocal(String path, String fileName, String[] headers, List<Object[]> datas) {\n        Workbook workbook = getWorkbook(headers, datas);\n        if (workbook != null) {\n            ByteArrayOutputStream byteArrayOutputStream = null;\n            FileOutputStream fileOutputStream = null;\n            try {\n                byteArrayOutputStream = new ByteArrayOutputStream();\n                workbook.write(byteArrayOutputStream);\n\n                String suffix = \".xls\";\n                File file = new File(path + File.separator + fileName + suffix);\n                if (!file.getParentFile().exists()) {\n                    file.getParentFile().mkdirs();\n                }\n\n                fileOutputStream = new FileOutputStream(file);\n                fileOutputStream.write(byteArrayOutputStream.toByteArray());\n            } catch (Exception e) {\n                e.printStackTrace();\n            } finally {\n                try {\n                    if (fileOutputStream != null) {\n                        fileOutputStream.close();\n                    }\n                } catch (IOException e) {\n                    e.printStackTrace();\n                }\n                try {\n                    if (byteArrayOutputStream != null) {\n                        byteArrayOutputStream.close();\n                    }\n                } catch (IOException e) {\n                    e.printStackTrace();\n                }\n\n                try {\n                    workbook.close();\n                } catch (IOException e) {\n                    e.printStackTrace();\n                }\n            }\n        }\n    }\n\n    /**\n     * 导出excel\n     *\n     * @param fileName\n     * @param headers\n     * @param datas\n     * @param response\n     */\n    public static void excelExport(String fileName, String[] headers, List<Object[]> datas,\n                                   HttpServletResponse response) {\n        Workbook workbook = getWorkbook(headers, datas);\n        if (workbook != null) {\n            ByteArrayOutputStream byteArrayOutputStream = null;\n            try {\n                byteArrayOutputStream = new ByteArrayOutputStream();\n                workbook.write(byteArrayOutputStream);\n\n                String suffix = \".xls\";\n                response.setContentType(\"application/vnd.ms-excel;charset=utf-8\");\n                response.setHeader(\"Content-Disposition\",\n                        \"attachment;filename=\" + new String((fileName + suffix).getBytes(), \"iso-8859-1\"));\n\n                OutputStream outputStream = response.getOutputStream();\n                outputStream.write(byteArrayOutputStream.toByteArray());\n                outputStream.close();\n            } catch (Exception e) {\n                e.printStackTrace();\n            } finally {\n                try {\n                    if (byteArrayOutputStream != null) {\n                        byteArrayOutputStream.close();\n                    }\n                } catch (IOException e) {\n                    e.printStackTrace();\n                }\n\n                try {\n                    workbook.close();\n                } catch (IOException e) {\n                    e.printStackTrace();\n                }\n            }\n        }\n    }\n\n    /**\n     * @param headers 列头\n     * @param datas   数据\n     * @return\n     */\n    public static Workbook getWorkbook(String[] headers, List<Object[]> datas) {\n        Workbook workbook = new HSSFWorkbook();\n\n        Sheet sheet = workbook.createSheet();\n        Row row = null;\n        Cell cell = null;\n        CellStyle style = workbook.createCellStyle();\n        style.setAlignment(HorizontalAlignment.CENTER_SELECTION);\n\n        Font font = workbook.createFont();\n\n        int line = 0, maxColumn = 0;\n        if (headers != null && headers.length > 0) {// 设置列头\n            row = sheet.createRow(line++);\n            row.setHeightInPoints(23);\n            font.setBold(true);\n            font.setFontHeightInPoints((short) 13);\n            style.setFont(font);\n\n            maxColumn = headers.length;\n            for (int i = 0; i < maxColumn; i++) {\n                cell = row.createCell(i);\n                cell.setCellValue(headers[i]);\n                cell.setCellStyle(style);\n            }\n        }\n\n        if (datas != null && datas.size() > 0) {// 渲染数据\n            for (int index = 0, size = datas.size(); index < size; index++) {\n                Object[] data = datas.get(index);\n                if (data != null && data.length > 0) {\n                    row = sheet.createRow(line++);\n                    row.setHeightInPoints(20);\n\n                    int length = data.length;\n                    if (length > maxColumn) {\n                        maxColumn = length;\n                    }\n\n                    for (int i = 0; i < length; i++) {\n                        cell = row.createCell(i);\n                        cell.setCellValue(data[i] == null ? null : data[i].toString());\n                    }\n                }\n            }\n        }\n\n        for (int i = 0; i < maxColumn; i++) {\n            sheet.autoSizeColumn(i);\n        }\n\n        return workbook;\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/utils/FileUtil.java",
    "content": "package com.open.capacity.security.utils;\n\nimport org.apache.commons.codec.digest.DigestUtils;\nimport org.springframework.web.multipart.MultipartFile;\n\nimport java.io.*;\nimport java.time.LocalDate;\n\n/**\n * 文件工具类\n *\n * @author 624191343@qq.com\n */\npublic class FileUtil {\n\n    public static String saveFile(MultipartFile file, String pathname) {\n        try {\n            File targetFile = new File(pathname);\n            if (targetFile.exists()) {\n                return pathname;\n            }\n\n            if (!targetFile.getParentFile().exists()) {\n                targetFile.getParentFile().mkdirs();\n            }\n            file.transferTo(targetFile);\n\n            return pathname;\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n\n        return null;\n    }\n\n    public static boolean deleteFile(String pathname) {\n        File file = new File(pathname);\n        if (file.exists()) {\n            boolean flag = file.delete();\n\n            if (flag) {\n                File[] files = file.getParentFile().listFiles();\n                if (files == null || files.length == 0) {\n                    file.getParentFile().delete();\n                }\n            }\n\n            return flag;\n        }\n\n        return false;\n    }\n\n    public static String fileMd5(InputStream inputStream) {\n        try {\n            return DigestUtils.md5Hex(inputStream);\n        } catch (IOException e) {\n            e.printStackTrace();\n        }\n\n        return null;\n    }\n\n    public static String getPath() {\n        return \"/\" + LocalDate.now().toString().replace(\"-\", \"/\") + \"/\";\n    }\n\n    /**\n     * 将文本写入文件\n     *\n     * @param value\n     * @param path\n     */\n    public static void saveTextFile(String value, String path) {\n        FileWriter writer = null;\n        try {\n            File file = new File(path);\n            if (!file.getParentFile().exists()) {\n                file.getParentFile().mkdirs();\n            }\n\n            writer = new FileWriter(file);\n            writer.write(value);\n            writer.flush();\n        } catch (IOException e) {\n            e.printStackTrace();\n        } finally {\n            try {\n                if (writer != null) {\n                    writer.close();\n                }\n            } catch (IOException e) {\n                e.printStackTrace();\n            }\n        }\n    }\n\n    public static String getText(String path) {\n        File file = new File(path);\n        if (!file.exists()) {\n            return null;\n        }\n\n        try {\n            return getText(new FileInputStream(file));\n        } catch (FileNotFoundException e) {\n            e.printStackTrace();\n        }\n\n        return null;\n    }\n\n    public static String getText(InputStream inputStream) {\n        InputStreamReader isr = null;\n        BufferedReader bufferedReader = null;\n        try {\n            isr = new InputStreamReader(inputStream, \"utf-8\");\n            bufferedReader = new BufferedReader(isr);\n            StringBuilder builder = new StringBuilder();\n            String string;\n            while ((string = bufferedReader.readLine()) != null) {\n                string = string + \"\\n\";\n                builder.append(string);\n            }\n\n            return builder.toString();\n        } catch (IOException e) {\n            e.printStackTrace();\n        } finally {\n            if (bufferedReader != null) {\n                try {\n                    bufferedReader.close();\n                } catch (IOException e) {\n                    e.printStackTrace();\n                }\n            }\n            if (isr != null) {\n                try {\n                    isr.close();\n                } catch (IOException e) {\n                    e.printStackTrace();\n                }\n            }\n        }\n\n        return null;\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/utils/ResponseUtil.java",
    "content": "package com.open.capacity.security.utils;\n\nimport com.alibaba.fastjson.JSONObject;\n\nimport javax.servlet.http.HttpServletResponse;\nimport java.io.IOException;\n\npublic class ResponseUtil {\n\n    public static void responseJson(HttpServletResponse response, int status, Object data) {\n        try {\n            response.setHeader(\"Access-Control-Allow-Origin\", \"*\");\n            response.setHeader(\"Access-Control-Allow-Methods\", \"*\");\n            response.setContentType(\"application/json;charset=UTF-8\");\n            response.setStatus(status);\n\n            response.getWriter().write(JSONObject.toJSONString(data));\n        } catch (IOException e) {\n            e.printStackTrace();\n        }\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/utils/SpringUtil.java",
    "content": "package com.open.capacity.security.utils;\n\nimport org.springframework.beans.BeansException;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.ApplicationContextAware;\nimport org.springframework.core.env.Environment;\nimport org.springframework.stereotype.Component;\n\n/**\n * spring获取bean工具类\n *\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2018年3月20日 下午10:13:18 类说明\n */\n@Component\npublic class SpringUtil implements ApplicationContextAware {\n\n    private static ApplicationContext applicationContext = null;\n\n    public static <T> T getBean(Class<T> cla) {\n        return applicationContext.getBean(cla);\n    }\n\n    public static <T> T getBean(String name, Class<T> cal) {\n        return applicationContext.getBean(name, cal);\n    }\n\n    public static String getProperty(String key) {\n        return applicationContext.getBean(Environment.class).getProperty(key);\n    }\n\n    @Override\n    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {\n        SpringUtil.applicationContext = applicationContext;\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/utils/StrUtil.java",
    "content": "package com.open.capacity.security.utils;\n\nimport com.google.common.collect.Lists;\n\nimport java.util.List;\n\n/**\n * 字符串转化工具类\n *\n * @author 624191343@qq.com\n */\npublic class StrUtil {\n\n    /**\n     * 字符串转为驼峰\n     *\n     * @param str\n     * @return\n     */\n    public static String str2hump(String str) {\n        StringBuffer buffer = new StringBuffer();\n        if (str != null && str.length() > 0) {\n            if (str.contains(\"_\")) {\n                String[] chars = str.split(\"_\");\n                int size = chars.length;\n                if (size > 0) {\n                    List<String> list = Lists.newArrayList();\n                    for (String s : chars) {\n                        if (s != null && s.trim().length() > 0) {\n                            list.add(s);\n                        }\n                    }\n\n                    size = list.size();\n                    if (size > 0) {\n                        buffer.append(list.get(0));\n                        for (int i = 1; i < size; i++) {\n                            String s = list.get(i);\n                            buffer.append(s.substring(0, 1).toUpperCase());\n                            if (s.length() > 1) {\n                                buffer.append(s.substring(1));\n                            }\n                        }\n                    }\n                }\n            } else {\n                buffer.append(str);\n            }\n        }\n\n        return buffer.toString();\n    }\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/utils/TemplateUtil.java",
    "content": "package com.open.capacity.security.utils;\n\nimport com.open.capacity.security.dto.GenerateInput;\nimport org.apache.commons.lang3.StringUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.io.File;\nimport java.math.BigDecimal;\nimport java.util.Date;\nimport java.util.List;\n\npublic class TemplateUtil {\n\n    private static final Logger log = LoggerFactory.getLogger(TemplateUtil.class);\n\n    public static String getTemplete(String fileName) {\n        return FileUtil.getText(TemplateUtil.class.getClassLoader().getResourceAsStream(\"generate/\" + fileName));\n    }\n\n    public static void saveJava(GenerateInput input) {\n        String path = input.getPath();\n        String beanPackageName = input.getBeanPackageName();\n        String beanName = input.getBeanName();\n        List<String> beanFieldName = input.getBeanFieldName();\n        List<String> beanFieldType = input.getBeanFieldType();\n        List<String> beanFieldValue = input.getBeanFieldValue();\n\n        String text = getTemplete(\"java.ftl\");\n        text = text.replace(\"{beanPackageName}\", beanPackageName).replace(\"{beanName}\", beanName);\n\n        String imports = \"\";\n        if (beanFieldType.contains(BigDecimal.class.getSimpleName())) {\n            imports += \"import \" + BigDecimal.class.getName() + \";\\n\";\n        }\n        if (beanFieldType.contains(Date.class.getSimpleName())) {\n            imports += \"import \" + Date.class.getName() + \";\";\n        }\n\n        text = text.replace(\"{import}\", imports);\n        String filelds = getFields(beanFieldName, beanFieldType, beanFieldValue);\n        text = text.replace(\"{filelds}\", filelds);\n        text = text.replace(\"{getset}\", getset(beanFieldName, beanFieldType));\n\n        FileUtil.saveTextFile(text, path + File.separator + getPackagePath(beanPackageName) + beanName + \".java\");\n        log.debug(\"生成java model：{}模板\", beanName);\n    }\n\n    private static String getFields(List<String> beanFieldName, List<String> beanFieldType,\n                                    List<String> beanFieldValue) {\n        StringBuffer buffer = new StringBuffer();\n        int size = beanFieldName.size();\n        for (int i = 0; i < size; i++) {\n            String name = beanFieldName.get(i);\n            if (\"id\".equals(name) || \"createTime\".equals(name) || \"updateTime\".equals(name)) {\n                continue;\n            }\n            String type = beanFieldType.get(i);\n            buffer.append(\"\\tprivate \").append(type).append(\" \").append(name);\n            // 默认值\n//\t\t\tString value = beanFieldValue.get(i);\n//\t\t\tif (!StringUtils.isEmpty(value)) {\n//\t\t\t\tbuffer.append(\" = \");\n//\t\t\t\tif (type.equals(String.class.getSimpleName())) {\n//\t\t\t\t\tvalue = \"\\\"\" + value + \"\\\"\";\n//\t\t\t\t} else if (type.equals(Double.class.getSimpleName())) {\n//\t\t\t\t\tvalue = value + \"D\";\n//\t\t\t\t} else if (type.equals(Float.class.getSimpleName())) {\n//\t\t\t\t\tvalue = value + \"F\";\n//\t\t\t\t} else if (type.equals(BigDecimal.class.getSimpleName())) {\n//\t\t\t\t\tvalue = \"new BigDecimal(\" + value + \")\";\n//\t\t\t\t}\n//\n//\t\t\t\tbuffer.append(value);\n//\t\t\t}\n            buffer.append(\";\\n\");\n        }\n\n        return buffer.toString();\n    }\n\n    private static String getset(List<String> beanFieldName, List<String> beanFieldType) {\n        StringBuffer buffer = new StringBuffer();\n        int size = beanFieldName.size();\n        for (int i = 0; i < size; i++) {\n            String name = beanFieldName.get(i);\n            if (\"id\".equals(name) || \"createTime\".equals(name) || \"updateTime\".equals(name)) {\n                continue;\n            }\n\n            String type = beanFieldType.get(i);\n            buffer.append(\"\\tpublic \").append(type).append(\" get\")\n                    .append(StringUtils.substring(name, 0, 1).toUpperCase() + name.substring(1, name.length()))\n                    .append(\"() {\\n\");\n            buffer.append(\"\\t\\treturn \").append(name).append(\";\\n\");\n            buffer.append(\"\\t}\\n\");\n            buffer.append(\"\\tpublic \").append(type).append(\" set\")\n                    .append(StringUtils.substring(name, 0, 1).toUpperCase() + name.substring(1, name.length()))\n                    .append(\"() {\\n\");\n            buffer.append(\"\\t\\treturn \").append(name).append(\";\\n\");\n            buffer.append(\"\\t}\\n\");\n        }\n\n        return buffer.toString();\n    }\n\n    public static void saveJavaDao(GenerateInput input) {\n        String path = input.getPath();\n        String tableName = input.getTableName();\n        String beanPackageName = input.getBeanPackageName();\n        String beanName = input.getBeanName();\n        String daoPackageName = input.getDaoPackageName();\n        String daoName = input.getDaoName();\n\n        String text = getTemplete(\"dao.ftl\");\n        text = text.replace(\"{daoPackageName}\", daoPackageName);\n        text = text.replace(\"{beanPackageName}\", beanPackageName);\n        text = text.replace(\"{daoName}\", daoName);\n        text = text.replace(\"{table_name}\", tableName);\n        text = text.replace(\"{beanName}\", beanName);\n        text = text.replace(\"{beanParamName}\", lowerFirstChar(beanName));\n\n        String insertColumns = getInsertColumns(input.getColumnNames());\n        text = text.replace(\"{insert_columns}\", insertColumns);\n        String insertValues = getInsertValues(input.getColumnNames(), input.getBeanFieldName());\n        text = text.replace(\"{insert_values}\", insertValues);\n        FileUtil.saveTextFile(text, path + File.separator + getPackagePath(daoPackageName) + daoName + \".java\");\n        log.debug(\"生成java dao：{}模板\", beanName);\n\n        text = getTemplete(\"mapper.xml\");\n        text = text.replace(\"{daoPackageName}\", daoPackageName);\n        text = text.replace(\"{daoName}\", daoName);\n        text = text.replace(\"{table_name}\", tableName);\n        text = text.replace(\"{beanName}\", beanName);\n        String sets = getUpdateSets(input.getColumnNames(), input.getBeanFieldName());\n        text = text.replace(\"{update_sets}\", sets);\n        String where = getWhere(input.getColumnNames(), input.getBeanFieldName());\n        text = text.replace(\"{where}\", where);\n        FileUtil.saveTextFile(text, path + File.separator + beanName + \"Mapper.xml\");\n    }\n\n    private static String getInsertValues(List<String> columnNames, List<String> beanFieldName) {\n        StringBuffer buffer = new StringBuffer();\n        int size = columnNames.size();\n        for (int i = 0; i < size; i++) {\n            String column = columnNames.get(i);\n            if (!\"id\".equals(column)) {\n                buffer.append(\"#{\").append(beanFieldName.get(i)).append(\"}, \");\n            }\n        }\n\n        String sets = StringUtils.substringBeforeLast(buffer.toString(), \",\");\n        return sets;\n    }\n\n    private static String getInsertColumns(List<String> columnNames) {\n        StringBuffer buffer = new StringBuffer();\n        int size = columnNames.size();\n        for (int i = 0; i < size; i++) {\n            String column = columnNames.get(i);\n            if (!\"id\".equals(column)) {\n                buffer.append(column).append(\", \");\n            }\n        }\n\n        String insertColumns = StringUtils.substringBeforeLast(buffer.toString(), \",\");\n        return insertColumns;\n    }\n\n    private static String getUpdateSets(List<String> columnNames, List<String> beanFieldName) {\n        StringBuffer buffer = new StringBuffer();\n        int size = columnNames.size();\n        for (int i = 0; i < size; i++) {\n            String column = columnNames.get(i);\n            if (!\"id\".equals(column)) {\n                buffer.append(\"\\t\\t\\t<if test=\\\"\" + column + \" != null\\\">\\n\");\n                buffer.append(\"\\t\\t\\t\\t\" + column).append(\" = \").append(\"#{\").append(beanFieldName.get(i))\n                        .append(\"}, \\n\");\n                buffer.append(\"\\t\\t\\t</if>\\n\");\n            }\n        }\n\n        return buffer.toString();\n    }\n\n    private static String getWhere(List<String> columnNames, List<String> beanFieldName) {\n        StringBuffer buffer = new StringBuffer();\n        int size = columnNames.size();\n        for (int i = 0; i < size; i++) {\n            String column = columnNames.get(i);\n            buffer.append(\"\\t\\t\\t<if test=\\\"params.\" + column + \" != null and params.\" + column + \" != ''\\\">\\n\");\n            buffer.append(\"\\t\\t\\t\\tand \" + column).append(\" = \").append(\"#{params.\").append(beanFieldName.get(i))\n                    .append(\"} \\n\");\n            buffer.append(\"\\t\\t\\t</if>\\n\");\n        }\n\n        return buffer.toString();\n    }\n\n    /**\n     * 变量名\n     *\n     * @param beanName\n     * @return\n     */\n    public static String lowerFirstChar(String beanName) {\n        String name = StrUtil.str2hump(beanName);\n        String firstChar = name.substring(0, 1);\n        name = name.replaceFirst(firstChar, firstChar.toLowerCase());\n\n        return name;\n    }\n\n    private static String getPackagePath(String packageName) {\n        String packagePath = packageName.replace(\".\", \"/\");\n        if (!packagePath.endsWith(\"/\")) {\n            packagePath = packagePath + \"/\";\n        }\n\n        return packagePath;\n    }\n\n    public static void saveController(GenerateInput input) {\n        String path = input.getPath();\n        String beanPackageName = input.getBeanPackageName();\n        String beanName = input.getBeanName();\n        String daoPackageName = input.getDaoPackageName();\n        String daoName = input.getDaoName();\n\n        String text = getTemplete(\"controller.ftl\");\n        text = text.replace(\"{daoPackageName}\", daoPackageName);\n        text = text.replace(\"{beanPackageName}\", beanPackageName);\n        text = text.replace(\"{daoName}\", daoName);\n        text = text.replace(\"{daoParamName}\", lowerFirstChar(daoName));\n        text = text.replace(\"{beanName}\", beanName);\n        text = text.replace(\"{beanParamName}\", lowerFirstChar(beanName));\n        text = text.replace(\"{controllerPkgName}\", input.getControllerPkgName());\n        text = text.replace(\"{controllerName}\", input.getControllerName());\n\n        FileUtil.saveTextFile(text, path + File.separator + getPackagePath(input.getControllerPkgName())\n                + input.getControllerName() + \".java\");\n        log.debug(\"生成controller：{}模板\", beanName);\n    }\n\n    public static void saveHtmlList(GenerateInput input) {\n        String path = input.getPath();\n        String beanName = input.getBeanName();\n        String beanParamName = lowerFirstChar(beanName);\n\n        String text = getTemplete(\"htmlList.ftl\");\n        text = text.replace(\"{beanParamName}\", beanParamName);\n        text = text.replace(\"{beanName}\", beanName);\n        List<String> beanFieldNames = input.getBeanFieldName();\n        text = text.replace(\"{columnsDatas}\", getHtmlColumnsDatas(beanFieldNames));\n        text = text.replace(\"{ths}\", getHtmlThs(beanFieldNames));\n\n        FileUtil.saveTextFile(text, path + File.separator + beanParamName + \"List.html\");\n        log.debug(\"生成查询页面：{}模板\", beanName);\n\n        text = getTemplete(\"htmlAdd.ftl\");\n        text = text.replace(\"{beanParamName}\", beanParamName);\n        text = text.replace(\"{addDivs}\", getAddDivs(beanFieldNames));\n        FileUtil.saveTextFile(text, path + File.separator + \"add\" + beanName + \".html\");\n        log.debug(\"生成添加页面：{}模板\", beanName);\n\n        text = getTemplete(\"htmlUpdate.ftl\");\n        text = text.replace(\"{beanParamName}\", beanParamName);\n        text = text.replace(\"{addDivs}\", getAddDivs(beanFieldNames));\n        text = text.replace(\"{initData}\", getInitData(beanFieldNames));\n        FileUtil.saveTextFile(text, path + File.separator + \"update\" + beanName + \".html\");\n        log.debug(\"生成修改页面：{}模板\", beanName);\n    }\n\n    private static CharSequence getInitData(List<String> beanFieldNames) {\n        StringBuilder builder = new StringBuilder();\n        beanFieldNames.forEach(b -> {\n            builder.append(\"\\t\\t\\t\\t\\t\\t$('#\" + b + \"').val(data.\" + b + \");\\n\");\n        });\n\n        return builder.toString();\n    }\n\n    private static String getAddDivs(List<String> beanFieldNames) {\n        StringBuilder builder = new StringBuilder();\n        beanFieldNames.forEach(b -> {\n            if (!\"id\".equals(b) && !\"createTime\".equals(b) && !\"updateTime\".equals(b)) {\n                builder.append(\"\\t\\t\\t<div class='form-group'>\\n\");\n                builder.append(\"\\t\\t\\t\\t<label class='col-md-2 control-label'>\" + b + \"</label>\\n\");\n                builder.append(\"\\t\\t\\t\\t<div class='col-md-10'>\\n\");\n                builder.append(\"\\t\\t\\t\\t\\t<input class='form-control' placeholder='\" + b + \"' type='text' name='\" + b\n                        + \"' id='\" + b + \"' data-bv-notempty='true' data-bv-notempty-message='\" + b + \" 不能为空'>\\n\");\n                builder.append(\"\\t\\t\\t\\t</div>\\n\");\n                builder.append(\"\\t\\t\\t</div>\\n\");\n            }\n        });\n        return builder.toString();\n    }\n\n    private static String getHtmlThs(List<String> beanFieldNames) {\n        StringBuilder builder = new StringBuilder();\n        beanFieldNames.forEach(b -> {\n            builder.append(\"\\t\\t\\t\\t\\t\\t\\t\\t\\t<th>{beanFieldName}</th>\\n\".replace(\"{beanFieldName}\", b));\n        });\n        return builder.toString();\n    }\n\n    private static String getHtmlColumnsDatas(List<String> beanFieldNames) {\n        StringBuilder builder = new StringBuilder();\n        beanFieldNames.forEach(b -> {\n            builder.append(\"\\t\\t\\t\\t{\\\"data\\\" : \\\"{beanFieldName}\\\", \\\"defaultContent\\\" : \\\"\\\"},\\n\"\n                    .replace(\"{beanFieldName}\", b));\n        });\n\n        builder.append(\"\");\n        return builder.toString();\n    }\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/java/com/open/capacity/security/utils/UserUtil.java",
    "content": "package com.open.capacity.security.utils;\n\nimport com.open.capacity.security.dto.LoginUser;\nimport org.springframework.security.authentication.AnonymousAuthenticationToken;\nimport org.springframework.security.authentication.UsernamePasswordAuthenticationToken;\nimport org.springframework.security.core.Authentication;\nimport org.springframework.security.core.context.SecurityContextHolder;\n\npublic class UserUtil {\n\n    public static LoginUser getLoginUser() {\n        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();\n        if (authentication != null) {\n            if (authentication instanceof AnonymousAuthenticationToken) {\n                return null;\n            }\n\n            if (authentication instanceof UsernamePasswordAuthenticationToken) {\n                return (LoginUser) authentication.getPrincipal();\n            }\n        }\n\n        return null;\n    }\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/resources/activiti.properties",
    "content": "\n# 演示模型禁止删除\nmodelId=142517"
  },
  {
    "path": "open-layui-web/src/main/resources/application.yml",
    "content": "server:\n  port: 9999\nsecurity:\n  sessions: stateless  \nspring:\n  application:\n    name: open-layui-web\n  servlet:\n    multipart:\n      max-file-size: 100MB\n      max-request-size: 100MB\n  mvc:\n    servlet:\n      load-on-startup: 1  \n  jackson:\n      date-format: yyyy-MM-dd HH:mm:ss\n      joda-date-time-format: yyyy-MM-dd HH:mm:ss\n      time-zone: GMT+8\n  mail:\n    host: smtp.163.com\n    username: 18579068155@163.com\n    password: 1q2w3e4r\n    properties:\n        mail.smtp.auth : true\n        mail.smtp.timeout : 2000\n        mail.smtp.starttls.enable : true\n        mail.smtp.starttls.required : true\n  thymeleaf:\n    cache: false\n    prefix: classpath:static/pages/\n    mode: LEGACYHTML5\n    content-type: text/html\n  http:\n    encoding:\n      charset:  utf8\n      force: true\n      enabled: true\n  datasource:\n      type: com.alibaba.druid.pool.DruidDataSource\n#      driver-class-name:  oracle.jdbc.OracleDriver\n#      url: jdbc:oracle:thin:@127.0.0.1:1521:orcl\n#      username: crm_owner_user\n#      password: bss_crm_test\n#      filters: stat,wall\n################## mysql start ############################\n      driver-class-name:  com.mysql.jdbc.Driver\n      #     192.168.3.150   130.75.131.211  134.224.249.39  47.94.252.160\n      url: jdbc:mysql://47.94.252.160:3306/boot_security?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false\n      username: root\n      password: root\n      filters: stat,wall\n################### mysq end l##########################\n  redis:\n################### redis 单机版 start ########################## \n    host: 47.94.252.160\n    port: 6379    \n    database: 1\n################### redis 单机版 end ##########################   \n#    cluster:\n#      nodes: 192.168.3.157:7000,192.168.3.158:7000,192.168.3.159:7000,192.168.3.157:7001,192.168.3.158:7001,192.168.3.159:7001\n##        #130.75.131.237:7000,130.75.131.238:7000,130.75.131.239:7000,130.75.131.237:7001,130.75.131.238:7001,130.75.131.239:7001\n#        #192.168.3.157:7000,192.168.3.158:7000,192.168.3.159:7000,192.168.3.157:7001,192.168.3.158:7001,192.168.3.159:7001\n#    timeout: 1000 # 连接超时时间（毫秒）\n#    pool:\n#      max-active: 10  # 连接池最大连接数（使用负值表示没有限制）\n#      max-idle: 8     # 连接池中的最大空闲连接\n#      min-idle: 2     # 连接池中的最小空闲连接\n#      max-wait: 100   # 连接池最大阻塞等待时间（使用负值表示没有限制）       \n    \n\nmybatis:\n  config-location: classpath:mybatis.cfg.xml\n  mapper-locations: classpath*:com/open/**/dao/*.xml  \nfiles:\n  path: ${file-path:d:/files}\nlogging:\n  config: classpath:logback-admin.xml\nlog:\n  level:\n    root: info\n    com.open: debug\n  file: logs/admin-server.log\n  maxsize: 30MB\n\n  \ntoken:\n  expire:\n    seconds: 7200\n  jwtSecret: open-layui-web\n\neureka:\n  client:\n    healthcheck:\n      enabled: true\n    serviceUrl:\n      defaultZone:  http://127.0.0.1:1111/eureka  #http://130.75.131.241:8761/eureka,http://130.75.131.248:8762/eureka\n      #http://134.224.249.33:1111/eureka/  正式库\n      #http://134.224.249.33:1111/eureka/  测试库\n      #http://127.0.0.1:8761/eureka,http://127.0.0.1:8762/eureka\n  instance:\n    prefer-ip-address: true\n    instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}\n    #instance-id: ${spring.application.name}:${docker.ipAddress}:${spring.application.instance_id:${server.port}}\n    lease-renewal-interval-in-seconds: 5  #每隔几秒告诉eureka服务器我还存活，用于心跳检测\n    lease-expiration-duration-in-seconds: 10 #如果心跳检测一直没有发送，10秒后会从eureka服务器中将此服务剔除\n    #注册实例文档\n#    status-page-url: http://${docker.ipAddress}:${server.port}/auth/doc.html # ${server.port}为该服务的端口号  \n\n\n  \n "
  },
  {
    "path": "open-layui-web/src/main/resources/bootstrap.yml",
    "content": "spring:\n  application:\n    name: open-web-server"
  },
  {
    "path": "open-layui-web/src/main/resources/bpmn/demo.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<definitions xmlns=\"http://www.omg.org/spec/BPMN/20100524/MODEL\" xmlns:activiti=\"http://activiti.org/bpmn\" xmlns:bpmndi=\"http://www.omg.org/spec/BPMN/20100524/DI\" xmlns:dc=\"http://www.omg.org/spec/DD/20100524/DC\" xmlns:di=\"http://www.omg.org/spec/DD/20100524/DI\" xmlns:tns=\"http://activiti.org/bpmn20\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" expressionLanguage=\"http://www.w3.org/1999/XPath\" id=\"definitions\" name=\"\" targetNamespace=\"http://activiti.org/bpmn20\" typeLanguage=\"http://www.w3.org/2001/XMLSchema\">\n  <process id=\"vacationRequest\" isClosed=\"false\" name=\"Vacation request\" processType=\"None\">\n    <startEvent activiti:initiator=\"employeeName\" id=\"request\">\n      <extensionElements>\n        <activiti:formProperty id=\"numberOfDays\" name=\"Number of days\" required=\"true\" type=\"long\" value=\"1\"/>\n        <activiti:formProperty datePattern=\"dd-MM-yyyy hh:mm\" id=\"startDate\" name=\"First day of holiday (dd-MM-yyy)\" required=\"true\" type=\"date\"/>\n        <activiti:formProperty id=\"vacationMotivation\" name=\"Motivation\" type=\"string\"/>\n      </extensionElements>\n    </startEvent>\n    <sequenceFlow id=\"flow1\" sourceRef=\"request\" targetRef=\"handleRequest\"/>\n    <userTask activiti:exclusive=\"true\" id=\"handleRequest\" name=\"Handle vacation request\">\n      <documentation id=\"handleRequest_D_1\"><![CDATA[\n        ${employeeName} would like to take ${numberOfDays} day(s) of vacation (Motivation: ${vacationMotivation}).\n      ]]></documentation>\n      <extensionElements>\n        <activiti:formProperty id=\"vacationApproved\" name=\"Do you approve this vacation\" required=\"true\" type=\"enum\">\n          <activiti:value id=\"true\" name=\"Approve\"/>\n          <activiti:value id=\"false\" name=\"Reject\"/>\n        </activiti:formProperty>\n        <activiti:formProperty id=\"managerMotivation\" name=\"Motivation\" type=\"string\"/>\n      </extensionElements>\n    </userTask>\n    <sequenceFlow id=\"flow2\" sourceRef=\"handleRequest\" targetRef=\"requestApprovedDecision\"/>\n    <exclusiveGateway gatewayDirection=\"Unspecified\" id=\"requestApprovedDecision\" name=\"Request approved?\"/>\n    <sequenceFlow id=\"flow3\" sourceRef=\"requestApprovedDecision\" targetRef=\"sendApprovalMail\">\n      <conditionExpression xsi:type=\"tFormalExpression\"><![CDATA[${vacationApproved == 'true'}]]></conditionExpression>\n    </sequenceFlow>\n    <task activiti:exclusive=\"true\" id=\"sendApprovalMail\" name=\"Send confirmation e-mail\"/>\n    <sequenceFlow id=\"flow4\" sourceRef=\"sendApprovalMail\" targetRef=\"theEnd1\"/>\n    <endEvent id=\"theEnd1\"/>\n    <sequenceFlow id=\"flow5\" sourceRef=\"requestApprovedDecision\" targetRef=\"adjustVacationRequestTask\">\n      <conditionExpression xsi:type=\"tFormalExpression\"><![CDATA[${vacationApproved == 'false'}]]></conditionExpression>\n    </sequenceFlow>\n    <userTask activiti:exclusive=\"true\" id=\"adjustVacationRequestTask\" name=\"Adjust vacation request\">\n      <documentation id=\"adjustVacationRequestTask_D_1\"><![CDATA[\n        Your manager has disapproved your vacation request for ${numberOfDays} days.\n        Reason: ${managerMotivation}\n      ]]></documentation>\n      <extensionElements>\n        <activiti:formProperty id=\"numberOfDays\" name=\"Number of days\" required=\"true\" type=\"long\" value=\"${numberOfDays}\"/>\n        <activiti:formProperty datePattern=\"dd-MM-yyyy hh:mm\" id=\"startDate\" name=\"First day of holiday (dd-MM-yyy)\" required=\"true\" type=\"date\" value=\"${startDate}\"/>\n        <activiti:formProperty id=\"vacationMotivation\" name=\"Motivation\" type=\"string\" value=\"${vacationMotivation}\"/>\n        <activiti:formProperty id=\"resendRequest\" name=\"Resend vacation request to manager?\" required=\"true\" type=\"enum\">\n          <activiti:value id=\"true\" name=\"Yes\"/>\n          <activiti:value id=\"false\" name=\"No\"/>\n        </activiti:formProperty>\n      </extensionElements>\n    </userTask>\n    <sequenceFlow id=\"flow6\" sourceRef=\"adjustVacationRequestTask\" targetRef=\"resendRequestDecision\"/>\n    <exclusiveGateway gatewayDirection=\"Unspecified\" id=\"resendRequestDecision\" name=\"Resend request?\"/>\n    <sequenceFlow id=\"flow7\" sourceRef=\"resendRequestDecision\" targetRef=\"handleRequest\">\n      <conditionExpression xsi:type=\"tFormalExpression\"><![CDATA[${resendRequest == 'true'}]]></conditionExpression>\n    </sequenceFlow>\n    <sequenceFlow id=\"flow8\" sourceRef=\"resendRequestDecision\" targetRef=\"theEnd2\">\n      <conditionExpression xsi:type=\"tFormalExpression\"><![CDATA[${resendRequest == 'false'}]]></conditionExpression>\n    </sequenceFlow>\n    <endEvent id=\"theEnd2\"/>\n  </process>\n  <bpmndi:BPMNDiagram documentation=\"background=#FFFFFF;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0\" id=\"Diagram-_1\" name=\"New Diagram\">\n    <bpmndi:BPMNPlane bpmnElement=\"vacationRequest\">\n      <bpmndi:BPMNShape bpmnElement=\"theEnd2\" id=\"Shape-theEnd2\">\n        <dc:Bounds height=\"32.0\" width=\"32.0\" x=\"586.0\" y=\"247.5\"/>\n        <bpmndi:BPMNLabel>\n          <dc:Bounds height=\"32.0\" width=\"32.0\" x=\"0.0\" y=\"0.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNShape>\n      <bpmndi:BPMNShape bpmnElement=\"resendRequestDecision\" id=\"Shape-resendRequestDecision\" isMarkerVisible=\"false\">\n        <dc:Bounds height=\"32.0\" width=\"32.0\" x=\"494.0\" y=\"247.5\"/>\n        <bpmndi:BPMNLabel>\n          <dc:Bounds height=\"32.0\" width=\"32.0\" x=\"0.0\" y=\"0.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNShape>\n      <bpmndi:BPMNShape bpmnElement=\"adjustVacationRequestTask\" id=\"Shape-adjustVacationRequestTask\">\n        <dc:Bounds height=\"55.0\" width=\"85.0\" x=\"349.0\" y=\"236.0\"/>\n        <bpmndi:BPMNLabel>\n          <dc:Bounds height=\"55.0\" width=\"85.0\" x=\"0.0\" y=\"0.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNShape>\n      <bpmndi:BPMNShape bpmnElement=\"theEnd1\" id=\"Shape-theEnd1\">\n        <dc:Bounds height=\"32.0\" width=\"32.0\" x=\"494.0\" y=\"152.5\"/>\n        <bpmndi:BPMNLabel>\n          <dc:Bounds height=\"32.0\" width=\"32.0\" x=\"0.0\" y=\"0.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNShape>\n      <bpmndi:BPMNShape bpmnElement=\"sendApprovalMail\" id=\"Shape-sendApprovalMail\">\n        <dc:Bounds height=\"55.0\" width=\"85.0\" x=\"349.0\" y=\"141.0\"/>\n        <bpmndi:BPMNLabel>\n          <dc:Bounds height=\"55.0\" width=\"85.0\" x=\"0.0\" y=\"0.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNShape>\n      <bpmndi:BPMNShape bpmnElement=\"requestApprovedDecision\" id=\"Shape-requestApprovedDecision\" isMarkerVisible=\"false\">\n        <dc:Bounds height=\"32.0\" width=\"32.0\" x=\"257.0\" y=\"200.0\"/>\n        <bpmndi:BPMNLabel>\n          <dc:Bounds height=\"32.0\" width=\"32.0\" x=\"0.0\" y=\"0.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNShape>\n      <bpmndi:BPMNShape bpmnElement=\"handleRequest\" id=\"Shape-handleRequest\">\n        <dc:Bounds height=\"55.0\" width=\"85.0\" x=\"112.0\" y=\"188.5\"/>\n        <bpmndi:BPMNLabel>\n          <dc:Bounds height=\"55.0\" width=\"85.0\" x=\"0.0\" y=\"0.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNShape>\n      <bpmndi:BPMNShape bpmnElement=\"request\" id=\"Shape-request\">\n        <dc:Bounds height=\"32.0\" width=\"32.0\" x=\"20.0\" y=\"200.0\"/>\n        <bpmndi:BPMNLabel>\n          <dc:Bounds height=\"32.0\" width=\"32.0\" x=\"0.0\" y=\"0.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNShape>\n      <bpmndi:BPMNEdge bpmnElement=\"flow1\" id=\"BPMNEdge_flow1\" sourceElement=\"request\" targetElement=\"handleRequest\">\n        <di:waypoint x=\"52.0\" y=\"216.0\"/>\n        <di:waypoint x=\"112.0\" y=\"216.0\"/>\n        <bpmndi:BPMNLabel>\n          <dc:Bounds height=\"-1.0\" width=\"-1.0\" x=\"-1.0\" y=\"-1.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNEdge>\n      <bpmndi:BPMNEdge bpmnElement=\"flow2\" id=\"BPMNEdge_flow2\" sourceElement=\"handleRequest\" targetElement=\"requestApprovedDecision\">\n        <di:waypoint x=\"197.0\" y=\"216.0\"/>\n        <di:waypoint x=\"257.0\" y=\"216.0\"/>\n        <bpmndi:BPMNLabel>\n          <dc:Bounds height=\"-1.0\" width=\"-1.0\" x=\"-1.0\" y=\"-1.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNEdge>\n      <bpmndi:BPMNEdge bpmnElement=\"flow3\" id=\"BPMNEdge_flow3\" sourceElement=\"requestApprovedDecision\" targetElement=\"sendApprovalMail\">\n        <di:waypoint x=\"289.0\" y=\"216.0\"/>\n        <di:waypoint x=\"349.0\" y=\"168.5\"/>\n        <bpmndi:BPMNLabel>\n          <dc:Bounds height=\"-1.0\" width=\"-1.0\" x=\"-1.0\" y=\"-1.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNEdge>\n      <bpmndi:BPMNEdge bpmnElement=\"flow4\" id=\"BPMNEdge_flow4\" sourceElement=\"sendApprovalMail\" targetElement=\"theEnd1\">\n        <di:waypoint x=\"434.0\" y=\"168.5\"/>\n        <di:waypoint x=\"494.0078144082805\" y=\"168.5\"/>\n        <bpmndi:BPMNLabel>\n          <dc:Bounds height=\"-1.0\" width=\"-1.0\" x=\"-1.0\" y=\"-1.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNEdge>\n      <bpmndi:BPMNEdge bpmnElement=\"flow5\" id=\"BPMNEdge_flow5\" sourceElement=\"requestApprovedDecision\" targetElement=\"adjustVacationRequestTask\">\n        <di:waypoint x=\"289.0\" y=\"216.0\"/>\n        <di:waypoint x=\"349.0\" y=\"263.5\"/>\n        <bpmndi:BPMNLabel>\n          <dc:Bounds height=\"-1.0\" width=\"-1.0\" x=\"-1.0\" y=\"-1.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNEdge>\n      <bpmndi:BPMNEdge bpmnElement=\"flow6\" id=\"BPMNEdge_flow6\" sourceElement=\"adjustVacationRequestTask\" targetElement=\"resendRequestDecision\">\n        <di:waypoint x=\"434.0\" y=\"263.5\"/>\n        <di:waypoint x=\"494.5\" y=\"263.5\"/>\n        <bpmndi:BPMNLabel>\n          <dc:Bounds height=\"-1.0\" width=\"-1.0\" x=\"-1.0\" y=\"-1.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNEdge>\n      <bpmndi:BPMNEdge bpmnElement=\"flow7\" id=\"BPMNEdge_flow7\" sourceElement=\"resendRequestDecision\" targetElement=\"handleRequest\">\n        <di:waypoint x=\"494.5\" y=\"263.5\"/>\n        <di:waypoint x=\"197.0\" y=\"216.0\"/>\n        <bpmndi:BPMNLabel>\n          <dc:Bounds height=\"-1.0\" width=\"-1.0\" x=\"-1.0\" y=\"-1.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNEdge>\n      <bpmndi:BPMNEdge bpmnElement=\"flow8\" id=\"BPMNEdge_flow8\" sourceElement=\"resendRequestDecision\" targetElement=\"theEnd2\">\n        <di:waypoint x=\"525.5\" y=\"263.5\"/>\n        <di:waypoint x=\"586.0078144082805\" y=\"263.5\"/>\n        <bpmndi:BPMNLabel>\n          <dc:Bounds height=\"-1.0\" width=\"-1.0\" x=\"-1.0\" y=\"-1.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNEdge>\n    </bpmndi:BPMNPlane>\n  </bpmndi:BPMNDiagram>\n</definitions>\n"
  },
  {
    "path": "open-layui-web/src/main/resources/bpmn/leave.bpmn",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<definitions xmlns=\"http://www.omg.org/spec/BPMN/20100524/MODEL\" xmlns:activiti=\"http://activiti.org/bpmn\" xmlns:bpmndi=\"http://www.omg.org/spec/BPMN/20100524/DI\" xmlns:omgdc=\"http://www.omg.org/spec/DD/20100524/DC\" xmlns:omgdi=\"http://www.omg.org/spec/DD/20100524/DI\" xmlns:tns=\"http://www.activiti.org/test\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" expressionLanguage=\"http://www.w3.org/1999/XPath\" id=\"m1516374578435\" name=\"\" targetNamespace=\"http://www.activiti.org/test\" typeLanguage=\"http://www.w3.org/2001/XMLSchema\">\n  <process id=\"studentLeaveProcess\" isClosed=\"false\" isExecutable=\"true\" processType=\"None\">\n    <startEvent id=\"_2\" name=\"StartEvent\"/>\n    <userTask activiti:assignee=\"张三\"  activiti:exclusive=\"true\" id=\"_3\" name=\"申请请假\"/>\n    <userTask activiti:assignee=\"李四\"  activiti:exclusive=\"true\" id=\"_4\" name=\"班长审批\"/>\n    <userTask activiti:assignee=\"王五\"  activiti:exclusive=\"true\" id=\"_5\" name=\"班主任审批\"/>\n    <endEvent id=\"_6\" name=\"EndEvent\"/>\n    <sequenceFlow id=\"_7\" sourceRef=\"_2\" targetRef=\"_3\"/>\n    <sequenceFlow id=\"_8\" sourceRef=\"_3\" targetRef=\"_4\"/>\n    <sequenceFlow id=\"_9\" sourceRef=\"_4\" targetRef=\"_5\"/>\n    <sequenceFlow id=\"_10\" sourceRef=\"_5\" targetRef=\"_6\"/>\n  </process>\n  <bpmndi:BPMNDiagram documentation=\"background=#FFFFFF;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0\" id=\"Diagram-_1\" name=\"New Diagram\">\n    <bpmndi:BPMNPlane bpmnElement=\"studentLeaveProcess\">\n      <bpmndi:BPMNShape bpmnElement=\"_2\" id=\"Shape-_2\">\n        <omgdc:Bounds height=\"32.0\" width=\"32.0\" x=\"245.0\" y=\"10.0\"/>\n        <bpmndi:BPMNLabel>\n          <omgdc:Bounds height=\"32.0\" width=\"32.0\" x=\"0.0\" y=\"0.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNShape>\n      <bpmndi:BPMNShape bpmnElement=\"_3\" id=\"Shape-_3\">\n        <omgdc:Bounds height=\"55.0\" width=\"85.0\" x=\"220.0\" y=\"75.0\"/>\n        <bpmndi:BPMNLabel>\n          <omgdc:Bounds height=\"55.0\" width=\"85.0\" x=\"0.0\" y=\"0.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNShape>\n      <bpmndi:BPMNShape bpmnElement=\"_4\" id=\"Shape-_4\">\n        <omgdc:Bounds height=\"55.0\" width=\"85.0\" x=\"220.0\" y=\"160.0\"/>\n        <bpmndi:BPMNLabel>\n          <omgdc:Bounds height=\"55.0\" width=\"85.0\" x=\"0.0\" y=\"0.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNShape>\n      <bpmndi:BPMNShape bpmnElement=\"_5\" id=\"Shape-_5\">\n        <omgdc:Bounds height=\"55.0\" width=\"85.0\" x=\"220.0\" y=\"240.0\"/>\n        <bpmndi:BPMNLabel>\n          <omgdc:Bounds height=\"55.0\" width=\"85.0\" x=\"0.0\" y=\"0.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNShape>\n      <bpmndi:BPMNShape bpmnElement=\"_6\" id=\"Shape-_6\">\n        <omgdc:Bounds height=\"32.0\" width=\"32.0\" x=\"240.0\" y=\"320.0\"/>\n        <bpmndi:BPMNLabel>\n          <omgdc:Bounds height=\"32.0\" width=\"32.0\" x=\"0.0\" y=\"0.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNShape>\n      <bpmndi:BPMNEdge bpmnElement=\"_7\" id=\"BPMNEdge__7\" sourceElement=\"_2\" targetElement=\"_3\">\n        <omgdi:waypoint x=\"261.0\" y=\"42.0\"/>\n        <omgdi:waypoint x=\"261.0\" y=\"75.0\"/>\n        <bpmndi:BPMNLabel>\n          <omgdc:Bounds height=\"0.0\" width=\"0.0\" x=\"0.0\" y=\"0.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNEdge>\n      <bpmndi:BPMNEdge bpmnElement=\"_8\" id=\"BPMNEdge__8\" sourceElement=\"_3\" targetElement=\"_4\">\n        <omgdi:waypoint x=\"262.5\" y=\"130.0\"/>\n        <omgdi:waypoint x=\"262.5\" y=\"160.0\"/>\n        <bpmndi:BPMNLabel>\n          <omgdc:Bounds height=\"0.0\" width=\"0.0\" x=\"0.0\" y=\"0.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNEdge>\n      <bpmndi:BPMNEdge bpmnElement=\"_9\" id=\"BPMNEdge__9\" sourceElement=\"_4\" targetElement=\"_5\">\n        <omgdi:waypoint x=\"262.5\" y=\"215.0\"/>\n        <omgdi:waypoint x=\"262.5\" y=\"240.0\"/>\n        <bpmndi:BPMNLabel>\n          <omgdc:Bounds height=\"0.0\" width=\"0.0\" x=\"0.0\" y=\"0.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNEdge>\n      <bpmndi:BPMNEdge bpmnElement=\"_10\" id=\"BPMNEdge__10\" sourceElement=\"_5\" targetElement=\"_6\">\n        <omgdi:waypoint x=\"256.0\" y=\"295.0\"/>\n        <omgdi:waypoint x=\"256.0\" y=\"320.0\"/>\n        <bpmndi:BPMNLabel>\n          <omgdc:Bounds height=\"0.0\" width=\"0.0\" x=\"0.0\" y=\"0.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNEdge>\n    </bpmndi:BPMNPlane>\n  </bpmndi:BPMNDiagram>\n</definitions>\n"
  },
  {
    "path": "open-layui-web/src/main/resources/bpmn/leave2.bpmn",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<definitions xmlns=\"http://www.omg.org/spec/BPMN/20100524/MODEL\" xmlns:activiti=\"http://activiti.org/bpmn\" xmlns:bpmndi=\"http://www.omg.org/spec/BPMN/20100524/DI\" xmlns:omgdc=\"http://www.omg.org/spec/DD/20100524/DC\" xmlns:omgdi=\"http://www.omg.org/spec/DD/20100524/DI\" xmlns:tns=\"http://www.activiti.org/test\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" expressionLanguage=\"http://www.w3.org/1999/XPath\" id=\"m1516374578435\" name=\"\" targetNamespace=\"http://www.activiti.org/test\" typeLanguage=\"http://www.w3.org/2001/XMLSchema\">\n  <process id=\"studentLeaveProcess2\" isClosed=\"false\" isExecutable=\"true\" processType=\"None\">\n    <startEvent id=\"_2\" name=\"StartEvent\"/>\n    <userTask activiti:assignee=\"张三\" activiti:exclusive=\"true\" id=\"_3\" name=\"申请请假\"/>\n    <userTask activiti:assignee=\"李四\" activiti:exclusive=\"true\" id=\"_4\" name=\"班长审批\"/>\n    <userTask activiti:assignee=\"王五\" activiti:exclusive=\"true\" id=\"_5\" name=\"班主任审批\"/>\n    <endEvent id=\"_6\" name=\"EndEvent\"/>\n    <sequenceFlow id=\"_7\" sourceRef=\"_2\" targetRef=\"_3\"/>\n    <sequenceFlow id=\"_8\" sourceRef=\"_3\" targetRef=\"_4\"/>\n    <sequenceFlow id=\"_9\" name=\"重要情况\" sourceRef=\"_4\" targetRef=\"_5\">\n      <extensionElements>\n        <activiti:executionListener event=\"start\"/>\n      </extensionElements>\n      <conditionExpression xsi:type=\"tFormalExpression\"><![CDATA[${msg=='重要情况'}]]></conditionExpression>\n    </sequenceFlow>\n    <sequenceFlow id=\"_10\" sourceRef=\"_5\" targetRef=\"_6\"/>\n    <sequenceFlow id=\"_11\" name=\"一般情况\" sourceRef=\"_4\" targetRef=\"_6\">\n      <conditionExpression xsi:type=\"tFormalExpression\"><![CDATA[${msg=='一般情况'}]]></conditionExpression>\n    </sequenceFlow>\n  </process>\n  <bpmndi:BPMNDiagram documentation=\"background=#FFFFFF;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0\" id=\"Diagram-_1\" name=\"New Diagram\">\n    <bpmndi:BPMNPlane bpmnElement=\"studentLeaveProcess2\">\n      <bpmndi:BPMNShape bpmnElement=\"_2\" id=\"Shape-_2\">\n        <omgdc:Bounds height=\"32.0\" width=\"32.0\" x=\"245.0\" y=\"10.0\"/>\n        <bpmndi:BPMNLabel>\n          <omgdc:Bounds height=\"32.0\" width=\"32.0\" x=\"0.0\" y=\"0.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNShape>\n      <bpmndi:BPMNShape bpmnElement=\"_3\" id=\"Shape-_3\">\n        <omgdc:Bounds height=\"55.0\" width=\"85.0\" x=\"220.0\" y=\"75.0\"/>\n        <bpmndi:BPMNLabel>\n          <omgdc:Bounds height=\"55.0\" width=\"85.0\" x=\"0.0\" y=\"0.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNShape>\n      <bpmndi:BPMNShape bpmnElement=\"_4\" id=\"Shape-_4\">\n        <omgdc:Bounds height=\"55.0\" width=\"85.0\" x=\"220.0\" y=\"160.0\"/>\n        <bpmndi:BPMNLabel>\n          <omgdc:Bounds height=\"55.0\" width=\"85.0\" x=\"0.0\" y=\"0.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNShape>\n      <bpmndi:BPMNShape bpmnElement=\"_5\" id=\"Shape-_5\">\n        <omgdc:Bounds height=\"55.0\" width=\"85.0\" x=\"360.0\" y=\"245.0\"/>\n        <bpmndi:BPMNLabel>\n          <omgdc:Bounds height=\"55.0\" width=\"85.0\" x=\"0.0\" y=\"0.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNShape>\n      <bpmndi:BPMNShape bpmnElement=\"_6\" id=\"Shape-_6\">\n        <omgdc:Bounds height=\"32.0\" width=\"32.0\" x=\"245.0\" y=\"360.0\"/>\n        <bpmndi:BPMNLabel>\n          <omgdc:Bounds height=\"32.0\" width=\"32.0\" x=\"0.0\" y=\"0.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNShape>\n      <bpmndi:BPMNEdge bpmnElement=\"_7\" id=\"BPMNEdge__7\" sourceElement=\"_2\" targetElement=\"_3\">\n        <omgdi:waypoint x=\"261.0\" y=\"42.0\"/>\n        <omgdi:waypoint x=\"261.0\" y=\"75.0\"/>\n        <bpmndi:BPMNLabel>\n          <omgdc:Bounds height=\"0.0\" width=\"0.0\" x=\"0.0\" y=\"0.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNEdge>\n      <bpmndi:BPMNEdge bpmnElement=\"_8\" id=\"BPMNEdge__8\" sourceElement=\"_3\" targetElement=\"_4\">\n        <omgdi:waypoint x=\"262.5\" y=\"130.0\"/>\n        <omgdi:waypoint x=\"262.5\" y=\"160.0\"/>\n        <bpmndi:BPMNLabel>\n          <omgdc:Bounds height=\"0.0\" width=\"0.0\" x=\"0.0\" y=\"0.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNEdge>\n      <bpmndi:BPMNEdge bpmnElement=\"_9\" id=\"BPMNEdge__9\" sourceElement=\"_4\" targetElement=\"_5\">\n        <omgdi:waypoint x=\"305.0\" y=\"187.5\"/>\n        <omgdi:waypoint x=\"360.0\" y=\"272.5\"/>\n        <bpmndi:BPMNLabel>\n          <omgdc:Bounds height=\"0.0\" width=\"0.0\" x=\"0.0\" y=\"0.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNEdge>\n      <bpmndi:BPMNEdge bpmnElement=\"_11\" id=\"BPMNEdge__11\" sourceElement=\"_4\" targetElement=\"_6\">\n        <omgdi:waypoint x=\"261.0\" y=\"215.0\"/>\n        <omgdi:waypoint x=\"261.0\" y=\"360.0\"/>\n        <bpmndi:BPMNLabel>\n          <omgdc:Bounds height=\"0.0\" width=\"0.0\" x=\"0.0\" y=\"0.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNEdge>\n      <bpmndi:BPMNEdge bpmnElement=\"_10\" id=\"BPMNEdge__10\" sourceElement=\"_5\" targetElement=\"_6\">\n        <omgdi:waypoint x=\"360.0\" y=\"272.5\"/>\n        <omgdi:waypoint x=\"277.0\" y=\"376.0\"/>\n        <bpmndi:BPMNLabel>\n          <omgdc:Bounds height=\"0.0\" width=\"0.0\" x=\"0.0\" y=\"0.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNEdge>\n    </bpmndi:BPMNPlane>\n  </bpmndi:BPMNDiagram>\n</definitions>\n"
  },
  {
    "path": "open-layui-web/src/main/resources/bpmn/vacationRequest.bpmn",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<definitions xmlns=\"http://www.omg.org/spec/BPMN/20100524/MODEL\" xmlns:activiti=\"http://activiti.org/bpmn\" xmlns:bpmndi=\"http://www.omg.org/spec/BPMN/20100524/DI\" xmlns:dc=\"http://www.omg.org/spec/DD/20100524/DC\" xmlns:di=\"http://www.omg.org/spec/DD/20100524/DI\" xmlns:tns=\"http://activiti.org/bpmn20\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" expressionLanguage=\"http://www.w3.org/1999/XPath\" id=\"definitions\" name=\"\" targetNamespace=\"http://activiti.org/bpmn20\" typeLanguage=\"http://www.w3.org/2001/XMLSchema\">\n  <process id=\"vacationRequest\" isClosed=\"false\" name=\"休假请求\" processType=\"None\">\n    <startEvent activiti:initiator=\"employeeName\" id=\"request\">\n      <extensionElements>\n        <activiti:formProperty id=\"numberOfDays\" name=\"Number of days\" required=\"true\" type=\"long\" value=\"1\"/>\n        <activiti:formProperty datePattern=\"dd-MM-yyyy hh:mm\" id=\"startDate\" name=\"First day of holiday (dd-MM-yyy)\" required=\"true\" type=\"date\"/>\n        <activiti:formProperty id=\"vacationMotivation\" name=\"Motivation\" type=\"string\"/>\n      </extensionElements>\n    </startEvent>\n    <sequenceFlow id=\"flow1\" sourceRef=\"request\" targetRef=\"user1\"/>\n    <userTask activiti:candidateUsers=\"张三\" activiti:exclusive=\"true\" id=\"user1\" name=\"请假申请\">\n      <documentation id=\"handleRequest_D_1\"><![CDATA[\n        ${employeeName} would like to take ${numberOfDays} day(s) of vacation (Motivation: ${vacationMotivation}).\n      ]]></documentation>\n      <extensionElements>\n        <activiti:formProperty id=\"vacationApproved\" name=\"Do you approve this vacation\" required=\"true\" type=\"enum\">\n          <activiti:value id=\"true\" name=\"Approve\"/>\n          <activiti:value id=\"false\" name=\"Reject\"/>\n        </activiti:formProperty>\n        <activiti:formProperty id=\"managerMotivation\" name=\"Motivation\" type=\"string\"/>\n      </extensionElements>\n    </userTask>\n    <sequenceFlow id=\"flow2\" sourceRef=\"user1\" targetRef=\"requestApprovedDecision\"/>\n    <exclusiveGateway gatewayDirection=\"Unspecified\" id=\"requestApprovedDecision\" name=\"请求批准？\"/>\n    <sequenceFlow id=\"flow3\" sourceRef=\"requestApprovedDecision\" targetRef=\"sendApprovalMail\">\n      <conditionExpression xsi:type=\"tFormalExpression\"><![CDATA[${vacationApproved == 'true'}]]></conditionExpression>\n    </sequenceFlow>\n    <task activiti:exclusive=\"true\" id=\"sendApprovalMail\" name=\"通过审批\"/>\n    <sequenceFlow id=\"flow4\" sourceRef=\"sendApprovalMail\" targetRef=\"theEnd1\"/>\n    <endEvent id=\"theEnd1\"/>\n    <sequenceFlow id=\"flow5\" sourceRef=\"requestApprovedDecision\" targetRef=\"adjustVacationRequestTask\">\n      <conditionExpression xsi:type=\"tFormalExpression\"><![CDATA[${vacationApproved == 'false'}]]></conditionExpression>\n    </sequenceFlow>\n    <userTask activiti:candidateUsers=\"李四\" activiti:exclusive=\"true\" id=\"adjustVacationRequestTask\" name=\"调整请假请求\">\n      <documentation id=\"adjustVacationRequestTask_D_1\"><![CDATA[\n        Your manager has disapproved your vacation request for ${numberOfDays} days.\n        Reason: ${managerMotivation}\n      ]]></documentation>\n      <extensionElements>\n        <activiti:formProperty id=\"numberOfDays\" name=\"Number of days\" required=\"true\" type=\"long\" value=\"${numberOfDays}\"/>\n        <activiti:formProperty datePattern=\"dd-MM-yyyy hh:mm\" id=\"startDate\" name=\"First day of holiday (dd-MM-yyy)\" required=\"true\" type=\"date\" value=\"${startDate}\"/>\n        <activiti:formProperty id=\"vacationMotivation\" name=\"Motivation\" type=\"string\" value=\"${vacationMotivation}\"/>\n        <activiti:formProperty id=\"resendRequest\" name=\"Resend vacation request to manager?\" required=\"true\" type=\"enum\">\n          <activiti:value id=\"true\" name=\"Yes\"/>\n          <activiti:value id=\"false\" name=\"No\"/>\n        </activiti:formProperty>\n      </extensionElements>\n    </userTask>\n    <sequenceFlow id=\"flow6\" sourceRef=\"adjustVacationRequestTask\" targetRef=\"resendRequestDecision\"/>\n    <exclusiveGateway gatewayDirection=\"Unspecified\" id=\"resendRequestDecision\" name=\"重新请求？\"/>\n    <sequenceFlow id=\"flow7\" sourceRef=\"resendRequestDecision\" targetRef=\"user1\">\n      <conditionExpression xsi:type=\"tFormalExpression\"><![CDATA[${resendRequest == 'true'}]]></conditionExpression>\n    </sequenceFlow>\n    <sequenceFlow id=\"flow8\" sourceRef=\"resendRequestDecision\" targetRef=\"theEnd2\">\n      <conditionExpression xsi:type=\"tFormalExpression\"><![CDATA[${resendRequest == 'false'}]]></conditionExpression>\n    </sequenceFlow>\n    <endEvent id=\"theEnd2\"/>\n  </process>\n  <bpmndi:BPMNDiagram documentation=\"background=#FFFFFF;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0\" id=\"Diagram-_1\" name=\"New Diagram\">\n    <bpmndi:BPMNPlane bpmnElement=\"vacationRequest\">\n      <bpmndi:BPMNShape bpmnElement=\"theEnd2\" id=\"Shape-theEnd2\">\n        <dc:Bounds height=\"32.0\" width=\"32.0\" x=\"772.0\" y=\"270.5\"/>\n        <bpmndi:BPMNLabel>\n          <dc:Bounds height=\"32.0\" width=\"32.0\" x=\"0.0\" y=\"0.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNShape>\n      <bpmndi:BPMNShape bpmnElement=\"resendRequestDecision\" id=\"Shape-resendRequestDecision\" isMarkerVisible=\"false\">\n        <dc:Bounds height=\"32.0\" width=\"32.0\" x=\"680.0\" y=\"270.5\"/>\n        <bpmndi:BPMNLabel>\n          <dc:Bounds height=\"32.0\" width=\"32.0\" x=\"0.0\" y=\"0.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNShape>\n      <bpmndi:BPMNShape bpmnElement=\"adjustVacationRequestTask\" id=\"Shape-adjustVacationRequestTask\">\n        <dc:Bounds height=\"55.0\" width=\"85.0\" x=\"485.0\" y=\"260.0\"/>\n        <bpmndi:BPMNLabel>\n          <dc:Bounds height=\"55.0\" width=\"85.0\" x=\"0.0\" y=\"0.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNShape>\n      <bpmndi:BPMNShape bpmnElement=\"theEnd1\" id=\"Shape-theEnd1\">\n        <dc:Bounds height=\"32.0\" width=\"32.0\" x=\"665.0\" y=\"145.5\"/>\n        <bpmndi:BPMNLabel>\n          <dc:Bounds height=\"32.0\" width=\"32.0\" x=\"0.0\" y=\"0.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNShape>\n      <bpmndi:BPMNShape bpmnElement=\"sendApprovalMail\" id=\"Shape-sendApprovalMail\">\n        <dc:Bounds height=\"55.0\" width=\"85.0\" x=\"475.0\" y=\"135.0\"/>\n        <bpmndi:BPMNLabel>\n          <dc:Bounds height=\"55.0\" width=\"85.0\" x=\"0.0\" y=\"0.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNShape>\n      <bpmndi:BPMNShape bpmnElement=\"requestApprovedDecision\" id=\"Shape-requestApprovedDecision\" isMarkerVisible=\"false\">\n        <dc:Bounds height=\"32.0\" width=\"32.0\" x=\"285.0\" y=\"200.0\"/>\n        <bpmndi:BPMNLabel>\n          <dc:Bounds height=\"32.0\" width=\"32.0\" x=\"0.0\" y=\"0.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNShape>\n      <bpmndi:BPMNShape bpmnElement=\"user1\" id=\"Shape-user1\">\n        <dc:Bounds height=\"55.0\" width=\"85.0\" x=\"112.0\" y=\"188.5\"/>\n        <bpmndi:BPMNLabel>\n          <dc:Bounds height=\"55.0\" width=\"85.0\" x=\"0.0\" y=\"0.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNShape>\n      <bpmndi:BPMNShape bpmnElement=\"request\" id=\"Shape-request\">\n        <dc:Bounds height=\"32.0\" width=\"32.0\" x=\"20.0\" y=\"200.0\"/>\n        <bpmndi:BPMNLabel>\n          <dc:Bounds height=\"32.0\" width=\"32.0\" x=\"0.0\" y=\"0.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNShape>\n      <bpmndi:BPMNEdge bpmnElement=\"flow1\" id=\"BPMNEdge_flow1\" sourceElement=\"request\" targetElement=\"user1\">\n        <di:waypoint x=\"52.0\" y=\"216.0\"/>\n        <di:waypoint x=\"112.0\" y=\"216.0\"/>\n        <bpmndi:BPMNLabel>\n          <dc:Bounds height=\"-1.0\" width=\"-1.0\" x=\"-1.0\" y=\"-1.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNEdge>\n      <bpmndi:BPMNEdge bpmnElement=\"flow2\" id=\"BPMNEdge_flow2\" sourceElement=\"user1\" targetElement=\"requestApprovedDecision\">\n        <di:waypoint x=\"197.0\" y=\"216.0\"/>\n        <di:waypoint x=\"285.0\" y=\"216.0\"/>\n        <bpmndi:BPMNLabel>\n          <dc:Bounds height=\"-1.0\" width=\"-1.0\" x=\"-1.0\" y=\"-1.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNEdge>\n      <bpmndi:BPMNEdge bpmnElement=\"flow3\" id=\"BPMNEdge_flow3\" sourceElement=\"requestApprovedDecision\" targetElement=\"sendApprovalMail\">\n        <di:waypoint x=\"300.0\" y=\"201.0\"/>\n        <di:waypoint x=\"300.0\" y=\"150.0\"/>\n        <di:waypoint x=\"475.0\" y=\"150.0\"/>\n        <bpmndi:BPMNLabel>\n          <dc:Bounds height=\"-1.0\" width=\"-1.0\" x=\"-1.0\" y=\"-1.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNEdge>\n      <bpmndi:BPMNEdge bpmnElement=\"flow4\" id=\"BPMNEdge_flow4\" sourceElement=\"sendApprovalMail\" targetElement=\"theEnd1\">\n        <di:waypoint x=\"560.0\" y=\"162.5\"/>\n        <di:waypoint x=\"665.0078144082805\" y=\"161.5\"/>\n        <bpmndi:BPMNLabel>\n          <dc:Bounds height=\"-1.0\" width=\"-1.0\" x=\"-1.0\" y=\"-1.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNEdge>\n      <bpmndi:BPMNEdge bpmnElement=\"flow5\" id=\"BPMNEdge_flow5\" sourceElement=\"requestApprovedDecision\" targetElement=\"adjustVacationRequestTask\">\n        <di:waypoint x=\"305.0\" y=\"228.0\"/>\n        <di:waypoint x=\"305.0\" y=\"285.0\"/>\n        <di:waypoint x=\"485.0\" y=\"285.0\"/>\n        <bpmndi:BPMNLabel>\n          <dc:Bounds height=\"-1.0\" width=\"-1.0\" x=\"-1.0\" y=\"-1.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNEdge>\n      <bpmndi:BPMNEdge bpmnElement=\"flow6\" id=\"BPMNEdge_flow6\" sourceElement=\"adjustVacationRequestTask\" targetElement=\"resendRequestDecision\">\n        <di:waypoint x=\"570.0\" y=\"287.5\"/>\n        <di:waypoint x=\"680.5\" y=\"286.5\"/>\n        <bpmndi:BPMNLabel>\n          <dc:Bounds height=\"-1.0\" width=\"-1.0\" x=\"-1.0\" y=\"-1.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNEdge>\n      <bpmndi:BPMNEdge bpmnElement=\"flow7\" id=\"BPMNEdge_flow7\" sourceElement=\"resendRequestDecision\" targetElement=\"user1\">\n        <di:waypoint x=\"696.0\" y=\"303.0\"/>\n        <di:waypoint x=\"285.0\" y=\"335.0\"/>\n        <di:waypoint x=\"154.5\" y=\"244.0\"/>\n        <bpmndi:BPMNLabel>\n          <dc:Bounds height=\"-1.0\" width=\"-1.0\" x=\"-1.0\" y=\"-1.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNEdge>\n      <bpmndi:BPMNEdge bpmnElement=\"flow8\" id=\"BPMNEdge_flow8\" sourceElement=\"resendRequestDecision\" targetElement=\"theEnd2\">\n        <di:waypoint x=\"711.5\" y=\"286.5\"/>\n        <di:waypoint x=\"772.0078144082805\" y=\"286.5\"/>\n        <bpmndi:BPMNLabel>\n          <dc:Bounds height=\"-1.0\" width=\"-1.0\" x=\"-1.0\" y=\"-1.0\"/>\n        </bpmndi:BPMNLabel>\n      </bpmndi:BPMNEdge>\n    </bpmndi:BPMNPlane>\n  </bpmndi:BPMNDiagram>\n</definitions>\n"
  },
  {
    "path": "open-layui-web/src/main/resources/db/boot_security.sql",
    "content": "CREATE DATABASE IF NOT EXISTS `boot_security` DEFAULT CHARACTER SET = utf8mb4;\n\nUse `boot_security`;\n\nset session  \nsql_mode='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';  \n\nSET FOREIGN_KEY_CHECKS=0;\n\n\n# Host: 192.168.3.150  (Version 5.7.22)\n# Date: 2018-06-24 11:52:30\n# Generator: MySQL-Front 5.4  (Build 4.153) - http://www.mysqlfront.de/\n\n/*!40101 SET NAMES utf8 */;\n\n#\n# Structure for table \"act_assignee\"\n#\n\nDROP TABLE IF EXISTS `act_assignee`;\nCREATE TABLE `act_assignee` (\n  `id` varchar(32) NOT NULL,\n  `sid` varchar(32) NOT NULL COMMENT '节点id',\n  `assignee` varchar(64) DEFAULT NULL COMMENT '办理人',\n  `role_id` varchar(32) DEFAULT NULL COMMENT '候选组(角色)',\n  `assignee_type` int(11) NOT NULL COMMENT '办理人类型1办理人2候选人3组',\n  `activti_name` varchar(128) DEFAULT NULL COMMENT '节点名称',\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\n#\n# Data for table \"act_assignee\"\n#\n\n\n#\n# Structure for table \"act_evt_log\"\n#\n\nDROP TABLE IF EXISTS `act_evt_log`;\nCREATE TABLE `act_evt_log` (\n  `LOG_NR_` bigint(20) NOT NULL AUTO_INCREMENT,\n  `TYPE_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `PROC_DEF_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `EXECUTION_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `TASK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `TIME_STAMP_` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),\n  `USER_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `DATA_` longblob,\n  `LOCK_OWNER_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `LOCK_TIME_` timestamp(3) NULL DEFAULT NULL,\n  `IS_PROCESSED_` tinyint(4) DEFAULT '0',\n  PRIMARY KEY (`LOG_NR_`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;\n\n#\n# Data for table \"act_evt_log\"\n#\n\n\n#\n# Structure for table \"act_ge_property\"\n#\n\nDROP TABLE IF EXISTS `act_ge_property`;\nCREATE TABLE `act_ge_property` (\n  `NAME_` varchar(64) COLLATE utf8_bin NOT NULL,\n  `VALUE_` varchar(300) COLLATE utf8_bin DEFAULT NULL,\n  `REV_` int(11) DEFAULT NULL,\n  PRIMARY KEY (`NAME_`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;\n\n#\n# Data for table \"act_ge_property\"\n#\n\nINSERT INTO `act_ge_property` VALUES ('next.dbid','215001',87),('schema.history','create(5.22.0.0)',1),('schema.version','5.22.0.0',1);\n\n#\n# Structure for table \"act_hi_actinst\"\n#\n\nDROP TABLE IF EXISTS `act_hi_actinst`;\nCREATE TABLE `act_hi_actinst` (\n  `ID_` varchar(64) COLLATE utf8_bin NOT NULL,\n  `PROC_DEF_ID_` varchar(64) COLLATE utf8_bin NOT NULL,\n  `PROC_INST_ID_` varchar(64) COLLATE utf8_bin NOT NULL,\n  `EXECUTION_ID_` varchar(64) COLLATE utf8_bin NOT NULL,\n  `ACT_ID_` varchar(255) COLLATE utf8_bin NOT NULL,\n  `TASK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `CALL_PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `ACT_NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `ACT_TYPE_` varchar(255) COLLATE utf8_bin NOT NULL,\n  `ASSIGNEE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `START_TIME_` datetime(3) NOT NULL,\n  `END_TIME_` datetime(3) DEFAULT NULL,\n  `DURATION_` bigint(20) DEFAULT NULL,\n  `TENANT_ID_` varchar(255) COLLATE utf8_bin DEFAULT '',\n  PRIMARY KEY (`ID_`),\n  KEY `ACT_IDX_HI_ACT_INST_START` (`START_TIME_`),\n  KEY `ACT_IDX_HI_ACT_INST_END` (`END_TIME_`),\n  KEY `ACT_IDX_HI_ACT_INST_PROCINST` (`PROC_INST_ID_`,`ACT_ID_`),\n  KEY `ACT_IDX_HI_ACT_INST_EXEC` (`EXECUTION_ID_`,`ACT_ID_`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;\n\n#\n# Data for table \"act_hi_actinst\"\n#\n\nINSERT INTO `act_hi_actinst` VALUES ('122506','leave_process:1:120011','122505','122505','start',NULL,NULL,'start','startEvent',NULL,'2018-01-24 23:06:38.000','2018-01-24 23:06:38.000',67,''),('122507','leave_process:1:120011','122505','122505','user1','122508',NULL,'经理审批','userTask',NULL,'2018-01-24 23:06:38.000',NULL,NULL,''),('130010','leave_process:1:120011','130009','130009','start',NULL,NULL,'start','startEvent',NULL,'2018-01-24 23:47:12.000','2018-01-24 23:47:12.000',3,''),('130011','leave_process:1:120011','130009','130009','user1','130012',NULL,'经理审批','userTask',NULL,'2018-01-24 23:47:12.000',NULL,NULL,''),('130015','leave_process:1:120011','130014','130014','start',NULL,NULL,'start','startEvent',NULL,'2018-01-24 23:50:10.000','2018-01-24 23:50:10.000',1,''),('130016','leave_process:1:120011','130014','130014','user1','130017',NULL,'经理审批','userTask',NULL,'2018-01-24 23:50:10.000',NULL,NULL,''),('130020','leave_process:1:120011','130019','130019','start',NULL,NULL,'start','startEvent',NULL,'2018-01-24 23:52:30.000','2018-01-24 23:52:30.000',7,''),('130024','leave_process:1:120011','130019','130019','user1','130025',NULL,'经理审批','userTask',NULL,'2018-01-24 23:52:30.000',NULL,NULL,'');\n\n#\n# Structure for table \"act_hi_attachment\"\n#\n\nDROP TABLE IF EXISTS `act_hi_attachment`;\nCREATE TABLE `act_hi_attachment` (\n  `ID_` varchar(64) COLLATE utf8_bin NOT NULL,\n  `REV_` int(11) DEFAULT NULL,\n  `USER_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `DESCRIPTION_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,\n  `TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `TASK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `URL_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,\n  `CONTENT_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `TIME_` datetime(3) DEFAULT NULL,\n  PRIMARY KEY (`ID_`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;\n\n#\n# Data for table \"act_hi_attachment\"\n#\n\n\n#\n# Structure for table \"act_hi_comment\"\n#\n\nDROP TABLE IF EXISTS `act_hi_comment`;\nCREATE TABLE `act_hi_comment` (\n  `ID_` varchar(64) COLLATE utf8_bin NOT NULL,\n  `TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `TIME_` datetime(3) NOT NULL,\n  `USER_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `TASK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `ACTION_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `MESSAGE_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,\n  `FULL_MSG_` longblob,\n  PRIMARY KEY (`ID_`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;\n\n#\n# Data for table \"act_hi_comment\"\n#\n\n\n#\n# Structure for table \"act_hi_detail\"\n#\n\nDROP TABLE IF EXISTS `act_hi_detail`;\nCREATE TABLE `act_hi_detail` (\n  `ID_` varchar(64) COLLATE utf8_bin NOT NULL,\n  `TYPE_` varchar(255) COLLATE utf8_bin NOT NULL,\n  `PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `EXECUTION_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `TASK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `ACT_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `NAME_` varchar(255) COLLATE utf8_bin NOT NULL,\n  `VAR_TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `REV_` int(11) DEFAULT NULL,\n  `TIME_` datetime(3) NOT NULL,\n  `BYTEARRAY_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `DOUBLE_` double DEFAULT NULL,\n  `LONG_` bigint(20) DEFAULT NULL,\n  `TEXT_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,\n  `TEXT2_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,\n  PRIMARY KEY (`ID_`),\n  KEY `ACT_IDX_HI_DETAIL_PROC_INST` (`PROC_INST_ID_`),\n  KEY `ACT_IDX_HI_DETAIL_ACT_INST` (`ACT_INST_ID_`),\n  KEY `ACT_IDX_HI_DETAIL_TIME` (`TIME_`),\n  KEY `ACT_IDX_HI_DETAIL_NAME` (`NAME_`),\n  KEY `ACT_IDX_HI_DETAIL_TASK_ID` (`TASK_ID_`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;\n\n#\n# Data for table \"act_hi_detail\"\n#\n\n\n#\n# Structure for table \"act_hi_identitylink\"\n#\n\nDROP TABLE IF EXISTS `act_hi_identitylink`;\nCREATE TABLE `act_hi_identitylink` (\n  `ID_` varchar(64) COLLATE utf8_bin NOT NULL,\n  `GROUP_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `USER_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `TASK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  PRIMARY KEY (`ID_`),\n  KEY `ACT_IDX_HI_IDENT_LNK_USER` (`USER_ID_`),\n  KEY `ACT_IDX_HI_IDENT_LNK_TASK` (`TASK_ID_`),\n  KEY `ACT_IDX_HI_IDENT_LNK_PROCINST` (`PROC_INST_ID_`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;\n\n#\n# Data for table \"act_hi_identitylink\"\n#\n\nINSERT INTO `act_hi_identitylink` VALUES ('130013','0ea934e5e55411e7b983201a068c6482','candidate',NULL,'130012',NULL),('130018','0ea934e5e55411e7b983201a068c6482','candidate',NULL,'130017',NULL),('130026','0ea934e5e55411e7b983201a068c6482','candidate',NULL,'130025',NULL);\n\n#\n# Structure for table \"act_hi_procinst\"\n#\n\nDROP TABLE IF EXISTS `act_hi_procinst`;\nCREATE TABLE `act_hi_procinst` (\n  `ID_` varchar(64) COLLATE utf8_bin NOT NULL,\n  `PROC_INST_ID_` varchar(64) COLLATE utf8_bin NOT NULL,\n  `BUSINESS_KEY_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `PROC_DEF_ID_` varchar(64) COLLATE utf8_bin NOT NULL,\n  `START_TIME_` datetime(3) NOT NULL,\n  `END_TIME_` datetime(3) DEFAULT NULL,\n  `DURATION_` bigint(20) DEFAULT NULL,\n  `START_USER_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `START_ACT_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `END_ACT_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `SUPER_PROCESS_INSTANCE_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `DELETE_REASON_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,\n  `TENANT_ID_` varchar(255) COLLATE utf8_bin DEFAULT '',\n  `NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  PRIMARY KEY (`ID_`),\n  UNIQUE KEY `PROC_INST_ID_` (`PROC_INST_ID_`),\n  KEY `ACT_IDX_HI_PRO_INST_END` (`END_TIME_`),\n  KEY `ACT_IDX_HI_PRO_I_BUSKEY` (`BUSINESS_KEY_`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;\n\n#\n# Data for table \"act_hi_procinst\"\n#\n\nINSERT INTO `act_hi_procinst` VALUES ('122505','122505',NULL,'leave_process:1:120011','2018-01-24 23:06:38.000',NULL,NULL,NULL,'start',NULL,NULL,NULL,'',NULL),('130009','130009',NULL,'leave_process:1:120011','2018-01-24 23:47:12.000',NULL,NULL,NULL,'start',NULL,NULL,NULL,'',NULL),('130014','130014',NULL,'leave_process:1:120011','2018-01-24 23:50:10.000',NULL,NULL,NULL,'start',NULL,NULL,NULL,'',NULL),('130019','130019',NULL,'leave_process:1:120011','2018-01-24 23:52:30.000',NULL,NULL,NULL,'start',NULL,NULL,NULL,'',NULL);\n\n#\n# Structure for table \"act_hi_taskinst\"\n#\n\nDROP TABLE IF EXISTS `act_hi_taskinst`;\nCREATE TABLE `act_hi_taskinst` (\n  `ID_` varchar(64) COLLATE utf8_bin NOT NULL,\n  `PROC_DEF_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `TASK_DEF_KEY_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `EXECUTION_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `PARENT_TASK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `DESCRIPTION_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,\n  `OWNER_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `ASSIGNEE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `START_TIME_` datetime(3) NOT NULL,\n  `CLAIM_TIME_` datetime(3) DEFAULT NULL,\n  `END_TIME_` datetime(3) DEFAULT NULL,\n  `DURATION_` bigint(20) DEFAULT NULL,\n  `DELETE_REASON_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,\n  `PRIORITY_` int(11) DEFAULT NULL,\n  `DUE_DATE_` datetime(3) DEFAULT NULL,\n  `FORM_KEY_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `CATEGORY_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `TENANT_ID_` varchar(255) COLLATE utf8_bin DEFAULT '',\n  PRIMARY KEY (`ID_`),\n  KEY `ACT_IDX_HI_TASK_INST_PROCINST` (`PROC_INST_ID_`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;\n\n#\n# Data for table \"act_hi_taskinst\"\n#\n\nINSERT INTO `act_hi_taskinst` VALUES ('122508','leave_process:1:120011','user1','122505','122505','经理审批',NULL,NULL,NULL,NULL,'2018-01-24 23:06:38.000',NULL,NULL,NULL,NULL,50,NULL,NULL,NULL,''),('130012','leave_process:1:120011','user1','130009','130009','经理审批',NULL,NULL,NULL,NULL,'2018-01-24 23:47:12.000',NULL,NULL,NULL,NULL,50,NULL,NULL,NULL,''),('130017','leave_process:1:120011','user1','130014','130014','经理审批',NULL,NULL,NULL,NULL,'2018-01-24 23:50:10.000',NULL,NULL,NULL,NULL,50,NULL,NULL,NULL,''),('130025','leave_process:1:120011','user1','130019','130019','经理审批',NULL,NULL,NULL,NULL,'2018-01-24 23:52:30.000',NULL,NULL,NULL,NULL,50,NULL,NULL,NULL,'');\n\n#\n# Structure for table \"act_hi_varinst\"\n#\n\nDROP TABLE IF EXISTS `act_hi_varinst`;\nCREATE TABLE `act_hi_varinst` (\n  `ID_` varchar(64) COLLATE utf8_bin NOT NULL,\n  `PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `EXECUTION_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `TASK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `NAME_` varchar(255) COLLATE utf8_bin NOT NULL,\n  `VAR_TYPE_` varchar(100) COLLATE utf8_bin DEFAULT NULL,\n  `REV_` int(11) DEFAULT NULL,\n  `BYTEARRAY_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `DOUBLE_` double DEFAULT NULL,\n  `LONG_` bigint(20) DEFAULT NULL,\n  `TEXT_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,\n  `TEXT2_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,\n  `CREATE_TIME_` datetime(3) DEFAULT NULL,\n  `LAST_UPDATED_TIME_` datetime(3) DEFAULT NULL,\n  PRIMARY KEY (`ID_`),\n  KEY `ACT_IDX_HI_PROCVAR_PROC_INST` (`PROC_INST_ID_`),\n  KEY `ACT_IDX_HI_PROCVAR_NAME_TYPE` (`NAME_`,`VAR_TYPE_`),\n  KEY `ACT_IDX_HI_PROCVAR_TASK_ID` (`TASK_ID_`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;\n\n#\n# Data for table \"act_hi_varinst\"\n#\n\nINSERT INTO `act_hi_varinst` VALUES ('130022','130019','130019',NULL,'userLeave','serializable',0,'130023',NULL,NULL,NULL,NULL,'2018-01-24 23:52:30.000','2018-01-24 23:52:30.000');\n\n#\n# Structure for table \"act_id_group\"\n#\n\nDROP TABLE IF EXISTS `act_id_group`;\nCREATE TABLE `act_id_group` (\n  `ID_` varchar(64) COLLATE utf8_bin NOT NULL,\n  `REV_` int(11) DEFAULT NULL,\n  `NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  PRIMARY KEY (`ID_`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;\n\n#\n# Data for table \"act_id_group\"\n#\n\nINSERT INTO `act_id_group` VALUES ('023366f3457511e8bcf1309c2315f9aa',1,'hr',NULL),('0ea934e5e55411e7b983201a068c6482',1,'manage',NULL),('2619a672e53811e7b983201a068c6482',1,'admin',NULL),('dcb0f642fe9611e7b472201a068c6482',1,'dev',NULL);\n\n#\n# Structure for table \"act_id_info\"\n#\n\nDROP TABLE IF EXISTS `act_id_info`;\nCREATE TABLE `act_id_info` (\n  `ID_` varchar(64) COLLATE utf8_bin NOT NULL,\n  `REV_` int(11) DEFAULT NULL,\n  `USER_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `TYPE_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `KEY_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `VALUE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `PASSWORD_` longblob,\n  `PARENT_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  PRIMARY KEY (`ID_`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;\n\n#\n# Data for table \"act_id_info\"\n#\n\n\n#\n# Structure for table \"act_id_user\"\n#\n\nDROP TABLE IF EXISTS `act_id_user`;\nCREATE TABLE `act_id_user` (\n  `ID_` varchar(64) COLLATE utf8_bin NOT NULL,\n  `REV_` int(11) DEFAULT NULL,\n  `FIRST_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `LAST_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `EMAIL_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `PWD_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `PICTURE_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  PRIMARY KEY (`ID_`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;\n\n#\n# Data for table \"act_id_user\"\n#\n\nINSERT INTO `act_id_user` VALUES ('2211fec3e17c11e795ed201a068c6482',1,'Tom Curise',NULL,'154040976@qq.com',NULL,NULL),('51d2179c457911e8bcf1309c2315f9aa',1,'333',NULL,'',NULL,NULL),('5354d45a018311e8a1a2201a068c6482',1,'111',NULL,'',NULL,NULL),('6a038f15019711e8a1a2201a068c6482',1,'张三',NULL,'',NULL,NULL),('a4a743bffe9711e7b472201a068c6482',1,'zxm',NULL,'1544040976@qq.com',NULL,NULL),('acfc0e9232f54732a5d9ffe9071bf572',1,'管理员',NULL,'',NULL,NULL),('c7f1a7d7018311e8a1a2201a068c6482',1,'666',NULL,'',NULL,NULL),('ce1f6f35018211e8a1a2201a068c6482',1,'123',NULL,'',NULL,NULL);\n\n#\n# Structure for table \"act_id_membership\"\n#\n\nDROP TABLE IF EXISTS `act_id_membership`;\nCREATE TABLE `act_id_membership` (\n  `USER_ID_` varchar(64) COLLATE utf8_bin NOT NULL,\n  `GROUP_ID_` varchar(64) COLLATE utf8_bin NOT NULL,\n  PRIMARY KEY (`USER_ID_`,`GROUP_ID_`),\n  KEY `ACT_FK_MEMB_GROUP` (`GROUP_ID_`),\n  CONSTRAINT `ACT_FK_MEMB_GROUP` FOREIGN KEY (`GROUP_ID_`) REFERENCES `act_id_group` (`ID_`),\n  CONSTRAINT `ACT_FK_MEMB_USER` FOREIGN KEY (`USER_ID_`) REFERENCES `act_id_user` (`ID_`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;\n\n#\n# Data for table \"act_id_membership\"\n#\n\nINSERT INTO `act_id_membership` VALUES ('2211fec3e17c11e795ed201a068c6482','0ea934e5e55411e7b983201a068c6482'),('51d2179c457911e8bcf1309c2315f9aa','023366f3457511e8bcf1309c2315f9aa'),('5354d45a018311e8a1a2201a068c6482','dcb0f642fe9611e7b472201a068c6482'),('6a038f15019711e8a1a2201a068c6482','dcb0f642fe9611e7b472201a068c6482'),('a4a743bffe9711e7b472201a068c6482','dcb0f642fe9611e7b472201a068c6482'),('acfc0e9232f54732a5d9ffe9071bf572','2619a672e53811e7b983201a068c6482'),('c7f1a7d7018311e8a1a2201a068c6482','dcb0f642fe9611e7b472201a068c6482');\n\n#\n# Structure for table \"act_re_deployment\"\n#\n\nDROP TABLE IF EXISTS `act_re_deployment`;\nCREATE TABLE `act_re_deployment` (\n  `ID_` varchar(64) COLLATE utf8_bin NOT NULL,\n  `NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `CATEGORY_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `TENANT_ID_` varchar(255) COLLATE utf8_bin DEFAULT '',\n  `DEPLOY_TIME_` timestamp(3) NULL DEFAULT NULL,\n  PRIMARY KEY (`ID_`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;\n\n#\n# Data for table \"act_re_deployment\"\n#\n\nINSERT INTO `act_re_deployment` VALUES ('212503','请假流程',NULL,'','2018-05-17 21:11:56.283');\n\n#\n# Structure for table \"act_ge_bytearray\"\n#\n\nDROP TABLE IF EXISTS `act_ge_bytearray`;\nCREATE TABLE `act_ge_bytearray` (\n  `ID_` varchar(64) COLLATE utf8_bin NOT NULL,\n  `REV_` int(11) DEFAULT NULL,\n  `NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `DEPLOYMENT_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `BYTES_` longblob,\n  `GENERATED_` tinyint(4) DEFAULT NULL,\n  PRIMARY KEY (`ID_`),\n  KEY `ACT_FK_BYTEARR_DEPL` (`DEPLOYMENT_ID_`),\n  CONSTRAINT `ACT_FK_BYTEARR_DEPL` FOREIGN KEY (`DEPLOYMENT_ID_`) REFERENCES `act_re_deployment` (`ID_`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;\n\n#\n# Data for table \"act_ge_bytearray\"\n#\n\nINSERT INTO `act_ge_bytearray` VALUES ('142518',9,'source',NULL,X'7B227265736F757263654964223A22313432353137222C2270726F70657274696573223A7B2270726F636573735F6964223A2270726F636573735F6C65617665222C226E616D65223A22E8AFB7E58187E6B581E7A88B222C22646F63756D656E746174696F6E223A22222C2270726F636573735F617574686F72223A22222C2270726F636573735F76657273696F6E223A22222C2270726F636573735F6E616D657370616365223A22687474703A2F2F7777772E61637469766974692E6F72672F70726F63657373646566222C22657865637574696F6E6C697374656E657273223A22222C226576656E746C697374656E657273223A22222C227369676E616C646566696E6974696F6E73223A22222C226D657373616765646566696E6974696F6E73223A22222C22636F6E646974696F6E73657175656E6365666C6F77223A22247B666C61673D3D747275657D227D2C227374656E63696C223A7B226964223A2242504D4E4469616772616D227D2C226368696C64536861706573223A5B7B227265736F757263654964223A227369642D41343530344644322D303230342D343246352D393036312D344134323938324442343938222C2270726F70657274696573223A7B226F766572726964656964223A227374617274222C226E616D65223A227374617274222C22646F63756D656E746174696F6E223A22222C22657865637574696F6E6C697374656E657273223A22222C22696E69746961746F72223A22222C22666F726D6B6579646566696E6974696F6E223A22222C22666F726D70726F70657274696573223A22227D2C227374656E63696C223A7B226964223A2253746172744E6F6E654576656E74227D2C226368696C64536861706573223A5B5D2C226F7574676F696E67223A5B7B227265736F757263654964223A227369642D30443235384332342D314631392D343233332D413937362D413044384342394441454143227D5D2C22626F756E6473223A7B226C6F7765725269676874223A7B2278223A37352C2279223A38342E39393939393733353039303436347D2C2275707065724C656674223A7B2278223A34352E30303030303030303030303030312C2279223A35342E39393939393733353039303436337D7D2C22646F636B657273223A5B5D7D2C7B227265736F757263654964223A227369642D34363841393635452D393339422D343733312D413232392D353137384436413042423834222C2270726F70657274696573223A7B226F766572726964656964223A227573657231222C226E616D65223A22E7BB8FE79086E5AEA1E689B9222C22646F63756D656E746174696F6E223A22222C226173796E6368726F6E6F7573646566696E6974696F6E223A2266616C7365222C226578636C7573697665646566696E6974696F6E223A2266616C7365222C22657865637574696F6E6C697374656E657273223A22222C226D756C7469696E7374616E63655F74797065223A224E6F6E65222C226D756C7469696E7374616E63655F63617264696E616C697479223A22222C226D756C7469696E7374616E63655F636F6C6C656374696F6E223A22222C226D756C7469696E7374616E63655F7661726961626C65223A22222C226D756C7469696E7374616E63655F636F6E646974696F6E223A22222C226973666F72636F6D70656E736174696F6E223A2266616C7365222C22757365727461736B61737369676E6D656E74223A22222C22666F726D6B6579646566696E6974696F6E223A22222C2264756564617465646566696E6974696F6E223A22222C227072696F72697479646566696E6974696F6E223A22222C22666F726D70726F70657274696573223A22222C227461736B6C697374656E657273223A7B227461736B4C697374656E657273223A5B7B226576656E74223A22637265617465222C22696D706C656D656E746174696F6E223A22636F6D2E6C656E2E6163746C697374656E65722E4163744E6F64654C697374656E6572222C22636C6173734E616D65223A22636F6D2E6C656E2E6163746C697374656E65722E4163744E6F64654C697374656E6572222C2265787072657373696F6E223A22222C2264656C656761746545787072657373696F6E223A22227D5D7D7D2C227374656E63696C223A7B226964223A22557365725461736B227D2C226368696C64536861706573223A5B5D2C226F7574676F696E67223A5B7B227265736F757263654964223A227369642D35343537313339312D463242332D344342342D383041302D303932444130323737334137227D5D2C22626F756E6473223A7B226C6F7765725269676874223A7B2278223A3235302C2279223A3130392E39393939393733353039303436347D2C2275707065724C656674223A7B2278223A3135302E30303030303030303030303030332C2279223A32392E39393939393733353039303436347D7D2C22646F636B657273223A5B5D7D2C7B227265736F757263654964223A227369642D30443235384332342D314631392D343233332D413937362D413044384342394441454143222C2270726F70657274696573223A7B226F766572726964656964223A22222C226E616D65223A22222C22646F63756D656E746174696F6E223A22222C22636F6E646974696F6E73657175656E6365666C6F77223A22222C22657865637574696F6E6C697374656E657273223A22222C2264656661756C74666C6F77223A2266616C7365227D2C227374656E63696C223A7B226964223A2253657175656E6365466C6F77227D2C226368696C64536861706573223A5B5D2C226F7574676F696E67223A5B7B227265736F757263654964223A227369642D34363841393635452D393339422D343733312D413232392D353137384436413042423834227D5D2C22626F756E6473223A7B226C6F7765725269676874223A7B2278223A3134392E37383132352C2279223A36392E39393939393733353039303436347D2C2275707065724C656674223A7B2278223A37352E32313837352C2279223A36392E39393939393733353039303436347D7D2C22646F636B657273223A5B7B2278223A31342E3939393939393939393939393939362C2279223A31357D2C7B2278223A34392E3939393939393939393939393938362C2279223A34307D5D2C22746172676574223A7B227265736F757263654964223A227369642D34363841393635452D393339422D343733312D413232392D353137384436413042423834227D7D2C7B227265736F757263654964223A227369642D37363845453443392D333233432D343744422D423438302D344230323746333136433835222C2270726F70657274696573223A7B226F766572726964656964223A227573657232222C226E616D65223A22E4BABAE4BA8BE5AEA1E689B9222C22646F63756D656E746174696F6E223A22222C226173796E6368726F6E6F7573646566696E6974696F6E223A2266616C7365222C226578636C7573697665646566696E6974696F6E223A2266616C7365222C22657865637574696F6E6C697374656E657273223A22222C226D756C7469696E7374616E63655F74797065223A224E6F6E65222C226D756C7469696E7374616E63655F63617264696E616C697479223A22222C226D756C7469696E7374616E63655F636F6C6C656374696F6E223A22222C226D756C7469696E7374616E63655F7661726961626C65223A22222C226D756C7469696E7374616E63655F636F6E646974696F6E223A22222C226973666F72636F6D70656E736174696F6E223A2266616C7365222C22757365727461736B61737369676E6D656E74223A22222C22666F726D6B6579646566696E6974696F6E223A22222C2264756564617465646566696E6974696F6E223A22222C227072696F72697479646566696E6974696F6E223A22222C22666F726D70726F70657274696573223A22222C227461736B6C697374656E657273223A7B227461736B4C697374656E657273223A5B7B226576656E74223A22637265617465222C22696D706C656D656E746174696F6E223A22636F6D2E6C656E2E6163746C697374656E65722E4163744E6F64654C697374656E6572222C22636C6173734E616D65223A22636F6D2E6C656E2E6163746C697374656E65722E4163744E6F64654C697374656E6572222C2265787072657373696F6E223A22222C2264656C656761746545787072657373696F6E223A22227D5D7D7D2C227374656E63696C223A7B226964223A22557365725461736B227D2C226368696C64536861706573223A5B5D2C226F7574676F696E67223A5B7B227265736F757263654964223A227369642D33334642463234452D464537302D343730412D394442352D394231383831453133383437227D5D2C22626F756E6473223A7B226C6F7765725269676874223A7B2278223A3535342E353435343431333138323233312C2279223A3130392E39393939393634353638333530367D2C2275707065724C656674223A7B2278223A3435342E353435343431333138323233322C2279223A32392E3939393939363435363833353036337D7D2C22646F636B657273223A5B5D7D2C7B227265736F757263654964223A227369642D35353636443037362D414234432D344134322D393938462D323533373738394638313831222C2270726F70657274696573223A7B226F766572726964656964223A22222C226E616D65223A22222C22646F63756D656E746174696F6E223A22222C226173796E6368726F6E6F7573646566696E6974696F6E223A2266616C7365222C226578636C7573697665646566696E6974696F6E223A2266616C7365222C2273657175656E6365666C6F776F72646572223A22227D2C227374656E63696C223A7B226964223A224578636C757369766547617465776179227D2C226368696C64536861706573223A5B5D2C226F7574676F696E67223A5B7B227265736F757263654964223A227369642D46423539344242452D383030352D344544432D423343382D393738314544323236433935227D2C7B227265736F757263654964223A227369642D34373638373538312D333535422D343335342D383433432D433330343233333238364146227D5D2C22626F756E6473223A7B226C6F7765725269676874223A7B2278223A3730302E303030303030303030303030312C2279223A38392E39393939393733353039303436347D2C2275707065724C656674223A7B2278223A3636302E303030303030303030303030312C2279223A34392E39393939393733353039303436347D7D2C22646F636B657273223A5B5D7D2C7B227265736F757263654964223A227369642D33334642463234452D464537302D343730412D394442352D394231383831453133383437222C2270726F70657274696573223A7B226F766572726964656964223A22222C226E616D65223A22222C22646F63756D656E746174696F6E223A22222C22636F6E646974696F6E73657175656E6365666C6F77223A22222C22657865637574696F6E6C697374656E657273223A22222C2264656661756C74666C6F77223A2266616C7365227D2C227374656E63696C223A7B226964223A2253657175656E6365466C6F77227D2C226368696C64536861706573223A5B5D2C226F7574676F696E67223A5B7B227265736F757263654964223A227369642D35353636443037362D414234432D344134322D393938462D323533373738394638313831227D5D2C22626F756E6473223A7B226C6F7765725269676874223A7B2278223A3635392E353637363531363836373836382C2279223A37302E343430353134393838323432347D2C2275707065724C656674223A7B2278223A3535352E303332363536393130303136322C2279223A37302E31343334363333343436373330357D7D2C22646F636B657273223A5B7B2278223A34392E39393939393939393939393939342C2279223A34307D2C7B2278223A32302E352C2279223A32302E3439393939393939393939393939367D5D2C22746172676574223A7B227265736F757263654964223A227369642D35353636443037362D414234432D344134322D393938462D323533373738394638313831227D7D2C7B227265736F757263654964223A227369642D42453337324431342D463530392D344544422D383745382D374232313037383335414535222C2270726F70657274696573223A7B226F766572726964656964223A22222C226E616D65223A22222C22646F63756D656E746174696F6E223A22222C226173796E6368726F6E6F7573646566696E6974696F6E223A2266616C7365222C226578636C7573697665646566696E6974696F6E223A2266616C7365222C2273657175656E6365666C6F776F72646572223A22227D2C227374656E63696C223A7B226964223A224578636C757369766547617465776179227D2C226368696C64536861706573223A5B5D2C226F7574676F696E67223A5B7B227265736F757263654964223A227369642D41453541454438342D303734362D343738372D393836462D364137393237433334433334227D2C7B227265736F757263654964223A227369642D35313046453036322D433042432D343643382D394231372D384133383037324132424336227D5D2C22626F756E6473223A7B226C6F7765725269676874223A7B2278223A3335352E303030303030303030303030312C2279223A38392E39393939393733353039303436347D2C2275707065724C656674223A7B2278223A3331352E303030303030303030303030312C2279223A34392E39393939393733353039303436347D7D2C22646F636B657273223A5B5D7D2C7B227265736F757263654964223A227369642D42324633433135342D434432322D343230412D424538422D363836444534373531423731222C2270726F70657274696573223A7B226F766572726964656964223A2275736572222C226E616D65223A22E8B083E695B4222C22646F63756D656E746174696F6E223A22222C226173796E6368726F6E6F7573646566696E6974696F6E223A2266616C7365222C226578636C7573697665646566696E6974696F6E223A2266616C7365222C22657865637574696F6E6C697374656E657273223A22222C226D756C7469696E7374616E63655F74797065223A224E6F6E65222C226D756C7469696E7374616E63655F63617264696E616C697479223A22222C226D756C7469696E7374616E63655F636F6C6C656374696F6E223A22222C226D756C7469696E7374616E63655F7661726961626C65223A22222C226D756C7469696E7374616E63655F636F6E646974696F6E223A22222C226973666F72636F6D70656E736174696F6E223A2266616C7365222C22757365727461736B61737369676E6D656E74223A22222C22666F726D6B6579646566696E6974696F6E223A22222C2264756564617465646566696E6974696F6E223A22222C227072696F72697479646566696E6974696F6E223A22222C22666F726D70726F70657274696573223A22222C227461736B6C697374656E657273223A7B227461736B4C697374656E657273223A5B7B226576656E74223A22637265617465222C22696D706C656D656E746174696F6E223A22636F6D2E6C656E2E6163746C697374656E65722E4C656176654C697374656E6572496D706C222C22636C6173734E616D65223A22636F6D2E6C656E2E6163746C697374656E65722E4C656176654C697374656E6572496D706C222C2265787072657373696F6E223A22222C2264656C656761746545787072657373696F6E223A22227D5D7D7D2C227374656E63696C223A7B226964223A22557365725461736B227D2C226368696C64536861706573223A5B5D2C226F7574676F696E67223A5B7B227265736F757263654964223A227369642D39394343413337462D413233352D343835332D383437322D444532333341443245443332227D2C7B227265736F757263654964223A227369642D30344339463239412D304242352D343639312D383034432D373634453445304132373136227D5D2C22626F756E6473223A7B226C6F7765725269676874223A7B2278223A3338352E303030303030303030303030332C2279223A3237357D2C2275707065724C656674223A7B2278223A3238352E30303030303030303030303030362C2279223A3139352E30303030303030303030303030337D7D2C22646F636B657273223A5B5D7D2C7B227265736F757263654964223A227369642D46313234303339432D394237422D344134382D384531332D413635353335384246443345222C2270726F70657274696573223A7B226F766572726964656964223A22656E64222C226E616D65223A22656E64222C22646F63756D656E746174696F6E223A22222C22657865637574696F6E6C697374656E657273223A22227D2C227374656E63696C223A7B226964223A22456E644E6F6E654576656E74227D2C226368696C64536861706573223A5B5D2C226F7574676F696E67223A5B5D2C22626F756E6473223A7B226C6F7765725269676874223A7B2278223A3835332E303030303030303030303030322C2279223A38332E39393939393733353039303436347D2C2275707065724C656674223A7B2278223A3832352E303030303030303030303030322C2279223A35352E39393939393733353039303436347D7D2C22646F636B657273223A5B5D7D2C7B227265736F757263654964223A227369642D35343537313339312D463242332D344342342D383041302D303932444130323737334137222C2270726F70657274696573223A7B226F766572726964656964223A22222C226E616D65223A22222C22646F63756D656E746174696F6E223A22222C22636F6E646974696F6E73657175656E6365666C6F77223A22222C22657865637574696F6E6C697374656E657273223A22222C2264656661756C74666C6F77223A2266616C7365227D2C227374656E63696C223A7B226964223A2253657175656E6365466C6F77227D2C226368696C64536861706573223A5B5D2C226F7574676F696E67223A5B7B227265736F757263654964223A227369642D42453337324431342D463530392D344544422D383745382D374232313037383335414535227D5D2C22626F756E6473223A7B226C6F7765725269676874223A7B2278223A3331342E333836373235353538313136372C2279223A37302E34323230383835383931323634377D2C2275707065724C656674223A7B2278223A3235302E37353338393934343138383334322C2279223A37302E313837323831313132363832387D7D2C22646F636B657273223A5B7B2278223A34392E39393939393939393939393939392C2279223A34307D2C7B2278223A32302E352C2279223A32302E3439393939393939393939393939367D5D2C22746172676574223A7B227265736F757263654964223A227369642D42453337324431342D463530392D344544422D383745382D374232313037383335414535227D7D2C7B227265736F757263654964223A227369642D41453541454438342D303734362D343738372D393836462D364137393237433334433334222C2270726F70657274696573223A7B226F766572726964656964223A22222C226E616D65223A22E5908CE6848F222C22646F63756D656E746174696F6E223A22222C22636F6E646974696F6E73657175656E6365666C6F77223A22247B666C61673D3D747275657D222C22657865637574696F6E6C697374656E657273223A22222C2264656661756C74666C6F77223A2266616C7365227D2C227374656E63696C223A7B226964223A2253657175656E6365466C6F77227D2C226368696C64536861706573223A5B5D2C226F7574676F696E67223A5B7B227265736F757263654964223A227369642D37363845453443392D333233432D343744422D423438302D344230323746333136433835227D5D2C22626F756E6473223A7B226C6F7765725269676874223A7B2278223A3435342E303230343134303536323536372C2279223A37302E34343233353139373631383238337D2C2275707065724C656674223A7B2278223A3335342E3938393334303736393934392C2279223A37302E31343934333838373037303234377D7D2C22646F636B657273223A5B7B2278223A32302E352C2279223A32302E3439393939393939393939393939367D2C7B2278223A34392E39393939393939393939393939342C2279223A34307D5D2C22746172676574223A7B227265736F757263654964223A227369642D37363845453443392D333233432D343744422D423438302D344230323746333136433835227D7D2C7B227265736F757263654964223A227369642D34373638373538312D333535422D343335342D383433432D433330343233333238364146222C2270726F70657274696573223A7B226F766572726964656964223A22222C226E616D65223A22E5908CE6848F222C22646F63756D656E746174696F6E223A22222C22636F6E646974696F6E73657175656E6365666C6F77223A22247B666C61673D3D747275657D222C22657865637574696F6E6C697374656E657273223A22222C2264656661756C74666C6F77223A2266616C7365227D2C227374656E63696C223A7B226964223A2253657175656E6365466C6F77227D2C226368696C64536861706573223A5B5D2C226F7574676F696E67223A5B7B227265736F757263654964223A227369642D46313234303339432D394237422D344134382D384531332D413635353335384246443345227D5D2C22626F756E6473223A7B226C6F7765725269676874223A7B2278223A3832342E333738393131323235363332312C2279223A37302E34333832343930343234363831347D2C2275707065724C656674223A7B2278223A3730302E303734323133373734333638332C2279223A37302E30343631323036353933343131337D7D2C22646F636B657273223A5B7B2278223A32302E352C2279223A32302E357D2C7B2278223A31342C2279223A31332E3939393939393939393939393939367D5D2C22746172676574223A7B227265736F757263654964223A227369642D46313234303339432D394237422D344134382D384531332D413635353335384246443345227D7D2C7B227265736F757263654964223A227369642D46423539344242452D383030352D344544432D423343382D393738314544323236433935222C2270726F70657274696573223A7B226F766572726964656964223A22222C226E616D65223A22E4B88DE5908CE6848F222C22646F63756D656E746174696F6E223A22222C22636F6E646974696F6E73657175656E6365666C6F77223A22247B666C61673D3D66616C73657D222C22657865637574696F6E6C697374656E657273223A22222C2264656661756C74666C6F77223A2266616C7365222C2273686F776469616D6F6E646D61726B6572223A66616C73657D2C227374656E63696C223A7B226964223A2253657175656E6365466C6F77227D2C226368696C64536861706573223A5B5D2C226F7574676F696E67223A5B7B227265736F757263654964223A227369642D42324633433135342D434432322D343230412D424538422D363836444534373531423731227D5D2C22626F756E6473223A7B226C6F7765725269676874223A7B2278223A3638302E353030303030303030303030312C2279223A3233352E30303030303030303030303030367D2C2275707065724C656674223A7B2278223A3338352E353739313031353632353030312C2279223A39302E373737333431343131333435357D7D2C22646F636B657273223A5B7B2278223A32302E352C2279223A32302E357D2C7B2278223A3638302E353030303030303030303030312C2279223A3233352E30303030303030303030303030367D2C7B2278223A39392C2279223A34302E3030303030303030303030303031347D5D2C22746172676574223A7B227265736F757263654964223A227369642D42324633433135342D434432322D343230412D424538422D363836444534373531423731227D7D2C7B227265736F757263654964223A227369642D39394343413337462D413233352D343835332D383437322D444532333341443245443332222C2270726F70657274696573223A7B226F766572726964656964223A22222C226E616D65223A22E9878DE696B0E794B3E8AFB7222C22646F63756D656E746174696F6E223A22222C22636F6E646974696F6E73657175656E6365666C6F77223A22247B666C61673D3D747275657D222C22657865637574696F6E6C697374656E657273223A22222C2264656661756C74666C6F77223A2266616C7365222C2273686F776469616D6F6E646D61726B6572223A66616C73657D2C227374656E63696C223A7B226964223A2253657175656E6365466C6F77227D2C226368696C64536861706573223A5B5D2C226F7574676F696E67223A5B7B227265736F757263654964223A227369642D34363841393635452D393339422D343733312D413232392D353137384436413042423834227D5D2C22626F756E6473223A7B226C6F7765725269676874223A7B2278223A3238352E30303030303030303030303030362C2279223A3233352E303030303030303030303030317D2C2275707065724C656674223A7B2278223A3230302C2279223A3131302E39363039333534393234383234367D7D2C22646F636B657273223A5B7B2278223A302E393939393939393939393939393939392C2279223A34302E30303030303030303030303030377D2C7B2278223A3230302C2279223A3233352E303030303030303030303030317D2C7B2278223A34392E3939393939393939393939393938362C2279223A34307D5D2C22746172676574223A7B227265736F757263654964223A227369642D34363841393635452D393339422D343733312D413232392D353137384436413042423834227D7D2C7B227265736F757263654964223A227369642D35313046453036322D433042432D343643382D394231372D384133383037324132424336222C2270726F70657274696573223A7B226F766572726964656964223A22222C226E616D65223A22E4B88DE5908CE6848F222C22646F63756D656E746174696F6E223A22222C22636F6E646974696F6E73657175656E6365666C6F77223A22247B666C61673D3D66616C73657D222C22657865637574696F6E6C697374656E657273223A22222C2264656661756C74666C6F77223A2266616C7365227D2C227374656E63696C223A7B226964223A2253657175656E6365466C6F77227D2C226368696C64536861706573223A5B5D2C226F7574676F696E67223A5B7B227265736F757263654964223A227369642D42324633433135342D434432322D343230412D424538422D363836444534373531423731227D5D2C22626F756E6473223A7B226C6F7765725269676874223A7B2278223A3333352E34333833363637353034313136362C2279223A3139342E31363031363032323737313137347D2C2275707065724C656674223A7B2278223A3333352E31323431333332343935383835372C2279223A39302E37373733333637393230353539367D7D2C22646F636B657273223A5B7B2278223A32302E352C2279223A32302E357D2C7B2278223A35302E3030303030303030303030303131342C2279223A33392E3939393939393939393939393938367D5D2C22746172676574223A7B227265736F757263654964223A227369642D42324633433135342D434432322D343230412D424538422D363836444534373531423731227D7D2C7B227265736F757263654964223A227369642D30344339463239412D304242352D343639312D383034432D373634453445304132373136222C2270726F70657274696573223A7B226F766572726964656964223A22222C226E616D65223A22E58F96E6B688E8AFB7E58187222C22646F63756D656E746174696F6E223A22222C22636F6E646974696F6E73657175656E6365666C6F77223A22247B666C61673D3D66616C73657D222C22657865637574696F6E6C697374656E657273223A22222C2264656661756C74666C6F77223A2266616C7365222C2273686F776469616D6F6E646D61726B6572223A66616C73657D2C227374656E63696C223A7B226964223A2253657175656E6365466C6F77227D2C226368696C64536861706573223A5B5D2C226F7574676F696E67223A5B7B227265736F757263654964223A227369642D46313234303339432D394237422D344134382D384531332D413635353335384246443345227D5D2C22626F756E6473223A7B226C6F7765725269676874223A7B2278223A3833392E303030303030303030303030322C2279223A3332317D2C2275707065724C656674223A7B2278223A3333352E30303030303030303030303031372C2279223A38342E37323635353939393537373730327D7D2C22646F636B657273223A5B7B2278223A35302E3030303030303030303030303131342C2279223A37382E39393939393939393939393939377D2C7B2278223A3333352E30303030303030303030303031372C2279223A3332317D2C7B2278223A3833392E303030303030303030303030322C2279223A3332317D2C7B2278223A31342C2279223A31332E3939393939393939393939393939367D5D2C22746172676574223A7B227265736F757263654964223A227369642D46313234303339432D394237422D344134382D384531332D413635353335384246443345227D7D5D2C22626F756E6473223A7B226C6F7765725269676874223A7B2278223A313230302C2279223A313035307D2C2275707065724C656674223A7B2278223A302C2279223A307D7D2C227374656E63696C736574223A7B2275726C223A227374656E63696C736574732F62706D6E322E302F62706D6E322E302E6A736F6E222C226E616D657370616365223A22687474703A2F2F62336D6E2E6F72672F7374656E63696C7365742F62706D6E322E3023227D2C227373657874656E73696F6E73223A5B5D7D',NULL),('142519',7,'source-extra',NULL,X'89504E470D0A1A0A0000000D49484452000003870000017308060000008D717CB0000000206348524D00007A26000080840000FA00000080E8000075300000EA6000003A98000017709CBA513C0000000467414D410000B18E7CFB5193000000017352474200AECE1CE900000006624B474400FF00FF00FFA0BDA793000000097048597300000EC400000EC401952B0E1B000020004944415478DAEDDD077C5455DAF8F133E9A1841288A14A559466C1B22E2AFA22A06B4111490C2A2AAEAFE5B5FC755504165450B1B27617150491203694559A8880055730405040A49700218D402690CCFC9FE7CE9D30840402A44CF97D3F9FC73B73A710CFDC39739E7BCE3DC71800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008EC04111A03ACD9E3DFB0C87C3D14F6EF690E8261143A99CB022893489F9129F5C76D9653F512400F517F5170080E4107E69D6AC591DC2C2C2FE1511117166E3C68DB7346AD4A849BD7AF512651F8573825C2ED7C6ECECECF48C8C8CBCACACACAE6EB77B9BEC7BB077EFDEE9940E5069F5D7CB125DE2E3E357262424346ED0A081EE23393CF1FACB999797F7DB8E1D3B76676666B62E2E2EDE40FD05002487086273E7CEEDE970383E6AD9B265718B162D1AC96D0AA5EA6C484F4F9F2349E25552CE77F4ECD9730645029C58FDE576BB27376DDA7475DBB66DFF22DFAB084AA5EAAC5BB76EF1962D5B5A4B39DF4EFD0500D52F9C22405537AC2223233FEED4A953FD8484845A2486554ECBF9ECBA75EBCEDAB56BD7E09B6FBE79EDC48913D7502CC0F1D55F5267BDDBA54B9768490E3BC86D863A54B1060D1A348F8F8FDFBF73E7CECB6FBAE9A6D5D45F0040728820A143B1222222BE95C4B06E5C5C1C05528D6263634F9704F11B6960DD3370E0C0591F7CF0C14E4A0538B6FA2B2C2CEC3F921846D5AB572F9E12A93E515151B10D1B360CCFC8C8B8322525E52BEA2F00A83E0C8F4195898989F9A0458B16B5CA4B0C0BF377985D6B679B7DD9EB8DDBED32B1F54F3609ED7A9998B866145E2590C6553F89715959592FCBDDCB2811A0E2F41AC3962D5B164862D8A2ACC7B5CECADAB8C8E46CFDC51C28C83211D171262EB18B896F75B1098F8CA5004F509D3A756AB56EDDDAB97EFDFA57E4EEA5940800540F7A0E5125162C5870AEC3E118D2A14387F0B286926A62B879E97BC6B967BB34B28AA5A5E5920656B6C9CB586E6AC7B7B31A5A3871090909F19B366D8AB9E9A69B964E9A34690B25021C9DCE4A1A191939A453A74E89E50D85DFB16ABA24870B8DABA8C0BAEF2A2E3405B99B8C336F8B896B72866108FD898B8B8B8BDDBE7D7BAD94949445D45F00503DB87E0255222626E691264D9A4496D740D24655D1FEBD87ED7715EF3799EBE7538095A755C3860D97C9B61F4501548C2E5791989858545EFDA53D85B9DB9696F9988E84D89BB99A42AC24F23B124EFD050024870870070E1CE85EAF5EBD721F2FC8DB5AEE63DAAB88CA238D5CED86ED41490015131E1EDE273E3EFEA472EBAFDC2DD6B052EAB0AAD7A0418346F2795C41490040F5E09A435409A7D39950B76EDD721F77171F28FFC5476874E1B81A579D64C3859C4005B95CAEAE47ACBF5C45477CBD9B3AACD2D4A953C714171777A0240080E41081DDB872B0C0BD7F90CFE1644A01A838B7DB1D49FDE537F597B5A12400A09AEA5D8A00000000004072881A1119DBA0DCC722A2EB52400002B2FE52E1517528240000C92150510D5B5E6022A26A1FDEA88A8C350D4FEE4E0101F05BBA266B9D46A796F998AED31A97703A8504002039042AAA4EE3D34CED321A57BABF6E42470A0880DF7238C2CC491DAE2AF3B184F67DE8390400901C02C7AAF840C161FB8A0AF7503000FCBFFE2A639D56EA300000C921708CF6EFDD65362D79D7E4EFFAFDB0C7F6EEFEC36CFA659CF51C00F047591B1799CDBF4E28F3B1ED2B3F363BD67CC57216008080C45216A856B9DB969A5D6B6799A272CEBAAB7D391BCD869FDF348DDBF634F55B9C6F0DE102809A76C0996376ACFAD2E467AE2EF7399A14666FFAC13873379B26A75F67A26A37A6E000002487802FED09D4B3E9DA335811AEE2FDD6F3F7ECFADD249C728589A9DB8442045063B2B7FC6C32FF9C53E670F8B2144872B87EF1EBA651EB1EA661AB8B38C905000808FC5AA15A684F604513435FFBB2D79B8DFF7D9B0284DF193468507D4A2134E830D21DABBEA87062E8E57615995D7FCEB55E0F803A162039046CDA1378BCB48105F8931B6EB8A1A7D3E9CC4E4E4EEE4369507F518701D4B140B0605829AA45879EA3280404851B6FBCF10CB7DB3DF58C33CED89196963655EE5FFCE1871FA65132C1AB519B4BAD00401D0B043B7A0E01E0D81A2DDF0C1A34C8FDC8238F9C74FFFDF73BE5FE77494949DD281D00A08E05480E01200424272777D046CB4D37DD54D0AB57AF78DD77DE79E7254823668FC3E1982E8D97567EFEBFD0814F1100752CF52C70240C2B0580A3D046495858D8D7D75D779DEBF2CB2F6FE6FB9834629A498366D3C4891317C8F32E4A4D4DDD50457FC6BD12E9A5F6254AC4F8DCEF2771954F23C5E9F3588AC4629FF7D06B791695F19E00108A752CF52C10ECC9614A4A4AF3A2A2A2BE0E87E362B97B86FD05AF637F9133A4B24993C7BE0F0F0F4F9D3C79F2160E070065355A222222E64B83A59E345CCA9C3DAF77EFDE2D0B0A0AB64C9B364D873F5D5C458D974612F3CB794CEBB57C8956A5F6699D778DC4F712B3B4DEB31B2B6D255EB75F0300D4B1D4B321895C214492C3E4E464FD90FF2F2A2AEA7491D5BD7BF73AAD5BB78E6ADCB8718C3052C1ECCEC9C9D9BF62C58AE8050B165CBA7EFDFABBA4B2D924AF7977CA94291FF05501A0742AF5E2E2E2593D7BF68CBBF1C61B8F38AD7ADFBE7D9BE7E6E6FE3173E6CC85529F5C58458D17FD1B7AD83F5CDEFABBB9DD08B9B554DDFE8B7D7B95FEAF487C6CDFBF5362884491BD7F8644269F3600EAD89204F17A73688FE0B1D6B3B753CFFA7FAE209B7BE4F8EB2EEDFF98329EA2FB5AC9637A32A0AF3CEF7939EEE68742AE1054C9A13D2CE1EDBA75EB761D3C78709D33CF3CB3B664FA89A59F171B1BDB4CC23469D2E4945EBD7AE92EA754368B274D9AF4A0BCC79D7200DC3A6DDAB4B57C7580D06EB4B85CAE05E79E7B6E624A4A4A5C455E73CB2DB7B497C64BFA8F3FFEB8B07FFFFEE7483D9251C97F568EC4E715789E3664CEF079CD4F7652A9FE23D1D3AEFF37D889268D1600D4B11E5A1FBE7582F5EC2CEA59FFCD1564F3A6DBED3E9E65527AC8EB7A047BAE1034C9E180010392222323DFB8EEBAEB22AEBAEAAABA92141ECBCB63FAF4E9932C91F3C20B2F7CB264C99285C9C9C9FFA01711084DD2E8A8B37FFFFE79D268697ED75D77C51D4B7D72DF7DF775DAB76FDF9AB4B4B4AFA51EB94CEA91CA6E10781B1CDEB3DAE71BCFF52C337C9EB3C18E41C6734D4CE906D479C6735DCC0C3E6D00D4B115AA6775398D9965D4B3238D67E86826F5ACFFE70AB279D5787A872D7AEC75EAD449273F32EDDAB533F5EBD73775EBD635728C999C9C1CB361C306F3F3CF3F1BC90DDC4545450EFB65DDE575BFCAF1775730E60A41315BE9CD37DF7C4D5C5CDCBF870F1FDEA06FDFBEC79A18FAAAFFF0C30FDFFEF8E38FFFEC703846CB873E98AF12105A060D1A1453BB76ED19679D7556DB7BEFBDB7C1F1D4278F3DF6D8291D3B7674B85CAE39DA08AAE43F51CF56EB10A6F976C4D8F7CBB3C127BCD7BE78CF660300756CC5EAD945E53C5793C22DD4B37E9F185E296DFB49DEC4508FBB2BAFBCD2BCFCF2CB7A3C994B2EB9C4B468D1C24A0C55AD5AB54CD3A64DCD05175C601E78E001F3EAABAF3AF4F96161616EFB2DEBB8DDEE49C1982B047C723870E0C094D8D8D80F478F1E5DB77DFBF695F29E9D3B77BEFAB9E79EDB2C07D170F9D007F2950242A7D12295FD976DDBB63DF79E7BEE893B81134D66F8F0E15DE57DA22322223ED3F7ADE23FBDA882CFCBB41B2B0C6F02401D7B6C1A95B33F9F7AD6EF13C32469D37F6627EC56D2F7CC33CFE86434A671E3C6157A0FED51D4E73FFBECB38E66CD9A157BF7CBF13C2ED87285804E0E75DC705454D4B8871E7AA856453FDC8A920FFEAF8F3DF6589A7CE8CFEBDA3B7CB58090F0719B366DFEFAE8A38FC6EAE45527EAC9279F3C4D1A2F098585855F5672E345274B1824A117D4EBB52E89E53C4F8741C5D8CFD1B3EBDEB3DBDF98C3879A020075ECB1D5B311D4B3FE9F2B4862F8AA37313CF5D453CDC89123AD5EC2E3A1AF93E32EBC73E7CE6E9F04F1CD60CA15023A396CD0A0C167D75E7B6D6C65F51896A63D88679F7DF67FF4AC005F2F20B80D1E3C38352121A1E7C30F3F1C1B19195929EFA967C5E547A84B6262E2494EA773528F1E3D2AE33A6F9D0DEF358909C63339CD58E39908A1B44E76A3E554BBB132576284F19CCDD6FDED24AEE49307401D7B981915AC673B50CFFA37490CB50D6FF5FA6A8FE1430F3D543274F478E990D3071E78C0B707B14E30E50A013B21CDEDB7DFDE5F3E9C4EBD7BF7AED27F472AB17E2929299BB5CB98096A80E074D34D37BD5FAF5EBD6B860D1B16AD95BED20BD1EFBAEBAEC39EFBCA2BAF1C320C452F5A97FAE8B0E7BDFEFAEBA661C38656E3E5E9A79FEE2C3F48B1B27B9C345EEE983F7F7ED109FCB965AD99A59325E899EB689F7DB748FCC3BEAD67B4F5DFF49D5A5D1B3D0FD90D1E863F01A08E3D28F304EAD9077DEA596D37DE4F3D5B3374B90A49DA7A7A4F24E8B583279A18FA2688F7DF7F7FF8638F3DE676B95C3A514DF760C91502B6E7502A99676EBCF1C688CA3AFB7404F56FB9E596E57270DDC9D70C083E77DF7DF7AB8D1A351A3062C48818DF1F0DBDBE401B2EDE868C5561868599B7DE3A7486F37FFFFBDFC6B71E6AD0A0815E0B6D355ABC74F8D4D8B163DBC5C5C55D90989838EE38CF6E1F69F15D6D78E8040A53EDFBAD7C6EEB7698F1CCA8A717CEFFAFF1CCC01763278B34580050C71E4CF08EA79E7DDFA79EBD57E231BB9E8DA09EAD51F7786F5C7EF9E5C73D94B43CFA7E575D7595770653132CB942402687C3860D6BBB7FFFFED65DBB76AD967FAF57AF5EFDA4C26A6AAF8D1212E4FF75989E71A9C4211A80DF1D93F7DC73CF0BB2B973C89021D1659D4DBCE8A28B743DD492FB2E97CBAC5FBFDEFCF28B67DDE3D5AB579B152B569803070E58F72322228C344E4C9F3E872F9FA48D9B975F7EF96469C4FC8F345E5E3E8E3FF79DA33CAE672BD3ECDB1BCCC1C599D3EC068B377478D46B474936395E00EAD850AB638D5D3F1E4F3DBBAA543D3B3214EA597F3E265352529AEB9A847A5B7B0D3539AC0A7A2CCA71E9BDFEB07B30E40A01F9A359AF5EBD21AD5AB50A3B9159AE8E514CFBF6ED574925A51727BF1022DFC9A7E44B654E3AE9A40239D0BFD631DB4545458BA64D9B964F75851A3E2673E4989C21C7E4E4133926EFBDF7DE31F2FAFB9F7CF2C988234D6825CF3343870EB58636A9828202F3CE3BEF5817B5BFFAEAAB25FB959E01FFFBDFFF6ECAAB9BE4F1E83163C6243CF2C823FD070C18B07AEAD4A9AFF1B156F9F1922BC7CB97277ABC54176D1C6BEF4945E5E7E75BC7DDB1BC06A88EEF0C752C2AF198DC239FE71752CF7D50D163529ED7578E612BCFD1CE24DF9EE6CAA43DE0679F7DB663F1E2C5DE5D019F2B04E4AF495E5EDEC5BA606575BAE0820BB4DBF8E250FB56CA174BC7F05F275FCEAFA532DE9E9C9CFC91449F6A9A36BA429E7EFA699391E199106CD9B26566E6CC9925F1E69B6F9A4D9B369534BABCE6CE9D6B2D6AFAFEFBEF9B2FBEF8E290B8EFBEFBCAFDB77478CBCE9D3B8FF8F7E8B511FADE4EA753AFB3D00ACA535B5C7F7DC96D9CD031595F3603ED6372BD3462C61FEB31F9F0C30FDFB77FFFFE87860F1F1E71B4998E131313AD3383B1B1B125FBB4B1327AF468AD8B4AF6E959F1BFFCE52FA64D9B36477CBF848484E8175F7CB14E7474F423F2B7FF2F9F68951F2FF57C8E970DC773BC5427AD93A4E153E1E72F58B04067CE3B649F3488ADA4913A0C35F59DA18E45251F93752552EC63724B458E49797E499BFDDC73CFADD2BFAFD4FB077CAE10903D873939392D4F3EF9E46AFD373B77EEDC5636B542FCFBA9B331F5976D7F693414CA1753D78C99BA7DFBF6199570F1F771D1844FAF3FD01F17D5B1634773DA69A7953CFEE8A38F9A1B6EB8C1BABD74E952B365CB163371E244BD48D96CDDBAD57AEDD5575F6D5DF7A089A4FAFAEBAF4B5EAFC35974888BEFBFF7C61B6F98B3CE3AAB64DFF2E5CB4DBF7EFD4AFEDDA8A828ABA2901F4673E9A5975AC36094FE407A6FA3D2E80C6483E4B81C24C764BEFC607C2C3F08D38F744CDE7DF7DDF7666767BFF4F8E38F87EBCC651571DD75D799EFBEFBCE3AA3AD7488939E74D0339A2595A97CB6DE63ED68E2E3E36B3FFFFCF3C50F3DF4D02839168BA64C99F20E1F65B5883FD6E3A5BA690F6079C39FF498D37ACCB79750EF2B3DB1E5FB1E9B376FB6EA24EA3054F777863A1655AC9ECF3159209FAF9E4DFBAC8C63F20CEF8DA39D503851AD5AB53265FDBB2487D5282F2F2F52BB71AB93FC7BF5EC03121ED1F2C54C926D922466F9F2E59C27B7DF8C8E8E9E3F61C2046775FD1152115867B6B52770F7EEDDBAD069C963DA8B78F1C517EB8F8475BF5BB76E567CFBEDB7A67FFFFE66D1A2455682A867D8F56C785967DAF57D1F7CF0C192FB7A365DCF64F6EC694D7E659D59D7B3F0DAA8D2469AFE986DD8B0C15A434787C4A07A4F5E787F30E498CC946352A7147FDFF7981C3264C8EDF279BDAC8D9663F9B1D0214CFFF77FFF67A4B161F6EEDD6BEDF36DB4687D74DB6DB71D32B1C2D1242424C43DF9E4937B860D1BF69234B8725253533FE623ACB1E3254B8E97D9DEE3A526FF289DC1D19BD895D6B2654B2B9E7BEE39D3A143D94B6A7DF0C107E6A38F3EA20E43557F6776CB77660E752C6A58AC1C2737CBF6663926F3E4739EED7038DED56352EAB644DFE3A78A7304DFBB8D480E6B406161A1A332164F3D1692389CA45B39F046F25D3CFC0743BE9C57CBF66A6D684819ADDFB56B5795FFA3DAA0D1864E7676B6D5A8D121283E9F9779EFBDF74C794B9D788755FDF1C71FD67BECD8B1C3DAFAD246D215575C616DBD3D937FFEF9A78E7DB7CEA8ABD9B3679B6BAEB9C6BAAD67E23566CD9A6535ACF4396FBFFDB6F51C3D5BAFF7B76DDB660DEB7AECB1C74C751DC399999956F984D8B1DBC87BF2428FC9010306AC95CF6D724646C6706928871DCF59446D2877EEDCD93A4E7C87286B2F4DF3E6CDAD130FC7AA75EBD675EFBEFBEE9CD75E7BED7D7BCAEDB5542735A2A1EFF1A2C33A9B356B66DAB66D5BED7F8826665A2F95951C96B4866263AD110F4A7BF99477820EDF910FC15287697DCE6FAFDF890F943A76E8D0A159A3468D7A9B3A36E8C5495C2F9FF1F57A4CFAAAACE52BCA53EAA4454CA01764402687FA83A41F7C752688DF7CF38DF7E608BE7F47AF8FB572D7614A557D1C74E9D2C56AF49C73CE3987247E13264C3063C68C317BF6ECB17A1675DD246D20E9F02A8D7FFDEB5FA65DBB76D6EB75D894360675ABBCD7FBE8197A6D0C0D1F3EDC5C72C925D6BEF4F474ABB7D1DBB0D204D47778962FFD71D36B21CF3CF34C6B3896FE2DEBD6ADB3CED8FBFEF055B5850B179A5F7FFD35A48F5D87C3D14E8E8B113A5C4F1B1FC74BA74FF7B9E8DCA267B7AFBDF6DAE37ECFEDDBB7D7B7DF2785AAC33F68CF9AF6BE0D1932A4DAFF6D4D4ABD3D27E566B20D1B960C23F50E2BF5D649BE27C482A50E5BB3660DBFBDD4B1C7FD9EA79F7E7AC3A64D9BEE91E39E3A364469DD559509A2EFA449C6B38409C961B59F1A888B2BCAC9C989F09E09AD0E9244644D9F3E5DCBEBE510F92E55E48758C77C680B21BCD48FC4BA6EDDBAB5A986E3C074EFDEDDFCF6DB6F562348E924347AE2E091471E294920870D1B665DC7A0B35569E8B052ED65D4B3E17A8D83D2B3F5DEC656E9464FFBF6EDAD7F47698FA84EBB7DFEF9E75BF7BFFCF24BEB8CA69736B8B4F1A4134268634C1350EF6B7578ABF77675BAF0C20BCDC68D1B35417C22048EC9F21A2EEB6AD7AE3DE9FBEFBF1F76EAA9A7869F77DE79C7F53E1F7EF8A1BED721C39DF4ACB6D40DDA0039AEF7AC55AB5696BCA79E76FC84B3DAD57EBCB8A4CC5DDE19ED7CEB96AA3EB95516AD5FF4DFD63A487BCBEAD4A973D873F4BA693996CB7D8F4F3EF9C4AAE75AB76E1D3475D829A79C120CF557D0D7B172BCBE2375EC53FE56C72E5AB468D7B66DDBA274F655EAD8D0A9C7E5FE01D96F2D90A9C3F5AB3239D4F7F711F06B5A066472D8B469D37DD2D88DABCEE4303737778F6C56A4A6A68E0C856F63525252B95F48F9B215CB974E13429DC1355CEEE7C8FDB95AF1464747CFD46B0F6EBBED367755FF8DDA801A3C78B0D5E397959565CE38E30CEBACBB0E9BD269B0F53A42F97BACB3CECF3CF3CC61AFD7DE463D03AE3F3C3A14CB3B4CEBCA2BAF3CAC319696E659D648932CED55F0F65AEB70542FEFCCA83AE44BAF7DF49E99AF698D1A35B27A061E7DF4D191417C4CBA1DDAA23878FFB06352F78F1C3972A97C4E9FEDDBB72FCCDB935251BADE964EDC51FAE4417171B1755CE8BA5CC73AECE9C71F7FDC3979F2E448798FAB3EFAE8A3B9B403AAE578D10FB058421B0D61728C84953E5EFAF7EF5FA0094975D3994A759A7E1D2A3A7EFC786BA2ACD275915EDBE2BD5ED0F7649677E4830E09D5496834B9F4F6E0047A1DA64972A8FCF6FA6B1D5B469D5B5E1DBBD2DFEA58F97BB48EBD9E3A36788E4939FE8AEC0430A2BC7ADCE9744E329E6525AC135EBA607D55D10E061F69248735A049932669E9E9E9171DEF99A9E3B178F1623D2DF05DA87E41E54B57285FB868FBCBA889A1CEDE325362AA3424E6CA0F434E75FF4D9AD4BDFEFAEBC63B4DB6FEB068634863DEBC7956E3C89BF0F9FEF82C59B2C44C9932C5BA9EE8F7DF7FB7662CF5F61CEA0F905EC3F8CF7FFEB3A4E1A5B3A6791B499A706A78EFEBE3DE75C974FA776DD4956ED0954527CFF14E948313672786473D26A5E1F28524C9177EF8E187DF4A6321CAB7917D24DA3879EDB5D70E99B4C8F7EC766E6EAED598D733DB159D3061EEDCB999F29A48397E7A49A3E5173EC5AA3D9724A15F5ACD88C2EC28F7784949A9FED1677A524B9320ED3954BAA0B74E9AE5DB53A743A3EC21962556AD5A656DBDAFDBBE7DBBF53EDE194DA9C35089A863E117F5B84F2F61B9C7E4800103BE93E759C9A15EEAA413145695527356047CAE1090C9E199679EF9E1B871E32ED2CAA4BC85502BDB8A152BB49B326467BAB213C37CBB0CFE13131333A33A67252D8F76E5A7A6A65A67D37D672A2D8BCEF0A7C3B174E8A977B896776D1ADF9E435F3A1C552B146F034DCFB2EBD4DCBAD692D264D2CB3B314459BCEB307A6982DAAB572FAAFACA69AC1CD3313966CC981FA40173E6E79F7FBE44EA9098F2262DF2F5E9A79F1E724D8136DCF538D0C939B4E1AD74ABD7A90D1A34E8A8EF27C7DBEEC993273BE535974C9B368D614ED5702EC94E0CFDAE0EF3265A3A8CF3F1C71F2FD9A7A322EEB9E71EABD1EC6DD4E82435DA48D6FAC49BFC79275EF036AA7508A9CE64EA5D42803A0CD4B1D4B1A1588F4744447CEE72B9C6BADDEE709DBD5E4798E9F5DA55D10EF55EFB6D0BF85C212093C3CE9D3BBF9F9090F09A7CD811E55D485F99962F5FBEBFB0B070BD24211B42ED9BA8DDF4B2992F0D11EF74D539FEF2B7E950295DAF4B1B54DA7BA867C3BD67C07D693278F6D967975C87689D7E2AE379BECFEFD4A993751D8EF62AFA3680F4357A42C2DB88BAF5D65B4B1ED37F5FD761F20E89D15942E7CC99634DFEA043C5F44CBD3E47F7EB1007D4DC31290D97DFE433E9F4D9679F2D97C6722DED292AEF4493368AF598F06DB8E8B0BBA143875A3336EA0F8ED25E9D9F7EFAC95C74D145475C53491A3739D3A74F97C3C4752D8D96D0AEC39477289D6F62E8F5F2CB2F5B1374CC9831C3DC7CF3CDD6A808EFB5825A9F683DA4758ED64BDED94A4B9FE4A20E03752C42F1989C3C79F296E4E4E46FE5664F3DC9A69D0055312A448F5DEF090CB128187285804C0E1D0E87532A9C8FE403B8512FBCAFEADEC371E3C6ED964AE6F510FB2E0E9772DE101313F3B1BF9C5D2F4D93376D3C79E92CA57AF6C6BB48B3367EF44BEB6DE478879F2AFD81D1E1577A7652E9D017EF8434FA25D7C4D37792062F7D0F6D6C95451B543AC5BBB75752AFF5D319D6744D4575E79D779A499326597F5F550E6FE098AC18F9ACFE94C64B97C58B172F954649DC1D77DC51665DF2D65B6F1D72ED950E69D2F5B6F4E2F67BEFBDD7EA91F6F6DE682F8D3E5FAF712DEBBDB4D122C759BE1C2B1786E2C926EAB043E9B076AD37BC7544695A87694F89D663A597B6D0B510F5DA423DD674129A8AA20E03752C42E898D4B6BB35B65993433DB15099D71E6A3DAC27EF7CF293B783A1D01D017C162166E4C891B9DDBA758B2A3D814865FAEAABAF0A3EFCF0C3655BB76EBD70FEFCF9457C4F2B66CE9C396EFD12C23F2C58B0C05C76D9650E4AE270528F34CACBCBFBBD7DFBF68D4A375EF49A2F5D16C57769016DA47BAF49557A8242274AF0F6B6E8B015AD93744A775FE3C78FCF9D376FDED6E2E2E28BA74C999249C9537F81FA8B3A963A16552B393979BEE40CD6D92C1DAAAC6BB856C6CCA5DAD3ADEFA509A2F770CEC8C8B824187285B080CD6A1D0EA7540C77FDE73FFFB1160CAE0A7A2DC6D4A9530BA542BA95C41008DA864B665656568B356BD66C7FF5D5574B8687E875043AE151E935E774789D2FED4DF19D5D4F87404D9C38B1642894B7D12275C8BAC2C2C2F368B400A08EA58E45F590C47050585858B6DED66B585F7CF1456B88F289268663C78EF54D0CF3252FB923587285803F13377DFAF47973E7CEBD4417F9F51D3678A2742DA861C386E5CB01749754341FF0F53A369C79F72F9C793FBAFEFDFBD769DDBAF58A7AF5EAB5FAC73FFE5132E4F844E8750E6FBDF5D69E254B96AC901FA8BFF9DBF56EA0FEA2FE02752C82DD800103922441FC4027A7D1FBDA83F8C0030F1CD710534D08F524874F62A81D56370553AE1016E8FF03575F7D752FF9D158F6D4534F555A0FA2F618FEF39FFF2C282C2C7C9EC410080DD3A64DCBDFB973E769B9B9B96B9E7FFEF9926B5C8E97BE5EDE679FDD68F91F1A2D00A863A96351FDA64E9D9A2AC7C86049E2748D5BAB0771C890213A694DE905ECCBE59D1D5F5FE79B18CAFB0E09B65C213CD0FF079E78E209D7871F7EF84E5151D1C5E3C78F6FA5EBE2E8FA75E5CD447934BA80F01B6FBC51E072B91E94F77B89AFD4F1B9F9E69B479E7CF2C914849FD0131E93264D7A829238B2B4B4B4A2F6EDDBBF131D1D7DD5F7DF7F9FA8D3FD7B27383A163A6C6AD4A85107366DDAF4BDD4257DFC754214507F517F813A16A1203D3D3DAD63C78E6BC2C3C37B4B4217AD6B68EABAB13AE197AE33AB3331EBF5B09A3FC8F1690D1DD551843AF1D7E79F7F6E5D1BBB72E5CA92B5378D67498D3B25F17C2DD8CA2A2218FE272421D431BE3D7EFAE9A7DBE6CC99F3D682050B2275BA5A9DC9B4A2F4C3970FB868F7EEDD7F161414F4C8A6A4BD00002000494441549D3265CA2ABE4A40E8B11B19670C1D3AF4FB9123475EA0D3A91FCBC5EBFA83F2F4D34F17656666CE901F9C1BB85E1900A86351F3B407312929E9274900DF71B95CFFA3FB7468B2CE745F6AADC2A359A4D718066BAE101E4CFF33EFBCF3CEAFF3E6CD7B3E3737B7DD8F3FFE78DAC71F7F1CA65DC7DE35EDF4EC94860E45C8CECE366BD7AE35DF7CF38D79EFBDF7DCBFFEFAEBD6BCBCBCA1AB57AFBE7DC68C193BF90A9D18CEBCFB17CEBC1FBB850B17BE77E185175EFAF5D75FB73CE79C731CB56BD73EEA6BF42CE3134F3C519C9393F3D59A356BFAD368A1FE02F517A863E13FD2D3D37356AC5831B153A74E2B25C16B28A1957D45871B2E9218919191F15030E70A11C1F63FA4B398CA26D9ED76DFBA72E5CADB962C5992220960A7CD9B37D792E42F4287224882E8964AA8283E3E7E5BC3860D7F6ADBB6ED98FBEEBBEF57BE32007C3DFBECB3173FF2C8235F3EF9E4937F1B3A74A8233131B1DCE7EAEC674F3FFD74714141C1177FFCF10767B301803A167E2A3535F563D97C9C9292D2DCE5725D2F79C35FE57E37094D1675022C1D3FBA55224DE23B7D6EA8AC9D1911ACFF637692F8861D00705C9E7BEEB9AB5E78E18537478F1E7D67798D173D9B3D6AD4A8E2B0B0B07FAD5EBDFA511A2D00401D0BFF3779F2E42DB219AB3168D0A018A7D359E04D25626262DA87E2F5AC611C160070640F3FFCF05D2D5AB418357CF870F7BA75EB0E794C87BCC97E5783060D468F1D3BF6211A2D00401D8BC02389E1F9BEF70B0B0B7B846239901C0240053CFAE8A3FF6CD3A6CD33A3468D72FFF6DB6FD6BED5AB575B3326376DDAF419D98EA09400803A1601EB96A3DCF78A92E84B72080021EEF1C71F1FDABE7DFB075E7AE9A5625DEF68ECD8B1C5D298797CC48811C3281D00A08E45E072BBDD87247CBA4C4A8F1E3DCABA044FA7D71D47720800D0C6CB2B898989C3A64F9F6E9A356BF6D4F0E1C3C7502A00401D8B80A1095F33DF3C283939B9BBC3E1A8EF932816E9FD8484841EA55ED724140A27187D2471430DBE1E4010FBF3CF3F6374BB72E54A07A50100D4B10818B74A3C24A16B147691B84F62A6E687BE4F92E4304292439DE07280DC9D6BBFEE3989C512AD480EFD5B8C9DF9EFF3D9777519CFAB656FF755E03DAFE6BB03000000048D7612FF90384B426721D5652BE6489C22C9E055BE4FD4F5D195248757366EDCB8DDAE5DBB9E95BBA74BEC92682CF11BC9A1FFD1646FBAFDFF502871AA446BE359BA22DA78D62631F6FED512EBEC03E11489BF49A47B4F0E483C28F1A8C44289CC325E9FCFF7090000000858E749C44A8CF7D9D7262929A9876C5B947E727171B1090F0F4F4C4848B84992C3797662A85CC15C48819C1CF691D86B0ECE16D4CCDEDE2D719BCF7D63278DFBEDDBFF6B3CDDC9B7FA3CBEC7E7F9AE325E0F00000020B0FD2071A7CFFD3B24461FE905CD9B37FFEBCA952BB7874A01057272A8DDB97FB5B3FFD912F38EF05C1D2FDC5FE26CFB8CC1AC528FBFCB7705000000085A7ABDA02E78AFB38D7A933DCD0D92CA7A727878B8B5AD5FBF7E5787C3D1DEED76D7319ED1845D480EFD935E48DA49A2A7442F89D7253A9B83C341BDF471ED29FC9BFD585F3B5904000000101AD64AFC3F895F249648B44A4848D0D18309E5BD4092C23CD9346ADAB4E9B4AD5BB7FE6927952B490EFD935E44BA5B62B21DDF19CFF5849A001619CFC5A23A36F82489353E4963C70ABCB7EFEB0100000004BE4976E8DC25FB2FB9E492E7657B41794F76BBDD91BABDF0C20B77A7A6A6B6379EF94BF6931CFAA736123F4BFC28116F3C13CE7C6B3FF6A2C44F123B8DA79770B8FDBCBAF6598382A3BCB7EFEB2F334C4803000000040B6BF50287C3D1F728CF8BB5B73D7BF4E8B16FFEFCF945C15E30819C1C6A2278929DF91795CAE24798831797EAFE0E7602996D0E9F61A8AC35744ABF1E40F0D57D7AED404F7B3BA1D4E3BA4FCF260E91C8A1B800E0B8D532652F23D6C06E97013562C08001E79B8AAF59D82E3131B1BB6CE7931C0648E65F86D249DDEE637C5F924220780D369EEB96B592BF52A27EA924501F1F43620800C725CE4EFEF4529E4DE6E0F2615EBA5E9C8EEA4AA6A85053A64E9DAAA3040FE9244A4A4A1A693C9D444FA4A6A68E0CC57289E0D000108266DA49E17C3B319C663C43CEF55A826F243E97B85E628B442AC50500C7447B5874D28EAFEC44F076E3991B42696F61671243C03F855104A892032B2CCCED72B928083F209FC346E3197A8D435D2331D0787A0775522B9DE27ABAF19CE1DE20F182443B8A29F4381C8E03D45F7E537F591B4A22E0E8F262CFFBDCBFD44E121BDBF5EA54E33941F70A4505901C2204C4C4C4ECDCB3670F05E107B2B3B335D949A3240EA3D7152F2AE7B10724BA19465784E60F6358D832EA2FFF909F9FAF6B8DADA22402D2ABC6B316B5D75A3BD6D9F767489C463101248708019191918B72737329083F909191A16BF4CCA7244AE830D297EDDB1B7CF67B7B575B19CFF588BF5054A1A9B8B878E6EEDDBB775012352F3B3B3B533E8FAF288980A31301EAB586B796F3F81CDAA100C9214288D3E97C6EFBF6ED07DC6E378551B3366465657595ED2714C521C9E1709FDB2579B4BDD5EB0C67DAB7EB515CA147EAAD4F32323222A8BF6A9EFC8E14537F051C9D8CE6DC233CDECA789609538CCE00480E110A2EBAE8A29FA561B57CDBB66D14460D4A4F4F9F239FC3B6CB2EBBEC274AE360C26C3C6B97FECD78868F7A797B0EF58CF79B124F49D07B14827AF5EA95565454F4DF4D9B366DA6346ACE962D5BB20E1C38F01BF557C0D1D12A13EDDBE3CB686B6EA01D0A901C2204399DCE811B366CD89797974761D4809C9C9CE959595957B95CAE07298D32E9CC79238DA7F77080C4FD76E87D5DC6E25DE39994062148BF37921CC6E6E6E6B29C490DD8BB776FE1FAF5EBDDC5C5C5F7511A01EB1E893BCCC109851A9B8313D2FC28F1BD4412C504901C2244F4EEDD7B9534B0AE59B972652E0962F527862B56ACE8EC7038EE90CF219D122953BEB7B8242E97B8D68E0FECC64B4F89188A2974EB2FD924A7A7A7EF9104713725528D5FCCFCFCECB4B4B45D727310F557407BDD1C1C91A13397EA440451123ADBD385127F95D84A3101248708213D7BF69C5B545474FDB265CBF2366DDA94C5353C556E833466C72D5FBEFC3CB97DBF94FF0C8AA44C99C633E18C267F19653C3ED77866323D9FA20AEDFACBE572DD26F59763EDDAB50BA9BFAADEFAF5EBFFBB74E9D22229F7BBA8BF025AAC44A47D5BAF2B4CF3094DF86B49BC26D186A202FC4B384580AA3671E2C4752929299FE7E6E676DDB66D5B9CD3E95C131616E6888E8EAEE37038FCF6EF5EB76E9D79FBEDB74D93264D4CC3860DFDF6EFD4750CB3B2B2BE9746D592D5AB57C717141444C8BE945EBD7A2DE2E82BD77E3BF4ACF6DA232490EBCA7AA053A74E3D64A3F19D24E3F329CEE0AEBF060E1CF8457E7EFEA55BB66CA9B577EFDE9FA4FEDA131313535FEA2F26D338F1FACB29BF0DCB376EDC982EF5973B27276787ECBB91FA2BE03925B2ECDB655DBB5D28A1B3D06653C7C29F70EC314B14AA893D44ABF7ECD9B3CFD8BE7D7B3F09FDE2E9B55D7E3B6CEFD34F3FD569D4CDD8B1634DFFFEFDFDB9789B49E810ACDF255E61F2860AB9D778D6D83A9A2DE6E0B0288476FD75B9D65FBB76EDEA27D18352A9D476885E93B64CE29FD45F416395A9D8845E7A9D37EBF002248708553A0B6020FC100C1A3428C6E97416E86DBD5E72F2E4C9B113264C70F209068D938CE7CCE0919C2AA1D79A31290D02AAFE02FCC07512BF55A01E1EC4770A203904FC9E2486875C6B565858A889C44C4A2668FC293141E24AE3E941AC630E4E50E3D5DD78CE7E03008E8F2688A7DB75ED7C7BDF5512538C67E4D0188A08F02F4C480394ED16DF3B6EB7FB768A24E8E8B0E67EF6ED39C6B3AEE1488961F63EBD163193620280E3E69D6DB681C469765C6BEFDB48F100248740409064B04FA95D3DFAF7EF5F8792092ABA84C577F6EDB72586DBC9A177228C0C8A08002AC51289FFDA0180E410081CC9C9C97D1C0E47A2CF2E9DD5B2517878781F4A070000002487408870B95CBD4BEDF22E6E760DA513129A53040050A9E2259AD80180E410080C3D7AF48870381CB795DA1D6D6FFBEA2CA69452506A653C434A35064834A24800E08445D95B5D6EA9B61DA32816C07F315B29E0A3499326E7BBDDEEB8321ED2652CEA141616EAD0D2CF29A9A0E19D2C6124450100956EA0BD65E66780E410083C479895B45022461EBF86E43028B4329EF5B554A7233C4F27A5610913003836BAB8FD2947798E8E5ECB95B89AE202480E01BFA3434A75965287C351D6C3F5ECE45187963E3861C2841C4A2CA04DA8C07362A82301E0B8DC491100248740404B4848E8516A96D2434862B8471EAF5F5050A08BA3CFA0C402DA068A000000E0504C480378BF0C6161479C8D5412C3227B7B0BA515F0DE349EA1A5A5E95A969C340380139326D1B88CFDC91271140F407208048294A33CDE40FFE376BB7BEA10548A2BA06D2D635F07892F8D67382900E0F85D56C63EBDA65FAF43CCA378009243C0AFDD70C30D3DBDC9DFD1E8D0D2934E3AE97A4A2DA02D92C8F7B95F5FE21989FEA5F603004E9CFEBEEA1AB24F501400C921E0F724E1EB768CCFEF40A905BC4C9FDB8325EE28B50F005039869318028181A17180983A75EAB3B279D6775F5252D248D98CD01FB4D4D4D4919452D0D1DEE2B912ED247E213104804A3547E23A895A12FF32655F83A89D143B282A80E410006A9A0E251D6F27876B25CA9A68E87B8977282A0038667ADDE1D9128F4A3C68CABE742392E410203904007FF0B11D0F1B4F0F621A450200956AA6C46CE399219AB50F8100C035870042DD0B12BA7665278A02002A9DCB4E0C87521400C921000482D724FA18CF3A870080CAF7A2C41914034072080081942002002ABF7DE9349E6B1001901C02805FD1464A4C19FB32241A513C0070427492995D65EC7F57E2648A07F05F4C48032014FD54CEFE45D48B0050A536520480FFA2E710000E55441100000092430000000000C9210000000080E410000000004072080000000020390400000000901C0200000000480E01000000002487000000000092430000000000C9210000000080E410000000004072080000000020390400000000901C5204000000000092430000000000C9210000000080E410000000004072080000000020390400000000901C0200000000480E01000000002487000000000092430000000000C9210000000080E410000000004072080000000020390400000000901C0200000000480E01000000002487000000000092430000000000C9210000000080E410000000004072080000000020390400000000901C0200000000480E01000000002487000000000092430000000000C9210000000080E410000000004072080000000020390400000000901C02000000008E2C82220080F20D1830E03187C3F14C390F8F484A4A1AE1BB233535D541A90100804044CF21001CA9920C0B4BA314000000C9210084B82953A6CC944D56059FBE851203000024870010A4DC6EF7A74779CA01FB7933292D000040720800C19B1C4E3DCAE32EDD3A1C8EC994160000203904802055AB56AD4592F8ED2CEF71792C5A36991919198B282D000040720800416AC284094EB7DBFD55390F5BBD86F2F8E7F3E7CF2FA2B4000000C9210004B7F7CBD95F6C55A661619F5044000080E41000829C3D6434AF8C872225B66CDFBE7D2EA5040000480E0120C8D943462796DAED1D523A9321A5000080E4100042842481B34ADD77D937BFA174000000C9210084881D3B76E83A86DBBDF71D0E47846C325D2ED70C4A070000901C024088B0878ECE2AB57BE6B469D3F2291D000040720800A1E590594B1D0E07B39402000092430008353131313FF9DE8F8E8E9E4FA9000000924300083113264C70CA6695DE76381CEBE47E0EA50200008241044500A0A6B9DDEE98F5EBD7DF9B9F9F3F70DFBE7DA7EEDDBB37C6E572F9EDDF9B9999697EFEF96773F6D967B7B9EDB6DBDCFEFA774AF2EA8E8E8EDE1D1515F5F38103075EE8DEBDFBB71C6D000080E410805F92A4F07F7FF9E597179D4E67ADC4C444A351B76E5D1316E6DF031BAEBBEE3ABF2F5B49B01D927037CACBCBBB222323A3E782050B7E2F282818D8BB77EF748E3C0000501AC34A01D4984D9B367DBE71E3C637E3E3E36B9D73CE39A665CB96A65EBD7A7E9F18064C052FE5181717679A376F6EBA75EB16D5A2458BAEDA8B386FDEBC6B281D0000407208C06F1243896B3A76EC689A356BA6432029942AD6B46953D3B56BD758491A27CD9D3BF74A4A040000901C02A8513A9474DDBA75D79C7AEAA956CF566985F93BCC96B44966CDB74F9AD5F3469A4D4BC71B67DE560AAE12D4AE5DDB74E9D2A5AE24E39366CD9AD589120100002487006A844E3E939999F9A20E212D2F31DCBCF43D939FB9DAB88AF71BB7ABC8ECCBFAD36C5AF22E0962252688AD5AB572858787BF426900000092430035426725D5C96774886359B2362E3445FBF71EB65F13C5CCF5F329C04AD2BC79F386111111EDE7CC99733EA5010000480E01543B5DAE4267242DEF1AC38223F40E6AAF222A4F424242866CFA5112000080E41040B5D3750C7546D2F2B88B0F94FF62B78B02AC448D1A356A269B1E9404000050AC7308A05AE902F7BA8E216A9E7C0E4D64D398920000008A9E4300D5CAE572B18EA1BFFC00783E074E12020000924300FE2732B641B98F4544D3E30800004072082024346C79818988AA7DD8FEF0C858D3F0E4EE1410000000C921805050A7F169A676A353CBDC5F37A123050400004072082054141F28386C5F51E11E0A06000080E4104028D8BF7797D9B4E45D93BFEBF7C31EDBBBFB0FB3E99771D6730000004072082048E56E5B2A89E13B665FF6FA729FB32F67A3D9F0F39B267BD30FC6CD9A87000000958A29CC01D428ED09DCB1E62BAB67B0225CC5FBADE7EFD9F5BB4938E50A13632DD5070000801345CF21801AA53D81154D0C7D690FE3C6FFBE4D01020000901C020806DA1378BCDCAE220A100000A09230AC14408DEAD0731485000000E007E8390400000000901C0238E1FA807A040000200830AC14F0FF84ADB1C49912F5EC6DBCFDD83F25B6977AFE5FECED8F3EDF71BD30AF8EC4DF25A2259E29E7DFEA2B71AEC463E53C1E23718DC4D452FBC7497C20F1ADC4C9121BF9D8000000480E01541E4D02CF96D82DB1C04ECCFE23B1D0E7391D2456D989DB60892D127F9338456280C42B12A74BAC95182F91EDF3DA2E128912DE05033BDB8FF7B4EF37B0B7D3ECAD53E277FB7D574BB4B15FDBD24E5C6F95E828F1301F1D000000C92180CAD1CE4EDE34F9AA25D1C24E14DB98833D87DAAB78B9C493129B25E64A4449DC213156E2FF493497D82AF14519FFC669F66BF6F824837BEC4454F5F14910BD964BA4DB7F97BEBEC0E7B18BCCE1BD8A00000008105C2B04F827EDE9FBDC4E08CB932431CC4E0CD52A3B59D4EFF51A73682FA1D7E9A5EE174AECB7E380F10C41F5DED7DBB9F6F39A495C67279D5DEC24748AFD376EB0B7B7DAFBEBF0F1010000041E7A0E01FFA5BD730DECC44BE9F582DBCCC161A53A7C74877DBB89F10C07D584F05D89D912FF90986927989A04EA904F1DFEF9A5CF7B5C650EF6FE9D6FDFF62677FABA25F66DED7DFC54E2528934FBB193EDBF5187BAF6B5FF3E4D30B567339F8F0F000080E41040E56963275EEA1C3BF9F30E2B3DC9E7793A31CD24FBB6F6EC69AFDE32E3B91E7091F10C2B6D2531BAD4FB7F592A91D3DB73EDDBDA7B1855CEDFA549638A393804D5FBF7AD344C48030000407208A052E9F050EDB1F3F6F2C5DB49E062FB7E3F9FE7FA5EA3E84D28F5F9E1127F1CE1FDEBFADC8F350767365531E6E0643565A96B27905E45A6EC6B1B010000407208E004E9904DEF75823AB94C6D73700299F77D9EB7D64E0E7598E93AE3E961D4E1A80F98436737F5A5CFE96A27754A673875DAA1128CA7F7B1B4C6F65687AA7E552A5904000000C921804A76A5F1F4E6C5FB245F453EF76F93C8349E6B00955E33F888F10CF7D424F15673709DC3B2CC2C755F7B0C7D8795CE2DE335DADBA84B66E85A897A8D615F9FC7CE29E73500000020390470024A0FD12C3D218DF60C5E613CCB4B6862F6A2CF7375E6525D03718DCFBEDA47F9F7222BF037E549BC6CDF3E60FF0D5A8F686F623D3E3200000092430095CBF71A422FBDAD8BD6FBF6D6696F622B73F03A44E393106E2FB53FFB28FFA60E13DD7394E73CE6737BB7BDD59E499DB8A6BBC4643E3A0000009243009567AD1DC7E3157BBBB8D4FE378EF2BA639D4C66B8CF6D9DA1F40E3EB6D071C30D37F40C0B0B3B3F35357514A5010000C921000495DDBB779B850B179ABE7DFB9A1F7EF8C1FCF6DB6F262121E190E74C9B36CD8C1933C6DA2FC99115F7DC738F19356A94993973A6494E4E3653A64C31B56BD736575F7D75D0944D8F1E3D22E4FFB987FCFF5E23776F9688B31F2239040080E41000824B7C7CBC69D4A8919931638689888830CD9B37377DFAF4316FBDF596E9D7AF9F69DCB8B1D9BA75AB69DAB4A9292A2A329F7DF699898C8CB46E6B52A90961464686993D7BB6B9F6DA6BCD175F7C613EF9E413337AF468EBBD0231216CD2A4C9F96EB7FBEF127D1C0E47638E120000480E01202474EFDEDDB85C2E2BC1D39E44ED299C3E7DBA292C2C34B1B1B14612244FE529C9A3F610DE7CF3CD25AF7DF5D557CD4B2FBD64EEB8E30E73C1051758BD89E3C78FB77A1703497272721F2983DE7273B02485D6BA97DEFF6F000040720800414D7BFCD2D2D2AC183870A0B54F7B12B5E770DEBC79E6FEFBEFB792C67FFFFBDF87BC2E2A2ACA4A14751B1D1D6D6AD5AA65F52EEA736362620222311C3468508CD3E93C5F12C05BE5EFBE5C12C2C624830000901C0238DC88A4A4244AA1922C5DBAD49C7EFAE9D6F04D7FA2D7105E7AE9A5562FA1F73AC3E5CB979B2D5BB658499EF612FEFEFBEFD69052AFC183079B9F7FFED96467679B5DBB76994F3FFDD44A12EBD7AF6F7AF7EE6DDE78E30DBFFE2CD6AD5B670D7B95C4B040EF4B5278CC3D84F2DD18C9510DA0B27F77290280E410E0872A04FCFAEBAFE6E4934FB6AEC9F327DAC3A7899D37F43AC2B3CE3ACB9C7BEEB9262E2ECEE4E7E75B7FF38409134A5E939B9B6B0D43AD57AF9EB9E4924BCC575F7D655AB76E6D25C093264DB27A1977ECD861EEBEFB6ED3B16347BFFB2C74C86C4E4E0EDF0D00004072081CC5048AA0F29D79E699232EBCF042BFFF3BF7EEDD6B4E3BED346B88A9F6102E5EBCD874EAD4A9E4F13FFFFCD31A76EA4D2CD7AC59630D4D3D70E08095FCEA4CA73ADC5427B2F1C7C450F5EFDFDF8C1D3BD64A724B29B27B112BF21BF1044735007E8701924320A8A5A6A66E90CD484AA272DD7EFBED23FC6D4869694EA7D36CDBB6CDEA05D4F02E4951A74E9D9244AA6DDBB6A6499326D6B585E1E1E1A64B972ED6EBF6ECD963F5362ADD6A82E8AFDAB46963AEBFFE7A3379F2E4D88282829E920CEA24347D259AFB0C2F3D20E196882AE77BC277040000924300083E3A9CF4B5D75EB36E6B8FE0FAF5EBAD2529B4E7F0F2CB2F3FE4B93AF98CD2994DDBB76F6F5D9BF8FDF7DF5BB39A6EDEBCD9ECDFBFDF3CF8E0837EFFFF3C61C204A76C6668F4E8D1E3C1C4C4C4BE6EB7BBB724887D3451F43E4FF6154A99C8C61DC391020000C921000435BDB65097A798356B96755F2799D1DEBF6EDDBA59C9A25E33599A2453D64435AB56AD32E79D775E494FA3D2496C7498A93791F477F3E7CF2F92CDC776E884333D64D34F42D7396CA7C34D010000C9210004BDF7DF7FDF2C5BB6CC0C1830C05349DAC34235F9D3896674B90AF5C30F3F987DFBF659899F5E53F8C71F7F5813D76812A8B7BD56AF5E7DC850D340939A9A3A5F7346BD2D6572BE6C6E2FDDA3080000480E01202875EDDAB5CCFD3A7BA986D245EEBD744869798EF458A0993A75EA4FB2F98923040080E01446110000000000480E01000000002487000000000092430000000000C9210000000080E410000000004072080000000020390400000000901C0200000000480E01000000002487000000000092430000000000C9210000000080E410000000004072080000000020390400000000901C0200000000480E01000000002487000000000092430000000000C9210000000080E410000000004072080000000020390400000000901C02F08B4A272CCCED72B928083F209FC346D9145112000080E41040B58B8989D9B967CF1E0AC20F646767A7CB268D92000000248700AA5D6464E4A2DCDC5C0AC20F646464E4C9663E25010000480E01543BA7D3F9DCF6EDDB0FB8DD6E0AA3666DC8CACAEA2ADB4F280A0000407208A0DA5D74D1453F4B62B87CDBB66D14460D4A4F4F9F239FC3B6CB2EBBEC274A030000901C02A8114EA773E0860D1BF6E5E5E5511835202727677A5656D6552E97EB414A030000901C02A831BD7BF75E2589C9352B57AECC2541ACFEC470C58A159D1D0EC71DF239A45322000080E410408DEAD9B3E7DCA2A2A2EB972D5B96B769D3A62CAE41AC721BD2D3D3C72D5FBEFC3CB97DBF94FF0C8A040000F80AA70800D494891327AE4B4949F93C3737B7EBB66DDBE29C4EE79AB0B030477474741D87C3E1B77F776666A699356B9669DCB8B1A955AB96DFFE9DBA8E615656D6F7EBD7AF5FB27AF5EAF882828208D997D2AB57AF451C7D00001CAA53A74E3D64A3F15D7A7AFAFC502C83080E030035498798EA66F6ECD9676CDFBEBD9F8456CAF52562FCF56F5EBA74A9F9F5D75FCDC68D1BCD59679DE5CFC5DB4C6297C4EF12AF30F90C0000203904E0F77AF5EAA58BB107C482EC4949492365334212C4271E7DF4D1917C7A0000201870CD210000000080E410000000004072080000000020390400000000901C0200000000480E01000000002487004257339FDB2DCA794E5CA9E70100000435D63904108A264844D9B775FB8CC45089111233EDFD6F4A3C4051010000924300085EF74BFC66DF9E2CB150A2AF844B62925D37BE2FB18BA202000024870010BC9AFA2487D13EFB3A482C91F8AF61D83D000020390480A0B7D7E7F69312D91299C6D38BE8358062020000A18433E30042517F896FED785B224662BEFDD84B124D24A64ADC4D510100805041CF218050F48E39F49A43A7F10C25554FD9C9A27A8FA202000024870010BCDA19CFE4335E1D7CB60DECE4B09EBD6F15C5050000480E0120387536077B0A1FB6B7F7DBDB5C9FE7D5A6A8000000C9210004A75A12D74AF494785CA2ABC4B2729E7B9EC4588A0C0000901C0240F0D927D1CDBE7D92C44D12BB25BE2EE3B92B282E000040720800C16F87F1CC48AA75A12E5D319922010000A18AA52C0050FF19534462080000421D3D87004291CE48FAA9C41B7692B844A29F397CE98A5D141500000815F41C020845D912DB2492253EB1F77591F8ABF15C8778A9C4E912DF52FE932C07000003F5494441545400002054D073082014F5B5B7C34AED4F97586B3C6B20EAF588D75154000080E4100082538C9D149E2DD1CADE774B19CFDB4D51010000924300085E4EE359CA4227A0192DB1C627490400002039048010D4C74E0EF5FAEBCE12E37C1ED37D7B25AEA098000000C9210004AF27ECC430CE4E04BBD8FBE30D434A0100400862B65200A1EA747BABCB5AACF2D9AF89E1788A070000841A7A0E0184A2A1E6E09A868F4B9C52EA713D713656E2018A0A0000901C0240F01AED73FB55E359C202000020A431AC1440A8DB4A11000000901C02403645000000C0B05200A1E96EE359A2E24A895F8C67C90A1525B1DFE7796324BEA2B8000000C9210004A73724DE329EE52C6E349E252D543B890D1245127524FE4E720800004205C34A0184A29B24EA19CF8CA40DEC7D174B1CB01342633FFE0A45050000480E012078E9BA86ED7C423D24B151A2BF7D5F27AA29A2A8000000C9210004AFFFDAF1A6F10C236D2C7197FDD80289161411000008355C73082054FD3F896EF6F6050997BD5F7B0BF51A44BDD690994C010000C9210004B9977CB62F957A2C46E23C893612E3292A0000100A18560A20542D2C753F4EE212FBB653E23B1243000040720800C16DB4C4FFF824859A08E6497C6B3C3398B6A188000000C92100043F1D46EA5DECFE79E359C6C2EB01899E121F514C0000209470CD218050B4DBE7F69D653CFE6F899F29260000104AE8390480B2A5510400002094D0730820547D616F9F92D829B1D91C5CCE42FDDDAE23DF38C27B8C484A4AA2240100080E23480E0120343D26B156A2AE44BCC4B3C673EDA10E336D29D14262383F24000080E41000829F4E4AB3DB8E4724A22466D9DBBF1EE17513283A00008216BFF30010624EB7B78D25FE22F1B644079FC78750440000000010DC3E9538C778868ED63AC2F352282A0000102A18560A20144D918891686547794EA1A80000000020789D6227878D7D6E4FB6B76FDB5B8D3A141500000815F41C0208554EBB0E8CB16F7BF74D9328B203000080E41000825C3BE3E9196C2011EDB32FD77826A8594811010080501246110008510724B225D6D9B71FB7B73B255EA6780000000020F8C51CE5F1361411000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040D9FE3F95B3FBD6F91ADCBB0000000049454E44AE426082',NULL),('212504',1,'请假流程.bpmn20.xml','212503',X'3C3F786D6C2076657273696F6E3D27312E302720656E636F64696E673D275554462D38273F3E0A3C646566696E6974696F6E7320786D6C6E733D22687474703A2F2F7777772E6F6D672E6F72672F737065632F42504D4E2F32303130303532342F4D4F44454C2220786D6C6E733A7873693D22687474703A2F2F7777772E77332E6F72672F323030312F584D4C536368656D612D696E7374616E63652220786D6C6E733A7873643D22687474703A2F2F7777772E77332E6F72672F323030312F584D4C536368656D612220786D6C6E733A61637469766974693D22687474703A2F2F61637469766974692E6F72672F62706D6E2220786D6C6E733A62706D6E64693D22687474703A2F2F7777772E6F6D672E6F72672F737065632F42504D4E2F32303130303532342F44492220786D6C6E733A6F6D6764633D22687474703A2F2F7777772E6F6D672E6F72672F737065632F44442F32303130303532342F44432220786D6C6E733A6F6D6764693D22687474703A2F2F7777772E6F6D672E6F72672F737065632F44442F32303130303532342F44492220747970654C616E67756167653D22687474703A2F2F7777772E77332E6F72672F323030312F584D4C536368656D61222065787072657373696F6E4C616E67756167653D22687474703A2F2F7777772E77332E6F72672F313939392F585061746822207461726765744E616D6573706163653D22687474703A2F2F7777772E61637469766974692E6F72672F70726F63657373646566223E0A20203C70726F636573732069643D2270726F636573735F6C6561766522206E616D653D22E8AFB7E58187E6B581E7A88B2220697345786563757461626C653D2274727565223E0A202020203C73746172744576656E742069643D22737461727422206E616D653D227374617274222F3E0A202020203C757365725461736B2069643D22757365723122206E616D653D22E7BB8FE79086E5AEA1E689B9223E0A2020202020203C657874656E73696F6E456C656D656E74733E0A20202020202020203C61637469766974693A7461736B4C697374656E6572206576656E743D226372656174652220636C6173733D22636F6D2E6C656E2E6163746C697374656E65722E4163744E6F64654C697374656E6572222F3E0A2020202020203C2F657874656E73696F6E456C656D656E74733E0A202020203C2F757365725461736B3E0A202020203C73657175656E6365466C6F772069643D227369642D30443235384332342D314631392D343233332D413937362D4130443843423944414541432220736F757263655265663D22737461727422207461726765745265663D227573657231222F3E0A202020203C757365725461736B2069643D22757365723222206E616D653D22E4BABAE4BA8BE5AEA1E689B9223E0A2020202020203C657874656E73696F6E456C656D656E74733E0A20202020202020203C61637469766974693A7461736B4C697374656E6572206576656E743D226372656174652220636C6173733D22636F6D2E6C656E2E6163746C697374656E65722E4163744E6F64654C697374656E6572222F3E0A2020202020203C2F657874656E73696F6E456C656D656E74733E0A202020203C2F757365725461736B3E0A202020203C6578636C7573697665476174657761792069643D227369642D35353636443037362D414234432D344134322D393938462D323533373738394638313831222F3E0A202020203C73657175656E6365466C6F772069643D227369642D33334642463234452D464537302D343730412D394442352D3942313838314531333834372220736F757263655265663D22757365723222207461726765745265663D227369642D35353636443037362D414234432D344134322D393938462D323533373738394638313831222F3E0A202020203C6578636C7573697665476174657761792069643D227369642D42453337324431342D463530392D344544422D383745382D374232313037383335414535222F3E0A202020203C757365725461736B2069643D227573657222206E616D653D22E8B083E695B4223E0A2020202020203C657874656E73696F6E456C656D656E74733E0A20202020202020203C61637469766974693A7461736B4C697374656E6572206576656E743D226372656174652220636C6173733D22636F6D2E6C656E2E6163746C697374656E65722E4C656176654C697374656E6572496D706C222F3E0A2020202020203C2F657874656E73696F6E456C656D656E74733E0A202020203C2F757365725461736B3E0A202020203C656E644576656E742069643D22656E6422206E616D653D22656E64222F3E0A202020203C73657175656E6365466C6F772069643D227369642D35343537313339312D463242332D344342342D383041302D3039324441303237373341372220736F757263655265663D22757365723122207461726765745265663D227369642D42453337324431342D463530392D344544422D383745382D374232313037383335414535222F3E0A202020203C73657175656E6365466C6F772069643D227369642D41453541454438342D303734362D343738372D393836462D36413739323743333443333422206E616D653D22E5908CE6848F2220736F757263655265663D227369642D42453337324431342D463530392D344544422D383745382D37423231303738333541453522207461726765745265663D227573657232223E0A2020202020203C636F6E646974696F6E45787072657373696F6E207873693A747970653D2274466F726D616C45787072657373696F6E223E3C215B43444154415B247B666C61673D3D747275657D5D5D3E3C2F636F6E646974696F6E45787072657373696F6E3E0A202020203C2F73657175656E6365466C6F773E0A202020203C73657175656E6365466C6F772069643D227369642D34373638373538312D333535422D343335342D383433432D43333034323333323836414622206E616D653D22E5908CE6848F2220736F757263655265663D227369642D35353636443037362D414234432D344134322D393938462D32353337373839463831383122207461726765745265663D22656E64223E0A2020202020203C636F6E646974696F6E45787072657373696F6E207873693A747970653D2274466F726D616C45787072657373696F6E223E3C215B43444154415B247B666C61673D3D747275657D5D5D3E3C2F636F6E646974696F6E45787072657373696F6E3E0A202020203C2F73657175656E6365466C6F773E0A202020203C73657175656E6365466C6F772069643D227369642D46423539344242452D383030352D344544432D423343382D39373831454432323643393522206E616D653D22E4B88DE5908CE6848F2220736F757263655265663D227369642D35353636443037362D414234432D344134322D393938462D32353337373839463831383122207461726765745265663D2275736572223E0A2020202020203C636F6E646974696F6E45787072657373696F6E207873693A747970653D2274466F726D616C45787072657373696F6E223E3C215B43444154415B247B666C61673D3D66616C73657D5D5D3E3C2F636F6E646974696F6E45787072657373696F6E3E0A202020203C2F73657175656E6365466C6F773E0A202020203C73657175656E6365466C6F772069643D227369642D39394343413337462D413233352D343835332D383437322D44453233334144324544333222206E616D653D22E9878DE696B0E794B3E8AFB72220736F757263655265663D227573657222207461726765745265663D227573657231223E0A2020202020203C636F6E646974696F6E45787072657373696F6E207873693A747970653D2274466F726D616C45787072657373696F6E223E3C215B43444154415B247B666C61673D3D747275657D5D5D3E3C2F636F6E646974696F6E45787072657373696F6E3E0A202020203C2F73657175656E6365466C6F773E0A202020203C73657175656E6365466C6F772069643D227369642D35313046453036322D433042432D343643382D394231372D38413338303732413242433622206E616D653D22E4B88DE5908CE6848F2220736F757263655265663D227369642D42453337324431342D463530392D344544422D383745382D37423231303738333541453522207461726765745265663D2275736572223E0A2020202020203C636F6E646974696F6E45787072657373696F6E207873693A747970653D2274466F726D616C45787072657373696F6E223E3C215B43444154415B247B666C61673D3D66616C73657D5D5D3E3C2F636F6E646974696F6E45787072657373696F6E3E0A202020203C2F73657175656E6365466C6F773E0A202020203C73657175656E6365466C6F772069643D227369642D30344339463239412D304242352D343639312D383034432D37363445344530413237313622206E616D653D22E58F96E6B688E8AFB7E581872220736F757263655265663D227573657222207461726765745265663D22656E64223E0A2020202020203C636F6E646974696F6E45787072657373696F6E207873693A747970653D2274466F726D616C45787072657373696F6E223E3C215B43444154415B247B666C61673D3D66616C73657D5D5D3E3C2F636F6E646974696F6E45787072657373696F6E3E0A202020203C2F73657175656E6365466C6F773E0A20203C2F70726F636573733E0A20203C62706D6E64693A42504D4E4469616772616D2069643D2242504D4E4469616772616D5F70726F636573735F6C65617665223E0A202020203C62706D6E64693A42504D4E506C616E652062706D6E456C656D656E743D2270726F636573735F6C65617665222069643D2242504D4E506C616E655F70726F636573735F6C65617665223E0A2020202020203C62706D6E64693A42504D4E53686170652062706D6E456C656D656E743D227374617274222069643D2242504D4E53686170655F7374617274223E0A20202020202020203C6F6D6764633A426F756E6473206865696768743D2233302E303030303030303030303030303037222077696474683D2232392E3939393939393939393939393939332220783D2234352E30303030303030303030303030312220793D2235342E3939393939373335303930343633222F3E0A2020202020203C2F62706D6E64693A42504D4E53686170653E0A2020202020203C62706D6E64693A42504D4E53686170652062706D6E456C656D656E743D227573657231222069643D2242504D4E53686170655F7573657231223E0A20202020202020203C6F6D6764633A426F756E6473206865696768743D2238302E30222077696474683D2239392E39393939393939393939393939372220783D223135302E30303030303030303030303030332220793D2232392E3939393939373335303930343634222F3E0A2020202020203C2F62706D6E64693A42504D4E53686170653E0A2020202020203C62706D6E64693A42504D4E53686170652062706D6E456C656D656E743D227573657232222069643D2242504D4E53686170655F7573657232223E0A20202020202020203C6F6D6764633A426F756E6473206865696768743D2238302E30222077696474683D2239392E39393939393939393939393938392220783D223435342E353435343431333138323233322220793D2232392E393939393936343536383335303633222F3E0A2020202020203C2F62706D6E64693A42504D4E53686170653E0A2020202020203C62706D6E64693A42504D4E53686170652062706D6E456C656D656E743D227369642D35353636443037362D414234432D344134322D393938462D323533373738394638313831222069643D2242504D4E53686170655F7369642D35353636443037362D414234432D344134322D393938462D323533373738394638313831223E0A20202020202020203C6F6D6764633A426F756E6473206865696768743D2233392E3939393939393939393939393939222077696474683D2234302E302220783D223636302E303030303030303030303030312220793D2234392E3939393939373335303930343634222F3E0A2020202020203C2F62706D6E64693A42504D4E53686170653E0A2020202020203C62706D6E64693A42504D4E53686170652062706D6E456C656D656E743D227369642D42453337324431342D463530392D344544422D383745382D374232313037383335414535222069643D2242504D4E53686170655F7369642D42453337324431342D463530392D344544422D383745382D374232313037383335414535223E0A20202020202020203C6F6D6764633A426F756E6473206865696768743D2233392E3939393939393939393939393939222077696474683D2234302E302220783D223331352E303030303030303030303030312220793D2234392E3939393939373335303930343634222F3E0A2020202020203C2F62706D6E64693A42504D4E53686170653E0A2020202020203C62706D6E64693A42504D4E53686170652062706D6E456C656D656E743D2275736572222069643D2242504D4E53686170655F75736572223E0A20202020202020203C6F6D6764633A426F756E6473206865696768743D2237392E3939393939393939393939393937222077696474683D223130302E30303030303030303030303032332220783D223238352E30303030303030303030303030362220793D223139352E3030303030303030303030303033222F3E0A2020202020203C2F62706D6E64693A42504D4E53686170653E0A2020202020203C62706D6E64693A42504D4E53686170652062706D6E456C656D656E743D22656E64222069643D2242504D4E53686170655F656E64223E0A20202020202020203C6F6D6764633A426F756E6473206865696768743D2232372E393939393939393939393939393933222077696474683D2232382E302220783D223832352E303030303030303030303030322220793D2235352E3939393939373335303930343634222F3E0A2020202020203C2F62706D6E64693A42504D4E53686170653E0A2020202020203C62706D6E64693A42504D4E456467652062706D6E456C656D656E743D227369642D30344339463239412D304242352D343639312D383034432D373634453445304132373136222069643D2242504D4E456467655F7369642D30344339463239412D304242352D343639312D383034432D373634453445304132373136223E0A20202020202020203C6F6D6764693A776179706F696E7420783D223333352E30303030303030303030303031372220793D223237352E30222F3E0A20202020202020203C6F6D6764693A776179706F696E7420783D223333352E30303030303030303030303031372220793D223332312E30222F3E0A20202020202020203C6F6D6764693A776179706F696E7420783D223833392E303030303030303030303030322220793D223332312E30222F3E0A20202020202020203C6F6D6764693A776179706F696E7420783D223833392E303030303030303030303030322220793D2238332E3939393939373335303930343634222F3E0A2020202020203C2F62706D6E64693A42504D4E456467653E0A2020202020203C62706D6E64693A42504D4E456467652062706D6E456C656D656E743D227369642D35313046453036322D433042432D343643382D394231372D384133383037324132424336222069643D2242504D4E456467655F7369642D35313046453036322D433042432D343643382D394231372D384133383037324132424336223E0A20202020202020203C6F6D6764693A776179706F696E7420783D223333352E343432303733313731363637352220793D2238392E3535373932343137393233373233222F3E0A20202020202020203C6F6D6764693A776179706F696E7420783D223333352E313231353830353435313534372220793D223139352E3030303030303030303030303033222F3E0A2020202020203C2F62706D6E64693A42504D4E456467653E0A2020202020203C62706D6E64693A42504D4E456467652062706D6E456C656D656E743D227369642D30443235384332342D314631392D343233332D413937362D413044384342394441454143222069643D2242504D4E456467655F7369642D30443235384332342D314631392D343233332D413937362D413044384342394441454143223E0A20202020202020203C6F6D6764693A776179706F696E7420783D2237352E302220793D2236392E3939393939373335303930343634222F3E0A20202020202020203C6F6D6764693A776179706F696E7420783D223135302E30303030303030303030303030332220793D2236392E3939393939373335303930343634222F3E0A2020202020203C2F62706D6E64693A42504D4E456467653E0A2020202020203C62706D6E64693A42504D4E456467652062706D6E456C656D656E743D227369642D39394343413337462D413233352D343835332D383437322D444532333341443245443332222069643D2242504D4E456467655F7369642D39394343413337462D413233352D343835332D383437322D444532333341443245443332223E0A20202020202020203C6F6D6764693A776179706F696E7420783D223238352E30303030303030303030303030362220793D223233352E30303030303030303030303031222F3E0A20202020202020203C6F6D6764693A776179706F696E7420783D223230302E302220793D223233352E30303030303030303030303031222F3E0A20202020202020203C6F6D6764693A776179706F696E7420783D223230302E302220793D223130392E3939393939373335303930343634222F3E0A2020202020203C2F62706D6E64693A42504D4E456467653E0A2020202020203C62706D6E64693A42504D4E456467652062706D6E456C656D656E743D227369642D41453541454438342D303734362D343738372D393836462D364137393237433334433334222069643D2242504D4E456467655F7369642D41453541454438342D303734362D343738372D393836462D364137393237433334433334223E0A20202020202020203C6F6D6764693A776179706F696E7420783D223335342E353536333634373232353534352220793D2237302E34343336333236323833353032222F3E0A20202020202020203C6F6D6764693A776179706F696E7420783D223435342E353435343431333138323233322220793D2237302E3134373838353935303338353032222F3E0A2020202020203C2F62706D6E64693A42504D4E456467653E0A2020202020203C62706D6E64693A42504D4E456467652062706D6E456C656D656E743D227369642D46423539344242452D383030352D344544432D423343382D393738314544323236433935222069643D2242504D4E456467655F7369642D46423539344242452D383030352D344544432D423343382D393738314544323236433935223E0A20202020202020203C6F6D6764693A776179706F696E7420783D223638302E353030303030303030303030312220793D2238392E3439393939373335303930343634222F3E0A20202020202020203C6F6D6764693A776179706F696E7420783D223638302E353030303030303030303030312220793D223233352E3030303030303030303030303036222F3E0A20202020202020203C6F6D6764693A776179706F696E7420783D223338352E303030303030303030303030332220793D223233352E3030303030303030303030303036222F3E0A2020202020203C2F62706D6E64693A42504D4E456467653E0A2020202020203C62706D6E64693A42504D4E456467652062706D6E456C656D656E743D227369642D33334642463234452D464537302D343730412D394442352D394231383831453133383437222069643D2242504D4E456467655F7369642D33334642463234452D464537302D343730412D394442352D394231383831453133383437223E0A20202020202020203C6F6D6764693A776179706F696E7420783D223535342E353435343431333138323233312220793D2237302E3134323037383834393533323231222F3E0A20202020202020203C6F6D6764693A776179706F696E7420783D223636302E3434333030353038333433392220793D2237302E3434333030323433343334333434222F3E0A2020202020203C2F62706D6E64693A42504D4E456467653E0A2020202020203C62706D6E64693A42504D4E456467652062706D6E456C656D656E743D227369642D35343537313339312D463242332D344342342D383041302D303932444130323737334137222069643D2242504D4E456467655F7369642D35343537313339312D463242332D344342342D383041302D303932444130323737334137223E0A20202020202020203C6F6D6764693A776179706F696E7420783D223235302E302220793D2237302E31383434393931393539323331222F3E0A20202020202020203C6F6D6764693A776179706F696E7420783D223331352E34323539323539323539323630342220793D2237302E3432353932333237363833303536222F3E0A2020202020203C2F62706D6E64693A42504D4E456467653E0A2020202020203C62706D6E64693A42504D4E456467652062706D6E456C656D656E743D227369642D34373638373538312D333535422D343335342D383433432D433330343233333238364146222069643D2242504D4E456467655F7369642D34373638373538312D333535422D343335342D383433432D433330343233333238364146223E0A20202020202020203C6F6D6764693A776179706F696E7420783D223639392E353630313236353832323738362220793D2237302E3433393837303736383632363135222F3E0A20202020202020203C6F6D6764693A776179706F696E7420783D223832352E303030303639363538383436312220793D2237302E3034343136313136393031353535222F3E0A2020202020203C2F62706D6E64693A42504D4E456467653E0A202020203C2F62706D6E64693A42504D4E506C616E653E0A20203C2F62706D6E64693A42504D4E4469616772616D3E0A3C2F646566696E6974696F6E733E',0),('212505',1,'请假流程.process_leave.png','212503',X'89504E470D0A1A0A0000000D494844520000035F0000014B0806000000299E36CD000022BE4944415478DAEDDD0D8C94F5B928F04D0AA949DBD4269AB4699BDA734F9A93DEA4C734986A3C369BA64D6C6A234DC57559AA5B6BA1D7A245D1D45AA8D61B2247AD043C0D6AF1B3AD4288410FF5822E2B5F453842391641A920C8C7F2B1A80B0559387CBCF77DA6F36E8665665976677767677FBFE49F9D9D995DE0E5F93FFFE779BFA6A6060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006429224C3B66CD93277D5AA55279A9B9B93A6A626A31FC7A2458B9265CB96BD978E31A211E42FF90B00AA58142ECB972F4F5A5B5B93A3478F1A0330F6EDDB972C5DBAF4405AC85C252241FE92BF00A04AC51E63854B451430479B9A9ADE1291207FC95F0050A5E2541DC543658CB47839262241FE92BF00A04AC579FB0A878A295E121109F297FC050043BC7839B47F77B265F513C98645F7E4463C8EE7141D8A1790BF0CF90B00CA54BC1C6C6B49D6BF3439F9EB8BB79F32E2B9784DE1A17801F94BFE1291005086E265C786FF3CAD70C9C6CE0DF3151E8A1790BFE42FF90B00CA51BCBCB5F8DF4B162FF19AC243F102F297FC252201A00CC5CBFAA6BB4B162FF19AC243F102F297FC25220140F1A27801F94BFE92BF006070142F7177B052C54BBCA6F050BC80FC257F8948002843F1B269C57F942C5EE2358587E205E42FF94B440240198A97F75BD625EB5FBEEBF45376D2E7E2358587E205E42FF94B440240198A97185BD73C7D5AF112CF293A142F207F19F2170094AB78397224D9F4EACCD34FD9499F8BD7141E8A1790BFE42F110900BD2C5E0EB6B5246FAF78A8E43513F15ABC47F1A17801F94BFE02007A52BC1C3992ECDEF44AF2C6C23B4B162ED988F7C47BED4556BC80FC257F01006751BC9C696FB1BDC88A1790BF0CF90B00CA50BC74676F71577B9115228A970A73AE4D207FC95FF217722C4045162F3D2D5CB2A11051BC5490CBD391E4BF227FC95FF217722C4065152F86E2A54A8C4C475B3AEE4FC7BE745C6393C85F86FC851C0BA07831142FE5D5982F066AF3DF5F98FFFE069B46FE32E42FE45800C58BE245F152DEA26044A7E71507F297217F21C702285E0CC54B99DC918E1DE9B8B8C4EBFF928EADE9186F53C95F86FC851C0B43527D7DFD79757575E3AFB9E69ADFA763753A0EA62349477BFAFC7FA7AF3F9B3EBE6DD4A8519FB6B5142F8A174AB83B5F145C7086F77D2E1D6FA463663A86D96CF297217F21C7A2571812D28D74414343C3A3D75E7BED7B93274FDEF4FCF3CFEFDAB061436B7B7BFBB12475F8F0E19D1B376EDC3C67CE9C2513274E5C9E6ED8F7D29F99996ED87FB6F5142F8A170A4CEB665190895B23AF4EC7EF1507F297217F21C752B9BD42D4FEE9D8976FB6CE34DAF50A25A40DD71DE938347BF6ECF60F3FFC30E98EB4296B9F39736653BA51F7A76392ADA87851BC90FA5D3AFE3B1D67BBB72B8A83A6743CA13890BF0CF90B39968A6BBC6E2B38C275B6E3985E212FED443F3E7EFCF895F7DE7BEF91D6D6D6A427DE7BEFBD0337DD74D37FA51B757E6363A30FF753BC285E86A6610545C1793DFC1DE7A463793AE6E51F237F19F217722C03DC2BD4D5D5CDEBDC504D9E3C39993F7F7EB27DFBF6E4EF7FFF7BAE278803382D2D2DC9C2850B932953A6146BC28676AF70F7DD779FFBB39FFD6CDF534F3D951C3F7E3CE9ADE9D3A7BF515F5FFFD7380F54A82A5E142F434A2CE2F3D3B1B8077B634BFDAE26C581FC65C85FC8B10C6CE395BFA6EB94A6EBEDB7DFEE566FF0EEBBEF26F7DC73CF290D58FE9AB0A1D72B44E375C71D77BC3777EEDCA49C1E7FFCF177A20173044CF1A27819527B6317142CE4C3D331A687BF6B4CFEE7E3773E912F34E412F9CB90BFE45839968169BC1617364ED137F4E4804DFC5C4343C3290DD890EB15A64C99F2B7993367267DE1BEFBEEDB986ED8B9C256F1A278A97A913857E60B836C0FEAE3E948F25F8777F3F70C2FF8B9C70A9EBFBFA677A7D8207FC95FC8B1722C3D90D6F24F64CD52344E2B56ACE8557FB07AF5EAE4073FF841E151B0A1D32BA44DD7BD13264C48BA7B638DB3D5DEDE9EFCF0873FDC9976B5D7085DC58BE2A5AA8B82D535A75EBC3D26BFB867A3B91B7B55CFCDBFAFF0E7C6742A0EDE4A873B25C95F86FC25C7CAB1F44FE375557D7DFDF1AC515AB26449597A8455AB56753E05B1FA7B85C58B177FFCE69B6F3E1EDD675F7AE38D370E8E1E3D7A5B1CB214C28A17C54BD5F95C91A220DBBBFA58A745FECD747CB1C4EFF9A7FCA25FF8FEC78AECCD8DE260ABE240FE32E42F39568EA56FD5D6D60E4B1BAFCD598354EE33E566CD9A55D8806DADFA5EE1B1C71E7BE181071E48FAC3A44993D6A7FF791384B1E245F152552E48C7A674DC5B53FA76C5BF48C7C982C5BE351D97747ACF25F9E7B3F79CCCFF5C2993F2C5C105FE0BE42F43FE9263E558FA46DA10FD246B8EAEBFFEFA8E3B19964B9C79F7E31FFFB8A301ABEA5E21FDF79EF3CB5FFEF25877EF50D25B9B376F3E3A7AF4E875C258F1A278A9AAA22016E7FFDB8DF75E9D8EF68285BF3DFFDC995EEBCA4FF24589BDB3F297217FC9B1722C7DD37CADCC1AA3B8957C5F885BD117DE7CA36A37E69A356BFECFEDB7DF5E96DBCA77D70D37DCF0AE4FB5AEA949BBFAA674FC9BE245F132D862B2C085E9D8978E3BCEE2678AED797DA9C81EDB8BCFE27736E68B930B2D9195152FF297FC851CCBE08EC9B419BA20BBD6ABB1B1B14FEF0F1147D5B206AC6A7B85A79E7A6AE9134F3C91F4A769D3A6BD1E9F886D2F42C7A1D5A6B4C3BF58F1A278192C31D9A928B8A1077F545C8BF066CDA9D71C74E75A85AE8CC9FF7D46584E2B275EE42FF90B3996C11D93E9F3E3B3F7DD77DF7D7DDA23CC9831A3F0DAAFEAEC15A64E9D7AE02F7FF94BBF365F6BD6ACD91A9F662DE04FFB84EF05C5F63E285E142F951693A96FE617E19FF4E28FFB423A3EE854147C907FBEC7FF84FCDFEB9B96D4CA8817F94BFE428E6570C764DCFEBDDC77382C256E5D5FF077A9CE5EE1E69B6F3EB67BF7EE7E6DBEF6ECD9D39A6ED01D02FEB480EFD8FB5018F88A17C54B85C5E4B9F9457C662FFEA86277DBEAED5ED9CCEFF2BFC787845640BCC85FF217722C833B26D3EF3765CF6FDFBEBD4F7B84969696C2BF4775F60A71EE669C63D99FE2CF4B3768BB802F1EF0857B1FE210B0E245F152693199DFEBD9968E2B7AF0C774F77A844B7AF0BBB3BFD7E596D4CA88973FFEF18F7287FC851CCB208EC9741CCEBE2FF75D0E8BDDF5B0E0CF6EAFDA8D3E10BAF19F6DE4477F375F6BD7AECD25E79800EFBFFF7EC778F3CD3793952B5776F9B35BB76E3DE5FBB6B6B664E3C68D25DF1F7FCEF4E9D3BBFC9DF19EDB6EBBADE371DC65277BFCDA6BAFF57BF12226FF31F28BEFD916077D7127AECE45C115FE7F2A6F0C44B3117174E38D3776FBFDCF3DF75CF2A52F7DE994E722EF5553FEEA66B165C8B172AC5174F4778F5095CDD775D75D77B2BF8F7C1D3E7C788F235F5D2E80ABEBEAEAAE880FB41B88D3762229FFE217BFC83D8E736FF7EDDB976BBEE2F9ABAFBEBAE37DBB76ED4AFEF0873F24975C7249F2F4D34F278F3EFA68EE3DF3E6CDCB7DBDE1861B92B973E7763472F1334B972E4D5E78E185E4DA6BAFCD7DFDEC673F9B7CED6B5FCB3D8E11C5CF17BFF8C5D3FE3EF1E17BD9E3679E79E6B4C7F61CF76F4C765A8C0F76B338B8B3E6CC77DB3ADBCFA0C9F4A448A11FE265208FDC470C7DF7BBDF2DF9FA45175D941B593EFACC673E931B593E7AF8E18773BF63E7CE9DF21772AC1C3B6463327D7CD091AF32BAE9A69B8EF6F7355F69D1FE37D77C150DF8A2C9B73F8B97ECA857E7BDBAE79F7F7E72E9A597962C70A2F0C81EBFFEFAEBB9AF4F3EF964B26DDBB6DCE368D48A151C1FFDE84793A953A7767C3F7CF8F08EC6EF9D77DEC9FDDEF899749B2473E6CCC93DCEF644C7E375EBD6C50D5C142FFD1C93A5F68696787D783A1EAFE9FE3507C5EED2F578FEF7141377DEDAA728A8CC7819E8E62B9AA9AEDE130DD557BEF295D39AAFDFFEF6B7C9C73EF6B1D37E9FFC851CCB508B49D77C95D9E4C99337AD5AB5AA5F9BAF975E7AE9FFB9DBE12901BFB2BEBE7E64A9E4DB5FC54B140B5971F1E52F7F39F9C637BE917B3E8E6AC5E3F81AC5C88E1D3B8A365F070F1ECC3D8EA361350547BE0A8B9F03070EE41ABC68C662647B85E3719C9E58AC50EABCE7F8539FFA546E0F733C5EB06041EE6B7CAF78E9BF983CCBBDA2633A2DF2CD3567BE50FBDCFCFB0A7FAEA14451127B85475A422B335E06AAF98A333A226E3EF9C94F76F9BEC8515FFDEA577339289AB018D951FDCF7FFEF3A7BC57FE428E6528C6A4BB1D96D9FDF7DF3F2B1686FE74D75D77BDE873BE72C1DC9D3D5EFD56BCC451AAD873BB69D3A65C228E662C0A97071F7CB0E33DB197365E8BBF53345BD9698571CA611C258BC7D9298AD1C465054A61C316DF472397356BF13BE2715C0BD1794F73F6FEB80E23FBB3B3EBCEE2F185175EE8B49D0188C92E8A838335C52FC4CEF6CA3ED6C5DED5627B731F2BF8B9527B831505151C2F03D57CC5F55435F9235FD188957ADF65975D96DC7AEBADB91C14F924463C8E26ABB9B9B9683E92BF9063194A31D99F9FF3356DDAB4EAFF9CAF499326FDAFF1E3C79F387EFC78BFDDEC70F4E8D1EFC4A7650BF9EEE9CFE265CF9E3DB9A220AEF38AC629CEBD8DC2221B2FBEF862AE49EBEAB4C3AC218BEB22E2F1E2C58B4F7B7F9CC2989D92139F669E9DF273E5955776BC6FF9F2E5491A2B1DCD5EE1EFCF1EC7A93C8A978A927D36CDE54516F9861EFECE31458A09D71FC85F673CE5F0DBDFFE762E8FC4E3520D58E4B462D77CC5F55CD134153BD22F7F21C732943434347C2EADDB8F4543943ECEED64EF0B7193B63163C69C2C68BEAAB757B8F5D65B37F7D7072DBFF4D24B7F4837E672A15C79C54B769A4E5CC710A7DCC469343FFFF9CF73D725D4E4AFE18A862C2647E762248E92455396153835F9235FD1C4156BD60A0B90AC718B53700A4F11CAEEB658D3E922F5C29F8DBF5B577BB5152F03225BB4FBEA56C46E752C7F752B97C511AA2C57C4DEDACE47FAE374EA68D08A355F93274F4E264C9890FBD9C2EBB2E42FE45886A2F8DCAFAC298A1AB12F3CFBECB38547BDAABB57F8D18F7E346AE2C489C7FAE1E857DBE8D1A3D7A6FF8163847165162FD12C658FE3C61985CD54B1BDB4710A4D4DFE8E627121799C7A93ED118E8226AE65883DC09D9BAF287A3AEF393EEFBCF372C5CE99AE9988D389E29CE0789CDDD063FDFAF58A97CA2B0EF6F5C1E2FD6F8A02F9AB3B47BDC68D1BD7F17DE487C266AC3B47BE221F7DEF7BDF2BFABBE52FE4588660F335326B8CE2E857B96FBC11BF2FED114E167CC873F5F70AE942B52E0AE7BE14D7974527DBC3739D152F7D3CE233BAA210888BCC63AF46612356D87CD5E46FBD1CA7E3C4E352D74514EEEDCD6ED5DCD59D128B35825971127B8BB3BDD935057763CCEECE987D8E8EE2A5A2947BEF691405BB6B9C06237F9DA1F18AD3FD8A7D8657BC1637D7E87CF43EDBC914392B3B321547F3E3FAD733FD59F217722C43455AC32FCE9AA3B856B65CB79D8F3305264E9C78BCF0A8D790E815E2BCCAEBAFBFFEF0DB6FBFDD278DD7BA75EB5E48FF8CDD6927FB2FC2B7728B97C20F498E2225FB0C9B285CB2CFB2890BD43B7FD8725C2B16178FC7293CF19E983C8D8D8DB9C7F13960714A4EA9E225FBD0D162235EAB29B848BDB0D089D7BEF5AD6FE5FECC52CD9DE2A522F6CE96A3385014C85F5D8EC80171C3A0B8757C57B7958F7C52ECC3E0E3E854BC76D75D779D55A3277F21C732849AAF0BD2B12F6B92225FF6B6018BC66BCA942985D7791D1C52BDC29831631AC68D1BF7616B6B6B591BAF7461F9F3E8D1A3B739DD7070EC39EEEF6B3306D3DF57F13220C5415F5FDF80FC257F21C7CAB174435D5DDD35D9CD37B223603D3D05317EAED311AF6448F60A0D0D0DD78F1D3BF660B98E80C511AF68BCD2FFAC3B84ACE265B00FC54B8FF5F4F41877DC92BF0CF90B39960A9236498D850D585C031697ABC45904DDBDAB61DC5CA3F01AAF1843BA5788AE76CC9831079E7FFEF943BDB80947DB6F7EF39B27E254C3F84F12AA8A17C58BBDB367591CD81B2B7F19F217722C15DA2BA4A3ADB0798A262CEE2C1B1FC41C47B5B25312E3D4C2969696DCCD8666CC98915C77DD75270A7F2E4E35D42BFCA3ABBD20ED489BC78D1BB767EDDAB587CFE673BC5E7EF9E567D3E66D755C30E71A2FC58BE2854E7B67BB7387AEDA9A7F7C98A8BDB1F297217F21C752A1BD42E12DE87B38F40A4536EC55D184353636B64E9D3A75C39FFFFCE76D69F7BA3BCE750F870F1FDEB36BD7AEBF2D5AB4E84F77DF7DF782B4EBDD121B323A58773554BC285E28B1B7B5AB453F8A82B8F0DB5E30F9CB90BF90631904BD42BE093B76364D975EE10CE2D3ADD30D3B21DD5073D3B1351DEDF98D175F77A4637E3A6EABEA4FA356BC285E142F7D5D1C7477AF2DF297217F21C752D9BDC209BD028A1743F15239BED9A938C88A02A7C1C85F86FC851CCB20565757777176242C6DC834FB285E0CC54B85C8F6CE4EABB13756FE32E42FE458AAA5F99A57708AE16A5B04C58BA178A91CB13736B6ABBDB1F297217F21C732C8A5CDD688CED77FA5CD98F843F162285E2AC8B93681FC65C85FC8B15445F335BFC80D3656BBB9068A1743F1523989DA7695BF0CF90B3996C11F6B234ADDF5B0BEBE7EA42D84E2C550BC280C90BFE42FE458284FAC2DE8E2F6F22B6D21142F86E2456180FC257F21C742EFE36CC4993EEBCBB55F285E0CC58BC200F94BFE428E85DEC7D9FC6E7CB8B23B1FA27831142F0A03E42FF90B3916C41E285E142F9233F297217F21C722F640F1A278417246FE92BF906341ECA17831142F9233F297217FC9B1722C620F142F8A172467F9CB90BF9063117BA07831142F9233F297FC851C0B620FC58BA178919C91BF0CF90B3916B1078A17C50B9233F297FC851C8BD8137B285E0CC58BE48CFC257F21C782D803C58BE2457246FE32E42FE458C41E285E0CC58BE48CFC257F21C782D843F162285E2467E42F43FE428E45EC416F3437372B1C2A63B4A7C5CB31112939237FC95FC8B120F6A852CB962DDBDDDADAAA7818E0D1D2D2323B2D5EDE12919233F297FC851C0B628F2AF5CA2BAF5CB964C992FD7BF7EE3DAC8818983DC651B82C5AB4685B3AAE12919233F297FC851C0B628F2A962E9A57343535AD8ED346E2BC7DA35F476CF3B7142E9233F297FC851C0B620F06C3E41B6102223903C8B1883DA0EF27DFFC9880B5B5B5C36C0D2467003916B107F481BABABA8BD3C9772C26607D7DFDE5B6089233801C8BD803FAA6F99A17932F3F56DB2248CE00722C620F28FFA41B911DF5CA46DA8C5D61CB203903C8B1883DA0BC936E7E61E3951DFD72ED179233801C8BD803CA37E14E3BEA958DFAFAFA91B6109233801C8BD803CA33E116146BBCF263A52D84E40C20C722F680DE4FB69247BD5CFB85E40C20C722F680F24DB6F95D355EEE7C88E40C20C722F6001310B10120C782D8031310B101801C8BD8034C40C406801C0B620F4C40C406801C0B620F4C40C40600722C620F3001111B00722C883D3001111B00C8B1883DC004446C00C8B1883DC004446C00C8B120F6C004446C0020C722F6001310B10120C782D8031310B101801C8BD8031310C406801C8BD8034C40C406801C0B620F4C40C40600722C620F3001111B00722C883D3001111B00722C883D3001111B00C8B1883DC004446C00C8B120F6C004446C0020C722F6001310B10120C722F6001310B10120C782D8031310B101801C8BD8034C40C406801C0B620F4C40C406801C2BC722F6C00404B10120C722F6001310B10120C782D8031310B101801C8BD8034C40C406801C8BD8137B6002223600E458107B60022236009063117B800988D800906341EC810988D800408E45EC0126206203408E45EC0126206203408E05B10726206203003916B1079880880D003916C41E9880880D003916C41E9880203600E458C41E6002223600E458107B60022236009063117B800988D8009063117B800988D800906341EC810988D800408E45EC0126206203408E05B10726206203003916B10726A00988D8009063117B800988D800906341EC810988D800408E45EC0126206203408E05B10726206203408E05B1072620880D003916B1079880880D003916C41E9880880D00E458C41E6002223600E458C41E6002223600E458107B60022236009063117B800988D800906341EC810988D800408E45EC8109086203408E45EC0126206203408E05B10726206203003916B1079880880D003916C41E9880880D003916C41E9880880DB10120C722F600139032C7C1FC8885338CD5B61480F517B1079880F42E0E46A4E35857CD575D5DDD15B61480F517B1079880F43E161674D17CADACADAD1D662B01587F117B800948EF636144A9E6ABBEBE7EA42D0460FD45EC012620E58B8762D77EAD76D40BC0FA8BD8034C40CA1B0FA75DFBE55A2F00EB2F620F3001E90369B335CF512F00EB2F620F3001E9FBE6EBE2826BBD2EB74500ACBF883DC004A4EFE22277ED97A35E00D65FC41E6002D2B77131426C00587F117B800958D1922419B665CB96B9AB56AD3AD1DCDC9C34353519FD3C162D5A942C5BB6ECBD748C119180F517C41E9880552A1AAFE5CB9727ADADADC9D1A3478D011AFBF6ED4B962E5D7A206DC4AE129580F517C41E988055288E7869BC2AA6013BDAD4D4F496A804ACBF20F6C004AC4271AAA1C6A77246DA7C1D139580F517C41E98805528AE39D2F45454F325C601EB2F883D30018772F37568FFEE64CBEA27920D8BEEC98D781CCF6998345F80F517C41E988094A9F93AD8D692AC7F6972F2D7176F3F65C473F19AA649F305587F41EC810948199AAF1D1BFEF3B4C62B1B3B37CCD73469BE00EB2F883D30012947F3F5D6E27F2FD97CC56B9A26CD1760FD05B10726206568BED637DD5DB2F98AD7344D9A2FC0FA0B620F4C40345F9A2F00EB2F620F30010747F31577372CD57CC56B9A26CD1760FD05B10726206568BE36ADF88F92CD57BCA669D27C01D65F107B60025286E6EBFD9675C9FA97EF3AFD94C3F4B9784DD3A4F902ACBF20F6C004A40CCD578CAD6B9E3EADF98AE7344C9A2FC0FA0B620F4C40CAD57C1D39926C7A75E6E9A71CA6CFC56B9A26CD1760FD05B1072620BD6CBE0EB6B5246FAF78A8E4355FF15ABC47E3A4F902ACBF20F6C004A427CDD79123C9EE4DAF246F2CBCB364E3958D784FBCD75130CD1760FD05B107262067D17C9DE96897A3609A2FC0FA0B620F4C40CAD07C75E768575747C134519A2FC0FA0B620F4C40BAD17CF5B4F1CA86264AF305587F41EC810948379A2F43F30560FD45EC810968026ABE345F00D65FC41E60026ABE0CCD1760FD05B10726209A2FCD1780F517B10798809A2F43F305587F41EC8109A8F932345F80F517C41E988068BE345F00D65FC41E60026ABE0CCD1760FD05B10726A0E64BF3A5F902B0FE22F6001350F3A5F902B0FE22F6001350F36568BE00EB2F883D3001D17C69BE00ACBF883DC004D47C199A2FC0FA0B620F4CC02A525B5B3B4CF3A5F902B0FE22F60013B08F2449F2E99D3B77AE5CB162453269D2A489A59A30CDD7E06ABED23930A2AEAE6E9E0807ACBF883DC004AC00DBB76F9FDCDEDE7E2CC93B72E4C8FFCC9E3D7BD34F7FFAD3FFADF91A9CCD57345DE9989F8E63E60160FD45EC0126E0003B74E8D0BFEEDDBBF7DDA484AD5BB7B64F9D3AF5E1C6C6C673345F83A3F9EADC746543B403D65FC41E60020E80B4AF3A67C78E1DBF3F71E2C4C9E40C4E9E3C7962E1C285EFDD72CB2DDFD57C556EF355575777719C5ED8B9E9D27C01D65FC41E60020E90BD7BF77E7FFFFEFD0792B3D4D6D67664E6CC99CDF3E7CFD7F45458F355EC4897E60BB0FE22F6807E9F80C6A963C68C19D148253D68BE723F1BBFA3A5A5A5629B91F7DF7F3F926EEEEFDBDEDE9EAC5DBB36F75CE158BC78F1693F173F73DF7DF7257BF6ECE9F87ECA942983A5F9320CC3A8B8A10A41F3050C790D0D0D9F1B3B76EC9F5E7DF5D5DD274F9E3CDE9DC66BFFFEFDCF8C1B376E719CD696AAF886E4231FF94872D96597E59AAF68A2A2018BAF0F3CF040477396BDF7139FF844F2E69B6FE69E5BBA74691247F6D6AF5F9FFBFEB5D75E4B162C58907BBC6FDFBE8A3EEDF0EAABAFFE66BAE0AC540401A0F902A830F5F5F5237FFDEB5FEF686B6B6BEDE27AAFF58F3CF2C8EFD244B629DE1F3F3758AEF93A70E040C711ACA79F7E3AF7F5D24B2FCD9A958EF745B3357DFAF4DC734F3EF964EEEBE8D1A393679E79A6E3E7E7CC9933686EB891FE3F5D9EFE7F2DD77C01A0F902A820A3468DFA784343C3F4E79E7BAEF5C48913870BFAAEF6CD9B373F9CBEB6BEAEAE6E5A6363E3B9D9CF5472F31547A7E273CAA2614AFF4D1DCD5376642B8E686DDCB8F194E6EB85175E48264F9E7C4A931647BC962F5FDEF1FDC1830707DDADE6F347C2966BBE00D07C015456A21A71CB2DB7ACDBB2654BCBE1C38797DE79E79D73F2A7B08DE8FCDEC170E42B1AA6ECF4C878FCD0430F25DFFFFEF7936BAFBD3679F9E5974F69BEB66DDB96CC9A352BF7DC45175DD4F1739B366DCA3DF79DEF7C67507FC872FE48D84A510E80E60BA042D4D6D60E4B0BF50991B4E26B7C5FEC7D83B1F98A1147B8E26BE7235FE79D775EEE5AAF786EE7CE9DB9EBC5621BC4B55EF1FA8D37DE987BADB9B97950365F00A0F902A8E026ACABD7074BF315A7186EDDBAB5E37AAEEC461BD9CD34E27DBB76EDCA7D8DC62A8E74C588D315BFFEF5AFE71EAF59B326D78C7DF8E18783F6C8170068BE0006A9C1D27C0D1F3E3C77038DECA856DC3423BEC66986350547BE0A7F26AE0DCB8E90655F1F7CF0C1417DDA210068BE00345F7DDA7CC56779D5E46F11FFFAEBAFE79ECF6E9C51AAF95AB76E5DAEE9FAC217BE70CA6BD91132CD170068BE00345F9D465CDB15A718163E17A711D6E46FAC5178ABF968B8CE3FFFFCDCD7B8F9467C46D8F8F1E373DF3FFAE8A3B99FC96E5DAFF90200CD1780E66B080ECD170068BE00CD97A1F90200CD1780E64BF305009A2F00CD97A1F90200CD17A0F9D2F468BE0040F305A0F9D27C0180E60B40F36568BE0040F305A0F9D27C0180E60B40F36568BE0040F30568BE0CCD170068BE00345F9A2F00D07C0168BE0CCD170068BE00345F9A2F00D07C0168BE345F161900D07C019A2F43F305009A2F00CD97E60B00345F009A2F43F305009A2F40F36568BE0040F305A0F9D27C0180E60B40F36568BE0040F305A0F9D27C0180E60B40F36568BE0040F30568BE0CCD170068BE00345F9A2F00D07C0168BE0CCD170068BE00345F9A2F00D07C01F4AFE6E6664D4FE58CF6B4F93A262A0140F30554A165CB96ED6E6D6DD5F854C0686969999D365F6F894A00D07C0155E895575EB972C99225FBF7EEDD7B5803347047BCA2F15AB468D1B6745C252A0140F30554A9B4E0BFA2A9A969759CF216D71C0DC6316FDEBC64B0FEDDF3DBFD2D8D170068BE002ADADEBD7BBF3F63C68C244DD017D81A00A0F902A00F244972CE071F7CD0964AC68E1DFB275B0400345F00F4811D3B76FC3EC97BF5D5575BEAEBEB47DA2A00A0F902A08C0E1D3AF4AF274E9C389914983265CA8EC6C6C6736D1D00D07C0150267BF6ECD99274B27FFFFE3D0D0D0DD36D1D00D07C015006DBB76F9F9C94306FDEBC3D69B21E612B0180E60B805E48FBAB4F1F3972E47F4A355F274F9E3C7ACB2DB7ACABADAD1D666B0180E60B801EDAB973E7CAE40CB66CD9B2A3BEBE7E82AD05009A2F007A68C58A1567EABD92F6F6F62591B01B1B1BCFB1C50040F305400FFCEA57BFFA6957A71D46EF75E79D77CE71E40B00345F00F4D2ECD9B3FF56AAF3DABC79F3C369B25EE99A2F00D07C01D04BA3468DFAE7B4C96A2F72B38DF50D0D0DEBDDED1000345F0094C9FDF7DFFF50DA6C9D286CBE66CD9AF5585D5DDD345B0700345F0094499C56B870E1C2D6820F587E264DD29B1A1B1BCFB5750040F30540198D1F3FFE1B6D6D6D47D2918C1D3B76517D7DFD485B0500345F00F481471E7964C18C193392BABABA79B6060068BE00E823719A6124E7B80987AD01009A2F00246700C0FA0E20390300D67700246700B0BE0320390300D67700C91900B0BE0320390300D67700C91900B0BE0320390380F51D00C91900B0BE0348CE0080F51D00C91900B0BE0348CE0080F51D40720600ACEF0048CE0080F51D40720600ACEF0048CE00607D0740720600ACEF00923300607D0740720600ACEF00923300607D0740720600EB3B00923300607D07909C0100EB3B0092330058DFADEF00923300607D07909C0100EB3B00923300607D07909C0100EB3B0092330058DF0118E8E46C1886611846F50D550E00000000000000000000000000000000000000000000000000000000005075FE3F9FEF977BF087DB470000000049454E44AE426082',1);\n\n#\n# Structure for table \"act_re_model\"\n#\n\nDROP TABLE IF EXISTS `act_re_model`;\nCREATE TABLE `act_re_model` (\n  `ID_` varchar(64) COLLATE utf8_bin NOT NULL,\n  `REV_` int(11) DEFAULT NULL,\n  `NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `KEY_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `CATEGORY_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `CREATE_TIME_` timestamp(3) NULL DEFAULT NULL,\n  `LAST_UPDATE_TIME_` timestamp(3) NULL DEFAULT NULL,\n  `VERSION_` int(11) DEFAULT NULL,\n  `META_INFO_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,\n  `DEPLOYMENT_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `EDITOR_SOURCE_VALUE_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `EDITOR_SOURCE_EXTRA_VALUE_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `TENANT_ID_` varchar(255) COLLATE utf8_bin DEFAULT '',\n  PRIMARY KEY (`ID_`),\n  KEY `ACT_FK_MODEL_SOURCE` (`EDITOR_SOURCE_VALUE_ID_`),\n  KEY `ACT_FK_MODEL_SOURCE_EXTRA` (`EDITOR_SOURCE_EXTRA_VALUE_ID_`),\n  KEY `ACT_FK_MODEL_DEPLOYMENT` (`DEPLOYMENT_ID_`),\n  CONSTRAINT `ACT_FK_MODEL_DEPLOYMENT` FOREIGN KEY (`DEPLOYMENT_ID_`) REFERENCES `act_re_deployment` (`ID_`),\n  CONSTRAINT `ACT_FK_MODEL_SOURCE` FOREIGN KEY (`EDITOR_SOURCE_VALUE_ID_`) REFERENCES `act_ge_bytearray` (`ID_`),\n  CONSTRAINT `ACT_FK_MODEL_SOURCE_EXTRA` FOREIGN KEY (`EDITOR_SOURCE_EXTRA_VALUE_ID_`) REFERENCES `act_ge_bytearray` (`ID_`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;\n\n#\n# Data for table \"act_re_model\"\n#\n\nINSERT INTO `act_re_model` VALUES ('142517',53,'请假流程','processKey',NULL,'2018-01-25 17:21:39.000','2018-05-17 21:11:56.681',1,'{\\\"name\\\":\\\"请假流程\\\",\\\"description\\\":\\\"\\\"}','212503','142518','142519','');\n\n#\n# Structure for table \"act_re_procdef\"\n#\n\nDROP TABLE IF EXISTS `act_re_procdef`;\nCREATE TABLE `act_re_procdef` (\n  `ID_` varchar(64) COLLATE utf8_bin NOT NULL,\n  `REV_` int(11) DEFAULT NULL,\n  `CATEGORY_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `KEY_` varchar(255) COLLATE utf8_bin NOT NULL,\n  `VERSION_` int(11) NOT NULL,\n  `DEPLOYMENT_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `RESOURCE_NAME_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,\n  `DGRM_RESOURCE_NAME_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,\n  `DESCRIPTION_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,\n  `HAS_START_FORM_KEY_` tinyint(4) DEFAULT NULL,\n  `HAS_GRAPHICAL_NOTATION_` tinyint(4) DEFAULT NULL,\n  `SUSPENSION_STATE_` int(11) DEFAULT NULL,\n  `TENANT_ID_` varchar(255) COLLATE utf8_bin DEFAULT '',\n  PRIMARY KEY (`ID_`),\n  UNIQUE KEY `ACT_UNIQ_PROCDEF` (`KEY_`,`VERSION_`,`TENANT_ID_`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;\n\n#\n# Data for table \"act_re_procdef\"\n#\n\nINSERT INTO `act_re_procdef` VALUES ('process_leave:1:212506',1,'http://www.activiti.org/processdef','请假流程','process_leave',1,'212503','请假流程.bpmn20.xml','请假流程.process_leave.png',NULL,0,1,1,'');\n\n#\n# Structure for table \"act_procdef_info\"\n#\n\nDROP TABLE IF EXISTS `act_procdef_info`;\nCREATE TABLE `act_procdef_info` (\n  `ID_` varchar(64) COLLATE utf8_bin NOT NULL,\n  `PROC_DEF_ID_` varchar(64) COLLATE utf8_bin NOT NULL,\n  `REV_` int(11) DEFAULT NULL,\n  `INFO_JSON_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  PRIMARY KEY (`ID_`),\n  UNIQUE KEY `ACT_UNIQ_INFO_PROCDEF` (`PROC_DEF_ID_`),\n  KEY `ACT_IDX_INFO_PROCDEF` (`PROC_DEF_ID_`),\n  KEY `ACT_FK_INFO_JSON_BA` (`INFO_JSON_ID_`),\n  CONSTRAINT `ACT_FK_INFO_JSON_BA` FOREIGN KEY (`INFO_JSON_ID_`) REFERENCES `act_ge_bytearray` (`ID_`),\n  CONSTRAINT `ACT_FK_INFO_PROCDEF` FOREIGN KEY (`PROC_DEF_ID_`) REFERENCES `act_re_procdef` (`ID_`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;\n\n#\n# Data for table \"act_procdef_info\"\n#\n\n\n#\n# Structure for table \"act_ru_execution\"\n#\n\nDROP TABLE IF EXISTS `act_ru_execution`;\nCREATE TABLE `act_ru_execution` (\n  `ID_` varchar(64) COLLATE utf8_bin NOT NULL,\n  `REV_` int(11) DEFAULT NULL,\n  `PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `BUSINESS_KEY_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `PARENT_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `PROC_DEF_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `SUPER_EXEC_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `ACT_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `IS_ACTIVE_` tinyint(4) DEFAULT NULL,\n  `IS_CONCURRENT_` tinyint(4) DEFAULT NULL,\n  `IS_SCOPE_` tinyint(4) DEFAULT NULL,\n  `IS_EVENT_SCOPE_` tinyint(4) DEFAULT NULL,\n  `SUSPENSION_STATE_` int(11) DEFAULT NULL,\n  `CACHED_ENT_STATE_` int(11) DEFAULT NULL,\n  `TENANT_ID_` varchar(255) COLLATE utf8_bin DEFAULT '',\n  `NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `LOCK_TIME_` timestamp(3) NULL DEFAULT NULL,\n  PRIMARY KEY (`ID_`),\n  KEY `ACT_IDX_EXEC_BUSKEY` (`BUSINESS_KEY_`),\n  KEY `ACT_FK_EXE_PROCINST` (`PROC_INST_ID_`),\n  KEY `ACT_FK_EXE_PARENT` (`PARENT_ID_`),\n  KEY `ACT_FK_EXE_SUPER` (`SUPER_EXEC_`),\n  KEY `ACT_FK_EXE_PROCDEF` (`PROC_DEF_ID_`),\n  CONSTRAINT `ACT_FK_EXE_PARENT` FOREIGN KEY (`PARENT_ID_`) REFERENCES `act_ru_execution` (`ID_`),\n  CONSTRAINT `ACT_FK_EXE_PROCDEF` FOREIGN KEY (`PROC_DEF_ID_`) REFERENCES `act_re_procdef` (`ID_`),\n  CONSTRAINT `ACT_FK_EXE_PROCINST` FOREIGN KEY (`PROC_INST_ID_`) REFERENCES `act_ru_execution` (`ID_`) ON DELETE CASCADE ON UPDATE CASCADE,\n  CONSTRAINT `ACT_FK_EXE_SUPER` FOREIGN KEY (`SUPER_EXEC_`) REFERENCES `act_ru_execution` (`ID_`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;\n\n#\n# Data for table \"act_ru_execution\"\n#\n\n\n#\n# Structure for table \"act_ru_event_subscr\"\n#\n\nDROP TABLE IF EXISTS `act_ru_event_subscr`;\nCREATE TABLE `act_ru_event_subscr` (\n  `ID_` varchar(64) COLLATE utf8_bin NOT NULL,\n  `REV_` int(11) DEFAULT NULL,\n  `EVENT_TYPE_` varchar(255) COLLATE utf8_bin NOT NULL,\n  `EVENT_NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `EXECUTION_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `ACTIVITY_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `CONFIGURATION_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `CREATED_` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),\n  `PROC_DEF_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `TENANT_ID_` varchar(255) COLLATE utf8_bin DEFAULT '',\n  PRIMARY KEY (`ID_`),\n  KEY `ACT_IDX_EVENT_SUBSCR_CONFIG_` (`CONFIGURATION_`),\n  KEY `ACT_FK_EVENT_EXEC` (`EXECUTION_ID_`),\n  CONSTRAINT `ACT_FK_EVENT_EXEC` FOREIGN KEY (`EXECUTION_ID_`) REFERENCES `act_ru_execution` (`ID_`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;\n\n#\n# Data for table \"act_ru_event_subscr\"\n#\n\n\n#\n# Structure for table \"act_ru_job\"\n#\n\nDROP TABLE IF EXISTS `act_ru_job`;\nCREATE TABLE `act_ru_job` (\n  `ID_` varchar(64) COLLATE utf8_bin NOT NULL,\n  `REV_` int(11) DEFAULT NULL,\n  `TYPE_` varchar(255) COLLATE utf8_bin NOT NULL,\n  `LOCK_EXP_TIME_` timestamp(3) NULL DEFAULT NULL,\n  `LOCK_OWNER_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `EXCLUSIVE_` tinyint(1) DEFAULT NULL,\n  `EXECUTION_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `PROCESS_INSTANCE_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `PROC_DEF_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `RETRIES_` int(11) DEFAULT NULL,\n  `EXCEPTION_STACK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `EXCEPTION_MSG_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,\n  `DUEDATE_` timestamp(3) NULL DEFAULT NULL,\n  `REPEAT_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `HANDLER_TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `HANDLER_CFG_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,\n  `TENANT_ID_` varchar(255) COLLATE utf8_bin DEFAULT '',\n  PRIMARY KEY (`ID_`),\n  KEY `ACT_FK_JOB_EXCEPTION` (`EXCEPTION_STACK_ID_`),\n  CONSTRAINT `ACT_FK_JOB_EXCEPTION` FOREIGN KEY (`EXCEPTION_STACK_ID_`) REFERENCES `act_ge_bytearray` (`ID_`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;\n\n#\n# Data for table \"act_ru_job\"\n#\n\n\n#\n# Structure for table \"act_ru_task\"\n#\n\nDROP TABLE IF EXISTS `act_ru_task`;\nCREATE TABLE `act_ru_task` (\n  `ID_` varchar(64) COLLATE utf8_bin NOT NULL,\n  `REV_` int(11) DEFAULT NULL,\n  `EXECUTION_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `PROC_DEF_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `PARENT_TASK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `DESCRIPTION_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,\n  `TASK_DEF_KEY_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `OWNER_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `ASSIGNEE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `DELEGATION_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `PRIORITY_` int(11) DEFAULT NULL,\n  `CREATE_TIME_` timestamp(3) NULL DEFAULT NULL,\n  `DUE_DATE_` datetime(3) DEFAULT NULL,\n  `CATEGORY_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `SUSPENSION_STATE_` int(11) DEFAULT NULL,\n  `TENANT_ID_` varchar(255) COLLATE utf8_bin DEFAULT '',\n  `FORM_KEY_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  PRIMARY KEY (`ID_`),\n  KEY `ACT_IDX_TASK_CREATE` (`CREATE_TIME_`),\n  KEY `ACT_FK_TASK_EXE` (`EXECUTION_ID_`),\n  KEY `ACT_FK_TASK_PROCINST` (`PROC_INST_ID_`),\n  KEY `ACT_FK_TASK_PROCDEF` (`PROC_DEF_ID_`),\n  CONSTRAINT `ACT_FK_TASK_EXE` FOREIGN KEY (`EXECUTION_ID_`) REFERENCES `act_ru_execution` (`ID_`),\n  CONSTRAINT `ACT_FK_TASK_PROCDEF` FOREIGN KEY (`PROC_DEF_ID_`) REFERENCES `act_re_procdef` (`ID_`),\n  CONSTRAINT `ACT_FK_TASK_PROCINST` FOREIGN KEY (`PROC_INST_ID_`) REFERENCES `act_ru_execution` (`ID_`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;\n\n#\n# Data for table \"act_ru_task\"\n#\n\n\n#\n# Structure for table \"act_ru_identitylink\"\n#\n\nDROP TABLE IF EXISTS `act_ru_identitylink`;\nCREATE TABLE `act_ru_identitylink` (\n  `ID_` varchar(64) COLLATE utf8_bin NOT NULL,\n  `REV_` int(11) DEFAULT NULL,\n  `GROUP_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `USER_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n  `TASK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `PROC_DEF_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  PRIMARY KEY (`ID_`),\n  KEY `ACT_IDX_IDENT_LNK_USER` (`USER_ID_`),\n  KEY `ACT_IDX_IDENT_LNK_GROUP` (`GROUP_ID_`),\n  KEY `ACT_IDX_ATHRZ_PROCEDEF` (`PROC_DEF_ID_`),\n  KEY `ACT_FK_TSKASS_TASK` (`TASK_ID_`),\n  KEY `ACT_FK_IDL_PROCINST` (`PROC_INST_ID_`),\n  CONSTRAINT `ACT_FK_ATHRZ_PROCEDEF` FOREIGN KEY (`PROC_DEF_ID_`) REFERENCES `act_re_procdef` (`ID_`),\n  CONSTRAINT `ACT_FK_IDL_PROCINST` FOREIGN KEY (`PROC_INST_ID_`) REFERENCES `act_ru_execution` (`ID_`),\n  CONSTRAINT `ACT_FK_TSKASS_TASK` FOREIGN KEY (`TASK_ID_`) REFERENCES `act_ru_task` (`ID_`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;\n\n#\n# Data for table \"act_ru_identitylink\"\n#\n\n\n#\n# Structure for table \"act_ru_variable\"\n#\n\nDROP TABLE IF EXISTS `act_ru_variable`;\nCREATE TABLE `act_ru_variable` (\n  `ID_` varchar(64) COLLATE utf8_bin NOT NULL,\n  `REV_` int(11) DEFAULT NULL,\n  `TYPE_` varchar(255) COLLATE utf8_bin NOT NULL,\n  `NAME_` varchar(255) COLLATE utf8_bin NOT NULL,\n  `EXECUTION_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `TASK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `BYTEARRAY_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,\n  `DOUBLE_` double DEFAULT NULL,\n  `LONG_` bigint(20) DEFAULT NULL,\n  `TEXT_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,\n  `TEXT2_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,\n  PRIMARY KEY (`ID_`),\n  KEY `ACT_IDX_VARIABLE_TASK_ID` (`TASK_ID_`),\n  KEY `ACT_FK_VAR_EXE` (`EXECUTION_ID_`),\n  KEY `ACT_FK_VAR_PROCINST` (`PROC_INST_ID_`),\n  KEY `ACT_FK_VAR_BYTEARRAY` (`BYTEARRAY_ID_`),\n  CONSTRAINT `ACT_FK_VAR_BYTEARRAY` FOREIGN KEY (`BYTEARRAY_ID_`) REFERENCES `act_ge_bytearray` (`ID_`),\n  CONSTRAINT `ACT_FK_VAR_EXE` FOREIGN KEY (`EXECUTION_ID_`) REFERENCES `act_ru_execution` (`ID_`),\n  CONSTRAINT `ACT_FK_VAR_PROCINST` FOREIGN KEY (`PROC_INST_ID_`) REFERENCES `act_ru_execution` (`ID_`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;\n\n#\n# Data for table \"act_ru_variable\"\n#\n\n\n#\n# Structure for table \"file_info\"\n#\n\nDROP TABLE IF EXISTS `file_info`;\nCREATE TABLE `file_info` (\n  `id` varchar(32) NOT NULL COMMENT '文件md5',\n  `contentType` varchar(128) NOT NULL,\n  `size` int(11) NOT NULL,\n  `path` varchar(255) NOT NULL COMMENT '物理路径',\n  `url` varchar(1024) NOT NULL,\n  `type` int(1) NOT NULL,\n  `createTime` datetime NOT NULL,\n  `updateTime` datetime NOT NULL,\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;\n\n#\n# Data for table \"file_info\"\n#\n\nINSERT INTO `file_info` VALUES ('c5ca69c2971ac9add9efe91115bf500c','image/png',12105,'d:/files/2018/05/28/c5ca69c2971ac9add9efe91115bf500c.png','/2018/05/28/c5ca69c2971ac9add9efe91115bf500c.png',1,'2018-05-28 02:54:47','2018-05-28 02:54:47');\n\n#\n# Structure for table \"oauth_access_token\"\n#\n\nDROP TABLE IF EXISTS `oauth_access_token`;\nCREATE TABLE `oauth_access_token` (\n  `token_id` varchar(256) DEFAULT NULL,\n  `token` blob,\n  `authentication_id` varchar(48) NOT NULL,\n  `user_name` varchar(256) DEFAULT NULL,\n  `client_id` varchar(256) DEFAULT NULL,\n  `authentication` blob,\n  `refresh_token` varchar(256) DEFAULT NULL,\n  PRIMARY KEY (`authentication_id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\n#\n# Data for table \"oauth_access_token\"\n#\n\n\n#\n# Structure for table \"oauth_approvals\"\n#\n\nDROP TABLE IF EXISTS `oauth_approvals`;\nCREATE TABLE `oauth_approvals` (\n  `userId` varchar(256) DEFAULT NULL,\n  `clientId` varchar(256) DEFAULT NULL,\n  `scope` varchar(256) DEFAULT NULL,\n  `status` varchar(10) DEFAULT NULL,\n  `expiresAt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n  `lastModifiedAt` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\n#\n# Data for table \"oauth_approvals\"\n#\n\n\n#\n# Structure for table \"oauth_client_details\"\n#\n\nDROP TABLE IF EXISTS `oauth_client_details`;\nCREATE TABLE `oauth_client_details` (\n  `id` int(11) NOT NULL AUTO_INCREMENT,\n  `client_id` varchar(48) NOT NULL,\n  `resource_ids` varchar(256) DEFAULT NULL,\n  `client_secret` varchar(256) DEFAULT NULL,\n  `scope` varchar(256) DEFAULT NULL,\n  `authorized_grant_types` varchar(256) DEFAULT NULL,\n  `web_server_redirect_uri` varchar(256) DEFAULT NULL,\n  `authorities` varchar(256) DEFAULT NULL,\n  `access_token_validity` int(11) DEFAULT NULL,\n  `refresh_token_validity` int(11) DEFAULT NULL,\n  `additional_information` varchar(4096) DEFAULT NULL,\n  `autoapprove` varchar(256) DEFAULT NULL,\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;\n\n#\n# Data for table \"oauth_client_details\"\n#\n\nINSERT INTO `oauth_client_details` VALUES (1,'app',NULL,'app','app','password,refresh_token',NULL,NULL,180000,NULL,'{}','true'),(2,'mobile','mobile,test','mobile','all','password,refresh_token',NULL,NULL,180000,NULL,'{}','true'),(3,'test','test','test','test','password,refresh_token',NULL,NULL,180000,NULL,'{}','true'),(4,'webApp',NULL,'webApp','app','authorization_code,password,refresh_token,client_credentials',NULL,NULL,180000,NULL,'{}','true'),(5,'clientId','','clientSecret','all','authorization_code,password,refresh_token,client_credentials','http://www.baidu.com','',180000,NULL,'{}','true'),(6,'owen',NULL,'owen','app','authorization_code,password,refresh_token,client_credentials','http://127.0.0.1:9997/clientOne/login',NULL,180000,NULL,'{}','true');\n\n#\n# Structure for table \"oauth_client_token\"\n#\n\nDROP TABLE IF EXISTS `oauth_client_token`;\nCREATE TABLE `oauth_client_token` (\n  `token_id` varchar(256) DEFAULT NULL,\n  `token` blob,\n  `authentication_id` varchar(48) NOT NULL,\n  `user_name` varchar(256) DEFAULT NULL,\n  `client_id` varchar(256) DEFAULT NULL,\n  PRIMARY KEY (`authentication_id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\n#\n# Data for table \"oauth_client_token\"\n#\n\n\n#\n# Structure for table \"oauth_code\"\n#\n\nDROP TABLE IF EXISTS `oauth_code`;\nCREATE TABLE `oauth_code` (\n  `code` varchar(256) DEFAULT NULL,\n  `authentication` blob\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\n#\n# Data for table \"oauth_code\"\n#\n\n\n#\n# Structure for table \"oauth_refresh_token\"\n#\n\nDROP TABLE IF EXISTS `oauth_refresh_token`;\nCREATE TABLE `oauth_refresh_token` (\n  `token_id` varchar(256) DEFAULT NULL,\n  `token` blob,\n  `authentication` blob\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\n#\n# Data for table \"oauth_refresh_token\"\n#\n\nINSERT INTO `oauth_refresh_token` VALUES ('b96e057b4e1c4920428e833db48d4c15',X'ACED00057372004C6F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E636F6D6D6F6E2E44656661756C744578706972696E674F417574683252656672657368546F6B656E2FDF47639DD0C9B70200014C000A65787069726174696F6E7400104C6A6176612F7574696C2F446174653B787200446F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E636F6D6D6F6E2E44656661756C744F417574683252656672657368546F6B656E73E10E0A6354D45E0200014C000576616C75657400124C6A6176612F6C616E672F537472696E673B787074002462303132643438372D613930382D343361662D613865662D3533633533393963386264367372000E6A6176612E7574696C2E44617465686A81014B59741903000078707708000001613B74C98E78',X'ACED0005737200416F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E4F417574683241757468656E7469636174696F6EBD400B02166252130200024C000D73746F7265645265717565737474003C4C6F72672F737072696E676672616D65776F726B2F73656375726974792F6F61757468322F70726F76696465722F4F4175746832526571756573743B4C00127573657241757468656E7469636174696F6E7400324C6F72672F737072696E676672616D65776F726B2F73656375726974792F636F72652F41757468656E7469636174696F6E3B787200476F72672E737072696E676672616D65776F726B2E73656375726974792E61757468656E7469636174696F6E2E416273747261637441757468656E7469636174696F6E546F6B656ED3AA287E6E47640E0200035A000D61757468656E746963617465644C000B617574686F7269746965737400164C6A6176612F7574696C2F436F6C6C656374696F6E3B4C000764657461696C737400124C6A6176612F6C616E672F4F626A6563743B787000737200266A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C654C697374FC0F2531B5EC8E100200014C00046C6973747400104C6A6176612F7574696C2F4C6973743B7872002C6A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65436F6C6C656374696F6E19420080CB5EF71E0200014C00016371007E00047870737200136A6176612E7574696C2E41727261794C6973747881D21D99C7619D03000149000473697A65787000000009770400000009737200426F72672E737072696E676672616D65776F726B2E73656375726974792E636F72652E617574686F726974792E53696D706C654772616E746564417574686F7269747900000000000001A40200014C0004726F6C657400124C6A6176612F6C616E672F537472696E673B787074000A524F4C455F61646D696E7371007E000D740006617069646F637371007E000D74000C64617461626173652F6C6F677371007E000D74000673797374656D7371007E000D740008757365722F6164647371007E000D74000B757365722F64656C6574657371007E000D740009757365722F656469747371007E000D740009757365722F766965777371007E000D740008757365724C6973747871007E000C707372003A6F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E4F41757468325265717565737400000000000000010200075A0008617070726F7665644C000B617574686F72697469657371007E00044C000A657874656E73696F6E7374000F4C6A6176612F7574696C2F4D61703B4C000B726564697265637455726971007E000E4C00077265667265736874003B4C6F72672F737072696E676672616D65776F726B2F73656375726974792F6F61757468322F70726F76696465722F546F6B656E526571756573743B4C000B7265736F7572636549647374000F4C6A6176612F7574696C2F5365743B4C000D726573706F6E7365547970657371007E0024787200386F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E426173655265717565737436287A3EA37169BD0200034C0008636C69656E74496471007E000E4C001172657175657374506172616D657465727371007E00224C000573636F706571007E00247870740006776562417070737200256A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C654D6170F1A5A8FE74F507420200014C00016D71007E00227870737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F400000000000037708000000040000000274000A6772616E745F7479706574000870617373776F7264740008757365726E616D6574000561646D696E78737200256A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65536574801D92D18F9B80550200007871007E0009737200176A6176612E7574696C2E4C696E6B656448617368536574D86CD75A95DD2A1E020000787200116A6176612E7574696C2E48617368536574BA44859596B8B7340300007870770C000000103F4000000000000174000361707078017371007E0033770C000000103F40000000000000787371007E002A3F40000000000000770800000010000000007870707371007E0033770C000000103F40000000000000787371007E0033770C000000103F40000000000000787372004F6F72672E737072696E676672616D65776F726B2E73656375726974792E61757468656E7469636174696F6E2E557365726E616D6550617373776F726441757468656E7469636174696F6E546F6B656E00000000000001A40200024C000B63726564656E7469616C7371007E00054C00097072696E636970616C71007E00057871007E0003017371007E00077371007E000B0000000977040000000971007E000F71007E001171007E001371007E001571007E001771007E001971007E001B71007E001D71007E001F7871007E003D737200176A6176612E7574696C2E4C696E6B6564486173684D617034C04E5C106CC0FB0200015A000B6163636573734F726465727871007E002A3F400000000000067708000000080000000271007E002C71007E002D71007E002E71007E002F780070737200326F72672E737072696E676672616D65776F726B2E73656375726974792E636F72652E7573657264657461696C732E5573657200000000000001A40200075A00116163636F756E744E6F6E457870697265645A00106163636F756E744E6F6E4C6F636B65645A001563726564656E7469616C734E6F6E457870697265645A0007656E61626C65644C000B617574686F72697469657371007E00244C000870617373776F726471007E000E4C0008757365726E616D6571007E000E7870010101017371007E0030737200116A6176612E7574696C2E54726565536574DD98509395ED875B0300007870737200466F72672E737072696E676672616D65776F726B2E73656375726974792E636F72652E7573657264657461696C732E5573657224417574686F72697479436F6D70617261746F7200000000000001A4020000787077040000000971007E000F71007E001171007E001371007E001571007E001771007E001971007E001B71007E001D71007E001F787074000561646D696E');\n\n#\n# Structure for table \"properties\"\n#\n\nDROP TABLE IF EXISTS `properties`;\nCREATE TABLE `properties` (\n  `id` int(11) NOT NULL,\n  `key` varchar(50) DEFAULT NULL,\n  `value` varchar(500) DEFAULT NULL,\n  `application` varchar(50) DEFAULT NULL,\n  `profile` varchar(50) DEFAULT NULL,\n  `lable` varchar(50) DEFAULT NULL,\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\n#\n# Data for table \"properties\"\n#\n\nINSERT INTO `properties` VALUES (1,'zuul.debug.request','false','unieap-eureka-config-client','dev','master');\n\n#\n# Structure for table \"sys_client_permission\"\n#\n\nDROP TABLE IF EXISTS `sys_client_permission`;\nCREATE TABLE `sys_client_permission` (\n  `clientId` int(11) NOT NULL,\n  `permissionId` int(11) NOT NULL,\n  PRIMARY KEY (`clientId`,`permissionId`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;\n\n#\n# Data for table \"sys_client_permission\"\n#\n\nINSERT INTO `sys_client_permission` VALUES (1,71),(1,72),(1,73),(1,74),(1,75),(2,71),(2,72),(2,73),(2,74),(2,75),(3,71),(3,72),(3,73),(3,74),(3,75),(4,71),(4,72),(4,73),(4,74),(4,75),(5,71),(5,72),(5,73),(5,74),(5,75);\n\n#\n# Structure for table \"sys_client_server\"\n#\n\nDROP TABLE IF EXISTS `sys_client_server`;\nCREATE TABLE `sys_client_server` (\n  `id` int(11) NOT NULL AUTO_INCREMENT,\n  `clientId` int(11) DEFAULT NULL,\n  `moduleId` int(11) DEFAULT NULL COMMENT '模块ID',\n  `serverId` int(11) DEFAULT NULL COMMENT '服务ID',\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='服务授权表';\n\n#\n# Data for table \"sys_client_server\"\n#\n\n\n#\n# Structure for table \"sys_logs\"\n#\n\nDROP TABLE IF EXISTS `sys_logs`;\nCREATE TABLE `sys_logs` (\n  `id` int(11) NOT NULL AUTO_INCREMENT,\n  `userId` int(11) NOT NULL,\n  `module` varchar(50) DEFAULT NULL COMMENT '模块名',\n  `flag` tinyint(4) NOT NULL DEFAULT '1' COMMENT '成功失败',\n  `remark` text COMMENT '备注',\n  `createTime` datetime NOT NULL,\n  PRIMARY KEY (`id`),\n  KEY `userId` (`userId`),\n  KEY `createTime` (`createTime`)\n) ENGINE=InnoDB AUTO_INCREMENT=362 DEFAULT CHARSET=utf8mb4;\n\n#\n# Data for table \"sys_logs\"\n#\n\nINSERT INTO `sys_logs` VALUES (1,1,'登陆',1,NULL,'2018-03-14 03:59:44'),(2,1,'登陆',1,NULL,'2018-03-14 06:26:11'),(3,1,'登陆',1,NULL,'2018-03-14 08:39:16'),(4,1,'保存用户',1,NULL,'2018-03-14 08:43:48'),(5,1,'修改用户',1,NULL,'2018-03-14 08:43:56'),(6,1,'登陆',1,NULL,'2018-03-14 10:12:39'),(7,1,'登陆',1,NULL,'2018-03-14 13:01:21'),(8,1,'保存用户',1,NULL,'2018-03-14 13:02:36'),(9,1,'保存角色',1,NULL,'2018-03-14 13:03:08'),(10,1,'保存角色',1,NULL,'2018-03-14 13:03:18'),(11,1,'保存角色',1,NULL,'2018-03-14 13:03:36'),(12,1,'修改用户',1,NULL,'2018-03-14 13:03:43'),(13,1,'退出',1,NULL,'2018-03-14 13:03:50'),(14,4,'登陆',1,NULL,'2018-03-14 13:03:55'),(15,4,'退出',1,NULL,'2018-03-14 13:04:04'),(16,1,'登陆',1,NULL,'2018-03-14 13:04:09'),(17,1,'保存角色',1,NULL,'2018-03-14 13:04:18'),(18,1,'退出',1,NULL,'2018-03-14 13:04:22'),(19,4,'登陆',1,NULL,'2018-03-14 13:04:27'),(20,4,'退出',1,NULL,'2018-03-14 13:13:39'),(21,4,'登陆',1,NULL,'2018-03-14 13:13:45'),(22,4,'退出',1,NULL,'2018-03-14 13:22:28'),(23,4,'登陆',1,NULL,'2018-03-14 13:22:32'),(24,4,'退出',1,NULL,'2018-03-14 13:24:27'),(25,4,'登陆',1,NULL,'2018-03-14 13:24:31'),(26,4,'退出',1,NULL,'2018-03-14 13:24:50'),(27,4,'登陆',1,NULL,'2018-03-14 13:24:54'),(28,4,'登陆',1,NULL,'2018-03-14 15:49:48'),(29,4,'退出',1,NULL,'2018-03-14 15:51:00'),(30,4,'登陆',1,NULL,'2018-03-14 15:51:03'),(31,4,'退出',1,NULL,'2018-03-14 15:52:06'),(32,4,'登陆',1,NULL,'2018-03-14 15:52:09'),(33,4,'退出',1,NULL,'2018-03-14 15:56:29'),(34,4,'登陆',1,NULL,'2018-03-14 15:56:32'),(35,4,'登陆',1,NULL,'2018-03-14 15:57:21'),(36,4,'退出',1,NULL,'2018-03-14 16:03:58'),(37,4,'登陆',1,NULL,'2018-03-14 16:04:01'),(38,4,'退出',1,NULL,'2018-03-14 16:26:27'),(39,1,'登陆',1,NULL,'2018-03-14 16:26:31'),(40,1,'退出',1,NULL,'2018-03-14 16:26:48'),(41,4,'登陆',1,NULL,'2018-03-14 16:26:51'),(42,4,'退出',1,NULL,'2018-03-14 16:34:39'),(43,1,'登陆',1,NULL,'2018-03-14 16:35:19'),(44,1,'登陆',1,NULL,'2018-03-14 18:45:34'),(45,1,'登陆',1,NULL,'2018-03-14 23:30:14'),(46,1,'添加定时任务',1,NULL,'2018-03-15 00:00:08'),(47,4,'��½',1,NULL,'2018-03-15 04:37:19'),(48,1,'登陆',1,NULL,'2018-03-15 04:43:52'),(49,1,'生成代码',0,NULL,'2018-03-15 04:44:50'),(50,1,'生成代码',0,NULL,'2018-03-15 04:45:13'),(51,1,'修改菜单',1,NULL,'2018-03-15 04:45:57'),(52,1,'登陆',1,NULL,'2018-03-25 23:30:29'),(53,1,'登陆',1,NULL,'2018-03-26 18:16:00'),(54,1,'保存角色',1,NULL,'2018-03-26 18:16:20'),(55,1,'退出',1,NULL,'2018-03-26 18:16:29'),(56,1,'登陆',1,NULL,'2018-03-26 18:16:34'),(57,1,'退出',1,NULL,'2018-03-26 19:29:52'),(58,1,'登陆',1,NULL,'2018-03-26 19:29:57'),(59,1,'退出',1,NULL,'2018-03-26 19:31:43'),(60,1,'登陆',1,NULL,'2018-03-26 19:31:52'),(61,1,'登陆',1,NULL,'2018-03-26 22:36:47'),(62,1,'登陆',1,NULL,'2018-03-27 00:38:15'),(63,1,'登陆',1,NULL,'2018-03-27 00:46:41'),(64,1,'登陆',1,NULL,'2018-03-27 00:52:14'),(65,1,'登陆',1,NULL,'2018-03-27 00:54:55'),(66,1,'登陆',1,NULL,'2018-03-27 01:23:12'),(67,1,'登陆',1,NULL,'2018-03-27 02:20:42'),(68,1,'登陆',1,NULL,'2018-03-27 03:42:26'),(69,1,'登陆',1,NULL,'2018-03-27 04:56:58'),(70,1,'登陆',1,NULL,'2018-03-27 04:57:23'),(71,1,'登陆',1,NULL,'2018-03-27 04:58:41'),(72,1,'登陆',1,NULL,'2018-03-27 05:02:02'),(73,1,'登陆',1,NULL,'2018-03-27 19:17:50'),(74,4,'登陆',1,NULL,'2018-03-28 23:12:13'),(75,4,'登陆',1,NULL,'2018-03-28 23:41:49'),(76,4,'退出',1,NULL,'2018-03-28 23:41:53'),(77,1,'登陆',1,NULL,'2018-03-28 23:41:58'),(78,1,'退出',1,NULL,'2018-03-28 23:44:53'),(79,1,'登陆',1,NULL,'2018-03-28 23:44:57'),(80,1,'退出',1,NULL,'2018-03-28 23:46:18'),(81,1,'登陆',1,NULL,'2018-03-28 23:46:23'),(82,1,'登陆',1,NULL,'2018-03-31 03:31:00'),(83,1,'登陆',1,NULL,'2018-03-31 04:08:08'),(84,1,'登陆',1,NULL,'2018-04-03 00:08:01'),(85,1,'保存角色',1,NULL,'2018-04-03 00:08:29'),(86,1,'退出',1,NULL,'2018-04-03 00:08:37'),(87,1,'登陆',1,NULL,'2018-04-03 00:08:42'),(88,1,'登陆',1,NULL,'2018-04-03 01:18:56'),(89,1,'登陆',1,NULL,'2018-04-04 23:00:02'),(90,1,'登陆',1,NULL,'2018-04-09 06:48:29'),(91,1,'登陆',1,NULL,'2018-04-12 00:19:47'),(92,1,'登陆',1,NULL,'2018-04-14 20:01:20'),(93,1,'退出',1,NULL,'2018-04-14 20:01:26'),(94,1,'登陆',1,NULL,'2018-04-14 20:16:46'),(95,1,'登陆',1,NULL,'2018-04-14 20:42:45'),(96,1,'登陆',1,NULL,'2018-04-14 21:22:18'),(97,1,'登陆',1,NULL,'2018-04-14 21:42:05'),(98,1,'保存用户',1,NULL,'2018-04-14 21:42:43'),(99,1,'修改菜单',1,NULL,'2018-04-14 21:43:11'),(100,1,'生成代码',0,NULL,'2018-04-14 21:44:00'),(101,1,'生成代码',0,NULL,'2018-04-14 21:46:30'),(102,1,'生成代码',0,NULL,'2018-04-14 21:47:02'),(103,1,'生成代码',0,NULL,'2018-04-14 21:49:52'),(104,1,'生成代码',0,NULL,'2018-04-14 21:50:10'),(105,1,'生成代码',1,NULL,'2018-04-14 22:04:21'),(106,1,'文件上传',1,NULL,'2018-04-14 22:12:57'),(107,1,'文件删除',1,NULL,'2018-04-14 22:14:21'),(108,1,'登陆',1,NULL,'2018-04-15 01:43:48'),(109,1,'退出',1,NULL,'2018-04-15 01:49:59'),(110,1,'登陆',1,NULL,'2018-04-15 01:50:09'),(111,1,'登陆',1,NULL,'2018-04-15 11:36:18'),(112,1,'保存角色',1,NULL,'2018-04-15 11:39:42'),(113,1,'退出',1,NULL,'2018-04-15 11:39:46'),(114,1,'登陆',1,NULL,'2018-04-15 11:39:51'),(115,1,'生成代码',1,NULL,'2018-04-15 11:42:35'),(116,1,'退出',1,NULL,'2018-04-15 11:47:17'),(117,1,'登陆',1,NULL,'2018-04-15 11:47:21'),(118,1,'退出',1,NULL,'2018-04-15 12:11:38'),(119,1,'登陆',1,NULL,'2018-04-15 12:11:44'),(120,1,'登陆',1,NULL,'2018-04-24 10:29:06'),(121,1,'登陆',1,NULL,'2018-04-24 10:32:11'),(122,1,'登陆',1,NULL,'2018-04-24 10:34:41'),(123,1,'登陆',1,NULL,'2018-04-24 10:55:53'),(124,1,'登陆',1,NULL,'2018-04-24 10:57:04'),(125,1,'登陆',1,NULL,'2018-04-24 10:59:25'),(126,1,'退出',1,NULL,'2018-04-24 11:07:13'),(127,1,'登陆',1,NULL,'2018-04-24 11:09:14'),(128,1,'保存角色',1,NULL,'2018-04-24 11:09:34'),(129,1,'文件上传',1,NULL,'2018-04-24 11:09:48'),(130,1,'文件删除',1,NULL,'2018-04-24 11:09:58'),(131,1,'登陆',1,NULL,'2018-04-24 17:46:26'),(132,1,'保存角色',1,NULL,'2018-04-24 17:47:12'),(133,1,'登陆',1,NULL,'2018-04-25 14:38:39'),(134,1,'退出',1,NULL,'2018-04-25 14:39:03'),(135,1,'登陆',1,NULL,'2018-04-25 14:39:09'),(136,1,'退出',1,NULL,'2018-04-25 14:46:06'),(137,1,'登陆',1,NULL,'2018-04-25 14:57:04'),(138,1,'退出',1,NULL,'2018-04-25 14:57:42'),(139,1,'登陆',1,NULL,'2018-04-25 15:03:02'),(140,1,'退出',1,NULL,'2018-04-25 15:03:08'),(141,1,'登陆',1,NULL,'2018-04-25 15:08:17'),(142,1,'退出',1,NULL,'2018-04-25 15:09:17'),(143,1,'登陆',1,NULL,'2018-04-25 15:23:24'),(144,1,'退出',1,NULL,'2018-04-25 15:30:49'),(145,1,'登陆',1,NULL,'2018-04-25 15:30:57'),(146,1,'保存角色',1,NULL,'2018-04-25 15:52:18'),(147,1,'保存角色',1,NULL,'2018-04-25 15:53:03'),(148,1,'登陆',1,NULL,'2018-04-25 16:02:21'),(149,1,'退出',1,NULL,'2018-04-25 16:03:22'),(150,1,'登陆',1,NULL,'2018-04-26 09:32:24'),(151,1,'修改菜单',1,NULL,'2018-04-26 09:33:47'),(152,1,'退出',1,NULL,'2018-04-26 09:33:59'),(153,1,'登陆',1,NULL,'2018-04-26 09:34:07'),(154,1,'退出',1,NULL,'2018-04-26 09:36:21'),(155,1,'登陆',1,NULL,'2018-04-26 09:36:36'),(156,1,'修改菜单',1,NULL,'2018-04-26 09:37:12'),(157,1,'退出',1,NULL,'2018-04-26 09:37:22'),(158,1,'登陆',1,NULL,'2018-04-26 09:37:33'),(159,1,'登陆',1,NULL,'2018-04-26 09:39:50'),(160,1,'退出',1,NULL,'2018-04-26 10:25:09'),(161,1,'登陆',1,NULL,'2018-04-26 10:25:16'),(162,1,'保存角色',1,NULL,'2018-04-26 10:49:07'),(163,1,'退出',1,NULL,'2018-04-26 10:51:52'),(164,1,'登陆',1,NULL,'2018-04-26 10:52:46'),(165,1,'登陆',1,NULL,'2018-04-26 10:57:38'),(166,1,'保存角色',1,NULL,'2018-04-26 11:16:36'),(167,1,'登陆',1,NULL,'2018-04-26 17:48:38'),(168,1,'登陆',1,NULL,'2018-04-27 10:30:53'),(169,1,'登陆',1,NULL,'2018-05-02 11:58:33'),(170,1,'登陆',1,NULL,'2018-05-02 15:05:51'),(171,1,'登陆',1,NULL,'2018-05-03 14:44:52'),(172,1,'退出',1,NULL,'2018-05-03 14:53:01'),(173,1,'登陆',1,NULL,'2018-05-03 14:53:08'),(174,1,'退出',1,NULL,'2018-05-03 14:54:07'),(175,1,'登陆',1,NULL,'2018-05-03 14:54:18'),(176,1,'登陆',1,NULL,'2018-05-03 15:12:14'),(177,1,'登陆',1,NULL,'2018-05-04 09:43:22'),(178,1,'登陆',1,NULL,'2018-05-04 10:05:30'),(179,1,'登陆',1,NULL,'2018-05-04 12:16:22'),(180,1,'登陆',1,NULL,'2018-05-14 15:25:11'),(181,1,'保存角色',1,NULL,'2018-05-14 15:25:53'),(182,1,'退出',1,NULL,'2018-05-14 15:25:56'),(183,1,'登陆',1,NULL,'2018-05-14 15:26:01'),(184,1,'退出',1,NULL,'2018-05-14 15:26:15'),(185,1,'登陆',1,NULL,'2018-05-14 15:26:23'),(186,1,'保存模块',1,NULL,'2018-05-14 15:27:33'),(187,1,'保存模块',1,NULL,'2018-05-14 15:28:06'),(188,1,'保存服务',1,NULL,'2018-05-14 15:29:41'),(189,1,'保存服务',1,NULL,'2018-05-14 15:30:10'),(190,1,'修改服务',1,NULL,'2018-05-14 15:30:24'),(191,1,'退出',1,NULL,'2018-05-15 20:25:15'),(192,1,'登陆',1,NULL,'2018-05-15 20:25:16'),(193,1,'退出',1,NULL,'2018-05-15 20:29:35'),(194,1,'登陆',1,NULL,'2018-05-15 20:29:36'),(195,1,'退出',1,NULL,'2018-05-15 20:30:02'),(196,1,'登陆',1,NULL,'2018-05-15 20:30:03'),(197,1,'退出',1,NULL,'2018-05-15 20:43:21'),(198,1,'登陆',1,NULL,'2018-05-15 20:43:22'),(199,1,'退出',1,NULL,'2018-05-15 21:12:00'),(200,1,'登陆',1,NULL,'2018-05-15 21:12:02'),(201,1,'退出',1,NULL,'2018-05-15 21:21:59'),(202,1,'登陆',1,NULL,'2018-05-15 21:22:00'),(203,1,'登陆',1,NULL,'2018-05-16 10:45:32'),(204,1,'登陆',1,NULL,'2018-05-16 11:12:57'),(205,1,'登陆',1,NULL,'2018-05-16 11:16:12'),(206,1,'登陆',1,NULL,'2018-05-16 11:37:20'),(207,1,'退出',1,NULL,'2018-05-16 11:54:56'),(208,1,'登陆',1,NULL,'2018-05-16 11:54:57'),(209,1,'退出',1,NULL,'2018-05-16 14:05:34'),(210,1,'登陆',1,NULL,'2018-05-16 14:05:36'),(211,1,'退出',1,NULL,'2018-05-16 14:13:04'),(212,1,'登陆',1,NULL,'2018-05-16 14:13:05'),(213,1,'登陆',1,NULL,'2018-05-16 14:20:20'),(214,1,'登陆',1,NULL,'2018-05-16 14:33:50'),(215,1,'登陆',1,NULL,'2018-05-16 14:44:44'),(216,1,'退出',1,NULL,'2018-05-16 14:46:48'),(217,1,'登陆',1,NULL,'2018-05-16 14:46:49'),(218,1,'退出',1,NULL,'2018-05-16 14:55:08'),(219,1,'登陆',1,NULL,'2018-05-16 14:55:09'),(220,1,'登陆',1,NULL,'2018-05-16 15:29:35'),(221,1,'退出',1,NULL,'2018-05-16 16:12:33'),(222,1,'登陆',1,NULL,'2018-05-16 16:12:34'),(223,1,'登陆',1,NULL,'2018-05-16 16:12:40'),(224,1,'登陆',1,NULL,'2018-05-16 16:36:01'),(225,1,'登陆',1,NULL,'2018-05-16 17:07:55'),(226,1,'登陆',1,NULL,'2018-05-16 17:31:19'),(227,1,'登陆',1,NULL,'2018-05-16 17:49:52'),(228,1,'登陆',1,NULL,'2018-05-16 17:55:27'),(229,1,'登陆',1,NULL,'2018-05-17 14:12:25'),(230,1,'登陆',1,NULL,'2018-05-17 14:48:04'),(231,1,'登陆',1,NULL,'2018-05-17 14:52:12'),(232,1,'登陆',1,NULL,'2018-05-17 15:08:28'),(233,1,'登陆',1,NULL,'2018-05-17 15:09:36'),(234,1,'登陆',1,NULL,'2018-05-17 15:13:14'),(235,1,'登陆',1,NULL,'2018-05-17 15:43:52'),(236,1,'登陆',1,NULL,'2018-05-17 15:46:45'),(237,1,'登陆',1,NULL,'2018-05-17 15:50:35'),(238,1,'登陆',1,NULL,'2018-05-17 15:51:46'),(239,1,'登陆',1,NULL,'2018-05-17 15:57:28'),(240,1,'退出',1,NULL,'2018-05-17 17:05:21'),(241,1,'登陆',1,NULL,'2018-05-17 17:05:25'),(242,1,'登陆',1,NULL,'2018-05-17 17:05:34'),(243,1,'登陆',1,NULL,'2018-05-17 17:46:35'),(244,1,'登陆',1,NULL,'2018-05-17 17:47:56'),(245,1,'登陆',1,NULL,'2018-05-17 17:49:23'),(246,1,'登陆',1,NULL,'2018-05-17 17:56:50'),(247,1,'登陆',1,NULL,'2018-05-17 18:00:28'),(248,1,'登陆',1,NULL,'2018-05-17 18:01:21'),(249,1,'退出',1,NULL,'2018-05-17 20:01:38'),(250,1,'登陆',1,NULL,'2018-05-17 20:01:39'),(251,1,'退出',1,NULL,'2018-05-17 20:02:27'),(252,1,'登陆',1,NULL,'2018-05-17 20:02:34'),(253,1,'登陆',1,NULL,'2018-05-17 20:05:36'),(254,1,'登陆',1,NULL,'2018-05-17 20:07:47'),(255,1,'登陆',1,NULL,'2018-05-17 20:08:29'),(256,1,'登陆',1,NULL,'2018-05-17 20:10:24'),(257,1,'登陆',1,NULL,'2018-05-17 21:07:53'),(258,1,'登陆',1,NULL,'2018-05-17 21:26:35'),(259,1,'退出',1,NULL,'2018-05-17 21:36:48'),(260,1,'登陆',1,NULL,'2018-05-17 21:37:01'),(261,1,'登陆',1,NULL,'2018-05-17 21:43:10'),(262,1,'登陆',1,NULL,'2018-05-17 21:51:16'),(263,1,'登陆',1,NULL,'2018-05-18 11:09:20'),(264,1,'登陆',1,NULL,'2018-06-07 10:00:30'),(265,1,'退出',1,NULL,'2018-06-07 10:01:04'),(266,1,'登陆',1,NULL,'2018-06-11 05:00:07'),(267,1,'退出',1,NULL,'2018-06-11 05:02:34'),(268,1,'登陆',1,NULL,'2018-06-11 05:26:20'),(269,1,'退出',1,NULL,'2018-06-11 05:29:11'),(270,1,'登陆',1,NULL,'2018-06-11 05:29:34'),(271,1,'修改菜单',1,NULL,'2018-06-11 05:30:12'),(272,1,'退出',1,NULL,'2018-06-11 05:30:16'),(273,1,'登陆',1,NULL,'2018-06-11 05:30:22'),(274,1,'登陆',1,NULL,'2018-06-12 04:19:00'),(275,1,'登陆',1,NULL,'2018-06-22 06:44:06'),(276,1,'登陆',1,NULL,'2018-06-22 11:56:38'),(277,1,'删除应用',1,NULL,'2018-06-22 11:56:50'),(278,1,'删除应用',1,NULL,'2018-06-22 11:56:53'),(279,1,'删除应用',1,NULL,'2018-06-22 11:56:56'),(280,1,'删除应用',1,NULL,'2018-06-22 11:56:58'),(281,1,'删除应用',1,NULL,'2018-06-22 11:57:00'),(282,1,'保存应用',1,NULL,'2018-06-22 11:59:22'),(283,1,'删除应用',1,NULL,'2018-06-22 12:00:12'),(284,1,'保存应用',1,NULL,'2018-06-22 12:00:25'),(285,1,'登陆',1,NULL,'2018-06-22 17:01:36'),(286,1,'保存菜单',1,NULL,'2018-06-22 17:09:40'),(287,1,'保存角色',1,NULL,'2018-06-22 17:09:54'),(288,1,'退出',1,NULL,'2018-06-22 17:09:57'),(289,1,'登陆',1,NULL,'2018-06-22 17:10:01'),(290,1,'退出',1,NULL,'2018-06-22 17:25:57'),(291,1,'登陆',1,NULL,'2018-06-22 17:26:01'),(292,1,'删除菜单',1,NULL,'2018-06-22 17:32:50'),(293,1,'删除菜单',1,NULL,'2018-06-22 17:33:18'),(294,1,'退出',1,NULL,'2018-06-22 17:44:04'),(295,1,'登陆',1,NULL,'2018-06-22 17:44:09'),(296,1,'修改服务',1,NULL,'2018-06-22 17:53:35'),(297,1,'保存服务',1,NULL,'2018-06-22 17:53:55'),(298,1,'删除服务',0,'\\r\\n### Error updating database.  Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column \\'permissionId\\' in \\'where clause\\'\\r\\n### The error may involve com.open.capacity.security.dao.ServiceDao.deleteRolePermission-Inline\\r\\n### The error occurred while setting parameters\\r\\n### SQL: delete from sys_services where permissionId = ?\\r\\n### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column \\'permissionId\\' in \\'where clause\\'\\n; bad SQL grammar []; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column \\'permissionId\\' in \\'where clause\\'','2018-06-22 17:54:10'),(299,1,'删除服务',1,NULL,'2018-06-22 17:57:45'),(300,1,'删除服务',1,NULL,'2018-06-22 17:59:05'),(301,1,'删除服务',1,NULL,'2018-06-22 17:59:08'),(302,1,'删除服务',1,NULL,'2018-06-22 17:59:10'),(303,1,'删除服务',1,NULL,'2018-06-22 17:59:13'),(304,1,'删除服务',1,NULL,'2018-06-22 17:59:15'),(305,1,'删除服务',1,NULL,'2018-06-22 17:59:17'),(306,1,'删除服务',1,NULL,'2018-06-22 17:59:19'),(307,1,'删除服务',1,NULL,'2018-06-22 17:59:21'),(308,1,'删除服务',1,NULL,'2018-06-22 17:59:24'),(309,1,'删除服务',1,NULL,'2018-06-22 17:59:26'),(310,1,'修改服务',1,NULL,'2018-06-22 17:59:42'),(311,1,'删除服务',1,NULL,'2018-06-22 18:00:25'),(312,1,'删除服务',1,NULL,'2018-06-22 18:00:29'),(313,1,'删除服务',1,NULL,'2018-06-22 18:00:38'),(314,1,'退出',1,NULL,'2018-06-22 07:23:01'),(315,1,'登陆',1,NULL,'2018-06-22 07:23:06'),(316,1,'保存服务',1,NULL,'2018-06-22 07:23:44'),(317,1,'保存服务',1,NULL,'2018-06-22 07:24:18'),(318,1,'修改服务',1,NULL,'2018-06-22 07:24:57'),(319,1,'保存服务',1,NULL,'2018-06-22 07:27:46'),(320,1,'修改服务',1,NULL,'2018-06-22 07:28:14'),(321,1,'保存服务',1,NULL,'2018-06-22 07:28:36'),(322,1,'保存服务',1,NULL,'2018-06-22 07:28:53'),(323,1,'保存服务',1,NULL,'2018-06-22 07:34:15'),(324,1,'保存服务',1,NULL,'2018-06-22 07:35:51'),(325,1,'修改服务',1,NULL,'2018-06-22 07:36:29'),(326,1,'修改服务',1,NULL,'2018-06-22 07:37:17'),(327,1,'保存服务',1,NULL,'2018-06-22 07:38:37'),(328,1,'修改服务',1,NULL,'2018-06-22 07:38:52'),(329,1,'保存菜单',1,NULL,'2018-06-22 07:44:33'),(330,1,'修改菜单',1,NULL,'2018-06-22 07:44:49'),(331,1,'修改菜单',1,NULL,'2018-06-22 07:45:05'),(332,1,'退出',1,NULL,'2018-06-22 07:45:10'),(333,1,'登陆',1,NULL,'2018-06-22 07:45:16'),(334,1,'保存角色',1,NULL,'2018-06-22 07:45:57'),(335,1,'退出',1,NULL,'2018-06-22 07:46:02'),(336,1,'登陆',1,NULL,'2018-06-22 07:46:07'),(337,1,'保存角色',1,NULL,'2018-06-22 07:46:48'),(338,1,'删除菜单',1,NULL,'2018-06-22 07:47:03'),(339,1,'退出',1,NULL,'2018-06-22 07:47:06'),(340,1,'登陆',1,NULL,'2018-06-22 07:47:12'),(341,1,'修改菜单',1,NULL,'2018-06-22 07:47:33'),(342,1,'退出',1,NULL,'2018-06-22 07:47:37'),(343,1,'登陆',1,NULL,'2018-06-22 07:47:45'),(344,1,'修改菜单',1,NULL,'2018-06-22 07:48:01'),(345,1,'退出',1,NULL,'2018-06-22 07:48:05'),(346,1,'登陆',1,NULL,'2018-06-22 07:48:11'),(347,1,'登陆',1,NULL,'2018-06-22 07:51:15'),(348,1,'退出',1,NULL,'2018-06-22 07:52:00'),(349,1,'登陆',1,NULL,'2018-06-22 07:52:05'),(350,1,'登陆',1,NULL,'2018-06-22 07:52:37'),(351,1,'登陆',1,NULL,'2018-06-22 07:54:01'),(352,1,'登陆',1,NULL,'2018-06-22 07:54:35'),(353,1,'登陆',1,NULL,'2018-06-22 07:54:51'),(354,1,'登陆',1,NULL,'2018-06-22 08:40:43'),(355,1,'保存应用',0,'webApp已存在','2018-06-22 08:40:57'),(356,1,'保存应用',0,'webApp已存在','2018-06-22 08:43:01'),(357,1,'保存应用',0,'webApp已存在','2018-06-22 08:44:30'),(358,1,'保存应用',0,'webApp已存在','2018-06-22 08:44:47'),(359,1,'保存服务',1,NULL,'2018-06-22 08:52:37'),(360,1,'修改服务',1,NULL,'2018-06-22 08:53:04'),(361,1,'保存服务',1,NULL,'2018-06-22 08:53:31');\n\n#\n# Structure for table \"sys_module\"\n#\n\nDROP TABLE IF EXISTS `sys_module`;\nCREATE TABLE `sys_module` (\n  `id` int(11) NOT NULL AUTO_INCREMENT,\n  `version` bigint(20) DEFAULT '0' COMMENT '版本号',\n  `description` varchar(200) COLLATE utf8_bin DEFAULT NULL COMMENT '描述',\n  `image` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT '图片',\n  `name` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT '模块名',\n  `index_page` varchar(255) COLLATE utf8_bin DEFAULT NULL COMMENT '模块首页',\n  `if_show` varchar(1) COLLATE utf8_bin DEFAULT '1' COMMENT '是否显示（1：显示；0：不显示）',\n  `sort` int(20) DEFAULT NULL COMMENT '排序',\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='模块表';\n\n#\n# Data for table \"sys_module\"\n#\n\nINSERT INTO `sys_module` VALUES (1,NULL,'',NULL,'认证中心','/auth','1',100),(2,NULL,'',NULL,'演示demo','/client','1',100);\n\n#\n# Structure for table \"sys_permission\"\n#\n\nDROP TABLE IF EXISTS `sys_permission`;\nCREATE TABLE `sys_permission` (\n  `id` int(11) NOT NULL AUTO_INCREMENT,\n  `parentId` int(11) NOT NULL,\n  `name` varchar(50) NOT NULL,\n  `css` varchar(30) DEFAULT NULL,\n  `href` varchar(1000) DEFAULT NULL,\n  `type` tinyint(1) NOT NULL,\n  `permission` varchar(50) DEFAULT NULL,\n  `sort` int(11) NOT NULL,\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=67 DEFAULT CHARSET=utf8mb4;\n\n#\n# Data for table \"sys_permission\"\n#\n\nINSERT INTO `sys_permission` VALUES (1,0,'用户管理','fa-users','',1,'',2),(2,1,'用户查询','fa-user','pages/user/userList.html',1,'',3),(3,2,'查询','','',2,'sys:user:query',100),(4,2,'新增','','',2,'sys:user:add',100),(6,1,'修改密码','fa-pencil-square-o','pages/user/changePassword.html',1,'sys:user:password',4),(7,0,'系统设置','fa-gears','',1,'',5),(8,7,'菜单','fa-cog','pages/menu/menuList.html',1,'',6),(9,8,'查询','','',2,'sys:menu:query',100),(10,8,'新增','','',2,'sys:menu:add',100),(11,8,'删除','','',2,'sys:menu:del',100),(12,7,'角色','fa-user-secret','pages/role/roleList.html',1,'',7),(13,12,'查询','','',2,'sys:role:query',100),(14,12,'新增','','',2,'sys:role:add',100),(15,12,'删除','','',2,'sys:role:del',100),(16,0,'文件管理','fa-folder-open','pages/file/fileList.html',1,'',8),(17,16,'查询','','',2,'sys:file:query',100),(18,16,'删除','','',2,'sys:file:del',100),(19,0,'数据源监控','fa-eye','druid/index.html',1,'',9),(26,0,'日志查询','fa-reorder','pages/log/logList.html',1,'sys:log:query',13),(41,0,'注册中心','fa-th-list','pages/euraka/euraka.html',1,'',18),(42,0,'配置中心','fa-th-list','http://127.0.0.1:8070',1,'',19),(56,0,'工作流管理','fa-th-list',NULL,1,NULL,22),(57,56,'流程管理',NULL,'/pages/activiti/actList.html',1,NULL,21),(58,56,'模型列表','','/pages/activiti/actModelList.html',1,'',22),(60,41,'操作','','',2,'job:add',100),(61,66,'应用管理','','pages/client/clientList.html',1,'',10),(62,61,'查询','','',2,'sys:role:query',100),(63,61,'新增','','',2,'sys:role:add',100),(64,61,'删除','','',2,'sys:role:del',100),(65,66,'服务管理','','pages/service/serviceList.html',1,'',1),(66,0,'资源管理','','',1,'',100);\n\n#\n# Structure for table \"sys_role\"\n#\n\nDROP TABLE IF EXISTS `sys_role`;\nCREATE TABLE `sys_role` (\n  `id` int(11) NOT NULL AUTO_INCREMENT,\n  `name` varchar(50) NOT NULL,\n  `description` varchar(100) DEFAULT NULL,\n  `createTime` datetime NOT NULL,\n  `updateTime` datetime NOT NULL,\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `name` (`name`)\n) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4;\n\n#\n# Data for table \"sys_role\"\n#\n\nINSERT INTO `sys_role` VALUES (1,'ADMIN','管理员','2017-05-01 13:25:39','2018-06-22 07:46:48'),(2,'USER','11','2017-08-01 21:47:31','2018-06-21 11:09:12'),(3,'test1','test1','2018-03-14 13:03:36','2018-06-21 11:09:32'),(4,'ttttt','ttt1','2018-04-24 11:09:34','2018-06-21 11:12:26'),(5,'11111','222222','2018-04-24 17:47:12','2018-04-26 10:49:07');\n\n#\n# Structure for table \"sys_role_permission\"\n#\n\nDROP TABLE IF EXISTS `sys_role_permission`;\nCREATE TABLE `sys_role_permission` (\n  `roleId` int(11) NOT NULL,\n  `permissionId` int(11) NOT NULL,\n  PRIMARY KEY (`roleId`,`permissionId`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;\n\n#\n# Data for table \"sys_role_permission\"\n#\n\nINSERT INTO `sys_role_permission` VALUES (1,1),(1,2),(1,3),(1,4),(1,6),(1,7),(1,8),(1,9),(1,10),(1,11),(1,12),(1,13),(1,14),(1,15),(1,16),(1,17),(1,18),(1,19),(1,26),(1,41),(1,42),(1,56),(1,57),(1,58),(1,60),(1,61),(1,62),(1,63),(1,64),(1,65),(1,66),(2,1),(2,2),(2,3),(2,4),(2,6),(2,7),(2,8),(2,9),(2,10),(2,11),(2,12),(2,13),(2,14),(2,15),(2,16),(2,17),(2,18),(2,19),(3,1),(3,2),(3,3),(3,7),(3,12),(3,13),(3,14),(3,15),(4,1),(4,2),(4,3),(4,4),(4,6),(4,7),(4,8),(4,9),(4,10),(4,11),(4,12),(4,13),(4,14),(4,15),(4,16),(4,17),(4,18),(4,19),(4,26),(4,41),(4,42),(5,1),(5,2),(5,3),(5,4),(5,6),(5,7),(5,8),(5,9),(5,10),(5,11),(5,12),(5,13),(5,14),(5,15),(5,16),(5,17),(5,18),(5,19),(5,26),(5,38),(5,39),(5,40),(5,41),(5,42);\n\n#\n# Structure for table \"sys_role_user\"\n#\n\nDROP TABLE IF EXISTS `sys_role_user`;\nCREATE TABLE `sys_role_user` (\n  `userId` int(11) NOT NULL,\n  `roleId` int(11) NOT NULL,\n  PRIMARY KEY (`userId`,`roleId`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;\n\n#\n# Data for table \"sys_role_user\"\n#\n\nINSERT INTO `sys_role_user` VALUES (1,1),(1,2),(1,3),(1,4),(1,5),(2,1),(2,2),(2,3),(2,4),(2,5),(3,1),(3,2),(4,3),(5,1),(5,2);\n\n#\n# Structure for table \"sys_server\"\n#\n\nDROP TABLE IF EXISTS `sys_server`;\nCREATE TABLE `sys_server` (\n  `id` int(11) NOT NULL AUTO_INCREMENT,\n  `parentId` int(11) DEFAULT NULL COMMENT '父ID',\n  `moduleId` int(11) DEFAULT NULL COMMENT '模块ID',\n  `name` varchar(100) DEFAULT NULL COMMENT '服务名称',\n  `path` varchar(100) DEFAULT NULL COMMENT '访问路径',\n  `description` varchar(255) DEFAULT NULL COMMENT '服务描述',\n  `sort` int(11) DEFAULT NULL COMMENT '排序',\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COMMENT='服务管理表';\n\n#\n# Data for table \"sys_server\"\n#\n\nINSERT INTO `sys_server` VALUES (1,0,1,'token服务','/user/token','用户名密码获取token',100),(2,0,1,'token服务','/client/token','clientId获取token',100);\n\n#\n# Structure for table \"sys_services\"\n#\n\nDROP TABLE IF EXISTS `sys_services`;\nCREATE TABLE `sys_services` (\n  `id` int(11) NOT NULL AUTO_INCREMENT,\n  `parentId` int(11) NOT NULL,\n  `name` varchar(50) NOT NULL,\n  `css` varchar(30) DEFAULT NULL,\n  `href` varchar(1000) DEFAULT NULL,\n  `type` tinyint(1) NOT NULL,\n  `permission` varchar(50) DEFAULT NULL,\n  `sort` int(11) NOT NULL,\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=74 DEFAULT CHARSET=utf8mb4;\n\n#\n# Data for table \"sys_services\"\n#\n\nINSERT INTO `sys_services` VALUES (71,0,'授权服务','','/auth',1,'',1),(72,71,'用户授权token','','/auth/user/token',1,'',100),(73,71,'应用申请token','','/auth/client/token',1,'',100),(74,0,'测试微服务','','/client',1,'',100),(75,74,'hello接口','','/client/hello',1,'',100);\n\n#\n# Structure for table \"sys_user\"\n#\n\nDROP TABLE IF EXISTS `sys_user`;\nCREATE TABLE `sys_user` (\n  `id` int(11) NOT NULL AUTO_INCREMENT,\n  `username` varchar(50) NOT NULL,\n  `password` varchar(60) NOT NULL,\n  `nickname` varchar(255) DEFAULT NULL,\n  `headImgUrl` varchar(255) DEFAULT NULL,\n  `phone` varchar(11) DEFAULT NULL,\n  `telephone` varchar(30) DEFAULT NULL,\n  `email` varchar(50) DEFAULT NULL,\n  `birthday` date DEFAULT NULL,\n  `sex` tinyint(1) DEFAULT NULL,\n  `status` tinyint(1) NOT NULL DEFAULT '1',\n  `createTime` datetime NOT NULL,\n  `updateTime` datetime NOT NULL,\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `username` (`username`)\n) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4;\n\n#\n# Data for table \"sys_user\"\n#\n\nINSERT INTO `sys_user` VALUES (1,'admin','$2a$10$q54rooCXqDTWYkf29d4ZFu/L3zkq5Uoa6jdA/spRNSwpxksEqJYpy','管理员',NULL,'','','','1998-07-01',0,1,'2017-04-10 15:21:38','2018-05-28 02:49:01'),(2,'user','$2a$10$ooGb4wjT7Hg3zgU2RhZp6eVu3jvG29i/U4L6VRwiZZ4.DZ0OOEAHu','用户',NULL,'22222','2222','',NULL,1,1,'2017-08-01 21:47:18','2018-06-21 21:05:02'),(3,'test123','$2a$10$MGxO0dynaARStolVS9tzk.ZGwzlC2WZ2LZ/LzxixWxCUoftU5Xtnq','test111',NULL,'18571111111','221','22','2018-03-14',1,1,'2018-03-14 08:43:48','2018-06-21 21:04:47'),(4,'owen','$2a$10$JTuOh..ec2N1BBi6NOsn1.beg72gN7je7uNvFn.VWbfkrAsPZ3otC','test',NULL,'18571111111','','11@11.com','2018-03-20',0,1,'2018-03-14 13:02:36','2018-06-12 20:56:07'),(5,'111111111','$2a$10$mJuBGzs67CyExiTZkk5iLOF9sE09GDK7jLf2O6gosMh.g/fDeKEiS','111111',NULL,'11111111111','11111111111','11@11.com','2018-04-11',0,1,'2018-04-14 21:42:43','2018-04-14 21:42:43');\n\n#\n# Structure for table \"t_dict\"\n#\n\nDROP TABLE IF EXISTS `t_dict`;\nCREATE TABLE `t_dict` (\n  `id` int(11) NOT NULL AUTO_INCREMENT,\n  `type` varchar(16) NOT NULL,\n  `k` varchar(16) NOT NULL,\n  `val` varchar(64) NOT NULL,\n  `createTime` datetime NOT NULL,\n  `updateTime` datetime NOT NULL,\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `type` (`type`,`k`)\n) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4;\n\n#\n# Data for table \"t_dict\"\n#\n\nINSERT INTO `t_dict` VALUES (1,'sex','0','女','2017-11-17 09:58:24','2017-11-18 14:21:05'),(2,'sex','1','男','2017-11-17 10:03:46','2017-11-17 10:03:46'),(3,'userStatus','0','无效','2017-11-17 16:26:06','2017-11-17 16:26:09'),(4,'userStatus','1','正常','2017-11-17 16:26:06','2017-11-17 16:26:09'),(5,'userStatus','2','锁定','2017-11-17 16:26:06','2017-11-17 16:26:09'),(6,'noticeStatus','0','草稿','2017-11-17 16:26:06','2017-11-17 16:26:09'),(7,'noticeStatus','1','发布','2017-11-17 16:26:06','2017-11-17 16:26:09'),(8,'isRead','0','未读','2017-11-17 16:26:06','2017-11-17 16:26:09'),(9,'isRead','1','已读','2017-11-17 16:26:06','2017-11-17 16:26:09');\n\n#\n# Structure for table \"t_job\"\n#\n\nDROP TABLE IF EXISTS `t_job`;\nCREATE TABLE `t_job` (\n  `id` int(11) NOT NULL AUTO_INCREMENT,\n  `jobName` varchar(64) NOT NULL,\n  `description` varchar(255) DEFAULT NULL,\n  `cron` varchar(64) NOT NULL,\n  `springBeanName` varchar(64) NOT NULL COMMENT 'springBean名',\n  `methodName` varchar(64) NOT NULL COMMENT '方法名',\n  `isSysJob` tinyint(1) NOT NULL COMMENT '是否是系统job',\n  `status` tinyint(1) NOT NULL DEFAULT '1',\n  `createTime` datetime NOT NULL,\n  `updateTime` datetime NOT NULL,\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `jobName` (`jobName`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;\n\n#\n# Data for table \"t_job\"\n#\n\n\n#\n# Structure for table \"t_mail\"\n#\n\nDROP TABLE IF EXISTS `t_mail`;\nCREATE TABLE `t_mail` (\n  `id` int(11) NOT NULL AUTO_INCREMENT,\n  `userId` int(11) NOT NULL COMMENT '发送人',\n  `subject` varchar(255) NOT NULL COMMENT '标题',\n  `content` longtext NOT NULL COMMENT '正文',\n  `createTime` datetime NOT NULL,\n  `updateTime` datetime NOT NULL,\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;\n\n#\n# Data for table \"t_mail\"\n#\n\n\n#\n# Structure for table \"t_mail_to\"\n#\n\nDROP TABLE IF EXISTS `t_mail_to`;\nCREATE TABLE `t_mail_to` (\n  `id` int(11) NOT NULL AUTO_INCREMENT,\n  `mailId` int(11) NOT NULL,\n  `toUser` varchar(128) NOT NULL,\n  `status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '1成功，0失败',\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;\n\n#\n# Data for table \"t_mail_to\"\n#\n\n\n#\n# Structure for table \"t_notice\"\n#\n\nDROP TABLE IF EXISTS `t_notice`;\nCREATE TABLE `t_notice` (\n  `id` int(11) NOT NULL AUTO_INCREMENT,\n  `title` varchar(128) NOT NULL,\n  `content` text NOT NULL,\n  `status` tinyint(1) NOT NULL DEFAULT '1',\n  `createTime` datetime NOT NULL,\n  `updateTime` datetime NOT NULL,\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;\n\n#\n# Data for table \"t_notice\"\n#\n\n\n#\n# Structure for table \"t_notice_read\"\n#\n\nDROP TABLE IF EXISTS `t_notice_read`;\nCREATE TABLE `t_notice_read` (\n  `noticeId` int(11) NOT NULL,\n  `userId` int(11) NOT NULL,\n  `createTime` datetime NOT NULL,\n  PRIMARY KEY (`noticeId`,`userId`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;\n\n#\n# Data for table \"t_notice_read\"\n#\n\n\n#\n# Structure for table \"t_token\"\n#\n\nDROP TABLE IF EXISTS `t_token`;\nCREATE TABLE `t_token` (\n  `id` varchar(36) NOT NULL COMMENT 'token',\n  `val` text NOT NULL COMMENT 'LoginUser的json串',\n  `expireTime` datetime NOT NULL,\n  `createTime` datetime NOT NULL,\n  `updateTime` datetime NOT NULL,\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;\n\n#\n# Data for table \"t_token\"\n#\n\n\n#\n# Structure for table \"user_leave\"\n#\n\nDROP TABLE IF EXISTS `user_leave`;\nCREATE TABLE `user_leave` (\n  `id` varchar(32) NOT NULL,\n  `user_id` varchar(32) NOT NULL,\n  `user_name` varchar(18) DEFAULT NULL,\n  `begin_time` datetime DEFAULT NULL,\n  `end_time` datetime DEFAULT NULL,\n  `reason` varchar(255) DEFAULT NULL,\n  `days` int(11) DEFAULT NULL,\n  `process_instance_Id` varchar(32) DEFAULT NULL,\n  `status` varchar(64) DEFAULT NULL,\n  `create_date` datetime DEFAULT NULL,\n  `create_by` varchar(32) DEFAULT NULL,\n  `update_date` datetime DEFAULT NULL,\n  `update_by` varchar(32) DEFAULT NULL,\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\n#\n# Data for table \"user_leave\"\n#\n\n"
  },
  {
    "path": "open-layui-web/src/main/resources/generate/controller.ftl",
    "content": "package {controllerPkgName};\n\nimport java.util.List;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.DeleteMapping;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.PutMapping;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport com.boot.security.server.page.table.PageTableRequest;\nimport com.boot.security.server.page.table.PageTableHandler;\nimport com.boot.security.server.page.table.PageTableResponse;\nimport com.boot.security.server.page.table.PageTableHandler.CountHandler;\nimport com.boot.security.server.page.table.PageTableHandler.ListHandler;\nimport {daoPackageName}.{daoName};\nimport {beanPackageName}.{beanName};\n\nimport io.swagger.annotations.ApiOperation;\n\n@RestController\n@RequestMapping(\"/{beanParamName}s\")\npublic class {controllerName} {\n\n    @Autowired\n    private {daoName} {daoParamName};\n\n    @PostMapping\n    @ApiOperation(value = \"保存\")\n    public {beanName} save(@RequestBody {beanName} {beanParamName}) {\n        {daoParamName}.save({beanParamName});\n\n        return {beanParamName};\n    }\n\n    @GetMapping(\"/{id}\")\n    @ApiOperation(value = \"根据id获取\")\n    public {beanName} get(@PathVariable Long id) {\n        return {daoParamName}.getById(id);\n    }\n\n    @PutMapping\n    @ApiOperation(value = \"修改\")\n    public {beanName} update(@RequestBody {beanName} {beanParamName}) {\n        {daoParamName}.update({beanParamName});\n\n        return {beanParamName};\n    }\n\n    @GetMapping\n    @ApiOperation(value = \"列表\")\n    public PageTableResponse list(PageTableRequest request) {\n        return new PageTableHandler(new CountHandler() {\n\n            @Override\n            public int count(PageTableRequest request) {\n                return {daoParamName}.count(request.getParams());\n            }\n        }, new ListHandler() {\n\n            @Override\n            public List<{beanName}> list(PageTableRequest request) {\n                return {daoParamName}.list(request.getParams(), request.getOffset(), request.getLimit());\n            }\n        }).handle(request);\n    }\n\n    @DeleteMapping(\"/{id}\")\n    @ApiOperation(value = \"删除\")\n    public void delete(@PathVariable Long id) {\n        {daoParamName}.delete(id);\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/resources/generate/dao.ftl",
    "content": "package {daoPackageName};\n\nimport java.util.List;\nimport java.util.Map;\n\nimport org.apache.ibatis.annotations.Delete;\nimport org.apache.ibatis.annotations.Insert;\nimport org.apache.ibatis.annotations.Mapper;\nimport org.apache.ibatis.annotations.Options;\nimport org.apache.ibatis.annotations.Param;\nimport org.apache.ibatis.annotations.Select;\n\nimport {beanPackageName}.{beanName};\n\n@Mapper\npublic interface {daoName} {\n\n    @Select(\"select * from {table_name} t where t.id = #{id}\")\n    {beanName} getById(Long id);\n\n    @Delete(\"delete from {table_name} where id = #{id}\")\n    int delete(Long id);\n\n    int update({beanName} {beanParamName});\n    \n    @Options(useGeneratedKeys = true, keyProperty = \"id\")\n    @Insert(\"insert into {table_name}({insert_columns}) values({insert_values})\")\n    int save({beanName} {beanParamName});\n    \n    int count(@Param(\"params\") Map<String, Object> params);\n\n    List<{beanName}> list(@Param(\"params\") Map<String, Object> params, @Param(\"offset\") Integer offset, @Param(\"limit\") Integer limit);\n}\n"
  },
  {
    "path": "open-layui-web/src/main/resources/generate/htmlAdd.ftl",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/bootstrap.min.css\">\n</head>\n<body>\n<div class=\"col-xs-12 col-sm-12 col-md-12 col-lg-12\">\n\t<form class=\"form-horizontal\" onsubmit=\"return false\" id=\"form\">\n\t\t<fieldset>\n{addDivs}\n\n\t\t\t<div class=\"form-actions\">\n\t\t\t\t<div class=\"row\" align=\"center\">\n\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t    <button class=\"btn btn-primary\" onclick=\"location.href='{beanParamName}List.html'\">返回</button>\n\t\t\t\t\t\t<button class=\"btn btn-primary\" type=\"submit\" onclick=\"add()\">\n\t\t\t\t\t\t\t<i class=\"fa fa-save\"></i> 保存\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t</fieldset>\n\t</form>\n</div>\n\t<script type=\"text/javascript\" src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/plugin/bootstrapvalidator/bootstrapValidator.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/common.js\"></script>\n\t<script type=\"text/javascript\" src=\"/lib/layui/layui.js\"></script>\n\t<script type=\"text/javascript\">\n\t\tlayui.use(['layer','laydate'], function(){\n\t\t    var layer = layui.layer;\n\t\t});\n\t\t\n\t\tfunction add() {\n\t\t\t$('#form').bootstrapValidator();\n\t\t\tvar bootstrapValidator = $(\"#form\").data('bootstrapValidator');\n\t\t\tbootstrapValidator.validate();\n\t\t    if(!bootstrapValidator.isValid()){\n\t\t\t   return;\n\t\t    }\n\t\t    \n\t\t    var formdata = $(\"#form\").serializeObject();\n\n\t\t\t$.ajax({\n\t\t\t\ttype : 'post',\n\t\t\t\turl : '/{beanParamName}s',\n\t\t\t\tcontentType: \"application/json; charset=utf-8\",  \n\t\t\t\tdata : JSON.stringify(formdata),\n\t\t\t\tsuccess : function(data) {\n\t\t\t\t\tlayer.msg(\"添加成功\", {shift: -1, time: 1000}, function(){\n                        location.href = \"{beanParamName}List.html\";\n                    });\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\t\n\t</script>\n</body>\n</html>"
  },
  {
    "path": "open-layui-web/src/main/resources/generate/htmlList.ftl",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<title>Insert title here</title>\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/bootstrap.min.css\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/dataTables.bootstrap.min.css\">\n<link rel=\"stylesheet\" href=\"/lib/layui/css/layui.css\" media=\"all\" />\n</head>\n<body>\n    <div>\n        <div class=\"col-xs-12 col-sm-12 col-md-12 col-lg-12\">\n            <div>\n                <header style=\"height: 100%\">\n                    <div align=\"left\">\n\t                    <table style=\"width: 100%\">\n\t                   \t\t<tr>\n\t                   \t\t\t<td>\n\t\t                   \t\t\t<form class=\"form-inline\" onsubmit=\"return false\">\n\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\tid：\n\t\t\t\t\t\t\t\t\t\t\t<input id=\"id\" type=\"text\" class=\"form-control\" placeholder=\"id\">\n\t\t\t\t\t\t\t\t\t\t\t<button id=\"searchBt\" class=\"layui-btn layui-btn-sm\"><i class=\"layui-icon\">&#xe615;</i>搜索</button>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</form>\n\t                   \t\t\t</td>\n\t                   \t\t\t<td align=\"right\">\n\t                   \t\t\t\t<button class=\"layui-btn layui-btn-sm\" onclick=\"location.href='add{beanName}.html'\">\n                                      <i class=\"layui-icon\">&#xe608;</i> 添加\n                                    </button>\n\t                   \t\t\t</td>\n\t                   \t\t</tr> \n\t                    </table>\n\t\t\t\t\t</div>\n                </header>\n                \n                <div>\n                    <div class=\"widget-body no-padding\">\n                        <table id=\"dt-table\" class=\"table table-striped table-bordered table-hover\" style=\"width:100%\">\n                            <thead>\n                                <tr>\n                                </tr>                       \n                                <tr>\n{ths}\t\t\t\t\t\t\t\t\t<th>操作</th>\n                                </tr>\n                            </thead>\n                            <tbody>\n                            </tbody>\n                        </table>\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>\n</body>\n</html>\n\n<script type=\"text/javascript\" src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n<script type=\"text/javascript\" src=\"/js/plugin/datatables/jquery.dataTables.min.js\"></script>\n<script type=\"text/javascript\" src=\"/js/plugin/datatables/dataTables.bootstrap.min.js\"></script>\n<script type=\"text/javascript\" src=\"/lib/layui/layui.js\"></script>\n<script type=\"text/javascript\" src=\"/js/my/permission.js\"></script>\n<script type=\"text/javascript\">\nvar pers = checkPermission();\n\nvar example;\nfunction init(){\n\texample = \n    \t$('#dt-table').DataTable({\n        \t\"searching\": false,\n        \t\"processing\": false,\n        \t\"serverSide\" : true,\n        \t\"ajax\": {\n        \t\t\"url\" : \"/{beanParamName}s\",\n        \t\t\"type\":\"get\",\n        \t\t\"data\":function(d){\n    \t\t\t\td.id = $(\"#id\").val();\n    \t\t\t}\n        \t},\n        \t\"dom\": \"<'dt-toolbar'r>t<'dt-toolbar-footer'<'col-sm-10 col-xs-12 hidden-xs'i><'col-xs-12 col-sm-10' p v>>\",\t\n            \"columns\": [\n{columnsDatas}\t\t\t\t{ \n\t\t\t\t\t\t\t\t\"data\": \"\", \n\t\t\t\t\t\t\t\t\"defaultContent\": \"\",\n\t\t\t\t\t\t\t\t\"orderable\":false,\n\t\t\t\t\t\t        \"render\": function (data, type, row) {\n                \t\t           var id = row['id'];\n                \t\t           var href = \"update{beanName}.html?id=\" + id;\n                                   var edit = buttonEdit(href, \"\", pers);\n                \t\t           var del = buttonDel(id, \"\", pers);\n                                   return edit + del;\n                  \t            }\t\t\n\t\t\t\t\t\t\t},\n                \n            ],\n           \"order\": [[ 0, \"asc\" ]]\n        } );\n}\n\nlayui.use('layer', function(){\n    var layer = layui.layer;\n});\n\nfunction del(id){\n\tlayer.confirm('确定要删除吗？', {\n        btn : [ '确定', '取消' ]\n    }, function() {\n    \t$.ajax({\n            type : 'delete',\n            url : '/{beanParamName}s/'+id,\n            success : function(data) {\n                example.ajax.reload();\n                layer.msg(\"删除成功\");\n            }\n        });\n        \n        layer.close(1);\n    });\n}\n\n$(\"#searchBt\").click(function(){\n\texample.ajax.reload();\n});\n\ninit();\n</script>"
  },
  {
    "path": "open-layui-web/src/main/resources/generate/htmlUpdate.ftl",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/bootstrap.min.css\">\n</head>\n<body>\n<div class=\"col-xs-12 col-sm-12 col-md-12 col-lg-12\">\n\t<form class=\"form-horizontal\" onsubmit=\"return false\" id=\"form\">\n\t\t<fieldset>\n\t\t\t<input type=\"hidden\" id=\"id\" name=\"id\">\n{addDivs}\n\n\n\t\t\t<div class=\"form-actions\">\n\t\t\t\t<div class=\"row\" align=\"center\">\n\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t    <button class=\"btn btn-primary\" onclick=\"location.href='{beanParamName}List.html'\">返回</button>\n\t\t\t\t\t\t<button class=\"btn btn-primary\" type=\"submit\" onclick=\"update()\">\n\t\t\t\t\t\t\t<i class=\"fa fa-save\"></i> 保存\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t</fieldset>\n\t</form>\n</div>\n\t<script type=\"text/javascript\" src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/plugin/bootstrapvalidator/bootstrapValidator.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/common.js\"></script>\n\t<script type=\"text/javascript\" src=\"/lib/layui/layui.js\"></script>\n\t<script type=\"text/javascript\">\n\t\tlayui.use(['layer','laydate'], function(){\n\t\t    var layer = layui.layer;\n\t\t});\n\t\t\n\t\tinitData();\n\t\t\n\t\tfunction initData(){\n\t\t\tvar id = getUrlParam(\"id\");\n\t\t\tif(id != \"\"){\n\t\t\t\t$.ajax({\n\t\t\t\t\ttype : 'get',\n\t\t\t\t\turl : '/{beanParamName}s/'+id,\n\t\t\t\t\tasync : false,\n\t\t\t\t\tsuccess : function(data) {\n{initData}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tfunction update() {\n\t\t\t$('#form').bootstrapValidator();\n\t\t\tvar bootstrapValidator = $(\"#form\").data('bootstrapValidator');\n\t\t\tbootstrapValidator.validate();\n\t\t    if(!bootstrapValidator.isValid()){\n\t\t\t   return;\n\t\t    }\n\t\t    \n\t\t    var formdata = $(\"#form\").serializeObject();\n\n\t\t\t$.ajax({\n\t\t\t\ttype : 'put',\n\t\t\t\turl : '/{beanParamName}s',\n\t\t\t\tcontentType: \"application/json; charset=utf-8\",  \n\t\t\t\tdata : JSON.stringify(formdata),\n\t\t\t\tsuccess : function(data) {\n\t\t\t\t\tlayer.msg(\"修改成功\", {shift: -1, time: 1000}, function(){\n                        location.href = \"{beanParamName}List.html\";\n                    });\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\t\n\t</script>\n</body>\n</html>"
  },
  {
    "path": "open-layui-web/src/main/resources/generate/java.ftl",
    "content": "package {beanPackageName};\n\n{import}\n\npublic class {beanName} extends BaseEntity<Long> {\n\n{filelds}\n{getset}\n}"
  },
  {
    "path": "open-layui-web/src/main/resources/generate/mapper.ftl",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"{daoPackageName}.{daoName}\">\n\n\t<sql id=\"where\">\n\t\t<where>\n{where}\t\t\n\t\t</where>\n\t</sql>\n\n\t<select id=\"count\" resultType=\"int\">\n\t\tselect count(1) from {table_name} t\n\t\t<include refid=\"where\" />\n\t</select>\n\n\t<select id=\"list\" resultType=\"{beanName}\">\n\t\tselect * from {table_name} t\n\t\t<include refid=\"where\" />\n\t\t${params.orderBy}\n\t\tlimit #{offset}, #{limit}\n\t</select>\n\n\t<update id=\"update\">\n\t\tupdate {table_name} t\n\t\t<set>\n{update_sets}\n\t\t</set>\n\n\t\twhere t.id = #{id}\n\t</update>\n\n</mapper>"
  },
  {
    "path": "open-layui-web/src/main/resources/logback-admin.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<configuration scan=\"true\" scanPeriod=\"30 seconds\">\n    <appender name=\"STDOUT\" class=\"ch.qos.logback.core.ConsoleAppender\">\n        <encoder>\n            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>\n        </encoder>\n    </appender>\n    <appender name=\"ERROR\" class=\"ch.qos.logback.core.rolling.RollingFileAppender\">\n        <rollingPolicy class=\"ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy\">\n            <fileNamePattern>../logs/open-layui-web-error.%d{yyyy-MM-dd}.%i.log</fileNamePattern>\n            <maxFileSize>100MB</maxFileSize>\n            <maxHistory>60</maxHistory>\n        </rollingPolicy>\n        <encoder>\n            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>\n        </encoder>\n        <triggeringPolicy class=\"ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy\">\n            <MaxFileSize>100MB</MaxFileSize>\n        </triggeringPolicy>\n        <filter class=\"ch.qos.logback.classic.filter.LevelFilter\"><!-- 鍙墦鍗伴敊璇棩蹇?-->\n            <level>ERROR</level>\n            <onMatch>ACCEPT</onMatch>\n            <onMismatch>DENY</onMismatch>\n        </filter>\n    </appender>\n    <appender name=\"INFO\" class=\"ch.qos.logback.core.rolling.RollingFileAppender\">\n        <rollingPolicy class=\"ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy\">\n            <fileNamePattern>../logs/open-layui-web-info.%d{yyyy-MM-dd}.%i.log</fileNamePattern>\n            <maxFileSize>100MB</maxFileSize>\n            <maxHistory>60</maxHistory>\n        </rollingPolicy>\n        <encoder>\n            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>\n        </encoder>\n        <filter class=\"ch.qos.logback.classic.filter.LevelFilter\">\n            <level>INFO</level>\n            <onMatch>ACCEPT</onMatch>\n            <onMismatch>DENY</onMismatch>\n        </filter>\n    </appender>\n\n    <root level=\"info\">\n        <appender-ref ref=\"STDOUT\"/>\n        <appender-ref ref=\"ERROR\"/>\n        <appender-ref ref=\"INFO\"/>\n    </root>\n</configuration>\n"
  },
  {
    "path": "open-layui-web/src/main/resources/mybatis.cfg.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE configuration   \n    PUBLIC \"-//mybatis.org//DTD Config 3.0//EN\"   \n    \"http://mybatis.org/dtd/mybatis-3-config.dtd\">\n<configuration>\n\t<!-- 进行Mybatis的相应的环境的属性定义 -->\n\t<settings>\t<!-- 在本项目之中开启二级缓存 -->\n\t\t<setting name=\"cacheEnabled\" value=\"false\"/>\n\t\t<!-- 使用驼峰命名法转换字段。 -->\n\t\t<setting name=\"mapUnderscoreToCamelCase\" value=\"true\"/>\n\t</settings>\n</configuration>\n"
  },
  {
    "path": "open-layui-web/src/main/resources/stencilset.json",
    "content": "{\n    \"title\" : \"BPMN 2.0标准工具\",\n    \"namespace\" : \"http://b3mn.org/stencilset/bpmn2.0#\",\n    \"description\" : \"BPMN process editor\",\n    \"propertyPackages\" : [ {\n        \"name\" : \"process_idpackage\",\n        \"properties\" : [ {\n            \"id\" : \"process_id\",\n            \"type\" : \"String\",\n            \"title\" : \"流程名称\",\n            \"value\" : \"process\",\n            \"description\" : \"流程的特殊唯一的名称标识\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"overrideidpackage\",\n        \"properties\" : [ {\n            \"id\" : \"overrideid\",\n            \"type\" : \"String\",\n            \"title\" : \"Id\",\n            \"value\" : \"\",\n            \"description\" : \"Unique identifier of the element.\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"namepackage\",\n        \"properties\" : [ {\n            \"id\" : \"name\",\n            \"type\" : \"String\",\n            \"title\" : \"名称\",\n            \"value\" : \"\",\n            \"description\" : \"元素名称\",\n            \"popular\" : true,\n            \"refToView\" : \"text_name\"\n        } ]\n    }, {\n        \"name\" : \"documentationpackage\",\n        \"properties\" : [ {\n            \"id\" : \"documentation\",\n            \"type\" : \"Text\",\n            \"title\" : \"描述\",\n            \"value\" : \"\",\n            \"description\" : \"元素描述\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"process_authorpackage\",\n        \"properties\" : [ {\n            \"id\" : \"process_author\",\n            \"type\" : \"String\",\n            \"title\" : \"流程作者\",\n            \"value\" : \"\",\n            \"description\" : \"流程定义者姓名\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"process_versionpackage\",\n        \"properties\" : [ {\n            \"id\" : \"process_version\",\n            \"type\" : \"String\",\n            \"title\" : \"流程版本\",\n            \"value\" : \"\",\n            \"description\" : \"标识文档版本\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"process_namespacepackage\",\n        \"properties\" : [ {\n            \"id\" : \"process_namespace\",\n            \"type\" : \"String\",\n            \"title\" : \"目标命名空间\",\n            \"value\" : \"http://www.activiti.org/processdef\",\n            \"description\" : \"工作流目标命名空间\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"asynchronousdefinitionpackage\",\n        \"properties\" : [ {\n            \"id\" : \"asynchronousdefinition\",\n            \"type\" : \"Boolean\",\n            \"title\" : \"异步\",\n            \"value\" : \"false\",\n            \"description\" : \"Define the activity as asynchronous.\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"exclusivedefinitionpackage\",\n        \"properties\" : [ {\n            \"id\" : \"exclusivedefinition\",\n            \"type\" : \"Boolean\",\n            \"title\" : \"单独\",\n            \"value\" : \"false\",\n            \"description\" : \"Define the activity as exclusive.\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"executionlistenerspackage\",\n        \"properties\" : [ {\n            \"id\" : \"executionlisteners\",\n            \"type\" : \"multiplecomplex\",\n            \"title\" : \"执行监听器\",\n            \"value\" : \"\",\n            \"description\" : \"Listeners for an activity, process, sequence flow, start and end event.\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"tasklistenerspackage\",\n        \"properties\" : [ {\n            \"id\" : \"tasklisteners\",\n            \"type\" : \"multiplecomplex\",\n            \"title\" : \"任务监听器\",\n            \"value\" : \"\",\n            \"description\" : \"Listeners for a user task\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"eventlistenerspackage\",\n        \"properties\" : [ {\n            \"id\" : \"eventlisteners\",\n            \"type\" : \"multiplecomplex\",\n            \"title\" : \"事件监听器\",\n            \"value\" : \"\",\n            \"description\" : \"Listeners for any event happening in the Activiti Engine. It's also possible to rethrow the event as a signal, message or error event\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"usertaskassignmentpackage\",\n        \"properties\" : [ {\n            \"id\" : \"usertaskassignment\",\n            \"type\" : \"Complex\",\n            \"title\" : \"代理\",\n            \"value\" : \"\",\n            \"description\" : \"Assignment definition for the user task\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"formpropertiespackage\",\n        \"properties\" : [ {\n            \"id\" : \"formproperties\",\n            \"type\" : \"Complex\",\n            \"title\" : \"动态表单属性\",\n            \"value\" : \"\",\n            \"description\" : \"Definition of the form with a list of form properties\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"formkeydefinitionpackage\",\n        \"properties\" : [ {\n            \"id\" : \"formkeydefinition\",\n            \"type\" : \"String\",\n            \"title\" : \"自定义表单\",\n            \"value\" : \"\",\n            \"description\" : \"用户任务表单编号\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"duedatedefinitionpackage\",\n        \"properties\" : [ {\n            \"id\" : \"duedatedefinition\",\n            \"type\" : \"String\",\n            \"title\" : \"到期日期\",\n            \"value\" : \"\",\n            \"description\" : \"用户任务到期时间\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"prioritydefinitionpackage\",\n        \"properties\" : [ {\n            \"id\" : \"prioritydefinition\",\n            \"type\" : \"String\",\n            \"title\" : \"优先级\",\n            \"value\" : \"\",\n            \"description\" : \"用户任务优先级\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"duedatedefinitionpackage\",\n        \"properties\" : [ {\n            \"id\" : \"duedatedefinition\",\n            \"type\" : \"String\",\n            \"title\" : \"到期日期\",\n            \"value\" : \"\",\n            \"description\" : \"Due date of the user task.\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"servicetaskclasspackage\",\n        \"properties\" : [ {\n            \"id\" : \"servicetaskclass\",\n            \"type\" : \"String\",\n            \"title\" : \"监听类\",\n            \"value\" : \"\",\n            \"description\" : \"Class that implements the service task logic.\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"servicetaskexpressionpackage\",\n        \"properties\" : [ {\n            \"id\" : \"servicetaskexpression\",\n            \"type\" : \"String\",\n            \"title\" : \"表达式\",\n            \"value\" : \"\",\n            \"description\" : \"Service task logic defined with an expression.\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"servicetaskdelegateexpressionpackage\",\n        \"properties\" : [ {\n            \"id\" : \"servicetaskdelegateexpression\",\n            \"type\" : \"String\",\n            \"title\" : \"委托表达式\",\n            \"value\" : \"\",\n            \"description\" : \"Service task logic defined with a delegate expression.\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"servicetaskfieldspackage\",\n        \"properties\" : [ {\n            \"id\" : \"servicetaskfields\",\n            \"type\" : \"Complex\",\n            \"title\" : \"字段\",\n            \"value\" : \"\",\n            \"description\" : \"Field extensions\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"servicetaskresultvariablepackage\",\n        \"properties\" : [ {\n            \"id\" : \"servicetaskresultvariable\",\n            \"type\" : \"String\",\n            \"title\" : \"Result variable name\",\n            \"value\" : \"\",\n            \"description\" : \"Process variable name to store the service task result.\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"scriptformatpackage\",\n        \"properties\" : [ {\n            \"id\" : \"scriptformat\",\n            \"type\" : \"String\",\n            \"title\" : \"脚本格式\",\n            \"value\" : \"\",\n            \"description\" : \"Script format of the script task.\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"scripttextpackage\",\n        \"properties\" : [ {\n            \"id\" : \"scripttext\",\n            \"type\" : \"Text\",\n            \"title\" : \"脚本\",\n            \"value\" : \"\",\n            \"description\" : \"Script text of the script task.\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"ruletask_rulespackage\",\n        \"properties\" : [ {\n            \"id\" : \"ruletask_rules\",\n            \"type\" : \"String\",\n            \"title\" : \"规则\",\n            \"value\" : \"\",\n            \"description\" : \"Rules of the rule task.\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"ruletask_variables_inputpackage\",\n        \"properties\" : [ {\n            \"id\" : \"ruletask_variables_input\",\n            \"type\" : \"String\",\n            \"title\" : \"输入变量\",\n            \"value\" : \"\",\n            \"description\" : \"Input variables of the rule task.\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"ruletask_excludepackage\",\n        \"properties\" : [ {\n            \"id\" : \"ruletask_exclude\",\n            \"type\" : \"Boolean\",\n            \"title\" : \"除外\",\n            \"value\" : \"false\",\n            \"description\" : \"Use the rules property as exclusion.\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"ruletask_resultpackage\",\n        \"properties\" : [ {\n            \"id\" : \"ruletask_result\",\n            \"type\" : \"String\",\n            \"title\" : \"返回变量\",\n            \"value\" : \"\",\n            \"description\" : \"Result variable of the rule task.\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"mailtasktopackage\",\n        \"properties\" : [ {\n            \"id\" : \"mailtaskto\",\n            \"type\" : \"Text\",\n            \"title\" : \"接收人\",\n            \"value\" : \"\",\n            \"description\" : \"The recipients if the e-mail. Multiple recipients are defined in a comma-separated list.\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"mailtaskfrompackage\",\n        \"properties\" : [ {\n            \"id\" : \"mailtaskfrom\",\n            \"type\" : \"Text\",\n            \"title\" : \"发件人\",\n            \"value\" : \"\",\n            \"description\" : \"The sender e-mail address. If not provided, the default configured from address is used.\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"mailtasksubjectpackage\",\n        \"properties\" : [ {\n            \"id\" : \"mailtasksubject\",\n            \"type\" : \"Text\",\n            \"title\" : \"主题\",\n            \"value\" : \"\",\n            \"description\" : \"The subject of the e-mail.\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"mailtaskccpackage\",\n        \"properties\" : [ {\n            \"id\" : \"mailtaskcc\",\n            \"type\" : \"Text\",\n            \"title\" : \"转发\",\n            \"value\" : \"\",\n            \"description\" : \"The cc's of the e-mail. Multiple recipients are defined in a comma-separated list\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"mailtaskbccpackage\",\n        \"properties\" : [ {\n            \"id\" : \"mailtaskbcc\",\n            \"type\" : \"Text\",\n            \"title\" : \"密送\",\n            \"value\" : \"\",\n            \"description\" : \"The bcc's of the e-mail. Multiple recipients are defined in a comma-separated list\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"mailtasktextpackage\",\n        \"properties\" : [ {\n            \"id\" : \"mailtasktext\",\n            \"type\" : \"Text\",\n            \"title\" : \"内容\",\n            \"value\" : \"\",\n            \"description\" : \"The content of the e-mail, in case one needs to send plain none-rich e-mails. Can be used in combination with html, for e-mail clients that don't support rich content. The client will then fall back to this text-only alternative.\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"mailtaskhtmlpackage\",\n        \"properties\" : [ {\n            \"id\" : \"mailtaskhtml\",\n            \"type\" : \"Text\",\n            \"title\" : \"Html\",\n            \"value\" : \"\",\n            \"description\" : \"A piece of HTML that is the content of the e-mail.\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"mailtaskcharsetpackage\",\n        \"properties\" : [ {\n            \"id\" : \"mailtaskcharset\",\n            \"type\" : \"String\",\n            \"title\" : \"Charset\",\n            \"value\" : \"\",\n            \"description\" : \"Allows to change the charset of the email, which is necessary for many non-English languages. \",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"callactivitycalledelementpackage\",\n        \"properties\" : [ {\n            \"id\" : \"callactivitycalledelement\",\n            \"type\" : \"String\",\n            \"title\" : \"被调用元素\",\n            \"value\" : \"\",\n            \"description\" : \"Process reference.\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"callactivityinparameterspackage\",\n        \"properties\" : [ {\n            \"id\" : \"callactivityinparameters\",\n            \"type\" : \"Complex\",\n            \"title\" : \"输入参数\",\n            \"value\" : \"\",\n            \"description\" : \"Definition of the input parameters\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"callactivityoutparameterspackage\",\n        \"properties\" : [ {\n            \"id\" : \"callactivityoutparameters\",\n            \"type\" : \"Complex\",\n            \"title\" : \"输出参数\",\n            \"value\" : \"\",\n            \"description\" : \"Definition of the output parameters\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"cameltaskcamelcontextpackage\",\n        \"properties\" : [ {\n            \"id\" : \"cameltaskcamelcontext\",\n            \"type\" : \"String\",\n            \"title\" : \"Camel内容\",\n            \"value\" : \"\",\n            \"description\" : \"An optional camel context definition, if left empty the default is used.\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"muletaskendpointurlpackage\",\n        \"properties\" : [ {\n            \"id\" : \"muletaskendpointurl\",\n            \"type\" : \"String\",\n            \"title\" : \"终端url\",\n            \"value\" : \"\",\n            \"description\" : \"A required endpoint url to sent the message to Mule.\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"muletasklanguagepackage\",\n        \"properties\" : [ {\n            \"id\" : \"muletasklanguage\",\n            \"type\" : \"String\",\n            \"title\" : \"语言\",\n            \"value\" : \"\",\n            \"description\" : \"A required definition for the language to resolve the payload expression, like juel.\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"muletaskpayloadexpressionpackage\",\n        \"properties\" : [ {\n            \"id\" : \"muletaskpayloadexpression\",\n            \"type\" : \"String\",\n            \"title\" : \"有效载荷表达式\",\n            \"value\" : \"\",\n            \"description\" : \"A required definition for the payload of the message sent to Mule.\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"muletaskresultvariablepackage\",\n        \"properties\" : [ {\n            \"id\" : \"muletaskresultvariable\",\n            \"type\" : \"String\",\n            \"title\" : \"返回变量\",\n            \"value\" : \"\",\n            \"description\" : \"An optional result variable for the payload returned.\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"conditionsequenceflowpackage\",\n        \"properties\" : [ {\n            \"id\" : \"conditionsequenceflow\",\n            \"type\" : \"Complex\",\n            \"title\" : \"流转条件\",\n            \"value\" : \"\",\n            \"description\" : \"The condition of the sequence flow\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"defaultflowpackage\",\n        \"properties\" : [ {\n            \"id\" : \"defaultflow\",\n            \"type\" : \"Boolean\",\n            \"title\" : \"默认流转\",\n            \"value\" : \"false\",\n            \"description\" : \"Define the sequence flow as default\",\n            \"popular\" : true,\n            \"refToView\" : \"default\"\n        } ]\n    }, {\n        \"name\" : \"conditionalflowpackage\",\n        \"properties\" : [ {\n            \"id\" : \"conditionalflow\",\n            \"type\" : \"Boolean\",\n            \"title\" : \"Conditional flow\",\n            \"value\" : \"false\",\n            \"description\" : \"Define the sequence flow with a condition\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"timercycledefinitionpackage\",\n        \"properties\" : [ {\n            \"id\" : \"timercycledefinition\",\n            \"type\" : \"String\",\n            \"title\" : \"循环时间(例：R3/PT10H)\",\n            \"value\" : \"\",\n            \"description\" : \"Define the timer with a ISO-8601 cycle.\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"timerdatedefinitionpackage\",\n        \"properties\" : [ {\n            \"id\" : \"timerdatedefinition\",\n            \"type\" : \"String\",\n            \"title\" : \"开始时间（ISO-8601）\",\n            \"value\" : \"\",\n            \"description\" : \"Define the timer with a ISO-8601 date definition.\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"timerdurationdefinitionpackage\",\n        \"properties\" : [ {\n            \"id\" : \"timerdurationdefinition\",\n            \"type\" : \"String\",\n            \"title\" : \"持续时间(例：PT5M)\",\n            \"value\" : \"\",\n            \"description\" : \"Define the timer with a ISO-8601 duration.\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"timerenddatedefinitionpackage\",\n        \"properties\" : [ {\n            \"id\" : \"timerenddatedefinition\",\n            \"type\" : \"String\",\n            \"title\" : \"结束时间（ISO-8601）\",\n            \"value\" : \"\",\n            \"description\" : \"Define the timer with a ISO-8601 duration.\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"messagerefpackage\",\n        \"properties\" : [ {\n            \"id\" : \"messageref\",\n            \"type\" : \"String\",\n            \"title\" : \"消息引用\",\n            \"value\" : \"\",\n            \"description\" : \"Define the message name.\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"signalrefpackage\",\n        \"properties\" : [ {\n            \"id\" : \"signalref\",\n            \"type\" : \"String\",\n            \"title\" : \"信号引用\",\n            \"value\" : \"\",\n            \"description\" : \"Define the signal name.\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"errorrefpackage\",\n        \"properties\" : [ {\n            \"id\" : \"errorref\",\n            \"type\" : \"String\",\n            \"title\" : \"错误引用\",\n            \"value\" : \"\",\n            \"description\" : \"Define the error name.\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"cancelactivitypackage\",\n        \"properties\" : [ {\n            \"id\" : \"cancelactivity\",\n            \"type\" : \"Boolean\",\n            \"title\" : \"取消活动\",\n            \"value\" : \"true\",\n            \"description\" : \"Should the activity be cancelled\",\n            \"popular\" : true,\n            \"refToView\" : [ \"frame\", \"frame2\" ]\n        } ]\n    }, {\n        \"name\" : \"initiatorpackage\",\n        \"properties\" : [ {\n            \"id\" : \"initiator\",\n            \"type\" : \"String\",\n            \"title\" : \"发起人\",\n            \"value\" : \"\",\n            \"description\" : \"Initiator of the process.\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"textpackage\",\n        \"properties\" : [ {\n            \"id\" : \"text\",\n            \"type\" : \"String\",\n            \"title\" : \"Text\",\n            \"value\" : \"\",\n            \"description\" : \"The text of the text annotation.\",\n            \"popular\" : true,\n            \"refToView\" : \"text\"\n        } ]\n    }, {\n        \"name\" : \"multiinstance_typepackage\",\n        \"properties\" : [ {\n            \"id\" : \"multiinstance_type\",\n            \"type\" : \"kisbpm-multiinstance\",\n            \"title\" : \"多实例类型\",\n            \"value\" : \"None\",\n            \"description\" : \"Repeated activity execution (parallel or sequential) can be displayed through different loop types\",\n            \"popular\" : true,\n            \"refToView\" : \"multiinstance\"\n        } ]\n    }, {\n        \"name\" : \"multiinstance_cardinalitypackage\",\n        \"properties\" : [ {\n            \"id\" : \"multiinstance_cardinality\",\n            \"type\" : \"String\",\n            \"title\" : \"基数(多实例)\",\n            \"value\" : \"\",\n            \"description\" : \"Define the cardinality of multi instance.\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"multiinstance_collectionpackage\",\n        \"properties\" : [ {\n            \"id\" : \"multiinstance_collection\",\n            \"type\" : \"String\",\n            \"title\" : \"集合(多实例)\",\n            \"value\" : \"\",\n            \"description\" : \"Define the collection for the multi instance.\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"multiinstance_variablepackage\",\n        \"properties\" : [ {\n            \"id\" : \"multiinstance_variable\",\n            \"type\" : \"String\",\n            \"title\" : \"元素变量(多实例)\",\n            \"value\" : \"\",\n            \"description\" : \"Define the element variable for the multi instance.\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"multiinstance_conditionpackage\",\n        \"properties\" : [ {\n            \"id\" : \"multiinstance_condition\",\n            \"type\" : \"String\",\n            \"title\" : \"完成条件(多实例)\",\n            \"value\" : \"\",\n            \"description\" : \"Define the completion condition for the multi instance.\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"isforcompensationpackage\",\n        \"properties\" : [ {\n            \"id\" : \"isforcompensation\",\n            \"type\" : \"Boolean\",\n            \"title\" : \"是否为补偿\",\n            \"value\" : \"false\",\n            \"description\" : \"一个标志,标识是否这个活动的目的是为了补偿.\",\n            \"popular\" : true,\n            \"refToView\" : \"compensation\"\n        } ]\n    }, {\n        \"name\" : \"sequencefloworderpackage\",\n        \"properties\" : [ {\n            \"id\" : \"sequencefloworder\",\n            \"type\" : \"Complex\",\n            \"title\" : \"流动顺序\",\n            \"value\" : \"\",\n            \"description\" : \"Order outgoing sequence flows.\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"signaldefinitionspackage\",\n        \"properties\" : [ {\n            \"id\" : \"signaldefinitions\",\n            \"type\" : \"multiplecomplex\",\n            \"title\" : \"信号定义\",\n            \"value\" : \"\",\n            \"description\" : \"Signal definitions\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"messagedefinitionspackage\",\n        \"properties\" : [ {\n            \"id\" : \"messagedefinitions\",\n            \"type\" : \"multiplecomplex\",\n            \"title\" : \"消息定义\",\n            \"value\" : \"\",\n            \"description\" : \"Message definitions\",\n            \"popular\" : true\n        } ]\n    }, {\n        \"name\" : \"istransactionpackage\",\n        \"properties\" : [ {\n            \"id\" : \"istransaction\",\n            \"type\" : \"Boolean\",\n            \"title\" : \"是否事务处理子过程\",\n            \"value\" : \"false\",\n            \"description\" : \"A flag that identifies whether this sub process is of type transaction.\",\n            \"popular\" : true,\n            \"refToView\" : \"border\"\n        } ]\n    }, {\n        \"name\" : \"terminateAllpackage\",\n        \"properties\" : [ {\n            \"id\" : \"terminateAll\",\n            \"type\" : \"Boolean\",\n            \"title\" : \"终止全部\",\n            \"value\" : \"false\",\n            \"description\" : \"Enable to terminate the process instance\",\n            \"popular\" : true\n        } ]\n    } ],\n    \"stencils\" : [ {\n        \"type\" : \"node\",\n        \"id\" : \"BPMNDiagram\",\n        \"title\" : \"BPMN-Diagram\",\n        \"description\" : \"A BPMN 2.0 diagram.\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n   xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:svg=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\n   xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\"\\n   width=\\\"800\\\"\\n   height=\\\"600\\\"\\n   version=\\\"1.0\\\">\\n  <defs></defs>\\n  <g pointer-events=\\\"fill\\\" >\\n    <polygon stroke=\\\"black\\\" fill=\\\"black\\\" stroke-width=\\\"1\\\" points=\\\"0,0 0,590 9,599 799,599 799,9 790,0\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-miterlimit=\\\"10\\\" />\\n    <rect id=\\\"diagramcanvas\\\" oryx:resize=\\\"vertical horizontal\\\" x=\\\"0\\\" y=\\\"0\\\" width=\\\"790\\\" height=\\\"590\\\" stroke=\\\"black\\\" stroke-width=\\\"2\\\" fill=\\\"white\\\" />\\n    \\t<text font-size=\\\"22\\\" id=\\\"diagramtext\\\" x=\\\"400\\\" y=\\\"25\\\" oryx:align=\\\"top center\\\" stroke=\\\"#373e48\\\"></text>\\n  </g>\\n</svg>\",\n        \"icon\" : \"diagram.png\",\n        \"groups\" : [ \"Diagram\" ],\n        \"mayBeRoot\" : true,\n        \"hide\" : true,\n        \"propertyPackages\" : [ \"process_idpackage\", \"namepackage\", \"documentationpackage\", \"process_authorpackage\", \"process_versionpackage\", \"process_namespacepackage\", \"executionlistenerspackage\", \"eventlistenerspackage\", \"signaldefinitionspackage\", \"messagedefinitionspackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ ]\n    }, {\n        \"type\" : \"node\",\n        \"id\" : \"StartNoneEvent\",\n        \"title\" : \"事件\",\n        \"description\" : \"A start event without a specific trigger\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n   xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\n   width=\\\"40\\\"\\n   height=\\\"40\\\"\\n   version=\\\"1.0\\\">\\n  <defs></defs>\\n  <oryx:magnets>\\n  \\t<oryx:magnet oryx:cx=\\\"16\\\" oryx:cy=\\\"16\\\" oryx:default=\\\"yes\\\" />\\n  </oryx:magnets>\\n  <g pointer-events=\\\"fill\\\">\\n    <circle id=\\\"bg_frame\\\" cx=\\\"16\\\" cy=\\\"16\\\" r=\\\"15\\\" stroke=\\\"#585858\\\" fill=\\\"#ffffff\\\" stroke-width=\\\"1\\\"/>\\n\\t<text font-size=\\\"11\\\" \\n\\t\\tid=\\\"text_name\\\" \\n\\t\\tx=\\\"16\\\" y=\\\"33\\\" \\n\\t\\toryx:align=\\\"top center\\\" \\n\\t\\tstroke=\\\"#373e48\\\"\\n\\t></text>\\n  </g>\\n</svg>\",\n        \"icon\" : \"startevent/none.png\",\n        \"groups\" : [ \"启动事件\" ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"executionlistenerspackage\", \"initiatorpackage\", \"formkeydefinitionpackage\", \"formpropertiespackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"sequence_start\", \"Startevents_all\", \"StartEventsMorph\", \"all\" ]\n    }, {\n        \"type\" : \"node\",\n        \"id\" : \"StartTimerEvent\",\n        \"title\" : \"定时事件\",\n        \"description\" : \"A start event with a timer trigger\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n   xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\n   width=\\\"40\\\"\\n   height=\\\"40\\\"\\n   version=\\\"1.0\\\">\\n  <defs></defs>\\n  <oryx:magnets>\\n  \\t<oryx:magnet oryx:cx=\\\"16\\\" oryx:cy=\\\"16\\\" oryx:default=\\\"yes\\\" />\\n  </oryx:magnets>\\n  <g pointer-events=\\\"fill\\\">\\n    <circle \\n    \\tid=\\\"bg_frame\\\" \\n    \\tcx=\\\"16\\\" \\n    \\tcy=\\\"16\\\" \\n    \\tr=\\\"15\\\" \\n    \\tstroke=\\\"#585858\\\" \\n    \\tfill=\\\"#ffffff\\\" \\n    \\tstroke-width=\\\"1\\\"\\n    \\tstyle=\\\"stroke-dasharray: 5.5, 3\\\" />\\n    <circle id=\\\"frame\\\" cx=\\\"16\\\" cy=\\\"16\\\" r=\\\"15\\\" stroke=\\\"#585858\\\" fill=\\\"none\\\" stroke-width=\\\"1\\\"/>\\n    \\n    <path id=\\\"path1\\\" transform=\\\"translate(6,6)\\\"\\n    \\td=\\\"M 10 0 C 4.4771525 0 0 4.4771525 0 10 C 0 15.522847 4.4771525 20 10 20 C 15.522847 20 20 15.522847 20 10 C 20 4.4771525 15.522847 1.1842379e-15 10 0 z M 9.09375 1.03125 C 9.2292164 1.0174926 9.362825 1.0389311 9.5 1.03125 L 9.5 3.5 L 10.5 3.5 L 10.5 1.03125 C 15.063526 1.2867831 18.713217 4.9364738 18.96875 9.5 L 16.5 9.5 L 16.5 10.5 L 18.96875 10.5 C 18.713217 15.063526 15.063526 18.713217 10.5 18.96875 L 10.5 16.5 L 9.5 16.5 L 9.5 18.96875 C 4.9364738 18.713217 1.2867831 15.063526 1.03125 10.5 L 3.5 10.5 L 3.5 9.5 L 1.03125 9.5 C 1.279102 5.0736488 4.7225326 1.4751713 9.09375 1.03125 z M 9.5 5 L 9.5 8.0625 C 8.6373007 8.2844627 8 9.0680195 8 10 C 8 11.104569 8.8954305 12 10 12 C 10.931981 12 11.715537 11.362699 11.9375 10.5 L 14 10.5 L 14 9.5 L 11.9375 9.5 C 11.756642 8.7970599 11.20294 8.2433585 10.5 8.0625 L 10.5 5 L 9.5 5 z \\\"  \\n    \\tfill=\\\"#585858\\\" stroke=\\\"none\\\" />\\n   \\n\\t<text font-size=\\\"11\\\" \\n\\t\\tid=\\\"text_name\\\" \\n\\t\\tx=\\\"16\\\" y=\\\"33\\\" \\n\\t\\toryx:align=\\\"top center\\\" \\n\\t\\tstroke=\\\"#373e48\\\"\\n\\t></text>\\n  </g>\\n</svg>\",\n        \"icon\" : \"startevent/timer.png\",\n        \"groups\" : [ \"启动事件\" ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"executionlistenerspackage\", \"timercycledefinitionpackage\", \"timerdatedefinitionpackage\", \"timerdurationdefinitionpackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"sequence_start\", \"Startevents_all\", \"StartEventsMorph\", \"all\" ]\n    }, {\n        \"type\" : \"node\",\n        \"id\" : \"StartSignalEvent\",\n        \"title\" : \"信号事件\",\n        \"description\" : \"A start event with a signal trigger\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n   xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\n   width=\\\"40\\\"\\n   height=\\\"40\\\"\\n   version=\\\"1.0\\\">\\n  <defs></defs>\\n  <oryx:magnets>\\n  \\t<oryx:magnet oryx:cx=\\\"16\\\" oryx:cy=\\\"16\\\" oryx:default=\\\"yes\\\" />\\n  </oryx:magnets>\\n  <g pointer-events=\\\"fill\\\">\\n\\n    <circle \\n    \\tid=\\\"bg_frame\\\" \\n    \\tcx=\\\"16\\\" \\n    \\tcy=\\\"16\\\" \\n    \\tr=\\\"15\\\" \\n    \\tstroke=\\\"#585858\\\" \\n    \\tfill=\\\"#ffffff\\\" \\n    \\tstroke-width=\\\"1\\\"\\n    \\tstyle=\\\"stroke-dasharray: 5.5, 3\\\" />\\n    <circle id=\\\"frame\\\" cx=\\\"16\\\" cy=\\\"16\\\" r=\\\"15\\\" stroke=\\\"#585858\\\" fill=\\\"none\\\" stroke-width=\\\"1\\\"/>\\n    <path\\n       d=\\\"M 8.7124971,21.247342 L 23.333334,21.247342 L 16.022915,8.5759512 L 8.7124971,21.247342 z\\\"\\n       id=\\\"triangle\\\"\\n       stroke=\\\"#585858\\\"\\n       style=\\\"fill:none;stroke-width:1.4;stroke-miterlimit:4;stroke-dasharray:none\\\" />\\n\\t<text font-size=\\\"11\\\" \\n\\t\\tid=\\\"text_name\\\" \\n\\t\\tx=\\\"16\\\" y=\\\"33\\\" \\n\\t\\toryx:align=\\\"top center\\\" \\n\\t\\tstroke=\\\"#373e48\\\"\\n\\t></text>\\n  </g>\\n</svg>\",\n        \"icon\" : \"startevent/signal.png\",\n        \"groups\" : [ \"启动事件\" ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"executionlistenerspackage\", \"signalrefpackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"sequence_start\", \"Startevents_all\", \"StartEventsMorph\", \"all\" ]\n    }, {\n        \"type\" : \"node\",\n        \"id\" : \"StartMessageEvent\",\n        \"title\" : \"消息事件\",\n        \"description\" : \"A start event with a message trigger\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n   xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\n   width=\\\"40\\\"\\n   height=\\\"40\\\"\\n   version=\\\"1.0\\\">\\n  <defs></defs>\\n  <oryx:magnets>\\n  \\t<oryx:magnet oryx:cx=\\\"16\\\" oryx:cy=\\\"16\\\" oryx:default=\\\"yes\\\" />\\n  </oryx:magnets>\\n  <g pointer-events=\\\"fill\\\">\\n    <circle \\n    \\tid=\\\"bg_frame\\\" \\n    \\tcx=\\\"16\\\" \\n    \\tcy=\\\"16\\\" \\n    \\tr=\\\"15\\\" \\n    \\tstroke=\\\"#585858\\\" \\n    \\tfill=\\\"#ffffff\\\" \\n    \\tstroke-width=\\\"1\\\"\\n    \\tstyle=\\\"stroke-dasharray: 5.5, 3\\\" />\\n    \\n    <circle id=\\\"frame\\\" cx=\\\"16\\\" cy=\\\"16\\\" r=\\\"15\\\" stroke=\\\"#585858\\\" fill=\\\"none\\\" stroke-width=\\\"1\\\"/>\\n    \\n    <path transform=\\\"translate(7,7)\\\" id=\\\"path1\\\" stroke=\\\"none\\\" fill=\\\"#585858\\\" stroke-width=\\\"1\\\" d=\\\"m 0.5,2.5 0,13 17,0 0,-13 z M 2,4 6.5,8.5 2,13 z M 4,4 14,4 9,9 z m 12,0 0,9 -4.5,-4.5 z M 7.5,9.5 9,11 10.5,9.5 15,14 3,14 z\\\"/>\\n\\t<text font-size=\\\"11\\\" \\n\\t\\tid=\\\"text_name\\\" \\n\\t\\tx=\\\"16\\\" y=\\\"33\\\" \\n\\t\\toryx:align=\\\"top center\\\" \\n\\t\\tstroke=\\\"#373e48\\\"\\n\\t></text>\\n  </g>\\n</svg>\",\n        \"icon\" : \"startevent/message.png\",\n        \"groups\" : [ \"启动事件\" ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"executionlistenerspackage\", \"messagerefpackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"sequence_start\", \"Startevents_all\", \"StartEventsMorph\", \"all\" ]\n    }, {\n        \"type\" : \"node\",\n        \"id\" : \"StartErrorEvent\",\n        \"title\" : \"异常事件\",\n        \"description\" : \"A start event that catches a thrown BPMN error\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n   xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\n   width=\\\"40\\\"\\n   height=\\\"40\\\"\\n   version=\\\"1.0\\\">\\n  <defs></defs>\\n  <oryx:magnets>\\n  \\t<oryx:magnet oryx:cx=\\\"16\\\" oryx:cy=\\\"16\\\" oryx:default=\\\"yes\\\" />\\n  </oryx:magnets>\\n  <oryx:docker oryx:cx=\\\"16\\\" oryx:cy=\\\"16\\\" />\\n  <g pointer-events=\\\"fill\\\">\\n    <circle id=\\\"bg_frame\\\" cx=\\\"16\\\" cy=\\\"16\\\" r=\\\"15\\\" stroke=\\\"#585858\\\" fill=\\\"#ffffff\\\" stroke-width=\\\"1\\\"/>\\n    \\n    <path\\n         stroke=\\\"#585858\\\"\\n         style=\\\"fill:none;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10\\\"\\n         d=\\\"M 22.820839,11.171502 L 19.36734,24.58992 L 13.54138,14.281819 L 9.3386512,20.071607 L 13.048949,6.8323057 L 18.996148,16.132659 L 22.820839,11.171502 z\\\"\\n         id=\\\"errorPolygon\\\" />\\n\\t<text font-size=\\\"11\\\" \\n\\t\\tid=\\\"text_name\\\" \\n\\t\\tx=\\\"16\\\" y=\\\"33\\\" \\n\\t\\toryx:align=\\\"top center\\\" \\n\\t\\tstroke=\\\"#373e48\\\"\\n\\t></text>\\n  </g>\\n</svg>\",\n        \"icon\" : \"startevent/error.png\",\n        \"groups\" : [ \"启动事件\" ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"executionlistenerspackage\", \"errorrefpackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"sequence_start\", \"Startevents_all\", \"StartEventsMorph\", \"all\" ]\n    }, {\n        \"type\" : \"node\",\n        \"id\" : \"UserTask\",\n        \"title\" : \"用户活动\",\n        \"description\" : \"分配给特定人的任务 \",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n   xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:svg=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\n   xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\"\\n\\n   width=\\\"102\\\"\\n   height=\\\"82\\\"\\n   version=\\\"1.0\\\">\\n  <defs></defs>\\n  <oryx:magnets>\\n  \\t<oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"20\\\" oryx:anchors=\\\"left\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"40\\\" oryx:anchors=\\\"left\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"60\\\" oryx:anchors=\\\"left\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"25\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"75\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"20\\\" oryx:anchors=\\\"right\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"40\\\" oryx:anchors=\\\"right\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"60\\\" oryx:anchors=\\\"right\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"25\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"75\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"40\\\" oryx:default=\\\"yes\\\" />\\n  </oryx:magnets>\\n  <g pointer-events=\\\"fill\\\" oryx:minimumSize=\\\"50 40\\\">\\n\\t<rect id=\\\"text_frame\\\" oryx:anchors=\\\"bottom top right left\\\" x=\\\"1\\\" y=\\\"1\\\" width=\\\"94\\\" height=\\\"79\\\" rx=\\\"10\\\" ry=\\\"10\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" fill=\\\"none\\\" />\\n\\t<rect id=\\\"bg_frame\\\" oryx:resize=\\\"vertical horizontal\\\" x=\\\"0\\\" y=\\\"0\\\" width=\\\"100\\\" height=\\\"80\\\" rx=\\\"10\\\" ry=\\\"10\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"1\\\" fill=\\\"#f9f9f9\\\" />\\n\\t\\t<text \\n\\t\\t\\tfont-size=\\\"12\\\" \\n\\t\\t\\tid=\\\"text_name\\\" \\n\\t\\t\\tx=\\\"50\\\" \\n\\t\\t\\ty=\\\"40\\\" \\n\\t\\t\\toryx:align=\\\"middle center\\\"\\n\\t\\t\\toryx:fittoelem=\\\"text_frame\\\"\\n\\t\\t\\tstroke=\\\"#373e48\\\">\\n\\t\\t</text>\\n\\t\\n\\t<g id=\\\"userTask\\\" transform=\\\"translate(3,3)\\\">\\n\\t\\t<path oryx:anchors=\\\"top left\\\"\\n       \\t\\tstyle=\\\"fill:#d1b575;stroke:none;\\\"\\n       \\t\\t d=\\\"m 1,17 16,0 0,-1.7778 -5.333332,-3.5555 0,-1.7778 c 1.244444,0 1.244444,-2.3111 1.244444,-2.3111 l 0,-3.0222 C 12.555557,0.8221 9.0000001,1.0001 9.0000001,1.0001 c 0,0 -3.5555556,-0.178 -3.9111111,3.5555 l 0,3.0222 c 0,0 0,2.3111 1.2444443,2.3111 l 0,1.7778 L 1,15.2222 1,17 17,17\\\" \\n         />\\n\\t\\t\\n\\t</g>\\n  \\n\\t<g id=\\\"parallel\\\">\\n\\t\\t<path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" d=\\\"M46 70 v8 M50 70 v8 M54 70 v8\\\" stroke-width=\\\"2\\\" />\\n\\t</g>\\n\\t\\n\\t<g id=\\\"sequential\\\">\\n\\t\\t<path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"2\\\" d=\\\"M46,76h10M46,72h10 M46,68h10\\\"/>\\n\\t</g>\\n\\t\\n\\n\\t<g id=\\\"compensation\\\">\\n\\t\\t<path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" d=\\\"M 62 74 L 66 70 L 66 78 L 62 74 L 62 70 L 58 74 L 62 78 L 62 74\\\" stroke-width=\\\"1\\\" />\\n\\t</g>\\n  </g>\\n</svg>\",\n        \"icon\" : \"activity/list/type.user.png\",\n        \"groups\" : [ \"活动列表\" ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"asynchronousdefinitionpackage\", \"exclusivedefinitionpackage\", \"executionlistenerspackage\", \"multiinstance_typepackage\", \"multiinstance_cardinalitypackage\", \"multiinstance_collectionpackage\", \"multiinstance_variablepackage\", \"multiinstance_conditionpackage\", \"isforcompensationpackage\", \"usertaskassignmentpackage\", \"formkeydefinitionpackage\", \"duedatedefinitionpackage\", \"prioritydefinitionpackage\", \"formpropertiespackage\", \"tasklistenerspackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"Activity\", \"sequence_start\", \"sequence_end\", \"ActivitiesMorph\", \"all\" ]\n    }, {\n        \"type\" : \"node\",\n        \"id\" : \"ServiceTask\",\n        \"title\" : \"服务任务\",\n        \"description\" : \"An automatic task with service logic\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n   xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:svg=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\n   xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\"\\n\\n   width=\\\"102\\\"\\n   height=\\\"82\\\"\\n   version=\\\"1.0\\\">\\n  <defs></defs>\\n  <oryx:magnets>\\n  \\t<oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"20\\\" oryx:anchors=\\\"left\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"40\\\" oryx:anchors=\\\"left\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"60\\\" oryx:anchors=\\\"left\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"25\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"75\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"20\\\" oryx:anchors=\\\"right\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"40\\\" oryx:anchors=\\\"right\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"60\\\" oryx:anchors=\\\"right\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"25\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"75\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"40\\\" oryx:default=\\\"yes\\\" />\\n  </oryx:magnets>\\n  <g pointer-events=\\\"fill\\\" oryx:minimumSize=\\\"50 40\\\">\\n\\t<rect id=\\\"text_frame\\\" oryx:anchors=\\\"bottom top right left\\\" x=\\\"1\\\" y=\\\"1\\\" width=\\\"94\\\" height=\\\"79\\\" rx=\\\"10\\\" ry=\\\"10\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" fill=\\\"none\\\" />\\n\\t<rect id=\\\"bg_frame\\\" oryx:resize=\\\"vertical horizontal\\\" x=\\\"0\\\" y=\\\"0\\\" width=\\\"100\\\" height=\\\"80\\\" rx=\\\"10\\\" ry=\\\"10\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"1\\\" fill=\\\"#f9f9f9\\\" />\\n\\t\\t<text \\n\\t\\t\\tfont-size=\\\"12\\\" \\n\\t\\t\\tid=\\\"text_name\\\" \\n\\t\\t\\tx=\\\"50\\\" \\n\\t\\t\\ty=\\\"40\\\" \\n\\t\\t\\toryx:align=\\\"middle center\\\"\\n\\t\\t\\toryx:fittoelem=\\\"text_frame\\\"\\n\\t\\t\\tstroke=\\\"#373e48\\\">\\n\\t\\t</text>\\n\\t\\n\\t<g id=\\\"serviceTask\\\" transform=\\\"translate(3,3)\\\">\\n\\t<path oryx:anchors=\\\"top left\\\"\\n\\t\\tstyle=\\\"fill:#72a7d0;stroke:none\\\"\\n     d=\\\"M 8,1 7.5,2.875 c 0,0 -0.02438,0.250763 -0.40625,0.4375 C 7.05724,3.330353 7.04387,3.358818 7,3.375 6.6676654,3.4929791 6.3336971,3.6092802 6.03125,3.78125 6.02349,3.78566 6.007733,3.77681 6,3.78125 5.8811373,3.761018 5.8125,3.71875 5.8125,3.71875 l -1.6875,-1 -1.40625,1.4375 0.96875,1.65625 c 0,0 0.065705,0.068637 0.09375,0.1875 0.002,0.00849 -0.00169,0.022138 0,0.03125 C 3.6092802,6.3336971 3.4929791,6.6676654 3.375,7 3.3629836,7.0338489 3.3239228,7.0596246 3.3125,7.09375 3.125763,7.4756184 2.875,7.5 2.875,7.5 L 1,8 l 0,2 1.875,0.5 c 0,0 0.250763,0.02438 0.4375,0.40625 0.017853,0.03651 0.046318,0.04988 0.0625,0.09375 0.1129372,0.318132 0.2124732,0.646641 0.375,0.9375 -0.00302,0.215512 -0.09375,0.34375 -0.09375,0.34375 L 2.6875,13.9375 4.09375,15.34375 5.78125,14.375 c 0,0 0.1229911,-0.09744 0.34375,-0.09375 0.2720511,0.147787 0.5795915,0.23888 0.875,0.34375 0.033849,0.01202 0.059625,0.05108 0.09375,0.0625 C 7.4756199,14.874237 7.5,15.125 7.5,15.125 L 8,17 l 2,0 0.5,-1.875 c 0,0 0.02438,-0.250763 0.40625,-0.4375 0.03651,-0.01785 0.04988,-0.04632 0.09375,-0.0625 0.332335,-0.117979 0.666303,-0.23428 0.96875,-0.40625 0.177303,0.0173 0.28125,0.09375 0.28125,0.09375 l 1.65625,0.96875 1.40625,-1.40625 -0.96875,-1.65625 c 0,0 -0.07645,-0.103947 -0.09375,-0.28125 0.162527,-0.290859 0.262063,-0.619368 0.375,-0.9375 0.01618,-0.04387 0.04465,-0.05724 0.0625,-0.09375 C 14.874237,10.52438 15.125,10.5 15.125,10.5 L 17,10 17,8 15.125,7.5 c 0,0 -0.250763,-0.024382 -0.4375,-0.40625 C 14.669647,7.0572406 14.641181,7.0438697 14.625,7 14.55912,6.8144282 14.520616,6.6141566 14.4375,6.4375 c -0.224363,-0.4866 0,-0.71875 0,-0.71875 L 15.40625,4.0625 14,2.625 l -1.65625,1 c 0,0 -0.253337,0.1695664 -0.71875,-0.03125 l -0.03125,0 C 11.405359,3.5035185 11.198648,3.4455201 11,3.375 10.95613,3.3588185 10.942759,3.3303534 10.90625,3.3125 10.524382,3.125763 10.5,2.875 10.5,2.875 L 10,1 8,1 z m 1,5 c 1.656854,0 3,1.3431458 3,3 0,1.656854 -1.343146,3 -3,3 C 7.3431458,12 6,10.656854 6,9 6,7.3431458 7.3431458,6 9,6 z\\\" />\\n\\t</g>\\n  \\n\\t<g id=\\\"parallel\\\">\\n\\t\\t<path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" d=\\\"M46 70 v8 M50 70 v8 M54 70 v8\\\" stroke-width=\\\"2\\\" />\\n\\t</g>\\n\\t\\n\\t<g id=\\\"sequential\\\">\\n\\t\\t<path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"2\\\" d=\\\"M46,76h10M46,72h10 M46,68h10\\\"/>\\n\\t</g>\\n\\t\\n\\t<g id=\\\"compensation\\\">\\n\\t\\t<path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" d=\\\"M 62 74 L 66 70 L 66 78 L 62 74 L 62 70 L 58 74 L 62 78 L 62 74\\\" stroke-width=\\\"1\\\" />\\n\\t</g>\\n  </g>\\n</svg>\",\n        \"icon\" : \"activity/list/type.service.png\",\n        \"groups\" : [ \"活动列表\" ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"asynchronousdefinitionpackage\", \"exclusivedefinitionpackage\", \"executionlistenerspackage\", \"multiinstance_typepackage\", \"multiinstance_cardinalitypackage\", \"multiinstance_collectionpackage\", \"multiinstance_variablepackage\", \"multiinstance_conditionpackage\", \"isforcompensationpackage\", \"servicetaskclasspackage\", \"servicetaskexpressionpackage\", \"servicetaskdelegateexpressionpackage\", \"servicetaskfieldspackage\", \"servicetaskresultvariablepackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"Activity\", \"sequence_start\", \"sequence_end\", \"ActivitiesMorph\", \"all\" ]\n    }, {\n        \"type\" : \"node\",\n        \"id\" : \"ScriptTask\",\n        \"title\" : \"脚本任务\",\n        \"description\" : \"An automatic task with script logic\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n   xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:svg=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\n   xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\"\\n\\n   width=\\\"102\\\"\\n   height=\\\"82\\\"\\n   version=\\\"1.0\\\">\\n  <defs></defs>\\n  <oryx:magnets>\\n  \\t<oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"20\\\" oryx:anchors=\\\"left\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"40\\\" oryx:anchors=\\\"left\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"60\\\" oryx:anchors=\\\"left\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"25\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"75\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"20\\\" oryx:anchors=\\\"right\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"40\\\" oryx:anchors=\\\"right\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"60\\\" oryx:anchors=\\\"right\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"25\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"75\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"40\\\" oryx:default=\\\"yes\\\" />\\n  </oryx:magnets>\\n  <g pointer-events=\\\"fill\\\" oryx:minimumSize=\\\"50 40\\\">\\n\\t<rect id=\\\"text_frame\\\" oryx:anchors=\\\"bottom top right left\\\" x=\\\"1\\\" y=\\\"1\\\" width=\\\"94\\\" height=\\\"79\\\" rx=\\\"10\\\" ry=\\\"10\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" fill=\\\"none\\\" />\\n\\t<rect id=\\\"bg_frame\\\" oryx:resize=\\\"vertical horizontal\\\" x=\\\"0\\\" y=\\\"0\\\" width=\\\"100\\\" height=\\\"80\\\" rx=\\\"10\\\" ry=\\\"10\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"1\\\" fill=\\\"#f9f9f9\\\" />\\n\\t\\t<text \\n\\t\\t\\tfont-size=\\\"12\\\" \\n\\t\\t\\tid=\\\"text_name\\\" \\n\\t\\t\\tx=\\\"50\\\" \\n\\t\\t\\ty=\\\"40\\\" \\n\\t\\t\\toryx:align=\\\"middle center\\\"\\n\\t\\t\\toryx:fittoelem=\\\"text_frame\\\"\\n\\t\\t\\tstroke=\\\"#373e48\\\">\\n\\t\\t</text>\\n\\t\\n\\t<g id=\\\"scriptTask\\\" transform=\\\"translate(2,2)\\\">\\n\\t\\t<path oryx:anchors=\\\"top left\\\"\\n\\t\\t\\td=\\\"m 5,2 0,0.094 c 0.23706,0.064 0.53189,0.1645 0.8125,0.375 0.5582,0.4186 1.05109,1.228 1.15625,2.5312 l 8.03125,0 1,0 1,0 c 0,-3 -2,-3 -2,-3 l -10,0 z M 4,3 4,13 2,13 c 0,3 2,3 2,3 l 9,0 c 0,0 2,0 2,-3 L 15,6 6,6 6,5.5 C 6,4.1111 5.5595,3.529 5.1875,3.25 4.8155,2.971 4.5,3 4.5,3 L 4,3 z\\\"\\n     \\t\\tstyle=\\\"fill:#72a7d0;stroke:none\\\"\\n\\t\\t/>\\n\\t</g>\\n  \\n\\t<g id=\\\"parallel\\\">\\n\\t\\t<path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" d=\\\"M46 70 v8 M50 70 v8 M54 70 v8\\\" stroke-width=\\\"2\\\" />\\n\\t</g>\\n\\t<g id=\\\"sequential\\\">\\n\\t\\t<path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"2\\\" d=\\\"M46,76h10M46,72h10 M46,68h10\\\"/>\\n\\t</g>\\n\\t\\n\\n\\t<g id=\\\"compensation\\\">\\n\\t\\t<path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" d=\\\"M 62 74 L 66 70 L 66 78 L 62 74 L 62 70 L 58 74 L 62 78 L 62 74\\\" stroke-width=\\\"1\\\" />\\n\\t</g>\\n  </g>\\n</svg>\",\n        \"icon\" : \"activity/list/type.script.png\",\n        \"groups\" : [ \"活动列表\" ],\n        \"propertyPackages\" : [ \"scriptformatpackage\", \"scripttextpackage\", \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"asynchronousdefinitionpackage\", \"exclusivedefinitionpackage\", \"executionlistenerspackage\", \"multiinstance_typepackage\", \"multiinstance_cardinalitypackage\", \"multiinstance_collectionpackage\", \"multiinstance_variablepackage\", \"multiinstance_conditionpackage\", \"isforcompensationpackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"Activity\", \"sequence_start\", \"sequence_end\", \"ActivitiesMorph\", \"all\" ]\n    }, {\n        \"type\" : \"node\",\n        \"id\" : \"BusinessRule\",\n        \"title\" : \"规则任务\",\n        \"description\" : \"An automatic task with rule logic\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n   xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:svg=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\n   xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\"\\n\\n   width=\\\"102\\\"\\n   height=\\\"82\\\"\\n   version=\\\"1.0\\\">\\n  <defs></defs>\\n  <oryx:magnets>\\n  \\t<oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"20\\\" oryx:anchors=\\\"left\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"40\\\" oryx:anchors=\\\"left\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"60\\\" oryx:anchors=\\\"left\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"25\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"75\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"20\\\" oryx:anchors=\\\"right\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"40\\\" oryx:anchors=\\\"right\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"60\\\" oryx:anchors=\\\"right\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"25\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"75\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"40\\\" oryx:default=\\\"yes\\\" />\\n  </oryx:magnets>\\n  <g pointer-events=\\\"fill\\\" oryx:minimumSize=\\\"50 40\\\">\\n  \\t<defs>\\n\\t\\t<radialGradient id=\\\"background\\\" cx=\\\"10%\\\" cy=\\\"10%\\\" r=\\\"100%\\\" fx=\\\"10%\\\" fy=\\\"10%\\\">\\n\\t\\t\\t<stop offset=\\\"0%\\\" stop-color=\\\"#ffffff\\\" stop-opacity=\\\"1\\\"/>\\n\\t\\t\\t<stop id=\\\"fill_el\\\" offset=\\\"100%\\\" stop-color=\\\"#ffffcc\\\" stop-opacity=\\\"1\\\"/>\\n\\t\\t</radialGradient>\\n\\t</defs>\\n\\t\\n\\t<rect id=\\\"text_frame\\\" oryx:anchors=\\\"bottom top right left\\\" x=\\\"1\\\" y=\\\"1\\\" width=\\\"94\\\" height=\\\"79\\\" rx=\\\"10\\\" ry=\\\"10\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" fill=\\\"none\\\" />\\n\\t<rect id=\\\"bg_frame\\\" oryx:resize=\\\"vertical horizontal\\\" x=\\\"0\\\" y=\\\"0\\\" width=\\\"100\\\" height=\\\"80\\\" rx=\\\"10\\\" ry=\\\"10\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"1\\\" fill=\\\"#f9f9f9\\\" />\\n\\t\\t<text \\n\\t\\t\\tfont-size=\\\"12\\\" \\n\\t\\t\\tid=\\\"text_name\\\" \\n\\t\\t\\tx=\\\"50\\\" \\n\\t\\t\\ty=\\\"40\\\" \\n\\t\\t\\toryx:align=\\\"middle center\\\"\\n\\t\\t\\toryx:fittoelem=\\\"text_frame\\\"\\n\\t\\t\\tstroke=\\\"#373e48\\\">\\n\\t\\t</text>\\n    \\n\\t<g id=\\\"businessRuleTask\\\" transform=\\\"translate(4,3)\\\">\\n\\t\\t<path oryx:anchors=\\\"top left\\\" \\n\\t\\t\\t d=\\\"m 1,2 0,14 16,0 0,-14 z m 1.45458,5.6000386 2.90906,0 0,2.7999224 -2.90906,0 z m 4.36364,0 8.72718,0 0,2.7999224 -8.72718,0 z m -4.36364,4.1998844 2.90906,0 0,2.800116 -2.90906,0 z m 4.36364,0 8.72718,0 0,2.800116 -8.72718,0 z\\\"\\n     \\t\\tstyle=\\\"fill:#72a7d0;stroke:none\\\"\\n\\t\\t/>\\n\\t</g>\\n\\t\\n\\t<g id=\\\"parallel\\\">\\n\\t\\t<path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" d=\\\"M46 70 v8 M50 70 v8 M54 70 v8\\\" stroke-width=\\\"2\\\" />\\n\\t</g>\\n\\t\\n\\t<g id=\\\"sequential\\\">\\n\\t\\t<path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"2\\\" d=\\\"M46,76h10M46,72h10 M46,68h10\\\"/>\\n\\t</g>\\n\\n\\t<g id=\\\"compensation\\\">\\n\\t\\t<path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" d=\\\"M 62 74 L 66 70 L 66 78 L 62 74 L 62 70 L 58 74 L 62 78 L 62 74\\\" stroke-width=\\\"1\\\" />\\n\\t</g>\\n  </g>\\n</svg>\",\n        \"icon\" : \"activity/list/type.business.rule.png\",\n        \"groups\" : [ \"活动列表\" ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"asynchronousdefinitionpackage\", \"exclusivedefinitionpackage\", \"executionlistenerspackage\", \"multiinstance_typepackage\", \"multiinstance_cardinalitypackage\", \"multiinstance_collectionpackage\", \"multiinstance_variablepackage\", \"multiinstance_conditionpackage\", \"isforcompensationpackage\", \"ruletask_rulespackage\", \"ruletask_variables_inputpackage\", \"ruletask_excludepackage\", \"ruletask_resultpackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"Activity\", \"sequence_start\", \"sequence_end\", \"ActivitiesMorph\", \"all\" ]\n    }, {\n        \"type\" : \"node\",\n        \"id\" : \"ReceiveTask\",\n        \"title\" : \"接受任务\",\n        \"description\" : \"An task that waits for a signal\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n   xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:svg=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\n   xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\"\\n\\n   width=\\\"102\\\"\\n   height=\\\"82\\\"\\n   version=\\\"1.0\\\">\\n  <defs></defs>\\n  <oryx:magnets>\\n  \\t<oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"20\\\" oryx:anchors=\\\"left\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"40\\\" oryx:anchors=\\\"left\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"60\\\" oryx:anchors=\\\"left\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"25\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"75\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"20\\\" oryx:anchors=\\\"right\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"40\\\" oryx:anchors=\\\"right\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"60\\\" oryx:anchors=\\\"right\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"25\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"75\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"40\\\" oryx:default=\\\"yes\\\" />\\n  </oryx:magnets>\\n  <g pointer-events=\\\"fill\\\" oryx:minimumSize=\\\"50 40\\\">\\n\\t<rect id=\\\"text_frame\\\" oryx:anchors=\\\"bottom top right left\\\" x=\\\"1\\\" y=\\\"1\\\" width=\\\"94\\\" height=\\\"79\\\" rx=\\\"10\\\" ry=\\\"10\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" fill=\\\"none\\\" />\\n\\t<rect id=\\\"bg_frame\\\" oryx:resize=\\\"vertical horizontal\\\" x=\\\"0\\\" y=\\\"0\\\" width=\\\"100\\\" height=\\\"80\\\" rx=\\\"10\\\" ry=\\\"10\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"1\\\" fill=\\\"#f9f9f9\\\" />\\n\\t\\t<text \\n\\t\\t\\tfont-size=\\\"12\\\" \\n\\t\\t\\tid=\\\"text_name\\\" \\n\\t\\t\\tx=\\\"50\\\" \\n\\t\\t\\ty=\\\"40\\\" \\n\\t\\t\\toryx:align=\\\"middle center\\\"\\n\\t\\t\\toryx:fittoelem=\\\"text_frame\\\"\\n\\t\\t\\tstroke=\\\"#373e48\\\">\\n\\t\\t</text>\\n    \\n\\t<g id=\\\"receiveTask\\\" transform=\\\"translate(4,3)\\\">\\n\\t\\t<path oryx:anchors=\\\"left top\\\" \\n\\t\\t\\t style=\\\"fill:#16964d;stroke:none;\\\"\\n     \\t\\t d=\\\"m 0.5,2.5 0,13 17,0 0,-13 z M 2,4 6.5,8.5 2,13 z M 4,4 14,4 9,9 z m 12,0 0,9 -4.5,-4.5 z M 7.5,9.5 9,11 10.5,9.5 15,14 3,14 z\\\"\\n\\t\\t />\\n\\t</g>\\n\\t\\n\\t<g id=\\\"parallel\\\">\\n\\t\\t<path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" d=\\\"M46 70 v8 M50 70 v8 M54 70 v8\\\" stroke-width=\\\"2\\\" />\\n\\t</g>\\n\\t\\n\\t<g id=\\\"sequential\\\">\\n\\t\\t<path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"2\\\" d=\\\"M46,76h10M46,72h10 M46,68h10\\\"/>\\n\\t</g>\\n\\n\\t<g id=\\\"compensation\\\">\\n\\t\\t<path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" d=\\\"M 62 74 L 66 70 L 66 78 L 62 74 L 62 70 L 58 74 L 62 78 L 62 74\\\" stroke-width=\\\"1\\\" />\\n\\t</g>\\n  </g>\\n</svg>\",\n        \"icon\" : \"activity/list/type.receive.png\",\n        \"groups\" : [ \"活动列表\" ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"asynchronousdefinitionpackage\", \"exclusivedefinitionpackage\", \"executionlistenerspackage\", \"multiinstance_typepackage\", \"multiinstance_cardinalitypackage\", \"multiinstance_collectionpackage\", \"multiinstance_variablepackage\", \"multiinstance_conditionpackage\", \"isforcompensationpackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"Activity\", \"sequence_start\", \"sequence_end\", \"ActivitiesMorph\", \"all\" ]\n    }, {\n        \"type\" : \"node\",\n        \"id\" : \"ManualTask\",\n        \"title\" : \"手工任务\",\n        \"description\" : \"An automatic task with no logic\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n   xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:svg=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\n   xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\"\\n\\n   width=\\\"102\\\"\\n   height=\\\"82\\\"\\n   version=\\\"1.0\\\">\\n  <defs></defs>\\n  <oryx:magnets>\\n  \\t<oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"20\\\" oryx:anchors=\\\"left\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"40\\\" oryx:anchors=\\\"left\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"60\\\" oryx:anchors=\\\"left\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"25\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"75\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"20\\\" oryx:anchors=\\\"right\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"40\\\" oryx:anchors=\\\"right\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"60\\\" oryx:anchors=\\\"right\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"25\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"75\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"40\\\" oryx:default=\\\"yes\\\" />\\n  </oryx:magnets>\\n  <g pointer-events=\\\"fill\\\" oryx:minimumSize=\\\"50 40\\\">\\n\\t<rect id=\\\"text_frame\\\" oryx:anchors=\\\"bottom top right left\\\" x=\\\"1\\\" y=\\\"1\\\" width=\\\"94\\\" height=\\\"79\\\" rx=\\\"10\\\" ry=\\\"10\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" fill=\\\"none\\\" />\\n\\t<rect id=\\\"bg_frame\\\" oryx:resize=\\\"vertical horizontal\\\" x=\\\"0\\\" y=\\\"0\\\" width=\\\"100\\\" height=\\\"80\\\" rx=\\\"10\\\" ry=\\\"10\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"1\\\" fill=\\\"#f9f9f9\\\" />\\n\\t\\t<text \\n\\t\\t\\tfont-size=\\\"12\\\" \\n\\t\\t\\tid=\\\"text_name\\\" \\n\\t\\t\\tx=\\\"50\\\" \\n\\t\\t\\ty=\\\"40\\\" \\n\\t\\t\\toryx:align=\\\"middle center\\\"\\n\\t\\t\\toryx:fittoelem=\\\"text_frame\\\"\\n\\t\\t\\tstroke=\\\"#373e48\\\">\\n\\t\\t</text>\\n    <g id=\\\"manualTask\\\" transform=\\\"translate(3,1)\\\">\\n    \\t<path oryx:anchors=\\\"top left\\\"\\n    \\t\\tstyle=\\\"fill:#d1b575;stroke=none\\\"\\n     \\t\\td=\\\"m 17,9.3290326 c -0.0069,0.5512461 -0.455166,1.0455894 -0.940778,1.0376604 l -5.792746,0 c 0.0053,0.119381 0.0026,0.237107 0.0061,0.355965 l 5.154918,0 c 0.482032,-0.0096 0.925529,0.49051 0.919525,1.037574 -0.0078,0.537128 -0.446283,1.017531 -0.919521,1.007683 l -5.245273,0 c -0.01507,0.104484 -0.03389,0.204081 -0.05316,0.301591 l 2.630175,0 c 0.454137,-0.0096 0.872112,0.461754 0.866386,0.977186 C 13.619526,14.554106 13.206293,15.009498 12.75924,15 L 3.7753054,15 C 3.6045812,15 3.433552,14.94423 3.2916363,14.837136 c -0.00174,0 -0.00436,0 -0.00609,0 C 1.7212035,14.367801 0.99998255,11.458641 1,11.458641 L 1,7.4588393 c 0,0 0.6623144,-1.316333 1.8390583,-2.0872584 1.1767614,-0.7711868 6.8053358,-2.40497 7.2587847,-2.8052901 0.453484,-0.40032 1.660213,1.4859942 0.04775,2.4010487 C 8.5332315,5.882394 8.507351,5.7996113 8.4370292,5.7936859 l 6.3569748,-0.00871 c 0.497046,-0.00958 0.952273,0.5097676 0.94612,1.0738232 -0.0053,0.556126 -0.456176,1.0566566 -0.94612,1.0496854 l -4.72435,0 c 0.01307,0.1149374 0.0244,0.2281319 0.03721,0.3498661 l 5.952195,0 c 0.494517,-0.00871 0.947906,0.5066305 0.940795,1.0679848 z\\\"\\n    \\t/>\\n\\t</g>\\n\\t\\n\\t<g id=\\\"parallel\\\">\\n\\t\\t<path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" d=\\\"M46 70 v8 M50 70 v8 M54 70 v8\\\" stroke-width=\\\"2\\\" />\\n\\t</g>\\n\\t\\n\\t<g id=\\\"sequential\\\">\\n\\t\\t<path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"2\\\" d=\\\"M46,76h10M46,72h10 M46,68h10\\\"/>\\n\\t</g>\\n\\n\\t<g id=\\\"compensation\\\">\\n\\t\\t<path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" d=\\\"M 62 74 L 66 70 L 66 78 L 62 74 L 62 70 L 58 74 L 62 78 L 62 74\\\" stroke-width=\\\"1\\\" />\\n\\t</g>\\n  </g>\\n</svg>\",\n        \"icon\" : \"activity/list/type.manual.png\",\n        \"groups\" : [ \"活动列表\" ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"asynchronousdefinitionpackage\", \"exclusivedefinitionpackage\", \"executionlistenerspackage\", \"multiinstance_typepackage\", \"multiinstance_cardinalitypackage\", \"multiinstance_collectionpackage\", \"multiinstance_variablepackage\", \"multiinstance_conditionpackage\", \"isforcompensationpackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"Activity\", \"sequence_start\", \"sequence_end\", \"ActivitiesMorph\", \"all\" ]\n    }, {\n        \"type\" : \"node\",\n        \"id\" : \"MailTask\",\n        \"title\" : \"邮件任务\",\n        \"description\" : \"An mail task\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n   xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:svg=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\n   xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\"\\n\\n   width=\\\"102\\\"\\n   height=\\\"82\\\"\\n   version=\\\"1.0\\\">\\n  <defs></defs>\\n  <oryx:magnets>\\n  \\t<oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"20\\\" oryx:anchors=\\\"left\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"40\\\" oryx:anchors=\\\"left\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"60\\\" oryx:anchors=\\\"left\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"25\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"75\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"20\\\" oryx:anchors=\\\"right\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"40\\\" oryx:anchors=\\\"right\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"60\\\" oryx:anchors=\\\"right\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"25\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"75\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"40\\\" oryx:default=\\\"yes\\\" />\\n  </oryx:magnets>\\n  <g pointer-events=\\\"fill\\\" oryx:minimumSize=\\\"50 40\\\">\\n\\t<rect id=\\\"text_frame\\\" oryx:anchors=\\\"bottom top right left\\\" x=\\\"1\\\" y=\\\"1\\\" width=\\\"94\\\" height=\\\"79\\\" rx=\\\"10\\\" ry=\\\"10\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" fill=\\\"none\\\" />\\n\\t<rect id=\\\"bg_frame\\\" oryx:resize=\\\"vertical horizontal\\\" x=\\\"0\\\" y=\\\"0\\\" width=\\\"100\\\" height=\\\"80\\\" rx=\\\"10\\\" ry=\\\"10\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"1\\\" fill=\\\"#f9f9f9\\\" />\\n\\t\\t<text \\n\\t\\t\\tfont-size=\\\"12\\\" \\n\\t\\t\\tid=\\\"text_name\\\" \\n\\t\\t\\tx=\\\"50\\\" \\n\\t\\t\\ty=\\\"40\\\" \\n\\t\\t\\toryx:align=\\\"middle center\\\"\\n\\t\\t\\toryx:fittoelem=\\\"text_frame\\\"\\n\\t\\t\\tstroke=\\\"#373e48\\\">\\n\\t\\t</text>\\n    \\n\\t<g id=\\\"sendTask\\\" transform=\\\"translate(4,3)\\\">\\n\\t\\n\\t<!-- path here -->\\n\\t\\t<path oryx:anchors=\\\"top left\\\"\\n\\t\\t\\tstyle=\\\"fill:#16964d;stroke:none;\\\"\\n     \\t\\td=\\\"M 1 3 L 9 11 L 17 3 L 1 3 z M 1 5 L 1 13 L 5 9 L 1 5 z M 17 5 L 13 9 L 17 13 L 17 5 z M 6 10 L 1 15 L 17 15 L 12 10 L 9 13 L 6 10 z \\\"\\n     \\t/>\\n\\t</g>\\n\\t\\n\\t<g id=\\\"parallel\\\">\\n\\t\\t<path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" d=\\\"M46 70 v8 M50 70 v8 M54 70 v8\\\" stroke-width=\\\"2\\\" />\\n\\t</g>\\n\\t\\n\\t<g id=\\\"sequential\\\">\\n\\t\\t<path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"2\\\" d=\\\"M46,76h10M46,72h10 M46,68h10\\\"/>\\n\\t</g>\\n\\n\\t<g id=\\\"compensation\\\">\\n\\t\\t<path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" d=\\\"M 62 74 L 66 70 L 66 78 L 62 74 L 62 70 L 58 74 L 62 78 L 62 74\\\" stroke-width=\\\"1\\\" />\\n\\t</g>\\n  </g>\\n</svg>\",\n        \"icon\" : \"activity/list/type.send.png\",\n        \"groups\" : [ \"活动列表\" ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"asynchronousdefinitionpackage\", \"exclusivedefinitionpackage\", \"executionlistenerspackage\", \"multiinstance_typepackage\", \"multiinstance_cardinalitypackage\", \"multiinstance_collectionpackage\", \"multiinstance_variablepackage\", \"multiinstance_conditionpackage\", \"isforcompensationpackage\", \"mailtasktopackage\", \"mailtaskfrompackage\", \"mailtasksubjectpackage\", \"mailtaskccpackage\", \"mailtaskbccpackage\", \"mailtasktextpackage\", \"mailtaskhtmlpackage\", \"mailtaskcharsetpackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"Activity\", \"sequence_start\", \"sequence_end\", \"ActivitiesMorph\", \"all\" ]\n    }, {\n        \"type\" : \"node\",\n        \"id\" : \"CamelTask\",\n        \"title\" : \"Camel任务\",\n        \"description\" : \"An task that sends a message to Camel\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n   xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:svg=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\n   xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\"\\n\\n   width=\\\"102\\\"\\n   height=\\\"82\\\"\\n   version=\\\"1.0\\\">\\n  <defs></defs>\\n  <oryx:magnets>\\n  \\t<oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"20\\\" oryx:anchors=\\\"left\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"40\\\" oryx:anchors=\\\"left\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"60\\\" oryx:anchors=\\\"left\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"25\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"75\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"20\\\" oryx:anchors=\\\"right\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"40\\\" oryx:anchors=\\\"right\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"60\\\" oryx:anchors=\\\"right\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"25\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"75\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"40\\\" oryx:default=\\\"yes\\\" />\\n  </oryx:magnets>\\n  <g pointer-events=\\\"fill\\\" oryx:minimumSize=\\\"50 40\\\">\\n\\t<rect id=\\\"text_frame\\\" oryx:anchors=\\\"bottom top right left\\\" x=\\\"1\\\" y=\\\"1\\\" width=\\\"94\\\" height=\\\"79\\\" rx=\\\"10\\\" ry=\\\"10\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" fill=\\\"none\\\" />\\n\\t<rect id=\\\"bg_frame\\\" oryx:resize=\\\"vertical horizontal\\\" x=\\\"0\\\" y=\\\"0\\\" width=\\\"100\\\" height=\\\"80\\\" rx=\\\"10\\\" ry=\\\"10\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"1\\\" fill=\\\"#f9f9f9\\\" />\\n\\t\\t<text \\n\\t\\t\\tfont-size=\\\"12\\\" \\n\\t\\t\\tid=\\\"text_name\\\" \\n\\t\\t\\tx=\\\"50\\\" \\n\\t\\t\\ty=\\\"40\\\" \\n\\t\\t\\toryx:align=\\\"middle center\\\"\\n\\t\\t\\toryx:fittoelem=\\\"text_frame\\\"\\n\\t\\t\\tstroke=\\\"#373e48\\\">\\n\\t\\t</text>\\n\\t\\n\\t<g id=\\\"camelTask\\\" transform=\\\"translate(4,4)\\\">\\n\\t\\t<path\\n     style=\\\"fill:#bd4848;fill-opacity:1\\\"\\n     d=\\\"m 8.1878027,15.383782 c -0.824818,-0.3427 0.375093,-1.1925 0.404055,-1.7743 0.230509,-0.8159 -0.217173,-1.5329 -0.550642,-2.2283 -0.106244,-0.5273 -0.03299,-1.8886005 -0.747194,-1.7818005 -0.712355,0.3776 -0.9225,1.2309005 -1.253911,1.9055005 -0.175574,1.0874 -0.630353,2.114 -0.775834,3.2123 -0.244009,0.4224 -1.741203,0.3888 -1.554386,-0.1397 0.651324,-0.3302 1.13227,-0.9222 1.180246,-1.6705 0.0082,-0.7042 -0.133578,-1.3681 0.302178,-2.0083 0.08617,-0.3202 0.356348,-1.0224005 -0.218996,-0.8051 -0.694517,0.2372 -1.651062,0.6128 -2.057645,-0.2959005 -0.696769,0.3057005 -1.102947,-0.611 -1.393127,-1.0565 -0.231079,-0.6218 -0.437041,-1.3041 -0.202103,-1.9476 -0.185217,-0.7514 -0.39751099,-1.5209 -0.35214999,-2.301 -0.243425,-0.7796 0.86000899,-1.2456 0.08581,-1.8855 -0.76078999,0.1964 -1.41630099,-0.7569 -0.79351899,-1.2877 0.58743,-0.52829998 1.49031699,-0.242 2.09856399,-0.77049998 0.816875,-0.3212 1.256619,0.65019998 1.923119,0.71939998 0.01194,0.7333 -0.0031,1.5042 -0.18417,2.2232 -0.194069,0.564 -0.811196,1.6968 0.06669,1.9398 0.738382,-0.173 1.095723,-0.9364 1.659041,-1.3729 0.727298,-0.3962 1.093982,-1.117 1.344137,-1.8675 0.400558,-0.8287 1.697676,-0.6854 1.955367,0.1758 0.103564,0.5511 0.9073983,1.7538 1.2472763,0.6846 0.121868,-0.6687 0.785541,-1.4454 1.518183,-1.0431 0.813587,0.4875 0.658233,1.6033 1.285504,2.2454 0.768715,0.8117 1.745394,1.4801 2.196633,2.5469 0.313781,0.8074 0.568552,1.707 0.496624,2.5733 -0.35485,0.8576005 -1.224508,-0.216 -0.64725,-0.7284 0.01868,-0.3794 -0.01834,-1.3264 -0.370249,-1.3272 -0.123187,0.7586 -0.152778,1.547 -0.10869,2.3154 0.270285,0.6662005 1.310741,0.7653005 1.060553,1.6763005 -0.03493,0.9801 0.294343,1.9505 0.148048,2.9272 -0.320479,0.2406 -0.79575,0.097 -1.185062,0.1512 -0.165725,0.3657 -0.40138,0.921 -1.020848,0.6744 -0.564671,0.1141 -1.246404,-0.266 -0.578559,-0.7715 0.679736,-0.5602 0.898618,-1.5362 0.687058,-2.3673 -0.529674,-1.108 -1.275984,-2.0954005 -1.839206,-3.1831005 -0.634619,-0.1004 -1.251945,0.6779 -1.956789,0.7408 -0.6065893,-0.038 -1.0354363,-0.06 -0.8495673,0.6969005 0.01681,0.711 0.152396,1.3997 0.157345,2.1104 0.07947,0.7464 0.171287,1.4944 0.238271,2.2351 0.237411,1.0076 -0.687542,1.1488 -1.414811,0.8598 z m 6.8675483,-1.8379 c 0.114364,-0.3658 0.206751,-1.2704 -0.114466,-1.3553 -0.152626,0.5835 -0.225018,1.1888 -0.227537,1.7919 0.147087,-0.1166 0.265559,-0.2643 0.342003,-0.4366 z\\\"\\n     />\\n\\t</g>\\n  \\n\\t<g id=\\\"parallel\\\">\\n\\t\\t<path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" d=\\\"M46 70 v8 M50 70 v8 M54 70 v8\\\" stroke-width=\\\"2\\\" />\\n\\t</g>\\n\\t<g id=\\\"sequential\\\">\\n\\t\\t<path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"2\\\" d=\\\"M46,76h10M46,72h10 M46,68h10\\\"/>\\n\\t</g>\\n\\t\\n\\n\\t<g id=\\\"compensation\\\">\\n\\t\\t<path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" d=\\\"M 62 74 L 66 70 L 66 78 L 62 74 L 62 70 L 58 74 L 62 78 L 62 74\\\" stroke-width=\\\"1\\\" />\\n\\t</g>\\n  </g>\\n</svg>\",\n        \"icon\" : \"activity/list/type.camel.png\",\n        \"groups\" : [ \"活动列表\" ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"asynchronousdefinitionpackage\", \"exclusivedefinitionpackage\", \"executionlistenerspackage\", \"multiinstance_typepackage\", \"multiinstance_cardinalitypackage\", \"multiinstance_collectionpackage\", \"multiinstance_variablepackage\", \"multiinstance_conditionpackage\", \"isforcompensationpackage\", \"cameltaskcamelcontextpackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"Activity\", \"sequence_start\", \"sequence_end\", \"ActivitiesMorph\", \"all\" ]\n    }, {\n        \"type\" : \"node\",\n        \"id\" : \"MuleTask\",\n        \"title\" : \"Mule任务\",\n        \"description\" : \"An task that sends a message to Mule\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n   xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:svg=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\n   xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\"\\n\\n   width=\\\"102\\\"\\n   height=\\\"82\\\"\\n   version=\\\"1.0\\\">\\n  <defs></defs>\\n  <oryx:magnets>\\n  \\t<oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"20\\\" oryx:anchors=\\\"left\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"40\\\" oryx:anchors=\\\"left\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"60\\\" oryx:anchors=\\\"left\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"25\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"75\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"20\\\" oryx:anchors=\\\"right\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"40\\\" oryx:anchors=\\\"right\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"60\\\" oryx:anchors=\\\"right\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"25\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"75\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"40\\\" oryx:default=\\\"yes\\\" />\\n  </oryx:magnets>\\n  <g pointer-events=\\\"fill\\\" oryx:minimumSize=\\\"50 40\\\">\\n\\t<rect id=\\\"text_frame\\\" oryx:anchors=\\\"bottom top right left\\\" x=\\\"1\\\" y=\\\"1\\\" width=\\\"94\\\" height=\\\"79\\\" rx=\\\"10\\\" ry=\\\"10\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" fill=\\\"none\\\" />\\n\\t<rect id=\\\"bg_frame\\\" oryx:resize=\\\"vertical horizontal\\\" x=\\\"0\\\" y=\\\"0\\\" width=\\\"100\\\" height=\\\"80\\\" rx=\\\"10\\\" ry=\\\"10\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"1\\\" fill=\\\"#f9f9f9\\\" />\\n\\t\\t<text \\n\\t\\t\\tfont-size=\\\"12\\\" \\n\\t\\t\\tid=\\\"text_name\\\" \\n\\t\\t\\tx=\\\"50\\\" \\n\\t\\t\\ty=\\\"40\\\" \\n\\t\\t\\toryx:align=\\\"middle center\\\"\\n\\t\\t\\toryx:fittoelem=\\\"text_frame\\\"\\n\\t\\t\\tstroke=\\\"#373e48\\\">\\n\\t\\t</text>\\n\\t\\n\\t<g id=\\\"muleTask\\\" transform=\\\"translate(4,4)\\\">\\n\\t\\t<path\\n     style=\\\"fill:#bd4848;fill-opacity:1\\\"\\n     d=\\\"M 8,0 C 3.581722,0 0,3.5817 0,8 c 0,4.4183 3.581722,8 8,8 4.418278,0 8,-3.5817 8,-8 L 16,7.6562 C 15.813571,3.3775 12.282847,0 8,0 z M 5.1875,2.7812 8,7.3437 10.8125,2.7812 c 1.323522,0.4299 2.329453,1.5645 2.8125,2.8438 1.136151,2.8609 -0.380702,6.4569 -3.25,7.5937 -0.217837,-0.6102 -0.438416,-1.2022 -0.65625,-1.8125 0.701032,-0.2274 1.313373,-0.6949 1.71875,-1.3125 0.73624,-1.2317 0.939877,-2.6305 -0.03125,-4.3125 l -2.75,4.0625 -0.65625,0 -0.65625,0 -2.75,-4 C 3.5268433,7.6916 3.82626,8.862 4.5625,10.0937 4.967877,10.7113 5.580218,11.1788 6.28125,11.4062 6.063416,12.0165 5.842837,12.6085 5.625,13.2187 2.755702,12.0819 1.238849,8.4858 2.375,5.625 2.858047,4.3457 3.863978,3.2112 5.1875,2.7812 z\\\"\\n     />\\n\\t</g>\\n  \\n\\t<g id=\\\"parallel\\\">\\n\\t\\t<path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" d=\\\"M46 70 v8 M50 70 v8 M54 70 v8\\\" stroke-width=\\\"2\\\" />\\n\\t</g>\\n\\t<g id=\\\"sequential\\\">\\n\\t\\t<path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"2\\\" d=\\\"M46,76h10M46,72h10 M46,68h10\\\"/>\\n\\t</g>\\n\\t\\n\\n\\t<g id=\\\"compensation\\\">\\n\\t\\t<path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" d=\\\"M 62 74 L 66 70 L 66 78 L 62 74 L 62 70 L 58 74 L 62 78 L 62 74\\\" stroke-width=\\\"1\\\" />\\n\\t</g>\\n  </g>\\n</svg>\",\n        \"icon\" : \"activity/list/type.mule.png\",\n        \"groups\" : [ \"活动列表\" ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"asynchronousdefinitionpackage\", \"exclusivedefinitionpackage\", \"executionlistenerspackage\", \"multiinstance_typepackage\", \"multiinstance_cardinalitypackage\", \"multiinstance_collectionpackage\", \"multiinstance_variablepackage\", \"multiinstance_conditionpackage\", \"isforcompensationpackage\", \"muletaskendpointurlpackage\", \"muletasklanguagepackage\", \"muletaskpayloadexpressionpackage\", \"muletaskresultvariablepackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"Activity\", \"sequence_start\", \"sequence_end\", \"ActivitiesMorph\", \"all\" ]\n    }, {\n        \"type\" : \"node\",\n        \"id\" : \"SendTask\",\n        \"title\" : \"Send task\",\n        \"description\" : \"An task that sends a message\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n   xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:svg=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\n   xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\"\\n\\n   width=\\\"102\\\"\\n   height=\\\"82\\\"\\n   version=\\\"1.0\\\">\\n  <defs></defs>\\n  <oryx:magnets>\\n  \\t<oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"20\\\" oryx:anchors=\\\"left\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"40\\\" oryx:anchors=\\\"left\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"60\\\" oryx:anchors=\\\"left\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"25\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"75\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"20\\\" oryx:anchors=\\\"right\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"40\\\" oryx:anchors=\\\"right\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"60\\\" oryx:anchors=\\\"right\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"25\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"75\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"40\\\" oryx:default=\\\"yes\\\" />\\n  </oryx:magnets>\\n  <g pointer-events=\\\"fill\\\" oryx:minimumSize=\\\"50 40\\\">\\n\\t<rect id=\\\"text_frame\\\" oryx:anchors=\\\"bottom top right left\\\" x=\\\"1\\\" y=\\\"1\\\" width=\\\"94\\\" height=\\\"79\\\" rx=\\\"10\\\" ry=\\\"10\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" fill=\\\"none\\\" />\\n\\t<rect id=\\\"bg_frame\\\" oryx:resize=\\\"vertical horizontal\\\" x=\\\"0\\\" y=\\\"0\\\" width=\\\"100\\\" height=\\\"80\\\" rx=\\\"10\\\" ry=\\\"10\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"1\\\" fill=\\\"#f9f9f9\\\" />\\n\\t\\t<text \\n\\t\\t\\tfont-size=\\\"12\\\" \\n\\t\\t\\tid=\\\"text_name\\\" \\n\\t\\t\\tx=\\\"50\\\" \\n\\t\\t\\ty=\\\"40\\\" \\n\\t\\t\\toryx:align=\\\"middle center\\\"\\n\\t\\t\\toryx:fittoelem=\\\"text_frame\\\"\\n\\t\\t\\tstroke=\\\"#373e48\\\">\\n\\t\\t</text>\\n    \\n\\t<g id=\\\"sendTask\\\" transform=\\\"translate(4,3)\\\">\\n\\t\\n\\t<!-- path here -->\\n\\t\\t<path oryx:anchors=\\\"top left\\\"\\n\\t\\t\\tstyle=\\\"fill:#16964d;stroke:none;\\\"\\n     \\t\\td=\\\"M 1 3 L 9 11 L 17 3 L 1 3 z M 1 5 L 1 13 L 5 9 L 1 5 z M 17 5 L 13 9 L 17 13 L 17 5 z M 6 10 L 1 15 L 17 15 L 12 10 L 9 13 L 6 10 z \\\"\\n     \\t/>\\n\\t</g>\\n\\t\\n\\t<g id=\\\"parallel\\\">\\n\\t\\t<path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" d=\\\"M46 70 v8 M50 70 v8 M54 70 v8\\\" stroke-width=\\\"2\\\" />\\n\\t</g>\\n\\t\\n\\t<g id=\\\"sequential\\\">\\n\\t\\t<path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"2\\\" d=\\\"M46,76h10M46,72h10 M46,68h10\\\"/>\\n\\t</g>\\n\\n\\t<g id=\\\"compensation\\\">\\n\\t\\t<path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" d=\\\"M 62 74 L 66 70 L 66 78 L 62 74 L 62 70 L 58 74 L 62 78 L 62 74\\\" stroke-width=\\\"1\\\" />\\n\\t</g>\\n  </g>\\n</svg>\",\n        \"icon\" : \"activity/list/type.send.png\",\n        \"groups\" : [ \"活动列表\" ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"asynchronousdefinitionpackage\", \"exclusivedefinitionpackage\", \"executionlistenerspackage\", \"multiinstance_typepackage\", \"multiinstance_cardinalitypackage\", \"multiinstance_collectionpackage\", \"multiinstance_variablepackage\", \"multiinstance_conditionpackage\", \"isforcompensationpackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"Activity\", \"sequence_start\", \"sequence_end\", \"ActivitiesMorph\", \"all\" ]\n    }, {\n        \"type\" : \"node\",\n        \"id\" : \"SubProcess\",\n        \"title\" : \"子流程\",\n        \"description\" : \"子流程范围\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n   xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:svg=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\n   xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\"\\n   width=\\\"200\\\"\\n   height=\\\"160\\\"\\n   version=\\\"1.0\\\">\\n  <defs></defs>\\n  <oryx:magnets>\\n  \\t<oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"50\\\" oryx:anchors=\\\"left\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"80\\\" oryx:anchors=\\\"left\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"110\\\" oryx:anchors=\\\"left\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"70\\\" oryx:cy=\\\"159\\\" oryx:anchors=\\\"bottom\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"100\\\" oryx:cy=\\\"159\\\" oryx:anchors=\\\"bottom\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"130\\\" oryx:cy=\\\"159\\\" oryx:anchors=\\\"bottom\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"199\\\" oryx:cy=\\\"50\\\" oryx:anchors=\\\"right\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"199\\\" oryx:cy=\\\"80\\\" oryx:anchors=\\\"right\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"199\\\" oryx:cy=\\\"110\\\" oryx:anchors=\\\"right\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"70\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"100\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"130\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"100\\\" oryx:cy=\\\"80\\\" oryx:default=\\\"yes\\\" />\\n  </oryx:magnets>\\n  <g pointer-events=\\\"fill\\\" oryx:minimumSize=\\\"120 100\\\" oryx:maximumSize=\\\"\\\" >\\n    <rect id=\\\"text_frame\\\" oryx:anchors=\\\"bottom top right left\\\" x=\\\"0\\\" y=\\\"0\\\" width=\\\"190\\\" height=\\\"160\\\" rx=\\\"10\\\" ry=\\\"10\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" fill=\\\"none\\\" />\\n\\t<rect id=\\\"bg_frame\\\" oryx:anchors=\\\"bottom top right left\\\" x=\\\"0\\\" y=\\\"0\\\" width=\\\"200\\\" height=\\\"160\\\" rx=\\\"10\\\" ry=\\\"10\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"1\\\" fill=\\\"#ffffff\\\" />\\n\\t<rect id=\\\"border\\\" oryx:anchors=\\\"top bottom left right\\\" oryx:resize=\\\"vertical horizontal\\\" x=\\\"2.5\\\" y=\\\"2.5\\\" width=\\\"195\\\" height=\\\"155\\\" rx=\\\"8\\\" ry=\\\"8\\\" stroke=\\\"black\\\" stroke-width=\\\"1\\\" fill=\\\"none\\\" />\\n\\t<text \\n\\t\\tfont-size=\\\"12\\\" \\n\\t\\tid=\\\"text_name\\\" \\n\\t\\tx=\\\"8\\\" \\n\\t\\ty=\\\"10\\\" \\n\\t\\toryx:align=\\\"top left\\\"\\n\\t\\toryx:fittoelem=\\\"text_frame\\\"\\n\\t\\toryx:anchors=\\\"left top\\\" \\n\\t\\tstroke=\\\"#373e48\\\">\\n\\t</text>\\n\\t\\n\\t<g \\tid=\\\"parallel\\\"\\n\\t\\ttransform=\\\"translate(1)\\\">\\n\\t\\t<path \\n\\t\\t\\tid=\\\"parallelpath\\\"\\n\\t\\t\\toryx:anchors=\\\"bottom\\\" \\n\\t\\t\\tfill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" d=\\\"M96 145 v10 M100 145 v10 M104 145 v10\\\" \\n\\t\\t\\tstroke-width=\\\"2\\\"\\n\\t\\t/>\\n\\t</g>\\n\\t<g \\tid=\\\"sequential\\\"\\n\\t\\ttransform=\\\"translate(1)\\\">\\n\\t\\t<path \\n\\t\\t\\tid=\\\"sequentialpath\\\"\\n\\t\\t\\toryx:anchors=\\\"bottom\\\" \\n\\t\\t\\tfill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"2\\\" d=\\\"M95,154h10 M95,150h10 M95,146h10\\\"\\n\\t\\t/>\\n\\t</g>\\n  </g>\\n</svg>\",\n        \"icon\" : \"activity/expanded.subprocess.png\",\n        \"groups\" : [ \"结构列表\" ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"asynchronousdefinitionpackage\", \"exclusivedefinitionpackage\", \"executionlistenerspackage\", \"multiinstance_typepackage\", \"multiinstance_cardinalitypackage\", \"multiinstance_collectionpackage\", \"multiinstance_variablepackage\", \"multiinstance_conditionpackage\", \"istransactionpackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"Activity\", \"sequence_start\", \"sequence_end\", \"all\" ]\n    }, {\n        \"type\" : \"node\",\n        \"id\" : \"EventSubProcess\",\n        \"title\" : \"事件子流程\",\n        \"description\" : \"一个事件周期的子流程\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n   xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:svg=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\n   xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\"\\n   width=\\\"200\\\"\\n   height=\\\"160\\\"\\n   version=\\\"1.0\\\">\\n  <defs></defs>\\n  <oryx:magnets>\\n  \\t<oryx:magnet oryx:cx=\\\"0\\\" oryx:cy=\\\"80\\\" oryx:anchors=\\\"left\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"100\\\" oryx:cy=\\\"160\\\" oryx:anchors=\\\"bottom\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"200\\\" oryx:cy=\\\"80\\\" oryx:anchors=\\\"right\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"100\\\" oryx:cy=\\\"0\\\" oryx:anchors=\\\"top\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"100\\\" oryx:cy=\\\"80\\\" oryx:default=\\\"yes\\\" />\\n  </oryx:magnets>\\n  <g pointer-events=\\\"fill\\\" oryx:minimumSize=\\\"120 100\\\" oryx:maximumSize=\\\"\\\" >\\n\\t<rect id=\\\"text_frame\\\" oryx:anchors=\\\"bottom top right left\\\" x=\\\"0\\\" y=\\\"0\\\" width=\\\"190\\\" height=\\\"160\\\" rx=\\\"10\\\" ry=\\\"10\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" fill=\\\"none\\\" />\\n\\t<rect id=\\\"bg_frame\\\" oryx:anchors=\\\"bottom top right left\\\" oryx:resize=\\\"vertical horizontal\\\" x=\\\"0\\\" y=\\\"0\\\" width=\\\"200\\\" height=\\\"160\\\" rx=\\\"10\\\" ry=\\\"10\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"1\\\" stroke-dasharray=\\\"2,2,2\\\" fill=\\\"#ffffff\\\" />\\n    \\t<text \\n\\t\\t\\tfont-size=\\\"12\\\" \\n\\t\\t\\tid=\\\"text_name\\\" \\n\\t\\t\\tx=\\\"8\\\" \\n\\t\\t\\ty=\\\"10\\\" \\n\\t\\t\\toryx:align=\\\"top left\\\"\\n\\t\\t\\toryx:fittoelem=\\\"text_frame\\\"\\n\\t\\t\\toryx:anchors=\\\"left top\\\" \\n\\t\\t\\tstroke=\\\"#373e48\\\">\\n\\t\\t</text>\\n    \\t\\n\\t<g id=\\\"none\\\"></g>\\n\\t\\n  </g>\\n</svg>\",\n        \"icon\" : \"activity/event.subprocess.png\",\n        \"groups\" : [ \"结构列表\" ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"asynchronousdefinitionpackage\", \"exclusivedefinitionpackage\", \"executionlistenerspackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"Activity\", \"all\" ]\n    }, {\n        \"type\" : \"node\",\n        \"id\" : \"CallActivity\",\n        \"title\" : \"调用活动\",\n        \"description\" : \"一个调用活动\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n   xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:svg=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\n   xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\"\\n\\n   width=\\\"102\\\"\\n   height=\\\"82\\\"\\n   version=\\\"1.0\\\">\\n  <defs></defs>\\n  <oryx:magnets>\\n  \\t<oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"20\\\" oryx:anchors=\\\"left\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"40\\\" oryx:anchors=\\\"left\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"1\\\" oryx:cy=\\\"60\\\" oryx:anchors=\\\"left\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"25\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"75\\\" oryx:cy=\\\"79\\\" oryx:anchors=\\\"bottom\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"20\\\" oryx:anchors=\\\"right\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"40\\\" oryx:anchors=\\\"right\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"99\\\" oryx:cy=\\\"60\\\" oryx:anchors=\\\"right\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"25\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"75\\\" oryx:cy=\\\"1\\\" oryx:anchors=\\\"top\\\" />\\n  \\t\\n  \\t<oryx:magnet oryx:cx=\\\"50\\\" oryx:cy=\\\"40\\\" oryx:default=\\\"yes\\\" />\\n  </oryx:magnets>\\n  <g pointer-events=\\\"fill\\\" oryx:minimumSize=\\\"50 40\\\">\\n\\t<rect id=\\\"text_frame\\\" oryx:anchors=\\\"bottom top right left\\\" x=\\\"1\\\" y=\\\"1\\\" width=\\\"94\\\" height=\\\"79\\\" rx=\\\"10\\\" ry=\\\"10\\\" stroke=\\\"none\\\" stroke-width=\\\"0\\\" fill=\\\"none\\\" />\\n    <rect oryx:resize=\\\"vertical horizontal\\\" oryx:anchors=\\\"bottom top right left\\\" x=\\\"0\\\" y=\\\"0\\\" width=\\\"100\\\" height=\\\"80\\\" rx=\\\"10\\\" ry=\\\"10\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"4\\\" fill=\\\"none\\\" />\\n\\t<rect id=\\\"bg_frame\\\" oryx:resize=\\\"vertical horizontal\\\" x=\\\"0\\\" y=\\\"0\\\" width=\\\"100\\\" height=\\\"80\\\" rx=\\\"10\\\" ry=\\\"10\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"1\\\" fill=\\\"#f9f9f9\\\" />\\n\\t\\t<text \\n\\t\\t\\tfont-size=\\\"12\\\" \\n\\t\\t\\tid=\\\"text_name\\\" \\n\\t\\t\\tx=\\\"50\\\" \\n\\t\\t\\ty=\\\"40\\\" \\n\\t\\t\\toryx:align=\\\"middle center\\\"\\n\\t\\t\\toryx:fittoelem=\\\"text_frame\\\"\\n\\t\\t\\tstroke=\\\"#373e48\\\">\\n\\t\\t</text>\\n    \\n\\t<g id=\\\"parallel\\\">\\n\\t\\t<path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" d=\\\"M46 70 v8 M50 70 v8 M54 70 v8\\\" stroke-width=\\\"2\\\" />\\n\\t</g>\\n\\t\\n\\t<g id=\\\"sequential\\\">\\n\\t\\t<path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" stroke-width=\\\"2\\\" d=\\\"M46,76h10M46,72h10 M46,68h10\\\"/>\\n\\t</g>\\n\\n\\t<g id=\\\"compensation\\\">\\n\\t\\t<path oryx:anchors=\\\"bottom\\\" fill=\\\"none\\\" stroke=\\\"#bbbbbb\\\" d=\\\"M 62 74 L 66 70 L 66 78 L 62 74 L 62 70 L 58 74 L 62 78 L 62 74\\\" stroke-width=\\\"1\\\" />\\n\\t</g>\\n  </g>\\n</svg>\",\n        \"icon\" : \"activity/task.png\",\n        \"groups\" : [ \"结构列表\" ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"asynchronousdefinitionpackage\", \"exclusivedefinitionpackage\", \"executionlistenerspackage\", \"callactivitycalledelementpackage\", \"callactivityinparameterspackage\", \"callactivityoutparameterspackage\", \"multiinstance_typepackage\", \"multiinstance_cardinalitypackage\", \"multiinstance_collectionpackage\", \"multiinstance_variablepackage\", \"multiinstance_conditionpackage\", \"isforcompensationpackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"Activity\", \"sequence_start\", \"sequence_end\", \"all\" ]\n    }, {\n        \"type\" : \"node\",\n        \"id\" : \"ExclusiveGateway\",\n        \"title\" : \"互斥网关\",\n        \"description\" : \"一个选择的网关\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n   xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\n   xmlns:svg=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n   version=\\\"1.0\\\"\\n   width=\\\"40\\\"\\n   height=\\\"40\\\">\\n  <defs\\n     id=\\\"defs4\\\" />\\n  <oryx:magnets>\\n    <oryx:magnet\\n       oryx:default=\\\"yes\\\"\\n       oryx:cy=\\\"16\\\"\\n       oryx:cx=\\\"16\\\" />\\n  </oryx:magnets>\\t\\t\\t\\t\\t\\n  <g>\\n  \\n    <path\\n       d=\\\"M -4.5,16 L 16,-4.5 L 35.5,16 L 16,35.5z\\\"\\n       id=\\\"bg_frame\\\"\\n       fill=\\\"#ffffff\\\"\\n       stroke=\\\"#585858\\\"\\n       style=\\\"stroke-width:1\\\" />\\n    <g\\n       id=\\\"cross\\\">\\n      <path\\n      \\tid=\\\"crosspath\\\"\\n      \\tstroke=\\\"#585858\\\"\\n      \\tfill=\\\"#585858\\\"\\n        d=\\\"M 8.75,7.55 L 12.75,7.55 L 23.15,24.45 L 19.25,24.45 z\\\"\\n        style=\\\"stroke-width:1\\\" />\\n      <path\\n      \\tid=\\\"crosspath2\\\"\\n      \\tstroke=\\\"#585858\\\"\\n      \\tfill=\\\"#585858\\\"\\n        d=\\\"M 8.75,24.45 L 19.25,7.55 L 23.15,7.55 L 12.75,24.45 z\\\"\\n        style=\\\"stroke-width:1\\\" />\\n    </g>\\n\\t\\n\\t<text id=\\\"text_name\\\" x=\\\"26\\\" y=\\\"26\\\" oryx:align=\\\"left top\\\"/>\\n\\t\\n  </g>\\n</svg>\\n\",\n        \"icon\" : \"gateway/exclusive.databased.png\",\n        \"groups\" : [ \"网关列表\" ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"asynchronousdefinitionpackage\", \"exclusivedefinitionpackage\", \"sequencefloworderpackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"sequence_start\", \"GatewaysMorph\", \"sequence_end\", \"all\" ]\n    }, {\n        \"type\" : \"node\",\n        \"id\" : \"ParallelGateway\",\n        \"title\" : \"并行网关\",\n        \"description\" : \"一个并行的网关\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n   xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\n   xmlns:svg=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n   version=\\\"1.0\\\"\\n   width=\\\"40\\\"\\n   height=\\\"40\\\">\\n   \\n  <oryx:magnets>\\n    <oryx:magnet\\n       oryx:default=\\\"yes\\\"\\n       oryx:cy=\\\"16\\\"\\n       oryx:cx=\\\"16\\\" />\\n  </oryx:magnets>\\n  <g>\\n    <path\\n       d=\\\"M -4.5,16 L 16,-4.5 L 35.5,16 L 16,35.5z\\\"\\n       id=\\\"bg_frame\\\"\\n       fill=\\\"#ffffff\\\"\\n       stroke=\\\"#585858\\\"\\n       style=\\\"stroke-width:1\\\" />\\n    <path\\n       d=\\\"M 6.75,16 L 25.75,16 M 16,6.75 L 16,25.75\\\"\\n       id=\\\"path9\\\"\\n       stroke=\\\"#585858\\\"\\n       style=\\\"fill:none;stroke-width:3\\\" />\\n    \\n\\t<text id=\\\"text_name\\\" x=\\\"26\\\" y=\\\"26\\\" oryx:align=\\\"left top\\\"/>\\n\\t\\n  </g>\\n</svg>\\n\",\n        \"icon\" : \"gateway/parallel.png\",\n        \"groups\" : [ \"网关列表\" ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"asynchronousdefinitionpackage\", \"exclusivedefinitionpackage\", \"sequencefloworderpackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"sequence_start\", \"GatewaysMorph\", \"sequence_end\", \"all\" ]\n    }, {\n        \"type\" : \"node\",\n        \"id\" : \"InclusiveGateway\",\n        \"title\" : \"包容性网关\",\n        \"description\" : \"一个包容性网关\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n   xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\n   xmlns:svg=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n   version=\\\"1.0\\\"\\n   width=\\\"40\\\"\\n   height=\\\"40\\\">\\n  <oryx:magnets>\\n    <oryx:magnet\\n       oryx:default=\\\"yes\\\"\\n       oryx:cy=\\\"16\\\"\\n       oryx:cx=\\\"16\\\" />\\n  </oryx:magnets>\\n  <g>\\n\\n    <path\\n       d=\\\"M -4.5,16 L 16,-4.5 L 35.5,16 L 16,35.5z\\\"\\n       id=\\\"bg_frame\\\"\\n       fill=\\\"#ffffff\\\"\\n       stroke=\\\"#585858\\\"\\n       style=\\\"stroke-width:1\\\" />\\n    <circle\\n    \\tid=\\\"circle\\\"\\n    \\tstroke=\\\"#585858\\\"\\n\\t\\tcx=\\\"16\\\"\\n\\t\\tcy=\\\"16\\\"\\n\\t\\tr=\\\"9.75\\\"\\n\\t\\tstyle=\\\"fill:none;stroke-width:2.5\\\" />\\n    \\n\\t<text id=\\\"text_name\\\" x=\\\"26\\\" y=\\\"26\\\" oryx:align=\\\"left top\\\"/>\\n\\t\\n  </g>\\n</svg>\\n\",\n        \"icon\" : \"gateway/inclusive.png\",\n        \"groups\" : [ \"网关列表\" ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"asynchronousdefinitionpackage\", \"exclusivedefinitionpackage\", \"sequencefloworderpackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"sequence_start\", \"GatewaysMorph\", \"sequence_end\", \"all\" ]\n    }, {\n        \"type\" : \"node\",\n        \"id\" : \"EventGateway\",\n        \"title\" : \"事件网关\",\n        \"description\" : \"一个事件网关\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n   xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\n   xmlns:svg=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n   version=\\\"1.0\\\"\\n   width=\\\"40\\\"\\n   height=\\\"40\\\">\\n  <oryx:magnets>\\n    <oryx:magnet\\n       oryx:default=\\\"yes\\\"\\n       oryx:cy=\\\"16\\\"\\n       oryx:cx=\\\"16\\\" />\\n  </oryx:magnets>\\n  \\n  <g> \\n  \\t\\n\\t<path\\n\\t\\td=\\\"M -4.5,16 L 16,-4.5 L 35.5,16 L 16,35.5z\\\"\\n\\t\\tid=\\\"bg_frame\\\"\\n\\t\\tfill=\\\"#ffffff\\\"\\n\\t\\tstroke=\\\"#585858\\\"\\n\\t\\tstyle=\\\"stroke-width:1\\\" />\\n\\t<circle\\n\\t\\tid=\\\"circle\\\"\\n\\t\\tcx=\\\"16\\\"\\n\\t\\tcy=\\\"16\\\"\\n\\t\\tr=\\\"10.4\\\"\\n\\t\\tstroke=\\\"#585858\\\"\\n\\t\\tstyle=\\\"fill:none;stroke-width:0.5\\\" />\\n\\t<circle\\n\\t\\tid=\\\"circle2\\\"\\n\\t\\tcx=\\\"16\\\"\\n\\t\\tcy=\\\"16\\\"\\n\\t\\tr=\\\"11.7\\\"\\n\\t\\tstroke=\\\"#585858\\\"\\n\\t\\tstyle=\\\"fill:none;stroke-width:0.5\\\" />\\n\\t<path\\n\\t\\td=\\\"M 20.327514,22.344972 L 11.259248,22.344216 L 8.4577203,13.719549 L 15.794545,8.389969 L 23.130481,13.720774 L 20.327514,22.344972 z\\\"\\n\\t\\tid=\\\"middlePolygon\\\"\\n\\t\\tstroke=\\\"#585858\\\"\\n\\t\\tstyle=\\\"fill:none;fill-opacity:1;stroke-width:1.39999998;stroke-linejoin:bevel;stroke-opacity:1\\\" />\\n\\t\\n\\t\\n\\t<g id=\\\"instantiate\\\">\\n\\t\\n\\t\\t<path\\n\\t\\t\\td=\\\"M -4.5,16 L 16,-4.5 L 35.5,16 L 16,35.5z\\\"\\n\\t\\t\\tid=\\\"bg_frame2\\\"\\n\\t\\t\\tfill=\\\"#ffffff\\\"\\n\\t\\t\\tstroke=\\\"#585858\\\"\\n\\t\\t\\tstyle=\\\"stroke-width:1\\\" />\\n\\t\\t<circle\\n\\t\\t\\tid=\\\"circle3\\\"\\n\\t\\t\\tcx=\\\"16\\\"\\n\\t\\t\\tcy=\\\"16\\\"\\n\\t\\t\\tr=\\\"11\\\"\\n\\t\\t\\tstroke=\\\"#585858\\\"\\n\\t\\t\\tstyle=\\\"fill:none;stroke-width:1\\\" />\\n\\t\\t<path\\n\\t\\t\\td=\\\"M 20.327514,22.344972 L 11.259248,22.344216 L 8.4577203,13.719549 L 15.794545,8.389969 L 23.130481,13.720774 L 20.327514,22.344972 z\\\"\\n\\t\\t\\tid=\\\"middlePolygon2\\\"\\n\\t\\t\\tstroke=\\\"#585858\\\"\\n\\t\\t\\tstyle=\\\"fill:none;fill-opacity:1;stroke-width:1.39999998;stroke-linejoin:bevel;stroke-opacity:1\\\" />\\n\\t\\n\\t\\n\\t\\t<g id=\\\"parallel\\\">\\n\\t\\t\\t<path\\n\\t\\t\\t\\td=\\\"M -4.5,16 L 16,-4.5 L 35.5,16 L 16,35.5z\\\"\\n\\t\\t\\t\\tid=\\\"bg_frame3\\\"\\n\\t\\t\\t\\tfill=\\\"#ffffff\\\"\\n\\t\\t\\t\\tstroke=\\\"#585858\\\"\\n\\t\\t\\t\\tstyle=\\\"stroke-width:1\\\" />\\n\\t\\t\\t<circle id=\\\"frame5\\\" cx=\\\"16\\\" cy=\\\"16\\\" r=\\\"12\\\" stroke=\\\"#585858\\\" fill=\\\"none\\\" stroke-width=\\\"1\\\"/>\\n\\t\\t\\t\\n\\t\\t\\t<path\\n\\t\\t\\t\\td=\\\"M 6.75,14 L6.75,18 L14,18 L14,24.75 L18,24.75 L18,18 L24.75,18 L24.75,14 L18,14 L18,6.75 L14,6.75 L14,14z\\\"\\n\\t\\t\\t\\tid=\\\"path92\\\"\\n\\t\\t\\t\\tstroke=\\\"#585858\\\"\\n\\t\\t\\t\\tstyle=\\\"fill:none;stroke-width:1\\\" />\\n\\t\\t\\n\\t\\t</g>\\n\\t\\n\\t</g>\\n\\t\\n\\t<text id=\\\"text_name\\\" x=\\\"26\\\" y=\\\"26\\\" oryx:align=\\\"left top\\\"/>\\n\\t\\n  </g>\\t\\n\\t\\n</svg>\\n\",\n        \"icon\" : \"gateway/eventbased.png\",\n        \"groups\" : [ \"网关列表\" ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"asynchronousdefinitionpackage\", \"exclusivedefinitionpackage\", \"sequencefloworderpackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"sequence_start\", \"GatewaysMorph\", \"sequence_end\", \"all\" ]\n    }, {\n        \"type\" : \"node\",\n        \"id\" : \"BoundaryErrorEvent\",\n        \"title\" : \"边界错误事件\",\n        \"description\" : \"一个捕捉BPMN异常的边界事件\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n   xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\n   width=\\\"40\\\"\\n   height=\\\"40\\\"\\n   version=\\\"1.0\\\">\\n  <defs></defs>\\n  <oryx:magnets>\\n  \\t<oryx:magnet oryx:cx=\\\"16\\\" oryx:cy=\\\"16\\\" oryx:default=\\\"yes\\\" />\\n  </oryx:magnets>\\n  <oryx:docker oryx:cx=\\\"16\\\" oryx:cy=\\\"16\\\" />\\n  <g pointer-events=\\\"fill\\\">\\n    <circle id=\\\"bg_frame\\\" cx=\\\"16\\\" cy=\\\"16\\\" r=\\\"15\\\" stroke=\\\"#585858\\\" fill=\\\"#ffffff\\\" stroke-width=\\\"1\\\"/>\\n    <circle id=\\\"frame\\\" cx=\\\"16\\\" cy=\\\"16\\\" r=\\\"12\\\" stroke=\\\"#585858\\\" fill=\\\"none\\\" stroke-width=\\\"1\\\"/>\\n    \\n    <path\\n         stroke=\\\"#585858\\\"\\n         style=\\\"fill:none;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10\\\"\\n         d=\\\"M 22.820839,11.171502 L 19.36734,24.58992 L 13.54138,14.281819 L 9.3386512,20.071607 L 13.048949,6.8323057 L 18.996148,16.132659 L 22.820839,11.171502 z\\\"\\n         id=\\\"errorPolygon\\\" />\\n\\t<text font-size=\\\"11\\\" \\n\\t\\tid=\\\"text_name\\\" \\n\\t\\tx=\\\"16\\\" y=\\\"33\\\" \\n\\t\\toryx:align=\\\"top center\\\" \\n\\t\\tstroke=\\\"#373e48\\\"\\n\\t></text>\\n  </g>\\n</svg>\",\n        \"icon\" : \"catching/error.png\",\n        \"groups\" : [ \"边界事件\" ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"errorrefpackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"sequence_start\", \"BoundaryEventsMorph\", \"IntermediateEventOnActivityBoundary\" ]\n    }, {\n        \"type\" : \"node\",\n        \"id\" : \"BoundaryTimerEvent\",\n        \"title\" : \"定时边界事件\",\n        \"description\" : \"一个定时触发的边界事件\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n   xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\n   width=\\\"40\\\"\\n   height=\\\"40\\\"\\n   version=\\\"1.0\\\">\\n  <defs></defs>\\n  <oryx:magnets>\\n  \\t<oryx:magnet oryx:cx=\\\"16\\\" oryx:cy=\\\"16\\\" oryx:default=\\\"yes\\\" />\\n  </oryx:magnets>\\n  <oryx:docker oryx:cx=\\\"16\\\" oryx:cy=\\\"16\\\" />\\n  <g pointer-events=\\\"fill\\\">\\n    <circle \\n    \\tid=\\\"bg_frame\\\" \\n    \\tcx=\\\"16\\\" \\n    \\tcy=\\\"16\\\" \\n    \\tr=\\\"15\\\" \\n    \\tstroke=\\\"#585858\\\" \\n    \\tfill=\\\"#ffffff\\\" \\n    \\tstroke-width=\\\"1\\\"\\n    \\tstyle=\\\"stroke-dasharray: 5.5, 3\\\" />\\n    \\t\\n    <circle \\n    \\tid=\\\"frame2_non_interrupting\\\" \\n    \\tcx=\\\"16\\\" \\n    \\tcy=\\\"16\\\" \\n    \\tr=\\\"12\\\" \\n    \\tstroke=\\\"#585858\\\" \\n    \\tfill=\\\"none\\\" \\n    \\tstroke-width=\\\"1\\\"\\n    \\tstyle=\\\"stroke-dasharray: 4.5, 3\\\" />\\n    \\n    <circle id=\\\"frame\\\" cx=\\\"16\\\" cy=\\\"16\\\" r=\\\"15\\\" stroke=\\\"#585858\\\" fill=\\\"none\\\" stroke-width=\\\"1\\\"/>\\n    <circle id=\\\"frame2\\\" cx=\\\"16\\\" cy=\\\"16\\\" r=\\\"12\\\" stroke=\\\"#585858\\\" fill=\\\"none\\\" stroke-width=\\\"1\\\"/>\\n    \\n    <path id=\\\"path1\\\" transform=\\\"translate(6,6)\\\"\\n    \\td=\\\"M 10 0 C 4.4771525 0 0 4.4771525 0 10 C 0 15.522847 4.4771525 20 10 20 C 15.522847 20 20 15.522847 20 10 C 20 4.4771525 15.522847 1.1842379e-15 10 0 z M 9.09375 1.03125 C 9.2292164 1.0174926 9.362825 1.0389311 9.5 1.03125 L 9.5 3.5 L 10.5 3.5 L 10.5 1.03125 C 15.063526 1.2867831 18.713217 4.9364738 18.96875 9.5 L 16.5 9.5 L 16.5 10.5 L 18.96875 10.5 C 18.713217 15.063526 15.063526 18.713217 10.5 18.96875 L 10.5 16.5 L 9.5 16.5 L 9.5 18.96875 C 4.9364738 18.713217 1.2867831 15.063526 1.03125 10.5 L 3.5 10.5 L 3.5 9.5 L 1.03125 9.5 C 1.279102 5.0736488 4.7225326 1.4751713 9.09375 1.03125 z M 9.5 5 L 9.5 8.0625 C 8.6373007 8.2844627 8 9.0680195 8 10 C 8 11.104569 8.8954305 12 10 12 C 10.931981 12 11.715537 11.362699 11.9375 10.5 L 14 10.5 L 14 9.5 L 11.9375 9.5 C 11.756642 8.7970599 11.20294 8.2433585 10.5 8.0625 L 10.5 5 L 9.5 5 z \\\"  \\n    \\tfill=\\\"#585858\\\" stroke=\\\"none\\\" />\\n    \\t\\n\\t<text font-size=\\\"11\\\" \\n\\t\\tid=\\\"text_name\\\" \\n\\t\\tx=\\\"16\\\" y=\\\"33\\\" \\n\\t\\toryx:align=\\\"top center\\\" \\n\\t\\tstroke=\\\"#373e48\\\"\\n\\t></text>\\n  </g>\\n</svg>\",\n        \"icon\" : \"catching/timer.png\",\n        \"groups\" : [ \"边界事件\" ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"timercycledefinitionpackage\", \"timerdatedefinitionpackage\", \"timerdurationdefinitionpackage\", \"timerenddatedefinitionpackage\", \"cancelactivitypackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"sequence_start\", \"BoundaryEventsMorph\", \"IntermediateEventOnActivityBoundary\" ]\n    }, {\n        \"type\" : \"node\",\n        \"id\" : \"BoundarySignalEvent\",\n        \"title\" : \"边界信号事件\",\n        \"description\" : \"一个信号触发的边界事件\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n   xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\n   width=\\\"40\\\"\\n   height=\\\"40\\\"\\n   version=\\\"1.0\\\">\\n  <defs></defs>\\n  <oryx:magnets>\\n  \\t<oryx:magnet oryx:cx=\\\"16\\\" oryx:cy=\\\"16\\\" oryx:default=\\\"yes\\\" />\\n  </oryx:magnets>\\n  <oryx:docker oryx:cx=\\\"16\\\" oryx:cy=\\\"16\\\" />\\n  <g pointer-events=\\\"fill\\\">\\n    <circle \\n    \\tid=\\\"bg_frame\\\" \\n    \\tcx=\\\"16\\\" \\n    \\tcy=\\\"16\\\" \\n    \\tr=\\\"15\\\" \\n    \\tstroke=\\\"#585858\\\" \\n    \\tfill=\\\"#ffffff\\\" \\n    \\tstroke-width=\\\"1\\\"\\n    \\tstyle=\\\"stroke-dasharray: 5.5, 3\\\" />\\n    \\t\\n    <circle \\n    \\tid=\\\"frame2_non_interrupting\\\" \\n    \\tcx=\\\"16\\\" \\n    \\tcy=\\\"16\\\" \\n    \\tr=\\\"12\\\" \\n    \\tstroke=\\\"#585858\\\" \\n    \\tfill=\\\"none\\\" \\n    \\tstroke-width=\\\"1\\\"\\n    \\tstyle=\\\"stroke-dasharray: 4.5, 3\\\" />\\n    \\n    <circle id=\\\"frame\\\" cx=\\\"16\\\" cy=\\\"16\\\" r=\\\"15\\\" stroke=\\\"#585858\\\" fill=\\\"none\\\" stroke-width=\\\"1\\\"/>\\n    <circle id=\\\"frame2\\\" cx=\\\"16\\\" cy=\\\"16\\\" r=\\\"12\\\" stroke=\\\"#585858\\\" fill=\\\"none\\\" stroke-width=\\\"1\\\"/>\\n\\t<path\\n\\t   id=\\\"signalCatching\\\"\\n\\t   stroke=\\\"#585858\\\"\\n       d=\\\"M 8.7124971,21.247342 L 23.333334,21.247342 L 16.022915,8.5759512 L 8.7124971,21.247342 z\\\"\\n       style=\\\"fill:none;stroke-width:1.4;stroke-miterlimit:4;stroke-dasharray:none\\\" />\\n\\t<text font-size=\\\"11\\\" \\n\\t\\tid=\\\"text_name\\\" \\n\\t\\tx=\\\"16\\\" y=\\\"33\\\" \\n\\t\\toryx:align=\\\"top center\\\" \\n\\t\\tstroke=\\\"#373e48\\\"\\n\\t></text>\\n  </g>\\n</svg>\",\n        \"icon\" : \"catching/signal.png\",\n        \"groups\" : [ \"边界事件\" ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"signalrefpackage\", \"cancelactivitypackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"sequence_start\", \"BoundaryEventsMorph\", \"IntermediateEventOnActivityBoundary\" ]\n    }, {\n        \"type\" : \"node\",\n        \"id\" : \"BoundaryMessageEvent\",\n        \"title\" : \"边界消息事件\",\n        \"description\" : \"一个边界消息事件\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n   xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\n   width=\\\"40\\\"\\n   height=\\\"40\\\"\\n   version=\\\"1.0\\\">\\n  <defs></defs>\\n  <oryx:magnets>\\n  \\t<oryx:magnet oryx:cx=\\\"16\\\" oryx:cy=\\\"16\\\" oryx:default=\\\"yes\\\" />\\n  </oryx:magnets>\\n  <oryx:docker oryx:cx=\\\"16\\\" oryx:cy=\\\"16\\\" />\\n  <g pointer-events=\\\"fill\\\">\\n    <circle \\n    \\tid=\\\"bg_frame\\\" \\n    \\tcx=\\\"16\\\" \\n    \\tcy=\\\"16\\\" \\n    \\tr=\\\"15\\\" \\n    \\tstroke=\\\"#585858\\\" \\n    \\tfill=\\\"#ffffff\\\" \\n    \\tstroke-width=\\\"1\\\"\\n    \\tstyle=\\\"stroke-dasharray: 5.5, 3\\\" />\\n    \\t\\n    <circle \\n    \\tid=\\\"frame2_non_interrupting\\\" \\n    \\tcx=\\\"16\\\" \\n    \\tcy=\\\"16\\\" \\n    \\tr=\\\"12\\\" \\n    \\tstroke=\\\"#585858\\\" \\n    \\tfill=\\\"none\\\" \\n    \\tstroke-width=\\\"1\\\"\\n    \\tstyle=\\\"stroke-dasharray: 4.5, 3\\\" />\\n    \\t\\n    <circle id=\\\"frame\\\" cx=\\\"16\\\" cy=\\\"16\\\" r=\\\"15\\\" stroke=\\\"#585858\\\" fill=\\\"none\\\" stroke-width=\\\"1\\\"/>\\n    <circle id=\\\"frame2\\\" cx=\\\"16\\\" cy=\\\"16\\\" r=\\\"12\\\" stroke=\\\"#585858\\\" fill=\\\"none\\\" stroke-width=\\\"1\\\"/>\\n    \\n\\t<g id=\\\"messageCatching\\\">\\n\\t\\t<path transform=\\\"translate(7,7)\\\" id=\\\"path1\\\" stroke=\\\"none\\\" fill=\\\"#585858\\\" stroke-width=\\\"1\\\" d=\\\"M 1 3 L 9 11 L 17 3 L 1 3 z M 1 5 L 1 13 L 5 9 L 1 5 z M 17 5 L 13 9 L 17 13 L 17 5 z M 6 10 L 1 15 L 17 15 L 12 10 L 9 13 L 6 10 z \\\"/>\\n\\t</g>\\n\\t<text font-size=\\\"11\\\" \\n\\t\\tid=\\\"text_name\\\" \\n\\t\\tx=\\\"16\\\" y=\\\"33\\\" \\n\\t\\toryx:align=\\\"top center\\\" \\n\\t\\tstroke=\\\"#373e48\\\"\\n\\t></text>\\n\\t\\n  </g>\\n</svg>\",\n        \"icon\" : \"catching/message.png\",\n        \"groups\" : [ \"边界事件\" ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"messagerefpackage\", \"cancelactivitypackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"sequence_start\", \"BoundaryEventsMorph\", \"IntermediateEventOnActivityBoundary\" ]\n    }, {\n        \"type\" : \"node\",\n        \"id\" : \"BoundaryCancelEvent\",\n        \"title\" : \"边界取消事件\",\n        \"description\" : \"一个边界取消事件\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n   xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\n   width=\\\"40\\\"\\n   height=\\\"40\\\"\\n   version=\\\"1.0\\\">\\n  <defs></defs>\\n  <oryx:magnets>\\n  \\t<oryx:magnet oryx:cx=\\\"16\\\" oryx:cy=\\\"16\\\" oryx:default=\\\"yes\\\" />\\n  </oryx:magnets>\\n  <oryx:docker oryx:cx=\\\"16\\\" oryx:cy=\\\"16\\\" />\\n  <g pointer-events=\\\"fill\\\">\\n  \\n    <circle id=\\\"bg_frame\\\" cx=\\\"16\\\" cy=\\\"16\\\" r=\\\"15\\\" stroke=\\\"#585858\\\" fill=\\\"#ffffff\\\" stroke-width=\\\"1\\\"/>\\n    <circle id=\\\"frame\\\" cx=\\\"16\\\" cy=\\\"16\\\" r=\\\"12\\\" stroke=\\\"#585858\\\" fill=\\\"none\\\" stroke-width=\\\"1\\\"/>\\n    \\n    <path\\n       d=\\\"M 7.2839105,10.27369 L 10.151395,7.4062062 L 15.886362,13.141174 L 21.621331,7.4062056 L 24.488814,10.273689 L 18.753846,16.008657 L 24.488815,21.743626 L 21.621331,24.611111 L 15.886362,18.876142 L 10.151394,24.611109 L 7.283911,21.743625 L 13.018878,16.008658 L 7.2839105,10.27369 z\\\"\\n       id=\\\"cancelCross\\\" fill=\\\"none\\\" stroke=\\\"#585858\\\" stroke-width=\\\"1.7\\\" />\\n\\t<text font-size=\\\"11\\\" \\n\\t\\tid=\\\"text_name\\\" \\n\\t\\tx=\\\"16\\\" y=\\\"33\\\" \\n\\t\\toryx:align=\\\"top center\\\" \\n\\t\\tstroke=\\\"#373e48\\\"\\n\\t></text>\\n  </g>\\n</svg>\",\n        \"icon\" : \"catching/cancel.png\",\n        \"groups\" : [ \"边界事件\" ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"sequence_start\", \"BoundaryEventsMorph\", \"IntermediateEventOnActivityBoundary\" ]\n    }, {\n        \"type\" : \"node\",\n        \"id\" : \"BoundaryCompensationEvent\",\n        \"title\" : \"边界修正事件\",\n        \"description\" : \"一个边界修正事件\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n   xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\n   width=\\\"40\\\"\\n   height=\\\"40\\\"\\n   version=\\\"1.0\\\">\\n  <defs></defs>\\n  <oryx:magnets>\\n  \\t<oryx:magnet oryx:cx=\\\"16\\\" oryx:cy=\\\"16\\\" oryx:default=\\\"yes\\\" />\\n  </oryx:magnets>\\n  <oryx:docker oryx:cx=\\\"16\\\" oryx:cy=\\\"16\\\" />\\n  <g pointer-events=\\\"fill\\\">\\n\\t\\n    <circle id=\\\"bg_frame\\\" cx=\\\"16\\\" cy=\\\"16\\\" r=\\\"15\\\" stroke=\\\"#585858\\\" fill=\\\"#ffffff\\\" stroke-width=\\\"1\\\"/>\\n    <circle id=\\\"frame\\\" cx=\\\"16\\\" cy=\\\"16\\\" r=\\\"12\\\" stroke=\\\"#585858\\\" fill=\\\"#ffffff\\\" stroke-width=\\\"1\\\"/>\\n    \\n    <polygon id=\\\"poly1\\\" stroke=\\\"#585858\\\" fill=\\\"none\\\" stroke-width=\\\"1.4\\\" points=\\\"15,9 15,23 8,16\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-miterlimit=\\\"10\\\" />\\n    <polygon id=\\\"poly2\\\" stroke=\\\"#585858\\\" fill=\\\"none\\\" stroke-width=\\\"1.4\\\" points=\\\"22,9 22,23 15,16\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" stroke-miterlimit=\\\"10\\\" />\\n\\t<text font-size=\\\"11\\\" \\n\\t\\tid=\\\"text_name\\\" \\n\\t\\tx=\\\"16\\\" y=\\\"33\\\" \\n\\t\\toryx:align=\\\"top center\\\" \\n\\t\\tstroke=\\\"#373e48\\\"\\n\\t></text>\\n </g>\\n</svg>\",\n        \"icon\" : \"catching/compensation.png\",\n        \"groups\" : [ \"边界事件\" ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"BoundaryEventsMorph\", \"IntermediateEventOnActivityBoundary\", \"all\" ]\n    }, {\n        \"type\" : \"node\",\n        \"id\" : \"CatchTimerEvent\",\n        \"title\" : \"中间定时器捕获事件\",\n        \"description\" : \"定时器触发的中间捕获事件\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n   xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\n   width=\\\"40\\\"\\n   height=\\\"40\\\"\\n   version=\\\"1.0\\\">\\n  <defs></defs>\\n  <oryx:magnets>\\n  \\t<oryx:magnet oryx:cx=\\\"16\\\" oryx:cy=\\\"16\\\" oryx:default=\\\"yes\\\" />\\n  </oryx:magnets>\\n  <oryx:docker oryx:cx=\\\"16\\\" oryx:cy=\\\"16\\\" />\\n  <g pointer-events=\\\"fill\\\">\\n    <circle \\n    \\tid=\\\"bg_frame\\\" \\n    \\tcx=\\\"16\\\" \\n    \\tcy=\\\"16\\\" \\n    \\tr=\\\"15\\\" \\n    \\tstroke=\\\"#585858\\\" \\n    \\tfill=\\\"#ffffff\\\" \\n    \\tstroke-width=\\\"1\\\"\\n    \\tstyle=\\\"stroke-dasharray: 5.5, 3\\\" />\\n    \\t\\n    <circle \\n    \\tid=\\\"frame2_non_interrupting\\\" \\n    \\tcx=\\\"16\\\" \\n    \\tcy=\\\"16\\\" \\n    \\tr=\\\"12\\\" \\n    \\tstroke=\\\"#585858\\\" \\n    \\tfill=\\\"none\\\" \\n    \\tstroke-width=\\\"1\\\"\\n    \\tstyle=\\\"stroke-dasharray: 4.5, 3\\\" />\\n    \\n    <circle id=\\\"frame\\\" cx=\\\"16\\\" cy=\\\"16\\\" r=\\\"15\\\" stroke=\\\"#585858\\\" fill=\\\"none\\\" stroke-width=\\\"1\\\"/>\\n    <circle id=\\\"frame2\\\" cx=\\\"16\\\" cy=\\\"16\\\" r=\\\"12\\\" stroke=\\\"#585858\\\" fill=\\\"none\\\" stroke-width=\\\"1\\\"/>\\n    \\n    <path id=\\\"path1\\\" transform=\\\"translate(6,6)\\\"\\n    \\td=\\\"M 10 0 C 4.4771525 0 0 4.4771525 0 10 C 0 15.522847 4.4771525 20 10 20 C 15.522847 20 20 15.522847 20 10 C 20 4.4771525 15.522847 1.1842379e-15 10 0 z M 9.09375 1.03125 C 9.2292164 1.0174926 9.362825 1.0389311 9.5 1.03125 L 9.5 3.5 L 10.5 3.5 L 10.5 1.03125 C 15.063526 1.2867831 18.713217 4.9364738 18.96875 9.5 L 16.5 9.5 L 16.5 10.5 L 18.96875 10.5 C 18.713217 15.063526 15.063526 18.713217 10.5 18.96875 L 10.5 16.5 L 9.5 16.5 L 9.5 18.96875 C 4.9364738 18.713217 1.2867831 15.063526 1.03125 10.5 L 3.5 10.5 L 3.5 9.5 L 1.03125 9.5 C 1.279102 5.0736488 4.7225326 1.4751713 9.09375 1.03125 z M 9.5 5 L 9.5 8.0625 C 8.6373007 8.2844627 8 9.0680195 8 10 C 8 11.104569 8.8954305 12 10 12 C 10.931981 12 11.715537 11.362699 11.9375 10.5 L 14 10.5 L 14 9.5 L 11.9375 9.5 C 11.756642 8.7970599 11.20294 8.2433585 10.5 8.0625 L 10.5 5 L 9.5 5 z \\\"  \\n    \\tfill=\\\"#585858\\\" stroke=\\\"none\\\" />\\n    \\t\\n\\t<text font-size=\\\"11\\\" \\n\\t\\tid=\\\"text_name\\\" \\n\\t\\tx=\\\"16\\\" y=\\\"33\\\" \\n\\t\\toryx:align=\\\"top center\\\" \\n\\t\\tstroke=\\\"#373e48\\\"\\n\\t></text>\\n  </g>\\n</svg>\",\n        \"icon\" : \"catching/timer.png\",\n        \"groups\" : [ \"中间捕获事件列表\" ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"executionlistenerspackage\", \"timercycledefinitionpackage\", \"timerdatedefinitionpackage\", \"timerdurationdefinitionpackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"sequence_start\", \"sequence_end\", \"CatchEventsMorph\", \"all\" ]\n    }, {\n        \"type\" : \"node\",\n        \"id\" : \"CatchSignalEvent\",\n        \"title\" : \"中间信号捕获事件\",\n        \"description\" : \"信号触发的捕获事件\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n   xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\n   width=\\\"40\\\"\\n   height=\\\"40\\\"\\n   version=\\\"1.0\\\">\\n  <defs></defs>\\n  <oryx:magnets>\\n  \\t<oryx:magnet oryx:cx=\\\"16\\\" oryx:cy=\\\"16\\\" oryx:default=\\\"yes\\\" />\\n  </oryx:magnets>\\n  <oryx:docker oryx:cx=\\\"16\\\" oryx:cy=\\\"16\\\" />\\n  <g pointer-events=\\\"fill\\\">\\n    <circle \\n    \\tid=\\\"bg_frame\\\" \\n    \\tcx=\\\"16\\\" \\n    \\tcy=\\\"16\\\" \\n    \\tr=\\\"15\\\" \\n    \\tstroke=\\\"#585858\\\" \\n    \\tfill=\\\"#ffffff\\\" \\n    \\tstroke-width=\\\"1\\\"\\n    \\tstyle=\\\"stroke-dasharray: 5.5, 3\\\" />\\n    \\t\\n    <circle \\n    \\tid=\\\"frame2_non_interrupting\\\" \\n    \\tcx=\\\"16\\\" \\n    \\tcy=\\\"16\\\" \\n    \\tr=\\\"12\\\" \\n    \\tstroke=\\\"#585858\\\" \\n    \\tfill=\\\"none\\\" \\n    \\tstroke-width=\\\"1\\\"\\n    \\tstyle=\\\"stroke-dasharray: 4.5, 3\\\" />\\n    \\n    <circle id=\\\"frame\\\" cx=\\\"16\\\" cy=\\\"16\\\" r=\\\"15\\\" stroke=\\\"#585858\\\" fill=\\\"none\\\" stroke-width=\\\"1\\\"/>\\n    <circle id=\\\"frame2\\\" cx=\\\"16\\\" cy=\\\"16\\\" r=\\\"12\\\" stroke=\\\"#585858\\\" fill=\\\"none\\\" stroke-width=\\\"1\\\"/>\\n\\t<path\\n\\t   id=\\\"signalCatching\\\"\\n\\t   stroke=\\\"#585858\\\"\\n       d=\\\"M 8.7124971,21.247342 L 23.333334,21.247342 L 16.022915,8.5759512 L 8.7124971,21.247342 z\\\"\\n       style=\\\"fill:none;stroke-width:1.4;stroke-miterlimit:4;stroke-dasharray:none\\\" />\\n\\t<text font-size=\\\"11\\\" \\n\\t\\tid=\\\"text_name\\\" \\n\\t\\tx=\\\"16\\\" y=\\\"33\\\" \\n\\t\\toryx:align=\\\"top center\\\" \\n\\t\\tstroke=\\\"#373e48\\\"\\n\\t></text>\\n  </g>\\n</svg>\",\n        \"icon\" : \"catching/signal.png\",\n        \"groups\" : [ \"中间捕获事件列表\" ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"executionlistenerspackage\", \"signalrefpackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"sequence_start\", \"sequence_end\", \"CatchEventsMorph\", \"all\" ]\n    }, {\n        \"type\" : \"node\",\n        \"id\" : \"CatchMessageEvent\",\n        \"title\" : \"中间消息捕获事件\",\n        \"description\" : \"一个消息触发的中间捕获事件\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n   xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\n   width=\\\"40\\\"\\n   height=\\\"40\\\"\\n   version=\\\"1.0\\\">\\n  <defs></defs>\\n  <oryx:magnets>\\n  \\t<oryx:magnet oryx:cx=\\\"16\\\" oryx:cy=\\\"16\\\" oryx:default=\\\"yes\\\" />\\n  </oryx:magnets>\\n  <oryx:docker oryx:cx=\\\"16\\\" oryx:cy=\\\"16\\\" />\\n  <g pointer-events=\\\"fill\\\">\\n    <circle \\n    \\tid=\\\"bg_frame\\\" \\n    \\tcx=\\\"16\\\" \\n    \\tcy=\\\"16\\\" \\n    \\tr=\\\"15\\\" \\n    \\tstroke=\\\"#585858\\\" \\n    \\tfill=\\\"#ffffff\\\" \\n    \\tstroke-width=\\\"1\\\"\\n    \\tstyle=\\\"stroke-dasharray: 5.5, 3\\\" />\\n    \\t\\n    <circle \\n    \\tid=\\\"frame2_non_interrupting\\\" \\n    \\tcx=\\\"16\\\" \\n    \\tcy=\\\"16\\\" \\n    \\tr=\\\"12\\\" \\n    \\tstroke=\\\"#585858\\\" \\n    \\tfill=\\\"none\\\" \\n    \\tstroke-width=\\\"1\\\"\\n    \\tstyle=\\\"stroke-dasharray: 4.5, 3\\\" />\\n    \\t\\n    <circle id=\\\"frame\\\" cx=\\\"16\\\" cy=\\\"16\\\" r=\\\"15\\\" stroke=\\\"#585858\\\" fill=\\\"none\\\" stroke-width=\\\"1\\\"/>\\n    <circle id=\\\"frame2\\\" cx=\\\"16\\\" cy=\\\"16\\\" r=\\\"12\\\" stroke=\\\"#585858\\\" fill=\\\"none\\\" stroke-width=\\\"1\\\"/>\\n    \\n\\t<g id=\\\"messageCatching\\\">\\n\\t\\t<path transform=\\\"translate(7,7)\\\" id=\\\"path1\\\" stroke=\\\"none\\\" fill=\\\"#585858\\\" stroke-width=\\\"1\\\" d=\\\"M 1 3 L 9 11 L 17 3 L 1 3 z M 1 5 L 1 13 L 5 9 L 1 5 z M 17 5 L 13 9 L 17 13 L 17 5 z M 6 10 L 1 15 L 17 15 L 12 10 L 9 13 L 6 10 z \\\"/>\\n\\t</g>\\n\\t<text font-size=\\\"11\\\" \\n\\t\\tid=\\\"text_name\\\" \\n\\t\\tx=\\\"16\\\" y=\\\"33\\\" \\n\\t\\toryx:align=\\\"top center\\\" \\n\\t\\tstroke=\\\"#373e48\\\"\\n\\t></text>\\n\\t\\n  </g>\\n</svg>\",\n        \"icon\" : \"catching/message.png\",\n        \"groups\" : [ \"中间捕获事件列表\" ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"executionlistenerspackage\", \"messagerefpackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"sequence_start\", \"sequence_end\", \"CatchEventsMorph\", \"all\" ]\n    }, {\n        \"type\" : \"node\",\n        \"id\" : \"ThrowNoneEvent\",\n        \"title\" : \"中间抛出事件\",\n        \"description\" : \"无触发器的中间抛出事件\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n   xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\n   width=\\\"40\\\"\\n   height=\\\"40\\\"\\n   version=\\\"1.0\\\">\\n  <defs></defs>\\n  <oryx:magnets>\\n  \\t<oryx:magnet oryx:cx=\\\"16\\\" oryx:cy=\\\"16\\\" oryx:default=\\\"yes\\\" />\\n  </oryx:magnets>\\n  <oryx:docker oryx:cx=\\\"16\\\" oryx:cy=\\\"16\\\" />\\n  <g pointer-events=\\\"fill\\\">\\n  \\n    <circle id=\\\"bg_frame\\\" cx=\\\"16\\\" cy=\\\"16\\\" r=\\\"15\\\" stroke=\\\"#585858\\\" fill=\\\"#ffffff\\\" stroke-width=\\\"1\\\"/>\\n    <circle id=\\\"frame\\\" cx=\\\"16\\\" cy=\\\"16\\\" r=\\\"12\\\" stroke=\\\"#585858\\\" fill=\\\"none\\\" stroke-width=\\\"1\\\"/>\\n\\t<text font-size=\\\"11\\\" \\n\\t\\tid=\\\"text_name\\\" \\n\\t\\tx=\\\"16\\\" y=\\\"33\\\" \\n\\t\\toryx:align=\\\"top center\\\" \\n\\t\\tstroke=\\\"#373e48\\\"\\n\\t></text>\\n  </g>\\n</svg>\",\n        \"icon\" : \"throwing/none.png\",\n        \"groups\" : [ \"中间抛出事件\" ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"executionlistenerspackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"ThrowEventsMorph\", \"sequence_start\", \"sequence_end\", \"all\" ]\n    }, {\n        \"type\" : \"node\",\n        \"id\" : \"ThrowSignalEvent\",\n        \"title\" : \"信号中间抛出事件\",\n        \"description\" : \"一个信号触发的中间抛出事件\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n   xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\n   width=\\\"40\\\"\\n   height=\\\"40\\\"\\n   version=\\\"1.0\\\">\\n  <defs></defs>\\n  <oryx:magnets>\\n  \\t<oryx:magnet oryx:cx=\\\"16\\\" oryx:cy=\\\"16\\\" oryx:default=\\\"yes\\\" />\\n  </oryx:magnets>\\n  <oryx:docker oryx:cx=\\\"16\\\" oryx:cy=\\\"16\\\" />\\n  <g pointer-events=\\\"fill\\\">\\n    <circle id=\\\"bg_frame\\\" cx=\\\"16\\\" cy=\\\"16\\\" r=\\\"15\\\" stroke=\\\"#585858\\\" fill=\\\"#ffffff\\\" stroke-width=\\\"1\\\"/>\\n    <circle id=\\\"frame\\\" cx=\\\"16\\\" cy=\\\"16\\\" r=\\\"12\\\" stroke=\\\"#585858\\\" fill=\\\"none\\\" stroke-width=\\\"1\\\"/>\\n    <path\\n\\t   id=\\\"signalThrowing\\\"\\n       d=\\\"M 8.7124971,21.247342 L 23.333334,21.247342 L 16.022915,8.5759512 L 8.7124971,21.247342 z\\\"\\n       fill=\\\"#585858\\\"\\n       stroke=\\\"#585858\\\"\\n       style=\\\"stroke-width:1.4;stroke-miterlimit:4;stroke-dasharray:none\\\" />\\n\\t<text font-size=\\\"11\\\" \\n\\t\\tid=\\\"text_name\\\" \\n\\t\\tx=\\\"16\\\" y=\\\"33\\\" \\n\\t\\toryx:align=\\\"top center\\\" \\n\\t\\tstroke=\\\"#373e48\\\"\\n\\t></text>\\n  </g>\\n</svg>\",\n        \"icon\" : \"throwing/signal.png\",\n        \"groups\" : [ \"中间抛出事件\" ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"executionlistenerspackage\", \"signalrefpackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"ThrowEventsMorph\", \"sequence_start\", \"sequence_end\", \"all\" ]\n    }, {\n        \"type\" : \"node\",\n        \"id\" : \"EndNoneEvent\",\n        \"title\" : \"结束任务\",\n        \"description\" : \"一个无触发器的结束任务\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n   xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\n   width=\\\"40\\\"\\n   height=\\\"40\\\"\\n   version=\\\"1.0\\\">\\n  <defs></defs>\\n  <oryx:magnets>\\n  \\t<oryx:magnet oryx:cx=\\\"16\\\" oryx:cy=\\\"16\\\" oryx:default=\\\"yes\\\" />\\n  </oryx:magnets>\\n  <g pointer-events=\\\"fill\\\">\\n    <circle id=\\\"bg_frame\\\" cx=\\\"16\\\" cy=\\\"16\\\" r=\\\"14\\\" stroke=\\\"#585858\\\" fill=\\\"#ffffff\\\" stroke-width=\\\"3\\\"/>\\n\\t<text font-size=\\\"11\\\" \\n\\t\\tid=\\\"text_name\\\" \\n\\t\\tx=\\\"16\\\" y=\\\"32\\\" \\n\\t\\toryx:align=\\\"top center\\\" \\n\\t\\tstroke=\\\"#373e48\\\"\\n\\t></text>\\n  </g>\\n</svg>\",\n        \"icon\" : \"endevent/none.png\",\n        \"groups\" : [ \"结束任务列表\" ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"executionlistenerspackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"EndEventsMorph\", \"sequence_end\", \"all\" ]\n    }, {\n        \"type\" : \"node\",\n        \"id\" : \"EndErrorEvent\",\n        \"title\" : \"结束错误任务\",\n        \"description\" : \"An end event that throws an error event\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n   xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\n   width=\\\"40\\\"\\n   height=\\\"40\\\"\\n   version=\\\"1.0\\\">\\n  <defs></defs>\\n  <oryx:magnets>\\n  \\t<oryx:magnet oryx:cx=\\\"16\\\" oryx:cy=\\\"16\\\" oryx:default=\\\"yes\\\" />\\n  </oryx:magnets>\\n  <oryx:docker oryx:cx=\\\"16\\\" oryx:cy=\\\"16\\\" />\\n  <g pointer-events=\\\"fill\\\">\\n    <circle id=\\\"bg_frame\\\" cx=\\\"16\\\" cy=\\\"16\\\" r=\\\"14\\\" stroke=\\\"#585858\\\" fill=\\\"#ffffff\\\" stroke-width=\\\"3\\\"/>\\n    \\n    <path\\n         fill=\\\"#585858\\\"\\n         stroke=\\\"#585858\\\"\\n         style=\\\"stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10\\\"\\n         d=\\\"M 22.820839,11.171502 L 19.36734,24.58992 L 13.54138,14.281819 L 9.3386512,20.071607 L 13.048949,6.8323057 L 18.996148,16.132659 L 22.820839,11.171502 z\\\"\\n         id=\\\"errorPolygon\\\" />\\n\\t<text font-size=\\\"11\\\" \\n\\t\\tid=\\\"text_name\\\" \\n\\t\\tx=\\\"16\\\" y=\\\"32\\\" \\n\\t\\toryx:align=\\\"top center\\\" \\n\\t\\tstroke=\\\"#373e48\\\"\\n\\t></text>\\n  </g>\\n</svg>\",\n        \"icon\" : \"endevent/error.png\",\n        \"groups\" : [ \"结束任务列表\" ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"executionlistenerspackage\", \"errorrefpackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"EndEventsMorph\", \"sequence_end\", \"all\" ]\n    }, {\n        \"type\" : \"node\",\n        \"id\" : \"EndCancelEvent\",\n        \"title\" : \"结束取消任务\",\n        \"description\" : \"A cancel end event\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n   xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\n   width=\\\"40\\\"\\n   height=\\\"40\\\"\\n   version=\\\"1.0\\\">\\n  <defs></defs>\\n  <oryx:magnets>\\n  \\t<oryx:magnet oryx:cx=\\\"16\\\" oryx:cy=\\\"16\\\" oryx:default=\\\"yes\\\" />\\n  </oryx:magnets>\\n  <g pointer-events=\\\"fill\\\">\\n    <circle id=\\\"bg_frame\\\" cx=\\\"16\\\" cy=\\\"16\\\" r=\\\"14\\\" stroke=\\\"#585858\\\" fill=\\\"#ffffff\\\" stroke-width=\\\"3\\\"/>\\n    \\n    <path id=\\\"path1\\\" d=\\\"M 9 9 L 23 23 M 9 23 L 23 9\\\" fill=\\\"none\\\" stroke=\\\"#585858\\\" stroke-width=\\\"5\\\" />\\n\\t<text font-size=\\\"11\\\" \\n\\t\\tid=\\\"text_name\\\" \\n\\t\\tx=\\\"16\\\" y=\\\"32\\\" \\n\\t\\toryx:align=\\\"top center\\\" \\n\\t\\tstroke=\\\"#373e48\\\"\\n\\t></text>\\n  </g>\\n</svg>\",\n        \"icon\" : \"endevent/cancel.png\",\n        \"groups\" : [ \"结束任务列表\" ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"executionlistenerspackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"EndEventsMorph\", \"sequence_end\", \"all\" ]\n    }, {\n        \"type\" : \"node\",\n        \"id\" : \"EndTerminateEvent\",\n        \"title\" : \"终结任务\",\n        \"description\" : \"A terminate end event\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n   xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\n   width=\\\"40\\\"\\n   height=\\\"40\\\"\\n   version=\\\"1.0\\\">\\n  <defs></defs>\\n  <oryx:magnets>\\n  \\t<oryx:magnet oryx:cx=\\\"16\\\" oryx:cy=\\\"16\\\" oryx:default=\\\"yes\\\" />\\n  </oryx:magnets>\\n  <g pointer-events=\\\"fill\\\">\\n    <circle id=\\\"bg_frame\\\" cx=\\\"16\\\" cy=\\\"16\\\" r=\\\"14\\\" stroke=\\\"#585858\\\" fill=\\\"#ffffff\\\" stroke-width=\\\"3\\\"/>\\n    \\n    <circle id=\\\"circle1\\\" cx=\\\"16\\\" cy=\\\"16\\\" r=\\\"9\\\" stroke=\\\"#585858\\\" fill=\\\"#585858\\\" stroke-width=\\\"1\\\"/>\\n\\t<text font-size=\\\"11\\\" \\n\\t\\tid=\\\"text_name\\\" \\n\\t\\tx=\\\"16\\\" y=\\\"32\\\" \\n\\t\\toryx:align=\\\"top center\\\" \\n\\t\\tstroke=\\\"#373e48\\\"\\n\\t></text>\\n  </g>\\n</svg>\",\n        \"icon\" : \"endevent/terminate.png\",\n        \"groups\" : [ \"结束任务列表\" ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"executionlistenerspackage\", \"terminateAllpackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"EndEventsMorph\", \"sequence_end\", \"all\" ]\n    }, {\n        \"type\" : \"node\",\n        \"id\" : \"Pool\",\n        \"title\" : \"池\",\n        \"description\" : \"A pool to stucture the process definition\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n   xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:svg=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\n   xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\"\\n   width=\\\"600\\\"\\n   height=\\\"250\\\"\\n   version=\\\"1.0\\\">\\n  <defs></defs>\\n  <oryx:magnets>\\n  \\t<oryx:magnet oryx:cx=\\\"0\\\" oryx:cy=\\\"124\\\" oryx:anchors=\\\"left\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"299\\\" oryx:cy=\\\"249\\\" oryx:anchors=\\\"bottom\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"599\\\" oryx:cy=\\\"124\\\" oryx:anchors=\\\"right\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"299\\\" oryx:cy=\\\"0\\\" oryx:anchors=\\\"top\\\" />\\n  \\t<oryx:magnet oryx:cx=\\\"299\\\" oryx:cy=\\\"124\\\" oryx:default=\\\"yes\\\" />\\n  </oryx:magnets>\\n  <g pointer-events=\\\"none\\\" >\\n    <defs>\\n\\t\\t<radialGradient id=\\\"background\\\" cx=\\\"0%\\\" cy=\\\"10%\\\" r=\\\"100%\\\" fx=\\\"20%\\\" fy=\\\"10%\\\">\\n\\t\\t\\t<stop offset=\\\"0%\\\" stop-color=\\\"#ffffff\\\" stop-opacity=\\\"1\\\"/>\\n\\t\\t\\t<stop id=\\\"fill_el\\\" offset=\\\"100%\\\" stop-color=\\\"#ffffff\\\" stop-opacity=\\\"1\\\"/>\\n\\t\\t</radialGradient>\\n\\t</defs>\\n\\t  \\t\\n  \\t<rect\\n  \\t\\tid=\\\"border\\\"\\n  \\t\\tclass=\\\"stripable-element-force\\\"\\n  \\t\\toryx:resize=\\\"vertical horizontal\\\"\\n  \\t\\tx=\\\"0\\\"\\n  \\t\\ty=\\\"0\\\"\\n  \\t\\twidth=\\\"600\\\"\\n  \\t\\theight=\\\"250\\\"\\n  \\t\\tfill=\\\"none\\\"\\n  \\t\\tstroke-width=\\\"9\\\"\\n  \\t\\tstroke=\\\"none\\\"\\n  \\t\\tvisibility=\\\"visible\\\"\\n  \\t\\tpointer-events=\\\"stroke\\\"\\n  \\t/>\\n    <rect\\n    \\tid=\\\"c\\\"\\n    \\toryx:resize=\\\"vertical horizontal\\\"\\n    \\tx=\\\"0\\\"\\n    \\ty=\\\"0\\\"\\n    \\twidth=\\\"600\\\" \\n    \\theight=\\\"250\\\" \\n    \\tstroke=\\\"black\\\" \\n    \\tfill=\\\"url(#background) white\\\"\\n    \\tfill-opacity=\\\"0.3\\\" \\n    />\\n    \\n\\t<rect \\n\\t\\tid=\\\"caption\\\"\\n\\t\\toryx:anchors=\\\"left top bottom\\\"\\n\\t\\tx=\\\"0\\\"\\n\\t\\ty=\\\"0\\\"\\n\\t\\twidth=\\\"30\\\"\\n\\t\\theight=\\\"250\\\"\\n\\t\\tstroke=\\\"black\\\"\\n\\t\\tstroke-width=\\\"1\\\"\\n\\t\\tfill=\\\"url(#background) white\\\"\\n\\t\\tpointer-events=\\\"all\\\"\\n\\t/>\\n\\t\\n\\t<rect \\n\\t\\tid=\\\"captionDisableAntialiasing\\\"\\n\\t\\toryx:anchors=\\\"left top bottom\\\"\\n\\t\\tx=\\\"0\\\"\\n\\t\\ty=\\\"0\\\"\\n\\t\\twidth=\\\"30\\\"\\n\\t\\theight=\\\"250\\\"\\n\\t\\tstroke=\\\"black\\\"\\n\\t\\tstroke-width=\\\"1\\\"\\n\\t\\tfill=\\\"url(#background) white\\\"\\n\\t\\tpointer-events=\\\"all\\\"\\n\\t/>\\n\\t\\n    <text x=\\\"13\\\" y=\\\"125\\\" font-size=\\\"12\\\" id=\\\"text_name\\\" oryx:fittoelem=\\\"caption\\\" oryx:align=\\\"middle center\\\" oryx:anchors=\\\"left\\\" oryx:rotate=\\\"270\\\" fill=\\\"black\\\" stroke=\\\"black\\\"></text>\\n    \\n  </g>\\n</svg>\",\n        \"icon\" : \"swimlane/pool.png\",\n        \"groups\" : [ \"泳道列表\" ],\n        \"layout\" : [ {\n            \"type\" : \"layout.bpmn2_0.pool\"\n        } ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"process_idpackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"canContainArtifacts\", \"all\" ]\n    }, {\n        \"type\" : \"node\",\n        \"id\" : \"Lane\",\n        \"title\" : \"泳道\",\n        \"description\" : \"A lane to stucture the process definition\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n   xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:svg=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\n   xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\"\\n   width=\\\"600\\\"\\n   height=\\\"250\\\"\\n   version=\\\"1.0\\\">\\n  <defs></defs>\\n  <g pointer-events=\\\"none\\\" >\\n  \\n     <defs>\\n\\t\\t<radialGradient id=\\\"background\\\" cx=\\\"0%\\\" cy=\\\"10%\\\" r=\\\"200%\\\" fx=\\\"20%\\\" fy=\\\"10%\\\">\\n\\t\\t\\t<stop offset=\\\"0%\\\" stop-color=\\\"#ffffff\\\" stop-opacity=\\\"1\\\"/>\\n\\t\\t\\t<stop id=\\\"fill_el\\\" offset=\\\"100%\\\" stop-color=\\\"#ffffff\\\" stop-opacity=\\\"0\\\"/>\\n\\t\\t</radialGradient>\\n\\t</defs>\\n\\t\\n  \\t<rect id=\\\"border_invisible\\\" class=\\\"stripable-element-force\\\" oryx:resize=\\\"vertical horizontal\\\" x=\\\"0\\\" y=\\\"0\\\" width=\\\"600\\\" height=\\\"250\\\" fill=\\\"none\\\" stroke-width=\\\"10\\\" stroke=\\\"white\\\" visibility=\\\"hidden\\\" pointer-events=\\\"stroke\\\"/>\\t\\t\\n\\t<rect id=\\\"border\\\" oryx:resize=\\\"vertical horizontal\\\" x=\\\"0\\\" y=\\\"0\\\" width=\\\"600\\\" height=\\\"250\\\" stroke=\\\"black\\\" stroke-width=\\\"1\\\" fill=\\\"url(#background) white\\\" pointer-events=\\\"none\\\" />\\n\\t\\n\\t\\n\\t<rect \\n\\t\\tid=\\\"caption\\\"\\n\\t\\toryx:anchors=\\\"left top bottom\\\"\\n\\t\\tx=\\\"0\\\"\\n\\t\\ty=\\\"1\\\"\\n\\t\\twidth=\\\"30\\\"\\n\\t\\theight=\\\"248\\\"\\n\\t\\tstroke=\\\"black\\\"\\n\\t\\tstroke-width=\\\"0\\\"\\n\\t\\tfill=\\\"white\\\"\\n\\t\\tvisibility=\\\"hidden\\\"\\n\\t\\tclass=\\\"stripable-element-force\\\"\\n\\t\\tpointer-events=\\\"all\\\"\\n\\t/>\\n\\t\\n\\t<path\\n\\t\\tstroke=\\\"black\\\"\\n\\t\\tstroke-width=\\\"1\\\"\\n\\t\\tfill=\\\"none\\\"\\n\\t\\td=\\\"M 0,0 L 0,250\\\"\\n        oryx:anchors=\\\"left top bottom\\\"\\n        id=\\\"captionDisableAntialiasing\\\"\\n    />\\n\\t\\n\\t<!--rect \\n\\t\\tid=\\\"captionDisableAntialiasing\\\"\\n\\t\\toryx:anchors=\\\"left top bottom\\\"\\n\\t\\tx=\\\"0\\\"\\n\\t\\ty=\\\"0\\\"\\n\\t\\twidth=\\\"30\\\"\\n\\t\\theight=\\\"250\\\"\\n\\t\\tstroke=\\\"black\\\"\\n\\t\\tstroke-width=\\\"1\\\"\\n\\t\\tfill=\\\"url(#background) white\\\"\\n\\t/-->\\n\\t\\n    <text \\n\\t\\tx=\\\"13\\\"\\n\\t\\ty=\\\"125\\\"\\n\\t\\toryx:rotate=\\\"270\\\" \\n\\t\\tfont-size=\\\"12\\\" \\n\\t\\tid=\\\"text_name\\\" \\n\\t\\toryx:align=\\\"middle center\\\" \\n\\t\\toryx:anchors=\\\"left\\\"\\n\\t\\toryx:fittoelem=\\\"caption\\\"\\n\\t\\tfill=\\\"black\\\" \\n\\t\\tstroke=\\\"black\\\">\\n\\t</text>\\n  </g>\\n</svg>\",\n        \"icon\" : \"swimlane/lane.png\",\n        \"groups\" : [ \"泳道列表\" ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"PoolChild\", \"canContainArtifacts\", \"all\" ]\n    }, {\n        \"type\" : \"edge\",\n        \"id\" : \"SequenceFlow\",\n        \"title\" : \"顺序流\",\n        \"description\" : \"顺序流定义活动的执行顺序\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\r\\n<svg\\r\\n\\txmlns=\\\"http://www.w3.org/2000/svg\\\"\\r\\n\\txmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\r\\n\\tversion=\\\"1.0\\\"\\r\\n\\toryx:edge=\\\"edge\\\" >\\r\\n\\t<defs>\\r\\n\\t  \\t<marker id=\\\"start\\\" refX=\\\"1\\\" refY=\\\"5\\\" markerUnits=\\\"userSpaceOnUse\\\" markerWidth=\\\"17\\\" markerHeight=\\\"11\\\" orient=\\\"auto\\\">\\r\\n\\t  \\t\\t<!-- <path id=\\\"conditional\\\"   d=\\\"M 0 6 L 8 1 L 15 5 L 8 9 L 1 5\\\" fill=\\\"white\\\" stroke=\\\"black\\\" stroke-width=\\\"1\\\" /> -->\\r\\n\\t\\t\\t<path id=\\\"default\\\" d=\\\"M 5 0 L 11 10\\\" fill=\\\"white\\\" stroke=\\\"#585858\\\" stroke-width=\\\"1\\\" />\\r\\n\\t  \\t</marker>\\r\\n\\t  \\t<marker id=\\\"end\\\" refX=\\\"15\\\" refY=\\\"6\\\" markerUnits=\\\"userSpaceOnUse\\\" markerWidth=\\\"15\\\" markerHeight=\\\"12\\\" orient=\\\"auto\\\">\\r\\n\\t  \\t\\t<path id=\\\"arrowhead\\\" d=\\\"M 0 1 L 15 6 L 0 11z\\\" fill=\\\"#585858\\\" stroke=\\\"#585858\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\" />\\r\\n\\t  \\t</marker>\\r\\n\\t</defs>\\r\\n\\t<g id=\\\"edge\\\">\\r\\n\\t\\t<path id=\\\"bg_frame\\\" d=\\\"M10 50 L210 50\\\" stroke=\\\"#585858\\\" fill=\\\"none\\\" stroke-width=\\\"2\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" marker-start=\\\"url(#start)\\\" marker-end=\\\"url(#end)\\\" />\\r\\n\\t\\t<text id=\\\"text_name\\\" x=\\\"0\\\" y=\\\"0\\\" oryx:edgePosition=\\\"startTop\\\"/>\\r\\n\\t</g>\\r\\n</svg>\",\n        \"icon\" : \"connector/sequenceflow.png\",\n        \"groups\" : [ \"连接对象\" ],\n        \"layout\" : [ {\n            \"type\" : \"layout.bpmn2_0.sequenceflow\"\n        } ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"conditionsequenceflowpackage\", \"executionlistenerspackage\", \"defaultflowpackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"ConnectingObjectsMorph\", \"all\" ]\n    }, {\n        \"type\" : \"edge\",\n        \"id\" : \"MessageFlow\",\n        \"title\" : \"消息流\",\n        \"description\" : \"Message flow to connect elements in different pools.\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\r\\n<svg\\r\\n\\txmlns=\\\"http://www.w3.org/2000/svg\\\"\\r\\n\\txmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\r\\n\\tversion=\\\"1.0\\\"\\r\\n\\toryx:edge=\\\"edge\\\" >\\r\\n\\t<defs>\\r\\n\\t\\t<marker id=\\\"start\\\" oryx:optional=\\\"yes\\\" oryx:enabled=\\\"yes\\\" refX=\\\"5\\\" refY=\\\"5\\\" markerUnits=\\\"userSpaceOnUse\\\" markerWidth=\\\"10\\\" markerHeight=\\\"10\\\" orient=\\\"auto\\\">\\r\\n\\t  \\t\\t<!-- <path d=\\\"M 10 10 L 0 5 L 10 0\\\" fill=\\\"none\\\" stroke=\\\"#585858\\\" /> -->\\r\\n\\t  \\t\\t<circle id=\\\"arrowhead\\\" cx=\\\"5\\\" cy=\\\"5\\\" r=\\\"5\\\" fill=\\\"white\\\" stroke=\\\"black\\\" />\\r\\n\\t  \\t</marker>\\r\\n\\r\\n\\t  \\t<marker id=\\\"end\\\" refX=\\\"10\\\" refY=\\\"5\\\" markerUnits=\\\"userSpaceOnUse\\\" markerWidth=\\\"10\\\" markerHeight=\\\"10\\\" orient=\\\"auto\\\">\\r\\n\\t  \\t\\t<path id=\\\"arrowhead2\\\" d=\\\"M 0 0 L 10 5 L 0 10 L 0 0\\\" fill=\\\"white\\\" stroke=\\\"#585858\\\" />\\r\\n\\t  \\t</marker>\\r\\n\\t</defs>\\r\\n\\t<g id=\\\"edge\\\">\\r\\n\\t    <path id=\\\"bg_frame\\\" d=\\\"M10 50 L210 50\\\" stroke=\\\"#585858\\\" fill=\\\"none\\\" stroke-width=\\\"2\\\" stroke-dasharray=\\\"3, 4\\\" marker-start=\\\"url(#start)\\\" marker-end=\\\"url(#end)\\\" />\\r\\n\\t\\t<text id=\\\"text_name\\\" x=\\\"0\\\" y=\\\"0\\\" oryx:edgePosition=\\\"midTop\\\"/>\\r\\n\\t</g>\\r\\n</svg>\",\n        \"icon\" : \"connector/messageflow.png\",\n        \"groups\" : [ \"连接对象\" ],\n        \"layout\" : [ {\n            \"type\" : \"layout.bpmn2_0.sequenceflow\"\n        } ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"ConnectingObjectsMorph\", \"all\" ]\n    }, {\n        \"type\" : \"edge\",\n        \"id\" : \"Association\",\n        \"title\" : \"注释\",\n        \"description\" : \"连接一个注释到指定元素\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\r\\n<svg\\r\\n\\txmlns=\\\"http://www.w3.org/2000/svg\\\"\\r\\n\\txmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\r\\n\\tversion=\\\"1.0\\\"\\r\\n\\toryx:edge=\\\"edge\\\" >\\r\\n\\t<g id=\\\"edge\\\">\\r\\n\\t    <path id=\\\"bg_frame\\\" d=\\\"M10 50 L210 50\\\" stroke=\\\"#585858\\\" fill=\\\"none\\\" stroke-width=\\\"2\\\" stroke-dasharray=\\\"3, 4\\\" />\\r\\n\\t\\t<text id=\\\"name\\\" x=\\\"0\\\" y=\\\"0\\\" oryx:edgePosition=\\\"midTop\\\" oryx:offsetTop=\\\"6\\\" style=\\\"font-size:9px;\\\"/>\\r\\n\\t</g>\\r\\n</svg>\",\n        \"icon\" : \"connector/association.undirected.png\",\n        \"groups\" : [ \"连接对象\" ],\n        \"layout\" : [ {\n            \"type\" : \"layout.bpmn2_0.sequenceflow\"\n        } ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"ConnectingObjectsMorph\", \"all\" ]\n    }, {\n        \"type\" : \"edge\",\n        \"id\" : \"DataAssociation\",\n        \"title\" : \"日期注释\",\n        \"description\" : \"连接一个日期注释到指定元素\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\r\\n<svg\\r\\n\\txmlns=\\\"http://www.w3.org/2000/svg\\\"\\r\\n\\txmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\r\\n\\tversion=\\\"1.0\\\"\\r\\n\\toryx:edge=\\\"edge\\\" >\\r\\n\\t<defs>\\r\\n\\t  \\t<marker id=\\\"end\\\" refX=\\\"10\\\" refY=\\\"5\\\" markerUnits=\\\"userSpaceOnUse\\\" markerWidth=\\\"10\\\" markerHeight=\\\"10\\\" orient=\\\"auto\\\">\\r\\n\\t  \\t\\t<path id=\\\"arrowhead\\\" d=\\\"M 0 0 L 10 5 L 0 10\\\" fill=\\\"none\\\" stroke=\\\"#585858\\\" />\\r\\n\\t  \\t</marker>\\r\\n\\t</defs>\\r\\n\\t<g id=\\\"edge\\\">\\r\\n\\t    <path id=\\\"bg_frame\\\" d=\\\"M10 50 L210 50\\\" stroke=\\\"#585858\\\" fill=\\\"none\\\" stroke-width=\\\"2\\\" stroke-dasharray=\\\"3, 4\\\" marker-end=\\\"url(#end)\\\" />\\r\\n\\t\\t<text id=\\\"name\\\" x=\\\"0\\\" y=\\\"0\\\" oryx:edgePosition=\\\"midTop\\\" oryx:offsetTop=\\\"6\\\" style=\\\"font-size:9px;\\\"/>\\r\\n\\t</g>\\r\\n</svg>\",\n        \"icon\" : \"connector/association.unidirectional.png\",\n        \"groups\" : [ \"连接对象\" ],\n        \"layout\" : [ {\n            \"type\" : \"layout.bpmn2_0.sequenceflow\"\n        } ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"ConnectingObjectsMorph\", \"all\" ]\n    }, {\n        \"type\" : \"node\",\n        \"id\" : \"TextAnnotation\",\n        \"title\" : \"文本注释\",\n        \"description\" : \"连接一个文本注释到指定元素\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n   xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:svg=\\\"http://www.w3.org/2000/svg\\\"\\n   xmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\n   xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\"\\n   width=\\\"102\\\"\\n   height=\\\"51\\\"\\n   version=\\\"1.0\\\">\\n  <defs></defs>\\n  <oryx:magnets>\\n  \\t<oryx:magnet oryx:cx=\\\"2\\\" oryx:cy=\\\"25\\\" oryx:anchors=\\\"left\\\" oryx:default=\\\"yes\\\"/>\\n  </oryx:magnets>\\n  <g pointer-events=\\\"all\\\" oryx:minimumSize=\\\"10 20\\\" oryx:maximumSize=\\\"\\\" >\\n  <rect \\n\\tid=\\\"textannotationrect\\\"\\n\\toryx:resize=\\\"vertical horizontal\\\"\\n\\tx=\\\"1\\\" \\n\\ty=\\\"1\\\"\\n\\twidth=\\\"100\\\"\\n\\theight=\\\"50\\\"\\n\\tstroke=\\\"none\\\"\\n\\tfill=\\\"none\\\" />\\n  <path \\n  \\tid = \\\"frame\\\"\\n\\td=\\\"M20,1 L1,1 L1,50 L20,50\\\" \\n\\toryx:anchors=\\\"top bottom left\\\" \\n\\tstroke=\\\"#585858\\\" \\n\\tfill=\\\"none\\\" \\n\\tstroke-width=\\\"1\\\" />\\n    \\n    <text \\n\\t\\tfont-size=\\\"12\\\" \\n\\t\\tid=\\\"text\\\" \\n\\t\\tx=\\\"5\\\" \\n\\t\\ty=\\\"25\\\" \\n\\t\\toryx:align=\\\"middle left\\\"\\n\\t\\toryx:fittoelem=\\\"textannotationrect\\\"\\n\\t\\toryx:anchors=\\\"left\\\"\\n\\t\\tstroke=\\\"#373e48\\\">\\n\\t</text>\\n  </g>\\n</svg>\",\n        \"icon\" : \"artifact/text.annotation.png\",\n        \"groups\" : [ \"加工\" ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\", \"textpackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"all\" ]\n    }, {\n        \"type\" : \"node\",\n        \"id\" : \"DataStore\",\n        \"title\" : \"Data store\",\n        \"description\" : \"Reference to a data store.\",\n        \"view\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\" standalone=\\\"no\\\" ?>\\r\\n<svg \\r\\n\\txmlns=\\\"http://www.w3.org/2000/svg\\\"\\r\\n\\txmlns:svg=\\\"http://www.w3.org/2000/svg\\\"\\r\\n   \\txmlns:oryx=\\\"http://www.b3mn.org/oryx\\\"\\r\\n   \\txmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\"\\r\\n\\t\\r\\n\\twidth=\\\"63.001px\\\" \\r\\n\\theight=\\\"61.173px\\\"\\r\\n\\tversion=\\\"1.0\\\">\\r\\n\\t<defs></defs>\\r\\n\\t<oryx:magnets>\\r\\n\\t\\t<oryx:magnet oryx:cx=\\\"0\\\" oryx:cy=\\\"30.5865\\\" oryx:anchors=\\\"left\\\" />\\r\\n\\t\\t<oryx:magnet oryx:cx=\\\"31.5005\\\" oryx:cy=\\\"61.173\\\" oryx:anchors=\\\"bottom\\\" />\\r\\n\\t\\t<oryx:magnet oryx:cx=\\\"63.001\\\" oryx:cy=\\\"30.5865\\\" oryx:anchors=\\\"right\\\" />\\r\\n\\t\\t<oryx:magnet oryx:cx=\\\"31.5005\\\" oryx:cy=\\\"0\\\" oryx:anchors=\\\"top\\\" />\\r\\n\\t\\t<oryx:magnet oryx:cx=\\\"31.5005\\\" oryx:cy=\\\"30.5865\\\" oryx:default=\\\"yes\\\" />\\r\\n\\t</oryx:magnets>\\r\\n\\t\\r\\n\\t<g>\\r\\n\\t\\t<defs>\\r\\n\\t\\t\\t<radialGradient id=\\\"background\\\" cx=\\\"30%\\\" cy=\\\"30%\\\" r=\\\"50%\\\" fx=\\\"0%\\\" fy=\\\"0%\\\">\\r\\n\\t\\t\\t\\t<stop offset=\\\"0%\\\" stop-color=\\\"#ffffff\\\" stop-opacity=\\\"1\\\"></stop>\\r\\n\\t\\t\\t\\t<stop offset=\\\"100%\\\" stop-color=\\\"#ffffff\\\" stop-opacity=\\\"1\\\" id=\\\"fill_el\\\"></stop>\\r\\n\\t\\t\\t</radialGradient>\\r\\n\\t\\t</defs>\\r\\n\\t\\t\\r\\n\\t\\t<path id=\\\"bg_frame\\\" fill=\\\"url(#background) #ffffff\\\" stroke=\\\"#000000\\\" d=\\\"M31.634,0.662c20.013,0,31.292,3.05,31.292,5.729c0,2.678,0,45.096,0,48.244\\r\\n\\t\\t\\tc0,3.148-16.42,6.2-31.388,6.2c-14.968,0-30.613-2.955-30.613-6.298c0-3.342,0-45.728,0-48.05\\r\\n\\t\\t\\tC0.925,4.165,11.622,0.662,31.634,0.662z\\\"/>\\r\\n\\t\\t<path id=\\\"bg_frame2\\\" fill=\\\"none\\\" stroke=\\\"#000000\\\" d=\\\"\\r\\n\\t\\t\\tM62.926,15.69c0,1.986-3.62,6.551-31.267,6.551c-27.646,0-30.734-4.686-30.734-6.454 M0.925,11.137\\r\\n\\t\\t\\tc0,1.769,3.088,6.455,30.734,6.455c27.647,0,31.267-4.565,31.267-6.551 M0.925,6.487c0,2.35,3.088,6.455,30.734,6.455\\r\\n\\t\\t\\tc27.647,0,31.267-3.912,31.267-6.552 M62.926,6.391v4.844 M0.949,6.391v4.844 M62.926,11.041v4.844 M0.949,11.041v4.844\\\"/>\\r\\n\\t\\t\\t \\t\\r\\n\\t\\t<text font-size=\\\"12\\\" id=\\\"text_name\\\" x=\\\"31\\\" y=\\\"66\\\" oryx:align=\\\"center top\\\" stroke=\\\"black\\\" />\\r\\n\\t\\t\\t \\r\\n\\t</g>\\r\\n</svg>\\r\\n\",\n        \"icon\" : \"dataobject/data.store.png\",\n        \"groups\" : [ \"Artifacts\" ],\n        \"propertyPackages\" : [ \"overrideidpackage\", \"namepackage\", \"documentationpackage\" ],\n        \"hiddenPropertyPackages\" : [ ],\n        \"roles\" : [ \"all\" ]\n    } ],\n    \"rules\" : {\n        \"cardinalityRules\" : [ {\n            \"role\" : \"Startevents_all\",\n            \"incomingEdges\" : [ {\n                \"role\" : \"SequenceFlow\",\n                \"maximum\" : 0\n            } ]\n        }, {\n            \"role\" : \"Endevents_all\",\n            \"outgoingEdges\" : [ {\n                \"role\" : \"SequenceFlow\",\n                \"maximum\" : 0\n            } ]\n        } ],\n        \"connectionRules\" : [ {\n            \"role\" : \"SequenceFlow\",\n            \"connects\" : [ {\n                \"from\" : \"sequence_start\",\n                \"to\" : [ \"sequence_end\" ]\n            } ]\n        }, {\n            \"role\" : \"Association\",\n            \"connects\" : [ {\n                \"from\" : \"sequence_start\",\n                \"to\" : [ \"TextAnnotation\" ]\n            }, {\n                \"from\" : \"sequence_end\",\n                \"to\" : [ \"TextAnnotation\" ]\n            }, {\n                \"from\" : \"TextAnnotation\",\n                \"to\" : [ \"sequence_end\" ]\n            }, {\n                \"from\" : \"BoundaryCompensationEvent\",\n                \"to\" : [ \"sequence_end\" ]\n            }, {\n                \"from\" : \"TextAnnotation\",\n                \"to\" : [ \"sequence_start\" ]\n            }, {\n                \"from\" : \"BoundaryCompensationEvent\",\n                \"to\" : [ \"sequence_start\" ]\n            } ]\n        }, {\n            \"role\" : \"DataAssociation\",\n            \"connects\" : [ {\n                \"from\" : \"sequence_start\",\n                \"to\" : [ \"DataStore\" ]\n            }, {\n                \"from\" : \"sequence_end\",\n                \"to\" : [ \"DataStore\" ]\n            }, {\n                \"from\" : \"DataStore\",\n                \"to\" : [ \"sequence_end\" ]\n            }, {\n                \"from\" : \"DataStore\",\n                \"to\" : [ \"sequence_start\" ]\n            } ]\n        }, {\n            \"role\" : \"IntermediateEventOnActivityBoundary\",\n            \"connects\" : [ {\n                \"from\" : \"Activity\",\n                \"to\" : [ \"IntermediateEventOnActivityBoundary\" ]\n            } ]\n        } ],\n        \"containmentRules\" : [ {\n            \"role\" : \"BPMNDiagram\",\n            \"contains\" : [ \"all\" ]\n        }, {\n            \"role\" : \"SubProcess\",\n            \"contains\" : [ \"sequence_start\", \"sequence_end\", \"from_task_event\", \"to_task_event\", \"EventSubProcess\", \"TextAnnotation\", \"DataStore\" ]\n        }, {\n            \"role\" : \"EventSubProcess\",\n            \"contains\" : [ \"sequence_start\", \"sequence_end\", \"from_task_event\", \"to_task_event\", \"TextAnnotation\", \"DataStore\" ]\n        }, {\n            \"role\" : \"Pool\",\n            \"contains\" : [ \"Lane\" ]\n        }, {\n            \"role\" : \"Lane\",\n            \"contains\" : [ \"sequence_start\", \"sequence_end\", \"EventSubProcess\", \"TextAnnotation\", \"DataStore\" ]\n        } ],\n        \"morphingRules\" : [ {\n            \"role\" : \"ActivitiesMorph\",\n            \"baseMorphs\" : [ \"UserTask\" ],\n            \"preserveBounds\" : true\n        }, {\n            \"role\" : \"GatewaysMorph\",\n            \"baseMorphs\" : [ \"ExclusiveGateway\" ]\n        }, {\n            \"role\" : \"StartEventsMorph\",\n            \"baseMorphs\" : [ \"StartNoneEvent\" ]\n        }, {\n            \"role\" : \"EndEventsMorph\",\n            \"baseMorphs\" : [ \"StartNoneEvent\" ]\n        }, {\n            \"role\" : \"CatchEventsMorph\",\n            \"baseMorphs\" : [ \"CatchTimerEvent\" ]\n        }, {\n            \"role\" : \"ThrowEventsMorph\",\n            \"baseMorphs\" : [ \"ThrowNoneEvent\" ]\n        }, {\n            \"role\" : \"BoundaryEventsMorph\",\n            \"baseMorphs\" : [ \"ThrowNoneEvent\" ]\n        }, {\n            \"role\" : \"BoundaryCompensationEvent\",\n            \"baseMorphs\" : [ \"BoundaryCompensationEvent\" ]\n        }, {\n            \"role\" : \"TextAnnotation\",\n            \"baseMorphs\" : [ \"TextAnnotation\" ]\n        }, {\n            \"role\" : \"DataStore\",\n            \"baseMorphs\" : [ \"DataStore\" ]\n        } ]\n    }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/admin.html",
    "content": "﻿<!DOCTYPE html>\n\n<html>\n\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">\n\t    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=1\">\n\t    <meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black\"> \n\t    <meta name=\"apple-mobile-web-app-capable\" content=\"yes\">\n\t    <meta name=\"format-detection\" content=\"telephone=no\">\n\t\t<title>后台管理系统</title>\n\t\t<link rel=\"stylesheet\" href=\"/lib/layui/css/layui.css\" media=\"all\" />\n\t\t<link rel=\"stylesheet\" href=\"/lib/layui/css/global.css\" media=\"all\" />\n\t\t<link rel=\"stylesheet\" href=\"/css/font-awesome/css/font-awesome.css\" media=\"all\" />\n\t\t\n\t</head>\n\n\t<body>\n\t\t<div class=\"layui-layout layui-layout-admin\" style=\"border-bottom: solid 5px #1aa094;\">\n\t\t    <!-- 标题栏 -->\n\t\t\t<div class=\"layui-header header header-demo\">\n                <div class=\"layui-main\">\n\t\t\t\t\t<div class=\"admin-login-box\">\n\t\t\t\t\t\t<a class=\"logo\" style=\"left: 0;\" href=\"/\">\n\t\t\t\t\t\t\t<span style=\"font-size: 22px;\">后台管理系统</span>\n\t\t\t\t\t\t</a>\n\t\t\t\t\t\t<div class=\"admin-side-toggle\">\n\t\t\t\t\t\t\t<i class=\"fa fa-bars\" aria-hidden=\"true\"></i>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t    <ul class=\"layui-nav\" pc>\n\t\t\t\t      \t<li class=\"layui-nav-item\">\n\t\t\t\t\t\t\t<a href='javascript:;' lay-id=\"-997\" data-url=\"pages/notice/noticePubList.html\"><i class=\"fa fa-envelope-o\" aria-hidden=\"true\" title=\"公告\" unreadNotice></i></a>\n\t\t\t\t\t\t</li>\n\t\t\t\t      <li class=\"layui-nav-item\" pc>\n\t\t\t\t        <a href=\"javascript:;\" class=\"admin-header-user\">\n\t                        <img />\n\t                        <span></span>\n\t                    </a>\n\t                    <dl class=\"layui-nav-child\">\n\t                        <dd>\n\t                            <a href='javascript:;' lay-id=\"-999\" data-url=\"pages/user/updateMyself.html\"><i class=\"fa fa-user-circle\" aria-hidden=\"true\"></i> 个人信息</a>\n\t                        </dd>\n\t                        <dd>\n\t                            <a href='javascript:;' lay-id=\"-998\" data-url=\"pages/user/updateHeadImg.html\"><i class=\"fa fa-drupal\" aria-hidden=\"true\"></i> 头像</a>\n\t                        </dd>\n\t                        <dd>\n\t                            <a href=\"javascript:;\" onclick=\"logout()\"><i class=\"fa fa-sign-out\" aria-hidden=\"true\"></i> 退出</a>\n\t                        </dd>\n\t                    </dl>\n\t\t\t\t      </li>\n\t\t\t\t    </ul>\n\t\t\t  </div>\n            </div>\n            <!-- 菜单 -->\n\t\t\t<div class=\"layui-side layui-bg-black\" id=\"admin-side\">\n\t\t\t\t<div class=\"layui-side-scroll\" id=\"admin-navbar-side\" lay-filter=\"side\">\n\t\t\t\t    <ul id=\"menu\" class=\"layui-nav layui-nav-tree\" lay-filter=\"demo\">\n\t\t\t\t    \n\t\t            </ul>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"layui-body\" style=\"bottom: 0;border-left: solid 2px #1AA094;\" id=\"admin-body\">\n\t\t\t\t<div class=\"layui-tab admin-nav-card layui-tab-brief\" lay-allowClose=\"true\" lay-filter=\"admin-tab\">\n\t\t\t\t\t<ul class=\"layui-tab-title\">\n\t\t\t\t\t\t<li class=\"layui-this\">\n\t\t\t\t\t\t\t<i class=\"fa fa-dashboard\" aria-hidden=\"true\"></i>\n\t\t\t\t\t\t\t<cite>Home</cite>\n\t\t\t\t\t\t</li>\n\t\t\t\t\t</ul>\n\t\t\t\t\t<div class=\"layui-tab-content\" style=\"min-height: 150px; padding: 5px 0 0 0;\">\n\t\t\t\t\t\t<div class=\"layui-tab-item layui-show\">\n\t\t\t\t\t\t\t<iframe src=\"pages/dashboard.html\"></iframe>\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</div>\n\t\t\t<div class=\"layui-footer footer footer-demo\" id=\"admin-footer\">\n\t\t\t\t<div>\n\t\t\t\t\t<p>UNIEAP研发中心  2015-2017</p>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"site-tree-mobile layui-hide\">\n\t\t\t\t<i class=\"layui-icon\">&#xe602;</i>\n\t\t\t</div>\n\t\t\t<div class=\"site-mobile-shade\"></div>\n\t\t\t\n\t\t\t<script type=\"text/javascript\" src=\"/lib/layui/layui.js\"></script>\n\t\t\t<script src=\"base-component/jquery/jquery.min.js\"></script>\n\t\t\t<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n\t\t\t<script type=\"text/javascript\" src=\"/js/main.js\"></script>\n\t</div>\n</body>\n\n</html>"
  },
  {
    "path": "open-layui-web/src/main/view/static/assets/css/admin.css",
    "content": "/**\n * admin.css\n */\n\n\n/*\n fixed-layout 固定头部和边栏布局\n*/\n\nhtml,\nbody {\n  height: 100%;\n  overflow: hidden;\n}\n*{\n  font-family: \"Helvetica Neue\", \"Luxi Sans\", \"DejaVu Sans\", Tahoma, \"Hiragino Sans GB\", STHeiti, \"Microsoft YaHei\";\n}\n\nul {\n  margin-top: 0;\n}\n\n.admin-icon-yellow {\n  color: #ffbe40;\n}\n\n.admin-header {\n  border-width: 0 0 0px;\n  position: fixed;\n  top: 0;\n  left: 0;\n  right: 0;\n  z-index: 1500;\n  font-size: 1.4rem;\n  margin-bottom: 0;\n}\n\n.admin-header-list a:hover :after {\n  content: none;\n}\n\n.admin-main {\n  position: relative;\n  height: 100%;\n  padding-top: 50px;\n  background: #f3f3f3;\n}\n\n.admin-menu {\n  position: fixed;\n  z-index: 100;\n  bottom: 15px;\n  right: 20px;\n}\n.am-list>li>a{\n  padding:10px 0;\n}\n.admin-sidebar {\n  color:#333 !important;\n  font-size: 1.4rem;\n  width: 260px;\n  min-height: 100%;\n  float: left;\n  border-right: 1px solid #cecece;\n}\n\n.admin-sidebar.am-active {\n  z-index: 1600;\n}\n\n.admin-sidebar-list {\n  margin-bottom: 0;\n}\n\n.admin-sidebar-list li a {\n  color: #333;\n  padding-left: 24px;\n}\n\n.admin-sidebar-list li:first-child {\n  border-top: none;\n}\n\n.admin-sidebar-sub {\n  margin-top: 0;\n  margin-bottom: 0;\n  box-shadow: 0 16px 8px -15px #e2e2e2 inset;\n  background: #ececec;\n  padding-left: 24px;\n}\n\n.admin-sidebar-sub li:first-child {\n  border-top: 1px solid #dedede;\n}\n\n.admin-sidebar-panel {\n  margin: 10px;\n}\n\n.admin-content {\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -ms-flexbox;\n  display: flex;\n  -webkit-box-orient: vertical;\n  -webkit-box-direction: normal;\n  -webkit-flex-direction: column;\n  -ms-flex-direction: column;\n  flex-direction: column;\n  background: #fff;\n}\n\n.admin-content,\n.admin-sidebar {\n  height: 100%;\n  overflow-x: hidden;\n  /*overflow-y: scroll;*/\n  -webkit-overflow-scrolling: touch;\n}\n\n.admin-content-body {\n  /*-webkit-box-flex: 1;\n  -webkit-flex: 1 0 auto;\n  -ms-flex: 1 0 auto;\n  flex: 1 0 auto;*/\n  width: 100%;\n  height: 100%;\n}\n.admin-tab-show{\n  height: 38px;\n  overflow: hidden;\n  position: absolute;\n  top: 0px;\n  border-bottom: none;\n  z-index: 1000;\n  width: 100%;\n}\n.admin-tab-left{\n  right: -1px;\n  text-align: center;\n  width: 20px;\n  height: 39px;\n  line-height: 39px;\n  float: left;\n  border-right: 1px solid #ddd;\n  cursor: pointer;\n}\n.admin-tab-right{\n  text-align: center;\n  width: 20px;\n  height: 39px;\n  line-height: 39px;\n  float: right;\n  border-left: 1px solid #ddd;\n  cursor: pointer;\n}\n.admin-tab-min-hr{\n  position: absolute;\n  bottom: 0px;\n  width: 100%;\n  height: 1px;\n  display: block;\n  background-color: #ddd;\n}\n.admin-tab-show-body{\n  height: 100%;\n  padding-top: 40px;\n  padding-bottom: 42px;\n}\n.admin-content-footer {\n  width: 100%;\n  background-color: #ffffff;\n  position: absolute;\n  bottom: 0px;\n  font-size: 85%;\n  color: #777;\n  border-top: 1px solid #ddd;\n}\n.admin-content-footer-p{\n  margin: 10px !important;\n}\n.admin-content-list {\n  border: 1px solid #e9ecf1;\n  margin-top: 0;\n}\n\n.admin-content-list li {\n  border: 1px solid #e9ecf1;\n  border-width: 0 1px;\n  margin-left: -1px;\n}\n\n.admin-content-list li:first-child {\n  border-left: none;\n}\n\n.admin-content-list li:last-child {\n  border-right: none;\n}\n\n.admin-content-table a {\n  color: #535353;\n}\n.admin-content-file {\n  margin-bottom: 0;\n  color: #666;\n}\n\n.admin-content-file p {\n  margin: 0 0 5px 0;\n  font-size: 1.4rem;\n}\n\n.admin-content-file li {\n  padding: 10px 0;\n}\n\n.admin-content-file li:first-child {\n  border-top: none;\n}\n\n.admin-content-file li:last-child {\n  border-bottom: none;\n}\n\n.admin-content-file li .am-progress {\n  margin-bottom: 4px;\n}\n\n.admin-content-file li .am-progress-bar {\n  line-height: 14px;\n}\n\n.admin-content-task {\n  margin-bottom: 0;\n}\n\n.admin-content-task li {\n  padding: 5px 0;\n  border-color: #eee;\n}\n\n.admin-content-task li:first-child {\n  border-top: none;\n}\n\n.admin-content-task li:last-child {\n  border-bottom: none;\n}\n\n.admin-task-meta {\n  font-size: 1.2rem;\n  color: #999;\n}\n\n.admin-task-bd {\n  font-size: 1.4rem;\n  margin-bottom: 5px;\n}\n\n.admin-content-comment {\n  margin-bottom: 0;\n}\n\n.admin-content-comment .am-comment-bd {\n  font-size: 1.4rem;\n}\n\n.admin-content-pagination {\n  margin-bottom: 0;\n}\n.admin-content-pagination li a {\n  padding: 4px 8px;\n}\n\n@media only screen and (min-width: 641px) {\n  .admin-sidebar {\n    display: block;\n    position: static;\n    background: none;\n  }\n\n  .admin-offcanvas-bar {\n    position: static;\n    width: auto;\n    background: none;\n    -webkit-transform: translate3d(0, 0, 0);\n    -ms-transform: translate3d(0, 0, 0);\n    transform: translate3d(0, 0, 0);\n    overflow-y: visible;\n    /*min-height: 100%;*/\n  }\n  .admin-offcanvas-bar:after {\n    content: none;\n  }\n}\n\n@media only screen and (max-width: 640px) {\n  .admin-tab-show{\n    display: none;\n  }\n  .admin-tab-show-body{\n    padding-top: 0px;\n    padding-bottom: 0px;\n  }\n  .admin-content-footer{\n    display: none;\n  }\n  .admin-sidebar {\n    width: inherit;\n  }\n\n  .admin-offcanvas-bar {\n    background: #f3f3f3;\n  }\n\n  .admin-offcanvas-bar:after {\n    background: #BABABA;\n  }\n\n  .admin-sidebar-list a:hover, .admin-sidebar-list a:active{\n    -webkit-transition: background-color .3s ease;\n    -moz-transition: background-color .3s ease;\n    -ms-transition: background-color .3s ease;\n    -o-transition: background-color .3s ease;\n    transition: background-color .3s ease;\n    background: #E4E4E4;\n  }\n\n  .admin-content-list li {\n    padding: 10px;\n    border-width: 1px 0;\n    margin-top: -1px;\n  }\n\n  .admin-content-list li:first-child {\n    border-top: none;\n  }\n\n  .admin-content-list li:last-child {\n    border-bottom: none;\n  }\n\n  .admin-form-text {\n    text-align: left !important;\n  }\n  .am-tab-panel{\n    padding: 0px !important;\n  }\n\n}\n\n/*\n* user.html css\n*/\n.user-info {\n  margin-bottom: 15px;\n}\n\n.user-info .am-progress {\n  margin-bottom: 4px;\n}\n\n.user-info p {\n  margin: 5px;\n}\n\n.user-info-order {\n  font-size: 1.4rem;\n}\n\n/*\n* errorLog.html css\n*/\n\n.error-log .am-pre-scrollable {\n  max-height: 40rem;\n}\n\n/*\n* table.html css\n*/\n\n.table-main {\n  font-size: 1.4rem;\n  padding: .5rem;\n}\n\n.table-main button {\n  background: #fff;\n}\n\n.table-check {\n  width: 30px;\n}\n\n.table-id {\n  width: 50px;\n}\n\n@media only screen and (max-width: 640px) {\n  .table-select {\n    margin-top: 10px;\n    margin-left: 5px;\n  }\n}\n\n/*\ngallery.html css\n*/\n\n.gallery-list li {\n  padding: 10px;\n}\n\n.gallery-list a {\n  color: #666;\n}\n\n.gallery-list a:hover {\n  color: #3bb4f2;\n}\n\n.gallery-title {\n  margin-top: 6px;\n  font-size: 1.4rem;\n}\n\n.gallery-desc {\n  font-size: 1.2rem;\n  margin-top: 4px;\n}\n.am-nav-tabs>li>a {\n  padding: .5rem 2rem;\n  /* padding: 1rem; */\n  margin-right: 0px !important;\n  line-height: 1.6;\n  border: 1px solid transparent;\n  border-radius: 0;\n  font-weight: 600;\n}\n\n/*\n 404.html css\n*/\n\n.page-404 {\n  background: #fff;\n  border: none;\n  width: 200px;\n  margin: 0 auto;\n}\n.am-tabs-nav li {\n  position: relative;\n  z-index: 1;\n}\n\n.am-tabs-nav .am-icon-close {\n  position: absolute;\n  top: 6px;\n  right: 8px;\n  color: #888;\n  cursor: pointer;\n  z-index: 100;\n}\n\n.am-tabs-nav .am-icon-close:hover {\n  color: #333;\n}\n\n.am-tabs-nav .am-icon-close ~ a {\n  padding-right: 25px!important;\n}\n.am-nav-tabs>li.am-active>a{\n  color:#333 !important;\n}\n.am-tab-refresh {\n  font-size: 14px;\n  position: absolute;\n  top: 9px;\n  left: 8px;\n  color: #888;\n  cursor: pointer;\n  z-index: 100;\n}\n.am-tab-panel{\n  padding: 0px !important;\n}"
  },
  {
    "path": "open-layui-web/src/main/view/static/assets/css/amazeui.css",
    "content": "/*! Amaze UI v2.6.0 | by Amaze UI Team | (c) 2016 AllMobilize, Inc. | Licensed under MIT | 2016-03-31T14:28:54+0800 */\n/* ==========================================================================\n   Component: Base\n ============================================================================ */\n/**\n * Fix the flawed CSS box model - Yes, IE6's box model is better\n * Browser support: IE8+\n * via: http://paulirish.com/2012/box-sizing-border-box-ftw/\n */\n*,\n*:before,\n*:after {\n  -webkit-box-sizing: border-box;\n          box-sizing: border-box;\n}\n/* normalize.css v3.0.2 | git.io/normalize */\n/* Set <html> and <body> to inherit the height of the viewport */\nhtml,\nbody {\n  min-height: 100%;\n}\n/**\n * 1. Prevent iOS text size adjust after orientation change, without disabling\n *    user zoom.\n *    https://developer.mozilla.org/en-US/docs/Web/CSS/text-size-adjust\n */\nhtml {\n  -ms-text-size-adjust: 100%;\n  /* 1 */\n  -webkit-text-size-adjust: 100%;\n  /* 1 */\n}\n/**\n * Remove default margin.\n */\nbody {\n  margin: 0;\n}\n/* HTML5 display definitions\n   ========================================================================== */\n/**\n * Correct `block` display not defined for any HTML5 element in IE 8/9.\n * Correct `block` display not defined for `details` or `summary` in IE 10/11 and Firefox.\n * Correct `block` display not defined for `main` in IE 11.\n * hgroup has been removed from the HTML5 (W3C) specification\n *        https://developer.mozilla.org/en-US/docs/Web/HTML/Element/hgroup\n */\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmenu,\nmain,\nnav,\nsection,\nsummary {\n  display: block;\n}\n/**\n * 1. Correct `inline-block` display not defined in IE 8/9.\n * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.\n */\naudio,\ncanvas,\nprogress,\nvideo {\n  display: inline-block;\n  /* 1 */\n  vertical-align: baseline;\n  /* 2 */\n}\n/**\n * Prevent modern browsers from displaying `audio` without controls.\n * Remove excess height in iOS 5 devices.\n */\naudio:not([controls]) {\n  display: none;\n  height: 0;\n}\n/**\n * Address `[hidden]` styling not present in IE 8/9/10.\n * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.\n */\n[hidden],\ntemplate,\nscript {\n  display: none;\n}\n/* Links\n   ========================================================================== */\n/**\n * Remove the gray background color from active links in IE 10.\n */\na {\n  background-color: transparent;\n}\n/**\n * Address `outline` inconsistency between Chrome and other browsers.\n */\na:focus {\n  outline: thin dotted;\n}\n/**\n * Improve readability when focused and also mouse hovered in all browsers.\n */\na:active,\na:hover {\n  outline: 0;\n}\n/* Text-level semantics\n   ========================================================================== */\n/**\n * Remove text-decoration\n */\nins,\na {\n  text-decoration: none;\n}\n/**\n * Address styling not present in IE 8/9, Safari 5, and Chrome.\n */\nabbr[title] {\n  border-bottom: 1px dotted;\n}\n/**\n * Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome.\n */\nb,\nstrong {\n  font-weight: bold;\n}\n/**\n * Improve readability of pre-formatted text in all browsers.\n */\npre {\n  white-space: pre-wrap;\n}\n/**\n * Set consistent quote types.\n */\nq {\n  quotes: \"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\";\n}\n/**\n * Address inconsistent and variable font size in all browsers.\n */\nsmall {\n  font-size: 80%;\n}\n/**\n * Prevent `sub` and `sup` affecting `line-height` in all browsers.\n */\nsub,\nsup {\n  font-size: 75%;\n  line-height: 0;\n  position: relative;\n  vertical-align: baseline;\n}\nsup {\n  top: -0.5em;\n}\nsub {\n  bottom: -0.25em;\n}\n/* Embedded content\n   ========================================================================== */\n/**\n  * 1. Corrects max-width behavior (2.) if padding and border are used\n  * 2. Responsiveness: Sets a maxium width relative to the parent and auto scales the height\n  * 3. Remove the gap between images and the bottom of their containers\n  * 4. Remove border when inside `a` element in IE 8/9.\n  * remove 2. for Issue #502\n  */\nimg {\n  -webkit-box-sizing: border-box;\n          box-sizing: border-box;\n  /* 1 */\n  vertical-align: middle;\n  /* 3 */\n  border: 0;\n  /* 4 */\n}\n/**\n * Correct overflow displayed oddly in IE 9.\n */\nsvg:not(:root) {\n  overflow: hidden;\n}\n/* Grouping content\n   ========================================================================== */\n/**\n * Address margin not present in IE 8/9 and Safari.\n */\nfigure {\n  margin: 0;\n}\n/**\n * Correct font family set oddly in Safari 5 and Chrome.\n */\ncode,\nkbd,\npre,\nsamp {\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", \"FontAwesome\", monospace;\n  font-size: 1em;\n}\n/* Forms\n   ========================================================================== */\n/**\n * Define consistent border, margin, and padding.\n */\nfieldset {\n  border: 1px solid #c0c0c0;\n  margin: 0 2px;\n  padding: 0.35em 0.625em 0.75em;\n}\n/**\n * 1. Correct `color` not being inherited in IE 8/9.\n * 2. Remove padding so people aren't caught out if they zero out fieldsets.\n */\nlegend {\n  border: 0;\n  /* 1 */\n  padding: 0;\n  /* 2 */\n}\n/**\n * 1. Correct color not being inherited.\n *    Known issue: affects color of disabled elements.\n * 2. Correct font properties not being inherited.\n * 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome.\n */\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n  color: inherit;\n  /* 1 */\n  font: inherit;\n  /* 2 */\n  margin: 0;\n  /* 3 */\n}\n/**\n * Address `overflow` set to `hidden` in IE 8/9/10/11.\n */\nbutton {\n  overflow: visible;\n}\n/**\n * Address Firefox 4+ setting `line-height` on `input` using `!important` in\n * the UA stylesheet.\n */\nbutton,\ninput {\n  line-height: normal;\n}\n/**\n * Address inconsistent `text-transform` inheritance for `button` and `select`.\n * All other form control elements do not inherit `text-transform` values.\n * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.\n * Correct `select` style inheritance in Firefox.\n */\nbutton,\nselect {\n  text-transform: none;\n}\n/**\n * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`\n *    and `video` controls.\n * 2. Correct inability to style clickable `input` types in iOS.\n * 3. Improve usability and consistency of cursor style between image-type\n *    `input` and others.\n */\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  -webkit-appearance: button;\n  /* 2 */\n  cursor: pointer;\n  /* 3 */\n}\n/*\n * 1. Improves consistency of cursor style for clickable elements\n * 2. Removes excess padding in IE 8/9.\n * 3. Address box sizing set to `content-box` in IE 8/9/10.\n */\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n  /*1*/\n  padding: 0;\n  /*2*/\n  -webkit-box-sizing: border-box;\n          box-sizing: border-box;\n  /* 3 */\n}\n/**\n * Re-set default cursor for disabled elements.\n */\nbutton[disabled],\nhtml input[disabled] {\n  cursor: default;\n}\n/**\n * Remove inner padding and border in Firefox 4+.\n */\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  border: 0;\n  padding: 0;\n}\n/**\n * Fix the cursor style for Chrome's increment/decrement buttons. For certain\n * `font-size` values of the `input`, it causes the cursor style of the\n * decrement button to change from `default` to `text`.\n */\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n  height: auto;\n}\n/**\n * 1. Address `appearance` set to `searchfield` in Safari and Chrome.\n * 2. Address `box-sizing` set to `border-box` in Safari and Chrome\n *    (include `-moz` to future-proof).\n */\ninput[type=\"search\"] {\n  -webkit-appearance: textfield;\n  /* 1 */\n  -webkit-box-sizing: content-box;\n          box-sizing: content-box;\n  /* 2 */\n}\n/**\n * Remove inner padding and search cancel button in Safari 5 and Chrome\n * on OS X.\n */\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n  -webkit-appearance: none;\n}\n/**\n * 1. Remove default vertical scrollbar in IE 8/9.\n * 2. Improve readability and alignment in all browsers.\n */\ntextarea {\n  overflow: auto;\n  /* 1 */\n  vertical-align: top;\n  /* 2 */\n  resize: vertical;\n}\n/**\n * Don't inherit the `font-weight` (applied by a rule above).\n * NOTE: the default cannot safely be changed in Chrome and Safari on OS X.\n */\noptgroup {\n  font-weight: bold;\n}\n/* Tables\n   ========================================================================== */\n/**\n * Remove most spacing between table cells.\n */\ntable {\n  border-collapse: collapse;\n  border-spacing: 0;\n}\ntd,\nth {\n  padding: 0;\n}\n/* AMUI Base\n   ========================================================================== */\n/**\n * `font-size` is set in `html` element to support the `rem` unit for font-sizes\n * NOTE: IE9 & IE10 do not recognize `rem` units when used with the\n   `font` shorthand property.\n */\nhtml {\n  font-size: 10px;\n  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\nbody {\n  position: relative;\n  background: #fff;\n  font-family: \"Segoe UI\", \"Lucida Grande\", Helvetica, Arial, \"Microsoft YaHei\", FreeSans, Arimo, \"Droid Sans\", \"wenquanyi micro hei\", \"Hiragino Sans GB\", \"Hiragino Sans GB W3\", \"FontAwesome\", sans-serif;\n  font-weight: normal;\n  line-height: 1.6;\n  color: #333333;\n  font-size: 1.6rem;\n}\n/**\n * 1. http://usabilitypost.com/2012/11/15/w-optimizelegibility-on-mobile-devices/\n * 2. http://maxvoltar.com/archive/-webkit-font-smoothing\n * NOTE: http://usabilitypost.com/2012/11/05/stop-fixing-font-smoothing/\n * 3. http://maximilianhoffmann.com/posts/better-font-rendering-on-osx\n *    http://jaydenseric.com/blog/css-font-smoothing-for-firefox-mac\n */\nbody,\ninput,\ntextarea,\nselect,\nbutton {\n  text-rendering: optimizeLegibility;\n  /* 1 */\n  -webkit-font-smoothing: antialiased;\n  /* 2 */\n  -moz-osx-font-smoothing: grayscale;\n  /* 3 Default: auto */\n  -moz-font-feature-settings: \"liga\", \"kern\";\n}\n/*Only phones */\n@media only screen and (max-width: 640px) {\n  /**\n   * Break strings if their length exceeds the width of their container\n   */\n  body {\n    word-wrap: break-word;\n    -webkit-hyphens: auto;\n    -ms-hyphens: auto;\n    -moz-hyphens: auto;\n    hyphens: auto;\n  }\n}\n/**\n * links\n */\na {\n  color: #0e90d2;\n}\na:hover,\na:focus {\n  color: #095f8a;\n}\na:focus {\n  outline: thin dotted;\n  outline: 1px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n/* Insert */\nins {\n  background: #ffa;\n  color: #333333;\n}\n/**\n * Mark\n * Note: Addresses styling not present in IE 8/9.\n */\nmark {\n  background: #ffa;\n  color: #333333;\n}\n/**\n * Abbreviation and definition\n */\nabbr[title],\ndfn[title] {\n  cursor: help;\n}\ndfn[title] {\n  border-bottom: 1px dotted;\n  font-style: normal;\n}\n/* Spacing for block elements */\np,\nhr,\nul,\nol,\ndl,\nblockquote,\npre,\naddress,\nfieldset,\nfigure {\n  margin: 0 0 1.6rem 0;\n}\n* + p,\n* + hr,\n* + ul,\n* + ol,\n* + dl,\n* + blockquote,\n* + pre,\n* + address,\n* + fieldset,\n* + figure {\n  margin-top: 1.6rem;\n}\n/* Headings\n   ========================================================================== */\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 0 0 1.6rem 0;\n  font-weight: 600;\n  font-size: 100%;\n}\nh1 {\n  font-size: 1.5em;\n}\nh2 {\n  font-size: 1.25em;\n}\n* + h1,\n* + h2,\n* + h3,\n* + h4,\n* + h5,\n* + h6 {\n  margin-top: 2em;\n}\n/* Ordered and unordered lists */\nul,\nol {\n  padding-left: 2em;\n}\n/* Reset margin for nested lists */\nul > li > ul,\nul > li > ol,\nol > li > ol,\nol > li > ul {\n  margin: 1em 0;\n}\n/* Description lists */\ndt {\n  font-weight: bold;\n}\ndt + dd {\n  margin-top: .5em;\n}\ndd {\n  margin-left: 0;\n}\ndd + dt {\n  margin-top: 1em;\n}\n/**\n * Horizontal rule\n * 1. Address differences between Firefox and other browsers.\n */\nhr {\n  display: block;\n  padding: 0;\n  border: 0;\n  height: 0;\n  border-top: 1px solid #eeeeee;\n  /* 1 */\n  -webkit-box-sizing: content-box;\n          box-sizing: content-box;\n  /* 1 */\n}\n/* Address */\naddress {\n  font-style: normal;\n}\n/* Quotes */\nblockquote {\n  padding-top: 5px;\n  padding-bottom: 5px;\n  padding-left: 15px;\n  border-left: 4px solid #ddd;\n  font-family: Georgia, \"Times New Roman\", Times, Kai, \"Kaiti SC\", KaiTi, BiauKai, \"FontAwesome\", serif;\n  /* Small print for identifying the source */\n  /* Smaller margin if `small` follows */\n}\nblockquote small {\n  display: block;\n  color: #999999;\n  font-family: \"Segoe UI\", \"Lucida Grande\", Helvetica, Arial, \"Microsoft YaHei\", FreeSans, Arimo, \"Droid Sans\", \"wenquanyi micro hei\", \"Hiragino Sans GB\", \"Hiragino Sans GB W3\", \"FontAwesome\", sans-serif;\n  text-align: right;\n}\nblockquote p:last-of-type {\n  margin-bottom: 0;\n}\n/* iframe */\niframe {\n  border: 0;\n}\n/* Forms\n   ========================================================================== */\n/**\n  * Vertical alignment\n  * Exclude `radio` and `checkbox` elements because the default `baseline` value aligns better with text\n  */\nbutton,\ninput:not([type=\"radio\"]):not([type=\"checkbox\"]),\nselect {\n  vertical-align: middle;\n}\n/**\n * Fix viewport for IE10 snap mode\n * http://timkadlec.com/2012/10/ie10-snap-mode-and-responsive-design/\n * http://msdn.microsoft.com/en-us/library/ie/hh869615%28v=vs.85%29.aspx\n * http://msdn.microsoft.com/zh-cn/library/ie/hh708740(v=vs.85).aspx\n * @2014.01.20: 设置一下属性以后，windows Phone 8 上显示的字体过小，暂时注释掉\n * ========================================================================== */\n/*\n@-ms-viewport {\n  width: device-width;\n}\n*/\n.am-scrollbar-measure {\n  width: 100px;\n  height: 100px;\n  overflow: scroll;\n  position: absolute;\n  top: -9999px;\n}\n/* ==========================================================================\n   Component: Grid\n ============================================================================ */\n.am-container {\n  -webkit-box-sizing: border-box;\n          box-sizing: border-box;\n  margin-left: auto;\n  margin-right: auto;\n  padding-left: 1rem;\n  padding-right: 1rem;\n  width: 100%;\n  max-width: 1300px;\n}\n.am-container:before,\n.am-container:after {\n  content: \" \";\n  display: table;\n}\n.am-container:after {\n  clear: both;\n}\n@media only screen and (min-width:641px) {\n  .am-container {\n    padding-left: 1.5rem;\n    padding-right: 1.5rem;\n  }\n}\n.am-container > .am-g {\n  width: auto;\n  margin-left: -1rem;\n  margin-right: -1rem;\n}\n@media only screen and (min-width:641px) {\n  .am-container > .am-g {\n    margin-left: -1.5rem;\n    margin-right: -1.5rem;\n  }\n}\n.am-g {\n  margin: 0 auto;\n  width: 100%;\n}\n.am-g:before,\n.am-g:after {\n  content: \" \";\n  display: table;\n}\n.am-g:after {\n  clear: both;\n}\n.am-g .am-g {\n  margin-left: -1rem;\n  margin-right: -1rem;\n  width: auto;\n}\n.am-g .am-g.am-g-collapse {\n  margin-left: 0;\n  margin-right: 0;\n  width: auto;\n}\n@media only screen and (min-width:641px) {\n  .am-g .am-g {\n    margin-left: -1.5rem;\n    margin-right: -1.5rem;\n  }\n}\n.am-g.am-g-collapse .am-g {\n  margin-left: 0;\n  margin-right: 0;\n}\n.am-g-collapse [class*=\"am-u-\"] {\n  padding-left: 0;\n  padding-right: 0;\n}\n.am-g-fixed {\n  max-width: 1000px;\n}\n[class*=\"am-u-\"] {\n  width: 100%;\n  padding-left: 1rem;\n  padding-right: 1rem;\n  float: left;\n  position: relative;\n}\n[class*=\"am-u-\"] + [class*=\"am-u-\"]:last-child {\n  float: right;\n}\n[class*=\"am-u-\"] + [class*=\"am-u-\"].am-u-end {\n  float: left;\n}\n@media only screen and (min-width:641px) {\n  [class*=\"am-u-\"] {\n    padding-left: 1.5rem;\n    padding-right: 1.5rem;\n  }\n}\n[class*=\"am-u-pull-\"] {\n  left: auto;\n}\n[class*=\"am-u-push-\"] {\n  right: auto;\n}\n@media only screen {\n  .am-u-sm-1 {\n    width: 8.33333333%;\n  }\n  .am-u-sm-2 {\n    width: 16.66666667%;\n  }\n  .am-u-sm-3 {\n    width: 25%;\n  }\n  .am-u-sm-4 {\n    width: 33.33333333%;\n  }\n  .am-u-sm-5 {\n    width: 41.66666667%;\n  }\n  .am-u-sm-6 {\n    width: 50%;\n  }\n  .am-u-sm-7 {\n    width: 58.33333333%;\n  }\n  .am-u-sm-8 {\n    width: 66.66666667%;\n  }\n  .am-u-sm-9 {\n    width: 75%;\n  }\n  .am-u-sm-10 {\n    width: 83.33333333%;\n  }\n  .am-u-sm-11 {\n    width: 91.66666667%;\n  }\n  .am-u-sm-12 {\n    width: 100%;\n  }\n  .am-u-sm-pull-0 {\n    right: 0;\n  }\n  .am-u-sm-pull-1 {\n    right: 8.33333333%;\n  }\n  .am-u-sm-pull-2 {\n    right: 16.66666667%;\n  }\n  .am-u-sm-pull-3 {\n    right: 25%;\n  }\n  .am-u-sm-pull-4 {\n    right: 33.33333333%;\n  }\n  .am-u-sm-pull-5 {\n    right: 41.66666667%;\n  }\n  .am-u-sm-pull-6 {\n    right: 50%;\n  }\n  .am-u-sm-pull-7 {\n    right: 58.33333333%;\n  }\n  .am-u-sm-pull-8 {\n    right: 66.66666667%;\n  }\n  .am-u-sm-pull-9 {\n    right: 75%;\n  }\n  .am-u-sm-pull-10 {\n    right: 83.33333333%;\n  }\n  .am-u-sm-pull-11 {\n    right: 91.66666667%;\n  }\n  .am-u-sm-push-0 {\n    left: 0;\n  }\n  .am-u-sm-push-1 {\n    left: 8.33333333%;\n  }\n  .am-u-sm-push-2 {\n    left: 16.66666667%;\n  }\n  .am-u-sm-push-3 {\n    left: 25%;\n  }\n  .am-u-sm-push-4 {\n    left: 33.33333333%;\n  }\n  .am-u-sm-push-5 {\n    left: 41.66666667%;\n  }\n  .am-u-sm-push-6 {\n    left: 50%;\n  }\n  .am-u-sm-push-7 {\n    left: 58.33333333%;\n  }\n  .am-u-sm-push-8 {\n    left: 66.66666667%;\n  }\n  .am-u-sm-push-9 {\n    left: 75%;\n  }\n  .am-u-sm-push-10 {\n    left: 83.33333333%;\n  }\n  .am-u-sm-push-11 {\n    left: 91.66666667%;\n  }\n  .am-u-sm-offset-0 {\n    margin-left: 0;\n  }\n  .am-u-sm-offset-1 {\n    margin-left: 8.33333333%;\n  }\n  .am-u-sm-offset-2 {\n    margin-left: 16.66666667%;\n  }\n  .am-u-sm-offset-3 {\n    margin-left: 25%;\n  }\n  .am-u-sm-offset-4 {\n    margin-left: 33.33333333%;\n  }\n  .am-u-sm-offset-5 {\n    margin-left: 41.66666667%;\n  }\n  .am-u-sm-offset-6 {\n    margin-left: 50%;\n  }\n  .am-u-sm-offset-7 {\n    margin-left: 58.33333333%;\n  }\n  .am-u-sm-offset-8 {\n    margin-left: 66.66666667%;\n  }\n  .am-u-sm-offset-9 {\n    margin-left: 75%;\n  }\n  .am-u-sm-offset-10 {\n    margin-left: 83.33333333%;\n  }\n  .am-u-sm-offset-11 {\n    margin-left: 91.66666667%;\n  }\n  .am-u-sm-reset-order {\n    margin-left: 0;\n    margin-right: 0;\n    left: auto;\n    right: auto;\n    float: left;\n  }\n  [class*=\"am-u-\"].am-u-sm-centered {\n    margin-left: auto;\n    margin-right: auto;\n    float: none;\n  }\n  [class*=\"am-u-\"].am-u-sm-centered:last-child {\n    float: none;\n  }\n  [class*=\"am-u-\"].am-u-sm-uncentered {\n    margin-left: 0;\n    margin-right: 0;\n    float: left;\n  }\n  [class*=\"am-u-\"].am-u-sm-uncentered:last-child {\n    float: left;\n  }\n}\n@media only screen and (min-width:641px) {\n  .am-u-md-1 {\n    width: 8.33333333%;\n  }\n  .am-u-md-2 {\n    width: 16.66666667%;\n  }\n  .am-u-md-3 {\n    width: 25%;\n  }\n  .am-u-md-4 {\n    width: 33.33333333%;\n  }\n  .am-u-md-5 {\n    width: 41.66666667%;\n  }\n  .am-u-md-6 {\n    width: 50%;\n  }\n  .am-u-md-7 {\n    width: 58.33333333%;\n  }\n  .am-u-md-8 {\n    width: 66.66666667%;\n  }\n  .am-u-md-9 {\n    width: 75%;\n  }\n  .am-u-md-10 {\n    width: 83.33333333%;\n  }\n  .am-u-md-11 {\n    width: 91.66666667%;\n  }\n  .am-u-md-12 {\n    width: 100%;\n  }\n  .am-u-md-pull-0 {\n    right: 0;\n  }\n  .am-u-md-pull-1 {\n    right: 8.33333333%;\n  }\n  .am-u-md-pull-2 {\n    right: 16.66666667%;\n  }\n  .am-u-md-pull-3 {\n    right: 25%;\n  }\n  .am-u-md-pull-4 {\n    right: 33.33333333%;\n  }\n  .am-u-md-pull-5 {\n    right: 41.66666667%;\n  }\n  .am-u-md-pull-6 {\n    right: 50%;\n  }\n  .am-u-md-pull-7 {\n    right: 58.33333333%;\n  }\n  .am-u-md-pull-8 {\n    right: 66.66666667%;\n  }\n  .am-u-md-pull-9 {\n    right: 75%;\n  }\n  .am-u-md-pull-10 {\n    right: 83.33333333%;\n  }\n  .am-u-md-pull-11 {\n    right: 91.66666667%;\n  }\n  .am-u-md-push-0 {\n    left: 0;\n  }\n  .am-u-md-push-1 {\n    left: 8.33333333%;\n  }\n  .am-u-md-push-2 {\n    left: 16.66666667%;\n  }\n  .am-u-md-push-3 {\n    left: 25%;\n  }\n  .am-u-md-push-4 {\n    left: 33.33333333%;\n  }\n  .am-u-md-push-5 {\n    left: 41.66666667%;\n  }\n  .am-u-md-push-6 {\n    left: 50%;\n  }\n  .am-u-md-push-7 {\n    left: 58.33333333%;\n  }\n  .am-u-md-push-8 {\n    left: 66.66666667%;\n  }\n  .am-u-md-push-9 {\n    left: 75%;\n  }\n  .am-u-md-push-10 {\n    left: 83.33333333%;\n  }\n  .am-u-md-push-11 {\n    left: 91.66666667%;\n  }\n  .am-u-md-offset-0 {\n    margin-left: 0;\n  }\n  .am-u-md-offset-1 {\n    margin-left: 8.33333333%;\n  }\n  .am-u-md-offset-2 {\n    margin-left: 16.66666667%;\n  }\n  .am-u-md-offset-3 {\n    margin-left: 25%;\n  }\n  .am-u-md-offset-4 {\n    margin-left: 33.33333333%;\n  }\n  .am-u-md-offset-5 {\n    margin-left: 41.66666667%;\n  }\n  .am-u-md-offset-6 {\n    margin-left: 50%;\n  }\n  .am-u-md-offset-7 {\n    margin-left: 58.33333333%;\n  }\n  .am-u-md-offset-8 {\n    margin-left: 66.66666667%;\n  }\n  .am-u-md-offset-9 {\n    margin-left: 75%;\n  }\n  .am-u-md-offset-10 {\n    margin-left: 83.33333333%;\n  }\n  .am-u-md-offset-11 {\n    margin-left: 91.66666667%;\n  }\n  .am-u-md-reset-order {\n    margin-left: 0;\n    margin-right: 0;\n    left: auto;\n    right: auto;\n    float: left;\n  }\n  [class*=\"am-u-\"].am-u-md-centered {\n    margin-left: auto;\n    margin-right: auto;\n    float: none;\n  }\n  [class*=\"am-u-\"].am-u-md-centered:last-child {\n    float: none;\n  }\n  [class*=\"am-u-\"].am-u-md-uncentered {\n    margin-left: 0;\n    margin-right: 0;\n    float: left;\n  }\n  [class*=\"am-u-\"].am-u-md-uncentered:last-child {\n    float: left;\n  }\n}\n@media only screen and (min-width:1025px) {\n  .am-u-lg-1 {\n    width: 8.33333333%;\n  }\n  .am-u-lg-2 {\n    width: 16.66666667%;\n  }\n  .am-u-lg-3 {\n    width: 25%;\n  }\n  .am-u-lg-4 {\n    width: 33.33333333%;\n  }\n  .am-u-lg-5 {\n    width: 41.66666667%;\n  }\n  .am-u-lg-6 {\n    width: 50%;\n  }\n  .am-u-lg-7 {\n    width: 58.33333333%;\n  }\n  .am-u-lg-8 {\n    width: 66.66666667%;\n  }\n  .am-u-lg-9 {\n    width: 75%;\n  }\n  .am-u-lg-10 {\n    width: 83.33333333%;\n  }\n  .am-u-lg-11 {\n    width: 91.66666667%;\n  }\n  .am-u-lg-12 {\n    width: 100%;\n  }\n  .am-u-lg-pull-0 {\n    right: 0;\n  }\n  .am-u-lg-pull-1 {\n    right: 8.33333333%;\n  }\n  .am-u-lg-pull-2 {\n    right: 16.66666667%;\n  }\n  .am-u-lg-pull-3 {\n    right: 25%;\n  }\n  .am-u-lg-pull-4 {\n    right: 33.33333333%;\n  }\n  .am-u-lg-pull-5 {\n    right: 41.66666667%;\n  }\n  .am-u-lg-pull-6 {\n    right: 50%;\n  }\n  .am-u-lg-pull-7 {\n    right: 58.33333333%;\n  }\n  .am-u-lg-pull-8 {\n    right: 66.66666667%;\n  }\n  .am-u-lg-pull-9 {\n    right: 75%;\n  }\n  .am-u-lg-pull-10 {\n    right: 83.33333333%;\n  }\n  .am-u-lg-pull-11 {\n    right: 91.66666667%;\n  }\n  .am-u-lg-push-0 {\n    left: 0;\n  }\n  .am-u-lg-push-1 {\n    left: 8.33333333%;\n  }\n  .am-u-lg-push-2 {\n    left: 16.66666667%;\n  }\n  .am-u-lg-push-3 {\n    left: 25%;\n  }\n  .am-u-lg-push-4 {\n    left: 33.33333333%;\n  }\n  .am-u-lg-push-5 {\n    left: 41.66666667%;\n  }\n  .am-u-lg-push-6 {\n    left: 50%;\n  }\n  .am-u-lg-push-7 {\n    left: 58.33333333%;\n  }\n  .am-u-lg-push-8 {\n    left: 66.66666667%;\n  }\n  .am-u-lg-push-9 {\n    left: 75%;\n  }\n  .am-u-lg-push-10 {\n    left: 83.33333333%;\n  }\n  .am-u-lg-push-11 {\n    left: 91.66666667%;\n  }\n  .am-u-lg-offset-0 {\n    margin-left: 0;\n  }\n  .am-u-lg-offset-1 {\n    margin-left: 8.33333333%;\n  }\n  .am-u-lg-offset-2 {\n    margin-left: 16.66666667%;\n  }\n  .am-u-lg-offset-3 {\n    margin-left: 25%;\n  }\n  .am-u-lg-offset-4 {\n    margin-left: 33.33333333%;\n  }\n  .am-u-lg-offset-5 {\n    margin-left: 41.66666667%;\n  }\n  .am-u-lg-offset-6 {\n    margin-left: 50%;\n  }\n  .am-u-lg-offset-7 {\n    margin-left: 58.33333333%;\n  }\n  .am-u-lg-offset-8 {\n    margin-left: 66.66666667%;\n  }\n  .am-u-lg-offset-9 {\n    margin-left: 75%;\n  }\n  .am-u-lg-offset-10 {\n    margin-left: 83.33333333%;\n  }\n  .am-u-lg-offset-11 {\n    margin-left: 91.66666667%;\n  }\n  .am-u-lg-reset-order {\n    margin-left: 0;\n    margin-right: 0;\n    left: auto;\n    right: auto;\n    float: left;\n  }\n  [class*=\"am-u-\"].am-u-lg-centered {\n    margin-left: auto;\n    margin-right: auto;\n    float: none;\n  }\n  [class*=\"am-u-\"].am-u-lg-centered:last-child {\n    float: none;\n  }\n  [class*=\"am-u-\"].am-u-lg-uncentered {\n    margin-left: 0;\n    margin-right: 0;\n    float: left;\n  }\n  [class*=\"am-u-\"].am-u-lg-uncentered:last-child {\n    float: left;\n  }\n}\n/* ==========================================================================\n   Component: AVG Grid\n ============================================================================ */\n[class*=\"am-avg-\"] {\n  display: block;\n  padding: 0;\n  margin: 0;\n  list-style: none;\n}\n[class*=\"am-avg-\"]:before,\n[class*=\"am-avg-\"]:after {\n  content: \" \";\n  display: table;\n}\n[class*=\"am-avg-\"]:after {\n  clear: both;\n}\n[class*=\"am-avg-\"] > li {\n  display: block;\n  height: auto;\n  float: left;\n}\n@media only screen {\n  .am-avg-sm-1 > li {\n    width: 100%;\n  }\n  .am-avg-sm-1 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-1 > li:nth-of-type(1n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-2 > li {\n    width: 50%;\n  }\n  .am-avg-sm-2 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-2 > li:nth-of-type(2n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-3 > li {\n    width: 33.33333333%;\n  }\n  .am-avg-sm-3 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-3 > li:nth-of-type(3n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-4 > li {\n    width: 25%;\n  }\n  .am-avg-sm-4 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-4 > li:nth-of-type(4n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-5 > li {\n    width: 20%;\n  }\n  .am-avg-sm-5 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-5 > li:nth-of-type(5n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-6 > li {\n    width: 16.66666667%;\n  }\n  .am-avg-sm-6 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-6 > li:nth-of-type(6n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-7 > li {\n    width: 14.28571429%;\n  }\n  .am-avg-sm-7 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-7 > li:nth-of-type(7n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-8 > li {\n    width: 12.5%;\n  }\n  .am-avg-sm-8 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-8 > li:nth-of-type(8n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-9 > li {\n    width: 11.11111111%;\n  }\n  .am-avg-sm-9 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-9 > li:nth-of-type(9n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-10 > li {\n    width: 10%;\n  }\n  .am-avg-sm-10 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-10 > li:nth-of-type(10n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-11 > li {\n    width: 9.09090909%;\n  }\n  .am-avg-sm-11 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-11 > li:nth-of-type(11n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-12 > li {\n    width: 8.33333333%;\n  }\n  .am-avg-sm-12 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-12 > li:nth-of-type(12n + 1) {\n    clear: both;\n  }\n}\n@media only screen and (min-width:641px) {\n  .am-avg-md-1 > li {\n    width: 100%;\n  }\n  .am-avg-md-1 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-1 > li:nth-of-type(1n + 1) {\n    clear: both;\n  }\n  .am-avg-md-2 > li {\n    width: 50%;\n  }\n  .am-avg-md-2 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-2 > li:nth-of-type(2n + 1) {\n    clear: both;\n  }\n  .am-avg-md-3 > li {\n    width: 33.33333333%;\n  }\n  .am-avg-md-3 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-3 > li:nth-of-type(3n + 1) {\n    clear: both;\n  }\n  .am-avg-md-4 > li {\n    width: 25%;\n  }\n  .am-avg-md-4 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-4 > li:nth-of-type(4n + 1) {\n    clear: both;\n  }\n  .am-avg-md-5 > li {\n    width: 20%;\n  }\n  .am-avg-md-5 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-5 > li:nth-of-type(5n + 1) {\n    clear: both;\n  }\n  .am-avg-md-6 > li {\n    width: 16.66666667%;\n  }\n  .am-avg-md-6 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-6 > li:nth-of-type(6n + 1) {\n    clear: both;\n  }\n  .am-avg-md-7 > li {\n    width: 14.28571429%;\n  }\n  .am-avg-md-7 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-7 > li:nth-of-type(7n + 1) {\n    clear: both;\n  }\n  .am-avg-md-8 > li {\n    width: 12.5%;\n  }\n  .am-avg-md-8 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-8 > li:nth-of-type(8n + 1) {\n    clear: both;\n  }\n  .am-avg-md-9 > li {\n    width: 11.11111111%;\n  }\n  .am-avg-md-9 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-9 > li:nth-of-type(9n + 1) {\n    clear: both;\n  }\n  .am-avg-md-10 > li {\n    width: 10%;\n  }\n  .am-avg-md-10 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-10 > li:nth-of-type(10n + 1) {\n    clear: both;\n  }\n  .am-avg-md-11 > li {\n    width: 9.09090909%;\n  }\n  .am-avg-md-11 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-11 > li:nth-of-type(11n + 1) {\n    clear: both;\n  }\n  .am-avg-md-12 > li {\n    width: 8.33333333%;\n  }\n  .am-avg-md-12 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-12 > li:nth-of-type(12n + 1) {\n    clear: both;\n  }\n}\n@media only screen and (min-width:1025px) {\n  .am-avg-lg-1 > li {\n    width: 100%;\n  }\n  .am-avg-lg-1 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-1 > li:nth-of-type(1n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-2 > li {\n    width: 50%;\n  }\n  .am-avg-lg-2 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-2 > li:nth-of-type(2n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-3 > li {\n    width: 33.33333333%;\n  }\n  .am-avg-lg-3 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-3 > li:nth-of-type(3n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-4 > li {\n    width: 25%;\n  }\n  .am-avg-lg-4 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-4 > li:nth-of-type(4n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-5 > li {\n    width: 20%;\n  }\n  .am-avg-lg-5 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-5 > li:nth-of-type(5n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-6 > li {\n    width: 16.66666667%;\n  }\n  .am-avg-lg-6 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-6 > li:nth-of-type(6n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-7 > li {\n    width: 14.28571429%;\n  }\n  .am-avg-lg-7 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-7 > li:nth-of-type(7n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-8 > li {\n    width: 12.5%;\n  }\n  .am-avg-lg-8 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-8 > li:nth-of-type(8n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-9 > li {\n    width: 11.11111111%;\n  }\n  .am-avg-lg-9 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-9 > li:nth-of-type(9n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-10 > li {\n    width: 10%;\n  }\n  .am-avg-lg-10 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-10 > li:nth-of-type(10n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-11 > li {\n    width: 9.09090909%;\n  }\n  .am-avg-lg-11 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-11 > li:nth-of-type(11n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-12 > li {\n    width: 8.33333333%;\n  }\n  .am-avg-lg-12 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-12 > li:nth-of-type(12n + 1) {\n    clear: both;\n  }\n}\n/* ==========================================================================\n   Component: Code\n ============================================================================ */\n/* Inline and block code styles */\ncode,\nkbd,\npre,\nsamp {\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", \"FontAwesome\", monospace;\n}\n/* Inline code */\ncode {\n  padding: 2px 4px;\n  font-size: 1.3rem;\n  color: #c7254e;\n  background-color: #f8f8f8;\n  white-space: nowrap;\n  border-radius: 0;\n}\n/* Code block */\npre {\n  display: block;\n  padding: 1rem;\n  margin: 1rem  0;\n  font-size: 1.3rem;\n  line-height: 1.6;\n  word-break: break-all;\n  word-wrap: break-word;\n  color: #555555;\n  background-color: #f8f8f8;\n  border: 1px solid #dedede;\n  border-radius: 0;\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/* Enable scrollable blocks of code */\n.am-pre-scrollable {\n  max-height: 24rem;\n  overflow-y: scroll;\n}\n/* ==========================================================================\n   Component: Button\n ============================================================================ */\n.am-btn {\n  display: inline-block;\n  margin-bottom: 0;\n  padding: 0.5em 1em;\n  vertical-align: middle;\n  font-size: 1.6rem;\n  font-weight: normal;\n  line-height: 1.2;\n  text-align: center;\n  white-space: nowrap;\n  background-image: none;\n  border: 1px solid transparent;\n  border-radius: 0;\n  cursor: pointer;\n  outline: none;\n  -webkit-appearance: none;\n  -webkit-user-select: none;\n     -moz-user-select: none;\n      -ms-user-select: none;\n          user-select: none;\n  -webkit-transition: background-color 300ms ease-out, border-color 300ms ease-out;\n  transition: background-color 300ms ease-out, border-color 300ms ease-out;\n}\n.am-btn:focus,\n.am-btn:active:focus {\n  outline: thin dotted;\n  outline: 1px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n.am-btn:hover,\n.am-btn:focus {\n  color: #444;\n  text-decoration: none;\n}\n.am-btn:active,\n.am-btn.am-active {\n  background-image: none;\n  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.15);\n}\n.am-btn.am-disabled,\n.am-btn[disabled],\nfieldset[disabled] .am-btn {\n  pointer-events: none;\n  border-color: transparent;\n  cursor: not-allowed;\n  opacity: 0.45;\n  -webkit-box-shadow: none;\n          box-shadow: none;\n}\n.am-btn.am-round {\n  border-radius: 1000px;\n}\n.am-btn.am-radius {\n  border-radius: 2px;\n}\n.am-btn-default {\n  color: #444;\n  background-color: #e6e6e6;\n  border-color: #e6e6e6;\n}\na.am-btn-default:visited {\n  color: #444;\n}\n.am-btn-default:hover,\n.am-btn-default:focus,\n.am-btn-default:active,\n.am-btn-default.am-active,\n.am-active .am-btn-default.am-dropdown-toggle {\n  color: #444;\n  border-color: #c7c7c7;\n}\n.am-btn-default:hover,\n.am-btn-default:focus {\n  background-color: #d4d4d4;\n}\n.am-btn-default:active,\n.am-btn-default.am-active,\n.am-active .am-btn-default.am-dropdown-toggle {\n  background-image: none;\n  background-color: #c2c2c2;\n}\n.am-btn-default.am-disabled,\n.am-btn-default[disabled],\nfieldset[disabled] .am-btn-default,\n.am-btn-default.am-disabled:hover,\n.am-btn-default[disabled]:hover,\nfieldset[disabled] .am-btn-default:hover,\n.am-btn-default.am-disabled:focus,\n.am-btn-default[disabled]:focus,\nfieldset[disabled] .am-btn-default:focus,\n.am-btn-default.am-disabled:active,\n.am-btn-default[disabled]:active,\nfieldset[disabled] .am-btn-default:active,\n.am-btn-default.am-disabled.am-active,\n.am-btn-default[disabled].am-active,\nfieldset[disabled] .am-btn-default.am-active {\n  background-color: #e6e6e6;\n  border-color: #e6e6e6;\n}\n.am-btn-group .am-btn-default,\n.am-btn-group-stacked .am-btn-default {\n  border-color: #d9d9d9;\n}\n.am-btn-primary {\n  color: #fff;\n  background-color: #0e90d2;\n  border-color: #0e90d2;\n}\na.am-btn-primary:visited {\n  color: #fff;\n}\n.am-btn-primary:hover,\n.am-btn-primary:focus,\n.am-btn-primary:active,\n.am-btn-primary.am-active,\n.am-active .am-btn-primary.am-dropdown-toggle {\n  color: #fff;\n  border-color: #0a6999;\n}\n.am-btn-primary:hover,\n.am-btn-primary:focus {\n  background-color: #0c79b1;\n}\n.am-btn-primary:active,\n.am-btn-primary.am-active,\n.am-active .am-btn-primary.am-dropdown-toggle {\n  background-image: none;\n  background-color: #0a628f;\n}\n.am-btn-primary.am-disabled,\n.am-btn-primary[disabled],\nfieldset[disabled] .am-btn-primary,\n.am-btn-primary.am-disabled:hover,\n.am-btn-primary[disabled]:hover,\nfieldset[disabled] .am-btn-primary:hover,\n.am-btn-primary.am-disabled:focus,\n.am-btn-primary[disabled]:focus,\nfieldset[disabled] .am-btn-primary:focus,\n.am-btn-primary.am-disabled:active,\n.am-btn-primary[disabled]:active,\nfieldset[disabled] .am-btn-primary:active,\n.am-btn-primary.am-disabled.am-active,\n.am-btn-primary[disabled].am-active,\nfieldset[disabled] .am-btn-primary.am-active {\n  background-color: #0e90d2;\n  border-color: #0e90d2;\n}\n.am-btn-group .am-btn-primary,\n.am-btn-group-stacked .am-btn-primary {\n  border-color: #0c80ba;\n}\n.am-btn-warning {\n  color: #fff;\n  background-color: #F37B1D;\n  border-color: #F37B1D;\n}\na.am-btn-warning:visited {\n  color: #fff;\n}\n.am-btn-warning:hover,\n.am-btn-warning:focus,\n.am-btn-warning:active,\n.am-btn-warning.am-active,\n.am-active .am-btn-warning.am-dropdown-toggle {\n  color: #fff;\n  border-color: #c85e0b;\n}\n.am-btn-warning:hover,\n.am-btn-warning:focus {\n  background-color: #e0690c;\n}\n.am-btn-warning:active,\n.am-btn-warning.am-active,\n.am-active .am-btn-warning.am-dropdown-toggle {\n  background-image: none;\n  background-color: #be590a;\n}\n.am-btn-warning.am-disabled,\n.am-btn-warning[disabled],\nfieldset[disabled] .am-btn-warning,\n.am-btn-warning.am-disabled:hover,\n.am-btn-warning[disabled]:hover,\nfieldset[disabled] .am-btn-warning:hover,\n.am-btn-warning.am-disabled:focus,\n.am-btn-warning[disabled]:focus,\nfieldset[disabled] .am-btn-warning:focus,\n.am-btn-warning.am-disabled:active,\n.am-btn-warning[disabled]:active,\nfieldset[disabled] .am-btn-warning:active,\n.am-btn-warning.am-disabled.am-active,\n.am-btn-warning[disabled].am-active,\nfieldset[disabled] .am-btn-warning.am-active {\n  background-color: #F37B1D;\n  border-color: #F37B1D;\n}\n.am-btn-group .am-btn-warning,\n.am-btn-group-stacked .am-btn-warning {\n  border-color: #ea6e0c;\n}\n.am-btn-danger {\n  color: #fff;\n  background-color: #dd514c;\n  border-color: #dd514c;\n}\na.am-btn-danger:visited {\n  color: #fff;\n}\n.am-btn-danger:hover,\n.am-btn-danger:focus,\n.am-btn-danger:active,\n.am-btn-danger.am-active,\n.am-active .am-btn-danger.am-dropdown-toggle {\n  color: #fff;\n  border-color: #c62b26;\n}\n.am-btn-danger:hover,\n.am-btn-danger:focus {\n  background-color: #d7342e;\n}\n.am-btn-danger:active,\n.am-btn-danger.am-active,\n.am-active .am-btn-danger.am-dropdown-toggle {\n  background-image: none;\n  background-color: #be2924;\n}\n.am-btn-danger.am-disabled,\n.am-btn-danger[disabled],\nfieldset[disabled] .am-btn-danger,\n.am-btn-danger.am-disabled:hover,\n.am-btn-danger[disabled]:hover,\nfieldset[disabled] .am-btn-danger:hover,\n.am-btn-danger.am-disabled:focus,\n.am-btn-danger[disabled]:focus,\nfieldset[disabled] .am-btn-danger:focus,\n.am-btn-danger.am-disabled:active,\n.am-btn-danger[disabled]:active,\nfieldset[disabled] .am-btn-danger:active,\n.am-btn-danger.am-disabled.am-active,\n.am-btn-danger[disabled].am-active,\nfieldset[disabled] .am-btn-danger.am-active {\n  background-color: #dd514c;\n  border-color: #dd514c;\n}\n.am-btn-group .am-btn-danger,\n.am-btn-group-stacked .am-btn-danger {\n  border-color: #d93c37;\n}\n.am-btn-success {\n  color: #fff;\n  background-color: #5eb95e;\n  border-color: #5eb95e;\n}\na.am-btn-success:visited {\n  color: #fff;\n}\n.am-btn-success:hover,\n.am-btn-success:focus,\n.am-btn-success:active,\n.am-btn-success.am-active,\n.am-active .am-btn-success.am-dropdown-toggle {\n  color: #fff;\n  border-color: #429842;\n}\n.am-btn-success:hover,\n.am-btn-success:focus {\n  background-color: #4aaa4a;\n}\n.am-btn-success:active,\n.am-btn-success.am-active,\n.am-active .am-btn-success.am-dropdown-toggle {\n  background-image: none;\n  background-color: #3f913f;\n}\n.am-btn-success.am-disabled,\n.am-btn-success[disabled],\nfieldset[disabled] .am-btn-success,\n.am-btn-success.am-disabled:hover,\n.am-btn-success[disabled]:hover,\nfieldset[disabled] .am-btn-success:hover,\n.am-btn-success.am-disabled:focus,\n.am-btn-success[disabled]:focus,\nfieldset[disabled] .am-btn-success:focus,\n.am-btn-success.am-disabled:active,\n.am-btn-success[disabled]:active,\nfieldset[disabled] .am-btn-success:active,\n.am-btn-success.am-disabled.am-active,\n.am-btn-success[disabled].am-active,\nfieldset[disabled] .am-btn-success.am-active {\n  background-color: #5eb95e;\n  border-color: #5eb95e;\n}\n.am-btn-group .am-btn-success,\n.am-btn-group-stacked .am-btn-success {\n  border-color: #4db14d;\n}\n.am-btn-secondary {\n  color: #fff;\n  background-color: #3bb4f2;\n  border-color: #3bb4f2;\n}\na.am-btn-secondary:visited {\n  color: #fff;\n}\n.am-btn-secondary:hover,\n.am-btn-secondary:focus,\n.am-btn-secondary:active,\n.am-btn-secondary.am-active,\n.am-active .am-btn-secondary.am-dropdown-toggle {\n  color: #fff;\n  border-color: #0f9ae0;\n}\n.am-btn-secondary:hover,\n.am-btn-secondary:focus {\n  background-color: #19a7f0;\n}\n.am-btn-secondary:active,\n.am-btn-secondary.am-active,\n.am-active .am-btn-secondary.am-dropdown-toggle {\n  background-image: none;\n  background-color: #0e93d7;\n}\n.am-btn-secondary.am-disabled,\n.am-btn-secondary[disabled],\nfieldset[disabled] .am-btn-secondary,\n.am-btn-secondary.am-disabled:hover,\n.am-btn-secondary[disabled]:hover,\nfieldset[disabled] .am-btn-secondary:hover,\n.am-btn-secondary.am-disabled:focus,\n.am-btn-secondary[disabled]:focus,\nfieldset[disabled] .am-btn-secondary:focus,\n.am-btn-secondary.am-disabled:active,\n.am-btn-secondary[disabled]:active,\nfieldset[disabled] .am-btn-secondary:active,\n.am-btn-secondary.am-disabled.am-active,\n.am-btn-secondary[disabled].am-active,\nfieldset[disabled] .am-btn-secondary.am-active {\n  background-color: #3bb4f2;\n  border-color: #3bb4f2;\n}\n.am-btn-group .am-btn-secondary,\n.am-btn-group-stacked .am-btn-secondary {\n  border-color: #23abf0;\n}\n/* Style links like a button */\n.am-btn-link {\n  color: #0e90d2;\n  font-weight: normal;\n  cursor: pointer;\n  border-radius: 0;\n}\n.am-btn-link,\n.am-btn-link:active,\n.am-btn-link[disabled],\nfieldset[disabled] .am-btn-link {\n  background-color: transparent;\n  -webkit-box-shadow: none;\n          box-shadow: none;\n}\n.am-btn-link,\n.am-btn-link:hover,\n.am-btn-link:focus,\n.am-btn-link:active {\n  border-color: transparent;\n}\n.am-btn-link:hover,\n.am-btn-link:focus {\n  color: #095f8a;\n  text-decoration: underline;\n  background-color: transparent;\n}\n.am-btn-link[disabled]:hover,\nfieldset[disabled] .am-btn-link:hover,\n.am-btn-link[disabled]:focus,\nfieldset[disabled] .am-btn-link:focus {\n  color: #999999;\n  text-decoration: none;\n}\n/* button size */\n.am-btn-xs {\n  font-size: 1.2rem;\n}\n.am-btn-sm {\n  font-size: 1.4rem;\n}\n.am-btn-lg {\n  font-size: 1.8rem;\n}\n.am-btn-xl {\n  font-size: 2rem;\n}\n/* Block button  */\n.am-btn-block {\n  display: block;\n  width: 100%;\n  padding-left: 0;\n  padding-right: 0;\n}\n/* Multiple block buttons vertically space */\n.am-btn-block + .am-btn-block {\n  margin-top: 5px;\n}\n/* Specificity overrides */\ninput[type=\"submit\"].am-btn-block,\ninput[type=\"reset\"].am-btn-block,\ninput[type=\"button\"].am-btn-block {\n  width: 100%;\n}\n/* Button with loading spinner */\n.am-btn.am-btn-loading .am-icon-spin {\n  margin-right: 5px;\n}\n/* ==========================================================================\n   Component: Table\n ============================================================================ */\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  empty-cells: show;\n}\ntable code {\n  white-space: normal;\n}\nth {\n  text-align: left;\n}\n.am-table {\n  width: 100%;\n  margin-bottom: 1.6rem;\n  border-spacing: 0;\n  border-collapse: separate;\n}\n.am-table > thead > tr > th,\n.am-table > tbody > tr > th,\n.am-table > tfoot > tr > th,\n.am-table > thead > tr > td,\n.am-table > tbody > tr > td,\n.am-table > tfoot > tr > td {\n  padding: 0.7rem;\n  line-height: 1.6;\n  vertical-align: top;\n  border-top: 1px solid #ddd;\n}\n.am-table > thead > tr > th {\n  vertical-align: bottom;\n  border-bottom: 1px solid #ddd;\n}\n.am-table > caption + thead > tr:first-child > th,\n.am-table > colgroup + thead > tr:first-child > th,\n.am-table > thead:first-child > tr:first-child > th,\n.am-table > caption + thead > tr:first-child > td,\n.am-table > colgroup + thead > tr:first-child > td,\n.am-table > thead:first-child > tr:first-child > td {\n  border-top: 0;\n}\n.am-table > tbody + tbody tr:first-child td {\n  border-top: 2px solid #ddd;\n}\n/* Bordered version */\n.am-table-bordered {\n  border: 1px solid #ddd;\n  border-left: none;\n}\n.am-table-bordered > thead > tr > th,\n.am-table-bordered > tbody > tr > th,\n.am-table-bordered > tfoot > tr > th,\n.am-table-bordered > thead > tr > td,\n.am-table-bordered > tbody > tr > td,\n.am-table-bordered > tfoot > tr > td {\n  border-left: 1px solid #ddd;\n  /*&:first-child {\n          border-left: none;\n        }*/\n}\n.am-table-bordered > tbody > tr:first-child > th,\n.am-table-bordered > tbody > tr:first-child > td {\n  border-top: none;\n}\n.am-table-bordered > thead + tbody > tr:first-child > th,\n.am-table-bordered > thead + tbody > tr:first-child > td {\n  border-top: 1px solid #ddd;\n}\n/* Border-radius version */\n.am-table-radius {\n  border: 1px solid #ddd;\n  border-radius: 2px;\n}\n.am-table-radius > thead > tr:first-child > th:first-child,\n.am-table-radius > thead > tr:first-child > td:first-child {\n  border-top-left-radius: 2px;\n  border-left: none;\n}\n.am-table-radius > thead > tr:first-child > th:last-child,\n.am-table-radius > thead > tr:first-child > td:last-child {\n  border-top-right-radius: 2px;\n  border-right: none;\n}\n.am-table-radius > tbody > tr > th:first-child,\n.am-table-radius > tbody > tr > td:first-child {\n  border-left: none;\n}\n.am-table-radius > tbody > tr > th:last-child,\n.am-table-radius > tbody > tr > td:last-child {\n  border-right: none;\n}\n.am-table-radius > tbody > tr:last-child > th,\n.am-table-radius > tbody > tr:last-child > td {\n  border-bottom: none;\n}\n.am-table-radius > tbody > tr:last-child > th:first-child,\n.am-table-radius > tbody > tr:last-child > td:first-child {\n  border-bottom-left-radius: 2px;\n}\n.am-table-radius > tbody > tr:last-child > th:last-child,\n.am-table-radius > tbody > tr:last-child > td:last-child {\n  border-bottom-right-radius: 2px;\n}\n/* Zebra-striping */\n.am-table-striped > tbody > tr:nth-child(odd) > td,\n.am-table-striped > tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n/* Hover effect */\n.am-table-hover > tbody > tr:hover > td,\n.am-table-hover > tbody > tr:hover > th {\n  background-color: #e9e9e9;\n}\n.am-table-compact > thead > tr > th,\n.am-table-compact > tbody > tr > th,\n.am-table-compact > tfoot > tr > th,\n.am-table-compact > thead > tr > td,\n.am-table-compact > tbody > tr > td,\n.am-table-compact > tfoot > tr > td {\n  padding: 0.4rem;\n}\n.am-table-centered > thead > tr > th,\n.am-table-centered > tbody > tr > th,\n.am-table-centered > tfoot > tr > th,\n.am-table-centered > thead > tr > td,\n.am-table-centered > tbody > tr > td,\n.am-table-centered > tfoot > tr > td {\n  text-align: center;\n}\n.am-table > thead > tr > td.am-active,\n.am-table > tbody > tr > td.am-active,\n.am-table > tfoot > tr > td.am-active,\n.am-table > thead > tr > th.am-active,\n.am-table > tbody > tr > th.am-active,\n.am-table > tfoot > tr > th.am-active,\n.am-table > thead > tr.am-active > td,\n.am-table > tbody > tr.am-active > td,\n.am-table > tfoot > tr.am-active > td,\n.am-table > thead > tr.am-active > th,\n.am-table > tbody > tr.am-active > th,\n.am-table > tfoot > tr.am-active > th {\n  background-color: #ffd;\n}\n.am-table > thead > tr > td.am-disabled,\n.am-table > tbody > tr > td.am-disabled,\n.am-table > tfoot > tr > td.am-disabled,\n.am-table > thead > tr > th.am-disabled,\n.am-table > tbody > tr > th.am-disabled,\n.am-table > tfoot > tr > th.am-disabled,\n.am-table > thead > tr.am-disabled > td,\n.am-table > tbody > tr.am-disabled > td,\n.am-table > tfoot > tr.am-disabled > td,\n.am-table > thead > tr.am-disabled > th,\n.am-table > tbody > tr.am-disabled > th,\n.am-table > tfoot > tr.am-disabled > th {\n  color: #999999;\n}\n.am-table > thead > tr > td.am-primary,\n.am-table > tbody > tr > td.am-primary,\n.am-table > tfoot > tr > td.am-primary,\n.am-table > thead > tr > th.am-primary,\n.am-table > tbody > tr > th.am-primary,\n.am-table > tfoot > tr > th.am-primary,\n.am-table > thead > tr.am-primary > td,\n.am-table > tbody > tr.am-primary > td,\n.am-table > tfoot > tr.am-primary > td,\n.am-table > thead > tr.am-primary > th,\n.am-table > tbody > tr.am-primary > th,\n.am-table > tfoot > tr.am-primary > th {\n  color: #0b76ac;\n  background-color: rgba(14, 144, 210, 0.115);\n}\n.am-table > thead > tr > td.am-success,\n.am-table > tbody > tr > td.am-success,\n.am-table > tfoot > tr > td.am-success,\n.am-table > thead > tr > th.am-success,\n.am-table > tbody > tr > th.am-success,\n.am-table > tfoot > tr > th.am-success,\n.am-table > thead > tr.am-success > td,\n.am-table > tbody > tr.am-success > td,\n.am-table > tfoot > tr.am-success > td,\n.am-table > thead > tr.am-success > th,\n.am-table > tbody > tr.am-success > th,\n.am-table > tfoot > tr.am-success > th {\n  color: #5eb95e;\n  background-color: rgba(94, 185, 94, 0.115);\n}\n.am-table > thead > tr > td.am-warning,\n.am-table > tbody > tr > td.am-warning,\n.am-table > tfoot > tr > td.am-warning,\n.am-table > thead > tr > th.am-warning,\n.am-table > tbody > tr > th.am-warning,\n.am-table > tfoot > tr > th.am-warning,\n.am-table > thead > tr.am-warning > td,\n.am-table > tbody > tr.am-warning > td,\n.am-table > tfoot > tr.am-warning > td,\n.am-table > thead > tr.am-warning > th,\n.am-table > tbody > tr.am-warning > th,\n.am-table > tfoot > tr.am-warning > th {\n  color: #F37B1D;\n  background-color: rgba(243, 123, 29, 0.115);\n}\n.am-table > thead > tr > td.am-danger,\n.am-table > tbody > tr > td.am-danger,\n.am-table > tfoot > tr > td.am-danger,\n.am-table > thead > tr > th.am-danger,\n.am-table > tbody > tr > th.am-danger,\n.am-table > tfoot > tr > th.am-danger,\n.am-table > thead > tr.am-danger > td,\n.am-table > tbody > tr.am-danger > td,\n.am-table > tfoot > tr.am-danger > td,\n.am-table > thead > tr.am-danger > th,\n.am-table > tbody > tr.am-danger > th,\n.am-table > tfoot > tr.am-danger > th {\n  color: #dd514c;\n  background-color: rgba(221, 81, 76, 0.115);\n}\n/* ==========================================================================\n   Component: Form\n ============================================================================ */\n/* Normalize */\nfieldset {\n  border: none;\n}\nlegend {\n  display: block;\n  width: 100%;\n  margin-bottom: 2rem;\n  font-size: 2rem;\n  line-height: inherit;\n  color: #333333;\n  border-bottom: 1px solid #e5e5e5;\n  padding-bottom: 0.5rem;\n}\nlabel {\n  display: inline-block;\n  margin-bottom: 5px;\n  font-weight: bold;\n}\ninput[type=\"search\"] {\n  -webkit-box-sizing: border-box;\n          box-sizing: border-box;\n}\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  /* IE8-9 */\n  line-height: normal;\n}\ninput[type=\"file\"] {\n  display: block;\n}\nselect[multiple],\nselect[size] {\n  height: auto;\n}\nselect optgroup {\n  font-size: inherit;\n  font-style: inherit;\n  font-family: inherit;\n}\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted;\n  outline: 1px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\ninput[type=\"number\"]::-webkit-outer-spin-button,\ninput[type=\"number\"]::-webkit-inner-spin-button {\n  height: auto;\n}\noutput {\n  display: block;\n  padding-top: 1.6rem;\n  font-size: 1.6rem;\n  line-height: 1.6;\n  color: #555555;\n  vertical-align: middle;\n}\n/* Common form controls */\n.am-form select,\n.am-form textarea,\n.am-form input[type=\"text\"],\n.am-form input[type=\"password\"],\n.am-form input[type=\"datetime\"],\n.am-form input[type=\"datetime-local\"],\n.am-form input[type=\"date\"],\n.am-form input[type=\"month\"],\n.am-form input[type=\"time\"],\n.am-form input[type=\"week\"],\n.am-form input[type=\"number\"],\n.am-form input[type=\"email\"],\n.am-form input[type=\"url\"],\n.am-form input[type=\"search\"],\n.am-form input[type=\"tel\"],\n.am-form input[type=\"color\"],\n.am-form-field {\n  display: block;\n  width: 100%;\n  padding: 0.5em;\n  font-size: 1.6rem;\n  line-height: 1.2;\n  color: #555555;\n  vertical-align: middle;\n  background-color: #fff;\n  background-image: none;\n  border: 1px solid #ccc;\n  border-radius: 0;\n  -webkit-appearance: none;\n  -webkit-transition: border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;\n  transition: border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;\n  transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n  transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;\n}\n.am-form select:focus,\n.am-form textarea:focus,\n.am-form input[type=\"text\"]:focus,\n.am-form input[type=\"password\"]:focus,\n.am-form input[type=\"datetime\"]:focus,\n.am-form input[type=\"datetime-local\"]:focus,\n.am-form input[type=\"date\"]:focus,\n.am-form input[type=\"month\"]:focus,\n.am-form input[type=\"time\"]:focus,\n.am-form input[type=\"week\"]:focus,\n.am-form input[type=\"number\"]:focus,\n.am-form input[type=\"email\"]:focus,\n.am-form input[type=\"url\"]:focus,\n.am-form input[type=\"search\"]:focus,\n.am-form input[type=\"tel\"]:focus,\n.am-form input[type=\"color\"]:focus,\n.am-form-field:focus {\n  outline: 0;\n}\n.am-form select:focus,\n.am-form textarea:focus,\n.am-form input[type=\"text\"]:focus,\n.am-form input[type=\"password\"]:focus,\n.am-form input[type=\"datetime\"]:focus,\n.am-form input[type=\"datetime-local\"]:focus,\n.am-form input[type=\"date\"]:focus,\n.am-form input[type=\"month\"]:focus,\n.am-form input[type=\"time\"]:focus,\n.am-form input[type=\"week\"]:focus,\n.am-form input[type=\"number\"]:focus,\n.am-form input[type=\"email\"]:focus,\n.am-form input[type=\"url\"]:focus,\n.am-form input[type=\"search\"]:focus,\n.am-form input[type=\"tel\"]:focus,\n.am-form input[type=\"color\"]:focus,\n.am-form-field:focus {\n  background-color: #fefffe;\n  border-color: #3bb4f2;\n  outline: 0;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 5px rgba(59, 180, 242, 0.3);\n          box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 5px rgba(59, 180, 242, 0.3);\n}\n.am-form select::-webkit-input-placeholder,\n.am-form textarea::-webkit-input-placeholder,\n.am-form input[type=\"text\"]::-webkit-input-placeholder,\n.am-form input[type=\"password\"]::-webkit-input-placeholder,\n.am-form input[type=\"datetime\"]::-webkit-input-placeholder,\n.am-form input[type=\"datetime-local\"]::-webkit-input-placeholder,\n.am-form input[type=\"date\"]::-webkit-input-placeholder,\n.am-form input[type=\"month\"]::-webkit-input-placeholder,\n.am-form input[type=\"time\"]::-webkit-input-placeholder,\n.am-form input[type=\"week\"]::-webkit-input-placeholder,\n.am-form input[type=\"number\"]::-webkit-input-placeholder,\n.am-form input[type=\"email\"]::-webkit-input-placeholder,\n.am-form input[type=\"url\"]::-webkit-input-placeholder,\n.am-form input[type=\"search\"]::-webkit-input-placeholder,\n.am-form input[type=\"tel\"]::-webkit-input-placeholder,\n.am-form input[type=\"color\"]::-webkit-input-placeholder,\n.am-form-field::-webkit-input-placeholder {\n  color: #999999;\n}\n.am-form select::-moz-placeholder,\n.am-form textarea::-moz-placeholder,\n.am-form input[type=\"text\"]::-moz-placeholder,\n.am-form input[type=\"password\"]::-moz-placeholder,\n.am-form input[type=\"datetime\"]::-moz-placeholder,\n.am-form input[type=\"datetime-local\"]::-moz-placeholder,\n.am-form input[type=\"date\"]::-moz-placeholder,\n.am-form input[type=\"month\"]::-moz-placeholder,\n.am-form input[type=\"time\"]::-moz-placeholder,\n.am-form input[type=\"week\"]::-moz-placeholder,\n.am-form input[type=\"number\"]::-moz-placeholder,\n.am-form input[type=\"email\"]::-moz-placeholder,\n.am-form input[type=\"url\"]::-moz-placeholder,\n.am-form input[type=\"search\"]::-moz-placeholder,\n.am-form input[type=\"tel\"]::-moz-placeholder,\n.am-form input[type=\"color\"]::-moz-placeholder,\n.am-form-field::-moz-placeholder {\n  color: #999999;\n}\n.am-form select:-ms-input-placeholder,\n.am-form textarea:-ms-input-placeholder,\n.am-form input[type=\"text\"]:-ms-input-placeholder,\n.am-form input[type=\"password\"]:-ms-input-placeholder,\n.am-form input[type=\"datetime\"]:-ms-input-placeholder,\n.am-form input[type=\"datetime-local\"]:-ms-input-placeholder,\n.am-form input[type=\"date\"]:-ms-input-placeholder,\n.am-form input[type=\"month\"]:-ms-input-placeholder,\n.am-form input[type=\"time\"]:-ms-input-placeholder,\n.am-form input[type=\"week\"]:-ms-input-placeholder,\n.am-form input[type=\"number\"]:-ms-input-placeholder,\n.am-form input[type=\"email\"]:-ms-input-placeholder,\n.am-form input[type=\"url\"]:-ms-input-placeholder,\n.am-form input[type=\"search\"]:-ms-input-placeholder,\n.am-form input[type=\"tel\"]:-ms-input-placeholder,\n.am-form input[type=\"color\"]:-ms-input-placeholder,\n.am-form-field:-ms-input-placeholder {\n  color: #999999;\n}\n.am-form select::placeholder,\n.am-form textarea::placeholder,\n.am-form input[type=\"text\"]::placeholder,\n.am-form input[type=\"password\"]::placeholder,\n.am-form input[type=\"datetime\"]::placeholder,\n.am-form input[type=\"datetime-local\"]::placeholder,\n.am-form input[type=\"date\"]::placeholder,\n.am-form input[type=\"month\"]::placeholder,\n.am-form input[type=\"time\"]::placeholder,\n.am-form input[type=\"week\"]::placeholder,\n.am-form input[type=\"number\"]::placeholder,\n.am-form input[type=\"email\"]::placeholder,\n.am-form input[type=\"url\"]::placeholder,\n.am-form input[type=\"search\"]::placeholder,\n.am-form input[type=\"tel\"]::placeholder,\n.am-form input[type=\"color\"]::placeholder,\n.am-form-field::placeholder {\n  color: #999999;\n}\n.am-form select::-moz-placeholder,\n.am-form textarea::-moz-placeholder,\n.am-form input[type=\"text\"]::-moz-placeholder,\n.am-form input[type=\"password\"]::-moz-placeholder,\n.am-form input[type=\"datetime\"]::-moz-placeholder,\n.am-form input[type=\"datetime-local\"]::-moz-placeholder,\n.am-form input[type=\"date\"]::-moz-placeholder,\n.am-form input[type=\"month\"]::-moz-placeholder,\n.am-form input[type=\"time\"]::-moz-placeholder,\n.am-form input[type=\"week\"]::-moz-placeholder,\n.am-form input[type=\"number\"]::-moz-placeholder,\n.am-form input[type=\"email\"]::-moz-placeholder,\n.am-form input[type=\"url\"]::-moz-placeholder,\n.am-form input[type=\"search\"]::-moz-placeholder,\n.am-form input[type=\"tel\"]::-moz-placeholder,\n.am-form input[type=\"color\"]::-moz-placeholder,\n.am-form-field::-moz-placeholder {\n  opacity: 1;\n}\n.am-form select[disabled],\n.am-form textarea[disabled],\n.am-form input[type=\"text\"][disabled],\n.am-form input[type=\"password\"][disabled],\n.am-form input[type=\"datetime\"][disabled],\n.am-form input[type=\"datetime-local\"][disabled],\n.am-form input[type=\"date\"][disabled],\n.am-form input[type=\"month\"][disabled],\n.am-form input[type=\"time\"][disabled],\n.am-form input[type=\"week\"][disabled],\n.am-form input[type=\"number\"][disabled],\n.am-form input[type=\"email\"][disabled],\n.am-form input[type=\"url\"][disabled],\n.am-form input[type=\"search\"][disabled],\n.am-form input[type=\"tel\"][disabled],\n.am-form input[type=\"color\"][disabled],\n.am-form-field[disabled],\n.am-form select[readonly],\n.am-form textarea[readonly],\n.am-form input[type=\"text\"][readonly],\n.am-form input[type=\"password\"][readonly],\n.am-form input[type=\"datetime\"][readonly],\n.am-form input[type=\"datetime-local\"][readonly],\n.am-form input[type=\"date\"][readonly],\n.am-form input[type=\"month\"][readonly],\n.am-form input[type=\"time\"][readonly],\n.am-form input[type=\"week\"][readonly],\n.am-form input[type=\"number\"][readonly],\n.am-form input[type=\"email\"][readonly],\n.am-form input[type=\"url\"][readonly],\n.am-form input[type=\"search\"][readonly],\n.am-form input[type=\"tel\"][readonly],\n.am-form input[type=\"color\"][readonly],\n.am-form-field[readonly],\nfieldset[disabled] .am-form select,\nfieldset[disabled] .am-form textarea,\nfieldset[disabled] .am-form input[type=\"text\"],\nfieldset[disabled] .am-form input[type=\"password\"],\nfieldset[disabled] .am-form input[type=\"datetime\"],\nfieldset[disabled] .am-form input[type=\"datetime-local\"],\nfieldset[disabled] .am-form input[type=\"date\"],\nfieldset[disabled] .am-form input[type=\"month\"],\nfieldset[disabled] .am-form input[type=\"time\"],\nfieldset[disabled] .am-form input[type=\"week\"],\nfieldset[disabled] .am-form input[type=\"number\"],\nfieldset[disabled] .am-form input[type=\"email\"],\nfieldset[disabled] .am-form input[type=\"url\"],\nfieldset[disabled] .am-form input[type=\"search\"],\nfieldset[disabled] .am-form input[type=\"tel\"],\nfieldset[disabled] .am-form input[type=\"color\"],\nfieldset[disabled] .am-form-field {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n.am-form select.am-radius,\n.am-form textarea.am-radius,\n.am-form input[type=\"text\"].am-radius,\n.am-form input[type=\"password\"].am-radius,\n.am-form input[type=\"datetime\"].am-radius,\n.am-form input[type=\"datetime-local\"].am-radius,\n.am-form input[type=\"date\"].am-radius,\n.am-form input[type=\"month\"].am-radius,\n.am-form input[type=\"time\"].am-radius,\n.am-form input[type=\"week\"].am-radius,\n.am-form input[type=\"number\"].am-radius,\n.am-form input[type=\"email\"].am-radius,\n.am-form input[type=\"url\"].am-radius,\n.am-form input[type=\"search\"].am-radius,\n.am-form input[type=\"tel\"].am-radius,\n.am-form input[type=\"color\"].am-radius,\n.am-form-field.am-radius {\n  border-radius: 2px;\n}\n.am-form select.am-round,\n.am-form textarea.am-round,\n.am-form input[type=\"text\"].am-round,\n.am-form input[type=\"password\"].am-round,\n.am-form input[type=\"datetime\"].am-round,\n.am-form input[type=\"datetime-local\"].am-round,\n.am-form input[type=\"date\"].am-round,\n.am-form input[type=\"month\"].am-round,\n.am-form input[type=\"time\"].am-round,\n.am-form input[type=\"week\"].am-round,\n.am-form input[type=\"number\"].am-round,\n.am-form input[type=\"email\"].am-round,\n.am-form input[type=\"url\"].am-round,\n.am-form input[type=\"search\"].am-round,\n.am-form input[type=\"tel\"].am-round,\n.am-form input[type=\"color\"].am-round,\n.am-form-field.am-round {\n  border-radius: 1000px;\n}\n.am-form textarea,\n.am-form select[multiple],\n.am-form select[size] {\n  height: auto;\n}\n.am-form select {\n  -webkit-appearance: none !important;\n  -moz-appearance: none !important;\n  -webkit-border-radius: 0;\n  background: #fff url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgeD0iMTJweCIgeT0iMHB4IiB3aWR0aD0iMjRweCIgaGVpZ2h0PSIzcHgiIHZpZXdCb3g9IjAgMCA2IDMiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDYgMyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PHBvbHlnb24gcG9pbnRzPSI1Ljk5MiwwIDIuOTkyLDMgLTAuMDA4LDAgIi8+PC9zdmc+') no-repeat 100% center;\n}\n.am-form select[multiple=\"multiple\"] {\n  background-image: none;\n}\n/* help text */\n.am-form-help {\n  display: block;\n  margin-top: 5px;\n  margin-bottom: 10px;\n  color: #999999;\n  font-size: 1.3rem;\n}\n/* form group */\n.am-form-group {\n  margin-bottom: 1.5rem;\n}\n/* file field */\n.am-form-file {\n  position: relative;\n  overflow: hidden;\n}\n.am-form-file input[type=\"file\"] {\n  position: absolute;\n  left: 0;\n  top: 0;\n  z-index: 1;\n  width: 100%;\n  opacity: 0;\n  cursor: pointer;\n  font-size: 50rem;\n}\n/**\n * Checkboxes and radios\n * Indent the labels to position radios/checkboxes as hanging controls.\n*/\n.am-radio,\n.am-checkbox {\n  display: block;\n  min-height: 1.92rem;\n  margin-top: 10px;\n  margin-bottom: 10px;\n  padding-left: 20px;\n  vertical-align: middle;\n}\n.am-radio label,\n.am-checkbox label {\n  display: inline;\n  margin-bottom: 0;\n  font-weight: normal;\n  cursor: pointer;\n}\n.am-radio input[type=\"radio\"],\n.am-radio-inline input[type=\"radio\"],\n.am-checkbox input[type=\"checkbox\"],\n.am-checkbox-inline input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n  outline: none;\n}\n.am-radio + .am-radio,\n.am-checkbox + .am-checkbox {\n  margin-top: -5px;\n}\n/* Radios and checkboxes inline */\n.am-radio-inline,\n.am-checkbox-inline {\n  display: inline-block;\n  padding-left: 20px;\n  margin-bottom: 0;\n  vertical-align: middle;\n  font-weight: normal;\n  cursor: pointer;\n}\n.am-radio-inline + .am-radio-inline,\n.am-checkbox-inline + .am-checkbox-inline {\n  margin-top: 0;\n  margin-left: 10px;\n}\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\n.am-radio[disabled],\n.am-radio-inline[disabled],\n.am-checkbox[disabled],\n.am-checkbox-inline[disabled],\nfieldset[disabled] input[type=\"radio\"],\nfieldset[disabled] input[type=\"checkbox\"],\nfieldset[disabled] .am-radio,\nfieldset[disabled] .am-radio-inline,\nfieldset[disabled] .am-checkbox,\nfieldset[disabled] .am-checkbox-inline {\n  cursor: not-allowed;\n}\n/* Form field feedback states */\n.am-form-warning .am-form-help,\n.am-form-warning .am-form-label,\n.am-form-warning .am-radio,\n.am-form-warning .am-checkbox,\n.am-form-warning .am-radio-inline,\n.am-form-warning .am-checkbox-inline,\n.am-form-warning label {\n  color: #F37B1D;\n}\n.am-form-warning [class*=\"icon-\"] {\n  color: #F37B1D;\n}\n.am-form-warning .am-form-field {\n  border-color: #F37B1D !important;\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.am-form-warning .am-form-field:focus {\n  background-color: #fefffe;\n  border-color: #d2620b;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 5px #f8b47e !important;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 5px #f8b47e !important;\n}\n.am-form-error .am-form-help,\n.am-form-error .am-form-label,\n.am-form-error .am-radio,\n.am-form-error .am-checkbox,\n.am-form-error .am-radio-inline,\n.am-form-error .am-checkbox-inline,\n.am-form-error label {\n  color: #dd514c;\n}\n.am-form-error [class*=\"icon-\"] {\n  color: #dd514c;\n}\n.am-form-error .am-form-field,\n.am-field-error {\n  border-color: #dd514c !important;\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.am-form-error .am-form-field:focus,\n.am-field-error:focus {\n  background-color: #fefffe;\n  border-color: #cf2d27;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 5px #eda4a2 !important;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 5px #eda4a2 !important;\n}\n.am-form-success .am-form-help,\n.am-form-success .am-form-label,\n.am-form-success .am-radio,\n.am-form-success .am-checkbox,\n.am-form-success .am-radio-inline,\n.am-form-success .am-checkbox-inline,\n.am-form-success label {\n  color: #5eb95e;\n}\n.am-form-success [class*=\"icon-\"] {\n  color: #5eb95e;\n}\n.am-form-success .am-form-field,\n.am-field-valid {\n  border-color: #5eb95e !important;\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.am-form-success .am-form-field:focus,\n.am-field-valid:focus {\n  background-color: #fefffe;\n  border-color: #459f45;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 5px #a5d8a5 !important;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 5px #a5d8a5 !important;\n}\n/* Horizontal forms */\n.am-form-horizontal .am-form-label,\n.am-form-horizontal .am-radio,\n.am-form-horizontal .am-checkbox,\n.am-form-horizontal .am-radio-inline,\n.am-form-horizontal .am-checkbox-inline {\n  margin-top: 0;\n  margin-bottom: 0;\n  padding-top: 0.6em;\n}\n.am-form-horizontal .am-form-group:before,\n.am-form-horizontal .am-form-group:after {\n  content: \" \";\n  display: table;\n}\n.am-form-horizontal .am-form-group:after {\n  clear: both;\n}\n@media only screen and (min-width:641px) {\n  .am-form-horizontal .am-form-label {\n    text-align: right;\n  }\n}\n/* Inline form elements */\n@media only screen and (min-width:641px) {\n  .am-form-inline .am-form-group {\n    display: inline-block;\n    margin-bottom: 0;\n    vertical-align: middle;\n  }\n  .am-form-inline .am-form-field {\n    display: inline-block;\n    width: auto;\n    vertical-align: middle;\n  }\n  .am-form-inline .am-input-group {\n    display: inline-table;\n    vertical-align: middle;\n  }\n  .am-form-inline .am-input-group .am-input-group-label,\n  .am-form-inline .am-input-group .am-input-group-btn,\n  .am-form-inline .am-input-group .am-form-label {\n    width: auto;\n  }\n  .am-form-inline .am-input-group > .am-form-field {\n    width: 100%;\n  }\n  .am-form-inline .am-form-label {\n    margin-bottom: 0;\n    vertical-align: middle;\n  }\n  .am-form-inline .am-radio,\n  .am-form-inline .am-checkbox {\n    display: inline-block;\n    margin-top: 0;\n    margin-bottom: 0;\n    padding-left: 0;\n    vertical-align: middle;\n  }\n  .am-form-inline .am-radio input[type=\"radio\"],\n  .am-form-inline .am-checkbox input[type=\"checkbox\"] {\n    float: none;\n    margin-left: 0;\n  }\n}\n/* Form field size */\n.am-input-sm {\n  font-size: 1.4rem !important;\n}\n.am-input-lg {\n  font-size: 1.8rem !important;\n}\n.am-form-group-sm .am-checkbox,\n.am-form-group-sm .am-radio,\n.am-form-group-sm .am-form-label,\n.am-form-group-sm .am-form-field {\n  font-size: 1.4rem !important;\n}\n.am-form-group-lg .am-checkbox,\n.am-form-group-lg .am-radio,\n.am-form-group-lg .am-form-label,\n.am-form-group-lg .am-form-field {\n  font-size: 1.8rem !important;\n}\n.am-form-group-lg input[type=\"radio\"],\n.am-form-group-lg input[type=\"checkbox\"] {\n  margin-top: 7px;\n}\n/* Form field feedback states */\n.am-form-icon {\n  position: relative;\n}\n.am-form-icon .am-form-field {\n  padding-left: 1.75em !important;\n}\n.am-form-icon [class*='am-icon-'] {\n  position: absolute;\n  left: 0.5em;\n  top: 50%;\n  display: block;\n  margin-top: -0.5em;\n  line-height: 1;\n  z-index: 2;\n}\n.am-form-icon label ~ [class*='am-icon-'] {\n  top: 70%;\n}\n/* Feedback Icon */\n.am-form-feedback {\n  position: relative;\n}\n.am-form-feedback .am-form-field {\n  padding-left: 0.5em !important;\n  padding-right: 1.75em !important;\n}\n.am-form-feedback [class*='am-icon-'] {\n  right: 0.5em;\n  left: auto;\n}\n.am-form-horizontal .am-form-feedback [class*='am-icon-'] {\n  right: 1.6em;\n}\n/* Form set */\n.am-form-set {\n  margin-bottom: 1.5rem;\n  padding: 0;\n}\n.am-form-set > input {\n  position: relative;\n  top: -1px;\n  border-radius: 0 !important;\n}\n.am-form-set > input:focus {\n  z-index: 2;\n}\n.am-form-set > input:first-child {\n  top: 1px;\n  border-top-right-radius: 0 !important;\n  border-top-left-radius: 0 !important;\n}\n.am-form-set > input:last-child {\n  top: -2px;\n  border-bottom-right-radius: 0 !important;\n  border-bottom-left-radius: 0 !important;\n}\n/* ==========================================================================\n   Component: Image\n ============================================================================ */\n/* Image thumbnails */\n.am-img-thumbnail {\n  display: inline-block;\n  max-width: 100%;\n  height: auto;\n  padding: 2px;\n  line-height: 1.6;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  border-radius: 0;\n  -webkit-transition: all 0.2s ease-in-out;\n  transition: all 0.2s ease-in-out;\n}\n.am-img-thumbnail.am-radius {\n  border-radius: 2px;\n}\n.am-img-responsive {\n  display: block;\n  max-width: 100%;\n  height: auto;\n}\n/* ==========================================================================\n   Component: Nav\n ============================================================================ */\n.am-nav {\n  margin-bottom: 0;\n  padding: 0;\n  list-style: none;\n}\n.am-nav:before,\n.am-nav:after {\n  content: \" \";\n  display: table;\n}\n.am-nav:after {\n  clear: both;\n}\n.am-nav > li {\n  position: relative;\n  display: block;\n}\n.am-nav > li + li {\n  margin-top: 5px;\n}\n.am-nav > li + .am-nav-header {\n  margin-top: 1em;\n}\n.am-nav > li > a {\n  position: relative;\n  display: block;\n  padding: 0.4em 1em;\n  border-radius: 0;\n}\n.am-nav > li > a:hover,\n.am-nav > li > a:focus {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n.am-nav > li.am-active > a,\n.am-nav > li.am-active > a:hover,\n.am-nav > li.am-active > a:focus {\n  color: #fff;\n  background-color: #0e90d2;\n  cursor: default;\n}\n.am-nav > li.am-disabled > a {\n  color: #999999;\n}\n.am-nav > li.am-disabled > a:hover,\n.am-nav > li.am-disabled > a:focus {\n  color: #999999;\n  text-decoration: none;\n  background-color: transparent;\n  cursor: not-allowed;\n}\n.am-nav-header {\n  padding: 0.4em 1em;\n  text-transform: uppercase;\n  font-weight: bold;\n  font-size: 100%;\n  color: #555555;\n}\n.am-nav-divider {\n  margin: 15px 1em !important;\n  border-top: 1px solid #ddd;\n  -webkit-box-shadow: 0 1px 0 #fff;\n          box-shadow: 0 1px 0 #fff;\n}\n.am-nav-pills > li {\n  float: left;\n}\n.am-nav-pills > li + li {\n  margin-left: 5px;\n  margin-top: 0;\n}\n.am-nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n.am-nav-tabs > li {\n  float: left;\n  margin-bottom: -1px;\n}\n.am-nav-tabs > li + li {\n  margin-top: 0;\n}\n.am-nav-tabs > li > a {\n  margin-right: 5px;\n  line-height: 1.6;\n  border: 1px solid transparent;\n  border-radius: 0 0 0 0;\n}\n.am-nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #ddd;\n}\n.am-nav-tabs > li.am-active > a,\n.am-nav-tabs > li.am-active > a:hover,\n.am-nav-tabs > li.am-active > a:focus {\n  color: #555555;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n  cursor: default;\n}\n.am-nav-tabs.am-nav-justify {\n  border-bottom: 0;\n  /*  > li > a {\n      margin-right: 0;\n      border-radius: @global-radius;\n    }\n\n    > .am-active > a {\n      &,\n      &:hover,\n      &:focus {\n        border: 1px solid @nav-tabs-justify-link-border-color;\n      }\n    }*/\n}\n.am-nav-tabs.am-nav-justify > li > a {\n  margin-right: 0;\n  border-bottom: 1px solid #ddd;\n  border-radius: 0 0 0 0;\n}\n.am-nav-tabs.am-nav-justify > .am-active > a,\n.am-nav-tabs.am-nav-justify > .am-active > a:hover,\n.am-nav-tabs.am-nav-justify > .am-active > a:focus {\n  border-bottom-color: #fff;\n}\n.am-nav-justify {\n  width: 100%;\n  display: table;\n}\n.am-nav-justify > li {\n  float: none;\n  display: table-cell;\n  width: 1%;\n}\n.am-nav-justify > li > a {\n  text-align: center;\n  margin-bottom: 0;\n}\n.lte9 .am-nav-justify > li {\n  display: table-cell;\n  width: 1%;\n}\n/* ==========================================================================\n   Component: Topbar\n ============================================================================ */\n.am-topbar {\n  position: relative;\n  min-height: 50px;\n  margin-bottom: 1.6rem;\n  background: #f8f8f8;\n  border-width: 0 0 1px;\n  border-style: solid;\n  border-color: #ddd;\n  color: #666;\n}\n.am-topbar:before,\n.am-topbar:after {\n  content: \" \";\n  display: table;\n}\n.am-topbar:after {\n  clear: both;\n}\n.am-topbar a {\n  color: #666;\n}\n.am-topbar-brand {\n  margin: 0;\n}\n@media only screen and (min-width:641px) {\n  .am-topbar-brand {\n    float: left;\n  }\n}\n.am-topbar-brand a:hover {\n  color: #4d4d4d;\n}\n.am-topbar-collapse {\n  width: 100%;\n  overflow-x: visible;\n  padding: 10px;\n  clear: both;\n  -webkit-overflow-scrolling: touch;\n}\n.am-topbar-collapse:before,\n.am-topbar-collapse:after {\n  content: \" \";\n  display: table;\n}\n.am-topbar-collapse:after {\n  clear: both;\n}\n.am-topbar-collapse.am-in {\n  overflow-y: auto;\n}\n@media only screen and (min-width:641px) {\n  .am-topbar-collapse {\n    margin-top: 0;\n    padding: 0;\n    width: auto;\n    clear: none;\n  }\n  .am-topbar-collapse.am-collapse {\n    display: block !important;\n    height: auto !important;\n    padding: 0;\n    overflow: visible !important;\n  }\n  .am-topbar-collapse.am-in {\n    overflow-y: visible;\n  }\n}\n.am-topbar-brand {\n  padding: 0 10px;\n  float: left;\n  font-size: 1.8rem;\n  height: 50px;\n  line-height: 50px;\n}\n.am-topbar-toggle {\n  position: relative;\n  float: right;\n  margin-right: 10px;\n}\n@media only screen and (min-width:641px) {\n  .am-topbar-toggle {\n    display: none;\n  }\n}\n@media only screen and (max-width: 640px) {\n  .am-topbar-nav {\n    margin-bottom: 8px;\n  }\n  .am-topbar-nav > li {\n    float: none;\n  }\n}\n@media only screen and (max-width: 640px) {\n  .am-topbar-nav > li + li {\n    margin-left: 0;\n    margin-top: 5px;\n  }\n}\n@media only screen and (min-width:641px) {\n  .am-topbar-nav {\n    float: left;\n  }\n  .am-topbar-nav > li > a {\n    position: relative;\n    line-height: 50px;\n    padding: 0 10px;\n  }\n  .am-topbar-nav > li > a:after {\n    position: absolute;\n    left: 50%;\n    margin-left: -7px;\n    bottom: -1px;\n    content: \"\";\n    display: inline-block;\n    width: 0;\n    height: 0;\n    vertical-align: middle;\n    border-bottom: 7px solid #f8f8f8;\n    border-right: 7px solid transparent;\n    border-left: 7px solid transparent;\n    border-top: 0 dotted;\n    -webkit-transform: rotate(360deg);\n        -ms-transform: rotate(360deg);\n            transform: rotate(360deg);\n    opacity: 0;\n    -webkit-transition: opacity .1s;\n    transition: opacity .1s;\n  }\n  .am-topbar-nav > li > a:hover:after {\n    opacity: 1;\n    border-bottom-color: #666;\n  }\n  .am-topbar-nav > li.am-dropdown > a:after {\n    display: none;\n  }\n  .am-topbar-nav > li.am-active > a,\n  .am-topbar-nav > li.am-active > a:hover,\n  .am-topbar-nav > li.am-active > a:focus {\n    border-radius: 0;\n    color: #0e90d2;\n    background: none;\n  }\n  .am-topbar-nav > li.am-active > a:after {\n    opacity: 1;\n    border-bottom-color: #0e90d2;\n  }\n}\n@media only screen and (max-width: 640px) {\n  .am-topbar-collapse .am-dropdown.am-active .am-dropdown-content {\n    float: none;\n    position: relative;\n    width: 100%;\n  }\n}\n@media only screen and (min-width:641px) {\n  .am-topbar-left {\n    float: left;\n  }\n  .am-topbar-right {\n    float: right;\n    margin-right: 10px;\n  }\n}\n@media only screen and (max-width: 640px) {\n  .am-topbar-form .am-form-group {\n    margin-bottom: 5px;\n  }\n}\n@media only screen and (min-width:641px) {\n  .am-topbar-form {\n    padding: 0 10px;\n    margin-top: 8px;\n  }\n  .am-topbar-form .am-form-group + .am-btn {\n    margin-left: 5px;\n  }\n}\n.am-topbar-btn {\n  margin-top: 8px;\n}\n@media only screen and (max-width: 640px) {\n  .am-topbar-collapse .am-topbar-btn,\n  .am-topbar-collapse .am-btn {\n    display: block;\n    width: 100%;\n  }\n}\n.am-topbar-inverse {\n  background-color: #0e90d2;\n  border-color: #0b6fa2;\n  color: #eeeeee;\n}\n.am-topbar-inverse a {\n  color: #eeeeee;\n}\n.am-topbar-inverse .am-topbar-brand a {\n  color: #fff;\n}\n.am-topbar-inverse .am-topbar-brand a:hover,\n.am-topbar-inverse .am-topbar-brand a:focus {\n  color: #fff;\n  background-color: transparent;\n}\n.am-topbar-inverse .am-topbar-nav > li > a {\n  color: #eeeeee;\n}\n.am-topbar-inverse .am-topbar-nav > li > a:hover,\n.am-topbar-inverse .am-topbar-nav > li > a:focus {\n  color: #fff;\n  background-color: rgba(0, 0, 0, 0.05);\n}\n.am-topbar-inverse .am-topbar-nav > li > a:hover:after,\n.am-topbar-inverse .am-topbar-nav > li > a:focus:after {\n  border-bottom-color: #0b6fa2;\n}\n.am-topbar-inverse .am-topbar-nav > li > a:after {\n  border-bottom-color: #0e90d2;\n}\n.am-topbar-inverse .am-topbar-nav > li.am-active > a,\n.am-topbar-inverse .am-topbar-nav > li.am-active > a:hover,\n.am-topbar-inverse .am-topbar-nav > li.am-active > a:focus {\n  color: #fff;\n  background-color: rgba(0, 0, 0, 0.1);\n}\n.am-topbar-inverse .am-topbar-nav > li.am-active > a:after,\n.am-topbar-inverse .am-topbar-nav > li.am-active > a:hover:after,\n.am-topbar-inverse .am-topbar-nav > li.am-active > a:focus:after {\n  border-bottom-color: #fff;\n}\n.am-topbar-inverse .am-topbar-nav > li .disabled > a,\n.am-topbar-inverse .am-topbar-nav > li .disabled > a:hover,\n.am-topbar-inverse .am-topbar-nav > li .disabled > a:focus {\n  color: #444;\n  background-color: transparent;\n}\n.am-topbar-fixed-top,\n.am-topbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1000;\n  -webkit-transform: translate3d(0, 0, 0);\n          transform: translate3d(0, 0, 0);\n}\n.am-topbar-fixed-top {\n  top: 0;\n}\n.am-topbar-fixed-bottom {\n  bottom: 0;\n  margin-bottom: 0;\n  border-width: 1px 0 0;\n}\n.am-with-topbar-fixed-top {\n  padding-top: 51px;\n}\n.am-with-topbar-fixed-bottom {\n  padding-bottom: 51px;\n}\n@media only screen and (max-width: 640px) {\n  .am-topbar-fixed-bottom .am-topbar-collapse {\n    position: absolute;\n    bottom: 100%;\n    margin-bottom: 1px;\n    background-color: #f8f8f8;\n  }\n  .am-topbar-fixed-bottom .am-topbar-collapse .am-dropdown-content:before,\n  .am-topbar-fixed-bottom .am-topbar-collapse .am-dropdown-content:after {\n    display: none;\n  }\n  .am-topbar-fixed-bottom.am-topbar-inverse .am-topbar-collapse {\n    background-color: #0e90d2;\n  }\n}\n/* ==========================================================================\n   Component: Breadcrumb\n ============================================================================ */\n.am-breadcrumb {\n  padding: .7em .5em;\n  margin-bottom: 2rem;\n  list-style: none;\n  background-color: transparent;\n  border-radius: 0;\n  font-size: 85%;\n}\n.am-breadcrumb > li {\n  display: inline-block;\n}\n.am-breadcrumb > li [class*=\"am-icon-\"]:before {\n  color: #999999;\n  margin-right: 5px;\n}\n.am-breadcrumb > li + li:before {\n  content: \"»\\00a0\";\n  padding: 0 8px;\n  color: #ccc;\n}\n.am-breadcrumb > .am-active {\n  color: #999999;\n}\n.am-breadcrumb-slash > li + li:before {\n  content: \"/\\00a0\";\n}\n/* ==========================================================================\n   Component: Pagination\n ============================================================================ */\n.am-pagination {\n  padding-left: 0;\n  margin: 1.5rem 0;\n  list-style: none;\n  color: #999999;\n  text-align: left;\n}\n.am-pagination:before,\n.am-pagination:after {\n  content: \" \";\n  display: table;\n}\n.am-pagination:after {\n  clear: both;\n}\n.am-pagination > li {\n  display: inline-block;\n}\n.am-pagination > li > a,\n.am-pagination > li > span {\n  position: relative;\n  display: block;\n  padding: 0.5em 1em;\n  text-decoration: none;\n  line-height: 1.2;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  border-radius: 0;\n  margin-bottom: 5px;\n  margin-right: 5px;\n}\n.am-pagination > li:last-child > a,\n.am-pagination > li:last-child > span {\n  margin-right: 0;\n}\n.am-pagination > li > a:hover,\n.am-pagination > li > span:hover,\n.am-pagination > li > a:focus,\n.am-pagination > li > span:focus {\n  background-color: #eeeeee;\n}\n.am-pagination > .am-active > a,\n.am-pagination > .am-active > span,\n.am-pagination > .am-active > a:hover,\n.am-pagination > .am-active > span:hover,\n.am-pagination > .am-active > a:focus,\n.am-pagination > .am-active > span:focus {\n  z-index: 2;\n  color: #fff;\n  background-color: #0e90d2;\n  border-color: #0e90d2;\n  cursor: default;\n}\n.am-pagination > .am-disabled > span,\n.am-pagination > .am-disabled > span:hover,\n.am-pagination > .am-disabled > span:focus,\n.am-pagination > .am-disabled > a,\n.am-pagination > .am-disabled > a:hover,\n.am-pagination > .am-disabled > a:focus {\n  color: #999999;\n  background-color: #fff;\n  border-color: #ddd;\n  cursor: not-allowed;\n  pointer-events: none;\n}\n.am-pagination .am-pagination-prev {\n  float: left;\n}\n.am-pagination .am-pagination-prev a {\n  border-radius: 0;\n}\n.am-pagination .am-pagination-next {\n  float: right;\n}\n.am-pagination .am-pagination-next a {\n  border-radius: 0;\n}\n.am-pagination-centered {\n  text-align: center;\n}\n.am-pagination-right {\n  text-align: right;\n}\n/* ==========================================================================\n   Component: Aniamtion\n ============================================================================ */\n[class*=\"am-animation-\"] {\n  -webkit-animation-duration: 0.5s;\n          animation-duration: 0.5s;\n  -webkit-animation-timing-function: ease-out;\n          animation-timing-function: ease-out;\n  -webkit-animation-fill-mode: both;\n          animation-fill-mode: both;\n}\n/* Hide animated element if scrollSpy is used */\n@media screen {\n  .cssanimations [data-am-scrollspy*=\"animation\"] {\n    opacity: 0;\n  }\n}\n/* Fade */\n.am-animation-fade {\n  -webkit-animation-name: am-fade;\n          animation-name: am-fade;\n  -webkit-animation-duration: 0.8s;\n          animation-duration: 0.8s;\n  -webkit-animation-timing-function: linear;\n          animation-timing-function: linear;\n}\n/* Scale */\n.am-animation-scale-up {\n  -webkit-animation-name: am-scale-up;\n          animation-name: am-scale-up;\n}\n.am-animation-scale-down {\n  -webkit-animation-name: am-scale-down;\n          animation-name: am-scale-down;\n}\n/* Slide */\n.am-animation-slide-top {\n  -webkit-animation-name: am-slide-top;\n          animation-name: am-slide-top;\n}\n.am-animation-slide-bottom {\n  -webkit-animation-name: am-slide-bottom;\n          animation-name: am-slide-bottom;\n}\n.am-animation-slide-left {\n  -webkit-animation-name: am-slide-left;\n          animation-name: am-slide-left;\n}\n.am-animation-slide-right {\n  -webkit-animation-name: am-slide-right;\n          animation-name: am-slide-right;\n}\n.am-animation-slide-top-fixed {\n  -webkit-animation-name: am-slide-top-fixed;\n          animation-name: am-slide-top-fixed;\n}\n/* Shake */\n.am-animation-shake {\n  -webkit-animation-name: am-shake;\n          animation-name: am-shake;\n}\n/* Spin */\n.am-animation-spin {\n  -webkit-animation: am-spin 2s infinite linear;\n          animation: am-spin 2s infinite linear;\n}\n/* Spring */\n.am-animation-left-spring {\n  -webkit-animation: am-left-spring 0.3s ease-in-out;\n          animation: am-left-spring 0.3s ease-in-out;\n}\n.am-animation-right-spring {\n  -webkit-animation: am-right-spring 0.3s ease-in-out;\n          animation: am-right-spring 0.3s ease-in-out;\n}\n.am-animation-reverse {\n  -webkit-animation-direction: reverse;\n          animation-direction: reverse;\n}\n.am-animation-paused {\n  -webkit-animation-play-state: paused !important;\n          animation-play-state: paused !important;\n}\n.am-animation-delay-1 {\n  -webkit-animation-delay: 1s;\n          animation-delay: 1s;\n}\n.am-animation-delay-2 {\n  -webkit-animation-delay: 2s;\n          animation-delay: 2s;\n}\n.am-animation-delay-3 {\n  -webkit-animation-delay: 3s;\n          animation-delay: 3s;\n}\n.am-animation-delay-4 {\n  -webkit-animation-delay: 4s;\n          animation-delay: 4s;\n}\n.am-animation-delay-5 {\n  -webkit-animation-delay: 5s;\n          animation-delay: 5s;\n}\n.am-animation-delay-6 {\n  -webkit-animation-delay: 6s;\n          animation-delay: 6s;\n}\n/* Keyframes\n ============================================================================ */\n/* Fade */\n@-webkit-keyframes am-fade {\n  0% {\n    opacity: 0;\n  }\n  100% {\n    opacity: 1;\n  }\n}\n@keyframes am-fade {\n  0% {\n    opacity: 0;\n  }\n  100% {\n    opacity: 1;\n  }\n}\n/* Scale up */\n@-webkit-keyframes am-scale-up {\n  0% {\n    opacity: 0;\n    -webkit-transform: scale(0.2);\n            transform: scale(0.2);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: scale(1);\n            transform: scale(1);\n  }\n}\n@keyframes am-scale-up {\n  0% {\n    opacity: 0;\n    -webkit-transform: scale(0.2);\n            transform: scale(0.2);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: scale(1);\n            transform: scale(1);\n  }\n}\n/* Scale down */\n@-webkit-keyframes am-scale-down {\n  0% {\n    opacity: 0;\n    -webkit-transform: scale(1.8);\n            transform: scale(1.8);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: scale(1);\n            transform: scale(1);\n  }\n}\n@keyframes am-scale-down {\n  0% {\n    opacity: 0;\n    -webkit-transform: scale(1.8);\n            transform: scale(1.8);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: scale(1);\n            transform: scale(1);\n  }\n}\n/* Slide top */\n@-webkit-keyframes am-slide-top {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(-100%);\n            transform: translateY(-100%);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n            transform: translateY(0);\n  }\n}\n@keyframes am-slide-top {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(-100%);\n            transform: translateY(-100%);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n            transform: translateY(0);\n  }\n}\n/* Slide bottom */\n@-webkit-keyframes am-slide-bottom {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(100%);\n            transform: translateY(100%);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n            transform: translateY(0);\n  }\n}\n@keyframes am-slide-bottom {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(100%);\n            transform: translateY(100%);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n            transform: translateY(0);\n  }\n}\n/* Slide left */\n@-webkit-keyframes am-slide-left {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateX(-100%);\n            transform: translateX(-100%);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n}\n@keyframes am-slide-left {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateX(-100%);\n            transform: translateX(-100%);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n}\n/* Slide right */\n@-webkit-keyframes am-slide-right {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateX(100%);\n            transform: translateX(100%);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n}\n@keyframes am-slide-right {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateX(100%);\n            transform: translateX(100%);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n}\n/* Shake */\n@-webkit-keyframes am-shake {\n  0%,\n  100% {\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n  10% {\n    -webkit-transform: translateX(-9px);\n            transform: translateX(-9px);\n  }\n  20% {\n    -webkit-transform: translateX(8px);\n            transform: translateX(8px);\n  }\n  30% {\n    -webkit-transform: translateX(-7px);\n            transform: translateX(-7px);\n  }\n  40% {\n    -webkit-transform: translateX(6px);\n            transform: translateX(6px);\n  }\n  50% {\n    -webkit-transform: translateX(-5px);\n            transform: translateX(-5px);\n  }\n  60% {\n    -webkit-transform: translateX(4px);\n            transform: translateX(4px);\n  }\n  70% {\n    -webkit-transform: translateX(-3px);\n            transform: translateX(-3px);\n  }\n  80% {\n    -webkit-transform: translateX(2px);\n            transform: translateX(2px);\n  }\n  90% {\n    -webkit-transform: translateX(-1px);\n            transform: translateX(-1px);\n  }\n}\n@keyframes am-shake {\n  0%,\n  100% {\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n  10% {\n    -webkit-transform: translateX(-9px);\n            transform: translateX(-9px);\n  }\n  20% {\n    -webkit-transform: translateX(8px);\n            transform: translateX(8px);\n  }\n  30% {\n    -webkit-transform: translateX(-7px);\n            transform: translateX(-7px);\n  }\n  40% {\n    -webkit-transform: translateX(6px);\n            transform: translateX(6px);\n  }\n  50% {\n    -webkit-transform: translateX(-5px);\n            transform: translateX(-5px);\n  }\n  60% {\n    -webkit-transform: translateX(4px);\n            transform: translateX(4px);\n  }\n  70% {\n    -webkit-transform: translateX(-3px);\n            transform: translateX(-3px);\n  }\n  80% {\n    -webkit-transform: translateX(2px);\n            transform: translateX(2px);\n  }\n  90% {\n    -webkit-transform: translateX(-1px);\n            transform: translateX(-1px);\n  }\n}\n/* Slide top fixed */\n@-webkit-keyframes am-slide-top-fixed {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(-10px);\n            transform: translateY(-10px);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n            transform: translateY(0);\n  }\n}\n@keyframes am-slide-top-fixed {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(-10px);\n            transform: translateY(-10px);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n            transform: translateY(0);\n  }\n}\n/* Slide bottom fixed */\n@-webkit-keyframes am-slide-bottom-fixed {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(10px);\n            transform: translateY(10px);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n            transform: translateY(0);\n  }\n}\n@keyframes am-slide-bottom-fixed {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(10px);\n            transform: translateY(10px);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n            transform: translateY(0);\n  }\n}\n/* Spin */\n@-webkit-keyframes am-spin {\n  0% {\n    -webkit-transform: rotate(0deg);\n            transform: rotate(0deg);\n  }\n  100% {\n    -webkit-transform: rotate(359deg);\n            transform: rotate(359deg);\n  }\n}\n@keyframes am-spin {\n  0% {\n    -webkit-transform: rotate(0deg);\n            transform: rotate(0deg);\n  }\n  100% {\n    -webkit-transform: rotate(359deg);\n            transform: rotate(359deg);\n  }\n}\n/* Spring */\n@-webkit-keyframes am-right-spring {\n  0% {\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n  50% {\n    -webkit-transform: translateX(-20%);\n            transform: translateX(-20%);\n  }\n  100% {\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n}\n@keyframes am-right-spring {\n  0% {\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n  50% {\n    -webkit-transform: translateX(-20%);\n            transform: translateX(-20%);\n  }\n  100% {\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n}\n@-webkit-keyframes am-left-spring {\n  0% {\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n  50% {\n    -webkit-transform: translateX(20%);\n            transform: translateX(20%);\n  }\n  100% {\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n}\n@keyframes am-left-spring {\n  0% {\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n  50% {\n    -webkit-transform: translateX(20%);\n            transform: translateX(20%);\n  }\n  100% {\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n}\n/* ==========================================================================\n   Component: Article\n ============================================================================ */\n.am-article:before,\n.am-article:after {\n  content: \" \";\n  display: table;\n}\n.am-article:after {\n  clear: both;\n}\n.am-article > :last-child {\n  margin-bottom: 0;\n}\n.am-article + .am-article {\n  margin-top: 2.4rem;\n}\n/* Sub-object `.@{ns}article-title` */\n.am-article-title {\n  font-size: 2.8rem;\n  line-height: 1.15;\n  font-weight: normal;\n}\n.am-article-title a {\n  color: inherit;\n  text-decoration: none;\n}\n/* Sub-object `.@{ns}article-meta` */\n.am-article-meta {\n  font-size: 1.2rem;\n  line-height: 1.5;\n  color: #999999;\n}\n/* Sub-object `.@{ns}article-lead` */\n.am-article-lead {\n  color: #666;\n  font-size: 1.4rem;\n  line-height: 1.5;\n  border: 1px solid #dedede;\n  border-radius: 2px;\n  background: #f9f9f9;\n  padding: 10px;\n}\n/* Sub-object `.@{ns}article-divider` */\n.am-article-divider {\n  margin-bottom: 2.4rem;\n  border-color: #eeeeee;\n}\n* + .am-article-divider {\n  margin-top: 2.4rem;\n}\n/* Sub-object `.@{ns}article-bd` */\n.am-article-bd blockquote {\n  font-family: Georgia, \"Times New Roman\", Times, Kai, \"Kaiti SC\", KaiTi, BiauKai, \"FontAwesome\", serif;\n}\n.am-article-bd img {\n  display: block;\n  max-width: 100%;\n}\n/* ==========================================================================\n   Component: Badge\n ============================================================================ */\n.am-badge {\n  display: inline-block;\n  min-width: 10px;\n  padding: 0.25em 0.625em;\n  font-size: 1.2rem;\n  font-weight: bold;\n  color: #fff;\n  line-height: 1;\n  vertical-align: baseline;\n  white-space: nowrap;\n  text-align: center;\n  background-color: #999999;\n  border-radius: 0;\n}\n.am-badge:empty {\n  display: none;\n}\n.am-badge.am-square {\n  border-radius: 0;\n}\n.am-badge.am-radius {\n  border-radius: 2px;\n}\n.am-badge.am-round {\n  border-radius: 1000px;\n}\na.am-badge:hover,\na.am-badge:focus {\n  color: #fff;\n  text-decoration: none;\n  cursor: pointer;\n}\n.am-badge-primary {\n  background-color: #0e90d2;\n}\n.am-badge-secondary {\n  background-color: #3bb4f2;\n}\n.am-badge-success {\n  background-color: #5eb95e;\n}\n.am-badge-warning {\n  background-color: #F37B1D;\n}\n.am-badge-danger {\n  background-color: #dd514c;\n}\n/* ==========================================================================\n   Component: Comment\n ============================================================================ */\n.am-comment:before,\n.am-comment:after {\n  content: \" \";\n  display: table;\n}\n.am-comment:after {\n  clear: both;\n}\n.am-comment-avatar {\n  float: left;\n  width: 32px;\n  height: 32px;\n  border-radius: 50%;\n  border: 1px solid transparent;\n}\n@media only screen and (min-width:641px) {\n  .am-comment-avatar {\n    width: 48px;\n    height: 48px;\n  }\n}\n.am-comment-main {\n  position: relative;\n  margin-left: 42px;\n  border: 1px solid #dedede;\n  border-radius: 0;\n}\n.am-comment-main:before,\n.am-comment-main:after {\n  position: absolute;\n  top: 10px;\n  left: -8px;\n  right: 100%;\n  width: 0;\n  height: 0;\n  display: block;\n  content: \" \";\n  border-color: transparent;\n  border-style: solid solid outset;\n  border-width: 8px 8px 8px 0;\n  pointer-events: none;\n}\n.am-comment-main:before {\n  border-right-color: #dedede;\n  z-index: 1;\n}\n.am-comment-main:after {\n  border-right-color: #f8f8f8;\n  margin-left: 1px;\n  z-index: 2;\n}\n@media only screen and (min-width:641px) {\n  .am-comment-main {\n    margin-left: 63px;\n  }\n}\n.am-comment-hd {\n  background: #f8f8f8;\n  border-bottom: 1px solid #eee;\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -ms-flexbox;\n  display: flex;\n}\n.am-comment-title {\n  margin: 0 0 8px 0;\n  font-size: 1.6rem;\n  line-height: 1.2;\n}\n.am-comment-meta {\n  -webkit-box-flex: 1;\n  -webkit-flex: 1;\n      -ms-flex: 1;\n          flex: 1;\n  padding: 10px 15px;\n  font-size: 13px;\n  color: #999999;\n  line-height: 1.2;\n  white-space: nowrap;\n  text-overflow: ellipsis;\n  overflow: hidden;\n}\n.am-comment-meta a {\n  color: #999999;\n}\n.am-comment-author {\n  font-weight: bold;\n  color: #999999;\n}\n.am-comment-bd {\n  padding: 15px;\n  overflow: hidden;\n}\n.am-comment-bd > :last-child {\n  margin-bottom: 0;\n}\n.am-comment-footer {\n  padding: 0 15px 5px;\n}\n.am-comment-footer .am-comment-actions a + a {\n  margin-left: 5px;\n}\n.am-comment-actions {\n  font-size: 13px;\n  color: #999999;\n}\n.am-comment-actions a {\n  display: inline-block;\n  padding: 10px 5px;\n  line-height: 1;\n  color: #999999;\n  opacity: .7;\n}\n.am-comment-actions a:hover {\n  color: #0e90d2;\n  opacity: 1;\n}\n.am-comment-hd .am-comment-actions {\n  padding-right: .5rem;\n}\n.am-comment-flip .am-comment-avatar {\n  float: right;\n}\n.am-comment-flip .am-comment-main {\n  margin-left: auto;\n  margin-right: 42px;\n}\n@media only screen and (min-width:641px) {\n  .am-comment-flip .am-comment-main {\n    margin-right: 63px;\n  }\n}\n.am-comment-flip .am-comment-main:before,\n.am-comment-flip .am-comment-main:after {\n  left: auto;\n  right: -8px;\n  border-width: 8px 0 8px 8px;\n}\n.am-comment-flip .am-comment-main:before {\n  border-left-color: #dedede;\n}\n.am-comment-flip .am-comment-main:after {\n  border-left-color: #f8f8f8;\n  margin-right: 1px;\n  margin-left: auto;\n}\n.am-comment-primary .am-comment-avatar {\n  border-color: #0e90d2;\n}\n.am-comment-primary .am-comment-main {\n  border-color: #0e90d2;\n}\n.am-comment-primary .am-comment-main:before {\n  border-right-color: #0e90d2;\n}\n.am-comment-primary.am-comment-flip .am-comment-main:before {\n  border-left-color: #0e90d2;\n  border-right-color: transparent;\n}\n.am-comment-primary.am-comment-flip .am-comment-main:after {\n  border-left-color: #f8f8f8;\n}\n.am-comment-secondary .am-comment-avatar,\n.am-comment-highlight .am-comment-avatar {\n  border-color: #3bb4f2;\n}\n.am-comment-secondary .am-comment-main,\n.am-comment-highlight .am-comment-main {\n  border-color: #3bb4f2;\n}\n.am-comment-secondary .am-comment-main:before,\n.am-comment-highlight .am-comment-main:before {\n  border-right-color: #3bb4f2;\n}\n.am-comment-secondary.am-comment-flip .am-comment-main:before,\n.am-comment-highlight.am-comment-flip .am-comment-main:before {\n  border-left-color: #3bb4f2;\n  border-right-color: transparent;\n}\n.am-comment-secondary.am-comment-flip .am-comment-main:after,\n.am-comment-highlight.am-comment-flip .am-comment-main:after {\n  border-left-color: #f8f8f8;\n}\n.am-comment-success .am-comment-avatar {\n  border-color: #5eb95e;\n}\n.am-comment-success .am-comment-main {\n  border-color: #5eb95e;\n}\n.am-comment-success .am-comment-main:before {\n  border-right-color: #5eb95e;\n}\n.am-comment-success.am-comment-flip .am-comment-main:before {\n  border-left-color: #5eb95e;\n  border-right-color: transparent;\n}\n.am-comment-success.am-comment-flip .am-comment-main:after {\n  border-left-color: #f8f8f8;\n}\n.am-comment-warning .am-comment-avatar {\n  border-color: #F37B1D;\n}\n.am-comment-warning .am-comment-main {\n  border-color: #F37B1D;\n}\n.am-comment-warning .am-comment-main:before {\n  border-right-color: #F37B1D;\n}\n.am-comment-warning.am-comment-flip .am-comment-main:before {\n  border-left-color: #F37B1D;\n  border-right-color: transparent;\n}\n.am-comment-warning.am-comment-flip .am-comment-main:after {\n  border-left-color: #f8f8f8;\n}\n.am-comment-danger .am-comment-avatar {\n  border-color: #dd514c;\n}\n.am-comment-danger .am-comment-main {\n  border-color: #dd514c;\n}\n.am-comment-danger .am-comment-main:before {\n  border-right-color: #dd514c;\n}\n.am-comment-danger.am-comment-flip .am-comment-main:before {\n  border-left-color: #dd514c;\n  border-right-color: transparent;\n}\n.am-comment-danger.am-comment-flip .am-comment-main:after {\n  border-left-color: #f8f8f8;\n}\n.am-comments-list {\n  padding: 0;\n  list-style: none;\n}\n.am-comments-list .am-comment {\n  margin: 1.6rem 0 0 0;\n  list-style: none;\n}\n@media only screen and (min-width:641px) {\n  .am-comments-list-flip .am-comment-main {\n    margin-right: 64px;\n  }\n  .am-comments-list-flip .am-comment-flip .am-comment-main {\n    margin-left: 64px;\n  }\n}\n/* ==========================================================================\n   Component: Button Group\n ============================================================================ */\n.am-btn-group,\n.am-btn-group-stacked {\n  position: relative;\n  display: inline-block;\n  vertical-align: middle;\n}\n.am-btn-group > .am-btn,\n.am-btn-group-stacked > .am-btn {\n  position: relative;\n  float: left;\n}\n.am-btn-group > .am-btn:hover,\n.am-btn-group-stacked > .am-btn:hover,\n.am-btn-group > .am-btn:focus,\n.am-btn-group-stacked > .am-btn:focus,\n.am-btn-group > .am-btn:active,\n.am-btn-group-stacked > .am-btn:active,\n.am-btn-group > .am-btn.active,\n.am-btn-group-stacked > .am-btn.active {\n  z-index: 2;\n}\n.am-btn-group > .am-btn:focus,\n.am-btn-group-stacked > .am-btn:focus {\n  outline: 0;\n}\n.am-btn-group .am-btn + .am-btn,\n.am-btn-group .am-btn + .am-btn-group,\n.am-btn-group .am-btn-group + .am-btn,\n.am-btn-group .am-btn-group + .am-btn-group {\n  margin-left: -1px;\n}\n.am-btn-toolbar {\n  margin-left: -5px;\n}\n.am-btn-toolbar:before,\n.am-btn-toolbar:after {\n  content: \" \";\n  display: table;\n}\n.am-btn-toolbar:after {\n  clear: both;\n}\n.am-btn-toolbar .am-btn-group,\n.am-btn-toolbar .am-input-group {\n  float: left;\n}\n.am-btn-toolbar > .am-btn,\n.am-btn-toolbar > .am-btn-group,\n.am-btn-toolbar > .am-input-group {\n  margin-left: 5px;\n}\n.am-btn-group > .am-btn:not(:first-child):not(:last-child):not(.am-dropdown-toggle) {\n  border-radius: 0;\n}\n.am-btn-group > .am-btn:first-child {\n  margin-left: 0;\n}\n.am-btn-group > .am-btn:first-child:not(:last-child):not(.am-dropdown-toggle) {\n  border-bottom-right-radius: 0;\n  border-top-right-radius: 0;\n}\n.am-btn-group > .am-btn:last-child:not(:first-child),\n.am-btn-group > .am-dropdown-toggle:not(:first-child) {\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n}\n.am-btn-group > .am-btn-group {\n  float: left;\n}\n.am-btn-group > .am-btn-group:not(:first-child):not(:last-child) > .am-btn {\n  border-radius: 0;\n}\n.am-btn-group > .am-btn-group:first-child > .am-btn:last-child,\n.am-btn-group > .am-btn-group:first-child > .am-dropdown-toggle {\n  border-bottom-right-radius: 0;\n  border-top-right-radius: 0;\n}\n.am-btn-group > .am-btn-group:last-child > .am-btn:first-child {\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n}\n.am-btn-group-xs > .am-btn {\n  font-size: 1.2rem;\n}\n.am-btn-group-sm > .am-btn {\n  font-size: 1.4rem;\n}\n.am-btn-group-lg > .am-btn {\n  font-size: 1.8rem;\n}\n.am-btn-group-stacked > .am-btn,\n.am-btn-group-stacked > .am-btn-group,\n.am-btn-group-stacked > .am-btn-group > .am-btn {\n  display: block;\n  float: none;\n  width: 100%;\n  max-width: 100%;\n}\n.am-btn-group-stacked > .am-btn-group:before,\n.am-btn-group-stacked > .am-btn-group:after {\n  content: \" \";\n  display: table;\n}\n.am-btn-group-stacked > .am-btn-group:after {\n  clear: both;\n}\n.am-btn-group-stacked > .am-btn-group > .am-btn {\n  float: none;\n}\n.am-btn-group-stacked > .am-btn + .am-btn,\n.am-btn-group-stacked > .am-btn + .am-btn-group,\n.am-btn-group-stacked > .am-btn-group + .am-btn,\n.am-btn-group-stacked > .am-btn-group + .am-btn-group {\n  margin-top: -1px;\n  margin-left: 0;\n}\n.am-btn-group-stacked > .am-btn:not(:first-child):not(:last-child) {\n  border-radius: 0;\n}\n.am-btn-group-stacked > .am-btn:first-child:not(:last-child) {\n  border-top-right-radius: 0;\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n.am-btn-group-stacked > .am-btn:last-child:not(:first-child) {\n  border-bottom-left-radius: 0;\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n.am-btn-group-stacked > .am-btn-group:not(:first-child):not(:last-child) > .am-btn {\n  border-radius: 0;\n}\n.am-btn-group-stacked > .am-btn-group:first-child:not(:last-child) > .am-btn:last-child,\n.am-btn-group-stacked > .am-btn-group:first-child:not(:last-child) > .am-dropdown-toggle {\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n.am-btn-group-stacked > .am-btn-group:last-child:not(:first-child) > .am-btn:first-child {\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n.am-btn-group-justify {\n  display: table;\n  table-layout: fixed;\n  border-collapse: separate;\n  width: 100%;\n}\n.am-btn-group-justify > .am-btn,\n.am-btn-group-justify > .am-btn-group {\n  float: none;\n  display: table-cell;\n  width: 1%;\n}\n.am-btn-group-justify > .am-btn-group .am-btn {\n  width: 100%;\n}\n.lte9 .am-btn-group-justify {\n  display: table;\n  table-layout: fixed;\n  border-collapse: separate;\n}\n.lte9 .am-btn-group-justify > .am-btn,\n.lte9 .am-btn-group-justify > .am-btn-group {\n  float: none;\n  display: table-cell;\n  width: 1%;\n}\n.am-btn-group .am-dropdown {\n  float: left;\n  margin-left: -1px;\n}\n.am-btn-group .am-dropdown > .am-btn {\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n}\n.am-btn-group .am-active .am-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.am-btn-group .am-active .am-dropdown-toggle.am-btn-link {\n  -webkit-box-shadow: none;\n          box-shadow: none;\n}\n.am-btn-group .am-dropdown-toggle:active,\n.am-btn-group .am-active .am-dropdown-toggle {\n  outline: 0;\n}\n[data-am-button] > .am-btn > input[type=\"radio\"],\n[data-am-button] > .am-btn > input[type=\"checkbox\"],\n.am-btn-group-check > .am-btn > input[type=\"radio\"],\n.am-btn-group-check > .am-btn > input[type=\"checkbox\"] {\n  position: absolute;\n  z-index: -1;\n  opacity: 0;\n}\n/* ==========================================================================\n   Component: Close\n ============================================================================ */\n.am-close {\n  display: inline-block;\n  text-align: center;\n  width: 24px;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 24px;\n  color: #000;\n  text-shadow: 0 1px 0 #fff;\n  opacity: .2;\n  -webkit-transition: all .3s;\n  transition: all .3s;\n}\n.am-close:hover,\n.am-close:focus {\n  color: #000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: .5;\n  outline: none;\n}\n.am-close[class*=\"am-icon-\"] {\n  font-size: 16px;\n}\nbutton.am-close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  /* Needed for Sarari */\n  border: 0;\n  -webkit-appearance: none;\n}\na.am-close:hover {\n  color: inherit;\n  text-decoration: none;\n  cursor: pointer;\n}\n/* Modifiers\n ============================================================================ */\n.am-close-alt {\n  border-radius: 50%;\n  background: #eee;\n  opacity: 0.7;\n  -webkit-box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25);\n          box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25);\n  /* Hover */\n}\n.am-close-alt:hover,\n.am-close-alt:focus {\n  opacity: 1;\n}\n.am-close-spin:hover {\n  -webkit-transform: rotate(360deg);\n      -ms-transform: rotate(360deg);\n          transform: rotate(360deg);\n}\n/* ==========================================================================\n   Component: Icon\n ============================================================================ */\n/* Font-face\n============================================================================= */\n@font-face {\n  font-family: 'FontAwesome';\n  src: url('../fonts/fontawesome-webfont.eot?v=4.5.0');\n  src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.5.0') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff2?v=4.5.0') format('woff2'), url('../fonts/fontawesome-webfont.woff?v=4.5.0') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.5.0') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.5.0#fontawesomeregular') format('svg');\n  font-weight: normal;\n  font-style: normal;\n}\n/* Component\n============================================================================= */\n[class*=\"am-icon-\"] {\n  display: inline-block;\n  font-style: normal;\n}\n[class*=\"am-icon-\"]:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n}\n.am-icon-border {\n  padding: .2em .25em .15em;\n  border: solid 0.08em #eee;\n  border-radius: .1em;\n}\n[class*=\"am-icon-\"].am-fl {\n  margin-right: .3em;\n}\n[class*=\"am-icon-\"].am-fr {\n  margin-left: .3em;\n}\n.am-icon-sm:before {\n  font-size: 150%;\n  vertical-align: -10%;\n}\n.am-icon-md:before {\n  font-size: 200%;\n  vertical-align: -16%;\n}\n.am-icon-lg:before {\n  font-size: 250%;\n  vertical-align: -22%;\n}\n/* Modifier: `.am-icon-btn`\n============================================================================= */\n.am-icon-btn {\n  -webkit-box-sizing: border-box;\n          box-sizing: border-box;\n  display: inline-block;\n  width: 48px;\n  height: 48px;\n  font-size: 24px;\n  line-height: 48px;\n  border-radius: 50%;\n  background-color: #eee;\n  color: #555555;\n  text-align: center;\n  /**\n   * Hover\n   * 1. Apply hover style also to focus state\n   * 2. Remove default focus style\n   */\n  /* Active */\n}\n.am-icon-btn:hover,\n.am-icon-btn:focus {\n  /* 1 */\n  background-color: #f5f5f5;\n  color: #333333;\n  text-decoration: none;\n  outline: none;\n  /* 2 */\n}\n.am-icon-btn:active {\n  background-color: #ddd;\n  color: #333333;\n}\n.am-icon-btn.am-primary,\n.am-icon-btn.am-secondary,\n.am-icon-btn.am-success,\n.am-icon-btn.am-warning,\n.am-icon-btn.am-danger {\n  color: #fff;\n}\n.am-icon-btn.am-primary {\n  background-color: #0e90d2;\n}\n.am-icon-btn.am-secondary {\n  background-color: #3bb4f2;\n}\n.am-icon-btn.am-success {\n  background-color: #5eb95e;\n}\n.am-icon-btn.am-warning {\n  background-color: #F37B1D;\n}\n.am-icon-btn.am-danger {\n  background-color: #dd514c;\n}\n.am-icon-btn-sm {\n  width: 32px;\n  height: 32px;\n  font-size: 16px;\n  line-height: 32px;\n}\n.am-icon-btn-lg {\n  width: 64px;\n  height: 64px;\n  font-size: 28px;\n  line-height: 64px;\n}\n/* Modifier: `.am-icon-fw` Fixed width\n============================================================================= */\n.am-icon-fw {\n  width: 1.25em;\n  text-align: center;\n}\n/* Icon mapping\n============================================================================= */\n.am-icon-glass:before {\n  content: \"\\f000\";\n}\n.am-icon-music:before {\n  content: \"\\f001\";\n}\n.am-icon-search:before {\n  content: \"\\f002\";\n}\n.am-icon-envelope-o:before {\n  content: \"\\f003\";\n}\n.am-icon-heart:before {\n  content: \"\\f004\";\n}\n.am-icon-star:before {\n  content: \"\\f005\";\n}\n.am-icon-star-o:before {\n  content: \"\\f006\";\n}\n.am-icon-user:before {\n  content: \"\\f007\";\n}\n.am-icon-film:before {\n  content: \"\\f008\";\n}\n.am-icon-th-large:before {\n  content: \"\\f009\";\n}\n.am-icon-th:before {\n  content: \"\\f00a\";\n}\n.am-icon-th-list:before {\n  content: \"\\f00b\";\n}\n.am-icon-check:before {\n  content: \"\\f00c\";\n}\n.am-icon-remove:before,\n.am-icon-close:before,\n.am-icon-times:before {\n  content: \"\\f00d\";\n}\n.am-icon-search-plus:before {\n  content: \"\\f00e\";\n}\n.am-icon-search-minus:before {\n  content: \"\\f010\";\n}\n.am-icon-power-off:before {\n  content: \"\\f011\";\n}\n.am-icon-signal:before {\n  content: \"\\f012\";\n}\n.am-icon-gear:before,\n.am-icon-cog:before {\n  content: \"\\f013\";\n}\n.am-icon-trash-o:before {\n  content: \"\\f014\";\n}\n.am-icon-home:before {\n  content: \"\\f015\";\n}\n.am-icon-file-o:before {\n  content: \"\\f016\";\n}\n.am-icon-clock-o:before {\n  content: \"\\f017\";\n}\n.am-icon-road:before {\n  content: \"\\f018\";\n}\n.am-icon-download:before {\n  content: \"\\f019\";\n}\n.am-icon-arrow-circle-o-down:before {\n  content: \"\\f01a\";\n}\n.am-icon-arrow-circle-o-up:before {\n  content: \"\\f01b\";\n}\n.am-icon-inbox:before {\n  content: \"\\f01c\";\n}\n.am-icon-play-circle-o:before {\n  content: \"\\f01d\";\n}\n.am-icon-rotate-right:before,\n.am-icon-repeat:before {\n  content: \"\\f01e\";\n}\n.am-icon-refresh:before {\n  content: \"\\f021\";\n}\n.am-icon-list-alt:before {\n  content: \"\\f022\";\n}\n.am-icon-lock:before {\n  content: \"\\f023\";\n}\n.am-icon-flag:before {\n  content: \"\\f024\";\n}\n.am-icon-headphones:before {\n  content: \"\\f025\";\n}\n.am-icon-volume-off:before {\n  content: \"\\f026\";\n}\n.am-icon-volume-down:before {\n  content: \"\\f027\";\n}\n.am-icon-volume-up:before {\n  content: \"\\f028\";\n}\n.am-icon-qrcode:before {\n  content: \"\\f029\";\n}\n.am-icon-barcode:before {\n  content: \"\\f02a\";\n}\n.am-icon-tag:before {\n  content: \"\\f02b\";\n}\n.am-icon-tags:before {\n  content: \"\\f02c\";\n}\n.am-icon-book:before {\n  content: \"\\f02d\";\n}\n.am-icon-bookmark:before {\n  content: \"\\f02e\";\n}\n.am-icon-print:before {\n  content: \"\\f02f\";\n}\n.am-icon-camera:before {\n  content: \"\\f030\";\n}\n.am-icon-font:before {\n  content: \"\\f031\";\n}\n.am-icon-bold:before {\n  content: \"\\f032\";\n}\n.am-icon-italic:before {\n  content: \"\\f033\";\n}\n.am-icon-text-height:before {\n  content: \"\\f034\";\n}\n.am-icon-text-width:before {\n  content: \"\\f035\";\n}\n.am-icon-align-left:before {\n  content: \"\\f036\";\n}\n.am-icon-align-center:before {\n  content: \"\\f037\";\n}\n.am-icon-align-right:before {\n  content: \"\\f038\";\n}\n.am-icon-align-justify:before {\n  content: \"\\f039\";\n}\n.am-icon-list:before {\n  content: \"\\f03a\";\n}\n.am-icon-dedent:before,\n.am-icon-outdent:before {\n  content: \"\\f03b\";\n}\n.am-icon-indent:before {\n  content: \"\\f03c\";\n}\n.am-icon-video-camera:before {\n  content: \"\\f03d\";\n}\n.am-icon-photo:before,\n.am-icon-image:before,\n.am-icon-picture-o:before {\n  content: \"\\f03e\";\n}\n.am-icon-pencil:before {\n  content: \"\\f040\";\n}\n.am-icon-map-marker:before {\n  content: \"\\f041\";\n}\n.am-icon-adjust:before {\n  content: \"\\f042\";\n}\n.am-icon-tint:before {\n  content: \"\\f043\";\n}\n.am-icon-edit:before,\n.am-icon-pencil-square-o:before {\n  content: \"\\f044\";\n}\n.am-icon-share-square-o:before {\n  content: \"\\f045\";\n}\n.am-icon-check-square-o:before {\n  content: \"\\f046\";\n}\n.am-icon-arrows:before {\n  content: \"\\f047\";\n}\n.am-icon-step-backward:before {\n  content: \"\\f048\";\n}\n.am-icon-fast-backward:before {\n  content: \"\\f049\";\n}\n.am-icon-backward:before {\n  content: \"\\f04a\";\n}\n.am-icon-play:before {\n  content: \"\\f04b\";\n}\n.am-icon-pause:before {\n  content: \"\\f04c\";\n}\n.am-icon-stop:before {\n  content: \"\\f04d\";\n}\n.am-icon-forward:before {\n  content: \"\\f04e\";\n}\n.am-icon-fast-forward:before {\n  content: \"\\f050\";\n}\n.am-icon-step-forward:before {\n  content: \"\\f051\";\n}\n.am-icon-eject:before {\n  content: \"\\f052\";\n}\n.am-icon-chevron-left:before {\n  content: \"\\f053\";\n}\n.am-icon-chevron-right:before {\n  content: \"\\f054\";\n}\n.am-icon-plus-circle:before {\n  content: \"\\f055\";\n}\n.am-icon-minus-circle:before {\n  content: \"\\f056\";\n}\n.am-icon-times-circle:before {\n  content: \"\\f057\";\n}\n.am-icon-check-circle:before {\n  content: \"\\f058\";\n}\n.am-icon-question-circle:before {\n  content: \"\\f059\";\n}\n.am-icon-info-circle:before {\n  content: \"\\f05a\";\n}\n.am-icon-crosshairs:before {\n  content: \"\\f05b\";\n}\n.am-icon-times-circle-o:before {\n  content: \"\\f05c\";\n}\n.am-icon-check-circle-o:before {\n  content: \"\\f05d\";\n}\n.am-icon-ban:before {\n  content: \"\\f05e\";\n}\n.am-icon-arrow-left:before {\n  content: \"\\f060\";\n}\n.am-icon-arrow-right:before {\n  content: \"\\f061\";\n}\n.am-icon-arrow-up:before {\n  content: \"\\f062\";\n}\n.am-icon-arrow-down:before {\n  content: \"\\f063\";\n}\n.am-icon-mail-forward:before,\n.am-icon-share:before {\n  content: \"\\f064\";\n}\n.am-icon-expand:before {\n  content: \"\\f065\";\n}\n.am-icon-compress:before {\n  content: \"\\f066\";\n}\n.am-icon-plus:before {\n  content: \"\\f067\";\n}\n.am-icon-minus:before {\n  content: \"\\f068\";\n}\n.am-icon-asterisk:before {\n  content: \"\\f069\";\n}\n.am-icon-exclamation-circle:before {\n  content: \"\\f06a\";\n}\n.am-icon-gift:before {\n  content: \"\\f06b\";\n}\n.am-icon-leaf:before {\n  content: \"\\f06c\";\n}\n.am-icon-fire:before {\n  content: \"\\f06d\";\n}\n.am-icon-eye:before {\n  content: \"\\f06e\";\n}\n.am-icon-eye-slash:before {\n  content: \"\\f070\";\n}\n.am-icon-warning:before,\n.am-icon-exclamation-triangle:before {\n  content: \"\\f071\";\n}\n.am-icon-plane:before {\n  content: \"\\f072\";\n}\n.am-icon-calendar:before {\n  content: \"\\f073\";\n}\n.am-icon-random:before {\n  content: \"\\f074\";\n}\n.am-icon-comment:before {\n  content: \"\\f075\";\n}\n.am-icon-magnet:before {\n  content: \"\\f076\";\n}\n.am-icon-chevron-up:before {\n  content: \"\\f077\";\n}\n.am-icon-chevron-down:before {\n  content: \"\\f078\";\n}\n.am-icon-retweet:before {\n  content: \"\\f079\";\n}\n.am-icon-shopping-cart:before {\n  content: \"\\f07a\";\n}\n.am-icon-folder:before {\n  content: \"\\f07b\";\n}\n.am-icon-folder-open:before {\n  content: \"\\f07c\";\n}\n.am-icon-arrows-v:before {\n  content: \"\\f07d\";\n}\n.am-icon-arrows-h:before {\n  content: \"\\f07e\";\n}\n.am-icon-bar-chart-o:before,\n.am-icon-bar-chart:before {\n  content: \"\\f080\";\n}\n.am-icon-twitter-square:before {\n  content: \"\\f081\";\n}\n.am-icon-facebook-square:before {\n  content: \"\\f082\";\n}\n.am-icon-camera-retro:before {\n  content: \"\\f083\";\n}\n.am-icon-key:before {\n  content: \"\\f084\";\n}\n.am-icon-gears:before,\n.am-icon-cogs:before {\n  content: \"\\f085\";\n}\n.am-icon-comments:before {\n  content: \"\\f086\";\n}\n.am-icon-thumbs-o-up:before {\n  content: \"\\f087\";\n}\n.am-icon-thumbs-o-down:before {\n  content: \"\\f088\";\n}\n.am-icon-star-half:before {\n  content: \"\\f089\";\n}\n.am-icon-heart-o:before {\n  content: \"\\f08a\";\n}\n.am-icon-sign-out:before {\n  content: \"\\f08b\";\n}\n.am-icon-linkedin-square:before {\n  content: \"\\f08c\";\n}\n.am-icon-thumb-tack:before {\n  content: \"\\f08d\";\n}\n.am-icon-external-link:before {\n  content: \"\\f08e\";\n}\n.am-icon-sign-in:before {\n  content: \"\\f090\";\n}\n.am-icon-trophy:before {\n  content: \"\\f091\";\n}\n.am-icon-github-square:before {\n  content: \"\\f092\";\n}\n.am-icon-upload:before {\n  content: \"\\f093\";\n}\n.am-icon-lemon-o:before {\n  content: \"\\f094\";\n}\n.am-icon-phone:before {\n  content: \"\\f095\";\n}\n.am-icon-square-o:before {\n  content: \"\\f096\";\n}\n.am-icon-bookmark-o:before {\n  content: \"\\f097\";\n}\n.am-icon-phone-square:before {\n  content: \"\\f098\";\n}\n.am-icon-twitter:before {\n  content: \"\\f099\";\n}\n.am-icon-facebook-f:before,\n.am-icon-facebook:before {\n  content: \"\\f09a\";\n}\n.am-icon-github:before {\n  content: \"\\f09b\";\n}\n.am-icon-unlock:before {\n  content: \"\\f09c\";\n}\n.am-icon-credit-card:before {\n  content: \"\\f09d\";\n}\n.am-icon-feed:before,\n.am-icon-rss:before {\n  content: \"\\f09e\";\n}\n.am-icon-hdd-o:before {\n  content: \"\\f0a0\";\n}\n.am-icon-bullhorn:before {\n  content: \"\\f0a1\";\n}\n.am-icon-bell:before {\n  content: \"\\f0f3\";\n}\n.am-icon-certificate:before {\n  content: \"\\f0a3\";\n}\n.am-icon-hand-o-right:before {\n  content: \"\\f0a4\";\n}\n.am-icon-hand-o-left:before {\n  content: \"\\f0a5\";\n}\n.am-icon-hand-o-up:before {\n  content: \"\\f0a6\";\n}\n.am-icon-hand-o-down:before {\n  content: \"\\f0a7\";\n}\n.am-icon-arrow-circle-left:before {\n  content: \"\\f0a8\";\n}\n.am-icon-arrow-circle-right:before {\n  content: \"\\f0a9\";\n}\n.am-icon-arrow-circle-up:before {\n  content: \"\\f0aa\";\n}\n.am-icon-arrow-circle-down:before {\n  content: \"\\f0ab\";\n}\n.am-icon-globe:before {\n  content: \"\\f0ac\";\n}\n.am-icon-wrench:before {\n  content: \"\\f0ad\";\n}\n.am-icon-tasks:before {\n  content: \"\\f0ae\";\n}\n.am-icon-filter:before {\n  content: \"\\f0b0\";\n}\n.am-icon-briefcase:before {\n  content: \"\\f0b1\";\n}\n.am-icon-arrows-alt:before {\n  content: \"\\f0b2\";\n}\n.am-icon-group:before,\n.am-icon-users:before {\n  content: \"\\f0c0\";\n}\n.am-icon-chain:before,\n.am-icon-link:before {\n  content: \"\\f0c1\";\n}\n.am-icon-cloud:before {\n  content: \"\\f0c2\";\n}\n.am-icon-flask:before {\n  content: \"\\f0c3\";\n}\n.am-icon-cut:before,\n.am-icon-scissors:before {\n  content: \"\\f0c4\";\n}\n.am-icon-copy:before,\n.am-icon-files-o:before {\n  content: \"\\f0c5\";\n}\n.am-icon-paperclip:before {\n  content: \"\\f0c6\";\n}\n.am-icon-save:before,\n.am-icon-floppy-o:before {\n  content: \"\\f0c7\";\n}\n.am-icon-square:before {\n  content: \"\\f0c8\";\n}\n.am-icon-navicon:before,\n.am-icon-reorder:before,\n.am-icon-bars:before {\n  content: \"\\f0c9\";\n}\n.am-icon-list-ul:before {\n  content: \"\\f0ca\";\n}\n.am-icon-list-ol:before {\n  content: \"\\f0cb\";\n}\n.am-icon-strikethrough:before {\n  content: \"\\f0cc\";\n}\n.am-icon-underline:before {\n  content: \"\\f0cd\";\n}\n.am-icon-table:before {\n  content: \"\\f0ce\";\n}\n.am-icon-magic:before {\n  content: \"\\f0d0\";\n}\n.am-icon-truck:before {\n  content: \"\\f0d1\";\n}\n.am-icon-pinterest:before {\n  content: \"\\f0d2\";\n}\n.am-icon-pinterest-square:before {\n  content: \"\\f0d3\";\n}\n.am-icon-google-plus-square:before {\n  content: \"\\f0d4\";\n}\n.am-icon-google-plus:before {\n  content: \"\\f0d5\";\n}\n.am-icon-money:before {\n  content: \"\\f0d6\";\n}\n.am-icon-caret-down:before {\n  content: \"\\f0d7\";\n}\n.am-icon-caret-up:before {\n  content: \"\\f0d8\";\n}\n.am-icon-caret-left:before {\n  content: \"\\f0d9\";\n}\n.am-icon-caret-right:before {\n  content: \"\\f0da\";\n}\n.am-icon-columns:before {\n  content: \"\\f0db\";\n}\n.am-icon-unsorted:before,\n.am-icon-sort:before {\n  content: \"\\f0dc\";\n}\n.am-icon-sort-down:before,\n.am-icon-sort-desc:before {\n  content: \"\\f0dd\";\n}\n.am-icon-sort-up:before,\n.am-icon-sort-asc:before {\n  content: \"\\f0de\";\n}\n.am-icon-envelope:before {\n  content: \"\\f0e0\";\n}\n.am-icon-linkedin:before {\n  content: \"\\f0e1\";\n}\n.am-icon-rotate-left:before,\n.am-icon-undo:before {\n  content: \"\\f0e2\";\n}\n.am-icon-legal:before,\n.am-icon-gavel:before {\n  content: \"\\f0e3\";\n}\n.am-icon-dashboard:before,\n.am-icon-tachometer:before {\n  content: \"\\f0e4\";\n}\n.am-icon-comment-o:before {\n  content: \"\\f0e5\";\n}\n.am-icon-comments-o:before {\n  content: \"\\f0e6\";\n}\n.am-icon-flash:before,\n.am-icon-bolt:before {\n  content: \"\\f0e7\";\n}\n.am-icon-sitemap:before {\n  content: \"\\f0e8\";\n}\n.am-icon-umbrella:before {\n  content: \"\\f0e9\";\n}\n.am-icon-paste:before,\n.am-icon-clipboard:before {\n  content: \"\\f0ea\";\n}\n.am-icon-lightbulb-o:before {\n  content: \"\\f0eb\";\n}\n.am-icon-exchange:before {\n  content: \"\\f0ec\";\n}\n.am-icon-cloud-download:before {\n  content: \"\\f0ed\";\n}\n.am-icon-cloud-upload:before {\n  content: \"\\f0ee\";\n}\n.am-icon-user-md:before {\n  content: \"\\f0f0\";\n}\n.am-icon-stethoscope:before {\n  content: \"\\f0f1\";\n}\n.am-icon-suitcase:before {\n  content: \"\\f0f2\";\n}\n.am-icon-bell-o:before {\n  content: \"\\f0a2\";\n}\n.am-icon-coffee:before {\n  content: \"\\f0f4\";\n}\n.am-icon-cutlery:before {\n  content: \"\\f0f5\";\n}\n.am-icon-file-text-o:before {\n  content: \"\\f0f6\";\n}\n.am-icon-building-o:before {\n  content: \"\\f0f7\";\n}\n.am-icon-hospital-o:before {\n  content: \"\\f0f8\";\n}\n.am-icon-ambulance:before {\n  content: \"\\f0f9\";\n}\n.am-icon-medkit:before {\n  content: \"\\f0fa\";\n}\n.am-icon-fighter-jet:before {\n  content: \"\\f0fb\";\n}\n.am-icon-beer:before {\n  content: \"\\f0fc\";\n}\n.am-icon-h-square:before {\n  content: \"\\f0fd\";\n}\n.am-icon-plus-square:before {\n  content: \"\\f0fe\";\n}\n.am-icon-angle-double-left:before {\n  content: \"\\f100\";\n}\n.am-icon-angle-double-right:before {\n  content: \"\\f101\";\n}\n.am-icon-angle-double-up:before {\n  content: \"\\f102\";\n}\n.am-icon-angle-double-down:before {\n  content: \"\\f103\";\n}\n.am-icon-angle-left:before {\n  content: \"\\f104\";\n}\n.am-icon-angle-right:before {\n  content: \"\\f105\";\n}\n.am-icon-angle-up:before {\n  content: \"\\f106\";\n}\n.am-icon-angle-down:before {\n  content: \"\\f107\";\n}\n.am-icon-desktop:before {\n  content: \"\\f108\";\n}\n.am-icon-laptop:before {\n  content: \"\\f109\";\n}\n.am-icon-tablet:before {\n  content: \"\\f10a\";\n}\n.am-icon-mobile-phone:before,\n.am-icon-mobile:before {\n  content: \"\\f10b\";\n}\n.am-icon-circle-o:before {\n  content: \"\\f10c\";\n}\n.am-icon-quote-left:before {\n  content: \"\\f10d\";\n}\n.am-icon-quote-right:before {\n  content: \"\\f10e\";\n}\n.am-icon-spinner:before {\n  content: \"\\f110\";\n}\n.am-icon-circle:before {\n  content: \"\\f111\";\n}\n.am-icon-mail-reply:before,\n.am-icon-reply:before {\n  content: \"\\f112\";\n}\n.am-icon-github-alt:before {\n  content: \"\\f113\";\n}\n.am-icon-folder-o:before {\n  content: \"\\f114\";\n}\n.am-icon-folder-open-o:before {\n  content: \"\\f115\";\n}\n.am-icon-smile-o:before {\n  content: \"\\f118\";\n}\n.am-icon-frown-o:before {\n  content: \"\\f119\";\n}\n.am-icon-meh-o:before {\n  content: \"\\f11a\";\n}\n.am-icon-gamepad:before {\n  content: \"\\f11b\";\n}\n.am-icon-keyboard-o:before {\n  content: \"\\f11c\";\n}\n.am-icon-flag-o:before {\n  content: \"\\f11d\";\n}\n.am-icon-flag-checkered:before {\n  content: \"\\f11e\";\n}\n.am-icon-terminal:before {\n  content: \"\\f120\";\n}\n.am-icon-code:before {\n  content: \"\\f121\";\n}\n.am-icon-mail-reply-all:before,\n.am-icon-reply-all:before {\n  content: \"\\f122\";\n}\n.am-icon-star-half-empty:before,\n.am-icon-star-half-full:before,\n.am-icon-star-half-o:before {\n  content: \"\\f123\";\n}\n.am-icon-location-arrow:before {\n  content: \"\\f124\";\n}\n.am-icon-crop:before {\n  content: \"\\f125\";\n}\n.am-icon-code-fork:before {\n  content: \"\\f126\";\n}\n.am-icon-unlink:before,\n.am-icon-chain-broken:before {\n  content: \"\\f127\";\n}\n.am-icon-question:before {\n  content: \"\\f128\";\n}\n.am-icon-info:before {\n  content: \"\\f129\";\n}\n.am-icon-exclamation:before {\n  content: \"\\f12a\";\n}\n.am-icon-superscript:before {\n  content: \"\\f12b\";\n}\n.am-icon-subscript:before {\n  content: \"\\f12c\";\n}\n.am-icon-eraser:before {\n  content: \"\\f12d\";\n}\n.am-icon-puzzle-piece:before {\n  content: \"\\f12e\";\n}\n.am-icon-microphone:before {\n  content: \"\\f130\";\n}\n.am-icon-microphone-slash:before {\n  content: \"\\f131\";\n}\n.am-icon-shield:before {\n  content: \"\\f132\";\n}\n.am-icon-calendar-o:before {\n  content: \"\\f133\";\n}\n.am-icon-fire-extinguisher:before {\n  content: \"\\f134\";\n}\n.am-icon-rocket:before {\n  content: \"\\f135\";\n}\n.am-icon-maxcdn:before {\n  content: \"\\f136\";\n}\n.am-icon-chevron-circle-left:before {\n  content: \"\\f137\";\n}\n.am-icon-chevron-circle-right:before {\n  content: \"\\f138\";\n}\n.am-icon-chevron-circle-up:before {\n  content: \"\\f139\";\n}\n.am-icon-chevron-circle-down:before {\n  content: \"\\f13a\";\n}\n.am-icon-html5:before {\n  content: \"\\f13b\";\n}\n.am-icon-css3:before {\n  content: \"\\f13c\";\n}\n.am-icon-anchor:before {\n  content: \"\\f13d\";\n}\n.am-icon-unlock-alt:before {\n  content: \"\\f13e\";\n}\n.am-icon-bullseye:before {\n  content: \"\\f140\";\n}\n.am-icon-ellipsis-h:before {\n  content: \"\\f141\";\n}\n.am-icon-ellipsis-v:before {\n  content: \"\\f142\";\n}\n.am-icon-rss-square:before {\n  content: \"\\f143\";\n}\n.am-icon-play-circle:before {\n  content: \"\\f144\";\n}\n.am-icon-ticket:before {\n  content: \"\\f145\";\n}\n.am-icon-minus-square:before {\n  content: \"\\f146\";\n}\n.am-icon-minus-square-o:before {\n  content: \"\\f147\";\n}\n.am-icon-level-up:before {\n  content: \"\\f148\";\n}\n.am-icon-level-down:before {\n  content: \"\\f149\";\n}\n.am-icon-check-square:before {\n  content: \"\\f14a\";\n}\n.am-icon-pencil-square:before {\n  content: \"\\f14b\";\n}\n.am-icon-external-link-square:before {\n  content: \"\\f14c\";\n}\n.am-icon-share-square:before {\n  content: \"\\f14d\";\n}\n.am-icon-compass:before {\n  content: \"\\f14e\";\n}\n.am-icon-toggle-down:before,\n.am-icon-caret-square-o-down:before {\n  content: \"\\f150\";\n}\n.am-icon-toggle-up:before,\n.am-icon-caret-square-o-up:before {\n  content: \"\\f151\";\n}\n.am-icon-toggle-right:before,\n.am-icon-caret-square-o-right:before {\n  content: \"\\f152\";\n}\n.am-icon-euro:before,\n.am-icon-eur:before {\n  content: \"\\f153\";\n}\n.am-icon-gbp:before {\n  content: \"\\f154\";\n}\n.am-icon-dollar:before,\n.am-icon-usd:before {\n  content: \"\\f155\";\n}\n.am-icon-rupee:before,\n.am-icon-inr:before {\n  content: \"\\f156\";\n}\n.am-icon-cny:before,\n.am-icon-rmb:before,\n.am-icon-yen:before,\n.am-icon-jpy:before {\n  content: \"\\f157\";\n}\n.am-icon-ruble:before,\n.am-icon-rouble:before,\n.am-icon-rub:before {\n  content: \"\\f158\";\n}\n.am-icon-won:before,\n.am-icon-krw:before {\n  content: \"\\f159\";\n}\n.am-icon-bitcoin:before,\n.am-icon-btc:before {\n  content: \"\\f15a\";\n}\n.am-icon-file:before {\n  content: \"\\f15b\";\n}\n.am-icon-file-text:before {\n  content: \"\\f15c\";\n}\n.am-icon-sort-alpha-asc:before {\n  content: \"\\f15d\";\n}\n.am-icon-sort-alpha-desc:before {\n  content: \"\\f15e\";\n}\n.am-icon-sort-amount-asc:before {\n  content: \"\\f160\";\n}\n.am-icon-sort-amount-desc:before {\n  content: \"\\f161\";\n}\n.am-icon-sort-numeric-asc:before {\n  content: \"\\f162\";\n}\n.am-icon-sort-numeric-desc:before {\n  content: \"\\f163\";\n}\n.am-icon-thumbs-up:before {\n  content: \"\\f164\";\n}\n.am-icon-thumbs-down:before {\n  content: \"\\f165\";\n}\n.am-icon-youtube-square:before {\n  content: \"\\f166\";\n}\n.am-icon-youtube:before {\n  content: \"\\f167\";\n}\n.am-icon-xing:before {\n  content: \"\\f168\";\n}\n.am-icon-xing-square:before {\n  content: \"\\f169\";\n}\n.am-icon-youtube-play:before {\n  content: \"\\f16a\";\n}\n.am-icon-dropbox:before {\n  content: \"\\f16b\";\n}\n.am-icon-stack-overflow:before {\n  content: \"\\f16c\";\n}\n.am-icon-instagram:before {\n  content: \"\\f16d\";\n}\n.am-icon-flickr:before {\n  content: \"\\f16e\";\n}\n.am-icon-adn:before {\n  content: \"\\f170\";\n}\n.am-icon-bitbucket:before {\n  content: \"\\f171\";\n}\n.am-icon-bitbucket-square:before {\n  content: \"\\f172\";\n}\n.am-icon-tumblr:before {\n  content: \"\\f173\";\n}\n.am-icon-tumblr-square:before {\n  content: \"\\f174\";\n}\n.am-icon-long-arrow-down:before {\n  content: \"\\f175\";\n}\n.am-icon-long-arrow-up:before {\n  content: \"\\f176\";\n}\n.am-icon-long-arrow-left:before {\n  content: \"\\f177\";\n}\n.am-icon-long-arrow-right:before {\n  content: \"\\f178\";\n}\n.am-icon-apple:before {\n  content: \"\\f179\";\n}\n.am-icon-windows:before {\n  content: \"\\f17a\";\n}\n.am-icon-android:before {\n  content: \"\\f17b\";\n}\n.am-icon-linux:before {\n  content: \"\\f17c\";\n}\n.am-icon-dribbble:before {\n  content: \"\\f17d\";\n}\n.am-icon-skype:before {\n  content: \"\\f17e\";\n}\n.am-icon-foursquare:before {\n  content: \"\\f180\";\n}\n.am-icon-trello:before {\n  content: \"\\f181\";\n}\n.am-icon-female:before {\n  content: \"\\f182\";\n}\n.am-icon-male:before {\n  content: \"\\f183\";\n}\n.am-icon-gittip:before,\n.am-icon-gratipay:before {\n  content: \"\\f184\";\n}\n.am-icon-sun-o:before {\n  content: \"\\f185\";\n}\n.am-icon-moon-o:before {\n  content: \"\\f186\";\n}\n.am-icon-archive:before {\n  content: \"\\f187\";\n}\n.am-icon-bug:before {\n  content: \"\\f188\";\n}\n.am-icon-vk:before {\n  content: \"\\f189\";\n}\n.am-icon-weibo:before {\n  content: \"\\f18a\";\n}\n.am-icon-renren:before {\n  content: \"\\f18b\";\n}\n.am-icon-pagelines:before {\n  content: \"\\f18c\";\n}\n.am-icon-stack-exchange:before {\n  content: \"\\f18d\";\n}\n.am-icon-arrow-circle-o-right:before {\n  content: \"\\f18e\";\n}\n.am-icon-arrow-circle-o-left:before {\n  content: \"\\f190\";\n}\n.am-icon-toggle-left:before,\n.am-icon-caret-square-o-left:before {\n  content: \"\\f191\";\n}\n.am-icon-dot-circle-o:before {\n  content: \"\\f192\";\n}\n.am-icon-wheelchair:before {\n  content: \"\\f193\";\n}\n.am-icon-vimeo-square:before {\n  content: \"\\f194\";\n}\n.am-icon-turkish-lira:before,\n.am-icon-try:before {\n  content: \"\\f195\";\n}\n.am-icon-plus-square-o:before {\n  content: \"\\f196\";\n}\n.am-icon-space-shuttle:before {\n  content: \"\\f197\";\n}\n.am-icon-slack:before {\n  content: \"\\f198\";\n}\n.am-icon-envelope-square:before {\n  content: \"\\f199\";\n}\n.am-icon-wordpress:before {\n  content: \"\\f19a\";\n}\n.am-icon-openid:before {\n  content: \"\\f19b\";\n}\n.am-icon-institution:before,\n.am-icon-bank:before,\n.am-icon-university:before {\n  content: \"\\f19c\";\n}\n.am-icon-mortar-board:before,\n.am-icon-graduation-cap:before {\n  content: \"\\f19d\";\n}\n.am-icon-yahoo:before {\n  content: \"\\f19e\";\n}\n.am-icon-google:before {\n  content: \"\\f1a0\";\n}\n.am-icon-reddit:before {\n  content: \"\\f1a1\";\n}\n.am-icon-reddit-square:before {\n  content: \"\\f1a2\";\n}\n.am-icon-stumbleupon-circle:before {\n  content: \"\\f1a3\";\n}\n.am-icon-stumbleupon:before {\n  content: \"\\f1a4\";\n}\n.am-icon-delicious:before {\n  content: \"\\f1a5\";\n}\n.am-icon-digg:before {\n  content: \"\\f1a6\";\n}\n.am-icon-pied-piper:before {\n  content: \"\\f1a7\";\n}\n.am-icon-pied-piper-alt:before {\n  content: \"\\f1a8\";\n}\n.am-icon-drupal:before {\n  content: \"\\f1a9\";\n}\n.am-icon-joomla:before {\n  content: \"\\f1aa\";\n}\n.am-icon-language:before {\n  content: \"\\f1ab\";\n}\n.am-icon-fax:before {\n  content: \"\\f1ac\";\n}\n.am-icon-building:before {\n  content: \"\\f1ad\";\n}\n.am-icon-child:before {\n  content: \"\\f1ae\";\n}\n.am-icon-paw:before {\n  content: \"\\f1b0\";\n}\n.am-icon-spoon:before {\n  content: \"\\f1b1\";\n}\n.am-icon-cube:before {\n  content: \"\\f1b2\";\n}\n.am-icon-cubes:before {\n  content: \"\\f1b3\";\n}\n.am-icon-behance:before {\n  content: \"\\f1b4\";\n}\n.am-icon-behance-square:before {\n  content: \"\\f1b5\";\n}\n.am-icon-steam:before {\n  content: \"\\f1b6\";\n}\n.am-icon-steam-square:before {\n  content: \"\\f1b7\";\n}\n.am-icon-recycle:before {\n  content: \"\\f1b8\";\n}\n.am-icon-automobile:before,\n.am-icon-car:before {\n  content: \"\\f1b9\";\n}\n.am-icon-cab:before,\n.am-icon-taxi:before {\n  content: \"\\f1ba\";\n}\n.am-icon-tree:before {\n  content: \"\\f1bb\";\n}\n.am-icon-spotify:before {\n  content: \"\\f1bc\";\n}\n.am-icon-deviantart:before {\n  content: \"\\f1bd\";\n}\n.am-icon-soundcloud:before {\n  content: \"\\f1be\";\n}\n.am-icon-database:before {\n  content: \"\\f1c0\";\n}\n.am-icon-file-pdf-o:before {\n  content: \"\\f1c1\";\n}\n.am-icon-file-word-o:before {\n  content: \"\\f1c2\";\n}\n.am-icon-file-excel-o:before {\n  content: \"\\f1c3\";\n}\n.am-icon-file-powerpoint-o:before {\n  content: \"\\f1c4\";\n}\n.am-icon-file-photo-o:before,\n.am-icon-file-picture-o:before,\n.am-icon-file-image-o:before {\n  content: \"\\f1c5\";\n}\n.am-icon-file-zip-o:before,\n.am-icon-file-archive-o:before {\n  content: \"\\f1c6\";\n}\n.am-icon-file-sound-o:before,\n.am-icon-file-audio-o:before {\n  content: \"\\f1c7\";\n}\n.am-icon-file-movie-o:before,\n.am-icon-file-video-o:before {\n  content: \"\\f1c8\";\n}\n.am-icon-file-code-o:before {\n  content: \"\\f1c9\";\n}\n.am-icon-vine:before {\n  content: \"\\f1ca\";\n}\n.am-icon-codepen:before {\n  content: \"\\f1cb\";\n}\n.am-icon-jsfiddle:before {\n  content: \"\\f1cc\";\n}\n.am-icon-life-bouy:before,\n.am-icon-life-buoy:before,\n.am-icon-life-saver:before,\n.am-icon-support:before,\n.am-icon-life-ring:before {\n  content: \"\\f1cd\";\n}\n.am-icon-circle-o-notch:before {\n  content: \"\\f1ce\";\n}\n.am-icon-ra:before,\n.am-icon-rebel:before {\n  content: \"\\f1d0\";\n}\n.am-icon-ge:before,\n.am-icon-empire:before {\n  content: \"\\f1d1\";\n}\n.am-icon-git-square:before {\n  content: \"\\f1d2\";\n}\n.am-icon-git:before {\n  content: \"\\f1d3\";\n}\n.am-icon-y-combinator-square:before,\n.am-icon-yc-square:before,\n.am-icon-hacker-news:before {\n  content: \"\\f1d4\";\n}\n.am-icon-tencent-weibo:before {\n  content: \"\\f1d5\";\n}\n.am-icon-qq:before {\n  content: \"\\f1d6\";\n}\n.am-icon-wechat:before,\n.am-icon-weixin:before {\n  content: \"\\f1d7\";\n}\n.am-icon-send:before,\n.am-icon-paper-plane:before {\n  content: \"\\f1d8\";\n}\n.am-icon-send-o:before,\n.am-icon-paper-plane-o:before {\n  content: \"\\f1d9\";\n}\n.am-icon-history:before {\n  content: \"\\f1da\";\n}\n.am-icon-circle-thin:before {\n  content: \"\\f1db\";\n}\n.am-icon-header:before {\n  content: \"\\f1dc\";\n}\n.am-icon-paragraph:before {\n  content: \"\\f1dd\";\n}\n.am-icon-sliders:before {\n  content: \"\\f1de\";\n}\n.am-icon-share-alt:before {\n  content: \"\\f1e0\";\n}\n.am-icon-share-alt-square:before {\n  content: \"\\f1e1\";\n}\n.am-icon-bomb:before {\n  content: \"\\f1e2\";\n}\n.am-icon-soccer-ball-o:before,\n.am-icon-futbol-o:before {\n  content: \"\\f1e3\";\n}\n.am-icon-tty:before {\n  content: \"\\f1e4\";\n}\n.am-icon-binoculars:before {\n  content: \"\\f1e5\";\n}\n.am-icon-plug:before {\n  content: \"\\f1e6\";\n}\n.am-icon-slideshare:before {\n  content: \"\\f1e7\";\n}\n.am-icon-twitch:before {\n  content: \"\\f1e8\";\n}\n.am-icon-yelp:before {\n  content: \"\\f1e9\";\n}\n.am-icon-newspaper-o:before {\n  content: \"\\f1ea\";\n}\n.am-icon-wifi:before {\n  content: \"\\f1eb\";\n}\n.am-icon-calculator:before {\n  content: \"\\f1ec\";\n}\n.am-icon-paypal:before {\n  content: \"\\f1ed\";\n}\n.am-icon-google-wallet:before {\n  content: \"\\f1ee\";\n}\n.am-icon-cc-visa:before {\n  content: \"\\f1f0\";\n}\n.am-icon-cc-mastercard:before {\n  content: \"\\f1f1\";\n}\n.am-icon-cc-discover:before {\n  content: \"\\f1f2\";\n}\n.am-icon-cc-amex:before {\n  content: \"\\f1f3\";\n}\n.am-icon-cc-paypal:before {\n  content: \"\\f1f4\";\n}\n.am-icon-cc-stripe:before {\n  content: \"\\f1f5\";\n}\n.am-icon-bell-slash:before {\n  content: \"\\f1f6\";\n}\n.am-icon-bell-slash-o:before {\n  content: \"\\f1f7\";\n}\n.am-icon-trash:before {\n  content: \"\\f1f8\";\n}\n.am-icon-copyright:before {\n  content: \"\\f1f9\";\n}\n.am-icon-at:before {\n  content: \"\\f1fa\";\n}\n.am-icon-eyedropper:before {\n  content: \"\\f1fb\";\n}\n.am-icon-paint-brush:before {\n  content: \"\\f1fc\";\n}\n.am-icon-birthday-cake:before {\n  content: \"\\f1fd\";\n}\n.am-icon-area-chart:before {\n  content: \"\\f1fe\";\n}\n.am-icon-pie-chart:before {\n  content: \"\\f200\";\n}\n.am-icon-line-chart:before {\n  content: \"\\f201\";\n}\n.am-icon-lastfm:before {\n  content: \"\\f202\";\n}\n.am-icon-lastfm-square:before {\n  content: \"\\f203\";\n}\n.am-icon-toggle-off:before {\n  content: \"\\f204\";\n}\n.am-icon-toggle-on:before {\n  content: \"\\f205\";\n}\n.am-icon-bicycle:before {\n  content: \"\\f206\";\n}\n.am-icon-bus:before {\n  content: \"\\f207\";\n}\n.am-icon-ioxhost:before {\n  content: \"\\f208\";\n}\n.am-icon-angellist:before {\n  content: \"\\f209\";\n}\n.am-icon-cc:before {\n  content: \"\\f20a\";\n}\n.am-icon-shekel:before,\n.am-icon-sheqel:before,\n.am-icon-ils:before {\n  content: \"\\f20b\";\n}\n.am-icon-meanpath:before {\n  content: \"\\f20c\";\n}\n.am-icon-buysellads:before {\n  content: \"\\f20d\";\n}\n.am-icon-connectdevelop:before {\n  content: \"\\f20e\";\n}\n.am-icon-dashcube:before {\n  content: \"\\f210\";\n}\n.am-icon-forumbee:before {\n  content: \"\\f211\";\n}\n.am-icon-leanpub:before {\n  content: \"\\f212\";\n}\n.am-icon-sellsy:before {\n  content: \"\\f213\";\n}\n.am-icon-shirtsinbulk:before {\n  content: \"\\f214\";\n}\n.am-icon-simplybuilt:before {\n  content: \"\\f215\";\n}\n.am-icon-skyatlas:before {\n  content: \"\\f216\";\n}\n.am-icon-cart-plus:before {\n  content: \"\\f217\";\n}\n.am-icon-cart-arrow-down:before {\n  content: \"\\f218\";\n}\n.am-icon-diamond:before {\n  content: \"\\f219\";\n}\n.am-icon-ship:before {\n  content: \"\\f21a\";\n}\n.am-icon-user-secret:before {\n  content: \"\\f21b\";\n}\n.am-icon-motorcycle:before {\n  content: \"\\f21c\";\n}\n.am-icon-street-view:before {\n  content: \"\\f21d\";\n}\n.am-icon-heartbeat:before {\n  content: \"\\f21e\";\n}\n.am-icon-venus:before {\n  content: \"\\f221\";\n}\n.am-icon-mars:before {\n  content: \"\\f222\";\n}\n.am-icon-mercury:before {\n  content: \"\\f223\";\n}\n.am-icon-intersex:before,\n.am-icon-transgender:before {\n  content: \"\\f224\";\n}\n.am-icon-transgender-alt:before {\n  content: \"\\f225\";\n}\n.am-icon-venus-double:before {\n  content: \"\\f226\";\n}\n.am-icon-mars-double:before {\n  content: \"\\f227\";\n}\n.am-icon-venus-mars:before {\n  content: \"\\f228\";\n}\n.am-icon-mars-stroke:before {\n  content: \"\\f229\";\n}\n.am-icon-mars-stroke-v:before {\n  content: \"\\f22a\";\n}\n.am-icon-mars-stroke-h:before {\n  content: \"\\f22b\";\n}\n.am-icon-neuter:before {\n  content: \"\\f22c\";\n}\n.am-icon-genderless:before {\n  content: \"\\f22d\";\n}\n.am-icon-facebook-official:before {\n  content: \"\\f230\";\n}\n.am-icon-pinterest-p:before {\n  content: \"\\f231\";\n}\n.am-icon-whatsapp:before {\n  content: \"\\f232\";\n}\n.am-icon-server:before {\n  content: \"\\f233\";\n}\n.am-icon-user-plus:before {\n  content: \"\\f234\";\n}\n.am-icon-user-times:before {\n  content: \"\\f235\";\n}\n.am-icon-hotel:before,\n.am-icon-bed:before {\n  content: \"\\f236\";\n}\n.am-icon-viacoin:before {\n  content: \"\\f237\";\n}\n.am-icon-train:before {\n  content: \"\\f238\";\n}\n.am-icon-subway:before {\n  content: \"\\f239\";\n}\n.am-icon-medium:before {\n  content: \"\\f23a\";\n}\n.am-icon-yc:before,\n.am-icon-y-combinator:before {\n  content: \"\\f23b\";\n}\n.am-icon-optin-monster:before {\n  content: \"\\f23c\";\n}\n.am-icon-opencart:before {\n  content: \"\\f23d\";\n}\n.am-icon-expeditedssl:before {\n  content: \"\\f23e\";\n}\n.am-icon-battery-4:before,\n.am-icon-battery-full:before {\n  content: \"\\f240\";\n}\n.am-icon-battery-3:before,\n.am-icon-battery-three-quarters:before {\n  content: \"\\f241\";\n}\n.am-icon-battery-2:before,\n.am-icon-battery-half:before {\n  content: \"\\f242\";\n}\n.am-icon-battery-1:before,\n.am-icon-battery-quarter:before {\n  content: \"\\f243\";\n}\n.am-icon-battery-0:before,\n.am-icon-battery-empty:before {\n  content: \"\\f244\";\n}\n.am-icon-mouse-pointer:before {\n  content: \"\\f245\";\n}\n.am-icon-i-cursor:before {\n  content: \"\\f246\";\n}\n.am-icon-object-group:before {\n  content: \"\\f247\";\n}\n.am-icon-object-ungroup:before {\n  content: \"\\f248\";\n}\n.am-icon-sticky-note:before {\n  content: \"\\f249\";\n}\n.am-icon-sticky-note-o:before {\n  content: \"\\f24a\";\n}\n.am-icon-cc-jcb:before {\n  content: \"\\f24b\";\n}\n.am-icon-cc-diners-club:before {\n  content: \"\\f24c\";\n}\n.am-icon-clone:before {\n  content: \"\\f24d\";\n}\n.am-icon-balance-scale:before {\n  content: \"\\f24e\";\n}\n.am-icon-hourglass-o:before {\n  content: \"\\f250\";\n}\n.am-icon-hourglass-1:before,\n.am-icon-hourglass-start:before {\n  content: \"\\f251\";\n}\n.am-icon-hourglass-2:before,\n.am-icon-hourglass-half:before {\n  content: \"\\f252\";\n}\n.am-icon-hourglass-3:before,\n.am-icon-hourglass-end:before {\n  content: \"\\f253\";\n}\n.am-icon-hourglass:before {\n  content: \"\\f254\";\n}\n.am-icon-hand-grab-o:before,\n.am-icon-hand-rock-o:before {\n  content: \"\\f255\";\n}\n.am-icon-hand-stop-o:before,\n.am-icon-hand-paper-o:before {\n  content: \"\\f256\";\n}\n.am-icon-hand-scissors-o:before {\n  content: \"\\f257\";\n}\n.am-icon-hand-lizard-o:before {\n  content: \"\\f258\";\n}\n.am-icon-hand-spock-o:before {\n  content: \"\\f259\";\n}\n.am-icon-hand-pointer-o:before {\n  content: \"\\f25a\";\n}\n.am-icon-hand-peace-o:before {\n  content: \"\\f25b\";\n}\n.am-icon-trademark:before {\n  content: \"\\f25c\";\n}\n.am-icon-registered:before {\n  content: \"\\f25d\";\n}\n.am-icon-creative-commons:before {\n  content: \"\\f25e\";\n}\n.am-icon-gg:before {\n  content: \"\\f260\";\n}\n.am-icon-gg-circle:before {\n  content: \"\\f261\";\n}\n.am-icon-tripadvisor:before {\n  content: \"\\f262\";\n}\n.am-icon-odnoklassniki:before {\n  content: \"\\f263\";\n}\n.am-icon-odnoklassniki-square:before {\n  content: \"\\f264\";\n}\n.am-icon-get-pocket:before {\n  content: \"\\f265\";\n}\n.am-icon-wikipedia-w:before {\n  content: \"\\f266\";\n}\n.am-icon-safari:before {\n  content: \"\\f267\";\n}\n.am-icon-chrome:before {\n  content: \"\\f268\";\n}\n.am-icon-firefox:before {\n  content: \"\\f269\";\n}\n.am-icon-opera:before {\n  content: \"\\f26a\";\n}\n.am-icon-internet-explorer:before {\n  content: \"\\f26b\";\n}\n.am-icon-tv:before,\n.am-icon-television:before {\n  content: \"\\f26c\";\n}\n.am-icon-contao:before {\n  content: \"\\f26d\";\n}\n.am-icon-500px:before {\n  content: \"\\f26e\";\n}\n.am-icon-amazon:before {\n  content: \"\\f270\";\n}\n.am-icon-calendar-plus-o:before {\n  content: \"\\f271\";\n}\n.am-icon-calendar-minus-o:before {\n  content: \"\\f272\";\n}\n.am-icon-calendar-times-o:before {\n  content: \"\\f273\";\n}\n.am-icon-calendar-check-o:before {\n  content: \"\\f274\";\n}\n.am-icon-industry:before {\n  content: \"\\f275\";\n}\n.am-icon-map-pin:before {\n  content: \"\\f276\";\n}\n.am-icon-map-signs:before {\n  content: \"\\f277\";\n}\n.am-icon-map-o:before {\n  content: \"\\f278\";\n}\n.am-icon-map:before {\n  content: \"\\f279\";\n}\n.am-icon-commenting:before {\n  content: \"\\f27a\";\n}\n.am-icon-commenting-o:before {\n  content: \"\\f27b\";\n}\n.am-icon-houzz:before {\n  content: \"\\f27c\";\n}\n.am-icon-vimeo:before {\n  content: \"\\f27d\";\n}\n.am-icon-black-tie:before {\n  content: \"\\f27e\";\n}\n.am-icon-fonticons:before {\n  content: \"\\f280\";\n}\n.am-icon-reddit-alien:before {\n  content: \"\\f281\";\n}\n.am-icon-edge:before {\n  content: \"\\f282\";\n}\n.am-icon-credit-card-alt:before {\n  content: \"\\f283\";\n}\n.am-icon-codiepie:before {\n  content: \"\\f284\";\n}\n.am-icon-modx:before {\n  content: \"\\f285\";\n}\n.am-icon-fort-awesome:before {\n  content: \"\\f286\";\n}\n.am-icon-usb:before {\n  content: \"\\f287\";\n}\n.am-icon-product-hunt:before {\n  content: \"\\f288\";\n}\n.am-icon-mixcloud:before {\n  content: \"\\f289\";\n}\n.am-icon-scribd:before {\n  content: \"\\f28a\";\n}\n.am-icon-pause-circle:before {\n  content: \"\\f28b\";\n}\n.am-icon-pause-circle-o:before {\n  content: \"\\f28c\";\n}\n.am-icon-stop-circle:before {\n  content: \"\\f28d\";\n}\n.am-icon-stop-circle-o:before {\n  content: \"\\f28e\";\n}\n.am-icon-shopping-bag:before {\n  content: \"\\f290\";\n}\n.am-icon-shopping-basket:before {\n  content: \"\\f291\";\n}\n.am-icon-hashtag:before {\n  content: \"\\f292\";\n}\n.am-icon-bluetooth:before {\n  content: \"\\f293\";\n}\n.am-icon-bluetooth-b:before {\n  content: \"\\f294\";\n}\n.am-icon-percent:before {\n  content: \"\\f295\";\n}\n/* Modifier: `am-icon-spin`\n============================================================================= */\n@-webkit-keyframes icon-spin {\n  0% {\n    -webkit-transform: rotate(0deg);\n            transform: rotate(0deg);\n  }\n  100% {\n    -webkit-transform: rotate(359deg);\n            transform: rotate(359deg);\n  }\n}\n@keyframes icon-spin {\n  0% {\n    -webkit-transform: rotate(0deg);\n            transform: rotate(0deg);\n  }\n  100% {\n    -webkit-transform: rotate(359deg);\n            transform: rotate(359deg);\n  }\n}\n.am-icon-spin {\n  -webkit-animation: icon-spin 2s infinite linear;\n          animation: icon-spin 2s infinite linear;\n}\n.am-icon-pulse {\n  -webkit-animation: icon-spin 1s infinite steps(8);\n          animation: icon-spin 1s infinite steps(8);\n}\n.am-icon-ul {\n  padding-left: 0;\n  margin-left: 2.14285714em;\n  list-style-type: none;\n}\n.am-icon-ul > li {\n  position: relative;\n}\n.am-icon-li {\n  position: absolute;\n  left: -2.14285714em;\n  width: 2.14285714em;\n  top: 0.14285714em;\n  text-align: center;\n}\n/* ==========================================================================\n   Component: Input group\n ============================================================================ */\n.am-input-group {\n  position: relative;\n  display: table;\n  border-collapse: separate;\n}\n.am-input-group .am-form-field {\n  position: relative;\n  z-index: 2;\n  float: left;\n  width: 100%;\n  margin-bottom: 0;\n}\n.am-input-group-label,\n.am-input-group-btn,\n.am-input-group .am-form-field {\n  display: table-cell;\n}\n.am-input-group-label:not(:first-child):not(:last-child),\n.am-input-group-btn:not(:first-child):not(:last-child),\n.am-input-group .am-form-field:not(:first-child):not(:last-child) {\n  border-radius: 0;\n}\n.am-input-group-label,\n.am-input-group-btn {\n  width: 1%;\n  white-space: nowrap;\n  vertical-align: middle;\n}\n.am-input-group-label {\n  height: 38px;\n  padding: 0 1em;\n  font-size: 1.6rem;\n  font-weight: normal;\n  line-height: 36px;\n  color: #555555;\n  text-align: center;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n  border-radius: 0;\n}\n.am-input-group-label input[type=\"radio\"],\n.am-input-group-label input[type=\"checkbox\"] {\n  margin-top: 0;\n}\n.am-input-group .am-form-field:first-child,\n.am-input-group-label:first-child,\n.am-input-group-btn:first-child > .am-btn,\n.am-input-group-btn:first-child > .am-btn-group > .am-btn,\n.am-input-group-btn:first-child > .am-dropdown-toggle,\n.am-input-group-btn:last-child > .am-btn:not(:last-child):not(.dropdown-toggle),\n.am-input-group-btn:last-child > .am-btn-group:not(:last-child) > .am-btn {\n  border-bottom-right-radius: 0;\n  border-top-right-radius: 0;\n}\n.am-input-group-label:first-child {\n  border-right: 0;\n}\n.am-input-group .am-form-field:last-child,\n.am-input-group-label:last-child,\n.am-input-group-btn:last-child > .am-btn,\n.am-input-group-btn:last-child > .am-btn-group > .am-btn,\n.am-input-group-btn:last-child > .am-dropdown-toggle,\n.am-input-group-btn:first-child > .am-btn:not(:first-child),\n.am-input-group-btn:first-child > .am-btn-group:not(:first-child) > .am-btn {\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n}\n.am-input-group-label:last-child {\n  border-left: 0;\n}\n.am-input-group-btn {\n  position: relative;\n  font-size: 0;\n  white-space: nowrap;\n}\n.am-input-group-btn > .am-btn {\n  position: relative;\n  border-color: #ccc;\n}\n.am-input-group-btn > .am-btn + .am-btn {\n  margin-left: -1px;\n}\n.am-input-group-btn > .am-btn:hover,\n.am-input-group-btn > .am-btn:focus,\n.am-input-group-btn > .am-btn:active {\n  z-index: 2;\n}\n.am-input-group-btn:first-child > .am-btn,\n.am-input-group-btn:first-child > .am-btn-group {\n  margin-right: -2px;\n}\n.am-input-group-btn:last-child > .am-btn,\n.am-input-group-btn:last-child > .am-btn-group {\n  margin-left: -1px;\n}\n.am-input-group .am-form-field,\n.am-input-group-btn > .am-btn {\n  height: 38px;\n  padding-bottom: auto;\n}\n.am-input-group-lg > .am-form-field,\n.am-input-group-lg > .am-input-group-label,\n.am-input-group-lg > .am-input-group-btn > .am-btn {\n  height: 42px;\n  font-size: 1.8rem !important;\n}\n.am-input-group-lg > .am-input-group-label {\n  line-height: 40px;\n}\n.am-input-group-sm > .am-form-field,\n.am-input-group-sm > .am-input-group-label,\n.am-input-group-sm > .am-input-group-btn > .am-btn {\n  height: 33px;\n  font-size: 1.4rem !important;\n}\n.am-input-group-sm > .am-input-group-label {\n  line-height: 31px;\n}\n.am-input-group-primary .am-input-group-label {\n  background: #0e90d2;\n  color: #fff;\n}\n.am-input-group-primary .am-input-group-label,\n.am-input-group-primary .am-input-group-btn > .am-btn,\n.am-input-group-primary.am-input-group .am-form-field {\n  border-color: #0e90d2;\n}\n.am-input-group-secondary .am-input-group-label {\n  background: #3bb4f2;\n  color: #fff;\n}\n.am-input-group-secondary .am-input-group-label,\n.am-input-group-secondary .am-input-group-btn > .am-btn,\n.am-input-group-secondary.am-input-group .am-form-field {\n  border-color: #3bb4f2;\n}\n.am-input-group-success .am-input-group-label {\n  background: #5eb95e;\n  color: #fff;\n}\n.am-input-group-success .am-input-group-label,\n.am-input-group-success .am-input-group-btn > .am-btn,\n.am-input-group-success.am-input-group .am-form-field {\n  border-color: #5eb95e;\n}\n.am-input-group-warning .am-input-group-label {\n  background: #F37B1D;\n  color: #fff;\n}\n.am-input-group-warning .am-input-group-label,\n.am-input-group-warning .am-input-group-btn > .am-btn,\n.am-input-group-warning.am-input-group .am-form-field {\n  border-color: #F37B1D;\n}\n.am-input-group-danger .am-input-group-label {\n  background: #dd514c;\n  color: #fff;\n}\n.am-input-group-danger .am-input-group-label,\n.am-input-group-danger .am-input-group-btn > .am-btn,\n.am-input-group-danger.am-input-group .am-form-field {\n  border-color: #dd514c;\n}\n/* ==========================================================================\n   Component: List\n ============================================================================ */\n.am-list {\n  margin-bottom: 1.6rem;\n  padding-left: 0;\n}\n.am-list > li {\n  position: relative;\n  display: block;\n  margin-bottom: -1px;\n  background-color: #fff;\n  border: 1px solid #dedede;\n  border-width: 1px 0;\n}\n.am-list > li > a {\n  display: block;\n  padding: 1rem 0;\n}\n.am-list > li > a.am-active,\n.am-list > li > a.am-active:hover,\n.am-list > li > a.am-active:focus {\n  z-index: 2;\n  color: #fff;\n  background-color: #0e90d2;\n  border-color: #0e90d2;\n}\n.am-list > li > a.am-active .am-list-item-heading,\n.am-list > li > a.am-active:hover .am-list-item-heading,\n.am-list > li > a.am-active:focus .am-list-item-heading {\n  color: inherit;\n}\n.am-list > li > a.am-active .am-list-item-text,\n.am-list > li > a.am-active:hover .am-list-item-text,\n.am-list > li > a.am-active:focus .am-list-item-text {\n  color: #b2e2fa;\n}\n.am-list > li > .am-badge {\n  float: right;\n}\n.am-list > li > .am-badge + .am-badge {\n  margin-right: 5px;\n}\n/* Pure text list */\n.am-list-static > li {\n  padding: .8rem .2rem;\n}\n.am-list-static.am-list-border > li {\n  padding: 1rem;\n}\n/* with border */\n.am-list-border > li,\n.am-list-bordered > li {\n  border-width: 1px;\n}\n.am-list-border > li:first-child,\n.am-list-bordered > li:first-child,\n.am-list-border > li:first-child > a,\n.am-list-bordered > li:first-child > a {\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n.am-list-border > li:last-child,\n.am-list-bordered > li:last-child,\n.am-list-border > li:last-child > a,\n.am-list-bordered > li:last-child > a {\n  margin-bottom: 0;\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n.am-list-border > li > a,\n.am-list-bordered > li > a {\n  padding: 1rem;\n}\n.am-list-border > li > a:hover,\n.am-list-bordered > li > a:hover,\n.am-list-border > li > a:focus,\n.am-list-bordered > li > a:focus {\n  background-color: #f5f5f5;\n}\n/* Striped */\n.am-list-striped > li:nth-of-type(even) {\n  background: #f5f5f5;\n}\n.am-list-item-hd {\n  margin-top: 0;\n}\n.am-list-item-text {\n  line-height: 1.4;\n  font-size: 1.3rem;\n  color: #999999;\n  margin: 0;\n}\n/* ==========================================================================\n   Component: Panel\n ============================================================================ */\n.am-panel {\n  margin-bottom: 20px;\n  background-color: #fff;\n  border: 1px solid transparent;\n  border-radius: 0;\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/* Panel header */\n.am-panel-hd {\n  padding: 0.6rem 1.25rem;\n  border-bottom: 1px solid transparent;\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n/* Panel content */\n.am-panel-bd {\n  padding: 1.25rem;\n}\n.am-panel-title {\n  margin: 0;\n  font-size: 100%;\n  color: inherit;\n}\n.am-panel-title > a {\n  color: inherit;\n}\n/* Panel footer */\n.am-panel-footer {\n  padding: 0.6rem 1.25rem;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n.am-panel-default {\n  border-color: #ddd;\n}\n.am-panel-default > .am-panel-hd {\n  color: #444;\n  background-color: #f5f5f5;\n  border-color: #ddd;\n}\n.am-panel-default > .am-panel-hd + .am-panel-collapse > .am-panel-bd {\n  border-top-color: #ddd;\n}\n.am-panel-default > .am-panel-footer + .am-panel-collapse > .am-panel-bd {\n  border-bottom-color: #ddd;\n}\n.am-panel-primary {\n  border-color: #10a0ea;\n}\n.am-panel-primary > .am-panel-hd {\n  color: #fff;\n  background-color: #0e90d2;\n  border-color: #10a0ea;\n}\n.am-panel-primary > .am-panel-hd + .am-panel-collapse > .am-panel-bd {\n  border-top-color: #10a0ea;\n}\n.am-panel-primary > .am-panel-footer + .am-panel-collapse > .am-panel-bd {\n  border-bottom-color: #10a0ea;\n}\n.am-panel-secondary {\n  border-color: #caebfb;\n}\n.am-panel-secondary > .am-panel-hd {\n  color: #14a6ef;\n  background-color: rgba(59, 180, 242, 0.15);\n  border-color: #caebfb;\n}\n.am-panel-secondary > .am-panel-hd + .am-panel-collapse > .am-panel-bd {\n  border-top-color: #caebfb;\n}\n.am-panel-secondary > .am-panel-footer + .am-panel-collapse > .am-panel-bd {\n  border-bottom-color: #caebfb;\n}\n.am-panel-success {\n  border-color: #c9e7c9;\n}\n.am-panel-success > .am-panel-hd {\n  color: #5eb95e;\n  background-color: rgba(94, 185, 94, 0.15);\n  border-color: #c9e7c9;\n}\n.am-panel-success > .am-panel-hd + .am-panel-collapse > .am-panel-bd {\n  border-top-color: #c9e7c9;\n}\n.am-panel-success > .am-panel-footer + .am-panel-collapse > .am-panel-bd {\n  border-bottom-color: #c9e7c9;\n}\n.am-panel-warning {\n  border-color: #fbd0ae;\n}\n.am-panel-warning > .am-panel-hd {\n  color: #F37B1D;\n  background-color: rgba(243, 123, 29, 0.15);\n  border-color: #fbd0ae;\n}\n.am-panel-warning > .am-panel-hd + .am-panel-collapse > .am-panel-bd {\n  border-top-color: #fbd0ae;\n}\n.am-panel-warning > .am-panel-footer + .am-panel-collapse > .am-panel-bd {\n  border-bottom-color: #fbd0ae;\n}\n.am-panel-danger {\n  border-color: #f5cecd;\n}\n.am-panel-danger > .am-panel-hd {\n  color: #dd514c;\n  background-color: rgba(221, 81, 76, 0.15);\n  border-color: #f5cecd;\n}\n.am-panel-danger > .am-panel-hd + .am-panel-collapse > .am-panel-bd {\n  border-top-color: #f5cecd;\n}\n.am-panel-danger > .am-panel-footer + .am-panel-collapse > .am-panel-bd {\n  border-bottom-color: #f5cecd;\n}\n.am-panel > .am-table {\n  margin-bottom: 0;\n}\n.am-panel > .am-table:first-child {\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n.am-panel > .am-table:first-child > thead:first-child > tr:first-child td:first-child,\n.am-panel > .am-table:first-child > tbody:first-child > tr:first-child td:first-child,\n.am-panel > .am-table:first-child > thead:first-child > tr:first-child th:first-child,\n.am-panel > .am-table:first-child > tbody:first-child > tr:first-child th:first-child {\n  border-top-left-radius: 0;\n}\n.am-panel > .am-table:first-child > thead:first-child > tr:first-child td:last-child,\n.am-panel > .am-table:first-child > tbody:first-child > tr:first-child td:last-child,\n.am-panel > .am-table:first-child > thead:first-child > tr:first-child th:last-child,\n.am-panel > .am-table:first-child > tbody:first-child > tr:first-child th:last-child {\n  border-top-right-radius: 0;\n}\n.am-panel > .am-table:last-child {\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n.am-panel > .am-table:last-child > tbody:last-child > tr:last-child td:first-child,\n.am-panel > .am-table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.am-panel > .am-table:last-child > tbody:last-child > tr:last-child th:first-child,\n.am-panel > .am-table:last-child > tfoot:last-child > tr:last-child th:first-child {\n  border-bottom-left-radius: 0;\n}\n.am-panel > .am-table:last-child > tbody:last-child > tr:last-child td:last-child,\n.am-panel > .am-table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.am-panel > .am-table:last-child > tbody:last-child > tr:last-child th:last-child,\n.am-panel > .am-table:last-child > tfoot:last-child > tr:last-child th:last-child {\n  border-bottom-right-radius: 0;\n}\n.am-panel > .am-panel-bd + .am-table {\n  border-top: 1px solid #ddd;\n}\n.am-panel > .am-table > tbody:first-child > tr:first-child th,\n.am-panel > .am-table > tbody:first-child > tr:first-child td {\n  border-top: 0;\n}\n.am-panel > .am-table-bd {\n  border: 0;\n}\n.am-panel > .am-table-bd > thead > tr > th:first-child,\n.am-panel > .am-table-bd > tbody > tr > th:first-child,\n.am-panel > .am-table-bd > tfoot > tr > th:first-child,\n.am-panel > .am-table-bd > thead > tr > td:first-child,\n.am-panel > .am-table-bd > tbody > tr > td:first-child,\n.am-panel > .am-table-bd > tfoot > tr > td:first-child {\n  border-left: 0;\n}\n.am-panel > .am-table-bd > thead > tr > th:last-child,\n.am-panel > .am-table-bd > tbody > tr > th:last-child,\n.am-panel > .am-table-bd > tfoot > tr > th:last-child,\n.am-panel > .am-table-bd > thead > tr > td:last-child,\n.am-panel > .am-table-bd > tbody > tr > td:last-child,\n.am-panel > .am-table-bd > tfoot > tr > td:last-child {\n  border-right: 0;\n}\n.am-panel > .am-table-bd > thead > tr:first-child > td,\n.am-panel > .am-table-bd > tbody > tr:first-child > td,\n.am-panel > .am-table-bd > thead > tr:first-child > th,\n.am-panel > .am-table-bd > tbody > tr:first-child > th {\n  border-bottom: 0;\n}\n.am-panel > .am-table-bd > tbody > tr:last-child > td,\n.am-panel > .am-table-bd > tfoot > tr:last-child > td,\n.am-panel > .am-table-bd > tbody > tr:last-child > th,\n.am-panel > .am-table-bd > tfoot > tr:last-child > th {\n  border-bottom: 0;\n}\n/* Wrap list */\n.am-panel > .am-list {\n  margin: 0;\n}\n.am-panel > .am-list > li > a {\n  padding-left: 1rem;\n  padding-right: 1rem;\n}\n.am-panel > .am-list-static li {\n  padding-left: 1rem;\n  padding-right: 1rem;\n}\n/* Panel group */\n.am-panel-group {\n  margin-bottom: 2rem;\n}\n.am-panel-group .am-panel {\n  margin-bottom: 0;\n  border-radius: 0;\n}\n.am-panel-group .am-panel + .am-panel {\n  margin-top: 6px;\n}\n.am-panel-group .am-panel-hd {\n  border-bottom: 0;\n}\n.am-panel-group .am-panel-hd + .am-panel-collapse .am-panel-bd {\n  border-top: 1px solid #ddd;\n}\n.am-panel-group .am-panel-footer {\n  border-top: 0;\n}\n.am-panel-group .am-panel-footer + .am-panel-collapse .am-panel-bd {\n  border-bottom: 1px solid #ddd;\n}\n/* ==========================================================================\n   Component: Progress\n ============================================================================ */\n/* Progress bar animation */\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 36px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 36px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n/*  Progress container */\n.am-progress {\n  overflow: hidden;\n  height: 2rem;\n  margin-bottom: 2rem;\n  background-color: #f5f5f5;\n  border-radius: 0;\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/* Progress bar */\n.am-progress-bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 1.2rem;\n  line-height: 2rem;\n  color: #fff;\n  text-align: center;\n  background-color: #0e90d2;\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 .6s ease;\n  transition: width .6s ease;\n}\n.am-progress-striped .am-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: 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  -webkit-background-size: 36px 36px;\n          background-size: 36px 36px;\n}\n.am-progress.am-active .am-progress-bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n.am-progress-bar[aria-valuenow=\"1\"],\n.am-progress-bar[aria-valuenow=\"2\"] {\n  min-width: 30px;\n}\n.am-progress-bar[aria-valuenow=\"0\"] {\n  color: #999999;\n  min-width: 30px;\n  background: none;\n  -webkit-box-shadow: none;\n          box-shadow: none;\n}\n.am-progress-bar-secondary {\n  background-color: #3bb4f2;\n}\n.am-progress-striped .am-progress-bar-secondary {\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: 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.am-progress-bar-success {\n  background-color: #5eb95e;\n}\n.am-progress-striped .am-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: 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.am-progress-bar-warning {\n  background-color: #F37B1D;\n}\n.am-progress-striped .am-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: 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.am-progress-bar-danger {\n  background-color: #dd514c;\n}\n.am-progress-striped .am-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: 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.am-progress-xs {\n  height: 0.6rem;\n}\n.am-progress-sm {\n  height: 1.2rem;\n}\n/* ==========================================================================\n   Component: Thumbnail\n ============================================================================ */\n.am-thumbnail {\n  display: block;\n  padding: 2px;\n  margin-bottom: 2rem;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  border-radius: 0;\n  -webkit-transition: all 0.2s ease-in-out;\n  transition: all 0.2s ease-in-out;\n}\n.am-thumbnail > img,\n.am-thumbnail a > img {\n  margin-left: auto;\n  margin-right: auto;\n  display: block;\n}\n.am-thumbnail a.am-thumbnail:hover,\n.am-thumbnail a.am-thumbnail:focus,\n.am-thumbnail a.am-thumbnail.active {\n  border-color: #0e90d2;\n  background-color: #fff;\n}\nimg.am-thumbnail,\n.am-thumbnail > img,\n.am-thumbnail a > img {\n  max-width: 100%;\n  height: auto;\n}\n/* Image caption */\n.am-thumbnail-caption {\n  margin: 0;\n  padding: 0.8rem;\n  color: #333;\n  font-weight: normal;\n}\n.am-thumbnail-caption *:last-child {\n  margin-bottom: 0;\n}\n.am-thumbnails {\n  margin-left: -0.5rem;\n  margin-right: -0.5rem;\n}\n.am-thumbnails > li {\n  padding: 0 .5rem 1rem .5rem;\n}\n/* ==========================================================================\n   Component: Utility\n ============================================================================ */\n.am-scrollable-horizontal {\n  width: 100%;\n  overflow-y: hidden;\n  overflow-x: auto;\n  -ms-overflow-style: -ms-autohiding-scrollbar;\n  -webkit-overflow-scrolling: touch;\n}\n.am-scrollable-vertical {\n  height: 240px;\n  overflow-y: scroll;\n  -webkit-overflow-scrolling: touch;\n  resize: vertical;\n}\n/* Border-radius*/\n.am-square {\n  border-radius: 0;\n}\n.am-radius {\n  border-radius: 2px;\n}\n.am-round {\n  border-radius: 1000px;\n}\n.am-circle {\n  border-radius: 50%;\n}\n/* Float blocks*/\n.am-cf:before,\n.am-cf:after {\n  content: \" \";\n  display: table;\n}\n.am-cf:after {\n  clear: both;\n}\n.am-fl {\n  float: left;\n}\n.am-fr {\n  float: right;\n}\n.am-nbfc {\n  overflow: hidden;\n}\n.am-center {\n  display: block;\n  margin-left: auto;\n  margin-right: auto;\n}\n/* Display */\n.am-block {\n  display: block !important;\n}\n.am-inline {\n  display: inline !important;\n}\n.am-inline-block {\n  display: inline-block !important;\n}\n.am-hide {\n  display: none !important;\n  visibility: hidden !important;\n}\n/*\n* Remove whitespace between child elements when using `inline-block`\n*/\n.am-vertical-align {\n  font-size: 0.001px;\n}\n/*\n* The `@{ns}vertical-align` container needs a specific height\n*/\n.am-vertical-align:before {\n  content: '';\n  display: inline-block;\n  height: 100%;\n  vertical-align: middle;\n}\n/*\n* Sub-object which can have any height\n* 1. Reset whitespace hack\n*/\n.am-vertical-align-middle,\n.am-vertical-align-bottom {\n  display: inline-block;\n  font-size: 1.6rem;\n  /* 1 */\n  max-width: 100%;\n}\n.am-vertical-align-middle {\n  vertical-align: middle;\n}\n.am-vertical-align-bottom {\n  vertical-align: bottom;\n}\n.am-responsive-width {\n  -webkit-box-sizing: border-box;\n          box-sizing: border-box;\n  max-width: 100%;\n  height: auto;\n}\n/* Margin helpers */\n.am-margin {\n  margin: 1.6rem;\n}\n.am-margin-0 {\n  margin: 0!important;\n}\n.am-margin-xs {\n  margin: 0.5rem;\n}\n.am-margin-sm {\n  margin: 1rem;\n}\n.am-margin-lg {\n  margin: 2.4rem;\n}\n.am-margin-xl {\n  margin: 3.2rem;\n}\n.am-margin-horizontal {\n  margin-left: 1.6rem;\n  margin-right: 1.6rem;\n}\n.am-margin-horizontal-0 {\n  margin-left: 0!important;\n  margin-right: 0!important;\n}\n.am-margin-horizontal-xs {\n  margin-left: 0.5rem;\n  margin-right: 0.5rem;\n}\n.am-margin-horizontal-sm {\n  margin-left: 1rem;\n  margin-right: 1rem;\n}\n.am-margin-horizontal-lg {\n  margin-left: 2.4rem;\n  margin-right: 2.4rem;\n}\n.am-margin-horizontal-xl {\n  margin-left: 3.2rem;\n  margin-right: 3.2rem;\n}\n.am-margin-vertical {\n  margin-top: 1.6rem;\n  margin-bottom: 1.6rem;\n}\n.am-margin-vertical-0 {\n  margin-top: 0!important;\n  margin-bottom: 0!important;\n}\n.am-margin-vertical-xs {\n  margin-top: 0.5rem;\n  margin-bottom: 0.5rem;\n}\n.am-margin-vertical-sm {\n  margin-top: 1rem;\n  margin-bottom: 1rem;\n}\n.am-margin-vertical-lg {\n  margin-top: 2.4rem;\n  margin-bottom: 2.4rem;\n}\n.am-margin-vertical-xl {\n  margin-top: 3.2rem;\n  margin-bottom: 3.2rem;\n}\n.am-margin-top {\n  margin-top: 1.6rem;\n}\n.am-margin-top-0 {\n  margin-top: 0!important;\n}\n.am-margin-top-xs {\n  margin-top: 0.5rem;\n}\n.am-margin-top-sm {\n  margin-top: 1rem;\n}\n.am-margin-top-lg {\n  margin-top: 2.4rem;\n}\n.am-margin-top-xl {\n  margin-top: 3.2rem;\n}\n.am-margin-bottom {\n  margin-bottom: 1.6rem;\n}\n.am-margin-bottom-0 {\n  margin-bottom: 0!important;\n}\n.am-margin-bottom-xs {\n  margin-bottom: 0.5rem;\n}\n.am-margin-bottom-sm {\n  margin-bottom: 1rem;\n}\n.am-margin-bottom-lg {\n  margin-bottom: 2.4rem;\n}\n.am-margin-bottom-xl {\n  margin-bottom: 3.2rem;\n}\n.am-margin-left {\n  margin-left: 1.6rem;\n}\n.am-margin-left-0 {\n  margin-left: 0!important;\n}\n.am-margin-left-xs {\n  margin-left: 0.5rem;\n}\n.am-margin-left-sm {\n  margin-left: 1rem;\n}\n.am-margin-left-lg {\n  margin-left: 2.4rem;\n}\n.am-margin-left-xl {\n  margin-left: 3.2rem;\n}\n.am-margin-right {\n  margin-right: 1.6rem;\n}\n.am-margin-right-0 {\n  margin-right: 0!important;\n}\n.am-margin-right-xs {\n  margin-right: 0.5rem;\n}\n.am-margin-right-sm {\n  margin-right: 1rem;\n}\n.am-margin-right-lg {\n  margin-right: 2.4rem;\n}\n.am-margin-right-xl {\n  margin-right: 3.2rem;\n}\n/* Padding helpers */\n.am-padding {\n  padding: 1.6rem;\n}\n.am-padding-0 {\n  padding: 0!important;\n}\n.am-padding-xs {\n  padding: 0.5rem;\n}\n.am-padding-sm {\n  padding: 1rem;\n}\n.am-padding-lg {\n  padding: 2.4rem;\n}\n.am-padding-xl {\n  padding: 3.2rem;\n}\n.am-padding-horizontal {\n  padding-left: 1.6rem;\n  padding-right: 1.6rem;\n}\n.am-padding-horizontal-0 {\n  padding-left: 0!important;\n  padding-right: 0!important;\n}\n.am-padding-horizontal-xs {\n  padding-left: 0.5rem;\n  padding-right: 0.5rem;\n}\n.am-padding-horizontal-sm {\n  padding-left: 1rem;\n  padding-right: 1rem;\n}\n.am-padding-horizontal-lg {\n  padding-left: 2.4rem;\n  padding-right: 2.4rem;\n}\n.am-padding-horizontal-xl {\n  padding-left: 3.2rem;\n  padding-right: 3.2rem;\n}\n.am-padding-vertical {\n  padding-top: 1.6rem;\n  padding-bottom: 1.6rem;\n}\n.am-padding-vertical-0 {\n  padding-top: 0!important;\n  padding-bottom: 0!important;\n}\n.am-padding-vertical-xs {\n  padding-top: 0.5rem;\n  padding-bottom: 0.5rem;\n}\n.am-padding-vertical-sm {\n  padding-top: 1rem;\n  padding-bottom: 1rem;\n}\n.am-padding-vertical-lg {\n  padding-top: 2.4rem;\n  padding-bottom: 2.4rem;\n}\n.am-padding-vertical-xl {\n  padding-top: 3.2rem;\n  padding-bottom: 3.2rem;\n}\n.am-padding-top {\n  padding-top: 1.6rem;\n}\n.am-padding-top-0 {\n  padding-top: 0!important;\n}\n.am-padding-top-xs {\n  padding-top: 0.5rem;\n}\n.am-padding-top-sm {\n  padding-top: 1rem;\n}\n.am-padding-top-lg {\n  padding-top: 2.4rem;\n}\n.am-padding-top-xl {\n  padding-top: 3.2rem;\n}\n.am-padding-bottom {\n  padding-bottom: 1.6rem;\n}\n.am-padding-bottom-0 {\n  padding-bottom: 0!important;\n}\n.am-padding-bottom-xs {\n  padding-bottom: 0.5rem;\n}\n.am-padding-bottom-sm {\n  padding-bottom: 1rem;\n}\n.am-padding-bottom-lg {\n  padding-bottom: 2.4rem;\n}\n.am-padding-bottom-xl {\n  padding-bottom: 3.2rem;\n}\n.am-padding-left {\n  padding-left: 1.6rem;\n}\n.am-padding-left-0 {\n  padding-left: 0!important;\n}\n.am-padding-left-xs {\n  padding-left: 0.5rem;\n}\n.am-padding-left-sm {\n  padding-left: 1rem;\n}\n.am-padding-left-lg {\n  padding-left: 2.4rem;\n}\n.am-padding-left-xl {\n  padding-left: 3.2rem;\n}\n.am-padding-right {\n  padding-right: 1.6rem;\n}\n.am-padding-right-0 {\n  padding-right: 0!important;\n}\n.am-padding-right-xs {\n  padding-right: 0.5rem;\n}\n.am-padding-right-sm {\n  padding-right: 1rem;\n}\n.am-padding-right-lg {\n  padding-right: 2.4rem;\n}\n.am-padding-right-xl {\n  padding-right: 3.2rem;\n}\n/* small displays */\n@media only screen {\n  .am-show-sm-only,\n  .am-show-sm-up,\n  .am-show-sm,\n  .am-show-sm-down,\n  .am-hide-md-only,\n  .am-hide-md-up,\n  .am-hide-md,\n  .am-show-md-down,\n  .am-hide-lg-only,\n  .am-hide-lg-up,\n  .am-hide-lg,\n  .am-show-lg-down {\n    display: inherit !important;\n  }\n  .am-hide-sm-only,\n  .am-hide-sm-up,\n  .am-hide-sm,\n  .am-hide-sm-down,\n  .am-show-md-only,\n  .am-show-md-up,\n  .am-show-md,\n  .am-hide-md-down,\n  .am-show-lg-only,\n  .am-show-lg-up,\n  .am-show-lg,\n  .am-hide-lg-down {\n    display: none !important;\n  }\n  /* table */\n  table.am-show-sm-only,\n  table.am-show-sm-up,\n  table.am-show-sm,\n  table.am-show-sm-down,\n  table.am-hide-md-only,\n  table.am-hide-md-up,\n  table.am-hide-md,\n  table.am-show-md-down,\n  table.am-hide-lg-only,\n  table.am-hide-lg-up,\n  table.am-hide-lg,\n  table.am-show-lg-down {\n    display: table !important;\n  }\n  thead.am-show-sm-only,\n  thead.am-show-sm-up,\n  thead.am-show-sm,\n  thead.am-show-sm-down,\n  thead.am-hide-md-only,\n  thead.am-hide-md-up,\n  thead.am-hide-md,\n  thead.am-show-md-down,\n  thead.am-hide-lg-only,\n  thead.am-hide-lg-up,\n  thead.am-hide-lg,\n  thead.am-show-lg-down {\n    display: table-header-group !important;\n  }\n  tbody.am-show-sm-only,\n  tbody.am-show-sm-up,\n  tbody.am-show-sm,\n  tbody.am-show-sm-down,\n  tbody.am-hide-md-only,\n  tbody.am-hide-md-up,\n  tbody.am-hide-md,\n  tbody.am-show-md-down,\n  tbody.am-hide-lg-only,\n  tbody.am-hide-lg-up,\n  tbody.am-hide-lg,\n  tbody.am-show-lg-down {\n    display: table-row-group !important;\n  }\n  tr.am-show-sm-only,\n  tr.am-show-sm-up,\n  tr.am-show-sm,\n  tr.am-show-sm-down,\n  tr.am-hide-md-only,\n  tr.am-hide-md-up,\n  tr.am-hide-md,\n  tr.am-show-md-down,\n  tr.am-hide-lg-only,\n  tr.am-hide-lg-up,\n  tr.am-hide-lg,\n  tr.am-show-lg-down {\n    display: table-row !important;\n  }\n  th.am-show-sm-only,\n  td.am-show-sm-only,\n  th.am-show-sm-up,\n  td.am-show-sm-up,\n  th.am-show-sm,\n  td.am-show-sm,\n  th.am-show-sm-down,\n  td.am-show-sm-down,\n  th.am-hide-md-only,\n  td.am-hide-md-only,\n  th.am-hide-md-up,\n  td.am-hide-md-up,\n  th.am-hide-md,\n  td.am-hide-md,\n  th.am-show-md-down,\n  td.am-show-md-down,\n  th.am-hide-lg-only,\n  td.am-hide-lg-only,\n  th.am-hide-lg-up,\n  td.am-hide-lg-up,\n  th.am-hide-lg,\n  td.am-hide-lg,\n  th.am-show-lg-down,\n  td.am-show-lg-down {\n    display: table-cell !important;\n  }\n}\n/* medium displays */\n@media only screen and (min-width:641px) {\n  .am-hide-sm-only,\n  .am-show-sm-up,\n  .am-hide-sm,\n  .am-hide-sm-down,\n  .am-show-md-only,\n  .am-show-md-up,\n  .am-show-md,\n  .am-show-md-down,\n  .am-hide-lg-only,\n  .am-hide-lg-up,\n  .am-hide-lg,\n  .am-show-lg-down {\n    display: inherit !important;\n  }\n  .am-show-sm-only,\n  .am-hide-sm-up,\n  .am-show-sm,\n  .am-show-sm-down,\n  .am-hide-md-only,\n  .am-hide-md-up,\n  .am-hide-md,\n  .am-hide-md-down,\n  .am-show-lg-only,\n  .am-show-lg-up,\n  .am-show-lg,\n  .am-hide-lg-down {\n    display: none !important;\n  }\n  table.am-hide-sm-only,\n  table.am-show-sm-up,\n  table.am-hide-sm,\n  table.am-hide-sm-down,\n  table.am-show-md-only,\n  table.am-show-md-up,\n  table.am-show-md,\n  table.am-show-md-down,\n  table.am-hide-lg-only,\n  table.am-hide-lg-up,\n  table.am-hide-lg,\n  table.am-show-lg-down {\n    display: table !important;\n  }\n  thead.am-hide-sm-only,\n  thead.am-show-sm-up,\n  thead.am-hide-sm,\n  thead.am-hide-sm-down,\n  thead.am-show-md-only,\n  thead.am-show-md-up,\n  thead.am-show-md,\n  thead.am-show-md-down,\n  thead.am-hide-lg-only,\n  thead.am-hide-lg-up,\n  thead.am-hide-lg,\n  thead.am-show-lg-down {\n    display: table-header-group !important;\n  }\n  tbody.am-hide-sm-only,\n  tbody.am-show-sm-up,\n  tbody.am-hide-sm,\n  tbody.am-hide-sm-down,\n  tbody.am-show-md-only,\n  tbody.am-show-md-up,\n  tbody.am-show-md,\n  tbody.am-show-md-down,\n  tbody.am-hide-lg-only,\n  tbody.am-hide-lg-up,\n  tbody.am-hide-lg,\n  tbody.am-show-lg-down {\n    display: table-row-group !important;\n  }\n  tr.am-hide-sm-only,\n  tr.am-show-sm-up,\n  tr.am-hide-sm,\n  tr.am-hide-sm-down,\n  tr.am-show-md-only,\n  tr.am-show-md-up,\n  tr.am-show-md,\n  tr.am-show-md-down,\n  tr.am-hide-lg-only,\n  tr.am-hide-lg-up,\n  tr.am-hide-lg,\n  tr.am-show-lg-down {\n    display: table-row !important;\n  }\n  th.am-hide-sm-only,\n  td.am-hide-sm-only,\n  th.am-show-sm-up,\n  td.am-show-sm-up,\n  th.am-hide-sm,\n  td.am-hide-sm,\n  th.am-hide-sm-down,\n  td.am-hide-sm-down,\n  th.am-show-md-only,\n  td.am-show-md-only,\n  th.am-show-md-up,\n  td.am-show-md-up,\n  th.am-show-md,\n  td.am-show-md,\n  th.am-show-md-down,\n  td.am-show-md-down,\n  th.am-hide-lg-only,\n  td.am-hide-lg-only,\n  th.am-hide-lg-up,\n  td.am-hide-lg-up,\n  th.am-hide-lg,\n  td.am-hide-lg,\n  th.am-show-lg-down,\n  td.am-show-lg-down {\n    display: table-cell !important;\n  }\n}\n/* large displays */\n@media only screen and (min-width:1025px) {\n  .am-hide-sm-only,\n  .am-show-sm-up,\n  .am-hide-sm,\n  .am-hide-sm-down,\n  .am-hide-md-only,\n  .am-show-md-up,\n  .am-hide-md,\n  .am-hide-md-down,\n  .am-show-lg-only,\n  .am-show-lg-up,\n  .am-show-lg,\n  .am-show-lg-down {\n    display: inherit !important;\n  }\n  .am-show-sm-only,\n  .am-hide-sm-up,\n  .am-show-sm,\n  .am-show-sm-down,\n  .am-show-md-only,\n  .am-hide-md-up,\n  .am-show-md,\n  .am-show-md-down,\n  .am-hide-lg-only,\n  .am-hide-lg-up,\n  .am-hide-lg,\n  .am-hide-lg-down {\n    display: none !important;\n  }\n  table.am-hide-sm-only,\n  table.am-show-sm-up,\n  table.am-hide-sm,\n  table.am-hide-sm-down,\n  table.am-hide-md-only,\n  table.am-show-md-up,\n  table.am-hide-md,\n  table.am-hide-md-down,\n  table.am-show-lg-only,\n  table.am-show-lg-up,\n  table.am-show-lg,\n  table.am-show-lg-down {\n    display: table !important;\n  }\n  thead.am-hide-sm-only,\n  thead.am-show-sm-up,\n  thead.am-hide-sm,\n  thead.am-hide-sm-down,\n  thead.am-hide-md-only,\n  thead.am-show-md-up,\n  thead.am-hide-md,\n  thead.am-hide-md-down,\n  thead.am-show-lg-only,\n  thead.am-show-lg-up,\n  thead.am-show-lg,\n  thead.am-show-lg-down {\n    display: table-header-group !important;\n  }\n  tbody.am-hide-sm-only,\n  tbody.am-show-sm-up,\n  tbody.am-hide-sm,\n  tbody.am-hide-sm-down,\n  tbody.am-hide-md-only,\n  tbody.am-show-md-up,\n  tbody.am-hide-md,\n  tbody.am-hide-md-down,\n  tbody.am-show-lg-only,\n  tbody.am-show-lg-up,\n  tbody.am-show-lg,\n  tbody.am-show-lg-down {\n    display: table-row-group !important;\n  }\n  tr.am-hide-sm-only,\n  tr.am-show-sm-up,\n  tr.am-hide-sm,\n  tr.am-hide-sm-down,\n  tr.am-hide-md-only,\n  tr.am-show-md-up,\n  tr.am-hide-md,\n  tr.am-hide-md-down,\n  tr.am-show-lg-only,\n  tr.am-show-lg-up,\n  tr.am-show-lg,\n  tr.am-show-lg-down {\n    display: table-row !important;\n  }\n  th.am-hide-sm-only,\n  td.am-hide-sm-only,\n  th.am-show-sm-up,\n  td.am-show-sm-up,\n  th.am-hide-sm,\n  td.am-hide-sm,\n  th.am-hide-sm-down,\n  td.am-hide-sm-down,\n  th.am-hide-md-only,\n  td.am-hide-md-only,\n  th.am-show-md-up,\n  td.am-show-md-up,\n  th.am-hide-md,\n  td.am-hide-md,\n  th.am-hide-md-down,\n  td.am-hide-md-down,\n  th.am-show-lg-only,\n  td.am-show-lg-only,\n  th.am-show-lg-up,\n  td.am-show-lg-up,\n  th.am-show-lg,\n  td.am-show-lg,\n  th.am-show-lg-down,\n  td.am-show-lg-down {\n    display: table-cell !important;\n  }\n}\n@media only screen and (orientation: landscape) {\n  .am-show-landscape,\n  .am-hide-portrait {\n    display: inherit !important;\n  }\n  .am-hide-landscape,\n  .am-show-portrait {\n    display: none !important;\n  }\n}\n@media only screen and (orientation: portrait) {\n  .am-show-portrait,\n  .am-hide-landscape {\n    display: inherit !important;\n  }\n  .am-hide-portrait,\n  .am-show-landscape {\n    display: none !important;\n  }\n}\n.am-sans-serif {\n  font-family: \"Segoe UI\", \"Lucida Grande\", Helvetica, Arial, \"Microsoft YaHei\", FreeSans, Arimo, \"Droid Sans\", \"wenquanyi micro hei\", \"Hiragino Sans GB\", \"Hiragino Sans GB W3\", \"FontAwesome\", sans-serif;\n}\n.am-serif {\n  font-family: Georgia, \"Times New Roman\", Times, SimSun, \"FontAwesome\", serif;\n}\n.am-kai {\n  font-family: Georgia, \"Times New Roman\", Times, Kai, \"Kaiti SC\", KaiTi, BiauKai, \"FontAwesome\", serif;\n}\n.am-monospace {\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", \"FontAwesome\", monospace;\n}\n.am-text-primary {\n  color: #0e90d2;\n}\n.am-text-secondary {\n  color: #3bb4f2;\n}\n.am-text-success {\n  color: #5eb95e;\n}\n.am-text-warning {\n  color: #F37B1D;\n}\n.am-text-danger {\n  color: #dd514c;\n}\n.am-link-muted {\n  color: #666;\n}\n.am-link-muted a {\n  color: #666;\n}\n.am-link-muted:hover,\n.am-link-muted a:hover {\n  color: #555;\n}\n.am-text-default {\n  font-size: 1.6rem;\n}\n/*\n.@{ns}text-xxs {\n  font-size: @font-size-xxs;\n}\n*/\n.am-text-xs {\n  font-size: 1.2rem;\n}\n.am-text-sm {\n  font-size: 1.4rem;\n}\n.am-text-lg {\n  font-size: 1.8rem;\n}\n.am-text-xl {\n  font-size: 2.4rem;\n}\n.am-text-xxl {\n  font-size: 3.2rem;\n}\n.am-text-xxxl {\n  font-size: 4.2rem;\n}\n.am-ellipsis,\n.am-text-truncate {\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-text-break {\n  word-wrap: break-word;\n  -webkit-hyphens: auto;\n  -ms-hyphens: auto;\n  -moz-hyphens: auto;\n  hyphens: auto;\n}\n.am-text-nowrap {\n  white-space: nowrap;\n}\n[class*='am-align-'] {\n  margin-bottom: 1rem;\n}\n.am-align-left {\n  margin-right: 1rem;\n  float: left;\n}\n.am-align-right {\n  margin-left: 1rem;\n  float: right;\n}\n/** Only display content to screen readers\n * See: http://a11yproject.com/posts/how-to-hide-content/\n */\n.am-sr-only {\n  position: absolute;\n  width: 1px;\n  height: 1px;\n  margin: -1px;\n  padding: 0;\n  overflow: hidden;\n  clip: rect(0, 0, 0, 0);\n  border: 0;\n}\n/* Text Image Replacement */\n.am-text-ir {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n/* Text align */\n@media only screen {\n  .am-text-left {\n    text-align: left !important;\n  }\n  .am-text-right {\n    text-align: right !important;\n  }\n  .am-text-center {\n    text-align: center !important;\n  }\n  .am-text-justify {\n    text-align: justify !important;\n  }\n}\n@media only screen and (max-width: 640px) {\n  .am-sm-only-text-left {\n    text-align: left !important;\n  }\n  .am-sm-only-text-right {\n    text-align: right !important;\n  }\n  .am-sm-only-text-center {\n    text-align: center !important;\n  }\n  .am-sm-only-text-justify {\n    text-align: justify !important;\n  }\n}\n@media only screen and (min-width:641px) and (max-width:1024px) {\n  .am-md-only-text-left {\n    text-align: left !important;\n  }\n  .am-md-only-text-right {\n    text-align: right !important;\n  }\n  .am-md-only-text-center {\n    text-align: center !important;\n  }\n  .am-md-only-text-justify {\n    text-align: justify !important;\n  }\n}\n@media only screen and (min-width:641px) {\n  .am-md-text-left {\n    text-align: left !important;\n  }\n  .am-md-text-right {\n    text-align: right !important;\n  }\n  .am-md-text-center {\n    text-align: center !important;\n  }\n  .am-md-text-justify {\n    text-align: justify !important;\n  }\n}\n@media only screen and (min-width:1025px) {\n  .am-lg-text-left {\n    text-align: left !important;\n  }\n  .am-lg-text-right {\n    text-align: right !important;\n  }\n  .am-lg-text-center {\n    text-align: center !important;\n  }\n  .am-lg-text-justify {\n    text-align: justify !important;\n  }\n}\n.am-text-top {\n  vertical-align: top !important;\n}\n.am-text-middle {\n  vertical-align: middle !important;\n}\n.am-text-bottom {\n  vertical-align: bottom !important;\n}\n.am-angle {\n  position: absolute;\n}\n.am-angle:before,\n.am-angle:after {\n  position: absolute;\n  display: block;\n  content: \"\";\n  width: 0;\n  height: 0;\n  border: 8px dashed transparent;\n  z-index: 1;\n}\n.am-angle-up {\n  top: 0;\n}\n.am-angle-up:before,\n.am-angle-up:after {\n  border-bottom-style: solid;\n  border-width: 0 8px 8px;\n}\n.am-angle-up:before {\n  border-bottom-color: #ddd;\n  bottom: 0;\n}\n.am-angle-up:after {\n  border-bottom-color: #fff;\n  bottom: -1px;\n}\n.am-angle-down {\n  bottom: -9px;\n}\n.am-angle-down:before,\n.am-angle-down:after {\n  border-top-style: solid;\n  border-width: 8px 8px 0;\n}\n.am-angle-down:before {\n  border-top-color: #ddd;\n  bottom: 0;\n}\n.am-angle-down:after {\n  border-top-color: #fff;\n  bottom: 1px;\n}\n.am-angle-left {\n  left: -9px;\n}\n.am-angle-left:before,\n.am-angle-left:after {\n  border-right-style: solid;\n  border-width: 8px 8px 8px 0;\n}\n.am-angle-left:before {\n  border-right-color: #ddd;\n  left: 0;\n}\n.am-angle-left:after {\n  border-right-color: #fff;\n  left: 1px;\n}\n.am-angle-right {\n  right: 0;\n}\n.am-angle-right:before,\n.am-angle-right:after {\n  border-left-style: solid;\n  border-width: 8px 0 8px 8px;\n}\n.am-angle-right:before {\n  border-left-color: #ddd;\n  left: 0;\n}\n.am-angle-right:after {\n  border-left-color: #fff;\n  left: -1px;\n}\n/* ==========================================================================\n   Component: Alert Plugin\n ============================================================================ */\n.am-alert {\n  margin-bottom: 1em;\n  padding: 0.625em;\n  background: #0e90d2;\n  color: #fff;\n  border: 1px solid #0c7cb5;\n  border-radius: 0;\n}\n.am-alert a {\n  color: #fff;\n}\n.am-alert h1,\n.am-alert h2,\n.am-alert h3,\n.am-alert h4,\n.am-alert h5,\n.am-alert h6 {\n  color: inherit;\n}\n.am-alert .am-close {\n  opacity: .4;\n}\n.am-alert .am-close:hover {\n  opacity: .6;\n}\n/* Add margin if adjacent element */\n* + .am-alert {\n  margin-top: 1em;\n}\n/* Remove margin from the last-child */\n.am-alert > :last-child {\n  margin-bottom: 0;\n}\n/* within am-form-group */\n.am-form-group .am-alert {\n  margin: 5px 0 0;\n  padding: 0.25em 0.625em;\n  font-size: 1.3rem;\n}\n/* Close in alert */\n.am-alert > .am-close:first-child {\n  float: right;\n  height: auto;\n  margin: -3px -5px auto auto;\n}\n/* Remove margin from adjacent element */\n.am-alert > .am-close:first-child + * {\n  margin-top: 0;\n}\n.am-alert-secondary {\n  background-color: #eeeeee;\n  border-color: #dfdfdf;\n  color: #555555;\n}\n.am-alert-success {\n  background-color: #5eb95e;\n  border-color: #4bad4b;\n  color: #fff;\n}\n.am-alert-warning {\n  background-color: #F37B1D;\n  border-color: #e56c0c;\n  color: #fff;\n}\n.am-alert-danger {\n  background-color: #dd514c;\n  border-color: #d83832;\n  color: #fff;\n}\n.am-dropdown {\n  position: relative;\n  display: inline-block;\n}\n.am-dropdown-toggle:focus {\n  outline: 0;\n}\n.am-dropdown-content {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1020;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 15px;\n  margin: 9px 0 0;\n  text-align: left;\n  line-height: 1.6;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  border-radius: 0;\n  -webkit-background-clip: padding-box;\n          background-clip: padding-box;\n  -webkit-animation-duration: .15s;\n          animation-duration: .15s;\n}\n.am-dropdown-content:before,\n.am-dropdown-content:after {\n  position: absolute;\n  display: block;\n  content: \"\";\n  width: 0;\n  height: 0;\n  border: 8px dashed transparent;\n  z-index: 1;\n}\n.am-dropdown-content:before,\n.am-dropdown-content:after {\n  border-bottom-style: solid;\n  border-width: 0 8px 8px;\n}\n.am-dropdown-content:before {\n  border-bottom-color: #ddd;\n  bottom: 0;\n}\n.am-dropdown-content:after {\n  border-bottom-color: #fff;\n  bottom: -1px;\n}\n.am-dropdown-content:before,\n.am-dropdown-content:after {\n  left: 10px;\n  top: -8px;\n  pointer-events: none;\n}\n.am-dropdown-content:after {\n  top: -7px;\n}\n.am-active > .am-dropdown-content {\n  display: block;\n}\n.am-dropdown-content :first-child {\n  margin-top: 0;\n}\n.am-dropdown-up .am-dropdown-content {\n  top: auto;\n  bottom: 100%;\n  margin: 0 0 9px;\n}\n.am-dropdown-up .am-dropdown-content:before,\n.am-dropdown-up .am-dropdown-content:after {\n  border-bottom: none;\n  border-top: 8px solid #ddd;\n  top: auto;\n  bottom: -8px;\n}\n.am-dropdown-up .am-dropdown-content:after {\n  bottom: -7px;\n  border-top-color: #fff;\n}\n.am-dropdown-flip .am-dropdown-content {\n  left: auto;\n  right: 0;\n}\n.am-dropdown-flip .am-dropdown-content:before,\n.am-dropdown-flip .am-dropdown-content:after {\n  left: auto;\n  right: 10px;\n}\nul.am-dropdown-content {\n  list-style: none;\n  padding: 5px 0;\n}\nul.am-dropdown-content.am-fr {\n  right: 0;\n  left: auto;\n}\nul.am-dropdown-content .am-divider {\n  height: 1px;\n  margin: 0rem 0;\n  overflow: hidden;\n  background-color: #e5e5e5;\n}\nul.am-dropdown-content > li > a {\n  display: block;\n  padding: 6px 20px;\n  clear: both;\n  font-weight: normal;\n  color: #333333;\n  white-space: nowrap;\n}\nul.am-dropdown-content > li > a:hover,\nul.am-dropdown-content > li > a:focus {\n  text-decoration: none;\n  color: #262626;\n  background-color: #f5f5f5;\n}\nul.am-dropdown-content > .am-active > a,\nul.am-dropdown-content > .am-active > a:hover,\nul.am-dropdown-content > .am-active > a:focus {\n  color: #fff;\n  text-decoration: none;\n  outline: 0;\n  background-color: #0e90d2;\n}\nul.am-dropdown-content > .am-disabled > a,\nul.am-dropdown-content > .am-disabled > a:hover,\nul.am-dropdown-content > .am-disabled > a:focus {\n  color: #999999;\n}\nul.am-dropdown-content > .am-disabled > a:hover,\nul.am-dropdown-content > .am-disabled > a:focus {\n  text-decoration: none;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n  cursor: not-allowed;\n}\n.am-dropdown-header {\n  display: block;\n  padding: 6px 20px;\n  font-size: 1.2rem;\n  color: #999999;\n}\n.am-fr > .am-dropdown-content {\n  right: 0;\n  left: auto;\n}\n.am-fr > .am-dropdown-content:before {\n  right: 10px;\n  left: auto;\n}\n.am-dropdown-animation {\n  -webkit-animation: am-dropdown-animation 0.15s ease-out;\n          animation: am-dropdown-animation 0.15s ease-out;\n}\n@-webkit-keyframes am-dropdown-animation {\n  0% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n            transform: translateY(0);\n  }\n  100% {\n    opacity: 0;\n    -webkit-transform: translateY(-10px);\n            transform: translateY(-10px);\n  }\n}\n@keyframes am-dropdown-animation {\n  0% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n            transform: translateY(0);\n  }\n  100% {\n    opacity: 0;\n    -webkit-transform: translateY(-10px);\n            transform: translateY(-10px);\n  }\n}\n/* ==========================================================================\n   Component: Flex Slider Plugin\n ============================================================================ */\n.am-slider a:hover,\n.am-slider a:focus {\n  outline: none;\n}\n.am-slides,\n.am-control-nav,\n.am-direction-nav {\n  margin: 0;\n  padding: 0;\n  list-style: none;\n}\n.am-slider {\n  margin: 0;\n  padding: 0;\n}\n.am-slider .am-slides:before,\n.am-slider .am-slides:after {\n  content: \" \";\n  display: table;\n}\n.am-slider .am-slides:after {\n  clear: both;\n}\n.am-slider .am-slides > li {\n  display: none;\n  -webkit-backface-visibility: hidden;\n  position: relative;\n}\n.no-js .am-slider .am-slides > li:first-child {\n  display: block;\n}\n.am-slider .am-slides img {\n  width: 100%;\n  display: block;\n}\n.am-pauseplay span {\n  text-transform: capitalize;\n}\n.am-slider {\n  position: relative;\n}\n.am-viewport {\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.am-slider-carousel li {\n  margin-right: 5px;\n}\n.am-control-nav {\n  position: absolute;\n}\n.am-control-nav li {\n  display: inline-block;\n}\n.am-control-thumbs {\n  position: static;\n  overflow: hidden;\n}\n.am-control-thumbs img {\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.am-slider-slide .am-slides > li {\n  display: none;\n  position: relative;\n}\n@media all and (transform-3d), (-webkit-transform-3d) {\n  .am-slider-slide .am-slides > li {\n    -webkit-transition: -webkit-transform 0.6s ease-in-out;\n    transition: -webkit-transform 0.6s ease-in-out;\n    transition: transform 0.6s ease-in-out;\n    transition: transform 0.6s ease-in-out, -webkit-transform 0.6s ease-in-out;\n    -webkit-backface-visibility: hidden;\n            backface-visibility: hidden;\n    -webkit-perspective: 1000px;\n            perspective: 1000px;\n  }\n  .am-slider-slide .am-slides > li.next,\n  .am-slider-slide .am-slides > li.active.right {\n    -webkit-transform: translate3d(100%, 0, 0);\n            transform: translate3d(100%, 0, 0);\n    left: 0;\n  }\n  .am-slider-slide .am-slides > li.prev,\n  .am-slider-slide .am-slides > li.active.left {\n    -webkit-transform: translate3d(-100%, 0, 0);\n            transform: translate3d(-100%, 0, 0);\n    left: 0;\n  }\n  .am-slider-slide .am-slides > li.next.left,\n  .am-slider-slide .am-slides > li.prev.right,\n  .am-slider-slide .am-slides > li.active {\n    -webkit-transform: translate3d(0, 0, 0);\n            transform: translate3d(0, 0, 0);\n    left: 0;\n  }\n}\n.am-slider-slide .am-slides > .active,\n.am-slider-slide .am-slides > .next,\n.am-slider-slide .am-slides > .prev {\n  display: block;\n}\n.am-slider-slide .am-slides > .active {\n  left: 0;\n}\n.am-slider-slide .am-slides > .next,\n.am-slider-slide .am-slides > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n.am-slider-slide .am-slides > .next {\n  left: 100%;\n}\n.am-slider-slide .am-slides > .prev {\n  left: -100%;\n}\n.am-slider-slide .am-slides > .next.left,\n.am-slider-slide .am-slides > .prev.right {\n  left: 0;\n}\n.am-slider-slide .am-slides > .active.left {\n  left: -100%;\n}\n.am-slider-slide .am-slides > .active.right {\n  left: 100%;\n}\n/**\n  * Slider Theme: Default\n  */\n.am-slider-default {\n  margin: 0 0 20px;\n  background-color: #fff;\n  border-radius: 2px;\n  -webkit-box-shadow: 0 0 2px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 2px rgba(0, 0, 0, 0.15);\n  /* Direction Nav */\n  /* Pause/Play */\n  /* Control Nav */\n}\n.am-slider-default .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-default .am-viewport {\n  max-height: 300px;\n}\n.am-slider-default .carousel li {\n  margin-right: 5px;\n}\n.am-slider-default .am-direction-nav a {\n  position: absolute;\n  top: 50%;\n  z-index: 10;\n  display: block;\n  width: 36px;\n  height: 36px;\n  margin: -18px 0 0;\n  overflow: hidden;\n  opacity: 0.45;\n  cursor: pointer;\n  color: rgba(0, 0, 0, 0.65);\n  -webkit-transition: all .3s ease;\n  transition: all .3s ease;\n}\n.am-slider-default .am-direction-nav a:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  width: 100%;\n  color: #333333;\n  content: \"\\f137\";\n  font-size: 24px!important;\n  text-align: center;\n  line-height: 36px!important;\n  height: 36px;\n}\n.am-slider-default .am-direction-nav a.am-next:before {\n  content: \"\\f138\";\n}\n.am-slider-default .am-direction-nav .am-prev {\n  left: 10px;\n}\n.am-slider-default .am-direction-nav .am-next {\n  right: 10px;\n  text-align: right;\n}\n.am-slider-default .am-direction-nav .am-disabled {\n  opacity: 0!important;\n  cursor: default;\n}\n.am-slider-default:hover .am-prev {\n  opacity: 0.7;\n  left: 10px;\n}\n.am-slider-default:hover .am-prev:hover {\n  opacity: 1;\n}\n.am-slider-default:hover .am-next {\n  opacity: 0.7;\n  right: 10px;\n}\n.am-slider-default:hover .am-next:hover {\n  opacity: 1;\n}\n.am-slider-default .am-pauseplay a {\n  display: block;\n  width: 20px;\n  height: 20px;\n  position: absolute;\n  bottom: 5px;\n  left: 10px;\n  opacity: 0.8;\n  z-index: 10;\n  overflow: hidden;\n  cursor: pointer;\n  color: #000;\n}\n.am-slider-default .am-pauseplay a::before {\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  font-size: 20px;\n  display: inline-block;\n  content: \"\\f04c\";\n}\n.am-slider-default .am-pauseplay a:hover {\n  opacity: 1;\n}\n.am-slider-default .am-pauseplay a.am-play::before {\n  content: \"\\f04b\";\n}\n.am-slider-default .am-slider-desc {\n  background-color: rgba(0, 0, 0, 0.7);\n  position: absolute;\n  bottom: 0;\n  padding: 10px;\n  width: 100%;\n  color: #fff;\n}\n.am-slider-default .am-control-nav {\n  width: 100%;\n  position: absolute;\n  bottom: -15px;\n  text-align: center;\n}\n.am-slider-default .am-control-nav li {\n  margin: 0 6px;\n  display: inline-block;\n}\n.am-slider-default .am-control-nav li a {\n  width: 8px;\n  height: 8px;\n  display: block;\n  background-color: #666;\n  background-color: rgba(0, 0, 0, 0.5);\n  line-height: 0;\n  font-size: 0;\n  cursor: pointer;\n  text-indent: -9999px;\n  border-radius: 20px;\n  -webkit-box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);\n          box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);\n}\n.am-slider-default .am-control-nav li a:hover {\n  background-color: #333;\n  background-color: rgba(0, 0, 0, 0.7);\n}\n.am-slider-default .am-control-nav li a.am-active {\n  background-color: #000;\n  background-color: #0e90d2;\n  cursor: default;\n}\n.am-slider-default .am-control-thumbs {\n  margin: 5px 0 0;\n  position: static;\n  overflow: hidden;\n}\n.am-slider-default .am-control-thumbs li {\n  width: 25%;\n  float: left;\n  margin: 0;\n}\n.am-slider-default .am-control-thumbs img {\n  width: 100%;\n  height: auto;\n  display: block;\n  opacity: .7;\n  cursor: pointer;\n}\n.am-slider-default .am-control-thumbs img:hover {\n  opacity: 1;\n}\n.am-slider-default .am-control-thumbs .am-active {\n  opacity: 1;\n  cursor: default;\n}\n.am-slider-default .am-control-thumbs i {\n  position: absolute;\n}\n/*\nTODO:\n  1. 动画应该放在 dialog 上，不再是整个 modal，涉及 JS 逻辑，需要统筹修改\n  2. modal 滚动条处理，是否需要添加一个滚动条宽度的水平 padding？\n*/\n/* ==========================================================================\n   Component: Modal Plugin\n ============================================================================ */\n.am-modal {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1110;\n  display: none;\n  opacity: 0;\n  outline: 0;\n  text-align: center;\n  -webkit-transform: scale(1.185);\n      -ms-transform: scale(1.185);\n          transform: scale(1.185);\n  -webkit-transition-property: opacity, -webkit-transform;\n  transition-property: opacity, -webkit-transform;\n  transition-property: transform, opacity;\n  transition-property: transform, opacity, -webkit-transform;\n  -webkit-backface-visibility: hidden;\n          backface-visibility: hidden;\n  -webkit-perspective: 1000px;\n          perspective: 1000px;\n}\n.am-modal:focus {\n  outline: 0;\n}\n.am-modal.am-modal-active {\n  opacity: 1;\n  -webkit-transition-duration: 300ms;\n          transition-duration: 300ms;\n  -webkit-transform: scale(1);\n      -ms-transform: scale(1);\n          transform: scale(1);\n  overflow-x: hidden;\n  overflow-y: auto;\n}\n.am-modal.am-modal-out {\n  opacity: 0;\n  z-index: 1109;\n  -webkit-transition-duration: 300ms;\n          transition-duration: 300ms;\n  -webkit-transform: scale(0.815);\n      -ms-transform: scale(0.815);\n          transform: scale(0.815);\n}\n.am-modal:before {\n  content: \"\\200B\";\n  display: inline-block;\n  height: 100%;\n  vertical-align: middle;\n}\n.am-modal-dialog {\n  position: relative;\n  display: inline-block;\n  vertical-align: middle;\n  margin-left: auto;\n  margin-right: auto;\n  width: 270px;\n  max-width: 100%;\n  border-radius: 0;\n  background: #f8f8f8;\n  /*@media @large-up {\n    width: @modal-lg;\n    margin-left: -@modal-lg/2;\n  }*/\n}\n@media only screen and (min-width:641px) {\n  .am-modal-dialog {\n    width: 540px;\n  }\n}\n.am-modal-hd {\n  padding: 15px 10px 5px 10px;\n  font-size: 1.8rem;\n  font-weight: 500;\n}\n.am-modal-hd + .am-modal-bd {\n  padding-top: 0;\n}\n.am-modal-hd .am-close {\n  position: absolute;\n  top: 4px;\n  right: 4px;\n}\n.am-modal-bd {\n  padding: 15px 10px;\n  text-align: center;\n  border-bottom: 1px solid #dedede;\n  border-radius: 2px 2px 0 0;\n}\n.am-modal-bd + .am-modal-bd {\n  margin-top: 5px;\n}\n.am-modal-prompt-input {\n  display: block;\n  margin: 5px auto 0 auto;\n  border-radius: 0;\n  padding: 5px;\n  line-height: 1.8rem;\n  width: 80%;\n  border: 1px solid #dedede;\n  -webkit-appearance: none;\n  -moz-appearance: none;\n  -ms-appearance: none;\n  appearance: none;\n}\n.am-modal-prompt-input:focus {\n  outline: none;\n  border-color: #d6d6d6;\n}\n.am-modal-footer {\n  height: 44px;\n  overflow: hidden;\n  display: table;\n  width: 100%;\n  border-collapse: collapse;\n}\n.am-modal-btn {\n  display: table-cell !important;\n  padding: 0 5px;\n  height: 44px;\n  -webkit-box-sizing: border-box !important;\n          box-sizing: border-box !important;\n  font-size: 1.6rem;\n  line-height: 44px;\n  text-align: center;\n  color: #0e90d2;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n  cursor: pointer;\n  border-right: 1px solid #dedede;\n}\n.am-modal-btn:first-child {\n  border-radius: 0 0 0 0;\n}\n.am-modal-btn:last-child {\n  border-right: none;\n  border-radius: 0 0 0 0;\n}\n.am-modal-btn:first-child:last-child {\n  border-radius: 0 0 0 0;\n}\n.am-modal-btn.am-modal-btn-bold {\n  font-weight: 500;\n}\n.am-modal-btn:active {\n  background: #d4d4d4;\n}\n.am-modal-btn + .am-modal-btn {\n  border-left: 1px solid #dedede;\n}\n.am-modal-no-btn .am-modal-dialog {\n  border-radius: 0;\n  border-bottom: none;\n}\n.am-modal-no-btn .am-modal-bd {\n  border-bottom: none;\n}\n.am-modal-no-btn .am-modal-footer {\n  display: none;\n}\n.am-modal-loading .am-modal-bd {\n  border-bottom: none;\n}\n.am-modal-loading .am-icon-spin {\n  display: inline-block;\n  font-size: 2.4rem;\n}\n.am-modal-loading .am-modal-footer {\n  display: none;\n}\n.am-modal-actions {\n  position: fixed;\n  left: 0;\n  bottom: 0;\n  z-index: 1110;\n  width: 100%;\n  max-height: 100%;\n  overflow-x: hidden;\n  overflow-y: auto;\n  text-align: center;\n  border-radius: 0;\n  -webkit-transform: translateY(100%);\n      -ms-transform: translateY(100%);\n          transform: translateY(100%);\n  -webkit-transition: -webkit-transform 300ms;\n  transition: -webkit-transform 300ms;\n  transition: transform 300ms;\n  transition: transform 300ms, -webkit-transform 300ms;\n}\n.am-modal-actions.am-modal-active {\n  -webkit-transform: translateY(0);\n      -ms-transform: translateY(0);\n          transform: translateY(0);\n}\n.am-modal-actions.am-modal-out {\n  z-index: 1109;\n  -webkit-transform: translateY(100%);\n      -ms-transform: translateY(100%);\n          transform: translateY(100%);\n}\n.am-modal-actions-group {\n  margin: 10px;\n}\n.am-modal-actions-group .am-list {\n  margin: 0;\n  border-radius: 0;\n}\n.am-modal-actions-group .am-list > li {\n  margin-bottom: 0;\n  border-bottom: none;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n  -webkit-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.015);\n          box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.015);\n}\n.am-modal-actions-group .am-list > li > a {\n  padding: 1rem;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-modal-actions-group .am-list > li:first-child {\n  border-top: none;\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n.am-modal-actions-group .am-list > li:last-child {\n  border-bottom: none;\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n.am-modal-actions-header {\n  padding: 1rem;\n  color: #999999;\n  font-size: 1.4rem;\n}\n.am-modal-actions-danger {\n  color: #dd514c;\n}\n.am-modal-actions-danger a {\n  color: inherit;\n}\n.am-popup {\n  position: fixed;\n  left: 0;\n  top: 0;\n  width: 100%;\n  height: 100%;\n  z-index: 1110;\n  background: #fff;\n  display: none;\n  overflow: hidden;\n  -webkit-transition-property: -webkit-transform;\n  transition-property: -webkit-transform;\n  transition-property: transform;\n  transition-property: transform, -webkit-transform;\n  -webkit-transform: translateY(100%);\n      -ms-transform: translateY(100%);\n          transform: translateY(100%);\n}\n.am-popup.am-modal-active,\n.am-popup.am-modal-out {\n  -webkit-transition-duration: 300ms;\n          transition-duration: 300ms;\n}\n.am-popup.am-modal-active {\n  -webkit-transform: translateY(0);\n      -ms-transform: translateY(0);\n          transform: translateY(0);\n}\n.am-popup.am-modal-out {\n  -webkit-transform: translateY(100%);\n      -ms-transform: translateY(100%);\n          transform: translateY(100%);\n}\n@media all and (min-width: 630px) and (min-height: 630px) {\n  .am-popup {\n    width: 630px;\n    height: 630px;\n    left: 50%;\n    top: 50%;\n    margin-left: -315px;\n    margin-top: -315px;\n    -webkit-transform: translateY(1024px);\n        -ms-transform: translateY(1024px);\n            transform: translateY(1024px);\n  }\n  .am-popup.am-modal-active {\n    -webkit-transform: translateY(0);\n        -ms-transform: translateY(0);\n            transform: translateY(0);\n  }\n  .am-popup.am-modal-out {\n    -webkit-transform: translateY(1024px);\n        -ms-transform: translateY(1024px);\n            transform: translateY(1024px);\n  }\n}\n.am-popup-inner {\n  padding-top: 44px;\n  height: 100%;\n  overflow: auto;\n  -webkit-overflow-scrolling: touch;\n}\n.am-popup-hd {\n  position: absolute;\n  top: 0;\n  z-index: 1000;\n  width: 100%;\n  height: 43px;\n  border-bottom: 1px solid #dedede;\n  background-color: #fff;\n}\n.am-popup-hd .am-popup-title {\n  font-size: 1.8rem;\n  font-weight: bold;\n  line-height: 43px;\n  text-align: center;\n  margin: 0 30px;\n  color: #333333;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-popup-hd .am-close {\n  position: absolute;\n  right: 10px;\n  top: 8px;\n  cursor: pointer;\n  -webkit-transition: all 0.3s;\n  transition: all 0.3s;\n  color: #999999;\n}\n.am-popup-hd .am-close:hover {\n  -webkit-transform: rotate(360deg);\n      -ms-transform: rotate(360deg);\n          transform: rotate(360deg);\n  color: #555555;\n}\n.am-popup-bd {\n  padding: 15px;\n  background: #f8f8f8;\n  color: #555555;\n}\n/* ==========================================================================\n   Component: OffCanvas Plugin\n ============================================================================ */\n/* Off-canvas overlay and bar container */\n.am-offcanvas {\n  display: none;\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1090;\n  background: rgba(0, 0, 0, 0.15);\n}\n.am-offcanvas.am-active {\n  display: block;\n}\n/**\n * .@{ns}offcanvas-page\n *\n * Prepares the whole HTML page to slide-out\n * 1. Fix the main page and disallow scrolling\n * 2. Side-out transition\n */\n.am-offcanvas-page {\n  position: fixed;\n  /* 1 */\n  -webkit-transition: margin-left 0.3s ease-in-out;\n  transition: margin-left 0.3s ease-in-out;\n  /* 2 */\n}\n/* Sub-object .@{ns}offcanvas-bar */\n.am-offcanvas-bar {\n  position: fixed;\n  top: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1091;\n  width: 270px;\n  max-width: 100%;\n  background: #333;\n  overflow-y: auto;\n  /* scrollable */\n  -webkit-overflow-scrolling: touch;\n  /* scrollable */\n  -webkit-transition: -webkit-transform 0.3s ease-in-out;\n  transition: -webkit-transform 0.3s ease-in-out;\n  transition: transform 0.3s ease-in-out;\n  transition: transform 0.3s ease-in-out, -webkit-transform 0.3s ease-in-out;\n  -webkit-transform: translateX(-100%);\n      -ms-transform: translateX(-100%);\n          transform: translateX(-100%);\n}\n.am-offcanvas-bar:after {\n  content: \"\";\n  display: block;\n  position: absolute;\n  top: 0;\n  bottom: 0;\n  right: 0;\n  width: 1px;\n  background: #262626;\n}\n.am-offcanvas.am-active .am-offcanvas-bar.am-offcanvas-bar-active {\n  -webkit-transform: translateX(0);\n      -ms-transform: translateX(0);\n          transform: translateX(0);\n}\n/* .@{ns}offcanvas-bar-flip */\n.am-offcanvas-bar-flip {\n  left: auto;\n  right: 0;\n  -webkit-transform: translateX(100%);\n      -ms-transform: translateX(100%);\n          transform: translateX(100%);\n}\n.am-offcanvas-bar-flip:after {\n  right: auto;\n  left: 0;\n}\n.am-offcanvas-content {\n  padding: 15px;\n  color: #999;\n}\n.am-offcanvas-content a {\n  color: #ccc;\n}\n/* ==========================================================================\n   Component: Popover Plugin\n ============================================================================ */\n.am-popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  margin: 0;\n  border-radius: 0;\n  background: #333333;\n  color: #fff;\n  border: 1px solid #333333;\n  display: none;\n  font-size: 1.6rem;\n  z-index: 1030;\n  opacity: 0;\n  -webkit-transition: opacity 300ms;\n  transition: opacity 300ms;\n}\n.am-popover.am-active {\n  display: block !important;\n  opacity: 1;\n}\n.am-popover-inner {\n  position: relative;\n  background: #333333;\n  padding: 8px;\n  z-index: 110;\n}\n.am-popover-caret {\n  position: absolute;\n  top: 0;\n  z-index: 100;\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: middle;\n  border-bottom: 8px solid #333333;\n  border-right: 8px solid transparent;\n  border-left: 8px solid transparent;\n  border-top: 0 dotted;\n  -webkit-transform: rotate(360deg);\n      -ms-transform: rotate(360deg);\n          transform: rotate(360deg);\n  overflow: hidden;\n}\n.am-popover-top .am-popover-caret {\n  top: auto;\n  bottom: -8px;\n  -webkit-transform: rotate(180deg);\n      -ms-transform: rotate(180deg);\n          transform: rotate(180deg);\n}\n.am-popover-bottom .am-popover-caret {\n  top: -8px;\n}\n.am-popover-top .am-popover-caret,\n.am-popover-bottom .am-popover-caret {\n  left: 50%;\n  margin-left: -8px;\n}\n.am-popover-left .am-popover-caret {\n  top: auto;\n  left: auto;\n  right: -12px;\n  -webkit-transform: rotate(90deg);\n      -ms-transform: rotate(90deg);\n          transform: rotate(90deg);\n}\n.am-popover-right .am-popover-caret {\n  right: auto;\n  left: -12px;\n  -webkit-transform: rotate(-90deg);\n      -ms-transform: rotate(-90deg);\n          transform: rotate(-90deg);\n}\n.am-popover-left .am-popover-caret,\n.am-popover-right .am-popover-caret {\n  top: 50%;\n  margin-top: -4px;\n}\n.am-popover-sm {\n  font-size: 1.4rem;\n}\n.am-popover-sm .am-popover-inner {\n  padding: 5px;\n}\n.am-popover-lg {\n  font-size: 1.8rem;\n}\n.am-popover-primary {\n  border-color: #0e90d2;\n}\n.am-popover-primary .am-popover-inner {\n  background: #0e90d2;\n}\n.am-popover-primary .am-popover-caret {\n  border-bottom-color: #0e90d2;\n}\n.am-popover-secondary {\n  border-color: #3bb4f2;\n}\n.am-popover-secondary .am-popover-inner {\n  background: #3bb4f2;\n}\n.am-popover-secondary .am-popover-caret {\n  border-bottom-color: #3bb4f2;\n}\n.am-popover-success {\n  border-color: #5eb95e;\n}\n.am-popover-success .am-popover-inner {\n  background: #5eb95e;\n}\n.am-popover-success .am-popover-caret {\n  border-bottom-color: #5eb95e;\n}\n.am-popover-warning {\n  border-color: #F37B1D;\n}\n.am-popover-warning .am-popover-inner {\n  background: #F37B1D;\n}\n.am-popover-warning .am-popover-caret {\n  border-bottom-color: #F37B1D;\n}\n.am-popover-danger {\n  border-color: #dd514c;\n}\n.am-popover-danger .am-popover-inner {\n  background: #dd514c;\n}\n.am-popover-danger .am-popover-caret {\n  border-bottom-color: #dd514c;\n}\n/* ==========================================================================\n   Component: Progress Plugin\n ============================================================================ */\n#nprogress {\n  /* Make clicks pass-through */\n  pointer-events: none;\n  /* Fancy blur effect */\n}\n#nprogress .nprogress-bar {\n  position: fixed;\n  top: 0;\n  left: 0;\n  z-index: 2000;\n  width: 100%;\n  height: 2px;\n  background: #5eb95e;\n}\n#nprogress .nprogress-peg {\n  display: block;\n  position: absolute;\n  right: 0;\n  width: 100px;\n  height: 100%;\n  -webkit-box-shadow: 0 0 10px #5eb95e, 0 0 5px #5eb95e;\n          box-shadow: 0 0 10px #5eb95e, 0 0 5px #5eb95e;\n  opacity: 1;\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#nprogress .nprogress-spinner {\n  position: fixed;\n  top: 15px;\n  right: 15px;\n  z-index: 2000;\n  display: block;\n}\n#nprogress .nprogress-spinner-icon {\n  width: 18px;\n  height: 18px;\n  -webkit-box-sizing: border-box;\n          box-sizing: border-box;\n  border: solid 2px transparent;\n  border-top-color: #5eb95e;\n  border-left-color: #5eb95e;\n  border-radius: 50%;\n  -webkit-animation: nprogress-spinner 400ms linear infinite;\n          animation: nprogress-spinner 400ms linear infinite;\n}\n@-webkit-keyframes nprogress-spinner {\n  0% {\n    -webkit-transform: rotate(0deg);\n            transform: rotate(0deg);\n  }\n  100% {\n    -webkit-transform: rotate(360deg);\n            transform: rotate(360deg);\n  }\n}\n@keyframes nprogress-spinner {\n  0% {\n    -webkit-transform: rotate(0deg);\n            transform: rotate(0deg);\n  }\n  100% {\n    -webkit-transform: rotate(360deg);\n            transform: rotate(360deg);\n  }\n}\n/* ==========================================================================\n   Component: Tabs Plugin\n ============================================================================ */\n.am-tabs-bd {\n  position: relative;\n  overflow: hidden;\n  border: 1px solid #ddd;\n  border-top: none;\n  z-index: 100;\n  -webkit-transition: height .3s;\n  transition: height .3s;\n}\n.am-tabs-bd:before,\n.am-tabs-bd:after {\n  content: \" \";\n  display: table;\n}\n.am-tabs-bd:after {\n  clear: both;\n}\n.am-tabs-bd .am-tab-panel {\n  position: absolute;\n  top: 0;\n  z-index: 99;\n  float: left;\n  width: 100%;\n  padding: 10px 10px 15px;\n  visibility: hidden;\n  -webkit-transition: -webkit-transform 0.3s;\n  transition: -webkit-transform 0.3s;\n  transition: transform 0.3s;\n  transition: transform 0.3s, -webkit-transform 0.3s;\n  -webkit-transform: translateX(-100%);\n      -ms-transform: translateX(-100%);\n          transform: translateX(-100%);\n}\n.am-tabs-bd .am-tab-panel * {\n  -webkit-user-drag: none;\n}\n.am-tabs-bd .am-tab-panel.am-active {\n  position: relative;\n  z-index: 100;\n  visibility: visible;\n  -webkit-transform: translateX(0);\n      -ms-transform: translateX(0);\n          transform: translateX(0);\n}\n.am-tabs-bd .am-tab-panel.am-active ~ .am-tab-panel {\n  -webkit-transform: translateX(100%);\n      -ms-transform: translateX(100%);\n          transform: translateX(100%);\n}\n.am-tabs-bd .am-tabs-bd {\n  border: none;\n}\n.am-tabs-bd-ofv {\n  overflow: visible;\n}\n.am-tabs-fade .am-tab-panel {\n  opacity: 0;\n  -webkit-transition: opacity .25s linear;\n  transition: opacity .25s linear;\n}\n.am-tabs-fade .am-tab-panel.am-in {\n  opacity: 1;\n}\n/* ==========================================================================\n   Component: Share Plugin\n ============================================================================ */\n.am-share {\n  font-size: 14px;\n}\n.am-share-title {\n  padding: 10px 0 0;\n  margin: 0 10px;\n  font-weight: normal;\n  text-align: center;\n  color: #555555;\n  background-color: #f8f8f8;\n  border-bottom: 1px solid #fff;\n  border-top-right-radius: 2px;\n  border-top-left-radius: 2px;\n}\n.am-share-title:after {\n  content: \"\";\n  display: block;\n  width: 100%;\n  height: 0;\n  margin-top: 10px;\n  border-bottom: 1px solid #dfdfdf;\n}\n.am-share-sns {\n  margin: 0 10px;\n  padding-top: 15px;\n  background-color: #f8f8f8;\n  border-bottom-right-radius: 2px;\n  border-bottom-left-radius: 2px;\n}\n.am-share-sns li {\n  margin-bottom: 15px;\n}\n.am-share-sns a {\n  display: block;\n  color: #555555;\n}\n.am-share-sns span {\n  display: block;\n}\n.am-share-sns [class*='am-icon'] {\n  background-color: #3bb4f2;\n  border-radius: 50%;\n  width: 36px;\n  height: 36px;\n  line-height: 36px;\n  color: #fff;\n  margin-bottom: 5px;\n  font-size: 18px;\n}\n.am-share-sns .am-icon-weibo {\n  background-color: #ea1328;\n}\n.am-share-sns .am-icon-qq {\n  background-color: #009cda;\n}\n.am-share-sns .am-icon-star {\n  background-color: #ffc028;\n}\n.am-share-sns .am-icon-tencent-weibo {\n  background-color: #23ccfe;\n}\n.am-share-sns .am-icon-wechat,\n.am-share-sns .am-icon-weixin {\n  background-color: #44b549;\n}\n.am-share-sns .am-icon-renren {\n  background-color: #105ba3;\n}\n.am-share-sns .am-icon-comment {\n  background-color: #5eb95e;\n}\n.am-share-footer {\n  margin: 10px;\n}\n.am-share-footer .am-btn {\n  color: #555555;\n}\n.am-share-wechat-qr {\n  font-size: 14px;\n  color: #777;\n}\n.am-share-wechat-qr .am-modal-dialog {\n  background-color: #fff;\n  border: 1px solid #dedede;\n}\n.am-share-wechat-qr .am-modal-hd {\n  padding-top: 10px;\n  text-align: left;\n  margin-bottom: 10px;\n}\n.am-share-wechat-qr .am-share-wx-qr {\n  margin-bottom: 10px;\n}\n.am-share-wechat-qr .am-share-wechat-tip {\n  text-align: left;\n}\n.am-share-wechat-qr .am-share-wechat-tip em {\n  color: #dd514c;\n  font-weight: bold;\n  font-style: normal;\n  margin-left: 3px;\n  margin-right: 3px;\n}\n/* ==========================================================================\n   Component: PureView Plugin\n ============================================================================ */\n.am-pureview {\n  position: fixed;\n  left: 0;\n  top: 0;\n  bottom: 0;\n  right: 0;\n  z-index: 1120;\n  width: 100%;\n  height: 100%;\n  background: rgba(0, 0, 0, 0.95);\n  display: none;\n  overflow: hidden;\n  -webkit-transition: -webkit-transform .3s;\n  transition: -webkit-transform .3s;\n  transition: transform .3s;\n  transition: transform .3s, -webkit-transform .3s;\n  -webkit-transform: translate(0, 100%);\n      -ms-transform: translate(0, 100%);\n          transform: translate(0, 100%);\n}\n.am-pureview.am-active {\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n}\n.am-pureview ul,\n.am-pureview ol {\n  list-style: none;\n  padding: 0;\n  margin: 0;\n  width: 100%;\n}\n.am-pureview-slider {\n  overflow: hidden;\n  height: 100%;\n}\n.am-pureview-slider li {\n  position: absolute;\n  width: 100%;\n  height: 100%;\n  top: 0;\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -ms-flexbox;\n  display: flex;\n  -webkit-box-pack: center;\n  -webkit-justify-content: center;\n      -ms-flex-pack: center;\n          justify-content: center;\n  -webkit-box-align: center;\n  -webkit-align-items: center;\n      -ms-flex-align: center;\n          align-items: center;\n  vertical-align: middle;\n  -webkit-transition: all .3s linear;\n  transition: all .3s linear;\n  z-index: 100;\n  visibility: hidden;\n}\n.am-pureview-slider li.am-pureview-slide-prev {\n  -webkit-transform: translate(-100%, 0);\n      -ms-transform: translate(-100%, 0);\n          transform: translate(-100%, 0);\n  z-index: 109;\n}\n.am-pureview-slider li.am-pureview-slide-next {\n  -webkit-transform: translate(100%, 0);\n      -ms-transform: translate(100%, 0);\n          transform: translate(100%, 0);\n  z-index: 109;\n}\n.am-pureview-slider li.am-active {\n  position: relative;\n  z-index: 110;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  visibility: visible;\n}\n.am-pureview-slider .pinch-zoom-container {\n  width: 100%;\n  z-index: 1121;\n}\n.am-pureview-slider .am-pinch-zoom {\n  position: relative;\n  width: 100%;\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -ms-flexbox;\n  display: flex;\n  -webkit-box-pack: center;\n  -webkit-justify-content: center;\n      -ms-flex-pack: center;\n          justify-content: center;\n  -webkit-box-align: center;\n  -webkit-align-items: center;\n      -ms-flex-align: center;\n          align-items: center;\n}\n.am-pureview-slider .am-pinch-zoom:after {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f110\";\n  -webkit-animation: icon-spin 2s infinite linear;\n          animation: icon-spin 2s infinite linear;\n  font-size: 24px;\n  line-height: 24px;\n  color: #eee;\n  position: absolute;\n  top: 50%;\n  left: 50%;\n  margin-left: -12px;\n  margin-top: -12px;\n  z-index: 1;\n}\n.am-pureview-slider .am-pinch-zoom.am-pureview-loaded:after {\n  display: none;\n}\n.am-pureview-slider img {\n  position: relative;\n  display: block;\n  max-width: 100%;\n  max-height: 100%;\n  opacity: 0;\n  z-index: 200;\n  -webkit-user-drag: none;\n  -webkit-transition: opacity 0.2s ease-in;\n  transition: opacity 0.2s ease-in;\n}\n.am-pureview-slider img.am-img-loaded {\n  opacity: 1;\n}\n.am-pureview-direction {\n  position: absolute;\n  top: 50%;\n  width: 100%;\n  margin-top: -18px !important;\n  z-index: 1122;\n}\n.am-touch .am-pureview-direction,\n.am-pureview-only .am-pureview-direction {\n  display: none;\n}\n.am-pureview-direction li {\n  position: absolute;\n  width: 36px;\n  height: 36px;\n}\n.am-pureview-direction a {\n  display: block;\n  height: 36px;\n  border: none;\n  color: #ccc;\n  opacity: 0.5;\n  cursor: pointer;\n  text-align: center;\n  z-index: 1125;\n}\n.am-pureview-direction a:before {\n  content: \"\\f137\";\n  line-height: 36px;\n  font-size: 24px;\n}\n.am-pureview-direction a:hover {\n  opacity: 1;\n}\n.am-pureview-direction .am-pureview-prev {\n  left: 15px;\n}\n.am-pureview-direction .am-pureview-next {\n  right: 15px;\n}\n.am-pureview-direction .am-pureview-next a:before {\n  content: \"\\f138\";\n}\n.am-pureview-bar {\n  position: absolute;\n  bottom: 0;\n  height: 45px;\n  width: 100%;\n  background-color: rgba(0, 0, 0, 0.35);\n  color: #eeeeee;\n  line-height: 45px;\n  padding: 0 10px;\n  font-size: 14px;\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -ms-flexbox;\n  display: flex;\n}\n.am-pureview-bar .am-pureview-title {\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n  margin-left: 6px;\n  -webkit-box-flex: 1;\n  -webkit-flex: 1;\n      -ms-flex: 1;\n          flex: 1;\n}\n.am-pureview-bar .am-pureview-total {\n  font-size: 10px;\n  line-height: 48px;\n}\n.am-pureview-actions {\n  position: absolute;\n  z-index: 1130;\n  left: 0;\n  right: 0;\n  top: 0;\n  height: 45px;\n  background-color: rgba(0, 0, 0, 0.35);\n}\n.am-pureview-actions a {\n  position: absolute;\n  left: 10px;\n  color: #ccc;\n  display: block;\n  width: 45px;\n  line-height: 45px;\n  text-align: left;\n  font-size: 16px;\n}\n.am-pureview-actions a:hover {\n  color: #fff;\n}\n.am-pureview-actions [data-am-toggle=\"share\"] {\n  left: auto;\n  right: 10px;\n}\n.am-pureview-bar,\n.am-pureview-actions {\n  opacity: 0;\n  -webkit-transition: all .15s;\n  transition: all .15s;\n  z-index: 1130;\n}\n.am-pureview-bar-active .am-pureview-bar,\n.am-pureview-bar-active .am-pureview-actions {\n  opacity: 1;\n}\n.am-pureview-nav {\n  position: absolute;\n  bottom: 15px;\n  left: 0;\n  right: 0;\n  text-align: center;\n  z-index: 1131;\n}\n.am-pureview-bar-active .am-pureview-nav {\n  display: none;\n}\n.am-pureview-nav li {\n  display: inline-block;\n  background: #ccc;\n  background: rgba(255, 255, 255, 0.5);\n  width: 8px;\n  height: 8px;\n  margin: 0 3px;\n  border-radius: 50%;\n  text-indent: -9999px;\n  overflow: hidden;\n  cursor: pointer;\n}\n.am-pureview-nav .am-active {\n  background: #fff;\n  background: rgba(255, 255, 255, 0.9);\n}\n[data-am-pureview] img {\n  cursor: pointer;\n}\n.am-pureview-active {\n  overflow: hidden;\n}\n.ath-viewport * {\n  -webkit-box-sizing: border-box;\n          box-sizing: border-box;\n}\n.ath-viewport {\n  position: relative;\n  z-index: 2147483641;\n  pointer-events: none;\n  -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          user-select: none;\n  -webkit-text-size-adjust: none;\n      -ms-text-size-adjust: none;\n          text-size-adjust: none;\n}\n.ath-modal {\n  pointer-events: auto !important;\n  background: rgba(0, 0, 0, 0.6);\n}\n.ath-mandatory {\n  background: #000;\n}\n.ath-container {\n  pointer-events: auto !important;\n  position: absolute;\n  z-index: 2147483641;\n  padding: 0.7em 0.6em;\n  width: 18em;\n  background: #eee;\n  -webkit-background-size: 100% auto;\n          background-size: 100% auto;\n  -webkit-box-shadow: 0 0.2em 0 #d1d1d1;\n          box-shadow: 0 0.2em 0 #d1d1d1;\n  font-family: sans-serif;\n  font-size: 15px;\n  line-height: 1.5em;\n  text-align: center;\n}\n.ath-container small {\n  font-size: 0.8em;\n  line-height: 1.3em;\n  display: block;\n  margin-top: 0.5em;\n}\n.ath-ios.ath-phone {\n  bottom: 1.8em;\n  left: 50%;\n  margin-left: -9em;\n}\n.ath-ios6.ath-tablet {\n  left: 5em;\n  top: 1.8em;\n}\n.ath-ios7.ath-tablet {\n  left: 0.7em;\n  top: 1.8em;\n}\n.ath-ios8.ath-tablet {\n  right: 0.4em;\n  top: 1.8em;\n}\n.ath-android {\n  bottom: 1.8em;\n  left: 50%;\n  margin-left: -9em;\n}\n/* close icon */\n.ath-container:before {\n  content: '';\n  position: relative;\n  display: block;\n  float: right;\n  margin: -0.7em -0.6em 0 0.5em;\n  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIQAAACECAMAAABmmnOVAAAAdVBMVEUAAAA5OTkzMzM7Ozs3NzdBQUFAQEA/Pz8+Pj5BQUFAQEA/Pz8+Pj5BQUFAQEA/Pz9BQUE+Pj4/Pz8/Pz8+Pj4/Pz8/Pz8/Pz8+Pj4/Pz8+Pj4/Pz8/Pz8/Pz8/Pz8/Pz8+Pj4/Pz8/Pz8/Pz8/Pz9AQEA/Pz+fdCaPAAAAJnRSTlMACQoNDjM4OTo7PEFCQ0RFS6ytsbS1tru8vcTFxu7x8vX19vf4+C5yomAAAAJESURBVHgBvdzLTsJAGEfxr4C2KBcVkQsIDsK8/yPaqIsPzVlyzrKrX/5p0kkXEz81L23otc9NpIbbWia2YVLqdnhlqFlhGWpSDHe1aopsSIpRb8gK0dC3G30b9rVmhWZIimTICsvQtx/FsuYOrWHoDjX3Gu31gzJxdki934WrAIOsAIOsAIOiAMPhPsJTgKGN0BVsYIVsYIVpYIVpYIVpYIVpYIVpYIVpYIVpYIVlAIVgEBRs8BRs8BRs8BRs8BRs8BRs8BRs8BRTNmgKNngKNngKNngKNngKNhiKGxgiOlZoBlaYBlaYBlaYBlaYBlaYBlaYBlaYBlZIBlBMfQMrVAMr2KAqBENSHFHhGEABhi5CV6gGUKgGUKgGUKgGUFwuqgEUvoEVsoEVpoEUpgEUggF+gKTKY+h1fxSlC7/Z+RrxOQ3fcEoAPPHZBlaYBlaYBlaYBlZYBlYIhvLBCstw7PgM7hkiWOEZWGEaWGEaWGEaIsakEAysmHkGVpxmvoEVqoEVpoEVpoEVpoEVpoEVpoEVkoEVgkFQsEFSsEFQsGEcoSvY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnmbNAUT2c2WAo2eAo2eAo2eAo2eAo2eArNEPFACjZ4CjZ4CjZ4CjaIird/rBvFH6llNCvewdli1URWCIakSIZesUaDoFg36dKFWk9zCZDei3TtwmCj7pC22AwikiIZPEU29IpFNliKxa/hC9DFITjQPYhcAAAAAElFTkSuQmCC);\n  background-color: rgba(255, 255, 255, 0.8);\n  -webkit-background-size: 50% 50%;\n          background-size: 50%;\n  background-repeat: no-repeat;\n  background-position: 50%;\n  width: 2.7em;\n  height: 2.7em;\n  text-align: center;\n  overflow: hidden;\n  color: #a33;\n  z-index: 2147483642;\n}\n.ath-container.ath-icon:before {\n  position: absolute;\n  top: 0;\n  right: 0;\n  margin: 0;\n  float: none;\n}\n.ath-mandatory .ath-container:before {\n  display: none;\n}\n.ath-container.ath-android:before {\n  float: left;\n  margin: -0.7em 0.5em 0 -0.6em;\n}\n.ath-container.ath-android.ath-icon:before {\n  position: absolute;\n  right: auto;\n  left: 0;\n  margin: 0;\n  float: none;\n}\n/* applied only if the application icon is shown */\n.ath-action-icon {\n  display: inline-block;\n  vertical-align: middle;\n  background-position: 50%;\n  background-repeat: no-repeat;\n  text-indent: -9999em;\n  overflow: hidden;\n}\n.ath-ios7 .ath-action-icon,\n.ath-ios8 .ath-action-icon {\n  width: 1.6em;\n  height: 1.6em;\n  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHgAAACtCAYAAAB7l7tOAAAF6UlEQVR4AezZWWxUZRiH8VcQEdxZEFFiUZBFUCIa1ABBDARDcCciYGKMqTEGww3SOcNSAwQTjOBiiIpEhRjAhRgXRC8MFxojEhAFZUGttVhaoSxlaW3n8W3yXZxm6vTrOMM5Q98n+V9MMu1pvl++uZhKuypghu49KaaTWGdZSYoVN6VD95nMpLNYZ9XNbdQR2od2k88O3Gm6Bh0t7H0p5Vwp2Ax3ajpu2tYbciFWwkTFO63DY6+JcI4USFaSyYpWp8N7SVZJKR3EinkBk9JxvZFXxhnZSjBaoWp1ZL0ES8WKYXMZp0AndORgy8WKFe5Yf1zvvSBWDEpys2LU6MjD5kmEWQlGKsJRHXlcqUSQVcItEnDEA6gAb7LhjvD9WO6yIEfICQI5A1nzGCYB1T4og5bBiFcyv2f6ujYhl4iVxwKG6qp8MK55HsqPwK0rMr9v/yEo3uCPrJstVh5KMER30Aeh31Ioq0FrHfjXw9CYghnrvYFTuqfEymFzGSwBlT4ARYr7u+K6GLmCVGvAGg2NMG0d/sgJnpScZLjXSkC5z8H3eQ72/k24Q8NfzvwFyK4qtuJSZKaubRPyE/K/Mtx+EvCHL+7uasId1t10w0scz/RzSzYzAfgKV30D3LPaG7lRkR8RK4tKKJKAMp+D7r0EfmmOe0x3m2itAc/ZxBjgAt1mXHWKPPkdb+QGSTJdrDaU5EoJ2OtzwD0WwY7KNNzbRfMFFg24WPdtGHnS221Cflgsj56hjwTs8TnY7oq7/QDhjutGicsb2AVcovsO18l6uPPNNiE/JFaGAq7Q7fY50G4LYVtz3FrdaNGyBXbIl+q24DqhyHes9EaulwR3SwtZs+ktAT/7HORliru1gnCndONFyx44Dfn7MPLYN7yR6yTJZAllJeguAT/4HOBFz8I3ZWm4E0TLFbBD7qn7EVdtHYx53R9ZN0ksrZRuErDN5+AuLIWvm+Oe1k0ULdfADrmX7idcR0/DyBXeyCdlLuMMOGCBz4F1ng+f7yFcve5e0fIFHELeiav6BAx70Rt5p0yhY3u/wR0kyarW/uX35b403PtFyzewQ75ctwtXzSkY8WqruHslSV8RscrL6TJ1bcvfWJ0/HzbtIdw/ugdFyzdwOOAq3T6fmzxwGQ3vbmO8iFioIWqYSsHMj9M/ljfuTsOdItoZBXYBfXX7cVXVwvXLm/8+fU3lcdCqdEMNGBbgUmRmfQISQKd5sGEn4VK6YtEiAXYBA3QVuA4q8hCHrDcafR1ul65jewfuovsCl7vJrNlOuEbdo6JFCuwCrtb9hqusBu56Cw4cI1y1briIWEBn3Ue0XKPuMdGiBg4H9NdV0HJ/6QZLOEPmPN0GmpfSPS5arIBdwHUtIFfoBsl/ZsgfhHCfFi2WwC5goO4AmvanbqBkzJA76tboZokWa2AXMEi3RTdAvDLkDqJFAhzB32xFD2wZsGXA0WfAlgFbBmwZsGXAlgFbBpzk04JaKb0iA9ZnF9x5SQAFtRKKIgPWZxfaeRmwAZ/BGbAB37eaG6MCbnq2Aed5czYyKirgpmcbsAHHZAZswN0Wwo7KeG1fFf2jAm56dtzOQ42yB+65mDhWFBUwUETMUiMDNmADbp/APRaTAh6I2bpGCNw1bufRZJQ1cPdF/NueHZsgDEBBGLbMGoIu4AZu5gLOZeEaYmEXeznF3jRPyEv4frgJvvJe3qTefY0AAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwb8rwADBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgz4/sz1Nia/9hizA7zgklwy3RYwYMBzBRjw4bPjxAbAAizAAtwgwAIswAIswAIMGDBgARZgARZgAS4FWIAFWIAFWIABAwYswAIswAIswIUAC7AAC7AACzBgwIAFWIAFWIAFuBBgARZgARZgAQYMGPApQ99ZCdgWtzqwATbABtgAG2DbnxNb7zbRimsMLMACrDf2wMWI/WasfQAAAABJRU5ErkJggg==);\n  margin-top: -0.3em;\n  -webkit-background-size: auto 100%;\n          background-size: auto 100%;\n}\n.ath-ios6 .ath-action-icon {\n  width: 1.8em;\n  height: 1.8em;\n  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJAAAAB0CAQAAADAmnOnAAAAAnNCSVQICFXsRgQAAAAJcEhZcwAAWwEAAFsBAXkZiFwAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAF4klEQVR4Ae3a/a+XdR3H8ec5HM45HDmKICoVohkZsxESRRCzcZM/2JKkdGR5MrSkleA0Pd00O4u5IVuNM2yYc6XSzCExU4oUNRPCJFdMUAhsYZpUGhscOHA4N8/WZzsL6HBxvofvdV3fa3yer//gsV3vH659KHzncBsJxUYhDzOEhCKQbORs+ip2wzgM+wvj+P9i35qAGLaHGcQSgKSTrxBLABJppZpYApCspoFYApBsZjSxBCD5OxOJJQBJG1cQSwCSLpqJJQCJ3MvgCGTinuSMCJS8LZwfgZL3FtMiUPIOcU0ESl4PLRHoRPsJtREoeRsYGYGS9yrvo6RmpbLaigWSfzOdErLs6+bLUMFA0sF1+QF1cz1UNlBYK9V5AHXyWSgEkKyiIWOgGh829Ki1lLcaxjCVK7mJRSxjBY+zgRf/u9pXcMB7jhEZAg32EUP3O6hMKOP5Iq2sZQeHMZXt5KKMgOpcY+iHVnFyjeQKlrCBdsxge5ieAVC9vzLUelI8H+A7bKIHM10H81IGGuKvDf1ggDxVTKOV1zG3/Yia1ICG+ltD32MgNTKfP2HuW0VDKkCNrjfUTOm9i6XswwrZJkaVHeh0f2fodkrtfO6jAytqrzG+rEDDfVG1x1sprZEs5RBW4PZxeT+Bbrf5hPu9arfzKaU6WjiAFbseWvoF1GW/6vYGSmkyW7Dit4xB5QHq9Br6Xx2t9GAhtp6zkoHsfNp1J9wX6H+jeR4LtJc4LxGopZZyNpN/YcG2mw9nBTSPLizgOmjKAujGgvJID3ekD7QYi7nGzkvmQtpA38Vi7iJf0TedlC7QTVjMfcY2QyvSBPpUMW/PIBfbo9pls1XpAX2EdizeznStob3OJpQO0DB2YfE21q2GtnghpAm0Gou3T9tm6BGHQppA12HRVt17eboNlydNoLHsx2JtmL801OYcQmkC/QKLtQt9ydBW3wNpA30ci7Ur3WdolUMhbaBqNhf/8qQJ9Hkszs5wjaH9XkUobaAqtmFRdoGbDb3sWMgG6DIs5852knO82RaXer+P+qyb3eWeo7ZNBrRZvm1otY2QFdBjeHIb6hTne49Put12+9ObMoDdYmfy5UkF6AK6cCCr9aM2u9IddptcOYCG+FNDB5xLKCugO7G01TndFp/xgAntdYvrfdwVLnORt3q9Vx25F27DUjbGPxr6qxMgW6Cd2N+d6wLXedA+6nKbK73Lr/pJxzusvE/wZrvX0FOOgGyBxmF/dprXutYOj6nNdS6xyYnWp/dGcaGdhr5vDWQN9E1MXrUzfcA2j2qPj/l1J1uT9iPOeh8w1O7nCGUN9HzyGZ7ndo9qp0ucanU2r1xH+wdDu5wIeQDVVx0+/kd1i697RNv8thdn+Qz4Uv9p6DeOhHyApmBfq3OBu+3Nfd7nVELZAX3Nw4ZarYG8gG7GY1dlk6/Zm3/2Rk8jlB1QvT82dNAmQjkBVf8Mj957fdrefM7ZVhPKEuidvmDob06CXIGGbsX/bZDf8KAhfdbJhLIGmuZuQ084HHIGatiLvRvrRkP6qldbBXkAzbfD0N0OhryBGqrEMOd50FC7d1hPKGugBh8ydMh5hPIGGouI1d5lj6F1vptQ9kDvcKOhN5wMlQH0QcRGnzC03yZCeQDN9G1D6xwBFQI07FI8x02GdjgB8gJqttPQcmuhYoAumzvG7YZWejrkA1TrPYYO+SVCFQO0aM4bqj0uJJQH0LluSP7PkyeQU9QOmyAvoBm+Zegpz4LKA/qYB/wE5AXUe3m81zqoRKAPOYWcuvP9dxvqcD6h7IAKkaNU3eUlHLcI9EzS5YlAi62h/zUy89QCqqKUmvgHywsJlEHnsQYxAvXVIJo5gIhnPhiBju1iNmLvLn85Ah1ZPYs5jBGo72awEzEC9dVwHqQHI9DxWoAYgSLQQKteGIESu/qhCJTYtT+PQBEoAkWgCBSBkotAEehUWwSKQBEoAkWg/BeBIlAEikARKAJFoFmealu4gVLy1Gt5dkARKAL9BzujPSurTmu/AAAAAElFTkSuQmCC);\n  margin-bottom: 0.4em;\n  -webkit-background-size: 100% auto;\n          background-size: 100% auto;\n}\n.ath-android .ath-action-icon {\n  width: 1.4em;\n  height: 1.4em;\n  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAMAAABg3Am1AAAANlBMVEVmZmb///9mZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZW6fJrAAAAEXRSTlMAAAYHG21ub8fLz9DR8/T4+RrZ9owAAAB3SURBVHja7dNLDoAgDATQWv4gKve/rEajJOJiWLgg6WzpSyB0aHqHiNj6nL1lovb4C+hYzkSNAT7mryQFAVOeGAj4CjwEtgrWXpD/uZKtwEJApXt+Vn0flzRhgNiFZQkOXY0aADQZCOCPlsZJ46Rx0jhp3IiN2wGDHhxtldrlwQAAAABJRU5ErkJggg==);\n  -webkit-background-size: 100% auto;\n          background-size: 100% auto;\n}\n.ath-container p {\n  margin: 0;\n  padding: 0;\n  position: relative;\n  z-index: 2147483642;\n  text-shadow: 0 0.1em 0 #fff;\n  font-size: 1.1em;\n}\n.ath-ios.ath-phone:after {\n  content: '';\n  background: #eee;\n  position: absolute;\n  width: 2em;\n  height: 2em;\n  bottom: -0.9em;\n  left: 50%;\n  margin-left: -1em;\n  -webkit-transform: scaleX(0.9) rotate(45deg);\n  -ms-transform: scaleX(0.9) rotate(45deg);\n      transform: scaleX(0.9) rotate(45deg);\n  -webkit-box-shadow: 0.2em 0.2em 0 #d1d1d1;\n          box-shadow: 0.2em 0.2em 0 #d1d1d1;\n}\n.ath-ios.ath-tablet:after {\n  content: '';\n  background: #eee;\n  position: absolute;\n  width: 2em;\n  height: 2em;\n  top: -0.9em;\n  left: 50%;\n  margin-left: -1em;\n  -webkit-transform: scaleX(0.9) rotate(45deg);\n  -ms-transform: scaleX(0.9) rotate(45deg);\n      transform: scaleX(0.9) rotate(45deg);\n  z-index: 2147483641;\n}\n.ath-application-icon {\n  position: relative;\n  padding: 0;\n  border: 0;\n  margin: 0 auto 0.2em auto;\n  height: 6em;\n  width: 6em;\n  z-index: 2147483642;\n}\n.ath-container.ath-ios .ath-application-icon {\n  border-radius: 1em;\n  -webkit-box-shadow: 0 0.2em 0.4em rgba(0, 0, 0, 0.3), inset 0 0.07em 0 rgba(255, 255, 255, 0.5);\n          box-shadow: 0 0.2em 0.4em rgba(0, 0, 0, 0.3), inset 0 0.07em 0 rgba(255, 255, 255, 0.5);\n  margin: 0 auto 0.4em auto;\n}\n@media only screen and (orientation: landscape) {\n  .ath-container.ath-phone {\n    width: 24em;\n  }\n  .ath-android.ath-phone {\n    margin-left: -12em;\n  }\n  .ath-ios.ath-phone {\n    margin-left: -12em;\n  }\n  .ath-ios6:after {\n    left: 39%;\n  }\n  .ath-ios8.ath-phone {\n    left: auto;\n    bottom: auto;\n    right: 0.4em;\n    top: 1.8em;\n  }\n  .ath-ios8.ath-phone:after {\n    bottom: auto;\n    top: -0.9em;\n    left: 68%;\n    z-index: 2147483641;\n    -webkit-box-shadow: none;\n            box-shadow: none;\n  }\n}\n/* ==========================================================================\n   Component: uCheck Plugin\n ============================================================================ */\n.am-checkbox,\n.am-radio,\n.am-checkbox-inline,\n.am-radio-inline {\n  padding-left: 22px;\n  position: relative;\n  -webkit-transition: color .25s linear;\n  transition: color .25s linear;\n  font-size: 14px;\n  line-height: 1.5;\n}\nlabel.am-checkbox,\nlabel.am-radio {\n  font-weight: normal;\n}\n.am-ucheck-icons {\n  color: #999999;\n  display: block;\n  height: 20px;\n  top: 0;\n  left: 0;\n  position: absolute;\n  width: 20px;\n  text-align: center;\n  line-height: 21px;\n  font-size: 18px;\n  cursor: pointer;\n}\n.am-checkbox .am-icon-checked,\n.am-radio .am-icon-checked,\n.am-checkbox-inline .am-icon-checked,\n.am-radio-inline .am-icon-checked,\n.am-checkbox .am-icon-unchecked,\n.am-radio .am-icon-unchecked,\n.am-checkbox-inline .am-icon-unchecked,\n.am-radio-inline .am-icon-unchecked {\n  position: absolute;\n  left: 0;\n  top: 0;\n  display: inline-table;\n  margin: 0;\n  background-color: transparent;\n  -webkit-transition: color .25s linear;\n  transition: color .25s linear;\n}\n.am-checkbox .am-icon-checked:before,\n.am-radio .am-icon-checked:before,\n.am-checkbox-inline .am-icon-checked:before,\n.am-radio-inline .am-icon-checked:before,\n.am-checkbox .am-icon-unchecked:before,\n.am-radio .am-icon-unchecked:before,\n.am-checkbox-inline .am-icon-unchecked:before,\n.am-radio-inline .am-icon-unchecked:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n}\n.am-checkbox .am-icon-checked,\n.am-radio .am-icon-checked,\n.am-checkbox-inline .am-icon-checked,\n.am-radio-inline .am-icon-checked {\n  opacity: 0;\n}\n.am-checkbox .am-icon-checked:before,\n.am-checkbox-inline .am-icon-checked:before {\n  content: \"\\f046\";\n}\n.am-checkbox .am-icon-unchecked:before,\n.am-checkbox-inline .am-icon-unchecked:before {\n  content: \"\\f096\";\n}\n.am-radio .am-icon-checked:before,\n.am-radio-inline .am-icon-checked:before {\n  content: \"\\f192\";\n}\n.am-radio .am-icon-unchecked:before,\n.am-radio-inline .am-icon-unchecked:before {\n  content: \"\\f10c\";\n}\n.am-ucheck-checkbox,\n.am-ucheck-radio {\n  position: absolute;\n  left: 0;\n  top: 0;\n  margin: 0;\n  padding: 0;\n  width: 20px;\n  height: 20px;\n  opacity: 0;\n  outline: none !important;\n}\n.am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons {\n  color: #0e90d2;\n}\n.am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-ucheck-radio:checked + .am-ucheck-icons {\n  color: #0e90d2;\n}\n.am-ucheck-checkbox:checked + .am-ucheck-icons .am-icon-unchecked,\n.am-ucheck-radio:checked + .am-ucheck-icons .am-icon-unchecked {\n  opacity: 0;\n}\n.am-ucheck-checkbox:checked + .am-ucheck-icons .am-icon-checked,\n.am-ucheck-radio:checked + .am-ucheck-icons .am-icon-checked {\n  opacity: 1;\n}\n.am-ucheck-checkbox:disabled + .am-ucheck-icons,\n.am-ucheck-radio:disabled + .am-ucheck-icons {\n  cursor: default;\n  color: #d8d8d8;\n}\n.am-ucheck-checkbox:disabled:checked + .am-ucheck-icons .am-icon-unchecked,\n.am-ucheck-radio:disabled:checked + .am-ucheck-icons .am-icon-unchecked {\n  opacity: 0;\n}\n.am-ucheck-checkbox:disabled:checked + .am-ucheck-icons .am-icon-checked,\n.am-ucheck-radio:disabled:checked + .am-ucheck-icons .am-icon-checked {\n  opacity: 1;\n  color: #d8d8d8;\n}\n.am-checkbox.am-secondary .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio.am-secondary .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox-inline.am-secondary .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio-inline.am-secondary .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox.am-secondary .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio.am-secondary .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox-inline.am-secondary .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio-inline.am-secondary .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons {\n  color: #3bb4f2;\n}\n.am-checkbox.am-secondary .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-radio.am-secondary .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-checkbox-inline.am-secondary .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-radio-inline.am-secondary .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-checkbox.am-secondary .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-radio.am-secondary .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-checkbox-inline.am-secondary .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-radio-inline.am-secondary .am-ucheck-radio:checked + .am-ucheck-icons {\n  color: #3bb4f2;\n}\n.am-checkbox.am-success .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio.am-success .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox-inline.am-success .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio-inline.am-success .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox.am-success .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio.am-success .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox-inline.am-success .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio-inline.am-success .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons {\n  color: #5eb95e;\n}\n.am-checkbox.am-success .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-radio.am-success .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-checkbox-inline.am-success .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-radio-inline.am-success .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-checkbox.am-success .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-radio.am-success .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-checkbox-inline.am-success .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-radio-inline.am-success .am-ucheck-radio:checked + .am-ucheck-icons {\n  color: #5eb95e;\n}\n.am-checkbox.am-warning .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio.am-warning .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox-inline.am-warning .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio-inline.am-warning .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox.am-warning .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio.am-warning .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox-inline.am-warning .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio-inline.am-warning .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons {\n  color: #F37B1D;\n}\n.am-checkbox.am-warning .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-radio.am-warning .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-checkbox-inline.am-warning .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-radio-inline.am-warning .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-checkbox.am-warning .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-radio.am-warning .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-checkbox-inline.am-warning .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-radio-inline.am-warning .am-ucheck-radio:checked + .am-ucheck-icons {\n  color: #F37B1D;\n}\n.am-checkbox.am-danger .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio.am-danger .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox-inline.am-danger .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio-inline.am-danger .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox.am-danger .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio.am-danger .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox-inline.am-danger .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio-inline.am-danger .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons {\n  color: #dd514c;\n}\n.am-checkbox.am-danger .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-radio.am-danger .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-checkbox-inline.am-danger .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-radio-inline.am-danger .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-checkbox.am-danger .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-radio.am-danger .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-checkbox-inline.am-danger .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-radio-inline.am-danger .am-ucheck-radio:checked + .am-ucheck-icons {\n  color: #dd514c;\n}\n.am-field-error + .am-ucheck-icons {\n  color: #dd514c;\n}\n.am-field-valid + .am-ucheck-icons {\n  color: #5eb95e;\n}\n/*\n// Group Addon\n.@{ns}input-group-label {\n  .@{ns}radio,\n  .@{ns}checkbox {\n    margin: -2px 0;\n    padding-left: 15px;\n  }\n}\n\n// Form inline style\n.@{ns}form-inline .@{ns}checkbox,\n.@{ns}form-inline .@{ns}radio {\n  padding-left: 24px;\n}\n*/\n/* ==========================================================================\n   Component: Selected Plugin\n ============================================================================ */\n.am-selected {\n  width: 200px;\n}\n.am-selected-btn {\n  width: 100%;\n  padding-left: 10px;\n  text-align: right;\n}\n.am-selected-btn.am-btn-default {\n  background: none;\n}\n.am-invalid .am-selected-btn {\n  border-color: #dd514c;\n}\n.am-selected-header {\n  height: 45px;\n  background-color: #f2f2f2;\n  border-bottom: 1px solid #ddd;\n  display: none;\n}\n.am-selected-status {\n  text-align: left;\n  width: 100%;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-selected-content {\n  padding: 10px 0;\n}\n.am-selected-search {\n  padding: 0 10px 10px;\n}\n.am-selected-search .am-form-field {\n  padding: .5em;\n}\n.am-selected-list {\n  margin: 0;\n  padding: 0;\n  list-style: none;\n  font-size: 1.5rem;\n}\n.am-selected-list li {\n  position: relative;\n  cursor: pointer;\n  padding: 5px 10px;\n  -webkit-transition: background-color 0.15s;\n  transition: background-color 0.15s;\n}\n.am-selected-list li:hover {\n  background-color: #f8f8f8;\n}\n.am-selected-list li:hover .am-icon-check {\n  opacity: .6;\n}\n.am-selected-list li.am-checked .am-icon-check {\n  opacity: 1;\n  color: #0e90d2;\n}\n.am-selected-list li.am-disabled {\n  opacity: .5;\n  pointer-events: none;\n  cursor: not-allowed;\n}\n.am-selected-list .am-selected-list-header {\n  margin-top: 8px;\n  font-size: 1.3rem;\n  color: #999999;\n  border-bottom: 1px solid #e5e5e5;\n  cursor: default;\n}\n.am-selected-list .am-selected-list-header:hover {\n  background: none;\n}\n.am-selected-list .am-selected-list-header:first-child {\n  margin-top: 0;\n}\n.am-selected-list .am-selected-text {\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n  margin-right: 30px;\n}\n.am-selected-list .am-icon-check {\n  position: absolute;\n  right: 8px;\n  top: 5px;\n  color: #999999;\n  opacity: 0;\n  -webkit-transition: opacity .15s;\n  transition: opacity .15s;\n}\n.am-selected-hint {\n  line-height: 1.2;\n  color: #dd514c;\n}\n.am-selected-hint:not(:empty) {\n  margin-top: 10px;\n  border-top: 1px solid #e5e5e5;\n  padding: 10px 10px 0;\n}\n.am-selected-placeholder {\n  opacity: .65;\n}\n/* ==========================================================================\n   Component: JS Plugins helpers\n ============================================================================ */\n.am-fade {\n  opacity: 0;\n  -webkit-transition: opacity .2s linear;\n  transition: opacity .2s linear;\n}\n.am-fade.am-in {\n  opacity: 1;\n}\n.am-collapse {\n  display: none;\n}\n.am-collapse.am-in {\n  display: block;\n}\ntr.am-collapse.am-in {\n  display: table-row;\n}\ntbody.am-collapse.am-in {\n  display: table-row-group;\n}\n.am-collapsing {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height .3s ease;\n  transition: height .3s ease;\n}\n.am-sticky {\n  position: fixed !important;\n  z-index: 1010;\n  -webkit-transform-origin: 0 0;\n      -ms-transform-origin: 0 0;\n          transform-origin: 0 0;\n}\n[data-am-sticky][class*=\"am-animation-\"] {\n  -webkit-animation-duration: .2s;\n          animation-duration: .2s;\n}\n.am-dimmer-active {\n  overflow: hidden;\n}\n.am-dimmer {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  display: none;\n  width: 100%;\n  height: 100%;\n  background-color: rgba(0, 0, 0, 0.6);\n  z-index: 1100;\n  opacity: 0;\n}\n.am-dimmer.am-active {\n  opacity: 1;\n}\n[data-am-collapse] {\n  cursor: pointer;\n}\n.am-datepicker {\n  top: 0;\n  left: 0;\n  border-radius: 0;\n  background: #fff;\n  -webkit-box-shadow: 0 0 10px #ccc;\n          box-shadow: 0 0 10px #ccc;\n  padding-bottom: 10px;\n  margin-top: 10px;\n  width: 238px;\n  color: #555;\n  display: none;\n}\n.am-datepicker > div {\n  display: none;\n}\n.am-datepicker table {\n  width: 100%;\n}\n.am-datepicker tr.am-datepicker-header {\n  font-size: 1.6rem;\n  color: #fff;\n  background: #3bb4f2;\n}\n.am-datepicker td,\n.am-datepicker th {\n  text-align: center;\n  font-weight: normal;\n  cursor: pointer;\n}\n.am-datepicker th {\n  height: 48px;\n}\n.am-datepicker td {\n  font-size: 1.4rem;\n}\n.am-datepicker td.am-datepicker-day {\n  height: 34px;\n  width: 34px;\n}\n.am-datepicker td.am-datepicker-day:hover {\n  background: #F0F0F0;\n  height: 34px;\n  width: 34px;\n}\n.am-datepicker td.am-datepicker-day.am-disabled {\n  cursor: no-drop;\n  color: #999;\n  background: #fafafa;\n}\n.am-datepicker td.am-datepicker-old,\n.am-datepicker td.am-datepicker-new {\n  color: #89d7ff;\n}\n.am-datepicker td.am-active,\n.am-datepicker td.am-active:hover {\n  border-radius: 0;\n  color: #0084c7;\n  background: #F0F0F0;\n}\n.am-datepicker td span {\n  display: block;\n  width: 79.33333333px;\n  height: 40px;\n  line-height: 40px;\n  float: left;\n  cursor: pointer;\n}\n.am-datepicker td span:hover {\n  background: #F0F0F0;\n}\n.am-datepicker td span.am-active {\n  color: #0084c7;\n  background: #F0F0F0;\n}\n.am-datepicker td span.am-disabled {\n  cursor: no-drop;\n  color: #999;\n  background: #fafafa;\n}\n.am-datepicker td span.am-datepicker-old {\n  color: #89d7ff;\n}\n.am-datepicker .am-datepicker-dow {\n  height: 40px;\n  color: #0c80ba;\n}\n.am-datepicker-caret {\n  display: block!important;\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: middle;\n  border-bottom: 7px solid #3bb4f2;\n  border-right: 7px solid transparent;\n  border-left: 7px solid transparent;\n  border-top: 0 dotted;\n  -webkit-transform: rotate(360deg);\n      -ms-transform: rotate(360deg);\n          transform: rotate(360deg);\n  position: absolute;\n  top: -7px;\n  left: 6px;\n}\n.am-datepicker-right .am-datepicker-caret {\n  left: auto;\n  right: 7px;\n}\n.am-datepicker-up .am-datepicker-caret {\n  top: auto;\n  bottom: -7px;\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: middle;\n  border-top: 7px solid #fff;\n  border-right: 7px solid transparent;\n  border-left: 7px solid transparent;\n  border-bottom: 0 dotted;\n  -webkit-transform: rotate(360deg);\n      -ms-transform: rotate(360deg);\n          transform: rotate(360deg);\n}\n.am-datepicker-select {\n  height: 34px;\n  line-height: 34px;\n  text-align: center;\n  -webkit-transition: background-color 300ms ease-out;\n  transition: background-color 300ms ease-out;\n}\n.am-datepicker-select:hover {\n  background: rgba(154, 217, 248, 0.5);\n  color: #0c80ba;\n}\n.am-datepicker-prev,\n.am-datepicker-next {\n  width: 34px;\n  height: 34px;\n}\n.am-datepicker-prev-icon,\n.am-datepicker-next-icon {\n  width: 34px;\n  height: 34px;\n  line-height: 34px;\n  display: inline-block;\n  -webkit-transition: background-color 300ms ease-out;\n  transition: background-color 300ms ease-out;\n}\n.am-datepicker-prev-icon:hover,\n.am-datepicker-next-icon:hover {\n  background: rgba(154, 217, 248, 0.5);\n  color: #0c80ba;\n}\n.am-datepicker-prev-icon:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f053\";\n}\n.am-datepicker-next-icon:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f054\";\n}\n.am-datepicker-dropdown {\n  position: absolute;\n  z-index: 1120;\n}\n@media only screen and (max-width: 640px) {\n  .am-datepicker {\n    width: 100%;\n  }\n  .am-datepicker td span {\n    width: 33.33%;\n  }\n  .am-datepicker-caret {\n    display: none!important;\n  }\n  .am-datepicker-prev,\n  .am-datepicker-next {\n    width: 44px;\n    height: 44px;\n  }\n}\n.am-datepicker-success tr.am-datepicker-header {\n  background: #5eb95e;\n}\n.am-datepicker-success td.am-datepicker-day.am-disabled {\n  color: #999;\n}\n.am-datepicker-success td.am-datepicker-old,\n.am-datepicker-success td.am-datepicker-new {\n  color: #94df94;\n}\n.am-datepicker-success td.am-active,\n.am-datepicker-success td.am-active:hover {\n  color: #1b961b;\n}\n.am-datepicker-success td span.am-datepicker-old {\n  color: #94df94;\n}\n.am-datepicker-success td span.am-active {\n  color: #1b961b;\n}\n.am-datepicker-success .am-datepicker-caret {\n  border-bottom-color: #5eb95e;\n}\n.am-datepicker-success .am-datepicker-dow {\n  color: #367b36;\n}\n.am-datepicker-success .am-datepicker-select:hover,\n.am-datepicker-success .am-datepicker-prev-icon:hover,\n.am-datepicker-success .am-datepicker-next-icon:hover {\n  background: rgba(165, 216, 165, 0.5);\n  color: #367b36;\n}\n.am-datepicker-danger tr.am-datepicker-header {\n  background: #dd514c;\n}\n.am-datepicker-danger td.am-datepicker-day.am-disabled {\n  color: #999;\n}\n.am-datepicker-danger td.am-datepicker-old,\n.am-datepicker-danger td.am-datepicker-new {\n  color: #f59490;\n}\n.am-datepicker-danger td.am-active,\n.am-datepicker-danger td.am-active:hover {\n  color: #c10802;\n}\n.am-datepicker-danger td span.am-datepicker-old {\n  color: #f59490;\n}\n.am-datepicker-danger td span.am-active {\n  color: #c10802;\n}\n.am-datepicker-danger .am-datepicker-caret {\n  border-bottom-color: #dd514c;\n}\n.am-datepicker-danger .am-datepicker-dow {\n  color: #a4241f;\n}\n.am-datepicker-danger .am-datepicker-select:hover,\n.am-datepicker-danger .am-datepicker-prev-icon:hover,\n.am-datepicker-danger .am-datepicker-next-icon:hover {\n  background: rgba(237, 164, 162, 0.5);\n  color: #a4241f;\n}\n.am-datepicker-warning tr.am-datepicker-header {\n  background: #F37B1D;\n}\n.am-datepicker-warning td.am-datepicker-day.am-disabled {\n  color: #999;\n}\n.am-datepicker-warning td.am-datepicker-old,\n.am-datepicker-warning td.am-datepicker-new {\n  color: #ffad6d;\n}\n.am-datepicker-warning td.am-active,\n.am-datepicker-warning td.am-active:hover {\n  color: #aa4b00;\n}\n.am-datepicker-warning td span.am-datepicker-old {\n  color: #ffad6d;\n}\n.am-datepicker-warning td span.am-active {\n  color: #aa4b00;\n}\n.am-datepicker-warning .am-datepicker-caret {\n  border-bottom-color: #F37B1D;\n}\n.am-datepicker-warning .am-datepicker-dow {\n  color: #a14c09;\n}\n.am-datepicker-warning .am-datepicker-select:hover,\n.am-datepicker-warning .am-datepicker-prev-icon:hover,\n.am-datepicker-warning .am-datepicker-next-icon:hover {\n  background: rgba(248, 180, 126, 0.5);\n  color: #a14c09;\n}\n.am-datepicker > div {\n  display: block;\n}\n.am-datepicker > div span.am-datepicker-hour {\n  width: 59.5px;\n}\n.am-datepicker-date {\n  display: block;\n}\n.am-datepicker-date.am-input-group {\n  display: table;\n}\n.am-datepicker-time-box {\n  padding: 30px 0 30px 0;\n}\n.am-datepicker-time-box strong {\n  font-size: 5.2rem;\n  display: inline-block;\n  height: 70px;\n  width: 70px;\n  line-height: 70px;\n  font-weight: normal;\n}\n.am-datepicker-time-box strong:hover {\n  border-radius: 4px;\n  background: #ECECEC;\n}\n.am-datepicker-time-box em {\n  display: inline-block;\n  height: 70px;\n  width: 20px;\n  line-height: 70px;\n  font-size: 5.2rem;\n  font-style: normal;\n}\n.am-datepicker-toggle {\n  text-align: center;\n  cursor: pointer;\n  padding: 10px 0;\n}\n.am-datepicker-toggle:hover {\n  background: #f0f0f0;\n}\n/* ==========================================================================\n   Component: Print\n ============================================================================ */\n@media print {\n  *,\n  *:before,\n  *:after {\n    background: transparent !important;\n    color: #000 !important;\n    /* Black prints faster: h5bp.com/s */\n    -webkit-box-shadow: none !important;\n            box-shadow: none !important;\n    text-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  /**\n   * Don't show links that are fragment identifiers,\n   * or use the `javascript:` pseudo protocol\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    /* h5bp.com/t */\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\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  @page {\n    margin: 0.5cm;\n  }\n  select {\n    background: #fff !important;\n  }\n  .am-topbar {\n    display: none;\n  }\n  .am-table td,\n  .am-table th {\n    background-color: #fff !important;\n  }\n  .am-table {\n    border-collapse: collapse !important;\n  }\n  .am-table-bordered th,\n  .am-table-bordered td {\n    border: 1px solid #ddd !important;\n  }\n}\n/* print helper classes */\n.am-print-block {\n  display: none !important;\n}\n@media print {\n  .am-print-block {\n    display: block !important;\n  }\n}\n.am-print-inline {\n  display: none !important;\n}\n@media print {\n  .am-print-inline {\n    display: inline !important;\n  }\n}\n.am-print-inline-block {\n  display: none !important;\n}\n@media print {\n  .am-print-inline-block {\n    display: inline-block !important;\n  }\n}\n@media print {\n  .am-print-hide {\n    display: none !important;\n  }\n}\n.lte9 #nprogress .nprogress-spinner {\n  display: none !important;\n}\n.lte8 .am-dimmer {\n  background-color: #000;\n  filter: alpha(opacity=60);\n}\n.lte8 .am-modal-actions {\n  display: none;\n}\n.lte8 .am-modal-actions.am-modal-active {\n  display: block;\n}\n.lte8 .am-offcanvas.am-active {\n  background: #000;\n}\n.lte8 .am-popover .am-popover-caret {\n  border: 8px solid transparent;\n}\n.lte8 .am-popover-top .am-popover-caret {\n  border-top: 8px solid #333333;\n  border-bottom: none;\n}\n.lte8 .am-popover-left .am-popover-caret {\n  right: -8px;\n  margin-top: -6px;\n  border-left: 8px solid #333333;\n  border-right: none;\n}\n.lte8 .am-popover-right .am-popover-caret {\n  left: -8px;\n  margin-top: -6px;\n  border-right: 8px solid #333333;\n  border-left: none;\n}\n.am-accordion-item {\n  margin: 0;\n}\n.am-accordion-title {\n  font-weight: normal;\n  cursor: pointer;\n}\n.am-accordion-item.am-disabled .am-accordion-title {\n  cursor: default;\n  pointer-events: none;\n}\n.am-accordion-bd {\n  margin: 0 !important;\n  padding: 0 !important;\n  border: none !important;\n}\n.am-accordion-content {\n  margin-top: 0;\n  padding: 0.8rem 1rem 1.2rem;\n  font-size: 1.4rem;\n}\n/**\n  * Accordion Theme: default\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-accordion-default {\n  margin: 1rem;\n  border-radius: 2px;\n  -webkit-box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);\n}\n.am-accordion-default .am-accordion-item {\n  border-top: 1px solid rgba(0, 0, 0, 0.05);\n}\n.am-accordion-default .am-accordion-item:first-child {\n  border-top: none;\n}\n.am-accordion-default .am-accordion-title {\n  color: rgba(0, 0, 0, 0.6);\n  -webkit-transition: background-color 0.2s ease-out;\n  transition: background-color 0.2s ease-out;\n  padding: .8rem 1rem;\n}\n.am-accordion-default .am-accordion-title:before {\n  content: \"\\f0da\";\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  -webkit-transition: -webkit-transform .2s ease;\n  transition: -webkit-transform .2s ease;\n  transition: transform .2s ease;\n  transition: transform .2s ease, -webkit-transform .2s ease;\n  -webkit-transform: rotate(0deg);\n      -ms-transform: rotate(0deg);\n          transform: rotate(0deg);\n  margin-right: 5px;\n}\n.am-accordion-default .am-accordion-title:hover {\n  color: #0e90d2;\n}\n.am-accordion-default .am-accordion-content {\n  color: #666;\n}\n.am-accordion-default .am-active .am-accordion-title {\n  background-color: #eeeeee;\n  color: #0e90d2;\n}\n.am-accordion-default .am-active .am-accordion-title:before {\n  -webkit-transform: rotate(90deg);\n      -ms-transform: rotate(90deg);\n          transform: rotate(90deg);\n}\n/**\n  * Accordion Theme: basic\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-accordion-basic {\n  margin: 1rem;\n}\n.am-accordion-basic .am-accordion-title {\n  color: #333333;\n  -webkit-transition: background-color 0.2s ease-out;\n  transition: background-color 0.2s ease-out;\n  padding: .8rem 0 0;\n}\n.am-accordion-basic .am-accordion-title:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f0da\";\n  -webkit-transition: -webkit-transform .2s ease;\n  transition: -webkit-transform .2s ease;\n  transition: transform .2s ease;\n  transition: transform .2s ease, -webkit-transform .2s ease;\n  -webkit-transform: rotate(0deg);\n      -ms-transform: rotate(0deg);\n          transform: rotate(0deg);\n  margin-right: .5rem;\n}\n.am-accordion-basic .am-accordion-content {\n  color: #666;\n}\n.am-accordion-basic .am-active .am-accordion-title {\n  color: #0e90d2;\n}\n.am-accordion-basic .am-active .am-accordion-title:before {\n  -webkit-transform: rotate(90deg);\n      -ms-transform: rotate(90deg);\n          transform: rotate(90deg);\n}\n/**\n  * Accordion Theme: gapped\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-accordion-gapped {\n  margin: .5rem 1rem;\n}\n.am-accordion-gapped .am-accordion-item {\n  border: 1px solid #dedede;\n  border-bottom: none;\n  margin: .5rem 0;\n}\n.am-accordion-gapped .am-accordion-item.am-active {\n  border-bottom: 1px solid #dedede;\n}\n.am-accordion-gapped .am-accordion-title {\n  color: rgba(0, 0, 0, 0.6);\n  -webkit-transition: background-color 0.15s ease-out;\n  transition: background-color 0.15s ease-out;\n  border-bottom: 1px solid #dedede;\n  padding: 0.8rem 2rem 0.8rem 1rem;\n  position: relative;\n}\n.am-accordion-gapped .am-accordion-title:after {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f105\";\n  -webkit-transition: -webkit-transform .2s linear;\n  transition: -webkit-transform .2s linear;\n  transition: transform .2s linear;\n  transition: transform .2s linear, -webkit-transform .2s linear;\n  position: absolute;\n  right: 10px;\n  top: 50%;\n  margin-top: -0.8rem;\n}\n.am-accordion-gapped .am-accordion-title:hover {\n  color: rgba(0, 0, 0, 0.8);\n}\n.am-accordion-gapped .am-accordion-content {\n  color: #666;\n}\n.am-accordion-gapped .am-active .am-accordion-title {\n  background-color: #f5f5f5;\n  color: rgba(0, 0, 0, 0.8);\n}\n.am-accordion-gapped .am-active .am-accordion-title:after {\n  -webkit-transform: rotate(90deg);\n      -ms-transform: rotate(90deg);\n          transform: rotate(90deg);\n}\n.am-divider {\n  height: 0;\n  margin: 1.5rem auto;\n  overflow: hidden;\n  clear: both;\n}\n/**\n  * Divider Theme: default\n  */\n.am-divider-default {\n  border-top: 1px solid #ddd;\n}\n/**\n  * Divider Theme: dotted\n  */\n.am-divider-dotted {\n  border-top: 1px dotted #ccc;\n}\n/**\n  * Divider Theme: dashed\n  */\n.am-divider-dashed {\n  border-top: 1px dashed #ccc;\n}\n.am-figure-zoomable {\n  position: relative;\n  cursor: pointer;\n}\n.am-figure-zoomable:after {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f00e\";\n  position: absolute;\n  top: 1rem;\n  right: 1rem;\n  color: #999999;\n  font-size: 1.6rem;\n  -webkit-transition: all 0.2s;\n  transition: all 0.2s;\n  pointer-events: none;\n}\n.am-figure-zoomable:hover:after {\n  color: #eeeeee;\n}\n.am-figure-default {\n  margin: 10px;\n}\n.am-figure-default img {\n  display: block;\n  max-width: 100%;\n  height: auto;\n  padding: 2px;\n  border: 1px solid #eeeeee;\n  margin: 10px auto;\n}\n.am-figure-default figcaption {\n  text-align: center;\n  font-size: 1.4rem;\n  margin-bottom: 15px;\n  color: #333333;\n}\n.am-footer {\n  text-align: center;\n  padding: 1em 0;\n  font-size: 1.6rem;\n}\n.am-footer .am-switch-mode-ysp {\n  cursor: pointer;\n}\n.am-footer .am-footer-text {\n  margin-top: 10px;\n  font-size: 14px;\n}\n.am-footer .am-footer-text-left {\n  text-align: left;\n  padding-left: 10px;\n}\n.am-modal-footer-hd {\n  padding-bottom: 10px;\n}\n/**\n  * Footer Theme: default\n  */\n.am-footer-default {\n  background-color: #fff;\n}\n.am-footer-default a {\n  color: #555555;\n}\n.am-footer-default .am-footer-switch {\n  margin-bottom: 10px;\n  font-weight: bold;\n}\n.am-footer-default .am-footer-ysp {\n  color: #555555;\n  cursor: pointer;\n}\n.am-footer-default .am-footer-divider {\n  color: #ccc;\n}\n.am-footer-default .am-footer-desktop {\n  color: #0e90d2;\n}\n.am-footer-default .am-footer-miscs {\n  color: #999999;\n  font-size: 13px;\n}\n.am-footer-default .am-footer-miscs p {\n  margin: 5px 0;\n}\n@media only screen and (min-width:641px) {\n  .am-footer-default .am-footer-miscs p {\n    display: inline-block;\n    margin: 5px;\n  }\n}\n.am-gallery {\n  padding: 5px 5px 0 5px;\n  list-style: none;\n}\n.am-gallery h3 {\n  margin: 0;\n}\n[data-am-gallery*='pureview'] img {\n  cursor: pointer;\n}\n/**\n  * Gallery Theme: default\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-gallery-default > li {\n  padding: 5px;\n}\n.am-gallery-default .am-gallery-item img {\n  width: 100%;\n  height: auto;\n}\n.am-gallery-default .am-gallery-title {\n  margin-top: 10px;\n  font-weight: normal;\n  font-size: 1.4rem;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n  color: #555555;\n}\n.am-gallery-default .am-gallery-desc {\n  color: #999999;\n  font-size: 1.2rem;\n}\n/**\n  * Gallery Theme: overlay\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-gallery-overlay > li {\n  padding: 5px;\n}\n.am-gallery-overlay .am-gallery-item {\n  position: relative;\n}\n.am-gallery-overlay .am-gallery-item img {\n  width: 100%;\n  height: auto;\n}\n.am-gallery-overlay .am-gallery-title {\n  font-weight: normal;\n  font-size: 1.4rem;\n  color: #FFF;\n  position: absolute;\n  bottom: 0;\n  width: 100%;\n  background-color: rgba(0, 0, 0, 0.5);\n  text-indent: 5px;\n  height: 30px;\n  line-height: 30px;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-gallery-overlay .am-gallery-desc {\n  display: none;\n}\n/**\n  * Accordion Theme: bordered\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-gallery-bordered > li {\n  padding: 5px;\n}\n.am-gallery-bordered .am-gallery-item {\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.35);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.35);\n  padding: 5px;\n}\n.am-gallery-bordered .am-gallery-item img {\n  width: 100%;\n  height: auto;\n}\n.am-gallery-bordered .am-gallery-title {\n  margin-top: 10px;\n  font-weight: normal;\n  font-size: 1.4rem;\n  color: #555555;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-gallery-bordered .am-gallery-desc {\n  color: #999999;\n  font-size: 1.2rem;\n}\n/**\n  * Gallery Theme: imgbordered\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-gallery-imgbordered > li {\n  padding: 5px;\n}\n.am-gallery-imgbordered .am-gallery-item img {\n  width: 100%;\n  height: auto;\n  border: 3px solid #FFF;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.35);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.35);\n}\n.am-gallery-imgbordered .am-gallery-title {\n  margin-top: 10px;\n  font-weight: normal;\n  font-size: 1.4rem;\n  color: #555555;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-gallery-imgbordered .am-gallery-desc {\n  color: #999999;\n  font-size: 1.2rem;\n}\n.am-gotop a {\n  display: inline-block;\n  text-decoration: none;\n}\n/**\n  * Gotop Theme: default\n  */\n.am-gotop-default {\n  text-align: center;\n  margin: 10px 0;\n}\n.am-gotop-default a {\n  background-color: #0e90d2;\n  padding: .5em 1.5em;\n  border-radius: 0;\n  color: #fff;\n}\n.am-gotop-default a img {\n  display: none;\n}\n/**\n  * Gotop Theme: fixed\n  */\n.am-gotop-fixed {\n  position: fixed;\n  right: 10px;\n  bottom: 10px;\n  z-index: 1010;\n  opacity: 0;\n  width: 32px;\n  min-height: 32px;\n  overflow: hidden;\n  border-radius: 0;\n  text-align: center;\n}\n.am-gotop-fixed.am-active {\n  opacity: .9;\n}\n.am-gotop-fixed.am-active:hover {\n  opacity: 1;\n}\n.am-gotop-fixed a {\n  display: block;\n}\n.am-gotop-fixed .am-gotop-title {\n  display: none;\n}\n.am-gotop-fixed .am-gotop-icon-custom {\n  display: inline-block;\n  max-width: 30px;\n  vertical-align: middle;\n}\n.am-gotop-fixed .am-gotop-icon {\n  width: 100%;\n  line-height: 32px;\n  background-color: #555555;\n  vertical-align: middle;\n  color: #ddd;\n}\n.am-gotop-fixed .am-gotop-icon:hover {\n  color: #fff;\n}\n.am-with-fixed-navbar .am-gotop-fixed {\n  bottom: 60px;\n}\n.am-header {\n  position: relative;\n  width: 100%;\n  height: 49px;\n  line-height: 49px;\n  padding: 0 10px;\n}\n.am-header h1 {\n  margin-top: 0;\n  margin-bottom: 0;\n}\n.am-header .am-header-title {\n  margin: 0 30%;\n  font-size: 2rem;\n  font-weight: normal;\n  text-align: center;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-header .am-header-title img {\n  margin-top: 12px;\n  height: 25px;\n  vertical-align: top;\n}\n.am-header .am-header-nav {\n  position: absolute;\n  top: 0;\n}\n.am-header .am-header-nav img {\n  height: 16px;\n  width: auto;\n  vertical-align: middle;\n}\n.am-header .am-header-left {\n  left: 10px;\n}\n.am-header .am-header-right {\n  right: 10px;\n}\n.am-header-fixed {\n  position: fixed;\n  top: 0;\n  left: 0;\n  right: 0;\n  width: 100%;\n  z-index: 1010;\n}\n.am-with-fixed-header {\n  padding-top: 49px;\n}\n/**\n  * Header Theme: default\n  */\n.am-header-default {\n  background-color: #0e90d2;\n}\n.am-header-default .am-header-title {\n  color: #fff;\n}\n.am-header-default .am-header-title a {\n  color: #fff;\n}\n.am-header-default .am-header-icon {\n  font-size: 20px;\n}\n.am-header-default .am-header-nav {\n  color: #eeeeee;\n}\n.am-header-default .am-header-nav > a {\n  display: inline-block;\n  min-width: 36px;\n  text-align: center;\n  color: #eeeeee;\n}\n.am-header-default .am-header-nav > a + a {\n  margin-left: 5px;\n}\n.am-header-default .am-header-nav .am-btn {\n  margin-top: 9px;\n  height: 31px;\n  padding: 0 0.5em;\n  line-height: 30px;\n  font-size: 14px;\n  vertical-align: top;\n}\n.am-header-default .am-header-nav .am-btn .am-header-icon {\n  font-size: inherit;\n}\n.am-header-default .am-header-nav .am-btn-default {\n  color: #999999;\n}\n.am-header-default .am-header-nav-title,\n.am-header-default .am-header-nav-title + .am-header-icon {\n  font-size: 14px;\n}\n.am-intro {\n  position: relative;\n}\n.am-intro img {\n  max-width: 100%;\n}\n.am-intro-hd {\n  position: relative;\n  height: 45px;\n  line-height: 45px;\n}\n.am-intro-title {\n  font-size: 18px;\n  margin: 0;\n  font-weight: bold;\n}\n.am-intro-more-top {\n  position: absolute;\n  right: 10px;\n  top: 0;\n  font-size: 1.4rem;\n}\n.am-intro-bd {\n  padding-top: 15px;\n  padding-bottom: 15px;\n  font-size: 1.4rem;\n}\n.am-intro-bd p:last-child {\n  margin-bottom: 0;\n}\n.am-intro-more-bottom {\n  clear: both;\n  text-align: center;\n}\n.am-intro-more-bottom .am-btn {\n  font-size: 14px;\n}\n/**\n  * Intro Theme: default\n  */\n.am-intro-default .am-intro-hd {\n  background-color: #0e90d2;\n  color: #fff;\n  padding: 0 10px;\n}\n.am-intro-default .am-intro-hd a {\n  color: #eee;\n}\n.am-intro-default .am-intro-right {\n  padding-left: 0;\n}\n.am-list-news-hd {\n  padding-top: 1.2rem;\n  padding-bottom: 0.8rem;\n}\n.am-list-news-hd a {\n  display: block;\n}\n.am-list-news-hd h2 {\n  font-size: 1.6rem;\n  float: left;\n  margin: 0;\n  height: 2rem;\n  line-height: 2rem;\n}\n.am-list-news-hd h3 {\n  margin: 0;\n}\n.am-list-news-hd .am-list-news-more {\n  font-size: 1.3rem;\n  height: 2rem;\n  line-height: 2rem;\n}\n.am-list .am-list-item-dated a {\n  padding-right: 80px;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-list .am-list-item-dated a::after {\n  display: none;\n}\n.am-list .am-list-item-desced a,\n.am-list .am-list-item-thumbed a {\n  padding-right: 0;\n}\n.am-list-news .am-list-item-hd {\n  margin: 0;\n}\n.am-list-date {\n  position: absolute;\n  right: 5px;\n  font-size: 1.3rem;\n  top: 1.3rem;\n}\n.am-list-item-desced {\n  padding-bottom: 1rem;\n}\n.am-list-item-desced > a {\n  padding: 1rem 0;\n}\n.am-list-item-desced .am-list-date {\n  position: static;\n}\n.am-list-item-thumbed {\n  padding-top: 1em;\n}\n.am-list-news-ft {\n  text-align: center;\n}\n.am-list-news .am-titlebar {\n  margin-left: 0;\n  margin-right: 0;\n}\n.am-list-news .am-titlebar ~ .am-list-news-bd .am-list > li:first-child {\n  border-top: none;\n}\n/**\n  * list_news Theme: default\n  */\n.am-list-news-default {\n  margin: 10px;\n}\n.am-list-news-default .am-g {\n  margin-left: auto;\n  margin-right: auto;\n}\n.am-list-news-default .am-list-item-hd {\n  font-weight: normal;\n}\n.am-list-news-default .am-list-date {\n  color: #999999;\n}\n.am-list-news-default .am-list > li {\n  border-color: #dedede;\n}\n.am-list-news-default .am-list .am-list-item-desced {\n  padding-top: 1rem;\n  padding-bottom: 1rem;\n}\n.am-list-news-default .am-list .am-list-item-desced > a {\n  padding: 0;\n}\n.am-list-news-default .am-list .am-list-item-desced .am-list-item-text {\n  margin-top: 0.5rem;\n  color: #757575;\n}\n.am-list-news-default .am-list .am-list-item-text {\n  overflow: hidden;\n  text-overflow: ellipsis;\n  display: -webkit-box;\n  -webkit-box-orient: vertical;\n  line-height: 1.3em;\n  -webkit-line-clamp: 2;\n  /* number of lines to show */\n  max-height: 2.6em;\n}\n.am-list-news-default .am-list .am-list-item-thumb-top .am-list-thumb {\n  padding: 0;\n  margin-bottom: 0.8rem;\n}\n.am-list-news-default .am-list .am-list-item-thumb-top .am-list-main {\n  padding: 0;\n}\n.am-list-news-default .am-list .am-list-item-thumb-left .am-list-thumb {\n  padding-left: 0;\n}\n.am-list-news-default .am-list .am-list-item-desced .am-list-main {\n  padding: 0;\n}\n.am-list-news-default .am-list .am-list-item-thumb-right .am-list-thumb {\n  padding-right: 0;\n}\n.am-list-news-default .am-list .am-list-item-thumb-bottom-left .am-list-item-hd {\n  clear: both;\n  padding-bottom: 0.5rem;\n}\n.am-list-news-default .am-list .am-list-item-thumb-bottom-left .am-list-thumb {\n  padding-left: 0;\n}\n.am-list-news-default .am-list .am-list-item-thumb-bottom-right .am-list-item-hd {\n  clear: both;\n  padding-bottom: 0.5rem;\n}\n.am-list-news-default .am-list .am-list-item-thumb-bottom-right .am-list-thumb {\n  padding-right: 0;\n}\n.am-list-news-default .am-list .am-list-thumb img {\n  width: 100%;\n  display: block;\n}\n@media only screen and (max-width: 640px) {\n  .am-list-news-default .am-list-item-thumb-left .am-list-thumb,\n  .am-list-news-default .am-list-item-thumb-right .am-list-thumb {\n    max-height: 80px;\n    overflow: hidden;\n  }\n  .am-list-news-default .am-list-item-thumb-bottom-left .am-list-item-text,\n  .am-list-news-default .am-list-item-thumb-bottom-right .am-list-item-text {\n    -webkit-line-clamp: 3;\n    /* number of lines to show */\n    max-height: 3.9em;\n  }\n  .am-list-news-default .am-list-item-thumb-bottom-left .am-list-thumb,\n  .am-list-news-default .am-list-item-thumb-bottom-right .am-list-thumb {\n    max-height: 60px;\n    overflow: hidden;\n  }\n}\n.am-map {\n  width: 100%;\n  height: 300px;\n}\n/**\n  * Accordion Theme: default\n  * Author: Hzp (hzp@yunshipei.com)\n  */\n.am-map-default #bd-map {\n  width: 100%;\n  height: 100%;\n  overflow: hidden;\n  margin: 0;\n  font-size: 14px;\n  line-height: 1.4!important;\n}\n.am-map-default .BMap_bubble_title {\n  font-weight: bold;\n}\n.am-map-default #BMap_mask {\n  width: 100%;\n}\n.am-mechat {\n  margin: 1rem;\n}\n.am-mechat .section-cbox-wap .cbox-post-wap .post-action-wap .action-function-wap .function-list-wap .list-upload-wap .upload-mutual-wap {\n  -webkit-box-sizing: content-box;\n          box-sizing: content-box;\n}\n.am-menu {\n  position: relative;\n  padding: 0;\n  margin: 0;\n}\n.am-menu ul {\n  padding: 0;\n  margin: 0;\n}\n.am-menu li {\n  list-style: none;\n}\n.am-menu a:after,\n.am-menu a:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n}\n.am-menu-sub {\n  z-index: 1050;\n}\n.am-menu-toggle {\n  display: none;\n  z-index: 1015;\n}\n.am-menu-toggle img {\n  display: inline-block;\n  height: 16px;\n  width: auto;\n  vertical-align: middle;\n}\n.am-menu-nav a {\n  display: block;\n  padding: 0.8rem 0;\n  -webkit-transition: all 0.45s;\n  transition: all 0.45s;\n}\n/**\n  * Menu Theme: default\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-menu-default .am-menu-nav {\n  padding-top: 8px;\n  padding-bottom: 8px;\n}\n.am-menu-default .am-menu-nav a {\n  text-align: center;\n  height: 36px;\n  line-height: 36px;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n  padding: 0;\n  color: #0e90d2;\n}\n.am-menu-default .am-menu-nav > .am-parent > a {\n  position: relative;\n  -webkit-transition: .15s;\n  transition: .15s;\n}\n.am-menu-default .am-menu-nav > .am-parent > a:after {\n  content: \"\\f107\";\n  margin-left: 5px;\n  -webkit-transition: .15s;\n  transition: .15s;\n}\n.am-menu-default .am-menu-nav > .am-parent > a:before {\n  position: absolute;\n  top: 100%;\n  margin-top: -16px;\n  left: 50%;\n  margin-left: -12px;\n  content: \"\\f0d8\";\n  display: none;\n  color: #f1f1f1;\n  font-size: 24px;\n}\n.am-menu-default .am-menu-nav > .am-parent.am-open > a {\n  color: #095f8a;\n}\n.am-menu-default .am-menu-nav > .am-parent.am-open > a:before {\n  display: block;\n}\n.am-menu-default .am-menu-nav > .am-parent.am-open > a:after {\n  -webkit-transform: rotate(-180deg);\n      -ms-transform: rotate(-180deg);\n          transform: rotate(-180deg);\n}\n.am-menu-default .am-menu-sub {\n  position: absolute;\n  left: 5px;\n  right: 5px;\n  background-color: #f1f1f1;\n  border-radius: 0;\n  padding-top: 8px;\n  padding-bottom: 8px;\n}\n.am-menu-default .am-menu-sub > li > a {\n  color: #555555;\n}\n@media only screen and (min-width:641px) {\n  .am-menu-default .am-menu-nav li {\n    width: auto;\n    float: left;\n    clear: none;\n    display: inline;\n  }\n  .am-menu-default .am-menu-nav a {\n    padding-left: 1.5rem;\n    padding-right: .5rem;\n  }\n}\n/**\n/**\n  * Menu Theme: dropdown1\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-menu-dropdown1 {\n  position: relative;\n  /*@media @medium-up {\n    .am-menu-toggle {\n      display: none!important;\n    }\n\n    .am-menu-nav {\n      &.am-collapse {\n        display: block;\n      }\n\n      .am-menu-sub {\n        background-color: ;//@menu-sub-bg;\n        display: block;\n        & > li {\n          clear: none;\n\n        }\n      }\n\n      .am-menu-lv2 {\n        & > li {\n          clear: none;\n          width: auto;\n        }\n      }\n    }\n  }*/\n}\n.am-menu-dropdown1 .am-menu-toggle {\n  position: absolute;\n  right: 5px;\n  top: -47px;\n  display: block;\n  width: 44px;\n  height: 44px;\n  line-height: 44px;\n  text-align: center;\n  color: #fff;\n}\n.am-menu-dropdown1 a {\n  -webkit-transition: all .4s;\n  transition: all .4s;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-menu-dropdown1 .am-menu-nav {\n  position: absolute;\n  left: 0;\n  right: 0;\n  z-index: 1050;\n}\n.am-menu-dropdown1 .am-menu-nav a {\n  padding: 0.8rem;\n}\n.am-menu-dropdown1 .am-menu-nav > li {\n  width: 100%;\n}\n.am-menu-dropdown1 .am-menu-nav > li.am-parent > a {\n  position: relative;\n}\n.am-menu-dropdown1 .am-menu-nav > li.am-parent > a::before {\n  content: \"\\f067\";\n  position: absolute;\n  right: 1rem;\n  top: 1.4rem;\n}\n.am-menu-dropdown1 .am-menu-nav > li.am-parent.am-open > a {\n  background-color: #0c80ba;\n  border-bottom: none;\n  color: #fff;\n}\n.am-menu-dropdown1 .am-menu-nav > li.am-parent.am-open > a:before {\n  content: \"\\f068\";\n}\n.am-menu-dropdown1 .am-menu-nav > li.am-parent.am-open > a:after {\n  content: \"\";\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: middle;\n  border-top: 8px solid #0c80ba;\n  border-right: 8px solid transparent;\n  border-left: 8px solid transparent;\n  border-bottom: 0 dotted;\n  -webkit-transform: rotate(360deg);\n      -ms-transform: rotate(360deg);\n          transform: rotate(360deg);\n  position: absolute;\n  top: 100%;\n  left: 50%;\n  margin-left: -4px;\n}\n.am-menu-dropdown1 .am-menu-nav > li > a {\n  border-bottom: 1px solid #0b76ac;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);\n  background-color: #0e90d2;\n  color: #fff;\n  height: 49px;\n  line-height: 49px;\n  padding: 0;\n  text-indent: 10px;\n}\n.am-menu-dropdown1 .am-menu-sub {\n  background-color: #fff;\n}\n.am-menu-dropdown1 .am-menu-sub a {\n  color: #555;\n  height: 44px;\n  line-height: 44px;\n  text-indent: 5px;\n  padding: 0;\n}\n.am-menu-dropdown1 .am-menu-sub a:before {\n  content: \"\\f105\";\n  color: #aaa;\n  font-size: 16px;\n  margin-right: 5px;\n}\n/**\n  * Menu Theme: dropdown2\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-menu-dropdown2 .am-menu-toggle {\n  position: absolute;\n  right: 5px;\n  top: -47px;\n  display: block;\n  width: 44px;\n  height: 44px;\n  line-height: 44px;\n  text-align: center;\n  color: #fff;\n}\n.am-menu-dropdown2 .am-menu-nav {\n  position: absolute;\n  left: 0;\n  right: 0;\n  background-color: #f5f5f5;\n  -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);\n  z-index: 1050;\n  padding-top: 8px;\n  padding-bottom: 8px;\n}\n.am-menu-dropdown2 .am-menu-nav a {\n  height: 38px;\n  line-height: 38px;\n  padding: 0;\n  text-align: center;\n}\n.am-menu-dropdown2 .am-menu-nav > li > a {\n  color: #333333;\n}\n.am-menu-dropdown2 .am-menu-nav > li.am-parent > a {\n  position: relative;\n}\n.am-menu-dropdown2 .am-menu-nav > li.am-parent > a:after {\n  content: \"\\f107\";\n  margin-left: 5px;\n  -webkit-transition: -webkit-transform .2s;\n  transition: -webkit-transform .2s;\n  transition: transform .2s;\n  transition: transform .2s, -webkit-transform .2s;\n}\n.am-menu-dropdown2 .am-menu-nav > li.am-parent.am-open > a {\n  position: relative;\n}\n.am-menu-dropdown2 .am-menu-nav > li.am-parent.am-open > a:after {\n  color: #0e90d2;\n  -webkit-transform: rotate(180deg);\n      -ms-transform: rotate(180deg);\n          transform: rotate(180deg);\n}\n.am-menu-dropdown2 .am-menu-nav > li.am-parent.am-open > a:before {\n  position: absolute;\n  top: 100%;\n  margin-top: -16px;\n  left: 50%;\n  margin-left: -12px;\n  font-size: 24px;\n  content: \"\\f0d8\";\n  color: rgba(0, 0, 0, 0.2);\n}\n.am-menu-dropdown2 .am-menu-sub {\n  position: absolute;\n  left: 5px;\n  right: 5px;\n  padding: 8px 0;\n  border-radius: 2px;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n  background-color: #fff;\n  z-index: 1055;\n}\n.am-menu-dropdown2 .am-menu-sub a {\n  padding: 0;\n  height: 35px;\n  color: #555555;\n  line-height: 35px;\n}\n@media only screen and (min-width:641px) {\n  .am-menu-dropdown2 .am-menu-toggle {\n    display: none !important;\n  }\n  .am-menu-dropdown2 .am-menu-nav {\n    position: static;\n    display: block;\n  }\n  .am-menu-dropdown2 .am-menu-nav > li {\n    float: none;\n    width: auto;\n    display: inline-block;\n  }\n  .am-menu-dropdown2 .am-menu-nav > li a {\n    padding-left: 1.5rem;\n    padding-right: 1.5rem;\n  }\n  .am-menu-dropdown2 .am-menu-sub {\n    left: auto;\n    right: auto;\n  }\n  .am-menu-dropdown2 .am-menu-sub > li {\n    float: none;\n    width: auto;\n  }\n  .am-menu-dropdown2 .am-menu-sub a {\n    padding-left: 2rem;\n    padding-right: 2rem;\n  }\n}\n/**\n  * Menu Theme: slide1\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-menu-slide1 .am-menu-toggle {\n  position: absolute;\n  right: 5px;\n  top: -47px;\n  display: block;\n  width: 44px;\n  height: 44px;\n  line-height: 44px;\n  text-align: center;\n  color: #fff;\n}\n.am-menu-slide1 .am-menu-nav {\n  background-color: #f5f5f5;\n  padding-top: 8px;\n  padding-bottom: 8px;\n}\n.am-menu-slide1 .am-menu-nav.am-in:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f0d8\";\n  font-size: 24px;\n  color: #f5f5f5;\n  position: absolute;\n  right: 16px;\n  top: -16px;\n}\n.am-menu-slide1 .am-menu-nav a {\n  line-height: 38px;\n  height: 38px;\n  display: block;\n  padding: 0;\n  text-align: center;\n}\n.am-menu-slide1 .am-menu-nav > li > a {\n  color: #333333;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-menu-slide1 .am-menu-nav > .am-parent > a {\n  position: relative;\n  -webkit-transition: .15s;\n  transition: .15s;\n}\n.am-menu-slide1 .am-menu-nav > .am-parent > a:after {\n  content: \"\\f107\";\n  margin-left: 5px;\n  -webkit-transition: .15s;\n  transition: .15s;\n}\n.am-menu-slide1 .am-menu-nav > .am-parent > a:before {\n  position: absolute;\n  top: 100%;\n  margin-top: -16px;\n  left: 50%;\n  margin-left: -12px;\n  content: \"\\f0d8\";\n  display: none;\n  color: #0e90d2;\n  font-size: 24px;\n}\n.am-menu-slide1 .am-menu-nav > .am-parent.am-open > a {\n  color: #0e90d2;\n}\n.am-menu-slide1 .am-menu-nav > .am-parent.am-open > a:before {\n  display: block;\n}\n.am-menu-slide1 .am-menu-nav > .am-parent.am-open > a:after {\n  -webkit-transform: rotate(-180deg);\n      -ms-transform: rotate(-180deg);\n          transform: rotate(-180deg);\n}\n.am-menu-slide1 .am-menu-sub {\n  position: absolute;\n  left: 5px;\n  right: 5px;\n  background-color: #0e90d2;\n  border-radius: 0;\n  padding-top: 8px;\n  padding-bottom: 8px;\n}\n.am-menu-slide1 .am-menu-sub > li > a {\n  color: #fff;\n}\n@media only screen and (min-width:641px) {\n  .am-menu-slide1 .am-menu-toggle {\n    display: none !important;\n  }\n  .am-menu-slide1 .am-menu-nav {\n    background-color: #f5f5f5;\n    display: block;\n  }\n  .am-menu-slide1 .am-menu-nav.am-in:before {\n    display: none;\n  }\n  .am-menu-slide1 .am-menu-nav li {\n    width: auto;\n    clear: none;\n  }\n  .am-menu-slide1 .am-menu-nav li a {\n    padding-left: 1.5rem;\n    padding-right: 1.5rem;\n  }\n}\n/**\n  * Menu Theme: offcanvas1\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-menu-offcanvas1 .am-menu-toggle {\n  position: absolute;\n  right: 5px;\n  top: -47px;\n  display: block;\n  width: 44px;\n  height: 44px;\n  line-height: 44px;\n  text-align: center;\n  color: #fff;\n}\n.am-menu-offcanvas1 .am-menu-nav {\n  border-bottom: 1px solid rgba(0, 0, 0, 0.3);\n  -webkit-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.05);\n          box-shadow: 0 1px 0 rgba(255, 255, 255, 0.05);\n}\n.am-menu-offcanvas1 .am-menu-nav > li > a {\n  height: 44px;\n  line-height: 44px;\n  text-indent: 15px;\n  padding: 0;\n  position: relative;\n  color: #ccc;\n  border-top: 1px solid rgba(0, 0, 0, 0.3);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);\n  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.5);\n}\n.am-menu-offcanvas1 .am-menu-nav > .am-open > a,\n.am-menu-offcanvas1 .am-menu-nav > li > a:hover,\n.am-menu-offcanvas1 .am-menu-nav > li > a:focus {\n  background-color: #474747;\n  color: #fff;\n  outline: none;\n}\n.am-menu-offcanvas1 .am-menu-nav > .am-active > a {\n  background-color: #1a1a1a;\n  color: #fff;\n}\n.am-menu-offcanvas1 .am-menu-nav > .am-parent > a {\n  -webkit-transition: all .3s;\n  transition: all .3s;\n}\n.am-menu-offcanvas1 .am-menu-nav > .am-parent > a:after {\n  content: \"\\f104\";\n  position: absolute;\n  right: 1.5rem;\n  top: 1.3rem;\n}\n.am-menu-offcanvas1 .am-menu-nav > .am-parent.am-open > a:after {\n  content: \"\\f107\";\n}\n.am-menu-offcanvas1 .am-menu-sub {\n  border-top: 1px solid rgba(0, 0, 0, 0.3);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);\n  padding: 5px 0 5px 15px;\n  background-color: #1a1a1a;\n  font-size: 1.4rem;\n}\n.am-menu-offcanvas1 .am-menu-sub a {\n  color: #eee;\n}\n.am-menu-offcanvas1 .am-menu-sub a:hover {\n  color: #fff;\n}\n.am-menu-offcanvas1 .am-nav-divider {\n  border-top: 1px solid #1a1a1a;\n}\n/**\n  * Menu Theme: offcanvas2\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-menu-offcanvas2 .am-menu-toggle {\n  position: absolute;\n  right: 5px;\n  top: -47px;\n  display: block;\n  width: 44px;\n  height: 44px;\n  line-height: 44px;\n  text-align: center;\n  color: #fff;\n}\n.am-menu-offcanvas2 .am-menu-nav {\n  padding: 10px 5px;\n}\n.am-menu-offcanvas2 .am-menu-nav > li {\n  padding: 5px;\n}\n.am-menu-offcanvas2 .am-menu-nav > li > a {\n  -webkit-transition: all 0.3s;\n  transition: all 0.3s;\n  background-color: #404040;\n  color: #ccc;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);\n  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.5);\n  height: 44px;\n  line-height: 44px;\n  padding: 0;\n  text-align: center;\n}\n.am-menu-offcanvas2 .am-menu-nav > li > a:hover,\n.am-menu-offcanvas2 .am-menu-nav > li > a:focus {\n  background-color: #262626;\n  color: #fff;\n  outline: none;\n}\n.am-menu-offcanvas2 .am-menu-nav > .am-active > a {\n  background-color: #262626;\n  color: #fff;\n}\n/**\n  * Menu Theme: stack\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-menu-stack .am-menu-nav {\n  border-bottom: 1px solid #dedede;\n  -webkit-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.05);\n          box-shadow: 0 1px 0 rgba(255, 255, 255, 0.05);\n}\n.am-menu-stack .am-menu-nav > .am-parent > a {\n  -webkit-transition: all .3s;\n  transition: all .3s;\n}\n.am-menu-stack .am-menu-nav > .am-parent > a:after {\n  content: \"\\f105\";\n  position: absolute;\n  right: 1.5rem;\n  top: 1.3rem;\n  -webkit-transition: all .15s;\n  transition: all .15s;\n}\n.am-menu-stack .am-menu-nav > .am-parent.am-open > a:after {\n  -webkit-transform: rotate(90deg);\n      -ms-transform: rotate(90deg);\n          transform: rotate(90deg);\n}\n.am-menu-stack .am-menu-nav > li > a {\n  position: relative;\n  color: #333;\n  background-color: #f5f5f5;\n  border-top: 1px solid #dedede;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);\n  height: 49px;\n  line-height: 49px;\n  text-indent: 10px;\n  padding: 0;\n}\n.am-menu-stack .am-menu-nav > .am-open > a,\n.am-menu-stack .am-menu-nav > li > a:hover,\n.am-menu-stack .am-menu-nav > li > a:focus {\n  background-color: #e5e5e5;\n  color: #222;\n  outline: none;\n}\n.am-menu-stack .am-menu-sub {\n  padding: 0;\n  font-size: 1.4rem;\n  border-top: 1px solid #dedede;\n}\n.am-menu-stack .am-menu-sub a {\n  border-bottom: 1px solid #dedede;\n  padding-left: 2rem;\n  color: #444;\n}\n.am-menu-stack .am-menu-sub a:hover {\n  color: #333;\n}\n.am-menu-stack .am-menu-sub li:last-child a {\n  border-bottom: none;\n}\n.am-menu-stack .am-menu-sub > li > a {\n  height: 44px;\n  line-height: 44px;\n  text-indent: 15px;\n  padding: 0;\n}\n@media only screen and (min-width:641px) {\n  .am-menu-stack .am-menu-nav {\n    background-color: #f5f5f5;\n  }\n  .am-menu-stack .am-menu-nav > li {\n    float: left;\n    width: auto;\n    clear: none !important;\n    display: inline-block;\n  }\n  .am-menu-stack .am-menu-nav > li a {\n    padding-left: 1.5rem;\n    padding-right: 1.5rem;\n  }\n  .am-menu-stack .am-menu-nav > li.am-parent > a:after {\n    position: static;\n    content: \"\\f107\";\n  }\n  .am-menu-stack .am-menu-nav > li.am-parent.am-open a {\n    border-bottom: none;\n  }\n  .am-menu-stack .am-menu-nav > li.am-parent.am-open a:after {\n    -webkit-transform: rotateX(-180deg);\n            transform: rotateX(-180deg);\n  }\n  .am-menu-stack .am-menu-nav > li.am-parent.am-open .am-menu-sub {\n    background-color: #e5e5e5;\n  }\n  .am-menu-stack .am-menu-sub {\n    position: absolute;\n    left: 0;\n    right: 0;\n    background-color: #ddd;\n    border-top: none;\n  }\n  .am-menu-stack .am-menu-sub li {\n    width: auto;\n    float: left;\n    clear: none;\n  }\n}\n.am-navbar {\n  position: fixed;\n  left: 0;\n  bottom: 0;\n  width: 100%;\n  height: 49px;\n  line-height: 49px;\n  z-index: 1010;\n}\n.am-navbar ul {\n  padding-left: 0;\n  margin: 0;\n  list-style: none;\n  width: 100%;\n}\n.am-navbar .am-navbar-nav {\n  padding-left: 8px;\n  padding-right: 8px;\n  text-align: center;\n  overflow: hidden;\n  display: table;\n}\n.am-navbar .am-navbar-nav li {\n  display: table-cell;\n  width: 1%;\n  float: none;\n}\n.am-navbar-nav {\n  position: relative;\n  z-index: 1015;\n}\n.am-navbar-nav a {\n  display: inline-block;\n  width: 100%;\n  height: 49px;\n  line-height: 20px;\n}\n.am-navbar-nav a img {\n  display: block;\n  vertical-align: middle;\n  height: 24px;\n  width: 24px;\n  margin: 4px auto 0;\n}\n.am-navbar-nav a [class*=\"am-icon\"] {\n  width: 24px;\n  height: 24px;\n  margin: 4px auto 0;\n  display: block;\n  line-height: 24px;\n}\n.am-navbar-nav a [class*=\"am-icon\"]:before {\n  font-size: 22px;\n  vertical-align: middle;\n}\n.am-navbar-nav a .am-navbar-label {\n  padding-top: 2px;\n  line-height: 1;\n  font-size: 12px;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-navbar-more [class*=\"am-icon-\"] {\n  -webkit-transition: 0.15s;\n  transition: 0.15s;\n}\n.am-navbar-more.am-active [class*=\"am-icon-\"] {\n  -webkit-transform: rotateX(-180deg);\n          transform: rotateX(-180deg);\n}\n.am-navbar-actions {\n  position: absolute;\n  bottom: 49px;\n  right: 0;\n  left: 0;\n  z-index: 1009;\n  opacity: 0;\n  -webkit-transition: .3s;\n  transition: .3s;\n  -webkit-transform: translate(0, 100%);\n      -ms-transform: translate(0, 100%);\n          transform: translate(0, 100%);\n}\n.am-navbar-actions.am-active {\n  opacity: 1;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n}\n.am-navbar-actions li {\n  line-height: 42px;\n  position: relative;\n}\n.am-navbar-actions li a {\n  display: block;\n  width: 100%;\n  height: 40px;\n  -webkit-box-shadow: inset 0 1px rgba(220, 220, 220, 0.25);\n          box-shadow: inset 0 1px rgba(220, 220, 220, 0.25);\n  padding-left: 20px;\n  padding-right: 36px;\n}\n.am-navbar-actions li a :after {\n  font-family: \"FontAwesome\", sans-serif;\n  content: \"\\f105\";\n  display: inline-block;\n  position: absolute;\n  top: 0;\n  right: 20px;\n}\n.am-navbar-actions li a img {\n  vertical-align: middle;\n  height: 20px;\n  width: 20px;\n  display: inline;\n}\n#am-navbar-qrcode {\n  width: 220px;\n  height: 220px;\n  margin-left: -110px;\n}\n#am-navbar-qrcode .am-modal-bd {\n  padding: 10px;\n}\n#am-navbar-qrcode canvas {\n  display: block;\n  width: 200px;\n  height: 200px;\n}\n.am-with-fixed-navbar {\n  padding-bottom: 54px;\n}\n/**\n  * Navbar Theme: default\n  * Author: hzp (hzp@yunshipei.com)\n  */\n.am-navbar-default a {\n  color: #fff;\n}\n.am-navbar-default .am-navbar-nav {\n  background-color: #0e90d2;\n}\n.am-navbar-default .am-navbar-actions {\n  background-color: #0d86c4;\n}\n.am-navbar-default .am-navbar-actions a {\n  border-bottom: 1px solid #0b6fa2;\n}\n.am-pagination {\n  position: relative;\n}\n/**\n  * Pagination Theme: default\n  */\n.am-pagination-default {\n  margin-left: 10px;\n  margin-right: 10px;\n  font-size: 1.6rem;\n}\n.am-pagination-default .am-pagination-prev,\n.am-pagination-default .am-pagination-next {\n  float: none;\n}\n/**\n  * Pagination Theme: select\n  */\n.am-pagination-select {\n  margin-left: 10px;\n  margin-right: 10px;\n  font-size: 1.6rem;\n}\n.am-pagination-select > li > a {\n  line-height: 36px;\n  background-color: #eeeeee;\n  padding: 0 15px;\n  border: 0;\n  color: #555555;\n}\n.am-pagination-select .am-pagination-select {\n  position: absolute;\n  top: 0;\n  left: 50%;\n  margin-left: -35px;\n  width: 70px;\n  height: 36px;\n  text-align: center;\n  border-radius: 0;\n}\n.am-pagination-select .am-pagination-select select {\n  display: block;\n  border: 0;\n  line-height: 36px;\n  width: 70px;\n  height: 36px;\n  border-radius: 0;\n  color: #555555;\n  background-color: #eeeeee;\n  -webkit-appearance: none;\n  -moz-appearance: none;\n  appearance: none;\n  padding-left: 18px;\n}\n.am-paragraph p {\n  margin: 10px 0;\n}\n.am-paragraph img {\n  max-width: 100%;\n}\n.am-paragraph h1,\n.am-paragraph h2,\n.am-paragraph h3,\n.am-paragraph h4,\n.am-paragraph h5,\n.am-paragraph h6 {\n  color: #222222;\n}\n.am-paragraph table {\n  max-width: none;\n}\n.am-paragraph-table-container {\n  overflow: hidden;\n  background: #eeeeee;\n  max-width: none;\n}\n.am-paragraph-table-container table {\n  width: 100%;\n  max-width: none;\n}\n.am-paragraph-table-container table th {\n  background: #bce5fb;\n  height: 40px;\n  border: 1px solid #999999;\n  text-align: center;\n}\n.am-paragraph-table-container table td {\n  border: 1px solid #999999;\n  text-align: center;\n  vertical-align: middle;\n  background: #fff;\n}\n.am-paragraph-table-container table td p {\n  text-indent: 0;\n  font-size: 1.4rem;\n}\n.am-paragraph-table-container table td a {\n  font-size: 1.4rem;\n}\n/**\n  * Paragraph Theme: default\n  */\n.am-paragraph-default {\n  margin: 0 10px;\n  color: #333333;\n  background-color: transparent;\n}\n.am-paragraph-default p {\n  font-size: 1.4rem;\n}\n.am-paragraph-default img {\n  max-width: 98%;\n  display: block;\n  margin: 5px auto;\n  border: 1px solid #eeeeee;\n  padding: 2px;\n}\n.am-paragraph-default a {\n  color: #0e90d2;\n}\n/**\n  * Slider Theme: a1\n  */\n.am-slider-a1 {\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Control Nav */\n}\n.am-slider-a1 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-a1 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-a1 .am-control-nav {\n  width: 100%;\n  position: absolute;\n  bottom: 5px;\n  text-align: center;\n  line-height: 0;\n}\n.am-slider-a1 .am-control-nav li {\n  margin: 0 6px;\n  display: inline-block;\n}\n.am-slider-a1 .am-control-nav li a {\n  width: 8px;\n  height: 8px;\n  display: block;\n  background-color: rgba(0, 0, 0, 0.5);\n  cursor: pointer;\n  text-indent: -9999px;\n  border-radius: 50%;\n  -webkit-box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);\n          box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);\n}\n.am-slider-a1 .am-control-nav li a:hover {\n  background-color: rgba(0, 0, 0, 0.7);\n}\n.am-slider-a1 .am-control-nav li a.am-active {\n  background-color: #0e90d2;\n  cursor: default;\n}\n.am-slider-a1 .am-direction-nav,\n.am-slider-a1 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: a2\n  */\n.am-slider-a2 {\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Control Nav */\n}\n.am-slider-a2 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-a2 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-a2 .am-control-nav {\n  width: 100%;\n  position: absolute;\n  bottom: 5px;\n  text-align: center;\n  line-height: 0;\n}\n.am-slider-a2 .am-control-nav li {\n  margin: 0 6px;\n  display: inline-block;\n}\n.am-slider-a2 .am-control-nav li a {\n  width: 8px;\n  height: 8px;\n  display: block;\n  background-color: rgba(0, 0, 0, 0.5);\n  cursor: pointer;\n  text-indent: -9999px;\n  -webkit-box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);\n          box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);\n}\n.am-slider-a2 .am-control-nav li a:hover {\n  background-color: rgba(0, 0, 0, 0.7);\n}\n.am-slider-a2 .am-control-nav li a.am-active {\n  background: #0e93d7;\n  cursor: default;\n}\n.am-slider-a2 .am-direction-nav,\n.am-slider-a2 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: a3\n  */\n.am-slider-a3 {\n  margin-bottom: 20px;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Control Nav */\n}\n.am-slider-a3 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-a3 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-a3 .am-control-nav {\n  width: 100%;\n  position: absolute;\n  bottom: -20px;\n  text-align: center;\n  height: 20px;\n  background-color: #000;\n  padding-top: 5px;\n  line-height: 0;\n}\n.am-slider-a3 .am-control-nav li {\n  margin: 0 6px;\n  display: inline-block;\n}\n.am-slider-a3 .am-control-nav li a {\n  width: 8px;\n  height: 8px;\n  display: block;\n  background-color: rgba(0, 0, 0, 0.5);\n  cursor: pointer;\n  text-indent: -9999px;\n  border-radius: 50%;\n  -webkit-box-shadow: inset 0 0 3px rgba(200, 200, 200, 0.3);\n          box-shadow: inset 0 0 3px rgba(200, 200, 200, 0.3);\n}\n.am-slider-a3 .am-control-nav li a:hover {\n  background-color: rgba(0, 0, 0, 0.7);\n}\n.am-slider-a3 .am-control-nav li a.am-active {\n  background: #0e90d2;\n  cursor: default;\n}\n.am-slider-a3 .am-direction-nav,\n.am-slider-a3 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: a4\n  */\n.am-slider-a4 {\n  margin-bottom: 30px;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Control Nav */\n}\n.am-slider-a4 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-a4 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-a4 .am-control-nav {\n  width: 100%;\n  position: absolute;\n  bottom: -15px;\n  text-align: center;\n  line-height: 0;\n}\n.am-slider-a4 .am-control-nav li {\n  margin: 0 6px;\n  display: inline-block;\n}\n.am-slider-a4 .am-control-nav li a {\n  width: 8px;\n  height: 8px;\n  display: block;\n  background-color: rgba(0, 0, 0, 0.5);\n  cursor: pointer;\n  text-indent: -9999px;\n  border-radius: 50%;\n  -webkit-box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);\n          box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);\n}\n.am-slider-a4 .am-control-nav li a:hover {\n  background-color: rgba(0, 0, 0, 0.7);\n}\n.am-slider-a4 .am-control-nav li a.am-active {\n  background-color: #0e90d2;\n  cursor: default;\n}\n.am-slider-a4 .am-direction-nav,\n.am-slider-a4 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: a5\n  */\n.am-slider-a5 {\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Control Nav */\n}\n.am-slider-a5 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-a5 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-a5 .am-control-nav {\n  width: 100%;\n  position: absolute;\n  text-align: center;\n  height: 6px;\n  display: table;\n  bottom: 0;\n  font-size: 0;\n  line-height: 0;\n}\n.am-slider-a5 .am-control-nav li {\n  display: table-cell;\n}\n.am-slider-a5 .am-control-nav li a {\n  width: 100%;\n  height: 6px;\n  display: block;\n  background-color: rgba(0, 0, 0, 0.5);\n  cursor: pointer;\n  text-indent: -9999px;\n}\n.am-slider-a5 .am-control-nav li a:hover {\n  background-color: rgba(0, 0, 0, 0.7);\n}\n.am-slider-a5 .am-control-nav li a.am-active {\n  background-color: #0e90d2;\n  cursor: default;\n}\n.am-slider-a5 .am-direction-nav,\n.am-slider-a5 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: b1\n  */\n.am-slider-b1 {\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Direction Nav */\n}\n.am-slider-b1 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-b1 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-b1 .am-direction-nav a {\n  -webkit-box-sizing: content-box;\n          box-sizing: content-box;\n  display: block;\n  width: 24px;\n  height: 24px;\n  padding: 8px 0;\n  margin: -20px 0 0;\n  position: absolute;\n  top: 50%;\n  z-index: 10;\n  overflow: hidden;\n  opacity: 0.45;\n  cursor: pointer;\n  color: #fff;\n  text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3);\n  background-color: rgba(0, 0, 0, 0.5);\n  font-size: 0;\n  text-align: center;\n  -webkit-transition: all .3s ease;\n  transition: all .3s ease;\n}\n.am-slider-b1 .am-direction-nav a:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f053\";\n  font-size: 24px;\n}\n.am-slider-b1 .am-direction-nav a.am-prev {\n  left: 0;\n  padding-right: 5px;\n  border-bottom-right-radius: 5px;\n  border-top-right-radius: 5px;\n}\n.am-slider-b1 .am-direction-nav a.am-next {\n  right: 0;\n  padding-left: 5px;\n  border-bottom-left-radius: 5px;\n  border-top-left-radius: 5px;\n}\n.am-slider-b1 .am-direction-nav a.am-next:before {\n  content: \"\\f054\";\n}\n.am-slider-b1 .am-direction-nav .am-disabled {\n  opacity: 0!important;\n  cursor: default;\n}\n.am-slider-b1:hover .am-prev {\n  opacity: 0.7;\n}\n.am-slider-b1:hover .am-prev:hover {\n  opacity: 1;\n}\n.am-slider-b1:hover .am-next {\n  opacity: 0.7;\n}\n.am-slider-b1:hover .am-next:hover {\n  opacity: 1;\n}\n.am-slider-b1 .am-control-nav,\n.am-slider-b1 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: b2\n  */\n.am-slider-b2 {\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Direction Nav */\n}\n.am-slider-b2 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-b2 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-b2 .am-direction-nav a {\n  -webkit-box-sizing: content-box;\n          box-sizing: content-box;\n  display: block;\n  width: 24px;\n  height: 24px;\n  padding: 4px;\n  margin: -16px 0 0;\n  position: absolute;\n  top: 50%;\n  z-index: 10;\n  overflow: hidden;\n  opacity: 0.45;\n  cursor: pointer;\n  color: #fff;\n  text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3);\n  background-color: rgba(0, 0, 0, 0.5);\n  font-size: 0;\n  text-align: center;\n  border-radius: 50%;\n  -webkit-transition: all .3s ease;\n  transition: all .3s ease;\n}\n.am-slider-b2 .am-direction-nav a:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f053\";\n  font-size: 16px;\n  line-height: 24px;\n}\n.am-slider-b2 .am-direction-nav a.am-prev {\n  left: 5px;\n}\n.am-slider-b2 .am-direction-nav a.am-next {\n  right: 5px;\n}\n.am-slider-b2 .am-direction-nav a.am-next:before {\n  content: \"\\f054\";\n}\n.am-slider-b2 .am-direction-nav .am-disabled {\n  opacity: 0!important;\n  cursor: default;\n}\n.am-slider-b2:hover .am-prev {\n  opacity: 0.7;\n}\n.am-slider-b2:hover .am-prev:hover {\n  opacity: 1;\n}\n.am-slider-b2:hover .am-next {\n  opacity: 0.7;\n}\n.am-slider-b2:hover .am-next:hover {\n  opacity: 1;\n}\n.am-slider-b2 .am-control-nav,\n.am-slider-b2 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: b3\n  */\n.am-slider-b3 {\n  margin: 15px 30px;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Direction Nav */\n}\n.am-slider-b3 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-b3 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-b3 .am-direction-nav a {\n  -webkit-box-sizing: content-box;\n          box-sizing: content-box;\n  display: block;\n  width: 24px;\n  height: 24px;\n  padding: 4px;\n  margin: -16px 0 0;\n  position: absolute;\n  top: 50%;\n  z-index: 10;\n  overflow: hidden;\n  opacity: 0.45;\n  cursor: pointer;\n  color: #333333;\n  text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3);\n  font-size: 0;\n  -webkit-transition: all .3s ease;\n  transition: all .3s ease;\n}\n.am-slider-b3 .am-direction-nav a:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f053\";\n  font-size: 24px;\n}\n.am-slider-b3 .am-direction-nav a.am-prev {\n  left: -25px;\n}\n.am-slider-b3 .am-direction-nav a.am-next {\n  right: -25px;\n  text-align: right;\n}\n.am-slider-b3 .am-direction-nav a.am-next:before {\n  content: \"\\f054\";\n}\n.am-slider-b3 .am-direction-nav .am-disabled {\n  opacity: 0!important;\n  cursor: default;\n}\n.am-slider-b3:hover .am-prev {\n  opacity: 0.7;\n}\n.am-slider-b3:hover .am-prev:hover {\n  opacity: 1;\n}\n.am-slider-b3:hover .am-next {\n  opacity: 0.7;\n}\n.am-slider-b3:hover .am-next:hover {\n  opacity: 1;\n}\n.am-slider-b3 .am-control-nav,\n.am-slider-b3 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: b4\n  */\n.am-slider-b4 {\n  margin: 15px 20px;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Direction Nav */\n}\n.am-slider-b4 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-b4 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-b4 .am-direction-nav a {\n  position: absolute;\n  top: 50%;\n  z-index: 10;\n  display: block;\n  -webkit-box-sizing: content-box;\n          box-sizing: content-box;\n  width: 24px;\n  height: 24px;\n  margin: -16px 0 0;\n  padding: 4px;\n  overflow: hidden;\n  opacity: 0.45;\n  background-color: rgba(0, 0, 0, 0.8);\n  cursor: pointer;\n  text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3);\n  font-size: 0;\n  border-radius: 50%;\n  text-align: center;\n  color: #fff;\n  -webkit-transition: all .3s ease;\n  transition: all .3s ease;\n}\n.am-slider-b4 .am-direction-nav a:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f053\";\n  font-size: 20px;\n  line-height: 24px;\n}\n.am-slider-b4 .am-direction-nav a.am-prev {\n  left: -15px;\n}\n.am-slider-b4 .am-direction-nav a.am-next {\n  right: -15px;\n}\n.am-slider-b4 .am-direction-nav a.am-next:before {\n  content: \"\\f054\";\n}\n.am-slider-b4 .am-direction-nav .am-disabled {\n  opacity: 0!important;\n  cursor: default;\n}\n.am-slider-b4:hover .am-prev {\n  opacity: 0.7;\n}\n.am-slider-b4:hover .am-prev:hover {\n  opacity: 0.9;\n}\n.am-slider-b4:hover .am-next {\n  opacity: 0.7;\n}\n.am-slider-b4:hover .am-next:hover {\n  opacity: 0.9;\n}\n.am-slider-b4 .am-control-nav,\n.am-slider-b4 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: c1\n  */\n.am-slider-c1 {\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Control Nav */\n}\n.am-slider-c1 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-c1 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-c1 .am-control-nav {\n  position: absolute;\n  bottom: 0;\n  display: table;\n  width: 100%;\n  height: 6px;\n  font-size: 0;\n  line-height: 0;\n  text-align: center;\n}\n.am-slider-c1 .am-control-nav li {\n  display: table-cell;\n  width: 1%;\n}\n.am-slider-c1 .am-control-nav li a {\n  width: 100%;\n  height: 6px;\n  display: block;\n  background-color: rgba(0, 0, 0, 0.7);\n  cursor: pointer;\n  text-indent: -9999px;\n}\n.am-slider-c1 .am-control-nav li a:hover {\n  background: rgba(0, 0, 0, 0.8);\n}\n.am-slider-c1 .am-control-nav li a.am-active {\n  background-color: #0e90d2;\n  cursor: default;\n}\n.am-slider-c1 .am-slider-desc {\n  background-color: rgba(0, 0, 0, 0.6);\n  position: absolute;\n  bottom: 6px;\n  padding: 8px;\n  width: 100%;\n  color: #fff;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-slider-c1 .am-direction-nav,\n.am-slider-c1 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: c2\n  */\n.am-slider-c2 {\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Control Nav */\n}\n.am-slider-c2 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-c2 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-c2 .am-control-nav {\n  position: absolute;\n  bottom: 15px;\n  right: 0;\n  height: 6px;\n  text-align: center;\n  font-size: 0;\n  line-height: 0;\n}\n.am-slider-c2 .am-control-nav li {\n  display: inline-block;\n  margin-right: 6px;\n}\n.am-slider-c2 .am-control-nav li a {\n  width: 6px;\n  height: 6px;\n  display: block;\n  background-color: rgba(255, 255, 255, 0.4);\n  cursor: pointer;\n  text-indent: -9999px;\n}\n.am-slider-c2 .am-control-nav li a:hover {\n  background: rgba(230, 230, 230, 0.4);\n}\n.am-slider-c2 .am-control-nav li a.am-active {\n  background-color: #0e90d2;\n  cursor: default;\n}\n.am-slider-c2 .am-slider-desc {\n  background-color: rgba(0, 0, 0, 0.6);\n  position: absolute;\n  bottom: 0;\n  padding: 8px 60px 8px 8px;\n  width: 100%;\n  color: #fff;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-slider-c2 .am-direction-nav,\n.am-slider-c2 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: c3\n  */\n.am-slider-c3 {\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Direction Nav */\n}\n.am-slider-c3 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-c3 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-c3 .am-slider-desc {\n  background-color: rgba(0, 0, 0, 0.6);\n  position: absolute;\n  bottom: 10px;\n  right: 60px;\n  height: 30px;\n  left: 0;\n  padding-right: 5px;\n  color: #fff;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-slider-c3 .am-slider-counter {\n  margin-right: 5px;\n  display: inline-block;\n  height: 30px;\n  background-color: #0e90d2;\n  width: 40px;\n  text-align: center;\n  line-height: 30px;\n  color: #eee;\n  font-size: 1rem;\n}\n.am-slider-c3 .am-slider-counter .am-active {\n  font-size: 1.8rem;\n  font-weight: bold;\n  color: #fff;\n}\n.am-slider-c3 .am-direction-nav a {\n  -webkit-box-sizing: content-box;\n          box-sizing: content-box;\n  display: block;\n  width: 24px;\n  height: 24px;\n  padding: 4px 0;\n  margin: -16px 0 0;\n  position: absolute;\n  top: 50%;\n  z-index: 10;\n  overflow: hidden;\n  opacity: 0.45;\n  cursor: pointer;\n  color: #fff;\n  text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3);\n  background-color: rgba(0, 0, 0, 0.5);\n  font-size: 0;\n  text-align: center;\n  -webkit-transition: all .3s ease;\n  transition: all .3s ease;\n}\n.am-slider-c3 .am-direction-nav a:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f053\";\n  font-size: 16px;\n  line-height: 24px;\n}\n.am-slider-c3 .am-direction-nav a.am-prev {\n  left: 0;\n  padding-right: 5px;\n}\n.am-slider-c3 .am-direction-nav a.am-next {\n  right: 0;\n  padding-left: 5px;\n}\n.am-slider-c3 .am-direction-nav a.am-next:before {\n  content: \"\\f054\";\n}\n.am-slider-c3 .am-direction-nav .am-disabled {\n  opacity: 0!important;\n  cursor: default;\n}\n.am-slider-c3:hover .am-prev {\n  opacity: 0.7;\n}\n.am-slider-c3:hover .am-prev:hover {\n  opacity: 1;\n}\n.am-slider-c3:hover .am-next {\n  opacity: 0.7;\n}\n.am-slider-c3:hover .am-next:hover {\n  opacity: 1;\n}\n.am-slider-c3 .am-control-nav,\n.am-slider-c3 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: c4\n  */\n.am-slider-c4 {\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Direction Nav */\n}\n.am-slider-c4 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-c4 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-c4 .am-slider-desc {\n  width: 100%;\n  background-color: rgba(0, 0, 0, 0.6);\n  position: absolute;\n  bottom: 0;\n  right: 0;\n  left: 0;\n  padding: 8px 40px;\n  color: #fff;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-slider-c4 .am-direction-nav a {\n  -webkit-box-sizing: content-box;\n          box-sizing: content-box;\n  display: block;\n  width: 24px;\n  height: 24px;\n  padding: 4px 0;\n  margin: 0;\n  position: absolute;\n  bottom: 4px;\n  z-index: 10;\n  overflow: hidden;\n  opacity: 0.45;\n  cursor: pointer;\n  text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3);\n  font-size: 0;\n  text-align: center;\n  color: rgba(0, 0, 0, 0.7);\n  -webkit-transition: all .3s ease;\n  transition: all .3s ease;\n}\n.am-slider-c4 .am-direction-nav a:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f053\";\n  font-size: 24px;\n}\n.am-slider-c4 .am-direction-nav a.am-prev {\n  left: 0;\n  padding-right: 5px;\n}\n.am-slider-c4 .am-direction-nav a.am-next {\n  right: 0;\n  padding-left: 5px;\n}\n.am-slider-c4 .am-direction-nav a.am-next:before {\n  content: \"\\f054\";\n}\n.am-slider-c4 .am-direction-nav .am-disabled {\n  opacity: 0!important;\n  cursor: default;\n}\n.am-slider-c4:hover .am-prev {\n  opacity: 0.7;\n}\n.am-slider-c4:hover .am-prev:hover {\n  opacity: 1;\n}\n.am-slider-c4:hover .am-next {\n  opacity: 0.7;\n}\n.am-slider-c4:hover .am-next:hover {\n  opacity: 1;\n}\n.am-slider-c4 .am-control-nav,\n.am-slider-c4 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: d1\n  */\n.am-slider-d1 {\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Direction Nav */\n}\n.am-slider-d1 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-d1 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-d1 .am-slider-desc {\n  padding: 8px 35px;\n  width: 100%;\n  color: #fff;\n  background-color: #0e90d2;\n}\n.am-slider-d1 .am-slider-title {\n  font-weight: normal;\n  margin-bottom: 2px;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-slider-d1 .am-slider-more {\n  color: #eeeeee;\n  font-size: 1.3rem;\n}\n.am-slider-d1 .am-direction-nav a {\n  -webkit-box-sizing: content-box;\n          box-sizing: content-box;\n  display: block;\n  width: 24px;\n  height: 24px;\n  margin: 0;\n  position: absolute;\n  bottom: 18px;\n  z-index: 10;\n  overflow: hidden;\n  opacity: 0.45;\n  cursor: pointer;\n  text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3);\n  font-size: 0;\n  text-align: center;\n  border: 1px solid rgba(255, 255, 255, 0.9);\n  color: rgba(255, 255, 255, 0.9);\n  border-radius: 50%;\n  -webkit-transition: all 03s ease;\n  transition: all 03s ease;\n}\n.am-slider-d1 .am-direction-nav a:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f053\";\n  font-size: 16px;\n  line-height: 24px;\n}\n.am-slider-d1 .am-direction-nav a.am-prev {\n  left: 5px;\n}\n.am-slider-d1 .am-direction-nav a.am-next {\n  right: 5px;\n}\n.am-slider-d1 .am-direction-nav a.am-next:before {\n  content: \"\\f054\";\n}\n.am-slider-d1 .am-direction-nav .am-disabled {\n  opacity: 0!important;\n  cursor: default;\n}\n.am-slider-d1:hover .am-prev {\n  opacity: 0.7;\n}\n.am-slider-d1:hover .am-prev:hover {\n  opacity: 1;\n}\n.am-slider-d1:hover .am-next {\n  opacity: 0.7;\n}\n.am-slider-d1:hover .am-next:hover {\n  opacity: 1;\n}\n.am-slider-d1 .am-control-nav,\n.am-slider-d1 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: d2\n  */\n.am-slider-d2 {\n  margin-bottom: 20px;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Control Nav */\n}\n.am-slider-d2 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-d2 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-d2 .am-slider-desc {\n  position: absolute;\n  left: 10px;\n  bottom: 20px;\n  right: 50px;\n  color: #fff;\n}\n.am-slider-d2 .am-slider-content {\n  background-color: rgba(0, 0, 0, 0.7);\n  padding: 10px 6px;\n  margin-bottom: 10px;\n}\n.am-slider-d2 .am-slider-content p {\n  margin: 0;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n  font-size: 1.4rem;\n}\n.am-slider-d2 .am-slider-title {\n  font-weight: normal;\n  margin-bottom: 5px;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-slider-d2 .am-slider-more {\n  color: #eeeeee;\n  font-size: 1.3rem;\n  background-color: #0e90d2;\n  padding: 2px 10px;\n}\n.am-slider-d2 .am-control-nav {\n  width: 100%;\n  position: absolute;\n  bottom: -15px;\n  text-align: center;\n}\n.am-slider-d2 .am-control-nav li {\n  margin: 0 6px;\n  display: inline-block;\n}\n.am-slider-d2 .am-control-nav li a {\n  width: 8px;\n  height: 8px;\n  display: block;\n  background-color: rgba(0, 0, 0, 0.5);\n  cursor: pointer;\n  text-indent: -9999px;\n  border-radius: 50%;\n  font-size: 0;\n  line-height: 0;\n  -webkit-box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);\n          box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);\n}\n.am-slider-d2 .am-control-nav li a:hover {\n  background: rgba(0, 0, 0, 0.5);\n}\n.am-slider-d2 .am-control-nav li a.am-active {\n  background: #0e90d2;\n  cursor: default;\n}\n.am-slider-d2 .am-direction-nav,\n.am-slider-d2 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: d3\n  */\n.am-slider-d3 {\n  margin-bottom: 10px;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Control Nav */\n}\n.am-slider-d3 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-d3 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-d3 .am-slider-desc {\n  position: absolute;\n  bottom: 0;\n  color: #fff;\n  width: 100%;\n  background-color: rgba(0, 0, 0, 0.7);\n  padding: 8px 5px;\n}\n.am-slider-d3 .am-slider-desc p {\n  margin: 0;\n  font-size: 1.3rem;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-slider-d3 .am-slider-title {\n  font-weight: normal;\n  margin-bottom: 5px;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-slider-d3 .am-control-thumbs {\n  position: static;\n  overflow: hidden;\n}\n.am-slider-d3 .am-control-thumbs li {\n  padding: 12px 4px 4px;\n  position: relative;\n}\n.am-slider-d3 .am-control-thumbs img {\n  width: 100%;\n  display: block;\n  opacity: .85;\n  cursor: pointer;\n}\n.am-slider-d3 .am-control-thumbs img:hover {\n  opacity: 1;\n}\n.am-slider-d3 .am-control-thumbs .am-active {\n  opacity: 1;\n  cursor: default;\n}\n.am-slider-d3 .am-control-thumbs .am-active + i {\n  position: absolute;\n  top: 0;\n  left: 50%;\n  content: \"\";\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: middle;\n  border-top: 8px solid rgba(0, 0, 0, 0.7);\n  border-right: 8px solid transparent;\n  border-left: 8px solid transparent;\n  border-bottom: 0 dotted;\n  -webkit-transform: rotate(360deg);\n      -ms-transform: rotate(360deg);\n          transform: rotate(360deg);\n  margin-left: -4px;\n  -webkit-transition: all 0.2s;\n  transition: all 0.2s;\n}\n.am-slider-d3 .am-direction-nav,\n.am-slider-d3 .am-pauseplay {\n  display: none;\n}\n.am-slider-d3 .am-control-thumbs {\n  display: table;\n}\n.am-slider-d3 .am-control-thumbs li {\n  display: table-cell;\n  width: 1%;\n}\n[data-am-widget='tabs'] {\n  margin: 10px;\n}\n[data-am-widget='tabs'] .am-tabs-nav {\n  width: 100%;\n  padding: 0;\n  margin: 0;\n  list-style: none;\n  text-align: center;\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -ms-flexbox;\n  display: flex;\n}\n[data-am-widget='tabs'] .am-tabs-nav li {\n  -webkit-box-flex: 1;\n  -webkit-flex: 1;\n      -ms-flex: 1;\n          flex: 1;\n}\n[data-am-widget='tabs'] .am-tabs-nav a {\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n/**\n  * Tabs Theme: default\n  */\n.am-tabs-default .am-tabs-nav {\n  line-height: 40px;\n  background-color: #eeeeee;\n}\n.am-tabs-default .am-tabs-nav a {\n  color: #222222;\n  line-height: 42px;\n}\n.am-tabs-default .am-tabs-nav > .am-active a {\n  background-color: #0e90d2;\n  color: #fff;\n}\n/**\n  * Tabs Theme: d2\n  */\n.am-tabs-d2 .am-tabs-nav {\n  background-color: #eeeeee;\n}\n.am-tabs-d2 .am-tabs-nav li {\n  height: 42px;\n}\n.am-tabs-d2 .am-tabs-nav a {\n  color: #222222;\n  line-height: 42px;\n}\n.am-tabs-d2 .am-tabs-nav > .am-active {\n  position: relative;\n  background-color: #fcfcfc;\n  border-bottom: 2px solid #0e90d2;\n}\n.am-tabs-d2 .am-tabs-nav > .am-active a {\n  line-height: 40px;\n  color: #0e90d2;\n}\n.am-tabs-d2 .am-tabs-nav > .am-active:after {\n  position: absolute;\n  width: 0;\n  height: 0;\n  bottom: 0px;\n  left: 50%;\n  margin-left: -5px;\n  border: 6px rgba(0, 0, 0, 0) solid;\n  content: \"\";\n  z-index: 1;\n  border-bottom-color: #0e90d2;\n}\n.am-titlebar {\n  margin-top: 20px;\n  height: 45px;\n  font-size: 100%;\n}\n.am-titlebar h2 {\n  margin-top: 0;\n  margin-bottom: 0;\n  font-size: 1.6rem;\n}\n.am-titlebar .am-titlebar-title img {\n  height: 24px;\n  width: auto;\n}\n/**\n  * Titlebar Theme: default\n  */\n.am-titlebar-default {\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -ms-flexbox;\n  display: flex;\n  margin-left: 10px;\n  margin-right: 10px;\n  background-color: transparent;\n  border-bottom: 1px solid #dedede;\n  line-height: 44px;\n}\n.am-titlebar-default a {\n  color: #0e90d2;\n}\n.am-titlebar-default .am-titlebar-title {\n  position: relative;\n  padding-left: 12px;\n  color: #0e90d2;\n  font-size: 1.8rem;\n  text-align: left;\n  font-weight: bold;\n}\n.am-titlebar-default .am-titlebar-title:before {\n  content: \"\";\n  position: absolute;\n  left: 2px;\n  top: 8px;\n  bottom: 8px;\n  border-left: 3px solid #0e90d2;\n}\n.am-titlebar-default .am-titlebar-nav {\n  -webkit-box-flex: 1;\n  -webkit-flex: 1;\n      -ms-flex: 1;\n          flex: 1;\n  text-align: right;\n}\n.am-titlebar-default .am-titlebar-nav a {\n  margin-right: 10px;\n}\n.am-titlebar-default .am-titlebar-nav a:last-child {\n  margin-right: 5px;\n}\n/**\n  * Titlebar Theme: multi\n  */\n.am-titlebar-multi {\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -ms-flexbox;\n  display: flex;\n  background-color: #f5f5f5;\n  border-top: 2px solid #3bb4f2;\n  border-bottom: 1px solid #e8e8e8;\n}\n.am-titlebar-multi a {\n  color: #0e90d2;\n}\n.am-titlebar-multi .am-titlebar-title {\n  padding-left: 10px;\n  color: #0e90d2;\n  font-size: 1.8rem;\n  text-align: left;\n  font-weight: bold;\n  line-height: 42px;\n}\n.am-titlebar-multi .am-titlebar-nav {\n  -webkit-box-flex: 1;\n  -webkit-flex: 1;\n      -ms-flex: 1;\n          flex: 1;\n  text-align: right;\n  line-height: 42px;\n}\n.am-titlebar-multi .am-titlebar-nav a {\n  margin-right: 10px;\n}\n/**\n  * Titlebar Theme: cols\n  */\n.am-titlebar-cols {\n  position: relative;\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -ms-flexbox;\n  display: flex;\n  padding-left: 10px;\n  background-color: #f5f5f5;\n  color: #555555;\n  font-size: 18px;\n  border-top: 2px solid #e1e1e1;\n  line-height: 41px;\n}\n.am-titlebar-cols a {\n  color: #555555;\n}\n.am-titlebar-cols .am-titlebar-title {\n  color: #0e90d2;\n  margin-right: 15px;\n  border-bottom: 2px solid #0e90d2;\n  font-weight: bold;\n}\n.am-titlebar-cols .am-titlebar-title a {\n  color: #0e90d2;\n}\n.am-titlebar-cols .am-titlebar-nav {\n  -webkit-box-flex: 1;\n  -webkit-flex: 1;\n      -ms-flex: 1;\n          flex: 1;\n}\n.am-titlebar-cols .am-titlebar-nav a {\n  display: inline-block;\n  margin-right: 15px;\n  line-height: 41px;\n  border-bottom: 2px solid transparent;\n}\n.am-titlebar-cols .am-titlebar-nav a:hover {\n  color: #3c3c3c;\n  border-bottom-color: #0e90d2;\n}\n.am-titlebar-cols .am-titlebar-nav a:last-child {\n  margin-right: 10px;\n}\n.am-wechatpay .am-wechatpay-btn {\n  margin-top: 1rem;\n  margin-bottom: 1rem;\n}\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/assets/css/amazeui.flat.css",
    "content": "/*! Amaze UI v2.6.0 | by Amaze UI Team | (c) 2016 AllMobilize, Inc. | Licensed under MIT | 2016-03-31T14:28:54+0800 */\n/* ==========================================================================\n   Component: Base\n ============================================================================ */\n/**\n * Fix the flawed CSS box model - Yes, IE6's box model is better\n * Browser support: IE8+\n * via: http://paulirish.com/2012/box-sizing-border-box-ftw/\n */\n*,\n*:before,\n*:after {\n  -webkit-box-sizing: border-box;\n          box-sizing: border-box;\n}\n/* normalize.css v3.0.2 | git.io/normalize */\n/* Set <html> and <body> to inherit the height of the viewport */\nhtml,\nbody {\n  min-height: 100%;\n}\n/**\n * 1. Prevent iOS text size adjust after orientation change, without disabling\n *    user zoom.\n *    https://developer.mozilla.org/en-US/docs/Web/CSS/text-size-adjust\n */\nhtml {\n  -ms-text-size-adjust: 100%;\n  /* 1 */\n  -webkit-text-size-adjust: 100%;\n  /* 1 */\n}\n/**\n * Remove default margin.\n */\nbody {\n  margin: 0;\n}\n/* HTML5 display definitions\n   ========================================================================== */\n/**\n * Correct `block` display not defined for any HTML5 element in IE 8/9.\n * Correct `block` display not defined for `details` or `summary` in IE 10/11 and Firefox.\n * Correct `block` display not defined for `main` in IE 11.\n * hgroup has been removed from the HTML5 (W3C) specification\n *        https://developer.mozilla.org/en-US/docs/Web/HTML/Element/hgroup\n */\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmenu,\nmain,\nnav,\nsection,\nsummary {\n  display: block;\n}\n/**\n * 1. Correct `inline-block` display not defined in IE 8/9.\n * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.\n */\naudio,\ncanvas,\nprogress,\nvideo {\n  display: inline-block;\n  /* 1 */\n  vertical-align: baseline;\n  /* 2 */\n}\n/**\n * Prevent modern browsers from displaying `audio` without controls.\n * Remove excess height in iOS 5 devices.\n */\naudio:not([controls]) {\n  display: none;\n  height: 0;\n}\n/**\n * Address `[hidden]` styling not present in IE 8/9/10.\n * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.\n */\n[hidden],\ntemplate,\nscript {\n  display: none;\n}\n/* Links\n   ========================================================================== */\n/**\n * Remove the gray background color from active links in IE 10.\n */\na {\n  background-color: transparent;\n}\n/**\n * Address `outline` inconsistency between Chrome and other browsers.\n */\na:focus {\n  outline: thin dotted;\n}\n/**\n * Improve readability when focused and also mouse hovered in all browsers.\n */\na:active,\na:hover {\n  outline: 0;\n}\n/* Text-level semantics\n   ========================================================================== */\n/**\n * Remove text-decoration\n */\nins,\na {\n  text-decoration: none;\n}\n/**\n * Address styling not present in IE 8/9, Safari 5, and Chrome.\n */\nabbr[title] {\n  border-bottom: 1px dotted;\n}\n/**\n * Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome.\n */\nb,\nstrong {\n  font-weight: bold;\n}\n/**\n * Improve readability of pre-formatted text in all browsers.\n */\npre {\n  white-space: pre-wrap;\n}\n/**\n * Set consistent quote types.\n */\nq {\n  quotes: \"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\";\n}\n/**\n * Address inconsistent and variable font size in all browsers.\n */\nsmall {\n  font-size: 80%;\n}\n/**\n * Prevent `sub` and `sup` affecting `line-height` in all browsers.\n */\nsub,\nsup {\n  font-size: 75%;\n  line-height: 0;\n  position: relative;\n  vertical-align: baseline;\n}\nsup {\n  top: -0.5em;\n}\nsub {\n  bottom: -0.25em;\n}\n/* Embedded content\n   ========================================================================== */\n/**\n  * 1. Corrects max-width behavior (2.) if padding and border are used\n  * 2. Responsiveness: Sets a maxium width relative to the parent and auto scales the height\n  * 3. Remove the gap between images and the bottom of their containers\n  * 4. Remove border when inside `a` element in IE 8/9.\n  * remove 2. for Issue #502\n  */\nimg {\n  -webkit-box-sizing: border-box;\n          box-sizing: border-box;\n  /* 1 */\n  vertical-align: middle;\n  /* 3 */\n  border: 0;\n  /* 4 */\n}\n/**\n * Correct overflow displayed oddly in IE 9.\n */\nsvg:not(:root) {\n  overflow: hidden;\n}\n/* Grouping content\n   ========================================================================== */\n/**\n * Address margin not present in IE 8/9 and Safari.\n */\nfigure {\n  margin: 0;\n}\n/**\n * Correct font family set oddly in Safari 5 and Chrome.\n */\ncode,\nkbd,\npre,\nsamp {\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", \"FontAwesome\", monospace;\n  font-size: 1em;\n}\n/* Forms\n   ========================================================================== */\n/**\n * Define consistent border, margin, and padding.\n */\nfieldset {\n  border: 1px solid #c0c0c0;\n  margin: 0 2px;\n  padding: 0.35em 0.625em 0.75em;\n}\n/**\n * 1. Correct `color` not being inherited in IE 8/9.\n * 2. Remove padding so people aren't caught out if they zero out fieldsets.\n */\nlegend {\n  border: 0;\n  /* 1 */\n  padding: 0;\n  /* 2 */\n}\n/**\n * 1. Correct color not being inherited.\n *    Known issue: affects color of disabled elements.\n * 2. Correct font properties not being inherited.\n * 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome.\n */\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n  color: inherit;\n  /* 1 */\n  font: inherit;\n  /* 2 */\n  margin: 0;\n  /* 3 */\n}\n/**\n * Address `overflow` set to `hidden` in IE 8/9/10/11.\n */\nbutton {\n  overflow: visible;\n}\n/**\n * Address Firefox 4+ setting `line-height` on `input` using `!important` in\n * the UA stylesheet.\n */\nbutton,\ninput {\n  line-height: normal;\n}\n/**\n * Address inconsistent `text-transform` inheritance for `button` and `select`.\n * All other form control elements do not inherit `text-transform` values.\n * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.\n * Correct `select` style inheritance in Firefox.\n */\nbutton,\nselect {\n  text-transform: none;\n}\n/**\n * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`\n *    and `video` controls.\n * 2. Correct inability to style clickable `input` types in iOS.\n * 3. Improve usability and consistency of cursor style between image-type\n *    `input` and others.\n */\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  -webkit-appearance: button;\n  /* 2 */\n  cursor: pointer;\n  /* 3 */\n}\n/*\n * 1. Improves consistency of cursor style for clickable elements\n * 2. Removes excess padding in IE 8/9.\n * 3. Address box sizing set to `content-box` in IE 8/9/10.\n */\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n  /*1*/\n  padding: 0;\n  /*2*/\n  -webkit-box-sizing: border-box;\n          box-sizing: border-box;\n  /* 3 */\n}\n/**\n * Re-set default cursor for disabled elements.\n */\nbutton[disabled],\nhtml input[disabled] {\n  cursor: default;\n}\n/**\n * Remove inner padding and border in Firefox 4+.\n */\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  border: 0;\n  padding: 0;\n}\n/**\n * Fix the cursor style for Chrome's increment/decrement buttons. For certain\n * `font-size` values of the `input`, it causes the cursor style of the\n * decrement button to change from `default` to `text`.\n */\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n  height: auto;\n}\n/**\n * 1. Address `appearance` set to `searchfield` in Safari and Chrome.\n * 2. Address `box-sizing` set to `border-box` in Safari and Chrome\n *    (include `-moz` to future-proof).\n */\ninput[type=\"search\"] {\n  -webkit-appearance: textfield;\n  /* 1 */\n  -webkit-box-sizing: content-box;\n          box-sizing: content-box;\n  /* 2 */\n}\n/**\n * Remove inner padding and search cancel button in Safari 5 and Chrome\n * on OS X.\n */\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n  -webkit-appearance: none;\n}\n/**\n * 1. Remove default vertical scrollbar in IE 8/9.\n * 2. Improve readability and alignment in all browsers.\n */\ntextarea {\n  overflow: auto;\n  /* 1 */\n  vertical-align: top;\n  /* 2 */\n  resize: vertical;\n}\n/**\n * Don't inherit the `font-weight` (applied by a rule above).\n * NOTE: the default cannot safely be changed in Chrome and Safari on OS X.\n */\noptgroup {\n  font-weight: bold;\n}\n/* Tables\n   ========================================================================== */\n/**\n * Remove most spacing between table cells.\n */\ntable {\n  border-collapse: collapse;\n  border-spacing: 0;\n}\ntd,\nth {\n  padding: 0;\n}\n/* AMUI Base\n   ========================================================================== */\n/**\n * `font-size` is set in `html` element to support the `rem` unit for font-sizes\n * NOTE: IE9 & IE10 do not recognize `rem` units when used with the\n   `font` shorthand property.\n */\nhtml {\n  font-size: 10px;\n  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\nbody {\n  position: relative;\n  background: #fff;\n  font-family: \"Segoe UI\", \"Lucida Grande\", Helvetica, Arial, \"Microsoft YaHei\", FreeSans, Arimo, \"Droid Sans\", \"wenquanyi micro hei\", \"Hiragino Sans GB\", \"Hiragino Sans GB W3\", \"FontAwesome\", sans-serif;\n  font-weight: normal;\n  line-height: 1.6;\n  color: #333333;\n  font-size: 1.6rem;\n}\n/**\n * 1. http://usabilitypost.com/2012/11/15/w-optimizelegibility-on-mobile-devices/\n * 2. http://maxvoltar.com/archive/-webkit-font-smoothing\n * NOTE: http://usabilitypost.com/2012/11/05/stop-fixing-font-smoothing/\n * 3. http://maximilianhoffmann.com/posts/better-font-rendering-on-osx\n *    http://jaydenseric.com/blog/css-font-smoothing-for-firefox-mac\n */\nbody,\ninput,\ntextarea,\nselect,\nbutton {\n  text-rendering: optimizeLegibility;\n  /* 1 */\n  -webkit-font-smoothing: antialiased;\n  /* 2 */\n  -moz-osx-font-smoothing: grayscale;\n  /* 3 Default: auto */\n  -moz-font-feature-settings: \"liga\", \"kern\";\n}\n/*Only phones */\n@media only screen and (max-width: 640px) {\n  /**\n   * Break strings if their length exceeds the width of their container\n   */\n  body {\n    word-wrap: break-word;\n    -webkit-hyphens: auto;\n    -ms-hyphens: auto;\n    -moz-hyphens: auto;\n    hyphens: auto;\n  }\n}\n/**\n * links\n */\na {\n  color: #0e90d2;\n}\na:hover,\na:focus {\n  color: #095f8a;\n}\na:focus {\n  outline: thin dotted;\n  outline: 1px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n/* Insert */\nins {\n  background: #ffa;\n  color: #333333;\n}\n/**\n * Mark\n * Note: Addresses styling not present in IE 8/9.\n */\nmark {\n  background: #ffa;\n  color: #333333;\n}\n/**\n * Abbreviation and definition\n */\nabbr[title],\ndfn[title] {\n  cursor: help;\n}\ndfn[title] {\n  border-bottom: 1px dotted;\n  font-style: normal;\n}\n/* Spacing for block elements */\np,\nhr,\nul,\nol,\ndl,\nblockquote,\npre,\naddress,\nfieldset,\nfigure {\n  margin: 0 0 1.6rem 0;\n}\n* + p,\n* + hr,\n* + ul,\n* + ol,\n* + dl,\n* + blockquote,\n* + pre,\n* + address,\n* + fieldset,\n* + figure {\n  margin-top: 1.6rem;\n}\n/* Headings\n   ========================================================================== */\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 0 0 1.6rem 0;\n  font-weight: 600;\n  font-size: 100%;\n}\nh1 {\n  font-size: 1.5em;\n}\nh2 {\n  font-size: 1.25em;\n}\n* + h1,\n* + h2,\n* + h3,\n* + h4,\n* + h5,\n* + h6 {\n  margin-top: 2em;\n}\n/* Ordered and unordered lists */\nul,\nol {\n  padding-left: 2em;\n}\n/* Reset margin for nested lists */\nul > li > ul,\nul > li > ol,\nol > li > ol,\nol > li > ul {\n  margin: 1em 0;\n}\n/* Description lists */\ndt {\n  font-weight: bold;\n}\ndt + dd {\n  margin-top: .5em;\n}\ndd {\n  margin-left: 0;\n}\ndd + dt {\n  margin-top: 1em;\n}\n/**\n * Horizontal rule\n * 1. Address differences between Firefox and other browsers.\n */\nhr {\n  display: block;\n  padding: 0;\n  border: 0;\n  height: 0;\n  border-top: 1px solid #eeeeee;\n  /* 1 */\n  -webkit-box-sizing: content-box;\n          box-sizing: content-box;\n  /* 1 */\n}\n/* Address */\naddress {\n  font-style: normal;\n}\n/* Quotes */\nblockquote {\n  padding-top: 5px;\n  padding-bottom: 5px;\n  padding-left: 15px;\n  border-left: 4px solid #ddd;\n  font-family: Georgia, \"Times New Roman\", Times, Kai, \"Kaiti SC\", KaiTi, BiauKai, \"FontAwesome\", serif;\n  /* Small print for identifying the source */\n  /* Smaller margin if `small` follows */\n}\nblockquote small {\n  display: block;\n  color: #999999;\n  font-family: \"Segoe UI\", \"Lucida Grande\", Helvetica, Arial, \"Microsoft YaHei\", FreeSans, Arimo, \"Droid Sans\", \"wenquanyi micro hei\", \"Hiragino Sans GB\", \"Hiragino Sans GB W3\", \"FontAwesome\", sans-serif;\n  text-align: right;\n}\nblockquote p:last-of-type {\n  margin-bottom: 0;\n}\n/* iframe */\niframe {\n  border: 0;\n}\n/* Forms\n   ========================================================================== */\n/**\n  * Vertical alignment\n  * Exclude `radio` and `checkbox` elements because the default `baseline` value aligns better with text\n  */\nbutton,\ninput:not([type=\"radio\"]):not([type=\"checkbox\"]),\nselect {\n  vertical-align: middle;\n}\n/**\n * Fix viewport for IE10 snap mode\n * http://timkadlec.com/2012/10/ie10-snap-mode-and-responsive-design/\n * http://msdn.microsoft.com/en-us/library/ie/hh869615%28v=vs.85%29.aspx\n * http://msdn.microsoft.com/zh-cn/library/ie/hh708740(v=vs.85).aspx\n * @2014.01.20: 设置一下属性以后，windows Phone 8 上显示的字体过小，暂时注释掉\n * ========================================================================== */\n/*\n@-ms-viewport {\n  width: device-width;\n}\n*/\n.am-scrollbar-measure {\n  width: 100px;\n  height: 100px;\n  overflow: scroll;\n  position: absolute;\n  top: -9999px;\n}\n/* ==========================================================================\n   Component: Grid\n ============================================================================ */\n.am-container {\n  -webkit-box-sizing: border-box;\n          box-sizing: border-box;\n  margin-left: auto;\n  margin-right: auto;\n  padding-left: 1rem;\n  padding-right: 1rem;\n  width: 100%;\n  max-width: 1000px;\n}\n.am-container:before,\n.am-container:after {\n  content: \" \";\n  display: table;\n}\n.am-container:after {\n  clear: both;\n}\n@media only screen and (min-width:641px) {\n  .am-container {\n    padding-left: 1.5rem;\n    padding-right: 1.5rem;\n  }\n}\n.am-container > .am-g {\n  width: auto;\n  margin-left: -1rem;\n  margin-right: -1rem;\n}\n@media only screen and (min-width:641px) {\n  .am-container > .am-g {\n    margin-left: -1.5rem;\n    margin-right: -1.5rem;\n  }\n}\n.am-g {\n  margin: 0 auto;\n  width: 100%;\n}\n.am-g:before,\n.am-g:after {\n  content: \" \";\n  display: table;\n}\n.am-g:after {\n  clear: both;\n}\n.am-g .am-g {\n  margin-left: -1rem;\n  margin-right: -1rem;\n  width: auto;\n}\n.am-g .am-g.am-g-collapse {\n  margin-left: 0;\n  margin-right: 0;\n  width: auto;\n}\n@media only screen and (min-width:641px) {\n  .am-g .am-g {\n    margin-left: -1.5rem;\n    margin-right: -1.5rem;\n  }\n}\n.am-g.am-g-collapse .am-g {\n  margin-left: 0;\n  margin-right: 0;\n}\n.am-g-collapse [class*=\"am-u-\"] {\n  padding-left: 0;\n  padding-right: 0;\n}\n.am-g-fixed {\n  max-width: 1000px;\n}\n[class*=\"am-u-\"] {\n  width: 100%;\n  padding-left: 1rem;\n  padding-right: 1rem;\n  float: left;\n  position: relative;\n}\n[class*=\"am-u-\"] + [class*=\"am-u-\"]:last-child {\n  float: right;\n}\n[class*=\"am-u-\"] + [class*=\"am-u-\"].am-u-end {\n  float: left;\n}\n@media only screen and (min-width:641px) {\n  [class*=\"am-u-\"] {\n    padding-left: 1.5rem;\n    padding-right: 1.5rem;\n  }\n}\n[class*=\"am-u-pull-\"] {\n  left: auto;\n}\n[class*=\"am-u-push-\"] {\n  right: auto;\n}\n@media only screen {\n  .am-u-sm-1 {\n    width: 8.33333333%;\n  }\n  .am-u-sm-2 {\n    width: 16.66666667%;\n  }\n  .am-u-sm-3 {\n    width: 25%;\n  }\n  .am-u-sm-4 {\n    width: 33.33333333%;\n  }\n  .am-u-sm-5 {\n    width: 41.66666667%;\n  }\n  .am-u-sm-6 {\n    width: 50%;\n  }\n  .am-u-sm-7 {\n    width: 58.33333333%;\n  }\n  .am-u-sm-8 {\n    width: 66.66666667%;\n  }\n  .am-u-sm-9 {\n    width: 75%;\n  }\n  .am-u-sm-10 {\n    width: 83.33333333%;\n  }\n  .am-u-sm-11 {\n    width: 91.66666667%;\n  }\n  .am-u-sm-12 {\n    width: 100%;\n  }\n  .am-u-sm-pull-0 {\n    right: 0;\n  }\n  .am-u-sm-pull-1 {\n    right: 8.33333333%;\n  }\n  .am-u-sm-pull-2 {\n    right: 16.66666667%;\n  }\n  .am-u-sm-pull-3 {\n    right: 25%;\n  }\n  .am-u-sm-pull-4 {\n    right: 33.33333333%;\n  }\n  .am-u-sm-pull-5 {\n    right: 41.66666667%;\n  }\n  .am-u-sm-pull-6 {\n    right: 50%;\n  }\n  .am-u-sm-pull-7 {\n    right: 58.33333333%;\n  }\n  .am-u-sm-pull-8 {\n    right: 66.66666667%;\n  }\n  .am-u-sm-pull-9 {\n    right: 75%;\n  }\n  .am-u-sm-pull-10 {\n    right: 83.33333333%;\n  }\n  .am-u-sm-pull-11 {\n    right: 91.66666667%;\n  }\n  .am-u-sm-push-0 {\n    left: 0;\n  }\n  .am-u-sm-push-1 {\n    left: 8.33333333%;\n  }\n  .am-u-sm-push-2 {\n    left: 16.66666667%;\n  }\n  .am-u-sm-push-3 {\n    left: 25%;\n  }\n  .am-u-sm-push-4 {\n    left: 33.33333333%;\n  }\n  .am-u-sm-push-5 {\n    left: 41.66666667%;\n  }\n  .am-u-sm-push-6 {\n    left: 50%;\n  }\n  .am-u-sm-push-7 {\n    left: 58.33333333%;\n  }\n  .am-u-sm-push-8 {\n    left: 66.66666667%;\n  }\n  .am-u-sm-push-9 {\n    left: 75%;\n  }\n  .am-u-sm-push-10 {\n    left: 83.33333333%;\n  }\n  .am-u-sm-push-11 {\n    left: 91.66666667%;\n  }\n  .am-u-sm-offset-0 {\n    margin-left: 0;\n  }\n  .am-u-sm-offset-1 {\n    margin-left: 8.33333333%;\n  }\n  .am-u-sm-offset-2 {\n    margin-left: 16.66666667%;\n  }\n  .am-u-sm-offset-3 {\n    margin-left: 25%;\n  }\n  .am-u-sm-offset-4 {\n    margin-left: 33.33333333%;\n  }\n  .am-u-sm-offset-5 {\n    margin-left: 41.66666667%;\n  }\n  .am-u-sm-offset-6 {\n    margin-left: 50%;\n  }\n  .am-u-sm-offset-7 {\n    margin-left: 58.33333333%;\n  }\n  .am-u-sm-offset-8 {\n    margin-left: 66.66666667%;\n  }\n  .am-u-sm-offset-9 {\n    margin-left: 75%;\n  }\n  .am-u-sm-offset-10 {\n    margin-left: 83.33333333%;\n  }\n  .am-u-sm-offset-11 {\n    margin-left: 91.66666667%;\n  }\n  .am-u-sm-reset-order {\n    margin-left: 0;\n    margin-right: 0;\n    left: auto;\n    right: auto;\n    float: left;\n  }\n  [class*=\"am-u-\"].am-u-sm-centered {\n    margin-left: auto;\n    margin-right: auto;\n    float: none;\n  }\n  [class*=\"am-u-\"].am-u-sm-centered:last-child {\n    float: none;\n  }\n  [class*=\"am-u-\"].am-u-sm-uncentered {\n    margin-left: 0;\n    margin-right: 0;\n    float: left;\n  }\n  [class*=\"am-u-\"].am-u-sm-uncentered:last-child {\n    float: left;\n  }\n}\n@media only screen and (min-width:641px) {\n  .am-u-md-1 {\n    width: 8.33333333%;\n  }\n  .am-u-md-2 {\n    width: 16.66666667%;\n  }\n  .am-u-md-3 {\n    width: 25%;\n  }\n  .am-u-md-4 {\n    width: 33.33333333%;\n  }\n  .am-u-md-5 {\n    width: 41.66666667%;\n  }\n  .am-u-md-6 {\n    width: 50%;\n  }\n  .am-u-md-7 {\n    width: 58.33333333%;\n  }\n  .am-u-md-8 {\n    width: 66.66666667%;\n  }\n  .am-u-md-9 {\n    width: 75%;\n  }\n  .am-u-md-10 {\n    width: 83.33333333%;\n  }\n  .am-u-md-11 {\n    width: 91.66666667%;\n  }\n  .am-u-md-12 {\n    width: 100%;\n  }\n  .am-u-md-pull-0 {\n    right: 0;\n  }\n  .am-u-md-pull-1 {\n    right: 8.33333333%;\n  }\n  .am-u-md-pull-2 {\n    right: 16.66666667%;\n  }\n  .am-u-md-pull-3 {\n    right: 25%;\n  }\n  .am-u-md-pull-4 {\n    right: 33.33333333%;\n  }\n  .am-u-md-pull-5 {\n    right: 41.66666667%;\n  }\n  .am-u-md-pull-6 {\n    right: 50%;\n  }\n  .am-u-md-pull-7 {\n    right: 58.33333333%;\n  }\n  .am-u-md-pull-8 {\n    right: 66.66666667%;\n  }\n  .am-u-md-pull-9 {\n    right: 75%;\n  }\n  .am-u-md-pull-10 {\n    right: 83.33333333%;\n  }\n  .am-u-md-pull-11 {\n    right: 91.66666667%;\n  }\n  .am-u-md-push-0 {\n    left: 0;\n  }\n  .am-u-md-push-1 {\n    left: 8.33333333%;\n  }\n  .am-u-md-push-2 {\n    left: 16.66666667%;\n  }\n  .am-u-md-push-3 {\n    left: 25%;\n  }\n  .am-u-md-push-4 {\n    left: 33.33333333%;\n  }\n  .am-u-md-push-5 {\n    left: 41.66666667%;\n  }\n  .am-u-md-push-6 {\n    left: 50%;\n  }\n  .am-u-md-push-7 {\n    left: 58.33333333%;\n  }\n  .am-u-md-push-8 {\n    left: 66.66666667%;\n  }\n  .am-u-md-push-9 {\n    left: 75%;\n  }\n  .am-u-md-push-10 {\n    left: 83.33333333%;\n  }\n  .am-u-md-push-11 {\n    left: 91.66666667%;\n  }\n  .am-u-md-offset-0 {\n    margin-left: 0;\n  }\n  .am-u-md-offset-1 {\n    margin-left: 8.33333333%;\n  }\n  .am-u-md-offset-2 {\n    margin-left: 16.66666667%;\n  }\n  .am-u-md-offset-3 {\n    margin-left: 25%;\n  }\n  .am-u-md-offset-4 {\n    margin-left: 33.33333333%;\n  }\n  .am-u-md-offset-5 {\n    margin-left: 41.66666667%;\n  }\n  .am-u-md-offset-6 {\n    margin-left: 50%;\n  }\n  .am-u-md-offset-7 {\n    margin-left: 58.33333333%;\n  }\n  .am-u-md-offset-8 {\n    margin-left: 66.66666667%;\n  }\n  .am-u-md-offset-9 {\n    margin-left: 75%;\n  }\n  .am-u-md-offset-10 {\n    margin-left: 83.33333333%;\n  }\n  .am-u-md-offset-11 {\n    margin-left: 91.66666667%;\n  }\n  .am-u-md-reset-order {\n    margin-left: 0;\n    margin-right: 0;\n    left: auto;\n    right: auto;\n    float: left;\n  }\n  [class*=\"am-u-\"].am-u-md-centered {\n    margin-left: auto;\n    margin-right: auto;\n    float: none;\n  }\n  [class*=\"am-u-\"].am-u-md-centered:last-child {\n    float: none;\n  }\n  [class*=\"am-u-\"].am-u-md-uncentered {\n    margin-left: 0;\n    margin-right: 0;\n    float: left;\n  }\n  [class*=\"am-u-\"].am-u-md-uncentered:last-child {\n    float: left;\n  }\n}\n@media only screen and (min-width:1025px) {\n  .am-u-lg-1 {\n    width: 8.33333333%;\n  }\n  .am-u-lg-2 {\n    width: 16.66666667%;\n  }\n  .am-u-lg-3 {\n    width: 25%;\n  }\n  .am-u-lg-4 {\n    width: 33.33333333%;\n  }\n  .am-u-lg-5 {\n    width: 41.66666667%;\n  }\n  .am-u-lg-6 {\n    width: 50%;\n  }\n  .am-u-lg-7 {\n    width: 58.33333333%;\n  }\n  .am-u-lg-8 {\n    width: 66.66666667%;\n  }\n  .am-u-lg-9 {\n    width: 75%;\n  }\n  .am-u-lg-10 {\n    width: 83.33333333%;\n  }\n  .am-u-lg-11 {\n    width: 91.66666667%;\n  }\n  .am-u-lg-12 {\n    width: 100%;\n  }\n  .am-u-lg-pull-0 {\n    right: 0;\n  }\n  .am-u-lg-pull-1 {\n    right: 8.33333333%;\n  }\n  .am-u-lg-pull-2 {\n    right: 16.66666667%;\n  }\n  .am-u-lg-pull-3 {\n    right: 25%;\n  }\n  .am-u-lg-pull-4 {\n    right: 33.33333333%;\n  }\n  .am-u-lg-pull-5 {\n    right: 41.66666667%;\n  }\n  .am-u-lg-pull-6 {\n    right: 50%;\n  }\n  .am-u-lg-pull-7 {\n    right: 58.33333333%;\n  }\n  .am-u-lg-pull-8 {\n    right: 66.66666667%;\n  }\n  .am-u-lg-pull-9 {\n    right: 75%;\n  }\n  .am-u-lg-pull-10 {\n    right: 83.33333333%;\n  }\n  .am-u-lg-pull-11 {\n    right: 91.66666667%;\n  }\n  .am-u-lg-push-0 {\n    left: 0;\n  }\n  .am-u-lg-push-1 {\n    left: 8.33333333%;\n  }\n  .am-u-lg-push-2 {\n    left: 16.66666667%;\n  }\n  .am-u-lg-push-3 {\n    left: 25%;\n  }\n  .am-u-lg-push-4 {\n    left: 33.33333333%;\n  }\n  .am-u-lg-push-5 {\n    left: 41.66666667%;\n  }\n  .am-u-lg-push-6 {\n    left: 50%;\n  }\n  .am-u-lg-push-7 {\n    left: 58.33333333%;\n  }\n  .am-u-lg-push-8 {\n    left: 66.66666667%;\n  }\n  .am-u-lg-push-9 {\n    left: 75%;\n  }\n  .am-u-lg-push-10 {\n    left: 83.33333333%;\n  }\n  .am-u-lg-push-11 {\n    left: 91.66666667%;\n  }\n  .am-u-lg-offset-0 {\n    margin-left: 0;\n  }\n  .am-u-lg-offset-1 {\n    margin-left: 8.33333333%;\n  }\n  .am-u-lg-offset-2 {\n    margin-left: 16.66666667%;\n  }\n  .am-u-lg-offset-3 {\n    margin-left: 25%;\n  }\n  .am-u-lg-offset-4 {\n    margin-left: 33.33333333%;\n  }\n  .am-u-lg-offset-5 {\n    margin-left: 41.66666667%;\n  }\n  .am-u-lg-offset-6 {\n    margin-left: 50%;\n  }\n  .am-u-lg-offset-7 {\n    margin-left: 58.33333333%;\n  }\n  .am-u-lg-offset-8 {\n    margin-left: 66.66666667%;\n  }\n  .am-u-lg-offset-9 {\n    margin-left: 75%;\n  }\n  .am-u-lg-offset-10 {\n    margin-left: 83.33333333%;\n  }\n  .am-u-lg-offset-11 {\n    margin-left: 91.66666667%;\n  }\n  .am-u-lg-reset-order {\n    margin-left: 0;\n    margin-right: 0;\n    left: auto;\n    right: auto;\n    float: left;\n  }\n  [class*=\"am-u-\"].am-u-lg-centered {\n    margin-left: auto;\n    margin-right: auto;\n    float: none;\n  }\n  [class*=\"am-u-\"].am-u-lg-centered:last-child {\n    float: none;\n  }\n  [class*=\"am-u-\"].am-u-lg-uncentered {\n    margin-left: 0;\n    margin-right: 0;\n    float: left;\n  }\n  [class*=\"am-u-\"].am-u-lg-uncentered:last-child {\n    float: left;\n  }\n}\n/* ==========================================================================\n   Component: AVG Grid\n ============================================================================ */\n[class*=\"am-avg-\"] {\n  display: block;\n  padding: 0;\n  margin: 0;\n  list-style: none;\n}\n[class*=\"am-avg-\"]:before,\n[class*=\"am-avg-\"]:after {\n  content: \" \";\n  display: table;\n}\n[class*=\"am-avg-\"]:after {\n  clear: both;\n}\n[class*=\"am-avg-\"] > li {\n  display: block;\n  height: auto;\n  float: left;\n}\n@media only screen {\n  .am-avg-sm-1 > li {\n    width: 100%;\n  }\n  .am-avg-sm-1 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-1 > li:nth-of-type(1n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-2 > li {\n    width: 50%;\n  }\n  .am-avg-sm-2 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-2 > li:nth-of-type(2n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-3 > li {\n    width: 33.33333333%;\n  }\n  .am-avg-sm-3 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-3 > li:nth-of-type(3n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-4 > li {\n    width: 25%;\n  }\n  .am-avg-sm-4 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-4 > li:nth-of-type(4n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-5 > li {\n    width: 20%;\n  }\n  .am-avg-sm-5 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-5 > li:nth-of-type(5n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-6 > li {\n    width: 16.66666667%;\n  }\n  .am-avg-sm-6 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-6 > li:nth-of-type(6n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-7 > li {\n    width: 14.28571429%;\n  }\n  .am-avg-sm-7 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-7 > li:nth-of-type(7n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-8 > li {\n    width: 12.5%;\n  }\n  .am-avg-sm-8 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-8 > li:nth-of-type(8n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-9 > li {\n    width: 11.11111111%;\n  }\n  .am-avg-sm-9 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-9 > li:nth-of-type(9n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-10 > li {\n    width: 10%;\n  }\n  .am-avg-sm-10 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-10 > li:nth-of-type(10n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-11 > li {\n    width: 9.09090909%;\n  }\n  .am-avg-sm-11 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-11 > li:nth-of-type(11n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-12 > li {\n    width: 8.33333333%;\n  }\n  .am-avg-sm-12 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-12 > li:nth-of-type(12n + 1) {\n    clear: both;\n  }\n}\n@media only screen and (min-width:641px) {\n  .am-avg-md-1 > li {\n    width: 100%;\n  }\n  .am-avg-md-1 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-1 > li:nth-of-type(1n + 1) {\n    clear: both;\n  }\n  .am-avg-md-2 > li {\n    width: 50%;\n  }\n  .am-avg-md-2 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-2 > li:nth-of-type(2n + 1) {\n    clear: both;\n  }\n  .am-avg-md-3 > li {\n    width: 33.33333333%;\n  }\n  .am-avg-md-3 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-3 > li:nth-of-type(3n + 1) {\n    clear: both;\n  }\n  .am-avg-md-4 > li {\n    width: 25%;\n  }\n  .am-avg-md-4 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-4 > li:nth-of-type(4n + 1) {\n    clear: both;\n  }\n  .am-avg-md-5 > li {\n    width: 20%;\n  }\n  .am-avg-md-5 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-5 > li:nth-of-type(5n + 1) {\n    clear: both;\n  }\n  .am-avg-md-6 > li {\n    width: 16.66666667%;\n  }\n  .am-avg-md-6 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-6 > li:nth-of-type(6n + 1) {\n    clear: both;\n  }\n  .am-avg-md-7 > li {\n    width: 14.28571429%;\n  }\n  .am-avg-md-7 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-7 > li:nth-of-type(7n + 1) {\n    clear: both;\n  }\n  .am-avg-md-8 > li {\n    width: 12.5%;\n  }\n  .am-avg-md-8 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-8 > li:nth-of-type(8n + 1) {\n    clear: both;\n  }\n  .am-avg-md-9 > li {\n    width: 11.11111111%;\n  }\n  .am-avg-md-9 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-9 > li:nth-of-type(9n + 1) {\n    clear: both;\n  }\n  .am-avg-md-10 > li {\n    width: 10%;\n  }\n  .am-avg-md-10 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-10 > li:nth-of-type(10n + 1) {\n    clear: both;\n  }\n  .am-avg-md-11 > li {\n    width: 9.09090909%;\n  }\n  .am-avg-md-11 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-11 > li:nth-of-type(11n + 1) {\n    clear: both;\n  }\n  .am-avg-md-12 > li {\n    width: 8.33333333%;\n  }\n  .am-avg-md-12 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-12 > li:nth-of-type(12n + 1) {\n    clear: both;\n  }\n}\n@media only screen and (min-width:1025px) {\n  .am-avg-lg-1 > li {\n    width: 100%;\n  }\n  .am-avg-lg-1 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-1 > li:nth-of-type(1n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-2 > li {\n    width: 50%;\n  }\n  .am-avg-lg-2 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-2 > li:nth-of-type(2n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-3 > li {\n    width: 33.33333333%;\n  }\n  .am-avg-lg-3 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-3 > li:nth-of-type(3n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-4 > li {\n    width: 25%;\n  }\n  .am-avg-lg-4 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-4 > li:nth-of-type(4n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-5 > li {\n    width: 20%;\n  }\n  .am-avg-lg-5 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-5 > li:nth-of-type(5n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-6 > li {\n    width: 16.66666667%;\n  }\n  .am-avg-lg-6 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-6 > li:nth-of-type(6n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-7 > li {\n    width: 14.28571429%;\n  }\n  .am-avg-lg-7 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-7 > li:nth-of-type(7n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-8 > li {\n    width: 12.5%;\n  }\n  .am-avg-lg-8 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-8 > li:nth-of-type(8n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-9 > li {\n    width: 11.11111111%;\n  }\n  .am-avg-lg-9 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-9 > li:nth-of-type(9n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-10 > li {\n    width: 10%;\n  }\n  .am-avg-lg-10 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-10 > li:nth-of-type(10n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-11 > li {\n    width: 9.09090909%;\n  }\n  .am-avg-lg-11 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-11 > li:nth-of-type(11n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-12 > li {\n    width: 8.33333333%;\n  }\n  .am-avg-lg-12 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-12 > li:nth-of-type(12n + 1) {\n    clear: both;\n  }\n}\n/* ==========================================================================\n   Component: Code\n ============================================================================ */\n/* Inline and block code styles */\ncode,\nkbd,\npre,\nsamp {\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", \"FontAwesome\", monospace;\n}\n/* Inline code */\ncode {\n  padding: 2px 4px;\n  font-size: 1.3rem;\n  color: #c7254e;\n  background-color: #f8f8f8;\n  white-space: nowrap;\n  border-radius: 2px;\n}\n/* Code block */\npre {\n  display: block;\n  padding: 1rem;\n  margin: 1rem  0;\n  font-size: 1.3rem;\n  line-height: 1.6;\n  word-break: break-all;\n  word-wrap: break-word;\n  color: #555555;\n  background-color: #f8f8f8;\n  border: 1px solid #dedede;\n  border-radius: 2px;\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/* Enable scrollable blocks of code */\n.am-pre-scrollable {\n  max-height: 24rem;\n  overflow-y: scroll;\n}\n/* ==========================================================================\n   Component: Button\n ============================================================================ */\n.am-btn {\n  display: inline-block;\n  margin-bottom: 0;\n  padding: 0.5em 1em;\n  vertical-align: middle;\n  font-size: 1.6rem;\n  font-weight: normal;\n  line-height: 1.2;\n  text-align: center;\n  white-space: nowrap;\n  background-image: none;\n  border: 1px solid transparent;\n  border-radius: 2px;\n  cursor: pointer;\n  outline: none;\n  -webkit-appearance: none;\n  -webkit-user-select: none;\n     -moz-user-select: none;\n      -ms-user-select: none;\n          user-select: none;\n  -webkit-transition: background-color 300ms ease-out, border-color 300ms ease-out;\n  transition: background-color 300ms ease-out, border-color 300ms ease-out;\n}\n.am-btn.am-square {\n  border-radius: 0;\n}\n.am-btn:focus,\n.am-btn:active:focus {\n  outline: thin dotted;\n  outline: 1px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n.am-btn:hover,\n.am-btn:focus {\n  color: #444;\n  text-decoration: none;\n}\n.am-btn:active,\n.am-btn.am-active {\n  background-image: none;\n  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.15);\n}\n.am-btn.am-disabled,\n.am-btn[disabled],\nfieldset[disabled] .am-btn {\n  pointer-events: none;\n  border-color: transparent;\n  cursor: not-allowed;\n  opacity: 0.45;\n  -webkit-box-shadow: none;\n          box-shadow: none;\n}\n.am-btn.am-round {\n  border-radius: 1000px;\n}\n.am-btn.am-radius {\n  border-radius: 2px;\n}\n.am-btn-default {\n  color: #444;\n  background-color: #e6e6e6;\n  border-color: #e6e6e6;\n}\na.am-btn-default:visited {\n  color: #444;\n}\n.am-btn-default:hover,\n.am-btn-default:focus,\n.am-btn-default:active,\n.am-btn-default.am-active,\n.am-active .am-btn-default.am-dropdown-toggle {\n  color: #444;\n  border-color: #c7c7c7;\n}\n.am-btn-default:hover,\n.am-btn-default:focus {\n  background-color: #d4d4d4;\n}\n.am-btn-default:active,\n.am-btn-default.am-active,\n.am-active .am-btn-default.am-dropdown-toggle {\n  background-image: none;\n  background-color: #c2c2c2;\n}\n.am-btn-default.am-disabled,\n.am-btn-default[disabled],\nfieldset[disabled] .am-btn-default,\n.am-btn-default.am-disabled:hover,\n.am-btn-default[disabled]:hover,\nfieldset[disabled] .am-btn-default:hover,\n.am-btn-default.am-disabled:focus,\n.am-btn-default[disabled]:focus,\nfieldset[disabled] .am-btn-default:focus,\n.am-btn-default.am-disabled:active,\n.am-btn-default[disabled]:active,\nfieldset[disabled] .am-btn-default:active,\n.am-btn-default.am-disabled.am-active,\n.am-btn-default[disabled].am-active,\nfieldset[disabled] .am-btn-default.am-active {\n  background-color: #e6e6e6;\n  border-color: #e6e6e6;\n}\n.am-btn-group .am-btn-default,\n.am-btn-group-stacked .am-btn-default {\n  border-color: #d9d9d9;\n}\n.am-btn-primary {\n  color: #fff;\n  background-color: #0e90d2;\n  border-color: #0e90d2;\n}\na.am-btn-primary:visited {\n  color: #fff;\n}\n.am-btn-primary:hover,\n.am-btn-primary:focus,\n.am-btn-primary:active,\n.am-btn-primary.am-active,\n.am-active .am-btn-primary.am-dropdown-toggle {\n  color: #fff;\n  border-color: #0a6999;\n}\n.am-btn-primary:hover,\n.am-btn-primary:focus {\n  background-color: #0c79b1;\n}\n.am-btn-primary:active,\n.am-btn-primary.am-active,\n.am-active .am-btn-primary.am-dropdown-toggle {\n  background-image: none;\n  background-color: #0a628f;\n}\n.am-btn-primary.am-disabled,\n.am-btn-primary[disabled],\nfieldset[disabled] .am-btn-primary,\n.am-btn-primary.am-disabled:hover,\n.am-btn-primary[disabled]:hover,\nfieldset[disabled] .am-btn-primary:hover,\n.am-btn-primary.am-disabled:focus,\n.am-btn-primary[disabled]:focus,\nfieldset[disabled] .am-btn-primary:focus,\n.am-btn-primary.am-disabled:active,\n.am-btn-primary[disabled]:active,\nfieldset[disabled] .am-btn-primary:active,\n.am-btn-primary.am-disabled.am-active,\n.am-btn-primary[disabled].am-active,\nfieldset[disabled] .am-btn-primary.am-active {\n  background-color: #0e90d2;\n  border-color: #0e90d2;\n}\n.am-btn-group .am-btn-primary,\n.am-btn-group-stacked .am-btn-primary {\n  border-color: #0c80ba;\n}\n.am-btn-warning {\n  color: #fff;\n  background-color: #F37B1D;\n  border-color: #F37B1D;\n}\na.am-btn-warning:visited {\n  color: #fff;\n}\n.am-btn-warning:hover,\n.am-btn-warning:focus,\n.am-btn-warning:active,\n.am-btn-warning.am-active,\n.am-active .am-btn-warning.am-dropdown-toggle {\n  color: #fff;\n  border-color: #c85e0b;\n}\n.am-btn-warning:hover,\n.am-btn-warning:focus {\n  background-color: #e0690c;\n}\n.am-btn-warning:active,\n.am-btn-warning.am-active,\n.am-active .am-btn-warning.am-dropdown-toggle {\n  background-image: none;\n  background-color: #be590a;\n}\n.am-btn-warning.am-disabled,\n.am-btn-warning[disabled],\nfieldset[disabled] .am-btn-warning,\n.am-btn-warning.am-disabled:hover,\n.am-btn-warning[disabled]:hover,\nfieldset[disabled] .am-btn-warning:hover,\n.am-btn-warning.am-disabled:focus,\n.am-btn-warning[disabled]:focus,\nfieldset[disabled] .am-btn-warning:focus,\n.am-btn-warning.am-disabled:active,\n.am-btn-warning[disabled]:active,\nfieldset[disabled] .am-btn-warning:active,\n.am-btn-warning.am-disabled.am-active,\n.am-btn-warning[disabled].am-active,\nfieldset[disabled] .am-btn-warning.am-active {\n  background-color: #F37B1D;\n  border-color: #F37B1D;\n}\n.am-btn-group .am-btn-warning,\n.am-btn-group-stacked .am-btn-warning {\n  border-color: #ea6e0c;\n}\n.am-btn-danger {\n  color: #fff;\n  background-color: #dd514c;\n  border-color: #dd514c;\n}\na.am-btn-danger:visited {\n  color: #fff;\n}\n.am-btn-danger:hover,\n.am-btn-danger:focus,\n.am-btn-danger:active,\n.am-btn-danger.am-active,\n.am-active .am-btn-danger.am-dropdown-toggle {\n  color: #fff;\n  border-color: #c62b26;\n}\n.am-btn-danger:hover,\n.am-btn-danger:focus {\n  background-color: #d7342e;\n}\n.am-btn-danger:active,\n.am-btn-danger.am-active,\n.am-active .am-btn-danger.am-dropdown-toggle {\n  background-image: none;\n  background-color: #be2924;\n}\n.am-btn-danger.am-disabled,\n.am-btn-danger[disabled],\nfieldset[disabled] .am-btn-danger,\n.am-btn-danger.am-disabled:hover,\n.am-btn-danger[disabled]:hover,\nfieldset[disabled] .am-btn-danger:hover,\n.am-btn-danger.am-disabled:focus,\n.am-btn-danger[disabled]:focus,\nfieldset[disabled] .am-btn-danger:focus,\n.am-btn-danger.am-disabled:active,\n.am-btn-danger[disabled]:active,\nfieldset[disabled] .am-btn-danger:active,\n.am-btn-danger.am-disabled.am-active,\n.am-btn-danger[disabled].am-active,\nfieldset[disabled] .am-btn-danger.am-active {\n  background-color: #dd514c;\n  border-color: #dd514c;\n}\n.am-btn-group .am-btn-danger,\n.am-btn-group-stacked .am-btn-danger {\n  border-color: #d93c37;\n}\n.am-btn-success {\n  color: #fff;\n  background-color: #5eb95e;\n  border-color: #5eb95e;\n}\na.am-btn-success:visited {\n  color: #fff;\n}\n.am-btn-success:hover,\n.am-btn-success:focus,\n.am-btn-success:active,\n.am-btn-success.am-active,\n.am-active .am-btn-success.am-dropdown-toggle {\n  color: #fff;\n  border-color: #429842;\n}\n.am-btn-success:hover,\n.am-btn-success:focus {\n  background-color: #4aaa4a;\n}\n.am-btn-success:active,\n.am-btn-success.am-active,\n.am-active .am-btn-success.am-dropdown-toggle {\n  background-image: none;\n  background-color: #3f913f;\n}\n.am-btn-success.am-disabled,\n.am-btn-success[disabled],\nfieldset[disabled] .am-btn-success,\n.am-btn-success.am-disabled:hover,\n.am-btn-success[disabled]:hover,\nfieldset[disabled] .am-btn-success:hover,\n.am-btn-success.am-disabled:focus,\n.am-btn-success[disabled]:focus,\nfieldset[disabled] .am-btn-success:focus,\n.am-btn-success.am-disabled:active,\n.am-btn-success[disabled]:active,\nfieldset[disabled] .am-btn-success:active,\n.am-btn-success.am-disabled.am-active,\n.am-btn-success[disabled].am-active,\nfieldset[disabled] .am-btn-success.am-active {\n  background-color: #5eb95e;\n  border-color: #5eb95e;\n}\n.am-btn-group .am-btn-success,\n.am-btn-group-stacked .am-btn-success {\n  border-color: #4db14d;\n}\n.am-btn-secondary {\n  color: #fff;\n  background-color: #3bb4f2;\n  border-color: #3bb4f2;\n}\na.am-btn-secondary:visited {\n  color: #fff;\n}\n.am-btn-secondary:hover,\n.am-btn-secondary:focus,\n.am-btn-secondary:active,\n.am-btn-secondary.am-active,\n.am-active .am-btn-secondary.am-dropdown-toggle {\n  color: #fff;\n  border-color: #0f9ae0;\n}\n.am-btn-secondary:hover,\n.am-btn-secondary:focus {\n  background-color: #19a7f0;\n}\n.am-btn-secondary:active,\n.am-btn-secondary.am-active,\n.am-active .am-btn-secondary.am-dropdown-toggle {\n  background-image: none;\n  background-color: #0e93d7;\n}\n.am-btn-secondary.am-disabled,\n.am-btn-secondary[disabled],\nfieldset[disabled] .am-btn-secondary,\n.am-btn-secondary.am-disabled:hover,\n.am-btn-secondary[disabled]:hover,\nfieldset[disabled] .am-btn-secondary:hover,\n.am-btn-secondary.am-disabled:focus,\n.am-btn-secondary[disabled]:focus,\nfieldset[disabled] .am-btn-secondary:focus,\n.am-btn-secondary.am-disabled:active,\n.am-btn-secondary[disabled]:active,\nfieldset[disabled] .am-btn-secondary:active,\n.am-btn-secondary.am-disabled.am-active,\n.am-btn-secondary[disabled].am-active,\nfieldset[disabled] .am-btn-secondary.am-active {\n  background-color: #3bb4f2;\n  border-color: #3bb4f2;\n}\n.am-btn-group .am-btn-secondary,\n.am-btn-group-stacked .am-btn-secondary {\n  border-color: #23abf0;\n}\n/* Style links like a button */\n.am-btn-link {\n  color: #0e90d2;\n  font-weight: normal;\n  cursor: pointer;\n  border-radius: 0;\n}\n.am-btn-link,\n.am-btn-link:active,\n.am-btn-link[disabled],\nfieldset[disabled] .am-btn-link {\n  background-color: transparent;\n  -webkit-box-shadow: none;\n          box-shadow: none;\n}\n.am-btn-link,\n.am-btn-link:hover,\n.am-btn-link:focus,\n.am-btn-link:active {\n  border-color: transparent;\n}\n.am-btn-link:hover,\n.am-btn-link:focus {\n  color: #095f8a;\n  text-decoration: underline;\n  background-color: transparent;\n}\n.am-btn-link[disabled]:hover,\nfieldset[disabled] .am-btn-link:hover,\n.am-btn-link[disabled]:focus,\nfieldset[disabled] .am-btn-link:focus {\n  color: #999999;\n  text-decoration: none;\n}\n/* button size */\n.am-btn-xs {\n  font-size: 1.2rem;\n}\n.am-btn-sm {\n  font-size: 1.4rem;\n}\n.am-btn-lg {\n  font-size: 1.8rem;\n}\n.am-btn-xl {\n  font-size: 2rem;\n}\n/* Block button  */\n.am-btn-block {\n  display: block;\n  width: 100%;\n  padding-left: 0;\n  padding-right: 0;\n}\n/* Multiple block buttons vertically space */\n.am-btn-block + .am-btn-block {\n  margin-top: 5px;\n}\n/* Specificity overrides */\ninput[type=\"submit\"].am-btn-block,\ninput[type=\"reset\"].am-btn-block,\ninput[type=\"button\"].am-btn-block {\n  width: 100%;\n}\n/* Button with loading spinner */\n.am-btn.am-btn-loading .am-icon-spin {\n  margin-right: 5px;\n}\n/* ==========================================================================\n   Component: Table\n ============================================================================ */\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  empty-cells: show;\n}\ntable code {\n  white-space: normal;\n}\nth {\n  text-align: left;\n}\n.am-table {\n  width: 100%;\n  margin-bottom: 1.6rem;\n  border-spacing: 0;\n  border-collapse: separate;\n}\n.am-table > thead > tr > th,\n.am-table > tbody > tr > th,\n.am-table > tfoot > tr > th,\n.am-table > thead > tr > td,\n.am-table > tbody > tr > td,\n.am-table > tfoot > tr > td {\n  padding: 0.7rem;\n  line-height: 1.6;\n  vertical-align: top;\n  border-top: 1px solid #ddd;\n}\n.am-table > thead > tr > th {\n  vertical-align: bottom;\n  border-bottom: 1px solid #ddd;\n}\n.am-table > caption + thead > tr:first-child > th,\n.am-table > colgroup + thead > tr:first-child > th,\n.am-table > thead:first-child > tr:first-child > th,\n.am-table > caption + thead > tr:first-child > td,\n.am-table > colgroup + thead > tr:first-child > td,\n.am-table > thead:first-child > tr:first-child > td {\n  border-top: 0;\n}\n.am-table > tbody + tbody tr:first-child td {\n  border-top: 2px solid #ddd;\n}\n/* Bordered version */\n.am-table-bordered {\n  border: 1px solid #ddd;\n  border-left: none;\n}\n.am-table-bordered > thead > tr > th,\n.am-table-bordered > tbody > tr > th,\n.am-table-bordered > tfoot > tr > th,\n.am-table-bordered > thead > tr > td,\n.am-table-bordered > tbody > tr > td,\n.am-table-bordered > tfoot > tr > td {\n  border-left: 1px solid #ddd;\n  /*&:first-child {\n          border-left: none;\n        }*/\n}\n.am-table-bordered > tbody > tr:first-child > th,\n.am-table-bordered > tbody > tr:first-child > td {\n  border-top: none;\n}\n.am-table-bordered > thead + tbody > tr:first-child > th,\n.am-table-bordered > thead + tbody > tr:first-child > td {\n  border-top: 1px solid #ddd;\n}\n/* Border-radius version */\n.am-table-radius {\n  border: 1px solid #ddd;\n  border-radius: 2px;\n}\n.am-table-radius > thead > tr:first-child > th:first-child,\n.am-table-radius > thead > tr:first-child > td:first-child {\n  border-top-left-radius: 2px;\n  border-left: none;\n}\n.am-table-radius > thead > tr:first-child > th:last-child,\n.am-table-radius > thead > tr:first-child > td:last-child {\n  border-top-right-radius: 2px;\n  border-right: none;\n}\n.am-table-radius > tbody > tr > th:first-child,\n.am-table-radius > tbody > tr > td:first-child {\n  border-left: none;\n}\n.am-table-radius > tbody > tr > th:last-child,\n.am-table-radius > tbody > tr > td:last-child {\n  border-right: none;\n}\n.am-table-radius > tbody > tr:last-child > th,\n.am-table-radius > tbody > tr:last-child > td {\n  border-bottom: none;\n}\n.am-table-radius > tbody > tr:last-child > th:first-child,\n.am-table-radius > tbody > tr:last-child > td:first-child {\n  border-bottom-left-radius: 2px;\n}\n.am-table-radius > tbody > tr:last-child > th:last-child,\n.am-table-radius > tbody > tr:last-child > td:last-child {\n  border-bottom-right-radius: 2px;\n}\n/* Zebra-striping */\n.am-table-striped > tbody > tr:nth-child(odd) > td,\n.am-table-striped > tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n/* Hover effect */\n.am-table-hover > tbody > tr:hover > td,\n.am-table-hover > tbody > tr:hover > th {\n  background-color: #e9e9e9;\n}\n.am-table-compact > thead > tr > th,\n.am-table-compact > tbody > tr > th,\n.am-table-compact > tfoot > tr > th,\n.am-table-compact > thead > tr > td,\n.am-table-compact > tbody > tr > td,\n.am-table-compact > tfoot > tr > td {\n  padding: 0.4rem;\n}\n.am-table-centered > thead > tr > th,\n.am-table-centered > tbody > tr > th,\n.am-table-centered > tfoot > tr > th,\n.am-table-centered > thead > tr > td,\n.am-table-centered > tbody > tr > td,\n.am-table-centered > tfoot > tr > td {\n  text-align: center;\n}\n.am-table > thead > tr > td.am-active,\n.am-table > tbody > tr > td.am-active,\n.am-table > tfoot > tr > td.am-active,\n.am-table > thead > tr > th.am-active,\n.am-table > tbody > tr > th.am-active,\n.am-table > tfoot > tr > th.am-active,\n.am-table > thead > tr.am-active > td,\n.am-table > tbody > tr.am-active > td,\n.am-table > tfoot > tr.am-active > td,\n.am-table > thead > tr.am-active > th,\n.am-table > tbody > tr.am-active > th,\n.am-table > tfoot > tr.am-active > th {\n  background-color: #ffd;\n}\n.am-table > thead > tr > td.am-disabled,\n.am-table > tbody > tr > td.am-disabled,\n.am-table > tfoot > tr > td.am-disabled,\n.am-table > thead > tr > th.am-disabled,\n.am-table > tbody > tr > th.am-disabled,\n.am-table > tfoot > tr > th.am-disabled,\n.am-table > thead > tr.am-disabled > td,\n.am-table > tbody > tr.am-disabled > td,\n.am-table > tfoot > tr.am-disabled > td,\n.am-table > thead > tr.am-disabled > th,\n.am-table > tbody > tr.am-disabled > th,\n.am-table > tfoot > tr.am-disabled > th {\n  color: #999999;\n}\n.am-table > thead > tr > td.am-primary,\n.am-table > tbody > tr > td.am-primary,\n.am-table > tfoot > tr > td.am-primary,\n.am-table > thead > tr > th.am-primary,\n.am-table > tbody > tr > th.am-primary,\n.am-table > tfoot > tr > th.am-primary,\n.am-table > thead > tr.am-primary > td,\n.am-table > tbody > tr.am-primary > td,\n.am-table > tfoot > tr.am-primary > td,\n.am-table > thead > tr.am-primary > th,\n.am-table > tbody > tr.am-primary > th,\n.am-table > tfoot > tr.am-primary > th {\n  color: #0b76ac;\n  background-color: rgba(14, 144, 210, 0.115);\n}\n.am-table > thead > tr > td.am-success,\n.am-table > tbody > tr > td.am-success,\n.am-table > tfoot > tr > td.am-success,\n.am-table > thead > tr > th.am-success,\n.am-table > tbody > tr > th.am-success,\n.am-table > tfoot > tr > th.am-success,\n.am-table > thead > tr.am-success > td,\n.am-table > tbody > tr.am-success > td,\n.am-table > tfoot > tr.am-success > td,\n.am-table > thead > tr.am-success > th,\n.am-table > tbody > tr.am-success > th,\n.am-table > tfoot > tr.am-success > th {\n  color: #5eb95e;\n  background-color: rgba(94, 185, 94, 0.115);\n}\n.am-table > thead > tr > td.am-warning,\n.am-table > tbody > tr > td.am-warning,\n.am-table > tfoot > tr > td.am-warning,\n.am-table > thead > tr > th.am-warning,\n.am-table > tbody > tr > th.am-warning,\n.am-table > tfoot > tr > th.am-warning,\n.am-table > thead > tr.am-warning > td,\n.am-table > tbody > tr.am-warning > td,\n.am-table > tfoot > tr.am-warning > td,\n.am-table > thead > tr.am-warning > th,\n.am-table > tbody > tr.am-warning > th,\n.am-table > tfoot > tr.am-warning > th {\n  color: #F37B1D;\n  background-color: rgba(243, 123, 29, 0.115);\n}\n.am-table > thead > tr > td.am-danger,\n.am-table > tbody > tr > td.am-danger,\n.am-table > tfoot > tr > td.am-danger,\n.am-table > thead > tr > th.am-danger,\n.am-table > tbody > tr > th.am-danger,\n.am-table > tfoot > tr > th.am-danger,\n.am-table > thead > tr.am-danger > td,\n.am-table > tbody > tr.am-danger > td,\n.am-table > tfoot > tr.am-danger > td,\n.am-table > thead > tr.am-danger > th,\n.am-table > tbody > tr.am-danger > th,\n.am-table > tfoot > tr.am-danger > th {\n  color: #dd514c;\n  background-color: rgba(221, 81, 76, 0.115);\n}\n/* ==========================================================================\n   Component: Form\n ============================================================================ */\n/* Normalize */\nfieldset {\n  border: none;\n}\nlegend {\n  display: block;\n  width: 100%;\n  margin-bottom: 2rem;\n  font-size: 2rem;\n  line-height: inherit;\n  color: #333333;\n  border-bottom: 1px solid #e5e5e5;\n  padding-bottom: 0.5rem;\n}\nlabel {\n  display: inline-block;\n  margin-bottom: 5px;\n  font-weight: bold;\n}\ninput[type=\"search\"] {\n  -webkit-box-sizing: border-box;\n          box-sizing: border-box;\n}\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  /* IE8-9 */\n  line-height: normal;\n}\ninput[type=\"file\"] {\n  display: block;\n}\nselect[multiple],\nselect[size] {\n  height: auto;\n}\nselect optgroup {\n  font-size: inherit;\n  font-style: inherit;\n  font-family: inherit;\n}\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted;\n  outline: 1px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\ninput[type=\"number\"]::-webkit-outer-spin-button,\ninput[type=\"number\"]::-webkit-inner-spin-button {\n  height: auto;\n}\noutput {\n  display: block;\n  padding-top: 1.6rem;\n  font-size: 1.6rem;\n  line-height: 1.6;\n  color: #555555;\n  vertical-align: middle;\n}\n/* Common form controls */\n.am-form select,\n.am-form textarea,\n.am-form input[type=\"text\"],\n.am-form input[type=\"password\"],\n.am-form input[type=\"datetime\"],\n.am-form input[type=\"datetime-local\"],\n.am-form input[type=\"date\"],\n.am-form input[type=\"month\"],\n.am-form input[type=\"time\"],\n.am-form input[type=\"week\"],\n.am-form input[type=\"number\"],\n.am-form input[type=\"email\"],\n.am-form input[type=\"url\"],\n.am-form input[type=\"search\"],\n.am-form input[type=\"tel\"],\n.am-form input[type=\"color\"],\n.am-form-field {\n  display: block;\n  width: 100%;\n  padding: 0.5em;\n  font-size: 1.6rem;\n  line-height: 1.2;\n  color: #555555;\n  vertical-align: middle;\n  background-color: #fff;\n  background-image: none;\n  border: 1px solid #ccc;\n  border-radius: 2px;\n  -webkit-appearance: none;\n  -webkit-transition: border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;\n  transition: border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;\n  transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n  transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;\n}\n.am-form select.am-square,\n.am-form textarea.am-square,\n.am-form input[type=\"text\"].am-square,\n.am-form input[type=\"password\"].am-square,\n.am-form input[type=\"datetime\"].am-square,\n.am-form input[type=\"datetime-local\"].am-square,\n.am-form input[type=\"date\"].am-square,\n.am-form input[type=\"month\"].am-square,\n.am-form input[type=\"time\"].am-square,\n.am-form input[type=\"week\"].am-square,\n.am-form input[type=\"number\"].am-square,\n.am-form input[type=\"email\"].am-square,\n.am-form input[type=\"url\"].am-square,\n.am-form input[type=\"search\"].am-square,\n.am-form input[type=\"tel\"].am-square,\n.am-form input[type=\"color\"].am-square,\n.am-form-field.am-square {\n  border-radius: 0;\n}\n.am-form select:focus,\n.am-form textarea:focus,\n.am-form input[type=\"text\"]:focus,\n.am-form input[type=\"password\"]:focus,\n.am-form input[type=\"datetime\"]:focus,\n.am-form input[type=\"datetime-local\"]:focus,\n.am-form input[type=\"date\"]:focus,\n.am-form input[type=\"month\"]:focus,\n.am-form input[type=\"time\"]:focus,\n.am-form input[type=\"week\"]:focus,\n.am-form input[type=\"number\"]:focus,\n.am-form input[type=\"email\"]:focus,\n.am-form input[type=\"url\"]:focus,\n.am-form input[type=\"search\"]:focus,\n.am-form input[type=\"tel\"]:focus,\n.am-form input[type=\"color\"]:focus,\n.am-form-field:focus {\n  outline: 0;\n}\n.am-form select:focus,\n.am-form textarea:focus,\n.am-form input[type=\"text\"]:focus,\n.am-form input[type=\"password\"]:focus,\n.am-form input[type=\"datetime\"]:focus,\n.am-form input[type=\"datetime-local\"]:focus,\n.am-form input[type=\"date\"]:focus,\n.am-form input[type=\"month\"]:focus,\n.am-form input[type=\"time\"]:focus,\n.am-form input[type=\"week\"]:focus,\n.am-form input[type=\"number\"]:focus,\n.am-form input[type=\"email\"]:focus,\n.am-form input[type=\"url\"]:focus,\n.am-form input[type=\"search\"]:focus,\n.am-form input[type=\"tel\"]:focus,\n.am-form input[type=\"color\"]:focus,\n.am-form-field:focus {\n  background-color: #fefffe;\n  border-color: #3bb4f2;\n  outline: 0;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 5px rgba(59, 180, 242, 0.3);\n          box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 5px rgba(59, 180, 242, 0.3);\n}\n.am-form select::-webkit-input-placeholder,\n.am-form textarea::-webkit-input-placeholder,\n.am-form input[type=\"text\"]::-webkit-input-placeholder,\n.am-form input[type=\"password\"]::-webkit-input-placeholder,\n.am-form input[type=\"datetime\"]::-webkit-input-placeholder,\n.am-form input[type=\"datetime-local\"]::-webkit-input-placeholder,\n.am-form input[type=\"date\"]::-webkit-input-placeholder,\n.am-form input[type=\"month\"]::-webkit-input-placeholder,\n.am-form input[type=\"time\"]::-webkit-input-placeholder,\n.am-form input[type=\"week\"]::-webkit-input-placeholder,\n.am-form input[type=\"number\"]::-webkit-input-placeholder,\n.am-form input[type=\"email\"]::-webkit-input-placeholder,\n.am-form input[type=\"url\"]::-webkit-input-placeholder,\n.am-form input[type=\"search\"]::-webkit-input-placeholder,\n.am-form input[type=\"tel\"]::-webkit-input-placeholder,\n.am-form input[type=\"color\"]::-webkit-input-placeholder,\n.am-form-field::-webkit-input-placeholder {\n  color: #999999;\n}\n.am-form select::-moz-placeholder,\n.am-form textarea::-moz-placeholder,\n.am-form input[type=\"text\"]::-moz-placeholder,\n.am-form input[type=\"password\"]::-moz-placeholder,\n.am-form input[type=\"datetime\"]::-moz-placeholder,\n.am-form input[type=\"datetime-local\"]::-moz-placeholder,\n.am-form input[type=\"date\"]::-moz-placeholder,\n.am-form input[type=\"month\"]::-moz-placeholder,\n.am-form input[type=\"time\"]::-moz-placeholder,\n.am-form input[type=\"week\"]::-moz-placeholder,\n.am-form input[type=\"number\"]::-moz-placeholder,\n.am-form input[type=\"email\"]::-moz-placeholder,\n.am-form input[type=\"url\"]::-moz-placeholder,\n.am-form input[type=\"search\"]::-moz-placeholder,\n.am-form input[type=\"tel\"]::-moz-placeholder,\n.am-form input[type=\"color\"]::-moz-placeholder,\n.am-form-field::-moz-placeholder {\n  color: #999999;\n}\n.am-form select:-ms-input-placeholder,\n.am-form textarea:-ms-input-placeholder,\n.am-form input[type=\"text\"]:-ms-input-placeholder,\n.am-form input[type=\"password\"]:-ms-input-placeholder,\n.am-form input[type=\"datetime\"]:-ms-input-placeholder,\n.am-form input[type=\"datetime-local\"]:-ms-input-placeholder,\n.am-form input[type=\"date\"]:-ms-input-placeholder,\n.am-form input[type=\"month\"]:-ms-input-placeholder,\n.am-form input[type=\"time\"]:-ms-input-placeholder,\n.am-form input[type=\"week\"]:-ms-input-placeholder,\n.am-form input[type=\"number\"]:-ms-input-placeholder,\n.am-form input[type=\"email\"]:-ms-input-placeholder,\n.am-form input[type=\"url\"]:-ms-input-placeholder,\n.am-form input[type=\"search\"]:-ms-input-placeholder,\n.am-form input[type=\"tel\"]:-ms-input-placeholder,\n.am-form input[type=\"color\"]:-ms-input-placeholder,\n.am-form-field:-ms-input-placeholder {\n  color: #999999;\n}\n.am-form select::placeholder,\n.am-form textarea::placeholder,\n.am-form input[type=\"text\"]::placeholder,\n.am-form input[type=\"password\"]::placeholder,\n.am-form input[type=\"datetime\"]::placeholder,\n.am-form input[type=\"datetime-local\"]::placeholder,\n.am-form input[type=\"date\"]::placeholder,\n.am-form input[type=\"month\"]::placeholder,\n.am-form input[type=\"time\"]::placeholder,\n.am-form input[type=\"week\"]::placeholder,\n.am-form input[type=\"number\"]::placeholder,\n.am-form input[type=\"email\"]::placeholder,\n.am-form input[type=\"url\"]::placeholder,\n.am-form input[type=\"search\"]::placeholder,\n.am-form input[type=\"tel\"]::placeholder,\n.am-form input[type=\"color\"]::placeholder,\n.am-form-field::placeholder {\n  color: #999999;\n}\n.am-form select::-moz-placeholder,\n.am-form textarea::-moz-placeholder,\n.am-form input[type=\"text\"]::-moz-placeholder,\n.am-form input[type=\"password\"]::-moz-placeholder,\n.am-form input[type=\"datetime\"]::-moz-placeholder,\n.am-form input[type=\"datetime-local\"]::-moz-placeholder,\n.am-form input[type=\"date\"]::-moz-placeholder,\n.am-form input[type=\"month\"]::-moz-placeholder,\n.am-form input[type=\"time\"]::-moz-placeholder,\n.am-form input[type=\"week\"]::-moz-placeholder,\n.am-form input[type=\"number\"]::-moz-placeholder,\n.am-form input[type=\"email\"]::-moz-placeholder,\n.am-form input[type=\"url\"]::-moz-placeholder,\n.am-form input[type=\"search\"]::-moz-placeholder,\n.am-form input[type=\"tel\"]::-moz-placeholder,\n.am-form input[type=\"color\"]::-moz-placeholder,\n.am-form-field::-moz-placeholder {\n  opacity: 1;\n}\n.am-form select[disabled],\n.am-form textarea[disabled],\n.am-form input[type=\"text\"][disabled],\n.am-form input[type=\"password\"][disabled],\n.am-form input[type=\"datetime\"][disabled],\n.am-form input[type=\"datetime-local\"][disabled],\n.am-form input[type=\"date\"][disabled],\n.am-form input[type=\"month\"][disabled],\n.am-form input[type=\"time\"][disabled],\n.am-form input[type=\"week\"][disabled],\n.am-form input[type=\"number\"][disabled],\n.am-form input[type=\"email\"][disabled],\n.am-form input[type=\"url\"][disabled],\n.am-form input[type=\"search\"][disabled],\n.am-form input[type=\"tel\"][disabled],\n.am-form input[type=\"color\"][disabled],\n.am-form-field[disabled],\n.am-form select[readonly],\n.am-form textarea[readonly],\n.am-form input[type=\"text\"][readonly],\n.am-form input[type=\"password\"][readonly],\n.am-form input[type=\"datetime\"][readonly],\n.am-form input[type=\"datetime-local\"][readonly],\n.am-form input[type=\"date\"][readonly],\n.am-form input[type=\"month\"][readonly],\n.am-form input[type=\"time\"][readonly],\n.am-form input[type=\"week\"][readonly],\n.am-form input[type=\"number\"][readonly],\n.am-form input[type=\"email\"][readonly],\n.am-form input[type=\"url\"][readonly],\n.am-form input[type=\"search\"][readonly],\n.am-form input[type=\"tel\"][readonly],\n.am-form input[type=\"color\"][readonly],\n.am-form-field[readonly],\nfieldset[disabled] .am-form select,\nfieldset[disabled] .am-form textarea,\nfieldset[disabled] .am-form input[type=\"text\"],\nfieldset[disabled] .am-form input[type=\"password\"],\nfieldset[disabled] .am-form input[type=\"datetime\"],\nfieldset[disabled] .am-form input[type=\"datetime-local\"],\nfieldset[disabled] .am-form input[type=\"date\"],\nfieldset[disabled] .am-form input[type=\"month\"],\nfieldset[disabled] .am-form input[type=\"time\"],\nfieldset[disabled] .am-form input[type=\"week\"],\nfieldset[disabled] .am-form input[type=\"number\"],\nfieldset[disabled] .am-form input[type=\"email\"],\nfieldset[disabled] .am-form input[type=\"url\"],\nfieldset[disabled] .am-form input[type=\"search\"],\nfieldset[disabled] .am-form input[type=\"tel\"],\nfieldset[disabled] .am-form input[type=\"color\"],\nfieldset[disabled] .am-form-field {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n.am-form select.am-radius,\n.am-form textarea.am-radius,\n.am-form input[type=\"text\"].am-radius,\n.am-form input[type=\"password\"].am-radius,\n.am-form input[type=\"datetime\"].am-radius,\n.am-form input[type=\"datetime-local\"].am-radius,\n.am-form input[type=\"date\"].am-radius,\n.am-form input[type=\"month\"].am-radius,\n.am-form input[type=\"time\"].am-radius,\n.am-form input[type=\"week\"].am-radius,\n.am-form input[type=\"number\"].am-radius,\n.am-form input[type=\"email\"].am-radius,\n.am-form input[type=\"url\"].am-radius,\n.am-form input[type=\"search\"].am-radius,\n.am-form input[type=\"tel\"].am-radius,\n.am-form input[type=\"color\"].am-radius,\n.am-form-field.am-radius {\n  border-radius: 2px;\n}\n.am-form select.am-round,\n.am-form textarea.am-round,\n.am-form input[type=\"text\"].am-round,\n.am-form input[type=\"password\"].am-round,\n.am-form input[type=\"datetime\"].am-round,\n.am-form input[type=\"datetime-local\"].am-round,\n.am-form input[type=\"date\"].am-round,\n.am-form input[type=\"month\"].am-round,\n.am-form input[type=\"time\"].am-round,\n.am-form input[type=\"week\"].am-round,\n.am-form input[type=\"number\"].am-round,\n.am-form input[type=\"email\"].am-round,\n.am-form input[type=\"url\"].am-round,\n.am-form input[type=\"search\"].am-round,\n.am-form input[type=\"tel\"].am-round,\n.am-form input[type=\"color\"].am-round,\n.am-form-field.am-round {\n  border-radius: 1000px;\n}\n.am-form textarea,\n.am-form select[multiple],\n.am-form select[size] {\n  height: auto;\n}\n.am-form select {\n  -webkit-appearance: none !important;\n  -moz-appearance: none !important;\n  -webkit-border-radius: 2px;\n  background: #fff url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgeD0iMTJweCIgeT0iMHB4IiB3aWR0aD0iMjRweCIgaGVpZ2h0PSIzcHgiIHZpZXdCb3g9IjAgMCA2IDMiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDYgMyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PHBvbHlnb24gcG9pbnRzPSI1Ljk5MiwwIDIuOTkyLDMgLTAuMDA4LDAgIi8+PC9zdmc+') no-repeat 100% center;\n}\n.am-form select[multiple=\"multiple\"] {\n  background-image: none;\n}\n/* help text */\n.am-form-help {\n  display: block;\n  margin-top: 5px;\n  margin-bottom: 10px;\n  color: #999999;\n  font-size: 1.3rem;\n}\n/* form group */\n.am-form-group {\n  margin-bottom: 1.5rem;\n}\n/* file field */\n.am-form-file {\n  position: relative;\n  overflow: hidden;\n}\n.am-form-file input[type=\"file\"] {\n  position: absolute;\n  left: 0;\n  top: 0;\n  z-index: 1;\n  width: 100%;\n  opacity: 0;\n  cursor: pointer;\n  font-size: 50rem;\n}\n/**\n * Checkboxes and radios\n * Indent the labels to position radios/checkboxes as hanging controls.\n*/\n.am-radio,\n.am-checkbox {\n  display: block;\n  min-height: 1.92rem;\n  margin-top: 10px;\n  margin-bottom: 10px;\n  padding-left: 20px;\n  vertical-align: middle;\n}\n.am-radio label,\n.am-checkbox label {\n  display: inline;\n  margin-bottom: 0;\n  font-weight: normal;\n  cursor: pointer;\n}\n.am-radio input[type=\"radio\"],\n.am-radio-inline input[type=\"radio\"],\n.am-checkbox input[type=\"checkbox\"],\n.am-checkbox-inline input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n  outline: none;\n}\n.am-radio + .am-radio,\n.am-checkbox + .am-checkbox {\n  margin-top: -5px;\n}\n/* Radios and checkboxes inline */\n.am-radio-inline,\n.am-checkbox-inline {\n  display: inline-block;\n  padding-left: 20px;\n  margin-bottom: 0;\n  vertical-align: middle;\n  font-weight: normal;\n  cursor: pointer;\n}\n.am-radio-inline + .am-radio-inline,\n.am-checkbox-inline + .am-checkbox-inline {\n  margin-top: 0;\n  margin-left: 10px;\n}\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\n.am-radio[disabled],\n.am-radio-inline[disabled],\n.am-checkbox[disabled],\n.am-checkbox-inline[disabled],\nfieldset[disabled] input[type=\"radio\"],\nfieldset[disabled] input[type=\"checkbox\"],\nfieldset[disabled] .am-radio,\nfieldset[disabled] .am-radio-inline,\nfieldset[disabled] .am-checkbox,\nfieldset[disabled] .am-checkbox-inline {\n  cursor: not-allowed;\n}\n/* Form field feedback states */\n.am-form-warning .am-form-help,\n.am-form-warning .am-form-label,\n.am-form-warning .am-radio,\n.am-form-warning .am-checkbox,\n.am-form-warning .am-radio-inline,\n.am-form-warning .am-checkbox-inline,\n.am-form-warning label {\n  color: #F37B1D;\n}\n.am-form-warning [class*=\"icon-\"] {\n  color: #F37B1D;\n}\n.am-form-warning .am-form-field {\n  border-color: #F37B1D !important;\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.am-form-warning .am-form-field:focus {\n  background-color: #fefffe;\n  border-color: #d2620b;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 5px #f8b47e !important;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 5px #f8b47e !important;\n}\n.am-form-error .am-form-help,\n.am-form-error .am-form-label,\n.am-form-error .am-radio,\n.am-form-error .am-checkbox,\n.am-form-error .am-radio-inline,\n.am-form-error .am-checkbox-inline,\n.am-form-error label {\n  color: #dd514c;\n}\n.am-form-error [class*=\"icon-\"] {\n  color: #dd514c;\n}\n.am-form-error .am-form-field,\n.am-field-error {\n  border-color: #dd514c !important;\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.am-form-error .am-form-field:focus,\n.am-field-error:focus {\n  background-color: #fefffe;\n  border-color: #cf2d27;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 5px #eda4a2 !important;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 5px #eda4a2 !important;\n}\n.am-form-success .am-form-help,\n.am-form-success .am-form-label,\n.am-form-success .am-radio,\n.am-form-success .am-checkbox,\n.am-form-success .am-radio-inline,\n.am-form-success .am-checkbox-inline,\n.am-form-success label {\n  color: #5eb95e;\n}\n.am-form-success [class*=\"icon-\"] {\n  color: #5eb95e;\n}\n.am-form-success .am-form-field,\n.am-field-valid {\n  border-color: #5eb95e !important;\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.am-form-success .am-form-field:focus,\n.am-field-valid:focus {\n  background-color: #fefffe;\n  border-color: #459f45;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 5px #a5d8a5 !important;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 5px #a5d8a5 !important;\n}\n/* Horizontal forms */\n.am-form-horizontal .am-form-label,\n.am-form-horizontal .am-radio,\n.am-form-horizontal .am-checkbox,\n.am-form-horizontal .am-radio-inline,\n.am-form-horizontal .am-checkbox-inline {\n  margin-top: 0;\n  margin-bottom: 0;\n  padding-top: 0.6em;\n}\n.am-form-horizontal .am-form-group:before,\n.am-form-horizontal .am-form-group:after {\n  content: \" \";\n  display: table;\n}\n.am-form-horizontal .am-form-group:after {\n  clear: both;\n}\n@media only screen and (min-width:641px) {\n  .am-form-horizontal .am-form-label {\n    text-align: right;\n  }\n}\n/* Inline form elements */\n@media only screen and (min-width:641px) {\n  .am-form-inline .am-form-group {\n    display: inline-block;\n    margin-bottom: 0;\n    vertical-align: middle;\n  }\n  .am-form-inline .am-form-field {\n    display: inline-block;\n    width: auto;\n    vertical-align: middle;\n  }\n  .am-form-inline .am-input-group {\n    display: inline-table;\n    vertical-align: middle;\n  }\n  .am-form-inline .am-input-group .am-input-group-label,\n  .am-form-inline .am-input-group .am-input-group-btn,\n  .am-form-inline .am-input-group .am-form-label {\n    width: auto;\n  }\n  .am-form-inline .am-input-group > .am-form-field {\n    width: 100%;\n  }\n  .am-form-inline .am-form-label {\n    margin-bottom: 0;\n    vertical-align: middle;\n  }\n  .am-form-inline .am-radio,\n  .am-form-inline .am-checkbox {\n    display: inline-block;\n    margin-top: 0;\n    margin-bottom: 0;\n    padding-left: 0;\n    vertical-align: middle;\n  }\n  .am-form-inline .am-radio input[type=\"radio\"],\n  .am-form-inline .am-checkbox input[type=\"checkbox\"] {\n    float: none;\n    margin-left: 0;\n  }\n}\n/* Form field size */\n.am-input-sm {\n  font-size: 1.4rem !important;\n}\n.am-input-lg {\n  font-size: 1.8rem !important;\n}\n.am-form-group-sm .am-checkbox,\n.am-form-group-sm .am-radio,\n.am-form-group-sm .am-form-label,\n.am-form-group-sm .am-form-field {\n  font-size: 1.4rem !important;\n}\n.am-form-group-lg .am-checkbox,\n.am-form-group-lg .am-radio,\n.am-form-group-lg .am-form-label,\n.am-form-group-lg .am-form-field {\n  font-size: 1.8rem !important;\n}\n.am-form-group-lg input[type=\"radio\"],\n.am-form-group-lg input[type=\"checkbox\"] {\n  margin-top: 7px;\n}\n/* Form field feedback states */\n.am-form-icon {\n  position: relative;\n}\n.am-form-icon .am-form-field {\n  padding-left: 1.75em !important;\n}\n.am-form-icon [class*='am-icon-'] {\n  position: absolute;\n  left: 0.5em;\n  top: 50%;\n  display: block;\n  margin-top: -0.5em;\n  line-height: 1;\n  z-index: 2;\n}\n.am-form-icon label ~ [class*='am-icon-'] {\n  top: 70%;\n}\n/* Feedback Icon */\n.am-form-feedback {\n  position: relative;\n}\n.am-form-feedback .am-form-field {\n  padding-left: 0.5em !important;\n  padding-right: 1.75em !important;\n}\n.am-form-feedback [class*='am-icon-'] {\n  right: 0.5em;\n  left: auto;\n}\n.am-form-horizontal .am-form-feedback [class*='am-icon-'] {\n  right: 1.6em;\n}\n/* Form set */\n.am-form-set {\n  margin-bottom: 1.5rem;\n  padding: 0;\n}\n.am-form-set > input {\n  position: relative;\n  top: -1px;\n  border-radius: 0 !important;\n}\n.am-form-set > input:focus {\n  z-index: 2;\n}\n.am-form-set > input:first-child {\n  top: 1px;\n  border-top-right-radius: 2px !important;\n  border-top-left-radius: 2px !important;\n}\n.am-form-set > input:last-child {\n  top: -2px;\n  border-bottom-right-radius: 2px !important;\n  border-bottom-left-radius: 2px !important;\n}\n/* ==========================================================================\n   Component: Image\n ============================================================================ */\n/* Image thumbnails */\n.am-img-thumbnail {\n  display: inline-block;\n  max-width: 100%;\n  height: auto;\n  padding: 2px;\n  line-height: 1.6;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  border-radius: 2px;\n  -webkit-transition: all 0.2s ease-in-out;\n  transition: all 0.2s ease-in-out;\n}\n.am-img-thumbnail.am-radius {\n  border-radius: 2px;\n}\n.am-img-responsive {\n  display: block;\n  max-width: 100%;\n  height: auto;\n}\n/* ==========================================================================\n   Component: Nav\n ============================================================================ */\n.am-nav {\n  margin-bottom: 0;\n  padding: 0;\n  list-style: none;\n}\n.am-nav:before,\n.am-nav:after {\n  content: \" \";\n  display: table;\n}\n.am-nav:after {\n  clear: both;\n}\n.am-nav > li {\n  position: relative;\n  display: block;\n}\n.am-nav > li + li {\n  margin-top: 5px;\n}\n.am-nav > li + .am-nav-header {\n  margin-top: 1em;\n}\n.am-nav > li > a {\n  position: relative;\n  display: block;\n  padding: 0.4em 1em;\n  border-radius: 2px;\n}\n.am-nav > li > a:hover,\n.am-nav > li > a:focus {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n.am-nav > li.am-active > a,\n.am-nav > li.am-active > a:hover,\n.am-nav > li.am-active > a:focus {\n  color: #fff;\n  background-color: #0e90d2;\n  cursor: default;\n}\n.am-nav > li.am-disabled > a {\n  color: #999999;\n}\n.am-nav > li.am-disabled > a:hover,\n.am-nav > li.am-disabled > a:focus {\n  color: #999999;\n  text-decoration: none;\n  background-color: transparent;\n  cursor: not-allowed;\n}\n.am-nav-header {\n  padding: 0.4em 1em;\n  text-transform: uppercase;\n  font-weight: bold;\n  font-size: 100%;\n  color: #555555;\n}\n.am-nav-divider {\n  margin: 15px 1em !important;\n  border-top: 1px solid #ddd;\n  -webkit-box-shadow: 0 1px 0 #fff;\n          box-shadow: 0 1px 0 #fff;\n}\n.am-nav-pills > li {\n  float: left;\n}\n.am-nav-pills > li + li {\n  margin-left: 5px;\n  margin-top: 0;\n}\n.am-nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n.am-nav-tabs > li {\n  float: left;\n  margin-bottom: -1px;\n}\n.am-nav-tabs > li + li {\n  margin-top: 0;\n}\n.am-nav-tabs > li > a {\n  margin-right: 5px;\n  line-height: 1.6;\n  border: 1px solid transparent;\n  border-radius: 2px 2px 0 0;\n}\n.am-nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #ddd;\n}\n.am-nav-tabs > li.am-active > a,\n.am-nav-tabs > li.am-active > a:hover,\n.am-nav-tabs > li.am-active > a:focus {\n  color: #555555;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n  cursor: default;\n}\n.am-nav-tabs.am-nav-justify {\n  border-bottom: 0;\n  /*  > li > a {\n      margin-right: 0;\n      border-radius: @global-radius;\n    }\n\n    > .am-active > a {\n      &,\n      &:hover,\n      &:focus {\n        border: 1px solid @nav-tabs-justify-link-border-color;\n      }\n    }*/\n}\n.am-nav-tabs.am-nav-justify > li > a {\n  margin-right: 0;\n  border-bottom: 1px solid #ddd;\n  border-radius: 2px 2px 0 0;\n}\n.am-nav-tabs.am-nav-justify > .am-active > a,\n.am-nav-tabs.am-nav-justify > .am-active > a:hover,\n.am-nav-tabs.am-nav-justify > .am-active > a:focus {\n  border-bottom-color: #fff;\n}\n.am-nav-justify {\n  width: 100%;\n  display: table;\n}\n.am-nav-justify > li {\n  float: none;\n  display: table-cell;\n  width: 1%;\n}\n.am-nav-justify > li > a {\n  text-align: center;\n  margin-bottom: 0;\n}\n.lte9 .am-nav-justify > li {\n  display: table-cell;\n  width: 1%;\n}\n/* ==========================================================================\n   Component: Topbar\n ============================================================================ */\n.am-topbar {\n  position: relative;\n  min-height: 50px;\n  margin-bottom: 1.6rem;\n  background: #f8f8f8;\n  border-width: 0 0 1px;\n  border-style: solid;\n  border-color: #ddd;\n  color: #666;\n}\n.am-topbar:before,\n.am-topbar:after {\n  content: \" \";\n  display: table;\n}\n.am-topbar:after {\n  clear: both;\n}\n.am-topbar a {\n  color: #666;\n}\n.am-topbar-brand {\n  margin: 0;\n}\n@media only screen and (min-width:641px) {\n  .am-topbar-brand {\n    float: left;\n  }\n}\n.am-topbar-brand a:hover {\n  color: #4d4d4d;\n}\n.am-topbar-collapse {\n  width: 100%;\n  overflow-x: visible;\n  padding: 10px;\n  clear: both;\n  -webkit-overflow-scrolling: touch;\n}\n.am-topbar-collapse:before,\n.am-topbar-collapse:after {\n  content: \" \";\n  display: table;\n}\n.am-topbar-collapse:after {\n  clear: both;\n}\n.am-topbar-collapse.am-in {\n  overflow-y: auto;\n}\n@media only screen and (min-width:641px) {\n  .am-topbar-collapse {\n    margin-top: 0;\n    padding: 0;\n    width: auto;\n    clear: none;\n  }\n  .am-topbar-collapse.am-collapse {\n    display: block !important;\n    height: auto !important;\n    padding: 0;\n    overflow: visible !important;\n  }\n  .am-topbar-collapse.am-in {\n    overflow-y: visible;\n  }\n}\n.am-topbar-brand {\n  padding: 0 10px;\n  float: left;\n  font-size: 1.8rem;\n  height: 50px;\n  line-height: 50px;\n}\n.am-topbar-toggle {\n  position: relative;\n  float: right;\n  margin-right: 10px;\n}\n@media only screen and (min-width:641px) {\n  .am-topbar-toggle {\n    display: none;\n  }\n}\n@media only screen and (max-width: 640px) {\n  .am-topbar-nav {\n    margin-bottom: 8px;\n  }\n  .am-topbar-nav > li {\n    float: none;\n  }\n}\n@media only screen and (max-width: 640px) {\n  .am-topbar-nav > li + li {\n    margin-left: 0;\n    margin-top: 5px;\n  }\n}\n@media only screen and (min-width:641px) {\n  .am-topbar-nav {\n    float: left;\n  }\n  .am-topbar-nav > li > a {\n    position: relative;\n    line-height: 50px;\n    padding: 0 10px;\n  }\n  .am-topbar-nav > li > a:after {\n    position: absolute;\n    left: 50%;\n    margin-left: -7px;\n    bottom: -1px;\n    content: \"\";\n    display: inline-block;\n    width: 0;\n    height: 0;\n    vertical-align: middle;\n    border-bottom: 7px solid #f8f8f8;\n    border-right: 7px solid transparent;\n    border-left: 7px solid transparent;\n    border-top: 0 dotted;\n    -webkit-transform: rotate(360deg);\n        -ms-transform: rotate(360deg);\n            transform: rotate(360deg);\n    opacity: 0;\n    -webkit-transition: opacity .1s;\n    transition: opacity .1s;\n  }\n  .am-topbar-nav > li > a:hover:after {\n    opacity: 1;\n    border-bottom-color: #666;\n  }\n  .am-topbar-nav > li.am-dropdown > a:after {\n    display: none;\n  }\n  .am-topbar-nav > li.am-active > a,\n  .am-topbar-nav > li.am-active > a:hover,\n  .am-topbar-nav > li.am-active > a:focus {\n    border-radius: 0;\n    color: #0e90d2;\n    background: none;\n  }\n  .am-topbar-nav > li.am-active > a:after {\n    opacity: 1;\n    border-bottom-color: #0e90d2;\n  }\n}\n@media only screen and (max-width: 640px) {\n  .am-topbar-collapse .am-dropdown.am-active .am-dropdown-content {\n    float: none;\n    position: relative;\n    width: 100%;\n  }\n}\n@media only screen and (min-width:641px) {\n  .am-topbar-left {\n    float: left;\n  }\n  .am-topbar-right {\n    float: right;\n    margin-right: 10px;\n  }\n}\n@media only screen and (max-width: 640px) {\n  .am-topbar-form .am-form-group {\n    margin-bottom: 5px;\n  }\n}\n@media only screen and (min-width:641px) {\n  .am-topbar-form {\n    padding: 0 10px;\n    margin-top: 8px;\n  }\n  .am-topbar-form .am-form-group + .am-btn {\n    margin-left: 5px;\n  }\n}\n.am-topbar-btn {\n  margin-top: 8px;\n}\n@media only screen and (max-width: 640px) {\n  .am-topbar-collapse .am-topbar-btn,\n  .am-topbar-collapse .am-btn {\n    display: block;\n    width: 100%;\n  }\n}\n.am-topbar-inverse {\n  background-color: #0e90d2;\n  border-color: #0b6fa2;\n  color: #eeeeee;\n}\n.am-topbar-inverse a {\n  color: #eeeeee;\n}\n.am-topbar-inverse .am-topbar-brand a {\n  color: #fff;\n}\n.am-topbar-inverse .am-topbar-brand a:hover,\n.am-topbar-inverse .am-topbar-brand a:focus {\n  color: #fff;\n  background-color: transparent;\n}\n.am-topbar-inverse .am-topbar-nav > li > a {\n  color: #eeeeee;\n}\n.am-topbar-inverse .am-topbar-nav > li > a:hover,\n.am-topbar-inverse .am-topbar-nav > li > a:focus {\n  color: #fff;\n  background-color: rgba(0, 0, 0, 0.05);\n}\n.am-topbar-inverse .am-topbar-nav > li > a:hover:after,\n.am-topbar-inverse .am-topbar-nav > li > a:focus:after {\n  border-bottom-color: #0b6fa2;\n}\n.am-topbar-inverse .am-topbar-nav > li > a:after {\n  border-bottom-color: #0e90d2;\n}\n.am-topbar-inverse .am-topbar-nav > li.am-active > a,\n.am-topbar-inverse .am-topbar-nav > li.am-active > a:hover,\n.am-topbar-inverse .am-topbar-nav > li.am-active > a:focus {\n  color: #fff;\n  background-color: rgba(0, 0, 0, 0.1);\n}\n.am-topbar-inverse .am-topbar-nav > li.am-active > a:after,\n.am-topbar-inverse .am-topbar-nav > li.am-active > a:hover:after,\n.am-topbar-inverse .am-topbar-nav > li.am-active > a:focus:after {\n  border-bottom-color: #fff;\n}\n.am-topbar-inverse .am-topbar-nav > li .disabled > a,\n.am-topbar-inverse .am-topbar-nav > li .disabled > a:hover,\n.am-topbar-inverse .am-topbar-nav > li .disabled > a:focus {\n  color: #444;\n  background-color: transparent;\n}\n.am-topbar-fixed-top,\n.am-topbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1000;\n  -webkit-transform: translate3d(0, 0, 0);\n          transform: translate3d(0, 0, 0);\n}\n.am-topbar-fixed-top {\n  top: 0;\n}\n.am-topbar-fixed-bottom {\n  bottom: 0;\n  margin-bottom: 0;\n  border-width: 1px 0 0;\n}\n.am-with-topbar-fixed-top {\n  padding-top: 51px;\n}\n.am-with-topbar-fixed-bottom {\n  padding-bottom: 51px;\n}\n@media only screen and (max-width: 640px) {\n  .am-topbar-fixed-bottom .am-topbar-collapse {\n    position: absolute;\n    bottom: 100%;\n    margin-bottom: 1px;\n    background-color: #f8f8f8;\n  }\n  .am-topbar-fixed-bottom .am-topbar-collapse .am-dropdown-content:before,\n  .am-topbar-fixed-bottom .am-topbar-collapse .am-dropdown-content:after {\n    display: none;\n  }\n  .am-topbar-fixed-bottom.am-topbar-inverse .am-topbar-collapse {\n    background-color: #0e90d2;\n  }\n}\n/* ==========================================================================\n   Component: Breadcrumb\n ============================================================================ */\n.am-breadcrumb {\n  padding: .7em .5em;\n  margin-bottom: 2rem;\n  list-style: none;\n  background-color: transparent;\n  border-radius: 2px;\n  font-size: 85%;\n}\n.am-breadcrumb > li {\n  display: inline-block;\n}\n.am-breadcrumb > li [class*=\"am-icon-\"]:before {\n  color: #999999;\n  margin-right: 5px;\n}\n.am-breadcrumb > li + li:before {\n  content: \"»\\00a0\";\n  padding: 0 8px;\n  color: #ccc;\n}\n.am-breadcrumb > .am-active {\n  color: #999999;\n}\n.am-breadcrumb-slash > li + li:before {\n  content: \"/\\00a0\";\n}\n/* ==========================================================================\n   Component: Pagination\n ============================================================================ */\n.am-pagination {\n  padding-left: 0;\n  margin: 1.5rem 0;\n  list-style: none;\n  color: #999999;\n  text-align: left;\n}\n.am-pagination:before,\n.am-pagination:after {\n  content: \" \";\n  display: table;\n}\n.am-pagination:after {\n  clear: both;\n}\n.am-pagination > li {\n  display: inline-block;\n}\n.am-pagination > li > a,\n.am-pagination > li > span {\n  position: relative;\n  display: block;\n  padding: 0.5em 1em;\n  text-decoration: none;\n  line-height: 1.2;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  border-radius: 2px;\n  margin-bottom: 5px;\n  margin-right: 5px;\n}\n.am-pagination > li:last-child > a,\n.am-pagination > li:last-child > span {\n  margin-right: 0;\n}\n.am-pagination > li > a:hover,\n.am-pagination > li > span:hover,\n.am-pagination > li > a:focus,\n.am-pagination > li > span:focus {\n  background-color: #eeeeee;\n}\n.am-pagination > .am-active > a,\n.am-pagination > .am-active > span,\n.am-pagination > .am-active > a:hover,\n.am-pagination > .am-active > span:hover,\n.am-pagination > .am-active > a:focus,\n.am-pagination > .am-active > span:focus {\n  z-index: 2;\n  color: #fff;\n  background-color: #0e90d2;\n  border-color: #0e90d2;\n  cursor: default;\n}\n.am-pagination > .am-disabled > span,\n.am-pagination > .am-disabled > span:hover,\n.am-pagination > .am-disabled > span:focus,\n.am-pagination > .am-disabled > a,\n.am-pagination > .am-disabled > a:hover,\n.am-pagination > .am-disabled > a:focus {\n  color: #999999;\n  background-color: #fff;\n  border-color: #ddd;\n  cursor: not-allowed;\n  pointer-events: none;\n}\n.am-pagination .am-pagination-prev {\n  float: left;\n}\n.am-pagination .am-pagination-prev a {\n  border-radius: 2px;\n}\n.am-pagination .am-pagination-next {\n  float: right;\n}\n.am-pagination .am-pagination-next a {\n  border-radius: 2px;\n}\n.am-pagination-centered {\n  text-align: center;\n}\n.am-pagination-right {\n  text-align: right;\n}\n/* ==========================================================================\n   Component: Aniamtion\n ============================================================================ */\n[class*=\"am-animation-\"] {\n  -webkit-animation-duration: 0.5s;\n          animation-duration: 0.5s;\n  -webkit-animation-timing-function: ease-out;\n          animation-timing-function: ease-out;\n  -webkit-animation-fill-mode: both;\n          animation-fill-mode: both;\n}\n/* Hide animated element if scrollSpy is used */\n@media screen {\n  .cssanimations [data-am-scrollspy*=\"animation\"] {\n    opacity: 0;\n  }\n}\n/* Fade */\n.am-animation-fade {\n  -webkit-animation-name: am-fade;\n          animation-name: am-fade;\n  -webkit-animation-duration: 0.8s;\n          animation-duration: 0.8s;\n  -webkit-animation-timing-function: linear;\n          animation-timing-function: linear;\n}\n/* Scale */\n.am-animation-scale-up {\n  -webkit-animation-name: am-scale-up;\n          animation-name: am-scale-up;\n}\n.am-animation-scale-down {\n  -webkit-animation-name: am-scale-down;\n          animation-name: am-scale-down;\n}\n/* Slide */\n.am-animation-slide-top {\n  -webkit-animation-name: am-slide-top;\n          animation-name: am-slide-top;\n}\n.am-animation-slide-bottom {\n  -webkit-animation-name: am-slide-bottom;\n          animation-name: am-slide-bottom;\n}\n.am-animation-slide-left {\n  -webkit-animation-name: am-slide-left;\n          animation-name: am-slide-left;\n}\n.am-animation-slide-right {\n  -webkit-animation-name: am-slide-right;\n          animation-name: am-slide-right;\n}\n.am-animation-slide-top-fixed {\n  -webkit-animation-name: am-slide-top-fixed;\n          animation-name: am-slide-top-fixed;\n}\n/* Shake */\n.am-animation-shake {\n  -webkit-animation-name: am-shake;\n          animation-name: am-shake;\n}\n/* Spin */\n.am-animation-spin {\n  -webkit-animation: am-spin 2s infinite linear;\n          animation: am-spin 2s infinite linear;\n}\n/* Spring */\n.am-animation-left-spring {\n  -webkit-animation: am-left-spring 0.3s ease-in-out;\n          animation: am-left-spring 0.3s ease-in-out;\n}\n.am-animation-right-spring {\n  -webkit-animation: am-right-spring 0.3s ease-in-out;\n          animation: am-right-spring 0.3s ease-in-out;\n}\n.am-animation-reverse {\n  -webkit-animation-direction: reverse;\n          animation-direction: reverse;\n}\n.am-animation-paused {\n  -webkit-animation-play-state: paused !important;\n          animation-play-state: paused !important;\n}\n.am-animation-delay-1 {\n  -webkit-animation-delay: 1s;\n          animation-delay: 1s;\n}\n.am-animation-delay-2 {\n  -webkit-animation-delay: 2s;\n          animation-delay: 2s;\n}\n.am-animation-delay-3 {\n  -webkit-animation-delay: 3s;\n          animation-delay: 3s;\n}\n.am-animation-delay-4 {\n  -webkit-animation-delay: 4s;\n          animation-delay: 4s;\n}\n.am-animation-delay-5 {\n  -webkit-animation-delay: 5s;\n          animation-delay: 5s;\n}\n.am-animation-delay-6 {\n  -webkit-animation-delay: 6s;\n          animation-delay: 6s;\n}\n/* Keyframes\n ============================================================================ */\n/* Fade */\n@-webkit-keyframes am-fade {\n  0% {\n    opacity: 0;\n  }\n  100% {\n    opacity: 1;\n  }\n}\n@keyframes am-fade {\n  0% {\n    opacity: 0;\n  }\n  100% {\n    opacity: 1;\n  }\n}\n/* Scale up */\n@-webkit-keyframes am-scale-up {\n  0% {\n    opacity: 0;\n    -webkit-transform: scale(0.2);\n            transform: scale(0.2);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: scale(1);\n            transform: scale(1);\n  }\n}\n@keyframes am-scale-up {\n  0% {\n    opacity: 0;\n    -webkit-transform: scale(0.2);\n            transform: scale(0.2);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: scale(1);\n            transform: scale(1);\n  }\n}\n/* Scale down */\n@-webkit-keyframes am-scale-down {\n  0% {\n    opacity: 0;\n    -webkit-transform: scale(1.8);\n            transform: scale(1.8);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: scale(1);\n            transform: scale(1);\n  }\n}\n@keyframes am-scale-down {\n  0% {\n    opacity: 0;\n    -webkit-transform: scale(1.8);\n            transform: scale(1.8);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: scale(1);\n            transform: scale(1);\n  }\n}\n/* Slide top */\n@-webkit-keyframes am-slide-top {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(-100%);\n            transform: translateY(-100%);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n            transform: translateY(0);\n  }\n}\n@keyframes am-slide-top {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(-100%);\n            transform: translateY(-100%);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n            transform: translateY(0);\n  }\n}\n/* Slide bottom */\n@-webkit-keyframes am-slide-bottom {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(100%);\n            transform: translateY(100%);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n            transform: translateY(0);\n  }\n}\n@keyframes am-slide-bottom {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(100%);\n            transform: translateY(100%);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n            transform: translateY(0);\n  }\n}\n/* Slide left */\n@-webkit-keyframes am-slide-left {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateX(-100%);\n            transform: translateX(-100%);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n}\n@keyframes am-slide-left {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateX(-100%);\n            transform: translateX(-100%);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n}\n/* Slide right */\n@-webkit-keyframes am-slide-right {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateX(100%);\n            transform: translateX(100%);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n}\n@keyframes am-slide-right {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateX(100%);\n            transform: translateX(100%);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n}\n/* Shake */\n@-webkit-keyframes am-shake {\n  0%,\n  100% {\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n  10% {\n    -webkit-transform: translateX(-9px);\n            transform: translateX(-9px);\n  }\n  20% {\n    -webkit-transform: translateX(8px);\n            transform: translateX(8px);\n  }\n  30% {\n    -webkit-transform: translateX(-7px);\n            transform: translateX(-7px);\n  }\n  40% {\n    -webkit-transform: translateX(6px);\n            transform: translateX(6px);\n  }\n  50% {\n    -webkit-transform: translateX(-5px);\n            transform: translateX(-5px);\n  }\n  60% {\n    -webkit-transform: translateX(4px);\n            transform: translateX(4px);\n  }\n  70% {\n    -webkit-transform: translateX(-3px);\n            transform: translateX(-3px);\n  }\n  80% {\n    -webkit-transform: translateX(2px);\n            transform: translateX(2px);\n  }\n  90% {\n    -webkit-transform: translateX(-1px);\n            transform: translateX(-1px);\n  }\n}\n@keyframes am-shake {\n  0%,\n  100% {\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n  10% {\n    -webkit-transform: translateX(-9px);\n            transform: translateX(-9px);\n  }\n  20% {\n    -webkit-transform: translateX(8px);\n            transform: translateX(8px);\n  }\n  30% {\n    -webkit-transform: translateX(-7px);\n            transform: translateX(-7px);\n  }\n  40% {\n    -webkit-transform: translateX(6px);\n            transform: translateX(6px);\n  }\n  50% {\n    -webkit-transform: translateX(-5px);\n            transform: translateX(-5px);\n  }\n  60% {\n    -webkit-transform: translateX(4px);\n            transform: translateX(4px);\n  }\n  70% {\n    -webkit-transform: translateX(-3px);\n            transform: translateX(-3px);\n  }\n  80% {\n    -webkit-transform: translateX(2px);\n            transform: translateX(2px);\n  }\n  90% {\n    -webkit-transform: translateX(-1px);\n            transform: translateX(-1px);\n  }\n}\n/* Slide top fixed */\n@-webkit-keyframes am-slide-top-fixed {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(-10px);\n            transform: translateY(-10px);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n            transform: translateY(0);\n  }\n}\n@keyframes am-slide-top-fixed {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(-10px);\n            transform: translateY(-10px);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n            transform: translateY(0);\n  }\n}\n/* Slide bottom fixed */\n@-webkit-keyframes am-slide-bottom-fixed {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(10px);\n            transform: translateY(10px);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n            transform: translateY(0);\n  }\n}\n@keyframes am-slide-bottom-fixed {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(10px);\n            transform: translateY(10px);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n            transform: translateY(0);\n  }\n}\n/* Spin */\n@-webkit-keyframes am-spin {\n  0% {\n    -webkit-transform: rotate(0deg);\n            transform: rotate(0deg);\n  }\n  100% {\n    -webkit-transform: rotate(359deg);\n            transform: rotate(359deg);\n  }\n}\n@keyframes am-spin {\n  0% {\n    -webkit-transform: rotate(0deg);\n            transform: rotate(0deg);\n  }\n  100% {\n    -webkit-transform: rotate(359deg);\n            transform: rotate(359deg);\n  }\n}\n/* Spring */\n@-webkit-keyframes am-right-spring {\n  0% {\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n  50% {\n    -webkit-transform: translateX(-20%);\n            transform: translateX(-20%);\n  }\n  100% {\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n}\n@keyframes am-right-spring {\n  0% {\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n  50% {\n    -webkit-transform: translateX(-20%);\n            transform: translateX(-20%);\n  }\n  100% {\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n}\n@-webkit-keyframes am-left-spring {\n  0% {\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n  50% {\n    -webkit-transform: translateX(20%);\n            transform: translateX(20%);\n  }\n  100% {\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n}\n@keyframes am-left-spring {\n  0% {\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n  50% {\n    -webkit-transform: translateX(20%);\n            transform: translateX(20%);\n  }\n  100% {\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n}\n/* ==========================================================================\n   Component: Article\n ============================================================================ */\n.am-article:before,\n.am-article:after {\n  content: \" \";\n  display: table;\n}\n.am-article:after {\n  clear: both;\n}\n.am-article > :last-child {\n  margin-bottom: 0;\n}\n.am-article + .am-article {\n  margin-top: 2.4rem;\n}\n/* Sub-object `.@{ns}article-title` */\n.am-article-title {\n  font-size: 2.8rem;\n  line-height: 1.15;\n  font-weight: normal;\n}\n.am-article-title a {\n  color: inherit;\n  text-decoration: none;\n}\n/* Sub-object `.@{ns}article-meta` */\n.am-article-meta {\n  font-size: 1.2rem;\n  line-height: 1.5;\n  color: #999999;\n}\n/* Sub-object `.@{ns}article-lead` */\n.am-article-lead {\n  color: #666;\n  font-size: 1.4rem;\n  line-height: 1.5;\n  border: 1px solid #dedede;\n  border-radius: 2px;\n  background: #f9f9f9;\n  padding: 10px;\n}\n/* Sub-object `.@{ns}article-divider` */\n.am-article-divider {\n  margin-bottom: 2.4rem;\n  border-color: #eeeeee;\n}\n* + .am-article-divider {\n  margin-top: 2.4rem;\n}\n/* Sub-object `.@{ns}article-bd` */\n.am-article-bd blockquote {\n  font-family: Georgia, \"Times New Roman\", Times, Kai, \"Kaiti SC\", KaiTi, BiauKai, \"FontAwesome\", serif;\n}\n.am-article-bd img {\n  display: block;\n  max-width: 100%;\n}\n/* ==========================================================================\n   Component: Badge\n ============================================================================ */\n.am-badge {\n  display: inline-block;\n  min-width: 10px;\n  padding: 0.25em 0.625em;\n  font-size: 1.2rem;\n  font-weight: bold;\n  color: #fff;\n  line-height: 1;\n  vertical-align: baseline;\n  white-space: nowrap;\n  text-align: center;\n  background-color: #999999;\n  border-radius: 0;\n}\n.am-badge:empty {\n  display: none;\n}\n.am-badge.am-square {\n  border-radius: 0;\n}\n.am-badge.am-radius {\n  border-radius: 2px;\n}\n.am-badge.am-round {\n  border-radius: 1000px;\n}\na.am-badge:hover,\na.am-badge:focus {\n  color: #fff;\n  text-decoration: none;\n  cursor: pointer;\n}\n.am-badge-primary {\n  background-color: #0e90d2;\n}\n.am-badge-secondary {\n  background-color: #3bb4f2;\n}\n.am-badge-success {\n  background-color: #5eb95e;\n}\n.am-badge-warning {\n  background-color: #F37B1D;\n}\n.am-badge-danger {\n  background-color: #dd514c;\n}\n/* ==========================================================================\n   Component: Comment\n ============================================================================ */\n.am-comment:before,\n.am-comment:after {\n  content: \" \";\n  display: table;\n}\n.am-comment:after {\n  clear: both;\n}\n.am-comment-avatar {\n  float: left;\n  width: 32px;\n  height: 32px;\n  border-radius: 50%;\n  border: 1px solid transparent;\n}\n@media only screen and (min-width:641px) {\n  .am-comment-avatar {\n    width: 48px;\n    height: 48px;\n  }\n}\n.am-comment-main {\n  position: relative;\n  margin-left: 42px;\n  border: 1px solid #dedede;\n  border-radius: 2px;\n}\n.am-comment-main:before,\n.am-comment-main:after {\n  position: absolute;\n  top: 10px;\n  left: -8px;\n  right: 100%;\n  width: 0;\n  height: 0;\n  display: block;\n  content: \" \";\n  border-color: transparent;\n  border-style: solid solid outset;\n  border-width: 8px 8px 8px 0;\n  pointer-events: none;\n}\n.am-comment-main:before {\n  border-right-color: #dedede;\n  z-index: 1;\n}\n.am-comment-main:after {\n  border-right-color: #f8f8f8;\n  margin-left: 1px;\n  z-index: 2;\n}\n@media only screen and (min-width:641px) {\n  .am-comment-main {\n    margin-left: 63px;\n  }\n}\n.am-comment-hd {\n  background: #f8f8f8;\n  border-bottom: 1px solid #eee;\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -ms-flexbox;\n  display: flex;\n}\n.am-comment-title {\n  margin: 0 0 8px 0;\n  font-size: 1.6rem;\n  line-height: 1.2;\n}\n.am-comment-meta {\n  -webkit-box-flex: 1;\n  -webkit-flex: 1;\n      -ms-flex: 1;\n          flex: 1;\n  padding: 10px 15px;\n  font-size: 13px;\n  color: #999999;\n  line-height: 1.2;\n  white-space: nowrap;\n  text-overflow: ellipsis;\n  overflow: hidden;\n}\n.am-comment-meta a {\n  color: #999999;\n}\n.am-comment-author {\n  font-weight: bold;\n  color: #999999;\n}\n.am-comment-bd {\n  padding: 15px;\n  overflow: hidden;\n}\n.am-comment-bd > :last-child {\n  margin-bottom: 0;\n}\n.am-comment-footer {\n  padding: 0 15px 5px;\n}\n.am-comment-footer .am-comment-actions a + a {\n  margin-left: 5px;\n}\n.am-comment-actions {\n  font-size: 13px;\n  color: #999999;\n}\n.am-comment-actions a {\n  display: inline-block;\n  padding: 10px 5px;\n  line-height: 1;\n  color: #999999;\n  opacity: .7;\n}\n.am-comment-actions a:hover {\n  color: #0e90d2;\n  opacity: 1;\n}\n.am-comment-hd .am-comment-actions {\n  padding-right: .5rem;\n}\n.am-comment-flip .am-comment-avatar {\n  float: right;\n}\n.am-comment-flip .am-comment-main {\n  margin-left: auto;\n  margin-right: 42px;\n}\n@media only screen and (min-width:641px) {\n  .am-comment-flip .am-comment-main {\n    margin-right: 63px;\n  }\n}\n.am-comment-flip .am-comment-main:before,\n.am-comment-flip .am-comment-main:after {\n  left: auto;\n  right: -8px;\n  border-width: 8px 0 8px 8px;\n}\n.am-comment-flip .am-comment-main:before {\n  border-left-color: #dedede;\n}\n.am-comment-flip .am-comment-main:after {\n  border-left-color: #f8f8f8;\n  margin-right: 1px;\n  margin-left: auto;\n}\n.am-comment-primary .am-comment-avatar {\n  border-color: #0e90d2;\n}\n.am-comment-primary .am-comment-main {\n  border-color: #0e90d2;\n}\n.am-comment-primary .am-comment-main:before {\n  border-right-color: #0e90d2;\n}\n.am-comment-primary.am-comment-flip .am-comment-main:before {\n  border-left-color: #0e90d2;\n  border-right-color: transparent;\n}\n.am-comment-primary.am-comment-flip .am-comment-main:after {\n  border-left-color: #f8f8f8;\n}\n.am-comment-secondary .am-comment-avatar,\n.am-comment-highlight .am-comment-avatar {\n  border-color: #3bb4f2;\n}\n.am-comment-secondary .am-comment-main,\n.am-comment-highlight .am-comment-main {\n  border-color: #3bb4f2;\n}\n.am-comment-secondary .am-comment-main:before,\n.am-comment-highlight .am-comment-main:before {\n  border-right-color: #3bb4f2;\n}\n.am-comment-secondary.am-comment-flip .am-comment-main:before,\n.am-comment-highlight.am-comment-flip .am-comment-main:before {\n  border-left-color: #3bb4f2;\n  border-right-color: transparent;\n}\n.am-comment-secondary.am-comment-flip .am-comment-main:after,\n.am-comment-highlight.am-comment-flip .am-comment-main:after {\n  border-left-color: #f8f8f8;\n}\n.am-comment-success .am-comment-avatar {\n  border-color: #5eb95e;\n}\n.am-comment-success .am-comment-main {\n  border-color: #5eb95e;\n}\n.am-comment-success .am-comment-main:before {\n  border-right-color: #5eb95e;\n}\n.am-comment-success.am-comment-flip .am-comment-main:before {\n  border-left-color: #5eb95e;\n  border-right-color: transparent;\n}\n.am-comment-success.am-comment-flip .am-comment-main:after {\n  border-left-color: #f8f8f8;\n}\n.am-comment-warning .am-comment-avatar {\n  border-color: #F37B1D;\n}\n.am-comment-warning .am-comment-main {\n  border-color: #F37B1D;\n}\n.am-comment-warning .am-comment-main:before {\n  border-right-color: #F37B1D;\n}\n.am-comment-warning.am-comment-flip .am-comment-main:before {\n  border-left-color: #F37B1D;\n  border-right-color: transparent;\n}\n.am-comment-warning.am-comment-flip .am-comment-main:after {\n  border-left-color: #f8f8f8;\n}\n.am-comment-danger .am-comment-avatar {\n  border-color: #dd514c;\n}\n.am-comment-danger .am-comment-main {\n  border-color: #dd514c;\n}\n.am-comment-danger .am-comment-main:before {\n  border-right-color: #dd514c;\n}\n.am-comment-danger.am-comment-flip .am-comment-main:before {\n  border-left-color: #dd514c;\n  border-right-color: transparent;\n}\n.am-comment-danger.am-comment-flip .am-comment-main:after {\n  border-left-color: #f8f8f8;\n}\n.am-comments-list {\n  padding: 0;\n  list-style: none;\n}\n.am-comments-list .am-comment {\n  margin: 1.6rem 0 0 0;\n  list-style: none;\n}\n@media only screen and (min-width:641px) {\n  .am-comments-list-flip .am-comment-main {\n    margin-right: 64px;\n  }\n  .am-comments-list-flip .am-comment-flip .am-comment-main {\n    margin-left: 64px;\n  }\n}\n/* ==========================================================================\n   Component: Button Group\n ============================================================================ */\n.am-btn-group,\n.am-btn-group-stacked {\n  position: relative;\n  display: inline-block;\n  vertical-align: middle;\n}\n.am-btn-group > .am-btn,\n.am-btn-group-stacked > .am-btn {\n  position: relative;\n  float: left;\n}\n.am-btn-group > .am-btn:hover,\n.am-btn-group-stacked > .am-btn:hover,\n.am-btn-group > .am-btn:focus,\n.am-btn-group-stacked > .am-btn:focus,\n.am-btn-group > .am-btn:active,\n.am-btn-group-stacked > .am-btn:active,\n.am-btn-group > .am-btn.active,\n.am-btn-group-stacked > .am-btn.active {\n  z-index: 2;\n}\n.am-btn-group > .am-btn:focus,\n.am-btn-group-stacked > .am-btn:focus {\n  outline: 0;\n}\n.am-btn-group .am-btn + .am-btn,\n.am-btn-group .am-btn + .am-btn-group,\n.am-btn-group .am-btn-group + .am-btn,\n.am-btn-group .am-btn-group + .am-btn-group {\n  margin-left: -1px;\n}\n.am-btn-toolbar {\n  margin-left: -5px;\n}\n.am-btn-toolbar:before,\n.am-btn-toolbar:after {\n  content: \" \";\n  display: table;\n}\n.am-btn-toolbar:after {\n  clear: both;\n}\n.am-btn-toolbar .am-btn-group,\n.am-btn-toolbar .am-input-group {\n  float: left;\n}\n.am-btn-toolbar > .am-btn,\n.am-btn-toolbar > .am-btn-group,\n.am-btn-toolbar > .am-input-group {\n  margin-left: 5px;\n}\n.am-btn-group > .am-btn:not(:first-child):not(:last-child):not(.am-dropdown-toggle) {\n  border-radius: 0;\n}\n.am-btn-group > .am-btn:first-child {\n  margin-left: 0;\n}\n.am-btn-group > .am-btn:first-child:not(:last-child):not(.am-dropdown-toggle) {\n  border-bottom-right-radius: 0;\n  border-top-right-radius: 0;\n}\n.am-btn-group > .am-btn:last-child:not(:first-child),\n.am-btn-group > .am-dropdown-toggle:not(:first-child) {\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n}\n.am-btn-group > .am-btn-group {\n  float: left;\n}\n.am-btn-group > .am-btn-group:not(:first-child):not(:last-child) > .am-btn {\n  border-radius: 0;\n}\n.am-btn-group > .am-btn-group:first-child > .am-btn:last-child,\n.am-btn-group > .am-btn-group:first-child > .am-dropdown-toggle {\n  border-bottom-right-radius: 0;\n  border-top-right-radius: 0;\n}\n.am-btn-group > .am-btn-group:last-child > .am-btn:first-child {\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n}\n.am-btn-group-xs > .am-btn {\n  font-size: 1.2rem;\n}\n.am-btn-group-sm > .am-btn {\n  font-size: 1.4rem;\n}\n.am-btn-group-lg > .am-btn {\n  font-size: 1.8rem;\n}\n.am-btn-group-stacked > .am-btn,\n.am-btn-group-stacked > .am-btn-group,\n.am-btn-group-stacked > .am-btn-group > .am-btn {\n  display: block;\n  float: none;\n  width: 100%;\n  max-width: 100%;\n}\n.am-btn-group-stacked > .am-btn-group:before,\n.am-btn-group-stacked > .am-btn-group:after {\n  content: \" \";\n  display: table;\n}\n.am-btn-group-stacked > .am-btn-group:after {\n  clear: both;\n}\n.am-btn-group-stacked > .am-btn-group > .am-btn {\n  float: none;\n}\n.am-btn-group-stacked > .am-btn + .am-btn,\n.am-btn-group-stacked > .am-btn + .am-btn-group,\n.am-btn-group-stacked > .am-btn-group + .am-btn,\n.am-btn-group-stacked > .am-btn-group + .am-btn-group {\n  margin-top: -1px;\n  margin-left: 0;\n}\n.am-btn-group-stacked > .am-btn:not(:first-child):not(:last-child) {\n  border-radius: 0;\n}\n.am-btn-group-stacked > .am-btn:first-child:not(:last-child) {\n  border-top-right-radius: 2px;\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n.am-btn-group-stacked > .am-btn:last-child:not(:first-child) {\n  border-bottom-left-radius: 2px;\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n.am-btn-group-stacked > .am-btn-group:not(:first-child):not(:last-child) > .am-btn {\n  border-radius: 0;\n}\n.am-btn-group-stacked > .am-btn-group:first-child:not(:last-child) > .am-btn:last-child,\n.am-btn-group-stacked > .am-btn-group:first-child:not(:last-child) > .am-dropdown-toggle {\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n.am-btn-group-stacked > .am-btn-group:last-child:not(:first-child) > .am-btn:first-child {\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n.am-btn-group-justify {\n  display: table;\n  table-layout: fixed;\n  border-collapse: separate;\n  width: 100%;\n}\n.am-btn-group-justify > .am-btn,\n.am-btn-group-justify > .am-btn-group {\n  float: none;\n  display: table-cell;\n  width: 1%;\n}\n.am-btn-group-justify > .am-btn-group .am-btn {\n  width: 100%;\n}\n.lte9 .am-btn-group-justify {\n  display: table;\n  table-layout: fixed;\n  border-collapse: separate;\n}\n.lte9 .am-btn-group-justify > .am-btn,\n.lte9 .am-btn-group-justify > .am-btn-group {\n  float: none;\n  display: table-cell;\n  width: 1%;\n}\n.am-btn-group .am-dropdown {\n  float: left;\n  margin-left: -1px;\n}\n.am-btn-group .am-dropdown > .am-btn {\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n}\n.am-btn-group .am-active .am-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.am-btn-group .am-active .am-dropdown-toggle.am-btn-link {\n  -webkit-box-shadow: none;\n          box-shadow: none;\n}\n.am-btn-group .am-dropdown-toggle:active,\n.am-btn-group .am-active .am-dropdown-toggle {\n  outline: 0;\n}\n[data-am-button] > .am-btn > input[type=\"radio\"],\n[data-am-button] > .am-btn > input[type=\"checkbox\"],\n.am-btn-group-check > .am-btn > input[type=\"radio\"],\n.am-btn-group-check > .am-btn > input[type=\"checkbox\"] {\n  position: absolute;\n  z-index: -1;\n  opacity: 0;\n}\n/* ==========================================================================\n   Component: Close\n ============================================================================ */\n.am-close {\n  display: inline-block;\n  text-align: center;\n  width: 24px;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 24px;\n  color: #000;\n  text-shadow: 0 1px 0 #fff;\n  opacity: .2;\n  -webkit-transition: all .3s;\n  transition: all .3s;\n}\n.am-close:hover,\n.am-close:focus {\n  color: #000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: .5;\n  outline: none;\n}\n.am-close[class*=\"am-icon-\"] {\n  font-size: 16px;\n}\nbutton.am-close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  /* Needed for Sarari */\n  border: 0;\n  -webkit-appearance: none;\n}\na.am-close:hover {\n  color: inherit;\n  text-decoration: none;\n  cursor: pointer;\n}\n/* Modifiers\n ============================================================================ */\n.am-close-alt {\n  border-radius: 50%;\n  background: #eee;\n  opacity: 0.7;\n  -webkit-box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25);\n          box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25);\n  /* Hover */\n}\n.am-close-alt:hover,\n.am-close-alt:focus {\n  opacity: 1;\n}\n.am-close-spin:hover {\n  -webkit-transform: rotate(360deg);\n      -ms-transform: rotate(360deg);\n          transform: rotate(360deg);\n}\n/* ==========================================================================\n   Component: Icon\n ============================================================================ */\n/* Font-face\n============================================================================= */\n@font-face {\n  font-family: 'FontAwesome';\n  src: url('../fonts/fontawesome-webfont.eot?v=4.5.0');\n  src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.5.0') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff2?v=4.5.0') format('woff2'), url('../fonts/fontawesome-webfont.woff?v=4.5.0') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.5.0') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.5.0#fontawesomeregular') format('svg');\n  font-weight: normal;\n  font-style: normal;\n}\n/* Component\n============================================================================= */\n[class*=\"am-icon-\"] {\n  display: inline-block;\n  font-style: normal;\n}\n[class*=\"am-icon-\"]:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n}\n.am-icon-border {\n  padding: .2em .25em .15em;\n  border: solid 0.08em #eee;\n  border-radius: .1em;\n}\n[class*=\"am-icon-\"].am-fl {\n  margin-right: .3em;\n}\n[class*=\"am-icon-\"].am-fr {\n  margin-left: .3em;\n}\n.am-icon-sm:before {\n  font-size: 150%;\n  vertical-align: -10%;\n}\n.am-icon-md:before {\n  font-size: 200%;\n  vertical-align: -16%;\n}\n.am-icon-lg:before {\n  font-size: 250%;\n  vertical-align: -22%;\n}\n/* Modifier: `.am-icon-btn`\n============================================================================= */\n.am-icon-btn {\n  -webkit-box-sizing: border-box;\n          box-sizing: border-box;\n  display: inline-block;\n  width: 48px;\n  height: 48px;\n  font-size: 24px;\n  line-height: 48px;\n  border-radius: 50%;\n  background-color: #eee;\n  color: #555555;\n  text-align: center;\n  /**\n   * Hover\n   * 1. Apply hover style also to focus state\n   * 2. Remove default focus style\n   */\n  /* Active */\n}\n.am-icon-btn:hover,\n.am-icon-btn:focus {\n  /* 1 */\n  background-color: #f5f5f5;\n  color: #333333;\n  text-decoration: none;\n  outline: none;\n  /* 2 */\n}\n.am-icon-btn:active {\n  background-color: #ddd;\n  color: #333333;\n}\n.am-icon-btn.am-primary,\n.am-icon-btn.am-secondary,\n.am-icon-btn.am-success,\n.am-icon-btn.am-warning,\n.am-icon-btn.am-danger {\n  color: #fff;\n}\n.am-icon-btn.am-primary {\n  background-color: #0e90d2;\n}\n.am-icon-btn.am-secondary {\n  background-color: #3bb4f2;\n}\n.am-icon-btn.am-success {\n  background-color: #5eb95e;\n}\n.am-icon-btn.am-warning {\n  background-color: #F37B1D;\n}\n.am-icon-btn.am-danger {\n  background-color: #dd514c;\n}\n.am-icon-btn-sm {\n  width: 32px;\n  height: 32px;\n  font-size: 16px;\n  line-height: 32px;\n}\n.am-icon-btn-lg {\n  width: 64px;\n  height: 64px;\n  font-size: 28px;\n  line-height: 64px;\n}\n/* Modifier: `.am-icon-fw` Fixed width\n============================================================================= */\n.am-icon-fw {\n  width: 1.25em;\n  text-align: center;\n}\n/* Icon mapping\n============================================================================= */\n.am-icon-glass:before {\n  content: \"\\f000\";\n}\n.am-icon-music:before {\n  content: \"\\f001\";\n}\n.am-icon-search:before {\n  content: \"\\f002\";\n}\n.am-icon-envelope-o:before {\n  content: \"\\f003\";\n}\n.am-icon-heart:before {\n  content: \"\\f004\";\n}\n.am-icon-star:before {\n  content: \"\\f005\";\n}\n.am-icon-star-o:before {\n  content: \"\\f006\";\n}\n.am-icon-user:before {\n  content: \"\\f007\";\n}\n.am-icon-film:before {\n  content: \"\\f008\";\n}\n.am-icon-th-large:before {\n  content: \"\\f009\";\n}\n.am-icon-th:before {\n  content: \"\\f00a\";\n}\n.am-icon-th-list:before {\n  content: \"\\f00b\";\n}\n.am-icon-check:before {\n  content: \"\\f00c\";\n}\n.am-icon-remove:before,\n.am-icon-close:before,\n.am-icon-times:before {\n  content: \"\\f00d\";\n}\n.am-icon-search-plus:before {\n  content: \"\\f00e\";\n}\n.am-icon-search-minus:before {\n  content: \"\\f010\";\n}\n.am-icon-power-off:before {\n  content: \"\\f011\";\n}\n.am-icon-signal:before {\n  content: \"\\f012\";\n}\n.am-icon-gear:before,\n.am-icon-cog:before {\n  content: \"\\f013\";\n}\n.am-icon-trash-o:before {\n  content: \"\\f014\";\n}\n.am-icon-home:before {\n  content: \"\\f015\";\n}\n.am-icon-file-o:before {\n  content: \"\\f016\";\n}\n.am-icon-clock-o:before {\n  content: \"\\f017\";\n}\n.am-icon-road:before {\n  content: \"\\f018\";\n}\n.am-icon-download:before {\n  content: \"\\f019\";\n}\n.am-icon-arrow-circle-o-down:before {\n  content: \"\\f01a\";\n}\n.am-icon-arrow-circle-o-up:before {\n  content: \"\\f01b\";\n}\n.am-icon-inbox:before {\n  content: \"\\f01c\";\n}\n.am-icon-play-circle-o:before {\n  content: \"\\f01d\";\n}\n.am-icon-rotate-right:before,\n.am-icon-repeat:before {\n  content: \"\\f01e\";\n}\n.am-icon-refresh:before {\n  content: \"\\f021\";\n}\n.am-icon-list-alt:before {\n  content: \"\\f022\";\n}\n.am-icon-lock:before {\n  content: \"\\f023\";\n}\n.am-icon-flag:before {\n  content: \"\\f024\";\n}\n.am-icon-headphones:before {\n  content: \"\\f025\";\n}\n.am-icon-volume-off:before {\n  content: \"\\f026\";\n}\n.am-icon-volume-down:before {\n  content: \"\\f027\";\n}\n.am-icon-volume-up:before {\n  content: \"\\f028\";\n}\n.am-icon-qrcode:before {\n  content: \"\\f029\";\n}\n.am-icon-barcode:before {\n  content: \"\\f02a\";\n}\n.am-icon-tag:before {\n  content: \"\\f02b\";\n}\n.am-icon-tags:before {\n  content: \"\\f02c\";\n}\n.am-icon-book:before {\n  content: \"\\f02d\";\n}\n.am-icon-bookmark:before {\n  content: \"\\f02e\";\n}\n.am-icon-print:before {\n  content: \"\\f02f\";\n}\n.am-icon-camera:before {\n  content: \"\\f030\";\n}\n.am-icon-font:before {\n  content: \"\\f031\";\n}\n.am-icon-bold:before {\n  content: \"\\f032\";\n}\n.am-icon-italic:before {\n  content: \"\\f033\";\n}\n.am-icon-text-height:before {\n  content: \"\\f034\";\n}\n.am-icon-text-width:before {\n  content: \"\\f035\";\n}\n.am-icon-align-left:before {\n  content: \"\\f036\";\n}\n.am-icon-align-center:before {\n  content: \"\\f037\";\n}\n.am-icon-align-right:before {\n  content: \"\\f038\";\n}\n.am-icon-align-justify:before {\n  content: \"\\f039\";\n}\n.am-icon-list:before {\n  content: \"\\f03a\";\n}\n.am-icon-dedent:before,\n.am-icon-outdent:before {\n  content: \"\\f03b\";\n}\n.am-icon-indent:before {\n  content: \"\\f03c\";\n}\n.am-icon-video-camera:before {\n  content: \"\\f03d\";\n}\n.am-icon-photo:before,\n.am-icon-image:before,\n.am-icon-picture-o:before {\n  content: \"\\f03e\";\n}\n.am-icon-pencil:before {\n  content: \"\\f040\";\n}\n.am-icon-map-marker:before {\n  content: \"\\f041\";\n}\n.am-icon-adjust:before {\n  content: \"\\f042\";\n}\n.am-icon-tint:before {\n  content: \"\\f043\";\n}\n.am-icon-edit:before,\n.am-icon-pencil-square-o:before {\n  content: \"\\f044\";\n}\n.am-icon-share-square-o:before {\n  content: \"\\f045\";\n}\n.am-icon-check-square-o:before {\n  content: \"\\f046\";\n}\n.am-icon-arrows:before {\n  content: \"\\f047\";\n}\n.am-icon-step-backward:before {\n  content: \"\\f048\";\n}\n.am-icon-fast-backward:before {\n  content: \"\\f049\";\n}\n.am-icon-backward:before {\n  content: \"\\f04a\";\n}\n.am-icon-play:before {\n  content: \"\\f04b\";\n}\n.am-icon-pause:before {\n  content: \"\\f04c\";\n}\n.am-icon-stop:before {\n  content: \"\\f04d\";\n}\n.am-icon-forward:before {\n  content: \"\\f04e\";\n}\n.am-icon-fast-forward:before {\n  content: \"\\f050\";\n}\n.am-icon-step-forward:before {\n  content: \"\\f051\";\n}\n.am-icon-eject:before {\n  content: \"\\f052\";\n}\n.am-icon-chevron-left:before {\n  content: \"\\f053\";\n}\n.am-icon-chevron-right:before {\n  content: \"\\f054\";\n}\n.am-icon-plus-circle:before {\n  content: \"\\f055\";\n}\n.am-icon-minus-circle:before {\n  content: \"\\f056\";\n}\n.am-icon-times-circle:before {\n  content: \"\\f057\";\n}\n.am-icon-check-circle:before {\n  content: \"\\f058\";\n}\n.am-icon-question-circle:before {\n  content: \"\\f059\";\n}\n.am-icon-info-circle:before {\n  content: \"\\f05a\";\n}\n.am-icon-crosshairs:before {\n  content: \"\\f05b\";\n}\n.am-icon-times-circle-o:before {\n  content: \"\\f05c\";\n}\n.am-icon-check-circle-o:before {\n  content: \"\\f05d\";\n}\n.am-icon-ban:before {\n  content: \"\\f05e\";\n}\n.am-icon-arrow-left:before {\n  content: \"\\f060\";\n}\n.am-icon-arrow-right:before {\n  content: \"\\f061\";\n}\n.am-icon-arrow-up:before {\n  content: \"\\f062\";\n}\n.am-icon-arrow-down:before {\n  content: \"\\f063\";\n}\n.am-icon-mail-forward:before,\n.am-icon-share:before {\n  content: \"\\f064\";\n}\n.am-icon-expand:before {\n  content: \"\\f065\";\n}\n.am-icon-compress:before {\n  content: \"\\f066\";\n}\n.am-icon-plus:before {\n  content: \"\\f067\";\n}\n.am-icon-minus:before {\n  content: \"\\f068\";\n}\n.am-icon-asterisk:before {\n  content: \"\\f069\";\n}\n.am-icon-exclamation-circle:before {\n  content: \"\\f06a\";\n}\n.am-icon-gift:before {\n  content: \"\\f06b\";\n}\n.am-icon-leaf:before {\n  content: \"\\f06c\";\n}\n.am-icon-fire:before {\n  content: \"\\f06d\";\n}\n.am-icon-eye:before {\n  content: \"\\f06e\";\n}\n.am-icon-eye-slash:before {\n  content: \"\\f070\";\n}\n.am-icon-warning:before,\n.am-icon-exclamation-triangle:before {\n  content: \"\\f071\";\n}\n.am-icon-plane:before {\n  content: \"\\f072\";\n}\n.am-icon-calendar:before {\n  content: \"\\f073\";\n}\n.am-icon-random:before {\n  content: \"\\f074\";\n}\n.am-icon-comment:before {\n  content: \"\\f075\";\n}\n.am-icon-magnet:before {\n  content: \"\\f076\";\n}\n.am-icon-chevron-up:before {\n  content: \"\\f077\";\n}\n.am-icon-chevron-down:before {\n  content: \"\\f078\";\n}\n.am-icon-retweet:before {\n  content: \"\\f079\";\n}\n.am-icon-shopping-cart:before {\n  content: \"\\f07a\";\n}\n.am-icon-folder:before {\n  content: \"\\f07b\";\n}\n.am-icon-folder-open:before {\n  content: \"\\f07c\";\n}\n.am-icon-arrows-v:before {\n  content: \"\\f07d\";\n}\n.am-icon-arrows-h:before {\n  content: \"\\f07e\";\n}\n.am-icon-bar-chart-o:before,\n.am-icon-bar-chart:before {\n  content: \"\\f080\";\n}\n.am-icon-twitter-square:before {\n  content: \"\\f081\";\n}\n.am-icon-facebook-square:before {\n  content: \"\\f082\";\n}\n.am-icon-camera-retro:before {\n  content: \"\\f083\";\n}\n.am-icon-key:before {\n  content: \"\\f084\";\n}\n.am-icon-gears:before,\n.am-icon-cogs:before {\n  content: \"\\f085\";\n}\n.am-icon-comments:before {\n  content: \"\\f086\";\n}\n.am-icon-thumbs-o-up:before {\n  content: \"\\f087\";\n}\n.am-icon-thumbs-o-down:before {\n  content: \"\\f088\";\n}\n.am-icon-star-half:before {\n  content: \"\\f089\";\n}\n.am-icon-heart-o:before {\n  content: \"\\f08a\";\n}\n.am-icon-sign-out:before {\n  content: \"\\f08b\";\n}\n.am-icon-linkedin-square:before {\n  content: \"\\f08c\";\n}\n.am-icon-thumb-tack:before {\n  content: \"\\f08d\";\n}\n.am-icon-external-link:before {\n  content: \"\\f08e\";\n}\n.am-icon-sign-in:before {\n  content: \"\\f090\";\n}\n.am-icon-trophy:before {\n  content: \"\\f091\";\n}\n.am-icon-github-square:before {\n  content: \"\\f092\";\n}\n.am-icon-upload:before {\n  content: \"\\f093\";\n}\n.am-icon-lemon-o:before {\n  content: \"\\f094\";\n}\n.am-icon-phone:before {\n  content: \"\\f095\";\n}\n.am-icon-square-o:before {\n  content: \"\\f096\";\n}\n.am-icon-bookmark-o:before {\n  content: \"\\f097\";\n}\n.am-icon-phone-square:before {\n  content: \"\\f098\";\n}\n.am-icon-twitter:before {\n  content: \"\\f099\";\n}\n.am-icon-facebook-f:before,\n.am-icon-facebook:before {\n  content: \"\\f09a\";\n}\n.am-icon-github:before {\n  content: \"\\f09b\";\n}\n.am-icon-unlock:before {\n  content: \"\\f09c\";\n}\n.am-icon-credit-card:before {\n  content: \"\\f09d\";\n}\n.am-icon-feed:before,\n.am-icon-rss:before {\n  content: \"\\f09e\";\n}\n.am-icon-hdd-o:before {\n  content: \"\\f0a0\";\n}\n.am-icon-bullhorn:before {\n  content: \"\\f0a1\";\n}\n.am-icon-bell:before {\n  content: \"\\f0f3\";\n}\n.am-icon-certificate:before {\n  content: \"\\f0a3\";\n}\n.am-icon-hand-o-right:before {\n  content: \"\\f0a4\";\n}\n.am-icon-hand-o-left:before {\n  content: \"\\f0a5\";\n}\n.am-icon-hand-o-up:before {\n  content: \"\\f0a6\";\n}\n.am-icon-hand-o-down:before {\n  content: \"\\f0a7\";\n}\n.am-icon-arrow-circle-left:before {\n  content: \"\\f0a8\";\n}\n.am-icon-arrow-circle-right:before {\n  content: \"\\f0a9\";\n}\n.am-icon-arrow-circle-up:before {\n  content: \"\\f0aa\";\n}\n.am-icon-arrow-circle-down:before {\n  content: \"\\f0ab\";\n}\n.am-icon-globe:before {\n  content: \"\\f0ac\";\n}\n.am-icon-wrench:before {\n  content: \"\\f0ad\";\n}\n.am-icon-tasks:before {\n  content: \"\\f0ae\";\n}\n.am-icon-filter:before {\n  content: \"\\f0b0\";\n}\n.am-icon-briefcase:before {\n  content: \"\\f0b1\";\n}\n.am-icon-arrows-alt:before {\n  content: \"\\f0b2\";\n}\n.am-icon-group:before,\n.am-icon-users:before {\n  content: \"\\f0c0\";\n}\n.am-icon-chain:before,\n.am-icon-link:before {\n  content: \"\\f0c1\";\n}\n.am-icon-cloud:before {\n  content: \"\\f0c2\";\n}\n.am-icon-flask:before {\n  content: \"\\f0c3\";\n}\n.am-icon-cut:before,\n.am-icon-scissors:before {\n  content: \"\\f0c4\";\n}\n.am-icon-copy:before,\n.am-icon-files-o:before {\n  content: \"\\f0c5\";\n}\n.am-icon-paperclip:before {\n  content: \"\\f0c6\";\n}\n.am-icon-save:before,\n.am-icon-floppy-o:before {\n  content: \"\\f0c7\";\n}\n.am-icon-square:before {\n  content: \"\\f0c8\";\n}\n.am-icon-navicon:before,\n.am-icon-reorder:before,\n.am-icon-bars:before {\n  content: \"\\f0c9\";\n}\n.am-icon-list-ul:before {\n  content: \"\\f0ca\";\n}\n.am-icon-list-ol:before {\n  content: \"\\f0cb\";\n}\n.am-icon-strikethrough:before {\n  content: \"\\f0cc\";\n}\n.am-icon-underline:before {\n  content: \"\\f0cd\";\n}\n.am-icon-table:before {\n  content: \"\\f0ce\";\n}\n.am-icon-magic:before {\n  content: \"\\f0d0\";\n}\n.am-icon-truck:before {\n  content: \"\\f0d1\";\n}\n.am-icon-pinterest:before {\n  content: \"\\f0d2\";\n}\n.am-icon-pinterest-square:before {\n  content: \"\\f0d3\";\n}\n.am-icon-google-plus-square:before {\n  content: \"\\f0d4\";\n}\n.am-icon-google-plus:before {\n  content: \"\\f0d5\";\n}\n.am-icon-money:before {\n  content: \"\\f0d6\";\n}\n.am-icon-caret-down:before {\n  content: \"\\f0d7\";\n}\n.am-icon-caret-up:before {\n  content: \"\\f0d8\";\n}\n.am-icon-caret-left:before {\n  content: \"\\f0d9\";\n}\n.am-icon-caret-right:before {\n  content: \"\\f0da\";\n}\n.am-icon-columns:before {\n  content: \"\\f0db\";\n}\n.am-icon-unsorted:before,\n.am-icon-sort:before {\n  content: \"\\f0dc\";\n}\n.am-icon-sort-down:before,\n.am-icon-sort-desc:before {\n  content: \"\\f0dd\";\n}\n.am-icon-sort-up:before,\n.am-icon-sort-asc:before {\n  content: \"\\f0de\";\n}\n.am-icon-envelope:before {\n  content: \"\\f0e0\";\n}\n.am-icon-linkedin:before {\n  content: \"\\f0e1\";\n}\n.am-icon-rotate-left:before,\n.am-icon-undo:before {\n  content: \"\\f0e2\";\n}\n.am-icon-legal:before,\n.am-icon-gavel:before {\n  content: \"\\f0e3\";\n}\n.am-icon-dashboard:before,\n.am-icon-tachometer:before {\n  content: \"\\f0e4\";\n}\n.am-icon-comment-o:before {\n  content: \"\\f0e5\";\n}\n.am-icon-comments-o:before {\n  content: \"\\f0e6\";\n}\n.am-icon-flash:before,\n.am-icon-bolt:before {\n  content: \"\\f0e7\";\n}\n.am-icon-sitemap:before {\n  content: \"\\f0e8\";\n}\n.am-icon-umbrella:before {\n  content: \"\\f0e9\";\n}\n.am-icon-paste:before,\n.am-icon-clipboard:before {\n  content: \"\\f0ea\";\n}\n.am-icon-lightbulb-o:before {\n  content: \"\\f0eb\";\n}\n.am-icon-exchange:before {\n  content: \"\\f0ec\";\n}\n.am-icon-cloud-download:before {\n  content: \"\\f0ed\";\n}\n.am-icon-cloud-upload:before {\n  content: \"\\f0ee\";\n}\n.am-icon-user-md:before {\n  content: \"\\f0f0\";\n}\n.am-icon-stethoscope:before {\n  content: \"\\f0f1\";\n}\n.am-icon-suitcase:before {\n  content: \"\\f0f2\";\n}\n.am-icon-bell-o:before {\n  content: \"\\f0a2\";\n}\n.am-icon-coffee:before {\n  content: \"\\f0f4\";\n}\n.am-icon-cutlery:before {\n  content: \"\\f0f5\";\n}\n.am-icon-file-text-o:before {\n  content: \"\\f0f6\";\n}\n.am-icon-building-o:before {\n  content: \"\\f0f7\";\n}\n.am-icon-hospital-o:before {\n  content: \"\\f0f8\";\n}\n.am-icon-ambulance:before {\n  content: \"\\f0f9\";\n}\n.am-icon-medkit:before {\n  content: \"\\f0fa\";\n}\n.am-icon-fighter-jet:before {\n  content: \"\\f0fb\";\n}\n.am-icon-beer:before {\n  content: \"\\f0fc\";\n}\n.am-icon-h-square:before {\n  content: \"\\f0fd\";\n}\n.am-icon-plus-square:before {\n  content: \"\\f0fe\";\n}\n.am-icon-angle-double-left:before {\n  content: \"\\f100\";\n}\n.am-icon-angle-double-right:before {\n  content: \"\\f101\";\n}\n.am-icon-angle-double-up:before {\n  content: \"\\f102\";\n}\n.am-icon-angle-double-down:before {\n  content: \"\\f103\";\n}\n.am-icon-angle-left:before {\n  content: \"\\f104\";\n}\n.am-icon-angle-right:before {\n  content: \"\\f105\";\n}\n.am-icon-angle-up:before {\n  content: \"\\f106\";\n}\n.am-icon-angle-down:before {\n  content: \"\\f107\";\n}\n.am-icon-desktop:before {\n  content: \"\\f108\";\n}\n.am-icon-laptop:before {\n  content: \"\\f109\";\n}\n.am-icon-tablet:before {\n  content: \"\\f10a\";\n}\n.am-icon-mobile-phone:before,\n.am-icon-mobile:before {\n  content: \"\\f10b\";\n}\n.am-icon-circle-o:before {\n  content: \"\\f10c\";\n}\n.am-icon-quote-left:before {\n  content: \"\\f10d\";\n}\n.am-icon-quote-right:before {\n  content: \"\\f10e\";\n}\n.am-icon-spinner:before {\n  content: \"\\f110\";\n}\n.am-icon-circle:before {\n  content: \"\\f111\";\n}\n.am-icon-mail-reply:before,\n.am-icon-reply:before {\n  content: \"\\f112\";\n}\n.am-icon-github-alt:before {\n  content: \"\\f113\";\n}\n.am-icon-folder-o:before {\n  content: \"\\f114\";\n}\n.am-icon-folder-open-o:before {\n  content: \"\\f115\";\n}\n.am-icon-smile-o:before {\n  content: \"\\f118\";\n}\n.am-icon-frown-o:before {\n  content: \"\\f119\";\n}\n.am-icon-meh-o:before {\n  content: \"\\f11a\";\n}\n.am-icon-gamepad:before {\n  content: \"\\f11b\";\n}\n.am-icon-keyboard-o:before {\n  content: \"\\f11c\";\n}\n.am-icon-flag-o:before {\n  content: \"\\f11d\";\n}\n.am-icon-flag-checkered:before {\n  content: \"\\f11e\";\n}\n.am-icon-terminal:before {\n  content: \"\\f120\";\n}\n.am-icon-code:before {\n  content: \"\\f121\";\n}\n.am-icon-mail-reply-all:before,\n.am-icon-reply-all:before {\n  content: \"\\f122\";\n}\n.am-icon-star-half-empty:before,\n.am-icon-star-half-full:before,\n.am-icon-star-half-o:before {\n  content: \"\\f123\";\n}\n.am-icon-location-arrow:before {\n  content: \"\\f124\";\n}\n.am-icon-crop:before {\n  content: \"\\f125\";\n}\n.am-icon-code-fork:before {\n  content: \"\\f126\";\n}\n.am-icon-unlink:before,\n.am-icon-chain-broken:before {\n  content: \"\\f127\";\n}\n.am-icon-question:before {\n  content: \"\\f128\";\n}\n.am-icon-info:before {\n  content: \"\\f129\";\n}\n.am-icon-exclamation:before {\n  content: \"\\f12a\";\n}\n.am-icon-superscript:before {\n  content: \"\\f12b\";\n}\n.am-icon-subscript:before {\n  content: \"\\f12c\";\n}\n.am-icon-eraser:before {\n  content: \"\\f12d\";\n}\n.am-icon-puzzle-piece:before {\n  content: \"\\f12e\";\n}\n.am-icon-microphone:before {\n  content: \"\\f130\";\n}\n.am-icon-microphone-slash:before {\n  content: \"\\f131\";\n}\n.am-icon-shield:before {\n  content: \"\\f132\";\n}\n.am-icon-calendar-o:before {\n  content: \"\\f133\";\n}\n.am-icon-fire-extinguisher:before {\n  content: \"\\f134\";\n}\n.am-icon-rocket:before {\n  content: \"\\f135\";\n}\n.am-icon-maxcdn:before {\n  content: \"\\f136\";\n}\n.am-icon-chevron-circle-left:before {\n  content: \"\\f137\";\n}\n.am-icon-chevron-circle-right:before {\n  content: \"\\f138\";\n}\n.am-icon-chevron-circle-up:before {\n  content: \"\\f139\";\n}\n.am-icon-chevron-circle-down:before {\n  content: \"\\f13a\";\n}\n.am-icon-html5:before {\n  content: \"\\f13b\";\n}\n.am-icon-css3:before {\n  content: \"\\f13c\";\n}\n.am-icon-anchor:before {\n  content: \"\\f13d\";\n}\n.am-icon-unlock-alt:before {\n  content: \"\\f13e\";\n}\n.am-icon-bullseye:before {\n  content: \"\\f140\";\n}\n.am-icon-ellipsis-h:before {\n  content: \"\\f141\";\n}\n.am-icon-ellipsis-v:before {\n  content: \"\\f142\";\n}\n.am-icon-rss-square:before {\n  content: \"\\f143\";\n}\n.am-icon-play-circle:before {\n  content: \"\\f144\";\n}\n.am-icon-ticket:before {\n  content: \"\\f145\";\n}\n.am-icon-minus-square:before {\n  content: \"\\f146\";\n}\n.am-icon-minus-square-o:before {\n  content: \"\\f147\";\n}\n.am-icon-level-up:before {\n  content: \"\\f148\";\n}\n.am-icon-level-down:before {\n  content: \"\\f149\";\n}\n.am-icon-check-square:before {\n  content: \"\\f14a\";\n}\n.am-icon-pencil-square:before {\n  content: \"\\f14b\";\n}\n.am-icon-external-link-square:before {\n  content: \"\\f14c\";\n}\n.am-icon-share-square:before {\n  content: \"\\f14d\";\n}\n.am-icon-compass:before {\n  content: \"\\f14e\";\n}\n.am-icon-toggle-down:before,\n.am-icon-caret-square-o-down:before {\n  content: \"\\f150\";\n}\n.am-icon-toggle-up:before,\n.am-icon-caret-square-o-up:before {\n  content: \"\\f151\";\n}\n.am-icon-toggle-right:before,\n.am-icon-caret-square-o-right:before {\n  content: \"\\f152\";\n}\n.am-icon-euro:before,\n.am-icon-eur:before {\n  content: \"\\f153\";\n}\n.am-icon-gbp:before {\n  content: \"\\f154\";\n}\n.am-icon-dollar:before,\n.am-icon-usd:before {\n  content: \"\\f155\";\n}\n.am-icon-rupee:before,\n.am-icon-inr:before {\n  content: \"\\f156\";\n}\n.am-icon-cny:before,\n.am-icon-rmb:before,\n.am-icon-yen:before,\n.am-icon-jpy:before {\n  content: \"\\f157\";\n}\n.am-icon-ruble:before,\n.am-icon-rouble:before,\n.am-icon-rub:before {\n  content: \"\\f158\";\n}\n.am-icon-won:before,\n.am-icon-krw:before {\n  content: \"\\f159\";\n}\n.am-icon-bitcoin:before,\n.am-icon-btc:before {\n  content: \"\\f15a\";\n}\n.am-icon-file:before {\n  content: \"\\f15b\";\n}\n.am-icon-file-text:before {\n  content: \"\\f15c\";\n}\n.am-icon-sort-alpha-asc:before {\n  content: \"\\f15d\";\n}\n.am-icon-sort-alpha-desc:before {\n  content: \"\\f15e\";\n}\n.am-icon-sort-amount-asc:before {\n  content: \"\\f160\";\n}\n.am-icon-sort-amount-desc:before {\n  content: \"\\f161\";\n}\n.am-icon-sort-numeric-asc:before {\n  content: \"\\f162\";\n}\n.am-icon-sort-numeric-desc:before {\n  content: \"\\f163\";\n}\n.am-icon-thumbs-up:before {\n  content: \"\\f164\";\n}\n.am-icon-thumbs-down:before {\n  content: \"\\f165\";\n}\n.am-icon-youtube-square:before {\n  content: \"\\f166\";\n}\n.am-icon-youtube:before {\n  content: \"\\f167\";\n}\n.am-icon-xing:before {\n  content: \"\\f168\";\n}\n.am-icon-xing-square:before {\n  content: \"\\f169\";\n}\n.am-icon-youtube-play:before {\n  content: \"\\f16a\";\n}\n.am-icon-dropbox:before {\n  content: \"\\f16b\";\n}\n.am-icon-stack-overflow:before {\n  content: \"\\f16c\";\n}\n.am-icon-instagram:before {\n  content: \"\\f16d\";\n}\n.am-icon-flickr:before {\n  content: \"\\f16e\";\n}\n.am-icon-adn:before {\n  content: \"\\f170\";\n}\n.am-icon-bitbucket:before {\n  content: \"\\f171\";\n}\n.am-icon-bitbucket-square:before {\n  content: \"\\f172\";\n}\n.am-icon-tumblr:before {\n  content: \"\\f173\";\n}\n.am-icon-tumblr-square:before {\n  content: \"\\f174\";\n}\n.am-icon-long-arrow-down:before {\n  content: \"\\f175\";\n}\n.am-icon-long-arrow-up:before {\n  content: \"\\f176\";\n}\n.am-icon-long-arrow-left:before {\n  content: \"\\f177\";\n}\n.am-icon-long-arrow-right:before {\n  content: \"\\f178\";\n}\n.am-icon-apple:before {\n  content: \"\\f179\";\n}\n.am-icon-windows:before {\n  content: \"\\f17a\";\n}\n.am-icon-android:before {\n  content: \"\\f17b\";\n}\n.am-icon-linux:before {\n  content: \"\\f17c\";\n}\n.am-icon-dribbble:before {\n  content: \"\\f17d\";\n}\n.am-icon-skype:before {\n  content: \"\\f17e\";\n}\n.am-icon-foursquare:before {\n  content: \"\\f180\";\n}\n.am-icon-trello:before {\n  content: \"\\f181\";\n}\n.am-icon-female:before {\n  content: \"\\f182\";\n}\n.am-icon-male:before {\n  content: \"\\f183\";\n}\n.am-icon-gittip:before,\n.am-icon-gratipay:before {\n  content: \"\\f184\";\n}\n.am-icon-sun-o:before {\n  content: \"\\f185\";\n}\n.am-icon-moon-o:before {\n  content: \"\\f186\";\n}\n.am-icon-archive:before {\n  content: \"\\f187\";\n}\n.am-icon-bug:before {\n  content: \"\\f188\";\n}\n.am-icon-vk:before {\n  content: \"\\f189\";\n}\n.am-icon-weibo:before {\n  content: \"\\f18a\";\n}\n.am-icon-renren:before {\n  content: \"\\f18b\";\n}\n.am-icon-pagelines:before {\n  content: \"\\f18c\";\n}\n.am-icon-stack-exchange:before {\n  content: \"\\f18d\";\n}\n.am-icon-arrow-circle-o-right:before {\n  content: \"\\f18e\";\n}\n.am-icon-arrow-circle-o-left:before {\n  content: \"\\f190\";\n}\n.am-icon-toggle-left:before,\n.am-icon-caret-square-o-left:before {\n  content: \"\\f191\";\n}\n.am-icon-dot-circle-o:before {\n  content: \"\\f192\";\n}\n.am-icon-wheelchair:before {\n  content: \"\\f193\";\n}\n.am-icon-vimeo-square:before {\n  content: \"\\f194\";\n}\n.am-icon-turkish-lira:before,\n.am-icon-try:before {\n  content: \"\\f195\";\n}\n.am-icon-plus-square-o:before {\n  content: \"\\f196\";\n}\n.am-icon-space-shuttle:before {\n  content: \"\\f197\";\n}\n.am-icon-slack:before {\n  content: \"\\f198\";\n}\n.am-icon-envelope-square:before {\n  content: \"\\f199\";\n}\n.am-icon-wordpress:before {\n  content: \"\\f19a\";\n}\n.am-icon-openid:before {\n  content: \"\\f19b\";\n}\n.am-icon-institution:before,\n.am-icon-bank:before,\n.am-icon-university:before {\n  content: \"\\f19c\";\n}\n.am-icon-mortar-board:before,\n.am-icon-graduation-cap:before {\n  content: \"\\f19d\";\n}\n.am-icon-yahoo:before {\n  content: \"\\f19e\";\n}\n.am-icon-google:before {\n  content: \"\\f1a0\";\n}\n.am-icon-reddit:before {\n  content: \"\\f1a1\";\n}\n.am-icon-reddit-square:before {\n  content: \"\\f1a2\";\n}\n.am-icon-stumbleupon-circle:before {\n  content: \"\\f1a3\";\n}\n.am-icon-stumbleupon:before {\n  content: \"\\f1a4\";\n}\n.am-icon-delicious:before {\n  content: \"\\f1a5\";\n}\n.am-icon-digg:before {\n  content: \"\\f1a6\";\n}\n.am-icon-pied-piper:before {\n  content: \"\\f1a7\";\n}\n.am-icon-pied-piper-alt:before {\n  content: \"\\f1a8\";\n}\n.am-icon-drupal:before {\n  content: \"\\f1a9\";\n}\n.am-icon-joomla:before {\n  content: \"\\f1aa\";\n}\n.am-icon-language:before {\n  content: \"\\f1ab\";\n}\n.am-icon-fax:before {\n  content: \"\\f1ac\";\n}\n.am-icon-building:before {\n  content: \"\\f1ad\";\n}\n.am-icon-child:before {\n  content: \"\\f1ae\";\n}\n.am-icon-paw:before {\n  content: \"\\f1b0\";\n}\n.am-icon-spoon:before {\n  content: \"\\f1b1\";\n}\n.am-icon-cube:before {\n  content: \"\\f1b2\";\n}\n.am-icon-cubes:before {\n  content: \"\\f1b3\";\n}\n.am-icon-behance:before {\n  content: \"\\f1b4\";\n}\n.am-icon-behance-square:before {\n  content: \"\\f1b5\";\n}\n.am-icon-steam:before {\n  content: \"\\f1b6\";\n}\n.am-icon-steam-square:before {\n  content: \"\\f1b7\";\n}\n.am-icon-recycle:before {\n  content: \"\\f1b8\";\n}\n.am-icon-automobile:before,\n.am-icon-car:before {\n  content: \"\\f1b9\";\n}\n.am-icon-cab:before,\n.am-icon-taxi:before {\n  content: \"\\f1ba\";\n}\n.am-icon-tree:before {\n  content: \"\\f1bb\";\n}\n.am-icon-spotify:before {\n  content: \"\\f1bc\";\n}\n.am-icon-deviantart:before {\n  content: \"\\f1bd\";\n}\n.am-icon-soundcloud:before {\n  content: \"\\f1be\";\n}\n.am-icon-database:before {\n  content: \"\\f1c0\";\n}\n.am-icon-file-pdf-o:before {\n  content: \"\\f1c1\";\n}\n.am-icon-file-word-o:before {\n  content: \"\\f1c2\";\n}\n.am-icon-file-excel-o:before {\n  content: \"\\f1c3\";\n}\n.am-icon-file-powerpoint-o:before {\n  content: \"\\f1c4\";\n}\n.am-icon-file-photo-o:before,\n.am-icon-file-picture-o:before,\n.am-icon-file-image-o:before {\n  content: \"\\f1c5\";\n}\n.am-icon-file-zip-o:before,\n.am-icon-file-archive-o:before {\n  content: \"\\f1c6\";\n}\n.am-icon-file-sound-o:before,\n.am-icon-file-audio-o:before {\n  content: \"\\f1c7\";\n}\n.am-icon-file-movie-o:before,\n.am-icon-file-video-o:before {\n  content: \"\\f1c8\";\n}\n.am-icon-file-code-o:before {\n  content: \"\\f1c9\";\n}\n.am-icon-vine:before {\n  content: \"\\f1ca\";\n}\n.am-icon-codepen:before {\n  content: \"\\f1cb\";\n}\n.am-icon-jsfiddle:before {\n  content: \"\\f1cc\";\n}\n.am-icon-life-bouy:before,\n.am-icon-life-buoy:before,\n.am-icon-life-saver:before,\n.am-icon-support:before,\n.am-icon-life-ring:before {\n  content: \"\\f1cd\";\n}\n.am-icon-circle-o-notch:before {\n  content: \"\\f1ce\";\n}\n.am-icon-ra:before,\n.am-icon-rebel:before {\n  content: \"\\f1d0\";\n}\n.am-icon-ge:before,\n.am-icon-empire:before {\n  content: \"\\f1d1\";\n}\n.am-icon-git-square:before {\n  content: \"\\f1d2\";\n}\n.am-icon-git:before {\n  content: \"\\f1d3\";\n}\n.am-icon-y-combinator-square:before,\n.am-icon-yc-square:before,\n.am-icon-hacker-news:before {\n  content: \"\\f1d4\";\n}\n.am-icon-tencent-weibo:before {\n  content: \"\\f1d5\";\n}\n.am-icon-qq:before {\n  content: \"\\f1d6\";\n}\n.am-icon-wechat:before,\n.am-icon-weixin:before {\n  content: \"\\f1d7\";\n}\n.am-icon-send:before,\n.am-icon-paper-plane:before {\n  content: \"\\f1d8\";\n}\n.am-icon-send-o:before,\n.am-icon-paper-plane-o:before {\n  content: \"\\f1d9\";\n}\n.am-icon-history:before {\n  content: \"\\f1da\";\n}\n.am-icon-circle-thin:before {\n  content: \"\\f1db\";\n}\n.am-icon-header:before {\n  content: \"\\f1dc\";\n}\n.am-icon-paragraph:before {\n  content: \"\\f1dd\";\n}\n.am-icon-sliders:before {\n  content: \"\\f1de\";\n}\n.am-icon-share-alt:before {\n  content: \"\\f1e0\";\n}\n.am-icon-share-alt-square:before {\n  content: \"\\f1e1\";\n}\n.am-icon-bomb:before {\n  content: \"\\f1e2\";\n}\n.am-icon-soccer-ball-o:before,\n.am-icon-futbol-o:before {\n  content: \"\\f1e3\";\n}\n.am-icon-tty:before {\n  content: \"\\f1e4\";\n}\n.am-icon-binoculars:before {\n  content: \"\\f1e5\";\n}\n.am-icon-plug:before {\n  content: \"\\f1e6\";\n}\n.am-icon-slideshare:before {\n  content: \"\\f1e7\";\n}\n.am-icon-twitch:before {\n  content: \"\\f1e8\";\n}\n.am-icon-yelp:before {\n  content: \"\\f1e9\";\n}\n.am-icon-newspaper-o:before {\n  content: \"\\f1ea\";\n}\n.am-icon-wifi:before {\n  content: \"\\f1eb\";\n}\n.am-icon-calculator:before {\n  content: \"\\f1ec\";\n}\n.am-icon-paypal:before {\n  content: \"\\f1ed\";\n}\n.am-icon-google-wallet:before {\n  content: \"\\f1ee\";\n}\n.am-icon-cc-visa:before {\n  content: \"\\f1f0\";\n}\n.am-icon-cc-mastercard:before {\n  content: \"\\f1f1\";\n}\n.am-icon-cc-discover:before {\n  content: \"\\f1f2\";\n}\n.am-icon-cc-amex:before {\n  content: \"\\f1f3\";\n}\n.am-icon-cc-paypal:before {\n  content: \"\\f1f4\";\n}\n.am-icon-cc-stripe:before {\n  content: \"\\f1f5\";\n}\n.am-icon-bell-slash:before {\n  content: \"\\f1f6\";\n}\n.am-icon-bell-slash-o:before {\n  content: \"\\f1f7\";\n}\n.am-icon-trash:before {\n  content: \"\\f1f8\";\n}\n.am-icon-copyright:before {\n  content: \"\\f1f9\";\n}\n.am-icon-at:before {\n  content: \"\\f1fa\";\n}\n.am-icon-eyedropper:before {\n  content: \"\\f1fb\";\n}\n.am-icon-paint-brush:before {\n  content: \"\\f1fc\";\n}\n.am-icon-birthday-cake:before {\n  content: \"\\f1fd\";\n}\n.am-icon-area-chart:before {\n  content: \"\\f1fe\";\n}\n.am-icon-pie-chart:before {\n  content: \"\\f200\";\n}\n.am-icon-line-chart:before {\n  content: \"\\f201\";\n}\n.am-icon-lastfm:before {\n  content: \"\\f202\";\n}\n.am-icon-lastfm-square:before {\n  content: \"\\f203\";\n}\n.am-icon-toggle-off:before {\n  content: \"\\f204\";\n}\n.am-icon-toggle-on:before {\n  content: \"\\f205\";\n}\n.am-icon-bicycle:before {\n  content: \"\\f206\";\n}\n.am-icon-bus:before {\n  content: \"\\f207\";\n}\n.am-icon-ioxhost:before {\n  content: \"\\f208\";\n}\n.am-icon-angellist:before {\n  content: \"\\f209\";\n}\n.am-icon-cc:before {\n  content: \"\\f20a\";\n}\n.am-icon-shekel:before,\n.am-icon-sheqel:before,\n.am-icon-ils:before {\n  content: \"\\f20b\";\n}\n.am-icon-meanpath:before {\n  content: \"\\f20c\";\n}\n.am-icon-buysellads:before {\n  content: \"\\f20d\";\n}\n.am-icon-connectdevelop:before {\n  content: \"\\f20e\";\n}\n.am-icon-dashcube:before {\n  content: \"\\f210\";\n}\n.am-icon-forumbee:before {\n  content: \"\\f211\";\n}\n.am-icon-leanpub:before {\n  content: \"\\f212\";\n}\n.am-icon-sellsy:before {\n  content: \"\\f213\";\n}\n.am-icon-shirtsinbulk:before {\n  content: \"\\f214\";\n}\n.am-icon-simplybuilt:before {\n  content: \"\\f215\";\n}\n.am-icon-skyatlas:before {\n  content: \"\\f216\";\n}\n.am-icon-cart-plus:before {\n  content: \"\\f217\";\n}\n.am-icon-cart-arrow-down:before {\n  content: \"\\f218\";\n}\n.am-icon-diamond:before {\n  content: \"\\f219\";\n}\n.am-icon-ship:before {\n  content: \"\\f21a\";\n}\n.am-icon-user-secret:before {\n  content: \"\\f21b\";\n}\n.am-icon-motorcycle:before {\n  content: \"\\f21c\";\n}\n.am-icon-street-view:before {\n  content: \"\\f21d\";\n}\n.am-icon-heartbeat:before {\n  content: \"\\f21e\";\n}\n.am-icon-venus:before {\n  content: \"\\f221\";\n}\n.am-icon-mars:before {\n  content: \"\\f222\";\n}\n.am-icon-mercury:before {\n  content: \"\\f223\";\n}\n.am-icon-intersex:before,\n.am-icon-transgender:before {\n  content: \"\\f224\";\n}\n.am-icon-transgender-alt:before {\n  content: \"\\f225\";\n}\n.am-icon-venus-double:before {\n  content: \"\\f226\";\n}\n.am-icon-mars-double:before {\n  content: \"\\f227\";\n}\n.am-icon-venus-mars:before {\n  content: \"\\f228\";\n}\n.am-icon-mars-stroke:before {\n  content: \"\\f229\";\n}\n.am-icon-mars-stroke-v:before {\n  content: \"\\f22a\";\n}\n.am-icon-mars-stroke-h:before {\n  content: \"\\f22b\";\n}\n.am-icon-neuter:before {\n  content: \"\\f22c\";\n}\n.am-icon-genderless:before {\n  content: \"\\f22d\";\n}\n.am-icon-facebook-official:before {\n  content: \"\\f230\";\n}\n.am-icon-pinterest-p:before {\n  content: \"\\f231\";\n}\n.am-icon-whatsapp:before {\n  content: \"\\f232\";\n}\n.am-icon-server:before {\n  content: \"\\f233\";\n}\n.am-icon-user-plus:before {\n  content: \"\\f234\";\n}\n.am-icon-user-times:before {\n  content: \"\\f235\";\n}\n.am-icon-hotel:before,\n.am-icon-bed:before {\n  content: \"\\f236\";\n}\n.am-icon-viacoin:before {\n  content: \"\\f237\";\n}\n.am-icon-train:before {\n  content: \"\\f238\";\n}\n.am-icon-subway:before {\n  content: \"\\f239\";\n}\n.am-icon-medium:before {\n  content: \"\\f23a\";\n}\n.am-icon-yc:before,\n.am-icon-y-combinator:before {\n  content: \"\\f23b\";\n}\n.am-icon-optin-monster:before {\n  content: \"\\f23c\";\n}\n.am-icon-opencart:before {\n  content: \"\\f23d\";\n}\n.am-icon-expeditedssl:before {\n  content: \"\\f23e\";\n}\n.am-icon-battery-4:before,\n.am-icon-battery-full:before {\n  content: \"\\f240\";\n}\n.am-icon-battery-3:before,\n.am-icon-battery-three-quarters:before {\n  content: \"\\f241\";\n}\n.am-icon-battery-2:before,\n.am-icon-battery-half:before {\n  content: \"\\f242\";\n}\n.am-icon-battery-1:before,\n.am-icon-battery-quarter:before {\n  content: \"\\f243\";\n}\n.am-icon-battery-0:before,\n.am-icon-battery-empty:before {\n  content: \"\\f244\";\n}\n.am-icon-mouse-pointer:before {\n  content: \"\\f245\";\n}\n.am-icon-i-cursor:before {\n  content: \"\\f246\";\n}\n.am-icon-object-group:before {\n  content: \"\\f247\";\n}\n.am-icon-object-ungroup:before {\n  content: \"\\f248\";\n}\n.am-icon-sticky-note:before {\n  content: \"\\f249\";\n}\n.am-icon-sticky-note-o:before {\n  content: \"\\f24a\";\n}\n.am-icon-cc-jcb:before {\n  content: \"\\f24b\";\n}\n.am-icon-cc-diners-club:before {\n  content: \"\\f24c\";\n}\n.am-icon-clone:before {\n  content: \"\\f24d\";\n}\n.am-icon-balance-scale:before {\n  content: \"\\f24e\";\n}\n.am-icon-hourglass-o:before {\n  content: \"\\f250\";\n}\n.am-icon-hourglass-1:before,\n.am-icon-hourglass-start:before {\n  content: \"\\f251\";\n}\n.am-icon-hourglass-2:before,\n.am-icon-hourglass-half:before {\n  content: \"\\f252\";\n}\n.am-icon-hourglass-3:before,\n.am-icon-hourglass-end:before {\n  content: \"\\f253\";\n}\n.am-icon-hourglass:before {\n  content: \"\\f254\";\n}\n.am-icon-hand-grab-o:before,\n.am-icon-hand-rock-o:before {\n  content: \"\\f255\";\n}\n.am-icon-hand-stop-o:before,\n.am-icon-hand-paper-o:before {\n  content: \"\\f256\";\n}\n.am-icon-hand-scissors-o:before {\n  content: \"\\f257\";\n}\n.am-icon-hand-lizard-o:before {\n  content: \"\\f258\";\n}\n.am-icon-hand-spock-o:before {\n  content: \"\\f259\";\n}\n.am-icon-hand-pointer-o:before {\n  content: \"\\f25a\";\n}\n.am-icon-hand-peace-o:before {\n  content: \"\\f25b\";\n}\n.am-icon-trademark:before {\n  content: \"\\f25c\";\n}\n.am-icon-registered:before {\n  content: \"\\f25d\";\n}\n.am-icon-creative-commons:before {\n  content: \"\\f25e\";\n}\n.am-icon-gg:before {\n  content: \"\\f260\";\n}\n.am-icon-gg-circle:before {\n  content: \"\\f261\";\n}\n.am-icon-tripadvisor:before {\n  content: \"\\f262\";\n}\n.am-icon-odnoklassniki:before {\n  content: \"\\f263\";\n}\n.am-icon-odnoklassniki-square:before {\n  content: \"\\f264\";\n}\n.am-icon-get-pocket:before {\n  content: \"\\f265\";\n}\n.am-icon-wikipedia-w:before {\n  content: \"\\f266\";\n}\n.am-icon-safari:before {\n  content: \"\\f267\";\n}\n.am-icon-chrome:before {\n  content: \"\\f268\";\n}\n.am-icon-firefox:before {\n  content: \"\\f269\";\n}\n.am-icon-opera:before {\n  content: \"\\f26a\";\n}\n.am-icon-internet-explorer:before {\n  content: \"\\f26b\";\n}\n.am-icon-tv:before,\n.am-icon-television:before {\n  content: \"\\f26c\";\n}\n.am-icon-contao:before {\n  content: \"\\f26d\";\n}\n.am-icon-500px:before {\n  content: \"\\f26e\";\n}\n.am-icon-amazon:before {\n  content: \"\\f270\";\n}\n.am-icon-calendar-plus-o:before {\n  content: \"\\f271\";\n}\n.am-icon-calendar-minus-o:before {\n  content: \"\\f272\";\n}\n.am-icon-calendar-times-o:before {\n  content: \"\\f273\";\n}\n.am-icon-calendar-check-o:before {\n  content: \"\\f274\";\n}\n.am-icon-industry:before {\n  content: \"\\f275\";\n}\n.am-icon-map-pin:before {\n  content: \"\\f276\";\n}\n.am-icon-map-signs:before {\n  content: \"\\f277\";\n}\n.am-icon-map-o:before {\n  content: \"\\f278\";\n}\n.am-icon-map:before {\n  content: \"\\f279\";\n}\n.am-icon-commenting:before {\n  content: \"\\f27a\";\n}\n.am-icon-commenting-o:before {\n  content: \"\\f27b\";\n}\n.am-icon-houzz:before {\n  content: \"\\f27c\";\n}\n.am-icon-vimeo:before {\n  content: \"\\f27d\";\n}\n.am-icon-black-tie:before {\n  content: \"\\f27e\";\n}\n.am-icon-fonticons:before {\n  content: \"\\f280\";\n}\n.am-icon-reddit-alien:before {\n  content: \"\\f281\";\n}\n.am-icon-edge:before {\n  content: \"\\f282\";\n}\n.am-icon-credit-card-alt:before {\n  content: \"\\f283\";\n}\n.am-icon-codiepie:before {\n  content: \"\\f284\";\n}\n.am-icon-modx:before {\n  content: \"\\f285\";\n}\n.am-icon-fort-awesome:before {\n  content: \"\\f286\";\n}\n.am-icon-usb:before {\n  content: \"\\f287\";\n}\n.am-icon-product-hunt:before {\n  content: \"\\f288\";\n}\n.am-icon-mixcloud:before {\n  content: \"\\f289\";\n}\n.am-icon-scribd:before {\n  content: \"\\f28a\";\n}\n.am-icon-pause-circle:before {\n  content: \"\\f28b\";\n}\n.am-icon-pause-circle-o:before {\n  content: \"\\f28c\";\n}\n.am-icon-stop-circle:before {\n  content: \"\\f28d\";\n}\n.am-icon-stop-circle-o:before {\n  content: \"\\f28e\";\n}\n.am-icon-shopping-bag:before {\n  content: \"\\f290\";\n}\n.am-icon-shopping-basket:before {\n  content: \"\\f291\";\n}\n.am-icon-hashtag:before {\n  content: \"\\f292\";\n}\n.am-icon-bluetooth:before {\n  content: \"\\f293\";\n}\n.am-icon-bluetooth-b:before {\n  content: \"\\f294\";\n}\n.am-icon-percent:before {\n  content: \"\\f295\";\n}\n/* Modifier: `am-icon-spin`\n============================================================================= */\n@-webkit-keyframes icon-spin {\n  0% {\n    -webkit-transform: rotate(0deg);\n            transform: rotate(0deg);\n  }\n  100% {\n    -webkit-transform: rotate(359deg);\n            transform: rotate(359deg);\n  }\n}\n@keyframes icon-spin {\n  0% {\n    -webkit-transform: rotate(0deg);\n            transform: rotate(0deg);\n  }\n  100% {\n    -webkit-transform: rotate(359deg);\n            transform: rotate(359deg);\n  }\n}\n.am-icon-spin {\n  -webkit-animation: icon-spin 2s infinite linear;\n          animation: icon-spin 2s infinite linear;\n}\n.am-icon-pulse {\n  -webkit-animation: icon-spin 1s infinite steps(8);\n          animation: icon-spin 1s infinite steps(8);\n}\n.am-icon-ul {\n  padding-left: 0;\n  margin-left: 2.14285714em;\n  list-style-type: none;\n}\n.am-icon-ul > li {\n  position: relative;\n}\n.am-icon-li {\n  position: absolute;\n  left: -2.14285714em;\n  width: 2.14285714em;\n  top: 0.14285714em;\n  text-align: center;\n}\n/* ==========================================================================\n   Component: Input group\n ============================================================================ */\n.am-input-group {\n  position: relative;\n  display: table;\n  border-collapse: separate;\n}\n.am-input-group .am-form-field {\n  position: relative;\n  z-index: 2;\n  float: left;\n  width: 100%;\n  margin-bottom: 0;\n}\n.am-input-group-label,\n.am-input-group-btn,\n.am-input-group .am-form-field {\n  display: table-cell;\n}\n.am-input-group-label:not(:first-child):not(:last-child),\n.am-input-group-btn:not(:first-child):not(:last-child),\n.am-input-group .am-form-field:not(:first-child):not(:last-child) {\n  border-radius: 0;\n}\n.am-input-group-label,\n.am-input-group-btn {\n  width: 1%;\n  white-space: nowrap;\n  vertical-align: middle;\n}\n.am-input-group-label {\n  height: 38px;\n  padding: 0 1em;\n  font-size: 1.6rem;\n  font-weight: normal;\n  line-height: 36px;\n  color: #555555;\n  text-align: center;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n  border-radius: 2px;\n}\n.am-input-group-label input[type=\"radio\"],\n.am-input-group-label input[type=\"checkbox\"] {\n  margin-top: 0;\n}\n.am-input-group .am-form-field:first-child,\n.am-input-group-label:first-child,\n.am-input-group-btn:first-child > .am-btn,\n.am-input-group-btn:first-child > .am-btn-group > .am-btn,\n.am-input-group-btn:first-child > .am-dropdown-toggle,\n.am-input-group-btn:last-child > .am-btn:not(:last-child):not(.dropdown-toggle),\n.am-input-group-btn:last-child > .am-btn-group:not(:last-child) > .am-btn {\n  border-bottom-right-radius: 0;\n  border-top-right-radius: 0;\n}\n.am-input-group-label:first-child {\n  border-right: 0;\n}\n.am-input-group .am-form-field:last-child,\n.am-input-group-label:last-child,\n.am-input-group-btn:last-child > .am-btn,\n.am-input-group-btn:last-child > .am-btn-group > .am-btn,\n.am-input-group-btn:last-child > .am-dropdown-toggle,\n.am-input-group-btn:first-child > .am-btn:not(:first-child),\n.am-input-group-btn:first-child > .am-btn-group:not(:first-child) > .am-btn {\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n}\n.am-input-group-label:last-child {\n  border-left: 0;\n}\n.am-input-group-btn {\n  position: relative;\n  font-size: 0;\n  white-space: nowrap;\n}\n.am-input-group-btn > .am-btn {\n  position: relative;\n  border-color: #ccc;\n}\n.am-input-group-btn > .am-btn + .am-btn {\n  margin-left: -1px;\n}\n.am-input-group-btn > .am-btn:hover,\n.am-input-group-btn > .am-btn:focus,\n.am-input-group-btn > .am-btn:active {\n  z-index: 2;\n}\n.am-input-group-btn:first-child > .am-btn,\n.am-input-group-btn:first-child > .am-btn-group {\n  margin-right: -2px;\n}\n.am-input-group-btn:last-child > .am-btn,\n.am-input-group-btn:last-child > .am-btn-group {\n  margin-left: -1px;\n}\n.am-input-group .am-form-field,\n.am-input-group-btn > .am-btn {\n  height: 38px;\n  padding-bottom: auto;\n}\n.am-input-group-lg > .am-form-field,\n.am-input-group-lg > .am-input-group-label,\n.am-input-group-lg > .am-input-group-btn > .am-btn {\n  height: 42px;\n  font-size: 1.8rem !important;\n}\n.am-input-group-lg > .am-input-group-label {\n  line-height: 40px;\n}\n.am-input-group-sm > .am-form-field,\n.am-input-group-sm > .am-input-group-label,\n.am-input-group-sm > .am-input-group-btn > .am-btn {\n  height: 33px;\n  font-size: 1.4rem !important;\n}\n.am-input-group-sm > .am-input-group-label {\n  line-height: 31px;\n}\n.am-input-group-primary .am-input-group-label {\n  background: #0e90d2;\n  color: #fff;\n}\n.am-input-group-primary .am-input-group-label,\n.am-input-group-primary .am-input-group-btn > .am-btn,\n.am-input-group-primary.am-input-group .am-form-field {\n  border-color: #0e90d2;\n}\n.am-input-group-secondary .am-input-group-label {\n  background: #3bb4f2;\n  color: #fff;\n}\n.am-input-group-secondary .am-input-group-label,\n.am-input-group-secondary .am-input-group-btn > .am-btn,\n.am-input-group-secondary.am-input-group .am-form-field {\n  border-color: #3bb4f2;\n}\n.am-input-group-success .am-input-group-label {\n  background: #5eb95e;\n  color: #fff;\n}\n.am-input-group-success .am-input-group-label,\n.am-input-group-success .am-input-group-btn > .am-btn,\n.am-input-group-success.am-input-group .am-form-field {\n  border-color: #5eb95e;\n}\n.am-input-group-warning .am-input-group-label {\n  background: #F37B1D;\n  color: #fff;\n}\n.am-input-group-warning .am-input-group-label,\n.am-input-group-warning .am-input-group-btn > .am-btn,\n.am-input-group-warning.am-input-group .am-form-field {\n  border-color: #F37B1D;\n}\n.am-input-group-danger .am-input-group-label {\n  background: #dd514c;\n  color: #fff;\n}\n.am-input-group-danger .am-input-group-label,\n.am-input-group-danger .am-input-group-btn > .am-btn,\n.am-input-group-danger.am-input-group .am-form-field {\n  border-color: #dd514c;\n}\n/* ==========================================================================\n   Component: List\n ============================================================================ */\n.am-list {\n  margin-bottom: 1.6rem;\n  padding-left: 0;\n}\n.am-list > li {\n  position: relative;\n  display: block;\n  margin-bottom: -1px;\n  background-color: #fff;\n  border: 1px solid #dedede;\n  border-width: 1px 0;\n}\n.am-list > li > a {\n  display: block;\n  padding: 1rem 0;\n}\n.am-list > li > a.am-active,\n.am-list > li > a.am-active:hover,\n.am-list > li > a.am-active:focus {\n  z-index: 2;\n  color: #fff;\n  background-color: #0e90d2;\n  border-color: #0e90d2;\n}\n.am-list > li > a.am-active .am-list-item-heading,\n.am-list > li > a.am-active:hover .am-list-item-heading,\n.am-list > li > a.am-active:focus .am-list-item-heading {\n  color: inherit;\n}\n.am-list > li > a.am-active .am-list-item-text,\n.am-list > li > a.am-active:hover .am-list-item-text,\n.am-list > li > a.am-active:focus .am-list-item-text {\n  color: #b2e2fa;\n}\n.am-list > li > .am-badge {\n  float: right;\n}\n.am-list > li > .am-badge + .am-badge {\n  margin-right: 5px;\n}\n/* Pure text list */\n.am-list-static > li {\n  padding: .8rem .2rem;\n}\n.am-list-static.am-list-border > li {\n  padding: 1rem;\n}\n/* with border */\n.am-list-border > li,\n.am-list-bordered > li {\n  border-width: 1px;\n}\n.am-list-border > li:first-child,\n.am-list-bordered > li:first-child,\n.am-list-border > li:first-child > a,\n.am-list-bordered > li:first-child > a {\n  border-top-right-radius: 2px;\n  border-top-left-radius: 2px;\n}\n.am-list-border > li:last-child,\n.am-list-bordered > li:last-child,\n.am-list-border > li:last-child > a,\n.am-list-bordered > li:last-child > a {\n  margin-bottom: 0;\n  border-bottom-right-radius: 2px;\n  border-bottom-left-radius: 2px;\n}\n.am-list-border > li > a,\n.am-list-bordered > li > a {\n  padding: 1rem;\n}\n.am-list-border > li > a:hover,\n.am-list-bordered > li > a:hover,\n.am-list-border > li > a:focus,\n.am-list-bordered > li > a:focus {\n  background-color: #f5f5f5;\n}\n/* Striped */\n.am-list-striped > li:nth-of-type(even) {\n  background: #f5f5f5;\n}\n.am-list-item-hd {\n  margin-top: 0;\n}\n.am-list-item-text {\n  line-height: 1.4;\n  font-size: 1.3rem;\n  color: #999999;\n  margin: 0;\n}\n/* ==========================================================================\n   Component: Panel\n ============================================================================ */\n.am-panel {\n  margin-bottom: 20px;\n  background-color: #fff;\n  border: 1px solid transparent;\n  border-radius: 2px;\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/* Panel header */\n.am-panel-hd {\n  padding: 0.6rem 1.25rem;\n  border-bottom: 1px solid transparent;\n  border-top-right-radius: 2px;\n  border-top-left-radius: 2px;\n}\n/* Panel content */\n.am-panel-bd {\n  padding: 1.25rem;\n}\n.am-panel-title {\n  margin: 0;\n  font-size: 100%;\n  color: inherit;\n}\n.am-panel-title > a {\n  color: inherit;\n}\n/* Panel footer */\n.am-panel-footer {\n  padding: 0.6rem 1.25rem;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  border-bottom-right-radius: 2px;\n  border-bottom-left-radius: 2px;\n}\n.am-panel-default {\n  border-color: #ddd;\n}\n.am-panel-default > .am-panel-hd {\n  color: #444;\n  background-color: #f5f5f5;\n  border-color: #ddd;\n}\n.am-panel-default > .am-panel-hd + .am-panel-collapse > .am-panel-bd {\n  border-top-color: #ddd;\n}\n.am-panel-default > .am-panel-footer + .am-panel-collapse > .am-panel-bd {\n  border-bottom-color: #ddd;\n}\n.am-panel-primary {\n  border-color: #10a0ea;\n}\n.am-panel-primary > .am-panel-hd {\n  color: #fff;\n  background-color: #0e90d2;\n  border-color: #10a0ea;\n}\n.am-panel-primary > .am-panel-hd + .am-panel-collapse > .am-panel-bd {\n  border-top-color: #10a0ea;\n}\n.am-panel-primary > .am-panel-footer + .am-panel-collapse > .am-panel-bd {\n  border-bottom-color: #10a0ea;\n}\n.am-panel-secondary {\n  border-color: #caebfb;\n}\n.am-panel-secondary > .am-panel-hd {\n  color: #14a6ef;\n  background-color: rgba(59, 180, 242, 0.15);\n  border-color: #caebfb;\n}\n.am-panel-secondary > .am-panel-hd + .am-panel-collapse > .am-panel-bd {\n  border-top-color: #caebfb;\n}\n.am-panel-secondary > .am-panel-footer + .am-panel-collapse > .am-panel-bd {\n  border-bottom-color: #caebfb;\n}\n.am-panel-success {\n  border-color: #c9e7c9;\n}\n.am-panel-success > .am-panel-hd {\n  color: #5eb95e;\n  background-color: rgba(94, 185, 94, 0.15);\n  border-color: #c9e7c9;\n}\n.am-panel-success > .am-panel-hd + .am-panel-collapse > .am-panel-bd {\n  border-top-color: #c9e7c9;\n}\n.am-panel-success > .am-panel-footer + .am-panel-collapse > .am-panel-bd {\n  border-bottom-color: #c9e7c9;\n}\n.am-panel-warning {\n  border-color: #fbd0ae;\n}\n.am-panel-warning > .am-panel-hd {\n  color: #F37B1D;\n  background-color: rgba(243, 123, 29, 0.15);\n  border-color: #fbd0ae;\n}\n.am-panel-warning > .am-panel-hd + .am-panel-collapse > .am-panel-bd {\n  border-top-color: #fbd0ae;\n}\n.am-panel-warning > .am-panel-footer + .am-panel-collapse > .am-panel-bd {\n  border-bottom-color: #fbd0ae;\n}\n.am-panel-danger {\n  border-color: #f5cecd;\n}\n.am-panel-danger > .am-panel-hd {\n  color: #dd514c;\n  background-color: rgba(221, 81, 76, 0.15);\n  border-color: #f5cecd;\n}\n.am-panel-danger > .am-panel-hd + .am-panel-collapse > .am-panel-bd {\n  border-top-color: #f5cecd;\n}\n.am-panel-danger > .am-panel-footer + .am-panel-collapse > .am-panel-bd {\n  border-bottom-color: #f5cecd;\n}\n.am-panel > .am-table {\n  margin-bottom: 0;\n}\n.am-panel > .am-table:first-child {\n  border-top-right-radius: 2px;\n  border-top-left-radius: 2px;\n}\n.am-panel > .am-table:first-child > thead:first-child > tr:first-child td:first-child,\n.am-panel > .am-table:first-child > tbody:first-child > tr:first-child td:first-child,\n.am-panel > .am-table:first-child > thead:first-child > tr:first-child th:first-child,\n.am-panel > .am-table:first-child > tbody:first-child > tr:first-child th:first-child {\n  border-top-left-radius: 2px;\n}\n.am-panel > .am-table:first-child > thead:first-child > tr:first-child td:last-child,\n.am-panel > .am-table:first-child > tbody:first-child > tr:first-child td:last-child,\n.am-panel > .am-table:first-child > thead:first-child > tr:first-child th:last-child,\n.am-panel > .am-table:first-child > tbody:first-child > tr:first-child th:last-child {\n  border-top-right-radius: 2px;\n}\n.am-panel > .am-table:last-child {\n  border-bottom-right-radius: 2px;\n  border-bottom-left-radius: 2px;\n}\n.am-panel > .am-table:last-child > tbody:last-child > tr:last-child td:first-child,\n.am-panel > .am-table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.am-panel > .am-table:last-child > tbody:last-child > tr:last-child th:first-child,\n.am-panel > .am-table:last-child > tfoot:last-child > tr:last-child th:first-child {\n  border-bottom-left-radius: 2px;\n}\n.am-panel > .am-table:last-child > tbody:last-child > tr:last-child td:last-child,\n.am-panel > .am-table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.am-panel > .am-table:last-child > tbody:last-child > tr:last-child th:last-child,\n.am-panel > .am-table:last-child > tfoot:last-child > tr:last-child th:last-child {\n  border-bottom-right-radius: 2px;\n}\n.am-panel > .am-panel-bd + .am-table {\n  border-top: 1px solid #ddd;\n}\n.am-panel > .am-table > tbody:first-child > tr:first-child th,\n.am-panel > .am-table > tbody:first-child > tr:first-child td {\n  border-top: 0;\n}\n.am-panel > .am-table-bd {\n  border: 0;\n}\n.am-panel > .am-table-bd > thead > tr > th:first-child,\n.am-panel > .am-table-bd > tbody > tr > th:first-child,\n.am-panel > .am-table-bd > tfoot > tr > th:first-child,\n.am-panel > .am-table-bd > thead > tr > td:first-child,\n.am-panel > .am-table-bd > tbody > tr > td:first-child,\n.am-panel > .am-table-bd > tfoot > tr > td:first-child {\n  border-left: 0;\n}\n.am-panel > .am-table-bd > thead > tr > th:last-child,\n.am-panel > .am-table-bd > tbody > tr > th:last-child,\n.am-panel > .am-table-bd > tfoot > tr > th:last-child,\n.am-panel > .am-table-bd > thead > tr > td:last-child,\n.am-panel > .am-table-bd > tbody > tr > td:last-child,\n.am-panel > .am-table-bd > tfoot > tr > td:last-child {\n  border-right: 0;\n}\n.am-panel > .am-table-bd > thead > tr:first-child > td,\n.am-panel > .am-table-bd > tbody > tr:first-child > td,\n.am-panel > .am-table-bd > thead > tr:first-child > th,\n.am-panel > .am-table-bd > tbody > tr:first-child > th {\n  border-bottom: 0;\n}\n.am-panel > .am-table-bd > tbody > tr:last-child > td,\n.am-panel > .am-table-bd > tfoot > tr:last-child > td,\n.am-panel > .am-table-bd > tbody > tr:last-child > th,\n.am-panel > .am-table-bd > tfoot > tr:last-child > th {\n  border-bottom: 0;\n}\n/* Wrap list */\n.am-panel > .am-list {\n  margin: 0;\n}\n.am-panel > .am-list > li > a {\n  padding-left: 1rem;\n  padding-right: 1rem;\n}\n.am-panel > .am-list-static li {\n  padding-left: 1rem;\n  padding-right: 1rem;\n}\n/* Panel group */\n.am-panel-group {\n  margin-bottom: 2rem;\n}\n.am-panel-group .am-panel {\n  margin-bottom: 0;\n  border-radius: 2px;\n}\n.am-panel-group .am-panel + .am-panel {\n  margin-top: 6px;\n}\n.am-panel-group .am-panel-hd {\n  border-bottom: 0;\n}\n.am-panel-group .am-panel-hd + .am-panel-collapse .am-panel-bd {\n  border-top: 1px solid #ddd;\n}\n.am-panel-group .am-panel-footer {\n  border-top: 0;\n}\n.am-panel-group .am-panel-footer + .am-panel-collapse .am-panel-bd {\n  border-bottom: 1px solid #ddd;\n}\n/* ==========================================================================\n   Component: Progress\n ============================================================================ */\n/* Progress bar animation */\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 36px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 36px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n/*  Progress container */\n.am-progress {\n  overflow: hidden;\n  height: 2rem;\n  margin-bottom: 2rem;\n  background-color: #f5f5f5;\n  border-radius: 2px;\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/* Progress bar */\n.am-progress-bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 1.2rem;\n  line-height: 2rem;\n  color: #fff;\n  text-align: center;\n  background-color: #0e90d2;\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 .6s ease;\n  transition: width .6s ease;\n}\n.am-progress-striped .am-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: 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  -webkit-background-size: 36px 36px;\n          background-size: 36px 36px;\n}\n.am-progress.am-active .am-progress-bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n.am-progress-bar[aria-valuenow=\"1\"],\n.am-progress-bar[aria-valuenow=\"2\"] {\n  min-width: 30px;\n}\n.am-progress-bar[aria-valuenow=\"0\"] {\n  color: #999999;\n  min-width: 30px;\n  background: none;\n  -webkit-box-shadow: none;\n          box-shadow: none;\n}\n.am-progress-bar-secondary {\n  background-color: #3bb4f2;\n}\n.am-progress-striped .am-progress-bar-secondary {\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: 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.am-progress-bar-success {\n  background-color: #5eb95e;\n}\n.am-progress-striped .am-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: 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.am-progress-bar-warning {\n  background-color: #F37B1D;\n}\n.am-progress-striped .am-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: 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.am-progress-bar-danger {\n  background-color: #dd514c;\n}\n.am-progress-striped .am-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: 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.am-progress-xs {\n  height: 0.6rem;\n}\n.am-progress-sm {\n  height: 1.2rem;\n}\n/* ==========================================================================\n   Component: Thumbnail\n ============================================================================ */\n.am-thumbnail {\n  display: block;\n  padding: 2px;\n  margin-bottom: 2rem;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  border-radius: 2px;\n  -webkit-transition: all 0.2s ease-in-out;\n  transition: all 0.2s ease-in-out;\n}\n.am-thumbnail > img,\n.am-thumbnail a > img {\n  margin-left: auto;\n  margin-right: auto;\n  display: block;\n}\n.am-thumbnail a.am-thumbnail:hover,\n.am-thumbnail a.am-thumbnail:focus,\n.am-thumbnail a.am-thumbnail.active {\n  border-color: #0e90d2;\n  background-color: #fff;\n}\nimg.am-thumbnail,\n.am-thumbnail > img,\n.am-thumbnail a > img {\n  max-width: 100%;\n  height: auto;\n}\n/* Image caption */\n.am-thumbnail-caption {\n  margin: 0;\n  padding: 0.8rem;\n  color: #333;\n  font-weight: normal;\n}\n.am-thumbnail-caption *:last-child {\n  margin-bottom: 0;\n}\n.am-thumbnails {\n  margin-left: -0.5rem;\n  margin-right: -0.5rem;\n}\n.am-thumbnails > li {\n  padding: 0 .5rem 1rem .5rem;\n}\n/* ==========================================================================\n   Component: Utility\n ============================================================================ */\n.am-scrollable-horizontal {\n  width: 100%;\n  overflow-y: hidden;\n  overflow-x: auto;\n  -ms-overflow-style: -ms-autohiding-scrollbar;\n  -webkit-overflow-scrolling: touch;\n}\n.am-scrollable-vertical {\n  height: 240px;\n  overflow-y: scroll;\n  -webkit-overflow-scrolling: touch;\n  resize: vertical;\n}\n/* Border-radius*/\n.am-square {\n  border-radius: 0;\n}\n.am-radius {\n  border-radius: 2px;\n}\n.am-round {\n  border-radius: 1000px;\n}\n.am-circle {\n  border-radius: 50%;\n}\n/* Float blocks*/\n.am-cf:before,\n.am-cf:after {\n  content: \" \";\n  display: table;\n}\n.am-cf:after {\n  clear: both;\n}\n.am-fl {\n  float: left;\n}\n.am-fr {\n  float: right;\n}\n.am-nbfc {\n  overflow: hidden;\n}\n.am-center {\n  display: block;\n  margin-left: auto;\n  margin-right: auto;\n}\n/* Display */\n.am-block {\n  display: block !important;\n}\n.am-inline {\n  display: inline !important;\n}\n.am-inline-block {\n  display: inline-block !important;\n}\n.am-hide {\n  display: none !important;\n  visibility: hidden !important;\n}\n/*\n* Remove whitespace between child elements when using `inline-block`\n*/\n.am-vertical-align {\n  font-size: 0.001px;\n}\n/*\n* The `@{ns}vertical-align` container needs a specific height\n*/\n.am-vertical-align:before {\n  content: '';\n  display: inline-block;\n  height: 100%;\n  vertical-align: middle;\n}\n/*\n* Sub-object which can have any height\n* 1. Reset whitespace hack\n*/\n.am-vertical-align-middle,\n.am-vertical-align-bottom {\n  display: inline-block;\n  font-size: 1.6rem;\n  /* 1 */\n  max-width: 100%;\n}\n.am-vertical-align-middle {\n  vertical-align: middle;\n}\n.am-vertical-align-bottom {\n  vertical-align: bottom;\n}\n.am-responsive-width {\n  -webkit-box-sizing: border-box;\n          box-sizing: border-box;\n  max-width: 100%;\n  height: auto;\n}\n/* Margin helpers */\n.am-margin {\n  margin: 1.6rem;\n}\n.am-margin-0 {\n  margin: 0!important;\n}\n.am-margin-xs {\n  margin: 0.5rem;\n}\n.am-margin-sm {\n  margin: 1rem;\n}\n.am-margin-lg {\n  margin: 2.4rem;\n}\n.am-margin-xl {\n  margin: 3.2rem;\n}\n.am-margin-horizontal {\n  margin-left: 1.6rem;\n  margin-right: 1.6rem;\n}\n.am-margin-horizontal-0 {\n  margin-left: 0!important;\n  margin-right: 0!important;\n}\n.am-margin-horizontal-xs {\n  margin-left: 0.5rem;\n  margin-right: 0.5rem;\n}\n.am-margin-horizontal-sm {\n  margin-left: 1rem;\n  margin-right: 1rem;\n}\n.am-margin-horizontal-lg {\n  margin-left: 2.4rem;\n  margin-right: 2.4rem;\n}\n.am-margin-horizontal-xl {\n  margin-left: 3.2rem;\n  margin-right: 3.2rem;\n}\n.am-margin-vertical {\n  margin-top: 1.6rem;\n  margin-bottom: 1.6rem;\n}\n.am-margin-vertical-0 {\n  margin-top: 0!important;\n  margin-bottom: 0!important;\n}\n.am-margin-vertical-xs {\n  margin-top: 0.5rem;\n  margin-bottom: 0.5rem;\n}\n.am-margin-vertical-sm {\n  margin-top: 1rem;\n  margin-bottom: 1rem;\n}\n.am-margin-vertical-lg {\n  margin-top: 2.4rem;\n  margin-bottom: 2.4rem;\n}\n.am-margin-vertical-xl {\n  margin-top: 3.2rem;\n  margin-bottom: 3.2rem;\n}\n.am-margin-top {\n  margin-top: 1.6rem;\n}\n.am-margin-top-0 {\n  margin-top: 0!important;\n}\n.am-margin-top-xs {\n  margin-top: 0.5rem;\n}\n.am-margin-top-sm {\n  margin-top: 1rem;\n}\n.am-margin-top-lg {\n  margin-top: 2.4rem;\n}\n.am-margin-top-xl {\n  margin-top: 3.2rem;\n}\n.am-margin-bottom {\n  margin-bottom: 1.6rem;\n}\n.am-margin-bottom-0 {\n  margin-bottom: 0!important;\n}\n.am-margin-bottom-xs {\n  margin-bottom: 0.5rem;\n}\n.am-margin-bottom-sm {\n  margin-bottom: 1rem;\n}\n.am-margin-bottom-lg {\n  margin-bottom: 2.4rem;\n}\n.am-margin-bottom-xl {\n  margin-bottom: 3.2rem;\n}\n.am-margin-left {\n  margin-left: 1.6rem;\n}\n.am-margin-left-0 {\n  margin-left: 0!important;\n}\n.am-margin-left-xs {\n  margin-left: 0.5rem;\n}\n.am-margin-left-sm {\n  margin-left: 1rem;\n}\n.am-margin-left-lg {\n  margin-left: 2.4rem;\n}\n.am-margin-left-xl {\n  margin-left: 3.2rem;\n}\n.am-margin-right {\n  margin-right: 1.6rem;\n}\n.am-margin-right-0 {\n  margin-right: 0!important;\n}\n.am-margin-right-xs {\n  margin-right: 0.5rem;\n}\n.am-margin-right-sm {\n  margin-right: 1rem;\n}\n.am-margin-right-lg {\n  margin-right: 2.4rem;\n}\n.am-margin-right-xl {\n  margin-right: 3.2rem;\n}\n/* Padding helpers */\n.am-padding {\n  padding: 1.6rem;\n}\n.am-padding-0 {\n  padding: 0!important;\n}\n.am-padding-xs {\n  padding: 0.5rem;\n}\n.am-padding-sm {\n  padding: 1rem;\n}\n.am-padding-lg {\n  padding: 2.4rem;\n}\n.am-padding-xl {\n  padding: 3.2rem;\n}\n.am-padding-horizontal {\n  padding-left: 1.6rem;\n  padding-right: 1.6rem;\n}\n.am-padding-horizontal-0 {\n  padding-left: 0!important;\n  padding-right: 0!important;\n}\n.am-padding-horizontal-xs {\n  padding-left: 0.5rem;\n  padding-right: 0.5rem;\n}\n.am-padding-horizontal-sm {\n  padding-left: 1rem;\n  padding-right: 1rem;\n}\n.am-padding-horizontal-lg {\n  padding-left: 2.4rem;\n  padding-right: 2.4rem;\n}\n.am-padding-horizontal-xl {\n  padding-left: 3.2rem;\n  padding-right: 3.2rem;\n}\n.am-padding-vertical {\n  padding-top: 1.6rem;\n  padding-bottom: 1.6rem;\n}\n.am-padding-vertical-0 {\n  padding-top: 0!important;\n  padding-bottom: 0!important;\n}\n.am-padding-vertical-xs {\n  padding-top: 0.5rem;\n  padding-bottom: 0.5rem;\n}\n.am-padding-vertical-sm {\n  padding-top: 1rem;\n  padding-bottom: 1rem;\n}\n.am-padding-vertical-lg {\n  padding-top: 2.4rem;\n  padding-bottom: 2.4rem;\n}\n.am-padding-vertical-xl {\n  padding-top: 3.2rem;\n  padding-bottom: 3.2rem;\n}\n.am-padding-top {\n  padding-top: 1.6rem;\n}\n.am-padding-top-0 {\n  padding-top: 0!important;\n}\n.am-padding-top-xs {\n  padding-top: 0.5rem;\n}\n.am-padding-top-sm {\n  padding-top: 1rem;\n}\n.am-padding-top-lg {\n  padding-top: 2.4rem;\n}\n.am-padding-top-xl {\n  padding-top: 3.2rem;\n}\n.am-padding-bottom {\n  padding-bottom: 1.6rem;\n}\n.am-padding-bottom-0 {\n  padding-bottom: 0!important;\n}\n.am-padding-bottom-xs {\n  padding-bottom: 0.5rem;\n}\n.am-padding-bottom-sm {\n  padding-bottom: 1rem;\n}\n.am-padding-bottom-lg {\n  padding-bottom: 2.4rem;\n}\n.am-padding-bottom-xl {\n  padding-bottom: 3.2rem;\n}\n.am-padding-left {\n  padding-left: 1.6rem;\n}\n.am-padding-left-0 {\n  padding-left: 0!important;\n}\n.am-padding-left-xs {\n  padding-left: 0.5rem;\n}\n.am-padding-left-sm {\n  padding-left: 1rem;\n}\n.am-padding-left-lg {\n  padding-left: 2.4rem;\n}\n.am-padding-left-xl {\n  padding-left: 3.2rem;\n}\n.am-padding-right {\n  padding-right: 1.6rem;\n}\n.am-padding-right-0 {\n  padding-right: 0!important;\n}\n.am-padding-right-xs {\n  padding-right: 0.5rem;\n}\n.am-padding-right-sm {\n  padding-right: 1rem;\n}\n.am-padding-right-lg {\n  padding-right: 2.4rem;\n}\n.am-padding-right-xl {\n  padding-right: 3.2rem;\n}\n/* small displays */\n@media only screen {\n  .am-show-sm-only,\n  .am-show-sm-up,\n  .am-show-sm,\n  .am-show-sm-down,\n  .am-hide-md-only,\n  .am-hide-md-up,\n  .am-hide-md,\n  .am-show-md-down,\n  .am-hide-lg-only,\n  .am-hide-lg-up,\n  .am-hide-lg,\n  .am-show-lg-down {\n    display: inherit !important;\n  }\n  .am-hide-sm-only,\n  .am-hide-sm-up,\n  .am-hide-sm,\n  .am-hide-sm-down,\n  .am-show-md-only,\n  .am-show-md-up,\n  .am-show-md,\n  .am-hide-md-down,\n  .am-show-lg-only,\n  .am-show-lg-up,\n  .am-show-lg,\n  .am-hide-lg-down {\n    display: none !important;\n  }\n  /* table */\n  table.am-show-sm-only,\n  table.am-show-sm-up,\n  table.am-show-sm,\n  table.am-show-sm-down,\n  table.am-hide-md-only,\n  table.am-hide-md-up,\n  table.am-hide-md,\n  table.am-show-md-down,\n  table.am-hide-lg-only,\n  table.am-hide-lg-up,\n  table.am-hide-lg,\n  table.am-show-lg-down {\n    display: table !important;\n  }\n  thead.am-show-sm-only,\n  thead.am-show-sm-up,\n  thead.am-show-sm,\n  thead.am-show-sm-down,\n  thead.am-hide-md-only,\n  thead.am-hide-md-up,\n  thead.am-hide-md,\n  thead.am-show-md-down,\n  thead.am-hide-lg-only,\n  thead.am-hide-lg-up,\n  thead.am-hide-lg,\n  thead.am-show-lg-down {\n    display: table-header-group !important;\n  }\n  tbody.am-show-sm-only,\n  tbody.am-show-sm-up,\n  tbody.am-show-sm,\n  tbody.am-show-sm-down,\n  tbody.am-hide-md-only,\n  tbody.am-hide-md-up,\n  tbody.am-hide-md,\n  tbody.am-show-md-down,\n  tbody.am-hide-lg-only,\n  tbody.am-hide-lg-up,\n  tbody.am-hide-lg,\n  tbody.am-show-lg-down {\n    display: table-row-group !important;\n  }\n  tr.am-show-sm-only,\n  tr.am-show-sm-up,\n  tr.am-show-sm,\n  tr.am-show-sm-down,\n  tr.am-hide-md-only,\n  tr.am-hide-md-up,\n  tr.am-hide-md,\n  tr.am-show-md-down,\n  tr.am-hide-lg-only,\n  tr.am-hide-lg-up,\n  tr.am-hide-lg,\n  tr.am-show-lg-down {\n    display: table-row !important;\n  }\n  th.am-show-sm-only,\n  td.am-show-sm-only,\n  th.am-show-sm-up,\n  td.am-show-sm-up,\n  th.am-show-sm,\n  td.am-show-sm,\n  th.am-show-sm-down,\n  td.am-show-sm-down,\n  th.am-hide-md-only,\n  td.am-hide-md-only,\n  th.am-hide-md-up,\n  td.am-hide-md-up,\n  th.am-hide-md,\n  td.am-hide-md,\n  th.am-show-md-down,\n  td.am-show-md-down,\n  th.am-hide-lg-only,\n  td.am-hide-lg-only,\n  th.am-hide-lg-up,\n  td.am-hide-lg-up,\n  th.am-hide-lg,\n  td.am-hide-lg,\n  th.am-show-lg-down,\n  td.am-show-lg-down {\n    display: table-cell !important;\n  }\n}\n/* medium displays */\n@media only screen and (min-width:641px) {\n  .am-hide-sm-only,\n  .am-show-sm-up,\n  .am-hide-sm,\n  .am-hide-sm-down,\n  .am-show-md-only,\n  .am-show-md-up,\n  .am-show-md,\n  .am-show-md-down,\n  .am-hide-lg-only,\n  .am-hide-lg-up,\n  .am-hide-lg,\n  .am-show-lg-down {\n    display: inherit !important;\n  }\n  .am-show-sm-only,\n  .am-hide-sm-up,\n  .am-show-sm,\n  .am-show-sm-down,\n  .am-hide-md-only,\n  .am-hide-md-up,\n  .am-hide-md,\n  .am-hide-md-down,\n  .am-show-lg-only,\n  .am-show-lg-up,\n  .am-show-lg,\n  .am-hide-lg-down {\n    display: none !important;\n  }\n  table.am-hide-sm-only,\n  table.am-show-sm-up,\n  table.am-hide-sm,\n  table.am-hide-sm-down,\n  table.am-show-md-only,\n  table.am-show-md-up,\n  table.am-show-md,\n  table.am-show-md-down,\n  table.am-hide-lg-only,\n  table.am-hide-lg-up,\n  table.am-hide-lg,\n  table.am-show-lg-down {\n    display: table !important;\n  }\n  thead.am-hide-sm-only,\n  thead.am-show-sm-up,\n  thead.am-hide-sm,\n  thead.am-hide-sm-down,\n  thead.am-show-md-only,\n  thead.am-show-md-up,\n  thead.am-show-md,\n  thead.am-show-md-down,\n  thead.am-hide-lg-only,\n  thead.am-hide-lg-up,\n  thead.am-hide-lg,\n  thead.am-show-lg-down {\n    display: table-header-group !important;\n  }\n  tbody.am-hide-sm-only,\n  tbody.am-show-sm-up,\n  tbody.am-hide-sm,\n  tbody.am-hide-sm-down,\n  tbody.am-show-md-only,\n  tbody.am-show-md-up,\n  tbody.am-show-md,\n  tbody.am-show-md-down,\n  tbody.am-hide-lg-only,\n  tbody.am-hide-lg-up,\n  tbody.am-hide-lg,\n  tbody.am-show-lg-down {\n    display: table-row-group !important;\n  }\n  tr.am-hide-sm-only,\n  tr.am-show-sm-up,\n  tr.am-hide-sm,\n  tr.am-hide-sm-down,\n  tr.am-show-md-only,\n  tr.am-show-md-up,\n  tr.am-show-md,\n  tr.am-show-md-down,\n  tr.am-hide-lg-only,\n  tr.am-hide-lg-up,\n  tr.am-hide-lg,\n  tr.am-show-lg-down {\n    display: table-row !important;\n  }\n  th.am-hide-sm-only,\n  td.am-hide-sm-only,\n  th.am-show-sm-up,\n  td.am-show-sm-up,\n  th.am-hide-sm,\n  td.am-hide-sm,\n  th.am-hide-sm-down,\n  td.am-hide-sm-down,\n  th.am-show-md-only,\n  td.am-show-md-only,\n  th.am-show-md-up,\n  td.am-show-md-up,\n  th.am-show-md,\n  td.am-show-md,\n  th.am-show-md-down,\n  td.am-show-md-down,\n  th.am-hide-lg-only,\n  td.am-hide-lg-only,\n  th.am-hide-lg-up,\n  td.am-hide-lg-up,\n  th.am-hide-lg,\n  td.am-hide-lg,\n  th.am-show-lg-down,\n  td.am-show-lg-down {\n    display: table-cell !important;\n  }\n}\n/* large displays */\n@media only screen and (min-width:1025px) {\n  .am-hide-sm-only,\n  .am-show-sm-up,\n  .am-hide-sm,\n  .am-hide-sm-down,\n  .am-hide-md-only,\n  .am-show-md-up,\n  .am-hide-md,\n  .am-hide-md-down,\n  .am-show-lg-only,\n  .am-show-lg-up,\n  .am-show-lg,\n  .am-show-lg-down {\n    display: inherit !important;\n  }\n  .am-show-sm-only,\n  .am-hide-sm-up,\n  .am-show-sm,\n  .am-show-sm-down,\n  .am-show-md-only,\n  .am-hide-md-up,\n  .am-show-md,\n  .am-show-md-down,\n  .am-hide-lg-only,\n  .am-hide-lg-up,\n  .am-hide-lg,\n  .am-hide-lg-down {\n    display: none !important;\n  }\n  table.am-hide-sm-only,\n  table.am-show-sm-up,\n  table.am-hide-sm,\n  table.am-hide-sm-down,\n  table.am-hide-md-only,\n  table.am-show-md-up,\n  table.am-hide-md,\n  table.am-hide-md-down,\n  table.am-show-lg-only,\n  table.am-show-lg-up,\n  table.am-show-lg,\n  table.am-show-lg-down {\n    display: table !important;\n  }\n  thead.am-hide-sm-only,\n  thead.am-show-sm-up,\n  thead.am-hide-sm,\n  thead.am-hide-sm-down,\n  thead.am-hide-md-only,\n  thead.am-show-md-up,\n  thead.am-hide-md,\n  thead.am-hide-md-down,\n  thead.am-show-lg-only,\n  thead.am-show-lg-up,\n  thead.am-show-lg,\n  thead.am-show-lg-down {\n    display: table-header-group !important;\n  }\n  tbody.am-hide-sm-only,\n  tbody.am-show-sm-up,\n  tbody.am-hide-sm,\n  tbody.am-hide-sm-down,\n  tbody.am-hide-md-only,\n  tbody.am-show-md-up,\n  tbody.am-hide-md,\n  tbody.am-hide-md-down,\n  tbody.am-show-lg-only,\n  tbody.am-show-lg-up,\n  tbody.am-show-lg,\n  tbody.am-show-lg-down {\n    display: table-row-group !important;\n  }\n  tr.am-hide-sm-only,\n  tr.am-show-sm-up,\n  tr.am-hide-sm,\n  tr.am-hide-sm-down,\n  tr.am-hide-md-only,\n  tr.am-show-md-up,\n  tr.am-hide-md,\n  tr.am-hide-md-down,\n  tr.am-show-lg-only,\n  tr.am-show-lg-up,\n  tr.am-show-lg,\n  tr.am-show-lg-down {\n    display: table-row !important;\n  }\n  th.am-hide-sm-only,\n  td.am-hide-sm-only,\n  th.am-show-sm-up,\n  td.am-show-sm-up,\n  th.am-hide-sm,\n  td.am-hide-sm,\n  th.am-hide-sm-down,\n  td.am-hide-sm-down,\n  th.am-hide-md-only,\n  td.am-hide-md-only,\n  th.am-show-md-up,\n  td.am-show-md-up,\n  th.am-hide-md,\n  td.am-hide-md,\n  th.am-hide-md-down,\n  td.am-hide-md-down,\n  th.am-show-lg-only,\n  td.am-show-lg-only,\n  th.am-show-lg-up,\n  td.am-show-lg-up,\n  th.am-show-lg,\n  td.am-show-lg,\n  th.am-show-lg-down,\n  td.am-show-lg-down {\n    display: table-cell !important;\n  }\n}\n@media only screen and (orientation: landscape) {\n  .am-show-landscape,\n  .am-hide-portrait {\n    display: inherit !important;\n  }\n  .am-hide-landscape,\n  .am-show-portrait {\n    display: none !important;\n  }\n}\n@media only screen and (orientation: portrait) {\n  .am-show-portrait,\n  .am-hide-landscape {\n    display: inherit !important;\n  }\n  .am-hide-portrait,\n  .am-show-landscape {\n    display: none !important;\n  }\n}\n.am-sans-serif {\n  font-family: \"Segoe UI\", \"Lucida Grande\", Helvetica, Arial, \"Microsoft YaHei\", FreeSans, Arimo, \"Droid Sans\", \"wenquanyi micro hei\", \"Hiragino Sans GB\", \"Hiragino Sans GB W3\", \"FontAwesome\", sans-serif;\n}\n.am-serif {\n  font-family: Georgia, \"Times New Roman\", Times, SimSun, \"FontAwesome\", serif;\n}\n.am-kai {\n  font-family: Georgia, \"Times New Roman\", Times, Kai, \"Kaiti SC\", KaiTi, BiauKai, \"FontAwesome\", serif;\n}\n.am-monospace {\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", \"FontAwesome\", monospace;\n}\n.am-text-primary {\n  color: #0e90d2;\n}\n.am-text-secondary {\n  color: #3bb4f2;\n}\n.am-text-success {\n  color: #5eb95e;\n}\n.am-text-warning {\n  color: #F37B1D;\n}\n.am-text-danger {\n  color: #dd514c;\n}\n.am-link-muted {\n  color: #666;\n}\n.am-link-muted a {\n  color: #666;\n}\n.am-link-muted:hover,\n.am-link-muted a:hover {\n  color: #555;\n}\n.am-text-default {\n  font-size: 1.6rem;\n}\n/*\n.@{ns}text-xxs {\n  font-size: @font-size-xxs;\n}\n*/\n.am-text-xs {\n  font-size: 1.2rem;\n}\n.am-text-sm {\n  font-size: 1.4rem;\n}\n.am-text-lg {\n  font-size: 1.8rem;\n}\n.am-text-xl {\n  font-size: 2.4rem;\n}\n.am-text-xxl {\n  font-size: 3.2rem;\n}\n.am-text-xxxl {\n  font-size: 4.2rem;\n}\n.am-ellipsis,\n.am-text-truncate {\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-text-break {\n  word-wrap: break-word;\n  -webkit-hyphens: auto;\n  -ms-hyphens: auto;\n  -moz-hyphens: auto;\n  hyphens: auto;\n}\n.am-text-nowrap {\n  white-space: nowrap;\n}\n[class*='am-align-'] {\n  margin-bottom: 1rem;\n}\n.am-align-left {\n  margin-right: 1rem;\n  float: left;\n}\n.am-align-right {\n  margin-left: 1rem;\n  float: right;\n}\n/** Only display content to screen readers\n * See: http://a11yproject.com/posts/how-to-hide-content/\n */\n.am-sr-only {\n  position: absolute;\n  width: 1px;\n  height: 1px;\n  margin: -1px;\n  padding: 0;\n  overflow: hidden;\n  clip: rect(0, 0, 0, 0);\n  border: 0;\n}\n/* Text Image Replacement */\n.am-text-ir {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n/* Text align */\n@media only screen {\n  .am-text-left {\n    text-align: left !important;\n  }\n  .am-text-right {\n    text-align: right !important;\n  }\n  .am-text-center {\n    text-align: center !important;\n  }\n  .am-text-justify {\n    text-align: justify !important;\n  }\n}\n@media only screen and (max-width: 640px) {\n  .am-sm-only-text-left {\n    text-align: left !important;\n  }\n  .am-sm-only-text-right {\n    text-align: right !important;\n  }\n  .am-sm-only-text-center {\n    text-align: center !important;\n  }\n  .am-sm-only-text-justify {\n    text-align: justify !important;\n  }\n}\n@media only screen and (min-width:641px) and (max-width:1024px) {\n  .am-md-only-text-left {\n    text-align: left !important;\n  }\n  .am-md-only-text-right {\n    text-align: right !important;\n  }\n  .am-md-only-text-center {\n    text-align: center !important;\n  }\n  .am-md-only-text-justify {\n    text-align: justify !important;\n  }\n}\n@media only screen and (min-width:641px) {\n  .am-md-text-left {\n    text-align: left !important;\n  }\n  .am-md-text-right {\n    text-align: right !important;\n  }\n  .am-md-text-center {\n    text-align: center !important;\n  }\n  .am-md-text-justify {\n    text-align: justify !important;\n  }\n}\n@media only screen and (min-width:1025px) {\n  .am-lg-text-left {\n    text-align: left !important;\n  }\n  .am-lg-text-right {\n    text-align: right !important;\n  }\n  .am-lg-text-center {\n    text-align: center !important;\n  }\n  .am-lg-text-justify {\n    text-align: justify !important;\n  }\n}\n.am-text-top {\n  vertical-align: top !important;\n}\n.am-text-middle {\n  vertical-align: middle !important;\n}\n.am-text-bottom {\n  vertical-align: bottom !important;\n}\n.am-angle {\n  position: absolute;\n}\n.am-angle:before,\n.am-angle:after {\n  position: absolute;\n  display: block;\n  content: \"\";\n  width: 0;\n  height: 0;\n  border: 8px dashed transparent;\n  z-index: 1;\n}\n.am-angle-up {\n  top: 0;\n}\n.am-angle-up:before,\n.am-angle-up:after {\n  border-bottom-style: solid;\n  border-width: 0 8px 8px;\n}\n.am-angle-up:before {\n  border-bottom-color: #ddd;\n  bottom: 0;\n}\n.am-angle-up:after {\n  border-bottom-color: #fff;\n  bottom: -1px;\n}\n.am-angle-down {\n  bottom: -9px;\n}\n.am-angle-down:before,\n.am-angle-down:after {\n  border-top-style: solid;\n  border-width: 8px 8px 0;\n}\n.am-angle-down:before {\n  border-top-color: #ddd;\n  bottom: 0;\n}\n.am-angle-down:after {\n  border-top-color: #fff;\n  bottom: 1px;\n}\n.am-angle-left {\n  left: -9px;\n}\n.am-angle-left:before,\n.am-angle-left:after {\n  border-right-style: solid;\n  border-width: 8px 8px 8px 0;\n}\n.am-angle-left:before {\n  border-right-color: #ddd;\n  left: 0;\n}\n.am-angle-left:after {\n  border-right-color: #fff;\n  left: 1px;\n}\n.am-angle-right {\n  right: 0;\n}\n.am-angle-right:before,\n.am-angle-right:after {\n  border-left-style: solid;\n  border-width: 8px 0 8px 8px;\n}\n.am-angle-right:before {\n  border-left-color: #ddd;\n  left: 0;\n}\n.am-angle-right:after {\n  border-left-color: #fff;\n  left: -1px;\n}\n/* ==========================================================================\n   Component: Alert Plugin\n ============================================================================ */\n.am-alert {\n  margin-bottom: 1em;\n  padding: 0.625em;\n  background: #0e90d2;\n  color: #fff;\n  border: 1px solid #0c7cb5;\n  border-radius: 2px;\n}\n.am-alert a {\n  color: #fff;\n}\n.am-alert h1,\n.am-alert h2,\n.am-alert h3,\n.am-alert h4,\n.am-alert h5,\n.am-alert h6 {\n  color: inherit;\n}\n.am-alert .am-close {\n  opacity: .4;\n}\n.am-alert .am-close:hover {\n  opacity: .6;\n}\n/* Add margin if adjacent element */\n* + .am-alert {\n  margin-top: 1em;\n}\n/* Remove margin from the last-child */\n.am-alert > :last-child {\n  margin-bottom: 0;\n}\n/* within am-form-group */\n.am-form-group .am-alert {\n  margin: 5px 0 0;\n  padding: 0.25em 0.625em;\n  font-size: 1.3rem;\n}\n/* Close in alert */\n.am-alert > .am-close:first-child {\n  float: right;\n  height: auto;\n  margin: -3px -5px auto auto;\n}\n/* Remove margin from adjacent element */\n.am-alert > .am-close:first-child + * {\n  margin-top: 0;\n}\n.am-alert-secondary {\n  background-color: #eeeeee;\n  border-color: #dfdfdf;\n  color: #555555;\n}\n.am-alert-success {\n  background-color: #5eb95e;\n  border-color: #4bad4b;\n  color: #fff;\n}\n.am-alert-warning {\n  background-color: #F37B1D;\n  border-color: #e56c0c;\n  color: #fff;\n}\n.am-alert-danger {\n  background-color: #dd514c;\n  border-color: #d83832;\n  color: #fff;\n}\n.am-dropdown {\n  position: relative;\n  display: inline-block;\n}\n.am-dropdown-toggle:focus {\n  outline: 0;\n}\n.am-dropdown-content {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1020;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 15px;\n  margin: 9px 0 0;\n  text-align: left;\n  line-height: 1.6;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  border-radius: 2px;\n  -webkit-background-clip: padding-box;\n          background-clip: padding-box;\n  -webkit-animation-duration: .15s;\n          animation-duration: .15s;\n}\n.am-dropdown-content:before,\n.am-dropdown-content:after {\n  position: absolute;\n  display: block;\n  content: \"\";\n  width: 0;\n  height: 0;\n  border: 8px dashed transparent;\n  z-index: 1;\n}\n.am-dropdown-content:before,\n.am-dropdown-content:after {\n  border-bottom-style: solid;\n  border-width: 0 8px 8px;\n}\n.am-dropdown-content:before {\n  border-bottom-color: #ddd;\n  bottom: 0;\n}\n.am-dropdown-content:after {\n  border-bottom-color: #fff;\n  bottom: -1px;\n}\n.am-dropdown-content:before,\n.am-dropdown-content:after {\n  left: 10px;\n  top: -8px;\n  pointer-events: none;\n}\n.am-dropdown-content:after {\n  top: -7px;\n}\n.am-active > .am-dropdown-content {\n  display: block;\n}\n.am-dropdown-content :first-child {\n  margin-top: 0;\n}\n.am-dropdown-up .am-dropdown-content {\n  top: auto;\n  bottom: 100%;\n  margin: 0 0 9px;\n}\n.am-dropdown-up .am-dropdown-content:before,\n.am-dropdown-up .am-dropdown-content:after {\n  border-bottom: none;\n  border-top: 8px solid #ddd;\n  top: auto;\n  bottom: -8px;\n}\n.am-dropdown-up .am-dropdown-content:after {\n  bottom: -7px;\n  border-top-color: #fff;\n}\n.am-dropdown-flip .am-dropdown-content {\n  left: auto;\n  right: 0;\n}\n.am-dropdown-flip .am-dropdown-content:before,\n.am-dropdown-flip .am-dropdown-content:after {\n  left: auto;\n  right: 10px;\n}\nul.am-dropdown-content {\n  list-style: none;\n  padding: 5px 0;\n}\nul.am-dropdown-content.am-fr {\n  right: 0;\n  left: auto;\n}\nul.am-dropdown-content .am-divider {\n  height: 1px;\n  margin: 0rem 0;\n  overflow: hidden;\n  background-color: #e5e5e5;\n}\nul.am-dropdown-content > li > a {\n  display: block;\n  padding: 6px 20px;\n  clear: both;\n  font-weight: normal;\n  color: #333333;\n  white-space: nowrap;\n}\nul.am-dropdown-content > li > a:hover,\nul.am-dropdown-content > li > a:focus {\n  text-decoration: none;\n  color: #262626;\n  background-color: #f5f5f5;\n}\nul.am-dropdown-content > .am-active > a,\nul.am-dropdown-content > .am-active > a:hover,\nul.am-dropdown-content > .am-active > a:focus {\n  color: #fff;\n  text-decoration: none;\n  outline: 0;\n  background-color: #0e90d2;\n}\nul.am-dropdown-content > .am-disabled > a,\nul.am-dropdown-content > .am-disabled > a:hover,\nul.am-dropdown-content > .am-disabled > a:focus {\n  color: #999999;\n}\nul.am-dropdown-content > .am-disabled > a:hover,\nul.am-dropdown-content > .am-disabled > a:focus {\n  text-decoration: none;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n  cursor: not-allowed;\n}\n.am-dropdown-header {\n  display: block;\n  padding: 6px 20px;\n  font-size: 1.2rem;\n  color: #999999;\n}\n.am-fr > .am-dropdown-content {\n  right: 0;\n  left: auto;\n}\n.am-fr > .am-dropdown-content:before {\n  right: 10px;\n  left: auto;\n}\n.am-dropdown-animation {\n  -webkit-animation: am-dropdown-animation 0.15s ease-out;\n          animation: am-dropdown-animation 0.15s ease-out;\n}\n@-webkit-keyframes am-dropdown-animation {\n  0% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n            transform: translateY(0);\n  }\n  100% {\n    opacity: 0;\n    -webkit-transform: translateY(-10px);\n            transform: translateY(-10px);\n  }\n}\n@keyframes am-dropdown-animation {\n  0% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n            transform: translateY(0);\n  }\n  100% {\n    opacity: 0;\n    -webkit-transform: translateY(-10px);\n            transform: translateY(-10px);\n  }\n}\n/* ==========================================================================\n   Component: Flex Slider Plugin\n ============================================================================ */\n.am-slider a:hover,\n.am-slider a:focus {\n  outline: none;\n}\n.am-slides,\n.am-control-nav,\n.am-direction-nav {\n  margin: 0;\n  padding: 0;\n  list-style: none;\n}\n.am-slider {\n  margin: 0;\n  padding: 0;\n}\n.am-slider .am-slides:before,\n.am-slider .am-slides:after {\n  content: \" \";\n  display: table;\n}\n.am-slider .am-slides:after {\n  clear: both;\n}\n.am-slider .am-slides > li {\n  display: none;\n  -webkit-backface-visibility: hidden;\n  position: relative;\n}\n.no-js .am-slider .am-slides > li:first-child {\n  display: block;\n}\n.am-slider .am-slides img {\n  width: 100%;\n  display: block;\n}\n.am-pauseplay span {\n  text-transform: capitalize;\n}\n.am-slider {\n  position: relative;\n}\n.am-viewport {\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.am-slider-carousel li {\n  margin-right: 5px;\n}\n.am-control-nav {\n  position: absolute;\n}\n.am-control-nav li {\n  display: inline-block;\n}\n.am-control-thumbs {\n  position: static;\n  overflow: hidden;\n}\n.am-control-thumbs img {\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.am-slider-slide .am-slides > li {\n  display: none;\n  position: relative;\n}\n@media all and (transform-3d), (-webkit-transform-3d) {\n  .am-slider-slide .am-slides > li {\n    -webkit-transition: -webkit-transform 0.6s ease-in-out;\n    transition: -webkit-transform 0.6s ease-in-out;\n    transition: transform 0.6s ease-in-out;\n    transition: transform 0.6s ease-in-out, -webkit-transform 0.6s ease-in-out;\n    -webkit-backface-visibility: hidden;\n            backface-visibility: hidden;\n    -webkit-perspective: 1000px;\n            perspective: 1000px;\n  }\n  .am-slider-slide .am-slides > li.next,\n  .am-slider-slide .am-slides > li.active.right {\n    -webkit-transform: translate3d(100%, 0, 0);\n            transform: translate3d(100%, 0, 0);\n    left: 0;\n  }\n  .am-slider-slide .am-slides > li.prev,\n  .am-slider-slide .am-slides > li.active.left {\n    -webkit-transform: translate3d(-100%, 0, 0);\n            transform: translate3d(-100%, 0, 0);\n    left: 0;\n  }\n  .am-slider-slide .am-slides > li.next.left,\n  .am-slider-slide .am-slides > li.prev.right,\n  .am-slider-slide .am-slides > li.active {\n    -webkit-transform: translate3d(0, 0, 0);\n            transform: translate3d(0, 0, 0);\n    left: 0;\n  }\n}\n.am-slider-slide .am-slides > .active,\n.am-slider-slide .am-slides > .next,\n.am-slider-slide .am-slides > .prev {\n  display: block;\n}\n.am-slider-slide .am-slides > .active {\n  left: 0;\n}\n.am-slider-slide .am-slides > .next,\n.am-slider-slide .am-slides > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n.am-slider-slide .am-slides > .next {\n  left: 100%;\n}\n.am-slider-slide .am-slides > .prev {\n  left: -100%;\n}\n.am-slider-slide .am-slides > .next.left,\n.am-slider-slide .am-slides > .prev.right {\n  left: 0;\n}\n.am-slider-slide .am-slides > .active.left {\n  left: -100%;\n}\n.am-slider-slide .am-slides > .active.right {\n  left: 100%;\n}\n/**\n  * Slider Theme: Default\n  */\n.am-slider-default {\n  margin: 0 0 20px;\n  background-color: #fff;\n  border-radius: 2px;\n  -webkit-box-shadow: 0 0 2px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 2px rgba(0, 0, 0, 0.15);\n  /* Direction Nav */\n  /* Pause/Play */\n  /* Control Nav */\n}\n.am-slider-default .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-default .am-viewport {\n  max-height: 300px;\n}\n.am-slider-default .carousel li {\n  margin-right: 5px;\n}\n.am-slider-default .am-direction-nav a {\n  position: absolute;\n  top: 50%;\n  z-index: 10;\n  display: block;\n  width: 36px;\n  height: 36px;\n  margin: -18px 0 0;\n  overflow: hidden;\n  opacity: 0.45;\n  cursor: pointer;\n  color: rgba(0, 0, 0, 0.65);\n  -webkit-transition: all .3s ease;\n  transition: all .3s ease;\n}\n.am-slider-default .am-direction-nav a:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  width: 100%;\n  color: #333333;\n  content: \"\\f137\";\n  font-size: 24px!important;\n  text-align: center;\n  line-height: 36px!important;\n  height: 36px;\n}\n.am-slider-default .am-direction-nav a.am-next:before {\n  content: \"\\f138\";\n}\n.am-slider-default .am-direction-nav .am-prev {\n  left: 10px;\n}\n.am-slider-default .am-direction-nav .am-next {\n  right: 10px;\n  text-align: right;\n}\n.am-slider-default .am-direction-nav .am-disabled {\n  opacity: 0!important;\n  cursor: default;\n}\n.am-slider-default:hover .am-prev {\n  opacity: 0.7;\n  left: 10px;\n}\n.am-slider-default:hover .am-prev:hover {\n  opacity: 1;\n}\n.am-slider-default:hover .am-next {\n  opacity: 0.7;\n  right: 10px;\n}\n.am-slider-default:hover .am-next:hover {\n  opacity: 1;\n}\n.am-slider-default .am-pauseplay a {\n  display: block;\n  width: 20px;\n  height: 20px;\n  position: absolute;\n  bottom: 5px;\n  left: 10px;\n  opacity: 0.8;\n  z-index: 10;\n  overflow: hidden;\n  cursor: pointer;\n  color: #000;\n}\n.am-slider-default .am-pauseplay a::before {\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  font-size: 20px;\n  display: inline-block;\n  content: \"\\f04c\";\n}\n.am-slider-default .am-pauseplay a:hover {\n  opacity: 1;\n}\n.am-slider-default .am-pauseplay a.am-play::before {\n  content: \"\\f04b\";\n}\n.am-slider-default .am-slider-desc {\n  background-color: rgba(0, 0, 0, 0.7);\n  position: absolute;\n  bottom: 0;\n  padding: 10px;\n  width: 100%;\n  color: #fff;\n}\n.am-slider-default .am-control-nav {\n  width: 100%;\n  position: absolute;\n  bottom: -15px;\n  text-align: center;\n}\n.am-slider-default .am-control-nav li {\n  margin: 0 6px;\n  display: inline-block;\n}\n.am-slider-default .am-control-nav li a {\n  width: 8px;\n  height: 8px;\n  display: block;\n  background-color: #666;\n  background-color: rgba(0, 0, 0, 0.5);\n  line-height: 0;\n  font-size: 0;\n  cursor: pointer;\n  text-indent: -9999px;\n  border-radius: 20px;\n  -webkit-box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);\n          box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);\n}\n.am-slider-default .am-control-nav li a:hover {\n  background-color: #333;\n  background-color: rgba(0, 0, 0, 0.7);\n}\n.am-slider-default .am-control-nav li a.am-active {\n  background-color: #000;\n  background-color: #0e90d2;\n  cursor: default;\n}\n.am-slider-default .am-control-thumbs {\n  margin: 5px 0 0;\n  position: static;\n  overflow: hidden;\n}\n.am-slider-default .am-control-thumbs li {\n  width: 25%;\n  float: left;\n  margin: 0;\n}\n.am-slider-default .am-control-thumbs img {\n  width: 100%;\n  height: auto;\n  display: block;\n  opacity: .7;\n  cursor: pointer;\n}\n.am-slider-default .am-control-thumbs img:hover {\n  opacity: 1;\n}\n.am-slider-default .am-control-thumbs .am-active {\n  opacity: 1;\n  cursor: default;\n}\n.am-slider-default .am-control-thumbs i {\n  position: absolute;\n}\n/*\nTODO:\n  1. 动画应该放在 dialog 上，不再是整个 modal，涉及 JS 逻辑，需要统筹修改\n  2. modal 滚动条处理，是否需要添加一个滚动条宽度的水平 padding？\n*/\n/* ==========================================================================\n   Component: Modal Plugin\n ============================================================================ */\n.am-modal {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1110;\n  display: none;\n  opacity: 0;\n  outline: 0;\n  text-align: center;\n  -webkit-transform: scale(1.185);\n      -ms-transform: scale(1.185);\n          transform: scale(1.185);\n  -webkit-transition-property: opacity, -webkit-transform;\n  transition-property: opacity, -webkit-transform;\n  transition-property: transform, opacity;\n  transition-property: transform, opacity, -webkit-transform;\n  -webkit-backface-visibility: hidden;\n          backface-visibility: hidden;\n  -webkit-perspective: 1000px;\n          perspective: 1000px;\n}\n.am-modal:focus {\n  outline: 0;\n}\n.am-modal.am-modal-active {\n  opacity: 1;\n  -webkit-transition-duration: 300ms;\n          transition-duration: 300ms;\n  -webkit-transform: scale(1);\n      -ms-transform: scale(1);\n          transform: scale(1);\n  overflow-x: hidden;\n  overflow-y: auto;\n}\n.am-modal.am-modal-out {\n  opacity: 0;\n  z-index: 1109;\n  -webkit-transition-duration: 300ms;\n          transition-duration: 300ms;\n  -webkit-transform: scale(0.815);\n      -ms-transform: scale(0.815);\n          transform: scale(0.815);\n}\n.am-modal:before {\n  content: \"\\200B\";\n  display: inline-block;\n  height: 100%;\n  vertical-align: middle;\n}\n.am-modal-dialog {\n  position: relative;\n  display: inline-block;\n  vertical-align: middle;\n  margin-left: auto;\n  margin-right: auto;\n  width: 270px;\n  max-width: 100%;\n  border-radius: 2px;\n  background: #f8f8f8;\n  /*@media @large-up {\n    width: @modal-lg;\n    margin-left: -@modal-lg/2;\n  }*/\n}\n@media only screen and (min-width:641px) {\n  .am-modal-dialog {\n    width: 540px;\n  }\n}\n.am-modal-hd {\n  padding: 15px 10px 5px 10px;\n  font-size: 1.8rem;\n  font-weight: 500;\n}\n.am-modal-hd + .am-modal-bd {\n  padding-top: 0;\n}\n.am-modal-hd .am-close {\n  position: absolute;\n  top: 4px;\n  right: 4px;\n}\n.am-modal-bd {\n  padding: 15px 10px;\n  text-align: center;\n  border-bottom: 1px solid #dedede;\n  border-radius: 2px 2px 0 0;\n}\n.am-modal-bd + .am-modal-bd {\n  margin-top: 5px;\n}\n.am-modal-prompt-input {\n  display: block;\n  margin: 5px auto 0 auto;\n  border-radius: 2px;\n  padding: 5px;\n  line-height: 1.8rem;\n  width: 80%;\n  border: 1px solid #dedede;\n  -webkit-appearance: none;\n  -moz-appearance: none;\n  -ms-appearance: none;\n  appearance: none;\n}\n.am-modal-prompt-input:focus {\n  outline: none;\n  border-color: #d6d6d6;\n}\n.am-modal-footer {\n  height: 44px;\n  overflow: hidden;\n  display: table;\n  width: 100%;\n  border-collapse: collapse;\n}\n.am-modal-btn {\n  display: table-cell !important;\n  padding: 0 5px;\n  height: 44px;\n  -webkit-box-sizing: border-box !important;\n          box-sizing: border-box !important;\n  font-size: 1.6rem;\n  line-height: 44px;\n  text-align: center;\n  color: #0e90d2;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n  cursor: pointer;\n  border-right: 1px solid #dedede;\n}\n.am-modal-btn:first-child {\n  border-radius: 0 0 0 2px;\n}\n.am-modal-btn:last-child {\n  border-right: none;\n  border-radius: 0 0 2px 0;\n}\n.am-modal-btn:first-child:last-child {\n  border-radius: 0 0 2px 2px;\n}\n.am-modal-btn.am-modal-btn-bold {\n  font-weight: 500;\n}\n.am-modal-btn:active {\n  background: #d4d4d4;\n}\n.am-modal-btn + .am-modal-btn {\n  border-left: 1px solid #dedede;\n}\n.am-modal-no-btn .am-modal-dialog {\n  border-radius: 2px;\n  border-bottom: none;\n}\n.am-modal-no-btn .am-modal-bd {\n  border-bottom: none;\n}\n.am-modal-no-btn .am-modal-footer {\n  display: none;\n}\n.am-modal-loading .am-modal-bd {\n  border-bottom: none;\n}\n.am-modal-loading .am-icon-spin {\n  display: inline-block;\n  font-size: 2.4rem;\n}\n.am-modal-loading .am-modal-footer {\n  display: none;\n}\n.am-modal-actions {\n  position: fixed;\n  left: 0;\n  bottom: 0;\n  z-index: 1110;\n  width: 100%;\n  max-height: 100%;\n  overflow-x: hidden;\n  overflow-y: auto;\n  text-align: center;\n  border-radius: 2px;\n  -webkit-transform: translateY(100%);\n      -ms-transform: translateY(100%);\n          transform: translateY(100%);\n  -webkit-transition: -webkit-transform 300ms;\n  transition: -webkit-transform 300ms;\n  transition: transform 300ms;\n  transition: transform 300ms, -webkit-transform 300ms;\n}\n.am-modal-actions.am-modal-active {\n  -webkit-transform: translateY(0);\n      -ms-transform: translateY(0);\n          transform: translateY(0);\n}\n.am-modal-actions.am-modal-out {\n  z-index: 1109;\n  -webkit-transform: translateY(100%);\n      -ms-transform: translateY(100%);\n          transform: translateY(100%);\n}\n.am-modal-actions-group {\n  margin: 10px;\n}\n.am-modal-actions-group .am-list {\n  margin: 0;\n  border-radius: 2px;\n}\n.am-modal-actions-group .am-list > li {\n  margin-bottom: 0;\n  border-bottom: none;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n  -webkit-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.015);\n          box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.015);\n}\n.am-modal-actions-group .am-list > li > a {\n  padding: 1rem;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-modal-actions-group .am-list > li:first-child {\n  border-top: none;\n  border-top-right-radius: 2px;\n  border-top-left-radius: 2px;\n}\n.am-modal-actions-group .am-list > li:last-child {\n  border-bottom: none;\n  border-bottom-right-radius: 2px;\n  border-bottom-left-radius: 2px;\n}\n.am-modal-actions-header {\n  padding: 1rem;\n  color: #999999;\n  font-size: 1.4rem;\n}\n.am-modal-actions-danger {\n  color: #dd514c;\n}\n.am-modal-actions-danger a {\n  color: inherit;\n}\n.am-popup {\n  position: fixed;\n  left: 0;\n  top: 0;\n  width: 100%;\n  height: 100%;\n  z-index: 1110;\n  background: #fff;\n  display: none;\n  overflow: hidden;\n  -webkit-transition-property: -webkit-transform;\n  transition-property: -webkit-transform;\n  transition-property: transform;\n  transition-property: transform, -webkit-transform;\n  -webkit-transform: translateY(100%);\n      -ms-transform: translateY(100%);\n          transform: translateY(100%);\n}\n.am-popup.am-modal-active,\n.am-popup.am-modal-out {\n  -webkit-transition-duration: 300ms;\n          transition-duration: 300ms;\n}\n.am-popup.am-modal-active {\n  -webkit-transform: translateY(0);\n      -ms-transform: translateY(0);\n          transform: translateY(0);\n}\n.am-popup.am-modal-out {\n  -webkit-transform: translateY(100%);\n      -ms-transform: translateY(100%);\n          transform: translateY(100%);\n}\n@media all and (min-width: 630px) and (min-height: 630px) {\n  .am-popup {\n    width: 630px;\n    height: 630px;\n    left: 50%;\n    top: 50%;\n    margin-left: -315px;\n    margin-top: -315px;\n    -webkit-transform: translateY(1024px);\n        -ms-transform: translateY(1024px);\n            transform: translateY(1024px);\n  }\n  .am-popup.am-modal-active {\n    -webkit-transform: translateY(0);\n        -ms-transform: translateY(0);\n            transform: translateY(0);\n  }\n  .am-popup.am-modal-out {\n    -webkit-transform: translateY(1024px);\n        -ms-transform: translateY(1024px);\n            transform: translateY(1024px);\n  }\n}\n.am-popup-inner {\n  padding-top: 44px;\n  height: 100%;\n  overflow: auto;\n  -webkit-overflow-scrolling: touch;\n}\n.am-popup-hd {\n  position: absolute;\n  top: 0;\n  z-index: 1000;\n  width: 100%;\n  height: 43px;\n  border-bottom: 1px solid #dedede;\n  background-color: #fff;\n}\n.am-popup-hd .am-popup-title {\n  font-size: 1.8rem;\n  font-weight: bold;\n  line-height: 43px;\n  text-align: center;\n  margin: 0 30px;\n  color: #333333;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-popup-hd .am-close {\n  position: absolute;\n  right: 10px;\n  top: 8px;\n  cursor: pointer;\n  -webkit-transition: all 0.3s;\n  transition: all 0.3s;\n  color: #999999;\n}\n.am-popup-hd .am-close:hover {\n  -webkit-transform: rotate(360deg);\n      -ms-transform: rotate(360deg);\n          transform: rotate(360deg);\n  color: #555555;\n}\n.am-popup-bd {\n  padding: 15px;\n  background: #f8f8f8;\n  color: #555555;\n}\n/* ==========================================================================\n   Component: OffCanvas Plugin\n ============================================================================ */\n/* Off-canvas overlay and bar container */\n.am-offcanvas {\n  display: none;\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1090;\n  background: rgba(0, 0, 0, 0.15);\n}\n.am-offcanvas.am-active {\n  display: block;\n}\n/**\n * .@{ns}offcanvas-page\n *\n * Prepares the whole HTML page to slide-out\n * 1. Fix the main page and disallow scrolling\n * 2. Side-out transition\n */\n.am-offcanvas-page {\n  position: fixed;\n  /* 1 */\n  -webkit-transition: margin-left 0.3s ease-in-out;\n  transition: margin-left 0.3s ease-in-out;\n  /* 2 */\n}\n/* Sub-object .@{ns}offcanvas-bar */\n.am-offcanvas-bar {\n  position: fixed;\n  top: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1091;\n  width: 270px;\n  max-width: 100%;\n  background: #333;\n  overflow-y: auto;\n  /* scrollable */\n  -webkit-overflow-scrolling: touch;\n  /* scrollable */\n  -webkit-transition: -webkit-transform 0.3s ease-in-out;\n  transition: -webkit-transform 0.3s ease-in-out;\n  transition: transform 0.3s ease-in-out;\n  transition: transform 0.3s ease-in-out, -webkit-transform 0.3s ease-in-out;\n  -webkit-transform: translateX(-100%);\n      -ms-transform: translateX(-100%);\n          transform: translateX(-100%);\n}\n.am-offcanvas-bar:after {\n  content: \"\";\n  display: block;\n  position: absolute;\n  top: 0;\n  bottom: 0;\n  right: 0;\n  width: 1px;\n  background: #262626;\n}\n.am-offcanvas.am-active .am-offcanvas-bar.am-offcanvas-bar-active {\n  -webkit-transform: translateX(0);\n      -ms-transform: translateX(0);\n          transform: translateX(0);\n}\n/* .@{ns}offcanvas-bar-flip */\n.am-offcanvas-bar-flip {\n  left: auto;\n  right: 0;\n  -webkit-transform: translateX(100%);\n      -ms-transform: translateX(100%);\n          transform: translateX(100%);\n}\n.am-offcanvas-bar-flip:after {\n  right: auto;\n  left: 0;\n}\n.am-offcanvas-content {\n  padding: 15px;\n  color: #999;\n}\n.am-offcanvas-content a {\n  color: #ccc;\n}\n/* ==========================================================================\n   Component: Popover Plugin\n ============================================================================ */\n.am-popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  margin: 0;\n  border-radius: 2px;\n  background: #333333;\n  color: #fff;\n  border: 1px solid #333333;\n  display: none;\n  font-size: 1.6rem;\n  z-index: 1030;\n  opacity: 0;\n  -webkit-transition: opacity 300ms;\n  transition: opacity 300ms;\n}\n.am-popover.am-active {\n  display: block !important;\n  opacity: 1;\n}\n.am-popover-inner {\n  position: relative;\n  background: #333333;\n  padding: 8px;\n  z-index: 110;\n}\n.am-popover-caret {\n  position: absolute;\n  top: 0;\n  z-index: 100;\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: middle;\n  border-bottom: 8px solid #333333;\n  border-right: 8px solid transparent;\n  border-left: 8px solid transparent;\n  border-top: 0 dotted;\n  -webkit-transform: rotate(360deg);\n      -ms-transform: rotate(360deg);\n          transform: rotate(360deg);\n  overflow: hidden;\n}\n.am-popover-top .am-popover-caret {\n  top: auto;\n  bottom: -8px;\n  -webkit-transform: rotate(180deg);\n      -ms-transform: rotate(180deg);\n          transform: rotate(180deg);\n}\n.am-popover-bottom .am-popover-caret {\n  top: -8px;\n}\n.am-popover-top .am-popover-caret,\n.am-popover-bottom .am-popover-caret {\n  left: 50%;\n  margin-left: -8px;\n}\n.am-popover-left .am-popover-caret {\n  top: auto;\n  left: auto;\n  right: -12px;\n  -webkit-transform: rotate(90deg);\n      -ms-transform: rotate(90deg);\n          transform: rotate(90deg);\n}\n.am-popover-right .am-popover-caret {\n  right: auto;\n  left: -12px;\n  -webkit-transform: rotate(-90deg);\n      -ms-transform: rotate(-90deg);\n          transform: rotate(-90deg);\n}\n.am-popover-left .am-popover-caret,\n.am-popover-right .am-popover-caret {\n  top: 50%;\n  margin-top: -4px;\n}\n.am-popover-sm {\n  font-size: 1.4rem;\n}\n.am-popover-sm .am-popover-inner {\n  padding: 5px;\n}\n.am-popover-lg {\n  font-size: 1.8rem;\n}\n.am-popover-primary {\n  border-color: #0e90d2;\n}\n.am-popover-primary .am-popover-inner {\n  background: #0e90d2;\n}\n.am-popover-primary .am-popover-caret {\n  border-bottom-color: #0e90d2;\n}\n.am-popover-secondary {\n  border-color: #3bb4f2;\n}\n.am-popover-secondary .am-popover-inner {\n  background: #3bb4f2;\n}\n.am-popover-secondary .am-popover-caret {\n  border-bottom-color: #3bb4f2;\n}\n.am-popover-success {\n  border-color: #5eb95e;\n}\n.am-popover-success .am-popover-inner {\n  background: #5eb95e;\n}\n.am-popover-success .am-popover-caret {\n  border-bottom-color: #5eb95e;\n}\n.am-popover-warning {\n  border-color: #F37B1D;\n}\n.am-popover-warning .am-popover-inner {\n  background: #F37B1D;\n}\n.am-popover-warning .am-popover-caret {\n  border-bottom-color: #F37B1D;\n}\n.am-popover-danger {\n  border-color: #dd514c;\n}\n.am-popover-danger .am-popover-inner {\n  background: #dd514c;\n}\n.am-popover-danger .am-popover-caret {\n  border-bottom-color: #dd514c;\n}\n/* ==========================================================================\n   Component: Progress Plugin\n ============================================================================ */\n#nprogress {\n  /* Make clicks pass-through */\n  pointer-events: none;\n  /* Fancy blur effect */\n}\n#nprogress .nprogress-bar {\n  position: fixed;\n  top: 0;\n  left: 0;\n  z-index: 2000;\n  width: 100%;\n  height: 2px;\n  background: #5eb95e;\n}\n#nprogress .nprogress-peg {\n  display: block;\n  position: absolute;\n  right: 0;\n  width: 100px;\n  height: 100%;\n  -webkit-box-shadow: 0 0 10px #5eb95e, 0 0 5px #5eb95e;\n          box-shadow: 0 0 10px #5eb95e, 0 0 5px #5eb95e;\n  opacity: 1;\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#nprogress .nprogress-spinner {\n  position: fixed;\n  top: 15px;\n  right: 15px;\n  z-index: 2000;\n  display: block;\n}\n#nprogress .nprogress-spinner-icon {\n  width: 18px;\n  height: 18px;\n  -webkit-box-sizing: border-box;\n          box-sizing: border-box;\n  border: solid 2px transparent;\n  border-top-color: #5eb95e;\n  border-left-color: #5eb95e;\n  border-radius: 50%;\n  -webkit-animation: nprogress-spinner 400ms linear infinite;\n          animation: nprogress-spinner 400ms linear infinite;\n}\n@-webkit-keyframes nprogress-spinner {\n  0% {\n    -webkit-transform: rotate(0deg);\n            transform: rotate(0deg);\n  }\n  100% {\n    -webkit-transform: rotate(360deg);\n            transform: rotate(360deg);\n  }\n}\n@keyframes nprogress-spinner {\n  0% {\n    -webkit-transform: rotate(0deg);\n            transform: rotate(0deg);\n  }\n  100% {\n    -webkit-transform: rotate(360deg);\n            transform: rotate(360deg);\n  }\n}\n/* ==========================================================================\n   Component: Tabs Plugin\n ============================================================================ */\n.am-tabs-bd {\n  position: relative;\n  overflow: hidden;\n  border: 1px solid #ddd;\n  border-top: none;\n  z-index: 100;\n  -webkit-transition: height .3s;\n  transition: height .3s;\n}\n.am-tabs-bd:before,\n.am-tabs-bd:after {\n  content: \" \";\n  display: table;\n}\n.am-tabs-bd:after {\n  clear: both;\n}\n.am-tabs-bd .am-tab-panel {\n  position: absolute;\n  top: 0;\n  z-index: 99;\n  float: left;\n  width: 100%;\n  padding: 10px 10px 15px;\n  visibility: hidden;\n  -webkit-transition: -webkit-transform 0.3s;\n  transition: -webkit-transform 0.3s;\n  transition: transform 0.3s;\n  transition: transform 0.3s, -webkit-transform 0.3s;\n  -webkit-transform: translateX(-100%);\n      -ms-transform: translateX(-100%);\n          transform: translateX(-100%);\n}\n.am-tabs-bd .am-tab-panel * {\n  -webkit-user-drag: none;\n}\n.am-tabs-bd .am-tab-panel.am-active {\n  position: relative;\n  z-index: 100;\n  visibility: visible;\n  -webkit-transform: translateX(0);\n      -ms-transform: translateX(0);\n          transform: translateX(0);\n}\n.am-tabs-bd .am-tab-panel.am-active ~ .am-tab-panel {\n  -webkit-transform: translateX(100%);\n      -ms-transform: translateX(100%);\n          transform: translateX(100%);\n}\n.am-tabs-bd .am-tabs-bd {\n  border: none;\n}\n.am-tabs-bd-ofv {\n  overflow: visible;\n}\n.am-tabs-fade .am-tab-panel {\n  opacity: 0;\n  -webkit-transition: opacity .25s linear;\n  transition: opacity .25s linear;\n}\n.am-tabs-fade .am-tab-panel.am-in {\n  opacity: 1;\n}\n/* ==========================================================================\n   Component: Share Plugin\n ============================================================================ */\n.am-share {\n  font-size: 14px;\n}\n.am-share-title {\n  padding: 10px 0 0;\n  margin: 0 10px;\n  font-weight: normal;\n  text-align: center;\n  color: #555555;\n  background-color: #f8f8f8;\n  border-bottom: 1px solid #fff;\n  border-top-right-radius: 2px;\n  border-top-left-radius: 2px;\n}\n.am-share-title:after {\n  content: \"\";\n  display: block;\n  width: 100%;\n  height: 0;\n  margin-top: 10px;\n  border-bottom: 1px solid #dfdfdf;\n}\n.am-share-sns {\n  margin: 0 10px;\n  padding-top: 15px;\n  background-color: #f8f8f8;\n  border-bottom-right-radius: 2px;\n  border-bottom-left-radius: 2px;\n}\n.am-share-sns li {\n  margin-bottom: 15px;\n}\n.am-share-sns a {\n  display: block;\n  color: #555555;\n}\n.am-share-sns span {\n  display: block;\n}\n.am-share-sns [class*='am-icon'] {\n  background-color: #3bb4f2;\n  border-radius: 50%;\n  width: 36px;\n  height: 36px;\n  line-height: 36px;\n  color: #fff;\n  margin-bottom: 5px;\n  font-size: 18px;\n}\n.am-share-sns .am-icon-weibo {\n  background-color: #ea1328;\n}\n.am-share-sns .am-icon-qq {\n  background-color: #009cda;\n}\n.am-share-sns .am-icon-star {\n  background-color: #ffc028;\n}\n.am-share-sns .am-icon-tencent-weibo {\n  background-color: #23ccfe;\n}\n.am-share-sns .am-icon-wechat,\n.am-share-sns .am-icon-weixin {\n  background-color: #44b549;\n}\n.am-share-sns .am-icon-renren {\n  background-color: #105ba3;\n}\n.am-share-sns .am-icon-comment {\n  background-color: #5eb95e;\n}\n.am-share-footer {\n  margin: 10px;\n}\n.am-share-footer .am-btn {\n  color: #555555;\n}\n.am-share-wechat-qr {\n  font-size: 14px;\n  color: #777;\n}\n.am-share-wechat-qr .am-modal-dialog {\n  background-color: #fff;\n  border: 1px solid #dedede;\n}\n.am-share-wechat-qr .am-modal-hd {\n  padding-top: 10px;\n  text-align: left;\n  margin-bottom: 10px;\n}\n.am-share-wechat-qr .am-share-wx-qr {\n  margin-bottom: 10px;\n}\n.am-share-wechat-qr .am-share-wechat-tip {\n  text-align: left;\n}\n.am-share-wechat-qr .am-share-wechat-tip em {\n  color: #dd514c;\n  font-weight: bold;\n  font-style: normal;\n  margin-left: 3px;\n  margin-right: 3px;\n}\n/* ==========================================================================\n   Component: PureView Plugin\n ============================================================================ */\n.am-pureview {\n  position: fixed;\n  left: 0;\n  top: 0;\n  bottom: 0;\n  right: 0;\n  z-index: 1120;\n  width: 100%;\n  height: 100%;\n  background: rgba(0, 0, 0, 0.95);\n  display: none;\n  overflow: hidden;\n  -webkit-transition: -webkit-transform .3s;\n  transition: -webkit-transform .3s;\n  transition: transform .3s;\n  transition: transform .3s, -webkit-transform .3s;\n  -webkit-transform: translate(0, 100%);\n      -ms-transform: translate(0, 100%);\n          transform: translate(0, 100%);\n}\n.am-pureview.am-active {\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n}\n.am-pureview ul,\n.am-pureview ol {\n  list-style: none;\n  padding: 0;\n  margin: 0;\n  width: 100%;\n}\n.am-pureview-slider {\n  overflow: hidden;\n  height: 100%;\n}\n.am-pureview-slider li {\n  position: absolute;\n  width: 100%;\n  height: 100%;\n  top: 0;\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -ms-flexbox;\n  display: flex;\n  -webkit-box-pack: center;\n  -webkit-justify-content: center;\n      -ms-flex-pack: center;\n          justify-content: center;\n  -webkit-box-align: center;\n  -webkit-align-items: center;\n      -ms-flex-align: center;\n          align-items: center;\n  vertical-align: middle;\n  -webkit-transition: all .3s linear;\n  transition: all .3s linear;\n  z-index: 100;\n  visibility: hidden;\n}\n.am-pureview-slider li.am-pureview-slide-prev {\n  -webkit-transform: translate(-100%, 0);\n      -ms-transform: translate(-100%, 0);\n          transform: translate(-100%, 0);\n  z-index: 109;\n}\n.am-pureview-slider li.am-pureview-slide-next {\n  -webkit-transform: translate(100%, 0);\n      -ms-transform: translate(100%, 0);\n          transform: translate(100%, 0);\n  z-index: 109;\n}\n.am-pureview-slider li.am-active {\n  position: relative;\n  z-index: 110;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  visibility: visible;\n}\n.am-pureview-slider .pinch-zoom-container {\n  width: 100%;\n  z-index: 1121;\n}\n.am-pureview-slider .am-pinch-zoom {\n  position: relative;\n  width: 100%;\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -ms-flexbox;\n  display: flex;\n  -webkit-box-pack: center;\n  -webkit-justify-content: center;\n      -ms-flex-pack: center;\n          justify-content: center;\n  -webkit-box-align: center;\n  -webkit-align-items: center;\n      -ms-flex-align: center;\n          align-items: center;\n}\n.am-pureview-slider .am-pinch-zoom:after {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f110\";\n  -webkit-animation: icon-spin 2s infinite linear;\n          animation: icon-spin 2s infinite linear;\n  font-size: 24px;\n  line-height: 24px;\n  color: #eee;\n  position: absolute;\n  top: 50%;\n  left: 50%;\n  margin-left: -12px;\n  margin-top: -12px;\n  z-index: 1;\n}\n.am-pureview-slider .am-pinch-zoom.am-pureview-loaded:after {\n  display: none;\n}\n.am-pureview-slider img {\n  position: relative;\n  display: block;\n  max-width: 100%;\n  max-height: 100%;\n  opacity: 0;\n  z-index: 200;\n  -webkit-user-drag: none;\n  -webkit-transition: opacity 0.2s ease-in;\n  transition: opacity 0.2s ease-in;\n}\n.am-pureview-slider img.am-img-loaded {\n  opacity: 1;\n}\n.am-pureview-direction {\n  position: absolute;\n  top: 50%;\n  width: 100%;\n  margin-top: -18px !important;\n  z-index: 1122;\n}\n.am-touch .am-pureview-direction,\n.am-pureview-only .am-pureview-direction {\n  display: none;\n}\n.am-pureview-direction li {\n  position: absolute;\n  width: 36px;\n  height: 36px;\n}\n.am-pureview-direction a {\n  display: block;\n  height: 36px;\n  border: none;\n  color: #ccc;\n  opacity: 0.5;\n  cursor: pointer;\n  text-align: center;\n  z-index: 1125;\n}\n.am-pureview-direction a:before {\n  content: \"\\f137\";\n  line-height: 36px;\n  font-size: 24px;\n}\n.am-pureview-direction a:hover {\n  opacity: 1;\n}\n.am-pureview-direction .am-pureview-prev {\n  left: 15px;\n}\n.am-pureview-direction .am-pureview-next {\n  right: 15px;\n}\n.am-pureview-direction .am-pureview-next a:before {\n  content: \"\\f138\";\n}\n.am-pureview-bar {\n  position: absolute;\n  bottom: 0;\n  height: 45px;\n  width: 100%;\n  background-color: rgba(0, 0, 0, 0.35);\n  color: #eeeeee;\n  line-height: 45px;\n  padding: 0 10px;\n  font-size: 14px;\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -ms-flexbox;\n  display: flex;\n}\n.am-pureview-bar .am-pureview-title {\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n  margin-left: 6px;\n  -webkit-box-flex: 1;\n  -webkit-flex: 1;\n      -ms-flex: 1;\n          flex: 1;\n}\n.am-pureview-bar .am-pureview-total {\n  font-size: 10px;\n  line-height: 48px;\n}\n.am-pureview-actions {\n  position: absolute;\n  z-index: 1130;\n  left: 0;\n  right: 0;\n  top: 0;\n  height: 45px;\n  background-color: rgba(0, 0, 0, 0.35);\n}\n.am-pureview-actions a {\n  position: absolute;\n  left: 10px;\n  color: #ccc;\n  display: block;\n  width: 45px;\n  line-height: 45px;\n  text-align: left;\n  font-size: 16px;\n}\n.am-pureview-actions a:hover {\n  color: #fff;\n}\n.am-pureview-actions [data-am-toggle=\"share\"] {\n  left: auto;\n  right: 10px;\n}\n.am-pureview-bar,\n.am-pureview-actions {\n  opacity: 0;\n  -webkit-transition: all .15s;\n  transition: all .15s;\n  z-index: 1130;\n}\n.am-pureview-bar-active .am-pureview-bar,\n.am-pureview-bar-active .am-pureview-actions {\n  opacity: 1;\n}\n.am-pureview-nav {\n  position: absolute;\n  bottom: 15px;\n  left: 0;\n  right: 0;\n  text-align: center;\n  z-index: 1131;\n}\n.am-pureview-bar-active .am-pureview-nav {\n  display: none;\n}\n.am-pureview-nav li {\n  display: inline-block;\n  background: #ccc;\n  background: rgba(255, 255, 255, 0.5);\n  width: 8px;\n  height: 8px;\n  margin: 0 3px;\n  border-radius: 50%;\n  text-indent: -9999px;\n  overflow: hidden;\n  cursor: pointer;\n}\n.am-pureview-nav .am-active {\n  background: #fff;\n  background: rgba(255, 255, 255, 0.9);\n}\n[data-am-pureview] img {\n  cursor: pointer;\n}\n.am-pureview-active {\n  overflow: hidden;\n}\n.ath-viewport * {\n  -webkit-box-sizing: border-box;\n          box-sizing: border-box;\n}\n.ath-viewport {\n  position: relative;\n  z-index: 2147483641;\n  pointer-events: none;\n  -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          user-select: none;\n  -webkit-text-size-adjust: none;\n      -ms-text-size-adjust: none;\n          text-size-adjust: none;\n}\n.ath-modal {\n  pointer-events: auto !important;\n  background: rgba(0, 0, 0, 0.6);\n}\n.ath-mandatory {\n  background: #000;\n}\n.ath-container {\n  pointer-events: auto !important;\n  position: absolute;\n  z-index: 2147483641;\n  padding: 0.7em 0.6em;\n  width: 18em;\n  background: #eee;\n  -webkit-background-size: 100% auto;\n          background-size: 100% auto;\n  -webkit-box-shadow: 0 0.2em 0 #d1d1d1;\n          box-shadow: 0 0.2em 0 #d1d1d1;\n  font-family: sans-serif;\n  font-size: 15px;\n  line-height: 1.5em;\n  text-align: center;\n}\n.ath-container small {\n  font-size: 0.8em;\n  line-height: 1.3em;\n  display: block;\n  margin-top: 0.5em;\n}\n.ath-ios.ath-phone {\n  bottom: 1.8em;\n  left: 50%;\n  margin-left: -9em;\n}\n.ath-ios6.ath-tablet {\n  left: 5em;\n  top: 1.8em;\n}\n.ath-ios7.ath-tablet {\n  left: 0.7em;\n  top: 1.8em;\n}\n.ath-ios8.ath-tablet {\n  right: 0.4em;\n  top: 1.8em;\n}\n.ath-android {\n  bottom: 1.8em;\n  left: 50%;\n  margin-left: -9em;\n}\n/* close icon */\n.ath-container:before {\n  content: '';\n  position: relative;\n  display: block;\n  float: right;\n  margin: -0.7em -0.6em 0 0.5em;\n  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIQAAACECAMAAABmmnOVAAAAdVBMVEUAAAA5OTkzMzM7Ozs3NzdBQUFAQEA/Pz8+Pj5BQUFAQEA/Pz8+Pj5BQUFAQEA/Pz9BQUE+Pj4/Pz8/Pz8+Pj4/Pz8/Pz8/Pz8+Pj4/Pz8+Pj4/Pz8/Pz8/Pz8/Pz8/Pz8+Pj4/Pz8/Pz8/Pz8/Pz9AQEA/Pz+fdCaPAAAAJnRSTlMACQoNDjM4OTo7PEFCQ0RFS6ytsbS1tru8vcTFxu7x8vX19vf4+C5yomAAAAJESURBVHgBvdzLTsJAGEfxr4C2KBcVkQsIDsK8/yPaqIsPzVlyzrKrX/5p0kkXEz81L23otc9NpIbbWia2YVLqdnhlqFlhGWpSDHe1aopsSIpRb8gK0dC3G30b9rVmhWZIimTICsvQtx/FsuYOrWHoDjX3Gu31gzJxdki934WrAIOsAIOsAIOiAMPhPsJTgKGN0BVsYIVsYIVpYIVpYIVpYIVpYIVpYIVpYIVpYIVlAIVgEBRs8BRs8BRs8BRs8BRs8BRs8BRs8BRTNmgKNngKNngKNngKNngKNhiKGxgiOlZoBlaYBlaYBlaYBlaYBlaYBlaYBlaYBlZIBlBMfQMrVAMr2KAqBENSHFHhGEABhi5CV6gGUKgGUKgGUKgGUFwuqgEUvoEVsoEVpoEUpgEUggF+gKTKY+h1fxSlC7/Z+RrxOQ3fcEoAPPHZBlaYBlaYBlaYBlZYBlYIhvLBCstw7PgM7hkiWOEZWGEaWGEaWGEaIsakEAysmHkGVpxmvoEVqoEVpoEVpoEVpoEVpoEVpoEVkoEVgkFQsEFSsEFQsGEcoSvY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnmbNAUT2c2WAo2eAo2eAo2eAo2eAo2eArNEPFACjZ4CjZ4CjZ4CjaIird/rBvFH6llNCvewdli1URWCIakSIZesUaDoFg36dKFWk9zCZDei3TtwmCj7pC22AwikiIZPEU29IpFNliKxa/hC9DFITjQPYhcAAAAAElFTkSuQmCC);\n  background-color: rgba(255, 255, 255, 0.8);\n  -webkit-background-size: 50% 50%;\n          background-size: 50%;\n  background-repeat: no-repeat;\n  background-position: 50%;\n  width: 2.7em;\n  height: 2.7em;\n  text-align: center;\n  overflow: hidden;\n  color: #a33;\n  z-index: 2147483642;\n}\n.ath-container.ath-icon:before {\n  position: absolute;\n  top: 0;\n  right: 0;\n  margin: 0;\n  float: none;\n}\n.ath-mandatory .ath-container:before {\n  display: none;\n}\n.ath-container.ath-android:before {\n  float: left;\n  margin: -0.7em 0.5em 0 -0.6em;\n}\n.ath-container.ath-android.ath-icon:before {\n  position: absolute;\n  right: auto;\n  left: 0;\n  margin: 0;\n  float: none;\n}\n/* applied only if the application icon is shown */\n.ath-action-icon {\n  display: inline-block;\n  vertical-align: middle;\n  background-position: 50%;\n  background-repeat: no-repeat;\n  text-indent: -9999em;\n  overflow: hidden;\n}\n.ath-ios7 .ath-action-icon,\n.ath-ios8 .ath-action-icon {\n  width: 1.6em;\n  height: 1.6em;\n  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHgAAACtCAYAAAB7l7tOAAAF6UlEQVR4AezZWWxUZRiH8VcQEdxZEFFiUZBFUCIa1ABBDARDcCciYGKMqTEGww3SOcNSAwQTjOBiiIpEhRjAhRgXRC8MFxojEhAFZUGttVhaoSxlaW3n8W3yXZxm6vTrOMM5Q98n+V9MMu1pvl++uZhKuypghu49KaaTWGdZSYoVN6VD95nMpLNYZ9XNbdQR2od2k88O3Gm6Bh0t7H0p5Vwp2Ax3ajpu2tYbciFWwkTFO63DY6+JcI4USFaSyYpWp8N7SVZJKR3EinkBk9JxvZFXxhnZSjBaoWp1ZL0ES8WKYXMZp0AndORgy8WKFe5Yf1zvvSBWDEpys2LU6MjD5kmEWQlGKsJRHXlcqUSQVcItEnDEA6gAb7LhjvD9WO6yIEfICQI5A1nzGCYB1T4og5bBiFcyv2f6ujYhl4iVxwKG6qp8MK55HsqPwK0rMr9v/yEo3uCPrJstVh5KMER30Aeh31Ioq0FrHfjXw9CYghnrvYFTuqfEymFzGSwBlT4ARYr7u+K6GLmCVGvAGg2NMG0d/sgJnpScZLjXSkC5z8H3eQ72/k24Q8NfzvwFyK4qtuJSZKaubRPyE/K/Mtx+EvCHL+7uasId1t10w0scz/RzSzYzAfgKV30D3LPaG7lRkR8RK4tKKJKAMp+D7r0EfmmOe0x3m2itAc/ZxBjgAt1mXHWKPPkdb+QGSTJdrDaU5EoJ2OtzwD0WwY7KNNzbRfMFFg24WPdtGHnS221Cflgsj56hjwTs8TnY7oq7/QDhjutGicsb2AVcovsO18l6uPPNNiE/JFaGAq7Q7fY50G4LYVtz3FrdaNGyBXbIl+q24DqhyHes9EaulwR3SwtZs+ktAT/7HORliru1gnCndONFyx44Dfn7MPLYN7yR6yTJZAllJeguAT/4HOBFz8I3ZWm4E0TLFbBD7qn7EVdtHYx53R9ZN0ksrZRuErDN5+AuLIWvm+Oe1k0ULdfADrmX7idcR0/DyBXeyCdlLuMMOGCBz4F1ng+f7yFcve5e0fIFHELeiav6BAx70Rt5p0yhY3u/wR0kyarW/uX35b403PtFyzewQ75ctwtXzSkY8WqruHslSV8RscrL6TJ1bcvfWJ0/HzbtIdw/ugdFyzdwOOAq3T6fmzxwGQ3vbmO8iFioIWqYSsHMj9M/ljfuTsOdItoZBXYBfXX7cVXVwvXLm/8+fU3lcdCqdEMNGBbgUmRmfQISQKd5sGEn4VK6YtEiAXYBA3QVuA4q8hCHrDcafR1ul65jewfuovsCl7vJrNlOuEbdo6JFCuwCrtb9hqusBu56Cw4cI1y1briIWEBn3Ue0XKPuMdGiBg4H9NdV0HJ/6QZLOEPmPN0GmpfSPS5arIBdwHUtIFfoBsl/ZsgfhHCfFi2WwC5goO4AmvanbqBkzJA76tboZokWa2AXMEi3RTdAvDLkDqJFAhzB32xFD2wZsGXA0WfAlgFbBmwZsGXAlgFbBpzk04JaKb0iA9ZnF9x5SQAFtRKKIgPWZxfaeRmwAZ/BGbAB37eaG6MCbnq2Aed5czYyKirgpmcbsAHHZAZswN0Wwo7KeG1fFf2jAm56dtzOQ42yB+65mDhWFBUwUETMUiMDNmADbp/APRaTAh6I2bpGCNw1bufRZJQ1cPdF/NueHZsgDEBBGLbMGoIu4AZu5gLOZeEaYmEXeznF3jRPyEv4frgJvvJe3qTefY0AAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwb8rwADBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgz4/sz1Nia/9hizA7zgklwy3RYwYMBzBRjw4bPjxAbAAizAAtwgwAIswAIswAIMGDBgARZgARZgAS4FWIAFWIAFWIABAwYswAIswAIswIUAC7AAC7AACzBgwIAFWIAFWIAFuBBgARZgARZgAQYMGPApQ99ZCdgWtzqwATbABtgAG2DbnxNb7zbRimsMLMACrDf2wMWI/WasfQAAAABJRU5ErkJggg==);\n  margin-top: -0.3em;\n  -webkit-background-size: auto 100%;\n          background-size: auto 100%;\n}\n.ath-ios6 .ath-action-icon {\n  width: 1.8em;\n  height: 1.8em;\n  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJAAAAB0CAQAAADAmnOnAAAAAnNCSVQICFXsRgQAAAAJcEhZcwAAWwEAAFsBAXkZiFwAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAF4klEQVR4Ae3a/a+XdR3H8ec5HM45HDmKICoVohkZsxESRRCzcZM/2JKkdGR5MrSkleA0Pd00O4u5IVuNM2yYc6XSzCExU4oUNRPCJFdMUAhsYZpUGhscOHA4N8/WZzsL6HBxvofvdV3fa3yer//gsV3vH659KHzncBsJxUYhDzOEhCKQbORs+ip2wzgM+wvj+P9i35qAGLaHGcQSgKSTrxBLABJppZpYApCspoFYApBsZjSxBCD5OxOJJQBJG1cQSwCSLpqJJQCJ3MvgCGTinuSMCJS8LZwfgZL3FtMiUPIOcU0ESl4PLRHoRPsJtREoeRsYGYGS9yrvo6RmpbLaigWSfzOdErLs6+bLUMFA0sF1+QF1cz1UNlBYK9V5AHXyWSgEkKyiIWOgGh829Ki1lLcaxjCVK7mJRSxjBY+zgRf/u9pXcMB7jhEZAg32EUP3O6hMKOP5Iq2sZQeHMZXt5KKMgOpcY+iHVnFyjeQKlrCBdsxge5ieAVC9vzLUelI8H+A7bKIHM10H81IGGuKvDf1ggDxVTKOV1zG3/Yia1ICG+ltD32MgNTKfP2HuW0VDKkCNrjfUTOm9i6XswwrZJkaVHeh0f2fodkrtfO6jAytqrzG+rEDDfVG1x1sprZEs5RBW4PZxeT+Bbrf5hPu9arfzKaU6WjiAFbseWvoF1GW/6vYGSmkyW7Dit4xB5QHq9Br6Xx2t9GAhtp6zkoHsfNp1J9wX6H+jeR4LtJc4LxGopZZyNpN/YcG2mw9nBTSPLizgOmjKAujGgvJID3ekD7QYi7nGzkvmQtpA38Vi7iJf0TedlC7QTVjMfcY2QyvSBPpUMW/PIBfbo9pls1XpAX2EdizeznStob3OJpQO0DB2YfE21q2GtnghpAm0Gou3T9tm6BGHQppA12HRVt17eboNlydNoLHsx2JtmL801OYcQmkC/QKLtQt9ydBW3wNpA30ci7Ur3WdolUMhbaBqNhf/8qQJ9Hkszs5wjaH9XkUobaAqtmFRdoGbDb3sWMgG6DIs5852knO82RaXer+P+qyb3eWeo7ZNBrRZvm1otY2QFdBjeHIb6hTne49Put12+9ObMoDdYmfy5UkF6AK6cCCr9aM2u9IddptcOYCG+FNDB5xLKCugO7G01TndFp/xgAntdYvrfdwVLnORt3q9Vx25F27DUjbGPxr6qxMgW6Cd2N+d6wLXedA+6nKbK73Lr/pJxzusvE/wZrvX0FOOgGyBxmF/dprXutYOj6nNdS6xyYnWp/dGcaGdhr5vDWQN9E1MXrUzfcA2j2qPj/l1J1uT9iPOeh8w1O7nCGUN9HzyGZ7ndo9qp0ucanU2r1xH+wdDu5wIeQDVVx0+/kd1i697RNv8thdn+Qz4Uv9p6DeOhHyApmBfq3OBu+3Nfd7nVELZAX3Nw4ZarYG8gG7GY1dlk6/Zm3/2Rk8jlB1QvT82dNAmQjkBVf8Mj957fdrefM7ZVhPKEuidvmDob06CXIGGbsX/bZDf8KAhfdbJhLIGmuZuQ084HHIGatiLvRvrRkP6qldbBXkAzbfD0N0OhryBGqrEMOd50FC7d1hPKGugBh8ydMh5hPIGGouI1d5lj6F1vptQ9kDvcKOhN5wMlQH0QcRGnzC03yZCeQDN9G1D6xwBFQI07FI8x02GdjgB8gJqttPQcmuhYoAumzvG7YZWejrkA1TrPYYO+SVCFQO0aM4bqj0uJJQH0LluSP7PkyeQU9QOmyAvoBm+Zegpz4LKA/qYB/wE5AXUe3m81zqoRKAPOYWcuvP9dxvqcD6h7IAKkaNU3eUlHLcI9EzS5YlAi62h/zUy89QCqqKUmvgHywsJlEHnsQYxAvXVIJo5gIhnPhiBju1iNmLvLn85Ah1ZPYs5jBGo72awEzEC9dVwHqQHI9DxWoAYgSLQQKteGIESu/qhCJTYtT+PQBEoAkWgCBSBkotAEehUWwSKQBEoAkWg/BeBIlAEikARKAJFoFmealu4gVLy1Gt5dkARKAL9BzujPSurTmu/AAAAAElFTkSuQmCC);\n  margin-bottom: 0.4em;\n  -webkit-background-size: 100% auto;\n          background-size: 100% auto;\n}\n.ath-android .ath-action-icon {\n  width: 1.4em;\n  height: 1.4em;\n  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAMAAABg3Am1AAAANlBMVEVmZmb///9mZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZW6fJrAAAAEXRSTlMAAAYHG21ub8fLz9DR8/T4+RrZ9owAAAB3SURBVHja7dNLDoAgDATQWv4gKve/rEajJOJiWLgg6WzpSyB0aHqHiNj6nL1lovb4C+hYzkSNAT7mryQFAVOeGAj4CjwEtgrWXpD/uZKtwEJApXt+Vn0flzRhgNiFZQkOXY0aADQZCOCPlsZJ46Rx0jhp3IiN2wGDHhxtldrlwQAAAABJRU5ErkJggg==);\n  -webkit-background-size: 100% auto;\n          background-size: 100% auto;\n}\n.ath-container p {\n  margin: 0;\n  padding: 0;\n  position: relative;\n  z-index: 2147483642;\n  text-shadow: 0 0.1em 0 #fff;\n  font-size: 1.1em;\n}\n.ath-ios.ath-phone:after {\n  content: '';\n  background: #eee;\n  position: absolute;\n  width: 2em;\n  height: 2em;\n  bottom: -0.9em;\n  left: 50%;\n  margin-left: -1em;\n  -webkit-transform: scaleX(0.9) rotate(45deg);\n  -ms-transform: scaleX(0.9) rotate(45deg);\n      transform: scaleX(0.9) rotate(45deg);\n  -webkit-box-shadow: 0.2em 0.2em 0 #d1d1d1;\n          box-shadow: 0.2em 0.2em 0 #d1d1d1;\n}\n.ath-ios.ath-tablet:after {\n  content: '';\n  background: #eee;\n  position: absolute;\n  width: 2em;\n  height: 2em;\n  top: -0.9em;\n  left: 50%;\n  margin-left: -1em;\n  -webkit-transform: scaleX(0.9) rotate(45deg);\n  -ms-transform: scaleX(0.9) rotate(45deg);\n      transform: scaleX(0.9) rotate(45deg);\n  z-index: 2147483641;\n}\n.ath-application-icon {\n  position: relative;\n  padding: 0;\n  border: 0;\n  margin: 0 auto 0.2em auto;\n  height: 6em;\n  width: 6em;\n  z-index: 2147483642;\n}\n.ath-container.ath-ios .ath-application-icon {\n  border-radius: 1em;\n  -webkit-box-shadow: 0 0.2em 0.4em rgba(0, 0, 0, 0.3), inset 0 0.07em 0 rgba(255, 255, 255, 0.5);\n          box-shadow: 0 0.2em 0.4em rgba(0, 0, 0, 0.3), inset 0 0.07em 0 rgba(255, 255, 255, 0.5);\n  margin: 0 auto 0.4em auto;\n}\n@media only screen and (orientation: landscape) {\n  .ath-container.ath-phone {\n    width: 24em;\n  }\n  .ath-android.ath-phone {\n    margin-left: -12em;\n  }\n  .ath-ios.ath-phone {\n    margin-left: -12em;\n  }\n  .ath-ios6:after {\n    left: 39%;\n  }\n  .ath-ios8.ath-phone {\n    left: auto;\n    bottom: auto;\n    right: 0.4em;\n    top: 1.8em;\n  }\n  .ath-ios8.ath-phone:after {\n    bottom: auto;\n    top: -0.9em;\n    left: 68%;\n    z-index: 2147483641;\n    -webkit-box-shadow: none;\n            box-shadow: none;\n  }\n}\n/* ==========================================================================\n   Component: uCheck Plugin\n ============================================================================ */\n.am-checkbox,\n.am-radio,\n.am-checkbox-inline,\n.am-radio-inline {\n  padding-left: 22px;\n  position: relative;\n  -webkit-transition: color .25s linear;\n  transition: color .25s linear;\n  font-size: 14px;\n  line-height: 1.5;\n}\nlabel.am-checkbox,\nlabel.am-radio {\n  font-weight: normal;\n}\n.am-ucheck-icons {\n  color: #999999;\n  display: block;\n  height: 20px;\n  top: 0;\n  left: 0;\n  position: absolute;\n  width: 20px;\n  text-align: center;\n  line-height: 21px;\n  font-size: 18px;\n  cursor: pointer;\n}\n.am-checkbox .am-icon-checked,\n.am-radio .am-icon-checked,\n.am-checkbox-inline .am-icon-checked,\n.am-radio-inline .am-icon-checked,\n.am-checkbox .am-icon-unchecked,\n.am-radio .am-icon-unchecked,\n.am-checkbox-inline .am-icon-unchecked,\n.am-radio-inline .am-icon-unchecked {\n  position: absolute;\n  left: 0;\n  top: 0;\n  display: inline-table;\n  margin: 0;\n  background-color: transparent;\n  -webkit-transition: color .25s linear;\n  transition: color .25s linear;\n}\n.am-checkbox .am-icon-checked:before,\n.am-radio .am-icon-checked:before,\n.am-checkbox-inline .am-icon-checked:before,\n.am-radio-inline .am-icon-checked:before,\n.am-checkbox .am-icon-unchecked:before,\n.am-radio .am-icon-unchecked:before,\n.am-checkbox-inline .am-icon-unchecked:before,\n.am-radio-inline .am-icon-unchecked:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n}\n.am-checkbox .am-icon-checked,\n.am-radio .am-icon-checked,\n.am-checkbox-inline .am-icon-checked,\n.am-radio-inline .am-icon-checked {\n  opacity: 0;\n}\n.am-checkbox .am-icon-checked:before,\n.am-checkbox-inline .am-icon-checked:before {\n  content: \"\\f046\";\n}\n.am-checkbox .am-icon-unchecked:before,\n.am-checkbox-inline .am-icon-unchecked:before {\n  content: \"\\f096\";\n}\n.am-radio .am-icon-checked:before,\n.am-radio-inline .am-icon-checked:before {\n  content: \"\\f192\";\n}\n.am-radio .am-icon-unchecked:before,\n.am-radio-inline .am-icon-unchecked:before {\n  content: \"\\f10c\";\n}\n.am-ucheck-checkbox,\n.am-ucheck-radio {\n  position: absolute;\n  left: 0;\n  top: 0;\n  margin: 0;\n  padding: 0;\n  width: 20px;\n  height: 20px;\n  opacity: 0;\n  outline: none !important;\n}\n.am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons {\n  color: #0e90d2;\n}\n.am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-ucheck-radio:checked + .am-ucheck-icons {\n  color: #0e90d2;\n}\n.am-ucheck-checkbox:checked + .am-ucheck-icons .am-icon-unchecked,\n.am-ucheck-radio:checked + .am-ucheck-icons .am-icon-unchecked {\n  opacity: 0;\n}\n.am-ucheck-checkbox:checked + .am-ucheck-icons .am-icon-checked,\n.am-ucheck-radio:checked + .am-ucheck-icons .am-icon-checked {\n  opacity: 1;\n}\n.am-ucheck-checkbox:disabled + .am-ucheck-icons,\n.am-ucheck-radio:disabled + .am-ucheck-icons {\n  cursor: default;\n  color: #d8d8d8;\n}\n.am-ucheck-checkbox:disabled:checked + .am-ucheck-icons .am-icon-unchecked,\n.am-ucheck-radio:disabled:checked + .am-ucheck-icons .am-icon-unchecked {\n  opacity: 0;\n}\n.am-ucheck-checkbox:disabled:checked + .am-ucheck-icons .am-icon-checked,\n.am-ucheck-radio:disabled:checked + .am-ucheck-icons .am-icon-checked {\n  opacity: 1;\n  color: #d8d8d8;\n}\n.am-checkbox.am-secondary .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio.am-secondary .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox-inline.am-secondary .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio-inline.am-secondary .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox.am-secondary .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio.am-secondary .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox-inline.am-secondary .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio-inline.am-secondary .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons {\n  color: #3bb4f2;\n}\n.am-checkbox.am-secondary .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-radio.am-secondary .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-checkbox-inline.am-secondary .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-radio-inline.am-secondary .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-checkbox.am-secondary .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-radio.am-secondary .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-checkbox-inline.am-secondary .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-radio-inline.am-secondary .am-ucheck-radio:checked + .am-ucheck-icons {\n  color: #3bb4f2;\n}\n.am-checkbox.am-success .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio.am-success .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox-inline.am-success .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio-inline.am-success .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox.am-success .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio.am-success .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox-inline.am-success .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio-inline.am-success .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons {\n  color: #5eb95e;\n}\n.am-checkbox.am-success .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-radio.am-success .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-checkbox-inline.am-success .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-radio-inline.am-success .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-checkbox.am-success .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-radio.am-success .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-checkbox-inline.am-success .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-radio-inline.am-success .am-ucheck-radio:checked + .am-ucheck-icons {\n  color: #5eb95e;\n}\n.am-checkbox.am-warning .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio.am-warning .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox-inline.am-warning .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio-inline.am-warning .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox.am-warning .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio.am-warning .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox-inline.am-warning .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio-inline.am-warning .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons {\n  color: #F37B1D;\n}\n.am-checkbox.am-warning .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-radio.am-warning .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-checkbox-inline.am-warning .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-radio-inline.am-warning .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-checkbox.am-warning .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-radio.am-warning .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-checkbox-inline.am-warning .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-radio-inline.am-warning .am-ucheck-radio:checked + .am-ucheck-icons {\n  color: #F37B1D;\n}\n.am-checkbox.am-danger .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio.am-danger .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox-inline.am-danger .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio-inline.am-danger .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox.am-danger .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio.am-danger .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox-inline.am-danger .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio-inline.am-danger .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons {\n  color: #dd514c;\n}\n.am-checkbox.am-danger .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-radio.am-danger .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-checkbox-inline.am-danger .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-radio-inline.am-danger .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-checkbox.am-danger .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-radio.am-danger .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-checkbox-inline.am-danger .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-radio-inline.am-danger .am-ucheck-radio:checked + .am-ucheck-icons {\n  color: #dd514c;\n}\n.am-field-error + .am-ucheck-icons {\n  color: #dd514c;\n}\n.am-field-valid + .am-ucheck-icons {\n  color: #5eb95e;\n}\n/*\n// Group Addon\n.@{ns}input-group-label {\n  .@{ns}radio,\n  .@{ns}checkbox {\n    margin: -2px 0;\n    padding-left: 15px;\n  }\n}\n\n// Form inline style\n.@{ns}form-inline .@{ns}checkbox,\n.@{ns}form-inline .@{ns}radio {\n  padding-left: 24px;\n}\n*/\n/* ==========================================================================\n   Component: Selected Plugin\n ============================================================================ */\n.am-selected {\n  width: 200px;\n}\n.am-selected-btn {\n  width: 100%;\n  padding-left: 10px;\n  text-align: right;\n}\n.am-selected-btn.am-btn-default {\n  background: none;\n}\n.am-invalid .am-selected-btn {\n  border-color: #dd514c;\n}\n.am-selected-header {\n  height: 45px;\n  background-color: #f2f2f2;\n  border-bottom: 1px solid #ddd;\n  display: none;\n}\n.am-selected-status {\n  text-align: left;\n  width: 100%;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-selected-content {\n  padding: 10px 0;\n}\n.am-selected-search {\n  padding: 0 10px 10px;\n}\n.am-selected-search .am-form-field {\n  padding: .5em;\n}\n.am-selected-list {\n  margin: 0;\n  padding: 0;\n  list-style: none;\n  font-size: 1.5rem;\n}\n.am-selected-list li {\n  position: relative;\n  cursor: pointer;\n  padding: 5px 10px;\n  -webkit-transition: background-color 0.15s;\n  transition: background-color 0.15s;\n}\n.am-selected-list li:hover {\n  background-color: #f8f8f8;\n}\n.am-selected-list li:hover .am-icon-check {\n  opacity: .6;\n}\n.am-selected-list li.am-checked .am-icon-check {\n  opacity: 1;\n  color: #0e90d2;\n}\n.am-selected-list li.am-disabled {\n  opacity: .5;\n  pointer-events: none;\n  cursor: not-allowed;\n}\n.am-selected-list .am-selected-list-header {\n  margin-top: 8px;\n  font-size: 1.3rem;\n  color: #999999;\n  border-bottom: 1px solid #e5e5e5;\n  cursor: default;\n}\n.am-selected-list .am-selected-list-header:hover {\n  background: none;\n}\n.am-selected-list .am-selected-list-header:first-child {\n  margin-top: 0;\n}\n.am-selected-list .am-selected-text {\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n  margin-right: 30px;\n}\n.am-selected-list .am-icon-check {\n  position: absolute;\n  right: 8px;\n  top: 5px;\n  color: #999999;\n  opacity: 0;\n  -webkit-transition: opacity .15s;\n  transition: opacity .15s;\n}\n.am-selected-hint {\n  line-height: 1.2;\n  color: #dd514c;\n}\n.am-selected-hint:not(:empty) {\n  margin-top: 10px;\n  border-top: 1px solid #e5e5e5;\n  padding: 10px 10px 0;\n}\n.am-selected-placeholder {\n  opacity: .65;\n}\n/* ==========================================================================\n   Component: JS Plugins helpers\n ============================================================================ */\n.am-fade {\n  opacity: 0;\n  -webkit-transition: opacity .2s linear;\n  transition: opacity .2s linear;\n}\n.am-fade.am-in {\n  opacity: 1;\n}\n.am-collapse {\n  display: none;\n}\n.am-collapse.am-in {\n  display: block;\n}\ntr.am-collapse.am-in {\n  display: table-row;\n}\ntbody.am-collapse.am-in {\n  display: table-row-group;\n}\n.am-collapsing {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height .3s ease;\n  transition: height .3s ease;\n}\n.am-sticky {\n  position: fixed !important;\n  z-index: 1010;\n  -webkit-transform-origin: 0 0;\n      -ms-transform-origin: 0 0;\n          transform-origin: 0 0;\n}\n[data-am-sticky][class*=\"am-animation-\"] {\n  -webkit-animation-duration: .2s;\n          animation-duration: .2s;\n}\n.am-dimmer-active {\n  overflow: hidden;\n}\n.am-dimmer {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  display: none;\n  width: 100%;\n  height: 100%;\n  background-color: rgba(0, 0, 0, 0.6);\n  z-index: 1100;\n  opacity: 0;\n}\n.am-dimmer.am-active {\n  opacity: 1;\n}\n[data-am-collapse] {\n  cursor: pointer;\n}\n.am-datepicker {\n  top: 0;\n  left: 0;\n  border-radius: 2px;\n  background: #fff;\n  -webkit-box-shadow: 0 0 10px #ccc;\n          box-shadow: 0 0 10px #ccc;\n  padding-bottom: 10px;\n  margin-top: 10px;\n  width: 238px;\n  color: #555;\n  display: none;\n}\n.am-datepicker > div {\n  display: none;\n}\n.am-datepicker table {\n  width: 100%;\n}\n.am-datepicker tr.am-datepicker-header {\n  font-size: 1.6rem;\n  color: #fff;\n  background: #3bb4f2;\n}\n.am-datepicker td,\n.am-datepicker th {\n  text-align: center;\n  font-weight: normal;\n  cursor: pointer;\n}\n.am-datepicker th {\n  height: 48px;\n}\n.am-datepicker td {\n  font-size: 1.4rem;\n}\n.am-datepicker td.am-datepicker-day {\n  height: 34px;\n  width: 34px;\n}\n.am-datepicker td.am-datepicker-day:hover {\n  background: #F0F0F0;\n  height: 34px;\n  width: 34px;\n}\n.am-datepicker td.am-datepicker-day.am-disabled {\n  cursor: no-drop;\n  color: #999;\n  background: #fafafa;\n}\n.am-datepicker td.am-datepicker-old,\n.am-datepicker td.am-datepicker-new {\n  color: #89d7ff;\n}\n.am-datepicker td.am-active,\n.am-datepicker td.am-active:hover {\n  border-radius: 2px;\n  color: #0084c7;\n  background: #F0F0F0;\n}\n.am-datepicker td span {\n  display: block;\n  width: 79.33333333px;\n  height: 40px;\n  line-height: 40px;\n  float: left;\n  cursor: pointer;\n}\n.am-datepicker td span:hover {\n  background: #F0F0F0;\n}\n.am-datepicker td span.am-active {\n  color: #0084c7;\n  background: #F0F0F0;\n}\n.am-datepicker td span.am-disabled {\n  cursor: no-drop;\n  color: #999;\n  background: #fafafa;\n}\n.am-datepicker td span.am-datepicker-old {\n  color: #89d7ff;\n}\n.am-datepicker .am-datepicker-dow {\n  height: 40px;\n  color: #0c80ba;\n}\n.am-datepicker-caret {\n  display: block!important;\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: middle;\n  border-bottom: 7px solid #3bb4f2;\n  border-right: 7px solid transparent;\n  border-left: 7px solid transparent;\n  border-top: 0 dotted;\n  -webkit-transform: rotate(360deg);\n      -ms-transform: rotate(360deg);\n          transform: rotate(360deg);\n  position: absolute;\n  top: -7px;\n  left: 6px;\n}\n.am-datepicker-right .am-datepicker-caret {\n  left: auto;\n  right: 7px;\n}\n.am-datepicker-up .am-datepicker-caret {\n  top: auto;\n  bottom: -7px;\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: middle;\n  border-top: 7px solid #fff;\n  border-right: 7px solid transparent;\n  border-left: 7px solid transparent;\n  border-bottom: 0 dotted;\n  -webkit-transform: rotate(360deg);\n      -ms-transform: rotate(360deg);\n          transform: rotate(360deg);\n}\n.am-datepicker-select {\n  height: 34px;\n  line-height: 34px;\n  text-align: center;\n  -webkit-transition: background-color 300ms ease-out;\n  transition: background-color 300ms ease-out;\n}\n.am-datepicker-select:hover {\n  background: rgba(154, 217, 248, 0.5);\n  color: #0c80ba;\n}\n.am-datepicker-prev,\n.am-datepicker-next {\n  width: 34px;\n  height: 34px;\n}\n.am-datepicker-prev-icon,\n.am-datepicker-next-icon {\n  width: 34px;\n  height: 34px;\n  line-height: 34px;\n  display: inline-block;\n  -webkit-transition: background-color 300ms ease-out;\n  transition: background-color 300ms ease-out;\n}\n.am-datepicker-prev-icon:hover,\n.am-datepicker-next-icon:hover {\n  background: rgba(154, 217, 248, 0.5);\n  color: #0c80ba;\n}\n.am-datepicker-prev-icon:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f053\";\n}\n.am-datepicker-next-icon:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f054\";\n}\n.am-datepicker-dropdown {\n  position: absolute;\n  z-index: 1120;\n}\n@media only screen and (max-width: 640px) {\n  .am-datepicker {\n    width: 100%;\n  }\n  .am-datepicker td span {\n    width: 33.33%;\n  }\n  .am-datepicker-caret {\n    display: none!important;\n  }\n  .am-datepicker-prev,\n  .am-datepicker-next {\n    width: 44px;\n    height: 44px;\n  }\n}\n.am-datepicker-success tr.am-datepicker-header {\n  background: #5eb95e;\n}\n.am-datepicker-success td.am-datepicker-day.am-disabled {\n  color: #999;\n}\n.am-datepicker-success td.am-datepicker-old,\n.am-datepicker-success td.am-datepicker-new {\n  color: #94df94;\n}\n.am-datepicker-success td.am-active,\n.am-datepicker-success td.am-active:hover {\n  color: #1b961b;\n}\n.am-datepicker-success td span.am-datepicker-old {\n  color: #94df94;\n}\n.am-datepicker-success td span.am-active {\n  color: #1b961b;\n}\n.am-datepicker-success .am-datepicker-caret {\n  border-bottom-color: #5eb95e;\n}\n.am-datepicker-success .am-datepicker-dow {\n  color: #367b36;\n}\n.am-datepicker-success .am-datepicker-select:hover,\n.am-datepicker-success .am-datepicker-prev-icon:hover,\n.am-datepicker-success .am-datepicker-next-icon:hover {\n  background: rgba(165, 216, 165, 0.5);\n  color: #367b36;\n}\n.am-datepicker-danger tr.am-datepicker-header {\n  background: #dd514c;\n}\n.am-datepicker-danger td.am-datepicker-day.am-disabled {\n  color: #999;\n}\n.am-datepicker-danger td.am-datepicker-old,\n.am-datepicker-danger td.am-datepicker-new {\n  color: #f59490;\n}\n.am-datepicker-danger td.am-active,\n.am-datepicker-danger td.am-active:hover {\n  color: #c10802;\n}\n.am-datepicker-danger td span.am-datepicker-old {\n  color: #f59490;\n}\n.am-datepicker-danger td span.am-active {\n  color: #c10802;\n}\n.am-datepicker-danger .am-datepicker-caret {\n  border-bottom-color: #dd514c;\n}\n.am-datepicker-danger .am-datepicker-dow {\n  color: #a4241f;\n}\n.am-datepicker-danger .am-datepicker-select:hover,\n.am-datepicker-danger .am-datepicker-prev-icon:hover,\n.am-datepicker-danger .am-datepicker-next-icon:hover {\n  background: rgba(237, 164, 162, 0.5);\n  color: #a4241f;\n}\n.am-datepicker-warning tr.am-datepicker-header {\n  background: #F37B1D;\n}\n.am-datepicker-warning td.am-datepicker-day.am-disabled {\n  color: #999;\n}\n.am-datepicker-warning td.am-datepicker-old,\n.am-datepicker-warning td.am-datepicker-new {\n  color: #ffad6d;\n}\n.am-datepicker-warning td.am-active,\n.am-datepicker-warning td.am-active:hover {\n  color: #aa4b00;\n}\n.am-datepicker-warning td span.am-datepicker-old {\n  color: #ffad6d;\n}\n.am-datepicker-warning td span.am-active {\n  color: #aa4b00;\n}\n.am-datepicker-warning .am-datepicker-caret {\n  border-bottom-color: #F37B1D;\n}\n.am-datepicker-warning .am-datepicker-dow {\n  color: #a14c09;\n}\n.am-datepicker-warning .am-datepicker-select:hover,\n.am-datepicker-warning .am-datepicker-prev-icon:hover,\n.am-datepicker-warning .am-datepicker-next-icon:hover {\n  background: rgba(248, 180, 126, 0.5);\n  color: #a14c09;\n}\n.am-datepicker > div {\n  display: block;\n}\n.am-datepicker > div span.am-datepicker-hour {\n  width: 59.5px;\n}\n.am-datepicker-date {\n  display: block;\n}\n.am-datepicker-date.am-input-group {\n  display: table;\n}\n.am-datepicker-time-box {\n  padding: 30px 0 30px 0;\n}\n.am-datepicker-time-box strong {\n  font-size: 5.2rem;\n  display: inline-block;\n  height: 70px;\n  width: 70px;\n  line-height: 70px;\n  font-weight: normal;\n}\n.am-datepicker-time-box strong:hover {\n  border-radius: 4px;\n  background: #ECECEC;\n}\n.am-datepicker-time-box em {\n  display: inline-block;\n  height: 70px;\n  width: 20px;\n  line-height: 70px;\n  font-size: 5.2rem;\n  font-style: normal;\n}\n.am-datepicker-toggle {\n  text-align: center;\n  cursor: pointer;\n  padding: 10px 0;\n}\n.am-datepicker-toggle:hover {\n  background: #f0f0f0;\n}\n/* ==========================================================================\n   Component: Print\n ============================================================================ */\n@media print {\n  *,\n  *:before,\n  *:after {\n    background: transparent !important;\n    color: #000 !important;\n    /* Black prints faster: h5bp.com/s */\n    -webkit-box-shadow: none !important;\n            box-shadow: none !important;\n    text-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  /**\n   * Don't show links that are fragment identifiers,\n   * or use the `javascript:` pseudo protocol\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    /* h5bp.com/t */\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\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  @page {\n    margin: 0.5cm;\n  }\n  select {\n    background: #fff !important;\n  }\n  .am-topbar {\n    display: none;\n  }\n  .am-table td,\n  .am-table th {\n    background-color: #fff !important;\n  }\n  .am-table {\n    border-collapse: collapse !important;\n  }\n  .am-table-bordered th,\n  .am-table-bordered td {\n    border: 1px solid #ddd !important;\n  }\n}\n/* print helper classes */\n.am-print-block {\n  display: none !important;\n}\n@media print {\n  .am-print-block {\n    display: block !important;\n  }\n}\n.am-print-inline {\n  display: none !important;\n}\n@media print {\n  .am-print-inline {\n    display: inline !important;\n  }\n}\n.am-print-inline-block {\n  display: none !important;\n}\n@media print {\n  .am-print-inline-block {\n    display: inline-block !important;\n  }\n}\n@media print {\n  .am-print-hide {\n    display: none !important;\n  }\n}\n.lte9 #nprogress .nprogress-spinner {\n  display: none !important;\n}\n.lte8 .am-dimmer {\n  background-color: #000;\n  filter: alpha(opacity=60);\n}\n.lte8 .am-modal-actions {\n  display: none;\n}\n.lte8 .am-modal-actions.am-modal-active {\n  display: block;\n}\n.lte8 .am-offcanvas.am-active {\n  background: #000;\n}\n.lte8 .am-popover .am-popover-caret {\n  border: 8px solid transparent;\n}\n.lte8 .am-popover-top .am-popover-caret {\n  border-top: 8px solid #333333;\n  border-bottom: none;\n}\n.lte8 .am-popover-left .am-popover-caret {\n  right: -8px;\n  margin-top: -6px;\n  border-left: 8px solid #333333;\n  border-right: none;\n}\n.lte8 .am-popover-right .am-popover-caret {\n  left: -8px;\n  margin-top: -6px;\n  border-right: 8px solid #333333;\n  border-left: none;\n}\n.am-accordion-item {\n  margin: 0;\n}\n.am-accordion-title {\n  font-weight: normal;\n  cursor: pointer;\n}\n.am-accordion-item.am-disabled .am-accordion-title {\n  cursor: default;\n  pointer-events: none;\n}\n.am-accordion-bd {\n  margin: 0 !important;\n  padding: 0 !important;\n  border: none !important;\n}\n.am-accordion-content {\n  margin-top: 0;\n  padding: 0.8rem 1rem 1.2rem;\n  font-size: 1.4rem;\n}\n/**\n  * Accordion Theme: default\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-accordion-default {\n  margin: 1rem;\n  border-radius: 2px;\n  -webkit-box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);\n}\n.am-accordion-default .am-accordion-item {\n  border-top: 1px solid rgba(0, 0, 0, 0.05);\n}\n.am-accordion-default .am-accordion-item:first-child {\n  border-top: none;\n}\n.am-accordion-default .am-accordion-title {\n  color: rgba(0, 0, 0, 0.6);\n  -webkit-transition: background-color 0.2s ease-out;\n  transition: background-color 0.2s ease-out;\n  padding: .8rem 1rem;\n}\n.am-accordion-default .am-accordion-title:before {\n  content: \"\\f0da\";\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  -webkit-transition: -webkit-transform .2s ease;\n  transition: -webkit-transform .2s ease;\n  transition: transform .2s ease;\n  transition: transform .2s ease, -webkit-transform .2s ease;\n  -webkit-transform: rotate(0deg);\n      -ms-transform: rotate(0deg);\n          transform: rotate(0deg);\n  margin-right: 5px;\n}\n.am-accordion-default .am-accordion-title:hover {\n  color: #0e90d2;\n}\n.am-accordion-default .am-accordion-content {\n  color: #666;\n}\n.am-accordion-default .am-active .am-accordion-title {\n  background-color: #eeeeee;\n  color: #0e90d2;\n}\n.am-accordion-default .am-active .am-accordion-title:before {\n  -webkit-transform: rotate(90deg);\n      -ms-transform: rotate(90deg);\n          transform: rotate(90deg);\n}\n/**\n  * Accordion Theme: basic\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-accordion-basic {\n  margin: 1rem;\n}\n.am-accordion-basic .am-accordion-title {\n  color: #333333;\n  -webkit-transition: background-color 0.2s ease-out;\n  transition: background-color 0.2s ease-out;\n  padding: .8rem 0 0;\n}\n.am-accordion-basic .am-accordion-title:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f0da\";\n  -webkit-transition: -webkit-transform .2s ease;\n  transition: -webkit-transform .2s ease;\n  transition: transform .2s ease;\n  transition: transform .2s ease, -webkit-transform .2s ease;\n  -webkit-transform: rotate(0deg);\n      -ms-transform: rotate(0deg);\n          transform: rotate(0deg);\n  margin-right: .5rem;\n}\n.am-accordion-basic .am-accordion-content {\n  color: #666;\n}\n.am-accordion-basic .am-active .am-accordion-title {\n  color: #0e90d2;\n}\n.am-accordion-basic .am-active .am-accordion-title:before {\n  -webkit-transform: rotate(90deg);\n      -ms-transform: rotate(90deg);\n          transform: rotate(90deg);\n}\n/**\n  * Accordion Theme: gapped\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-accordion-gapped {\n  margin: .5rem 1rem;\n}\n.am-accordion-gapped .am-accordion-item {\n  border: 1px solid #dedede;\n  border-bottom: none;\n  margin: .5rem 0;\n}\n.am-accordion-gapped .am-accordion-item.am-active {\n  border-bottom: 1px solid #dedede;\n}\n.am-accordion-gapped .am-accordion-title {\n  color: rgba(0, 0, 0, 0.6);\n  -webkit-transition: background-color 0.15s ease-out;\n  transition: background-color 0.15s ease-out;\n  border-bottom: 1px solid #dedede;\n  padding: 0.8rem 2rem 0.8rem 1rem;\n  position: relative;\n}\n.am-accordion-gapped .am-accordion-title:after {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f105\";\n  -webkit-transition: -webkit-transform .2s linear;\n  transition: -webkit-transform .2s linear;\n  transition: transform .2s linear;\n  transition: transform .2s linear, -webkit-transform .2s linear;\n  position: absolute;\n  right: 10px;\n  top: 50%;\n  margin-top: -0.8rem;\n}\n.am-accordion-gapped .am-accordion-title:hover {\n  color: rgba(0, 0, 0, 0.8);\n}\n.am-accordion-gapped .am-accordion-content {\n  color: #666;\n}\n.am-accordion-gapped .am-active .am-accordion-title {\n  background-color: #f5f5f5;\n  color: rgba(0, 0, 0, 0.8);\n}\n.am-accordion-gapped .am-active .am-accordion-title:after {\n  -webkit-transform: rotate(90deg);\n      -ms-transform: rotate(90deg);\n          transform: rotate(90deg);\n}\n.am-divider {\n  height: 0;\n  margin: 1.5rem auto;\n  overflow: hidden;\n  clear: both;\n}\n/**\n  * Divider Theme: default\n  */\n.am-divider-default {\n  border-top: 1px solid #ddd;\n}\n/**\n  * Divider Theme: dotted\n  */\n.am-divider-dotted {\n  border-top: 1px dotted #ccc;\n}\n/**\n  * Divider Theme: dashed\n  */\n.am-divider-dashed {\n  border-top: 1px dashed #ccc;\n}\n.am-figure-zoomable {\n  position: relative;\n  cursor: pointer;\n}\n.am-figure-zoomable:after {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f00e\";\n  position: absolute;\n  top: 1rem;\n  right: 1rem;\n  color: #999999;\n  font-size: 1.6rem;\n  -webkit-transition: all 0.2s;\n  transition: all 0.2s;\n  pointer-events: none;\n}\n.am-figure-zoomable:hover:after {\n  color: #eeeeee;\n}\n.am-figure-default {\n  margin: 10px;\n}\n.am-figure-default img {\n  display: block;\n  max-width: 100%;\n  height: auto;\n  padding: 2px;\n  border: 1px solid #eeeeee;\n  margin: 10px auto;\n}\n.am-figure-default figcaption {\n  text-align: center;\n  font-size: 1.4rem;\n  margin-bottom: 15px;\n  color: #333333;\n}\n.am-footer {\n  text-align: center;\n  padding: 1em 0;\n  font-size: 1.6rem;\n}\n.am-footer .am-switch-mode-ysp {\n  cursor: pointer;\n}\n.am-footer .am-footer-text {\n  margin-top: 10px;\n  font-size: 14px;\n}\n.am-footer .am-footer-text-left {\n  text-align: left;\n  padding-left: 10px;\n}\n.am-modal-footer-hd {\n  padding-bottom: 10px;\n}\n/**\n  * Footer Theme: default\n  */\n.am-footer-default {\n  background-color: #fff;\n}\n.am-footer-default a {\n  color: #555555;\n}\n.am-footer-default .am-footer-switch {\n  margin-bottom: 10px;\n  font-weight: bold;\n}\n.am-footer-default .am-footer-ysp {\n  color: #555555;\n  cursor: pointer;\n}\n.am-footer-default .am-footer-divider {\n  color: #ccc;\n}\n.am-footer-default .am-footer-desktop {\n  color: #0e90d2;\n}\n.am-footer-default .am-footer-miscs {\n  color: #999999;\n  font-size: 13px;\n}\n.am-footer-default .am-footer-miscs p {\n  margin: 5px 0;\n}\n@media only screen and (min-width:641px) {\n  .am-footer-default .am-footer-miscs p {\n    display: inline-block;\n    margin: 5px;\n  }\n}\n.am-gallery {\n  padding: 5px 5px 0 5px;\n  list-style: none;\n}\n.am-gallery h3 {\n  margin: 0;\n}\n[data-am-gallery*='pureview'] img {\n  cursor: pointer;\n}\n/**\n  * Gallery Theme: default\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-gallery-default > li {\n  padding: 5px;\n}\n.am-gallery-default .am-gallery-item img {\n  width: 100%;\n  height: auto;\n}\n.am-gallery-default .am-gallery-title {\n  margin-top: 10px;\n  font-weight: normal;\n  font-size: 1.4rem;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n  color: #555555;\n}\n.am-gallery-default .am-gallery-desc {\n  color: #999999;\n  font-size: 1.2rem;\n}\n/**\n  * Gallery Theme: overlay\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-gallery-overlay > li {\n  padding: 5px;\n}\n.am-gallery-overlay .am-gallery-item {\n  position: relative;\n}\n.am-gallery-overlay .am-gallery-item img {\n  width: 100%;\n  height: auto;\n}\n.am-gallery-overlay .am-gallery-title {\n  font-weight: normal;\n  font-size: 1.4rem;\n  color: #FFF;\n  position: absolute;\n  bottom: 0;\n  width: 100%;\n  background-color: rgba(0, 0, 0, 0.5);\n  text-indent: 5px;\n  height: 30px;\n  line-height: 30px;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-gallery-overlay .am-gallery-desc {\n  display: none;\n}\n/**\n  * Accordion Theme: bordered\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-gallery-bordered > li {\n  padding: 5px;\n}\n.am-gallery-bordered .am-gallery-item {\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.35);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.35);\n  padding: 5px;\n}\n.am-gallery-bordered .am-gallery-item img {\n  width: 100%;\n  height: auto;\n}\n.am-gallery-bordered .am-gallery-title {\n  margin-top: 10px;\n  font-weight: normal;\n  font-size: 1.4rem;\n  color: #555555;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-gallery-bordered .am-gallery-desc {\n  color: #999999;\n  font-size: 1.2rem;\n}\n/**\n  * Gallery Theme: imgbordered\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-gallery-imgbordered > li {\n  padding: 5px;\n}\n.am-gallery-imgbordered .am-gallery-item img {\n  width: 100%;\n  height: auto;\n  border: 3px solid #FFF;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.35);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.35);\n}\n.am-gallery-imgbordered .am-gallery-title {\n  margin-top: 10px;\n  font-weight: normal;\n  font-size: 1.4rem;\n  color: #555555;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-gallery-imgbordered .am-gallery-desc {\n  color: #999999;\n  font-size: 1.2rem;\n}\n.am-gotop a {\n  display: inline-block;\n  text-decoration: none;\n}\n/**\n  * Gotop Theme: default\n  */\n.am-gotop-default {\n  text-align: center;\n  margin: 10px 0;\n}\n.am-gotop-default a {\n  background-color: #0e90d2;\n  padding: .5em 1.5em;\n  border-radius: 2px;\n  color: #fff;\n}\n.am-gotop-default a img {\n  display: none;\n}\n/**\n  * Gotop Theme: fixed\n  */\n.am-gotop-fixed {\n  position: fixed;\n  right: 10px;\n  bottom: 10px;\n  z-index: 1010;\n  opacity: 0;\n  width: 32px;\n  min-height: 32px;\n  overflow: hidden;\n  border-radius: 2px;\n  text-align: center;\n}\n.am-gotop-fixed.am-active {\n  opacity: .9;\n}\n.am-gotop-fixed.am-active:hover {\n  opacity: 1;\n}\n.am-gotop-fixed a {\n  display: block;\n}\n.am-gotop-fixed .am-gotop-title {\n  display: none;\n}\n.am-gotop-fixed .am-gotop-icon-custom {\n  display: inline-block;\n  max-width: 30px;\n  vertical-align: middle;\n}\n.am-gotop-fixed .am-gotop-icon {\n  width: 100%;\n  line-height: 32px;\n  background-color: #555555;\n  vertical-align: middle;\n  color: #ddd;\n}\n.am-gotop-fixed .am-gotop-icon:hover {\n  color: #fff;\n}\n.am-with-fixed-navbar .am-gotop-fixed {\n  bottom: 60px;\n}\n.am-header {\n  position: relative;\n  width: 100%;\n  height: 49px;\n  line-height: 49px;\n  padding: 0 10px;\n}\n.am-header h1 {\n  margin-top: 0;\n  margin-bottom: 0;\n}\n.am-header .am-header-title {\n  margin: 0 30%;\n  font-size: 2rem;\n  font-weight: normal;\n  text-align: center;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-header .am-header-title img {\n  margin-top: 12px;\n  height: 25px;\n  vertical-align: top;\n}\n.am-header .am-header-nav {\n  position: absolute;\n  top: 0;\n}\n.am-header .am-header-nav img {\n  height: 16px;\n  width: auto;\n  vertical-align: middle;\n}\n.am-header .am-header-left {\n  left: 10px;\n}\n.am-header .am-header-right {\n  right: 10px;\n}\n.am-header-fixed {\n  position: fixed;\n  top: 0;\n  left: 0;\n  right: 0;\n  width: 100%;\n  z-index: 1010;\n}\n.am-with-fixed-header {\n  padding-top: 49px;\n}\n/**\n  * Header Theme: default\n  */\n.am-header-default {\n  background-color: #0e90d2;\n}\n.am-header-default .am-header-title {\n  color: #fff;\n}\n.am-header-default .am-header-title a {\n  color: #fff;\n}\n.am-header-default .am-header-icon {\n  font-size: 20px;\n}\n.am-header-default .am-header-nav {\n  color: #eeeeee;\n}\n.am-header-default .am-header-nav > a {\n  display: inline-block;\n  min-width: 36px;\n  text-align: center;\n  color: #eeeeee;\n}\n.am-header-default .am-header-nav > a + a {\n  margin-left: 5px;\n}\n.am-header-default .am-header-nav .am-btn {\n  margin-top: 9px;\n  height: 31px;\n  padding: 0 0.5em;\n  line-height: 30px;\n  font-size: 14px;\n  vertical-align: top;\n}\n.am-header-default .am-header-nav .am-btn .am-header-icon {\n  font-size: inherit;\n}\n.am-header-default .am-header-nav .am-btn-default {\n  color: #999999;\n}\n.am-header-default .am-header-nav-title,\n.am-header-default .am-header-nav-title + .am-header-icon {\n  font-size: 14px;\n}\n.am-intro {\n  position: relative;\n}\n.am-intro img {\n  max-width: 100%;\n}\n.am-intro-hd {\n  position: relative;\n  height: 45px;\n  line-height: 45px;\n}\n.am-intro-title {\n  font-size: 18px;\n  margin: 0;\n  font-weight: bold;\n}\n.am-intro-more-top {\n  position: absolute;\n  right: 10px;\n  top: 0;\n  font-size: 1.4rem;\n}\n.am-intro-bd {\n  padding-top: 15px;\n  padding-bottom: 15px;\n  font-size: 1.4rem;\n}\n.am-intro-bd p:last-child {\n  margin-bottom: 0;\n}\n.am-intro-more-bottom {\n  clear: both;\n  text-align: center;\n}\n.am-intro-more-bottom .am-btn {\n  font-size: 14px;\n}\n/**\n  * Intro Theme: default\n  */\n.am-intro-default .am-intro-hd {\n  background-color: #0e90d2;\n  color: #fff;\n  padding: 0 10px;\n}\n.am-intro-default .am-intro-hd a {\n  color: #eee;\n}\n.am-intro-default .am-intro-right {\n  padding-left: 0;\n}\n.am-list-news-hd {\n  padding-top: 1.2rem;\n  padding-bottom: 0.8rem;\n}\n.am-list-news-hd a {\n  display: block;\n}\n.am-list-news-hd h2 {\n  font-size: 1.6rem;\n  float: left;\n  margin: 0;\n  height: 2rem;\n  line-height: 2rem;\n}\n.am-list-news-hd h3 {\n  margin: 0;\n}\n.am-list-news-hd .am-list-news-more {\n  font-size: 1.3rem;\n  height: 2rem;\n  line-height: 2rem;\n}\n.am-list .am-list-item-dated a {\n  padding-right: 80px;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-list .am-list-item-dated a::after {\n  display: none;\n}\n.am-list .am-list-item-desced a,\n.am-list .am-list-item-thumbed a {\n  padding-right: 0;\n}\n.am-list-news .am-list-item-hd {\n  margin: 0;\n}\n.am-list-date {\n  position: absolute;\n  right: 5px;\n  font-size: 1.3rem;\n  top: 1.3rem;\n}\n.am-list-item-desced {\n  padding-bottom: 1rem;\n}\n.am-list-item-desced > a {\n  padding: 1rem 0;\n}\n.am-list-item-desced .am-list-date {\n  position: static;\n}\n.am-list-item-thumbed {\n  padding-top: 1em;\n}\n.am-list-news-ft {\n  text-align: center;\n}\n.am-list-news .am-titlebar {\n  margin-left: 0;\n  margin-right: 0;\n}\n.am-list-news .am-titlebar ~ .am-list-news-bd .am-list > li:first-child {\n  border-top: none;\n}\n/**\n  * list_news Theme: default\n  */\n.am-list-news-default {\n  margin: 10px;\n}\n.am-list-news-default .am-g {\n  margin-left: auto;\n  margin-right: auto;\n}\n.am-list-news-default .am-list-item-hd {\n  font-weight: normal;\n}\n.am-list-news-default .am-list-date {\n  color: #999999;\n}\n.am-list-news-default .am-list > li {\n  border-color: #dedede;\n}\n.am-list-news-default .am-list .am-list-item-desced {\n  padding-top: 1rem;\n  padding-bottom: 1rem;\n}\n.am-list-news-default .am-list .am-list-item-desced > a {\n  padding: 0;\n}\n.am-list-news-default .am-list .am-list-item-desced .am-list-item-text {\n  margin-top: 0.5rem;\n  color: #757575;\n}\n.am-list-news-default .am-list .am-list-item-text {\n  overflow: hidden;\n  text-overflow: ellipsis;\n  display: -webkit-box;\n  -webkit-box-orient: vertical;\n  line-height: 1.3em;\n  -webkit-line-clamp: 2;\n  /* number of lines to show */\n  max-height: 2.6em;\n}\n.am-list-news-default .am-list .am-list-item-thumb-top .am-list-thumb {\n  padding: 0;\n  margin-bottom: 0.8rem;\n}\n.am-list-news-default .am-list .am-list-item-thumb-top .am-list-main {\n  padding: 0;\n}\n.am-list-news-default .am-list .am-list-item-thumb-left .am-list-thumb {\n  padding-left: 0;\n}\n.am-list-news-default .am-list .am-list-item-desced .am-list-main {\n  padding: 0;\n}\n.am-list-news-default .am-list .am-list-item-thumb-right .am-list-thumb {\n  padding-right: 0;\n}\n.am-list-news-default .am-list .am-list-item-thumb-bottom-left .am-list-item-hd {\n  clear: both;\n  padding-bottom: 0.5rem;\n}\n.am-list-news-default .am-list .am-list-item-thumb-bottom-left .am-list-thumb {\n  padding-left: 0;\n}\n.am-list-news-default .am-list .am-list-item-thumb-bottom-right .am-list-item-hd {\n  clear: both;\n  padding-bottom: 0.5rem;\n}\n.am-list-news-default .am-list .am-list-item-thumb-bottom-right .am-list-thumb {\n  padding-right: 0;\n}\n.am-list-news-default .am-list .am-list-thumb img {\n  width: 100%;\n  display: block;\n}\n@media only screen and (max-width: 640px) {\n  .am-list-news-default .am-list-item-thumb-left .am-list-thumb,\n  .am-list-news-default .am-list-item-thumb-right .am-list-thumb {\n    max-height: 80px;\n    overflow: hidden;\n  }\n  .am-list-news-default .am-list-item-thumb-bottom-left .am-list-item-text,\n  .am-list-news-default .am-list-item-thumb-bottom-right .am-list-item-text {\n    -webkit-line-clamp: 3;\n    /* number of lines to show */\n    max-height: 3.9em;\n  }\n  .am-list-news-default .am-list-item-thumb-bottom-left .am-list-thumb,\n  .am-list-news-default .am-list-item-thumb-bottom-right .am-list-thumb {\n    max-height: 60px;\n    overflow: hidden;\n  }\n}\n.am-map {\n  width: 100%;\n  height: 300px;\n}\n/**\n  * Accordion Theme: default\n  * Author: Hzp (hzp@yunshipei.com)\n  */\n.am-map-default #bd-map {\n  width: 100%;\n  height: 100%;\n  overflow: hidden;\n  margin: 0;\n  font-size: 14px;\n  line-height: 1.4!important;\n}\n.am-map-default .BMap_bubble_title {\n  font-weight: bold;\n}\n.am-map-default #BMap_mask {\n  width: 100%;\n}\n.am-mechat {\n  margin: 1rem;\n}\n.am-mechat .section-cbox-wap .cbox-post-wap .post-action-wap .action-function-wap .function-list-wap .list-upload-wap .upload-mutual-wap {\n  -webkit-box-sizing: content-box;\n          box-sizing: content-box;\n}\n.am-menu {\n  position: relative;\n  padding: 0;\n  margin: 0;\n}\n.am-menu ul {\n  padding: 0;\n  margin: 0;\n}\n.am-menu li {\n  list-style: none;\n}\n.am-menu a:after,\n.am-menu a:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n}\n.am-menu-sub {\n  z-index: 1050;\n}\n.am-menu-toggle {\n  display: none;\n  z-index: 1015;\n}\n.am-menu-toggle img {\n  display: inline-block;\n  height: 16px;\n  width: auto;\n  vertical-align: middle;\n}\n.am-menu-nav a {\n  display: block;\n  padding: 0.8rem 0;\n  -webkit-transition: all 0.45s;\n  transition: all 0.45s;\n}\n/**\n  * Menu Theme: default\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-menu-default .am-menu-nav {\n  padding-top: 8px;\n  padding-bottom: 8px;\n}\n.am-menu-default .am-menu-nav a {\n  text-align: center;\n  height: 36px;\n  line-height: 36px;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n  padding: 0;\n  color: #0e90d2;\n}\n.am-menu-default .am-menu-nav > .am-parent > a {\n  position: relative;\n  -webkit-transition: .15s;\n  transition: .15s;\n}\n.am-menu-default .am-menu-nav > .am-parent > a:after {\n  content: \"\\f107\";\n  margin-left: 5px;\n  -webkit-transition: .15s;\n  transition: .15s;\n}\n.am-menu-default .am-menu-nav > .am-parent > a:before {\n  position: absolute;\n  top: 100%;\n  margin-top: -16px;\n  left: 50%;\n  margin-left: -12px;\n  content: \"\\f0d8\";\n  display: none;\n  color: #f1f1f1;\n  font-size: 24px;\n}\n.am-menu-default .am-menu-nav > .am-parent.am-open > a {\n  color: #095f8a;\n}\n.am-menu-default .am-menu-nav > .am-parent.am-open > a:before {\n  display: block;\n}\n.am-menu-default .am-menu-nav > .am-parent.am-open > a:after {\n  -webkit-transform: rotate(-180deg);\n      -ms-transform: rotate(-180deg);\n          transform: rotate(-180deg);\n}\n.am-menu-default .am-menu-sub {\n  position: absolute;\n  left: 5px;\n  right: 5px;\n  background-color: #f1f1f1;\n  border-radius: 2px;\n  padding-top: 8px;\n  padding-bottom: 8px;\n}\n.am-menu-default .am-menu-sub > li > a {\n  color: #555555;\n}\n@media only screen and (min-width:641px) {\n  .am-menu-default .am-menu-nav li {\n    width: auto;\n    float: left;\n    clear: none;\n    display: inline;\n  }\n  .am-menu-default .am-menu-nav a {\n    padding-left: 1.5rem;\n    padding-right: .5rem;\n  }\n}\n/**\n/**\n  * Menu Theme: dropdown1\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-menu-dropdown1 {\n  position: relative;\n  /*@media @medium-up {\n    .am-menu-toggle {\n      display: none!important;\n    }\n\n    .am-menu-nav {\n      &.am-collapse {\n        display: block;\n      }\n\n      .am-menu-sub {\n        background-color: ;//@menu-sub-bg;\n        display: block;\n        & > li {\n          clear: none;\n\n        }\n      }\n\n      .am-menu-lv2 {\n        & > li {\n          clear: none;\n          width: auto;\n        }\n      }\n    }\n  }*/\n}\n.am-menu-dropdown1 .am-menu-toggle {\n  position: absolute;\n  right: 5px;\n  top: -47px;\n  display: block;\n  width: 44px;\n  height: 44px;\n  line-height: 44px;\n  text-align: center;\n  color: #fff;\n}\n.am-menu-dropdown1 a {\n  -webkit-transition: all .4s;\n  transition: all .4s;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-menu-dropdown1 .am-menu-nav {\n  position: absolute;\n  left: 0;\n  right: 0;\n  z-index: 1050;\n}\n.am-menu-dropdown1 .am-menu-nav a {\n  padding: 0.8rem;\n}\n.am-menu-dropdown1 .am-menu-nav > li {\n  width: 100%;\n}\n.am-menu-dropdown1 .am-menu-nav > li.am-parent > a {\n  position: relative;\n}\n.am-menu-dropdown1 .am-menu-nav > li.am-parent > a::before {\n  content: \"\\f067\";\n  position: absolute;\n  right: 1rem;\n  top: 1.4rem;\n}\n.am-menu-dropdown1 .am-menu-nav > li.am-parent.am-open > a {\n  background-color: #0c80ba;\n  border-bottom: none;\n  color: #fff;\n}\n.am-menu-dropdown1 .am-menu-nav > li.am-parent.am-open > a:before {\n  content: \"\\f068\";\n}\n.am-menu-dropdown1 .am-menu-nav > li.am-parent.am-open > a:after {\n  content: \"\";\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: middle;\n  border-top: 8px solid #0c80ba;\n  border-right: 8px solid transparent;\n  border-left: 8px solid transparent;\n  border-bottom: 0 dotted;\n  -webkit-transform: rotate(360deg);\n      -ms-transform: rotate(360deg);\n          transform: rotate(360deg);\n  position: absolute;\n  top: 100%;\n  left: 50%;\n  margin-left: -4px;\n}\n.am-menu-dropdown1 .am-menu-nav > li > a {\n  border-bottom: 1px solid #0b76ac;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);\n  background-color: #0e90d2;\n  color: #fff;\n  height: 49px;\n  line-height: 49px;\n  padding: 0;\n  text-indent: 10px;\n}\n.am-menu-dropdown1 .am-menu-sub {\n  background-color: #fff;\n}\n.am-menu-dropdown1 .am-menu-sub a {\n  color: #555;\n  height: 44px;\n  line-height: 44px;\n  text-indent: 5px;\n  padding: 0;\n}\n.am-menu-dropdown1 .am-menu-sub a:before {\n  content: \"\\f105\";\n  color: #aaa;\n  font-size: 16px;\n  margin-right: 5px;\n}\n/**\n  * Menu Theme: dropdown2\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-menu-dropdown2 .am-menu-toggle {\n  position: absolute;\n  right: 5px;\n  top: -47px;\n  display: block;\n  width: 44px;\n  height: 44px;\n  line-height: 44px;\n  text-align: center;\n  color: #fff;\n}\n.am-menu-dropdown2 .am-menu-nav {\n  position: absolute;\n  left: 0;\n  right: 0;\n  background-color: #f5f5f5;\n  -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);\n  z-index: 1050;\n  padding-top: 8px;\n  padding-bottom: 8px;\n}\n.am-menu-dropdown2 .am-menu-nav a {\n  height: 38px;\n  line-height: 38px;\n  padding: 0;\n  text-align: center;\n}\n.am-menu-dropdown2 .am-menu-nav > li > a {\n  color: #333333;\n}\n.am-menu-dropdown2 .am-menu-nav > li.am-parent > a {\n  position: relative;\n}\n.am-menu-dropdown2 .am-menu-nav > li.am-parent > a:after {\n  content: \"\\f107\";\n  margin-left: 5px;\n  -webkit-transition: -webkit-transform .2s;\n  transition: -webkit-transform .2s;\n  transition: transform .2s;\n  transition: transform .2s, -webkit-transform .2s;\n}\n.am-menu-dropdown2 .am-menu-nav > li.am-parent.am-open > a {\n  position: relative;\n}\n.am-menu-dropdown2 .am-menu-nav > li.am-parent.am-open > a:after {\n  color: #0e90d2;\n  -webkit-transform: rotate(180deg);\n      -ms-transform: rotate(180deg);\n          transform: rotate(180deg);\n}\n.am-menu-dropdown2 .am-menu-nav > li.am-parent.am-open > a:before {\n  position: absolute;\n  top: 100%;\n  margin-top: -16px;\n  left: 50%;\n  margin-left: -12px;\n  font-size: 24px;\n  content: \"\\f0d8\";\n  color: rgba(0, 0, 0, 0.2);\n}\n.am-menu-dropdown2 .am-menu-sub {\n  position: absolute;\n  left: 5px;\n  right: 5px;\n  padding: 8px 0;\n  border-radius: 2px;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n  background-color: #fff;\n  z-index: 1055;\n}\n.am-menu-dropdown2 .am-menu-sub a {\n  padding: 0;\n  height: 35px;\n  color: #555555;\n  line-height: 35px;\n}\n@media only screen and (min-width:641px) {\n  .am-menu-dropdown2 .am-menu-toggle {\n    display: none !important;\n  }\n  .am-menu-dropdown2 .am-menu-nav {\n    position: static;\n    display: block;\n  }\n  .am-menu-dropdown2 .am-menu-nav > li {\n    float: none;\n    width: auto;\n    display: inline-block;\n  }\n  .am-menu-dropdown2 .am-menu-nav > li a {\n    padding-left: 1.5rem;\n    padding-right: 1.5rem;\n  }\n  .am-menu-dropdown2 .am-menu-sub {\n    left: auto;\n    right: auto;\n  }\n  .am-menu-dropdown2 .am-menu-sub > li {\n    float: none;\n    width: auto;\n  }\n  .am-menu-dropdown2 .am-menu-sub a {\n    padding-left: 2rem;\n    padding-right: 2rem;\n  }\n}\n/**\n  * Menu Theme: slide1\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-menu-slide1 .am-menu-toggle {\n  position: absolute;\n  right: 5px;\n  top: -47px;\n  display: block;\n  width: 44px;\n  height: 44px;\n  line-height: 44px;\n  text-align: center;\n  color: #fff;\n}\n.am-menu-slide1 .am-menu-nav {\n  background-color: #f5f5f5;\n  padding-top: 8px;\n  padding-bottom: 8px;\n}\n.am-menu-slide1 .am-menu-nav.am-in:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f0d8\";\n  font-size: 24px;\n  color: #f5f5f5;\n  position: absolute;\n  right: 16px;\n  top: -16px;\n}\n.am-menu-slide1 .am-menu-nav a {\n  line-height: 38px;\n  height: 38px;\n  display: block;\n  padding: 0;\n  text-align: center;\n}\n.am-menu-slide1 .am-menu-nav > li > a {\n  color: #333333;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-menu-slide1 .am-menu-nav > .am-parent > a {\n  position: relative;\n  -webkit-transition: .15s;\n  transition: .15s;\n}\n.am-menu-slide1 .am-menu-nav > .am-parent > a:after {\n  content: \"\\f107\";\n  margin-left: 5px;\n  -webkit-transition: .15s;\n  transition: .15s;\n}\n.am-menu-slide1 .am-menu-nav > .am-parent > a:before {\n  position: absolute;\n  top: 100%;\n  margin-top: -16px;\n  left: 50%;\n  margin-left: -12px;\n  content: \"\\f0d8\";\n  display: none;\n  color: #0e90d2;\n  font-size: 24px;\n}\n.am-menu-slide1 .am-menu-nav > .am-parent.am-open > a {\n  color: #0e90d2;\n}\n.am-menu-slide1 .am-menu-nav > .am-parent.am-open > a:before {\n  display: block;\n}\n.am-menu-slide1 .am-menu-nav > .am-parent.am-open > a:after {\n  -webkit-transform: rotate(-180deg);\n      -ms-transform: rotate(-180deg);\n          transform: rotate(-180deg);\n}\n.am-menu-slide1 .am-menu-sub {\n  position: absolute;\n  left: 5px;\n  right: 5px;\n  background-color: #0e90d2;\n  border-radius: 2px;\n  padding-top: 8px;\n  padding-bottom: 8px;\n}\n.am-menu-slide1 .am-menu-sub > li > a {\n  color: #fff;\n}\n@media only screen and (min-width:641px) {\n  .am-menu-slide1 .am-menu-toggle {\n    display: none !important;\n  }\n  .am-menu-slide1 .am-menu-nav {\n    background-color: #f5f5f5;\n    display: block;\n  }\n  .am-menu-slide1 .am-menu-nav.am-in:before {\n    display: none;\n  }\n  .am-menu-slide1 .am-menu-nav li {\n    width: auto;\n    clear: none;\n  }\n  .am-menu-slide1 .am-menu-nav li a {\n    padding-left: 1.5rem;\n    padding-right: 1.5rem;\n  }\n}\n/**\n  * Menu Theme: offcanvas1\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-menu-offcanvas1 .am-menu-toggle {\n  position: absolute;\n  right: 5px;\n  top: -47px;\n  display: block;\n  width: 44px;\n  height: 44px;\n  line-height: 44px;\n  text-align: center;\n  color: #fff;\n}\n.am-menu-offcanvas1 .am-menu-nav {\n  border-bottom: 1px solid rgba(0, 0, 0, 0.3);\n  -webkit-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.05);\n          box-shadow: 0 1px 0 rgba(255, 255, 255, 0.05);\n}\n.am-menu-offcanvas1 .am-menu-nav > li > a {\n  height: 44px;\n  line-height: 44px;\n  text-indent: 15px;\n  padding: 0;\n  position: relative;\n  color: #ccc;\n  border-top: 1px solid rgba(0, 0, 0, 0.3);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);\n  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.5);\n}\n.am-menu-offcanvas1 .am-menu-nav > .am-open > a,\n.am-menu-offcanvas1 .am-menu-nav > li > a:hover,\n.am-menu-offcanvas1 .am-menu-nav > li > a:focus {\n  background-color: #474747;\n  color: #fff;\n  outline: none;\n}\n.am-menu-offcanvas1 .am-menu-nav > .am-active > a {\n  background-color: #1a1a1a;\n  color: #fff;\n}\n.am-menu-offcanvas1 .am-menu-nav > .am-parent > a {\n  -webkit-transition: all .3s;\n  transition: all .3s;\n}\n.am-menu-offcanvas1 .am-menu-nav > .am-parent > a:after {\n  content: \"\\f104\";\n  position: absolute;\n  right: 1.5rem;\n  top: 1.3rem;\n}\n.am-menu-offcanvas1 .am-menu-nav > .am-parent.am-open > a:after {\n  content: \"\\f107\";\n}\n.am-menu-offcanvas1 .am-menu-sub {\n  border-top: 1px solid rgba(0, 0, 0, 0.3);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);\n  padding: 5px 0 5px 15px;\n  background-color: #1a1a1a;\n  font-size: 1.4rem;\n}\n.am-menu-offcanvas1 .am-menu-sub a {\n  color: #eee;\n}\n.am-menu-offcanvas1 .am-menu-sub a:hover {\n  color: #fff;\n}\n.am-menu-offcanvas1 .am-nav-divider {\n  border-top: 1px solid #1a1a1a;\n}\n/**\n  * Menu Theme: offcanvas2\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-menu-offcanvas2 .am-menu-toggle {\n  position: absolute;\n  right: 5px;\n  top: -47px;\n  display: block;\n  width: 44px;\n  height: 44px;\n  line-height: 44px;\n  text-align: center;\n  color: #fff;\n}\n.am-menu-offcanvas2 .am-menu-nav {\n  padding: 10px 5px;\n}\n.am-menu-offcanvas2 .am-menu-nav > li {\n  padding: 5px;\n}\n.am-menu-offcanvas2 .am-menu-nav > li > a {\n  -webkit-transition: all 0.3s;\n  transition: all 0.3s;\n  background-color: #404040;\n  color: #ccc;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);\n  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.5);\n  height: 44px;\n  line-height: 44px;\n  padding: 0;\n  text-align: center;\n}\n.am-menu-offcanvas2 .am-menu-nav > li > a:hover,\n.am-menu-offcanvas2 .am-menu-nav > li > a:focus {\n  background-color: #262626;\n  color: #fff;\n  outline: none;\n}\n.am-menu-offcanvas2 .am-menu-nav > .am-active > a {\n  background-color: #262626;\n  color: #fff;\n}\n/**\n  * Menu Theme: stack\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-menu-stack .am-menu-nav {\n  border-bottom: 1px solid #dedede;\n  -webkit-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.05);\n          box-shadow: 0 1px 0 rgba(255, 255, 255, 0.05);\n}\n.am-menu-stack .am-menu-nav > .am-parent > a {\n  -webkit-transition: all .3s;\n  transition: all .3s;\n}\n.am-menu-stack .am-menu-nav > .am-parent > a:after {\n  content: \"\\f105\";\n  position: absolute;\n  right: 1.5rem;\n  top: 1.3rem;\n  -webkit-transition: all .15s;\n  transition: all .15s;\n}\n.am-menu-stack .am-menu-nav > .am-parent.am-open > a:after {\n  -webkit-transform: rotate(90deg);\n      -ms-transform: rotate(90deg);\n          transform: rotate(90deg);\n}\n.am-menu-stack .am-menu-nav > li > a {\n  position: relative;\n  color: #333;\n  background-color: #f5f5f5;\n  border-top: 1px solid #dedede;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);\n  height: 49px;\n  line-height: 49px;\n  text-indent: 10px;\n  padding: 0;\n}\n.am-menu-stack .am-menu-nav > .am-open > a,\n.am-menu-stack .am-menu-nav > li > a:hover,\n.am-menu-stack .am-menu-nav > li > a:focus {\n  background-color: #e5e5e5;\n  color: #222;\n  outline: none;\n}\n.am-menu-stack .am-menu-sub {\n  padding: 0;\n  font-size: 1.4rem;\n  border-top: 1px solid #dedede;\n}\n.am-menu-stack .am-menu-sub a {\n  border-bottom: 1px solid #dedede;\n  padding-left: 2rem;\n  color: #444;\n}\n.am-menu-stack .am-menu-sub a:hover {\n  color: #333;\n}\n.am-menu-stack .am-menu-sub li:last-child a {\n  border-bottom: none;\n}\n.am-menu-stack .am-menu-sub > li > a {\n  height: 44px;\n  line-height: 44px;\n  text-indent: 15px;\n  padding: 0;\n}\n@media only screen and (min-width:641px) {\n  .am-menu-stack .am-menu-nav {\n    background-color: #f5f5f5;\n  }\n  .am-menu-stack .am-menu-nav > li {\n    float: left;\n    width: auto;\n    clear: none !important;\n    display: inline-block;\n  }\n  .am-menu-stack .am-menu-nav > li a {\n    padding-left: 1.5rem;\n    padding-right: 1.5rem;\n  }\n  .am-menu-stack .am-menu-nav > li.am-parent > a:after {\n    position: static;\n    content: \"\\f107\";\n  }\n  .am-menu-stack .am-menu-nav > li.am-parent.am-open a {\n    border-bottom: none;\n  }\n  .am-menu-stack .am-menu-nav > li.am-parent.am-open a:after {\n    -webkit-transform: rotateX(-180deg);\n            transform: rotateX(-180deg);\n  }\n  .am-menu-stack .am-menu-nav > li.am-parent.am-open .am-menu-sub {\n    background-color: #e5e5e5;\n  }\n  .am-menu-stack .am-menu-sub {\n    position: absolute;\n    left: 0;\n    right: 0;\n    background-color: #ddd;\n    border-top: none;\n  }\n  .am-menu-stack .am-menu-sub li {\n    width: auto;\n    float: left;\n    clear: none;\n  }\n}\n.am-navbar {\n  position: fixed;\n  left: 0;\n  bottom: 0;\n  width: 100%;\n  height: 49px;\n  line-height: 49px;\n  z-index: 1010;\n}\n.am-navbar ul {\n  padding-left: 0;\n  margin: 0;\n  list-style: none;\n  width: 100%;\n}\n.am-navbar .am-navbar-nav {\n  padding-left: 8px;\n  padding-right: 8px;\n  text-align: center;\n  overflow: hidden;\n  display: table;\n}\n.am-navbar .am-navbar-nav li {\n  display: table-cell;\n  width: 1%;\n  float: none;\n}\n.am-navbar-nav {\n  position: relative;\n  z-index: 1015;\n}\n.am-navbar-nav a {\n  display: inline-block;\n  width: 100%;\n  height: 49px;\n  line-height: 20px;\n}\n.am-navbar-nav a img {\n  display: block;\n  vertical-align: middle;\n  height: 24px;\n  width: 24px;\n  margin: 4px auto 0;\n}\n.am-navbar-nav a [class*=\"am-icon\"] {\n  width: 24px;\n  height: 24px;\n  margin: 4px auto 0;\n  display: block;\n  line-height: 24px;\n}\n.am-navbar-nav a [class*=\"am-icon\"]:before {\n  font-size: 22px;\n  vertical-align: middle;\n}\n.am-navbar-nav a .am-navbar-label {\n  padding-top: 2px;\n  line-height: 1;\n  font-size: 12px;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-navbar-more [class*=\"am-icon-\"] {\n  -webkit-transition: 0.15s;\n  transition: 0.15s;\n}\n.am-navbar-more.am-active [class*=\"am-icon-\"] {\n  -webkit-transform: rotateX(-180deg);\n          transform: rotateX(-180deg);\n}\n.am-navbar-actions {\n  position: absolute;\n  bottom: 49px;\n  right: 0;\n  left: 0;\n  z-index: 1009;\n  opacity: 0;\n  -webkit-transition: .3s;\n  transition: .3s;\n  -webkit-transform: translate(0, 100%);\n      -ms-transform: translate(0, 100%);\n          transform: translate(0, 100%);\n}\n.am-navbar-actions.am-active {\n  opacity: 1;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n}\n.am-navbar-actions li {\n  line-height: 42px;\n  position: relative;\n}\n.am-navbar-actions li a {\n  display: block;\n  width: 100%;\n  height: 40px;\n  -webkit-box-shadow: inset 0 1px rgba(220, 220, 220, 0.25);\n          box-shadow: inset 0 1px rgba(220, 220, 220, 0.25);\n  padding-left: 20px;\n  padding-right: 36px;\n}\n.am-navbar-actions li a :after {\n  font-family: \"FontAwesome\", sans-serif;\n  content: \"\\f105\";\n  display: inline-block;\n  position: absolute;\n  top: 0;\n  right: 20px;\n}\n.am-navbar-actions li a img {\n  vertical-align: middle;\n  height: 20px;\n  width: 20px;\n  display: inline;\n}\n#am-navbar-qrcode {\n  width: 220px;\n  height: 220px;\n  margin-left: -110px;\n}\n#am-navbar-qrcode .am-modal-bd {\n  padding: 10px;\n}\n#am-navbar-qrcode canvas {\n  display: block;\n  width: 200px;\n  height: 200px;\n}\n.am-with-fixed-navbar {\n  padding-bottom: 54px;\n}\n/**\n  * Navbar Theme: default\n  * Author: hzp (hzp@yunshipei.com)\n  */\n.am-navbar-default a {\n  color: #fff;\n}\n.am-navbar-default .am-navbar-nav {\n  background-color: #0e90d2;\n}\n.am-navbar-default .am-navbar-actions {\n  background-color: #0d86c4;\n}\n.am-navbar-default .am-navbar-actions a {\n  border-bottom: 1px solid #0b6fa2;\n}\n.am-pagination {\n  position: relative;\n}\n/**\n  * Pagination Theme: default\n  */\n.am-pagination-default {\n  margin-left: 10px;\n  margin-right: 10px;\n  font-size: 1.6rem;\n}\n.am-pagination-default .am-pagination-prev,\n.am-pagination-default .am-pagination-next {\n  float: none;\n}\n/**\n  * Pagination Theme: select\n  */\n.am-pagination-select {\n  margin-left: 10px;\n  margin-right: 10px;\n  font-size: 1.6rem;\n}\n.am-pagination-select > li > a {\n  line-height: 36px;\n  background-color: #eeeeee;\n  padding: 0 15px;\n  border: 0;\n  color: #555555;\n}\n.am-pagination-select .am-pagination-select {\n  position: absolute;\n  top: 0;\n  left: 50%;\n  margin-left: -35px;\n  width: 70px;\n  height: 36px;\n  text-align: center;\n  border-radius: 2px;\n}\n.am-pagination-select .am-pagination-select select {\n  display: block;\n  border: 0;\n  line-height: 36px;\n  width: 70px;\n  height: 36px;\n  border-radius: 2px;\n  color: #555555;\n  background-color: #eeeeee;\n  -webkit-appearance: none;\n  -moz-appearance: none;\n  appearance: none;\n  padding-left: 18px;\n}\n.am-paragraph p {\n  margin: 10px 0;\n}\n.am-paragraph img {\n  max-width: 100%;\n}\n.am-paragraph h1,\n.am-paragraph h2,\n.am-paragraph h3,\n.am-paragraph h4,\n.am-paragraph h5,\n.am-paragraph h6 {\n  color: #222222;\n}\n.am-paragraph table {\n  max-width: none;\n}\n.am-paragraph-table-container {\n  overflow: hidden;\n  background: #eeeeee;\n  max-width: none;\n}\n.am-paragraph-table-container table {\n  width: 100%;\n  max-width: none;\n}\n.am-paragraph-table-container table th {\n  background: #bce5fb;\n  height: 40px;\n  border: 1px solid #999999;\n  text-align: center;\n}\n.am-paragraph-table-container table td {\n  border: 1px solid #999999;\n  text-align: center;\n  vertical-align: middle;\n  background: #fff;\n}\n.am-paragraph-table-container table td p {\n  text-indent: 0;\n  font-size: 1.4rem;\n}\n.am-paragraph-table-container table td a {\n  font-size: 1.4rem;\n}\n/**\n  * Paragraph Theme: default\n  */\n.am-paragraph-default {\n  margin: 0 10px;\n  color: #333333;\n  background-color: transparent;\n}\n.am-paragraph-default p {\n  font-size: 1.4rem;\n}\n.am-paragraph-default img {\n  max-width: 98%;\n  display: block;\n  margin: 5px auto;\n  border: 1px solid #eeeeee;\n  padding: 2px;\n}\n.am-paragraph-default a {\n  color: #0e90d2;\n}\n/**\n  * Slider Theme: a1\n  */\n.am-slider-a1 {\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Control Nav */\n}\n.am-slider-a1 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-a1 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-a1 .am-control-nav {\n  width: 100%;\n  position: absolute;\n  bottom: 5px;\n  text-align: center;\n  line-height: 0;\n}\n.am-slider-a1 .am-control-nav li {\n  margin: 0 6px;\n  display: inline-block;\n}\n.am-slider-a1 .am-control-nav li a {\n  width: 8px;\n  height: 8px;\n  display: block;\n  background-color: rgba(0, 0, 0, 0.5);\n  cursor: pointer;\n  text-indent: -9999px;\n  border-radius: 50%;\n  -webkit-box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);\n          box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);\n}\n.am-slider-a1 .am-control-nav li a:hover {\n  background-color: rgba(0, 0, 0, 0.7);\n}\n.am-slider-a1 .am-control-nav li a.am-active {\n  background-color: #0e90d2;\n  cursor: default;\n}\n.am-slider-a1 .am-direction-nav,\n.am-slider-a1 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: a2\n  */\n.am-slider-a2 {\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Control Nav */\n}\n.am-slider-a2 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-a2 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-a2 .am-control-nav {\n  width: 100%;\n  position: absolute;\n  bottom: 5px;\n  text-align: center;\n  line-height: 0;\n}\n.am-slider-a2 .am-control-nav li {\n  margin: 0 6px;\n  display: inline-block;\n}\n.am-slider-a2 .am-control-nav li a {\n  width: 8px;\n  height: 8px;\n  display: block;\n  background-color: rgba(0, 0, 0, 0.5);\n  cursor: pointer;\n  text-indent: -9999px;\n  -webkit-box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);\n          box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);\n}\n.am-slider-a2 .am-control-nav li a:hover {\n  background-color: rgba(0, 0, 0, 0.7);\n}\n.am-slider-a2 .am-control-nav li a.am-active {\n  background: #0e93d7;\n  cursor: default;\n}\n.am-slider-a2 .am-direction-nav,\n.am-slider-a2 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: a3\n  */\n.am-slider-a3 {\n  margin-bottom: 20px;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Control Nav */\n}\n.am-slider-a3 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-a3 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-a3 .am-control-nav {\n  width: 100%;\n  position: absolute;\n  bottom: -20px;\n  text-align: center;\n  height: 20px;\n  background-color: #000;\n  padding-top: 5px;\n  line-height: 0;\n}\n.am-slider-a3 .am-control-nav li {\n  margin: 0 6px;\n  display: inline-block;\n}\n.am-slider-a3 .am-control-nav li a {\n  width: 8px;\n  height: 8px;\n  display: block;\n  background-color: rgba(0, 0, 0, 0.5);\n  cursor: pointer;\n  text-indent: -9999px;\n  border-radius: 50%;\n  -webkit-box-shadow: inset 0 0 3px rgba(200, 200, 200, 0.3);\n          box-shadow: inset 0 0 3px rgba(200, 200, 200, 0.3);\n}\n.am-slider-a3 .am-control-nav li a:hover {\n  background-color: rgba(0, 0, 0, 0.7);\n}\n.am-slider-a3 .am-control-nav li a.am-active {\n  background: #0e90d2;\n  cursor: default;\n}\n.am-slider-a3 .am-direction-nav,\n.am-slider-a3 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: a4\n  */\n.am-slider-a4 {\n  margin-bottom: 30px;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Control Nav */\n}\n.am-slider-a4 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-a4 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-a4 .am-control-nav {\n  width: 100%;\n  position: absolute;\n  bottom: -15px;\n  text-align: center;\n  line-height: 0;\n}\n.am-slider-a4 .am-control-nav li {\n  margin: 0 6px;\n  display: inline-block;\n}\n.am-slider-a4 .am-control-nav li a {\n  width: 8px;\n  height: 8px;\n  display: block;\n  background-color: rgba(0, 0, 0, 0.5);\n  cursor: pointer;\n  text-indent: -9999px;\n  border-radius: 50%;\n  -webkit-box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);\n          box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);\n}\n.am-slider-a4 .am-control-nav li a:hover {\n  background-color: rgba(0, 0, 0, 0.7);\n}\n.am-slider-a4 .am-control-nav li a.am-active {\n  background-color: #0e90d2;\n  cursor: default;\n}\n.am-slider-a4 .am-direction-nav,\n.am-slider-a4 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: a5\n  */\n.am-slider-a5 {\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Control Nav */\n}\n.am-slider-a5 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-a5 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-a5 .am-control-nav {\n  width: 100%;\n  position: absolute;\n  text-align: center;\n  height: 6px;\n  display: table;\n  bottom: 0;\n  font-size: 0;\n  line-height: 0;\n}\n.am-slider-a5 .am-control-nav li {\n  display: table-cell;\n}\n.am-slider-a5 .am-control-nav li a {\n  width: 100%;\n  height: 6px;\n  display: block;\n  background-color: rgba(0, 0, 0, 0.5);\n  cursor: pointer;\n  text-indent: -9999px;\n}\n.am-slider-a5 .am-control-nav li a:hover {\n  background-color: rgba(0, 0, 0, 0.7);\n}\n.am-slider-a5 .am-control-nav li a.am-active {\n  background-color: #0e90d2;\n  cursor: default;\n}\n.am-slider-a5 .am-direction-nav,\n.am-slider-a5 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: b1\n  */\n.am-slider-b1 {\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Direction Nav */\n}\n.am-slider-b1 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-b1 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-b1 .am-direction-nav a {\n  -webkit-box-sizing: content-box;\n          box-sizing: content-box;\n  display: block;\n  width: 24px;\n  height: 24px;\n  padding: 8px 0;\n  margin: -20px 0 0;\n  position: absolute;\n  top: 50%;\n  z-index: 10;\n  overflow: hidden;\n  opacity: 0.45;\n  cursor: pointer;\n  color: #fff;\n  text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3);\n  background-color: rgba(0, 0, 0, 0.5);\n  font-size: 0;\n  text-align: center;\n  -webkit-transition: all .3s ease;\n  transition: all .3s ease;\n}\n.am-slider-b1 .am-direction-nav a:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f053\";\n  font-size: 24px;\n}\n.am-slider-b1 .am-direction-nav a.am-prev {\n  left: 0;\n  padding-right: 5px;\n  border-bottom-right-radius: 5px;\n  border-top-right-radius: 5px;\n}\n.am-slider-b1 .am-direction-nav a.am-next {\n  right: 0;\n  padding-left: 5px;\n  border-bottom-left-radius: 5px;\n  border-top-left-radius: 5px;\n}\n.am-slider-b1 .am-direction-nav a.am-next:before {\n  content: \"\\f054\";\n}\n.am-slider-b1 .am-direction-nav .am-disabled {\n  opacity: 0!important;\n  cursor: default;\n}\n.am-slider-b1:hover .am-prev {\n  opacity: 0.7;\n}\n.am-slider-b1:hover .am-prev:hover {\n  opacity: 1;\n}\n.am-slider-b1:hover .am-next {\n  opacity: 0.7;\n}\n.am-slider-b1:hover .am-next:hover {\n  opacity: 1;\n}\n.am-slider-b1 .am-control-nav,\n.am-slider-b1 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: b2\n  */\n.am-slider-b2 {\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Direction Nav */\n}\n.am-slider-b2 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-b2 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-b2 .am-direction-nav a {\n  -webkit-box-sizing: content-box;\n          box-sizing: content-box;\n  display: block;\n  width: 24px;\n  height: 24px;\n  padding: 4px;\n  margin: -16px 0 0;\n  position: absolute;\n  top: 50%;\n  z-index: 10;\n  overflow: hidden;\n  opacity: 0.45;\n  cursor: pointer;\n  color: #fff;\n  text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3);\n  background-color: rgba(0, 0, 0, 0.5);\n  font-size: 0;\n  text-align: center;\n  border-radius: 50%;\n  -webkit-transition: all .3s ease;\n  transition: all .3s ease;\n}\n.am-slider-b2 .am-direction-nav a:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f053\";\n  font-size: 16px;\n  line-height: 24px;\n}\n.am-slider-b2 .am-direction-nav a.am-prev {\n  left: 5px;\n}\n.am-slider-b2 .am-direction-nav a.am-next {\n  right: 5px;\n}\n.am-slider-b2 .am-direction-nav a.am-next:before {\n  content: \"\\f054\";\n}\n.am-slider-b2 .am-direction-nav .am-disabled {\n  opacity: 0!important;\n  cursor: default;\n}\n.am-slider-b2:hover .am-prev {\n  opacity: 0.7;\n}\n.am-slider-b2:hover .am-prev:hover {\n  opacity: 1;\n}\n.am-slider-b2:hover .am-next {\n  opacity: 0.7;\n}\n.am-slider-b2:hover .am-next:hover {\n  opacity: 1;\n}\n.am-slider-b2 .am-control-nav,\n.am-slider-b2 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: b3\n  */\n.am-slider-b3 {\n  margin: 15px 30px;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Direction Nav */\n}\n.am-slider-b3 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-b3 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-b3 .am-direction-nav a {\n  -webkit-box-sizing: content-box;\n          box-sizing: content-box;\n  display: block;\n  width: 24px;\n  height: 24px;\n  padding: 4px;\n  margin: -16px 0 0;\n  position: absolute;\n  top: 50%;\n  z-index: 10;\n  overflow: hidden;\n  opacity: 0.45;\n  cursor: pointer;\n  color: #333333;\n  text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3);\n  font-size: 0;\n  -webkit-transition: all .3s ease;\n  transition: all .3s ease;\n}\n.am-slider-b3 .am-direction-nav a:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f053\";\n  font-size: 24px;\n}\n.am-slider-b3 .am-direction-nav a.am-prev {\n  left: -25px;\n}\n.am-slider-b3 .am-direction-nav a.am-next {\n  right: -25px;\n  text-align: right;\n}\n.am-slider-b3 .am-direction-nav a.am-next:before {\n  content: \"\\f054\";\n}\n.am-slider-b3 .am-direction-nav .am-disabled {\n  opacity: 0!important;\n  cursor: default;\n}\n.am-slider-b3:hover .am-prev {\n  opacity: 0.7;\n}\n.am-slider-b3:hover .am-prev:hover {\n  opacity: 1;\n}\n.am-slider-b3:hover .am-next {\n  opacity: 0.7;\n}\n.am-slider-b3:hover .am-next:hover {\n  opacity: 1;\n}\n.am-slider-b3 .am-control-nav,\n.am-slider-b3 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: b4\n  */\n.am-slider-b4 {\n  margin: 15px 20px;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Direction Nav */\n}\n.am-slider-b4 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-b4 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-b4 .am-direction-nav a {\n  position: absolute;\n  top: 50%;\n  z-index: 10;\n  display: block;\n  -webkit-box-sizing: content-box;\n          box-sizing: content-box;\n  width: 24px;\n  height: 24px;\n  margin: -16px 0 0;\n  padding: 4px;\n  overflow: hidden;\n  opacity: 0.45;\n  background-color: rgba(0, 0, 0, 0.8);\n  cursor: pointer;\n  text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3);\n  font-size: 0;\n  border-radius: 50%;\n  text-align: center;\n  color: #fff;\n  -webkit-transition: all .3s ease;\n  transition: all .3s ease;\n}\n.am-slider-b4 .am-direction-nav a:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f053\";\n  font-size: 20px;\n  line-height: 24px;\n}\n.am-slider-b4 .am-direction-nav a.am-prev {\n  left: -15px;\n}\n.am-slider-b4 .am-direction-nav a.am-next {\n  right: -15px;\n}\n.am-slider-b4 .am-direction-nav a.am-next:before {\n  content: \"\\f054\";\n}\n.am-slider-b4 .am-direction-nav .am-disabled {\n  opacity: 0!important;\n  cursor: default;\n}\n.am-slider-b4:hover .am-prev {\n  opacity: 0.7;\n}\n.am-slider-b4:hover .am-prev:hover {\n  opacity: 0.9;\n}\n.am-slider-b4:hover .am-next {\n  opacity: 0.7;\n}\n.am-slider-b4:hover .am-next:hover {\n  opacity: 0.9;\n}\n.am-slider-b4 .am-control-nav,\n.am-slider-b4 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: c1\n  */\n.am-slider-c1 {\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Control Nav */\n}\n.am-slider-c1 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-c1 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-c1 .am-control-nav {\n  position: absolute;\n  bottom: 0;\n  display: table;\n  width: 100%;\n  height: 6px;\n  font-size: 0;\n  line-height: 0;\n  text-align: center;\n}\n.am-slider-c1 .am-control-nav li {\n  display: table-cell;\n  width: 1%;\n}\n.am-slider-c1 .am-control-nav li a {\n  width: 100%;\n  height: 6px;\n  display: block;\n  background-color: rgba(0, 0, 0, 0.7);\n  cursor: pointer;\n  text-indent: -9999px;\n}\n.am-slider-c1 .am-control-nav li a:hover {\n  background: rgba(0, 0, 0, 0.8);\n}\n.am-slider-c1 .am-control-nav li a.am-active {\n  background-color: #0e90d2;\n  cursor: default;\n}\n.am-slider-c1 .am-slider-desc {\n  background-color: rgba(0, 0, 0, 0.6);\n  position: absolute;\n  bottom: 6px;\n  padding: 8px;\n  width: 100%;\n  color: #fff;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-slider-c1 .am-direction-nav,\n.am-slider-c1 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: c2\n  */\n.am-slider-c2 {\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Control Nav */\n}\n.am-slider-c2 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-c2 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-c2 .am-control-nav {\n  position: absolute;\n  bottom: 15px;\n  right: 0;\n  height: 6px;\n  text-align: center;\n  font-size: 0;\n  line-height: 0;\n}\n.am-slider-c2 .am-control-nav li {\n  display: inline-block;\n  margin-right: 6px;\n}\n.am-slider-c2 .am-control-nav li a {\n  width: 6px;\n  height: 6px;\n  display: block;\n  background-color: rgba(255, 255, 255, 0.4);\n  cursor: pointer;\n  text-indent: -9999px;\n}\n.am-slider-c2 .am-control-nav li a:hover {\n  background: rgba(230, 230, 230, 0.4);\n}\n.am-slider-c2 .am-control-nav li a.am-active {\n  background-color: #0e90d2;\n  cursor: default;\n}\n.am-slider-c2 .am-slider-desc {\n  background-color: rgba(0, 0, 0, 0.6);\n  position: absolute;\n  bottom: 0;\n  padding: 8px 60px 8px 8px;\n  width: 100%;\n  color: #fff;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-slider-c2 .am-direction-nav,\n.am-slider-c2 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: c3\n  */\n.am-slider-c3 {\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Direction Nav */\n}\n.am-slider-c3 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-c3 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-c3 .am-slider-desc {\n  background-color: rgba(0, 0, 0, 0.6);\n  position: absolute;\n  bottom: 10px;\n  right: 60px;\n  height: 30px;\n  left: 0;\n  padding-right: 5px;\n  color: #fff;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-slider-c3 .am-slider-counter {\n  margin-right: 5px;\n  display: inline-block;\n  height: 30px;\n  background-color: #0e90d2;\n  width: 40px;\n  text-align: center;\n  line-height: 30px;\n  color: #eee;\n  font-size: 1rem;\n}\n.am-slider-c3 .am-slider-counter .am-active {\n  font-size: 1.8rem;\n  font-weight: bold;\n  color: #fff;\n}\n.am-slider-c3 .am-direction-nav a {\n  -webkit-box-sizing: content-box;\n          box-sizing: content-box;\n  display: block;\n  width: 24px;\n  height: 24px;\n  padding: 4px 0;\n  margin: -16px 0 0;\n  position: absolute;\n  top: 50%;\n  z-index: 10;\n  overflow: hidden;\n  opacity: 0.45;\n  cursor: pointer;\n  color: #fff;\n  text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3);\n  background-color: rgba(0, 0, 0, 0.5);\n  font-size: 0;\n  text-align: center;\n  -webkit-transition: all .3s ease;\n  transition: all .3s ease;\n}\n.am-slider-c3 .am-direction-nav a:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f053\";\n  font-size: 16px;\n  line-height: 24px;\n}\n.am-slider-c3 .am-direction-nav a.am-prev {\n  left: 0;\n  padding-right: 5px;\n}\n.am-slider-c3 .am-direction-nav a.am-next {\n  right: 0;\n  padding-left: 5px;\n}\n.am-slider-c3 .am-direction-nav a.am-next:before {\n  content: \"\\f054\";\n}\n.am-slider-c3 .am-direction-nav .am-disabled {\n  opacity: 0!important;\n  cursor: default;\n}\n.am-slider-c3:hover .am-prev {\n  opacity: 0.7;\n}\n.am-slider-c3:hover .am-prev:hover {\n  opacity: 1;\n}\n.am-slider-c3:hover .am-next {\n  opacity: 0.7;\n}\n.am-slider-c3:hover .am-next:hover {\n  opacity: 1;\n}\n.am-slider-c3 .am-control-nav,\n.am-slider-c3 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: c4\n  */\n.am-slider-c4 {\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Direction Nav */\n}\n.am-slider-c4 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-c4 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-c4 .am-slider-desc {\n  width: 100%;\n  background-color: rgba(0, 0, 0, 0.6);\n  position: absolute;\n  bottom: 0;\n  right: 0;\n  left: 0;\n  padding: 8px 40px;\n  color: #fff;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-slider-c4 .am-direction-nav a {\n  -webkit-box-sizing: content-box;\n          box-sizing: content-box;\n  display: block;\n  width: 24px;\n  height: 24px;\n  padding: 4px 0;\n  margin: 0;\n  position: absolute;\n  bottom: 4px;\n  z-index: 10;\n  overflow: hidden;\n  opacity: 0.45;\n  cursor: pointer;\n  text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3);\n  font-size: 0;\n  text-align: center;\n  color: rgba(0, 0, 0, 0.7);\n  -webkit-transition: all .3s ease;\n  transition: all .3s ease;\n}\n.am-slider-c4 .am-direction-nav a:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f053\";\n  font-size: 24px;\n}\n.am-slider-c4 .am-direction-nav a.am-prev {\n  left: 0;\n  padding-right: 5px;\n}\n.am-slider-c4 .am-direction-nav a.am-next {\n  right: 0;\n  padding-left: 5px;\n}\n.am-slider-c4 .am-direction-nav a.am-next:before {\n  content: \"\\f054\";\n}\n.am-slider-c4 .am-direction-nav .am-disabled {\n  opacity: 0!important;\n  cursor: default;\n}\n.am-slider-c4:hover .am-prev {\n  opacity: 0.7;\n}\n.am-slider-c4:hover .am-prev:hover {\n  opacity: 1;\n}\n.am-slider-c4:hover .am-next {\n  opacity: 0.7;\n}\n.am-slider-c4:hover .am-next:hover {\n  opacity: 1;\n}\n.am-slider-c4 .am-control-nav,\n.am-slider-c4 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: d1\n  */\n.am-slider-d1 {\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Direction Nav */\n}\n.am-slider-d1 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-d1 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-d1 .am-slider-desc {\n  padding: 8px 35px;\n  width: 100%;\n  color: #fff;\n  background-color: #0e90d2;\n}\n.am-slider-d1 .am-slider-title {\n  font-weight: normal;\n  margin-bottom: 2px;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-slider-d1 .am-slider-more {\n  color: #eeeeee;\n  font-size: 1.3rem;\n}\n.am-slider-d1 .am-direction-nav a {\n  -webkit-box-sizing: content-box;\n          box-sizing: content-box;\n  display: block;\n  width: 24px;\n  height: 24px;\n  margin: 0;\n  position: absolute;\n  bottom: 18px;\n  z-index: 10;\n  overflow: hidden;\n  opacity: 0.45;\n  cursor: pointer;\n  text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3);\n  font-size: 0;\n  text-align: center;\n  border: 1px solid rgba(255, 255, 255, 0.9);\n  color: rgba(255, 255, 255, 0.9);\n  border-radius: 50%;\n  -webkit-transition: all 03s ease;\n  transition: all 03s ease;\n}\n.am-slider-d1 .am-direction-nav a:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f053\";\n  font-size: 16px;\n  line-height: 24px;\n}\n.am-slider-d1 .am-direction-nav a.am-prev {\n  left: 5px;\n}\n.am-slider-d1 .am-direction-nav a.am-next {\n  right: 5px;\n}\n.am-slider-d1 .am-direction-nav a.am-next:before {\n  content: \"\\f054\";\n}\n.am-slider-d1 .am-direction-nav .am-disabled {\n  opacity: 0!important;\n  cursor: default;\n}\n.am-slider-d1:hover .am-prev {\n  opacity: 0.7;\n}\n.am-slider-d1:hover .am-prev:hover {\n  opacity: 1;\n}\n.am-slider-d1:hover .am-next {\n  opacity: 0.7;\n}\n.am-slider-d1:hover .am-next:hover {\n  opacity: 1;\n}\n.am-slider-d1 .am-control-nav,\n.am-slider-d1 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: d2\n  */\n.am-slider-d2 {\n  margin-bottom: 20px;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Control Nav */\n}\n.am-slider-d2 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-d2 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-d2 .am-slider-desc {\n  position: absolute;\n  left: 10px;\n  bottom: 20px;\n  right: 50px;\n  color: #fff;\n}\n.am-slider-d2 .am-slider-content {\n  background-color: rgba(0, 0, 0, 0.7);\n  padding: 10px 6px;\n  margin-bottom: 10px;\n}\n.am-slider-d2 .am-slider-content p {\n  margin: 0;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n  font-size: 1.4rem;\n}\n.am-slider-d2 .am-slider-title {\n  font-weight: normal;\n  margin-bottom: 5px;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-slider-d2 .am-slider-more {\n  color: #eeeeee;\n  font-size: 1.3rem;\n  background-color: #0e90d2;\n  padding: 2px 10px;\n}\n.am-slider-d2 .am-control-nav {\n  width: 100%;\n  position: absolute;\n  bottom: -15px;\n  text-align: center;\n}\n.am-slider-d2 .am-control-nav li {\n  margin: 0 6px;\n  display: inline-block;\n}\n.am-slider-d2 .am-control-nav li a {\n  width: 8px;\n  height: 8px;\n  display: block;\n  background-color: rgba(0, 0, 0, 0.5);\n  cursor: pointer;\n  text-indent: -9999px;\n  border-radius: 50%;\n  font-size: 0;\n  line-height: 0;\n  -webkit-box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);\n          box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);\n}\n.am-slider-d2 .am-control-nav li a:hover {\n  background: rgba(0, 0, 0, 0.5);\n}\n.am-slider-d2 .am-control-nav li a.am-active {\n  background: #0e90d2;\n  cursor: default;\n}\n.am-slider-d2 .am-direction-nav,\n.am-slider-d2 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: d3\n  */\n.am-slider-d3 {\n  margin-bottom: 10px;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Control Nav */\n}\n.am-slider-d3 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-d3 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-d3 .am-slider-desc {\n  position: absolute;\n  bottom: 0;\n  color: #fff;\n  width: 100%;\n  background-color: rgba(0, 0, 0, 0.7);\n  padding: 8px 5px;\n}\n.am-slider-d3 .am-slider-desc p {\n  margin: 0;\n  font-size: 1.3rem;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-slider-d3 .am-slider-title {\n  font-weight: normal;\n  margin-bottom: 5px;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-slider-d3 .am-control-thumbs {\n  position: static;\n  overflow: hidden;\n}\n.am-slider-d3 .am-control-thumbs li {\n  padding: 12px 4px 4px;\n  position: relative;\n}\n.am-slider-d3 .am-control-thumbs img {\n  width: 100%;\n  display: block;\n  opacity: .85;\n  cursor: pointer;\n}\n.am-slider-d3 .am-control-thumbs img:hover {\n  opacity: 1;\n}\n.am-slider-d3 .am-control-thumbs .am-active {\n  opacity: 1;\n  cursor: default;\n}\n.am-slider-d3 .am-control-thumbs .am-active + i {\n  position: absolute;\n  top: 0;\n  left: 50%;\n  content: \"\";\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: middle;\n  border-top: 8px solid rgba(0, 0, 0, 0.7);\n  border-right: 8px solid transparent;\n  border-left: 8px solid transparent;\n  border-bottom: 0 dotted;\n  -webkit-transform: rotate(360deg);\n      -ms-transform: rotate(360deg);\n          transform: rotate(360deg);\n  margin-left: -4px;\n  -webkit-transition: all 0.2s;\n  transition: all 0.2s;\n}\n.am-slider-d3 .am-direction-nav,\n.am-slider-d3 .am-pauseplay {\n  display: none;\n}\n.am-slider-d3 .am-control-thumbs {\n  display: table;\n}\n.am-slider-d3 .am-control-thumbs li {\n  display: table-cell;\n  width: 1%;\n}\n[data-am-widget='tabs'] {\n  margin: 10px;\n}\n[data-am-widget='tabs'] .am-tabs-nav {\n  width: 100%;\n  padding: 0;\n  margin: 0;\n  list-style: none;\n  text-align: center;\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -ms-flexbox;\n  display: flex;\n}\n[data-am-widget='tabs'] .am-tabs-nav li {\n  -webkit-box-flex: 1;\n  -webkit-flex: 1;\n      -ms-flex: 1;\n          flex: 1;\n}\n[data-am-widget='tabs'] .am-tabs-nav a {\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n/**\n  * Tabs Theme: default\n  */\n.am-tabs-default .am-tabs-nav {\n  line-height: 40px;\n  background-color: #eeeeee;\n}\n.am-tabs-default .am-tabs-nav a {\n  color: #222222;\n  line-height: 42px;\n}\n.am-tabs-default .am-tabs-nav > .am-active a {\n  background-color: #0e90d2;\n  color: #fff;\n}\n/**\n  * Tabs Theme: d2\n  */\n.am-tabs-d2 .am-tabs-nav {\n  background-color: #eeeeee;\n}\n.am-tabs-d2 .am-tabs-nav li {\n  height: 42px;\n}\n.am-tabs-d2 .am-tabs-nav a {\n  color: #222222;\n  line-height: 42px;\n}\n.am-tabs-d2 .am-tabs-nav > .am-active {\n  position: relative;\n  background-color: #fcfcfc;\n  border-bottom: 2px solid #0e90d2;\n}\n.am-tabs-d2 .am-tabs-nav > .am-active a {\n  line-height: 40px;\n  color: #0e90d2;\n}\n.am-tabs-d2 .am-tabs-nav > .am-active:after {\n  position: absolute;\n  width: 0;\n  height: 0;\n  bottom: 0px;\n  left: 50%;\n  margin-left: -5px;\n  border: 6px rgba(0, 0, 0, 0) solid;\n  content: \"\";\n  z-index: 1;\n  border-bottom-color: #0e90d2;\n}\n.am-titlebar {\n  margin-top: 20px;\n  height: 45px;\n  font-size: 100%;\n}\n.am-titlebar h2 {\n  margin-top: 0;\n  margin-bottom: 0;\n  font-size: 1.6rem;\n}\n.am-titlebar .am-titlebar-title img {\n  height: 24px;\n  width: auto;\n}\n/**\n  * Titlebar Theme: default\n  */\n.am-titlebar-default {\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -ms-flexbox;\n  display: flex;\n  margin-left: 10px;\n  margin-right: 10px;\n  background-color: transparent;\n  border-bottom: 1px solid #dedede;\n  line-height: 44px;\n}\n.am-titlebar-default a {\n  color: #0e90d2;\n}\n.am-titlebar-default .am-titlebar-title {\n  position: relative;\n  padding-left: 12px;\n  color: #0e90d2;\n  font-size: 1.8rem;\n  text-align: left;\n  font-weight: bold;\n}\n.am-titlebar-default .am-titlebar-title:before {\n  content: \"\";\n  position: absolute;\n  left: 2px;\n  top: 8px;\n  bottom: 8px;\n  border-left: 3px solid #0e90d2;\n}\n.am-titlebar-default .am-titlebar-nav {\n  -webkit-box-flex: 1;\n  -webkit-flex: 1;\n      -ms-flex: 1;\n          flex: 1;\n  text-align: right;\n}\n.am-titlebar-default .am-titlebar-nav a {\n  margin-right: 10px;\n}\n.am-titlebar-default .am-titlebar-nav a:last-child {\n  margin-right: 5px;\n}\n/**\n  * Titlebar Theme: multi\n  */\n.am-titlebar-multi {\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -ms-flexbox;\n  display: flex;\n  background-color: #f5f5f5;\n  border-top: 2px solid #3bb4f2;\n  border-bottom: 1px solid #e8e8e8;\n}\n.am-titlebar-multi a {\n  color: #0e90d2;\n}\n.am-titlebar-multi .am-titlebar-title {\n  padding-left: 10px;\n  color: #0e90d2;\n  font-size: 1.8rem;\n  text-align: left;\n  font-weight: bold;\n  line-height: 42px;\n}\n.am-titlebar-multi .am-titlebar-nav {\n  -webkit-box-flex: 1;\n  -webkit-flex: 1;\n      -ms-flex: 1;\n          flex: 1;\n  text-align: right;\n  line-height: 42px;\n}\n.am-titlebar-multi .am-titlebar-nav a {\n  margin-right: 10px;\n}\n/**\n  * Titlebar Theme: cols\n  */\n.am-titlebar-cols {\n  position: relative;\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -ms-flexbox;\n  display: flex;\n  padding-left: 10px;\n  background-color: #f5f5f5;\n  color: #555555;\n  font-size: 18px;\n  border-top: 2px solid #e1e1e1;\n  line-height: 41px;\n}\n.am-titlebar-cols a {\n  color: #555555;\n}\n.am-titlebar-cols .am-titlebar-title {\n  color: #0e90d2;\n  margin-right: 15px;\n  border-bottom: 2px solid #0e90d2;\n  font-weight: bold;\n}\n.am-titlebar-cols .am-titlebar-title a {\n  color: #0e90d2;\n}\n.am-titlebar-cols .am-titlebar-nav {\n  -webkit-box-flex: 1;\n  -webkit-flex: 1;\n      -ms-flex: 1;\n          flex: 1;\n}\n.am-titlebar-cols .am-titlebar-nav a {\n  display: inline-block;\n  margin-right: 15px;\n  line-height: 41px;\n  border-bottom: 2px solid transparent;\n}\n.am-titlebar-cols .am-titlebar-nav a:hover {\n  color: #3c3c3c;\n  border-bottom-color: #0e90d2;\n}\n.am-titlebar-cols .am-titlebar-nav a:last-child {\n  margin-right: 10px;\n}\n.am-wechatpay .am-wechatpay-btn {\n  margin-top: 1rem;\n  margin-bottom: 1rem;\n}\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/assets/css/app.css",
    "content": "/* Write your styles */\n/*html,body{background: #444444;}*/\n/* 登陆logo */\n.myapp-login {\n\n    overflow: auto;\n    top: 0;\n    bottom: 0;\n    left: 0;\n    right: 0;\n    height: 100%;\n    overflow: hidden;\n    width: 100%;\n\n\n}\n.myapp-login-logo-block { width: 100%;}\n.myapp-login-logo {width: 100%; text-align: center; padding-top: 30px;}\n.myapp-login-logo i { color: #eb602e; font-size: 120px;display: inline-block;}\n.myapp-login-logo-text {font-family: \"Lucida Grande\",Helvetica,Arial,\"Microsoft YaHei\",FreeSans,Arimo,\"Droid Sans\",\"wenquanyi micro hei\",\"Hiragino Sans GB\",\"Hiragino Sans GB W3\",FontAwesome,sans-serif;  color:#fff; font-weight: bold;font-size: 40px; margin-top: -40px; text-align: center; width: 100%;}\n.myapp-login-logo-text span {color: #eb602e;}\n.myapp-login-logo-text .info { padding-bottom: 30px; border-bottom: 1px solid #4d4d4d;font-family: FreeSans,Arimo,\"Droid Sans\",\"wenquanyi micro hei\",\"Hiragino Sans GB\",\"Hiragino Sans GB W3\",FontAwesome,sans-serif; width: 100%; font-weight: normal; font-size: 14px; color: #fff;}\n.login-font {font-size: 12px; font-family:\"wenquanyi micro hei\",\"Hiragino Sans GB\",\"Hiragino Sans GB W3\",FontAwesome,sans-serif; width: 100%; color: #5e5e5e; text-align: center; padding: 20px 0;}\n.login-font i {color: #eb602e; font-style: normal;}\n.login-font span { color: #fff;}\n.login-am-center { margin: 0 auto; float:none;}\n.login-am-center .am-form input { background: #565656; border: none;  font-size: 12px; line-height: 30px; text-indent: 10px;}\n.login-am-center .am-btn-default { width: 100%; background: #eb602e; border: none; color: #fff; font-size: 14px; line-height: 30px;}\n\n\n\nbody {\n    background-image: linear-gradient(-180deg, #1a1454 0%, #0e81a5 100%);\n    background-repeat: no-repeat;\n    background-size: cover;\n    margin: 0 auto;\n}\n\n.osc_git_box {\n     background-color: #fff;\n     margin-top: 20px;\n }\n\n\n\ncanvas {\n    z-index:-999;\n    position: fixed;\n    left: 0;\n    right: 0;\n    top: 0;\n    bottom: 0;\n}"
  },
  {
    "path": "open-layui-web/src/main/view/static/assets/css/login.css",
    "content": "/** EasyWeb */\n\nbody {\n    background-image: linear-gradient(-180deg, #1a1454 0%, #0e81a5 100%);\n    /*background-image: url(\"../images/bg_login.png\");*/\n    background-repeat: no-repeat;\n    background-size: cover;\n}\n\n.login-wrapper, body, html {\n    height: 100%;\n}\n\n\n.login-wrapper {\n    overflow: auto;\n    position: absolute;\n    top: 0;\n    bottom: 0;\n    left: 0;\n    right: 0;\n    height: 100%;\n    overflow: hidden;\n    width: 100%;\n}\n\n.login-body {\n    padding: 10px 10px 40px 10px;\n}\n\n\n\n.login-body > .layui-card {\n    max-width: 360px;\n    margin: 0 auto;\n}\n\n.login-body .layui-card-header {\n    font-weight: 700;\n    font-size: 15px;\n}\n\n.login-body .layui-form-pane .layui-form-label {\n    width: 48px;\n}\n\n.login-body .layui-form-pane .layui-input-block {\n    margin-left: 48px;\n}\n\n.login-body .login-captcha {\n    width: 100%;\n    cursor: pointer;\n}\n\n.login-body .login-other > * {\n    display: inline-block;\n    vertical-align: middle;\n    margin-right: 10px;\n    font-size: 14px;\n}\n\n.login-body .login-other .layui-icon {\n    position: relative;\n    top: 2px;\n    font-size: 26px;\n}\n\n.login-body .login-other a:hover {\n    opacity: .8;\n}\n\n.layui-icon-login-qq {\n    color: #3492ED\n}\n\n.layui-icon-login-wechat {\n    color: #4DAF29\n}\n\n.layui-icon-login-weibo {\n    color: #CF1900\n}\n\n/** 底部样式 */\n.login-footer {\n    text-align: center;\n    line-height: 30px;\n    color: rgba(255, 255, 255, 0.7) !important;\n    padding-bottom: 20px;\n}\n\n.login-footer span {\n    padding: 0 5px\n}\n\n.login-footer a {\n    padding: 0 5px;\n    color: rgba(255, 255, 255, 0.7) !important;\n}\n\n.login-footer a:hover {\n    color: rgba(255, 255, 255, 0.4) !important;\n}\n\n/** 头部样式 */\n.login-header {\n    font-size: 20px;\n    font-weight: bold;\n    color: rgba(255, 255, 255, 0.85) !important;\n    padding: 10px;\n}\n\n.login-header img {\n    height: 40px;\n}\n\n/** 移动设备样式 */\n@media screen and (min-height: 590px) {\n    .login-footer {\n        position: absolute;\n        bottom: 0;\n        width: 100%;\n    }\n}\n\n@media screen and (min-height: 670px) {\n    .login-body {\n        padding: 250px 10px 40px 10px;\n    }\n}\n\n/** 辅助样式 */\n.layui-link {\n    color: #029789 !important;\n}\n\n.layui-link:hover {\n    opacity: .8;\n}\n\n.pull-right {\n    float: right;\n}\n\n.inline-block {\n    display: inline-block;\n}\n\n.osc_git_box {\n    background-color: #fff;\n    margin-top: 20px;\n}\n\n\ncanvas {\n    /*position:relative;*/\n    z-index:-999;\n    position: fixed;\n    left: 0;\n    right: 0;\n    top: 0;\n    bottom: 0;\n}"
  },
  {
    "path": "open-layui-web/src/main/view/static/assets/js/amazeui.ie8polyfill.js",
    "content": "/*! Amaze UI v2.6.0 ~ IE8 Fucker | by Amaze UI Team | (c) 2016 AllMobilize, Inc. | Licensed under MIT | 2016-03-31T14:28:54+0800 */ \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/**\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.\nvar $Array = Array;\nvar ArrayPrototype = $Array.prototype;\nvar $Object = Object;\nvar ObjectPrototype = $Object.prototype;\nvar $Function = Function;\nvar FunctionPrototype = $Function.prototype;\nvar $String = String;\nvar StringPrototype = $String.prototype;\nvar $Number = Number;\nvar NumberPrototype = $Number.prototype;\nvar array_slice = ArrayPrototype.slice;\nvar array_splice = ArrayPrototype.splice;\nvar array_push = ArrayPrototype.push;\nvar array_unshift = ArrayPrototype.unshift;\nvar array_concat = ArrayPrototype.concat;\nvar array_join = ArrayPrototype.join;\nvar call = FunctionPrototype.call;\nvar apply = FunctionPrototype.apply;\nvar max = Math.max;\nvar min = Math.min;\n\n// Having a toString local variable name breaks in Opera so use to_string.\nvar to_string = ObjectPrototype.toString;\n\n/* global Symbol */\n/* eslint-disable one-var-declaration-per-line, no-redeclare */\nvar hasToStringTag = typeof Symbol === 'function' && typeof Symbol.toStringTag === 'symbol';\nvar 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\nvar 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; };\nvar 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 */\n\n/* inlined from http://npmjs.com/define-properties */\nvar supportsDescriptors = $Object.defineProperty && (function () {\n    try {\n        var obj = {};\n        $Object.defineProperty(obj, 'x', { enumerable: false, value: obj });\n        for (var _ in obj) { return false; }\n        return obj.x === obj;\n    } catch (e) { /* this is ES3 */\n        return false;\n    }\n}());\nvar 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)) { return; }\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)) { return; }\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 */\nvar isPrimitive = function isPrimitive(input) {\n    var type = typeof input;\n    return input === null || (type !== 'object' && type !== 'function');\n};\n\nvar isActualNaN = $Number.isNaN || function (x) { return x !== x; };\n\nvar 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\nvar Empty = function Empty() {};\n\ndefineProperties(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.\nvar owns = call.bind(ObjectPrototype.hasOwnProperty);\nvar toStr = call.bind(ObjectPrototype.toString);\nvar arraySlice = call.bind(array_slice);\nvar arraySliceApply = apply.bind(array_slice);\nvar strSlice = call.bind(StringPrototype.slice);\nvar strSplit = call.bind(StringPrototype.split);\nvar strIndexOf = call.bind(StringPrototype.indexOf);\nvar pushCall = call.bind(array_push);\nvar isEnum = call.bind(ObjectPrototype.propertyIsEnumerable);\nvar arraySort = call.bind(ArrayPrototype.sort);\n\n//\n// Array\n// =====\n//\n\nvar 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\"\nvar hasUnshiftReturnValueBug = [].unshift(0) !== 1;\ndefineProperties(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\ndefineProperties($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)\nvar boxedString = $Object('a');\nvar splitString = boxedString[0] !== 'a' || !(0 in boxedString);\n\nvar 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') { properlyBoxesNonStrict = false; }\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\ndefineProperties(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\ndefineProperties(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\ndefineProperties(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\ndefineProperties(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\ndefineProperties(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\nvar reduceCoercesToObject = false;\nif (ArrayPrototype.reduce) {\n    reduceCoercesToObject = typeof ArrayPrototype.reduce.call('es5', function (_, __, ___, list) { return list; }) === 'object';\n}\ndefineProperties(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\nvar reduceRightCoercesToObject = false;\nif (ArrayPrototype.reduceRight) {\n    reduceRightCoercesToObject = typeof ArrayPrototype.reduceRight.call('es5', function (_, __, ___, list) { return list; }) === 'object';\n}\ndefineProperties(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\nvar hasFirefox2IndexOfBug = ArrayPrototype.indexOf && [0, 1].indexOf(1, 2) !== -1;\ndefineProperties(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\nvar hasFirefox2LastIndexOfBug = ArrayPrototype.lastIndexOf && [0, 1].lastIndexOf(0, -3) !== -1;\ndefineProperties(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\nvar spliceNoopReturnsEmptyArray = (function () {\n    var a = [1, 2];\n    var result = a.splice();\n    return a.length === 2 && isArray(result) && result.length === 0;\n}());\ndefineProperties(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\nvar spliceWorksWithEmptyObject = (function () {\n    var obj = {};\n    ArrayPrototype.splice.call(obj, 0, 0, 1);\n    return obj.length === 1;\n}());\ndefineProperties(ArrayPrototype, {\n    splice: function splice(start, deleteCount) {\n        if (arguments.length === 0) { return []; }\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);\nvar 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}());\nvar 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}());\ndefineProperties(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\nvar originalJoin = ArrayPrototype.join;\nvar hasStringJoinBug;\ntry {\n    hasStringJoinBug = Array.prototype.join.call('123', ',') !== '1,2,3';\n} catch (e) {\n    hasStringJoinBug = true;\n}\nif (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\nvar hasJoinUndefinedBug = [1, 2].join(undefined) !== '1,2';\nif (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\nvar 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\nvar 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}());\ndefineProperties(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\nvar 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}());\ndefineProperties(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\ndefineProperties(ArrayPrototype, {\n    slice: function (start, end) {\n        var arr = isString(this) ? strSplit(this, '') : this;\n        return arraySliceApply(arr, arguments);\n    }\n}, splitString);\n\nvar sortIgnoresNonFunctions = (function () {\n    try {\n        [1, 2].sort(null);\n        [1, 2].sort({});\n        return true;\n    } catch (e) { /**/ }\n    return false;\n}());\nvar 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}());\nvar 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}());\ndefineProperties(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\nvar hasDontEnumBug = !({ 'toString': null }).propertyIsEnumerable('toString');\nvar hasProtoEnumBug = function () {}.propertyIsEnumerable('prototype');\nvar hasStringEnumBug = !owns('x', '0');\nvar equalsConstructorPrototype = function (o) {\n    var ctor = o.constructor;\n    return ctor && ctor.prototype === o;\n};\nvar 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};\nvar hasAutomationEqualityBug = (function () {\n    /* globals window */\n    if (typeof window === 'undefined') { return false; }\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}());\nvar equalsConstructorPrototypeIfNotBuggy = function (object) {\n    if (typeof window === 'undefined' || !hasAutomationEqualityBug) { return equalsConstructorPrototype(object); }\n    try {\n        return equalsConstructorPrototype(object);\n    } catch (e) {\n        return false;\n    }\n};\nvar dontEnums = [\n    'toString',\n    'toLocaleString',\n    'valueOf',\n    'hasOwnProperty',\n    'isPrototypeOf',\n    'propertyIsEnumerable',\n    'constructor'\n];\nvar 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\nvar isStandardArguments = function isArguments(value) {\n    return toStr(value) === '[object Arguments]';\n};\nvar 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};\nvar isArguments = isStandardArguments(arguments) ? isStandardArguments : isLegacyArguments;\n\ndefineProperties($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\nvar keysWorksWithArguments = $Object.keys && (function () {\n    // Safari 5.0 bug\n    return $Object.keys(arguments).length === 2;\n}(1, 2));\nvar keysHasArgumentsLengthBug = $Object.keys && (function () {\n    var argKeys = $Object.keys(arguments);\n    return arguments.length !== 1 || argKeys.length !== 1 || argKeys[0] !== 1;\n}(1));\nvar originalKeys = $Object.keys;\ndefineProperties($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\nvar hasNegativeMonthYearBug = new Date(-3509827329600292).getUTCMonth() !== 0;\nvar aNegativeTestDate = new Date(-1509842289600292);\nvar aPositiveTestDate = new Date(1449662400000);\nvar hasToUTCStringFormatBug = aNegativeTestDate.toUTCString() !== 'Mon, 01 Jan -45875 11:59:59 GMT';\nvar hasToDateStringFormatBug;\nvar hasToStringFormatBug;\nvar timeZoneOffset = aNegativeTestDate.getTimezoneOffset();\nif (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\nvar originalGetFullYear = call.bind(Date.prototype.getFullYear);\nvar originalGetMonth = call.bind(Date.prototype.getMonth);\nvar originalGetDate = call.bind(Date.prototype.getDate);\nvar originalGetUTCFullYear = call.bind(Date.prototype.getUTCFullYear);\nvar originalGetUTCMonth = call.bind(Date.prototype.getUTCMonth);\nvar originalGetUTCDate = call.bind(Date.prototype.getUTCDate);\nvar originalGetUTCDay = call.bind(Date.prototype.getUTCDay);\nvar originalGetUTCHours = call.bind(Date.prototype.getUTCHours);\nvar originalGetUTCMinutes = call.bind(Date.prototype.getUTCMinutes);\nvar originalGetUTCSeconds = call.bind(Date.prototype.getUTCSeconds);\nvar originalGetUTCMilliseconds = call.bind(Date.prototype.getUTCMilliseconds);\nvar dayName = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];\nvar monthName = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];\nvar daysInMonth = function daysInMonth(month, year) {\n    return originalGetDate(new Date(year, month, 0));\n};\n\ndefineProperties(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\ndefineProperties(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 `,`\ndefineProperties(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\nif (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.\nvar negativeDate = -62198755200000;\nvar negativeYearString = '-000001';\nvar hasNegativeDateBug = Date.prototype.toISOString && new Date(negativeDate).toISOString().indexOf(negativeYearString) === -1;\nvar hasSafari51DateBug = Date.prototype.toISOString && new Date(-1).toISOString() !== '1969-12-31T23:59:59.999Z';\n\nvar getTime = call.bind(Date.prototype.getTime);\n\ndefineProperties(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).\nvar 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}());\nif (!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\nvar supportsExtendedYears = Date.parse('+033658-09-27T01:46:40.000Z') === 1e15;\nvar 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'));\nvar doesNotParseY2KNewYear = isNaN(Date.parse('2000-01-01T00:00:00.000Z'));\nif (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\nif (!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\nvar 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\nvar 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\nvar 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};\ndefineProperties(NumberPrototype, { toFixed: toFixedShim }, hasToFixedBugs);\n\nvar hasToPrecisionUndefinedBug = (function () {\n    try {\n        return 1.0.toPrecision(undefined) === '1';\n    } catch (e) {\n        return true;\n    }\n}());\nvar originalToPrecision = NumberPrototype.toPrecision;\ndefineProperties(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\nif (\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) { return []; }\n        return strSplit(this, separator, limit);\n    };\n}\n\nvar str_replace = StringPrototype.replace;\nvar 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\nif (!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\nvar string_substr = StringPrototype.substr;\nvar hasNegativeSubstrBug = ''.substr && '0b'.substr(-1) !== 'b';\ndefineProperties(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\nvar 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';\nvar zeroWidth = '\\u200b';\nvar wsRegexChars = '[' + ws + ']';\nvar trimBeginRegexp = new RegExp('^' + wsRegexChars + wsRegexChars + '*');\nvar trimEndRegexp = new RegExp(wsRegexChars + wsRegexChars + '*$');\nvar hasTrimWhitespaceBug = StringPrototype.trim && (ws.trim() || !zeroWidth.trim());\ndefineProperties(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);\nvar trim = call.bind(String.prototype.trim);\n\nvar hasLastIndexBug = StringPrototype.lastIndexOf && 'abcあい'.lastIndexOf('あい', 2) !== -1;\ndefineProperties(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\nvar originalLastIndexOf = StringPrototype.lastIndexOf;\ndefineProperties(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 */\nif (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(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\nif (1 / parseFloat('-0') !== -Infinity) {\n    /* global parseFloat: true */\n    parseFloat = (function (origParseFloat) {\n        return function parseFloat(string) {\n            var inputString = trim(string);\n            var result = origParseFloat(inputString);\n            return result === 0 && strSlice(inputString, 0, 1) === '-' ? -0 : result;\n        };\n    }(parseFloat));\n}\n\nif (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\nif (supportsDescriptors) {\n    var ensureNonEnumerable = function (obj, prop) {\n        if (isEnum(obj, prop)) {\n            var desc = Object.getOwnPropertyDescriptor(obj, prop);\n            desc.enumerable = false;\n            Object.defineProperty(obj, prop, desc);\n        }\n    };\n    ensureNonEnumerable(Error.prototype, 'message');\n    if (Error.prototype.message !== '') {\n      Error.prototype.message = '';\n    }\n    ensureNonEnumerable(Error.prototype, 'name');\n}\n\nif (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\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\nvar call = Function.call;\nvar prototypeOfObject = Object.prototype;\nvar owns = call.bind(prototypeOfObject.hasOwnProperty);\nvar isEnumerable = call.bind(prototypeOfObject.propertyIsEnumerable);\nvar toStr = call.bind(prototypeOfObject.toString);\n\n// If JS engine supports accessors creating shortcuts.\nvar defineGetter;\nvar defineSetter;\nvar lookupGetter;\nvar lookupSetter;\nvar supportsAccessors = owns(prototypeOfObject, '__defineGetter__');\nif (supportsAccessors) {\n    /* eslint-disable no-underscore-dangle */\n    defineGetter = call.bind(prototypeOfObject.__defineGetter__);\n    defineSetter = call.bind(prototypeOfObject.__defineSetter__);\n    lookupGetter = call.bind(prototypeOfObject.__lookupGetter__);\n    lookupSetter = call.bind(prototypeOfObject.__lookupSetter__);\n    /* eslint-enable no-underscore-dangle */\n}\n\n// ES5 15.2.3.2\n// http://es5.github.com/#x15.2.3.2\nif (!Object.getPrototypeOf) {\n    // https://github.com/es-shims/es5-shim/issues#issue/2\n    // http://ejohn.org/blog/objectgetprototypeof/\n    // recommended by fschaefer on github\n    //\n    // sure, and webreflection says ^_^\n    // ... this will nerever possibly return null\n    // ... Opera Mini breaks here with infinite loops\n    Object.getPrototypeOf = function getPrototypeOf(object) {\n        /* eslint-disable no-proto */\n        var proto = object.__proto__;\n        /* eslint-enable no-proto */\n        if (proto || proto === null) {\n            return proto;\n        } else if (toStr(object.constructor) === '[object Function]') {\n            return object.constructor.prototype;\n        } else if (object instanceof Object) {\n          return prototypeOfObject;\n        } else {\n          // Correctly return null for Objects created with `Object.create(null)`\n          // (shammed or native) or `{ __proto__: null}`.  Also returns null for\n          // cross-realm objects on browsers that lack `__proto__` support (like\n          // IE <11), but that's the best we can do.\n          return null;\n        }\n    };\n}\n\n// ES5 15.2.3.3\n// http://es5.github.com/#x15.2.3.3\n\nvar doesGetOwnPropertyDescriptorWork = function doesGetOwnPropertyDescriptorWork(object) {\n    try {\n        object.sentinel = 0;\n        return Object.getOwnPropertyDescriptor(object, 'sentinel').value === 0;\n    } catch (exception) {\n        return false;\n    }\n};\n\n// check whether getOwnPropertyDescriptor works if it's given. Otherwise, shim partially.\nif (Object.defineProperty) {\n    var getOwnPropertyDescriptorWorksOnObject = doesGetOwnPropertyDescriptorWork({});\n    var getOwnPropertyDescriptorWorksOnDom = typeof document === 'undefined' ||\n    doesGetOwnPropertyDescriptorWork(document.createElement('div'));\n    if (!getOwnPropertyDescriptorWorksOnDom || !getOwnPropertyDescriptorWorksOnObject) {\n        var getOwnPropertyDescriptorFallback = Object.getOwnPropertyDescriptor;\n    }\n}\n\nif (!Object.getOwnPropertyDescriptor || getOwnPropertyDescriptorFallback) {\n    var ERR_NON_OBJECT = 'Object.getOwnPropertyDescriptor called on a non-object: ';\n\n    /* eslint-disable no-proto */\n    Object.getOwnPropertyDescriptor = function getOwnPropertyDescriptor(object, property) {\n        if ((typeof object !== 'object' && typeof object !== 'function') || object === null) {\n            throw new TypeError(ERR_NON_OBJECT + object);\n        }\n\n        // make a valiant attempt to use the real getOwnPropertyDescriptor\n        // for I8's DOM elements.\n        if (getOwnPropertyDescriptorFallback) {\n            try {\n                return getOwnPropertyDescriptorFallback.call(Object, object, property);\n            } catch (exception) {\n                // try the shim if the real one doesn't work\n            }\n        }\n\n        var descriptor;\n\n        // If object does not owns property return undefined immediately.\n        if (!owns(object, property)) {\n            return descriptor;\n        }\n\n        // If object has a property then it's for sure `configurable`, and\n        // probably `enumerable`. Detect enumerability though.\n        descriptor = {\n            enumerable: isEnumerable(object, property),\n            configurable: true\n        };\n\n        // If JS engine supports accessor properties then property may be a\n        // getter or setter.\n        if (supportsAccessors) {\n            // Unfortunately `__lookupGetter__` will return a getter even\n            // if object has own non getter property along with a same named\n            // inherited getter. To avoid misbehavior we temporary remove\n            // `__proto__` so that `__lookupGetter__` will return getter only\n            // if it's owned by an object.\n            var prototype = object.__proto__;\n            var notPrototypeOfObject = object !== prototypeOfObject;\n            // avoid recursion problem, breaking in Opera Mini when\n            // Object.getOwnPropertyDescriptor(Object.prototype, 'toString')\n            // or any other Object.prototype accessor\n            if (notPrototypeOfObject) {\n                object.__proto__ = prototypeOfObject;\n            }\n\n            var getter = lookupGetter(object, property);\n            var setter = lookupSetter(object, property);\n\n            if (notPrototypeOfObject) {\n                // Once we have getter and setter we can put values back.\n                object.__proto__ = prototype;\n            }\n\n            if (getter || setter) {\n                if (getter) {\n                    descriptor.get = getter;\n                }\n                if (setter) {\n                    descriptor.set = setter;\n                }\n                // If it was accessor property we're done and return here\n                // in order to avoid adding `value` to the descriptor.\n                return descriptor;\n            }\n        }\n\n        // If we got this far we know that object has an own property that is\n        // not an accessor so we set it as a value and return descriptor.\n        descriptor.value = object[property];\n        descriptor.writable = true;\n        return descriptor;\n    };\n    /* eslint-enable no-proto */\n}\n\n// ES5 15.2.3.4\n// http://es5.github.com/#x15.2.3.4\nif (!Object.getOwnPropertyNames) {\n    Object.getOwnPropertyNames = function getOwnPropertyNames(object) {\n        return Object.keys(object);\n    };\n}\n\n// ES5 15.2.3.5\n// http://es5.github.com/#x15.2.3.5\nif (!Object.create) {\n\n    // Contributed by Brandon Benvie, October, 2012\n    var createEmpty;\n    var supportsProto = !({ __proto__: null } instanceof Object);\n                        // the following produces false positives\n                        // in Opera Mini => not a reliable check\n                        // Object.prototype.__proto__ === null\n\n    // Check for document.domain and active x support\n    // No need to use active x approach when document.domain is not set\n    // see https://github.com/es-shims/es5-shim/issues/150\n    // variation of https://github.com/kitcambridge/es5-shim/commit/4f738ac066346\n    /* global ActiveXObject */\n    var shouldUseActiveX = function shouldUseActiveX() {\n        // return early if document.domain not set\n        if (!document.domain) {\n            return false;\n        }\n\n        try {\n            return !!new ActiveXObject('htmlfile');\n        } catch (exception) {\n            return false;\n        }\n    };\n\n    // This supports IE8 when document.domain is used\n    // see https://github.com/es-shims/es5-shim/issues/150\n    // variation of https://github.com/kitcambridge/es5-shim/commit/4f738ac066346\n    var getEmptyViaActiveX = function getEmptyViaActiveX() {\n        var empty;\n        var xDoc;\n\n        xDoc = new ActiveXObject('htmlfile');\n\n        xDoc.write('<script><\\/script>');\n        xDoc.close();\n\n        empty = xDoc.parentWindow.Object.prototype;\n        xDoc = null;\n\n        return empty;\n    };\n\n    // The original implementation using an iframe\n    // before the activex approach was added\n    // see https://github.com/es-shims/es5-shim/issues/150\n    var getEmptyViaIFrame = function getEmptyViaIFrame() {\n        var iframe = document.createElement('iframe');\n        var parent = document.body || document.documentElement;\n        var empty;\n\n        iframe.style.display = 'none';\n        parent.appendChild(iframe);\n        /* eslint-disable no-script-url */\n        iframe.src = 'javascript:';\n        /* eslint-enable no-script-url */\n\n        empty = iframe.contentWindow.Object.prototype;\n        parent.removeChild(iframe);\n        iframe = null;\n\n        return empty;\n    };\n\n    /* global document */\n    if (supportsProto || typeof document === 'undefined') {\n        createEmpty = function () {\n            return { __proto__: null };\n        };\n    } else {\n        // In old IE __proto__ can't be used to manually set `null`, nor does\n        // any other method exist to make an object that inherits from nothing,\n        // aside from Object.prototype itself. Instead, create a new global\n        // object and *steal* its Object.prototype and strip it bare. This is\n        // used as the prototype to create nullary objects.\n        createEmpty = function () {\n            // Determine which approach to use\n            // see https://github.com/es-shims/es5-shim/issues/150\n            var empty = shouldUseActiveX() ? getEmptyViaActiveX() : getEmptyViaIFrame();\n\n            delete empty.constructor;\n            delete empty.hasOwnProperty;\n            delete empty.propertyIsEnumerable;\n            delete empty.isPrototypeOf;\n            delete empty.toLocaleString;\n            delete empty.toString;\n            delete empty.valueOf;\n\n            var Empty = function Empty() {};\n            Empty.prototype = empty;\n            // short-circuit future calls\n            createEmpty = function () {\n                return new Empty();\n            };\n            return new Empty();\n        };\n    }\n\n    Object.create = function create(prototype, properties) {\n\n        var object;\n        var Type = function Type() {}; // An empty constructor.\n\n        if (prototype === null) {\n            object = createEmpty();\n        } else {\n            if (typeof prototype !== 'object' && typeof prototype !== 'function') {\n                // In the native implementation `parent` can be `null`\n                // OR *any* `instanceof Object`  (Object|Function|Array|RegExp|etc)\n                // Use `typeof` tho, b/c in old IE, DOM elements are not `instanceof Object`\n                // like they are in modern browsers. Using `Object.create` on DOM elements\n                // is...err...probably inappropriate, but the native version allows for it.\n                throw new TypeError('Object prototype may only be an Object or null'); // same msg as Chrome\n            }\n            Type.prototype = prototype;\n            object = new Type();\n            // IE has no built-in implementation of `Object.getPrototypeOf`\n            // neither `__proto__`, but this manually setting `__proto__` will\n            // guarantee that `Object.getPrototypeOf` will work as expected with\n            // objects created using `Object.create`\n            /* eslint-disable no-proto */\n            object.__proto__ = prototype;\n            /* eslint-enable no-proto */\n        }\n\n        if (properties !== void 0) {\n            Object.defineProperties(object, properties);\n        }\n\n        return object;\n    };\n}\n\n// ES5 15.2.3.6\n// http://es5.github.com/#x15.2.3.6\n\n// Patch for WebKit and IE8 standard mode\n// Designed by hax <hax.github.com>\n// related issue: https://github.com/es-shims/es5-shim/issues#issue/5\n// IE8 Reference:\n//     http://msdn.microsoft.com/en-us/library/dd282900.aspx\n//     http://msdn.microsoft.com/en-us/library/dd229916.aspx\n// WebKit Bugs:\n//     https://bugs.webkit.org/show_bug.cgi?id=36423\n\nvar doesDefinePropertyWork = function doesDefinePropertyWork(object) {\n    try {\n        Object.defineProperty(object, 'sentinel', {});\n        return 'sentinel' in object;\n    } catch (exception) {\n        return false;\n    }\n};\n\n// check whether defineProperty works if it's given. Otherwise,\n// shim partially.\nif (Object.defineProperty) {\n    var definePropertyWorksOnObject = doesDefinePropertyWork({});\n    var definePropertyWorksOnDom = typeof document === 'undefined' ||\n        doesDefinePropertyWork(document.createElement('div'));\n    if (!definePropertyWorksOnObject || !definePropertyWorksOnDom) {\n        var definePropertyFallback = Object.defineProperty,\n            definePropertiesFallback = Object.defineProperties;\n    }\n}\n\nif (!Object.defineProperty || definePropertyFallback) {\n    var ERR_NON_OBJECT_DESCRIPTOR = 'Property description must be an object: ';\n    var ERR_NON_OBJECT_TARGET = 'Object.defineProperty called on non-object: ';\n    var ERR_ACCESSORS_NOT_SUPPORTED = 'getters & setters can not be defined on this javascript engine';\n\n    Object.defineProperty = function defineProperty(object, property, descriptor) {\n        if ((typeof object !== 'object' && typeof object !== 'function') || object === null) {\n            throw new TypeError(ERR_NON_OBJECT_TARGET + object);\n        }\n        if ((typeof descriptor !== 'object' && typeof descriptor !== 'function') || descriptor === null) {\n            throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR + descriptor);\n        }\n        // make a valiant attempt to use the real defineProperty\n        // for I8's DOM elements.\n        if (definePropertyFallback) {\n            try {\n                return definePropertyFallback.call(Object, object, property, descriptor);\n            } catch (exception) {\n                // try the shim if the real one doesn't work\n            }\n        }\n\n        // If it's a data property.\n        if ('value' in descriptor) {\n            // fail silently if 'writable', 'enumerable', or 'configurable'\n            // are requested but not supported\n            /*\n            // alternate approach:\n            if ( // can't implement these features; allow false but not true\n                ('writable' in descriptor && !descriptor.writable) ||\n                ('enumerable' in descriptor && !descriptor.enumerable) ||\n                ('configurable' in descriptor && !descriptor.configurable)\n            ))\n                throw new RangeError(\n                    'This implementation of Object.defineProperty does not support configurable, enumerable, or writable.'\n                );\n            */\n\n            if (supportsAccessors && (lookupGetter(object, property) || lookupSetter(object, property))) {\n                // As accessors are supported only on engines implementing\n                // `__proto__` we can safely override `__proto__` while defining\n                // a property to make sure that we don't hit an inherited\n                // accessor.\n                /* eslint-disable no-proto */\n                var prototype = object.__proto__;\n                object.__proto__ = prototypeOfObject;\n                // Deleting a property anyway since getter / setter may be\n                // defined on object itself.\n                delete object[property];\n                object[property] = descriptor.value;\n                // Setting original `__proto__` back now.\n                object.__proto__ = prototype;\n                /* eslint-enable no-proto */\n            } else {\n                object[property] = descriptor.value;\n            }\n        } else {\n            if (!supportsAccessors && (('get' in descriptor) || ('set' in descriptor))) {\n                throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED);\n            }\n            // If we got that far then getters and setters can be defined !!\n            if ('get' in descriptor) {\n                defineGetter(object, property, descriptor.get);\n            }\n            if ('set' in descriptor) {\n                defineSetter(object, property, descriptor.set);\n            }\n        }\n        return object;\n    };\n}\n\n// ES5 15.2.3.7\n// http://es5.github.com/#x15.2.3.7\nif (!Object.defineProperties || definePropertiesFallback) {\n    Object.defineProperties = function defineProperties(object, properties) {\n        // make a valiant attempt to use the real defineProperties\n        if (definePropertiesFallback) {\n            try {\n                return definePropertiesFallback.call(Object, object, properties);\n            } catch (exception) {\n                // try the shim if the real one doesn't work\n            }\n        }\n\n        Object.keys(properties).forEach(function (property) {\n            if (property !== '__proto__') {\n                Object.defineProperty(object, property, properties[property]);\n            }\n        });\n        return object;\n    };\n}\n\n// ES5 15.2.3.8\n// http://es5.github.com/#x15.2.3.8\nif (!Object.seal) {\n    Object.seal = function seal(object) {\n        if (Object(object) !== object) {\n            throw new TypeError('Object.seal can only be called on Objects.');\n        }\n        // this is misleading and breaks feature-detection, but\n        // allows \"securable\" code to \"gracefully\" degrade to working\n        // but insecure code.\n        return object;\n    };\n}\n\n// ES5 15.2.3.9\n// http://es5.github.com/#x15.2.3.9\nif (!Object.freeze) {\n    Object.freeze = function freeze(object) {\n        if (Object(object) !== object) {\n            throw new TypeError('Object.freeze can only be called on Objects.');\n        }\n        // this is misleading and breaks feature-detection, but\n        // allows \"securable\" code to \"gracefully\" degrade to working\n        // but insecure code.\n        return object;\n    };\n}\n\n// detect a Rhino bug and patch it\ntry {\n    Object.freeze(function () {});\n} catch (exception) {\n    Object.freeze = (function (freezeObject) {\n        return function freeze(object) {\n            if (typeof object === 'function') {\n                return object;\n            } else {\n                return freezeObject(object);\n            }\n        };\n    }(Object.freeze));\n}\n\n// ES5 15.2.3.10\n// http://es5.github.com/#x15.2.3.10\nif (!Object.preventExtensions) {\n    Object.preventExtensions = function preventExtensions(object) {\n        if (Object(object) !== object) {\n            throw new TypeError('Object.preventExtensions can only be called on Objects.');\n        }\n        // this is misleading and breaks feature-detection, but\n        // allows \"securable\" code to \"gracefully\" degrade to working\n        // but insecure code.\n        return object;\n    };\n}\n\n// ES5 15.2.3.11\n// http://es5.github.com/#x15.2.3.11\nif (!Object.isSealed) {\n    Object.isSealed = function isSealed(object) {\n        if (Object(object) !== object) {\n            throw new TypeError('Object.isSealed can only be called on Objects.');\n        }\n        return false;\n    };\n}\n\n// ES5 15.2.3.12\n// http://es5.github.com/#x15.2.3.12\nif (!Object.isFrozen) {\n    Object.isFrozen = function isFrozen(object) {\n        if (Object(object) !== object) {\n            throw new TypeError('Object.isFrozen can only be called on Objects.');\n        }\n        return false;\n    };\n}\n\n// ES5 15.2.3.13\n// http://es5.github.com/#x15.2.3.13\nif (!Object.isExtensible) {\n    Object.isExtensible = function isExtensible(object) {\n        // 1. If Type(O) is not Object throw a TypeError exception.\n        if (Object(object) !== object) {\n            throw new TypeError('Object.isExtensible can only be called on Objects.');\n        }\n        // 2. Return the Boolean value of the [[Extensible]] internal property of O.\n        var name = '';\n        while (owns(object, name)) {\n            name += '?';\n        }\n        object[name] = true;\n        var returnValue = owns(object, name);\n        delete object[name];\n        return returnValue;\n    };\n}\n\n}));\n\n// Console-polyfill. MIT license.\n// https://github.com/paulmillr/console-polyfill\n// Make it safe to do console.log() always.\n(function(global) {\n  'use strict';\n  global.console = global.console || {};\n  var con = global.console;\n  var prop, method;\n  var empty = {};\n  var dummy = function() {};\n  var properties = 'memory'.split(',');\n  var methods = ('assert,clear,count,debug,dir,dirxml,error,exception,group,' +\n  'groupCollapsed,groupEnd,info,log,markTimeline,profile,profiles,profileEnd,' +\n  'show,table,time,timeEnd,timeline,timelineEnd,timeStamp,trace,warn').split(',');\n  while (prop = properties.pop()) if (!con[prop]) con[prop] = empty;\n  while (method = methods.pop()) if (typeof con[method] !== 'function') con[method] = dummy;\n  // Using `this` for web workers & supports Browserify / Webpack.\n})(typeof window === 'undefined' ? this : window);\n\n!window.addEventListener && (function (WindowPrototype, DocumentPrototype, ElementPrototype, addEventListener, removeEventListener, dispatchEvent, registry) {\n  WindowPrototype[addEventListener] = DocumentPrototype[addEventListener] = ElementPrototype[addEventListener] = function (type, listener) {\n    var target = this;\n\n    registry.unshift([target, type, listener, function (event) {\n      event.currentTarget = target;\n      event.preventDefault = function () { event.returnValue = false };\n      event.stopPropagation = function () { event.cancelBubble = true };\n      event.target = event.srcElement || target;\n\n      listener.call(target, event);\n    }]);\n\n    this.attachEvent(\"on\" + type, registry[0][3]);\n  };\n\n  WindowPrototype[removeEventListener] = DocumentPrototype[removeEventListener] = ElementPrototype[removeEventListener] = function (type, listener) {\n    for (var index = 0, register; register = registry[index]; ++index) {\n      if (register[0] == this && register[1] == type && register[2] == listener) {\n        return this.detachEvent(\"on\" + type, registry.splice(index, 1)[0][3]);\n      }\n    }\n  };\n\n  WindowPrototype[dispatchEvent] = DocumentPrototype[dispatchEvent] = ElementPrototype[dispatchEvent] = function (eventObject) {\n    return this.fireEvent(\"on\" + eventObject.type, eventObject);\n  };\n})(Window.prototype, HTMLDocument.prototype, Element.prototype, \"addEventListener\", \"removeEventListener\", \"dispatchEvent\", []);\n\n/**\n * Module: rem - v1.3.4\n * Description: A polyfill to parse CSS links and rewrite pixel equivalents into head for non supporting browsers\n * Date Built: 2014-07-02\n * Copyright (c) 2014  | Chuck Carpenter <chuck.carpenter@me.com>,Lucas Serven <lserven@gmail.com>;\n * @see https://github.com/chuckcarpenter/REM-unit-polyfill\n**/\n\n(function (window, undefined) {\n  \"use strict\";\n  // test for REM unit support\n  var cssremunit =  function() {\n      var div = document.createElement( 'div' );\n      div.style.cssText = 'font-size: 1rem;';\n\n      return (/rem/).test(div.style.fontSize);\n    },\n\n  // filter returned links for stylesheets\n    isStyleSheet = function () {\n      var styles = document.getElementsByTagName('link'),\n        filteredLinks = [];\n\n      for ( var i = 0; i < styles.length; i++) {\n        if ( styles[i].rel.toLowerCase() === 'stylesheet' && styles[i].getAttribute('data-norem') === null ) {\n\n          filteredLinks.push( styles[i].href );\n        }\n      }\n\n      return filteredLinks;\n    },\n\n    processLinks = function () {\n      //prepare to match each link\n      for( var i = 0; i < links.length; i++ ){\n        xhr( links[i], storeCSS );\n      }\n    },\n\n    storeCSS = function ( response, link ) {\n\n      preCSS.push(response.responseText);\n      CSSLinks.push(link);\n\n      if( CSSLinks.length === links.length ){\n        for( var j = 0; j <  CSSLinks.length; j++ ){\n          matchCSS( preCSS[j], CSSLinks[j] );\n        }\n\n        if( ( links = importLinks.slice(0) ).length > 0 ){ //after finishing all current links, set links equal to the new imports found\n          CSSLinks = [];\n          preCSS = [];\n          importLinks = [];\n          processLinks();\n        } else {\n          buildCSS();\n        }\n      }\n    },\n\n    matchCSS = function ( sheetCSS, link ) { // collect all of the rules from the xhr response texts and match them to a pattern\n      var clean = removeMediaQueries( sheetCSS ).replace(/\\/\\*[\\s\\S]*?\\*\\//g, ''), // remove MediaQueries and comments\n        pattern = /[\\w\\d\\s\\-\\/\\\\\\[\\]:,.'\"*()<>+~%#^$_=|@]+\\{[\\w\\d\\s\\-\\/\\\\%#:!;,.'\"*()]+\\d*\\.?\\d+rem[\\w\\d\\s\\-\\/\\\\%#:!;,.'\"*()]*\\}/g, //find selectors that use rem in one or more of their rules\n        current = clean.match(pattern),\n        remPattern =/\\d*\\.?\\d+rem/g,\n        remCurrent = clean.match(remPattern),\n        sheetPathPattern = /(.*\\/)/,\n        sheetPath = sheetPathPattern.exec(link)[0], //relative path to css file specified in @import\n        importPattern = /@import (?:url\\()?['\"]?([^'\\)\"]*)['\"]?\\)?[^;]*/gm, //matches all @import variations outlined at: https://developer.mozilla.org/en-US/docs/Web/CSS/@import\n        importStatement;\n\n      while( (importStatement = importPattern.exec(sheetCSS)) !== null ){\n        if( importStatement[1].indexOf(\"/\") === 0 ) { // check if the value of importStatement[1] is a root relative path, in which case it shouldn't be concatenated with sheetPath\n          importLinks.push( importStatement[1] );\n        } else {\n          importLinks.push( sheetPath + importStatement[1] );\n        }\n      }\n\n      if( current !== null && current.length !== 0 ){\n        found = found.concat( current ); // save all of the blocks of rules with rem in a property\n        foundProps = foundProps.concat( remCurrent ); // save all of the properties with rem\n      }\n    },\n\n    buildCSS = function () { // first build each individual rule from elements in the found array and then add it to the string of rules.\n      var pattern = /[\\w\\d\\s\\-\\/\\\\%#:,.'\"*()]+\\d*\\.?\\d+rem[\\w\\d\\s\\-\\/\\\\%#:!,.'\"*()]*[;}]/g; // find properties with rem values in them\n      for( var i = 0; i < found.length; i++ ){\n        rules = rules + found[i].substr(0,found[i].indexOf(\"{\")+1); // save the selector portion of each rule with a rem value\n        var current = found[i].match( pattern );\n        for( var j = 0; j<current.length; j++ ){ // build a new set of with only the selector and properties that have rem in the value\n          rules = rules + current[j];\n          if( j === current.length-1 && rules[rules.length-1] !== \"}\" ){\n            rules = rules + \"\\n}\";\n          }\n        }\n      }\n\n      parseCSS();\n    },\n\n    parseCSS = function () { // replace each set of parentheses with evaluated content\n      for( var i = 0; i < foundProps.length; i++ ){\n        css[i] = Math.round( parseFloat(foundProps[i].substr(0,foundProps[i].length-3)*fontSize) ) + 'px';\n      }\n\n      loadCSS();\n    },\n\n    loadCSS = function () { // replace and load the new rules\n      for( var i = 0; i < css.length; i++ ){ // only run this loop as many times as css has entries\n        if( css[i] ){\n          rules = rules.replace( foundProps[i],css[i] ); // replace old rules with our processed rules\n        }\n      }\n      var remcss = document.createElement( 'style' );\n      remcss.setAttribute( 'type', 'text/css' );\n      remcss.id = 'remReplace';\n      document.getElementsByTagName( 'head' )[0].appendChild( remcss );   // create the new element\n      if( remcss.styleSheet ) {\n        remcss.styleSheet.cssText = rules; // IE8 will not support innerHTML on read-only elements, such as STYLE\n      } else {\n        remcss.appendChild( document.createTextNode( rules ) );\n      }\n    },\n\n    xhr = function ( url, callback ) { // create new XMLHttpRequest object and run it\n      try {\n        //try to create a request object\n        //arranging the two conditions this way is for IE7/8's benefit\n        //so that it works with any combination of ActiveX or Native XHR settings,\n        //as long as one or the other is enabled; but if both are enabled\n        //it prefers ActiveX, which means it still works with local files\n        //(Native XHR in IE7/8 is blocked and throws \"access is denied\",\n        // but ActiveX is permitted if the user allows it [default is to prompt])\n        var xhr = window.ActiveXObject ? ( new ActiveXObject('Microsoft.XMLHTTP') || new ActiveXObject('Msxml2.XMLHTTP') ) : new XMLHttpRequest();\n\n        xhr.open( 'GET', url, true );\n        xhr.onreadystatechange = function() {\n          if ( xhr.readyState === 4 ){\n            callback(xhr, url);\n          } // else { callback function on AJAX error }\n        };\n\n        xhr.send( null );\n      } catch (e){\n        if ( window.XDomainRequest ) {\n          var xdr = new XDomainRequest();\n          xdr.open('get', url);\n          xdr.onload = function() {\n            callback(xdr, url);\n          };\n          xdr.onerror = function() {\n            return false; // xdr load fail\n          };\n          xdr.send();\n        }\n      }\n    },\n\n  // Remove queries.\n    removeMediaQueries = function(css) {\n      // Test for Media Query support\n      if ( !window.matchMedia && !window.msMatchMedia ) {\n        // If the browser doesn't support media queries, we find all @media declarations in the CSS and remove them.\n        // Note: Since @rules can't be nested in the CSS spec, we're safe to just check for the closest following \"}}\" to the \"@media\".\n        css = css.replace(/@media[\\s\\S]*?\\}\\s*\\}/g, \"\");\n      }\n\n      return css;\n    };\n\n  if( !cssremunit() ){ // this checks if the rem value is supported\n    var rules = '', // initialize the rules variable in this scope so it can be used later\n      links = isStyleSheet(), // initialize the array holding the sheets urls for use later\n      importLinks = [], //initialize the array holding the import sheet urls for use later\n      found = [], // initialize the array holding the found rules for use later\n      foundProps = [], // initialize the array holding the found properties for use later\n      preCSS = [], // initialize array that holds css before being parsed\n      CSSLinks = [], //initialize array holding css links returned from xhr\n      css = [], // initialize the array holding the parsed rules for use later\n      fontSize = '';\n\n    // Notice: rem is a \"root em\" that means that in case when html element size was changed by css\n    // or style we should not change document.documentElement.fontSize to 1em - only body size should be changed\n    // to 1em for calculation\n\n    fontSize = (function () {\n      var doc = document,\n        docElement = doc.documentElement,\n        body = doc.body || doc.createElement('body'),\n        isFakeBody = !doc.body,\n        div = doc.createElement('div'),\n        currentSize = body.style.fontSize,\n        size;\n\n      if ( isFakeBody ) {\n        docElement.appendChild( body );\n      }\n\n      div.style.cssText = 'width:1em; position:absolute; visibility:hidden; padding: 0;';\n\n      body.style.fontSize = '1em';\n\n      body.appendChild( div );\n      size = div.offsetWidth;\n\n      if ( isFakeBody ) {\n        docElement.removeChild( body );\n      }\n      else {\n        body.removeChild( div );\n        body.style.fontSize = currentSize;\n      }\n\n      return size;\n    }());\n\n    processLinks();\n  } // else { do nothing, you are awesome and have REM support }\n\n})(window);\n\n/*! Respond.js v1.4.2: min/max-width media query polyfill\n * Copyright 2014 Scott Jehl\n * Licensed under MIT\n * http://j.mp/respondjs */\n\n!function(a){\"use strict\";a.matchMedia=a.matchMedia||function(a){var b,c=a.documentElement,d=c.firstElementChild||c.firstChild,e=a.createElement(\"body\"),f=a.createElement(\"div\");return f.id=\"mq-test-1\",f.style.cssText=\"position:absolute;top:-100em\",e.style.background=\"none\",e.appendChild(f),function(a){return f.innerHTML='&shy;<style media=\"'+a+'\"> #mq-test-1 { width: 42px; }</style>',c.insertBefore(e,d),b=42===f.offsetWidth,c.removeChild(e),{matches:b,media:a}}}(a.document)}(this),function(a){\"use strict\";function b(){v(!0)}var c={};a.respond=c,c.update=function(){};var d=[],e=function(){var b=!1;try{b=new a.XMLHttpRequest}catch(c){b=new a.ActiveXObject(\"Microsoft.XMLHTTP\")}return function(){return b}}(),f=function(a,b){var c=e();c&&(c.open(\"GET\",a,!0),c.onreadystatechange=function(){4!==c.readyState||200!==c.status&&304!==c.status||b(c.responseText)},4!==c.readyState&&c.send(null))},g=function(a){return a.replace(c.regex.minmaxwh,\"\").match(c.regex.other)};if(c.ajax=f,c.queue=d,c.unsupportedmq=g,c.regex={media:/@media[^\\{]+\\{([^\\{\\}]*\\{[^\\}\\{]*\\})+/gi,keyframes:/@(?:\\-(?:o|moz|webkit)\\-)?keyframes[^\\{]+\\{(?:[^\\{\\}]*\\{[^\\}\\{]*\\})+[^\\}]*\\}/gi,comments:/\\/\\*[^*]*\\*+([^/][^*]*\\*+)*\\//gi,urls:/(url\\()['\"]?([^\\/\\)'\"][^:\\)'\"]+)['\"]?(\\))/g,findStyles:/@media *([^\\{]+)\\{([\\S\\s]+?)$/,only:/(only\\s+)?([a-zA-Z]+)\\s?/,minw:/\\(\\s*min\\-width\\s*:\\s*(\\s*[0-9\\.]+)(px|em)\\s*\\)/,maxw:/\\(\\s*max\\-width\\s*:\\s*(\\s*[0-9\\.]+)(px|em)\\s*\\)/,minmaxwh:/\\(\\s*m(in|ax)\\-(height|width)\\s*:\\s*(\\s*[0-9\\.]+)(px|em)\\s*\\)/gi,other:/\\([^\\)]*\\)/g},c.mediaQueriesSupported=a.matchMedia&&null!==a.matchMedia(\"only all\")&&a.matchMedia(\"only all\").matches,!c.mediaQueriesSupported){var h,i,j,k=a.document,l=k.documentElement,m=[],n=[],o=[],p={},q=30,r=k.getElementsByTagName(\"head\")[0]||l,s=k.getElementsByTagName(\"base\")[0],t=r.getElementsByTagName(\"link\"),u=function(){var a,b=k.createElement(\"div\"),c=k.body,d=l.style.fontSize,e=c&&c.style.fontSize,f=!1;return b.style.cssText=\"position:absolute;font-size:1em;width:1em\",c||(c=f=k.createElement(\"body\"),c.style.background=\"none\"),l.style.fontSize=\"100%\",c.style.fontSize=\"100%\",c.appendChild(b),f&&l.insertBefore(c,l.firstChild),a=b.offsetWidth,f?l.removeChild(c):c.removeChild(b),l.style.fontSize=d,e&&(c.style.fontSize=e),a=j=parseFloat(a)},v=function(b){var c=\"clientWidth\",d=l[c],e=\"CSS1Compat\"===k.compatMode&&d||k.body[c]||d,f={},g=t[t.length-1],p=(new Date).getTime();if(b&&h&&q>p-h)return a.clearTimeout(i),i=a.setTimeout(v,q),void 0;h=p;for(var s in m)if(m.hasOwnProperty(s)){var w=m[s],x=w.minw,y=w.maxw,z=null===x,A=null===y,B=\"em\";x&&(x=parseFloat(x)*(x.indexOf(B)>-1?j||u():1)),y&&(y=parseFloat(y)*(y.indexOf(B)>-1?j||u():1)),w.hasquery&&(z&&A||!(z||e>=x)||!(A||y>=e))||(f[w.media]||(f[w.media]=[]),f[w.media].push(n[w.rules]))}for(var C in o)o.hasOwnProperty(C)&&o[C]&&o[C].parentNode===r&&r.removeChild(o[C]);o.length=0;for(var D in f)if(f.hasOwnProperty(D)){var E=k.createElement(\"style\"),F=f[D].join(\"\\n\");E.type=\"text/css\",E.media=D,r.insertBefore(E,g.nextSibling),E.styleSheet?E.styleSheet.cssText=F:E.appendChild(k.createTextNode(F)),o.push(E)}},w=function(a,b,d){var e=a.replace(c.regex.comments,\"\").replace(c.regex.keyframes,\"\").match(c.regex.media),f=e&&e.length||0;b=b.substring(0,b.lastIndexOf(\"/\"));var h=function(a){return a.replace(c.regex.urls,\"$1\"+b+\"$2$3\")},i=!f&&d;b.length&&(b+=\"/\"),i&&(f=1);for(var j=0;f>j;j++){var k,l,o,p;i?(k=d,n.push(h(a))):(k=e[j].match(c.regex.findStyles)&&RegExp.$1,n.push(RegExp.$2&&h(RegExp.$2))),o=k.split(\",\"),p=o.length;for(var q=0;p>q;q++)l=o[q],g(l)||m.push({media:l.split(\"(\")[0].match(c.regex.only)&&RegExp.$2||\"all\",rules:n.length-1,hasquery:l.indexOf(\"(\")>-1,minw:l.match(c.regex.minw)&&parseFloat(RegExp.$1)+(RegExp.$2||\"\"),maxw:l.match(c.regex.maxw)&&parseFloat(RegExp.$1)+(RegExp.$2||\"\")})}v()},x=function(){if(d.length){var b=d.shift();f(b.href,function(c){w(c,b.href,b.media),p[b.href]=!0,a.setTimeout(function(){x()},0)})}},y=function(){for(var b=0;b<t.length;b++){var c=t[b],e=c.href,f=c.media,g=c.rel&&\"stylesheet\"===c.rel.toLowerCase();e&&g&&!p[e]&&(c.styleSheet&&c.styleSheet.rawCssText?(w(c.styleSheet.rawCssText,e,f),p[e]=!0):(!/^([a-zA-Z:]*\\/\\/)/.test(e)&&!s||e.replace(RegExp.$1,\"\").split(\"/\")[0]===a.location.host)&&(\"//\"===e.substring(0,2)&&(e=a.location.protocol+e),d.push({href:e,media:f})))}x()};y(),c.update=y,c.getEmValue=u,a.addEventListener?a.addEventListener(\"resize\",b,!1):a.attachEvent&&a.attachEvent(\"onresize\",b)}}(this);"
  },
  {
    "path": "open-layui-web/src/main/view/static/assets/js/amazeui.js",
    "content": "/*! Amaze UI v2.6.0 | by Amaze UI Team | (c) 2016 AllMobilize, Inc. | Licensed under MIT | 2016-03-31T14:28:54+0800 */ \n(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory(require(\"jquery\"));\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([\"jquery\"], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"AMUI\"] = factory(require(\"jquery\"));\n\telse\n\t\troot[\"AMUI\"] = factory(root[\"jQuery\"]);\n})(this, function(__WEBPACK_EXTERNAL_MODULE_1__) {\nreturn /******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId])\n/******/ \t\t\treturn installedModules[moduleId].exports;\n\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\texports: {},\n/******/ \t\t\tid: moduleId,\n/******/ \t\t\tloaded: false\n/******/ \t\t};\n\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.loaded = true;\n\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n\n\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(0);\n/******/ })\n/************************************************************************/\n/******/ ([\n/* 0 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\t__webpack_require__(3);\n\t__webpack_require__(4);\n\t__webpack_require__(5);\n\t__webpack_require__(6);\n\t__webpack_require__(7);\n\t__webpack_require__(8);\n\t__webpack_require__(9);\n\t__webpack_require__(10);\n\t__webpack_require__(11);\n\t__webpack_require__(14);\n\t__webpack_require__(15);\n\t__webpack_require__(16);\n\t__webpack_require__(17);\n\t__webpack_require__(18);\n\t__webpack_require__(19);\n\t__webpack_require__(20);\n\t__webpack_require__(21);\n\t__webpack_require__(22);\n\t__webpack_require__(24);\n\t__webpack_require__(25);\n\t__webpack_require__(23);\n\t__webpack_require__(27);\n\t__webpack_require__(28);\n\t__webpack_require__(29);\n\t__webpack_require__(30);\n\t__webpack_require__(31);\n\t__webpack_require__(32);\n\t__webpack_require__(33);\n\t__webpack_require__(26);\n\t__webpack_require__(34);\n\t__webpack_require__(35);\n\t__webpack_require__(36);\n\t__webpack_require__(37);\n\t__webpack_require__(38);\n\t__webpack_require__(39);\n\t__webpack_require__(40);\n\t__webpack_require__(41);\n\t__webpack_require__(42);\n\t__webpack_require__(43);\n\t__webpack_require__(44);\n\t__webpack_require__(45);\n\t__webpack_require__(46);\n\t__webpack_require__(47);\n\t__webpack_require__(48);\n\t__webpack_require__(49);\n\t__webpack_require__(50);\n\t__webpack_require__(51);\n\t__webpack_require__(52);\n\t__webpack_require__(53);\n\t__webpack_require__(54);\n\n\tmodule.exports = $.AMUI = UI;\n\n\n/***/ },\n/* 1 */\n/***/ function(module, exports) {\n\n\tmodule.exports = __WEBPACK_EXTERNAL_MODULE_1__;\n\n/***/ },\n/* 2 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\t/* jshint -W040 */\n\n\tvar $ = __webpack_require__(1);\n\n\tif (typeof $ === 'undefined') {\n\t  throw new Error('Amaze UI 2.x requires jQuery :-(\\n' +\n\t  '\\u7231\\u4e0a\\u4e00\\u5339\\u91ce\\u9a6c\\uff0c\\u53ef\\u4f60' +\n\t  '\\u7684\\u5bb6\\u91cc\\u6ca1\\u6709\\u8349\\u539f\\u2026');\n\t}\n\n\tvar UI = $.AMUI || {};\n\tvar $win = $(window);\n\tvar doc = window.document;\n\tvar $html = $('html');\n\n\tUI.VERSION = '2.6.0';\n\n\tUI.support = {};\n\n\tUI.support.transition = (function() {\n\t  var transitionEnd = (function() {\n\t    // https://developer.mozilla.org/en-US/docs/Web/Events/transitionend#Browser_compatibility\n\t    var element = doc.body || doc.documentElement;\n\t    var transEndEventNames = {\n\t      WebkitTransition: 'webkitTransitionEnd',\n\t      MozTransition: 'transitionend',\n\t      OTransition: 'oTransitionEnd otransitionend',\n\t      transition: 'transitionend'\n\t    };\n\n\t    for (var name in transEndEventNames) {\n\t      if (element.style[name] !== undefined) {\n\t        return transEndEventNames[name];\n\t      }\n\t    }\n\t  })();\n\n\t  return transitionEnd && {end: transitionEnd};\n\t})();\n\n\tUI.support.animation = (function() {\n\t  var animationEnd = (function() {\n\t    var element = doc.body || doc.documentElement;\n\t    var animEndEventNames = {\n\t      WebkitAnimation: 'webkitAnimationEnd',\n\t      MozAnimation: 'animationend',\n\t      OAnimation: 'oAnimationEnd oanimationend',\n\t      animation: 'animationend'\n\t    };\n\n\t    for (var name in animEndEventNames) {\n\t      if (element.style[name] !== undefined) {\n\t        return animEndEventNames[name];\n\t      }\n\t    }\n\t  })();\n\n\t  return animationEnd && {end: animationEnd};\n\t})();\n\n\t/* jshint -W069 */\n\tUI.support.touch = (\n\t('ontouchstart' in window &&\n\tnavigator.userAgent.toLowerCase().match(/mobile|tablet/)) ||\n\t(window.DocumentTouch && document instanceof window.DocumentTouch) ||\n\t(window.navigator['msPointerEnabled'] &&\n\twindow.navigator['msMaxTouchPoints'] > 0) || //IE 10\n\t(window.navigator['pointerEnabled'] &&\n\twindow.navigator['maxTouchPoints'] > 0) || //IE >=11\n\tfalse);\n\n\t// https://developer.mozilla.org/zh-CN/docs/DOM/MutationObserver\n\tUI.support.mutationobserver = (window.MutationObserver ||\n\twindow.WebKitMutationObserver || null);\n\n\t// https://github.com/Modernizr/Modernizr/blob/924c7611c170ef2dc502582e5079507aff61e388/feature-detects/forms/validation.js#L20\n\tUI.support.formValidation = (typeof document.createElement('form').\n\t  checkValidity === 'function');\n\n\tUI.utils = {};\n\n\t/**\n\t * Debounce function\n\t * @param {function} func  Function to be debounced\n\t * @param {number} wait Function execution threshold in milliseconds\n\t * @param {bool} immediate  Whether the function should be called at\n\t *                          the beginning of the delay instead of the\n\t *                          end. Default is false.\n\t * @desc Executes a function when it stops being invoked for n seconds\n\t * @via  _.debounce() http://underscorejs.org\n\t */\n\tUI.utils.debounce = function(func, wait, immediate) {\n\t  var timeout;\n\t  return function() {\n\t    var context = this;\n\t    var args = arguments;\n\t    var later = function() {\n\t      timeout = null;\n\t      if (!immediate) {\n\t        func.apply(context, args);\n\t      }\n\t    };\n\t    var callNow = immediate && !timeout;\n\n\t    clearTimeout(timeout);\n\t    timeout = setTimeout(later, wait);\n\n\t    if (callNow) {\n\t      func.apply(context, args);\n\t    }\n\t  };\n\t};\n\n\tUI.utils.isInView = function(element, options) {\n\t  var $element = $(element);\n\t  var visible = !!($element.width() || $element.height()) &&\n\t    $element.css('display') !== 'none';\n\n\t  if (!visible) {\n\t    return false;\n\t  }\n\n\t  var windowLeft = $win.scrollLeft();\n\t  var windowTop = $win.scrollTop();\n\t  var offset = $element.offset();\n\t  var left = offset.left;\n\t  var top = offset.top;\n\n\t  options = $.extend({topOffset: 0, leftOffset: 0}, options);\n\n\t  return (top + $element.height() >= windowTop &&\n\t  top - options.topOffset <= windowTop + $win.height() &&\n\t  left + $element.width() >= windowLeft &&\n\t  left - options.leftOffset <= windowLeft + $win.width());\n\t};\n\n\t/* jshint -W054 */\n\tUI.utils.parseOptions = UI.utils.options = function(string) {\n\t  if ($.isPlainObject(string)) {\n\t    return string;\n\t  }\n\n\t  var start = (string ? string.indexOf('{') : -1);\n\t  var options = {};\n\n\t  if (start != -1) {\n\t    try {\n\t      options = (new Function('',\n\t        'var json = ' + string.substr(start) +\n\t        '; return JSON.parse(JSON.stringify(json));'))();\n\t    } catch (e) {\n\t    }\n\t  }\n\n\t  return options;\n\t};\n\n\t/* jshint +W054 */\n\n\tUI.utils.generateGUID = function(namespace) {\n\t  var uid = namespace + '-' || 'am-';\n\n\t  do {\n\t    uid += Math.random().toString(36).substring(2, 7);\n\t  } while (document.getElementById(uid));\n\n\t  return uid;\n\t};\n\n\t// @see https://davidwalsh.name/get-absolute-url\n\tUI.utils.getAbsoluteUrl = (function() {\n\t  var a;\n\n\t  return function(url) {\n\t    if (!a) {\n\t      a = document.createElement('a');\n\t    }\n\n\t    a.href = url;\n\n\t    return a.href;\n\t  };\n\t})();\n\n\t/**\n\t * Plugin AMUI Component to jQuery\n\t *\n\t * @param {String} name - plugin name\n\t * @param {Function} Component - plugin constructor\n\t * @param {Object} [pluginOption]\n\t * @param {String} pluginOption.dataOptions\n\t * @param {Function} pluginOption.methodCall - custom method call\n\t * @param {Function} pluginOption.before\n\t * @param {Function} pluginOption.after\n\t * @since v2.4.1\n\t */\n\tUI.plugin = function UIPlugin(name, Component, pluginOption) {\n\t  var old = $.fn[name];\n\t  pluginOption = pluginOption || {};\n\n\t  $.fn[name] = function(option) {\n\t    var allArgs = Array.prototype.slice.call(arguments, 0);\n\t    var args = allArgs.slice(1);\n\t    var propReturn;\n\t    var $set = this.each(function() {\n\t      var $this = $(this);\n\t      var dataName = 'amui.' + name;\n\t      var dataOptionsName = pluginOption.dataOptions || ('data-am-' + name);\n\t      var instance = $this.data(dataName);\n\t      var options = $.extend({},\n\t        UI.utils.parseOptions($this.attr(dataOptionsName)),\n\t        typeof option === 'object' && option);\n\n\t      if (!instance && option === 'destroy') {\n\t        return;\n\t      }\n\n\t      if (!instance) {\n\t        $this.data(dataName, (instance = new Component(this, options)));\n\t      }\n\n\t      // custom method call\n\t      if (pluginOption.methodCall) {\n\t        pluginOption.methodCall.call($this, allArgs, instance);\n\t      } else {\n\t        // before method call\n\t        pluginOption.before &&\n\t        pluginOption.before.call($this, allArgs, instance);\n\n\t        if (typeof option === 'string') {\n\t          propReturn = typeof instance[option] === 'function' ?\n\t            instance[option].apply(instance, args) : instance[option];\n\t        }\n\n\t        // after method call\n\t        pluginOption.after && pluginOption.after.call($this, allArgs, instance);\n\t      }\n\t    });\n\n\t    return (propReturn === undefined) ? $set : propReturn;\n\t  };\n\n\t  $.fn[name].Constructor = Component;\n\n\t  // no conflict\n\t  $.fn[name].noConflict = function() {\n\t    $.fn[name] = old;\n\t    return this;\n\t  };\n\n\t  UI[name] = Component;\n\t};\n\n\t// http://blog.alexmaccaw.com/css-transitions\n\t$.fn.emulateTransitionEnd = function(duration) {\n\t  var called = false;\n\t  var $el = this;\n\n\t  $(this).one(UI.support.transition.end, function() {\n\t    called = true;\n\t  });\n\n\t  var callback = function() {\n\t    if (!called) {\n\t      $($el).trigger(UI.support.transition.end);\n\t    }\n\t    $el.transitionEndTimmer = undefined;\n\t  };\n\t  this.transitionEndTimmer = setTimeout(callback, duration);\n\t  return this;\n\t};\n\n\t$.fn.redraw = function() {\n\t  return this.each(function() {\n\t    /* jshint unused:false */\n\t    var redraw = this.offsetHeight;\n\t  });\n\t};\n\n\t/* jshint unused:true */\n\n\t$.fn.transitionEnd = function(callback) {\n\t  var endEvent = UI.support.transition.end;\n\t  var dom = this;\n\n\t  function fireCallBack(e) {\n\t    callback.call(this, e);\n\t    endEvent && dom.off(endEvent, fireCallBack);\n\t  }\n\n\t  if (callback && endEvent) {\n\t    dom.on(endEvent, fireCallBack);\n\t  }\n\n\t  return this;\n\t};\n\n\t$.fn.removeClassRegEx = function() {\n\t  return this.each(function(regex) {\n\t    var classes = $(this).attr('class');\n\n\t    if (!classes || !regex) {\n\t      return false;\n\t    }\n\n\t    var classArray = [];\n\t    classes = classes.split(' ');\n\n\t    for (var i = 0, len = classes.length; i < len; i++) {\n\t      if (!classes[i].match(regex)) {\n\t        classArray.push(classes[i]);\n\t      }\n\t    }\n\n\t    $(this).attr('class', classArray.join(' '));\n\t  });\n\t};\n\n\t//\n\t$.fn.alterClass = function(removals, additions) {\n\t  var self = this;\n\n\t  if (removals.indexOf('*') === -1) {\n\t    // Use native jQuery methods if there is no wildcard matching\n\t    self.removeClass(removals);\n\t    return !additions ? self : self.addClass(additions);\n\t  }\n\n\t  var classPattern = new RegExp('\\\\s' +\n\t  removals.\n\t    replace(/\\*/g, '[A-Za-z0-9-_]+').\n\t    split(' ').\n\t    join('\\\\s|\\\\s') +\n\t  '\\\\s', 'g');\n\n\t  self.each(function(i, it) {\n\t    var cn = ' ' + it.className + ' ';\n\t    while (classPattern.test(cn)) {\n\t      cn = cn.replace(classPattern, ' ');\n\t    }\n\t    it.className = $.trim(cn);\n\t  });\n\n\t  return !additions ? self : self.addClass(additions);\n\t};\n\n\t// handle multiple browsers for requestAnimationFrame()\n\t// http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/\n\t// https://github.com/gnarf/jquery-requestAnimationFrame\n\tUI.utils.rAF = (function() {\n\t  return window.requestAnimationFrame ||\n\t    window.webkitRequestAnimationFrame ||\n\t    window.mozRequestAnimationFrame ||\n\t    window.oRequestAnimationFrame ||\n\t      // if all else fails, use setTimeout\n\t    function(callback) {\n\t      return window.setTimeout(callback, 1000 / 60); // shoot for 60 fps\n\t    };\n\t})();\n\n\t// handle multiple browsers for cancelAnimationFrame()\n\tUI.utils.cancelAF = (function() {\n\t  return window.cancelAnimationFrame ||\n\t    window.webkitCancelAnimationFrame ||\n\t    window.mozCancelAnimationFrame ||\n\t    window.oCancelAnimationFrame ||\n\t    function(id) {\n\t      window.clearTimeout(id);\n\t    };\n\t})();\n\n\t// via http://davidwalsh.name/detect-scrollbar-width\n\tUI.utils.measureScrollbar = function() {\n\t  if (document.body.clientWidth >= window.innerWidth) {\n\t    return 0;\n\t  }\n\n\t  // if ($html.width() >= window.innerWidth) return;\n\t  // var scrollbarWidth = window.innerWidth - $html.width();\n\t  var $measure = $('<div ' +\n\t  'style=\"width: 100px;height: 100px;overflow: scroll;' +\n\t  'position: absolute;top: -9999px;\"></div>');\n\n\t  $(document.body).append($measure);\n\n\t  var scrollbarWidth = $measure[0].offsetWidth - $measure[0].clientWidth;\n\n\t  $measure.remove();\n\n\t  return scrollbarWidth;\n\t};\n\n\tUI.utils.imageLoader = function($image, callback) {\n\t  function loaded() {\n\t    callback($image[0]);\n\t  }\n\n\t  function bindLoad() {\n\t    this.one('load', loaded);\n\t    if (/MSIE (\\d+\\.\\d+);/.test(navigator.userAgent)) {\n\t      var src = this.attr('src');\n\t      var param = src.match(/\\?/) ? '&' : '?';\n\n\t      param += 'random=' + (new Date()).getTime();\n\t      this.attr('src', src + param);\n\t    }\n\t  }\n\n\t  if (!$image.attr('src')) {\n\t    loaded();\n\t    return;\n\t  }\n\n\t  if ($image[0].complete || $image[0].readyState === 4) {\n\t    loaded();\n\t  } else {\n\t    bindLoad.call($image);\n\t  }\n\t};\n\n\t/**\n\t * https://github.com/cho45/micro-template.js\n\t * (c) cho45 http://cho45.github.com/mit-license\n\t */\n\t/* jshint -W109 */\n\tUI.template = function(id, data) {\n\t  var me = UI.template;\n\n\t  if (!me.cache[id]) {\n\t    me.cache[id] = (function() {\n\t      var name = id;\n\t      var string = /^[\\w\\-]+$/.test(id) ?\n\t        me.get(id) : (name = 'template(string)', id); // no warnings\n\n\t      var line = 1;\n\t      var body = ('try { ' + (me.variable ?\n\t      'var ' + me.variable + ' = this.stash;' : 'with (this.stash) { ') +\n\t      \"this.ret += '\" +\n\t      string.\n\t        replace(/<%/g, '\\x11').replace(/%>/g, '\\x13'). // if you want other tag, just edit this line\n\t        replace(/'(?![^\\x11\\x13]+?\\x13)/g, '\\\\x27').\n\t        replace(/^\\s*|\\s*$/g, '').\n\t        replace(/\\n/g, function() {\n\t          return \"';\\nthis.line = \" + (++line) + \"; this.ret += '\\\\n\";\n\t        }).\n\t        replace(/\\x11-(.+?)\\x13/g, \"' + ($1) + '\").\n\t        replace(/\\x11=(.+?)\\x13/g, \"' + this.escapeHTML($1) + '\").\n\t        replace(/\\x11(.+?)\\x13/g, \"'; $1; this.ret += '\") +\n\t      \"'; \" + (me.variable ? \"\" : \"}\") + \"return this.ret;\" +\n\t      \"} catch (e) { throw 'TemplateError: ' + e + ' (on \" + name +\n\t      \"' + ' line ' + this.line + ')'; } \" +\n\t      \"//@ sourceURL=\" + name + \"\\n\" // source map\n\t      ).replace(/this\\.ret \\+= '';/g, '');\n\t      /* jshint -W054 */\n\t      var func = new Function(body);\n\t      var map = {\n\t        '&': '&amp;',\n\t        '<': '&lt;',\n\t        '>': '&gt;',\n\t        '\\x22': '&#x22;',\n\t        '\\x27': '&#x27;'\n\t      };\n\t      var escapeHTML = function(string) {\n\t        return ('' + string).replace(/[&<>\\'\\\"]/g, function(_) {\n\t          return map[_];\n\t        });\n\t      };\n\n\t      return function(stash) {\n\t        return func.call(me.context = {\n\t          escapeHTML: escapeHTML,\n\t          line: 1,\n\t          ret: '',\n\t          stash: stash\n\t        });\n\t      };\n\t    })();\n\t  }\n\n\t  return data ? me.cache[id](data) : me.cache[id];\n\t};\n\t/* jshint +W109 */\n\t/* jshint +W054 */\n\n\tUI.template.cache = {};\n\n\tUI.template.get = function(id) {\n\t  if (id) {\n\t    var element = document.getElementById(id);\n\t    return element && element.innerHTML || '';\n\t  }\n\t};\n\n\t// Dom mutation watchers\n\tUI.DOMWatchers = [];\n\tUI.DOMReady = false;\n\tUI.ready = function(callback) {\n\t  UI.DOMWatchers.push(callback);\n\t  if (UI.DOMReady) {\n\t    // console.log('Ready call');\n\t    callback(document);\n\t  }\n\t};\n\n\tUI.DOMObserve = function(elements, options, callback) {\n\t  var Observer = UI.support.mutationobserver;\n\t  if (!Observer) {\n\t    return;\n\t  }\n\n\t  options = $.isPlainObject(options) ?\n\t    options : {childList: true, subtree: true};\n\n\t  callback = typeof callback === 'function' && callback || function() {\n\t  };\n\n\t  $(elements).each(function() {\n\t    var element = this;\n\t    var $element = $(element);\n\n\t    if ($element.data('am.observer')) {\n\t      return;\n\t    }\n\n\t    try {\n\t      var observer = new Observer(UI.utils.debounce(\n\t        function(mutations, instance) {\n\t        callback.call(element, mutations, instance);\n\t        // trigger this event manually if MutationObserver not supported\n\t        $element.trigger('changed.dom.amui');\n\t      }, 50));\n\n\t      observer.observe(element, options);\n\n\t      $element.data('am.observer', observer);\n\t    } catch (e) {\n\t    }\n\t  });\n\t};\n\n\t$.fn.DOMObserve = function(options, callback) {\n\t  return this.each(function() {\n\t    UI.DOMObserve(this, options, callback);\n\t  });\n\t};\n\n\tif (UI.support.touch) {\n\t  $html.addClass('am-touch');\n\t}\n\n\t$(document).on('changed.dom.amui', function(e) {\n\t  var element = e.target;\n\n\t  // TODO: just call changed element's watcher\n\t  //       every watcher callback should have a key\n\t  //       use like this: <div data-am-observe='key1, key2'>\n\t  //       get keys via $(element).data('amObserve')\n\t  //       call functions store with these keys\n\t  $.each(UI.DOMWatchers, function(i, watcher) {\n\t    watcher(element);\n\t  });\n\t});\n\n\t$(function() {\n\t  var $body = $('body');\n\n\t  UI.DOMReady = true;\n\n\t  // Run default init\n\t  $.each(UI.DOMWatchers, function(i, watcher) {\n\t    watcher(document);\n\t  });\n\n\t  // watches DOM\n\t  UI.DOMObserve('[data-am-observe]');\n\n\t  $html.removeClass('no-js').addClass('js');\n\n\t  UI.support.animation && $html.addClass('cssanimations');\n\n\t  // iOS standalone mode\n\t  if (window.navigator.standalone) {\n\t    $html.addClass('am-standalone');\n\t  }\n\n\t  $('.am-topbar-fixed-top').length &&\n\t  $body.addClass('am-with-topbar-fixed-top');\n\n\t  $('.am-topbar-fixed-bottom').length &&\n\t  $body.addClass('am-with-topbar-fixed-bottom');\n\n\t  // Remove responsive classes in .am-layout\n\t  var $layout = $('.am-layout');\n\t  $layout.find('[class*=\"md-block-grid\"]').alterClass('md-block-grid-*');\n\t  $layout.find('[class*=\"lg-block-grid\"]').alterClass('lg-block-grid');\n\n\t  // widgets not in .am-layout\n\t  $('[data-am-widget]').each(function() {\n\t    var $widget = $(this);\n\t    // console.log($widget.parents('.am-layout').length)\n\t    if ($widget.parents('.am-layout').length === 0) {\n\t      $widget.addClass('am-no-layout');\n\t    }\n\t  });\n\t});\n\n\tmodule.exports = UI;\n\n\n/***/ },\n/* 3 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t/*! Hammer.JS - v2.0.6 - 2015-12-23\n\t * http://hammerjs.github.io/\n\t *\n\t * Copyright (c) 2015 Jorik Tangelder;\n\t * Licensed under the MIT license */\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\n\tvar VENDOR_PREFIXES = ['', 'webkit', 'Moz', 'MS', 'ms', 'o'];\n\tvar TEST_ELEMENT = document.createElement('div');\n\n\tvar TYPE_FUNCTION = 'function';\n\n\tvar round = Math.round;\n\tvar abs = Math.abs;\n\tvar now = Date.now;\n\n\t/**\n\t * set a timeout with a given scope\n\t * @param {Function} fn\n\t * @param {Number} timeout\n\t * @param {Object} context\n\t * @returns {number}\n\t */\n\tfunction setTimeoutContext(fn, timeout, context) {\n\t  return setTimeout(bindFn(fn, context), timeout);\n\t}\n\n\t/**\n\t * if the argument is an array, we want to execute the fn on each entry\n\t * if it aint an array we don't want to do a thing.\n\t * this is used by all the methods that accept a single and array argument.\n\t * @param {*|Array} arg\n\t * @param {String} fn\n\t * @param {Object} [context]\n\t * @returns {Boolean}\n\t */\n\tfunction invokeArrayArg(arg, fn, context) {\n\t  if (Array.isArray(arg)) {\n\t    each(arg, context[fn], context);\n\t    return true;\n\t  }\n\t  return false;\n\t}\n\n\t/**\n\t * walk objects and arrays\n\t * @param {Object} obj\n\t * @param {Function} iterator\n\t * @param {Object} context\n\t */\n\tfunction each(obj, iterator, context) {\n\t  var i;\n\n\t  if (!obj) {\n\t    return;\n\t  }\n\n\t  if (obj.forEach) {\n\t    obj.forEach(iterator, context);\n\t  } else if (obj.length !== undefined) {\n\t    i = 0;\n\t    while (i < obj.length) {\n\t      iterator.call(context, obj[i], i, obj);\n\t      i++;\n\t    }\n\t  } else {\n\t    for (i in obj) {\n\t      obj.hasOwnProperty(i) && iterator.call(context, obj[i], i, obj);\n\t    }\n\t  }\n\t}\n\n\t/**\n\t * wrap a method with a deprecation warning and stack trace\n\t * @param {Function} method\n\t * @param {String} name\n\t * @param {String} message\n\t * @returns {Function} A new function wrapping the supplied method.\n\t */\n\tfunction deprecate(method, name, message) {\n\t  var deprecationMessage = 'DEPRECATED METHOD: ' + name + '\\n' + message + ' AT \\n';\n\t  return function() {\n\t    var e = new Error('get-stack-trace');\n\t    var stack = e && e.stack ? e.stack.replace(/^[^\\(]+?[\\n$]/gm, '')\n\t      .replace(/^\\s+at\\s+/gm, '')\n\t      .replace(/^Object.<anonymous>\\s*\\(/gm, '{anonymous}()@') : 'Unknown Stack Trace';\n\n\t    var log = window.console && (window.console.warn || window.console.log);\n\t    if (log) {\n\t      log.call(window.console, deprecationMessage, stack);\n\t    }\n\t    return method.apply(this, arguments);\n\t  };\n\t}\n\n\t/**\n\t * extend object.\n\t * means that properties in dest will be overwritten by the ones in src.\n\t * @param {Object} target\n\t * @param {...Object} objects_to_assign\n\t * @returns {Object} target\n\t */\n\tvar assign;\n\tif (typeof Object.assign !== 'function') {\n\t  assign = function assign(target) {\n\t    if (target === undefined || target === null) {\n\t      throw new TypeError('Cannot convert undefined or null to object');\n\t    }\n\n\t    var output = Object(target);\n\t    for (var index = 1; index < arguments.length; index++) {\n\t      var source = arguments[index];\n\t      if (source !== undefined && source !== null) {\n\t        for (var nextKey in source) {\n\t          if (source.hasOwnProperty(nextKey)) {\n\t            output[nextKey] = source[nextKey];\n\t          }\n\t        }\n\t      }\n\t    }\n\t    return output;\n\t  };\n\t} else {\n\t  assign = Object.assign;\n\t}\n\n\t/**\n\t * extend object.\n\t * means that properties in dest will be overwritten by the ones in src.\n\t * @param {Object} dest\n\t * @param {Object} src\n\t * @param {Boolean=false} [merge]\n\t * @returns {Object} dest\n\t */\n\tvar extend = deprecate(function extend(dest, src, merge) {\n\t  var keys = Object.keys(src);\n\t  var i = 0;\n\t  while (i < keys.length) {\n\t    if (!merge || (merge && dest[keys[i]] === undefined)) {\n\t      dest[keys[i]] = src[keys[i]];\n\t    }\n\t    i++;\n\t  }\n\t  return dest;\n\t}, 'extend', 'Use `assign`.');\n\n\t/**\n\t * merge the values from src in the dest.\n\t * means that properties that exist in dest will not be overwritten by src\n\t * @param {Object} dest\n\t * @param {Object} src\n\t * @returns {Object} dest\n\t */\n\tvar merge = deprecate(function merge(dest, src) {\n\t  return extend(dest, src, true);\n\t}, 'merge', 'Use `assign`.');\n\n\t/**\n\t * simple class inheritance\n\t * @param {Function} child\n\t * @param {Function} base\n\t * @param {Object} [properties]\n\t */\n\tfunction inherit(child, base, properties) {\n\t  var baseP = base.prototype,\n\t    childP;\n\n\t  childP = child.prototype = Object.create(baseP);\n\t  childP.constructor = child;\n\t  childP._super = baseP;\n\n\t  if (properties) {\n\t    assign(childP, properties);\n\t  }\n\t}\n\n\t/**\n\t * simple function bind\n\t * @param {Function} fn\n\t * @param {Object} context\n\t * @returns {Function}\n\t */\n\tfunction bindFn(fn, context) {\n\t  return function boundFn() {\n\t    return fn.apply(context, arguments);\n\t  };\n\t}\n\n\t/**\n\t * let a boolean value also be a function that must return a boolean\n\t * this first item in args will be used as the context\n\t * @param {Boolean|Function} val\n\t * @param {Array} [args]\n\t * @returns {Boolean}\n\t */\n\tfunction boolOrFn(val, args) {\n\t  if (typeof val == TYPE_FUNCTION) {\n\t    return val.apply(args ? args[0] || undefined : undefined, args);\n\t  }\n\t  return val;\n\t}\n\n\t/**\n\t * use the val2 when val1 is undefined\n\t * @param {*} val1\n\t * @param {*} val2\n\t * @returns {*}\n\t */\n\tfunction ifUndefined(val1, val2) {\n\t  return (val1 === undefined) ? val2 : val1;\n\t}\n\n\t/**\n\t * addEventListener with multiple events at once\n\t * @param {EventTarget} target\n\t * @param {String} types\n\t * @param {Function} handler\n\t */\n\tfunction addEventListeners(target, types, handler) {\n\t  each(splitStr(types), function(type) {\n\t    target.addEventListener(type, handler, false);\n\t  });\n\t}\n\n\t/**\n\t * removeEventListener with multiple events at once\n\t * @param {EventTarget} target\n\t * @param {String} types\n\t * @param {Function} handler\n\t */\n\tfunction removeEventListeners(target, types, handler) {\n\t  each(splitStr(types), function(type) {\n\t    target.removeEventListener(type, handler, false);\n\t  });\n\t}\n\n\t/**\n\t * find if a node is in the given parent\n\t * @method hasParent\n\t * @param {HTMLElement} node\n\t * @param {HTMLElement} parent\n\t * @return {Boolean} found\n\t */\n\tfunction hasParent(node, parent) {\n\t  while (node) {\n\t    if (node == parent) {\n\t      return true;\n\t    }\n\t    node = node.parentNode;\n\t  }\n\t  return false;\n\t}\n\n\t/**\n\t * small indexOf wrapper\n\t * @param {String} str\n\t * @param {String} find\n\t * @returns {Boolean} found\n\t */\n\tfunction inStr(str, find) {\n\t  return str.indexOf(find) > -1;\n\t}\n\n\t/**\n\t * split string on whitespace\n\t * @param {String} str\n\t * @returns {Array} words\n\t */\n\tfunction splitStr(str) {\n\t  return str.trim().split(/\\s+/g);\n\t}\n\n\t/**\n\t * find if a array contains the object using indexOf or a simple polyFill\n\t * @param {Array} src\n\t * @param {String} find\n\t * @param {String} [findByKey]\n\t * @return {Boolean|Number} false when not found, or the index\n\t */\n\tfunction inArray(src, find, findByKey) {\n\t  if (src.indexOf && !findByKey) {\n\t    return src.indexOf(find);\n\t  } else {\n\t    var i = 0;\n\t    while (i < src.length) {\n\t      if ((findByKey && src[i][findByKey] == find) || (!findByKey && src[i] === find)) {\n\t        return i;\n\t      }\n\t      i++;\n\t    }\n\t    return -1;\n\t  }\n\t}\n\n\t/**\n\t * convert array-like objects to real arrays\n\t * @param {Object} obj\n\t * @returns {Array}\n\t */\n\tfunction toArray(obj) {\n\t  return Array.prototype.slice.call(obj, 0);\n\t}\n\n\t/**\n\t * unique array with objects based on a key (like 'id') or just by the array's value\n\t * @param {Array} src [{id:1},{id:2},{id:1}]\n\t * @param {String} [key]\n\t * @param {Boolean} [sort=False]\n\t * @returns {Array} [{id:1},{id:2}]\n\t */\n\tfunction uniqueArray(src, key, sort) {\n\t  var results = [];\n\t  var values = [];\n\t  var i = 0;\n\n\t  while (i < src.length) {\n\t    var val = key ? src[i][key] : src[i];\n\t    if (inArray(values, val) < 0) {\n\t      results.push(src[i]);\n\t    }\n\t    values[i] = val;\n\t    i++;\n\t  }\n\n\t  if (sort) {\n\t    if (!key) {\n\t      results = results.sort();\n\t    } else {\n\t      results = results.sort(function sortUniqueArray(a, b) {\n\t        return a[key] > b[key];\n\t      });\n\t    }\n\t  }\n\n\t  return results;\n\t}\n\n\t/**\n\t * get the prefixed property\n\t * @param {Object} obj\n\t * @param {String} property\n\t * @returns {String|Undefined} prefixed\n\t */\n\tfunction prefixed(obj, property) {\n\t  var prefix, prop;\n\t  var camelProp = property[0].toUpperCase() + property.slice(1);\n\n\t  var i = 0;\n\t  while (i < VENDOR_PREFIXES.length) {\n\t    prefix = VENDOR_PREFIXES[i];\n\t    prop = (prefix) ? prefix + camelProp : property;\n\n\t    if (prop in obj) {\n\t      return prop;\n\t    }\n\t    i++;\n\t  }\n\t  return undefined;\n\t}\n\n\t/**\n\t * get a unique id\n\t * @returns {number} uniqueId\n\t */\n\tvar _uniqueId = 1;\n\tfunction uniqueId() {\n\t  return _uniqueId++;\n\t}\n\n\t/**\n\t * get the window object of an element\n\t * @param {HTMLElement} element\n\t * @returns {DocumentView|Window}\n\t */\n\tfunction getWindowForElement(element) {\n\t  var doc = element.ownerDocument || element;\n\t  return (doc.defaultView || doc.parentWindow || window);\n\t}\n\n\tvar MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i;\n\n\tvar SUPPORT_TOUCH = ('ontouchstart' in window);\n\tvar SUPPORT_POINTER_EVENTS = prefixed(window, 'PointerEvent') !== undefined;\n\tvar SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent);\n\n\tvar INPUT_TYPE_TOUCH = 'touch';\n\tvar INPUT_TYPE_PEN = 'pen';\n\tvar INPUT_TYPE_MOUSE = 'mouse';\n\tvar INPUT_TYPE_KINECT = 'kinect';\n\n\tvar COMPUTE_INTERVAL = 25;\n\n\tvar INPUT_START = 1;\n\tvar INPUT_MOVE = 2;\n\tvar INPUT_END = 4;\n\tvar INPUT_CANCEL = 8;\n\n\tvar DIRECTION_NONE = 1;\n\tvar DIRECTION_LEFT = 2;\n\tvar DIRECTION_RIGHT = 4;\n\tvar DIRECTION_UP = 8;\n\tvar DIRECTION_DOWN = 16;\n\n\tvar DIRECTION_HORIZONTAL = DIRECTION_LEFT | DIRECTION_RIGHT;\n\tvar DIRECTION_VERTICAL = DIRECTION_UP | DIRECTION_DOWN;\n\tvar DIRECTION_ALL = DIRECTION_HORIZONTAL | DIRECTION_VERTICAL;\n\n\tvar PROPS_XY = ['x', 'y'];\n\tvar PROPS_CLIENT_XY = ['clientX', 'clientY'];\n\n\t/**\n\t * create new input type manager\n\t * @param {Manager} manager\n\t * @param {Function} callback\n\t * @returns {Input}\n\t * @constructor\n\t */\n\tfunction Input(manager, callback) {\n\t  var self = this;\n\t  this.manager = manager;\n\t  this.callback = callback;\n\t  this.element = manager.element;\n\t  this.target = manager.options.inputTarget;\n\n\t  // smaller wrapper around the handler, for the scope and the enabled state of the manager,\n\t  // so when disabled the input events are completely bypassed.\n\t  this.domHandler = function(ev) {\n\t    if (boolOrFn(manager.options.enable, [manager])) {\n\t      self.handler(ev);\n\t    }\n\t  };\n\n\t  this.init();\n\n\t}\n\n\tInput.prototype = {\n\t  /**\n\t   * should handle the inputEvent data and trigger the callback\n\t   * @virtual\n\t   */\n\t  handler: function() { },\n\n\t  /**\n\t   * bind the events\n\t   */\n\t  init: function() {\n\t    this.evEl && addEventListeners(this.element, this.evEl, this.domHandler);\n\t    this.evTarget && addEventListeners(this.target, this.evTarget, this.domHandler);\n\t    this.evWin && addEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler);\n\t  },\n\n\t  /**\n\t   * unbind the events\n\t   */\n\t  destroy: function() {\n\t    this.evEl && removeEventListeners(this.element, this.evEl, this.domHandler);\n\t    this.evTarget && removeEventListeners(this.target, this.evTarget, this.domHandler);\n\t    this.evWin && removeEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler);\n\t  }\n\t};\n\n\t/**\n\t * create new input type manager\n\t * called by the Manager constructor\n\t * @param {Hammer} manager\n\t * @returns {Input}\n\t */\n\tfunction createInputInstance(manager) {\n\t  var Type;\n\t  var inputClass = manager.options.inputClass;\n\n\t  if (inputClass) {\n\t    Type = inputClass;\n\t  } else if (SUPPORT_POINTER_EVENTS) {\n\t    Type = PointerEventInput;\n\t  } else if (SUPPORT_ONLY_TOUCH) {\n\t    Type = TouchInput;\n\t  } else if (!SUPPORT_TOUCH) {\n\t    Type = MouseInput;\n\t  } else {\n\t    Type = TouchMouseInput;\n\t  }\n\t  return new (Type)(manager, inputHandler);\n\t}\n\n\t/**\n\t * handle input events\n\t * @param {Manager} manager\n\t * @param {String} eventType\n\t * @param {Object} input\n\t */\n\tfunction inputHandler(manager, eventType, input) {\n\t  var pointersLen = input.pointers.length;\n\t  var changedPointersLen = input.changedPointers.length;\n\t  var isFirst = (eventType & INPUT_START && (pointersLen - changedPointersLen === 0));\n\t  var isFinal = (eventType & (INPUT_END | INPUT_CANCEL) && (pointersLen - changedPointersLen === 0));\n\n\t  input.isFirst = !!isFirst;\n\t  input.isFinal = !!isFinal;\n\n\t  if (isFirst) {\n\t    manager.session = {};\n\t  }\n\n\t  // source event is the normalized value of the domEvents\n\t  // like 'touchstart, mouseup, pointerdown'\n\t  input.eventType = eventType;\n\n\t  // compute scale, rotation etc\n\t  computeInputData(manager, input);\n\n\t  // emit secret event\n\t  manager.emit('hammer.input', input);\n\n\t  manager.recognize(input);\n\t  manager.session.prevInput = input;\n\t}\n\n\t/**\n\t * extend the data with some usable properties like scale, rotate, velocity etc\n\t * @param {Object} manager\n\t * @param {Object} input\n\t */\n\tfunction computeInputData(manager, input) {\n\t  var session = manager.session;\n\t  var pointers = input.pointers;\n\t  var pointersLength = pointers.length;\n\n\t  // store the first input to calculate the distance and direction\n\t  if (!session.firstInput) {\n\t    session.firstInput = simpleCloneInputData(input);\n\t  }\n\n\t  // to compute scale and rotation we need to store the multiple touches\n\t  if (pointersLength > 1 && !session.firstMultiple) {\n\t    session.firstMultiple = simpleCloneInputData(input);\n\t  } else if (pointersLength === 1) {\n\t    session.firstMultiple = false;\n\t  }\n\n\t  var firstInput = session.firstInput;\n\t  var firstMultiple = session.firstMultiple;\n\t  var offsetCenter = firstMultiple ? firstMultiple.center : firstInput.center;\n\n\t  var center = input.center = getCenter(pointers);\n\t  input.timeStamp = now();\n\t  input.deltaTime = input.timeStamp - firstInput.timeStamp;\n\n\t  input.angle = getAngle(offsetCenter, center);\n\t  input.distance = getDistance(offsetCenter, center);\n\n\t  computeDeltaXY(session, input);\n\t  input.offsetDirection = getDirection(input.deltaX, input.deltaY);\n\n\t  var overallVelocity = getVelocity(input.deltaTime, input.deltaX, input.deltaY);\n\t  input.overallVelocityX = overallVelocity.x;\n\t  input.overallVelocityY = overallVelocity.y;\n\t  input.overallVelocity = (abs(overallVelocity.x) > abs(overallVelocity.y)) ? overallVelocity.x : overallVelocity.y;\n\n\t  input.scale = firstMultiple ? getScale(firstMultiple.pointers, pointers) : 1;\n\t  input.rotation = firstMultiple ? getRotation(firstMultiple.pointers, pointers) : 0;\n\n\t  input.maxPointers = !session.prevInput ? input.pointers.length : ((input.pointers.length >\n\t  session.prevInput.maxPointers) ? input.pointers.length : session.prevInput.maxPointers);\n\n\t  computeIntervalInputData(session, input);\n\n\t  // find the correct target\n\t  var target = manager.element;\n\t  if (hasParent(input.srcEvent.target, target)) {\n\t    target = input.srcEvent.target;\n\t  }\n\t  input.target = target;\n\t}\n\n\tfunction computeDeltaXY(session, input) {\n\t  var center = input.center;\n\t  var offset = session.offsetDelta || {};\n\t  var prevDelta = session.prevDelta || {};\n\t  var prevInput = session.prevInput || {};\n\n\t  if (input.eventType === INPUT_START || prevInput.eventType === INPUT_END) {\n\t    prevDelta = session.prevDelta = {\n\t      x: prevInput.deltaX || 0,\n\t      y: prevInput.deltaY || 0\n\t    };\n\n\t    offset = session.offsetDelta = {\n\t      x: center.x,\n\t      y: center.y\n\t    };\n\t  }\n\n\t  input.deltaX = prevDelta.x + (center.x - offset.x);\n\t  input.deltaY = prevDelta.y + (center.y - offset.y);\n\t}\n\n\t/**\n\t * velocity is calculated every x ms\n\t * @param {Object} session\n\t * @param {Object} input\n\t */\n\tfunction computeIntervalInputData(session, input) {\n\t  var last = session.lastInterval || input,\n\t    deltaTime = input.timeStamp - last.timeStamp,\n\t    velocity, velocityX, velocityY, direction;\n\n\t  if (input.eventType != INPUT_CANCEL && (deltaTime > COMPUTE_INTERVAL || last.velocity === undefined)) {\n\t    var deltaX = input.deltaX - last.deltaX;\n\t    var deltaY = input.deltaY - last.deltaY;\n\n\t    var v = getVelocity(deltaTime, deltaX, deltaY);\n\t    velocityX = v.x;\n\t    velocityY = v.y;\n\t    velocity = (abs(v.x) > abs(v.y)) ? v.x : v.y;\n\t    direction = getDirection(deltaX, deltaY);\n\n\t    session.lastInterval = input;\n\t  } else {\n\t    // use latest velocity info if it doesn't overtake a minimum period\n\t    velocity = last.velocity;\n\t    velocityX = last.velocityX;\n\t    velocityY = last.velocityY;\n\t    direction = last.direction;\n\t  }\n\n\t  input.velocity = velocity;\n\t  input.velocityX = velocityX;\n\t  input.velocityY = velocityY;\n\t  input.direction = direction;\n\t}\n\n\t/**\n\t * create a simple clone from the input used for storage of firstInput and firstMultiple\n\t * @param {Object} input\n\t * @returns {Object} clonedInputData\n\t */\n\tfunction simpleCloneInputData(input) {\n\t  // make a simple copy of the pointers because we will get a reference if we don't\n\t  // we only need clientXY for the calculations\n\t  var pointers = [];\n\t  var i = 0;\n\t  while (i < input.pointers.length) {\n\t    pointers[i] = {\n\t      clientX: round(input.pointers[i].clientX),\n\t      clientY: round(input.pointers[i].clientY)\n\t    };\n\t    i++;\n\t  }\n\n\t  return {\n\t    timeStamp: now(),\n\t    pointers: pointers,\n\t    center: getCenter(pointers),\n\t    deltaX: input.deltaX,\n\t    deltaY: input.deltaY\n\t  };\n\t}\n\n\t/**\n\t * get the center of all the pointers\n\t * @param {Array} pointers\n\t * @return {Object} center contains `x` and `y` properties\n\t */\n\tfunction getCenter(pointers) {\n\t  var pointersLength = pointers.length;\n\n\t  // no need to loop when only one touch\n\t  if (pointersLength === 1) {\n\t    return {\n\t      x: round(pointers[0].clientX),\n\t      y: round(pointers[0].clientY)\n\t    };\n\t  }\n\n\t  var x = 0, y = 0, i = 0;\n\t  while (i < pointersLength) {\n\t    x += pointers[i].clientX;\n\t    y += pointers[i].clientY;\n\t    i++;\n\t  }\n\n\t  return {\n\t    x: round(x / pointersLength),\n\t    y: round(y / pointersLength)\n\t  };\n\t}\n\n\t/**\n\t * calculate the velocity between two points. unit is in px per ms.\n\t * @param {Number} deltaTime\n\t * @param {Number} x\n\t * @param {Number} y\n\t * @return {Object} velocity `x` and `y`\n\t */\n\tfunction getVelocity(deltaTime, x, y) {\n\t  return {\n\t    x: x / deltaTime || 0,\n\t    y: y / deltaTime || 0\n\t  };\n\t}\n\n\t/**\n\t * get the direction between two points\n\t * @param {Number} x\n\t * @param {Number} y\n\t * @return {Number} direction\n\t */\n\tfunction getDirection(x, y) {\n\t  if (x === y) {\n\t    return DIRECTION_NONE;\n\t  }\n\n\t  if (abs(x) >= abs(y)) {\n\t    return x < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT;\n\t  }\n\t  return y < 0 ? DIRECTION_UP : DIRECTION_DOWN;\n\t}\n\n\t/**\n\t * calculate the absolute distance between two points\n\t * @param {Object} p1 {x, y}\n\t * @param {Object} p2 {x, y}\n\t * @param {Array} [props] containing x and y keys\n\t * @return {Number} distance\n\t */\n\tfunction getDistance(p1, p2, props) {\n\t  if (!props) {\n\t    props = PROPS_XY;\n\t  }\n\t  var x = p2[props[0]] - p1[props[0]],\n\t    y = p2[props[1]] - p1[props[1]];\n\n\t  return Math.sqrt((x * x) + (y * y));\n\t}\n\n\t/**\n\t * calculate the angle between two coordinates\n\t * @param {Object} p1\n\t * @param {Object} p2\n\t * @param {Array} [props] containing x and y keys\n\t * @return {Number} angle\n\t */\n\tfunction getAngle(p1, p2, props) {\n\t  if (!props) {\n\t    props = PROPS_XY;\n\t  }\n\t  var x = p2[props[0]] - p1[props[0]],\n\t    y = p2[props[1]] - p1[props[1]];\n\t  return Math.atan2(y, x) * 180 / Math.PI;\n\t}\n\n\t/**\n\t * calculate the rotation degrees between two pointersets\n\t * @param {Array} start array of pointers\n\t * @param {Array} end array of pointers\n\t * @return {Number} rotation\n\t */\n\tfunction getRotation(start, end) {\n\t  return getAngle(end[1], end[0], PROPS_CLIENT_XY) + getAngle(start[1], start[0], PROPS_CLIENT_XY);\n\t}\n\n\t/**\n\t * calculate the scale factor between two pointersets\n\t * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out\n\t * @param {Array} start array of pointers\n\t * @param {Array} end array of pointers\n\t * @return {Number} scale\n\t */\n\tfunction getScale(start, end) {\n\t  return getDistance(end[0], end[1], PROPS_CLIENT_XY) / getDistance(start[0], start[1], PROPS_CLIENT_XY);\n\t}\n\n\tvar MOUSE_INPUT_MAP = {\n\t  mousedown: INPUT_START,\n\t  mousemove: INPUT_MOVE,\n\t  mouseup: INPUT_END\n\t};\n\n\tvar MOUSE_ELEMENT_EVENTS = 'mousedown';\n\tvar MOUSE_WINDOW_EVENTS = 'mousemove mouseup';\n\n\t/**\n\t * Mouse events input\n\t * @constructor\n\t * @extends Input\n\t */\n\tfunction MouseInput() {\n\t  this.evEl = MOUSE_ELEMENT_EVENTS;\n\t  this.evWin = MOUSE_WINDOW_EVENTS;\n\n\t  this.allow = true; // used by Input.TouchMouse to disable mouse events\n\t  this.pressed = false; // mousedown state\n\n\t  Input.apply(this, arguments);\n\t}\n\n\tinherit(MouseInput, Input, {\n\t  /**\n\t   * handle mouse events\n\t   * @param {Object} ev\n\t   */\n\t  handler: function MEhandler(ev) {\n\t    var eventType = MOUSE_INPUT_MAP[ev.type];\n\n\t    // on start we want to have the left mouse button down\n\t    if (eventType & INPUT_START && ev.button === 0) {\n\t      this.pressed = true;\n\t    }\n\n\t    if (eventType & INPUT_MOVE && ev.which !== 1) {\n\t      eventType = INPUT_END;\n\t    }\n\n\t    // mouse must be down, and mouse events are allowed (see the TouchMouse input)\n\t    if (!this.pressed || !this.allow) {\n\t      return;\n\t    }\n\n\t    if (eventType & INPUT_END) {\n\t      this.pressed = false;\n\t    }\n\n\t    this.callback(this.manager, eventType, {\n\t      pointers: [ev],\n\t      changedPointers: [ev],\n\t      pointerType: INPUT_TYPE_MOUSE,\n\t      srcEvent: ev\n\t    });\n\t  }\n\t});\n\n\tvar POINTER_INPUT_MAP = {\n\t  pointerdown: INPUT_START,\n\t  pointermove: INPUT_MOVE,\n\t  pointerup: INPUT_END,\n\t  pointercancel: INPUT_CANCEL,\n\t  pointerout: INPUT_CANCEL\n\t};\n\n\t// in IE10 the pointer types is defined as an enum\n\tvar IE10_POINTER_TYPE_ENUM = {\n\t  2: INPUT_TYPE_TOUCH,\n\t  3: INPUT_TYPE_PEN,\n\t  4: INPUT_TYPE_MOUSE,\n\t  5: INPUT_TYPE_KINECT // see https://twitter.com/jacobrossi/status/480596438489890816\n\t};\n\n\tvar POINTER_ELEMENT_EVENTS = 'pointerdown';\n\tvar POINTER_WINDOW_EVENTS = 'pointermove pointerup pointercancel';\n\n\t// IE10 has prefixed support, and case-sensitive\n\tif (window.MSPointerEvent && !window.PointerEvent) {\n\t  POINTER_ELEMENT_EVENTS = 'MSPointerDown';\n\t  POINTER_WINDOW_EVENTS = 'MSPointerMove MSPointerUp MSPointerCancel';\n\t}\n\n\t/**\n\t * Pointer events input\n\t * @constructor\n\t * @extends Input\n\t */\n\tfunction PointerEventInput() {\n\t  this.evEl = POINTER_ELEMENT_EVENTS;\n\t  this.evWin = POINTER_WINDOW_EVENTS;\n\n\t  Input.apply(this, arguments);\n\n\t  this.store = (this.manager.session.pointerEvents = []);\n\t}\n\n\tinherit(PointerEventInput, Input, {\n\t  /**\n\t   * handle mouse events\n\t   * @param {Object} ev\n\t   */\n\t  handler: function PEhandler(ev) {\n\t    var store = this.store;\n\t    var removePointer = false;\n\n\t    var eventTypeNormalized = ev.type.toLowerCase().replace('ms', '');\n\t    var eventType = POINTER_INPUT_MAP[eventTypeNormalized];\n\t    var pointerType = IE10_POINTER_TYPE_ENUM[ev.pointerType] || ev.pointerType;\n\n\t    var isTouch = (pointerType == INPUT_TYPE_TOUCH);\n\n\t    // get index of the event in the store\n\t    var storeIndex = inArray(store, ev.pointerId, 'pointerId');\n\n\t    // start and mouse must be down\n\t    if (eventType & INPUT_START && (ev.button === 0 || isTouch)) {\n\t      if (storeIndex < 0) {\n\t        store.push(ev);\n\t        storeIndex = store.length - 1;\n\t      }\n\t    } else if (eventType & (INPUT_END | INPUT_CANCEL)) {\n\t      removePointer = true;\n\t    }\n\n\t    // it not found, so the pointer hasn't been down (so it's probably a hover)\n\t    if (storeIndex < 0) {\n\t      return;\n\t    }\n\n\t    // update the event in the store\n\t    store[storeIndex] = ev;\n\n\t    this.callback(this.manager, eventType, {\n\t      pointers: store,\n\t      changedPointers: [ev],\n\t      pointerType: pointerType,\n\t      srcEvent: ev\n\t    });\n\n\t    if (removePointer) {\n\t      // remove from the store\n\t      store.splice(storeIndex, 1);\n\t    }\n\t  }\n\t});\n\n\tvar SINGLE_TOUCH_INPUT_MAP = {\n\t  touchstart: INPUT_START,\n\t  touchmove: INPUT_MOVE,\n\t  touchend: INPUT_END,\n\t  touchcancel: INPUT_CANCEL\n\t};\n\n\tvar SINGLE_TOUCH_TARGET_EVENTS = 'touchstart';\n\tvar SINGLE_TOUCH_WINDOW_EVENTS = 'touchstart touchmove touchend touchcancel';\n\n\t/**\n\t * Touch events input\n\t * @constructor\n\t * @extends Input\n\t */\n\tfunction SingleTouchInput() {\n\t  this.evTarget = SINGLE_TOUCH_TARGET_EVENTS;\n\t  this.evWin = SINGLE_TOUCH_WINDOW_EVENTS;\n\t  this.started = false;\n\n\t  Input.apply(this, arguments);\n\t}\n\n\tinherit(SingleTouchInput, Input, {\n\t  handler: function TEhandler(ev) {\n\t    var type = SINGLE_TOUCH_INPUT_MAP[ev.type];\n\n\t    // should we handle the touch events?\n\t    if (type === INPUT_START) {\n\t      this.started = true;\n\t    }\n\n\t    if (!this.started) {\n\t      return;\n\t    }\n\n\t    var touches = normalizeSingleTouches.call(this, ev, type);\n\n\t    // when done, reset the started state\n\t    if (type & (INPUT_END | INPUT_CANCEL) && touches[0].length - touches[1].length === 0) {\n\t      this.started = false;\n\t    }\n\n\t    this.callback(this.manager, type, {\n\t      pointers: touches[0],\n\t      changedPointers: touches[1],\n\t      pointerType: INPUT_TYPE_TOUCH,\n\t      srcEvent: ev\n\t    });\n\t  }\n\t});\n\n\t/**\n\t * @this {TouchInput}\n\t * @param {Object} ev\n\t * @param {Number} type flag\n\t * @returns {undefined|Array} [all, changed]\n\t */\n\tfunction normalizeSingleTouches(ev, type) {\n\t  var all = toArray(ev.touches);\n\t  var changed = toArray(ev.changedTouches);\n\n\t  if (type & (INPUT_END | INPUT_CANCEL)) {\n\t    all = uniqueArray(all.concat(changed), 'identifier', true);\n\t  }\n\n\t  return [all, changed];\n\t}\n\n\tvar TOUCH_INPUT_MAP = {\n\t  touchstart: INPUT_START,\n\t  touchmove: INPUT_MOVE,\n\t  touchend: INPUT_END,\n\t  touchcancel: INPUT_CANCEL\n\t};\n\n\tvar TOUCH_TARGET_EVENTS = 'touchstart touchmove touchend touchcancel';\n\n\t/**\n\t * Multi-user touch events input\n\t * @constructor\n\t * @extends Input\n\t */\n\tfunction TouchInput() {\n\t  this.evTarget = TOUCH_TARGET_EVENTS;\n\t  this.targetIds = {};\n\n\t  Input.apply(this, arguments);\n\t}\n\n\tinherit(TouchInput, Input, {\n\t  handler: function MTEhandler(ev) {\n\t    var type = TOUCH_INPUT_MAP[ev.type];\n\t    var touches = getTouches.call(this, ev, type);\n\t    if (!touches) {\n\t      return;\n\t    }\n\n\t    this.callback(this.manager, type, {\n\t      pointers: touches[0],\n\t      changedPointers: touches[1],\n\t      pointerType: INPUT_TYPE_TOUCH,\n\t      srcEvent: ev\n\t    });\n\t  }\n\t});\n\n\t/**\n\t * @this {TouchInput}\n\t * @param {Object} ev\n\t * @param {Number} type flag\n\t * @returns {undefined|Array} [all, changed]\n\t */\n\tfunction getTouches(ev, type) {\n\t  var allTouches = toArray(ev.touches);\n\t  var targetIds = this.targetIds;\n\n\t  // when there is only one touch, the process can be simplified\n\t  if (type & (INPUT_START | INPUT_MOVE) && allTouches.length === 1) {\n\t    targetIds[allTouches[0].identifier] = true;\n\t    return [allTouches, allTouches];\n\t  }\n\n\t  var i,\n\t    targetTouches,\n\t    changedTouches = toArray(ev.changedTouches),\n\t    changedTargetTouches = [],\n\t    target = this.target;\n\n\t  // get target touches from touches\n\t  targetTouches = allTouches.filter(function(touch) {\n\t    return hasParent(touch.target, target);\n\t  });\n\n\t  // collect touches\n\t  if (type === INPUT_START) {\n\t    i = 0;\n\t    while (i < targetTouches.length) {\n\t      targetIds[targetTouches[i].identifier] = true;\n\t      i++;\n\t    }\n\t  }\n\n\t  // filter changed touches to only contain touches that exist in the collected target ids\n\t  i = 0;\n\t  while (i < changedTouches.length) {\n\t    if (targetIds[changedTouches[i].identifier]) {\n\t      changedTargetTouches.push(changedTouches[i]);\n\t    }\n\n\t    // cleanup removed touches\n\t    if (type & (INPUT_END | INPUT_CANCEL)) {\n\t      delete targetIds[changedTouches[i].identifier];\n\t    }\n\t    i++;\n\t  }\n\n\t  if (!changedTargetTouches.length) {\n\t    return;\n\t  }\n\n\t  return [\n\t    // merge targetTouches with changedTargetTouches so it contains ALL touches, including 'end' and 'cancel'\n\t    uniqueArray(targetTouches.concat(changedTargetTouches), 'identifier', true),\n\t    changedTargetTouches\n\t  ];\n\t}\n\n\t/**\n\t * Combined touch and mouse input\n\t *\n\t * Touch has a higher priority then mouse, and while touching no mouse events are allowed.\n\t * This because touch devices also emit mouse events while doing a touch.\n\t *\n\t * @constructor\n\t * @extends Input\n\t */\n\tfunction TouchMouseInput() {\n\t  Input.apply(this, arguments);\n\n\t  var handler = bindFn(this.handler, this);\n\t  this.touch = new TouchInput(this.manager, handler);\n\t  this.mouse = new MouseInput(this.manager, handler);\n\t}\n\n\tinherit(TouchMouseInput, Input, {\n\t  /**\n\t   * handle mouse and touch events\n\t   * @param {Hammer} manager\n\t   * @param {String} inputEvent\n\t   * @param {Object} inputData\n\t   */\n\t  handler: function TMEhandler(manager, inputEvent, inputData) {\n\t    var isTouch = (inputData.pointerType == INPUT_TYPE_TOUCH),\n\t      isMouse = (inputData.pointerType == INPUT_TYPE_MOUSE);\n\n\t    // when we're in a touch event, so  block all upcoming mouse events\n\t    // most mobile browser also emit mouseevents, right after touchstart\n\t    if (isTouch) {\n\t      this.mouse.allow = false;\n\t    } else if (isMouse && !this.mouse.allow) {\n\t      return;\n\t    }\n\n\t    // reset the allowMouse when we're done\n\t    if (inputEvent & (INPUT_END | INPUT_CANCEL)) {\n\t      this.mouse.allow = true;\n\t    }\n\n\t    this.callback(manager, inputEvent, inputData);\n\t  },\n\n\t  /**\n\t   * remove the event listeners\n\t   */\n\t  destroy: function destroy() {\n\t    this.touch.destroy();\n\t    this.mouse.destroy();\n\t  }\n\t});\n\n\tvar PREFIXED_TOUCH_ACTION = prefixed(TEST_ELEMENT.style, 'touchAction');\n\tvar NATIVE_TOUCH_ACTION = PREFIXED_TOUCH_ACTION !== undefined;\n\n\t// magical touchAction value\n\tvar TOUCH_ACTION_COMPUTE = 'compute';\n\tvar TOUCH_ACTION_AUTO = 'auto';\n\tvar TOUCH_ACTION_MANIPULATION = 'manipulation'; // not implemented\n\tvar TOUCH_ACTION_NONE = 'none';\n\tvar TOUCH_ACTION_PAN_X = 'pan-x';\n\tvar TOUCH_ACTION_PAN_Y = 'pan-y';\n\n\t/**\n\t * Touch Action\n\t * sets the touchAction property or uses the js alternative\n\t * @param {Manager} manager\n\t * @param {String} value\n\t * @constructor\n\t */\n\tfunction TouchAction(manager, value) {\n\t  this.manager = manager;\n\t  this.set(value);\n\t}\n\n\tTouchAction.prototype = {\n\t  /**\n\t   * set the touchAction value on the element or enable the polyfill\n\t   * @param {String} value\n\t   */\n\t  set: function(value) {\n\t    // find out the touch-action by the event handlers\n\t    if (value == TOUCH_ACTION_COMPUTE) {\n\t      value = this.compute();\n\t    }\n\n\t    if (NATIVE_TOUCH_ACTION && this.manager.element.style) {\n\t      this.manager.element.style[PREFIXED_TOUCH_ACTION] = value;\n\t    }\n\t    this.actions = value.toLowerCase().trim();\n\t  },\n\n\t  /**\n\t   * just re-set the touchAction value\n\t   */\n\t  update: function() {\n\t    this.set(this.manager.options.touchAction);\n\t  },\n\n\t  /**\n\t   * compute the value for the touchAction property based on the recognizer's settings\n\t   * @returns {String} value\n\t   */\n\t  compute: function() {\n\t    var actions = [];\n\t    each(this.manager.recognizers, function(recognizer) {\n\t      if (boolOrFn(recognizer.options.enable, [recognizer])) {\n\t        actions = actions.concat(recognizer.getTouchAction());\n\t      }\n\t    });\n\t    return cleanTouchActions(actions.join(' '));\n\t  },\n\n\t  /**\n\t   * this method is called on each input cycle and provides the preventing of the browser behavior\n\t   * @param {Object} input\n\t   */\n\t  preventDefaults: function(input) {\n\t    // not needed with native support for the touchAction property\n\t    if (NATIVE_TOUCH_ACTION) {\n\t      return;\n\t    }\n\n\t    var srcEvent = input.srcEvent;\n\t    var direction = input.offsetDirection;\n\n\t    // if the touch action did prevented once this session\n\t    if (this.manager.session.prevented) {\n\t      srcEvent.preventDefault();\n\t      return;\n\t    }\n\n\t    var actions = this.actions;\n\t    var hasNone = inStr(actions, TOUCH_ACTION_NONE);\n\t    var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y);\n\t    var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X);\n\n\t    if (hasNone) {\n\t      //do not prevent defaults if this is a tap gesture\n\n\t      var isTapPointer = input.pointers.length === 1;\n\t      var isTapMovement = input.distance < 2;\n\t      var isTapTouchTime = input.deltaTime < 250;\n\n\t      if (isTapPointer && isTapMovement && isTapTouchTime) {\n\t        return;\n\t      }\n\t    }\n\n\t    if (hasPanX && hasPanY) {\n\t      // `pan-x pan-y` means browser handles all scrolling/panning, do not prevent\n\t      return;\n\t    }\n\n\t    if (hasNone ||\n\t      (hasPanY && direction & DIRECTION_HORIZONTAL) ||\n\t      (hasPanX && direction & DIRECTION_VERTICAL)) {\n\t      return this.preventSrc(srcEvent);\n\t    }\n\t  },\n\n\t  /**\n\t   * call preventDefault to prevent the browser's default behavior (scrolling in most cases)\n\t   * @param {Object} srcEvent\n\t   */\n\t  preventSrc: function(srcEvent) {\n\t    this.manager.session.prevented = true;\n\t    srcEvent.preventDefault();\n\t  }\n\t};\n\n\t/**\n\t * when the touchActions are collected they are not a valid value, so we need to clean things up. *\n\t * @param {String} actions\n\t * @returns {*}\n\t */\n\tfunction cleanTouchActions(actions) {\n\t  // none\n\t  if (inStr(actions, TOUCH_ACTION_NONE)) {\n\t    return TOUCH_ACTION_NONE;\n\t  }\n\n\t  var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X);\n\t  var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y);\n\n\t  // if both pan-x and pan-y are set (different recognizers\n\t  // for different directions, e.g. horizontal pan but vertical swipe?)\n\t  // we need none (as otherwise with pan-x pan-y combined none of these\n\t  // recognizers will work, since the browser would handle all panning\n\t  if (hasPanX && hasPanY) {\n\t    return TOUCH_ACTION_NONE;\n\t  }\n\n\t  // pan-x OR pan-y\n\t  if (hasPanX || hasPanY) {\n\t    return hasPanX ? TOUCH_ACTION_PAN_X : TOUCH_ACTION_PAN_Y;\n\t  }\n\n\t  // manipulation\n\t  if (inStr(actions, TOUCH_ACTION_MANIPULATION)) {\n\t    return TOUCH_ACTION_MANIPULATION;\n\t  }\n\n\t  return TOUCH_ACTION_AUTO;\n\t}\n\n\t/**\n\t * Recognizer flow explained; *\n\t * All recognizers have the initial state of POSSIBLE when a input session starts.\n\t * The definition of a input session is from the first input until the last input, with all it's movement in it. *\n\t * Example session for mouse-input: mousedown -> mousemove -> mouseup\n\t *\n\t * On each recognizing cycle (see Manager.recognize) the .recognize() method is executed\n\t * which determines with state it should be.\n\t *\n\t * If the recognizer has the state FAILED, CANCELLED or RECOGNIZED (equals ENDED), it is reset to\n\t * POSSIBLE to give it another change on the next cycle.\n\t *\n\t *               Possible\n\t *                  |\n\t *            +-----+---------------+\n\t *            |                     |\n\t *      +-----+-----+               |\n\t *      |           |               |\n\t *   Failed      Cancelled          |\n\t *                          +-------+------+\n\t *                          |              |\n\t *                      Recognized       Began\n\t *                                         |\n\t *                                      Changed\n\t *                                         |\n\t *                                  Ended/Recognized\n\t */\n\tvar STATE_POSSIBLE = 1;\n\tvar STATE_BEGAN = 2;\n\tvar STATE_CHANGED = 4;\n\tvar STATE_ENDED = 8;\n\tvar STATE_RECOGNIZED = STATE_ENDED;\n\tvar STATE_CANCELLED = 16;\n\tvar STATE_FAILED = 32;\n\n\t/**\n\t * Recognizer\n\t * Every recognizer needs to extend from this class.\n\t * @constructor\n\t * @param {Object} options\n\t */\n\tfunction Recognizer(options) {\n\t  this.options = assign({}, this.defaults, options || {});\n\n\t  this.id = uniqueId();\n\n\t  this.manager = null;\n\n\t  // default is enable true\n\t  this.options.enable = ifUndefined(this.options.enable, true);\n\n\t  this.state = STATE_POSSIBLE;\n\n\t  this.simultaneous = {};\n\t  this.requireFail = [];\n\t}\n\n\tRecognizer.prototype = {\n\t  /**\n\t   * @virtual\n\t   * @type {Object}\n\t   */\n\t  defaults: {},\n\n\t  /**\n\t   * set options\n\t   * @param {Object} options\n\t   * @return {Recognizer}\n\t   */\n\t  set: function(options) {\n\t    assign(this.options, options);\n\n\t    // also update the touchAction, in case something changed about the directions/enabled state\n\t    this.manager && this.manager.touchAction.update();\n\t    return this;\n\t  },\n\n\t  /**\n\t   * recognize simultaneous with an other recognizer.\n\t   * @param {Recognizer} otherRecognizer\n\t   * @returns {Recognizer} this\n\t   */\n\t  recognizeWith: function(otherRecognizer) {\n\t    if (invokeArrayArg(otherRecognizer, 'recognizeWith', this)) {\n\t      return this;\n\t    }\n\n\t    var simultaneous = this.simultaneous;\n\t    otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);\n\t    if (!simultaneous[otherRecognizer.id]) {\n\t      simultaneous[otherRecognizer.id] = otherRecognizer;\n\t      otherRecognizer.recognizeWith(this);\n\t    }\n\t    return this;\n\t  },\n\n\t  /**\n\t   * drop the simultaneous link. it doesnt remove the link on the other recognizer.\n\t   * @param {Recognizer} otherRecognizer\n\t   * @returns {Recognizer} this\n\t   */\n\t  dropRecognizeWith: function(otherRecognizer) {\n\t    if (invokeArrayArg(otherRecognizer, 'dropRecognizeWith', this)) {\n\t      return this;\n\t    }\n\n\t    otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);\n\t    delete this.simultaneous[otherRecognizer.id];\n\t    return this;\n\t  },\n\n\t  /**\n\t   * recognizer can only run when an other is failing\n\t   * @param {Recognizer} otherRecognizer\n\t   * @returns {Recognizer} this\n\t   */\n\t  requireFailure: function(otherRecognizer) {\n\t    if (invokeArrayArg(otherRecognizer, 'requireFailure', this)) {\n\t      return this;\n\t    }\n\n\t    var requireFail = this.requireFail;\n\t    otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);\n\t    if (inArray(requireFail, otherRecognizer) === -1) {\n\t      requireFail.push(otherRecognizer);\n\t      otherRecognizer.requireFailure(this);\n\t    }\n\t    return this;\n\t  },\n\n\t  /**\n\t   * drop the requireFailure link. it does not remove the link on the other recognizer.\n\t   * @param {Recognizer} otherRecognizer\n\t   * @returns {Recognizer} this\n\t   */\n\t  dropRequireFailure: function(otherRecognizer) {\n\t    if (invokeArrayArg(otherRecognizer, 'dropRequireFailure', this)) {\n\t      return this;\n\t    }\n\n\t    otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);\n\t    var index = inArray(this.requireFail, otherRecognizer);\n\t    if (index > -1) {\n\t      this.requireFail.splice(index, 1);\n\t    }\n\t    return this;\n\t  },\n\n\t  /**\n\t   * has require failures boolean\n\t   * @returns {boolean}\n\t   */\n\t  hasRequireFailures: function() {\n\t    return this.requireFail.length > 0;\n\t  },\n\n\t  /**\n\t   * if the recognizer can recognize simultaneous with an other recognizer\n\t   * @param {Recognizer} otherRecognizer\n\t   * @returns {Boolean}\n\t   */\n\t  canRecognizeWith: function(otherRecognizer) {\n\t    return !!this.simultaneous[otherRecognizer.id];\n\t  },\n\n\t  /**\n\t   * You should use `tryEmit` instead of `emit` directly to check\n\t   * that all the needed recognizers has failed before emitting.\n\t   * @param {Object} input\n\t   */\n\t  emit: function(input) {\n\t    var self = this;\n\t    var state = this.state;\n\n\t    function emit(event) {\n\t      self.manager.emit(event, input);\n\t    }\n\n\t    // 'panstart' and 'panmove'\n\t    if (state < STATE_ENDED) {\n\t      emit(self.options.event + stateStr(state));\n\t    }\n\n\t    emit(self.options.event); // simple 'eventName' events\n\n\t    if (input.additionalEvent) { // additional event(panleft, panright, pinchin, pinchout...)\n\t      emit(input.additionalEvent);\n\t    }\n\n\t    // panend and pancancel\n\t    if (state >= STATE_ENDED) {\n\t      emit(self.options.event + stateStr(state));\n\t    }\n\t  },\n\n\t  /**\n\t   * Check that all the require failure recognizers has failed,\n\t   * if true, it emits a gesture event,\n\t   * otherwise, setup the state to FAILED.\n\t   * @param {Object} input\n\t   */\n\t  tryEmit: function(input) {\n\t    if (this.canEmit()) {\n\t      return this.emit(input);\n\t    }\n\t    // it's failing anyway\n\t    this.state = STATE_FAILED;\n\t  },\n\n\t  /**\n\t   * can we emit?\n\t   * @returns {boolean}\n\t   */\n\t  canEmit: function() {\n\t    var i = 0;\n\t    while (i < this.requireFail.length) {\n\t      if (!(this.requireFail[i].state & (STATE_FAILED | STATE_POSSIBLE))) {\n\t        return false;\n\t      }\n\t      i++;\n\t    }\n\t    return true;\n\t  },\n\n\t  /**\n\t   * update the recognizer\n\t   * @param {Object} inputData\n\t   */\n\t  recognize: function(inputData) {\n\t    // make a new copy of the inputData\n\t    // so we can change the inputData without messing up the other recognizers\n\t    var inputDataClone = assign({}, inputData);\n\n\t    // is is enabled and allow recognizing?\n\t    if (!boolOrFn(this.options.enable, [this, inputDataClone])) {\n\t      this.reset();\n\t      this.state = STATE_FAILED;\n\t      return;\n\t    }\n\n\t    // reset when we've reached the end\n\t    if (this.state & (STATE_RECOGNIZED | STATE_CANCELLED | STATE_FAILED)) {\n\t      this.state = STATE_POSSIBLE;\n\t    }\n\n\t    this.state = this.process(inputDataClone);\n\n\t    // the recognizer has recognized a gesture\n\t    // so trigger an event\n\t    if (this.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED | STATE_CANCELLED)) {\n\t      this.tryEmit(inputDataClone);\n\t    }\n\t  },\n\n\t  /**\n\t   * return the state of the recognizer\n\t   * the actual recognizing happens in this method\n\t   * @virtual\n\t   * @param {Object} inputData\n\t   * @returns {Const} STATE\n\t   */\n\t  process: function(inputData) { }, // jshint ignore:line\n\n\t  /**\n\t   * return the preferred touch-action\n\t   * @virtual\n\t   * @returns {Array}\n\t   */\n\t  getTouchAction: function() { },\n\n\t  /**\n\t   * called when the gesture isn't allowed to recognize\n\t   * like when another is being recognized or it is disabled\n\t   * @virtual\n\t   */\n\t  reset: function() { }\n\t};\n\n\t/**\n\t * get a usable string, used as event postfix\n\t * @param {Const} state\n\t * @returns {String} state\n\t */\n\tfunction stateStr(state) {\n\t  if (state & STATE_CANCELLED) {\n\t    return 'cancel';\n\t  } else if (state & STATE_ENDED) {\n\t    return 'end';\n\t  } else if (state & STATE_CHANGED) {\n\t    return 'move';\n\t  } else if (state & STATE_BEGAN) {\n\t    return 'start';\n\t  }\n\t  return '';\n\t}\n\n\t/**\n\t * direction cons to string\n\t * @param {Const} direction\n\t * @returns {String}\n\t */\n\tfunction directionStr(direction) {\n\t  if (direction == DIRECTION_DOWN) {\n\t    return 'down';\n\t  } else if (direction == DIRECTION_UP) {\n\t    return 'up';\n\t  } else if (direction == DIRECTION_LEFT) {\n\t    return 'left';\n\t  } else if (direction == DIRECTION_RIGHT) {\n\t    return 'right';\n\t  }\n\t  return '';\n\t}\n\n\t/**\n\t * get a recognizer by name if it is bound to a manager\n\t * @param {Recognizer|String} otherRecognizer\n\t * @param {Recognizer} recognizer\n\t * @returns {Recognizer}\n\t */\n\tfunction getRecognizerByNameIfManager(otherRecognizer, recognizer) {\n\t  var manager = recognizer.manager;\n\t  if (manager) {\n\t    return manager.get(otherRecognizer);\n\t  }\n\t  return otherRecognizer;\n\t}\n\n\t/**\n\t * This recognizer is just used as a base for the simple attribute recognizers.\n\t * @constructor\n\t * @extends Recognizer\n\t */\n\tfunction AttrRecognizer() {\n\t  Recognizer.apply(this, arguments);\n\t}\n\n\tinherit(AttrRecognizer, Recognizer, {\n\t  /**\n\t   * @namespace\n\t   * @memberof AttrRecognizer\n\t   */\n\t  defaults: {\n\t    /**\n\t     * @type {Number}\n\t     * @default 1\n\t     */\n\t    pointers: 1\n\t  },\n\n\t  /**\n\t   * Used to check if it the recognizer receives valid input, like input.distance > 10.\n\t   * @memberof AttrRecognizer\n\t   * @param {Object} input\n\t   * @returns {Boolean} recognized\n\t   */\n\t  attrTest: function(input) {\n\t    var optionPointers = this.options.pointers;\n\t    return optionPointers === 0 || input.pointers.length === optionPointers;\n\t  },\n\n\t  /**\n\t   * Process the input and return the state for the recognizer\n\t   * @memberof AttrRecognizer\n\t   * @param {Object} input\n\t   * @returns {*} State\n\t   */\n\t  process: function(input) {\n\t    var state = this.state;\n\t    var eventType = input.eventType;\n\n\t    var isRecognized = state & (STATE_BEGAN | STATE_CHANGED);\n\t    var isValid = this.attrTest(input);\n\n\t    // on cancel input and we've recognized before, return STATE_CANCELLED\n\t    if (isRecognized && (eventType & INPUT_CANCEL || !isValid)) {\n\t      return state | STATE_CANCELLED;\n\t    } else if (isRecognized || isValid) {\n\t      if (eventType & INPUT_END) {\n\t        return state | STATE_ENDED;\n\t      } else if (!(state & STATE_BEGAN)) {\n\t        return STATE_BEGAN;\n\t      }\n\t      return state | STATE_CHANGED;\n\t    }\n\t    return STATE_FAILED;\n\t  }\n\t});\n\n\t/**\n\t * Pan\n\t * Recognized when the pointer is down and moved in the allowed direction.\n\t * @constructor\n\t * @extends AttrRecognizer\n\t */\n\tfunction PanRecognizer() {\n\t  AttrRecognizer.apply(this, arguments);\n\n\t  this.pX = null;\n\t  this.pY = null;\n\t}\n\n\tinherit(PanRecognizer, AttrRecognizer, {\n\t  /**\n\t   * @namespace\n\t   * @memberof PanRecognizer\n\t   */\n\t  defaults: {\n\t    event: 'pan',\n\t    threshold: 10,\n\t    pointers: 1,\n\t    direction: DIRECTION_ALL\n\t  },\n\n\t  getTouchAction: function() {\n\t    var direction = this.options.direction;\n\t    var actions = [];\n\t    if (direction & DIRECTION_HORIZONTAL) {\n\t      actions.push(TOUCH_ACTION_PAN_Y);\n\t    }\n\t    if (direction & DIRECTION_VERTICAL) {\n\t      actions.push(TOUCH_ACTION_PAN_X);\n\t    }\n\t    return actions;\n\t  },\n\n\t  directionTest: function(input) {\n\t    var options = this.options;\n\t    var hasMoved = true;\n\t    var distance = input.distance;\n\t    var direction = input.direction;\n\t    var x = input.deltaX;\n\t    var y = input.deltaY;\n\n\t    // lock to axis?\n\t    if (!(direction & options.direction)) {\n\t      if (options.direction & DIRECTION_HORIZONTAL) {\n\t        direction = (x === 0) ? DIRECTION_NONE : (x < 0) ? DIRECTION_LEFT : DIRECTION_RIGHT;\n\t        hasMoved = x != this.pX;\n\t        distance = Math.abs(input.deltaX);\n\t      } else {\n\t        direction = (y === 0) ? DIRECTION_NONE : (y < 0) ? DIRECTION_UP : DIRECTION_DOWN;\n\t        hasMoved = y != this.pY;\n\t        distance = Math.abs(input.deltaY);\n\t      }\n\t    }\n\t    input.direction = direction;\n\t    return hasMoved && distance > options.threshold && direction & options.direction;\n\t  },\n\n\t  attrTest: function(input) {\n\t    return AttrRecognizer.prototype.attrTest.call(this, input) &&\n\t      (this.state & STATE_BEGAN || (!(this.state & STATE_BEGAN) && this.directionTest(input)));\n\t  },\n\n\t  emit: function(input) {\n\n\t    this.pX = input.deltaX;\n\t    this.pY = input.deltaY;\n\n\t    var direction = directionStr(input.direction);\n\n\t    if (direction) {\n\t      input.additionalEvent = this.options.event + direction;\n\t    }\n\t    this._super.emit.call(this, input);\n\t  }\n\t});\n\n\t/**\n\t * Pinch\n\t * Recognized when two or more pointers are moving toward (zoom-in) or away from each other (zoom-out).\n\t * @constructor\n\t * @extends AttrRecognizer\n\t */\n\tfunction PinchRecognizer() {\n\t  AttrRecognizer.apply(this, arguments);\n\t}\n\n\tinherit(PinchRecognizer, AttrRecognizer, {\n\t  /**\n\t   * @namespace\n\t   * @memberof PinchRecognizer\n\t   */\n\t  defaults: {\n\t    event: 'pinch',\n\t    threshold: 0,\n\t    pointers: 2\n\t  },\n\n\t  getTouchAction: function() {\n\t    return [TOUCH_ACTION_NONE];\n\t  },\n\n\t  attrTest: function(input) {\n\t    return this._super.attrTest.call(this, input) &&\n\t      (Math.abs(input.scale - 1) > this.options.threshold || this.state & STATE_BEGAN);\n\t  },\n\n\t  emit: function(input) {\n\t    if (input.scale !== 1) {\n\t      var inOut = input.scale < 1 ? 'in' : 'out';\n\t      input.additionalEvent = this.options.event + inOut;\n\t    }\n\t    this._super.emit.call(this, input);\n\t  }\n\t});\n\n\t/**\n\t * Press\n\t * Recognized when the pointer is down for x ms without any movement.\n\t * @constructor\n\t * @extends Recognizer\n\t */\n\tfunction PressRecognizer() {\n\t  Recognizer.apply(this, arguments);\n\n\t  this._timer = null;\n\t  this._input = null;\n\t}\n\n\tinherit(PressRecognizer, Recognizer, {\n\t  /**\n\t   * @namespace\n\t   * @memberof PressRecognizer\n\t   */\n\t  defaults: {\n\t    event: 'press',\n\t    pointers: 1,\n\t    time: 251, // minimal time of the pointer to be pressed\n\t    threshold: 9 // a minimal movement is ok, but keep it low\n\t  },\n\n\t  getTouchAction: function() {\n\t    return [TOUCH_ACTION_AUTO];\n\t  },\n\n\t  process: function(input) {\n\t    var options = this.options;\n\t    var validPointers = input.pointers.length === options.pointers;\n\t    var validMovement = input.distance < options.threshold;\n\t    var validTime = input.deltaTime > options.time;\n\n\t    this._input = input;\n\n\t    // we only allow little movement\n\t    // and we've reached an end event, so a tap is possible\n\t    if (!validMovement || !validPointers || (input.eventType & (INPUT_END | INPUT_CANCEL) && !validTime)) {\n\t      this.reset();\n\t    } else if (input.eventType & INPUT_START) {\n\t      this.reset();\n\t      this._timer = setTimeoutContext(function() {\n\t        this.state = STATE_RECOGNIZED;\n\t        this.tryEmit();\n\t      }, options.time, this);\n\t    } else if (input.eventType & INPUT_END) {\n\t      return STATE_RECOGNIZED;\n\t    }\n\t    return STATE_FAILED;\n\t  },\n\n\t  reset: function() {\n\t    clearTimeout(this._timer);\n\t  },\n\n\t  emit: function(input) {\n\t    if (this.state !== STATE_RECOGNIZED) {\n\t      return;\n\t    }\n\n\t    if (input && (input.eventType & INPUT_END)) {\n\t      this.manager.emit(this.options.event + 'up', input);\n\t    } else {\n\t      this._input.timeStamp = now();\n\t      this.manager.emit(this.options.event, this._input);\n\t    }\n\t  }\n\t});\n\n\t/**\n\t * Rotate\n\t * Recognized when two or more pointer are moving in a circular motion.\n\t * @constructor\n\t * @extends AttrRecognizer\n\t */\n\tfunction RotateRecognizer() {\n\t  AttrRecognizer.apply(this, arguments);\n\t}\n\n\tinherit(RotateRecognizer, AttrRecognizer, {\n\t  /**\n\t   * @namespace\n\t   * @memberof RotateRecognizer\n\t   */\n\t  defaults: {\n\t    event: 'rotate',\n\t    threshold: 0,\n\t    pointers: 2\n\t  },\n\n\t  getTouchAction: function() {\n\t    return [TOUCH_ACTION_NONE];\n\t  },\n\n\t  attrTest: function(input) {\n\t    return this._super.attrTest.call(this, input) &&\n\t      (Math.abs(input.rotation) > this.options.threshold || this.state & STATE_BEGAN);\n\t  }\n\t});\n\n\t/**\n\t * Swipe\n\t * Recognized when the pointer is moving fast (velocity), with enough distance in the allowed direction.\n\t * @constructor\n\t * @extends AttrRecognizer\n\t */\n\tfunction SwipeRecognizer() {\n\t  AttrRecognizer.apply(this, arguments);\n\t}\n\n\tinherit(SwipeRecognizer, AttrRecognizer, {\n\t  /**\n\t   * @namespace\n\t   * @memberof SwipeRecognizer\n\t   */\n\t  defaults: {\n\t    event: 'swipe',\n\t    threshold: 10,\n\t    velocity: 0.3,\n\t    direction: DIRECTION_HORIZONTAL | DIRECTION_VERTICAL,\n\t    pointers: 1\n\t  },\n\n\t  getTouchAction: function() {\n\t    return PanRecognizer.prototype.getTouchAction.call(this);\n\t  },\n\n\t  attrTest: function(input) {\n\t    var direction = this.options.direction;\n\t    var velocity;\n\n\t    if (direction & (DIRECTION_HORIZONTAL | DIRECTION_VERTICAL)) {\n\t      velocity = input.overallVelocity;\n\t    } else if (direction & DIRECTION_HORIZONTAL) {\n\t      velocity = input.overallVelocityX;\n\t    } else if (direction & DIRECTION_VERTICAL) {\n\t      velocity = input.overallVelocityY;\n\t    }\n\n\t    return this._super.attrTest.call(this, input) &&\n\t      direction & input.offsetDirection &&\n\t      input.distance > this.options.threshold &&\n\t      input.maxPointers == this.options.pointers &&\n\t      abs(velocity) > this.options.velocity && input.eventType & INPUT_END;\n\t  },\n\n\t  emit: function(input) {\n\t    var direction = directionStr(input.offsetDirection);\n\t    if (direction) {\n\t      this.manager.emit(this.options.event + direction, input);\n\t    }\n\n\t    this.manager.emit(this.options.event, input);\n\t  }\n\t});\n\n\t/**\n\t * A tap is ecognized when the pointer is doing a small tap/click. Multiple taps are recognized if they occur\n\t * between the given interval and position. The delay option can be used to recognize multi-taps without firing\n\t * a single tap.\n\t *\n\t * The eventData from the emitted event contains the property `tapCount`, which contains the amount of\n\t * multi-taps being recognized.\n\t * @constructor\n\t * @extends Recognizer\n\t */\n\tfunction TapRecognizer() {\n\t  Recognizer.apply(this, arguments);\n\n\t  // previous time and center,\n\t  // used for tap counting\n\t  this.pTime = false;\n\t  this.pCenter = false;\n\n\t  this._timer = null;\n\t  this._input = null;\n\t  this.count = 0;\n\t}\n\n\tinherit(TapRecognizer, Recognizer, {\n\t  /**\n\t   * @namespace\n\t   * @memberof PinchRecognizer\n\t   */\n\t  defaults: {\n\t    event: 'tap',\n\t    pointers: 1,\n\t    taps: 1,\n\t    interval: 300, // max time between the multi-tap taps\n\t    time: 250, // max time of the pointer to be down (like finger on the screen)\n\t    threshold: 9, // a minimal movement is ok, but keep it low\n\t    posThreshold: 10 // a multi-tap can be a bit off the initial position\n\t  },\n\n\t  getTouchAction: function() {\n\t    return [TOUCH_ACTION_MANIPULATION];\n\t  },\n\n\t  process: function(input) {\n\t    var options = this.options;\n\n\t    var validPointers = input.pointers.length === options.pointers;\n\t    var validMovement = input.distance < options.threshold;\n\t    var validTouchTime = input.deltaTime < options.time;\n\n\t    this.reset();\n\n\t    if ((input.eventType & INPUT_START) && (this.count === 0)) {\n\t      return this.failTimeout();\n\t    }\n\n\t    // we only allow little movement\n\t    // and we've reached an end event, so a tap is possible\n\t    if (validMovement && validTouchTime && validPointers) {\n\t      if (input.eventType != INPUT_END) {\n\t        return this.failTimeout();\n\t      }\n\n\t      var validInterval = this.pTime ? (input.timeStamp - this.pTime < options.interval) : true;\n\t      var validMultiTap = !this.pCenter || getDistance(this.pCenter, input.center) < options.posThreshold;\n\n\t      this.pTime = input.timeStamp;\n\t      this.pCenter = input.center;\n\n\t      if (!validMultiTap || !validInterval) {\n\t        this.count = 1;\n\t      } else {\n\t        this.count += 1;\n\t      }\n\n\t      this._input = input;\n\n\t      // if tap count matches we have recognized it,\n\t      // else it has began recognizing...\n\t      var tapCount = this.count % options.taps;\n\t      if (tapCount === 0) {\n\t        // no failing requirements, immediately trigger the tap event\n\t        // or wait as long as the multitap interval to trigger\n\t        if (!this.hasRequireFailures()) {\n\t          return STATE_RECOGNIZED;\n\t        } else {\n\t          this._timer = setTimeoutContext(function() {\n\t            this.state = STATE_RECOGNIZED;\n\t            this.tryEmit();\n\t          }, options.interval, this);\n\t          return STATE_BEGAN;\n\t        }\n\t      }\n\t    }\n\t    return STATE_FAILED;\n\t  },\n\n\t  failTimeout: function() {\n\t    this._timer = setTimeoutContext(function() {\n\t      this.state = STATE_FAILED;\n\t    }, this.options.interval, this);\n\t    return STATE_FAILED;\n\t  },\n\n\t  reset: function() {\n\t    clearTimeout(this._timer);\n\t  },\n\n\t  emit: function() {\n\t    if (this.state == STATE_RECOGNIZED) {\n\t      this._input.tapCount = this.count;\n\t      this.manager.emit(this.options.event, this._input);\n\t    }\n\t  }\n\t});\n\n\t/**\n\t * Simple way to create a manager with a default set of recognizers.\n\t * @param {HTMLElement} element\n\t * @param {Object} [options]\n\t * @constructor\n\t */\n\tfunction Hammer(element, options) {\n\t  options = options || {};\n\t  options.recognizers = ifUndefined(options.recognizers, Hammer.defaults.preset);\n\t  return new Manager(element, options);\n\t}\n\n\t/**\n\t * @const {string}\n\t */\n\tHammer.VERSION = '2.0.6';\n\n\t/**\n\t * default settings\n\t * @namespace\n\t */\n\tHammer.defaults = {\n\t  /**\n\t   * set if DOM events are being triggered.\n\t   * But this is slower and unused by simple implementations, so disabled by default.\n\t   * @type {Boolean}\n\t   * @default false\n\t   */\n\t  domEvents: false,\n\n\t  /**\n\t   * The value for the touchAction property/fallback.\n\t   * When set to `compute` it will magically set the correct value based on the added recognizers.\n\t   * @type {String}\n\t   * @default compute\n\t   */\n\t  touchAction: TOUCH_ACTION_COMPUTE,\n\n\t  /**\n\t   * @type {Boolean}\n\t   * @default true\n\t   */\n\t  enable: true,\n\n\t  /**\n\t   * EXPERIMENTAL FEATURE -- can be removed/changed\n\t   * Change the parent input target element.\n\t   * If Null, then it is being set the to main element.\n\t   * @type {Null|EventTarget}\n\t   * @default null\n\t   */\n\t  inputTarget: null,\n\n\t  /**\n\t   * force an input class\n\t   * @type {Null|Function}\n\t   * @default null\n\t   */\n\t  inputClass: null,\n\n\t  /**\n\t   * Default recognizer setup when calling `Hammer()`\n\t   * When creating a new Manager these will be skipped.\n\t   * @type {Array}\n\t   */\n\t  preset: [\n\t    // RecognizerClass, options, [recognizeWith, ...], [requireFailure, ...]\n\t    [RotateRecognizer, {enable: false}],\n\t    [PinchRecognizer, {enable: false}, ['rotate']],\n\t    [SwipeRecognizer, {direction: DIRECTION_HORIZONTAL}],\n\t    [PanRecognizer, {direction: DIRECTION_HORIZONTAL}, ['swipe']],\n\t    [TapRecognizer],\n\t    [TapRecognizer, {event: 'doubletap', taps: 2}, ['tap']],\n\t    [PressRecognizer]\n\t  ],\n\n\t  /**\n\t   * Some CSS properties can be used to improve the working of Hammer.\n\t   * Add them to this method and they will be set when creating a new Manager.\n\t   * @namespace\n\t   */\n\t  cssProps: {\n\t    /**\n\t     * Disables text selection to improve the dragging gesture. Mainly for desktop browsers.\n\t     * @type {String}\n\t     * @default 'none'\n\t     */\n\t    userSelect: 'none',\n\n\t    /**\n\t     * Disable the Windows Phone grippers when pressing an element.\n\t     * @type {String}\n\t     * @default 'none'\n\t     */\n\t    touchSelect: 'none',\n\n\t    /**\n\t     * Disables the default callout shown when you touch and hold a touch target.\n\t     * On iOS, when you touch and hold a touch target such as a link, Safari displays\n\t     * a callout containing information about the link. This property allows you to disable that callout.\n\t     * @type {String}\n\t     * @default 'none'\n\t     */\n\t    touchCallout: 'none',\n\n\t    /**\n\t     * Specifies whether zooming is enabled. Used by IE10>\n\t     * @type {String}\n\t     * @default 'none'\n\t     */\n\t    contentZooming: 'none',\n\n\t    /**\n\t     * Specifies that an entire element should be draggable instead of its contents. Mainly for desktop browsers.\n\t     * @type {String}\n\t     * @default 'none'\n\t     */\n\t    userDrag: 'none',\n\n\t    /**\n\t     * Overrides the highlight color shown when the user taps a link or a JavaScript\n\t     * clickable element in iOS. This property obeys the alpha value, if specified.\n\t     * @type {String}\n\t     * @default 'rgba(0,0,0,0)'\n\t     */\n\t    tapHighlightColor: 'rgba(0,0,0,0)'\n\t  }\n\t};\n\n\tvar STOP = 1;\n\tvar FORCED_STOP = 2;\n\n\t/**\n\t * Manager\n\t * @param {HTMLElement} element\n\t * @param {Object} [options]\n\t * @constructor\n\t */\n\tfunction Manager(element, options) {\n\t  this.options = assign({}, Hammer.defaults, options || {});\n\n\t  this.options.inputTarget = this.options.inputTarget || element;\n\n\t  this.handlers = {};\n\t  this.session = {};\n\t  this.recognizers = [];\n\n\t  this.element = element;\n\t  this.input = createInputInstance(this);\n\t  this.touchAction = new TouchAction(this, this.options.touchAction);\n\n\t  toggleCssProps(this, true);\n\n\t  each(this.options.recognizers, function(item) {\n\t    var recognizer = this.add(new (item[0])(item[1]));\n\t    item[2] && recognizer.recognizeWith(item[2]);\n\t    item[3] && recognizer.requireFailure(item[3]);\n\t  }, this);\n\t}\n\n\tManager.prototype = {\n\t  /**\n\t   * set options\n\t   * @param {Object} options\n\t   * @returns {Manager}\n\t   */\n\t  set: function(options) {\n\t    assign(this.options, options);\n\n\t    // Options that need a little more setup\n\t    if (options.touchAction) {\n\t      this.touchAction.update();\n\t    }\n\t    if (options.inputTarget) {\n\t      // Clean up existing event listeners and reinitialize\n\t      this.input.destroy();\n\t      this.input.target = options.inputTarget;\n\t      this.input.init();\n\t    }\n\t    return this;\n\t  },\n\n\t  /**\n\t   * stop recognizing for this session.\n\t   * This session will be discarded, when a new [input]start event is fired.\n\t   * When forced, the recognizer cycle is stopped immediately.\n\t   * @param {Boolean} [force]\n\t   */\n\t  stop: function(force) {\n\t    this.session.stopped = force ? FORCED_STOP : STOP;\n\t  },\n\n\t  /**\n\t   * run the recognizers!\n\t   * called by the inputHandler function on every movement of the pointers (touches)\n\t   * it walks through all the recognizers and tries to detect the gesture that is being made\n\t   * @param {Object} inputData\n\t   */\n\t  recognize: function(inputData) {\n\t    var session = this.session;\n\t    if (session.stopped) {\n\t      return;\n\t    }\n\n\t    // run the touch-action polyfill\n\t    this.touchAction.preventDefaults(inputData);\n\n\t    var recognizer;\n\t    var recognizers = this.recognizers;\n\n\t    // this holds the recognizer that is being recognized.\n\t    // so the recognizer's state needs to be BEGAN, CHANGED, ENDED or RECOGNIZED\n\t    // if no recognizer is detecting a thing, it is set to `null`\n\t    var curRecognizer = session.curRecognizer;\n\n\t    // reset when the last recognizer is recognized\n\t    // or when we're in a new session\n\t    if (!curRecognizer || (curRecognizer && curRecognizer.state & STATE_RECOGNIZED)) {\n\t      curRecognizer = session.curRecognizer = null;\n\t    }\n\n\t    var i = 0;\n\t    while (i < recognizers.length) {\n\t      recognizer = recognizers[i];\n\n\t      // find out if we are allowed try to recognize the input for this one.\n\t      // 1.   allow if the session is NOT forced stopped (see the .stop() method)\n\t      // 2.   allow if we still haven't recognized a gesture in this session, or the this recognizer is the one\n\t      //      that is being recognized.\n\t      // 3.   allow if the recognizer is allowed to run simultaneous with the current recognized recognizer.\n\t      //      this can be setup with the `recognizeWith()` method on the recognizer.\n\t      if (session.stopped !== FORCED_STOP && ( // 1\n\t        !curRecognizer || recognizer == curRecognizer || // 2\n\t        recognizer.canRecognizeWith(curRecognizer))) { // 3\n\t        recognizer.recognize(inputData);\n\t      } else {\n\t        recognizer.reset();\n\t      }\n\n\t      // if the recognizer has been recognizing the input as a valid gesture, we want to store this one as the\n\t      // current active recognizer. but only if we don't already have an active recognizer\n\t      if (!curRecognizer && recognizer.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED)) {\n\t        curRecognizer = session.curRecognizer = recognizer;\n\t      }\n\t      i++;\n\t    }\n\t  },\n\n\t  /**\n\t   * get a recognizer by its event name.\n\t   * @param {Recognizer|String} recognizer\n\t   * @returns {Recognizer|Null}\n\t   */\n\t  get: function(recognizer) {\n\t    if (recognizer instanceof Recognizer) {\n\t      return recognizer;\n\t    }\n\n\t    var recognizers = this.recognizers;\n\t    for (var i = 0; i < recognizers.length; i++) {\n\t      if (recognizers[i].options.event == recognizer) {\n\t        return recognizers[i];\n\t      }\n\t    }\n\t    return null;\n\t  },\n\n\t  /**\n\t   * add a recognizer to the manager\n\t   * existing recognizers with the same event name will be removed\n\t   * @param {Recognizer} recognizer\n\t   * @returns {Recognizer|Manager}\n\t   */\n\t  add: function(recognizer) {\n\t    if (invokeArrayArg(recognizer, 'add', this)) {\n\t      return this;\n\t    }\n\n\t    // remove existing\n\t    var existing = this.get(recognizer.options.event);\n\t    if (existing) {\n\t      this.remove(existing);\n\t    }\n\n\t    this.recognizers.push(recognizer);\n\t    recognizer.manager = this;\n\n\t    this.touchAction.update();\n\t    return recognizer;\n\t  },\n\n\t  /**\n\t   * remove a recognizer by name or instance\n\t   * @param {Recognizer|String} recognizer\n\t   * @returns {Manager}\n\t   */\n\t  remove: function(recognizer) {\n\t    if (invokeArrayArg(recognizer, 'remove', this)) {\n\t      return this;\n\t    }\n\n\t    recognizer = this.get(recognizer);\n\n\t    // let's make sure this recognizer exists\n\t    if (recognizer) {\n\t      var recognizers = this.recognizers;\n\t      var index = inArray(recognizers, recognizer);\n\n\t      if (index !== -1) {\n\t        recognizers.splice(index, 1);\n\t        this.touchAction.update();\n\t      }\n\t    }\n\n\t    return this;\n\t  },\n\n\t  /**\n\t   * bind event\n\t   * @param {String} events\n\t   * @param {Function} handler\n\t   * @returns {EventEmitter} this\n\t   */\n\t  on: function(events, handler) {\n\t    var handlers = this.handlers;\n\t    each(splitStr(events), function(event) {\n\t      handlers[event] = handlers[event] || [];\n\t      handlers[event].push(handler);\n\t    });\n\t    return this;\n\t  },\n\n\t  /**\n\t   * unbind event, leave emit blank to remove all handlers\n\t   * @param {String} events\n\t   * @param {Function} [handler]\n\t   * @returns {EventEmitter} this\n\t   */\n\t  off: function(events, handler) {\n\t    var handlers = this.handlers;\n\t    each(splitStr(events), function(event) {\n\t      if (!handler) {\n\t        delete handlers[event];\n\t      } else {\n\t        handlers[event] && handlers[event].splice(inArray(handlers[event], handler), 1);\n\t      }\n\t    });\n\t    return this;\n\t  },\n\n\t  /**\n\t   * emit event to the listeners\n\t   * @param {String} event\n\t   * @param {Object} data\n\t   */\n\t  emit: function(event, data) {\n\t    // we also want to trigger dom events\n\t    if (this.options.domEvents) {\n\t      triggerDomEvent(event, data);\n\t    }\n\n\t    // no handlers, so skip it all\n\t    var handlers = this.handlers[event] && this.handlers[event].slice();\n\t    if (!handlers || !handlers.length) {\n\t      return;\n\t    }\n\n\t    data.type = event;\n\t    data.preventDefault = function() {\n\t      data.srcEvent.preventDefault();\n\t    };\n\n\t    var i = 0;\n\t    while (i < handlers.length) {\n\t      handlers[i](data);\n\t      i++;\n\t    }\n\t  },\n\n\t  /**\n\t   * destroy the manager and unbinds all events\n\t   * it doesn't unbind dom events, that is the user own responsibility\n\t   */\n\t  destroy: function() {\n\t    this.element && toggleCssProps(this, false);\n\n\t    this.handlers = {};\n\t    this.session = {};\n\t    this.input.destroy();\n\t    this.element = null;\n\t  }\n\t};\n\n\t/**\n\t * add/remove the css properties as defined in manager.options.cssProps\n\t * @param {Manager} manager\n\t * @param {Boolean} add\n\t */\n\tfunction toggleCssProps(manager, add) {\n\t  var element = manager.element;\n\t  if (!element.style) {\n\t    return;\n\t  }\n\t  each(manager.options.cssProps, function(value, name) {\n\t    element.style[prefixed(element.style, name)] = add ? value : '';\n\t  });\n\t}\n\n\t/**\n\t * trigger dom event\n\t * @param {String} event\n\t * @param {Object} data\n\t */\n\tfunction triggerDomEvent(event, data) {\n\t  var gestureEvent = document.createEvent('Event');\n\t  gestureEvent.initEvent(event, true, true);\n\t  gestureEvent.gesture = data;\n\t  data.target.dispatchEvent(gestureEvent);\n\t}\n\n\tassign(Hammer, {\n\t  INPUT_START: INPUT_START,\n\t  INPUT_MOVE: INPUT_MOVE,\n\t  INPUT_END: INPUT_END,\n\t  INPUT_CANCEL: INPUT_CANCEL,\n\n\t  STATE_POSSIBLE: STATE_POSSIBLE,\n\t  STATE_BEGAN: STATE_BEGAN,\n\t  STATE_CHANGED: STATE_CHANGED,\n\t  STATE_ENDED: STATE_ENDED,\n\t  STATE_RECOGNIZED: STATE_RECOGNIZED,\n\t  STATE_CANCELLED: STATE_CANCELLED,\n\t  STATE_FAILED: STATE_FAILED,\n\n\t  DIRECTION_NONE: DIRECTION_NONE,\n\t  DIRECTION_LEFT: DIRECTION_LEFT,\n\t  DIRECTION_RIGHT: DIRECTION_RIGHT,\n\t  DIRECTION_UP: DIRECTION_UP,\n\t  DIRECTION_DOWN: DIRECTION_DOWN,\n\t  DIRECTION_HORIZONTAL: DIRECTION_HORIZONTAL,\n\t  DIRECTION_VERTICAL: DIRECTION_VERTICAL,\n\t  DIRECTION_ALL: DIRECTION_ALL,\n\n\t  Manager: Manager,\n\t  Input: Input,\n\t  TouchAction: TouchAction,\n\n\t  TouchInput: TouchInput,\n\t  MouseInput: MouseInput,\n\t  PointerEventInput: PointerEventInput,\n\t  TouchMouseInput: TouchMouseInput,\n\t  SingleTouchInput: SingleTouchInput,\n\n\t  Recognizer: Recognizer,\n\t  AttrRecognizer: AttrRecognizer,\n\t  Tap: TapRecognizer,\n\t  Pan: PanRecognizer,\n\t  Swipe: SwipeRecognizer,\n\t  Pinch: PinchRecognizer,\n\t  Rotate: RotateRecognizer,\n\t  Press: PressRecognizer,\n\n\t  on: addEventListeners,\n\t  off: removeEventListeners,\n\t  each: each,\n\t  merge: merge,\n\t  extend: extend,\n\t  assign: assign,\n\t  inherit: inherit,\n\t  bindFn: bindFn,\n\t  prefixed: prefixed\n\t});\n\n\t// jquery.hammer.js\n\t// This jQuery plugin is just a small wrapper around the Hammer() class.\n\t// It also extends the Manager.emit method by triggering jQuery events.\n\t// $(element).hammer(options).bind(\"pan\", myPanHandler);\n\t// The Hammer instance is stored at $element.data(\"hammer\").\n\t// https://github.com/hammerjs/jquery.hammer.js\n\n\t(function($, Hammer) {\n\t  function hammerify(el, options) {\n\t    var $el = $(el);\n\t    if (!$el.data('hammer')) {\n\t      $el.data('hammer', new Hammer($el[0], options));\n\t    }\n\t  }\n\n\t  $.fn.hammer = function(options) {\n\t    return this.each(function() {\n\t      hammerify(this, options);\n\t    });\n\t  };\n\n\t  // extend the emit method to also trigger jQuery events\n\t  Hammer.Manager.prototype.emit = (function(originalEmit) {\n\t    return function(type, data) {\n\t      originalEmit.call(this, type, data);\n\t      $(this.element).trigger({\n\t        type: type,\n\t        gesture: data\n\t      });\n\t    };\n\t  })(Hammer.Manager.prototype.emit);\n\t})($, Hammer);\n\n\tmodule.exports = UI.Hammer = Hammer;\n\n\n/***/ },\n/* 4 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar UI = __webpack_require__(2);\n\n\t/* jshint -W101, -W106 */\n\t/**\n\t * Add to Homescreen v3.2.2\n\t * (c) 2015 Matteo Spinelli\n\t * @license: http://cubiq.org/license\n\t */\n\n\t// Check for addEventListener browser support (prevent errors in IE<9)\n\tvar _eventListener = 'addEventListener' in window;\n\n\t// Check if document is loaded, needed by autostart\n\tvar _DOMReady = false;\n\tif (document.readyState === 'complete') {\n\t  _DOMReady = true;\n\t} else if (_eventListener) {\n\t  window.addEventListener('load', loaded, false);\n\t}\n\n\tfunction loaded() {\n\t  window.removeEventListener('load', loaded, false);\n\t  _DOMReady = true;\n\t}\n\n\t// regex used to detect if app has been added to the homescreen\n\tvar _reSmartURL = /\\/ath(\\/)?$/;\n\tvar _reQueryString = /([\\?&]ath=[^&]*$|&ath=[^&]*(&))/;\n\n\t// singleton\n\tvar _instance;\n\tfunction ath(options) {\n\t  _instance = _instance || new ath.Class(options);\n\n\t  return _instance;\n\t}\n\n\t// message in all supported languages\n\tath.intl = {\n\t  en_us: {\n\t    ios: 'To add this web app to the home screen: tap %icon and then <strong>Add to Home Screen</strong>.',\n\t    android: 'To add this web app to the home screen open the browser option menu and tap on <strong>Add to homescreen</strong>. <small>The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon <span class=\"ath-action-icon\">icon</span>.</small>'\n\t  },\n\n\t  zh_cn: {\n\t    ios: '如要把应用程式加至主屏幕,请点击%icon, 然后<strong>加至主屏幕</strong>',\n\t    android: 'To add this web app to the home screen open the browser option menu and tap on <strong>Add to homescreen</strong>. <small>The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon <span class=\"ath-action-icon\">icon</span>.</small>'\n\t  },\n\n\t  zh_tw: {\n\t    ios: '如要把應用程式加至主屏幕, 請點擊%icon, 然後<strong>加至主屏幕</strong>.',\n\t    android: 'To add this web app to the home screen open the browser option menu and tap on <strong>Add to homescreen</strong>. <small>The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon <span class=\"ath-action-icon\">icon</span>.</small>'\n\t  }\n\t};\n\n\t// Add 2 characters language support (Android mostly)\n\tfor (var lang in ath.intl) {\n\t  ath.intl[lang.substr(0, 2)] = ath.intl[lang];\n\t}\n\n\t// default options\n\tath.defaults = {\n\t  appID: 'org.cubiq.addtohome',\t\t// local storage name (no need to change)\n\t  fontSize: 15,\t\t\t\t// base font size, used to properly resize the popup based on viewport scale factor\n\t  debug: false,\t\t\t\t// override browser checks\n\t  logging: false,\t\t\t\t// log reasons for showing or not showing to js console; defaults to true when debug is true\n\t  modal: false,\t\t\t\t// prevent further actions until the message is closed\n\t  mandatory: false,\t\t\t// you can't proceed if you don't add the app to the homescreen\n\t  autostart: true,\t\t\t// show the message automatically\n\t  skipFirstVisit: false,\t\t// show only to returning visitors (ie: skip the first time you visit)\n\t  startDelay: 1,\t\t\t\t// display the message after that many seconds from page load\n\t  lifespan: 15,\t\t\t\t// life of the message in seconds\n\t  displayPace: 1440,\t\t\t// minutes before the message is shown again (0: display every time, default 24 hours)\n\t  maxDisplayCount: 0,\t\t\t// absolute maximum number of times the message will be shown to the user (0: no limit)\n\t  icon: true,\t\t\t\t\t// add touch icon to the message\n\t  message: '',\t\t\t\t// the message can be customized\n\t  validLocation: [],\t\t\t// list of pages where the message will be shown (array of regexes)\n\t  onInit: null,\t\t\t\t// executed on instance creation\n\t  onShow: null,\t\t\t\t// executed when the message is shown\n\t  onRemove: null,\t\t\t\t// executed when the message is removed\n\t  onAdd: null,\t\t\t\t// when the application is launched the first time from the homescreen (guesstimate)\n\t  onPrivate: null,\t\t\t// executed if user is in private mode\n\t  privateModeOverride: false,\t// show the message even in private mode (very rude)\n\t  detectHomescreen: false\t\t// try to detect if the site has been added to the homescreen (false | true | 'hash' | 'queryString' | 'smartURL')\n\t};\n\n\t// browser info and capability\n\tvar _ua = window.navigator.userAgent;\n\n\tvar _nav = window.navigator;\n\t_extend(ath, {\n\t  hasToken: document.location.hash == '#ath' || _reSmartURL.test(document.location.href) || _reQueryString.test(document.location.search),\n\t  isRetina: window.devicePixelRatio && window.devicePixelRatio > 1,\n\t  isIDevice: (/iphone|ipod|ipad/i).test(_ua),\n\t  isMobileChrome: _ua.indexOf('Android') > -1 && (/Chrome\\/[.0-9]*/).test(_ua) && _ua.indexOf(\"Version\") == -1,\n\t  isMobileIE: _ua.indexOf('Windows Phone') > -1,\n\t  language: _nav.language && _nav.language.toLowerCase().replace('-', '_') || ''\n\t});\n\n\t// falls back to en_us if language is unsupported\n\tath.language = ath.language && ath.language in ath.intl ? ath.language : 'en_us';\n\n\tath.isMobileSafari = ath.isIDevice && _ua.indexOf('Safari') > -1 && _ua.indexOf('CriOS') < 0;\n\tath.OS = ath.isIDevice ? 'ios' : ath.isMobileChrome ? 'android' : ath.isMobileIE ? 'windows' : 'unsupported';\n\n\tath.OSVersion = _ua.match(/(OS|Android) (\\d+[_\\.]\\d+)/);\n\tath.OSVersion = ath.OSVersion && ath.OSVersion[2] ? +ath.OSVersion[2].replace('_', '.') : 0;\n\n\tath.isStandalone = 'standalone' in window.navigator && window.navigator.standalone;\n\tath.isTablet = (ath.isMobileSafari && _ua.indexOf('iPad') > -1) || (ath.isMobileChrome && _ua.indexOf('Mobile') < 0);\n\n\tath.isCompatible = (ath.isMobileSafari && ath.OSVersion >= 6) || ath.isMobileChrome;\t// TODO: add winphone\n\n\tvar _defaultSession = {\n\t  lastDisplayTime: 0,\t\t\t// last time we displayed the message\n\t  returningVisitor: false,\t// is this the first time you visit\n\t  displayCount: 0,\t\t\t// number of times the message has been shown\n\t  optedout: false,\t\t\t// has the user opted out\n\t  added: false\t\t\t\t// has been actually added to the homescreen\n\t};\n\n\tath.removeSession = function(appID) {\n\t  try {\n\t    if (!localStorage) {\n\t      throw new Error('localStorage is not defined');\n\t    }\n\n\t    localStorage.removeItem(appID || ath.defaults.appID);\n\t  } catch (e) {\n\t    // we are most likely in private mode\n\t  }\n\t};\n\n\tath.doLog = function(logStr) {\n\t  if (this.options.logging) {\n\t    console.log(logStr);\n\t  }\n\t};\n\n\tath.Class = function(options) {\n\t  // class methods\n\t  this.doLog = ath.doLog;\n\n\t  // merge default options with user config\n\t  this.options = _extend({}, ath.defaults);\n\t  _extend(this.options, options);\n\t  // override defaults that are dependent on each other\n\t  if (this.options.debug) {\n\t    this.options.logging = true;\n\t  }\n\n\t  // IE<9 so exit (I hate you, really)\n\t  if (!_eventListener) {\n\t    return;\n\t  }\n\n\t  // normalize some options\n\t  this.options.mandatory = this.options.mandatory && ( 'standalone' in window.navigator || this.options.debug );\n\t  this.options.modal = this.options.modal || this.options.mandatory;\n\t  if (this.options.mandatory) {\n\t    this.options.startDelay = -0.5;\t\t// make the popup hasty\n\t  }\n\t  this.options.detectHomescreen = this.options.detectHomescreen === true ? 'hash' : this.options.detectHomescreen;\n\n\t  // setup the debug environment\n\t  if (this.options.debug) {\n\t    ath.isCompatible = true;\n\t    ath.OS = typeof this.options.debug == 'string' ? this.options.debug : ath.OS == 'unsupported' ? 'android' : ath.OS;\n\t    ath.OSVersion = ath.OS == 'ios' ? '8' : '4';\n\t  }\n\n\t  // the element the message will be appended to\n\t  this.container = document.documentElement;\n\n\t  // load session\n\t  this.session = this.getItem(this.options.appID);\n\t  this.session = this.session ? JSON.parse(this.session) : undefined;\n\n\t  // user most likely came from a direct link containing our token, we don't need it and we remove it\n\t  if (ath.hasToken && ( !ath.isCompatible || !this.session )) {\n\t    ath.hasToken = false;\n\t    _removeToken();\n\t  }\n\n\t  // the device is not supported\n\t  if (!ath.isCompatible) {\n\t    this.doLog(\"Add to homescreen: not displaying callout because device not supported\");\n\t    return;\n\t  }\n\n\t  this.session = this.session || _defaultSession;\n\n\t  // check if we can use the local storage\n\t  try {\n\t    if (!localStorage) {\n\t      throw new Error('localStorage is not defined');\n\t    }\n\n\t    localStorage.setItem(this.options.appID, JSON.stringify(this.session));\n\t    ath.hasLocalStorage = true;\n\t  } catch (e) {\n\t    // we are most likely in private mode\n\t    ath.hasLocalStorage = false;\n\n\t    if (this.options.onPrivate) {\n\t      this.options.onPrivate.call(this);\n\t    }\n\t  }\n\n\t  // check if this is a valid location\n\t  var isValidLocation = !this.options.validLocation.length;\n\t  for (var i = this.options.validLocation.length; i--;) {\n\t    if (this.options.validLocation[i].test(document.location.href)) {\n\t      isValidLocation = true;\n\t      break;\n\t    }\n\t  }\n\n\t  // check compatibility with old versions of add to homescreen. Opt-out if an old session is found\n\t  if (this.getItem('addToHome')) {\n\t    this.optOut();\n\t  }\n\n\t  // critical errors:\n\t  if (this.session.optedout) {\n\t    this.doLog(\"Add to homescreen: not displaying callout because user opted out\");\n\t    return;\n\t  }\n\t  if (this.session.added) {\n\t    this.doLog(\"Add to homescreen: not displaying callout because already added to the homescreen\");\n\t    return;\n\t  }\n\t  if (!isValidLocation) {\n\t    this.doLog(\"Add to homescreen: not displaying callout because not a valid location\");\n\t    return;\n\t  }\n\n\t  // check if the app is in stand alone mode\n\t  if (ath.isStandalone) {\n\t    // execute the onAdd event if we haven't already\n\t    if (!this.session.added) {\n\t      this.session.added = true;\n\t      this.updateSession();\n\n\t      if (this.options.onAdd && ath.hasLocalStorage) {\t// double check on localstorage to avoid multiple calls to the custom event\n\t        this.options.onAdd.call(this);\n\t      }\n\t    }\n\n\t    this.doLog(\"Add to homescreen: not displaying callout because in standalone mode\");\n\t    return;\n\t  }\n\n\t  // (try to) check if the page has been added to the homescreen\n\t  if (this.options.detectHomescreen) {\n\t    // the URL has the token, we are likely coming from the homescreen\n\t    if (ath.hasToken) {\n\t      _removeToken();\t\t// we don't actually need the token anymore, we remove it to prevent redistribution\n\n\t      // this is called the first time the user opens the app from the homescreen\n\t      if (!this.session.added) {\n\t        this.session.added = true;\n\t        this.updateSession();\n\n\t        if (this.options.onAdd && ath.hasLocalStorage) {\t// double check on localstorage to avoid multiple calls to the custom event\n\t          this.options.onAdd.call(this);\n\t        }\n\t      }\n\n\t      this.doLog(\"Add to homescreen: not displaying callout because URL has token, so we are likely coming from homescreen\");\n\t      return;\n\t    }\n\n\t    // URL doesn't have the token, so add it\n\t    if (this.options.detectHomescreen == 'hash') {\n\t      history.replaceState('', window.document.title, document.location.href + '#ath');\n\t    } else if (this.options.detectHomescreen == 'smartURL') {\n\t      history.replaceState('', window.document.title, document.location.href.replace(/(\\/)?$/, '/ath$1'));\n\t    } else {\n\t      history.replaceState('', window.document.title, document.location.href + (document.location.search ? '&' : '?' ) + 'ath=');\n\t    }\n\t  }\n\n\t  // check if this is a returning visitor\n\t  if (!this.session.returningVisitor) {\n\t    this.session.returningVisitor = true;\n\t    this.updateSession();\n\n\t    // we do not show the message if this is your first visit\n\t    if (this.options.skipFirstVisit) {\n\t      this.doLog(\"Add to homescreen: not displaying callout because skipping first visit\");\n\t      return;\n\t    }\n\t  }\n\n\t  // we do no show the message in private mode\n\t  if (!this.options.privateModeOverride && !ath.hasLocalStorage) {\n\t    this.doLog(\"Add to homescreen: not displaying callout because browser is in private mode\");\n\t    return;\n\t  }\n\n\t  // all checks passed, ready to display\n\t  this.ready = true;\n\n\t  if (this.options.onInit) {\n\t    this.options.onInit.call(this);\n\t  }\n\n\t  if (this.options.autostart) {\n\t    this.doLog(\"Add to homescreen: autostart displaying callout\");\n\t    this.show();\n\t  }\n\t};\n\n\tath.Class.prototype = {\n\t  // event type to method conversion\n\t  events: {\n\t    load: '_delayedShow',\n\t    error: '_delayedShow',\n\t    orientationchange: 'resize',\n\t    resize: 'resize',\n\t    scroll: 'resize',\n\t    click: 'remove',\n\t    touchmove: '_preventDefault',\n\t    transitionend: '_removeElements',\n\t    webkitTransitionEnd: '_removeElements',\n\t    MSTransitionEnd: '_removeElements'\n\t  },\n\n\t  handleEvent: function(e) {\n\t    var type = this.events[e.type];\n\t    if (type) {\n\t      this[type](e);\n\t    }\n\t  },\n\n\t  show: function(force) {\n\t    // in autostart mode wait for the document to be ready\n\t    if (this.options.autostart && !_DOMReady) {\n\t      setTimeout(this.show.bind(this), 50);\n\t      // we are not displaying callout because DOM not ready, but don't log that because\n\t      // it would log too frequently\n\t      return;\n\t    }\n\n\t    // message already on screen\n\t    if (this.shown) {\n\t      this.doLog(\"Add to homescreen: not displaying callout because already shown on screen\");\n\t      return;\n\t    }\n\n\t    var now = Date.now();\n\t    var lastDisplayTime = this.session.lastDisplayTime;\n\n\t    if (force !== true) {\n\t      // this is needed if autostart is disabled and you programmatically call the show() method\n\t      if (!this.ready) {\n\t        this.doLog(\"Add to homescreen: not displaying callout because not ready\");\n\t        return;\n\t      }\n\n\t      // we obey the display pace (prevent the message to popup too often)\n\t      if (now - lastDisplayTime < this.options.displayPace * 60000) {\n\t        this.doLog(\"Add to homescreen: not displaying callout because displayed recently\");\n\t        return;\n\t      }\n\n\t      // obey the maximum number of display count\n\t      if (this.options.maxDisplayCount && this.session.displayCount >= this.options.maxDisplayCount) {\n\t        this.doLog(\"Add to homescreen: not displaying callout because displayed too many times already\");\n\t        return;\n\t      }\n\t    }\n\n\t    this.shown = true;\n\n\t    // increment the display count\n\t    this.session.lastDisplayTime = now;\n\t    this.session.displayCount++;\n\t    this.updateSession();\n\n\t    // try to get the highest resolution application icon\n\t    if (!this.applicationIcon) {\n\t      if (ath.OS == 'ios') {\n\t        this.applicationIcon = document.querySelector('head link[rel^=apple-touch-icon][sizes=\"152x152\"],head link[rel^=apple-touch-icon][sizes=\"144x144\"],head link[rel^=apple-touch-icon][sizes=\"120x120\"],head link[rel^=apple-touch-icon][sizes=\"114x114\"],head link[rel^=apple-touch-icon]');\n\t      } else {\n\t        this.applicationIcon = document.querySelector('head link[rel^=\"shortcut icon\"][sizes=\"196x196\"],head link[rel^=apple-touch-icon]');\n\t      }\n\t    }\n\n\t    var message = '';\n\n\t    if (typeof this.options.message == 'object' && ath.language in this.options.message) {\t\t// use custom language message\n\t      message = this.options.message[ath.language][ath.OS];\n\t    } else if (typeof this.options.message == 'object' && ath.OS in this.options.message) {\t\t// use custom os message\n\t      message = this.options.message[ath.OS];\n\t    } else if (this.options.message in ath.intl) {\t\t\t\t// you can force the locale\n\t      message = ath.intl[this.options.message][ath.OS];\n\t    } else if (this.options.message !== '') {\t\t\t\t\t\t// use a custom message\n\t      message = this.options.message;\n\t    } else if (ath.OS in ath.intl[ath.language]) {\t\t\t\t// otherwise we use our message\n\t      message = ath.intl[ath.language][ath.OS];\n\t    }\n\n\t    // add the action icon\n\t    message = '<p>' + message.replace('%icon', '<span class=\"ath-action-icon\">icon</span>') + '</p>';\n\n\t    // create the message container\n\t    this.viewport = document.createElement('div');\n\t    this.viewport.className = 'ath-viewport';\n\t    if (this.options.modal) {\n\t      this.viewport.className += ' ath-modal';\n\t    }\n\t    if (this.options.mandatory) {\n\t      this.viewport.className += ' ath-mandatory';\n\t    }\n\t    this.viewport.style.position = 'absolute';\n\n\t    // create the actual message element\n\t    this.element = document.createElement('div');\n\t    this.element.className = 'ath-container ath-' + ath.OS + ' ath-' + ath.OS + (ath.OSVersion + '').substr(0, 1) + ' ath-' + (ath.isTablet ? 'tablet' : 'phone');\n\t    this.element.style.cssText = '-webkit-transition-property:-webkit-transform,opacity;-webkit-transition-duration:0s;-webkit-transition-timing-function:ease-out;transition-property:transform,opacity;transition-duration:0s;transition-timing-function:ease-out;';\n\t    this.element.style.webkitTransform = 'translate3d(0,-' + window.innerHeight + 'px,0)';\n\t    this.element.style.transform = 'translate3d(0,-' + window.innerHeight + 'px,0)';\n\n\t    // add the application icon\n\t    if (this.options.icon && this.applicationIcon) {\n\t      this.element.className += ' ath-icon';\n\t      this.img = document.createElement('img');\n\t      this.img.className = 'ath-application-icon';\n\t      this.img.addEventListener('load', this, false);\n\t      this.img.addEventListener('error', this, false);\n\n\t      this.img.src = this.applicationIcon.href;\n\t      this.element.appendChild(this.img);\n\t    }\n\n\t    this.element.innerHTML += message;\n\n\t    // we are not ready to show, place the message out of sight\n\t    this.viewport.style.left = '-99999em';\n\n\t    // attach all elements to the DOM\n\t    this.viewport.appendChild(this.element);\n\t    this.container.appendChild(this.viewport);\n\n\t    // if we don't have to wait for an image to load, show the message right away\n\t    if (this.img) {\n\t      this.doLog(\"Add to homescreen: not displaying callout because waiting for img to load\");\n\t    } else {\n\t      this._delayedShow();\n\t    }\n\t  },\n\n\t  _delayedShow: function(e) {\n\t    setTimeout(this._show.bind(this), this.options.startDelay * 1000 + 500);\n\t  },\n\n\t  _show: function() {\n\t    var that = this;\n\n\t    // update the viewport size and orientation\n\t    this.updateViewport();\n\n\t    // reposition/resize the message on orientation change\n\t    window.addEventListener('resize', this, false);\n\t    window.addEventListener('scroll', this, false);\n\t    window.addEventListener('orientationchange', this, false);\n\n\t    if (this.options.modal) {\n\t      // lock any other interaction\n\t      document.addEventListener('touchmove', this, true);\n\t    }\n\n\t    // Enable closing after 1 second\n\t    if (!this.options.mandatory) {\n\t      setTimeout(function() {\n\t        that.element.addEventListener('click', that, true);\n\t      }, 1000);\n\t    }\n\n\t    // kick the animation\n\t    setTimeout(function() {\n\t      that.element.style.webkitTransitionDuration = '1.2s';\n\t      that.element.style.transitionDuration = '1.2s';\n\t      that.element.style.webkitTransform = 'translate3d(0,0,0)';\n\t      that.element.style.transform = 'translate3d(0,0,0)';\n\t    }, 0);\n\n\t    // set the destroy timer\n\t    if (this.options.lifespan) {\n\t      this.removeTimer = setTimeout(this.remove.bind(this), this.options.lifespan * 1000);\n\t    }\n\n\t    // fire the custom onShow event\n\t    if (this.options.onShow) {\n\t      this.options.onShow.call(this);\n\t    }\n\t  },\n\n\t  remove: function() {\n\t    clearTimeout(this.removeTimer);\n\n\t    // clear up the event listeners\n\t    if (this.img) {\n\t      this.img.removeEventListener('load', this, false);\n\t      this.img.removeEventListener('error', this, false);\n\t    }\n\n\t    window.removeEventListener('resize', this, false);\n\t    window.removeEventListener('scroll', this, false);\n\t    window.removeEventListener('orientationchange', this, false);\n\t    document.removeEventListener('touchmove', this, true);\n\t    this.element.removeEventListener('click', this, true);\n\n\t    // remove the message element on transition end\n\t    this.element.addEventListener('transitionend', this, false);\n\t    this.element.addEventListener('webkitTransitionEnd', this, false);\n\t    this.element.addEventListener('MSTransitionEnd', this, false);\n\n\t    // start the fade out animation\n\t    this.element.style.webkitTransitionDuration = '0.3s';\n\t    this.element.style.opacity = '0';\n\t  },\n\n\t  _removeElements: function() {\n\t    this.element.removeEventListener('transitionend', this, false);\n\t    this.element.removeEventListener('webkitTransitionEnd', this, false);\n\t    this.element.removeEventListener('MSTransitionEnd', this, false);\n\n\t    // remove the message from the DOM\n\t    this.container.removeChild(this.viewport);\n\n\t    this.shown = false;\n\n\t    // fire the custom onRemove event\n\t    if (this.options.onRemove) {\n\t      this.options.onRemove.call(this);\n\t    }\n\t  },\n\n\t  updateViewport: function() {\n\t    if (!this.shown) {\n\t      return;\n\t    }\n\n\t    this.viewport.style.width = window.innerWidth + 'px';\n\t    this.viewport.style.height = window.innerHeight + 'px';\n\t    this.viewport.style.left = window.scrollX + 'px';\n\t    this.viewport.style.top = window.scrollY + 'px';\n\n\t    var clientWidth = document.documentElement.clientWidth;\n\n\t    this.orientation = clientWidth > document.documentElement.clientHeight ? 'landscape' : 'portrait';\n\n\t    var screenWidth = ath.OS == 'ios' ? this.orientation == 'portrait' ? screen.width : screen.height : screen.width;\n\t    this.scale = screen.width > clientWidth ? 1 : screenWidth / window.innerWidth;\n\n\t    this.element.style.fontSize = this.options.fontSize / this.scale + 'px';\n\t  },\n\n\t  resize: function() {\n\t    clearTimeout(this.resizeTimer);\n\t    this.resizeTimer = setTimeout(this.updateViewport.bind(this), 100);\n\t  },\n\n\t  updateSession: function() {\n\t    if (ath.hasLocalStorage === false) {\n\t      return;\n\t    }\n\n\t    if (localStorage) {\n\t      localStorage.setItem(this.options.appID, JSON.stringify(this.session));\n\t    }\n\t  },\n\n\t  clearSession: function() {\n\t    this.session = _defaultSession;\n\t    this.updateSession();\n\t  },\n\n\t  getItem: function(item) {\n\t    try {\n\t      if (!localStorage) {\n\t        throw new Error('localStorage is not defined');\n\t      }\n\n\t      return localStorage.getItem(item);\n\t    } catch (e) {\n\t      // Preventing exception for some browsers when fetching localStorage key\n\t      ath.hasLocalStorage = false;\n\t    }\n\t  },\n\n\t  optOut: function() {\n\t    this.session.optedout = true;\n\t    this.updateSession();\n\t  },\n\n\t  optIn: function() {\n\t    this.session.optedout = false;\n\t    this.updateSession();\n\t  },\n\n\t  clearDisplayCount: function() {\n\t    this.session.displayCount = 0;\n\t    this.updateSession();\n\t  },\n\n\t  _preventDefault: function(e) {\n\t    e.preventDefault();\n\t    e.stopPropagation();\n\t  }\n\t};\n\n\t// utility\n\tfunction _extend(target, obj) {\n\t  for (var i in obj) {\n\t    target[i] = obj[i];\n\t  }\n\n\t  return target;\n\t}\n\n\tfunction _removeToken() {\n\t  if (document.location.hash == '#ath') {\n\t    history.replaceState('', window.document.title, document.location.href.split('#')[0]);\n\t  }\n\n\t  if (_reSmartURL.test(document.location.href)) {\n\t    history.replaceState('', window.document.title, document.location.href.replace(_reSmartURL, '$1'));\n\t  }\n\n\t  if (_reQueryString.test(document.location.search)) {\n\t    history.replaceState('', window.document.title, document.location.href.replace(_reQueryString, '$2'));\n\t  }\n\t}\n\n\t/* jshint +W101, +W106 */\n\n\tath.VERSION = '3.2.2';\n\n\tmodule.exports = UI.addToHomescreen = ath;\n\n\n/***/ },\n/* 5 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\n\t/**\n\t * @via https://github.com/Minwe/bootstrap/blob/master/js/alert.js\n\t * @copyright Copyright 2013 Twitter, Inc.\n\t * @license Apache 2.0\n\t */\n\n\t// Alert Class\n\t// NOTE: removeElement option is unavailable now\n\tvar Alert = function(element, options) {\n\t  var _this = this;\n\t  this.options = $.extend({}, Alert.DEFAULTS, options);\n\t  this.$element = $(element);\n\n\t  this.$element\n\t    .addClass('am-fade am-in')\n\t    .on('click.alert.amui', '.am-close', function() {\n\t      _this.close();\n\t    });\n\t};\n\n\tAlert.DEFAULTS = {\n\t  removeElement: true\n\t};\n\n\tAlert.prototype.close = function() {\n\t  var $element = this.$element;\n\n\t  $element.trigger('close.alert.amui').removeClass('am-in');\n\n\t  function processAlert() {\n\t    $element.trigger('closed.alert.amui').remove();\n\t  }\n\n\t  UI.support.transition && $element.hasClass('am-fade') ?\n\t    $element\n\t      .one(UI.support.transition.end, processAlert)\n\t      .emulateTransitionEnd(200) :\n\t    processAlert();\n\t};\n\n\t// plugin\n\tUI.plugin('alert', Alert);\n\n\t// Init code\n\t$(document).on('click.alert.amui.data-api', '[data-am-alert]', function(e) {\n\t  var $target = $(e.target);\n\t  $target.is('.am-close') && $(this).alert('close');\n\t});\n\n\tmodule.exports = Alert;\n\n\n/***/ },\n/* 6 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\n\t/**\n\t * @via https://github.com/twbs/bootstrap/blob/master/js/button.js\n\t * @copyright (c) 2011-2014 Twitter, Inc\n\t * @license The MIT License\n\t */\n\n\tvar Button = function(element, options) {\n\t  this.$element = $(element);\n\t  this.options = $.extend({}, Button.DEFAULTS, options);\n\t  this.isLoading = false;\n\t  this.hasSpinner = false;\n\t};\n\n\tButton.DEFAULTS = {\n\t  loadingText: 'loading...',\n\t  disabledClassName: 'am-disabled',\n\t  spinner: undefined\n\t};\n\n\tButton.prototype.setState = function(state, stateText) {\n\t  var $element = this.$element;\n\t  var disabled = 'disabled';\n\t  var data = $element.data();\n\t  var options = this.options;\n\t  var val = $element.is('input') ? 'val' : 'html';\n\t  var stateClassName = 'am-btn-' + state + ' ' + options.disabledClassName;\n\n\t  state += 'Text';\n\n\t  if (!options.resetText) {\n\t    options.resetText = $element[val]();\n\t  }\n\n\t  // add spinner for element with html()\n\t  if (UI.support.animation && options.spinner &&\n\t    val === 'html' && !this.hasSpinner) {\n\t    options.loadingText = '<span class=\"am-icon-' + options.spinner +\n\t      ' am-icon-spin\"></span>' + options.loadingText;\n\n\t    this.hasSpinner = true;\n\t  }\n\n\t  stateText = stateText ||\n\t    (data[state] === undefined ? options[state] : data[state]);\n\n\t  $element[val](stateText);\n\n\t  // push to event loop to allow forms to submit\n\t  setTimeout($.proxy(function() {\n\t    // TODO: add stateClass for other states\n\t    if (state === 'loadingText') {\n\t      $element.addClass(stateClassName).attr(disabled, disabled);\n\t      this.isLoading = true;\n\t    } else if (this.isLoading) {\n\t      $element.removeClass(stateClassName).removeAttr(disabled);\n\t      this.isLoading = false;\n\t    }\n\t  }, this), 0);\n\t};\n\n\tButton.prototype.toggle = function() {\n\t  var changed = true;\n\t  var $element = this.$element;\n\t  var $parent = this.$element.parent('[class*=\"am-btn-group\"]');\n\n\t  if ($parent.length) {\n\t    var $input = this.$element.find('input');\n\n\t    if ($input.prop('type') == 'radio') {\n\t      if ($input.prop('checked') && $element.hasClass('am-active')) {\n\t        changed = false;\n\t      } else {\n\t        $parent.find('.am-active').removeClass('am-active');\n\t      }\n\t    }\n\n\t    if (changed) {\n\t      $input.prop('checked',\n\t        !$element.hasClass('am-active')).trigger('change');\n\t    }\n\t  }\n\n\t  if (changed) {\n\t    $element.toggleClass('am-active');\n\t    if (!$element.hasClass('am-active')) {\n\t      $element.blur();\n\t    }\n\t  }\n\t};\n\n\tUI.plugin('button', Button, {\n\t  dataOptions: 'data-am-loading',\n\t  methodCall: function(args, instance) {\n\t    if (args[0] === 'toggle') {\n\t      instance.toggle();\n\t    } else if (typeof args[0] === 'string') {\n\t      instance.setState.apply(instance, args);\n\t    }\n\t  }\n\t});\n\n\t// Init code\n\t$(document).on('click.button.amui.data-api', '[data-am-button]', function(e) {\n\t  e.preventDefault();\n\t  var $btn = $(e.target);\n\n\t  if (!$btn.hasClass('am-btn')) {\n\t    $btn = $btn.closest('.am-btn');\n\t  }\n\n\t  $btn.button('toggle');\n\t});\n\n\tUI.ready(function(context) {\n\t  $('[data-am-loading]', context).button();\n\t});\n\n\tmodule.exports = UI.button = Button;\n\n\n/***/ },\n/* 7 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\n\t/**\n\t * @via https://github.com/twbs/bootstrap/blob/master/js/collapse.js\n\t * @copyright (c) 2011-2014 Twitter, Inc\n\t * @license The MIT License\n\t */\n\n\tvar Collapse = function(element, options) {\n\t  this.$element = $(element);\n\t  this.options = $.extend({}, Collapse.DEFAULTS, options);\n\t  this.transitioning = null;\n\n\t  if (this.options.parent) {\n\t    this.$parent = $(this.options.parent);\n\t  }\n\n\t  if (this.options.toggle) {\n\t    this.toggle();\n\t  }\n\t};\n\n\tCollapse.DEFAULTS = {\n\t  toggle: true\n\t};\n\n\tCollapse.prototype.open = function() {\n\t  if (this.transitioning || this.$element.hasClass('am-in')) {\n\t    return;\n\t  }\n\n\t  var startEvent = $.Event('open.collapse.amui');\n\t  this.$element.trigger(startEvent);\n\n\t  if (startEvent.isDefaultPrevented()) {\n\t    return;\n\t  }\n\n\t  var actives = this.$parent && this.$parent.find('> .am-panel > .am-in');\n\n\t  if (actives && actives.length) {\n\t    var hasData = actives.data('amui.collapse');\n\n\t    if (hasData && hasData.transitioning) {\n\t      return;\n\t    }\n\n\t    Plugin.call(actives, 'close');\n\n\t    hasData || actives.data('amui.collapse', null);\n\t  }\n\n\t  this.$element\n\t    .removeClass('am-collapse')\n\t    .addClass('am-collapsing').height(0);\n\n\t  this.transitioning = 1;\n\n\t  var complete = function() {\n\t    this.$element\n\t      .removeClass('am-collapsing')\n\t      .addClass('am-collapse am-in')\n\t      .height('')\n\t      .trigger('opened.collapse.amui');\n\t    this.transitioning = 0;\n\t  };\n\n\t  if (!UI.support.transition) {\n\t    return complete.call(this);\n\t  }\n\n\t  var scrollHeight = this.$element[0].scrollHeight;\n\n\t  this.$element\n\t    .one(UI.support.transition.end, $.proxy(complete, this))\n\t    .emulateTransitionEnd(300)\n\t    .css({height: scrollHeight}); // 当折叠的容器有 padding 时，如果用 height() 只能设置内容的宽度\n\t};\n\n\tCollapse.prototype.close = function() {\n\t  if (this.transitioning || !this.$element.hasClass('am-in')) {\n\t    return;\n\t  }\n\n\t  var startEvent = $.Event('close.collapse.amui');\n\t  this.$element.trigger(startEvent);\n\n\t  if (startEvent.isDefaultPrevented()) {\n\t    return;\n\t  }\n\n\t  this.$element.height(this.$element.height()).redraw();\n\n\t  this.$element.addClass('am-collapsing').\n\t    removeClass('am-collapse am-in');\n\n\t  this.transitioning = 1;\n\n\t  var complete = function() {\n\t    this.transitioning = 0;\n\t    this.$element\n\t      .trigger('closed.collapse.amui')\n\t      .removeClass('am-collapsing')\n\t      .addClass('am-collapse');\n\t    // css({height: '0'});\n\t  };\n\n\t  if (!UI.support.transition) {\n\t    return complete.call(this);\n\t  }\n\n\t  this.$element.height(0)\n\t    .one(UI.support.transition.end, $.proxy(complete, this))\n\t    .emulateTransitionEnd(300);\n\t};\n\n\tCollapse.prototype.toggle = function() {\n\t  this[this.$element.hasClass('am-in') ? 'close' : 'open']();\n\t};\n\n\t// Collapse Plugin\n\tfunction Plugin(option) {\n\t  return this.each(function() {\n\t    var $this = $(this);\n\t    var data = $this.data('amui.collapse');\n\t    var options = $.extend({}, Collapse.DEFAULTS,\n\t      UI.utils.options($this.attr('data-am-collapse')),\n\t      typeof option == 'object' && option);\n\n\t    if (!data && options.toggle && option === 'open') {\n\t      option = !option;\n\t    }\n\n\t    if (!data) {\n\t      $this.data('amui.collapse', (data = new Collapse(this, options)));\n\t    }\n\n\t    if (typeof option == 'string') {\n\t      data[option]();\n\t    }\n\t  });\n\t}\n\n\t$.fn.collapse = Plugin;\n\n\t// Init code\n\t$(document).on('click.collapse.amui.data-api', '[data-am-collapse]',\n\t  function(e) {\n\t    var href;\n\t    var $this = $(this);\n\t    var options = UI.utils.options($this.attr('data-am-collapse'));\n\t    var target = options.target ||\n\t      e.preventDefault() ||\n\t      (href = $this.attr('href')) &&\n\t      href.replace(/.*(?=#[^\\s]+$)/, '');\n\t    var $target = $(target);\n\t    var data = $target.data('amui.collapse');\n\t    var option = data ? 'toggle' : options;\n\t    var parent = options.parent;\n\t    var $parent = parent && $(parent);\n\n\t    if (!data || !data.transitioning) {\n\t      if ($parent) {\n\t        // '[data-am-collapse*=\"{parent: \\'' + parent + '\"]\n\t        $parent.find('[data-am-collapse]').not($this).addClass('am-collapsed');\n\t      }\n\n\t      $this[$target.hasClass('am-in') ?\n\t        'addClass' : 'removeClass']('am-collapsed');\n\t    }\n\n\t    Plugin.call($target, option);\n\t  });\n\n\tmodule.exports = UI.collapse = Collapse;\n\n\t// TODO: 更好的 target 选择方式\n\t//       折叠的容器必须没有 border/padding 才能正常处理，否则动画会有一些小问题\n\t//       寻找更好的未知高度 transition 动画解决方案，max-height 之类的就算了\n\n\n/***/ },\n/* 8 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\tvar $doc = $(document);\n\n\t/**\n\t * bootstrap-datepicker.js\n\t * @via http://www.eyecon.ro/bootstrap-datepicker\n\t * @license http://www.apache.org/licenses/LICENSE-2.0\n\t */\n\tvar Datepicker = function(element, options) {\n\t  this.$element = $(element);\n\t  this.options = $.extend({}, Datepicker.DEFAULTS, options);\n\t  this.format = DPGlobal.parseFormat(this.options.format);\n\n\t  this.$element.data('date', this.options.date);\n\t  this.language = this.getLocale(this.options.locale);\n\t  this.theme = this.options.theme;\n\t  this.$picker = $(DPGlobal.template).appendTo('body').on({\n\t    click: $.proxy(this.click, this)\n\t    // mousedown: $.proxy(this.mousedown, this)\n\t  });\n\n\t  this.isInput = this.$element.is('input');\n\t  this.component = this.$element.is('.am-datepicker-date') ?\n\t    this.$element.find('.am-datepicker-add-on') : false;\n\n\t  if (this.isInput) {\n\t    this.$element.on({\n\t      'click.datepicker.amui': $.proxy(this.open, this),\n\t      // blur: $.proxy(this.close, this),\n\t      'keyup.datepicker.amui': $.proxy(this.update, this)\n\t    });\n\t  } else {\n\t    if (this.component) {\n\t      this.component.on('click.datepicker.amui', $.proxy(this.open, this));\n\t    } else {\n\t      this.$element.on('click.datepicker.amui', $.proxy(this.open, this));\n\t    }\n\t  }\n\n\t  this.minViewMode = this.options.minViewMode;\n\n\t  if (typeof this.minViewMode === 'string') {\n\t    switch (this.minViewMode) {\n\t      case 'months':\n\t        this.minViewMode = 1;\n\t        break;\n\t      case 'years':\n\t        this.minViewMode = 2;\n\t        break;\n\t      default:\n\t        this.minViewMode = 0;\n\t        break;\n\t    }\n\t  }\n\n\t  this.viewMode = this.options.viewMode;\n\n\t  if (typeof this.viewMode === 'string') {\n\t    switch (this.viewMode) {\n\t      case 'months':\n\t        this.viewMode = 1;\n\t        break;\n\t      case 'years':\n\t        this.viewMode = 2;\n\t        break;\n\t      default:\n\t        this.viewMode = 0;\n\t        break;\n\t    }\n\t  }\n\n\t  this.startViewMode = this.viewMode;\n\t  this.weekStart = ((this.options.weekStart ||\n\t  Datepicker.locales[this.language].weekStart || 0) % 7);\n\t  this.weekEnd = ((this.weekStart + 6) % 7);\n\t  this.onRender = this.options.onRender;\n\n\t  this.setTheme();\n\t  this.fillDow();\n\t  this.fillMonths();\n\t  this.update();\n\t  this.showMode();\n\t};\n\n\tDatepicker.DEFAULTS = {\n\t  locale: 'zh_CN',\n\t  format: 'yyyy-mm-dd',\n\t  weekStart: undefined,\n\t  viewMode: 0,\n\t  minViewMode: 0,\n\t  date: '',\n\t  theme: '',\n\t  autoClose: 1,\n\t  onRender: function(date) {\n\t    return '';\n\t  }\n\t};\n\n\tDatepicker.prototype.open = function(e) {\n\t  this.$picker.show();\n\t  this.height = this.component ?\n\t    this.component.outerHeight() : this.$element.outerHeight();\n\n\t  this.place();\n\t  $(window).on('resize.datepicker.amui', $.proxy(this.place, this));\n\t  if (e) {\n\t    e.stopPropagation();\n\t    e.preventDefault();\n\t  }\n\t  var that = this;\n\t  $doc.on('mousedown.datapicker.amui touchstart.datepicker.amui', function(ev) {\n\t    if ($(ev.target).closest('.am-datepicker').length === 0) {\n\t      that.close();\n\t    }\n\t  });\n\t  this.$element.trigger({\n\t    type: 'open.datepicker.amui',\n\t    date: this.date\n\t  });\n\t};\n\n\tDatepicker.prototype.close = function() {\n\t  this.$picker.hide();\n\t  $(window).off('resize.datepicker.amui', this.place);\n\t  this.viewMode = this.startViewMode;\n\t  this.showMode();\n\t  if (!this.isInput) {\n\t    $(document).off('mousedown.datapicker.amui touchstart.datepicker.amui',\n\t      this.close);\n\t  }\n\t  // this.set();\n\t  this.$element.trigger({\n\t    type: 'close.datepicker.amui',\n\t    date: this.date\n\t  });\n\t};\n\n\tDatepicker.prototype.set = function() {\n\t  var formatted = DPGlobal.formatDate(this.date, this.format);\n\t  var $input;\n\n\t  if (!this.isInput) {\n\t    if (this.component) {\n\t      $input = this.$element.find('input').attr('value', formatted);\n\t    }\n\n\t    this.$element.data('date', formatted);\n\t  } else {\n\t    $input = this.$element.attr('value', formatted);\n\t  }\n\n\t  // fixes https://github.com/amazeui/amazeui/issues/711\n\t  $input && $input.trigger('change');\n\t};\n\n\tDatepicker.prototype.setValue = function(newDate) {\n\t  if (typeof newDate === 'string') {\n\t    this.date = DPGlobal.parseDate(newDate, this.format);\n\t  } else {\n\t    this.date = new Date(newDate);\n\t  }\n\t  this.set();\n\n\t  this.viewDate = new Date(this.date.getFullYear(),\n\t    this.date.getMonth(), 1, 0, 0, 0, 0);\n\n\t  this.fill();\n\t};\n\n\tDatepicker.prototype.place = function() {\n\t  var offset = this.component ?\n\t    this.component.offset() : this.$element.offset();\n\t  var $width = this.component ?\n\t    this.component.width() : this.$element.width();\n\t  var top = offset.top + this.height;\n\t  var left = offset.left;\n\t  var right = $doc.width() - offset.left - $width;\n\t  var isOutView = this.isOutView();\n\n\t  this.$picker.removeClass('am-datepicker-right');\n\t  this.$picker.removeClass('am-datepicker-up');\n\n\t  if ($doc.width() > 640) {\n\t    if (isOutView.outRight) {\n\t      this.$picker.addClass('am-datepicker-right');\n\t      this.$picker.css({\n\t        top: top,\n\t        left: 'auto',\n\t        right: right\n\t      });\n\t      return;\n\t    }\n\t    if (isOutView.outBottom) {\n\t      this.$picker.addClass('am-datepicker-up');\n\t      top = offset.top - this.$picker.outerHeight(true);\n\t    }\n\t  } else {\n\t    left = 0;\n\t  }\n\n\t  this.$picker.css({\n\t    top: top,\n\t    left: left\n\t  });\n\t};\n\n\tDatepicker.prototype.update = function(newDate) {\n\t  this.date = DPGlobal.parseDate(\n\t    typeof newDate === 'string' ? newDate : (this.isInput ?\n\t      this.$element.prop('value') : this.$element.data('date')),\n\t    this.format\n\t  );\n\t  this.viewDate = new Date(this.date.getFullYear(),\n\t    this.date.getMonth(), 1, 0, 0, 0, 0);\n\t  this.fill();\n\t};\n\n\t// Days of week\n\tDatepicker.prototype.fillDow = function() {\n\t  var dowCount = this.weekStart;\n\t  var html = '<tr>';\n\t  while (dowCount < this.weekStart + 7) {\n\t    // NOTE: do % then add 1\n\t    html += '<th class=\"am-datepicker-dow\">' +\n\t    Datepicker.locales[this.language].daysMin[(dowCount++) % 7] +\n\t    '</th>';\n\t  }\n\t  html += '</tr>';\n\n\t  this.$picker.find('.am-datepicker-days thead').append(html);\n\t};\n\n\tDatepicker.prototype.fillMonths = function() {\n\t  var html = '';\n\t  var i = 0;\n\t  while (i < 12) {\n\t    html += '<span class=\"am-datepicker-month\">' +\n\t    Datepicker.locales[this.language].monthsShort[i++] + '</span>';\n\t  }\n\t  this.$picker.find('.am-datepicker-months td').append(html);\n\t};\n\n\tDatepicker.prototype.fill = function() {\n\t  var d = new Date(this.viewDate);\n\t  var year = d.getFullYear();\n\t  var month = d.getMonth();\n\t  var currentDate = this.date.valueOf();\n\n\t  var prevMonth = new Date(year, month - 1, 28, 0, 0, 0, 0);\n\t  var day = DPGlobal\n\t    .getDaysInMonth(prevMonth.getFullYear(), prevMonth.getMonth());\n\n\t  var daysSelect = this.$picker\n\t    .find('.am-datepicker-days .am-datepicker-select');\n\n\t  if (this.language === 'zh_CN') {\n\t    daysSelect.text(year + Datepicker.locales[this.language].year[0] +\n\t    ' ' + Datepicker.locales[this.language].months[month]);\n\t  } else {\n\t    daysSelect.text(Datepicker.locales[this.language].months[month] +\n\t    ' ' + year);\n\t  }\n\n\t  prevMonth.setDate(day);\n\t  prevMonth.setDate(day - (prevMonth.getDay() - this.weekStart + 7) % 7);\n\n\t  var nextMonth = new Date(prevMonth);\n\t  nextMonth.setDate(nextMonth.getDate() + 42);\n\t  nextMonth = nextMonth.valueOf();\n\t  var html = [];\n\n\t  var className;\n\t  var prevY;\n\t  var prevM;\n\n\t  while (prevMonth.valueOf() < nextMonth) {\n\t    if (prevMonth.getDay() === this.weekStart) {\n\t      html.push('<tr>');\n\t    }\n\n\t    className = this.onRender(prevMonth, 0);\n\t    prevY = prevMonth.getFullYear();\n\t    prevM = prevMonth.getMonth();\n\n\t    if ((prevM < month && prevY === year) || prevY < year) {\n\t      className += ' am-datepicker-old';\n\t    } else if ((prevM > month && prevY === year) || prevY > year) {\n\t      className += ' am-datepicker-new';\n\t    }\n\n\t    if (prevMonth.valueOf() === currentDate) {\n\t      className += ' am-active';\n\t    }\n\t    html.push('<td class=\"am-datepicker-day ' +\n\t    className + '\">' + prevMonth.getDate() + '</td>');\n\n\t    if (prevMonth.getDay() === this.weekEnd) {\n\t      html.push('</tr>');\n\t    }\n\n\t    prevMonth.setDate(prevMonth.getDate() + 1);\n\t  }\n\n\t  this.$picker.find('.am-datepicker-days tbody')\n\t    .empty().append(html.join(''));\n\n\t  var currentYear = this.date.getFullYear();\n\t  var months = this.$picker.find('.am-datepicker-months')\n\t    .find('.am-datepicker-select')\n\t    .text(year);\n\t  months = months.end()\n\t    .find('span').removeClass('am-active').removeClass('am-disabled');\n\n\t  var monthLen = 0;\n\n\t  while (monthLen < 12) {\n\t    if (this.onRender(d.setFullYear(year, monthLen), 1)) {\n\t      months.eq(monthLen).addClass('am-disabled');\n\t    }\n\t    monthLen++;\n\t  }\n\n\t  if (currentYear === year) {\n\t    months.eq(this.date.getMonth())\n\t        .removeClass('am-disabled')\n\t        .addClass('am-active');\n\t  }\n\n\t  html = '';\n\t  year = parseInt(year / 10, 10) * 10;\n\t  var yearCont = this.$picker\n\t    .find('.am-datepicker-years')\n\t    .find('.am-datepicker-select')\n\t    .text(year + '-' + (year + 9))\n\t    .end()\n\t    .find('td');\n\t  var yearClassName;\n\t  // fixes https://github.com/amazeui/amazeui/issues/770\n\t  // maybe not need now\n\t  var viewDate = new Date(this.viewDate);\n\n\t  year -= 1;\n\n\t  for (var i = -1; i < 11; i++) {\n\t    yearClassName = this.onRender(viewDate.setFullYear(year), 2);\n\t    html += '<span class=\"' + yearClassName + '' +\n\t    (i === -1 || i === 10 ? ' am-datepicker-old' : '') +\n\t    (currentYear === year ? ' am-active' : '') + '\">' + year + '</span>';\n\t    year += 1;\n\t  }\n\t  yearCont.html(html);\n\t};\n\n\tDatepicker.prototype.click = function(event) {\n\t  event.stopPropagation();\n\t  event.preventDefault();\n\t  var month;\n\t  var year;\n\t  var $dayActive = this.$picker.find('.am-datepicker-days').find('.am-active');\n\t  var $months = this.$picker.find('.am-datepicker-months');\n\t  var $monthIndex = $months.find('.am-active').index();\n\n\t  var $target = $(event.target).closest('span, td, th');\n\t  if ($target.length === 1) {\n\t    switch ($target[0].nodeName.toLowerCase()) {\n\t      case 'th':\n\t        switch ($target[0].className) {\n\t          case 'am-datepicker-switch':\n\t            this.showMode(1);\n\t            break;\n\t          case 'am-datepicker-prev':\n\t          case 'am-datepicker-next':\n\t            this.viewDate['set' + DPGlobal.modes[this.viewMode].navFnc].call(\n\t              this.viewDate,\n\t              this.viewDate\n\t                ['get' + DPGlobal.modes[this.viewMode].navFnc]\n\t                .call(this.viewDate) +\n\t              DPGlobal.modes[this.viewMode].navStep *\n\t              ($target[0].className === 'am-datepicker-prev' ? -1 : 1)\n\t            );\n\t            this.fill();\n\t            this.set();\n\t            break;\n\t        }\n\t        break;\n\t      case 'span':\n\t        if ($target.is('.am-disabled')) {\n\t          return;\n\t        }\n\n\t        if ($target.is('.am-datepicker-month')) {\n\t          month = $target.parent().find('span').index($target);\n\n\t          if ($target.is('.am-active')) {\n\t            this.viewDate.setMonth(month, $dayActive.text());\n\t          } else {\n\t            this.viewDate.setMonth(month);\n\t          }\n\n\t        } else {\n\t          year = parseInt($target.text(), 10) || 0;\n\t          if ($target.is('.am-active')) {\n\t            this.viewDate.setFullYear(year, $monthIndex, $dayActive.text());\n\t          } else {\n\t            this.viewDate.setFullYear(year);\n\t          }\n\n\t        }\n\n\t        if (this.viewMode !== 0) {\n\t          this.date = new Date(this.viewDate);\n\t          this.$element.trigger({\n\t            type: 'changeDate.datepicker.amui',\n\t            date: this.date,\n\t            viewMode: DPGlobal.modes[this.viewMode].clsName\n\t          });\n\t        }\n\n\t        this.showMode(-1);\n\t        this.fill();\n\t        this.set();\n\t        break;\n\t      case 'td':\n\t        if ($target.is('.am-datepicker-day') && !$target.is('.am-disabled')) {\n\t          var day = parseInt($target.text(), 10) || 1;\n\t          month = this.viewDate.getMonth();\n\t          if ($target.is('.am-datepicker-old')) {\n\t            month -= 1;\n\t          } else if ($target.is('.am-datepicker-new')) {\n\t            month += 1;\n\t          }\n\t          year = this.viewDate.getFullYear();\n\t          this.date = new Date(year, month, day, 0, 0, 0, 0);\n\t          this.viewDate = new Date(year, month, Math.min(28, day), 0, 0, 0, 0);\n\t          this.fill();\n\t          this.set();\n\t          this.$element.trigger({\n\t            type: 'changeDate.datepicker.amui',\n\t            date: this.date,\n\t            viewMode: DPGlobal.modes[this.viewMode].clsName\n\t          });\n\n\t          this.options.autoClose && this.close();\n\t        }\n\t        break;\n\t    }\n\t  }\n\t};\n\n\tDatepicker.prototype.mousedown = function(event) {\n\t  event.stopPropagation();\n\t  event.preventDefault();\n\t};\n\n\tDatepicker.prototype.showMode = function(dir) {\n\t  if (dir) {\n\t    this.viewMode = Math.max(this.minViewMode,\n\t      Math.min(2, this.viewMode + dir));\n\t  }\n\n\t  this.$picker.find('>div').hide().\n\t    filter('.am-datepicker-' + DPGlobal.modes[this.viewMode].clsName).show();\n\t};\n\n\tDatepicker.prototype.isOutView = function() {\n\t  var offset = this.component ?\n\t    this.component.offset() : this.$element.offset();\n\t  var isOutView = {\n\t    outRight: false,\n\t    outBottom: false\n\t  };\n\t  var $picker = this.$picker;\n\t  var width = offset.left + $picker.outerWidth(true);\n\t  var height = offset.top + $picker.outerHeight(true) +\n\t    this.$element.innerHeight();\n\n\t  if (width > $doc.width()) {\n\t    isOutView.outRight = true;\n\t  }\n\t  if (height > $doc.height()) {\n\t    isOutView.outBottom = true;\n\t  }\n\t  return isOutView;\n\t};\n\n\tDatepicker.prototype.getLocale = function(locale) {\n\t  if (!locale) {\n\t    locale = navigator.language && navigator.language.split('-');\n\t    locale[1] = locale[1].toUpperCase();\n\t    locale = locale.join('_');\n\t  }\n\n\t  if (!Datepicker.locales[locale]) {\n\t    locale = 'en_US';\n\t  }\n\t  return locale;\n\t};\n\n\tDatepicker.prototype.setTheme = function() {\n\t  if (this.theme) {\n\t    this.$picker.addClass('am-datepicker-' + this.theme);\n\t  }\n\t};\n\n\t// Datepicker locales\n\tDatepicker.locales = {\n\t  en_US: {\n\t    days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',\n\t      'Friday', 'Saturday'],\n\t    daysShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],\n\t    daysMin: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'],\n\t    months: ['January', 'February', 'March', 'April', 'May', 'June',\n\t      'July', 'August', 'September', 'October', 'November', 'December'],\n\t    monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',\n\t      'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],\n\t    weekStart: 0\n\t  },\n\t  zh_CN: {\n\t    days: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],\n\t    daysShort: ['周日', '周一', '周二', '周三', '周四', '周五', '周六'],\n\t    daysMin: ['日', '一', '二', '三', '四', '五', '六'],\n\t    months: ['一月', '二月', '三月', '四月', '五月', '六月', '七月',\n\t      '八月', '九月', '十月', '十一月', '十二月'],\n\t    monthsShort: ['一月', '二月', '三月', '四月', '五月', '六月',\n\t      '七月', '八月', '九月', '十月', '十一月', '十二月'],\n\t    weekStart: 1,\n\t    year: ['年']\n\t  }\n\t};\n\n\tvar DPGlobal = {\n\t  modes: [\n\t    {\n\t      clsName: 'days',\n\t      navFnc: 'Month',\n\t      navStep: 1\n\t    },\n\t    {\n\t      clsName: 'months',\n\t      navFnc: 'FullYear',\n\t      navStep: 1\n\t    },\n\t    {\n\t      clsName: 'years',\n\t      navFnc: 'FullYear',\n\t      navStep: 10\n\t    }\n\t  ],\n\n\t  isLeapYear: function(year) {\n\t    return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0));\n\t  },\n\n\t  getDaysInMonth: function(year, month) {\n\t    return [31, (DPGlobal.isLeapYear(year) ? 29 : 28),\n\t      31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];\n\t  },\n\n\t  parseFormat: function(format) {\n\t    var separator = format.match(/[.\\/\\-\\s].*?/);\n\t    var parts = format.split(/\\W+/);\n\n\t    if (!separator || !parts || parts.length === 0) {\n\t      throw new Error('Invalid date format.');\n\t    }\n\n\t    return {\n\t      separator: separator,\n\t      parts: parts\n\t    };\n\t  },\n\n\t  parseDate: function(date, format) {\n\t    var parts = date.split(format.separator);\n\t    var val;\n\t    date = new Date();\n\n\t    date.setHours(0);\n\t    date.setMinutes(0);\n\t    date.setSeconds(0);\n\t    date.setMilliseconds(0);\n\n\t    if (parts.length === format.parts.length) {\n\t      var year = date.getFullYear();\n\t      var day = date.getDate();\n\t      var month = date.getMonth();\n\n\t      for (var i = 0, cnt = format.parts.length; i < cnt; i++) {\n\t        val = parseInt(parts[i], 10) || 1;\n\t        switch (format.parts[i]) {\n\t          case 'dd':\n\t          case 'd':\n\t            day = val;\n\t            date.setDate(val);\n\t            break;\n\t          case 'mm':\n\t          case 'm':\n\t            month = val - 1;\n\t            date.setMonth(val - 1);\n\t            break;\n\t          case 'yy':\n\t            year = 2000 + val;\n\t            date.setFullYear(2000 + val);\n\t            break;\n\t          case 'yyyy':\n\t            year = val;\n\t            date.setFullYear(val);\n\t            break;\n\t        }\n\t      }\n\t      date = new Date(year, month, day, 0, 0, 0);\n\t    }\n\t    return date;\n\t  },\n\n\t  formatDate: function(date, format) {\n\t    var val = {\n\t      d: date.getDate(),\n\t      m: date.getMonth() + 1,\n\t      yy: date.getFullYear().toString().substring(2),\n\t      yyyy: date.getFullYear()\n\t    };\n\t    var dateArray = [];\n\n\t    val.dd = (val.d < 10 ? '0' : '') + val.d;\n\t    val.mm = (val.m < 10 ? '0' : '') + val.m;\n\n\t    for (var i = 0, cnt = format.parts.length; i < cnt; i++) {\n\t      dateArray.push(val[format.parts[i]]);\n\t    }\n\t    return dateArray.join(format.separator);\n\t  },\n\n\t  headTemplate: '<thead>' +\n\t  '<tr class=\"am-datepicker-header\">' +\n\t  '<th class=\"am-datepicker-prev\">' +\n\t  '<i class=\"am-datepicker-prev-icon\"></i></th>' +\n\t  '<th colspan=\"5\" class=\"am-datepicker-switch\">' +\n\t  '<div class=\"am-datepicker-select\"></div></th>' +\n\t  '<th class=\"am-datepicker-next\"><i class=\"am-datepicker-next-icon\"></i>' +\n\t  '</th></tr></thead>',\n\n\t  contTemplate: '<tbody><tr><td colspan=\"7\"></td></tr></tbody>'\n\t};\n\n\tDPGlobal.template = '<div class=\"am-datepicker am-datepicker-dropdown\">' +\n\t'<div class=\"am-datepicker-caret\"></div>' +\n\t'<div class=\"am-datepicker-days\">' +\n\t'<table class=\"am-datepicker-table\">' +\n\tDPGlobal.headTemplate +\n\t'<tbody></tbody>' +\n\t'</table>' +\n\t'</div>' +\n\t'<div class=\"am-datepicker-months\">' +\n\t'<table class=\"am-datepicker-table\">' +\n\tDPGlobal.headTemplate +\n\tDPGlobal.contTemplate +\n\t'</table>' +\n\t'</div>' +\n\t'<div class=\"am-datepicker-years\">' +\n\t'<table class=\"am-datepicker-table\">' +\n\tDPGlobal.headTemplate +\n\tDPGlobal.contTemplate +\n\t'</table>' +\n\t'</div>' +\n\t'</div>';\n\n\t// jQuery plugin\n\tUI.plugin('datepicker', Datepicker);\n\n\t// Init code\n\tUI.ready(function(context) {\n\t  $('[data-am-datepicker]').datepicker();\n\t});\n\n\tmodule.exports = UI.datepicker = Datepicker;\n\n\t// TODO: 1. 载入动画\n\t//       2. less 优化\n\n\n/***/ },\n/* 9 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\tvar $doc = $(document);\n\tvar transition = UI.support.transition;\n\n\tvar Dimmer = function() {\n\t  this.id = UI.utils.generateGUID('am-dimmer');\n\t  this.$element = $(Dimmer.DEFAULTS.tpl, {\n\t    id: this.id\n\t  });\n\n\t  this.inited = false;\n\t  this.scrollbarWidth = 0;\n\t  this.$used = $([]);\n\t};\n\n\tDimmer.DEFAULTS = {\n\t  tpl: '<div class=\"am-dimmer\" data-am-dimmer></div>'\n\t};\n\n\tDimmer.prototype.init = function() {\n\t  if (!this.inited) {\n\t    $(document.body).append(this.$element);\n\t    this.inited = true;\n\t    $doc.trigger('init.dimmer.amui');\n\t    this.$element.on('touchmove.dimmer.amui', function(e) {\n\t      e.preventDefault();\n\t    });\n\t  }\n\n\t  return this;\n\t};\n\n\tDimmer.prototype.open = function(relatedElement) {\n\t  if (!this.inited) {\n\t    this.init();\n\t  }\n\n\t  var $element = this.$element;\n\n\t  // 用于多重调用\n\t  if (relatedElement) {\n\t    this.$used = this.$used.add($(relatedElement));\n\t  }\n\n\t  this.checkScrollbar().setScrollbar();\n\n\t  $element.show().trigger('open.dimmer.amui');\n\n\t  transition && $element.off(transition.end);\n\n\t  setTimeout(function() {\n\t    $element.addClass('am-active');\n\t  }, 0);\n\n\t  return this;\n\t};\n\n\tDimmer.prototype.close = function(relatedElement, force) {\n\t  this.$used = this.$used.not($(relatedElement));\n\n\t  if (!force && this.$used.length) {\n\t    return this;\n\t  }\n\n\t  var $element = this.$element;\n\n\t  $element.removeClass('am-active').trigger('close.dimmer.amui');\n\n\t  function complete() {\n\t    $element.hide();\n\t    this.resetScrollbar();\n\t  }\n\n\t  // transition ? $element.one(transition.end, $.proxy(complete, this)) :\n\t  complete.call(this);\n\n\t  return this;\n\t};\n\n\tDimmer.prototype.checkScrollbar = function() {\n\t  this.scrollbarWidth = UI.utils.measureScrollbar();\n\n\t  return this;\n\t};\n\n\tDimmer.prototype.setScrollbar = function() {\n\t  var $body = $(document.body);\n\t  var bodyPaddingRight = parseInt(($body.css('padding-right') || 0), 10);\n\n\t  if (this.scrollbarWidth) {\n\t    $body.css('padding-right', bodyPaddingRight + this.scrollbarWidth);\n\t  }\n\n\t  $body.addClass('am-dimmer-active');\n\n\t  return this;\n\t};\n\n\tDimmer.prototype.resetScrollbar = function() {\n\t  $(document.body).css('padding-right', '').removeClass('am-dimmer-active');\n\n\t  return this;\n\t};\n\n\tmodule.exports = UI.dimmer = new Dimmer();\n\n\n/***/ },\n/* 10 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\tvar animation = UI.support.animation;\n\n\t/**\n\t * @via https://github.com/Minwe/bootstrap/blob/master/js/dropdown.js\n\t * @copyright (c) 2011-2014 Twitter, Inc\n\t * @license The MIT License\n\t */\n\n\t// var toggle = '[data-am-dropdown] > .am-dropdown-toggle';\n\n\tvar Dropdown = function(element, options) {\n\t  this.options = $.extend({}, Dropdown.DEFAULTS, options);\n\n\t  options = this.options;\n\n\t  this.$element = $(element);\n\t  this.$toggle = this.$element.find(options.selector.toggle);\n\t  this.$dropdown = this.$element.find(options.selector.dropdown);\n\t  this.$boundary = (options.boundary === window) ? $(window) :\n\t    this.$element.closest(options.boundary);\n\t  this.$justify = (options.justify && $(options.justify).length &&\n\t  $(options.justify)) || undefined;\n\n\t  !this.$boundary.length && (this.$boundary = $(window));\n\n\t  this.active = this.$element.hasClass('am-active') ? true : false;\n\t  this.animating = null;\n\n\t  this.events();\n\t};\n\n\tDropdown.DEFAULTS = {\n\t  animation: 'am-animation-slide-top-fixed',\n\t  boundary: window,\n\t  justify: undefined,\n\t  selector: {\n\t    dropdown: '.am-dropdown-content',\n\t    toggle: '.am-dropdown-toggle'\n\t  },\n\t  trigger: 'click'\n\t};\n\n\tDropdown.prototype.toggle = function() {\n\t  this.clear();\n\n\t  if (this.animating) {\n\t    return;\n\t  }\n\n\t  this[this.active ? 'close' : 'open']();\n\t};\n\n\tDropdown.prototype.open = function(e) {\n\t  var $toggle = this.$toggle;\n\t  var $element = this.$element;\n\t  var $dropdown = this.$dropdown;\n\n\t  if ($toggle.is('.am-disabled, :disabled')) {\n\t    return;\n\t  }\n\n\t  if (this.active) {\n\t    return;\n\t  }\n\n\t  $element.trigger('open.dropdown.amui').addClass('am-active');\n\n\t  $toggle.trigger('focus');\n\n\t  this.checkDimensions();\n\n\t  var complete = $.proxy(function() {\n\t    $element.trigger('opened.dropdown.amui');\n\t    this.active = true;\n\t    this.animating = 0;\n\t  }, this);\n\n\t  if (animation) {\n\t    this.animating = 1;\n\t    $dropdown.addClass(this.options.animation).\n\t      on(animation.end + '.open.dropdown.amui', $.proxy(function() {\n\t        complete();\n\t        $dropdown.removeClass(this.options.animation);\n\t      }, this));\n\t  } else {\n\t    complete();\n\t  }\n\t};\n\n\tDropdown.prototype.close = function() {\n\t  if (!this.active) {\n\t    return;\n\t  }\n\n\t  // fix #165\n\t  // var animationName = this.options.animation + ' am-animation-reverse';\n\t  var animationName = 'am-dropdown-animation';\n\t  var $element = this.$element;\n\t  var $dropdown = this.$dropdown;\n\n\t  $element.trigger('close.dropdown.amui');\n\n\t  var complete = $.proxy(function complete() {\n\t    $element.\n\t      removeClass('am-active').\n\t      trigger('closed.dropdown.amui');\n\t    this.active = false;\n\t    this.animating = 0;\n\t    this.$toggle.blur();\n\t  }, this);\n\n\t  if (animation) {\n\t    $dropdown.removeClass(this.options.animation);\n\t    $dropdown.addClass(animationName);\n\t    this.animating = 1;\n\t    // animation\n\t    $dropdown.one(animation.end + '.close.dropdown.amui', function() {\n\t      $dropdown.removeClass(animationName);\n\t      complete();\n\t    });\n\t  } else {\n\t    complete();\n\t  }\n\t};\n\n\tDropdown.prototype.enable = function() {\n\t  this.$toggle.prop('disabled', false);\n\t},\n\n\tDropdown.prototype.disable = function() {\n\t  this.$toggle.prop('disabled', true);\n\t},\n\n\tDropdown.prototype.checkDimensions = function() {\n\t  if (!this.$dropdown.length) {\n\t    return;\n\t  }\n\n\t  var $dropdown = this.$dropdown;\n\t  var offset = $dropdown.offset();\n\t  var width = $dropdown.outerWidth();\n\t  var boundaryWidth = this.$boundary.width();\n\t  var boundaryOffset = $.isWindow(this.boundary) && this.$boundary.offset() ?\n\t    this.$boundary.offset().left : 0;\n\n\t  if (this.$justify) {\n\t    // jQuery.fn.width() is really...\n\t    $dropdown.css({'min-width': this.$justify.css('width')});\n\t  }\n\n\t  if ((width + (offset.left - boundaryOffset)) > boundaryWidth) {\n\t    this.$element.addClass('am-dropdown-flip');\n\t  }\n\t};\n\n\tDropdown.prototype.clear = function() {\n\t  $('[data-am-dropdown]').not(this.$element).each(function() {\n\t    var data = $(this).data('amui.dropdown');\n\t    data && data.close();\n\t  });\n\t};\n\n\tDropdown.prototype.events = function() {\n\t  var eventNS = 'dropdown.amui';\n\t  // triggers = this.options.trigger.split(' '),\n\t  var $toggle = this.$toggle;\n\n\t  $toggle.on('click.' + eventNS, $.proxy(function(e) {\n\t    e.preventDefault();\n\t    this.toggle();\n\t  }, this));\n\n\t  /*for (var i = triggers.length; i--;) {\n\t   var trigger = triggers[i];\n\n\t   if (trigger === 'click') {\n\t   $toggle.on('click.' + eventNS, $.proxy(this.toggle, this))\n\t   }\n\n\t   if (trigger === 'focus' || trigger === 'hover') {\n\t   var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focusin';\n\t   var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout';\n\n\t   this.$element.on(eventIn + '.' + eventNS, $.proxy(this.open, this))\n\t   .on(eventOut + '.' + eventNS, $.proxy(this.close, this));\n\t   }\n\t   }*/\n\n\t  $(document).on('keydown.dropdown.amui', $.proxy(function(e) {\n\t    e.keyCode === 27 && this.active && this.close();\n\t  }, this)).on('click.outer.dropdown.amui', $.proxy(function(e) {\n\t    // var $target = $(e.target);\n\n\t    if (this.active &&\n\t      (this.$element[0] === e.target || !this.$element.find(e.target).length)) {\n\t      this.close();\n\t    }\n\t  }, this));\n\t};\n\n\t// Dropdown Plugin\n\tUI.plugin('dropdown', Dropdown);\n\n\t// Init code\n\tUI.ready(function(context) {\n\t  $('[data-am-dropdown]', context).dropdown();\n\t});\n\n\t$(document).on('click.dropdown.amui.data-api', '.am-dropdown form',\n\t  function(e) {\n\t    e.stopPropagation();\n\t  });\n\n\tmodule.exports = UI.dropdown = Dropdown;\n\n\t// TODO: 1. 处理链接 focus\n\t//       2. 增加 mouseenter / mouseleave 选项\n\t//       3. 宽度适应\n\n\n/***/ },\n/* 11 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t/* WEBPACK VAR INJECTION */(function(setImmediate) {var $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\n\t// MODIFIED:\n\t// - LINE 252: add `<i></i>`\n\t// - namespace\n\t// - Init code\n\t// TODO: start after x ms when pause on actions\n\n\t/*\n\t * jQuery FlexSlider v2.6.0\n\t * Copyright 2012 WooThemes\n\t * Contributing Author: Tyler Smith\n\t */\n\n\tvar focused = true;\n\n\t// FlexSlider: Object Instance\n\t$.flexslider = function(el, options) {\n\t  var slider = $(el);\n\n\t  // making variables public\n\t  slider.vars = $.extend({}, $.flexslider.defaults, options);\n\n\t  var namespace = slider.vars.namespace,\n\t    msGesture = window.navigator && window.navigator.msPointerEnabled && window.MSGesture,\n\t    touch = (( \"ontouchstart\" in window ) || msGesture || window.DocumentTouch && document instanceof DocumentTouch) && slider.vars.touch,\n\t  // depricating this idea, as devices are being released with both of these events\n\t    eventType = \"click touchend MSPointerUp keyup\",\n\t    watchedEvent = \"\",\n\t    watchedEventClearTimer,\n\t    vertical = slider.vars.direction === \"vertical\",\n\t    reverse = slider.vars.reverse,\n\t    carousel = (slider.vars.itemWidth > 0),\n\t    fade = slider.vars.animation === \"fade\",\n\t    asNav = slider.vars.asNavFor !== \"\",\n\t    methods = {};\n\n\t  // Store a reference to the slider object\n\t  $.data(el, 'flexslider', slider);\n\n\t  // Private slider methods\n\t  methods = {\n\t    init: function() {\n\t      slider.animating = false;\n\t      // Get current slide and make sure it is a number\n\t      slider.currentSlide = parseInt((slider.vars.startAt ? slider.vars.startAt : 0), 10);\n\t      if (isNaN(slider.currentSlide)) {\n\t        slider.currentSlide = 0;\n\t      }\n\t      slider.animatingTo = slider.currentSlide;\n\t      slider.atEnd = (slider.currentSlide === 0 || slider.currentSlide === slider.last);\n\t      slider.containerSelector = slider.vars.selector.substr(0, slider.vars.selector.search(' '));\n\t      slider.slides = $(slider.vars.selector, slider);\n\t      slider.container = $(slider.containerSelector, slider);\n\t      slider.count = slider.slides.length;\n\t      // SYNC:\n\t      slider.syncExists = $(slider.vars.sync).length > 0;\n\t      // SLIDE:\n\t      if (slider.vars.animation === \"slide\") {\n\t        slider.vars.animation = \"swing\";\n\t      }\n\t      slider.prop = (vertical) ? \"top\" : \"marginLeft\";\n\t      slider.args = {};\n\t      // SLIDESHOW:\n\t      slider.manualPause = false;\n\t      slider.stopped = false;\n\t      //PAUSE WHEN INVISIBLE\n\t      slider.started = false;\n\t      slider.startTimeout = null;\n\t      // TOUCH/USECSS:\n\t      slider.transitions = !slider.vars.video && !fade && slider.vars.useCSS && (function() {\n\t        var obj = document.createElement('div'),\n\t          props = ['perspectiveProperty', 'WebkitPerspective', 'MozPerspective', 'OPerspective', 'msPerspective'];\n\t        for (var i in props) {\n\t          if (obj.style[props[i]] !== undefined) {\n\t            slider.pfx = props[i].replace('Perspective', '').toLowerCase();\n\t            slider.prop = \"-\" + slider.pfx + \"-transform\";\n\t            return true;\n\t          }\n\t        }\n\t        return false;\n\t      }());\n\t      slider.ensureAnimationEnd = '';\n\t      // CONTROLSCONTAINER:\n\t      if (slider.vars.controlsContainer !== \"\") slider.controlsContainer = $(slider.vars.controlsContainer).length > 0 && $(slider.vars.controlsContainer);\n\t      // MANUAL:\n\t      if (slider.vars.manualControls !== \"\") slider.manualControls = $(slider.vars.manualControls).length > 0 && $(slider.vars.manualControls);\n\n\t      // CUSTOM DIRECTION NAV:\n\t      if (slider.vars.customDirectionNav !== \"\") slider.customDirectionNav = $(slider.vars.customDirectionNav).length === 2 && $(slider.vars.customDirectionNav);\n\n\t      // RANDOMIZE:\n\t      if (slider.vars.randomize) {\n\t        slider.slides.sort(function() {\n\t          return (Math.round(Math.random()) - 0.5);\n\t        });\n\t        slider.container.empty().append(slider.slides);\n\t      }\n\n\t      slider.doMath();\n\n\t      // INIT\n\t      slider.setup(\"init\");\n\n\t      // CONTROLNAV:\n\t      if (slider.vars.controlNav) {\n\t        methods.controlNav.setup();\n\t      }\n\n\t      // DIRECTIONNAV:\n\t      if (slider.vars.directionNav) {\n\t        methods.directionNav.setup();\n\t      }\n\n\t      // KEYBOARD:\n\t      if (slider.vars.keyboard && ($(slider.containerSelector).length === 1 || slider.vars.multipleKeyboard)) {\n\t        $(document).bind('keyup', function(event) {\n\t          var keycode = event.keyCode;\n\t          if (!slider.animating && (keycode === 39 || keycode === 37)) {\n\t            var target = (keycode === 39) ? slider.getTarget('next') :\n\t              (keycode === 37) ? slider.getTarget('prev') : false;\n\t            slider.flexAnimate(target, slider.vars.pauseOnAction);\n\t          }\n\t        });\n\t      }\n\t      // MOUSEWHEEL:\n\t      if (slider.vars.mousewheel) {\n\t        slider.bind('mousewheel', function(event, delta, deltaX, deltaY) {\n\t          event.preventDefault();\n\t          var target = (delta < 0) ? slider.getTarget('next') : slider.getTarget('prev');\n\t          slider.flexAnimate(target, slider.vars.pauseOnAction);\n\t        });\n\t      }\n\n\t      // PAUSEPLAY\n\t      if (slider.vars.pausePlay) {\n\t        methods.pausePlay.setup();\n\t      }\n\n\t      //PAUSE WHEN INVISIBLE\n\t      if (slider.vars.slideshow && slider.vars.pauseInvisible) {\n\t        methods.pauseInvisible.init();\n\t      }\n\n\t      // SLIDSESHOW\n\t      if (slider.vars.slideshow) {\n\t        if (slider.vars.pauseOnHover) {\n\t          slider.hover(function() {\n\t            if (!slider.manualPlay && !slider.manualPause) {slider.pause();}\n\t          }, function() {\n\t            if (!slider.manualPause && !slider.manualPlay && !slider.stopped) {slider.play();}\n\t          });\n\t        }\n\t        // initialize animation\n\t        // If we're visible, or we don't use PageVisibility API\n\t        if (!slider.vars.pauseInvisible || !methods.pauseInvisible.isHidden()) {\n\t          (slider.vars.initDelay > 0) ? slider.startTimeout = setTimeout(slider.play, slider.vars.initDelay) : slider.play();\n\t        }\n\t      }\n\n\t      // ASNAV:\n\t      if (asNav) {methods.asNav.setup();}\n\n\t      // TOUCH\n\t      if (touch && slider.vars.touch) {methods.touch();}\n\n\t      // FADE&&SMOOTHHEIGHT || SLIDE:\n\t      if (!fade || (fade && slider.vars.smoothHeight)) {$(window).bind(\"resize orientationchange focus\", methods.resize);}\n\n\t      slider.find(\"img\").attr(\"draggable\", \"false\");\n\n\t      // API: start() Callback\n\t      setTimeout(function() {\n\t        slider.vars.start(slider);\n\t      }, 200);\n\t    },\n\t    asNav: {\n\t      setup: function() {\n\t        slider.asNav = true;\n\t        slider.animatingTo = Math.floor(slider.currentSlide / slider.move);\n\t        slider.currentItem = slider.currentSlide;\n\t        slider.slides.removeClass(namespace + \"active-slide\").eq(slider.currentItem).addClass(namespace + \"active-slide\");\n\t        if (!msGesture) {\n\t          slider.slides.on(eventType, function(e) {\n\t            e.preventDefault();\n\t            var $slide = $(this),\n\t              target = $slide.index();\n\t            var posFromLeft = $slide.offset().left - $(slider).scrollLeft(); // Find position of slide relative to left of slider container\n\t            if (posFromLeft <= 0 && $slide.hasClass(namespace + 'active-slide')) {\n\t              slider.flexAnimate(slider.getTarget(\"prev\"), true);\n\t            } else if (!$(slider.vars.asNavFor).data('flexslider').animating && !$slide.hasClass(namespace + \"active-slide\")) {\n\t              slider.direction = (slider.currentItem < target) ? \"next\" : \"prev\";\n\t              slider.flexAnimate(target, slider.vars.pauseOnAction, false, true, true);\n\t            }\n\t          });\n\t        } else {\n\t          el._slider = slider;\n\t          slider.slides.each(function() {\n\t            var that = this;\n\t            that._gesture = new MSGesture();\n\t            that._gesture.target = that;\n\t            that.addEventListener(\"MSPointerDown\", function(e) {\n\t              e.preventDefault();\n\t              if (e.currentTarget._gesture) {\n\t                e.currentTarget._gesture.addPointer(e.pointerId);\n\t              }\n\t            }, false);\n\t            that.addEventListener(\"MSGestureTap\", function(e) {\n\t              e.preventDefault();\n\t              var $slide = $(this),\n\t                target = $slide.index();\n\t              if (!$(slider.vars.asNavFor).data('flexslider').animating && !$slide.hasClass('active')) {\n\t                slider.direction = (slider.currentItem < target) ? \"next\" : \"prev\";\n\t                slider.flexAnimate(target, slider.vars.pauseOnAction, false, true, true);\n\t              }\n\t            });\n\t          });\n\t        }\n\t      }\n\t    },\n\t    controlNav: {\n\t      setup: function() {\n\t        if (!slider.manualControls) {\n\t          methods.controlNav.setupPaging();\n\t        } else { // MANUALCONTROLS:\n\t          methods.controlNav.setupManual();\n\t        }\n\t      },\n\t      setupPaging: function() {\n\t        var type = (slider.vars.controlNav === \"thumbnails\") ? 'control-thumbs' : 'control-paging',\n\t          j = 1,\n\t          item,\n\t          slide;\n\n\t        slider.controlNavScaffold = $('<ol class=\"' + namespace + 'control-nav ' + namespace + type + '\"></ol>');\n\n\t        if (slider.pagingCount > 1) {\n\t          for (var i = 0; i < slider.pagingCount; i++) {\n\t            slide = slider.slides.eq(i);\n\t            if (undefined === slide.attr('data-thumb-alt')) {\n\t              slide.attr('data-thumb-alt', '');\n\t            }\n\t            altText = ( '' !== slide.attr('data-thumb-alt') ) ? altText = ' alt=\"' + slide.attr('data-thumb-alt') + '\"' : '';\n\t            item = (slider.vars.controlNav === \"thumbnails\") ? '<img src=\"' + slide.attr( 'data-thumb' ) + '\"' + altText + '/>' : '<a href=\"#\">' + j + '</a>';\n\t            if ('thumbnails' === slider.vars.controlNav && true === slider.vars.thumbCaptions) {\n\t              var captn = slide.attr('data-thumbcaption');\n\t              if ('' !== captn && undefined !== captn) {item += '<span class=\"' + namespace + 'caption\">' + captn + '</span>';}\n\t            }\n\t            // slider.controlNavScaffold.append('<li>' + item + '</li>');\n\t            slider.controlNavScaffold.append('<li>' + item + '<i></i></li>');\n\t            j++;\n\t          }\n\t        }\n\n\t        // CONTROLSCONTAINER:\n\t        (slider.controlsContainer) ? $(slider.controlsContainer).append(slider.controlNavScaffold) : slider.append(slider.controlNavScaffold);\n\t        methods.controlNav.set();\n\n\t        methods.controlNav.active();\n\n\t        slider.controlNavScaffold.delegate('a, img', eventType, function(event) {\n\t          event.preventDefault();\n\n\t          if (watchedEvent === \"\" || watchedEvent === event.type) {\n\t            var $this = $(this),\n\t              target = slider.controlNav.index($this);\n\n\t            if (!$this.hasClass(namespace + 'active')) {\n\t              slider.direction = (target > slider.currentSlide) ? \"next\" : \"prev\";\n\t              slider.flexAnimate(target, slider.vars.pauseOnAction);\n\t            }\n\t          }\n\n\t          // setup flags to prevent event duplication\n\t          if (watchedEvent === \"\") {\n\t            watchedEvent = event.type;\n\t          }\n\t          methods.setToClearWatchedEvent();\n\n\t        });\n\t      },\n\t      setupManual: function() {\n\t        slider.controlNav = slider.manualControls;\n\t        methods.controlNav.active();\n\n\t        slider.controlNav.bind(eventType, function(event) {\n\t          event.preventDefault();\n\n\t          if (watchedEvent === \"\" || watchedEvent === event.type) {\n\t            var $this = $(this),\n\t              target = slider.controlNav.index($this);\n\n\t            if (!$this.hasClass(namespace + 'active')) {\n\t              (target > slider.currentSlide) ? slider.direction = \"next\" : slider.direction = \"prev\";\n\t              slider.flexAnimate(target, slider.vars.pauseOnAction);\n\t            }\n\t          }\n\n\t          // setup flags to prevent event duplication\n\t          if (watchedEvent === \"\") {\n\t            watchedEvent = event.type;\n\t          }\n\t          methods.setToClearWatchedEvent();\n\t        });\n\t      },\n\t      set: function() {\n\t        var selector = (slider.vars.controlNav === \"thumbnails\") ? 'img' : 'a';\n\t        slider.controlNav = $('.' + namespace + 'control-nav li ' + selector, (slider.controlsContainer) ? slider.controlsContainer : slider);\n\t      },\n\t      active: function() {\n\t        slider.controlNav.removeClass(namespace + \"active\").eq(slider.animatingTo).addClass(namespace + \"active\");\n\t      },\n\t      update: function(action, pos) {\n\t        if (slider.pagingCount > 1 && action === \"add\") {\n\t          slider.controlNavScaffold.append($('<li><a href=\"#\">' + slider.count + '</a></li>'));\n\t        } else if (slider.pagingCount === 1) {\n\t          slider.controlNavScaffold.find('li').remove();\n\t        } else {\n\t          slider.controlNav.eq(pos).closest('li').remove();\n\t        }\n\t        methods.controlNav.set();\n\t        (slider.pagingCount > 1 && slider.pagingCount !== slider.controlNav.length) ? slider.update(pos, action) : methods.controlNav.active();\n\t      }\n\t    },\n\t    directionNav: {\n\t      setup: function() {\n\t        var directionNavScaffold = $('<ul class=\"' + namespace + 'direction-nav\"><li class=\"' + namespace + 'nav-prev\"><a class=\"' + namespace + 'prev\" href=\"#\">' + slider.vars.prevText + '</a></li><li class=\"' + namespace + 'nav-next\"><a class=\"' + namespace + 'next\" href=\"#\">' + slider.vars.nextText + '</a></li></ul>');\n\n\t        // CUSTOM DIRECTION NAV:\n\t        if (slider.customDirectionNav) {\n\t          slider.directionNav = slider.customDirectionNav;\n\t        } else if (slider.controlsContainer) { // CONTROLSCONTAINER:\n\t          $(slider.controlsContainer).append(directionNavScaffold);\n\t          slider.directionNav = $('.' + namespace + 'direction-nav li a', slider.controlsContainer);\n\t        } else {\n\t          slider.append(directionNavScaffold);\n\t          slider.directionNav = $('.' + namespace + 'direction-nav li a', slider);\n\t        }\n\n\t        methods.directionNav.update();\n\n\t        slider.directionNav.bind(eventType, function(event) {\n\t          event.preventDefault();\n\t          var target;\n\n\t          if (watchedEvent === \"\" || watchedEvent === event.type) {\n\t            target = ($(this).hasClass(namespace + 'next')) ? slider.getTarget('next') : slider.getTarget('prev');\n\t            slider.flexAnimate(target, slider.vars.pauseOnAction);\n\t          }\n\n\t          // setup flags to prevent event duplication\n\t          if (watchedEvent === \"\") {\n\t            watchedEvent = event.type;\n\t          }\n\t          methods.setToClearWatchedEvent();\n\t        });\n\t      },\n\t      update: function() {\n\t        var disabledClass = namespace + 'disabled';\n\t        if (slider.pagingCount === 1) {\n\t          slider.directionNav.addClass(disabledClass).attr('tabindex', '-1');\n\t        } else if (!slider.vars.animationLoop) {\n\t          if (slider.animatingTo === 0) {\n\t            slider.directionNav.removeClass(disabledClass).filter('.' + namespace + \"prev\").addClass(disabledClass).attr('tabindex', '-1');\n\t          } else if (slider.animatingTo === slider.last) {\n\t            slider.directionNav.removeClass(disabledClass).filter('.' + namespace + \"next\").addClass(disabledClass).attr('tabindex', '-1');\n\t          } else {\n\t            slider.directionNav.removeClass(disabledClass).removeAttr('tabindex');\n\t          }\n\t        } else {\n\t          slider.directionNav.removeClass(disabledClass).removeAttr('tabindex');\n\t        }\n\t      }\n\t    },\n\t    pausePlay: {\n\t      setup: function() {\n\t        var pausePlayScaffold = $('<div class=\"' + namespace + 'pauseplay\"><a href=\"#\"></a></div>');\n\n\t        // CONTROLSCONTAINER:\n\t        if (slider.controlsContainer) {\n\t          slider.controlsContainer.append(pausePlayScaffold);\n\t          slider.pausePlay = $('.' + namespace + 'pauseplay a', slider.controlsContainer);\n\t        } else {\n\t          slider.append(pausePlayScaffold);\n\t          slider.pausePlay = $('.' + namespace + 'pauseplay a', slider);\n\t        }\n\n\t        methods.pausePlay.update((slider.vars.slideshow) ? namespace + 'pause' : namespace + 'play');\n\n\t        slider.pausePlay.bind(eventType, function(event) {\n\t          event.preventDefault();\n\n\t          if (watchedEvent === \"\" || watchedEvent === event.type) {\n\t            if ($(this).hasClass(namespace + 'pause')) {\n\t              slider.manualPause = true;\n\t              slider.manualPlay = false;\n\t              slider.pause();\n\t            } else {\n\t              slider.manualPause = false;\n\t              slider.manualPlay = true;\n\t              slider.play();\n\t            }\n\t          }\n\n\t          // setup flags to prevent event duplication\n\t          if (watchedEvent === \"\") {\n\t            watchedEvent = event.type;\n\t          }\n\t          methods.setToClearWatchedEvent();\n\t        });\n\t      },\n\t      update: function(state) {\n\t        (state === \"play\") ? slider.pausePlay.removeClass(namespace + 'pause').addClass(namespace + 'play').html(slider.vars.playText) : slider.pausePlay.removeClass(namespace + 'play').addClass(namespace + 'pause').html(slider.vars.pauseText);\n\t      }\n\t    },\n\t    touch: function() {\n\t      var startX,\n\t        startY,\n\t        offset,\n\t        cwidth,\n\t        dx,\n\t        startT,\n\t        onTouchStart,\n\t        onTouchMove,\n\t        onTouchEnd,\n\t        scrolling = false,\n\t        localX = 0,\n\t        localY = 0,\n\t        accDx = 0;\n\n\t      if (!msGesture) {\n\t        onTouchStart = function(e) {\n\t          if (slider.animating) {\n\t            e.preventDefault();\n\t          } else if (( window.navigator.msPointerEnabled ) || e.touches.length === 1) {\n\t            slider.pause();\n\t            // CAROUSEL:\n\t            cwidth = (vertical) ? slider.h : slider.w;\n\t            startT = Number(new Date());\n\t            // CAROUSEL:\n\n\t            // Local vars for X and Y points.\n\t            localX = e.touches[0].pageX;\n\t            localY = e.touches[0].pageY;\n\n\t            offset = (carousel && reverse && slider.animatingTo === slider.last) ? 0 :\n\t              (carousel && reverse) ? slider.limit - (((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.animatingTo) :\n\t                (carousel && slider.currentSlide === slider.last) ? slider.limit :\n\t                  (carousel) ? ((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.currentSlide :\n\t                    (reverse) ? (slider.last - slider.currentSlide + slider.cloneOffset) * cwidth : (slider.currentSlide + slider.cloneOffset) * cwidth;\n\t            startX = (vertical) ? localY : localX;\n\t            startY = (vertical) ? localX : localY;\n\n\t            el.addEventListener('touchmove', onTouchMove, false);\n\t            el.addEventListener('touchend', onTouchEnd, false);\n\t          }\n\t        };\n\n\t        onTouchMove = function(e) {\n\t          // Local vars for X and Y points.\n\n\t          localX = e.touches[0].pageX;\n\t          localY = e.touches[0].pageY;\n\n\t          dx = (vertical) ? startX - localY : startX - localX;\n\t          scrolling = (vertical) ? (Math.abs(dx) < Math.abs(localX - startY)) : (Math.abs(dx) < Math.abs(localY - startY));\n\n\t          var fxms = 500;\n\n\t          if (!scrolling || Number(new Date()) - startT > fxms) {\n\t            e.preventDefault();\n\t            if (!fade && slider.transitions) {\n\t              if (!slider.vars.animationLoop) {\n\t                dx = dx / ((slider.currentSlide === 0 && dx < 0 || slider.currentSlide === slider.last && dx > 0) ? (Math.abs(dx) / cwidth + 2) : 1);\n\t              }\n\t              slider.setProps(offset + dx, \"setTouch\");\n\t            }\n\t          }\n\t        };\n\n\t        onTouchEnd = function(e) {\n\t          // finish the touch by undoing the touch session\n\t          el.removeEventListener('touchmove', onTouchMove, false);\n\n\t          if (slider.animatingTo === slider.currentSlide && !scrolling && !(dx === null)) {\n\t            var updateDx = (reverse) ? -dx : dx,\n\t              target = (updateDx > 0) ? slider.getTarget('next') : slider.getTarget('prev');\n\n\t            if (slider.canAdvance(target) && (Number(new Date()) - startT < 550 && Math.abs(updateDx) > 50 || Math.abs(updateDx) > cwidth / 2)) {\n\t              slider.flexAnimate(target, slider.vars.pauseOnAction);\n\t            } else {\n\t              if (!fade) {slider.flexAnimate(slider.currentSlide, slider.vars.pauseOnAction, true);}\n\t            }\n\t          }\n\t          el.removeEventListener('touchend', onTouchEnd, false);\n\n\t          startX = null;\n\t          startY = null;\n\t          dx = null;\n\t          offset = null;\n\t        };\n\n\t        el.addEventListener('touchstart', onTouchStart, false);\n\t      } else {\n\t        el.style.msTouchAction = \"none\";\n\t        el._gesture = new MSGesture();\n\t        el._gesture.target = el;\n\t        el.addEventListener(\"MSPointerDown\", onMSPointerDown, false);\n\t        el._slider = slider;\n\t        el.addEventListener(\"MSGestureChange\", onMSGestureChange, false);\n\t        el.addEventListener(\"MSGestureEnd\", onMSGestureEnd, false);\n\n\t        function onMSPointerDown(e) {\n\t          e.stopPropagation();\n\t          if (slider.animating) {\n\t            e.preventDefault();\n\t          } else {\n\t            slider.pause();\n\t            el._gesture.addPointer(e.pointerId);\n\t            accDx = 0;\n\t            cwidth = (vertical) ? slider.h : slider.w;\n\t            startT = Number(new Date());\n\t            // CAROUSEL:\n\n\t            offset = (carousel && reverse && slider.animatingTo === slider.last) ? 0 :\n\t              (carousel && reverse) ? slider.limit - (((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.animatingTo) :\n\t                (carousel && slider.currentSlide === slider.last) ? slider.limit :\n\t                  (carousel) ? ((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.currentSlide :\n\t                    (reverse) ? (slider.last - slider.currentSlide + slider.cloneOffset) * cwidth : (slider.currentSlide + slider.cloneOffset) * cwidth;\n\t          }\n\t        }\n\n\t        function onMSGestureChange(e) {\n\t          e.stopPropagation();\n\t          var slider = e.target._slider;\n\t          if (!slider) {\n\t            return;\n\t          }\n\t          var transX = -e.translationX,\n\t            transY = -e.translationY;\n\n\t          //Accumulate translations.\n\t          accDx = accDx + ((vertical) ? transY : transX);\n\t          dx = accDx;\n\t          scrolling = (vertical) ? (Math.abs(accDx) < Math.abs(-transX)) : (Math.abs(accDx) < Math.abs(-transY));\n\n\t          if (e.detail === e.MSGESTURE_FLAG_INERTIA) {\n\t            setImmediate(function() {\n\t              el._gesture.stop();\n\t            });\n\n\t            return;\n\t          }\n\n\t          if (!scrolling || Number(new Date()) - startT > 500) {\n\t            e.preventDefault();\n\t            if (!fade && slider.transitions) {\n\t              if (!slider.vars.animationLoop) {\n\t                dx = accDx / ((slider.currentSlide === 0 && accDx < 0 || slider.currentSlide === slider.last && accDx > 0) ? (Math.abs(accDx) / cwidth + 2) : 1);\n\t              }\n\t              slider.setProps(offset + dx, \"setTouch\");\n\t            }\n\t          }\n\t        }\n\n\t        function onMSGestureEnd(e) {\n\t          e.stopPropagation();\n\t          var slider = e.target._slider;\n\t          if (!slider) {\n\t            return;\n\t          }\n\t          if (slider.animatingTo === slider.currentSlide && !scrolling && !(dx === null)) {\n\t            var updateDx = (reverse) ? -dx : dx,\n\t              target = (updateDx > 0) ? slider.getTarget('next') : slider.getTarget('prev');\n\n\t            if (slider.canAdvance(target) && (Number(new Date()) - startT < 550 && Math.abs(updateDx) > 50 || Math.abs(updateDx) > cwidth / 2)) {\n\t              slider.flexAnimate(target, slider.vars.pauseOnAction);\n\t            } else {\n\t              if (!fade) {slider.flexAnimate(slider.currentSlide, slider.vars.pauseOnAction, true);}\n\t            }\n\t          }\n\n\t          startX = null;\n\t          startY = null;\n\t          dx = null;\n\t          offset = null;\n\t          accDx = 0;\n\t        }\n\t      }\n\t    },\n\t    resize: function() {\n\t      if (!slider.animating && slider.is(':visible')) {\n\t        if (!carousel) {slider.doMath()};\n\n\t        if (fade) {\n\t          // SMOOTH HEIGHT:\n\t          methods.smoothHeight();\n\t        } else if (carousel) { //CAROUSEL:\n\t          slider.slides.width(slider.computedW);\n\t          slider.update(slider.pagingCount);\n\t          slider.setProps();\n\t        }\n\t        else if (vertical) { //VERTICAL:\n\t          slider.viewport.height(slider.h);\n\t          slider.setProps(slider.h, \"setTotal\");\n\t        } else {\n\t          // SMOOTH HEIGHT:\n\t          if (slider.vars.smoothHeight) {methods.smoothHeight();}\n\t          slider.newSlides.width(slider.computedW);\n\t          slider.setProps(slider.computedW, \"setTotal\");\n\t        }\n\t      }\n\t    },\n\t    smoothHeight: function(dur) {\n\t      if (!vertical || fade) {\n\t        var $obj = (fade) ? slider : slider.viewport;\n\t        (dur) ? $obj.animate({\"height\": slider.slides.eq(slider.animatingTo).height()}, dur) : $obj.height(slider.slides.eq(slider.animatingTo).height());\n\t      }\n\t    },\n\t    sync: function(action) {\n\t      var $obj = $(slider.vars.sync).data(\"flexslider\"),\n\t        target = slider.animatingTo;\n\n\t      switch (action) {\n\t        case \"animate\":\n\t          $obj.flexAnimate(target, slider.vars.pauseOnAction, false, true);\n\t          break;\n\t        case \"play\":\n\t          if (!$obj.playing && !$obj.asNav) {\n\t            $obj.play();\n\t          }\n\t          break;\n\t        case \"pause\":\n\t          $obj.pause();\n\t          break;\n\t      }\n\t    },\n\t    uniqueID: function($clone) {\n\t      // Append _clone to current level and children elements with id attributes\n\t      $clone.filter('[id]').add($clone.find('[id]')).each(function() {\n\t        var $this = $(this);\n\t        $this.attr('id', $this.attr('id') + '_clone');\n\t      });\n\t      return $clone;\n\t    },\n\t    pauseInvisible: {\n\t      visProp: null,\n\t      init: function() {\n\t        var visProp = methods.pauseInvisible.getHiddenProp();\n\t        if (visProp) {\n\t          var evtname = visProp.replace(/[H|h]idden/,'') + 'visibilitychange';\n\t          document.addEventListener(evtname, function() {\n\t            if (methods.pauseInvisible.isHidden()) {\n\t              if(slider.startTimeout) {\n\t                clearTimeout(slider.startTimeout); //If clock is ticking, stop timer and prevent from starting while invisible\n\t              } else {\n\t                slider.pause(); //Or just pause\n\t              }\n\t            }\n\t            else {\n\t              if(slider.started) {\n\t                slider.play(); //Initiated before, just play\n\t              } else {\n\t                if (slider.vars.initDelay > 0) {\n\t                  setTimeout(slider.play, slider.vars.initDelay);\n\t                } else {\n\t                  slider.play(); //Didn't init before: simply init or wait for it\n\t                }\n\t              }\n\t            }\n\t          });\n\t        }\n\t      },\n\t      isHidden: function() {\n\t        var prop = methods.pauseInvisible.getHiddenProp();\n\t        if (!prop) {\n\t          return false;\n\t        }\n\t        return document[prop];\n\t      },\n\t      getHiddenProp: function() {\n\t        var prefixes = ['webkit','moz','ms','o'];\n\t        // if 'hidden' is natively supported just return it\n\t        if ('hidden' in document) {\n\t          return 'hidden';\n\t        }\n\t        // otherwise loop over all the known prefixes until we find one\n\t        for (var i = 0; i < prefixes.length; i++ ) {\n\t          if ((prefixes[i] + 'Hidden') in document) {\n\t            return prefixes[i] + 'Hidden';\n\t          }\n\t        }\n\t        // otherwise it's not supported\n\t        return null;\n\t      }\n\t    },\n\t    setToClearWatchedEvent: function() {\n\t      clearTimeout(watchedEventClearTimer);\n\t      watchedEventClearTimer = setTimeout(function() {\n\t        watchedEvent = \"\";\n\t      }, 3000);\n\t    }\n\t  };\n\n\t  // public methods\n\t  slider.flexAnimate = function(target, pause, override, withSync, fromNav) {\n\t    if (!slider.vars.animationLoop && target !== slider.currentSlide) {\n\t      slider.direction = (target > slider.currentSlide) ? \"next\" : \"prev\";\n\t    }\n\n\t    if (asNav && slider.pagingCount === 1) slider.direction = (slider.currentItem < target) ? \"next\" : \"prev\";\n\n\t    if (!slider.animating && (slider.canAdvance(target, fromNav) || override) && slider.is(\":visible\")) {\n\t      if (asNav && withSync) {\n\t        var master = $(slider.vars.asNavFor).data('flexslider');\n\t        slider.atEnd = target === 0 || target === slider.count - 1;\n\t        master.flexAnimate(target, true, false, true, fromNav);\n\t        slider.direction = (slider.currentItem < target) ? \"next\" : \"prev\";\n\t        master.direction = slider.direction;\n\n\t        if (Math.ceil((target + 1) / slider.visible) - 1 !== slider.currentSlide && target !== 0) {\n\t          slider.currentItem = target;\n\t          slider.slides.removeClass(namespace + \"active-slide\").eq(target).addClass(namespace + \"active-slide\");\n\t          target = Math.floor(target / slider.visible);\n\t        } else {\n\t          slider.currentItem = target;\n\t          slider.slides.removeClass(namespace + \"active-slide\").eq(target).addClass(namespace + \"active-slide\");\n\t          return false;\n\t        }\n\t      }\n\n\t      slider.animating = true;\n\t      slider.animatingTo = target;\n\n\t      // SLIDESHOW:\n\t      if (pause) {slider.pause();}\n\n\t      // API: before() animation Callback\n\t      slider.vars.before(slider);\n\n\t      // SYNC:\n\t      if (slider.syncExists && !fromNav) {methods.sync(\"animate\");}\n\n\t      // CONTROLNAV\n\t      if (slider.vars.controlNav) {methods.controlNav.active();}\n\n\t      // !CAROUSEL:\n\t      // CANDIDATE: slide active class (for add/remove slide)\n\t      if (!carousel) {slider.slides.removeClass(namespace + 'active-slide').eq(target).addClass(namespace + 'active-slide');}\n\n\t      // INFINITE LOOP:\n\t      // CANDIDATE: atEnd\n\t      slider.atEnd = target === 0 || target === slider.last;\n\n\t      // DIRECTIONNAV:\n\t      if (slider.vars.directionNav) {methods.directionNav.update();}\n\n\t      if (target === slider.last) {\n\t        // API: end() of cycle Callback\n\t        slider.vars.end(slider);\n\t        // SLIDESHOW && !INFINITE LOOP:\n\t        if (!slider.vars.animationLoop) {slider.pause();}\n\t      }\n\n\t      // SLIDE:\n\t      if (!fade) {\n\t        var dimension = (vertical) ? slider.slides.filter(':first').height() : slider.computedW,\n\t          margin, slideString, calcNext;\n\n\t        // INFINITE LOOP / REVERSE:\n\t        if (carousel) {\n\t          //margin = (slider.vars.itemWidth > slider.w) ? slider.vars.itemMargin * 2 : slider.vars.itemMargin;\n\t          margin = slider.vars.itemMargin;\n\t          calcNext = ((slider.itemW + margin) * slider.move) * slider.animatingTo;\n\t          slideString = (calcNext > slider.limit && slider.visible !== 1) ? slider.limit : calcNext;\n\t        } else if (slider.currentSlide === 0 && target === slider.count - 1 && slider.vars.animationLoop && slider.direction !== \"next\") {\n\t          slideString = (reverse) ? (slider.count + slider.cloneOffset) * dimension : 0;\n\t        } else if (slider.currentSlide === slider.last && target === 0 && slider.vars.animationLoop && slider.direction !== \"prev\") {\n\t          slideString = (reverse) ? 0 : (slider.count + 1) * dimension;\n\t        } else {\n\t          slideString = (reverse) ? ((slider.count - 1) - target + slider.cloneOffset) * dimension : (target + slider.cloneOffset) * dimension;\n\t        }\n\t        slider.setProps(slideString, \"\", slider.vars.animationSpeed);\n\t        if (slider.transitions) {\n\t          if (!slider.vars.animationLoop || !slider.atEnd) {\n\t            slider.animating = false;\n\t            slider.currentSlide = slider.animatingTo;\n\t          }\n\n\t          // Unbind previous transitionEnd events and re-bind new transitionEnd event\n\t          slider.container.unbind(\"webkitTransitionEnd transitionend\");\n\t          slider.container.bind(\"webkitTransitionEnd transitionend\", function() {\n\t            clearTimeout(slider.ensureAnimationEnd);\n\t            slider.wrapup(dimension);\n\t          });\n\n\t          // Insurance for the ever-so-fickle transitionEnd event\n\t          clearTimeout(slider.ensureAnimationEnd);\n\t          slider.ensureAnimationEnd = setTimeout(function() {\n\t            slider.wrapup(dimension);\n\t          }, slider.vars.animationSpeed + 100);\n\n\t        } else {\n\t          slider.container.animate(slider.args, slider.vars.animationSpeed, slider.vars.easing, function(){\n\t            slider.wrapup(dimension);\n\t          });\n\t        }\n\t      } else { // FADE:\n\t        if (!touch) {\n\t          //slider.slides.eq(slider.currentSlide).fadeOut(slider.vars.animationSpeed, slider.vars.easing);\n\t          //slider.slides.eq(target).fadeIn(slider.vars.animationSpeed, slider.vars.easing, slider.wrapup);\n\n\t          slider.slides.eq(slider.currentSlide).css({\"zIndex\": 1}).animate({\"opacity\": 0}, slider.vars.animationSpeed, slider.vars.easing);\n\t          slider.slides.eq(target).css({\"zIndex\": 2}).animate({\"opacity\": 1}, slider.vars.animationSpeed, slider.vars.easing, slider.wrapup);\n\n\t        } else {\n\t          slider.slides.eq(slider.currentSlide).css({\n\t            \"opacity\": 0,\n\t            \"zIndex\": 1\n\t          });\n\t          slider.slides.eq(target).css({\"opacity\": 1, \"zIndex\": 2});\n\t          slider.wrapup(dimension);\n\t        }\n\t      }\n\t      // SMOOTH HEIGHT:\n\t      if (slider.vars.smoothHeight) {methods.smoothHeight(slider.vars.animationSpeed)};\n\t    }\n\t  };\n\t  slider.wrapup = function(dimension) {\n\t    // SLIDE:\n\t    if (!fade && !carousel) {\n\t      if (slider.currentSlide === 0 && slider.animatingTo === slider.last && slider.vars.animationLoop) {\n\t        slider.setProps(dimension, \"jumpEnd\");\n\t      } else if (slider.currentSlide === slider.last && slider.animatingTo === 0 && slider.vars.animationLoop) {\n\t        slider.setProps(dimension, \"jumpStart\");\n\t      }\n\t    }\n\t    slider.animating = false;\n\t    slider.currentSlide = slider.animatingTo;\n\t    // API: after() animation Callback\n\t    slider.vars.after(slider);\n\t  };\n\n\t  // SLIDESHOW:\n\t  slider.animateSlides = function() {\n\t    if (!slider.animating && focused) {slider.flexAnimate(slider.getTarget(\"next\"));}\n\t  };\n\t  // SLIDESHOW:\n\t  slider.pause = function() {\n\t    clearInterval(slider.animatedSlides);\n\t    slider.animatedSlides = null;\n\t    slider.playing = false;\n\t    // PAUSEPLAY:\n\t    if (slider.vars.pausePlay) {methods.pausePlay.update(\"play\");}\n\t    // SYNC:\n\t    if (slider.syncExists) {methods.sync(\"pause\");}\n\t  };\n\t  // SLIDESHOW:\n\t  slider.play = function() {\n\t    if (slider.playing) {clearInterval(slider.animatedSlides);}\n\t    slider.animatedSlides = slider.animatedSlides || setInterval(slider.animateSlides, slider.vars.slideshowSpeed);\n\t    slider.started = slider.playing = true;\n\t    // PAUSEPLAY:\n\t    if (slider.vars.pausePlay) {methods.pausePlay.update(\"pause\");}\n\t    // SYNC:\n\t    if (slider.syncExists) {methods.sync(\"play\");}\n\t  };\n\t  // STOP:\n\t  slider.stop = function() {\n\t    slider.pause();\n\t    slider.stopped = true;\n\t  };\n\t  slider.canAdvance = function(target, fromNav) {\n\t    // ASNAV:\n\t    var last = (asNav) ? slider.pagingCount - 1 : slider.last;\n\t    return (fromNav) ? true :\n\t      (asNav && slider.currentItem === slider.count - 1 && target === 0 && slider.direction === \"prev\") ? true :\n\t        (asNav && slider.currentItem === 0 && target === slider.pagingCount - 1 && slider.direction !== \"next\") ? false :\n\t          (target === slider.currentSlide && !asNav) ? false :\n\t            (slider.vars.animationLoop) ? true :\n\t              (slider.atEnd && slider.currentSlide === 0 && target === last && slider.direction !== \"next\") ? false :\n\t                (slider.atEnd && slider.currentSlide === last && target === 0 && slider.direction === \"next\") ? false :\n\t                  true;\n\t  };\n\t  slider.getTarget = function(dir) {\n\t    slider.direction = dir;\n\t    if (dir === \"next\") {\n\t      return (slider.currentSlide === slider.last) ? 0 : slider.currentSlide + 1;\n\t    } else {\n\t      return (slider.currentSlide === 0) ? slider.last : slider.currentSlide - 1;\n\t    }\n\t  };\n\n\t  // SLIDE:\n\t  slider.setProps = function(pos, special, dur) {\n\t    var target = (function() {\n\t      var posCheck = (pos) ? pos : ((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.animatingTo,\n\t        posCalc = (function() {\n\t          if (carousel) {\n\t            return (special === \"setTouch\") ? pos :\n\t              (reverse && slider.animatingTo === slider.last) ? 0 :\n\t                (reverse) ? slider.limit - (((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.animatingTo) :\n\t                  (slider.animatingTo === slider.last) ? slider.limit : posCheck;\n\t          } else {\n\t            switch (special) {\n\t              case \"setTotal\":\n\t                return (reverse) ? ((slider.count - 1) - slider.currentSlide + slider.cloneOffset) * pos : (slider.currentSlide + slider.cloneOffset) * pos;\n\t              case \"setTouch\":\n\t                return (reverse) ? pos : pos;\n\t              case \"jumpEnd\":\n\t                return (reverse) ? pos : slider.count * pos;\n\t              case \"jumpStart\":\n\t                return (reverse) ? slider.count * pos : pos;\n\t              default:\n\t                return pos;\n\t            }\n\t          }\n\t        }());\n\n\t      return (posCalc * -1) + \"px\";\n\t    }());\n\n\t    if (slider.transitions) {\n\t      target = (vertical) ? \"translate3d(0,\" + target + \",0)\" : \"translate3d(\" + target + \",0,0)\";\n\t      dur = (dur !== undefined) ? (dur / 1000) + \"s\" : \"0s\";\n\t      slider.container.css(\"-\" + slider.pfx + \"-transition-duration\", dur);\n\t      slider.container.css(\"transition-duration\", dur);\n\t    }\n\n\t    slider.args[slider.prop] = target;\n\t    if (slider.transitions || dur === undefined) {slider.container.css(slider.args);}\n\n\t    slider.container.css('transform', target);\n\t  };\n\n\t  slider.setup = function(type) {\n\t    // SLIDE:\n\t    if (!fade) {\n\t      var sliderOffset, arr;\n\n\t      if (type === \"init\") {\n\t        slider.viewport = $('<div class=\"' + namespace + 'viewport\"></div>').css({\n\t          \"overflow\": \"hidden\",\n\t          \"position\": \"relative\"\n\t        }).appendTo(slider).append(slider.container);\n\t        // INFINITE LOOP:\n\t        slider.cloneCount = 0;\n\t        slider.cloneOffset = 0;\n\t        // REVERSE:\n\t        if (reverse) {\n\t          arr = $.makeArray(slider.slides).reverse();\n\t          slider.slides = $(arr);\n\t          slider.container.empty().append(slider.slides);\n\t        }\n\t      }\n\t      // INFINITE LOOP && !CAROUSEL:\n\t      if (slider.vars.animationLoop && !carousel) {\n\t        slider.cloneCount = 2;\n\t        slider.cloneOffset = 1;\n\t        // clear out old clones\n\t        if (type !== \"init\") { slider.container.find('.clone').remove(); }\n\t        slider.container.append(methods.uniqueID(slider.slides.first().clone().addClass('clone')).attr('aria-hidden', 'true'))\n\t          .prepend(methods.uniqueID(slider.slides.last().clone().addClass('clone')).attr('aria-hidden', 'true'));\n\t      }\n\t      slider.newSlides = $(slider.vars.selector, slider);\n\n\t      sliderOffset = (reverse) ? slider.count - 1 - slider.currentSlide + slider.cloneOffset : slider.currentSlide + slider.cloneOffset;\n\t      // VERTICAL:\n\t      if (vertical && !carousel) {\n\t        slider.container.height((slider.count + slider.cloneCount) * 200 + \"%\").css(\"position\", \"absolute\").width(\"100%\");\n\t        setTimeout(function() {\n\t          slider.newSlides.css({\"display\": \"block\"});\n\t          slider.doMath();\n\t          slider.viewport.height(slider.h);\n\t          slider.setProps(sliderOffset * slider.h, \"init\");\n\t        }, (type === \"init\") ? 100 : 0);\n\t      } else {\n\t        slider.container.width((slider.count + slider.cloneCount) * 200 + \"%\");\n\t        slider.setProps(sliderOffset * slider.computedW, \"init\");\n\t        setTimeout(function() {\n\t          slider.doMath();\n\t          slider.newSlides.css({\"width\": slider.computedW, \"marginRight\" : slider.computedM, \"float\": \"left\", \"display\": \"block\"});\n\n\t          // SMOOTH HEIGHT:\n\t          if (slider.vars.smoothHeight) {methods.smoothHeight();}\n\t        }, (type === \"init\") ? 100 : 0);\n\t      }\n\t    } else { // FADE:\n\t      slider.slides.css({\n\t        \"width\": \"100%\",\n\t        \"float\": \"left\",\n\t        \"marginRight\": \"-100%\",\n\t        \"position\": \"relative\"\n\t      });\n\t      if (type === \"init\") {\n\t        if (!touch) {\n\t          //slider.slides.eq(slider.currentSlide).fadeIn(slider.vars.animationSpeed, slider.vars.easing);\n\t          if (slider.vars.fadeFirstSlide == false) {\n\t            slider.slides.css({ \"opacity\": 0, \"display\": \"block\", \"zIndex\": 1 }).eq(slider.currentSlide).css({\"zIndex\": 2}).css({\"opacity\": 1});\n\t          } else {\n\t            slider.slides.css({ \"opacity\": 0, \"display\": \"block\", \"zIndex\": 1 }).eq(slider.currentSlide).css({\"zIndex\": 2}).animate({\"opacity\": 1},slider.vars.animationSpeed,slider.vars.easing);\n\t          }\n\t        } else {\n\t          slider.slides.css({ \"opacity\": 0, \"display\": \"block\", \"webkitTransition\": \"opacity \" + slider.vars.animationSpeed / 1000 + \"s ease\", \"zIndex\": 1 }).eq(slider.currentSlide).css({ \"opacity\": 1, \"zIndex\": 2});\n\t        }\n\t      }\n\t      // SMOOTH HEIGHT:\n\t      if (slider.vars.smoothHeight) {methods.smoothHeight();}\n\t    }\n\t    // !CAROUSEL:\n\t    // CANDIDATE: active slide\n\t    if (!carousel) {slider.slides.removeClass(namespace + \"active-slide\").eq(slider.currentSlide).addClass(namespace + \"active-slide\");}\n\n\t    //FlexSlider: init() Callback\n\t    slider.vars.init(slider);\n\t  };\n\n\t  slider.doMath = function() {\n\t    var slide = slider.slides.first(),\n\t      slideMargin = slider.vars.itemMargin,\n\t      minItems = slider.vars.minItems,\n\t      maxItems = slider.vars.maxItems;\n\n\t    slider.w = (slider.viewport === undefined) ? slider.width() : slider.viewport.width();\n\t    slider.h = slide.height();\n\t    slider.boxPadding = slide.outerWidth() - slide.width();\n\n\t    // CAROUSEL:\n\t    if (carousel) {\n\t      slider.itemT = slider.vars.itemWidth + slideMargin;\n\t      slider.itemM = slideMargin;\n\t      slider.minW = (minItems) ? minItems * slider.itemT : slider.w;\n\t      slider.maxW = (maxItems) ? (maxItems * slider.itemT) - slideMargin : slider.w;\n\t      slider.itemW = (slider.minW > slider.w) ? (slider.w - (slideMargin * (minItems - 1))) / minItems :\n\t        (slider.maxW < slider.w) ? (slider.w - (slideMargin * (maxItems - 1))) / maxItems :\n\t          (slider.vars.itemWidth > slider.w) ? slider.w : slider.vars.itemWidth;\n\n\t      slider.visible = Math.floor(slider.w / (slider.itemW));\n\t      slider.move = (slider.vars.move > 0 && slider.vars.move < slider.visible ) ? slider.vars.move : slider.visible;\n\t      slider.pagingCount = Math.ceil(((slider.count - slider.visible) / slider.move) + 1);\n\t      slider.last = slider.pagingCount - 1;\n\t      slider.limit = (slider.pagingCount === 1) ? 0 :\n\t        (slider.vars.itemWidth > slider.w) ? (slider.itemW * (slider.count - 1)) + (slideMargin * (slider.count - 1)) : ((slider.itemW + slideMargin) * slider.count) - slider.w - slideMargin;\n\t    } else {\n\t      slider.itemW = slider.w;\n\t      slider.itemM = slideMargin;\n\t      slider.pagingCount = slider.count;\n\t      slider.last = slider.count - 1;\n\t    }\n\t    slider.computedW = slider.itemW - slider.boxPadding;\n\t    slider.computedM = slider.itemM;\n\t  };\n\n\t  slider.update = function(pos, action) {\n\t    slider.doMath();\n\n\t    // update currentSlide and slider.animatingTo if necessary\n\t    if (!carousel) {\n\t      if (pos < slider.currentSlide) {\n\t        slider.currentSlide += 1;\n\t      } else if (pos <= slider.currentSlide && pos !== 0) {\n\t        slider.currentSlide -= 1;\n\t      }\n\t      slider.animatingTo = slider.currentSlide;\n\t    }\n\n\t    // update controlNav\n\t    if (slider.vars.controlNav && !slider.manualControls) {\n\t      if ((action === \"add\" && !carousel) || slider.pagingCount > slider.controlNav.length) {\n\t        methods.controlNav.update(\"add\");\n\t      } else if ((action === \"remove\" && !carousel) || slider.pagingCount < slider.controlNav.length) {\n\t        if (carousel && slider.currentSlide > slider.last) {\n\t          slider.currentSlide -= 1;\n\t          slider.animatingTo -= 1;\n\t        }\n\t        methods.controlNav.update(\"remove\", slider.last);\n\t      }\n\t    }\n\t    // update directionNav\n\t    if (slider.vars.directionNav) {methods.directionNav.update();}\n\n\t  };\n\n\t  slider.addSlide = function(obj, pos) {\n\t    var $obj = $(obj);\n\n\t    slider.count += 1;\n\t    slider.last = slider.count - 1;\n\n\t    // append new slide\n\t    if (vertical && reverse) {\n\t      (pos !== undefined) ? slider.slides.eq(slider.count - pos).after($obj) : slider.container.prepend($obj);\n\t    } else {\n\t      (pos !== undefined) ? slider.slides.eq(pos).before($obj) : slider.container.append($obj);\n\t    }\n\n\t    // update currentSlide, animatingTo, controlNav, and directionNav\n\t    slider.update(pos, \"add\");\n\n\t    // update slider.slides\n\t    slider.slides = $(slider.vars.selector + ':not(.clone)', slider);\n\t    // re-setup the slider to accomdate new slide\n\t    slider.setup();\n\n\t    //FlexSlider: added() Callback\n\t    slider.vars.added(slider);\n\t  };\n\t  slider.removeSlide = function(obj) {\n\t    var pos = (isNaN(obj)) ? slider.slides.index($(obj)) : obj;\n\n\t    // update count\n\t    slider.count -= 1;\n\t    slider.last = slider.count - 1;\n\n\t    // remove slide\n\t    if (isNaN(obj)) {\n\t      $(obj, slider.slides).remove();\n\t    } else {\n\t      (vertical && reverse) ? slider.slides.eq(slider.last).remove() : slider.slides.eq(obj).remove();\n\t    }\n\n\t    // update currentSlide, animatingTo, controlNav, and directionNav\n\t    slider.doMath();\n\t    slider.update(pos, \"remove\");\n\n\t    // update slider.slides\n\t    slider.slides = $(slider.vars.selector + ':not(.clone)', slider);\n\t    // re-setup the slider to accomdate new slide\n\t    slider.setup();\n\n\t    // FlexSlider: removed() Callback\n\t    slider.vars.removed(slider);\n\t  };\n\n\t  //FlexSlider: Initialize\n\t  methods.init();\n\t};\n\n\t// Ensure the slider isn't focussed if the window loses focus.\n\t$(window).blur(function(e) {\n\t  focused = false;\n\t}).focus(function(e) {\n\t  focused = true;\n\t});\n\n\t// FlexSlider: Default Settings\n\t$.flexslider.defaults = {\n\t  namespace: 'am-',             // {NEW} String: Prefix string attached to the class of every element generated by the plugin\n\t  selector: '.am-slides > li',       // {NEW} Selector: Must match a simple pattern. '{container} > {slide}' -- Ignore pattern at your own peril\n\t  animation: 'slide',              // String: Select your animation type, 'fade' or 'slide'\n\t  easing: 'swing',                // {NEW} String: Determines the easing method used in jQuery transitions. jQuery easing plugin is supported!\n\t  direction: 'horizontal',        // String: Select the sliding direction, \"horizontal\" or \"vertical\"\n\t  reverse: false,                 // {NEW} Boolean: Reverse the animation direction\n\t  animationLoop: true,            // Boolean: Should the animation loop? If false, directionNav will received \"disable\" classes at either end\n\t  smoothHeight: false,            // {NEW} Boolean: Allow height of the slider to animate smoothly in horizontal mode\n\t  startAt: 0,                     // Integer: The slide that the slider should start on. Array notation (0 = first slide)\n\t  slideshow: true,                // Boolean: Animate slider automatically\n\t  slideshowSpeed: 5000,           // Integer: Set the speed of the slideshow cycling, in milliseconds\n\t  animationSpeed: 600,            // Integer: Set the speed of animations, in milliseconds\n\t  initDelay: 0,                   // {NEW} Integer: Set an initialization delay, in milliseconds\n\t  randomize: false,               // Boolean: Randomize slide order\n\t  fadeFirstSlide: true,           // Boolean: Fade in the first slide when animation type is \"fade\"\n\t  thumbCaptions: false,           // Boolean: Whether or not to put captions on thumbnails when using the \"thumbnails\" controlNav.\n\n\t  // Usability features\n\t  pauseOnAction: true,            // Boolean: Pause the slideshow when interacting with control elements, highly recommended.\n\t  pauseOnHover: false,            // Boolean: Pause the slideshow when hovering over slider, then resume when no longer hovering\n\t  pauseInvisible: true,   \t\t// {NEW} Boolean: Pause the slideshow when tab is invisible, resume when visible. Provides better UX, lower CPU usage.\n\t  useCSS: true,                   // {NEW} Boolean: Slider will use CSS3 transitions if available\n\t  touch: true,                    // {NEW} Boolean: Allow touch swipe navigation of the slider on touch-enabled devices\n\t  video: false,                   // {NEW} Boolean: If using video in the slider, will prevent CSS3 3D Transforms to avoid graphical glitches\n\n\t  // Primary Controls\n\t  controlNav: true,               // Boolean: Create navigation for paging control of each slide? Note: Leave true for manualControls usage\n\t  directionNav: true,             // Boolean: Create navigation for previous/next navigation? (true/false)\n\t  prevText: ' ',           // String: Set the text for the \"previous\" directionNav item\n\t  nextText: ' ',               // String: Set the text for the \"next\" directionNav item\n\n\t  // Secondary Navigation\n\t  keyboard: true,                 // Boolean: Allow slider navigating via keyboard left/right keys\n\t  multipleKeyboard: false,        // {NEW} Boolean: Allow keyboard navigation to affect multiple sliders. Default behavior cuts out keyboard navigation with more than one slider present.\n\t  mousewheel: false,              // {UPDATED} Boolean: Requires jquery.mousewheel.js (https://github.com/brandonaaron/jquery-mousewheel) - Allows slider navigating via mousewheel\n\t  pausePlay: false,               // Boolean: Create pause/play dynamic element\n\t  pauseText: 'Pause',             // String: Set the text for the 'pause' pausePlay item\n\t  playText: 'Play',               // String: Set the text for the 'play' pausePlay item\n\n\t  //  Special properties\n\t  controlsContainer: '',          // {UPDATED} jQuery Object/Selector: Declare which container the navigation elements should be appended too. Default container is the FlexSlider element. Example use would be $('.flexslider-container'). Property is ignored if given element is not found.\n\t  manualControls: '',             // {UPDATED} jQuery Object/Selector: Declare custom control navigation. Examples would be $(\".flex-control-nav li\") or \"#tabs-nav li img\", etc. The number of elements in your controlNav should match the number of slides/tabs.\n\t  customDirectionNav: '',         // {NEW} jQuery Object/Selector: Custom prev / next button. Must be two jQuery elements. In order to make the events work they have to have the classes \"prev\" and \"next\" (plus namespace)\n\t  sync: '',                       // {NEW} Selector: Mirror the actions performed on this slider with another slider. Use with care.\n\t  asNavFor: '',                   // {NEW} Selector: Internal property exposed for turning the slider into a thumbnail navigation for another slider\n\n\t  // Carousel Options\n\t  itemWidth: 0,                   // {NEW} Integer: Box-model width of individual carousel items, including horizontal borders and padding.\n\t  itemMargin: 0,                  // {NEW} Integer: Margin between carousel items.\n\t  minItems: 1,                    // {NEW} Integer: Minimum number of carousel items that should be visible. Items will resize fluidly when below this.\n\t  maxItems: 0,                    // {NEW} Integer: Maxmimum number of carousel items that should be visible. Items will resize fluidly when above this limit.\n\t  move: 0,                        // {NEW} Integer: Number of carousel items that should move on animation. If 0, slider will move all visible items.\n\t  allowOneSlide: true,           // {NEW} Boolean: Whether or not to allow a slider comprised of a single slide\n\n\t  // Callback API\n\t  start: function() {\n\t  },            // Callback: function(slider) - Fires when the slider loads the first slide\n\t  before: function() {\n\t  },           // Callback: function(slider) - Fires asynchronously with each slider animation\n\t  after: function() {\n\t  },            // Callback: function(slider) - Fires after each slider animation completes\n\t  end: function() {\n\t  },              // Callback: function(slider) - Fires when the slider reaches the last slide (asynchronous)\n\t  added: function() {\n\t  },            // {NEW} Callback: function(slider) - Fires after a slide is added\n\t  removed: function() {\n\t  },           // {NEW} Callback: function(slider) - Fires after a slide is removed\n\t  init: function() {\n\t  }             // {NEW} Callback: function(slider) - Fires after the slider is initially setup\n\t};\n\n\t// FlexSlider: Plugin Function\n\t$.fn.flexslider = function(options) {\n\t  var args = Array.prototype.slice.call(arguments, 1);\n\t  if (options === undefined) {options = {};}\n\n\t  if (typeof options === 'object') {\n\t    return this.each(function() {\n\t      var $this = $(this);\n\t      var selector = (options.selector) ? options.selector : '.am-slides > li';\n\t      var $slides = $this.find(selector);\n\n\t      if (($slides.length === 1 && options.allowOneSlide === true) || $slides.length === 0) {\n\t        $slides.fadeIn(400);\n\t        if (options.start) {options.start($this);}\n\t      } else if ($this.data('flexslider') === undefined) {\n\t        new $.flexslider(this, options);\n\t      }\n\t    });\n\t  } else {\n\t    // Helper strings to quickly pecdrform functions on the slider\n\t    var $slider = $(this).data('flexslider');\n\t    var methodReturn;\n\t    switch (options) {\n\t      case 'next':\n\t        $slider.flexAnimate($slider.getTarget('next'), true);\n\t        break;\n\t      case 'prev':\n\t      case 'previous':\n\t        $slider.flexAnimate($slider.getTarget('prev'), true);\n\t        break;\n\t      default:\n\t        if (typeof options === 'number') {\n\t          $slider.flexAnimate(options, true);\n\t        } else if (typeof options === 'string') {\n\t          methodReturn = (typeof $slider[options] === 'function') ?\n\t            $slider[options].apply($slider, args) : $slider[options];\n\t        }\n\t    }\n\n\t    return methodReturn === undefined ? this : methodReturn;\n\t  }\n\t};\n\n\t// Init code\n\tUI.ready(function(context) {\n\t  $('[data-am-flexslider]', context).each(function(i, item) {\n\t    var $slider = $(item);\n\t    var options = UI.utils.parseOptions($slider.data('amFlexslider'));\n\n\t    options.before = function(slider) {\n\t      if (slider._pausedTimer) {\n\t        window.clearTimeout(slider._pausedTimer);\n\t        slider._pausedTimer = null;\n\t      }\n\t    };\n\n\t    options.after = function(slider) {\n\t      var pauseTime = slider.vars.playAfterPaused;\n\t      if (pauseTime && !isNaN(pauseTime) && !slider.playing) {\n\t        if (!slider.manualPause && !slider.manualPlay && !slider.stopped) {\n\t          slider._pausedTimer = window.setTimeout(function() {\n\t            slider.play();\n\t          }, pauseTime);\n\t        }\n\t      }\n\t    };\n\n\t    $slider.flexslider(options);\n\t  });\n\t});\n\n\tmodule.exports = $.flexslider;\n\n\t/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(12).setImmediate))\n\n/***/ },\n/* 12 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t/* WEBPACK VAR INJECTION */(function(setImmediate, clearImmediate) {var nextTick = __webpack_require__(13).nextTick;\n\tvar apply = Function.prototype.apply;\n\tvar slice = Array.prototype.slice;\n\tvar immediateIds = {};\n\tvar nextImmediateId = 0;\n\n\t// DOM APIs, for completeness\n\n\texports.setTimeout = function() {\n\t  return new Timeout(apply.call(setTimeout, window, arguments), clearTimeout);\n\t};\n\texports.setInterval = function() {\n\t  return new Timeout(apply.call(setInterval, window, arguments), clearInterval);\n\t};\n\texports.clearTimeout =\n\texports.clearInterval = function(timeout) { timeout.close(); };\n\n\tfunction Timeout(id, clearFn) {\n\t  this._id = id;\n\t  this._clearFn = clearFn;\n\t}\n\tTimeout.prototype.unref = Timeout.prototype.ref = function() {};\n\tTimeout.prototype.close = function() {\n\t  this._clearFn.call(window, this._id);\n\t};\n\n\t// Does not start the time, just sets up the members needed.\n\texports.enroll = function(item, msecs) {\n\t  clearTimeout(item._idleTimeoutId);\n\t  item._idleTimeout = msecs;\n\t};\n\n\texports.unenroll = function(item) {\n\t  clearTimeout(item._idleTimeoutId);\n\t  item._idleTimeout = -1;\n\t};\n\n\texports._unrefActive = exports.active = function(item) {\n\t  clearTimeout(item._idleTimeoutId);\n\n\t  var msecs = item._idleTimeout;\n\t  if (msecs >= 0) {\n\t    item._idleTimeoutId = setTimeout(function onTimeout() {\n\t      if (item._onTimeout)\n\t        item._onTimeout();\n\t    }, msecs);\n\t  }\n\t};\n\n\t// That's not how node.js implements it but the exposed api is the same.\n\texports.setImmediate = typeof setImmediate === \"function\" ? setImmediate : function(fn) {\n\t  var id = nextImmediateId++;\n\t  var args = arguments.length < 2 ? false : slice.call(arguments, 1);\n\n\t  immediateIds[id] = true;\n\n\t  nextTick(function onNextTick() {\n\t    if (immediateIds[id]) {\n\t      // fn.call() is faster so we optimize for the common use-case\n\t      // @see http://jsperf.com/call-apply-segu\n\t      if (args) {\n\t        fn.apply(null, args);\n\t      } else {\n\t        fn.call(null);\n\t      }\n\t      // Prevent ids from leaking\n\t      exports.clearImmediate(id);\n\t    }\n\t  });\n\n\t  return id;\n\t};\n\n\texports.clearImmediate = typeof clearImmediate === \"function\" ? clearImmediate : function(id) {\n\t  delete immediateIds[id];\n\t};\n\t/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(12).setImmediate, __webpack_require__(12).clearImmediate))\n\n/***/ },\n/* 13 */\n/***/ function(module, exports) {\n\n\t// shim for using process in browser\n\n\tvar process = module.exports = {};\n\tvar queue = [];\n\tvar draining = false;\n\tvar currentQueue;\n\tvar queueIndex = -1;\n\n\tfunction cleanUpNextTick() {\n\t    draining = false;\n\t    if (currentQueue.length) {\n\t        queue = currentQueue.concat(queue);\n\t    } else {\n\t        queueIndex = -1;\n\t    }\n\t    if (queue.length) {\n\t        drainQueue();\n\t    }\n\t}\n\n\tfunction drainQueue() {\n\t    if (draining) {\n\t        return;\n\t    }\n\t    var timeout = setTimeout(cleanUpNextTick);\n\t    draining = true;\n\n\t    var len = queue.length;\n\t    while(len) {\n\t        currentQueue = queue;\n\t        queue = [];\n\t        while (++queueIndex < len) {\n\t            if (currentQueue) {\n\t                currentQueue[queueIndex].run();\n\t            }\n\t        }\n\t        queueIndex = -1;\n\t        len = queue.length;\n\t    }\n\t    currentQueue = null;\n\t    draining = false;\n\t    clearTimeout(timeout);\n\t}\n\n\tprocess.nextTick = function (fun) {\n\t    var args = new Array(arguments.length - 1);\n\t    if (arguments.length > 1) {\n\t        for (var i = 1; i < arguments.length; i++) {\n\t            args[i - 1] = arguments[i];\n\t        }\n\t    }\n\t    queue.push(new Item(fun, args));\n\t    if (queue.length === 1 && !draining) {\n\t        setTimeout(drainQueue, 0);\n\t    }\n\t};\n\n\t// v8 likes predictible objects\n\tfunction Item(fun, array) {\n\t    this.fun = fun;\n\t    this.array = array;\n\t}\n\tItem.prototype.run = function () {\n\t    this.fun.apply(null, this.array);\n\t};\n\tprocess.title = 'browser';\n\tprocess.browser = true;\n\tprocess.env = {};\n\tprocess.argv = [];\n\tprocess.version = ''; // empty string to avoid regexp issues\n\tprocess.versions = {};\n\n\tfunction noop() {}\n\n\tprocess.on = noop;\n\tprocess.addListener = noop;\n\tprocess.once = noop;\n\tprocess.off = noop;\n\tprocess.removeListener = noop;\n\tprocess.removeAllListeners = noop;\n\tprocess.emit = noop;\n\n\tprocess.binding = function (name) {\n\t    throw new Error('process.binding is not supported');\n\t};\n\n\tprocess.cwd = function () { return '/' };\n\tprocess.chdir = function (dir) {\n\t    throw new Error('process.chdir is not supported');\n\t};\n\tprocess.umask = function() { return 0; };\n\n\n/***/ },\n/* 14 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar UI = __webpack_require__(2);\n\n\t/* jshint unused: false */\n\t/* jshint -W101, -W116, -W109 */\n\n\t/*! iScroll v5.1.3\n\t * (c) 2008-2014 Matteo Spinelli\n\t * http://cubiq.org/license\n\t */\n\n\tvar rAF = window.requestAnimationFrame ||\n\t  window.webkitRequestAnimationFrame ||\n\t  window.mozRequestAnimationFrame ||\n\t  window.oRequestAnimationFrame ||\n\t  window.msRequestAnimationFrame ||\n\t  function(callback) {\n\t    window.setTimeout(callback, 1000 / 60);\n\t  };\n\n\tvar utils = (function() {\n\t  var me = {};\n\n\t  var _elementStyle = document.createElement('div').style;\n\t  var _vendor = (function() {\n\t    var vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'],\n\t      transform,\n\t      i = 0,\n\t      l = vendors.length;\n\n\t    for (; i < l; i++) {\n\t      transform = vendors[i] + 'ransform';\n\t      if (transform in _elementStyle) return vendors[i].substr(0, vendors[i].length - 1);\n\t    }\n\n\t    return false;\n\t  })();\n\n\t  function _prefixStyle(style) {\n\t    if (_vendor === false) return false;\n\t    if (_vendor === '') return style;\n\t    return _vendor + style.charAt(0).toUpperCase() + style.substr(1);\n\t  }\n\n\t  me.getTime = Date.now || function getTime() {\n\t    return new Date().getTime();\n\t  };\n\n\t  me.extend = function(target, obj) {\n\t    for (var i in obj) {\n\t      target[i] = obj[i];\n\t    }\n\t  };\n\n\t  me.addEvent = function(el, type, fn, capture) {\n\t    el.addEventListener(type, fn, !!capture);\n\t  };\n\n\t  me.removeEvent = function(el, type, fn, capture) {\n\t    el.removeEventListener(type, fn, !!capture);\n\t  };\n\n\t  me.prefixPointerEvent = function(pointerEvent) {\n\t    return window.MSPointerEvent ?\n\t    'MSPointer' + pointerEvent.charAt(9).toUpperCase() + pointerEvent.substr(10) :\n\t      pointerEvent;\n\t  };\n\n\t  me.momentum = function(current, start, time, lowerMargin, wrapperSize, deceleration) {\n\t    var distance = current - start,\n\t      speed = Math.abs(distance) / time,\n\t      destination,\n\t      duration;\n\n\t    deceleration = deceleration === undefined ? 0.0006 : deceleration;\n\n\t    destination = current + ( speed * speed ) / ( 2 * deceleration ) * ( distance < 0 ? -1 : 1 );\n\t    duration = speed / deceleration;\n\n\t    if (destination < lowerMargin) {\n\t      destination = wrapperSize ? lowerMargin - ( wrapperSize / 2.5 * ( speed / 8 ) ) : lowerMargin;\n\t      distance = Math.abs(destination - current);\n\t      duration = distance / speed;\n\t    } else if (destination > 0) {\n\t      destination = wrapperSize ? wrapperSize / 2.5 * ( speed / 8 ) : 0;\n\t      distance = Math.abs(current) + destination;\n\t      duration = distance / speed;\n\t    }\n\n\t    return {\n\t      destination: Math.round(destination),\n\t      duration: duration\n\t    };\n\t  };\n\n\t  var _transform = _prefixStyle('transform');\n\n\t  me.extend(me, {\n\t    hasTransform: _transform !== false,\n\t    hasPerspective: _prefixStyle('perspective') in _elementStyle,\n\t    hasTouch: 'ontouchstart' in window,\n\t    hasPointer: window.PointerEvent || window.MSPointerEvent, // IE10 is prefixed\n\t    hasTransition: _prefixStyle('transition') in _elementStyle\n\t  });\n\n\t  // This should find all Android browsers lower than build 535.19 (both stock browser and webview)\n\t  me.isBadAndroid = /Android /.test(window.navigator.appVersion) && !(/Chrome\\/\\d/.test(window.navigator.appVersion));\n\n\t  me.extend(me.style = {}, {\n\t    transform: _transform,\n\t    transitionTimingFunction: _prefixStyle('transitionTimingFunction'),\n\t    transitionDuration: _prefixStyle('transitionDuration'),\n\t    transitionDelay: _prefixStyle('transitionDelay'),\n\t    transformOrigin: _prefixStyle('transformOrigin')\n\t  });\n\n\t  me.hasClass = function(e, c) {\n\t    var re = new RegExp(\"(^|\\\\s)\" + c + \"(\\\\s|$)\");\n\t    return re.test(e.className);\n\t  };\n\n\t  me.addClass = function(e, c) {\n\t    if (me.hasClass(e, c)) {\n\t      return;\n\t    }\n\n\t    var newclass = e.className.split(' ');\n\t    newclass.push(c);\n\t    e.className = newclass.join(' ');\n\t  };\n\n\t  me.removeClass = function(e, c) {\n\t    if (!me.hasClass(e, c)) {\n\t      return;\n\t    }\n\n\t    var re = new RegExp(\"(^|\\\\s)\" + c + \"(\\\\s|$)\", 'g');\n\t    e.className = e.className.replace(re, ' ');\n\t  };\n\n\t  me.offset = function(el) {\n\t    var left = -el.offsetLeft,\n\t      top = -el.offsetTop;\n\n\t    // jshint -W084\n\t    while (el = el.offsetParent) {\n\t      left -= el.offsetLeft;\n\t      top -= el.offsetTop;\n\t    }\n\t    // jshint +W084\n\n\t    return {\n\t      left: left,\n\t      top: top\n\t    };\n\t  };\n\n\t  me.preventDefaultException = function(el, exceptions) {\n\t    for (var i in exceptions) {\n\t      if (exceptions[i].test(el[i])) {\n\t        return true;\n\t      }\n\t    }\n\n\t    return false;\n\t  };\n\n\t  me.extend(me.eventType = {}, {\n\t    touchstart: 1,\n\t    touchmove: 1,\n\t    touchend: 1,\n\n\t    mousedown: 2,\n\t    mousemove: 2,\n\t    mouseup: 2,\n\n\t    pointerdown: 3,\n\t    pointermove: 3,\n\t    pointerup: 3,\n\n\t    MSPointerDown: 3,\n\t    MSPointerMove: 3,\n\t    MSPointerUp: 3\n\t  });\n\n\t  me.extend(me.ease = {}, {\n\t    quadratic: {\n\t      style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',\n\t      fn: function(k) {\n\t        return k * ( 2 - k );\n\t      }\n\t    },\n\t    circular: {\n\t      style: 'cubic-bezier(0.1, 0.57, 0.1, 1)',\t// Not properly \"circular\" but this looks better, it should be (0.075, 0.82, 0.165, 1)\n\t      fn: function(k) {\n\t        return Math.sqrt(1 - ( --k * k ));\n\t      }\n\t    },\n\t    back: {\n\t      style: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)',\n\t      fn: function(k) {\n\t        var b = 4;\n\t        return ( k = k - 1 ) * k * ( ( b + 1 ) * k + b ) + 1;\n\t      }\n\t    },\n\t    bounce: {\n\t      style: '',\n\t      fn: function(k) {\n\t        if (( k /= 1 ) < ( 1 / 2.75 )) {\n\t          return 7.5625 * k * k;\n\t        } else if (k < ( 2 / 2.75 )) {\n\t          return 7.5625 * ( k -= ( 1.5 / 2.75 ) ) * k + 0.75;\n\t        } else if (k < ( 2.5 / 2.75 )) {\n\t          return 7.5625 * ( k -= ( 2.25 / 2.75 ) ) * k + 0.9375;\n\t        } else {\n\t          return 7.5625 * ( k -= ( 2.625 / 2.75 ) ) * k + 0.984375;\n\t        }\n\t      }\n\t    },\n\t    elastic: {\n\t      style: '',\n\t      fn: function(k) {\n\t        var f = 0.22,\n\t          e = 0.4;\n\n\t        if (k === 0) {\n\t          return 0;\n\t        }\n\t        if (k == 1) {\n\t          return 1;\n\t        }\n\n\t        return ( e * Math.pow(2, -10 * k) * Math.sin(( k - f / 4 ) * ( 2 * Math.PI ) / f) + 1 );\n\t      }\n\t    }\n\t  });\n\n\t  me.tap = function(e, eventName) {\n\t    var ev = document.createEvent('Event');\n\t    ev.initEvent(eventName, true, true);\n\t    ev.pageX = e.pageX;\n\t    ev.pageY = e.pageY;\n\t    e.target.dispatchEvent(ev);\n\t  };\n\n\t  me.click = function(e) {\n\t    var target = e.target,\n\t      ev;\n\n\t    if (!(/(SELECT|INPUT|TEXTAREA)/i).test(target.tagName)) {\n\t      ev = document.createEvent('MouseEvents');\n\t      ev.initMouseEvent('click', true, true, e.view, 1,\n\t        target.screenX, target.screenY, target.clientX, target.clientY,\n\t        e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,\n\t        0, null);\n\n\t      ev._constructed = true;\n\t      target.dispatchEvent(ev);\n\t    }\n\t  };\n\n\t  return me;\n\t})();\n\n\tfunction IScroll(el, options) {\n\t  this.wrapper = typeof el == 'string' ? document.querySelector(el) : el;\n\t  this.scroller = this.wrapper.children[0];\n\t  this.scrollerStyle = this.scroller.style;\t\t// cache style for better performance\n\n\t  this.options = {\n\n\t    // INSERT POINT: OPTIONS\n\n\t    startX: 0,\n\t    startY: 0,\n\t    scrollY: true,\n\t    directionLockThreshold: 5,\n\t    momentum: true,\n\n\t    bounce: true,\n\t    bounceTime: 600,\n\t    bounceEasing: '',\n\n\t    preventDefault: true,\n\t    preventDefaultException: {tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT)$/},\n\n\t    HWCompositing: true,\n\t    useTransition: true,\n\t    useTransform: true\n\t  };\n\n\t  for (var i in options) {\n\t    this.options[i] = options[i];\n\t  }\n\n\t  // Normalize options\n\t  this.translateZ = this.options.HWCompositing && utils.hasPerspective ? ' translateZ(0)' : '';\n\n\t  this.options.useTransition = utils.hasTransition && this.options.useTransition;\n\t  this.options.useTransform = utils.hasTransform && this.options.useTransform;\n\n\t  this.options.eventPassthrough = this.options.eventPassthrough === true ? 'vertical' : this.options.eventPassthrough;\n\t  this.options.preventDefault = !this.options.eventPassthrough && this.options.preventDefault;\n\n\t  // If you want eventPassthrough I have to lock one of the axes\n\t  this.options.scrollY = this.options.eventPassthrough == 'vertical' ? false : this.options.scrollY;\n\t  this.options.scrollX = this.options.eventPassthrough == 'horizontal' ? false : this.options.scrollX;\n\n\t  // With eventPassthrough we also need lockDirection mechanism\n\t  this.options.freeScroll = this.options.freeScroll && !this.options.eventPassthrough;\n\t  this.options.directionLockThreshold = this.options.eventPassthrough ? 0 : this.options.directionLockThreshold;\n\n\t  this.options.bounceEasing = typeof this.options.bounceEasing == 'string' ? utils.ease[this.options.bounceEasing] || utils.ease.circular : this.options.bounceEasing;\n\n\t  this.options.resizePolling = this.options.resizePolling === undefined ? 60 : this.options.resizePolling;\n\n\t  if (this.options.tap === true) {\n\t    this.options.tap = 'tap';\n\t  }\n\n\t  // INSERT POINT: NORMALIZATION\n\n\t  // Some defaults\n\t  this.x = 0;\n\t  this.y = 0;\n\t  this.directionX = 0;\n\t  this.directionY = 0;\n\t  this._events = {};\n\n\t  // INSERT POINT: DEFAULTS\n\n\t  this._init();\n\t  this.refresh();\n\n\t  this.scrollTo(this.options.startX, this.options.startY);\n\t  this.enable();\n\t}\n\n\tIScroll.prototype = {\n\t  version: '5.1.3',\n\n\t  _init: function() {\n\t    this._initEvents();\n\n\t    // INSERT POINT: _init\n\n\t  },\n\n\t  destroy: function() {\n\t    this._initEvents(true);\n\n\t    this._execEvent('destroy');\n\t  },\n\n\t  _transitionEnd: function(e) {\n\t    if (e.target != this.scroller || !this.isInTransition) {\n\t      return;\n\t    }\n\n\t    this._transitionTime();\n\t    if (!this.resetPosition(this.options.bounceTime)) {\n\t      this.isInTransition = false;\n\t      this._execEvent('scrollEnd');\n\t    }\n\t  },\n\n\t  _start: function(e) {\n\t    // React to left mouse button only\n\t    if (utils.eventType[e.type] != 1) {\n\t      if (e.button !== 0) {\n\t        return;\n\t      }\n\t    }\n\n\t    if (!this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated)) {\n\t      return;\n\t    }\n\n\t    if (this.options.preventDefault && !utils.isBadAndroid && !utils.preventDefaultException(e.target, this.options.preventDefaultException)) {\n\t      e.preventDefault();\n\t    }\n\n\t    var point = e.touches ? e.touches[0] : e,\n\t      pos;\n\n\t    this.initiated = utils.eventType[e.type];\n\t    this.moved = false;\n\t    this.distX = 0;\n\t    this.distY = 0;\n\t    this.directionX = 0;\n\t    this.directionY = 0;\n\t    this.directionLocked = 0;\n\n\t    this._transitionTime();\n\n\t    this.startTime = utils.getTime();\n\n\t    if (this.options.useTransition && this.isInTransition) {\n\t      this.isInTransition = false;\n\t      pos = this.getComputedPosition();\n\t      this._translate(Math.round(pos.x), Math.round(pos.y));\n\t      this._execEvent('scrollEnd');\n\t    } else if (!this.options.useTransition && this.isAnimating) {\n\t      this.isAnimating = false;\n\t      this._execEvent('scrollEnd');\n\t    }\n\n\t    this.startX = this.x;\n\t    this.startY = this.y;\n\t    this.absStartX = this.x;\n\t    this.absStartY = this.y;\n\t    this.pointX = point.pageX;\n\t    this.pointY = point.pageY;\n\n\t    this._execEvent('beforeScrollStart');\n\t  },\n\n\t  _move: function(e) {\n\t    if (!this.enabled || utils.eventType[e.type] !== this.initiated) {\n\t      return;\n\t    }\n\n\t    if (this.options.preventDefault) {\t// increases performance on Android? TODO: check!\n\t      e.preventDefault();\n\t    }\n\n\t    var point = e.touches ? e.touches[0] : e,\n\t      deltaX = point.pageX - this.pointX,\n\t      deltaY = point.pageY - this.pointY,\n\t      timestamp = utils.getTime(),\n\t      newX, newY,\n\t      absDistX, absDistY;\n\n\t    this.pointX = point.pageX;\n\t    this.pointY = point.pageY;\n\n\t    this.distX += deltaX;\n\t    this.distY += deltaY;\n\t    absDistX = Math.abs(this.distX);\n\t    absDistY = Math.abs(this.distY);\n\n\t    // We need to move at least 10 pixels for the scrolling to initiate\n\t    if (timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10)) {\n\t      return;\n\t    }\n\n\t    // If you are scrolling in one direction lock the other\n\t    if (!this.directionLocked && !this.options.freeScroll) {\n\t      if (absDistX > absDistY + this.options.directionLockThreshold) {\n\t        this.directionLocked = 'h';\t\t// lock horizontally\n\t      } else if (absDistY >= absDistX + this.options.directionLockThreshold) {\n\t        this.directionLocked = 'v';\t\t// lock vertically\n\t      } else {\n\t        this.directionLocked = 'n';\t\t// no lock\n\t      }\n\t    }\n\n\t    if (this.directionLocked == 'h') {\n\t      if (this.options.eventPassthrough == 'vertical') {\n\t        e.preventDefault();\n\t      } else if (this.options.eventPassthrough == 'horizontal') {\n\t        this.initiated = false;\n\t        return;\n\t      }\n\n\t      deltaY = 0;\n\t    } else if (this.directionLocked == 'v') {\n\t      if (this.options.eventPassthrough == 'horizontal') {\n\t        e.preventDefault();\n\t      } else if (this.options.eventPassthrough == 'vertical') {\n\t        this.initiated = false;\n\t        return;\n\t      }\n\n\t      deltaX = 0;\n\t    }\n\n\t    deltaX = this.hasHorizontalScroll ? deltaX : 0;\n\t    deltaY = this.hasVerticalScroll ? deltaY : 0;\n\n\t    newX = this.x + deltaX;\n\t    newY = this.y + deltaY;\n\n\t    // Slow down if outside of the boundaries\n\t    if (newX > 0 || newX < this.maxScrollX) {\n\t      newX = this.options.bounce ? this.x + deltaX / 3 : newX > 0 ? 0 : this.maxScrollX;\n\t    }\n\t    if (newY > 0 || newY < this.maxScrollY) {\n\t      newY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY;\n\t    }\n\n\t    this.directionX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0;\n\t    this.directionY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0;\n\n\t    if (!this.moved) {\n\t      this._execEvent('scrollStart');\n\t    }\n\n\t    this.moved = true;\n\n\t    this._translate(newX, newY);\n\n\t    /* REPLACE START: _move */\n\n\t    if (timestamp - this.startTime > 300) {\n\t      this.startTime = timestamp;\n\t      this.startX = this.x;\n\t      this.startY = this.y;\n\t    }\n\n\t    /* REPLACE END: _move */\n\n\t  },\n\n\t  _end: function(e) {\n\t    if (!this.enabled || utils.eventType[e.type] !== this.initiated) {\n\t      return;\n\t    }\n\n\t    if (this.options.preventDefault && !utils.preventDefaultException(e.target, this.options.preventDefaultException)) {\n\t      e.preventDefault();\n\t    }\n\n\t    var point = e.changedTouches ? e.changedTouches[0] : e,\n\t      momentumX,\n\t      momentumY,\n\t      duration = utils.getTime() - this.startTime,\n\t      newX = Math.round(this.x),\n\t      newY = Math.round(this.y),\n\t      distanceX = Math.abs(newX - this.startX),\n\t      distanceY = Math.abs(newY - this.startY),\n\t      time = 0,\n\t      easing = '';\n\n\t    this.isInTransition = 0;\n\t    this.initiated = 0;\n\t    this.endTime = utils.getTime();\n\n\t    // reset if we are outside of the boundaries\n\t    if (this.resetPosition(this.options.bounceTime)) {\n\t      return;\n\t    }\n\n\t    this.scrollTo(newX, newY);\t// ensures that the last position is rounded\n\n\t    // we scrolled less than 10 pixels\n\t    if (!this.moved) {\n\t      if (this.options.tap) {\n\t        utils.tap(e, this.options.tap);\n\t      }\n\n\t      if (this.options.click) {\n\t        utils.click(e);\n\t      }\n\n\t      this._execEvent('scrollCancel');\n\t      return;\n\t    }\n\n\t    if (this._events.flick && duration < 200 && distanceX < 100 && distanceY < 100) {\n\t      this._execEvent('flick');\n\t      return;\n\t    }\n\n\t    // start momentum animation if needed\n\t    if (this.options.momentum && duration < 300) {\n\t      momentumX = this.hasHorizontalScroll ? utils.momentum(this.x, this.startX, duration, this.maxScrollX, this.options.bounce ? this.wrapperWidth : 0, this.options.deceleration) : {\n\t        destination: newX,\n\t        duration: 0\n\t      };\n\t      momentumY = this.hasVerticalScroll ? utils.momentum(this.y, this.startY, duration, this.maxScrollY, this.options.bounce ? this.wrapperHeight : 0, this.options.deceleration) : {\n\t        destination: newY,\n\t        duration: 0\n\t      };\n\t      newX = momentumX.destination;\n\t      newY = momentumY.destination;\n\t      time = Math.max(momentumX.duration, momentumY.duration);\n\t      this.isInTransition = 1;\n\t    }\n\n\t    // INSERT POINT: _end\n\n\t    if (newX != this.x || newY != this.y) {\n\t      // change easing function when scroller goes out of the boundaries\n\t      if (newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY) {\n\t        easing = utils.ease.quadratic;\n\t      }\n\n\t      this.scrollTo(newX, newY, time, easing);\n\t      return;\n\t    }\n\n\t    this._execEvent('scrollEnd');\n\t  },\n\n\t  _resize: function() {\n\t    var that = this;\n\n\t    clearTimeout(this.resizeTimeout);\n\n\t    this.resizeTimeout = setTimeout(function() {\n\t      that.refresh();\n\t    }, this.options.resizePolling);\n\t  },\n\n\t  resetPosition: function(time) {\n\t    var x = this.x,\n\t      y = this.y;\n\n\t    time = time || 0;\n\n\t    if (!this.hasHorizontalScroll || this.x > 0) {\n\t      x = 0;\n\t    } else if (this.x < this.maxScrollX) {\n\t      x = this.maxScrollX;\n\t    }\n\n\t    if (!this.hasVerticalScroll || this.y > 0) {\n\t      y = 0;\n\t    } else if (this.y < this.maxScrollY) {\n\t      y = this.maxScrollY;\n\t    }\n\n\t    if (x == this.x && y == this.y) {\n\t      return false;\n\t    }\n\n\t    this.scrollTo(x, y, time, this.options.bounceEasing);\n\n\t    return true;\n\t  },\n\n\t  disable: function() {\n\t    this.enabled = false;\n\t  },\n\n\t  enable: function() {\n\t    this.enabled = true;\n\t  },\n\n\t  refresh: function() {\n\t    var rf = this.wrapper.offsetHeight;\t\t// Force reflow\n\n\t    this.wrapperWidth = this.wrapper.clientWidth;\n\t    this.wrapperHeight = this.wrapper.clientHeight;\n\n\t    /* REPLACE START: refresh */\n\n\t    this.scrollerWidth = this.scroller.offsetWidth;\n\t    this.scrollerHeight = this.scroller.offsetHeight;\n\n\t    this.maxScrollX = this.wrapperWidth - this.scrollerWidth;\n\t    this.maxScrollY = this.wrapperHeight - this.scrollerHeight;\n\n\t    /* REPLACE END: refresh */\n\n\t    this.hasHorizontalScroll = this.options.scrollX && this.maxScrollX < 0;\n\t    this.hasVerticalScroll = this.options.scrollY && this.maxScrollY < 0;\n\n\t    if (!this.hasHorizontalScroll) {\n\t      this.maxScrollX = 0;\n\t      this.scrollerWidth = this.wrapperWidth;\n\t    }\n\n\t    if (!this.hasVerticalScroll) {\n\t      this.maxScrollY = 0;\n\t      this.scrollerHeight = this.wrapperHeight;\n\t    }\n\n\t    this.endTime = 0;\n\t    this.directionX = 0;\n\t    this.directionY = 0;\n\n\t    this.wrapperOffset = utils.offset(this.wrapper);\n\n\t    this._execEvent('refresh');\n\n\t    this.resetPosition();\n\n\t    // INSERT POINT: _refresh\n\n\t  },\n\n\t  on: function(type, fn) {\n\t    if (!this._events[type]) {\n\t      this._events[type] = [];\n\t    }\n\n\t    this._events[type].push(fn);\n\t  },\n\n\t  off: function(type, fn) {\n\t    if (!this._events[type]) {\n\t      return;\n\t    }\n\n\t    var index = this._events[type].indexOf(fn);\n\n\t    if (index > -1) {\n\t      this._events[type].splice(index, 1);\n\t    }\n\t  },\n\n\t  _execEvent: function(type) {\n\t    if (!this._events[type]) {\n\t      return;\n\t    }\n\n\t    var i = 0,\n\t      l = this._events[type].length;\n\n\t    if (!l) {\n\t      return;\n\t    }\n\n\t    for (; i < l; i++) {\n\t      this._events[type][i].apply(this, [].slice.call(arguments, 1));\n\t    }\n\t  },\n\n\t  scrollBy: function(x, y, time, easing) {\n\t    x = this.x + x;\n\t    y = this.y + y;\n\t    time = time || 0;\n\n\t    this.scrollTo(x, y, time, easing);\n\t  },\n\n\t  scrollTo: function(x, y, time, easing) {\n\t    easing = easing || utils.ease.circular;\n\n\t    this.isInTransition = this.options.useTransition && time > 0;\n\n\t    if (!time || (this.options.useTransition && easing.style)) {\n\t      this._transitionTimingFunction(easing.style);\n\t      this._transitionTime(time);\n\t      this._translate(x, y);\n\t    } else {\n\t      this._animate(x, y, time, easing.fn);\n\t    }\n\t  },\n\n\t  scrollToElement: function(el, time, offsetX, offsetY, easing) {\n\t    el = el.nodeType ? el : this.scroller.querySelector(el);\n\n\t    if (!el) {\n\t      return;\n\t    }\n\n\t    var pos = utils.offset(el);\n\n\t    pos.left -= this.wrapperOffset.left;\n\t    pos.top -= this.wrapperOffset.top;\n\n\t    // if offsetX/Y are true we center the element to the screen\n\t    if (offsetX === true) {\n\t      offsetX = Math.round(el.offsetWidth / 2 - this.wrapper.offsetWidth / 2);\n\t    }\n\t    if (offsetY === true) {\n\t      offsetY = Math.round(el.offsetHeight / 2 - this.wrapper.offsetHeight / 2);\n\t    }\n\n\t    pos.left -= offsetX || 0;\n\t    pos.top -= offsetY || 0;\n\n\t    pos.left = pos.left > 0 ? 0 : pos.left < this.maxScrollX ? this.maxScrollX : pos.left;\n\t    pos.top = pos.top > 0 ? 0 : pos.top < this.maxScrollY ? this.maxScrollY : pos.top;\n\n\t    time = time === undefined || time === null || time === 'auto' ? Math.max(Math.abs(this.x - pos.left), Math.abs(this.y - pos.top)) : time;\n\n\t    this.scrollTo(pos.left, pos.top, time, easing);\n\t  },\n\n\t  _transitionTime: function(time) {\n\t    time = time || 0;\n\n\t    this.scrollerStyle[utils.style.transitionDuration] = time + 'ms';\n\n\t    if (!time && utils.isBadAndroid) {\n\t      this.scrollerStyle[utils.style.transitionDuration] = '0.001s';\n\t    }\n\n\t    // INSERT POINT: _transitionTime\n\n\t  },\n\n\t  _transitionTimingFunction: function(easing) {\n\t    this.scrollerStyle[utils.style.transitionTimingFunction] = easing;\n\n\t    // INSERT POINT: _transitionTimingFunction\n\n\t  },\n\n\t  _translate: function(x, y) {\n\t    if (this.options.useTransform) {\n\n\t      /* REPLACE START: _translate */\n\n\t      this.scrollerStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.translateZ;\n\n\t      /* REPLACE END: _translate */\n\n\t    } else {\n\t      x = Math.round(x);\n\t      y = Math.round(y);\n\t      this.scrollerStyle.left = x + 'px';\n\t      this.scrollerStyle.top = y + 'px';\n\t    }\n\n\t    this.x = x;\n\t    this.y = y;\n\n\t    // INSERT POINT: _translate\n\n\t  },\n\n\t  _initEvents: function(remove) {\n\t    var eventType = remove ? utils.removeEvent : utils.addEvent,\n\t      target = this.options.bindToWrapper ? this.wrapper : window;\n\n\t    eventType(window, 'orientationchange', this);\n\t    eventType(window, 'resize', this);\n\n\t    if (this.options.click) {\n\t      eventType(this.wrapper, 'click', this, true);\n\t    }\n\n\t    if (!this.options.disableMouse) {\n\t      eventType(this.wrapper, 'mousedown', this);\n\t      eventType(target, 'mousemove', this);\n\t      eventType(target, 'mousecancel', this);\n\t      eventType(target, 'mouseup', this);\n\t    }\n\n\t    if (utils.hasPointer && !this.options.disablePointer) {\n\t      eventType(this.wrapper, utils.prefixPointerEvent('pointerdown'), this);\n\t      eventType(target, utils.prefixPointerEvent('pointermove'), this);\n\t      eventType(target, utils.prefixPointerEvent('pointercancel'), this);\n\t      eventType(target, utils.prefixPointerEvent('pointerup'), this);\n\t    }\n\n\t    if (utils.hasTouch && !this.options.disableTouch) {\n\t      eventType(this.wrapper, 'touchstart', this);\n\t      eventType(target, 'touchmove', this);\n\t      eventType(target, 'touchcancel', this);\n\t      eventType(target, 'touchend', this);\n\t    }\n\n\t    eventType(this.scroller, 'transitionend', this);\n\t    eventType(this.scroller, 'webkitTransitionEnd', this);\n\t    eventType(this.scroller, 'oTransitionEnd', this);\n\t    eventType(this.scroller, 'MSTransitionEnd', this);\n\t  },\n\n\t  getComputedPosition: function() {\n\t    var matrix = window.getComputedStyle(this.scroller, null),\n\t      x, y;\n\n\t    if (this.options.useTransform) {\n\t      matrix = matrix[utils.style.transform].split(')')[0].split(', ');\n\t      x = +(matrix[12] || matrix[4]);\n\t      y = +(matrix[13] || matrix[5]);\n\t    } else {\n\t      x = +matrix.left.replace(/[^-\\d.]/g, '');\n\t      y = +matrix.top.replace(/[^-\\d.]/g, '');\n\t    }\n\n\t    return {x: x, y: y};\n\t  },\n\n\t  _animate: function(destX, destY, duration, easingFn) {\n\t    var that = this,\n\t      startX = this.x,\n\t      startY = this.y,\n\t      startTime = utils.getTime(),\n\t      destTime = startTime + duration;\n\n\t    function step() {\n\t      var now = utils.getTime(),\n\t        newX, newY,\n\t        easing;\n\n\t      if (now >= destTime) {\n\t        that.isAnimating = false;\n\t        that._translate(destX, destY);\n\n\t        if (!that.resetPosition(that.options.bounceTime)) {\n\t          that._execEvent('scrollEnd');\n\t        }\n\n\t        return;\n\t      }\n\n\t      now = ( now - startTime ) / duration;\n\t      easing = easingFn(now);\n\t      newX = ( destX - startX ) * easing + startX;\n\t      newY = ( destY - startY ) * easing + startY;\n\t      that._translate(newX, newY);\n\n\t      if (that.isAnimating) {\n\t        rAF(step);\n\t      }\n\t    }\n\n\t    this.isAnimating = true;\n\t    step();\n\t  },\n\t  handleEvent: function(e) {\n\t    switch (e.type) {\n\t      case 'touchstart':\n\t      case 'pointerdown':\n\t      case 'MSPointerDown':\n\t      case 'mousedown':\n\t        this._start(e);\n\t        break;\n\t      case 'touchmove':\n\t      case 'pointermove':\n\t      case 'MSPointerMove':\n\t      case 'mousemove':\n\t        this._move(e);\n\t        break;\n\t      case 'touchend':\n\t      case 'pointerup':\n\t      case 'MSPointerUp':\n\t      case 'mouseup':\n\t      case 'touchcancel':\n\t      case 'pointercancel':\n\t      case 'MSPointerCancel':\n\t      case 'mousecancel':\n\t        this._end(e);\n\t        break;\n\t      case 'orientationchange':\n\t      case 'resize':\n\t        this._resize();\n\t        break;\n\t      case 'transitionend':\n\t      case 'webkitTransitionEnd':\n\t      case 'oTransitionEnd':\n\t      case 'MSTransitionEnd':\n\t        this._transitionEnd(e);\n\t        break;\n\t      case 'wheel':\n\t      case 'DOMMouseScroll':\n\t      case 'mousewheel':\n\t        this._wheel(e);\n\t        break;\n\t      case 'keydown':\n\t        this._key(e);\n\t        break;\n\t      case 'click':\n\t        if (!e._constructed) {\n\t          e.preventDefault();\n\t          e.stopPropagation();\n\t        }\n\t        break;\n\t    }\n\t  }\n\t};\n\n\tIScroll.utils = utils;\n\n\tmodule.exports = UI.iScroll = IScroll;\n\n\t/* jshint unused: true */\n\t/* jshint +W101, +W116, +W109 */\n\n\n/***/ },\n/* 15 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\tvar dimmer = __webpack_require__(9);\n\tvar $doc = $(document);\n\tvar supportTransition = UI.support.transition;\n\n\t/**\n\t * @reference https://github.com/nolimits4web/Framework7/blob/master/src/js/modals.js\n\t * @license https://github.com/nolimits4web/Framework7/blob/master/LICENSE\n\t */\n\n\tvar Modal = function(element, options) {\n\t  this.options = $.extend({}, Modal.DEFAULTS, options || {});\n\t  this.$element = $(element);\n\t  this.$dialog =   this.$element.find('.am-modal-dialog');\n\n\t  if (!this.$element.attr('id')) {\n\t    this.$element.attr('id', UI.utils.generateGUID('am-modal'));\n\t  }\n\n\t  this.isPopup = this.$element.hasClass('am-popup');\n\t  this.isActions = this.$element.hasClass('am-modal-actions');\n\t  this.isPrompt = this.$element.hasClass('am-modal-prompt');\n\t  this.isLoading = this.$element.hasClass('am-modal-loading');\n\t  this.active = this.transitioning = this.relatedTarget = null;\n\t  this.dimmer = this.options.dimmer ? dimmer : {\n\t    open: function() {},\n\t    close: function() {}\n\t  };\n\n\t  this.events();\n\t};\n\n\tModal.DEFAULTS = {\n\t  className: {\n\t    active: 'am-modal-active',\n\t    out: 'am-modal-out'\n\t  },\n\t  selector: {\n\t    modal: '.am-modal',\n\t    active: '.am-modal-active'\n\t  },\n\t  closeViaDimmer: true,\n\t  cancelable: true,\n\t  onConfirm: function() {\n\t  },\n\t  onCancel: function() {\n\t  },\n\t  closeOnCancel: true,\n\t  closeOnConfirm: true,\n\t  dimmer: true,\n\t  height: undefined,\n\t  width: undefined,\n\t  duration: 300, // must equal the CSS transition duration\n\t  transitionEnd: supportTransition && supportTransition.end + '.modal.amui'\n\t};\n\n\tModal.prototype.toggle = function(relatedTarget) {\n\t  return this.active ? this.close() : this.open(relatedTarget);\n\t};\n\n\tModal.prototype.open = function(relatedTarget) {\n\t  var $element = this.$element;\n\t  var options = this.options;\n\t  var isPopup = this.isPopup;\n\t  var width = options.width;\n\t  var height = options.height;\n\t  var style = {};\n\n\t  if (this.active) {\n\t    return;\n\t  }\n\n\t  if (!this.$element.length) {\n\t    return;\n\t  }\n\n\t  // callback hook\n\t  relatedTarget && (this.relatedTarget = relatedTarget);\n\n\t  // 判断如果还在动画，就先触发之前的closed事件\n\t  if (this.transitioning) {\n\t    clearTimeout($element.transitionEndTimmer);\n\t    $element.transitionEndTimmer = null;\n\t    $element.trigger(options.transitionEnd)\n\t      .off(options.transitionEnd);\n\t  }\n\n\t  isPopup && this.$element.show();\n\n\t  this.active = true;\n\n\t  $element.trigger($.Event('open.modal.amui', {relatedTarget: relatedTarget}));\n\n\t  this.dimmer.open($element);\n\n\t  $element.show().redraw();\n\n\t  // apply Modal width/height if set\n\t  if (!isPopup && !this.isActions) {\n\t    if (width) {\n\t      style.width =  parseInt(width, 10) + 'px';\n\t    }\n\n\t    if (height) {\n\t      style.height = parseInt(height, 10) + 'px';\n\t    }\n\n\t    this.$dialog.css(style);\n\t  }\n\n\t  $element\n\t    .removeClass(options.className.out)\n\t    .addClass(options.className.active);\n\n\t  this.transitioning = 1;\n\n\t  var complete = function() {\n\t    $element.trigger(\n\t      $.Event('opened.modal.amui', {relatedTarget: relatedTarget})\n\t    );\n\t    this.transitioning = 0;\n\n\t    // Prompt auto focus\n\t    if (this.isPrompt) {\n\t      this.$dialog.find('input').eq(0).focus();\n\t    }\n\t  };\n\n\t  if (!supportTransition) {\n\t    return complete.call(this);\n\t  }\n\n\t  $element\n\t    .one(options.transitionEnd, $.proxy(complete, this))\n\t    .emulateTransitionEnd(options.duration);\n\t};\n\n\tModal.prototype.close = function(relatedTarget) {\n\t  if (!this.active) {\n\t    return;\n\t  }\n\n\t  var $element = this.$element;\n\t  var options = this.options;\n\t  var isPopup = this.isPopup;\n\n\t  // 判断如果还在动画，就先触发之前的opened事件\n\t  if (this.transitioning) {\n\t    clearTimeout($element.transitionEndTimmer);\n\t    $element.transitionEndTimmer = null;\n\t    $element.trigger(options.transitionEnd).off(options.transitionEnd);\n\t    this.dimmer.close($element, true);\n\t  }\n\n\t  this.$element.trigger($.Event('close.modal.amui',\n\t    {relatedTarget: relatedTarget}));\n\n\t  this.transitioning = 1;\n\n\t  var complete = function() {\n\t    $element.trigger('closed.modal.amui');\n\t    isPopup && $element.removeClass(options.className.out);\n\t    $element.hide();\n\t    this.transitioning = 0;\n\t    // 不强制关闭 Dimmer，以便多个 Modal 可以共享 Dimmer\n\t    this.dimmer.close($element, false);\n\t    this.active = false;\n\t  };\n\n\t  $element.removeClass(options.className.active).\n\t    addClass(options.className.out);\n\n\t  if (!supportTransition) {\n\t    return complete.call(this);\n\t  }\n\n\t  $element.one(options.transitionEnd, $.proxy(complete, this))\n\t    .emulateTransitionEnd(options.duration);\n\t};\n\n\tModal.prototype.events = function() {\n\t  var options = this.options;\n\t  var _this = this;\n\t  var $element = this.$element;\n\t  var $ipt = $element.find('.am-modal-prompt-input');\n\t  var $confirm = $element.find('[data-am-modal-confirm]');\n\t  var $cancel = $element.find('[data-am-modal-cancel]');\n\t  var getData = function() {\n\t    var data = [];\n\t    $ipt.each(function() {\n\t      data.push($(this).val());\n\t    });\n\n\t    return (data.length === 0) ? undefined :\n\t      ((data.length === 1) ? data[0] : data);\n\t  };\n\n\t  // close via Esc key\n\t  if (this.options.cancelable) {\n\t    $element.on('keyup.modal.amui', function(e) {\n\t        if (_this.active && e.which === 27) {\n\t          $element.trigger('cancel.modal.amui');\n\t          _this.close();\n\t        }\n\t      });\n\t  }\n\n\t  // Close Modal when dimmer clicked\n\t  if (this.options.dimmer && this.options.closeViaDimmer && !this.isLoading) {\n\t    this.dimmer.$element.on('click.dimmer.modal.amui', function(e) {\n\t      _this.close();\n\t    });\n\t  }\n\n\t  // Close Modal when button clicked\n\t  $element.on('click.close.modal.amui', '[data-am-modal-close], .am-modal-btn', function(e) {\n\t      e.preventDefault();\n\t      var $this = $(this);\n\n\t      if ($this.is($confirm)) {\n\t        options.closeOnConfirm && _this.close();\n\t      } else if ($this.is($cancel)) {\n\t        options.closeOnCancel && _this.close();\n\t      } else {\n\t        _this.close();\n\t      }\n\t    });\n\n\t  $confirm.on('click.confirm.modal.amui',\n\t    function() {\n\t      $element.trigger($.Event('confirm.modal.amui', {\n\t        trigger: this\n\t      }));\n\t    });\n\n\t  $cancel.on('click.cancel.modal.amui', function() {\n\t      $element.trigger($.Event('cancel.modal.amui', {\n\t        trigger: this\n\t      }));\n\t    });\n\n\t  $element.on('confirm.modal.amui', function(e) {\n\t    e.data = getData();\n\t    _this.options.onConfirm.call(_this, e);\n\t  }).on('cancel.modal.amui', function(e) {\n\t    e.data = getData();\n\t    _this.options.onCancel.call(_this, e);\n\t  });\n\t};\n\n\tfunction Plugin(option, relatedTarget) {\n\t  return this.each(function() {\n\t    var $this = $(this);\n\t    var data = $this.data('amui.modal');\n\t    var options = typeof option == 'object' && option;\n\n\t    if (!data) {\n\t      $this.data('amui.modal', (data = new Modal(this, options)));\n\t    }\n\n\t    if (typeof option == 'string') {\n\t      data[option] && data[option](relatedTarget);\n\t    } else {\n\t      data.toggle(option && option.relatedTarget || undefined);\n\t    }\n\t  });\n\t}\n\n\t$.fn.modal = Plugin;\n\n\t// Init\n\t$doc.on('click.modal.amui.data-api', '[data-am-modal]', function() {\n\t  var $this = $(this);\n\t  var options = UI.utils.parseOptions($this.attr('data-am-modal'));\n\t  var $target = $(options.target ||\n\t  (this.href && this.href.replace(/.*(?=#[^\\s]+$)/, '')));\n\t  var option = $target.data('amui.modal') ? 'toggle' : options;\n\n\t  Plugin.call($target, option, this);\n\t});\n\n\tmodule.exports = UI.modal = Modal;\n\n\n/***/ },\n/* 16 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\t__webpack_require__(3);\n\n\tvar $win = $(window);\n\tvar $doc = $(document);\n\tvar scrollPos;\n\n\t/**\n\t * @via https://github.com/uikit/uikit/blob/master/src/js/offcanvas.js\n\t * @license https://github.com/uikit/uikit/blob/master/LICENSE.md\n\t */\n\n\tvar OffCanvas = function(element, options) {\n\t  this.$element = $(element);\n\t  this.options = $.extend({}, OffCanvas.DEFAULTS, options);\n\t  this.active = null;\n\t  this.bindEvents();\n\t};\n\n\tOffCanvas.DEFAULTS = {\n\t  duration: 300,\n\t  effect: 'overlay' // {push|overlay}, push is too expensive\n\t};\n\n\tOffCanvas.prototype.open = function(relatedElement) {\n\t  var _this = this;\n\t  var $element = this.$element;\n\n\t  if (!$element.length || $element.hasClass('am-active')) {\n\t    return;\n\t  }\n\n\t  var effect = this.options.effect;\n\t  var $html = $('html');\n\t  var $body = $('body');\n\t  var $bar = $element.find('.am-offcanvas-bar').first();\n\t  var dir = $bar.hasClass('am-offcanvas-bar-flip') ? -1 : 1;\n\n\t  $bar.addClass('am-offcanvas-bar-' + effect);\n\n\t  scrollPos = {x: window.scrollX, y: window.scrollY};\n\n\t  $element.addClass('am-active');\n\n\t  $body.css({\n\t    width: window.innerWidth,\n\t    height: $win.height()\n\t  }).addClass('am-offcanvas-page');\n\n\t  if (effect !== 'overlay') {\n\t    $body.css({\n\t      'margin-left': $bar.outerWidth() * dir\n\t    }).width(); // force redraw\n\t  }\n\n\t  $html.css('margin-top', scrollPos.y * -1);\n\n\t  setTimeout(function() {\n\t    $bar.addClass('am-offcanvas-bar-active').width();\n\t  }, 0);\n\n\t  $element.trigger('open.offcanvas.amui');\n\n\t  this.active = 1;\n\n\t  // Close OffCanvas when none content area clicked\n\t  $element.on('click.offcanvas.amui', function(e) {\n\t    var $target = $(e.target);\n\n\t    if ($target.hasClass('am-offcanvas-bar')) {\n\t      return;\n\t    }\n\n\t    if ($target.parents('.am-offcanvas-bar').first().length) {\n\t      return;\n\t    }\n\n\t    // https://developer.mozilla.org/zh-CN/docs/DOM/event.stopImmediatePropagation\n\t    e.stopImmediatePropagation();\n\n\t    _this.close();\n\t  });\n\n\t  $html.on('keydown.offcanvas.amui', function(e) {\n\t    (e.keyCode === 27) && _this.close();\n\t  });\n\t};\n\n\tOffCanvas.prototype.close = function(relatedElement) {\n\t  var _this = this;\n\t  var $html = $('html');\n\t  var $body = $('body');\n\t  var $element = this.$element;\n\t  var $bar = $element.find('.am-offcanvas-bar').first();\n\n\t  if (!$element.length || !this.active || !$element.hasClass('am-active')) {\n\t    return;\n\t  }\n\n\t  $element.trigger('close.offcanvas.amui');\n\n\t  function complete() {\n\t    $body\n\t      .removeClass('am-offcanvas-page')\n\t      .css({\n\t        width: '',\n\t        height: '',\n\t        'margin-left': '',\n\t        'margin-right': ''\n\t      });\n\t    $element.removeClass('am-active');\n\t    $bar.removeClass('am-offcanvas-bar-active');\n\t    $html.css('margin-top', '');\n\t    window.scrollTo(scrollPos.x, scrollPos.y);\n\t    $element.trigger('closed.offcanvas.amui');\n\t    _this.active = 0;\n\t  }\n\n\t  if (UI.support.transition) {\n\t    setTimeout(function() {\n\t      $bar.removeClass('am-offcanvas-bar-active');\n\t    }, 0);\n\n\t    $body.css('margin-left', '').one(UI.support.transition.end, function() {\n\t      complete();\n\t    }).emulateTransitionEnd(this.options.duration);\n\t  } else {\n\t    complete();\n\t  }\n\n\t  $element.off('click.offcanvas.amui');\n\t  $html.off('.offcanvas.amui');\n\t};\n\n\tOffCanvas.prototype.bindEvents = function() {\n\t  var _this = this;\n\t  $doc.on('click.offcanvas.amui', '[data-am-dismiss=\"offcanvas\"]', function(e) {\n\t      e.preventDefault();\n\t      _this.close();\n\t    });\n\n\t  $win.on('resize.offcanvas.amui orientationchange.offcanvas.amui',\n\t    function() {\n\t      _this.active && _this.close();\n\t    });\n\n\t  this.$element.hammer().on('swipeleft swipeleft', function(e) {\n\t    e.preventDefault();\n\t    _this.close();\n\t  });\n\n\t  return this;\n\t};\n\n\tfunction Plugin(option, relatedElement) {\n\t  var args = Array.prototype.slice.call(arguments, 1);\n\n\t  return this.each(function() {\n\t    var $this = $(this);\n\t    var data = $this.data('amui.offcanvas');\n\t    var options = $.extend({}, typeof option == 'object' && option);\n\n\t    if (!data) {\n\t      $this.data('amui.offcanvas', (data = new OffCanvas(this, options)));\n\t      (!option || typeof option == 'object') && data.open(relatedElement);\n\t    }\n\n\t    if (typeof option == 'string') {\n\t      data[option] && data[option].apply(data, args);\n\t    }\n\t  });\n\t}\n\n\t$.fn.offCanvas = Plugin;\n\n\t// Init code\n\t$doc.on('click.offcanvas.amui', '[data-am-offcanvas]', function(e) {\n\t  e.preventDefault();\n\t  var $this = $(this);\n\t  var options = UI.utils.parseOptions($this.data('amOffcanvas'));\n\t  var $target = $(options.target ||\n\t  (this.href && this.href.replace(/.*(?=#[^\\s]+$)/, '')));\n\t  var option = $target.data('amui.offcanvas') ? 'open' : options;\n\n\t  Plugin.call($target, option, this);\n\t});\n\n\tmodule.exports = UI.offcanvas = OffCanvas;\n\n\t// TODO: 优化动画效果\n\t// http://dbushell.github.io/Responsive-Off-Canvas-Menu/step4.html\n\n\n/***/ },\n/* 17 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\n\t/**\n\t * @via https://github.com/manuelstofer/pinchzoom/blob/master/src/pinchzoom.js\n\t * @license the MIT License.\n\t */\n\n\tvar definePinchZoom = function($) {\n\t  /**\n\t   * Pinch zoom using jQuery\n\t   * @version 0.0.2\n\t   * @author Manuel Stofer <mst@rtp.ch>\n\t   * @param el\n\t   * @param options\n\t   * @constructor\n\t   */\n\t  var PinchZoom = function(el, options) {\n\t      this.el = $(el);\n\t      this.zoomFactor = 1;\n\t      this.lastScale = 1;\n\t      this.offset = {\n\t        x: 0,\n\t        y: 0\n\t      };\n\t      this.options = $.extend({}, this.defaults, options);\n\t      this.setupMarkup();\n\t      this.bindEvents();\n\t      this.update();\n\t      // default enable.\n\t      this.enable();\n\n\t    },\n\t    sum = function(a, b) {\n\t      return a + b;\n\t    },\n\t    isCloseTo = function(value, expected) {\n\t      return value > expected - 0.01 && value < expected + 0.01;\n\t    };\n\n\t  PinchZoom.prototype = {\n\n\t    defaults: {\n\t      tapZoomFactor: 2,\n\t      zoomOutFactor: 1.3,\n\t      animationDuration: 300,\n\t      animationInterval: 5,\n\t      maxZoom: 5,\n\t      minZoom: 0.5,\n\t      lockDragAxis: false,\n\t      use2d: false,\n\t      zoomStartEventName: 'pz_zoomstart',\n\t      zoomEndEventName: 'pz_zoomend',\n\t      dragStartEventName: 'pz_dragstart',\n\t      dragEndEventName: 'pz_dragend',\n\t      doubleTapEventName: 'pz_doubletap'\n\t    },\n\n\t    /**\n\t     * Event handler for 'dragstart'\n\t     * @param event\n\t     */\n\t    handleDragStart: function(event) {\n\t      this.el.trigger(this.options.dragStartEventName);\n\t      this.stopAnimation();\n\t      this.lastDragPosition = false;\n\t      this.hasInteraction = true;\n\t      this.handleDrag(event);\n\t    },\n\n\t    /**\n\t     * Event handler for 'drag'\n\t     * @param event\n\t     */\n\t    handleDrag: function(event) {\n\n\t      if (this.zoomFactor > 1.0) {\n\t        var touch = this.getTouches(event)[0];\n\t        this.drag(touch, this.lastDragPosition);\n\t        this.offset = this.sanitizeOffset(this.offset);\n\t        this.lastDragPosition = touch;\n\t      }\n\t    },\n\n\t    handleDragEnd: function() {\n\t      this.el.trigger(this.options.dragEndEventName);\n\t      this.end();\n\t    },\n\n\t    /**\n\t     * Event handler for 'zoomstart'\n\t     * @param event\n\t     */\n\t    handleZoomStart: function(event) {\n\t      this.el.trigger(this.options.zoomStartEventName);\n\t      this.stopAnimation();\n\t      this.lastScale = 1;\n\t      this.nthZoom = 0;\n\t      this.lastZoomCenter = false;\n\t      this.hasInteraction = true;\n\t    },\n\n\t    /**\n\t     * Event handler for 'zoom'\n\t     * @param event\n\t     */\n\t    handleZoom: function(event, newScale) {\n\n\t      // a relative scale factor is used\n\t      var touchCenter = this.getTouchCenter(this.getTouches(event)),\n\t        scale = newScale / this.lastScale;\n\t      this.lastScale = newScale;\n\n\t      // the first touch events are thrown away since they are not precise\n\t      this.nthZoom += 1;\n\t      if (this.nthZoom > 3) {\n\n\t        this.scale(scale, touchCenter);\n\t        this.drag(touchCenter, this.lastZoomCenter);\n\t      }\n\t      this.lastZoomCenter = touchCenter;\n\t    },\n\n\t    handleZoomEnd: function() {\n\t      this.el.trigger(this.options.zoomEndEventName);\n\t      this.end();\n\t    },\n\n\t    /**\n\t     * Event handler for 'doubletap'\n\t     * @param event\n\t     */\n\t    handleDoubleTap: function(event) {\n\t      var center = this.getTouches(event)[0],\n\t        zoomFactor = this.zoomFactor > 1 ? 1 : this.options.tapZoomFactor,\n\t        startZoomFactor = this.zoomFactor,\n\t        updateProgress = (function(progress) {\n\t          this.scaleTo(startZoomFactor + progress * (zoomFactor - startZoomFactor), center);\n\t        }).bind(this);\n\n\t      if (this.hasInteraction) {\n\t        return;\n\t      }\n\t      if (startZoomFactor > zoomFactor) {\n\t        center = this.getCurrentZoomCenter();\n\t      }\n\n\t      this.animate(this.options.animationDuration, this.options.animationInterval, updateProgress, this.swing);\n\t      this.el.trigger(this.options.doubleTapEventName);\n\t    },\n\n\t    /**\n\t     * Max / min values for the offset\n\t     * @param offset\n\t     * @return {Object} the sanitized offset\n\t     */\n\t    sanitizeOffset: function(offset) {\n\t      var maxX = (this.zoomFactor - 1) * this.getContainerX(),\n\t        maxY = (this.zoomFactor - 1) * this.getContainerY(),\n\t        maxOffsetX = Math.max(maxX, 0),\n\t        maxOffsetY = Math.max(maxY, 0),\n\t        minOffsetX = Math.min(maxX, 0),\n\t        minOffsetY = Math.min(maxY, 0);\n\n\t      return {\n\t        x: Math.min(Math.max(offset.x, minOffsetX), maxOffsetX),\n\t        y: Math.min(Math.max(offset.y, minOffsetY), maxOffsetY)\n\t      };\n\t    },\n\n\t    /**\n\t     * Scale to a specific zoom factor (not relative)\n\t     * @param zoomFactor\n\t     * @param center\n\t     */\n\t    scaleTo: function(zoomFactor, center) {\n\t      this.scale(zoomFactor / this.zoomFactor, center);\n\t    },\n\n\t    /**\n\t     * Scales the element from specified center\n\t     * @param scale\n\t     * @param center\n\t     */\n\t    scale: function(scale, center) {\n\t      scale = this.scaleZoomFactor(scale);\n\t      this.addOffset({\n\t        x: (scale - 1) * (center.x + this.offset.x),\n\t        y: (scale - 1) * (center.y + this.offset.y)\n\t      });\n\t    },\n\n\t    /**\n\t     * Scales the zoom factor relative to current state\n\t     * @param scale\n\t     * @return the actual scale (can differ because of max min zoom factor)\n\t     */\n\t    scaleZoomFactor: function(scale) {\n\t      var originalZoomFactor = this.zoomFactor;\n\t      this.zoomFactor *= scale;\n\t      this.zoomFactor = Math.min(this.options.maxZoom, Math.max(this.zoomFactor, this.options.minZoom));\n\t      return this.zoomFactor / originalZoomFactor;\n\t    },\n\n\t    /**\n\t     * Drags the element\n\t     * @param center\n\t     * @param lastCenter\n\t     */\n\t    drag: function(center, lastCenter) {\n\t      if (lastCenter) {\n\t        if (this.options.lockDragAxis) {\n\t          // lock scroll to position that was changed the most\n\t          if (Math.abs(center.x - lastCenter.x) > Math.abs(center.y - lastCenter.y)) {\n\t            this.addOffset({\n\t              x: -(center.x - lastCenter.x),\n\t              y: 0\n\t            });\n\t          }\n\t          else {\n\t            this.addOffset({\n\t              y: -(center.y - lastCenter.y),\n\t              x: 0\n\t            });\n\t          }\n\t        }\n\t        else {\n\t          this.addOffset({\n\t            y: -(center.y - lastCenter.y),\n\t            x: -(center.x - lastCenter.x)\n\t          });\n\t        }\n\t      }\n\t    },\n\n\t    /**\n\t     * Calculates the touch center of multiple touches\n\t     * @param touches\n\t     * @return {Object}\n\t     */\n\t    getTouchCenter: function(touches) {\n\t      return this.getVectorAvg(touches);\n\t    },\n\n\t    /**\n\t     * Calculates the average of multiple vectors (x, y values)\n\t     */\n\t    getVectorAvg: function(vectors) {\n\t      return {\n\t        x: vectors.map(function(v) {\n\t          return v.x;\n\t        }).reduce(sum) / vectors.length,\n\t        y: vectors.map(function(v) {\n\t          return v.y;\n\t        }).reduce(sum) / vectors.length\n\t      };\n\t    },\n\n\t    /**\n\t     * Adds an offset\n\t     * @param offset the offset to add\n\t     * @return return true when the offset change was accepted\n\t     */\n\t    addOffset: function(offset) {\n\t      this.offset = {\n\t        x: this.offset.x + offset.x,\n\t        y: this.offset.y + offset.y\n\t      };\n\t    },\n\n\t    sanitize: function() {\n\t      if (this.zoomFactor < this.options.zoomOutFactor) {\n\t        this.zoomOutAnimation();\n\t      } else if (this.isInsaneOffset(this.offset)) {\n\t        this.sanitizeOffsetAnimation();\n\t      }\n\t    },\n\n\t    /**\n\t     * Checks if the offset is ok with the current zoom factor\n\t     * @param offset\n\t     * @return {Boolean}\n\t     */\n\t    isInsaneOffset: function(offset) {\n\t      var sanitizedOffset = this.sanitizeOffset(offset);\n\t      return sanitizedOffset.x !== offset.x ||\n\t        sanitizedOffset.y !== offset.y;\n\t    },\n\n\t    /**\n\t     * Creates an animation moving to a sane offset\n\t     */\n\t    sanitizeOffsetAnimation: function() {\n\t      var targetOffset = this.sanitizeOffset(this.offset),\n\t        startOffset = {\n\t          x: this.offset.x,\n\t          y: this.offset.y\n\t        },\n\t        updateProgress = (function(progress) {\n\t          this.offset.x = startOffset.x + progress * (targetOffset.x - startOffset.x);\n\t          this.offset.y = startOffset.y + progress * (targetOffset.y - startOffset.y);\n\t          this.update();\n\t        }).bind(this);\n\n\t      this.animate(\n\t        this.options.animationDuration,\n\t        this.options.animationInterval,\n\t        updateProgress,\n\t        this.swing\n\t      );\n\t    },\n\n\t    /**\n\t     * Zooms back to the original position,\n\t     * (no offset and zoom factor 1)\n\t     */\n\t    zoomOutAnimation: function() {\n\t      var startZoomFactor = this.zoomFactor,\n\t        zoomFactor = 1,\n\t        center = this.getCurrentZoomCenter(),\n\t        updateProgress = (function(progress) {\n\t          this.scaleTo(startZoomFactor + progress * (zoomFactor - startZoomFactor), center);\n\t        }).bind(this);\n\n\t      this.animate(\n\t        this.options.animationDuration,\n\t        this.options.animationInterval,\n\t        updateProgress,\n\t        this.swing\n\t      );\n\t    },\n\n\t    /**\n\t     * Updates the aspect ratio\n\t     */\n\t    updateAspectRatio: function() {\n\t      // this.setContainerY(this.getContainerX() / this.getAspectRatio());\n\t      // @modified\n\t      this.setContainerY()\n\t    },\n\n\t    /**\n\t     * Calculates the initial zoom factor (for the element to fit into the container)\n\t     * @return the initial zoom factor\n\t     */\n\t    getInitialZoomFactor: function() {\n\t      // use .offsetWidth instead of width()\n\t      // because jQuery-width() return the original width but Zepto-width() will calculate width with transform.\n\t      // the same as .height()\n\t      return this.container[0].offsetWidth / this.el[0].offsetWidth;\n\t    },\n\n\t    /**\n\t     * Calculates the aspect ratio of the element\n\t     * @return the aspect ratio\n\t     */\n\t    getAspectRatio: function() {\n\t      return this.el[0].offsetWidth / this.el[0].offsetHeight;\n\t    },\n\n\t    /**\n\t     * Calculates the virtual zoom center for the current offset and zoom factor\n\t     * (used for reverse zoom)\n\t     * @return {Object} the current zoom center\n\t     */\n\t    getCurrentZoomCenter: function() {\n\n\t      // uses following formula to calculate the zoom center x value\n\t      // offset_left / offset_right = zoomcenter_x / (container_x - zoomcenter_x)\n\t      var length = this.container[0].offsetWidth * this.zoomFactor,\n\t        offsetLeft = this.offset.x,\n\t        offsetRight = length - offsetLeft - this.container[0].offsetWidth,\n\t        widthOffsetRatio = offsetLeft / offsetRight,\n\t        centerX = widthOffsetRatio * this.container[0].offsetWidth / (widthOffsetRatio + 1),\n\n\t      // the same for the zoomcenter y\n\t        height = this.container[0].offsetHeight * this.zoomFactor,\n\t        offsetTop = this.offset.y,\n\t        offsetBottom = height - offsetTop - this.container[0].offsetHeight,\n\t        heightOffsetRatio = offsetTop / offsetBottom,\n\t        centerY = heightOffsetRatio * this.container[0].offsetHeight / (heightOffsetRatio + 1);\n\n\t      // prevents division by zero\n\t      if (offsetRight === 0) {\n\t        centerX = this.container[0].offsetWidth;\n\t      }\n\t      if (offsetBottom === 0) {\n\t        centerY = this.container[0].offsetHeight;\n\t      }\n\n\t      return {\n\t        x: centerX,\n\t        y: centerY\n\t      };\n\t    },\n\n\t    canDrag: function() {\n\t      return !isCloseTo(this.zoomFactor, 1);\n\t    },\n\n\t    /**\n\t     * Returns the touches of an event relative to the container offset\n\t     * @param event\n\t     * @return array touches\n\t     */\n\t    getTouches: function(event) {\n\t      var position = this.container.offset();\n\t      return Array.prototype.slice.call(event.touches).map(function(touch) {\n\t        return {\n\t          x: touch.pageX - position.left,\n\t          y: touch.pageY - position.top\n\t        };\n\t      });\n\t    },\n\n\t    /**\n\t     * Animation loop\n\t     * does not support simultaneous animations\n\t     * @param duration\n\t     * @param interval\n\t     * @param framefn\n\t     * @param timefn\n\t     * @param callback\n\t     */\n\t    animate: function(duration, interval, framefn, timefn, callback) {\n\t      var startTime = new Date().getTime(),\n\t        renderFrame = (function() {\n\t          if (!this.inAnimation) {\n\t            return;\n\t          }\n\t          var frameTime = new Date().getTime() - startTime,\n\t            progress = frameTime / duration;\n\t          if (frameTime >= duration) {\n\t            framefn(1);\n\t            if (callback) {\n\t              callback();\n\t            }\n\t            this.update();\n\t            this.stopAnimation();\n\t            this.update();\n\t          } else {\n\t            if (timefn) {\n\t              progress = timefn(progress);\n\t            }\n\t            framefn(progress);\n\t            this.update();\n\t            setTimeout(renderFrame, interval);\n\t          }\n\t        }).bind(this);\n\t      this.inAnimation = true;\n\t      renderFrame();\n\t    },\n\n\t    /**\n\t     * Stops the animation\n\t     */\n\t    stopAnimation: function() {\n\t      this.inAnimation = false;\n\t    },\n\n\t    /**\n\t     * Swing timing function for animations\n\t     * @param p\n\t     * @return {Number}\n\t     */\n\t    swing: function(p) {\n\t      return -Math.cos(p * Math.PI) / 2 + 0.5;\n\t    },\n\n\t    getContainerX: function() {\n\t      // return this.container[0].offsetWidth;\n\t      // @modified\n\t      return window.innerWidth\n\t    },\n\n\t    getContainerY: function() {\n\t      // return this.container[0].offsetHeight;\n\t      // @modified\n\t      return window.innerHeight\n\t    },\n\n\t    setContainerY: function(y) {\n\t      // return this.container.height(y);\n\t      // @modified\n\t      var t = window.innerHeight;\n\t      return this.el.css({height: t}), this.container.height(t);\n\t    },\n\n\t    /**\n\t     * Creates the expected html structure\n\t     */\n\t    setupMarkup: function() {\n\t      this.container = $('<div class=\"pinch-zoom-container\"></div>');\n\t      this.el.before(this.container);\n\t      this.container.append(this.el);\n\n\t      this.container.css({\n\t        'overflow': 'hidden',\n\t        'position': 'relative'\n\t      });\n\n\t      // Zepto doesn't recognize `webkitTransform..` style\n\t      this.el.css({\n\t        '-webkit-transform-origin': '0% 0%',\n\t        '-moz-transform-origin': '0% 0%',\n\t        '-ms-transform-origin': '0% 0%',\n\t        '-o-transform-origin': '0% 0%',\n\t        'transform-origin': '0% 0%',\n\t        'position': 'absolute'\n\t      });\n\t    },\n\n\t    end: function() {\n\t      this.hasInteraction = false;\n\t      this.sanitize();\n\t      this.update();\n\t    },\n\n\t    /**\n\t     * Binds all required event listeners\n\t     */\n\t    bindEvents: function() {\n\t      detectGestures(this.container.get(0), this);\n\t      // Zepto and jQuery both know about `on`\n\t      $(window).on('resize', this.update.bind(this));\n\t      $(this.el).find('img').on('load', this.update.bind(this));\n\t    },\n\n\t    /**\n\t     * Updates the css values according to the current zoom factor and offset\n\t     */\n\t    update: function() {\n\n\t      if (this.updatePlaned) {\n\t        return;\n\t      }\n\t      this.updatePlaned = true;\n\n\t      setTimeout((function() {\n\t        this.updatePlaned = false;\n\t        this.updateAspectRatio();\n\n\t        var zoomFactor = this.getInitialZoomFactor() * this.zoomFactor,\n\t          offsetX = -this.offset.x / zoomFactor,\n\t          offsetY = -this.offset.y / zoomFactor,\n\t          transform3d = 'scale3d(' + zoomFactor + ', ' + zoomFactor + ',1) ' +\n\t            'translate3d(' + offsetX + 'px,' + offsetY + 'px,0px)',\n\t          transform2d = 'scale(' + zoomFactor + ', ' + zoomFactor + ') ' +\n\t            'translate(' + offsetX + 'px,' + offsetY + 'px)',\n\t          removeClone = (function() {\n\t            if (this.clone) {\n\t              this.clone.remove();\n\t              delete this.clone;\n\t            }\n\t          }).bind(this);\n\n\t        // Scale 3d and translate3d are faster (at least on ios)\n\t        // but they also reduce the quality.\n\t        // PinchZoom uses the 3d transformations during interactions\n\t        // after interactions it falls back to 2d transformations\n\t        if (!this.options.use2d || this.hasInteraction || this.inAnimation) {\n\t          this.is3d = true;\n\t          removeClone();\n\t          this.el.css({\n\t            '-webkit-transform': transform3d,\n\t            '-o-transform': transform2d,\n\t            '-ms-transform': transform2d,\n\t            '-moz-transform': transform2d,\n\t            'transform': transform3d\n\t          });\n\t        } else {\n\n\t          // When changing from 3d to 2d transform webkit has some glitches.\n\t          // To avoid this, a copy of the 3d transformed element is displayed in the\n\t          // foreground while the element is converted from 3d to 2d transform\n\t          if (this.is3d) {\n\t            this.clone = this.el.clone();\n\t            this.clone.css('pointer-events', 'none');\n\t            this.clone.appendTo(this.container);\n\t            setTimeout(removeClone, 200);\n\t          }\n\t          this.el.css({\n\t            '-webkit-transform': transform2d,\n\t            '-o-transform': transform2d,\n\t            '-ms-transform': transform2d,\n\t            '-moz-transform': transform2d,\n\t            'transform': transform2d\n\t          });\n\t          this.is3d = false;\n\t        }\n\t      }).bind(this), 0);\n\t    },\n\n\t    /**\n\t     * Enables event handling for gestures\n\t     */\n\t    enable: function() {\n\t      this.enabled = true;\n\t    },\n\n\t    /**\n\t     * Disables event handling for gestures\n\t     */\n\t    disable: function() {\n\t      this.enabled = false;\n\t    }\n\t  };\n\n\t  var detectGestures = function(el, target) {\n\t    var interaction = null,\n\t      fingers = 0,\n\t      lastTouchStart = null,\n\t      startTouches = null,\n\n\t      setInteraction = function(newInteraction, event) {\n\t        if (interaction !== newInteraction) {\n\n\t          if (interaction && !newInteraction) {\n\t            switch (interaction) {\n\t              case \"zoom\":\n\t                target.handleZoomEnd(event);\n\t                break;\n\t              case 'drag':\n\t                target.handleDragEnd(event);\n\t                break;\n\t            }\n\t          }\n\n\t          switch (newInteraction) {\n\t            case 'zoom':\n\t              target.handleZoomStart(event);\n\t              break;\n\t            case 'drag':\n\t              target.handleDragStart(event);\n\t              break;\n\t          }\n\t        }\n\t        interaction = newInteraction;\n\t      },\n\n\t      updateInteraction = function(event) {\n\t        if (fingers === 2) {\n\t          setInteraction('zoom');\n\t        } else if (fingers === 1 && target.canDrag()) {\n\t          setInteraction('drag', event);\n\t        } else {\n\t          setInteraction(null, event);\n\t        }\n\t      },\n\n\t      targetTouches = function(touches) {\n\t        return Array.prototype.slice.call(touches).map(function(touch) {\n\t          return {\n\t            x: touch.pageX,\n\t            y: touch.pageY\n\t          };\n\t        });\n\t      },\n\n\t      getDistance = function(a, b) {\n\t        var x, y;\n\t        x = a.x - b.x;\n\t        y = a.y - b.y;\n\t        return Math.sqrt(x * x + y * y);\n\t      },\n\n\t      calculateScale = function(startTouches, endTouches) {\n\t        var startDistance = getDistance(startTouches[0], startTouches[1]),\n\t          endDistance = getDistance(endTouches[0], endTouches[1]);\n\t        return endDistance / startDistance;\n\t      },\n\n\t      cancelEvent = function(event) {\n\t        event.stopPropagation();\n\t        event.preventDefault();\n\t      },\n\n\t      detectDoubleTap = function(event) {\n\t        var time = (new Date()).getTime();\n\n\t        if (fingers > 1) {\n\t          lastTouchStart = null;\n\t        }\n\n\t        if (time - lastTouchStart < 300) {\n\t          cancelEvent(event);\n\n\t          target.handleDoubleTap(event);\n\t          switch (interaction) {\n\t            case \"zoom\":\n\t              target.handleZoomEnd(event);\n\t              break;\n\t            case 'drag':\n\t              target.handleDragEnd(event);\n\t              break;\n\t          }\n\t        }\n\n\t        if (fingers === 1) {\n\t          lastTouchStart = time;\n\t        }\n\t      },\n\t      firstMove = true;\n\n\t    el.addEventListener('touchstart', function(event) {\n\t      if (target.enabled) {\n\t        firstMove = true;\n\t        fingers = event.touches.length;\n\t        detectDoubleTap(event);\n\t      }\n\t    });\n\n\t    el.addEventListener('touchmove', function(event) {\n\t      if (target.enabled) {\n\t        if (firstMove) {\n\t          updateInteraction(event);\n\t          if (interaction) {\n\t            cancelEvent(event);\n\t          }\n\t          startTouches = targetTouches(event.touches);\n\t        } else {\n\t          switch (interaction) {\n\t            case 'zoom':\n\t              target.handleZoom(event, calculateScale(startTouches, targetTouches(event.touches)));\n\t              break;\n\t            case 'drag':\n\t              target.handleDrag(event);\n\t              break;\n\t          }\n\t          if (interaction) {\n\t            cancelEvent(event);\n\t            target.update();\n\t          }\n\t        }\n\n\t        firstMove = false;\n\t      }\n\t    });\n\n\t    el.addEventListener('touchend', function(event) {\n\t      if (target.enabled) {\n\t        fingers = event.touches.length;\n\t        updateInteraction(event);\n\t      }\n\t    });\n\t  };\n\n\t  return PinchZoom;\n\t};\n\n\tmodule.exports = UI.pichzoom = definePinchZoom($);\n\n\n/***/ },\n/* 18 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\tvar $w = $(window);\n\n\t/**\n\t * @reference https://github.com/nolimits4web/Framework7/blob/master/src/js/modals.js\n\t * @license https://github.com/nolimits4web/Framework7/blob/master/LICENSE\n\t */\n\n\tvar Popover = function(element, options) {\n\t  this.options = $.extend({}, Popover.DEFAULTS, options);\n\t  this.$element = $(element);\n\t  this.active = null;\n\t  this.$popover = (this.options.target && $(this.options.target)) || null;\n\n\t  this.init();\n\t  this._bindEvents();\n\t};\n\n\tPopover.DEFAULTS = {\n\t  theme: null,\n\t  trigger: 'click',\n\t  content: '',\n\t  open: false,\n\t  target: null,\n\t  tpl: '<div class=\"am-popover\">' +\n\t    '<div class=\"am-popover-inner\"></div>' +\n\t    '<div class=\"am-popover-caret\"></div></div>'\n\t};\n\n\tPopover.prototype.init = function() {\n\t  var _this = this;\n\t  var $element = this.$element;\n\t  var $popover;\n\n\t  if (!this.options.target) {\n\t    this.$popover = this.getPopover();\n\t    this.setContent();\n\t  }\n\n\t  $popover = this.$popover;\n\n\t  $popover.appendTo($('body'));\n\n\t  this.sizePopover();\n\n\t  function sizePopover() {\n\t    _this.sizePopover();\n\t  }\n\n\t  // TODO: 监听页面内容变化，重新调整位置\n\n\t  $element.on('open.popover.amui', function() {\n\t    $(window).on('resize.popover.amui', UI.utils.debounce(sizePopover, 50));\n\t  });\n\n\t  $element.on('close.popover.amui', function() {\n\t    $(window).off('resize.popover.amui', sizePopover);\n\t  });\n\n\t  this.options.open && this.open();\n\t};\n\n\tPopover.prototype.sizePopover = function sizePopover() {\n\t  var $element = this.$element;\n\t  var $popover = this.$popover;\n\n\t  if (!$popover || !$popover.length) {\n\t    return;\n\t  }\n\n\t  var popWidth = $popover.outerWidth();\n\t  var popHeight = $popover.outerHeight();\n\t  var $popCaret = $popover.find('.am-popover-caret');\n\t  var popCaretSize = ($popCaret.outerWidth() / 2) || 8;\n\t  // 取不到 $popCaret.outerHeight() 的值，所以直接加 8\n\t  var popTotalHeight = popHeight + 8; // $popCaret.outerHeight();\n\n\t  var triggerWidth = $element.outerWidth();\n\t  var triggerHeight = $element.outerHeight();\n\t  var triggerOffset = $element.offset();\n\t  var triggerRect = $element[0].getBoundingClientRect();\n\n\t  var winHeight = $w.height();\n\t  var winWidth = $w.width();\n\t  var popTop = 0;\n\t  var popLeft = 0;\n\t  var diff = 0;\n\t  var spacing = 2;\n\t  var popPosition = 'top';\n\n\t  $popover.css({left: '', top: ''}).removeClass('am-popover-left ' +\n\t  'am-popover-right am-popover-top am-popover-bottom');\n\n\t  // $popCaret.css({left: '', top: ''});\n\n\t  if (popTotalHeight - spacing < triggerRect.top + spacing) {\n\t    // Popover on the top of trigger\n\t    popTop = triggerOffset.top - popTotalHeight - spacing;\n\t  } else if (popTotalHeight <\n\t    winHeight - triggerRect.top - triggerRect.height) {\n\t    // On bottom\n\t    popPosition = 'bottom';\n\t    popTop = triggerOffset.top + triggerHeight + popCaretSize + spacing;\n\t  } else { // On middle\n\t    popPosition = 'middle';\n\t    popTop = triggerHeight / 2 + triggerOffset.top - popHeight / 2;\n\t  }\n\n\t  // Horizontal Position\n\t  if (popPosition === 'top' || popPosition === 'bottom') {\n\t    popLeft = triggerWidth / 2 + triggerOffset.left - popWidth / 2;\n\n\t    diff = popLeft;\n\n\t    if (popLeft < 5) {\n\t      popLeft = 5;\n\t    }\n\n\t    if (popLeft + popWidth > winWidth) {\n\t      popLeft = (winWidth - popWidth - 20);\n\t      // console.log('left %d, win %d, popw %d', popLeft, winWidth, popWidth);\n\t    }\n\n\t    if (popPosition === 'top') {\n\t      // This is the Popover position, NOT caret position\n\t      // Popover on the Top of trigger, caret on the bottom of Popover\n\t      $popover.addClass('am-popover-top');\n\t    }\n\n\t    if (popPosition === 'bottom') {\n\t      $popover.addClass('am-popover-bottom');\n\t    }\n\n\t    diff = diff - popLeft;\n\t    // $popCaret.css({left: (popWidth / 2 - popCaretSize + diff) + 'px'});\n\n\t  } else if (popPosition === 'middle') {\n\t    popLeft = triggerOffset.left - popWidth - popCaretSize;\n\t    $popover.addClass('am-popover-left');\n\t    if (popLeft < 5) {\n\t      popLeft = triggerOffset.left + triggerWidth + popCaretSize;\n\t      $popover.removeClass('am-popover-left').addClass('am-popover-right');\n\t    }\n\n\t    if (popLeft + popWidth > winWidth) {\n\t      popLeft = winWidth - popWidth - 5;\n\t      $popover.removeClass('am-popover-left').addClass('am-popover-right');\n\t    }\n\t    // $popCaret.css({top: (popHeight / 2 - popCaretSize / 2) + 'px'});\n\t  }\n\n\t  // Apply position style\n\t  $popover.css({top: popTop + 'px', left: popLeft + 'px'});\n\t};\n\n\tPopover.prototype.toggle = function() {\n\t  return this[this.active ? 'close' : 'open']();\n\t};\n\n\tPopover.prototype.open = function() {\n\t  var $popover = this.$popover;\n\n\t  this.$element.trigger('open.popover.amui');\n\t  this.sizePopover();\n\t  $popover.show().addClass('am-active');\n\t  this.active = true;\n\t};\n\n\tPopover.prototype.close = function() {\n\t  var $popover = this.$popover;\n\n\t  this.$element.trigger('close.popover.amui');\n\n\t  $popover\n\t    .removeClass('am-active')\n\t    .trigger('closed.popover.amui')\n\t    .hide();\n\n\t  this.active = false;\n\t};\n\n\tPopover.prototype.getPopover = function() {\n\t  var uid = UI.utils.generateGUID('am-popover');\n\t  var theme = [];\n\n\t  if (this.options.theme) {\n\t    $.each(this.options.theme.split(' '), function(i, item) {\n\t      theme.push('am-popover-' + $.trim(item));\n\t    });\n\t  }\n\n\t  return $(this.options.tpl).attr('id', uid).addClass(theme.join(' '));\n\t};\n\n\tPopover.prototype.setContent = function(content) {\n\t  content = content || this.options.content;\n\t  this.$popover && this.$popover.find('.am-popover-inner')\n\t    .empty().html(content);\n\t};\n\n\tPopover.prototype._bindEvents = function() {\n\t  var eventNS = 'popover.amui';\n\t  var triggers = this.options.trigger.split(' ');\n\n\t  for (var i = triggers.length; i--;) {\n\t    var trigger = triggers[i];\n\n\t    if (trigger === 'click') {\n\t      this.$element.on('click.' + eventNS, $.proxy(this.toggle, this));\n\t    } else { // hover or focus\n\t      var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin';\n\t      var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout';\n\n\t      this.$element.on(eventIn + '.' + eventNS, $.proxy(this.open, this));\n\t      this.$element.on(eventOut + '.' + eventNS, $.proxy(this.close, this));\n\t    }\n\t  }\n\t};\n\n\tPopover.prototype.destroy = function() {\n\t  this.$element.off('.popover.amui').removeData('amui.popover');\n\t  this.$popover.remove();\n\t};\n\n\tUI.plugin('popover', Popover);\n\n\t// Init code\n\tUI.ready(function(context) {\n\t  $('[data-am-popover]', context).popover();\n\t});\n\n\tmodule.exports = Popover;\n\n\t// TODO: 允许用户定义位置\n\n\n/***/ },\n/* 19 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar UI = __webpack_require__(2);\n\n\tvar Progress = (function() {\n\t  /**\n\t   * NProgress (c) 2013, Rico Sta. Cruz\n\t   * @via http://ricostacruz.com/nprogress\n\t   */\n\n\t  var NProgress = {};\n\n\t  NProgress.version = '0.2.0';\n\n\t  var Settings = NProgress.settings = {\n\t    minimum: 0.08,\n\t    easing: 'ease',\n\t    positionUsing: '',\n\t    speed: 200,\n\t    trickle: true,\n\t    trickleRate: 0.02,\n\t    trickleSpeed: 800,\n\t    showSpinner: true,\n\t    parent: 'body',\n\t    barSelector: '[role=\"nprogress-bar\"]',\n\t    spinnerSelector: '[role=\"nprogress-spinner\"]',\n\t    template: '<div class=\"nprogress-bar\" role=\"nprogress-bar\">' +\n\t    '<div class=\"nprogress-peg\"></div></div>' +\n\t    '<div class=\"nprogress-spinner\" role=\"nprogress-spinner\">' +\n\t    '<div class=\"nprogress-spinner-icon\"></div></div>'\n\t  };\n\n\t  /**\n\t   * Updates configuration.\n\t   *\n\t   *     NProgress.configure({\n\t   *       minimum: 0.1\n\t   *     });\n\t   */\n\t  NProgress.configure = function(options) {\n\t    var key, value;\n\t    for (key in options) {\n\t      value = options[key];\n\t      if (value !== undefined && options.hasOwnProperty(key)) Settings[key] = value;\n\t    }\n\n\t    return this;\n\t  };\n\n\t  /**\n\t   * Last number.\n\t   */\n\n\t  NProgress.status = null;\n\n\t  /**\n\t   * Sets the progress bar status, where `n` is a number from `0.0` to `1.0`.\n\t   *\n\t   *     NProgress.set(0.4);\n\t   *     NProgress.set(1.0);\n\t   */\n\n\t  NProgress.set = function(n) {\n\t    var started = NProgress.isStarted();\n\n\t    n = clamp(n, Settings.minimum, 1);\n\t    NProgress.status = (n === 1 ? null : n);\n\n\t    var progress = NProgress.render(!started),\n\t      bar      = progress.querySelector(Settings.barSelector),\n\t      speed    = Settings.speed,\n\t      ease     = Settings.easing;\n\n\t    progress.offsetWidth; /* Repaint */\n\n\t    queue(function(next) {\n\t      // Set positionUsing if it hasn't already been set\n\t      if (Settings.positionUsing === '') Settings.positionUsing = NProgress.getPositioningCSS();\n\n\t      // Add transition\n\t      css(bar, barPositionCSS(n, speed, ease));\n\n\t      if (n === 1) {\n\t        // Fade out\n\t        css(progress, {\n\t          transition: 'none',\n\t          opacity: 1\n\t        });\n\t        progress.offsetWidth; /* Repaint */\n\n\t        setTimeout(function() {\n\t          css(progress, {\n\t            transition: 'all ' + speed + 'ms linear',\n\t            opacity: 0\n\t          });\n\t          setTimeout(function() {\n\t            NProgress.remove();\n\t            next();\n\t          }, speed);\n\t        }, speed);\n\t      } else {\n\t        setTimeout(next, speed);\n\t      }\n\t    });\n\n\t    return this;\n\t  };\n\n\t  NProgress.isStarted = function() {\n\t    return typeof NProgress.status === 'number';\n\t  };\n\n\t  /**\n\t   * Shows the progress bar.\n\t   * This is the same as setting the status to 0%, except that it doesn't go backwards.\n\t   *\n\t   *     NProgress.start();\n\t   *\n\t   */\n\t  NProgress.start = function() {\n\t    if (!NProgress.status) NProgress.set(0);\n\n\t    var work = function() {\n\t      setTimeout(function() {\n\t        if (!NProgress.status) return;\n\t        NProgress.trickle();\n\t        work();\n\t      }, Settings.trickleSpeed);\n\t    };\n\n\t    if (Settings.trickle) work();\n\n\t    return this;\n\t  };\n\n\t  /**\n\t   * Hides the progress bar.\n\t   * This is the *sort of* the same as setting the status to 100%, with the\n\t   * difference being `done()` makes some placebo effect of some realistic motion.\n\t   *\n\t   *     NProgress.done();\n\t   *\n\t   * If `true` is passed, it will show the progress bar even if its hidden.\n\t   *\n\t   *     NProgress.done(true);\n\t   */\n\n\t  NProgress.done = function(force) {\n\t    if (!force && !NProgress.status) return this;\n\n\t    return NProgress.inc(0.3 + 0.5 * Math.random()).set(1);\n\t  };\n\n\t  /**\n\t   * Increments by a random amount.\n\t   */\n\n\t  NProgress.inc = function(amount) {\n\t    var n = NProgress.status;\n\n\t    if (!n) {\n\t      return NProgress.start();\n\t    } else {\n\t      if (typeof amount !== 'number') {\n\t        amount = (1 - n) * clamp(Math.random() * n, 0.1, 0.95);\n\t      }\n\n\t      n = clamp(n + amount, 0, 0.994);\n\t      return NProgress.set(n);\n\t    }\n\t  };\n\n\t  NProgress.trickle = function() {\n\t    return NProgress.inc(Math.random() * Settings.trickleRate);\n\t  };\n\n\t  /**\n\t   * Waits for all supplied jQuery promises and\n\t   * increases the progress as the promises resolve.\n\t   *\n\t   * @param $promise jQUery Promise\n\t   */\n\t  (function() {\n\t    var initial = 0, current = 0;\n\n\t    NProgress.promise = function($promise) {\n\t      if (!$promise || $promise.state() === \"resolved\") {\n\t        return this;\n\t      }\n\n\t      if (current === 0) {\n\t        NProgress.start();\n\t      }\n\n\t      initial++;\n\t      current++;\n\n\t      $promise.always(function() {\n\t        current--;\n\t        if (current === 0) {\n\t          initial = 0;\n\t          NProgress.done();\n\t        } else {\n\t          NProgress.set((initial - current) / initial);\n\t        }\n\t      });\n\n\t      return this;\n\t    };\n\n\t  })();\n\n\t  /**\n\t   * (Internal) renders the progress bar markup based on the `template`\n\t   * setting.\n\t   */\n\n\t  NProgress.render = function(fromStart) {\n\t    if (NProgress.isRendered()) return document.getElementById('nprogress');\n\n\t    addClass(document.documentElement, 'nprogress-busy');\n\n\t    var progress = document.createElement('div');\n\t    progress.id = 'nprogress';\n\t    progress.innerHTML = Settings.template;\n\n\t    var bar      = progress.querySelector(Settings.barSelector),\n\t      perc     = fromStart ? '-100' : toBarPerc(NProgress.status || 0),\n\t      parent   = document.querySelector(Settings.parent),\n\t      spinner;\n\n\t    css(bar, {\n\t      transition: 'all 0 linear',\n\t      transform: 'translate3d(' + perc + '%,0,0)'\n\t    });\n\n\t    if (!Settings.showSpinner) {\n\t      spinner = progress.querySelector(Settings.spinnerSelector);\n\t      spinner && removeElement(spinner);\n\t    }\n\n\t    if (parent != document.body) {\n\t      addClass(parent, 'nprogress-custom-parent');\n\t    }\n\n\t    parent.appendChild(progress);\n\t    return progress;\n\t  };\n\n\t  /**\n\t   * Removes the element. Opposite of render().\n\t   */\n\n\t  NProgress.remove = function() {\n\t    removeClass(document.documentElement, 'nprogress-busy');\n\t    removeClass(document.querySelector(Settings.parent), 'nprogress-custom-parent');\n\t    var progress = document.getElementById('nprogress');\n\t    progress && removeElement(progress);\n\t  };\n\n\t  /**\n\t   * Checks if the progress bar is rendered.\n\t   */\n\n\t  NProgress.isRendered = function() {\n\t    return !!document.getElementById('nprogress');\n\t  };\n\n\t  /**\n\t   * Determine which positioning CSS rule to use.\n\t   */\n\n\t  NProgress.getPositioningCSS = function() {\n\t    // Sniff on document.body.style\n\t    var bodyStyle = document.body.style;\n\n\t    // Sniff prefixes\n\t    var vendorPrefix = ('WebkitTransform' in bodyStyle) ? 'Webkit' :\n\t      ('MozTransform' in bodyStyle) ? 'Moz' :\n\t        ('msTransform' in bodyStyle) ? 'ms' :\n\t          ('OTransform' in bodyStyle) ? 'O' : '';\n\n\t    if (vendorPrefix + 'Perspective' in bodyStyle) {\n\t      // Modern browsers with 3D support, e.g. Webkit, IE10\n\t      return 'translate3d';\n\t    } else if (vendorPrefix + 'Transform' in bodyStyle) {\n\t      // Browsers without 3D support, e.g. IE9\n\t      return 'translate';\n\t    } else {\n\t      // Browsers without translate() support, e.g. IE7-8\n\t      return 'margin';\n\t    }\n\t  };\n\n\t  /**\n\t   * Helpers\n\t   */\n\n\t  function clamp(n, min, max) {\n\t    if (n < min) return min;\n\t    if (n > max) return max;\n\t    return n;\n\t  }\n\n\t  /**\n\t   * (Internal) converts a percentage (`0..1`) to a bar translateX\n\t   * percentage (`-100%..0%`).\n\t   */\n\n\t  function toBarPerc(n) {\n\t    return (-1 + n) * 100;\n\t  }\n\n\n\t  /**\n\t   * (Internal) returns the correct CSS for changing the bar's\n\t   * position given an n percentage, and speed and ease from Settings\n\t   */\n\n\t  function barPositionCSS(n, speed, ease) {\n\t    var barCSS;\n\n\t    if (Settings.positionUsing === 'translate3d') {\n\t      barCSS = { transform: 'translate3d('+toBarPerc(n)+'%,0,0)' };\n\t    } else if (Settings.positionUsing === 'translate') {\n\t      barCSS = { transform: 'translate('+toBarPerc(n)+'%,0)' };\n\t    } else {\n\t      barCSS = { 'margin-left': toBarPerc(n)+'%' };\n\t    }\n\n\t    barCSS.transition = 'all '+speed+'ms '+ease;\n\n\t    return barCSS;\n\t  }\n\n\t  /**\n\t   * (Internal) Queues a function to be executed.\n\t   */\n\n\t  var queue = (function() {\n\t    var pending = [];\n\n\t    function next() {\n\t      var fn = pending.shift();\n\t      if (fn) {\n\t        fn(next);\n\t      }\n\t    }\n\n\t    return function(fn) {\n\t      pending.push(fn);\n\t      if (pending.length == 1) next();\n\t    };\n\t  })();\n\n\t  /**\n\t   * (Internal) Applies css properties to an element, similar to the jQuery\n\t   * css method.\n\t   *\n\t   * While this helper does assist with vendor prefixed property names, it\n\t   * does not perform any manipulation of values prior to setting styles.\n\t   */\n\n\t  var css = (function() {\n\t    var cssPrefixes = [ 'Webkit', 'O', 'Moz', 'ms' ],\n\t      cssProps    = {};\n\n\t    function camelCase(string) {\n\t      return string.replace(/^-ms-/, 'ms-').replace(/-([\\da-z])/gi, function(match, letter) {\n\t        return letter.toUpperCase();\n\t      });\n\t    }\n\n\t    function getVendorProp(name) {\n\t      var style = document.body.style;\n\t      if (name in style) return name;\n\n\t      var i = cssPrefixes.length,\n\t        capName = name.charAt(0).toUpperCase() + name.slice(1),\n\t        vendorName;\n\t      while (i--) {\n\t        vendorName = cssPrefixes[i] + capName;\n\t        if (vendorName in style) return vendorName;\n\t      }\n\n\t      return name;\n\t    }\n\n\t    function getStyleProp(name) {\n\t      name = camelCase(name);\n\t      return cssProps[name] || (cssProps[name] = getVendorProp(name));\n\t    }\n\n\t    function applyCss(element, prop, value) {\n\t      prop = getStyleProp(prop);\n\t      element.style[prop] = value;\n\t    }\n\n\t    return function(element, properties) {\n\t      var args = arguments,\n\t        prop,\n\t        value;\n\n\t      if (args.length == 2) {\n\t        for (prop in properties) {\n\t          value = properties[prop];\n\t          if (value !== undefined && properties.hasOwnProperty(prop)) applyCss(element, prop, value);\n\t        }\n\t      } else {\n\t        applyCss(element, args[1], args[2]);\n\t      }\n\t    }\n\t  })();\n\n\t  /**\n\t   * (Internal) Determines if an element or space separated list of class names contains a class name.\n\t   */\n\n\t  function hasClass(element, name) {\n\t    var list = typeof element == 'string' ? element : classList(element);\n\t    return list.indexOf(' ' + name + ' ') >= 0;\n\t  }\n\n\t  /**\n\t   * (Internal) Adds a class to an element.\n\t   */\n\n\t  function addClass(element, name) {\n\t    var oldList = classList(element),\n\t      newList = oldList + name;\n\n\t    if (hasClass(oldList, name)) return;\n\n\t    // Trim the opening space.\n\t    element.className = newList.substring(1);\n\t  }\n\n\t  /**\n\t   * (Internal) Removes a class from an element.\n\t   */\n\n\t  function removeClass(element, name) {\n\t    var oldList = classList(element),\n\t      newList;\n\n\t    if (!hasClass(element, name)) return;\n\n\t    // Replace the class name.\n\t    newList = oldList.replace(' ' + name + ' ', ' ');\n\n\t    // Trim the opening and closing spaces.\n\t    element.className = newList.substring(1, newList.length - 1);\n\t  }\n\n\t  /**\n\t   * (Internal) Gets a space separated list of the class names on the element.\n\t   * The list is wrapped with a single space on each end to facilitate finding\n\t   * matches within the list.\n\t   */\n\n\t  function classList(element) {\n\t    return (' ' + (element.className || '') + ' ').replace(/\\s+/gi, ' ');\n\t  }\n\n\t  /**\n\t   * (Internal) Removes an element from the DOM.\n\t   */\n\n\t  function removeElement(element) {\n\t    element && element.parentNode && element.parentNode.removeChild(element);\n\t  }\n\n\t  return NProgress;\n\t})();\n\n\tmodule.exports = UI.progress = Progress;\n\n\n/***/ },\n/* 20 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\tvar PinchZoom = __webpack_require__(17);\n\tvar Hammer = __webpack_require__(3);\n\tvar animation = UI.support.animation;\n\tvar transition = UI.support.transition;\n\n\t/**\n\t * PureView\n\t * @desc Image browser for Mobile\n\t * @param element\n\t * @param options\n\t * @constructor\n\t */\n\n\tvar PureView = function(element, options) {\n\t  this.$element = $(element);\n\t  this.$body = $(document.body);\n\t  this.options = $.extend({}, PureView.DEFAULTS, options);\n\t  this.$pureview = $(this.options.tpl).attr('id',\n\t    UI.utils.generateGUID('am-pureview'));\n\n\t  this.$slides = null;\n\t  this.transitioning = null;\n\t  this.scrollbarWidth = 0;\n\n\t  this.init();\n\t};\n\n\tPureView.DEFAULTS = {\n\t  tpl: '<div class=\"am-pureview am-pureview-bar-active\">' +\n\t  '<ul class=\"am-pureview-slider\"></ul>' +\n\t  '<ul class=\"am-pureview-direction\">' +\n\t  '<li class=\"am-pureview-prev\"><a href=\"\"></a></li>' +\n\t  '<li class=\"am-pureview-next\"><a href=\"\"></a></li></ul>' +\n\t  '<ol class=\"am-pureview-nav\"></ol>' +\n\t  '<div class=\"am-pureview-bar am-active\">' +\n\t  '<span class=\"am-pureview-title\"></span>' +\n\t  '<div class=\"am-pureview-counter\"><span class=\"am-pureview-current\"></span> / ' +\n\t  '<span class=\"am-pureview-total\"></span></div></div>' +\n\t  '<div class=\"am-pureview-actions am-active\">' +\n\t  '<a href=\"javascript: void(0)\" class=\"am-icon-chevron-left\" ' +\n\t  'data-am-close=\"pureview\"></a></div>' +\n\t  '</div>',\n\n\t  className: {\n\t    prevSlide: 'am-pureview-slide-prev',\n\t    nextSlide: 'am-pureview-slide-next',\n\t    onlyOne: 'am-pureview-only',\n\t    active: 'am-active',\n\t    barActive: 'am-pureview-bar-active',\n\t    activeBody: 'am-pureview-active'\n\t  },\n\n\t  selector: {\n\t    slider: '.am-pureview-slider',\n\t    close: '[data-am-close=\"pureview\"]',\n\t    total: '.am-pureview-total',\n\t    current: '.am-pureview-current',\n\t    title: '.am-pureview-title',\n\t    actions: '.am-pureview-actions',\n\t    bar: '.am-pureview-bar',\n\t    pinchZoom: '.am-pinch-zoom',\n\t    nav: '.am-pureview-nav'\n\t  },\n\n\t  shareBtn: false,\n\n\t  // press to toggle Toolbar\n\t  toggleToolbar: true,\n\n\t  // 从何处获取图片，img 可以使用 data-rel 指定大图\n\t  target: 'img',\n\n\t  // 微信 Webview 中调用微信的图片浏览器\n\t  // 实现图片保存、分享好友、收藏图片等功能\n\t  weChatImagePreview: true\n\t};\n\n\tPureView.prototype.init = function() {\n\t  var _this = this;\n\t  var options = this.options;\n\t  var $element = this.$element;\n\t  var $pureview = this.$pureview;\n\n\t  this.refreshSlides();\n\n\t  $('body').append($pureview);\n\n\t  this.$title = $pureview.find(options.selector.title);\n\t  this.$current = $pureview.find(options.selector.current);\n\t  this.$bar = $pureview.find(options.selector.bar);\n\t  this.$actions = $pureview.find(options.selector.actions);\n\n\t  if (options.shareBtn) {\n\t    this.$actions.append('<a href=\"javascript: void(0)\" ' +\n\t    'class=\"am-icon-share-square-o\" data-am-toggle=\"share\"></a>');\n\t  }\n\n\t  this.$element.on('click.pureview.amui', options.target, function(e) {\n\t    e.preventDefault();\n\t    var clicked = _this.$images.index(this);\n\n\t    // Invoke WeChat ImagePreview in WeChat\n\t    // TODO: detect WeChat before init\n\t    if (options.weChatImagePreview && window.WeixinJSBridge) {\n\t      window.WeixinJSBridge.invoke('imagePreview', {\n\t        current: _this.imgUrls[clicked],\n\t        urls: _this.imgUrls\n\t      });\n\t    } else {\n\t      _this.open(clicked);\n\t    }\n\t  });\n\n\t  $pureview.find('.am-pureview-direction').\n\t    on('click.direction.pureview.amui', 'li', function(e) {\n\t      e.preventDefault();\n\n\t      if ($(this).is('.am-pureview-prev')) {\n\t        _this.prevSlide();\n\t      } else {\n\t        _this.nextSlide();\n\t      }\n\t    });\n\n\t  // Nav Contorl\n\t  $pureview.find(options.selector.nav).on('click.nav.pureview.amui', 'li',\n\t    function() {\n\t      var index = _this.$navItems.index($(this));\n\t      _this.activate(_this.$slides.eq(index));\n\t    });\n\n\t  // Close Icon\n\t  $pureview.find(options.selector.close).\n\t    on('click.close.pureview.amui', function(e) {\n\t      e.preventDefault();\n\t      _this.close();\n\t    });\n\n\t  this.$slider.hammer().on('swipeleft.pureview.amui', function(e) {\n\t    e.preventDefault();\n\t    _this.nextSlide();\n\t  }).on('swiperight.pureview.amui', function(e) {\n\t    e.preventDefault();\n\t    _this.prevSlide();\n\t  }).on('press.pureview.amui', function(e) {\n\t    e.preventDefault();\n\t    options.toggleToolbar && _this.toggleToolBar();\n\t  });\n\n\t  this.$slider.data('hammer').get('swipe').set({\n\t    direction: Hammer.DIRECTION_HORIZONTAL,\n\t    velocity: 0.35\n\t  });\n\n\t  // Observe DOM\n\t  $element.DOMObserve({\n\t    childList: true,\n\t    subtree: true\n\t  }, function(mutations, observer) {\n\t    // _this.refreshSlides();\n\t    // console.log('mutations[0].type);\n\t  });\n\n\t  // NOTE:\n\t  // trigger this event manually if MutationObserver not supported\n\t  //   when new images appended, or call refreshSlides()\n\t  // if (!UI.support.mutationobserver) $element.trigger('changed.dom.amui')\n\t  $element.on('changed.dom.amui', function(e) {\n\t    e.stopPropagation();\n\t    _this.refreshSlides();\n\t  });\n\n\t  $(document).on('keydown.pureview.amui', $.proxy(function(e) {\n\t    var keyCode = e.keyCode;\n\t    if (keyCode == 37) {\n\t      this.prevSlide();\n\t    } else if (keyCode == 39) {\n\t      this.nextSlide();\n\t    } else if (keyCode == 27) {\n\t      this.close();\n\t    }\n\t  }, this));\n\t};\n\n\tPureView.prototype.refreshSlides = function() {\n\t  // update images collections\n\t  this.$images = this.$element.find(this.options.target);\n\t  var _this = this;\n\t  var options = this.options;\n\t  var $pureview = this.$pureview;\n\t  var $slides = $([]);\n\t  var $navItems = $([]);\n\t  var $images = this.$images;\n\t  var total = $images.length;\n\t  this.$slider = $pureview.find(options.selector.slider);\n\t  this.$nav = $pureview.find(options.selector.nav);\n\t  var viewedFlag = 'data-am-pureviewed';\n\t  // for WeChat Image Preview\n\t  this.imgUrls = this.imgUrls || [];\n\n\t  if (!total) {\n\t    return;\n\t  }\n\n\t  if (total === 1) {\n\t    $pureview.addClass(options.className.onlyOne);\n\t  }\n\n\t  $images.not('[' + viewedFlag + ']').each(function(i, item) {\n\t    var src;\n\t    var title;\n\n\t    // get image URI from link's href attribute\n\t    if (item.nodeName === 'A') {\n\t      src = item.href; // to absolute path\n\t      title = item.title || '';\n\t    } else {\n\t      // NOTE: `data-rel` should be a full URL, otherwise,\n\t      //        WeChat images preview will not work\n\t      src = $(item).data('rel') || item.src; // <img src='' data-rel='' />\n\t      src = UI.utils.getAbsoluteUrl(src);\n\t      title = $(item).attr('alt') || '';\n\t    }\n\n\t    // add pureviewed flag\n\t    item.setAttribute(viewedFlag, '1');\n\n\t    // hide bar: wechat_webview_type=1\n\t    // http://tmt.io/wechat/  not working?\n\t    _this.imgUrls.push(src);\n\n\t    $slides = $slides.add($('<li data-src=\"' + src + '\" data-title=\"' + title +\n\t    '\"></li>'));\n\t    $navItems = $navItems.add($('<li>' + (i + 1) + '</li>'));\n\t  });\n\n\t  $pureview.find(options.selector.total).text(total);\n\n\t  this.$slider.append($slides);\n\t  this.$nav.append($navItems);\n\t  this.$navItems = this.$nav.find('li');\n\t  this.$slides = this.$slider.find('li');\n\t};\n\n\tPureView.prototype.loadImage = function($slide, callback) {\n\t  var appendedFlag = 'image-appended';\n\n\t  if (!$slide.data(appendedFlag)) {\n\t    var $img = $('<img>', {\n\t      src: $slide.data('src'),\n\t      alt: $slide.data('title')\n\t    });\n\n\t    $slide.html($img).wrapInner('<div class=\"am-pinch-zoom\"></div>').redraw();\n\n\t    var $pinchWrapper = $slide.find(this.options.selector.pinchZoom);\n\t    $pinchWrapper.data('amui.pinchzoom', new PinchZoom($pinchWrapper[0], {}));\n\t    $slide.data('image-appended', true);\n\t  }\n\n\t  callback && callback.call(this);\n\t};\n\n\tPureView.prototype.activate = function($slide) {\n\t  var options = this.options;\n\t  var $slides = this.$slides;\n\t  var activeIndex = $slides.index($slide);\n\t  var title = $slide.data('title') || '';\n\t  var active = options.className.active;\n\n\t  if ($slides.find('.' + active).is($slide)) {\n\t    return;\n\t  }\n\n\t  if (this.transitioning) {\n\t    return;\n\t  }\n\n\t  this.loadImage($slide, function() {\n\t    UI.utils.imageLoader($slide.find('img'), function(image) {\n\t      $slide.find('.am-pinch-zoom').addClass('am-pureview-loaded');\n\t      $(image).addClass('am-img-loaded');\n\t    });\n\t  });\n\n\t  this.transitioning = 1;\n\n\t  this.$title.text(title);\n\t  this.$current.text(activeIndex + 1);\n\t  $slides.removeClass();\n\t  $slide.addClass(active);\n\t  $slides.eq(activeIndex - 1).addClass(options.className.prevSlide);\n\t  $slides.eq(activeIndex + 1).addClass(options.className.nextSlide);\n\n\t  this.$navItems.removeClass().\n\t    eq(activeIndex).addClass(options.className.active);\n\n\t  if (transition) {\n\t    $slide.one(transition.end, $.proxy(function() {\n\t      this.transitioning = 0;\n\t    }, this)).emulateTransitionEnd(300);\n\t  } else {\n\t    this.transitioning = 0;\n\t  }\n\n\t  // TODO: pre-load next image\n\t};\n\n\tPureView.prototype.nextSlide = function() {\n\t  if (this.$slides.length === 1) {\n\t    return;\n\t  }\n\n\t  var $slides = this.$slides;\n\t  var $active = $slides.filter('.am-active');\n\t  var activeIndex = $slides.index($active);\n\t  var rightSpring = 'am-animation-right-spring';\n\n\t  if (activeIndex + 1 >= $slides.length) { // last one\n\t    animation && $active.addClass(rightSpring).on(animation.end, function() {\n\t      $active.removeClass(rightSpring);\n\t    });\n\t  } else {\n\t    this.activate($slides.eq(activeIndex + 1));\n\t  }\n\t};\n\n\tPureView.prototype.prevSlide = function() {\n\t  if (this.$slides.length === 1) {\n\t    return;\n\t  }\n\n\t  var $slides = this.$slides;\n\t  var $active = $slides.filter('.am-active');\n\t  var activeIndex = this.$slides.index(($active));\n\t  var leftSpring = 'am-animation-left-spring';\n\n\t  if (activeIndex === 0) { // first one\n\t    animation && $active.addClass(leftSpring).on(animation.end, function() {\n\t      $active.removeClass(leftSpring);\n\t    });\n\t  } else {\n\t    this.activate($slides.eq(activeIndex - 1));\n\t  }\n\t};\n\n\tPureView.prototype.toggleToolBar = function() {\n\t  this.$pureview.toggleClass(this.options.className.barActive);\n\t};\n\n\tPureView.prototype.open = function(index) {\n\t  var active = index || 0;\n\t  this.checkScrollbar();\n\t  this.setScrollbar();\n\t  this.activate(this.$slides.eq(active));\n\t  this.$pureview.show().redraw().addClass(this.options.className.active);\n\t  this.$body.addClass(this.options.className.activeBody);\n\t};\n\n\tPureView.prototype.close = function() {\n\t  var options = this.options;\n\n\t  this.$pureview.removeClass(options.className.active);\n\t  this.$slides.removeClass();\n\n\t  function resetBody() {\n\t    this.$pureview.hide();\n\t    this.$body.removeClass(options.className.activeBody);\n\t    this.resetScrollbar();\n\t  }\n\n\t  if (transition) {\n\t    this.$pureview.one(transition.end, $.proxy(resetBody, this)).\n\t      emulateTransitionEnd(300);\n\t  } else {\n\t    resetBody.call(this);\n\t  }\n\t};\n\n\tPureView.prototype.checkScrollbar = function() {\n\t  this.scrollbarWidth = UI.utils.measureScrollbar();\n\t};\n\n\tPureView.prototype.setScrollbar = function() {\n\t  var bodyPaddingRight = parseInt((this.$body.css('padding-right') || 0), 10);\n\t  if (this.scrollbarWidth) {\n\t    this.$body.css('padding-right', bodyPaddingRight + this.scrollbarWidth);\n\t  }\n\t};\n\n\tPureView.prototype.resetScrollbar = function() {\n\t  this.$body.css('padding-right', '');\n\t};\n\n\tUI.plugin('pureview', PureView);\n\n\t// Init code\n\tUI.ready(function(context) {\n\t  $('[data-am-pureview]', context).pureview();\n\t});\n\n\tmodule.exports = PureView;\n\n\t// TODO: 1. 动画改进\n\t//       2. 改变图片的时候恢复 Zoom\n\t//       3. 选项\n\t//       4. 图片高度问题：由于 PinchZoom 的原因，过高的图片如果设置看了滚动，则放大以后显示不全\n\n\n/***/ },\n/* 21 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\n\t/**\n\t * @via https://github.com/uikit/uikit/blob/master/src/js/scrollspy.js\n\t * @license https://github.com/uikit/uikit/blob/master/LICENSE.md\n\t */\n\n\tvar ScrollSpy = function(element, options) {\n\t  if (!UI.support.animation) {\n\t    return;\n\t  }\n\n\t  this.options = $.extend({}, ScrollSpy.DEFAULTS, options);\n\t  this.$element = $(element);\n\n\t  var checkViewRAF = function() {\n\t    UI.utils.rAF.call(window, $.proxy(this.checkView, this));\n\t  }.bind(this);\n\n\t  this.$window = $(window).on('scroll.scrollspy.amui', checkViewRAF)\n\t    .on('resize.scrollspy.amui orientationchange.scrollspy.amui',\n\t    UI.utils.debounce(checkViewRAF, 50));\n\n\t  this.timer = this.inViewState = this.initInView = null;\n\n\t  checkViewRAF();\n\t};\n\n\tScrollSpy.DEFAULTS = {\n\t  animation: 'fade',\n\t  className: {\n\t    inView: 'am-scrollspy-inview',\n\t    init: 'am-scrollspy-init'\n\t  },\n\t  repeat: true,\n\t  delay: 0,\n\t  topOffset: 0,\n\t  leftOffset: 0\n\t};\n\n\tScrollSpy.prototype.checkView = function() {\n\t  var $element = this.$element;\n\t  var options = this.options;\n\t  var inView = UI.utils.isInView($element, options);\n\t  var animation = options.animation ?\n\t  ' am-animation-' + options.animation : '';\n\n\t  if (inView && !this.inViewState) {\n\t    if (this.timer) {\n\t      clearTimeout(this.timer);\n\t    }\n\n\t    if (!this.initInView) {\n\t      $element.addClass(options.className.init);\n\t      this.offset = $element.offset();\n\t      this.initInView = true;\n\n\t      $element.trigger('init.scrollspy.amui');\n\t    }\n\n\t    this.timer = setTimeout(function() {\n\t      if (inView) {\n\t        $element.addClass(options.className.inView + animation).width();\n\t      }\n\t    }, options.delay);\n\n\t    this.inViewState = true;\n\t    $element.trigger('inview.scrollspy.amui');\n\t  }\n\n\t  if (!inView && this.inViewState && options.repeat) {\n\t    $element.removeClass(options.className.inView + animation);\n\n\t    this.inViewState = false;\n\n\t    $element.trigger('outview.scrollspy.amui');\n\t  }\n\t};\n\n\tScrollSpy.prototype.check = function() {\n\t  UI.utils.rAF.call(window, $.proxy(this.checkView, this));\n\t};\n\n\t// Sticky Plugin\n\tUI.plugin('scrollspy', ScrollSpy);\n\n\t// Init code\n\tUI.ready(function(context) {\n\t  $('[data-am-scrollspy]', context).scrollspy();\n\t});\n\n\tmodule.exports = ScrollSpy;\n\n\n/***/ },\n/* 22 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\t__webpack_require__(23);\n\n\t/**\n\t * @via https://github.com/uikit/uikit/\n\t * @license https://github.com/uikit/uikit/blob/master/LICENSE.md\n\t */\n\n\t// ScrollSpyNav Class\n\tvar ScrollSpyNav = function(element, options) {\n\t  this.options = $.extend({}, ScrollSpyNav.DEFAULTS, options);\n\t  this.$element = $(element);\n\t  this.anchors = [];\n\n\t  this.$links = this.$element.find('a[href^=\"#\"]').each(function(i, link) {\n\t    this.anchors.push($(link).attr('href'));\n\t  }.bind(this));\n\n\t  this.$targets = $(this.anchors.join(', '));\n\n\t  var processRAF = function() {\n\t    UI.utils.rAF.call(window, $.proxy(this.process, this));\n\t  }.bind(this);\n\n\t  this.$window = $(window).on('scroll.scrollspynav.amui', processRAF)\n\t    .on('resize.scrollspynav.amui orientationchange.scrollspynav.amui',\n\t    UI.utils.debounce(processRAF, 50));\n\n\t  processRAF();\n\t  this.scrollProcess();\n\t};\n\n\tScrollSpyNav.DEFAULTS = {\n\t  className: {\n\t    active: 'am-active'\n\t  },\n\t  closest: false,\n\t  smooth: true,\n\t  offsetTop: 0\n\t};\n\n\tScrollSpyNav.prototype.process = function() {\n\t  var scrollTop = this.$window.scrollTop();\n\t  var options = this.options;\n\t  var inViews = [];\n\t  var $links = this.$links;\n\n\t  var $targets = this.$targets;\n\n\t  $targets.each(function(i, target) {\n\t    if (UI.utils.isInView(target, options)) {\n\t      inViews.push(target);\n\t    }\n\t  });\n\n\t  // console.log(inViews.length);\n\n\t  if (inViews.length) {\n\t    var $target;\n\n\t    $.each(inViews, function(i, item) {\n\t      if ($(item).offset().top >= scrollTop) {\n\t        $target = $(item);\n\t        return false; // break\n\t      }\n\t    });\n\n\t    if (!$target) {\n\t      return;\n\t    }\n\n\t    if (options.closest) {\n\t      $links.closest(options.closest).removeClass(options.className.active);\n\t      $links.filter('a[href=\"#' + $target.attr('id') + '\"]').\n\t        closest(options.closest).addClass(options.className.active);\n\t    } else {\n\t      $links.removeClass(options.className.active).\n\t        filter('a[href=\"#' + $target.attr('id') + '\"]').\n\t        addClass(options.className.active);\n\t    }\n\t  }\n\t};\n\n\tScrollSpyNav.prototype.scrollProcess = function() {\n\t  var $links = this.$links;\n\t  var options = this.options;\n\n\t  // smoothScroll\n\t  if (options.smooth && $.fn.smoothScroll) {\n\t    $links.on('click', function(e) {\n\t      e.preventDefault();\n\n\t      var $this = $(this);\n\t      var $target = $($this.attr('href'));\n\n\t      if (!$target) {\n\t        return;\n\t      }\n\n\t      var offsetTop = options.offsetTop &&\n\t        !isNaN(parseInt(options.offsetTop)) && parseInt(options.offsetTop) || 0;\n\n\t      $(window).smoothScroll({position: $target.offset().top - offsetTop});\n\t    });\n\t  }\n\t};\n\n\t// ScrollSpyNav Plugin\n\tUI.plugin('scrollspynav', ScrollSpyNav);\n\n\t// Init code\n\tUI.ready(function(context) {\n\t  $('[data-am-scrollspy-nav]', context).scrollspynav();\n\t});\n\n\tmodule.exports = ScrollSpyNav;\n\n\t// TODO: 1. 算法改进\n\t//       2. 多级菜单支持\n\t//       3. smooth scroll pushState\n\n\n/***/ },\n/* 23 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\tvar rAF = UI.utils.rAF;\n\tvar cAF = UI.utils.cancelAF;\n\n\t/**\n\t * Smooth Scroll\n\t * @param position\n\t * @via http://mir.aculo.us/2014/01/19/scrolling-dom-elements-to-the-top-a-zepto-plugin/\n\t */\n\n\t// Usage: $(window).smoothScroll([options])\n\n\t// only allow one scroll to top operation to be in progress at a time,\n\t// which is probably what you want\n\tvar smoothScrollInProgress = false;\n\n\tvar SmoothScroll = function(element, options) {\n\t  options = options || {};\n\n\t  var $this = $(element);\n\t  var targetY = parseInt(options.position) || SmoothScroll.DEFAULTS.position;\n\t  var initialY = $this.scrollTop();\n\t  var lastY = initialY;\n\t  var delta = targetY - initialY;\n\t  // duration in ms, make it a bit shorter for short distances\n\t  // this is not scientific and you might want to adjust this for\n\t  // your preferences\n\t  var speed = options.speed ||\n\t      Math.min(750, Math.min(1500, Math.abs(initialY - targetY)));\n\t  // temp variables (t will be a position between 0 and 1, y is the calculated scrollTop)\n\t  var start;\n\t  var t;\n\t  var y;\n\t  var cancelScroll = function() {\n\t      abort();\n\t    };\n\n\t  // abort if already in progress or nothing to scroll\n\t  if (smoothScrollInProgress) {\n\t    return;\n\t  }\n\n\t  if (delta === 0) {\n\t    return;\n\t  }\n\n\t  // quint ease-in-out smoothing, from\n\t  // https://github.com/madrobby/scripty2/blob/master/src/effects/transitions/penner.js#L127-L136\n\t  function smooth(pos) {\n\t    if ((pos /= 0.5) < 1) {\n\t      return 0.5 * Math.pow(pos, 5);\n\t    }\n\n\t    return 0.5 * (Math.pow((pos - 2), 5) + 2);\n\t  }\n\n\t  function abort() {\n\t    $this.off('touchstart.smoothscroll.amui', cancelScroll);\n\t    smoothScrollInProgress = false;\n\t  }\n\n\t  // when there's a touch detected while scrolling is in progress, abort\n\t  // the scrolling (emulates native scrolling behavior)\n\t  $this.on('touchstart.smoothscroll.amui', cancelScroll);\n\t  smoothScrollInProgress = true;\n\n\t  // start rendering away! note the function given to frame\n\t  // is named \"render\" so we can reference it again further down\n\t  function render(now) {\n\t    if (!smoothScrollInProgress) {\n\t      return;\n\t    }\n\t    if (!start) {\n\t      start = now;\n\t    }\n\n\t    // calculate t, position of animation in [0..1]\n\t    t = Math.min(1, Math.max((now - start) / speed, 0));\n\t    // calculate the new scrollTop position (don't forget to smooth)\n\t    y = Math.round(initialY + delta * smooth(t));\n\t    // bracket scrollTop so we're never over-scrolling\n\t    if (delta > 0 && y > targetY) {\n\t      y = targetY;\n\t    }\n\t    if (delta < 0 && y < targetY) {\n\t      y = targetY;\n\t    }\n\n\t    // only actually set scrollTop if there was a change fromt he last frame\n\t    if (lastY != y) {\n\t      $this.scrollTop(y);\n\t    }\n\n\t    lastY = y;\n\t    // if we're not done yet, queue up an other frame to render,\n\t    // or clean up\n\t    if (y !== targetY) {\n\t      cAF(scrollRAF);\n\t      scrollRAF = rAF(render);\n\t    } else {\n\t      cAF(scrollRAF);\n\t      abort();\n\t    }\n\t  }\n\n\t  var scrollRAF = rAF(render);\n\t};\n\n\tSmoothScroll.DEFAULTS = {\n\t  position: 0\n\t};\n\n\t$.fn.smoothScroll = function(option) {\n\t  return this.each(function() {\n\t    new SmoothScroll(this, option);\n\t  });\n\t};\n\n\t// Init code\n\t$(document).on('click.smoothScroll.amui.data-api', '[data-am-smooth-scroll]',\n\t  function(e) {\n\t    e.preventDefault();\n\t    var options = UI.utils.parseOptions($(this).data('amSmoothScroll'));\n\n\t    $(window).smoothScroll(options);\n\t  });\n\n\tmodule.exports = SmoothScroll;\n\n\n/***/ },\n/* 24 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\t// require('./ui.dropdown');\n\n\t// Make jQuery :contains Case-Insensitive\n\t$.expr[':'].containsNC = function(elem, i, match, array) {\n\t  return (elem.textContent || elem.innerText || '').toLowerCase().\n\t      indexOf((match[3] || '').toLowerCase()) >= 0;\n\t};\n\n\t/**\n\t * Selected\n\t * @desc HTML select replacer\n\t * @via https://github.com/silviomoreto/bootstrap-select\n\t * @license https://github.com/silviomoreto/bootstrap-select/blob/master/LICENSE\n\t * @param element\n\t * @param options\n\t * @constructor\n\t */\n\n\tvar Selected = function(element, options) {\n\t  this.$element = $(element);\n\t  this.options = $.extend({}, Selected.DEFAULTS, {\n\t    placeholder: element.getAttribute('placeholder') ||\n\t    Selected.DEFAULTS.placeholder\n\t  }, options);\n\t  this.$originalOptions = this.$element.find('option');\n\t  this.multiple = element.multiple;\n\t  this.$selector = null;\n\t  this.initialized = false;\n\t  this.init();\n\t};\n\n\tSelected.DEFAULTS = {\n\t  btnWidth: null,\n\t  btnSize: null,\n\t  btnStyle: 'default',\n\t  dropUp: 0,\n\t  maxHeight: null,\n\t  maxChecked: null,\n\t  placeholder: '点击选择...',\n\t  selectedClass: 'am-checked',\n\t  disabledClass: 'am-disabled',\n\t  searchBox: false,\n\t  tpl: '<div class=\"am-selected am-dropdown ' +\n\t  '<%= dropUp ? \\'am-dropdown-up\\': \\'\\' %>\" id=\"<%= id %>\" data-am-dropdown>' +\n\t  '  <button type=\"button\" class=\"am-selected-btn am-btn am-dropdown-toggle\">' +\n\t  '    <span class=\"am-selected-status am-fl\"></span>' +\n\t  '    <i class=\"am-selected-icon am-icon-caret-' +\n\t  '<%= dropUp ? \\'up\\' : \\'down\\' %>\"></i>' +\n\t  '  </button>' +\n\t  '  <div class=\"am-selected-content am-dropdown-content\">' +\n\t  '    <h2 class=\"am-selected-header\">' +\n\t  '<span class=\"am-icon-chevron-left\">返回</span></h2>' +\n\t  '   <% if (searchBox) { %>' +\n\t  '   <div class=\"am-selected-search\">' +\n\t  '     <input autocomplete=\"off\" class=\"am-form-field am-input-sm\" />' +\n\t  '   </div>' +\n\t  '   <% } %>' +\n\t  '    <ul class=\"am-selected-list\">' +\n\t  '      <% for (var i = 0; i < options.length; i++) { %>' +\n\t  '       <% var option = options[i] %>' +\n\t  '       <% if (option.header) { %>' +\n\t  '  <li data-group=\"<%= option.group %>\" class=\"am-selected-list-header\">' +\n\t  '       <%= option.text %></li>' +\n\t  '       <% } else { %>' +\n\t  '       <li class=\"<%= option.classNames%>\" ' +\n\t  '         data-index=\"<%= option.index %>\" ' +\n\t  '         data-group=\"<%= option.group || 0 %>\" ' +\n\t  '         data-value=\"<%= option.value %>\" >' +\n\t  '         <span class=\"am-selected-text\"><%= option.text %></span>' +\n\t  '         <i class=\"am-icon-check\"></i></li>' +\n\t  '      <% } %>' +\n\t  '      <% } %>' +\n\t  '    </ul>' +\n\t  '    <div class=\"am-selected-hint\"></div>' +\n\t  '  </div>' +\n\t  '</div>',\n\t  listTpl:   '<% for (var i = 0; i < options.length; i++) { %>' +\n\t  '       <% var option = options[i] %>' +\n\t  '       <% if (option.header) { %>' +\n\t  '  <li data-group=\"<%= option.group %>\" class=\"am-selected-list-header\">' +\n\t  '       <%= option.text %></li>' +\n\t  '       <% } else { %>' +\n\t  '       <li class=\"<%= option.classNames %>\" ' +\n\t  '         data-index=\"<%= option.index %>\" ' +\n\t  '         data-group=\"<%= option.group || 0 %>\" ' +\n\t  '         data-value=\"<%= option.value %>\" >' +\n\t  '         <span class=\"am-selected-text\"><%= option.text %></span>' +\n\t  '         <i class=\"am-icon-check\"></i></li>' +\n\t  '      <% } %>' +\n\t  '      <% } %>'\n\t};\n\n\tSelected.prototype.init = function() {\n\t  var _this = this;\n\t  var $element = this.$element;\n\t  var options = this.options;\n\n\t  $element.hide();\n\n\t  var data = {\n\t    id: UI.utils.generateGUID('am-selected'),\n\t    multiple: this.multiple,\n\t    options: [],\n\t    searchBox: options.searchBox,\n\t    dropUp: options.dropUp,\n\t    placeholder: options.placeholder\n\t  };\n\n\t  this.$selector = $(UI.template(this.options.tpl, data));\n\t  // set select button styles\n\t  this.$selector.css({width: this.options.btnWidth});\n\n\t  if (this.$element[0].disabled) {\n\t    this.$selector.addClass(options.disabledClass);\n\t  }\n\n\t  this.$list = this.$selector.find('.am-selected-list');\n\t  this.$searchField = this.$selector.find('.am-selected-search input');\n\t  this.$hint = this.$selector.find('.am-selected-hint');\n\n\t  var $selectorBtn = this.$selector.find('.am-selected-btn');\n\t  var btnClassNames = [];\n\n\t  options.btnSize && btnClassNames.push('am-btn-' + options.btnSize);\n\t  options.btnStyle && btnClassNames.push('am-btn-' + options.btnStyle);\n\t  $selectorBtn.addClass(btnClassNames.join(' '));\n\n\t  this.$selector.dropdown({\n\t    justify: $selectorBtn\n\t  });\n\n\t  // set list height\n\t  if (options.maxHeight) {\n\t    this.$selector.find('.am-selected-list').css({\n\t      'max-height': options.maxHeight,\n\t      'overflow-y': 'scroll'\n\t    });\n\t  }\n\n\t  // set hint text\n\t  var hint = [];\n\t  var min = $element.attr('minchecked');\n\t  var max = $element.attr('maxchecked') || options.maxChecked;\n\n\t  this.maxChecked = max || Infinity;\n\n\t  if ($element[0].required) {\n\t    hint.push('必选');\n\t  }\n\n\t  if (min || max) {\n\t    min && hint.push('至少选择 ' + min + ' 项');\n\t    max && hint.push('至多选择 ' + max + ' 项');\n\t  }\n\n\t  this.$hint.text(hint.join('，'));\n\n\t  // render dropdown list\n\t  this.renderOptions();\n\n\t  // append $selector after <select>\n\t  this.$element.after(this.$selector);\n\t  this.dropdown = this.$selector.data('amui.dropdown');\n\t  this.$status = this.$selector.find('.am-selected-status');\n\n\t  // #try to fixes #476\n\t  setTimeout(function() {\n\t    _this.syncData();\n\t    _this.initialized = true;\n\t  }, 0);\n\n\t  this.bindEvents();\n\t};\n\n\tSelected.prototype.renderOptions = function() {\n\t  var $element = this.$element;\n\t  var options = this.options;\n\t  var optionItems = [];\n\t  var $optgroup = $element.find('optgroup');\n\t  this.$originalOptions = this.$element.find('option');\n\n\t  // 单选框使用 JS 禁用已经选择的 option 以后，\n\t  // 浏览器会重新选定第一个 option，但有一定延迟，致使 JS 获取 value 时返回 null\n\t  if (!this.multiple && ($element.val() === null)) {\n\t    this.$originalOptions.length &&\n\t    (this.$originalOptions.get(0).selected = true);\n\t  }\n\n\t  function pushOption(index, item, group) {\n\t    if (item.value === '') {\n\t      // skip to next iteration\n\t      // @see http://stackoverflow.com/questions/481601/how-to-skip-to-next-iteration-in-jquery-each-util\n\t      return true;\n\t    }\n\n\t    var classNames = '';\n\t    item.disabled && (classNames += options.disabledClass);\n\t    !item.disabled && item.selected && (classNames += options.selectedClass);\n\n\t    optionItems.push({\n\t      group: group,\n\t      index: index,\n\t      classNames: classNames,\n\t      text: item.text,\n\t      value: item.value\n\t    });\n\t  }\n\n\t  // select with option groups\n\t  if ($optgroup.length) {\n\t    $optgroup.each(function(i) {\n\t      // push group name\n\t      optionItems.push({\n\t        header: true,\n\t        group: i + 1,\n\t        text: this.label\n\t      });\n\n\t      $optgroup.eq(i).find('option').each(function(index, item) {\n\t        pushOption(index, item, i);\n\t      });\n\t    });\n\t  } else {\n\t    // without option groups\n\t    this.$originalOptions.each(function(index, item) {\n\t      pushOption(index, item, null);\n\t    });\n\t  }\n\n\t  this.$list.html(UI.template(options.listTpl, {options: optionItems}));\n\t  this.$shadowOptions = this.$list.find('> li').\n\t    not('.am-selected-list-header');\n\t};\n\n\tSelected.prototype.setChecked = function(item) {\n\t  var options = this.options;\n\t  var $item = $(item);\n\t  var isChecked = $item.hasClass(options.selectedClass);\n\n\t  if (this.multiple) {\n\t    // multiple\n\t    var checkedLength = this.$list.find('.' + options.selectedClass).length;\n\n\t    if (!isChecked && this.maxChecked <= checkedLength) {\n\t      this.$element.trigger('checkedOverflow.selected.amui', {\n\t        selected: this\n\t      });\n\n\t      return false;\n\t    }\n\t  } else {\n\t    if (isChecked) {\n\t      return false;\n\t    }\n\n\t    this.dropdown.close();\n\t    this.$shadowOptions.not($item).removeClass(options.selectedClass);\n\t  }\n\n\t  $item.toggleClass(options.selectedClass);\n\t  this.syncData(item);\n\t};\n\n\t/**\n\t * syncData\n\t * @desc if `item` set, only sync `item` related option\n\t * @param {Object} item\n\t */\n\tSelected.prototype.syncData = function(item) {\n\t  var _this = this;\n\t  var options = this.options;\n\t  var status = [];\n\t  var $checked = $([]);\n\n\t  this.$shadowOptions.filter('.' + options.selectedClass).each(function() {\n\t    var $this = $(this);\n\t    status.push($this.find('.am-selected-text').text());\n\n\t    if (!item) {\n\t      $checked = $checked.add(_this.$originalOptions\n\t        .filter('[value=\"' + $this.data('value') + '\"]')\n\t        .prop('selected', true));\n\t    }\n\t  });\n\n\t  if (item) {\n\t    var $item = $(item);\n\t    this.$originalOptions\n\t      .filter('[value=\"' + $item.data('value') + '\"]')\n\t      .prop('selected', $item.hasClass(options.selectedClass));\n\t  } else {\n\t    this.$originalOptions.not($checked).prop('selected', false);\n\t  }\n\n\t  // nothing selected\n\t  if (!this.$element.val()) {\n\t    status = [options.placeholder];\n\t  }\n\n\t  this.$status.text(status.join(', '));\n\n\t  // Do not trigger change event on initializing\n\t  this.initialized && this.$element.trigger('change');\n\t};\n\n\tSelected.prototype.bindEvents = function() {\n\t  var _this = this;\n\t  var header = 'am-selected-list-header';\n\t  var handleKeyup = UI.utils.debounce(function(e) {\n\t    _this.$shadowOptions.not('.' + header).hide().\n\t     filter(':containsNC(\"' + e.target.value + '\")').show();\n\t  }, 100);\n\n\t  this.$list.on('click', '> li', function(e) {\n\t    var $this = $(this);\n\t    !$this.hasClass(_this.options.disabledClass) &&\n\t      !$this.hasClass(header) && _this.setChecked(this);\n\t  });\n\n\t  // simple search with jQuery :contains\n\t  this.$searchField.on('keyup.selected.amui', handleKeyup);\n\n\t  // empty search keywords\n\t  this.$selector.on('closed.dropdown.amui', function() {\n\t    _this.$searchField.val('');\n\t    _this.$shadowOptions.css({display: ''});\n\t  });\n\n\t  // work with Validator\n\t  // @since 2.5\n\t  this.$element.on('validated.field.validator.amui', function(e) {\n\t    if (e.validity) {\n\t      var valid = e.validity.valid;\n\t      var errorClassName = 'am-invalid';\n\n\t      _this.$selector[(!valid ? 'add' : 'remove') + 'Class'](errorClassName);\n\t    }\n\t  });\n\n\t  // observe DOM\n\t  if (UI.support.mutationobserver) {\n\t    this.observer = new UI.support.mutationobserver(function() {\n\t      _this.$element.trigger('changed.selected.amui');\n\t    });\n\n\t    this.observer.observe(this.$element[0], {\n\t      childList: true,\n\t      attributes: true,\n\t      subtree: true,\n\t      characterData: true\n\t    });\n\t  }\n\n\t  // custom event\n\t  this.$element.on('changed.selected.amui', function() {\n\t    _this.renderOptions();\n\t    _this.syncData();\n\t  });\n\t};\n\n\t// @since: 2.5\n\tSelected.prototype.select = function(item) {\n\t  var $item;\n\n\t  if (typeof item === 'number') {\n\t    $item = this.$list.find('> li').not('.am-selected-list-header').eq(item);\n\t  } else if (typeof item === 'string') {\n\t    $item = this.$list.find(item);\n\t  } else {\n\t    $item = $(item);\n\t  }\n\n\t  $item.trigger('click');\n\t},\n\n\t// @since: 2.5\n\tSelected.prototype.enable = function() {\n\t  this.$element.prop('disable', false);\n\t  this.$selector.dropdown('enable');\n\t},\n\n\t// @since: 2.5\n\tSelected.prototype.disable = function() {\n\t  this.$element.prop('disable', true);\n\t  this.$selector.dropdown('disable');\n\t},\n\n\tSelected.prototype.destroy = function() {\n\t  this.$element.removeData('amui.selected').show();\n\t  this.$selector.remove();\n\t};\n\n\tUI.plugin('selected', Selected);\n\n\t// Conflict with jQuery form\n\t// https://github.com/malsup/form/blob/6bf24a5f6d8be65f4e5491863180c09356d9dadd/jquery.form.js#L1240-L1258\n\t// https://github.com/allmobilize/amazeui/issues/379\n\t// @deprecated: $.fn.selected = $.fn.selectIt = Plugin;\n\n\t// New way to resolve conflict:\n\t// @see https://github.com/amazeui/amazeui/issues/781#issuecomment-158873541\n\n\tUI.ready(function(context) {\n\t  $('[data-am-selected]', context).selected();\n\t});\n\n\tmodule.exports = Selected;\n\n\n/***/ },\n/* 25 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\t__webpack_require__(15);\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\tvar QRCode = __webpack_require__(26);\n\tvar doc = document;\n\tvar $doc = $(doc);\n\n\tvar Share = function(options) {\n\t  this.options = $.extend({}, Share.DEFAULTS, options || {});\n\t  this.$element = null;\n\t  this.$wechatQr = null;\n\t  this.pics = null;\n\t  this.inited = false;\n\t  this.active = false;\n\t  // this.init();\n\t};\n\n\tShare.DEFAULTS = {\n\t  sns: ['weibo', 'qq', 'qzone', 'tqq', 'wechat', 'renren'],\n\t  title: '分享到',\n\t  cancel: '取消',\n\t  closeOnShare: true,\n\t  id: UI.utils.generateGUID('am-share'),\n\t  desc: 'Hi，孤夜观天象，发现一个不错的西西，分享一下下 ;-)',\n\t  via: 'Amaze UI',\n\t  tpl: '<div class=\"am-share am-modal-actions\" id=\"<%= id %>\">' +\n\t  '<h3 class=\"am-share-title\"><%= title %></h3>' +\n\t  '<ul class=\"am-share-sns am-avg-sm-3\">' +\n\t  '<% for(var i = 0; i < sns.length; i++) {%>' +\n\t  '<li>' +\n\t  '<a href=\"<%= sns[i].shareUrl %>\" ' +\n\t  'data-am-share-to=\"<%= sns[i].id %>\" >' +\n\t  '<i class=\"am-icon-<%= sns[i].icon %>\"></i>' +\n\t  '<span><%= sns[i].title %></span>' +\n\t  '</a></li>' +\n\t  '<% } %></ul>' +\n\t  '<div class=\"am-share-footer\">' +\n\t  '<button class=\"am-btn am-btn-default am-btn-block\" ' +\n\t  'data-am-share-close><%= cancel %></button></div>' +\n\t  '</div>'\n\t};\n\n\tShare.SNS = {\n\t  weibo: {\n\t    title: '新浪微博',\n\t    url: 'http://service.weibo.com/share/share.php',\n\t    width: 620,\n\t    height: 450,\n\t    icon: 'weibo'\n\t  },\n\t  // url          链接地址\n\t  // title:”,     分享的文字内容(可选，默认为所在页面的title)\n\t  // appkey:”,    您申请的应用appkey,显示分享来源(可选)\n\t  // pic:”,       分享图片的路径(可选)\n\t  // ralateUid:”, 关联用户的UID，分享微博会@该用户(可选)\n\t  // NOTE: 会自动抓取图片，不用指定 pic\n\n\t  qq: {\n\t    title: 'QQ 好友',\n\t    url: 'http://connect.qq.com/widget/shareqq/index.html',\n\t    icon: 'qq'\n\t  },\n\t  // url:,\n\t  // title:'',    分享标题(可选)\n\t  // pics:'',     分享图片的路径(可选)\n\t  // summary:'',  分享摘要(可选)\n\t  // site:'',     分享来源 如：腾讯网(可选)\n\t  // desc: ''     发送给用户的消息\n\t  // NOTE: 经过测试，最终发给用户的只有 url 和 desc\n\n\t  qzone: {\n\t    title: 'QQ 空间',\n\t    url: 'http://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey',\n\t    icon: 'star'\n\t  },\n\t  // http://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?url=xxx&title=xxx&desc=&summary=&site=\n\t  // url:,\n\t  // title:'',    分享标题(可选)\n\t  // desc:'',     默认分享理由(可选)\n\t  // summary:'',  分享摘要(可选)\n\t  // site:'',     分享来源 如：腾讯网(可选)\n\t  // pics:'',     分享图片的路径(可选)，不会自动抓取，多个图片用|分隔\n\n\t  tqq: {\n\t    title: '腾讯微博',\n\t    url: 'http://v.t.qq.com/share/share.php',\n\t    icon: 'tencent-weibo'\n\t  },\n\t  // url=xx&title=&appkey=801cf76d3cfc44ada52ec13114e84a96\n\t  // url\n\t  // title\n\t  // pic 多个图片用 | 分隔\n\t  // appkey\n\t  // NOTE: 不会自动抓取图片\n\n\t  wechat: {\n\t    title: '微信',\n\t    url: '[qrcode]',\n\t    icon: 'wechat'\n\t  },\n\t  // 生成一个二维码 供用户扫描\n\t  // 相关接口 https://github.com/zxlie/WeixinApi\n\n\t  renren: {\n\t    title: '人人网',\n\t    url: 'http://widget.renren.com/dialog/share',\n\t    icon: 'renren'\n\t  },\n\t  // http://widget.renren.com/dialog/share?resourceUrl=www&srcUrl=www&title=ww&description=xxx\n\t  // 550 * 400\n\t  // resourceUrl : '', // 分享的资源Url\n\t  // srcUrl : '',\t     // 分享的资源来源Url,\n\t  //                   //   默认为header中的Referer,如果分享失败可以调整此值为resourceUrl试试\n\t  // pic : '',\t\t // 分享的主题图片，会自动抓取\n\t  // title : '',\t\t // 分享的标题\n\t  // description : ''\t // 分享的详细描述\n\t  // NOTE: 经过测试，直接使用 url 参数即可\n\n\t  douban: {\n\t    title: '豆瓣',\n\t    url: 'http://www.douban.com/recommend/',\n\t    icon: 'share-alt'\n\t  },\n\t  // http://www.douban.com/service/sharebutton\n\t  // 450 * 330\n\t  // http://www.douban.com/share/service?bm=1&image=&href=xxx&updated=&name=\n\t  // href 链接\n\t  // name 标题\n\n\t  /* void (function() {\n\t   var d = document, e = encodeURIComponent,\n\t   s1 = window.getSelection, s2 = d.getSelection,\n\t   s3 = d.selection, s = s1 ? s1()\n\t   : s2 ? s2() : s3 ? s3.createRange().text : '',\n\t   r = 'http://www.douban.com/recommend/?url=&title=&sel=&v=1&r=1'\n\t   })();\n\t   */\n\n\t  // tsohu: '',\n\t  // http://t.sohu.com/third/post.jsp?url=&title=&content=utf-8&pic=\n\n\t  // print: '',\n\n\t  mail: {\n\t    title: '邮件分享',\n\t    url: 'mailto:',\n\t    icon: 'envelope-o'\n\t  },\n\n\t  sms: {\n\t    title: '短信分享',\n\t    url: 'sms:',\n\t    icon: 'comment'\n\t  }\n\t};\n\n\tShare.prototype.render = function() {\n\t  var options = this.options;\n\t  var snsData = [];\n\t  var title = encodeURIComponent(doc.title);\n\t  var link = encodeURIComponent(doc.location);\n\t  var msgBody = '?body=' + title + link;\n\n\t  options.sns.forEach(function(item, i) {\n\t    if (Share.SNS[item]) {\n\t      var tmp = Share.SNS[item];\n\t      var shareUrl;\n\n\t      tmp.id = item;\n\n\t      if (item === 'mail') {\n\t        shareUrl = msgBody + '&subject=' + options.desc;\n\t      } else if (item === 'sms') {\n\t        shareUrl = msgBody;\n\t      } else {\n\t        shareUrl = '?url=' + link + '&title=' + title;\n\t      }\n\n\t      tmp.shareUrl = tmp.url + shareUrl;\n\n\t      snsData.push(tmp);\n\t    }\n\t  });\n\n\t  return UI.template(options.tpl, $.extend({}, options, {sns: snsData}));\n\t};\n\n\tShare.prototype.init = function() {\n\t  if (this.inited) {\n\t    return;\n\t  }\n\n\t  var me = this;\n\t  var shareItem = '[data-am-share-to]';\n\n\t  $doc.ready($.proxy(function() {\n\t    $('body').append(this.render()); // append share DOM to body\n\t    this.$element = $('#' + this.options.id);\n\n\t    this.$element.find('[data-am-share-close]').\n\t      on('click.share.amui', function() {\n\t        me.close();\n\t      });\n\t  }, this));\n\n\t  $doc.on('click.share.amui', shareItem, $.proxy(function(e) {\n\t    var $clicked = $(e.target);\n\t    var $target = $clicked.is(shareItem) && $clicked ||\n\t      $clicked.parent(shareItem);\n\t    var sns = $target.attr('data-am-share-to');\n\n\t    if (!(sns === 'mail' || sns === 'sms')) {\n\t      e.preventDefault();\n\t      this.shareTo(sns, this.setData(sns));\n\t    }\n\n\t    this.close();\n\t  }, this));\n\n\t  this.inited = true;\n\t};\n\n\tShare.prototype.open = function() {\n\t  !this.inited && this.init();\n\t  this.$element && this.$element.modal('open');\n\t  this.$element.trigger('open.share.amui');\n\t  this.active = true;\n\t};\n\n\tShare.prototype.close = function() {\n\t  this.$element && this.$element.modal('close');\n\t  this.$element.trigger('close.share.amui');\n\t  this.active = false;\n\t};\n\n\tShare.prototype.toggle = function() {\n\t  this.active ? this.close() : this.open();\n\t};\n\n\tShare.prototype.setData = function(sns) {\n\t  if (!sns) {\n\t    return;\n\t  }\n\n\t  var shareData = {\n\t    url: doc.location,\n\t    title: doc.title\n\t  };\n\t  var desc = this.options.desc;\n\t  var imgSrc = this.pics || [];\n\t  var qqReg = /^(qzone|qq|tqq)$/;\n\n\t  if (qqReg.test(sns) && !imgSrc.length) {\n\t    var allImages = doc.images;\n\n\t    for (var i = 0; i < allImages.length && i < 10; i++) {\n\t      !!allImages[i].src && imgSrc.push(encodeURIComponent(allImages[i].src));\n\t    }\n\n\t    this.pics = imgSrc; // 缓存图片\n\t  }\n\n\t  switch (sns) {\n\t    case 'qzone':\n\t      shareData.desc = desc;\n\t      shareData.site = this.options.via;\n\t      shareData.pics = imgSrc.join('|');\n\t      // TODO: 抓取图片多张\n\t      break;\n\t    case 'qq':\n\t      shareData.desc = desc;\n\t      shareData.site = this.options.via;\n\t      shareData.pics = imgSrc[0];\n\t      // 抓取一张图片\n\t      break;\n\t    case 'tqq':\n\t      // 抓取图片多张\n\t      shareData.pic = imgSrc.join('|');\n\t      break;\n\t  }\n\n\t  return shareData;\n\t};\n\n\tShare.prototype.shareTo = function(sns, data) {\n\t  var snsInfo = Share.SNS[sns];\n\n\t  if (!snsInfo) {\n\t    return;\n\t  }\n\n\t  if (sns === 'wechat' || sns === 'weixin') {\n\t    return this.wechatQr();\n\t  }\n\n\t  var query = [];\n\t  for (var key in data) {\n\t    if (data[key]) {\n\t      // 避免 encode 图片分隔符 |\n\t      query.push(key.toString() + '=' + ((key === 'pic' || key === 'pics') ?\n\t        data[key] : encodeURIComponent(data[key])));\n\t    }\n\t  }\n\n\t  window.open(snsInfo.url + '?' + query.join('&'));\n\t};\n\n\tShare.prototype.wechatQr = function() {\n\t  if (!this.$wechatQr) {\n\t    var qrId = UI.utils.generateGUID('am-share-wechat');\n\t    var $qr = $('<div class=\"am-modal am-modal-no-btn am-share-wechat-qr\">' +\n\t    '<div class=\"am-modal-dialog\"><div class=\"am-modal-hd\">分享到微信 ' +\n\t    '<a href=\"\" class=\"am-close am-close-spin\" ' +\n\t    'data-am-modal-close>&times;</a> </div>' +\n\t    '<div class=\"am-modal-bd\">' +\n\t    '<div class=\"am-share-wx-qr\"></div>' +\n\t    '<div class=\"am-share-wechat-tip\">' +\n\t    '打开微信，点击底部的<em>发现</em>，<br/> ' +\n\t    '使用<em>扫一扫</em>将网页分享至朋友圈</div></div></div></div>');\n\n\t    $qr.attr('id', qrId);\n\n\t    var qrNode = new QRCode({\n\t      render: 'canvas',\n\t      correctLevel: 0,\n\t      text: doc.location.href,\n\t      width: 180,\n\t      height: 180,\n\t      background: '#fff',\n\t      foreground: '#000'\n\t    });\n\n\t    $qr.find('.am-share-wx-qr').html(qrNode);\n\n\t    $qr.appendTo($('body'));\n\n\t    this.$wechatQr = $('#' + qrId);\n\t  }\n\n\t  this.$wechatQr.modal('open');\n\t};\n\n\tvar share = new Share();\n\n\t$doc.on('click.share.amui.data-api', '[data-am-toggle=\"share\"]', function(e) {\n\t  e.preventDefault();\n\t  share.toggle();\n\t});\n\n\tmodule.exports = UI.share = share;\n\n\n/***/ },\n/* 26 */\n/***/ function(module, exports, __webpack_require__) {\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\n\t/**\n\t * @ver 1.1.0\n\t * @via https://github.com/aralejs/qrcode/blob/master/src/qrcode.js\n\t * @license http://aralejs.org/\n\t */\n\n\tvar qrcodeAlgObjCache = [];\n\n\t/**\n\t * 二维码构造函数，主要用于绘制\n\t * @param  {Object} opt 传递参数\n\t * @return {String} qrcode\n\t * @constructor\n\t */\n\tvar QRCode = function(opt) {\n\t  if (typeof opt === 'string') { // 只编码ASCII字符串\n\t    opt = {\n\t      text: opt\n\t    };\n\t  }\n\t  // 设置默认参数\n\t  this.options = $.extend({}, {\n\t    text: \"\",\n\t    render: \"\",\n\t    width: 256,\n\t    height: 256,\n\t    correctLevel: 3,\n\t    background: \"#ffffff\",\n\t    foreground: \"#000000\"\n\t  }, opt);\n\n\t  // 使用QRCodeAlg创建二维码结构\n\t  var qrCodeAlg = null;\n\t  for (var i = 0, l = qrcodeAlgObjCache.length; i < l; i++) {\n\t    if (qrcodeAlgObjCache[i].text == this.options.text && qrcodeAlgObjCache[i].text.correctLevel == this.options.correctLevel) {\n\t      qrCodeAlg = qrcodeAlgObjCache[i].obj;\n\t      break;\n\t    }\n\t  }\n\t  if (i == l) {\n\t    qrCodeAlg = new QRCodeAlg(this.options.text, this.options.correctLevel);\n\t    qrcodeAlgObjCache.push({\n\t      text: this.options.text,\n\t      correctLevel: this.options.correctLevel,\n\t      obj: qrCodeAlg\n\t    });\n\t  }\n\n\t  if (this.options.render) {\n\t    switch (this.options.render) {\n\t      case \"canvas\":\n\t        return this.createCanvas(qrCodeAlg);\n\t      case \"table\":\n\t        return this.createTable(qrCodeAlg);\n\t      case \"svg\":\n\t        return this.createSVG(qrCodeAlg);\n\t      default:\n\t        return this.createDefault(qrCodeAlg);\n\t    }\n\t  }\n\t  return this.createDefault(qrCodeAlg);\n\t};\n\t/**\n\t * 使用Canvas来画二维码\n\t * @return {}\n\t */\n\n\tQRCode.prototype.createDefault = function(qrCodeAlg) {\n\t  var canvas = document.createElement('canvas');\n\t  if (canvas.getContext)\n\t    return this.createCanvas(qrCodeAlg);\n\t  if (!!document.createElementNS && !!document.createElementNS(SVG_NS, 'svg').createSVGRect)\n\t    return this.createSVG(qrCodeAlg);\n\t  return this.createTable(qrCodeAlg);\n\t};\n\tQRCode.prototype.createCanvas = function(qrCodeAlg) {\n\t  //创建canvas节点\n\t  var canvas = document.createElement('canvas');\n\t  canvas.width = this.options.width;\n\t  canvas.height = this.options.height;\n\t  var ctx = canvas.getContext('2d');\n\n\t  //计算每个点的长宽\n\t  var tileW = (this.options.width / qrCodeAlg.getModuleCount()).toPrecision(4);\n\t  var tileH = this.options.height / qrCodeAlg.getModuleCount().toPrecision(4);\n\n\t  //绘制\n\t  for (var row = 0; row < qrCodeAlg.getModuleCount(); row++) {\n\t    for (var col = 0; col < qrCodeAlg.getModuleCount(); col++) {\n\t      ctx.fillStyle = qrCodeAlg.modules[row][col] ? this.options.foreground : this.options.background;\n\t      var w = (Math.ceil((col + 1) * tileW) - Math.floor(col * tileW));\n\t      var h = (Math.ceil((row + 1) * tileW) - Math.floor(row * tileW));\n\t      ctx.fillRect(Math.round(col * tileW), Math.round(row * tileH), w, h);\n\t    }\n\t  }\n\t  //返回绘制的节点\n\t  return canvas;\n\t};\n\t/**\n\t * 使用table来绘制二维码\n\t * @return {}\n\t */\n\tQRCode.prototype.createTable = function(qrCodeAlg) {\n\t  //创建table节点\n\t  var s = [];\n\t  s.push('<table style=\"border:0px; margin:0px; padding:0px; border-collapse:collapse; background-color: ' +\n\t  this.options.background +\n\t  ';\">');\n\t  // 计算每个节点的长宽；取整，防止点之间出现分离\n\t  var tileW = -1, tileH = -1, caculateW = -1, caculateH = -1;\n\t  tileW = caculateW = Math.floor(this.options.width / qrCodeAlg.getModuleCount());\n\t  tileH = caculateH = Math.floor(this.options.height / qrCodeAlg.getModuleCount());\n\t  if (caculateW <= 0) {\n\t    if (qrCodeAlg.getModuleCount() < 80) {\n\t      tileW = 2;\n\t    } else {\n\t      tileW = 1;\n\t    }\n\t  }\n\t  if (caculateH <= 0) {\n\t    if (qrCodeAlg.getModuleCount() < 80) {\n\t      tileH = 2;\n\t    } else {\n\t      tileH = 1;\n\t    }\n\t  }\n\n\t  // 绘制二维码\n\t  foreTd = '<td style=\"border:0px; margin:0px; padding:0px; width:' + tileW + 'px; background-color: ' + this.options.foreground + '\"></td>',\n\t    backTd = '<td style=\"border:0px; margin:0px; padding:0px; width:' + tileW + 'px; background-color: ' + this.options.background + '\"></td>',\n\t    l = qrCodeAlg.getModuleCount();\n\n\t  for (var row = 0; row < l; row++) {\n\t    s.push('<tr style=\"border:0px; margin:0px; padding:0px; height: ' + tileH + 'px\">');\n\t    for (var col = 0; col < l; col++) {\n\t      s.push(qrCodeAlg.modules[row][col] ? foreTd : backTd);\n\t    }\n\t    s.push('</tr>');\n\t  }\n\t  s.push('</table>');\n\t  var span = document.createElement(\"span\");\n\t  span.innerHTML = s.join('');\n\n\t  return span.firstChild;\n\t};\n\n\t/**\n\t * 使用SVG开绘制二维码\n\t * @return {}\n\t */\n\tQRCode.prototype.createSVG = function(qrCodeAlg) {\n\t  var x, dx, y, dy,\n\t    moduleCount = qrCodeAlg.getModuleCount(),\n\t    scale = this.options.height / this.options.width,\n\t    svg = '<svg xmlns=\"http://www.w3.org/2000/svg\" '\n\t      + 'width=\"' + this.options.width + 'px\" height=\"' + this.options.height + 'px\" '\n\t      + 'viewbox=\"0 0 ' + moduleCount * 10 + ' ' + moduleCount * 10 * scale + '\">',\n\t    rectHead = '<path ',\n\t    foreRect = ' style=\"stroke-width:0.5;stroke:' + this.options.foreground\n\t      + ';fill:' + this.options.foreground + ';\"></path>',\n\t    backRect = ' style=\"stroke-width:0.5;stroke:' + this.options.background\n\t      + ';fill:' + this.options.background + ';\"></path>';\n\n\t  // draw in the svg\n\t  for (var row = 0; row < moduleCount; row++) {\n\t    for (var col = 0; col < moduleCount; col++) {\n\t      x = col * 10;\n\t      y = row * 10 * scale;\n\t      dx = (col + 1) * 10;\n\t      dy = (row + 1) * 10 * scale;\n\n\t      svg += rectHead + 'd=\"M ' + x + ',' + y\n\t      + ' L ' + dx + ',' + y\n\t      + ' L ' + dx + ',' + dy\n\t      + ' L ' + x + ',' + dy\n\t      + ' Z\"';\n\n\t      svg += qrCodeAlg.modules[row][col] ? foreRect : backRect;\n\t    }\n\t  }\n\n\t  svg += '</svg>';\n\n\t  // return just built svg\n\t  return $(svg)[0];\n\t};\n\n\t/**\n\t * 获取单个字符的utf8编码\n\t * unicode BMP平面约65535个字符\n\t * @param {num} code\n\t * return {array}\n\t */\n\tfunction unicodeFormat8(code) {\n\t  // 1 byte\n\t  if (code < 128) {\n\t    return [code];\n\t    // 2 bytes\n\t  } else if (code < 2048) {\n\t    c0 = 192 + (code >> 6);\n\t    c1 = 128 + (code & 63);\n\t    return [c0, c1];\n\t    // 3 bytes\n\t  } else {\n\t    c0 = 224 + (code >> 12);\n\t    c1 = 128 + (code >> 6 & 63);\n\t    c2 = 128 + (code & 63);\n\t    return [c0, c1, c2];\n\t  }\n\t}\n\n\t/**\n\t * 获取字符串的utf8编码字节串\n\t * @param {string} string\n\t * @return {array}\n\t */\n\tfunction getUTF8Bytes(string) {\n\t  var utf8codes = [];\n\t  for (var i = 0; i < string.length; i++) {\n\t    var code = string.charCodeAt(i);\n\t    var utf8 = unicodeFormat8(code);\n\t    for (var j = 0; j < utf8.length; j++) {\n\t      utf8codes.push(utf8[j]);\n\t    }\n\t  }\n\t  return utf8codes;\n\t}\n\n\t/**\n\t * 二维码算法实现\n\t * @param {string} data              要编码的信息字符串\n\t * @param {num} errorCorrectLevel 纠错等级\n\t */\n\tfunction QRCodeAlg(data, errorCorrectLevel) {\n\t  this.typeNumber = -1; // 版本\n\t  this.errorCorrectLevel = errorCorrectLevel;\n\t  this.modules = null;  // 二维矩阵，存放最终结果\n\t  this.moduleCount = 0; // 矩阵大小\n\t  this.dataCache = null; // 数据缓存\n\t  this.rsBlocks = null; // 版本数据信息\n\t  this.totalDataCount = -1; // 可使用的数据量\n\t  this.data = data;\n\t  this.utf8bytes = getUTF8Bytes(data);\n\t  this.make();\n\t}\n\n\tQRCodeAlg.prototype = {\n\t  constructor: QRCodeAlg,\n\t  /**\n\t   * 获取二维码矩阵大小\n\t   * @return {num} 矩阵大小\n\t   */\n\t  getModuleCount: function() {\n\t    return this.moduleCount;\n\t  },\n\t  /**\n\t   * 编码\n\t   */\n\t  make: function() {\n\t    this.getRightType();\n\t    this.dataCache = this.createData();\n\t    this.createQrcode();\n\t  },\n\t  /**\n\t   * 设置二位矩阵功能图形\n\t   * @param  {bool} test 表示是否在寻找最好掩膜阶段\n\t   * @param  {num} maskPattern 掩膜的版本\n\t   */\n\t  makeImpl: function(maskPattern) {\n\n\t    this.moduleCount = this.typeNumber * 4 + 17;\n\t    this.modules = new Array(this.moduleCount);\n\n\t    for (var row = 0; row < this.moduleCount; row++) {\n\n\t      this.modules[row] = new Array(this.moduleCount);\n\n\t    }\n\t    this.setupPositionProbePattern(0, 0);\n\t    this.setupPositionProbePattern(this.moduleCount - 7, 0);\n\t    this.setupPositionProbePattern(0, this.moduleCount - 7);\n\t    this.setupPositionAdjustPattern();\n\t    this.setupTimingPattern();\n\t    this.setupTypeInfo(true, maskPattern);\n\n\t    if (this.typeNumber >= 7) {\n\t      this.setupTypeNumber(true);\n\t    }\n\t    this.mapData(this.dataCache, maskPattern);\n\t  },\n\t  /**\n\t   * 设置二维码的位置探测图形\n\t   * @param  {num} row 探测图形的中心横坐标\n\t   * @param  {num} col 探测图形的中心纵坐标\n\t   */\n\t  setupPositionProbePattern: function(row, col) {\n\n\t    for (var r = -1; r <= 7; r++) {\n\n\t      if (row + r <= -1 || this.moduleCount <= row + r) continue;\n\n\t      for (var c = -1; c <= 7; c++) {\n\n\t        if (col + c <= -1 || this.moduleCount <= col + c) continue;\n\n\t        if ((0 <= r && r <= 6 && (c == 0 || c == 6)) || (0 <= c && c <= 6 && (r == 0 || r == 6)) || (2 <= r && r <= 4 && 2 <= c && c <= 4)) {\n\t          this.modules[row + r][col + c] = true;\n\t        } else {\n\t          this.modules[row + r][col + c] = false;\n\t        }\n\t      }\n\t    }\n\t  },\n\t  /**\n\t   * 创建二维码\n\t   * @return {[type]} [description]\n\t   */\n\t  createQrcode: function() {\n\n\t    var minLostPoint = 0;\n\t    var pattern = 0;\n\t    var bestModules = null;\n\n\t    for (var i = 0; i < 8; i++) {\n\n\t      this.makeImpl(i);\n\n\t      var lostPoint = QRUtil.getLostPoint(this);\n\t      if (i == 0 || minLostPoint > lostPoint) {\n\t        minLostPoint = lostPoint;\n\t        pattern = i;\n\t        bestModules = this.modules;\n\t      }\n\t    }\n\t    this.modules = bestModules;\n\t    this.setupTypeInfo(false, pattern);\n\n\t    if (this.typeNumber >= 7) {\n\t      this.setupTypeNumber(false);\n\t    }\n\n\t  },\n\t  /**\n\t   * 设置定位图形\n\t   * @return {[type]} [description]\n\t   */\n\t  setupTimingPattern: function() {\n\n\t    for (var r = 8; r < this.moduleCount - 8; r++) {\n\t      if (this.modules[r][6] != null) {\n\t        continue;\n\t      }\n\t      this.modules[r][6] = (r % 2 == 0);\n\n\t      if (this.modules[6][r] != null) {\n\t        continue;\n\t      }\n\t      this.modules[6][r] = (r % 2 == 0);\n\t    }\n\t  },\n\t  /**\n\t   * 设置矫正图形\n\t   * @return {[type]} [description]\n\t   */\n\t  setupPositionAdjustPattern: function() {\n\n\t    var pos = QRUtil.getPatternPosition(this.typeNumber);\n\n\t    for (var i = 0; i < pos.length; i++) {\n\n\t      for (var j = 0; j < pos.length; j++) {\n\n\t        var row = pos[i];\n\t        var col = pos[j];\n\n\t        if (this.modules[row][col] != null) {\n\t          continue;\n\t        }\n\n\t        for (var r = -2; r <= 2; r++) {\n\n\t          for (var c = -2; c <= 2; c++) {\n\n\t            if (r == -2 || r == 2 || c == -2 || c == 2 || (r == 0 && c == 0)) {\n\t              this.modules[row + r][col + c] = true;\n\t            } else {\n\t              this.modules[row + r][col + c] = false;\n\t            }\n\t          }\n\t        }\n\t      }\n\t    }\n\t  },\n\t  /**\n\t   * 设置版本信息（7以上版本才有）\n\t   * @param  {bool} test 是否处于判断最佳掩膜阶段\n\t   * @return {[type]}      [description]\n\t   */\n\t  setupTypeNumber: function(test) {\n\n\t    var bits = QRUtil.getBCHTypeNumber(this.typeNumber);\n\n\t    for (var i = 0; i < 18; i++) {\n\t      var mod = (!test && ((bits >> i) & 1) == 1);\n\t      this.modules[Math.floor(i / 3)][i % 3 + this.moduleCount - 8 - 3] = mod;\n\t      this.modules[i % 3 + this.moduleCount - 8 - 3][Math.floor(i / 3)] = mod;\n\t    }\n\t  },\n\t  /**\n\t   * 设置格式信息（纠错等级和掩膜版本）\n\t   * @param  {bool} test\n\t   * @param  {num} maskPattern 掩膜版本\n\t   * @return {}\n\t   */\n\t  setupTypeInfo: function(test, maskPattern) {\n\n\t    var data = (QRErrorCorrectLevel[this.errorCorrectLevel] << 3) | maskPattern;\n\t    var bits = QRUtil.getBCHTypeInfo(data);\n\n\t    // vertical\n\t    for (var i = 0; i < 15; i++) {\n\n\t      var mod = (!test && ((bits >> i) & 1) == 1);\n\n\t      if (i < 6) {\n\t        this.modules[i][8] = mod;\n\t      } else if (i < 8) {\n\t        this.modules[i + 1][8] = mod;\n\t      } else {\n\t        this.modules[this.moduleCount - 15 + i][8] = mod;\n\t      }\n\n\t      // horizontal\n\t      var mod = (!test && ((bits >> i) & 1) == 1);\n\n\t      if (i < 8) {\n\t        this.modules[8][this.moduleCount - i - 1] = mod;\n\t      } else if (i < 9) {\n\t        this.modules[8][15 - i - 1 + 1] = mod;\n\t      } else {\n\t        this.modules[8][15 - i - 1] = mod;\n\t      }\n\t    }\n\n\t    // fixed module\n\t    this.modules[this.moduleCount - 8][8] = (!test);\n\n\t  },\n\t  /**\n\t   * 数据编码\n\t   * @return {[type]} [description]\n\t   */\n\t  createData: function() {\n\t    var buffer = new QRBitBuffer();\n\t    var lengthBits = this.typeNumber > 9 ? 16 : 8;\n\t    buffer.put(4, 4); //添加模式\n\t    buffer.put(this.utf8bytes.length, lengthBits);\n\t    for (var i = 0, l = this.utf8bytes.length; i < l; i++) {\n\t      buffer.put(this.utf8bytes[i], 8);\n\t    }\n\t    if (buffer.length + 4 <= this.totalDataCount * 8) {\n\t      buffer.put(0, 4);\n\t    }\n\n\t    // padding\n\t    while (buffer.length % 8 != 0) {\n\t      buffer.putBit(false);\n\t    }\n\n\t    // padding\n\t    while (true) {\n\n\t      if (buffer.length >= this.totalDataCount * 8) {\n\t        break;\n\t      }\n\t      buffer.put(QRCodeAlg.PAD0, 8);\n\n\t      if (buffer.length >= this.totalDataCount * 8) {\n\t        break;\n\t      }\n\t      buffer.put(QRCodeAlg.PAD1, 8);\n\t    }\n\t    return this.createBytes(buffer);\n\t  },\n\t  /**\n\t   * 纠错码编码\n\t   * @param  {buffer} buffer 数据编码\n\t   * @return {[type]}\n\t   */\n\t  createBytes: function(buffer) {\n\n\t    var offset = 0;\n\n\t    var maxDcCount = 0;\n\t    var maxEcCount = 0;\n\n\t    var length = this.rsBlock.length / 3;\n\n\t    var rsBlocks = new Array();\n\n\t    for (var i = 0; i < length; i++) {\n\n\t      var count = this.rsBlock[i * 3 + 0];\n\t      var totalCount = this.rsBlock[i * 3 + 1];\n\t      var dataCount = this.rsBlock[i * 3 + 2];\n\n\t      for (var j = 0; j < count; j++) {\n\t        rsBlocks.push([dataCount, totalCount]);\n\t      }\n\t    }\n\n\t    var dcdata = new Array(rsBlocks.length);\n\t    var ecdata = new Array(rsBlocks.length);\n\n\t    for (var r = 0; r < rsBlocks.length; r++) {\n\n\t      var dcCount = rsBlocks[r][0];\n\t      var ecCount = rsBlocks[r][1] - dcCount;\n\n\t      maxDcCount = Math.max(maxDcCount, dcCount);\n\t      maxEcCount = Math.max(maxEcCount, ecCount);\n\n\t      dcdata[r] = new Array(dcCount);\n\n\t      for (var i = 0; i < dcdata[r].length; i++) {\n\t        dcdata[r][i] = 0xff & buffer.buffer[i + offset];\n\t      }\n\t      offset += dcCount;\n\n\t      var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount);\n\t      var rawPoly = new QRPolynomial(dcdata[r], rsPoly.getLength() - 1);\n\n\t      var modPoly = rawPoly.mod(rsPoly);\n\t      ecdata[r] = new Array(rsPoly.getLength() - 1);\n\t      for (var i = 0; i < ecdata[r].length; i++) {\n\t        var modIndex = i + modPoly.getLength() - ecdata[r].length;\n\t        ecdata[r][i] = (modIndex >= 0) ? modPoly.get(modIndex) : 0;\n\t      }\n\t    }\n\n\t    var data = new Array(this.totalDataCount);\n\t    var index = 0;\n\n\t    for (var i = 0; i < maxDcCount; i++) {\n\t      for (var r = 0; r < rsBlocks.length; r++) {\n\t        if (i < dcdata[r].length) {\n\t          data[index++] = dcdata[r][i];\n\t        }\n\t      }\n\t    }\n\n\t    for (var i = 0; i < maxEcCount; i++) {\n\t      for (var r = 0; r < rsBlocks.length; r++) {\n\t        if (i < ecdata[r].length) {\n\t          data[index++] = ecdata[r][i];\n\t        }\n\t      }\n\t    }\n\n\t    return data;\n\n\t  },\n\t  /**\n\t   * 布置模块，构建最终信息\n\t   * @param  {} data\n\t   * @param  {} maskPattern\n\t   * @return {}\n\t   */\n\t  mapData: function(data, maskPattern) {\n\n\t    var inc = -1;\n\t    var row = this.moduleCount - 1;\n\t    var bitIndex = 7;\n\t    var byteIndex = 0;\n\n\t    for (var col = this.moduleCount - 1; col > 0; col -= 2) {\n\n\t      if (col == 6) col--;\n\n\t      while (true) {\n\n\t        for (var c = 0; c < 2; c++) {\n\n\t          if (this.modules[row][col - c] == null) {\n\n\t            var dark = false;\n\n\t            if (byteIndex < data.length) {\n\t              dark = (((data[byteIndex] >>> bitIndex) & 1) == 1);\n\t            }\n\n\t            var mask = QRUtil.getMask(maskPattern, row, col - c);\n\n\t            if (mask) {\n\t              dark = !dark;\n\t            }\n\n\t            this.modules[row][col - c] = dark;\n\t            bitIndex--;\n\n\t            if (bitIndex == -1) {\n\t              byteIndex++;\n\t              bitIndex = 7;\n\t            }\n\t          }\n\t        }\n\n\t        row += inc;\n\n\t        if (row < 0 || this.moduleCount <= row) {\n\t          row -= inc;\n\t          inc = -inc;\n\t          break;\n\t        }\n\t      }\n\t    }\n\t  }\n\n\t};\n\t/**\n\t * 填充字段\n\t */\n\tQRCodeAlg.PAD0 = 0xEC;\n\tQRCodeAlg.PAD1 = 0x11;\n\n\n\t//---------------------------------------------------------------------\n\t// 纠错等级对应的编码\n\t//---------------------------------------------------------------------\n\n\tvar QRErrorCorrectLevel = [1, 0, 3, 2];\n\n\t//---------------------------------------------------------------------\n\t// 掩膜版本\n\t//---------------------------------------------------------------------\n\n\tvar QRMaskPattern = {\n\t  PATTERN000: 0,\n\t  PATTERN001: 1,\n\t  PATTERN010: 2,\n\t  PATTERN011: 3,\n\t  PATTERN100: 4,\n\t  PATTERN101: 5,\n\t  PATTERN110: 6,\n\t  PATTERN111: 7\n\t};\n\n\t//---------------------------------------------------------------------\n\t// 工具类\n\t//---------------------------------------------------------------------\n\n\tvar QRUtil = {\n\n\t  /*\n\t   每个版本矫正图形的位置\n\t   */\n\t  PATTERN_POSITION_TABLE: [\n\t    [],\n\t    [6, 18],\n\t    [6, 22],\n\t    [6, 26],\n\t    [6, 30],\n\t    [6, 34],\n\t    [6, 22, 38],\n\t    [6, 24, 42],\n\t    [6, 26, 46],\n\t    [6, 28, 50],\n\t    [6, 30, 54],\n\t    [6, 32, 58],\n\t    [6, 34, 62],\n\t    [6, 26, 46, 66],\n\t    [6, 26, 48, 70],\n\t    [6, 26, 50, 74],\n\t    [6, 30, 54, 78],\n\t    [6, 30, 56, 82],\n\t    [6, 30, 58, 86],\n\t    [6, 34, 62, 90],\n\t    [6, 28, 50, 72, 94],\n\t    [6, 26, 50, 74, 98],\n\t    [6, 30, 54, 78, 102],\n\t    [6, 28, 54, 80, 106],\n\t    [6, 32, 58, 84, 110],\n\t    [6, 30, 58, 86, 114],\n\t    [6, 34, 62, 90, 118],\n\t    [6, 26, 50, 74, 98, 122],\n\t    [6, 30, 54, 78, 102, 126],\n\t    [6, 26, 52, 78, 104, 130],\n\t    [6, 30, 56, 82, 108, 134],\n\t    [6, 34, 60, 86, 112, 138],\n\t    [6, 30, 58, 86, 114, 142],\n\t    [6, 34, 62, 90, 118, 146],\n\t    [6, 30, 54, 78, 102, 126, 150],\n\t    [6, 24, 50, 76, 102, 128, 154],\n\t    [6, 28, 54, 80, 106, 132, 158],\n\t    [6, 32, 58, 84, 110, 136, 162],\n\t    [6, 26, 54, 82, 110, 138, 166],\n\t    [6, 30, 58, 86, 114, 142, 170]\n\t  ],\n\n\t  G15: (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0),\n\t  G18: (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0),\n\t  G15_MASK: (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1),\n\n\t  /*\n\t   BCH编码格式信息\n\t   */\n\t  getBCHTypeInfo: function(data) {\n\t    var d = data << 10;\n\t    while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) >= 0) {\n\t      d ^= (QRUtil.G15 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15)));\n\t    }\n\t    return ((data << 10) | d) ^ QRUtil.G15_MASK;\n\t  },\n\t  /*\n\t   BCH编码版本信息\n\t   */\n\t  getBCHTypeNumber: function(data) {\n\t    var d = data << 12;\n\t    while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) >= 0) {\n\t      d ^= (QRUtil.G18 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18)));\n\t    }\n\t    return (data << 12) | d;\n\t  },\n\t  /*\n\t   获取BCH位信息\n\t   */\n\t  getBCHDigit: function(data) {\n\n\t    var digit = 0;\n\n\t    while (data != 0) {\n\t      digit++;\n\t      data >>>= 1;\n\t    }\n\n\t    return digit;\n\t  },\n\t  /*\n\t   获取版本对应的矫正图形位置\n\t   */\n\t  getPatternPosition: function(typeNumber) {\n\t    return QRUtil.PATTERN_POSITION_TABLE[typeNumber - 1];\n\t  },\n\t  /*\n\t   掩膜算法\n\t   */\n\t  getMask: function(maskPattern, i, j) {\n\n\t    switch (maskPattern) {\n\n\t      case QRMaskPattern.PATTERN000:\n\t        return (i + j) % 2 == 0;\n\t      case QRMaskPattern.PATTERN001:\n\t        return i % 2 == 0;\n\t      case QRMaskPattern.PATTERN010:\n\t        return j % 3 == 0;\n\t      case QRMaskPattern.PATTERN011:\n\t        return (i + j) % 3 == 0;\n\t      case QRMaskPattern.PATTERN100:\n\t        return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 == 0;\n\t      case QRMaskPattern.PATTERN101:\n\t        return (i * j) % 2 + (i * j) % 3 == 0;\n\t      case QRMaskPattern.PATTERN110:\n\t        return ((i * j) % 2 + (i * j) % 3) % 2 == 0;\n\t      case QRMaskPattern.PATTERN111:\n\t        return ((i * j) % 3 + (i + j) % 2) % 2 == 0;\n\n\t      default:\n\t        throw new Error(\"bad maskPattern:\" + maskPattern);\n\t    }\n\t  },\n\t  /*\n\t   获取RS的纠错多项式\n\t   */\n\t  getErrorCorrectPolynomial: function(errorCorrectLength) {\n\n\t    var a = new QRPolynomial([1], 0);\n\n\t    for (var i = 0; i < errorCorrectLength; i++) {\n\t      a = a.multiply(new QRPolynomial([1, QRMath.gexp(i)], 0));\n\t    }\n\n\t    return a;\n\t  },\n\t  /*\n\t   获取评价\n\t   */\n\t  getLostPoint: function(qrCode) {\n\n\t    var moduleCount = qrCode.getModuleCount(),\n\t      lostPoint = 0,\n\t      darkCount = 0;\n\n\t    for (var row = 0; row < moduleCount; row++) {\n\n\t      var sameCount = 0;\n\t      var head = qrCode.modules[row][0];\n\n\t      for (var col = 0; col < moduleCount; col++) {\n\n\t        var current = qrCode.modules[row][col];\n\n\t        //level 3 评价\n\t        if (col < moduleCount - 6) {\n\t          if (current && !qrCode.modules[row][col + 1] && qrCode.modules[row][col + 2] && qrCode.modules[row][col + 3] && qrCode.modules[row][col + 4] && !qrCode.modules[row][col + 5] && qrCode.modules[row][col + 6]) {\n\t            if (col < moduleCount - 10) {\n\t              if (qrCode.modules[row][col + 7] && qrCode.modules[row][col + 8] && qrCode.modules[row][col + 9] && qrCode.modules[row][col + 10]) {\n\t                lostPoint += 40;\n\t              }\n\t            } else if (col > 3) {\n\t              if (qrCode.modules[row][col - 1] && qrCode.modules[row][col - 2] && qrCode.modules[row][col - 3] && qrCode.modules[row][col - 4]) {\n\t                lostPoint += 40;\n\t              }\n\t            }\n\n\t          }\n\t        }\n\n\t        //level 2 评价\n\t        if ((row < moduleCount - 1) && (col < moduleCount - 1)) {\n\t          var count = 0;\n\t          if (current) count++;\n\t          if (qrCode.modules[row + 1][col]) count++;\n\t          if (qrCode.modules[row][col + 1]) count++;\n\t          if (qrCode.modules[row + 1][col + 1]) count++;\n\t          if (count == 0 || count == 4) {\n\t            lostPoint += 3;\n\t          }\n\t        }\n\n\t        //level 1 评价\n\t        if (head ^ current) {\n\t          sameCount++;\n\t        } else {\n\t          head = current;\n\t          if (sameCount >= 5) {\n\t            lostPoint += (3 + sameCount - 5);\n\t          }\n\t          sameCount = 1;\n\t        }\n\n\t        //level 4 评价\n\t        if (current) {\n\t          darkCount++;\n\t        }\n\n\t      }\n\t    }\n\n\t    for (var col = 0; col < moduleCount; col++) {\n\n\t      var sameCount = 0;\n\t      var head = qrCode.modules[0][col];\n\n\t      for (var row = 0; row < moduleCount; row++) {\n\n\t        var current = qrCode.modules[row][col];\n\n\t        //level 3 评价\n\t        if (row < moduleCount - 6) {\n\t          if (current && !qrCode.modules[row + 1][col] && qrCode.modules[row + 2][col] && qrCode.modules[row + 3][col] && qrCode.modules[row + 4][col] && !qrCode.modules[row + 5][col] && qrCode.modules[row + 6][col]) {\n\t            if (row < moduleCount - 10) {\n\t              if (qrCode.modules[row + 7][col] && qrCode.modules[row + 8][col] && qrCode.modules[row + 9][col] && qrCode.modules[row + 10][col]) {\n\t                lostPoint += 40;\n\t              }\n\t            } else if (row > 3) {\n\t              if (qrCode.modules[row - 1][col] && qrCode.modules[row - 2][col] && qrCode.modules[row - 3][col] && qrCode.modules[row - 4][col]) {\n\t                lostPoint += 40;\n\t              }\n\t            }\n\t          }\n\t        }\n\n\t        //level 1 评价\n\t        if (head ^ current) {\n\t          sameCount++;\n\t        } else {\n\t          head = current;\n\t          if (sameCount >= 5) {\n\t            lostPoint += (3 + sameCount - 5);\n\t          }\n\t          sameCount = 1;\n\t        }\n\n\t      }\n\t    }\n\n\t    // LEVEL4\n\n\t    var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;\n\t    lostPoint += ratio * 10;\n\n\t    return lostPoint;\n\t  }\n\n\t};\n\n\n\t//---------------------------------------------------------------------\n\t// QRMath使用的数学工具\n\t//---------------------------------------------------------------------\n\n\tvar QRMath = {\n\t  /*\n\t   将n转化为a^m\n\t   */\n\t  glog: function(n) {\n\n\t    if (n < 1) {\n\t      throw new Error(\"glog(\" + n + \")\");\n\t    }\n\n\t    return QRMath.LOG_TABLE[n];\n\t  },\n\t  /*\n\t   将a^m转化为n\n\t   */\n\t  gexp: function(n) {\n\n\t    while (n < 0) {\n\t      n += 255;\n\t    }\n\n\t    while (n >= 256) {\n\t      n -= 255;\n\t    }\n\n\t    return QRMath.EXP_TABLE[n];\n\t  },\n\n\t  EXP_TABLE: new Array(256),\n\n\t  LOG_TABLE: new Array(256)\n\n\t};\n\n\tfor (var i = 0; i < 8; i++) {\n\t  QRMath.EXP_TABLE[i] = 1 << i;\n\t}\n\tfor (var i = 8; i < 256; i++) {\n\t  QRMath.EXP_TABLE[i] = QRMath.EXP_TABLE[i - 4] ^ QRMath.EXP_TABLE[i - 5] ^ QRMath.EXP_TABLE[i - 6] ^ QRMath.EXP_TABLE[i - 8];\n\t}\n\tfor (var i = 0; i < 255; i++) {\n\t  QRMath.LOG_TABLE[QRMath.EXP_TABLE[i]] = i;\n\t}\n\n\t//---------------------------------------------------------------------\n\t// QRPolynomial 多项式\n\t//---------------------------------------------------------------------\n\t/**\n\t * 多项式类\n\t * @param {Array} num   系数\n\t * @param {num} shift a^shift\n\t */\n\tfunction QRPolynomial(num, shift) {\n\n\t  if (num.length == undefined) {\n\t    throw new Error(num.length + \"/\" + shift);\n\t  }\n\n\t  var offset = 0;\n\n\t  while (offset < num.length && num[offset] == 0) {\n\t    offset++;\n\t  }\n\n\t  this.num = new Array(num.length - offset + shift);\n\t  for (var i = 0; i < num.length - offset; i++) {\n\t    this.num[i] = num[i + offset];\n\t  }\n\t}\n\n\tQRPolynomial.prototype = {\n\n\t  get: function(index) {\n\t    return this.num[index];\n\t  },\n\n\t  getLength: function() {\n\t    return this.num.length;\n\t  },\n\t  /**\n\t   * 多项式乘法\n\t   * @param  {QRPolynomial} e 被乘多项式\n\t   * @return {[type]}   [description]\n\t   */\n\t  multiply: function(e) {\n\n\t    var num = new Array(this.getLength() + e.getLength() - 1);\n\n\t    for (var i = 0; i < this.getLength(); i++) {\n\t      for (var j = 0; j < e.getLength(); j++) {\n\t        num[i + j] ^= QRMath.gexp(QRMath.glog(this.get(i)) + QRMath.glog(e.get(j)));\n\t      }\n\t    }\n\n\t    return new QRPolynomial(num, 0);\n\t  },\n\t  /**\n\t   * 多项式模运算\n\t   * @param  {QRPolynomial} e 模多项式\n\t   * @return {}\n\t   */\n\t  mod: function(e) {\n\t    var tl = this.getLength(),\n\t      el = e.getLength();\n\t    if (tl - el < 0) {\n\t      return this;\n\t    }\n\t    var num = new Array(tl);\n\t    for (var i = 0; i < tl; i++) {\n\t      num[i] = this.get(i);\n\t    }\n\t    while (num.length >= el) {\n\t      var ratio = QRMath.glog(num[0]) - QRMath.glog(e.get(0));\n\n\t      for (var i = 0; i < e.getLength(); i++) {\n\t        num[i] ^= QRMath.gexp(QRMath.glog(e.get(i)) + ratio);\n\t      }\n\t      while (num[0] == 0) {\n\t        num.shift();\n\t      }\n\t    }\n\t    return new QRPolynomial(num, 0);\n\t  }\n\t};\n\n\t//---------------------------------------------------------------------\n\t// RS_BLOCK_TABLE\n\t//---------------------------------------------------------------------\n\t/*\n\t 二维码各个版本信息[块数, 每块中的数据块数, 每块中的信息块数]\n\t */\n\tvar RS_BLOCK_TABLE = [\n\n\t  // L\n\t  // M\n\t  // Q\n\t  // H\n\n\t  // 1\n\t  [1, 26, 19],\n\t  [1, 26, 16],\n\t  [1, 26, 13],\n\t  [1, 26, 9],\n\n\t  // 2\n\t  [1, 44, 34],\n\t  [1, 44, 28],\n\t  [1, 44, 22],\n\t  [1, 44, 16],\n\n\t  // 3\n\t  [1, 70, 55],\n\t  [1, 70, 44],\n\t  [2, 35, 17],\n\t  [2, 35, 13],\n\n\t  // 4\n\t  [1, 100, 80],\n\t  [2, 50, 32],\n\t  [2, 50, 24],\n\t  [4, 25, 9],\n\n\t  // 5\n\t  [1, 134, 108],\n\t  [2, 67, 43],\n\t  [2, 33, 15, 2, 34, 16],\n\t  [2, 33, 11, 2, 34, 12],\n\n\t  // 6\n\t  [2, 86, 68],\n\t  [4, 43, 27],\n\t  [4, 43, 19],\n\t  [4, 43, 15],\n\n\t  // 7\n\t  [2, 98, 78],\n\t  [4, 49, 31],\n\t  [2, 32, 14, 4, 33, 15],\n\t  [4, 39, 13, 1, 40, 14],\n\n\t  // 8\n\t  [2, 121, 97],\n\t  [2, 60, 38, 2, 61, 39],\n\t  [4, 40, 18, 2, 41, 19],\n\t  [4, 40, 14, 2, 41, 15],\n\n\t  // 9\n\t  [2, 146, 116],\n\t  [3, 58, 36, 2, 59, 37],\n\t  [4, 36, 16, 4, 37, 17],\n\t  [4, 36, 12, 4, 37, 13],\n\n\t  // 10\n\t  [2, 86, 68, 2, 87, 69],\n\t  [4, 69, 43, 1, 70, 44],\n\t  [6, 43, 19, 2, 44, 20],\n\t  [6, 43, 15, 2, 44, 16],\n\n\t  // 11\n\t  [4, 101, 81],\n\t  [1, 80, 50, 4, 81, 51],\n\t  [4, 50, 22, 4, 51, 23],\n\t  [3, 36, 12, 8, 37, 13],\n\n\t  // 12\n\t  [2, 116, 92, 2, 117, 93],\n\t  [6, 58, 36, 2, 59, 37],\n\t  [4, 46, 20, 6, 47, 21],\n\t  [7, 42, 14, 4, 43, 15],\n\n\t  // 13\n\t  [4, 133, 107],\n\t  [8, 59, 37, 1, 60, 38],\n\t  [8, 44, 20, 4, 45, 21],\n\t  [12, 33, 11, 4, 34, 12],\n\n\t  // 14\n\t  [3, 145, 115, 1, 146, 116],\n\t  [4, 64, 40, 5, 65, 41],\n\t  [11, 36, 16, 5, 37, 17],\n\t  [11, 36, 12, 5, 37, 13],\n\n\t  // 15\n\t  [5, 109, 87, 1, 110, 88],\n\t  [5, 65, 41, 5, 66, 42],\n\t  [5, 54, 24, 7, 55, 25],\n\t  [11, 36, 12],\n\n\t  // 16\n\t  [5, 122, 98, 1, 123, 99],\n\t  [7, 73, 45, 3, 74, 46],\n\t  [15, 43, 19, 2, 44, 20],\n\t  [3, 45, 15, 13, 46, 16],\n\n\t  // 17\n\t  [1, 135, 107, 5, 136, 108],\n\t  [10, 74, 46, 1, 75, 47],\n\t  [1, 50, 22, 15, 51, 23],\n\t  [2, 42, 14, 17, 43, 15],\n\n\t  // 18\n\t  [5, 150, 120, 1, 151, 121],\n\t  [9, 69, 43, 4, 70, 44],\n\t  [17, 50, 22, 1, 51, 23],\n\t  [2, 42, 14, 19, 43, 15],\n\n\t  // 19\n\t  [3, 141, 113, 4, 142, 114],\n\t  [3, 70, 44, 11, 71, 45],\n\t  [17, 47, 21, 4, 48, 22],\n\t  [9, 39, 13, 16, 40, 14],\n\n\t  // 20\n\t  [3, 135, 107, 5, 136, 108],\n\t  [3, 67, 41, 13, 68, 42],\n\t  [15, 54, 24, 5, 55, 25],\n\t  [15, 43, 15, 10, 44, 16],\n\n\t  // 21\n\t  [4, 144, 116, 4, 145, 117],\n\t  [17, 68, 42],\n\t  [17, 50, 22, 6, 51, 23],\n\t  [19, 46, 16, 6, 47, 17],\n\n\t  // 22\n\t  [2, 139, 111, 7, 140, 112],\n\t  [17, 74, 46],\n\t  [7, 54, 24, 16, 55, 25],\n\t  [34, 37, 13],\n\n\t  // 23\n\t  [4, 151, 121, 5, 152, 122],\n\t  [4, 75, 47, 14, 76, 48],\n\t  [11, 54, 24, 14, 55, 25],\n\t  [16, 45, 15, 14, 46, 16],\n\n\t  // 24\n\t  [6, 147, 117, 4, 148, 118],\n\t  [6, 73, 45, 14, 74, 46],\n\t  [11, 54, 24, 16, 55, 25],\n\t  [30, 46, 16, 2, 47, 17],\n\n\t  // 25\n\t  [8, 132, 106, 4, 133, 107],\n\t  [8, 75, 47, 13, 76, 48],\n\t  [7, 54, 24, 22, 55, 25],\n\t  [22, 45, 15, 13, 46, 16],\n\n\t  // 26\n\t  [10, 142, 114, 2, 143, 115],\n\t  [19, 74, 46, 4, 75, 47],\n\t  [28, 50, 22, 6, 51, 23],\n\t  [33, 46, 16, 4, 47, 17],\n\n\t  // 27\n\t  [8, 152, 122, 4, 153, 123],\n\t  [22, 73, 45, 3, 74, 46],\n\t  [8, 53, 23, 26, 54, 24],\n\t  [12, 45, 15, 28, 46, 16],\n\n\t  // 28\n\t  [3, 147, 117, 10, 148, 118],\n\t  [3, 73, 45, 23, 74, 46],\n\t  [4, 54, 24, 31, 55, 25],\n\t  [11, 45, 15, 31, 46, 16],\n\n\t  // 29\n\t  [7, 146, 116, 7, 147, 117],\n\t  [21, 73, 45, 7, 74, 46],\n\t  [1, 53, 23, 37, 54, 24],\n\t  [19, 45, 15, 26, 46, 16],\n\n\t  // 30\n\t  [5, 145, 115, 10, 146, 116],\n\t  [19, 75, 47, 10, 76, 48],\n\t  [15, 54, 24, 25, 55, 25],\n\t  [23, 45, 15, 25, 46, 16],\n\n\t  // 31\n\t  [13, 145, 115, 3, 146, 116],\n\t  [2, 74, 46, 29, 75, 47],\n\t  [42, 54, 24, 1, 55, 25],\n\t  [23, 45, 15, 28, 46, 16],\n\n\t  // 32\n\t  [17, 145, 115],\n\t  [10, 74, 46, 23, 75, 47],\n\t  [10, 54, 24, 35, 55, 25],\n\t  [19, 45, 15, 35, 46, 16],\n\n\t  // 33\n\t  [17, 145, 115, 1, 146, 116],\n\t  [14, 74, 46, 21, 75, 47],\n\t  [29, 54, 24, 19, 55, 25],\n\t  [11, 45, 15, 46, 46, 16],\n\n\t  // 34\n\t  [13, 145, 115, 6, 146, 116],\n\t  [14, 74, 46, 23, 75, 47],\n\t  [44, 54, 24, 7, 55, 25],\n\t  [59, 46, 16, 1, 47, 17],\n\n\t  // 35\n\t  [12, 151, 121, 7, 152, 122],\n\t  [12, 75, 47, 26, 76, 48],\n\t  [39, 54, 24, 14, 55, 25],\n\t  [22, 45, 15, 41, 46, 16],\n\n\t  // 36\n\t  [6, 151, 121, 14, 152, 122],\n\t  [6, 75, 47, 34, 76, 48],\n\t  [46, 54, 24, 10, 55, 25],\n\t  [2, 45, 15, 64, 46, 16],\n\n\t  // 37\n\t  [17, 152, 122, 4, 153, 123],\n\t  [29, 74, 46, 14, 75, 47],\n\t  [49, 54, 24, 10, 55, 25],\n\t  [24, 45, 15, 46, 46, 16],\n\n\t  // 38\n\t  [4, 152, 122, 18, 153, 123],\n\t  [13, 74, 46, 32, 75, 47],\n\t  [48, 54, 24, 14, 55, 25],\n\t  [42, 45, 15, 32, 46, 16],\n\n\t  // 39\n\t  [20, 147, 117, 4, 148, 118],\n\t  [40, 75, 47, 7, 76, 48],\n\t  [43, 54, 24, 22, 55, 25],\n\t  [10, 45, 15, 67, 46, 16],\n\n\t  // 40\n\t  [19, 148, 118, 6, 149, 119],\n\t  [18, 75, 47, 31, 76, 48],\n\t  [34, 54, 24, 34, 55, 25],\n\t  [20, 45, 15, 61, 46, 16]\n\t];\n\n\t/**\n\t * 根据数据获取对应版本\n\t * @return {[type]} [description]\n\t */\n\tQRCodeAlg.prototype.getRightType = function() {\n\t  for (var typeNumber = 1; typeNumber < 41; typeNumber++) {\n\t    var rsBlock = RS_BLOCK_TABLE[(typeNumber - 1) * 4 + this.errorCorrectLevel];\n\t    if (rsBlock == undefined) {\n\t      throw new Error(\"bad rs block @ typeNumber:\" + typeNumber + \"/errorCorrectLevel:\" + this.errorCorrectLevel);\n\t    }\n\t    var length = rsBlock.length / 3;\n\t    var totalDataCount = 0;\n\t    for (var i = 0; i < length; i++) {\n\t      var count = rsBlock[i * 3 + 0];\n\t      var dataCount = rsBlock[i * 3 + 2];\n\t      totalDataCount += dataCount * count;\n\t    }\n\n\t    var lengthBytes = typeNumber > 9 ? 2 : 1;\n\t    if (this.utf8bytes.length + lengthBytes < totalDataCount || typeNumber == 40) {\n\t      this.typeNumber = typeNumber;\n\t      this.rsBlock = rsBlock;\n\t      this.totalDataCount = totalDataCount;\n\t      break;\n\t    }\n\t  }\n\t};\n\n\t//---------------------------------------------------------------------\n\t// QRBitBuffer\n\t//---------------------------------------------------------------------\n\n\tfunction QRBitBuffer() {\n\t  this.buffer = new Array();\n\t  this.length = 0;\n\t}\n\n\tQRBitBuffer.prototype = {\n\n\t  get: function(index) {\n\t    var bufIndex = Math.floor(index / 8);\n\t    return ((this.buffer[bufIndex] >>> (7 - index % 8)) & 1);\n\t  },\n\n\t  put: function(num, length) {\n\t    for (var i = 0; i < length; i++) {\n\t      this.putBit(((num >>> (length - i - 1)) & 1));\n\t    }\n\t  },\n\n\t  putBit: function(bit) {\n\n\t    var bufIndex = Math.floor(this.length / 8);\n\t    if (this.buffer.length <= bufIndex) {\n\t      this.buffer.push(0);\n\t    }\n\n\t    if (bit) {\n\t      this.buffer[bufIndex] |= (0x80 >>> (this.length % 8));\n\t    }\n\n\t    this.length++;\n\t  }\n\t};\n\t/**\n\t * 获取单个字符的utf8编码\n\t * unicode BMP平面约65535个字符\n\t * @param {num} code\n\t * return {array}\n\t */\n\tfunction unicodeFormat8(code) {\n\t  // 1 byte\n\t  if (code < 128) {\n\t    return [code];\n\t    // 2 bytes\n\t  } else if (code < 2048) {\n\t    c0 = 192 + (code >> 6);\n\t    c1 = 128 + (code & 63);\n\t    return [c0, c1];\n\t    // 3 bytes\n\t  } else {\n\t    c0 = 224 + (code >> 12);\n\t    c1 = 128 + (code >> 6 & 63);\n\t    c2 = 128 + (code & 63);\n\t    return [c0, c1, c2];\n\t  }\n\t}\n\n\t/**\n\t * 获取字符串的utf8编码字节串\n\t * @param {string} string\n\t * @return {array}\n\t */\n\tfunction getUTF8Bytes(string) {\n\t  var utf8codes = [];\n\t  for (var i = 0; i < string.length; i++) {\n\t    var code = string.charCodeAt(i);\n\t    var utf8 = unicodeFormat8(code);\n\t    for (var j = 0; j < utf8.length; j++) {\n\t      utf8codes.push(utf8[j]);\n\t    }\n\t  }\n\t  return utf8codes;\n\t}\n\n\t/**\n\t * 二维码算法实现\n\t * @param {string} data              要编码的信息字符串\n\t * @param {num} errorCorrectLevel 纠错等级\n\t */\n\tfunction QRCodeAlg(data, errorCorrectLevel) {\n\t  this.typeNumber = -1; //版本\n\t  this.errorCorrectLevel = errorCorrectLevel;\n\t  this.modules = null;  //二维矩阵，存放最终结果\n\t  this.moduleCount = 0; //矩阵大小\n\t  this.dataCache = null; //数据缓存\n\t  this.rsBlocks = null; //版本数据信息\n\t  this.totalDataCount = -1; //可使用的数据量\n\t  this.data = data;\n\t  this.utf8bytes = getUTF8Bytes(data);\n\t  this.make();\n\t}\n\n\tQRCodeAlg.prototype = {\n\t  constructor: QRCodeAlg,\n\t  /**\n\t   * 获取二维码矩阵大小\n\t   * @return {num} 矩阵大小\n\t   */\n\t  getModuleCount: function() {\n\t    return this.moduleCount;\n\t  },\n\t  /**\n\t   * 编码\n\t   */\n\t  make: function() {\n\t    this.getRightType();\n\t    this.dataCache = this.createData();\n\t    this.createQrcode();\n\t  },\n\t  /**\n\t   * 设置二位矩阵功能图形\n\t   * @param  {bool} test 表示是否在寻找最好掩膜阶段\n\t   * @param  {num} maskPattern 掩膜的版本\n\t   */\n\t  makeImpl: function(maskPattern) {\n\n\t    this.moduleCount = this.typeNumber * 4 + 17;\n\t    this.modules = new Array(this.moduleCount);\n\n\t    for (var row = 0; row < this.moduleCount; row++) {\n\n\t      this.modules[row] = new Array(this.moduleCount);\n\n\t    }\n\t    this.setupPositionProbePattern(0, 0);\n\t    this.setupPositionProbePattern(this.moduleCount - 7, 0);\n\t    this.setupPositionProbePattern(0, this.moduleCount - 7);\n\t    this.setupPositionAdjustPattern();\n\t    this.setupTimingPattern();\n\t    this.setupTypeInfo(true, maskPattern);\n\n\t    if (this.typeNumber >= 7) {\n\t      this.setupTypeNumber(true);\n\t    }\n\t    this.mapData(this.dataCache, maskPattern);\n\t  },\n\t  /**\n\t   * 设置二维码的位置探测图形\n\t   * @param  {num} row 探测图形的中心横坐标\n\t   * @param  {num} col 探测图形的中心纵坐标\n\t   */\n\t  setupPositionProbePattern: function(row, col) {\n\n\t    for (var r = -1; r <= 7; r++) {\n\n\t      if (row + r <= -1 || this.moduleCount <= row + r) continue;\n\n\t      for (var c = -1; c <= 7; c++) {\n\n\t        if (col + c <= -1 || this.moduleCount <= col + c) continue;\n\n\t        if ((0 <= r && r <= 6 && (c == 0 || c == 6)) || (0 <= c && c <= 6 && (r == 0 || r == 6)) || (2 <= r && r <= 4 && 2 <= c && c <= 4)) {\n\t          this.modules[row + r][col + c] = true;\n\t        } else {\n\t          this.modules[row + r][col + c] = false;\n\t        }\n\t      }\n\t    }\n\t  },\n\t  /**\n\t   * 创建二维码\n\t   * @return {[type]} [description]\n\t   */\n\t  createQrcode: function() {\n\n\t    var minLostPoint = 0;\n\t    var pattern = 0;\n\t    var bestModules = null;\n\n\t    for (var i = 0; i < 8; i++) {\n\n\t      this.makeImpl(i);\n\n\t      var lostPoint = QRUtil.getLostPoint(this);\n\t      if (i == 0 || minLostPoint > lostPoint) {\n\t        minLostPoint = lostPoint;\n\t        pattern = i;\n\t        bestModules = this.modules;\n\t      }\n\t    }\n\t    this.modules = bestModules;\n\t    this.setupTypeInfo(false, pattern);\n\n\t    if (this.typeNumber >= 7) {\n\t      this.setupTypeNumber(false);\n\t    }\n\n\t  },\n\t  /**\n\t   * 设置定位图形\n\t   * @return {[type]} [description]\n\t   */\n\t  setupTimingPattern: function() {\n\n\t    for (var r = 8; r < this.moduleCount - 8; r++) {\n\t      if (this.modules[r][6] != null) {\n\t        continue;\n\t      }\n\t      this.modules[r][6] = (r % 2 == 0);\n\n\t      if (this.modules[6][r] != null) {\n\t        continue;\n\t      }\n\t      this.modules[6][r] = (r % 2 == 0);\n\t    }\n\t  },\n\t  /**\n\t   * 设置矫正图形\n\t   * @return {[type]} [description]\n\t   */\n\t  setupPositionAdjustPattern: function() {\n\n\t    var pos = QRUtil.getPatternPosition(this.typeNumber);\n\n\t    for (var i = 0; i < pos.length; i++) {\n\n\t      for (var j = 0; j < pos.length; j++) {\n\n\t        var row = pos[i];\n\t        var col = pos[j];\n\n\t        if (this.modules[row][col] != null) {\n\t          continue;\n\t        }\n\n\t        for (var r = -2; r <= 2; r++) {\n\n\t          for (var c = -2; c <= 2; c++) {\n\n\t            if (r == -2 || r == 2 || c == -2 || c == 2 || (r == 0 && c == 0)) {\n\t              this.modules[row + r][col + c] = true;\n\t            } else {\n\t              this.modules[row + r][col + c] = false;\n\t            }\n\t          }\n\t        }\n\t      }\n\t    }\n\t  },\n\t  /**\n\t   * 设置版本信息（7以上版本才有）\n\t   * @param  {bool} test 是否处于判断最佳掩膜阶段\n\t   * @return {[type]}      [description]\n\t   */\n\t  setupTypeNumber: function(test) {\n\n\t    var bits = QRUtil.getBCHTypeNumber(this.typeNumber);\n\n\t    for (var i = 0; i < 18; i++) {\n\t      var mod = (!test && ((bits >> i) & 1) == 1);\n\t      this.modules[Math.floor(i / 3)][i % 3 + this.moduleCount - 8 - 3] = mod;\n\t      this.modules[i % 3 + this.moduleCount - 8 - 3][Math.floor(i / 3)] = mod;\n\t    }\n\t  },\n\t  /**\n\t   * 设置格式信息（纠错等级和掩膜版本）\n\t   * @param  {bool} test\n\t   * @param  {num} maskPattern 掩膜版本\n\t   * @return {}\n\t   */\n\t  setupTypeInfo: function(test, maskPattern) {\n\n\t    var data = (QRErrorCorrectLevel[this.errorCorrectLevel] << 3) | maskPattern;\n\t    var bits = QRUtil.getBCHTypeInfo(data);\n\n\t    // vertical\n\t    for (var i = 0; i < 15; i++) {\n\n\t      var mod = (!test && ((bits >> i) & 1) == 1);\n\n\t      if (i < 6) {\n\t        this.modules[i][8] = mod;\n\t      } else if (i < 8) {\n\t        this.modules[i + 1][8] = mod;\n\t      } else {\n\t        this.modules[this.moduleCount - 15 + i][8] = mod;\n\t      }\n\n\t      // horizontal\n\t      var mod = (!test && ((bits >> i) & 1) == 1);\n\n\t      if (i < 8) {\n\t        this.modules[8][this.moduleCount - i - 1] = mod;\n\t      } else if (i < 9) {\n\t        this.modules[8][15 - i - 1 + 1] = mod;\n\t      } else {\n\t        this.modules[8][15 - i - 1] = mod;\n\t      }\n\t    }\n\n\t    // fixed module\n\t    this.modules[this.moduleCount - 8][8] = (!test);\n\n\t  },\n\t  /**\n\t   * 数据编码\n\t   * @return {[type]} [description]\n\t   */\n\t  createData: function() {\n\t    var buffer = new QRBitBuffer();\n\t    var lengthBits = this.typeNumber > 9 ? 16 : 8;\n\t    buffer.put(4, 4); //添加模式\n\t    buffer.put(this.utf8bytes.length, lengthBits);\n\t    for (var i = 0, l = this.utf8bytes.length; i < l; i++) {\n\t      buffer.put(this.utf8bytes[i], 8);\n\t    }\n\t    if (buffer.length + 4 <= this.totalDataCount * 8) {\n\t      buffer.put(0, 4);\n\t    }\n\n\t    // padding\n\t    while (buffer.length % 8 != 0) {\n\t      buffer.putBit(false);\n\t    }\n\n\t    // padding\n\t    while (true) {\n\n\t      if (buffer.length >= this.totalDataCount * 8) {\n\t        break;\n\t      }\n\t      buffer.put(QRCodeAlg.PAD0, 8);\n\n\t      if (buffer.length >= this.totalDataCount * 8) {\n\t        break;\n\t      }\n\t      buffer.put(QRCodeAlg.PAD1, 8);\n\t    }\n\t    return this.createBytes(buffer);\n\t  },\n\t  /**\n\t   * 纠错码编码\n\t   * @param  {buffer} buffer 数据编码\n\t   * @return {[type]}\n\t   */\n\t  createBytes: function(buffer) {\n\n\t    var offset = 0;\n\n\t    var maxDcCount = 0;\n\t    var maxEcCount = 0;\n\n\t    var length = this.rsBlock.length / 3;\n\n\t    var rsBlocks = new Array();\n\n\t    for (var i = 0; i < length; i++) {\n\n\t      var count = this.rsBlock[i * 3 + 0];\n\t      var totalCount = this.rsBlock[i * 3 + 1];\n\t      var dataCount = this.rsBlock[i * 3 + 2];\n\n\t      for (var j = 0; j < count; j++) {\n\t        rsBlocks.push([dataCount, totalCount]);\n\t      }\n\t    }\n\n\t    var dcdata = new Array(rsBlocks.length);\n\t    var ecdata = new Array(rsBlocks.length);\n\n\t    for (var r = 0; r < rsBlocks.length; r++) {\n\n\t      var dcCount = rsBlocks[r][0];\n\t      var ecCount = rsBlocks[r][1] - dcCount;\n\n\t      maxDcCount = Math.max(maxDcCount, dcCount);\n\t      maxEcCount = Math.max(maxEcCount, ecCount);\n\n\t      dcdata[r] = new Array(dcCount);\n\n\t      for (var i = 0; i < dcdata[r].length; i++) {\n\t        dcdata[r][i] = 0xff & buffer.buffer[i + offset];\n\t      }\n\t      offset += dcCount;\n\n\t      var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount);\n\t      var rawPoly = new QRPolynomial(dcdata[r], rsPoly.getLength() - 1);\n\n\t      var modPoly = rawPoly.mod(rsPoly);\n\t      ecdata[r] = new Array(rsPoly.getLength() - 1);\n\t      for (var i = 0; i < ecdata[r].length; i++) {\n\t        var modIndex = i + modPoly.getLength() - ecdata[r].length;\n\t        ecdata[r][i] = (modIndex >= 0) ? modPoly.get(modIndex) : 0;\n\t      }\n\t    }\n\n\t    var data = new Array(this.totalDataCount);\n\t    var index = 0;\n\n\t    for (var i = 0; i < maxDcCount; i++) {\n\t      for (var r = 0; r < rsBlocks.length; r++) {\n\t        if (i < dcdata[r].length) {\n\t          data[index++] = dcdata[r][i];\n\t        }\n\t      }\n\t    }\n\n\t    for (var i = 0; i < maxEcCount; i++) {\n\t      for (var r = 0; r < rsBlocks.length; r++) {\n\t        if (i < ecdata[r].length) {\n\t          data[index++] = ecdata[r][i];\n\t        }\n\t      }\n\t    }\n\n\t    return data;\n\n\t  },\n\t  /**\n\t   * 布置模块，构建最终信息\n\t   * @param  {} data\n\t   * @param  {} maskPattern\n\t   * @return {}\n\t   */\n\t  mapData: function(data, maskPattern) {\n\n\t    var inc = -1;\n\t    var row = this.moduleCount - 1;\n\t    var bitIndex = 7;\n\t    var byteIndex = 0;\n\n\t    for (var col = this.moduleCount - 1; col > 0; col -= 2) {\n\n\t      if (col == 6) col--;\n\n\t      while (true) {\n\n\t        for (var c = 0; c < 2; c++) {\n\n\t          if (this.modules[row][col - c] == null) {\n\n\t            var dark = false;\n\n\t            if (byteIndex < data.length) {\n\t              dark = (((data[byteIndex] >>> bitIndex) & 1) == 1);\n\t            }\n\n\t            var mask = QRUtil.getMask(maskPattern, row, col - c);\n\n\t            if (mask) {\n\t              dark = !dark;\n\t            }\n\n\t            this.modules[row][col - c] = dark;\n\t            bitIndex--;\n\n\t            if (bitIndex == -1) {\n\t              byteIndex++;\n\t              bitIndex = 7;\n\t            }\n\t          }\n\t        }\n\n\t        row += inc;\n\n\t        if (row < 0 || this.moduleCount <= row) {\n\t          row -= inc;\n\t          inc = -inc;\n\t          break;\n\t        }\n\t      }\n\t    }\n\t  }\n\n\t};\n\t/**\n\t * 填充字段\n\t */\n\tQRCodeAlg.PAD0 = 0xEC;\n\tQRCodeAlg.PAD1 = 0x11;\n\n\n\t//---------------------------------------------------------------------\n\t// 纠错等级对应的编码\n\t//---------------------------------------------------------------------\n\n\tvar QRErrorCorrectLevel = [1, 0, 3, 2];\n\n\t//---------------------------------------------------------------------\n\t// 掩膜版本\n\t//---------------------------------------------------------------------\n\n\tvar QRMaskPattern = {\n\t  PATTERN000: 0,\n\t  PATTERN001: 1,\n\t  PATTERN010: 2,\n\t  PATTERN011: 3,\n\t  PATTERN100: 4,\n\t  PATTERN101: 5,\n\t  PATTERN110: 6,\n\t  PATTERN111: 7\n\t};\n\n\t//---------------------------------------------------------------------\n\t// 工具类\n\t//---------------------------------------------------------------------\n\n\tvar QRUtil = {\n\n\t  /*\n\t   每个版本矫正图形的位置\n\t   */\n\t  PATTERN_POSITION_TABLE: [\n\t    [],\n\t    [6, 18],\n\t    [6, 22],\n\t    [6, 26],\n\t    [6, 30],\n\t    [6, 34],\n\t    [6, 22, 38],\n\t    [6, 24, 42],\n\t    [6, 26, 46],\n\t    [6, 28, 50],\n\t    [6, 30, 54],\n\t    [6, 32, 58],\n\t    [6, 34, 62],\n\t    [6, 26, 46, 66],\n\t    [6, 26, 48, 70],\n\t    [6, 26, 50, 74],\n\t    [6, 30, 54, 78],\n\t    [6, 30, 56, 82],\n\t    [6, 30, 58, 86],\n\t    [6, 34, 62, 90],\n\t    [6, 28, 50, 72, 94],\n\t    [6, 26, 50, 74, 98],\n\t    [6, 30, 54, 78, 102],\n\t    [6, 28, 54, 80, 106],\n\t    [6, 32, 58, 84, 110],\n\t    [6, 30, 58, 86, 114],\n\t    [6, 34, 62, 90, 118],\n\t    [6, 26, 50, 74, 98, 122],\n\t    [6, 30, 54, 78, 102, 126],\n\t    [6, 26, 52, 78, 104, 130],\n\t    [6, 30, 56, 82, 108, 134],\n\t    [6, 34, 60, 86, 112, 138],\n\t    [6, 30, 58, 86, 114, 142],\n\t    [6, 34, 62, 90, 118, 146],\n\t    [6, 30, 54, 78, 102, 126, 150],\n\t    [6, 24, 50, 76, 102, 128, 154],\n\t    [6, 28, 54, 80, 106, 132, 158],\n\t    [6, 32, 58, 84, 110, 136, 162],\n\t    [6, 26, 54, 82, 110, 138, 166],\n\t    [6, 30, 58, 86, 114, 142, 170]\n\t  ],\n\n\t  G15: (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0),\n\t  G18: (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0),\n\t  G15_MASK: (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1),\n\n\t  /*\n\t   BCH编码格式信息\n\t   */\n\t  getBCHTypeInfo: function(data) {\n\t    var d = data << 10;\n\t    while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) >= 0) {\n\t      d ^= (QRUtil.G15 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15)));\n\t    }\n\t    return ((data << 10) | d) ^ QRUtil.G15_MASK;\n\t  },\n\t  /*\n\t   BCH编码版本信息\n\t   */\n\t  getBCHTypeNumber: function(data) {\n\t    var d = data << 12;\n\t    while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) >= 0) {\n\t      d ^= (QRUtil.G18 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18)));\n\t    }\n\t    return (data << 12) | d;\n\t  },\n\t  /*\n\t   获取BCH位信息\n\t   */\n\t  getBCHDigit: function(data) {\n\n\t    var digit = 0;\n\n\t    while (data != 0) {\n\t      digit++;\n\t      data >>>= 1;\n\t    }\n\n\t    return digit;\n\t  },\n\t  /*\n\t   获取版本对应的矫正图形位置\n\t   */\n\t  getPatternPosition: function(typeNumber) {\n\t    return QRUtil.PATTERN_POSITION_TABLE[typeNumber - 1];\n\t  },\n\t  /*\n\t   掩膜算法\n\t   */\n\t  getMask: function(maskPattern, i, j) {\n\n\t    switch (maskPattern) {\n\n\t      case QRMaskPattern.PATTERN000:\n\t        return (i + j) % 2 == 0;\n\t      case QRMaskPattern.PATTERN001:\n\t        return i % 2 == 0;\n\t      case QRMaskPattern.PATTERN010:\n\t        return j % 3 == 0;\n\t      case QRMaskPattern.PATTERN011:\n\t        return (i + j) % 3 == 0;\n\t      case QRMaskPattern.PATTERN100:\n\t        return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 == 0;\n\t      case QRMaskPattern.PATTERN101:\n\t        return (i * j) % 2 + (i * j) % 3 == 0;\n\t      case QRMaskPattern.PATTERN110:\n\t        return ((i * j) % 2 + (i * j) % 3) % 2 == 0;\n\t      case QRMaskPattern.PATTERN111:\n\t        return ((i * j) % 3 + (i + j) % 2) % 2 == 0;\n\n\t      default:\n\t        throw new Error(\"bad maskPattern:\" + maskPattern);\n\t    }\n\t  },\n\t  /*\n\t   获取RS的纠错多项式\n\t   */\n\t  getErrorCorrectPolynomial: function(errorCorrectLength) {\n\n\t    var a = new QRPolynomial([1], 0);\n\n\t    for (var i = 0; i < errorCorrectLength; i++) {\n\t      a = a.multiply(new QRPolynomial([1, QRMath.gexp(i)], 0));\n\t    }\n\n\t    return a;\n\t  },\n\t  /*\n\t   获取评价\n\t   */\n\t  getLostPoint: function(qrCode) {\n\n\t    var moduleCount = qrCode.getModuleCount(),\n\t      lostPoint = 0,\n\t      darkCount = 0;\n\n\t    for (var row = 0; row < moduleCount; row++) {\n\n\t      var sameCount = 0;\n\t      var head = qrCode.modules[row][0];\n\n\t      for (var col = 0; col < moduleCount; col++) {\n\n\t        var current = qrCode.modules[row][col];\n\n\t        //level 3 评价\n\t        if (col < moduleCount - 6) {\n\t          if (current && !qrCode.modules[row][col + 1] && qrCode.modules[row][col + 2] && qrCode.modules[row][col + 3] && qrCode.modules[row][col + 4] && !qrCode.modules[row][col + 5] && qrCode.modules[row][col + 6]) {\n\t            if (col < moduleCount - 10) {\n\t              if (qrCode.modules[row][col + 7] && qrCode.modules[row][col + 8] && qrCode.modules[row][col + 9] && qrCode.modules[row][col + 10]) {\n\t                lostPoint += 40;\n\t              }\n\t            } else if (col > 3) {\n\t              if (qrCode.modules[row][col - 1] && qrCode.modules[row][col - 2] && qrCode.modules[row][col - 3] && qrCode.modules[row][col - 4]) {\n\t                lostPoint += 40;\n\t              }\n\t            }\n\n\t          }\n\t        }\n\n\t        //level 2 评价\n\t        if ((row < moduleCount - 1) && (col < moduleCount - 1)) {\n\t          var count = 0;\n\t          if (current) count++;\n\t          if (qrCode.modules[row + 1][col]) count++;\n\t          if (qrCode.modules[row][col + 1]) count++;\n\t          if (qrCode.modules[row + 1][col + 1]) count++;\n\t          if (count == 0 || count == 4) {\n\t            lostPoint += 3;\n\t          }\n\t        }\n\n\t        //level 1 评价\n\t        if (head ^ current) {\n\t          sameCount++;\n\t        } else {\n\t          head = current;\n\t          if (sameCount >= 5) {\n\t            lostPoint += (3 + sameCount - 5);\n\t          }\n\t          sameCount = 1;\n\t        }\n\n\t        //level 4 评价\n\t        if (current) {\n\t          darkCount++;\n\t        }\n\n\t      }\n\t    }\n\n\t    for (var col = 0; col < moduleCount; col++) {\n\n\t      var sameCount = 0;\n\t      var head = qrCode.modules[0][col];\n\n\t      for (var row = 0; row < moduleCount; row++) {\n\n\t        var current = qrCode.modules[row][col];\n\n\t        //level 3 评价\n\t        if (row < moduleCount - 6) {\n\t          if (current && !qrCode.modules[row + 1][col] && qrCode.modules[row + 2][col] && qrCode.modules[row + 3][col] && qrCode.modules[row + 4][col] && !qrCode.modules[row + 5][col] && qrCode.modules[row + 6][col]) {\n\t            if (row < moduleCount - 10) {\n\t              if (qrCode.modules[row + 7][col] && qrCode.modules[row + 8][col] && qrCode.modules[row + 9][col] && qrCode.modules[row + 10][col]) {\n\t                lostPoint += 40;\n\t              }\n\t            } else if (row > 3) {\n\t              if (qrCode.modules[row - 1][col] && qrCode.modules[row - 2][col] && qrCode.modules[row - 3][col] && qrCode.modules[row - 4][col]) {\n\t                lostPoint += 40;\n\t              }\n\t            }\n\t          }\n\t        }\n\n\t        //level 1 评价\n\t        if (head ^ current) {\n\t          sameCount++;\n\t        } else {\n\t          head = current;\n\t          if (sameCount >= 5) {\n\t            lostPoint += (3 + sameCount - 5);\n\t          }\n\t          sameCount = 1;\n\t        }\n\n\t      }\n\t    }\n\n\t    // LEVEL4\n\n\t    var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;\n\t    lostPoint += ratio * 10;\n\n\t    return lostPoint;\n\t  }\n\n\t};\n\n\n\t//---------------------------------------------------------------------\n\t// QRMath使用的数学工具\n\t//---------------------------------------------------------------------\n\n\tvar QRMath = {\n\t  /*\n\t   将n转化为a^m\n\t   */\n\t  glog: function(n) {\n\n\t    if (n < 1) {\n\t      throw new Error(\"glog(\" + n + \")\");\n\t    }\n\n\t    return QRMath.LOG_TABLE[n];\n\t  },\n\t  /*\n\t   将a^m转化为n\n\t   */\n\t  gexp: function(n) {\n\n\t    while (n < 0) {\n\t      n += 255;\n\t    }\n\n\t    while (n >= 256) {\n\t      n -= 255;\n\t    }\n\n\t    return QRMath.EXP_TABLE[n];\n\t  },\n\n\t  EXP_TABLE: new Array(256),\n\n\t  LOG_TABLE: new Array(256)\n\n\t};\n\n\tfor (var i = 0; i < 8; i++) {\n\t  QRMath.EXP_TABLE[i] = 1 << i;\n\t}\n\tfor (var i = 8; i < 256; i++) {\n\t  QRMath.EXP_TABLE[i] = QRMath.EXP_TABLE[i - 4] ^ QRMath.EXP_TABLE[i - 5] ^ QRMath.EXP_TABLE[i - 6] ^ QRMath.EXP_TABLE[i - 8];\n\t}\n\tfor (var i = 0; i < 255; i++) {\n\t  QRMath.LOG_TABLE[QRMath.EXP_TABLE[i]] = i;\n\t}\n\n\t//---------------------------------------------------------------------\n\t// QRPolynomial 多项式\n\t//---------------------------------------------------------------------\n\t/**\n\t * 多项式类\n\t * @param {Array} num   系数\n\t * @param {num} shift a^shift\n\t */\n\tfunction QRPolynomial(num, shift) {\n\n\t  if (num.length == undefined) {\n\t    throw new Error(num.length + \"/\" + shift);\n\t  }\n\n\t  var offset = 0;\n\n\t  while (offset < num.length && num[offset] == 0) {\n\t    offset++;\n\t  }\n\n\t  this.num = new Array(num.length - offset + shift);\n\t  for (var i = 0; i < num.length - offset; i++) {\n\t    this.num[i] = num[i + offset];\n\t  }\n\t}\n\n\tQRPolynomial.prototype = {\n\n\t  get: function(index) {\n\t    return this.num[index];\n\t  },\n\n\t  getLength: function() {\n\t    return this.num.length;\n\t  },\n\t  /**\n\t   * 多项式乘法\n\t   * @param  {QRPolynomial} e 被乘多项式\n\t   * @return {[type]}   [description]\n\t   */\n\t  multiply: function(e) {\n\n\t    var num = new Array(this.getLength() + e.getLength() - 1);\n\n\t    for (var i = 0; i < this.getLength(); i++) {\n\t      for (var j = 0; j < e.getLength(); j++) {\n\t        num[i + j] ^= QRMath.gexp(QRMath.glog(this.get(i)) + QRMath.glog(e.get(j)));\n\t      }\n\t    }\n\n\t    return new QRPolynomial(num, 0);\n\t  },\n\t  /**\n\t   * 多项式模运算\n\t   * @param  {QRPolynomial} e 模多项式\n\t   * @return {}\n\t   */\n\t  mod: function(e) {\n\t    var tl = this.getLength(),\n\t      el = e.getLength();\n\t    if (tl - el < 0) {\n\t      return this;\n\t    }\n\t    var num = new Array(tl);\n\t    for (var i = 0; i < tl; i++) {\n\t      num[i] = this.get(i);\n\t    }\n\t    while (num.length >= el) {\n\t      var ratio = QRMath.glog(num[0]) - QRMath.glog(e.get(0));\n\n\t      for (var i = 0; i < e.getLength(); i++) {\n\t        num[i] ^= QRMath.gexp(QRMath.glog(e.get(i)) + ratio);\n\t      }\n\t      while (num[0] == 0) {\n\t        num.shift();\n\t      }\n\t    }\n\t    return new QRPolynomial(num, 0);\n\t  }\n\t};\n\n\t//---------------------------------------------------------------------\n\t// RS_BLOCK_TABLE\n\t//---------------------------------------------------------------------\n\t/*\n\t 二维码各个版本信息[块数, 每块中的数据块数, 每块中的信息块数]\n\t */\n\tRS_BLOCK_TABLE = [\n\n\t  // L\n\t  // M\n\t  // Q\n\t  // H\n\n\t  // 1\n\t  [1, 26, 19],\n\t  [1, 26, 16],\n\t  [1, 26, 13],\n\t  [1, 26, 9],\n\n\t  // 2\n\t  [1, 44, 34],\n\t  [1, 44, 28],\n\t  [1, 44, 22],\n\t  [1, 44, 16],\n\n\t  // 3\n\t  [1, 70, 55],\n\t  [1, 70, 44],\n\t  [2, 35, 17],\n\t  [2, 35, 13],\n\n\t  // 4\n\t  [1, 100, 80],\n\t  [2, 50, 32],\n\t  [2, 50, 24],\n\t  [4, 25, 9],\n\n\t  // 5\n\t  [1, 134, 108],\n\t  [2, 67, 43],\n\t  [2, 33, 15, 2, 34, 16],\n\t  [2, 33, 11, 2, 34, 12],\n\n\t  // 6\n\t  [2, 86, 68],\n\t  [4, 43, 27],\n\t  [4, 43, 19],\n\t  [4, 43, 15],\n\n\t  // 7\n\t  [2, 98, 78],\n\t  [4, 49, 31],\n\t  [2, 32, 14, 4, 33, 15],\n\t  [4, 39, 13, 1, 40, 14],\n\n\t  // 8\n\t  [2, 121, 97],\n\t  [2, 60, 38, 2, 61, 39],\n\t  [4, 40, 18, 2, 41, 19],\n\t  [4, 40, 14, 2, 41, 15],\n\n\t  // 9\n\t  [2, 146, 116],\n\t  [3, 58, 36, 2, 59, 37],\n\t  [4, 36, 16, 4, 37, 17],\n\t  [4, 36, 12, 4, 37, 13],\n\n\t  // 10\n\t  [2, 86, 68, 2, 87, 69],\n\t  [4, 69, 43, 1, 70, 44],\n\t  [6, 43, 19, 2, 44, 20],\n\t  [6, 43, 15, 2, 44, 16],\n\n\t  // 11\n\t  [4, 101, 81],\n\t  [1, 80, 50, 4, 81, 51],\n\t  [4, 50, 22, 4, 51, 23],\n\t  [3, 36, 12, 8, 37, 13],\n\n\t  // 12\n\t  [2, 116, 92, 2, 117, 93],\n\t  [6, 58, 36, 2, 59, 37],\n\t  [4, 46, 20, 6, 47, 21],\n\t  [7, 42, 14, 4, 43, 15],\n\n\t  // 13\n\t  [4, 133, 107],\n\t  [8, 59, 37, 1, 60, 38],\n\t  [8, 44, 20, 4, 45, 21],\n\t  [12, 33, 11, 4, 34, 12],\n\n\t  // 14\n\t  [3, 145, 115, 1, 146, 116],\n\t  [4, 64, 40, 5, 65, 41],\n\t  [11, 36, 16, 5, 37, 17],\n\t  [11, 36, 12, 5, 37, 13],\n\n\t  // 15\n\t  [5, 109, 87, 1, 110, 88],\n\t  [5, 65, 41, 5, 66, 42],\n\t  [5, 54, 24, 7, 55, 25],\n\t  [11, 36, 12],\n\n\t  // 16\n\t  [5, 122, 98, 1, 123, 99],\n\t  [7, 73, 45, 3, 74, 46],\n\t  [15, 43, 19, 2, 44, 20],\n\t  [3, 45, 15, 13, 46, 16],\n\n\t  // 17\n\t  [1, 135, 107, 5, 136, 108],\n\t  [10, 74, 46, 1, 75, 47],\n\t  [1, 50, 22, 15, 51, 23],\n\t  [2, 42, 14, 17, 43, 15],\n\n\t  // 18\n\t  [5, 150, 120, 1, 151, 121],\n\t  [9, 69, 43, 4, 70, 44],\n\t  [17, 50, 22, 1, 51, 23],\n\t  [2, 42, 14, 19, 43, 15],\n\n\t  // 19\n\t  [3, 141, 113, 4, 142, 114],\n\t  [3, 70, 44, 11, 71, 45],\n\t  [17, 47, 21, 4, 48, 22],\n\t  [9, 39, 13, 16, 40, 14],\n\n\t  // 20\n\t  [3, 135, 107, 5, 136, 108],\n\t  [3, 67, 41, 13, 68, 42],\n\t  [15, 54, 24, 5, 55, 25],\n\t  [15, 43, 15, 10, 44, 16],\n\n\t  // 21\n\t  [4, 144, 116, 4, 145, 117],\n\t  [17, 68, 42],\n\t  [17, 50, 22, 6, 51, 23],\n\t  [19, 46, 16, 6, 47, 17],\n\n\t  // 22\n\t  [2, 139, 111, 7, 140, 112],\n\t  [17, 74, 46],\n\t  [7, 54, 24, 16, 55, 25],\n\t  [34, 37, 13],\n\n\t  // 23\n\t  [4, 151, 121, 5, 152, 122],\n\t  [4, 75, 47, 14, 76, 48],\n\t  [11, 54, 24, 14, 55, 25],\n\t  [16, 45, 15, 14, 46, 16],\n\n\t  // 24\n\t  [6, 147, 117, 4, 148, 118],\n\t  [6, 73, 45, 14, 74, 46],\n\t  [11, 54, 24, 16, 55, 25],\n\t  [30, 46, 16, 2, 47, 17],\n\n\t  // 25\n\t  [8, 132, 106, 4, 133, 107],\n\t  [8, 75, 47, 13, 76, 48],\n\t  [7, 54, 24, 22, 55, 25],\n\t  [22, 45, 15, 13, 46, 16],\n\n\t  // 26\n\t  [10, 142, 114, 2, 143, 115],\n\t  [19, 74, 46, 4, 75, 47],\n\t  [28, 50, 22, 6, 51, 23],\n\t  [33, 46, 16, 4, 47, 17],\n\n\t  // 27\n\t  [8, 152, 122, 4, 153, 123],\n\t  [22, 73, 45, 3, 74, 46],\n\t  [8, 53, 23, 26, 54, 24],\n\t  [12, 45, 15, 28, 46, 16],\n\n\t  // 28\n\t  [3, 147, 117, 10, 148, 118],\n\t  [3, 73, 45, 23, 74, 46],\n\t  [4, 54, 24, 31, 55, 25],\n\t  [11, 45, 15, 31, 46, 16],\n\n\t  // 29\n\t  [7, 146, 116, 7, 147, 117],\n\t  [21, 73, 45, 7, 74, 46],\n\t  [1, 53, 23, 37, 54, 24],\n\t  [19, 45, 15, 26, 46, 16],\n\n\t  // 30\n\t  [5, 145, 115, 10, 146, 116],\n\t  [19, 75, 47, 10, 76, 48],\n\t  [15, 54, 24, 25, 55, 25],\n\t  [23, 45, 15, 25, 46, 16],\n\n\t  // 31\n\t  [13, 145, 115, 3, 146, 116],\n\t  [2, 74, 46, 29, 75, 47],\n\t  [42, 54, 24, 1, 55, 25],\n\t  [23, 45, 15, 28, 46, 16],\n\n\t  // 32\n\t  [17, 145, 115],\n\t  [10, 74, 46, 23, 75, 47],\n\t  [10, 54, 24, 35, 55, 25],\n\t  [19, 45, 15, 35, 46, 16],\n\n\t  // 33\n\t  [17, 145, 115, 1, 146, 116],\n\t  [14, 74, 46, 21, 75, 47],\n\t  [29, 54, 24, 19, 55, 25],\n\t  [11, 45, 15, 46, 46, 16],\n\n\t  // 34\n\t  [13, 145, 115, 6, 146, 116],\n\t  [14, 74, 46, 23, 75, 47],\n\t  [44, 54, 24, 7, 55, 25],\n\t  [59, 46, 16, 1, 47, 17],\n\n\t  // 35\n\t  [12, 151, 121, 7, 152, 122],\n\t  [12, 75, 47, 26, 76, 48],\n\t  [39, 54, 24, 14, 55, 25],\n\t  [22, 45, 15, 41, 46, 16],\n\n\t  // 36\n\t  [6, 151, 121, 14, 152, 122],\n\t  [6, 75, 47, 34, 76, 48],\n\t  [46, 54, 24, 10, 55, 25],\n\t  [2, 45, 15, 64, 46, 16],\n\n\t  // 37\n\t  [17, 152, 122, 4, 153, 123],\n\t  [29, 74, 46, 14, 75, 47],\n\t  [49, 54, 24, 10, 55, 25],\n\t  [24, 45, 15, 46, 46, 16],\n\n\t  // 38\n\t  [4, 152, 122, 18, 153, 123],\n\t  [13, 74, 46, 32, 75, 47],\n\t  [48, 54, 24, 14, 55, 25],\n\t  [42, 45, 15, 32, 46, 16],\n\n\t  // 39\n\t  [20, 147, 117, 4, 148, 118],\n\t  [40, 75, 47, 7, 76, 48],\n\t  [43, 54, 24, 22, 55, 25],\n\t  [10, 45, 15, 67, 46, 16],\n\n\t  // 40\n\t  [19, 148, 118, 6, 149, 119],\n\t  [18, 75, 47, 31, 76, 48],\n\t  [34, 54, 24, 34, 55, 25],\n\t  [20, 45, 15, 61, 46, 16]\n\t];\n\n\t/**\n\t * 根据数据获取对应版本\n\t * @return {[type]} [description]\n\t */\n\tQRCodeAlg.prototype.getRightType = function() {\n\t  for (var typeNumber = 1; typeNumber < 41; typeNumber++) {\n\t    var rsBlock = RS_BLOCK_TABLE[(typeNumber - 1) * 4 + this.errorCorrectLevel];\n\t    if (rsBlock == undefined) {\n\t      throw new Error('bad rs block @ typeNumber:' + typeNumber + '/errorCorrectLevel:' + this.errorCorrectLevel);\n\t    }\n\t    var length = rsBlock.length / 3;\n\t    var totalDataCount = 0;\n\t    for (var i = 0; i < length; i++) {\n\t      var count = rsBlock[i * 3 + 0];\n\t      var dataCount = rsBlock[i * 3 + 2];\n\t      totalDataCount += dataCount * count;\n\t    }\n\n\t    var lengthBytes = typeNumber > 9 ? 2 : 1;\n\t    if (this.utf8bytes.length + lengthBytes < totalDataCount || typeNumber == 40) {\n\t      this.typeNumber = typeNumber;\n\t      this.rsBlock = rsBlock;\n\t      this.totalDataCount = totalDataCount;\n\t      break;\n\t    }\n\t  }\n\t};\n\n\t// ---------------------------------------------------------------------\n\t// QRBitBuffer\n\t// ---------------------------------------------------------------------\n\n\tfunction QRBitBuffer() {\n\t  this.buffer = new Array();\n\t  this.length = 0;\n\t}\n\n\tQRBitBuffer.prototype = {\n\t  get: function(index) {\n\t    var bufIndex = Math.floor(index / 8);\n\t    return ((this.buffer[bufIndex] >>> (7 - index % 8)) & 1);\n\t  },\n\n\t  put: function(num, length) {\n\t    for (var i = 0; i < length; i++) {\n\t      this.putBit(((num >>> (length - i - 1)) & 1));\n\t    }\n\t  },\n\n\t  putBit: function(bit) {\n\n\t    var bufIndex = Math.floor(this.length / 8);\n\t    if (this.buffer.length <= bufIndex) {\n\t      this.buffer.push(0);\n\t    }\n\n\t    if (bit) {\n\t      this.buffer[bufIndex] |= (0x80 >>> (this.length % 8));\n\t    }\n\n\t    this.length++;\n\t  }\n\t};\n\n\t$.fn.qrcode = function QRCodePlugin(option) {\n\t  return this.each(function() {\n\t    $(this).append(new QRCode(option));\n\t  });\n\t};\n\n\tmodule.exports = UI.qrcode = QRCode;\n\n\n/***/ },\n/* 27 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\n\t/**\n\t * @via https://github.com/uikit/uikit/blob/master/src/js/addons/sticky.js\n\t * @license https://github.com/uikit/uikit/blob/master/LICENSE.md\n\t */\n\n\t// Sticky Class\n\tvar Sticky = function(element, options) {\n\t  var _this = this;\n\n\t  this.options = $.extend({}, Sticky.DEFAULTS, options);\n\t  this.$element = $(element);\n\t  this.sticked = null;\n\t  this.inited = null;\n\t  this.$holder = undefined;\n\n\t  this.$window = $(window).\n\t    on('scroll.sticky.amui',\n\t    UI.utils.debounce($.proxy(this.checkPosition, this), 10)).\n\t    on('resize.sticky.amui orientationchange.sticky.amui',\n\t    UI.utils.debounce(function() {\n\t      _this.reset(true, function() {\n\t        _this.checkPosition();\n\t      });\n\t    }, 50)).\n\t    on('load.sticky.amui', $.proxy(this.checkPosition, this));\n\n\t  // the `.offset()` is diff between jQuery & Zepto.js\n\t  // jQuery: return `top` and `left`\n\t  // Zepto.js: return `top`, `left`, `width`, `height`\n\t  this.offset = this.$element.offset();\n\n\t  this.init();\n\t};\n\n\tSticky.DEFAULTS = {\n\t  top: 0,\n\t  bottom: 0,\n\t  animation: '',\n\t  className: {\n\t    sticky: 'am-sticky',\n\t    resetting: 'am-sticky-resetting',\n\t    stickyBtm: 'am-sticky-bottom',\n\t    animationRev: 'am-animation-reverse'\n\t  }\n\t};\n\n\tSticky.prototype.init = function() {\n\t  var result = this.check();\n\n\t  if (!result) {\n\t    return false;\n\t  }\n\n\t  var $element = this.$element;\n\t  var $elementMargin = '';\n\n\t  $.each($element.css(\n\t      ['marginTop', 'marginRight', 'marginBottom', 'marginLeft']),\n\t    function(name, value) {\n\t      return $elementMargin += ' ' + value;\n\t    });\n\n\t  var $holder = $('<div class=\"am-sticky-placeholder\"></div>').css({\n\t    height: $element.css('position') !== 'absolute' ?\n\t      $element.outerHeight() : '',\n\t    float: $element.css('float') != 'none' ? $element.css('float') : '',\n\t    margin: $elementMargin\n\t  });\n\n\t  this.$holder = $element.css('margin', 0).wrap($holder).parent();\n\t  this.inited = 1;\n\n\t  return true;\n\t};\n\n\tSticky.prototype.reset = function(force, cb) {\n\t  var options = this.options;\n\t  var $element = this.$element;\n\t  var animation = (options.animation) ?\n\t  ' am-animation-' + options.animation : '';\n\t  var complete = function() {\n\t    $element.css({position: '', top: '', width: '', left: '', margin: 0});\n\t    $element.removeClass([\n\t      animation,\n\t      options.className.animationRev,\n\t      options.className.sticky,\n\t      options.className.resetting\n\t    ].join(' '));\n\n\t    this.animating = false;\n\t    this.sticked = false;\n\t    this.offset = $element.offset();\n\t    cb && cb();\n\t  }.bind(this);\n\n\t  $element.addClass(options.className.resetting);\n\n\t  if (!force && options.animation && UI.support.animation) {\n\n\t    this.animating = true;\n\n\t    $element.removeClass(animation).one(UI.support.animation.end, function() {\n\t      complete();\n\t    }).width(); // force redraw\n\n\t    $element.addClass(animation + ' ' + options.className.animationRev);\n\t  } else {\n\t    complete();\n\t  }\n\t};\n\n\tSticky.prototype.check = function() {\n\t  if (!this.$element.is(':visible')) {\n\t    return false;\n\t  }\n\n\t  var media = this.options.media;\n\n\t  if (media) {\n\t    switch (typeof(media)) {\n\t      case 'number':\n\t        if (window.innerWidth < media) {\n\t          return false;\n\t        }\n\t        break;\n\n\t      case 'string':\n\t        if (window.matchMedia && !window.matchMedia(media).matches) {\n\t          return false;\n\t        }\n\t        break;\n\t    }\n\t  }\n\n\t  return true;\n\t};\n\n\tSticky.prototype.checkPosition = function() {\n\t  if (!this.inited) {\n\t    var initialized = this.init();\n\t    if (!initialized) {\n\t      return;\n\t    }\n\t  }\n\n\t  var options = this.options;\n\t  var scrollTop = this.$window.scrollTop();\n\t  var offsetTop = options.top;\n\t  var offsetBottom = options.bottom;\n\t  var $element = this.$element;\n\t  var animation = (options.animation) ?\n\t    ' am-animation-' + options.animation : '';\n\t  var className = [options.className.sticky, animation].join(' ');\n\n\t  if (typeof offsetBottom == 'function') {\n\t    offsetBottom = offsetBottom(this.$element);\n\t  }\n\n\t  var checkResult = (scrollTop > this.$holder.offset().top);\n\n\t  if (!this.sticked && checkResult) {\n\t    $element.addClass(className);\n\t  } else if (this.sticked && !checkResult) {\n\t    this.reset();\n\t  }\n\n\t  this.$holder.css({\n\t    height: $element.is(':visible') && $element.css('position') !== 'absolute' ?\n\t      $element.outerHeight() : ''\n\t  });\n\n\t  if (checkResult) {\n\t    $element.css({\n\t      top: offsetTop,\n\t      left: this.$holder.offset().left,\n\t      width: this.$holder.width()\n\t    });\n\n\t    /*\n\t     if (offsetBottom) {\n\t     // （底部边距 + 元素高度 > 窗口高度） 时定位到底部\n\t     if ((offsetBottom + this.offset.height > $(window).height()) &&\n\t     (scrollTop + $(window).height() >= scrollHeight - offsetBottom)) {\n\t     $element.addClass(options.className.stickyBtm).\n\t     css({top: $(window).height() - offsetBottom - this.offset.height});\n\t     } else {\n\t     $element.removeClass(options.className.stickyBtm).css({top: offsetTop});\n\t     }\n\t     }\n\t     */\n\t  }\n\n\t  this.sticked = checkResult;\n\t};\n\n\t// Sticky Plugin\n\tUI.plugin('sticky', Sticky);\n\n\t// Init code\n\t$(window).on('load', function() {\n\t  $('[data-am-sticky]').sticky();\n\t});\n\n\tmodule.exports = Sticky;\n\n\n/***/ },\n/* 28 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\tvar Hammer = __webpack_require__(3);\n\tvar supportTransition = UI.support.transition;\n\tvar animation = UI.support.animation;\n\n\t/**\n\t * @via https://github.com/twbs/bootstrap/blob/master/js/tab.js\n\t * @copyright 2011-2014 Twitter, Inc.\n\t * @license MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n\t */\n\n\t/**\n\t * Tabs\n\t * @param {HTMLElement} element\n\t * @param {Object} options\n\t * @constructor\n\t */\n\tvar Tabs = function(element, options) {\n\t  this.$element = $(element);\n\t  this.options = $.extend({}, Tabs.DEFAULTS, options || {});\n\t  this.transitioning = this.activeIndex = null;\n\n\t  this.refresh();\n\t  this.init();\n\t};\n\n\tTabs.DEFAULTS = {\n\t  selector: {\n\t    nav: '> .am-tabs-nav',\n\t    content: '> .am-tabs-bd',\n\t    panel: '> .am-tab-panel'\n\t  },\n\t  activeClass: 'am-active'\n\t};\n\n\tTabs.prototype.refresh = function() {\n\t  var selector = this.options.selector;\n\n\t  this.$tabNav = this.$element.find(selector.nav);\n\t  this.$navs = this.$tabNav.find('a');\n\n\t  this.$content = this.$element.find(selector.content);\n\t  this.$tabPanels = this.$content.find(selector.panel);\n\n\t  var $active = this.$tabNav.find('> .' + this.options.activeClass);\n\n\t  // Activate the first Tab when no active Tab or multiple active Tabs\n\t  if ($active.length !== 1) {\n\t    this.open(0);\n\t  } else {\n\t    this.activeIndex = this.$navs.index($active.children('a'));\n\t  }\n\t};\n\n\tTabs.prototype.init = function() {\n\t  var _this = this;\n\t  var options = this.options;\n\n\t  this.$element.on('click.tabs.amui', options.selector.nav + ' a', function(e) {\n\t    e.preventDefault();\n\t    _this.open($(this));\n\t  });\n\n\t  // TODO: nested Tabs touch events\n\t  if (!options.noSwipe) {\n\t    if (!this.$content.length) {\n\t      return this;\n\t    }\n\n\t    var hammer = new Hammer.Manager(this.$content[0]);\n\t    var swipe = new Hammer.Swipe({\n\t      direction: Hammer.DIRECTION_HORIZONTAL\n\t      // threshold: 40\n\t    });\n\n\t    hammer.add(swipe);\n\n\t    hammer.on('swipeleft', UI.utils.debounce(function(e) {\n\t      e.preventDefault();\n\t      _this.goTo('next');\n\t    }, 100));\n\n\t    hammer.on('swiperight', UI.utils.debounce(function(e) {\n\t      e.preventDefault();\n\t      _this.goTo('prev');\n\t    }, 100));\n\n\t    this._hammer = hammer;\n\t  }\n\t};\n\n\t/**\n\t * Open $nav tab\n\t * @param {jQuery|HTMLElement|Number} $nav\n\t * @returns {Tabs}\n\t */\n\tTabs.prototype.open = function($nav) {\n\t  var activeClass = this.options.activeClass;\n\t  var activeIndex = typeof $nav === 'number' ? $nav : this.$navs.index($($nav));\n\n\t  $nav = typeof $nav === 'number' ? this.$navs.eq(activeIndex) : $($nav);\n\n\t  if (!$nav ||\n\t    !$nav.length ||\n\t    this.transitioning ||\n\t    $nav.parent('li').hasClass(activeClass)) {\n\t    return;\n\t  }\n\n\t  var $tabNav = this.$tabNav;\n\t  var href = $nav.attr('href');\n\t  var regexHash = /^#.+$/;\n\t  var $target = regexHash.test(href) && this.$content.find(href) ||\n\t    this.$tabPanels.eq(activeIndex);\n\t  var previous = $tabNav.find('.' + activeClass + ' a')[0];\n\t  var e = $.Event('open.tabs.amui', {\n\t    relatedTarget: previous\n\t  });\n\n\t  $nav.trigger(e);\n\n\t  if (e.isDefaultPrevented()) {\n\t    return;\n\t  }\n\n\t  // activate Tab nav\n\t  this.activate($nav.closest('li'), $tabNav);\n\n\t  // activate Tab content\n\t  this.activate($target, this.$content, function() {\n\t    $nav.trigger({\n\t      type: 'opened.tabs.amui',\n\t      relatedTarget: previous\n\t    });\n\t  });\n\n\t  this.activeIndex = activeIndex;\n\t};\n\n\tTabs.prototype.activate = function($element, $container, callback) {\n\t  this.transitioning = true;\n\n\t  var activeClass = this.options.activeClass;\n\t  var $active = $container.find('> .' + activeClass);\n\t  var transition = callback && supportTransition && !!$active.length;\n\n\t  $active.removeClass(activeClass + ' am-in');\n\n\t  $element.addClass(activeClass);\n\n\t  if (transition) {\n\t    $element.redraw(); // reflow for transition\n\t    $element.addClass('am-in');\n\t  } else {\n\t    $element.removeClass('am-fade');\n\t  }\n\n\t  var complete = $.proxy(function complete() {\n\t    callback && callback();\n\t    this.transitioning = false;\n\t  }, this);\n\n\t  transition ? $active.one(supportTransition.end, complete) : complete();\n\t};\n\n\t/**\n\t * Go to `next` or `prev` tab\n\t * @param {String} direction - `next` or `prev`\n\t */\n\tTabs.prototype.goTo = function(direction) {\n\t  var navIndex = this.activeIndex;\n\t  var isNext = direction === 'next';\n\t  var spring = isNext ? 'am-animation-right-spring' :\n\t    'am-animation-left-spring';\n\n\t  if ((isNext && navIndex + 1 >= this.$navs.length) || // last one\n\t    (!isNext && navIndex === 0)) { // first one\n\t    var $panel = this.$tabPanels.eq(navIndex);\n\n\t    animation && $panel.addClass(spring).on(animation.end, function() {\n\t      $panel.removeClass(spring);\n\t    });\n\t  } else {\n\t    this.open(isNext ? navIndex + 1 : navIndex - 1);\n\t  }\n\t};\n\n\tTabs.prototype.destroy = function() {\n\t  this.$element.off('.tabs.amui');\n\t  Hammer.off(this.$content[0], 'swipeleft swiperight');\n\t  this._hammer && this._hammer.destroy();\n\t  $.removeData(this.$element, 'amui.tabs');\n\t};\n\n\t// Plugin\n\tfunction Plugin(option) {\n\t  var args = Array.prototype.slice.call(arguments, 1);\n\t  var methodReturn;\n\n\t  this.each(function() {\n\t    var $this = $(this);\n\t    var $tabs = $this.is('.am-tabs') && $this || $this.closest('.am-tabs');\n\t    var data = $tabs.data('amui.tabs');\n\t    var options = $.extend({}, UI.utils.parseOptions($this.data('amTabs')),\n\t      $.isPlainObject(option) && option);\n\n\t    if (!data) {\n\t      $tabs.data('amui.tabs', (data = new Tabs($tabs[0], options)));\n\t    }\n\n\t    if (typeof option === 'string') {\n\t      if (option === 'open' && $this.is('.am-tabs-nav a')) {\n\t        data.open($this);\n\t      } else {\n\t        methodReturn = typeof data[option] === 'function' ?\n\t          data[option].apply(data, args) : data[option];\n\t      }\n\t    }\n\t  });\n\n\t  return methodReturn === undefined ? this : methodReturn;\n\t}\n\n\t$.fn.tabs = Plugin;\n\n\t// Init code\n\tUI.ready(function(context) {\n\t  $('[data-am-tabs]', context).tabs();\n\t});\n\n\t$(document).on('click.tabs.amui.data-api', '[data-am-tabs] .am-tabs-nav a',\n\t  function(e) {\n\t  e.preventDefault();\n\t  Plugin.call($(this), 'open');\n\t});\n\n\tmodule.exports = UI.tabs = Tabs;\n\n\t// TODO: 1. Ajax 支持\n\t//       2. touch 事件处理逻辑优化\n\n\n/***/ },\n/* 29 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\n\t/**\n\t * UCheck\n\t * @via https://github.com/designmodo/Flat-UI/blob/8ef98df23ba7f5033e596a9bd05b53b535a9fe99/js/radiocheck.js\n\t * @license CC BY 3.0 & MIT\n\t * @param {HTMLElement} element\n\t * @param {object} options\n\t * @constructor\n\t */\n\n\tvar UCheck = function(element, options) {\n\t  this.options = $.extend({}, UCheck.DEFAULTS, options);\n\t  // this.options = $.extend({}, UCheck.DEFAULTS, this.$element.data(), options);\n\t  this.$element = $(element);\n\t  this.init();\n\t};\n\n\tUCheck.DEFAULTS = {\n\t  checkboxClass: 'am-ucheck-checkbox',\n\t  radioClass: 'am-ucheck-radio',\n\t  checkboxTpl: '<span class=\"am-ucheck-icons\">' +\n\t  '<i class=\"am-icon-unchecked\"></i><i class=\"am-icon-checked\"></i></span>',\n\t  radioTpl: '<span class=\"am-ucheck-icons\">' +\n\t  '<i class=\"am-icon-unchecked\"></i><i class=\"am-icon-checked\"></i></span>'\n\t};\n\n\tUCheck.prototype.init = function() {\n\t  var $element = this.$element;\n\t  var element = $element[0];\n\t  var options = this.options;\n\n\t  if (element.type === 'checkbox') {\n\t    $element.addClass(options.checkboxClass)\n\t      .after(options.checkboxTpl);\n\t  } else if (element.type === 'radio') {\n\t    $element.addClass(options.radioClass)\n\t      .after(options.radioTpl);\n\t  }\n\t};\n\n\tUCheck.prototype.check = function() {\n\t  this.$element\n\t    .prop('checked', true)\n\t    .trigger('change.ucheck.amui')\n\t    .trigger('checked.ucheck.amui');\n\t},\n\n\tUCheck.prototype.uncheck = function() {\n\t  this.$element\n\t    .prop('checked', false)\n\t    // trigger `change` event for form validation, etc.\n\t    // @see https://forum.jquery.com/topic/should-chk-prop-checked-true-trigger-change-event\n\t    .trigger('change')\n\t    .trigger('unchecked.ucheck.amui');\n\t},\n\n\tUCheck.prototype.toggle = function() {\n\t  this.$element.\n\t    prop('checked', function(i, value) {\n\t      return !value;\n\t    })\n\t    .trigger('change.ucheck.amui')\n\t    .trigger('toggled.ucheck.amui');\n\t},\n\n\tUCheck.prototype.disable = function() {\n\t  this.$element\n\t    .prop('disabled', true)\n\t    .trigger('change.ucheck.amui')\n\t    .trigger('disabled.ucheck.amui');\n\t},\n\n\tUCheck.prototype.enable = function() {\n\t  this.$element.prop('disabled', false);\n\t  this.$element.trigger('change.ucheck.amui').trigger('enabled.ucheck.amui');\n\t},\n\n\tUCheck.prototype.destroy = function() {\n\t  this.$element\n\t    .removeData('amui.ucheck')\n\t    .removeClass(this.options.checkboxClass + ' ' + this.options.radioClass)\n\t    .next('.am-ucheck-icons')\n\t    .remove()\n\t  .end()\n\t    .trigger('destroyed.ucheck.amui');\n\t};\n\n\tUI.plugin('uCheck', UCheck, {\n\t  after: function() {\n\t    // Adding 'am-nohover' class for touch devices\n\t    if (UI.support.touch) {\n\t      this.parent().hover(function() {\n\t        $(this).addClass('am-nohover');\n\t      }, function() {\n\t        $(this).removeClass('am-nohover');\n\t      });\n\t    }\n\t  }\n\t});\n\n\tUI.ready(function(context) {\n\t  $('[data-am-ucheck]', context).uCheck();\n\t});\n\n\tmodule.exports = UCheck;\n\n\t// TODO: 与表单验证结合使用的情况\n\n\n/***/ },\n/* 30 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\n\tvar Validator = function(element, options) {\n\t  this.options = $.extend({}, Validator.DEFAULTS, options);\n\t  this.options.patterns = $.extend({}, Validator.patterns,\n\t    this.options.patterns);\n\t  var locales = this.options.locales;\n\t  !Validator.validationMessages[locales] && (this.options.locales = 'zh_CN');\n\t  this.$element = $(element);\n\t  this.init();\n\t};\n\n\tValidator.DEFAULTS = {\n\t  debug: false,\n\t  locales: 'zh_CN',\n\t  H5validation: false,\n\t  H5inputType: ['email', 'url', 'number'],\n\t  patterns: {},\n\t  patternClassPrefix: 'js-pattern-',\n\t  activeClass: 'am-active',\n\t  inValidClass: 'am-field-error',\n\t  validClass: 'am-field-valid',\n\n\t  validateOnSubmit: true,\n\t  alwaysRevalidate: false,\n\t  // Elements to validate with allValid (only validating visible elements)\n\t  // :input: selects all input, textarea, select and button elements.\n\t  // @since 2.5: move `:visible` to `ignore` option (became to `:hidden`)\n\t  allFields: ':input:not(:submit, :button, :disabled, .am-novalidate)',\n\n\t  // ignored elements\n\t  // @since 2.5\n\t  ignore: ':hidden:not([data-am-selected], .am-validate)',\n\n\t  // Custom events\n\t  customEvents: 'validate',\n\n\t  // Keyboard events\n\t  keyboardFields: ':input:not(:submit, :button, :disabled, .am-novalidate)',\n\t  keyboardEvents: 'focusout, change', // keyup, focusin\n\n\t  // bind `keyup` event to active field\n\t  activeKeyup: false,\n\t  textareaMaxlenthKeyup: true,\n\n\t  // Mouse events\n\t  pointerFields: 'input[type=\"range\"]:not(:disabled, .am-novalidate), ' +\n\t  'input[type=\"radio\"]:not(:disabled, .am-novalidate), ' +\n\t  'input[type=\"checkbox\"]:not(:disabled, .am-novalidate), ' +\n\t  'select:not(:disabled, .am-novalidate), ' +\n\t  'option:not(:disabled, .am-novalidate)',\n\t  pointerEvents: 'click',\n\n\t  onValid: function(validity) {\n\t  },\n\n\t  onInValid: function(validity) {\n\t  },\n\n\t  markValid: function(validity) {\n\t    // this is Validator instance\n\t    var options = this.options;\n\t    var $field = $(validity.field);\n\t    var $parent = $field.closest('.am-form-group');\n\n\t    $field.addClass(options.validClass).removeClass(options.inValidClass);\n\t    $parent.addClass('am-form-success').removeClass('am-form-error');\n\t    options.onValid.call(this, validity);\n\t  },\n\n\t  markInValid: function(validity) {\n\t    var options = this.options;\n\t    var $field = $(validity.field);\n\t    var $parent = $field.closest('.am-form-group');\n\n\t    $field.addClass(options.inValidClass + ' ' + options.activeClass).\n\t      removeClass(options.validClass);\n\t    $parent.addClass('am-form-error').removeClass('am-form-success');\n\t    options.onInValid.call(this, validity);\n\t  },\n\n\t  validate: function(validity) {\n\t    // return validity;\n\t  },\n\n\t  submit: null\n\t};\n\n\tValidator.VERSION = '2.6.0';\n\n\t/* jshint -W101 */\n\tValidator.patterns = {\n\t  email: /^((([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+(\\.([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(\\\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-zA-Z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-zA-Z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-zA-Z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-zA-Z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.)+(([a-zA-Z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-zA-Z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-zA-Z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-zA-Z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.?$/,\n\n\t  url: /^(https?|ftp):\\/\\/(((([a-zA-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-zA-Z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-zA-Z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-zA-Z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-zA-Z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.)+(([a-zA-Z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-zA-Z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-zA-Z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-zA-Z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.?)(:\\d*)?)(\\/((([a-zA-Z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&'\\(\\)\\*\\+,;=]|:|@)+(\\/(([a-zA-Z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&'\\(\\)\\*\\+,;=]|:|@)*)*)?)?(\\?((([a-zA-Z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&'\\(\\)\\*\\+,;=]|:|@)|[\\uE000-\\uF8FF]|\\/|\\?)*)?(\\#((([a-zA-Z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&'\\(\\)\\*\\+,;=]|:|@)|\\/|\\?)*)?$/,\n\n\t  // Number, including positive, negative, and floating decimal\n\t  number: /^-?(?:\\d+|\\d{1,3}(?:,\\d{3})+)?(?:\\.\\d+)?$/,\n\t  dateISO: /^\\d{4}[\\/\\-]\\d{1,2}[\\/\\-]\\d{1,2}$/,\n\t  integer: /^-?\\d+$/\n\t};\n\t/* jshint +W101 */\n\n\tValidator.validationMessages = {\n\t  zh_CN: {\n\t    valueMissing: '请填写（选择）此字段',\n\t    customError: {\n\t      tooShort: '至少填写 %s 个字符',\n\t      checkedOverflow: '至多选择 %s 项',\n\t      checkedUnderflow: '至少选择 %s 项'\n\t    },\n\t    patternMismatch: '请按照要求的格式填写',\n\t    rangeOverflow: '请填写小于等于 %s 的值',\n\t    rangeUnderflow: '请填写大于等于 %s 的值',\n\t    stepMismatch: '',\n\t    tooLong: '至多填写 %s 个字符',\n\t    typeMismatch: '请按照要求的类型填写'\n\t  }\n\t};\n\n\tValidator.ERROR_MAP = {\n\t  tooShort: 'minlength',\n\t  checkedOverflow: 'maxchecked',\n\t  checkedUnderflow: 'minchecked',\n\t  rangeOverflow: 'max',\n\t  rangeUnderflow: 'min',\n\t  tooLong: 'maxlength'\n\t};\n\n\t// TODO: 考虑表单元素不是 form 子元素的情形\n\t// TODO: change/click/focusout 同时触发时处理重复\n\t// TODO: 显示提示信息\n\n\tValidator.prototype.init = function() {\n\t  var _this = this;\n\t  var $element = this.$element;\n\t  var options = this.options;\n\n\t  // using H5 form validation if option set and supported\n\t  if (options.H5validation && UI.support.formValidation) {\n\t    return false;\n\t  }\n\n\t  // disable HTML5 form validation\n\t  $element.attr('novalidate', 'novalidate');\n\n\t  function regexToPattern(regex) {\n\t    var pattern = regex.toString();\n\t    return pattern.substring(1, pattern.length - 1);\n\t  }\n\n\t  // add pattern to H5 input type\n\t  $.each(options.H5inputType, function(i, type) {\n\t    var $field = $element.find('input[type=' + type + ']');\n\t    if (!$field.attr('pattern') &&\n\t      !$field.is('[class*=' + options.patternClassPrefix + ']')) {\n\t      $field.attr('pattern', regexToPattern(options.patterns[type]));\n\t    }\n\t  });\n\n\t  // add pattern to .js-pattern-xx\n\t  $.each(options.patterns, function(key, value) {\n\t    var $field = $element.find('.' + options.patternClassPrefix + key);\n\t    !$field.attr('pattern') && $field.attr('pattern', regexToPattern(value));\n\t  });\n\n\t  $element.on('submit.validator.amui', function(e) {\n\t    // user custom submit handler\n\t    if (typeof options.submit === 'function') {\n\t      return options.submit.call(_this, e);\n\t    }\n\n\t    if (options.validateOnSubmit) {\n\t      var formValidity = _this.isFormValid();\n\n\t      // sync validate, return result\n\t      if ($.type(formValidity) === 'boolean') {\n\t        return formValidity;\n\t      }\n\n\t      if ($element.data('amui.checked')) {\n\t        return true;\n\t      } else {\n\t        $.when(formValidity).then(function() {\n\t          // done, submit form\n\t          $element.data('amui.checked', true).submit();\n\t        }, function() {\n\t          // fail\n\t          $element.data('amui.checked', false).\n\t            find('.' + options.inValidClass).eq(0).focus();\n\t        });\n\t        return false;\n\t      }\n\t    }\n\t  });\n\n\t  function bindEvents(fields, eventFlags, debounce) {\n\t    var events = eventFlags.split(',');\n\t    var validate = function(e) {\n\t      // console.log(e.type);\n\t      _this.validate(this);\n\t    };\n\n\t    if (debounce) {\n\t      validate = UI.utils.debounce(validate, debounce);\n\t    }\n\n\t    $.each(events, function(i, event) {\n\t      $element.on(event + '.validator.amui', fields, validate);\n\t    });\n\t  }\n\n\t  bindEvents(':input', options.customEvents);\n\t  bindEvents(options.keyboardFields, options.keyboardEvents);\n\t  bindEvents(options.pointerFields, options.pointerEvents);\n\n\t  if (options.textareaMaxlenthKeyup) {\n\t    bindEvents('textarea[maxlength]', 'keyup', 50);\n\t  }\n\n\t  if (options.activeKeyup) {\n\t    bindEvents('.am-active', 'keyup', 50);\n\t  }\n\n\t  /*if (options.errorMessage === 'tooltip') {\n\t    this.$tooltip = $('<div></div>', {\n\t      'class': 'am-validator-message',\n\t      id: UI.utils.generateGUID('am-validator-message')\n\t    });\n\n\t    $(document.body).append(this.$tooltip);\n\t  }*/\n\t};\n\n\tValidator.prototype.isValid = function(field) {\n\t  var $field = $(field);\n\t  var options = this.options;\n\t  // valid field not has been validated\n\t  if ($field.data('validity') === undefined || options.alwaysRevalidate) {\n\t    this.validate(field);\n\t  }\n\n\t  return $field.data('validity') && $field.data('validity').valid;\n\t};\n\n\tValidator.prototype.validate = function(field) {\n\t  var _this = this;\n\t  var $element = this.$element;\n\t  var options = this.options;\n\t  var $field = $(field);\n\n\t  // Validate equal, e.g. confirm password\n\t  var equalTo = $field.data('equalTo');\n\t  if (equalTo) {\n\t    $field.attr('pattern', '^' + $element.find(equalTo).val() + '$');\n\t  }\n\n\t  var pattern = $field.attr('pattern') || false;\n\t  var re = new RegExp(pattern);\n\t  var $radioGroup = null;\n\t  var $checkboxGroup = null;\n\t  // if checkbox, return `:chcked` length\n\t  // NOTE: checkbox and radio should have name attribute\n\t  var value = ($field.is('[type=checkbox]')) ?\n\t    ($checkboxGroup = $element.find('input[name=\"' + field.name + '\"]')).\n\t      filter(':checked').length : ($field.is('[type=radio]') ?\n\t  ($radioGroup = this.$element.find('input[name=\"' + field.name + '\"]')).\n\t    filter(':checked').length > 0 : $field.val());\n\n\t  // if checkbox, valid the first input of checkbox group\n\t  $field = ($checkboxGroup && $checkboxGroup.length) ?\n\t    $checkboxGroup.first() : $field;\n\n\t  var required = ($field.attr('required') !== undefined) &&\n\t    ($field.attr('required') !== 'false');\n\t  var maxLength = parseInt($field.attr('maxlength'), 10);\n\t  var minLength = parseInt($field.attr('minlength'), 10);\n\t  var min = Number($field.attr('min'));\n\t  var max = Number($field.attr('max'));\n\t  var validity = this.createValidity({field: $field[0], valid: true});\n\n\t  // Debug\n\t  if (options.debug && window.console) {\n\t    console.log('Validate: value -> [' + value + ', regex -> [' + re +\n\t    '], required -> ' + required);\n\t    console.log('Regex test: ' + re.test(value) + ', Pattern: ' + pattern);\n\t  }\n\n\t  // check value length\n\t  if (!isNaN(maxLength) && value.length > maxLength) {\n\t    validity.valid = false;\n\t    validity.tooLong = true;\n\t  }\n\n\t  if (!isNaN(minLength) && value.length < minLength) {\n\t    validity.valid = false;\n\t    validity.customError = 'tooShort';\n\t  }\n\n\t  // check minimum and maximum\n\t  // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Input\n\t  // TODO: 日期验证最小值和最大值 min/max\n\t  if (!isNaN(min) && Number(value) < min) {\n\t    validity.valid = false;\n\t    validity.rangeUnderflow = true;\n\t  }\n\n\t  if (!isNaN(max) && Number(value) > max) {\n\t    validity.valid = false;\n\t    validity.rangeOverflow = true;\n\t  }\n\n\t  // check required\n\t  if (required && !value) {\n\t    validity.valid = false;\n\t    validity.valueMissing = true;\n\t  } else if (($checkboxGroup || $field.is('select[multiple=\"multiple\"]')) &&\n\t    value) {\n\t    // check checkboxes / multiple select with `minchecked`/`maxchecked` attr\n\t    // var $multipleField = $checkboxGroup ? $checkboxGroup.first() : $field;\n\n\t    // if is select[multiple=\"multiple\"], return selected length\n\t    value = $checkboxGroup ? value : value.length;\n\n\t    // at least checked\n\t    var minChecked = parseInt($field.attr('minchecked'), 10);\n\t    // at most checked\n\t    var maxChecked = parseInt($field.attr('maxchecked'), 10);\n\n\t    if (!isNaN(minChecked) && value < minChecked) {\n\t      // console.log('At least [%d] items checked！', maxChecked);\n\t      validity.valid = false;\n\t      validity.customError = 'checkedUnderflow';\n\t    }\n\n\t    if (!isNaN(maxChecked) && value > maxChecked) {\n\t      // console.log('At most [%d] items checked！', maxChecked);\n\t      validity.valid = false;\n\t      validity.customError = 'checkedOverflow';\n\t    }\n\t  } else if (pattern && !re.test(value) && value) { // check pattern\n\t    validity.valid = false;\n\t    validity.patternMismatch = true;\n\t  }\n\n\t  var validateComplete = function(validity) {\n\t    this.markField(validity);\n\n\t    var event = $.Event('validated.field.validator.amui');\n\t    event.validity = validity;\n\n\t    $field.trigger(event).data('validity', validity);\n\n\t    // validate the radios/checkboxes with the same name\n\t    var $fields = $radioGroup || $checkboxGroup;\n\t    if ($fields) {\n\t      $fields.not($field).data('validity', validity).each(function() {\n\t        validity.field = this;\n\t        _this.markField(validity);\n\t      });\n\t    }\n\n\t    return validity;\n\t  };\n\n\t  // Run custom validate\n\t  // NOTE: async custom validate should return Deferred project\n\t  var customValidate;\n\t  (typeof options.validate === 'function') &&\n\t    (customValidate = options.validate.call(this, validity));\n\n\t  // Deferred\n\t  if (customValidate) {\n\t    var dfd = new $.Deferred();\n\t    $field.data('amui.dfdValidity', dfd.promise());\n\t    return $.when(customValidate).always(function(validity) {\n\t      dfd[validity.valid ? 'resolve' : 'reject'](validity);\n\t      validateComplete.call(_this, validity);\n\t    });\n\t  }\n\n\t  validateComplete.call(this, validity);\n\t};\n\n\tValidator.prototype.markField = function(validity) {\n\t  var options = this.options;\n\t  var flag = 'mark' + (validity.valid ? '' : 'In') + 'Valid';\n\t  options[flag] && options[flag].call(this, validity);\n\t};\n\n\t// check all fields in the form are valid\n\tValidator.prototype.validateForm = function() {\n\t  var _this = this;\n\t  var $element = this.$element;\n\t  var options = this.options;\n\t  var $allFields = $element.find(options.allFields).not(options.ignore);\n\t  var radioNames = [];\n\t  var valid = true;\n\t  var formValidity = [];\n\t  var $inValidFields = $([]);\n\t  var promises = [];\n\t  // for async validate\n\t  var async = false;\n\n\t  $element.trigger('validate.form.validator.amui');\n\n\t  // Filter radio with the same name and keep only one,\n\t  //   since they will be checked as a group by validate()\n\t  var $filteredFields = $allFields.filter(function(index) {\n\t    var name;\n\t    if (this.tagName === 'INPUT' && this.type === 'radio') {\n\t      name = this.name;\n\t      if (radioNames[name] === true) {\n\t        return false;\n\t      }\n\t      radioNames[name] = true;\n\t    }\n\t    return true;\n\t  });\n\n\t  $filteredFields.each(function() {\n\t    var $this = $(this);\n\t    var fieldValid = _this.isValid(this);\n\t    var fieldValidity = $this.data('validity');\n\n\t    valid = !!fieldValid && valid;\n\t    formValidity.push(fieldValidity);\n\n\t    if (!fieldValid) {\n\t      $inValidFields = $inValidFields.add($(this), $element);\n\t    }\n\n\t    // async validity\n\t    var promise = $this.data('amui.dfdValidity');\n\n\t    if (promise) {\n\t      promises.push(promise);\n\t      async = true;\n\t    } else {\n\t      // convert sync validity to Promise\n\t      var dfd = new $.Deferred();\n\t      promises.push(dfd.promise());\n\t      dfd[fieldValid ? 'resolve' : 'reject'](fieldValidity);\n\t    }\n\t  });\n\n\t  // NOTE: If there are async validity, the valid may be not exact result.\n\t  var validity = {\n\t    valid: valid,\n\t    $invalidFields: $inValidFields,\n\t    validity: formValidity,\n\t    promises: promises,\n\t    async: async\n\t  };\n\n\t  $element.trigger('validated.form.validator.amui', validity);\n\n\t  return validity;\n\t};\n\n\tValidator.prototype.isFormValid = function() {\n\t  var _this = this;\n\t  var formValidity = this.validateForm();\n\t  var triggerValid = function(type) {\n\t    _this.$element.trigger(type + '.validator.amui');\n\t  };\n\n\t  if (formValidity.async) {\n\t    var masterDfd = new $.Deferred();\n\n\t    $.when.apply(null, formValidity.promises).then(function() {\n\t      masterDfd.resolve();\n\t      triggerValid('valid');\n\t    }, function() {\n\t      masterDfd.reject();\n\t      triggerValid('invalid');\n\t    });\n\n\t    return masterDfd.promise();\n\t  } else {\n\t    if (!formValidity.valid) {\n\t      var $first = formValidity.$invalidFields.first();\n\n\t      // Selected plugin support\n\t      // @since 2.5\n\t      if ($first.is('[data-am-selected]')) {\n\t        $first = $first.next('.am-selected').find('.am-selected-btn');\n\t      }\n\n\t      $first.focus();\n\t      triggerValid('invalid');\n\t      return false;\n\t    }\n\n\t    triggerValid('valid');\n\t    return true;\n\t  }\n\t};\n\n\t// customErrors:\n\t//    1. tooShort\n\t//    2. checkedOverflow\n\t//    3. checkedUnderflow\n\tValidator.prototype.createValidity = function(validity) {\n\t  return $.extend({\n\t    customError: validity.customError || false,\n\t    patternMismatch: validity.patternMismatch || false,\n\t    rangeOverflow: validity.rangeOverflow || false, // higher than maximum\n\t    rangeUnderflow: validity.rangeUnderflow || false, // lower than  minimum\n\t    stepMismatch: validity.stepMismatch || false,\n\t    tooLong: validity.tooLong || false,\n\t    // value is not in the correct syntax\n\t    typeMismatch: validity.typeMismatch || false,\n\t    valid: validity.valid || true,\n\t    // Returns true if the element has no value but is a required field\n\t    valueMissing: validity.valueMissing || false\n\t  }, validity);\n\t};\n\n\tValidator.prototype.getValidationMessage = function(validity) {\n\t  var messages = Validator.validationMessages[this.options.locales];\n\t  var error;\n\t  var message;\n\t  var placeholder = '%s';\n\t  var $field = $(validity.field);\n\n\t  if ($field.is('[type=\"checkbox\"]') || $field.is('[type=\"radio\"]')) {\n\t    $field = this.$element.find('[name=' + $field.attr('name') + ']').first();\n\t  }\n\n\t  // get error name\n\t  $.each(validity, function(key, val) {\n\t    // skip `field` and `valid`\n\t    if (key === 'field' || key === 'valid') {\n\t      return key;\n\t    }\n\n\t    // Amaze UI custom error type\n\t    if (key === 'customError' && val) {\n\t      error = val;\n\t      messages = messages.customError;\n\t      return false;\n\t    }\n\n\t    // W3C specs error type\n\t    if (val === true) {\n\t      error = key;\n\t      return false;\n\t    }\n\t  });\n\n\t  message = messages[error] || undefined;\n\n\t  if (message && Validator.ERROR_MAP[error]) {\n\t    message = message.replace(placeholder,\n\t      $field.attr(Validator.ERROR_MAP[error]) || '规定的');\n\t  }\n\n\t  return message;\n\t};\n\n\t// remove valid mark\n\tValidator.prototype.removeMark = function() {\n\t  this.$element\n\t    .find('.am-form-success, .am-form-error, .' + this.options.inValidClass +\n\t      ', .' + this.options.validClass)\n\t    .removeClass([\n\t      'am-form-success',\n\t      'am-form-error',\n\t      this.options.inValidClass,\n\t      this.options.validClass\n\t    ].join(' '));\n\t};\n\n\t// @since 2.5\n\tValidator.prototype.destroy = function() {\n\t  this.removeMark();\n\n\t  // Remove data\n\t  // - Validator.prototype.init -> $element.data('amui.checked')\n\t  // - Validator.prototype.validateForm\n\t  // - Validator.prototype.isValid\n\t  this.$element.removeData('amui.validator amui.checked')\n\t    .off('.validator.amui')\n\t    .find(this.options.allFields).removeData('validity amui.dfdValidity');\n\t};\n\n\tUI.plugin('validator', Validator);\n\n\t// init code\n\tUI.ready(function(context) {\n\t  $('[data-am-validator]', context).validator();\n\t});\n\n\tmodule.exports = Validator;\n\n\n/***/ },\n/* 31 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar UI = __webpack_require__(2);\n\n\tvar cookie = {\n\t  get: function(name) {\n\t    var cookieName = encodeURIComponent(name) + '=';\n\t    var cookieStart = document.cookie.indexOf(cookieName);\n\t    var cookieValue = null;\n\t    var cookieEnd;\n\n\t    if (cookieStart > -1) {\n\t      cookieEnd = document.cookie.indexOf(';', cookieStart);\n\t      if (cookieEnd == -1) {\n\t        cookieEnd = document.cookie.length;\n\t      }\n\t      cookieValue = decodeURIComponent(document.cookie.substring(cookieStart +\n\t      cookieName.length, cookieEnd));\n\t    }\n\n\t    return cookieValue;\n\t  },\n\n\t  set: function(name, value, expires, path, domain, secure) {\n\t    var cookieText = encodeURIComponent(name) + '=' +\n\t      encodeURIComponent(value);\n\n\t    if (expires instanceof Date) {\n\t      cookieText += '; expires=' + expires.toUTCString();\n\t    }\n\n\t    if (path) {\n\t      cookieText += '; path=' + path;\n\t    }\n\n\t    if (domain) {\n\t      cookieText += '; domain=' + domain;\n\t    }\n\n\t    if (secure) {\n\t      cookieText += '; secure';\n\t    }\n\n\t    document.cookie = cookieText;\n\t  },\n\n\t  unset: function(name, path, domain, secure) {\n\t    this.set(name, '', new Date(0), path, domain, secure);\n\t  }\n\t};\n\n\tUI.utils = UI.utils || {};\n\n\tmodule.exports = UI.utils.cookie = cookie;\n\n\n/***/ },\n/* 32 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\t/**\n\t * @via https://github.com/sindresorhus/screenfull.js\n\t * @license MIT © Sindre Sorhus\n\t */\n\n\tvar UI = __webpack_require__(2);\n\tvar screenfull = (function() {\n\t  var keyboardAllowed = typeof Element !== 'undefined' &&\n\t    'ALLOW_KEYBOARD_INPUT' in Element;\n\n\t  var fn = (function() {\n\t    var val;\n\t    var valLength;\n\n\t    var fnMap = [\n\t      [\n\t        'requestFullscreen',\n\t        'exitFullscreen',\n\t        'fullscreenElement',\n\t        'fullscreenEnabled',\n\t        'fullscreenchange',\n\t        'fullscreenerror'\n\t      ],\n\t      // new WebKit\n\t      [\n\t        'webkitRequestFullscreen',\n\t        'webkitExitFullscreen',\n\t        'webkitFullscreenElement',\n\t        'webkitFullscreenEnabled',\n\t        'webkitfullscreenchange',\n\t        'webkitfullscreenerror'\n\n\t      ],\n\t      // old WebKit (Safari 5.1)\n\t      [\n\t        'webkitRequestFullScreen',\n\t        'webkitCancelFullScreen',\n\t        'webkitCurrentFullScreenElement',\n\t        'webkitCancelFullScreen',\n\t        'webkitfullscreenchange',\n\t        'webkitfullscreenerror'\n\n\t      ],\n\t      [\n\t        'mozRequestFullScreen',\n\t        'mozCancelFullScreen',\n\t        'mozFullScreenElement',\n\t        'mozFullScreenEnabled',\n\t        'mozfullscreenchange',\n\t        'mozfullscreenerror'\n\t      ],\n\t      [\n\t        'msRequestFullscreen',\n\t        'msExitFullscreen',\n\t        'msFullscreenElement',\n\t        'msFullscreenEnabled',\n\t        'MSFullscreenChange',\n\t        'MSFullscreenError'\n\t      ]\n\t    ];\n\n\t    var i = 0;\n\t    var l = fnMap.length;\n\t    var ret = {};\n\n\t    for (; i < l; i++) {\n\t      val = fnMap[i];\n\t      if (val && val[1] in document) {\n\t        for (i = 0, valLength = val.length; i < valLength; i++) {\n\t          ret[fnMap[0][i]] = val[i];\n\t        }\n\t        return ret;\n\t      }\n\t    }\n\n\t    return false;\n\t  })();\n\n\t  var screenfull = {\n\t    request: function(elem) {\n\t      var request = fn.requestFullscreen;\n\n\t      elem = elem || document.documentElement;\n\n\t      // Work around Safari 5.1 bug: reports support for\n\t      // keyboard in fullscreen even though it doesn't.\n\t      // Browser sniffing, since the alternative with\n\t      // setTimeout is even worse.\n\t      if (/5\\.1[\\.\\d]* Safari/.test(navigator.userAgent)) {\n\t        elem[request]();\n\t      } else {\n\t        elem[request](keyboardAllowed && Element.ALLOW_KEYBOARD_INPUT);\n\t      }\n\t    },\n\t    exit: function() {\n\t      document[fn.exitFullscreen]();\n\t    },\n\t    toggle: function(elem) {\n\t      if (this.isFullscreen) {\n\t        this.exit();\n\t      } else {\n\t        this.request(elem);\n\t      }\n\t    },\n\t    raw: fn\n\t  };\n\n\t  if (!fn) {\n\t    return false;\n\t  }\n\n\t  Object.defineProperties(screenfull, {\n\t    isFullscreen: {\n\t      get: function() {\n\t        return !!document[fn.fullscreenElement];\n\t      }\n\t    },\n\t    element: {\n\t      enumerable: true,\n\t      get: function() {\n\t        return document[fn.fullscreenElement];\n\t      }\n\t    },\n\t    enabled: {\n\t      enumerable: true,\n\t      get: function() {\n\t        // Coerce to boolean in case of old WebKit\n\t        return !!document[fn.fullscreenEnabled];\n\t      }\n\t    }\n\t  });\n\n\t  screenfull.VERSION = '3.0.0';\n\n\t  return screenfull;\n\t})();\n\n\tmodule.exports = UI.fullscreen = screenfull;\n\n\n/***/ },\n/* 33 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\tUI.support.geolocation = window.navigator && window.navigator.geolocation;\n\n\tvar geo = UI.support.geolocation;\n\n\tvar Geolocation = function(options) {\n\t  this.options = options || {};\n\t};\n\n\tGeolocation.MESSAGES = {\n\t  unsupportedBrowser: 'Browser does not support location services',\n\t  permissionDenied: 'You have rejected access to your location',\n\t  positionUnavailable: 'Unable to determine your location',\n\t  timeout: 'Service timeout has been reached'\n\t};\n\n\tGeolocation.ERROR_CODE = {\n\t  0: 'unsupportedBrowser',\n\t  1: 'permissionDenied',\n\t  2: 'positionUnavailable',\n\t  3: 'timeout'\n\t};\n\n\tGeolocation.prototype.get = function(options) {\n\t  var _this = this;\n\t  options = $.extend({}, this.options, options);\n\t  var deferred = new $.Deferred();\n\n\t  if (geo) {\n\t    this.watchID = geo.getCurrentPosition(function(position) {\n\t      deferred.resolve.call(_this, position);\n\t    }, function(error) {\n\t      deferred.reject(Geolocation.MESSAGES[Geolocation.ERROR_CODE[error.code]]);\n\t    }, options);\n\t  } else {\n\t    deferred.reject(Geolocation.MESSAGES.unsupportedBrowser);\n\t  }\n\n\t  return deferred.promise();\n\t};\n\n\tGeolocation.prototype.watch = function(options) {\n\t  if (!geo) {\n\t    return;\n\t  }\n\n\t  options = $.extend({}, this.options, options);\n\n\t  if (!$.isFunction(options.done)) {\n\t    return;\n\t  }\n\n\t  this.clearWatch();\n\n\t  var fail = $.isFunction(options.fail) ? options.fail : null;\n\n\t  this.watchID = geo.watchPosition(options.done, fail, options);\n\n\t  return this.watchID;\n\t};\n\n\tGeolocation.prototype.clearWatch = function() {\n\t  if (!geo || !this.watchID) {\n\t    return;\n\t  }\n\t  geo.clearWatch(this.watchID);\n\t  this.watchID = null;\n\t};\n\n\tmodule.exports = UI.Geolocation = Geolocation;\n\n\n/***/ },\n/* 34 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t/* WEBPACK VAR INJECTION */(function(global) {'use strict';\n\n\tvar UI = __webpack_require__(2);\n\n\t/**\n\t * store.js\n\t * @via https://github.com/marcuswestin/store.js\n\t * @license https://github.com/marcuswestin/store.js/blob/master/LICENSE\n\t */\n\n\tvar store = {};\n\tvar win = (typeof window != 'undefined' ? window : global);\n\tvar localStorageName = 'localStorage';\n\tvar storage;\n\n\tstore.disabled = false;\n\tstore.version = '1.3.20';\n\n\tstore.set = function(key, value) {\n\t};\n\n\tstore.get = function(key, defaultVal) {\n\t};\n\n\tstore.has = function(key) {\n\t  return store.get(key) !== undefined;\n\t};\n\n\tstore.remove = function(key) {\n\t};\n\n\tstore.clear = function() {\n\t};\n\n\tstore.transact = function(key, defaultVal, transactionFn) {\n\t  if (transactionFn == null) {\n\t    transactionFn = defaultVal;\n\t    defaultVal = null;\n\t  }\n\t  if (defaultVal == null) {\n\t    defaultVal = {};\n\t  }\n\n\t  var val = store.get(key, defaultVal);\n\t  transactionFn(val);\n\t  store.set(key, val);\n\t};\n\n\tstore.getAll = function() {\n\t};\n\n\tstore.forEach = function() {\n\t};\n\n\tstore.serialize = function(value) {\n\t  return JSON.stringify(value);\n\t};\n\n\tstore.deserialize = function(value) {\n\t  if (typeof value != 'string') {\n\t    return undefined;\n\t  }\n\n\t  try {\n\t    return JSON.parse(value);\n\t  } catch (e) {\n\t    return value || undefined;\n\t  }\n\t};\n\n\t// Functions to encapsulate questionable FireFox 3.6.13 behavior\n\t// when about.config::dom.storage.enabled === false\n\t// See https://github.com/marcuswestin/store.js/issues#issue/13\n\tfunction isLocalStorageNameSupported() {\n\t  try {\n\t    return (localStorageName in win && win[localStorageName]);\n\t  } catch (err) {\n\t    return false;\n\t  }\n\t}\n\n\tif (isLocalStorageNameSupported()) {\n\t  storage = win[localStorageName];\n\n\t  store.set = function(key, val) {\n\t    if (val === undefined) {\n\t      return store.remove(key);\n\t    }\n\t    storage.setItem(key, store.serialize(val));\n\t    return val;\n\t  };\n\n\t  store.get = function(key, defaultVal) {\n\t    var val = store.deserialize(storage.getItem(key));\n\t    return (val === undefined ? defaultVal : val);\n\t  };\n\n\t  store.remove = function(key) {\n\t    storage.removeItem(key);\n\t  };\n\n\t  store.clear = function() {\n\t    storage.clear();\n\t  };\n\n\t  store.getAll = function() {\n\t    var ret = {};\n\t    store.forEach(function(key, val) {\n\t      ret[key] = val;\n\t    });\n\t    return ret;\n\t  };\n\n\t  store.forEach = function(callback) {\n\t    for (var i = 0; i < storage.length; i++) {\n\t      var key = storage.key(i);\n\t      callback(key, store.get(key));\n\t    }\n\t  };\n\t}\n\n\ttry {\n\t  var testKey = '__storejs__';\n\t  store.set(testKey, testKey);\n\t  if (store.get(testKey) != testKey) {\n\t    store.disabled = true;\n\t  }\n\t  store.remove(testKey);\n\t} catch (e) {\n\t  store.disabled = true;\n\t}\n\n\tstore.enabled = !store.disabled;\n\n\tmodule.exports = UI.store = store;\n\n\t/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))\n\n/***/ },\n/* 35 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\t__webpack_require__(7);\n\n\tfunction accordionInit() {\n\t  var $accordion = $('[data-am-widget=\"accordion\"]');\n\t  var selector = {\n\t    item: '.am-accordion-item',\n\t    title: '.am-accordion-title',\n\t    body: '.am-accordion-bd',\n\t    disabled: '.am-disabled'\n\t  };\n\n\t  $accordion.each(function(i, item) {\n\t    var options = UI.utils.parseOptions($(item).attr('data-am-accordion'));\n\t    var $title = $(item).find(selector.title);\n\n\t    $title.on('click.accordion.amui', function() {\n\t      var $collapse = $(this).next(selector.body);\n\t      var $parent = $(this).parent(selector.item);\n\t      var data = $collapse.data('amui.collapse');\n\n\t      if ($parent.is(selector.disabled)) {\n\t        return;\n\t      }\n\n\t      $parent.toggleClass('am-active');\n\n\t      if (!data) {\n\t        $collapse.collapse();\n\t      } else {\n\t        $collapse.collapse('toggle');\n\t      }\n\n\t      !options.multiple &&\n\t      $(item).children('.am-active').\n\t        not($parent).not(selector.disabled).removeClass('am-active').\n\t        find(selector.body + '.am-in').collapse('close');\n\t    });\n\t  });\n\t}\n\n\t// Init on DOM ready\n\t$(accordionInit);\n\n\tmodule.exports = UI.accordion = {\n\t  VERSION: '2.1.0',\n\t  init: accordionInit\n\t};\n\n\n/***/ },\n/* 36 */\n/***/ function(module, exports) {\n\n\t'use strict';\n\n\tmodule.exports = {\n\t  VERSION: '2.0.1'\n\t};\n\n\n/***/ },\n/* 37 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\n\tfunction duoshuoInit() {\n\t  var $dsThread = $('.ds-thread');\n\t  var dsShortName = $dsThread.parent('[data-am-widget=\"duoshuo\"]').\n\t    attr('data-ds-short-name');\n\t  var dsSrc = (document.location.protocol == 'https:' ? 'https:' : 'http:') +\n\t    '//static.duoshuo.com/embed.js';\n\n\t  if (!$dsThread.length || !dsShortName) {\n\t    return;\n\t  }\n\n\t  window.duoshuoQuery = {\n\t    short_name: dsShortName\n\t  };\n\n\t  // 已经有多说脚本\n\t  if ($('script[src=\"' + dsSrc + '\"]').length) {\n\t    return;\n\t  }\n\n\t  var $dsJS = $('<script>', {\n\t    async: true,\n\t    type: 'text/javascript',\n\t    src: dsSrc,\n\t    charset: 'utf-8'\n\t  });\n\n\t  $('body').append($dsJS);\n\t}\n\n\t$(window).on('load', duoshuoInit);\n\n\tmodule.exports = UI.duoshuo = {\n\t  VERSION: '2.0.1',\n\t  init: duoshuoInit\n\t};\n\n\n/***/ },\n/* 38 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\t__webpack_require__(20);\n\n\t/**\n\t * Is Images zoomable\n\t * @return {Boolean}\n\t */\n\t$.isImgZoomAble = function(element) {\n\t  var t = new Image();\n\t  t.src = element.src;\n\n\t  var zoomAble = ($(element).width() < t.width);\n\n\t  if (zoomAble) {\n\t    $(element).closest('.am-figure').addClass('am-figure-zoomable');\n\t  }\n\n\t  return zoomAble;\n\t};\n\n\tfunction figureInit() {\n\t  $('.am-figure').each(function(i, item) {\n\t    var options = UI.utils.parseOptions($(item).attr('data-am-figure'));\n\t    var $item = $(item);\n\t    var data;\n\n\t    if (options.pureview) {\n\t      if (options.pureview === 'auto') {\n\t        var zoomAble = $.isImgZoomAble($item.find('img')[0]);\n\t        zoomAble && $item.pureview();\n\t      } else {\n\t        $item.addClass('am-figure-zoomable').pureview();\n\t      }\n\t    }\n\n\t    data = $item.data('amui.pureview');\n\n\t    if (data) {\n\t      $item.on('click', ':not(img)', function() {\n\t        data.open(0);\n\t      });\n\t    }\n\t  });\n\t}\n\n\t$(window).on('load', figureInit);\n\n\tmodule.exports = UI.figure = {\n\t  VERSION: '2.0.3',\n\t  init: figureInit\n\t};\n\n\n/***/ },\n/* 39 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\t__webpack_require__(15);\n\tvar addToHS = __webpack_require__(4);\n\tvar cookie = __webpack_require__(31);\n\n\tfunction footerInit() {\n\t  // modal mode\n\t  $('.am-footer-ysp').on('click', function() {\n\t    $('#am-footer-modal').modal();\n\t  });\n\n\t  var options = UI.utils.parseOptions($('.am-footer').data('amFooter'));\n\t  options.addToHS && addToHS();\n\n\t  // switch mode\n\t  // switch to desktop\n\t  $('[data-rel=\"desktop\"]').on('click', function(e) {\n\t    e.preventDefault();\n\t    if (window.AMPlatform) { // front end\n\t      window.AMPlatform.util.goDesktop();\n\t    } else { // back end\n\t      cookie.set('allmobilize', 'desktop', '', '/');\n\t      window.location = window.location;\n\t    }\n\t  });\n\t}\n\n\t$(footerInit);\n\n\tmodule.exports = UI.footer = {\n\t  VERSION: '3.1.2',\n\t  init: footerInit\n\t};\n\n\n/***/ },\n/* 40 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\t__webpack_require__(20);\n\n\tfunction galleryInit() {\n\t  var $gallery = $('[data-am-widget=\"gallery\"]');\n\n\t  $gallery.each(function() {\n\t    var options = UI.utils.parseOptions($(this).attr('data-am-gallery'));\n\n\t    if (options.pureview) {\n\t      (typeof options.pureview === 'object') ?\n\t        $(this).pureview(options.pureview) : $(this).pureview();\n\t    }\n\t  });\n\t}\n\n\t$(galleryInit);\n\n\tmodule.exports = UI.gallery = {\n\t  VERSION: '3.0.0',\n\t  init: galleryInit\n\t};\n\n\n/***/ },\n/* 41 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\t__webpack_require__(23);\n\n\tfunction goTopInit() {\n\t  var $goTop = $('[data-am-widget=\"gotop\"]');\n\t  var $fixed = $goTop.filter('.am-gotop-fixed');\n\t  var $win = $(window);\n\n\t  if ($goTop.data('init')) {\n\t    return;\n\t  }\n\n\t  $goTop.find('a').on('click', function(e) {\n\t    e.preventDefault();\n\t    $win.smoothScroll();\n\t  });\n\n\t  function checkPosition() {\n\t    $fixed[($win.scrollTop() > 50 ? 'add' : 'remove') + 'Class']('am-active');\n\t  }\n\n\t  checkPosition();\n\n\t  $win.on('scroll.gotop.amui', UI.utils.debounce(checkPosition, 100));\n\n\t  $goTop.data('init', true);\n\t}\n\n\t$(goTopInit);\n\n\tmodule.exports = UI.gotop = {\n\t  VERSION: '4.0.2',\n\t  init: goTopInit\n\t};\n\n\n/***/ },\n/* 42 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\n\tfunction headerInit() {\n\t  $('[data-am-widget=\"header\"]').each(function() {\n\t    if ($(this).hasClass('am-header-fixed')) {\n\t      $('body').addClass('am-with-fixed-header');\n\t      return false;\n\t    }\n\t  });\n\t}\n\n\t$(headerInit);\n\n\tmodule.exports = UI.header = {\n\t  VERSION: '2.0.0',\n\t  init: headerInit\n\t};\n\n\n/***/ },\n/* 43 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar UI = __webpack_require__(2);\n\n\tmodule.exports = UI.intro = {\n\t  VERSION: '4.0.2',\n\t  init: function() {}\n\t};\n\n\n/***/ },\n/* 44 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar UI = __webpack_require__(2);\n\n\tmodule.exports = UI.listNews = {\n\t  VERSION: '4.0.0',\n\t  init: function() {}\n\t};\n\n\n/***/ },\n/* 45 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t/* jshint strict: false, maxlen: 200 */\n\t/* global BMap */\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\n\tfunction addMapApi(callback) {\n\t  var $mapApi0 = $('<script />', {\n\t    id: 'am-map-api-0'\n\t  });\n\n\t  $('body').append($mapApi0);\n\n\t  $mapApi0.on('load', function() {\n\t    console.log('load');\n\t    var $mapApi1 = $('<script/>', {\n\t      id: 'am-map-api-1'\n\t    });\n\n\t    $('body').append($mapApi1);\n\n\t    $mapApi1.on('load', function() {\n\t      var script = document.createElement('script');\n\t      script.textContent = '(' + callback.toString() + ')();';\n\t      $('body')[0].appendChild(script);\n\t    }).attr('src', 'http://api.map.baidu.com/getscript' +\n\t      '?type=quick&file=feature' +\n\t      '&ak=WVAXZ05oyNRXS5egLImmentg&t=20140109092002');\n\t  }).attr('src', 'http://api.map.baidu.com/getscript' +\n\t  '?type=quick&file=api&ak=WVAXZ05oyNRXS5egLImmentg&t=20140109092002');\n\n\t  // jQuery 中 `load` 事件触发有问题，动态设置 src 属性才会触发 `load` 事件\n\t  // $mapApi0 = $('<script />', {src: 'xxx'}); 这样的写法在 Zepto.js 中则没有问题\n\t}\n\n\tfunction addBdMap() {\n\t  // 如果使用 $ 选择符，minify 以后会报错: $ is undefined\n\t  // 即使传入 $ 也无效，改为使用原生方法\n\t  // 这个函数作为 callback 会插入到 body 以后才执行，应该是 $ 引用错误导致\n\t  var content = document.querySelector('.am-map');\n\t  var defaultLng = 116.331398; // 经度默认值\n\t  var defaultLat = 39.897445;  // 纬度默认值\n\t  var name = content.getAttribute('data-name');\n\t  var address = content.getAttribute('data-address');\n\t  var lng = content.getAttribute('data-longitude') || defaultLng;\n\t  var lat = content.getAttribute('data-latitude') || defaultLat;\n\t  var setZoom = content.getAttribute('data-setZoom') || 17;\n\t  var icon = content.getAttribute('data-icon');\n\n\t  var map = new BMap.Map('bd-map');\n\n\t  // 实例化一个地理坐标点\n\t  var point = new BMap.Point(lng, lat);\n\n\t  // 设初始化地图, options: 3-18\n\t  map.centerAndZoom(point, setZoom);\n\n\t  // 添加地图缩放控件\n\t  if (content.getAttribute('data-zoomControl')) {\n\t    map.addControl(new BMap.ZoomControl());\n\t  }\n\n\t  // 添加比例尺控件\n\t  if (content.getAttribute('data-scaleControl')) {\n\t    map.addControl(new BMap.ScaleControl());\n\t  }\n\n\t  // 创建标准与自定义 icon\n\t  var marker = new BMap.Marker(point);\n\t  if (icon) {\n\t    marker.setIcon(new BMap.Icon(icon, new BMap.Size(40, 40)));\n\t  }\n\n\t  var opts = {\n\t    width: 200,     // 信息窗口宽度\n\t    // height: 'auto',     // 信息窗口高度\n\t    title: name // 信息窗口标题\n\t  };\n\n\t  // 创建信息窗口对象\n\t  var infoWindow = new BMap.InfoWindow('地址：' + address, opts);\n\n\t  // 创建地址解析器实例\n\t  var myGeo = new BMap.Geocoder();\n\n\t  // 判断有没有使用经纬度\n\t  if (lng == defaultLng && lat == defaultLat) {\n\t    // 使用地址反解析来设置地图\n\t    // 将地址解析结果显示在地图上,并调整地图视野\n\t    myGeo.getPoint(address, function(point) {\n\t      if (point) {\n\t        map.centerAndZoom(point, setZoom);\n\t        marker.setPosition(point);\n\t        map.addOverlay(marker);\n\t        map.openInfoWindow(infoWindow, point); // 开启信息窗口\n\t      }\n\t    }, '');\n\n\t  } else {\n\t    // 使用经纬度来设置地图\n\t    myGeo.getLocation(point, function(result) {\n\t      map.centerAndZoom(point, setZoom);\n\t      marker.setPosition(point);\n\t      map.addOverlay(marker);\n\t      if (address) {\n\t        map.openInfoWindow(infoWindow, point); // 开启信息窗口\n\t      } else {\n\t        map.openInfoWindow(new BMap.InfoWindow(address, opts), point); // 开启信息窗口\n\t      }\n\t    });\n\t  }\n\t}\n\n\tvar mapInit = function() {\n\t  $('.am-map').length && addMapApi(addBdMap);\n\t};\n\n\t$(mapInit);\n\n\tmodule.exports = UI.map = {\n\t  VERSION: '2.0.2',\n\t  init: mapInit\n\t};\n\n\n/***/ },\n/* 46 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\n\tfunction mechatInit() {\n\t  if (!$('#mechat').length) {\n\t    return;\n\t  }\n\n\t  var $mechat = $('[data-am-widget=\"mechat\"]');\n\t  var unitid = $mechat.data('am-mechat-unitid');\n\t  var $mechatData = $('<script>', {\n\t    charset: 'utf-8',\n\t    src: 'http://mechatim.com/js/unit/button.js?id=' + unitid\n\t  });\n\n\t  $('body').append($mechatData);\n\t}\n\n\t// Lazy load\n\t$(window).on('load', mechatInit);\n\n\tmodule.exports = UI.mechat = {\n\t  VERSION: '2.0.1',\n\t  init: mechatInit\n\t};\n\n\n/***/ },\n/* 47 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\tvar IScroll = __webpack_require__(14);\n\t__webpack_require__(16);\n\t__webpack_require__(7);\n\n\tvar menuInit = function() {\n\t  var $menus = $('[data-am-widget=\"menu\"]');\n\n\t  $menus.find('.am-menu-nav .am-parent > a').on('click', function(e) {\n\t    e.preventDefault();\n\t    var $clicked = $(this);\n\t    var $parent = $clicked.parent();\n\t    var $subMenu = $clicked.next('.am-menu-sub');\n\n\t    $parent.toggleClass('am-open');\n\t    $subMenu.collapse('toggle');\n\t    $parent.siblings('.am-parent').removeClass('am-open')\n\t      .children('.am-menu-sub.am-in').collapse('close');\n\t  });\n\n\t  // Dropdown/slideDown menu\n\t  $menus.\n\t    filter('[data-am-menu-collapse]').\n\t    find('> .am-menu-toggle').\n\t    on('click', function(e) {\n\t      e.preventDefault();\n\t      var $this = $(this);\n\t      var $nav = $this.next('.am-menu-nav');\n\n\t      $this.toggleClass('am-active');\n\n\t      $nav.collapse('toggle');\n\t    });\n\n\t  // OffCanvas menu\n\t  $menus.\n\t    filter('[data-am-menu-offcanvas]').\n\t    find('> .am-menu-toggle').\n\t    on('click', function(e) {\n\t      e.preventDefault();\n\t      var $this = $(this);\n\t      var $nav = $this.next('.am-offcanvas');\n\n\t      $this.toggleClass('am-active');\n\n\t      $nav.offCanvas('open');\n\t    });\n\n\t  // Close offCanvas when link clicked\n\t  var autoCloseOffCanvas = '.am-offcanvas[data-dismiss-on=\"click\"]';\n\t  var $autoCloseOffCanvas = $(autoCloseOffCanvas);\n\n\t  $autoCloseOffCanvas.find('a').not('.am-parent>a').on('click', function(e) {\n\t    $(this).parents(autoCloseOffCanvas).offCanvas('close');\n\t  });\n\n\t  // one theme\n\t  $menus.filter('.am-menu-one').each(function(index) {\n\t    var $this = $(this);\n\t    var $wrap = $('<div class=\"am-menu-nav-sub-wrap\"></div>');\n\t    var allWidth = 0;\n\t    var $nav = $this.find('.am-menu-nav');\n\t    var $navTopItem = $nav.children('li');\n\t    var prevIndex;\n\n\t    $navTopItem.filter('.am-parent').each(function(index) {\n\t      $(this).attr('data-rel', '#am-menu-sub-' + index);\n\t      $(this).\n\t        find('.am-menu-sub').\n\t        attr('id', 'am-menu-sub-' + index).\n\t        appendTo($wrap);\n\t    });\n\n\t    $this.append($wrap);\n\n\t    $nav.wrap('<div class=\"am-menu-nav-wrap\" id=\"am-menu-' + index + '\">');\n\n\t    // $navTopItem.eq(0).addClass('am-active');\n\n\t    // 计算出所有 li 宽度\n\t    $navTopItem.each(function(i) {\n\t      allWidth += parseFloat($(this).css('width'));\n\t    });\n\n\t    $nav.width(allWidth);\n\n\t    var menuScroll = new IScroll('#am-menu-' + index, {\n\t      eventPassthrough: true,\n\t      scrollX: true,\n\t      scrollY: false,\n\t      preventDefault: false\n\t    });\n\n\t    $navTopItem.on('click', function() {\n\t      var $clicked = $(this);\n\t      $clicked.addClass('am-active').siblings().removeClass('am-active');\n\n\t      $wrap.find('.am-menu-sub.am-in').collapse('close');\n\n\t      if ($clicked.is('.am-parent')) {\n\t        !$clicked.hasClass('.am-open') &&\n\t        $wrap.find($clicked.attr('data-rel')).collapse('open');\n\t      } else {\n\t        $clicked.siblings().removeClass('am-open');\n\t      }\n\n\t      // 第一次调用，没有prevIndex\n\t      if (prevIndex === undefined) {\n\t        prevIndex = $(this).index() ? 0 : 1;\n\t      }\n\n\t      // 判断方向\n\t      var dir = $(this).index() > prevIndex;\n\t      var target = $(this)[dir ? 'next' : 'prev']();\n\n\t      // 点击的按钮，显示一半\n\t      var offset = target.offset() || $(this).offset();\n\t      var within = $this.offset();\n\n\t      // 父类左边距\n\t      var listOffset;\n\t      var parentLeft = parseInt($this.css('padding-left'));\n\n\t      if (dir ? offset.left + offset.width > within.left + within.width :\n\t        offset.left < within.left) {\n\t        listOffset = $nav.offset();\n\t        menuScroll.scrollTo(dir ?\n\t        within.width - offset.left + listOffset.left -\n\t        offset.width - parentLeft :\n\t        listOffset.left - offset.left, 0, 400);\n\t      }\n\n\t      prevIndex = $(this).index();\n\n\t    });\n\n\t    $this.on('touchmove', function(event) {\n\t      event.preventDefault();\n\t    });\n\t  });\n\t};\n\n\t$(menuInit);\n\n\tmodule.exports = UI.menu = {\n\t  VERSION: '4.0.3',\n\t  init: menuInit\n\t};\n\n\n/***/ },\n/* 48 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\tvar share = __webpack_require__(25);\n\tvar QRCode = __webpack_require__(26);\n\t__webpack_require__(15);\n\n\tfunction navbarInit() {\n\t  var $navBar = $('[data-am-widget=\"navbar\"]');\n\n\t  if (!$navBar.length) {\n\t    return;\n\t  }\n\n\t  var $win = $(window);\n\t  var $body = $('body');\n\t  var $navBarNav = $navBar.find('.am-navbar-nav');\n\t  var $navItems = $navBar.find('li');\n\t  var navItemsCounter = $navItems.length;\n\t  var configItems = $navBarNav.attr('class') &&\n\t    parseInt($navBarNav.attr('class').\n\t      match(/am-avg-sm-(\\d+)/)[1]) || 3;\n\t  var navMinWidth = 60; // 每个 li 最小宽度\n\t  var offsetWidth = 16;\n\t  var $share = $navItems.filter('[data-am-navbar-share]');\n\t  var $qrcode = $navItems.filter('[data-am-navbar-qrcode]');\n\t  var activeStatus = 'am-active';\n\t  var $moreActions = $('<ul class=\"am-navbar-actions\"></ul>', {\n\t    id: UI.utils.generateGUID('am-navbar-actions')\n\t  });\n\t  var $moreLink = $('<li class=\"am-navbar-labels am-navbar-more\">' +\n\t  '<a href=\"javascript: void(0);\">' +\n\t  '<span class=\"am-icon-angle-up\"></span>' +\n\t  '<span class=\"am-navbar-label\">更多</span></a></li>');\n\n\t  // 如果有 Fix 的工具栏则设置 body 的 padding-bottom\n\t  if ($navBar.css('position') == 'fixed') {\n\t    $body.addClass('am-with-fixed-navbar');\n\t  }\n\n\t  if ($qrcode.length) {\n\t    var qrId = 'am-navbar-qrcode';\n\t    $qrModal = $('#' + qrId);\n\n\t    if (!$qrModal.length) {\n\t      var qrImg = $qrcode.attr('data-am-navbar-qrcode');\n\t      var $qrModal = $('<div class=\"am-modal am-modal-no-btn\" id=\"\">' +\n\t      '<div class=\"am-modal-dialog\">' +\n\t      '<div class=\"am-modal-bd\"></div></div>' +\n\t      '</div>', {\n\t        id: qrId\n\t      });\n\t      var $qrContainer = $qrModal.find('.am-modal-bd');\n\n\t      // 判断上传自定义的二维码没有，否则生成二维码\n\t      if (qrImg) {\n\t        $qrContainer.html('<img src=\"' + qrImg + '\"/>');\n\t      } else {\n\t        var qrnode = new QRCode({\n\t          render: 'canvas',\n\t          correctLevel: 0,\n\t          text: window.location.href,\n\t          width: 200,\n\t          height: 200,\n\t          background: '#fff',\n\t          foreground: '#000'\n\t        });\n\t        $qrContainer.html(qrnode);\n\t      }\n\n\t      $body.append($qrModal);\n\t    }\n\n\t    $qrcode.on('click', function(e) {\n\t      e.preventDefault();\n\t      $qrModal.modal();\n\t    });\n\t  }\n\n\t  if (navItemsCounter > configItems && navItemsCounter > calcSuiteItems()) {\n\t    initActions();\n\t  }\n\n\t  // console.log('NavItems: %d, config: %d, best: %d',\n\t  //    navItemsCounter, configItems, calcSuiteItems());\n\n\t  function initActions() {\n\t    $navBarNav.append($moreLink);\n\n\t    $navBarNav.\n\t      find('li').\n\t      not('.am-navbar-more').\n\t      slice(calcSuiteItems() - 1).\n\t      appendTo($moreActions);\n\n\t    // Append more actions\n\t    $navBar.append($moreActions);\n\t  }\n\n\t  function checkNavBarItems() {\n\t    if (calcSuiteItems() >= navItemsCounter) {\n\t      // 显示所有链接，隐藏 more\n\t      $moreLink.hide();\n\t      $moreActions.find('li').insertBefore($moreLink);\n\t      return;\n\t    }\n\n\t    !$navBar.find('.am-navbar-actions').length && initActions();\n\n\t    $moreLink.show();\n\n\t    if ($navBarNav.find('li').length < calcSuiteItems()) {\n\t      $moreActions.find('li').\n\t        slice(0, calcSuiteItems() - $navBarNav.find('li').length).\n\t        insertBefore($moreLink);\n\t    } else if ($navBarNav.find('li').length > calcSuiteItems()) {\n\t      if ($moreActions.find('li').length) {\n\t        $navBarNav.find('li').not($moreLink).slice(calcSuiteItems() - 1).\n\t          insertBefore($moreActions.find('li').first());\n\t      } else {\n\t        $navBarNav.find('li').not($moreLink).slice(calcSuiteItems() - 1).\n\t          appendTo($moreActions);\n\t      }\n\t    }\n\t  }\n\n\t  /**\n\t   * 计算最适合显示的条目个数\n\t   * @returns {number}\n\t   */\n\t  function calcSuiteItems() {\n\t    return Math.floor(($win.width() - offsetWidth) / navMinWidth);\n\t  }\n\n\t  $navBar.on('click.navbar.amui', '.am-navbar-more', function(e) {\n\t    e.preventDefault();\n\n\t    $moreLink[$moreActions.hasClass(activeStatus) ?\n\t      'removeClass' : 'addClass'](activeStatus);\n\n\t    $moreActions.toggleClass(activeStatus);\n\t  });\n\n\t  if ($share.length) {\n\t    $share.on('click.navbar.amui', function(e) {\n\t      e.preventDefault();\n\t      share.toggle();\n\t    });\n\t  }\n\n\t  $win.on('resize.navbar.amui orientationchange.navbar.amui',\n\t    UI.utils.debounce(checkNavBarItems, 150));\n\t}\n\n\t// DOMContent ready\n\t$(navbarInit);\n\n\tmodule.exports = UI.navbar = {\n\t  VERSION: '2.0.2',\n\t  init: navbarInit\n\t};\n\n\n/***/ },\n/* 49 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar UI = __webpack_require__(2);\n\n\tmodule.exports = UI.pagination = {\n\t  VERSION: '3.0.1'\n\t};\n\n\n/***/ },\n/* 50 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\tvar IScroll = __webpack_require__(14);\n\t__webpack_require__(20);\n\n\t/**\n\t * 表格滚动\n\t * @param {number} index ID 标识，多个 paragraph 里面多个 table\n\t */\n\t$.fn.scrollTable = function(index) {\n\t  var $this = $(this);\n\t  var $parent;\n\n\t  $this.wrap('<div class=\"am-paragraph-table-container\" ' +\n\t  'id=\"am-paragraph-table-' + index + '\">' +\n\t  '<div class=\"am-paragraph-table-scroller\"></div></div>');\n\n\t  $parent = $this.parent();\n\t  $parent.width($this.width());\n\t  $parent.height($this.height());\n\n\t  new IScroll('#am-paragraph-table-' + index, {\n\t    eventPassthrough: true,\n\t    scrollX: true,\n\t    scrollY: false,\n\t    preventDefault: false\n\t  });\n\t};\n\n\tfunction paragraphInit() {\n\t  var $paragraph = $('[data-am-widget=\"paragraph\"]');\n\n\t  $paragraph.each(function(index) {\n\t    var $this = $(this);\n\t    var options = UI.utils.parseOptions($this.attr('data-am-paragraph'));\n\t    var $index = index;\n\n\t    if (options.pureview) {\n\t      $this.pureview();\n\t    }\n\n\t    if (options.tableScrollable) {\n\t      $this.find('table').each(function(index) {\n\t        if ($(this).width() > $(window).width()) {\n\t          $(this).scrollTable($index + '-' + index);\n\t        }\n\t      });\n\t    }\n\t  });\n\t}\n\n\t$(window).on('load', paragraphInit);\n\n\tmodule.exports = UI.paragraph = {\n\t  VERSION: '2.0.1',\n\t  init: paragraphInit\n\t};\n\n\n/***/ },\n/* 51 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\t__webpack_require__(11);\n\n\tfunction sliderInit() {\n\t  var $sliders = $('[data-am-widget=\"slider\"]');\n\t  $sliders.not('.am-slider-manual').each(function(i, item) {\n\t    var options = UI.utils.parseOptions($(item).attr('data-am-slider'));\n\t    $(item).flexslider(options);\n\t  });\n\t}\n\n\t$(sliderInit);\n\n\tmodule.exports = UI.slider = {\n\t  VERSION: '3.0.1',\n\t  init: sliderInit\n\t};\n\n\n/***/ },\n/* 52 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\t__webpack_require__(28);\n\n\tfunction tabsInit() {\n\t  $('[data-am-widget=\"tabs\"]').each(function() {\n\t    var options = $(this).data('amTabsNoswipe') ? {noSwipe: 1} : {};\n\t    $(this).tabs(options);\n\t  });\n\t}\n\n\t$(tabsInit);\n\n\tmodule.exports = UI.tab = {\n\t  VERSION: '4.0.1',\n\t  init: tabsInit\n\t};\n\n\n/***/ },\n/* 53 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar UI = __webpack_require__(2);\n\n\tmodule.exports = UI.titlebar = {\n\t  VERSION: '4.0.1'\n\t};\n\n\n/***/ },\n/* 54 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\n\tvar isWeChat = window.navigator.userAgent.indexOf('MicroMessenger') > -1;\n\n\t/* global wx,alert */\n\n\tfunction appendWeChatSDK(callback) {\n\t  var $weChatSDK = $('<script/>', {\n\t    id: 'wechat-sdk'\n\t  });\n\n\t  $('body').append($weChatSDK);\n\n\t  $weChatSDK.on('load', function() {\n\t    callback && callback();\n\t  }).attr('src', 'http://res.wx.qq.com/open/js/jweixin-1.0.0.js');\n\t}\n\n\tfunction payHandler() {\n\t  var $paymentBtn = $('[data-am-widget=\"wechatpay\"]');\n\n\t  if (!isWeChat) {\n\t    $paymentBtn.hide();\n\t    return false;\n\t  }\n\n\t  $paymentBtn.on('click', '.am-wechatpay-btn', function(e) {\n\t    e.preventDefault();\n\t    var options = UI.utils.parseOptions($(this).parent().data('wechatPay'));\n\t    // console.log(options);\n\t    // alert('pay button clicked');\n\t    if (!window.wx) {\n\t      alert('没有微信 JS SDK');\n\t      return;\n\t    }\n\n\t    wx.checkJsApi({\n\t      jsApiList: ['chooseWXPay'],\n\t      success: function(res) {\n\t        if (res.checkResult.chooseWXPay) {\n\t          wx.chooseWXPay(options);\n\t        } else {\n\t          alert('微信版本不支持支付接口或没有开启！');\n\t        }\n\t      },\n\t      fail: function() {\n\t        alert('调用 checkJsApi 接口时发生错误!');\n\t      }\n\t    });\n\t  });\n\t}\n\n\tvar payInit = payHandler;\n\n\t// Init on DOM ready\n\t$(payInit);\n\n\tmodule.exports = UI.pay = {\n\t  VERSION: '1.0.0',\n\t  init: payInit\n\t};\n\n\n/***/ }\n/******/ ])\n});\n;"
  },
  {
    "path": "open-layui-web/src/main/view/static/assets/js/amazeui.widgets.helper.js",
    "content": "/*! Amaze UI v2.6.0 ~ Handlebars helper | by Amaze UI Team | (c) 2016 AllMobilize, Inc. | Licensed under MIT | 2016-03-31T14:28:54+0800 */ \n(function(undefined) {\n  'use strict';\n\n  var registerIfCondHelper = function(hbs) {\n    hbs.registerHelper('ifCond', function(v1, operator, v2, options) {\n      switch (operator) {\n        case '==':\n          return (v1 == v2) ? options.fn(this) : options.inverse(this);\n          break;\n        case '===':\n          return (v1 === v2) ? options.fn(this) : options.inverse(this);\n          break;\n        case '<':\n          return (v1 < v2) ? options.fn(this) : options.inverse(this);\n          break;\n        case '<=':\n          return (v1 <= v2) ? options.fn(this) : options.inverse(this);\n          break;\n        case '>':\n          return (v1 > v2) ? options.fn(this) : options.inverse(this);\n          break;\n        case '>=':\n          return (v1 >= v2) ? options.fn(this) : options.inverse(this);\n          break;\n        default:\n          return options.inverse(this);\n          break;\n      }\n      return options.inverse(this);\n    });\n  };\n\n  if (typeof module !== 'undefined' && module.exports) {\n    module.exports = registerIfCondHelper;\n  }\n\n  this.Handlebars && registerIfCondHelper(this.Handlebars);\n}).call(this);\n\n(function(undefined){\n  'use strict';\n\n  var registerAMUIPartials = function(hbs) {\n    hbs.registerPartial('accordion', \"{{#this}}\\n  <section data-am-widget=\\\"accordion\\\" class=\\\"am-accordion {{#if theme}}am-accordion-{{theme}}{{else}}am-accordion-default{{/if}}{{#if widgetId}} {{widgetId}}{{/if}}{{#if className}} {{className}}{{/if}}\\\"{{#if id}} id=\\\"{{id}}\\\"{{/if}} data-am-accordion='{ {{#if options.multiple}}\\\"multiple\\\": true{{/if}} }'>\\n    {{#each content}}\\n      <dl class=\\\"am-accordion-item{{#if active}} am-active{{/if}}{{#if disabled}} am-disabled{{/if}}\\\">\\n        <dt class=\\\"am-accordion-title\\\">\\n          {{{title}}}\\n        </dt>\\n        <dd class=\\\"am-accordion-bd am-collapse {{#if active}}am-in{{/if}}\\\">\\n          <!-- 规避 Collapase 处理有 padding 的折叠内容计算计算有误问题， 加一个容器 -->\\n          <div class=\\\"am-accordion-content\\\">\\n            {{{content}}}\\n          </div>\\n        </dd>\\n      </dl>\\n    {{/each}}\\n  </section>\\n{{/this}}\\n\");\n\n    hbs.registerPartial('divider', \"{{#this}}\\n  <hr data-am-widget=\\\"divider\\\" style=\\\"{{#if options.width}}width:{{{options.width}}};{{/if}}{{#if options.height}}height:{{{options.height}}};{{/if}}\\\" class=\\\"am-divider {{#if theme}}am-divider-{{theme}}{{else}}am-divider-default{{/if}}{{#if widgetId}} {{widgetId}}{{/if}}{{#if className}} {{className}}{{/if}}\\\"{{#if id}} id=\\\"{{id}}\\\"{{/if}} />\\n{{/this}}\\n\");\n\n    hbs.registerPartial('duoshuo', \"{{#this}}\\n  <div data-am-widget=\\\"duoshuo\\\" class=\\\"am-duoshuo{{#if theme}} am-duoshuo-{{theme}}{{else}} am-duoshuo-default{{/if}}{{#if widgetId}} {{widgetId}}{{/if}}{{#if className}} {{className}}{{/if}}\\\"{{#if id}} id=\\\"{{id}}\\\"{{/if}} {{#if options.shortName}}data-ds-short-name=\\\"{{options.shortName}}\\\"{{/if}}>\\n    <div class=\\\"ds-thread\\\" {{#if content}}{{#each content}}{{#ifCond @key '==' 'threadKey'}}  data-thread-key=\\\"{{this}}\\\"{{else}} data-{{@key}}=\\\"{{this}}\\\"{{/ifCond}}{{/each}}{{/if}}>\\n    </div>\\n  </div>\\n{{/this}}\");\n\n    hbs.registerPartial('figure', \"{{#this}}\\n  <figure data-am-widget=\\\"figure\\\" class=\\\"am am-figure {{#if theme}}am-figure-{{theme}}{{else}}am-figure-default{{/if}} {{#if widgetId}} {{widgetId}}{{/if}}{{#if className}} {{className}}{{/if}}\\\" {{#if id}}\\n      id=\\\"{{id}}\\\"{{/if}}  data-am-figure=\\\"{ {{#if options.zoomAble}} pureview: '{{options.zoomAble}}'{{/if}} }\\\">\\n    {{#if content.link}}<a href=\\\"{{content.link}}\\\" title=\\\"{{content.figcaption}}\\\" class=\\\"{{className}}\\\">{{/if}}\\n\\n    {{#if options.figcaptionPosition}}\\n      {{#ifCond options.figcaptionPosition '==' 'top'}}\\n        {{#if content.figcaption}}\\n          <figcaption class=\\\"am-figure-capition-top\\\">\\n            {{content.figcaption}}\\n          </figcaption>\\n        {{/if}}\\n      {{/ifCond}}\\n    {{/if}}\\n\\n    {{#if content.img}}\\n      <img src=\\\"{{content.img}}\\\" {{#if content.rel}}data-rel=\\\"{{content.rel}}\\\"{{/if}} alt=\\\"{{#if content.imgAlt}}{{content.imgAlt}}{{else}}{{content.figcaption}}{{/if}}\\\"/>\\n    {{/if}}\\n    {{#if options.figcaptionPosition}}\\n      {{#ifCond options.figcaptionPosition '==' 'bottom'}}\\n        {{#if content.figcaption}}\\n          <figcaption class=\\\"am-figure-capition-btm\\\">\\n            {{content.figcaption}}\\n          </figcaption>\\n        {{/if}}\\n      {{/ifCond}}\\n    {{else}}\\n      {{#if content.figcaption}}\\n        <figcaption class=\\\"am-figure-capition-btm\\\">\\n          {{content.figcaption}}\\n        </figcaption>\\n      {{/if}}\\n    {{/if}}\\n\\n    {{#if content.link}}</a>{{/if}}\\n  </figure>\\n{{/this}}\\n\");\n\n    hbs.registerPartial('footer', \"{{#this}}\\n  <footer data-am-widget=\\\"footer\\\"\\n          class=\\\"am-footer {{#if theme}}am-footer-{{theme}}{{else}}am-footer-default {{/if}}{{#if widgetId}} {{widgetId}}{{/if}}{{#if className}} {{className}}{{/if}}\\\"\\n          {{#if id}}id=\\\"{{id}}\\\"{{/if}} data-am-footer=\\\"{ {{#if options.addToHS}}addToHS: 1{{/if}} }\\\">\\n    <div class=\\\"am-footer-switch\\\">\\n    <span class=\\\"{{#if options.modal}}am-footer-ysp{{/if}}\\\" data-rel=\\\"mobile\\\"\\n          data-am-modal=\\\"{target: '#am-switch-mode'}\\\">\\n      {{#unless content.switchName}}\\n        {{#ifCond content.lang '==' 'en'}}\\n          Mobile\\n        {{else}}\\n          云适配版\\n        {{/ifCond}}\\n      {{else}}\\n        {{content.switchName}}\\n      {{/unless}}\\n    </span>\\n      <span class=\\\"am-footer-divider\\\"> | </span>\\n      <a id=\\\"godesktop\\\" data-rel=\\\"desktop\\\" class=\\\"am-footer-desktop\\\" href=\\\"javascript:\\\">\\n        {{#ifCond content.lang '==' 'en'}}\\n          Desktop\\n        {{else}}\\n          电脑版\\n        {{/ifCond}}\\n      </a>\\n    </div>\\n    <div class=\\\"am-footer-miscs {{#if options.textPosition}}am-text-left{{/if}}\\\">\\n\\n      {{#if options.techSupportCo}}\\n        {{#ifCond content.lang '==' 'en'}}\\n          <p>Supported by {{#if options.techSupportSite}}<a href=\\\"{{options.techSupportSite}}\\\"\\n                                                            title=\\\"{{options.techSupportCo}}\\\"\\n                                                            target=\\\"_blank\\\"> class=\\\"{{className}}\\\"{{{options.techSupportCo}}}</a>{{else}}{{{options.techSupportCo}}}{{/if}}\\n            .</p>\\n        {{else}}\\n          <p>由 {{#if options.techSupportSite}}<a href=\\\"{{options.techSupportSite}}\\\" title=\\\"{{options.techSupportCo}}\\\"\\n                                                target=\\\"_blank\\\" class=\\\"{{techSupportClassName}}\\\">{{{options.techSupportCo}}}</a>{{else}}{{{options.techSupportCo}}}{{/if}}\\n            提供技术支持</p>\\n        {{/ifCond}}\\n      {{/if}}\\n      {{#each content.companyInfo}}\\n        <p>{{{detail}}}</p>\\n      {{/each}}\\n    </div>\\n  </footer>\\n\\n  <div id=\\\"am-footer-modal\\\"\\n       class=\\\"am-modal am-modal-no-btn am-switch-mode-m {{#if theme}}am-switch-mode-m-{{theme}}{{/if}}\\\">\\n    <div class=\\\"am-modal-dialog\\\">\\n      <div class=\\\"am-modal-hd am-modal-footer-hd\\\">\\n        <a href=\\\"javascript:void(0)\\\" data-dismiss=\\\"modal\\\" class=\\\"am-close am-close-spin {{className}}\\\" data-am-modal-close>&times;</a>\\n      </div>\\n      <div class=\\\"am-modal-bd\\\">\\n        {{#ifCond content.lang '==' 'en'}}\\n          You are visiting\\n        {{else}}\\n          您正在浏览的是\\n        {{/ifCond}}\\n\\n        <span class=\\\"am-switch-mode-owner\\\">\\n          {{#if content.owner}}\\n            {{content.owner}}\\n          {{else}}\\n            云适配\\n          {{/if}}\\n        </span>\\n\\n        <span class=\\\"am-switch-mode-slogan\\\">\\n          {{#if content.slogan}}\\n            {{{content.slogan}}}\\n          {{else}}\\n            {{#ifCond content.lang '==' 'en'}}\\n              mobilized version for your device.\\n            {{else}}\\n              为您当前手机订制的移动网站。\\n            {{/ifCond}}\\n          {{/if}}\\n        </span>\\n      </div>\\n    </div>\\n  </div>\\n{{/this}}\\n\");\n\n    hbs.registerPartial('gallery', \"{{#this}}\\n  <ul data-am-widget=\\\"gallery\\\" class=\\\"am-gallery{{#if options.cols}} am-avg-sm-{{options.cols}}{{else}} am-avg-sm-2{{/if}}\\n  am-avg-md-3 am-avg-lg-4 {{#if\\n  theme}}am-gallery-{{theme}}{{else}}am-gallery-default{{/if}}{{#if widgetId}} {{widgetId}}{{/if}}{{#if className}} {{className}}{{/if}}\\\" data-am-gallery=\\\"{ {{#if options.gallery}}pureview: true{{/if}} }\\\" {{#if id}}id=\\\"{{id}}\\\"{{/if}}>\\n    {{#each content}}\\n      <li>\\n        <div class=\\\"am-gallery-item\\\">\\n          {{#if link}}\\n            <a href=\\\"{{link}}\\\" class=\\\"{{className}}\\\">\\n              {{#if img}}<img src=\\\"{{img}}\\\" {{#if rel}}data-rel=\\\"{{rel}}\\\"{{/if}} alt=\\\"{{title}}\\\"/>{{/if}}\\n              {{#if title}}\\n                <h3 class=\\\"am-gallery-title\\\">{{{title}}}</h3>\\n              {{/if}}\\n              {{#if desc}}\\n                <div class=\\\"am-gallery-desc\\\">{{{desc}}}</div>\\n              {{/if}}\\n            </a>\\n          {{else}}\\n            {{#if img}}<img src=\\\"{{img}}\\\" {{#if rel}}data-rel=\\\"{{rel}}\\\"{{/if}} alt=\\\"{{title}}\\\"/>{{/if}}\\n            {{#if title}}\\n              <h3 class=\\\"am-gallery-title\\\">{{{title}}}</h3>\\n            {{/if}}\\n            {{#if desc}}\\n              <div class=\\\"am-gallery-desc\\\">{{{desc}}}</div>\\n            {{/if}}\\n          {{/if}}\\n        </div>\\n      </li>\\n    {{/each}}\\n  </ul>\\n{{/this}}\\n\");\n\n    hbs.registerPartial('gotop', \"{{#this}}\\n  <div data-am-widget=\\\"gotop\\\" class=\\\"am-gotop {{#if theme}}am-gotop-{{theme}}{{else}}am-gotop-default{{/if}}{{#if widgetId}} {{widgetId}}{{/if}}{{#if className}} {{className}}{{/if}}\\\" {{#if id}}id=\\\"{{id}}\\\"{{/if}}>\\n    <a href=\\\"#top\\\" title=\\\"{{content.title}}\\\">\\n      {{#if content.title}}\\n        <span class=\\\"am-gotop-title\\\">{{content.title}}</span>\\n      {{/if}}\\n      {{#if content.customIcon}}\\n        <img class=\\\"am-gotop-icon-custom\\\" src=\\\"{{content.customIcon}}\\\" />\\n      {{else}}\\n        {{#if content.icon}}\\n          <i class=\\\"am-gotop-icon am-icon-{{content.icon}}\\\"></i>\\n        {{else}}\\n          <i class=\\\"am-gotop-icon am-icon-chevron-up\\\"></i>\\n        {{/if}}\\n      {{/if}}\\n    </a>\\n  </div>\\n{{/this}}\\n\");\n\n    hbs.registerPartial('header', \"{{#this}}\\n  <header data-am-widget=\\\"header\\\"\\n          class=\\\"am-header{{#if theme}} am-header-{{theme}}{{else}} am-header-default{{/if}}{{#if options.fixed}} am-header-fixed{{/if}}{{#if widgetId}} {{widgetId}}{{/if}}{{#if className}} {{className}}{{/if}}\\\"{{#if id}}\\n          id=\\\"{{id}}\\\"{{/if}}>\\n    {{#if content.left}}\\n      <div class=\\\"am-header-left am-header-nav\\\">\\n        {{#each content.left}}\\n          <a href=\\\"{{link}}\\\" class=\\\"{{className}}\\\">\\n            {{#if title}}\\n              <span class=\\\"am-header-nav-title\\\">\\n                {{title}}\\n              </span>\\n            {{/if}}\\n\\n            {{# if customIcon}}\\n              <img class=\\\"am-header-icon-custom\\\" src=\\\"{{customIcon}}\\\" alt=\\\"\\\"/>\\n            {{else}}\\n              {{#if icon}}\\n                <i class=\\\"am-header-icon am-icon-{{icon}}\\\"></i>\\n              {{/if}}\\n            {{/if}}\\n          </a>\\n        {{/each}}\\n      </div>\\n    {{/if}}\\n\\n    {{#if content.title}}\\n      <h1 class=\\\"am-header-title\\\">\\n        {{#if content.link}}\\n          <a href=\\\"{{content.link}}\\\" class=\\\"{{content.className}}\\\">\\n            {{{content.title}}}\\n          </a>\\n        {{else}}\\n          {{{content.title}}}\\n        {{/if}}\\n      </h1>\\n    {{/if}}\\n\\n    {{#if content.right}}\\n      <div class=\\\"am-header-right am-header-nav\\\">\\n        {{#each content.right}}\\n          <a href=\\\"{{link}}\\\" class=\\\"{{className}}\\\">\\n            {{#if title}}\\n              <span class=\\\"am-header-nav-title\\\">\\n                {{title}}\\n              </span>\\n            {{/if}}\\n\\n            {{# if customIcon}}\\n              <img class=\\\"am-header-icon-custom\\\" src=\\\"{{customIcon}}\\\" alt=\\\"\\\"/>\\n            {{else}}\\n              {{#if icon}}\\n                <i class=\\\"am-header-icon am-icon-{{icon}}\\\"></i>\\n              {{/if}}\\n            {{/if}}\\n          </a>\\n        {{/each}}\\n      </div>\\n    {{/if}}\\n  </header>\\n{{/this}}\\n\");\n\n    hbs.registerPartial('intro', \"{{#this }}\\n  <div data-am-widget=\\\"intro\\\"\\n       class=\\\"am-intro am-cf {{#if theme}}am-intro-{{theme}}{{else}}am-intro-default{{/if}}{{#if widgetId}} {{widgetId}}{{/if}}{{#if className}} {{className}}{{/if}}\\\"\\n       {{#if id}}id=\\\"{{id}}\\\"{{/if}}>\\n    {{#if content.title}}\\n      <div class=\\\"am-intro-hd\\\">\\n        <h2 class=\\\"am-intro-title\\\">{{{content.title}}}</h2>\\n        {{#if content.more.link}}\\n          {{#ifCond options.position '==' 'top'}}\\n            <a class=\\\"am-intro-more am-intro-more-top {{content.more.className}}\\\" href=\\\"{{content.more.link}}\\\">{{content.more.title}}</a>\\n          {{/ifCond}}\\n        {{/if}}\\n      </div>\\n    {{/if}}\\n\\n    <div class=\\\"am-g am-intro-bd\\\">\\n      {{#if content.left}}\\n        <div\\n            class=\\\"am-intro-left {{#if options.leftCols}}am-u-sm-{{options.leftCols}}{{/if}}\\\">{{{content.left}}}</div>\\n      {{/if}}\\n      {{#if content.right}}\\n        <div\\n            class=\\\"am-intro-right {{#if options.rightCols}}am-u-sm-{{options.rightCols}}{{/if}}\\\">{{{content.right}}}</div>\\n      {{/if}}\\n    </div>\\n    {{#ifCond options.position '==' 'bottom'}}\\n      <div class=\\\"am-intro-more-bottom\\\">\\n        <a class=\\\"am-btn am-btn-default {{content.more.className}}\\\"\\n           href=\\\"{{content.more.link}}\\\">{{content.more.title}}</a>\\n      </div>\\n    {{/ifCond}}\\n  </div>\\n{{/this}}\\n\");\n\n    hbs.registerPartial('list_news', \"{{#this}}\\n  <div data-am-widget=\\\"list_news\\\" class=\\\"am-list-news{{#if theme}} am-list-news-{{theme}}{{else}} am-list-news-default{{/if}}{{#if widgetId}} {{widgetId}}{{/if}}{{#if className}} {{className}}{{/if}}\\\" {{#if id}}id=\\\"{{id}}\\\"{{/if}}>\\n  <!--列表标题-->\\n  {{#if content.header.title}}\\n    <div class=\\\"am-list-news-hd am-cf\\\">\\n      {{#if content.header.link}} <!--带更多链接-->\\n        <a href=\\\"{{content.header.link}}\\\" class=\\\"{{content.header.className}}\\\">\\n          <h2>{{{content.header.title}}}</h2>\\n          {{#ifCond content.header.morePosition '==' 'top'}}\\n            <span class=\\\"am-list-news-more am-fr\\\">{{{content.header.moreText}}}</span>\\n          {{/ifCond}}\\n        </a>\\n      {{else}} <!--不带更多链接-->\\n        <h2>{{{content.header.title}}}</h2>\\n      {{/if}}\\n    </div>\\n  {{/if}}\\n\\n  <div class=\\\"am-list-news-bd\\\">\\n  <ul class=\\\"am-list\\\">\\n  {{#ifCond options.type '==' 'thumb'}}\\n    {{#ifCond options.thumbPosition '==' 'top'}} <!--缩略图在标题上方-->\\n    {{#each content.main}}\\n      <li class=\\\"am-g{{#if date}} am-list-item-dated{{/if}}{{#if desc}} am-list-item-desced{{/if}}{{#if img}} am-list-item-thumbed am-list-item-thumb-top{{/if}}\\\">\\n        {{!--\\n          am-list-item-dated - 带日期\\n          am-list-item-desced - 带描述\\n          am-list-item-thumbed - 带缩略图的\\n        --}}\\n        {{#if img}}\\n        <div class=\\\"am-list-thumb am-u-sm-12\\\">\\n          <a href=\\\"{{link}}\\\" class=\\\"{{className}}\\\">\\n            <img src=\\\"{{img}}\\\" alt=\\\"{{title}}\\\"/>\\n          </a>\\n          {{#if thumbAddition}}\\n            <div class=\\\"am-list-thumb-addon\\\">{{{thumbAddition}}}</div>\\n          {{/if}}\\n        </div>\\n        {{/if}}\\n\\n        <div class=\\\"{{#if img}}{{/if}} am-list-main\\\">\\n          {{#if title}}\\n            <h3 class=\\\"am-list-item-hd\\\"><a href=\\\"{{link}}\\\" class=\\\"{{className}}\\\">{{{title}}}</a></h3>\\n          {{/if}}\\n\\n          {{#if date}}\\n            <span class=\\\"am-list-date\\\">{{date}}</span>\\n          {{/if}}\\n\\n          {{#if desc}}\\n            <div class=\\\"am-list-item-text\\\">{{{desc}}}</div>\\n          {{/if}}\\n\\n          {{#if mainAddition}}\\n            <div class=\\\"am-list-news-addon\\\">{{{mainAddition}}}</div>\\n          {{/if}}\\n        </div>\\n      </li>\\n    {{/each}}\\n    {{/ifCond}}\\n\\n    {{#ifCond options.thumbPosition '==' 'bottom-left'}} <!--缩略图在标题下方居左-->\\n    {{#each content.main}}\\n      <li class=\\\"am-g{{#if date}} am-list-item-dated{{/if}}{{#if desc}} am-list-item-desced{{/if}}{{#if img}} am-list-item-thumbed am-list-item-thumb-bottom-left{{/if}}\\\">\\n        {{!--\\n          am-list-item-dated - 带日期\\n          am-list-item-desced - 带描述\\n          am-list-item-thumbed - 带缩略图的\\n        --}}\\n        {{#if title}}\\n          <h3 class=\\\"am-list-item-hd\\\"><a href=\\\"{{link}}\\\" class=\\\"{{className}}\\\">{{{title}}}</a></h3>\\n        {{/if}}\\n        {{#if img}}\\n        <div class=\\\"am-u-sm-4 am-list-thumb\\\">\\n          <a href=\\\"{{link}}\\\" class=\\\"{{className}}\\\">\\n            <img src=\\\"{{img}}\\\" alt=\\\"{{title}}\\\"/>\\n          </a>\\n          {{#if thumbAddition}}\\n            <div class=\\\"am-list-thumb-addon\\\">{{{thumbAddition}}}</div>\\n          {{/if}}\\n        </div>\\n        {{/if}}\\n\\n        <div class=\\\"{{#if img}} am-u-sm-8 {{/if}} am-list-main\\\">\\n          {{#if date}}\\n            <span class=\\\"am-list-date\\\">{{date}}</span>\\n          {{/if}}\\n\\n          {{#if desc}}\\n            <div class=\\\"am-list-item-text\\\">{{{desc}}}</div>\\n          {{/if}}\\n\\n          {{#if mainAddition}}\\n            <div class=\\\"am-list-news-addon\\\">{{{mainAddition}}}</div>\\n          {{/if}}\\n        </div>\\n      </li>\\n    {{/each}}\\n    {{/ifCond}}\\n\\n    {{#ifCond options.thumbPosition '==' 'bottom-right'}} <!--缩略图在标题下方居右-->\\n    {{#each content.main}}\\n      <li class=\\\"am-g{{#if date}} am-list-item-dated{{/if}}{{#if desc}} am-list-item-desced{{/if}}{{#if img}} am-list-item-thumbed am-list-item-thumb-bottom-right{{/if}}\\\">\\n        {{!--\\n          am-list-item-dated - 带日期\\n          am-list-item-desced - 带描述\\n          am-list-item-thumbed - 带缩略图的\\n        --}}\\n        {{#if title}}\\n          <h3 class=\\\"am-list-item-hd\\\"><a href=\\\"{{link}}\\\" class=\\\"{{className}}\\\">{{{title}}}</a></h3>\\n        {{/if}}\\n\\n        <div class=\\\"{{#if img}} am-u-sm-8{{/if}} am-list-main\\\">\\n          {{#if date}}\\n            <span class=\\\"am-list-date\\\">{{date}}</span>\\n          {{/if}}\\n\\n          {{#if desc}}\\n            <div class=\\\"am-list-item-text\\\">{{{desc}}}</div>\\n          {{/if}}\\n\\n          {{#if mainAddition}}\\n            <div class=\\\"am-list-news-addon\\\">{{{mainAddition}}}</div>\\n          {{/if}}\\n        </div>\\n        {{#if img}}\\n        <div class=\\\"am-list-thumb am-u-sm-4\\\">\\n          <a href=\\\"{{link}}\\\" class=\\\"{{className}}\\\">\\n            <img src=\\\"{{img}}\\\" alt=\\\"{{title}}\\\"/>\\n          </a>\\n          {{#if thumbAddition}}\\n            <div class=\\\"am-list-thumb-addon\\\">{{{thumbAddition}}}</div>\\n          {{/if}}\\n        </div>\\n        {{/if}}\\n      </li>\\n    {{/each}}\\n    {{/ifCond}}\\n\\n    {{#ifCond options.thumbPosition '==' 'left'}} <!--缩略图在标题左边-->\\n    {{#each content.main}}\\n      <li class=\\\"am-g{{#if date}} am-list-item-dated{{/if}}{{#if desc}} am-list-item-desced{{/if}}{{#if img}} am-list-item-thumbed am-list-item-thumb-left{{/if}}\\\">\\n        {{!--\\n          am-list-item-dated - 带日期\\n          am-list-item-desced - 带描述\\n          am-list-item-thumbed - 带缩略图的\\n        --}}\\n        {{#if img}}\\n        <div class=\\\"am-u-sm-4 am-list-thumb\\\">\\n          <a href=\\\"{{link}}\\\" class=\\\"{{className}}\\\">\\n            <img src=\\\"{{img}}\\\" alt=\\\"{{title}}\\\"/>\\n          </a>\\n          {{#if thumbAddition}}\\n            <div class=\\\"am-list-thumb-addon\\\">{{{thumbAddition}}}</div>\\n          {{/if}}\\n        </div>\\n        {{/if}}\\n\\n        <div class=\\\"{{#if img}} am-u-sm-8{{/if}} am-list-main\\\">\\n          {{#if title}}\\n            <h3 class=\\\"am-list-item-hd\\\"><a href=\\\"{{link}}\\\" class=\\\"{{className}}\\\">{{{title}}}</a></h3>\\n          {{/if}}\\n          {{#if date}}\\n            <span class=\\\"am-list-date\\\">{{date}}</span>\\n          {{/if}}\\n\\n          {{#if desc}}\\n            <div class=\\\"am-list-item-text\\\">{{{desc}}}</div>\\n          {{/if}}\\n\\n          {{#if mainAddition}}\\n            <div class=\\\"am-list-news-addon\\\">{{{mainAddition}}}</div>\\n          {{/if}}\\n        </div>\\n      </li>\\n    {{/each}}\\n    {{/ifCond}}\\n\\n    {{#ifCond options.thumbPosition '==' 'right'}} <!--缩略图在标题右边-->\\n    {{#each content.main}}\\n      <li class=\\\"am-g{{#if date}} am-list-item-dated{{/if}}{{#if desc}} am-list-item-desced{{/if}}{{#if img}} am-list-item-thumbed am-list-item-thumb-right{{/if}}\\\">\\n        {{!--\\n          am-list-item-dated - 带日期\\n          am-list-item-desced - 带描述\\n          am-list-item-thumbed - 带缩略图的\\n        --}}\\n        <div class=\\\"{{#if img}} am-u-sm-8{{/if}} am-list-main\\\">\\n          {{#if title}}\\n            <h3 class=\\\"am-list-item-hd\\\"><a href=\\\"{{link}}\\\" class=\\\"{{className}}\\\">{{{title}}}</a></h3>\\n          {{/if}}\\n\\n          {{#if date}}\\n            <span class=\\\"am-list-date\\\">{{date}}</span>\\n          {{/if}}\\n\\n          {{#if desc}}\\n            <div class=\\\"am-list-item-text\\\">{{{desc}}}</div>\\n          {{/if}}\\n\\n          {{#if mainAddition}}\\n            <div class=\\\"am-list-news-addon\\\">{{{mainAddition}}}</div>\\n          {{/if}}\\n        </div>\\n        {{#if img}}\\n          <div class=\\\"am-u-sm-4 am-list-thumb\\\">\\n            <a href=\\\"{{link}}\\\" class=\\\"{{className}}\\\">\\n              <img src=\\\"{{img}}\\\" alt=\\\"{{title}}\\\"/>\\n            </a>\\n            {{#if thumbAddition}}\\n              <div class=\\\"am-list-thumb-addon\\\">{{{thumbAddition}}}</div>\\n            {{/if}}\\n          </div>\\n        {{/if}}\\n      </li>\\n    {{/each}}\\n    {{/ifCond}}\\n\\n  {{else}}{{!--不带缩略图--}}\\n    {{#each content.main}}\\n      <li class=\\\"am-g{{#if date}} am-list-item-dated{{/if}}{{#if desc}} am-list-item-desced{{/if}}{{#if img}} am-list-item-thumbed{{/if}}\\\">\\n        {{!--\\n          am-list-item-dated - 带日期\\n          am-list-item-desced - 带描述\\n          am-list-item-thumbed - 带缩略图的\\n        --}}\\n        {{#if title}}\\n          <a href=\\\"{{link}}\\\" class=\\\"am-list-item-hd {{className}}\\\">{{{title}}}</a>\\n        {{/if}}\\n\\n        {{#if date}}\\n          <span class=\\\"am-list-date\\\">{{date}}</span>\\n        {{/if}}\\n\\n        {{#if desc}}\\n          <div class=\\\"am-list-item-text\\\">{{{desc}}}</div>\\n        {{/if}}\\n\\n        {{#if mainAddition}}\\n          <div class=\\\"am-list-news-addon\\\">{{{mainAddition}}}</div>\\n        {{/if}}\\n      </li>\\n    {{/each}}\\n  {{/ifCond}}\\n  </ul>\\n  </div>\\n\\n  {{#ifCond content.header.morePosition '==' 'bottom'}}<!--更多在底部-->\\n    {{#if content.header.link}}\\n      <div class=\\\"am-list-news-ft\\\">\\n        <a class=\\\"am-list-news-more am-btn am-btn-default {{content.header.className}}\\\" href=\\\"{{content.header.link}}\\\">{{{content.header.moreText}}}</a>\\n      </div>\\n    {{/if}}\\n  {{/ifCond}}\\n  </div>\\n{{/this}}\\n\");\n\n    hbs.registerPartial('map', \"{{#this}}\\n  <div data-am-widget=\\\"map\\\" class=\\\"am-map {{#if theme}}am-map-{{theme}}{{else}}am-map-default{{/if}}{{#if widgetId}} {{widgetId}}{{/if}}{{#if className}} {{className}}{{/if}}\\\"\\n      data-name=\\\"{{options.name}}\\\" data-address=\\\"{{options.address}}\\\" data-longitude=\\\"{{options.longitude}}\\\" data-latitude=\\\"{{options.latitude}}\\\" data-scaleControl=\\\"{{options.scaleControl}}\\\" data-zoomControl=\\\"{{options.zoomControl}}\\\" data-setZoom=\\\"{{options.setZoom}}\\\" data-icon=\\\"{{options.icon}}\\\">\\n    <div id=\\\"bd-map\\\"></div>\\n  </div>\\n{{/this}}\");\n\n    hbs.registerPartial('mechat', \"{{#this}}\\n  <section data-am-widget=\\\"mechat\\\" class=\\\"am-mechat{{#if theme}} am-mechat-{{theme}}{{else}} am-mechat-default{{/if}}{{#if widgetId}} {{widgetId}}{{/if}}{{#if className}} {{className}}{{/if}}\\\" {{#if id}} id=\\\"{{id}}\\\" {{/if}} {{#if options.unitid}}data-am-mechat-unitid=\\\"{{options.unitid}}\\\"{{/if}}>\\n    <div id=\\\"mechat\\\"></div>\\n  </section>\\n{{/this}}\");\n\n    hbs.registerPartial('menu', \"{{#this}}\\n  <nav data-am-widget=\\\"menu\\\" class=\\\"am-menu {{#if theme}} am-menu-{{theme}}{{else}} am-menu-default{{/if}}{{#if widgetId}} {{widgetId}}{{/if}}{{#if className}} {{className}}{{/if}}\\\" {{options.dataset}} {{#if id}}id=\\\"{{id}}\\\"{{/if}}\\n    {{#ifCond theme '==' 'dropdown1'}} data-am-menu-collapse{{/ifCond}}\\n    {{#ifCond theme '==' 'dropdown2'}} data-am-menu-collapse{{/ifCond}}\\n    {{#ifCond theme '==' 'slide1'}} data-am-menu-collapse{{/ifCond}}\\n    {{#ifCond theme '==' 'offcanvas1'}} data-am-menu-offcanvas{{/ifCond}}\\n    {{#ifCond theme '==' 'offcanvas2'}} data-am-menu-offcanvas{{/ifCond}}> {{!-- 与模板深耦合，与 JS 浅耦合 --}}\\n    <a href=\\\"javascript: void(0)\\\" class=\\\"am-menu-toggle\\\">\\n      {{#if options.toggleTitle}}\\n        <span class=\\\"am-menu-toggle-title\\\">{{options.toggleTitle}}</span>\\n      {{/if}}\\n      {{#if options.toggleCustomIcon}}\\n        <img src=\\\"{{options.toggleCustomIcon}}\\\" alt=\\\"Menu Toggle\\\"/>\\n      {{else}}\\n        {{#if options.toggleIcon}}\\n          <i class=\\\"am-menu-toggle-icon am-icon-{{options.toggleIcon}}\\\"></i>\\n          {{else}}\\n          <i class=\\\"am-menu-toggle-icon am-icon-bars\\\"></i>\\n        {{/if}}\\n      {{/if}}\\n    </a>\\n\\n    {{!-- offCanvas menu Wrap --}}\\n    {{!-- 问题：方便用户，但是与主题名称（类名）耦合过深 --}}\\n    {{#ifCond theme '==' 'offcanvas1'}}\\n    <div class=\\\"am-offcanvas\\\" {{#if options.closeOffCanvasOnclick}}data-dismiss-on=\\\"click\\\"{{/if}}>\\n      <div class=\\\"am-offcanvas-bar{{#if options.offCanvasFlip}} am-offcanvas-bar-flip{{/if}}\\\">\\n    {{/ifCond}}\\n    {{#ifCond theme '==' 'offcanvas2'}}\\n    <div class=\\\"am-offcanvas\\\">\\n      <div class=\\\"am-offcanvas-bar{{#if options.offCanvasFlip}} am-offcanvas-bar-flip{{/if}}\\\">\\n    {{/ifCond}}\\n\\n    {{#if content}}\\n      <ul class=\\\"am-menu-nav {{#if options.cols}}am-avg-sm-{{options\\n      .cols}}{{else}}am-avg-sm-1{{/if}}{{#ifCond theme '==' 'dropdown1'}} am-collapse{{/ifCond}}{{#ifCond theme\\n      '==' 'dropdown2'}} am-collapse{{/ifCond}}{{#ifCond theme\\n      '==' 'slide1'}} am-collapse{{/ifCond}}\\\">\\n        {{#each content}}\\n          <li class=\\\"{{#if subMenu}}am-parent{{/if}}{{#if className}} {{className}}{{/if}}\\\">\\n            <a href=\\\"{{link}}\\\" class=\\\"{{className}}\\\" {{#if target}}target=\\\"{{target}}\\\" {{/if}}>{{{title}}}</a>\\n            {{#if subMenu}}\\n              <ul class=\\\"am-menu-sub am-collapse {{#if subCols}} am-avg-sm-{{subCols}}{{else}}\\n              am-avg-sm-1{{/if}} {{subMenuClassName}}\\\">\\n                {{#each subMenu}}\\n                  <li class=\\\"{{#if subMenu}} am-parent{{/if}}{{#if className}} {{className}}{{/if}}\\\">\\n                    <a href=\\\"{{link}}\\\" class=\\\"{{className}}\\\" {{#if target}}target=\\\"{{target}}\\\" {{/if}}>{{{title}}}</a>\\n                  </li>\\n                {{/each}}\\n                {{!-- 显示进入栏目链接 --}}\\n                {{#if channelLink}}\\n                  <li class=\\\"am-menu-nav-channel\\\"><a href=\\\"{{link}}\\\" class=\\\"{{className}}\\\" title=\\\"{{title}}\\\">{{{channelLink}}}</a></li>\\n                {{/if}}\\n              </ul>\\n            {{/if}}\\n          </li>\\n        {{/each}}\\n      </ul>\\n    {{/if}}\\n\\n    {{#ifCond theme '==' 'offcanvas1'}}\\n      </div>\\n    </div>\\n    {{/ifCond}}\\n    {{#ifCond theme '==' 'offcanvas2'}}\\n      </div>\\n    </div>\\n    {{/ifCond}}\\n    {{!-- 不要问我为什么这样写，我也不想这样 --}}\\n  </nav>\\n{{/this}}\\n\");\n\n    hbs.registerPartial('navbar', \"{{#this}}\\n  <div data-am-widget=\\\"navbar\\\" class=\\\"am-navbar am-cf {{#if theme}}am-navbar-{{theme}}{{else}}am-navbar-default{{/if}} {{#if options.iconPosition}}am-navbar-inline{{/if}}{{#if widgetId}} {{widgetId}}{{/if}}{{#if className}} {{className}}{{/if}}\\\"\\n      id=\\\"{{id}}\\\">\\n    {{#if content}}\\n      <ul class=\\\"am-navbar-nav am-cf {{#if options.cols}}am-avg-sm-{{options.cols}}{{/if}}\\\">\\n        {{#each content}}\\n          <li {{{dataApi}}}>\\n            <a href=\\\"{{link}}\\\" class=\\\"{{className}}\\\">\\n              {{#if customIcon}}\\n                <img src=\\\"{{customIcon}}\\\" alt=\\\"{{title}}\\\"/>\\n              {{else}}\\n                {{#if icon}}\\n                  <span class=\\\"am-icon-{{icon}}\\\"></span>\\n                {{/if}}\\n              {{/if}}\\n              {{#if title}}\\n                <span class=\\\"am-navbar-label\\\">{{title}}</span>\\n              {{/if}}\\n            </a>\\n          </li>\\n        {{/each}}\\n      </ul>\\n    {{/if}}\\n  </div>\\n{{/this}}\\n\");\n\n    hbs.registerPartial('pagination', \"{{#this}}\\n  <ul data-am-widget=\\\"pagination\\\"\\n      class=\\\"am-pagination {{#if theme}}am-pagination-{{theme}}{{else}}am-pagination-default{{/if}}{{#if widgetId}} {{widgetId}}{{/if}}{{#if className}} {{className}}{{/if}}\\\"\\n      {{#if id}}id=\\\"{{id}}\\\"{{/if}}>\\n\\n    {{#if content.firstTitle}}\\n      <li class=\\\"am-pagination-first {{content.firstClassName}}\\\">\\n        <a href=\\\"{{content.firstLink}}\\\" class=\\\"{{content.firstClassName}}\\\">{{{content.firstTitle}}}</a>\\n      </li>\\n    {{/if}}\\n\\n    {{#if content.prevTitle}}\\n      <li class=\\\"am-pagination-prev {{content.prevClassName}}\\\">\\n        <a href=\\\"{{content.prevLink}}\\\" class=\\\"{{content.prevClassName}}\\\">{{{content.prevTitle}}}</a>\\n      </li>\\n    {{/if}}\\n\\n    {{! 移除 options.select，根据主题来判断结构，无奈 handlebars 逻辑处理...}}\\n\\n    {{#if content.page}}\\n      {{#ifCond theme '==' 'select'}}\\n        <li class=\\\"am-pagination-select\\\">\\n          <select>\\n            {{#each content.page}}\\n              <option value=\\\"{{link}}\\\" class=\\\"{{className}}\\\">{{title}}{{#if ../content.total}}\\n                / {{../../content.total}}{{/if}}\\n              </option>\\n            {{/each}}\\n          </select>\\n        </li>\\n      {{else}}\\n        {{#ifCond theme '==' 'one'}}\\n          <li class=\\\"am-pagination-select\\\">\\n            <select>\\n              {{#each content.page}}\\n                {{content.total}}\\n                <option value=\\\"{{link}}\\\" class=\\\"{{className}}\\\">{{title}}{{#if ../content.total}}\\n                  / {{../../content.total}}{{/if}}\\n                </option>\\n              {{/each}}\\n            </select>\\n          </li>\\n        {{else}}\\n          {{#each content.page}}\\n            <li class=\\\"{{className}}\\\">\\n              <a href=\\\"{{link}}\\\" class=\\\"{{className}}\\\">{{{title}}}</a>\\n            </li>\\n          {{/each}}\\n        {{/ifCond}}\\n      {{/ifCond}}\\n\\n    {{/if}}\\n\\n    {{#if content.nextTitle}}\\n      <li class=\\\"am-pagination-next {{content.nextClassName}}\\\">\\n        <a href=\\\"{{content.nextLink}}\\\" class=\\\"{{content.nextClassName}}\\\">{{{content.nextTitle}}}</a>\\n      </li>\\n    {{/if}}\\n\\n    {{#if content.lastTitle}}\\n      <li class=\\\"am-pagination-last {{content.lastClassName}}\\\">\\n        <a href=\\\"{{content.lastLink}}\\\" class=\\\"{{content.lastClassName}}\\\">{{{content.lastTitle}}}</a>\\n      </li>\\n    {{/if}}\\n  </ul>\\n{{/this}}\\n\");\n\n    hbs.registerPartial('paragraph', \"{{#this}}\\n  <article data-am-widget=\\\"paragraph\\\"\\n           class=\\\"am-paragraph {{#if theme}}am-paragraph-{{theme}}{{else}}am-paragraph-default{{/if}}{{#if widgetId}} {{widgetId}}{{/if}}{{#if className}} {{className}}{{/if}}\\\"\\n           {{#if id}}id=\\\"{{id}}\\\"{{/if}}\\n           data-am-paragraph=\\\"{ {{#if options.tableScrollable}}tableScrollable: true,{{/if}} {{#if options.imgLightbox}}pureview: true{{/if}} }\\\">\\n\\n    {{#if content}}\\n      {{{ content.content }}}\\n    {{/if}}\\n  </article>\\n{{/this}}\\n\");\n\n    hbs.registerPartial('slider', \"{{#this}}\\n  <div data-am-widget=\\\"slider\\\" class=\\\"am-slider {{#if theme}}am-slider-{{theme}}{{else}}am-slider-default{{/if}}{{#if widgetId}} {{widgetId}}{{/if}}{{#if className}} {{className}}{{/if}}\\\" data-am-slider='{{sliderConfig}}' {{#if id}}id=\\\"{{id}}\\\"{{/if}}>\\n  <ul class=\\\"am-slides\\\">\\n    {{#each content}}\\n      <li{{#if thumb}} data-thumb=\\\"{{thumb}}\\\"{{/if}}>\\n        {{#if link}}\\n          <a href=\\\"{{link}}\\\" class=\\\"{{className}}\\\">\\n        {{/if}}\\n        {{#if img}}\\n        \\t<img src=\\\"{{img}}\\\">\\n        {{/if}}\\n        {{#if desc}}\\n          <div class=\\\"am-slider-desc\\\">{{{desc}}}</div>\\n        {{/if}}\\n        {{#if link}}</a>{{/if}} {{!--/end link--}}\\n      </li>\\n    {{/each}}\\n  </ul>\\n</div>\\n{{/this}}\");\n\n    hbs.registerPartial('tabs', \"{{#this}}\\n  <div data-am-widget=\\\"tabs\\\"\\n       class=\\\"am-tabs{{#if theme}} am-tabs-{{theme}}{{else}} am-tabs-default{{/if}}{{#if widgetId}} {{widgetId}}{{/if}}{{#if className}} {{className}}{{/if}}\\\"\\n       {{#if id}}id=\\\"{{id}}\\\"{{/if}} {{#if options.noSwipe}}data-am-tabs-noswipe=\\\"1\\\"{{/if}}>\\n    {{#if content}}\\n      <ul class=\\\"am-tabs-nav am-cf\\\">\\n        {{#each content}}\\n          <li class=\\\"{{#if active}}am-active{{/if}}\\\"><a href=\\\"[data-tab-panel-{{@index}}]\\\">{{{title}}}</a></li>\\n        {{/each}}\\n      </ul>\\n      <div class=\\\"am-tabs-bd\\\">\\n        {{#each content}}\\n          <div data-tab-panel-{{@index}} class=\\\"am-tab-panel {{#if active}}am-active{{/if}}\\\">\\n            {{{content}}}\\n          </div>\\n        {{/each}}\\n      </div>\\n    {{/if}}\\n  </div>\\n{{/this}}\\n\");\n\n    hbs.registerPartial('titlebar', \"{{#this}}\\n<div data-am-widget=\\\"titlebar\\\" class=\\\"am-titlebar {{#if theme}}am-titlebar-{{theme}}{{else}}am-titlebar-default{{/if}}{{#if widgetId}} {{widgetId}}{{/if}}{{#if className}} {{className}}{{/if}}\\\" {{#if id}}id=\\\"{{id}}\\\"{{/if}}>\\n  {{#if content.title}}\\n    <h2 class=\\\"am-titlebar-title {{#unless content.link}}{{content.className}}{{/unless}}\\\">\\n      {{#if content.link}}\\n        <a href=\\\"{{content.link}}\\\" class=\\\"{{content.className}}\\\">{{{content.title}}}</a>\\n      {{else}}\\n        {{{content.title}}}\\n      {{/if}}\\n    </h2>\\n  {{/if}}\\n\\n  {{#if content.nav}}\\n    <nav class=\\\"am-titlebar-nav\\\">\\n      {{#each content.nav}}\\n        <a href=\\\"{{link}}\\\" class=\\\"{{className}}\\\">{{{title}}}</a>\\n      {{/each}}\\n    </nav>\\n  {{/if}}\\n</div>\\n{{/this}}\\n\");\n\n    hbs.registerPartial('wechatpay', \"{{#this}}\\n  <div data-am-widget=\\\"wechatpay\\\" class=\\\"am-wechatpay{{#if theme}} am-wechatpay-{{theme}}{{else}} am-wechatpay-default{{/if}}{{#if widgetId}} {{widgetId}}{{/if}}{{#if className}} {{className}}{{/if}}\\\"{{#if id}} id=\\\"{{id}}\\\"{{/if}} data-wechat-pay=\\\"{ {{#each content.order}} {{@key}}: '{{this}}',{{/each}} }\\\">\\n      <button type=\\\"button\\\" class=\\\"am-btn am-btn-primary am-btn-block am-wechatpay-btn\\\">\\n        {{#if content.title}}\\n          {{content.title}}\\n        {{else}}\\n          微信支付\\n        {{/if}}\\n      </button>\\n  </div>\\n{{/this}}\\n\");\n\n  };\n\n  if (typeof module !== 'undefined' && module.exports) {\n    module.exports = registerAMUIPartials;\n  }\n\n  this.Handlebars && registerAMUIPartials(this.Handlebars);\n}).call(this);\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/assets/js/app.js",
    "content": "(function($) {\n  'use strict';\n\n  $(function() {\n    var $fullText = $('.admin-fullText');\n    $('#admin-fullscreen').on('click', function() {\n      $.AMUI.fullscreen.toggle();\n    });\n\n    $(document).on($.AMUI.fullscreen.raw.fullscreenchange, function() {\n      $fullText.text($.AMUI.fullscreen.isFullscreen ? '退出全屏' : '开启全屏');\n    });\n  });\n})(jQuery);\n\n\n/*全局配置tab控制*/\n$(function() {\n  var tabCounter = 0;\n  var $tab = $('#admin-tab-body-index');\n  var $nav = $tab.find('.am-tabs-nav');\n  var $bd = $tab.find('.am-tabs-bd');\n\n  function addTab() {\n    var nav = '<li><span class=\"am-icon-close\"></span>' +\n        '<a href=\"javascript: void(0)\">标签 ' + tabCounter + '</a></li>';\n    var content = '<div class=\"am-tab-panel\">动态插入的标签内容' + tabCounter + '</div>';\n\n    $nav.append(nav);\n    $bd.append(content);\n    tabCounter++;\n    $tab.tabs('refresh');\n  }\n\n  // 动态添加标签页\n  $('.js-append-tab').on('click', function() {\n    addTab();\n  });\n\n  /**\n   * 动态添加tab\n   */\n  $(document).on('click','.admin-open-new-tab',function(){\n    var iframeUrl = $(this).attr('iframe-url');\n    var iframeName = $(this).attr('iframe-name');\n    var iframeUuid = $(this).attr('iframe-uuid');\n    if(!iframeUrl || !iframeUuid){\n      return;\n    }\n    addIframeTal(iframeUrl,iframeName,iframeUuid);\n  });\n\n  /**\n   * 刷新当前tab页面\n   */\n  $(document).on('click','.am-tab-refresh',function(){\n    var clickIndex = 0;\n    var iframeUuid = $(this).attr('iframe-uuid');\n    $('#admin-tab-body-index>ul>li').each(function(index){\n      if($(this).attr('iframe-uuid') == iframeUuid){\n        clickIndex = index;\n        return;\n      }\n    });\n    //console.log($($('#admin-tab-body-index .am-tabs-bd .am-tab-panel')[clickIndex]).find('iframe')[0])\n    $('.admin-iframe-html')[clickIndex].contentWindow.location.reload(true);\n  });\n\n\n  function addIframeTal(iframeUrl,tabName,iframeUuid){\n    var haveFlg = false;\n    //判断是否打开了该标签页，不能重复打开标签页\n    $('#admin-tab-body-index>ul>li').each(function(index){\n      if($(this).attr('iframe-uuid') == iframeUuid){\n        $tab.tabs('open',index);\n        haveFlg = true;\n        return;\n      }\n    });\n    if(haveFlg == true){\n      return;\n    }\n\n    //不存在该tab则新建tab\n    var nav = '<li iframe-uuid=\"'+iframeUuid+'\">' +\n        '<span class=\"am-tab-refresh am-icon-refresh\" iframe-url=\"'+iframeUrl+'\" iframe-uuid=\"'+iframeUuid+'\"></span>' +\n        '<span class=\"am-icon-close\"></span>' +\n        '<a href=\"javascript: void(0)\" iframe-uuid=\"'+iframeUuid+'\">' + tabName + '</a></li>';\n    var content = '<div class=\"am-tab-panel\" style=\"height: 100%\"><iframe src=\"'+iframeUrl+'\" class=\"admin-iframe-html\" style=\"width: 100%;height: 100%;\"></iframe></div>';\n    $nav.append(nav);\n    $bd.append(content);\n    $tab.tabs('refresh');\n    //$('#admin-tab-body-index').tabs('open',$('#admin-tab-body-index>ul>li').length -1);\n    setTimeout(\"$('#admin-tab-body-index').tabs('open',$('#admin-tab-body-index>ul>li').length -1);\",50);\n  }\n\n\n\n  // 移除标签页\n  $nav.on('click', '.am-icon-close', function() {\n    var $item = $(this).closest('li');\n    var index = $nav.children('li').index($item);\n\n    $item.remove();\n    $bd.find('.am-tab-panel').eq(index).remove();\n\n    $tab.tabs('open', index > 0 ? index - 1 : index + 1);\n    $tab.tabs('refresh');\n  });\n\n  /**\n   * 左移tab标签\n   */\n  $('.admin-tab-left').on('click',function(){\n    moveToRight();\n  });\n\n  function moveToLeft(){\n    //需要显示的下一个tab\n    var getCurrentFlg = false;\n    var currentTab = 0;\n    //需要添加的margin-left总数\n    var addMargin = 0;\n    var tabLength = $('.admin-tab-show').width();\n    var allTabLength = 0;\n    var oneMarginLeft = parseInt($($('#admin-tab-body-index>ul>li')[0]).css('margin-left'));\n    $('#admin-tab-body-index>ul>li').each(function(index){\n      allTabLength = allTabLength + $(this).width();\n      if(parseInt($(this).css('margin-left')) == 0 && getCurrentFlg == false){\n        currentTab = index;\n        getCurrentFlg = true;\n      }\n    });\n    if((allTabLength + oneMarginLeft)> tabLength){\n      /*$('#admin-tab-body-index>ul>li').css('margin-left',(oneMarginLeft-100)+'px')*/\n      for(var i=0;i<$('#admin-tab-body-index>ul>li').length;i++){\n        if(i == currentTab+1){\n          break;\n        }\n        if(i==currentTab){\n          addMargin = parseInt($($('#admin-tab-body-index>ul>li')[i]).css('margin-left')) - $($('#admin-tab-body-index>ul>li')[currentTab]).width() -20;\n        }else{\n          addMargin = parseInt($($('#admin-tab-body-index>ul>li')[i]).css('margin-left')) - $($('#admin-tab-body-index>ul>li')[currentTab]).width();\n        }\n        //$($('#admin-tab-body-index>ul>li')[i]).animate({'margin-left':addMargin+'px'},\"fast\");\n        $($('#admin-tab-body-index>ul>li')[i]).css('margin-left',addMargin+'px');\n      }\n    }\n  }\n  /**\n   * 右移tab标签\n   */\n  $('.admin-tab-right').on('click',function(){\n    moveToLeft();\n  });\n\n  function moveToRight(){\n//需要显示的下一个tab\n    var getCurrentFlg = false;\n    var currentTab = 0;\n    //需要添加的margin-left总数\n    var addMargin = 0;\n    var tabLength = $('.admin-tab-show').width();\n    var allTabLength = 0;\n    var oneMarginLeft = parseInt($($('#admin-tab-body-index>ul>li')[0]).css('margin-left'));\n    $('#admin-tab-body-index>ul>li').each(function(index){\n      allTabLength = allTabLength + $(this).width();\n      if(parseInt($(this).css('margin-left')) == 0 && getCurrentFlg == false){\n        currentTab = index;\n        getCurrentFlg = true;\n      }\n    });\n    if(currentTab != 0){\n      for(var i=0;i<$('#admin-tab-body-index>ul>li').length;i++){\n        if(parseInt($($('#admin-tab-body-index>ul>li')[i]).css('margin-left')) !=0){\n          if((currentTab - 1) == i ){\n            addMargin = parseInt($($('#admin-tab-body-index>ul>li')[i]).css('margin-left')) + $($('#admin-tab-body-index>ul>li')[currentTab-1]).width()+20;\n          }else{\n            addMargin = parseInt($($('#admin-tab-body-index>ul>li')[i]).css('margin-left')) + $($('#admin-tab-body-index>ul>li')[currentTab-1]).width();\n          }\n          //$($('#admin-tab-body-index>ul>li')[i]).animate({'margin-left':addMargin+'px'},\"fast\");\n          $($('#admin-tab-body-index>ul>li')[i]).css('margin-left',addMargin+'px');\n        }\n      }\n    }\n  }\n\n  $('.admin-tab-right-close-all').on('click', function () {\n    if($('.am-icon-close').length == 0){\n      return;\n    }\n    layer.confirm('是否确定删除其他TAB选项卡', {icon: 3,skin: 'layer-ext-moon', title: '提示'}, function (index) {\n      //do something\n      $('.am-icon-close').each(function(index){\n        var $item = $(this).closest('li');\n        var index = $nav.children('li').index($item);\n        $item.remove();\n        $bd.find('.am-tab-panel').eq(index).remove();\n      });\n      $tab.tabs('open', 0);\n      $tab.tabs('refresh');\n      layer.close(index);\n    });\n  });\n});\n\n/**\n * 页面执行完加载左侧列表\n */\n(function () {\n  var html = '';\n  var mainClick = \"$('#admin-tab-body-index').tabs('open', 0);\";\n  html = html + '<li><a href=\"javascript:void(0);\" iframe-uuid=\"' + TAB_JSON.list[0].listUuid + '\" onclick=\"' + mainClick + '\" class=\"admin-open-new-tab\">' +\n      '<span class=\"' + TAB_JSON.list[0].listIcon + '\"></span> ' + TAB_JSON.list[0].listName + ' ' +\n      '<span class=\"' + TAB_JSON.list[0].listRightIcon + ' am-fr am-margin-right ' + TAB_JSON.list[0].listNumberColor + '\">' +\n      '' + TAB_JSON.list[0].listNumber + '</span></a></li>';\n  \n  \n  for (var i = 1; i < TAB_JSON.list.length; i++) {\n    if (TAB_JSON.list[i].isHtml == true) {\n      html = html + '<li style=\"display:none\"><a href=\"javascript:void(0);\" iframe-uuid=\"' + TAB_JSON.list[i].listUuid + '\" class=\"admin-open-new-tab\">' +\n          '<span class=\"' + TAB_JSON.list[i].listIcon + '\"></span> ' + TAB_JSON.list[i].listName + ' ' +\n          '<span class=\"' + TAB_JSON.list[i].listRightIcon + ' am-fr am-margin-right ' + TAB_JSON.list[i].listNumberColor + '\">' +\n          '' + TAB_JSON.list[i].listNumber + '</span></a></li>';\n      \n      if(TAB_JSON.list[i].listUrl != null   && TAB_JSON.list[i].listUrl!= \"\"){\n    \t  \n            html = html + ' <li><a href=\"javascript:void(0);\" iframe-url=\"' + TAB_JSON.list[i].listUrl + '\" ' +\n                'iframe-name=\"' + TAB_JSON.list[i].listName + '\" iframe-uuid=\"' + TAB_JSON.list[i].listUuid + '\" class=\"am-cf admin-open-new-tab\">' +\n                '<span class=\"' + TAB_JSON.list[i].listIcon + '\"></span> ' + TAB_JSON.list[i].listName + '' +\n                '<span class=\"' + TAB_JSON.list[i].listRightIcon + ' am-fr am-margin-right ' + TAB_JSON.list[i].listNumberColor + '\">' +\n                '' + TAB_JSON.list[i].listNumber + '</span>' +\n                '</a></li>'\n          html = html + '</li>';\n    \t  \n      }\n      \n    } else {\n      var subListIdName = 'collapse' + i;\n      var subListId = \"{target: '#\" + subListIdName + \"'}\";\n      html = html + '<li class=\"admin-parent\">' +\n          '<a class=\"am-cf am-collapsed\" data-am-collapse=\"' + subListId + '\"><span class=\"' + TAB_JSON.list[i].listIcon + '\">' +\n          '</span> ' + TAB_JSON.list[i].listName + ' <span class=\"' + TAB_JSON.list[i].listRightIcon + ' am-fr am-margin-right\"></span></a>';\n      if (TAB_JSON.list[i].subList.length == 0) {\n        html = html + '</li>';\n        break;\n      } else {\n        html = html + '<ul class=\"am-list admin-sidebar-sub am-collapse\" id=\"' + subListIdName + '\">';\n        for (var j = 0; j < TAB_JSON.list[i].subList.length; j++) {\n          html = html + ' <li><a href=\"javascript:void(0);\" iframe-url=\"' + TAB_JSON.list[i].subList[j].listUrl + '\" ' +\n              'iframe-name=\"' + TAB_JSON.list[i].subList[j].listName + '\" iframe-uuid=\"' + TAB_JSON.list[i].subList[j].listUuid + '\" class=\"am-cf admin-open-new-tab\">' +\n              '<span class=\"' + TAB_JSON.list[i].subList[j].listIcon + '\"></span> ' + TAB_JSON.list[i].subList[j].listName + '' +\n              '<span class=\"' + TAB_JSON.list[i].subList[j].listRightIcon + ' am-fr am-margin-right ' + TAB_JSON.list[i].subList[j].listNumberColor + '\">' +\n              '' + TAB_JSON.list[i].subList[j].listNumber + '</span>' +\n              '</a></li>'\n        }\n        html = html + '</ul> </li>';\n      }\n    }\n  }\n\n  $('#admin-list-config').html(html);\n})();\n\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/assets/js/area.js",
    "content": "﻿/*\n*\t全国三级城市联动 js版\n*/\nfunction Dsy(){\n\tthis.Items = {};\n}\nDsy.prototype.add = function(id,iArray){\n\tthis.Items[id] = iArray;\n}\nDsy.prototype.Exists = function(id){\n\tif(typeof(this.Items[id]) == \"undefined\") return false;\n\treturn true;\n}\n\nfunction change(v){\n\tvar str=\"0\";\n\tfor(i=0;i<v;i++){\n\t\tstr+=(\"_\"+(document.getElementById(s[i]).selectedIndex-1));\n\t};\n\tvar ss=document.getElementById(s[v]);\n\twith(ss){\n\t\tlength = 0;\n\t\toptions[0]=new Option(opt0[v],opt0[v]);\n\t\tif(v && document.getElementById(s[v-1]).selectedIndex>0 || !v){\n\t\t\tif(dsy.Exists(str)){\n\t\t\t\tar = dsy.Items[str];\n\t\t\t\tfor(i=0;i<ar.length;i++){\n\t\t\t\t\toptions[length]=new Option(ar[i],ar[i]);\n\t\t\t\t}//end for\n\t\t\t\tif(v){ options[0].selected = true; }\n\t\t\t}\n\t\t}//end if v\n\t\tif(++v<s.length){change(v);}\n\t}//End with\n}\n\nvar dsy = new Dsy();\n\ndsy.add(\"0\",[\"北京市\",\"天津市\",\"上海市\",\"重庆市\",\"河北省\",\"山西省\",\"内蒙古\",\"辽宁省\",\"吉林省\",\"黑龙江省\",\"江苏省\",\"浙江省\",\"安徽省\",\"福建省\",\"江西省\",\"山东省\",\"河南省\",\"湖北省\",\"湖南省\",\"广东省\",\"广西\",\"海南省\",\"四川省\",\"贵州省\",\"云南省\",\"西藏\",\"陕西省\",\"甘肃省\",\"青海省\",\"宁夏\",\"新疆\",\"香港\",\"澳门\",\"台湾省\"]);\ndsy.add(\"0_0_0\",[\"东城区\",\"西城区\",\"崇文区\",\"宣武区\",\"朝阳区\",\"丰台区\",\"石景山区\",\"海淀区\",\"门头沟区\",\"房山区\",\"通州区\",\"顺义区\",\"昌平区\",\"大兴区\",\"怀柔区\",\"平谷区\",\"密云县\",\"延庆县\",\"延庆镇\"]);\ndsy.add(\"0_0\",[\"北京市\"]);\ndsy.add(\"0_1_0\",[\"和平区\",\"河东区\",\"河西区\",\"南开区\",\"河北区\",\"红桥区\",\"塘沽区\",\"汉沽区\",\"大港区\",\"东丽区\",\"西青区\",\"津南区\",\"北辰区\",\"武清区\",\"宝坻区\",\"蓟县\",\"宁河县\",\"芦台镇\",\"静海县\",\"静海镇\"]);\ndsy.add(\"0_1\",[\"天津市\"]);\ndsy.add(\"0_2_0\",[\"黄浦区\",\"卢湾区\",\"徐汇区\",\"长宁区\",\"静安区\",\"普陀区\",\"闸北区\",\"虹口区\",\"杨浦区\",\"闵行区\",\"宝山区\",\"嘉定区\",\"浦东新区\",\"金山区\",\"松江区\",\"青浦区\",\"南汇区\",\"奉贤区\",\"崇明县\",\"城桥镇\"]);\ndsy.add(\"0_2\",[\"上海市\"]);\ndsy.add(\"0_3_0\",[\"渝中区\",\"大渡口区\",\"江北区\",\"沙坪坝区\",\"九龙坡区\",\"南岸区\",\"北碚区\",\"万盛区\",\"双桥区\",\"渝北区\",\"巴南区\",\"万州区\",\"涪陵区\",\"黔江区\",\"长寿区\",\"合川市\",\"永川区市\",\"江津市\",\"南川市\",\"綦江县\",\"潼南县\",\"铜梁县\",\"大足县\",\"荣昌县\",\"璧山县\",\"垫江县\",\"武隆县\",\"丰都县\",\"城口县\",\"梁平县\",\"开县\",\"巫溪县\",\"巫山县\",\"奉节县\",\"云阳县\",\"忠县\",\"石柱土家族自治县\",\"彭水苗族土家族自治县\",\"酉阳土家族苗族自治县\",\"秀山土家族苗族自治县\"]);\ndsy.add(\"0_3\",[\"重庆市\"]);\ndsy.add(\"0_4_0\",[\"长安区\",\"桥东区\",\"桥西区\",\"新华区\",\"裕华区\",\"井陉矿区\",\"辛集市\",\"藁城市\",\"晋州市\",\"新乐市\",\"鹿泉市\",\"井陉县\",\"微水镇\",\"正定县\",\"正定镇\",\"栾城县\",\"栾城镇\",\"行唐县\",\"龙州镇\",\"灵寿县\",\"灵寿镇\",\"高邑县\",\"高邑镇\",\"深泽县\",\"深泽镇\",\"赞皇县\",\"赞皇镇\",\"无极县\",\"无极镇\",\"平山县\",\"平山镇\",\"元氏县\",\"槐阳镇\",\"赵县\",\"赵州镇\"]);\ndsy.add(\"0_4_1\",[\"桥西区\",\"桥东区\",\"宣化区\",\"下花园区\",\"宣化县\",\"张家口市宣化区\",\"张北县\",\"张北镇\",\"康保县\",\"康保镇\",\"沽源县\",\"平定堡镇\",\"尚义县\",\"南壕堑镇\",\"蔚县\",\"蔚州镇\",\"阳原县\",\"西城镇\",\"怀安县\",\"柴沟堡镇\",\"万全县\",\"孔家庄镇\",\"怀来县\",\"沙城镇\",\"涿鹿县\",\"涿鹿镇\",\"赤城县\",\"赤城镇\",\"崇礼县\",\"西湾子镇\"]);\ndsy.add(\"0_4_2\",[\"双桥区\",\"双滦区\",\"鹰手营子矿区\",\"承德县\",\"下板城镇\",\"兴隆县\",\"兴隆镇\",\"平泉县\",\"平泉镇\",\"滦平县\",\"滦平镇\",\"隆化县\",\"隆化镇\",\"丰宁满族自治县\",\"大阁镇\",\"宽城满族自治县\",\"宽城镇\",\"围场满族蒙古族自治县\",\"围场镇\"]);\ndsy.add(\"0_4_3\",[\"海港区\",\"山海关区\",\"北戴河区\",\"昌黎县\",\"昌黎镇\",\"抚宁县\",\"抚宁镇\",\"卢龙县\",\"卢龙镇\",\"青龙满族自治县\",\"青龙镇\"]);\ndsy.add(\"0_4_4\",[\"路北区\",\"路南区\",\"古冶区\",\"开平区\",\"丰润区\",\"丰南区\",\"遵化市\",\"迁安市\",\"滦县\",\"滦州镇\",\"滦南县\",\"倴城镇\",\"乐亭县\",\"乐亭镇\",\"迁西县\",\"兴城镇\",\"玉田县\",\"玉田镇\",\"唐海县\",\"唐海镇\"]);\ndsy.add(\"0_4_5\",[\"安次区\",\"广阳区\",\"霸州市\",\"三河市\",\"固安县\",\"固安镇\",\"永清县\",\"永清镇\",\"香河县\",\"淑阳镇\",\"大城县\",\"平舒镇\",\"文安县\",\"文安镇\",\"大厂回族自治县\",\"大厂镇\"]);\ndsy.add(\"0_4_6\",[\"新市区\",\"北市区\",\"南市区\",\"定州市\",\"涿州市\",\"安国市\",\"高碑店市\",\"满城县\",\"满城镇\",\"清苑县\",\"清苑镇\",\"易县\",\"易州镇\",\"徐水县\",\"安肃镇\",\"涞源县\",\"涞源镇\",\"定兴县\",\"定兴镇\",\"顺平县\",\"蒲阳镇\",\"唐县\",\"仁厚镇\",\"望都县\",\"望都镇\",\"涞水县\",\"涞水镇\",\"高阳县\",\"高阳镇\",\"安新县\",\"安新镇\",\"雄县\",\"雄州镇\",\"容城县\",\"容城镇\",\"曲阳县\",\"恒州镇\",\"阜平县\",\"阜平镇\",\"博野县\",\"博陵镇\",\"蠡县\",\"蠡吾镇\"]);\ndsy.add(\"0_4_7\",[\"桃城区\",\"冀州市\",\"深州市\",\"枣强县\",\"枣强镇\",\"武邑县\",\"武邑镇\",\"武强县\",\"武强镇\",\"饶阳县\",\"饶阳镇\",\"安平县\",\"安平镇\",\"故城县\",\"郑口镇\",\"景县\",\"景州镇\",\"阜城县\",\"阜城镇\"]);\ndsy.add(\"0_4_8\",[\"运河区\",\"新华区\",\"泊头市\",\"任丘市\",\"黄骅市\",\"河间市\",\"沧县\",\"沧州市新华区\",\"青县\",\"清州镇\",\"东光县\",\"东光镇\",\"海兴县\",\"苏基镇\",\"盐山县\",\"盐山镇\",\"肃宁县\",\"肃宁镇\",\"南皮县\",\"南皮镇\",\"吴桥县\",\"桑园镇\",\"献县\",\"乐寿镇\",\"孟村回族自治县\",\"孟村镇\"]);\ndsy.add(\"0_4_9\",[\"桥东区\",\"桥西区\",\"南宫市\",\"沙河市\",\"邢台县\",\"邢台市桥东区\",\"临城县\",\"临城镇\",\"内丘县\",\"内丘镇\",\"柏乡县\",\"柏乡镇\",\"隆尧县\",\"隆尧镇\",\"任县\",\"任城镇\",\"南和县\",\"和阳镇\",\"宁晋县\",\"凤凰镇\",\"巨鹿县\",\"巨鹿镇\",\"新河县\",\"新河镇\",\"广宗县\",\"广宗镇\",\"平乡县\",\"丰州镇\",\"威县\",\"洺州镇\",\"清河县\",\"葛仙庄镇\",\"临西县\",\"临西镇\"]);\ndsy.add(\"0_4_10\",[\"丛台区\",\"邯山区\",\"复兴区\",\"峰峰矿区\",\"武安市\",\"邯郸县\",\"南堡乡东小屯村\",\"临漳县\",\"临漳镇\",\"成安县\",\"成安镇\",\"大名县\",\"大名镇\",\"涉县\",\"涉城镇\",\"磁县\",\"磁州镇\",\"肥乡县\",\"肥乡镇\",\"永年县\",\"临洺关镇\",\"邱县\",\"新马头镇\",\"鸡泽县\",\"鸡泽镇\",\"广平县\",\"广平镇\",\"馆陶县\",\"馆陶镇\",\"魏县\",\"魏城镇\",\"曲周县\",\"曲周镇\"]);\ndsy.add(\"0_4\",[\"石家庄市\",\"张家口市\",\"承德市\",\"秦皇岛市\",\"唐山市\",\"廊坊市\",\"保定市\",\"衡水市\",\"沧州市\",\"邢台市\",\"邯郸市\"]);\ndsy.add(\"0_5_0\",[\"杏花岭区\",\"小店区\",\"迎泽区\",\"尖草坪区\",\"万柏林区\",\"晋源区\",\"古交市\",\"清徐县\",\"清源镇\",\"阳曲县\",\"黄寨镇\",\"娄烦县\",\"娄烦镇\"]);\ndsy.add(\"0_5_1\",[\"朔城区\",\"平鲁区\",\"山阴县\",\"岱岳乡\",\"应县\",\"金城镇\",\"右玉县\",\"新城镇\",\"怀仁县\",\"云中镇\"]);\ndsy.add(\"0_5_2\",[\"城区\",\"矿区\",\"南郊区\",\"新荣区\",\"阳高县\",\"龙泉镇\",\"天镇县\",\"玉泉镇\",\"广灵县\",\"壶泉镇\",\"灵丘县\",\"武灵镇\",\"浑源县\",\"永安镇\",\"左云县\",\"云兴镇\",\"大同县\",\"西坪镇\"]);\ndsy.add(\"0_5_3\",[\"城区\",\"矿区\",\"郊区\",\"平定县\",\"冠山镇\",\"盂县\",\"秀水镇\"]);\ndsy.add(\"0_5_4\",[\"城区\",\"郊区\",\"潞城市\",\"长治县\",\"韩店镇\",\"襄垣县\",\"古韩镇\",\"屯留县\",\"麟绛镇\",\"平顺县\",\"青羊镇\",\"黎城县\",\"黎侯镇\",\"壶关县\",\"龙泉镇\",\"长子县\",\"丹朱镇\",\"武乡县\",\"丰州镇\",\"沁县\",\"定昌镇\",\"沁源县\",\"沁河镇\"]);\ndsy.add(\"0_5_5\",[\"城区\",\"高平市\",\"泽州县\",\"南村镇\",\"沁水县\",\"龙港镇\",\"阳城县\",\"凤城镇\",\"陵川县\",\"崇文镇\"]);\ndsy.add(\"0_5_6\",[\"忻府区\",\"原平市\",\"定襄县\",\"晋昌镇\",\"五台县\",\"台城镇\",\"代县\",\"上馆镇\",\"繁峙县\",\"繁城镇\",\"宁武县\",\"凤凰镇\",\"静乐县\",\"鹅城镇\",\"神池县\",\"龙泉镇\",\"五寨县\",\"砚城镇\",\"岢岚县\",\"岚漪镇\",\"河曲县\",\"文笔镇\",\"保德县\",\"东关镇\",\"偏关县\",\"新关镇\"]);\ndsy.add(\"0_5_7\",[\"榆次区\",\"介休市\",\"榆社县\",\"箕城镇\",\"左权县\",\"辽阳镇\",\"和顺县\",\"义兴镇\",\"昔阳县\",\"乐平镇\",\"寿阳县\",\"朝阳镇\",\"太谷县\",\"明星镇\",\"祁县\",\"昭余镇\",\"平遥县\",\"古陶镇\",\"灵石县\",\"翠峰镇\"]);\ndsy.add(\"0_5_8\",[\"尧都区\",\"侯马市\",\"霍州市\",\"曲沃县\",\"乐昌镇\",\"翼城县\",\"唐兴镇\",\"襄汾县\",\"新城镇\",\"洪洞县\",\"大槐树镇\",\"古县\",\"岳阳镇\",\"安泽县\",\"府城镇\",\"浮山县\",\"天坛镇\",\"吉县\",\"吉昌镇\",\"乡宁县\",\"昌宁镇\",\"蒲县\",\"蒲城镇\",\"大宁县\",\"昕水镇\",\"永和县\",\"芝河镇\",\"隰县\",\"龙泉镇\",\"汾西县\",\"永安镇\"]);\ndsy.add(\"0_5_9\",[\"离石区\",\"孝义市\",\"汾阳市\",\"文水县\",\"凤城镇\",\"中阳县\",\"宁乡镇\",\"兴县\",\"蔚汾镇\",\"临县\",\"临泉镇\",\"方山县\",\"圪洞镇\",\"柳林县\",\"柳林镇\",\"岚县\",\"东村镇\",\"交口县\",\"水头镇\",\"交城县\",\"天宁镇\",\"石楼县\",\"灵泉镇\"]);\ndsy.add(\"0_5_10\",[\"盐湖区\",\"永济市\",\"河津市\",\"芮城县\",\"古魏镇\",\"临猗县\",\"猗氏镇\",\"万荣县\",\"解店镇\",\"新绛县\",\"龙兴镇\",\"稷山县\",\"稷峰镇\",\"闻喜县\",\"桐城镇\",\"夏县\",\"瑶峰镇\",\"绛县\",\"古绛镇\",\"平陆县\",\"圣人涧镇\",\"垣曲县\",\"新城镇\"]);\ndsy.add(\"0_5\",[\"太原市\",\"朔州市\",\"大同市\",\"阳泉市\",\"长治市\",\"晋城市\",\"忻州市\",\"晋中市\",\"临汾市\",\"吕梁市\",\"运城市\"]);\ndsy.add(\"0_6_0\",[\"回民区\",\"新城区\",\"玉泉区\",\"赛罕区\",\"托克托县\",\"双河镇\",\"武川县\",\"可可以力更镇\",\"和林格尔县\",\"城关镇\",\"清水河县\",\"城关镇\",\"土默特左旗\",\"察素齐镇\"]);\ndsy.add(\"0_6_1\",[\"昆都仑区\",\"东河区\",\"青山区\",\"石拐区\",\"白云矿区\",\"九原区\",\"固阳县\",\"金山镇\",\"土默特右旗\",\"萨拉齐镇\",\"达尔罕茂明安联合旗\",\"百灵庙镇\"]);\ndsy.add(\"0_6_2\",[\"海勃湾区\",\"海南区\",\"乌达区\"]);\ndsy.add(\"0_6_3\",[\"红山区\",\"元宝山区\",\"松山区\",\"宁城县\",\"天义镇\",\"林西县\",\"林西镇\",\"阿鲁科尔沁旗\",\"天山镇\",\"巴林左旗\",\"林东镇\",\"巴林右旗\",\"大板镇\",\"克什克腾旗\",\"经棚镇\",\"翁牛特旗\",\"乌丹镇\",\"喀喇沁旗\",\"锦山镇\",\"敖汉旗\",\"新惠镇\"]);\ndsy.add(\"0_6_4\",[\"科尔沁区\",\"霍林郭勒市\",\"开鲁县\",\"开鲁镇\",\"库伦旗\",\"库伦镇\",\"奈曼旗\",\"大沁他拉镇\",\"扎鲁特旗\",\"鲁北镇\",\"科尔沁左翼中旗\",\"保康镇\",\"科尔沁左翼后旗\",\"甘旗卡镇\"]);\ndsy.add(\"0_6_5\",[\"海拉尔区\",\"满洲里市\",\"扎兰屯市\",\"牙克石市\",\"根河市\",\"额尔古纳市\",\"阿荣旗\",\"那吉镇\",\"新巴尔虎右旗\",\"阿拉坦额莫勒镇\",\"新巴尔虎左旗\",\"阿穆古郎镇\",\"陈巴尔虎旗\",\"巴彦库仁镇\",\"鄂伦春自治旗\",\"阿里河镇\",\"鄂温克族自治旗\",\"巴彦托海镇\",\"莫力达瓦达斡尔族自治旗\",\"尼尔基镇\"]);\ndsy.add(\"0_6_6\",[\"东胜区\",\"达拉特旗\",\"树林召镇\",\"准格尔旗\",\"薛家湾镇\",\"鄂托克前旗\",\"敖勒召其镇\",\"鄂托克旗\",\"乌兰镇\",\"杭锦旗\",\"锡尼镇\",\"乌审旗\",\"嘎鲁图镇\",\"伊金霍洛旗\",\"阿勒腾席热镇\"]);\ndsy.add(\"0_6_7\",[\"集宁区\",\"丰镇市\",\"卓资县\",\"卓资山镇\",\"化德县\",\"长顺镇\",\"商都县\",\"商都镇\",\"兴和县\",\"城关镇\",\"凉城县\",\"岱海镇\",\"察哈尔右翼前旗\",\"土贵乌拉镇\",\"察哈尔右翼中旗\",\"科布尔镇\",\"察哈尔右翼后旗\",\"白音察干镇\",\"四子王旗\",\"乌兰花镇\"]);\ndsy.add(\"0_6_8\",[\"临河区\",\"五原县\",\"隆兴昌镇\",\"磴口县\",\"巴彦高勒镇\",\"乌拉特前旗\",\"乌拉山镇\",\"乌拉特中旗\",\"海流图镇\",\"乌拉特后旗\",\"巴音宝力格镇\",\"杭锦后旗\",\"陕坝镇\"]);\ndsy.add(\"0_6_9\",[\"乌兰浩特市\",\"阿尔山市\",\"突泉县\",\"突泉镇\",\"科尔沁右翼前旗\",\"大坝沟镇\",\"科尔沁右翼中旗\",\"巴彦呼硕镇\",\"扎赉特旗\",\"音德尔镇\"]);\ndsy.add(\"0_6_10\",[\"锡林浩特市\",\"二连浩特市\",\"多伦县\",\"多伦淖尔镇\",\"阿巴嘎旗\",\"别力古台镇\",\"苏尼特左旗\",\"满都拉图镇\",\"苏尼特右旗\",\"赛汉塔拉镇\",\"东乌珠穆沁旗\",\"乌里雅斯太镇\",\"西乌珠穆沁旗\",\"巴拉嘎尔郭勒镇\",\"太仆寺旗\",\"宝昌镇\",\"镶黄旗\",\"新宝拉格镇\",\"正镶白旗\",\"明安图镇\",\"正蓝旗\",\"上都镇\"]);\ndsy.add(\"0_6_11\",[\"巴彦浩特镇\",\"阿拉善右旗\",\"额肯呼都格镇\",\"额济纳旗\",\"达来呼布镇\"]);\ndsy.add(\"0_6\",[\"呼和浩特市\",\"包头市\",\"乌海市\",\"赤峰市\",\"通辽市\",\"呼伦贝尔市\",\"鄂尔多斯市\",\"乌兰察布市\",\"巴彦淖尔市\",\"兴安盟\",\"锡林郭勒盟\",\"阿拉善盟\"]);\ndsy.add(\"0_7_0\",[\"沈河区\",\"和平区\",\"大东区\",\"皇姑区\",\"铁西区\",\"苏家屯区\",\"东陵区\",\"新城子区\",\"于洪区\",\"新民市\",\"辽中县\",\"辽中镇\",\"康平县\",\"康平镇\",\"法库县\",\"法库镇\"]);\ndsy.add(\"0_7_1\",[\"双塔区\",\"龙城区\",\"北票市\",\"凌源市\",\"朝阳县\",\"朝阳市双塔区\",\"建平县\",\"喀喇沁左翼蒙古族自治县\",\"大城子镇\"]);\ndsy.add(\"0_7_2\",[\"海州区\",\"新邱区\",\"太平区\",\"清河门区\",\"细河区\",\"彰武县\",\"彰武镇\",\"阜新蒙古族自治县\",\"阜新镇\"]);\ndsy.add(\"0_7_3\",[\"银州区\",\"清河区\",\"调兵山市\",\"开原市\",\"铁岭县\",\"铁岭市银州区\",\"西丰县\",\"西丰镇\",\"昌图县\",\"昌图镇\"]);\ndsy.add(\"0_7_4\",[\"顺城区\",\"新抚区\",\"东洲区\",\"望花区\",\"抚顺县\",\"抚顺市顺城区\",\"新宾满族自治县\",\"新宾镇\",\"清原满族自治县\",\"清原镇\"]);\ndsy.add(\"0_7_5\",[\"平山区\",\"溪湖区\",\"明山区\",\"南芬区\",\"本溪满族自治县\",\"小市镇\",\"桓仁满族自治县\",\"桓仁镇\"]);\ndsy.add(\"0_7_6\",[\"白塔区\",\"文圣区\",\"宏伟区\",\"弓长岭区\",\"太子河区\",\"灯塔市\",\"辽阳县\",\"首山镇\"]);\ndsy.add(\"0_7_7\",[\"铁东区\",\"铁西区\",\"立山区\",\"千山区\",\"海城市\",\"台安县\",\"台安镇\",\"岫岩满族自治县\",\"岫岩镇\"]);\ndsy.add(\"0_7_8\",[\"振兴区\",\"元宝区\",\"振安区\",\"凤城市\",\"东港市\",\"宽甸满族自治县\",\"宽甸镇\"]);\ndsy.add(\"0_7_9\",[\"西岗区\",\"中山区\",\"沙河口区\",\"甘井子区\",\"旅顺口区\",\"金州区\",\"瓦房店市\",\"普兰店市\",\"庄河市\",\"长海县\",\"大长山岛镇\"]);\ndsy.add(\"0_7_10\",[\"站前区\",\"西市区\",\"鲅鱼圈区\",\"老边区\",\"大石桥市\",\"盖州市\"]);\ndsy.add(\"0_7_11\",[\"兴隆台区\",\"双台子区\",\"大洼县\",\"大洼镇\",\"盘山县\",\"盘锦市双台子区\"]);\ndsy.add(\"0_7_12\",[\"太和区\",\"古塔区\",\"凌河区\",\"凌海市\",\"北宁市\",\"黑山县\",\"黑山镇\",\"义县\",\"义州镇\"]);\ndsy.add(\"0_7_13\",[\"龙港区\",\"连山区\",\"南票区\",\"兴城市\",\"绥中县\",\"绥中镇\",\"建昌县\",\"建昌镇\"]);\ndsy.add(\"0_7\",[\"沈阳市\",\"朝阳市\",\"阜新市\",\"铁岭市\",\"抚顺市\",\"本溪市\",\"辽阳市\",\"鞍山市\",\"丹东市\",\"大连市\",\"营口市\",\"盘锦市\",\"锦州市\",\"葫芦岛市\"]);\ndsy.add(\"0_8_0\",[\"朝阳区\",\"南关区\",\"宽城区\",\"二道区\",\"绿园区\",\"双阳区\",\"德惠市\",\"九台市\",\"榆树市\",\"农安县\",\"农安镇\"]);\ndsy.add(\"0_8_1\",[\"洮北区\",\"大安市\",\"洮南市\",\"镇赉县\",\"镇赉镇\",\"通榆县\",\"开通镇\"]);\ndsy.add(\"0_8_2\",[\"宁江区\",\"扶余县\",\"三岔河镇\",\"长岭县\",\"长岭镇\",\"乾安县\",\"乾安镇\",\"前郭尔罗斯蒙古族自治县\",\"前郭镇\"]);\ndsy.add(\"0_8_3\",[\"船营区\",\"龙潭区\",\"昌邑区\",\"丰满区\",\"磐石市\",\"蛟河市\",\"桦甸市\",\"舒兰市\",\"永吉县\",\"口前镇\"]);\ndsy.add(\"0_8_4\",[\"铁西区\",\"铁东区\",\"双辽市\",\"公主岭市\",\"梨树县\",\"梨树镇\",\"伊通满族自治县\",\"伊通镇\"]);\ndsy.add(\"0_8_5\",[\"龙山区\",\"西安区\",\"东丰县\",\"东丰镇\",\"东辽县\",\"白泉镇\"]);\ndsy.add(\"0_8_6\",[\"东昌区\",\"二道江区\",\"梅河口市\",\"集安市\",\"通化县\",\"快大茂镇\",\"辉南县\",\"朝阳镇\",\"柳河县\",\"柳河镇\"]);\ndsy.add(\"0_8_7\",[\"八道江区\",\"临江市\",\"江源县\",\"孙家堡子镇\",\"抚松县\",\"抚松镇\",\"靖宇县\",\"靖宇镇\",\"长白朝鲜族自治县\",\"长白镇\"]);\ndsy.add(\"0_8_8\",[\"延吉市\",\"图们市\",\"敦化市\",\"珲春市\",\"龙井市\",\"和龙市\",\"汪清县\",\"汪清镇\",\"安图县\",\"明月镇\"]);\ndsy.add(\"0_8\",[\"长春市\",\"白城市\",\"松原市\",\"吉林市\",\"四平市\",\"辽源市\",\"通化市\",\"白山市\",\"延边州\"]);\ndsy.add(\"0_9_0\",[\"松北区\",\"道里区\",\"南岗区\",\"道外区\",\"香坊区\",\"动力区\",\"平房区\",\"呼兰区\",\"双城市\",\"尚志市\",\"五常市\",\"阿城市\",\"依兰县\",\"依兰镇\",\"方正县\",\"方正镇\",\"宾县\",\"宾州镇\",\"巴彦县\",\"巴彦镇\",\"木兰县\",\"木兰镇\",\"通河县\",\"通河镇\",\"延寿县\",\"延寿镇\"]);\ndsy.add(\"0_9_1\",[\"建华区\",\"龙沙区\",\"铁锋区\",\"昂昂溪区\",\"富拉尔基区\",\"碾子山区\",\"梅里斯达斡尔族区\",\"讷河市\",\"龙江县\",\"龙江镇\",\"依安县\",\"依安镇\",\"泰来县\",\"泰来镇\",\"甘南县\",\"甘南镇\",\"富裕县\",\"富裕镇\",\"克山县\",\"克山镇\",\"克东县\",\"克东镇\",\"拜泉县\",\"拜泉镇\"]);\ndsy.add(\"0_9_2\",[\"桃山区\",\"新兴区\",\"茄子河区\",\"勃利县\",\"勃利镇\"]);\ndsy.add(\"0_9_3\",[\"爱辉区\",\"北安市\",\"五大连池市\",\"嫩江县\",\"嫩江镇\",\"逊克县\",\"边疆镇\",\"孙吴县\",\"孙吴镇\"]);\ndsy.add(\"0_9_4\",[\"萨尔图区\",\"龙凤区\",\"让胡路区\",\"大同区\",\"红岗区\",\"肇州县\",\"肇州镇\",\"肇源县\",\"肇源镇\",\"林甸县\",\"林甸镇\",\"杜尔伯特蒙古族自治县\",\"泰康镇\"]);\ndsy.add(\"0_9_5\",[\"兴山区\",\"向阳区\",\"工农区\",\"南山区\",\"兴安区\",\"东山区\",\"萝北县\",\"凤翔镇\",\"绥滨县\",\"绥滨镇\"]);\ndsy.add(\"0_9_6\",[\"伊春区\",\"南岔区\",\"友好区\",\"西林区\",\"翠峦区\",\"新青区\",\"美溪区\",\"金山屯区\",\"五营区\",\"乌马河区\",\"汤旺河区\",\"带岭区\",\"乌伊岭区\",\"红星区\",\"上甘岭区\",\"铁力市\",\"嘉荫县\",\"朝阳镇\"]);\ndsy.add(\"0_9_7\",[\"前进区\",\"永红区\",\"向阳区\",\"东风区\",\"郊区\",\"同江市\",\"富锦市\",\"桦南县\",\"桦南镇\",\"桦川县\",\"悦来镇\",\"汤原县\",\"汤原镇\",\"抚远县\",\"抚远镇\"]);\ndsy.add(\"0_9_8\",[\"尖山区\",\"岭东区\",\"四方台区\",\"宝山区\",\"集贤县\",\"福利镇\",\"友谊县\",\"友谊镇\",\"宝清县\",\"宝清镇\",\"饶河县\",\"饶河镇\"]);\ndsy.add(\"0_9_9\",[\"鸡冠区\",\"恒山区\",\"滴道区\",\"梨树区\",\"城子河区\",\"麻山区\",\"虎林市\",\"密山市\",\"鸡东县\",\"鸡东镇\"]);\ndsy.add(\"0_9_10\",[\"爱民区\",\"东安区\",\"阳明区\",\"西安区\",\"穆棱市\",\"绥芬河市\",\"海林市\",\"宁安市\",\"东宁县\",\"东宁镇\",\"林口县\",\"林口镇\"]);\ndsy.add(\"0_9_11\",[\"北林区\",\"安达市\",\"肇东市\",\"海伦市\",\"望奎县\",\"望奎镇\",\"兰西县\",\"兰西镇\",\"青冈县\",\"青冈镇\",\"庆安县\",\"庆安镇\",\"明水县\",\"明水镇\",\"绥棱县\",\"绥棱镇\"]);\ndsy.add(\"0_9_12\",[\"呼玛县\",\"呼玛镇\",\"塔河县\",\"塔河镇\",\"漠河县\",\"西林吉镇\"]);\ndsy.add(\"0_9\",[\"哈尔滨市\",\"齐齐哈尔市\",\"七台河市\",\"黑河市\",\"大庆市\",\"鹤岗市\",\"伊春市\",\"佳木斯市\",\"双鸭山市\",\"鸡西市\",\"牡丹江市\",\"绥化市\",\"大兴安岭地区\"]);\ndsy.add(\"0_10_0\",[\"玄武区\",\"白下区\",\"秦淮区\",\"建邺区\",\"鼓楼区\",\"下关区\",\"浦口区\",\"六合区\",\"栖霞区\",\"雨花台区\",\"江宁区\",\"溧水县\",\"永阳镇\",\"高淳县\",\"淳溪镇\"]);\ndsy.add(\"0_10_1\",[\"云龙区\",\"鼓楼区\",\"九里区\",\"贾汪区\",\"泉山区\",\"邳州市\",\"新沂市\",\"铜山县\",\"铜山镇\",\"睢宁县\",\"睢城镇\",\"沛县\",\"沛城镇\",\"丰县\",\"凤城镇\"]);\ndsy.add(\"0_10_2\",[\"新浦区\",\"连云区\",\"海州区\",\"赣榆县\",\"青口镇\",\"灌云县\",\"伊山镇\",\"东海县\",\"牛山镇\",\"灌南县\",\"新安镇\"]);\ndsy.add(\"0_10_3\",[\"宿城区\",\"宿豫区\",\"沭阳县\",\"沭城镇\",\"泗阳县\",\"众兴镇\",\"泗洪县\",\"青阳镇\"]);\ndsy.add(\"0_10_4\",[\"清河区\",\"清浦区\",\"楚州区\",\"淮阴区\",\"金湖县\",\"黎城镇\",\"盱眙县\",\"盱城镇\",\"洪泽县\",\"高良涧镇\",\"涟水县\",\"涟城镇\"]);\ndsy.add(\"0_10_5\",[\"亭湖区\",\"盐都区\",\"东台市\",\"大丰市\",\"射阳县\",\"合德镇\",\"阜宁县\",\"阜城镇\",\"滨海县\",\"东坎镇\",\"响水县\",\"响水镇\",\"建湖县\",\"近湖镇\"]);\ndsy.add(\"0_10_6\",[\"维扬区\",\"广陵区\",\"邗江区\",\"仪征市\",\"江都市\",\"高邮市\",\"宝应县\",\"安宜镇\"]);\ndsy.add(\"0_10_7\",[\"海陵区\",\"高港区\",\"靖江市\",\"泰兴市\",\"姜堰市\",\"兴化市\"]);\ndsy.add(\"0_10_8\",[\"崇川区\",\"港闸区\",\"海门市\",\"启东市\",\"通州市\",\"如皋市\",\"如东县\",\"掘港镇\",\"海安县\",\"海安镇\"]);\ndsy.add(\"0_10_9\",[\"京口区\",\"润州区\",\"丹徒区\",\"扬中市\",\"丹阳市\",\"句容市\"]);\ndsy.add(\"0_10_10\",[\"钟楼区\",\"天宁区\",\"戚墅堰区\",\"新北区\",\"武进区\",\"金坛市\",\"溧阳市\"]);\ndsy.add(\"0_10_11\",[\"崇安区\",\"南长区\",\"北塘区\",\"滨湖区\",\"惠山区\",\"锡山区\",\"江阴市\",\"宜兴市\"]);\ndsy.add(\"0_10_12\",[\"金阊区\",\"沧浪区\",\"平江区\",\"虎丘区\",\"吴中区\",\"相城区\",\"吴江市\",\"昆山市\",\"太仓市\",\"常熟市\",\"张家港市\"]);\ndsy.add(\"0_10\",[\"南京市\",\"徐州市\",\"连云港市\",\"宿迁市\",\"淮安市\",\"盐城市\",\"扬州市\",\"泰州市\",\"南通市\",\"镇江市\",\"常州市\",\"无锡市\",\"苏州市\"]);\ndsy.add(\"0_11_0\",[\"拱墅区\",\"上城区\",\"下城区\",\"江干区\",\"西湖区\",\"滨江区\",\"余杭区\",\"萧山区\",\"临安市\",\"富阳市\",\"建德市\",\"桐庐县\",\"淳安县\",\"千岛湖镇\"]);\ndsy.add(\"0_11_1\",[\"吴兴区\",\"南浔区\",\"长兴县\",\"雉城镇\",\"德清县\",\"武康镇\",\"安吉县\",\"递铺镇\"]);\ndsy.add(\"0_11_2\",[\"南湖区\",\"秀洲区\",\"平湖市\",\"海宁市\",\"桐乡市\",\"嘉善县\",\"魏塘镇\",\"海盐县\",\"武原镇\"]);\ndsy.add(\"0_11_3\",[\"定海区\",\"普陀区\",\"岱山县\",\"高亭镇\",\"嵊泗县\",\"菜园镇\"]);\ndsy.add(\"0_11_4\",[\"海曙区\",\"江东区\",\"江北区\",\"北仑区\",\"镇海区\",\"鄞州区\",\"慈溪市\",\"余姚市\",\"奉化市\",\"宁海县\",\"象山县\"]);\ndsy.add(\"0_11_5\",[\"越城区\",\"诸暨市\",\"上虞市\",\"嵊州市\",\"绍兴县\",\"新昌县\",\"城关镇\"]);\ndsy.add(\"0_11_6\",[\"柯城区\",\"衢江区\",\"江山市\",\"常山县\",\"天马镇\",\"开化县\",\"城关镇\",\"龙游县\"]);\ndsy.add(\"0_11_7\",[\"婺城区\",\"金东区\",\"兰溪市\",\"永康市\",\"义乌市\",\"东阳市\",\"武义县\",\"浦江县\",\"磐安县\",\"安文镇\"]);\ndsy.add(\"0_11_8\",[\"椒江区\",\"黄岩区\",\"路桥区\",\"临海市\",\"温岭市\",\"三门县\",\"海游镇\",\"天台县\",\"仙居县\",\"玉环县\",\"珠港镇\"]);\ndsy.add(\"0_11_9\",[\"鹿城区\",\"龙湾区\",\"瓯海区\",\"瑞安市\",\"乐清市\",\"永嘉县\",\"上塘镇\",\"文成县\",\"大峃镇\",\"平阳县\",\"昆阳镇\",\"泰顺县\",\"罗阳镇\",\"洞头县\",\"北岙镇\",\"苍南县\",\"灵溪镇\"]);\ndsy.add(\"0_11_10\",[\"莲都区\",\"龙泉市\",\"缙云县\",\"五云镇\",\"青田县\",\"鹤城镇\",\"云和县\",\"云和镇\",\"遂昌县\",\"妙高镇\",\"松阳县\",\"西屏镇\",\"庆元县\",\"松源镇\",\"景宁畲族自治县\",\"鹤溪镇\"]);\ndsy.add(\"0_11\",[\"杭州市\",\"湖州市\",\"嘉兴市\",\"舟山市\",\"宁波市\",\"绍兴市\",\"衢州市\",\"金华市\",\"台州市\",\"温州市\",\"丽水市\"]);\ndsy.add(\"0_12_0\",[\"庐阳区\",\"瑶海区\",\"蜀山区\",\"包河区\",\"长丰县\",\"水湖镇\",\"肥东县\",\"店埠镇\",\"肥西县\",\"上派镇\"]);\ndsy.add(\"0_12_1\",[\"埇桥区\",\"砀山县\",\"砀城镇\",\"萧县\",\"龙城镇\",\"灵璧县\",\"灵城镇\",\"泗县\",\"泗城镇\"]);\ndsy.add(\"0_12_2\",[\"相山区\",\"杜集区\",\"烈山区\",\"濉溪县\",\"濉溪镇\"]);\ndsy.add(\"0_12_3\",[\"谯城区\",\"涡阳县\",\"城关镇\",\"蒙城县\",\"城关镇\",\"利辛县\",\"城关镇\"]);\ndsy.add(\"0_12_4\",[\"颍州区\",\"颍东区\",\"颍泉区\",\"界首市\",\"临泉县\",\"城关镇\",\"太和县\",\"城关镇\",\"阜南县\",\"城关镇\",\"颍上县\",\"慎城镇\"]);\ndsy.add(\"0_12_5\",[\"蚌山区\",\"龙子湖区\",\"禹会区\",\"淮上区\",\"怀远县\",\"城关镇\",\"五河县\",\"城关镇\",\"固镇县\",\"城关镇\"]);\ndsy.add(\"0_12_6\",[\"田家庵区\",\"大通区\",\"谢家集区\",\"八公山区\",\"潘集区\",\"凤台县\",\"城关镇\"]);\ndsy.add(\"0_12_7\",[\"琅区\",\"南谯区\",\"明光市\",\"天长市\",\"来安县\",\"新安镇\",\"全椒县\",\"襄河镇\",\"定远县\",\"定城镇\",\"凤阳县\",\"府城镇\"]);\ndsy.add(\"0_12_8\",[\"雨山区\",\"花山区\",\"金家庄区\",\"当涂县\",\"姑孰镇\"]);\ndsy.add(\"0_12_9\",[\"镜湖区\",\"弋江区\",\"三山区\",\"鸠江区\",\"芜湖县\",\"湾镇\",\"繁昌县\",\"繁阳镇\",\"南陵县\",\"籍山镇\"]);\ndsy.add(\"0_12_10\",[\"铜官山区\",\"狮子山区\",\"郊区\",\"铜陵县\",\"五松镇\"]);\ndsy.add(\"0_12_11\",[\"迎江区\",\"大观区\",\"宜秀区\",\"桐城市\",\"怀宁县\",\"高河镇\",\"枞阳县\",\"枞阳镇\",\"潜山县\",\"梅城镇\",\"太湖县\",\"晋熙镇\",\"宿松县\",\"孚玉镇\",\"望江县\",\"雷阳镇\",\"岳西县\",\"天堂镇\"]);\ndsy.add(\"0_12_12\",[\"屯溪区\",\"黄山区\",\"徽州区\",\"歙县\",\"徽城镇\",\"休宁县\",\"海阳镇\",\"黟县\",\"碧阳镇\",\"祁门县\",\"祁山镇\"]);\ndsy.add(\"0_12_13\",[\"金安区\",\"裕安区\",\"寿县\",\"寿春镇\",\"霍邱县\",\"城关镇\",\"舒城县\",\"城关镇\",\"金寨县\",\"梅山镇\",\"霍山县\",\"衡山镇\"]);\ndsy.add(\"0_12_14\",[\"居巢区\",\"庐江县\",\"庐城镇\",\"无为县\",\"无城镇\",\"含山县\",\"环峰镇\",\"和县\",\"历阳镇\"]);\ndsy.add(\"0_12_15\",[\"贵池区\",\"东至县\",\"尧渡镇\",\"石台县\",\"七里镇\",\"青阳县\",\"蓉城镇\"]);\ndsy.add(\"0_12_16\",[\"宣州区\",\"宁国市\",\"郎溪县\",\"建平镇\",\"广德县\",\"桃州镇\",\"泾县\",\"泾川镇\",\"旌德县\",\"旌阳镇\",\"绩溪县\",\"华阳镇\"]);\ndsy.add(\"0_12\",[\"合肥市\",\"宿州市\",\"淮北市\",\"亳州市\",\"阜阳市\",\"蚌埠市\",\"淮南市\",\"滁州市\",\"马鞍山市\",\"芜湖市\",\"铜陵市\",\"安庆市\",\"黄山市\",\"六安市\",\"巢湖市\",\"池州市\",\"宣城市\"]);\ndsy.add(\"0_13_0\",[\"鼓楼区\",\"台江区\",\"仓山区\",\"马尾区\",\"晋安区\",\"福清市\",\"长乐市\",\"闽侯县\",\"连江县\",\"凤城镇\",\"罗源县\",\"凤山镇\",\"闽清县\",\"梅城镇\",\"永泰县\",\"樟城镇\",\"平潭县\",\"潭城镇\"]);\ndsy.add(\"0_13_1\",[\"延平区\",\"邵武市\",\"武夷山市\",\"建瓯市\",\"建阳市\",\"顺昌县\",\"浦城县\",\"光泽县\",\"杭川镇\",\"松溪县\",\"松源镇\",\"政和县\",\"熊山镇\"]);\ndsy.add(\"0_13_2\",[\"城厢区\",\"涵江区\",\"荔城区\",\"秀屿区\",\"仙游县\"]);\ndsy.add(\"0_13_3\",[\"梅列区\",\"三元区\",\"永安市\",\"明溪县\",\"雪峰镇\",\"清流县\",\"龙津镇\",\"宁化县\",\"翠江镇\",\"大田县\",\"均溪镇\",\"尤溪县\",\"城关镇\",\"沙县\",\"将乐县\",\"古镛镇\",\"泰宁县\",\"杉城镇\",\"建宁县\",\"濉城镇\"]);\ndsy.add(\"0_13_4\",[\"鲤城区\",\"丰泽区\",\"洛江区\",\"泉港区\",\"石狮市\",\"晋江市\",\"南安市\",\"惠安县\",\"螺城镇\",\"安溪县\",\"凤城镇\",\"永春县\",\"桃城镇\",\"德化县\",\"浔中镇\",\"金门县\",\"☆\"]);\ndsy.add(\"0_13_5\",[\"思明区\",\"海沧区\",\"湖里区\",\"集美区\",\"同安区\",\"翔安区\"]);\ndsy.add(\"0_13_6\",[\"芗城区\",\"龙文区\",\"龙海市\",\"云霄县\",\"云陵镇\",\"漳浦县\",\"绥安镇\",\"诏安县\",\"南诏镇\",\"长泰县\",\"武安镇\",\"东山县\",\"西埔镇\",\"南靖县\",\"山城镇\",\"平和县\",\"小溪镇\",\"华安县\",\"华丰镇\"]);\ndsy.add(\"0_13_7\",[\"新罗区\",\"漳平市\",\"长汀县\",\"汀州镇\",\"永定县\",\"凤城镇\",\"上杭县\",\"临江镇\",\"武平县\",\"平川镇\",\"连城县\",\"莲峰镇\"]);\ndsy.add(\"0_13_8\",[\"蕉城区\",\"福安市\",\"福鼎市\",\"寿宁县\",\"鳌阳镇\",\"霞浦县\",\"柘荣县\",\"双城镇\",\"屏南县\",\"古峰镇\",\"古田县\",\"周宁县\",\"狮城镇\"]);\ndsy.add(\"0_13\",[\"福州市\",\"南平市\",\"莆田市\",\"三明市\",\"泉州市\",\"厦门市\",\"漳州市\",\"龙岩市\",\"宁德市\"]);\ndsy.add(\"0_14_0\",[\"东湖区\",\"西湖区\",\"青云谱区\",\"湾里区\",\"青山湖区\",\"南昌县\",\"莲塘镇\",\"新建县\",\"长堎镇\",\"安义县\",\"龙津镇\",\"进贤县\",\"民和镇\"]);\ndsy.add(\"0_14_1\",[\"浔阳区\",\"庐山区\",\"瑞昌市\",\"九江县\",\"沙河街镇\",\"武宁县\",\"新宁镇\",\"修水县\",\"义宁镇\",\"永修县\",\"涂埠镇\",\"德安县\",\"蒲亭镇\",\"星子县\",\"南康镇\",\"都昌县\",\"都昌镇\",\"湖口县\",\"双钟镇\",\"彭泽县\",\"龙城镇\"]);\ndsy.add(\"0_14_2\",[\"珠山区\",\"昌江区\",\"乐平市\",\"浮梁县\",\"浮梁镇\"]);\ndsy.add(\"0_14_3\",[\"月湖区\",\"贵溪市\",\"余江县\",\"邓埠镇\"]);\ndsy.add(\"0_14_4\",[\"渝水区\",\"分宜县\",\"分宜镇\"]);\ndsy.add(\"0_14_5\",[\"安源区\",\"湘东区\",\"莲花县\",\"琴亭镇\",\"上栗县\",\"上栗镇\",\"芦溪县\",\"芦溪镇\"]);\ndsy.add(\"0_14_6\",[\"章贡区\",\"瑞金市\",\"南康市\",\"赣县\",\"梅林镇\",\"信丰县\",\"嘉定镇\",\"大余县\",\"南安镇\",\"上犹县\",\"东山镇\",\"崇义县\",\"横水镇\",\"安远县\",\"欣山镇\",\"龙南县\",\"龙南镇\",\"定南县\",\"历市镇\",\"全南县\",\"城厢镇\",\"宁都县\",\"梅江镇\",\"于都县\",\"贡江镇\",\"兴国县\",\"潋江镇\",\"会昌县\",\"文武坝镇\",\"寻乌县\",\"长宁镇\",\"石城县\",\"琴江镇\"]);\ndsy.add(\"0_14_7\",[\"信州区\",\"德兴市\",\"上饶县\",\"旭日镇\",\"广丰县\",\"永丰镇\",\"玉山县\",\"冰溪镇\",\"铅山县\",\"河口镇\",\"横峰县\",\"岑阳镇\",\"弋阳县\",\"弋江镇\",\"余干县\",\"玉亭镇\",\"鄱阳县\",\"鄱阳镇\",\"万年县\",\"陈营镇\",\"婺源县\",\"紫阳镇\"]);\ndsy.add(\"0_14_8\",[\"临川区\",\"南城县\",\"建昌镇\",\"黎川县\",\"日峰镇\",\"南丰县\",\"琴城镇\",\"崇仁县\",\"巴山镇\",\"乐安县\",\"鳌溪镇\",\"宜黄县\",\"凤冈镇\",\"金溪县\",\"秀谷镇\",\"资溪县\",\"鹤城镇\",\"东乡县\",\"孝岗镇\",\"广昌县\",\"旴江镇\"]);\ndsy.add(\"0_14_9\",[\"袁州区\",\"丰城市\",\"樟树市\",\"高安市\",\"奉新县\",\"冯川镇\",\"万载县\",\"上高县\",\"宜丰县\",\"新昌镇\",\"靖安县\",\"双溪镇\",\"铜鼓县\",\"永宁镇\"]);\ndsy.add(\"0_14_10\",[\"吉州区\",\"青原区\",\"井冈山市\",\"厦坪镇\",\"吉安县\",\"敦厚镇\",\"吉水县\",\"文峰镇\",\"峡江县\",\"水边镇\",\"新干县\",\"金川镇\",\"永丰县\",\"恩江镇\",\"泰和县\",\"澄江镇\",\"遂川县\",\"泉江镇\",\"万安县\",\"芙蓉镇\",\"安福县\",\"平都镇\",\"永新县\",\"禾川镇\"]);\ndsy.add(\"0_14\",[\"南昌市\",\"九江市\",\"景德镇市\",\"鹰潭市\",\"新余市\",\"萍乡市\",\"赣州市\",\"上饶市\",\"抚州市\",\"宜春市\",\"吉安市\"]);\ndsy.add(\"0_15_0\",[\"市中区\",\"历下区\",\"槐荫区\",\"天桥区\",\"历城区\",\"长清区\",\"章丘市\",\"平阴县\",\"平阴镇\",\"济阳县\",\"济阳镇\",\"商河县\"]);\ndsy.add(\"0_15_1\",[\"市南区\",\"市北区\",\"四方区\",\"黄岛区\",\"崂山区\",\"城阳区\",\"李沧区\",\"胶州市\",\"即墨市\",\"平度市\",\"胶南市\",\"莱西市\"]);\ndsy.add(\"0_15_2\",[\"东昌府区\",\"临清市\",\"阳谷县\",\"莘县\",\"茌平县\",\"东阿县\",\"冠县\",\"冠城镇\",\"高唐县\"]);\ndsy.add(\"0_15_3\",[\"德城区\",\"乐陵市\",\"禹城市\",\"陵县\",\"陵城镇\",\"平原县\",\"夏津县\",\"夏津镇\",\"武城县\",\"武城镇\",\"齐河县\",\"晏城镇\",\"临邑县\",\"宁津县\",\"宁津镇\",\"庆云县\",\"庆云镇\"]);\ndsy.add(\"0_15_4\",[\"东营区\",\"河口区\",\"垦利县\",\"垦利镇\",\"利津县\",\"利津镇\",\"广饶县\",\"广饶镇\"]);\ndsy.add(\"0_15_5\",[\"张店区\",\"淄川区\",\"博山区\",\"临淄区\",\"周村区\",\"桓台县\",\"索镇\",\"高青县\",\"田镇\",\"沂源县\",\"南麻镇\"]);\ndsy.add(\"0_15_6\",[\"潍城区\",\"寒亭区\",\"坊子区\",\"奎文区\",\"安丘市\",\"昌邑市\",\"高密市\",\"青州市\",\"诸城市\",\"寿光市\",\"临朐县\",\"昌乐县\"]);\ndsy.add(\"0_15_7\",[\"莱山区\",\"芝罘区\",\"福山区\",\"牟平区\",\"栖霞市\",\"海阳市\",\"龙口市\",\"莱阳市\",\"莱州市\",\"蓬莱市\",\"招远市\",\"长岛县\",\"南长山镇\"]);\ndsy.add(\"0_15_8\",[\"环翠区\",\"荣成市\",\"乳山市\",\"文登市\"]);\ndsy.add(\"0_15_9\",[\"东港区\",\"岚山区\",\"五莲县\",\"洪凝镇\",\"莒县\",\"城阳镇\"]);\ndsy.add(\"0_15_10\",[\"兰山区\",\"罗庄区\",\"河东区\",\"郯城县\",\"郯城镇\",\"苍山县\",\"卞庄镇\",\"莒南县\",\"十字路镇\",\"沂水县\",\"沂水镇\",\"蒙阴县\",\"蒙阴镇\",\"平邑县\",\"平邑镇\",\"费县\",\"费城镇\",\"沂南县\",\"界湖镇\",\"临沭县\",\"临沭镇\"]);\ndsy.add(\"0_15_11\",[\"薛城区\",\"市中区\",\"峄城区\",\"台儿庄区\",\"山亭区\",\"滕州市\"]);\ndsy.add(\"0_15_12\",[\"市中区\",\"任城区\",\"曲阜市\",\"兖州市\",\"邹城市\",\"微山县\",\"鱼台县\",\"谷亭镇\",\"金乡县\",\"金乡镇\",\"嘉祥县\",\"嘉祥镇\",\"汶上县\",\"汶上镇\",\"泗水县\",\"梁山县\",\"梁山镇\"]);\ndsy.add(\"0_15_13\",[\"泰山区\",\"岱岳区\",\"新泰市\",\"肥城市\",\"宁阳县\",\"宁阳镇\",\"东平县\",\"东平镇\"]);\ndsy.add(\"0_15_14\",[\"莱城区\",\"钢城区\"]);\ndsy.add(\"0_15_15\",[\"滨城区\",\"惠民县\",\"惠民镇\",\"阳信县\",\"阳信镇\",\"无棣县\",\"无棣镇\",\"沾化县\",\"富国镇\",\"博兴县\",\"博兴镇\",\"邹平县\"]);\ndsy.add(\"0_15_16\",[\"牡丹区\",\"曹县\",\"曹城镇\",\"定陶县\",\"定陶镇\",\"成武县\",\"成武镇\",\"单县\",\"单城镇\",\"巨野县\",\"巨野镇\",\"郓城县\",\"郓城镇\",\"鄄城县\",\"鄄城镇\",\"东明县\",\"城关镇\"]);\ndsy.add(\"0_15\",[\"济南市\",\"青岛市\",\"聊城市\",\"德州市\",\"东营市\",\"淄博市\",\"潍坊市\",\"烟台市\",\"威海市\",\"日照市\",\"临沂市\",\"枣庄市\",\"济宁市\",\"泰安市\",\"莱芜市\",\"滨州市\",\"菏泽市\"]);\ndsy.add(\"0_16_0\",[\"中原区\",\"二七区\",\"管城回族区\",\"金水区\",\"上街区\",\"惠济区\",\"新郑市\",\"登封市\",\"新密市\",\"巩义市\",\"荥阳市\",\"中牟县\",\"城关镇\"]);\ndsy.add(\"0_16_1\",[\"鼓楼区\",\"龙亭区\",\"顺河回族区\",\"禹王台区\",\"金明区\",\"杞县\",\"城关镇\",\"通许县\",\"城关镇\",\"尉氏县\",\"城关镇\",\"开封县\",\"城关镇\",\"兰考县\",\"城关镇\"]);\ndsy.add(\"0_16_2\",[\"湖滨区\",\"义马市\",\"灵宝市\",\"渑池县\",\"城关镇\",\"陕县\",\"大营镇\",\"卢氏县\",\"城关镇\"]);\ndsy.add(\"0_16_3\",[\"西工区\",\"老城区\",\"瀍河回族区\",\"涧西区\",\"吉利区\",\"洛龙区\",\"偃师市\",\"孟津县\",\"城关镇\",\"新安县\",\"城关镇\",\"栾川县\",\"城关镇\",\"嵩县\",\"城关镇\",\"汝阳县\",\"城关镇\",\"宜阳县\",\"城关镇\",\"洛宁县\",\"城关镇\",\"伊川县\",\"城关镇\"]);\ndsy.add(\"0_16_4\",[\"解放区\",\"山阳区\",\"中站区\",\"马村区\",\"孟州市\",\"沁阳市\",\"修武县\",\"城关镇\",\"博爱县\",\"清化镇\",\"武陟县\",\"木城镇\",\"温县\",\"温泉镇\"]);\ndsy.add(\"0_16_5\",[\"卫滨区\",\"红旗区\",\"凤泉区\",\"牧野区\",\"卫辉市\",\"辉县市\",\"新乡县\",\"新乡市红旗区\",\"获嘉县\",\"城关镇\",\"原阳县\",\"城关镇\",\"延津县\",\"城关镇\",\"封丘县\",\"城关镇\",\"长垣县\",\"城关镇\"]);\ndsy.add(\"0_16_6\",[\"淇滨区\",\"山城区\",\"鹤山区\",\"浚县\",\"城关镇\",\"淇县\",\"朝歌镇\"]);\ndsy.add(\"0_16_7\",[\"北关区\",\"文峰区\",\"殷都区\",\"龙安区\",\"林州市\",\"安阳县\",\"安阳市北关区\",\"汤阴县\",\"城关镇\",\"滑县\",\"道口镇\",\"内黄县\",\"城关镇\"]);\ndsy.add(\"0_16_8\",[\"华龙区\",\"清丰县\",\"城关镇\",\"南乐县\",\"城关镇\",\"范县\",\"城关镇\",\"台前县\",\"城关镇\",\"濮阳县\",\"城关镇\"]);\ndsy.add(\"0_16_9\",[\"梁园区\",\"睢阳区\",\"永城市\",\"虞城县\",\"城关镇\",\"民权县\",\"城关镇\",\"宁陵县\",\"城关镇\",\"睢县\",\"城关镇\",\"夏邑县\",\"城关镇\",\"柘城县\",\"城关镇\"]);\ndsy.add(\"0_16_10\",[\"魏都区\",\"禹州市\",\"长葛市\",\"许昌县\",\"许昌市魏都区\",\"鄢陵县\",\"安陵镇\",\"襄城县\",\"城关镇\"]);\ndsy.add(\"0_16_11\",[\"源汇区\",\"郾城区\",\"召陵区\",\"舞阳县\",\"舞泉镇\",\"临颍县\",\"城关镇\"]);\ndsy.add(\"0_16_12\",[\"新华区\",\"卫东区\",\"湛河区\",\"石龙区\",\"舞钢市\",\"汝州市\",\"宝丰县\",\"城关镇\",\"叶县\",\"昆阳镇\",\"鲁山县\",\"鲁阳镇\",\"郏县\",\"城关镇\"]);\ndsy.add(\"0_16_13\",[\"卧龙区\",\"宛城区\",\"邓州市\",\"南召县\",\"城关镇\",\"方城县\",\"城关镇\",\"西峡县\",\"镇平县\",\"城关镇\",\"内乡县\",\"城关镇\",\"淅川县\",\"社旗县\",\"赊店镇\",\"唐河县\",\"新野县\",\"城关镇\",\"桐柏县\",\"城关镇\"]);\ndsy.add(\"0_16_14\",[\"河区\",\"平桥区\",\"息县\",\"城关镇\",\"淮滨县\",\"城关镇\",\"潢川县\",\"光山县\",\"固始县\",\"城关镇\",\"商城县\",\"城关镇\",\"罗山县\",\"城关镇\",\"新县\",\"新集镇\"]);\ndsy.add(\"0_16_15\",[\"川汇区\",\"项城市\",\"扶沟县\",\"城关镇\",\"西华县\",\"城关镇\",\"商水县\",\"城关镇\",\"太康县\",\"城关镇\",\"鹿邑县\",\"城关镇\",\"郸城县\",\"城关镇\",\"淮阳县\",\"城关镇\",\"沈丘县\",\"槐店镇\"]);\ndsy.add(\"0_16_16\",[\"驿城区\",\"确山县\",\"盘龙镇\",\"泌阳县\",\"泌水镇\",\"遂平县\",\"灈阳镇\",\"西平县\",\"上蔡县\",\"蔡都镇\",\"汝南县\",\"汝宁镇\",\"平舆县\",\"古槐镇\",\"新蔡县\",\"古吕镇\",\"正阳县\",\"真阳镇\"]);\ndsy.add(\"0_16\",[\"郑州市\",\"开封市\",\"三门峡市\",\"洛阳市\",\"焦作市\",\"新乡市\",\"鹤壁市\",\"安阳市\",\"濮阳市\",\"商丘市\",\"许昌市\",\"漯河市\",\"平顶山市\",\"南阳市\",\"信阳市\",\"周口市\",\"驻马店市\",\"济源市\"]);\ndsy.add(\"0_17_0\",[\"江岸区\",\"江汉区\",\"硚口区\",\"汉阳区\",\"武昌区\",\"青山区\",\"洪山区\",\"东西湖区\",\"汉南区\",\"蔡甸区\",\"江夏区\",\"黄陂区\",\"新洲区\"]);\ndsy.add(\"0_17_1\",[\"张湾区\",\"茅箭区\",\"丹江口市\",\"郧县\",\"城关镇\",\"竹山县\",\"城关镇\",\"房县\",\"城关镇\",\"郧西县\",\"城关镇\",\"竹溪县\",\"城关镇\"]);\ndsy.add(\"0_17_2\",[\"襄城区\",\"樊城区\",\"襄阳区\",\"老河口市\",\"枣阳市\",\"宜城市\",\"南漳县\",\"城关镇\",\"谷城县\",\"城关镇\",\"保康县\",\"城关镇\"]);\ndsy.add(\"0_17_3\",[\"东宝区\",\"掇刀区\",\"钟祥市\",\"沙洋县\",\"沙洋镇\",\"京山县\",\"新市镇\"]);\ndsy.add(\"0_17_4\",[\"孝南区\",\"应城市\",\"安陆市\",\"汉川市\",\"孝昌县\",\"花园镇\",\"大悟县\",\"城关镇\",\"云梦县\",\"城关镇\"]);\ndsy.add(\"0_17_5\",[\"黄州区\",\"麻城市\",\"武穴市\",\"红安县\",\"城关镇\",\"罗田县\",\"凤山镇\",\"英山县\",\"温泉镇\",\"浠水县\",\"清泉镇\",\"蕲春县\",\"漕河镇\",\"黄梅县\",\"黄梅镇\",\"团风县\",\"团风镇\"]);\ndsy.add(\"0_17_6\",[\"鄂城区\",\"梁子湖区\",\"华容区\"]);\ndsy.add(\"0_17_7\",[\"黄石港区\",\"西塞山区\",\"下陆区\",\"铁山区\",\"大冶市\",\"阳新县\",\"兴国镇\"]);\ndsy.add(\"0_17_8\",[\"咸安区\",\"赤壁市\",\"嘉鱼县\",\"鱼岳镇\",\"通城县\",\"隽水镇\",\"崇阳县\",\"天城镇\",\"通山县\",\"通羊镇\"]);\ndsy.add(\"0_17_9\",[\"沙市区\",\"荆州区\",\"石首市\",\"洪湖市\",\"松滋市\",\"江陵县\",\"郝穴镇\",\"公安县\",\"斗湖堤镇\",\"监利县\",\"容城镇\"]);\ndsy.add(\"0_17_10\",[\"西陵区\",\"伍家岗区\",\"点军区\",\"猇亭区\",\"夷陵区\",\"枝江市\",\"宜都市\",\"当阳市\",\"远安县\",\"鸣凤镇\",\"兴山县\",\"古夫镇\",\"秭归县\",\"茅坪镇\",\"长阳土家族自治县\",\"龙舟坪镇\",\"五峰土家族自治县\",\"五峰镇\"]);\ndsy.add(\"0_17_11\",[\"曾都区\",\"广水市\"]);\ndsy.add(\"0_17_12\",[\"仙桃市\",\"天门市\",\"潜江市\",\"神农架林区\",\"松柏镇\"]);\ndsy.add(\"0_17_13\",[\"恩施市\",\"利川市\",\"建始县\",\"业州镇\",\"巴东县\",\"信陵镇\",\"宣恩县\",\"珠山镇\",\"咸丰县\",\"高乐山镇\",\"来凤县\",\"翔凤镇\",\"鹤峰县\",\"容美镇\"]);\ndsy.add(\"0_17\",[\"武汉市\",\"十堰市\",\"襄樊市\",\"荆门市\",\"孝感市\",\"黄冈市\",\"鄂州市\",\"黄石市\",\"咸宁市\",\"荆州市\",\"宜昌市\",\"随州市\",\"省直辖县级行政单位\",\"恩施州\"]);\ndsy.add(\"0_18_0\",[\"长沙市\",\"岳麓区\",\"芙蓉区\",\"天心区\",\"开福区\",\"雨花区\",\"浏阳市\",\"长沙县\",\"星沙镇\",\"望城县\",\"高塘岭镇\",\"宁乡县\",\"玉潭镇\"]);\ndsy.add(\"0_18_1\",[\"永定区\",\"武陵源区\",\"慈利县\",\"零阳镇\",\"桑植县\",\"澧源镇\"]);\ndsy.add(\"0_18_2\",[\"武陵区\",\"鼎城区\",\"津市市\",\"安乡县\",\"城关镇\",\"汉寿县\",\"龙阳镇\",\"澧县\",\"澧阳镇\",\"临澧县\",\"安福镇\",\"桃源县\",\"漳江镇\",\"石门县\",\"楚江镇\"]);\ndsy.add(\"0_18_3\",[\"赫山区\",\"资阳区\",\"沅江市\",\"南县\",\"南洲镇\",\"桃江县\",\"桃花江镇\",\"安化县\",\"东坪镇\"]);\ndsy.add(\"0_18_4\",[\"岳阳楼区\",\"君山区\",\"云溪区\",\"汨罗市\",\"临湘市\",\"岳阳县\",\"荣家湾镇\",\"华容县\",\"城关镇\",\"湘阴县\",\"文星镇\",\"平江县\",\"汉昌镇\"]);\ndsy.add(\"0_18_5\",[\"天元区\",\"荷塘区\",\"芦淞区\",\"石峰区\",\"醴陵市\",\"株洲县\",\"渌口镇\",\"攸县\",\"城关镇\",\"茶陵县\",\"城关镇\",\"炎陵县\",\"霞阳镇\"]);\ndsy.add(\"0_18_6\",[\"岳塘区\",\"雨湖区\",\"湘乡市\",\"韶山市\",\"湘潭县\",\"易俗河镇\"]);\ndsy.add(\"0_18_7\",[\"雁峰区\",\"珠晖区\",\"石鼓区\",\"蒸湘区\",\"南岳区\",\"常宁市\",\"耒阳市\",\"衡阳县\",\"西渡镇\",\"衡南县\",\"云集镇\",\"衡山县\",\"开云镇\",\"衡东县\",\"城关镇\",\"祁东县\",\"洪桥镇\"]);\ndsy.add(\"0_18_8\",[\"北湖区\",\"苏仙区\",\"资兴市\",\"桂阳县\",\"城关镇\",\"永兴县\",\"城关镇\",\"宜章县\",\"城关镇\",\"嘉禾县\",\"城关镇\",\"临武县\",\"城关镇\",\"汝城县\",\"城关镇\",\"桂东县\",\"城关镇\",\"安仁县\",\"城关镇\"]);\ndsy.add(\"0_18_9\",[\"冷水滩区\",\"零陵区\",\"东安县\",\"白牙市镇\",\"道县\",\"道江镇\",\"宁远县\",\"舜陵镇\",\"江永县\",\"潇浦镇\",\"蓝山县\",\"塔峰镇\",\"新田县\",\"龙泉镇\",\"双牌县\",\"泷泊镇\",\"祁阳县\",\"浯溪镇\",\"江华瑶族自治县\",\"沱江镇\"]);\ndsy.add(\"0_18_10\",[\"双清区\",\"大祥区\",\"北塔区\",\"武冈市\",\"邵东县\",\"两市镇\",\"邵阳县\",\"塘渡口镇\",\"新邵县\",\"酿溪镇\",\"隆回县\",\"桃洪镇\",\"洞口县\",\"洞口镇\",\"绥宁县\",\"长铺镇\",\"新宁县\",\"金石镇\",\"城步苗族自治县\",\"儒林镇\"]);\ndsy.add(\"0_18_11\",[\"鹤城区\",\"洪江市\",\"沅陵县\",\"沅陵镇\",\"辰溪县\",\"辰阳镇\",\"溆浦县\",\"卢峰镇\",\"中方县\",\"中方镇\",\"会同县\",\"林城镇\",\"麻阳苗族自治县\",\"高村镇\",\"新晃侗族自治县\",\"新晃镇\",\"芷江侗族自治县\",\"芷江镇\",\"靖州苗族侗族自治县\",\"渠阳镇\",\"通道侗族自治县\",\"双江镇\"]);\ndsy.add(\"0_18_12\",[\"娄星区\",\"冷水江市\",\"涟源市\",\"双峰县\",\"永丰镇\",\"新化县\",\"上梅镇\"]);\ndsy.add(\"0_18_13\",[\"吉首市\",\"泸溪县\",\"白沙镇\",\"凤凰县\",\"沱江镇\",\"花垣县\",\"花垣镇\",\"保靖县\",\"迁陵镇\",\"古丈县\",\"古阳镇\",\"永顺县\",\"灵溪镇\",\"龙山县\"]);\ndsy.add(\"0_18\",[\"长沙市\",\"张家界市\",\"常德市\",\"益阳市\",\"岳阳市\",\"株洲市\",\"湘潭市\",\"衡阳市\",\"郴州市\",\"永州市\",\"邵阳市\",\"怀化市\",\"娄底市\",\"湘西州\"]);\ndsy.add(\"0_19_0\",[\"越秀区\",\"荔湾区\",\"海珠区\",\"天河区\",\"白云区\",\"黄埔区\",\"番禺区\",\"花都区\",\"南沙区\",\"萝岗区\",\"增城市\",\"从化市\"]);\ndsy.add(\"0_19_1\",[\"福田区\",\"罗湖区\",\"南山区\",\"宝安区\",\"龙岗区\",\"盐田区\"]);\ndsy.add(\"0_19_2\",[\"清城区\",\"英德市\",\"连州市\",\"佛冈县\",\"石角镇\",\"阳山县\",\"阳城镇\",\"清新县\",\"太和镇\",\"连山壮族瑶族自治县\",\"吉田镇\",\"连南瑶族自治县\",\"三江镇\"]);\ndsy.add(\"0_19_3\",[\"浈江区\",\"武江区\",\"曲江区\",\"乐昌市\",\"南雄市\",\"始兴县\",\"太平镇\",\"仁化县\",\"仁化镇\",\"翁源县\",\"龙仙镇\",\"新丰县\",\"乳源瑶族自治县\",\"乳城镇\"]);\ndsy.add(\"0_19_4\",[\"源城区\",\"紫金县\",\"紫城镇\",\"龙川县\",\"老隆镇\",\"连平县\",\"元善镇\",\"和平县\",\"阳明镇\",\"东源县\",\"仙塘镇\"]);\ndsy.add(\"0_19_5\",[\"梅江区\",\"兴宁市\",\"梅县\",\"程江镇\",\"大埔县\",\"湖寮镇\",\"丰顺县\",\"汤坑镇\",\"五华县\",\"水寨镇\",\"平远县\",\"大柘镇\",\"蕉岭县\",\"蕉城镇\"]);\ndsy.add(\"0_19_6\",[\"湘桥区\",\"潮安县\",\"庵埠镇\",\"饶平县\",\"黄冈镇\"]);\ndsy.add(\"0_19_7\",[\"金平区\",\"濠江区\",\"龙湖区\",\"潮阳区\",\"潮南区\",\"澄海区\",\"南澳县\",\"后宅镇\"]);\ndsy.add(\"0_19_8\",[\"榕城区\",\"普宁市\",\"揭东县\",\"曲溪镇\",\"揭西县\",\"河婆镇\",\"惠来县\",\"惠城镇\"]);\ndsy.add(\"0_19_9\",[\"城区\",\"陆丰市\",\"海丰县\",\"海城镇\",\"陆河县\",\"河田镇\"]);\ndsy.add(\"0_19_10\",[\"惠城区\",\"惠阳区\",\"博罗县\",\"罗阳镇\",\"惠东县\",\"龙门县\"]);\ndsy.add(\"0_19_12\",[\"香洲区\",\"斗门区\",\"金湾区\"]);\ndsy.add(\"0_19_14\",[\"江海区\",\"蓬江区\",\"新会区\",\"恩平市\",\"台山市\",\"开平市\",\"鹤山市\"]);\ndsy.add(\"0_19_15\",[\"禅城区\",\"南海区\",\"顺德区\",\"三水区\",\"高明区\"]);\ndsy.add(\"0_19_16\",[\"端州区\",\"鼎湖区\",\"高要市\",\"四会市\",\"广宁县\",\"南街镇\",\"怀集县\",\"怀城镇\",\"封开县\",\"江口镇\",\"德庆县\"]);\ndsy.add(\"0_19_17\",[\"云城区\",\"罗定市\",\"云安县\",\"六都镇\",\"新兴县\",\"新城镇\",\"郁南县\",\"都城镇\"]);\ndsy.add(\"0_19_18\",[\"江城区\",\"阳春市\",\"阳西县\",\"织镇\",\"阳东县\",\"东城镇\"]);\ndsy.add(\"0_19_19\",[\"茂南区\",\"茂港区\",\"化州市\",\"信宜市\",\"高州市\",\"电白县\",\"水东镇\"]);\ndsy.add(\"0_19_20\",[\"赤坎区\",\"霞山区\",\"坡头区\",\"麻章区\",\"吴川市\",\"廉江市\",\"雷州市\",\"遂溪县\",\"遂城镇\",\"徐闻县\",\"撤销广州市东山区\",\"芳村区\",\"设立广州市南沙区\",\"萝岗区\"]);\ndsy.add(\"0_19\",[\"广州市\",\"深圳市\",\"清远市\",\"韶关市\",\"河源市\",\"梅州市\",\"潮州市\",\"汕头市\",\"揭阳市\",\"汕尾市\",\"惠州市\",\"东莞市\",\"珠海市\",\"中山市\",\"江门市\",\"佛山市\",\"肇庆市\",\"云浮市\",\"阳江市\",\"茂名市\",\"湛江市\"]);\ndsy.add(\"0_20_0\",[\"青秀区\",\"兴宁区\",\"江南区\",\"西乡塘区\",\"良庆区\",\"邕宁区\",\"武鸣县\",\"横县\",\"宾阳县\",\"上林县\",\"隆安县\",\"马山县\"]);\ndsy.add(\"0_20_1\",[\"象山区\",\"叠彩区\",\"秀峰区\",\"七星区\",\"雁山区\",\"阳朔县\",\"阳朔镇\",\"临桂县\",\"临桂镇\",\"灵川县\",\"灵川镇\",\"全州县\",\"全州镇\",\"兴安县\",\"兴安镇\",\"永福县\",\"永福镇\",\"灌阳县\",\"灌阳镇\",\"资源县\",\"资源镇\",\"平乐县\",\"平乐镇\",\"荔浦县\",\"荔城镇\",\"龙胜各族自治县\",\"龙胜镇\",\"恭城瑶族自治县\",\"恭城镇\"]);\ndsy.add(\"0_20_2\",[\"城中区\",\"鱼峰区\",\"柳南区\",\"柳北区\",\"柳江县\",\"拉堡镇\",\"柳城县\",\"大埔镇\",\"鹿寨县\",\"鹿寨镇\",\"融安县\",\"长安镇\",\"三江侗族自治县\",\"古宜镇\",\"融水苗族自治县\",\"融水镇\"]);\ndsy.add(\"0_20_3\",[\"万秀区\",\"蝶山区\",\"长洲区\",\"岑溪市\",\"苍梧县\",\"龙圩镇\",\"藤县\",\"藤州镇\",\"蒙山县\",\"蒙山镇\"]);\ndsy.add(\"0_20_4\",[\"港北区\",\"港南区\",\"覃塘区\",\"桂平市\",\"平南县\",\"平南镇\"]);\ndsy.add(\"0_20_5\",[\"玉州区\",\"北流市\",\"兴业县\",\"石南镇\",\"容县\",\"容州镇\",\"陆川县\",\"陆城镇\",\"博白县\",\"博白镇\"]);\ndsy.add(\"0_20_6\",[\"钦南区\",\"钦北区\",\"灵山县\",\"灵城镇\",\"浦北县\",\"小江镇\"]);\ndsy.add(\"0_20_7\",[\"海城区\",\"银海区\",\"铁山港区\",\"合浦县\",\"廉州镇\"]);\ndsy.add(\"0_20_8\",[\"港口区\",\"防城区\",\"东兴市\",\"上思县\",\"思阳镇\"]);\ndsy.add(\"0_20_9\",[\"江州区\",\"凭祥市\",\"扶绥县\",\"新宁镇\",\"大新县\",\"桃城镇\",\"天等县\",\"天等镇\",\"宁明县\",\"城中镇\",\"龙州县\",\"龙州镇\"]);\ndsy.add(\"0_20_10\",[\"右江区\",\"田阳县\",\"田州镇\",\"田东县\",\"平马镇\",\"平果县\",\"马头镇\",\"德保县\",\"城关镇\",\"靖西县\",\"新靖镇\",\"那坡县\",\"城厢镇\",\"凌云县\",\"泗城镇\",\"乐业县\",\"同乐镇\",\"西林县\",\"八达镇\",\"田林县\",\"乐里镇\",\"隆林各族自治县\",\"新州镇\"]);\ndsy.add(\"0_20_11\",[\"金城江区\",\"宜州市\",\"南丹县\",\"城关镇\",\"天峨县\",\"六排镇\",\"凤山县\",\"凤城镇\",\"东兰县\",\"东兰镇\",\"巴马瑶族自治县\",\"巴马镇\",\"都安瑶族自治县\",\"安阳镇\",\"大化瑶族自治县\",\"大化镇\",\"罗城仫佬族自治县\",\"东门镇\",\"环江毛南族自治县\",\"思恩镇\"]);\ndsy.add(\"0_20_12\",[\"兴宾区\",\"合山市\",\"象州县\",\"象州镇\",\"武宣县\",\"武宣镇\",\"忻城县\",\"城关镇\",\"金秀瑶族自治县\",\"金秀镇\"]);\ndsy.add(\"0_20_13\",[\"八步区\",\"昭平县\",\"昭平镇\",\"钟山县\",\"钟山镇\",\"富川瑶族自治县\",\"富阳镇\"]);\ndsy.add(\"0_20\",[\"南宁市\",\"桂林市\",\"柳州市\",\"梧州市\",\"贵港市\",\"玉林市\",\"钦州市\",\"北海市\",\"防城港市\",\"崇左市\",\"百色市\",\"河池市\",\"来宾市\",\"贺州市\"]);\ndsy.add(\"0_21_0\",[\"龙华区\",\"秀英区\",\"琼山区\",\"美兰区\"]);\ndsy.add(\"0_21_2\",[\"文昌市\",\"琼海市\",\"万宁市\",\"五指山市\",\"东方市\",\"儋州市\",\"临高县\",\"临城镇\",\"澄迈县\",\"金江镇\",\"定安县\",\"定城镇\",\"屯昌县\",\"屯城镇\",\"昌江黎族自治县\",\"石碌镇\",\"白沙黎族自治县\",\"牙叉镇\",\"琼中黎族苗族自治县\",\"营根镇\",\"陵水黎族自治县\",\"椰林镇\",\"保亭黎族苗族自治县\",\"保城镇\",\"乐东黎族自治县\",\"抱由镇\"]);\ndsy.add(\"0_21\",[\"海口市\",\"三亚市\",\"省直辖行政单位\"]);\ndsy.add(\"0_22_0\",[\"青羊区\",\"锦江区\",\"金牛区\",\"武侯区\",\"成华区\",\"龙泉驿区\",\"青白江区\",\"新都区\",\"温江区\",\"都江堰市\",\"彭州市\",\"邛崃市\",\"崇州市\",\"金堂县\",\"赵镇\",\"双流县\",\"郫县\",\"郫筒镇\",\"大邑县\",\"晋原镇\",\"蒲江县\",\"鹤山镇\",\"新津县\",\"五津镇\"]);\ndsy.add(\"0_22_1\",[\"市中区\",\"元坝区\",\"朝天区\",\"旺苍县\",\"东河镇\",\"青川县\",\"乔庄镇\",\"剑阁县\",\"下寺镇\",\"苍溪县\",\"陵江镇\"]);\ndsy.add(\"0_22_2\",[\"涪城区\",\"游仙区\",\"江油市\",\"三台县\",\"潼川镇\",\"盐亭县\",\"云溪镇\",\"安县\",\"花荄镇\",\"梓潼县\",\"文昌镇\",\"北川羌族自治县\",\"曲山镇\",\"平武县\",\"龙安镇\"]);\ndsy.add(\"0_22_3\",[\"旌阳区\",\"什邡市\",\"广汉市\",\"绵竹市\",\"罗江县\",\"罗江镇\",\"中江县\",\"凯江镇\"]);\ndsy.add(\"0_22_4\",[\"顺庆区\",\"高坪区\",\"嘉陵区\",\"阆中市\",\"南部县\",\"南隆镇\",\"营山县\",\"朗池镇\",\"蓬安县\",\"周口镇\",\"仪陇县\",\"新政镇\",\"西充县\",\"晋城镇\"]);\ndsy.add(\"0_22_5\",[\"广安区\",\"华蓥市\",\"岳池县\",\"九龙镇\",\"武胜县\",\"沿口镇\",\"邻水县\",\"鼎屏镇\"]);\ndsy.add(\"0_22_6\",[\"船山区\",\"安居区\",\"蓬溪县\",\"赤城镇\",\"射洪县\",\"太和镇\",\"大英县\",\"蓬莱镇\"]);\ndsy.add(\"0_22_7\",[\"市中区\",\"东兴区\",\"威远县\",\"严陵镇\",\"资中县\",\"重龙镇\",\"隆昌县\",\"金鹅镇\"]);\ndsy.add(\"0_22_8\",[\"市中区\",\"沙湾区\",\"五通桥区\",\"金口河区\",\"峨眉山市\",\"犍为县\",\"玉津镇\",\"井研县\",\"研城镇\",\"夹江县\",\"漹城镇\",\"沐川县\",\"沐溪镇\",\"峨边彝族自治县\",\"沙坪镇\",\"马边彝族自治县\",\"民建镇\"]);\ndsy.add(\"0_22_9\",[\"自流井区\",\"大安区\",\"贡井区\",\"沿滩区\",\"荣县\",\"旭阳镇\",\"富顺县\",\"富世镇\"]);\ndsy.add(\"0_22_10\",[\"江阳区\",\"纳溪区\",\"龙马潭区\",\"泸县\",\"福集镇\",\"合江县\",\"合江镇\",\"叙永县\",\"叙永镇\",\"古蔺县\",\"古蔺镇\"]);\ndsy.add(\"0_22_11\",[\"翠屏区\",\"宜宾县\",\"柏溪镇\",\"南溪县\",\"南溪镇\",\"江安县\",\"江安镇\",\"长宁县\",\"长宁镇\",\"高县\",\"庆符镇\",\"筠连县\",\"筠连镇\",\"珙县\",\"巡场镇\",\"兴文县\",\"中城镇\",\"屏山县\",\"屏山镇\"]);\ndsy.add(\"0_22_12\",[\"东区\",\"西区\",\"仁和区\",\"米易县\",\"攀莲镇\",\"盐边县\",\"桐子林镇\"]);\ndsy.add(\"0_22_13\",[\"巴州区\",\"通江县\",\"诺江镇\",\"南江县\",\"南江镇\",\"平昌县\",\"江口镇\"]);\ndsy.add(\"0_22_14\",[\"通川区\",\"万源市\",\"达县\",\"南外镇\",\"宣汉县\",\"东乡镇\",\"开江县\",\"新宁镇\",\"大竹县\",\"竹阳镇\",\"渠县\",\"渠江镇\"]);\ndsy.add(\"0_22_15\",[\"雁江区\",\"简阳市\",\"乐至县\",\"天池镇\",\"安岳县\",\"岳阳镇\"]);\ndsy.add(\"0_22_16\",[\"东坡区\",\"仁寿县\",\"文林镇\",\"彭山县\",\"凤鸣镇\",\"洪雅县\",\"洪川镇\",\"丹棱县\",\"丹棱镇\",\"青神县\",\"城厢镇\"]);\ndsy.add(\"0_22_17\",[\"雨城区\",\"名山县\",\"蒙阳镇\",\"荥经县\",\"严道镇\",\"汉源县\",\"富林镇\",\"石棉县\",\"新棉镇\",\"天全县\",\"城厢镇\",\"芦山县\",\"芦阳镇\",\"宝兴县\",\"穆坪镇\"]);\ndsy.add(\"0_22_18\",[\"马尔康县\",\"马尔康镇\",\"汶川县\",\"威州镇\",\"理县\",\"杂谷脑镇\",\"茂县\",\"凤仪镇\",\"松潘县\",\"进安镇\",\"九寨沟县\",\"永乐镇\",\"金川县\",\"金川镇\",\"小金县\",\"美兴镇\",\"黑水县\",\"芦花镇\",\"壤塘县\",\"壤柯镇\",\"阿坝县\",\"阿坝镇\",\"若尔盖县\",\"达扎寺镇\",\"红原县\",\"邛溪镇\"]);\ndsy.add(\"0_22_19\",[\"康定县\",\"炉城镇\",\"泸定县\",\"泸桥镇\",\"丹巴县\",\"章谷镇\",\"九龙县\",\"呷尔镇\",\"雅江县\",\"河口镇\",\"道孚县\",\"鲜水镇\",\"炉霍县\",\"新都镇\",\"甘孜县\",\"甘孜镇\",\"新龙县\",\"茹龙镇\",\"德格县\",\"更庆镇\",\"白玉县\",\"建设镇\",\"石渠县\",\"尼呷镇\",\"色达县\",\"色柯镇\",\"理塘县\",\"高城镇\",\"巴塘县\",\"夏邛镇\",\"乡城县\",\"桑披镇\",\"稻城县\",\"金珠镇\",\"得荣县\",\"松麦镇\"]);\ndsy.add(\"0_22_20\",[\"西昌市\",\"盐源县\",\"盐井镇\",\"德昌县\",\"德州镇\",\"会理县\",\"城关镇\",\"会东县\",\"会东镇\",\"宁南县\",\"披砂镇\",\"普格县\",\"普基镇\",\"布拖县\",\"特木里镇\",\"金阳县\",\"天地坝镇\",\"昭觉县\",\"新城镇\",\"喜德县\",\"光明镇\",\"冕宁县\",\"城厢镇\",\"越西县\",\"越城镇\",\"甘洛县\",\"新市坝镇\",\"美姑县\",\"巴普镇\",\"雷波县\",\"锦城镇\",\"木里藏族自治县\",\"乔瓦镇\"]);\ndsy.add(\"0_22\",[\"成都市\",\"广元市\",\"绵阳市\",\"德阳市\",\"南充市\",\"广安市\",\"遂宁市\",\"内江市\",\"乐山市\",\"自贡市\",\"泸州市\",\"宜宾市\",\"攀枝花市\",\"巴中市\",\"达州市\",\"资阳市\",\"眉山市\",\"雅安市\",\"阿坝州\",\"甘孜州\",\"凉山州\"]);\ndsy.add(\"0_23_0\",[\"乌当区\",\"南明区\",\"云岩区\",\"花溪区\",\"白云区\",\"小河区\",\"清镇市\",\"开阳县\",\"城关镇\",\"修文县\",\"龙场镇\",\"息烽县\",\"永靖镇\"]);\ndsy.add(\"0_23_1\",[\"钟山区\",\"盘县\",\"红果镇\",\"六枝特区\",\"平寨镇\",\"水城县\"]);\ndsy.add(\"0_23_2\",[\"红花岗区\",\"汇川区\",\"赤水市\",\"仁怀市\",\"遵义县\",\"南白镇\",\"桐梓县\",\"娄山关镇\",\"绥阳县\",\"洋川镇\",\"正安县\",\"凤仪镇\",\"凤冈县\",\"龙泉镇\",\"湄潭县\",\"湄江镇\",\"余庆县\",\"白泥镇\",\"习水县\",\"东皇镇\",\"道真仡佬族苗族自治县\",\"玉溪镇\",\"务川仡佬族苗族自治县\",\"都濡镇\"]);\ndsy.add(\"0_23_3\",[\"西秀区\",\"平坝县\",\"城关镇\",\"普定县\",\"城关镇\",\"关岭布依族苗族自治县\",\"关索镇\",\"镇宁布依族苗族自治县\",\"城关镇\",\"紫云苗族布依族自治县\",\"松山镇\"]);\ndsy.add(\"0_23_4\",[\"毕节市\",\"大方县\",\"大方镇\",\"黔西县\",\"城关镇\",\"金沙县\",\"城关镇\",\"织金县\",\"城关镇\",\"纳雍县\",\"雍熙镇\",\"赫章县\",\"城关镇\",\"威宁彝族回族苗族自治县\",\"草海镇\"]);\ndsy.add(\"0_23_5\",[\"铜仁市\",\"江口县\",\"双江镇\",\"石阡县\",\"汤山镇\",\"思南县\",\"思唐镇\",\"德江县\",\"青龙镇\",\"玉屏侗族自治县\",\"平溪镇\",\"印江土家族苗族自治县\",\"峨岭镇\",\"沿河土家族自治县\",\"和平镇\",\"松桃苗族自治县\",\"蓼皋镇\",\"万山特区\",\"万山镇\"]);\ndsy.add(\"0_23_6\",[\"凯里市\",\"黄平县\",\"新州镇\",\"施秉县\",\"城关镇\",\"三穗县\",\"八弓镇\",\"镇远县\",\"阳镇\",\"岑巩县\",\"思旸镇\",\"天柱县\",\"凤城镇\",\"锦屏县\",\"三江镇\",\"剑河县\",\"革东镇\",\"台江县\",\"台拱镇\",\"黎平县\",\"德凤镇\",\"榕江县\",\"古州镇\",\"从江县\",\"丙妹镇\",\"雷山县\",\"丹江镇\",\"麻江县\",\"杏山镇\",\"丹寨县\",\"龙泉镇\"]);\ndsy.add(\"0_23_7\",[\"都匀市\",\"福泉市\",\"荔波县\",\"玉屏镇\",\"贵定县\",\"城关镇\",\"瓮安县\",\"雍阳镇\",\"独山县\",\"城关镇\",\"平塘县\",\"平湖镇\",\"罗甸县\",\"龙坪镇\",\"长顺县\",\"长寨镇\",\"龙里县\",\"龙山镇\",\"惠水县\",\"和平镇\",\"三都水族自治县\",\"三合镇\"]);\ndsy.add(\"0_23_8\",[\"兴义市\",\"兴仁县\",\"城关镇\",\"普安县\",\"盘水镇\",\"晴隆县\",\"莲城镇\",\"贞丰县\",\"珉谷镇\",\"望谟县\",\"复兴镇\",\"册亨县\",\"者楼镇\",\"安龙县\",\"新安镇\",\"剑河县人民政府驻地由柳川镇迁至革东镇\"]);\ndsy.add(\"0_23\",[\"贵阳市\",\"六盘水市\",\"遵义市\",\"安顺市\",\"毕节地区\",\"铜仁地区\",\"黔东南州\",\"黔南州\",\"黔西南州\"]);\ndsy.add(\"0_24_0\",[\"盘龙区\",\"五华区\",\"官渡区\",\"西山区\",\"东川区\",\"安宁市\",\"呈贡县\",\"龙城镇\",\"晋宁县\",\"昆阳镇\",\"富民县\",\"永定镇\",\"宜良县\",\"匡远镇\",\"嵩明县\",\"嵩阳镇\",\"石林彝族自治县\",\"鹿阜镇\",\"禄劝彝族苗族自治县\",\"屏山镇\",\"寻甸回族彝族自治县\",\"仁德镇\"]);\ndsy.add(\"0_24_1\",[\"麒麟区\",\"宣威市\",\"马龙县\",\"通泉镇\",\"沾益县\",\"西平镇\",\"富源县\",\"中安镇\",\"罗平县\",\"罗雄镇\",\"师宗县\",\"丹凤镇\",\"陆良县\",\"中枢镇\",\"会泽县\",\"金钟镇\"]);\ndsy.add(\"0_24_2\",[\"红塔区\",\"江川县\",\"大街镇\",\"澄江县\",\"凤麓镇\",\"通海县\",\"秀山镇\",\"华宁县\",\"宁州镇\",\"易门县\",\"龙泉镇\",\"峨山彝族自治县\",\"双江镇\",\"新平彝族傣族自治县\",\"桂山镇\",\"元江哈尼族彝族傣族自治县\",\"澧江镇\"]);\ndsy.add(\"0_24_3\",[\"隆阳区\",\"施甸县\",\"甸阳镇\",\"腾冲县\",\"腾越镇\",\"龙陵县\",\"龙山镇\",\"昌宁县\",\"田园镇\"]);\ndsy.add(\"0_24_4\",[\"昭阳区\",\"鲁甸县\",\"文屏镇\",\"巧家县\",\"新华镇\",\"盐津县\",\"盐井镇\",\"大关县\",\"翠华镇\",\"永善县\",\"溪落渡镇\",\"绥江县\",\"中城镇\",\"镇雄县\",\"乌峰镇\",\"彝良县\",\"角奎镇\",\"威信县\",\"扎西镇\",\"水富县\",\"向家坝镇\"]);\ndsy.add(\"0_24_5\",[\"古城区\",\"永胜县\",\"永北镇\",\"华坪县\",\"中心镇\",\"玉龙纳西族自治县\",\"黄山镇\",\"宁蒗彝族自治县\",\"大兴镇\"]);\ndsy.add(\"0_24_6\",[\"翠云区\",\"普洱哈尼族彝族自治县\",\"宁洱镇\",\"墨江哈尼族自治县\",\"联珠镇\",\"景东彝族自治县\",\"锦屏镇\",\"景谷傣族彝族自治县\",\"威远镇\",\"镇沅彝族哈尼族拉祜族自治县\",\"恩乐镇\",\"江城哈尼族彝族自治县\",\"勐烈镇\",\"孟连傣族拉祜族佤族自治县\",\"娜允镇\",\"澜沧拉祜族自治县\",\"勐朗镇\",\"西盟佤族自治县\",\"勐梭镇\"]);\ndsy.add(\"0_24_7\",[\"临翔区\",\"凤庆县\",\"凤山镇\",\"云县\",\"爱华镇\",\"永德县\",\"德党镇\",\"镇康县\",\"南伞镇\",\"双江拉祜族佤族布朗族傣族自治县\",\"勐勐镇\",\"耿马傣族佤族自治县\",\"耿马镇\",\"沧源佤族自治县\",\"勐董镇\"]);\ndsy.add(\"0_24_8\",[\"潞西市\",\"瑞丽市\",\"梁河县\",\"遮岛镇\",\"盈江县\",\"平原镇\",\"陇川县\",\"章凤镇\"]);\ndsy.add(\"0_24_9\",[\"泸水县六库镇\",\"泸水县\",\"六库镇\",\"福贡县\",\"上帕镇\",\"贡山独龙族怒族自治县\",\"茨开镇\",\"兰坪白族普米族自治县\",\"金顶镇\"]);\ndsy.add(\"0_24_10\",[\"香格里拉县\",\"建塘镇\",\"德钦县\",\"升平镇\",\"维西傈僳族自治县\",\"保和镇\"]);\ndsy.add(\"0_24_11\",[\"大理市\",\"祥云县\",\"祥城镇\",\"宾川县\",\"金牛镇\",\"弥渡县\",\"弥城镇\",\"永平县\",\"博南镇\",\"云龙县\",\"诺邓镇\",\"洱源县\",\"茈碧湖镇\",\"剑川县\",\"金华镇\",\"鹤庆县\",\"云鹤镇\",\"漾濞彝族自治县\",\"苍山西镇\",\"南涧彝族自治县\",\"南涧镇\",\"巍山彝族回族自治县\",\"南诏镇\"]);\ndsy.add(\"0_24_12\",[\"楚雄市\",\"双柏县\",\"妥甸镇\",\"牟定县\",\"共和镇\",\"南华县\",\"龙川镇\",\"姚安县\",\"栋川镇\",\"大姚县\",\"金碧镇\",\"永仁县\",\"永定镇\",\"元谋县\",\"元马镇\",\"武定县\",\"狮山镇\",\"禄丰县\",\"金山镇\"]);\ndsy.add(\"0_24_13\",[\"蒙自县\",\"文澜镇\",\"个旧市\",\"开远市\",\"绿春县\",\"大兴镇\",\"建水县\",\"临安镇\",\"石屏县\",\"异龙镇\",\"弥勒县\",\"弥阳镇\",\"泸西县\",\"中枢镇\",\"元阳县\",\"南沙镇\",\"红河县\",\"迤萨镇\",\"金平苗族瑶族傣族自治县\",\"金河镇\",\"河口瑶族自治县\",\"河口镇\",\"屏边苗族自治县\",\"玉屏镇\"]);\ndsy.add(\"0_24_14\",[\"文山县\",\"开化镇\",\"砚山县\",\"江那镇\",\"西畴县\",\"西洒镇\",\"麻栗坡县\",\"麻栗镇\",\"马关县\",\"马白镇\",\"丘北县\",\"锦屏镇\",\"广南县\",\"莲城镇\",\"富宁县\",\"新华镇\"]);\ndsy.add(\"0_24_15\",[\"景洪市\",\"勐海县\",\"勐海镇\",\"勐腊县\",\"勐腊镇\"]);\ndsy.add(\"0_24\",[\"昆明市\",\"曲靖市\",\"玉溪市\",\"保山市\",\"昭通市\",\"丽江市\",\"思茅市\",\"临沧市\",\"德宏州\",\"怒江州\",\"迪庆州\",\"大理州\",\"楚雄州\",\"红河州\",\"文山州\",\"西双版纳州\"]);\ndsy.add(\"0_25_0\",[\"城关区\",\"林周县\",\"甘丹曲果镇\",\"当雄县\",\"当曲卡镇\",\"尼木县\",\"塔荣镇\",\"曲水县\",\"曲水镇\",\"堆龙德庆县\",\"东嘎镇\",\"达孜县\",\"德庆镇\",\"墨竹工卡县\",\"工卡镇\"]);\ndsy.add(\"0_25_1\",[\"那曲县\",\"那曲镇\",\"嘉黎县\",\"阿扎镇\",\"比如县\",\"比如镇\",\"聂荣县\",\"聂荣镇\",\"安多县\",\"帕那镇\",\"申扎县\",\"申扎镇\",\"索县\",\"亚拉镇\",\"班戈县\",\"普保镇\",\"巴青县\",\"拉西镇\",\"尼玛县\",\"尼玛镇\"]);\ndsy.add(\"0_25_2\",[\"昌都县\",\"城关镇\",\"江达县\",\"江达镇\",\"贡觉县\",\"莫洛镇\",\"类乌齐县\",\"桑多镇\",\"丁青县\",\"丁青镇\",\"察雅县\",\"烟多镇\",\"八宿县\",\"白玛镇\",\"左贡县\",\"旺达镇\",\"芒康县\",\"嘎托镇\",\"洛隆县\",\"孜托镇\",\"边坝县\",\"草卡镇\"]);\ndsy.add(\"0_25_3\",[\"林芝县\",\"八一镇\",\"工布江达县\",\"工布江达镇\",\"米林县\",\"米林镇\",\"墨脱县\",\"墨脱镇\",\"波密县\",\"扎木镇\",\"察隅县\",\"竹瓦根镇\",\"朗县\",\"朗镇\"]);\ndsy.add(\"0_25_4\",[\"乃东县\",\"泽当镇\",\"扎囊县\",\"扎塘镇\",\"贡嘎县\",\"吉雄镇\",\"桑日县\",\"桑日镇\",\"琼结县\",\"琼结镇\",\"曲松县\",\"曲松镇\",\"措美县\",\"措美镇\",\"洛扎县\",\"洛扎镇\",\"加查县\",\"安绕镇\",\"隆子县\",\"隆子镇\",\"错那县\",\"错那镇\",\"浪卡子县\",\"浪卡子镇\"]);\ndsy.add(\"0_25_5\",[\"日喀则市\",\"南木林县\",\"南木林镇\",\"江孜县\",\"江孜镇\",\"定日县\",\"协格尔镇\",\"萨迦县\",\"萨迦镇\",\"拉孜县\",\"曲下镇\",\"昂仁县\",\"卡嘎镇\",\"谢通门县\",\"卡嘎镇\",\"白朗县\",\"洛江镇\",\"仁布县\",\"德吉林镇\",\"康马县\",\"康马镇\",\"定结县\",\"江嘎镇\",\"仲巴县\",\"拉让乡\",\"亚东县\",\"下司马镇\",\"吉隆县\",\"宗嘎镇\",\"聂拉木县\",\"聂拉木镇\",\"萨嘎县\",\"加加镇\",\"岗巴县\",\"岗巴镇\"]);\ndsy.add(\"0_25_6\",[\"噶尔县\",\"狮泉河镇\",\"普兰县\",\"普兰镇\",\"札达县\",\"托林镇\",\"日土县\",\"日土镇\",\"革吉县\",\"革吉镇\",\"改则县\",\"改则镇\",\"措勤县\",\"措勤镇\",\"林芝县人民政府驻地由林芝镇迁至八一镇\"]);\ndsy.add(\"0_25\",[\"拉萨市\",\"那曲地区\",\"昌都地区\",\"林芝地区\",\"山南地区\",\"日喀则地区\",\"阿里地区\"]);\ndsy.add(\"0_26_0\",[\"莲湖区\",\"新城区\",\"碑林区\",\"灞桥区\",\"未央区\",\"雁塔区\",\"阎良区\",\"临潼区\",\"长安区\",\"蓝田县\",\"蓝关镇\",\"周至县\",\"二曲镇\",\"户县\",\"甘亭镇\",\"高陵县\",\"鹿苑镇\"]);\ndsy.add(\"0_26_1\",[\"宝塔区\",\"延长县\",\"七里村镇\",\"延川县\",\"延川镇\",\"子长县\",\"瓦窑堡镇\",\"安塞县\",\"真武洞镇\",\"志丹县\",\"保安镇\",\"吴起县\",\"吴旗镇\",\"甘泉县\",\"城关镇\",\"富县\",\"富城镇\",\"洛川县\",\"凤栖镇\",\"宜川县\",\"丹州镇\",\"黄龙县\",\"石堡镇\",\"黄陵县\",\"桥山镇\"]);\ndsy.add(\"0_26_2\",[\"耀州区\",\"王益区\",\"印台区\",\"宜君县\",\"城关镇\"]);\ndsy.add(\"0_26_3\",[\"临渭区\",\"华阴市\",\"韩城市\",\"华县\",\"华州镇\",\"潼关县\",\"城关镇\",\"大荔县\",\"城关镇\",\"蒲城县\",\"城关镇\",\"澄城县\",\"城关镇\",\"白水县\",\"城关镇\",\"合阳县\",\"城关镇\",\"富平县\",\"窦村镇\"]);\ndsy.add(\"0_26_4\",[\"秦都区\",\"杨陵区\",\"渭城区\",\"兴平市\",\"三原县\",\"城关镇\",\"泾阳县\",\"泾干镇\",\"乾县\",\"城关镇\",\"礼泉县\",\"城关镇\",\"永寿县\",\"监军镇\",\"彬县\",\"城关镇\",\"长武县\",\"昭仁镇\",\"旬邑县\",\"城关镇\",\"淳化县\",\"城关镇\",\"武功县\",\"普集镇\"]);\ndsy.add(\"0_26_5\",[\"渭滨区\",\"金台区\",\"陈仓区\",\"凤翔县\",\"城关镇\",\"岐山县\",\"凤鸣镇\",\"扶风县\",\"城关镇\",\"眉县\",\"首善镇\",\"陇县\",\"城关镇\",\"千阳县\",\"城关镇\",\"麟游县\",\"九成宫镇\",\"凤县\",\"双石铺镇\",\"太白县\",\"嘴头镇\"]);\ndsy.add(\"0_26_6\",[\"汉台区\",\"南郑县\",\"城关镇\",\"城固县\",\"博望镇\",\"洋县\",\"洋州镇\",\"西乡县\",\"城关镇\",\"勉县\",\"勉阳镇\",\"宁强县\",\"汉源镇\",\"略阳县\",\"城关镇\",\"镇巴县\",\"泾洋镇\",\"留坝县\",\"城关镇\",\"佛坪县\",\"袁家庄镇\"]);\ndsy.add(\"0_26_7\",[\"榆阳区\",\"神木县\",\"神木镇\",\"府谷县\",\"府谷镇\",\"横山县\",\"横山镇\",\"靖边县\",\"张家畔镇\",\"定边县\",\"定边镇\",\"绥德县\",\"名州镇\",\"米脂县\",\"银州镇\",\"佳县\",\"佳芦镇\",\"吴堡县\",\"宋家川镇\",\"清涧县\",\"宽洲镇\",\"子洲县\",\"双湖峪镇\"]);\ndsy.add(\"0_26_8\",[\"汉滨区\",\"汉阴县\",\"城关镇\",\"石泉县\",\"城关镇\",\"宁陕县\",\"城关镇\",\"紫阳县\",\"城关镇\",\"岚皋县\",\"城关镇\",\"平利县\",\"城关镇\",\"镇坪县\",\"城关镇\",\"旬阳县\",\"城关镇\",\"白河县\",\"城关镇\"]);\ndsy.add(\"0_26_9\",[\"商州区\",\"洛南县\",\"城关镇\",\"丹凤县\",\"龙驹寨镇\",\"商南县\",\"城关镇\",\"山阳县\",\"城关镇\",\"镇安县\",\"永乐镇\",\"柞水县\",\"乾佑镇\"]);\ndsy.add(\"0_26\",[\"西安市\",\"延安市\",\"铜川市\",\"渭南市\",\"咸阳市\",\"宝鸡市\",\"汉中市\",\"榆林市\",\"安康市\",\"商洛市\"]);\ndsy.add(\"0_27_0\",[\"城关区\",\"七里河区\",\"西固区\",\"安宁区\",\"红古区\",\"永登县\",\"城关镇\",\"皋兰县\",\"石洞镇\",\"榆中县\",\"城关镇\"]);\ndsy.add(\"0_27_1\",[\"金昌市\",\"金川区\",\"永昌县\",\"城关镇\"]);\ndsy.add(\"0_27_2\",[\"白银区\",\"平川区\",\"靖远县\",\"乌兰镇\",\"会宁县\",\"会师镇\",\"景泰县\",\"一条山镇\"]);\ndsy.add(\"0_27_3\",[\"秦州区\",\"麦积区\",\"清水县\",\"永清镇\",\"秦安县\",\"兴国镇\",\"甘谷县\",\"大像山镇\",\"武山县\",\"城关镇\",\"张家川回族自治县\",\"张家川镇\"]);\ndsy.add(\"0_27_4\",[\"凉州区\",\"民勤县\",\"城关镇\",\"古浪县\",\"古浪镇\",\"天祝藏族自治县\",\"华藏寺镇\"]);\ndsy.add(\"0_27_5\",[\"肃州区\",\"玉门市\",\"敦煌市\",\"金塔县\",\"金塔镇\",\"安西县\",\"渊泉镇\",\"肃北蒙古族自治县\",\"党城湾镇\",\"阿克塞哈萨克族自治县\",\"红柳湾镇\"]);\ndsy.add(\"0_27_6\",[\"甘州区\",\"民乐县\",\"洪水镇\",\"临泽县\",\"沙河镇\",\"高台县\",\"城关镇\",\"山丹县\",\"清泉镇\",\"肃南裕固族自治县\",\"红湾寺镇\"]);\ndsy.add(\"0_27_7\",[\"西峰区\",\"庆城县\",\"庆城镇\",\"环县\",\"环城镇\",\"华池县\",\"柔远镇\",\"合水县\",\"西华池镇\",\"正宁县\",\"山河镇\",\"宁县\",\"新宁镇\",\"镇原县\",\"城关镇\"]);\ndsy.add(\"0_27_8\",[\"崆峒区\",\"泾川县\",\"城关镇\",\"灵台县\",\"中台镇\",\"崇信县\",\"锦屏镇\",\"华亭县\",\"东华镇\",\"庄浪县\",\"水洛镇\",\"静宁县\",\"城关镇\"]);\ndsy.add(\"0_27_9\",[\"安定区\",\"通渭县\",\"平襄镇\",\"临洮县\",\"洮阳镇\",\"漳县\",\"武阳镇\",\"岷县\",\"岷阳镇\",\"渭源县\",\"清源镇\",\"陇西县\",\"巩昌镇\"]);\ndsy.add(\"0_27_10\",[\"武都区\",\"成县\",\"城关镇\",\"宕昌县\",\"城关镇\",\"康县\",\"文县\",\"城关镇\",\"西和县\",\"汉源镇\",\"礼县\",\"城关镇\",\"两当县\",\"城关镇\",\"徽县\",\"城关镇\"]);\ndsy.add(\"0_27_11\",[\"临夏市\",\"临夏县\",\"韩集镇\",\"康乐县\",\"附城镇\",\"永靖县\",\"刘家峡镇\",\"广河县\",\"城关镇\",\"和政县\",\"城关镇\",\"东乡族自治县\",\"锁南坝镇\",\"积石山保安族东乡族撒拉族自治县\",\"吹麻滩镇\"]);\ndsy.add(\"0_27_12\",[\"合作市\",\"临潭县\",\"城关镇\",\"卓尼县\",\"柳林镇\",\"舟曲县\",\"城关镇\",\"迭部县\",\"电尕镇\",\"玛曲县\",\"尼玛镇\",\"碌曲县\",\"玛艾镇\",\"夏河县\",\"拉卜楞镇\"]);\ndsy.add(\"0_27\",[\"兰州市\",\"嘉峪关市\",\"白银市\",\"天水市\",\"武威市\",\"酒泉市\",\"张掖市\",\"庆阳市\",\"平凉市\",\"定西市\",\"陇南市\",\"临夏州\",\"甘南州\"]);\ndsy.add(\"0_28_0\",[\"城中区\",\"城东区\",\"城西区\",\"城北区\",\"大通回族土族自治县\",\"桥头镇\",\"湟源县\",\"城关镇\",\"湟中县\",\"鲁沙尔镇\"]);\ndsy.add(\"0_28_1\",[\"平安县\",\"平安镇\",\"乐都县\",\"碾伯镇\",\"民和回族土族自治县\",\"川口镇\",\"互助土族自治县\",\"威远镇\",\"化隆回族自治县\",\"巴燕镇\",\"循化撒拉族自治县\",\"积石镇\"]);\ndsy.add(\"0_28_2\",[\"海晏县\",\"三角城镇\",\"祁连县\",\"八宝镇\",\"刚察县\",\"沙柳河镇\",\"门源回族自治县\",\"浩门镇\"]);\ndsy.add(\"0_28_3\",[\"共和县\",\"恰卜恰镇\",\"同德县\",\"尕巴松多镇\",\"贵德县\",\"河阴镇\",\"兴海县\",\"子科滩镇\",\"贵南县\",\"茫曲镇\"]);\ndsy.add(\"0_28_4\",[\"同仁县\",\"隆务镇\",\"尖扎县\",\"马克唐镇\",\"泽库县\",\"泽曲镇\",\"河南蒙古族自治县\",\"优干宁镇\"]);\ndsy.add(\"0_28_5\",[\"玛沁县\",\"大武镇\",\"班玛县\",\"赛来塘镇\",\"甘德县\",\"柯曲镇\",\"达日县\",\"吉迈镇\",\"久治县\",\"智青松多镇\",\"玛多县\",\"黄河乡\"]);\ndsy.add(\"0_28_6\",[\"玉树县\",\"结古镇\",\"杂多县\",\"萨呼腾镇\",\"称多县\",\"称文镇\",\"治多县\",\"加吉博洛镇\",\"囊谦县\",\"香达镇\",\"曲麻莱县\",\"约改镇\"]);\ndsy.add(\"0_28_7\",[\"德令哈市\",\"格尔木市\",\"乌兰县\",\"希里沟镇\",\"都兰县\",\"察汗乌苏镇\",\"天峻县\",\"新源镇\"]);\ndsy.add(\"0_28\",[\"西宁市\",\"海东地区\",\"海北州\",\"海南州\",\"黄南州\",\"果洛州\",\"玉树州\",\"海西州\"]);\ndsy.add(\"0_29_0\",[\"兴庆区\",\"金凤区\",\"西夏区\",\"灵武市\",\"永宁县\",\"杨和镇\",\"贺兰县\",\"习岗镇\"]);\ndsy.add(\"0_29_1\",[\"大武口区\",\"惠农区\",\"平罗县\",\"城关镇\"]);\ndsy.add(\"0_29_2\",[\"利通区\",\"青铜峡市\",\"盐池县\",\"花马池镇\",\"同心县\",\"豫海镇\"]);\ndsy.add(\"0_29_3\",[\"原州区\",\"西吉县\",\"吉强镇\",\"隆德县\",\"城关镇\",\"泾源县\",\"香水镇\",\"彭阳县\",\"白阳镇\"]);\ndsy.add(\"0_29_4\",[\"沙坡头区\",\"中宁县\",\"海原县\"]);\ndsy.add(\"0_29\",[\"银川市\",\"石嘴山市\",\"吴忠市\",\"固原市\",\"中卫市\"]);\ndsy.add(\"0_30_0\",[\"天山区\",\"沙依巴克区\",\"新市区\",\"水磨沟区\",\"头屯河区\",\"达坂城区\",\"东山区\",\"乌鲁木齐县\",\"乌鲁木齐市水磨沟区\"]);\ndsy.add(\"0_30_1\",[\"克拉玛依区\",\"独山子区\",\"白碱滩区\",\"乌尔禾区\"]);\ndsy.add(\"0_30_2\",[\"石河子市\",\"阿拉尔市\",\"图木舒克市\",\"五家渠市\"]);\ndsy.add(\"0_30_3\",[\"喀什市\",\"疏附县\",\"托克扎克镇\",\"疏勒县\",\"疏勒镇\",\"英吉沙县\",\"英吉沙镇\",\"泽普县\",\"泽普镇\",\"莎车县\",\"莎车镇\",\"叶城县\",\"喀格勒克镇\",\"麦盖提县\",\"麦盖提镇\",\"岳普湖县\",\"岳普湖镇\",\"伽师县\",\"巴仁镇\",\"巴楚县\",\"巴楚镇\",\"塔什库尔干塔吉克自治县\",\"塔什库尔干镇\"]);\ndsy.add(\"0_30_4\",[\"阿克苏市\",\"温宿县\",\"温宿镇\",\"库车县\",\"库车镇\",\"沙雅县\",\"沙雅镇\",\"新和县\",\"新和镇\",\"拜城县\",\"拜城镇\",\"乌什县\",\"乌什镇\",\"阿瓦提县\",\"阿瓦提镇\",\"柯坪县\",\"柯坪镇\"]);\ndsy.add(\"0_30_5\",[\"和田市\",\"和田县\",\"墨玉县\",\"喀拉喀什镇\",\"皮山县\",\"固玛镇\",\"洛浦县\",\"洛浦镇\",\"策勒县\",\"策勒镇\",\"于田县\",\"木尕拉镇\",\"民丰县\",\"尼雅镇\"]);\ndsy.add(\"0_30_6\",[\"吐鲁番市\",\"鄯善县\",\"鄯善镇\",\"托克逊县\",\"托克逊镇\"]);\ndsy.add(\"0_30_7\",[\"哈密市\",\"伊吾县\",\"伊吾镇\",\"巴里坤哈萨克自治县\",\"巴里坤镇\"]);\ndsy.add(\"0_30_8\",[\"阿图什市\",\"阿克陶县\",\"阿克陶镇\",\"阿合奇县\",\"阿合奇镇\",\"乌恰县\",\"乌恰镇\"]);\ndsy.add(\"0_30_9\",[\"博乐市\",\"精河县\",\"精河镇\",\"温泉县\",\"博格达尔镇\"]);\ndsy.add(\"0_30_10\",[\"昌吉市\",\"阜康市\",\"米泉市\",\"呼图壁县\",\"呼图壁镇\",\"玛纳斯县\",\"玛纳斯镇\",\"奇台县\",\"奇台镇\",\"吉木萨尔县\",\"吉木萨尔镇\",\"木垒哈萨克自治县\",\"木垒镇\"]);\ndsy.add(\"0_30_11\",[\"库尔勒市\",\"轮台县\",\"轮台镇\",\"尉犁县\",\"尉犁镇\",\"若羌县\",\"若羌镇\",\"且末县\",\"且末镇\",\"和静县\",\"和静镇\",\"和硕县\",\"特吾里克镇\",\"博湖县\",\"博湖镇\",\"焉耆回族自治县\",\"焉耆镇\"]);\ndsy.add(\"0_30_12\",[\"伊宁市\",\"奎屯市\",\"伊宁县\",\"吉里于孜镇\",\"霍城县\",\"水定镇\",\"巩留县\",\"巩留镇\",\"新源县\",\"新源镇\",\"昭苏县\",\"昭苏镇\",\"特克斯县\",\"特克斯镇\",\"尼勒克县\",\"尼勒克镇\",\"察布查尔锡伯自治县\",\"察布查尔镇\"]);\ndsy.add(\"0_30_13\",[\"塔城市\",\"乌苏市\",\"额敏县\",\"额敏镇\",\"沙湾县\",\"三道河子镇\",\"托里县\",\"托里镇\",\"裕民县\",\"哈拉布拉镇\",\"和布克赛尔蒙古自治县\",\"和布克赛尔镇\"]);\ndsy.add(\"0_30_14\",[\"阿勒泰市\",\"布尔津县\",\"布尔津镇\",\"富蕴县\",\"库额尔齐斯镇\",\"福海县\",\"哈巴河县\",\"青河县\",\"吉木乃县\"]);\ndsy.add(\"0_30\",[\"乌鲁木齐市\",\"克拉玛依市\",\"自治区直辖县级行政单位\",\"喀什地区\",\"阿克苏地区\",\"和田地区\",\"吐鲁番地区\",\"哈密地区\",\"克孜勒苏柯州\",\"博尔塔拉州\",\"昌吉州\",\"巴音郭楞州\",\"伊犁州\",\"塔城地区\",\"阿勒泰地区\"]);\ndsy.add(\"0_31_0\",[\"中西区\",\"东区\",\"九龙城区\",\"观塘区\",\"南区\",\"深水埗区\",\"湾仔区\",\"黄大仙区\",\"油尖旺区\",\"离岛区\",\"葵青区\",\"北区\",\"西贡区\",\"沙田区\",\"屯门区\",\"大埔区\",\"荃湾区\",\"元朗区\"]);\ndsy.add(\"0_31\",[\"香港特别行政区\"]);\ndsy.add(\"0_32_0\",[\"澳门特别行政区\"]);\ndsy.add(\"0_32\",[\"澳门特别行政区\"]);\ndsy.add(\"0_33_0\",[\" \"]);\ndsy.add(\"0_33\",[\"台北\",\"高雄\",\"台中\",\"花莲\",\"基隆\",\"嘉义\",\"金门\",\"连江\",\"苗栗\",\"南投\",\"澎湖\",\"屏东\",\"台东\",\"台南\",\"桃园\",\"新竹\",\"宜兰\",\"云林\",\"彰化\"]);\ndsy.add(\"0\",[\"北京市\",\"天津市\",\"上海市\",\"重庆市\",\"河北省\",\"山西省\",\"内蒙古\",\"辽宁省\",\"吉林省\",\"黑龙江省\",\"江苏省\",\"浙江省\",\"安徽省\",\"福建省\",\"江西省\",\"山东省\",\"河南省\",\"湖北省\",\"湖南省\",\"广东省\",\"广西\",\"海南省\",\"四川省\",\"贵州省\",\"云南省\",\"西藏\",\"陕西省\",\"甘肃省\",\"青海省\",\"宁夏\",\"新疆\",\"香港\",\"澳门\",\"台湾省\"]);\n\nvar s=[\"s_province\",\"s_city\",\"s_county\"];//三个select的name\nvar opt0 = [\"省份\",\"地级市\",\"市、县级市\"];//初始值\nfunction _init_area(){  //初始化函数\n\tfor(i=0;i<s.length-1;i++){\n\t  document.getElementById(s[i]).onchange=new Function(\"change(\"+(i+1)+\")\");\n\t}\n\tchange(0);\n}\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/assets/js/config.js",
    "content": "/**\n * Created by huzhihui on 2016/9/30.\n */\n\n/**\n * 全局列表json\n * @type {{}}\n */\nvar TAB_JSON = {\n    list: [\n        {\n            listName: '首页',/*tab名称*/\n            listUrl: 'pages/dashboard.html',/*页面路径*/\n            listUuid: 'uuid-main',/*tab唯一标识*/\n            listIcon: 'am-icon-home',/*左侧显示图标*/\n            listRightIcon: '',/*右侧显示图标*/\n            listNumber: '',/*右侧显示数字数据*/\n            listNumberColor: 'am-badge am-badge-secondary',/*右侧显示数字数据样式*/\n            isHtml: true/*是否是页面，false为折叠tab*/\n        } \n    ]     \n};\n\n$.ajax({  \n    url:\"/permissions/current\",  \n    type:\"get\",  \n    async:false,\n    success:function(data){\n   \t if(!$.isArray(data)){\n   \t\t location.href='/login.html';\n   \t\t return;\n   \t }\n   \t var menu =  TAB_JSON.list ;\n   \t $.each(data, function(i,item){\n   \t\t \n   \t\t \tvar obj ={} ;\n   \t\t \tobj.listName = item.name ;      \n   \t\t \tobj.listUuid = \"uuid-home\"+item.id ;\n           \n   \t\t \tobj.listIcon = item.css ;\n            \n            var href = item.href;\n            if(href != null && href != \"\"){\n                obj.listUrl =  href;\n                \n                \n                \n            }\n            obj.listRightIcon = '' ;\n            obj.listNumber = '';\n            obj.isHtml = true ;\n            \n            //二级菜单\n            var child2 = item.child;\n            if(child2 != null && child2.length > 0){\n            \t\n            \t obj.subList= [] ;\n           \t $.each(child2, function(j,item2){\n           \t\tobj.isHtml = false ;\n           \t\tvar subObj ={} ;\n           \t\tsubObj.listName = item2.name ;      \n           \t\tsubObj.listUuid = \"uuid-home\"+ item2.id ;\n               \n           \t\tsubObj.listIcon = item2.css ;\n                \n                var href = item2.href;\n                if(href != null && href != \"\"){\n                \tsubObj.listUrl =  href;\n                }\n                subObj.listRightIcon = '' ;\n                subObj.listNumber = '';\n                subObj.isHtml = true ;\n                  \n                obj.subList.push(subObj);\n                   \n                  \n           \t });\n           }\n           menu.push(obj);\n       });\n    }\n});"
  },
  {
    "path": "open-layui-web/src/main/view/static/assets/js/iscroll.js",
    "content": "/*! iScroll v5.2.0 ~ (c) 2008-2016 Matteo Spinelli ~ http://cubiq.org/license */\n(function (window, document, Math) {\nvar rAF = window.requestAnimationFrame\t||\n\twindow.webkitRequestAnimationFrame\t||\n\twindow.mozRequestAnimationFrame\t\t||\n\twindow.oRequestAnimationFrame\t\t||\n\twindow.msRequestAnimationFrame\t\t||\n\tfunction (callback) { window.setTimeout(callback, 1000 / 60); };\n\nvar utils = (function () {\n\tvar me = {};\n\n\tvar _elementStyle = document.createElement('div').style;\n\tvar _vendor = (function () {\n\t\tvar vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'],\n\t\t\ttransform,\n\t\t\ti = 0,\n\t\t\tl = vendors.length;\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\ttransform = vendors[i] + 'ransform';\n\t\t\tif ( transform in _elementStyle ) return vendors[i].substr(0, vendors[i].length-1);\n\t\t}\n\n\t\treturn false;\n\t})();\n\n\tfunction _prefixStyle (style) {\n\t\tif ( _vendor === false ) return false;\n\t\tif ( _vendor === '' ) return style;\n\t\treturn _vendor + style.charAt(0).toUpperCase() + style.substr(1);\n\t}\n\n\tme.getTime = Date.now || function getTime () { return new Date().getTime(); };\n\n\tme.extend = function (target, obj) {\n\t\tfor ( var i in obj ) {\n\t\t\ttarget[i] = obj[i];\n\t\t}\n\t};\n\n\tme.addEvent = function (el, type, fn, capture) {\n\t\tel.addEventListener(type, fn, !!capture);\n\t};\n\n\tme.removeEvent = function (el, type, fn, capture) {\n\t\tel.removeEventListener(type, fn, !!capture);\n\t};\n\n\tme.prefixPointerEvent = function (pointerEvent) {\n\t\treturn window.MSPointerEvent ?\n\t\t\t'MSPointer' + pointerEvent.charAt(7).toUpperCase() + pointerEvent.substr(8):\n\t\t\tpointerEvent;\n\t};\n\n\tme.momentum = function (current, start, time, lowerMargin, wrapperSize, deceleration) {\n\t\tvar distance = current - start,\n\t\t\tspeed = Math.abs(distance) / time,\n\t\t\tdestination,\n\t\t\tduration;\n\n\t\tdeceleration = deceleration === undefined ? 0.0006 : deceleration;\n\n\t\tdestination = current + ( speed * speed ) / ( 2 * deceleration ) * ( distance < 0 ? -1 : 1 );\n\t\tduration = speed / deceleration;\n\n\t\tif ( destination < lowerMargin ) {\n\t\t\tdestination = wrapperSize ? lowerMargin - ( wrapperSize / 2.5 * ( speed / 8 ) ) : lowerMargin;\n\t\t\tdistance = Math.abs(destination - current);\n\t\t\tduration = distance / speed;\n\t\t} else if ( destination > 0 ) {\n\t\t\tdestination = wrapperSize ? wrapperSize / 2.5 * ( speed / 8 ) : 0;\n\t\t\tdistance = Math.abs(current) + destination;\n\t\t\tduration = distance / speed;\n\t\t}\n\n\t\treturn {\n\t\t\tdestination: Math.round(destination),\n\t\t\tduration: duration\n\t\t};\n\t};\n\n\tvar _transform = _prefixStyle('transform');\n\n\tme.extend(me, {\n\t\thasTransform: _transform !== false,\n\t\thasPerspective: _prefixStyle('perspective') in _elementStyle,\n\t\thasTouch: 'ontouchstart' in window,\n\t\thasPointer: !!(window.PointerEvent || window.MSPointerEvent), // IE10 is prefixed\n\t\thasTransition: _prefixStyle('transition') in _elementStyle\n\t});\n\n\t/*\n\tThis should find all Android browsers lower than build 535.19 (both stock browser and webview)\n\t- galaxy S2 is ok\n    - 2.3.6 : `AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1`\n    - 4.0.4 : `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`\n   - galaxy S3 is badAndroid (stock brower, webview)\n     `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`\n   - galaxy S4 is badAndroid (stock brower, webview)\n     `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`\n   - galaxy S5 is OK\n     `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)`\n   - galaxy S6 is OK\n     `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)`\n  */\n\tme.isBadAndroid = (function() {\n\t\tvar appVersion = window.navigator.appVersion;\n\t\t// Android browser is not a chrome browser.\n\t\tif (/Android/.test(appVersion) && !(/Chrome\\/\\d/.test(appVersion))) {\n\t\t\tvar safariVersion = appVersion.match(/Safari\\/(\\d+.\\d)/);\n\t\t\tif(safariVersion && typeof safariVersion === \"object\" && safariVersion.length >= 2) {\n\t\t\t\treturn parseFloat(safariVersion[1]) < 535.19;\n\t\t\t} else {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t})();\n\n\tme.extend(me.style = {}, {\n\t\ttransform: _transform,\n\t\ttransitionTimingFunction: _prefixStyle('transitionTimingFunction'),\n\t\ttransitionDuration: _prefixStyle('transitionDuration'),\n\t\ttransitionDelay: _prefixStyle('transitionDelay'),\n\t\ttransformOrigin: _prefixStyle('transformOrigin')\n\t});\n\n\tme.hasClass = function (e, c) {\n\t\tvar re = new RegExp(\"(^|\\\\s)\" + c + \"(\\\\s|$)\");\n\t\treturn re.test(e.className);\n\t};\n\n\tme.addClass = function (e, c) {\n\t\tif ( me.hasClass(e, c) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar newclass = e.className.split(' ');\n\t\tnewclass.push(c);\n\t\te.className = newclass.join(' ');\n\t};\n\n\tme.removeClass = function (e, c) {\n\t\tif ( !me.hasClass(e, c) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar re = new RegExp(\"(^|\\\\s)\" + c + \"(\\\\s|$)\", 'g');\n\t\te.className = e.className.replace(re, ' ');\n\t};\n\n\tme.offset = function (el) {\n\t\tvar left = -el.offsetLeft,\n\t\t\ttop = -el.offsetTop;\n\n\t\t// jshint -W084\n\t\twhile (el = el.offsetParent) {\n\t\t\tleft -= el.offsetLeft;\n\t\t\ttop -= el.offsetTop;\n\t\t}\n\t\t// jshint +W084\n\n\t\treturn {\n\t\t\tleft: left,\n\t\t\ttop: top\n\t\t};\n\t};\n\n\tme.preventDefaultException = function (el, exceptions) {\n\t\tfor ( var i in exceptions ) {\n\t\t\tif ( exceptions[i].test(el[i]) ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t};\n\n\tme.extend(me.eventType = {}, {\n\t\ttouchstart: 1,\n\t\ttouchmove: 1,\n\t\ttouchend: 1,\n\n\t\tmousedown: 2,\n\t\tmousemove: 2,\n\t\tmouseup: 2,\n\n\t\tpointerdown: 3,\n\t\tpointermove: 3,\n\t\tpointerup: 3,\n\n\t\tMSPointerDown: 3,\n\t\tMSPointerMove: 3,\n\t\tMSPointerUp: 3\n\t});\n\n\tme.extend(me.ease = {}, {\n\t\tquadratic: {\n\t\t\tstyle: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',\n\t\t\tfn: function (k) {\n\t\t\t\treturn k * ( 2 - k );\n\t\t\t}\n\t\t},\n\t\tcircular: {\n\t\t\tstyle: 'cubic-bezier(0.1, 0.57, 0.1, 1)',\t// Not properly \"circular\" but this looks better, it should be (0.075, 0.82, 0.165, 1)\n\t\t\tfn: function (k) {\n\t\t\t\treturn Math.sqrt( 1 - ( --k * k ) );\n\t\t\t}\n\t\t},\n\t\tback: {\n\t\t\tstyle: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)',\n\t\t\tfn: function (k) {\n\t\t\t\tvar b = 4;\n\t\t\t\treturn ( k = k - 1 ) * k * ( ( b + 1 ) * k + b ) + 1;\n\t\t\t}\n\t\t},\n\t\tbounce: {\n\t\t\tstyle: '',\n\t\t\tfn: function (k) {\n\t\t\t\tif ( ( k /= 1 ) < ( 1 / 2.75 ) ) {\n\t\t\t\t\treturn 7.5625 * k * k;\n\t\t\t\t} else if ( k < ( 2 / 2.75 ) ) {\n\t\t\t\t\treturn 7.5625 * ( k -= ( 1.5 / 2.75 ) ) * k + 0.75;\n\t\t\t\t} else if ( k < ( 2.5 / 2.75 ) ) {\n\t\t\t\t\treturn 7.5625 * ( k -= ( 2.25 / 2.75 ) ) * k + 0.9375;\n\t\t\t\t} else {\n\t\t\t\t\treturn 7.5625 * ( k -= ( 2.625 / 2.75 ) ) * k + 0.984375;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\telastic: {\n\t\t\tstyle: '',\n\t\t\tfn: function (k) {\n\t\t\t\tvar f = 0.22,\n\t\t\t\t\te = 0.4;\n\n\t\t\t\tif ( k === 0 ) { return 0; }\n\t\t\t\tif ( k == 1 ) { return 1; }\n\n\t\t\t\treturn ( e * Math.pow( 2, - 10 * k ) * Math.sin( ( k - f / 4 ) * ( 2 * Math.PI ) / f ) + 1 );\n\t\t\t}\n\t\t}\n\t});\n\n\tme.tap = function (e, eventName) {\n\t\tvar ev = document.createEvent('Event');\n\t\tev.initEvent(eventName, true, true);\n\t\tev.pageX = e.pageX;\n\t\tev.pageY = e.pageY;\n\t\te.target.dispatchEvent(ev);\n\t};\n\n\tme.click = function (e) {\n\t\tvar target = e.target,\n\t\t\tev;\n\n\t\tif ( !(/(SELECT|INPUT|TEXTAREA)/i).test(target.tagName) ) {\n\t\t\t// https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/initMouseEvent\n\t\t\t// initMouseEvent is deprecated.\n\t\t\tev = document.createEvent(window.MouseEvent ? 'MouseEvents' : 'Event');\n\t\t\tev.initEvent('click', true, true);\n\t\t\tev.view = e.view || window;\n\t\t\tev.detail = 1;\n\t\t\tev.screenX = target.screenX || 0;\n\t\t\tev.screenY = target.screenY || 0;\n\t\t\tev.clientX = target.clientX || 0;\n\t\t\tev.clientY = target.clientY || 0;\n\t\t\tev.ctrlKey = !!e.ctrlKey;\n\t\t\tev.altKey = !!e.altKey;\n\t\t\tev.shiftKey = !!e.shiftKey;\n\t\t\tev.metaKey = !!e.metaKey;\n\t\t\tev.button = 0;\n\t\t\tev.relatedTarget = null;\n\t\t\tev._constructed = true;\n\t\t\ttarget.dispatchEvent(ev);\n\t\t}\n\t};\n\n\treturn me;\n})();\nfunction IScroll (el, options) {\n\tthis.wrapper = typeof el == 'string' ? document.querySelector(el) : el;\n\tthis.scroller = this.wrapper.children[0];\n\tthis.scrollerStyle = this.scroller.style;\t\t// cache style for better performance\n\n\tthis.options = {\n\n\t\tresizeScrollbars: true,\n\n\t\tmouseWheelSpeed: 20,\n\n\t\tsnapThreshold: 0.334,\n\n// INSERT POINT: OPTIONS\n\t\tdisablePointer : !utils.hasPointer,\n\t\tdisableTouch : utils.hasPointer || !utils.hasTouch,\n\t\tdisableMouse : utils.hasPointer || utils.hasTouch,\n\t\tstartX: 0,\n\t\tstartY: 0,\n\t\tscrollY: true,\n\t\tdirectionLockThreshold: 5,\n\t\tmomentum: true,\n\n\t\tbounce: true,\n\t\tbounceTime: 600,\n\t\tbounceEasing: '',\n\n\t\tpreventDefault: true,\n\t\tpreventDefaultException: { tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT)$/ },\n\n\t\tHWCompositing: true,\n\t\tuseTransition: true,\n\t\tuseTransform: true,\n\t\tbindToWrapper: typeof window.onmousedown === \"undefined\"\n\t};\n\n\tfor ( var i in options ) {\n\t\tthis.options[i] = options[i];\n\t}\n\n\t// Normalize options\n\tthis.translateZ = this.options.HWCompositing && utils.hasPerspective ? ' translateZ(0)' : '';\n\n\tthis.options.useTransition = utils.hasTransition && this.options.useTransition;\n\tthis.options.useTransform = utils.hasTransform && this.options.useTransform;\n\n\tthis.options.eventPassthrough = this.options.eventPassthrough === true ? 'vertical' : this.options.eventPassthrough;\n\tthis.options.preventDefault = !this.options.eventPassthrough && this.options.preventDefault;\n\n\t// If you want eventPassthrough I have to lock one of the axes\n\tthis.options.scrollY = this.options.eventPassthrough == 'vertical' ? false : this.options.scrollY;\n\tthis.options.scrollX = this.options.eventPassthrough == 'horizontal' ? false : this.options.scrollX;\n\n\t// With eventPassthrough we also need lockDirection mechanism\n\tthis.options.freeScroll = this.options.freeScroll && !this.options.eventPassthrough;\n\tthis.options.directionLockThreshold = this.options.eventPassthrough ? 0 : this.options.directionLockThreshold;\n\n\tthis.options.bounceEasing = typeof this.options.bounceEasing == 'string' ? utils.ease[this.options.bounceEasing] || utils.ease.circular : this.options.bounceEasing;\n\n\tthis.options.resizePolling = this.options.resizePolling === undefined ? 60 : this.options.resizePolling;\n\n\tif ( this.options.tap === true ) {\n\t\tthis.options.tap = 'tap';\n\t}\n\n\t// https://github.com/cubiq/iscroll/issues/1029\n\tif (!this.options.useTransition && !this.options.useTransform) {\n\t\tif(!(/relative|absolute/i).test(this.scrollerStyle.position)) {\n\t\t\tthis.scrollerStyle.position = \"relative\";\n\t\t}\n\t}\n\n\tif ( this.options.shrinkScrollbars == 'scale' ) {\n\t\tthis.options.useTransition = false;\n\t}\n\n\tthis.options.invertWheelDirection = this.options.invertWheelDirection ? -1 : 1;\n\n// INSERT POINT: NORMALIZATION\n\n\t// Some defaults\n\tthis.x = 0;\n\tthis.y = 0;\n\tthis.directionX = 0;\n\tthis.directionY = 0;\n\tthis._events = {};\n\n// INSERT POINT: DEFAULTS\n\n\tthis._init();\n\tthis.refresh();\n\n\tthis.scrollTo(this.options.startX, this.options.startY);\n\tthis.enable();\n}\n\nIScroll.prototype = {\n\tversion: '5.2.0',\n\n\t_init: function () {\n\t\tthis._initEvents();\n\n\t\tif ( this.options.scrollbars || this.options.indicators ) {\n\t\t\tthis._initIndicators();\n\t\t}\n\n\t\tif ( this.options.mouseWheel ) {\n\t\t\tthis._initWheel();\n\t\t}\n\n\t\tif ( this.options.snap ) {\n\t\t\tthis._initSnap();\n\t\t}\n\n\t\tif ( this.options.keyBindings ) {\n\t\t\tthis._initKeys();\n\t\t}\n\n// INSERT POINT: _init\n\n\t},\n\n\tdestroy: function () {\n\t\tthis._initEvents(true);\n\t\tclearTimeout(this.resizeTimeout);\n \t\tthis.resizeTimeout = null;\n\t\tthis._execEvent('destroy');\n\t},\n\n\t_transitionEnd: function (e) {\n\t\tif ( e.target != this.scroller || !this.isInTransition ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._transitionTime();\n\t\tif ( !this.resetPosition(this.options.bounceTime) ) {\n\t\t\tthis.isInTransition = false;\n\t\t\tthis._execEvent('scrollEnd');\n\t\t}\n\t},\n\n\t_start: function (e) {\n\t\t// React to left mouse button only\n\t\tif ( utils.eventType[e.type] != 1 ) {\n\t\t  // for button property\n\t\t  // http://unixpapa.com/js/mouse.html\n\t\t  var button;\n\t    if (!e.which) {\n\t      /* IE case */\n\t      button = (e.button < 2) ? 0 :\n\t               ((e.button == 4) ? 1 : 2);\n\t    } else {\n\t      /* All others */\n\t      button = e.button;\n\t    }\n\t\t\tif ( button !== 0 ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tif ( !this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( this.options.preventDefault && !utils.isBadAndroid && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) {\n\t\t\te.preventDefault();\n\t\t}\n\n\t\tvar point = e.touches ? e.touches[0] : e,\n\t\t\tpos;\n\n\t\tthis.initiated\t= utils.eventType[e.type];\n\t\tthis.moved\t\t= false;\n\t\tthis.distX\t\t= 0;\n\t\tthis.distY\t\t= 0;\n\t\tthis.directionX = 0;\n\t\tthis.directionY = 0;\n\t\tthis.directionLocked = 0;\n\n\t\tthis.startTime = utils.getTime();\n\n\t\tif ( this.options.useTransition && this.isInTransition ) {\n\t\t\tthis._transitionTime();\n\t\t\tthis.isInTransition = false;\n\t\t\tpos = this.getComputedPosition();\n\t\t\tthis._translate(Math.round(pos.x), Math.round(pos.y));\n\t\t\tthis._execEvent('scrollEnd');\n\t\t} else if ( !this.options.useTransition && this.isAnimating ) {\n\t\t\tthis.isAnimating = false;\n\t\t\tthis._execEvent('scrollEnd');\n\t\t}\n\n\t\tthis.startX    = this.x;\n\t\tthis.startY    = this.y;\n\t\tthis.absStartX = this.x;\n\t\tthis.absStartY = this.y;\n\t\tthis.pointX    = point.pageX;\n\t\tthis.pointY    = point.pageY;\n\n\t\tthis._execEvent('beforeScrollStart');\n\t},\n\n\t_move: function (e) {\n\t\tif ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( this.options.preventDefault ) {\t// increases performance on Android? TODO: check!\n\t\t\te.preventDefault();\n\t\t}\n\n\t\tvar point\t\t= e.touches ? e.touches[0] : e,\n\t\t\tdeltaX\t\t= point.pageX - this.pointX,\n\t\t\tdeltaY\t\t= point.pageY - this.pointY,\n\t\t\ttimestamp\t= utils.getTime(),\n\t\t\tnewX, newY,\n\t\t\tabsDistX, absDistY;\n\n\t\tthis.pointX\t\t= point.pageX;\n\t\tthis.pointY\t\t= point.pageY;\n\n\t\tthis.distX\t\t+= deltaX;\n\t\tthis.distY\t\t+= deltaY;\n\t\tabsDistX\t\t= Math.abs(this.distX);\n\t\tabsDistY\t\t= Math.abs(this.distY);\n\n\t\t// We need to move at least 10 pixels for the scrolling to initiate\n\t\tif ( timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If you are scrolling in one direction lock the other\n\t\tif ( !this.directionLocked && !this.options.freeScroll ) {\n\t\t\tif ( absDistX > absDistY + this.options.directionLockThreshold ) {\n\t\t\t\tthis.directionLocked = 'h';\t\t// lock horizontally\n\t\t\t} else if ( absDistY >= absDistX + this.options.directionLockThreshold ) {\n\t\t\t\tthis.directionLocked = 'v';\t\t// lock vertically\n\t\t\t} else {\n\t\t\t\tthis.directionLocked = 'n';\t\t// no lock\n\t\t\t}\n\t\t}\n\n\t\tif ( this.directionLocked == 'h' ) {\n\t\t\tif ( this.options.eventPassthrough == 'vertical' ) {\n\t\t\t\te.preventDefault();\n\t\t\t} else if ( this.options.eventPassthrough == 'horizontal' ) {\n\t\t\t\tthis.initiated = false;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tdeltaY = 0;\n\t\t} else if ( this.directionLocked == 'v' ) {\n\t\t\tif ( this.options.eventPassthrough == 'horizontal' ) {\n\t\t\t\te.preventDefault();\n\t\t\t} else if ( this.options.eventPassthrough == 'vertical' ) {\n\t\t\t\tthis.initiated = false;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tdeltaX = 0;\n\t\t}\n\n\t\tdeltaX = this.hasHorizontalScroll ? deltaX : 0;\n\t\tdeltaY = this.hasVerticalScroll ? deltaY : 0;\n\n\t\tnewX = this.x + deltaX;\n\t\tnewY = this.y + deltaY;\n\n\t\t// Slow down if outside of the boundaries\n\t\tif ( newX > 0 || newX < this.maxScrollX ) {\n\t\t\tnewX = this.options.bounce ? this.x + deltaX / 3 : newX > 0 ? 0 : this.maxScrollX;\n\t\t}\n\t\tif ( newY > 0 || newY < this.maxScrollY ) {\n\t\t\tnewY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY;\n\t\t}\n\n\t\tthis.directionX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0;\n\t\tthis.directionY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0;\n\n\t\tif ( !this.moved ) {\n\t\t\tthis._execEvent('scrollStart');\n\t\t}\n\n\t\tthis.moved = true;\n\n\t\tthis._translate(newX, newY);\n\n/* REPLACE START: _move */\n\n\t\tif ( timestamp - this.startTime > 300 ) {\n\t\t\tthis.startTime = timestamp;\n\t\t\tthis.startX = this.x;\n\t\t\tthis.startY = this.y;\n\t\t}\n\n/* REPLACE END: _move */\n\n\t},\n\n\t_end: function (e) {\n\t\tif ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( this.options.preventDefault && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) {\n\t\t\te.preventDefault();\n\t\t}\n\n\t\tvar point = e.changedTouches ? e.changedTouches[0] : e,\n\t\t\tmomentumX,\n\t\t\tmomentumY,\n\t\t\tduration = utils.getTime() - this.startTime,\n\t\t\tnewX = Math.round(this.x),\n\t\t\tnewY = Math.round(this.y),\n\t\t\tdistanceX = Math.abs(newX - this.startX),\n\t\t\tdistanceY = Math.abs(newY - this.startY),\n\t\t\ttime = 0,\n\t\t\teasing = '';\n\n\t\tthis.isInTransition = 0;\n\t\tthis.initiated = 0;\n\t\tthis.endTime = utils.getTime();\n\n\t\t// reset if we are outside of the boundaries\n\t\tif ( this.resetPosition(this.options.bounceTime) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.scrollTo(newX, newY);\t// ensures that the last position is rounded\n\n\t\t// we scrolled less than 10 pixels\n\t\tif ( !this.moved ) {\n\t\t\tif ( this.options.tap ) {\n\t\t\t\tutils.tap(e, this.options.tap);\n\t\t\t}\n\n\t\t\tif ( this.options.click ) {\n\t\t\t\tutils.click(e);\n\t\t\t}\n\n\t\t\tthis._execEvent('scrollCancel');\n\t\t\treturn;\n\t\t}\n\n\t\tif ( this._events.flick && duration < 200 && distanceX < 100 && distanceY < 100 ) {\n\t\t\tthis._execEvent('flick');\n\t\t\treturn;\n\t\t}\n\n\t\t// start momentum animation if needed\n\t\tif ( this.options.momentum && duration < 300 ) {\n\t\t\tmomentumX = this.hasHorizontalScroll ? utils.momentum(this.x, this.startX, duration, this.maxScrollX, this.options.bounce ? this.wrapperWidth : 0, this.options.deceleration) : { destination: newX, duration: 0 };\n\t\t\tmomentumY = this.hasVerticalScroll ? utils.momentum(this.y, this.startY, duration, this.maxScrollY, this.options.bounce ? this.wrapperHeight : 0, this.options.deceleration) : { destination: newY, duration: 0 };\n\t\t\tnewX = momentumX.destination;\n\t\t\tnewY = momentumY.destination;\n\t\t\ttime = Math.max(momentumX.duration, momentumY.duration);\n\t\t\tthis.isInTransition = 1;\n\t\t}\n\n\n\t\tif ( this.options.snap ) {\n\t\t\tvar snap = this._nearestSnap(newX, newY);\n\t\t\tthis.currentPage = snap;\n\t\t\ttime = this.options.snapSpeed || Math.max(\n\t\t\t\t\tMath.max(\n\t\t\t\t\t\tMath.min(Math.abs(newX - snap.x), 1000),\n\t\t\t\t\t\tMath.min(Math.abs(newY - snap.y), 1000)\n\t\t\t\t\t), 300);\n\t\t\tnewX = snap.x;\n\t\t\tnewY = snap.y;\n\n\t\t\tthis.directionX = 0;\n\t\t\tthis.directionY = 0;\n\t\t\teasing = this.options.bounceEasing;\n\t\t}\n\n// INSERT POINT: _end\n\n\t\tif ( newX != this.x || newY != this.y ) {\n\t\t\t// change easing function when scroller goes out of the boundaries\n\t\t\tif ( newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY ) {\n\t\t\t\teasing = utils.ease.quadratic;\n\t\t\t}\n\n\t\t\tthis.scrollTo(newX, newY, time, easing);\n\t\t\treturn;\n\t\t}\n\n\t\tthis._execEvent('scrollEnd');\n\t},\n\n\t_resize: function () {\n\t\tvar that = this;\n\n\t\tclearTimeout(this.resizeTimeout);\n\n\t\tthis.resizeTimeout = setTimeout(function () {\n\t\t\tthat.refresh();\n\t\t}, this.options.resizePolling);\n\t},\n\n\tresetPosition: function (time) {\n\t\tvar x = this.x,\n\t\t\ty = this.y;\n\n\t\ttime = time || 0;\n\n\t\tif ( !this.hasHorizontalScroll || this.x > 0 ) {\n\t\t\tx = 0;\n\t\t} else if ( this.x < this.maxScrollX ) {\n\t\t\tx = this.maxScrollX;\n\t\t}\n\n\t\tif ( !this.hasVerticalScroll || this.y > 0 ) {\n\t\t\ty = 0;\n\t\t} else if ( this.y < this.maxScrollY ) {\n\t\t\ty = this.maxScrollY;\n\t\t}\n\n\t\tif ( x == this.x && y == this.y ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tthis.scrollTo(x, y, time, this.options.bounceEasing);\n\n\t\treturn true;\n\t},\n\n\tdisable: function () {\n\t\tthis.enabled = false;\n\t},\n\n\tenable: function () {\n\t\tthis.enabled = true;\n\t},\n\n\trefresh: function () {\n\t\tvar rf = this.wrapper.offsetHeight;\t\t// Force reflow\n\n\t\tthis.wrapperWidth\t= this.wrapper.clientWidth;\n\t\tthis.wrapperHeight\t= this.wrapper.clientHeight;\n\n/* REPLACE START: refresh */\n\n\t\tthis.scrollerWidth\t= this.scroller.offsetWidth;\n\t\tthis.scrollerHeight\t= this.scroller.offsetHeight;\n\n\t\tthis.maxScrollX\t\t= this.wrapperWidth - this.scrollerWidth;\n\t\tthis.maxScrollY\t\t= this.wrapperHeight - this.scrollerHeight;\n\n/* REPLACE END: refresh */\n\n\t\tthis.hasHorizontalScroll\t= this.options.scrollX && this.maxScrollX < 0;\n\t\tthis.hasVerticalScroll\t\t= this.options.scrollY && this.maxScrollY < 0;\n\n\t\tif ( !this.hasHorizontalScroll ) {\n\t\t\tthis.maxScrollX = 0;\n\t\t\tthis.scrollerWidth = this.wrapperWidth;\n\t\t}\n\n\t\tif ( !this.hasVerticalScroll ) {\n\t\t\tthis.maxScrollY = 0;\n\t\t\tthis.scrollerHeight = this.wrapperHeight;\n\t\t}\n\n\t\tthis.endTime = 0;\n\t\tthis.directionX = 0;\n\t\tthis.directionY = 0;\n\n\t\tthis.wrapperOffset = utils.offset(this.wrapper);\n\n\t\tthis._execEvent('refresh');\n\n\t\tthis.resetPosition();\n\n// INSERT POINT: _refresh\n\n\t},\n\n\ton: function (type, fn) {\n\t\tif ( !this._events[type] ) {\n\t\t\tthis._events[type] = [];\n\t\t}\n\n\t\tthis._events[type].push(fn);\n\t},\n\n\toff: function (type, fn) {\n\t\tif ( !this._events[type] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar index = this._events[type].indexOf(fn);\n\n\t\tif ( index > -1 ) {\n\t\t\tthis._events[type].splice(index, 1);\n\t\t}\n\t},\n\n\t_execEvent: function (type) {\n\t\tif ( !this._events[type] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar i = 0,\n\t\t\tl = this._events[type].length;\n\n\t\tif ( !l ) {\n\t\t\treturn;\n\t\t}\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tthis._events[type][i].apply(this, [].slice.call(arguments, 1));\n\t\t}\n\t},\n\n\tscrollBy: function (x, y, time, easing) {\n\t\tx = this.x + x;\n\t\ty = this.y + y;\n\t\ttime = time || 0;\n\n\t\tthis.scrollTo(x, y, time, easing);\n\t},\n\n\tscrollTo: function (x, y, time, easing) {\n\t\teasing = easing || utils.ease.circular;\n\n\t\tthis.isInTransition = this.options.useTransition && time > 0;\n\t\tvar transitionType = this.options.useTransition && easing.style;\n\t\tif ( !time || transitionType ) {\n\t\t\t\tif(transitionType) {\n\t\t\t\t\tthis._transitionTimingFunction(easing.style);\n\t\t\t\t\tthis._transitionTime(time);\n\t\t\t\t}\n\t\t\tthis._translate(x, y);\n\t\t} else {\n\t\t\tthis._animate(x, y, time, easing.fn);\n\t\t}\n\t},\n\n\tscrollToElement: function (el, time, offsetX, offsetY, easing) {\n\t\tel = el.nodeType ? el : this.scroller.querySelector(el);\n\n\t\tif ( !el ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar pos = utils.offset(el);\n\n\t\tpos.left -= this.wrapperOffset.left;\n\t\tpos.top  -= this.wrapperOffset.top;\n\n\t\t// if offsetX/Y are true we center the element to the screen\n\t\tif ( offsetX === true ) {\n\t\t\toffsetX = Math.round(el.offsetWidth / 2 - this.wrapper.offsetWidth / 2);\n\t\t}\n\t\tif ( offsetY === true ) {\n\t\t\toffsetY = Math.round(el.offsetHeight / 2 - this.wrapper.offsetHeight / 2);\n\t\t}\n\n\t\tpos.left -= offsetX || 0;\n\t\tpos.top  -= offsetY || 0;\n\n\t\tpos.left = pos.left > 0 ? 0 : pos.left < this.maxScrollX ? this.maxScrollX : pos.left;\n\t\tpos.top  = pos.top  > 0 ? 0 : pos.top  < this.maxScrollY ? this.maxScrollY : pos.top;\n\n\t\ttime = time === undefined || time === null || time === 'auto' ? Math.max(Math.abs(this.x-pos.left), Math.abs(this.y-pos.top)) : time;\n\n\t\tthis.scrollTo(pos.left, pos.top, time, easing);\n\t},\n\n\t_transitionTime: function (time) {\n\t\tif (!this.options.useTransition) {\n\t\t\treturn;\n\t\t}\n\t\ttime = time || 0;\n\t\tvar durationProp = utils.style.transitionDuration;\n\t\tif(!durationProp) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.scrollerStyle[durationProp] = time + 'ms';\n\n\t\tif ( !time && utils.isBadAndroid ) {\n\t\t\tthis.scrollerStyle[durationProp] = '0.0001ms';\n\t\t\t// remove 0.0001ms\n\t\t\tvar self = this;\n\t\t\trAF(function() {\n\t\t\t\tif(self.scrollerStyle[durationProp] === '0.0001ms') {\n\t\t\t\t\tself.scrollerStyle[durationProp] = '0s';\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\n\t\tif ( this.indicators ) {\n\t\t\tfor ( var i = this.indicators.length; i--; ) {\n\t\t\t\tthis.indicators[i].transitionTime(time);\n\t\t\t}\n\t\t}\n\n\n// INSERT POINT: _transitionTime\n\n\t},\n\n\t_transitionTimingFunction: function (easing) {\n\t\tthis.scrollerStyle[utils.style.transitionTimingFunction] = easing;\n\n\n\t\tif ( this.indicators ) {\n\t\t\tfor ( var i = this.indicators.length; i--; ) {\n\t\t\t\tthis.indicators[i].transitionTimingFunction(easing);\n\t\t\t}\n\t\t}\n\n\n// INSERT POINT: _transitionTimingFunction\n\n\t},\n\n\t_translate: function (x, y) {\n\t\tif ( this.options.useTransform ) {\n\n/* REPLACE START: _translate */\n\n\t\t\tthis.scrollerStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.translateZ;\n\n/* REPLACE END: _translate */\n\n\t\t} else {\n\t\t\tx = Math.round(x);\n\t\t\ty = Math.round(y);\n\t\t\tthis.scrollerStyle.left = x + 'px';\n\t\t\tthis.scrollerStyle.top = y + 'px';\n\t\t}\n\n\t\tthis.x = x;\n\t\tthis.y = y;\n\n\n\tif ( this.indicators ) {\n\t\tfor ( var i = this.indicators.length; i--; ) {\n\t\t\tthis.indicators[i].updatePosition();\n\t\t}\n\t}\n\n\n// INSERT POINT: _translate\n\n\t},\n\n\t_initEvents: function (remove) {\n\t\tvar eventType = remove ? utils.removeEvent : utils.addEvent,\n\t\t\ttarget = this.options.bindToWrapper ? this.wrapper : window;\n\n\t\teventType(window, 'orientationchange', this);\n\t\teventType(window, 'resize', this);\n\n\t\tif ( this.options.click ) {\n\t\t\teventType(this.wrapper, 'click', this, true);\n\t\t}\n\n\t\tif ( !this.options.disableMouse ) {\n\t\t\teventType(this.wrapper, 'mousedown', this);\n\t\t\teventType(target, 'mousemove', this);\n\t\t\teventType(target, 'mousecancel', this);\n\t\t\teventType(target, 'mouseup', this);\n\t\t}\n\n\t\tif ( utils.hasPointer && !this.options.disablePointer ) {\n\t\t\teventType(this.wrapper, utils.prefixPointerEvent('pointerdown'), this);\n\t\t\teventType(target, utils.prefixPointerEvent('pointermove'), this);\n\t\t\teventType(target, utils.prefixPointerEvent('pointercancel'), this);\n\t\t\teventType(target, utils.prefixPointerEvent('pointerup'), this);\n\t\t}\n\n\t\tif ( utils.hasTouch && !this.options.disableTouch ) {\n\t\t\teventType(this.wrapper, 'touchstart', this);\n\t\t\teventType(target, 'touchmove', this);\n\t\t\teventType(target, 'touchcancel', this);\n\t\t\teventType(target, 'touchend', this);\n\t\t}\n\n\t\teventType(this.scroller, 'transitionend', this);\n\t\teventType(this.scroller, 'webkitTransitionEnd', this);\n\t\teventType(this.scroller, 'oTransitionEnd', this);\n\t\teventType(this.scroller, 'MSTransitionEnd', this);\n\t},\n\n\tgetComputedPosition: function () {\n\t\tvar matrix = window.getComputedStyle(this.scroller, null),\n\t\t\tx, y;\n\n\t\tif ( this.options.useTransform ) {\n\t\t\tmatrix = matrix[utils.style.transform].split(')')[0].split(', ');\n\t\t\tx = +(matrix[12] || matrix[4]);\n\t\t\ty = +(matrix[13] || matrix[5]);\n\t\t} else {\n\t\t\tx = +matrix.left.replace(/[^-\\d.]/g, '');\n\t\t\ty = +matrix.top.replace(/[^-\\d.]/g, '');\n\t\t}\n\n\t\treturn { x: x, y: y };\n\t},\n\t_initIndicators: function () {\n\t\tvar interactive = this.options.interactiveScrollbars,\n\t\t\tcustomStyle = typeof this.options.scrollbars != 'string',\n\t\t\tindicators = [],\n\t\t\tindicator;\n\n\t\tvar that = this;\n\n\t\tthis.indicators = [];\n\n\t\tif ( this.options.scrollbars ) {\n\t\t\t// Vertical scrollbar\n\t\t\tif ( this.options.scrollY ) {\n\t\t\t\tindicator = {\n\t\t\t\t\tel: createDefaultScrollbar('v', interactive, this.options.scrollbars),\n\t\t\t\t\tinteractive: interactive,\n\t\t\t\t\tdefaultScrollbars: true,\n\t\t\t\t\tcustomStyle: customStyle,\n\t\t\t\t\tresize: this.options.resizeScrollbars,\n\t\t\t\t\tshrink: this.options.shrinkScrollbars,\n\t\t\t\t\tfade: this.options.fadeScrollbars,\n\t\t\t\t\tlistenX: false\n\t\t\t\t};\n\n\t\t\t\tthis.wrapper.appendChild(indicator.el);\n\t\t\t\tindicators.push(indicator);\n\t\t\t}\n\n\t\t\t// Horizontal scrollbar\n\t\t\tif ( this.options.scrollX ) {\n\t\t\t\tindicator = {\n\t\t\t\t\tel: createDefaultScrollbar('h', interactive, this.options.scrollbars),\n\t\t\t\t\tinteractive: interactive,\n\t\t\t\t\tdefaultScrollbars: true,\n\t\t\t\t\tcustomStyle: customStyle,\n\t\t\t\t\tresize: this.options.resizeScrollbars,\n\t\t\t\t\tshrink: this.options.shrinkScrollbars,\n\t\t\t\t\tfade: this.options.fadeScrollbars,\n\t\t\t\t\tlistenY: false\n\t\t\t\t};\n\n\t\t\t\tthis.wrapper.appendChild(indicator.el);\n\t\t\t\tindicators.push(indicator);\n\t\t\t}\n\t\t}\n\n\t\tif ( this.options.indicators ) {\n\t\t\t// TODO: check concat compatibility\n\t\t\tindicators = indicators.concat(this.options.indicators);\n\t\t}\n\n\t\tfor ( var i = indicators.length; i--; ) {\n\t\t\tthis.indicators.push( new Indicator(this, indicators[i]) );\n\t\t}\n\n\t\t// TODO: check if we can use array.map (wide compatibility and performance issues)\n\t\tfunction _indicatorsMap (fn) {\n\t\t\tif (that.indicators) {\n\t\t\t\tfor ( var i = that.indicators.length; i--; ) {\n\t\t\t\t\tfn.call(that.indicators[i]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( this.options.fadeScrollbars ) {\n\t\t\tthis.on('scrollEnd', function () {\n\t\t\t\t_indicatorsMap(function () {\n\t\t\t\t\tthis.fade();\n\t\t\t\t});\n\t\t\t});\n\n\t\t\tthis.on('scrollCancel', function () {\n\t\t\t\t_indicatorsMap(function () {\n\t\t\t\t\tthis.fade();\n\t\t\t\t});\n\t\t\t});\n\n\t\t\tthis.on('scrollStart', function () {\n\t\t\t\t_indicatorsMap(function () {\n\t\t\t\t\tthis.fade(1);\n\t\t\t\t});\n\t\t\t});\n\n\t\t\tthis.on('beforeScrollStart', function () {\n\t\t\t\t_indicatorsMap(function () {\n\t\t\t\t\tthis.fade(1, true);\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\n\n\t\tthis.on('refresh', function () {\n\t\t\t_indicatorsMap(function () {\n\t\t\t\tthis.refresh();\n\t\t\t});\n\t\t});\n\n\t\tthis.on('destroy', function () {\n\t\t\t_indicatorsMap(function () {\n\t\t\t\tthis.destroy();\n\t\t\t});\n\n\t\t\tdelete this.indicators;\n\t\t});\n\t},\n\n\t_initWheel: function () {\n\t\tutils.addEvent(this.wrapper, 'wheel', this);\n\t\tutils.addEvent(this.wrapper, 'mousewheel', this);\n\t\tutils.addEvent(this.wrapper, 'DOMMouseScroll', this);\n\n\t\tthis.on('destroy', function () {\n\t\t\tclearTimeout(this.wheelTimeout);\n\t\t\tthis.wheelTimeout = null;\n\t\t\tutils.removeEvent(this.wrapper, 'wheel', this);\n\t\t\tutils.removeEvent(this.wrapper, 'mousewheel', this);\n\t\t\tutils.removeEvent(this.wrapper, 'DOMMouseScroll', this);\n\t\t});\n\t},\n\n\t_wheel: function (e) {\n\t\tif ( !this.enabled ) {\n\t\t\treturn;\n\t\t}\n\n\t\te.preventDefault();\n\n\t\tvar wheelDeltaX, wheelDeltaY,\n\t\t\tnewX, newY,\n\t\t\tthat = this;\n\n\t\tif ( this.wheelTimeout === undefined ) {\n\t\t\tthat._execEvent('scrollStart');\n\t\t}\n\n\t\t// Execute the scrollEnd event after 400ms the wheel stopped scrolling\n\t\tclearTimeout(this.wheelTimeout);\n\t\tthis.wheelTimeout = setTimeout(function () {\n\t\t\tif(!that.options.snap) {\n\t\t\t\tthat._execEvent('scrollEnd');\n\t\t\t}\n\t\t\tthat.wheelTimeout = undefined;\n\t\t}, 400);\n\n\t\tif ( 'deltaX' in e ) {\n\t\t\tif (e.deltaMode === 1) {\n\t\t\t\twheelDeltaX = -e.deltaX * this.options.mouseWheelSpeed;\n\t\t\t\twheelDeltaY = -e.deltaY * this.options.mouseWheelSpeed;\n\t\t\t} else {\n\t\t\t\twheelDeltaX = -e.deltaX;\n\t\t\t\twheelDeltaY = -e.deltaY;\n\t\t\t}\n\t\t} else if ( 'wheelDeltaX' in e ) {\n\t\t\twheelDeltaX = e.wheelDeltaX / 120 * this.options.mouseWheelSpeed;\n\t\t\twheelDeltaY = e.wheelDeltaY / 120 * this.options.mouseWheelSpeed;\n\t\t} else if ( 'wheelDelta' in e ) {\n\t\t\twheelDeltaX = wheelDeltaY = e.wheelDelta / 120 * this.options.mouseWheelSpeed;\n\t\t} else if ( 'detail' in e ) {\n\t\t\twheelDeltaX = wheelDeltaY = -e.detail / 3 * this.options.mouseWheelSpeed;\n\t\t} else {\n\t\t\treturn;\n\t\t}\n\n\t\twheelDeltaX *= this.options.invertWheelDirection;\n\t\twheelDeltaY *= this.options.invertWheelDirection;\n\n\t\tif ( !this.hasVerticalScroll ) {\n\t\t\twheelDeltaX = wheelDeltaY;\n\t\t\twheelDeltaY = 0;\n\t\t}\n\n\t\tif ( this.options.snap ) {\n\t\t\tnewX = this.currentPage.pageX;\n\t\t\tnewY = this.currentPage.pageY;\n\n\t\t\tif ( wheelDeltaX > 0 ) {\n\t\t\t\tnewX--;\n\t\t\t} else if ( wheelDeltaX < 0 ) {\n\t\t\t\tnewX++;\n\t\t\t}\n\n\t\t\tif ( wheelDeltaY > 0 ) {\n\t\t\t\tnewY--;\n\t\t\t} else if ( wheelDeltaY < 0 ) {\n\t\t\t\tnewY++;\n\t\t\t}\n\n\t\t\tthis.goToPage(newX, newY);\n\n\t\t\treturn;\n\t\t}\n\n\t\tnewX = this.x + Math.round(this.hasHorizontalScroll ? wheelDeltaX : 0);\n\t\tnewY = this.y + Math.round(this.hasVerticalScroll ? wheelDeltaY : 0);\n\n\t\tthis.directionX = wheelDeltaX > 0 ? -1 : wheelDeltaX < 0 ? 1 : 0;\n\t\tthis.directionY = wheelDeltaY > 0 ? -1 : wheelDeltaY < 0 ? 1 : 0;\n\n\t\tif ( newX > 0 ) {\n\t\t\tnewX = 0;\n\t\t} else if ( newX < this.maxScrollX ) {\n\t\t\tnewX = this.maxScrollX;\n\t\t}\n\n\t\tif ( newY > 0 ) {\n\t\t\tnewY = 0;\n\t\t} else if ( newY < this.maxScrollY ) {\n\t\t\tnewY = this.maxScrollY;\n\t\t}\n\n\t\tthis.scrollTo(newX, newY, 0);\n\n// INSERT POINT: _wheel\n\t},\n\n\t_initSnap: function () {\n\t\tthis.currentPage = {};\n\n\t\tif ( typeof this.options.snap == 'string' ) {\n\t\t\tthis.options.snap = this.scroller.querySelectorAll(this.options.snap);\n\t\t}\n\n\t\tthis.on('refresh', function () {\n\t\t\tvar i = 0, l,\n\t\t\t\tm = 0, n,\n\t\t\t\tcx, cy,\n\t\t\t\tx = 0, y,\n\t\t\t\tstepX = this.options.snapStepX || this.wrapperWidth,\n\t\t\t\tstepY = this.options.snapStepY || this.wrapperHeight,\n\t\t\t\tel;\n\n\t\t\tthis.pages = [];\n\n\t\t\tif ( !this.wrapperWidth || !this.wrapperHeight || !this.scrollerWidth || !this.scrollerHeight ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( this.options.snap === true ) {\n\t\t\t\tcx = Math.round( stepX / 2 );\n\t\t\t\tcy = Math.round( stepY / 2 );\n\n\t\t\t\twhile ( x > -this.scrollerWidth ) {\n\t\t\t\t\tthis.pages[i] = [];\n\t\t\t\t\tl = 0;\n\t\t\t\t\ty = 0;\n\n\t\t\t\t\twhile ( y > -this.scrollerHeight ) {\n\t\t\t\t\t\tthis.pages[i][l] = {\n\t\t\t\t\t\t\tx: Math.max(x, this.maxScrollX),\n\t\t\t\t\t\t\ty: Math.max(y, this.maxScrollY),\n\t\t\t\t\t\t\twidth: stepX,\n\t\t\t\t\t\t\theight: stepY,\n\t\t\t\t\t\t\tcx: x - cx,\n\t\t\t\t\t\t\tcy: y - cy\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\ty -= stepY;\n\t\t\t\t\t\tl++;\n\t\t\t\t\t}\n\n\t\t\t\t\tx -= stepX;\n\t\t\t\t\ti++;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tel = this.options.snap;\n\t\t\t\tl = el.length;\n\t\t\t\tn = -1;\n\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\tif ( i === 0 || el[i].offsetLeft <= el[i-1].offsetLeft ) {\n\t\t\t\t\t\tm = 0;\n\t\t\t\t\t\tn++;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( !this.pages[m] ) {\n\t\t\t\t\t\tthis.pages[m] = [];\n\t\t\t\t\t}\n\n\t\t\t\t\tx = Math.max(-el[i].offsetLeft, this.maxScrollX);\n\t\t\t\t\ty = Math.max(-el[i].offsetTop, this.maxScrollY);\n\t\t\t\t\tcx = x - Math.round(el[i].offsetWidth / 2);\n\t\t\t\t\tcy = y - Math.round(el[i].offsetHeight / 2);\n\n\t\t\t\t\tthis.pages[m][n] = {\n\t\t\t\t\t\tx: x,\n\t\t\t\t\t\ty: y,\n\t\t\t\t\t\twidth: el[i].offsetWidth,\n\t\t\t\t\t\theight: el[i].offsetHeight,\n\t\t\t\t\t\tcx: cx,\n\t\t\t\t\t\tcy: cy\n\t\t\t\t\t};\n\n\t\t\t\t\tif ( x > this.maxScrollX ) {\n\t\t\t\t\t\tm++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.goToPage(this.currentPage.pageX || 0, this.currentPage.pageY || 0, 0);\n\n\t\t\t// Update snap threshold if needed\n\t\t\tif ( this.options.snapThreshold % 1 === 0 ) {\n\t\t\t\tthis.snapThresholdX = this.options.snapThreshold;\n\t\t\t\tthis.snapThresholdY = this.options.snapThreshold;\n\t\t\t} else {\n\t\t\t\tthis.snapThresholdX = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].width * this.options.snapThreshold);\n\t\t\t\tthis.snapThresholdY = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].height * this.options.snapThreshold);\n\t\t\t}\n\t\t});\n\n\t\tthis.on('flick', function () {\n\t\t\tvar time = this.options.snapSpeed || Math.max(\n\t\t\t\t\tMath.max(\n\t\t\t\t\t\tMath.min(Math.abs(this.x - this.startX), 1000),\n\t\t\t\t\t\tMath.min(Math.abs(this.y - this.startY), 1000)\n\t\t\t\t\t), 300);\n\n\t\t\tthis.goToPage(\n\t\t\t\tthis.currentPage.pageX + this.directionX,\n\t\t\t\tthis.currentPage.pageY + this.directionY,\n\t\t\t\ttime\n\t\t\t);\n\t\t});\n\t},\n\n\t_nearestSnap: function (x, y) {\n\t\tif ( !this.pages.length ) {\n\t\t\treturn { x: 0, y: 0, pageX: 0, pageY: 0 };\n\t\t}\n\n\t\tvar i = 0,\n\t\t\tl = this.pages.length,\n\t\t\tm = 0;\n\n\t\t// Check if we exceeded the snap threshold\n\t\tif ( Math.abs(x - this.absStartX) < this.snapThresholdX &&\n\t\t\tMath.abs(y - this.absStartY) < this.snapThresholdY ) {\n\t\t\treturn this.currentPage;\n\t\t}\n\n\t\tif ( x > 0 ) {\n\t\t\tx = 0;\n\t\t} else if ( x < this.maxScrollX ) {\n\t\t\tx = this.maxScrollX;\n\t\t}\n\n\t\tif ( y > 0 ) {\n\t\t\ty = 0;\n\t\t} else if ( y < this.maxScrollY ) {\n\t\t\ty = this.maxScrollY;\n\t\t}\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tif ( x >= this.pages[i][0].cx ) {\n\t\t\t\tx = this.pages[i][0].x;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tl = this.pages[i].length;\n\n\t\tfor ( ; m < l; m++ ) {\n\t\t\tif ( y >= this.pages[0][m].cy ) {\n\t\t\t\ty = this.pages[0][m].y;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif ( i == this.currentPage.pageX ) {\n\t\t\ti += this.directionX;\n\n\t\t\tif ( i < 0 ) {\n\t\t\t\ti = 0;\n\t\t\t} else if ( i >= this.pages.length ) {\n\t\t\t\ti = this.pages.length - 1;\n\t\t\t}\n\n\t\t\tx = this.pages[i][0].x;\n\t\t}\n\n\t\tif ( m == this.currentPage.pageY ) {\n\t\t\tm += this.directionY;\n\n\t\t\tif ( m < 0 ) {\n\t\t\t\tm = 0;\n\t\t\t} else if ( m >= this.pages[0].length ) {\n\t\t\t\tm = this.pages[0].length - 1;\n\t\t\t}\n\n\t\t\ty = this.pages[0][m].y;\n\t\t}\n\n\t\treturn {\n\t\t\tx: x,\n\t\t\ty: y,\n\t\t\tpageX: i,\n\t\t\tpageY: m\n\t\t};\n\t},\n\n\tgoToPage: function (x, y, time, easing) {\n\t\teasing = easing || this.options.bounceEasing;\n\n\t\tif ( x >= this.pages.length ) {\n\t\t\tx = this.pages.length - 1;\n\t\t} else if ( x < 0 ) {\n\t\t\tx = 0;\n\t\t}\n\n\t\tif ( y >= this.pages[x].length ) {\n\t\t\ty = this.pages[x].length - 1;\n\t\t} else if ( y < 0 ) {\n\t\t\ty = 0;\n\t\t}\n\n\t\tvar posX = this.pages[x][y].x,\n\t\t\tposY = this.pages[x][y].y;\n\n\t\ttime = time === undefined ? this.options.snapSpeed || Math.max(\n\t\t\tMath.max(\n\t\t\t\tMath.min(Math.abs(posX - this.x), 1000),\n\t\t\t\tMath.min(Math.abs(posY - this.y), 1000)\n\t\t\t), 300) : time;\n\n\t\tthis.currentPage = {\n\t\t\tx: posX,\n\t\t\ty: posY,\n\t\t\tpageX: x,\n\t\t\tpageY: y\n\t\t};\n\n\t\tthis.scrollTo(posX, posY, time, easing);\n\t},\n\n\tnext: function (time, easing) {\n\t\tvar x = this.currentPage.pageX,\n\t\t\ty = this.currentPage.pageY;\n\n\t\tx++;\n\n\t\tif ( x >= this.pages.length && this.hasVerticalScroll ) {\n\t\t\tx = 0;\n\t\t\ty++;\n\t\t}\n\n\t\tthis.goToPage(x, y, time, easing);\n\t},\n\n\tprev: function (time, easing) {\n\t\tvar x = this.currentPage.pageX,\n\t\t\ty = this.currentPage.pageY;\n\n\t\tx--;\n\n\t\tif ( x < 0 && this.hasVerticalScroll ) {\n\t\t\tx = 0;\n\t\t\ty--;\n\t\t}\n\n\t\tthis.goToPage(x, y, time, easing);\n\t},\n\n\t_initKeys: function (e) {\n\t\t// default key bindings\n\t\tvar keys = {\n\t\t\tpageUp: 33,\n\t\t\tpageDown: 34,\n\t\t\tend: 35,\n\t\t\thome: 36,\n\t\t\tleft: 37,\n\t\t\tup: 38,\n\t\t\tright: 39,\n\t\t\tdown: 40\n\t\t};\n\t\tvar i;\n\n\t\t// if you give me characters I give you keycode\n\t\tif ( typeof this.options.keyBindings == 'object' ) {\n\t\t\tfor ( i in this.options.keyBindings ) {\n\t\t\t\tif ( typeof this.options.keyBindings[i] == 'string' ) {\n\t\t\t\t\tthis.options.keyBindings[i] = this.options.keyBindings[i].toUpperCase().charCodeAt(0);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthis.options.keyBindings = {};\n\t\t}\n\n\t\tfor ( i in keys ) {\n\t\t\tthis.options.keyBindings[i] = this.options.keyBindings[i] || keys[i];\n\t\t}\n\n\t\tutils.addEvent(window, 'keydown', this);\n\n\t\tthis.on('destroy', function () {\n\t\t\tutils.removeEvent(window, 'keydown', this);\n\t\t});\n\t},\n\n\t_key: function (e) {\n\t\tif ( !this.enabled ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar snap = this.options.snap,\t// we are using this alot, better to cache it\n\t\t\tnewX = snap ? this.currentPage.pageX : this.x,\n\t\t\tnewY = snap ? this.currentPage.pageY : this.y,\n\t\t\tnow = utils.getTime(),\n\t\t\tprevTime = this.keyTime || 0,\n\t\t\tacceleration = 0.250,\n\t\t\tpos;\n\n\t\tif ( this.options.useTransition && this.isInTransition ) {\n\t\t\tpos = this.getComputedPosition();\n\n\t\t\tthis._translate(Math.round(pos.x), Math.round(pos.y));\n\t\t\tthis.isInTransition = false;\n\t\t}\n\n\t\tthis.keyAcceleration = now - prevTime < 200 ? Math.min(this.keyAcceleration + acceleration, 50) : 0;\n\n\t\tswitch ( e.keyCode ) {\n\t\t\tcase this.options.keyBindings.pageUp:\n\t\t\t\tif ( this.hasHorizontalScroll && !this.hasVerticalScroll ) {\n\t\t\t\t\tnewX += snap ? 1 : this.wrapperWidth;\n\t\t\t\t} else {\n\t\t\t\t\tnewY += snap ? 1 : this.wrapperHeight;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase this.options.keyBindings.pageDown:\n\t\t\t\tif ( this.hasHorizontalScroll && !this.hasVerticalScroll ) {\n\t\t\t\t\tnewX -= snap ? 1 : this.wrapperWidth;\n\t\t\t\t} else {\n\t\t\t\t\tnewY -= snap ? 1 : this.wrapperHeight;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase this.options.keyBindings.end:\n\t\t\t\tnewX = snap ? this.pages.length-1 : this.maxScrollX;\n\t\t\t\tnewY = snap ? this.pages[0].length-1 : this.maxScrollY;\n\t\t\t\tbreak;\n\t\t\tcase this.options.keyBindings.home:\n\t\t\t\tnewX = 0;\n\t\t\t\tnewY = 0;\n\t\t\t\tbreak;\n\t\t\tcase this.options.keyBindings.left:\n\t\t\t\tnewX += snap ? -1 : 5 + this.keyAcceleration>>0;\n\t\t\t\tbreak;\n\t\t\tcase this.options.keyBindings.up:\n\t\t\t\tnewY += snap ? 1 : 5 + this.keyAcceleration>>0;\n\t\t\t\tbreak;\n\t\t\tcase this.options.keyBindings.right:\n\t\t\t\tnewX -= snap ? -1 : 5 + this.keyAcceleration>>0;\n\t\t\t\tbreak;\n\t\t\tcase this.options.keyBindings.down:\n\t\t\t\tnewY -= snap ? 1 : 5 + this.keyAcceleration>>0;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\treturn;\n\t\t}\n\n\t\tif ( snap ) {\n\t\t\tthis.goToPage(newX, newY);\n\t\t\treturn;\n\t\t}\n\n\t\tif ( newX > 0 ) {\n\t\t\tnewX = 0;\n\t\t\tthis.keyAcceleration = 0;\n\t\t} else if ( newX < this.maxScrollX ) {\n\t\t\tnewX = this.maxScrollX;\n\t\t\tthis.keyAcceleration = 0;\n\t\t}\n\n\t\tif ( newY > 0 ) {\n\t\t\tnewY = 0;\n\t\t\tthis.keyAcceleration = 0;\n\t\t} else if ( newY < this.maxScrollY ) {\n\t\t\tnewY = this.maxScrollY;\n\t\t\tthis.keyAcceleration = 0;\n\t\t}\n\n\t\tthis.scrollTo(newX, newY, 0);\n\n\t\tthis.keyTime = now;\n\t},\n\n\t_animate: function (destX, destY, duration, easingFn) {\n\t\tvar that = this,\n\t\t\tstartX = this.x,\n\t\t\tstartY = this.y,\n\t\t\tstartTime = utils.getTime(),\n\t\t\tdestTime = startTime + duration;\n\n\t\tfunction step () {\n\t\t\tvar now = utils.getTime(),\n\t\t\t\tnewX, newY,\n\t\t\t\teasing;\n\n\t\t\tif ( now >= destTime ) {\n\t\t\t\tthat.isAnimating = false;\n\t\t\t\tthat._translate(destX, destY);\n\n\t\t\t\tif ( !that.resetPosition(that.options.bounceTime) ) {\n\t\t\t\t\tthat._execEvent('scrollEnd');\n\t\t\t\t}\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tnow = ( now - startTime ) / duration;\n\t\t\teasing = easingFn(now);\n\t\t\tnewX = ( destX - startX ) * easing + startX;\n\t\t\tnewY = ( destY - startY ) * easing + startY;\n\t\t\tthat._translate(newX, newY);\n\n\t\t\tif ( that.isAnimating ) {\n\t\t\t\trAF(step);\n\t\t\t}\n\t\t}\n\n\t\tthis.isAnimating = true;\n\t\tstep();\n\t},\n\thandleEvent: function (e) {\n\t\tswitch ( e.type ) {\n\t\t\tcase 'touchstart':\n\t\t\tcase 'pointerdown':\n\t\t\tcase 'MSPointerDown':\n\t\t\tcase 'mousedown':\n\t\t\t\tthis._start(e);\n\t\t\t\tbreak;\n\t\t\tcase 'touchmove':\n\t\t\tcase 'pointermove':\n\t\t\tcase 'MSPointerMove':\n\t\t\tcase 'mousemove':\n\t\t\t\tthis._move(e);\n\t\t\t\tbreak;\n\t\t\tcase 'touchend':\n\t\t\tcase 'pointerup':\n\t\t\tcase 'MSPointerUp':\n\t\t\tcase 'mouseup':\n\t\t\tcase 'touchcancel':\n\t\t\tcase 'pointercancel':\n\t\t\tcase 'MSPointerCancel':\n\t\t\tcase 'mousecancel':\n\t\t\t\tthis._end(e);\n\t\t\t\tbreak;\n\t\t\tcase 'orientationchange':\n\t\t\tcase 'resize':\n\t\t\t\tthis._resize();\n\t\t\t\tbreak;\n\t\t\tcase 'transitionend':\n\t\t\tcase 'webkitTransitionEnd':\n\t\t\tcase 'oTransitionEnd':\n\t\t\tcase 'MSTransitionEnd':\n\t\t\t\tthis._transitionEnd(e);\n\t\t\t\tbreak;\n\t\t\tcase 'wheel':\n\t\t\tcase 'DOMMouseScroll':\n\t\t\tcase 'mousewheel':\n\t\t\t\tthis._wheel(e);\n\t\t\t\tbreak;\n\t\t\tcase 'keydown':\n\t\t\t\tthis._key(e);\n\t\t\t\tbreak;\n\t\t\tcase 'click':\n\t\t\t\tif ( this.enabled && !e._constructed ) {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\te.stopPropagation();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n};\nfunction createDefaultScrollbar (direction, interactive, type) {\n\tvar scrollbar = document.createElement('div'),\n\t\tindicator = document.createElement('div');\n\n\tif ( type === true ) {\n\t\tscrollbar.style.cssText = 'position:absolute;z-index:9999';\n\t\tindicator.style.cssText = '-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;position:absolute;background:rgba(0,0,0,0.5);border:1px solid rgba(255,255,255,0.9);border-radius:3px';\n\t}\n\n\tindicator.className = 'iScrollIndicator';\n\n\tif ( direction == 'h' ) {\n\t\tif ( type === true ) {\n\t\t\tscrollbar.style.cssText += ';height:7px;left:2px;right:2px;bottom:0';\n\t\t\tindicator.style.height = '100%';\n\t\t}\n\t\tscrollbar.className = 'iScrollHorizontalScrollbar';\n\t} else {\n\t\tif ( type === true ) {\n\t\t\tscrollbar.style.cssText += ';width:7px;bottom:2px;top:2px;right:1px';\n\t\t\tindicator.style.width = '100%';\n\t\t}\n\t\tscrollbar.className = 'iScrollVerticalScrollbar';\n\t}\n\n\tscrollbar.style.cssText += ';overflow:hidden';\n\n\tif ( !interactive ) {\n\t\tscrollbar.style.pointerEvents = 'none';\n\t}\n\n\tscrollbar.appendChild(indicator);\n\n\treturn scrollbar;\n}\n\nfunction Indicator (scroller, options) {\n\tthis.wrapper = typeof options.el == 'string' ? document.querySelector(options.el) : options.el;\n\tthis.wrapperStyle = this.wrapper.style;\n\tthis.indicator = this.wrapper.children[0];\n\tthis.indicatorStyle = this.indicator.style;\n\tthis.scroller = scroller;\n\n\tthis.options = {\n\t\tlistenX: true,\n\t\tlistenY: true,\n\t\tinteractive: false,\n\t\tresize: true,\n\t\tdefaultScrollbars: false,\n\t\tshrink: false,\n\t\tfade: false,\n\t\tspeedRatioX: 0,\n\t\tspeedRatioY: 0\n\t};\n\n\tfor ( var i in options ) {\n\t\tthis.options[i] = options[i];\n\t}\n\n\tthis.sizeRatioX = 1;\n\tthis.sizeRatioY = 1;\n\tthis.maxPosX = 0;\n\tthis.maxPosY = 0;\n\n\tif ( this.options.interactive ) {\n\t\tif ( !this.options.disableTouch ) {\n\t\t\tutils.addEvent(this.indicator, 'touchstart', this);\n\t\t\tutils.addEvent(window, 'touchend', this);\n\t\t}\n\t\tif ( !this.options.disablePointer ) {\n\t\t\tutils.addEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this);\n\t\t\tutils.addEvent(window, utils.prefixPointerEvent('pointerup'), this);\n\t\t}\n\t\tif ( !this.options.disableMouse ) {\n\t\t\tutils.addEvent(this.indicator, 'mousedown', this);\n\t\t\tutils.addEvent(window, 'mouseup', this);\n\t\t}\n\t}\n\n\tif ( this.options.fade ) {\n\t\tthis.wrapperStyle[utils.style.transform] = this.scroller.translateZ;\n\t\tvar durationProp = utils.style.transitionDuration;\n\t\tif(!durationProp) {\n\t\t\treturn;\n\t\t}\n\t\tthis.wrapperStyle[durationProp] = utils.isBadAndroid ? '0.0001ms' : '0ms';\n\t\t// remove 0.0001ms\n\t\tvar self = this;\n\t\tif(utils.isBadAndroid) {\n\t\t\trAF(function() {\n\t\t\t\tif(self.wrapperStyle[durationProp] === '0.0001ms') {\n\t\t\t\t\tself.wrapperStyle[durationProp] = '0s';\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\tthis.wrapperStyle.opacity = '0';\n\t}\n}\n\nIndicator.prototype = {\n\thandleEvent: function (e) {\n\t\tswitch ( e.type ) {\n\t\t\tcase 'touchstart':\n\t\t\tcase 'pointerdown':\n\t\t\tcase 'MSPointerDown':\n\t\t\tcase 'mousedown':\n\t\t\t\tthis._start(e);\n\t\t\t\tbreak;\n\t\t\tcase 'touchmove':\n\t\t\tcase 'pointermove':\n\t\t\tcase 'MSPointerMove':\n\t\t\tcase 'mousemove':\n\t\t\t\tthis._move(e);\n\t\t\t\tbreak;\n\t\t\tcase 'touchend':\n\t\t\tcase 'pointerup':\n\t\t\tcase 'MSPointerUp':\n\t\t\tcase 'mouseup':\n\t\t\tcase 'touchcancel':\n\t\t\tcase 'pointercancel':\n\t\t\tcase 'MSPointerCancel':\n\t\t\tcase 'mousecancel':\n\t\t\t\tthis._end(e);\n\t\t\t\tbreak;\n\t\t}\n\t},\n\n\tdestroy: function () {\n\t\tif ( this.options.fadeScrollbars ) {\n\t\t\tclearTimeout(this.fadeTimeout);\n\t\t\tthis.fadeTimeout = null;\n\t\t}\n\t\tif ( this.options.interactive ) {\n\t\t\tutils.removeEvent(this.indicator, 'touchstart', this);\n\t\t\tutils.removeEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this);\n\t\t\tutils.removeEvent(this.indicator, 'mousedown', this);\n\n\t\t\tutils.removeEvent(window, 'touchmove', this);\n\t\t\tutils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this);\n\t\t\tutils.removeEvent(window, 'mousemove', this);\n\n\t\t\tutils.removeEvent(window, 'touchend', this);\n\t\t\tutils.removeEvent(window, utils.prefixPointerEvent('pointerup'), this);\n\t\t\tutils.removeEvent(window, 'mouseup', this);\n\t\t}\n\n\t\tif ( this.options.defaultScrollbars ) {\n\t\t\tthis.wrapper.parentNode.removeChild(this.wrapper);\n\t\t}\n\t},\n\n\t_start: function (e) {\n\t\tvar point = e.touches ? e.touches[0] : e;\n\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\n\t\tthis.transitionTime();\n\n\t\tthis.initiated = true;\n\t\tthis.moved = false;\n\t\tthis.lastPointX\t= point.pageX;\n\t\tthis.lastPointY\t= point.pageY;\n\n\t\tthis.startTime\t= utils.getTime();\n\n\t\tif ( !this.options.disableTouch ) {\n\t\t\tutils.addEvent(window, 'touchmove', this);\n\t\t}\n\t\tif ( !this.options.disablePointer ) {\n\t\t\tutils.addEvent(window, utils.prefixPointerEvent('pointermove'), this);\n\t\t}\n\t\tif ( !this.options.disableMouse ) {\n\t\t\tutils.addEvent(window, 'mousemove', this);\n\t\t}\n\n\t\tthis.scroller._execEvent('beforeScrollStart');\n\t},\n\n\t_move: function (e) {\n\t\tvar point = e.touches ? e.touches[0] : e,\n\t\t\tdeltaX, deltaY,\n\t\t\tnewX, newY,\n\t\t\ttimestamp = utils.getTime();\n\n\t\tif ( !this.moved ) {\n\t\t\tthis.scroller._execEvent('scrollStart');\n\t\t}\n\n\t\tthis.moved = true;\n\n\t\tdeltaX = point.pageX - this.lastPointX;\n\t\tthis.lastPointX = point.pageX;\n\n\t\tdeltaY = point.pageY - this.lastPointY;\n\t\tthis.lastPointY = point.pageY;\n\n\t\tnewX = this.x + deltaX;\n\t\tnewY = this.y + deltaY;\n\n\t\tthis._pos(newX, newY);\n\n// INSERT POINT: indicator._move\n\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\t},\n\n\t_end: function (e) {\n\t\tif ( !this.initiated ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.initiated = false;\n\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\n\t\tutils.removeEvent(window, 'touchmove', this);\n\t\tutils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this);\n\t\tutils.removeEvent(window, 'mousemove', this);\n\n\t\tif ( this.scroller.options.snap ) {\n\t\t\tvar snap = this.scroller._nearestSnap(this.scroller.x, this.scroller.y);\n\n\t\t\tvar time = this.options.snapSpeed || Math.max(\n\t\t\t\t\tMath.max(\n\t\t\t\t\t\tMath.min(Math.abs(this.scroller.x - snap.x), 1000),\n\t\t\t\t\t\tMath.min(Math.abs(this.scroller.y - snap.y), 1000)\n\t\t\t\t\t), 300);\n\n\t\t\tif ( this.scroller.x != snap.x || this.scroller.y != snap.y ) {\n\t\t\t\tthis.scroller.directionX = 0;\n\t\t\t\tthis.scroller.directionY = 0;\n\t\t\t\tthis.scroller.currentPage = snap;\n\t\t\t\tthis.scroller.scrollTo(snap.x, snap.y, time, this.scroller.options.bounceEasing);\n\t\t\t}\n\t\t}\n\n\t\tif ( this.moved ) {\n\t\t\tthis.scroller._execEvent('scrollEnd');\n\t\t}\n\t},\n\n\ttransitionTime: function (time) {\n\t\ttime = time || 0;\n\t\tvar durationProp = utils.style.transitionDuration;\n\t\tif(!durationProp) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.indicatorStyle[durationProp] = time + 'ms';\n\n\t\tif ( !time && utils.isBadAndroid ) {\n\t\t\tthis.indicatorStyle[durationProp] = '0.0001ms';\n\t\t\t// remove 0.0001ms\n\t\t\tvar self = this;\n\t\t\trAF(function() {\n\t\t\t\tif(self.indicatorStyle[durationProp] === '0.0001ms') {\n\t\t\t\t\tself.indicatorStyle[durationProp] = '0s';\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t},\n\n\ttransitionTimingFunction: function (easing) {\n\t\tthis.indicatorStyle[utils.style.transitionTimingFunction] = easing;\n\t},\n\n\trefresh: function () {\n\t\tthis.transitionTime();\n\n\t\tif ( this.options.listenX && !this.options.listenY ) {\n\t\t\tthis.indicatorStyle.display = this.scroller.hasHorizontalScroll ? 'block' : 'none';\n\t\t} else if ( this.options.listenY && !this.options.listenX ) {\n\t\t\tthis.indicatorStyle.display = this.scroller.hasVerticalScroll ? 'block' : 'none';\n\t\t} else {\n\t\t\tthis.indicatorStyle.display = this.scroller.hasHorizontalScroll || this.scroller.hasVerticalScroll ? 'block' : 'none';\n\t\t}\n\n\t\tif ( this.scroller.hasHorizontalScroll && this.scroller.hasVerticalScroll ) {\n\t\t\tutils.addClass(this.wrapper, 'iScrollBothScrollbars');\n\t\t\tutils.removeClass(this.wrapper, 'iScrollLoneScrollbar');\n\n\t\t\tif ( this.options.defaultScrollbars && this.options.customStyle ) {\n\t\t\t\tif ( this.options.listenX ) {\n\t\t\t\t\tthis.wrapper.style.right = '8px';\n\t\t\t\t} else {\n\t\t\t\t\tthis.wrapper.style.bottom = '8px';\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tutils.removeClass(this.wrapper, 'iScrollBothScrollbars');\n\t\t\tutils.addClass(this.wrapper, 'iScrollLoneScrollbar');\n\n\t\t\tif ( this.options.defaultScrollbars && this.options.customStyle ) {\n\t\t\t\tif ( this.options.listenX ) {\n\t\t\t\t\tthis.wrapper.style.right = '2px';\n\t\t\t\t} else {\n\t\t\t\t\tthis.wrapper.style.bottom = '2px';\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tvar r = this.wrapper.offsetHeight;\t// force refresh\n\n\t\tif ( this.options.listenX ) {\n\t\t\tthis.wrapperWidth = this.wrapper.clientWidth;\n\t\t\tif ( this.options.resize ) {\n\t\t\t\tthis.indicatorWidth = Math.max(Math.round(this.wrapperWidth * this.wrapperWidth / (this.scroller.scrollerWidth || this.wrapperWidth || 1)), 8);\n\t\t\t\tthis.indicatorStyle.width = this.indicatorWidth + 'px';\n\t\t\t} else {\n\t\t\t\tthis.indicatorWidth = this.indicator.clientWidth;\n\t\t\t}\n\n\t\t\tthis.maxPosX = this.wrapperWidth - this.indicatorWidth;\n\n\t\t\tif ( this.options.shrink == 'clip' ) {\n\t\t\t\tthis.minBoundaryX = -this.indicatorWidth + 8;\n\t\t\t\tthis.maxBoundaryX = this.wrapperWidth - 8;\n\t\t\t} else {\n\t\t\t\tthis.minBoundaryX = 0;\n\t\t\t\tthis.maxBoundaryX = this.maxPosX;\n\t\t\t}\n\n\t\t\tthis.sizeRatioX = this.options.speedRatioX || (this.scroller.maxScrollX && (this.maxPosX / this.scroller.maxScrollX));\n\t\t}\n\n\t\tif ( this.options.listenY ) {\n\t\t\tthis.wrapperHeight = this.wrapper.clientHeight;\n\t\t\tif ( this.options.resize ) {\n\t\t\t\tthis.indicatorHeight = Math.max(Math.round(this.wrapperHeight * this.wrapperHeight / (this.scroller.scrollerHeight || this.wrapperHeight || 1)), 8);\n\t\t\t\tthis.indicatorStyle.height = this.indicatorHeight + 'px';\n\t\t\t} else {\n\t\t\t\tthis.indicatorHeight = this.indicator.clientHeight;\n\t\t\t}\n\n\t\t\tthis.maxPosY = this.wrapperHeight - this.indicatorHeight;\n\n\t\t\tif ( this.options.shrink == 'clip' ) {\n\t\t\t\tthis.minBoundaryY = -this.indicatorHeight + 8;\n\t\t\t\tthis.maxBoundaryY = this.wrapperHeight - 8;\n\t\t\t} else {\n\t\t\t\tthis.minBoundaryY = 0;\n\t\t\t\tthis.maxBoundaryY = this.maxPosY;\n\t\t\t}\n\n\t\t\tthis.maxPosY = this.wrapperHeight - this.indicatorHeight;\n\t\t\tthis.sizeRatioY = this.options.speedRatioY || (this.scroller.maxScrollY && (this.maxPosY / this.scroller.maxScrollY));\n\t\t}\n\n\t\tthis.updatePosition();\n\t},\n\n\tupdatePosition: function () {\n\t\tvar x = this.options.listenX && Math.round(this.sizeRatioX * this.scroller.x) || 0,\n\t\t\ty = this.options.listenY && Math.round(this.sizeRatioY * this.scroller.y) || 0;\n\n\t\tif ( !this.options.ignoreBoundaries ) {\n\t\t\tif ( x < this.minBoundaryX ) {\n\t\t\t\tif ( this.options.shrink == 'scale' ) {\n\t\t\t\t\tthis.width = Math.max(this.indicatorWidth + x, 8);\n\t\t\t\t\tthis.indicatorStyle.width = this.width + 'px';\n\t\t\t\t}\n\t\t\t\tx = this.minBoundaryX;\n\t\t\t} else if ( x > this.maxBoundaryX ) {\n\t\t\t\tif ( this.options.shrink == 'scale' ) {\n\t\t\t\t\tthis.width = Math.max(this.indicatorWidth - (x - this.maxPosX), 8);\n\t\t\t\t\tthis.indicatorStyle.width = this.width + 'px';\n\t\t\t\t\tx = this.maxPosX + this.indicatorWidth - this.width;\n\t\t\t\t} else {\n\t\t\t\t\tx = this.maxBoundaryX;\n\t\t\t\t}\n\t\t\t} else if ( this.options.shrink == 'scale' && this.width != this.indicatorWidth ) {\n\t\t\t\tthis.width = this.indicatorWidth;\n\t\t\t\tthis.indicatorStyle.width = this.width + 'px';\n\t\t\t}\n\n\t\t\tif ( y < this.minBoundaryY ) {\n\t\t\t\tif ( this.options.shrink == 'scale' ) {\n\t\t\t\t\tthis.height = Math.max(this.indicatorHeight + y * 3, 8);\n\t\t\t\t\tthis.indicatorStyle.height = this.height + 'px';\n\t\t\t\t}\n\t\t\t\ty = this.minBoundaryY;\n\t\t\t} else if ( y > this.maxBoundaryY ) {\n\t\t\t\tif ( this.options.shrink == 'scale' ) {\n\t\t\t\t\tthis.height = Math.max(this.indicatorHeight - (y - this.maxPosY) * 3, 8);\n\t\t\t\t\tthis.indicatorStyle.height = this.height + 'px';\n\t\t\t\t\ty = this.maxPosY + this.indicatorHeight - this.height;\n\t\t\t\t} else {\n\t\t\t\t\ty = this.maxBoundaryY;\n\t\t\t\t}\n\t\t\t} else if ( this.options.shrink == 'scale' && this.height != this.indicatorHeight ) {\n\t\t\t\tthis.height = this.indicatorHeight;\n\t\t\t\tthis.indicatorStyle.height = this.height + 'px';\n\t\t\t}\n\t\t}\n\n\t\tthis.x = x;\n\t\tthis.y = y;\n\n\t\tif ( this.scroller.options.useTransform ) {\n\t\t\tthis.indicatorStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.scroller.translateZ;\n\t\t} else {\n\t\t\tthis.indicatorStyle.left = x + 'px';\n\t\t\tthis.indicatorStyle.top = y + 'px';\n\t\t}\n\t},\n\n\t_pos: function (x, y) {\n\t\tif ( x < 0 ) {\n\t\t\tx = 0;\n\t\t} else if ( x > this.maxPosX ) {\n\t\t\tx = this.maxPosX;\n\t\t}\n\n\t\tif ( y < 0 ) {\n\t\t\ty = 0;\n\t\t} else if ( y > this.maxPosY ) {\n\t\t\ty = this.maxPosY;\n\t\t}\n\n\t\tx = this.options.listenX ? Math.round(x / this.sizeRatioX) : this.scroller.x;\n\t\ty = this.options.listenY ? Math.round(y / this.sizeRatioY) : this.scroller.y;\n\n\t\tthis.scroller.scrollTo(x, y);\n\t},\n\n\tfade: function (val, hold) {\n\t\tif ( hold && !this.visible ) {\n\t\t\treturn;\n\t\t}\n\n\t\tclearTimeout(this.fadeTimeout);\n\t\tthis.fadeTimeout = null;\n\n\t\tvar time = val ? 250 : 500,\n\t\t\tdelay = val ? 0 : 300;\n\n\t\tval = val ? '1' : '0';\n\n\t\tthis.wrapperStyle[utils.style.transitionDuration] = time + 'ms';\n\n\t\tthis.fadeTimeout = setTimeout((function (val) {\n\t\t\tthis.wrapperStyle.opacity = val;\n\t\t\tthis.visible = +val;\n\t\t}).bind(this, val), delay);\n\t}\n};\n\nIScroll.utils = utils;\n\nif ( typeof module != 'undefined' && module.exports ) {\n\tmodule.exports = IScroll;\n} else if ( typeof define == 'function' && define.amd ) {\n        define( function () { return IScroll; } );\n} else {\n\twindow.IScroll = IScroll;\n}\n\n})(window, document, Math);\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/assets/js/login.js",
    "content": "$(document).ready(function() {\n    $('.myapp-login').particleground({\n        // //粒子颜色\n        // dotColor: '#cbda5a',\n        // //线颜色\n        // lineColor: '#eda'\n        dotColor: '#bcbcbc',\n        lineColor: '#bcbcbc'\n    });\n    // $('.login-body').css({\n    //     // 'margin-top': -($('.login-body').height() * 3 )\n    //     'margin-top': -($(this).height()  )\n    //\n    // });\n});\n\n/**\n * Particleground\n *\n * @author Jonathan Nicol - @mrjnicol\n * @version 1.0.1\n * @description Creates a canvas based particle system background\n *\n * Inspired by:\n * http://requestlab.fr/\n * http://disruptivebydesign.com/\n *\n * @license The MIT License (MIT)\n *\n * Copyright (c) 2014 Jonathan Nicol - @mrjnicol\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!function(a){function b(b,d){function e(){if(w){$canvas=a('<canvas class=\"pg-canvas\"></canvas>'),v.prepend($canvas),p=$canvas[0],q=p.getContext(\"2d\"),f();for(var b=Math.round(p.width*p.height/d.density),c=0;b>c;c++){var e=new l;e.setStackPos(c),x.push(e)}a(window).on(\"resize\",function(){h()}),a(document).on(\"mousemove\",function(a){y=a.pageX,z=a.pageY}),B&&!A&&window.addEventListener(\"deviceorientation\",function(){D=Math.min(Math.max(-event.beta,-30),30),C=Math.min(Math.max(-event.gamma,-30),30)},!0),g(),o(\"onInit\")}}function f(){p.width=v.width(),p.height=v.height(),q.fillStyle=d.dotColor,q.strokeStyle=d.lineColor,q.lineWidth=d.lineWidth}function g(){if(w){s=a(window).width(),t=a(window).height(),q.clearRect(0,0,p.width,p.height);for(var b=0;b<x.length;b++)x[b].updatePosition();for(var b=0;b<x.length;b++)x[b].draw();E||(r=requestAnimationFrame(g))}}function h(){for(f(),i=x.length-1;i>=0;i--)(x[i].position.x>v.width()||x[i].position.y>v.height())&&x.splice(i,1);var a=Math.round(p.width*p.height/d.density);if(a>x.length)for(;a>x.length;){var b=new l;x.push(b)}else a<x.length&&x.splice(a);for(i=x.length-1;i>=0;i--)x[i].setStackPos(i)}function j(){E=!0}function k(){E=!1,g()}function l(){switch(this.stackPos,this.active=!0,this.layer=Math.ceil(3*Math.random()),this.parallaxOffsetX=0,this.parallaxOffsetY=0,this.position={x:Math.ceil(Math.random()*p.width),y:Math.ceil(Math.random()*p.height)},this.speed={},d.directionX){case\"left\":this.speed.x=+(-d.maxSpeedX+Math.random()*d.maxSpeedX-d.minSpeedX).toFixed(2);break;case\"right\":this.speed.x=+(Math.random()*d.maxSpeedX+d.minSpeedX).toFixed(2);break;default:this.speed.x=+(-d.maxSpeedX/2+Math.random()*d.maxSpeedX).toFixed(2),this.speed.x+=this.speed.x>0?d.minSpeedX:-d.minSpeedX}switch(d.directionY){case\"up\":this.speed.y=+(-d.maxSpeedY+Math.random()*d.maxSpeedY-d.minSpeedY).toFixed(2);break;case\"down\":this.speed.y=+(Math.random()*d.maxSpeedY+d.minSpeedY).toFixed(2);break;default:this.speed.y=+(-d.maxSpeedY/2+Math.random()*d.maxSpeedY).toFixed(2),this.speed.x+=this.speed.y>0?d.minSpeedY:-d.minSpeedY}}function m(a,b){return b?void(d[a]=b):d[a]}function n(){v.find(\".pg-canvas\").remove(),o(\"onDestroy\"),v.removeData(\"plugin_\"+c)}function o(a){void 0!==d[a]&&d[a].call(u)}var p,q,r,s,t,u=b,v=a(b),w=!!document.createElement(\"canvas\").getContext,x=[],y=0,z=0,A=!navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry|BB10|mobi|tablet|opera mini|nexus 7)/i),B=!!window.DeviceOrientationEvent,C=0,D=0,E=!1;return d=a.extend({},a.fn[c].defaults,d),l.prototype.draw=function(){q.beginPath(),q.arc(this.position.x+this.parallaxOffsetX,this.position.y+this.parallaxOffsetY,d.particleRadius/2,0,2*Math.PI,!0),q.closePath(),q.fill(),q.beginPath();for(var a=x.length-1;a>this.stackPos;a--){var b=x[a],c=this.position.x-b.position.x,e=this.position.y-b.position.y,f=Math.sqrt(c*c+e*e).toFixed(2);f<d.proximity&&(q.moveTo(this.position.x+this.parallaxOffsetX,this.position.y+this.parallaxOffsetY),d.curvedLines?q.quadraticCurveTo(Math.max(b.position.x,b.position.x),Math.min(b.position.y,b.position.y),b.position.x+b.parallaxOffsetX,b.position.y+b.parallaxOffsetY):q.lineTo(b.position.x+b.parallaxOffsetX,b.position.y+b.parallaxOffsetY))}q.stroke(),q.closePath()},l.prototype.updatePosition=function(){if(d.parallax){if(B&&!A){var a=(s-0)/60;pointerX=(C- -30)*a+0;var b=(t-0)/60;pointerY=(D- -30)*b+0}else pointerX=y,pointerY=z;this.parallaxTargX=(pointerX-s/2)/(d.parallaxMultiplier*this.layer),this.parallaxOffsetX+=(this.parallaxTargX-this.parallaxOffsetX)/10,this.parallaxTargY=(pointerY-t/2)/(d.parallaxMultiplier*this.layer),this.parallaxOffsetY+=(this.parallaxTargY-this.parallaxOffsetY)/10}switch(d.directionX){case\"left\":this.position.x+this.speed.x+this.parallaxOffsetX<0&&(this.position.x=v.width()-this.parallaxOffsetX);break;case\"right\":this.position.x+this.speed.x+this.parallaxOffsetX>v.width()&&(this.position.x=0-this.parallaxOffsetX);break;default:(this.position.x+this.speed.x+this.parallaxOffsetX>v.width()||this.position.x+this.speed.x+this.parallaxOffsetX<0)&&(this.speed.x=-this.speed.x)}switch(d.directionY){case\"up\":this.position.y+this.speed.y+this.parallaxOffsetY<0&&(this.position.y=v.height()-this.parallaxOffsetY);break;case\"down\":this.position.y+this.speed.y+this.parallaxOffsetY>v.height()&&(this.position.y=0-this.parallaxOffsetY);break;default:(this.position.y+this.speed.y+this.parallaxOffsetY>v.height()||this.position.y+this.speed.y+this.parallaxOffsetY<0)&&(this.speed.y=-this.speed.y)}this.position.x+=this.speed.x,this.position.y+=this.speed.y},l.prototype.setStackPos=function(a){this.stackPos=a},e(),{option:m,destroy:n,start:k,pause:j}}var c=\"particleground\";a.fn[c]=function(d){if(\"string\"==typeof arguments[0]){var e,f=arguments[0],g=Array.prototype.slice.call(arguments,1);return this.each(function(){a.data(this,\"plugin_\"+c)&&\"function\"==typeof a.data(this,\"plugin_\"+c)[f]&&(e=a.data(this,\"plugin_\"+c)[f].apply(this,g))}),void 0!==e?e:this}return\"object\"!=typeof d&&d?void 0:this.each(function(){a.data(this,\"plugin_\"+c)||a.data(this,\"plugin_\"+c,new b(this,d))})},a.fn[c].defaults={minSpeedX:.1,maxSpeedX:.7,minSpeedY:.1,maxSpeedY:.7,directionX:\"center\",directionY:\"center\",density:1e4,dotColor:\"#666666\",lineColor:\"#666666\",particleRadius:7,lineWidth:1,curvedLines:!1,proximity:100,parallax:!0,parallaxMultiplier:5,onInit:function(){},onDestroy:function(){}}}(jQuery),/**\n * requestAnimationFrame polyfill by Erik M枚ller. fixes from Paul Irish and Tino Zijdel\n * @see: http://paulirish.com/2011/requestanimationframe-for-smart-animating/\n * @see: http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating\n * @license: MIT license\n */\nfunction(){for(var a=0,b=[\"ms\",\"moz\",\"webkit\",\"o\"],c=0;c<b.length&&!window.requestAnimationFrame;++c)window.requestAnimationFrame=window[b[c]+\"RequestAnimationFrame\"],window.cancelAnimationFrame=window[b[c]+\"CancelAnimationFrame\"]||window[b[c]+\"CancelRequestAnimationFrame\"];window.requestAnimationFrame||(window.requestAnimationFrame=function(b){var c=(new Date).getTime(),d=Math.max(0,16-(c-a)),e=window.setTimeout(function(){b(c+d)},d);return a=c+d,e}),window.cancelAnimationFrame||(window.cancelAnimationFrame=function(a){clearTimeout(a)})}();"
  },
  {
    "path": "open-layui-web/src/main/view/static/assets/js/summernote.js",
    "content": "/**\n * Super simple wysiwyg editor v0.8.2\n * http://summernote.org/\n *\n * summernote.js\n * Copyright 2013-2016 Alan Hong. and other contributors\n * summernote may be freely distributed under the MIT license./\n *\n * Date: 2016-08-07T05:11Z\n */\n(function (factory) {\n  /* global define */\n  if (typeof define === 'function' && define.amd) {\n    // AMD. Register as an anonymous module.\n    define(['jquery'], factory);\n  } else if (typeof module === 'object' && module.exports) {\n    // Node/CommonJS\n    module.exports = factory(require('jquery'));\n  } else {\n    // Browser globals\n    factory(window.jQuery);\n  }\n}(function ($) {\n  'use strict';\n\n  /**\n   * @class core.func\n   *\n   * func utils (for high-order func's arg)\n   *\n   * @singleton\n   * @alternateClassName func\n   */\n  var func = (function () {\n    var eq = function (itemA) {\n      return function (itemB) {\n        return itemA === itemB;\n      };\n    };\n\n    var eq2 = function (itemA, itemB) {\n      return itemA === itemB;\n    };\n\n    var peq2 = function (propName) {\n      return function (itemA, itemB) {\n        return itemA[propName] === itemB[propName];\n      };\n    };\n\n    var ok = function () {\n      return true;\n    };\n\n    var fail = function () {\n      return false;\n    };\n\n    var not = function (f) {\n      return function () {\n        return !f.apply(f, arguments);\n      };\n    };\n\n    var and = function (fA, fB) {\n      return function (item) {\n        return fA(item) && fB(item);\n      };\n    };\n\n    var self = function (a) {\n      return a;\n    };\n\n    var invoke = function (obj, method) {\n      return function () {\n        return obj[method].apply(obj, arguments);\n      };\n    };\n\n    var idCounter = 0;\n\n    /**\n     * generate a globally-unique id\n     *\n     * @param {String} [prefix]\n     */\n    var uniqueId = function (prefix) {\n      var id = ++idCounter + '';\n      return prefix ? prefix + id : id;\n    };\n\n    /**\n     * returns bnd (bounds) from rect\n     *\n     * - IE Compatibility Issue: http://goo.gl/sRLOAo\n     * - Scroll Issue: http://goo.gl/sNjUc\n     *\n     * @param {Rect} rect\n     * @return {Object} bounds\n     * @return {Number} bounds.top\n     * @return {Number} bounds.left\n     * @return {Number} bounds.width\n     * @return {Number} bounds.height\n     */\n    var rect2bnd = function (rect) {\n      var $document = $(document);\n      return {\n        top: rect.top + $document.scrollTop(),\n        left: rect.left + $document.scrollLeft(),\n        width: rect.right - rect.left,\n        height: rect.bottom - rect.top\n      };\n    };\n\n    /**\n     * returns a copy of the object where the keys have become the values and the values the keys.\n     * @param {Object} obj\n     * @return {Object}\n     */\n    var invertObject = function (obj) {\n      var inverted = {};\n      for (var key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          inverted[obj[key]] = key;\n        }\n      }\n      return inverted;\n    };\n\n    /**\n     * @param {String} namespace\n     * @param {String} [prefix]\n     * @return {String}\n     */\n    var namespaceToCamel = function (namespace, prefix) {\n      prefix = prefix || '';\n      return prefix + namespace.split('.').map(function (name) {\n        return name.substring(0, 1).toUpperCase() + name.substring(1);\n      }).join('');\n    };\n\n    /**\n     * Returns a function, that, as long as it continues to be invoked, will not\n     * be triggered. The function will be called after it stops being called for\n     * N milliseconds. If `immediate` is passed, trigger the function on the\n     * leading edge, instead of the trailing.\n     * @param {Function} func\n     * @param {Number} wait\n     * @param {Boolean} immediate\n     * @return {Function}\n     */\n    var debounce = function (func, wait, immediate) {\n      var timeout;\n      return function () {\n        var context = this, args = arguments;\n        var later = function () {\n          timeout = null;\n          if (!immediate) {\n            func.apply(context, args);\n          }\n        };\n        var callNow = immediate && !timeout;\n        clearTimeout(timeout);\n        timeout = setTimeout(later, wait);\n        if (callNow) {\n          func.apply(context, args);\n        }\n      };\n    };\n\n    return {\n      eq: eq,\n      eq2: eq2,\n      peq2: peq2,\n      ok: ok,\n      fail: fail,\n      self: self,\n      not: not,\n      and: and,\n      invoke: invoke,\n      uniqueId: uniqueId,\n      rect2bnd: rect2bnd,\n      invertObject: invertObject,\n      namespaceToCamel: namespaceToCamel,\n      debounce: debounce\n    };\n  })();\n\n  /**\n   * @class core.list\n   *\n   * list utils\n   *\n   * @singleton\n   * @alternateClassName list\n   */\n  var list = (function () {\n    /**\n     * returns the first item of an array.\n     *\n     * @param {Array} array\n     */\n    var head = function (array) {\n      return array[0];\n    };\n\n    /**\n     * returns the last item of an array.\n     *\n     * @param {Array} array\n     */\n    var last = function (array) {\n      return array[array.length - 1];\n    };\n\n    /**\n     * returns everything but the last entry of the array.\n     *\n     * @param {Array} array\n     */\n    var initial = function (array) {\n      return array.slice(0, array.length - 1);\n    };\n\n    /**\n     * returns the rest of the items in an array.\n     *\n     * @param {Array} array\n     */\n    var tail = function (array) {\n      return array.slice(1);\n    };\n\n    /**\n     * returns item of array\n     */\n    var find = function (array, pred) {\n      for (var idx = 0, len = array.length; idx < len; idx ++) {\n        var item = array[idx];\n        if (pred(item)) {\n          return item;\n        }\n      }\n    };\n\n    /**\n     * returns true if all of the values in the array pass the predicate truth test.\n     */\n    var all = function (array, pred) {\n      for (var idx = 0, len = array.length; idx < len; idx ++) {\n        if (!pred(array[idx])) {\n          return false;\n        }\n      }\n      return true;\n    };\n\n    /**\n     * returns index of item\n     */\n    var indexOf = function (array, item) {\n      return $.inArray(item, array);\n    };\n\n    /**\n     * returns true if the value is present in the list.\n     */\n    var contains = function (array, item) {\n      return indexOf(array, item) !== -1;\n    };\n\n    /**\n     * get sum from a list\n     *\n     * @param {Array} array - array\n     * @param {Function} fn - iterator\n     */\n    var sum = function (array, fn) {\n      fn = fn || func.self;\n      return array.reduce(function (memo, v) {\n        return memo + fn(v);\n      }, 0);\n    };\n  \n    /**\n     * returns a copy of the collection with array type.\n     * @param {Collection} collection - collection eg) node.childNodes, ...\n     */\n    var from = function (collection) {\n      var result = [], idx = -1, length = collection.length;\n      while (++idx < length) {\n        result[idx] = collection[idx];\n      }\n      return result;\n    };\n\n    /**\n     * returns whether list is empty or not\n     */\n    var isEmpty = function (array) {\n      return !array || !array.length;\n    };\n  \n    /**\n     * cluster elements by predicate function.\n     *\n     * @param {Array} array - array\n     * @param {Function} fn - predicate function for cluster rule\n     * @param {Array[]}\n     */\n    var clusterBy = function (array, fn) {\n      if (!array.length) { return []; }\n      var aTail = tail(array);\n      return aTail.reduce(function (memo, v) {\n        var aLast = last(memo);\n        if (fn(last(aLast), v)) {\n          aLast[aLast.length] = v;\n        } else {\n          memo[memo.length] = [v];\n        }\n        return memo;\n      }, [[head(array)]]);\n    };\n  \n    /**\n     * returns a copy of the array with all false values removed\n     *\n     * @param {Array} array - array\n     * @param {Function} fn - predicate function for cluster rule\n     */\n    var compact = function (array) {\n      var aResult = [];\n      for (var idx = 0, len = array.length; idx < len; idx ++) {\n        if (array[idx]) { aResult.push(array[idx]); }\n      }\n      return aResult;\n    };\n\n    /**\n     * produces a duplicate-free version of the array\n     *\n     * @param {Array} array\n     */\n    var unique = function (array) {\n      var results = [];\n\n      for (var idx = 0, len = array.length; idx < len; idx ++) {\n        if (!contains(results, array[idx])) {\n          results.push(array[idx]);\n        }\n      }\n\n      return results;\n    };\n\n    /**\n     * returns next item.\n     * @param {Array} array\n     */\n    var next = function (array, item) {\n      var idx = indexOf(array, item);\n      if (idx === -1) { return null; }\n\n      return array[idx + 1];\n    };\n\n    /**\n     * returns prev item.\n     * @param {Array} array\n     */\n    var prev = function (array, item) {\n      var idx = indexOf(array, item);\n      if (idx === -1) { return null; }\n\n      return array[idx - 1];\n    };\n\n    return { head: head, last: last, initial: initial, tail: tail,\n             prev: prev, next: next, find: find, contains: contains,\n             all: all, sum: sum, from: from, isEmpty: isEmpty,\n             clusterBy: clusterBy, compact: compact, unique: unique };\n  })();\n\n  var isSupportAmd = typeof define === 'function' && define.amd;\n\n  /**\n   * returns whether font is installed or not.\n   *\n   * @param {String} fontName\n   * @return {Boolean}\n   */\n  var isFontInstalled = function (fontName) {\n    var testFontName = fontName === 'Comic Sans MS' ? 'Courier New' : 'Comic Sans MS';\n    var $tester = $('<div>').css({\n      position: 'absolute',\n      left: '-9999px',\n      top: '-9999px',\n      fontSize: '200px'\n    }).text('mmmmmmmmmwwwwwww').appendTo(document.body);\n\n    var originalWidth = $tester.css('fontFamily', testFontName).width();\n    var width = $tester.css('fontFamily', fontName + ',' + testFontName).width();\n\n    $tester.remove();\n\n    return originalWidth !== width;\n  };\n\n  var userAgent = navigator.userAgent;\n  var isMSIE = /MSIE|Trident/i.test(userAgent);\n  var browserVersion;\n  if (isMSIE) {\n    var matches = /MSIE (\\d+[.]\\d+)/.exec(userAgent);\n    if (matches) {\n      browserVersion = parseFloat(matches[1]);\n    }\n    matches = /Trident\\/.*rv:([0-9]{1,}[\\.0-9]{0,})/.exec(userAgent);\n    if (matches) {\n      browserVersion = parseFloat(matches[1]);\n    }\n  }\n\n  var isEdge = /Edge\\/\\d+/.test(userAgent);\n\n  var hasCodeMirror = !!window.CodeMirror;\n  if (!hasCodeMirror && isSupportAmd && typeof require !== 'undefined') {\n    if (typeof require.resolve !== 'undefined') {\n      try {\n        // If CodeMirror can't be resolved, `require.resolve` will throw an\n        // exception and `hasCodeMirror` won't be set to `true`.\n        require.resolve('codemirror');\n        hasCodeMirror = true;\n      } catch (e) {\n        // Do nothing.\n      }\n    } else if (typeof eval('require').specified !== 'undefined') {\n      hasCodeMirror = eval('require').specified('codemirror');\n    }\n  }\n\n  /**\n   * @class core.agent\n   *\n   * Object which check platform and agent\n   *\n   * @singleton\n   * @alternateClassName agent\n   */\n  var agent = {\n    isMac: navigator.appVersion.indexOf('Mac') > -1,\n    isMSIE: isMSIE,\n    isEdge: isEdge,\n    isFF: !isEdge && /firefox/i.test(userAgent),\n    isPhantom: /PhantomJS/i.test(userAgent),\n    isWebkit: !isEdge && /webkit/i.test(userAgent),\n    isChrome: !isEdge && /chrome/i.test(userAgent),\n    isSafari: !isEdge && /safari/i.test(userAgent),\n    browserVersion: browserVersion,\n    jqueryVersion: parseFloat($.fn.jquery),\n    isSupportAmd: isSupportAmd,\n    hasCodeMirror: hasCodeMirror,\n    isFontInstalled: isFontInstalled,\n    isW3CRangeSupport: !!document.createRange\n  };\n\n\n  var NBSP_CHAR = String.fromCharCode(160);\n  var ZERO_WIDTH_NBSP_CHAR = '\\ufeff';\n\n  /**\n   * @class core.dom\n   *\n   * Dom functions\n   *\n   * @singleton\n   * @alternateClassName dom\n   */\n  var dom = (function () {\n    /**\n     * @method isEditable\n     *\n     * returns whether node is `note-editable` or not.\n     *\n     * @param {Node} node\n     * @return {Boolean}\n     */\n    var isEditable = function (node) {\n      return node && $(node).hasClass('note-editable');\n    };\n\n    /**\n     * @method isControlSizing\n     *\n     * returns whether node is `note-control-sizing` or not.\n     *\n     * @param {Node} node\n     * @return {Boolean}\n     */\n    var isControlSizing = function (node) {\n      return node && $(node).hasClass('note-control-sizing');\n    };\n\n    /**\n     * @method makePredByNodeName\n     *\n     * returns predicate which judge whether nodeName is same\n     *\n     * @param {String} nodeName\n     * @return {Function}\n     */\n    var makePredByNodeName = function (nodeName) {\n      nodeName = nodeName.toUpperCase();\n      return function (node) {\n        return node && node.nodeName.toUpperCase() === nodeName;\n      };\n    };\n\n    /**\n     * @method isText\n     *\n     *\n     *\n     * @param {Node} node\n     * @return {Boolean} true if node's type is text(3)\n     */\n    var isText = function (node) {\n      return node && node.nodeType === 3;\n    };\n\n    /**\n     * @method isElement\n     *\n     *\n     *\n     * @param {Node} node\n     * @return {Boolean} true if node's type is element(1)\n     */\n    var isElement = function (node) {\n      return node && node.nodeType === 1;\n    };\n\n    /**\n     * ex) br, col, embed, hr, img, input, ...\n     * @see http://www.w3.org/html/wg/drafts/html/master/syntax.html#void-elements\n     */\n    var isVoid = function (node) {\n      return node && /^BR|^IMG|^HR|^IFRAME|^BUTTON/.test(node.nodeName.toUpperCase());\n    };\n\n    var isPara = function (node) {\n      if (isEditable(node)) {\n        return false;\n      }\n\n      // Chrome(v31.0), FF(v25.0.1) use DIV for paragraph\n      return node && /^DIV|^P|^LI|^H[1-7]/.test(node.nodeName.toUpperCase());\n    };\n\n    var isHeading = function (node) {\n      return node && /^H[1-7]/.test(node.nodeName.toUpperCase());\n    };\n\n    var isPre = makePredByNodeName('PRE');\n\n    var isLi = makePredByNodeName('LI');\n\n    var isPurePara = function (node) {\n      return isPara(node) && !isLi(node);\n    };\n\n    var isTable = makePredByNodeName('TABLE');\n\n    var isData = makePredByNodeName('DATA');\n\n    var isInline = function (node) {\n      return !isBodyContainer(node) &&\n             !isList(node) &&\n             !isHr(node) &&\n             !isPara(node) &&\n             !isTable(node) &&\n             !isBlockquote(node) &&\n             !isData(node);\n    };\n\n    var isList = function (node) {\n      return node && /^UL|^OL/.test(node.nodeName.toUpperCase());\n    };\n\n    var isHr = makePredByNodeName('HR');\n\n    var isCell = function (node) {\n      return node && /^TD|^TH/.test(node.nodeName.toUpperCase());\n    };\n\n    var isBlockquote = makePredByNodeName('BLOCKQUOTE');\n\n    var isBodyContainer = function (node) {\n      return isCell(node) || isBlockquote(node) || isEditable(node);\n    };\n\n    var isAnchor = makePredByNodeName('A');\n\n    var isParaInline = function (node) {\n      return isInline(node) && !!ancestor(node, isPara);\n    };\n\n    var isBodyInline = function (node) {\n      return isInline(node) && !ancestor(node, isPara);\n    };\n\n    var isBody = makePredByNodeName('BODY');\n\n    /**\n     * returns whether nodeB is closest sibling of nodeA\n     *\n     * @param {Node} nodeA\n     * @param {Node} nodeB\n     * @return {Boolean}\n     */\n    var isClosestSibling = function (nodeA, nodeB) {\n      return nodeA.nextSibling === nodeB ||\n             nodeA.previousSibling === nodeB;\n    };\n\n    /**\n     * returns array of closest siblings with node\n     *\n     * @param {Node} node\n     * @param {function} [pred] - predicate function\n     * @return {Node[]}\n     */\n    var withClosestSiblings = function (node, pred) {\n      pred = pred || func.ok;\n\n      var siblings = [];\n      if (node.previousSibling && pred(node.previousSibling)) {\n        siblings.push(node.previousSibling);\n      }\n      siblings.push(node);\n      if (node.nextSibling && pred(node.nextSibling)) {\n        siblings.push(node.nextSibling);\n      }\n      return siblings;\n    };\n\n    /**\n     * blank HTML for cursor position\n     * - [workaround] old IE only works with &nbsp;\n     * - [workaround] IE11 and other browser works with bogus br\n     */\n    var blankHTML = agent.isMSIE && agent.browserVersion < 11 ? '&nbsp;' : '<br>';\n\n    /**\n     * @method nodeLength\n     *\n     * returns #text's text size or element's childNodes size\n     *\n     * @param {Node} node\n     */\n    var nodeLength = function (node) {\n      if (isText(node)) {\n        return node.nodeValue.length;\n      }\n      \n      if (node) {\n        return node.childNodes.length;\n      }\n      \n      return 0;\n      \n    };\n\n    /**\n     * returns whether node is empty or not.\n     *\n     * @param {Node} node\n     * @return {Boolean}\n     */\n    var isEmpty = function (node) {\n      var len = nodeLength(node);\n\n      if (len === 0) {\n        return true;\n      } else if (!isText(node) && len === 1 && node.innerHTML === blankHTML) {\n        // ex) <p><br></p>, <span><br></span>\n        return true;\n      } else if (list.all(node.childNodes, isText) && node.innerHTML === '') {\n        // ex) <p></p>, <span></span>\n        return true;\n      }\n\n      return false;\n    };\n\n    /**\n     * padding blankHTML if node is empty (for cursor position)\n     */\n    var paddingBlankHTML = function (node) {\n      if (!isVoid(node) && !nodeLength(node)) {\n        node.innerHTML = blankHTML;\n      }\n    };\n\n    /**\n     * find nearest ancestor predicate hit\n     *\n     * @param {Node} node\n     * @param {Function} pred - predicate function\n     */\n    var ancestor = function (node, pred) {\n      while (node) {\n        if (pred(node)) { return node; }\n        if (isEditable(node)) { break; }\n\n        node = node.parentNode;\n      }\n      return null;\n    };\n\n    /**\n     * find nearest ancestor only single child blood line and predicate hit\n     *\n     * @param {Node} node\n     * @param {Function} pred - predicate function\n     */\n    var singleChildAncestor = function (node, pred) {\n      node = node.parentNode;\n\n      while (node) {\n        if (nodeLength(node) !== 1) { break; }\n        if (pred(node)) { return node; }\n        if (isEditable(node)) { break; }\n\n        node = node.parentNode;\n      }\n      return null;\n    };\n\n    /**\n     * returns new array of ancestor nodes (until predicate hit).\n     *\n     * @param {Node} node\n     * @param {Function} [optional] pred - predicate function\n     */\n    var listAncestor = function (node, pred) {\n      pred = pred || func.fail;\n\n      var ancestors = [];\n      ancestor(node, function (el) {\n        if (!isEditable(el)) {\n          ancestors.push(el);\n        }\n\n        return pred(el);\n      });\n      return ancestors;\n    };\n\n    /**\n     * find farthest ancestor predicate hit\n     */\n    var lastAncestor = function (node, pred) {\n      var ancestors = listAncestor(node);\n      return list.last(ancestors.filter(pred));\n    };\n\n    /**\n     * returns common ancestor node between two nodes.\n     *\n     * @param {Node} nodeA\n     * @param {Node} nodeB\n     */\n    var commonAncestor = function (nodeA, nodeB) {\n      var ancestors = listAncestor(nodeA);\n      for (var n = nodeB; n; n = n.parentNode) {\n        if ($.inArray(n, ancestors) > -1) { return n; }\n      }\n      return null; // difference document area\n    };\n\n    /**\n     * listing all previous siblings (until predicate hit).\n     *\n     * @param {Node} node\n     * @param {Function} [optional] pred - predicate function\n     */\n    var listPrev = function (node, pred) {\n      pred = pred || func.fail;\n\n      var nodes = [];\n      while (node) {\n        if (pred(node)) { break; }\n        nodes.push(node);\n        node = node.previousSibling;\n      }\n      return nodes;\n    };\n\n    /**\n     * listing next siblings (until predicate hit).\n     *\n     * @param {Node} node\n     * @param {Function} [pred] - predicate function\n     */\n    var listNext = function (node, pred) {\n      pred = pred || func.fail;\n\n      var nodes = [];\n      while (node) {\n        if (pred(node)) { break; }\n        nodes.push(node);\n        node = node.nextSibling;\n      }\n      return nodes;\n    };\n\n    /**\n     * listing descendant nodes\n     *\n     * @param {Node} node\n     * @param {Function} [pred] - predicate function\n     */\n    var listDescendant = function (node, pred) {\n      var descendants = [];\n      pred = pred || func.ok;\n\n      // start DFS(depth first search) with node\n      (function fnWalk(current) {\n        if (node !== current && pred(current)) {\n          descendants.push(current);\n        }\n        for (var idx = 0, len = current.childNodes.length; idx < len; idx++) {\n          fnWalk(current.childNodes[idx]);\n        }\n      })(node);\n\n      return descendants;\n    };\n\n    /**\n     * wrap node with new tag.\n     *\n     * @param {Node} node\n     * @param {Node} tagName of wrapper\n     * @return {Node} - wrapper\n     */\n    var wrap = function (node, wrapperName) {\n      var parent = node.parentNode;\n      var wrapper = $('<' + wrapperName + '>')[0];\n\n      parent.insertBefore(wrapper, node);\n      wrapper.appendChild(node);\n\n      return wrapper;\n    };\n\n    /**\n     * insert node after preceding\n     *\n     * @param {Node} node\n     * @param {Node} preceding - predicate function\n     */\n    var insertAfter = function (node, preceding) {\n      var next = preceding.nextSibling, parent = preceding.parentNode;\n      if (next) {\n        parent.insertBefore(node, next);\n      } else {\n        parent.appendChild(node);\n      }\n      return node;\n    };\n\n    /**\n     * append elements.\n     *\n     * @param {Node} node\n     * @param {Collection} aChild\n     */\n    var appendChildNodes = function (node, aChild) {\n      $.each(aChild, function (idx, child) {\n        node.appendChild(child);\n      });\n      return node;\n    };\n\n    /**\n     * returns whether boundaryPoint is left edge or not.\n     *\n     * @param {BoundaryPoint} point\n     * @return {Boolean}\n     */\n    var isLeftEdgePoint = function (point) {\n      return point.offset === 0;\n    };\n\n    /**\n     * returns whether boundaryPoint is right edge or not.\n     *\n     * @param {BoundaryPoint} point\n     * @return {Boolean}\n     */\n    var isRightEdgePoint = function (point) {\n      return point.offset === nodeLength(point.node);\n    };\n\n    /**\n     * returns whether boundaryPoint is edge or not.\n     *\n     * @param {BoundaryPoint} point\n     * @return {Boolean}\n     */\n    var isEdgePoint = function (point) {\n      return isLeftEdgePoint(point) || isRightEdgePoint(point);\n    };\n\n    /**\n     * returns whether node is left edge of ancestor or not.\n     *\n     * @param {Node} node\n     * @param {Node} ancestor\n     * @return {Boolean}\n     */\n    var isLeftEdgeOf = function (node, ancestor) {\n      while (node && node !== ancestor) {\n        if (position(node) !== 0) {\n          return false;\n        }\n        node = node.parentNode;\n      }\n\n      return true;\n    };\n\n    /**\n     * returns whether node is right edge of ancestor or not.\n     *\n     * @param {Node} node\n     * @param {Node} ancestor\n     * @return {Boolean}\n     */\n    var isRightEdgeOf = function (node, ancestor) {\n      if (!ancestor) {\n        return false;\n      }\n      while (node && node !== ancestor) {\n        if (position(node) !== nodeLength(node.parentNode) - 1) {\n          return false;\n        }\n        node = node.parentNode;\n      }\n\n      return true;\n    };\n\n    /**\n     * returns whether point is left edge of ancestor or not.\n     * @param {BoundaryPoint} point\n     * @param {Node} ancestor\n     * @return {Boolean}\n     */\n    var isLeftEdgePointOf = function (point, ancestor) {\n      return isLeftEdgePoint(point) && isLeftEdgeOf(point.node, ancestor);\n    };\n\n    /**\n     * returns whether point is right edge of ancestor or not.\n     * @param {BoundaryPoint} point\n     * @param {Node} ancestor\n     * @return {Boolean}\n     */\n    var isRightEdgePointOf = function (point, ancestor) {\n      return isRightEdgePoint(point) && isRightEdgeOf(point.node, ancestor);\n    };\n\n    /**\n     * returns offset from parent.\n     *\n     * @param {Node} node\n     */\n    var position = function (node) {\n      var offset = 0;\n      while ((node = node.previousSibling)) {\n        offset += 1;\n      }\n      return offset;\n    };\n\n    var hasChildren = function (node) {\n      return !!(node && node.childNodes && node.childNodes.length);\n    };\n\n    /**\n     * returns previous boundaryPoint\n     *\n     * @param {BoundaryPoint} point\n     * @param {Boolean} isSkipInnerOffset\n     * @return {BoundaryPoint}\n     */\n    var prevPoint = function (point, isSkipInnerOffset) {\n      var node, offset;\n\n      if (point.offset === 0) {\n        if (isEditable(point.node)) {\n          return null;\n        }\n\n        node = point.node.parentNode;\n        offset = position(point.node);\n      } else if (hasChildren(point.node)) {\n        node = point.node.childNodes[point.offset - 1];\n        offset = nodeLength(node);\n      } else {\n        node = point.node;\n        offset = isSkipInnerOffset ? 0 : point.offset - 1;\n      }\n\n      return {\n        node: node,\n        offset: offset\n      };\n    };\n\n    /**\n     * returns next boundaryPoint\n     *\n     * @param {BoundaryPoint} point\n     * @param {Boolean} isSkipInnerOffset\n     * @return {BoundaryPoint}\n     */\n    var nextPoint = function (point, isSkipInnerOffset) {\n      var node, offset;\n\n      if (nodeLength(point.node) === point.offset) {\n        if (isEditable(point.node)) {\n          return null;\n        }\n\n        node = point.node.parentNode;\n        offset = position(point.node) + 1;\n      } else if (hasChildren(point.node)) {\n        node = point.node.childNodes[point.offset];\n        offset = 0;\n      } else {\n        node = point.node;\n        offset = isSkipInnerOffset ? nodeLength(point.node) : point.offset + 1;\n      }\n\n      return {\n        node: node,\n        offset: offset\n      };\n    };\n\n    /**\n     * returns whether pointA and pointB is same or not.\n     *\n     * @param {BoundaryPoint} pointA\n     * @param {BoundaryPoint} pointB\n     * @return {Boolean}\n     */\n    var isSamePoint = function (pointA, pointB) {\n      return pointA.node === pointB.node && pointA.offset === pointB.offset;\n    };\n\n    /**\n     * returns whether point is visible (can set cursor) or not.\n     *\n     * @param {BoundaryPoint} point\n     * @return {Boolean}\n     */\n    var isVisiblePoint = function (point) {\n      if (isText(point.node) || !hasChildren(point.node) || isEmpty(point.node)) {\n        return true;\n      }\n\n      var leftNode = point.node.childNodes[point.offset - 1];\n      var rightNode = point.node.childNodes[point.offset];\n      if ((!leftNode || isVoid(leftNode)) && (!rightNode || isVoid(rightNode))) {\n        return true;\n      }\n\n      return false;\n    };\n\n    /**\n     * @method prevPointUtil\n     *\n     * @param {BoundaryPoint} point\n     * @param {Function} pred\n     * @return {BoundaryPoint}\n     */\n    var prevPointUntil = function (point, pred) {\n      while (point) {\n        if (pred(point)) {\n          return point;\n        }\n\n        point = prevPoint(point);\n      }\n\n      return null;\n    };\n\n    /**\n     * @method nextPointUntil\n     *\n     * @param {BoundaryPoint} point\n     * @param {Function} pred\n     * @return {BoundaryPoint}\n     */\n    var nextPointUntil = function (point, pred) {\n      while (point) {\n        if (pred(point)) {\n          return point;\n        }\n\n        point = nextPoint(point);\n      }\n\n      return null;\n    };\n\n    /**\n     * returns whether point has character or not.\n     *\n     * @param {Point} point\n     * @return {Boolean}\n     */\n    var isCharPoint = function (point) {\n      if (!isText(point.node)) {\n        return false;\n      }\n\n      var ch = point.node.nodeValue.charAt(point.offset - 1);\n      return ch && (ch !== ' ' && ch !== NBSP_CHAR);\n    };\n\n    /**\n     * @method walkPoint\n     *\n     * @param {BoundaryPoint} startPoint\n     * @param {BoundaryPoint} endPoint\n     * @param {Function} handler\n     * @param {Boolean} isSkipInnerOffset\n     */\n    var walkPoint = function (startPoint, endPoint, handler, isSkipInnerOffset) {\n      var point = startPoint;\n\n      while (point) {\n        handler(point);\n\n        if (isSamePoint(point, endPoint)) {\n          break;\n        }\n\n        var isSkipOffset = isSkipInnerOffset &&\n                           startPoint.node !== point.node &&\n                           endPoint.node !== point.node;\n        point = nextPoint(point, isSkipOffset);\n      }\n    };\n\n    /**\n     * @method makeOffsetPath\n     *\n     * return offsetPath(array of offset) from ancestor\n     *\n     * @param {Node} ancestor - ancestor node\n     * @param {Node} node\n     */\n    var makeOffsetPath = function (ancestor, node) {\n      var ancestors = listAncestor(node, func.eq(ancestor));\n      return ancestors.map(position).reverse();\n    };\n\n    /**\n     * @method fromOffsetPath\n     *\n     * return element from offsetPath(array of offset)\n     *\n     * @param {Node} ancestor - ancestor node\n     * @param {array} offsets - offsetPath\n     */\n    var fromOffsetPath = function (ancestor, offsets) {\n      var current = ancestor;\n      for (var i = 0, len = offsets.length; i < len; i++) {\n        if (current.childNodes.length <= offsets[i]) {\n          current = current.childNodes[current.childNodes.length - 1];\n        } else {\n          current = current.childNodes[offsets[i]];\n        }\n      }\n      return current;\n    };\n\n    /**\n     * @method splitNode\n     *\n     * split element or #text\n     *\n     * @param {BoundaryPoint} point\n     * @param {Object} [options]\n     * @param {Boolean} [options.isSkipPaddingBlankHTML] - default: false\n     * @param {Boolean} [options.isNotSplitEdgePoint] - default: false\n     * @return {Node} right node of boundaryPoint\n     */\n    var splitNode = function (point, options) {\n      var isSkipPaddingBlankHTML = options && options.isSkipPaddingBlankHTML;\n      var isNotSplitEdgePoint = options && options.isNotSplitEdgePoint;\n\n      // edge case\n      if (isEdgePoint(point) && (isText(point.node) || isNotSplitEdgePoint)) {\n        if (isLeftEdgePoint(point)) {\n          return point.node;\n        } else if (isRightEdgePoint(point)) {\n          return point.node.nextSibling;\n        }\n      }\n\n      // split #text\n      if (isText(point.node)) {\n        return point.node.splitText(point.offset);\n      } else {\n        var childNode = point.node.childNodes[point.offset];\n        var clone = insertAfter(point.node.cloneNode(false), point.node);\n        appendChildNodes(clone, listNext(childNode));\n\n        if (!isSkipPaddingBlankHTML) {\n          paddingBlankHTML(point.node);\n          paddingBlankHTML(clone);\n        }\n\n        return clone;\n      }\n    };\n\n    /**\n     * @method splitTree\n     *\n     * split tree by point\n     *\n     * @param {Node} root - split root\n     * @param {BoundaryPoint} point\n     * @param {Object} [options]\n     * @param {Boolean} [options.isSkipPaddingBlankHTML] - default: false\n     * @param {Boolean} [options.isNotSplitEdgePoint] - default: false\n     * @return {Node} right node of boundaryPoint\n     */\n    var splitTree = function (root, point, options) {\n      // ex) [#text, <span>, <p>]\n      var ancestors = listAncestor(point.node, func.eq(root));\n\n      if (!ancestors.length) {\n        return null;\n      } else if (ancestors.length === 1) {\n        return splitNode(point, options);\n      }\n\n      return ancestors.reduce(function (node, parent) {\n        if (node === point.node) {\n          node = splitNode(point, options);\n        }\n\n        return splitNode({\n          node: parent,\n          offset: node ? dom.position(node) : nodeLength(parent)\n        }, options);\n      });\n    };\n\n    /**\n     * split point\n     *\n     * @param {Point} point\n     * @param {Boolean} isInline\n     * @return {Object}\n     */\n    var splitPoint = function (point, isInline) {\n      // find splitRoot, container\n      //  - inline: splitRoot is a child of paragraph\n      //  - block: splitRoot is a child of bodyContainer\n      var pred = isInline ? isPara : isBodyContainer;\n      var ancestors = listAncestor(point.node, pred);\n      var topAncestor = list.last(ancestors) || point.node;\n\n      var splitRoot, container;\n      if (pred(topAncestor)) {\n        splitRoot = ancestors[ancestors.length - 2];\n        container = topAncestor;\n      } else {\n        splitRoot = topAncestor;\n        container = splitRoot.parentNode;\n      }\n\n      // if splitRoot is exists, split with splitTree\n      var pivot = splitRoot && splitTree(splitRoot, point, {\n        isSkipPaddingBlankHTML: isInline,\n        isNotSplitEdgePoint: isInline\n      });\n\n      // if container is point.node, find pivot with point.offset\n      if (!pivot && container === point.node) {\n        pivot = point.node.childNodes[point.offset];\n      }\n\n      return {\n        rightNode: pivot,\n        container: container\n      };\n    };\n\n    var create = function (nodeName) {\n      return document.createElement(nodeName);\n    };\n\n    var createText = function (text) {\n      return document.createTextNode(text);\n    };\n\n    /**\n     * @method remove\n     *\n     * remove node, (isRemoveChild: remove child or not)\n     *\n     * @param {Node} node\n     * @param {Boolean} isRemoveChild\n     */\n    var remove = function (node, isRemoveChild) {\n      if (!node || !node.parentNode) { return; }\n      if (node.removeNode) { return node.removeNode(isRemoveChild); }\n\n      var parent = node.parentNode;\n      if (!isRemoveChild) {\n        var nodes = [];\n        var i, len;\n        for (i = 0, len = node.childNodes.length; i < len; i++) {\n          nodes.push(node.childNodes[i]);\n        }\n\n        for (i = 0, len = nodes.length; i < len; i++) {\n          parent.insertBefore(nodes[i], node);\n        }\n      }\n\n      parent.removeChild(node);\n    };\n\n    /**\n     * @method removeWhile\n     *\n     * @param {Node} node\n     * @param {Function} pred\n     */\n    var removeWhile = function (node, pred) {\n      while (node) {\n        if (isEditable(node) || !pred(node)) {\n          break;\n        }\n\n        var parent = node.parentNode;\n        remove(node);\n        node = parent;\n      }\n    };\n\n    /**\n     * @method replace\n     *\n     * replace node with provided nodeName\n     *\n     * @param {Node} node\n     * @param {String} nodeName\n     * @return {Node} - new node\n     */\n    var replace = function (node, nodeName) {\n      if (node.nodeName.toUpperCase() === nodeName.toUpperCase()) {\n        return node;\n      }\n\n      var newNode = create(nodeName);\n\n      if (node.style.cssText) {\n        newNode.style.cssText = node.style.cssText;\n      }\n\n      appendChildNodes(newNode, list.from(node.childNodes));\n      insertAfter(newNode, node);\n      remove(node);\n\n      return newNode;\n    };\n\n    var isTextarea = makePredByNodeName('TEXTAREA');\n\n    /**\n     * @param {jQuery} $node\n     * @param {Boolean} [stripLinebreaks] - default: false\n     */\n    var value = function ($node, stripLinebreaks) {\n      var val = isTextarea($node[0]) ? $node.val() : $node.html();\n      if (stripLinebreaks) {\n        return val.replace(/[\\n\\r]/g, '');\n      }\n      return val;\n    };\n\n    /**\n     * @method html\n     *\n     * get the HTML contents of node\n     *\n     * @param {jQuery} $node\n     * @param {Boolean} [isNewlineOnBlock]\n     */\n    var html = function ($node, isNewlineOnBlock) {\n      var markup = value($node);\n\n      if (isNewlineOnBlock) {\n        var regexTag = /<(\\/?)(\\b(?!!)[^>\\s]*)(.*?)(\\s*\\/?>)/g;\n        markup = markup.replace(regexTag, function (match, endSlash, name) {\n          name = name.toUpperCase();\n          var isEndOfInlineContainer = /^DIV|^TD|^TH|^P|^LI|^H[1-7]/.test(name) &&\n                                       !!endSlash;\n          var isBlockNode = /^BLOCKQUOTE|^TABLE|^TBODY|^TR|^HR|^UL|^OL/.test(name);\n\n          return match + ((isEndOfInlineContainer || isBlockNode) ? '\\n' : '');\n        });\n        markup = $.trim(markup);\n      }\n\n      return markup;\n    };\n\n    var posFromPlaceholder = function (placeholder) {\n      var $placeholder = $(placeholder);\n      var pos = $placeholder.offset();\n      var height = $placeholder.outerHeight(true); // include margin\n\n      return {\n        left: pos.left,\n        top: pos.top + height\n      };\n    };\n\n    var attachEvents = function ($node, events) {\n      Object.keys(events).forEach(function (key) {\n        $node.on(key, events[key]);\n      });\n    };\n\n    var detachEvents = function ($node, events) {\n      Object.keys(events).forEach(function (key) {\n        $node.off(key, events[key]);\n      });\n    };\n\n    return {\n      /** @property {String} NBSP_CHAR */\n      NBSP_CHAR: NBSP_CHAR,\n      /** @property {String} ZERO_WIDTH_NBSP_CHAR */\n      ZERO_WIDTH_NBSP_CHAR: ZERO_WIDTH_NBSP_CHAR,\n      /** @property {String} blank */\n      blank: blankHTML,\n      /** @property {String} emptyPara */\n      emptyPara: '<p>' + blankHTML + '</p>',\n      makePredByNodeName: makePredByNodeName,\n      isEditable: isEditable,\n      isControlSizing: isControlSizing,\n      isText: isText,\n      isElement: isElement,\n      isVoid: isVoid,\n      isPara: isPara,\n      isPurePara: isPurePara,\n      isHeading: isHeading,\n      isInline: isInline,\n      isBlock: func.not(isInline),\n      isBodyInline: isBodyInline,\n      isBody: isBody,\n      isParaInline: isParaInline,\n      isPre: isPre,\n      isList: isList,\n      isTable: isTable,\n      isData: isData,\n      isCell: isCell,\n      isBlockquote: isBlockquote,\n      isBodyContainer: isBodyContainer,\n      isAnchor: isAnchor,\n      isDiv: makePredByNodeName('DIV'),\n      isLi: isLi,\n      isBR: makePredByNodeName('BR'),\n      isSpan: makePredByNodeName('SPAN'),\n      isB: makePredByNodeName('B'),\n      isU: makePredByNodeName('U'),\n      isS: makePredByNodeName('S'),\n      isI: makePredByNodeName('I'),\n      isImg: makePredByNodeName('IMG'),\n      isTextarea: isTextarea,\n      isEmpty: isEmpty,\n      isEmptyAnchor: func.and(isAnchor, isEmpty),\n      isClosestSibling: isClosestSibling,\n      withClosestSiblings: withClosestSiblings,\n      nodeLength: nodeLength,\n      isLeftEdgePoint: isLeftEdgePoint,\n      isRightEdgePoint: isRightEdgePoint,\n      isEdgePoint: isEdgePoint,\n      isLeftEdgeOf: isLeftEdgeOf,\n      isRightEdgeOf: isRightEdgeOf,\n      isLeftEdgePointOf: isLeftEdgePointOf,\n      isRightEdgePointOf: isRightEdgePointOf,\n      prevPoint: prevPoint,\n      nextPoint: nextPoint,\n      isSamePoint: isSamePoint,\n      isVisiblePoint: isVisiblePoint,\n      prevPointUntil: prevPointUntil,\n      nextPointUntil: nextPointUntil,\n      isCharPoint: isCharPoint,\n      walkPoint: walkPoint,\n      ancestor: ancestor,\n      singleChildAncestor: singleChildAncestor,\n      listAncestor: listAncestor,\n      lastAncestor: lastAncestor,\n      listNext: listNext,\n      listPrev: listPrev,\n      listDescendant: listDescendant,\n      commonAncestor: commonAncestor,\n      wrap: wrap,\n      insertAfter: insertAfter,\n      appendChildNodes: appendChildNodes,\n      position: position,\n      hasChildren: hasChildren,\n      makeOffsetPath: makeOffsetPath,\n      fromOffsetPath: fromOffsetPath,\n      splitTree: splitTree,\n      splitPoint: splitPoint,\n      create: create,\n      createText: createText,\n      remove: remove,\n      removeWhile: removeWhile,\n      replace: replace,\n      html: html,\n      value: value,\n      posFromPlaceholder: posFromPlaceholder,\n      attachEvents: attachEvents,\n      detachEvents: detachEvents\n    };\n  })();\n\n  /**\n   * @param {jQuery} $note\n   * @param {Object} options\n   * @return {Context}\n   */\n  var Context = function ($note, options) {\n    var self = this;\n\n    var ui = $.summernote.ui;\n    this.memos = {};\n    this.modules = {};\n    this.layoutInfo = {};\n    this.options = options;\n\n    /**\n     * create layout and initialize modules and other resources\n     */\n    this.initialize = function () {\n      this.layoutInfo = ui.createLayout($note, options);\n      this._initialize();\n      $note.hide();\n      return this;\n    };\n\n    /**\n     * destroy modules and other resources and remove layout\n     */\n    this.destroy = function () {\n      this._destroy();\n      $note.removeData('summernote');\n      ui.removeLayout($note, this.layoutInfo);\n    };\n\n    /**\n     * destory modules and other resources and initialize it again\n     */\n    this.reset = function () {\n      var disabled = self.isDisabled();\n      this.code(dom.emptyPara);\n      this._destroy();\n      this._initialize();\n\n      if (disabled) {\n        self.disable();\n      }\n    };\n\n    this._initialize = function () {\n      // add optional buttons\n      var buttons = $.extend({}, this.options.buttons);\n      Object.keys(buttons).forEach(function (key) {\n        self.memo('button.' + key, buttons[key]);\n      });\n\n      var modules = $.extend({}, this.options.modules, $.summernote.plugins || {});\n\n      // add and initialize modules\n      Object.keys(modules).forEach(function (key) {\n        self.module(key, modules[key], true);\n      });\n\n      Object.keys(this.modules).forEach(function (key) {\n        self.initializeModule(key);\n      });\n    };\n\n    this._destroy = function () {\n      // destroy modules with reversed order\n      Object.keys(this.modules).reverse().forEach(function (key) {\n        self.removeModule(key);\n      });\n\n      Object.keys(this.memos).forEach(function (key) {\n        self.removeMemo(key);\n      });\n    };\n\n    this.code = function (html) {\n      var isActivated = this.invoke('codeview.isActivated');\n\n      if (html === undefined) {\n        this.invoke('codeview.sync');\n        return isActivated ? this.layoutInfo.codable.val() : this.layoutInfo.editable.html();\n      } else {\n        if (isActivated) {\n          this.layoutInfo.codable.val(html);\n        } else {\n          this.layoutInfo.editable.html(html);\n        }\n        $note.val(html);\n        this.triggerEvent('change', html);\n      }\n    };\n\n    this.isDisabled = function () {\n      return this.layoutInfo.editable.attr('contenteditable') === 'false';\n    };\n\n    this.enable = function () {\n      this.layoutInfo.editable.attr('contenteditable', true);\n      this.invoke('toolbar.activate', true);\n    };\n\n    this.disable = function () {\n      // close codeview if codeview is opend\n      if (this.invoke('codeview.isActivated')) {\n        this.invoke('codeview.deactivate');\n      }\n      this.layoutInfo.editable.attr('contenteditable', false);\n      this.invoke('toolbar.deactivate', true);\n    };\n\n    this.triggerEvent = function () {\n      var namespace = list.head(arguments);\n      var args = list.tail(list.from(arguments));\n\n      var callback = this.options.callbacks[func.namespaceToCamel(namespace, 'on')];\n      if (callback) {\n        callback.apply($note[0], args);\n      }\n      $note.trigger('summernote.' + namespace, args);\n    };\n\n    this.initializeModule = function (key) {\n      var module = this.modules[key];\n      module.shouldInitialize = module.shouldInitialize || func.ok;\n      if (!module.shouldInitialize()) {\n        return;\n      }\n\n      // initialize module\n      if (module.initialize) {\n        module.initialize();\n      }\n\n      // attach events\n      if (module.events) {\n        dom.attachEvents($note, module.events);\n      }\n    };\n\n    this.module = function (key, ModuleClass, withoutIntialize) {\n      if (arguments.length === 1) {\n        return this.modules[key];\n      }\n\n      this.modules[key] = new ModuleClass(this);\n\n      if (!withoutIntialize) {\n        this.initializeModule(key);\n      }\n    };\n\n    this.removeModule = function (key) {\n      var module = this.modules[key];\n      if (module.shouldInitialize()) {\n        if (module.events) {\n          dom.detachEvents($note, module.events);\n        }\n\n        if (module.destroy) {\n          module.destroy();\n        }\n      }\n\n      delete this.modules[key];\n    };\n\n    this.memo = function (key, obj) {\n      if (arguments.length === 1) {\n        return this.memos[key];\n      }\n      this.memos[key] = obj;\n    };\n\n    this.removeMemo = function (key) {\n      if (this.memos[key] && this.memos[key].destroy) {\n        this.memos[key].destroy();\n      }\n\n      delete this.memos[key];\n    };\n\n    this.createInvokeHandler = function (namespace, value) {\n      return function (event) {\n        event.preventDefault();\n        self.invoke(namespace, value || $(event.target).closest('[data-value]').data('value'));\n      };\n    };\n\n    this.invoke = function () {\n      var namespace = list.head(arguments);\n      var args = list.tail(list.from(arguments));\n\n      var splits = namespace.split('.');\n      var hasSeparator = splits.length > 1;\n      var moduleName = hasSeparator && list.head(splits);\n      var methodName = hasSeparator ? list.last(splits) : list.head(splits);\n\n      var module = this.modules[moduleName || 'editor'];\n      if (!moduleName && this[methodName]) {\n        return this[methodName].apply(this, args);\n      } else if (module && module[methodName] && module.shouldInitialize()) {\n        return module[methodName].apply(module, args);\n      }\n    };\n\n    return this.initialize();\n  };\n\n  $.fn.extend({\n    /**\n     * Summernote API\n     *\n     * @param {Object|String}\n     * @return {this}\n     */\n    summernote: function () {\n      var type = $.type(list.head(arguments));\n      var isExternalAPICalled = type === 'string';\n      var hasInitOptions = type === 'object';\n\n      var options = hasInitOptions ? list.head(arguments) : {};\n\n      options = $.extend({}, $.summernote.options, options);\n      options.langInfo = $.extend(true, {}, $.summernote.lang['en-US'], $.summernote.lang[options.lang]);\n      options.icons = $.extend(true, {}, $.summernote.options.icons, options.icons);\n\n      this.each(function (idx, note) {\n        var $note = $(note);\n        if (!$note.data('summernote')) {\n          var context = new Context($note, options);\n          $note.data('summernote', context);\n          $note.data('summernote').triggerEvent('init', context.layoutInfo);\n        }\n      });\n\n      var $note = this.first();\n      if ($note.length) {\n        var context = $note.data('summernote');\n        if (isExternalAPICalled) {\n          return context.invoke.apply(context, list.from(arguments));\n        } else if (options.focus) {\n          context.invoke('editor.focus');\n        }\n      }\n\n      return this;\n    }\n  });\n\n\n  var Renderer = function (markup, children, options, callback) {\n    this.render = function ($parent) {\n      var $node = $(markup);\n\n      if (options && options.contents) {\n        $node.html(options.contents);\n      }\n\n      if (options && options.className) {\n        $node.addClass(options.className);\n      }\n\n      if (options && options.data) {\n        $.each(options.data, function (k, v) {\n          $node.attr('data-' + k, v);\n        });\n      }\n\n      if (options && options.click) {\n        $node.on('click', options.click);\n      }\n\n      if (children) {\n        var $container = $node.find('.note-children-container');\n        children.forEach(function (child) {\n          child.render($container.length ? $container : $node);\n        });\n      }\n\n      if (callback) {\n        callback($node, options);\n      }\n\n      if (options && options.callback) {\n        options.callback($node);\n      }\n\n      if ($parent) {\n        $parent.append($node);\n      }\n\n      return $node;\n    };\n  };\n\n  var renderer = {\n    create: function (markup, callback) {\n      return function () {\n        var children = $.isArray(arguments[0]) ? arguments[0] : [];\n        var options = typeof arguments[1] === 'object' ? arguments[1] : arguments[0];\n        if (options && options.children) {\n          children = options.children;\n        }\n        return new Renderer(markup, children, options, callback);\n      };\n    }\n  };\n\n  var editor = renderer.create('<div class=\"note-editor note-frame panel panel-default\"/>');\n  var toolbar = renderer.create('<div class=\"note-toolbar panel-heading\"/>');\n  var editingArea = renderer.create('<div class=\"note-editing-area\"/>');\n  var codable = renderer.create('<textarea class=\"note-codable\"/>');\n  var editable = renderer.create('<div class=\"note-editable panel-body\" contentEditable=\"true\"/>');\n  var statusbar = renderer.create([\n    '<div class=\"note-statusbar\">',\n    '  <div class=\"note-resizebar\">',\n    '    <div class=\"note-icon-bar\"/>',\n    '    <div class=\"note-icon-bar\"/>',\n    '    <div class=\"note-icon-bar\"/>',\n    '  </div>',\n    '</div>'\n  ].join(''));\n\n  var airEditor = renderer.create('<div class=\"note-editor\"/>');\n  var airEditable = renderer.create('<div class=\"note-editable\" contentEditable=\"true\"/>');\n\n  var buttonGroup = renderer.create('<div class=\"note-btn-group btn-group\">');\n  var button = renderer.create('<button type=\"button\" class=\"note-btn btn btn-default btn-sm\" tabindex=\"-1\">', function ($node, options) {\n    if (options && options.tooltip) {\n      $node.attr({\n        title: options.tooltip\n      }).tooltip({\n        container: 'body',\n        trigger: 'hover',\n        placement: 'bottom'\n      });\n    }\n  });\n\n  var dropdown = renderer.create('<div class=\"dropdown-menu\">', function ($node, options) {\n    var markup = $.isArray(options.items) ? options.items.map(function (item) {\n      var value = (typeof item === 'string') ? item : (item.value || '');\n      var content = options.template ? options.template(item) : item;\n      return '<li><a href=\"#\" data-value=\"' + value + '\">' + content + '</a></li>';\n    }).join('') : options.items;\n\n    $node.html(markup);\n  });\n\n  var dropdownCheck = renderer.create('<div class=\"dropdown-menu note-check\">', function ($node, options) {\n    var markup = $.isArray(options.items) ? options.items.map(function (item) {\n      var value = (typeof item === 'string') ? item : (item.value || '');\n      var content = options.template ? options.template(item) : item;\n      return '<li><a href=\"#\" data-value=\"' + value + '\">' + icon(options.checkClassName) + ' ' + content + '</a></li>';\n    }).join('') : options.items;\n    $node.html(markup);\n  });\n\n  var palette = renderer.create('<div class=\"note-color-palette\"/>', function ($node, options) {\n    var contents = [];\n    for (var row = 0, rowSize = options.colors.length; row < rowSize; row++) {\n      var eventName = options.eventName;\n      var colors = options.colors[row];\n      var buttons = [];\n      for (var col = 0, colSize = colors.length; col < colSize; col++) {\n        var color = colors[col];\n        buttons.push([\n          '<button type=\"button\" class=\"note-color-btn\"',\n          'style=\"background-color:', color, '\" ',\n          'data-event=\"', eventName, '\" ',\n          'data-value=\"', color, '\" ',\n          'title=\"', color, '\" ',\n          'data-toggle=\"button\" tabindex=\"-1\"></button>'\n        ].join(''));\n      }\n      contents.push('<div class=\"note-color-row\">' + buttons.join('') + '</div>');\n    }\n    $node.html(contents.join(''));\n\n    $node.find('.note-color-btn').tooltip({\n      container: 'body',\n      trigger: 'hover',\n      placement: 'bottom'\n    });\n  });\n\n  var dialog = renderer.create('<div class=\"modal\" aria-hidden=\"false\" tabindex=\"-1\"/>', function ($node, options) {\n    if (options.fade) {\n      $node.addClass('fade');\n    }\n    $node.html([\n      '<div class=\"modal-dialog\">',\n      '  <div class=\"modal-content\">',\n      (options.title ?\n      '    <div class=\"modal-header\">' +\n      '      <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>' +\n      '      <h4 class=\"modal-title\">' + options.title + '</h4>' +\n      '    </div>' : ''\n      ),\n      '    <div class=\"modal-body\">' + options.body + '</div>',\n      (options.footer ?\n      '    <div class=\"modal-footer\">' + options.footer + '</div>' : ''\n      ),\n      '  </div>',\n      '</div>'\n    ].join(''));\n  });\n\n  var popover = renderer.create([\n    '<div class=\"note-popover popover in\">',\n    '  <div class=\"arrow\"/>',\n    '  <div class=\"popover-content note-children-container\"/>',\n    '</div>'\n  ].join(''), function ($node, options) {\n    var direction = typeof options.direction !== 'undefined' ? options.direction : 'bottom';\n\n    $node.addClass(direction);\n\n    if (options.hideArrow) {\n      $node.find('.arrow').hide();\n    }\n  });\n\n  var icon = function (iconClassName, tagName) {\n    tagName = tagName || 'i';\n    return '<' + tagName + ' class=\"' + iconClassName + '\"/>';\n  };\n\n  var ui = {\n    editor: editor,\n    toolbar: toolbar,\n    editingArea: editingArea,\n    codable: codable,\n    editable: editable,\n    statusbar: statusbar,\n    airEditor: airEditor,\n    airEditable: airEditable,\n    buttonGroup: buttonGroup,\n    button: button,\n    dropdown: dropdown,\n    dropdownCheck: dropdownCheck,\n    palette: palette,\n    dialog: dialog,\n    popover: popover,\n    icon: icon,\n\n    toggleBtn: function ($btn, isEnable) {\n      $btn.toggleClass('disabled', !isEnable);\n      $btn.attr('disabled', !isEnable);\n    },\n\n    toggleBtnActive: function ($btn, isActive) {\n      $btn.toggleClass('active', isActive);\n    },\n\n    onDialogShown: function ($dialog, handler) {\n      $dialog.one('shown.bs.modal', handler);\n    },\n\n    onDialogHidden: function ($dialog, handler) {\n      $dialog.one('hidden.bs.modal', handler);\n    },\n\n    showDialog: function ($dialog) {\n      $dialog.modal('show');\n    },\n\n    hideDialog: function ($dialog) {\n      $dialog.modal('hide');\n    },\n\n    createLayout: function ($note, options) {\n      var $editor = (options.airMode ? ui.airEditor([\n        ui.editingArea([\n          ui.airEditable()\n        ])\n      ]) : ui.editor([\n        ui.toolbar(),\n        ui.editingArea([\n          ui.codable(),\n          ui.editable()\n        ]),\n        ui.statusbar()\n      ])).render();\n\n      $editor.insertAfter($note);\n\n      return {\n        note: $note,\n        editor: $editor,\n        toolbar: $editor.find('.note-toolbar'),\n        editingArea: $editor.find('.note-editing-area'),\n        editable: $editor.find('.note-editable'),\n        codable: $editor.find('.note-codable'),\n        statusbar: $editor.find('.note-statusbar')\n      };\n    },\n\n    removeLayout: function ($note, layoutInfo) {\n      $note.html(layoutInfo.editable.html());\n      layoutInfo.editor.remove();\n      $note.show();\n    }\n  };\n\n  $.summernote = $.summernote || {\n    lang: {}\n  };\n\n  $.extend($.summernote.lang, {\n    'en-US': {\n      font: {\n        bold: 'Bold',\n        italic: 'Italic',\n        underline: 'Underline',\n        clear: 'Remove Font Style',\n        height: 'Line Height',\n        name: 'Font Family',\n        strikethrough: 'Strikethrough',\n        subscript: 'Subscript',\n        superscript: 'Superscript',\n        size: 'Font Size'\n      },\n      image: {\n        image: 'Picture',\n        insert: 'Insert Image',\n        resizeFull: 'Resize Full',\n        resizeHalf: 'Resize Half',\n        resizeQuarter: 'Resize Quarter',\n        floatLeft: 'Float Left',\n        floatRight: 'Float Right',\n        floatNone: 'Float None',\n        shapeRounded: 'Shape: Rounded',\n        shapeCircle: 'Shape: Circle',\n        shapeThumbnail: 'Shape: Thumbnail',\n        shapeNone: 'Shape: None',\n        dragImageHere: 'Drag image or text here',\n        dropImage: 'Drop image or Text',\n        selectFromFiles: 'Select from files',\n        maximumFileSize: 'Maximum file size',\n        maximumFileSizeError: 'Maximum file size exceeded.',\n        url: 'Image URL',\n        remove: 'Remove Image'\n      },\n      video: {\n        video: 'Video',\n        videoLink: 'Video Link',\n        insert: 'Insert Video',\n        url: 'Video URL?',\n        providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion or Youku)'\n      },\n      link: {\n        link: 'Link',\n        insert: 'Insert Link',\n        unlink: 'Unlink',\n        edit: 'Edit',\n        textToDisplay: 'Text to display',\n        url: 'To what URL should this link go?',\n        openInNewWindow: 'Open in new window'\n      },\n      table: {\n        table: 'Table'\n      },\n      hr: {\n        insert: 'Insert Horizontal Rule'\n      },\n      style: {\n        style: 'Style',\n        normal: 'Normal',\n        blockquote: 'Quote',\n        pre: 'Code',\n        h1: 'Header 1',\n        h2: 'Header 2',\n        h3: 'Header 3',\n        h4: 'Header 4',\n        h5: 'Header 5',\n        h6: 'Header 6'\n      },\n      lists: {\n        unordered: 'Unordered list',\n        ordered: 'Ordered list'\n      },\n      options: {\n        help: 'Help',\n        fullscreen: 'Full Screen',\n        codeview: 'Code View'\n      },\n      paragraph: {\n        paragraph: 'Paragraph',\n        outdent: 'Outdent',\n        indent: 'Indent',\n        left: 'Align left',\n        center: 'Align center',\n        right: 'Align right',\n        justify: 'Justify full'\n      },\n      color: {\n        recent: 'Recent Color',\n        more: 'More Color',\n        background: 'Background Color',\n        foreground: 'Foreground Color',\n        transparent: 'Transparent',\n        setTransparent: 'Set transparent',\n        reset: 'Reset',\n        resetToDefault: 'Reset to default'\n      },\n      shortcut: {\n        shortcuts: 'Keyboard shortcuts',\n        close: 'Close',\n        textFormatting: 'Text formatting',\n        action: 'Action',\n        paragraphFormatting: 'Paragraph formatting',\n        documentStyle: 'Document Style',\n        extraKeys: 'Extra keys'\n      },\n      help: {\n        'insertParagraph': 'Insert Paragraph',\n        'undo': 'Undoes the last command',\n        'redo': 'Redoes the last command',\n        'tab': 'Tab',\n        'untab': 'Untab',\n        'bold': 'Set a bold style',\n        'italic': 'Set a italic style',\n        'underline': 'Set a underline style',\n        'strikethrough': 'Set a strikethrough style',\n        'removeFormat': 'Clean a style',\n        'justifyLeft': 'Set left align',\n        'justifyCenter': 'Set center align',\n        'justifyRight': 'Set right align',\n        'justifyFull': 'Set full align',\n        'insertUnorderedList': 'Toggle unordered list',\n        'insertOrderedList': 'Toggle ordered list',\n        'outdent': 'Outdent on current paragraph',\n        'indent': 'Indent on current paragraph',\n        'formatPara': 'Change current block\\'s format as a paragraph(P tag)',\n        'formatH1': 'Change current block\\'s format as H1',\n        'formatH2': 'Change current block\\'s format as H2',\n        'formatH3': 'Change current block\\'s format as H3',\n        'formatH4': 'Change current block\\'s format as H4',\n        'formatH5': 'Change current block\\'s format as H5',\n        'formatH6': 'Change current block\\'s format as H6',\n        'insertHorizontalRule': 'Insert horizontal rule',\n        'linkDialog.show': 'Show Link Dialog'\n      },\n      history: {\n        undo: 'Undo',\n        redo: 'Redo'\n      },\n      specialChar: {\n        specialChar: 'SPECIAL CHARACTERS',\n        select: 'Select Special characters'\n      }\n    }\n  });\n\n\n  /**\n   * @class core.key\n   *\n   * Object for keycodes.\n   *\n   * @singleton\n   * @alternateClassName key\n   */\n  var key = (function () {\n    var keyMap = {\n      'BACKSPACE': 8,\n      'TAB': 9,\n      'ENTER': 13,\n      'SPACE': 32,\n\n      // Arrow\n      'LEFT': 37,\n      'UP': 38,\n      'RIGHT': 39,\n      'DOWN': 40,\n\n      // Number: 0-9\n      'NUM0': 48,\n      'NUM1': 49,\n      'NUM2': 50,\n      'NUM3': 51,\n      'NUM4': 52,\n      'NUM5': 53,\n      'NUM6': 54,\n      'NUM7': 55,\n      'NUM8': 56,\n\n      // Alphabet: a-z\n      'B': 66,\n      'E': 69,\n      'I': 73,\n      'J': 74,\n      'K': 75,\n      'L': 76,\n      'R': 82,\n      'S': 83,\n      'U': 85,\n      'V': 86,\n      'Y': 89,\n      'Z': 90,\n\n      'SLASH': 191,\n      'LEFTBRACKET': 219,\n      'BACKSLASH': 220,\n      'RIGHTBRACKET': 221\n    };\n\n    return {\n      /**\n       * @method isEdit\n       *\n       * @param {Number} keyCode\n       * @return {Boolean}\n       */\n      isEdit: function (keyCode) {\n        return list.contains([\n          keyMap.BACKSPACE,\n          keyMap.TAB,\n          keyMap.ENTER,\n          keyMap.SPACE\n        ], keyCode);\n      },\n      /**\n       * @method isMove\n       *\n       * @param {Number} keyCode\n       * @return {Boolean}\n       */\n      isMove: function (keyCode) {\n        return list.contains([\n          keyMap.LEFT,\n          keyMap.UP,\n          keyMap.RIGHT,\n          keyMap.DOWN\n        ], keyCode);\n      },\n      /**\n       * @property {Object} nameFromCode\n       * @property {String} nameFromCode.8 \"BACKSPACE\"\n       */\n      nameFromCode: func.invertObject(keyMap),\n      code: keyMap\n    };\n  })();\n\n  var range = (function () {\n\n    /**\n     * return boundaryPoint from TextRange, inspired by Andy Na's HuskyRange.js\n     *\n     * @param {TextRange} textRange\n     * @param {Boolean} isStart\n     * @return {BoundaryPoint}\n     *\n     * @see http://msdn.microsoft.com/en-us/library/ie/ms535872(v=vs.85).aspx\n     */\n    var textRangeToPoint = function (textRange, isStart) {\n      var container = textRange.parentElement(), offset;\n  \n      var tester = document.body.createTextRange(), prevContainer;\n      var childNodes = list.from(container.childNodes);\n      for (offset = 0; offset < childNodes.length; offset++) {\n        if (dom.isText(childNodes[offset])) {\n          continue;\n        }\n        tester.moveToElementText(childNodes[offset]);\n        if (tester.compareEndPoints('StartToStart', textRange) >= 0) {\n          break;\n        }\n        prevContainer = childNodes[offset];\n      }\n  \n      if (offset !== 0 && dom.isText(childNodes[offset - 1])) {\n        var textRangeStart = document.body.createTextRange(), curTextNode = null;\n        textRangeStart.moveToElementText(prevContainer || container);\n        textRangeStart.collapse(!prevContainer);\n        curTextNode = prevContainer ? prevContainer.nextSibling : container.firstChild;\n  \n        var pointTester = textRange.duplicate();\n        pointTester.setEndPoint('StartToStart', textRangeStart);\n        var textCount = pointTester.text.replace(/[\\r\\n]/g, '').length;\n  \n        while (textCount > curTextNode.nodeValue.length && curTextNode.nextSibling) {\n          textCount -= curTextNode.nodeValue.length;\n          curTextNode = curTextNode.nextSibling;\n        }\n  \n        /* jshint ignore:start */\n        var dummy = curTextNode.nodeValue; // enforce IE to re-reference curTextNode, hack\n        /* jshint ignore:end */\n  \n        if (isStart && curTextNode.nextSibling && dom.isText(curTextNode.nextSibling) &&\n            textCount === curTextNode.nodeValue.length) {\n          textCount -= curTextNode.nodeValue.length;\n          curTextNode = curTextNode.nextSibling;\n        }\n  \n        container = curTextNode;\n        offset = textCount;\n      }\n  \n      return {\n        cont: container,\n        offset: offset\n      };\n    };\n    \n    /**\n     * return TextRange from boundary point (inspired by google closure-library)\n     * @param {BoundaryPoint} point\n     * @return {TextRange}\n     */\n    var pointToTextRange = function (point) {\n      var textRangeInfo = function (container, offset) {\n        var node, isCollapseToStart;\n  \n        if (dom.isText(container)) {\n          var prevTextNodes = dom.listPrev(container, func.not(dom.isText));\n          var prevContainer = list.last(prevTextNodes).previousSibling;\n          node =  prevContainer || container.parentNode;\n          offset += list.sum(list.tail(prevTextNodes), dom.nodeLength);\n          isCollapseToStart = !prevContainer;\n        } else {\n          node = container.childNodes[offset] || container;\n          if (dom.isText(node)) {\n            return textRangeInfo(node, 0);\n          }\n  \n          offset = 0;\n          isCollapseToStart = false;\n        }\n  \n        return {\n          node: node,\n          collapseToStart: isCollapseToStart,\n          offset: offset\n        };\n      };\n  \n      var textRange = document.body.createTextRange();\n      var info = textRangeInfo(point.node, point.offset);\n  \n      textRange.moveToElementText(info.node);\n      textRange.collapse(info.collapseToStart);\n      textRange.moveStart('character', info.offset);\n      return textRange;\n    };\n    \n    /**\n     * Wrapped Range\n     *\n     * @constructor\n     * @param {Node} sc - start container\n     * @param {Number} so - start offset\n     * @param {Node} ec - end container\n     * @param {Number} eo - end offset\n     */\n    var WrappedRange = function (sc, so, ec, eo) {\n      this.sc = sc;\n      this.so = so;\n      this.ec = ec;\n      this.eo = eo;\n  \n      // nativeRange: get nativeRange from sc, so, ec, eo\n      var nativeRange = function () {\n        if (agent.isW3CRangeSupport) {\n          var w3cRange = document.createRange();\n          w3cRange.setStart(sc, so);\n          w3cRange.setEnd(ec, eo);\n\n          return w3cRange;\n        } else {\n          var textRange = pointToTextRange({\n            node: sc,\n            offset: so\n          });\n\n          textRange.setEndPoint('EndToEnd', pointToTextRange({\n            node: ec,\n            offset: eo\n          }));\n\n          return textRange;\n        }\n      };\n\n      this.getPoints = function () {\n        return {\n          sc: sc,\n          so: so,\n          ec: ec,\n          eo: eo\n        };\n      };\n\n      this.getStartPoint = function () {\n        return {\n          node: sc,\n          offset: so\n        };\n      };\n\n      this.getEndPoint = function () {\n        return {\n          node: ec,\n          offset: eo\n        };\n      };\n\n      /**\n       * select update visible range\n       */\n      this.select = function () {\n        var nativeRng = nativeRange();\n        if (agent.isW3CRangeSupport) {\n          var selection = document.getSelection();\n          if (selection.rangeCount > 0) {\n            selection.removeAllRanges();\n          }\n          selection.addRange(nativeRng);\n        } else {\n          nativeRng.select();\n        }\n        \n        return this;\n      };\n\n      /**\n       * Moves the scrollbar to start container(sc) of current range\n       *\n       * @return {WrappedRange}\n       */\n      this.scrollIntoView = function (container) {\n        var height = $(container).height();\n        if (container.scrollTop + height < this.sc.offsetTop) {\n          container.scrollTop += Math.abs(container.scrollTop + height - this.sc.offsetTop);\n        }\n\n        return this;\n      };\n\n      /**\n       * @return {WrappedRange}\n       */\n      this.normalize = function () {\n\n        /**\n         * @param {BoundaryPoint} point\n         * @param {Boolean} isLeftToRight\n         * @return {BoundaryPoint}\n         */\n        var getVisiblePoint = function (point, isLeftToRight) {\n          if ((dom.isVisiblePoint(point) && !dom.isEdgePoint(point)) ||\n              (dom.isVisiblePoint(point) && dom.isRightEdgePoint(point) && !isLeftToRight) ||\n              (dom.isVisiblePoint(point) && dom.isLeftEdgePoint(point) && isLeftToRight) ||\n              (dom.isVisiblePoint(point) && dom.isBlock(point.node) && dom.isEmpty(point.node))) {\n            return point;\n          }\n\n          // point on block's edge\n          var block = dom.ancestor(point.node, dom.isBlock);\n          if (((dom.isLeftEdgePointOf(point, block) || dom.isVoid(dom.prevPoint(point).node)) && !isLeftToRight) ||\n              ((dom.isRightEdgePointOf(point, block) || dom.isVoid(dom.nextPoint(point).node)) && isLeftToRight)) {\n\n            // returns point already on visible point\n            if (dom.isVisiblePoint(point)) {\n              return point;\n            }\n            // reverse direction \n            isLeftToRight = !isLeftToRight;\n          }\n\n          var nextPoint = isLeftToRight ? dom.nextPointUntil(dom.nextPoint(point), dom.isVisiblePoint) :\n                                          dom.prevPointUntil(dom.prevPoint(point), dom.isVisiblePoint);\n          return nextPoint || point;\n        };\n\n        var endPoint = getVisiblePoint(this.getEndPoint(), false);\n        var startPoint = this.isCollapsed() ? endPoint : getVisiblePoint(this.getStartPoint(), true);\n\n        return new WrappedRange(\n          startPoint.node,\n          startPoint.offset,\n          endPoint.node,\n          endPoint.offset\n        );\n      };\n\n      /**\n       * returns matched nodes on range\n       *\n       * @param {Function} [pred] - predicate function\n       * @param {Object} [options]\n       * @param {Boolean} [options.includeAncestor]\n       * @param {Boolean} [options.fullyContains]\n       * @return {Node[]}\n       */\n      this.nodes = function (pred, options) {\n        pred = pred || func.ok;\n\n        var includeAncestor = options && options.includeAncestor;\n        var fullyContains = options && options.fullyContains;\n\n        // TODO compare points and sort\n        var startPoint = this.getStartPoint();\n        var endPoint = this.getEndPoint();\n\n        var nodes = [];\n        var leftEdgeNodes = [];\n\n        dom.walkPoint(startPoint, endPoint, function (point) {\n          if (dom.isEditable(point.node)) {\n            return;\n          }\n\n          var node;\n          if (fullyContains) {\n            if (dom.isLeftEdgePoint(point)) {\n              leftEdgeNodes.push(point.node);\n            }\n            if (dom.isRightEdgePoint(point) && list.contains(leftEdgeNodes, point.node)) {\n              node = point.node;\n            }\n          } else if (includeAncestor) {\n            node = dom.ancestor(point.node, pred);\n          } else {\n            node = point.node;\n          }\n\n          if (node && pred(node)) {\n            nodes.push(node);\n          }\n        }, true);\n\n        return list.unique(nodes);\n      };\n\n      /**\n       * returns commonAncestor of range\n       * @return {Element} - commonAncestor\n       */\n      this.commonAncestor = function () {\n        return dom.commonAncestor(sc, ec);\n      };\n\n      /**\n       * returns expanded range by pred\n       *\n       * @param {Function} pred - predicate function\n       * @return {WrappedRange}\n       */\n      this.expand = function (pred) {\n        var startAncestor = dom.ancestor(sc, pred);\n        var endAncestor = dom.ancestor(ec, pred);\n\n        if (!startAncestor && !endAncestor) {\n          return new WrappedRange(sc, so, ec, eo);\n        }\n\n        var boundaryPoints = this.getPoints();\n\n        if (startAncestor) {\n          boundaryPoints.sc = startAncestor;\n          boundaryPoints.so = 0;\n        }\n\n        if (endAncestor) {\n          boundaryPoints.ec = endAncestor;\n          boundaryPoints.eo = dom.nodeLength(endAncestor);\n        }\n\n        return new WrappedRange(\n          boundaryPoints.sc,\n          boundaryPoints.so,\n          boundaryPoints.ec,\n          boundaryPoints.eo\n        );\n      };\n\n      /**\n       * @param {Boolean} isCollapseToStart\n       * @return {WrappedRange}\n       */\n      this.collapse = function (isCollapseToStart) {\n        if (isCollapseToStart) {\n          return new WrappedRange(sc, so, sc, so);\n        } else {\n          return new WrappedRange(ec, eo, ec, eo);\n        }\n      };\n\n      /**\n       * splitText on range\n       */\n      this.splitText = function () {\n        var isSameContainer = sc === ec;\n        var boundaryPoints = this.getPoints();\n\n        if (dom.isText(ec) && !dom.isEdgePoint(this.getEndPoint())) {\n          ec.splitText(eo);\n        }\n\n        if (dom.isText(sc) && !dom.isEdgePoint(this.getStartPoint())) {\n          boundaryPoints.sc = sc.splitText(so);\n          boundaryPoints.so = 0;\n\n          if (isSameContainer) {\n            boundaryPoints.ec = boundaryPoints.sc;\n            boundaryPoints.eo = eo - so;\n          }\n        }\n\n        return new WrappedRange(\n          boundaryPoints.sc,\n          boundaryPoints.so,\n          boundaryPoints.ec,\n          boundaryPoints.eo\n        );\n      };\n\n      /**\n       * delete contents on range\n       * @return {WrappedRange}\n       */\n      this.deleteContents = function () {\n        if (this.isCollapsed()) {\n          return this;\n        }\n\n        var rng = this.splitText();\n        var nodes = rng.nodes(null, {\n          fullyContains: true\n        });\n\n        // find new cursor point\n        var point = dom.prevPointUntil(rng.getStartPoint(), function (point) {\n          return !list.contains(nodes, point.node);\n        });\n\n        var emptyParents = [];\n        $.each(nodes, function (idx, node) {\n          // find empty parents\n          var parent = node.parentNode;\n          if (point.node !== parent && dom.nodeLength(parent) === 1) {\n            emptyParents.push(parent);\n          }\n          dom.remove(node, false);\n        });\n\n        // remove empty parents\n        $.each(emptyParents, function (idx, node) {\n          dom.remove(node, false);\n        });\n\n        return new WrappedRange(\n          point.node,\n          point.offset,\n          point.node,\n          point.offset\n        ).normalize();\n      };\n      \n      /**\n       * makeIsOn: return isOn(pred) function\n       */\n      var makeIsOn = function (pred) {\n        return function () {\n          var ancestor = dom.ancestor(sc, pred);\n          return !!ancestor && (ancestor === dom.ancestor(ec, pred));\n        };\n      };\n  \n      // isOnEditable: judge whether range is on editable or not\n      this.isOnEditable = makeIsOn(dom.isEditable);\n      // isOnList: judge whether range is on list node or not\n      this.isOnList = makeIsOn(dom.isList);\n      // isOnAnchor: judge whether range is on anchor node or not\n      this.isOnAnchor = makeIsOn(dom.isAnchor);\n      // isOnCell: judge whether range is on cell node or not\n      this.isOnCell = makeIsOn(dom.isCell);\n      // isOnData: judge whether range is on data node or not\n      this.isOnData = makeIsOn(dom.isData);\n\n      /**\n       * @param {Function} pred\n       * @return {Boolean}\n       */\n      this.isLeftEdgeOf = function (pred) {\n        if (!dom.isLeftEdgePoint(this.getStartPoint())) {\n          return false;\n        }\n\n        var node = dom.ancestor(this.sc, pred);\n        return node && dom.isLeftEdgeOf(this.sc, node);\n      };\n\n      /**\n       * returns whether range was collapsed or not\n       */\n      this.isCollapsed = function () {\n        return sc === ec && so === eo;\n      };\n\n      /**\n       * wrap inline nodes which children of body with paragraph\n       *\n       * @return {WrappedRange}\n       */\n      this.wrapBodyInlineWithPara = function () {\n        if (dom.isBodyContainer(sc) && dom.isEmpty(sc)) {\n          sc.innerHTML = dom.emptyPara;\n          return new WrappedRange(sc.firstChild, 0, sc.firstChild, 0);\n        }\n\n        /**\n         * [workaround] firefox often create range on not visible point. so normalize here.\n         *  - firefox: |<p>text</p>|\n         *  - chrome: <p>|text|</p>\n         */\n        var rng = this.normalize();\n        if (dom.isParaInline(sc) || dom.isPara(sc)) {\n          return rng;\n        }\n\n        // find inline top ancestor\n        var topAncestor;\n        if (dom.isInline(rng.sc)) {\n          var ancestors = dom.listAncestor(rng.sc, func.not(dom.isInline));\n          topAncestor = list.last(ancestors);\n          if (!dom.isInline(topAncestor)) {\n            topAncestor = ancestors[ancestors.length - 2] || rng.sc.childNodes[rng.so];\n          }\n        } else {\n          topAncestor = rng.sc.childNodes[rng.so > 0 ? rng.so - 1 : 0];\n        }\n\n        // siblings not in paragraph\n        var inlineSiblings = dom.listPrev(topAncestor, dom.isParaInline).reverse();\n        inlineSiblings = inlineSiblings.concat(dom.listNext(topAncestor.nextSibling, dom.isParaInline));\n\n        // wrap with paragraph\n        if (inlineSiblings.length) {\n          var para = dom.wrap(list.head(inlineSiblings), 'p');\n          dom.appendChildNodes(para, list.tail(inlineSiblings));\n        }\n\n        return this.normalize();\n      };\n\n      /**\n       * insert node at current cursor\n       *\n       * @param {Node} node\n       * @return {Node}\n       */\n      this.insertNode = function (node) {\n        var rng = this.wrapBodyInlineWithPara().deleteContents();\n        var info = dom.splitPoint(rng.getStartPoint(), dom.isInline(node));\n\n        if (info.rightNode) {\n          info.rightNode.parentNode.insertBefore(node, info.rightNode);\n        } else {\n          info.container.appendChild(node);\n        }\n\n        return node;\n      };\n\n      /**\n       * insert html at current cursor\n       */\n      this.pasteHTML = function (markup) {\n        var contentsContainer = $('<div></div>').html(markup)[0];\n        var childNodes = list.from(contentsContainer.childNodes);\n\n        var rng = this.wrapBodyInlineWithPara().deleteContents();\n\n        return childNodes.reverse().map(function (childNode) {\n          return rng.insertNode(childNode);\n        }).reverse();\n      };\n  \n      /**\n       * returns text in range\n       *\n       * @return {String}\n       */\n      this.toString = function () {\n        var nativeRng = nativeRange();\n        return agent.isW3CRangeSupport ? nativeRng.toString() : nativeRng.text;\n      };\n\n      /**\n       * returns range for word before cursor\n       *\n       * @param {Boolean} [findAfter] - find after cursor, default: false\n       * @return {WrappedRange}\n       */\n      this.getWordRange = function (findAfter) {\n        var endPoint = this.getEndPoint();\n\n        if (!dom.isCharPoint(endPoint)) {\n          return this;\n        }\n\n        var startPoint = dom.prevPointUntil(endPoint, function (point) {\n          return !dom.isCharPoint(point);\n        });\n\n        if (findAfter) {\n          endPoint = dom.nextPointUntil(endPoint, function (point) {\n            return !dom.isCharPoint(point);\n          });\n        }\n\n        return new WrappedRange(\n          startPoint.node,\n          startPoint.offset,\n          endPoint.node,\n          endPoint.offset\n        );\n      };\n  \n      /**\n       * create offsetPath bookmark\n       *\n       * @param {Node} editable\n       */\n      this.bookmark = function (editable) {\n        return {\n          s: {\n            path: dom.makeOffsetPath(editable, sc),\n            offset: so\n          },\n          e: {\n            path: dom.makeOffsetPath(editable, ec),\n            offset: eo\n          }\n        };\n      };\n\n      /**\n       * create offsetPath bookmark base on paragraph\n       *\n       * @param {Node[]} paras\n       */\n      this.paraBookmark = function (paras) {\n        return {\n          s: {\n            path: list.tail(dom.makeOffsetPath(list.head(paras), sc)),\n            offset: so\n          },\n          e: {\n            path: list.tail(dom.makeOffsetPath(list.last(paras), ec)),\n            offset: eo\n          }\n        };\n      };\n\n      /**\n       * getClientRects\n       * @return {Rect[]}\n       */\n      this.getClientRects = function () {\n        var nativeRng = nativeRange();\n        return nativeRng.getClientRects();\n      };\n    };\n\n  /**\n   * @class core.range\n   *\n   * Data structure\n   *  * BoundaryPoint: a point of dom tree\n   *  * BoundaryPoints: two boundaryPoints corresponding to the start and the end of the Range\n   *\n   * See to http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Position\n   *\n   * @singleton\n   * @alternateClassName range\n   */\n    return {\n      /**\n       * create Range Object From arguments or Browser Selection\n       *\n       * @param {Node} sc - start container\n       * @param {Number} so - start offset\n       * @param {Node} ec - end container\n       * @param {Number} eo - end offset\n       * @return {WrappedRange}\n       */\n      create: function (sc, so, ec, eo) {\n        if (arguments.length === 4) {\n          return new WrappedRange(sc, so, ec, eo);\n        } else if (arguments.length === 2) { //collapsed\n          ec = sc;\n          eo = so;\n          return new WrappedRange(sc, so, ec, eo);\n        } else {\n          var wrappedRange = this.createFromSelection();\n          if (!wrappedRange && arguments.length === 1) {\n            wrappedRange = this.createFromNode(arguments[0]);\n            return wrappedRange.collapse(dom.emptyPara === arguments[0].innerHTML);\n          }\n          return wrappedRange;\n        }\n      },\n\n      createFromSelection: function () {\n        var sc, so, ec, eo;\n        if (agent.isW3CRangeSupport) {\n          var selection = document.getSelection();\n          if (!selection || selection.rangeCount === 0) {\n            return null;\n          } else if (dom.isBody(selection.anchorNode)) {\n            // Firefox: returns entire body as range on initialization.\n            // We won't never need it.\n            return null;\n          }\n\n          var nativeRng = selection.getRangeAt(0);\n          sc = nativeRng.startContainer;\n          so = nativeRng.startOffset;\n          ec = nativeRng.endContainer;\n          eo = nativeRng.endOffset;\n        } else { // IE8: TextRange\n          var textRange = document.selection.createRange();\n          var textRangeEnd = textRange.duplicate();\n          textRangeEnd.collapse(false);\n          var textRangeStart = textRange;\n          textRangeStart.collapse(true);\n\n          var startPoint = textRangeToPoint(textRangeStart, true),\n          endPoint = textRangeToPoint(textRangeEnd, false);\n\n          // same visible point case: range was collapsed.\n          if (dom.isText(startPoint.node) && dom.isLeftEdgePoint(startPoint) &&\n              dom.isTextNode(endPoint.node) && dom.isRightEdgePoint(endPoint) &&\n              endPoint.node.nextSibling === startPoint.node) {\n            startPoint = endPoint;\n          }\n\n          sc = startPoint.cont;\n          so = startPoint.offset;\n          ec = endPoint.cont;\n          eo = endPoint.offset;\n        }\n\n        return new WrappedRange(sc, so, ec, eo);\n      },\n\n      /**\n       * @method \n       * \n       * create WrappedRange from node\n       *\n       * @param {Node} node\n       * @return {WrappedRange}\n       */\n      createFromNode: function (node) {\n        var sc = node;\n        var so = 0;\n        var ec = node;\n        var eo = dom.nodeLength(ec);\n\n        // browsers can't target a picture or void node\n        if (dom.isVoid(sc)) {\n          so = dom.listPrev(sc).length - 1;\n          sc = sc.parentNode;\n        }\n        if (dom.isBR(ec)) {\n          eo = dom.listPrev(ec).length - 1;\n          ec = ec.parentNode;\n        } else if (dom.isVoid(ec)) {\n          eo = dom.listPrev(ec).length;\n          ec = ec.parentNode;\n        }\n\n        return this.create(sc, so, ec, eo);\n      },\n\n      /**\n       * create WrappedRange from node after position\n       *\n       * @param {Node} node\n       * @return {WrappedRange}\n       */\n      createFromNodeBefore: function (node) {\n        return this.createFromNode(node).collapse(true);\n      },\n\n      /**\n       * create WrappedRange from node after position\n       *\n       * @param {Node} node\n       * @return {WrappedRange}\n       */\n      createFromNodeAfter: function (node) {\n        return this.createFromNode(node).collapse();\n      },\n\n      /**\n       * @method \n       * \n       * create WrappedRange from bookmark\n       *\n       * @param {Node} editable\n       * @param {Object} bookmark\n       * @return {WrappedRange}\n       */\n      createFromBookmark: function (editable, bookmark) {\n        var sc = dom.fromOffsetPath(editable, bookmark.s.path);\n        var so = bookmark.s.offset;\n        var ec = dom.fromOffsetPath(editable, bookmark.e.path);\n        var eo = bookmark.e.offset;\n        return new WrappedRange(sc, so, ec, eo);\n      },\n\n      /**\n       * @method \n       *\n       * create WrappedRange from paraBookmark\n       *\n       * @param {Object} bookmark\n       * @param {Node[]} paras\n       * @return {WrappedRange}\n       */\n      createFromParaBookmark: function (bookmark, paras) {\n        var so = bookmark.s.offset;\n        var eo = bookmark.e.offset;\n        var sc = dom.fromOffsetPath(list.head(paras), bookmark.s.path);\n        var ec = dom.fromOffsetPath(list.last(paras), bookmark.e.path);\n\n        return new WrappedRange(sc, so, ec, eo);\n      }\n    };\n  })();\n\n  /**\n   * @class core.async\n   *\n   * Async functions which returns `Promise`\n   *\n   * @singleton\n   * @alternateClassName async\n   */\n  var async = (function () {\n    /**\n     * @method readFileAsDataURL\n     *\n     * read contents of file as representing URL\n     *\n     * @param {File} file\n     * @return {Promise} - then: dataUrl\n     */\n    var readFileAsDataURL = function (file) {\n      return $.Deferred(function (deferred) {\n        $.extend(new FileReader(), {\n          onload: function (e) {\n            var dataURL = e.target.result;\n            deferred.resolve(dataURL);\n          },\n          onerror: function () {\n            deferred.reject(this);\n          }\n        }).readAsDataURL(file);\n      }).promise();\n    };\n  \n    /**\n     * @method createImage\n     *\n     * create `<image>` from url string\n     *\n     * @param {String} url\n     * @return {Promise} - then: $image\n     */\n    var createImage = function (url) {\n      return $.Deferred(function (deferred) {\n        var $img = $('<img>');\n\n        $img.one('load', function () {\n          $img.off('error abort');\n          deferred.resolve($img);\n        }).one('error abort', function () {\n          $img.off('load').detach();\n          deferred.reject($img);\n        }).css({\n          display: 'none'\n        }).appendTo(document.body).attr('src', url);\n      }).promise();\n    };\n\n    return {\n      readFileAsDataURL: readFileAsDataURL,\n      createImage: createImage\n    };\n  })();\n\n  /**\n   * @class editing.History\n   *\n   * Editor History\n   *\n   */\n  var History = function ($editable) {\n    var stack = [], stackOffset = -1;\n    var editable = $editable[0];\n\n    var makeSnapshot = function () {\n      var rng = range.create(editable);\n      var emptyBookmark = {s: {path: [], offset: 0}, e: {path: [], offset: 0}};\n\n      return {\n        contents: $editable.html(),\n        bookmark: (rng ? rng.bookmark(editable) : emptyBookmark)\n      };\n    };\n\n    var applySnapshot = function (snapshot) {\n      if (snapshot.contents !== null) {\n        $editable.html(snapshot.contents);\n      }\n      if (snapshot.bookmark !== null) {\n        range.createFromBookmark(editable, snapshot.bookmark).select();\n      }\n    };\n\n    /**\n    * @method rewind\n    * Rewinds the history stack back to the first snapshot taken.\n    * Leaves the stack intact, so that \"Redo\" can still be used.\n    */\n    this.rewind = function () {\n      // Create snap shot if not yet recorded\n      if ($editable.html() !== stack[stackOffset].contents) {\n        this.recordUndo();\n      }\n\n      // Return to the first available snapshot.\n      stackOffset = 0;\n\n      // Apply that snapshot.\n      applySnapshot(stack[stackOffset]);\n    };\n\n    /**\n    * @method reset\n    * Resets the history stack completely; reverting to an empty editor.\n    */\n    this.reset = function () {\n      // Clear the stack.\n      stack = [];\n\n      // Restore stackOffset to its original value.\n      stackOffset = -1;\n\n      // Clear the editable area.\n      $editable.html('');\n\n      // Record our first snapshot (of nothing).\n      this.recordUndo();\n    };\n\n    /**\n     * undo\n     */\n    this.undo = function () {\n      // Create snap shot if not yet recorded\n      if ($editable.html() !== stack[stackOffset].contents) {\n        this.recordUndo();\n      }\n\n      if (0 < stackOffset) {\n        stackOffset--;\n        applySnapshot(stack[stackOffset]);\n      }\n    };\n\n    /**\n     * redo\n     */\n    this.redo = function () {\n      if (stack.length - 1 > stackOffset) {\n        stackOffset++;\n        applySnapshot(stack[stackOffset]);\n      }\n    };\n\n    /**\n     * recorded undo\n     */\n    this.recordUndo = function () {\n      stackOffset++;\n\n      // Wash out stack after stackOffset\n      if (stack.length > stackOffset) {\n        stack = stack.slice(0, stackOffset);\n      }\n\n      // Create new snapshot and push it to the end\n      stack.push(makeSnapshot());\n    };\n  };\n\n  /**\n   * @class editing.Style\n   *\n   * Style\n   *\n   */\n  var Style = function () {\n    /**\n     * @method jQueryCSS\n     *\n     * [workaround] for old jQuery\n     * passing an array of style properties to .css()\n     * will result in an object of property-value pairs.\n     * (compability with version < 1.9)\n     *\n     * @private\n     * @param  {jQuery} $obj\n     * @param  {Array} propertyNames - An array of one or more CSS properties.\n     * @return {Object}\n     */\n    var jQueryCSS = function ($obj, propertyNames) {\n      if (agent.jqueryVersion < 1.9) {\n        var result = {};\n        $.each(propertyNames, function (idx, propertyName) {\n          result[propertyName] = $obj.css(propertyName);\n        });\n        return result;\n      }\n      return $obj.css.call($obj, propertyNames);\n    };\n\n    /**\n     * returns style object from node\n     *\n     * @param {jQuery} $node\n     * @return {Object}\n     */\n    this.fromNode = function ($node) {\n      var properties = ['font-family', 'font-size', 'text-align', 'list-style-type', 'line-height'];\n      var styleInfo = jQueryCSS($node, properties) || {};\n      styleInfo['font-size'] = parseInt(styleInfo['font-size'], 10);\n      return styleInfo;\n    };\n\n    /**\n     * paragraph level style\n     *\n     * @param {WrappedRange} rng\n     * @param {Object} styleInfo\n     */\n    this.stylePara = function (rng, styleInfo) {\n      $.each(rng.nodes(dom.isPara, {\n        includeAncestor: true\n      }), function (idx, para) {\n        $(para).css(styleInfo);\n      });\n    };\n\n    /**\n     * insert and returns styleNodes on range.\n     *\n     * @param {WrappedRange} rng\n     * @param {Object} [options] - options for styleNodes\n     * @param {String} [options.nodeName] - default: `SPAN`\n     * @param {Boolean} [options.expandClosestSibling] - default: `false`\n     * @param {Boolean} [options.onlyPartialContains] - default: `false`\n     * @return {Node[]}\n     */\n    this.styleNodes = function (rng, options) {\n      rng = rng.splitText();\n\n      var nodeName = options && options.nodeName || 'SPAN';\n      var expandClosestSibling = !!(options && options.expandClosestSibling);\n      var onlyPartialContains = !!(options && options.onlyPartialContains);\n\n      if (rng.isCollapsed()) {\n        return [rng.insertNode(dom.create(nodeName))];\n      }\n\n      var pred = dom.makePredByNodeName(nodeName);\n      var nodes = rng.nodes(dom.isText, {\n        fullyContains: true\n      }).map(function (text) {\n        return dom.singleChildAncestor(text, pred) || dom.wrap(text, nodeName);\n      });\n\n      if (expandClosestSibling) {\n        if (onlyPartialContains) {\n          var nodesInRange = rng.nodes();\n          // compose with partial contains predication\n          pred = func.and(pred, function (node) {\n            return list.contains(nodesInRange, node);\n          });\n        }\n\n        return nodes.map(function (node) {\n          var siblings = dom.withClosestSiblings(node, pred);\n          var head = list.head(siblings);\n          var tails = list.tail(siblings);\n          $.each(tails, function (idx, elem) {\n            dom.appendChildNodes(head, elem.childNodes);\n            dom.remove(elem);\n          });\n          return list.head(siblings);\n        });\n      } else {\n        return nodes;\n      }\n    };\n\n    /**\n     * get current style on cursor\n     *\n     * @param {WrappedRange} rng\n     * @return {Object} - object contains style properties.\n     */\n    this.current = function (rng) {\n      var $cont = $(!dom.isElement(rng.sc) ? rng.sc.parentNode : rng.sc);\n      var styleInfo = this.fromNode($cont);\n\n      // document.queryCommandState for toggle state\n      // [workaround] prevent Firefox nsresult: \"0x80004005 (NS_ERROR_FAILURE)\"\n      try {\n        styleInfo = $.extend(styleInfo, {\n          'font-bold': document.queryCommandState('bold') ? 'bold' : 'normal',\n          'font-italic': document.queryCommandState('italic') ? 'italic' : 'normal',\n          'font-underline': document.queryCommandState('underline') ? 'underline' : 'normal',\n          'font-subscript': document.queryCommandState('subscript') ? 'subscript' : 'normal',\n          'font-superscript': document.queryCommandState('superscript') ? 'superscript' : 'normal',\n          'font-strikethrough': document.queryCommandState('strikethrough') ? 'strikethrough' : 'normal'\n        });\n      } catch (e) {}\n\n      // list-style-type to list-style(unordered, ordered)\n      if (!rng.isOnList()) {\n        styleInfo['list-style'] = 'none';\n      } else {\n        var orderedTypes = ['circle', 'disc', 'disc-leading-zero', 'square'];\n        var isUnordered = $.inArray(styleInfo['list-style-type'], orderedTypes) > -1;\n        styleInfo['list-style'] = isUnordered ? 'unordered' : 'ordered';\n      }\n\n      var para = dom.ancestor(rng.sc, dom.isPara);\n      if (para && para.style['line-height']) {\n        styleInfo['line-height'] = para.style.lineHeight;\n      } else {\n        var lineHeight = parseInt(styleInfo['line-height'], 10) / parseInt(styleInfo['font-size'], 10);\n        styleInfo['line-height'] = lineHeight.toFixed(1);\n      }\n\n      styleInfo.anchor = rng.isOnAnchor() && dom.ancestor(rng.sc, dom.isAnchor);\n      styleInfo.ancestors = dom.listAncestor(rng.sc, dom.isEditable);\n      styleInfo.range = rng;\n\n      return styleInfo;\n    };\n  };\n\n\n  /**\n   * @class editing.Bullet\n   *\n   * @alternateClassName Bullet\n   */\n  var Bullet = function () {\n    var self = this;\n\n    /**\n     * toggle ordered list\n     */\n    this.insertOrderedList = function (editable) {\n      this.toggleList('OL', editable);\n    };\n\n    /**\n     * toggle unordered list\n     */\n    this.insertUnorderedList = function (editable) {\n      this.toggleList('UL', editable);\n    };\n\n    /**\n     * indent\n     */\n    this.indent = function (editable) {\n      var self = this;\n      var rng = range.create(editable).wrapBodyInlineWithPara();\n\n      var paras = rng.nodes(dom.isPara, { includeAncestor: true });\n      var clustereds = list.clusterBy(paras, func.peq2('parentNode'));\n\n      $.each(clustereds, function (idx, paras) {\n        var head = list.head(paras);\n        if (dom.isLi(head)) {\n          self.wrapList(paras, head.parentNode.nodeName);\n        } else {\n          $.each(paras, function (idx, para) {\n            $(para).css('marginLeft', function (idx, val) {\n              return (parseInt(val, 10) || 0) + 25;\n            });\n          });\n        }\n      });\n\n      rng.select();\n    };\n\n    /**\n     * outdent\n     */\n    this.outdent = function (editable) {\n      var self = this;\n      var rng = range.create(editable).wrapBodyInlineWithPara();\n\n      var paras = rng.nodes(dom.isPara, { includeAncestor: true });\n      var clustereds = list.clusterBy(paras, func.peq2('parentNode'));\n\n      $.each(clustereds, function (idx, paras) {\n        var head = list.head(paras);\n        if (dom.isLi(head)) {\n          self.releaseList([paras]);\n        } else {\n          $.each(paras, function (idx, para) {\n            $(para).css('marginLeft', function (idx, val) {\n              val = (parseInt(val, 10) || 0);\n              return val > 25 ? val - 25 : '';\n            });\n          });\n        }\n      });\n\n      rng.select();\n    };\n\n    /**\n     * toggle list\n     *\n     * @param {String} listName - OL or UL\n     */\n    this.toggleList = function (listName, editable) {\n      var rng = range.create(editable).wrapBodyInlineWithPara();\n\n      var paras = rng.nodes(dom.isPara, { includeAncestor: true });\n      var bookmark = rng.paraBookmark(paras);\n      var clustereds = list.clusterBy(paras, func.peq2('parentNode'));\n\n      // paragraph to list\n      if (list.find(paras, dom.isPurePara)) {\n        var wrappedParas = [];\n        $.each(clustereds, function (idx, paras) {\n          wrappedParas = wrappedParas.concat(self.wrapList(paras, listName));\n        });\n        paras = wrappedParas;\n      // list to paragraph or change list style\n      } else {\n        var diffLists = rng.nodes(dom.isList, {\n          includeAncestor: true\n        }).filter(function (listNode) {\n          return !$.nodeName(listNode, listName);\n        });\n\n        if (diffLists.length) {\n          $.each(diffLists, function (idx, listNode) {\n            dom.replace(listNode, listName);\n          });\n        } else {\n          paras = this.releaseList(clustereds, true);\n        }\n      }\n\n      range.createFromParaBookmark(bookmark, paras).select();\n    };\n\n    /**\n     * @param {Node[]} paras\n     * @param {String} listName\n     * @return {Node[]}\n     */\n    this.wrapList = function (paras, listName) {\n      var head = list.head(paras);\n      var last = list.last(paras);\n\n      var prevList = dom.isList(head.previousSibling) && head.previousSibling;\n      var nextList = dom.isList(last.nextSibling) && last.nextSibling;\n\n      var listNode = prevList || dom.insertAfter(dom.create(listName || 'UL'), last);\n\n      // P to LI\n      paras = paras.map(function (para) {\n        return dom.isPurePara(para) ? dom.replace(para, 'LI') : para;\n      });\n\n      // append to list(<ul>, <ol>)\n      dom.appendChildNodes(listNode, paras);\n\n      if (nextList) {\n        dom.appendChildNodes(listNode, list.from(nextList.childNodes));\n        dom.remove(nextList);\n      }\n\n      return paras;\n    };\n\n    /**\n     * @method releaseList\n     *\n     * @param {Array[]} clustereds\n     * @param {Boolean} isEscapseToBody\n     * @return {Node[]}\n     */\n    this.releaseList = function (clustereds, isEscapseToBody) {\n      var releasedParas = [];\n\n      $.each(clustereds, function (idx, paras) {\n        var head = list.head(paras);\n        var last = list.last(paras);\n\n        var headList = isEscapseToBody ? dom.lastAncestor(head, dom.isList) :\n                                         head.parentNode;\n        var lastList = headList.childNodes.length > 1 ? dom.splitTree(headList, {\n          node: last.parentNode,\n          offset: dom.position(last) + 1\n        }, {\n          isSkipPaddingBlankHTML: true\n        }) : null;\n\n        var middleList = dom.splitTree(headList, {\n          node: head.parentNode,\n          offset: dom.position(head)\n        }, {\n          isSkipPaddingBlankHTML: true\n        });\n\n        paras = isEscapseToBody ? dom.listDescendant(middleList, dom.isLi) :\n                                  list.from(middleList.childNodes).filter(dom.isLi);\n\n        // LI to P\n        if (isEscapseToBody || !dom.isList(headList.parentNode)) {\n          paras = paras.map(function (para) {\n            return dom.replace(para, 'P');\n          });\n        }\n\n        $.each(list.from(paras).reverse(), function (idx, para) {\n          dom.insertAfter(para, headList);\n        });\n\n        // remove empty lists\n        var rootLists = list.compact([headList, middleList, lastList]);\n        $.each(rootLists, function (idx, rootList) {\n          var listNodes = [rootList].concat(dom.listDescendant(rootList, dom.isList));\n          $.each(listNodes.reverse(), function (idx, listNode) {\n            if (!dom.nodeLength(listNode)) {\n              dom.remove(listNode, true);\n            }\n          });\n        });\n\n        releasedParas = releasedParas.concat(paras);\n      });\n\n      return releasedParas;\n    };\n  };\n\n\n  /**\n   * @class editing.Typing\n   *\n   * Typing\n   *\n   */\n  var Typing = function () {\n\n    // a Bullet instance to toggle lists off\n    var bullet = new Bullet();\n\n    /**\n     * insert tab\n     *\n     * @param {WrappedRange} rng\n     * @param {Number} tabsize\n     */\n    this.insertTab = function (rng, tabsize) {\n      var tab = dom.createText(new Array(tabsize + 1).join(dom.NBSP_CHAR));\n      rng = rng.deleteContents();\n      rng.insertNode(tab, true);\n\n      rng = range.create(tab, tabsize);\n      rng.select();\n    };\n\n    /**\n     * insert paragraph\n     */\n    this.insertParagraph = function (editable) {\n      var rng = range.create(editable);\n\n      // deleteContents on range.\n      rng = rng.deleteContents();\n\n      // Wrap range if it needs to be wrapped by paragraph\n      rng = rng.wrapBodyInlineWithPara();\n\n      // finding paragraph\n      var splitRoot = dom.ancestor(rng.sc, dom.isPara);\n\n      var nextPara;\n      // on paragraph: split paragraph\n      if (splitRoot) {\n        // if it is an empty line with li\n        if (dom.isEmpty(splitRoot) && dom.isLi(splitRoot)) {\n          // toogle UL/OL and escape\n          bullet.toggleList(splitRoot.parentNode.nodeName);\n          return;\n        // if it is an empty line with para on blockquote\n        } else if (dom.isEmpty(splitRoot) && dom.isPara(splitRoot) && dom.isBlockquote(splitRoot.parentNode)) {\n          // escape blockquote\n          dom.insertAfter(splitRoot, splitRoot.parentNode);\n          nextPara = splitRoot;\n        // if new line has content (not a line break)\n        } else {\n          nextPara = dom.splitTree(splitRoot, rng.getStartPoint());\n\n          var emptyAnchors = dom.listDescendant(splitRoot, dom.isEmptyAnchor);\n          emptyAnchors = emptyAnchors.concat(dom.listDescendant(nextPara, dom.isEmptyAnchor));\n\n          $.each(emptyAnchors, function (idx, anchor) {\n            dom.remove(anchor);\n          });\n\n          // replace empty heading or pre with P tag\n          if ((dom.isHeading(nextPara) || dom.isPre(nextPara)) && dom.isEmpty(nextPara)) {\n            nextPara = dom.replace(nextPara, 'p');\n          }\n        }\n      // no paragraph: insert empty paragraph\n      } else {\n        var next = rng.sc.childNodes[rng.so];\n        nextPara = $(dom.emptyPara)[0];\n        if (next) {\n          rng.sc.insertBefore(nextPara, next);\n        } else {\n          rng.sc.appendChild(nextPara);\n        }\n      }\n\n      range.create(nextPara, 0).normalize().select().scrollIntoView(editable);\n    };\n  };\n\n  /**\n   * @class editing.Table\n   *\n   * Table\n   *\n   */\n  var Table = function () {\n    /**\n     * handle tab key\n     *\n     * @param {WrappedRange} rng\n     * @param {Boolean} isShift\n     */\n    this.tab = function (rng, isShift) {\n      var cell = dom.ancestor(rng.commonAncestor(), dom.isCell);\n      var table = dom.ancestor(cell, dom.isTable);\n      var cells = dom.listDescendant(table, dom.isCell);\n\n      var nextCell = list[isShift ? 'prev' : 'next'](cells, cell);\n      if (nextCell) {\n        range.create(nextCell, 0).select();\n      }\n    };\n\n    /**\n     * create empty table element\n     *\n     * @param {Number} rowCount\n     * @param {Number} colCount\n     * @return {Node}\n     */\n    this.createTable = function (colCount, rowCount, options) {\n      var tds = [], tdHTML;\n      for (var idxCol = 0; idxCol < colCount; idxCol++) {\n        tds.push('<td>' + dom.blank + '</td>');\n      }\n      tdHTML = tds.join('');\n\n      var trs = [], trHTML;\n      for (var idxRow = 0; idxRow < rowCount; idxRow++) {\n        trs.push('<tr>' + tdHTML + '</tr>');\n      }\n      trHTML = trs.join('');\n      var $table = $('<table>' + trHTML + '</table>');\n      if (options && options.tableClassName) {\n        $table.addClass(options.tableClassName);\n      }\n\n      return $table[0];\n    };\n  };\n\n\n  var KEY_BOGUS = 'bogus';\n\n  /**\n   * @class Editor\n   */\n  var Editor = function (context) {\n    var self = this;\n\n    var $note = context.layoutInfo.note;\n    var $editor = context.layoutInfo.editor;\n    var $editable = context.layoutInfo.editable;\n    var options = context.options;\n    var lang = options.langInfo;\n\n    var editable = $editable[0];\n    var lastRange = null;\n\n    var style = new Style();\n    var table = new Table();\n    var typing = new Typing();\n    var bullet = new Bullet();\n    var history = new History($editable);\n\n    this.initialize = function () {\n      // bind custom events\n      $editable.on('keydown', function (event) {\n        if (event.keyCode === key.code.ENTER) {\n          context.triggerEvent('enter', event);\n        }\n        context.triggerEvent('keydown', event);\n\n        if (!event.isDefaultPrevented()) {\n          if (options.shortcuts) {\n            self.handleKeyMap(event);\n          } else {\n            self.preventDefaultEditableShortCuts(event);\n          }\n        }\n      }).on('keyup', function (event) {\n        context.triggerEvent('keyup', event);\n      }).on('focus', function (event) {\n        context.triggerEvent('focus', event);\n      }).on('blur', function (event) {\n        context.triggerEvent('blur', event);\n      }).on('mousedown', function (event) {\n        context.triggerEvent('mousedown', event);\n      }).on('mouseup', function (event) {\n        context.triggerEvent('mouseup', event);\n      }).on('scroll', function (event) {\n        context.triggerEvent('scroll', event);\n      }).on('paste', function (event) {\n        context.triggerEvent('paste', event);\n      });\n\n      // init content before set event\n      $editable.html(dom.html($note) || dom.emptyPara);\n\n      // [workaround] IE doesn't have input events for contentEditable\n      // - see: https://goo.gl/4bfIvA\n      var changeEventName = agent.isMSIE ? 'DOMCharacterDataModified DOMSubtreeModified DOMNodeInserted' : 'input';\n      $editable.on(changeEventName, func.debounce(function () {\n        context.triggerEvent('change', $editable.html());\n      }, 250));\n\n      $editor.on('focusin', function (event) {\n        context.triggerEvent('focusin', event);\n      }).on('focusout', function (event) {\n        context.triggerEvent('focusout', event);\n      });\n\n      if (!options.airMode) {\n        if (options.width) {\n          $editor.outerWidth(options.width);\n        }\n        if (options.height) {\n          $editable.outerHeight(options.height);\n        }\n        if (options.maxHeight) {\n          $editable.css('max-height', options.maxHeight);\n        }\n        if (options.minHeight) {\n          $editable.css('min-height', options.minHeight);\n        }\n      }\n\n      history.recordUndo();\n    };\n\n    this.destroy = function () {\n      $editable.off();\n    };\n\n    this.handleKeyMap = function (event) {\n      var keyMap = options.keyMap[agent.isMac ? 'mac' : 'pc'];\n      var keys = [];\n\n      if (event.metaKey) { keys.push('CMD'); }\n      if (event.ctrlKey && !event.altKey) { keys.push('CTRL'); }\n      if (event.shiftKey) { keys.push('SHIFT'); }\n\n      var keyName = key.nameFromCode[event.keyCode];\n      if (keyName) {\n        keys.push(keyName);\n      }\n\n      var eventName = keyMap[keys.join('+')];\n      if (eventName) {\n        event.preventDefault();\n        context.invoke(eventName);\n      } else if (key.isEdit(event.keyCode)) {\n        this.afterCommand();\n      }\n    };\n\n    this.preventDefaultEditableShortCuts = function (event) {\n      // B(Bold, 66) / I(Italic, 73) / U(Underline, 85)\n      if ((event.ctrlKey || event.metaKey) &&\n        list.contains([66, 73, 85], event.keyCode)) {\n        event.preventDefault();\n      }\n    };\n\n    /**\n     * create range\n     * @return {WrappedRange}\n     */\n    this.createRange = function () {\n      this.focus();\n      return range.create(editable);\n    };\n\n    /**\n     * saveRange\n     *\n     * save current range\n     *\n     * @param {Boolean} [thenCollapse=false]\n     */\n    this.saveRange = function (thenCollapse) {\n      lastRange = this.createRange();\n      if (thenCollapse) {\n        lastRange.collapse().select();\n      }\n    };\n\n    /**\n     * restoreRange\n     *\n     * restore lately range\n     */\n    this.restoreRange = function () {\n      if (lastRange) {\n        lastRange.select();\n        this.focus();\n      }\n    };\n\n    this.saveTarget = function (node) {\n      $editable.data('target', node);\n    };\n\n    this.clearTarget = function () {\n      $editable.removeData('target');\n    };\n\n    this.restoreTarget = function () {\n      return $editable.data('target');\n    };\n\n    /**\n     * currentStyle\n     *\n     * current style\n     * @return {Object|Boolean} unfocus\n     */\n    this.currentStyle = function () {\n      var rng = range.create();\n      if (rng) {\n        rng = rng.normalize();\n      }\n      return rng ? style.current(rng) : style.fromNode($editable);\n    };\n\n    /**\n     * style from node\n     *\n     * @param {jQuery} $node\n     * @return {Object}\n     */\n    this.styleFromNode = function ($node) {\n      return style.fromNode($node);\n    };\n\n    /**\n     * undo\n     */\n    this.undo = function () {\n      context.triggerEvent('before.command', $editable.html());\n      history.undo();\n      context.triggerEvent('change', $editable.html());\n    };\n    context.memo('help.undo', lang.help.undo);\n\n    /**\n     * redo\n     */\n    this.redo = function () {\n      context.triggerEvent('before.command', $editable.html());\n      history.redo();\n      context.triggerEvent('change', $editable.html());\n    };\n    context.memo('help.redo', lang.help.redo);\n\n    /**\n     * before command\n     */\n    var beforeCommand = this.beforeCommand = function () {\n      context.triggerEvent('before.command', $editable.html());\n      // keep focus on editable before command execution\n      self.focus();\n    };\n\n    /**\n     * after command\n     * @param {Boolean} isPreventTrigger\n     */\n    var afterCommand = this.afterCommand = function (isPreventTrigger) {\n      history.recordUndo();\n      if (!isPreventTrigger) {\n        context.triggerEvent('change', $editable.html());\n      }\n    };\n\n    /* jshint ignore:start */\n    // native commands(with execCommand), generate function for execCommand\n    var commands = ['bold', 'italic', 'underline', 'strikethrough', 'superscript', 'subscript',\n                    'justifyLeft', 'justifyCenter', 'justifyRight', 'justifyFull',\n                    'formatBlock', 'removeFormat',\n                    'backColor', 'foreColor', 'fontName'];\n\n    for (var idx = 0, len = commands.length; idx < len; idx ++) {\n      this[commands[idx]] = (function (sCmd) {\n        return function (value) {\n          beforeCommand();\n          document.execCommand(sCmd, false, value);\n          afterCommand(true);\n        };\n      })(commands[idx]);\n      context.memo('help.' + commands[idx], lang.help[commands[idx]]);\n    }\n    /* jshint ignore:end */\n\n    /**\n     * handle tab key\n     */\n    this.tab = function () {\n      var rng = this.createRange();\n      if (rng.isCollapsed() && rng.isOnCell()) {\n        table.tab(rng);\n      } else {\n        beforeCommand();\n        typing.insertTab(rng, options.tabSize);\n        afterCommand();\n      }\n    };\n    context.memo('help.tab', lang.help.tab);\n\n    /**\n     * handle shift+tab key\n     */\n    this.untab = function () {\n      var rng = this.createRange();\n      if (rng.isCollapsed() && rng.isOnCell()) {\n        table.tab(rng, true);\n      }\n    };\n    context.memo('help.untab', lang.help.untab);\n\n    /**\n     * run given function between beforeCommand and afterCommand\n     */\n    this.wrapCommand = function (fn) {\n      return function () {\n        beforeCommand();\n        fn.apply(self, arguments);\n        afterCommand();\n      };\n    };\n\n    /**\n     * insert paragraph\n     */\n    this.insertParagraph = this.wrapCommand(function () {\n      typing.insertParagraph(editable);\n    });\n    context.memo('help.insertParagraph', lang.help.insertParagraph);\n\n    this.insertOrderedList = this.wrapCommand(function () {\n      bullet.insertOrderedList(editable);\n    });\n    context.memo('help.insertOrderedList', lang.help.insertOrderedList);\n\n    this.insertUnorderedList = this.wrapCommand(function () {\n      bullet.insertUnorderedList(editable);\n    });\n    context.memo('help.insertUnorderedList', lang.help.insertUnorderedList);\n\n    this.indent = this.wrapCommand(function () {\n      bullet.indent(editable);\n    });\n    context.memo('help.indent', lang.help.indent);\n\n    this.outdent = this.wrapCommand(function () {\n      bullet.outdent(editable);\n    });\n    context.memo('help.outdent', lang.help.outdent);\n\n    /**\n     * insert image\n     *\n     * @param {String} src\n     * @param {String|Function} param\n     * @return {Promise}\n     */\n    this.insertImage = function (src, param) {\n      return async.createImage(src, param).then(function ($image) {\n        beforeCommand();\n\n        if (typeof param === 'function') {\n          param($image);\n        } else {\n          if (typeof param === 'string') {\n            $image.attr('data-filename', param);\n          }\n          $image.css('width', Math.min($editable.width(), $image.width()));\n        }\n\n        $image.show();\n        range.create(editable).insertNode($image[0]);\n        range.createFromNodeAfter($image[0]).select();\n        afterCommand();\n      }).fail(function (e) {\n        context.triggerEvent('image.upload.error', e);\n      });\n    };\n\n    /**\n     * insertImages\n     * @param {File[]} files\n     */\n    this.insertImages = function (files) {\n      $.each(files, function (idx, file) {\n        var filename = file.name;\n        if (options.maximumImageFileSize && options.maximumImageFileSize < file.size) {\n          context.triggerEvent('image.upload.error', lang.image.maximumFileSizeError);\n        } else {\n          async.readFileAsDataURL(file).then(function (dataURL) {\n            return self.insertImage(dataURL, filename);\n          }).fail(function () {\n            context.triggerEvent('image.upload.error');\n          });\n        }\n      });\n    };\n\n    /**\n     * insertImagesOrCallback\n     * @param {File[]} files\n     */\n    this.insertImagesOrCallback = function (files) {\n      var callbacks = options.callbacks;\n\n      // If onImageUpload options setted\n      if (callbacks.onImageUpload) {\n        context.triggerEvent('image.upload', files);\n      // else insert Image as dataURL\n      } else {\n        this.insertImages(files);\n      }\n    };\n\n    /**\n     * insertNode\n     * insert node\n     * @param {Node} node\n     */\n    this.insertNode = this.wrapCommand(function (node) {\n      var rng = this.createRange();\n      rng.insertNode(node);\n      range.createFromNodeAfter(node).select();\n    });\n\n    /**\n     * insert text\n     * @param {String} text\n     */\n    this.insertText = this.wrapCommand(function (text) {\n      var rng = this.createRange();\n      var textNode = rng.insertNode(dom.createText(text));\n      range.create(textNode, dom.nodeLength(textNode)).select();\n    });\n\n    /**\n     * return selected plain text\n     * @return {String} text\n     */\n    this.getSelectedText = function () {\n      var rng = this.createRange();\n\n      // if range on anchor, expand range with anchor\n      if (rng.isOnAnchor()) {\n        rng = range.createFromNode(dom.ancestor(rng.sc, dom.isAnchor));\n      }\n\n      return rng.toString();\n    };\n\n    /**\n     * paste HTML\n     * @param {String} markup\n     */\n    this.pasteHTML = this.wrapCommand(function (markup) {\n      var contents = this.createRange().pasteHTML(markup);\n      range.createFromNodeAfter(list.last(contents)).select();\n    });\n\n    /**\n     * formatBlock\n     *\n     * @param {String} tagName\n     */\n    this.formatBlock = this.wrapCommand(function (tagName) {\n      // [workaround] for MSIE, IE need `<`\n      tagName = agent.isMSIE ? '<' + tagName + '>' : tagName;\n      document.execCommand('FormatBlock', false, tagName);\n    });\n\n    this.formatPara = function () {\n      this.formatBlock('P');\n    };\n    context.memo('help.formatPara', lang.help.formatPara);\n\n    /* jshint ignore:start */\n    for (var idx = 1; idx <= 6; idx ++) {\n      this['formatH' + idx] = function (idx) {\n        return function () {\n          this.formatBlock('H' + idx);\n        };\n      }(idx);\n      context.memo('help.formatH'+idx, lang.help['formatH' + idx]);\n    };\n    /* jshint ignore:end */\n\n    /**\n     * fontSize\n     *\n     * @param {String} value - px\n     */\n    this.fontSize = function (value) {\n      var rng = this.createRange();\n\n      if (rng && rng.isCollapsed()) {\n        var spans = style.styleNodes(rng);\n        var firstSpan = list.head(spans);\n\n        $(spans).css({\n          'font-size': value + 'px'\n        });\n\n        // [workaround] added styled bogus span for style\n        //  - also bogus character needed for cursor position\n        if (firstSpan && !dom.nodeLength(firstSpan)) {\n          firstSpan.innerHTML = dom.ZERO_WIDTH_NBSP_CHAR;\n          range.createFromNodeAfter(firstSpan.firstChild).select();\n          $editable.data(KEY_BOGUS, firstSpan);\n        }\n      } else {\n        beforeCommand();\n        $(style.styleNodes(rng)).css({\n          'font-size': value + 'px'\n        });\n        afterCommand();\n      }\n    };\n\n    /**\n     * insert horizontal rule\n     */\n    this.insertHorizontalRule = this.wrapCommand(function () {\n      var hrNode = this.createRange().insertNode(dom.create('HR'));\n      if (hrNode.nextSibling) {\n        range.create(hrNode.nextSibling, 0).normalize().select();\n      }\n    });\n    context.memo('help.insertHorizontalRule', lang.help.insertHorizontalRule);\n\n    /**\n     * remove bogus node and character\n     */\n    this.removeBogus = function () {\n      var bogusNode = $editable.data(KEY_BOGUS);\n      if (!bogusNode) {\n        return;\n      }\n\n      var textNode = list.find(list.from(bogusNode.childNodes), dom.isText);\n\n      var bogusCharIdx = textNode.nodeValue.indexOf(dom.ZERO_WIDTH_NBSP_CHAR);\n      if (bogusCharIdx !== -1) {\n        textNode.deleteData(bogusCharIdx, 1);\n      }\n\n      if (dom.isEmpty(bogusNode)) {\n        dom.remove(bogusNode);\n      }\n\n      $editable.removeData(KEY_BOGUS);\n    };\n\n    /**\n     * lineHeight\n     * @param {String} value\n     */\n    this.lineHeight = this.wrapCommand(function (value) {\n      style.stylePara(this.createRange(), {\n        lineHeight: value\n      });\n    });\n\n    /**\n     * unlink\n     *\n     * @type command\n     */\n    this.unlink = function () {\n      var rng = this.createRange();\n      if (rng.isOnAnchor()) {\n        var anchor = dom.ancestor(rng.sc, dom.isAnchor);\n        rng = range.createFromNode(anchor);\n        rng.select();\n\n        beforeCommand();\n        document.execCommand('unlink');\n        afterCommand();\n      }\n    };\n\n    /**\n     * create link (command)\n     *\n     * @param {Object} linkInfo\n     */\n    this.createLink = this.wrapCommand(function (linkInfo) {\n      var linkUrl = linkInfo.url;\n      var linkText = linkInfo.text;\n      var isNewWindow = linkInfo.isNewWindow;\n      var rng = linkInfo.range || this.createRange();\n      var isTextChanged = rng.toString() !== linkText;\n\n      // handle spaced urls from input\n      if (typeof linkUrl === 'string') {\n        linkUrl = linkUrl.trim();\n      }\n\n      if (options.onCreateLink) {\n        linkUrl = options.onCreateLink(linkUrl);\n      }\n\n      var anchors = [];\n      if (isTextChanged) {\n        rng = rng.deleteContents();\n        var anchor = rng.insertNode($('<A>' + linkText + '</A>')[0]);\n        anchors.push(anchor);\n      } else {\n        anchors = style.styleNodes(rng, {\n          nodeName: 'A',\n          expandClosestSibling: true,\n          onlyPartialContains: true\n        });\n      }\n\n      $.each(anchors, function (idx, anchor) {\n        // if url doesn't match an URL schema, set http:// as default\n        linkUrl = /^[A-Za-z][A-Za-z0-9+-.]*\\:[\\/\\/]?/.test(linkUrl) ?\n          linkUrl : 'http://' + linkUrl;\n\n        $(anchor).attr('href', linkUrl);\n        if (isNewWindow) {\n          $(anchor).attr('target', '_blank');\n        } else {\n          $(anchor).removeAttr('target');\n        }\n      });\n\n      var startRange = range.createFromNodeBefore(list.head(anchors));\n      var startPoint = startRange.getStartPoint();\n      var endRange = range.createFromNodeAfter(list.last(anchors));\n      var endPoint = endRange.getEndPoint();\n\n      range.create(\n        startPoint.node,\n        startPoint.offset,\n        endPoint.node,\n        endPoint.offset\n      ).select();\n    });\n\n    /**\n     * returns link info\n     *\n     * @return {Object}\n     * @return {WrappedRange} return.range\n     * @return {String} return.text\n     * @return {Boolean} [return.isNewWindow=true]\n     * @return {String} [return.url=\"\"]\n     */\n    this.getLinkInfo = function () {\n      var rng = this.createRange().expand(dom.isAnchor);\n\n      // Get the first anchor on range(for edit).\n      var $anchor = $(list.head(rng.nodes(dom.isAnchor)));\n\n      return {\n        range: rng,\n        text: rng.toString(),\n        isNewWindow: $anchor.length ? $anchor.attr('target') === '_blank' : false,\n        url: $anchor.length ? $anchor.attr('href') : ''\n      };\n    };\n\n    /**\n     * setting color\n     *\n     * @param {Object} sObjColor  color code\n     * @param {String} sObjColor.foreColor foreground color\n     * @param {String} sObjColor.backColor background color\n     */\n    this.color = this.wrapCommand(function (colorInfo) {\n      var foreColor = colorInfo.foreColor;\n      var backColor = colorInfo.backColor;\n\n      if (foreColor) { document.execCommand('foreColor', false, foreColor); }\n      if (backColor) { document.execCommand('backColor', false, backColor); }\n    });\n\n    /**\n     * insert Table\n     *\n     * @param {String} dimension of table (ex : \"5x5\")\n     */\n    this.insertTable = this.wrapCommand(function (dim) {\n      var dimension = dim.split('x');\n\n      var rng = this.createRange().deleteContents();\n      rng.insertNode(table.createTable(dimension[0], dimension[1], options));\n    });\n\n    /**\n     * float me\n     *\n     * @param {String} value\n     */\n    this.floatMe = this.wrapCommand(function (value) {\n      var $target = $(this.restoreTarget());\n      $target.css('float', value);\n    });\n\n    /**\n     * resize overlay element\n     * @param {String} value\n     */\n    this.resize = this.wrapCommand(function (value) {\n      var $target = $(this.restoreTarget());\n      $target.css({\n        width: value * 100 + '%',\n        height: ''\n      });\n    });\n\n    /**\n     * @param {Position} pos\n     * @param {jQuery} $target - target element\n     * @param {Boolean} [bKeepRatio] - keep ratio\n     */\n    this.resizeTo = function (pos, $target, bKeepRatio) {\n      var imageSize;\n      if (bKeepRatio) {\n        var newRatio = pos.y / pos.x;\n        var ratio = $target.data('ratio');\n        imageSize = {\n          width: ratio > newRatio ? pos.x : pos.y / ratio,\n          height: ratio > newRatio ? pos.x * ratio : pos.y\n        };\n      } else {\n        imageSize = {\n          width: pos.x,\n          height: pos.y\n        };\n      }\n\n      $target.css(imageSize);\n    };\n\n    /**\n     * remove media object\n     */\n    this.removeMedia = this.wrapCommand(function () {\n      var $target = $(this.restoreTarget()).detach();\n      context.triggerEvent('media.delete', $target, $editable);\n    });\n\n    /**\n     * returns whether editable area has focus or not.\n     */\n    this.hasFocus = function () {\n      return $editable.is(':focus');\n    };\n\n    /**\n     * set focus\n     */\n    this.focus = function () {\n      // [workaround] Screen will move when page is scolled in IE.\n      //  - do focus when not focused\n      if (!this.hasFocus()) {\n        $editable.focus();\n      }\n    };\n\n    /**\n     * returns whether contents is empty or not.\n     * @return {Boolean}\n     */\n    this.isEmpty = function () {\n      return dom.isEmpty($editable[0]) || dom.emptyPara === $editable.html();\n    };\n\n    /**\n     * Removes all contents and restores the editable instance to an _emptyPara_.\n     */\n    this.empty = function () {\n      context.invoke('code', dom.emptyPara);\n    };\n  };\n\n  var Clipboard = function (context) {\n    var self = this;\n\n    var $editable = context.layoutInfo.editable;\n\n    this.events = {\n      'summernote.keydown': function (we, e) {\n        if (self.needKeydownHook()) {\n          if ((e.ctrlKey || e.metaKey) && e.keyCode === key.code.V) {\n            context.invoke('editor.saveRange');\n            self.$paste.focus();\n\n            setTimeout(function () {\n              self.pasteByHook();\n            }, 0);\n          }\n        }\n      }\n    };\n\n    this.needKeydownHook = function () {\n      return (agent.isMSIE && agent.browserVersion > 10) || agent.isFF;\n    };\n\n    this.initialize = function () {\n      // [workaround] getting image from clipboard\n      //  - IE11 and Firefox: CTRL+v hook\n      //  - Webkit: event.clipboardData\n      if (this.needKeydownHook()) {\n        this.$paste = $('<div tabindex=\"-1\" />').attr('contenteditable', true).css({\n          position: 'absolute',\n          left: -100000,\n          opacity: 0\n        });\n        $editable.before(this.$paste);\n\n        this.$paste.on('paste', function (event) {\n          context.triggerEvent('paste', event);\n        });\n      } else {\n        $editable.on('paste', this.pasteByEvent);\n      }\n    };\n\n    this.destroy = function () {\n      if (this.needKeydownHook()) {\n        this.$paste.remove();\n        this.$paste = null;\n      }\n    };\n\n    this.pasteByHook = function () {\n      var node = this.$paste[0].firstChild;\n\n      if (dom.isImg(node)) {\n        var dataURI = node.src;\n        var decodedData = atob(dataURI.split(',')[1]);\n        var array = new Uint8Array(decodedData.length);\n        for (var i = 0; i < decodedData.length; i++) {\n          array[i] = decodedData.charCodeAt(i);\n        }\n\n        var blob = new Blob([array], { type: 'image/png' });\n        blob.name = 'clipboard.png';\n\n        context.invoke('editor.restoreRange');\n        context.invoke('editor.focus');\n        context.invoke('editor.insertImagesOrCallback', [blob]);\n      } else {\n        var pasteContent = $('<div />').html(this.$paste.html()).html();\n        context.invoke('editor.restoreRange');\n        context.invoke('editor.focus');\n\n        if (pasteContent) {\n          context.invoke('editor.pasteHTML', pasteContent);\n        }\n      }\n\n      this.$paste.empty();\n    };\n\n    /**\n     * paste by clipboard event\n     *\n     * @param {Event} event\n     */\n    this.pasteByEvent = function (event) {\n      var clipboardData = event.originalEvent.clipboardData;\n      if (clipboardData && clipboardData.items && clipboardData.items.length) {\n        var item = list.head(clipboardData.items);\n        if (item.kind === 'file' && item.type.indexOf('image/') !== -1) {\n          context.invoke('editor.insertImagesOrCallback', [item.getAsFile()]);\n        }\n        context.invoke('editor.afterCommand');\n      }\n    };\n  };\n\n  var Dropzone = function (context) {\n    var $document = $(document);\n    var $editor = context.layoutInfo.editor;\n    var $editable = context.layoutInfo.editable;\n    var options = context.options;\n    var lang = options.langInfo;\n    var documentEventHandlers = {};\n\n    var $dropzone = $([\n      '<div class=\"note-dropzone\">',\n      '  <div class=\"note-dropzone-message\"/>',\n      '</div>'\n    ].join('')).prependTo($editor);\n\n    var detachDocumentEvent = function () {\n      Object.keys(documentEventHandlers).forEach(function (key) {\n        $document.off(key.substr(2).toLowerCase(), documentEventHandlers[key]);\n      });\n      documentEventHandlers = {};\n    };\n\n    /**\n     * attach Drag and Drop Events\n     */\n    this.initialize = function () {\n      if (options.disableDragAndDrop) {\n        // prevent default drop event\n        documentEventHandlers.onDrop = function (e) {\n          e.preventDefault();\n        };\n        $document.on('drop', documentEventHandlers.onDrop);\n      } else {\n        this.attachDragAndDropEvent();\n      }\n    };\n\n    /**\n     * attach Drag and Drop Events\n     */\n    this.attachDragAndDropEvent = function () {\n      var collection = $(),\n          $dropzoneMessage = $dropzone.find('.note-dropzone-message');\n\n      documentEventHandlers.onDragenter = function (e) {\n        var isCodeview = context.invoke('codeview.isActivated');\n        var hasEditorSize = $editor.width() > 0 && $editor.height() > 0;\n        if (!isCodeview && !collection.length && hasEditorSize) {\n          $editor.addClass('dragover');\n          $dropzone.width($editor.width());\n          $dropzone.height($editor.height());\n          $dropzoneMessage.text(lang.image.dragImageHere);\n        }\n        collection = collection.add(e.target);\n      };\n\n      documentEventHandlers.onDragleave = function (e) {\n        collection = collection.not(e.target);\n        if (!collection.length) {\n          $editor.removeClass('dragover');\n        }\n      };\n\n      documentEventHandlers.onDrop = function () {\n        collection = $();\n        $editor.removeClass('dragover');\n      };\n\n      // show dropzone on dragenter when dragging a object to document\n      // -but only if the editor is visible, i.e. has a positive width and height\n      $document.on('dragenter', documentEventHandlers.onDragenter)\n        .on('dragleave', documentEventHandlers.onDragleave)\n        .on('drop', documentEventHandlers.onDrop);\n\n      // change dropzone's message on hover.\n      $dropzone.on('dragenter', function () {\n        $dropzone.addClass('hover');\n        $dropzoneMessage.text(lang.image.dropImage);\n      }).on('dragleave', function () {\n        $dropzone.removeClass('hover');\n        $dropzoneMessage.text(lang.image.dragImageHere);\n      });\n\n      // attach dropImage\n      $dropzone.on('drop', function (event) {\n        var dataTransfer = event.originalEvent.dataTransfer;\n\n        if (dataTransfer && dataTransfer.files && dataTransfer.files.length) {\n          event.preventDefault();\n          $editable.focus();\n          context.invoke('editor.insertImagesOrCallback', dataTransfer.files);\n        } else {\n          $.each(dataTransfer.types, function (idx, type) {\n            var content = dataTransfer.getData(type);\n\n            if (type.toLowerCase().indexOf('text') > -1) {\n              context.invoke('editor.pasteHTML', content);\n            } else {\n              $(content).each(function () {\n                context.invoke('editor.insertNode', this);\n              });\n            }\n          });\n        }\n      }).on('dragover', false); // prevent default dragover event\n    };\n\n    this.destroy = function () {\n      detachDocumentEvent();\n    };\n  };\n\n\n  var CodeMirror;\n  if (agent.hasCodeMirror) {\n    if (agent.isSupportAmd) {\n      require(['codemirror'], function (cm) {\n        CodeMirror = cm;\n      });\n    } else {\n      CodeMirror = window.CodeMirror;\n    }\n  }\n\n  /**\n   * @class Codeview\n   */\n  var Codeview = function (context) {\n    var $editor = context.layoutInfo.editor;\n    var $editable = context.layoutInfo.editable;\n    var $codable = context.layoutInfo.codable;\n    var options = context.options;\n\n    this.sync = function () {\n      var isCodeview = this.isActivated();\n      if (isCodeview && agent.hasCodeMirror) {\n        $codable.data('cmEditor').save();\n      }\n    };\n\n    /**\n     * @return {Boolean}\n     */\n    this.isActivated = function () {\n      return $editor.hasClass('codeview');\n    };\n\n    /**\n     * toggle codeview\n     */\n    this.toggle = function () {\n      if (this.isActivated()) {\n        this.deactivate();\n      } else {\n        this.activate();\n      }\n      context.triggerEvent('codeview.toggled');\n    };\n\n    /**\n     * activate code view\n     */\n    this.activate = function () {\n      $codable.val(dom.html($editable, options.prettifyHtml));\n      $codable.height($editable.height());\n\n      context.invoke('toolbar.updateCodeview', true);\n      $editor.addClass('codeview');\n      $codable.focus();\n\n      // activate CodeMirror as codable\n      if (agent.hasCodeMirror) {\n        var cmEditor = CodeMirror.fromTextArea($codable[0], options.codemirror);\n\n        // CodeMirror TernServer\n        if (options.codemirror.tern) {\n          var server = new CodeMirror.TernServer(options.codemirror.tern);\n          cmEditor.ternServer = server;\n          cmEditor.on('cursorActivity', function (cm) {\n            server.updateArgHints(cm);\n          });\n        }\n\n        // CodeMirror hasn't Padding.\n        cmEditor.setSize(null, $editable.outerHeight());\n        $codable.data('cmEditor', cmEditor);\n      }\n    };\n\n    /**\n     * deactivate code view\n     */\n    this.deactivate = function () {\n      // deactivate CodeMirror as codable\n      if (agent.hasCodeMirror) {\n        var cmEditor = $codable.data('cmEditor');\n        $codable.val(cmEditor.getValue());\n        cmEditor.toTextArea();\n      }\n\n      var value = dom.value($codable, options.prettifyHtml) || dom.emptyPara;\n      var isChange = $editable.html() !== value;\n\n      $editable.html(value);\n      $editable.height(options.height ? $codable.height() : 'auto');\n      $editor.removeClass('codeview');\n\n      if (isChange) {\n        context.triggerEvent('change', $editable.html(), $editable);\n      }\n\n      $editable.focus();\n\n      context.invoke('toolbar.updateCodeview', false);\n    };\n\n    this.destroy = function () {\n      if (this.isActivated()) {\n        this.deactivate();\n      }\n    };\n  };\n\n  var EDITABLE_PADDING = 24;\n\n  var Statusbar = function (context) {\n    var $document = $(document);\n    var $statusbar = context.layoutInfo.statusbar;\n    var $editable = context.layoutInfo.editable;\n    var options = context.options;\n\n    this.initialize = function () {\n      if (options.airMode || options.disableResizeEditor) {\n        return;\n      }\n\n      $statusbar.on('mousedown', function (event) {\n        event.preventDefault();\n        event.stopPropagation();\n\n        var editableTop = $editable.offset().top - $document.scrollTop();\n\n        $document.on('mousemove', function (event) {\n          var height = event.clientY - (editableTop + EDITABLE_PADDING);\n\n          height = (options.minheight > 0) ? Math.max(height, options.minheight) : height;\n          height = (options.maxHeight > 0) ? Math.min(height, options.maxHeight) : height;\n\n          $editable.height(height);\n        }).one('mouseup', function () {\n          $document.off('mousemove');\n        });\n      });\n    };\n\n    this.destroy = function () {\n      $statusbar.off();\n      $statusbar.remove();\n    };\n  };\n\n  var Fullscreen = function (context) {\n    var $editor = context.layoutInfo.editor;\n    var $toolbar = context.layoutInfo.toolbar;\n    var $editable = context.layoutInfo.editable;\n    var $codable = context.layoutInfo.codable;\n\n    var $window = $(window);\n    var $scrollbar = $('html, body');\n\n    /**\n     * toggle fullscreen\n     */\n    this.toggle = function () {\n      var resize = function (size) {\n        $editable.css('height', size.h);\n        $codable.css('height', size.h);\n        if ($codable.data('cmeditor')) {\n          $codable.data('cmeditor').setsize(null, size.h);\n        }\n      };\n\n      $editor.toggleClass('fullscreen');\n      if (this.isFullscreen()) {\n        $editable.data('orgHeight', $editable.css('height'));\n\n        $window.on('resize', function () {\n          resize({\n            h: $window.height() - $toolbar.outerHeight()\n          });\n        }).trigger('resize');\n\n        $scrollbar.css('overflow', 'hidden');\n      } else {\n        $window.off('resize');\n        resize({\n          h: $editable.data('orgHeight')\n        });\n        $scrollbar.css('overflow', 'visible');\n      }\n\n      context.invoke('toolbar.updateFullscreen', this.isFullscreen());\n    };\n\n    this.isFullscreen = function () {\n      return $editor.hasClass('fullscreen');\n    };\n  };\n\n  var Handle = function (context) {\n    var self = this;\n\n    var $document = $(document);\n    var $editingArea = context.layoutInfo.editingArea;\n    var options = context.options;\n\n    this.events = {\n      'summernote.mousedown': function (we, e) {\n        if (self.update(e.target)) {\n          e.preventDefault();\n        }\n      },\n      'summernote.keyup summernote.scroll summernote.change summernote.dialog.shown': function () {\n        self.update();\n      }\n    };\n\n    this.initialize = function () {\n      this.$handle = $([\n        '<div class=\"note-handle\">',\n        '<div class=\"note-control-selection\">',\n        '<div class=\"note-control-selection-bg\"></div>',\n        '<div class=\"note-control-holder note-control-nw\"></div>',\n        '<div class=\"note-control-holder note-control-ne\"></div>',\n        '<div class=\"note-control-holder note-control-sw\"></div>',\n        '<div class=\"',\n        (options.disableResizeImage ? 'note-control-holder' : 'note-control-sizing'),\n        ' note-control-se\"></div>',\n        (options.disableResizeImage ? '' : '<div class=\"note-control-selection-info\"></div>'),\n        '</div>',\n        '</div>'\n      ].join('')).prependTo($editingArea);\n\n      this.$handle.on('mousedown', function (event) {\n        if (dom.isControlSizing(event.target)) {\n          event.preventDefault();\n          event.stopPropagation();\n\n          var $target = self.$handle.find('.note-control-selection').data('target'),\n              posStart = $target.offset(),\n              scrollTop = $document.scrollTop();\n\n          $document.on('mousemove', function (event) {\n            context.invoke('editor.resizeTo', {\n              x: event.clientX - posStart.left,\n              y: event.clientY - (posStart.top - scrollTop)\n            }, $target, !event.shiftKey);\n\n            self.update($target[0]);\n          }).one('mouseup', function (e) {\n            e.preventDefault();\n            $document.off('mousemove');\n            context.invoke('editor.afterCommand');\n          });\n\n          if (!$target.data('ratio')) { // original ratio.\n            $target.data('ratio', $target.height() / $target.width());\n          }\n        }\n      });\n    };\n\n    this.destroy = function () {\n      this.$handle.remove();\n    };\n\n    this.update = function (target) {\n      var isImage = dom.isImg(target);\n      var $selection = this.$handle.find('.note-control-selection');\n\n      context.invoke('imagePopover.update', target);\n\n      if (isImage) {\n        var $image = $(target);\n        var pos = $image.position();\n\n        // include margin\n        var imageSize = {\n          w: $image.outerWidth(true),\n          h: $image.outerHeight(true)\n        };\n\n        $selection.css({\n          display: 'block',\n          left: pos.left,\n          top: pos.top,\n          width: imageSize.w,\n          height: imageSize.h\n        }).data('target', $image); // save current image element.\n\n        var sizingText = imageSize.w + 'x' + imageSize.h;\n        $selection.find('.note-control-selection-info').text(sizingText);\n        context.invoke('editor.saveTarget', target);\n      } else {\n        this.hide();\n      }\n\n      return isImage;\n    };\n\n    /**\n     * hide\n     *\n     * @param {jQuery} $handle\n     */\n    this.hide = function () {\n      context.invoke('editor.clearTarget');\n      this.$handle.children().hide();\n    };\n  };\n\n  var AutoLink = function (context) {\n    var self = this;\n    var defaultScheme = 'http://';\n    var linkPattern = /^([A-Za-z][A-Za-z0-9+-.]*\\:[\\/\\/]?|mailto:[A-Z0-9._%+-]+@)?(www\\.)?(.+)$/i;\n\n    this.events = {\n      'summernote.keyup': function (we, e) {\n        if (!e.isDefaultPrevented()) {\n          self.handleKeyup(e);\n        }\n      },\n      'summernote.keydown': function (we, e) {\n        self.handleKeydown(e);\n      }\n    };\n\n    this.initialize = function () {\n      this.lastWordRange = null;\n    };\n\n    this.destroy = function () {\n      this.lastWordRange = null;\n    };\n\n    this.replace = function () {\n      if (!this.lastWordRange) {\n        return;\n      }\n\n      var keyword = this.lastWordRange.toString();\n      var match = keyword.match(linkPattern);\n\n      if (match && (match[1] || match[2])) {\n        var link = match[1] ? keyword : defaultScheme + keyword;\n        var node = $('<a />').html(keyword).attr('href', link)[0];\n\n        this.lastWordRange.insertNode(node);\n        this.lastWordRange = null;\n        context.invoke('editor.focus');\n      }\n\n    };\n\n    this.handleKeydown = function (e) {\n      if (list.contains([key.code.ENTER, key.code.SPACE], e.keyCode)) {\n        var wordRange = context.invoke('editor.createRange').getWordRange();\n        this.lastWordRange = wordRange;\n      }\n    };\n\n    this.handleKeyup = function (e) {\n      if (list.contains([key.code.ENTER, key.code.SPACE], e.keyCode)) {\n        this.replace();\n      }\n    };\n  };\n\n  /**\n   * textarea auto sync.\n   */\n  var AutoSync = function (context) {\n    var $note = context.layoutInfo.note;\n\n    this.events = {\n      'summernote.change': function () {\n        $note.val(context.invoke('code'));\n      }\n    };\n\n    this.shouldInitialize = function () {\n      return dom.isTextarea($note[0]);\n    };\n  };\n\n  var Placeholder = function (context) {\n    var self = this;\n    var $editingArea = context.layoutInfo.editingArea;\n    var options = context.options;\n\n    this.events = {\n      'summernote.init summernote.change': function () {\n        self.update();\n      },\n      'summernote.codeview.toggled': function () {\n        self.update();\n      }\n    };\n\n    this.shouldInitialize = function () {\n      return !!options.placeholder;\n    };\n\n    this.initialize = function () {\n      this.$placeholder = $('<div class=\"note-placeholder\">');\n      this.$placeholder.on('click', function () {\n        context.invoke('focus');\n      }).text(options.placeholder).prependTo($editingArea);\n    };\n\n    this.destroy = function () {\n      this.$placeholder.remove();\n    };\n\n    this.update = function () {\n      var isShow = !context.invoke('codeview.isActivated') && context.invoke('editor.isEmpty');\n      this.$placeholder.toggle(isShow);\n    };\n  };\n\n  var Buttons = function (context) {\n    var self = this;\n    var ui = $.summernote.ui;\n\n    var $toolbar = context.layoutInfo.toolbar;\n    var options = context.options;\n    var lang = options.langInfo;\n\n    var invertedKeyMap = func.invertObject(options.keyMap[agent.isMac ? 'mac' : 'pc']);\n\n    var representShortcut = this.representShortcut = function (editorMethod) {\n      var shortcut = invertedKeyMap[editorMethod];\n      if (!options.shortcuts || !shortcut) {\n        return '';\n      }\n      \n      if (agent.isMac) {\n        shortcut = shortcut.replace('CMD', '⌘').replace('SHIFT', '⇧');\n      }\n\n      shortcut = shortcut.replace('BACKSLASH', '\\\\')\n                         .replace('SLASH', '/')\n                         .replace('LEFTBRACKET', '[')\n                         .replace('RIGHTBRACKET', ']');\n\n      return ' (' + shortcut + ')';\n    };\n\n    this.initialize = function () {\n      this.addToolbarButtons();\n      this.addImagePopoverButtons();\n      this.addLinkPopoverButtons();\n      this.fontInstalledMap = {};\n    };\n\n    this.destroy = function () {\n      delete this.fontInstalledMap;\n    };\n\n    this.isFontInstalled = function (name) {\n      if (!self.fontInstalledMap.hasOwnProperty(name)) {\n        self.fontInstalledMap[name] = agent.isFontInstalled(name) ||\n          list.contains(options.fontNamesIgnoreCheck, name);\n      }\n\n      return self.fontInstalledMap[name];\n    };\n\n    this.addToolbarButtons = function () {\n      context.memo('button.style', function () {\n        return ui.buttonGroup([\n          ui.button({\n            className: 'dropdown-toggle',\n            contents: ui.icon(options.icons.magic) + ' ' + ui.icon(options.icons.caret, 'span'),\n            tooltip: lang.style.style,\n            data: {\n              toggle: 'dropdown'\n            }\n          }),\n          ui.dropdown({\n            className: 'dropdown-style',\n            items: context.options.styleTags,\n            template: function (item) {\n\n              if (typeof item === 'string') {\n                item = { tag: item, title: (lang.style.hasOwnProperty(item) ? lang.style[item] : item) };\n              }\n\n              var tag = item.tag;\n              var title = item.title;\n              var style = item.style ? ' style=\"' + item.style + '\" ' : '';\n              var className = item.className ? ' class=\"' + item.className + '\"' : '';\n\n              return '<' + tag + style + className + '>' + title + '</' + tag +  '>';\n            },\n            click: context.createInvokeHandler('editor.formatBlock')\n          })\n        ]).render();\n      });\n\n      context.memo('button.bold', function () {\n        return ui.button({\n          className: 'note-btn-bold',\n          contents: ui.icon(options.icons.bold),\n          tooltip: lang.font.bold + representShortcut('bold'),\n          click: context.createInvokeHandler('editor.bold')\n        }).render();\n      });\n\n      context.memo('button.italic', function () {\n        return ui.button({\n          className: 'note-btn-italic',\n          contents: ui.icon(options.icons.italic),\n          tooltip: lang.font.italic + representShortcut('italic'),\n          click: context.createInvokeHandler('editor.italic')\n        }).render();\n      });\n\n      context.memo('button.underline', function () {\n        return ui.button({\n          className: 'note-btn-underline',\n          contents: ui.icon(options.icons.underline),\n          tooltip: lang.font.underline + representShortcut('underline'),\n          click: context.createInvokeHandler('editor.underline')\n        }).render();\n      });\n\n      context.memo('button.clear', function () {\n        return ui.button({\n          contents: ui.icon(options.icons.eraser),\n          tooltip: lang.font.clear + representShortcut('removeFormat'),\n          click: context.createInvokeHandler('editor.removeFormat')\n        }).render();\n      });\n\n      context.memo('button.strikethrough', function () {\n        return ui.button({\n          className: 'note-btn-strikethrough',\n          contents: ui.icon(options.icons.strikethrough),\n          tooltip: lang.font.strikethrough + representShortcut('strikethrough'),\n          click: context.createInvokeHandler('editor.strikethrough')\n        }).render();\n      });\n\n      context.memo('button.superscript', function () {\n        return ui.button({\n          className: 'note-btn-superscript',\n          contents: ui.icon(options.icons.superscript),\n          tooltip: lang.font.superscript,\n          click: context.createInvokeHandler('editor.superscript')\n        }).render();\n      });\n\n      context.memo('button.subscript', function () {\n        return ui.button({\n          className: 'note-btn-subscript',\n          contents: ui.icon(options.icons.subscript),\n          tooltip: lang.font.subscript,\n          click: context.createInvokeHandler('editor.subscript')\n        }).render();\n      });\n\n      context.memo('button.fontname', function () {\n        return ui.buttonGroup([\n          ui.button({\n            className: 'dropdown-toggle',\n            contents: '<span class=\"note-current-fontname\"/> ' + ui.icon(options.icons.caret, 'span'),\n            tooltip: lang.font.name,\n            data: {\n              toggle: 'dropdown'\n            }\n          }),\n          ui.dropdownCheck({\n            className: 'dropdown-fontname',\n            checkClassName: options.icons.menuCheck,\n            items: options.fontNames.filter(self.isFontInstalled),\n            template: function (item) {\n              return '<span style=\"font-family:' + item + '\">' + item + '</span>';\n            },\n            click: context.createInvokeHandler('editor.fontName')\n          })\n        ]).render();\n      });\n\n      context.memo('button.fontsize', function () {\n        return ui.buttonGroup([\n          ui.button({\n            className: 'dropdown-toggle',\n            contents: '<span class=\"note-current-fontsize\"/>' + ui.icon(options.icons.caret, 'span'),\n            tooltip: lang.font.size,\n            data: {\n              toggle: 'dropdown'\n            }\n          }),\n          ui.dropdownCheck({\n            className: 'dropdown-fontsize',\n            checkClassName: options.icons.menuCheck,\n            items: options.fontSizes,\n            click: context.createInvokeHandler('editor.fontSize')\n          })\n        ]).render();\n      });\n\n      context.memo('button.color', function () {\n        return ui.buttonGroup({\n          className: 'note-color',\n          children: [\n            ui.button({\n              className: 'note-current-color-button',\n              contents: ui.icon(options.icons.font + ' note-recent-color'),\n              tooltip: lang.color.recent,\n              click: function (e) {\n                var $button = $(e.currentTarget);\n                context.invoke('editor.color', {\n                  backColor: $button.attr('data-backColor'),\n                  foreColor: $button.attr('data-foreColor')\n                });\n              },\n              callback: function ($button) {\n                var $recentColor = $button.find('.note-recent-color');\n                $recentColor.css('background-color', '#FFFF00');\n                $button.attr('data-backColor', '#FFFF00');\n              }\n            }),\n            ui.button({\n              className: 'dropdown-toggle',\n              contents: ui.icon(options.icons.caret, 'span'),\n              tooltip: lang.color.more,\n              data: {\n                toggle: 'dropdown'\n              }\n            }),\n            ui.dropdown({\n              items: [\n                '<li>',\n                '<div class=\"btn-group\">',\n                '  <div class=\"note-palette-title\">' + lang.color.background + '</div>',\n                '  <div>',\n                '    <button type=\"button\" class=\"note-color-reset btn btn-default\" data-event=\"backColor\" data-value=\"inherit\">',\n                lang.color.transparent,\n                '    </button>',\n                '  </div>',\n                '  <div class=\"note-holder\" data-event=\"backColor\"/>',\n                '</div>',\n                '<div class=\"btn-group\">',\n                '  <div class=\"note-palette-title\">' + lang.color.foreground + '</div>',\n                '  <div>',\n                '    <button type=\"button\" class=\"note-color-reset btn btn-default\" data-event=\"removeFormat\" data-value=\"foreColor\">',\n                lang.color.resetToDefault,\n                '    </button>',\n                '  </div>',\n                '  <div class=\"note-holder\" data-event=\"foreColor\"/>',\n                '</div>',\n                '</li>'\n              ].join(''),\n              callback: function ($dropdown) {\n                $dropdown.find('.note-holder').each(function () {\n                  var $holder = $(this);\n                  $holder.append(ui.palette({\n                    colors: options.colors,\n                    eventName: $holder.data('event')\n                  }).render());\n                });\n              },\n              click: function (event) {\n                var $button = $(event.target);\n                var eventName = $button.data('event');\n                var value = $button.data('value');\n\n                if (eventName && value) {\n                  var key = eventName === 'backColor' ? 'background-color' : 'color';\n                  var $color = $button.closest('.note-color').find('.note-recent-color');\n                  var $currentButton = $button.closest('.note-color').find('.note-current-color-button');\n\n                  $color.css(key, value);\n                  $currentButton.attr('data-' + eventName, value);\n                  context.invoke('editor.' + eventName, value);\n                }\n              }\n            })\n          ]\n        }).render();\n      });\n\n      context.memo('button.ul',  function () {\n        return ui.button({\n          contents: ui.icon(options.icons.unorderedlist),\n          tooltip: lang.lists.unordered + representShortcut('insertUnorderedList'),\n          click: context.createInvokeHandler('editor.insertUnorderedList')\n        }).render();\n      });\n\n      context.memo('button.ol', function () {\n        return ui.button({\n          contents: ui.icon(options.icons.orderedlist),\n          tooltip: lang.lists.ordered + representShortcut('insertOrderedList'),\n          click:  context.createInvokeHandler('editor.insertOrderedList')\n        }).render();\n      });\n\n      var justifyLeft = ui.button({\n        contents: ui.icon(options.icons.alignLeft),\n        tooltip: lang.paragraph.left + representShortcut('justifyLeft'),\n        click: context.createInvokeHandler('editor.justifyLeft')\n      });\n\n      var justifyCenter = ui.button({\n        contents: ui.icon(options.icons.alignCenter),\n        tooltip: lang.paragraph.center + representShortcut('justifyCenter'),\n        click: context.createInvokeHandler('editor.justifyCenter')\n      });\n\n      var justifyRight = ui.button({\n        contents: ui.icon(options.icons.alignRight),\n        tooltip: lang.paragraph.right + representShortcut('justifyRight'),\n        click: context.createInvokeHandler('editor.justifyRight')\n      });\n\n      var justifyFull = ui.button({\n        contents: ui.icon(options.icons.alignJustify),\n        tooltip: lang.paragraph.justify + representShortcut('justifyFull'),\n        click: context.createInvokeHandler('editor.justifyFull')\n      });\n\n      var outdent = ui.button({\n        contents: ui.icon(options.icons.outdent),\n        tooltip: lang.paragraph.outdent + representShortcut('outdent'),\n        click: context.createInvokeHandler('editor.outdent')\n      });\n\n      var indent = ui.button({\n        contents: ui.icon(options.icons.indent),\n        tooltip: lang.paragraph.indent + representShortcut('indent'),\n        click: context.createInvokeHandler('editor.indent')\n      });\n\n      context.memo('button.justifyLeft', func.invoke(justifyLeft, 'render'));\n      context.memo('button.justifyCenter', func.invoke(justifyCenter, 'render'));\n      context.memo('button.justifyRight', func.invoke(justifyRight, 'render'));\n      context.memo('button.justifyFull', func.invoke(justifyFull, 'render'));\n      context.memo('button.outdent', func.invoke(outdent, 'render'));\n      context.memo('button.indent', func.invoke(indent, 'render'));\n\n      context.memo('button.paragraph', function () {\n        return ui.buttonGroup([\n          ui.button({\n            className: 'dropdown-toggle',\n            contents: ui.icon(options.icons.alignLeft) + ' ' + ui.icon(options.icons.caret, 'span'),\n            tooltip: lang.paragraph.paragraph,\n            data: {\n              toggle: 'dropdown'\n            }\n          }),\n          ui.dropdown([\n            ui.buttonGroup({\n              className: 'note-align',\n              children: [justifyLeft, justifyCenter, justifyRight, justifyFull]\n            }),\n            ui.buttonGroup({\n              className: 'note-list',\n              children: [outdent, indent]\n            })\n          ])\n        ]).render();\n      });\n\n      context.memo('button.height', function () {\n        return ui.buttonGroup([\n          ui.button({\n            className: 'dropdown-toggle',\n            contents: ui.icon(options.icons.textHeight) + ' ' + ui.icon(options.icons.caret, 'span'),\n            tooltip: lang.font.height,\n            data: {\n              toggle: 'dropdown'\n            }\n          }),\n          ui.dropdownCheck({\n            items: options.lineHeights,\n            checkClassName: options.icons.menuCheck,\n            className: 'dropdown-line-height',\n            click: context.createInvokeHandler('editor.lineHeight')\n          })\n        ]).render();\n      });\n\n      context.memo('button.table', function () {\n        return ui.buttonGroup([\n          ui.button({\n            className: 'dropdown-toggle',\n            contents: ui.icon(options.icons.table) + ' ' + ui.icon(options.icons.caret, 'span'),\n            tooltip: lang.table.table,\n            data: {\n              toggle: 'dropdown'\n            }\n          }),\n          ui.dropdown({\n            className: 'note-table',\n            items: [\n              '<div class=\"note-dimension-picker\">',\n              '  <div class=\"note-dimension-picker-mousecatcher\" data-event=\"insertTable\" data-value=\"1x1\"/>',\n              '  <div class=\"note-dimension-picker-highlighted\"/>',\n              '  <div class=\"note-dimension-picker-unhighlighted\"/>',\n              '</div>',\n              '<div class=\"note-dimension-display\">1 x 1</div>'\n            ].join('')\n          })\n        ], {\n          callback: function ($node) {\n            var $catcher = $node.find('.note-dimension-picker-mousecatcher');\n            $catcher.css({\n              width: options.insertTableMaxSize.col + 'em',\n              height: options.insertTableMaxSize.row + 'em'\n            }).mousedown(context.createInvokeHandler('editor.insertTable'))\n              .on('mousemove', self.tableMoveHandler);\n          }\n        }).render();\n      });\n\n      context.memo('button.link', function () {\n        return ui.button({\n          contents: ui.icon(options.icons.link),\n          tooltip: lang.link.link + representShortcut('linkDialog.show'),\n          click: context.createInvokeHandler('linkDialog.show')\n        }).render();\n      });\n\n      context.memo('button.picture', function () {\n        return ui.button({\n          contents: ui.icon(options.icons.picture),\n          tooltip: lang.image.image,\n          click: context.createInvokeHandler('imageDialog.show')\n        }).render();\n      });\n\n      context.memo('button.video', function () {\n        return ui.button({\n          contents: ui.icon(options.icons.video),\n          tooltip: lang.video.video,\n          click: context.createInvokeHandler('videoDialog.show')\n        }).render();\n      });\n\n      context.memo('button.hr', function () {\n        return ui.button({\n          contents: ui.icon(options.icons.minus),\n          tooltip: lang.hr.insert + representShortcut('insertHorizontalRule'),\n          click: context.createInvokeHandler('editor.insertHorizontalRule')\n        }).render();\n      });\n\n      context.memo('button.fullscreen', function () {\n        return ui.button({\n          className: 'btn-fullscreen',\n          contents: ui.icon(options.icons.arrowsAlt),\n          tooltip: lang.options.fullscreen,\n          click: context.createInvokeHandler('fullscreen.toggle')\n        }).render();\n      });\n\n      context.memo('button.codeview', function () {\n        return ui.button({\n          className: 'btn-codeview',\n          contents: ui.icon(options.icons.code),\n          tooltip: lang.options.codeview,\n          click: context.createInvokeHandler('codeview.toggle')\n        }).render();\n      });\n\n      context.memo('button.redo', function () {\n        return ui.button({\n          contents: ui.icon(options.icons.redo),\n          tooltip: lang.history.redo + representShortcut('redo'),\n          click: context.createInvokeHandler('editor.redo')\n        }).render();\n      });\n\n      context.memo('button.undo', function () {\n        return ui.button({\n          contents: ui.icon(options.icons.undo),\n          tooltip: lang.history.undo + representShortcut('undo'),\n          click: context.createInvokeHandler('editor.undo')\n        }).render();\n      });\n\n      context.memo('button.help', function () {\n        return ui.button({\n          contents: ui.icon(options.icons.question),\n          tooltip: lang.options.help,\n          click: context.createInvokeHandler('helpDialog.show')\n        }).render();\n      });\n    };\n\n    /**\n     * image : [\n     *   ['imagesize', ['imageSize100', 'imageSize50', 'imageSize25']],\n     *   ['float', ['floatLeft', 'floatRight', 'floatNone' ]],\n     *   ['remove', ['removeMedia']]\n     * ],\n     */\n    this.addImagePopoverButtons = function () {\n      // Image Size Buttons\n      context.memo('button.imageSize100', function () {\n        return ui.button({\n          contents: '<span class=\"note-fontsize-10\">100%</span>',\n          tooltip: lang.image.resizeFull,\n          click: context.createInvokeHandler('editor.resize', '1')\n        }).render();\n      });\n      context.memo('button.imageSize50', function () {\n        return  ui.button({\n          contents: '<span class=\"note-fontsize-10\">50%</span>',\n          tooltip: lang.image.resizeHalf,\n          click: context.createInvokeHandler('editor.resize', '0.5')\n        }).render();\n      });\n      context.memo('button.imageSize25', function () {\n        return ui.button({\n          contents: '<span class=\"note-fontsize-10\">25%</span>',\n          tooltip: lang.image.resizeQuarter,\n          click: context.createInvokeHandler('editor.resize', '0.25')\n        }).render();\n      });\n\n      // Float Buttons\n      context.memo('button.floatLeft', function () {\n        return ui.button({\n          contents: ui.icon(options.icons.alignLeft),\n          tooltip: lang.image.floatLeft,\n          click: context.createInvokeHandler('editor.floatMe', 'left')\n        }).render();\n      });\n\n      context.memo('button.floatRight', function () {\n        return ui.button({\n          contents: ui.icon(options.icons.alignRight),\n          tooltip: lang.image.floatRight,\n          click: context.createInvokeHandler('editor.floatMe', 'right')\n        }).render();\n      });\n\n      context.memo('button.floatNone', function () {\n        return ui.button({\n          contents: ui.icon(options.icons.alignJustify),\n          tooltip: lang.image.floatNone,\n          click: context.createInvokeHandler('editor.floatMe', 'none')\n        }).render();\n      });\n\n      // Remove Buttons\n      context.memo('button.removeMedia', function () {\n        return ui.button({\n          contents: ui.icon(options.icons.trash),\n          tooltip: lang.image.remove,\n          click: context.createInvokeHandler('editor.removeMedia')\n        }).render();\n      });\n    };\n\n    this.addLinkPopoverButtons = function () {\n      context.memo('button.linkDialogShow', function () {\n        return ui.button({\n          contents: ui.icon(options.icons.link),\n          tooltip: lang.link.edit,\n          click: context.createInvokeHandler('linkDialog.show')\n        }).render();\n      });\n\n      context.memo('button.unlink', function () {\n        return ui.button({\n          contents: ui.icon(options.icons.unlink),\n          tooltip: lang.link.unlink,\n          click: context.createInvokeHandler('editor.unlink')\n        }).render();\n      });\n    };\n\n    this.build = function ($container, groups) {\n      for (var groupIdx = 0, groupLen = groups.length; groupIdx < groupLen; groupIdx++) {\n        var group = groups[groupIdx];\n        var groupName = group[0];\n        var buttons = group[1];\n\n        var $group = ui.buttonGroup({\n          className: 'note-' + groupName\n        }).render();\n\n        for (var idx = 0, len = buttons.length; idx < len; idx++) {\n          var button = context.memo('button.' + buttons[idx]);\n          if (button) {\n            $group.append(typeof button === 'function' ? button(context) : button);\n          }\n        }\n        $group.appendTo($container);\n      }\n    };\n\n    this.updateCurrentStyle = function () {\n      var styleInfo = context.invoke('editor.currentStyle');\n      this.updateBtnStates({\n        '.note-btn-bold': function () {\n          return styleInfo['font-bold'] === 'bold';\n        },\n        '.note-btn-italic': function () {\n          return styleInfo['font-italic'] === 'italic';\n        },\n        '.note-btn-underline': function () {\n          return styleInfo['font-underline'] === 'underline';\n        },\n        '.note-btn-subscript': function () {\n          return styleInfo['font-subscript'] === 'subscript';\n        },\n        '.note-btn-superscript': function () {\n          return styleInfo['font-superscript'] === 'superscript';\n        },\n        '.note-btn-strikethrough': function () {\n          return styleInfo['font-strikethrough'] === 'strikethrough';\n        }\n      });\n\n      if (styleInfo['font-family']) {\n        var fontNames = styleInfo['font-family'].split(',').map(function (name) {\n          return name.replace(/[\\'\\\"]/g, '')\n            .replace(/\\s+$/, '')\n            .replace(/^\\s+/, '');\n        });\n        var fontName = list.find(fontNames, self.isFontInstalled);\n\n        $toolbar.find('.dropdown-fontname li a').each(function () {\n          // always compare string to avoid creating another func.\n          var isChecked = ($(this).data('value') + '') === (fontName + '');\n          this.className = isChecked ? 'checked' : '';\n        });\n        $toolbar.find('.note-current-fontname').text(fontName);\n      }\n\n      if (styleInfo['font-size']) {\n        var fontSize = styleInfo['font-size'];\n        $toolbar.find('.dropdown-fontsize li a').each(function () {\n          // always compare with string to avoid creating another func.\n          var isChecked = ($(this).data('value') + '') === (fontSize + '');\n          this.className = isChecked ? 'checked' : '';\n        });\n        $toolbar.find('.note-current-fontsize').text(fontSize);\n      }\n\n      if (styleInfo['line-height']) {\n        var lineHeight = styleInfo['line-height'];\n        $toolbar.find('.dropdown-line-height li a').each(function () {\n          // always compare with string to avoid creating another func.\n          var isChecked = ($(this).data('value') + '') === (lineHeight + '');\n          this.className = isChecked ? 'checked' : '';\n        });\n      }\n    };\n\n    this.updateBtnStates = function (infos) {\n      $.each(infos, function (selector, pred) {\n        ui.toggleBtnActive($toolbar.find(selector), pred());\n      });\n    };\n\n    this.tableMoveHandler = function (event) {\n      var PX_PER_EM = 18;\n      var $picker = $(event.target.parentNode); // target is mousecatcher\n      var $dimensionDisplay = $picker.next();\n      var $catcher = $picker.find('.note-dimension-picker-mousecatcher');\n      var $highlighted = $picker.find('.note-dimension-picker-highlighted');\n      var $unhighlighted = $picker.find('.note-dimension-picker-unhighlighted');\n\n      var posOffset;\n      // HTML5 with jQuery - e.offsetX is undefined in Firefox\n      if (event.offsetX === undefined) {\n        var posCatcher = $(event.target).offset();\n        posOffset = {\n          x: event.pageX - posCatcher.left,\n          y: event.pageY - posCatcher.top\n        };\n      } else {\n        posOffset = {\n          x: event.offsetX,\n          y: event.offsetY\n        };\n      }\n\n      var dim = {\n        c: Math.ceil(posOffset.x / PX_PER_EM) || 1,\n        r: Math.ceil(posOffset.y / PX_PER_EM) || 1\n      };\n\n      $highlighted.css({ width: dim.c + 'em', height: dim.r + 'em' });\n      $catcher.data('value', dim.c + 'x' + dim.r);\n\n      if (3 < dim.c && dim.c < options.insertTableMaxSize.col) {\n        $unhighlighted.css({ width: dim.c + 1 + 'em'});\n      }\n\n      if (3 < dim.r && dim.r < options.insertTableMaxSize.row) {\n        $unhighlighted.css({ height: dim.r + 1 + 'em'});\n      }\n\n      $dimensionDisplay.html(dim.c + ' x ' + dim.r);\n    };\n  };\n\n  var Toolbar = function (context) {\n    var ui = $.summernote.ui;\n\n    var $note = context.layoutInfo.note;\n    var $toolbar = context.layoutInfo.toolbar;\n    var options = context.options;\n\n    this.shouldInitialize = function () {\n      return !options.airMode;\n    };\n\n    this.initialize = function () {\n      options.toolbar = options.toolbar || [];\n\n      if (!options.toolbar.length) {\n        $toolbar.hide();\n      } else {\n        context.invoke('buttons.build', $toolbar, options.toolbar);\n      }\n\n      if (options.toolbarContainer) {\n        $toolbar.appendTo(options.toolbarContainer);\n      }\n\n      $note.on('summernote.keyup summernote.mouseup summernote.change', function () {\n        context.invoke('buttons.updateCurrentStyle');\n      });\n\n      context.invoke('buttons.updateCurrentStyle');\n    };\n\n    this.destroy = function () {\n      $toolbar.children().remove();\n    };\n\n    this.updateFullscreen = function (isFullscreen) {\n      ui.toggleBtnActive($toolbar.find('.btn-fullscreen'), isFullscreen);\n    };\n\n    this.updateCodeview = function (isCodeview) {\n      ui.toggleBtnActive($toolbar.find('.btn-codeview'), isCodeview);\n      if (isCodeview) {\n        this.deactivate();\n      } else {\n        this.activate();\n      }\n    };\n\n    this.activate = function (isIncludeCodeview) {\n      var $btn = $toolbar.find('button');\n      if (!isIncludeCodeview) {\n        $btn = $btn.not('.btn-codeview');\n      }\n      ui.toggleBtn($btn, true);\n    };\n\n    this.deactivate = function (isIncludeCodeview) {\n      var $btn = $toolbar.find('button');\n      if (!isIncludeCodeview) {\n        $btn = $btn.not('.btn-codeview');\n      }\n      ui.toggleBtn($btn, false);\n    };\n  };\n\n  var LinkDialog = function (context) {\n    var self = this;\n    var ui = $.summernote.ui;\n\n    var $editor = context.layoutInfo.editor;\n    var options = context.options;\n    var lang = options.langInfo;\n\n    this.initialize = function () {\n      var $container = options.dialogsInBody ? $(document.body) : $editor;\n\n      var body = '<div class=\"form-group\">' +\n                   '<label>' + lang.link.textToDisplay + '</label>' +\n                   '<input class=\"note-link-text form-control\" type=\"text\" />' +\n                 '</div>' +\n                 '<div class=\"form-group\">' +\n                   '<label>' + lang.link.url + '</label>' +\n                   '<input class=\"note-link-url form-control\" type=\"text\" value=\"http://\" />' +\n                 '</div>' +\n                 (!options.disableLinkTarget ?\n                   '<div class=\"checkbox\">' +\n                     '<label>' + '<input type=\"checkbox\" checked> ' + lang.link.openInNewWindow + '</label>' +\n                   '</div>' : ''\n                 );\n      var footer = '<button href=\"#\" class=\"btn btn-primary note-link-btn disabled\" disabled>' + lang.link.insert + '</button>';\n\n      this.$dialog = ui.dialog({\n        className: 'link-dialog',\n        title: lang.link.insert,\n        fade: options.dialogsFade,\n        body: body,\n        footer: footer\n      }).render().appendTo($container);\n    };\n\n    this.destroy = function () {\n      ui.hideDialog(this.$dialog);\n      this.$dialog.remove();\n    };\n\n    this.bindEnterKey = function ($input, $btn) {\n      $input.on('keypress', function (event) {\n        if (event.keyCode === key.code.ENTER) {\n          $btn.trigger('click');\n        }\n      });\n    };\n\n    /**\n     * toggle update button\n     */\n    this.toggleLinkBtn = function ($linkBtn, $linkText, $linkUrl) {\n      ui.toggleBtn($linkBtn, $linkText.val() && $linkUrl.val());\n    };\n\n    /**\n     * Show link dialog and set event handlers on dialog controls.\n     *\n     * @param {Object} linkInfo\n     * @return {Promise}\n     */\n    this.showLinkDialog = function (linkInfo) {\n      return $.Deferred(function (deferred) {\n        var $linkText = self.$dialog.find('.note-link-text'),\n        $linkUrl = self.$dialog.find('.note-link-url'),\n        $linkBtn = self.$dialog.find('.note-link-btn'),\n        $openInNewWindow = self.$dialog.find('input[type=checkbox]');\n\n        ui.onDialogShown(self.$dialog, function () {\n          context.triggerEvent('dialog.shown');\n\n          // if no url was given, copy text to url\n          if (!linkInfo.url) {\n            linkInfo.url = linkInfo.text;\n          }\n\n          $linkText.val(linkInfo.text);\n\n          var handleLinkTextUpdate = function () {\n            self.toggleLinkBtn($linkBtn, $linkText, $linkUrl);\n            // if linktext was modified by keyup,\n            // stop cloning text from linkUrl\n            linkInfo.text = $linkText.val();\n          };\n\n          $linkText.on('input', handleLinkTextUpdate).on('paste', function () {\n            setTimeout(handleLinkTextUpdate, 0);\n          });\n\n          var handleLinkUrlUpdate = function () {\n            self.toggleLinkBtn($linkBtn, $linkText, $linkUrl);\n            // display same link on `Text to display` input\n            // when create a new link\n            if (!linkInfo.text) {\n              $linkText.val($linkUrl.val());\n            }\n          };\n\n          $linkUrl.on('input', handleLinkUrlUpdate).on('paste', function () {\n            setTimeout(handleLinkUrlUpdate, 0);\n          }).val(linkInfo.url).trigger('focus');\n\n          self.toggleLinkBtn($linkBtn, $linkText, $linkUrl);\n          self.bindEnterKey($linkUrl, $linkBtn);\n          self.bindEnterKey($linkText, $linkBtn);\n\n          $openInNewWindow.prop('checked', linkInfo.isNewWindow);\n\n          $linkBtn.one('click', function (event) {\n            event.preventDefault();\n\n            deferred.resolve({\n              range: linkInfo.range,\n              url: $linkUrl.val(),\n              text: $linkText.val(),\n              isNewWindow: $openInNewWindow.is(':checked')\n            });\n            self.$dialog.modal('hide');\n          });\n        });\n\n        ui.onDialogHidden(self.$dialog, function () {\n          // detach events\n          $linkText.off('input paste keypress');\n          $linkUrl.off('input paste keypress');\n          $linkBtn.off('click');\n\n          if (deferred.state() === 'pending') {\n            deferred.reject();\n          }\n        });\n\n        ui.showDialog(self.$dialog);\n      }).promise();\n    };\n\n    /**\n     * @param {Object} layoutInfo\n     */\n    this.show = function () {\n      var linkInfo = context.invoke('editor.getLinkInfo');\n\n      context.invoke('editor.saveRange');\n      this.showLinkDialog(linkInfo).then(function (linkInfo) {\n        context.invoke('editor.restoreRange');\n        context.invoke('editor.createLink', linkInfo);\n      }).fail(function () {\n        context.invoke('editor.restoreRange');\n      });\n    };\n    context.memo('help.linkDialog.show', options.langInfo.help['linkDialog.show']);\n  };\n\n  var LinkPopover = function (context) {\n    var self = this;\n    var ui = $.summernote.ui;\n\n    var options = context.options;\n\n    this.events = {\n      'summernote.keyup summernote.mouseup summernote.change summernote.scroll': function () {\n        self.update();\n      },\n      'summernote.dialog.shown': function () {\n        self.hide();\n      }\n    };\n\n    this.shouldInitialize = function () {\n      return !list.isEmpty(options.popover.link);\n    };\n\n    this.initialize = function () {\n      this.$popover = ui.popover({\n        className: 'note-link-popover',\n        callback: function ($node) {\n          var $content = $node.find('.popover-content');\n          $content.prepend('<span><a target=\"_blank\"></a>&nbsp;</span>');\n        }\n      }).render().appendTo('body');\n      var $content = this.$popover.find('.popover-content');\n\n      context.invoke('buttons.build', $content, options.popover.link);\n    };\n\n    this.destroy = function () {\n      this.$popover.remove();\n    };\n\n    this.update = function () {\n      // Prevent focusing on editable when invoke('code') is executed\n      if (!context.invoke('editor.hasFocus')) {\n        this.hide();\n        return;\n      }\n\n      var rng = context.invoke('editor.createRange');\n      if (rng.isCollapsed() && rng.isOnAnchor()) {\n        var anchor = dom.ancestor(rng.sc, dom.isAnchor);\n        var href = $(anchor).attr('href');\n        this.$popover.find('a').attr('href', href).html(href);\n\n        var pos = dom.posFromPlaceholder(anchor);\n        this.$popover.css({\n          display: 'block',\n          left: pos.left,\n          top: pos.top\n        });\n      } else {\n        this.hide();\n      }\n    };\n\n    this.hide = function () {\n      this.$popover.hide();\n    };\n  };\n\n  var ImageDialog = function (context) {\n    var self = this;\n    var ui = $.summernote.ui;\n\n    var $editor = context.layoutInfo.editor;\n    var options = context.options;\n    var lang = options.langInfo;\n\n    this.initialize = function () {\n      var $container = options.dialogsInBody ? $(document.body) : $editor;\n\n      var imageLimitation = '';\n      if (options.maximumImageFileSize) {\n        var unit = Math.floor(Math.log(options.maximumImageFileSize) / Math.log(1024));\n        var readableSize = (options.maximumImageFileSize / Math.pow(1024, unit)).toFixed(2) * 1 +\n                           ' ' + ' KMGTP'[unit] + 'B';\n        imageLimitation = '<small>' + lang.image.maximumFileSize + ' : ' + readableSize + '</small>';\n      }\n\n      var body = '<div class=\"form-group note-group-select-from-files\">' +\n                   '<label>' + lang.image.selectFromFiles + '</label>' +\n                   '<input class=\"note-image-input form-control\" type=\"file\" name=\"files\" accept=\"image/*\" multiple=\"multiple\" />' +\n                   imageLimitation +\n                 '</div>' +\n                 '<div class=\"form-group note-group-image-url\" style=\"overflow:auto;\">' +\n                   '<label>' + lang.image.url + '</label>' +\n                   '<input class=\"note-image-url form-control col-md-12\" type=\"text\" />' +\n                 '</div>';\n      var footer = '<button href=\"#\" class=\"btn btn-primary note-image-btn disabled\" disabled>' + lang.image.insert + '</button>';\n\n      this.$dialog = ui.dialog({\n        title: lang.image.insert,\n        fade: options.dialogsFade,\n        body: body,\n        footer: footer\n      }).render().appendTo($container);\n    };\n\n    this.destroy = function () {\n      ui.hideDialog(this.$dialog);\n      this.$dialog.remove();\n    };\n\n    this.bindEnterKey = function ($input, $btn) {\n      $input.on('keypress', function (event) {\n        if (event.keyCode === key.code.ENTER) {\n          $btn.trigger('click');\n        }\n      });\n    };\n\n    this.show = function () {\n      context.invoke('editor.saveRange');\n      this.showImageDialog().then(function (data) {\n        // [workaround] hide dialog before restore range for IE range focus\n        ui.hideDialog(self.$dialog);\n        context.invoke('editor.restoreRange');\n\n        if (typeof data === 'string') { // image url\n          context.invoke('editor.insertImage', data);\n        } else { // array of files\n          context.invoke('editor.insertImagesOrCallback', data);\n        }\n      }).fail(function () {\n        context.invoke('editor.restoreRange');\n      });\n    };\n\n    /**\n     * show image dialog\n     *\n     * @param {jQuery} $dialog\n     * @return {Promise}\n     */\n    this.showImageDialog = function () {\n      return $.Deferred(function (deferred) {\n        var $imageInput = self.$dialog.find('.note-image-input'),\n            $imageUrl = self.$dialog.find('.note-image-url'),\n            $imageBtn = self.$dialog.find('.note-image-btn');\n\n        ui.onDialogShown(self.$dialog, function () {\n          context.triggerEvent('dialog.shown');\n\n          // Cloning imageInput to clear element.\n          $imageInput.replaceWith($imageInput.clone()\n            .on('change', function () {\n              deferred.resolve(this.files || this.value);\n            })\n            .val('')\n          );\n\n          $imageBtn.click(function (event) {\n            event.preventDefault();\n\n            deferred.resolve($imageUrl.val());\n          });\n\n          $imageUrl.on('keyup paste', function () {\n            var url = $imageUrl.val();\n            ui.toggleBtn($imageBtn, url);\n          }).val('').trigger('focus');\n          self.bindEnterKey($imageUrl, $imageBtn);\n        });\n\n        ui.onDialogHidden(self.$dialog, function () {\n          $imageInput.off('change');\n          $imageUrl.off('keyup paste keypress');\n          $imageBtn.off('click');\n\n          if (deferred.state() === 'pending') {\n            deferred.reject();\n          }\n        });\n\n        ui.showDialog(self.$dialog);\n      });\n    };\n  };\n\n  var ImagePopover = function (context) {\n    var ui = $.summernote.ui;\n\n    var options = context.options;\n\n    this.shouldInitialize = function () {\n      return !list.isEmpty(options.popover.image);\n    };\n\n    this.initialize = function () {\n      this.$popover = ui.popover({\n        className: 'note-image-popover'\n      }).render().appendTo('body');\n      var $content = this.$popover.find('.popover-content');\n\n      context.invoke('buttons.build', $content, options.popover.image);\n    };\n\n    this.destroy = function () {\n      this.$popover.remove();\n    };\n\n    this.update = function (target) {\n      if (dom.isImg(target)) {\n        var pos = dom.posFromPlaceholder(target);\n        this.$popover.css({\n          display: 'block',\n          left: pos.left,\n          top: pos.top\n        });\n      } else {\n        this.hide();\n      }\n    };\n\n    this.hide = function () {\n      this.$popover.hide();\n    };\n  };\n\n  var VideoDialog = function (context) {\n    var self = this;\n    var ui = $.summernote.ui;\n\n    var $editor = context.layoutInfo.editor;\n    var options = context.options;\n    var lang = options.langInfo;\n\n    this.initialize = function () {\n      var $container = options.dialogsInBody ? $(document.body) : $editor;\n\n      var body = '<div class=\"form-group row-fluid\">' +\n          '<label>' + lang.video.url + ' <small class=\"text-muted\">' + lang.video.providers + '</small></label>' +\n          '<input class=\"note-video-url form-control span12\" type=\"text\" />' +\n          '</div>';\n      var footer = '<button href=\"#\" class=\"btn btn-primary note-video-btn disabled\" disabled>' + lang.video.insert + '</button>';\n\n      this.$dialog = ui.dialog({\n        title: lang.video.insert,\n        fade: options.dialogsFade,\n        body: body,\n        footer: footer\n      }).render().appendTo($container);\n    };\n\n    this.destroy = function () {\n      ui.hideDialog(this.$dialog);\n      this.$dialog.remove();\n    };\n\n    this.bindEnterKey = function ($input, $btn) {\n      $input.on('keypress', function (event) {\n        if (event.keyCode === key.code.ENTER) {\n          $btn.trigger('click');\n        }\n      });\n    };\n\n    this.createVideoNode = function (url) {\n      // video url patterns(youtube, instagram, vimeo, dailymotion, youku, mp4, ogg, webm)\n      var ytRegExp = /^(?:https?:\\/\\/)?(?:www\\.)?(?:youtu\\.be\\/|youtube\\.com\\/(?:embed\\/|v\\/|watch\\?v=|watch\\?.+&v=))((\\w|-){11})(?:\\S+)?$/;\n      var ytMatch = url.match(ytRegExp);\n\n      var igRegExp = /(?:www\\.|\\/\\/)instagram\\.com\\/p\\/(.[a-zA-Z0-9_-]*)/;\n      var igMatch = url.match(igRegExp);\n\n      var vRegExp = /\\/\\/vine\\.co\\/v\\/([a-zA-Z0-9]+)/;\n      var vMatch = url.match(vRegExp);\n\n      var vimRegExp = /\\/\\/(player\\.)?vimeo\\.com\\/([a-z]*\\/)*([0-9]{6,11})[?]?.*/;\n      var vimMatch = url.match(vimRegExp);\n\n      var dmRegExp = /.+dailymotion.com\\/(video|hub)\\/([^_]+)[^#]*(#video=([^_&]+))?/;\n      var dmMatch = url.match(dmRegExp);\n\n      var youkuRegExp = /\\/\\/v\\.youku\\.com\\/v_show\\/id_(\\w+)=*\\.html/;\n      var youkuMatch = url.match(youkuRegExp);\n\n      var mp4RegExp = /^.+.(mp4|m4v)$/;\n      var mp4Match = url.match(mp4RegExp);\n\n      var oggRegExp = /^.+.(ogg|ogv)$/;\n      var oggMatch = url.match(oggRegExp);\n\n      var webmRegExp = /^.+.(webm)$/;\n      var webmMatch = url.match(webmRegExp);\n\n      var $video;\n      if (ytMatch && ytMatch[1].length === 11) {\n        var youtubeId = ytMatch[1];\n        $video = $('<iframe>')\n            .attr('frameborder', 0)\n            .attr('src', '//www.youtube.com/embed/' + youtubeId)\n            .attr('width', '640').attr('height', '360');\n      } else if (igMatch && igMatch[0].length) {\n        $video = $('<iframe>')\n            .attr('frameborder', 0)\n            .attr('src', 'https://instagram.com/p/' + igMatch[1] + '/embed/')\n            .attr('width', '612').attr('height', '710')\n            .attr('scrolling', 'no')\n            .attr('allowtransparency', 'true');\n      } else if (vMatch && vMatch[0].length) {\n        $video = $('<iframe>')\n            .attr('frameborder', 0)\n            .attr('src', vMatch[0] + '/embed/simple')\n            .attr('width', '600').attr('height', '600')\n            .attr('class', 'vine-embed');\n      } else if (vimMatch && vimMatch[3].length) {\n        $video = $('<iframe webkitallowfullscreen mozallowfullscreen allowfullscreen>')\n            .attr('frameborder', 0)\n            .attr('src', '//player.vimeo.com/video/' + vimMatch[3])\n            .attr('width', '640').attr('height', '360');\n      } else if (dmMatch && dmMatch[2].length) {\n        $video = $('<iframe>')\n            .attr('frameborder', 0)\n            .attr('src', '//www.dailymotion.com/embed/video/' + dmMatch[2])\n            .attr('width', '640').attr('height', '360');\n      } else if (youkuMatch && youkuMatch[1].length) {\n        $video = $('<iframe webkitallowfullscreen mozallowfullscreen allowfullscreen>')\n            .attr('frameborder', 0)\n            .attr('height', '498')\n            .attr('width', '510')\n            .attr('src', '//player.youku.com/embed/' + youkuMatch[1]);\n      } else if (mp4Match || oggMatch || webmMatch) {\n        $video = $('<video controls>')\n            .attr('src', url)\n            .attr('width', '640').attr('height', '360');\n      } else {\n        // this is not a known video link. Now what, Cat? Now what?\n        return false;\n      }\n\n      $video.addClass('note-video-clip');\n\n      return $video[0];\n    };\n\n    this.show = function () {\n      var text = context.invoke('editor.getSelectedText');\n      context.invoke('editor.saveRange');\n      this.showVideoDialog(text).then(function (url) {\n        // [workaround] hide dialog before restore range for IE range focus\n        ui.hideDialog(self.$dialog);\n        context.invoke('editor.restoreRange');\n\n        // build node\n        var $node = self.createVideoNode(url);\n\n        if ($node) {\n          // insert video node\n          context.invoke('editor.insertNode', $node);\n        }\n      }).fail(function () {\n        context.invoke('editor.restoreRange');\n      });\n    };\n\n    /**\n     * show image dialog\n     *\n     * @param {jQuery} $dialog\n     * @return {Promise}\n     */\n    this.showVideoDialog = function (text) {\n      return $.Deferred(function (deferred) {\n        var $videoUrl = self.$dialog.find('.note-video-url'),\n            $videoBtn = self.$dialog.find('.note-video-btn');\n\n        ui.onDialogShown(self.$dialog, function () {\n          context.triggerEvent('dialog.shown');\n\n          $videoUrl.val(text).on('input', function () {\n            ui.toggleBtn($videoBtn, $videoUrl.val());\n          }).trigger('focus');\n\n          $videoBtn.click(function (event) {\n            event.preventDefault();\n\n            deferred.resolve($videoUrl.val());\n          });\n\n          self.bindEnterKey($videoUrl, $videoBtn);\n        });\n\n        ui.onDialogHidden(self.$dialog, function () {\n          $videoUrl.off('input');\n          $videoBtn.off('click');\n\n          if (deferred.state() === 'pending') {\n            deferred.reject();\n          }\n        });\n\n        ui.showDialog(self.$dialog);\n      });\n    };\n  };\n\n  var HelpDialog = function (context) {\n    var self = this;\n    var ui = $.summernote.ui;\n\n    var $editor = context.layoutInfo.editor;\n    var options = context.options;\n    var lang = options.langInfo;\n\n    this.createShortCutList = function () {\n      var keyMap = options.keyMap[agent.isMac ? 'mac' : 'pc'];\n      return Object.keys(keyMap).map(function (key) {\n        var command = keyMap[key];\n        var $row = $('<div><div class=\"help-list-item\"/></div>');\n        $row.append($('<label><kbd>' + key + '</kdb></label>').css({\n          'width': 180,\n          'margin-right': 10\n        })).append($('<span/>').html(context.memo('help.' + command) || command));\n        return $row.html();\n      }).join('');\n    };\n\n    this.initialize = function () {\n      var $container = options.dialogsInBody ? $(document.body) : $editor;\n\n      var body = [\n        '<p class=\"text-center\">',\n        '<a href=\"http://summernote.org/\" target=\"_blank\">Summernote 0.8.2</a> · ',\n        '<a href=\"https://github.com/summernote/summernote\" target=\"_blank\">Project</a> · ',\n        '<a href=\"https://github.com/summernote/summernote/issues\" target=\"_blank\">Issues</a>',\n        '</p>'\n      ].join('');\n\n      this.$dialog = ui.dialog({\n        title: lang.options.help,\n        fade: options.dialogsFade,\n        body: this.createShortCutList(),\n        footer: body,\n        callback: function ($node) {\n          $node.find('.modal-body').css({\n            'max-height': 300,\n            'overflow': 'scroll'\n          });\n        }\n      }).render().appendTo($container);\n    };\n\n    this.destroy = function () {\n      ui.hideDialog(this.$dialog);\n      this.$dialog.remove();\n    };\n\n    /**\n     * show help dialog\n     *\n     * @return {Promise}\n     */\n    this.showHelpDialog = function () {\n      return $.Deferred(function (deferred) {\n        ui.onDialogShown(self.$dialog, function () {\n          context.triggerEvent('dialog.shown');\n          deferred.resolve();\n        });\n        ui.showDialog(self.$dialog);\n      }).promise();\n    };\n\n    this.show = function () {\n      context.invoke('editor.saveRange');\n      this.showHelpDialog().then(function () {\n        context.invoke('editor.restoreRange');\n      });\n    };\n  };\n\n  var AirPopover = function (context) {\n    var self = this;\n    var ui = $.summernote.ui;\n\n    var options = context.options;\n\n    var AIR_MODE_POPOVER_X_OFFSET = 20;\n\n    this.events = {\n      'summernote.keyup summernote.mouseup summernote.scroll': function () {\n        self.update();\n      },\n      'summernote.change summernote.dialog.shown': function () {\n        self.hide();\n      },\n      'summernote.focusout': function (we, e) {\n        // [workaround] Firefox doesn't support relatedTarget on focusout\n        //  - Ignore hide action on focus out in FF.\n        if (agent.isFF) {\n          return;\n        }\n\n        if (!e.relatedTarget || !dom.ancestor(e.relatedTarget, func.eq(self.$popover[0]))) {\n          self.hide();\n        }\n      }\n    };\n\n    this.shouldInitialize = function () {\n      return options.airMode && !list.isEmpty(options.popover.air);\n    };\n\n    this.initialize = function () {\n      this.$popover = ui.popover({\n        className: 'note-air-popover'\n      }).render().appendTo('body');\n      var $content = this.$popover.find('.popover-content');\n\n      context.invoke('buttons.build', $content, options.popover.air);\n    };\n\n    this.destroy = function () {\n      this.$popover.remove();\n    };\n\n    this.update = function () {\n      var styleInfo = context.invoke('editor.currentStyle');\n      if (styleInfo.range && !styleInfo.range.isCollapsed()) {\n        var rect = list.last(styleInfo.range.getClientRects());\n        if (rect) {\n          var bnd = func.rect2bnd(rect);\n          this.$popover.css({\n            display: 'block',\n            left: Math.max(bnd.left + bnd.width / 2, 0) - AIR_MODE_POPOVER_X_OFFSET,\n            top: bnd.top + bnd.height\n          });\n        }\n      } else {\n        this.hide();\n      }\n    };\n\n    this.hide = function () {\n      this.$popover.hide();\n    };\n  };\n\n  var HintPopover = function (context) {\n    var self = this;\n    var ui = $.summernote.ui;\n\n    var POPOVER_DIST = 5;\n    var hint = context.options.hint || [];\n    var direction = context.options.hintDirection || 'bottom';\n    var hints = $.isArray(hint) ? hint : [hint];\n\n    this.events = {\n      'summernote.keyup': function (we, e) {\n        if (!e.isDefaultPrevented()) {\n          self.handleKeyup(e);\n        }\n      },\n      'summernote.keydown': function (we, e) {\n        self.handleKeydown(e);\n      },\n      'summernote.dialog.shown': function () {\n        self.hide();\n      }\n    };\n\n    this.shouldInitialize = function () {\n      return hints.length > 0;\n    };\n\n    this.initialize = function () {\n      this.lastWordRange = null;\n      this.$popover = ui.popover({\n        className: 'note-hint-popover',\n        hideArrow: true,\n        direction: ''\n      }).render().appendTo('body');\n\n      this.$popover.hide();\n\n      this.$content = this.$popover.find('.popover-content');\n\n      this.$content.on('click', '.note-hint-item', function () {\n        self.$content.find('.active').removeClass('active');\n        $(this).addClass('active');\n        self.replace();\n      });\n    };\n\n    this.destroy = function () {\n      this.$popover.remove();\n    };\n\n    this.selectItem = function ($item) {\n      this.$content.find('.active').removeClass('active');\n      $item.addClass('active');\n\n      this.$content[0].scrollTop = $item[0].offsetTop - (this.$content.innerHeight() / 2);\n    };\n\n    this.moveDown = function () {\n      var $current = this.$content.find('.note-hint-item.active');\n      var $next = $current.next();\n\n      if ($next.length) {\n        this.selectItem($next);\n      } else {\n        var $nextGroup = $current.parent().next();\n\n        if (!$nextGroup.length) {\n          $nextGroup = this.$content.find('.note-hint-group').first();\n        }\n\n        this.selectItem($nextGroup.find('.note-hint-item').first());\n      }\n    };\n\n    this.moveUp = function () {\n      var $current = this.$content.find('.note-hint-item.active');\n      var $prev = $current.prev();\n\n      if ($prev.length) {\n        this.selectItem($prev);\n      } else {\n        var $prevGroup = $current.parent().prev();\n\n        if (!$prevGroup.length) {\n          $prevGroup = this.$content.find('.note-hint-group').last();\n        }\n\n        this.selectItem($prevGroup.find('.note-hint-item').last());\n      }\n    };\n\n    this.replace = function () {\n      var $item = this.$content.find('.note-hint-item.active');\n\n      if ($item.length) {\n        var node = this.nodeFromItem($item);\n        this.lastWordRange.insertNode(node);\n        range.createFromNode(node).collapse().select();\n\n        this.lastWordRange = null;\n        this.hide();\n        context.invoke('editor.focus');\n      }\n\n    };\n\n    this.nodeFromItem = function ($item) {\n      var hint = hints[$item.data('index')];\n      var item = $item.data('item');\n      var node = hint.content ? hint.content(item) : item;\n      if (typeof node === 'string') {\n        node = dom.createText(node);\n      }\n      return node;\n    };\n\n    this.createItemTemplates = function (hintIdx, items) {\n      var hint = hints[hintIdx];\n      return items.map(function (item, idx) {\n        var $item = $('<div class=\"note-hint-item\"/>');\n        $item.append(hint.template ? hint.template(item) : item + '');\n        $item.data({\n          'index': hintIdx,\n          'item': item\n        });\n\n        if (hintIdx === 0 && idx === 0) {\n          $item.addClass('active');\n        }\n        return $item;\n      });\n    };\n\n    this.handleKeydown = function (e) {\n      if (!this.$popover.is(':visible')) {\n        return;\n      }\n\n      if (e.keyCode === key.code.ENTER) {\n        e.preventDefault();\n        this.replace();\n      } else if (e.keyCode === key.code.UP) {\n        e.preventDefault();\n        this.moveUp();\n      } else if (e.keyCode === key.code.DOWN) {\n        e.preventDefault();\n        this.moveDown();\n      }\n    };\n\n    this.searchKeyword = function (index, keyword, callback) {\n      var hint = hints[index];\n      if (hint && hint.match.test(keyword) && hint.search) {\n        var matches = hint.match.exec(keyword);\n        hint.search(matches[1], callback);\n      } else {\n        callback();\n      }\n    };\n\n    this.createGroup = function (idx, keyword) {\n      var $group = $('<div class=\"note-hint-group note-hint-group-' + idx + '\"/>');\n      this.searchKeyword(idx, keyword, function (items) {\n        items = items || [];\n        if (items.length) {\n          $group.html(self.createItemTemplates(idx, items));\n          self.show();\n        }\n      });\n\n      return $group;\n    };\n\n    this.handleKeyup = function (e) {\n      if (list.contains([key.code.ENTER, key.code.UP, key.code.DOWN], e.keyCode)) {\n        if (e.keyCode === key.code.ENTER) {\n          if (this.$popover.is(':visible')) {\n            return;\n          }\n        }\n      } else {\n        var wordRange = context.invoke('editor.createRange').getWordRange();\n        var keyword = wordRange.toString();\n        if (hints.length && keyword) {\n          this.$content.empty();\n\n          var bnd = func.rect2bnd(list.last(wordRange.getClientRects()));\n          if (bnd) {\n\n            this.$popover.hide();\n\n            this.lastWordRange = wordRange;\n\n            hints.forEach(function (hint, idx) {\n              if (hint.match.test(keyword)) {\n                self.createGroup(idx, keyword).appendTo(self.$content);\n              }\n            });\n\n            // set position for popover after group is created\n            if (direction === 'top') {\n              this.$popover.css({\n                left: bnd.left,\n                top: bnd.top - this.$popover.outerHeight() - POPOVER_DIST\n              });\n            } else {\n              this.$popover.css({\n                left: bnd.left,\n                top: bnd.top + bnd.height + POPOVER_DIST\n              });\n            }\n\n          }\n        } else {\n          this.hide();\n        }\n      }\n    };\n\n    this.show = function () {\n      this.$popover.show();\n    };\n\n    this.hide = function () {\n      this.$popover.hide();\n    };\n  };\n\n\n  $.summernote = $.extend($.summernote, {\n    version: '0.8.2',\n    ui: ui,\n    dom: dom,\n\n    plugins: {},\n\n    options: {\n      modules: {\n        'editor': Editor,\n        'clipboard': Clipboard,\n        'dropzone': Dropzone,\n        'codeview': Codeview,\n        'statusbar': Statusbar,\n        'fullscreen': Fullscreen,\n        'handle': Handle,\n        // FIXME: HintPopover must be front of autolink\n        //  - Script error about range when Enter key is pressed on hint popover\n        'hintPopover': HintPopover,\n        'autoLink': AutoLink,\n        'autoSync': AutoSync,\n        'placeholder': Placeholder,\n        'buttons': Buttons,\n        'toolbar': Toolbar,\n        'linkDialog': LinkDialog,\n        'linkPopover': LinkPopover,\n        'imageDialog': ImageDialog,\n        'imagePopover': ImagePopover,\n        'videoDialog': VideoDialog,\n        'helpDialog': HelpDialog,\n        'airPopover': AirPopover\n      },\n\n      buttons: {},\n      \n      lang: 'en-US',\n\n      // toolbar\n      toolbar: [\n        ['style', ['style']],\n        ['font', ['bold', 'underline', 'clear']],\n        ['fontname', ['fontname']],\n        ['color', ['color']],\n        ['para', ['ul', 'ol', 'paragraph']],\n        ['table', ['table']],\n        ['insert', ['link', 'picture', 'video']],\n        ['view', ['fullscreen', 'codeview', 'help']]\n      ],\n\n      // popover\n      popover: {\n        image: [\n          ['imagesize', ['imageSize100', 'imageSize50', 'imageSize25']],\n          ['float', ['floatLeft', 'floatRight', 'floatNone']],\n          ['remove', ['removeMedia']]\n        ],\n        link: [\n          ['link', ['linkDialogShow', 'unlink']]\n        ],\n        air: [\n          ['color', ['color']],\n          ['font', ['bold', 'underline', 'clear']],\n          ['para', ['ul', 'paragraph']],\n          ['table', ['table']],\n          ['insert', ['link', 'picture']]\n        ]\n      },\n\n      // air mode: inline editor\n      airMode: false,\n\n      width: null,\n      height: null,\n\n      focus: false,\n      tabSize: 4,\n      styleWithSpan: true,\n      shortcuts: true,\n      textareaAutoSync: true,\n      direction: null,\n\n      styleTags: ['p', 'blockquote', 'pre', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'],\n\n      fontNames: [\n        'Arial', 'Arial Black', 'Comic Sans MS', 'Courier New',\n        'Helvetica Neue', 'Helvetica', 'Impact', 'Lucida Grande',\n        'Tahoma', 'Times New Roman', 'Verdana'\n      ],\n\n      fontSizes: ['8', '9', '10', '11', '12', '14', '18', '24', '36'],\n\n      // pallete colors(n x n)\n      colors: [\n        ['#000000', '#424242', '#636363', '#9C9C94', '#CEC6CE', '#EFEFEF', '#F7F7F7', '#FFFFFF'],\n        ['#FF0000', '#FF9C00', '#FFFF00', '#00FF00', '#00FFFF', '#0000FF', '#9C00FF', '#FF00FF'],\n        ['#F7C6CE', '#FFE7CE', '#FFEFC6', '#D6EFD6', '#CEDEE7', '#CEE7F7', '#D6D6E7', '#E7D6DE'],\n        ['#E79C9C', '#FFC69C', '#FFE79C', '#B5D6A5', '#A5C6CE', '#9CC6EF', '#B5A5D6', '#D6A5BD'],\n        ['#E76363', '#F7AD6B', '#FFD663', '#94BD7B', '#73A5AD', '#6BADDE', '#8C7BC6', '#C67BA5'],\n        ['#CE0000', '#E79439', '#EFC631', '#6BA54A', '#4A7B8C', '#3984C6', '#634AA5', '#A54A7B'],\n        ['#9C0000', '#B56308', '#BD9400', '#397B21', '#104A5A', '#085294', '#311873', '#731842'],\n        ['#630000', '#7B3900', '#846300', '#295218', '#083139', '#003163', '#21104A', '#4A1031']\n      ],\n\n      lineHeights: ['1.0', '1.2', '1.4', '1.5', '1.6', '1.8', '2.0', '3.0'],\n\n      tableClassName: 'table table-bordered',\n\n      insertTableMaxSize: {\n        col: 10,\n        row: 10\n      },\n\n      dialogsInBody: false,\n      dialogsFade: false,\n\n      maximumImageFileSize: null,\n\n      callbacks: {\n        onInit: null,\n        onFocus: null,\n        onBlur: null,\n        onEnter: null,\n        onKeyup: null,\n        onKeydown: null,\n        onImageUpload: null,\n        onImageUploadError: null\n      },\n\n      codemirror: {\n        mode: 'text/html',\n        htmlMode: true,\n        lineNumbers: true\n      },\n\n      keyMap: {\n        pc: {\n          'ENTER': 'insertParagraph',\n          'CTRL+Z': 'undo',\n          'CTRL+Y': 'redo',\n          'TAB': 'tab',\n          'SHIFT+TAB': 'untab',\n          'CTRL+B': 'bold',\n          'CTRL+I': 'italic',\n          'CTRL+U': 'underline',\n          'CTRL+SHIFT+S': 'strikethrough',\n          'CTRL+BACKSLASH': 'removeFormat',\n          'CTRL+SHIFT+L': 'justifyLeft',\n          'CTRL+SHIFT+E': 'justifyCenter',\n          'CTRL+SHIFT+R': 'justifyRight',\n          'CTRL+SHIFT+J': 'justifyFull',\n          'CTRL+SHIFT+NUM7': 'insertUnorderedList',\n          'CTRL+SHIFT+NUM8': 'insertOrderedList',\n          'CTRL+LEFTBRACKET': 'outdent',\n          'CTRL+RIGHTBRACKET': 'indent',\n          'CTRL+NUM0': 'formatPara',\n          'CTRL+NUM1': 'formatH1',\n          'CTRL+NUM2': 'formatH2',\n          'CTRL+NUM3': 'formatH3',\n          'CTRL+NUM4': 'formatH4',\n          'CTRL+NUM5': 'formatH5',\n          'CTRL+NUM6': 'formatH6',\n          'CTRL+ENTER': 'insertHorizontalRule',\n          'CTRL+K': 'linkDialog.show'\n        },\n\n        mac: {\n          'ENTER': 'insertParagraph',\n          'CMD+Z': 'undo',\n          'CMD+SHIFT+Z': 'redo',\n          'TAB': 'tab',\n          'SHIFT+TAB': 'untab',\n          'CMD+B': 'bold',\n          'CMD+I': 'italic',\n          'CMD+U': 'underline',\n          'CMD+SHIFT+S': 'strikethrough',\n          'CMD+BACKSLASH': 'removeFormat',\n          'CMD+SHIFT+L': 'justifyLeft',\n          'CMD+SHIFT+E': 'justifyCenter',\n          'CMD+SHIFT+R': 'justifyRight',\n          'CMD+SHIFT+J': 'justifyFull',\n          'CMD+SHIFT+NUM7': 'insertUnorderedList',\n          'CMD+SHIFT+NUM8': 'insertOrderedList',\n          'CMD+LEFTBRACKET': 'outdent',\n          'CMD+RIGHTBRACKET': 'indent',\n          'CMD+NUM0': 'formatPara',\n          'CMD+NUM1': 'formatH1',\n          'CMD+NUM2': 'formatH2',\n          'CMD+NUM3': 'formatH3',\n          'CMD+NUM4': 'formatH4',\n          'CMD+NUM5': 'formatH5',\n          'CMD+NUM6': 'formatH6',\n          'CMD+ENTER': 'insertHorizontalRule',\n          'CMD+K': 'linkDialog.show'\n        }\n      },\n      icons: {\n        'align': 'note-icon-align',\n        'alignCenter': 'note-icon-align-center',\n        'alignJustify': 'note-icon-align-justify',\n        'alignLeft': 'note-icon-align-left',\n        'alignRight': 'note-icon-align-right',\n        'indent': 'note-icon-align-indent',\n        'outdent': 'note-icon-align-outdent',\n        'arrowsAlt': 'note-icon-arrows-alt',\n        'bold': 'note-icon-bold',\n        'caret': 'note-icon-caret',\n        'circle': 'note-icon-circle',\n        'close': 'note-icon-close',\n        'code': 'note-icon-code',\n        'eraser': 'note-icon-eraser',\n        'font': 'note-icon-font',\n        'frame': 'note-icon-frame',\n        'italic': 'note-icon-italic',\n        'link': 'note-icon-link',\n        'unlink': 'note-icon-chain-broken',\n        'magic': 'note-icon-magic',\n        'menuCheck': 'note-icon-check',\n        'minus': 'note-icon-minus',\n        'orderedlist': 'note-icon-orderedlist',\n        'pencil': 'note-icon-pencil',\n        'picture': 'note-icon-picture',\n        'question': 'note-icon-question',\n        'redo': 'note-icon-redo',\n        'square': 'note-icon-square',\n        'strikethrough': 'note-icon-strikethrough',\n        'subscript': 'note-icon-subscript',\n        'superscript': 'note-icon-superscript',\n        'table': 'note-icon-table',\n        'textHeight': 'note-icon-text-height',\n        'trash': 'note-icon-trash',\n        'underline': 'note-icon-underline',\n        'undo': 'note-icon-undo',\n        'unorderedlist': 'note-icon-unorderedlist',\n        'video': 'note-icon-video'\n      }\n    }\n  });\n\n}));\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/base-component/amazeui/css/admin.css",
    "content": "/**\n * admin.css\n */\n\n\n/*\n fixed-layout 固定头部和边栏布局\n*/\n\nhtml,\nbody {\n  height: 100%;\n  overflow: hidden;\n}\n*{\n  font-family: \"Helvetica Neue\", \"Luxi Sans\", \"DejaVu Sans\", Tahoma, \"Hiragino Sans GB\", STHeiti, \"Microsoft YaHei\";\n}\n\nul {\n  margin-top: 0;\n}\n\n.admin-icon-yellow {\n  color: #ffbe40;\n}\n\n.admin-header {\n  border-width: 0 0 0px;\n  position: fixed;\n  top: 0;\n  left: 0;\n  right: 0;\n  z-index: 1500;\n  font-size: 1.4rem;\n  margin-bottom: 0;\n}\n\n.admin-header-list a:hover :after {\n  content: none;\n}\n\n.admin-main {\n  position: relative;\n  height: 100%;\n  padding-top: 50px;\n  background: #f3f3f3;\n}\n\n.admin-menu {\n  position: fixed;\n  z-index: 100;\n  bottom: 15px;\n  right: 20px;\n}\n.am-list>li>a{\n  padding:10px 0;\n}\n.admin-sidebar {\n  color:#333 !important;\n  font-size: 1.4rem;\n  width: 260px;\n  min-height: 100%;\n  float: left;\n  border-right: 1px solid #cecece;\n}\n\n.admin-sidebar.am-active {\n  z-index: 1600;\n}\n\n.admin-sidebar-list {\n  margin-bottom: 0;\n}\n\n.admin-sidebar-list li a {\n  color: #333;\n  padding-left: 24px;\n}\n\n.admin-sidebar-list li:first-child {\n  border-top: none;\n}\n\n.admin-sidebar-sub {\n  margin-top: 0;\n  margin-bottom: 0;\n  box-shadow: 0 16px 8px -15px #e2e2e2 inset;\n  background: #ececec;\n  padding-left: 24px;\n}\n\n.admin-sidebar-sub li:first-child {\n  border-top: 1px solid #dedede;\n}\n\n.admin-sidebar-panel {\n  margin: 10px;\n}\n\n.admin-content {\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -ms-flexbox;\n  display: flex;\n  -webkit-box-orient: vertical;\n  -webkit-box-direction: normal;\n  -webkit-flex-direction: column;\n  -ms-flex-direction: column;\n  flex-direction: column;\n  background: #fff;\n}\n\n.admin-content,\n.admin-sidebar {\n  height: 100%;\n  overflow-x: hidden;\n  /*overflow-y: scroll;*/\n  -webkit-overflow-scrolling: touch;\n}\n\n.admin-content-body {\n  /*-webkit-box-flex: 1;\n  -webkit-flex: 1 0 auto;\n  -ms-flex: 1 0 auto;\n  flex: 1 0 auto;*/\n  width: 100%;\n  height: 100%;\n}\n.admin-tab-show{\n  height: 38px;\n  overflow: hidden;\n  position: absolute;\n  top: 0px;\n  border-bottom: none;\n  z-index: 1000;\n  width: 100%;\n}\n.admin-tab-left{\n  right: -1px;\n  text-align: center;\n  width: 20px;\n  height: 39px;\n  line-height: 39px;\n  float: left;\n  border-right: 1px solid #ddd;\n  cursor: pointer;\n}\n.admin-tab-right{\n  text-align: center;\n  width: 20px;\n  height: 39px;\n  line-height: 39px;\n  float: right;\n  border-left: 1px solid #ddd;\n  cursor: pointer;\n}\n.admin-tab-min-hr{\n  position: absolute;\n  bottom: 0px;\n  width: 100%;\n  height: 1px;\n  display: block;\n  background-color: #ddd;\n}\n.admin-tab-show-body{\n  height: 100%;\n  padding-top: 40px;\n  padding-bottom: 42px;\n}\n.admin-content-footer {\n  width: 100%;\n  background-color: #ffffff;\n  position: absolute;\n  bottom: 0px;\n  font-size: 85%;\n  color: #777;\n  border-top: 1px solid #ddd;\n}\n.admin-content-footer-p{\n  margin: 10px !important;\n}\n.admin-content-list {\n  border: 1px solid #e9ecf1;\n  margin-top: 0;\n}\n\n.admin-content-list li {\n  border: 1px solid #e9ecf1;\n  border-width: 0 1px;\n  margin-left: -1px;\n}\n\n.admin-content-list li:first-child {\n  border-left: none;\n}\n\n.admin-content-list li:last-child {\n  border-right: none;\n}\n\n.admin-content-table a {\n  color: #535353;\n}\n.admin-content-file {\n  margin-bottom: 0;\n  color: #666;\n}\n\n.admin-content-file p {\n  margin: 0 0 5px 0;\n  font-size: 1.4rem;\n}\n\n.admin-content-file li {\n  padding: 10px 0;\n}\n\n.admin-content-file li:first-child {\n  border-top: none;\n}\n\n.admin-content-file li:last-child {\n  border-bottom: none;\n}\n\n.admin-content-file li .am-progress {\n  margin-bottom: 4px;\n}\n\n.admin-content-file li .am-progress-bar {\n  line-height: 14px;\n}\n\n.admin-content-task {\n  margin-bottom: 0;\n}\n\n.admin-content-task li {\n  padding: 5px 0;\n  border-color: #eee;\n}\n\n.admin-content-task li:first-child {\n  border-top: none;\n}\n\n.admin-content-task li:last-child {\n  border-bottom: none;\n}\n\n.admin-task-meta {\n  font-size: 1.2rem;\n  color: #999;\n}\n\n.admin-task-bd {\n  font-size: 1.4rem;\n  margin-bottom: 5px;\n}\n\n.admin-content-comment {\n  margin-bottom: 0;\n}\n\n.admin-content-comment .am-comment-bd {\n  font-size: 1.4rem;\n}\n\n.admin-content-pagination {\n  margin-bottom: 0;\n}\n.admin-content-pagination li a {\n  padding: 4px 8px;\n}\n\n@media only screen and (min-width: 641px) {\n  .admin-sidebar {\n    display: block;\n    position: static;\n    background: none;\n  }\n\n  .admin-offcanvas-bar {\n    position: static;\n    width: auto;\n    background: none;\n    -webkit-transform: translate3d(0, 0, 0);\n    -ms-transform: translate3d(0, 0, 0);\n    transform: translate3d(0, 0, 0);\n    overflow-y: visible;\n    /*min-height: 100%;*/\n  }\n  .admin-offcanvas-bar:after {\n    content: none;\n  }\n}\n\n@media only screen and (max-width: 640px) {\n  .admin-tab-show{\n    display: none;\n  }\n  .admin-tab-show-body{\n    padding-top: 0px;\n    padding-bottom: 0px;\n  }\n  .admin-content-footer{\n    display: none;\n  }\n  .admin-sidebar {\n    width: inherit;\n  }\n\n  .admin-offcanvas-bar {\n    background: #f3f3f3;\n  }\n\n  .admin-offcanvas-bar:after {\n    background: #BABABA;\n  }\n\n  .admin-sidebar-list a:hover, .admin-sidebar-list a:active{\n    -webkit-transition: background-color .3s ease;\n    -moz-transition: background-color .3s ease;\n    -ms-transition: background-color .3s ease;\n    -o-transition: background-color .3s ease;\n    transition: background-color .3s ease;\n    background: #E4E4E4;\n  }\n\n  .admin-content-list li {\n    padding: 10px;\n    border-width: 1px 0;\n    margin-top: -1px;\n  }\n\n  .admin-content-list li:first-child {\n    border-top: none;\n  }\n\n  .admin-content-list li:last-child {\n    border-bottom: none;\n  }\n\n  .admin-form-text {\n    text-align: left !important;\n  }\n  .am-tab-panel{\n    padding: 0px !important;\n  }\n\n}\n\n/*\n* user.html css\n*/\n.user-info {\n  margin-bottom: 15px;\n}\n\n.user-info .am-progress {\n  margin-bottom: 4px;\n}\n\n.user-info p {\n  margin: 5px;\n}\n\n.user-info-order {\n  font-size: 1.4rem;\n}\n\n/*\n* errorLog.html css\n*/\n\n.error-log .am-pre-scrollable {\n  max-height: 40rem;\n}\n\n/*\n* table.html css\n*/\n\n.table-main {\n  font-size: 1.4rem;\n  padding: .5rem;\n}\n\n.table-main button {\n  background: #fff;\n}\n\n.table-check {\n  width: 30px;\n}\n\n.table-id {\n  width: 50px;\n}\n\n@media only screen and (max-width: 640px) {\n  .table-select {\n    margin-top: 10px;\n    margin-left: 5px;\n  }\n}\n\n/*\ngallery.html css\n*/\n\n.gallery-list li {\n  padding: 10px;\n}\n\n.gallery-list a {\n  color: #666;\n}\n\n.gallery-list a:hover {\n  color: #3bb4f2;\n}\n\n.gallery-title {\n  margin-top: 6px;\n  font-size: 1.4rem;\n}\n\n.gallery-desc {\n  font-size: 1.2rem;\n  margin-top: 4px;\n}\n.am-nav-tabs>li>a {\n  padding: .5rem 2rem;\n  /* padding: 1rem; */\n  margin-right: 0px !important;\n  line-height: 1.6;\n  border: 1px solid transparent;\n  border-radius: 0;\n  font-weight: 600;\n}\n\n/*\n 404.html css\n*/\n\n.page-404 {\n  background: #fff;\n  border: none;\n  width: 200px;\n  margin: 0 auto;\n}\n.am-tabs-nav li {\n  position: relative;\n  z-index: 1;\n}\n\n.am-tabs-nav .am-icon-close {\n  position: absolute;\n  top: 6px;\n  right: 8px;\n  color: #888;\n  cursor: pointer;\n  z-index: 100;\n}\n\n.am-tabs-nav .am-icon-close:hover {\n  color: #333;\n}\n\n.am-tabs-nav .am-icon-close ~ a {\n  padding-right: 25px!important;\n}\n.am-nav-tabs>li.am-active>a{\n  color:#333 !important;\n}\n.am-tab-refresh {\n  font-size: 14px;\n  position: absolute;\n  top: 9px;\n  left: 8px;\n  color: #888;\n  cursor: pointer;\n  z-index: 100;\n}\n.am-tab-panel{\n  padding: 0px !important;\n}"
  },
  {
    "path": "open-layui-web/src/main/view/static/base-component/amazeui/css/amazeui.css",
    "content": "/*! Amaze UI v2.6.0 | by Amaze UI Team | (c) 2016 AllMobilize, Inc. | Licensed under MIT | 2016-03-31T14:28:54+0800 */\n/* ==========================================================================\n   Component: Base\n ============================================================================ */\n/**\n * Fix the flawed CSS box model - Yes, IE6's box model is better\n * Browser support: IE8+\n * via: http://paulirish.com/2012/box-sizing-border-box-ftw/\n */\n*,\n*:before,\n*:after {\n  -webkit-box-sizing: border-box;\n          box-sizing: border-box;\n}\n/* normalize.css v3.0.2 | git.io/normalize */\n/* Set <html> and <body> to inherit the height of the viewport */\nhtml,\nbody {\n  min-height: 100%;\n}\n/**\n * 1. Prevent iOS text size adjust after orientation change, without disabling\n *    user zoom.\n *    https://developer.mozilla.org/en-US/docs/Web/CSS/text-size-adjust\n */\nhtml {\n  -ms-text-size-adjust: 100%;\n  /* 1 */\n  -webkit-text-size-adjust: 100%;\n  /* 1 */\n}\n/**\n * Remove default margin.\n */\nbody {\n  margin: 0;\n}\n/* HTML5 display definitions\n   ========================================================================== */\n/**\n * Correct `block` display not defined for any HTML5 element in IE 8/9.\n * Correct `block` display not defined for `details` or `summary` in IE 10/11 and Firefox.\n * Correct `block` display not defined for `main` in IE 11.\n * hgroup has been removed from the HTML5 (W3C) specification\n *        https://developer.mozilla.org/en-US/docs/Web/HTML/Element/hgroup\n */\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmenu,\nmain,\nnav,\nsection,\nsummary {\n  display: block;\n}\n/**\n * 1. Correct `inline-block` display not defined in IE 8/9.\n * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.\n */\naudio,\ncanvas,\nprogress,\nvideo {\n  display: inline-block;\n  /* 1 */\n  vertical-align: baseline;\n  /* 2 */\n}\n/**\n * Prevent modern browsers from displaying `audio` without controls.\n * Remove excess height in iOS 5 devices.\n */\naudio:not([controls]) {\n  display: none;\n  height: 0;\n}\n/**\n * Address `[hidden]` styling not present in IE 8/9/10.\n * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.\n */\n[hidden],\ntemplate,\nscript {\n  display: none;\n}\n/* Links\n   ========================================================================== */\n/**\n * Remove the gray background color from active links in IE 10.\n */\na {\n  background-color: transparent;\n}\n/**\n * Address `outline` inconsistency between Chrome and other browsers.\n */\na:focus {\n  outline: thin dotted;\n}\n/**\n * Improve readability when focused and also mouse hovered in all browsers.\n */\na:active,\na:hover {\n  outline: 0;\n}\n/* Text-level semantics\n   ========================================================================== */\n/**\n * Remove text-decoration\n */\nins,\na {\n  text-decoration: none;\n}\n/**\n * Address styling not present in IE 8/9, Safari 5, and Chrome.\n */\nabbr[title] {\n  border-bottom: 1px dotted;\n}\n/**\n * Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome.\n */\nb,\nstrong {\n  font-weight: bold;\n}\n/**\n * Improve readability of pre-formatted text in all browsers.\n */\npre {\n  white-space: pre-wrap;\n}\n/**\n * Set consistent quote types.\n */\nq {\n  quotes: \"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\";\n}\n/**\n * Address inconsistent and variable font size in all browsers.\n */\nsmall {\n  font-size: 80%;\n}\n/**\n * Prevent `sub` and `sup` affecting `line-height` in all browsers.\n */\nsub,\nsup {\n  font-size: 75%;\n  line-height: 0;\n  position: relative;\n  vertical-align: baseline;\n}\nsup {\n  top: -0.5em;\n}\nsub {\n  bottom: -0.25em;\n}\n/* Embedded content\n   ========================================================================== */\n/**\n  * 1. Corrects max-width behavior (2.) if padding and border are used\n  * 2. Responsiveness: Sets a maxium width relative to the parent and auto scales the height\n  * 3. Remove the gap between images and the bottom of their containers\n  * 4. Remove border when inside `a` element in IE 8/9.\n  * remove 2. for Issue #502\n  */\nimg {\n  -webkit-box-sizing: border-box;\n          box-sizing: border-box;\n  /* 1 */\n  vertical-align: middle;\n  /* 3 */\n  border: 0;\n  /* 4 */\n}\n/**\n * Correct overflow displayed oddly in IE 9.\n */\nsvg:not(:root) {\n  overflow: hidden;\n}\n/* Grouping content\n   ========================================================================== */\n/**\n * Address margin not present in IE 8/9 and Safari.\n */\nfigure {\n  margin: 0;\n}\n/**\n * Correct font family set oddly in Safari 5 and Chrome.\n */\ncode,\nkbd,\npre,\nsamp {\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", \"FontAwesome\", monospace;\n  font-size: 1em;\n}\n/* Forms\n   ========================================================================== */\n/**\n * Define consistent border, margin, and padding.\n */\nfieldset {\n  border: 1px solid #c0c0c0;\n  margin: 0 2px;\n  padding: 0.35em 0.625em 0.75em;\n}\n/**\n * 1. Correct `color` not being inherited in IE 8/9.\n * 2. Remove padding so people aren't caught out if they zero out fieldsets.\n */\nlegend {\n  border: 0;\n  /* 1 */\n  padding: 0;\n  /* 2 */\n}\n/**\n * 1. Correct color not being inherited.\n *    Known issue: affects color of disabled elements.\n * 2. Correct font properties not being inherited.\n * 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome.\n */\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n  color: inherit;\n  /* 1 */\n  font: inherit;\n  /* 2 */\n  margin: 0;\n  /* 3 */\n}\n/**\n * Address `overflow` set to `hidden` in IE 8/9/10/11.\n */\nbutton {\n  overflow: visible;\n}\n/**\n * Address Firefox 4+ setting `line-height` on `input` using `!important` in\n * the UA stylesheet.\n */\nbutton,\ninput {\n  line-height: normal;\n}\n/**\n * Address inconsistent `text-transform` inheritance for `button` and `select`.\n * All other form control elements do not inherit `text-transform` values.\n * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.\n * Correct `select` style inheritance in Firefox.\n */\nbutton,\nselect {\n  text-transform: none;\n}\n/**\n * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`\n *    and `video` controls.\n * 2. Correct inability to style clickable `input` types in iOS.\n * 3. Improve usability and consistency of cursor style between image-type\n *    `input` and others.\n */\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  -webkit-appearance: button;\n  /* 2 */\n  cursor: pointer;\n  /* 3 */\n}\n/*\n * 1. Improves consistency of cursor style for clickable elements\n * 2. Removes excess padding in IE 8/9.\n * 3. Address box sizing set to `content-box` in IE 8/9/10.\n */\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n  /*1*/\n  padding: 0;\n  /*2*/\n  -webkit-box-sizing: border-box;\n          box-sizing: border-box;\n  /* 3 */\n}\n/**\n * Re-set default cursor for disabled elements.\n */\nbutton[disabled],\nhtml input[disabled] {\n  cursor: default;\n}\n/**\n * Remove inner padding and border in Firefox 4+.\n */\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  border: 0;\n  padding: 0;\n}\n/**\n * Fix the cursor style for Chrome's increment/decrement buttons. For certain\n * `font-size` values of the `input`, it causes the cursor style of the\n * decrement button to change from `default` to `text`.\n */\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n  height: auto;\n}\n/**\n * 1. Address `appearance` set to `searchfield` in Safari and Chrome.\n * 2. Address `box-sizing` set to `border-box` in Safari and Chrome\n *    (include `-moz` to future-proof).\n */\ninput[type=\"search\"] {\n  -webkit-appearance: textfield;\n  /* 1 */\n  -webkit-box-sizing: content-box;\n          box-sizing: content-box;\n  /* 2 */\n}\n/**\n * Remove inner padding and search cancel button in Safari 5 and Chrome\n * on OS X.\n */\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n  -webkit-appearance: none;\n}\n/**\n * 1. Remove default vertical scrollbar in IE 8/9.\n * 2. Improve readability and alignment in all browsers.\n */\ntextarea {\n  overflow: auto;\n  /* 1 */\n  vertical-align: top;\n  /* 2 */\n  resize: vertical;\n}\n/**\n * Don't inherit the `font-weight` (applied by a rule above).\n * NOTE: the default cannot safely be changed in Chrome and Safari on OS X.\n */\noptgroup {\n  font-weight: bold;\n}\n/* Tables\n   ========================================================================== */\n/**\n * Remove most spacing between table cells.\n */\ntable {\n  border-collapse: collapse;\n  border-spacing: 0;\n}\ntd,\nth {\n  padding: 0;\n}\n/* AMUI Base\n   ========================================================================== */\n/**\n * `font-size` is set in `html` element to support the `rem` unit for font-sizes\n * NOTE: IE9 & IE10 do not recognize `rem` units when used with the\n   `font` shorthand property.\n */\nhtml {\n  font-size: 10px;\n  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\nbody {\n  position: relative;\n  background: #fff;\n  font-family: \"Segoe UI\", \"Lucida Grande\", Helvetica, Arial, \"Microsoft YaHei\", FreeSans, Arimo, \"Droid Sans\", \"wenquanyi micro hei\", \"Hiragino Sans GB\", \"Hiragino Sans GB W3\", \"FontAwesome\", sans-serif;\n  font-weight: normal;\n  line-height: 1.6;\n  color: #333333;\n  font-size: 1.6rem;\n}\n/**\n * 1. http://usabilitypost.com/2012/11/15/w-optimizelegibility-on-mobile-devices/\n * 2. http://maxvoltar.com/archive/-webkit-font-smoothing\n * NOTE: http://usabilitypost.com/2012/11/05/stop-fixing-font-smoothing/\n * 3. http://maximilianhoffmann.com/posts/better-font-rendering-on-osx\n *    http://jaydenseric.com/blog/css-font-smoothing-for-firefox-mac\n */\nbody,\ninput,\ntextarea,\nselect,\nbutton {\n  text-rendering: optimizeLegibility;\n  /* 1 */\n  -webkit-font-smoothing: antialiased;\n  /* 2 */\n  -moz-osx-font-smoothing: grayscale;\n  /* 3 Default: auto */\n  -moz-font-feature-settings: \"liga\", \"kern\";\n}\n/*Only phones */\n@media only screen and (max-width: 640px) {\n  /**\n   * Break strings if their length exceeds the width of their container\n   */\n  body {\n    word-wrap: break-word;\n    -webkit-hyphens: auto;\n    -ms-hyphens: auto;\n    -moz-hyphens: auto;\n    hyphens: auto;\n  }\n}\n/**\n * links\n */\na {\n  color: #0e90d2;\n}\na:hover,\na:focus {\n  color: #095f8a;\n}\na:focus {\n  outline: thin dotted;\n  outline: 1px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n/* Insert */\nins {\n  background: #ffa;\n  color: #333333;\n}\n/**\n * Mark\n * Note: Addresses styling not present in IE 8/9.\n */\nmark {\n  background: #ffa;\n  color: #333333;\n}\n/**\n * Abbreviation and definition\n */\nabbr[title],\ndfn[title] {\n  cursor: help;\n}\ndfn[title] {\n  border-bottom: 1px dotted;\n  font-style: normal;\n}\n/* Spacing for block elements */\np,\nhr,\nul,\nol,\ndl,\nblockquote,\npre,\naddress,\nfieldset,\nfigure {\n  margin: 0 0 1.6rem 0;\n}\n* + p,\n* + hr,\n* + ul,\n* + ol,\n* + dl,\n* + blockquote,\n* + pre,\n* + address,\n* + fieldset,\n* + figure {\n  margin-top: 1.6rem;\n}\n/* Headings\n   ========================================================================== */\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 0 0 1.6rem 0;\n  font-weight: 600;\n  font-size: 100%;\n}\nh1 {\n  font-size: 1.5em;\n}\nh2 {\n  font-size: 1.25em;\n}\n* + h1,\n* + h2,\n* + h3,\n* + h4,\n* + h5,\n* + h6 {\n  margin-top: 2em;\n}\n/* Ordered and unordered lists */\nul,\nol {\n  padding-left: 2em;\n}\n/* Reset margin for nested lists */\nul > li > ul,\nul > li > ol,\nol > li > ol,\nol > li > ul {\n  margin: 1em 0;\n}\n/* Description lists */\ndt {\n  font-weight: bold;\n}\ndt + dd {\n  margin-top: .5em;\n}\ndd {\n  margin-left: 0;\n}\ndd + dt {\n  margin-top: 1em;\n}\n/**\n * Horizontal rule\n * 1. Address differences between Firefox and other browsers.\n */\nhr {\n  display: block;\n  padding: 0;\n  border: 0;\n  height: 0;\n  border-top: 1px solid #eeeeee;\n  /* 1 */\n  -webkit-box-sizing: content-box;\n          box-sizing: content-box;\n  /* 1 */\n}\n/* Address */\naddress {\n  font-style: normal;\n}\n/* Quotes */\nblockquote {\n  padding-top: 5px;\n  padding-bottom: 5px;\n  padding-left: 15px;\n  border-left: 4px solid #ddd;\n  font-family: Georgia, \"Times New Roman\", Times, Kai, \"Kaiti SC\", KaiTi, BiauKai, \"FontAwesome\", serif;\n  /* Small print for identifying the source */\n  /* Smaller margin if `small` follows */\n}\nblockquote small {\n  display: block;\n  color: #999999;\n  font-family: \"Segoe UI\", \"Lucida Grande\", Helvetica, Arial, \"Microsoft YaHei\", FreeSans, Arimo, \"Droid Sans\", \"wenquanyi micro hei\", \"Hiragino Sans GB\", \"Hiragino Sans GB W3\", \"FontAwesome\", sans-serif;\n  text-align: right;\n}\nblockquote p:last-of-type {\n  margin-bottom: 0;\n}\n/* iframe */\niframe {\n  border: 0;\n}\n/* Forms\n   ========================================================================== */\n/**\n  * Vertical alignment\n  * Exclude `radio` and `checkbox` elements because the default `baseline` value aligns better with text\n  */\nbutton,\ninput:not([type=\"radio\"]):not([type=\"checkbox\"]),\nselect {\n  vertical-align: middle;\n}\n/**\n * Fix viewport for IE10 snap mode\n * http://timkadlec.com/2012/10/ie10-snap-mode-and-responsive-design/\n * http://msdn.microsoft.com/en-us/library/ie/hh869615%28v=vs.85%29.aspx\n * http://msdn.microsoft.com/zh-cn/library/ie/hh708740(v=vs.85).aspx\n * @2014.01.20: 设置一下属性以后，windows Phone 8 上显示的字体过小，暂时注释掉\n * ========================================================================== */\n/*\n@-ms-viewport {\n  width: device-width;\n}\n*/\n.am-scrollbar-measure {\n  width: 100px;\n  height: 100px;\n  overflow: scroll;\n  position: absolute;\n  top: -9999px;\n}\n/* ==========================================================================\n   Component: Grid\n ============================================================================ */\n.am-container {\n  -webkit-box-sizing: border-box;\n          box-sizing: border-box;\n  margin-left: auto;\n  margin-right: auto;\n  padding-left: 1rem;\n  padding-right: 1rem;\n  width: 100%;\n  max-width: 1300px;\n}\n.am-container:before,\n.am-container:after {\n  content: \" \";\n  display: table;\n}\n.am-container:after {\n  clear: both;\n}\n@media only screen and (min-width:641px) {\n  .am-container {\n    padding-left: 1.5rem;\n    padding-right: 1.5rem;\n  }\n}\n.am-container > .am-g {\n  width: auto;\n  margin-left: -1rem;\n  margin-right: -1rem;\n}\n@media only screen and (min-width:641px) {\n  .am-container > .am-g {\n    margin-left: -1.5rem;\n    margin-right: -1.5rem;\n  }\n}\n.am-g {\n  margin: 0 auto;\n  width: 100%;\n}\n.am-g:before,\n.am-g:after {\n  content: \" \";\n  display: table;\n}\n.am-g:after {\n  clear: both;\n}\n.am-g .am-g {\n  margin-left: -1rem;\n  margin-right: -1rem;\n  width: auto;\n}\n.am-g .am-g.am-g-collapse {\n  margin-left: 0;\n  margin-right: 0;\n  width: auto;\n}\n@media only screen and (min-width:641px) {\n  .am-g .am-g {\n    margin-left: -1.5rem;\n    margin-right: -1.5rem;\n  }\n}\n.am-g.am-g-collapse .am-g {\n  margin-left: 0;\n  margin-right: 0;\n}\n.am-g-collapse [class*=\"am-u-\"] {\n  padding-left: 0;\n  padding-right: 0;\n}\n.am-g-fixed {\n  max-width: 1000px;\n}\n[class*=\"am-u-\"] {\n  width: 100%;\n  padding-left: 1rem;\n  padding-right: 1rem;\n  float: left;\n  position: relative;\n}\n[class*=\"am-u-\"] + [class*=\"am-u-\"]:last-child {\n  float: right;\n}\n[class*=\"am-u-\"] + [class*=\"am-u-\"].am-u-end {\n  float: left;\n}\n@media only screen and (min-width:641px) {\n  [class*=\"am-u-\"] {\n    padding-left: 1.5rem;\n    padding-right: 1.5rem;\n  }\n}\n[class*=\"am-u-pull-\"] {\n  left: auto;\n}\n[class*=\"am-u-push-\"] {\n  right: auto;\n}\n@media only screen {\n  .am-u-sm-1 {\n    width: 8.33333333%;\n  }\n  .am-u-sm-2 {\n    width: 16.66666667%;\n  }\n  .am-u-sm-3 {\n    width: 25%;\n  }\n  .am-u-sm-4 {\n    width: 33.33333333%;\n  }\n  .am-u-sm-5 {\n    width: 41.66666667%;\n  }\n  .am-u-sm-6 {\n    width: 50%;\n  }\n  .am-u-sm-7 {\n    width: 58.33333333%;\n  }\n  .am-u-sm-8 {\n    width: 66.66666667%;\n  }\n  .am-u-sm-9 {\n    width: 75%;\n  }\n  .am-u-sm-10 {\n    width: 83.33333333%;\n  }\n  .am-u-sm-11 {\n    width: 91.66666667%;\n  }\n  .am-u-sm-12 {\n    width: 100%;\n  }\n  .am-u-sm-pull-0 {\n    right: 0;\n  }\n  .am-u-sm-pull-1 {\n    right: 8.33333333%;\n  }\n  .am-u-sm-pull-2 {\n    right: 16.66666667%;\n  }\n  .am-u-sm-pull-3 {\n    right: 25%;\n  }\n  .am-u-sm-pull-4 {\n    right: 33.33333333%;\n  }\n  .am-u-sm-pull-5 {\n    right: 41.66666667%;\n  }\n  .am-u-sm-pull-6 {\n    right: 50%;\n  }\n  .am-u-sm-pull-7 {\n    right: 58.33333333%;\n  }\n  .am-u-sm-pull-8 {\n    right: 66.66666667%;\n  }\n  .am-u-sm-pull-9 {\n    right: 75%;\n  }\n  .am-u-sm-pull-10 {\n    right: 83.33333333%;\n  }\n  .am-u-sm-pull-11 {\n    right: 91.66666667%;\n  }\n  .am-u-sm-push-0 {\n    left: 0;\n  }\n  .am-u-sm-push-1 {\n    left: 8.33333333%;\n  }\n  .am-u-sm-push-2 {\n    left: 16.66666667%;\n  }\n  .am-u-sm-push-3 {\n    left: 25%;\n  }\n  .am-u-sm-push-4 {\n    left: 33.33333333%;\n  }\n  .am-u-sm-push-5 {\n    left: 41.66666667%;\n  }\n  .am-u-sm-push-6 {\n    left: 50%;\n  }\n  .am-u-sm-push-7 {\n    left: 58.33333333%;\n  }\n  .am-u-sm-push-8 {\n    left: 66.66666667%;\n  }\n  .am-u-sm-push-9 {\n    left: 75%;\n  }\n  .am-u-sm-push-10 {\n    left: 83.33333333%;\n  }\n  .am-u-sm-push-11 {\n    left: 91.66666667%;\n  }\n  .am-u-sm-offset-0 {\n    margin-left: 0;\n  }\n  .am-u-sm-offset-1 {\n    margin-left: 8.33333333%;\n  }\n  .am-u-sm-offset-2 {\n    margin-left: 16.66666667%;\n  }\n  .am-u-sm-offset-3 {\n    margin-left: 25%;\n  }\n  .am-u-sm-offset-4 {\n    margin-left: 33.33333333%;\n  }\n  .am-u-sm-offset-5 {\n    margin-left: 41.66666667%;\n  }\n  .am-u-sm-offset-6 {\n    margin-left: 50%;\n  }\n  .am-u-sm-offset-7 {\n    margin-left: 58.33333333%;\n  }\n  .am-u-sm-offset-8 {\n    margin-left: 66.66666667%;\n  }\n  .am-u-sm-offset-9 {\n    margin-left: 75%;\n  }\n  .am-u-sm-offset-10 {\n    margin-left: 83.33333333%;\n  }\n  .am-u-sm-offset-11 {\n    margin-left: 91.66666667%;\n  }\n  .am-u-sm-reset-order {\n    margin-left: 0;\n    margin-right: 0;\n    left: auto;\n    right: auto;\n    float: left;\n  }\n  [class*=\"am-u-\"].am-u-sm-centered {\n    margin-left: auto;\n    margin-right: auto;\n    float: none;\n  }\n  [class*=\"am-u-\"].am-u-sm-centered:last-child {\n    float: none;\n  }\n  [class*=\"am-u-\"].am-u-sm-uncentered {\n    margin-left: 0;\n    margin-right: 0;\n    float: left;\n  }\n  [class*=\"am-u-\"].am-u-sm-uncentered:last-child {\n    float: left;\n  }\n}\n@media only screen and (min-width:641px) {\n  .am-u-md-1 {\n    width: 8.33333333%;\n  }\n  .am-u-md-2 {\n    width: 16.66666667%;\n  }\n  .am-u-md-3 {\n    width: 25%;\n  }\n  .am-u-md-4 {\n    width: 33.33333333%;\n  }\n  .am-u-md-5 {\n    width: 41.66666667%;\n  }\n  .am-u-md-6 {\n    width: 50%;\n  }\n  .am-u-md-7 {\n    width: 58.33333333%;\n  }\n  .am-u-md-8 {\n    width: 66.66666667%;\n  }\n  .am-u-md-9 {\n    width: 75%;\n  }\n  .am-u-md-10 {\n    width: 83.33333333%;\n  }\n  .am-u-md-11 {\n    width: 91.66666667%;\n  }\n  .am-u-md-12 {\n    width: 100%;\n  }\n  .am-u-md-pull-0 {\n    right: 0;\n  }\n  .am-u-md-pull-1 {\n    right: 8.33333333%;\n  }\n  .am-u-md-pull-2 {\n    right: 16.66666667%;\n  }\n  .am-u-md-pull-3 {\n    right: 25%;\n  }\n  .am-u-md-pull-4 {\n    right: 33.33333333%;\n  }\n  .am-u-md-pull-5 {\n    right: 41.66666667%;\n  }\n  .am-u-md-pull-6 {\n    right: 50%;\n  }\n  .am-u-md-pull-7 {\n    right: 58.33333333%;\n  }\n  .am-u-md-pull-8 {\n    right: 66.66666667%;\n  }\n  .am-u-md-pull-9 {\n    right: 75%;\n  }\n  .am-u-md-pull-10 {\n    right: 83.33333333%;\n  }\n  .am-u-md-pull-11 {\n    right: 91.66666667%;\n  }\n  .am-u-md-push-0 {\n    left: 0;\n  }\n  .am-u-md-push-1 {\n    left: 8.33333333%;\n  }\n  .am-u-md-push-2 {\n    left: 16.66666667%;\n  }\n  .am-u-md-push-3 {\n    left: 25%;\n  }\n  .am-u-md-push-4 {\n    left: 33.33333333%;\n  }\n  .am-u-md-push-5 {\n    left: 41.66666667%;\n  }\n  .am-u-md-push-6 {\n    left: 50%;\n  }\n  .am-u-md-push-7 {\n    left: 58.33333333%;\n  }\n  .am-u-md-push-8 {\n    left: 66.66666667%;\n  }\n  .am-u-md-push-9 {\n    left: 75%;\n  }\n  .am-u-md-push-10 {\n    left: 83.33333333%;\n  }\n  .am-u-md-push-11 {\n    left: 91.66666667%;\n  }\n  .am-u-md-offset-0 {\n    margin-left: 0;\n  }\n  .am-u-md-offset-1 {\n    margin-left: 8.33333333%;\n  }\n  .am-u-md-offset-2 {\n    margin-left: 16.66666667%;\n  }\n  .am-u-md-offset-3 {\n    margin-left: 25%;\n  }\n  .am-u-md-offset-4 {\n    margin-left: 33.33333333%;\n  }\n  .am-u-md-offset-5 {\n    margin-left: 41.66666667%;\n  }\n  .am-u-md-offset-6 {\n    margin-left: 50%;\n  }\n  .am-u-md-offset-7 {\n    margin-left: 58.33333333%;\n  }\n  .am-u-md-offset-8 {\n    margin-left: 66.66666667%;\n  }\n  .am-u-md-offset-9 {\n    margin-left: 75%;\n  }\n  .am-u-md-offset-10 {\n    margin-left: 83.33333333%;\n  }\n  .am-u-md-offset-11 {\n    margin-left: 91.66666667%;\n  }\n  .am-u-md-reset-order {\n    margin-left: 0;\n    margin-right: 0;\n    left: auto;\n    right: auto;\n    float: left;\n  }\n  [class*=\"am-u-\"].am-u-md-centered {\n    margin-left: auto;\n    margin-right: auto;\n    float: none;\n  }\n  [class*=\"am-u-\"].am-u-md-centered:last-child {\n    float: none;\n  }\n  [class*=\"am-u-\"].am-u-md-uncentered {\n    margin-left: 0;\n    margin-right: 0;\n    float: left;\n  }\n  [class*=\"am-u-\"].am-u-md-uncentered:last-child {\n    float: left;\n  }\n}\n@media only screen and (min-width:1025px) {\n  .am-u-lg-1 {\n    width: 8.33333333%;\n  }\n  .am-u-lg-2 {\n    width: 16.66666667%;\n  }\n  .am-u-lg-3 {\n    width: 25%;\n  }\n  .am-u-lg-4 {\n    width: 33.33333333%;\n  }\n  .am-u-lg-5 {\n    width: 41.66666667%;\n  }\n  .am-u-lg-6 {\n    width: 50%;\n  }\n  .am-u-lg-7 {\n    width: 58.33333333%;\n  }\n  .am-u-lg-8 {\n    width: 66.66666667%;\n  }\n  .am-u-lg-9 {\n    width: 75%;\n  }\n  .am-u-lg-10 {\n    width: 83.33333333%;\n  }\n  .am-u-lg-11 {\n    width: 91.66666667%;\n  }\n  .am-u-lg-12 {\n    width: 100%;\n  }\n  .am-u-lg-pull-0 {\n    right: 0;\n  }\n  .am-u-lg-pull-1 {\n    right: 8.33333333%;\n  }\n  .am-u-lg-pull-2 {\n    right: 16.66666667%;\n  }\n  .am-u-lg-pull-3 {\n    right: 25%;\n  }\n  .am-u-lg-pull-4 {\n    right: 33.33333333%;\n  }\n  .am-u-lg-pull-5 {\n    right: 41.66666667%;\n  }\n  .am-u-lg-pull-6 {\n    right: 50%;\n  }\n  .am-u-lg-pull-7 {\n    right: 58.33333333%;\n  }\n  .am-u-lg-pull-8 {\n    right: 66.66666667%;\n  }\n  .am-u-lg-pull-9 {\n    right: 75%;\n  }\n  .am-u-lg-pull-10 {\n    right: 83.33333333%;\n  }\n  .am-u-lg-pull-11 {\n    right: 91.66666667%;\n  }\n  .am-u-lg-push-0 {\n    left: 0;\n  }\n  .am-u-lg-push-1 {\n    left: 8.33333333%;\n  }\n  .am-u-lg-push-2 {\n    left: 16.66666667%;\n  }\n  .am-u-lg-push-3 {\n    left: 25%;\n  }\n  .am-u-lg-push-4 {\n    left: 33.33333333%;\n  }\n  .am-u-lg-push-5 {\n    left: 41.66666667%;\n  }\n  .am-u-lg-push-6 {\n    left: 50%;\n  }\n  .am-u-lg-push-7 {\n    left: 58.33333333%;\n  }\n  .am-u-lg-push-8 {\n    left: 66.66666667%;\n  }\n  .am-u-lg-push-9 {\n    left: 75%;\n  }\n  .am-u-lg-push-10 {\n    left: 83.33333333%;\n  }\n  .am-u-lg-push-11 {\n    left: 91.66666667%;\n  }\n  .am-u-lg-offset-0 {\n    margin-left: 0;\n  }\n  .am-u-lg-offset-1 {\n    margin-left: 8.33333333%;\n  }\n  .am-u-lg-offset-2 {\n    margin-left: 16.66666667%;\n  }\n  .am-u-lg-offset-3 {\n    margin-left: 25%;\n  }\n  .am-u-lg-offset-4 {\n    margin-left: 33.33333333%;\n  }\n  .am-u-lg-offset-5 {\n    margin-left: 41.66666667%;\n  }\n  .am-u-lg-offset-6 {\n    margin-left: 50%;\n  }\n  .am-u-lg-offset-7 {\n    margin-left: 58.33333333%;\n  }\n  .am-u-lg-offset-8 {\n    margin-left: 66.66666667%;\n  }\n  .am-u-lg-offset-9 {\n    margin-left: 75%;\n  }\n  .am-u-lg-offset-10 {\n    margin-left: 83.33333333%;\n  }\n  .am-u-lg-offset-11 {\n    margin-left: 91.66666667%;\n  }\n  .am-u-lg-reset-order {\n    margin-left: 0;\n    margin-right: 0;\n    left: auto;\n    right: auto;\n    float: left;\n  }\n  [class*=\"am-u-\"].am-u-lg-centered {\n    margin-left: auto;\n    margin-right: auto;\n    float: none;\n  }\n  [class*=\"am-u-\"].am-u-lg-centered:last-child {\n    float: none;\n  }\n  [class*=\"am-u-\"].am-u-lg-uncentered {\n    margin-left: 0;\n    margin-right: 0;\n    float: left;\n  }\n  [class*=\"am-u-\"].am-u-lg-uncentered:last-child {\n    float: left;\n  }\n}\n/* ==========================================================================\n   Component: AVG Grid\n ============================================================================ */\n[class*=\"am-avg-\"] {\n  display: block;\n  padding: 0;\n  margin: 0;\n  list-style: none;\n}\n[class*=\"am-avg-\"]:before,\n[class*=\"am-avg-\"]:after {\n  content: \" \";\n  display: table;\n}\n[class*=\"am-avg-\"]:after {\n  clear: both;\n}\n[class*=\"am-avg-\"] > li {\n  display: block;\n  height: auto;\n  float: left;\n}\n@media only screen {\n  .am-avg-sm-1 > li {\n    width: 100%;\n  }\n  .am-avg-sm-1 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-1 > li:nth-of-type(1n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-2 > li {\n    width: 50%;\n  }\n  .am-avg-sm-2 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-2 > li:nth-of-type(2n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-3 > li {\n    width: 33.33333333%;\n  }\n  .am-avg-sm-3 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-3 > li:nth-of-type(3n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-4 > li {\n    width: 25%;\n  }\n  .am-avg-sm-4 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-4 > li:nth-of-type(4n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-5 > li {\n    width: 20%;\n  }\n  .am-avg-sm-5 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-5 > li:nth-of-type(5n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-6 > li {\n    width: 16.66666667%;\n  }\n  .am-avg-sm-6 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-6 > li:nth-of-type(6n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-7 > li {\n    width: 14.28571429%;\n  }\n  .am-avg-sm-7 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-7 > li:nth-of-type(7n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-8 > li {\n    width: 12.5%;\n  }\n  .am-avg-sm-8 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-8 > li:nth-of-type(8n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-9 > li {\n    width: 11.11111111%;\n  }\n  .am-avg-sm-9 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-9 > li:nth-of-type(9n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-10 > li {\n    width: 10%;\n  }\n  .am-avg-sm-10 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-10 > li:nth-of-type(10n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-11 > li {\n    width: 9.09090909%;\n  }\n  .am-avg-sm-11 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-11 > li:nth-of-type(11n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-12 > li {\n    width: 8.33333333%;\n  }\n  .am-avg-sm-12 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-12 > li:nth-of-type(12n + 1) {\n    clear: both;\n  }\n}\n@media only screen and (min-width:641px) {\n  .am-avg-md-1 > li {\n    width: 100%;\n  }\n  .am-avg-md-1 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-1 > li:nth-of-type(1n + 1) {\n    clear: both;\n  }\n  .am-avg-md-2 > li {\n    width: 50%;\n  }\n  .am-avg-md-2 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-2 > li:nth-of-type(2n + 1) {\n    clear: both;\n  }\n  .am-avg-md-3 > li {\n    width: 33.33333333%;\n  }\n  .am-avg-md-3 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-3 > li:nth-of-type(3n + 1) {\n    clear: both;\n  }\n  .am-avg-md-4 > li {\n    width: 25%;\n  }\n  .am-avg-md-4 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-4 > li:nth-of-type(4n + 1) {\n    clear: both;\n  }\n  .am-avg-md-5 > li {\n    width: 20%;\n  }\n  .am-avg-md-5 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-5 > li:nth-of-type(5n + 1) {\n    clear: both;\n  }\n  .am-avg-md-6 > li {\n    width: 16.66666667%;\n  }\n  .am-avg-md-6 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-6 > li:nth-of-type(6n + 1) {\n    clear: both;\n  }\n  .am-avg-md-7 > li {\n    width: 14.28571429%;\n  }\n  .am-avg-md-7 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-7 > li:nth-of-type(7n + 1) {\n    clear: both;\n  }\n  .am-avg-md-8 > li {\n    width: 12.5%;\n  }\n  .am-avg-md-8 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-8 > li:nth-of-type(8n + 1) {\n    clear: both;\n  }\n  .am-avg-md-9 > li {\n    width: 11.11111111%;\n  }\n  .am-avg-md-9 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-9 > li:nth-of-type(9n + 1) {\n    clear: both;\n  }\n  .am-avg-md-10 > li {\n    width: 10%;\n  }\n  .am-avg-md-10 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-10 > li:nth-of-type(10n + 1) {\n    clear: both;\n  }\n  .am-avg-md-11 > li {\n    width: 9.09090909%;\n  }\n  .am-avg-md-11 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-11 > li:nth-of-type(11n + 1) {\n    clear: both;\n  }\n  .am-avg-md-12 > li {\n    width: 8.33333333%;\n  }\n  .am-avg-md-12 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-12 > li:nth-of-type(12n + 1) {\n    clear: both;\n  }\n}\n@media only screen and (min-width:1025px) {\n  .am-avg-lg-1 > li {\n    width: 100%;\n  }\n  .am-avg-lg-1 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-1 > li:nth-of-type(1n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-2 > li {\n    width: 50%;\n  }\n  .am-avg-lg-2 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-2 > li:nth-of-type(2n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-3 > li {\n    width: 33.33333333%;\n  }\n  .am-avg-lg-3 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-3 > li:nth-of-type(3n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-4 > li {\n    width: 25%;\n  }\n  .am-avg-lg-4 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-4 > li:nth-of-type(4n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-5 > li {\n    width: 20%;\n  }\n  .am-avg-lg-5 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-5 > li:nth-of-type(5n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-6 > li {\n    width: 16.66666667%;\n  }\n  .am-avg-lg-6 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-6 > li:nth-of-type(6n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-7 > li {\n    width: 14.28571429%;\n  }\n  .am-avg-lg-7 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-7 > li:nth-of-type(7n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-8 > li {\n    width: 12.5%;\n  }\n  .am-avg-lg-8 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-8 > li:nth-of-type(8n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-9 > li {\n    width: 11.11111111%;\n  }\n  .am-avg-lg-9 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-9 > li:nth-of-type(9n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-10 > li {\n    width: 10%;\n  }\n  .am-avg-lg-10 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-10 > li:nth-of-type(10n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-11 > li {\n    width: 9.09090909%;\n  }\n  .am-avg-lg-11 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-11 > li:nth-of-type(11n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-12 > li {\n    width: 8.33333333%;\n  }\n  .am-avg-lg-12 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-12 > li:nth-of-type(12n + 1) {\n    clear: both;\n  }\n}\n/* ==========================================================================\n   Component: Code\n ============================================================================ */\n/* Inline and block code styles */\ncode,\nkbd,\npre,\nsamp {\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", \"FontAwesome\", monospace;\n}\n/* Inline code */\ncode {\n  padding: 2px 4px;\n  font-size: 1.3rem;\n  color: #c7254e;\n  background-color: #f8f8f8;\n  white-space: nowrap;\n  border-radius: 0;\n}\n/* Code block */\npre {\n  display: block;\n  padding: 1rem;\n  margin: 1rem  0;\n  font-size: 1.3rem;\n  line-height: 1.6;\n  word-break: break-all;\n  word-wrap: break-word;\n  color: #555555;\n  background-color: #f8f8f8;\n  border: 1px solid #dedede;\n  border-radius: 0;\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/* Enable scrollable blocks of code */\n.am-pre-scrollable {\n  max-height: 24rem;\n  overflow-y: scroll;\n}\n/* ==========================================================================\n   Component: Button\n ============================================================================ */\n.am-btn {\n  display: inline-block;\n  margin-bottom: 0;\n  padding: 0.5em 1em;\n  vertical-align: middle;\n  font-size: 1.6rem;\n  font-weight: normal;\n  line-height: 1.2;\n  text-align: center;\n  white-space: nowrap;\n  background-image: none;\n  border: 1px solid transparent;\n  border-radius: 0;\n  cursor: pointer;\n  outline: none;\n  -webkit-appearance: none;\n  -webkit-user-select: none;\n     -moz-user-select: none;\n      -ms-user-select: none;\n          user-select: none;\n  -webkit-transition: background-color 300ms ease-out, border-color 300ms ease-out;\n  transition: background-color 300ms ease-out, border-color 300ms ease-out;\n}\n.am-btn:focus,\n.am-btn:active:focus {\n  outline: thin dotted;\n  outline: 1px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n.am-btn:hover,\n.am-btn:focus {\n  color: #444;\n  text-decoration: none;\n}\n.am-btn:active,\n.am-btn.am-active {\n  background-image: none;\n  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.15);\n}\n.am-btn.am-disabled,\n.am-btn[disabled],\nfieldset[disabled] .am-btn {\n  pointer-events: none;\n  border-color: transparent;\n  cursor: not-allowed;\n  opacity: 0.45;\n  -webkit-box-shadow: none;\n          box-shadow: none;\n}\n.am-btn.am-round {\n  border-radius: 1000px;\n}\n.am-btn.am-radius {\n  border-radius: 2px;\n}\n.am-btn-default {\n  color: #444;\n  background-color: #e6e6e6;\n  border-color: #e6e6e6;\n}\na.am-btn-default:visited {\n  color: #444;\n}\n.am-btn-default:hover,\n.am-btn-default:focus,\n.am-btn-default:active,\n.am-btn-default.am-active,\n.am-active .am-btn-default.am-dropdown-toggle {\n  color: #444;\n  border-color: #c7c7c7;\n}\n.am-btn-default:hover,\n.am-btn-default:focus {\n  background-color: #d4d4d4;\n}\n.am-btn-default:active,\n.am-btn-default.am-active,\n.am-active .am-btn-default.am-dropdown-toggle {\n  background-image: none;\n  background-color: #c2c2c2;\n}\n.am-btn-default.am-disabled,\n.am-btn-default[disabled],\nfieldset[disabled] .am-btn-default,\n.am-btn-default.am-disabled:hover,\n.am-btn-default[disabled]:hover,\nfieldset[disabled] .am-btn-default:hover,\n.am-btn-default.am-disabled:focus,\n.am-btn-default[disabled]:focus,\nfieldset[disabled] .am-btn-default:focus,\n.am-btn-default.am-disabled:active,\n.am-btn-default[disabled]:active,\nfieldset[disabled] .am-btn-default:active,\n.am-btn-default.am-disabled.am-active,\n.am-btn-default[disabled].am-active,\nfieldset[disabled] .am-btn-default.am-active {\n  background-color: #e6e6e6;\n  border-color: #e6e6e6;\n}\n.am-btn-group .am-btn-default,\n.am-btn-group-stacked .am-btn-default {\n  border-color: #d9d9d9;\n}\n.am-btn-primary {\n  color: #fff;\n  background-color: #0e90d2;\n  border-color: #0e90d2;\n}\na.am-btn-primary:visited {\n  color: #fff;\n}\n.am-btn-primary:hover,\n.am-btn-primary:focus,\n.am-btn-primary:active,\n.am-btn-primary.am-active,\n.am-active .am-btn-primary.am-dropdown-toggle {\n  color: #fff;\n  border-color: #0a6999;\n}\n.am-btn-primary:hover,\n.am-btn-primary:focus {\n  background-color: #0c79b1;\n}\n.am-btn-primary:active,\n.am-btn-primary.am-active,\n.am-active .am-btn-primary.am-dropdown-toggle {\n  background-image: none;\n  background-color: #0a628f;\n}\n.am-btn-primary.am-disabled,\n.am-btn-primary[disabled],\nfieldset[disabled] .am-btn-primary,\n.am-btn-primary.am-disabled:hover,\n.am-btn-primary[disabled]:hover,\nfieldset[disabled] .am-btn-primary:hover,\n.am-btn-primary.am-disabled:focus,\n.am-btn-primary[disabled]:focus,\nfieldset[disabled] .am-btn-primary:focus,\n.am-btn-primary.am-disabled:active,\n.am-btn-primary[disabled]:active,\nfieldset[disabled] .am-btn-primary:active,\n.am-btn-primary.am-disabled.am-active,\n.am-btn-primary[disabled].am-active,\nfieldset[disabled] .am-btn-primary.am-active {\n  background-color: #0e90d2;\n  border-color: #0e90d2;\n}\n.am-btn-group .am-btn-primary,\n.am-btn-group-stacked .am-btn-primary {\n  border-color: #0c80ba;\n}\n.am-btn-warning {\n  color: #fff;\n  background-color: #F37B1D;\n  border-color: #F37B1D;\n}\na.am-btn-warning:visited {\n  color: #fff;\n}\n.am-btn-warning:hover,\n.am-btn-warning:focus,\n.am-btn-warning:active,\n.am-btn-warning.am-active,\n.am-active .am-btn-warning.am-dropdown-toggle {\n  color: #fff;\n  border-color: #c85e0b;\n}\n.am-btn-warning:hover,\n.am-btn-warning:focus {\n  background-color: #e0690c;\n}\n.am-btn-warning:active,\n.am-btn-warning.am-active,\n.am-active .am-btn-warning.am-dropdown-toggle {\n  background-image: none;\n  background-color: #be590a;\n}\n.am-btn-warning.am-disabled,\n.am-btn-warning[disabled],\nfieldset[disabled] .am-btn-warning,\n.am-btn-warning.am-disabled:hover,\n.am-btn-warning[disabled]:hover,\nfieldset[disabled] .am-btn-warning:hover,\n.am-btn-warning.am-disabled:focus,\n.am-btn-warning[disabled]:focus,\nfieldset[disabled] .am-btn-warning:focus,\n.am-btn-warning.am-disabled:active,\n.am-btn-warning[disabled]:active,\nfieldset[disabled] .am-btn-warning:active,\n.am-btn-warning.am-disabled.am-active,\n.am-btn-warning[disabled].am-active,\nfieldset[disabled] .am-btn-warning.am-active {\n  background-color: #F37B1D;\n  border-color: #F37B1D;\n}\n.am-btn-group .am-btn-warning,\n.am-btn-group-stacked .am-btn-warning {\n  border-color: #ea6e0c;\n}\n.am-btn-danger {\n  color: #fff;\n  background-color: #dd514c;\n  border-color: #dd514c;\n}\na.am-btn-danger:visited {\n  color: #fff;\n}\n.am-btn-danger:hover,\n.am-btn-danger:focus,\n.am-btn-danger:active,\n.am-btn-danger.am-active,\n.am-active .am-btn-danger.am-dropdown-toggle {\n  color: #fff;\n  border-color: #c62b26;\n}\n.am-btn-danger:hover,\n.am-btn-danger:focus {\n  background-color: #d7342e;\n}\n.am-btn-danger:active,\n.am-btn-danger.am-active,\n.am-active .am-btn-danger.am-dropdown-toggle {\n  background-image: none;\n  background-color: #be2924;\n}\n.am-btn-danger.am-disabled,\n.am-btn-danger[disabled],\nfieldset[disabled] .am-btn-danger,\n.am-btn-danger.am-disabled:hover,\n.am-btn-danger[disabled]:hover,\nfieldset[disabled] .am-btn-danger:hover,\n.am-btn-danger.am-disabled:focus,\n.am-btn-danger[disabled]:focus,\nfieldset[disabled] .am-btn-danger:focus,\n.am-btn-danger.am-disabled:active,\n.am-btn-danger[disabled]:active,\nfieldset[disabled] .am-btn-danger:active,\n.am-btn-danger.am-disabled.am-active,\n.am-btn-danger[disabled].am-active,\nfieldset[disabled] .am-btn-danger.am-active {\n  background-color: #dd514c;\n  border-color: #dd514c;\n}\n.am-btn-group .am-btn-danger,\n.am-btn-group-stacked .am-btn-danger {\n  border-color: #d93c37;\n}\n.am-btn-success {\n  color: #fff;\n  background-color: #5eb95e;\n  border-color: #5eb95e;\n}\na.am-btn-success:visited {\n  color: #fff;\n}\n.am-btn-success:hover,\n.am-btn-success:focus,\n.am-btn-success:active,\n.am-btn-success.am-active,\n.am-active .am-btn-success.am-dropdown-toggle {\n  color: #fff;\n  border-color: #429842;\n}\n.am-btn-success:hover,\n.am-btn-success:focus {\n  background-color: #4aaa4a;\n}\n.am-btn-success:active,\n.am-btn-success.am-active,\n.am-active .am-btn-success.am-dropdown-toggle {\n  background-image: none;\n  background-color: #3f913f;\n}\n.am-btn-success.am-disabled,\n.am-btn-success[disabled],\nfieldset[disabled] .am-btn-success,\n.am-btn-success.am-disabled:hover,\n.am-btn-success[disabled]:hover,\nfieldset[disabled] .am-btn-success:hover,\n.am-btn-success.am-disabled:focus,\n.am-btn-success[disabled]:focus,\nfieldset[disabled] .am-btn-success:focus,\n.am-btn-success.am-disabled:active,\n.am-btn-success[disabled]:active,\nfieldset[disabled] .am-btn-success:active,\n.am-btn-success.am-disabled.am-active,\n.am-btn-success[disabled].am-active,\nfieldset[disabled] .am-btn-success.am-active {\n  background-color: #5eb95e;\n  border-color: #5eb95e;\n}\n.am-btn-group .am-btn-success,\n.am-btn-group-stacked .am-btn-success {\n  border-color: #4db14d;\n}\n.am-btn-secondary {\n  color: #fff;\n  background-color: #3bb4f2;\n  border-color: #3bb4f2;\n}\na.am-btn-secondary:visited {\n  color: #fff;\n}\n.am-btn-secondary:hover,\n.am-btn-secondary:focus,\n.am-btn-secondary:active,\n.am-btn-secondary.am-active,\n.am-active .am-btn-secondary.am-dropdown-toggle {\n  color: #fff;\n  border-color: #0f9ae0;\n}\n.am-btn-secondary:hover,\n.am-btn-secondary:focus {\n  background-color: #19a7f0;\n}\n.am-btn-secondary:active,\n.am-btn-secondary.am-active,\n.am-active .am-btn-secondary.am-dropdown-toggle {\n  background-image: none;\n  background-color: #0e93d7;\n}\n.am-btn-secondary.am-disabled,\n.am-btn-secondary[disabled],\nfieldset[disabled] .am-btn-secondary,\n.am-btn-secondary.am-disabled:hover,\n.am-btn-secondary[disabled]:hover,\nfieldset[disabled] .am-btn-secondary:hover,\n.am-btn-secondary.am-disabled:focus,\n.am-btn-secondary[disabled]:focus,\nfieldset[disabled] .am-btn-secondary:focus,\n.am-btn-secondary.am-disabled:active,\n.am-btn-secondary[disabled]:active,\nfieldset[disabled] .am-btn-secondary:active,\n.am-btn-secondary.am-disabled.am-active,\n.am-btn-secondary[disabled].am-active,\nfieldset[disabled] .am-btn-secondary.am-active {\n  background-color: #3bb4f2;\n  border-color: #3bb4f2;\n}\n.am-btn-group .am-btn-secondary,\n.am-btn-group-stacked .am-btn-secondary {\n  border-color: #23abf0;\n}\n/* Style links like a button */\n.am-btn-link {\n  color: #0e90d2;\n  font-weight: normal;\n  cursor: pointer;\n  border-radius: 0;\n}\n.am-btn-link,\n.am-btn-link:active,\n.am-btn-link[disabled],\nfieldset[disabled] .am-btn-link {\n  background-color: transparent;\n  -webkit-box-shadow: none;\n          box-shadow: none;\n}\n.am-btn-link,\n.am-btn-link:hover,\n.am-btn-link:focus,\n.am-btn-link:active {\n  border-color: transparent;\n}\n.am-btn-link:hover,\n.am-btn-link:focus {\n  color: #095f8a;\n  text-decoration: underline;\n  background-color: transparent;\n}\n.am-btn-link[disabled]:hover,\nfieldset[disabled] .am-btn-link:hover,\n.am-btn-link[disabled]:focus,\nfieldset[disabled] .am-btn-link:focus {\n  color: #999999;\n  text-decoration: none;\n}\n/* button size */\n.am-btn-xs {\n  font-size: 1.2rem;\n}\n.am-btn-sm {\n  font-size: 1.4rem;\n}\n.am-btn-lg {\n  font-size: 1.8rem;\n}\n.am-btn-xl {\n  font-size: 2rem;\n}\n/* Block button  */\n.am-btn-block {\n  display: block;\n  width: 100%;\n  padding-left: 0;\n  padding-right: 0;\n}\n/* Multiple block buttons vertically space */\n.am-btn-block + .am-btn-block {\n  margin-top: 5px;\n}\n/* Specificity overrides */\ninput[type=\"submit\"].am-btn-block,\ninput[type=\"reset\"].am-btn-block,\ninput[type=\"button\"].am-btn-block {\n  width: 100%;\n}\n/* Button with loading spinner */\n.am-btn.am-btn-loading .am-icon-spin {\n  margin-right: 5px;\n}\n/* ==========================================================================\n   Component: Table\n ============================================================================ */\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  empty-cells: show;\n}\ntable code {\n  white-space: normal;\n}\nth {\n  text-align: left;\n}\n.am-table {\n  width: 100%;\n  margin-bottom: 1.6rem;\n  border-spacing: 0;\n  border-collapse: separate;\n}\n.am-table > thead > tr > th,\n.am-table > tbody > tr > th,\n.am-table > tfoot > tr > th,\n.am-table > thead > tr > td,\n.am-table > tbody > tr > td,\n.am-table > tfoot > tr > td {\n  padding: 0.7rem;\n  line-height: 1.6;\n  vertical-align: top;\n  border-top: 1px solid #ddd;\n}\n.am-table > thead > tr > th {\n  vertical-align: bottom;\n  border-bottom: 1px solid #ddd;\n}\n.am-table > caption + thead > tr:first-child > th,\n.am-table > colgroup + thead > tr:first-child > th,\n.am-table > thead:first-child > tr:first-child > th,\n.am-table > caption + thead > tr:first-child > td,\n.am-table > colgroup + thead > tr:first-child > td,\n.am-table > thead:first-child > tr:first-child > td {\n  border-top: 0;\n}\n.am-table > tbody + tbody tr:first-child td {\n  border-top: 2px solid #ddd;\n}\n/* Bordered version */\n.am-table-bordered {\n  border: 1px solid #ddd;\n  border-left: none;\n}\n.am-table-bordered > thead > tr > th,\n.am-table-bordered > tbody > tr > th,\n.am-table-bordered > tfoot > tr > th,\n.am-table-bordered > thead > tr > td,\n.am-table-bordered > tbody > tr > td,\n.am-table-bordered > tfoot > tr > td {\n  border-left: 1px solid #ddd;\n  /*&:first-child {\n          border-left: none;\n        }*/\n}\n.am-table-bordered > tbody > tr:first-child > th,\n.am-table-bordered > tbody > tr:first-child > td {\n  border-top: none;\n}\n.am-table-bordered > thead + tbody > tr:first-child > th,\n.am-table-bordered > thead + tbody > tr:first-child > td {\n  border-top: 1px solid #ddd;\n}\n/* Border-radius version */\n.am-table-radius {\n  border: 1px solid #ddd;\n  border-radius: 2px;\n}\n.am-table-radius > thead > tr:first-child > th:first-child,\n.am-table-radius > thead > tr:first-child > td:first-child {\n  border-top-left-radius: 2px;\n  border-left: none;\n}\n.am-table-radius > thead > tr:first-child > th:last-child,\n.am-table-radius > thead > tr:first-child > td:last-child {\n  border-top-right-radius: 2px;\n  border-right: none;\n}\n.am-table-radius > tbody > tr > th:first-child,\n.am-table-radius > tbody > tr > td:first-child {\n  border-left: none;\n}\n.am-table-radius > tbody > tr > th:last-child,\n.am-table-radius > tbody > tr > td:last-child {\n  border-right: none;\n}\n.am-table-radius > tbody > tr:last-child > th,\n.am-table-radius > tbody > tr:last-child > td {\n  border-bottom: none;\n}\n.am-table-radius > tbody > tr:last-child > th:first-child,\n.am-table-radius > tbody > tr:last-child > td:first-child {\n  border-bottom-left-radius: 2px;\n}\n.am-table-radius > tbody > tr:last-child > th:last-child,\n.am-table-radius > tbody > tr:last-child > td:last-child {\n  border-bottom-right-radius: 2px;\n}\n/* Zebra-striping */\n.am-table-striped > tbody > tr:nth-child(odd) > td,\n.am-table-striped > tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n/* Hover effect */\n.am-table-hover > tbody > tr:hover > td,\n.am-table-hover > tbody > tr:hover > th {\n  background-color: #e9e9e9;\n}\n.am-table-compact > thead > tr > th,\n.am-table-compact > tbody > tr > th,\n.am-table-compact > tfoot > tr > th,\n.am-table-compact > thead > tr > td,\n.am-table-compact > tbody > tr > td,\n.am-table-compact > tfoot > tr > td {\n  padding: 0.4rem;\n}\n.am-table-centered > thead > tr > th,\n.am-table-centered > tbody > tr > th,\n.am-table-centered > tfoot > tr > th,\n.am-table-centered > thead > tr > td,\n.am-table-centered > tbody > tr > td,\n.am-table-centered > tfoot > tr > td {\n  text-align: center;\n}\n.am-table > thead > tr > td.am-active,\n.am-table > tbody > tr > td.am-active,\n.am-table > tfoot > tr > td.am-active,\n.am-table > thead > tr > th.am-active,\n.am-table > tbody > tr > th.am-active,\n.am-table > tfoot > tr > th.am-active,\n.am-table > thead > tr.am-active > td,\n.am-table > tbody > tr.am-active > td,\n.am-table > tfoot > tr.am-active > td,\n.am-table > thead > tr.am-active > th,\n.am-table > tbody > tr.am-active > th,\n.am-table > tfoot > tr.am-active > th {\n  background-color: #ffd;\n}\n.am-table > thead > tr > td.am-disabled,\n.am-table > tbody > tr > td.am-disabled,\n.am-table > tfoot > tr > td.am-disabled,\n.am-table > thead > tr > th.am-disabled,\n.am-table > tbody > tr > th.am-disabled,\n.am-table > tfoot > tr > th.am-disabled,\n.am-table > thead > tr.am-disabled > td,\n.am-table > tbody > tr.am-disabled > td,\n.am-table > tfoot > tr.am-disabled > td,\n.am-table > thead > tr.am-disabled > th,\n.am-table > tbody > tr.am-disabled > th,\n.am-table > tfoot > tr.am-disabled > th {\n  color: #999999;\n}\n.am-table > thead > tr > td.am-primary,\n.am-table > tbody > tr > td.am-primary,\n.am-table > tfoot > tr > td.am-primary,\n.am-table > thead > tr > th.am-primary,\n.am-table > tbody > tr > th.am-primary,\n.am-table > tfoot > tr > th.am-primary,\n.am-table > thead > tr.am-primary > td,\n.am-table > tbody > tr.am-primary > td,\n.am-table > tfoot > tr.am-primary > td,\n.am-table > thead > tr.am-primary > th,\n.am-table > tbody > tr.am-primary > th,\n.am-table > tfoot > tr.am-primary > th {\n  color: #0b76ac;\n  background-color: rgba(14, 144, 210, 0.115);\n}\n.am-table > thead > tr > td.am-success,\n.am-table > tbody > tr > td.am-success,\n.am-table > tfoot > tr > td.am-success,\n.am-table > thead > tr > th.am-success,\n.am-table > tbody > tr > th.am-success,\n.am-table > tfoot > tr > th.am-success,\n.am-table > thead > tr.am-success > td,\n.am-table > tbody > tr.am-success > td,\n.am-table > tfoot > tr.am-success > td,\n.am-table > thead > tr.am-success > th,\n.am-table > tbody > tr.am-success > th,\n.am-table > tfoot > tr.am-success > th {\n  color: #5eb95e;\n  background-color: rgba(94, 185, 94, 0.115);\n}\n.am-table > thead > tr > td.am-warning,\n.am-table > tbody > tr > td.am-warning,\n.am-table > tfoot > tr > td.am-warning,\n.am-table > thead > tr > th.am-warning,\n.am-table > tbody > tr > th.am-warning,\n.am-table > tfoot > tr > th.am-warning,\n.am-table > thead > tr.am-warning > td,\n.am-table > tbody > tr.am-warning > td,\n.am-table > tfoot > tr.am-warning > td,\n.am-table > thead > tr.am-warning > th,\n.am-table > tbody > tr.am-warning > th,\n.am-table > tfoot > tr.am-warning > th {\n  color: #F37B1D;\n  background-color: rgba(243, 123, 29, 0.115);\n}\n.am-table > thead > tr > td.am-danger,\n.am-table > tbody > tr > td.am-danger,\n.am-table > tfoot > tr > td.am-danger,\n.am-table > thead > tr > th.am-danger,\n.am-table > tbody > tr > th.am-danger,\n.am-table > tfoot > tr > th.am-danger,\n.am-table > thead > tr.am-danger > td,\n.am-table > tbody > tr.am-danger > td,\n.am-table > tfoot > tr.am-danger > td,\n.am-table > thead > tr.am-danger > th,\n.am-table > tbody > tr.am-danger > th,\n.am-table > tfoot > tr.am-danger > th {\n  color: #dd514c;\n  background-color: rgba(221, 81, 76, 0.115);\n}\n/* ==========================================================================\n   Component: Form\n ============================================================================ */\n/* Normalize */\nfieldset {\n  border: none;\n}\nlegend {\n  display: block;\n  width: 100%;\n  margin-bottom: 2rem;\n  font-size: 2rem;\n  line-height: inherit;\n  color: #333333;\n  border-bottom: 1px solid #e5e5e5;\n  padding-bottom: 0.5rem;\n}\nlabel {\n  display: inline-block;\n  margin-bottom: 5px;\n  font-weight: bold;\n}\ninput[type=\"search\"] {\n  -webkit-box-sizing: border-box;\n          box-sizing: border-box;\n}\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  /* IE8-9 */\n  line-height: normal;\n}\ninput[type=\"file\"] {\n  display: block;\n}\nselect[multiple],\nselect[size] {\n  height: auto;\n}\nselect optgroup {\n  font-size: inherit;\n  font-style: inherit;\n  font-family: inherit;\n}\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted;\n  outline: 1px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\ninput[type=\"number\"]::-webkit-outer-spin-button,\ninput[type=\"number\"]::-webkit-inner-spin-button {\n  height: auto;\n}\noutput {\n  display: block;\n  padding-top: 1.6rem;\n  font-size: 1.6rem;\n  line-height: 1.6;\n  color: #555555;\n  vertical-align: middle;\n}\n/* Common form controls */\n.am-form select,\n.am-form textarea,\n.am-form input[type=\"text\"],\n.am-form input[type=\"password\"],\n.am-form input[type=\"datetime\"],\n.am-form input[type=\"datetime-local\"],\n.am-form input[type=\"date\"],\n.am-form input[type=\"month\"],\n.am-form input[type=\"time\"],\n.am-form input[type=\"week\"],\n.am-form input[type=\"number\"],\n.am-form input[type=\"email\"],\n.am-form input[type=\"url\"],\n.am-form input[type=\"search\"],\n.am-form input[type=\"tel\"],\n.am-form input[type=\"color\"],\n.am-form-field {\n  display: block;\n  width: 100%;\n  padding: 0.5em;\n  font-size: 1.6rem;\n  line-height: 1.2;\n  color: #555555;\n  vertical-align: middle;\n  background-color: #fff;\n  background-image: none;\n  border: 1px solid #ccc;\n  border-radius: 0;\n  -webkit-appearance: none;\n  -webkit-transition: border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;\n  transition: border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;\n  transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n  transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;\n}\n.am-form select:focus,\n.am-form textarea:focus,\n.am-form input[type=\"text\"]:focus,\n.am-form input[type=\"password\"]:focus,\n.am-form input[type=\"datetime\"]:focus,\n.am-form input[type=\"datetime-local\"]:focus,\n.am-form input[type=\"date\"]:focus,\n.am-form input[type=\"month\"]:focus,\n.am-form input[type=\"time\"]:focus,\n.am-form input[type=\"week\"]:focus,\n.am-form input[type=\"number\"]:focus,\n.am-form input[type=\"email\"]:focus,\n.am-form input[type=\"url\"]:focus,\n.am-form input[type=\"search\"]:focus,\n.am-form input[type=\"tel\"]:focus,\n.am-form input[type=\"color\"]:focus,\n.am-form-field:focus {\n  outline: 0;\n}\n.am-form select:focus,\n.am-form textarea:focus,\n.am-form input[type=\"text\"]:focus,\n.am-form input[type=\"password\"]:focus,\n.am-form input[type=\"datetime\"]:focus,\n.am-form input[type=\"datetime-local\"]:focus,\n.am-form input[type=\"date\"]:focus,\n.am-form input[type=\"month\"]:focus,\n.am-form input[type=\"time\"]:focus,\n.am-form input[type=\"week\"]:focus,\n.am-form input[type=\"number\"]:focus,\n.am-form input[type=\"email\"]:focus,\n.am-form input[type=\"url\"]:focus,\n.am-form input[type=\"search\"]:focus,\n.am-form input[type=\"tel\"]:focus,\n.am-form input[type=\"color\"]:focus,\n.am-form-field:focus {\n  background-color: #fefffe;\n  border-color: #3bb4f2;\n  outline: 0;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 5px rgba(59, 180, 242, 0.3);\n          box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 5px rgba(59, 180, 242, 0.3);\n}\n.am-form select::-webkit-input-placeholder,\n.am-form textarea::-webkit-input-placeholder,\n.am-form input[type=\"text\"]::-webkit-input-placeholder,\n.am-form input[type=\"password\"]::-webkit-input-placeholder,\n.am-form input[type=\"datetime\"]::-webkit-input-placeholder,\n.am-form input[type=\"datetime-local\"]::-webkit-input-placeholder,\n.am-form input[type=\"date\"]::-webkit-input-placeholder,\n.am-form input[type=\"month\"]::-webkit-input-placeholder,\n.am-form input[type=\"time\"]::-webkit-input-placeholder,\n.am-form input[type=\"week\"]::-webkit-input-placeholder,\n.am-form input[type=\"number\"]::-webkit-input-placeholder,\n.am-form input[type=\"email\"]::-webkit-input-placeholder,\n.am-form input[type=\"url\"]::-webkit-input-placeholder,\n.am-form input[type=\"search\"]::-webkit-input-placeholder,\n.am-form input[type=\"tel\"]::-webkit-input-placeholder,\n.am-form input[type=\"color\"]::-webkit-input-placeholder,\n.am-form-field::-webkit-input-placeholder {\n  color: #999999;\n}\n.am-form select::-moz-placeholder,\n.am-form textarea::-moz-placeholder,\n.am-form input[type=\"text\"]::-moz-placeholder,\n.am-form input[type=\"password\"]::-moz-placeholder,\n.am-form input[type=\"datetime\"]::-moz-placeholder,\n.am-form input[type=\"datetime-local\"]::-moz-placeholder,\n.am-form input[type=\"date\"]::-moz-placeholder,\n.am-form input[type=\"month\"]::-moz-placeholder,\n.am-form input[type=\"time\"]::-moz-placeholder,\n.am-form input[type=\"week\"]::-moz-placeholder,\n.am-form input[type=\"number\"]::-moz-placeholder,\n.am-form input[type=\"email\"]::-moz-placeholder,\n.am-form input[type=\"url\"]::-moz-placeholder,\n.am-form input[type=\"search\"]::-moz-placeholder,\n.am-form input[type=\"tel\"]::-moz-placeholder,\n.am-form input[type=\"color\"]::-moz-placeholder,\n.am-form-field::-moz-placeholder {\n  color: #999999;\n}\n.am-form select:-ms-input-placeholder,\n.am-form textarea:-ms-input-placeholder,\n.am-form input[type=\"text\"]:-ms-input-placeholder,\n.am-form input[type=\"password\"]:-ms-input-placeholder,\n.am-form input[type=\"datetime\"]:-ms-input-placeholder,\n.am-form input[type=\"datetime-local\"]:-ms-input-placeholder,\n.am-form input[type=\"date\"]:-ms-input-placeholder,\n.am-form input[type=\"month\"]:-ms-input-placeholder,\n.am-form input[type=\"time\"]:-ms-input-placeholder,\n.am-form input[type=\"week\"]:-ms-input-placeholder,\n.am-form input[type=\"number\"]:-ms-input-placeholder,\n.am-form input[type=\"email\"]:-ms-input-placeholder,\n.am-form input[type=\"url\"]:-ms-input-placeholder,\n.am-form input[type=\"search\"]:-ms-input-placeholder,\n.am-form input[type=\"tel\"]:-ms-input-placeholder,\n.am-form input[type=\"color\"]:-ms-input-placeholder,\n.am-form-field:-ms-input-placeholder {\n  color: #999999;\n}\n.am-form select::placeholder,\n.am-form textarea::placeholder,\n.am-form input[type=\"text\"]::placeholder,\n.am-form input[type=\"password\"]::placeholder,\n.am-form input[type=\"datetime\"]::placeholder,\n.am-form input[type=\"datetime-local\"]::placeholder,\n.am-form input[type=\"date\"]::placeholder,\n.am-form input[type=\"month\"]::placeholder,\n.am-form input[type=\"time\"]::placeholder,\n.am-form input[type=\"week\"]::placeholder,\n.am-form input[type=\"number\"]::placeholder,\n.am-form input[type=\"email\"]::placeholder,\n.am-form input[type=\"url\"]::placeholder,\n.am-form input[type=\"search\"]::placeholder,\n.am-form input[type=\"tel\"]::placeholder,\n.am-form input[type=\"color\"]::placeholder,\n.am-form-field::placeholder {\n  color: #999999;\n}\n.am-form select::-moz-placeholder,\n.am-form textarea::-moz-placeholder,\n.am-form input[type=\"text\"]::-moz-placeholder,\n.am-form input[type=\"password\"]::-moz-placeholder,\n.am-form input[type=\"datetime\"]::-moz-placeholder,\n.am-form input[type=\"datetime-local\"]::-moz-placeholder,\n.am-form input[type=\"date\"]::-moz-placeholder,\n.am-form input[type=\"month\"]::-moz-placeholder,\n.am-form input[type=\"time\"]::-moz-placeholder,\n.am-form input[type=\"week\"]::-moz-placeholder,\n.am-form input[type=\"number\"]::-moz-placeholder,\n.am-form input[type=\"email\"]::-moz-placeholder,\n.am-form input[type=\"url\"]::-moz-placeholder,\n.am-form input[type=\"search\"]::-moz-placeholder,\n.am-form input[type=\"tel\"]::-moz-placeholder,\n.am-form input[type=\"color\"]::-moz-placeholder,\n.am-form-field::-moz-placeholder {\n  opacity: 1;\n}\n.am-form select[disabled],\n.am-form textarea[disabled],\n.am-form input[type=\"text\"][disabled],\n.am-form input[type=\"password\"][disabled],\n.am-form input[type=\"datetime\"][disabled],\n.am-form input[type=\"datetime-local\"][disabled],\n.am-form input[type=\"date\"][disabled],\n.am-form input[type=\"month\"][disabled],\n.am-form input[type=\"time\"][disabled],\n.am-form input[type=\"week\"][disabled],\n.am-form input[type=\"number\"][disabled],\n.am-form input[type=\"email\"][disabled],\n.am-form input[type=\"url\"][disabled],\n.am-form input[type=\"search\"][disabled],\n.am-form input[type=\"tel\"][disabled],\n.am-form input[type=\"color\"][disabled],\n.am-form-field[disabled],\n.am-form select[readonly],\n.am-form textarea[readonly],\n.am-form input[type=\"text\"][readonly],\n.am-form input[type=\"password\"][readonly],\n.am-form input[type=\"datetime\"][readonly],\n.am-form input[type=\"datetime-local\"][readonly],\n.am-form input[type=\"date\"][readonly],\n.am-form input[type=\"month\"][readonly],\n.am-form input[type=\"time\"][readonly],\n.am-form input[type=\"week\"][readonly],\n.am-form input[type=\"number\"][readonly],\n.am-form input[type=\"email\"][readonly],\n.am-form input[type=\"url\"][readonly],\n.am-form input[type=\"search\"][readonly],\n.am-form input[type=\"tel\"][readonly],\n.am-form input[type=\"color\"][readonly],\n.am-form-field[readonly],\nfieldset[disabled] .am-form select,\nfieldset[disabled] .am-form textarea,\nfieldset[disabled] .am-form input[type=\"text\"],\nfieldset[disabled] .am-form input[type=\"password\"],\nfieldset[disabled] .am-form input[type=\"datetime\"],\nfieldset[disabled] .am-form input[type=\"datetime-local\"],\nfieldset[disabled] .am-form input[type=\"date\"],\nfieldset[disabled] .am-form input[type=\"month\"],\nfieldset[disabled] .am-form input[type=\"time\"],\nfieldset[disabled] .am-form input[type=\"week\"],\nfieldset[disabled] .am-form input[type=\"number\"],\nfieldset[disabled] .am-form input[type=\"email\"],\nfieldset[disabled] .am-form input[type=\"url\"],\nfieldset[disabled] .am-form input[type=\"search\"],\nfieldset[disabled] .am-form input[type=\"tel\"],\nfieldset[disabled] .am-form input[type=\"color\"],\nfieldset[disabled] .am-form-field {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n.am-form select.am-radius,\n.am-form textarea.am-radius,\n.am-form input[type=\"text\"].am-radius,\n.am-form input[type=\"password\"].am-radius,\n.am-form input[type=\"datetime\"].am-radius,\n.am-form input[type=\"datetime-local\"].am-radius,\n.am-form input[type=\"date\"].am-radius,\n.am-form input[type=\"month\"].am-radius,\n.am-form input[type=\"time\"].am-radius,\n.am-form input[type=\"week\"].am-radius,\n.am-form input[type=\"number\"].am-radius,\n.am-form input[type=\"email\"].am-radius,\n.am-form input[type=\"url\"].am-radius,\n.am-form input[type=\"search\"].am-radius,\n.am-form input[type=\"tel\"].am-radius,\n.am-form input[type=\"color\"].am-radius,\n.am-form-field.am-radius {\n  border-radius: 2px;\n}\n.am-form select.am-round,\n.am-form textarea.am-round,\n.am-form input[type=\"text\"].am-round,\n.am-form input[type=\"password\"].am-round,\n.am-form input[type=\"datetime\"].am-round,\n.am-form input[type=\"datetime-local\"].am-round,\n.am-form input[type=\"date\"].am-round,\n.am-form input[type=\"month\"].am-round,\n.am-form input[type=\"time\"].am-round,\n.am-form input[type=\"week\"].am-round,\n.am-form input[type=\"number\"].am-round,\n.am-form input[type=\"email\"].am-round,\n.am-form input[type=\"url\"].am-round,\n.am-form input[type=\"search\"].am-round,\n.am-form input[type=\"tel\"].am-round,\n.am-form input[type=\"color\"].am-round,\n.am-form-field.am-round {\n  border-radius: 1000px;\n}\n.am-form textarea,\n.am-form select[multiple],\n.am-form select[size] {\n  height: auto;\n}\n.am-form select {\n  -webkit-appearance: none !important;\n  -moz-appearance: none !important;\n  -webkit-border-radius: 0;\n  background: #fff url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgeD0iMTJweCIgeT0iMHB4IiB3aWR0aD0iMjRweCIgaGVpZ2h0PSIzcHgiIHZpZXdCb3g9IjAgMCA2IDMiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDYgMyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PHBvbHlnb24gcG9pbnRzPSI1Ljk5MiwwIDIuOTkyLDMgLTAuMDA4LDAgIi8+PC9zdmc+') no-repeat 100% center;\n}\n.am-form select[multiple=\"multiple\"] {\n  background-image: none;\n}\n/* help text */\n.am-form-help {\n  display: block;\n  margin-top: 5px;\n  margin-bottom: 10px;\n  color: #999999;\n  font-size: 1.3rem;\n}\n/* form group */\n.am-form-group {\n  margin-bottom: 1.5rem;\n}\n/* file field */\n.am-form-file {\n  position: relative;\n  overflow: hidden;\n}\n.am-form-file input[type=\"file\"] {\n  position: absolute;\n  left: 0;\n  top: 0;\n  z-index: 1;\n  width: 100%;\n  opacity: 0;\n  cursor: pointer;\n  font-size: 50rem;\n}\n/**\n * Checkboxes and radios\n * Indent the labels to position radios/checkboxes as hanging controls.\n*/\n.am-radio,\n.am-checkbox {\n  display: block;\n  min-height: 1.92rem;\n  margin-top: 10px;\n  margin-bottom: 10px;\n  padding-left: 20px;\n  vertical-align: middle;\n}\n.am-radio label,\n.am-checkbox label {\n  display: inline;\n  margin-bottom: 0;\n  font-weight: normal;\n  cursor: pointer;\n}\n.am-radio input[type=\"radio\"],\n.am-radio-inline input[type=\"radio\"],\n.am-checkbox input[type=\"checkbox\"],\n.am-checkbox-inline input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n  outline: none;\n}\n.am-radio + .am-radio,\n.am-checkbox + .am-checkbox {\n  margin-top: -5px;\n}\n/* Radios and checkboxes inline */\n.am-radio-inline,\n.am-checkbox-inline {\n  display: inline-block;\n  padding-left: 20px;\n  margin-bottom: 0;\n  vertical-align: middle;\n  font-weight: normal;\n  cursor: pointer;\n}\n.am-radio-inline + .am-radio-inline,\n.am-checkbox-inline + .am-checkbox-inline {\n  margin-top: 0;\n  margin-left: 10px;\n}\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\n.am-radio[disabled],\n.am-radio-inline[disabled],\n.am-checkbox[disabled],\n.am-checkbox-inline[disabled],\nfieldset[disabled] input[type=\"radio\"],\nfieldset[disabled] input[type=\"checkbox\"],\nfieldset[disabled] .am-radio,\nfieldset[disabled] .am-radio-inline,\nfieldset[disabled] .am-checkbox,\nfieldset[disabled] .am-checkbox-inline {\n  cursor: not-allowed;\n}\n/* Form field feedback states */\n.am-form-warning .am-form-help,\n.am-form-warning .am-form-label,\n.am-form-warning .am-radio,\n.am-form-warning .am-checkbox,\n.am-form-warning .am-radio-inline,\n.am-form-warning .am-checkbox-inline,\n.am-form-warning label {\n  color: #F37B1D;\n}\n.am-form-warning [class*=\"icon-\"] {\n  color: #F37B1D;\n}\n.am-form-warning .am-form-field {\n  border-color: #F37B1D !important;\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.am-form-warning .am-form-field:focus {\n  background-color: #fefffe;\n  border-color: #d2620b;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 5px #f8b47e !important;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 5px #f8b47e !important;\n}\n.am-form-error .am-form-help,\n.am-form-error .am-form-label,\n.am-form-error .am-radio,\n.am-form-error .am-checkbox,\n.am-form-error .am-radio-inline,\n.am-form-error .am-checkbox-inline,\n.am-form-error label {\n  color: #dd514c;\n}\n.am-form-error [class*=\"icon-\"] {\n  color: #dd514c;\n}\n.am-form-error .am-form-field,\n.am-field-error {\n  border-color: #dd514c !important;\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.am-form-error .am-form-field:focus,\n.am-field-error:focus {\n  background-color: #fefffe;\n  border-color: #cf2d27;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 5px #eda4a2 !important;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 5px #eda4a2 !important;\n}\n.am-form-success .am-form-help,\n.am-form-success .am-form-label,\n.am-form-success .am-radio,\n.am-form-success .am-checkbox,\n.am-form-success .am-radio-inline,\n.am-form-success .am-checkbox-inline,\n.am-form-success label {\n  color: #5eb95e;\n}\n.am-form-success [class*=\"icon-\"] {\n  color: #5eb95e;\n}\n.am-form-success .am-form-field,\n.am-field-valid {\n  border-color: #5eb95e !important;\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.am-form-success .am-form-field:focus,\n.am-field-valid:focus {\n  background-color: #fefffe;\n  border-color: #459f45;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 5px #a5d8a5 !important;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 5px #a5d8a5 !important;\n}\n/* Horizontal forms */\n.am-form-horizontal .am-form-label,\n.am-form-horizontal .am-radio,\n.am-form-horizontal .am-checkbox,\n.am-form-horizontal .am-radio-inline,\n.am-form-horizontal .am-checkbox-inline {\n  margin-top: 0;\n  margin-bottom: 0;\n  padding-top: 0.6em;\n}\n.am-form-horizontal .am-form-group:before,\n.am-form-horizontal .am-form-group:after {\n  content: \" \";\n  display: table;\n}\n.am-form-horizontal .am-form-group:after {\n  clear: both;\n}\n@media only screen and (min-width:641px) {\n  .am-form-horizontal .am-form-label {\n    text-align: right;\n  }\n}\n/* Inline form elements */\n@media only screen and (min-width:641px) {\n  .am-form-inline .am-form-group {\n    display: inline-block;\n    margin-bottom: 0;\n    vertical-align: middle;\n  }\n  .am-form-inline .am-form-field {\n    display: inline-block;\n    width: auto;\n    vertical-align: middle;\n  }\n  .am-form-inline .am-input-group {\n    display: inline-table;\n    vertical-align: middle;\n  }\n  .am-form-inline .am-input-group .am-input-group-label,\n  .am-form-inline .am-input-group .am-input-group-btn,\n  .am-form-inline .am-input-group .am-form-label {\n    width: auto;\n  }\n  .am-form-inline .am-input-group > .am-form-field {\n    width: 100%;\n  }\n  .am-form-inline .am-form-label {\n    margin-bottom: 0;\n    vertical-align: middle;\n  }\n  .am-form-inline .am-radio,\n  .am-form-inline .am-checkbox {\n    display: inline-block;\n    margin-top: 0;\n    margin-bottom: 0;\n    padding-left: 0;\n    vertical-align: middle;\n  }\n  .am-form-inline .am-radio input[type=\"radio\"],\n  .am-form-inline .am-checkbox input[type=\"checkbox\"] {\n    float: none;\n    margin-left: 0;\n  }\n}\n/* Form field size */\n.am-input-sm {\n  font-size: 1.4rem !important;\n}\n.am-input-lg {\n  font-size: 1.8rem !important;\n}\n.am-form-group-sm .am-checkbox,\n.am-form-group-sm .am-radio,\n.am-form-group-sm .am-form-label,\n.am-form-group-sm .am-form-field {\n  font-size: 1.4rem !important;\n}\n.am-form-group-lg .am-checkbox,\n.am-form-group-lg .am-radio,\n.am-form-group-lg .am-form-label,\n.am-form-group-lg .am-form-field {\n  font-size: 1.8rem !important;\n}\n.am-form-group-lg input[type=\"radio\"],\n.am-form-group-lg input[type=\"checkbox\"] {\n  margin-top: 7px;\n}\n/* Form field feedback states */\n.am-form-icon {\n  position: relative;\n}\n.am-form-icon .am-form-field {\n  padding-left: 1.75em !important;\n}\n.am-form-icon [class*='am-icon-'] {\n  position: absolute;\n  left: 0.5em;\n  top: 50%;\n  display: block;\n  margin-top: -0.5em;\n  line-height: 1;\n  z-index: 2;\n}\n.am-form-icon label ~ [class*='am-icon-'] {\n  top: 70%;\n}\n/* Feedback Icon */\n.am-form-feedback {\n  position: relative;\n}\n.am-form-feedback .am-form-field {\n  padding-left: 0.5em !important;\n  padding-right: 1.75em !important;\n}\n.am-form-feedback [class*='am-icon-'] {\n  right: 0.5em;\n  left: auto;\n}\n.am-form-horizontal .am-form-feedback [class*='am-icon-'] {\n  right: 1.6em;\n}\n/* Form set */\n.am-form-set {\n  margin-bottom: 1.5rem;\n  padding: 0;\n}\n.am-form-set > input {\n  position: relative;\n  top: -1px;\n  border-radius: 0 !important;\n}\n.am-form-set > input:focus {\n  z-index: 2;\n}\n.am-form-set > input:first-child {\n  top: 1px;\n  border-top-right-radius: 0 !important;\n  border-top-left-radius: 0 !important;\n}\n.am-form-set > input:last-child {\n  top: -2px;\n  border-bottom-right-radius: 0 !important;\n  border-bottom-left-radius: 0 !important;\n}\n/* ==========================================================================\n   Component: Image\n ============================================================================ */\n/* Image thumbnails */\n.am-img-thumbnail {\n  display: inline-block;\n  max-width: 100%;\n  height: auto;\n  padding: 2px;\n  line-height: 1.6;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  border-radius: 0;\n  -webkit-transition: all 0.2s ease-in-out;\n  transition: all 0.2s ease-in-out;\n}\n.am-img-thumbnail.am-radius {\n  border-radius: 2px;\n}\n.am-img-responsive {\n  display: block;\n  max-width: 100%;\n  height: auto;\n}\n/* ==========================================================================\n   Component: Nav\n ============================================================================ */\n.am-nav {\n  margin-bottom: 0;\n  padding: 0;\n  list-style: none;\n}\n.am-nav:before,\n.am-nav:after {\n  content: \" \";\n  display: table;\n}\n.am-nav:after {\n  clear: both;\n}\n.am-nav > li {\n  position: relative;\n  display: block;\n}\n.am-nav > li + li {\n  margin-top: 5px;\n}\n.am-nav > li + .am-nav-header {\n  margin-top: 1em;\n}\n.am-nav > li > a {\n  position: relative;\n  display: block;\n  padding: 0.4em 1em;\n  border-radius: 0;\n}\n.am-nav > li > a:hover,\n.am-nav > li > a:focus {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n.am-nav > li.am-active > a,\n.am-nav > li.am-active > a:hover,\n.am-nav > li.am-active > a:focus {\n  color: #fff;\n  background-color: #0e90d2;\n  cursor: default;\n}\n.am-nav > li.am-disabled > a {\n  color: #999999;\n}\n.am-nav > li.am-disabled > a:hover,\n.am-nav > li.am-disabled > a:focus {\n  color: #999999;\n  text-decoration: none;\n  background-color: transparent;\n  cursor: not-allowed;\n}\n.am-nav-header {\n  padding: 0.4em 1em;\n  text-transform: uppercase;\n  font-weight: bold;\n  font-size: 100%;\n  color: #555555;\n}\n.am-nav-divider {\n  margin: 15px 1em !important;\n  border-top: 1px solid #ddd;\n  -webkit-box-shadow: 0 1px 0 #fff;\n          box-shadow: 0 1px 0 #fff;\n}\n.am-nav-pills > li {\n  float: left;\n}\n.am-nav-pills > li + li {\n  margin-left: 5px;\n  margin-top: 0;\n}\n.am-nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n.am-nav-tabs > li {\n  float: left;\n  margin-bottom: -1px;\n}\n.am-nav-tabs > li + li {\n  margin-top: 0;\n}\n.am-nav-tabs > li > a {\n  margin-right: 5px;\n  line-height: 1.6;\n  border: 1px solid transparent;\n  border-radius: 0 0 0 0;\n}\n.am-nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #ddd;\n}\n.am-nav-tabs > li.am-active > a,\n.am-nav-tabs > li.am-active > a:hover,\n.am-nav-tabs > li.am-active > a:focus {\n  color: #555555;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n  cursor: default;\n}\n.am-nav-tabs.am-nav-justify {\n  border-bottom: 0;\n  /*  > li > a {\n      margin-right: 0;\n      border-radius: @global-radius;\n    }\n\n    > .am-active > a {\n      &,\n      &:hover,\n      &:focus {\n        border: 1px solid @nav-tabs-justify-link-border-color;\n      }\n    }*/\n}\n.am-nav-tabs.am-nav-justify > li > a {\n  margin-right: 0;\n  border-bottom: 1px solid #ddd;\n  border-radius: 0 0 0 0;\n}\n.am-nav-tabs.am-nav-justify > .am-active > a,\n.am-nav-tabs.am-nav-justify > .am-active > a:hover,\n.am-nav-tabs.am-nav-justify > .am-active > a:focus {\n  border-bottom-color: #fff;\n}\n.am-nav-justify {\n  width: 100%;\n  display: table;\n}\n.am-nav-justify > li {\n  float: none;\n  display: table-cell;\n  width: 1%;\n}\n.am-nav-justify > li > a {\n  text-align: center;\n  margin-bottom: 0;\n}\n.lte9 .am-nav-justify > li {\n  display: table-cell;\n  width: 1%;\n}\n/* ==========================================================================\n   Component: Topbar\n ============================================================================ */\n.am-topbar {\n  position: relative;\n  min-height: 50px;\n  margin-bottom: 1.6rem;\n  background: #f8f8f8;\n  border-width: 0 0 1px;\n  border-style: solid;\n  border-color: #ddd;\n  color: #666;\n}\n.am-topbar:before,\n.am-topbar:after {\n  content: \" \";\n  display: table;\n}\n.am-topbar:after {\n  clear: both;\n}\n.am-topbar a {\n  color: #666;\n}\n.am-topbar-brand {\n  margin: 0;\n}\n@media only screen and (min-width:641px) {\n  .am-topbar-brand {\n    float: left;\n  }\n}\n.am-topbar-brand a:hover {\n  color: #4d4d4d;\n}\n.am-topbar-collapse {\n  width: 100%;\n  overflow-x: visible;\n  padding: 10px;\n  clear: both;\n  -webkit-overflow-scrolling: touch;\n}\n.am-topbar-collapse:before,\n.am-topbar-collapse:after {\n  content: \" \";\n  display: table;\n}\n.am-topbar-collapse:after {\n  clear: both;\n}\n.am-topbar-collapse.am-in {\n  overflow-y: auto;\n}\n@media only screen and (min-width:641px) {\n  .am-topbar-collapse {\n    margin-top: 0;\n    padding: 0;\n    width: auto;\n    clear: none;\n  }\n  .am-topbar-collapse.am-collapse {\n    display: block !important;\n    height: auto !important;\n    padding: 0;\n    overflow: visible !important;\n  }\n  .am-topbar-collapse.am-in {\n    overflow-y: visible;\n  }\n}\n.am-topbar-brand {\n  padding: 0 10px;\n  float: left;\n  font-size: 1.8rem;\n  height: 50px;\n  line-height: 50px;\n}\n.am-topbar-toggle {\n  position: relative;\n  float: right;\n  margin-right: 10px;\n}\n@media only screen and (min-width:641px) {\n  .am-topbar-toggle {\n    display: none;\n  }\n}\n@media only screen and (max-width: 640px) {\n  .am-topbar-nav {\n    margin-bottom: 8px;\n  }\n  .am-topbar-nav > li {\n    float: none;\n  }\n}\n@media only screen and (max-width: 640px) {\n  .am-topbar-nav > li + li {\n    margin-left: 0;\n    margin-top: 5px;\n  }\n}\n@media only screen and (min-width:641px) {\n  .am-topbar-nav {\n    float: left;\n  }\n  .am-topbar-nav > li > a {\n    position: relative;\n    line-height: 50px;\n    padding: 0 10px;\n  }\n  .am-topbar-nav > li > a:after {\n    position: absolute;\n    left: 50%;\n    margin-left: -7px;\n    bottom: -1px;\n    content: \"\";\n    display: inline-block;\n    width: 0;\n    height: 0;\n    vertical-align: middle;\n    border-bottom: 7px solid #f8f8f8;\n    border-right: 7px solid transparent;\n    border-left: 7px solid transparent;\n    border-top: 0 dotted;\n    -webkit-transform: rotate(360deg);\n        -ms-transform: rotate(360deg);\n            transform: rotate(360deg);\n    opacity: 0;\n    -webkit-transition: opacity .1s;\n    transition: opacity .1s;\n  }\n  .am-topbar-nav > li > a:hover:after {\n    opacity: 1;\n    border-bottom-color: #666;\n  }\n  .am-topbar-nav > li.am-dropdown > a:after {\n    display: none;\n  }\n  .am-topbar-nav > li.am-active > a,\n  .am-topbar-nav > li.am-active > a:hover,\n  .am-topbar-nav > li.am-active > a:focus {\n    border-radius: 0;\n    color: #0e90d2;\n    background: none;\n  }\n  .am-topbar-nav > li.am-active > a:after {\n    opacity: 1;\n    border-bottom-color: #0e90d2;\n  }\n}\n@media only screen and (max-width: 640px) {\n  .am-topbar-collapse .am-dropdown.am-active .am-dropdown-content {\n    float: none;\n    position: relative;\n    width: 100%;\n  }\n}\n@media only screen and (min-width:641px) {\n  .am-topbar-left {\n    float: left;\n  }\n  .am-topbar-right {\n    float: right;\n    margin-right: 10px;\n  }\n}\n@media only screen and (max-width: 640px) {\n  .am-topbar-form .am-form-group {\n    margin-bottom: 5px;\n  }\n}\n@media only screen and (min-width:641px) {\n  .am-topbar-form {\n    padding: 0 10px;\n    margin-top: 8px;\n  }\n  .am-topbar-form .am-form-group + .am-btn {\n    margin-left: 5px;\n  }\n}\n.am-topbar-btn {\n  margin-top: 8px;\n}\n@media only screen and (max-width: 640px) {\n  .am-topbar-collapse .am-topbar-btn,\n  .am-topbar-collapse .am-btn {\n    display: block;\n    width: 100%;\n  }\n}\n.am-topbar-inverse {\n  background-color: #0e90d2;\n  border-color: #0b6fa2;\n  color: #eeeeee;\n}\n.am-topbar-inverse a {\n  color: #eeeeee;\n}\n.am-topbar-inverse .am-topbar-brand a {\n  color: #fff;\n}\n.am-topbar-inverse .am-topbar-brand a:hover,\n.am-topbar-inverse .am-topbar-brand a:focus {\n  color: #fff;\n  background-color: transparent;\n}\n.am-topbar-inverse .am-topbar-nav > li > a {\n  color: #eeeeee;\n}\n.am-topbar-inverse .am-topbar-nav > li > a:hover,\n.am-topbar-inverse .am-topbar-nav > li > a:focus {\n  color: #fff;\n  background-color: rgba(0, 0, 0, 0.05);\n}\n.am-topbar-inverse .am-topbar-nav > li > a:hover:after,\n.am-topbar-inverse .am-topbar-nav > li > a:focus:after {\n  border-bottom-color: #0b6fa2;\n}\n.am-topbar-inverse .am-topbar-nav > li > a:after {\n  border-bottom-color: #0e90d2;\n}\n.am-topbar-inverse .am-topbar-nav > li.am-active > a,\n.am-topbar-inverse .am-topbar-nav > li.am-active > a:hover,\n.am-topbar-inverse .am-topbar-nav > li.am-active > a:focus {\n  color: #fff;\n  background-color: rgba(0, 0, 0, 0.1);\n}\n.am-topbar-inverse .am-topbar-nav > li.am-active > a:after,\n.am-topbar-inverse .am-topbar-nav > li.am-active > a:hover:after,\n.am-topbar-inverse .am-topbar-nav > li.am-active > a:focus:after {\n  border-bottom-color: #fff;\n}\n.am-topbar-inverse .am-topbar-nav > li .disabled > a,\n.am-topbar-inverse .am-topbar-nav > li .disabled > a:hover,\n.am-topbar-inverse .am-topbar-nav > li .disabled > a:focus {\n  color: #444;\n  background-color: transparent;\n}\n.am-topbar-fixed-top,\n.am-topbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1000;\n  -webkit-transform: translate3d(0, 0, 0);\n          transform: translate3d(0, 0, 0);\n}\n.am-topbar-fixed-top {\n  top: 0;\n}\n.am-topbar-fixed-bottom {\n  bottom: 0;\n  margin-bottom: 0;\n  border-width: 1px 0 0;\n}\n.am-with-topbar-fixed-top {\n  padding-top: 51px;\n}\n.am-with-topbar-fixed-bottom {\n  padding-bottom: 51px;\n}\n@media only screen and (max-width: 640px) {\n  .am-topbar-fixed-bottom .am-topbar-collapse {\n    position: absolute;\n    bottom: 100%;\n    margin-bottom: 1px;\n    background-color: #f8f8f8;\n  }\n  .am-topbar-fixed-bottom .am-topbar-collapse .am-dropdown-content:before,\n  .am-topbar-fixed-bottom .am-topbar-collapse .am-dropdown-content:after {\n    display: none;\n  }\n  .am-topbar-fixed-bottom.am-topbar-inverse .am-topbar-collapse {\n    background-color: #0e90d2;\n  }\n}\n/* ==========================================================================\n   Component: Breadcrumb\n ============================================================================ */\n.am-breadcrumb {\n  padding: .7em .5em;\n  margin-bottom: 2rem;\n  list-style: none;\n  background-color: transparent;\n  border-radius: 0;\n  font-size: 85%;\n}\n.am-breadcrumb > li {\n  display: inline-block;\n}\n.am-breadcrumb > li [class*=\"am-icon-\"]:before {\n  color: #999999;\n  margin-right: 5px;\n}\n.am-breadcrumb > li + li:before {\n  content: \"»\\00a0\";\n  padding: 0 8px;\n  color: #ccc;\n}\n.am-breadcrumb > .am-active {\n  color: #999999;\n}\n.am-breadcrumb-slash > li + li:before {\n  content: \"/\\00a0\";\n}\n/* ==========================================================================\n   Component: Pagination\n ============================================================================ */\n.am-pagination {\n  padding-left: 0;\n  margin: 1.5rem 0;\n  list-style: none;\n  color: #999999;\n  text-align: left;\n}\n.am-pagination:before,\n.am-pagination:after {\n  content: \" \";\n  display: table;\n}\n.am-pagination:after {\n  clear: both;\n}\n.am-pagination > li {\n  display: inline-block;\n}\n.am-pagination > li > a,\n.am-pagination > li > span {\n  position: relative;\n  display: block;\n  padding: 0.5em 1em;\n  text-decoration: none;\n  line-height: 1.2;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  border-radius: 0;\n  margin-bottom: 5px;\n  margin-right: 5px;\n}\n.am-pagination > li:last-child > a,\n.am-pagination > li:last-child > span {\n  margin-right: 0;\n}\n.am-pagination > li > a:hover,\n.am-pagination > li > span:hover,\n.am-pagination > li > a:focus,\n.am-pagination > li > span:focus {\n  background-color: #eeeeee;\n}\n.am-pagination > .am-active > a,\n.am-pagination > .am-active > span,\n.am-pagination > .am-active > a:hover,\n.am-pagination > .am-active > span:hover,\n.am-pagination > .am-active > a:focus,\n.am-pagination > .am-active > span:focus {\n  z-index: 2;\n  color: #fff;\n  background-color: #0e90d2;\n  border-color: #0e90d2;\n  cursor: default;\n}\n.am-pagination > .am-disabled > span,\n.am-pagination > .am-disabled > span:hover,\n.am-pagination > .am-disabled > span:focus,\n.am-pagination > .am-disabled > a,\n.am-pagination > .am-disabled > a:hover,\n.am-pagination > .am-disabled > a:focus {\n  color: #999999;\n  background-color: #fff;\n  border-color: #ddd;\n  cursor: not-allowed;\n  pointer-events: none;\n}\n.am-pagination .am-pagination-prev {\n  float: left;\n}\n.am-pagination .am-pagination-prev a {\n  border-radius: 0;\n}\n.am-pagination .am-pagination-next {\n  float: right;\n}\n.am-pagination .am-pagination-next a {\n  border-radius: 0;\n}\n.am-pagination-centered {\n  text-align: center;\n}\n.am-pagination-right {\n  text-align: right;\n}\n/* ==========================================================================\n   Component: Aniamtion\n ============================================================================ */\n[class*=\"am-animation-\"] {\n  -webkit-animation-duration: 0.5s;\n          animation-duration: 0.5s;\n  -webkit-animation-timing-function: ease-out;\n          animation-timing-function: ease-out;\n  -webkit-animation-fill-mode: both;\n          animation-fill-mode: both;\n}\n/* Hide animated element if scrollSpy is used */\n@media screen {\n  .cssanimations [data-am-scrollspy*=\"animation\"] {\n    opacity: 0;\n  }\n}\n/* Fade */\n.am-animation-fade {\n  -webkit-animation-name: am-fade;\n          animation-name: am-fade;\n  -webkit-animation-duration: 0.8s;\n          animation-duration: 0.8s;\n  -webkit-animation-timing-function: linear;\n          animation-timing-function: linear;\n}\n/* Scale */\n.am-animation-scale-up {\n  -webkit-animation-name: am-scale-up;\n          animation-name: am-scale-up;\n}\n.am-animation-scale-down {\n  -webkit-animation-name: am-scale-down;\n          animation-name: am-scale-down;\n}\n/* Slide */\n.am-animation-slide-top {\n  -webkit-animation-name: am-slide-top;\n          animation-name: am-slide-top;\n}\n.am-animation-slide-bottom {\n  -webkit-animation-name: am-slide-bottom;\n          animation-name: am-slide-bottom;\n}\n.am-animation-slide-left {\n  -webkit-animation-name: am-slide-left;\n          animation-name: am-slide-left;\n}\n.am-animation-slide-right {\n  -webkit-animation-name: am-slide-right;\n          animation-name: am-slide-right;\n}\n.am-animation-slide-top-fixed {\n  -webkit-animation-name: am-slide-top-fixed;\n          animation-name: am-slide-top-fixed;\n}\n/* Shake */\n.am-animation-shake {\n  -webkit-animation-name: am-shake;\n          animation-name: am-shake;\n}\n/* Spin */\n.am-animation-spin {\n  -webkit-animation: am-spin 2s infinite linear;\n          animation: am-spin 2s infinite linear;\n}\n/* Spring */\n.am-animation-left-spring {\n  -webkit-animation: am-left-spring 0.3s ease-in-out;\n          animation: am-left-spring 0.3s ease-in-out;\n}\n.am-animation-right-spring {\n  -webkit-animation: am-right-spring 0.3s ease-in-out;\n          animation: am-right-spring 0.3s ease-in-out;\n}\n.am-animation-reverse {\n  -webkit-animation-direction: reverse;\n          animation-direction: reverse;\n}\n.am-animation-paused {\n  -webkit-animation-play-state: paused !important;\n          animation-play-state: paused !important;\n}\n.am-animation-delay-1 {\n  -webkit-animation-delay: 1s;\n          animation-delay: 1s;\n}\n.am-animation-delay-2 {\n  -webkit-animation-delay: 2s;\n          animation-delay: 2s;\n}\n.am-animation-delay-3 {\n  -webkit-animation-delay: 3s;\n          animation-delay: 3s;\n}\n.am-animation-delay-4 {\n  -webkit-animation-delay: 4s;\n          animation-delay: 4s;\n}\n.am-animation-delay-5 {\n  -webkit-animation-delay: 5s;\n          animation-delay: 5s;\n}\n.am-animation-delay-6 {\n  -webkit-animation-delay: 6s;\n          animation-delay: 6s;\n}\n/* Keyframes\n ============================================================================ */\n/* Fade */\n@-webkit-keyframes am-fade {\n  0% {\n    opacity: 0;\n  }\n  100% {\n    opacity: 1;\n  }\n}\n@keyframes am-fade {\n  0% {\n    opacity: 0;\n  }\n  100% {\n    opacity: 1;\n  }\n}\n/* Scale up */\n@-webkit-keyframes am-scale-up {\n  0% {\n    opacity: 0;\n    -webkit-transform: scale(0.2);\n            transform: scale(0.2);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: scale(1);\n            transform: scale(1);\n  }\n}\n@keyframes am-scale-up {\n  0% {\n    opacity: 0;\n    -webkit-transform: scale(0.2);\n            transform: scale(0.2);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: scale(1);\n            transform: scale(1);\n  }\n}\n/* Scale down */\n@-webkit-keyframes am-scale-down {\n  0% {\n    opacity: 0;\n    -webkit-transform: scale(1.8);\n            transform: scale(1.8);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: scale(1);\n            transform: scale(1);\n  }\n}\n@keyframes am-scale-down {\n  0% {\n    opacity: 0;\n    -webkit-transform: scale(1.8);\n            transform: scale(1.8);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: scale(1);\n            transform: scale(1);\n  }\n}\n/* Slide top */\n@-webkit-keyframes am-slide-top {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(-100%);\n            transform: translateY(-100%);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n            transform: translateY(0);\n  }\n}\n@keyframes am-slide-top {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(-100%);\n            transform: translateY(-100%);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n            transform: translateY(0);\n  }\n}\n/* Slide bottom */\n@-webkit-keyframes am-slide-bottom {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(100%);\n            transform: translateY(100%);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n            transform: translateY(0);\n  }\n}\n@keyframes am-slide-bottom {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(100%);\n            transform: translateY(100%);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n            transform: translateY(0);\n  }\n}\n/* Slide left */\n@-webkit-keyframes am-slide-left {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateX(-100%);\n            transform: translateX(-100%);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n}\n@keyframes am-slide-left {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateX(-100%);\n            transform: translateX(-100%);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n}\n/* Slide right */\n@-webkit-keyframes am-slide-right {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateX(100%);\n            transform: translateX(100%);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n}\n@keyframes am-slide-right {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateX(100%);\n            transform: translateX(100%);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n}\n/* Shake */\n@-webkit-keyframes am-shake {\n  0%,\n  100% {\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n  10% {\n    -webkit-transform: translateX(-9px);\n            transform: translateX(-9px);\n  }\n  20% {\n    -webkit-transform: translateX(8px);\n            transform: translateX(8px);\n  }\n  30% {\n    -webkit-transform: translateX(-7px);\n            transform: translateX(-7px);\n  }\n  40% {\n    -webkit-transform: translateX(6px);\n            transform: translateX(6px);\n  }\n  50% {\n    -webkit-transform: translateX(-5px);\n            transform: translateX(-5px);\n  }\n  60% {\n    -webkit-transform: translateX(4px);\n            transform: translateX(4px);\n  }\n  70% {\n    -webkit-transform: translateX(-3px);\n            transform: translateX(-3px);\n  }\n  80% {\n    -webkit-transform: translateX(2px);\n            transform: translateX(2px);\n  }\n  90% {\n    -webkit-transform: translateX(-1px);\n            transform: translateX(-1px);\n  }\n}\n@keyframes am-shake {\n  0%,\n  100% {\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n  10% {\n    -webkit-transform: translateX(-9px);\n            transform: translateX(-9px);\n  }\n  20% {\n    -webkit-transform: translateX(8px);\n            transform: translateX(8px);\n  }\n  30% {\n    -webkit-transform: translateX(-7px);\n            transform: translateX(-7px);\n  }\n  40% {\n    -webkit-transform: translateX(6px);\n            transform: translateX(6px);\n  }\n  50% {\n    -webkit-transform: translateX(-5px);\n            transform: translateX(-5px);\n  }\n  60% {\n    -webkit-transform: translateX(4px);\n            transform: translateX(4px);\n  }\n  70% {\n    -webkit-transform: translateX(-3px);\n            transform: translateX(-3px);\n  }\n  80% {\n    -webkit-transform: translateX(2px);\n            transform: translateX(2px);\n  }\n  90% {\n    -webkit-transform: translateX(-1px);\n            transform: translateX(-1px);\n  }\n}\n/* Slide top fixed */\n@-webkit-keyframes am-slide-top-fixed {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(-10px);\n            transform: translateY(-10px);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n            transform: translateY(0);\n  }\n}\n@keyframes am-slide-top-fixed {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(-10px);\n            transform: translateY(-10px);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n            transform: translateY(0);\n  }\n}\n/* Slide bottom fixed */\n@-webkit-keyframes am-slide-bottom-fixed {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(10px);\n            transform: translateY(10px);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n            transform: translateY(0);\n  }\n}\n@keyframes am-slide-bottom-fixed {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(10px);\n            transform: translateY(10px);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n            transform: translateY(0);\n  }\n}\n/* Spin */\n@-webkit-keyframes am-spin {\n  0% {\n    -webkit-transform: rotate(0deg);\n            transform: rotate(0deg);\n  }\n  100% {\n    -webkit-transform: rotate(359deg);\n            transform: rotate(359deg);\n  }\n}\n@keyframes am-spin {\n  0% {\n    -webkit-transform: rotate(0deg);\n            transform: rotate(0deg);\n  }\n  100% {\n    -webkit-transform: rotate(359deg);\n            transform: rotate(359deg);\n  }\n}\n/* Spring */\n@-webkit-keyframes am-right-spring {\n  0% {\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n  50% {\n    -webkit-transform: translateX(-20%);\n            transform: translateX(-20%);\n  }\n  100% {\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n}\n@keyframes am-right-spring {\n  0% {\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n  50% {\n    -webkit-transform: translateX(-20%);\n            transform: translateX(-20%);\n  }\n  100% {\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n}\n@-webkit-keyframes am-left-spring {\n  0% {\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n  50% {\n    -webkit-transform: translateX(20%);\n            transform: translateX(20%);\n  }\n  100% {\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n}\n@keyframes am-left-spring {\n  0% {\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n  50% {\n    -webkit-transform: translateX(20%);\n            transform: translateX(20%);\n  }\n  100% {\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n}\n/* ==========================================================================\n   Component: Article\n ============================================================================ */\n.am-article:before,\n.am-article:after {\n  content: \" \";\n  display: table;\n}\n.am-article:after {\n  clear: both;\n}\n.am-article > :last-child {\n  margin-bottom: 0;\n}\n.am-article + .am-article {\n  margin-top: 2.4rem;\n}\n/* Sub-object `.@{ns}article-title` */\n.am-article-title {\n  font-size: 2.8rem;\n  line-height: 1.15;\n  font-weight: normal;\n}\n.am-article-title a {\n  color: inherit;\n  text-decoration: none;\n}\n/* Sub-object `.@{ns}article-meta` */\n.am-article-meta {\n  font-size: 1.2rem;\n  line-height: 1.5;\n  color: #999999;\n}\n/* Sub-object `.@{ns}article-lead` */\n.am-article-lead {\n  color: #666;\n  font-size: 1.4rem;\n  line-height: 1.5;\n  border: 1px solid #dedede;\n  border-radius: 2px;\n  background: #f9f9f9;\n  padding: 10px;\n}\n/* Sub-object `.@{ns}article-divider` */\n.am-article-divider {\n  margin-bottom: 2.4rem;\n  border-color: #eeeeee;\n}\n* + .am-article-divider {\n  margin-top: 2.4rem;\n}\n/* Sub-object `.@{ns}article-bd` */\n.am-article-bd blockquote {\n  font-family: Georgia, \"Times New Roman\", Times, Kai, \"Kaiti SC\", KaiTi, BiauKai, \"FontAwesome\", serif;\n}\n.am-article-bd img {\n  display: block;\n  max-width: 100%;\n}\n/* ==========================================================================\n   Component: Badge\n ============================================================================ */\n.am-badge {\n  display: inline-block;\n  min-width: 10px;\n  padding: 0.25em 0.625em;\n  font-size: 1.2rem;\n  font-weight: bold;\n  color: #fff;\n  line-height: 1;\n  vertical-align: baseline;\n  white-space: nowrap;\n  text-align: center;\n  background-color: #999999;\n  border-radius: 0;\n}\n.am-badge:empty {\n  display: none;\n}\n.am-badge.am-square {\n  border-radius: 0;\n}\n.am-badge.am-radius {\n  border-radius: 2px;\n}\n.am-badge.am-round {\n  border-radius: 1000px;\n}\na.am-badge:hover,\na.am-badge:focus {\n  color: #fff;\n  text-decoration: none;\n  cursor: pointer;\n}\n.am-badge-primary {\n  background-color: #0e90d2;\n}\n.am-badge-secondary {\n  background-color: #3bb4f2;\n}\n.am-badge-success {\n  background-color: #5eb95e;\n}\n.am-badge-warning {\n  background-color: #F37B1D;\n}\n.am-badge-danger {\n  background-color: #dd514c;\n}\n/* ==========================================================================\n   Component: Comment\n ============================================================================ */\n.am-comment:before,\n.am-comment:after {\n  content: \" \";\n  display: table;\n}\n.am-comment:after {\n  clear: both;\n}\n.am-comment-avatar {\n  float: left;\n  width: 32px;\n  height: 32px;\n  border-radius: 50%;\n  border: 1px solid transparent;\n}\n@media only screen and (min-width:641px) {\n  .am-comment-avatar {\n    width: 48px;\n    height: 48px;\n  }\n}\n.am-comment-main {\n  position: relative;\n  margin-left: 42px;\n  border: 1px solid #dedede;\n  border-radius: 0;\n}\n.am-comment-main:before,\n.am-comment-main:after {\n  position: absolute;\n  top: 10px;\n  left: -8px;\n  right: 100%;\n  width: 0;\n  height: 0;\n  display: block;\n  content: \" \";\n  border-color: transparent;\n  border-style: solid solid outset;\n  border-width: 8px 8px 8px 0;\n  pointer-events: none;\n}\n.am-comment-main:before {\n  border-right-color: #dedede;\n  z-index: 1;\n}\n.am-comment-main:after {\n  border-right-color: #f8f8f8;\n  margin-left: 1px;\n  z-index: 2;\n}\n@media only screen and (min-width:641px) {\n  .am-comment-main {\n    margin-left: 63px;\n  }\n}\n.am-comment-hd {\n  background: #f8f8f8;\n  border-bottom: 1px solid #eee;\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -ms-flexbox;\n  display: flex;\n}\n.am-comment-title {\n  margin: 0 0 8px 0;\n  font-size: 1.6rem;\n  line-height: 1.2;\n}\n.am-comment-meta {\n  -webkit-box-flex: 1;\n  -webkit-flex: 1;\n      -ms-flex: 1;\n          flex: 1;\n  padding: 10px 15px;\n  font-size: 13px;\n  color: #999999;\n  line-height: 1.2;\n  white-space: nowrap;\n  text-overflow: ellipsis;\n  overflow: hidden;\n}\n.am-comment-meta a {\n  color: #999999;\n}\n.am-comment-author {\n  font-weight: bold;\n  color: #999999;\n}\n.am-comment-bd {\n  padding: 15px;\n  overflow: hidden;\n}\n.am-comment-bd > :last-child {\n  margin-bottom: 0;\n}\n.am-comment-footer {\n  padding: 0 15px 5px;\n}\n.am-comment-footer .am-comment-actions a + a {\n  margin-left: 5px;\n}\n.am-comment-actions {\n  font-size: 13px;\n  color: #999999;\n}\n.am-comment-actions a {\n  display: inline-block;\n  padding: 10px 5px;\n  line-height: 1;\n  color: #999999;\n  opacity: .7;\n}\n.am-comment-actions a:hover {\n  color: #0e90d2;\n  opacity: 1;\n}\n.am-comment-hd .am-comment-actions {\n  padding-right: .5rem;\n}\n.am-comment-flip .am-comment-avatar {\n  float: right;\n}\n.am-comment-flip .am-comment-main {\n  margin-left: auto;\n  margin-right: 42px;\n}\n@media only screen and (min-width:641px) {\n  .am-comment-flip .am-comment-main {\n    margin-right: 63px;\n  }\n}\n.am-comment-flip .am-comment-main:before,\n.am-comment-flip .am-comment-main:after {\n  left: auto;\n  right: -8px;\n  border-width: 8px 0 8px 8px;\n}\n.am-comment-flip .am-comment-main:before {\n  border-left-color: #dedede;\n}\n.am-comment-flip .am-comment-main:after {\n  border-left-color: #f8f8f8;\n  margin-right: 1px;\n  margin-left: auto;\n}\n.am-comment-primary .am-comment-avatar {\n  border-color: #0e90d2;\n}\n.am-comment-primary .am-comment-main {\n  border-color: #0e90d2;\n}\n.am-comment-primary .am-comment-main:before {\n  border-right-color: #0e90d2;\n}\n.am-comment-primary.am-comment-flip .am-comment-main:before {\n  border-left-color: #0e90d2;\n  border-right-color: transparent;\n}\n.am-comment-primary.am-comment-flip .am-comment-main:after {\n  border-left-color: #f8f8f8;\n}\n.am-comment-secondary .am-comment-avatar,\n.am-comment-highlight .am-comment-avatar {\n  border-color: #3bb4f2;\n}\n.am-comment-secondary .am-comment-main,\n.am-comment-highlight .am-comment-main {\n  border-color: #3bb4f2;\n}\n.am-comment-secondary .am-comment-main:before,\n.am-comment-highlight .am-comment-main:before {\n  border-right-color: #3bb4f2;\n}\n.am-comment-secondary.am-comment-flip .am-comment-main:before,\n.am-comment-highlight.am-comment-flip .am-comment-main:before {\n  border-left-color: #3bb4f2;\n  border-right-color: transparent;\n}\n.am-comment-secondary.am-comment-flip .am-comment-main:after,\n.am-comment-highlight.am-comment-flip .am-comment-main:after {\n  border-left-color: #f8f8f8;\n}\n.am-comment-success .am-comment-avatar {\n  border-color: #5eb95e;\n}\n.am-comment-success .am-comment-main {\n  border-color: #5eb95e;\n}\n.am-comment-success .am-comment-main:before {\n  border-right-color: #5eb95e;\n}\n.am-comment-success.am-comment-flip .am-comment-main:before {\n  border-left-color: #5eb95e;\n  border-right-color: transparent;\n}\n.am-comment-success.am-comment-flip .am-comment-main:after {\n  border-left-color: #f8f8f8;\n}\n.am-comment-warning .am-comment-avatar {\n  border-color: #F37B1D;\n}\n.am-comment-warning .am-comment-main {\n  border-color: #F37B1D;\n}\n.am-comment-warning .am-comment-main:before {\n  border-right-color: #F37B1D;\n}\n.am-comment-warning.am-comment-flip .am-comment-main:before {\n  border-left-color: #F37B1D;\n  border-right-color: transparent;\n}\n.am-comment-warning.am-comment-flip .am-comment-main:after {\n  border-left-color: #f8f8f8;\n}\n.am-comment-danger .am-comment-avatar {\n  border-color: #dd514c;\n}\n.am-comment-danger .am-comment-main {\n  border-color: #dd514c;\n}\n.am-comment-danger .am-comment-main:before {\n  border-right-color: #dd514c;\n}\n.am-comment-danger.am-comment-flip .am-comment-main:before {\n  border-left-color: #dd514c;\n  border-right-color: transparent;\n}\n.am-comment-danger.am-comment-flip .am-comment-main:after {\n  border-left-color: #f8f8f8;\n}\n.am-comments-list {\n  padding: 0;\n  list-style: none;\n}\n.am-comments-list .am-comment {\n  margin: 1.6rem 0 0 0;\n  list-style: none;\n}\n@media only screen and (min-width:641px) {\n  .am-comments-list-flip .am-comment-main {\n    margin-right: 64px;\n  }\n  .am-comments-list-flip .am-comment-flip .am-comment-main {\n    margin-left: 64px;\n  }\n}\n/* ==========================================================================\n   Component: Button Group\n ============================================================================ */\n.am-btn-group,\n.am-btn-group-stacked {\n  position: relative;\n  display: inline-block;\n  vertical-align: middle;\n}\n.am-btn-group > .am-btn,\n.am-btn-group-stacked > .am-btn {\n  position: relative;\n  float: left;\n}\n.am-btn-group > .am-btn:hover,\n.am-btn-group-stacked > .am-btn:hover,\n.am-btn-group > .am-btn:focus,\n.am-btn-group-stacked > .am-btn:focus,\n.am-btn-group > .am-btn:active,\n.am-btn-group-stacked > .am-btn:active,\n.am-btn-group > .am-btn.active,\n.am-btn-group-stacked > .am-btn.active {\n  z-index: 2;\n}\n.am-btn-group > .am-btn:focus,\n.am-btn-group-stacked > .am-btn:focus {\n  outline: 0;\n}\n.am-btn-group .am-btn + .am-btn,\n.am-btn-group .am-btn + .am-btn-group,\n.am-btn-group .am-btn-group + .am-btn,\n.am-btn-group .am-btn-group + .am-btn-group {\n  margin-left: -1px;\n}\n.am-btn-toolbar {\n  margin-left: -5px;\n}\n.am-btn-toolbar:before,\n.am-btn-toolbar:after {\n  content: \" \";\n  display: table;\n}\n.am-btn-toolbar:after {\n  clear: both;\n}\n.am-btn-toolbar .am-btn-group,\n.am-btn-toolbar .am-input-group {\n  float: left;\n}\n.am-btn-toolbar > .am-btn,\n.am-btn-toolbar > .am-btn-group,\n.am-btn-toolbar > .am-input-group {\n  margin-left: 5px;\n}\n.am-btn-group > .am-btn:not(:first-child):not(:last-child):not(.am-dropdown-toggle) {\n  border-radius: 0;\n}\n.am-btn-group > .am-btn:first-child {\n  margin-left: 0;\n}\n.am-btn-group > .am-btn:first-child:not(:last-child):not(.am-dropdown-toggle) {\n  border-bottom-right-radius: 0;\n  border-top-right-radius: 0;\n}\n.am-btn-group > .am-btn:last-child:not(:first-child),\n.am-btn-group > .am-dropdown-toggle:not(:first-child) {\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n}\n.am-btn-group > .am-btn-group {\n  float: left;\n}\n.am-btn-group > .am-btn-group:not(:first-child):not(:last-child) > .am-btn {\n  border-radius: 0;\n}\n.am-btn-group > .am-btn-group:first-child > .am-btn:last-child,\n.am-btn-group > .am-btn-group:first-child > .am-dropdown-toggle {\n  border-bottom-right-radius: 0;\n  border-top-right-radius: 0;\n}\n.am-btn-group > .am-btn-group:last-child > .am-btn:first-child {\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n}\n.am-btn-group-xs > .am-btn {\n  font-size: 1.2rem;\n}\n.am-btn-group-sm > .am-btn {\n  font-size: 1.4rem;\n}\n.am-btn-group-lg > .am-btn {\n  font-size: 1.8rem;\n}\n.am-btn-group-stacked > .am-btn,\n.am-btn-group-stacked > .am-btn-group,\n.am-btn-group-stacked > .am-btn-group > .am-btn {\n  display: block;\n  float: none;\n  width: 100%;\n  max-width: 100%;\n}\n.am-btn-group-stacked > .am-btn-group:before,\n.am-btn-group-stacked > .am-btn-group:after {\n  content: \" \";\n  display: table;\n}\n.am-btn-group-stacked > .am-btn-group:after {\n  clear: both;\n}\n.am-btn-group-stacked > .am-btn-group > .am-btn {\n  float: none;\n}\n.am-btn-group-stacked > .am-btn + .am-btn,\n.am-btn-group-stacked > .am-btn + .am-btn-group,\n.am-btn-group-stacked > .am-btn-group + .am-btn,\n.am-btn-group-stacked > .am-btn-group + .am-btn-group {\n  margin-top: -1px;\n  margin-left: 0;\n}\n.am-btn-group-stacked > .am-btn:not(:first-child):not(:last-child) {\n  border-radius: 0;\n}\n.am-btn-group-stacked > .am-btn:first-child:not(:last-child) {\n  border-top-right-radius: 0;\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n.am-btn-group-stacked > .am-btn:last-child:not(:first-child) {\n  border-bottom-left-radius: 0;\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n.am-btn-group-stacked > .am-btn-group:not(:first-child):not(:last-child) > .am-btn {\n  border-radius: 0;\n}\n.am-btn-group-stacked > .am-btn-group:first-child:not(:last-child) > .am-btn:last-child,\n.am-btn-group-stacked > .am-btn-group:first-child:not(:last-child) > .am-dropdown-toggle {\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n.am-btn-group-stacked > .am-btn-group:last-child:not(:first-child) > .am-btn:first-child {\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n.am-btn-group-justify {\n  display: table;\n  table-layout: fixed;\n  border-collapse: separate;\n  width: 100%;\n}\n.am-btn-group-justify > .am-btn,\n.am-btn-group-justify > .am-btn-group {\n  float: none;\n  display: table-cell;\n  width: 1%;\n}\n.am-btn-group-justify > .am-btn-group .am-btn {\n  width: 100%;\n}\n.lte9 .am-btn-group-justify {\n  display: table;\n  table-layout: fixed;\n  border-collapse: separate;\n}\n.lte9 .am-btn-group-justify > .am-btn,\n.lte9 .am-btn-group-justify > .am-btn-group {\n  float: none;\n  display: table-cell;\n  width: 1%;\n}\n.am-btn-group .am-dropdown {\n  float: left;\n  margin-left: -1px;\n}\n.am-btn-group .am-dropdown > .am-btn {\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n}\n.am-btn-group .am-active .am-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.am-btn-group .am-active .am-dropdown-toggle.am-btn-link {\n  -webkit-box-shadow: none;\n          box-shadow: none;\n}\n.am-btn-group .am-dropdown-toggle:active,\n.am-btn-group .am-active .am-dropdown-toggle {\n  outline: 0;\n}\n[data-am-button] > .am-btn > input[type=\"radio\"],\n[data-am-button] > .am-btn > input[type=\"checkbox\"],\n.am-btn-group-check > .am-btn > input[type=\"radio\"],\n.am-btn-group-check > .am-btn > input[type=\"checkbox\"] {\n  position: absolute;\n  z-index: -1;\n  opacity: 0;\n}\n/* ==========================================================================\n   Component: Close\n ============================================================================ */\n.am-close {\n  display: inline-block;\n  text-align: center;\n  width: 24px;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 24px;\n  color: #000;\n  text-shadow: 0 1px 0 #fff;\n  opacity: .2;\n  -webkit-transition: all .3s;\n  transition: all .3s;\n}\n.am-close:hover,\n.am-close:focus {\n  color: #000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: .5;\n  outline: none;\n}\n.am-close[class*=\"am-icon-\"] {\n  font-size: 16px;\n}\nbutton.am-close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  /* Needed for Sarari */\n  border: 0;\n  -webkit-appearance: none;\n}\na.am-close:hover {\n  color: inherit;\n  text-decoration: none;\n  cursor: pointer;\n}\n/* Modifiers\n ============================================================================ */\n.am-close-alt {\n  border-radius: 50%;\n  background: #eee;\n  opacity: 0.7;\n  -webkit-box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25);\n          box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25);\n  /* Hover */\n}\n.am-close-alt:hover,\n.am-close-alt:focus {\n  opacity: 1;\n}\n.am-close-spin:hover {\n  -webkit-transform: rotate(360deg);\n      -ms-transform: rotate(360deg);\n          transform: rotate(360deg);\n}\n/* ==========================================================================\n   Component: Icon\n ============================================================================ */\n/* Font-face\n============================================================================= */\n@font-face {\n  font-family: 'FontAwesome';\n  src: url('../fonts/fontawesome-webfont.eot?v=4.5.0');\n  src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.5.0') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff2?v=4.5.0') format('woff2'), url('../fonts/fontawesome-webfont.woff?v=4.5.0') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.5.0') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.5.0#fontawesomeregular') format('svg');\n  font-weight: normal;\n  font-style: normal;\n}\n/* Component\n============================================================================= */\n[class*=\"am-icon-\"] {\n  display: inline-block;\n  font-style: normal;\n}\n[class*=\"am-icon-\"]:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n}\n.am-icon-border {\n  padding: .2em .25em .15em;\n  border: solid 0.08em #eee;\n  border-radius: .1em;\n}\n[class*=\"am-icon-\"].am-fl {\n  margin-right: .3em;\n}\n[class*=\"am-icon-\"].am-fr {\n  margin-left: .3em;\n}\n.am-icon-sm:before {\n  font-size: 150%;\n  vertical-align: -10%;\n}\n.am-icon-md:before {\n  font-size: 200%;\n  vertical-align: -16%;\n}\n.am-icon-lg:before {\n  font-size: 250%;\n  vertical-align: -22%;\n}\n/* Modifier: `.am-icon-btn`\n============================================================================= */\n.am-icon-btn {\n  -webkit-box-sizing: border-box;\n          box-sizing: border-box;\n  display: inline-block;\n  width: 48px;\n  height: 48px;\n  font-size: 24px;\n  line-height: 48px;\n  border-radius: 50%;\n  background-color: #eee;\n  color: #555555;\n  text-align: center;\n  /**\n   * Hover\n   * 1. Apply hover style also to focus state\n   * 2. Remove default focus style\n   */\n  /* Active */\n}\n.am-icon-btn:hover,\n.am-icon-btn:focus {\n  /* 1 */\n  background-color: #f5f5f5;\n  color: #333333;\n  text-decoration: none;\n  outline: none;\n  /* 2 */\n}\n.am-icon-btn:active {\n  background-color: #ddd;\n  color: #333333;\n}\n.am-icon-btn.am-primary,\n.am-icon-btn.am-secondary,\n.am-icon-btn.am-success,\n.am-icon-btn.am-warning,\n.am-icon-btn.am-danger {\n  color: #fff;\n}\n.am-icon-btn.am-primary {\n  background-color: #0e90d2;\n}\n.am-icon-btn.am-secondary {\n  background-color: #3bb4f2;\n}\n.am-icon-btn.am-success {\n  background-color: #5eb95e;\n}\n.am-icon-btn.am-warning {\n  background-color: #F37B1D;\n}\n.am-icon-btn.am-danger {\n  background-color: #dd514c;\n}\n.am-icon-btn-sm {\n  width: 32px;\n  height: 32px;\n  font-size: 16px;\n  line-height: 32px;\n}\n.am-icon-btn-lg {\n  width: 64px;\n  height: 64px;\n  font-size: 28px;\n  line-height: 64px;\n}\n/* Modifier: `.am-icon-fw` Fixed width\n============================================================================= */\n.am-icon-fw {\n  width: 1.25em;\n  text-align: center;\n}\n/* Icon mapping\n============================================================================= */\n.am-icon-glass:before {\n  content: \"\\f000\";\n}\n.am-icon-music:before {\n  content: \"\\f001\";\n}\n.am-icon-search:before {\n  content: \"\\f002\";\n}\n.am-icon-envelope-o:before {\n  content: \"\\f003\";\n}\n.am-icon-heart:before {\n  content: \"\\f004\";\n}\n.am-icon-star:before {\n  content: \"\\f005\";\n}\n.am-icon-star-o:before {\n  content: \"\\f006\";\n}\n.am-icon-user:before {\n  content: \"\\f007\";\n}\n.am-icon-film:before {\n  content: \"\\f008\";\n}\n.am-icon-th-large:before {\n  content: \"\\f009\";\n}\n.am-icon-th:before {\n  content: \"\\f00a\";\n}\n.am-icon-th-list:before {\n  content: \"\\f00b\";\n}\n.am-icon-check:before {\n  content: \"\\f00c\";\n}\n.am-icon-remove:before,\n.am-icon-close:before,\n.am-icon-times:before {\n  content: \"\\f00d\";\n}\n.am-icon-search-plus:before {\n  content: \"\\f00e\";\n}\n.am-icon-search-minus:before {\n  content: \"\\f010\";\n}\n.am-icon-power-off:before {\n  content: \"\\f011\";\n}\n.am-icon-signal:before {\n  content: \"\\f012\";\n}\n.am-icon-gear:before,\n.am-icon-cog:before {\n  content: \"\\f013\";\n}\n.am-icon-trash-o:before {\n  content: \"\\f014\";\n}\n.am-icon-home:before {\n  content: \"\\f015\";\n}\n.am-icon-file-o:before {\n  content: \"\\f016\";\n}\n.am-icon-clock-o:before {\n  content: \"\\f017\";\n}\n.am-icon-road:before {\n  content: \"\\f018\";\n}\n.am-icon-download:before {\n  content: \"\\f019\";\n}\n.am-icon-arrow-circle-o-down:before {\n  content: \"\\f01a\";\n}\n.am-icon-arrow-circle-o-up:before {\n  content: \"\\f01b\";\n}\n.am-icon-inbox:before {\n  content: \"\\f01c\";\n}\n.am-icon-play-circle-o:before {\n  content: \"\\f01d\";\n}\n.am-icon-rotate-right:before,\n.am-icon-repeat:before {\n  content: \"\\f01e\";\n}\n.am-icon-refresh:before {\n  content: \"\\f021\";\n}\n.am-icon-list-alt:before {\n  content: \"\\f022\";\n}\n.am-icon-lock:before {\n  content: \"\\f023\";\n}\n.am-icon-flag:before {\n  content: \"\\f024\";\n}\n.am-icon-headphones:before {\n  content: \"\\f025\";\n}\n.am-icon-volume-off:before {\n  content: \"\\f026\";\n}\n.am-icon-volume-down:before {\n  content: \"\\f027\";\n}\n.am-icon-volume-up:before {\n  content: \"\\f028\";\n}\n.am-icon-qrcode:before {\n  content: \"\\f029\";\n}\n.am-icon-barcode:before {\n  content: \"\\f02a\";\n}\n.am-icon-tag:before {\n  content: \"\\f02b\";\n}\n.am-icon-tags:before {\n  content: \"\\f02c\";\n}\n.am-icon-book:before {\n  content: \"\\f02d\";\n}\n.am-icon-bookmark:before {\n  content: \"\\f02e\";\n}\n.am-icon-print:before {\n  content: \"\\f02f\";\n}\n.am-icon-camera:before {\n  content: \"\\f030\";\n}\n.am-icon-font:before {\n  content: \"\\f031\";\n}\n.am-icon-bold:before {\n  content: \"\\f032\";\n}\n.am-icon-italic:before {\n  content: \"\\f033\";\n}\n.am-icon-text-height:before {\n  content: \"\\f034\";\n}\n.am-icon-text-width:before {\n  content: \"\\f035\";\n}\n.am-icon-align-left:before {\n  content: \"\\f036\";\n}\n.am-icon-align-center:before {\n  content: \"\\f037\";\n}\n.am-icon-align-right:before {\n  content: \"\\f038\";\n}\n.am-icon-align-justify:before {\n  content: \"\\f039\";\n}\n.am-icon-list:before {\n  content: \"\\f03a\";\n}\n.am-icon-dedent:before,\n.am-icon-outdent:before {\n  content: \"\\f03b\";\n}\n.am-icon-indent:before {\n  content: \"\\f03c\";\n}\n.am-icon-video-camera:before {\n  content: \"\\f03d\";\n}\n.am-icon-photo:before,\n.am-icon-image:before,\n.am-icon-picture-o:before {\n  content: \"\\f03e\";\n}\n.am-icon-pencil:before {\n  content: \"\\f040\";\n}\n.am-icon-map-marker:before {\n  content: \"\\f041\";\n}\n.am-icon-adjust:before {\n  content: \"\\f042\";\n}\n.am-icon-tint:before {\n  content: \"\\f043\";\n}\n.am-icon-edit:before,\n.am-icon-pencil-square-o:before {\n  content: \"\\f044\";\n}\n.am-icon-share-square-o:before {\n  content: \"\\f045\";\n}\n.am-icon-check-square-o:before {\n  content: \"\\f046\";\n}\n.am-icon-arrows:before {\n  content: \"\\f047\";\n}\n.am-icon-step-backward:before {\n  content: \"\\f048\";\n}\n.am-icon-fast-backward:before {\n  content: \"\\f049\";\n}\n.am-icon-backward:before {\n  content: \"\\f04a\";\n}\n.am-icon-play:before {\n  content: \"\\f04b\";\n}\n.am-icon-pause:before {\n  content: \"\\f04c\";\n}\n.am-icon-stop:before {\n  content: \"\\f04d\";\n}\n.am-icon-forward:before {\n  content: \"\\f04e\";\n}\n.am-icon-fast-forward:before {\n  content: \"\\f050\";\n}\n.am-icon-step-forward:before {\n  content: \"\\f051\";\n}\n.am-icon-eject:before {\n  content: \"\\f052\";\n}\n.am-icon-chevron-left:before {\n  content: \"\\f053\";\n}\n.am-icon-chevron-right:before {\n  content: \"\\f054\";\n}\n.am-icon-plus-circle:before {\n  content: \"\\f055\";\n}\n.am-icon-minus-circle:before {\n  content: \"\\f056\";\n}\n.am-icon-times-circle:before {\n  content: \"\\f057\";\n}\n.am-icon-check-circle:before {\n  content: \"\\f058\";\n}\n.am-icon-question-circle:before {\n  content: \"\\f059\";\n}\n.am-icon-info-circle:before {\n  content: \"\\f05a\";\n}\n.am-icon-crosshairs:before {\n  content: \"\\f05b\";\n}\n.am-icon-times-circle-o:before {\n  content: \"\\f05c\";\n}\n.am-icon-check-circle-o:before {\n  content: \"\\f05d\";\n}\n.am-icon-ban:before {\n  content: \"\\f05e\";\n}\n.am-icon-arrow-left:before {\n  content: \"\\f060\";\n}\n.am-icon-arrow-right:before {\n  content: \"\\f061\";\n}\n.am-icon-arrow-up:before {\n  content: \"\\f062\";\n}\n.am-icon-arrow-down:before {\n  content: \"\\f063\";\n}\n.am-icon-mail-forward:before,\n.am-icon-share:before {\n  content: \"\\f064\";\n}\n.am-icon-expand:before {\n  content: \"\\f065\";\n}\n.am-icon-compress:before {\n  content: \"\\f066\";\n}\n.am-icon-plus:before {\n  content: \"\\f067\";\n}\n.am-icon-minus:before {\n  content: \"\\f068\";\n}\n.am-icon-asterisk:before {\n  content: \"\\f069\";\n}\n.am-icon-exclamation-circle:before {\n  content: \"\\f06a\";\n}\n.am-icon-gift:before {\n  content: \"\\f06b\";\n}\n.am-icon-leaf:before {\n  content: \"\\f06c\";\n}\n.am-icon-fire:before {\n  content: \"\\f06d\";\n}\n.am-icon-eye:before {\n  content: \"\\f06e\";\n}\n.am-icon-eye-slash:before {\n  content: \"\\f070\";\n}\n.am-icon-warning:before,\n.am-icon-exclamation-triangle:before {\n  content: \"\\f071\";\n}\n.am-icon-plane:before {\n  content: \"\\f072\";\n}\n.am-icon-calendar:before {\n  content: \"\\f073\";\n}\n.am-icon-random:before {\n  content: \"\\f074\";\n}\n.am-icon-comment:before {\n  content: \"\\f075\";\n}\n.am-icon-magnet:before {\n  content: \"\\f076\";\n}\n.am-icon-chevron-up:before {\n  content: \"\\f077\";\n}\n.am-icon-chevron-down:before {\n  content: \"\\f078\";\n}\n.am-icon-retweet:before {\n  content: \"\\f079\";\n}\n.am-icon-shopping-cart:before {\n  content: \"\\f07a\";\n}\n.am-icon-folder:before {\n  content: \"\\f07b\";\n}\n.am-icon-folder-open:before {\n  content: \"\\f07c\";\n}\n.am-icon-arrows-v:before {\n  content: \"\\f07d\";\n}\n.am-icon-arrows-h:before {\n  content: \"\\f07e\";\n}\n.am-icon-bar-chart-o:before,\n.am-icon-bar-chart:before {\n  content: \"\\f080\";\n}\n.am-icon-twitter-square:before {\n  content: \"\\f081\";\n}\n.am-icon-facebook-square:before {\n  content: \"\\f082\";\n}\n.am-icon-camera-retro:before {\n  content: \"\\f083\";\n}\n.am-icon-key:before {\n  content: \"\\f084\";\n}\n.am-icon-gears:before,\n.am-icon-cogs:before {\n  content: \"\\f085\";\n}\n.am-icon-comments:before {\n  content: \"\\f086\";\n}\n.am-icon-thumbs-o-up:before {\n  content: \"\\f087\";\n}\n.am-icon-thumbs-o-down:before {\n  content: \"\\f088\";\n}\n.am-icon-star-half:before {\n  content: \"\\f089\";\n}\n.am-icon-heart-o:before {\n  content: \"\\f08a\";\n}\n.am-icon-sign-out:before {\n  content: \"\\f08b\";\n}\n.am-icon-linkedin-square:before {\n  content: \"\\f08c\";\n}\n.am-icon-thumb-tack:before {\n  content: \"\\f08d\";\n}\n.am-icon-external-link:before {\n  content: \"\\f08e\";\n}\n.am-icon-sign-in:before {\n  content: \"\\f090\";\n}\n.am-icon-trophy:before {\n  content: \"\\f091\";\n}\n.am-icon-github-square:before {\n  content: \"\\f092\";\n}\n.am-icon-upload:before {\n  content: \"\\f093\";\n}\n.am-icon-lemon-o:before {\n  content: \"\\f094\";\n}\n.am-icon-phone:before {\n  content: \"\\f095\";\n}\n.am-icon-square-o:before {\n  content: \"\\f096\";\n}\n.am-icon-bookmark-o:before {\n  content: \"\\f097\";\n}\n.am-icon-phone-square:before {\n  content: \"\\f098\";\n}\n.am-icon-twitter:before {\n  content: \"\\f099\";\n}\n.am-icon-facebook-f:before,\n.am-icon-facebook:before {\n  content: \"\\f09a\";\n}\n.am-icon-github:before {\n  content: \"\\f09b\";\n}\n.am-icon-unlock:before {\n  content: \"\\f09c\";\n}\n.am-icon-credit-card:before {\n  content: \"\\f09d\";\n}\n.am-icon-feed:before,\n.am-icon-rss:before {\n  content: \"\\f09e\";\n}\n.am-icon-hdd-o:before {\n  content: \"\\f0a0\";\n}\n.am-icon-bullhorn:before {\n  content: \"\\f0a1\";\n}\n.am-icon-bell:before {\n  content: \"\\f0f3\";\n}\n.am-icon-certificate:before {\n  content: \"\\f0a3\";\n}\n.am-icon-hand-o-right:before {\n  content: \"\\f0a4\";\n}\n.am-icon-hand-o-left:before {\n  content: \"\\f0a5\";\n}\n.am-icon-hand-o-up:before {\n  content: \"\\f0a6\";\n}\n.am-icon-hand-o-down:before {\n  content: \"\\f0a7\";\n}\n.am-icon-arrow-circle-left:before {\n  content: \"\\f0a8\";\n}\n.am-icon-arrow-circle-right:before {\n  content: \"\\f0a9\";\n}\n.am-icon-arrow-circle-up:before {\n  content: \"\\f0aa\";\n}\n.am-icon-arrow-circle-down:before {\n  content: \"\\f0ab\";\n}\n.am-icon-globe:before {\n  content: \"\\f0ac\";\n}\n.am-icon-wrench:before {\n  content: \"\\f0ad\";\n}\n.am-icon-tasks:before {\n  content: \"\\f0ae\";\n}\n.am-icon-filter:before {\n  content: \"\\f0b0\";\n}\n.am-icon-briefcase:before {\n  content: \"\\f0b1\";\n}\n.am-icon-arrows-alt:before {\n  content: \"\\f0b2\";\n}\n.am-icon-group:before,\n.am-icon-users:before {\n  content: \"\\f0c0\";\n}\n.am-icon-chain:before,\n.am-icon-link:before {\n  content: \"\\f0c1\";\n}\n.am-icon-cloud:before {\n  content: \"\\f0c2\";\n}\n.am-icon-flask:before {\n  content: \"\\f0c3\";\n}\n.am-icon-cut:before,\n.am-icon-scissors:before {\n  content: \"\\f0c4\";\n}\n.am-icon-copy:before,\n.am-icon-files-o:before {\n  content: \"\\f0c5\";\n}\n.am-icon-paperclip:before {\n  content: \"\\f0c6\";\n}\n.am-icon-save:before,\n.am-icon-floppy-o:before {\n  content: \"\\f0c7\";\n}\n.am-icon-square:before {\n  content: \"\\f0c8\";\n}\n.am-icon-navicon:before,\n.am-icon-reorder:before,\n.am-icon-bars:before {\n  content: \"\\f0c9\";\n}\n.am-icon-list-ul:before {\n  content: \"\\f0ca\";\n}\n.am-icon-list-ol:before {\n  content: \"\\f0cb\";\n}\n.am-icon-strikethrough:before {\n  content: \"\\f0cc\";\n}\n.am-icon-underline:before {\n  content: \"\\f0cd\";\n}\n.am-icon-table:before {\n  content: \"\\f0ce\";\n}\n.am-icon-magic:before {\n  content: \"\\f0d0\";\n}\n.am-icon-truck:before {\n  content: \"\\f0d1\";\n}\n.am-icon-pinterest:before {\n  content: \"\\f0d2\";\n}\n.am-icon-pinterest-square:before {\n  content: \"\\f0d3\";\n}\n.am-icon-google-plus-square:before {\n  content: \"\\f0d4\";\n}\n.am-icon-google-plus:before {\n  content: \"\\f0d5\";\n}\n.am-icon-money:before {\n  content: \"\\f0d6\";\n}\n.am-icon-caret-down:before {\n  content: \"\\f0d7\";\n}\n.am-icon-caret-up:before {\n  content: \"\\f0d8\";\n}\n.am-icon-caret-left:before {\n  content: \"\\f0d9\";\n}\n.am-icon-caret-right:before {\n  content: \"\\f0da\";\n}\n.am-icon-columns:before {\n  content: \"\\f0db\";\n}\n.am-icon-unsorted:before,\n.am-icon-sort:before {\n  content: \"\\f0dc\";\n}\n.am-icon-sort-down:before,\n.am-icon-sort-desc:before {\n  content: \"\\f0dd\";\n}\n.am-icon-sort-up:before,\n.am-icon-sort-asc:before {\n  content: \"\\f0de\";\n}\n.am-icon-envelope:before {\n  content: \"\\f0e0\";\n}\n.am-icon-linkedin:before {\n  content: \"\\f0e1\";\n}\n.am-icon-rotate-left:before,\n.am-icon-undo:before {\n  content: \"\\f0e2\";\n}\n.am-icon-legal:before,\n.am-icon-gavel:before {\n  content: \"\\f0e3\";\n}\n.am-icon-dashboard:before,\n.am-icon-tachometer:before {\n  content: \"\\f0e4\";\n}\n.am-icon-comment-o:before {\n  content: \"\\f0e5\";\n}\n.am-icon-comments-o:before {\n  content: \"\\f0e6\";\n}\n.am-icon-flash:before,\n.am-icon-bolt:before {\n  content: \"\\f0e7\";\n}\n.am-icon-sitemap:before {\n  content: \"\\f0e8\";\n}\n.am-icon-umbrella:before {\n  content: \"\\f0e9\";\n}\n.am-icon-paste:before,\n.am-icon-clipboard:before {\n  content: \"\\f0ea\";\n}\n.am-icon-lightbulb-o:before {\n  content: \"\\f0eb\";\n}\n.am-icon-exchange:before {\n  content: \"\\f0ec\";\n}\n.am-icon-cloud-download:before {\n  content: \"\\f0ed\";\n}\n.am-icon-cloud-upload:before {\n  content: \"\\f0ee\";\n}\n.am-icon-user-md:before {\n  content: \"\\f0f0\";\n}\n.am-icon-stethoscope:before {\n  content: \"\\f0f1\";\n}\n.am-icon-suitcase:before {\n  content: \"\\f0f2\";\n}\n.am-icon-bell-o:before {\n  content: \"\\f0a2\";\n}\n.am-icon-coffee:before {\n  content: \"\\f0f4\";\n}\n.am-icon-cutlery:before {\n  content: \"\\f0f5\";\n}\n.am-icon-file-text-o:before {\n  content: \"\\f0f6\";\n}\n.am-icon-building-o:before {\n  content: \"\\f0f7\";\n}\n.am-icon-hospital-o:before {\n  content: \"\\f0f8\";\n}\n.am-icon-ambulance:before {\n  content: \"\\f0f9\";\n}\n.am-icon-medkit:before {\n  content: \"\\f0fa\";\n}\n.am-icon-fighter-jet:before {\n  content: \"\\f0fb\";\n}\n.am-icon-beer:before {\n  content: \"\\f0fc\";\n}\n.am-icon-h-square:before {\n  content: \"\\f0fd\";\n}\n.am-icon-plus-square:before {\n  content: \"\\f0fe\";\n}\n.am-icon-angle-double-left:before {\n  content: \"\\f100\";\n}\n.am-icon-angle-double-right:before {\n  content: \"\\f101\";\n}\n.am-icon-angle-double-up:before {\n  content: \"\\f102\";\n}\n.am-icon-angle-double-down:before {\n  content: \"\\f103\";\n}\n.am-icon-angle-left:before {\n  content: \"\\f104\";\n}\n.am-icon-angle-right:before {\n  content: \"\\f105\";\n}\n.am-icon-angle-up:before {\n  content: \"\\f106\";\n}\n.am-icon-angle-down:before {\n  content: \"\\f107\";\n}\n.am-icon-desktop:before {\n  content: \"\\f108\";\n}\n.am-icon-laptop:before {\n  content: \"\\f109\";\n}\n.am-icon-tablet:before {\n  content: \"\\f10a\";\n}\n.am-icon-mobile-phone:before,\n.am-icon-mobile:before {\n  content: \"\\f10b\";\n}\n.am-icon-circle-o:before {\n  content: \"\\f10c\";\n}\n.am-icon-quote-left:before {\n  content: \"\\f10d\";\n}\n.am-icon-quote-right:before {\n  content: \"\\f10e\";\n}\n.am-icon-spinner:before {\n  content: \"\\f110\";\n}\n.am-icon-circle:before {\n  content: \"\\f111\";\n}\n.am-icon-mail-reply:before,\n.am-icon-reply:before {\n  content: \"\\f112\";\n}\n.am-icon-github-alt:before {\n  content: \"\\f113\";\n}\n.am-icon-folder-o:before {\n  content: \"\\f114\";\n}\n.am-icon-folder-open-o:before {\n  content: \"\\f115\";\n}\n.am-icon-smile-o:before {\n  content: \"\\f118\";\n}\n.am-icon-frown-o:before {\n  content: \"\\f119\";\n}\n.am-icon-meh-o:before {\n  content: \"\\f11a\";\n}\n.am-icon-gamepad:before {\n  content: \"\\f11b\";\n}\n.am-icon-keyboard-o:before {\n  content: \"\\f11c\";\n}\n.am-icon-flag-o:before {\n  content: \"\\f11d\";\n}\n.am-icon-flag-checkered:before {\n  content: \"\\f11e\";\n}\n.am-icon-terminal:before {\n  content: \"\\f120\";\n}\n.am-icon-code:before {\n  content: \"\\f121\";\n}\n.am-icon-mail-reply-all:before,\n.am-icon-reply-all:before {\n  content: \"\\f122\";\n}\n.am-icon-star-half-empty:before,\n.am-icon-star-half-full:before,\n.am-icon-star-half-o:before {\n  content: \"\\f123\";\n}\n.am-icon-location-arrow:before {\n  content: \"\\f124\";\n}\n.am-icon-crop:before {\n  content: \"\\f125\";\n}\n.am-icon-code-fork:before {\n  content: \"\\f126\";\n}\n.am-icon-unlink:before,\n.am-icon-chain-broken:before {\n  content: \"\\f127\";\n}\n.am-icon-question:before {\n  content: \"\\f128\";\n}\n.am-icon-info:before {\n  content: \"\\f129\";\n}\n.am-icon-exclamation:before {\n  content: \"\\f12a\";\n}\n.am-icon-superscript:before {\n  content: \"\\f12b\";\n}\n.am-icon-subscript:before {\n  content: \"\\f12c\";\n}\n.am-icon-eraser:before {\n  content: \"\\f12d\";\n}\n.am-icon-puzzle-piece:before {\n  content: \"\\f12e\";\n}\n.am-icon-microphone:before {\n  content: \"\\f130\";\n}\n.am-icon-microphone-slash:before {\n  content: \"\\f131\";\n}\n.am-icon-shield:before {\n  content: \"\\f132\";\n}\n.am-icon-calendar-o:before {\n  content: \"\\f133\";\n}\n.am-icon-fire-extinguisher:before {\n  content: \"\\f134\";\n}\n.am-icon-rocket:before {\n  content: \"\\f135\";\n}\n.am-icon-maxcdn:before {\n  content: \"\\f136\";\n}\n.am-icon-chevron-circle-left:before {\n  content: \"\\f137\";\n}\n.am-icon-chevron-circle-right:before {\n  content: \"\\f138\";\n}\n.am-icon-chevron-circle-up:before {\n  content: \"\\f139\";\n}\n.am-icon-chevron-circle-down:before {\n  content: \"\\f13a\";\n}\n.am-icon-html5:before {\n  content: \"\\f13b\";\n}\n.am-icon-css3:before {\n  content: \"\\f13c\";\n}\n.am-icon-anchor:before {\n  content: \"\\f13d\";\n}\n.am-icon-unlock-alt:before {\n  content: \"\\f13e\";\n}\n.am-icon-bullseye:before {\n  content: \"\\f140\";\n}\n.am-icon-ellipsis-h:before {\n  content: \"\\f141\";\n}\n.am-icon-ellipsis-v:before {\n  content: \"\\f142\";\n}\n.am-icon-rss-square:before {\n  content: \"\\f143\";\n}\n.am-icon-play-circle:before {\n  content: \"\\f144\";\n}\n.am-icon-ticket:before {\n  content: \"\\f145\";\n}\n.am-icon-minus-square:before {\n  content: \"\\f146\";\n}\n.am-icon-minus-square-o:before {\n  content: \"\\f147\";\n}\n.am-icon-level-up:before {\n  content: \"\\f148\";\n}\n.am-icon-level-down:before {\n  content: \"\\f149\";\n}\n.am-icon-check-square:before {\n  content: \"\\f14a\";\n}\n.am-icon-pencil-square:before {\n  content: \"\\f14b\";\n}\n.am-icon-external-link-square:before {\n  content: \"\\f14c\";\n}\n.am-icon-share-square:before {\n  content: \"\\f14d\";\n}\n.am-icon-compass:before {\n  content: \"\\f14e\";\n}\n.am-icon-toggle-down:before,\n.am-icon-caret-square-o-down:before {\n  content: \"\\f150\";\n}\n.am-icon-toggle-up:before,\n.am-icon-caret-square-o-up:before {\n  content: \"\\f151\";\n}\n.am-icon-toggle-right:before,\n.am-icon-caret-square-o-right:before {\n  content: \"\\f152\";\n}\n.am-icon-euro:before,\n.am-icon-eur:before {\n  content: \"\\f153\";\n}\n.am-icon-gbp:before {\n  content: \"\\f154\";\n}\n.am-icon-dollar:before,\n.am-icon-usd:before {\n  content: \"\\f155\";\n}\n.am-icon-rupee:before,\n.am-icon-inr:before {\n  content: \"\\f156\";\n}\n.am-icon-cny:before,\n.am-icon-rmb:before,\n.am-icon-yen:before,\n.am-icon-jpy:before {\n  content: \"\\f157\";\n}\n.am-icon-ruble:before,\n.am-icon-rouble:before,\n.am-icon-rub:before {\n  content: \"\\f158\";\n}\n.am-icon-won:before,\n.am-icon-krw:before {\n  content: \"\\f159\";\n}\n.am-icon-bitcoin:before,\n.am-icon-btc:before {\n  content: \"\\f15a\";\n}\n.am-icon-file:before {\n  content: \"\\f15b\";\n}\n.am-icon-file-text:before {\n  content: \"\\f15c\";\n}\n.am-icon-sort-alpha-asc:before {\n  content: \"\\f15d\";\n}\n.am-icon-sort-alpha-desc:before {\n  content: \"\\f15e\";\n}\n.am-icon-sort-amount-asc:before {\n  content: \"\\f160\";\n}\n.am-icon-sort-amount-desc:before {\n  content: \"\\f161\";\n}\n.am-icon-sort-numeric-asc:before {\n  content: \"\\f162\";\n}\n.am-icon-sort-numeric-desc:before {\n  content: \"\\f163\";\n}\n.am-icon-thumbs-up:before {\n  content: \"\\f164\";\n}\n.am-icon-thumbs-down:before {\n  content: \"\\f165\";\n}\n.am-icon-youtube-square:before {\n  content: \"\\f166\";\n}\n.am-icon-youtube:before {\n  content: \"\\f167\";\n}\n.am-icon-xing:before {\n  content: \"\\f168\";\n}\n.am-icon-xing-square:before {\n  content: \"\\f169\";\n}\n.am-icon-youtube-play:before {\n  content: \"\\f16a\";\n}\n.am-icon-dropbox:before {\n  content: \"\\f16b\";\n}\n.am-icon-stack-overflow:before {\n  content: \"\\f16c\";\n}\n.am-icon-instagram:before {\n  content: \"\\f16d\";\n}\n.am-icon-flickr:before {\n  content: \"\\f16e\";\n}\n.am-icon-adn:before {\n  content: \"\\f170\";\n}\n.am-icon-bitbucket:before {\n  content: \"\\f171\";\n}\n.am-icon-bitbucket-square:before {\n  content: \"\\f172\";\n}\n.am-icon-tumblr:before {\n  content: \"\\f173\";\n}\n.am-icon-tumblr-square:before {\n  content: \"\\f174\";\n}\n.am-icon-long-arrow-down:before {\n  content: \"\\f175\";\n}\n.am-icon-long-arrow-up:before {\n  content: \"\\f176\";\n}\n.am-icon-long-arrow-left:before {\n  content: \"\\f177\";\n}\n.am-icon-long-arrow-right:before {\n  content: \"\\f178\";\n}\n.am-icon-apple:before {\n  content: \"\\f179\";\n}\n.am-icon-windows:before {\n  content: \"\\f17a\";\n}\n.am-icon-android:before {\n  content: \"\\f17b\";\n}\n.am-icon-linux:before {\n  content: \"\\f17c\";\n}\n.am-icon-dribbble:before {\n  content: \"\\f17d\";\n}\n.am-icon-skype:before {\n  content: \"\\f17e\";\n}\n.am-icon-foursquare:before {\n  content: \"\\f180\";\n}\n.am-icon-trello:before {\n  content: \"\\f181\";\n}\n.am-icon-female:before {\n  content: \"\\f182\";\n}\n.am-icon-male:before {\n  content: \"\\f183\";\n}\n.am-icon-gittip:before,\n.am-icon-gratipay:before {\n  content: \"\\f184\";\n}\n.am-icon-sun-o:before {\n  content: \"\\f185\";\n}\n.am-icon-moon-o:before {\n  content: \"\\f186\";\n}\n.am-icon-archive:before {\n  content: \"\\f187\";\n}\n.am-icon-bug:before {\n  content: \"\\f188\";\n}\n.am-icon-vk:before {\n  content: \"\\f189\";\n}\n.am-icon-weibo:before {\n  content: \"\\f18a\";\n}\n.am-icon-renren:before {\n  content: \"\\f18b\";\n}\n.am-icon-pagelines:before {\n  content: \"\\f18c\";\n}\n.am-icon-stack-exchange:before {\n  content: \"\\f18d\";\n}\n.am-icon-arrow-circle-o-right:before {\n  content: \"\\f18e\";\n}\n.am-icon-arrow-circle-o-left:before {\n  content: \"\\f190\";\n}\n.am-icon-toggle-left:before,\n.am-icon-caret-square-o-left:before {\n  content: \"\\f191\";\n}\n.am-icon-dot-circle-o:before {\n  content: \"\\f192\";\n}\n.am-icon-wheelchair:before {\n  content: \"\\f193\";\n}\n.am-icon-vimeo-square:before {\n  content: \"\\f194\";\n}\n.am-icon-turkish-lira:before,\n.am-icon-try:before {\n  content: \"\\f195\";\n}\n.am-icon-plus-square-o:before {\n  content: \"\\f196\";\n}\n.am-icon-space-shuttle:before {\n  content: \"\\f197\";\n}\n.am-icon-slack:before {\n  content: \"\\f198\";\n}\n.am-icon-envelope-square:before {\n  content: \"\\f199\";\n}\n.am-icon-wordpress:before {\n  content: \"\\f19a\";\n}\n.am-icon-openid:before {\n  content: \"\\f19b\";\n}\n.am-icon-institution:before,\n.am-icon-bank:before,\n.am-icon-university:before {\n  content: \"\\f19c\";\n}\n.am-icon-mortar-board:before,\n.am-icon-graduation-cap:before {\n  content: \"\\f19d\";\n}\n.am-icon-yahoo:before {\n  content: \"\\f19e\";\n}\n.am-icon-google:before {\n  content: \"\\f1a0\";\n}\n.am-icon-reddit:before {\n  content: \"\\f1a1\";\n}\n.am-icon-reddit-square:before {\n  content: \"\\f1a2\";\n}\n.am-icon-stumbleupon-circle:before {\n  content: \"\\f1a3\";\n}\n.am-icon-stumbleupon:before {\n  content: \"\\f1a4\";\n}\n.am-icon-delicious:before {\n  content: \"\\f1a5\";\n}\n.am-icon-digg:before {\n  content: \"\\f1a6\";\n}\n.am-icon-pied-piper:before {\n  content: \"\\f1a7\";\n}\n.am-icon-pied-piper-alt:before {\n  content: \"\\f1a8\";\n}\n.am-icon-drupal:before {\n  content: \"\\f1a9\";\n}\n.am-icon-joomla:before {\n  content: \"\\f1aa\";\n}\n.am-icon-language:before {\n  content: \"\\f1ab\";\n}\n.am-icon-fax:before {\n  content: \"\\f1ac\";\n}\n.am-icon-building:before {\n  content: \"\\f1ad\";\n}\n.am-icon-child:before {\n  content: \"\\f1ae\";\n}\n.am-icon-paw:before {\n  content: \"\\f1b0\";\n}\n.am-icon-spoon:before {\n  content: \"\\f1b1\";\n}\n.am-icon-cube:before {\n  content: \"\\f1b2\";\n}\n.am-icon-cubes:before {\n  content: \"\\f1b3\";\n}\n.am-icon-behance:before {\n  content: \"\\f1b4\";\n}\n.am-icon-behance-square:before {\n  content: \"\\f1b5\";\n}\n.am-icon-steam:before {\n  content: \"\\f1b6\";\n}\n.am-icon-steam-square:before {\n  content: \"\\f1b7\";\n}\n.am-icon-recycle:before {\n  content: \"\\f1b8\";\n}\n.am-icon-automobile:before,\n.am-icon-car:before {\n  content: \"\\f1b9\";\n}\n.am-icon-cab:before,\n.am-icon-taxi:before {\n  content: \"\\f1ba\";\n}\n.am-icon-tree:before {\n  content: \"\\f1bb\";\n}\n.am-icon-spotify:before {\n  content: \"\\f1bc\";\n}\n.am-icon-deviantart:before {\n  content: \"\\f1bd\";\n}\n.am-icon-soundcloud:before {\n  content: \"\\f1be\";\n}\n.am-icon-database:before {\n  content: \"\\f1c0\";\n}\n.am-icon-file-pdf-o:before {\n  content: \"\\f1c1\";\n}\n.am-icon-file-word-o:before {\n  content: \"\\f1c2\";\n}\n.am-icon-file-excel-o:before {\n  content: \"\\f1c3\";\n}\n.am-icon-file-powerpoint-o:before {\n  content: \"\\f1c4\";\n}\n.am-icon-file-photo-o:before,\n.am-icon-file-picture-o:before,\n.am-icon-file-image-o:before {\n  content: \"\\f1c5\";\n}\n.am-icon-file-zip-o:before,\n.am-icon-file-archive-o:before {\n  content: \"\\f1c6\";\n}\n.am-icon-file-sound-o:before,\n.am-icon-file-audio-o:before {\n  content: \"\\f1c7\";\n}\n.am-icon-file-movie-o:before,\n.am-icon-file-video-o:before {\n  content: \"\\f1c8\";\n}\n.am-icon-file-code-o:before {\n  content: \"\\f1c9\";\n}\n.am-icon-vine:before {\n  content: \"\\f1ca\";\n}\n.am-icon-codepen:before {\n  content: \"\\f1cb\";\n}\n.am-icon-jsfiddle:before {\n  content: \"\\f1cc\";\n}\n.am-icon-life-bouy:before,\n.am-icon-life-buoy:before,\n.am-icon-life-saver:before,\n.am-icon-support:before,\n.am-icon-life-ring:before {\n  content: \"\\f1cd\";\n}\n.am-icon-circle-o-notch:before {\n  content: \"\\f1ce\";\n}\n.am-icon-ra:before,\n.am-icon-rebel:before {\n  content: \"\\f1d0\";\n}\n.am-icon-ge:before,\n.am-icon-empire:before {\n  content: \"\\f1d1\";\n}\n.am-icon-git-square:before {\n  content: \"\\f1d2\";\n}\n.am-icon-git:before {\n  content: \"\\f1d3\";\n}\n.am-icon-y-combinator-square:before,\n.am-icon-yc-square:before,\n.am-icon-hacker-news:before {\n  content: \"\\f1d4\";\n}\n.am-icon-tencent-weibo:before {\n  content: \"\\f1d5\";\n}\n.am-icon-qq:before {\n  content: \"\\f1d6\";\n}\n.am-icon-wechat:before,\n.am-icon-weixin:before {\n  content: \"\\f1d7\";\n}\n.am-icon-send:before,\n.am-icon-paper-plane:before {\n  content: \"\\f1d8\";\n}\n.am-icon-send-o:before,\n.am-icon-paper-plane-o:before {\n  content: \"\\f1d9\";\n}\n.am-icon-history:before {\n  content: \"\\f1da\";\n}\n.am-icon-circle-thin:before {\n  content: \"\\f1db\";\n}\n.am-icon-header:before {\n  content: \"\\f1dc\";\n}\n.am-icon-paragraph:before {\n  content: \"\\f1dd\";\n}\n.am-icon-sliders:before {\n  content: \"\\f1de\";\n}\n.am-icon-share-alt:before {\n  content: \"\\f1e0\";\n}\n.am-icon-share-alt-square:before {\n  content: \"\\f1e1\";\n}\n.am-icon-bomb:before {\n  content: \"\\f1e2\";\n}\n.am-icon-soccer-ball-o:before,\n.am-icon-futbol-o:before {\n  content: \"\\f1e3\";\n}\n.am-icon-tty:before {\n  content: \"\\f1e4\";\n}\n.am-icon-binoculars:before {\n  content: \"\\f1e5\";\n}\n.am-icon-plug:before {\n  content: \"\\f1e6\";\n}\n.am-icon-slideshare:before {\n  content: \"\\f1e7\";\n}\n.am-icon-twitch:before {\n  content: \"\\f1e8\";\n}\n.am-icon-yelp:before {\n  content: \"\\f1e9\";\n}\n.am-icon-newspaper-o:before {\n  content: \"\\f1ea\";\n}\n.am-icon-wifi:before {\n  content: \"\\f1eb\";\n}\n.am-icon-calculator:before {\n  content: \"\\f1ec\";\n}\n.am-icon-paypal:before {\n  content: \"\\f1ed\";\n}\n.am-icon-google-wallet:before {\n  content: \"\\f1ee\";\n}\n.am-icon-cc-visa:before {\n  content: \"\\f1f0\";\n}\n.am-icon-cc-mastercard:before {\n  content: \"\\f1f1\";\n}\n.am-icon-cc-discover:before {\n  content: \"\\f1f2\";\n}\n.am-icon-cc-amex:before {\n  content: \"\\f1f3\";\n}\n.am-icon-cc-paypal:before {\n  content: \"\\f1f4\";\n}\n.am-icon-cc-stripe:before {\n  content: \"\\f1f5\";\n}\n.am-icon-bell-slash:before {\n  content: \"\\f1f6\";\n}\n.am-icon-bell-slash-o:before {\n  content: \"\\f1f7\";\n}\n.am-icon-trash:before {\n  content: \"\\f1f8\";\n}\n.am-icon-copyright:before {\n  content: \"\\f1f9\";\n}\n.am-icon-at:before {\n  content: \"\\f1fa\";\n}\n.am-icon-eyedropper:before {\n  content: \"\\f1fb\";\n}\n.am-icon-paint-brush:before {\n  content: \"\\f1fc\";\n}\n.am-icon-birthday-cake:before {\n  content: \"\\f1fd\";\n}\n.am-icon-area-chart:before {\n  content: \"\\f1fe\";\n}\n.am-icon-pie-chart:before {\n  content: \"\\f200\";\n}\n.am-icon-line-chart:before {\n  content: \"\\f201\";\n}\n.am-icon-lastfm:before {\n  content: \"\\f202\";\n}\n.am-icon-lastfm-square:before {\n  content: \"\\f203\";\n}\n.am-icon-toggle-off:before {\n  content: \"\\f204\";\n}\n.am-icon-toggle-on:before {\n  content: \"\\f205\";\n}\n.am-icon-bicycle:before {\n  content: \"\\f206\";\n}\n.am-icon-bus:before {\n  content: \"\\f207\";\n}\n.am-icon-ioxhost:before {\n  content: \"\\f208\";\n}\n.am-icon-angellist:before {\n  content: \"\\f209\";\n}\n.am-icon-cc:before {\n  content: \"\\f20a\";\n}\n.am-icon-shekel:before,\n.am-icon-sheqel:before,\n.am-icon-ils:before {\n  content: \"\\f20b\";\n}\n.am-icon-meanpath:before {\n  content: \"\\f20c\";\n}\n.am-icon-buysellads:before {\n  content: \"\\f20d\";\n}\n.am-icon-connectdevelop:before {\n  content: \"\\f20e\";\n}\n.am-icon-dashcube:before {\n  content: \"\\f210\";\n}\n.am-icon-forumbee:before {\n  content: \"\\f211\";\n}\n.am-icon-leanpub:before {\n  content: \"\\f212\";\n}\n.am-icon-sellsy:before {\n  content: \"\\f213\";\n}\n.am-icon-shirtsinbulk:before {\n  content: \"\\f214\";\n}\n.am-icon-simplybuilt:before {\n  content: \"\\f215\";\n}\n.am-icon-skyatlas:before {\n  content: \"\\f216\";\n}\n.am-icon-cart-plus:before {\n  content: \"\\f217\";\n}\n.am-icon-cart-arrow-down:before {\n  content: \"\\f218\";\n}\n.am-icon-diamond:before {\n  content: \"\\f219\";\n}\n.am-icon-ship:before {\n  content: \"\\f21a\";\n}\n.am-icon-user-secret:before {\n  content: \"\\f21b\";\n}\n.am-icon-motorcycle:before {\n  content: \"\\f21c\";\n}\n.am-icon-street-view:before {\n  content: \"\\f21d\";\n}\n.am-icon-heartbeat:before {\n  content: \"\\f21e\";\n}\n.am-icon-venus:before {\n  content: \"\\f221\";\n}\n.am-icon-mars:before {\n  content: \"\\f222\";\n}\n.am-icon-mercury:before {\n  content: \"\\f223\";\n}\n.am-icon-intersex:before,\n.am-icon-transgender:before {\n  content: \"\\f224\";\n}\n.am-icon-transgender-alt:before {\n  content: \"\\f225\";\n}\n.am-icon-venus-double:before {\n  content: \"\\f226\";\n}\n.am-icon-mars-double:before {\n  content: \"\\f227\";\n}\n.am-icon-venus-mars:before {\n  content: \"\\f228\";\n}\n.am-icon-mars-stroke:before {\n  content: \"\\f229\";\n}\n.am-icon-mars-stroke-v:before {\n  content: \"\\f22a\";\n}\n.am-icon-mars-stroke-h:before {\n  content: \"\\f22b\";\n}\n.am-icon-neuter:before {\n  content: \"\\f22c\";\n}\n.am-icon-genderless:before {\n  content: \"\\f22d\";\n}\n.am-icon-facebook-official:before {\n  content: \"\\f230\";\n}\n.am-icon-pinterest-p:before {\n  content: \"\\f231\";\n}\n.am-icon-whatsapp:before {\n  content: \"\\f232\";\n}\n.am-icon-server:before {\n  content: \"\\f233\";\n}\n.am-icon-user-plus:before {\n  content: \"\\f234\";\n}\n.am-icon-user-times:before {\n  content: \"\\f235\";\n}\n.am-icon-hotel:before,\n.am-icon-bed:before {\n  content: \"\\f236\";\n}\n.am-icon-viacoin:before {\n  content: \"\\f237\";\n}\n.am-icon-train:before {\n  content: \"\\f238\";\n}\n.am-icon-subway:before {\n  content: \"\\f239\";\n}\n.am-icon-medium:before {\n  content: \"\\f23a\";\n}\n.am-icon-yc:before,\n.am-icon-y-combinator:before {\n  content: \"\\f23b\";\n}\n.am-icon-optin-monster:before {\n  content: \"\\f23c\";\n}\n.am-icon-opencart:before {\n  content: \"\\f23d\";\n}\n.am-icon-expeditedssl:before {\n  content: \"\\f23e\";\n}\n.am-icon-battery-4:before,\n.am-icon-battery-full:before {\n  content: \"\\f240\";\n}\n.am-icon-battery-3:before,\n.am-icon-battery-three-quarters:before {\n  content: \"\\f241\";\n}\n.am-icon-battery-2:before,\n.am-icon-battery-half:before {\n  content: \"\\f242\";\n}\n.am-icon-battery-1:before,\n.am-icon-battery-quarter:before {\n  content: \"\\f243\";\n}\n.am-icon-battery-0:before,\n.am-icon-battery-empty:before {\n  content: \"\\f244\";\n}\n.am-icon-mouse-pointer:before {\n  content: \"\\f245\";\n}\n.am-icon-i-cursor:before {\n  content: \"\\f246\";\n}\n.am-icon-object-group:before {\n  content: \"\\f247\";\n}\n.am-icon-object-ungroup:before {\n  content: \"\\f248\";\n}\n.am-icon-sticky-note:before {\n  content: \"\\f249\";\n}\n.am-icon-sticky-note-o:before {\n  content: \"\\f24a\";\n}\n.am-icon-cc-jcb:before {\n  content: \"\\f24b\";\n}\n.am-icon-cc-diners-club:before {\n  content: \"\\f24c\";\n}\n.am-icon-clone:before {\n  content: \"\\f24d\";\n}\n.am-icon-balance-scale:before {\n  content: \"\\f24e\";\n}\n.am-icon-hourglass-o:before {\n  content: \"\\f250\";\n}\n.am-icon-hourglass-1:before,\n.am-icon-hourglass-start:before {\n  content: \"\\f251\";\n}\n.am-icon-hourglass-2:before,\n.am-icon-hourglass-half:before {\n  content: \"\\f252\";\n}\n.am-icon-hourglass-3:before,\n.am-icon-hourglass-end:before {\n  content: \"\\f253\";\n}\n.am-icon-hourglass:before {\n  content: \"\\f254\";\n}\n.am-icon-hand-grab-o:before,\n.am-icon-hand-rock-o:before {\n  content: \"\\f255\";\n}\n.am-icon-hand-stop-o:before,\n.am-icon-hand-paper-o:before {\n  content: \"\\f256\";\n}\n.am-icon-hand-scissors-o:before {\n  content: \"\\f257\";\n}\n.am-icon-hand-lizard-o:before {\n  content: \"\\f258\";\n}\n.am-icon-hand-spock-o:before {\n  content: \"\\f259\";\n}\n.am-icon-hand-pointer-o:before {\n  content: \"\\f25a\";\n}\n.am-icon-hand-peace-o:before {\n  content: \"\\f25b\";\n}\n.am-icon-trademark:before {\n  content: \"\\f25c\";\n}\n.am-icon-registered:before {\n  content: \"\\f25d\";\n}\n.am-icon-creative-commons:before {\n  content: \"\\f25e\";\n}\n.am-icon-gg:before {\n  content: \"\\f260\";\n}\n.am-icon-gg-circle:before {\n  content: \"\\f261\";\n}\n.am-icon-tripadvisor:before {\n  content: \"\\f262\";\n}\n.am-icon-odnoklassniki:before {\n  content: \"\\f263\";\n}\n.am-icon-odnoklassniki-square:before {\n  content: \"\\f264\";\n}\n.am-icon-get-pocket:before {\n  content: \"\\f265\";\n}\n.am-icon-wikipedia-w:before {\n  content: \"\\f266\";\n}\n.am-icon-safari:before {\n  content: \"\\f267\";\n}\n.am-icon-chrome:before {\n  content: \"\\f268\";\n}\n.am-icon-firefox:before {\n  content: \"\\f269\";\n}\n.am-icon-opera:before {\n  content: \"\\f26a\";\n}\n.am-icon-internet-explorer:before {\n  content: \"\\f26b\";\n}\n.am-icon-tv:before,\n.am-icon-television:before {\n  content: \"\\f26c\";\n}\n.am-icon-contao:before {\n  content: \"\\f26d\";\n}\n.am-icon-500px:before {\n  content: \"\\f26e\";\n}\n.am-icon-amazon:before {\n  content: \"\\f270\";\n}\n.am-icon-calendar-plus-o:before {\n  content: \"\\f271\";\n}\n.am-icon-calendar-minus-o:before {\n  content: \"\\f272\";\n}\n.am-icon-calendar-times-o:before {\n  content: \"\\f273\";\n}\n.am-icon-calendar-check-o:before {\n  content: \"\\f274\";\n}\n.am-icon-industry:before {\n  content: \"\\f275\";\n}\n.am-icon-map-pin:before {\n  content: \"\\f276\";\n}\n.am-icon-map-signs:before {\n  content: \"\\f277\";\n}\n.am-icon-map-o:before {\n  content: \"\\f278\";\n}\n.am-icon-map:before {\n  content: \"\\f279\";\n}\n.am-icon-commenting:before {\n  content: \"\\f27a\";\n}\n.am-icon-commenting-o:before {\n  content: \"\\f27b\";\n}\n.am-icon-houzz:before {\n  content: \"\\f27c\";\n}\n.am-icon-vimeo:before {\n  content: \"\\f27d\";\n}\n.am-icon-black-tie:before {\n  content: \"\\f27e\";\n}\n.am-icon-fonticons:before {\n  content: \"\\f280\";\n}\n.am-icon-reddit-alien:before {\n  content: \"\\f281\";\n}\n.am-icon-edge:before {\n  content: \"\\f282\";\n}\n.am-icon-credit-card-alt:before {\n  content: \"\\f283\";\n}\n.am-icon-codiepie:before {\n  content: \"\\f284\";\n}\n.am-icon-modx:before {\n  content: \"\\f285\";\n}\n.am-icon-fort-awesome:before {\n  content: \"\\f286\";\n}\n.am-icon-usb:before {\n  content: \"\\f287\";\n}\n.am-icon-product-hunt:before {\n  content: \"\\f288\";\n}\n.am-icon-mixcloud:before {\n  content: \"\\f289\";\n}\n.am-icon-scribd:before {\n  content: \"\\f28a\";\n}\n.am-icon-pause-circle:before {\n  content: \"\\f28b\";\n}\n.am-icon-pause-circle-o:before {\n  content: \"\\f28c\";\n}\n.am-icon-stop-circle:before {\n  content: \"\\f28d\";\n}\n.am-icon-stop-circle-o:before {\n  content: \"\\f28e\";\n}\n.am-icon-shopping-bag:before {\n  content: \"\\f290\";\n}\n.am-icon-shopping-basket:before {\n  content: \"\\f291\";\n}\n.am-icon-hashtag:before {\n  content: \"\\f292\";\n}\n.am-icon-bluetooth:before {\n  content: \"\\f293\";\n}\n.am-icon-bluetooth-b:before {\n  content: \"\\f294\";\n}\n.am-icon-percent:before {\n  content: \"\\f295\";\n}\n/* Modifier: `am-icon-spin`\n============================================================================= */\n@-webkit-keyframes icon-spin {\n  0% {\n    -webkit-transform: rotate(0deg);\n            transform: rotate(0deg);\n  }\n  100% {\n    -webkit-transform: rotate(359deg);\n            transform: rotate(359deg);\n  }\n}\n@keyframes icon-spin {\n  0% {\n    -webkit-transform: rotate(0deg);\n            transform: rotate(0deg);\n  }\n  100% {\n    -webkit-transform: rotate(359deg);\n            transform: rotate(359deg);\n  }\n}\n.am-icon-spin {\n  -webkit-animation: icon-spin 2s infinite linear;\n          animation: icon-spin 2s infinite linear;\n}\n.am-icon-pulse {\n  -webkit-animation: icon-spin 1s infinite steps(8);\n          animation: icon-spin 1s infinite steps(8);\n}\n.am-icon-ul {\n  padding-left: 0;\n  margin-left: 2.14285714em;\n  list-style-type: none;\n}\n.am-icon-ul > li {\n  position: relative;\n}\n.am-icon-li {\n  position: absolute;\n  left: -2.14285714em;\n  width: 2.14285714em;\n  top: 0.14285714em;\n  text-align: center;\n}\n/* ==========================================================================\n   Component: Input group\n ============================================================================ */\n.am-input-group {\n  position: relative;\n  display: table;\n  border-collapse: separate;\n}\n.am-input-group .am-form-field {\n  position: relative;\n  z-index: 2;\n  float: left;\n  width: 100%;\n  margin-bottom: 0;\n}\n.am-input-group-label,\n.am-input-group-btn,\n.am-input-group .am-form-field {\n  display: table-cell;\n}\n.am-input-group-label:not(:first-child):not(:last-child),\n.am-input-group-btn:not(:first-child):not(:last-child),\n.am-input-group .am-form-field:not(:first-child):not(:last-child) {\n  border-radius: 0;\n}\n.am-input-group-label,\n.am-input-group-btn {\n  width: 1%;\n  white-space: nowrap;\n  vertical-align: middle;\n}\n.am-input-group-label {\n  height: 38px;\n  padding: 0 1em;\n  font-size: 1.6rem;\n  font-weight: normal;\n  line-height: 36px;\n  color: #555555;\n  text-align: center;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n  border-radius: 0;\n}\n.am-input-group-label input[type=\"radio\"],\n.am-input-group-label input[type=\"checkbox\"] {\n  margin-top: 0;\n}\n.am-input-group .am-form-field:first-child,\n.am-input-group-label:first-child,\n.am-input-group-btn:first-child > .am-btn,\n.am-input-group-btn:first-child > .am-btn-group > .am-btn,\n.am-input-group-btn:first-child > .am-dropdown-toggle,\n.am-input-group-btn:last-child > .am-btn:not(:last-child):not(.dropdown-toggle),\n.am-input-group-btn:last-child > .am-btn-group:not(:last-child) > .am-btn {\n  border-bottom-right-radius: 0;\n  border-top-right-radius: 0;\n}\n.am-input-group-label:first-child {\n  border-right: 0;\n}\n.am-input-group .am-form-field:last-child,\n.am-input-group-label:last-child,\n.am-input-group-btn:last-child > .am-btn,\n.am-input-group-btn:last-child > .am-btn-group > .am-btn,\n.am-input-group-btn:last-child > .am-dropdown-toggle,\n.am-input-group-btn:first-child > .am-btn:not(:first-child),\n.am-input-group-btn:first-child > .am-btn-group:not(:first-child) > .am-btn {\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n}\n.am-input-group-label:last-child {\n  border-left: 0;\n}\n.am-input-group-btn {\n  position: relative;\n  font-size: 0;\n  white-space: nowrap;\n}\n.am-input-group-btn > .am-btn {\n  position: relative;\n  border-color: #ccc;\n}\n.am-input-group-btn > .am-btn + .am-btn {\n  margin-left: -1px;\n}\n.am-input-group-btn > .am-btn:hover,\n.am-input-group-btn > .am-btn:focus,\n.am-input-group-btn > .am-btn:active {\n  z-index: 2;\n}\n.am-input-group-btn:first-child > .am-btn,\n.am-input-group-btn:first-child > .am-btn-group {\n  margin-right: -2px;\n}\n.am-input-group-btn:last-child > .am-btn,\n.am-input-group-btn:last-child > .am-btn-group {\n  margin-left: -1px;\n}\n.am-input-group .am-form-field,\n.am-input-group-btn > .am-btn {\n  height: 38px;\n  padding-bottom: auto;\n}\n.am-input-group-lg > .am-form-field,\n.am-input-group-lg > .am-input-group-label,\n.am-input-group-lg > .am-input-group-btn > .am-btn {\n  height: 42px;\n  font-size: 1.8rem !important;\n}\n.am-input-group-lg > .am-input-group-label {\n  line-height: 40px;\n}\n.am-input-group-sm > .am-form-field,\n.am-input-group-sm > .am-input-group-label,\n.am-input-group-sm > .am-input-group-btn > .am-btn {\n  height: 33px;\n  font-size: 1.4rem !important;\n}\n.am-input-group-sm > .am-input-group-label {\n  line-height: 31px;\n}\n.am-input-group-primary .am-input-group-label {\n  background: #0e90d2;\n  color: #fff;\n}\n.am-input-group-primary .am-input-group-label,\n.am-input-group-primary .am-input-group-btn > .am-btn,\n.am-input-group-primary.am-input-group .am-form-field {\n  border-color: #0e90d2;\n}\n.am-input-group-secondary .am-input-group-label {\n  background: #3bb4f2;\n  color: #fff;\n}\n.am-input-group-secondary .am-input-group-label,\n.am-input-group-secondary .am-input-group-btn > .am-btn,\n.am-input-group-secondary.am-input-group .am-form-field {\n  border-color: #3bb4f2;\n}\n.am-input-group-success .am-input-group-label {\n  background: #5eb95e;\n  color: #fff;\n}\n.am-input-group-success .am-input-group-label,\n.am-input-group-success .am-input-group-btn > .am-btn,\n.am-input-group-success.am-input-group .am-form-field {\n  border-color: #5eb95e;\n}\n.am-input-group-warning .am-input-group-label {\n  background: #F37B1D;\n  color: #fff;\n}\n.am-input-group-warning .am-input-group-label,\n.am-input-group-warning .am-input-group-btn > .am-btn,\n.am-input-group-warning.am-input-group .am-form-field {\n  border-color: #F37B1D;\n}\n.am-input-group-danger .am-input-group-label {\n  background: #dd514c;\n  color: #fff;\n}\n.am-input-group-danger .am-input-group-label,\n.am-input-group-danger .am-input-group-btn > .am-btn,\n.am-input-group-danger.am-input-group .am-form-field {\n  border-color: #dd514c;\n}\n/* ==========================================================================\n   Component: List\n ============================================================================ */\n.am-list {\n  margin-bottom: 1.6rem;\n  padding-left: 0;\n}\n.am-list > li {\n  position: relative;\n  display: block;\n  margin-bottom: -1px;\n  background-color: #fff;\n  border: 1px solid #dedede;\n  border-width: 1px 0;\n}\n.am-list > li > a {\n  display: block;\n  padding: 1rem 0;\n}\n.am-list > li > a.am-active,\n.am-list > li > a.am-active:hover,\n.am-list > li > a.am-active:focus {\n  z-index: 2;\n  color: #fff;\n  background-color: #0e90d2;\n  border-color: #0e90d2;\n}\n.am-list > li > a.am-active .am-list-item-heading,\n.am-list > li > a.am-active:hover .am-list-item-heading,\n.am-list > li > a.am-active:focus .am-list-item-heading {\n  color: inherit;\n}\n.am-list > li > a.am-active .am-list-item-text,\n.am-list > li > a.am-active:hover .am-list-item-text,\n.am-list > li > a.am-active:focus .am-list-item-text {\n  color: #b2e2fa;\n}\n.am-list > li > .am-badge {\n  float: right;\n}\n.am-list > li > .am-badge + .am-badge {\n  margin-right: 5px;\n}\n/* Pure text list */\n.am-list-static > li {\n  padding: .8rem .2rem;\n}\n.am-list-static.am-list-border > li {\n  padding: 1rem;\n}\n/* with border */\n.am-list-border > li,\n.am-list-bordered > li {\n  border-width: 1px;\n}\n.am-list-border > li:first-child,\n.am-list-bordered > li:first-child,\n.am-list-border > li:first-child > a,\n.am-list-bordered > li:first-child > a {\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n.am-list-border > li:last-child,\n.am-list-bordered > li:last-child,\n.am-list-border > li:last-child > a,\n.am-list-bordered > li:last-child > a {\n  margin-bottom: 0;\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n.am-list-border > li > a,\n.am-list-bordered > li > a {\n  padding: 1rem;\n}\n.am-list-border > li > a:hover,\n.am-list-bordered > li > a:hover,\n.am-list-border > li > a:focus,\n.am-list-bordered > li > a:focus {\n  background-color: #f5f5f5;\n}\n/* Striped */\n.am-list-striped > li:nth-of-type(even) {\n  background: #f5f5f5;\n}\n.am-list-item-hd {\n  margin-top: 0;\n}\n.am-list-item-text {\n  line-height: 1.4;\n  font-size: 1.3rem;\n  color: #999999;\n  margin: 0;\n}\n/* ==========================================================================\n   Component: Panel\n ============================================================================ */\n.am-panel {\n  margin-bottom: 20px;\n  background-color: #fff;\n  border: 1px solid transparent;\n  border-radius: 0;\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/* Panel header */\n.am-panel-hd {\n  padding: 0.6rem 1.25rem;\n  border-bottom: 1px solid transparent;\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n/* Panel content */\n.am-panel-bd {\n  padding: 1.25rem;\n}\n.am-panel-title {\n  margin: 0;\n  font-size: 100%;\n  color: inherit;\n}\n.am-panel-title > a {\n  color: inherit;\n}\n/* Panel footer */\n.am-panel-footer {\n  padding: 0.6rem 1.25rem;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n.am-panel-default {\n  border-color: #ddd;\n}\n.am-panel-default > .am-panel-hd {\n  color: #444;\n  background-color: #f5f5f5;\n  border-color: #ddd;\n}\n.am-panel-default > .am-panel-hd + .am-panel-collapse > .am-panel-bd {\n  border-top-color: #ddd;\n}\n.am-panel-default > .am-panel-footer + .am-panel-collapse > .am-panel-bd {\n  border-bottom-color: #ddd;\n}\n.am-panel-primary {\n  border-color: #10a0ea;\n}\n.am-panel-primary > .am-panel-hd {\n  color: #fff;\n  background-color: #0e90d2;\n  border-color: #10a0ea;\n}\n.am-panel-primary > .am-panel-hd + .am-panel-collapse > .am-panel-bd {\n  border-top-color: #10a0ea;\n}\n.am-panel-primary > .am-panel-footer + .am-panel-collapse > .am-panel-bd {\n  border-bottom-color: #10a0ea;\n}\n.am-panel-secondary {\n  border-color: #caebfb;\n}\n.am-panel-secondary > .am-panel-hd {\n  color: #14a6ef;\n  background-color: rgba(59, 180, 242, 0.15);\n  border-color: #caebfb;\n}\n.am-panel-secondary > .am-panel-hd + .am-panel-collapse > .am-panel-bd {\n  border-top-color: #caebfb;\n}\n.am-panel-secondary > .am-panel-footer + .am-panel-collapse > .am-panel-bd {\n  border-bottom-color: #caebfb;\n}\n.am-panel-success {\n  border-color: #c9e7c9;\n}\n.am-panel-success > .am-panel-hd {\n  color: #5eb95e;\n  background-color: rgba(94, 185, 94, 0.15);\n  border-color: #c9e7c9;\n}\n.am-panel-success > .am-panel-hd + .am-panel-collapse > .am-panel-bd {\n  border-top-color: #c9e7c9;\n}\n.am-panel-success > .am-panel-footer + .am-panel-collapse > .am-panel-bd {\n  border-bottom-color: #c9e7c9;\n}\n.am-panel-warning {\n  border-color: #fbd0ae;\n}\n.am-panel-warning > .am-panel-hd {\n  color: #F37B1D;\n  background-color: rgba(243, 123, 29, 0.15);\n  border-color: #fbd0ae;\n}\n.am-panel-warning > .am-panel-hd + .am-panel-collapse > .am-panel-bd {\n  border-top-color: #fbd0ae;\n}\n.am-panel-warning > .am-panel-footer + .am-panel-collapse > .am-panel-bd {\n  border-bottom-color: #fbd0ae;\n}\n.am-panel-danger {\n  border-color: #f5cecd;\n}\n.am-panel-danger > .am-panel-hd {\n  color: #dd514c;\n  background-color: rgba(221, 81, 76, 0.15);\n  border-color: #f5cecd;\n}\n.am-panel-danger > .am-panel-hd + .am-panel-collapse > .am-panel-bd {\n  border-top-color: #f5cecd;\n}\n.am-panel-danger > .am-panel-footer + .am-panel-collapse > .am-panel-bd {\n  border-bottom-color: #f5cecd;\n}\n.am-panel > .am-table {\n  margin-bottom: 0;\n}\n.am-panel > .am-table:first-child {\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n.am-panel > .am-table:first-child > thead:first-child > tr:first-child td:first-child,\n.am-panel > .am-table:first-child > tbody:first-child > tr:first-child td:first-child,\n.am-panel > .am-table:first-child > thead:first-child > tr:first-child th:first-child,\n.am-panel > .am-table:first-child > tbody:first-child > tr:first-child th:first-child {\n  border-top-left-radius: 0;\n}\n.am-panel > .am-table:first-child > thead:first-child > tr:first-child td:last-child,\n.am-panel > .am-table:first-child > tbody:first-child > tr:first-child td:last-child,\n.am-panel > .am-table:first-child > thead:first-child > tr:first-child th:last-child,\n.am-panel > .am-table:first-child > tbody:first-child > tr:first-child th:last-child {\n  border-top-right-radius: 0;\n}\n.am-panel > .am-table:last-child {\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n.am-panel > .am-table:last-child > tbody:last-child > tr:last-child td:first-child,\n.am-panel > .am-table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.am-panel > .am-table:last-child > tbody:last-child > tr:last-child th:first-child,\n.am-panel > .am-table:last-child > tfoot:last-child > tr:last-child th:first-child {\n  border-bottom-left-radius: 0;\n}\n.am-panel > .am-table:last-child > tbody:last-child > tr:last-child td:last-child,\n.am-panel > .am-table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.am-panel > .am-table:last-child > tbody:last-child > tr:last-child th:last-child,\n.am-panel > .am-table:last-child > tfoot:last-child > tr:last-child th:last-child {\n  border-bottom-right-radius: 0;\n}\n.am-panel > .am-panel-bd + .am-table {\n  border-top: 1px solid #ddd;\n}\n.am-panel > .am-table > tbody:first-child > tr:first-child th,\n.am-panel > .am-table > tbody:first-child > tr:first-child td {\n  border-top: 0;\n}\n.am-panel > .am-table-bd {\n  border: 0;\n}\n.am-panel > .am-table-bd > thead > tr > th:first-child,\n.am-panel > .am-table-bd > tbody > tr > th:first-child,\n.am-panel > .am-table-bd > tfoot > tr > th:first-child,\n.am-panel > .am-table-bd > thead > tr > td:first-child,\n.am-panel > .am-table-bd > tbody > tr > td:first-child,\n.am-panel > .am-table-bd > tfoot > tr > td:first-child {\n  border-left: 0;\n}\n.am-panel > .am-table-bd > thead > tr > th:last-child,\n.am-panel > .am-table-bd > tbody > tr > th:last-child,\n.am-panel > .am-table-bd > tfoot > tr > th:last-child,\n.am-panel > .am-table-bd > thead > tr > td:last-child,\n.am-panel > .am-table-bd > tbody > tr > td:last-child,\n.am-panel > .am-table-bd > tfoot > tr > td:last-child {\n  border-right: 0;\n}\n.am-panel > .am-table-bd > thead > tr:first-child > td,\n.am-panel > .am-table-bd > tbody > tr:first-child > td,\n.am-panel > .am-table-bd > thead > tr:first-child > th,\n.am-panel > .am-table-bd > tbody > tr:first-child > th {\n  border-bottom: 0;\n}\n.am-panel > .am-table-bd > tbody > tr:last-child > td,\n.am-panel > .am-table-bd > tfoot > tr:last-child > td,\n.am-panel > .am-table-bd > tbody > tr:last-child > th,\n.am-panel > .am-table-bd > tfoot > tr:last-child > th {\n  border-bottom: 0;\n}\n/* Wrap list */\n.am-panel > .am-list {\n  margin: 0;\n}\n.am-panel > .am-list > li > a {\n  padding-left: 1rem;\n  padding-right: 1rem;\n}\n.am-panel > .am-list-static li {\n  padding-left: 1rem;\n  padding-right: 1rem;\n}\n/* Panel group */\n.am-panel-group {\n  margin-bottom: 2rem;\n}\n.am-panel-group .am-panel {\n  margin-bottom: 0;\n  border-radius: 0;\n}\n.am-panel-group .am-panel + .am-panel {\n  margin-top: 6px;\n}\n.am-panel-group .am-panel-hd {\n  border-bottom: 0;\n}\n.am-panel-group .am-panel-hd + .am-panel-collapse .am-panel-bd {\n  border-top: 1px solid #ddd;\n}\n.am-panel-group .am-panel-footer {\n  border-top: 0;\n}\n.am-panel-group .am-panel-footer + .am-panel-collapse .am-panel-bd {\n  border-bottom: 1px solid #ddd;\n}\n/* ==========================================================================\n   Component: Progress\n ============================================================================ */\n/* Progress bar animation */\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 36px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 36px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n/*  Progress container */\n.am-progress {\n  overflow: hidden;\n  height: 2rem;\n  margin-bottom: 2rem;\n  background-color: #f5f5f5;\n  border-radius: 0;\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/* Progress bar */\n.am-progress-bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 1.2rem;\n  line-height: 2rem;\n  color: #fff;\n  text-align: center;\n  background-color: #0e90d2;\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 .6s ease;\n  transition: width .6s ease;\n}\n.am-progress-striped .am-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: 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  -webkit-background-size: 36px 36px;\n          background-size: 36px 36px;\n}\n.am-progress.am-active .am-progress-bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n.am-progress-bar[aria-valuenow=\"1\"],\n.am-progress-bar[aria-valuenow=\"2\"] {\n  min-width: 30px;\n}\n.am-progress-bar[aria-valuenow=\"0\"] {\n  color: #999999;\n  min-width: 30px;\n  background: none;\n  -webkit-box-shadow: none;\n          box-shadow: none;\n}\n.am-progress-bar-secondary {\n  background-color: #3bb4f2;\n}\n.am-progress-striped .am-progress-bar-secondary {\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: 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.am-progress-bar-success {\n  background-color: #5eb95e;\n}\n.am-progress-striped .am-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: 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.am-progress-bar-warning {\n  background-color: #F37B1D;\n}\n.am-progress-striped .am-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: 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.am-progress-bar-danger {\n  background-color: #dd514c;\n}\n.am-progress-striped .am-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: 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.am-progress-xs {\n  height: 0.6rem;\n}\n.am-progress-sm {\n  height: 1.2rem;\n}\n/* ==========================================================================\n   Component: Thumbnail\n ============================================================================ */\n.am-thumbnail {\n  display: block;\n  padding: 2px;\n  margin-bottom: 2rem;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  border-radius: 0;\n  -webkit-transition: all 0.2s ease-in-out;\n  transition: all 0.2s ease-in-out;\n}\n.am-thumbnail > img,\n.am-thumbnail a > img {\n  margin-left: auto;\n  margin-right: auto;\n  display: block;\n}\n.am-thumbnail a.am-thumbnail:hover,\n.am-thumbnail a.am-thumbnail:focus,\n.am-thumbnail a.am-thumbnail.active {\n  border-color: #0e90d2;\n  background-color: #fff;\n}\nimg.am-thumbnail,\n.am-thumbnail > img,\n.am-thumbnail a > img {\n  max-width: 100%;\n  height: auto;\n}\n/* Image caption */\n.am-thumbnail-caption {\n  margin: 0;\n  padding: 0.8rem;\n  color: #333;\n  font-weight: normal;\n}\n.am-thumbnail-caption *:last-child {\n  margin-bottom: 0;\n}\n.am-thumbnails {\n  margin-left: -0.5rem;\n  margin-right: -0.5rem;\n}\n.am-thumbnails > li {\n  padding: 0 .5rem 1rem .5rem;\n}\n/* ==========================================================================\n   Component: Utility\n ============================================================================ */\n.am-scrollable-horizontal {\n  width: 100%;\n  overflow-y: hidden;\n  overflow-x: auto;\n  -ms-overflow-style: -ms-autohiding-scrollbar;\n  -webkit-overflow-scrolling: touch;\n}\n.am-scrollable-vertical {\n  height: 240px;\n  overflow-y: scroll;\n  -webkit-overflow-scrolling: touch;\n  resize: vertical;\n}\n/* Border-radius*/\n.am-square {\n  border-radius: 0;\n}\n.am-radius {\n  border-radius: 2px;\n}\n.am-round {\n  border-radius: 1000px;\n}\n.am-circle {\n  border-radius: 50%;\n}\n/* Float blocks*/\n.am-cf:before,\n.am-cf:after {\n  content: \" \";\n  display: table;\n}\n.am-cf:after {\n  clear: both;\n}\n.am-fl {\n  float: left;\n}\n.am-fr {\n  float: right;\n}\n.am-nbfc {\n  overflow: hidden;\n}\n.am-center {\n  display: block;\n  margin-left: auto;\n  margin-right: auto;\n}\n/* Display */\n.am-block {\n  display: block !important;\n}\n.am-inline {\n  display: inline !important;\n}\n.am-inline-block {\n  display: inline-block !important;\n}\n.am-hide {\n  display: none !important;\n  visibility: hidden !important;\n}\n/*\n* Remove whitespace between child elements when using `inline-block`\n*/\n.am-vertical-align {\n  font-size: 0.001px;\n}\n/*\n* The `@{ns}vertical-align` container needs a specific height\n*/\n.am-vertical-align:before {\n  content: '';\n  display: inline-block;\n  height: 100%;\n  vertical-align: middle;\n}\n/*\n* Sub-object which can have any height\n* 1. Reset whitespace hack\n*/\n.am-vertical-align-middle,\n.am-vertical-align-bottom {\n  display: inline-block;\n  font-size: 1.6rem;\n  /* 1 */\n  max-width: 100%;\n}\n.am-vertical-align-middle {\n  vertical-align: middle;\n}\n.am-vertical-align-bottom {\n  vertical-align: bottom;\n}\n.am-responsive-width {\n  -webkit-box-sizing: border-box;\n          box-sizing: border-box;\n  max-width: 100%;\n  height: auto;\n}\n/* Margin helpers */\n.am-margin {\n  margin: 1.6rem;\n}\n.am-margin-0 {\n  margin: 0!important;\n}\n.am-margin-xs {\n  margin: 0.5rem;\n}\n.am-margin-sm {\n  margin: 1rem;\n}\n.am-margin-lg {\n  margin: 2.4rem;\n}\n.am-margin-xl {\n  margin: 3.2rem;\n}\n.am-margin-horizontal {\n  margin-left: 1.6rem;\n  margin-right: 1.6rem;\n}\n.am-margin-horizontal-0 {\n  margin-left: 0!important;\n  margin-right: 0!important;\n}\n.am-margin-horizontal-xs {\n  margin-left: 0.5rem;\n  margin-right: 0.5rem;\n}\n.am-margin-horizontal-sm {\n  margin-left: 1rem;\n  margin-right: 1rem;\n}\n.am-margin-horizontal-lg {\n  margin-left: 2.4rem;\n  margin-right: 2.4rem;\n}\n.am-margin-horizontal-xl {\n  margin-left: 3.2rem;\n  margin-right: 3.2rem;\n}\n.am-margin-vertical {\n  margin-top: 1.6rem;\n  margin-bottom: 1.6rem;\n}\n.am-margin-vertical-0 {\n  margin-top: 0!important;\n  margin-bottom: 0!important;\n}\n.am-margin-vertical-xs {\n  margin-top: 0.5rem;\n  margin-bottom: 0.5rem;\n}\n.am-margin-vertical-sm {\n  margin-top: 1rem;\n  margin-bottom: 1rem;\n}\n.am-margin-vertical-lg {\n  margin-top: 2.4rem;\n  margin-bottom: 2.4rem;\n}\n.am-margin-vertical-xl {\n  margin-top: 3.2rem;\n  margin-bottom: 3.2rem;\n}\n.am-margin-top {\n  margin-top: 1.6rem;\n}\n.am-margin-top-0 {\n  margin-top: 0!important;\n}\n.am-margin-top-xs {\n  margin-top: 0.5rem;\n}\n.am-margin-top-sm {\n  margin-top: 1rem;\n}\n.am-margin-top-lg {\n  margin-top: 2.4rem;\n}\n.am-margin-top-xl {\n  margin-top: 3.2rem;\n}\n.am-margin-bottom {\n  margin-bottom: 1.6rem;\n}\n.am-margin-bottom-0 {\n  margin-bottom: 0!important;\n}\n.am-margin-bottom-xs {\n  margin-bottom: 0.5rem;\n}\n.am-margin-bottom-sm {\n  margin-bottom: 1rem;\n}\n.am-margin-bottom-lg {\n  margin-bottom: 2.4rem;\n}\n.am-margin-bottom-xl {\n  margin-bottom: 3.2rem;\n}\n.am-margin-left {\n  margin-left: 1.6rem;\n}\n.am-margin-left-0 {\n  margin-left: 0!important;\n}\n.am-margin-left-xs {\n  margin-left: 0.5rem;\n}\n.am-margin-left-sm {\n  margin-left: 1rem;\n}\n.am-margin-left-lg {\n  margin-left: 2.4rem;\n}\n.am-margin-left-xl {\n  margin-left: 3.2rem;\n}\n.am-margin-right {\n  margin-right: 1.6rem;\n}\n.am-margin-right-0 {\n  margin-right: 0!important;\n}\n.am-margin-right-xs {\n  margin-right: 0.5rem;\n}\n.am-margin-right-sm {\n  margin-right: 1rem;\n}\n.am-margin-right-lg {\n  margin-right: 2.4rem;\n}\n.am-margin-right-xl {\n  margin-right: 3.2rem;\n}\n/* Padding helpers */\n.am-padding {\n  padding: 1.6rem;\n}\n.am-padding-0 {\n  padding: 0!important;\n}\n.am-padding-xs {\n  padding: 0.5rem;\n}\n.am-padding-sm {\n  padding: 1rem;\n}\n.am-padding-lg {\n  padding: 2.4rem;\n}\n.am-padding-xl {\n  padding: 3.2rem;\n}\n.am-padding-horizontal {\n  padding-left: 1.6rem;\n  padding-right: 1.6rem;\n}\n.am-padding-horizontal-0 {\n  padding-left: 0!important;\n  padding-right: 0!important;\n}\n.am-padding-horizontal-xs {\n  padding-left: 0.5rem;\n  padding-right: 0.5rem;\n}\n.am-padding-horizontal-sm {\n  padding-left: 1rem;\n  padding-right: 1rem;\n}\n.am-padding-horizontal-lg {\n  padding-left: 2.4rem;\n  padding-right: 2.4rem;\n}\n.am-padding-horizontal-xl {\n  padding-left: 3.2rem;\n  padding-right: 3.2rem;\n}\n.am-padding-vertical {\n  padding-top: 1.6rem;\n  padding-bottom: 1.6rem;\n}\n.am-padding-vertical-0 {\n  padding-top: 0!important;\n  padding-bottom: 0!important;\n}\n.am-padding-vertical-xs {\n  padding-top: 0.5rem;\n  padding-bottom: 0.5rem;\n}\n.am-padding-vertical-sm {\n  padding-top: 1rem;\n  padding-bottom: 1rem;\n}\n.am-padding-vertical-lg {\n  padding-top: 2.4rem;\n  padding-bottom: 2.4rem;\n}\n.am-padding-vertical-xl {\n  padding-top: 3.2rem;\n  padding-bottom: 3.2rem;\n}\n.am-padding-top {\n  padding-top: 1.6rem;\n}\n.am-padding-top-0 {\n  padding-top: 0!important;\n}\n.am-padding-top-xs {\n  padding-top: 0.5rem;\n}\n.am-padding-top-sm {\n  padding-top: 1rem;\n}\n.am-padding-top-lg {\n  padding-top: 2.4rem;\n}\n.am-padding-top-xl {\n  padding-top: 3.2rem;\n}\n.am-padding-bottom {\n  padding-bottom: 1.6rem;\n}\n.am-padding-bottom-0 {\n  padding-bottom: 0!important;\n}\n.am-padding-bottom-xs {\n  padding-bottom: 0.5rem;\n}\n.am-padding-bottom-sm {\n  padding-bottom: 1rem;\n}\n.am-padding-bottom-lg {\n  padding-bottom: 2.4rem;\n}\n.am-padding-bottom-xl {\n  padding-bottom: 3.2rem;\n}\n.am-padding-left {\n  padding-left: 1.6rem;\n}\n.am-padding-left-0 {\n  padding-left: 0!important;\n}\n.am-padding-left-xs {\n  padding-left: 0.5rem;\n}\n.am-padding-left-sm {\n  padding-left: 1rem;\n}\n.am-padding-left-lg {\n  padding-left: 2.4rem;\n}\n.am-padding-left-xl {\n  padding-left: 3.2rem;\n}\n.am-padding-right {\n  padding-right: 1.6rem;\n}\n.am-padding-right-0 {\n  padding-right: 0!important;\n}\n.am-padding-right-xs {\n  padding-right: 0.5rem;\n}\n.am-padding-right-sm {\n  padding-right: 1rem;\n}\n.am-padding-right-lg {\n  padding-right: 2.4rem;\n}\n.am-padding-right-xl {\n  padding-right: 3.2rem;\n}\n/* small displays */\n@media only screen {\n  .am-show-sm-only,\n  .am-show-sm-up,\n  .am-show-sm,\n  .am-show-sm-down,\n  .am-hide-md-only,\n  .am-hide-md-up,\n  .am-hide-md,\n  .am-show-md-down,\n  .am-hide-lg-only,\n  .am-hide-lg-up,\n  .am-hide-lg,\n  .am-show-lg-down {\n    display: inherit !important;\n  }\n  .am-hide-sm-only,\n  .am-hide-sm-up,\n  .am-hide-sm,\n  .am-hide-sm-down,\n  .am-show-md-only,\n  .am-show-md-up,\n  .am-show-md,\n  .am-hide-md-down,\n  .am-show-lg-only,\n  .am-show-lg-up,\n  .am-show-lg,\n  .am-hide-lg-down {\n    display: none !important;\n  }\n  /* table */\n  table.am-show-sm-only,\n  table.am-show-sm-up,\n  table.am-show-sm,\n  table.am-show-sm-down,\n  table.am-hide-md-only,\n  table.am-hide-md-up,\n  table.am-hide-md,\n  table.am-show-md-down,\n  table.am-hide-lg-only,\n  table.am-hide-lg-up,\n  table.am-hide-lg,\n  table.am-show-lg-down {\n    display: table !important;\n  }\n  thead.am-show-sm-only,\n  thead.am-show-sm-up,\n  thead.am-show-sm,\n  thead.am-show-sm-down,\n  thead.am-hide-md-only,\n  thead.am-hide-md-up,\n  thead.am-hide-md,\n  thead.am-show-md-down,\n  thead.am-hide-lg-only,\n  thead.am-hide-lg-up,\n  thead.am-hide-lg,\n  thead.am-show-lg-down {\n    display: table-header-group !important;\n  }\n  tbody.am-show-sm-only,\n  tbody.am-show-sm-up,\n  tbody.am-show-sm,\n  tbody.am-show-sm-down,\n  tbody.am-hide-md-only,\n  tbody.am-hide-md-up,\n  tbody.am-hide-md,\n  tbody.am-show-md-down,\n  tbody.am-hide-lg-only,\n  tbody.am-hide-lg-up,\n  tbody.am-hide-lg,\n  tbody.am-show-lg-down {\n    display: table-row-group !important;\n  }\n  tr.am-show-sm-only,\n  tr.am-show-sm-up,\n  tr.am-show-sm,\n  tr.am-show-sm-down,\n  tr.am-hide-md-only,\n  tr.am-hide-md-up,\n  tr.am-hide-md,\n  tr.am-show-md-down,\n  tr.am-hide-lg-only,\n  tr.am-hide-lg-up,\n  tr.am-hide-lg,\n  tr.am-show-lg-down {\n    display: table-row !important;\n  }\n  th.am-show-sm-only,\n  td.am-show-sm-only,\n  th.am-show-sm-up,\n  td.am-show-sm-up,\n  th.am-show-sm,\n  td.am-show-sm,\n  th.am-show-sm-down,\n  td.am-show-sm-down,\n  th.am-hide-md-only,\n  td.am-hide-md-only,\n  th.am-hide-md-up,\n  td.am-hide-md-up,\n  th.am-hide-md,\n  td.am-hide-md,\n  th.am-show-md-down,\n  td.am-show-md-down,\n  th.am-hide-lg-only,\n  td.am-hide-lg-only,\n  th.am-hide-lg-up,\n  td.am-hide-lg-up,\n  th.am-hide-lg,\n  td.am-hide-lg,\n  th.am-show-lg-down,\n  td.am-show-lg-down {\n    display: table-cell !important;\n  }\n}\n/* medium displays */\n@media only screen and (min-width:641px) {\n  .am-hide-sm-only,\n  .am-show-sm-up,\n  .am-hide-sm,\n  .am-hide-sm-down,\n  .am-show-md-only,\n  .am-show-md-up,\n  .am-show-md,\n  .am-show-md-down,\n  .am-hide-lg-only,\n  .am-hide-lg-up,\n  .am-hide-lg,\n  .am-show-lg-down {\n    display: inherit !important;\n  }\n  .am-show-sm-only,\n  .am-hide-sm-up,\n  .am-show-sm,\n  .am-show-sm-down,\n  .am-hide-md-only,\n  .am-hide-md-up,\n  .am-hide-md,\n  .am-hide-md-down,\n  .am-show-lg-only,\n  .am-show-lg-up,\n  .am-show-lg,\n  .am-hide-lg-down {\n    display: none !important;\n  }\n  table.am-hide-sm-only,\n  table.am-show-sm-up,\n  table.am-hide-sm,\n  table.am-hide-sm-down,\n  table.am-show-md-only,\n  table.am-show-md-up,\n  table.am-show-md,\n  table.am-show-md-down,\n  table.am-hide-lg-only,\n  table.am-hide-lg-up,\n  table.am-hide-lg,\n  table.am-show-lg-down {\n    display: table !important;\n  }\n  thead.am-hide-sm-only,\n  thead.am-show-sm-up,\n  thead.am-hide-sm,\n  thead.am-hide-sm-down,\n  thead.am-show-md-only,\n  thead.am-show-md-up,\n  thead.am-show-md,\n  thead.am-show-md-down,\n  thead.am-hide-lg-only,\n  thead.am-hide-lg-up,\n  thead.am-hide-lg,\n  thead.am-show-lg-down {\n    display: table-header-group !important;\n  }\n  tbody.am-hide-sm-only,\n  tbody.am-show-sm-up,\n  tbody.am-hide-sm,\n  tbody.am-hide-sm-down,\n  tbody.am-show-md-only,\n  tbody.am-show-md-up,\n  tbody.am-show-md,\n  tbody.am-show-md-down,\n  tbody.am-hide-lg-only,\n  tbody.am-hide-lg-up,\n  tbody.am-hide-lg,\n  tbody.am-show-lg-down {\n    display: table-row-group !important;\n  }\n  tr.am-hide-sm-only,\n  tr.am-show-sm-up,\n  tr.am-hide-sm,\n  tr.am-hide-sm-down,\n  tr.am-show-md-only,\n  tr.am-show-md-up,\n  tr.am-show-md,\n  tr.am-show-md-down,\n  tr.am-hide-lg-only,\n  tr.am-hide-lg-up,\n  tr.am-hide-lg,\n  tr.am-show-lg-down {\n    display: table-row !important;\n  }\n  th.am-hide-sm-only,\n  td.am-hide-sm-only,\n  th.am-show-sm-up,\n  td.am-show-sm-up,\n  th.am-hide-sm,\n  td.am-hide-sm,\n  th.am-hide-sm-down,\n  td.am-hide-sm-down,\n  th.am-show-md-only,\n  td.am-show-md-only,\n  th.am-show-md-up,\n  td.am-show-md-up,\n  th.am-show-md,\n  td.am-show-md,\n  th.am-show-md-down,\n  td.am-show-md-down,\n  th.am-hide-lg-only,\n  td.am-hide-lg-only,\n  th.am-hide-lg-up,\n  td.am-hide-lg-up,\n  th.am-hide-lg,\n  td.am-hide-lg,\n  th.am-show-lg-down,\n  td.am-show-lg-down {\n    display: table-cell !important;\n  }\n}\n/* large displays */\n@media only screen and (min-width:1025px) {\n  .am-hide-sm-only,\n  .am-show-sm-up,\n  .am-hide-sm,\n  .am-hide-sm-down,\n  .am-hide-md-only,\n  .am-show-md-up,\n  .am-hide-md,\n  .am-hide-md-down,\n  .am-show-lg-only,\n  .am-show-lg-up,\n  .am-show-lg,\n  .am-show-lg-down {\n    display: inherit !important;\n  }\n  .am-show-sm-only,\n  .am-hide-sm-up,\n  .am-show-sm,\n  .am-show-sm-down,\n  .am-show-md-only,\n  .am-hide-md-up,\n  .am-show-md,\n  .am-show-md-down,\n  .am-hide-lg-only,\n  .am-hide-lg-up,\n  .am-hide-lg,\n  .am-hide-lg-down {\n    display: none !important;\n  }\n  table.am-hide-sm-only,\n  table.am-show-sm-up,\n  table.am-hide-sm,\n  table.am-hide-sm-down,\n  table.am-hide-md-only,\n  table.am-show-md-up,\n  table.am-hide-md,\n  table.am-hide-md-down,\n  table.am-show-lg-only,\n  table.am-show-lg-up,\n  table.am-show-lg,\n  table.am-show-lg-down {\n    display: table !important;\n  }\n  thead.am-hide-sm-only,\n  thead.am-show-sm-up,\n  thead.am-hide-sm,\n  thead.am-hide-sm-down,\n  thead.am-hide-md-only,\n  thead.am-show-md-up,\n  thead.am-hide-md,\n  thead.am-hide-md-down,\n  thead.am-show-lg-only,\n  thead.am-show-lg-up,\n  thead.am-show-lg,\n  thead.am-show-lg-down {\n    display: table-header-group !important;\n  }\n  tbody.am-hide-sm-only,\n  tbody.am-show-sm-up,\n  tbody.am-hide-sm,\n  tbody.am-hide-sm-down,\n  tbody.am-hide-md-only,\n  tbody.am-show-md-up,\n  tbody.am-hide-md,\n  tbody.am-hide-md-down,\n  tbody.am-show-lg-only,\n  tbody.am-show-lg-up,\n  tbody.am-show-lg,\n  tbody.am-show-lg-down {\n    display: table-row-group !important;\n  }\n  tr.am-hide-sm-only,\n  tr.am-show-sm-up,\n  tr.am-hide-sm,\n  tr.am-hide-sm-down,\n  tr.am-hide-md-only,\n  tr.am-show-md-up,\n  tr.am-hide-md,\n  tr.am-hide-md-down,\n  tr.am-show-lg-only,\n  tr.am-show-lg-up,\n  tr.am-show-lg,\n  tr.am-show-lg-down {\n    display: table-row !important;\n  }\n  th.am-hide-sm-only,\n  td.am-hide-sm-only,\n  th.am-show-sm-up,\n  td.am-show-sm-up,\n  th.am-hide-sm,\n  td.am-hide-sm,\n  th.am-hide-sm-down,\n  td.am-hide-sm-down,\n  th.am-hide-md-only,\n  td.am-hide-md-only,\n  th.am-show-md-up,\n  td.am-show-md-up,\n  th.am-hide-md,\n  td.am-hide-md,\n  th.am-hide-md-down,\n  td.am-hide-md-down,\n  th.am-show-lg-only,\n  td.am-show-lg-only,\n  th.am-show-lg-up,\n  td.am-show-lg-up,\n  th.am-show-lg,\n  td.am-show-lg,\n  th.am-show-lg-down,\n  td.am-show-lg-down {\n    display: table-cell !important;\n  }\n}\n@media only screen and (orientation: landscape) {\n  .am-show-landscape,\n  .am-hide-portrait {\n    display: inherit !important;\n  }\n  .am-hide-landscape,\n  .am-show-portrait {\n    display: none !important;\n  }\n}\n@media only screen and (orientation: portrait) {\n  .am-show-portrait,\n  .am-hide-landscape {\n    display: inherit !important;\n  }\n  .am-hide-portrait,\n  .am-show-landscape {\n    display: none !important;\n  }\n}\n.am-sans-serif {\n  font-family: \"Segoe UI\", \"Lucida Grande\", Helvetica, Arial, \"Microsoft YaHei\", FreeSans, Arimo, \"Droid Sans\", \"wenquanyi micro hei\", \"Hiragino Sans GB\", \"Hiragino Sans GB W3\", \"FontAwesome\", sans-serif;\n}\n.am-serif {\n  font-family: Georgia, \"Times New Roman\", Times, SimSun, \"FontAwesome\", serif;\n}\n.am-kai {\n  font-family: Georgia, \"Times New Roman\", Times, Kai, \"Kaiti SC\", KaiTi, BiauKai, \"FontAwesome\", serif;\n}\n.am-monospace {\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", \"FontAwesome\", monospace;\n}\n.am-text-primary {\n  color: #0e90d2;\n}\n.am-text-secondary {\n  color: #3bb4f2;\n}\n.am-text-success {\n  color: #5eb95e;\n}\n.am-text-warning {\n  color: #F37B1D;\n}\n.am-text-danger {\n  color: #dd514c;\n}\n.am-link-muted {\n  color: #666;\n}\n.am-link-muted a {\n  color: #666;\n}\n.am-link-muted:hover,\n.am-link-muted a:hover {\n  color: #555;\n}\n.am-text-default {\n  font-size: 1.6rem;\n}\n/*\n.@{ns}text-xxs {\n  font-size: @font-size-xxs;\n}\n*/\n.am-text-xs {\n  font-size: 1.2rem;\n}\n.am-text-sm {\n  font-size: 1.4rem;\n}\n.am-text-lg {\n  font-size: 1.8rem;\n}\n.am-text-xl {\n  font-size: 2.4rem;\n}\n.am-text-xxl {\n  font-size: 3.2rem;\n}\n.am-text-xxxl {\n  font-size: 4.2rem;\n}\n.am-ellipsis,\n.am-text-truncate {\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-text-break {\n  word-wrap: break-word;\n  -webkit-hyphens: auto;\n  -ms-hyphens: auto;\n  -moz-hyphens: auto;\n  hyphens: auto;\n}\n.am-text-nowrap {\n  white-space: nowrap;\n}\n[class*='am-align-'] {\n  margin-bottom: 1rem;\n}\n.am-align-left {\n  margin-right: 1rem;\n  float: left;\n}\n.am-align-right {\n  margin-left: 1rem;\n  float: right;\n}\n/** Only display content to screen readers\n * See: http://a11yproject.com/posts/how-to-hide-content/\n */\n.am-sr-only {\n  position: absolute;\n  width: 1px;\n  height: 1px;\n  margin: -1px;\n  padding: 0;\n  overflow: hidden;\n  clip: rect(0, 0, 0, 0);\n  border: 0;\n}\n/* Text Image Replacement */\n.am-text-ir {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n/* Text align */\n@media only screen {\n  .am-text-left {\n    text-align: left !important;\n  }\n  .am-text-right {\n    text-align: right !important;\n  }\n  .am-text-center {\n    text-align: center !important;\n  }\n  .am-text-justify {\n    text-align: justify !important;\n  }\n}\n@media only screen and (max-width: 640px) {\n  .am-sm-only-text-left {\n    text-align: left !important;\n  }\n  .am-sm-only-text-right {\n    text-align: right !important;\n  }\n  .am-sm-only-text-center {\n    text-align: center !important;\n  }\n  .am-sm-only-text-justify {\n    text-align: justify !important;\n  }\n}\n@media only screen and (min-width:641px) and (max-width:1024px) {\n  .am-md-only-text-left {\n    text-align: left !important;\n  }\n  .am-md-only-text-right {\n    text-align: right !important;\n  }\n  .am-md-only-text-center {\n    text-align: center !important;\n  }\n  .am-md-only-text-justify {\n    text-align: justify !important;\n  }\n}\n@media only screen and (min-width:641px) {\n  .am-md-text-left {\n    text-align: left !important;\n  }\n  .am-md-text-right {\n    text-align: right !important;\n  }\n  .am-md-text-center {\n    text-align: center !important;\n  }\n  .am-md-text-justify {\n    text-align: justify !important;\n  }\n}\n@media only screen and (min-width:1025px) {\n  .am-lg-text-left {\n    text-align: left !important;\n  }\n  .am-lg-text-right {\n    text-align: right !important;\n  }\n  .am-lg-text-center {\n    text-align: center !important;\n  }\n  .am-lg-text-justify {\n    text-align: justify !important;\n  }\n}\n.am-text-top {\n  vertical-align: top !important;\n}\n.am-text-middle {\n  vertical-align: middle !important;\n}\n.am-text-bottom {\n  vertical-align: bottom !important;\n}\n.am-angle {\n  position: absolute;\n}\n.am-angle:before,\n.am-angle:after {\n  position: absolute;\n  display: block;\n  content: \"\";\n  width: 0;\n  height: 0;\n  border: 8px dashed transparent;\n  z-index: 1;\n}\n.am-angle-up {\n  top: 0;\n}\n.am-angle-up:before,\n.am-angle-up:after {\n  border-bottom-style: solid;\n  border-width: 0 8px 8px;\n}\n.am-angle-up:before {\n  border-bottom-color: #ddd;\n  bottom: 0;\n}\n.am-angle-up:after {\n  border-bottom-color: #fff;\n  bottom: -1px;\n}\n.am-angle-down {\n  bottom: -9px;\n}\n.am-angle-down:before,\n.am-angle-down:after {\n  border-top-style: solid;\n  border-width: 8px 8px 0;\n}\n.am-angle-down:before {\n  border-top-color: #ddd;\n  bottom: 0;\n}\n.am-angle-down:after {\n  border-top-color: #fff;\n  bottom: 1px;\n}\n.am-angle-left {\n  left: -9px;\n}\n.am-angle-left:before,\n.am-angle-left:after {\n  border-right-style: solid;\n  border-width: 8px 8px 8px 0;\n}\n.am-angle-left:before {\n  border-right-color: #ddd;\n  left: 0;\n}\n.am-angle-left:after {\n  border-right-color: #fff;\n  left: 1px;\n}\n.am-angle-right {\n  right: 0;\n}\n.am-angle-right:before,\n.am-angle-right:after {\n  border-left-style: solid;\n  border-width: 8px 0 8px 8px;\n}\n.am-angle-right:before {\n  border-left-color: #ddd;\n  left: 0;\n}\n.am-angle-right:after {\n  border-left-color: #fff;\n  left: -1px;\n}\n/* ==========================================================================\n   Component: Alert Plugin\n ============================================================================ */\n.am-alert {\n  margin-bottom: 1em;\n  padding: 0.625em;\n  background: #0e90d2;\n  color: #fff;\n  border: 1px solid #0c7cb5;\n  border-radius: 0;\n}\n.am-alert a {\n  color: #fff;\n}\n.am-alert h1,\n.am-alert h2,\n.am-alert h3,\n.am-alert h4,\n.am-alert h5,\n.am-alert h6 {\n  color: inherit;\n}\n.am-alert .am-close {\n  opacity: .4;\n}\n.am-alert .am-close:hover {\n  opacity: .6;\n}\n/* Add margin if adjacent element */\n* + .am-alert {\n  margin-top: 1em;\n}\n/* Remove margin from the last-child */\n.am-alert > :last-child {\n  margin-bottom: 0;\n}\n/* within am-form-group */\n.am-form-group .am-alert {\n  margin: 5px 0 0;\n  padding: 0.25em 0.625em;\n  font-size: 1.3rem;\n}\n/* Close in alert */\n.am-alert > .am-close:first-child {\n  float: right;\n  height: auto;\n  margin: -3px -5px auto auto;\n}\n/* Remove margin from adjacent element */\n.am-alert > .am-close:first-child + * {\n  margin-top: 0;\n}\n.am-alert-secondary {\n  background-color: #eeeeee;\n  border-color: #dfdfdf;\n  color: #555555;\n}\n.am-alert-success {\n  background-color: #5eb95e;\n  border-color: #4bad4b;\n  color: #fff;\n}\n.am-alert-warning {\n  background-color: #F37B1D;\n  border-color: #e56c0c;\n  color: #fff;\n}\n.am-alert-danger {\n  background-color: #dd514c;\n  border-color: #d83832;\n  color: #fff;\n}\n.am-dropdown {\n  position: relative;\n  display: inline-block;\n}\n.am-dropdown-toggle:focus {\n  outline: 0;\n}\n.am-dropdown-content {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1020;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 15px;\n  margin: 9px 0 0;\n  text-align: left;\n  line-height: 1.6;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  border-radius: 0;\n  -webkit-background-clip: padding-box;\n          background-clip: padding-box;\n  -webkit-animation-duration: .15s;\n          animation-duration: .15s;\n}\n.am-dropdown-content:before,\n.am-dropdown-content:after {\n  position: absolute;\n  display: block;\n  content: \"\";\n  width: 0;\n  height: 0;\n  border: 8px dashed transparent;\n  z-index: 1;\n}\n.am-dropdown-content:before,\n.am-dropdown-content:after {\n  border-bottom-style: solid;\n  border-width: 0 8px 8px;\n}\n.am-dropdown-content:before {\n  border-bottom-color: #ddd;\n  bottom: 0;\n}\n.am-dropdown-content:after {\n  border-bottom-color: #fff;\n  bottom: -1px;\n}\n.am-dropdown-content:before,\n.am-dropdown-content:after {\n  left: 10px;\n  top: -8px;\n  pointer-events: none;\n}\n.am-dropdown-content:after {\n  top: -7px;\n}\n.am-active > .am-dropdown-content {\n  display: block;\n}\n.am-dropdown-content :first-child {\n  margin-top: 0;\n}\n.am-dropdown-up .am-dropdown-content {\n  top: auto;\n  bottom: 100%;\n  margin: 0 0 9px;\n}\n.am-dropdown-up .am-dropdown-content:before,\n.am-dropdown-up .am-dropdown-content:after {\n  border-bottom: none;\n  border-top: 8px solid #ddd;\n  top: auto;\n  bottom: -8px;\n}\n.am-dropdown-up .am-dropdown-content:after {\n  bottom: -7px;\n  border-top-color: #fff;\n}\n.am-dropdown-flip .am-dropdown-content {\n  left: auto;\n  right: 0;\n}\n.am-dropdown-flip .am-dropdown-content:before,\n.am-dropdown-flip .am-dropdown-content:after {\n  left: auto;\n  right: 10px;\n}\nul.am-dropdown-content {\n  list-style: none;\n  padding: 5px 0;\n}\nul.am-dropdown-content.am-fr {\n  right: 0;\n  left: auto;\n}\nul.am-dropdown-content .am-divider {\n  height: 1px;\n  margin: 0rem 0;\n  overflow: hidden;\n  background-color: #e5e5e5;\n}\nul.am-dropdown-content > li > a {\n  display: block;\n  padding: 6px 20px;\n  clear: both;\n  font-weight: normal;\n  color: #333333;\n  white-space: nowrap;\n}\nul.am-dropdown-content > li > a:hover,\nul.am-dropdown-content > li > a:focus {\n  text-decoration: none;\n  color: #262626;\n  background-color: #f5f5f5;\n}\nul.am-dropdown-content > .am-active > a,\nul.am-dropdown-content > .am-active > a:hover,\nul.am-dropdown-content > .am-active > a:focus {\n  color: #fff;\n  text-decoration: none;\n  outline: 0;\n  background-color: #0e90d2;\n}\nul.am-dropdown-content > .am-disabled > a,\nul.am-dropdown-content > .am-disabled > a:hover,\nul.am-dropdown-content > .am-disabled > a:focus {\n  color: #999999;\n}\nul.am-dropdown-content > .am-disabled > a:hover,\nul.am-dropdown-content > .am-disabled > a:focus {\n  text-decoration: none;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n  cursor: not-allowed;\n}\n.am-dropdown-header {\n  display: block;\n  padding: 6px 20px;\n  font-size: 1.2rem;\n  color: #999999;\n}\n.am-fr > .am-dropdown-content {\n  right: 0;\n  left: auto;\n}\n.am-fr > .am-dropdown-content:before {\n  right: 10px;\n  left: auto;\n}\n.am-dropdown-animation {\n  -webkit-animation: am-dropdown-animation 0.15s ease-out;\n          animation: am-dropdown-animation 0.15s ease-out;\n}\n@-webkit-keyframes am-dropdown-animation {\n  0% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n            transform: translateY(0);\n  }\n  100% {\n    opacity: 0;\n    -webkit-transform: translateY(-10px);\n            transform: translateY(-10px);\n  }\n}\n@keyframes am-dropdown-animation {\n  0% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n            transform: translateY(0);\n  }\n  100% {\n    opacity: 0;\n    -webkit-transform: translateY(-10px);\n            transform: translateY(-10px);\n  }\n}\n/* ==========================================================================\n   Component: Flex Slider Plugin\n ============================================================================ */\n.am-slider a:hover,\n.am-slider a:focus {\n  outline: none;\n}\n.am-slides,\n.am-control-nav,\n.am-direction-nav {\n  margin: 0;\n  padding: 0;\n  list-style: none;\n}\n.am-slider {\n  margin: 0;\n  padding: 0;\n}\n.am-slider .am-slides:before,\n.am-slider .am-slides:after {\n  content: \" \";\n  display: table;\n}\n.am-slider .am-slides:after {\n  clear: both;\n}\n.am-slider .am-slides > li {\n  display: none;\n  -webkit-backface-visibility: hidden;\n  position: relative;\n}\n.no-js .am-slider .am-slides > li:first-child {\n  display: block;\n}\n.am-slider .am-slides img {\n  width: 100%;\n  display: block;\n}\n.am-pauseplay span {\n  text-transform: capitalize;\n}\n.am-slider {\n  position: relative;\n}\n.am-viewport {\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.am-slider-carousel li {\n  margin-right: 5px;\n}\n.am-control-nav {\n  position: absolute;\n}\n.am-control-nav li {\n  display: inline-block;\n}\n.am-control-thumbs {\n  position: static;\n  overflow: hidden;\n}\n.am-control-thumbs img {\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.am-slider-slide .am-slides > li {\n  display: none;\n  position: relative;\n}\n@media all and (transform-3d), (-webkit-transform-3d) {\n  .am-slider-slide .am-slides > li {\n    -webkit-transition: -webkit-transform 0.6s ease-in-out;\n    transition: -webkit-transform 0.6s ease-in-out;\n    transition: transform 0.6s ease-in-out;\n    transition: transform 0.6s ease-in-out, -webkit-transform 0.6s ease-in-out;\n    -webkit-backface-visibility: hidden;\n            backface-visibility: hidden;\n    -webkit-perspective: 1000px;\n            perspective: 1000px;\n  }\n  .am-slider-slide .am-slides > li.next,\n  .am-slider-slide .am-slides > li.active.right {\n    -webkit-transform: translate3d(100%, 0, 0);\n            transform: translate3d(100%, 0, 0);\n    left: 0;\n  }\n  .am-slider-slide .am-slides > li.prev,\n  .am-slider-slide .am-slides > li.active.left {\n    -webkit-transform: translate3d(-100%, 0, 0);\n            transform: translate3d(-100%, 0, 0);\n    left: 0;\n  }\n  .am-slider-slide .am-slides > li.next.left,\n  .am-slider-slide .am-slides > li.prev.right,\n  .am-slider-slide .am-slides > li.active {\n    -webkit-transform: translate3d(0, 0, 0);\n            transform: translate3d(0, 0, 0);\n    left: 0;\n  }\n}\n.am-slider-slide .am-slides > .active,\n.am-slider-slide .am-slides > .next,\n.am-slider-slide .am-slides > .prev {\n  display: block;\n}\n.am-slider-slide .am-slides > .active {\n  left: 0;\n}\n.am-slider-slide .am-slides > .next,\n.am-slider-slide .am-slides > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n.am-slider-slide .am-slides > .next {\n  left: 100%;\n}\n.am-slider-slide .am-slides > .prev {\n  left: -100%;\n}\n.am-slider-slide .am-slides > .next.left,\n.am-slider-slide .am-slides > .prev.right {\n  left: 0;\n}\n.am-slider-slide .am-slides > .active.left {\n  left: -100%;\n}\n.am-slider-slide .am-slides > .active.right {\n  left: 100%;\n}\n/**\n  * Slider Theme: Default\n  */\n.am-slider-default {\n  margin: 0 0 20px;\n  background-color: #fff;\n  border-radius: 2px;\n  -webkit-box-shadow: 0 0 2px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 2px rgba(0, 0, 0, 0.15);\n  /* Direction Nav */\n  /* Pause/Play */\n  /* Control Nav */\n}\n.am-slider-default .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-default .am-viewport {\n  max-height: 300px;\n}\n.am-slider-default .carousel li {\n  margin-right: 5px;\n}\n.am-slider-default .am-direction-nav a {\n  position: absolute;\n  top: 50%;\n  z-index: 10;\n  display: block;\n  width: 36px;\n  height: 36px;\n  margin: -18px 0 0;\n  overflow: hidden;\n  opacity: 0.45;\n  cursor: pointer;\n  color: rgba(0, 0, 0, 0.65);\n  -webkit-transition: all .3s ease;\n  transition: all .3s ease;\n}\n.am-slider-default .am-direction-nav a:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  width: 100%;\n  color: #333333;\n  content: \"\\f137\";\n  font-size: 24px!important;\n  text-align: center;\n  line-height: 36px!important;\n  height: 36px;\n}\n.am-slider-default .am-direction-nav a.am-next:before {\n  content: \"\\f138\";\n}\n.am-slider-default .am-direction-nav .am-prev {\n  left: 10px;\n}\n.am-slider-default .am-direction-nav .am-next {\n  right: 10px;\n  text-align: right;\n}\n.am-slider-default .am-direction-nav .am-disabled {\n  opacity: 0!important;\n  cursor: default;\n}\n.am-slider-default:hover .am-prev {\n  opacity: 0.7;\n  left: 10px;\n}\n.am-slider-default:hover .am-prev:hover {\n  opacity: 1;\n}\n.am-slider-default:hover .am-next {\n  opacity: 0.7;\n  right: 10px;\n}\n.am-slider-default:hover .am-next:hover {\n  opacity: 1;\n}\n.am-slider-default .am-pauseplay a {\n  display: block;\n  width: 20px;\n  height: 20px;\n  position: absolute;\n  bottom: 5px;\n  left: 10px;\n  opacity: 0.8;\n  z-index: 10;\n  overflow: hidden;\n  cursor: pointer;\n  color: #000;\n}\n.am-slider-default .am-pauseplay a::before {\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  font-size: 20px;\n  display: inline-block;\n  content: \"\\f04c\";\n}\n.am-slider-default .am-pauseplay a:hover {\n  opacity: 1;\n}\n.am-slider-default .am-pauseplay a.am-play::before {\n  content: \"\\f04b\";\n}\n.am-slider-default .am-slider-desc {\n  background-color: rgba(0, 0, 0, 0.7);\n  position: absolute;\n  bottom: 0;\n  padding: 10px;\n  width: 100%;\n  color: #fff;\n}\n.am-slider-default .am-control-nav {\n  width: 100%;\n  position: absolute;\n  bottom: -15px;\n  text-align: center;\n}\n.am-slider-default .am-control-nav li {\n  margin: 0 6px;\n  display: inline-block;\n}\n.am-slider-default .am-control-nav li a {\n  width: 8px;\n  height: 8px;\n  display: block;\n  background-color: #666;\n  background-color: rgba(0, 0, 0, 0.5);\n  line-height: 0;\n  font-size: 0;\n  cursor: pointer;\n  text-indent: -9999px;\n  border-radius: 20px;\n  -webkit-box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);\n          box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);\n}\n.am-slider-default .am-control-nav li a:hover {\n  background-color: #333;\n  background-color: rgba(0, 0, 0, 0.7);\n}\n.am-slider-default .am-control-nav li a.am-active {\n  background-color: #000;\n  background-color: #0e90d2;\n  cursor: default;\n}\n.am-slider-default .am-control-thumbs {\n  margin: 5px 0 0;\n  position: static;\n  overflow: hidden;\n}\n.am-slider-default .am-control-thumbs li {\n  width: 25%;\n  float: left;\n  margin: 0;\n}\n.am-slider-default .am-control-thumbs img {\n  width: 100%;\n  height: auto;\n  display: block;\n  opacity: .7;\n  cursor: pointer;\n}\n.am-slider-default .am-control-thumbs img:hover {\n  opacity: 1;\n}\n.am-slider-default .am-control-thumbs .am-active {\n  opacity: 1;\n  cursor: default;\n}\n.am-slider-default .am-control-thumbs i {\n  position: absolute;\n}\n/*\nTODO:\n  1. 动画应该放在 dialog 上，不再是整个 modal，涉及 JS 逻辑，需要统筹修改\n  2. modal 滚动条处理，是否需要添加一个滚动条宽度的水平 padding？\n*/\n/* ==========================================================================\n   Component: Modal Plugin\n ============================================================================ */\n.am-modal {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1110;\n  display: none;\n  opacity: 0;\n  outline: 0;\n  text-align: center;\n  -webkit-transform: scale(1.185);\n      -ms-transform: scale(1.185);\n          transform: scale(1.185);\n  -webkit-transition-property: opacity, -webkit-transform;\n  transition-property: opacity, -webkit-transform;\n  transition-property: transform, opacity;\n  transition-property: transform, opacity, -webkit-transform;\n  -webkit-backface-visibility: hidden;\n          backface-visibility: hidden;\n  -webkit-perspective: 1000px;\n          perspective: 1000px;\n}\n.am-modal:focus {\n  outline: 0;\n}\n.am-modal.am-modal-active {\n  opacity: 1;\n  -webkit-transition-duration: 300ms;\n          transition-duration: 300ms;\n  -webkit-transform: scale(1);\n      -ms-transform: scale(1);\n          transform: scale(1);\n  overflow-x: hidden;\n  overflow-y: auto;\n}\n.am-modal.am-modal-out {\n  opacity: 0;\n  z-index: 1109;\n  -webkit-transition-duration: 300ms;\n          transition-duration: 300ms;\n  -webkit-transform: scale(0.815);\n      -ms-transform: scale(0.815);\n          transform: scale(0.815);\n}\n.am-modal:before {\n  content: \"\\200B\";\n  display: inline-block;\n  height: 100%;\n  vertical-align: middle;\n}\n.am-modal-dialog {\n  position: relative;\n  display: inline-block;\n  vertical-align: middle;\n  margin-left: auto;\n  margin-right: auto;\n  width: 270px;\n  max-width: 100%;\n  border-radius: 0;\n  background: #f8f8f8;\n  /*@media @large-up {\n    width: @modal-lg;\n    margin-left: -@modal-lg/2;\n  }*/\n}\n@media only screen and (min-width:641px) {\n  .am-modal-dialog {\n    width: 540px;\n  }\n}\n.am-modal-hd {\n  padding: 15px 10px 5px 10px;\n  font-size: 1.8rem;\n  font-weight: 500;\n}\n.am-modal-hd + .am-modal-bd {\n  padding-top: 0;\n}\n.am-modal-hd .am-close {\n  position: absolute;\n  top: 4px;\n  right: 4px;\n}\n.am-modal-bd {\n  padding: 15px 10px;\n  text-align: center;\n  border-bottom: 1px solid #dedede;\n  border-radius: 2px 2px 0 0;\n}\n.am-modal-bd + .am-modal-bd {\n  margin-top: 5px;\n}\n.am-modal-prompt-input {\n  display: block;\n  margin: 5px auto 0 auto;\n  border-radius: 0;\n  padding: 5px;\n  line-height: 1.8rem;\n  width: 80%;\n  border: 1px solid #dedede;\n  -webkit-appearance: none;\n  -moz-appearance: none;\n  -ms-appearance: none;\n  appearance: none;\n}\n.am-modal-prompt-input:focus {\n  outline: none;\n  border-color: #d6d6d6;\n}\n.am-modal-footer {\n  height: 44px;\n  overflow: hidden;\n  display: table;\n  width: 100%;\n  border-collapse: collapse;\n}\n.am-modal-btn {\n  display: table-cell !important;\n  padding: 0 5px;\n  height: 44px;\n  -webkit-box-sizing: border-box !important;\n          box-sizing: border-box !important;\n  font-size: 1.6rem;\n  line-height: 44px;\n  text-align: center;\n  color: #0e90d2;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n  cursor: pointer;\n  border-right: 1px solid #dedede;\n}\n.am-modal-btn:first-child {\n  border-radius: 0 0 0 0;\n}\n.am-modal-btn:last-child {\n  border-right: none;\n  border-radius: 0 0 0 0;\n}\n.am-modal-btn:first-child:last-child {\n  border-radius: 0 0 0 0;\n}\n.am-modal-btn.am-modal-btn-bold {\n  font-weight: 500;\n}\n.am-modal-btn:active {\n  background: #d4d4d4;\n}\n.am-modal-btn + .am-modal-btn {\n  border-left: 1px solid #dedede;\n}\n.am-modal-no-btn .am-modal-dialog {\n  border-radius: 0;\n  border-bottom: none;\n}\n.am-modal-no-btn .am-modal-bd {\n  border-bottom: none;\n}\n.am-modal-no-btn .am-modal-footer {\n  display: none;\n}\n.am-modal-loading .am-modal-bd {\n  border-bottom: none;\n}\n.am-modal-loading .am-icon-spin {\n  display: inline-block;\n  font-size: 2.4rem;\n}\n.am-modal-loading .am-modal-footer {\n  display: none;\n}\n.am-modal-actions {\n  position: fixed;\n  left: 0;\n  bottom: 0;\n  z-index: 1110;\n  width: 100%;\n  max-height: 100%;\n  overflow-x: hidden;\n  overflow-y: auto;\n  text-align: center;\n  border-radius: 0;\n  -webkit-transform: translateY(100%);\n      -ms-transform: translateY(100%);\n          transform: translateY(100%);\n  -webkit-transition: -webkit-transform 300ms;\n  transition: -webkit-transform 300ms;\n  transition: transform 300ms;\n  transition: transform 300ms, -webkit-transform 300ms;\n}\n.am-modal-actions.am-modal-active {\n  -webkit-transform: translateY(0);\n      -ms-transform: translateY(0);\n          transform: translateY(0);\n}\n.am-modal-actions.am-modal-out {\n  z-index: 1109;\n  -webkit-transform: translateY(100%);\n      -ms-transform: translateY(100%);\n          transform: translateY(100%);\n}\n.am-modal-actions-group {\n  margin: 10px;\n}\n.am-modal-actions-group .am-list {\n  margin: 0;\n  border-radius: 0;\n}\n.am-modal-actions-group .am-list > li {\n  margin-bottom: 0;\n  border-bottom: none;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n  -webkit-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.015);\n          box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.015);\n}\n.am-modal-actions-group .am-list > li > a {\n  padding: 1rem;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-modal-actions-group .am-list > li:first-child {\n  border-top: none;\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n.am-modal-actions-group .am-list > li:last-child {\n  border-bottom: none;\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n.am-modal-actions-header {\n  padding: 1rem;\n  color: #999999;\n  font-size: 1.4rem;\n}\n.am-modal-actions-danger {\n  color: #dd514c;\n}\n.am-modal-actions-danger a {\n  color: inherit;\n}\n.am-popup {\n  position: fixed;\n  left: 0;\n  top: 0;\n  width: 100%;\n  height: 100%;\n  z-index: 1110;\n  background: #fff;\n  display: none;\n  overflow: hidden;\n  -webkit-transition-property: -webkit-transform;\n  transition-property: -webkit-transform;\n  transition-property: transform;\n  transition-property: transform, -webkit-transform;\n  -webkit-transform: translateY(100%);\n      -ms-transform: translateY(100%);\n          transform: translateY(100%);\n}\n.am-popup.am-modal-active,\n.am-popup.am-modal-out {\n  -webkit-transition-duration: 300ms;\n          transition-duration: 300ms;\n}\n.am-popup.am-modal-active {\n  -webkit-transform: translateY(0);\n      -ms-transform: translateY(0);\n          transform: translateY(0);\n}\n.am-popup.am-modal-out {\n  -webkit-transform: translateY(100%);\n      -ms-transform: translateY(100%);\n          transform: translateY(100%);\n}\n@media all and (min-width: 630px) and (min-height: 630px) {\n  .am-popup {\n    width: 630px;\n    height: 630px;\n    left: 50%;\n    top: 50%;\n    margin-left: -315px;\n    margin-top: -315px;\n    -webkit-transform: translateY(1024px);\n        -ms-transform: translateY(1024px);\n            transform: translateY(1024px);\n  }\n  .am-popup.am-modal-active {\n    -webkit-transform: translateY(0);\n        -ms-transform: translateY(0);\n            transform: translateY(0);\n  }\n  .am-popup.am-modal-out {\n    -webkit-transform: translateY(1024px);\n        -ms-transform: translateY(1024px);\n            transform: translateY(1024px);\n  }\n}\n.am-popup-inner {\n  padding-top: 44px;\n  height: 100%;\n  overflow: auto;\n  -webkit-overflow-scrolling: touch;\n}\n.am-popup-hd {\n  position: absolute;\n  top: 0;\n  z-index: 1000;\n  width: 100%;\n  height: 43px;\n  border-bottom: 1px solid #dedede;\n  background-color: #fff;\n}\n.am-popup-hd .am-popup-title {\n  font-size: 1.8rem;\n  font-weight: bold;\n  line-height: 43px;\n  text-align: center;\n  margin: 0 30px;\n  color: #333333;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-popup-hd .am-close {\n  position: absolute;\n  right: 10px;\n  top: 8px;\n  cursor: pointer;\n  -webkit-transition: all 0.3s;\n  transition: all 0.3s;\n  color: #999999;\n}\n.am-popup-hd .am-close:hover {\n  -webkit-transform: rotate(360deg);\n      -ms-transform: rotate(360deg);\n          transform: rotate(360deg);\n  color: #555555;\n}\n.am-popup-bd {\n  padding: 15px;\n  background: #f8f8f8;\n  color: #555555;\n}\n/* ==========================================================================\n   Component: OffCanvas Plugin\n ============================================================================ */\n/* Off-canvas overlay and bar container */\n.am-offcanvas {\n  display: none;\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1090;\n  background: rgba(0, 0, 0, 0.15);\n}\n.am-offcanvas.am-active {\n  display: block;\n}\n/**\n * .@{ns}offcanvas-page\n *\n * Prepares the whole HTML page to slide-out\n * 1. Fix the main page and disallow scrolling\n * 2. Side-out transition\n */\n.am-offcanvas-page {\n  position: fixed;\n  /* 1 */\n  -webkit-transition: margin-left 0.3s ease-in-out;\n  transition: margin-left 0.3s ease-in-out;\n  /* 2 */\n}\n/* Sub-object .@{ns}offcanvas-bar */\n.am-offcanvas-bar {\n  position: fixed;\n  top: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1091;\n  width: 270px;\n  max-width: 100%;\n  background: #333;\n  overflow-y: auto;\n  /* scrollable */\n  -webkit-overflow-scrolling: touch;\n  /* scrollable */\n  -webkit-transition: -webkit-transform 0.3s ease-in-out;\n  transition: -webkit-transform 0.3s ease-in-out;\n  transition: transform 0.3s ease-in-out;\n  transition: transform 0.3s ease-in-out, -webkit-transform 0.3s ease-in-out;\n  -webkit-transform: translateX(-100%);\n      -ms-transform: translateX(-100%);\n          transform: translateX(-100%);\n}\n.am-offcanvas-bar:after {\n  content: \"\";\n  display: block;\n  position: absolute;\n  top: 0;\n  bottom: 0;\n  right: 0;\n  width: 1px;\n  background: #262626;\n}\n.am-offcanvas.am-active .am-offcanvas-bar.am-offcanvas-bar-active {\n  -webkit-transform: translateX(0);\n      -ms-transform: translateX(0);\n          transform: translateX(0);\n}\n/* .@{ns}offcanvas-bar-flip */\n.am-offcanvas-bar-flip {\n  left: auto;\n  right: 0;\n  -webkit-transform: translateX(100%);\n      -ms-transform: translateX(100%);\n          transform: translateX(100%);\n}\n.am-offcanvas-bar-flip:after {\n  right: auto;\n  left: 0;\n}\n.am-offcanvas-content {\n  padding: 15px;\n  color: #999;\n}\n.am-offcanvas-content a {\n  color: #ccc;\n}\n/* ==========================================================================\n   Component: Popover Plugin\n ============================================================================ */\n.am-popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  margin: 0;\n  border-radius: 0;\n  background: #333333;\n  color: #fff;\n  border: 1px solid #333333;\n  display: none;\n  font-size: 1.6rem;\n  z-index: 1030;\n  opacity: 0;\n  -webkit-transition: opacity 300ms;\n  transition: opacity 300ms;\n}\n.am-popover.am-active {\n  display: block !important;\n  opacity: 1;\n}\n.am-popover-inner {\n  position: relative;\n  background: #333333;\n  padding: 8px;\n  z-index: 110;\n}\n.am-popover-caret {\n  position: absolute;\n  top: 0;\n  z-index: 100;\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: middle;\n  border-bottom: 8px solid #333333;\n  border-right: 8px solid transparent;\n  border-left: 8px solid transparent;\n  border-top: 0 dotted;\n  -webkit-transform: rotate(360deg);\n      -ms-transform: rotate(360deg);\n          transform: rotate(360deg);\n  overflow: hidden;\n}\n.am-popover-top .am-popover-caret {\n  top: auto;\n  bottom: -8px;\n  -webkit-transform: rotate(180deg);\n      -ms-transform: rotate(180deg);\n          transform: rotate(180deg);\n}\n.am-popover-bottom .am-popover-caret {\n  top: -8px;\n}\n.am-popover-top .am-popover-caret,\n.am-popover-bottom .am-popover-caret {\n  left: 50%;\n  margin-left: -8px;\n}\n.am-popover-left .am-popover-caret {\n  top: auto;\n  left: auto;\n  right: -12px;\n  -webkit-transform: rotate(90deg);\n      -ms-transform: rotate(90deg);\n          transform: rotate(90deg);\n}\n.am-popover-right .am-popover-caret {\n  right: auto;\n  left: -12px;\n  -webkit-transform: rotate(-90deg);\n      -ms-transform: rotate(-90deg);\n          transform: rotate(-90deg);\n}\n.am-popover-left .am-popover-caret,\n.am-popover-right .am-popover-caret {\n  top: 50%;\n  margin-top: -4px;\n}\n.am-popover-sm {\n  font-size: 1.4rem;\n}\n.am-popover-sm .am-popover-inner {\n  padding: 5px;\n}\n.am-popover-lg {\n  font-size: 1.8rem;\n}\n.am-popover-primary {\n  border-color: #0e90d2;\n}\n.am-popover-primary .am-popover-inner {\n  background: #0e90d2;\n}\n.am-popover-primary .am-popover-caret {\n  border-bottom-color: #0e90d2;\n}\n.am-popover-secondary {\n  border-color: #3bb4f2;\n}\n.am-popover-secondary .am-popover-inner {\n  background: #3bb4f2;\n}\n.am-popover-secondary .am-popover-caret {\n  border-bottom-color: #3bb4f2;\n}\n.am-popover-success {\n  border-color: #5eb95e;\n}\n.am-popover-success .am-popover-inner {\n  background: #5eb95e;\n}\n.am-popover-success .am-popover-caret {\n  border-bottom-color: #5eb95e;\n}\n.am-popover-warning {\n  border-color: #F37B1D;\n}\n.am-popover-warning .am-popover-inner {\n  background: #F37B1D;\n}\n.am-popover-warning .am-popover-caret {\n  border-bottom-color: #F37B1D;\n}\n.am-popover-danger {\n  border-color: #dd514c;\n}\n.am-popover-danger .am-popover-inner {\n  background: #dd514c;\n}\n.am-popover-danger .am-popover-caret {\n  border-bottom-color: #dd514c;\n}\n/* ==========================================================================\n   Component: Progress Plugin\n ============================================================================ */\n#nprogress {\n  /* Make clicks pass-through */\n  pointer-events: none;\n  /* Fancy blur effect */\n}\n#nprogress .nprogress-bar {\n  position: fixed;\n  top: 0;\n  left: 0;\n  z-index: 2000;\n  width: 100%;\n  height: 2px;\n  background: #5eb95e;\n}\n#nprogress .nprogress-peg {\n  display: block;\n  position: absolute;\n  right: 0;\n  width: 100px;\n  height: 100%;\n  -webkit-box-shadow: 0 0 10px #5eb95e, 0 0 5px #5eb95e;\n          box-shadow: 0 0 10px #5eb95e, 0 0 5px #5eb95e;\n  opacity: 1;\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#nprogress .nprogress-spinner {\n  position: fixed;\n  top: 15px;\n  right: 15px;\n  z-index: 2000;\n  display: block;\n}\n#nprogress .nprogress-spinner-icon {\n  width: 18px;\n  height: 18px;\n  -webkit-box-sizing: border-box;\n          box-sizing: border-box;\n  border: solid 2px transparent;\n  border-top-color: #5eb95e;\n  border-left-color: #5eb95e;\n  border-radius: 50%;\n  -webkit-animation: nprogress-spinner 400ms linear infinite;\n          animation: nprogress-spinner 400ms linear infinite;\n}\n@-webkit-keyframes nprogress-spinner {\n  0% {\n    -webkit-transform: rotate(0deg);\n            transform: rotate(0deg);\n  }\n  100% {\n    -webkit-transform: rotate(360deg);\n            transform: rotate(360deg);\n  }\n}\n@keyframes nprogress-spinner {\n  0% {\n    -webkit-transform: rotate(0deg);\n            transform: rotate(0deg);\n  }\n  100% {\n    -webkit-transform: rotate(360deg);\n            transform: rotate(360deg);\n  }\n}\n/* ==========================================================================\n   Component: Tabs Plugin\n ============================================================================ */\n.am-tabs-bd {\n  position: relative;\n  overflow: hidden;\n  border: 1px solid #ddd;\n  border-top: none;\n  z-index: 100;\n  -webkit-transition: height .3s;\n  transition: height .3s;\n}\n.am-tabs-bd:before,\n.am-tabs-bd:after {\n  content: \" \";\n  display: table;\n}\n.am-tabs-bd:after {\n  clear: both;\n}\n.am-tabs-bd .am-tab-panel {\n  position: absolute;\n  top: 0;\n  z-index: 99;\n  float: left;\n  width: 100%;\n  padding: 10px 10px 15px;\n  visibility: hidden;\n  -webkit-transition: -webkit-transform 0.3s;\n  transition: -webkit-transform 0.3s;\n  transition: transform 0.3s;\n  transition: transform 0.3s, -webkit-transform 0.3s;\n  -webkit-transform: translateX(-100%);\n      -ms-transform: translateX(-100%);\n          transform: translateX(-100%);\n}\n.am-tabs-bd .am-tab-panel * {\n  -webkit-user-drag: none;\n}\n.am-tabs-bd .am-tab-panel.am-active {\n  position: relative;\n  z-index: 100;\n  visibility: visible;\n  -webkit-transform: translateX(0);\n      -ms-transform: translateX(0);\n          transform: translateX(0);\n}\n.am-tabs-bd .am-tab-panel.am-active ~ .am-tab-panel {\n  -webkit-transform: translateX(100%);\n      -ms-transform: translateX(100%);\n          transform: translateX(100%);\n}\n.am-tabs-bd .am-tabs-bd {\n  border: none;\n}\n.am-tabs-bd-ofv {\n  overflow: visible;\n}\n.am-tabs-fade .am-tab-panel {\n  opacity: 0;\n  -webkit-transition: opacity .25s linear;\n  transition: opacity .25s linear;\n}\n.am-tabs-fade .am-tab-panel.am-in {\n  opacity: 1;\n}\n/* ==========================================================================\n   Component: Share Plugin\n ============================================================================ */\n.am-share {\n  font-size: 14px;\n}\n.am-share-title {\n  padding: 10px 0 0;\n  margin: 0 10px;\n  font-weight: normal;\n  text-align: center;\n  color: #555555;\n  background-color: #f8f8f8;\n  border-bottom: 1px solid #fff;\n  border-top-right-radius: 2px;\n  border-top-left-radius: 2px;\n}\n.am-share-title:after {\n  content: \"\";\n  display: block;\n  width: 100%;\n  height: 0;\n  margin-top: 10px;\n  border-bottom: 1px solid #dfdfdf;\n}\n.am-share-sns {\n  margin: 0 10px;\n  padding-top: 15px;\n  background-color: #f8f8f8;\n  border-bottom-right-radius: 2px;\n  border-bottom-left-radius: 2px;\n}\n.am-share-sns li {\n  margin-bottom: 15px;\n}\n.am-share-sns a {\n  display: block;\n  color: #555555;\n}\n.am-share-sns span {\n  display: block;\n}\n.am-share-sns [class*='am-icon'] {\n  background-color: #3bb4f2;\n  border-radius: 50%;\n  width: 36px;\n  height: 36px;\n  line-height: 36px;\n  color: #fff;\n  margin-bottom: 5px;\n  font-size: 18px;\n}\n.am-share-sns .am-icon-weibo {\n  background-color: #ea1328;\n}\n.am-share-sns .am-icon-qq {\n  background-color: #009cda;\n}\n.am-share-sns .am-icon-star {\n  background-color: #ffc028;\n}\n.am-share-sns .am-icon-tencent-weibo {\n  background-color: #23ccfe;\n}\n.am-share-sns .am-icon-wechat,\n.am-share-sns .am-icon-weixin {\n  background-color: #44b549;\n}\n.am-share-sns .am-icon-renren {\n  background-color: #105ba3;\n}\n.am-share-sns .am-icon-comment {\n  background-color: #5eb95e;\n}\n.am-share-footer {\n  margin: 10px;\n}\n.am-share-footer .am-btn {\n  color: #555555;\n}\n.am-share-wechat-qr {\n  font-size: 14px;\n  color: #777;\n}\n.am-share-wechat-qr .am-modal-dialog {\n  background-color: #fff;\n  border: 1px solid #dedede;\n}\n.am-share-wechat-qr .am-modal-hd {\n  padding-top: 10px;\n  text-align: left;\n  margin-bottom: 10px;\n}\n.am-share-wechat-qr .am-share-wx-qr {\n  margin-bottom: 10px;\n}\n.am-share-wechat-qr .am-share-wechat-tip {\n  text-align: left;\n}\n.am-share-wechat-qr .am-share-wechat-tip em {\n  color: #dd514c;\n  font-weight: bold;\n  font-style: normal;\n  margin-left: 3px;\n  margin-right: 3px;\n}\n/* ==========================================================================\n   Component: PureView Plugin\n ============================================================================ */\n.am-pureview {\n  position: fixed;\n  left: 0;\n  top: 0;\n  bottom: 0;\n  right: 0;\n  z-index: 1120;\n  width: 100%;\n  height: 100%;\n  background: rgba(0, 0, 0, 0.95);\n  display: none;\n  overflow: hidden;\n  -webkit-transition: -webkit-transform .3s;\n  transition: -webkit-transform .3s;\n  transition: transform .3s;\n  transition: transform .3s, -webkit-transform .3s;\n  -webkit-transform: translate(0, 100%);\n      -ms-transform: translate(0, 100%);\n          transform: translate(0, 100%);\n}\n.am-pureview.am-active {\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n}\n.am-pureview ul,\n.am-pureview ol {\n  list-style: none;\n  padding: 0;\n  margin: 0;\n  width: 100%;\n}\n.am-pureview-slider {\n  overflow: hidden;\n  height: 100%;\n}\n.am-pureview-slider li {\n  position: absolute;\n  width: 100%;\n  height: 100%;\n  top: 0;\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -ms-flexbox;\n  display: flex;\n  -webkit-box-pack: center;\n  -webkit-justify-content: center;\n      -ms-flex-pack: center;\n          justify-content: center;\n  -webkit-box-align: center;\n  -webkit-align-items: center;\n      -ms-flex-align: center;\n          align-items: center;\n  vertical-align: middle;\n  -webkit-transition: all .3s linear;\n  transition: all .3s linear;\n  z-index: 100;\n  visibility: hidden;\n}\n.am-pureview-slider li.am-pureview-slide-prev {\n  -webkit-transform: translate(-100%, 0);\n      -ms-transform: translate(-100%, 0);\n          transform: translate(-100%, 0);\n  z-index: 109;\n}\n.am-pureview-slider li.am-pureview-slide-next {\n  -webkit-transform: translate(100%, 0);\n      -ms-transform: translate(100%, 0);\n          transform: translate(100%, 0);\n  z-index: 109;\n}\n.am-pureview-slider li.am-active {\n  position: relative;\n  z-index: 110;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  visibility: visible;\n}\n.am-pureview-slider .pinch-zoom-container {\n  width: 100%;\n  z-index: 1121;\n}\n.am-pureview-slider .am-pinch-zoom {\n  position: relative;\n  width: 100%;\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -ms-flexbox;\n  display: flex;\n  -webkit-box-pack: center;\n  -webkit-justify-content: center;\n      -ms-flex-pack: center;\n          justify-content: center;\n  -webkit-box-align: center;\n  -webkit-align-items: center;\n      -ms-flex-align: center;\n          align-items: center;\n}\n.am-pureview-slider .am-pinch-zoom:after {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f110\";\n  -webkit-animation: icon-spin 2s infinite linear;\n          animation: icon-spin 2s infinite linear;\n  font-size: 24px;\n  line-height: 24px;\n  color: #eee;\n  position: absolute;\n  top: 50%;\n  left: 50%;\n  margin-left: -12px;\n  margin-top: -12px;\n  z-index: 1;\n}\n.am-pureview-slider .am-pinch-zoom.am-pureview-loaded:after {\n  display: none;\n}\n.am-pureview-slider img {\n  position: relative;\n  display: block;\n  max-width: 100%;\n  max-height: 100%;\n  opacity: 0;\n  z-index: 200;\n  -webkit-user-drag: none;\n  -webkit-transition: opacity 0.2s ease-in;\n  transition: opacity 0.2s ease-in;\n}\n.am-pureview-slider img.am-img-loaded {\n  opacity: 1;\n}\n.am-pureview-direction {\n  position: absolute;\n  top: 50%;\n  width: 100%;\n  margin-top: -18px !important;\n  z-index: 1122;\n}\n.am-touch .am-pureview-direction,\n.am-pureview-only .am-pureview-direction {\n  display: none;\n}\n.am-pureview-direction li {\n  position: absolute;\n  width: 36px;\n  height: 36px;\n}\n.am-pureview-direction a {\n  display: block;\n  height: 36px;\n  border: none;\n  color: #ccc;\n  opacity: 0.5;\n  cursor: pointer;\n  text-align: center;\n  z-index: 1125;\n}\n.am-pureview-direction a:before {\n  content: \"\\f137\";\n  line-height: 36px;\n  font-size: 24px;\n}\n.am-pureview-direction a:hover {\n  opacity: 1;\n}\n.am-pureview-direction .am-pureview-prev {\n  left: 15px;\n}\n.am-pureview-direction .am-pureview-next {\n  right: 15px;\n}\n.am-pureview-direction .am-pureview-next a:before {\n  content: \"\\f138\";\n}\n.am-pureview-bar {\n  position: absolute;\n  bottom: 0;\n  height: 45px;\n  width: 100%;\n  background-color: rgba(0, 0, 0, 0.35);\n  color: #eeeeee;\n  line-height: 45px;\n  padding: 0 10px;\n  font-size: 14px;\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -ms-flexbox;\n  display: flex;\n}\n.am-pureview-bar .am-pureview-title {\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n  margin-left: 6px;\n  -webkit-box-flex: 1;\n  -webkit-flex: 1;\n      -ms-flex: 1;\n          flex: 1;\n}\n.am-pureview-bar .am-pureview-total {\n  font-size: 10px;\n  line-height: 48px;\n}\n.am-pureview-actions {\n  position: absolute;\n  z-index: 1130;\n  left: 0;\n  right: 0;\n  top: 0;\n  height: 45px;\n  background-color: rgba(0, 0, 0, 0.35);\n}\n.am-pureview-actions a {\n  position: absolute;\n  left: 10px;\n  color: #ccc;\n  display: block;\n  width: 45px;\n  line-height: 45px;\n  text-align: left;\n  font-size: 16px;\n}\n.am-pureview-actions a:hover {\n  color: #fff;\n}\n.am-pureview-actions [data-am-toggle=\"share\"] {\n  left: auto;\n  right: 10px;\n}\n.am-pureview-bar,\n.am-pureview-actions {\n  opacity: 0;\n  -webkit-transition: all .15s;\n  transition: all .15s;\n  z-index: 1130;\n}\n.am-pureview-bar-active .am-pureview-bar,\n.am-pureview-bar-active .am-pureview-actions {\n  opacity: 1;\n}\n.am-pureview-nav {\n  position: absolute;\n  bottom: 15px;\n  left: 0;\n  right: 0;\n  text-align: center;\n  z-index: 1131;\n}\n.am-pureview-bar-active .am-pureview-nav {\n  display: none;\n}\n.am-pureview-nav li {\n  display: inline-block;\n  background: #ccc;\n  background: rgba(255, 255, 255, 0.5);\n  width: 8px;\n  height: 8px;\n  margin: 0 3px;\n  border-radius: 50%;\n  text-indent: -9999px;\n  overflow: hidden;\n  cursor: pointer;\n}\n.am-pureview-nav .am-active {\n  background: #fff;\n  background: rgba(255, 255, 255, 0.9);\n}\n[data-am-pureview] img {\n  cursor: pointer;\n}\n.am-pureview-active {\n  overflow: hidden;\n}\n.ath-viewport * {\n  -webkit-box-sizing: border-box;\n          box-sizing: border-box;\n}\n.ath-viewport {\n  position: relative;\n  z-index: 2147483641;\n  pointer-events: none;\n  -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          user-select: none;\n  -webkit-text-size-adjust: none;\n      -ms-text-size-adjust: none;\n          text-size-adjust: none;\n}\n.ath-modal {\n  pointer-events: auto !important;\n  background: rgba(0, 0, 0, 0.6);\n}\n.ath-mandatory {\n  background: #000;\n}\n.ath-container {\n  pointer-events: auto !important;\n  position: absolute;\n  z-index: 2147483641;\n  padding: 0.7em 0.6em;\n  width: 18em;\n  background: #eee;\n  -webkit-background-size: 100% auto;\n          background-size: 100% auto;\n  -webkit-box-shadow: 0 0.2em 0 #d1d1d1;\n          box-shadow: 0 0.2em 0 #d1d1d1;\n  font-family: sans-serif;\n  font-size: 15px;\n  line-height: 1.5em;\n  text-align: center;\n}\n.ath-container small {\n  font-size: 0.8em;\n  line-height: 1.3em;\n  display: block;\n  margin-top: 0.5em;\n}\n.ath-ios.ath-phone {\n  bottom: 1.8em;\n  left: 50%;\n  margin-left: -9em;\n}\n.ath-ios6.ath-tablet {\n  left: 5em;\n  top: 1.8em;\n}\n.ath-ios7.ath-tablet {\n  left: 0.7em;\n  top: 1.8em;\n}\n.ath-ios8.ath-tablet {\n  right: 0.4em;\n  top: 1.8em;\n}\n.ath-android {\n  bottom: 1.8em;\n  left: 50%;\n  margin-left: -9em;\n}\n/* close icon */\n.ath-container:before {\n  content: '';\n  position: relative;\n  display: block;\n  float: right;\n  margin: -0.7em -0.6em 0 0.5em;\n  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIQAAACECAMAAABmmnOVAAAAdVBMVEUAAAA5OTkzMzM7Ozs3NzdBQUFAQEA/Pz8+Pj5BQUFAQEA/Pz8+Pj5BQUFAQEA/Pz9BQUE+Pj4/Pz8/Pz8+Pj4/Pz8/Pz8/Pz8+Pj4/Pz8+Pj4/Pz8/Pz8/Pz8/Pz8/Pz8+Pj4/Pz8/Pz8/Pz8/Pz9AQEA/Pz+fdCaPAAAAJnRSTlMACQoNDjM4OTo7PEFCQ0RFS6ytsbS1tru8vcTFxu7x8vX19vf4+C5yomAAAAJESURBVHgBvdzLTsJAGEfxr4C2KBcVkQsIDsK8/yPaqIsPzVlyzrKrX/5p0kkXEz81L23otc9NpIbbWia2YVLqdnhlqFlhGWpSDHe1aopsSIpRb8gK0dC3G30b9rVmhWZIimTICsvQtx/FsuYOrWHoDjX3Gu31gzJxdki934WrAIOsAIOsAIOiAMPhPsJTgKGN0BVsYIVsYIVpYIVpYIVpYIVpYIVpYIVpYIVpYIVlAIVgEBRs8BRs8BRs8BRs8BRs8BRs8BRs8BRTNmgKNngKNngKNngKNngKNhiKGxgiOlZoBlaYBlaYBlaYBlaYBlaYBlaYBlaYBlZIBlBMfQMrVAMr2KAqBENSHFHhGEABhi5CV6gGUKgGUKgGUKgGUFwuqgEUvoEVsoEVpoEUpgEUggF+gKTKY+h1fxSlC7/Z+RrxOQ3fcEoAPPHZBlaYBlaYBlaYBlZYBlYIhvLBCstw7PgM7hkiWOEZWGEaWGEaWGEaIsakEAysmHkGVpxmvoEVqoEVpoEVpoEVpoEVpoEVpoEVkoEVgkFQsEFSsEFQsGEcoSvY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnmbNAUT2c2WAo2eAo2eAo2eAo2eAo2eArNEPFACjZ4CjZ4CjZ4CjaIird/rBvFH6llNCvewdli1URWCIakSIZesUaDoFg36dKFWk9zCZDei3TtwmCj7pC22AwikiIZPEU29IpFNliKxa/hC9DFITjQPYhcAAAAAElFTkSuQmCC);\n  background-color: rgba(255, 255, 255, 0.8);\n  -webkit-background-size: 50% 50%;\n          background-size: 50%;\n  background-repeat: no-repeat;\n  background-position: 50%;\n  width: 2.7em;\n  height: 2.7em;\n  text-align: center;\n  overflow: hidden;\n  color: #a33;\n  z-index: 2147483642;\n}\n.ath-container.ath-icon:before {\n  position: absolute;\n  top: 0;\n  right: 0;\n  margin: 0;\n  float: none;\n}\n.ath-mandatory .ath-container:before {\n  display: none;\n}\n.ath-container.ath-android:before {\n  float: left;\n  margin: -0.7em 0.5em 0 -0.6em;\n}\n.ath-container.ath-android.ath-icon:before {\n  position: absolute;\n  right: auto;\n  left: 0;\n  margin: 0;\n  float: none;\n}\n/* applied only if the application icon is shown */\n.ath-action-icon {\n  display: inline-block;\n  vertical-align: middle;\n  background-position: 50%;\n  background-repeat: no-repeat;\n  text-indent: -9999em;\n  overflow: hidden;\n}\n.ath-ios7 .ath-action-icon,\n.ath-ios8 .ath-action-icon {\n  width: 1.6em;\n  height: 1.6em;\n  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHgAAACtCAYAAAB7l7tOAAAF6UlEQVR4AezZWWxUZRiH8VcQEdxZEFFiUZBFUCIa1ABBDARDcCciYGKMqTEGww3SOcNSAwQTjOBiiIpEhRjAhRgXRC8MFxojEhAFZUGttVhaoSxlaW3n8W3yXZxm6vTrOMM5Q98n+V9MMu1pvl++uZhKuypghu49KaaTWGdZSYoVN6VD95nMpLNYZ9XNbdQR2od2k88O3Gm6Bh0t7H0p5Vwp2Ax3ajpu2tYbciFWwkTFO63DY6+JcI4USFaSyYpWp8N7SVZJKR3EinkBk9JxvZFXxhnZSjBaoWp1ZL0ES8WKYXMZp0AndORgy8WKFe5Yf1zvvSBWDEpys2LU6MjD5kmEWQlGKsJRHXlcqUSQVcItEnDEA6gAb7LhjvD9WO6yIEfICQI5A1nzGCYB1T4og5bBiFcyv2f6ujYhl4iVxwKG6qp8MK55HsqPwK0rMr9v/yEo3uCPrJstVh5KMER30Aeh31Ioq0FrHfjXw9CYghnrvYFTuqfEymFzGSwBlT4ARYr7u+K6GLmCVGvAGg2NMG0d/sgJnpScZLjXSkC5z8H3eQ72/k24Q8NfzvwFyK4qtuJSZKaubRPyE/K/Mtx+EvCHL+7uasId1t10w0scz/RzSzYzAfgKV30D3LPaG7lRkR8RK4tKKJKAMp+D7r0EfmmOe0x3m2itAc/ZxBjgAt1mXHWKPPkdb+QGSTJdrDaU5EoJ2OtzwD0WwY7KNNzbRfMFFg24WPdtGHnS221Cflgsj56hjwTs8TnY7oq7/QDhjutGicsb2AVcovsO18l6uPPNNiE/JFaGAq7Q7fY50G4LYVtz3FrdaNGyBXbIl+q24DqhyHes9EaulwR3SwtZs+ktAT/7HORliru1gnCndONFyx44Dfn7MPLYN7yR6yTJZAllJeguAT/4HOBFz8I3ZWm4E0TLFbBD7qn7EVdtHYx53R9ZN0ksrZRuErDN5+AuLIWvm+Oe1k0ULdfADrmX7idcR0/DyBXeyCdlLuMMOGCBz4F1ng+f7yFcve5e0fIFHELeiav6BAx70Rt5p0yhY3u/wR0kyarW/uX35b403PtFyzewQ75ctwtXzSkY8WqruHslSV8RscrL6TJ1bcvfWJ0/HzbtIdw/ugdFyzdwOOAq3T6fmzxwGQ3vbmO8iFioIWqYSsHMj9M/ljfuTsOdItoZBXYBfXX7cVXVwvXLm/8+fU3lcdCqdEMNGBbgUmRmfQISQKd5sGEn4VK6YtEiAXYBA3QVuA4q8hCHrDcafR1ul65jewfuovsCl7vJrNlOuEbdo6JFCuwCrtb9hqusBu56Cw4cI1y1briIWEBn3Ue0XKPuMdGiBg4H9NdV0HJ/6QZLOEPmPN0GmpfSPS5arIBdwHUtIFfoBsl/ZsgfhHCfFi2WwC5goO4AmvanbqBkzJA76tboZokWa2AXMEi3RTdAvDLkDqJFAhzB32xFD2wZsGXA0WfAlgFbBmwZsGXAlgFbBpzk04JaKb0iA9ZnF9x5SQAFtRKKIgPWZxfaeRmwAZ/BGbAB37eaG6MCbnq2Aed5czYyKirgpmcbsAHHZAZswN0Wwo7KeG1fFf2jAm56dtzOQ42yB+65mDhWFBUwUETMUiMDNmADbp/APRaTAh6I2bpGCNw1bufRZJQ1cPdF/NueHZsgDEBBGLbMGoIu4AZu5gLOZeEaYmEXeznF3jRPyEv4frgJvvJe3qTefY0AAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwb8rwADBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgz4/sz1Nia/9hizA7zgklwy3RYwYMBzBRjw4bPjxAbAAizAAtwgwAIswAIswAIMGDBgARZgARZgAS4FWIAFWIAFWIABAwYswAIswAIswIUAC7AAC7AACzBgwIAFWIAFWIAFuBBgARZgARZgAQYMGPApQ99ZCdgWtzqwATbABtgAG2DbnxNb7zbRimsMLMACrDf2wMWI/WasfQAAAABJRU5ErkJggg==);\n  margin-top: -0.3em;\n  -webkit-background-size: auto 100%;\n          background-size: auto 100%;\n}\n.ath-ios6 .ath-action-icon {\n  width: 1.8em;\n  height: 1.8em;\n  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJAAAAB0CAQAAADAmnOnAAAAAnNCSVQICFXsRgQAAAAJcEhZcwAAWwEAAFsBAXkZiFwAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAF4klEQVR4Ae3a/a+XdR3H8ec5HM45HDmKICoVohkZsxESRRCzcZM/2JKkdGR5MrSkleA0Pd00O4u5IVuNM2yYc6XSzCExU4oUNRPCJFdMUAhsYZpUGhscOHA4N8/WZzsL6HBxvofvdV3fa3yer//gsV3vH659KHzncBsJxUYhDzOEhCKQbORs+ip2wzgM+wvj+P9i35qAGLaHGcQSgKSTrxBLABJppZpYApCspoFYApBsZjSxBCD5OxOJJQBJG1cQSwCSLpqJJQCJ3MvgCGTinuSMCJS8LZwfgZL3FtMiUPIOcU0ESl4PLRHoRPsJtREoeRsYGYGS9yrvo6RmpbLaigWSfzOdErLs6+bLUMFA0sF1+QF1cz1UNlBYK9V5AHXyWSgEkKyiIWOgGh829Ki1lLcaxjCVK7mJRSxjBY+zgRf/u9pXcMB7jhEZAg32EUP3O6hMKOP5Iq2sZQeHMZXt5KKMgOpcY+iHVnFyjeQKlrCBdsxge5ieAVC9vzLUelI8H+A7bKIHM10H81IGGuKvDf1ggDxVTKOV1zG3/Yia1ICG+ltD32MgNTKfP2HuW0VDKkCNrjfUTOm9i6XswwrZJkaVHeh0f2fodkrtfO6jAytqrzG+rEDDfVG1x1sprZEs5RBW4PZxeT+Bbrf5hPu9arfzKaU6WjiAFbseWvoF1GW/6vYGSmkyW7Dit4xB5QHq9Br6Xx2t9GAhtp6zkoHsfNp1J9wX6H+jeR4LtJc4LxGopZZyNpN/YcG2mw9nBTSPLizgOmjKAujGgvJID3ekD7QYi7nGzkvmQtpA38Vi7iJf0TedlC7QTVjMfcY2QyvSBPpUMW/PIBfbo9pls1XpAX2EdizeznStob3OJpQO0DB2YfE21q2GtnghpAm0Gou3T9tm6BGHQppA12HRVt17eboNlydNoLHsx2JtmL801OYcQmkC/QKLtQt9ydBW3wNpA30ci7Ur3WdolUMhbaBqNhf/8qQJ9Hkszs5wjaH9XkUobaAqtmFRdoGbDb3sWMgG6DIs5852knO82RaXer+P+qyb3eWeo7ZNBrRZvm1otY2QFdBjeHIb6hTne49Put12+9ObMoDdYmfy5UkF6AK6cCCr9aM2u9IddptcOYCG+FNDB5xLKCugO7G01TndFp/xgAntdYvrfdwVLnORt3q9Vx25F27DUjbGPxr6qxMgW6Cd2N+d6wLXedA+6nKbK73Lr/pJxzusvE/wZrvX0FOOgGyBxmF/dprXutYOj6nNdS6xyYnWp/dGcaGdhr5vDWQN9E1MXrUzfcA2j2qPj/l1J1uT9iPOeh8w1O7nCGUN9HzyGZ7ndo9qp0ucanU2r1xH+wdDu5wIeQDVVx0+/kd1i697RNv8thdn+Qz4Uv9p6DeOhHyApmBfq3OBu+3Nfd7nVELZAX3Nw4ZarYG8gG7GY1dlk6/Zm3/2Rk8jlB1QvT82dNAmQjkBVf8Mj957fdrefM7ZVhPKEuidvmDob06CXIGGbsX/bZDf8KAhfdbJhLIGmuZuQ084HHIGatiLvRvrRkP6qldbBXkAzbfD0N0OhryBGqrEMOd50FC7d1hPKGugBh8ydMh5hPIGGouI1d5lj6F1vptQ9kDvcKOhN5wMlQH0QcRGnzC03yZCeQDN9G1D6xwBFQI07FI8x02GdjgB8gJqttPQcmuhYoAumzvG7YZWejrkA1TrPYYO+SVCFQO0aM4bqj0uJJQH0LluSP7PkyeQU9QOmyAvoBm+Zegpz4LKA/qYB/wE5AXUe3m81zqoRKAPOYWcuvP9dxvqcD6h7IAKkaNU3eUlHLcI9EzS5YlAi62h/zUy89QCqqKUmvgHywsJlEHnsQYxAvXVIJo5gIhnPhiBju1iNmLvLn85Ah1ZPYs5jBGo72awEzEC9dVwHqQHI9DxWoAYgSLQQKteGIESu/qhCJTYtT+PQBEoAkWgCBSBkotAEehUWwSKQBEoAkWg/BeBIlAEikARKAJFoFmealu4gVLy1Gt5dkARKAL9BzujPSurTmu/AAAAAElFTkSuQmCC);\n  margin-bottom: 0.4em;\n  -webkit-background-size: 100% auto;\n          background-size: 100% auto;\n}\n.ath-android .ath-action-icon {\n  width: 1.4em;\n  height: 1.4em;\n  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAMAAABg3Am1AAAANlBMVEVmZmb///9mZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZW6fJrAAAAEXRSTlMAAAYHG21ub8fLz9DR8/T4+RrZ9owAAAB3SURBVHja7dNLDoAgDATQWv4gKve/rEajJOJiWLgg6WzpSyB0aHqHiNj6nL1lovb4C+hYzkSNAT7mryQFAVOeGAj4CjwEtgrWXpD/uZKtwEJApXt+Vn0flzRhgNiFZQkOXY0aADQZCOCPlsZJ46Rx0jhp3IiN2wGDHhxtldrlwQAAAABJRU5ErkJggg==);\n  -webkit-background-size: 100% auto;\n          background-size: 100% auto;\n}\n.ath-container p {\n  margin: 0;\n  padding: 0;\n  position: relative;\n  z-index: 2147483642;\n  text-shadow: 0 0.1em 0 #fff;\n  font-size: 1.1em;\n}\n.ath-ios.ath-phone:after {\n  content: '';\n  background: #eee;\n  position: absolute;\n  width: 2em;\n  height: 2em;\n  bottom: -0.9em;\n  left: 50%;\n  margin-left: -1em;\n  -webkit-transform: scaleX(0.9) rotate(45deg);\n  -ms-transform: scaleX(0.9) rotate(45deg);\n      transform: scaleX(0.9) rotate(45deg);\n  -webkit-box-shadow: 0.2em 0.2em 0 #d1d1d1;\n          box-shadow: 0.2em 0.2em 0 #d1d1d1;\n}\n.ath-ios.ath-tablet:after {\n  content: '';\n  background: #eee;\n  position: absolute;\n  width: 2em;\n  height: 2em;\n  top: -0.9em;\n  left: 50%;\n  margin-left: -1em;\n  -webkit-transform: scaleX(0.9) rotate(45deg);\n  -ms-transform: scaleX(0.9) rotate(45deg);\n      transform: scaleX(0.9) rotate(45deg);\n  z-index: 2147483641;\n}\n.ath-application-icon {\n  position: relative;\n  padding: 0;\n  border: 0;\n  margin: 0 auto 0.2em auto;\n  height: 6em;\n  width: 6em;\n  z-index: 2147483642;\n}\n.ath-container.ath-ios .ath-application-icon {\n  border-radius: 1em;\n  -webkit-box-shadow: 0 0.2em 0.4em rgba(0, 0, 0, 0.3), inset 0 0.07em 0 rgba(255, 255, 255, 0.5);\n          box-shadow: 0 0.2em 0.4em rgba(0, 0, 0, 0.3), inset 0 0.07em 0 rgba(255, 255, 255, 0.5);\n  margin: 0 auto 0.4em auto;\n}\n@media only screen and (orientation: landscape) {\n  .ath-container.ath-phone {\n    width: 24em;\n  }\n  .ath-android.ath-phone {\n    margin-left: -12em;\n  }\n  .ath-ios.ath-phone {\n    margin-left: -12em;\n  }\n  .ath-ios6:after {\n    left: 39%;\n  }\n  .ath-ios8.ath-phone {\n    left: auto;\n    bottom: auto;\n    right: 0.4em;\n    top: 1.8em;\n  }\n  .ath-ios8.ath-phone:after {\n    bottom: auto;\n    top: -0.9em;\n    left: 68%;\n    z-index: 2147483641;\n    -webkit-box-shadow: none;\n            box-shadow: none;\n  }\n}\n/* ==========================================================================\n   Component: uCheck Plugin\n ============================================================================ */\n.am-checkbox,\n.am-radio,\n.am-checkbox-inline,\n.am-radio-inline {\n  padding-left: 22px;\n  position: relative;\n  -webkit-transition: color .25s linear;\n  transition: color .25s linear;\n  font-size: 14px;\n  line-height: 1.5;\n}\nlabel.am-checkbox,\nlabel.am-radio {\n  font-weight: normal;\n}\n.am-ucheck-icons {\n  color: #999999;\n  display: block;\n  height: 20px;\n  top: 0;\n  left: 0;\n  position: absolute;\n  width: 20px;\n  text-align: center;\n  line-height: 21px;\n  font-size: 18px;\n  cursor: pointer;\n}\n.am-checkbox .am-icon-checked,\n.am-radio .am-icon-checked,\n.am-checkbox-inline .am-icon-checked,\n.am-radio-inline .am-icon-checked,\n.am-checkbox .am-icon-unchecked,\n.am-radio .am-icon-unchecked,\n.am-checkbox-inline .am-icon-unchecked,\n.am-radio-inline .am-icon-unchecked {\n  position: absolute;\n  left: 0;\n  top: 0;\n  display: inline-table;\n  margin: 0;\n  background-color: transparent;\n  -webkit-transition: color .25s linear;\n  transition: color .25s linear;\n}\n.am-checkbox .am-icon-checked:before,\n.am-radio .am-icon-checked:before,\n.am-checkbox-inline .am-icon-checked:before,\n.am-radio-inline .am-icon-checked:before,\n.am-checkbox .am-icon-unchecked:before,\n.am-radio .am-icon-unchecked:before,\n.am-checkbox-inline .am-icon-unchecked:before,\n.am-radio-inline .am-icon-unchecked:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n}\n.am-checkbox .am-icon-checked,\n.am-radio .am-icon-checked,\n.am-checkbox-inline .am-icon-checked,\n.am-radio-inline .am-icon-checked {\n  opacity: 0;\n}\n.am-checkbox .am-icon-checked:before,\n.am-checkbox-inline .am-icon-checked:before {\n  content: \"\\f046\";\n}\n.am-checkbox .am-icon-unchecked:before,\n.am-checkbox-inline .am-icon-unchecked:before {\n  content: \"\\f096\";\n}\n.am-radio .am-icon-checked:before,\n.am-radio-inline .am-icon-checked:before {\n  content: \"\\f192\";\n}\n.am-radio .am-icon-unchecked:before,\n.am-radio-inline .am-icon-unchecked:before {\n  content: \"\\f10c\";\n}\n.am-ucheck-checkbox,\n.am-ucheck-radio {\n  position: absolute;\n  left: 0;\n  top: 0;\n  margin: 0;\n  padding: 0;\n  width: 20px;\n  height: 20px;\n  opacity: 0;\n  outline: none !important;\n}\n.am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons {\n  color: #0e90d2;\n}\n.am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-ucheck-radio:checked + .am-ucheck-icons {\n  color: #0e90d2;\n}\n.am-ucheck-checkbox:checked + .am-ucheck-icons .am-icon-unchecked,\n.am-ucheck-radio:checked + .am-ucheck-icons .am-icon-unchecked {\n  opacity: 0;\n}\n.am-ucheck-checkbox:checked + .am-ucheck-icons .am-icon-checked,\n.am-ucheck-radio:checked + .am-ucheck-icons .am-icon-checked {\n  opacity: 1;\n}\n.am-ucheck-checkbox:disabled + .am-ucheck-icons,\n.am-ucheck-radio:disabled + .am-ucheck-icons {\n  cursor: default;\n  color: #d8d8d8;\n}\n.am-ucheck-checkbox:disabled:checked + .am-ucheck-icons .am-icon-unchecked,\n.am-ucheck-radio:disabled:checked + .am-ucheck-icons .am-icon-unchecked {\n  opacity: 0;\n}\n.am-ucheck-checkbox:disabled:checked + .am-ucheck-icons .am-icon-checked,\n.am-ucheck-radio:disabled:checked + .am-ucheck-icons .am-icon-checked {\n  opacity: 1;\n  color: #d8d8d8;\n}\n.am-checkbox.am-secondary .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio.am-secondary .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox-inline.am-secondary .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio-inline.am-secondary .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox.am-secondary .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio.am-secondary .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox-inline.am-secondary .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio-inline.am-secondary .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons {\n  color: #3bb4f2;\n}\n.am-checkbox.am-secondary .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-radio.am-secondary .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-checkbox-inline.am-secondary .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-radio-inline.am-secondary .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-checkbox.am-secondary .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-radio.am-secondary .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-checkbox-inline.am-secondary .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-radio-inline.am-secondary .am-ucheck-radio:checked + .am-ucheck-icons {\n  color: #3bb4f2;\n}\n.am-checkbox.am-success .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio.am-success .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox-inline.am-success .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio-inline.am-success .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox.am-success .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio.am-success .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox-inline.am-success .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio-inline.am-success .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons {\n  color: #5eb95e;\n}\n.am-checkbox.am-success .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-radio.am-success .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-checkbox-inline.am-success .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-radio-inline.am-success .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-checkbox.am-success .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-radio.am-success .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-checkbox-inline.am-success .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-radio-inline.am-success .am-ucheck-radio:checked + .am-ucheck-icons {\n  color: #5eb95e;\n}\n.am-checkbox.am-warning .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio.am-warning .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox-inline.am-warning .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio-inline.am-warning .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox.am-warning .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio.am-warning .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox-inline.am-warning .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio-inline.am-warning .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons {\n  color: #F37B1D;\n}\n.am-checkbox.am-warning .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-radio.am-warning .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-checkbox-inline.am-warning .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-radio-inline.am-warning .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-checkbox.am-warning .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-radio.am-warning .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-checkbox-inline.am-warning .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-radio-inline.am-warning .am-ucheck-radio:checked + .am-ucheck-icons {\n  color: #F37B1D;\n}\n.am-checkbox.am-danger .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio.am-danger .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox-inline.am-danger .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio-inline.am-danger .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox.am-danger .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio.am-danger .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox-inline.am-danger .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio-inline.am-danger .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons {\n  color: #dd514c;\n}\n.am-checkbox.am-danger .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-radio.am-danger .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-checkbox-inline.am-danger .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-radio-inline.am-danger .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-checkbox.am-danger .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-radio.am-danger .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-checkbox-inline.am-danger .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-radio-inline.am-danger .am-ucheck-radio:checked + .am-ucheck-icons {\n  color: #dd514c;\n}\n.am-field-error + .am-ucheck-icons {\n  color: #dd514c;\n}\n.am-field-valid + .am-ucheck-icons {\n  color: #5eb95e;\n}\n/*\n// Group Addon\n.@{ns}input-group-label {\n  .@{ns}radio,\n  .@{ns}checkbox {\n    margin: -2px 0;\n    padding-left: 15px;\n  }\n}\n\n// Form inline style\n.@{ns}form-inline .@{ns}checkbox,\n.@{ns}form-inline .@{ns}radio {\n  padding-left: 24px;\n}\n*/\n/* ==========================================================================\n   Component: Selected Plugin\n ============================================================================ */\n.am-selected {\n  width: 200px;\n}\n.am-selected-btn {\n  width: 100%;\n  padding-left: 10px;\n  text-align: right;\n}\n.am-selected-btn.am-btn-default {\n  background: none;\n}\n.am-invalid .am-selected-btn {\n  border-color: #dd514c;\n}\n.am-selected-header {\n  height: 45px;\n  background-color: #f2f2f2;\n  border-bottom: 1px solid #ddd;\n  display: none;\n}\n.am-selected-status {\n  text-align: left;\n  width: 100%;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-selected-content {\n  padding: 10px 0;\n}\n.am-selected-search {\n  padding: 0 10px 10px;\n}\n.am-selected-search .am-form-field {\n  padding: .5em;\n}\n.am-selected-list {\n  margin: 0;\n  padding: 0;\n  list-style: none;\n  font-size: 1.5rem;\n}\n.am-selected-list li {\n  position: relative;\n  cursor: pointer;\n  padding: 5px 10px;\n  -webkit-transition: background-color 0.15s;\n  transition: background-color 0.15s;\n}\n.am-selected-list li:hover {\n  background-color: #f8f8f8;\n}\n.am-selected-list li:hover .am-icon-check {\n  opacity: .6;\n}\n.am-selected-list li.am-checked .am-icon-check {\n  opacity: 1;\n  color: #0e90d2;\n}\n.am-selected-list li.am-disabled {\n  opacity: .5;\n  pointer-events: none;\n  cursor: not-allowed;\n}\n.am-selected-list .am-selected-list-header {\n  margin-top: 8px;\n  font-size: 1.3rem;\n  color: #999999;\n  border-bottom: 1px solid #e5e5e5;\n  cursor: default;\n}\n.am-selected-list .am-selected-list-header:hover {\n  background: none;\n}\n.am-selected-list .am-selected-list-header:first-child {\n  margin-top: 0;\n}\n.am-selected-list .am-selected-text {\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n  margin-right: 30px;\n}\n.am-selected-list .am-icon-check {\n  position: absolute;\n  right: 8px;\n  top: 5px;\n  color: #999999;\n  opacity: 0;\n  -webkit-transition: opacity .15s;\n  transition: opacity .15s;\n}\n.am-selected-hint {\n  line-height: 1.2;\n  color: #dd514c;\n}\n.am-selected-hint:not(:empty) {\n  margin-top: 10px;\n  border-top: 1px solid #e5e5e5;\n  padding: 10px 10px 0;\n}\n.am-selected-placeholder {\n  opacity: .65;\n}\n/* ==========================================================================\n   Component: JS Plugins helpers\n ============================================================================ */\n.am-fade {\n  opacity: 0;\n  -webkit-transition: opacity .2s linear;\n  transition: opacity .2s linear;\n}\n.am-fade.am-in {\n  opacity: 1;\n}\n.am-collapse {\n  display: none;\n}\n.am-collapse.am-in {\n  display: block;\n}\ntr.am-collapse.am-in {\n  display: table-row;\n}\ntbody.am-collapse.am-in {\n  display: table-row-group;\n}\n.am-collapsing {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height .3s ease;\n  transition: height .3s ease;\n}\n.am-sticky {\n  position: fixed !important;\n  z-index: 1010;\n  -webkit-transform-origin: 0 0;\n      -ms-transform-origin: 0 0;\n          transform-origin: 0 0;\n}\n[data-am-sticky][class*=\"am-animation-\"] {\n  -webkit-animation-duration: .2s;\n          animation-duration: .2s;\n}\n.am-dimmer-active {\n  overflow: hidden;\n}\n.am-dimmer {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  display: none;\n  width: 100%;\n  height: 100%;\n  background-color: rgba(0, 0, 0, 0.6);\n  z-index: 1100;\n  opacity: 0;\n}\n.am-dimmer.am-active {\n  opacity: 1;\n}\n[data-am-collapse] {\n  cursor: pointer;\n}\n.am-datepicker {\n  top: 0;\n  left: 0;\n  border-radius: 0;\n  background: #fff;\n  -webkit-box-shadow: 0 0 10px #ccc;\n          box-shadow: 0 0 10px #ccc;\n  padding-bottom: 10px;\n  margin-top: 10px;\n  width: 238px;\n  color: #555;\n  display: none;\n}\n.am-datepicker > div {\n  display: none;\n}\n.am-datepicker table {\n  width: 100%;\n}\n.am-datepicker tr.am-datepicker-header {\n  font-size: 1.6rem;\n  color: #fff;\n  background: #3bb4f2;\n}\n.am-datepicker td,\n.am-datepicker th {\n  text-align: center;\n  font-weight: normal;\n  cursor: pointer;\n}\n.am-datepicker th {\n  height: 48px;\n}\n.am-datepicker td {\n  font-size: 1.4rem;\n}\n.am-datepicker td.am-datepicker-day {\n  height: 34px;\n  width: 34px;\n}\n.am-datepicker td.am-datepicker-day:hover {\n  background: #F0F0F0;\n  height: 34px;\n  width: 34px;\n}\n.am-datepicker td.am-datepicker-day.am-disabled {\n  cursor: no-drop;\n  color: #999;\n  background: #fafafa;\n}\n.am-datepicker td.am-datepicker-old,\n.am-datepicker td.am-datepicker-new {\n  color: #89d7ff;\n}\n.am-datepicker td.am-active,\n.am-datepicker td.am-active:hover {\n  border-radius: 0;\n  color: #0084c7;\n  background: #F0F0F0;\n}\n.am-datepicker td span {\n  display: block;\n  width: 79.33333333px;\n  height: 40px;\n  line-height: 40px;\n  float: left;\n  cursor: pointer;\n}\n.am-datepicker td span:hover {\n  background: #F0F0F0;\n}\n.am-datepicker td span.am-active {\n  color: #0084c7;\n  background: #F0F0F0;\n}\n.am-datepicker td span.am-disabled {\n  cursor: no-drop;\n  color: #999;\n  background: #fafafa;\n}\n.am-datepicker td span.am-datepicker-old {\n  color: #89d7ff;\n}\n.am-datepicker .am-datepicker-dow {\n  height: 40px;\n  color: #0c80ba;\n}\n.am-datepicker-caret {\n  display: block!important;\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: middle;\n  border-bottom: 7px solid #3bb4f2;\n  border-right: 7px solid transparent;\n  border-left: 7px solid transparent;\n  border-top: 0 dotted;\n  -webkit-transform: rotate(360deg);\n      -ms-transform: rotate(360deg);\n          transform: rotate(360deg);\n  position: absolute;\n  top: -7px;\n  left: 6px;\n}\n.am-datepicker-right .am-datepicker-caret {\n  left: auto;\n  right: 7px;\n}\n.am-datepicker-up .am-datepicker-caret {\n  top: auto;\n  bottom: -7px;\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: middle;\n  border-top: 7px solid #fff;\n  border-right: 7px solid transparent;\n  border-left: 7px solid transparent;\n  border-bottom: 0 dotted;\n  -webkit-transform: rotate(360deg);\n      -ms-transform: rotate(360deg);\n          transform: rotate(360deg);\n}\n.am-datepicker-select {\n  height: 34px;\n  line-height: 34px;\n  text-align: center;\n  -webkit-transition: background-color 300ms ease-out;\n  transition: background-color 300ms ease-out;\n}\n.am-datepicker-select:hover {\n  background: rgba(154, 217, 248, 0.5);\n  color: #0c80ba;\n}\n.am-datepicker-prev,\n.am-datepicker-next {\n  width: 34px;\n  height: 34px;\n}\n.am-datepicker-prev-icon,\n.am-datepicker-next-icon {\n  width: 34px;\n  height: 34px;\n  line-height: 34px;\n  display: inline-block;\n  -webkit-transition: background-color 300ms ease-out;\n  transition: background-color 300ms ease-out;\n}\n.am-datepicker-prev-icon:hover,\n.am-datepicker-next-icon:hover {\n  background: rgba(154, 217, 248, 0.5);\n  color: #0c80ba;\n}\n.am-datepicker-prev-icon:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f053\";\n}\n.am-datepicker-next-icon:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f054\";\n}\n.am-datepicker-dropdown {\n  position: absolute;\n  z-index: 1120;\n}\n@media only screen and (max-width: 640px) {\n  .am-datepicker {\n    width: 100%;\n  }\n  .am-datepicker td span {\n    width: 33.33%;\n  }\n  .am-datepicker-caret {\n    display: none!important;\n  }\n  .am-datepicker-prev,\n  .am-datepicker-next {\n    width: 44px;\n    height: 44px;\n  }\n}\n.am-datepicker-success tr.am-datepicker-header {\n  background: #5eb95e;\n}\n.am-datepicker-success td.am-datepicker-day.am-disabled {\n  color: #999;\n}\n.am-datepicker-success td.am-datepicker-old,\n.am-datepicker-success td.am-datepicker-new {\n  color: #94df94;\n}\n.am-datepicker-success td.am-active,\n.am-datepicker-success td.am-active:hover {\n  color: #1b961b;\n}\n.am-datepicker-success td span.am-datepicker-old {\n  color: #94df94;\n}\n.am-datepicker-success td span.am-active {\n  color: #1b961b;\n}\n.am-datepicker-success .am-datepicker-caret {\n  border-bottom-color: #5eb95e;\n}\n.am-datepicker-success .am-datepicker-dow {\n  color: #367b36;\n}\n.am-datepicker-success .am-datepicker-select:hover,\n.am-datepicker-success .am-datepicker-prev-icon:hover,\n.am-datepicker-success .am-datepicker-next-icon:hover {\n  background: rgba(165, 216, 165, 0.5);\n  color: #367b36;\n}\n.am-datepicker-danger tr.am-datepicker-header {\n  background: #dd514c;\n}\n.am-datepicker-danger td.am-datepicker-day.am-disabled {\n  color: #999;\n}\n.am-datepicker-danger td.am-datepicker-old,\n.am-datepicker-danger td.am-datepicker-new {\n  color: #f59490;\n}\n.am-datepicker-danger td.am-active,\n.am-datepicker-danger td.am-active:hover {\n  color: #c10802;\n}\n.am-datepicker-danger td span.am-datepicker-old {\n  color: #f59490;\n}\n.am-datepicker-danger td span.am-active {\n  color: #c10802;\n}\n.am-datepicker-danger .am-datepicker-caret {\n  border-bottom-color: #dd514c;\n}\n.am-datepicker-danger .am-datepicker-dow {\n  color: #a4241f;\n}\n.am-datepicker-danger .am-datepicker-select:hover,\n.am-datepicker-danger .am-datepicker-prev-icon:hover,\n.am-datepicker-danger .am-datepicker-next-icon:hover {\n  background: rgba(237, 164, 162, 0.5);\n  color: #a4241f;\n}\n.am-datepicker-warning tr.am-datepicker-header {\n  background: #F37B1D;\n}\n.am-datepicker-warning td.am-datepicker-day.am-disabled {\n  color: #999;\n}\n.am-datepicker-warning td.am-datepicker-old,\n.am-datepicker-warning td.am-datepicker-new {\n  color: #ffad6d;\n}\n.am-datepicker-warning td.am-active,\n.am-datepicker-warning td.am-active:hover {\n  color: #aa4b00;\n}\n.am-datepicker-warning td span.am-datepicker-old {\n  color: #ffad6d;\n}\n.am-datepicker-warning td span.am-active {\n  color: #aa4b00;\n}\n.am-datepicker-warning .am-datepicker-caret {\n  border-bottom-color: #F37B1D;\n}\n.am-datepicker-warning .am-datepicker-dow {\n  color: #a14c09;\n}\n.am-datepicker-warning .am-datepicker-select:hover,\n.am-datepicker-warning .am-datepicker-prev-icon:hover,\n.am-datepicker-warning .am-datepicker-next-icon:hover {\n  background: rgba(248, 180, 126, 0.5);\n  color: #a14c09;\n}\n.am-datepicker > div {\n  display: block;\n}\n.am-datepicker > div span.am-datepicker-hour {\n  width: 59.5px;\n}\n.am-datepicker-date {\n  display: block;\n}\n.am-datepicker-date.am-input-group {\n  display: table;\n}\n.am-datepicker-time-box {\n  padding: 30px 0 30px 0;\n}\n.am-datepicker-time-box strong {\n  font-size: 5.2rem;\n  display: inline-block;\n  height: 70px;\n  width: 70px;\n  line-height: 70px;\n  font-weight: normal;\n}\n.am-datepicker-time-box strong:hover {\n  border-radius: 4px;\n  background: #ECECEC;\n}\n.am-datepicker-time-box em {\n  display: inline-block;\n  height: 70px;\n  width: 20px;\n  line-height: 70px;\n  font-size: 5.2rem;\n  font-style: normal;\n}\n.am-datepicker-toggle {\n  text-align: center;\n  cursor: pointer;\n  padding: 10px 0;\n}\n.am-datepicker-toggle:hover {\n  background: #f0f0f0;\n}\n/* ==========================================================================\n   Component: Print\n ============================================================================ */\n@media print {\n  *,\n  *:before,\n  *:after {\n    background: transparent !important;\n    color: #000 !important;\n    /* Black prints faster: h5bp.com/s */\n    -webkit-box-shadow: none !important;\n            box-shadow: none !important;\n    text-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  /**\n   * Don't show links that are fragment identifiers,\n   * or use the `javascript:` pseudo protocol\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    /* h5bp.com/t */\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\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  @page {\n    margin: 0.5cm;\n  }\n  select {\n    background: #fff !important;\n  }\n  .am-topbar {\n    display: none;\n  }\n  .am-table td,\n  .am-table th {\n    background-color: #fff !important;\n  }\n  .am-table {\n    border-collapse: collapse !important;\n  }\n  .am-table-bordered th,\n  .am-table-bordered td {\n    border: 1px solid #ddd !important;\n  }\n}\n/* print helper classes */\n.am-print-block {\n  display: none !important;\n}\n@media print {\n  .am-print-block {\n    display: block !important;\n  }\n}\n.am-print-inline {\n  display: none !important;\n}\n@media print {\n  .am-print-inline {\n    display: inline !important;\n  }\n}\n.am-print-inline-block {\n  display: none !important;\n}\n@media print {\n  .am-print-inline-block {\n    display: inline-block !important;\n  }\n}\n@media print {\n  .am-print-hide {\n    display: none !important;\n  }\n}\n.lte9 #nprogress .nprogress-spinner {\n  display: none !important;\n}\n.lte8 .am-dimmer {\n  background-color: #000;\n  filter: alpha(opacity=60);\n}\n.lte8 .am-modal-actions {\n  display: none;\n}\n.lte8 .am-modal-actions.am-modal-active {\n  display: block;\n}\n.lte8 .am-offcanvas.am-active {\n  background: #000;\n}\n.lte8 .am-popover .am-popover-caret {\n  border: 8px solid transparent;\n}\n.lte8 .am-popover-top .am-popover-caret {\n  border-top: 8px solid #333333;\n  border-bottom: none;\n}\n.lte8 .am-popover-left .am-popover-caret {\n  right: -8px;\n  margin-top: -6px;\n  border-left: 8px solid #333333;\n  border-right: none;\n}\n.lte8 .am-popover-right .am-popover-caret {\n  left: -8px;\n  margin-top: -6px;\n  border-right: 8px solid #333333;\n  border-left: none;\n}\n.am-accordion-item {\n  margin: 0;\n}\n.am-accordion-title {\n  font-weight: normal;\n  cursor: pointer;\n}\n.am-accordion-item.am-disabled .am-accordion-title {\n  cursor: default;\n  pointer-events: none;\n}\n.am-accordion-bd {\n  margin: 0 !important;\n  padding: 0 !important;\n  border: none !important;\n}\n.am-accordion-content {\n  margin-top: 0;\n  padding: 0.8rem 1rem 1.2rem;\n  font-size: 1.4rem;\n}\n/**\n  * Accordion Theme: default\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-accordion-default {\n  margin: 1rem;\n  border-radius: 2px;\n  -webkit-box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);\n}\n.am-accordion-default .am-accordion-item {\n  border-top: 1px solid rgba(0, 0, 0, 0.05);\n}\n.am-accordion-default .am-accordion-item:first-child {\n  border-top: none;\n}\n.am-accordion-default .am-accordion-title {\n  color: rgba(0, 0, 0, 0.6);\n  -webkit-transition: background-color 0.2s ease-out;\n  transition: background-color 0.2s ease-out;\n  padding: .8rem 1rem;\n}\n.am-accordion-default .am-accordion-title:before {\n  content: \"\\f0da\";\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  -webkit-transition: -webkit-transform .2s ease;\n  transition: -webkit-transform .2s ease;\n  transition: transform .2s ease;\n  transition: transform .2s ease, -webkit-transform .2s ease;\n  -webkit-transform: rotate(0deg);\n      -ms-transform: rotate(0deg);\n          transform: rotate(0deg);\n  margin-right: 5px;\n}\n.am-accordion-default .am-accordion-title:hover {\n  color: #0e90d2;\n}\n.am-accordion-default .am-accordion-content {\n  color: #666;\n}\n.am-accordion-default .am-active .am-accordion-title {\n  background-color: #eeeeee;\n  color: #0e90d2;\n}\n.am-accordion-default .am-active .am-accordion-title:before {\n  -webkit-transform: rotate(90deg);\n      -ms-transform: rotate(90deg);\n          transform: rotate(90deg);\n}\n/**\n  * Accordion Theme: basic\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-accordion-basic {\n  margin: 1rem;\n}\n.am-accordion-basic .am-accordion-title {\n  color: #333333;\n  -webkit-transition: background-color 0.2s ease-out;\n  transition: background-color 0.2s ease-out;\n  padding: .8rem 0 0;\n}\n.am-accordion-basic .am-accordion-title:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f0da\";\n  -webkit-transition: -webkit-transform .2s ease;\n  transition: -webkit-transform .2s ease;\n  transition: transform .2s ease;\n  transition: transform .2s ease, -webkit-transform .2s ease;\n  -webkit-transform: rotate(0deg);\n      -ms-transform: rotate(0deg);\n          transform: rotate(0deg);\n  margin-right: .5rem;\n}\n.am-accordion-basic .am-accordion-content {\n  color: #666;\n}\n.am-accordion-basic .am-active .am-accordion-title {\n  color: #0e90d2;\n}\n.am-accordion-basic .am-active .am-accordion-title:before {\n  -webkit-transform: rotate(90deg);\n      -ms-transform: rotate(90deg);\n          transform: rotate(90deg);\n}\n/**\n  * Accordion Theme: gapped\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-accordion-gapped {\n  margin: .5rem 1rem;\n}\n.am-accordion-gapped .am-accordion-item {\n  border: 1px solid #dedede;\n  border-bottom: none;\n  margin: .5rem 0;\n}\n.am-accordion-gapped .am-accordion-item.am-active {\n  border-bottom: 1px solid #dedede;\n}\n.am-accordion-gapped .am-accordion-title {\n  color: rgba(0, 0, 0, 0.6);\n  -webkit-transition: background-color 0.15s ease-out;\n  transition: background-color 0.15s ease-out;\n  border-bottom: 1px solid #dedede;\n  padding: 0.8rem 2rem 0.8rem 1rem;\n  position: relative;\n}\n.am-accordion-gapped .am-accordion-title:after {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f105\";\n  -webkit-transition: -webkit-transform .2s linear;\n  transition: -webkit-transform .2s linear;\n  transition: transform .2s linear;\n  transition: transform .2s linear, -webkit-transform .2s linear;\n  position: absolute;\n  right: 10px;\n  top: 50%;\n  margin-top: -0.8rem;\n}\n.am-accordion-gapped .am-accordion-title:hover {\n  color: rgba(0, 0, 0, 0.8);\n}\n.am-accordion-gapped .am-accordion-content {\n  color: #666;\n}\n.am-accordion-gapped .am-active .am-accordion-title {\n  background-color: #f5f5f5;\n  color: rgba(0, 0, 0, 0.8);\n}\n.am-accordion-gapped .am-active .am-accordion-title:after {\n  -webkit-transform: rotate(90deg);\n      -ms-transform: rotate(90deg);\n          transform: rotate(90deg);\n}\n.am-divider {\n  height: 0;\n  margin: 1.5rem auto;\n  overflow: hidden;\n  clear: both;\n}\n/**\n  * Divider Theme: default\n  */\n.am-divider-default {\n  border-top: 1px solid #ddd;\n}\n/**\n  * Divider Theme: dotted\n  */\n.am-divider-dotted {\n  border-top: 1px dotted #ccc;\n}\n/**\n  * Divider Theme: dashed\n  */\n.am-divider-dashed {\n  border-top: 1px dashed #ccc;\n}\n.am-figure-zoomable {\n  position: relative;\n  cursor: pointer;\n}\n.am-figure-zoomable:after {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f00e\";\n  position: absolute;\n  top: 1rem;\n  right: 1rem;\n  color: #999999;\n  font-size: 1.6rem;\n  -webkit-transition: all 0.2s;\n  transition: all 0.2s;\n  pointer-events: none;\n}\n.am-figure-zoomable:hover:after {\n  color: #eeeeee;\n}\n.am-figure-default {\n  margin: 10px;\n}\n.am-figure-default img {\n  display: block;\n  max-width: 100%;\n  height: auto;\n  padding: 2px;\n  border: 1px solid #eeeeee;\n  margin: 10px auto;\n}\n.am-figure-default figcaption {\n  text-align: center;\n  font-size: 1.4rem;\n  margin-bottom: 15px;\n  color: #333333;\n}\n.am-footer {\n  text-align: center;\n  padding: 1em 0;\n  font-size: 1.6rem;\n}\n.am-footer .am-switch-mode-ysp {\n  cursor: pointer;\n}\n.am-footer .am-footer-text {\n  margin-top: 10px;\n  font-size: 14px;\n}\n.am-footer .am-footer-text-left {\n  text-align: left;\n  padding-left: 10px;\n}\n.am-modal-footer-hd {\n  padding-bottom: 10px;\n}\n/**\n  * Footer Theme: default\n  */\n.am-footer-default {\n  background-color: #fff;\n}\n.am-footer-default a {\n  color: #555555;\n}\n.am-footer-default .am-footer-switch {\n  margin-bottom: 10px;\n  font-weight: bold;\n}\n.am-footer-default .am-footer-ysp {\n  color: #555555;\n  cursor: pointer;\n}\n.am-footer-default .am-footer-divider {\n  color: #ccc;\n}\n.am-footer-default .am-footer-desktop {\n  color: #0e90d2;\n}\n.am-footer-default .am-footer-miscs {\n  color: #999999;\n  font-size: 13px;\n}\n.am-footer-default .am-footer-miscs p {\n  margin: 5px 0;\n}\n@media only screen and (min-width:641px) {\n  .am-footer-default .am-footer-miscs p {\n    display: inline-block;\n    margin: 5px;\n  }\n}\n.am-gallery {\n  padding: 5px 5px 0 5px;\n  list-style: none;\n}\n.am-gallery h3 {\n  margin: 0;\n}\n[data-am-gallery*='pureview'] img {\n  cursor: pointer;\n}\n/**\n  * Gallery Theme: default\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-gallery-default > li {\n  padding: 5px;\n}\n.am-gallery-default .am-gallery-item img {\n  width: 100%;\n  height: auto;\n}\n.am-gallery-default .am-gallery-title {\n  margin-top: 10px;\n  font-weight: normal;\n  font-size: 1.4rem;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n  color: #555555;\n}\n.am-gallery-default .am-gallery-desc {\n  color: #999999;\n  font-size: 1.2rem;\n}\n/**\n  * Gallery Theme: overlay\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-gallery-overlay > li {\n  padding: 5px;\n}\n.am-gallery-overlay .am-gallery-item {\n  position: relative;\n}\n.am-gallery-overlay .am-gallery-item img {\n  width: 100%;\n  height: auto;\n}\n.am-gallery-overlay .am-gallery-title {\n  font-weight: normal;\n  font-size: 1.4rem;\n  color: #FFF;\n  position: absolute;\n  bottom: 0;\n  width: 100%;\n  background-color: rgba(0, 0, 0, 0.5);\n  text-indent: 5px;\n  height: 30px;\n  line-height: 30px;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-gallery-overlay .am-gallery-desc {\n  display: none;\n}\n/**\n  * Accordion Theme: bordered\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-gallery-bordered > li {\n  padding: 5px;\n}\n.am-gallery-bordered .am-gallery-item {\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.35);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.35);\n  padding: 5px;\n}\n.am-gallery-bordered .am-gallery-item img {\n  width: 100%;\n  height: auto;\n}\n.am-gallery-bordered .am-gallery-title {\n  margin-top: 10px;\n  font-weight: normal;\n  font-size: 1.4rem;\n  color: #555555;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-gallery-bordered .am-gallery-desc {\n  color: #999999;\n  font-size: 1.2rem;\n}\n/**\n  * Gallery Theme: imgbordered\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-gallery-imgbordered > li {\n  padding: 5px;\n}\n.am-gallery-imgbordered .am-gallery-item img {\n  width: 100%;\n  height: auto;\n  border: 3px solid #FFF;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.35);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.35);\n}\n.am-gallery-imgbordered .am-gallery-title {\n  margin-top: 10px;\n  font-weight: normal;\n  font-size: 1.4rem;\n  color: #555555;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-gallery-imgbordered .am-gallery-desc {\n  color: #999999;\n  font-size: 1.2rem;\n}\n.am-gotop a {\n  display: inline-block;\n  text-decoration: none;\n}\n/**\n  * Gotop Theme: default\n  */\n.am-gotop-default {\n  text-align: center;\n  margin: 10px 0;\n}\n.am-gotop-default a {\n  background-color: #0e90d2;\n  padding: .5em 1.5em;\n  border-radius: 0;\n  color: #fff;\n}\n.am-gotop-default a img {\n  display: none;\n}\n/**\n  * Gotop Theme: fixed\n  */\n.am-gotop-fixed {\n  position: fixed;\n  right: 10px;\n  bottom: 10px;\n  z-index: 1010;\n  opacity: 0;\n  width: 32px;\n  min-height: 32px;\n  overflow: hidden;\n  border-radius: 0;\n  text-align: center;\n}\n.am-gotop-fixed.am-active {\n  opacity: .9;\n}\n.am-gotop-fixed.am-active:hover {\n  opacity: 1;\n}\n.am-gotop-fixed a {\n  display: block;\n}\n.am-gotop-fixed .am-gotop-title {\n  display: none;\n}\n.am-gotop-fixed .am-gotop-icon-custom {\n  display: inline-block;\n  max-width: 30px;\n  vertical-align: middle;\n}\n.am-gotop-fixed .am-gotop-icon {\n  width: 100%;\n  line-height: 32px;\n  background-color: #555555;\n  vertical-align: middle;\n  color: #ddd;\n}\n.am-gotop-fixed .am-gotop-icon:hover {\n  color: #fff;\n}\n.am-with-fixed-navbar .am-gotop-fixed {\n  bottom: 60px;\n}\n.am-header {\n  position: relative;\n  width: 100%;\n  height: 49px;\n  line-height: 49px;\n  padding: 0 10px;\n}\n.am-header h1 {\n  margin-top: 0;\n  margin-bottom: 0;\n}\n.am-header .am-header-title {\n  margin: 0 30%;\n  font-size: 2rem;\n  font-weight: normal;\n  text-align: center;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-header .am-header-title img {\n  margin-top: 12px;\n  height: 25px;\n  vertical-align: top;\n}\n.am-header .am-header-nav {\n  position: absolute;\n  top: 0;\n}\n.am-header .am-header-nav img {\n  height: 16px;\n  width: auto;\n  vertical-align: middle;\n}\n.am-header .am-header-left {\n  left: 10px;\n}\n.am-header .am-header-right {\n  right: 10px;\n}\n.am-header-fixed {\n  position: fixed;\n  top: 0;\n  left: 0;\n  right: 0;\n  width: 100%;\n  z-index: 1010;\n}\n.am-with-fixed-header {\n  padding-top: 49px;\n}\n/**\n  * Header Theme: default\n  */\n.am-header-default {\n  background-color: #0e90d2;\n}\n.am-header-default .am-header-title {\n  color: #fff;\n}\n.am-header-default .am-header-title a {\n  color: #fff;\n}\n.am-header-default .am-header-icon {\n  font-size: 20px;\n}\n.am-header-default .am-header-nav {\n  color: #eeeeee;\n}\n.am-header-default .am-header-nav > a {\n  display: inline-block;\n  min-width: 36px;\n  text-align: center;\n  color: #eeeeee;\n}\n.am-header-default .am-header-nav > a + a {\n  margin-left: 5px;\n}\n.am-header-default .am-header-nav .am-btn {\n  margin-top: 9px;\n  height: 31px;\n  padding: 0 0.5em;\n  line-height: 30px;\n  font-size: 14px;\n  vertical-align: top;\n}\n.am-header-default .am-header-nav .am-btn .am-header-icon {\n  font-size: inherit;\n}\n.am-header-default .am-header-nav .am-btn-default {\n  color: #999999;\n}\n.am-header-default .am-header-nav-title,\n.am-header-default .am-header-nav-title + .am-header-icon {\n  font-size: 14px;\n}\n.am-intro {\n  position: relative;\n}\n.am-intro img {\n  max-width: 100%;\n}\n.am-intro-hd {\n  position: relative;\n  height: 45px;\n  line-height: 45px;\n}\n.am-intro-title {\n  font-size: 18px;\n  margin: 0;\n  font-weight: bold;\n}\n.am-intro-more-top {\n  position: absolute;\n  right: 10px;\n  top: 0;\n  font-size: 1.4rem;\n}\n.am-intro-bd {\n  padding-top: 15px;\n  padding-bottom: 15px;\n  font-size: 1.4rem;\n}\n.am-intro-bd p:last-child {\n  margin-bottom: 0;\n}\n.am-intro-more-bottom {\n  clear: both;\n  text-align: center;\n}\n.am-intro-more-bottom .am-btn {\n  font-size: 14px;\n}\n/**\n  * Intro Theme: default\n  */\n.am-intro-default .am-intro-hd {\n  background-color: #0e90d2;\n  color: #fff;\n  padding: 0 10px;\n}\n.am-intro-default .am-intro-hd a {\n  color: #eee;\n}\n.am-intro-default .am-intro-right {\n  padding-left: 0;\n}\n.am-list-news-hd {\n  padding-top: 1.2rem;\n  padding-bottom: 0.8rem;\n}\n.am-list-news-hd a {\n  display: block;\n}\n.am-list-news-hd h2 {\n  font-size: 1.6rem;\n  float: left;\n  margin: 0;\n  height: 2rem;\n  line-height: 2rem;\n}\n.am-list-news-hd h3 {\n  margin: 0;\n}\n.am-list-news-hd .am-list-news-more {\n  font-size: 1.3rem;\n  height: 2rem;\n  line-height: 2rem;\n}\n.am-list .am-list-item-dated a {\n  padding-right: 80px;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-list .am-list-item-dated a::after {\n  display: none;\n}\n.am-list .am-list-item-desced a,\n.am-list .am-list-item-thumbed a {\n  padding-right: 0;\n}\n.am-list-news .am-list-item-hd {\n  margin: 0;\n}\n.am-list-date {\n  position: absolute;\n  right: 5px;\n  font-size: 1.3rem;\n  top: 1.3rem;\n}\n.am-list-item-desced {\n  padding-bottom: 1rem;\n}\n.am-list-item-desced > a {\n  padding: 1rem 0;\n}\n.am-list-item-desced .am-list-date {\n  position: static;\n}\n.am-list-item-thumbed {\n  padding-top: 1em;\n}\n.am-list-news-ft {\n  text-align: center;\n}\n.am-list-news .am-titlebar {\n  margin-left: 0;\n  margin-right: 0;\n}\n.am-list-news .am-titlebar ~ .am-list-news-bd .am-list > li:first-child {\n  border-top: none;\n}\n/**\n  * list_news Theme: default\n  */\n.am-list-news-default {\n  margin: 10px;\n}\n.am-list-news-default .am-g {\n  margin-left: auto;\n  margin-right: auto;\n}\n.am-list-news-default .am-list-item-hd {\n  font-weight: normal;\n}\n.am-list-news-default .am-list-date {\n  color: #999999;\n}\n.am-list-news-default .am-list > li {\n  border-color: #dedede;\n}\n.am-list-news-default .am-list .am-list-item-desced {\n  padding-top: 1rem;\n  padding-bottom: 1rem;\n}\n.am-list-news-default .am-list .am-list-item-desced > a {\n  padding: 0;\n}\n.am-list-news-default .am-list .am-list-item-desced .am-list-item-text {\n  margin-top: 0.5rem;\n  color: #757575;\n}\n.am-list-news-default .am-list .am-list-item-text {\n  overflow: hidden;\n  text-overflow: ellipsis;\n  display: -webkit-box;\n  -webkit-box-orient: vertical;\n  line-height: 1.3em;\n  -webkit-line-clamp: 2;\n  /* number of lines to show */\n  max-height: 2.6em;\n}\n.am-list-news-default .am-list .am-list-item-thumb-top .am-list-thumb {\n  padding: 0;\n  margin-bottom: 0.8rem;\n}\n.am-list-news-default .am-list .am-list-item-thumb-top .am-list-main {\n  padding: 0;\n}\n.am-list-news-default .am-list .am-list-item-thumb-left .am-list-thumb {\n  padding-left: 0;\n}\n.am-list-news-default .am-list .am-list-item-desced .am-list-main {\n  padding: 0;\n}\n.am-list-news-default .am-list .am-list-item-thumb-right .am-list-thumb {\n  padding-right: 0;\n}\n.am-list-news-default .am-list .am-list-item-thumb-bottom-left .am-list-item-hd {\n  clear: both;\n  padding-bottom: 0.5rem;\n}\n.am-list-news-default .am-list .am-list-item-thumb-bottom-left .am-list-thumb {\n  padding-left: 0;\n}\n.am-list-news-default .am-list .am-list-item-thumb-bottom-right .am-list-item-hd {\n  clear: both;\n  padding-bottom: 0.5rem;\n}\n.am-list-news-default .am-list .am-list-item-thumb-bottom-right .am-list-thumb {\n  padding-right: 0;\n}\n.am-list-news-default .am-list .am-list-thumb img {\n  width: 100%;\n  display: block;\n}\n@media only screen and (max-width: 640px) {\n  .am-list-news-default .am-list-item-thumb-left .am-list-thumb,\n  .am-list-news-default .am-list-item-thumb-right .am-list-thumb {\n    max-height: 80px;\n    overflow: hidden;\n  }\n  .am-list-news-default .am-list-item-thumb-bottom-left .am-list-item-text,\n  .am-list-news-default .am-list-item-thumb-bottom-right .am-list-item-text {\n    -webkit-line-clamp: 3;\n    /* number of lines to show */\n    max-height: 3.9em;\n  }\n  .am-list-news-default .am-list-item-thumb-bottom-left .am-list-thumb,\n  .am-list-news-default .am-list-item-thumb-bottom-right .am-list-thumb {\n    max-height: 60px;\n    overflow: hidden;\n  }\n}\n.am-map {\n  width: 100%;\n  height: 300px;\n}\n/**\n  * Accordion Theme: default\n  * Author: Hzp (hzp@yunshipei.com)\n  */\n.am-map-default #bd-map {\n  width: 100%;\n  height: 100%;\n  overflow: hidden;\n  margin: 0;\n  font-size: 14px;\n  line-height: 1.4!important;\n}\n.am-map-default .BMap_bubble_title {\n  font-weight: bold;\n}\n.am-map-default #BMap_mask {\n  width: 100%;\n}\n.am-mechat {\n  margin: 1rem;\n}\n.am-mechat .section-cbox-wap .cbox-post-wap .post-action-wap .action-function-wap .function-list-wap .list-upload-wap .upload-mutual-wap {\n  -webkit-box-sizing: content-box;\n          box-sizing: content-box;\n}\n.am-menu {\n  position: relative;\n  padding: 0;\n  margin: 0;\n}\n.am-menu ul {\n  padding: 0;\n  margin: 0;\n}\n.am-menu li {\n  list-style: none;\n}\n.am-menu a:after,\n.am-menu a:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n}\n.am-menu-sub {\n  z-index: 1050;\n}\n.am-menu-toggle {\n  display: none;\n  z-index: 1015;\n}\n.am-menu-toggle img {\n  display: inline-block;\n  height: 16px;\n  width: auto;\n  vertical-align: middle;\n}\n.am-menu-nav a {\n  display: block;\n  padding: 0.8rem 0;\n  -webkit-transition: all 0.45s;\n  transition: all 0.45s;\n}\n/**\n  * Menu Theme: default\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-menu-default .am-menu-nav {\n  padding-top: 8px;\n  padding-bottom: 8px;\n}\n.am-menu-default .am-menu-nav a {\n  text-align: center;\n  height: 36px;\n  line-height: 36px;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n  padding: 0;\n  color: #0e90d2;\n}\n.am-menu-default .am-menu-nav > .am-parent > a {\n  position: relative;\n  -webkit-transition: .15s;\n  transition: .15s;\n}\n.am-menu-default .am-menu-nav > .am-parent > a:after {\n  content: \"\\f107\";\n  margin-left: 5px;\n  -webkit-transition: .15s;\n  transition: .15s;\n}\n.am-menu-default .am-menu-nav > .am-parent > a:before {\n  position: absolute;\n  top: 100%;\n  margin-top: -16px;\n  left: 50%;\n  margin-left: -12px;\n  content: \"\\f0d8\";\n  display: none;\n  color: #f1f1f1;\n  font-size: 24px;\n}\n.am-menu-default .am-menu-nav > .am-parent.am-open > a {\n  color: #095f8a;\n}\n.am-menu-default .am-menu-nav > .am-parent.am-open > a:before {\n  display: block;\n}\n.am-menu-default .am-menu-nav > .am-parent.am-open > a:after {\n  -webkit-transform: rotate(-180deg);\n      -ms-transform: rotate(-180deg);\n          transform: rotate(-180deg);\n}\n.am-menu-default .am-menu-sub {\n  position: absolute;\n  left: 5px;\n  right: 5px;\n  background-color: #f1f1f1;\n  border-radius: 0;\n  padding-top: 8px;\n  padding-bottom: 8px;\n}\n.am-menu-default .am-menu-sub > li > a {\n  color: #555555;\n}\n@media only screen and (min-width:641px) {\n  .am-menu-default .am-menu-nav li {\n    width: auto;\n    float: left;\n    clear: none;\n    display: inline;\n  }\n  .am-menu-default .am-menu-nav a {\n    padding-left: 1.5rem;\n    padding-right: .5rem;\n  }\n}\n/**\n/**\n  * Menu Theme: dropdown1\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-menu-dropdown1 {\n  position: relative;\n  /*@media @medium-up {\n    .am-menu-toggle {\n      display: none!important;\n    }\n\n    .am-menu-nav {\n      &.am-collapse {\n        display: block;\n      }\n\n      .am-menu-sub {\n        background-color: ;//@menu-sub-bg;\n        display: block;\n        & > li {\n          clear: none;\n\n        }\n      }\n\n      .am-menu-lv2 {\n        & > li {\n          clear: none;\n          width: auto;\n        }\n      }\n    }\n  }*/\n}\n.am-menu-dropdown1 .am-menu-toggle {\n  position: absolute;\n  right: 5px;\n  top: -47px;\n  display: block;\n  width: 44px;\n  height: 44px;\n  line-height: 44px;\n  text-align: center;\n  color: #fff;\n}\n.am-menu-dropdown1 a {\n  -webkit-transition: all .4s;\n  transition: all .4s;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-menu-dropdown1 .am-menu-nav {\n  position: absolute;\n  left: 0;\n  right: 0;\n  z-index: 1050;\n}\n.am-menu-dropdown1 .am-menu-nav a {\n  padding: 0.8rem;\n}\n.am-menu-dropdown1 .am-menu-nav > li {\n  width: 100%;\n}\n.am-menu-dropdown1 .am-menu-nav > li.am-parent > a {\n  position: relative;\n}\n.am-menu-dropdown1 .am-menu-nav > li.am-parent > a::before {\n  content: \"\\f067\";\n  position: absolute;\n  right: 1rem;\n  top: 1.4rem;\n}\n.am-menu-dropdown1 .am-menu-nav > li.am-parent.am-open > a {\n  background-color: #0c80ba;\n  border-bottom: none;\n  color: #fff;\n}\n.am-menu-dropdown1 .am-menu-nav > li.am-parent.am-open > a:before {\n  content: \"\\f068\";\n}\n.am-menu-dropdown1 .am-menu-nav > li.am-parent.am-open > a:after {\n  content: \"\";\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: middle;\n  border-top: 8px solid #0c80ba;\n  border-right: 8px solid transparent;\n  border-left: 8px solid transparent;\n  border-bottom: 0 dotted;\n  -webkit-transform: rotate(360deg);\n      -ms-transform: rotate(360deg);\n          transform: rotate(360deg);\n  position: absolute;\n  top: 100%;\n  left: 50%;\n  margin-left: -4px;\n}\n.am-menu-dropdown1 .am-menu-nav > li > a {\n  border-bottom: 1px solid #0b76ac;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);\n  background-color: #0e90d2;\n  color: #fff;\n  height: 49px;\n  line-height: 49px;\n  padding: 0;\n  text-indent: 10px;\n}\n.am-menu-dropdown1 .am-menu-sub {\n  background-color: #fff;\n}\n.am-menu-dropdown1 .am-menu-sub a {\n  color: #555;\n  height: 44px;\n  line-height: 44px;\n  text-indent: 5px;\n  padding: 0;\n}\n.am-menu-dropdown1 .am-menu-sub a:before {\n  content: \"\\f105\";\n  color: #aaa;\n  font-size: 16px;\n  margin-right: 5px;\n}\n/**\n  * Menu Theme: dropdown2\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-menu-dropdown2 .am-menu-toggle {\n  position: absolute;\n  right: 5px;\n  top: -47px;\n  display: block;\n  width: 44px;\n  height: 44px;\n  line-height: 44px;\n  text-align: center;\n  color: #fff;\n}\n.am-menu-dropdown2 .am-menu-nav {\n  position: absolute;\n  left: 0;\n  right: 0;\n  background-color: #f5f5f5;\n  -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);\n  z-index: 1050;\n  padding-top: 8px;\n  padding-bottom: 8px;\n}\n.am-menu-dropdown2 .am-menu-nav a {\n  height: 38px;\n  line-height: 38px;\n  padding: 0;\n  text-align: center;\n}\n.am-menu-dropdown2 .am-menu-nav > li > a {\n  color: #333333;\n}\n.am-menu-dropdown2 .am-menu-nav > li.am-parent > a {\n  position: relative;\n}\n.am-menu-dropdown2 .am-menu-nav > li.am-parent > a:after {\n  content: \"\\f107\";\n  margin-left: 5px;\n  -webkit-transition: -webkit-transform .2s;\n  transition: -webkit-transform .2s;\n  transition: transform .2s;\n  transition: transform .2s, -webkit-transform .2s;\n}\n.am-menu-dropdown2 .am-menu-nav > li.am-parent.am-open > a {\n  position: relative;\n}\n.am-menu-dropdown2 .am-menu-nav > li.am-parent.am-open > a:after {\n  color: #0e90d2;\n  -webkit-transform: rotate(180deg);\n      -ms-transform: rotate(180deg);\n          transform: rotate(180deg);\n}\n.am-menu-dropdown2 .am-menu-nav > li.am-parent.am-open > a:before {\n  position: absolute;\n  top: 100%;\n  margin-top: -16px;\n  left: 50%;\n  margin-left: -12px;\n  font-size: 24px;\n  content: \"\\f0d8\";\n  color: rgba(0, 0, 0, 0.2);\n}\n.am-menu-dropdown2 .am-menu-sub {\n  position: absolute;\n  left: 5px;\n  right: 5px;\n  padding: 8px 0;\n  border-radius: 2px;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n  background-color: #fff;\n  z-index: 1055;\n}\n.am-menu-dropdown2 .am-menu-sub a {\n  padding: 0;\n  height: 35px;\n  color: #555555;\n  line-height: 35px;\n}\n@media only screen and (min-width:641px) {\n  .am-menu-dropdown2 .am-menu-toggle {\n    display: none !important;\n  }\n  .am-menu-dropdown2 .am-menu-nav {\n    position: static;\n    display: block;\n  }\n  .am-menu-dropdown2 .am-menu-nav > li {\n    float: none;\n    width: auto;\n    display: inline-block;\n  }\n  .am-menu-dropdown2 .am-menu-nav > li a {\n    padding-left: 1.5rem;\n    padding-right: 1.5rem;\n  }\n  .am-menu-dropdown2 .am-menu-sub {\n    left: auto;\n    right: auto;\n  }\n  .am-menu-dropdown2 .am-menu-sub > li {\n    float: none;\n    width: auto;\n  }\n  .am-menu-dropdown2 .am-menu-sub a {\n    padding-left: 2rem;\n    padding-right: 2rem;\n  }\n}\n/**\n  * Menu Theme: slide1\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-menu-slide1 .am-menu-toggle {\n  position: absolute;\n  right: 5px;\n  top: -47px;\n  display: block;\n  width: 44px;\n  height: 44px;\n  line-height: 44px;\n  text-align: center;\n  color: #fff;\n}\n.am-menu-slide1 .am-menu-nav {\n  background-color: #f5f5f5;\n  padding-top: 8px;\n  padding-bottom: 8px;\n}\n.am-menu-slide1 .am-menu-nav.am-in:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f0d8\";\n  font-size: 24px;\n  color: #f5f5f5;\n  position: absolute;\n  right: 16px;\n  top: -16px;\n}\n.am-menu-slide1 .am-menu-nav a {\n  line-height: 38px;\n  height: 38px;\n  display: block;\n  padding: 0;\n  text-align: center;\n}\n.am-menu-slide1 .am-menu-nav > li > a {\n  color: #333333;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-menu-slide1 .am-menu-nav > .am-parent > a {\n  position: relative;\n  -webkit-transition: .15s;\n  transition: .15s;\n}\n.am-menu-slide1 .am-menu-nav > .am-parent > a:after {\n  content: \"\\f107\";\n  margin-left: 5px;\n  -webkit-transition: .15s;\n  transition: .15s;\n}\n.am-menu-slide1 .am-menu-nav > .am-parent > a:before {\n  position: absolute;\n  top: 100%;\n  margin-top: -16px;\n  left: 50%;\n  margin-left: -12px;\n  content: \"\\f0d8\";\n  display: none;\n  color: #0e90d2;\n  font-size: 24px;\n}\n.am-menu-slide1 .am-menu-nav > .am-parent.am-open > a {\n  color: #0e90d2;\n}\n.am-menu-slide1 .am-menu-nav > .am-parent.am-open > a:before {\n  display: block;\n}\n.am-menu-slide1 .am-menu-nav > .am-parent.am-open > a:after {\n  -webkit-transform: rotate(-180deg);\n      -ms-transform: rotate(-180deg);\n          transform: rotate(-180deg);\n}\n.am-menu-slide1 .am-menu-sub {\n  position: absolute;\n  left: 5px;\n  right: 5px;\n  background-color: #0e90d2;\n  border-radius: 0;\n  padding-top: 8px;\n  padding-bottom: 8px;\n}\n.am-menu-slide1 .am-menu-sub > li > a {\n  color: #fff;\n}\n@media only screen and (min-width:641px) {\n  .am-menu-slide1 .am-menu-toggle {\n    display: none !important;\n  }\n  .am-menu-slide1 .am-menu-nav {\n    background-color: #f5f5f5;\n    display: block;\n  }\n  .am-menu-slide1 .am-menu-nav.am-in:before {\n    display: none;\n  }\n  .am-menu-slide1 .am-menu-nav li {\n    width: auto;\n    clear: none;\n  }\n  .am-menu-slide1 .am-menu-nav li a {\n    padding-left: 1.5rem;\n    padding-right: 1.5rem;\n  }\n}\n/**\n  * Menu Theme: offcanvas1\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-menu-offcanvas1 .am-menu-toggle {\n  position: absolute;\n  right: 5px;\n  top: -47px;\n  display: block;\n  width: 44px;\n  height: 44px;\n  line-height: 44px;\n  text-align: center;\n  color: #fff;\n}\n.am-menu-offcanvas1 .am-menu-nav {\n  border-bottom: 1px solid rgba(0, 0, 0, 0.3);\n  -webkit-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.05);\n          box-shadow: 0 1px 0 rgba(255, 255, 255, 0.05);\n}\n.am-menu-offcanvas1 .am-menu-nav > li > a {\n  height: 44px;\n  line-height: 44px;\n  text-indent: 15px;\n  padding: 0;\n  position: relative;\n  color: #ccc;\n  border-top: 1px solid rgba(0, 0, 0, 0.3);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);\n  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.5);\n}\n.am-menu-offcanvas1 .am-menu-nav > .am-open > a,\n.am-menu-offcanvas1 .am-menu-nav > li > a:hover,\n.am-menu-offcanvas1 .am-menu-nav > li > a:focus {\n  background-color: #474747;\n  color: #fff;\n  outline: none;\n}\n.am-menu-offcanvas1 .am-menu-nav > .am-active > a {\n  background-color: #1a1a1a;\n  color: #fff;\n}\n.am-menu-offcanvas1 .am-menu-nav > .am-parent > a {\n  -webkit-transition: all .3s;\n  transition: all .3s;\n}\n.am-menu-offcanvas1 .am-menu-nav > .am-parent > a:after {\n  content: \"\\f104\";\n  position: absolute;\n  right: 1.5rem;\n  top: 1.3rem;\n}\n.am-menu-offcanvas1 .am-menu-nav > .am-parent.am-open > a:after {\n  content: \"\\f107\";\n}\n.am-menu-offcanvas1 .am-menu-sub {\n  border-top: 1px solid rgba(0, 0, 0, 0.3);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);\n  padding: 5px 0 5px 15px;\n  background-color: #1a1a1a;\n  font-size: 1.4rem;\n}\n.am-menu-offcanvas1 .am-menu-sub a {\n  color: #eee;\n}\n.am-menu-offcanvas1 .am-menu-sub a:hover {\n  color: #fff;\n}\n.am-menu-offcanvas1 .am-nav-divider {\n  border-top: 1px solid #1a1a1a;\n}\n/**\n  * Menu Theme: offcanvas2\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-menu-offcanvas2 .am-menu-toggle {\n  position: absolute;\n  right: 5px;\n  top: -47px;\n  display: block;\n  width: 44px;\n  height: 44px;\n  line-height: 44px;\n  text-align: center;\n  color: #fff;\n}\n.am-menu-offcanvas2 .am-menu-nav {\n  padding: 10px 5px;\n}\n.am-menu-offcanvas2 .am-menu-nav > li {\n  padding: 5px;\n}\n.am-menu-offcanvas2 .am-menu-nav > li > a {\n  -webkit-transition: all 0.3s;\n  transition: all 0.3s;\n  background-color: #404040;\n  color: #ccc;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);\n  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.5);\n  height: 44px;\n  line-height: 44px;\n  padding: 0;\n  text-align: center;\n}\n.am-menu-offcanvas2 .am-menu-nav > li > a:hover,\n.am-menu-offcanvas2 .am-menu-nav > li > a:focus {\n  background-color: #262626;\n  color: #fff;\n  outline: none;\n}\n.am-menu-offcanvas2 .am-menu-nav > .am-active > a {\n  background-color: #262626;\n  color: #fff;\n}\n/**\n  * Menu Theme: stack\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-menu-stack .am-menu-nav {\n  border-bottom: 1px solid #dedede;\n  -webkit-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.05);\n          box-shadow: 0 1px 0 rgba(255, 255, 255, 0.05);\n}\n.am-menu-stack .am-menu-nav > .am-parent > a {\n  -webkit-transition: all .3s;\n  transition: all .3s;\n}\n.am-menu-stack .am-menu-nav > .am-parent > a:after {\n  content: \"\\f105\";\n  position: absolute;\n  right: 1.5rem;\n  top: 1.3rem;\n  -webkit-transition: all .15s;\n  transition: all .15s;\n}\n.am-menu-stack .am-menu-nav > .am-parent.am-open > a:after {\n  -webkit-transform: rotate(90deg);\n      -ms-transform: rotate(90deg);\n          transform: rotate(90deg);\n}\n.am-menu-stack .am-menu-nav > li > a {\n  position: relative;\n  color: #333;\n  background-color: #f5f5f5;\n  border-top: 1px solid #dedede;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);\n  height: 49px;\n  line-height: 49px;\n  text-indent: 10px;\n  padding: 0;\n}\n.am-menu-stack .am-menu-nav > .am-open > a,\n.am-menu-stack .am-menu-nav > li > a:hover,\n.am-menu-stack .am-menu-nav > li > a:focus {\n  background-color: #e5e5e5;\n  color: #222;\n  outline: none;\n}\n.am-menu-stack .am-menu-sub {\n  padding: 0;\n  font-size: 1.4rem;\n  border-top: 1px solid #dedede;\n}\n.am-menu-stack .am-menu-sub a {\n  border-bottom: 1px solid #dedede;\n  padding-left: 2rem;\n  color: #444;\n}\n.am-menu-stack .am-menu-sub a:hover {\n  color: #333;\n}\n.am-menu-stack .am-menu-sub li:last-child a {\n  border-bottom: none;\n}\n.am-menu-stack .am-menu-sub > li > a {\n  height: 44px;\n  line-height: 44px;\n  text-indent: 15px;\n  padding: 0;\n}\n@media only screen and (min-width:641px) {\n  .am-menu-stack .am-menu-nav {\n    background-color: #f5f5f5;\n  }\n  .am-menu-stack .am-menu-nav > li {\n    float: left;\n    width: auto;\n    clear: none !important;\n    display: inline-block;\n  }\n  .am-menu-stack .am-menu-nav > li a {\n    padding-left: 1.5rem;\n    padding-right: 1.5rem;\n  }\n  .am-menu-stack .am-menu-nav > li.am-parent > a:after {\n    position: static;\n    content: \"\\f107\";\n  }\n  .am-menu-stack .am-menu-nav > li.am-parent.am-open a {\n    border-bottom: none;\n  }\n  .am-menu-stack .am-menu-nav > li.am-parent.am-open a:after {\n    -webkit-transform: rotateX(-180deg);\n            transform: rotateX(-180deg);\n  }\n  .am-menu-stack .am-menu-nav > li.am-parent.am-open .am-menu-sub {\n    background-color: #e5e5e5;\n  }\n  .am-menu-stack .am-menu-sub {\n    position: absolute;\n    left: 0;\n    right: 0;\n    background-color: #ddd;\n    border-top: none;\n  }\n  .am-menu-stack .am-menu-sub li {\n    width: auto;\n    float: left;\n    clear: none;\n  }\n}\n.am-navbar {\n  position: fixed;\n  left: 0;\n  bottom: 0;\n  width: 100%;\n  height: 49px;\n  line-height: 49px;\n  z-index: 1010;\n}\n.am-navbar ul {\n  padding-left: 0;\n  margin: 0;\n  list-style: none;\n  width: 100%;\n}\n.am-navbar .am-navbar-nav {\n  padding-left: 8px;\n  padding-right: 8px;\n  text-align: center;\n  overflow: hidden;\n  display: table;\n}\n.am-navbar .am-navbar-nav li {\n  display: table-cell;\n  width: 1%;\n  float: none;\n}\n.am-navbar-nav {\n  position: relative;\n  z-index: 1015;\n}\n.am-navbar-nav a {\n  display: inline-block;\n  width: 100%;\n  height: 49px;\n  line-height: 20px;\n}\n.am-navbar-nav a img {\n  display: block;\n  vertical-align: middle;\n  height: 24px;\n  width: 24px;\n  margin: 4px auto 0;\n}\n.am-navbar-nav a [class*=\"am-icon\"] {\n  width: 24px;\n  height: 24px;\n  margin: 4px auto 0;\n  display: block;\n  line-height: 24px;\n}\n.am-navbar-nav a [class*=\"am-icon\"]:before {\n  font-size: 22px;\n  vertical-align: middle;\n}\n.am-navbar-nav a .am-navbar-label {\n  padding-top: 2px;\n  line-height: 1;\n  font-size: 12px;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-navbar-more [class*=\"am-icon-\"] {\n  -webkit-transition: 0.15s;\n  transition: 0.15s;\n}\n.am-navbar-more.am-active [class*=\"am-icon-\"] {\n  -webkit-transform: rotateX(-180deg);\n          transform: rotateX(-180deg);\n}\n.am-navbar-actions {\n  position: absolute;\n  bottom: 49px;\n  right: 0;\n  left: 0;\n  z-index: 1009;\n  opacity: 0;\n  -webkit-transition: .3s;\n  transition: .3s;\n  -webkit-transform: translate(0, 100%);\n      -ms-transform: translate(0, 100%);\n          transform: translate(0, 100%);\n}\n.am-navbar-actions.am-active {\n  opacity: 1;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n}\n.am-navbar-actions li {\n  line-height: 42px;\n  position: relative;\n}\n.am-navbar-actions li a {\n  display: block;\n  width: 100%;\n  height: 40px;\n  -webkit-box-shadow: inset 0 1px rgba(220, 220, 220, 0.25);\n          box-shadow: inset 0 1px rgba(220, 220, 220, 0.25);\n  padding-left: 20px;\n  padding-right: 36px;\n}\n.am-navbar-actions li a :after {\n  font-family: \"FontAwesome\", sans-serif;\n  content: \"\\f105\";\n  display: inline-block;\n  position: absolute;\n  top: 0;\n  right: 20px;\n}\n.am-navbar-actions li a img {\n  vertical-align: middle;\n  height: 20px;\n  width: 20px;\n  display: inline;\n}\n#am-navbar-qrcode {\n  width: 220px;\n  height: 220px;\n  margin-left: -110px;\n}\n#am-navbar-qrcode .am-modal-bd {\n  padding: 10px;\n}\n#am-navbar-qrcode canvas {\n  display: block;\n  width: 200px;\n  height: 200px;\n}\n.am-with-fixed-navbar {\n  padding-bottom: 54px;\n}\n/**\n  * Navbar Theme: default\n  * Author: hzp (hzp@yunshipei.com)\n  */\n.am-navbar-default a {\n  color: #fff;\n}\n.am-navbar-default .am-navbar-nav {\n  background-color: #0e90d2;\n}\n.am-navbar-default .am-navbar-actions {\n  background-color: #0d86c4;\n}\n.am-navbar-default .am-navbar-actions a {\n  border-bottom: 1px solid #0b6fa2;\n}\n.am-pagination {\n  position: relative;\n}\n/**\n  * Pagination Theme: default\n  */\n.am-pagination-default {\n  margin-left: 10px;\n  margin-right: 10px;\n  font-size: 1.6rem;\n}\n.am-pagination-default .am-pagination-prev,\n.am-pagination-default .am-pagination-next {\n  float: none;\n}\n/**\n  * Pagination Theme: select\n  */\n.am-pagination-select {\n  margin-left: 10px;\n  margin-right: 10px;\n  font-size: 1.6rem;\n}\n.am-pagination-select > li > a {\n  line-height: 36px;\n  background-color: #eeeeee;\n  padding: 0 15px;\n  border: 0;\n  color: #555555;\n}\n.am-pagination-select .am-pagination-select {\n  position: absolute;\n  top: 0;\n  left: 50%;\n  margin-left: -35px;\n  width: 70px;\n  height: 36px;\n  text-align: center;\n  border-radius: 0;\n}\n.am-pagination-select .am-pagination-select select {\n  display: block;\n  border: 0;\n  line-height: 36px;\n  width: 70px;\n  height: 36px;\n  border-radius: 0;\n  color: #555555;\n  background-color: #eeeeee;\n  -webkit-appearance: none;\n  -moz-appearance: none;\n  appearance: none;\n  padding-left: 18px;\n}\n.am-paragraph p {\n  margin: 10px 0;\n}\n.am-paragraph img {\n  max-width: 100%;\n}\n.am-paragraph h1,\n.am-paragraph h2,\n.am-paragraph h3,\n.am-paragraph h4,\n.am-paragraph h5,\n.am-paragraph h6 {\n  color: #222222;\n}\n.am-paragraph table {\n  max-width: none;\n}\n.am-paragraph-table-container {\n  overflow: hidden;\n  background: #eeeeee;\n  max-width: none;\n}\n.am-paragraph-table-container table {\n  width: 100%;\n  max-width: none;\n}\n.am-paragraph-table-container table th {\n  background: #bce5fb;\n  height: 40px;\n  border: 1px solid #999999;\n  text-align: center;\n}\n.am-paragraph-table-container table td {\n  border: 1px solid #999999;\n  text-align: center;\n  vertical-align: middle;\n  background: #fff;\n}\n.am-paragraph-table-container table td p {\n  text-indent: 0;\n  font-size: 1.4rem;\n}\n.am-paragraph-table-container table td a {\n  font-size: 1.4rem;\n}\n/**\n  * Paragraph Theme: default\n  */\n.am-paragraph-default {\n  margin: 0 10px;\n  color: #333333;\n  background-color: transparent;\n}\n.am-paragraph-default p {\n  font-size: 1.4rem;\n}\n.am-paragraph-default img {\n  max-width: 98%;\n  display: block;\n  margin: 5px auto;\n  border: 1px solid #eeeeee;\n  padding: 2px;\n}\n.am-paragraph-default a {\n  color: #0e90d2;\n}\n/**\n  * Slider Theme: a1\n  */\n.am-slider-a1 {\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Control Nav */\n}\n.am-slider-a1 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-a1 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-a1 .am-control-nav {\n  width: 100%;\n  position: absolute;\n  bottom: 5px;\n  text-align: center;\n  line-height: 0;\n}\n.am-slider-a1 .am-control-nav li {\n  margin: 0 6px;\n  display: inline-block;\n}\n.am-slider-a1 .am-control-nav li a {\n  width: 8px;\n  height: 8px;\n  display: block;\n  background-color: rgba(0, 0, 0, 0.5);\n  cursor: pointer;\n  text-indent: -9999px;\n  border-radius: 50%;\n  -webkit-box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);\n          box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);\n}\n.am-slider-a1 .am-control-nav li a:hover {\n  background-color: rgba(0, 0, 0, 0.7);\n}\n.am-slider-a1 .am-control-nav li a.am-active {\n  background-color: #0e90d2;\n  cursor: default;\n}\n.am-slider-a1 .am-direction-nav,\n.am-slider-a1 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: a2\n  */\n.am-slider-a2 {\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Control Nav */\n}\n.am-slider-a2 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-a2 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-a2 .am-control-nav {\n  width: 100%;\n  position: absolute;\n  bottom: 5px;\n  text-align: center;\n  line-height: 0;\n}\n.am-slider-a2 .am-control-nav li {\n  margin: 0 6px;\n  display: inline-block;\n}\n.am-slider-a2 .am-control-nav li a {\n  width: 8px;\n  height: 8px;\n  display: block;\n  background-color: rgba(0, 0, 0, 0.5);\n  cursor: pointer;\n  text-indent: -9999px;\n  -webkit-box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);\n          box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);\n}\n.am-slider-a2 .am-control-nav li a:hover {\n  background-color: rgba(0, 0, 0, 0.7);\n}\n.am-slider-a2 .am-control-nav li a.am-active {\n  background: #0e93d7;\n  cursor: default;\n}\n.am-slider-a2 .am-direction-nav,\n.am-slider-a2 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: a3\n  */\n.am-slider-a3 {\n  margin-bottom: 20px;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Control Nav */\n}\n.am-slider-a3 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-a3 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-a3 .am-control-nav {\n  width: 100%;\n  position: absolute;\n  bottom: -20px;\n  text-align: center;\n  height: 20px;\n  background-color: #000;\n  padding-top: 5px;\n  line-height: 0;\n}\n.am-slider-a3 .am-control-nav li {\n  margin: 0 6px;\n  display: inline-block;\n}\n.am-slider-a3 .am-control-nav li a {\n  width: 8px;\n  height: 8px;\n  display: block;\n  background-color: rgba(0, 0, 0, 0.5);\n  cursor: pointer;\n  text-indent: -9999px;\n  border-radius: 50%;\n  -webkit-box-shadow: inset 0 0 3px rgba(200, 200, 200, 0.3);\n          box-shadow: inset 0 0 3px rgba(200, 200, 200, 0.3);\n}\n.am-slider-a3 .am-control-nav li a:hover {\n  background-color: rgba(0, 0, 0, 0.7);\n}\n.am-slider-a3 .am-control-nav li a.am-active {\n  background: #0e90d2;\n  cursor: default;\n}\n.am-slider-a3 .am-direction-nav,\n.am-slider-a3 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: a4\n  */\n.am-slider-a4 {\n  margin-bottom: 30px;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Control Nav */\n}\n.am-slider-a4 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-a4 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-a4 .am-control-nav {\n  width: 100%;\n  position: absolute;\n  bottom: -15px;\n  text-align: center;\n  line-height: 0;\n}\n.am-slider-a4 .am-control-nav li {\n  margin: 0 6px;\n  display: inline-block;\n}\n.am-slider-a4 .am-control-nav li a {\n  width: 8px;\n  height: 8px;\n  display: block;\n  background-color: rgba(0, 0, 0, 0.5);\n  cursor: pointer;\n  text-indent: -9999px;\n  border-radius: 50%;\n  -webkit-box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);\n          box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);\n}\n.am-slider-a4 .am-control-nav li a:hover {\n  background-color: rgba(0, 0, 0, 0.7);\n}\n.am-slider-a4 .am-control-nav li a.am-active {\n  background-color: #0e90d2;\n  cursor: default;\n}\n.am-slider-a4 .am-direction-nav,\n.am-slider-a4 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: a5\n  */\n.am-slider-a5 {\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Control Nav */\n}\n.am-slider-a5 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-a5 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-a5 .am-control-nav {\n  width: 100%;\n  position: absolute;\n  text-align: center;\n  height: 6px;\n  display: table;\n  bottom: 0;\n  font-size: 0;\n  line-height: 0;\n}\n.am-slider-a5 .am-control-nav li {\n  display: table-cell;\n}\n.am-slider-a5 .am-control-nav li a {\n  width: 100%;\n  height: 6px;\n  display: block;\n  background-color: rgba(0, 0, 0, 0.5);\n  cursor: pointer;\n  text-indent: -9999px;\n}\n.am-slider-a5 .am-control-nav li a:hover {\n  background-color: rgba(0, 0, 0, 0.7);\n}\n.am-slider-a5 .am-control-nav li a.am-active {\n  background-color: #0e90d2;\n  cursor: default;\n}\n.am-slider-a5 .am-direction-nav,\n.am-slider-a5 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: b1\n  */\n.am-slider-b1 {\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Direction Nav */\n}\n.am-slider-b1 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-b1 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-b1 .am-direction-nav a {\n  -webkit-box-sizing: content-box;\n          box-sizing: content-box;\n  display: block;\n  width: 24px;\n  height: 24px;\n  padding: 8px 0;\n  margin: -20px 0 0;\n  position: absolute;\n  top: 50%;\n  z-index: 10;\n  overflow: hidden;\n  opacity: 0.45;\n  cursor: pointer;\n  color: #fff;\n  text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3);\n  background-color: rgba(0, 0, 0, 0.5);\n  font-size: 0;\n  text-align: center;\n  -webkit-transition: all .3s ease;\n  transition: all .3s ease;\n}\n.am-slider-b1 .am-direction-nav a:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f053\";\n  font-size: 24px;\n}\n.am-slider-b1 .am-direction-nav a.am-prev {\n  left: 0;\n  padding-right: 5px;\n  border-bottom-right-radius: 5px;\n  border-top-right-radius: 5px;\n}\n.am-slider-b1 .am-direction-nav a.am-next {\n  right: 0;\n  padding-left: 5px;\n  border-bottom-left-radius: 5px;\n  border-top-left-radius: 5px;\n}\n.am-slider-b1 .am-direction-nav a.am-next:before {\n  content: \"\\f054\";\n}\n.am-slider-b1 .am-direction-nav .am-disabled {\n  opacity: 0!important;\n  cursor: default;\n}\n.am-slider-b1:hover .am-prev {\n  opacity: 0.7;\n}\n.am-slider-b1:hover .am-prev:hover {\n  opacity: 1;\n}\n.am-slider-b1:hover .am-next {\n  opacity: 0.7;\n}\n.am-slider-b1:hover .am-next:hover {\n  opacity: 1;\n}\n.am-slider-b1 .am-control-nav,\n.am-slider-b1 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: b2\n  */\n.am-slider-b2 {\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Direction Nav */\n}\n.am-slider-b2 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-b2 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-b2 .am-direction-nav a {\n  -webkit-box-sizing: content-box;\n          box-sizing: content-box;\n  display: block;\n  width: 24px;\n  height: 24px;\n  padding: 4px;\n  margin: -16px 0 0;\n  position: absolute;\n  top: 50%;\n  z-index: 10;\n  overflow: hidden;\n  opacity: 0.45;\n  cursor: pointer;\n  color: #fff;\n  text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3);\n  background-color: rgba(0, 0, 0, 0.5);\n  font-size: 0;\n  text-align: center;\n  border-radius: 50%;\n  -webkit-transition: all .3s ease;\n  transition: all .3s ease;\n}\n.am-slider-b2 .am-direction-nav a:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f053\";\n  font-size: 16px;\n  line-height: 24px;\n}\n.am-slider-b2 .am-direction-nav a.am-prev {\n  left: 5px;\n}\n.am-slider-b2 .am-direction-nav a.am-next {\n  right: 5px;\n}\n.am-slider-b2 .am-direction-nav a.am-next:before {\n  content: \"\\f054\";\n}\n.am-slider-b2 .am-direction-nav .am-disabled {\n  opacity: 0!important;\n  cursor: default;\n}\n.am-slider-b2:hover .am-prev {\n  opacity: 0.7;\n}\n.am-slider-b2:hover .am-prev:hover {\n  opacity: 1;\n}\n.am-slider-b2:hover .am-next {\n  opacity: 0.7;\n}\n.am-slider-b2:hover .am-next:hover {\n  opacity: 1;\n}\n.am-slider-b2 .am-control-nav,\n.am-slider-b2 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: b3\n  */\n.am-slider-b3 {\n  margin: 15px 30px;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Direction Nav */\n}\n.am-slider-b3 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-b3 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-b3 .am-direction-nav a {\n  -webkit-box-sizing: content-box;\n          box-sizing: content-box;\n  display: block;\n  width: 24px;\n  height: 24px;\n  padding: 4px;\n  margin: -16px 0 0;\n  position: absolute;\n  top: 50%;\n  z-index: 10;\n  overflow: hidden;\n  opacity: 0.45;\n  cursor: pointer;\n  color: #333333;\n  text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3);\n  font-size: 0;\n  -webkit-transition: all .3s ease;\n  transition: all .3s ease;\n}\n.am-slider-b3 .am-direction-nav a:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f053\";\n  font-size: 24px;\n}\n.am-slider-b3 .am-direction-nav a.am-prev {\n  left: -25px;\n}\n.am-slider-b3 .am-direction-nav a.am-next {\n  right: -25px;\n  text-align: right;\n}\n.am-slider-b3 .am-direction-nav a.am-next:before {\n  content: \"\\f054\";\n}\n.am-slider-b3 .am-direction-nav .am-disabled {\n  opacity: 0!important;\n  cursor: default;\n}\n.am-slider-b3:hover .am-prev {\n  opacity: 0.7;\n}\n.am-slider-b3:hover .am-prev:hover {\n  opacity: 1;\n}\n.am-slider-b3:hover .am-next {\n  opacity: 0.7;\n}\n.am-slider-b3:hover .am-next:hover {\n  opacity: 1;\n}\n.am-slider-b3 .am-control-nav,\n.am-slider-b3 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: b4\n  */\n.am-slider-b4 {\n  margin: 15px 20px;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Direction Nav */\n}\n.am-slider-b4 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-b4 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-b4 .am-direction-nav a {\n  position: absolute;\n  top: 50%;\n  z-index: 10;\n  display: block;\n  -webkit-box-sizing: content-box;\n          box-sizing: content-box;\n  width: 24px;\n  height: 24px;\n  margin: -16px 0 0;\n  padding: 4px;\n  overflow: hidden;\n  opacity: 0.45;\n  background-color: rgba(0, 0, 0, 0.8);\n  cursor: pointer;\n  text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3);\n  font-size: 0;\n  border-radius: 50%;\n  text-align: center;\n  color: #fff;\n  -webkit-transition: all .3s ease;\n  transition: all .3s ease;\n}\n.am-slider-b4 .am-direction-nav a:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f053\";\n  font-size: 20px;\n  line-height: 24px;\n}\n.am-slider-b4 .am-direction-nav a.am-prev {\n  left: -15px;\n}\n.am-slider-b4 .am-direction-nav a.am-next {\n  right: -15px;\n}\n.am-slider-b4 .am-direction-nav a.am-next:before {\n  content: \"\\f054\";\n}\n.am-slider-b4 .am-direction-nav .am-disabled {\n  opacity: 0!important;\n  cursor: default;\n}\n.am-slider-b4:hover .am-prev {\n  opacity: 0.7;\n}\n.am-slider-b4:hover .am-prev:hover {\n  opacity: 0.9;\n}\n.am-slider-b4:hover .am-next {\n  opacity: 0.7;\n}\n.am-slider-b4:hover .am-next:hover {\n  opacity: 0.9;\n}\n.am-slider-b4 .am-control-nav,\n.am-slider-b4 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: c1\n  */\n.am-slider-c1 {\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Control Nav */\n}\n.am-slider-c1 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-c1 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-c1 .am-control-nav {\n  position: absolute;\n  bottom: 0;\n  display: table;\n  width: 100%;\n  height: 6px;\n  font-size: 0;\n  line-height: 0;\n  text-align: center;\n}\n.am-slider-c1 .am-control-nav li {\n  display: table-cell;\n  width: 1%;\n}\n.am-slider-c1 .am-control-nav li a {\n  width: 100%;\n  height: 6px;\n  display: block;\n  background-color: rgba(0, 0, 0, 0.7);\n  cursor: pointer;\n  text-indent: -9999px;\n}\n.am-slider-c1 .am-control-nav li a:hover {\n  background: rgba(0, 0, 0, 0.8);\n}\n.am-slider-c1 .am-control-nav li a.am-active {\n  background-color: #0e90d2;\n  cursor: default;\n}\n.am-slider-c1 .am-slider-desc {\n  background-color: rgba(0, 0, 0, 0.6);\n  position: absolute;\n  bottom: 6px;\n  padding: 8px;\n  width: 100%;\n  color: #fff;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-slider-c1 .am-direction-nav,\n.am-slider-c1 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: c2\n  */\n.am-slider-c2 {\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Control Nav */\n}\n.am-slider-c2 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-c2 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-c2 .am-control-nav {\n  position: absolute;\n  bottom: 15px;\n  right: 0;\n  height: 6px;\n  text-align: center;\n  font-size: 0;\n  line-height: 0;\n}\n.am-slider-c2 .am-control-nav li {\n  display: inline-block;\n  margin-right: 6px;\n}\n.am-slider-c2 .am-control-nav li a {\n  width: 6px;\n  height: 6px;\n  display: block;\n  background-color: rgba(255, 255, 255, 0.4);\n  cursor: pointer;\n  text-indent: -9999px;\n}\n.am-slider-c2 .am-control-nav li a:hover {\n  background: rgba(230, 230, 230, 0.4);\n}\n.am-slider-c2 .am-control-nav li a.am-active {\n  background-color: #0e90d2;\n  cursor: default;\n}\n.am-slider-c2 .am-slider-desc {\n  background-color: rgba(0, 0, 0, 0.6);\n  position: absolute;\n  bottom: 0;\n  padding: 8px 60px 8px 8px;\n  width: 100%;\n  color: #fff;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-slider-c2 .am-direction-nav,\n.am-slider-c2 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: c3\n  */\n.am-slider-c3 {\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Direction Nav */\n}\n.am-slider-c3 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-c3 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-c3 .am-slider-desc {\n  background-color: rgba(0, 0, 0, 0.6);\n  position: absolute;\n  bottom: 10px;\n  right: 60px;\n  height: 30px;\n  left: 0;\n  padding-right: 5px;\n  color: #fff;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-slider-c3 .am-slider-counter {\n  margin-right: 5px;\n  display: inline-block;\n  height: 30px;\n  background-color: #0e90d2;\n  width: 40px;\n  text-align: center;\n  line-height: 30px;\n  color: #eee;\n  font-size: 1rem;\n}\n.am-slider-c3 .am-slider-counter .am-active {\n  font-size: 1.8rem;\n  font-weight: bold;\n  color: #fff;\n}\n.am-slider-c3 .am-direction-nav a {\n  -webkit-box-sizing: content-box;\n          box-sizing: content-box;\n  display: block;\n  width: 24px;\n  height: 24px;\n  padding: 4px 0;\n  margin: -16px 0 0;\n  position: absolute;\n  top: 50%;\n  z-index: 10;\n  overflow: hidden;\n  opacity: 0.45;\n  cursor: pointer;\n  color: #fff;\n  text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3);\n  background-color: rgba(0, 0, 0, 0.5);\n  font-size: 0;\n  text-align: center;\n  -webkit-transition: all .3s ease;\n  transition: all .3s ease;\n}\n.am-slider-c3 .am-direction-nav a:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f053\";\n  font-size: 16px;\n  line-height: 24px;\n}\n.am-slider-c3 .am-direction-nav a.am-prev {\n  left: 0;\n  padding-right: 5px;\n}\n.am-slider-c3 .am-direction-nav a.am-next {\n  right: 0;\n  padding-left: 5px;\n}\n.am-slider-c3 .am-direction-nav a.am-next:before {\n  content: \"\\f054\";\n}\n.am-slider-c3 .am-direction-nav .am-disabled {\n  opacity: 0!important;\n  cursor: default;\n}\n.am-slider-c3:hover .am-prev {\n  opacity: 0.7;\n}\n.am-slider-c3:hover .am-prev:hover {\n  opacity: 1;\n}\n.am-slider-c3:hover .am-next {\n  opacity: 0.7;\n}\n.am-slider-c3:hover .am-next:hover {\n  opacity: 1;\n}\n.am-slider-c3 .am-control-nav,\n.am-slider-c3 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: c4\n  */\n.am-slider-c4 {\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Direction Nav */\n}\n.am-slider-c4 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-c4 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-c4 .am-slider-desc {\n  width: 100%;\n  background-color: rgba(0, 0, 0, 0.6);\n  position: absolute;\n  bottom: 0;\n  right: 0;\n  left: 0;\n  padding: 8px 40px;\n  color: #fff;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-slider-c4 .am-direction-nav a {\n  -webkit-box-sizing: content-box;\n          box-sizing: content-box;\n  display: block;\n  width: 24px;\n  height: 24px;\n  padding: 4px 0;\n  margin: 0;\n  position: absolute;\n  bottom: 4px;\n  z-index: 10;\n  overflow: hidden;\n  opacity: 0.45;\n  cursor: pointer;\n  text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3);\n  font-size: 0;\n  text-align: center;\n  color: rgba(0, 0, 0, 0.7);\n  -webkit-transition: all .3s ease;\n  transition: all .3s ease;\n}\n.am-slider-c4 .am-direction-nav a:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f053\";\n  font-size: 24px;\n}\n.am-slider-c4 .am-direction-nav a.am-prev {\n  left: 0;\n  padding-right: 5px;\n}\n.am-slider-c4 .am-direction-nav a.am-next {\n  right: 0;\n  padding-left: 5px;\n}\n.am-slider-c4 .am-direction-nav a.am-next:before {\n  content: \"\\f054\";\n}\n.am-slider-c4 .am-direction-nav .am-disabled {\n  opacity: 0!important;\n  cursor: default;\n}\n.am-slider-c4:hover .am-prev {\n  opacity: 0.7;\n}\n.am-slider-c4:hover .am-prev:hover {\n  opacity: 1;\n}\n.am-slider-c4:hover .am-next {\n  opacity: 0.7;\n}\n.am-slider-c4:hover .am-next:hover {\n  opacity: 1;\n}\n.am-slider-c4 .am-control-nav,\n.am-slider-c4 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: d1\n  */\n.am-slider-d1 {\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Direction Nav */\n}\n.am-slider-d1 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-d1 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-d1 .am-slider-desc {\n  padding: 8px 35px;\n  width: 100%;\n  color: #fff;\n  background-color: #0e90d2;\n}\n.am-slider-d1 .am-slider-title {\n  font-weight: normal;\n  margin-bottom: 2px;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-slider-d1 .am-slider-more {\n  color: #eeeeee;\n  font-size: 1.3rem;\n}\n.am-slider-d1 .am-direction-nav a {\n  -webkit-box-sizing: content-box;\n          box-sizing: content-box;\n  display: block;\n  width: 24px;\n  height: 24px;\n  margin: 0;\n  position: absolute;\n  bottom: 18px;\n  z-index: 10;\n  overflow: hidden;\n  opacity: 0.45;\n  cursor: pointer;\n  text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3);\n  font-size: 0;\n  text-align: center;\n  border: 1px solid rgba(255, 255, 255, 0.9);\n  color: rgba(255, 255, 255, 0.9);\n  border-radius: 50%;\n  -webkit-transition: all 03s ease;\n  transition: all 03s ease;\n}\n.am-slider-d1 .am-direction-nav a:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f053\";\n  font-size: 16px;\n  line-height: 24px;\n}\n.am-slider-d1 .am-direction-nav a.am-prev {\n  left: 5px;\n}\n.am-slider-d1 .am-direction-nav a.am-next {\n  right: 5px;\n}\n.am-slider-d1 .am-direction-nav a.am-next:before {\n  content: \"\\f054\";\n}\n.am-slider-d1 .am-direction-nav .am-disabled {\n  opacity: 0!important;\n  cursor: default;\n}\n.am-slider-d1:hover .am-prev {\n  opacity: 0.7;\n}\n.am-slider-d1:hover .am-prev:hover {\n  opacity: 1;\n}\n.am-slider-d1:hover .am-next {\n  opacity: 0.7;\n}\n.am-slider-d1:hover .am-next:hover {\n  opacity: 1;\n}\n.am-slider-d1 .am-control-nav,\n.am-slider-d1 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: d2\n  */\n.am-slider-d2 {\n  margin-bottom: 20px;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Control Nav */\n}\n.am-slider-d2 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-d2 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-d2 .am-slider-desc {\n  position: absolute;\n  left: 10px;\n  bottom: 20px;\n  right: 50px;\n  color: #fff;\n}\n.am-slider-d2 .am-slider-content {\n  background-color: rgba(0, 0, 0, 0.7);\n  padding: 10px 6px;\n  margin-bottom: 10px;\n}\n.am-slider-d2 .am-slider-content p {\n  margin: 0;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n  font-size: 1.4rem;\n}\n.am-slider-d2 .am-slider-title {\n  font-weight: normal;\n  margin-bottom: 5px;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-slider-d2 .am-slider-more {\n  color: #eeeeee;\n  font-size: 1.3rem;\n  background-color: #0e90d2;\n  padding: 2px 10px;\n}\n.am-slider-d2 .am-control-nav {\n  width: 100%;\n  position: absolute;\n  bottom: -15px;\n  text-align: center;\n}\n.am-slider-d2 .am-control-nav li {\n  margin: 0 6px;\n  display: inline-block;\n}\n.am-slider-d2 .am-control-nav li a {\n  width: 8px;\n  height: 8px;\n  display: block;\n  background-color: rgba(0, 0, 0, 0.5);\n  cursor: pointer;\n  text-indent: -9999px;\n  border-radius: 50%;\n  font-size: 0;\n  line-height: 0;\n  -webkit-box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);\n          box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);\n}\n.am-slider-d2 .am-control-nav li a:hover {\n  background: rgba(0, 0, 0, 0.5);\n}\n.am-slider-d2 .am-control-nav li a.am-active {\n  background: #0e90d2;\n  cursor: default;\n}\n.am-slider-d2 .am-direction-nav,\n.am-slider-d2 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: d3\n  */\n.am-slider-d3 {\n  margin-bottom: 10px;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Control Nav */\n}\n.am-slider-d3 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-d3 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-d3 .am-slider-desc {\n  position: absolute;\n  bottom: 0;\n  color: #fff;\n  width: 100%;\n  background-color: rgba(0, 0, 0, 0.7);\n  padding: 8px 5px;\n}\n.am-slider-d3 .am-slider-desc p {\n  margin: 0;\n  font-size: 1.3rem;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-slider-d3 .am-slider-title {\n  font-weight: normal;\n  margin-bottom: 5px;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-slider-d3 .am-control-thumbs {\n  position: static;\n  overflow: hidden;\n}\n.am-slider-d3 .am-control-thumbs li {\n  padding: 12px 4px 4px;\n  position: relative;\n}\n.am-slider-d3 .am-control-thumbs img {\n  width: 100%;\n  display: block;\n  opacity: .85;\n  cursor: pointer;\n}\n.am-slider-d3 .am-control-thumbs img:hover {\n  opacity: 1;\n}\n.am-slider-d3 .am-control-thumbs .am-active {\n  opacity: 1;\n  cursor: default;\n}\n.am-slider-d3 .am-control-thumbs .am-active + i {\n  position: absolute;\n  top: 0;\n  left: 50%;\n  content: \"\";\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: middle;\n  border-top: 8px solid rgba(0, 0, 0, 0.7);\n  border-right: 8px solid transparent;\n  border-left: 8px solid transparent;\n  border-bottom: 0 dotted;\n  -webkit-transform: rotate(360deg);\n      -ms-transform: rotate(360deg);\n          transform: rotate(360deg);\n  margin-left: -4px;\n  -webkit-transition: all 0.2s;\n  transition: all 0.2s;\n}\n.am-slider-d3 .am-direction-nav,\n.am-slider-d3 .am-pauseplay {\n  display: none;\n}\n.am-slider-d3 .am-control-thumbs {\n  display: table;\n}\n.am-slider-d3 .am-control-thumbs li {\n  display: table-cell;\n  width: 1%;\n}\n[data-am-widget='tabs'] {\n  margin: 10px;\n}\n[data-am-widget='tabs'] .am-tabs-nav {\n  width: 100%;\n  padding: 0;\n  margin: 0;\n  list-style: none;\n  text-align: center;\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -ms-flexbox;\n  display: flex;\n}\n[data-am-widget='tabs'] .am-tabs-nav li {\n  -webkit-box-flex: 1;\n  -webkit-flex: 1;\n      -ms-flex: 1;\n          flex: 1;\n}\n[data-am-widget='tabs'] .am-tabs-nav a {\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n/**\n  * Tabs Theme: default\n  */\n.am-tabs-default .am-tabs-nav {\n  line-height: 40px;\n  background-color: #eeeeee;\n}\n.am-tabs-default .am-tabs-nav a {\n  color: #222222;\n  line-height: 42px;\n}\n.am-tabs-default .am-tabs-nav > .am-active a {\n  background-color: #0e90d2;\n  color: #fff;\n}\n/**\n  * Tabs Theme: d2\n  */\n.am-tabs-d2 .am-tabs-nav {\n  background-color: #eeeeee;\n}\n.am-tabs-d2 .am-tabs-nav li {\n  height: 42px;\n}\n.am-tabs-d2 .am-tabs-nav a {\n  color: #222222;\n  line-height: 42px;\n}\n.am-tabs-d2 .am-tabs-nav > .am-active {\n  position: relative;\n  background-color: #fcfcfc;\n  border-bottom: 2px solid #0e90d2;\n}\n.am-tabs-d2 .am-tabs-nav > .am-active a {\n  line-height: 40px;\n  color: #0e90d2;\n}\n.am-tabs-d2 .am-tabs-nav > .am-active:after {\n  position: absolute;\n  width: 0;\n  height: 0;\n  bottom: 0px;\n  left: 50%;\n  margin-left: -5px;\n  border: 6px rgba(0, 0, 0, 0) solid;\n  content: \"\";\n  z-index: 1;\n  border-bottom-color: #0e90d2;\n}\n.am-titlebar {\n  margin-top: 20px;\n  height: 45px;\n  font-size: 100%;\n}\n.am-titlebar h2 {\n  margin-top: 0;\n  margin-bottom: 0;\n  font-size: 1.6rem;\n}\n.am-titlebar .am-titlebar-title img {\n  height: 24px;\n  width: auto;\n}\n/**\n  * Titlebar Theme: default\n  */\n.am-titlebar-default {\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -ms-flexbox;\n  display: flex;\n  margin-left: 10px;\n  margin-right: 10px;\n  background-color: transparent;\n  border-bottom: 1px solid #dedede;\n  line-height: 44px;\n}\n.am-titlebar-default a {\n  color: #0e90d2;\n}\n.am-titlebar-default .am-titlebar-title {\n  position: relative;\n  padding-left: 12px;\n  color: #0e90d2;\n  font-size: 1.8rem;\n  text-align: left;\n  font-weight: bold;\n}\n.am-titlebar-default .am-titlebar-title:before {\n  content: \"\";\n  position: absolute;\n  left: 2px;\n  top: 8px;\n  bottom: 8px;\n  border-left: 3px solid #0e90d2;\n}\n.am-titlebar-default .am-titlebar-nav {\n  -webkit-box-flex: 1;\n  -webkit-flex: 1;\n      -ms-flex: 1;\n          flex: 1;\n  text-align: right;\n}\n.am-titlebar-default .am-titlebar-nav a {\n  margin-right: 10px;\n}\n.am-titlebar-default .am-titlebar-nav a:last-child {\n  margin-right: 5px;\n}\n/**\n  * Titlebar Theme: multi\n  */\n.am-titlebar-multi {\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -ms-flexbox;\n  display: flex;\n  background-color: #f5f5f5;\n  border-top: 2px solid #3bb4f2;\n  border-bottom: 1px solid #e8e8e8;\n}\n.am-titlebar-multi a {\n  color: #0e90d2;\n}\n.am-titlebar-multi .am-titlebar-title {\n  padding-left: 10px;\n  color: #0e90d2;\n  font-size: 1.8rem;\n  text-align: left;\n  font-weight: bold;\n  line-height: 42px;\n}\n.am-titlebar-multi .am-titlebar-nav {\n  -webkit-box-flex: 1;\n  -webkit-flex: 1;\n      -ms-flex: 1;\n          flex: 1;\n  text-align: right;\n  line-height: 42px;\n}\n.am-titlebar-multi .am-titlebar-nav a {\n  margin-right: 10px;\n}\n/**\n  * Titlebar Theme: cols\n  */\n.am-titlebar-cols {\n  position: relative;\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -ms-flexbox;\n  display: flex;\n  padding-left: 10px;\n  background-color: #f5f5f5;\n  color: #555555;\n  font-size: 18px;\n  border-top: 2px solid #e1e1e1;\n  line-height: 41px;\n}\n.am-titlebar-cols a {\n  color: #555555;\n}\n.am-titlebar-cols .am-titlebar-title {\n  color: #0e90d2;\n  margin-right: 15px;\n  border-bottom: 2px solid #0e90d2;\n  font-weight: bold;\n}\n.am-titlebar-cols .am-titlebar-title a {\n  color: #0e90d2;\n}\n.am-titlebar-cols .am-titlebar-nav {\n  -webkit-box-flex: 1;\n  -webkit-flex: 1;\n      -ms-flex: 1;\n          flex: 1;\n}\n.am-titlebar-cols .am-titlebar-nav a {\n  display: inline-block;\n  margin-right: 15px;\n  line-height: 41px;\n  border-bottom: 2px solid transparent;\n}\n.am-titlebar-cols .am-titlebar-nav a:hover {\n  color: #3c3c3c;\n  border-bottom-color: #0e90d2;\n}\n.am-titlebar-cols .am-titlebar-nav a:last-child {\n  margin-right: 10px;\n}\n.am-wechatpay .am-wechatpay-btn {\n  margin-top: 1rem;\n  margin-bottom: 1rem;\n}\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/base-component/amazeui/css/amazeui.flat.css",
    "content": "/*! Amaze UI v2.6.0 | by Amaze UI Team | (c) 2016 AllMobilize, Inc. | Licensed under MIT | 2016-03-31T14:28:54+0800 */\n/* ==========================================================================\n   Component: Base\n ============================================================================ */\n/**\n * Fix the flawed CSS box model - Yes, IE6's box model is better\n * Browser support: IE8+\n * via: http://paulirish.com/2012/box-sizing-border-box-ftw/\n */\n*,\n*:before,\n*:after {\n  -webkit-box-sizing: border-box;\n          box-sizing: border-box;\n}\n/* normalize.css v3.0.2 | git.io/normalize */\n/* Set <html> and <body> to inherit the height of the viewport */\nhtml,\nbody {\n  min-height: 100%;\n}\n/**\n * 1. Prevent iOS text size adjust after orientation change, without disabling\n *    user zoom.\n *    https://developer.mozilla.org/en-US/docs/Web/CSS/text-size-adjust\n */\nhtml {\n  -ms-text-size-adjust: 100%;\n  /* 1 */\n  -webkit-text-size-adjust: 100%;\n  /* 1 */\n}\n/**\n * Remove default margin.\n */\nbody {\n  margin: 0;\n}\n/* HTML5 display definitions\n   ========================================================================== */\n/**\n * Correct `block` display not defined for any HTML5 element in IE 8/9.\n * Correct `block` display not defined for `details` or `summary` in IE 10/11 and Firefox.\n * Correct `block` display not defined for `main` in IE 11.\n * hgroup has been removed from the HTML5 (W3C) specification\n *        https://developer.mozilla.org/en-US/docs/Web/HTML/Element/hgroup\n */\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmenu,\nmain,\nnav,\nsection,\nsummary {\n  display: block;\n}\n/**\n * 1. Correct `inline-block` display not defined in IE 8/9.\n * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.\n */\naudio,\ncanvas,\nprogress,\nvideo {\n  display: inline-block;\n  /* 1 */\n  vertical-align: baseline;\n  /* 2 */\n}\n/**\n * Prevent modern browsers from displaying `audio` without controls.\n * Remove excess height in iOS 5 devices.\n */\naudio:not([controls]) {\n  display: none;\n  height: 0;\n}\n/**\n * Address `[hidden]` styling not present in IE 8/9/10.\n * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.\n */\n[hidden],\ntemplate,\nscript {\n  display: none;\n}\n/* Links\n   ========================================================================== */\n/**\n * Remove the gray background color from active links in IE 10.\n */\na {\n  background-color: transparent;\n}\n/**\n * Address `outline` inconsistency between Chrome and other browsers.\n */\na:focus {\n  outline: thin dotted;\n}\n/**\n * Improve readability when focused and also mouse hovered in all browsers.\n */\na:active,\na:hover {\n  outline: 0;\n}\n/* Text-level semantics\n   ========================================================================== */\n/**\n * Remove text-decoration\n */\nins,\na {\n  text-decoration: none;\n}\n/**\n * Address styling not present in IE 8/9, Safari 5, and Chrome.\n */\nabbr[title] {\n  border-bottom: 1px dotted;\n}\n/**\n * Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome.\n */\nb,\nstrong {\n  font-weight: bold;\n}\n/**\n * Improve readability of pre-formatted text in all browsers.\n */\npre {\n  white-space: pre-wrap;\n}\n/**\n * Set consistent quote types.\n */\nq {\n  quotes: \"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\";\n}\n/**\n * Address inconsistent and variable font size in all browsers.\n */\nsmall {\n  font-size: 80%;\n}\n/**\n * Prevent `sub` and `sup` affecting `line-height` in all browsers.\n */\nsub,\nsup {\n  font-size: 75%;\n  line-height: 0;\n  position: relative;\n  vertical-align: baseline;\n}\nsup {\n  top: -0.5em;\n}\nsub {\n  bottom: -0.25em;\n}\n/* Embedded content\n   ========================================================================== */\n/**\n  * 1. Corrects max-width behavior (2.) if padding and border are used\n  * 2. Responsiveness: Sets a maxium width relative to the parent and auto scales the height\n  * 3. Remove the gap between images and the bottom of their containers\n  * 4. Remove border when inside `a` element in IE 8/9.\n  * remove 2. for Issue #502\n  */\nimg {\n  -webkit-box-sizing: border-box;\n          box-sizing: border-box;\n  /* 1 */\n  vertical-align: middle;\n  /* 3 */\n  border: 0;\n  /* 4 */\n}\n/**\n * Correct overflow displayed oddly in IE 9.\n */\nsvg:not(:root) {\n  overflow: hidden;\n}\n/* Grouping content\n   ========================================================================== */\n/**\n * Address margin not present in IE 8/9 and Safari.\n */\nfigure {\n  margin: 0;\n}\n/**\n * Correct font family set oddly in Safari 5 and Chrome.\n */\ncode,\nkbd,\npre,\nsamp {\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", \"FontAwesome\", monospace;\n  font-size: 1em;\n}\n/* Forms\n   ========================================================================== */\n/**\n * Define consistent border, margin, and padding.\n */\nfieldset {\n  border: 1px solid #c0c0c0;\n  margin: 0 2px;\n  padding: 0.35em 0.625em 0.75em;\n}\n/**\n * 1. Correct `color` not being inherited in IE 8/9.\n * 2. Remove padding so people aren't caught out if they zero out fieldsets.\n */\nlegend {\n  border: 0;\n  /* 1 */\n  padding: 0;\n  /* 2 */\n}\n/**\n * 1. Correct color not being inherited.\n *    Known issue: affects color of disabled elements.\n * 2. Correct font properties not being inherited.\n * 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome.\n */\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n  color: inherit;\n  /* 1 */\n  font: inherit;\n  /* 2 */\n  margin: 0;\n  /* 3 */\n}\n/**\n * Address `overflow` set to `hidden` in IE 8/9/10/11.\n */\nbutton {\n  overflow: visible;\n}\n/**\n * Address Firefox 4+ setting `line-height` on `input` using `!important` in\n * the UA stylesheet.\n */\nbutton,\ninput {\n  line-height: normal;\n}\n/**\n * Address inconsistent `text-transform` inheritance for `button` and `select`.\n * All other form control elements do not inherit `text-transform` values.\n * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.\n * Correct `select` style inheritance in Firefox.\n */\nbutton,\nselect {\n  text-transform: none;\n}\n/**\n * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`\n *    and `video` controls.\n * 2. Correct inability to style clickable `input` types in iOS.\n * 3. Improve usability and consistency of cursor style between image-type\n *    `input` and others.\n */\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  -webkit-appearance: button;\n  /* 2 */\n  cursor: pointer;\n  /* 3 */\n}\n/*\n * 1. Improves consistency of cursor style for clickable elements\n * 2. Removes excess padding in IE 8/9.\n * 3. Address box sizing set to `content-box` in IE 8/9/10.\n */\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  cursor: pointer;\n  /*1*/\n  padding: 0;\n  /*2*/\n  -webkit-box-sizing: border-box;\n          box-sizing: border-box;\n  /* 3 */\n}\n/**\n * Re-set default cursor for disabled elements.\n */\nbutton[disabled],\nhtml input[disabled] {\n  cursor: default;\n}\n/**\n * Remove inner padding and border in Firefox 4+.\n */\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  border: 0;\n  padding: 0;\n}\n/**\n * Fix the cursor style for Chrome's increment/decrement buttons. For certain\n * `font-size` values of the `input`, it causes the cursor style of the\n * decrement button to change from `default` to `text`.\n */\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n  height: auto;\n}\n/**\n * 1. Address `appearance` set to `searchfield` in Safari and Chrome.\n * 2. Address `box-sizing` set to `border-box` in Safari and Chrome\n *    (include `-moz` to future-proof).\n */\ninput[type=\"search\"] {\n  -webkit-appearance: textfield;\n  /* 1 */\n  -webkit-box-sizing: content-box;\n          box-sizing: content-box;\n  /* 2 */\n}\n/**\n * Remove inner padding and search cancel button in Safari 5 and Chrome\n * on OS X.\n */\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n  -webkit-appearance: none;\n}\n/**\n * 1. Remove default vertical scrollbar in IE 8/9.\n * 2. Improve readability and alignment in all browsers.\n */\ntextarea {\n  overflow: auto;\n  /* 1 */\n  vertical-align: top;\n  /* 2 */\n  resize: vertical;\n}\n/**\n * Don't inherit the `font-weight` (applied by a rule above).\n * NOTE: the default cannot safely be changed in Chrome and Safari on OS X.\n */\noptgroup {\n  font-weight: bold;\n}\n/* Tables\n   ========================================================================== */\n/**\n * Remove most spacing between table cells.\n */\ntable {\n  border-collapse: collapse;\n  border-spacing: 0;\n}\ntd,\nth {\n  padding: 0;\n}\n/* AMUI Base\n   ========================================================================== */\n/**\n * `font-size` is set in `html` element to support the `rem` unit for font-sizes\n * NOTE: IE9 & IE10 do not recognize `rem` units when used with the\n   `font` shorthand property.\n */\nhtml {\n  font-size: 10px;\n  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\nbody {\n  position: relative;\n  background: #fff;\n  font-family: \"Segoe UI\", \"Lucida Grande\", Helvetica, Arial, \"Microsoft YaHei\", FreeSans, Arimo, \"Droid Sans\", \"wenquanyi micro hei\", \"Hiragino Sans GB\", \"Hiragino Sans GB W3\", \"FontAwesome\", sans-serif;\n  font-weight: normal;\n  line-height: 1.6;\n  color: #333333;\n  font-size: 1.6rem;\n}\n/**\n * 1. http://usabilitypost.com/2012/11/15/w-optimizelegibility-on-mobile-devices/\n * 2. http://maxvoltar.com/archive/-webkit-font-smoothing\n * NOTE: http://usabilitypost.com/2012/11/05/stop-fixing-font-smoothing/\n * 3. http://maximilianhoffmann.com/posts/better-font-rendering-on-osx\n *    http://jaydenseric.com/blog/css-font-smoothing-for-firefox-mac\n */\nbody,\ninput,\ntextarea,\nselect,\nbutton {\n  text-rendering: optimizeLegibility;\n  /* 1 */\n  -webkit-font-smoothing: antialiased;\n  /* 2 */\n  -moz-osx-font-smoothing: grayscale;\n  /* 3 Default: auto */\n  -moz-font-feature-settings: \"liga\", \"kern\";\n}\n/*Only phones */\n@media only screen and (max-width: 640px) {\n  /**\n   * Break strings if their length exceeds the width of their container\n   */\n  body {\n    word-wrap: break-word;\n    -webkit-hyphens: auto;\n    -ms-hyphens: auto;\n    -moz-hyphens: auto;\n    hyphens: auto;\n  }\n}\n/**\n * links\n */\na {\n  color: #0e90d2;\n}\na:hover,\na:focus {\n  color: #095f8a;\n}\na:focus {\n  outline: thin dotted;\n  outline: 1px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n/* Insert */\nins {\n  background: #ffa;\n  color: #333333;\n}\n/**\n * Mark\n * Note: Addresses styling not present in IE 8/9.\n */\nmark {\n  background: #ffa;\n  color: #333333;\n}\n/**\n * Abbreviation and definition\n */\nabbr[title],\ndfn[title] {\n  cursor: help;\n}\ndfn[title] {\n  border-bottom: 1px dotted;\n  font-style: normal;\n}\n/* Spacing for block elements */\np,\nhr,\nul,\nol,\ndl,\nblockquote,\npre,\naddress,\nfieldset,\nfigure {\n  margin: 0 0 1.6rem 0;\n}\n* + p,\n* + hr,\n* + ul,\n* + ol,\n* + dl,\n* + blockquote,\n* + pre,\n* + address,\n* + fieldset,\n* + figure {\n  margin-top: 1.6rem;\n}\n/* Headings\n   ========================================================================== */\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 0 0 1.6rem 0;\n  font-weight: 600;\n  font-size: 100%;\n}\nh1 {\n  font-size: 1.5em;\n}\nh2 {\n  font-size: 1.25em;\n}\n* + h1,\n* + h2,\n* + h3,\n* + h4,\n* + h5,\n* + h6 {\n  margin-top: 2em;\n}\n/* Ordered and unordered lists */\nul,\nol {\n  padding-left: 2em;\n}\n/* Reset margin for nested lists */\nul > li > ul,\nul > li > ol,\nol > li > ol,\nol > li > ul {\n  margin: 1em 0;\n}\n/* Description lists */\ndt {\n  font-weight: bold;\n}\ndt + dd {\n  margin-top: .5em;\n}\ndd {\n  margin-left: 0;\n}\ndd + dt {\n  margin-top: 1em;\n}\n/**\n * Horizontal rule\n * 1. Address differences between Firefox and other browsers.\n */\nhr {\n  display: block;\n  padding: 0;\n  border: 0;\n  height: 0;\n  border-top: 1px solid #eeeeee;\n  /* 1 */\n  -webkit-box-sizing: content-box;\n          box-sizing: content-box;\n  /* 1 */\n}\n/* Address */\naddress {\n  font-style: normal;\n}\n/* Quotes */\nblockquote {\n  padding-top: 5px;\n  padding-bottom: 5px;\n  padding-left: 15px;\n  border-left: 4px solid #ddd;\n  font-family: Georgia, \"Times New Roman\", Times, Kai, \"Kaiti SC\", KaiTi, BiauKai, \"FontAwesome\", serif;\n  /* Small print for identifying the source */\n  /* Smaller margin if `small` follows */\n}\nblockquote small {\n  display: block;\n  color: #999999;\n  font-family: \"Segoe UI\", \"Lucida Grande\", Helvetica, Arial, \"Microsoft YaHei\", FreeSans, Arimo, \"Droid Sans\", \"wenquanyi micro hei\", \"Hiragino Sans GB\", \"Hiragino Sans GB W3\", \"FontAwesome\", sans-serif;\n  text-align: right;\n}\nblockquote p:last-of-type {\n  margin-bottom: 0;\n}\n/* iframe */\niframe {\n  border: 0;\n}\n/* Forms\n   ========================================================================== */\n/**\n  * Vertical alignment\n  * Exclude `radio` and `checkbox` elements because the default `baseline` value aligns better with text\n  */\nbutton,\ninput:not([type=\"radio\"]):not([type=\"checkbox\"]),\nselect {\n  vertical-align: middle;\n}\n/**\n * Fix viewport for IE10 snap mode\n * http://timkadlec.com/2012/10/ie10-snap-mode-and-responsive-design/\n * http://msdn.microsoft.com/en-us/library/ie/hh869615%28v=vs.85%29.aspx\n * http://msdn.microsoft.com/zh-cn/library/ie/hh708740(v=vs.85).aspx\n * @2014.01.20: 设置一下属性以后，windows Phone 8 上显示的字体过小，暂时注释掉\n * ========================================================================== */\n/*\n@-ms-viewport {\n  width: device-width;\n}\n*/\n.am-scrollbar-measure {\n  width: 100px;\n  height: 100px;\n  overflow: scroll;\n  position: absolute;\n  top: -9999px;\n}\n/* ==========================================================================\n   Component: Grid\n ============================================================================ */\n.am-container {\n  -webkit-box-sizing: border-box;\n          box-sizing: border-box;\n  margin-left: auto;\n  margin-right: auto;\n  padding-left: 1rem;\n  padding-right: 1rem;\n  width: 100%;\n  max-width: 1000px;\n}\n.am-container:before,\n.am-container:after {\n  content: \" \";\n  display: table;\n}\n.am-container:after {\n  clear: both;\n}\n@media only screen and (min-width:641px) {\n  .am-container {\n    padding-left: 1.5rem;\n    padding-right: 1.5rem;\n  }\n}\n.am-container > .am-g {\n  width: auto;\n  margin-left: -1rem;\n  margin-right: -1rem;\n}\n@media only screen and (min-width:641px) {\n  .am-container > .am-g {\n    margin-left: -1.5rem;\n    margin-right: -1.5rem;\n  }\n}\n.am-g {\n  margin: 0 auto;\n  width: 100%;\n}\n.am-g:before,\n.am-g:after {\n  content: \" \";\n  display: table;\n}\n.am-g:after {\n  clear: both;\n}\n.am-g .am-g {\n  margin-left: -1rem;\n  margin-right: -1rem;\n  width: auto;\n}\n.am-g .am-g.am-g-collapse {\n  margin-left: 0;\n  margin-right: 0;\n  width: auto;\n}\n@media only screen and (min-width:641px) {\n  .am-g .am-g {\n    margin-left: -1.5rem;\n    margin-right: -1.5rem;\n  }\n}\n.am-g.am-g-collapse .am-g {\n  margin-left: 0;\n  margin-right: 0;\n}\n.am-g-collapse [class*=\"am-u-\"] {\n  padding-left: 0;\n  padding-right: 0;\n}\n.am-g-fixed {\n  max-width: 1000px;\n}\n[class*=\"am-u-\"] {\n  width: 100%;\n  padding-left: 1rem;\n  padding-right: 1rem;\n  float: left;\n  position: relative;\n}\n[class*=\"am-u-\"] + [class*=\"am-u-\"]:last-child {\n  float: right;\n}\n[class*=\"am-u-\"] + [class*=\"am-u-\"].am-u-end {\n  float: left;\n}\n@media only screen and (min-width:641px) {\n  [class*=\"am-u-\"] {\n    padding-left: 1.5rem;\n    padding-right: 1.5rem;\n  }\n}\n[class*=\"am-u-pull-\"] {\n  left: auto;\n}\n[class*=\"am-u-push-\"] {\n  right: auto;\n}\n@media only screen {\n  .am-u-sm-1 {\n    width: 8.33333333%;\n  }\n  .am-u-sm-2 {\n    width: 16.66666667%;\n  }\n  .am-u-sm-3 {\n    width: 25%;\n  }\n  .am-u-sm-4 {\n    width: 33.33333333%;\n  }\n  .am-u-sm-5 {\n    width: 41.66666667%;\n  }\n  .am-u-sm-6 {\n    width: 50%;\n  }\n  .am-u-sm-7 {\n    width: 58.33333333%;\n  }\n  .am-u-sm-8 {\n    width: 66.66666667%;\n  }\n  .am-u-sm-9 {\n    width: 75%;\n  }\n  .am-u-sm-10 {\n    width: 83.33333333%;\n  }\n  .am-u-sm-11 {\n    width: 91.66666667%;\n  }\n  .am-u-sm-12 {\n    width: 100%;\n  }\n  .am-u-sm-pull-0 {\n    right: 0;\n  }\n  .am-u-sm-pull-1 {\n    right: 8.33333333%;\n  }\n  .am-u-sm-pull-2 {\n    right: 16.66666667%;\n  }\n  .am-u-sm-pull-3 {\n    right: 25%;\n  }\n  .am-u-sm-pull-4 {\n    right: 33.33333333%;\n  }\n  .am-u-sm-pull-5 {\n    right: 41.66666667%;\n  }\n  .am-u-sm-pull-6 {\n    right: 50%;\n  }\n  .am-u-sm-pull-7 {\n    right: 58.33333333%;\n  }\n  .am-u-sm-pull-8 {\n    right: 66.66666667%;\n  }\n  .am-u-sm-pull-9 {\n    right: 75%;\n  }\n  .am-u-sm-pull-10 {\n    right: 83.33333333%;\n  }\n  .am-u-sm-pull-11 {\n    right: 91.66666667%;\n  }\n  .am-u-sm-push-0 {\n    left: 0;\n  }\n  .am-u-sm-push-1 {\n    left: 8.33333333%;\n  }\n  .am-u-sm-push-2 {\n    left: 16.66666667%;\n  }\n  .am-u-sm-push-3 {\n    left: 25%;\n  }\n  .am-u-sm-push-4 {\n    left: 33.33333333%;\n  }\n  .am-u-sm-push-5 {\n    left: 41.66666667%;\n  }\n  .am-u-sm-push-6 {\n    left: 50%;\n  }\n  .am-u-sm-push-7 {\n    left: 58.33333333%;\n  }\n  .am-u-sm-push-8 {\n    left: 66.66666667%;\n  }\n  .am-u-sm-push-9 {\n    left: 75%;\n  }\n  .am-u-sm-push-10 {\n    left: 83.33333333%;\n  }\n  .am-u-sm-push-11 {\n    left: 91.66666667%;\n  }\n  .am-u-sm-offset-0 {\n    margin-left: 0;\n  }\n  .am-u-sm-offset-1 {\n    margin-left: 8.33333333%;\n  }\n  .am-u-sm-offset-2 {\n    margin-left: 16.66666667%;\n  }\n  .am-u-sm-offset-3 {\n    margin-left: 25%;\n  }\n  .am-u-sm-offset-4 {\n    margin-left: 33.33333333%;\n  }\n  .am-u-sm-offset-5 {\n    margin-left: 41.66666667%;\n  }\n  .am-u-sm-offset-6 {\n    margin-left: 50%;\n  }\n  .am-u-sm-offset-7 {\n    margin-left: 58.33333333%;\n  }\n  .am-u-sm-offset-8 {\n    margin-left: 66.66666667%;\n  }\n  .am-u-sm-offset-9 {\n    margin-left: 75%;\n  }\n  .am-u-sm-offset-10 {\n    margin-left: 83.33333333%;\n  }\n  .am-u-sm-offset-11 {\n    margin-left: 91.66666667%;\n  }\n  .am-u-sm-reset-order {\n    margin-left: 0;\n    margin-right: 0;\n    left: auto;\n    right: auto;\n    float: left;\n  }\n  [class*=\"am-u-\"].am-u-sm-centered {\n    margin-left: auto;\n    margin-right: auto;\n    float: none;\n  }\n  [class*=\"am-u-\"].am-u-sm-centered:last-child {\n    float: none;\n  }\n  [class*=\"am-u-\"].am-u-sm-uncentered {\n    margin-left: 0;\n    margin-right: 0;\n    float: left;\n  }\n  [class*=\"am-u-\"].am-u-sm-uncentered:last-child {\n    float: left;\n  }\n}\n@media only screen and (min-width:641px) {\n  .am-u-md-1 {\n    width: 8.33333333%;\n  }\n  .am-u-md-2 {\n    width: 16.66666667%;\n  }\n  .am-u-md-3 {\n    width: 25%;\n  }\n  .am-u-md-4 {\n    width: 33.33333333%;\n  }\n  .am-u-md-5 {\n    width: 41.66666667%;\n  }\n  .am-u-md-6 {\n    width: 50%;\n  }\n  .am-u-md-7 {\n    width: 58.33333333%;\n  }\n  .am-u-md-8 {\n    width: 66.66666667%;\n  }\n  .am-u-md-9 {\n    width: 75%;\n  }\n  .am-u-md-10 {\n    width: 83.33333333%;\n  }\n  .am-u-md-11 {\n    width: 91.66666667%;\n  }\n  .am-u-md-12 {\n    width: 100%;\n  }\n  .am-u-md-pull-0 {\n    right: 0;\n  }\n  .am-u-md-pull-1 {\n    right: 8.33333333%;\n  }\n  .am-u-md-pull-2 {\n    right: 16.66666667%;\n  }\n  .am-u-md-pull-3 {\n    right: 25%;\n  }\n  .am-u-md-pull-4 {\n    right: 33.33333333%;\n  }\n  .am-u-md-pull-5 {\n    right: 41.66666667%;\n  }\n  .am-u-md-pull-6 {\n    right: 50%;\n  }\n  .am-u-md-pull-7 {\n    right: 58.33333333%;\n  }\n  .am-u-md-pull-8 {\n    right: 66.66666667%;\n  }\n  .am-u-md-pull-9 {\n    right: 75%;\n  }\n  .am-u-md-pull-10 {\n    right: 83.33333333%;\n  }\n  .am-u-md-pull-11 {\n    right: 91.66666667%;\n  }\n  .am-u-md-push-0 {\n    left: 0;\n  }\n  .am-u-md-push-1 {\n    left: 8.33333333%;\n  }\n  .am-u-md-push-2 {\n    left: 16.66666667%;\n  }\n  .am-u-md-push-3 {\n    left: 25%;\n  }\n  .am-u-md-push-4 {\n    left: 33.33333333%;\n  }\n  .am-u-md-push-5 {\n    left: 41.66666667%;\n  }\n  .am-u-md-push-6 {\n    left: 50%;\n  }\n  .am-u-md-push-7 {\n    left: 58.33333333%;\n  }\n  .am-u-md-push-8 {\n    left: 66.66666667%;\n  }\n  .am-u-md-push-9 {\n    left: 75%;\n  }\n  .am-u-md-push-10 {\n    left: 83.33333333%;\n  }\n  .am-u-md-push-11 {\n    left: 91.66666667%;\n  }\n  .am-u-md-offset-0 {\n    margin-left: 0;\n  }\n  .am-u-md-offset-1 {\n    margin-left: 8.33333333%;\n  }\n  .am-u-md-offset-2 {\n    margin-left: 16.66666667%;\n  }\n  .am-u-md-offset-3 {\n    margin-left: 25%;\n  }\n  .am-u-md-offset-4 {\n    margin-left: 33.33333333%;\n  }\n  .am-u-md-offset-5 {\n    margin-left: 41.66666667%;\n  }\n  .am-u-md-offset-6 {\n    margin-left: 50%;\n  }\n  .am-u-md-offset-7 {\n    margin-left: 58.33333333%;\n  }\n  .am-u-md-offset-8 {\n    margin-left: 66.66666667%;\n  }\n  .am-u-md-offset-9 {\n    margin-left: 75%;\n  }\n  .am-u-md-offset-10 {\n    margin-left: 83.33333333%;\n  }\n  .am-u-md-offset-11 {\n    margin-left: 91.66666667%;\n  }\n  .am-u-md-reset-order {\n    margin-left: 0;\n    margin-right: 0;\n    left: auto;\n    right: auto;\n    float: left;\n  }\n  [class*=\"am-u-\"].am-u-md-centered {\n    margin-left: auto;\n    margin-right: auto;\n    float: none;\n  }\n  [class*=\"am-u-\"].am-u-md-centered:last-child {\n    float: none;\n  }\n  [class*=\"am-u-\"].am-u-md-uncentered {\n    margin-left: 0;\n    margin-right: 0;\n    float: left;\n  }\n  [class*=\"am-u-\"].am-u-md-uncentered:last-child {\n    float: left;\n  }\n}\n@media only screen and (min-width:1025px) {\n  .am-u-lg-1 {\n    width: 8.33333333%;\n  }\n  .am-u-lg-2 {\n    width: 16.66666667%;\n  }\n  .am-u-lg-3 {\n    width: 25%;\n  }\n  .am-u-lg-4 {\n    width: 33.33333333%;\n  }\n  .am-u-lg-5 {\n    width: 41.66666667%;\n  }\n  .am-u-lg-6 {\n    width: 50%;\n  }\n  .am-u-lg-7 {\n    width: 58.33333333%;\n  }\n  .am-u-lg-8 {\n    width: 66.66666667%;\n  }\n  .am-u-lg-9 {\n    width: 75%;\n  }\n  .am-u-lg-10 {\n    width: 83.33333333%;\n  }\n  .am-u-lg-11 {\n    width: 91.66666667%;\n  }\n  .am-u-lg-12 {\n    width: 100%;\n  }\n  .am-u-lg-pull-0 {\n    right: 0;\n  }\n  .am-u-lg-pull-1 {\n    right: 8.33333333%;\n  }\n  .am-u-lg-pull-2 {\n    right: 16.66666667%;\n  }\n  .am-u-lg-pull-3 {\n    right: 25%;\n  }\n  .am-u-lg-pull-4 {\n    right: 33.33333333%;\n  }\n  .am-u-lg-pull-5 {\n    right: 41.66666667%;\n  }\n  .am-u-lg-pull-6 {\n    right: 50%;\n  }\n  .am-u-lg-pull-7 {\n    right: 58.33333333%;\n  }\n  .am-u-lg-pull-8 {\n    right: 66.66666667%;\n  }\n  .am-u-lg-pull-9 {\n    right: 75%;\n  }\n  .am-u-lg-pull-10 {\n    right: 83.33333333%;\n  }\n  .am-u-lg-pull-11 {\n    right: 91.66666667%;\n  }\n  .am-u-lg-push-0 {\n    left: 0;\n  }\n  .am-u-lg-push-1 {\n    left: 8.33333333%;\n  }\n  .am-u-lg-push-2 {\n    left: 16.66666667%;\n  }\n  .am-u-lg-push-3 {\n    left: 25%;\n  }\n  .am-u-lg-push-4 {\n    left: 33.33333333%;\n  }\n  .am-u-lg-push-5 {\n    left: 41.66666667%;\n  }\n  .am-u-lg-push-6 {\n    left: 50%;\n  }\n  .am-u-lg-push-7 {\n    left: 58.33333333%;\n  }\n  .am-u-lg-push-8 {\n    left: 66.66666667%;\n  }\n  .am-u-lg-push-9 {\n    left: 75%;\n  }\n  .am-u-lg-push-10 {\n    left: 83.33333333%;\n  }\n  .am-u-lg-push-11 {\n    left: 91.66666667%;\n  }\n  .am-u-lg-offset-0 {\n    margin-left: 0;\n  }\n  .am-u-lg-offset-1 {\n    margin-left: 8.33333333%;\n  }\n  .am-u-lg-offset-2 {\n    margin-left: 16.66666667%;\n  }\n  .am-u-lg-offset-3 {\n    margin-left: 25%;\n  }\n  .am-u-lg-offset-4 {\n    margin-left: 33.33333333%;\n  }\n  .am-u-lg-offset-5 {\n    margin-left: 41.66666667%;\n  }\n  .am-u-lg-offset-6 {\n    margin-left: 50%;\n  }\n  .am-u-lg-offset-7 {\n    margin-left: 58.33333333%;\n  }\n  .am-u-lg-offset-8 {\n    margin-left: 66.66666667%;\n  }\n  .am-u-lg-offset-9 {\n    margin-left: 75%;\n  }\n  .am-u-lg-offset-10 {\n    margin-left: 83.33333333%;\n  }\n  .am-u-lg-offset-11 {\n    margin-left: 91.66666667%;\n  }\n  .am-u-lg-reset-order {\n    margin-left: 0;\n    margin-right: 0;\n    left: auto;\n    right: auto;\n    float: left;\n  }\n  [class*=\"am-u-\"].am-u-lg-centered {\n    margin-left: auto;\n    margin-right: auto;\n    float: none;\n  }\n  [class*=\"am-u-\"].am-u-lg-centered:last-child {\n    float: none;\n  }\n  [class*=\"am-u-\"].am-u-lg-uncentered {\n    margin-left: 0;\n    margin-right: 0;\n    float: left;\n  }\n  [class*=\"am-u-\"].am-u-lg-uncentered:last-child {\n    float: left;\n  }\n}\n/* ==========================================================================\n   Component: AVG Grid\n ============================================================================ */\n[class*=\"am-avg-\"] {\n  display: block;\n  padding: 0;\n  margin: 0;\n  list-style: none;\n}\n[class*=\"am-avg-\"]:before,\n[class*=\"am-avg-\"]:after {\n  content: \" \";\n  display: table;\n}\n[class*=\"am-avg-\"]:after {\n  clear: both;\n}\n[class*=\"am-avg-\"] > li {\n  display: block;\n  height: auto;\n  float: left;\n}\n@media only screen {\n  .am-avg-sm-1 > li {\n    width: 100%;\n  }\n  .am-avg-sm-1 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-1 > li:nth-of-type(1n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-2 > li {\n    width: 50%;\n  }\n  .am-avg-sm-2 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-2 > li:nth-of-type(2n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-3 > li {\n    width: 33.33333333%;\n  }\n  .am-avg-sm-3 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-3 > li:nth-of-type(3n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-4 > li {\n    width: 25%;\n  }\n  .am-avg-sm-4 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-4 > li:nth-of-type(4n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-5 > li {\n    width: 20%;\n  }\n  .am-avg-sm-5 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-5 > li:nth-of-type(5n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-6 > li {\n    width: 16.66666667%;\n  }\n  .am-avg-sm-6 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-6 > li:nth-of-type(6n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-7 > li {\n    width: 14.28571429%;\n  }\n  .am-avg-sm-7 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-7 > li:nth-of-type(7n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-8 > li {\n    width: 12.5%;\n  }\n  .am-avg-sm-8 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-8 > li:nth-of-type(8n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-9 > li {\n    width: 11.11111111%;\n  }\n  .am-avg-sm-9 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-9 > li:nth-of-type(9n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-10 > li {\n    width: 10%;\n  }\n  .am-avg-sm-10 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-10 > li:nth-of-type(10n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-11 > li {\n    width: 9.09090909%;\n  }\n  .am-avg-sm-11 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-11 > li:nth-of-type(11n + 1) {\n    clear: both;\n  }\n  .am-avg-sm-12 > li {\n    width: 8.33333333%;\n  }\n  .am-avg-sm-12 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-sm-12 > li:nth-of-type(12n + 1) {\n    clear: both;\n  }\n}\n@media only screen and (min-width:641px) {\n  .am-avg-md-1 > li {\n    width: 100%;\n  }\n  .am-avg-md-1 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-1 > li:nth-of-type(1n + 1) {\n    clear: both;\n  }\n  .am-avg-md-2 > li {\n    width: 50%;\n  }\n  .am-avg-md-2 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-2 > li:nth-of-type(2n + 1) {\n    clear: both;\n  }\n  .am-avg-md-3 > li {\n    width: 33.33333333%;\n  }\n  .am-avg-md-3 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-3 > li:nth-of-type(3n + 1) {\n    clear: both;\n  }\n  .am-avg-md-4 > li {\n    width: 25%;\n  }\n  .am-avg-md-4 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-4 > li:nth-of-type(4n + 1) {\n    clear: both;\n  }\n  .am-avg-md-5 > li {\n    width: 20%;\n  }\n  .am-avg-md-5 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-5 > li:nth-of-type(5n + 1) {\n    clear: both;\n  }\n  .am-avg-md-6 > li {\n    width: 16.66666667%;\n  }\n  .am-avg-md-6 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-6 > li:nth-of-type(6n + 1) {\n    clear: both;\n  }\n  .am-avg-md-7 > li {\n    width: 14.28571429%;\n  }\n  .am-avg-md-7 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-7 > li:nth-of-type(7n + 1) {\n    clear: both;\n  }\n  .am-avg-md-8 > li {\n    width: 12.5%;\n  }\n  .am-avg-md-8 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-8 > li:nth-of-type(8n + 1) {\n    clear: both;\n  }\n  .am-avg-md-9 > li {\n    width: 11.11111111%;\n  }\n  .am-avg-md-9 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-9 > li:nth-of-type(9n + 1) {\n    clear: both;\n  }\n  .am-avg-md-10 > li {\n    width: 10%;\n  }\n  .am-avg-md-10 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-10 > li:nth-of-type(10n + 1) {\n    clear: both;\n  }\n  .am-avg-md-11 > li {\n    width: 9.09090909%;\n  }\n  .am-avg-md-11 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-11 > li:nth-of-type(11n + 1) {\n    clear: both;\n  }\n  .am-avg-md-12 > li {\n    width: 8.33333333%;\n  }\n  .am-avg-md-12 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-md-12 > li:nth-of-type(12n + 1) {\n    clear: both;\n  }\n}\n@media only screen and (min-width:1025px) {\n  .am-avg-lg-1 > li {\n    width: 100%;\n  }\n  .am-avg-lg-1 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-1 > li:nth-of-type(1n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-2 > li {\n    width: 50%;\n  }\n  .am-avg-lg-2 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-2 > li:nth-of-type(2n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-3 > li {\n    width: 33.33333333%;\n  }\n  .am-avg-lg-3 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-3 > li:nth-of-type(3n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-4 > li {\n    width: 25%;\n  }\n  .am-avg-lg-4 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-4 > li:nth-of-type(4n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-5 > li {\n    width: 20%;\n  }\n  .am-avg-lg-5 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-5 > li:nth-of-type(5n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-6 > li {\n    width: 16.66666667%;\n  }\n  .am-avg-lg-6 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-6 > li:nth-of-type(6n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-7 > li {\n    width: 14.28571429%;\n  }\n  .am-avg-lg-7 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-7 > li:nth-of-type(7n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-8 > li {\n    width: 12.5%;\n  }\n  .am-avg-lg-8 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-8 > li:nth-of-type(8n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-9 > li {\n    width: 11.11111111%;\n  }\n  .am-avg-lg-9 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-9 > li:nth-of-type(9n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-10 > li {\n    width: 10%;\n  }\n  .am-avg-lg-10 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-10 > li:nth-of-type(10n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-11 > li {\n    width: 9.09090909%;\n  }\n  .am-avg-lg-11 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-11 > li:nth-of-type(11n + 1) {\n    clear: both;\n  }\n  .am-avg-lg-12 > li {\n    width: 8.33333333%;\n  }\n  .am-avg-lg-12 > li:nth-of-type(n) {\n    clear: none;\n  }\n  .am-avg-lg-12 > li:nth-of-type(12n + 1) {\n    clear: both;\n  }\n}\n/* ==========================================================================\n   Component: Code\n ============================================================================ */\n/* Inline and block code styles */\ncode,\nkbd,\npre,\nsamp {\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", \"FontAwesome\", monospace;\n}\n/* Inline code */\ncode {\n  padding: 2px 4px;\n  font-size: 1.3rem;\n  color: #c7254e;\n  background-color: #f8f8f8;\n  white-space: nowrap;\n  border-radius: 2px;\n}\n/* Code block */\npre {\n  display: block;\n  padding: 1rem;\n  margin: 1rem  0;\n  font-size: 1.3rem;\n  line-height: 1.6;\n  word-break: break-all;\n  word-wrap: break-word;\n  color: #555555;\n  background-color: #f8f8f8;\n  border: 1px solid #dedede;\n  border-radius: 2px;\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/* Enable scrollable blocks of code */\n.am-pre-scrollable {\n  max-height: 24rem;\n  overflow-y: scroll;\n}\n/* ==========================================================================\n   Component: Button\n ============================================================================ */\n.am-btn {\n  display: inline-block;\n  margin-bottom: 0;\n  padding: 0.5em 1em;\n  vertical-align: middle;\n  font-size: 1.6rem;\n  font-weight: normal;\n  line-height: 1.2;\n  text-align: center;\n  white-space: nowrap;\n  background-image: none;\n  border: 1px solid transparent;\n  border-radius: 2px;\n  cursor: pointer;\n  outline: none;\n  -webkit-appearance: none;\n  -webkit-user-select: none;\n     -moz-user-select: none;\n      -ms-user-select: none;\n          user-select: none;\n  -webkit-transition: background-color 300ms ease-out, border-color 300ms ease-out;\n  transition: background-color 300ms ease-out, border-color 300ms ease-out;\n}\n.am-btn.am-square {\n  border-radius: 0;\n}\n.am-btn:focus,\n.am-btn:active:focus {\n  outline: thin dotted;\n  outline: 1px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n.am-btn:hover,\n.am-btn:focus {\n  color: #444;\n  text-decoration: none;\n}\n.am-btn:active,\n.am-btn.am-active {\n  background-image: none;\n  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.15);\n}\n.am-btn.am-disabled,\n.am-btn[disabled],\nfieldset[disabled] .am-btn {\n  pointer-events: none;\n  border-color: transparent;\n  cursor: not-allowed;\n  opacity: 0.45;\n  -webkit-box-shadow: none;\n          box-shadow: none;\n}\n.am-btn.am-round {\n  border-radius: 1000px;\n}\n.am-btn.am-radius {\n  border-radius: 2px;\n}\n.am-btn-default {\n  color: #444;\n  background-color: #e6e6e6;\n  border-color: #e6e6e6;\n}\na.am-btn-default:visited {\n  color: #444;\n}\n.am-btn-default:hover,\n.am-btn-default:focus,\n.am-btn-default:active,\n.am-btn-default.am-active,\n.am-active .am-btn-default.am-dropdown-toggle {\n  color: #444;\n  border-color: #c7c7c7;\n}\n.am-btn-default:hover,\n.am-btn-default:focus {\n  background-color: #d4d4d4;\n}\n.am-btn-default:active,\n.am-btn-default.am-active,\n.am-active .am-btn-default.am-dropdown-toggle {\n  background-image: none;\n  background-color: #c2c2c2;\n}\n.am-btn-default.am-disabled,\n.am-btn-default[disabled],\nfieldset[disabled] .am-btn-default,\n.am-btn-default.am-disabled:hover,\n.am-btn-default[disabled]:hover,\nfieldset[disabled] .am-btn-default:hover,\n.am-btn-default.am-disabled:focus,\n.am-btn-default[disabled]:focus,\nfieldset[disabled] .am-btn-default:focus,\n.am-btn-default.am-disabled:active,\n.am-btn-default[disabled]:active,\nfieldset[disabled] .am-btn-default:active,\n.am-btn-default.am-disabled.am-active,\n.am-btn-default[disabled].am-active,\nfieldset[disabled] .am-btn-default.am-active {\n  background-color: #e6e6e6;\n  border-color: #e6e6e6;\n}\n.am-btn-group .am-btn-default,\n.am-btn-group-stacked .am-btn-default {\n  border-color: #d9d9d9;\n}\n.am-btn-primary {\n  color: #fff;\n  background-color: #0e90d2;\n  border-color: #0e90d2;\n}\na.am-btn-primary:visited {\n  color: #fff;\n}\n.am-btn-primary:hover,\n.am-btn-primary:focus,\n.am-btn-primary:active,\n.am-btn-primary.am-active,\n.am-active .am-btn-primary.am-dropdown-toggle {\n  color: #fff;\n  border-color: #0a6999;\n}\n.am-btn-primary:hover,\n.am-btn-primary:focus {\n  background-color: #0c79b1;\n}\n.am-btn-primary:active,\n.am-btn-primary.am-active,\n.am-active .am-btn-primary.am-dropdown-toggle {\n  background-image: none;\n  background-color: #0a628f;\n}\n.am-btn-primary.am-disabled,\n.am-btn-primary[disabled],\nfieldset[disabled] .am-btn-primary,\n.am-btn-primary.am-disabled:hover,\n.am-btn-primary[disabled]:hover,\nfieldset[disabled] .am-btn-primary:hover,\n.am-btn-primary.am-disabled:focus,\n.am-btn-primary[disabled]:focus,\nfieldset[disabled] .am-btn-primary:focus,\n.am-btn-primary.am-disabled:active,\n.am-btn-primary[disabled]:active,\nfieldset[disabled] .am-btn-primary:active,\n.am-btn-primary.am-disabled.am-active,\n.am-btn-primary[disabled].am-active,\nfieldset[disabled] .am-btn-primary.am-active {\n  background-color: #0e90d2;\n  border-color: #0e90d2;\n}\n.am-btn-group .am-btn-primary,\n.am-btn-group-stacked .am-btn-primary {\n  border-color: #0c80ba;\n}\n.am-btn-warning {\n  color: #fff;\n  background-color: #F37B1D;\n  border-color: #F37B1D;\n}\na.am-btn-warning:visited {\n  color: #fff;\n}\n.am-btn-warning:hover,\n.am-btn-warning:focus,\n.am-btn-warning:active,\n.am-btn-warning.am-active,\n.am-active .am-btn-warning.am-dropdown-toggle {\n  color: #fff;\n  border-color: #c85e0b;\n}\n.am-btn-warning:hover,\n.am-btn-warning:focus {\n  background-color: #e0690c;\n}\n.am-btn-warning:active,\n.am-btn-warning.am-active,\n.am-active .am-btn-warning.am-dropdown-toggle {\n  background-image: none;\n  background-color: #be590a;\n}\n.am-btn-warning.am-disabled,\n.am-btn-warning[disabled],\nfieldset[disabled] .am-btn-warning,\n.am-btn-warning.am-disabled:hover,\n.am-btn-warning[disabled]:hover,\nfieldset[disabled] .am-btn-warning:hover,\n.am-btn-warning.am-disabled:focus,\n.am-btn-warning[disabled]:focus,\nfieldset[disabled] .am-btn-warning:focus,\n.am-btn-warning.am-disabled:active,\n.am-btn-warning[disabled]:active,\nfieldset[disabled] .am-btn-warning:active,\n.am-btn-warning.am-disabled.am-active,\n.am-btn-warning[disabled].am-active,\nfieldset[disabled] .am-btn-warning.am-active {\n  background-color: #F37B1D;\n  border-color: #F37B1D;\n}\n.am-btn-group .am-btn-warning,\n.am-btn-group-stacked .am-btn-warning {\n  border-color: #ea6e0c;\n}\n.am-btn-danger {\n  color: #fff;\n  background-color: #dd514c;\n  border-color: #dd514c;\n}\na.am-btn-danger:visited {\n  color: #fff;\n}\n.am-btn-danger:hover,\n.am-btn-danger:focus,\n.am-btn-danger:active,\n.am-btn-danger.am-active,\n.am-active .am-btn-danger.am-dropdown-toggle {\n  color: #fff;\n  border-color: #c62b26;\n}\n.am-btn-danger:hover,\n.am-btn-danger:focus {\n  background-color: #d7342e;\n}\n.am-btn-danger:active,\n.am-btn-danger.am-active,\n.am-active .am-btn-danger.am-dropdown-toggle {\n  background-image: none;\n  background-color: #be2924;\n}\n.am-btn-danger.am-disabled,\n.am-btn-danger[disabled],\nfieldset[disabled] .am-btn-danger,\n.am-btn-danger.am-disabled:hover,\n.am-btn-danger[disabled]:hover,\nfieldset[disabled] .am-btn-danger:hover,\n.am-btn-danger.am-disabled:focus,\n.am-btn-danger[disabled]:focus,\nfieldset[disabled] .am-btn-danger:focus,\n.am-btn-danger.am-disabled:active,\n.am-btn-danger[disabled]:active,\nfieldset[disabled] .am-btn-danger:active,\n.am-btn-danger.am-disabled.am-active,\n.am-btn-danger[disabled].am-active,\nfieldset[disabled] .am-btn-danger.am-active {\n  background-color: #dd514c;\n  border-color: #dd514c;\n}\n.am-btn-group .am-btn-danger,\n.am-btn-group-stacked .am-btn-danger {\n  border-color: #d93c37;\n}\n.am-btn-success {\n  color: #fff;\n  background-color: #5eb95e;\n  border-color: #5eb95e;\n}\na.am-btn-success:visited {\n  color: #fff;\n}\n.am-btn-success:hover,\n.am-btn-success:focus,\n.am-btn-success:active,\n.am-btn-success.am-active,\n.am-active .am-btn-success.am-dropdown-toggle {\n  color: #fff;\n  border-color: #429842;\n}\n.am-btn-success:hover,\n.am-btn-success:focus {\n  background-color: #4aaa4a;\n}\n.am-btn-success:active,\n.am-btn-success.am-active,\n.am-active .am-btn-success.am-dropdown-toggle {\n  background-image: none;\n  background-color: #3f913f;\n}\n.am-btn-success.am-disabled,\n.am-btn-success[disabled],\nfieldset[disabled] .am-btn-success,\n.am-btn-success.am-disabled:hover,\n.am-btn-success[disabled]:hover,\nfieldset[disabled] .am-btn-success:hover,\n.am-btn-success.am-disabled:focus,\n.am-btn-success[disabled]:focus,\nfieldset[disabled] .am-btn-success:focus,\n.am-btn-success.am-disabled:active,\n.am-btn-success[disabled]:active,\nfieldset[disabled] .am-btn-success:active,\n.am-btn-success.am-disabled.am-active,\n.am-btn-success[disabled].am-active,\nfieldset[disabled] .am-btn-success.am-active {\n  background-color: #5eb95e;\n  border-color: #5eb95e;\n}\n.am-btn-group .am-btn-success,\n.am-btn-group-stacked .am-btn-success {\n  border-color: #4db14d;\n}\n.am-btn-secondary {\n  color: #fff;\n  background-color: #3bb4f2;\n  border-color: #3bb4f2;\n}\na.am-btn-secondary:visited {\n  color: #fff;\n}\n.am-btn-secondary:hover,\n.am-btn-secondary:focus,\n.am-btn-secondary:active,\n.am-btn-secondary.am-active,\n.am-active .am-btn-secondary.am-dropdown-toggle {\n  color: #fff;\n  border-color: #0f9ae0;\n}\n.am-btn-secondary:hover,\n.am-btn-secondary:focus {\n  background-color: #19a7f0;\n}\n.am-btn-secondary:active,\n.am-btn-secondary.am-active,\n.am-active .am-btn-secondary.am-dropdown-toggle {\n  background-image: none;\n  background-color: #0e93d7;\n}\n.am-btn-secondary.am-disabled,\n.am-btn-secondary[disabled],\nfieldset[disabled] .am-btn-secondary,\n.am-btn-secondary.am-disabled:hover,\n.am-btn-secondary[disabled]:hover,\nfieldset[disabled] .am-btn-secondary:hover,\n.am-btn-secondary.am-disabled:focus,\n.am-btn-secondary[disabled]:focus,\nfieldset[disabled] .am-btn-secondary:focus,\n.am-btn-secondary.am-disabled:active,\n.am-btn-secondary[disabled]:active,\nfieldset[disabled] .am-btn-secondary:active,\n.am-btn-secondary.am-disabled.am-active,\n.am-btn-secondary[disabled].am-active,\nfieldset[disabled] .am-btn-secondary.am-active {\n  background-color: #3bb4f2;\n  border-color: #3bb4f2;\n}\n.am-btn-group .am-btn-secondary,\n.am-btn-group-stacked .am-btn-secondary {\n  border-color: #23abf0;\n}\n/* Style links like a button */\n.am-btn-link {\n  color: #0e90d2;\n  font-weight: normal;\n  cursor: pointer;\n  border-radius: 0;\n}\n.am-btn-link,\n.am-btn-link:active,\n.am-btn-link[disabled],\nfieldset[disabled] .am-btn-link {\n  background-color: transparent;\n  -webkit-box-shadow: none;\n          box-shadow: none;\n}\n.am-btn-link,\n.am-btn-link:hover,\n.am-btn-link:focus,\n.am-btn-link:active {\n  border-color: transparent;\n}\n.am-btn-link:hover,\n.am-btn-link:focus {\n  color: #095f8a;\n  text-decoration: underline;\n  background-color: transparent;\n}\n.am-btn-link[disabled]:hover,\nfieldset[disabled] .am-btn-link:hover,\n.am-btn-link[disabled]:focus,\nfieldset[disabled] .am-btn-link:focus {\n  color: #999999;\n  text-decoration: none;\n}\n/* button size */\n.am-btn-xs {\n  font-size: 1.2rem;\n}\n.am-btn-sm {\n  font-size: 1.4rem;\n}\n.am-btn-lg {\n  font-size: 1.8rem;\n}\n.am-btn-xl {\n  font-size: 2rem;\n}\n/* Block button  */\n.am-btn-block {\n  display: block;\n  width: 100%;\n  padding-left: 0;\n  padding-right: 0;\n}\n/* Multiple block buttons vertically space */\n.am-btn-block + .am-btn-block {\n  margin-top: 5px;\n}\n/* Specificity overrides */\ninput[type=\"submit\"].am-btn-block,\ninput[type=\"reset\"].am-btn-block,\ninput[type=\"button\"].am-btn-block {\n  width: 100%;\n}\n/* Button with loading spinner */\n.am-btn.am-btn-loading .am-icon-spin {\n  margin-right: 5px;\n}\n/* ==========================================================================\n   Component: Table\n ============================================================================ */\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  empty-cells: show;\n}\ntable code {\n  white-space: normal;\n}\nth {\n  text-align: left;\n}\n.am-table {\n  width: 100%;\n  margin-bottom: 1.6rem;\n  border-spacing: 0;\n  border-collapse: separate;\n}\n.am-table > thead > tr > th,\n.am-table > tbody > tr > th,\n.am-table > tfoot > tr > th,\n.am-table > thead > tr > td,\n.am-table > tbody > tr > td,\n.am-table > tfoot > tr > td {\n  padding: 0.7rem;\n  line-height: 1.6;\n  vertical-align: top;\n  border-top: 1px solid #ddd;\n}\n.am-table > thead > tr > th {\n  vertical-align: bottom;\n  border-bottom: 1px solid #ddd;\n}\n.am-table > caption + thead > tr:first-child > th,\n.am-table > colgroup + thead > tr:first-child > th,\n.am-table > thead:first-child > tr:first-child > th,\n.am-table > caption + thead > tr:first-child > td,\n.am-table > colgroup + thead > tr:first-child > td,\n.am-table > thead:first-child > tr:first-child > td {\n  border-top: 0;\n}\n.am-table > tbody + tbody tr:first-child td {\n  border-top: 2px solid #ddd;\n}\n/* Bordered version */\n.am-table-bordered {\n  border: 1px solid #ddd;\n  border-left: none;\n}\n.am-table-bordered > thead > tr > th,\n.am-table-bordered > tbody > tr > th,\n.am-table-bordered > tfoot > tr > th,\n.am-table-bordered > thead > tr > td,\n.am-table-bordered > tbody > tr > td,\n.am-table-bordered > tfoot > tr > td {\n  border-left: 1px solid #ddd;\n  /*&:first-child {\n          border-left: none;\n        }*/\n}\n.am-table-bordered > tbody > tr:first-child > th,\n.am-table-bordered > tbody > tr:first-child > td {\n  border-top: none;\n}\n.am-table-bordered > thead + tbody > tr:first-child > th,\n.am-table-bordered > thead + tbody > tr:first-child > td {\n  border-top: 1px solid #ddd;\n}\n/* Border-radius version */\n.am-table-radius {\n  border: 1px solid #ddd;\n  border-radius: 2px;\n}\n.am-table-radius > thead > tr:first-child > th:first-child,\n.am-table-radius > thead > tr:first-child > td:first-child {\n  border-top-left-radius: 2px;\n  border-left: none;\n}\n.am-table-radius > thead > tr:first-child > th:last-child,\n.am-table-radius > thead > tr:first-child > td:last-child {\n  border-top-right-radius: 2px;\n  border-right: none;\n}\n.am-table-radius > tbody > tr > th:first-child,\n.am-table-radius > tbody > tr > td:first-child {\n  border-left: none;\n}\n.am-table-radius > tbody > tr > th:last-child,\n.am-table-radius > tbody > tr > td:last-child {\n  border-right: none;\n}\n.am-table-radius > tbody > tr:last-child > th,\n.am-table-radius > tbody > tr:last-child > td {\n  border-bottom: none;\n}\n.am-table-radius > tbody > tr:last-child > th:first-child,\n.am-table-radius > tbody > tr:last-child > td:first-child {\n  border-bottom-left-radius: 2px;\n}\n.am-table-radius > tbody > tr:last-child > th:last-child,\n.am-table-radius > tbody > tr:last-child > td:last-child {\n  border-bottom-right-radius: 2px;\n}\n/* Zebra-striping */\n.am-table-striped > tbody > tr:nth-child(odd) > td,\n.am-table-striped > tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n/* Hover effect */\n.am-table-hover > tbody > tr:hover > td,\n.am-table-hover > tbody > tr:hover > th {\n  background-color: #e9e9e9;\n}\n.am-table-compact > thead > tr > th,\n.am-table-compact > tbody > tr > th,\n.am-table-compact > tfoot > tr > th,\n.am-table-compact > thead > tr > td,\n.am-table-compact > tbody > tr > td,\n.am-table-compact > tfoot > tr > td {\n  padding: 0.4rem;\n}\n.am-table-centered > thead > tr > th,\n.am-table-centered > tbody > tr > th,\n.am-table-centered > tfoot > tr > th,\n.am-table-centered > thead > tr > td,\n.am-table-centered > tbody > tr > td,\n.am-table-centered > tfoot > tr > td {\n  text-align: center;\n}\n.am-table > thead > tr > td.am-active,\n.am-table > tbody > tr > td.am-active,\n.am-table > tfoot > tr > td.am-active,\n.am-table > thead > tr > th.am-active,\n.am-table > tbody > tr > th.am-active,\n.am-table > tfoot > tr > th.am-active,\n.am-table > thead > tr.am-active > td,\n.am-table > tbody > tr.am-active > td,\n.am-table > tfoot > tr.am-active > td,\n.am-table > thead > tr.am-active > th,\n.am-table > tbody > tr.am-active > th,\n.am-table > tfoot > tr.am-active > th {\n  background-color: #ffd;\n}\n.am-table > thead > tr > td.am-disabled,\n.am-table > tbody > tr > td.am-disabled,\n.am-table > tfoot > tr > td.am-disabled,\n.am-table > thead > tr > th.am-disabled,\n.am-table > tbody > tr > th.am-disabled,\n.am-table > tfoot > tr > th.am-disabled,\n.am-table > thead > tr.am-disabled > td,\n.am-table > tbody > tr.am-disabled > td,\n.am-table > tfoot > tr.am-disabled > td,\n.am-table > thead > tr.am-disabled > th,\n.am-table > tbody > tr.am-disabled > th,\n.am-table > tfoot > tr.am-disabled > th {\n  color: #999999;\n}\n.am-table > thead > tr > td.am-primary,\n.am-table > tbody > tr > td.am-primary,\n.am-table > tfoot > tr > td.am-primary,\n.am-table > thead > tr > th.am-primary,\n.am-table > tbody > tr > th.am-primary,\n.am-table > tfoot > tr > th.am-primary,\n.am-table > thead > tr.am-primary > td,\n.am-table > tbody > tr.am-primary > td,\n.am-table > tfoot > tr.am-primary > td,\n.am-table > thead > tr.am-primary > th,\n.am-table > tbody > tr.am-primary > th,\n.am-table > tfoot > tr.am-primary > th {\n  color: #0b76ac;\n  background-color: rgba(14, 144, 210, 0.115);\n}\n.am-table > thead > tr > td.am-success,\n.am-table > tbody > tr > td.am-success,\n.am-table > tfoot > tr > td.am-success,\n.am-table > thead > tr > th.am-success,\n.am-table > tbody > tr > th.am-success,\n.am-table > tfoot > tr > th.am-success,\n.am-table > thead > tr.am-success > td,\n.am-table > tbody > tr.am-success > td,\n.am-table > tfoot > tr.am-success > td,\n.am-table > thead > tr.am-success > th,\n.am-table > tbody > tr.am-success > th,\n.am-table > tfoot > tr.am-success > th {\n  color: #5eb95e;\n  background-color: rgba(94, 185, 94, 0.115);\n}\n.am-table > thead > tr > td.am-warning,\n.am-table > tbody > tr > td.am-warning,\n.am-table > tfoot > tr > td.am-warning,\n.am-table > thead > tr > th.am-warning,\n.am-table > tbody > tr > th.am-warning,\n.am-table > tfoot > tr > th.am-warning,\n.am-table > thead > tr.am-warning > td,\n.am-table > tbody > tr.am-warning > td,\n.am-table > tfoot > tr.am-warning > td,\n.am-table > thead > tr.am-warning > th,\n.am-table > tbody > tr.am-warning > th,\n.am-table > tfoot > tr.am-warning > th {\n  color: #F37B1D;\n  background-color: rgba(243, 123, 29, 0.115);\n}\n.am-table > thead > tr > td.am-danger,\n.am-table > tbody > tr > td.am-danger,\n.am-table > tfoot > tr > td.am-danger,\n.am-table > thead > tr > th.am-danger,\n.am-table > tbody > tr > th.am-danger,\n.am-table > tfoot > tr > th.am-danger,\n.am-table > thead > tr.am-danger > td,\n.am-table > tbody > tr.am-danger > td,\n.am-table > tfoot > tr.am-danger > td,\n.am-table > thead > tr.am-danger > th,\n.am-table > tbody > tr.am-danger > th,\n.am-table > tfoot > tr.am-danger > th {\n  color: #dd514c;\n  background-color: rgba(221, 81, 76, 0.115);\n}\n/* ==========================================================================\n   Component: Form\n ============================================================================ */\n/* Normalize */\nfieldset {\n  border: none;\n}\nlegend {\n  display: block;\n  width: 100%;\n  margin-bottom: 2rem;\n  font-size: 2rem;\n  line-height: inherit;\n  color: #333333;\n  border-bottom: 1px solid #e5e5e5;\n  padding-bottom: 0.5rem;\n}\nlabel {\n  display: inline-block;\n  margin-bottom: 5px;\n  font-weight: bold;\n}\ninput[type=\"search\"] {\n  -webkit-box-sizing: border-box;\n          box-sizing: border-box;\n}\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  /* IE8-9 */\n  line-height: normal;\n}\ninput[type=\"file\"] {\n  display: block;\n}\nselect[multiple],\nselect[size] {\n  height: auto;\n}\nselect optgroup {\n  font-size: inherit;\n  font-style: inherit;\n  font-family: inherit;\n}\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted;\n  outline: 1px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\ninput[type=\"number\"]::-webkit-outer-spin-button,\ninput[type=\"number\"]::-webkit-inner-spin-button {\n  height: auto;\n}\noutput {\n  display: block;\n  padding-top: 1.6rem;\n  font-size: 1.6rem;\n  line-height: 1.6;\n  color: #555555;\n  vertical-align: middle;\n}\n/* Common form controls */\n.am-form select,\n.am-form textarea,\n.am-form input[type=\"text\"],\n.am-form input[type=\"password\"],\n.am-form input[type=\"datetime\"],\n.am-form input[type=\"datetime-local\"],\n.am-form input[type=\"date\"],\n.am-form input[type=\"month\"],\n.am-form input[type=\"time\"],\n.am-form input[type=\"week\"],\n.am-form input[type=\"number\"],\n.am-form input[type=\"email\"],\n.am-form input[type=\"url\"],\n.am-form input[type=\"search\"],\n.am-form input[type=\"tel\"],\n.am-form input[type=\"color\"],\n.am-form-field {\n  display: block;\n  width: 100%;\n  padding: 0.5em;\n  font-size: 1.6rem;\n  line-height: 1.2;\n  color: #555555;\n  vertical-align: middle;\n  background-color: #fff;\n  background-image: none;\n  border: 1px solid #ccc;\n  border-radius: 2px;\n  -webkit-appearance: none;\n  -webkit-transition: border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;\n  transition: border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;\n  transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n  transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;\n}\n.am-form select.am-square,\n.am-form textarea.am-square,\n.am-form input[type=\"text\"].am-square,\n.am-form input[type=\"password\"].am-square,\n.am-form input[type=\"datetime\"].am-square,\n.am-form input[type=\"datetime-local\"].am-square,\n.am-form input[type=\"date\"].am-square,\n.am-form input[type=\"month\"].am-square,\n.am-form input[type=\"time\"].am-square,\n.am-form input[type=\"week\"].am-square,\n.am-form input[type=\"number\"].am-square,\n.am-form input[type=\"email\"].am-square,\n.am-form input[type=\"url\"].am-square,\n.am-form input[type=\"search\"].am-square,\n.am-form input[type=\"tel\"].am-square,\n.am-form input[type=\"color\"].am-square,\n.am-form-field.am-square {\n  border-radius: 0;\n}\n.am-form select:focus,\n.am-form textarea:focus,\n.am-form input[type=\"text\"]:focus,\n.am-form input[type=\"password\"]:focus,\n.am-form input[type=\"datetime\"]:focus,\n.am-form input[type=\"datetime-local\"]:focus,\n.am-form input[type=\"date\"]:focus,\n.am-form input[type=\"month\"]:focus,\n.am-form input[type=\"time\"]:focus,\n.am-form input[type=\"week\"]:focus,\n.am-form input[type=\"number\"]:focus,\n.am-form input[type=\"email\"]:focus,\n.am-form input[type=\"url\"]:focus,\n.am-form input[type=\"search\"]:focus,\n.am-form input[type=\"tel\"]:focus,\n.am-form input[type=\"color\"]:focus,\n.am-form-field:focus {\n  outline: 0;\n}\n.am-form select:focus,\n.am-form textarea:focus,\n.am-form input[type=\"text\"]:focus,\n.am-form input[type=\"password\"]:focus,\n.am-form input[type=\"datetime\"]:focus,\n.am-form input[type=\"datetime-local\"]:focus,\n.am-form input[type=\"date\"]:focus,\n.am-form input[type=\"month\"]:focus,\n.am-form input[type=\"time\"]:focus,\n.am-form input[type=\"week\"]:focus,\n.am-form input[type=\"number\"]:focus,\n.am-form input[type=\"email\"]:focus,\n.am-form input[type=\"url\"]:focus,\n.am-form input[type=\"search\"]:focus,\n.am-form input[type=\"tel\"]:focus,\n.am-form input[type=\"color\"]:focus,\n.am-form-field:focus {\n  background-color: #fefffe;\n  border-color: #3bb4f2;\n  outline: 0;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 5px rgba(59, 180, 242, 0.3);\n          box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 5px rgba(59, 180, 242, 0.3);\n}\n.am-form select::-webkit-input-placeholder,\n.am-form textarea::-webkit-input-placeholder,\n.am-form input[type=\"text\"]::-webkit-input-placeholder,\n.am-form input[type=\"password\"]::-webkit-input-placeholder,\n.am-form input[type=\"datetime\"]::-webkit-input-placeholder,\n.am-form input[type=\"datetime-local\"]::-webkit-input-placeholder,\n.am-form input[type=\"date\"]::-webkit-input-placeholder,\n.am-form input[type=\"month\"]::-webkit-input-placeholder,\n.am-form input[type=\"time\"]::-webkit-input-placeholder,\n.am-form input[type=\"week\"]::-webkit-input-placeholder,\n.am-form input[type=\"number\"]::-webkit-input-placeholder,\n.am-form input[type=\"email\"]::-webkit-input-placeholder,\n.am-form input[type=\"url\"]::-webkit-input-placeholder,\n.am-form input[type=\"search\"]::-webkit-input-placeholder,\n.am-form input[type=\"tel\"]::-webkit-input-placeholder,\n.am-form input[type=\"color\"]::-webkit-input-placeholder,\n.am-form-field::-webkit-input-placeholder {\n  color: #999999;\n}\n.am-form select::-moz-placeholder,\n.am-form textarea::-moz-placeholder,\n.am-form input[type=\"text\"]::-moz-placeholder,\n.am-form input[type=\"password\"]::-moz-placeholder,\n.am-form input[type=\"datetime\"]::-moz-placeholder,\n.am-form input[type=\"datetime-local\"]::-moz-placeholder,\n.am-form input[type=\"date\"]::-moz-placeholder,\n.am-form input[type=\"month\"]::-moz-placeholder,\n.am-form input[type=\"time\"]::-moz-placeholder,\n.am-form input[type=\"week\"]::-moz-placeholder,\n.am-form input[type=\"number\"]::-moz-placeholder,\n.am-form input[type=\"email\"]::-moz-placeholder,\n.am-form input[type=\"url\"]::-moz-placeholder,\n.am-form input[type=\"search\"]::-moz-placeholder,\n.am-form input[type=\"tel\"]::-moz-placeholder,\n.am-form input[type=\"color\"]::-moz-placeholder,\n.am-form-field::-moz-placeholder {\n  color: #999999;\n}\n.am-form select:-ms-input-placeholder,\n.am-form textarea:-ms-input-placeholder,\n.am-form input[type=\"text\"]:-ms-input-placeholder,\n.am-form input[type=\"password\"]:-ms-input-placeholder,\n.am-form input[type=\"datetime\"]:-ms-input-placeholder,\n.am-form input[type=\"datetime-local\"]:-ms-input-placeholder,\n.am-form input[type=\"date\"]:-ms-input-placeholder,\n.am-form input[type=\"month\"]:-ms-input-placeholder,\n.am-form input[type=\"time\"]:-ms-input-placeholder,\n.am-form input[type=\"week\"]:-ms-input-placeholder,\n.am-form input[type=\"number\"]:-ms-input-placeholder,\n.am-form input[type=\"email\"]:-ms-input-placeholder,\n.am-form input[type=\"url\"]:-ms-input-placeholder,\n.am-form input[type=\"search\"]:-ms-input-placeholder,\n.am-form input[type=\"tel\"]:-ms-input-placeholder,\n.am-form input[type=\"color\"]:-ms-input-placeholder,\n.am-form-field:-ms-input-placeholder {\n  color: #999999;\n}\n.am-form select::placeholder,\n.am-form textarea::placeholder,\n.am-form input[type=\"text\"]::placeholder,\n.am-form input[type=\"password\"]::placeholder,\n.am-form input[type=\"datetime\"]::placeholder,\n.am-form input[type=\"datetime-local\"]::placeholder,\n.am-form input[type=\"date\"]::placeholder,\n.am-form input[type=\"month\"]::placeholder,\n.am-form input[type=\"time\"]::placeholder,\n.am-form input[type=\"week\"]::placeholder,\n.am-form input[type=\"number\"]::placeholder,\n.am-form input[type=\"email\"]::placeholder,\n.am-form input[type=\"url\"]::placeholder,\n.am-form input[type=\"search\"]::placeholder,\n.am-form input[type=\"tel\"]::placeholder,\n.am-form input[type=\"color\"]::placeholder,\n.am-form-field::placeholder {\n  color: #999999;\n}\n.am-form select::-moz-placeholder,\n.am-form textarea::-moz-placeholder,\n.am-form input[type=\"text\"]::-moz-placeholder,\n.am-form input[type=\"password\"]::-moz-placeholder,\n.am-form input[type=\"datetime\"]::-moz-placeholder,\n.am-form input[type=\"datetime-local\"]::-moz-placeholder,\n.am-form input[type=\"date\"]::-moz-placeholder,\n.am-form input[type=\"month\"]::-moz-placeholder,\n.am-form input[type=\"time\"]::-moz-placeholder,\n.am-form input[type=\"week\"]::-moz-placeholder,\n.am-form input[type=\"number\"]::-moz-placeholder,\n.am-form input[type=\"email\"]::-moz-placeholder,\n.am-form input[type=\"url\"]::-moz-placeholder,\n.am-form input[type=\"search\"]::-moz-placeholder,\n.am-form input[type=\"tel\"]::-moz-placeholder,\n.am-form input[type=\"color\"]::-moz-placeholder,\n.am-form-field::-moz-placeholder {\n  opacity: 1;\n}\n.am-form select[disabled],\n.am-form textarea[disabled],\n.am-form input[type=\"text\"][disabled],\n.am-form input[type=\"password\"][disabled],\n.am-form input[type=\"datetime\"][disabled],\n.am-form input[type=\"datetime-local\"][disabled],\n.am-form input[type=\"date\"][disabled],\n.am-form input[type=\"month\"][disabled],\n.am-form input[type=\"time\"][disabled],\n.am-form input[type=\"week\"][disabled],\n.am-form input[type=\"number\"][disabled],\n.am-form input[type=\"email\"][disabled],\n.am-form input[type=\"url\"][disabled],\n.am-form input[type=\"search\"][disabled],\n.am-form input[type=\"tel\"][disabled],\n.am-form input[type=\"color\"][disabled],\n.am-form-field[disabled],\n.am-form select[readonly],\n.am-form textarea[readonly],\n.am-form input[type=\"text\"][readonly],\n.am-form input[type=\"password\"][readonly],\n.am-form input[type=\"datetime\"][readonly],\n.am-form input[type=\"datetime-local\"][readonly],\n.am-form input[type=\"date\"][readonly],\n.am-form input[type=\"month\"][readonly],\n.am-form input[type=\"time\"][readonly],\n.am-form input[type=\"week\"][readonly],\n.am-form input[type=\"number\"][readonly],\n.am-form input[type=\"email\"][readonly],\n.am-form input[type=\"url\"][readonly],\n.am-form input[type=\"search\"][readonly],\n.am-form input[type=\"tel\"][readonly],\n.am-form input[type=\"color\"][readonly],\n.am-form-field[readonly],\nfieldset[disabled] .am-form select,\nfieldset[disabled] .am-form textarea,\nfieldset[disabled] .am-form input[type=\"text\"],\nfieldset[disabled] .am-form input[type=\"password\"],\nfieldset[disabled] .am-form input[type=\"datetime\"],\nfieldset[disabled] .am-form input[type=\"datetime-local\"],\nfieldset[disabled] .am-form input[type=\"date\"],\nfieldset[disabled] .am-form input[type=\"month\"],\nfieldset[disabled] .am-form input[type=\"time\"],\nfieldset[disabled] .am-form input[type=\"week\"],\nfieldset[disabled] .am-form input[type=\"number\"],\nfieldset[disabled] .am-form input[type=\"email\"],\nfieldset[disabled] .am-form input[type=\"url\"],\nfieldset[disabled] .am-form input[type=\"search\"],\nfieldset[disabled] .am-form input[type=\"tel\"],\nfieldset[disabled] .am-form input[type=\"color\"],\nfieldset[disabled] .am-form-field {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n.am-form select.am-radius,\n.am-form textarea.am-radius,\n.am-form input[type=\"text\"].am-radius,\n.am-form input[type=\"password\"].am-radius,\n.am-form input[type=\"datetime\"].am-radius,\n.am-form input[type=\"datetime-local\"].am-radius,\n.am-form input[type=\"date\"].am-radius,\n.am-form input[type=\"month\"].am-radius,\n.am-form input[type=\"time\"].am-radius,\n.am-form input[type=\"week\"].am-radius,\n.am-form input[type=\"number\"].am-radius,\n.am-form input[type=\"email\"].am-radius,\n.am-form input[type=\"url\"].am-radius,\n.am-form input[type=\"search\"].am-radius,\n.am-form input[type=\"tel\"].am-radius,\n.am-form input[type=\"color\"].am-radius,\n.am-form-field.am-radius {\n  border-radius: 2px;\n}\n.am-form select.am-round,\n.am-form textarea.am-round,\n.am-form input[type=\"text\"].am-round,\n.am-form input[type=\"password\"].am-round,\n.am-form input[type=\"datetime\"].am-round,\n.am-form input[type=\"datetime-local\"].am-round,\n.am-form input[type=\"date\"].am-round,\n.am-form input[type=\"month\"].am-round,\n.am-form input[type=\"time\"].am-round,\n.am-form input[type=\"week\"].am-round,\n.am-form input[type=\"number\"].am-round,\n.am-form input[type=\"email\"].am-round,\n.am-form input[type=\"url\"].am-round,\n.am-form input[type=\"search\"].am-round,\n.am-form input[type=\"tel\"].am-round,\n.am-form input[type=\"color\"].am-round,\n.am-form-field.am-round {\n  border-radius: 1000px;\n}\n.am-form textarea,\n.am-form select[multiple],\n.am-form select[size] {\n  height: auto;\n}\n.am-form select {\n  -webkit-appearance: none !important;\n  -moz-appearance: none !important;\n  -webkit-border-radius: 2px;\n  background: #fff url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgeD0iMTJweCIgeT0iMHB4IiB3aWR0aD0iMjRweCIgaGVpZ2h0PSIzcHgiIHZpZXdCb3g9IjAgMCA2IDMiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDYgMyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PHBvbHlnb24gcG9pbnRzPSI1Ljk5MiwwIDIuOTkyLDMgLTAuMDA4LDAgIi8+PC9zdmc+') no-repeat 100% center;\n}\n.am-form select[multiple=\"multiple\"] {\n  background-image: none;\n}\n/* help text */\n.am-form-help {\n  display: block;\n  margin-top: 5px;\n  margin-bottom: 10px;\n  color: #999999;\n  font-size: 1.3rem;\n}\n/* form group */\n.am-form-group {\n  margin-bottom: 1.5rem;\n}\n/* file field */\n.am-form-file {\n  position: relative;\n  overflow: hidden;\n}\n.am-form-file input[type=\"file\"] {\n  position: absolute;\n  left: 0;\n  top: 0;\n  z-index: 1;\n  width: 100%;\n  opacity: 0;\n  cursor: pointer;\n  font-size: 50rem;\n}\n/**\n * Checkboxes and radios\n * Indent the labels to position radios/checkboxes as hanging controls.\n*/\n.am-radio,\n.am-checkbox {\n  display: block;\n  min-height: 1.92rem;\n  margin-top: 10px;\n  margin-bottom: 10px;\n  padding-left: 20px;\n  vertical-align: middle;\n}\n.am-radio label,\n.am-checkbox label {\n  display: inline;\n  margin-bottom: 0;\n  font-weight: normal;\n  cursor: pointer;\n}\n.am-radio input[type=\"radio\"],\n.am-radio-inline input[type=\"radio\"],\n.am-checkbox input[type=\"checkbox\"],\n.am-checkbox-inline input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n  outline: none;\n}\n.am-radio + .am-radio,\n.am-checkbox + .am-checkbox {\n  margin-top: -5px;\n}\n/* Radios and checkboxes inline */\n.am-radio-inline,\n.am-checkbox-inline {\n  display: inline-block;\n  padding-left: 20px;\n  margin-bottom: 0;\n  vertical-align: middle;\n  font-weight: normal;\n  cursor: pointer;\n}\n.am-radio-inline + .am-radio-inline,\n.am-checkbox-inline + .am-checkbox-inline {\n  margin-top: 0;\n  margin-left: 10px;\n}\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\n.am-radio[disabled],\n.am-radio-inline[disabled],\n.am-checkbox[disabled],\n.am-checkbox-inline[disabled],\nfieldset[disabled] input[type=\"radio\"],\nfieldset[disabled] input[type=\"checkbox\"],\nfieldset[disabled] .am-radio,\nfieldset[disabled] .am-radio-inline,\nfieldset[disabled] .am-checkbox,\nfieldset[disabled] .am-checkbox-inline {\n  cursor: not-allowed;\n}\n/* Form field feedback states */\n.am-form-warning .am-form-help,\n.am-form-warning .am-form-label,\n.am-form-warning .am-radio,\n.am-form-warning .am-checkbox,\n.am-form-warning .am-radio-inline,\n.am-form-warning .am-checkbox-inline,\n.am-form-warning label {\n  color: #F37B1D;\n}\n.am-form-warning [class*=\"icon-\"] {\n  color: #F37B1D;\n}\n.am-form-warning .am-form-field {\n  border-color: #F37B1D !important;\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.am-form-warning .am-form-field:focus {\n  background-color: #fefffe;\n  border-color: #d2620b;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 5px #f8b47e !important;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 5px #f8b47e !important;\n}\n.am-form-error .am-form-help,\n.am-form-error .am-form-label,\n.am-form-error .am-radio,\n.am-form-error .am-checkbox,\n.am-form-error .am-radio-inline,\n.am-form-error .am-checkbox-inline,\n.am-form-error label {\n  color: #dd514c;\n}\n.am-form-error [class*=\"icon-\"] {\n  color: #dd514c;\n}\n.am-form-error .am-form-field,\n.am-field-error {\n  border-color: #dd514c !important;\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.am-form-error .am-form-field:focus,\n.am-field-error:focus {\n  background-color: #fefffe;\n  border-color: #cf2d27;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 5px #eda4a2 !important;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 5px #eda4a2 !important;\n}\n.am-form-success .am-form-help,\n.am-form-success .am-form-label,\n.am-form-success .am-radio,\n.am-form-success .am-checkbox,\n.am-form-success .am-radio-inline,\n.am-form-success .am-checkbox-inline,\n.am-form-success label {\n  color: #5eb95e;\n}\n.am-form-success [class*=\"icon-\"] {\n  color: #5eb95e;\n}\n.am-form-success .am-form-field,\n.am-field-valid {\n  border-color: #5eb95e !important;\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.am-form-success .am-form-field:focus,\n.am-field-valid:focus {\n  background-color: #fefffe;\n  border-color: #459f45;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 5px #a5d8a5 !important;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 5px #a5d8a5 !important;\n}\n/* Horizontal forms */\n.am-form-horizontal .am-form-label,\n.am-form-horizontal .am-radio,\n.am-form-horizontal .am-checkbox,\n.am-form-horizontal .am-radio-inline,\n.am-form-horizontal .am-checkbox-inline {\n  margin-top: 0;\n  margin-bottom: 0;\n  padding-top: 0.6em;\n}\n.am-form-horizontal .am-form-group:before,\n.am-form-horizontal .am-form-group:after {\n  content: \" \";\n  display: table;\n}\n.am-form-horizontal .am-form-group:after {\n  clear: both;\n}\n@media only screen and (min-width:641px) {\n  .am-form-horizontal .am-form-label {\n    text-align: right;\n  }\n}\n/* Inline form elements */\n@media only screen and (min-width:641px) {\n  .am-form-inline .am-form-group {\n    display: inline-block;\n    margin-bottom: 0;\n    vertical-align: middle;\n  }\n  .am-form-inline .am-form-field {\n    display: inline-block;\n    width: auto;\n    vertical-align: middle;\n  }\n  .am-form-inline .am-input-group {\n    display: inline-table;\n    vertical-align: middle;\n  }\n  .am-form-inline .am-input-group .am-input-group-label,\n  .am-form-inline .am-input-group .am-input-group-btn,\n  .am-form-inline .am-input-group .am-form-label {\n    width: auto;\n  }\n  .am-form-inline .am-input-group > .am-form-field {\n    width: 100%;\n  }\n  .am-form-inline .am-form-label {\n    margin-bottom: 0;\n    vertical-align: middle;\n  }\n  .am-form-inline .am-radio,\n  .am-form-inline .am-checkbox {\n    display: inline-block;\n    margin-top: 0;\n    margin-bottom: 0;\n    padding-left: 0;\n    vertical-align: middle;\n  }\n  .am-form-inline .am-radio input[type=\"radio\"],\n  .am-form-inline .am-checkbox input[type=\"checkbox\"] {\n    float: none;\n    margin-left: 0;\n  }\n}\n/* Form field size */\n.am-input-sm {\n  font-size: 1.4rem !important;\n}\n.am-input-lg {\n  font-size: 1.8rem !important;\n}\n.am-form-group-sm .am-checkbox,\n.am-form-group-sm .am-radio,\n.am-form-group-sm .am-form-label,\n.am-form-group-sm .am-form-field {\n  font-size: 1.4rem !important;\n}\n.am-form-group-lg .am-checkbox,\n.am-form-group-lg .am-radio,\n.am-form-group-lg .am-form-label,\n.am-form-group-lg .am-form-field {\n  font-size: 1.8rem !important;\n}\n.am-form-group-lg input[type=\"radio\"],\n.am-form-group-lg input[type=\"checkbox\"] {\n  margin-top: 7px;\n}\n/* Form field feedback states */\n.am-form-icon {\n  position: relative;\n}\n.am-form-icon .am-form-field {\n  padding-left: 1.75em !important;\n}\n.am-form-icon [class*='am-icon-'] {\n  position: absolute;\n  left: 0.5em;\n  top: 50%;\n  display: block;\n  margin-top: -0.5em;\n  line-height: 1;\n  z-index: 2;\n}\n.am-form-icon label ~ [class*='am-icon-'] {\n  top: 70%;\n}\n/* Feedback Icon */\n.am-form-feedback {\n  position: relative;\n}\n.am-form-feedback .am-form-field {\n  padding-left: 0.5em !important;\n  padding-right: 1.75em !important;\n}\n.am-form-feedback [class*='am-icon-'] {\n  right: 0.5em;\n  left: auto;\n}\n.am-form-horizontal .am-form-feedback [class*='am-icon-'] {\n  right: 1.6em;\n}\n/* Form set */\n.am-form-set {\n  margin-bottom: 1.5rem;\n  padding: 0;\n}\n.am-form-set > input {\n  position: relative;\n  top: -1px;\n  border-radius: 0 !important;\n}\n.am-form-set > input:focus {\n  z-index: 2;\n}\n.am-form-set > input:first-child {\n  top: 1px;\n  border-top-right-radius: 2px !important;\n  border-top-left-radius: 2px !important;\n}\n.am-form-set > input:last-child {\n  top: -2px;\n  border-bottom-right-radius: 2px !important;\n  border-bottom-left-radius: 2px !important;\n}\n/* ==========================================================================\n   Component: Image\n ============================================================================ */\n/* Image thumbnails */\n.am-img-thumbnail {\n  display: inline-block;\n  max-width: 100%;\n  height: auto;\n  padding: 2px;\n  line-height: 1.6;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  border-radius: 2px;\n  -webkit-transition: all 0.2s ease-in-out;\n  transition: all 0.2s ease-in-out;\n}\n.am-img-thumbnail.am-radius {\n  border-radius: 2px;\n}\n.am-img-responsive {\n  display: block;\n  max-width: 100%;\n  height: auto;\n}\n/* ==========================================================================\n   Component: Nav\n ============================================================================ */\n.am-nav {\n  margin-bottom: 0;\n  padding: 0;\n  list-style: none;\n}\n.am-nav:before,\n.am-nav:after {\n  content: \" \";\n  display: table;\n}\n.am-nav:after {\n  clear: both;\n}\n.am-nav > li {\n  position: relative;\n  display: block;\n}\n.am-nav > li + li {\n  margin-top: 5px;\n}\n.am-nav > li + .am-nav-header {\n  margin-top: 1em;\n}\n.am-nav > li > a {\n  position: relative;\n  display: block;\n  padding: 0.4em 1em;\n  border-radius: 2px;\n}\n.am-nav > li > a:hover,\n.am-nav > li > a:focus {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n.am-nav > li.am-active > a,\n.am-nav > li.am-active > a:hover,\n.am-nav > li.am-active > a:focus {\n  color: #fff;\n  background-color: #0e90d2;\n  cursor: default;\n}\n.am-nav > li.am-disabled > a {\n  color: #999999;\n}\n.am-nav > li.am-disabled > a:hover,\n.am-nav > li.am-disabled > a:focus {\n  color: #999999;\n  text-decoration: none;\n  background-color: transparent;\n  cursor: not-allowed;\n}\n.am-nav-header {\n  padding: 0.4em 1em;\n  text-transform: uppercase;\n  font-weight: bold;\n  font-size: 100%;\n  color: #555555;\n}\n.am-nav-divider {\n  margin: 15px 1em !important;\n  border-top: 1px solid #ddd;\n  -webkit-box-shadow: 0 1px 0 #fff;\n          box-shadow: 0 1px 0 #fff;\n}\n.am-nav-pills > li {\n  float: left;\n}\n.am-nav-pills > li + li {\n  margin-left: 5px;\n  margin-top: 0;\n}\n.am-nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n.am-nav-tabs > li {\n  float: left;\n  margin-bottom: -1px;\n}\n.am-nav-tabs > li + li {\n  margin-top: 0;\n}\n.am-nav-tabs > li > a {\n  margin-right: 5px;\n  line-height: 1.6;\n  border: 1px solid transparent;\n  border-radius: 2px 2px 0 0;\n}\n.am-nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #ddd;\n}\n.am-nav-tabs > li.am-active > a,\n.am-nav-tabs > li.am-active > a:hover,\n.am-nav-tabs > li.am-active > a:focus {\n  color: #555555;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n  cursor: default;\n}\n.am-nav-tabs.am-nav-justify {\n  border-bottom: 0;\n  /*  > li > a {\n      margin-right: 0;\n      border-radius: @global-radius;\n    }\n\n    > .am-active > a {\n      &,\n      &:hover,\n      &:focus {\n        border: 1px solid @nav-tabs-justify-link-border-color;\n      }\n    }*/\n}\n.am-nav-tabs.am-nav-justify > li > a {\n  margin-right: 0;\n  border-bottom: 1px solid #ddd;\n  border-radius: 2px 2px 0 0;\n}\n.am-nav-tabs.am-nav-justify > .am-active > a,\n.am-nav-tabs.am-nav-justify > .am-active > a:hover,\n.am-nav-tabs.am-nav-justify > .am-active > a:focus {\n  border-bottom-color: #fff;\n}\n.am-nav-justify {\n  width: 100%;\n  display: table;\n}\n.am-nav-justify > li {\n  float: none;\n  display: table-cell;\n  width: 1%;\n}\n.am-nav-justify > li > a {\n  text-align: center;\n  margin-bottom: 0;\n}\n.lte9 .am-nav-justify > li {\n  display: table-cell;\n  width: 1%;\n}\n/* ==========================================================================\n   Component: Topbar\n ============================================================================ */\n.am-topbar {\n  position: relative;\n  min-height: 50px;\n  margin-bottom: 1.6rem;\n  background: #f8f8f8;\n  border-width: 0 0 1px;\n  border-style: solid;\n  border-color: #ddd;\n  color: #666;\n}\n.am-topbar:before,\n.am-topbar:after {\n  content: \" \";\n  display: table;\n}\n.am-topbar:after {\n  clear: both;\n}\n.am-topbar a {\n  color: #666;\n}\n.am-topbar-brand {\n  margin: 0;\n}\n@media only screen and (min-width:641px) {\n  .am-topbar-brand {\n    float: left;\n  }\n}\n.am-topbar-brand a:hover {\n  color: #4d4d4d;\n}\n.am-topbar-collapse {\n  width: 100%;\n  overflow-x: visible;\n  padding: 10px;\n  clear: both;\n  -webkit-overflow-scrolling: touch;\n}\n.am-topbar-collapse:before,\n.am-topbar-collapse:after {\n  content: \" \";\n  display: table;\n}\n.am-topbar-collapse:after {\n  clear: both;\n}\n.am-topbar-collapse.am-in {\n  overflow-y: auto;\n}\n@media only screen and (min-width:641px) {\n  .am-topbar-collapse {\n    margin-top: 0;\n    padding: 0;\n    width: auto;\n    clear: none;\n  }\n  .am-topbar-collapse.am-collapse {\n    display: block !important;\n    height: auto !important;\n    padding: 0;\n    overflow: visible !important;\n  }\n  .am-topbar-collapse.am-in {\n    overflow-y: visible;\n  }\n}\n.am-topbar-brand {\n  padding: 0 10px;\n  float: left;\n  font-size: 1.8rem;\n  height: 50px;\n  line-height: 50px;\n}\n.am-topbar-toggle {\n  position: relative;\n  float: right;\n  margin-right: 10px;\n}\n@media only screen and (min-width:641px) {\n  .am-topbar-toggle {\n    display: none;\n  }\n}\n@media only screen and (max-width: 640px) {\n  .am-topbar-nav {\n    margin-bottom: 8px;\n  }\n  .am-topbar-nav > li {\n    float: none;\n  }\n}\n@media only screen and (max-width: 640px) {\n  .am-topbar-nav > li + li {\n    margin-left: 0;\n    margin-top: 5px;\n  }\n}\n@media only screen and (min-width:641px) {\n  .am-topbar-nav {\n    float: left;\n  }\n  .am-topbar-nav > li > a {\n    position: relative;\n    line-height: 50px;\n    padding: 0 10px;\n  }\n  .am-topbar-nav > li > a:after {\n    position: absolute;\n    left: 50%;\n    margin-left: -7px;\n    bottom: -1px;\n    content: \"\";\n    display: inline-block;\n    width: 0;\n    height: 0;\n    vertical-align: middle;\n    border-bottom: 7px solid #f8f8f8;\n    border-right: 7px solid transparent;\n    border-left: 7px solid transparent;\n    border-top: 0 dotted;\n    -webkit-transform: rotate(360deg);\n        -ms-transform: rotate(360deg);\n            transform: rotate(360deg);\n    opacity: 0;\n    -webkit-transition: opacity .1s;\n    transition: opacity .1s;\n  }\n  .am-topbar-nav > li > a:hover:after {\n    opacity: 1;\n    border-bottom-color: #666;\n  }\n  .am-topbar-nav > li.am-dropdown > a:after {\n    display: none;\n  }\n  .am-topbar-nav > li.am-active > a,\n  .am-topbar-nav > li.am-active > a:hover,\n  .am-topbar-nav > li.am-active > a:focus {\n    border-radius: 0;\n    color: #0e90d2;\n    background: none;\n  }\n  .am-topbar-nav > li.am-active > a:after {\n    opacity: 1;\n    border-bottom-color: #0e90d2;\n  }\n}\n@media only screen and (max-width: 640px) {\n  .am-topbar-collapse .am-dropdown.am-active .am-dropdown-content {\n    float: none;\n    position: relative;\n    width: 100%;\n  }\n}\n@media only screen and (min-width:641px) {\n  .am-topbar-left {\n    float: left;\n  }\n  .am-topbar-right {\n    float: right;\n    margin-right: 10px;\n  }\n}\n@media only screen and (max-width: 640px) {\n  .am-topbar-form .am-form-group {\n    margin-bottom: 5px;\n  }\n}\n@media only screen and (min-width:641px) {\n  .am-topbar-form {\n    padding: 0 10px;\n    margin-top: 8px;\n  }\n  .am-topbar-form .am-form-group + .am-btn {\n    margin-left: 5px;\n  }\n}\n.am-topbar-btn {\n  margin-top: 8px;\n}\n@media only screen and (max-width: 640px) {\n  .am-topbar-collapse .am-topbar-btn,\n  .am-topbar-collapse .am-btn {\n    display: block;\n    width: 100%;\n  }\n}\n.am-topbar-inverse {\n  background-color: #0e90d2;\n  border-color: #0b6fa2;\n  color: #eeeeee;\n}\n.am-topbar-inverse a {\n  color: #eeeeee;\n}\n.am-topbar-inverse .am-topbar-brand a {\n  color: #fff;\n}\n.am-topbar-inverse .am-topbar-brand a:hover,\n.am-topbar-inverse .am-topbar-brand a:focus {\n  color: #fff;\n  background-color: transparent;\n}\n.am-topbar-inverse .am-topbar-nav > li > a {\n  color: #eeeeee;\n}\n.am-topbar-inverse .am-topbar-nav > li > a:hover,\n.am-topbar-inverse .am-topbar-nav > li > a:focus {\n  color: #fff;\n  background-color: rgba(0, 0, 0, 0.05);\n}\n.am-topbar-inverse .am-topbar-nav > li > a:hover:after,\n.am-topbar-inverse .am-topbar-nav > li > a:focus:after {\n  border-bottom-color: #0b6fa2;\n}\n.am-topbar-inverse .am-topbar-nav > li > a:after {\n  border-bottom-color: #0e90d2;\n}\n.am-topbar-inverse .am-topbar-nav > li.am-active > a,\n.am-topbar-inverse .am-topbar-nav > li.am-active > a:hover,\n.am-topbar-inverse .am-topbar-nav > li.am-active > a:focus {\n  color: #fff;\n  background-color: rgba(0, 0, 0, 0.1);\n}\n.am-topbar-inverse .am-topbar-nav > li.am-active > a:after,\n.am-topbar-inverse .am-topbar-nav > li.am-active > a:hover:after,\n.am-topbar-inverse .am-topbar-nav > li.am-active > a:focus:after {\n  border-bottom-color: #fff;\n}\n.am-topbar-inverse .am-topbar-nav > li .disabled > a,\n.am-topbar-inverse .am-topbar-nav > li .disabled > a:hover,\n.am-topbar-inverse .am-topbar-nav > li .disabled > a:focus {\n  color: #444;\n  background-color: transparent;\n}\n.am-topbar-fixed-top,\n.am-topbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1000;\n  -webkit-transform: translate3d(0, 0, 0);\n          transform: translate3d(0, 0, 0);\n}\n.am-topbar-fixed-top {\n  top: 0;\n}\n.am-topbar-fixed-bottom {\n  bottom: 0;\n  margin-bottom: 0;\n  border-width: 1px 0 0;\n}\n.am-with-topbar-fixed-top {\n  padding-top: 51px;\n}\n.am-with-topbar-fixed-bottom {\n  padding-bottom: 51px;\n}\n@media only screen and (max-width: 640px) {\n  .am-topbar-fixed-bottom .am-topbar-collapse {\n    position: absolute;\n    bottom: 100%;\n    margin-bottom: 1px;\n    background-color: #f8f8f8;\n  }\n  .am-topbar-fixed-bottom .am-topbar-collapse .am-dropdown-content:before,\n  .am-topbar-fixed-bottom .am-topbar-collapse .am-dropdown-content:after {\n    display: none;\n  }\n  .am-topbar-fixed-bottom.am-topbar-inverse .am-topbar-collapse {\n    background-color: #0e90d2;\n  }\n}\n/* ==========================================================================\n   Component: Breadcrumb\n ============================================================================ */\n.am-breadcrumb {\n  padding: .7em .5em;\n  margin-bottom: 2rem;\n  list-style: none;\n  background-color: transparent;\n  border-radius: 2px;\n  font-size: 85%;\n}\n.am-breadcrumb > li {\n  display: inline-block;\n}\n.am-breadcrumb > li [class*=\"am-icon-\"]:before {\n  color: #999999;\n  margin-right: 5px;\n}\n.am-breadcrumb > li + li:before {\n  content: \"»\\00a0\";\n  padding: 0 8px;\n  color: #ccc;\n}\n.am-breadcrumb > .am-active {\n  color: #999999;\n}\n.am-breadcrumb-slash > li + li:before {\n  content: \"/\\00a0\";\n}\n/* ==========================================================================\n   Component: Pagination\n ============================================================================ */\n.am-pagination {\n  padding-left: 0;\n  margin: 1.5rem 0;\n  list-style: none;\n  color: #999999;\n  text-align: left;\n}\n.am-pagination:before,\n.am-pagination:after {\n  content: \" \";\n  display: table;\n}\n.am-pagination:after {\n  clear: both;\n}\n.am-pagination > li {\n  display: inline-block;\n}\n.am-pagination > li > a,\n.am-pagination > li > span {\n  position: relative;\n  display: block;\n  padding: 0.5em 1em;\n  text-decoration: none;\n  line-height: 1.2;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  border-radius: 2px;\n  margin-bottom: 5px;\n  margin-right: 5px;\n}\n.am-pagination > li:last-child > a,\n.am-pagination > li:last-child > span {\n  margin-right: 0;\n}\n.am-pagination > li > a:hover,\n.am-pagination > li > span:hover,\n.am-pagination > li > a:focus,\n.am-pagination > li > span:focus {\n  background-color: #eeeeee;\n}\n.am-pagination > .am-active > a,\n.am-pagination > .am-active > span,\n.am-pagination > .am-active > a:hover,\n.am-pagination > .am-active > span:hover,\n.am-pagination > .am-active > a:focus,\n.am-pagination > .am-active > span:focus {\n  z-index: 2;\n  color: #fff;\n  background-color: #0e90d2;\n  border-color: #0e90d2;\n  cursor: default;\n}\n.am-pagination > .am-disabled > span,\n.am-pagination > .am-disabled > span:hover,\n.am-pagination > .am-disabled > span:focus,\n.am-pagination > .am-disabled > a,\n.am-pagination > .am-disabled > a:hover,\n.am-pagination > .am-disabled > a:focus {\n  color: #999999;\n  background-color: #fff;\n  border-color: #ddd;\n  cursor: not-allowed;\n  pointer-events: none;\n}\n.am-pagination .am-pagination-prev {\n  float: left;\n}\n.am-pagination .am-pagination-prev a {\n  border-radius: 2px;\n}\n.am-pagination .am-pagination-next {\n  float: right;\n}\n.am-pagination .am-pagination-next a {\n  border-radius: 2px;\n}\n.am-pagination-centered {\n  text-align: center;\n}\n.am-pagination-right {\n  text-align: right;\n}\n/* ==========================================================================\n   Component: Aniamtion\n ============================================================================ */\n[class*=\"am-animation-\"] {\n  -webkit-animation-duration: 0.5s;\n          animation-duration: 0.5s;\n  -webkit-animation-timing-function: ease-out;\n          animation-timing-function: ease-out;\n  -webkit-animation-fill-mode: both;\n          animation-fill-mode: both;\n}\n/* Hide animated element if scrollSpy is used */\n@media screen {\n  .cssanimations [data-am-scrollspy*=\"animation\"] {\n    opacity: 0;\n  }\n}\n/* Fade */\n.am-animation-fade {\n  -webkit-animation-name: am-fade;\n          animation-name: am-fade;\n  -webkit-animation-duration: 0.8s;\n          animation-duration: 0.8s;\n  -webkit-animation-timing-function: linear;\n          animation-timing-function: linear;\n}\n/* Scale */\n.am-animation-scale-up {\n  -webkit-animation-name: am-scale-up;\n          animation-name: am-scale-up;\n}\n.am-animation-scale-down {\n  -webkit-animation-name: am-scale-down;\n          animation-name: am-scale-down;\n}\n/* Slide */\n.am-animation-slide-top {\n  -webkit-animation-name: am-slide-top;\n          animation-name: am-slide-top;\n}\n.am-animation-slide-bottom {\n  -webkit-animation-name: am-slide-bottom;\n          animation-name: am-slide-bottom;\n}\n.am-animation-slide-left {\n  -webkit-animation-name: am-slide-left;\n          animation-name: am-slide-left;\n}\n.am-animation-slide-right {\n  -webkit-animation-name: am-slide-right;\n          animation-name: am-slide-right;\n}\n.am-animation-slide-top-fixed {\n  -webkit-animation-name: am-slide-top-fixed;\n          animation-name: am-slide-top-fixed;\n}\n/* Shake */\n.am-animation-shake {\n  -webkit-animation-name: am-shake;\n          animation-name: am-shake;\n}\n/* Spin */\n.am-animation-spin {\n  -webkit-animation: am-spin 2s infinite linear;\n          animation: am-spin 2s infinite linear;\n}\n/* Spring */\n.am-animation-left-spring {\n  -webkit-animation: am-left-spring 0.3s ease-in-out;\n          animation: am-left-spring 0.3s ease-in-out;\n}\n.am-animation-right-spring {\n  -webkit-animation: am-right-spring 0.3s ease-in-out;\n          animation: am-right-spring 0.3s ease-in-out;\n}\n.am-animation-reverse {\n  -webkit-animation-direction: reverse;\n          animation-direction: reverse;\n}\n.am-animation-paused {\n  -webkit-animation-play-state: paused !important;\n          animation-play-state: paused !important;\n}\n.am-animation-delay-1 {\n  -webkit-animation-delay: 1s;\n          animation-delay: 1s;\n}\n.am-animation-delay-2 {\n  -webkit-animation-delay: 2s;\n          animation-delay: 2s;\n}\n.am-animation-delay-3 {\n  -webkit-animation-delay: 3s;\n          animation-delay: 3s;\n}\n.am-animation-delay-4 {\n  -webkit-animation-delay: 4s;\n          animation-delay: 4s;\n}\n.am-animation-delay-5 {\n  -webkit-animation-delay: 5s;\n          animation-delay: 5s;\n}\n.am-animation-delay-6 {\n  -webkit-animation-delay: 6s;\n          animation-delay: 6s;\n}\n/* Keyframes\n ============================================================================ */\n/* Fade */\n@-webkit-keyframes am-fade {\n  0% {\n    opacity: 0;\n  }\n  100% {\n    opacity: 1;\n  }\n}\n@keyframes am-fade {\n  0% {\n    opacity: 0;\n  }\n  100% {\n    opacity: 1;\n  }\n}\n/* Scale up */\n@-webkit-keyframes am-scale-up {\n  0% {\n    opacity: 0;\n    -webkit-transform: scale(0.2);\n            transform: scale(0.2);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: scale(1);\n            transform: scale(1);\n  }\n}\n@keyframes am-scale-up {\n  0% {\n    opacity: 0;\n    -webkit-transform: scale(0.2);\n            transform: scale(0.2);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: scale(1);\n            transform: scale(1);\n  }\n}\n/* Scale down */\n@-webkit-keyframes am-scale-down {\n  0% {\n    opacity: 0;\n    -webkit-transform: scale(1.8);\n            transform: scale(1.8);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: scale(1);\n            transform: scale(1);\n  }\n}\n@keyframes am-scale-down {\n  0% {\n    opacity: 0;\n    -webkit-transform: scale(1.8);\n            transform: scale(1.8);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: scale(1);\n            transform: scale(1);\n  }\n}\n/* Slide top */\n@-webkit-keyframes am-slide-top {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(-100%);\n            transform: translateY(-100%);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n            transform: translateY(0);\n  }\n}\n@keyframes am-slide-top {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(-100%);\n            transform: translateY(-100%);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n            transform: translateY(0);\n  }\n}\n/* Slide bottom */\n@-webkit-keyframes am-slide-bottom {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(100%);\n            transform: translateY(100%);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n            transform: translateY(0);\n  }\n}\n@keyframes am-slide-bottom {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(100%);\n            transform: translateY(100%);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n            transform: translateY(0);\n  }\n}\n/* Slide left */\n@-webkit-keyframes am-slide-left {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateX(-100%);\n            transform: translateX(-100%);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n}\n@keyframes am-slide-left {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateX(-100%);\n            transform: translateX(-100%);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n}\n/* Slide right */\n@-webkit-keyframes am-slide-right {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateX(100%);\n            transform: translateX(100%);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n}\n@keyframes am-slide-right {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateX(100%);\n            transform: translateX(100%);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n}\n/* Shake */\n@-webkit-keyframes am-shake {\n  0%,\n  100% {\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n  10% {\n    -webkit-transform: translateX(-9px);\n            transform: translateX(-9px);\n  }\n  20% {\n    -webkit-transform: translateX(8px);\n            transform: translateX(8px);\n  }\n  30% {\n    -webkit-transform: translateX(-7px);\n            transform: translateX(-7px);\n  }\n  40% {\n    -webkit-transform: translateX(6px);\n            transform: translateX(6px);\n  }\n  50% {\n    -webkit-transform: translateX(-5px);\n            transform: translateX(-5px);\n  }\n  60% {\n    -webkit-transform: translateX(4px);\n            transform: translateX(4px);\n  }\n  70% {\n    -webkit-transform: translateX(-3px);\n            transform: translateX(-3px);\n  }\n  80% {\n    -webkit-transform: translateX(2px);\n            transform: translateX(2px);\n  }\n  90% {\n    -webkit-transform: translateX(-1px);\n            transform: translateX(-1px);\n  }\n}\n@keyframes am-shake {\n  0%,\n  100% {\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n  10% {\n    -webkit-transform: translateX(-9px);\n            transform: translateX(-9px);\n  }\n  20% {\n    -webkit-transform: translateX(8px);\n            transform: translateX(8px);\n  }\n  30% {\n    -webkit-transform: translateX(-7px);\n            transform: translateX(-7px);\n  }\n  40% {\n    -webkit-transform: translateX(6px);\n            transform: translateX(6px);\n  }\n  50% {\n    -webkit-transform: translateX(-5px);\n            transform: translateX(-5px);\n  }\n  60% {\n    -webkit-transform: translateX(4px);\n            transform: translateX(4px);\n  }\n  70% {\n    -webkit-transform: translateX(-3px);\n            transform: translateX(-3px);\n  }\n  80% {\n    -webkit-transform: translateX(2px);\n            transform: translateX(2px);\n  }\n  90% {\n    -webkit-transform: translateX(-1px);\n            transform: translateX(-1px);\n  }\n}\n/* Slide top fixed */\n@-webkit-keyframes am-slide-top-fixed {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(-10px);\n            transform: translateY(-10px);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n            transform: translateY(0);\n  }\n}\n@keyframes am-slide-top-fixed {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(-10px);\n            transform: translateY(-10px);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n            transform: translateY(0);\n  }\n}\n/* Slide bottom fixed */\n@-webkit-keyframes am-slide-bottom-fixed {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(10px);\n            transform: translateY(10px);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n            transform: translateY(0);\n  }\n}\n@keyframes am-slide-bottom-fixed {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(10px);\n            transform: translateY(10px);\n  }\n  100% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n            transform: translateY(0);\n  }\n}\n/* Spin */\n@-webkit-keyframes am-spin {\n  0% {\n    -webkit-transform: rotate(0deg);\n            transform: rotate(0deg);\n  }\n  100% {\n    -webkit-transform: rotate(359deg);\n            transform: rotate(359deg);\n  }\n}\n@keyframes am-spin {\n  0% {\n    -webkit-transform: rotate(0deg);\n            transform: rotate(0deg);\n  }\n  100% {\n    -webkit-transform: rotate(359deg);\n            transform: rotate(359deg);\n  }\n}\n/* Spring */\n@-webkit-keyframes am-right-spring {\n  0% {\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n  50% {\n    -webkit-transform: translateX(-20%);\n            transform: translateX(-20%);\n  }\n  100% {\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n}\n@keyframes am-right-spring {\n  0% {\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n  50% {\n    -webkit-transform: translateX(-20%);\n            transform: translateX(-20%);\n  }\n  100% {\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n}\n@-webkit-keyframes am-left-spring {\n  0% {\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n  50% {\n    -webkit-transform: translateX(20%);\n            transform: translateX(20%);\n  }\n  100% {\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n}\n@keyframes am-left-spring {\n  0% {\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n  50% {\n    -webkit-transform: translateX(20%);\n            transform: translateX(20%);\n  }\n  100% {\n    -webkit-transform: translateX(0);\n            transform: translateX(0);\n  }\n}\n/* ==========================================================================\n   Component: Article\n ============================================================================ */\n.am-article:before,\n.am-article:after {\n  content: \" \";\n  display: table;\n}\n.am-article:after {\n  clear: both;\n}\n.am-article > :last-child {\n  margin-bottom: 0;\n}\n.am-article + .am-article {\n  margin-top: 2.4rem;\n}\n/* Sub-object `.@{ns}article-title` */\n.am-article-title {\n  font-size: 2.8rem;\n  line-height: 1.15;\n  font-weight: normal;\n}\n.am-article-title a {\n  color: inherit;\n  text-decoration: none;\n}\n/* Sub-object `.@{ns}article-meta` */\n.am-article-meta {\n  font-size: 1.2rem;\n  line-height: 1.5;\n  color: #999999;\n}\n/* Sub-object `.@{ns}article-lead` */\n.am-article-lead {\n  color: #666;\n  font-size: 1.4rem;\n  line-height: 1.5;\n  border: 1px solid #dedede;\n  border-radius: 2px;\n  background: #f9f9f9;\n  padding: 10px;\n}\n/* Sub-object `.@{ns}article-divider` */\n.am-article-divider {\n  margin-bottom: 2.4rem;\n  border-color: #eeeeee;\n}\n* + .am-article-divider {\n  margin-top: 2.4rem;\n}\n/* Sub-object `.@{ns}article-bd` */\n.am-article-bd blockquote {\n  font-family: Georgia, \"Times New Roman\", Times, Kai, \"Kaiti SC\", KaiTi, BiauKai, \"FontAwesome\", serif;\n}\n.am-article-bd img {\n  display: block;\n  max-width: 100%;\n}\n/* ==========================================================================\n   Component: Badge\n ============================================================================ */\n.am-badge {\n  display: inline-block;\n  min-width: 10px;\n  padding: 0.25em 0.625em;\n  font-size: 1.2rem;\n  font-weight: bold;\n  color: #fff;\n  line-height: 1;\n  vertical-align: baseline;\n  white-space: nowrap;\n  text-align: center;\n  background-color: #999999;\n  border-radius: 0;\n}\n.am-badge:empty {\n  display: none;\n}\n.am-badge.am-square {\n  border-radius: 0;\n}\n.am-badge.am-radius {\n  border-radius: 2px;\n}\n.am-badge.am-round {\n  border-radius: 1000px;\n}\na.am-badge:hover,\na.am-badge:focus {\n  color: #fff;\n  text-decoration: none;\n  cursor: pointer;\n}\n.am-badge-primary {\n  background-color: #0e90d2;\n}\n.am-badge-secondary {\n  background-color: #3bb4f2;\n}\n.am-badge-success {\n  background-color: #5eb95e;\n}\n.am-badge-warning {\n  background-color: #F37B1D;\n}\n.am-badge-danger {\n  background-color: #dd514c;\n}\n/* ==========================================================================\n   Component: Comment\n ============================================================================ */\n.am-comment:before,\n.am-comment:after {\n  content: \" \";\n  display: table;\n}\n.am-comment:after {\n  clear: both;\n}\n.am-comment-avatar {\n  float: left;\n  width: 32px;\n  height: 32px;\n  border-radius: 50%;\n  border: 1px solid transparent;\n}\n@media only screen and (min-width:641px) {\n  .am-comment-avatar {\n    width: 48px;\n    height: 48px;\n  }\n}\n.am-comment-main {\n  position: relative;\n  margin-left: 42px;\n  border: 1px solid #dedede;\n  border-radius: 2px;\n}\n.am-comment-main:before,\n.am-comment-main:after {\n  position: absolute;\n  top: 10px;\n  left: -8px;\n  right: 100%;\n  width: 0;\n  height: 0;\n  display: block;\n  content: \" \";\n  border-color: transparent;\n  border-style: solid solid outset;\n  border-width: 8px 8px 8px 0;\n  pointer-events: none;\n}\n.am-comment-main:before {\n  border-right-color: #dedede;\n  z-index: 1;\n}\n.am-comment-main:after {\n  border-right-color: #f8f8f8;\n  margin-left: 1px;\n  z-index: 2;\n}\n@media only screen and (min-width:641px) {\n  .am-comment-main {\n    margin-left: 63px;\n  }\n}\n.am-comment-hd {\n  background: #f8f8f8;\n  border-bottom: 1px solid #eee;\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -ms-flexbox;\n  display: flex;\n}\n.am-comment-title {\n  margin: 0 0 8px 0;\n  font-size: 1.6rem;\n  line-height: 1.2;\n}\n.am-comment-meta {\n  -webkit-box-flex: 1;\n  -webkit-flex: 1;\n      -ms-flex: 1;\n          flex: 1;\n  padding: 10px 15px;\n  font-size: 13px;\n  color: #999999;\n  line-height: 1.2;\n  white-space: nowrap;\n  text-overflow: ellipsis;\n  overflow: hidden;\n}\n.am-comment-meta a {\n  color: #999999;\n}\n.am-comment-author {\n  font-weight: bold;\n  color: #999999;\n}\n.am-comment-bd {\n  padding: 15px;\n  overflow: hidden;\n}\n.am-comment-bd > :last-child {\n  margin-bottom: 0;\n}\n.am-comment-footer {\n  padding: 0 15px 5px;\n}\n.am-comment-footer .am-comment-actions a + a {\n  margin-left: 5px;\n}\n.am-comment-actions {\n  font-size: 13px;\n  color: #999999;\n}\n.am-comment-actions a {\n  display: inline-block;\n  padding: 10px 5px;\n  line-height: 1;\n  color: #999999;\n  opacity: .7;\n}\n.am-comment-actions a:hover {\n  color: #0e90d2;\n  opacity: 1;\n}\n.am-comment-hd .am-comment-actions {\n  padding-right: .5rem;\n}\n.am-comment-flip .am-comment-avatar {\n  float: right;\n}\n.am-comment-flip .am-comment-main {\n  margin-left: auto;\n  margin-right: 42px;\n}\n@media only screen and (min-width:641px) {\n  .am-comment-flip .am-comment-main {\n    margin-right: 63px;\n  }\n}\n.am-comment-flip .am-comment-main:before,\n.am-comment-flip .am-comment-main:after {\n  left: auto;\n  right: -8px;\n  border-width: 8px 0 8px 8px;\n}\n.am-comment-flip .am-comment-main:before {\n  border-left-color: #dedede;\n}\n.am-comment-flip .am-comment-main:after {\n  border-left-color: #f8f8f8;\n  margin-right: 1px;\n  margin-left: auto;\n}\n.am-comment-primary .am-comment-avatar {\n  border-color: #0e90d2;\n}\n.am-comment-primary .am-comment-main {\n  border-color: #0e90d2;\n}\n.am-comment-primary .am-comment-main:before {\n  border-right-color: #0e90d2;\n}\n.am-comment-primary.am-comment-flip .am-comment-main:before {\n  border-left-color: #0e90d2;\n  border-right-color: transparent;\n}\n.am-comment-primary.am-comment-flip .am-comment-main:after {\n  border-left-color: #f8f8f8;\n}\n.am-comment-secondary .am-comment-avatar,\n.am-comment-highlight .am-comment-avatar {\n  border-color: #3bb4f2;\n}\n.am-comment-secondary .am-comment-main,\n.am-comment-highlight .am-comment-main {\n  border-color: #3bb4f2;\n}\n.am-comment-secondary .am-comment-main:before,\n.am-comment-highlight .am-comment-main:before {\n  border-right-color: #3bb4f2;\n}\n.am-comment-secondary.am-comment-flip .am-comment-main:before,\n.am-comment-highlight.am-comment-flip .am-comment-main:before {\n  border-left-color: #3bb4f2;\n  border-right-color: transparent;\n}\n.am-comment-secondary.am-comment-flip .am-comment-main:after,\n.am-comment-highlight.am-comment-flip .am-comment-main:after {\n  border-left-color: #f8f8f8;\n}\n.am-comment-success .am-comment-avatar {\n  border-color: #5eb95e;\n}\n.am-comment-success .am-comment-main {\n  border-color: #5eb95e;\n}\n.am-comment-success .am-comment-main:before {\n  border-right-color: #5eb95e;\n}\n.am-comment-success.am-comment-flip .am-comment-main:before {\n  border-left-color: #5eb95e;\n  border-right-color: transparent;\n}\n.am-comment-success.am-comment-flip .am-comment-main:after {\n  border-left-color: #f8f8f8;\n}\n.am-comment-warning .am-comment-avatar {\n  border-color: #F37B1D;\n}\n.am-comment-warning .am-comment-main {\n  border-color: #F37B1D;\n}\n.am-comment-warning .am-comment-main:before {\n  border-right-color: #F37B1D;\n}\n.am-comment-warning.am-comment-flip .am-comment-main:before {\n  border-left-color: #F37B1D;\n  border-right-color: transparent;\n}\n.am-comment-warning.am-comment-flip .am-comment-main:after {\n  border-left-color: #f8f8f8;\n}\n.am-comment-danger .am-comment-avatar {\n  border-color: #dd514c;\n}\n.am-comment-danger .am-comment-main {\n  border-color: #dd514c;\n}\n.am-comment-danger .am-comment-main:before {\n  border-right-color: #dd514c;\n}\n.am-comment-danger.am-comment-flip .am-comment-main:before {\n  border-left-color: #dd514c;\n  border-right-color: transparent;\n}\n.am-comment-danger.am-comment-flip .am-comment-main:after {\n  border-left-color: #f8f8f8;\n}\n.am-comments-list {\n  padding: 0;\n  list-style: none;\n}\n.am-comments-list .am-comment {\n  margin: 1.6rem 0 0 0;\n  list-style: none;\n}\n@media only screen and (min-width:641px) {\n  .am-comments-list-flip .am-comment-main {\n    margin-right: 64px;\n  }\n  .am-comments-list-flip .am-comment-flip .am-comment-main {\n    margin-left: 64px;\n  }\n}\n/* ==========================================================================\n   Component: Button Group\n ============================================================================ */\n.am-btn-group,\n.am-btn-group-stacked {\n  position: relative;\n  display: inline-block;\n  vertical-align: middle;\n}\n.am-btn-group > .am-btn,\n.am-btn-group-stacked > .am-btn {\n  position: relative;\n  float: left;\n}\n.am-btn-group > .am-btn:hover,\n.am-btn-group-stacked > .am-btn:hover,\n.am-btn-group > .am-btn:focus,\n.am-btn-group-stacked > .am-btn:focus,\n.am-btn-group > .am-btn:active,\n.am-btn-group-stacked > .am-btn:active,\n.am-btn-group > .am-btn.active,\n.am-btn-group-stacked > .am-btn.active {\n  z-index: 2;\n}\n.am-btn-group > .am-btn:focus,\n.am-btn-group-stacked > .am-btn:focus {\n  outline: 0;\n}\n.am-btn-group .am-btn + .am-btn,\n.am-btn-group .am-btn + .am-btn-group,\n.am-btn-group .am-btn-group + .am-btn,\n.am-btn-group .am-btn-group + .am-btn-group {\n  margin-left: -1px;\n}\n.am-btn-toolbar {\n  margin-left: -5px;\n}\n.am-btn-toolbar:before,\n.am-btn-toolbar:after {\n  content: \" \";\n  display: table;\n}\n.am-btn-toolbar:after {\n  clear: both;\n}\n.am-btn-toolbar .am-btn-group,\n.am-btn-toolbar .am-input-group {\n  float: left;\n}\n.am-btn-toolbar > .am-btn,\n.am-btn-toolbar > .am-btn-group,\n.am-btn-toolbar > .am-input-group {\n  margin-left: 5px;\n}\n.am-btn-group > .am-btn:not(:first-child):not(:last-child):not(.am-dropdown-toggle) {\n  border-radius: 0;\n}\n.am-btn-group > .am-btn:first-child {\n  margin-left: 0;\n}\n.am-btn-group > .am-btn:first-child:not(:last-child):not(.am-dropdown-toggle) {\n  border-bottom-right-radius: 0;\n  border-top-right-radius: 0;\n}\n.am-btn-group > .am-btn:last-child:not(:first-child),\n.am-btn-group > .am-dropdown-toggle:not(:first-child) {\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n}\n.am-btn-group > .am-btn-group {\n  float: left;\n}\n.am-btn-group > .am-btn-group:not(:first-child):not(:last-child) > .am-btn {\n  border-radius: 0;\n}\n.am-btn-group > .am-btn-group:first-child > .am-btn:last-child,\n.am-btn-group > .am-btn-group:first-child > .am-dropdown-toggle {\n  border-bottom-right-radius: 0;\n  border-top-right-radius: 0;\n}\n.am-btn-group > .am-btn-group:last-child > .am-btn:first-child {\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n}\n.am-btn-group-xs > .am-btn {\n  font-size: 1.2rem;\n}\n.am-btn-group-sm > .am-btn {\n  font-size: 1.4rem;\n}\n.am-btn-group-lg > .am-btn {\n  font-size: 1.8rem;\n}\n.am-btn-group-stacked > .am-btn,\n.am-btn-group-stacked > .am-btn-group,\n.am-btn-group-stacked > .am-btn-group > .am-btn {\n  display: block;\n  float: none;\n  width: 100%;\n  max-width: 100%;\n}\n.am-btn-group-stacked > .am-btn-group:before,\n.am-btn-group-stacked > .am-btn-group:after {\n  content: \" \";\n  display: table;\n}\n.am-btn-group-stacked > .am-btn-group:after {\n  clear: both;\n}\n.am-btn-group-stacked > .am-btn-group > .am-btn {\n  float: none;\n}\n.am-btn-group-stacked > .am-btn + .am-btn,\n.am-btn-group-stacked > .am-btn + .am-btn-group,\n.am-btn-group-stacked > .am-btn-group + .am-btn,\n.am-btn-group-stacked > .am-btn-group + .am-btn-group {\n  margin-top: -1px;\n  margin-left: 0;\n}\n.am-btn-group-stacked > .am-btn:not(:first-child):not(:last-child) {\n  border-radius: 0;\n}\n.am-btn-group-stacked > .am-btn:first-child:not(:last-child) {\n  border-top-right-radius: 2px;\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n.am-btn-group-stacked > .am-btn:last-child:not(:first-child) {\n  border-bottom-left-radius: 2px;\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n.am-btn-group-stacked > .am-btn-group:not(:first-child):not(:last-child) > .am-btn {\n  border-radius: 0;\n}\n.am-btn-group-stacked > .am-btn-group:first-child:not(:last-child) > .am-btn:last-child,\n.am-btn-group-stacked > .am-btn-group:first-child:not(:last-child) > .am-dropdown-toggle {\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n.am-btn-group-stacked > .am-btn-group:last-child:not(:first-child) > .am-btn:first-child {\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n.am-btn-group-justify {\n  display: table;\n  table-layout: fixed;\n  border-collapse: separate;\n  width: 100%;\n}\n.am-btn-group-justify > .am-btn,\n.am-btn-group-justify > .am-btn-group {\n  float: none;\n  display: table-cell;\n  width: 1%;\n}\n.am-btn-group-justify > .am-btn-group .am-btn {\n  width: 100%;\n}\n.lte9 .am-btn-group-justify {\n  display: table;\n  table-layout: fixed;\n  border-collapse: separate;\n}\n.lte9 .am-btn-group-justify > .am-btn,\n.lte9 .am-btn-group-justify > .am-btn-group {\n  float: none;\n  display: table-cell;\n  width: 1%;\n}\n.am-btn-group .am-dropdown {\n  float: left;\n  margin-left: -1px;\n}\n.am-btn-group .am-dropdown > .am-btn {\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n}\n.am-btn-group .am-active .am-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.am-btn-group .am-active .am-dropdown-toggle.am-btn-link {\n  -webkit-box-shadow: none;\n          box-shadow: none;\n}\n.am-btn-group .am-dropdown-toggle:active,\n.am-btn-group .am-active .am-dropdown-toggle {\n  outline: 0;\n}\n[data-am-button] > .am-btn > input[type=\"radio\"],\n[data-am-button] > .am-btn > input[type=\"checkbox\"],\n.am-btn-group-check > .am-btn > input[type=\"radio\"],\n.am-btn-group-check > .am-btn > input[type=\"checkbox\"] {\n  position: absolute;\n  z-index: -1;\n  opacity: 0;\n}\n/* ==========================================================================\n   Component: Close\n ============================================================================ */\n.am-close {\n  display: inline-block;\n  text-align: center;\n  width: 24px;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 24px;\n  color: #000;\n  text-shadow: 0 1px 0 #fff;\n  opacity: .2;\n  -webkit-transition: all .3s;\n  transition: all .3s;\n}\n.am-close:hover,\n.am-close:focus {\n  color: #000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: .5;\n  outline: none;\n}\n.am-close[class*=\"am-icon-\"] {\n  font-size: 16px;\n}\nbutton.am-close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  /* Needed for Sarari */\n  border: 0;\n  -webkit-appearance: none;\n}\na.am-close:hover {\n  color: inherit;\n  text-decoration: none;\n  cursor: pointer;\n}\n/* Modifiers\n ============================================================================ */\n.am-close-alt {\n  border-radius: 50%;\n  background: #eee;\n  opacity: 0.7;\n  -webkit-box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25);\n          box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25);\n  /* Hover */\n}\n.am-close-alt:hover,\n.am-close-alt:focus {\n  opacity: 1;\n}\n.am-close-spin:hover {\n  -webkit-transform: rotate(360deg);\n      -ms-transform: rotate(360deg);\n          transform: rotate(360deg);\n}\n/* ==========================================================================\n   Component: Icon\n ============================================================================ */\n/* Font-face\n============================================================================= */\n@font-face {\n  font-family: 'FontAwesome';\n  src: url('../fonts/fontawesome-webfont.eot?v=4.5.0');\n  src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.5.0') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff2?v=4.5.0') format('woff2'), url('../fonts/fontawesome-webfont.woff?v=4.5.0') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.5.0') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.5.0#fontawesomeregular') format('svg');\n  font-weight: normal;\n  font-style: normal;\n}\n/* Component\n============================================================================= */\n[class*=\"am-icon-\"] {\n  display: inline-block;\n  font-style: normal;\n}\n[class*=\"am-icon-\"]:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n}\n.am-icon-border {\n  padding: .2em .25em .15em;\n  border: solid 0.08em #eee;\n  border-radius: .1em;\n}\n[class*=\"am-icon-\"].am-fl {\n  margin-right: .3em;\n}\n[class*=\"am-icon-\"].am-fr {\n  margin-left: .3em;\n}\n.am-icon-sm:before {\n  font-size: 150%;\n  vertical-align: -10%;\n}\n.am-icon-md:before {\n  font-size: 200%;\n  vertical-align: -16%;\n}\n.am-icon-lg:before {\n  font-size: 250%;\n  vertical-align: -22%;\n}\n/* Modifier: `.am-icon-btn`\n============================================================================= */\n.am-icon-btn {\n  -webkit-box-sizing: border-box;\n          box-sizing: border-box;\n  display: inline-block;\n  width: 48px;\n  height: 48px;\n  font-size: 24px;\n  line-height: 48px;\n  border-radius: 50%;\n  background-color: #eee;\n  color: #555555;\n  text-align: center;\n  /**\n   * Hover\n   * 1. Apply hover style also to focus state\n   * 2. Remove default focus style\n   */\n  /* Active */\n}\n.am-icon-btn:hover,\n.am-icon-btn:focus {\n  /* 1 */\n  background-color: #f5f5f5;\n  color: #333333;\n  text-decoration: none;\n  outline: none;\n  /* 2 */\n}\n.am-icon-btn:active {\n  background-color: #ddd;\n  color: #333333;\n}\n.am-icon-btn.am-primary,\n.am-icon-btn.am-secondary,\n.am-icon-btn.am-success,\n.am-icon-btn.am-warning,\n.am-icon-btn.am-danger {\n  color: #fff;\n}\n.am-icon-btn.am-primary {\n  background-color: #0e90d2;\n}\n.am-icon-btn.am-secondary {\n  background-color: #3bb4f2;\n}\n.am-icon-btn.am-success {\n  background-color: #5eb95e;\n}\n.am-icon-btn.am-warning {\n  background-color: #F37B1D;\n}\n.am-icon-btn.am-danger {\n  background-color: #dd514c;\n}\n.am-icon-btn-sm {\n  width: 32px;\n  height: 32px;\n  font-size: 16px;\n  line-height: 32px;\n}\n.am-icon-btn-lg {\n  width: 64px;\n  height: 64px;\n  font-size: 28px;\n  line-height: 64px;\n}\n/* Modifier: `.am-icon-fw` Fixed width\n============================================================================= */\n.am-icon-fw {\n  width: 1.25em;\n  text-align: center;\n}\n/* Icon mapping\n============================================================================= */\n.am-icon-glass:before {\n  content: \"\\f000\";\n}\n.am-icon-music:before {\n  content: \"\\f001\";\n}\n.am-icon-search:before {\n  content: \"\\f002\";\n}\n.am-icon-envelope-o:before {\n  content: \"\\f003\";\n}\n.am-icon-heart:before {\n  content: \"\\f004\";\n}\n.am-icon-star:before {\n  content: \"\\f005\";\n}\n.am-icon-star-o:before {\n  content: \"\\f006\";\n}\n.am-icon-user:before {\n  content: \"\\f007\";\n}\n.am-icon-film:before {\n  content: \"\\f008\";\n}\n.am-icon-th-large:before {\n  content: \"\\f009\";\n}\n.am-icon-th:before {\n  content: \"\\f00a\";\n}\n.am-icon-th-list:before {\n  content: \"\\f00b\";\n}\n.am-icon-check:before {\n  content: \"\\f00c\";\n}\n.am-icon-remove:before,\n.am-icon-close:before,\n.am-icon-times:before {\n  content: \"\\f00d\";\n}\n.am-icon-search-plus:before {\n  content: \"\\f00e\";\n}\n.am-icon-search-minus:before {\n  content: \"\\f010\";\n}\n.am-icon-power-off:before {\n  content: \"\\f011\";\n}\n.am-icon-signal:before {\n  content: \"\\f012\";\n}\n.am-icon-gear:before,\n.am-icon-cog:before {\n  content: \"\\f013\";\n}\n.am-icon-trash-o:before {\n  content: \"\\f014\";\n}\n.am-icon-home:before {\n  content: \"\\f015\";\n}\n.am-icon-file-o:before {\n  content: \"\\f016\";\n}\n.am-icon-clock-o:before {\n  content: \"\\f017\";\n}\n.am-icon-road:before {\n  content: \"\\f018\";\n}\n.am-icon-download:before {\n  content: \"\\f019\";\n}\n.am-icon-arrow-circle-o-down:before {\n  content: \"\\f01a\";\n}\n.am-icon-arrow-circle-o-up:before {\n  content: \"\\f01b\";\n}\n.am-icon-inbox:before {\n  content: \"\\f01c\";\n}\n.am-icon-play-circle-o:before {\n  content: \"\\f01d\";\n}\n.am-icon-rotate-right:before,\n.am-icon-repeat:before {\n  content: \"\\f01e\";\n}\n.am-icon-refresh:before {\n  content: \"\\f021\";\n}\n.am-icon-list-alt:before {\n  content: \"\\f022\";\n}\n.am-icon-lock:before {\n  content: \"\\f023\";\n}\n.am-icon-flag:before {\n  content: \"\\f024\";\n}\n.am-icon-headphones:before {\n  content: \"\\f025\";\n}\n.am-icon-volume-off:before {\n  content: \"\\f026\";\n}\n.am-icon-volume-down:before {\n  content: \"\\f027\";\n}\n.am-icon-volume-up:before {\n  content: \"\\f028\";\n}\n.am-icon-qrcode:before {\n  content: \"\\f029\";\n}\n.am-icon-barcode:before {\n  content: \"\\f02a\";\n}\n.am-icon-tag:before {\n  content: \"\\f02b\";\n}\n.am-icon-tags:before {\n  content: \"\\f02c\";\n}\n.am-icon-book:before {\n  content: \"\\f02d\";\n}\n.am-icon-bookmark:before {\n  content: \"\\f02e\";\n}\n.am-icon-print:before {\n  content: \"\\f02f\";\n}\n.am-icon-camera:before {\n  content: \"\\f030\";\n}\n.am-icon-font:before {\n  content: \"\\f031\";\n}\n.am-icon-bold:before {\n  content: \"\\f032\";\n}\n.am-icon-italic:before {\n  content: \"\\f033\";\n}\n.am-icon-text-height:before {\n  content: \"\\f034\";\n}\n.am-icon-text-width:before {\n  content: \"\\f035\";\n}\n.am-icon-align-left:before {\n  content: \"\\f036\";\n}\n.am-icon-align-center:before {\n  content: \"\\f037\";\n}\n.am-icon-align-right:before {\n  content: \"\\f038\";\n}\n.am-icon-align-justify:before {\n  content: \"\\f039\";\n}\n.am-icon-list:before {\n  content: \"\\f03a\";\n}\n.am-icon-dedent:before,\n.am-icon-outdent:before {\n  content: \"\\f03b\";\n}\n.am-icon-indent:before {\n  content: \"\\f03c\";\n}\n.am-icon-video-camera:before {\n  content: \"\\f03d\";\n}\n.am-icon-photo:before,\n.am-icon-image:before,\n.am-icon-picture-o:before {\n  content: \"\\f03e\";\n}\n.am-icon-pencil:before {\n  content: \"\\f040\";\n}\n.am-icon-map-marker:before {\n  content: \"\\f041\";\n}\n.am-icon-adjust:before {\n  content: \"\\f042\";\n}\n.am-icon-tint:before {\n  content: \"\\f043\";\n}\n.am-icon-edit:before,\n.am-icon-pencil-square-o:before {\n  content: \"\\f044\";\n}\n.am-icon-share-square-o:before {\n  content: \"\\f045\";\n}\n.am-icon-check-square-o:before {\n  content: \"\\f046\";\n}\n.am-icon-arrows:before {\n  content: \"\\f047\";\n}\n.am-icon-step-backward:before {\n  content: \"\\f048\";\n}\n.am-icon-fast-backward:before {\n  content: \"\\f049\";\n}\n.am-icon-backward:before {\n  content: \"\\f04a\";\n}\n.am-icon-play:before {\n  content: \"\\f04b\";\n}\n.am-icon-pause:before {\n  content: \"\\f04c\";\n}\n.am-icon-stop:before {\n  content: \"\\f04d\";\n}\n.am-icon-forward:before {\n  content: \"\\f04e\";\n}\n.am-icon-fast-forward:before {\n  content: \"\\f050\";\n}\n.am-icon-step-forward:before {\n  content: \"\\f051\";\n}\n.am-icon-eject:before {\n  content: \"\\f052\";\n}\n.am-icon-chevron-left:before {\n  content: \"\\f053\";\n}\n.am-icon-chevron-right:before {\n  content: \"\\f054\";\n}\n.am-icon-plus-circle:before {\n  content: \"\\f055\";\n}\n.am-icon-minus-circle:before {\n  content: \"\\f056\";\n}\n.am-icon-times-circle:before {\n  content: \"\\f057\";\n}\n.am-icon-check-circle:before {\n  content: \"\\f058\";\n}\n.am-icon-question-circle:before {\n  content: \"\\f059\";\n}\n.am-icon-info-circle:before {\n  content: \"\\f05a\";\n}\n.am-icon-crosshairs:before {\n  content: \"\\f05b\";\n}\n.am-icon-times-circle-o:before {\n  content: \"\\f05c\";\n}\n.am-icon-check-circle-o:before {\n  content: \"\\f05d\";\n}\n.am-icon-ban:before {\n  content: \"\\f05e\";\n}\n.am-icon-arrow-left:before {\n  content: \"\\f060\";\n}\n.am-icon-arrow-right:before {\n  content: \"\\f061\";\n}\n.am-icon-arrow-up:before {\n  content: \"\\f062\";\n}\n.am-icon-arrow-down:before {\n  content: \"\\f063\";\n}\n.am-icon-mail-forward:before,\n.am-icon-share:before {\n  content: \"\\f064\";\n}\n.am-icon-expand:before {\n  content: \"\\f065\";\n}\n.am-icon-compress:before {\n  content: \"\\f066\";\n}\n.am-icon-plus:before {\n  content: \"\\f067\";\n}\n.am-icon-minus:before {\n  content: \"\\f068\";\n}\n.am-icon-asterisk:before {\n  content: \"\\f069\";\n}\n.am-icon-exclamation-circle:before {\n  content: \"\\f06a\";\n}\n.am-icon-gift:before {\n  content: \"\\f06b\";\n}\n.am-icon-leaf:before {\n  content: \"\\f06c\";\n}\n.am-icon-fire:before {\n  content: \"\\f06d\";\n}\n.am-icon-eye:before {\n  content: \"\\f06e\";\n}\n.am-icon-eye-slash:before {\n  content: \"\\f070\";\n}\n.am-icon-warning:before,\n.am-icon-exclamation-triangle:before {\n  content: \"\\f071\";\n}\n.am-icon-plane:before {\n  content: \"\\f072\";\n}\n.am-icon-calendar:before {\n  content: \"\\f073\";\n}\n.am-icon-random:before {\n  content: \"\\f074\";\n}\n.am-icon-comment:before {\n  content: \"\\f075\";\n}\n.am-icon-magnet:before {\n  content: \"\\f076\";\n}\n.am-icon-chevron-up:before {\n  content: \"\\f077\";\n}\n.am-icon-chevron-down:before {\n  content: \"\\f078\";\n}\n.am-icon-retweet:before {\n  content: \"\\f079\";\n}\n.am-icon-shopping-cart:before {\n  content: \"\\f07a\";\n}\n.am-icon-folder:before {\n  content: \"\\f07b\";\n}\n.am-icon-folder-open:before {\n  content: \"\\f07c\";\n}\n.am-icon-arrows-v:before {\n  content: \"\\f07d\";\n}\n.am-icon-arrows-h:before {\n  content: \"\\f07e\";\n}\n.am-icon-bar-chart-o:before,\n.am-icon-bar-chart:before {\n  content: \"\\f080\";\n}\n.am-icon-twitter-square:before {\n  content: \"\\f081\";\n}\n.am-icon-facebook-square:before {\n  content: \"\\f082\";\n}\n.am-icon-camera-retro:before {\n  content: \"\\f083\";\n}\n.am-icon-key:before {\n  content: \"\\f084\";\n}\n.am-icon-gears:before,\n.am-icon-cogs:before {\n  content: \"\\f085\";\n}\n.am-icon-comments:before {\n  content: \"\\f086\";\n}\n.am-icon-thumbs-o-up:before {\n  content: \"\\f087\";\n}\n.am-icon-thumbs-o-down:before {\n  content: \"\\f088\";\n}\n.am-icon-star-half:before {\n  content: \"\\f089\";\n}\n.am-icon-heart-o:before {\n  content: \"\\f08a\";\n}\n.am-icon-sign-out:before {\n  content: \"\\f08b\";\n}\n.am-icon-linkedin-square:before {\n  content: \"\\f08c\";\n}\n.am-icon-thumb-tack:before {\n  content: \"\\f08d\";\n}\n.am-icon-external-link:before {\n  content: \"\\f08e\";\n}\n.am-icon-sign-in:before {\n  content: \"\\f090\";\n}\n.am-icon-trophy:before {\n  content: \"\\f091\";\n}\n.am-icon-github-square:before {\n  content: \"\\f092\";\n}\n.am-icon-upload:before {\n  content: \"\\f093\";\n}\n.am-icon-lemon-o:before {\n  content: \"\\f094\";\n}\n.am-icon-phone:before {\n  content: \"\\f095\";\n}\n.am-icon-square-o:before {\n  content: \"\\f096\";\n}\n.am-icon-bookmark-o:before {\n  content: \"\\f097\";\n}\n.am-icon-phone-square:before {\n  content: \"\\f098\";\n}\n.am-icon-twitter:before {\n  content: \"\\f099\";\n}\n.am-icon-facebook-f:before,\n.am-icon-facebook:before {\n  content: \"\\f09a\";\n}\n.am-icon-github:before {\n  content: \"\\f09b\";\n}\n.am-icon-unlock:before {\n  content: \"\\f09c\";\n}\n.am-icon-credit-card:before {\n  content: \"\\f09d\";\n}\n.am-icon-feed:before,\n.am-icon-rss:before {\n  content: \"\\f09e\";\n}\n.am-icon-hdd-o:before {\n  content: \"\\f0a0\";\n}\n.am-icon-bullhorn:before {\n  content: \"\\f0a1\";\n}\n.am-icon-bell:before {\n  content: \"\\f0f3\";\n}\n.am-icon-certificate:before {\n  content: \"\\f0a3\";\n}\n.am-icon-hand-o-right:before {\n  content: \"\\f0a4\";\n}\n.am-icon-hand-o-left:before {\n  content: \"\\f0a5\";\n}\n.am-icon-hand-o-up:before {\n  content: \"\\f0a6\";\n}\n.am-icon-hand-o-down:before {\n  content: \"\\f0a7\";\n}\n.am-icon-arrow-circle-left:before {\n  content: \"\\f0a8\";\n}\n.am-icon-arrow-circle-right:before {\n  content: \"\\f0a9\";\n}\n.am-icon-arrow-circle-up:before {\n  content: \"\\f0aa\";\n}\n.am-icon-arrow-circle-down:before {\n  content: \"\\f0ab\";\n}\n.am-icon-globe:before {\n  content: \"\\f0ac\";\n}\n.am-icon-wrench:before {\n  content: \"\\f0ad\";\n}\n.am-icon-tasks:before {\n  content: \"\\f0ae\";\n}\n.am-icon-filter:before {\n  content: \"\\f0b0\";\n}\n.am-icon-briefcase:before {\n  content: \"\\f0b1\";\n}\n.am-icon-arrows-alt:before {\n  content: \"\\f0b2\";\n}\n.am-icon-group:before,\n.am-icon-users:before {\n  content: \"\\f0c0\";\n}\n.am-icon-chain:before,\n.am-icon-link:before {\n  content: \"\\f0c1\";\n}\n.am-icon-cloud:before {\n  content: \"\\f0c2\";\n}\n.am-icon-flask:before {\n  content: \"\\f0c3\";\n}\n.am-icon-cut:before,\n.am-icon-scissors:before {\n  content: \"\\f0c4\";\n}\n.am-icon-copy:before,\n.am-icon-files-o:before {\n  content: \"\\f0c5\";\n}\n.am-icon-paperclip:before {\n  content: \"\\f0c6\";\n}\n.am-icon-save:before,\n.am-icon-floppy-o:before {\n  content: \"\\f0c7\";\n}\n.am-icon-square:before {\n  content: \"\\f0c8\";\n}\n.am-icon-navicon:before,\n.am-icon-reorder:before,\n.am-icon-bars:before {\n  content: \"\\f0c9\";\n}\n.am-icon-list-ul:before {\n  content: \"\\f0ca\";\n}\n.am-icon-list-ol:before {\n  content: \"\\f0cb\";\n}\n.am-icon-strikethrough:before {\n  content: \"\\f0cc\";\n}\n.am-icon-underline:before {\n  content: \"\\f0cd\";\n}\n.am-icon-table:before {\n  content: \"\\f0ce\";\n}\n.am-icon-magic:before {\n  content: \"\\f0d0\";\n}\n.am-icon-truck:before {\n  content: \"\\f0d1\";\n}\n.am-icon-pinterest:before {\n  content: \"\\f0d2\";\n}\n.am-icon-pinterest-square:before {\n  content: \"\\f0d3\";\n}\n.am-icon-google-plus-square:before {\n  content: \"\\f0d4\";\n}\n.am-icon-google-plus:before {\n  content: \"\\f0d5\";\n}\n.am-icon-money:before {\n  content: \"\\f0d6\";\n}\n.am-icon-caret-down:before {\n  content: \"\\f0d7\";\n}\n.am-icon-caret-up:before {\n  content: \"\\f0d8\";\n}\n.am-icon-caret-left:before {\n  content: \"\\f0d9\";\n}\n.am-icon-caret-right:before {\n  content: \"\\f0da\";\n}\n.am-icon-columns:before {\n  content: \"\\f0db\";\n}\n.am-icon-unsorted:before,\n.am-icon-sort:before {\n  content: \"\\f0dc\";\n}\n.am-icon-sort-down:before,\n.am-icon-sort-desc:before {\n  content: \"\\f0dd\";\n}\n.am-icon-sort-up:before,\n.am-icon-sort-asc:before {\n  content: \"\\f0de\";\n}\n.am-icon-envelope:before {\n  content: \"\\f0e0\";\n}\n.am-icon-linkedin:before {\n  content: \"\\f0e1\";\n}\n.am-icon-rotate-left:before,\n.am-icon-undo:before {\n  content: \"\\f0e2\";\n}\n.am-icon-legal:before,\n.am-icon-gavel:before {\n  content: \"\\f0e3\";\n}\n.am-icon-dashboard:before,\n.am-icon-tachometer:before {\n  content: \"\\f0e4\";\n}\n.am-icon-comment-o:before {\n  content: \"\\f0e5\";\n}\n.am-icon-comments-o:before {\n  content: \"\\f0e6\";\n}\n.am-icon-flash:before,\n.am-icon-bolt:before {\n  content: \"\\f0e7\";\n}\n.am-icon-sitemap:before {\n  content: \"\\f0e8\";\n}\n.am-icon-umbrella:before {\n  content: \"\\f0e9\";\n}\n.am-icon-paste:before,\n.am-icon-clipboard:before {\n  content: \"\\f0ea\";\n}\n.am-icon-lightbulb-o:before {\n  content: \"\\f0eb\";\n}\n.am-icon-exchange:before {\n  content: \"\\f0ec\";\n}\n.am-icon-cloud-download:before {\n  content: \"\\f0ed\";\n}\n.am-icon-cloud-upload:before {\n  content: \"\\f0ee\";\n}\n.am-icon-user-md:before {\n  content: \"\\f0f0\";\n}\n.am-icon-stethoscope:before {\n  content: \"\\f0f1\";\n}\n.am-icon-suitcase:before {\n  content: \"\\f0f2\";\n}\n.am-icon-bell-o:before {\n  content: \"\\f0a2\";\n}\n.am-icon-coffee:before {\n  content: \"\\f0f4\";\n}\n.am-icon-cutlery:before {\n  content: \"\\f0f5\";\n}\n.am-icon-file-text-o:before {\n  content: \"\\f0f6\";\n}\n.am-icon-building-o:before {\n  content: \"\\f0f7\";\n}\n.am-icon-hospital-o:before {\n  content: \"\\f0f8\";\n}\n.am-icon-ambulance:before {\n  content: \"\\f0f9\";\n}\n.am-icon-medkit:before {\n  content: \"\\f0fa\";\n}\n.am-icon-fighter-jet:before {\n  content: \"\\f0fb\";\n}\n.am-icon-beer:before {\n  content: \"\\f0fc\";\n}\n.am-icon-h-square:before {\n  content: \"\\f0fd\";\n}\n.am-icon-plus-square:before {\n  content: \"\\f0fe\";\n}\n.am-icon-angle-double-left:before {\n  content: \"\\f100\";\n}\n.am-icon-angle-double-right:before {\n  content: \"\\f101\";\n}\n.am-icon-angle-double-up:before {\n  content: \"\\f102\";\n}\n.am-icon-angle-double-down:before {\n  content: \"\\f103\";\n}\n.am-icon-angle-left:before {\n  content: \"\\f104\";\n}\n.am-icon-angle-right:before {\n  content: \"\\f105\";\n}\n.am-icon-angle-up:before {\n  content: \"\\f106\";\n}\n.am-icon-angle-down:before {\n  content: \"\\f107\";\n}\n.am-icon-desktop:before {\n  content: \"\\f108\";\n}\n.am-icon-laptop:before {\n  content: \"\\f109\";\n}\n.am-icon-tablet:before {\n  content: \"\\f10a\";\n}\n.am-icon-mobile-phone:before,\n.am-icon-mobile:before {\n  content: \"\\f10b\";\n}\n.am-icon-circle-o:before {\n  content: \"\\f10c\";\n}\n.am-icon-quote-left:before {\n  content: \"\\f10d\";\n}\n.am-icon-quote-right:before {\n  content: \"\\f10e\";\n}\n.am-icon-spinner:before {\n  content: \"\\f110\";\n}\n.am-icon-circle:before {\n  content: \"\\f111\";\n}\n.am-icon-mail-reply:before,\n.am-icon-reply:before {\n  content: \"\\f112\";\n}\n.am-icon-github-alt:before {\n  content: \"\\f113\";\n}\n.am-icon-folder-o:before {\n  content: \"\\f114\";\n}\n.am-icon-folder-open-o:before {\n  content: \"\\f115\";\n}\n.am-icon-smile-o:before {\n  content: \"\\f118\";\n}\n.am-icon-frown-o:before {\n  content: \"\\f119\";\n}\n.am-icon-meh-o:before {\n  content: \"\\f11a\";\n}\n.am-icon-gamepad:before {\n  content: \"\\f11b\";\n}\n.am-icon-keyboard-o:before {\n  content: \"\\f11c\";\n}\n.am-icon-flag-o:before {\n  content: \"\\f11d\";\n}\n.am-icon-flag-checkered:before {\n  content: \"\\f11e\";\n}\n.am-icon-terminal:before {\n  content: \"\\f120\";\n}\n.am-icon-code:before {\n  content: \"\\f121\";\n}\n.am-icon-mail-reply-all:before,\n.am-icon-reply-all:before {\n  content: \"\\f122\";\n}\n.am-icon-star-half-empty:before,\n.am-icon-star-half-full:before,\n.am-icon-star-half-o:before {\n  content: \"\\f123\";\n}\n.am-icon-location-arrow:before {\n  content: \"\\f124\";\n}\n.am-icon-crop:before {\n  content: \"\\f125\";\n}\n.am-icon-code-fork:before {\n  content: \"\\f126\";\n}\n.am-icon-unlink:before,\n.am-icon-chain-broken:before {\n  content: \"\\f127\";\n}\n.am-icon-question:before {\n  content: \"\\f128\";\n}\n.am-icon-info:before {\n  content: \"\\f129\";\n}\n.am-icon-exclamation:before {\n  content: \"\\f12a\";\n}\n.am-icon-superscript:before {\n  content: \"\\f12b\";\n}\n.am-icon-subscript:before {\n  content: \"\\f12c\";\n}\n.am-icon-eraser:before {\n  content: \"\\f12d\";\n}\n.am-icon-puzzle-piece:before {\n  content: \"\\f12e\";\n}\n.am-icon-microphone:before {\n  content: \"\\f130\";\n}\n.am-icon-microphone-slash:before {\n  content: \"\\f131\";\n}\n.am-icon-shield:before {\n  content: \"\\f132\";\n}\n.am-icon-calendar-o:before {\n  content: \"\\f133\";\n}\n.am-icon-fire-extinguisher:before {\n  content: \"\\f134\";\n}\n.am-icon-rocket:before {\n  content: \"\\f135\";\n}\n.am-icon-maxcdn:before {\n  content: \"\\f136\";\n}\n.am-icon-chevron-circle-left:before {\n  content: \"\\f137\";\n}\n.am-icon-chevron-circle-right:before {\n  content: \"\\f138\";\n}\n.am-icon-chevron-circle-up:before {\n  content: \"\\f139\";\n}\n.am-icon-chevron-circle-down:before {\n  content: \"\\f13a\";\n}\n.am-icon-html5:before {\n  content: \"\\f13b\";\n}\n.am-icon-css3:before {\n  content: \"\\f13c\";\n}\n.am-icon-anchor:before {\n  content: \"\\f13d\";\n}\n.am-icon-unlock-alt:before {\n  content: \"\\f13e\";\n}\n.am-icon-bullseye:before {\n  content: \"\\f140\";\n}\n.am-icon-ellipsis-h:before {\n  content: \"\\f141\";\n}\n.am-icon-ellipsis-v:before {\n  content: \"\\f142\";\n}\n.am-icon-rss-square:before {\n  content: \"\\f143\";\n}\n.am-icon-play-circle:before {\n  content: \"\\f144\";\n}\n.am-icon-ticket:before {\n  content: \"\\f145\";\n}\n.am-icon-minus-square:before {\n  content: \"\\f146\";\n}\n.am-icon-minus-square-o:before {\n  content: \"\\f147\";\n}\n.am-icon-level-up:before {\n  content: \"\\f148\";\n}\n.am-icon-level-down:before {\n  content: \"\\f149\";\n}\n.am-icon-check-square:before {\n  content: \"\\f14a\";\n}\n.am-icon-pencil-square:before {\n  content: \"\\f14b\";\n}\n.am-icon-external-link-square:before {\n  content: \"\\f14c\";\n}\n.am-icon-share-square:before {\n  content: \"\\f14d\";\n}\n.am-icon-compass:before {\n  content: \"\\f14e\";\n}\n.am-icon-toggle-down:before,\n.am-icon-caret-square-o-down:before {\n  content: \"\\f150\";\n}\n.am-icon-toggle-up:before,\n.am-icon-caret-square-o-up:before {\n  content: \"\\f151\";\n}\n.am-icon-toggle-right:before,\n.am-icon-caret-square-o-right:before {\n  content: \"\\f152\";\n}\n.am-icon-euro:before,\n.am-icon-eur:before {\n  content: \"\\f153\";\n}\n.am-icon-gbp:before {\n  content: \"\\f154\";\n}\n.am-icon-dollar:before,\n.am-icon-usd:before {\n  content: \"\\f155\";\n}\n.am-icon-rupee:before,\n.am-icon-inr:before {\n  content: \"\\f156\";\n}\n.am-icon-cny:before,\n.am-icon-rmb:before,\n.am-icon-yen:before,\n.am-icon-jpy:before {\n  content: \"\\f157\";\n}\n.am-icon-ruble:before,\n.am-icon-rouble:before,\n.am-icon-rub:before {\n  content: \"\\f158\";\n}\n.am-icon-won:before,\n.am-icon-krw:before {\n  content: \"\\f159\";\n}\n.am-icon-bitcoin:before,\n.am-icon-btc:before {\n  content: \"\\f15a\";\n}\n.am-icon-file:before {\n  content: \"\\f15b\";\n}\n.am-icon-file-text:before {\n  content: \"\\f15c\";\n}\n.am-icon-sort-alpha-asc:before {\n  content: \"\\f15d\";\n}\n.am-icon-sort-alpha-desc:before {\n  content: \"\\f15e\";\n}\n.am-icon-sort-amount-asc:before {\n  content: \"\\f160\";\n}\n.am-icon-sort-amount-desc:before {\n  content: \"\\f161\";\n}\n.am-icon-sort-numeric-asc:before {\n  content: \"\\f162\";\n}\n.am-icon-sort-numeric-desc:before {\n  content: \"\\f163\";\n}\n.am-icon-thumbs-up:before {\n  content: \"\\f164\";\n}\n.am-icon-thumbs-down:before {\n  content: \"\\f165\";\n}\n.am-icon-youtube-square:before {\n  content: \"\\f166\";\n}\n.am-icon-youtube:before {\n  content: \"\\f167\";\n}\n.am-icon-xing:before {\n  content: \"\\f168\";\n}\n.am-icon-xing-square:before {\n  content: \"\\f169\";\n}\n.am-icon-youtube-play:before {\n  content: \"\\f16a\";\n}\n.am-icon-dropbox:before {\n  content: \"\\f16b\";\n}\n.am-icon-stack-overflow:before {\n  content: \"\\f16c\";\n}\n.am-icon-instagram:before {\n  content: \"\\f16d\";\n}\n.am-icon-flickr:before {\n  content: \"\\f16e\";\n}\n.am-icon-adn:before {\n  content: \"\\f170\";\n}\n.am-icon-bitbucket:before {\n  content: \"\\f171\";\n}\n.am-icon-bitbucket-square:before {\n  content: \"\\f172\";\n}\n.am-icon-tumblr:before {\n  content: \"\\f173\";\n}\n.am-icon-tumblr-square:before {\n  content: \"\\f174\";\n}\n.am-icon-long-arrow-down:before {\n  content: \"\\f175\";\n}\n.am-icon-long-arrow-up:before {\n  content: \"\\f176\";\n}\n.am-icon-long-arrow-left:before {\n  content: \"\\f177\";\n}\n.am-icon-long-arrow-right:before {\n  content: \"\\f178\";\n}\n.am-icon-apple:before {\n  content: \"\\f179\";\n}\n.am-icon-windows:before {\n  content: \"\\f17a\";\n}\n.am-icon-android:before {\n  content: \"\\f17b\";\n}\n.am-icon-linux:before {\n  content: \"\\f17c\";\n}\n.am-icon-dribbble:before {\n  content: \"\\f17d\";\n}\n.am-icon-skype:before {\n  content: \"\\f17e\";\n}\n.am-icon-foursquare:before {\n  content: \"\\f180\";\n}\n.am-icon-trello:before {\n  content: \"\\f181\";\n}\n.am-icon-female:before {\n  content: \"\\f182\";\n}\n.am-icon-male:before {\n  content: \"\\f183\";\n}\n.am-icon-gittip:before,\n.am-icon-gratipay:before {\n  content: \"\\f184\";\n}\n.am-icon-sun-o:before {\n  content: \"\\f185\";\n}\n.am-icon-moon-o:before {\n  content: \"\\f186\";\n}\n.am-icon-archive:before {\n  content: \"\\f187\";\n}\n.am-icon-bug:before {\n  content: \"\\f188\";\n}\n.am-icon-vk:before {\n  content: \"\\f189\";\n}\n.am-icon-weibo:before {\n  content: \"\\f18a\";\n}\n.am-icon-renren:before {\n  content: \"\\f18b\";\n}\n.am-icon-pagelines:before {\n  content: \"\\f18c\";\n}\n.am-icon-stack-exchange:before {\n  content: \"\\f18d\";\n}\n.am-icon-arrow-circle-o-right:before {\n  content: \"\\f18e\";\n}\n.am-icon-arrow-circle-o-left:before {\n  content: \"\\f190\";\n}\n.am-icon-toggle-left:before,\n.am-icon-caret-square-o-left:before {\n  content: \"\\f191\";\n}\n.am-icon-dot-circle-o:before {\n  content: \"\\f192\";\n}\n.am-icon-wheelchair:before {\n  content: \"\\f193\";\n}\n.am-icon-vimeo-square:before {\n  content: \"\\f194\";\n}\n.am-icon-turkish-lira:before,\n.am-icon-try:before {\n  content: \"\\f195\";\n}\n.am-icon-plus-square-o:before {\n  content: \"\\f196\";\n}\n.am-icon-space-shuttle:before {\n  content: \"\\f197\";\n}\n.am-icon-slack:before {\n  content: \"\\f198\";\n}\n.am-icon-envelope-square:before {\n  content: \"\\f199\";\n}\n.am-icon-wordpress:before {\n  content: \"\\f19a\";\n}\n.am-icon-openid:before {\n  content: \"\\f19b\";\n}\n.am-icon-institution:before,\n.am-icon-bank:before,\n.am-icon-university:before {\n  content: \"\\f19c\";\n}\n.am-icon-mortar-board:before,\n.am-icon-graduation-cap:before {\n  content: \"\\f19d\";\n}\n.am-icon-yahoo:before {\n  content: \"\\f19e\";\n}\n.am-icon-google:before {\n  content: \"\\f1a0\";\n}\n.am-icon-reddit:before {\n  content: \"\\f1a1\";\n}\n.am-icon-reddit-square:before {\n  content: \"\\f1a2\";\n}\n.am-icon-stumbleupon-circle:before {\n  content: \"\\f1a3\";\n}\n.am-icon-stumbleupon:before {\n  content: \"\\f1a4\";\n}\n.am-icon-delicious:before {\n  content: \"\\f1a5\";\n}\n.am-icon-digg:before {\n  content: \"\\f1a6\";\n}\n.am-icon-pied-piper:before {\n  content: \"\\f1a7\";\n}\n.am-icon-pied-piper-alt:before {\n  content: \"\\f1a8\";\n}\n.am-icon-drupal:before {\n  content: \"\\f1a9\";\n}\n.am-icon-joomla:before {\n  content: \"\\f1aa\";\n}\n.am-icon-language:before {\n  content: \"\\f1ab\";\n}\n.am-icon-fax:before {\n  content: \"\\f1ac\";\n}\n.am-icon-building:before {\n  content: \"\\f1ad\";\n}\n.am-icon-child:before {\n  content: \"\\f1ae\";\n}\n.am-icon-paw:before {\n  content: \"\\f1b0\";\n}\n.am-icon-spoon:before {\n  content: \"\\f1b1\";\n}\n.am-icon-cube:before {\n  content: \"\\f1b2\";\n}\n.am-icon-cubes:before {\n  content: \"\\f1b3\";\n}\n.am-icon-behance:before {\n  content: \"\\f1b4\";\n}\n.am-icon-behance-square:before {\n  content: \"\\f1b5\";\n}\n.am-icon-steam:before {\n  content: \"\\f1b6\";\n}\n.am-icon-steam-square:before {\n  content: \"\\f1b7\";\n}\n.am-icon-recycle:before {\n  content: \"\\f1b8\";\n}\n.am-icon-automobile:before,\n.am-icon-car:before {\n  content: \"\\f1b9\";\n}\n.am-icon-cab:before,\n.am-icon-taxi:before {\n  content: \"\\f1ba\";\n}\n.am-icon-tree:before {\n  content: \"\\f1bb\";\n}\n.am-icon-spotify:before {\n  content: \"\\f1bc\";\n}\n.am-icon-deviantart:before {\n  content: \"\\f1bd\";\n}\n.am-icon-soundcloud:before {\n  content: \"\\f1be\";\n}\n.am-icon-database:before {\n  content: \"\\f1c0\";\n}\n.am-icon-file-pdf-o:before {\n  content: \"\\f1c1\";\n}\n.am-icon-file-word-o:before {\n  content: \"\\f1c2\";\n}\n.am-icon-file-excel-o:before {\n  content: \"\\f1c3\";\n}\n.am-icon-file-powerpoint-o:before {\n  content: \"\\f1c4\";\n}\n.am-icon-file-photo-o:before,\n.am-icon-file-picture-o:before,\n.am-icon-file-image-o:before {\n  content: \"\\f1c5\";\n}\n.am-icon-file-zip-o:before,\n.am-icon-file-archive-o:before {\n  content: \"\\f1c6\";\n}\n.am-icon-file-sound-o:before,\n.am-icon-file-audio-o:before {\n  content: \"\\f1c7\";\n}\n.am-icon-file-movie-o:before,\n.am-icon-file-video-o:before {\n  content: \"\\f1c8\";\n}\n.am-icon-file-code-o:before {\n  content: \"\\f1c9\";\n}\n.am-icon-vine:before {\n  content: \"\\f1ca\";\n}\n.am-icon-codepen:before {\n  content: \"\\f1cb\";\n}\n.am-icon-jsfiddle:before {\n  content: \"\\f1cc\";\n}\n.am-icon-life-bouy:before,\n.am-icon-life-buoy:before,\n.am-icon-life-saver:before,\n.am-icon-support:before,\n.am-icon-life-ring:before {\n  content: \"\\f1cd\";\n}\n.am-icon-circle-o-notch:before {\n  content: \"\\f1ce\";\n}\n.am-icon-ra:before,\n.am-icon-rebel:before {\n  content: \"\\f1d0\";\n}\n.am-icon-ge:before,\n.am-icon-empire:before {\n  content: \"\\f1d1\";\n}\n.am-icon-git-square:before {\n  content: \"\\f1d2\";\n}\n.am-icon-git:before {\n  content: \"\\f1d3\";\n}\n.am-icon-y-combinator-square:before,\n.am-icon-yc-square:before,\n.am-icon-hacker-news:before {\n  content: \"\\f1d4\";\n}\n.am-icon-tencent-weibo:before {\n  content: \"\\f1d5\";\n}\n.am-icon-qq:before {\n  content: \"\\f1d6\";\n}\n.am-icon-wechat:before,\n.am-icon-weixin:before {\n  content: \"\\f1d7\";\n}\n.am-icon-send:before,\n.am-icon-paper-plane:before {\n  content: \"\\f1d8\";\n}\n.am-icon-send-o:before,\n.am-icon-paper-plane-o:before {\n  content: \"\\f1d9\";\n}\n.am-icon-history:before {\n  content: \"\\f1da\";\n}\n.am-icon-circle-thin:before {\n  content: \"\\f1db\";\n}\n.am-icon-header:before {\n  content: \"\\f1dc\";\n}\n.am-icon-paragraph:before {\n  content: \"\\f1dd\";\n}\n.am-icon-sliders:before {\n  content: \"\\f1de\";\n}\n.am-icon-share-alt:before {\n  content: \"\\f1e0\";\n}\n.am-icon-share-alt-square:before {\n  content: \"\\f1e1\";\n}\n.am-icon-bomb:before {\n  content: \"\\f1e2\";\n}\n.am-icon-soccer-ball-o:before,\n.am-icon-futbol-o:before {\n  content: \"\\f1e3\";\n}\n.am-icon-tty:before {\n  content: \"\\f1e4\";\n}\n.am-icon-binoculars:before {\n  content: \"\\f1e5\";\n}\n.am-icon-plug:before {\n  content: \"\\f1e6\";\n}\n.am-icon-slideshare:before {\n  content: \"\\f1e7\";\n}\n.am-icon-twitch:before {\n  content: \"\\f1e8\";\n}\n.am-icon-yelp:before {\n  content: \"\\f1e9\";\n}\n.am-icon-newspaper-o:before {\n  content: \"\\f1ea\";\n}\n.am-icon-wifi:before {\n  content: \"\\f1eb\";\n}\n.am-icon-calculator:before {\n  content: \"\\f1ec\";\n}\n.am-icon-paypal:before {\n  content: \"\\f1ed\";\n}\n.am-icon-google-wallet:before {\n  content: \"\\f1ee\";\n}\n.am-icon-cc-visa:before {\n  content: \"\\f1f0\";\n}\n.am-icon-cc-mastercard:before {\n  content: \"\\f1f1\";\n}\n.am-icon-cc-discover:before {\n  content: \"\\f1f2\";\n}\n.am-icon-cc-amex:before {\n  content: \"\\f1f3\";\n}\n.am-icon-cc-paypal:before {\n  content: \"\\f1f4\";\n}\n.am-icon-cc-stripe:before {\n  content: \"\\f1f5\";\n}\n.am-icon-bell-slash:before {\n  content: \"\\f1f6\";\n}\n.am-icon-bell-slash-o:before {\n  content: \"\\f1f7\";\n}\n.am-icon-trash:before {\n  content: \"\\f1f8\";\n}\n.am-icon-copyright:before {\n  content: \"\\f1f9\";\n}\n.am-icon-at:before {\n  content: \"\\f1fa\";\n}\n.am-icon-eyedropper:before {\n  content: \"\\f1fb\";\n}\n.am-icon-paint-brush:before {\n  content: \"\\f1fc\";\n}\n.am-icon-birthday-cake:before {\n  content: \"\\f1fd\";\n}\n.am-icon-area-chart:before {\n  content: \"\\f1fe\";\n}\n.am-icon-pie-chart:before {\n  content: \"\\f200\";\n}\n.am-icon-line-chart:before {\n  content: \"\\f201\";\n}\n.am-icon-lastfm:before {\n  content: \"\\f202\";\n}\n.am-icon-lastfm-square:before {\n  content: \"\\f203\";\n}\n.am-icon-toggle-off:before {\n  content: \"\\f204\";\n}\n.am-icon-toggle-on:before {\n  content: \"\\f205\";\n}\n.am-icon-bicycle:before {\n  content: \"\\f206\";\n}\n.am-icon-bus:before {\n  content: \"\\f207\";\n}\n.am-icon-ioxhost:before {\n  content: \"\\f208\";\n}\n.am-icon-angellist:before {\n  content: \"\\f209\";\n}\n.am-icon-cc:before {\n  content: \"\\f20a\";\n}\n.am-icon-shekel:before,\n.am-icon-sheqel:before,\n.am-icon-ils:before {\n  content: \"\\f20b\";\n}\n.am-icon-meanpath:before {\n  content: \"\\f20c\";\n}\n.am-icon-buysellads:before {\n  content: \"\\f20d\";\n}\n.am-icon-connectdevelop:before {\n  content: \"\\f20e\";\n}\n.am-icon-dashcube:before {\n  content: \"\\f210\";\n}\n.am-icon-forumbee:before {\n  content: \"\\f211\";\n}\n.am-icon-leanpub:before {\n  content: \"\\f212\";\n}\n.am-icon-sellsy:before {\n  content: \"\\f213\";\n}\n.am-icon-shirtsinbulk:before {\n  content: \"\\f214\";\n}\n.am-icon-simplybuilt:before {\n  content: \"\\f215\";\n}\n.am-icon-skyatlas:before {\n  content: \"\\f216\";\n}\n.am-icon-cart-plus:before {\n  content: \"\\f217\";\n}\n.am-icon-cart-arrow-down:before {\n  content: \"\\f218\";\n}\n.am-icon-diamond:before {\n  content: \"\\f219\";\n}\n.am-icon-ship:before {\n  content: \"\\f21a\";\n}\n.am-icon-user-secret:before {\n  content: \"\\f21b\";\n}\n.am-icon-motorcycle:before {\n  content: \"\\f21c\";\n}\n.am-icon-street-view:before {\n  content: \"\\f21d\";\n}\n.am-icon-heartbeat:before {\n  content: \"\\f21e\";\n}\n.am-icon-venus:before {\n  content: \"\\f221\";\n}\n.am-icon-mars:before {\n  content: \"\\f222\";\n}\n.am-icon-mercury:before {\n  content: \"\\f223\";\n}\n.am-icon-intersex:before,\n.am-icon-transgender:before {\n  content: \"\\f224\";\n}\n.am-icon-transgender-alt:before {\n  content: \"\\f225\";\n}\n.am-icon-venus-double:before {\n  content: \"\\f226\";\n}\n.am-icon-mars-double:before {\n  content: \"\\f227\";\n}\n.am-icon-venus-mars:before {\n  content: \"\\f228\";\n}\n.am-icon-mars-stroke:before {\n  content: \"\\f229\";\n}\n.am-icon-mars-stroke-v:before {\n  content: \"\\f22a\";\n}\n.am-icon-mars-stroke-h:before {\n  content: \"\\f22b\";\n}\n.am-icon-neuter:before {\n  content: \"\\f22c\";\n}\n.am-icon-genderless:before {\n  content: \"\\f22d\";\n}\n.am-icon-facebook-official:before {\n  content: \"\\f230\";\n}\n.am-icon-pinterest-p:before {\n  content: \"\\f231\";\n}\n.am-icon-whatsapp:before {\n  content: \"\\f232\";\n}\n.am-icon-server:before {\n  content: \"\\f233\";\n}\n.am-icon-user-plus:before {\n  content: \"\\f234\";\n}\n.am-icon-user-times:before {\n  content: \"\\f235\";\n}\n.am-icon-hotel:before,\n.am-icon-bed:before {\n  content: \"\\f236\";\n}\n.am-icon-viacoin:before {\n  content: \"\\f237\";\n}\n.am-icon-train:before {\n  content: \"\\f238\";\n}\n.am-icon-subway:before {\n  content: \"\\f239\";\n}\n.am-icon-medium:before {\n  content: \"\\f23a\";\n}\n.am-icon-yc:before,\n.am-icon-y-combinator:before {\n  content: \"\\f23b\";\n}\n.am-icon-optin-monster:before {\n  content: \"\\f23c\";\n}\n.am-icon-opencart:before {\n  content: \"\\f23d\";\n}\n.am-icon-expeditedssl:before {\n  content: \"\\f23e\";\n}\n.am-icon-battery-4:before,\n.am-icon-battery-full:before {\n  content: \"\\f240\";\n}\n.am-icon-battery-3:before,\n.am-icon-battery-three-quarters:before {\n  content: \"\\f241\";\n}\n.am-icon-battery-2:before,\n.am-icon-battery-half:before {\n  content: \"\\f242\";\n}\n.am-icon-battery-1:before,\n.am-icon-battery-quarter:before {\n  content: \"\\f243\";\n}\n.am-icon-battery-0:before,\n.am-icon-battery-empty:before {\n  content: \"\\f244\";\n}\n.am-icon-mouse-pointer:before {\n  content: \"\\f245\";\n}\n.am-icon-i-cursor:before {\n  content: \"\\f246\";\n}\n.am-icon-object-group:before {\n  content: \"\\f247\";\n}\n.am-icon-object-ungroup:before {\n  content: \"\\f248\";\n}\n.am-icon-sticky-note:before {\n  content: \"\\f249\";\n}\n.am-icon-sticky-note-o:before {\n  content: \"\\f24a\";\n}\n.am-icon-cc-jcb:before {\n  content: \"\\f24b\";\n}\n.am-icon-cc-diners-club:before {\n  content: \"\\f24c\";\n}\n.am-icon-clone:before {\n  content: \"\\f24d\";\n}\n.am-icon-balance-scale:before {\n  content: \"\\f24e\";\n}\n.am-icon-hourglass-o:before {\n  content: \"\\f250\";\n}\n.am-icon-hourglass-1:before,\n.am-icon-hourglass-start:before {\n  content: \"\\f251\";\n}\n.am-icon-hourglass-2:before,\n.am-icon-hourglass-half:before {\n  content: \"\\f252\";\n}\n.am-icon-hourglass-3:before,\n.am-icon-hourglass-end:before {\n  content: \"\\f253\";\n}\n.am-icon-hourglass:before {\n  content: \"\\f254\";\n}\n.am-icon-hand-grab-o:before,\n.am-icon-hand-rock-o:before {\n  content: \"\\f255\";\n}\n.am-icon-hand-stop-o:before,\n.am-icon-hand-paper-o:before {\n  content: \"\\f256\";\n}\n.am-icon-hand-scissors-o:before {\n  content: \"\\f257\";\n}\n.am-icon-hand-lizard-o:before {\n  content: \"\\f258\";\n}\n.am-icon-hand-spock-o:before {\n  content: \"\\f259\";\n}\n.am-icon-hand-pointer-o:before {\n  content: \"\\f25a\";\n}\n.am-icon-hand-peace-o:before {\n  content: \"\\f25b\";\n}\n.am-icon-trademark:before {\n  content: \"\\f25c\";\n}\n.am-icon-registered:before {\n  content: \"\\f25d\";\n}\n.am-icon-creative-commons:before {\n  content: \"\\f25e\";\n}\n.am-icon-gg:before {\n  content: \"\\f260\";\n}\n.am-icon-gg-circle:before {\n  content: \"\\f261\";\n}\n.am-icon-tripadvisor:before {\n  content: \"\\f262\";\n}\n.am-icon-odnoklassniki:before {\n  content: \"\\f263\";\n}\n.am-icon-odnoklassniki-square:before {\n  content: \"\\f264\";\n}\n.am-icon-get-pocket:before {\n  content: \"\\f265\";\n}\n.am-icon-wikipedia-w:before {\n  content: \"\\f266\";\n}\n.am-icon-safari:before {\n  content: \"\\f267\";\n}\n.am-icon-chrome:before {\n  content: \"\\f268\";\n}\n.am-icon-firefox:before {\n  content: \"\\f269\";\n}\n.am-icon-opera:before {\n  content: \"\\f26a\";\n}\n.am-icon-internet-explorer:before {\n  content: \"\\f26b\";\n}\n.am-icon-tv:before,\n.am-icon-television:before {\n  content: \"\\f26c\";\n}\n.am-icon-contao:before {\n  content: \"\\f26d\";\n}\n.am-icon-500px:before {\n  content: \"\\f26e\";\n}\n.am-icon-amazon:before {\n  content: \"\\f270\";\n}\n.am-icon-calendar-plus-o:before {\n  content: \"\\f271\";\n}\n.am-icon-calendar-minus-o:before {\n  content: \"\\f272\";\n}\n.am-icon-calendar-times-o:before {\n  content: \"\\f273\";\n}\n.am-icon-calendar-check-o:before {\n  content: \"\\f274\";\n}\n.am-icon-industry:before {\n  content: \"\\f275\";\n}\n.am-icon-map-pin:before {\n  content: \"\\f276\";\n}\n.am-icon-map-signs:before {\n  content: \"\\f277\";\n}\n.am-icon-map-o:before {\n  content: \"\\f278\";\n}\n.am-icon-map:before {\n  content: \"\\f279\";\n}\n.am-icon-commenting:before {\n  content: \"\\f27a\";\n}\n.am-icon-commenting-o:before {\n  content: \"\\f27b\";\n}\n.am-icon-houzz:before {\n  content: \"\\f27c\";\n}\n.am-icon-vimeo:before {\n  content: \"\\f27d\";\n}\n.am-icon-black-tie:before {\n  content: \"\\f27e\";\n}\n.am-icon-fonticons:before {\n  content: \"\\f280\";\n}\n.am-icon-reddit-alien:before {\n  content: \"\\f281\";\n}\n.am-icon-edge:before {\n  content: \"\\f282\";\n}\n.am-icon-credit-card-alt:before {\n  content: \"\\f283\";\n}\n.am-icon-codiepie:before {\n  content: \"\\f284\";\n}\n.am-icon-modx:before {\n  content: \"\\f285\";\n}\n.am-icon-fort-awesome:before {\n  content: \"\\f286\";\n}\n.am-icon-usb:before {\n  content: \"\\f287\";\n}\n.am-icon-product-hunt:before {\n  content: \"\\f288\";\n}\n.am-icon-mixcloud:before {\n  content: \"\\f289\";\n}\n.am-icon-scribd:before {\n  content: \"\\f28a\";\n}\n.am-icon-pause-circle:before {\n  content: \"\\f28b\";\n}\n.am-icon-pause-circle-o:before {\n  content: \"\\f28c\";\n}\n.am-icon-stop-circle:before {\n  content: \"\\f28d\";\n}\n.am-icon-stop-circle-o:before {\n  content: \"\\f28e\";\n}\n.am-icon-shopping-bag:before {\n  content: \"\\f290\";\n}\n.am-icon-shopping-basket:before {\n  content: \"\\f291\";\n}\n.am-icon-hashtag:before {\n  content: \"\\f292\";\n}\n.am-icon-bluetooth:before {\n  content: \"\\f293\";\n}\n.am-icon-bluetooth-b:before {\n  content: \"\\f294\";\n}\n.am-icon-percent:before {\n  content: \"\\f295\";\n}\n/* Modifier: `am-icon-spin`\n============================================================================= */\n@-webkit-keyframes icon-spin {\n  0% {\n    -webkit-transform: rotate(0deg);\n            transform: rotate(0deg);\n  }\n  100% {\n    -webkit-transform: rotate(359deg);\n            transform: rotate(359deg);\n  }\n}\n@keyframes icon-spin {\n  0% {\n    -webkit-transform: rotate(0deg);\n            transform: rotate(0deg);\n  }\n  100% {\n    -webkit-transform: rotate(359deg);\n            transform: rotate(359deg);\n  }\n}\n.am-icon-spin {\n  -webkit-animation: icon-spin 2s infinite linear;\n          animation: icon-spin 2s infinite linear;\n}\n.am-icon-pulse {\n  -webkit-animation: icon-spin 1s infinite steps(8);\n          animation: icon-spin 1s infinite steps(8);\n}\n.am-icon-ul {\n  padding-left: 0;\n  margin-left: 2.14285714em;\n  list-style-type: none;\n}\n.am-icon-ul > li {\n  position: relative;\n}\n.am-icon-li {\n  position: absolute;\n  left: -2.14285714em;\n  width: 2.14285714em;\n  top: 0.14285714em;\n  text-align: center;\n}\n/* ==========================================================================\n   Component: Input group\n ============================================================================ */\n.am-input-group {\n  position: relative;\n  display: table;\n  border-collapse: separate;\n}\n.am-input-group .am-form-field {\n  position: relative;\n  z-index: 2;\n  float: left;\n  width: 100%;\n  margin-bottom: 0;\n}\n.am-input-group-label,\n.am-input-group-btn,\n.am-input-group .am-form-field {\n  display: table-cell;\n}\n.am-input-group-label:not(:first-child):not(:last-child),\n.am-input-group-btn:not(:first-child):not(:last-child),\n.am-input-group .am-form-field:not(:first-child):not(:last-child) {\n  border-radius: 0;\n}\n.am-input-group-label,\n.am-input-group-btn {\n  width: 1%;\n  white-space: nowrap;\n  vertical-align: middle;\n}\n.am-input-group-label {\n  height: 38px;\n  padding: 0 1em;\n  font-size: 1.6rem;\n  font-weight: normal;\n  line-height: 36px;\n  color: #555555;\n  text-align: center;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n  border-radius: 2px;\n}\n.am-input-group-label input[type=\"radio\"],\n.am-input-group-label input[type=\"checkbox\"] {\n  margin-top: 0;\n}\n.am-input-group .am-form-field:first-child,\n.am-input-group-label:first-child,\n.am-input-group-btn:first-child > .am-btn,\n.am-input-group-btn:first-child > .am-btn-group > .am-btn,\n.am-input-group-btn:first-child > .am-dropdown-toggle,\n.am-input-group-btn:last-child > .am-btn:not(:last-child):not(.dropdown-toggle),\n.am-input-group-btn:last-child > .am-btn-group:not(:last-child) > .am-btn {\n  border-bottom-right-radius: 0;\n  border-top-right-radius: 0;\n}\n.am-input-group-label:first-child {\n  border-right: 0;\n}\n.am-input-group .am-form-field:last-child,\n.am-input-group-label:last-child,\n.am-input-group-btn:last-child > .am-btn,\n.am-input-group-btn:last-child > .am-btn-group > .am-btn,\n.am-input-group-btn:last-child > .am-dropdown-toggle,\n.am-input-group-btn:first-child > .am-btn:not(:first-child),\n.am-input-group-btn:first-child > .am-btn-group:not(:first-child) > .am-btn {\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n}\n.am-input-group-label:last-child {\n  border-left: 0;\n}\n.am-input-group-btn {\n  position: relative;\n  font-size: 0;\n  white-space: nowrap;\n}\n.am-input-group-btn > .am-btn {\n  position: relative;\n  border-color: #ccc;\n}\n.am-input-group-btn > .am-btn + .am-btn {\n  margin-left: -1px;\n}\n.am-input-group-btn > .am-btn:hover,\n.am-input-group-btn > .am-btn:focus,\n.am-input-group-btn > .am-btn:active {\n  z-index: 2;\n}\n.am-input-group-btn:first-child > .am-btn,\n.am-input-group-btn:first-child > .am-btn-group {\n  margin-right: -2px;\n}\n.am-input-group-btn:last-child > .am-btn,\n.am-input-group-btn:last-child > .am-btn-group {\n  margin-left: -1px;\n}\n.am-input-group .am-form-field,\n.am-input-group-btn > .am-btn {\n  height: 38px;\n  padding-bottom: auto;\n}\n.am-input-group-lg > .am-form-field,\n.am-input-group-lg > .am-input-group-label,\n.am-input-group-lg > .am-input-group-btn > .am-btn {\n  height: 42px;\n  font-size: 1.8rem !important;\n}\n.am-input-group-lg > .am-input-group-label {\n  line-height: 40px;\n}\n.am-input-group-sm > .am-form-field,\n.am-input-group-sm > .am-input-group-label,\n.am-input-group-sm > .am-input-group-btn > .am-btn {\n  height: 33px;\n  font-size: 1.4rem !important;\n}\n.am-input-group-sm > .am-input-group-label {\n  line-height: 31px;\n}\n.am-input-group-primary .am-input-group-label {\n  background: #0e90d2;\n  color: #fff;\n}\n.am-input-group-primary .am-input-group-label,\n.am-input-group-primary .am-input-group-btn > .am-btn,\n.am-input-group-primary.am-input-group .am-form-field {\n  border-color: #0e90d2;\n}\n.am-input-group-secondary .am-input-group-label {\n  background: #3bb4f2;\n  color: #fff;\n}\n.am-input-group-secondary .am-input-group-label,\n.am-input-group-secondary .am-input-group-btn > .am-btn,\n.am-input-group-secondary.am-input-group .am-form-field {\n  border-color: #3bb4f2;\n}\n.am-input-group-success .am-input-group-label {\n  background: #5eb95e;\n  color: #fff;\n}\n.am-input-group-success .am-input-group-label,\n.am-input-group-success .am-input-group-btn > .am-btn,\n.am-input-group-success.am-input-group .am-form-field {\n  border-color: #5eb95e;\n}\n.am-input-group-warning .am-input-group-label {\n  background: #F37B1D;\n  color: #fff;\n}\n.am-input-group-warning .am-input-group-label,\n.am-input-group-warning .am-input-group-btn > .am-btn,\n.am-input-group-warning.am-input-group .am-form-field {\n  border-color: #F37B1D;\n}\n.am-input-group-danger .am-input-group-label {\n  background: #dd514c;\n  color: #fff;\n}\n.am-input-group-danger .am-input-group-label,\n.am-input-group-danger .am-input-group-btn > .am-btn,\n.am-input-group-danger.am-input-group .am-form-field {\n  border-color: #dd514c;\n}\n/* ==========================================================================\n   Component: List\n ============================================================================ */\n.am-list {\n  margin-bottom: 1.6rem;\n  padding-left: 0;\n}\n.am-list > li {\n  position: relative;\n  display: block;\n  margin-bottom: -1px;\n  background-color: #fff;\n  border: 1px solid #dedede;\n  border-width: 1px 0;\n}\n.am-list > li > a {\n  display: block;\n  padding: 1rem 0;\n}\n.am-list > li > a.am-active,\n.am-list > li > a.am-active:hover,\n.am-list > li > a.am-active:focus {\n  z-index: 2;\n  color: #fff;\n  background-color: #0e90d2;\n  border-color: #0e90d2;\n}\n.am-list > li > a.am-active .am-list-item-heading,\n.am-list > li > a.am-active:hover .am-list-item-heading,\n.am-list > li > a.am-active:focus .am-list-item-heading {\n  color: inherit;\n}\n.am-list > li > a.am-active .am-list-item-text,\n.am-list > li > a.am-active:hover .am-list-item-text,\n.am-list > li > a.am-active:focus .am-list-item-text {\n  color: #b2e2fa;\n}\n.am-list > li > .am-badge {\n  float: right;\n}\n.am-list > li > .am-badge + .am-badge {\n  margin-right: 5px;\n}\n/* Pure text list */\n.am-list-static > li {\n  padding: .8rem .2rem;\n}\n.am-list-static.am-list-border > li {\n  padding: 1rem;\n}\n/* with border */\n.am-list-border > li,\n.am-list-bordered > li {\n  border-width: 1px;\n}\n.am-list-border > li:first-child,\n.am-list-bordered > li:first-child,\n.am-list-border > li:first-child > a,\n.am-list-bordered > li:first-child > a {\n  border-top-right-radius: 2px;\n  border-top-left-radius: 2px;\n}\n.am-list-border > li:last-child,\n.am-list-bordered > li:last-child,\n.am-list-border > li:last-child > a,\n.am-list-bordered > li:last-child > a {\n  margin-bottom: 0;\n  border-bottom-right-radius: 2px;\n  border-bottom-left-radius: 2px;\n}\n.am-list-border > li > a,\n.am-list-bordered > li > a {\n  padding: 1rem;\n}\n.am-list-border > li > a:hover,\n.am-list-bordered > li > a:hover,\n.am-list-border > li > a:focus,\n.am-list-bordered > li > a:focus {\n  background-color: #f5f5f5;\n}\n/* Striped */\n.am-list-striped > li:nth-of-type(even) {\n  background: #f5f5f5;\n}\n.am-list-item-hd {\n  margin-top: 0;\n}\n.am-list-item-text {\n  line-height: 1.4;\n  font-size: 1.3rem;\n  color: #999999;\n  margin: 0;\n}\n/* ==========================================================================\n   Component: Panel\n ============================================================================ */\n.am-panel {\n  margin-bottom: 20px;\n  background-color: #fff;\n  border: 1px solid transparent;\n  border-radius: 2px;\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/* Panel header */\n.am-panel-hd {\n  padding: 0.6rem 1.25rem;\n  border-bottom: 1px solid transparent;\n  border-top-right-radius: 2px;\n  border-top-left-radius: 2px;\n}\n/* Panel content */\n.am-panel-bd {\n  padding: 1.25rem;\n}\n.am-panel-title {\n  margin: 0;\n  font-size: 100%;\n  color: inherit;\n}\n.am-panel-title > a {\n  color: inherit;\n}\n/* Panel footer */\n.am-panel-footer {\n  padding: 0.6rem 1.25rem;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  border-bottom-right-radius: 2px;\n  border-bottom-left-radius: 2px;\n}\n.am-panel-default {\n  border-color: #ddd;\n}\n.am-panel-default > .am-panel-hd {\n  color: #444;\n  background-color: #f5f5f5;\n  border-color: #ddd;\n}\n.am-panel-default > .am-panel-hd + .am-panel-collapse > .am-panel-bd {\n  border-top-color: #ddd;\n}\n.am-panel-default > .am-panel-footer + .am-panel-collapse > .am-panel-bd {\n  border-bottom-color: #ddd;\n}\n.am-panel-primary {\n  border-color: #10a0ea;\n}\n.am-panel-primary > .am-panel-hd {\n  color: #fff;\n  background-color: #0e90d2;\n  border-color: #10a0ea;\n}\n.am-panel-primary > .am-panel-hd + .am-panel-collapse > .am-panel-bd {\n  border-top-color: #10a0ea;\n}\n.am-panel-primary > .am-panel-footer + .am-panel-collapse > .am-panel-bd {\n  border-bottom-color: #10a0ea;\n}\n.am-panel-secondary {\n  border-color: #caebfb;\n}\n.am-panel-secondary > .am-panel-hd {\n  color: #14a6ef;\n  background-color: rgba(59, 180, 242, 0.15);\n  border-color: #caebfb;\n}\n.am-panel-secondary > .am-panel-hd + .am-panel-collapse > .am-panel-bd {\n  border-top-color: #caebfb;\n}\n.am-panel-secondary > .am-panel-footer + .am-panel-collapse > .am-panel-bd {\n  border-bottom-color: #caebfb;\n}\n.am-panel-success {\n  border-color: #c9e7c9;\n}\n.am-panel-success > .am-panel-hd {\n  color: #5eb95e;\n  background-color: rgba(94, 185, 94, 0.15);\n  border-color: #c9e7c9;\n}\n.am-panel-success > .am-panel-hd + .am-panel-collapse > .am-panel-bd {\n  border-top-color: #c9e7c9;\n}\n.am-panel-success > .am-panel-footer + .am-panel-collapse > .am-panel-bd {\n  border-bottom-color: #c9e7c9;\n}\n.am-panel-warning {\n  border-color: #fbd0ae;\n}\n.am-panel-warning > .am-panel-hd {\n  color: #F37B1D;\n  background-color: rgba(243, 123, 29, 0.15);\n  border-color: #fbd0ae;\n}\n.am-panel-warning > .am-panel-hd + .am-panel-collapse > .am-panel-bd {\n  border-top-color: #fbd0ae;\n}\n.am-panel-warning > .am-panel-footer + .am-panel-collapse > .am-panel-bd {\n  border-bottom-color: #fbd0ae;\n}\n.am-panel-danger {\n  border-color: #f5cecd;\n}\n.am-panel-danger > .am-panel-hd {\n  color: #dd514c;\n  background-color: rgba(221, 81, 76, 0.15);\n  border-color: #f5cecd;\n}\n.am-panel-danger > .am-panel-hd + .am-panel-collapse > .am-panel-bd {\n  border-top-color: #f5cecd;\n}\n.am-panel-danger > .am-panel-footer + .am-panel-collapse > .am-panel-bd {\n  border-bottom-color: #f5cecd;\n}\n.am-panel > .am-table {\n  margin-bottom: 0;\n}\n.am-panel > .am-table:first-child {\n  border-top-right-radius: 2px;\n  border-top-left-radius: 2px;\n}\n.am-panel > .am-table:first-child > thead:first-child > tr:first-child td:first-child,\n.am-panel > .am-table:first-child > tbody:first-child > tr:first-child td:first-child,\n.am-panel > .am-table:first-child > thead:first-child > tr:first-child th:first-child,\n.am-panel > .am-table:first-child > tbody:first-child > tr:first-child th:first-child {\n  border-top-left-radius: 2px;\n}\n.am-panel > .am-table:first-child > thead:first-child > tr:first-child td:last-child,\n.am-panel > .am-table:first-child > tbody:first-child > tr:first-child td:last-child,\n.am-panel > .am-table:first-child > thead:first-child > tr:first-child th:last-child,\n.am-panel > .am-table:first-child > tbody:first-child > tr:first-child th:last-child {\n  border-top-right-radius: 2px;\n}\n.am-panel > .am-table:last-child {\n  border-bottom-right-radius: 2px;\n  border-bottom-left-radius: 2px;\n}\n.am-panel > .am-table:last-child > tbody:last-child > tr:last-child td:first-child,\n.am-panel > .am-table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.am-panel > .am-table:last-child > tbody:last-child > tr:last-child th:first-child,\n.am-panel > .am-table:last-child > tfoot:last-child > tr:last-child th:first-child {\n  border-bottom-left-radius: 2px;\n}\n.am-panel > .am-table:last-child > tbody:last-child > tr:last-child td:last-child,\n.am-panel > .am-table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.am-panel > .am-table:last-child > tbody:last-child > tr:last-child th:last-child,\n.am-panel > .am-table:last-child > tfoot:last-child > tr:last-child th:last-child {\n  border-bottom-right-radius: 2px;\n}\n.am-panel > .am-panel-bd + .am-table {\n  border-top: 1px solid #ddd;\n}\n.am-panel > .am-table > tbody:first-child > tr:first-child th,\n.am-panel > .am-table > tbody:first-child > tr:first-child td {\n  border-top: 0;\n}\n.am-panel > .am-table-bd {\n  border: 0;\n}\n.am-panel > .am-table-bd > thead > tr > th:first-child,\n.am-panel > .am-table-bd > tbody > tr > th:first-child,\n.am-panel > .am-table-bd > tfoot > tr > th:first-child,\n.am-panel > .am-table-bd > thead > tr > td:first-child,\n.am-panel > .am-table-bd > tbody > tr > td:first-child,\n.am-panel > .am-table-bd > tfoot > tr > td:first-child {\n  border-left: 0;\n}\n.am-panel > .am-table-bd > thead > tr > th:last-child,\n.am-panel > .am-table-bd > tbody > tr > th:last-child,\n.am-panel > .am-table-bd > tfoot > tr > th:last-child,\n.am-panel > .am-table-bd > thead > tr > td:last-child,\n.am-panel > .am-table-bd > tbody > tr > td:last-child,\n.am-panel > .am-table-bd > tfoot > tr > td:last-child {\n  border-right: 0;\n}\n.am-panel > .am-table-bd > thead > tr:first-child > td,\n.am-panel > .am-table-bd > tbody > tr:first-child > td,\n.am-panel > .am-table-bd > thead > tr:first-child > th,\n.am-panel > .am-table-bd > tbody > tr:first-child > th {\n  border-bottom: 0;\n}\n.am-panel > .am-table-bd > tbody > tr:last-child > td,\n.am-panel > .am-table-bd > tfoot > tr:last-child > td,\n.am-panel > .am-table-bd > tbody > tr:last-child > th,\n.am-panel > .am-table-bd > tfoot > tr:last-child > th {\n  border-bottom: 0;\n}\n/* Wrap list */\n.am-panel > .am-list {\n  margin: 0;\n}\n.am-panel > .am-list > li > a {\n  padding-left: 1rem;\n  padding-right: 1rem;\n}\n.am-panel > .am-list-static li {\n  padding-left: 1rem;\n  padding-right: 1rem;\n}\n/* Panel group */\n.am-panel-group {\n  margin-bottom: 2rem;\n}\n.am-panel-group .am-panel {\n  margin-bottom: 0;\n  border-radius: 2px;\n}\n.am-panel-group .am-panel + .am-panel {\n  margin-top: 6px;\n}\n.am-panel-group .am-panel-hd {\n  border-bottom: 0;\n}\n.am-panel-group .am-panel-hd + .am-panel-collapse .am-panel-bd {\n  border-top: 1px solid #ddd;\n}\n.am-panel-group .am-panel-footer {\n  border-top: 0;\n}\n.am-panel-group .am-panel-footer + .am-panel-collapse .am-panel-bd {\n  border-bottom: 1px solid #ddd;\n}\n/* ==========================================================================\n   Component: Progress\n ============================================================================ */\n/* Progress bar animation */\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 36px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 36px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n/*  Progress container */\n.am-progress {\n  overflow: hidden;\n  height: 2rem;\n  margin-bottom: 2rem;\n  background-color: #f5f5f5;\n  border-radius: 2px;\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/* Progress bar */\n.am-progress-bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 1.2rem;\n  line-height: 2rem;\n  color: #fff;\n  text-align: center;\n  background-color: #0e90d2;\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 .6s ease;\n  transition: width .6s ease;\n}\n.am-progress-striped .am-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: 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  -webkit-background-size: 36px 36px;\n          background-size: 36px 36px;\n}\n.am-progress.am-active .am-progress-bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n.am-progress-bar[aria-valuenow=\"1\"],\n.am-progress-bar[aria-valuenow=\"2\"] {\n  min-width: 30px;\n}\n.am-progress-bar[aria-valuenow=\"0\"] {\n  color: #999999;\n  min-width: 30px;\n  background: none;\n  -webkit-box-shadow: none;\n          box-shadow: none;\n}\n.am-progress-bar-secondary {\n  background-color: #3bb4f2;\n}\n.am-progress-striped .am-progress-bar-secondary {\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: 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.am-progress-bar-success {\n  background-color: #5eb95e;\n}\n.am-progress-striped .am-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: 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.am-progress-bar-warning {\n  background-color: #F37B1D;\n}\n.am-progress-striped .am-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: 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.am-progress-bar-danger {\n  background-color: #dd514c;\n}\n.am-progress-striped .am-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: 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.am-progress-xs {\n  height: 0.6rem;\n}\n.am-progress-sm {\n  height: 1.2rem;\n}\n/* ==========================================================================\n   Component: Thumbnail\n ============================================================================ */\n.am-thumbnail {\n  display: block;\n  padding: 2px;\n  margin-bottom: 2rem;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  border-radius: 2px;\n  -webkit-transition: all 0.2s ease-in-out;\n  transition: all 0.2s ease-in-out;\n}\n.am-thumbnail > img,\n.am-thumbnail a > img {\n  margin-left: auto;\n  margin-right: auto;\n  display: block;\n}\n.am-thumbnail a.am-thumbnail:hover,\n.am-thumbnail a.am-thumbnail:focus,\n.am-thumbnail a.am-thumbnail.active {\n  border-color: #0e90d2;\n  background-color: #fff;\n}\nimg.am-thumbnail,\n.am-thumbnail > img,\n.am-thumbnail a > img {\n  max-width: 100%;\n  height: auto;\n}\n/* Image caption */\n.am-thumbnail-caption {\n  margin: 0;\n  padding: 0.8rem;\n  color: #333;\n  font-weight: normal;\n}\n.am-thumbnail-caption *:last-child {\n  margin-bottom: 0;\n}\n.am-thumbnails {\n  margin-left: -0.5rem;\n  margin-right: -0.5rem;\n}\n.am-thumbnails > li {\n  padding: 0 .5rem 1rem .5rem;\n}\n/* ==========================================================================\n   Component: Utility\n ============================================================================ */\n.am-scrollable-horizontal {\n  width: 100%;\n  overflow-y: hidden;\n  overflow-x: auto;\n  -ms-overflow-style: -ms-autohiding-scrollbar;\n  -webkit-overflow-scrolling: touch;\n}\n.am-scrollable-vertical {\n  height: 240px;\n  overflow-y: scroll;\n  -webkit-overflow-scrolling: touch;\n  resize: vertical;\n}\n/* Border-radius*/\n.am-square {\n  border-radius: 0;\n}\n.am-radius {\n  border-radius: 2px;\n}\n.am-round {\n  border-radius: 1000px;\n}\n.am-circle {\n  border-radius: 50%;\n}\n/* Float blocks*/\n.am-cf:before,\n.am-cf:after {\n  content: \" \";\n  display: table;\n}\n.am-cf:after {\n  clear: both;\n}\n.am-fl {\n  float: left;\n}\n.am-fr {\n  float: right;\n}\n.am-nbfc {\n  overflow: hidden;\n}\n.am-center {\n  display: block;\n  margin-left: auto;\n  margin-right: auto;\n}\n/* Display */\n.am-block {\n  display: block !important;\n}\n.am-inline {\n  display: inline !important;\n}\n.am-inline-block {\n  display: inline-block !important;\n}\n.am-hide {\n  display: none !important;\n  visibility: hidden !important;\n}\n/*\n* Remove whitespace between child elements when using `inline-block`\n*/\n.am-vertical-align {\n  font-size: 0.001px;\n}\n/*\n* The `@{ns}vertical-align` container needs a specific height\n*/\n.am-vertical-align:before {\n  content: '';\n  display: inline-block;\n  height: 100%;\n  vertical-align: middle;\n}\n/*\n* Sub-object which can have any height\n* 1. Reset whitespace hack\n*/\n.am-vertical-align-middle,\n.am-vertical-align-bottom {\n  display: inline-block;\n  font-size: 1.6rem;\n  /* 1 */\n  max-width: 100%;\n}\n.am-vertical-align-middle {\n  vertical-align: middle;\n}\n.am-vertical-align-bottom {\n  vertical-align: bottom;\n}\n.am-responsive-width {\n  -webkit-box-sizing: border-box;\n          box-sizing: border-box;\n  max-width: 100%;\n  height: auto;\n}\n/* Margin helpers */\n.am-margin {\n  margin: 1.6rem;\n}\n.am-margin-0 {\n  margin: 0!important;\n}\n.am-margin-xs {\n  margin: 0.5rem;\n}\n.am-margin-sm {\n  margin: 1rem;\n}\n.am-margin-lg {\n  margin: 2.4rem;\n}\n.am-margin-xl {\n  margin: 3.2rem;\n}\n.am-margin-horizontal {\n  margin-left: 1.6rem;\n  margin-right: 1.6rem;\n}\n.am-margin-horizontal-0 {\n  margin-left: 0!important;\n  margin-right: 0!important;\n}\n.am-margin-horizontal-xs {\n  margin-left: 0.5rem;\n  margin-right: 0.5rem;\n}\n.am-margin-horizontal-sm {\n  margin-left: 1rem;\n  margin-right: 1rem;\n}\n.am-margin-horizontal-lg {\n  margin-left: 2.4rem;\n  margin-right: 2.4rem;\n}\n.am-margin-horizontal-xl {\n  margin-left: 3.2rem;\n  margin-right: 3.2rem;\n}\n.am-margin-vertical {\n  margin-top: 1.6rem;\n  margin-bottom: 1.6rem;\n}\n.am-margin-vertical-0 {\n  margin-top: 0!important;\n  margin-bottom: 0!important;\n}\n.am-margin-vertical-xs {\n  margin-top: 0.5rem;\n  margin-bottom: 0.5rem;\n}\n.am-margin-vertical-sm {\n  margin-top: 1rem;\n  margin-bottom: 1rem;\n}\n.am-margin-vertical-lg {\n  margin-top: 2.4rem;\n  margin-bottom: 2.4rem;\n}\n.am-margin-vertical-xl {\n  margin-top: 3.2rem;\n  margin-bottom: 3.2rem;\n}\n.am-margin-top {\n  margin-top: 1.6rem;\n}\n.am-margin-top-0 {\n  margin-top: 0!important;\n}\n.am-margin-top-xs {\n  margin-top: 0.5rem;\n}\n.am-margin-top-sm {\n  margin-top: 1rem;\n}\n.am-margin-top-lg {\n  margin-top: 2.4rem;\n}\n.am-margin-top-xl {\n  margin-top: 3.2rem;\n}\n.am-margin-bottom {\n  margin-bottom: 1.6rem;\n}\n.am-margin-bottom-0 {\n  margin-bottom: 0!important;\n}\n.am-margin-bottom-xs {\n  margin-bottom: 0.5rem;\n}\n.am-margin-bottom-sm {\n  margin-bottom: 1rem;\n}\n.am-margin-bottom-lg {\n  margin-bottom: 2.4rem;\n}\n.am-margin-bottom-xl {\n  margin-bottom: 3.2rem;\n}\n.am-margin-left {\n  margin-left: 1.6rem;\n}\n.am-margin-left-0 {\n  margin-left: 0!important;\n}\n.am-margin-left-xs {\n  margin-left: 0.5rem;\n}\n.am-margin-left-sm {\n  margin-left: 1rem;\n}\n.am-margin-left-lg {\n  margin-left: 2.4rem;\n}\n.am-margin-left-xl {\n  margin-left: 3.2rem;\n}\n.am-margin-right {\n  margin-right: 1.6rem;\n}\n.am-margin-right-0 {\n  margin-right: 0!important;\n}\n.am-margin-right-xs {\n  margin-right: 0.5rem;\n}\n.am-margin-right-sm {\n  margin-right: 1rem;\n}\n.am-margin-right-lg {\n  margin-right: 2.4rem;\n}\n.am-margin-right-xl {\n  margin-right: 3.2rem;\n}\n/* Padding helpers */\n.am-padding {\n  padding: 1.6rem;\n}\n.am-padding-0 {\n  padding: 0!important;\n}\n.am-padding-xs {\n  padding: 0.5rem;\n}\n.am-padding-sm {\n  padding: 1rem;\n}\n.am-padding-lg {\n  padding: 2.4rem;\n}\n.am-padding-xl {\n  padding: 3.2rem;\n}\n.am-padding-horizontal {\n  padding-left: 1.6rem;\n  padding-right: 1.6rem;\n}\n.am-padding-horizontal-0 {\n  padding-left: 0!important;\n  padding-right: 0!important;\n}\n.am-padding-horizontal-xs {\n  padding-left: 0.5rem;\n  padding-right: 0.5rem;\n}\n.am-padding-horizontal-sm {\n  padding-left: 1rem;\n  padding-right: 1rem;\n}\n.am-padding-horizontal-lg {\n  padding-left: 2.4rem;\n  padding-right: 2.4rem;\n}\n.am-padding-horizontal-xl {\n  padding-left: 3.2rem;\n  padding-right: 3.2rem;\n}\n.am-padding-vertical {\n  padding-top: 1.6rem;\n  padding-bottom: 1.6rem;\n}\n.am-padding-vertical-0 {\n  padding-top: 0!important;\n  padding-bottom: 0!important;\n}\n.am-padding-vertical-xs {\n  padding-top: 0.5rem;\n  padding-bottom: 0.5rem;\n}\n.am-padding-vertical-sm {\n  padding-top: 1rem;\n  padding-bottom: 1rem;\n}\n.am-padding-vertical-lg {\n  padding-top: 2.4rem;\n  padding-bottom: 2.4rem;\n}\n.am-padding-vertical-xl {\n  padding-top: 3.2rem;\n  padding-bottom: 3.2rem;\n}\n.am-padding-top {\n  padding-top: 1.6rem;\n}\n.am-padding-top-0 {\n  padding-top: 0!important;\n}\n.am-padding-top-xs {\n  padding-top: 0.5rem;\n}\n.am-padding-top-sm {\n  padding-top: 1rem;\n}\n.am-padding-top-lg {\n  padding-top: 2.4rem;\n}\n.am-padding-top-xl {\n  padding-top: 3.2rem;\n}\n.am-padding-bottom {\n  padding-bottom: 1.6rem;\n}\n.am-padding-bottom-0 {\n  padding-bottom: 0!important;\n}\n.am-padding-bottom-xs {\n  padding-bottom: 0.5rem;\n}\n.am-padding-bottom-sm {\n  padding-bottom: 1rem;\n}\n.am-padding-bottom-lg {\n  padding-bottom: 2.4rem;\n}\n.am-padding-bottom-xl {\n  padding-bottom: 3.2rem;\n}\n.am-padding-left {\n  padding-left: 1.6rem;\n}\n.am-padding-left-0 {\n  padding-left: 0!important;\n}\n.am-padding-left-xs {\n  padding-left: 0.5rem;\n}\n.am-padding-left-sm {\n  padding-left: 1rem;\n}\n.am-padding-left-lg {\n  padding-left: 2.4rem;\n}\n.am-padding-left-xl {\n  padding-left: 3.2rem;\n}\n.am-padding-right {\n  padding-right: 1.6rem;\n}\n.am-padding-right-0 {\n  padding-right: 0!important;\n}\n.am-padding-right-xs {\n  padding-right: 0.5rem;\n}\n.am-padding-right-sm {\n  padding-right: 1rem;\n}\n.am-padding-right-lg {\n  padding-right: 2.4rem;\n}\n.am-padding-right-xl {\n  padding-right: 3.2rem;\n}\n/* small displays */\n@media only screen {\n  .am-show-sm-only,\n  .am-show-sm-up,\n  .am-show-sm,\n  .am-show-sm-down,\n  .am-hide-md-only,\n  .am-hide-md-up,\n  .am-hide-md,\n  .am-show-md-down,\n  .am-hide-lg-only,\n  .am-hide-lg-up,\n  .am-hide-lg,\n  .am-show-lg-down {\n    display: inherit !important;\n  }\n  .am-hide-sm-only,\n  .am-hide-sm-up,\n  .am-hide-sm,\n  .am-hide-sm-down,\n  .am-show-md-only,\n  .am-show-md-up,\n  .am-show-md,\n  .am-hide-md-down,\n  .am-show-lg-only,\n  .am-show-lg-up,\n  .am-show-lg,\n  .am-hide-lg-down {\n    display: none !important;\n  }\n  /* table */\n  table.am-show-sm-only,\n  table.am-show-sm-up,\n  table.am-show-sm,\n  table.am-show-sm-down,\n  table.am-hide-md-only,\n  table.am-hide-md-up,\n  table.am-hide-md,\n  table.am-show-md-down,\n  table.am-hide-lg-only,\n  table.am-hide-lg-up,\n  table.am-hide-lg,\n  table.am-show-lg-down {\n    display: table !important;\n  }\n  thead.am-show-sm-only,\n  thead.am-show-sm-up,\n  thead.am-show-sm,\n  thead.am-show-sm-down,\n  thead.am-hide-md-only,\n  thead.am-hide-md-up,\n  thead.am-hide-md,\n  thead.am-show-md-down,\n  thead.am-hide-lg-only,\n  thead.am-hide-lg-up,\n  thead.am-hide-lg,\n  thead.am-show-lg-down {\n    display: table-header-group !important;\n  }\n  tbody.am-show-sm-only,\n  tbody.am-show-sm-up,\n  tbody.am-show-sm,\n  tbody.am-show-sm-down,\n  tbody.am-hide-md-only,\n  tbody.am-hide-md-up,\n  tbody.am-hide-md,\n  tbody.am-show-md-down,\n  tbody.am-hide-lg-only,\n  tbody.am-hide-lg-up,\n  tbody.am-hide-lg,\n  tbody.am-show-lg-down {\n    display: table-row-group !important;\n  }\n  tr.am-show-sm-only,\n  tr.am-show-sm-up,\n  tr.am-show-sm,\n  tr.am-show-sm-down,\n  tr.am-hide-md-only,\n  tr.am-hide-md-up,\n  tr.am-hide-md,\n  tr.am-show-md-down,\n  tr.am-hide-lg-only,\n  tr.am-hide-lg-up,\n  tr.am-hide-lg,\n  tr.am-show-lg-down {\n    display: table-row !important;\n  }\n  th.am-show-sm-only,\n  td.am-show-sm-only,\n  th.am-show-sm-up,\n  td.am-show-sm-up,\n  th.am-show-sm,\n  td.am-show-sm,\n  th.am-show-sm-down,\n  td.am-show-sm-down,\n  th.am-hide-md-only,\n  td.am-hide-md-only,\n  th.am-hide-md-up,\n  td.am-hide-md-up,\n  th.am-hide-md,\n  td.am-hide-md,\n  th.am-show-md-down,\n  td.am-show-md-down,\n  th.am-hide-lg-only,\n  td.am-hide-lg-only,\n  th.am-hide-lg-up,\n  td.am-hide-lg-up,\n  th.am-hide-lg,\n  td.am-hide-lg,\n  th.am-show-lg-down,\n  td.am-show-lg-down {\n    display: table-cell !important;\n  }\n}\n/* medium displays */\n@media only screen and (min-width:641px) {\n  .am-hide-sm-only,\n  .am-show-sm-up,\n  .am-hide-sm,\n  .am-hide-sm-down,\n  .am-show-md-only,\n  .am-show-md-up,\n  .am-show-md,\n  .am-show-md-down,\n  .am-hide-lg-only,\n  .am-hide-lg-up,\n  .am-hide-lg,\n  .am-show-lg-down {\n    display: inherit !important;\n  }\n  .am-show-sm-only,\n  .am-hide-sm-up,\n  .am-show-sm,\n  .am-show-sm-down,\n  .am-hide-md-only,\n  .am-hide-md-up,\n  .am-hide-md,\n  .am-hide-md-down,\n  .am-show-lg-only,\n  .am-show-lg-up,\n  .am-show-lg,\n  .am-hide-lg-down {\n    display: none !important;\n  }\n  table.am-hide-sm-only,\n  table.am-show-sm-up,\n  table.am-hide-sm,\n  table.am-hide-sm-down,\n  table.am-show-md-only,\n  table.am-show-md-up,\n  table.am-show-md,\n  table.am-show-md-down,\n  table.am-hide-lg-only,\n  table.am-hide-lg-up,\n  table.am-hide-lg,\n  table.am-show-lg-down {\n    display: table !important;\n  }\n  thead.am-hide-sm-only,\n  thead.am-show-sm-up,\n  thead.am-hide-sm,\n  thead.am-hide-sm-down,\n  thead.am-show-md-only,\n  thead.am-show-md-up,\n  thead.am-show-md,\n  thead.am-show-md-down,\n  thead.am-hide-lg-only,\n  thead.am-hide-lg-up,\n  thead.am-hide-lg,\n  thead.am-show-lg-down {\n    display: table-header-group !important;\n  }\n  tbody.am-hide-sm-only,\n  tbody.am-show-sm-up,\n  tbody.am-hide-sm,\n  tbody.am-hide-sm-down,\n  tbody.am-show-md-only,\n  tbody.am-show-md-up,\n  tbody.am-show-md,\n  tbody.am-show-md-down,\n  tbody.am-hide-lg-only,\n  tbody.am-hide-lg-up,\n  tbody.am-hide-lg,\n  tbody.am-show-lg-down {\n    display: table-row-group !important;\n  }\n  tr.am-hide-sm-only,\n  tr.am-show-sm-up,\n  tr.am-hide-sm,\n  tr.am-hide-sm-down,\n  tr.am-show-md-only,\n  tr.am-show-md-up,\n  tr.am-show-md,\n  tr.am-show-md-down,\n  tr.am-hide-lg-only,\n  tr.am-hide-lg-up,\n  tr.am-hide-lg,\n  tr.am-show-lg-down {\n    display: table-row !important;\n  }\n  th.am-hide-sm-only,\n  td.am-hide-sm-only,\n  th.am-show-sm-up,\n  td.am-show-sm-up,\n  th.am-hide-sm,\n  td.am-hide-sm,\n  th.am-hide-sm-down,\n  td.am-hide-sm-down,\n  th.am-show-md-only,\n  td.am-show-md-only,\n  th.am-show-md-up,\n  td.am-show-md-up,\n  th.am-show-md,\n  td.am-show-md,\n  th.am-show-md-down,\n  td.am-show-md-down,\n  th.am-hide-lg-only,\n  td.am-hide-lg-only,\n  th.am-hide-lg-up,\n  td.am-hide-lg-up,\n  th.am-hide-lg,\n  td.am-hide-lg,\n  th.am-show-lg-down,\n  td.am-show-lg-down {\n    display: table-cell !important;\n  }\n}\n/* large displays */\n@media only screen and (min-width:1025px) {\n  .am-hide-sm-only,\n  .am-show-sm-up,\n  .am-hide-sm,\n  .am-hide-sm-down,\n  .am-hide-md-only,\n  .am-show-md-up,\n  .am-hide-md,\n  .am-hide-md-down,\n  .am-show-lg-only,\n  .am-show-lg-up,\n  .am-show-lg,\n  .am-show-lg-down {\n    display: inherit !important;\n  }\n  .am-show-sm-only,\n  .am-hide-sm-up,\n  .am-show-sm,\n  .am-show-sm-down,\n  .am-show-md-only,\n  .am-hide-md-up,\n  .am-show-md,\n  .am-show-md-down,\n  .am-hide-lg-only,\n  .am-hide-lg-up,\n  .am-hide-lg,\n  .am-hide-lg-down {\n    display: none !important;\n  }\n  table.am-hide-sm-only,\n  table.am-show-sm-up,\n  table.am-hide-sm,\n  table.am-hide-sm-down,\n  table.am-hide-md-only,\n  table.am-show-md-up,\n  table.am-hide-md,\n  table.am-hide-md-down,\n  table.am-show-lg-only,\n  table.am-show-lg-up,\n  table.am-show-lg,\n  table.am-show-lg-down {\n    display: table !important;\n  }\n  thead.am-hide-sm-only,\n  thead.am-show-sm-up,\n  thead.am-hide-sm,\n  thead.am-hide-sm-down,\n  thead.am-hide-md-only,\n  thead.am-show-md-up,\n  thead.am-hide-md,\n  thead.am-hide-md-down,\n  thead.am-show-lg-only,\n  thead.am-show-lg-up,\n  thead.am-show-lg,\n  thead.am-show-lg-down {\n    display: table-header-group !important;\n  }\n  tbody.am-hide-sm-only,\n  tbody.am-show-sm-up,\n  tbody.am-hide-sm,\n  tbody.am-hide-sm-down,\n  tbody.am-hide-md-only,\n  tbody.am-show-md-up,\n  tbody.am-hide-md,\n  tbody.am-hide-md-down,\n  tbody.am-show-lg-only,\n  tbody.am-show-lg-up,\n  tbody.am-show-lg,\n  tbody.am-show-lg-down {\n    display: table-row-group !important;\n  }\n  tr.am-hide-sm-only,\n  tr.am-show-sm-up,\n  tr.am-hide-sm,\n  tr.am-hide-sm-down,\n  tr.am-hide-md-only,\n  tr.am-show-md-up,\n  tr.am-hide-md,\n  tr.am-hide-md-down,\n  tr.am-show-lg-only,\n  tr.am-show-lg-up,\n  tr.am-show-lg,\n  tr.am-show-lg-down {\n    display: table-row !important;\n  }\n  th.am-hide-sm-only,\n  td.am-hide-sm-only,\n  th.am-show-sm-up,\n  td.am-show-sm-up,\n  th.am-hide-sm,\n  td.am-hide-sm,\n  th.am-hide-sm-down,\n  td.am-hide-sm-down,\n  th.am-hide-md-only,\n  td.am-hide-md-only,\n  th.am-show-md-up,\n  td.am-show-md-up,\n  th.am-hide-md,\n  td.am-hide-md,\n  th.am-hide-md-down,\n  td.am-hide-md-down,\n  th.am-show-lg-only,\n  td.am-show-lg-only,\n  th.am-show-lg-up,\n  td.am-show-lg-up,\n  th.am-show-lg,\n  td.am-show-lg,\n  th.am-show-lg-down,\n  td.am-show-lg-down {\n    display: table-cell !important;\n  }\n}\n@media only screen and (orientation: landscape) {\n  .am-show-landscape,\n  .am-hide-portrait {\n    display: inherit !important;\n  }\n  .am-hide-landscape,\n  .am-show-portrait {\n    display: none !important;\n  }\n}\n@media only screen and (orientation: portrait) {\n  .am-show-portrait,\n  .am-hide-landscape {\n    display: inherit !important;\n  }\n  .am-hide-portrait,\n  .am-show-landscape {\n    display: none !important;\n  }\n}\n.am-sans-serif {\n  font-family: \"Segoe UI\", \"Lucida Grande\", Helvetica, Arial, \"Microsoft YaHei\", FreeSans, Arimo, \"Droid Sans\", \"wenquanyi micro hei\", \"Hiragino Sans GB\", \"Hiragino Sans GB W3\", \"FontAwesome\", sans-serif;\n}\n.am-serif {\n  font-family: Georgia, \"Times New Roman\", Times, SimSun, \"FontAwesome\", serif;\n}\n.am-kai {\n  font-family: Georgia, \"Times New Roman\", Times, Kai, \"Kaiti SC\", KaiTi, BiauKai, \"FontAwesome\", serif;\n}\n.am-monospace {\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", \"FontAwesome\", monospace;\n}\n.am-text-primary {\n  color: #0e90d2;\n}\n.am-text-secondary {\n  color: #3bb4f2;\n}\n.am-text-success {\n  color: #5eb95e;\n}\n.am-text-warning {\n  color: #F37B1D;\n}\n.am-text-danger {\n  color: #dd514c;\n}\n.am-link-muted {\n  color: #666;\n}\n.am-link-muted a {\n  color: #666;\n}\n.am-link-muted:hover,\n.am-link-muted a:hover {\n  color: #555;\n}\n.am-text-default {\n  font-size: 1.6rem;\n}\n/*\n.@{ns}text-xxs {\n  font-size: @font-size-xxs;\n}\n*/\n.am-text-xs {\n  font-size: 1.2rem;\n}\n.am-text-sm {\n  font-size: 1.4rem;\n}\n.am-text-lg {\n  font-size: 1.8rem;\n}\n.am-text-xl {\n  font-size: 2.4rem;\n}\n.am-text-xxl {\n  font-size: 3.2rem;\n}\n.am-text-xxxl {\n  font-size: 4.2rem;\n}\n.am-ellipsis,\n.am-text-truncate {\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-text-break {\n  word-wrap: break-word;\n  -webkit-hyphens: auto;\n  -ms-hyphens: auto;\n  -moz-hyphens: auto;\n  hyphens: auto;\n}\n.am-text-nowrap {\n  white-space: nowrap;\n}\n[class*='am-align-'] {\n  margin-bottom: 1rem;\n}\n.am-align-left {\n  margin-right: 1rem;\n  float: left;\n}\n.am-align-right {\n  margin-left: 1rem;\n  float: right;\n}\n/** Only display content to screen readers\n * See: http://a11yproject.com/posts/how-to-hide-content/\n */\n.am-sr-only {\n  position: absolute;\n  width: 1px;\n  height: 1px;\n  margin: -1px;\n  padding: 0;\n  overflow: hidden;\n  clip: rect(0, 0, 0, 0);\n  border: 0;\n}\n/* Text Image Replacement */\n.am-text-ir {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n/* Text align */\n@media only screen {\n  .am-text-left {\n    text-align: left !important;\n  }\n  .am-text-right {\n    text-align: right !important;\n  }\n  .am-text-center {\n    text-align: center !important;\n  }\n  .am-text-justify {\n    text-align: justify !important;\n  }\n}\n@media only screen and (max-width: 640px) {\n  .am-sm-only-text-left {\n    text-align: left !important;\n  }\n  .am-sm-only-text-right {\n    text-align: right !important;\n  }\n  .am-sm-only-text-center {\n    text-align: center !important;\n  }\n  .am-sm-only-text-justify {\n    text-align: justify !important;\n  }\n}\n@media only screen and (min-width:641px) and (max-width:1024px) {\n  .am-md-only-text-left {\n    text-align: left !important;\n  }\n  .am-md-only-text-right {\n    text-align: right !important;\n  }\n  .am-md-only-text-center {\n    text-align: center !important;\n  }\n  .am-md-only-text-justify {\n    text-align: justify !important;\n  }\n}\n@media only screen and (min-width:641px) {\n  .am-md-text-left {\n    text-align: left !important;\n  }\n  .am-md-text-right {\n    text-align: right !important;\n  }\n  .am-md-text-center {\n    text-align: center !important;\n  }\n  .am-md-text-justify {\n    text-align: justify !important;\n  }\n}\n@media only screen and (min-width:1025px) {\n  .am-lg-text-left {\n    text-align: left !important;\n  }\n  .am-lg-text-right {\n    text-align: right !important;\n  }\n  .am-lg-text-center {\n    text-align: center !important;\n  }\n  .am-lg-text-justify {\n    text-align: justify !important;\n  }\n}\n.am-text-top {\n  vertical-align: top !important;\n}\n.am-text-middle {\n  vertical-align: middle !important;\n}\n.am-text-bottom {\n  vertical-align: bottom !important;\n}\n.am-angle {\n  position: absolute;\n}\n.am-angle:before,\n.am-angle:after {\n  position: absolute;\n  display: block;\n  content: \"\";\n  width: 0;\n  height: 0;\n  border: 8px dashed transparent;\n  z-index: 1;\n}\n.am-angle-up {\n  top: 0;\n}\n.am-angle-up:before,\n.am-angle-up:after {\n  border-bottom-style: solid;\n  border-width: 0 8px 8px;\n}\n.am-angle-up:before {\n  border-bottom-color: #ddd;\n  bottom: 0;\n}\n.am-angle-up:after {\n  border-bottom-color: #fff;\n  bottom: -1px;\n}\n.am-angle-down {\n  bottom: -9px;\n}\n.am-angle-down:before,\n.am-angle-down:after {\n  border-top-style: solid;\n  border-width: 8px 8px 0;\n}\n.am-angle-down:before {\n  border-top-color: #ddd;\n  bottom: 0;\n}\n.am-angle-down:after {\n  border-top-color: #fff;\n  bottom: 1px;\n}\n.am-angle-left {\n  left: -9px;\n}\n.am-angle-left:before,\n.am-angle-left:after {\n  border-right-style: solid;\n  border-width: 8px 8px 8px 0;\n}\n.am-angle-left:before {\n  border-right-color: #ddd;\n  left: 0;\n}\n.am-angle-left:after {\n  border-right-color: #fff;\n  left: 1px;\n}\n.am-angle-right {\n  right: 0;\n}\n.am-angle-right:before,\n.am-angle-right:after {\n  border-left-style: solid;\n  border-width: 8px 0 8px 8px;\n}\n.am-angle-right:before {\n  border-left-color: #ddd;\n  left: 0;\n}\n.am-angle-right:after {\n  border-left-color: #fff;\n  left: -1px;\n}\n/* ==========================================================================\n   Component: Alert Plugin\n ============================================================================ */\n.am-alert {\n  margin-bottom: 1em;\n  padding: 0.625em;\n  background: #0e90d2;\n  color: #fff;\n  border: 1px solid #0c7cb5;\n  border-radius: 2px;\n}\n.am-alert a {\n  color: #fff;\n}\n.am-alert h1,\n.am-alert h2,\n.am-alert h3,\n.am-alert h4,\n.am-alert h5,\n.am-alert h6 {\n  color: inherit;\n}\n.am-alert .am-close {\n  opacity: .4;\n}\n.am-alert .am-close:hover {\n  opacity: .6;\n}\n/* Add margin if adjacent element */\n* + .am-alert {\n  margin-top: 1em;\n}\n/* Remove margin from the last-child */\n.am-alert > :last-child {\n  margin-bottom: 0;\n}\n/* within am-form-group */\n.am-form-group .am-alert {\n  margin: 5px 0 0;\n  padding: 0.25em 0.625em;\n  font-size: 1.3rem;\n}\n/* Close in alert */\n.am-alert > .am-close:first-child {\n  float: right;\n  height: auto;\n  margin: -3px -5px auto auto;\n}\n/* Remove margin from adjacent element */\n.am-alert > .am-close:first-child + * {\n  margin-top: 0;\n}\n.am-alert-secondary {\n  background-color: #eeeeee;\n  border-color: #dfdfdf;\n  color: #555555;\n}\n.am-alert-success {\n  background-color: #5eb95e;\n  border-color: #4bad4b;\n  color: #fff;\n}\n.am-alert-warning {\n  background-color: #F37B1D;\n  border-color: #e56c0c;\n  color: #fff;\n}\n.am-alert-danger {\n  background-color: #dd514c;\n  border-color: #d83832;\n  color: #fff;\n}\n.am-dropdown {\n  position: relative;\n  display: inline-block;\n}\n.am-dropdown-toggle:focus {\n  outline: 0;\n}\n.am-dropdown-content {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1020;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 15px;\n  margin: 9px 0 0;\n  text-align: left;\n  line-height: 1.6;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  border-radius: 2px;\n  -webkit-background-clip: padding-box;\n          background-clip: padding-box;\n  -webkit-animation-duration: .15s;\n          animation-duration: .15s;\n}\n.am-dropdown-content:before,\n.am-dropdown-content:after {\n  position: absolute;\n  display: block;\n  content: \"\";\n  width: 0;\n  height: 0;\n  border: 8px dashed transparent;\n  z-index: 1;\n}\n.am-dropdown-content:before,\n.am-dropdown-content:after {\n  border-bottom-style: solid;\n  border-width: 0 8px 8px;\n}\n.am-dropdown-content:before {\n  border-bottom-color: #ddd;\n  bottom: 0;\n}\n.am-dropdown-content:after {\n  border-bottom-color: #fff;\n  bottom: -1px;\n}\n.am-dropdown-content:before,\n.am-dropdown-content:after {\n  left: 10px;\n  top: -8px;\n  pointer-events: none;\n}\n.am-dropdown-content:after {\n  top: -7px;\n}\n.am-active > .am-dropdown-content {\n  display: block;\n}\n.am-dropdown-content :first-child {\n  margin-top: 0;\n}\n.am-dropdown-up .am-dropdown-content {\n  top: auto;\n  bottom: 100%;\n  margin: 0 0 9px;\n}\n.am-dropdown-up .am-dropdown-content:before,\n.am-dropdown-up .am-dropdown-content:after {\n  border-bottom: none;\n  border-top: 8px solid #ddd;\n  top: auto;\n  bottom: -8px;\n}\n.am-dropdown-up .am-dropdown-content:after {\n  bottom: -7px;\n  border-top-color: #fff;\n}\n.am-dropdown-flip .am-dropdown-content {\n  left: auto;\n  right: 0;\n}\n.am-dropdown-flip .am-dropdown-content:before,\n.am-dropdown-flip .am-dropdown-content:after {\n  left: auto;\n  right: 10px;\n}\nul.am-dropdown-content {\n  list-style: none;\n  padding: 5px 0;\n}\nul.am-dropdown-content.am-fr {\n  right: 0;\n  left: auto;\n}\nul.am-dropdown-content .am-divider {\n  height: 1px;\n  margin: 0rem 0;\n  overflow: hidden;\n  background-color: #e5e5e5;\n}\nul.am-dropdown-content > li > a {\n  display: block;\n  padding: 6px 20px;\n  clear: both;\n  font-weight: normal;\n  color: #333333;\n  white-space: nowrap;\n}\nul.am-dropdown-content > li > a:hover,\nul.am-dropdown-content > li > a:focus {\n  text-decoration: none;\n  color: #262626;\n  background-color: #f5f5f5;\n}\nul.am-dropdown-content > .am-active > a,\nul.am-dropdown-content > .am-active > a:hover,\nul.am-dropdown-content > .am-active > a:focus {\n  color: #fff;\n  text-decoration: none;\n  outline: 0;\n  background-color: #0e90d2;\n}\nul.am-dropdown-content > .am-disabled > a,\nul.am-dropdown-content > .am-disabled > a:hover,\nul.am-dropdown-content > .am-disabled > a:focus {\n  color: #999999;\n}\nul.am-dropdown-content > .am-disabled > a:hover,\nul.am-dropdown-content > .am-disabled > a:focus {\n  text-decoration: none;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n  cursor: not-allowed;\n}\n.am-dropdown-header {\n  display: block;\n  padding: 6px 20px;\n  font-size: 1.2rem;\n  color: #999999;\n}\n.am-fr > .am-dropdown-content {\n  right: 0;\n  left: auto;\n}\n.am-fr > .am-dropdown-content:before {\n  right: 10px;\n  left: auto;\n}\n.am-dropdown-animation {\n  -webkit-animation: am-dropdown-animation 0.15s ease-out;\n          animation: am-dropdown-animation 0.15s ease-out;\n}\n@-webkit-keyframes am-dropdown-animation {\n  0% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n            transform: translateY(0);\n  }\n  100% {\n    opacity: 0;\n    -webkit-transform: translateY(-10px);\n            transform: translateY(-10px);\n  }\n}\n@keyframes am-dropdown-animation {\n  0% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n            transform: translateY(0);\n  }\n  100% {\n    opacity: 0;\n    -webkit-transform: translateY(-10px);\n            transform: translateY(-10px);\n  }\n}\n/* ==========================================================================\n   Component: Flex Slider Plugin\n ============================================================================ */\n.am-slider a:hover,\n.am-slider a:focus {\n  outline: none;\n}\n.am-slides,\n.am-control-nav,\n.am-direction-nav {\n  margin: 0;\n  padding: 0;\n  list-style: none;\n}\n.am-slider {\n  margin: 0;\n  padding: 0;\n}\n.am-slider .am-slides:before,\n.am-slider .am-slides:after {\n  content: \" \";\n  display: table;\n}\n.am-slider .am-slides:after {\n  clear: both;\n}\n.am-slider .am-slides > li {\n  display: none;\n  -webkit-backface-visibility: hidden;\n  position: relative;\n}\n.no-js .am-slider .am-slides > li:first-child {\n  display: block;\n}\n.am-slider .am-slides img {\n  width: 100%;\n  display: block;\n}\n.am-pauseplay span {\n  text-transform: capitalize;\n}\n.am-slider {\n  position: relative;\n}\n.am-viewport {\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.am-slider-carousel li {\n  margin-right: 5px;\n}\n.am-control-nav {\n  position: absolute;\n}\n.am-control-nav li {\n  display: inline-block;\n}\n.am-control-thumbs {\n  position: static;\n  overflow: hidden;\n}\n.am-control-thumbs img {\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.am-slider-slide .am-slides > li {\n  display: none;\n  position: relative;\n}\n@media all and (transform-3d), (-webkit-transform-3d) {\n  .am-slider-slide .am-slides > li {\n    -webkit-transition: -webkit-transform 0.6s ease-in-out;\n    transition: -webkit-transform 0.6s ease-in-out;\n    transition: transform 0.6s ease-in-out;\n    transition: transform 0.6s ease-in-out, -webkit-transform 0.6s ease-in-out;\n    -webkit-backface-visibility: hidden;\n            backface-visibility: hidden;\n    -webkit-perspective: 1000px;\n            perspective: 1000px;\n  }\n  .am-slider-slide .am-slides > li.next,\n  .am-slider-slide .am-slides > li.active.right {\n    -webkit-transform: translate3d(100%, 0, 0);\n            transform: translate3d(100%, 0, 0);\n    left: 0;\n  }\n  .am-slider-slide .am-slides > li.prev,\n  .am-slider-slide .am-slides > li.active.left {\n    -webkit-transform: translate3d(-100%, 0, 0);\n            transform: translate3d(-100%, 0, 0);\n    left: 0;\n  }\n  .am-slider-slide .am-slides > li.next.left,\n  .am-slider-slide .am-slides > li.prev.right,\n  .am-slider-slide .am-slides > li.active {\n    -webkit-transform: translate3d(0, 0, 0);\n            transform: translate3d(0, 0, 0);\n    left: 0;\n  }\n}\n.am-slider-slide .am-slides > .active,\n.am-slider-slide .am-slides > .next,\n.am-slider-slide .am-slides > .prev {\n  display: block;\n}\n.am-slider-slide .am-slides > .active {\n  left: 0;\n}\n.am-slider-slide .am-slides > .next,\n.am-slider-slide .am-slides > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n.am-slider-slide .am-slides > .next {\n  left: 100%;\n}\n.am-slider-slide .am-slides > .prev {\n  left: -100%;\n}\n.am-slider-slide .am-slides > .next.left,\n.am-slider-slide .am-slides > .prev.right {\n  left: 0;\n}\n.am-slider-slide .am-slides > .active.left {\n  left: -100%;\n}\n.am-slider-slide .am-slides > .active.right {\n  left: 100%;\n}\n/**\n  * Slider Theme: Default\n  */\n.am-slider-default {\n  margin: 0 0 20px;\n  background-color: #fff;\n  border-radius: 2px;\n  -webkit-box-shadow: 0 0 2px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 2px rgba(0, 0, 0, 0.15);\n  /* Direction Nav */\n  /* Pause/Play */\n  /* Control Nav */\n}\n.am-slider-default .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-default .am-viewport {\n  max-height: 300px;\n}\n.am-slider-default .carousel li {\n  margin-right: 5px;\n}\n.am-slider-default .am-direction-nav a {\n  position: absolute;\n  top: 50%;\n  z-index: 10;\n  display: block;\n  width: 36px;\n  height: 36px;\n  margin: -18px 0 0;\n  overflow: hidden;\n  opacity: 0.45;\n  cursor: pointer;\n  color: rgba(0, 0, 0, 0.65);\n  -webkit-transition: all .3s ease;\n  transition: all .3s ease;\n}\n.am-slider-default .am-direction-nav a:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  width: 100%;\n  color: #333333;\n  content: \"\\f137\";\n  font-size: 24px!important;\n  text-align: center;\n  line-height: 36px!important;\n  height: 36px;\n}\n.am-slider-default .am-direction-nav a.am-next:before {\n  content: \"\\f138\";\n}\n.am-slider-default .am-direction-nav .am-prev {\n  left: 10px;\n}\n.am-slider-default .am-direction-nav .am-next {\n  right: 10px;\n  text-align: right;\n}\n.am-slider-default .am-direction-nav .am-disabled {\n  opacity: 0!important;\n  cursor: default;\n}\n.am-slider-default:hover .am-prev {\n  opacity: 0.7;\n  left: 10px;\n}\n.am-slider-default:hover .am-prev:hover {\n  opacity: 1;\n}\n.am-slider-default:hover .am-next {\n  opacity: 0.7;\n  right: 10px;\n}\n.am-slider-default:hover .am-next:hover {\n  opacity: 1;\n}\n.am-slider-default .am-pauseplay a {\n  display: block;\n  width: 20px;\n  height: 20px;\n  position: absolute;\n  bottom: 5px;\n  left: 10px;\n  opacity: 0.8;\n  z-index: 10;\n  overflow: hidden;\n  cursor: pointer;\n  color: #000;\n}\n.am-slider-default .am-pauseplay a::before {\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  font-size: 20px;\n  display: inline-block;\n  content: \"\\f04c\";\n}\n.am-slider-default .am-pauseplay a:hover {\n  opacity: 1;\n}\n.am-slider-default .am-pauseplay a.am-play::before {\n  content: \"\\f04b\";\n}\n.am-slider-default .am-slider-desc {\n  background-color: rgba(0, 0, 0, 0.7);\n  position: absolute;\n  bottom: 0;\n  padding: 10px;\n  width: 100%;\n  color: #fff;\n}\n.am-slider-default .am-control-nav {\n  width: 100%;\n  position: absolute;\n  bottom: -15px;\n  text-align: center;\n}\n.am-slider-default .am-control-nav li {\n  margin: 0 6px;\n  display: inline-block;\n}\n.am-slider-default .am-control-nav li a {\n  width: 8px;\n  height: 8px;\n  display: block;\n  background-color: #666;\n  background-color: rgba(0, 0, 0, 0.5);\n  line-height: 0;\n  font-size: 0;\n  cursor: pointer;\n  text-indent: -9999px;\n  border-radius: 20px;\n  -webkit-box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);\n          box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);\n}\n.am-slider-default .am-control-nav li a:hover {\n  background-color: #333;\n  background-color: rgba(0, 0, 0, 0.7);\n}\n.am-slider-default .am-control-nav li a.am-active {\n  background-color: #000;\n  background-color: #0e90d2;\n  cursor: default;\n}\n.am-slider-default .am-control-thumbs {\n  margin: 5px 0 0;\n  position: static;\n  overflow: hidden;\n}\n.am-slider-default .am-control-thumbs li {\n  width: 25%;\n  float: left;\n  margin: 0;\n}\n.am-slider-default .am-control-thumbs img {\n  width: 100%;\n  height: auto;\n  display: block;\n  opacity: .7;\n  cursor: pointer;\n}\n.am-slider-default .am-control-thumbs img:hover {\n  opacity: 1;\n}\n.am-slider-default .am-control-thumbs .am-active {\n  opacity: 1;\n  cursor: default;\n}\n.am-slider-default .am-control-thumbs i {\n  position: absolute;\n}\n/*\nTODO:\n  1. 动画应该放在 dialog 上，不再是整个 modal，涉及 JS 逻辑，需要统筹修改\n  2. modal 滚动条处理，是否需要添加一个滚动条宽度的水平 padding？\n*/\n/* ==========================================================================\n   Component: Modal Plugin\n ============================================================================ */\n.am-modal {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1110;\n  display: none;\n  opacity: 0;\n  outline: 0;\n  text-align: center;\n  -webkit-transform: scale(1.185);\n      -ms-transform: scale(1.185);\n          transform: scale(1.185);\n  -webkit-transition-property: opacity, -webkit-transform;\n  transition-property: opacity, -webkit-transform;\n  transition-property: transform, opacity;\n  transition-property: transform, opacity, -webkit-transform;\n  -webkit-backface-visibility: hidden;\n          backface-visibility: hidden;\n  -webkit-perspective: 1000px;\n          perspective: 1000px;\n}\n.am-modal:focus {\n  outline: 0;\n}\n.am-modal.am-modal-active {\n  opacity: 1;\n  -webkit-transition-duration: 300ms;\n          transition-duration: 300ms;\n  -webkit-transform: scale(1);\n      -ms-transform: scale(1);\n          transform: scale(1);\n  overflow-x: hidden;\n  overflow-y: auto;\n}\n.am-modal.am-modal-out {\n  opacity: 0;\n  z-index: 1109;\n  -webkit-transition-duration: 300ms;\n          transition-duration: 300ms;\n  -webkit-transform: scale(0.815);\n      -ms-transform: scale(0.815);\n          transform: scale(0.815);\n}\n.am-modal:before {\n  content: \"\\200B\";\n  display: inline-block;\n  height: 100%;\n  vertical-align: middle;\n}\n.am-modal-dialog {\n  position: relative;\n  display: inline-block;\n  vertical-align: middle;\n  margin-left: auto;\n  margin-right: auto;\n  width: 270px;\n  max-width: 100%;\n  border-radius: 2px;\n  background: #f8f8f8;\n  /*@media @large-up {\n    width: @modal-lg;\n    margin-left: -@modal-lg/2;\n  }*/\n}\n@media only screen and (min-width:641px) {\n  .am-modal-dialog {\n    width: 540px;\n  }\n}\n.am-modal-hd {\n  padding: 15px 10px 5px 10px;\n  font-size: 1.8rem;\n  font-weight: 500;\n}\n.am-modal-hd + .am-modal-bd {\n  padding-top: 0;\n}\n.am-modal-hd .am-close {\n  position: absolute;\n  top: 4px;\n  right: 4px;\n}\n.am-modal-bd {\n  padding: 15px 10px;\n  text-align: center;\n  border-bottom: 1px solid #dedede;\n  border-radius: 2px 2px 0 0;\n}\n.am-modal-bd + .am-modal-bd {\n  margin-top: 5px;\n}\n.am-modal-prompt-input {\n  display: block;\n  margin: 5px auto 0 auto;\n  border-radius: 2px;\n  padding: 5px;\n  line-height: 1.8rem;\n  width: 80%;\n  border: 1px solid #dedede;\n  -webkit-appearance: none;\n  -moz-appearance: none;\n  -ms-appearance: none;\n  appearance: none;\n}\n.am-modal-prompt-input:focus {\n  outline: none;\n  border-color: #d6d6d6;\n}\n.am-modal-footer {\n  height: 44px;\n  overflow: hidden;\n  display: table;\n  width: 100%;\n  border-collapse: collapse;\n}\n.am-modal-btn {\n  display: table-cell !important;\n  padding: 0 5px;\n  height: 44px;\n  -webkit-box-sizing: border-box !important;\n          box-sizing: border-box !important;\n  font-size: 1.6rem;\n  line-height: 44px;\n  text-align: center;\n  color: #0e90d2;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n  cursor: pointer;\n  border-right: 1px solid #dedede;\n}\n.am-modal-btn:first-child {\n  border-radius: 0 0 0 2px;\n}\n.am-modal-btn:last-child {\n  border-right: none;\n  border-radius: 0 0 2px 0;\n}\n.am-modal-btn:first-child:last-child {\n  border-radius: 0 0 2px 2px;\n}\n.am-modal-btn.am-modal-btn-bold {\n  font-weight: 500;\n}\n.am-modal-btn:active {\n  background: #d4d4d4;\n}\n.am-modal-btn + .am-modal-btn {\n  border-left: 1px solid #dedede;\n}\n.am-modal-no-btn .am-modal-dialog {\n  border-radius: 2px;\n  border-bottom: none;\n}\n.am-modal-no-btn .am-modal-bd {\n  border-bottom: none;\n}\n.am-modal-no-btn .am-modal-footer {\n  display: none;\n}\n.am-modal-loading .am-modal-bd {\n  border-bottom: none;\n}\n.am-modal-loading .am-icon-spin {\n  display: inline-block;\n  font-size: 2.4rem;\n}\n.am-modal-loading .am-modal-footer {\n  display: none;\n}\n.am-modal-actions {\n  position: fixed;\n  left: 0;\n  bottom: 0;\n  z-index: 1110;\n  width: 100%;\n  max-height: 100%;\n  overflow-x: hidden;\n  overflow-y: auto;\n  text-align: center;\n  border-radius: 2px;\n  -webkit-transform: translateY(100%);\n      -ms-transform: translateY(100%);\n          transform: translateY(100%);\n  -webkit-transition: -webkit-transform 300ms;\n  transition: -webkit-transform 300ms;\n  transition: transform 300ms;\n  transition: transform 300ms, -webkit-transform 300ms;\n}\n.am-modal-actions.am-modal-active {\n  -webkit-transform: translateY(0);\n      -ms-transform: translateY(0);\n          transform: translateY(0);\n}\n.am-modal-actions.am-modal-out {\n  z-index: 1109;\n  -webkit-transform: translateY(100%);\n      -ms-transform: translateY(100%);\n          transform: translateY(100%);\n}\n.am-modal-actions-group {\n  margin: 10px;\n}\n.am-modal-actions-group .am-list {\n  margin: 0;\n  border-radius: 2px;\n}\n.am-modal-actions-group .am-list > li {\n  margin-bottom: 0;\n  border-bottom: none;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n  -webkit-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.015);\n          box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.015);\n}\n.am-modal-actions-group .am-list > li > a {\n  padding: 1rem;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-modal-actions-group .am-list > li:first-child {\n  border-top: none;\n  border-top-right-radius: 2px;\n  border-top-left-radius: 2px;\n}\n.am-modal-actions-group .am-list > li:last-child {\n  border-bottom: none;\n  border-bottom-right-radius: 2px;\n  border-bottom-left-radius: 2px;\n}\n.am-modal-actions-header {\n  padding: 1rem;\n  color: #999999;\n  font-size: 1.4rem;\n}\n.am-modal-actions-danger {\n  color: #dd514c;\n}\n.am-modal-actions-danger a {\n  color: inherit;\n}\n.am-popup {\n  position: fixed;\n  left: 0;\n  top: 0;\n  width: 100%;\n  height: 100%;\n  z-index: 1110;\n  background: #fff;\n  display: none;\n  overflow: hidden;\n  -webkit-transition-property: -webkit-transform;\n  transition-property: -webkit-transform;\n  transition-property: transform;\n  transition-property: transform, -webkit-transform;\n  -webkit-transform: translateY(100%);\n      -ms-transform: translateY(100%);\n          transform: translateY(100%);\n}\n.am-popup.am-modal-active,\n.am-popup.am-modal-out {\n  -webkit-transition-duration: 300ms;\n          transition-duration: 300ms;\n}\n.am-popup.am-modal-active {\n  -webkit-transform: translateY(0);\n      -ms-transform: translateY(0);\n          transform: translateY(0);\n}\n.am-popup.am-modal-out {\n  -webkit-transform: translateY(100%);\n      -ms-transform: translateY(100%);\n          transform: translateY(100%);\n}\n@media all and (min-width: 630px) and (min-height: 630px) {\n  .am-popup {\n    width: 630px;\n    height: 630px;\n    left: 50%;\n    top: 50%;\n    margin-left: -315px;\n    margin-top: -315px;\n    -webkit-transform: translateY(1024px);\n        -ms-transform: translateY(1024px);\n            transform: translateY(1024px);\n  }\n  .am-popup.am-modal-active {\n    -webkit-transform: translateY(0);\n        -ms-transform: translateY(0);\n            transform: translateY(0);\n  }\n  .am-popup.am-modal-out {\n    -webkit-transform: translateY(1024px);\n        -ms-transform: translateY(1024px);\n            transform: translateY(1024px);\n  }\n}\n.am-popup-inner {\n  padding-top: 44px;\n  height: 100%;\n  overflow: auto;\n  -webkit-overflow-scrolling: touch;\n}\n.am-popup-hd {\n  position: absolute;\n  top: 0;\n  z-index: 1000;\n  width: 100%;\n  height: 43px;\n  border-bottom: 1px solid #dedede;\n  background-color: #fff;\n}\n.am-popup-hd .am-popup-title {\n  font-size: 1.8rem;\n  font-weight: bold;\n  line-height: 43px;\n  text-align: center;\n  margin: 0 30px;\n  color: #333333;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-popup-hd .am-close {\n  position: absolute;\n  right: 10px;\n  top: 8px;\n  cursor: pointer;\n  -webkit-transition: all 0.3s;\n  transition: all 0.3s;\n  color: #999999;\n}\n.am-popup-hd .am-close:hover {\n  -webkit-transform: rotate(360deg);\n      -ms-transform: rotate(360deg);\n          transform: rotate(360deg);\n  color: #555555;\n}\n.am-popup-bd {\n  padding: 15px;\n  background: #f8f8f8;\n  color: #555555;\n}\n/* ==========================================================================\n   Component: OffCanvas Plugin\n ============================================================================ */\n/* Off-canvas overlay and bar container */\n.am-offcanvas {\n  display: none;\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1090;\n  background: rgba(0, 0, 0, 0.15);\n}\n.am-offcanvas.am-active {\n  display: block;\n}\n/**\n * .@{ns}offcanvas-page\n *\n * Prepares the whole HTML page to slide-out\n * 1. Fix the main page and disallow scrolling\n * 2. Side-out transition\n */\n.am-offcanvas-page {\n  position: fixed;\n  /* 1 */\n  -webkit-transition: margin-left 0.3s ease-in-out;\n  transition: margin-left 0.3s ease-in-out;\n  /* 2 */\n}\n/* Sub-object .@{ns}offcanvas-bar */\n.am-offcanvas-bar {\n  position: fixed;\n  top: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1091;\n  width: 270px;\n  max-width: 100%;\n  background: #333;\n  overflow-y: auto;\n  /* scrollable */\n  -webkit-overflow-scrolling: touch;\n  /* scrollable */\n  -webkit-transition: -webkit-transform 0.3s ease-in-out;\n  transition: -webkit-transform 0.3s ease-in-out;\n  transition: transform 0.3s ease-in-out;\n  transition: transform 0.3s ease-in-out, -webkit-transform 0.3s ease-in-out;\n  -webkit-transform: translateX(-100%);\n      -ms-transform: translateX(-100%);\n          transform: translateX(-100%);\n}\n.am-offcanvas-bar:after {\n  content: \"\";\n  display: block;\n  position: absolute;\n  top: 0;\n  bottom: 0;\n  right: 0;\n  width: 1px;\n  background: #262626;\n}\n.am-offcanvas.am-active .am-offcanvas-bar.am-offcanvas-bar-active {\n  -webkit-transform: translateX(0);\n      -ms-transform: translateX(0);\n          transform: translateX(0);\n}\n/* .@{ns}offcanvas-bar-flip */\n.am-offcanvas-bar-flip {\n  left: auto;\n  right: 0;\n  -webkit-transform: translateX(100%);\n      -ms-transform: translateX(100%);\n          transform: translateX(100%);\n}\n.am-offcanvas-bar-flip:after {\n  right: auto;\n  left: 0;\n}\n.am-offcanvas-content {\n  padding: 15px;\n  color: #999;\n}\n.am-offcanvas-content a {\n  color: #ccc;\n}\n/* ==========================================================================\n   Component: Popover Plugin\n ============================================================================ */\n.am-popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  margin: 0;\n  border-radius: 2px;\n  background: #333333;\n  color: #fff;\n  border: 1px solid #333333;\n  display: none;\n  font-size: 1.6rem;\n  z-index: 1030;\n  opacity: 0;\n  -webkit-transition: opacity 300ms;\n  transition: opacity 300ms;\n}\n.am-popover.am-active {\n  display: block !important;\n  opacity: 1;\n}\n.am-popover-inner {\n  position: relative;\n  background: #333333;\n  padding: 8px;\n  z-index: 110;\n}\n.am-popover-caret {\n  position: absolute;\n  top: 0;\n  z-index: 100;\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: middle;\n  border-bottom: 8px solid #333333;\n  border-right: 8px solid transparent;\n  border-left: 8px solid transparent;\n  border-top: 0 dotted;\n  -webkit-transform: rotate(360deg);\n      -ms-transform: rotate(360deg);\n          transform: rotate(360deg);\n  overflow: hidden;\n}\n.am-popover-top .am-popover-caret {\n  top: auto;\n  bottom: -8px;\n  -webkit-transform: rotate(180deg);\n      -ms-transform: rotate(180deg);\n          transform: rotate(180deg);\n}\n.am-popover-bottom .am-popover-caret {\n  top: -8px;\n}\n.am-popover-top .am-popover-caret,\n.am-popover-bottom .am-popover-caret {\n  left: 50%;\n  margin-left: -8px;\n}\n.am-popover-left .am-popover-caret {\n  top: auto;\n  left: auto;\n  right: -12px;\n  -webkit-transform: rotate(90deg);\n      -ms-transform: rotate(90deg);\n          transform: rotate(90deg);\n}\n.am-popover-right .am-popover-caret {\n  right: auto;\n  left: -12px;\n  -webkit-transform: rotate(-90deg);\n      -ms-transform: rotate(-90deg);\n          transform: rotate(-90deg);\n}\n.am-popover-left .am-popover-caret,\n.am-popover-right .am-popover-caret {\n  top: 50%;\n  margin-top: -4px;\n}\n.am-popover-sm {\n  font-size: 1.4rem;\n}\n.am-popover-sm .am-popover-inner {\n  padding: 5px;\n}\n.am-popover-lg {\n  font-size: 1.8rem;\n}\n.am-popover-primary {\n  border-color: #0e90d2;\n}\n.am-popover-primary .am-popover-inner {\n  background: #0e90d2;\n}\n.am-popover-primary .am-popover-caret {\n  border-bottom-color: #0e90d2;\n}\n.am-popover-secondary {\n  border-color: #3bb4f2;\n}\n.am-popover-secondary .am-popover-inner {\n  background: #3bb4f2;\n}\n.am-popover-secondary .am-popover-caret {\n  border-bottom-color: #3bb4f2;\n}\n.am-popover-success {\n  border-color: #5eb95e;\n}\n.am-popover-success .am-popover-inner {\n  background: #5eb95e;\n}\n.am-popover-success .am-popover-caret {\n  border-bottom-color: #5eb95e;\n}\n.am-popover-warning {\n  border-color: #F37B1D;\n}\n.am-popover-warning .am-popover-inner {\n  background: #F37B1D;\n}\n.am-popover-warning .am-popover-caret {\n  border-bottom-color: #F37B1D;\n}\n.am-popover-danger {\n  border-color: #dd514c;\n}\n.am-popover-danger .am-popover-inner {\n  background: #dd514c;\n}\n.am-popover-danger .am-popover-caret {\n  border-bottom-color: #dd514c;\n}\n/* ==========================================================================\n   Component: Progress Plugin\n ============================================================================ */\n#nprogress {\n  /* Make clicks pass-through */\n  pointer-events: none;\n  /* Fancy blur effect */\n}\n#nprogress .nprogress-bar {\n  position: fixed;\n  top: 0;\n  left: 0;\n  z-index: 2000;\n  width: 100%;\n  height: 2px;\n  background: #5eb95e;\n}\n#nprogress .nprogress-peg {\n  display: block;\n  position: absolute;\n  right: 0;\n  width: 100px;\n  height: 100%;\n  -webkit-box-shadow: 0 0 10px #5eb95e, 0 0 5px #5eb95e;\n          box-shadow: 0 0 10px #5eb95e, 0 0 5px #5eb95e;\n  opacity: 1;\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#nprogress .nprogress-spinner {\n  position: fixed;\n  top: 15px;\n  right: 15px;\n  z-index: 2000;\n  display: block;\n}\n#nprogress .nprogress-spinner-icon {\n  width: 18px;\n  height: 18px;\n  -webkit-box-sizing: border-box;\n          box-sizing: border-box;\n  border: solid 2px transparent;\n  border-top-color: #5eb95e;\n  border-left-color: #5eb95e;\n  border-radius: 50%;\n  -webkit-animation: nprogress-spinner 400ms linear infinite;\n          animation: nprogress-spinner 400ms linear infinite;\n}\n@-webkit-keyframes nprogress-spinner {\n  0% {\n    -webkit-transform: rotate(0deg);\n            transform: rotate(0deg);\n  }\n  100% {\n    -webkit-transform: rotate(360deg);\n            transform: rotate(360deg);\n  }\n}\n@keyframes nprogress-spinner {\n  0% {\n    -webkit-transform: rotate(0deg);\n            transform: rotate(0deg);\n  }\n  100% {\n    -webkit-transform: rotate(360deg);\n            transform: rotate(360deg);\n  }\n}\n/* ==========================================================================\n   Component: Tabs Plugin\n ============================================================================ */\n.am-tabs-bd {\n  position: relative;\n  overflow: hidden;\n  border: 1px solid #ddd;\n  border-top: none;\n  z-index: 100;\n  -webkit-transition: height .3s;\n  transition: height .3s;\n}\n.am-tabs-bd:before,\n.am-tabs-bd:after {\n  content: \" \";\n  display: table;\n}\n.am-tabs-bd:after {\n  clear: both;\n}\n.am-tabs-bd .am-tab-panel {\n  position: absolute;\n  top: 0;\n  z-index: 99;\n  float: left;\n  width: 100%;\n  padding: 10px 10px 15px;\n  visibility: hidden;\n  -webkit-transition: -webkit-transform 0.3s;\n  transition: -webkit-transform 0.3s;\n  transition: transform 0.3s;\n  transition: transform 0.3s, -webkit-transform 0.3s;\n  -webkit-transform: translateX(-100%);\n      -ms-transform: translateX(-100%);\n          transform: translateX(-100%);\n}\n.am-tabs-bd .am-tab-panel * {\n  -webkit-user-drag: none;\n}\n.am-tabs-bd .am-tab-panel.am-active {\n  position: relative;\n  z-index: 100;\n  visibility: visible;\n  -webkit-transform: translateX(0);\n      -ms-transform: translateX(0);\n          transform: translateX(0);\n}\n.am-tabs-bd .am-tab-panel.am-active ~ .am-tab-panel {\n  -webkit-transform: translateX(100%);\n      -ms-transform: translateX(100%);\n          transform: translateX(100%);\n}\n.am-tabs-bd .am-tabs-bd {\n  border: none;\n}\n.am-tabs-bd-ofv {\n  overflow: visible;\n}\n.am-tabs-fade .am-tab-panel {\n  opacity: 0;\n  -webkit-transition: opacity .25s linear;\n  transition: opacity .25s linear;\n}\n.am-tabs-fade .am-tab-panel.am-in {\n  opacity: 1;\n}\n/* ==========================================================================\n   Component: Share Plugin\n ============================================================================ */\n.am-share {\n  font-size: 14px;\n}\n.am-share-title {\n  padding: 10px 0 0;\n  margin: 0 10px;\n  font-weight: normal;\n  text-align: center;\n  color: #555555;\n  background-color: #f8f8f8;\n  border-bottom: 1px solid #fff;\n  border-top-right-radius: 2px;\n  border-top-left-radius: 2px;\n}\n.am-share-title:after {\n  content: \"\";\n  display: block;\n  width: 100%;\n  height: 0;\n  margin-top: 10px;\n  border-bottom: 1px solid #dfdfdf;\n}\n.am-share-sns {\n  margin: 0 10px;\n  padding-top: 15px;\n  background-color: #f8f8f8;\n  border-bottom-right-radius: 2px;\n  border-bottom-left-radius: 2px;\n}\n.am-share-sns li {\n  margin-bottom: 15px;\n}\n.am-share-sns a {\n  display: block;\n  color: #555555;\n}\n.am-share-sns span {\n  display: block;\n}\n.am-share-sns [class*='am-icon'] {\n  background-color: #3bb4f2;\n  border-radius: 50%;\n  width: 36px;\n  height: 36px;\n  line-height: 36px;\n  color: #fff;\n  margin-bottom: 5px;\n  font-size: 18px;\n}\n.am-share-sns .am-icon-weibo {\n  background-color: #ea1328;\n}\n.am-share-sns .am-icon-qq {\n  background-color: #009cda;\n}\n.am-share-sns .am-icon-star {\n  background-color: #ffc028;\n}\n.am-share-sns .am-icon-tencent-weibo {\n  background-color: #23ccfe;\n}\n.am-share-sns .am-icon-wechat,\n.am-share-sns .am-icon-weixin {\n  background-color: #44b549;\n}\n.am-share-sns .am-icon-renren {\n  background-color: #105ba3;\n}\n.am-share-sns .am-icon-comment {\n  background-color: #5eb95e;\n}\n.am-share-footer {\n  margin: 10px;\n}\n.am-share-footer .am-btn {\n  color: #555555;\n}\n.am-share-wechat-qr {\n  font-size: 14px;\n  color: #777;\n}\n.am-share-wechat-qr .am-modal-dialog {\n  background-color: #fff;\n  border: 1px solid #dedede;\n}\n.am-share-wechat-qr .am-modal-hd {\n  padding-top: 10px;\n  text-align: left;\n  margin-bottom: 10px;\n}\n.am-share-wechat-qr .am-share-wx-qr {\n  margin-bottom: 10px;\n}\n.am-share-wechat-qr .am-share-wechat-tip {\n  text-align: left;\n}\n.am-share-wechat-qr .am-share-wechat-tip em {\n  color: #dd514c;\n  font-weight: bold;\n  font-style: normal;\n  margin-left: 3px;\n  margin-right: 3px;\n}\n/* ==========================================================================\n   Component: PureView Plugin\n ============================================================================ */\n.am-pureview {\n  position: fixed;\n  left: 0;\n  top: 0;\n  bottom: 0;\n  right: 0;\n  z-index: 1120;\n  width: 100%;\n  height: 100%;\n  background: rgba(0, 0, 0, 0.95);\n  display: none;\n  overflow: hidden;\n  -webkit-transition: -webkit-transform .3s;\n  transition: -webkit-transform .3s;\n  transition: transform .3s;\n  transition: transform .3s, -webkit-transform .3s;\n  -webkit-transform: translate(0, 100%);\n      -ms-transform: translate(0, 100%);\n          transform: translate(0, 100%);\n}\n.am-pureview.am-active {\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n}\n.am-pureview ul,\n.am-pureview ol {\n  list-style: none;\n  padding: 0;\n  margin: 0;\n  width: 100%;\n}\n.am-pureview-slider {\n  overflow: hidden;\n  height: 100%;\n}\n.am-pureview-slider li {\n  position: absolute;\n  width: 100%;\n  height: 100%;\n  top: 0;\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -ms-flexbox;\n  display: flex;\n  -webkit-box-pack: center;\n  -webkit-justify-content: center;\n      -ms-flex-pack: center;\n          justify-content: center;\n  -webkit-box-align: center;\n  -webkit-align-items: center;\n      -ms-flex-align: center;\n          align-items: center;\n  vertical-align: middle;\n  -webkit-transition: all .3s linear;\n  transition: all .3s linear;\n  z-index: 100;\n  visibility: hidden;\n}\n.am-pureview-slider li.am-pureview-slide-prev {\n  -webkit-transform: translate(-100%, 0);\n      -ms-transform: translate(-100%, 0);\n          transform: translate(-100%, 0);\n  z-index: 109;\n}\n.am-pureview-slider li.am-pureview-slide-next {\n  -webkit-transform: translate(100%, 0);\n      -ms-transform: translate(100%, 0);\n          transform: translate(100%, 0);\n  z-index: 109;\n}\n.am-pureview-slider li.am-active {\n  position: relative;\n  z-index: 110;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  visibility: visible;\n}\n.am-pureview-slider .pinch-zoom-container {\n  width: 100%;\n  z-index: 1121;\n}\n.am-pureview-slider .am-pinch-zoom {\n  position: relative;\n  width: 100%;\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -ms-flexbox;\n  display: flex;\n  -webkit-box-pack: center;\n  -webkit-justify-content: center;\n      -ms-flex-pack: center;\n          justify-content: center;\n  -webkit-box-align: center;\n  -webkit-align-items: center;\n      -ms-flex-align: center;\n          align-items: center;\n}\n.am-pureview-slider .am-pinch-zoom:after {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f110\";\n  -webkit-animation: icon-spin 2s infinite linear;\n          animation: icon-spin 2s infinite linear;\n  font-size: 24px;\n  line-height: 24px;\n  color: #eee;\n  position: absolute;\n  top: 50%;\n  left: 50%;\n  margin-left: -12px;\n  margin-top: -12px;\n  z-index: 1;\n}\n.am-pureview-slider .am-pinch-zoom.am-pureview-loaded:after {\n  display: none;\n}\n.am-pureview-slider img {\n  position: relative;\n  display: block;\n  max-width: 100%;\n  max-height: 100%;\n  opacity: 0;\n  z-index: 200;\n  -webkit-user-drag: none;\n  -webkit-transition: opacity 0.2s ease-in;\n  transition: opacity 0.2s ease-in;\n}\n.am-pureview-slider img.am-img-loaded {\n  opacity: 1;\n}\n.am-pureview-direction {\n  position: absolute;\n  top: 50%;\n  width: 100%;\n  margin-top: -18px !important;\n  z-index: 1122;\n}\n.am-touch .am-pureview-direction,\n.am-pureview-only .am-pureview-direction {\n  display: none;\n}\n.am-pureview-direction li {\n  position: absolute;\n  width: 36px;\n  height: 36px;\n}\n.am-pureview-direction a {\n  display: block;\n  height: 36px;\n  border: none;\n  color: #ccc;\n  opacity: 0.5;\n  cursor: pointer;\n  text-align: center;\n  z-index: 1125;\n}\n.am-pureview-direction a:before {\n  content: \"\\f137\";\n  line-height: 36px;\n  font-size: 24px;\n}\n.am-pureview-direction a:hover {\n  opacity: 1;\n}\n.am-pureview-direction .am-pureview-prev {\n  left: 15px;\n}\n.am-pureview-direction .am-pureview-next {\n  right: 15px;\n}\n.am-pureview-direction .am-pureview-next a:before {\n  content: \"\\f138\";\n}\n.am-pureview-bar {\n  position: absolute;\n  bottom: 0;\n  height: 45px;\n  width: 100%;\n  background-color: rgba(0, 0, 0, 0.35);\n  color: #eeeeee;\n  line-height: 45px;\n  padding: 0 10px;\n  font-size: 14px;\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -ms-flexbox;\n  display: flex;\n}\n.am-pureview-bar .am-pureview-title {\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n  margin-left: 6px;\n  -webkit-box-flex: 1;\n  -webkit-flex: 1;\n      -ms-flex: 1;\n          flex: 1;\n}\n.am-pureview-bar .am-pureview-total {\n  font-size: 10px;\n  line-height: 48px;\n}\n.am-pureview-actions {\n  position: absolute;\n  z-index: 1130;\n  left: 0;\n  right: 0;\n  top: 0;\n  height: 45px;\n  background-color: rgba(0, 0, 0, 0.35);\n}\n.am-pureview-actions a {\n  position: absolute;\n  left: 10px;\n  color: #ccc;\n  display: block;\n  width: 45px;\n  line-height: 45px;\n  text-align: left;\n  font-size: 16px;\n}\n.am-pureview-actions a:hover {\n  color: #fff;\n}\n.am-pureview-actions [data-am-toggle=\"share\"] {\n  left: auto;\n  right: 10px;\n}\n.am-pureview-bar,\n.am-pureview-actions {\n  opacity: 0;\n  -webkit-transition: all .15s;\n  transition: all .15s;\n  z-index: 1130;\n}\n.am-pureview-bar-active .am-pureview-bar,\n.am-pureview-bar-active .am-pureview-actions {\n  opacity: 1;\n}\n.am-pureview-nav {\n  position: absolute;\n  bottom: 15px;\n  left: 0;\n  right: 0;\n  text-align: center;\n  z-index: 1131;\n}\n.am-pureview-bar-active .am-pureview-nav {\n  display: none;\n}\n.am-pureview-nav li {\n  display: inline-block;\n  background: #ccc;\n  background: rgba(255, 255, 255, 0.5);\n  width: 8px;\n  height: 8px;\n  margin: 0 3px;\n  border-radius: 50%;\n  text-indent: -9999px;\n  overflow: hidden;\n  cursor: pointer;\n}\n.am-pureview-nav .am-active {\n  background: #fff;\n  background: rgba(255, 255, 255, 0.9);\n}\n[data-am-pureview] img {\n  cursor: pointer;\n}\n.am-pureview-active {\n  overflow: hidden;\n}\n.ath-viewport * {\n  -webkit-box-sizing: border-box;\n          box-sizing: border-box;\n}\n.ath-viewport {\n  position: relative;\n  z-index: 2147483641;\n  pointer-events: none;\n  -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          user-select: none;\n  -webkit-text-size-adjust: none;\n      -ms-text-size-adjust: none;\n          text-size-adjust: none;\n}\n.ath-modal {\n  pointer-events: auto !important;\n  background: rgba(0, 0, 0, 0.6);\n}\n.ath-mandatory {\n  background: #000;\n}\n.ath-container {\n  pointer-events: auto !important;\n  position: absolute;\n  z-index: 2147483641;\n  padding: 0.7em 0.6em;\n  width: 18em;\n  background: #eee;\n  -webkit-background-size: 100% auto;\n          background-size: 100% auto;\n  -webkit-box-shadow: 0 0.2em 0 #d1d1d1;\n          box-shadow: 0 0.2em 0 #d1d1d1;\n  font-family: sans-serif;\n  font-size: 15px;\n  line-height: 1.5em;\n  text-align: center;\n}\n.ath-container small {\n  font-size: 0.8em;\n  line-height: 1.3em;\n  display: block;\n  margin-top: 0.5em;\n}\n.ath-ios.ath-phone {\n  bottom: 1.8em;\n  left: 50%;\n  margin-left: -9em;\n}\n.ath-ios6.ath-tablet {\n  left: 5em;\n  top: 1.8em;\n}\n.ath-ios7.ath-tablet {\n  left: 0.7em;\n  top: 1.8em;\n}\n.ath-ios8.ath-tablet {\n  right: 0.4em;\n  top: 1.8em;\n}\n.ath-android {\n  bottom: 1.8em;\n  left: 50%;\n  margin-left: -9em;\n}\n/* close icon */\n.ath-container:before {\n  content: '';\n  position: relative;\n  display: block;\n  float: right;\n  margin: -0.7em -0.6em 0 0.5em;\n  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIQAAACECAMAAABmmnOVAAAAdVBMVEUAAAA5OTkzMzM7Ozs3NzdBQUFAQEA/Pz8+Pj5BQUFAQEA/Pz8+Pj5BQUFAQEA/Pz9BQUE+Pj4/Pz8/Pz8+Pj4/Pz8/Pz8/Pz8+Pj4/Pz8+Pj4/Pz8/Pz8/Pz8/Pz8/Pz8+Pj4/Pz8/Pz8/Pz8/Pz9AQEA/Pz+fdCaPAAAAJnRSTlMACQoNDjM4OTo7PEFCQ0RFS6ytsbS1tru8vcTFxu7x8vX19vf4+C5yomAAAAJESURBVHgBvdzLTsJAGEfxr4C2KBcVkQsIDsK8/yPaqIsPzVlyzrKrX/5p0kkXEz81L23otc9NpIbbWia2YVLqdnhlqFlhGWpSDHe1aopsSIpRb8gK0dC3G30b9rVmhWZIimTICsvQtx/FsuYOrWHoDjX3Gu31gzJxdki934WrAIOsAIOsAIOiAMPhPsJTgKGN0BVsYIVsYIVpYIVpYIVpYIVpYIVpYIVpYIVpYIVlAIVgEBRs8BRs8BRs8BRs8BRs8BRs8BRs8BRTNmgKNngKNngKNngKNngKNhiKGxgiOlZoBlaYBlaYBlaYBlaYBlaYBlaYBlaYBlZIBlBMfQMrVAMr2KAqBENSHFHhGEABhi5CV6gGUKgGUKgGUKgGUFwuqgEUvoEVsoEVpoEUpgEUggF+gKTKY+h1fxSlC7/Z+RrxOQ3fcEoAPPHZBlaYBlaYBlaYBlZYBlYIhvLBCstw7PgM7hkiWOEZWGEaWGEaWGEaIsakEAysmHkGVpxmvoEVqoEVpoEVpoEVpoEVpoEVpoEVkoEVgkFQsEFSsEFQsGEcoSvY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnmbNAUT2c2WAo2eAo2eAo2eAo2eAo2eArNEPFACjZ4CjZ4CjZ4CjaIird/rBvFH6llNCvewdli1URWCIakSIZesUaDoFg36dKFWk9zCZDei3TtwmCj7pC22AwikiIZPEU29IpFNliKxa/hC9DFITjQPYhcAAAAAElFTkSuQmCC);\n  background-color: rgba(255, 255, 255, 0.8);\n  -webkit-background-size: 50% 50%;\n          background-size: 50%;\n  background-repeat: no-repeat;\n  background-position: 50%;\n  width: 2.7em;\n  height: 2.7em;\n  text-align: center;\n  overflow: hidden;\n  color: #a33;\n  z-index: 2147483642;\n}\n.ath-container.ath-icon:before {\n  position: absolute;\n  top: 0;\n  right: 0;\n  margin: 0;\n  float: none;\n}\n.ath-mandatory .ath-container:before {\n  display: none;\n}\n.ath-container.ath-android:before {\n  float: left;\n  margin: -0.7em 0.5em 0 -0.6em;\n}\n.ath-container.ath-android.ath-icon:before {\n  position: absolute;\n  right: auto;\n  left: 0;\n  margin: 0;\n  float: none;\n}\n/* applied only if the application icon is shown */\n.ath-action-icon {\n  display: inline-block;\n  vertical-align: middle;\n  background-position: 50%;\n  background-repeat: no-repeat;\n  text-indent: -9999em;\n  overflow: hidden;\n}\n.ath-ios7 .ath-action-icon,\n.ath-ios8 .ath-action-icon {\n  width: 1.6em;\n  height: 1.6em;\n  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHgAAACtCAYAAAB7l7tOAAAF6UlEQVR4AezZWWxUZRiH8VcQEdxZEFFiUZBFUCIa1ABBDARDcCciYGKMqTEGww3SOcNSAwQTjOBiiIpEhRjAhRgXRC8MFxojEhAFZUGttVhaoSxlaW3n8W3yXZxm6vTrOMM5Q98n+V9MMu1pvl++uZhKuypghu49KaaTWGdZSYoVN6VD95nMpLNYZ9XNbdQR2od2k88O3Gm6Bh0t7H0p5Vwp2Ax3ajpu2tYbciFWwkTFO63DY6+JcI4USFaSyYpWp8N7SVZJKR3EinkBk9JxvZFXxhnZSjBaoWp1ZL0ES8WKYXMZp0AndORgy8WKFe5Yf1zvvSBWDEpys2LU6MjD5kmEWQlGKsJRHXlcqUSQVcItEnDEA6gAb7LhjvD9WO6yIEfICQI5A1nzGCYB1T4og5bBiFcyv2f6ujYhl4iVxwKG6qp8MK55HsqPwK0rMr9v/yEo3uCPrJstVh5KMER30Aeh31Ioq0FrHfjXw9CYghnrvYFTuqfEymFzGSwBlT4ARYr7u+K6GLmCVGvAGg2NMG0d/sgJnpScZLjXSkC5z8H3eQ72/k24Q8NfzvwFyK4qtuJSZKaubRPyE/K/Mtx+EvCHL+7uasId1t10w0scz/RzSzYzAfgKV30D3LPaG7lRkR8RK4tKKJKAMp+D7r0EfmmOe0x3m2itAc/ZxBjgAt1mXHWKPPkdb+QGSTJdrDaU5EoJ2OtzwD0WwY7KNNzbRfMFFg24WPdtGHnS221Cflgsj56hjwTs8TnY7oq7/QDhjutGicsb2AVcovsO18l6uPPNNiE/JFaGAq7Q7fY50G4LYVtz3FrdaNGyBXbIl+q24DqhyHes9EaulwR3SwtZs+ktAT/7HORliru1gnCndONFyx44Dfn7MPLYN7yR6yTJZAllJeguAT/4HOBFz8I3ZWm4E0TLFbBD7qn7EVdtHYx53R9ZN0ksrZRuErDN5+AuLIWvm+Oe1k0ULdfADrmX7idcR0/DyBXeyCdlLuMMOGCBz4F1ng+f7yFcve5e0fIFHELeiav6BAx70Rt5p0yhY3u/wR0kyarW/uX35b403PtFyzewQ75ctwtXzSkY8WqruHslSV8RscrL6TJ1bcvfWJ0/HzbtIdw/ugdFyzdwOOAq3T6fmzxwGQ3vbmO8iFioIWqYSsHMj9M/ljfuTsOdItoZBXYBfXX7cVXVwvXLm/8+fU3lcdCqdEMNGBbgUmRmfQISQKd5sGEn4VK6YtEiAXYBA3QVuA4q8hCHrDcafR1ul65jewfuovsCl7vJrNlOuEbdo6JFCuwCrtb9hqusBu56Cw4cI1y1briIWEBn3Ue0XKPuMdGiBg4H9NdV0HJ/6QZLOEPmPN0GmpfSPS5arIBdwHUtIFfoBsl/ZsgfhHCfFi2WwC5goO4AmvanbqBkzJA76tboZokWa2AXMEi3RTdAvDLkDqJFAhzB32xFD2wZsGXA0WfAlgFbBmwZsGXAlgFbBpzk04JaKb0iA9ZnF9x5SQAFtRKKIgPWZxfaeRmwAZ/BGbAB37eaG6MCbnq2Aed5czYyKirgpmcbsAHHZAZswN0Wwo7KeG1fFf2jAm56dtzOQ42yB+65mDhWFBUwUETMUiMDNmADbp/APRaTAh6I2bpGCNw1bufRZJQ1cPdF/NueHZsgDEBBGLbMGoIu4AZu5gLOZeEaYmEXeznF3jRPyEv4frgJvvJe3qTefY0AAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwb8rwADBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgz4/sz1Nia/9hizA7zgklwy3RYwYMBzBRjw4bPjxAbAAizAAtwgwAIswAIswAIMGDBgARZgARZgAS4FWIAFWIAFWIABAwYswAIswAIswIUAC7AAC7AACzBgwIAFWIAFWIAFuBBgARZgARZgAQYMGPApQ99ZCdgWtzqwATbABtgAG2DbnxNb7zbRimsMLMACrDf2wMWI/WasfQAAAABJRU5ErkJggg==);\n  margin-top: -0.3em;\n  -webkit-background-size: auto 100%;\n          background-size: auto 100%;\n}\n.ath-ios6 .ath-action-icon {\n  width: 1.8em;\n  height: 1.8em;\n  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJAAAAB0CAQAAADAmnOnAAAAAnNCSVQICFXsRgQAAAAJcEhZcwAAWwEAAFsBAXkZiFwAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAF4klEQVR4Ae3a/a+XdR3H8ec5HM45HDmKICoVohkZsxESRRCzcZM/2JKkdGR5MrSkleA0Pd00O4u5IVuNM2yYc6XSzCExU4oUNRPCJFdMUAhsYZpUGhscOHA4N8/WZzsL6HBxvofvdV3fa3yer//gsV3vH659KHzncBsJxUYhDzOEhCKQbORs+ip2wzgM+wvj+P9i35qAGLaHGcQSgKSTrxBLABJppZpYApCspoFYApBsZjSxBCD5OxOJJQBJG1cQSwCSLpqJJQCJ3MvgCGTinuSMCJS8LZwfgZL3FtMiUPIOcU0ESl4PLRHoRPsJtREoeRsYGYGS9yrvo6RmpbLaigWSfzOdErLs6+bLUMFA0sF1+QF1cz1UNlBYK9V5AHXyWSgEkKyiIWOgGh829Ki1lLcaxjCVK7mJRSxjBY+zgRf/u9pXcMB7jhEZAg32EUP3O6hMKOP5Iq2sZQeHMZXt5KKMgOpcY+iHVnFyjeQKlrCBdsxge5ieAVC9vzLUelI8H+A7bKIHM10H81IGGuKvDf1ggDxVTKOV1zG3/Yia1ICG+ltD32MgNTKfP2HuW0VDKkCNrjfUTOm9i6XswwrZJkaVHeh0f2fodkrtfO6jAytqrzG+rEDDfVG1x1sprZEs5RBW4PZxeT+Bbrf5hPu9arfzKaU6WjiAFbseWvoF1GW/6vYGSmkyW7Dit4xB5QHq9Br6Xx2t9GAhtp6zkoHsfNp1J9wX6H+jeR4LtJc4LxGopZZyNpN/YcG2mw9nBTSPLizgOmjKAujGgvJID3ekD7QYi7nGzkvmQtpA38Vi7iJf0TedlC7QTVjMfcY2QyvSBPpUMW/PIBfbo9pls1XpAX2EdizeznStob3OJpQO0DB2YfE21q2GtnghpAm0Gou3T9tm6BGHQppA12HRVt17eboNlydNoLHsx2JtmL801OYcQmkC/QKLtQt9ydBW3wNpA30ci7Ur3WdolUMhbaBqNhf/8qQJ9Hkszs5wjaH9XkUobaAqtmFRdoGbDb3sWMgG6DIs5852knO82RaXer+P+qyb3eWeo7ZNBrRZvm1otY2QFdBjeHIb6hTne49Put12+9ObMoDdYmfy5UkF6AK6cCCr9aM2u9IddptcOYCG+FNDB5xLKCugO7G01TndFp/xgAntdYvrfdwVLnORt3q9Vx25F27DUjbGPxr6qxMgW6Cd2N+d6wLXedA+6nKbK73Lr/pJxzusvE/wZrvX0FOOgGyBxmF/dprXutYOj6nNdS6xyYnWp/dGcaGdhr5vDWQN9E1MXrUzfcA2j2qPj/l1J1uT9iPOeh8w1O7nCGUN9HzyGZ7ndo9qp0ucanU2r1xH+wdDu5wIeQDVVx0+/kd1i697RNv8thdn+Qz4Uv9p6DeOhHyApmBfq3OBu+3Nfd7nVELZAX3Nw4ZarYG8gG7GY1dlk6/Zm3/2Rk8jlB1QvT82dNAmQjkBVf8Mj957fdrefM7ZVhPKEuidvmDob06CXIGGbsX/bZDf8KAhfdbJhLIGmuZuQ084HHIGatiLvRvrRkP6qldbBXkAzbfD0N0OhryBGqrEMOd50FC7d1hPKGugBh8ydMh5hPIGGouI1d5lj6F1vptQ9kDvcKOhN5wMlQH0QcRGnzC03yZCeQDN9G1D6xwBFQI07FI8x02GdjgB8gJqttPQcmuhYoAumzvG7YZWejrkA1TrPYYO+SVCFQO0aM4bqj0uJJQH0LluSP7PkyeQU9QOmyAvoBm+Zegpz4LKA/qYB/wE5AXUe3m81zqoRKAPOYWcuvP9dxvqcD6h7IAKkaNU3eUlHLcI9EzS5YlAi62h/zUy89QCqqKUmvgHywsJlEHnsQYxAvXVIJo5gIhnPhiBju1iNmLvLn85Ah1ZPYs5jBGo72awEzEC9dVwHqQHI9DxWoAYgSLQQKteGIESu/qhCJTYtT+PQBEoAkWgCBSBkotAEehUWwSKQBEoAkWg/BeBIlAEikARKAJFoFmealu4gVLy1Gt5dkARKAL9BzujPSurTmu/AAAAAElFTkSuQmCC);\n  margin-bottom: 0.4em;\n  -webkit-background-size: 100% auto;\n          background-size: 100% auto;\n}\n.ath-android .ath-action-icon {\n  width: 1.4em;\n  height: 1.4em;\n  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAMAAABg3Am1AAAANlBMVEVmZmb///9mZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZW6fJrAAAAEXRSTlMAAAYHG21ub8fLz9DR8/T4+RrZ9owAAAB3SURBVHja7dNLDoAgDATQWv4gKve/rEajJOJiWLgg6WzpSyB0aHqHiNj6nL1lovb4C+hYzkSNAT7mryQFAVOeGAj4CjwEtgrWXpD/uZKtwEJApXt+Vn0flzRhgNiFZQkOXY0aADQZCOCPlsZJ46Rx0jhp3IiN2wGDHhxtldrlwQAAAABJRU5ErkJggg==);\n  -webkit-background-size: 100% auto;\n          background-size: 100% auto;\n}\n.ath-container p {\n  margin: 0;\n  padding: 0;\n  position: relative;\n  z-index: 2147483642;\n  text-shadow: 0 0.1em 0 #fff;\n  font-size: 1.1em;\n}\n.ath-ios.ath-phone:after {\n  content: '';\n  background: #eee;\n  position: absolute;\n  width: 2em;\n  height: 2em;\n  bottom: -0.9em;\n  left: 50%;\n  margin-left: -1em;\n  -webkit-transform: scaleX(0.9) rotate(45deg);\n  -ms-transform: scaleX(0.9) rotate(45deg);\n      transform: scaleX(0.9) rotate(45deg);\n  -webkit-box-shadow: 0.2em 0.2em 0 #d1d1d1;\n          box-shadow: 0.2em 0.2em 0 #d1d1d1;\n}\n.ath-ios.ath-tablet:after {\n  content: '';\n  background: #eee;\n  position: absolute;\n  width: 2em;\n  height: 2em;\n  top: -0.9em;\n  left: 50%;\n  margin-left: -1em;\n  -webkit-transform: scaleX(0.9) rotate(45deg);\n  -ms-transform: scaleX(0.9) rotate(45deg);\n      transform: scaleX(0.9) rotate(45deg);\n  z-index: 2147483641;\n}\n.ath-application-icon {\n  position: relative;\n  padding: 0;\n  border: 0;\n  margin: 0 auto 0.2em auto;\n  height: 6em;\n  width: 6em;\n  z-index: 2147483642;\n}\n.ath-container.ath-ios .ath-application-icon {\n  border-radius: 1em;\n  -webkit-box-shadow: 0 0.2em 0.4em rgba(0, 0, 0, 0.3), inset 0 0.07em 0 rgba(255, 255, 255, 0.5);\n          box-shadow: 0 0.2em 0.4em rgba(0, 0, 0, 0.3), inset 0 0.07em 0 rgba(255, 255, 255, 0.5);\n  margin: 0 auto 0.4em auto;\n}\n@media only screen and (orientation: landscape) {\n  .ath-container.ath-phone {\n    width: 24em;\n  }\n  .ath-android.ath-phone {\n    margin-left: -12em;\n  }\n  .ath-ios.ath-phone {\n    margin-left: -12em;\n  }\n  .ath-ios6:after {\n    left: 39%;\n  }\n  .ath-ios8.ath-phone {\n    left: auto;\n    bottom: auto;\n    right: 0.4em;\n    top: 1.8em;\n  }\n  .ath-ios8.ath-phone:after {\n    bottom: auto;\n    top: -0.9em;\n    left: 68%;\n    z-index: 2147483641;\n    -webkit-box-shadow: none;\n            box-shadow: none;\n  }\n}\n/* ==========================================================================\n   Component: uCheck Plugin\n ============================================================================ */\n.am-checkbox,\n.am-radio,\n.am-checkbox-inline,\n.am-radio-inline {\n  padding-left: 22px;\n  position: relative;\n  -webkit-transition: color .25s linear;\n  transition: color .25s linear;\n  font-size: 14px;\n  line-height: 1.5;\n}\nlabel.am-checkbox,\nlabel.am-radio {\n  font-weight: normal;\n}\n.am-ucheck-icons {\n  color: #999999;\n  display: block;\n  height: 20px;\n  top: 0;\n  left: 0;\n  position: absolute;\n  width: 20px;\n  text-align: center;\n  line-height: 21px;\n  font-size: 18px;\n  cursor: pointer;\n}\n.am-checkbox .am-icon-checked,\n.am-radio .am-icon-checked,\n.am-checkbox-inline .am-icon-checked,\n.am-radio-inline .am-icon-checked,\n.am-checkbox .am-icon-unchecked,\n.am-radio .am-icon-unchecked,\n.am-checkbox-inline .am-icon-unchecked,\n.am-radio-inline .am-icon-unchecked {\n  position: absolute;\n  left: 0;\n  top: 0;\n  display: inline-table;\n  margin: 0;\n  background-color: transparent;\n  -webkit-transition: color .25s linear;\n  transition: color .25s linear;\n}\n.am-checkbox .am-icon-checked:before,\n.am-radio .am-icon-checked:before,\n.am-checkbox-inline .am-icon-checked:before,\n.am-radio-inline .am-icon-checked:before,\n.am-checkbox .am-icon-unchecked:before,\n.am-radio .am-icon-unchecked:before,\n.am-checkbox-inline .am-icon-unchecked:before,\n.am-radio-inline .am-icon-unchecked:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n}\n.am-checkbox .am-icon-checked,\n.am-radio .am-icon-checked,\n.am-checkbox-inline .am-icon-checked,\n.am-radio-inline .am-icon-checked {\n  opacity: 0;\n}\n.am-checkbox .am-icon-checked:before,\n.am-checkbox-inline .am-icon-checked:before {\n  content: \"\\f046\";\n}\n.am-checkbox .am-icon-unchecked:before,\n.am-checkbox-inline .am-icon-unchecked:before {\n  content: \"\\f096\";\n}\n.am-radio .am-icon-checked:before,\n.am-radio-inline .am-icon-checked:before {\n  content: \"\\f192\";\n}\n.am-radio .am-icon-unchecked:before,\n.am-radio-inline .am-icon-unchecked:before {\n  content: \"\\f10c\";\n}\n.am-ucheck-checkbox,\n.am-ucheck-radio {\n  position: absolute;\n  left: 0;\n  top: 0;\n  margin: 0;\n  padding: 0;\n  width: 20px;\n  height: 20px;\n  opacity: 0;\n  outline: none !important;\n}\n.am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons {\n  color: #0e90d2;\n}\n.am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-ucheck-radio:checked + .am-ucheck-icons {\n  color: #0e90d2;\n}\n.am-ucheck-checkbox:checked + .am-ucheck-icons .am-icon-unchecked,\n.am-ucheck-radio:checked + .am-ucheck-icons .am-icon-unchecked {\n  opacity: 0;\n}\n.am-ucheck-checkbox:checked + .am-ucheck-icons .am-icon-checked,\n.am-ucheck-radio:checked + .am-ucheck-icons .am-icon-checked {\n  opacity: 1;\n}\n.am-ucheck-checkbox:disabled + .am-ucheck-icons,\n.am-ucheck-radio:disabled + .am-ucheck-icons {\n  cursor: default;\n  color: #d8d8d8;\n}\n.am-ucheck-checkbox:disabled:checked + .am-ucheck-icons .am-icon-unchecked,\n.am-ucheck-radio:disabled:checked + .am-ucheck-icons .am-icon-unchecked {\n  opacity: 0;\n}\n.am-ucheck-checkbox:disabled:checked + .am-ucheck-icons .am-icon-checked,\n.am-ucheck-radio:disabled:checked + .am-ucheck-icons .am-icon-checked {\n  opacity: 1;\n  color: #d8d8d8;\n}\n.am-checkbox.am-secondary .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio.am-secondary .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox-inline.am-secondary .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio-inline.am-secondary .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox.am-secondary .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio.am-secondary .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox-inline.am-secondary .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio-inline.am-secondary .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons {\n  color: #3bb4f2;\n}\n.am-checkbox.am-secondary .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-radio.am-secondary .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-checkbox-inline.am-secondary .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-radio-inline.am-secondary .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-checkbox.am-secondary .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-radio.am-secondary .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-checkbox-inline.am-secondary .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-radio-inline.am-secondary .am-ucheck-radio:checked + .am-ucheck-icons {\n  color: #3bb4f2;\n}\n.am-checkbox.am-success .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio.am-success .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox-inline.am-success .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio-inline.am-success .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox.am-success .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio.am-success .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox-inline.am-success .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio-inline.am-success .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons {\n  color: #5eb95e;\n}\n.am-checkbox.am-success .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-radio.am-success .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-checkbox-inline.am-success .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-radio-inline.am-success .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-checkbox.am-success .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-radio.am-success .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-checkbox-inline.am-success .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-radio-inline.am-success .am-ucheck-radio:checked + .am-ucheck-icons {\n  color: #5eb95e;\n}\n.am-checkbox.am-warning .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio.am-warning .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox-inline.am-warning .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio-inline.am-warning .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox.am-warning .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio.am-warning .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox-inline.am-warning .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio-inline.am-warning .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons {\n  color: #F37B1D;\n}\n.am-checkbox.am-warning .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-radio.am-warning .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-checkbox-inline.am-warning .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-radio-inline.am-warning .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-checkbox.am-warning .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-radio.am-warning .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-checkbox-inline.am-warning .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-radio-inline.am-warning .am-ucheck-radio:checked + .am-ucheck-icons {\n  color: #F37B1D;\n}\n.am-checkbox.am-danger .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio.am-danger .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox-inline.am-danger .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio-inline.am-danger .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox.am-danger .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio.am-danger .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-checkbox-inline.am-danger .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons,\n.am-radio-inline.am-danger .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons {\n  color: #dd514c;\n}\n.am-checkbox.am-danger .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-radio.am-danger .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-checkbox-inline.am-danger .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-radio-inline.am-danger .am-ucheck-checkbox:checked + .am-ucheck-icons,\n.am-checkbox.am-danger .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-radio.am-danger .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-checkbox-inline.am-danger .am-ucheck-radio:checked + .am-ucheck-icons,\n.am-radio-inline.am-danger .am-ucheck-radio:checked + .am-ucheck-icons {\n  color: #dd514c;\n}\n.am-field-error + .am-ucheck-icons {\n  color: #dd514c;\n}\n.am-field-valid + .am-ucheck-icons {\n  color: #5eb95e;\n}\n/*\n// Group Addon\n.@{ns}input-group-label {\n  .@{ns}radio,\n  .@{ns}checkbox {\n    margin: -2px 0;\n    padding-left: 15px;\n  }\n}\n\n// Form inline style\n.@{ns}form-inline .@{ns}checkbox,\n.@{ns}form-inline .@{ns}radio {\n  padding-left: 24px;\n}\n*/\n/* ==========================================================================\n   Component: Selected Plugin\n ============================================================================ */\n.am-selected {\n  width: 200px;\n}\n.am-selected-btn {\n  width: 100%;\n  padding-left: 10px;\n  text-align: right;\n}\n.am-selected-btn.am-btn-default {\n  background: none;\n}\n.am-invalid .am-selected-btn {\n  border-color: #dd514c;\n}\n.am-selected-header {\n  height: 45px;\n  background-color: #f2f2f2;\n  border-bottom: 1px solid #ddd;\n  display: none;\n}\n.am-selected-status {\n  text-align: left;\n  width: 100%;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-selected-content {\n  padding: 10px 0;\n}\n.am-selected-search {\n  padding: 0 10px 10px;\n}\n.am-selected-search .am-form-field {\n  padding: .5em;\n}\n.am-selected-list {\n  margin: 0;\n  padding: 0;\n  list-style: none;\n  font-size: 1.5rem;\n}\n.am-selected-list li {\n  position: relative;\n  cursor: pointer;\n  padding: 5px 10px;\n  -webkit-transition: background-color 0.15s;\n  transition: background-color 0.15s;\n}\n.am-selected-list li:hover {\n  background-color: #f8f8f8;\n}\n.am-selected-list li:hover .am-icon-check {\n  opacity: .6;\n}\n.am-selected-list li.am-checked .am-icon-check {\n  opacity: 1;\n  color: #0e90d2;\n}\n.am-selected-list li.am-disabled {\n  opacity: .5;\n  pointer-events: none;\n  cursor: not-allowed;\n}\n.am-selected-list .am-selected-list-header {\n  margin-top: 8px;\n  font-size: 1.3rem;\n  color: #999999;\n  border-bottom: 1px solid #e5e5e5;\n  cursor: default;\n}\n.am-selected-list .am-selected-list-header:hover {\n  background: none;\n}\n.am-selected-list .am-selected-list-header:first-child {\n  margin-top: 0;\n}\n.am-selected-list .am-selected-text {\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n  margin-right: 30px;\n}\n.am-selected-list .am-icon-check {\n  position: absolute;\n  right: 8px;\n  top: 5px;\n  color: #999999;\n  opacity: 0;\n  -webkit-transition: opacity .15s;\n  transition: opacity .15s;\n}\n.am-selected-hint {\n  line-height: 1.2;\n  color: #dd514c;\n}\n.am-selected-hint:not(:empty) {\n  margin-top: 10px;\n  border-top: 1px solid #e5e5e5;\n  padding: 10px 10px 0;\n}\n.am-selected-placeholder {\n  opacity: .65;\n}\n/* ==========================================================================\n   Component: JS Plugins helpers\n ============================================================================ */\n.am-fade {\n  opacity: 0;\n  -webkit-transition: opacity .2s linear;\n  transition: opacity .2s linear;\n}\n.am-fade.am-in {\n  opacity: 1;\n}\n.am-collapse {\n  display: none;\n}\n.am-collapse.am-in {\n  display: block;\n}\ntr.am-collapse.am-in {\n  display: table-row;\n}\ntbody.am-collapse.am-in {\n  display: table-row-group;\n}\n.am-collapsing {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height .3s ease;\n  transition: height .3s ease;\n}\n.am-sticky {\n  position: fixed !important;\n  z-index: 1010;\n  -webkit-transform-origin: 0 0;\n      -ms-transform-origin: 0 0;\n          transform-origin: 0 0;\n}\n[data-am-sticky][class*=\"am-animation-\"] {\n  -webkit-animation-duration: .2s;\n          animation-duration: .2s;\n}\n.am-dimmer-active {\n  overflow: hidden;\n}\n.am-dimmer {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  display: none;\n  width: 100%;\n  height: 100%;\n  background-color: rgba(0, 0, 0, 0.6);\n  z-index: 1100;\n  opacity: 0;\n}\n.am-dimmer.am-active {\n  opacity: 1;\n}\n[data-am-collapse] {\n  cursor: pointer;\n}\n.am-datepicker {\n  top: 0;\n  left: 0;\n  border-radius: 2px;\n  background: #fff;\n  -webkit-box-shadow: 0 0 10px #ccc;\n          box-shadow: 0 0 10px #ccc;\n  padding-bottom: 10px;\n  margin-top: 10px;\n  width: 238px;\n  color: #555;\n  display: none;\n}\n.am-datepicker > div {\n  display: none;\n}\n.am-datepicker table {\n  width: 100%;\n}\n.am-datepicker tr.am-datepicker-header {\n  font-size: 1.6rem;\n  color: #fff;\n  background: #3bb4f2;\n}\n.am-datepicker td,\n.am-datepicker th {\n  text-align: center;\n  font-weight: normal;\n  cursor: pointer;\n}\n.am-datepicker th {\n  height: 48px;\n}\n.am-datepicker td {\n  font-size: 1.4rem;\n}\n.am-datepicker td.am-datepicker-day {\n  height: 34px;\n  width: 34px;\n}\n.am-datepicker td.am-datepicker-day:hover {\n  background: #F0F0F0;\n  height: 34px;\n  width: 34px;\n}\n.am-datepicker td.am-datepicker-day.am-disabled {\n  cursor: no-drop;\n  color: #999;\n  background: #fafafa;\n}\n.am-datepicker td.am-datepicker-old,\n.am-datepicker td.am-datepicker-new {\n  color: #89d7ff;\n}\n.am-datepicker td.am-active,\n.am-datepicker td.am-active:hover {\n  border-radius: 2px;\n  color: #0084c7;\n  background: #F0F0F0;\n}\n.am-datepicker td span {\n  display: block;\n  width: 79.33333333px;\n  height: 40px;\n  line-height: 40px;\n  float: left;\n  cursor: pointer;\n}\n.am-datepicker td span:hover {\n  background: #F0F0F0;\n}\n.am-datepicker td span.am-active {\n  color: #0084c7;\n  background: #F0F0F0;\n}\n.am-datepicker td span.am-disabled {\n  cursor: no-drop;\n  color: #999;\n  background: #fafafa;\n}\n.am-datepicker td span.am-datepicker-old {\n  color: #89d7ff;\n}\n.am-datepicker .am-datepicker-dow {\n  height: 40px;\n  color: #0c80ba;\n}\n.am-datepicker-caret {\n  display: block!important;\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: middle;\n  border-bottom: 7px solid #3bb4f2;\n  border-right: 7px solid transparent;\n  border-left: 7px solid transparent;\n  border-top: 0 dotted;\n  -webkit-transform: rotate(360deg);\n      -ms-transform: rotate(360deg);\n          transform: rotate(360deg);\n  position: absolute;\n  top: -7px;\n  left: 6px;\n}\n.am-datepicker-right .am-datepicker-caret {\n  left: auto;\n  right: 7px;\n}\n.am-datepicker-up .am-datepicker-caret {\n  top: auto;\n  bottom: -7px;\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: middle;\n  border-top: 7px solid #fff;\n  border-right: 7px solid transparent;\n  border-left: 7px solid transparent;\n  border-bottom: 0 dotted;\n  -webkit-transform: rotate(360deg);\n      -ms-transform: rotate(360deg);\n          transform: rotate(360deg);\n}\n.am-datepicker-select {\n  height: 34px;\n  line-height: 34px;\n  text-align: center;\n  -webkit-transition: background-color 300ms ease-out;\n  transition: background-color 300ms ease-out;\n}\n.am-datepicker-select:hover {\n  background: rgba(154, 217, 248, 0.5);\n  color: #0c80ba;\n}\n.am-datepicker-prev,\n.am-datepicker-next {\n  width: 34px;\n  height: 34px;\n}\n.am-datepicker-prev-icon,\n.am-datepicker-next-icon {\n  width: 34px;\n  height: 34px;\n  line-height: 34px;\n  display: inline-block;\n  -webkit-transition: background-color 300ms ease-out;\n  transition: background-color 300ms ease-out;\n}\n.am-datepicker-prev-icon:hover,\n.am-datepicker-next-icon:hover {\n  background: rgba(154, 217, 248, 0.5);\n  color: #0c80ba;\n}\n.am-datepicker-prev-icon:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f053\";\n}\n.am-datepicker-next-icon:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f054\";\n}\n.am-datepicker-dropdown {\n  position: absolute;\n  z-index: 1120;\n}\n@media only screen and (max-width: 640px) {\n  .am-datepicker {\n    width: 100%;\n  }\n  .am-datepicker td span {\n    width: 33.33%;\n  }\n  .am-datepicker-caret {\n    display: none!important;\n  }\n  .am-datepicker-prev,\n  .am-datepicker-next {\n    width: 44px;\n    height: 44px;\n  }\n}\n.am-datepicker-success tr.am-datepicker-header {\n  background: #5eb95e;\n}\n.am-datepicker-success td.am-datepicker-day.am-disabled {\n  color: #999;\n}\n.am-datepicker-success td.am-datepicker-old,\n.am-datepicker-success td.am-datepicker-new {\n  color: #94df94;\n}\n.am-datepicker-success td.am-active,\n.am-datepicker-success td.am-active:hover {\n  color: #1b961b;\n}\n.am-datepicker-success td span.am-datepicker-old {\n  color: #94df94;\n}\n.am-datepicker-success td span.am-active {\n  color: #1b961b;\n}\n.am-datepicker-success .am-datepicker-caret {\n  border-bottom-color: #5eb95e;\n}\n.am-datepicker-success .am-datepicker-dow {\n  color: #367b36;\n}\n.am-datepicker-success .am-datepicker-select:hover,\n.am-datepicker-success .am-datepicker-prev-icon:hover,\n.am-datepicker-success .am-datepicker-next-icon:hover {\n  background: rgba(165, 216, 165, 0.5);\n  color: #367b36;\n}\n.am-datepicker-danger tr.am-datepicker-header {\n  background: #dd514c;\n}\n.am-datepicker-danger td.am-datepicker-day.am-disabled {\n  color: #999;\n}\n.am-datepicker-danger td.am-datepicker-old,\n.am-datepicker-danger td.am-datepicker-new {\n  color: #f59490;\n}\n.am-datepicker-danger td.am-active,\n.am-datepicker-danger td.am-active:hover {\n  color: #c10802;\n}\n.am-datepicker-danger td span.am-datepicker-old {\n  color: #f59490;\n}\n.am-datepicker-danger td span.am-active {\n  color: #c10802;\n}\n.am-datepicker-danger .am-datepicker-caret {\n  border-bottom-color: #dd514c;\n}\n.am-datepicker-danger .am-datepicker-dow {\n  color: #a4241f;\n}\n.am-datepicker-danger .am-datepicker-select:hover,\n.am-datepicker-danger .am-datepicker-prev-icon:hover,\n.am-datepicker-danger .am-datepicker-next-icon:hover {\n  background: rgba(237, 164, 162, 0.5);\n  color: #a4241f;\n}\n.am-datepicker-warning tr.am-datepicker-header {\n  background: #F37B1D;\n}\n.am-datepicker-warning td.am-datepicker-day.am-disabled {\n  color: #999;\n}\n.am-datepicker-warning td.am-datepicker-old,\n.am-datepicker-warning td.am-datepicker-new {\n  color: #ffad6d;\n}\n.am-datepicker-warning td.am-active,\n.am-datepicker-warning td.am-active:hover {\n  color: #aa4b00;\n}\n.am-datepicker-warning td span.am-datepicker-old {\n  color: #ffad6d;\n}\n.am-datepicker-warning td span.am-active {\n  color: #aa4b00;\n}\n.am-datepicker-warning .am-datepicker-caret {\n  border-bottom-color: #F37B1D;\n}\n.am-datepicker-warning .am-datepicker-dow {\n  color: #a14c09;\n}\n.am-datepicker-warning .am-datepicker-select:hover,\n.am-datepicker-warning .am-datepicker-prev-icon:hover,\n.am-datepicker-warning .am-datepicker-next-icon:hover {\n  background: rgba(248, 180, 126, 0.5);\n  color: #a14c09;\n}\n.am-datepicker > div {\n  display: block;\n}\n.am-datepicker > div span.am-datepicker-hour {\n  width: 59.5px;\n}\n.am-datepicker-date {\n  display: block;\n}\n.am-datepicker-date.am-input-group {\n  display: table;\n}\n.am-datepicker-time-box {\n  padding: 30px 0 30px 0;\n}\n.am-datepicker-time-box strong {\n  font-size: 5.2rem;\n  display: inline-block;\n  height: 70px;\n  width: 70px;\n  line-height: 70px;\n  font-weight: normal;\n}\n.am-datepicker-time-box strong:hover {\n  border-radius: 4px;\n  background: #ECECEC;\n}\n.am-datepicker-time-box em {\n  display: inline-block;\n  height: 70px;\n  width: 20px;\n  line-height: 70px;\n  font-size: 5.2rem;\n  font-style: normal;\n}\n.am-datepicker-toggle {\n  text-align: center;\n  cursor: pointer;\n  padding: 10px 0;\n}\n.am-datepicker-toggle:hover {\n  background: #f0f0f0;\n}\n/* ==========================================================================\n   Component: Print\n ============================================================================ */\n@media print {\n  *,\n  *:before,\n  *:after {\n    background: transparent !important;\n    color: #000 !important;\n    /* Black prints faster: h5bp.com/s */\n    -webkit-box-shadow: none !important;\n            box-shadow: none !important;\n    text-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  /**\n   * Don't show links that are fragment identifiers,\n   * or use the `javascript:` pseudo protocol\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    /* h5bp.com/t */\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\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  @page {\n    margin: 0.5cm;\n  }\n  select {\n    background: #fff !important;\n  }\n  .am-topbar {\n    display: none;\n  }\n  .am-table td,\n  .am-table th {\n    background-color: #fff !important;\n  }\n  .am-table {\n    border-collapse: collapse !important;\n  }\n  .am-table-bordered th,\n  .am-table-bordered td {\n    border: 1px solid #ddd !important;\n  }\n}\n/* print helper classes */\n.am-print-block {\n  display: none !important;\n}\n@media print {\n  .am-print-block {\n    display: block !important;\n  }\n}\n.am-print-inline {\n  display: none !important;\n}\n@media print {\n  .am-print-inline {\n    display: inline !important;\n  }\n}\n.am-print-inline-block {\n  display: none !important;\n}\n@media print {\n  .am-print-inline-block {\n    display: inline-block !important;\n  }\n}\n@media print {\n  .am-print-hide {\n    display: none !important;\n  }\n}\n.lte9 #nprogress .nprogress-spinner {\n  display: none !important;\n}\n.lte8 .am-dimmer {\n  background-color: #000;\n  filter: alpha(opacity=60);\n}\n.lte8 .am-modal-actions {\n  display: none;\n}\n.lte8 .am-modal-actions.am-modal-active {\n  display: block;\n}\n.lte8 .am-offcanvas.am-active {\n  background: #000;\n}\n.lte8 .am-popover .am-popover-caret {\n  border: 8px solid transparent;\n}\n.lte8 .am-popover-top .am-popover-caret {\n  border-top: 8px solid #333333;\n  border-bottom: none;\n}\n.lte8 .am-popover-left .am-popover-caret {\n  right: -8px;\n  margin-top: -6px;\n  border-left: 8px solid #333333;\n  border-right: none;\n}\n.lte8 .am-popover-right .am-popover-caret {\n  left: -8px;\n  margin-top: -6px;\n  border-right: 8px solid #333333;\n  border-left: none;\n}\n.am-accordion-item {\n  margin: 0;\n}\n.am-accordion-title {\n  font-weight: normal;\n  cursor: pointer;\n}\n.am-accordion-item.am-disabled .am-accordion-title {\n  cursor: default;\n  pointer-events: none;\n}\n.am-accordion-bd {\n  margin: 0 !important;\n  padding: 0 !important;\n  border: none !important;\n}\n.am-accordion-content {\n  margin-top: 0;\n  padding: 0.8rem 1rem 1.2rem;\n  font-size: 1.4rem;\n}\n/**\n  * Accordion Theme: default\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-accordion-default {\n  margin: 1rem;\n  border-radius: 2px;\n  -webkit-box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);\n          box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);\n}\n.am-accordion-default .am-accordion-item {\n  border-top: 1px solid rgba(0, 0, 0, 0.05);\n}\n.am-accordion-default .am-accordion-item:first-child {\n  border-top: none;\n}\n.am-accordion-default .am-accordion-title {\n  color: rgba(0, 0, 0, 0.6);\n  -webkit-transition: background-color 0.2s ease-out;\n  transition: background-color 0.2s ease-out;\n  padding: .8rem 1rem;\n}\n.am-accordion-default .am-accordion-title:before {\n  content: \"\\f0da\";\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  -webkit-transition: -webkit-transform .2s ease;\n  transition: -webkit-transform .2s ease;\n  transition: transform .2s ease;\n  transition: transform .2s ease, -webkit-transform .2s ease;\n  -webkit-transform: rotate(0deg);\n      -ms-transform: rotate(0deg);\n          transform: rotate(0deg);\n  margin-right: 5px;\n}\n.am-accordion-default .am-accordion-title:hover {\n  color: #0e90d2;\n}\n.am-accordion-default .am-accordion-content {\n  color: #666;\n}\n.am-accordion-default .am-active .am-accordion-title {\n  background-color: #eeeeee;\n  color: #0e90d2;\n}\n.am-accordion-default .am-active .am-accordion-title:before {\n  -webkit-transform: rotate(90deg);\n      -ms-transform: rotate(90deg);\n          transform: rotate(90deg);\n}\n/**\n  * Accordion Theme: basic\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-accordion-basic {\n  margin: 1rem;\n}\n.am-accordion-basic .am-accordion-title {\n  color: #333333;\n  -webkit-transition: background-color 0.2s ease-out;\n  transition: background-color 0.2s ease-out;\n  padding: .8rem 0 0;\n}\n.am-accordion-basic .am-accordion-title:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f0da\";\n  -webkit-transition: -webkit-transform .2s ease;\n  transition: -webkit-transform .2s ease;\n  transition: transform .2s ease;\n  transition: transform .2s ease, -webkit-transform .2s ease;\n  -webkit-transform: rotate(0deg);\n      -ms-transform: rotate(0deg);\n          transform: rotate(0deg);\n  margin-right: .5rem;\n}\n.am-accordion-basic .am-accordion-content {\n  color: #666;\n}\n.am-accordion-basic .am-active .am-accordion-title {\n  color: #0e90d2;\n}\n.am-accordion-basic .am-active .am-accordion-title:before {\n  -webkit-transform: rotate(90deg);\n      -ms-transform: rotate(90deg);\n          transform: rotate(90deg);\n}\n/**\n  * Accordion Theme: gapped\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-accordion-gapped {\n  margin: .5rem 1rem;\n}\n.am-accordion-gapped .am-accordion-item {\n  border: 1px solid #dedede;\n  border-bottom: none;\n  margin: .5rem 0;\n}\n.am-accordion-gapped .am-accordion-item.am-active {\n  border-bottom: 1px solid #dedede;\n}\n.am-accordion-gapped .am-accordion-title {\n  color: rgba(0, 0, 0, 0.6);\n  -webkit-transition: background-color 0.15s ease-out;\n  transition: background-color 0.15s ease-out;\n  border-bottom: 1px solid #dedede;\n  padding: 0.8rem 2rem 0.8rem 1rem;\n  position: relative;\n}\n.am-accordion-gapped .am-accordion-title:after {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f105\";\n  -webkit-transition: -webkit-transform .2s linear;\n  transition: -webkit-transform .2s linear;\n  transition: transform .2s linear;\n  transition: transform .2s linear, -webkit-transform .2s linear;\n  position: absolute;\n  right: 10px;\n  top: 50%;\n  margin-top: -0.8rem;\n}\n.am-accordion-gapped .am-accordion-title:hover {\n  color: rgba(0, 0, 0, 0.8);\n}\n.am-accordion-gapped .am-accordion-content {\n  color: #666;\n}\n.am-accordion-gapped .am-active .am-accordion-title {\n  background-color: #f5f5f5;\n  color: rgba(0, 0, 0, 0.8);\n}\n.am-accordion-gapped .am-active .am-accordion-title:after {\n  -webkit-transform: rotate(90deg);\n      -ms-transform: rotate(90deg);\n          transform: rotate(90deg);\n}\n.am-divider {\n  height: 0;\n  margin: 1.5rem auto;\n  overflow: hidden;\n  clear: both;\n}\n/**\n  * Divider Theme: default\n  */\n.am-divider-default {\n  border-top: 1px solid #ddd;\n}\n/**\n  * Divider Theme: dotted\n  */\n.am-divider-dotted {\n  border-top: 1px dotted #ccc;\n}\n/**\n  * Divider Theme: dashed\n  */\n.am-divider-dashed {\n  border-top: 1px dashed #ccc;\n}\n.am-figure-zoomable {\n  position: relative;\n  cursor: pointer;\n}\n.am-figure-zoomable:after {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f00e\";\n  position: absolute;\n  top: 1rem;\n  right: 1rem;\n  color: #999999;\n  font-size: 1.6rem;\n  -webkit-transition: all 0.2s;\n  transition: all 0.2s;\n  pointer-events: none;\n}\n.am-figure-zoomable:hover:after {\n  color: #eeeeee;\n}\n.am-figure-default {\n  margin: 10px;\n}\n.am-figure-default img {\n  display: block;\n  max-width: 100%;\n  height: auto;\n  padding: 2px;\n  border: 1px solid #eeeeee;\n  margin: 10px auto;\n}\n.am-figure-default figcaption {\n  text-align: center;\n  font-size: 1.4rem;\n  margin-bottom: 15px;\n  color: #333333;\n}\n.am-footer {\n  text-align: center;\n  padding: 1em 0;\n  font-size: 1.6rem;\n}\n.am-footer .am-switch-mode-ysp {\n  cursor: pointer;\n}\n.am-footer .am-footer-text {\n  margin-top: 10px;\n  font-size: 14px;\n}\n.am-footer .am-footer-text-left {\n  text-align: left;\n  padding-left: 10px;\n}\n.am-modal-footer-hd {\n  padding-bottom: 10px;\n}\n/**\n  * Footer Theme: default\n  */\n.am-footer-default {\n  background-color: #fff;\n}\n.am-footer-default a {\n  color: #555555;\n}\n.am-footer-default .am-footer-switch {\n  margin-bottom: 10px;\n  font-weight: bold;\n}\n.am-footer-default .am-footer-ysp {\n  color: #555555;\n  cursor: pointer;\n}\n.am-footer-default .am-footer-divider {\n  color: #ccc;\n}\n.am-footer-default .am-footer-desktop {\n  color: #0e90d2;\n}\n.am-footer-default .am-footer-miscs {\n  color: #999999;\n  font-size: 13px;\n}\n.am-footer-default .am-footer-miscs p {\n  margin: 5px 0;\n}\n@media only screen and (min-width:641px) {\n  .am-footer-default .am-footer-miscs p {\n    display: inline-block;\n    margin: 5px;\n  }\n}\n.am-gallery {\n  padding: 5px 5px 0 5px;\n  list-style: none;\n}\n.am-gallery h3 {\n  margin: 0;\n}\n[data-am-gallery*='pureview'] img {\n  cursor: pointer;\n}\n/**\n  * Gallery Theme: default\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-gallery-default > li {\n  padding: 5px;\n}\n.am-gallery-default .am-gallery-item img {\n  width: 100%;\n  height: auto;\n}\n.am-gallery-default .am-gallery-title {\n  margin-top: 10px;\n  font-weight: normal;\n  font-size: 1.4rem;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n  color: #555555;\n}\n.am-gallery-default .am-gallery-desc {\n  color: #999999;\n  font-size: 1.2rem;\n}\n/**\n  * Gallery Theme: overlay\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-gallery-overlay > li {\n  padding: 5px;\n}\n.am-gallery-overlay .am-gallery-item {\n  position: relative;\n}\n.am-gallery-overlay .am-gallery-item img {\n  width: 100%;\n  height: auto;\n}\n.am-gallery-overlay .am-gallery-title {\n  font-weight: normal;\n  font-size: 1.4rem;\n  color: #FFF;\n  position: absolute;\n  bottom: 0;\n  width: 100%;\n  background-color: rgba(0, 0, 0, 0.5);\n  text-indent: 5px;\n  height: 30px;\n  line-height: 30px;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-gallery-overlay .am-gallery-desc {\n  display: none;\n}\n/**\n  * Accordion Theme: bordered\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-gallery-bordered > li {\n  padding: 5px;\n}\n.am-gallery-bordered .am-gallery-item {\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.35);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.35);\n  padding: 5px;\n}\n.am-gallery-bordered .am-gallery-item img {\n  width: 100%;\n  height: auto;\n}\n.am-gallery-bordered .am-gallery-title {\n  margin-top: 10px;\n  font-weight: normal;\n  font-size: 1.4rem;\n  color: #555555;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-gallery-bordered .am-gallery-desc {\n  color: #999999;\n  font-size: 1.2rem;\n}\n/**\n  * Gallery Theme: imgbordered\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-gallery-imgbordered > li {\n  padding: 5px;\n}\n.am-gallery-imgbordered .am-gallery-item img {\n  width: 100%;\n  height: auto;\n  border: 3px solid #FFF;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.35);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.35);\n}\n.am-gallery-imgbordered .am-gallery-title {\n  margin-top: 10px;\n  font-weight: normal;\n  font-size: 1.4rem;\n  color: #555555;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-gallery-imgbordered .am-gallery-desc {\n  color: #999999;\n  font-size: 1.2rem;\n}\n.am-gotop a {\n  display: inline-block;\n  text-decoration: none;\n}\n/**\n  * Gotop Theme: default\n  */\n.am-gotop-default {\n  text-align: center;\n  margin: 10px 0;\n}\n.am-gotop-default a {\n  background-color: #0e90d2;\n  padding: .5em 1.5em;\n  border-radius: 2px;\n  color: #fff;\n}\n.am-gotop-default a img {\n  display: none;\n}\n/**\n  * Gotop Theme: fixed\n  */\n.am-gotop-fixed {\n  position: fixed;\n  right: 10px;\n  bottom: 10px;\n  z-index: 1010;\n  opacity: 0;\n  width: 32px;\n  min-height: 32px;\n  overflow: hidden;\n  border-radius: 2px;\n  text-align: center;\n}\n.am-gotop-fixed.am-active {\n  opacity: .9;\n}\n.am-gotop-fixed.am-active:hover {\n  opacity: 1;\n}\n.am-gotop-fixed a {\n  display: block;\n}\n.am-gotop-fixed .am-gotop-title {\n  display: none;\n}\n.am-gotop-fixed .am-gotop-icon-custom {\n  display: inline-block;\n  max-width: 30px;\n  vertical-align: middle;\n}\n.am-gotop-fixed .am-gotop-icon {\n  width: 100%;\n  line-height: 32px;\n  background-color: #555555;\n  vertical-align: middle;\n  color: #ddd;\n}\n.am-gotop-fixed .am-gotop-icon:hover {\n  color: #fff;\n}\n.am-with-fixed-navbar .am-gotop-fixed {\n  bottom: 60px;\n}\n.am-header {\n  position: relative;\n  width: 100%;\n  height: 49px;\n  line-height: 49px;\n  padding: 0 10px;\n}\n.am-header h1 {\n  margin-top: 0;\n  margin-bottom: 0;\n}\n.am-header .am-header-title {\n  margin: 0 30%;\n  font-size: 2rem;\n  font-weight: normal;\n  text-align: center;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-header .am-header-title img {\n  margin-top: 12px;\n  height: 25px;\n  vertical-align: top;\n}\n.am-header .am-header-nav {\n  position: absolute;\n  top: 0;\n}\n.am-header .am-header-nav img {\n  height: 16px;\n  width: auto;\n  vertical-align: middle;\n}\n.am-header .am-header-left {\n  left: 10px;\n}\n.am-header .am-header-right {\n  right: 10px;\n}\n.am-header-fixed {\n  position: fixed;\n  top: 0;\n  left: 0;\n  right: 0;\n  width: 100%;\n  z-index: 1010;\n}\n.am-with-fixed-header {\n  padding-top: 49px;\n}\n/**\n  * Header Theme: default\n  */\n.am-header-default {\n  background-color: #0e90d2;\n}\n.am-header-default .am-header-title {\n  color: #fff;\n}\n.am-header-default .am-header-title a {\n  color: #fff;\n}\n.am-header-default .am-header-icon {\n  font-size: 20px;\n}\n.am-header-default .am-header-nav {\n  color: #eeeeee;\n}\n.am-header-default .am-header-nav > a {\n  display: inline-block;\n  min-width: 36px;\n  text-align: center;\n  color: #eeeeee;\n}\n.am-header-default .am-header-nav > a + a {\n  margin-left: 5px;\n}\n.am-header-default .am-header-nav .am-btn {\n  margin-top: 9px;\n  height: 31px;\n  padding: 0 0.5em;\n  line-height: 30px;\n  font-size: 14px;\n  vertical-align: top;\n}\n.am-header-default .am-header-nav .am-btn .am-header-icon {\n  font-size: inherit;\n}\n.am-header-default .am-header-nav .am-btn-default {\n  color: #999999;\n}\n.am-header-default .am-header-nav-title,\n.am-header-default .am-header-nav-title + .am-header-icon {\n  font-size: 14px;\n}\n.am-intro {\n  position: relative;\n}\n.am-intro img {\n  max-width: 100%;\n}\n.am-intro-hd {\n  position: relative;\n  height: 45px;\n  line-height: 45px;\n}\n.am-intro-title {\n  font-size: 18px;\n  margin: 0;\n  font-weight: bold;\n}\n.am-intro-more-top {\n  position: absolute;\n  right: 10px;\n  top: 0;\n  font-size: 1.4rem;\n}\n.am-intro-bd {\n  padding-top: 15px;\n  padding-bottom: 15px;\n  font-size: 1.4rem;\n}\n.am-intro-bd p:last-child {\n  margin-bottom: 0;\n}\n.am-intro-more-bottom {\n  clear: both;\n  text-align: center;\n}\n.am-intro-more-bottom .am-btn {\n  font-size: 14px;\n}\n/**\n  * Intro Theme: default\n  */\n.am-intro-default .am-intro-hd {\n  background-color: #0e90d2;\n  color: #fff;\n  padding: 0 10px;\n}\n.am-intro-default .am-intro-hd a {\n  color: #eee;\n}\n.am-intro-default .am-intro-right {\n  padding-left: 0;\n}\n.am-list-news-hd {\n  padding-top: 1.2rem;\n  padding-bottom: 0.8rem;\n}\n.am-list-news-hd a {\n  display: block;\n}\n.am-list-news-hd h2 {\n  font-size: 1.6rem;\n  float: left;\n  margin: 0;\n  height: 2rem;\n  line-height: 2rem;\n}\n.am-list-news-hd h3 {\n  margin: 0;\n}\n.am-list-news-hd .am-list-news-more {\n  font-size: 1.3rem;\n  height: 2rem;\n  line-height: 2rem;\n}\n.am-list .am-list-item-dated a {\n  padding-right: 80px;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-list .am-list-item-dated a::after {\n  display: none;\n}\n.am-list .am-list-item-desced a,\n.am-list .am-list-item-thumbed a {\n  padding-right: 0;\n}\n.am-list-news .am-list-item-hd {\n  margin: 0;\n}\n.am-list-date {\n  position: absolute;\n  right: 5px;\n  font-size: 1.3rem;\n  top: 1.3rem;\n}\n.am-list-item-desced {\n  padding-bottom: 1rem;\n}\n.am-list-item-desced > a {\n  padding: 1rem 0;\n}\n.am-list-item-desced .am-list-date {\n  position: static;\n}\n.am-list-item-thumbed {\n  padding-top: 1em;\n}\n.am-list-news-ft {\n  text-align: center;\n}\n.am-list-news .am-titlebar {\n  margin-left: 0;\n  margin-right: 0;\n}\n.am-list-news .am-titlebar ~ .am-list-news-bd .am-list > li:first-child {\n  border-top: none;\n}\n/**\n  * list_news Theme: default\n  */\n.am-list-news-default {\n  margin: 10px;\n}\n.am-list-news-default .am-g {\n  margin-left: auto;\n  margin-right: auto;\n}\n.am-list-news-default .am-list-item-hd {\n  font-weight: normal;\n}\n.am-list-news-default .am-list-date {\n  color: #999999;\n}\n.am-list-news-default .am-list > li {\n  border-color: #dedede;\n}\n.am-list-news-default .am-list .am-list-item-desced {\n  padding-top: 1rem;\n  padding-bottom: 1rem;\n}\n.am-list-news-default .am-list .am-list-item-desced > a {\n  padding: 0;\n}\n.am-list-news-default .am-list .am-list-item-desced .am-list-item-text {\n  margin-top: 0.5rem;\n  color: #757575;\n}\n.am-list-news-default .am-list .am-list-item-text {\n  overflow: hidden;\n  text-overflow: ellipsis;\n  display: -webkit-box;\n  -webkit-box-orient: vertical;\n  line-height: 1.3em;\n  -webkit-line-clamp: 2;\n  /* number of lines to show */\n  max-height: 2.6em;\n}\n.am-list-news-default .am-list .am-list-item-thumb-top .am-list-thumb {\n  padding: 0;\n  margin-bottom: 0.8rem;\n}\n.am-list-news-default .am-list .am-list-item-thumb-top .am-list-main {\n  padding: 0;\n}\n.am-list-news-default .am-list .am-list-item-thumb-left .am-list-thumb {\n  padding-left: 0;\n}\n.am-list-news-default .am-list .am-list-item-desced .am-list-main {\n  padding: 0;\n}\n.am-list-news-default .am-list .am-list-item-thumb-right .am-list-thumb {\n  padding-right: 0;\n}\n.am-list-news-default .am-list .am-list-item-thumb-bottom-left .am-list-item-hd {\n  clear: both;\n  padding-bottom: 0.5rem;\n}\n.am-list-news-default .am-list .am-list-item-thumb-bottom-left .am-list-thumb {\n  padding-left: 0;\n}\n.am-list-news-default .am-list .am-list-item-thumb-bottom-right .am-list-item-hd {\n  clear: both;\n  padding-bottom: 0.5rem;\n}\n.am-list-news-default .am-list .am-list-item-thumb-bottom-right .am-list-thumb {\n  padding-right: 0;\n}\n.am-list-news-default .am-list .am-list-thumb img {\n  width: 100%;\n  display: block;\n}\n@media only screen and (max-width: 640px) {\n  .am-list-news-default .am-list-item-thumb-left .am-list-thumb,\n  .am-list-news-default .am-list-item-thumb-right .am-list-thumb {\n    max-height: 80px;\n    overflow: hidden;\n  }\n  .am-list-news-default .am-list-item-thumb-bottom-left .am-list-item-text,\n  .am-list-news-default .am-list-item-thumb-bottom-right .am-list-item-text {\n    -webkit-line-clamp: 3;\n    /* number of lines to show */\n    max-height: 3.9em;\n  }\n  .am-list-news-default .am-list-item-thumb-bottom-left .am-list-thumb,\n  .am-list-news-default .am-list-item-thumb-bottom-right .am-list-thumb {\n    max-height: 60px;\n    overflow: hidden;\n  }\n}\n.am-map {\n  width: 100%;\n  height: 300px;\n}\n/**\n  * Accordion Theme: default\n  * Author: Hzp (hzp@yunshipei.com)\n  */\n.am-map-default #bd-map {\n  width: 100%;\n  height: 100%;\n  overflow: hidden;\n  margin: 0;\n  font-size: 14px;\n  line-height: 1.4!important;\n}\n.am-map-default .BMap_bubble_title {\n  font-weight: bold;\n}\n.am-map-default #BMap_mask {\n  width: 100%;\n}\n.am-mechat {\n  margin: 1rem;\n}\n.am-mechat .section-cbox-wap .cbox-post-wap .post-action-wap .action-function-wap .function-list-wap .list-upload-wap .upload-mutual-wap {\n  -webkit-box-sizing: content-box;\n          box-sizing: content-box;\n}\n.am-menu {\n  position: relative;\n  padding: 0;\n  margin: 0;\n}\n.am-menu ul {\n  padding: 0;\n  margin: 0;\n}\n.am-menu li {\n  list-style: none;\n}\n.am-menu a:after,\n.am-menu a:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n}\n.am-menu-sub {\n  z-index: 1050;\n}\n.am-menu-toggle {\n  display: none;\n  z-index: 1015;\n}\n.am-menu-toggle img {\n  display: inline-block;\n  height: 16px;\n  width: auto;\n  vertical-align: middle;\n}\n.am-menu-nav a {\n  display: block;\n  padding: 0.8rem 0;\n  -webkit-transition: all 0.45s;\n  transition: all 0.45s;\n}\n/**\n  * Menu Theme: default\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-menu-default .am-menu-nav {\n  padding-top: 8px;\n  padding-bottom: 8px;\n}\n.am-menu-default .am-menu-nav a {\n  text-align: center;\n  height: 36px;\n  line-height: 36px;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n  padding: 0;\n  color: #0e90d2;\n}\n.am-menu-default .am-menu-nav > .am-parent > a {\n  position: relative;\n  -webkit-transition: .15s;\n  transition: .15s;\n}\n.am-menu-default .am-menu-nav > .am-parent > a:after {\n  content: \"\\f107\";\n  margin-left: 5px;\n  -webkit-transition: .15s;\n  transition: .15s;\n}\n.am-menu-default .am-menu-nav > .am-parent > a:before {\n  position: absolute;\n  top: 100%;\n  margin-top: -16px;\n  left: 50%;\n  margin-left: -12px;\n  content: \"\\f0d8\";\n  display: none;\n  color: #f1f1f1;\n  font-size: 24px;\n}\n.am-menu-default .am-menu-nav > .am-parent.am-open > a {\n  color: #095f8a;\n}\n.am-menu-default .am-menu-nav > .am-parent.am-open > a:before {\n  display: block;\n}\n.am-menu-default .am-menu-nav > .am-parent.am-open > a:after {\n  -webkit-transform: rotate(-180deg);\n      -ms-transform: rotate(-180deg);\n          transform: rotate(-180deg);\n}\n.am-menu-default .am-menu-sub {\n  position: absolute;\n  left: 5px;\n  right: 5px;\n  background-color: #f1f1f1;\n  border-radius: 2px;\n  padding-top: 8px;\n  padding-bottom: 8px;\n}\n.am-menu-default .am-menu-sub > li > a {\n  color: #555555;\n}\n@media only screen and (min-width:641px) {\n  .am-menu-default .am-menu-nav li {\n    width: auto;\n    float: left;\n    clear: none;\n    display: inline;\n  }\n  .am-menu-default .am-menu-nav a {\n    padding-left: 1.5rem;\n    padding-right: .5rem;\n  }\n}\n/**\n/**\n  * Menu Theme: dropdown1\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-menu-dropdown1 {\n  position: relative;\n  /*@media @medium-up {\n    .am-menu-toggle {\n      display: none!important;\n    }\n\n    .am-menu-nav {\n      &.am-collapse {\n        display: block;\n      }\n\n      .am-menu-sub {\n        background-color: ;//@menu-sub-bg;\n        display: block;\n        & > li {\n          clear: none;\n\n        }\n      }\n\n      .am-menu-lv2 {\n        & > li {\n          clear: none;\n          width: auto;\n        }\n      }\n    }\n  }*/\n}\n.am-menu-dropdown1 .am-menu-toggle {\n  position: absolute;\n  right: 5px;\n  top: -47px;\n  display: block;\n  width: 44px;\n  height: 44px;\n  line-height: 44px;\n  text-align: center;\n  color: #fff;\n}\n.am-menu-dropdown1 a {\n  -webkit-transition: all .4s;\n  transition: all .4s;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-menu-dropdown1 .am-menu-nav {\n  position: absolute;\n  left: 0;\n  right: 0;\n  z-index: 1050;\n}\n.am-menu-dropdown1 .am-menu-nav a {\n  padding: 0.8rem;\n}\n.am-menu-dropdown1 .am-menu-nav > li {\n  width: 100%;\n}\n.am-menu-dropdown1 .am-menu-nav > li.am-parent > a {\n  position: relative;\n}\n.am-menu-dropdown1 .am-menu-nav > li.am-parent > a::before {\n  content: \"\\f067\";\n  position: absolute;\n  right: 1rem;\n  top: 1.4rem;\n}\n.am-menu-dropdown1 .am-menu-nav > li.am-parent.am-open > a {\n  background-color: #0c80ba;\n  border-bottom: none;\n  color: #fff;\n}\n.am-menu-dropdown1 .am-menu-nav > li.am-parent.am-open > a:before {\n  content: \"\\f068\";\n}\n.am-menu-dropdown1 .am-menu-nav > li.am-parent.am-open > a:after {\n  content: \"\";\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: middle;\n  border-top: 8px solid #0c80ba;\n  border-right: 8px solid transparent;\n  border-left: 8px solid transparent;\n  border-bottom: 0 dotted;\n  -webkit-transform: rotate(360deg);\n      -ms-transform: rotate(360deg);\n          transform: rotate(360deg);\n  position: absolute;\n  top: 100%;\n  left: 50%;\n  margin-left: -4px;\n}\n.am-menu-dropdown1 .am-menu-nav > li > a {\n  border-bottom: 1px solid #0b76ac;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);\n  background-color: #0e90d2;\n  color: #fff;\n  height: 49px;\n  line-height: 49px;\n  padding: 0;\n  text-indent: 10px;\n}\n.am-menu-dropdown1 .am-menu-sub {\n  background-color: #fff;\n}\n.am-menu-dropdown1 .am-menu-sub a {\n  color: #555;\n  height: 44px;\n  line-height: 44px;\n  text-indent: 5px;\n  padding: 0;\n}\n.am-menu-dropdown1 .am-menu-sub a:before {\n  content: \"\\f105\";\n  color: #aaa;\n  font-size: 16px;\n  margin-right: 5px;\n}\n/**\n  * Menu Theme: dropdown2\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-menu-dropdown2 .am-menu-toggle {\n  position: absolute;\n  right: 5px;\n  top: -47px;\n  display: block;\n  width: 44px;\n  height: 44px;\n  line-height: 44px;\n  text-align: center;\n  color: #fff;\n}\n.am-menu-dropdown2 .am-menu-nav {\n  position: absolute;\n  left: 0;\n  right: 0;\n  background-color: #f5f5f5;\n  -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);\n  z-index: 1050;\n  padding-top: 8px;\n  padding-bottom: 8px;\n}\n.am-menu-dropdown2 .am-menu-nav a {\n  height: 38px;\n  line-height: 38px;\n  padding: 0;\n  text-align: center;\n}\n.am-menu-dropdown2 .am-menu-nav > li > a {\n  color: #333333;\n}\n.am-menu-dropdown2 .am-menu-nav > li.am-parent > a {\n  position: relative;\n}\n.am-menu-dropdown2 .am-menu-nav > li.am-parent > a:after {\n  content: \"\\f107\";\n  margin-left: 5px;\n  -webkit-transition: -webkit-transform .2s;\n  transition: -webkit-transform .2s;\n  transition: transform .2s;\n  transition: transform .2s, -webkit-transform .2s;\n}\n.am-menu-dropdown2 .am-menu-nav > li.am-parent.am-open > a {\n  position: relative;\n}\n.am-menu-dropdown2 .am-menu-nav > li.am-parent.am-open > a:after {\n  color: #0e90d2;\n  -webkit-transform: rotate(180deg);\n      -ms-transform: rotate(180deg);\n          transform: rotate(180deg);\n}\n.am-menu-dropdown2 .am-menu-nav > li.am-parent.am-open > a:before {\n  position: absolute;\n  top: 100%;\n  margin-top: -16px;\n  left: 50%;\n  margin-left: -12px;\n  font-size: 24px;\n  content: \"\\f0d8\";\n  color: rgba(0, 0, 0, 0.2);\n}\n.am-menu-dropdown2 .am-menu-sub {\n  position: absolute;\n  left: 5px;\n  right: 5px;\n  padding: 8px 0;\n  border-radius: 2px;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n  background-color: #fff;\n  z-index: 1055;\n}\n.am-menu-dropdown2 .am-menu-sub a {\n  padding: 0;\n  height: 35px;\n  color: #555555;\n  line-height: 35px;\n}\n@media only screen and (min-width:641px) {\n  .am-menu-dropdown2 .am-menu-toggle {\n    display: none !important;\n  }\n  .am-menu-dropdown2 .am-menu-nav {\n    position: static;\n    display: block;\n  }\n  .am-menu-dropdown2 .am-menu-nav > li {\n    float: none;\n    width: auto;\n    display: inline-block;\n  }\n  .am-menu-dropdown2 .am-menu-nav > li a {\n    padding-left: 1.5rem;\n    padding-right: 1.5rem;\n  }\n  .am-menu-dropdown2 .am-menu-sub {\n    left: auto;\n    right: auto;\n  }\n  .am-menu-dropdown2 .am-menu-sub > li {\n    float: none;\n    width: auto;\n  }\n  .am-menu-dropdown2 .am-menu-sub a {\n    padding-left: 2rem;\n    padding-right: 2rem;\n  }\n}\n/**\n  * Menu Theme: slide1\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-menu-slide1 .am-menu-toggle {\n  position: absolute;\n  right: 5px;\n  top: -47px;\n  display: block;\n  width: 44px;\n  height: 44px;\n  line-height: 44px;\n  text-align: center;\n  color: #fff;\n}\n.am-menu-slide1 .am-menu-nav {\n  background-color: #f5f5f5;\n  padding-top: 8px;\n  padding-bottom: 8px;\n}\n.am-menu-slide1 .am-menu-nav.am-in:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f0d8\";\n  font-size: 24px;\n  color: #f5f5f5;\n  position: absolute;\n  right: 16px;\n  top: -16px;\n}\n.am-menu-slide1 .am-menu-nav a {\n  line-height: 38px;\n  height: 38px;\n  display: block;\n  padding: 0;\n  text-align: center;\n}\n.am-menu-slide1 .am-menu-nav > li > a {\n  color: #333333;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-menu-slide1 .am-menu-nav > .am-parent > a {\n  position: relative;\n  -webkit-transition: .15s;\n  transition: .15s;\n}\n.am-menu-slide1 .am-menu-nav > .am-parent > a:after {\n  content: \"\\f107\";\n  margin-left: 5px;\n  -webkit-transition: .15s;\n  transition: .15s;\n}\n.am-menu-slide1 .am-menu-nav > .am-parent > a:before {\n  position: absolute;\n  top: 100%;\n  margin-top: -16px;\n  left: 50%;\n  margin-left: -12px;\n  content: \"\\f0d8\";\n  display: none;\n  color: #0e90d2;\n  font-size: 24px;\n}\n.am-menu-slide1 .am-menu-nav > .am-parent.am-open > a {\n  color: #0e90d2;\n}\n.am-menu-slide1 .am-menu-nav > .am-parent.am-open > a:before {\n  display: block;\n}\n.am-menu-slide1 .am-menu-nav > .am-parent.am-open > a:after {\n  -webkit-transform: rotate(-180deg);\n      -ms-transform: rotate(-180deg);\n          transform: rotate(-180deg);\n}\n.am-menu-slide1 .am-menu-sub {\n  position: absolute;\n  left: 5px;\n  right: 5px;\n  background-color: #0e90d2;\n  border-radius: 2px;\n  padding-top: 8px;\n  padding-bottom: 8px;\n}\n.am-menu-slide1 .am-menu-sub > li > a {\n  color: #fff;\n}\n@media only screen and (min-width:641px) {\n  .am-menu-slide1 .am-menu-toggle {\n    display: none !important;\n  }\n  .am-menu-slide1 .am-menu-nav {\n    background-color: #f5f5f5;\n    display: block;\n  }\n  .am-menu-slide1 .am-menu-nav.am-in:before {\n    display: none;\n  }\n  .am-menu-slide1 .am-menu-nav li {\n    width: auto;\n    clear: none;\n  }\n  .am-menu-slide1 .am-menu-nav li a {\n    padding-left: 1.5rem;\n    padding-right: 1.5rem;\n  }\n}\n/**\n  * Menu Theme: offcanvas1\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-menu-offcanvas1 .am-menu-toggle {\n  position: absolute;\n  right: 5px;\n  top: -47px;\n  display: block;\n  width: 44px;\n  height: 44px;\n  line-height: 44px;\n  text-align: center;\n  color: #fff;\n}\n.am-menu-offcanvas1 .am-menu-nav {\n  border-bottom: 1px solid rgba(0, 0, 0, 0.3);\n  -webkit-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.05);\n          box-shadow: 0 1px 0 rgba(255, 255, 255, 0.05);\n}\n.am-menu-offcanvas1 .am-menu-nav > li > a {\n  height: 44px;\n  line-height: 44px;\n  text-indent: 15px;\n  padding: 0;\n  position: relative;\n  color: #ccc;\n  border-top: 1px solid rgba(0, 0, 0, 0.3);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);\n  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.5);\n}\n.am-menu-offcanvas1 .am-menu-nav > .am-open > a,\n.am-menu-offcanvas1 .am-menu-nav > li > a:hover,\n.am-menu-offcanvas1 .am-menu-nav > li > a:focus {\n  background-color: #474747;\n  color: #fff;\n  outline: none;\n}\n.am-menu-offcanvas1 .am-menu-nav > .am-active > a {\n  background-color: #1a1a1a;\n  color: #fff;\n}\n.am-menu-offcanvas1 .am-menu-nav > .am-parent > a {\n  -webkit-transition: all .3s;\n  transition: all .3s;\n}\n.am-menu-offcanvas1 .am-menu-nav > .am-parent > a:after {\n  content: \"\\f104\";\n  position: absolute;\n  right: 1.5rem;\n  top: 1.3rem;\n}\n.am-menu-offcanvas1 .am-menu-nav > .am-parent.am-open > a:after {\n  content: \"\\f107\";\n}\n.am-menu-offcanvas1 .am-menu-sub {\n  border-top: 1px solid rgba(0, 0, 0, 0.3);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);\n  padding: 5px 0 5px 15px;\n  background-color: #1a1a1a;\n  font-size: 1.4rem;\n}\n.am-menu-offcanvas1 .am-menu-sub a {\n  color: #eee;\n}\n.am-menu-offcanvas1 .am-menu-sub a:hover {\n  color: #fff;\n}\n.am-menu-offcanvas1 .am-nav-divider {\n  border-top: 1px solid #1a1a1a;\n}\n/**\n  * Menu Theme: offcanvas2\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-menu-offcanvas2 .am-menu-toggle {\n  position: absolute;\n  right: 5px;\n  top: -47px;\n  display: block;\n  width: 44px;\n  height: 44px;\n  line-height: 44px;\n  text-align: center;\n  color: #fff;\n}\n.am-menu-offcanvas2 .am-menu-nav {\n  padding: 10px 5px;\n}\n.am-menu-offcanvas2 .am-menu-nav > li {\n  padding: 5px;\n}\n.am-menu-offcanvas2 .am-menu-nav > li > a {\n  -webkit-transition: all 0.3s;\n  transition: all 0.3s;\n  background-color: #404040;\n  color: #ccc;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);\n  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.5);\n  height: 44px;\n  line-height: 44px;\n  padding: 0;\n  text-align: center;\n}\n.am-menu-offcanvas2 .am-menu-nav > li > a:hover,\n.am-menu-offcanvas2 .am-menu-nav > li > a:focus {\n  background-color: #262626;\n  color: #fff;\n  outline: none;\n}\n.am-menu-offcanvas2 .am-menu-nav > .am-active > a {\n  background-color: #262626;\n  color: #fff;\n}\n/**\n  * Menu Theme: stack\n  * Author: Minwe (minwe@yunshipei.com)\n  */\n.am-menu-stack .am-menu-nav {\n  border-bottom: 1px solid #dedede;\n  -webkit-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.05);\n          box-shadow: 0 1px 0 rgba(255, 255, 255, 0.05);\n}\n.am-menu-stack .am-menu-nav > .am-parent > a {\n  -webkit-transition: all .3s;\n  transition: all .3s;\n}\n.am-menu-stack .am-menu-nav > .am-parent > a:after {\n  content: \"\\f105\";\n  position: absolute;\n  right: 1.5rem;\n  top: 1.3rem;\n  -webkit-transition: all .15s;\n  transition: all .15s;\n}\n.am-menu-stack .am-menu-nav > .am-parent.am-open > a:after {\n  -webkit-transform: rotate(90deg);\n      -ms-transform: rotate(90deg);\n          transform: rotate(90deg);\n}\n.am-menu-stack .am-menu-nav > li > a {\n  position: relative;\n  color: #333;\n  background-color: #f5f5f5;\n  border-top: 1px solid #dedede;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);\n  height: 49px;\n  line-height: 49px;\n  text-indent: 10px;\n  padding: 0;\n}\n.am-menu-stack .am-menu-nav > .am-open > a,\n.am-menu-stack .am-menu-nav > li > a:hover,\n.am-menu-stack .am-menu-nav > li > a:focus {\n  background-color: #e5e5e5;\n  color: #222;\n  outline: none;\n}\n.am-menu-stack .am-menu-sub {\n  padding: 0;\n  font-size: 1.4rem;\n  border-top: 1px solid #dedede;\n}\n.am-menu-stack .am-menu-sub a {\n  border-bottom: 1px solid #dedede;\n  padding-left: 2rem;\n  color: #444;\n}\n.am-menu-stack .am-menu-sub a:hover {\n  color: #333;\n}\n.am-menu-stack .am-menu-sub li:last-child a {\n  border-bottom: none;\n}\n.am-menu-stack .am-menu-sub > li > a {\n  height: 44px;\n  line-height: 44px;\n  text-indent: 15px;\n  padding: 0;\n}\n@media only screen and (min-width:641px) {\n  .am-menu-stack .am-menu-nav {\n    background-color: #f5f5f5;\n  }\n  .am-menu-stack .am-menu-nav > li {\n    float: left;\n    width: auto;\n    clear: none !important;\n    display: inline-block;\n  }\n  .am-menu-stack .am-menu-nav > li a {\n    padding-left: 1.5rem;\n    padding-right: 1.5rem;\n  }\n  .am-menu-stack .am-menu-nav > li.am-parent > a:after {\n    position: static;\n    content: \"\\f107\";\n  }\n  .am-menu-stack .am-menu-nav > li.am-parent.am-open a {\n    border-bottom: none;\n  }\n  .am-menu-stack .am-menu-nav > li.am-parent.am-open a:after {\n    -webkit-transform: rotateX(-180deg);\n            transform: rotateX(-180deg);\n  }\n  .am-menu-stack .am-menu-nav > li.am-parent.am-open .am-menu-sub {\n    background-color: #e5e5e5;\n  }\n  .am-menu-stack .am-menu-sub {\n    position: absolute;\n    left: 0;\n    right: 0;\n    background-color: #ddd;\n    border-top: none;\n  }\n  .am-menu-stack .am-menu-sub li {\n    width: auto;\n    float: left;\n    clear: none;\n  }\n}\n.am-navbar {\n  position: fixed;\n  left: 0;\n  bottom: 0;\n  width: 100%;\n  height: 49px;\n  line-height: 49px;\n  z-index: 1010;\n}\n.am-navbar ul {\n  padding-left: 0;\n  margin: 0;\n  list-style: none;\n  width: 100%;\n}\n.am-navbar .am-navbar-nav {\n  padding-left: 8px;\n  padding-right: 8px;\n  text-align: center;\n  overflow: hidden;\n  display: table;\n}\n.am-navbar .am-navbar-nav li {\n  display: table-cell;\n  width: 1%;\n  float: none;\n}\n.am-navbar-nav {\n  position: relative;\n  z-index: 1015;\n}\n.am-navbar-nav a {\n  display: inline-block;\n  width: 100%;\n  height: 49px;\n  line-height: 20px;\n}\n.am-navbar-nav a img {\n  display: block;\n  vertical-align: middle;\n  height: 24px;\n  width: 24px;\n  margin: 4px auto 0;\n}\n.am-navbar-nav a [class*=\"am-icon\"] {\n  width: 24px;\n  height: 24px;\n  margin: 4px auto 0;\n  display: block;\n  line-height: 24px;\n}\n.am-navbar-nav a [class*=\"am-icon\"]:before {\n  font-size: 22px;\n  vertical-align: middle;\n}\n.am-navbar-nav a .am-navbar-label {\n  padding-top: 2px;\n  line-height: 1;\n  font-size: 12px;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-navbar-more [class*=\"am-icon-\"] {\n  -webkit-transition: 0.15s;\n  transition: 0.15s;\n}\n.am-navbar-more.am-active [class*=\"am-icon-\"] {\n  -webkit-transform: rotateX(-180deg);\n          transform: rotateX(-180deg);\n}\n.am-navbar-actions {\n  position: absolute;\n  bottom: 49px;\n  right: 0;\n  left: 0;\n  z-index: 1009;\n  opacity: 0;\n  -webkit-transition: .3s;\n  transition: .3s;\n  -webkit-transform: translate(0, 100%);\n      -ms-transform: translate(0, 100%);\n          transform: translate(0, 100%);\n}\n.am-navbar-actions.am-active {\n  opacity: 1;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n}\n.am-navbar-actions li {\n  line-height: 42px;\n  position: relative;\n}\n.am-navbar-actions li a {\n  display: block;\n  width: 100%;\n  height: 40px;\n  -webkit-box-shadow: inset 0 1px rgba(220, 220, 220, 0.25);\n          box-shadow: inset 0 1px rgba(220, 220, 220, 0.25);\n  padding-left: 20px;\n  padding-right: 36px;\n}\n.am-navbar-actions li a :after {\n  font-family: \"FontAwesome\", sans-serif;\n  content: \"\\f105\";\n  display: inline-block;\n  position: absolute;\n  top: 0;\n  right: 20px;\n}\n.am-navbar-actions li a img {\n  vertical-align: middle;\n  height: 20px;\n  width: 20px;\n  display: inline;\n}\n#am-navbar-qrcode {\n  width: 220px;\n  height: 220px;\n  margin-left: -110px;\n}\n#am-navbar-qrcode .am-modal-bd {\n  padding: 10px;\n}\n#am-navbar-qrcode canvas {\n  display: block;\n  width: 200px;\n  height: 200px;\n}\n.am-with-fixed-navbar {\n  padding-bottom: 54px;\n}\n/**\n  * Navbar Theme: default\n  * Author: hzp (hzp@yunshipei.com)\n  */\n.am-navbar-default a {\n  color: #fff;\n}\n.am-navbar-default .am-navbar-nav {\n  background-color: #0e90d2;\n}\n.am-navbar-default .am-navbar-actions {\n  background-color: #0d86c4;\n}\n.am-navbar-default .am-navbar-actions a {\n  border-bottom: 1px solid #0b6fa2;\n}\n.am-pagination {\n  position: relative;\n}\n/**\n  * Pagination Theme: default\n  */\n.am-pagination-default {\n  margin-left: 10px;\n  margin-right: 10px;\n  font-size: 1.6rem;\n}\n.am-pagination-default .am-pagination-prev,\n.am-pagination-default .am-pagination-next {\n  float: none;\n}\n/**\n  * Pagination Theme: select\n  */\n.am-pagination-select {\n  margin-left: 10px;\n  margin-right: 10px;\n  font-size: 1.6rem;\n}\n.am-pagination-select > li > a {\n  line-height: 36px;\n  background-color: #eeeeee;\n  padding: 0 15px;\n  border: 0;\n  color: #555555;\n}\n.am-pagination-select .am-pagination-select {\n  position: absolute;\n  top: 0;\n  left: 50%;\n  margin-left: -35px;\n  width: 70px;\n  height: 36px;\n  text-align: center;\n  border-radius: 2px;\n}\n.am-pagination-select .am-pagination-select select {\n  display: block;\n  border: 0;\n  line-height: 36px;\n  width: 70px;\n  height: 36px;\n  border-radius: 2px;\n  color: #555555;\n  background-color: #eeeeee;\n  -webkit-appearance: none;\n  -moz-appearance: none;\n  appearance: none;\n  padding-left: 18px;\n}\n.am-paragraph p {\n  margin: 10px 0;\n}\n.am-paragraph img {\n  max-width: 100%;\n}\n.am-paragraph h1,\n.am-paragraph h2,\n.am-paragraph h3,\n.am-paragraph h4,\n.am-paragraph h5,\n.am-paragraph h6 {\n  color: #222222;\n}\n.am-paragraph table {\n  max-width: none;\n}\n.am-paragraph-table-container {\n  overflow: hidden;\n  background: #eeeeee;\n  max-width: none;\n}\n.am-paragraph-table-container table {\n  width: 100%;\n  max-width: none;\n}\n.am-paragraph-table-container table th {\n  background: #bce5fb;\n  height: 40px;\n  border: 1px solid #999999;\n  text-align: center;\n}\n.am-paragraph-table-container table td {\n  border: 1px solid #999999;\n  text-align: center;\n  vertical-align: middle;\n  background: #fff;\n}\n.am-paragraph-table-container table td p {\n  text-indent: 0;\n  font-size: 1.4rem;\n}\n.am-paragraph-table-container table td a {\n  font-size: 1.4rem;\n}\n/**\n  * Paragraph Theme: default\n  */\n.am-paragraph-default {\n  margin: 0 10px;\n  color: #333333;\n  background-color: transparent;\n}\n.am-paragraph-default p {\n  font-size: 1.4rem;\n}\n.am-paragraph-default img {\n  max-width: 98%;\n  display: block;\n  margin: 5px auto;\n  border: 1px solid #eeeeee;\n  padding: 2px;\n}\n.am-paragraph-default a {\n  color: #0e90d2;\n}\n/**\n  * Slider Theme: a1\n  */\n.am-slider-a1 {\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Control Nav */\n}\n.am-slider-a1 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-a1 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-a1 .am-control-nav {\n  width: 100%;\n  position: absolute;\n  bottom: 5px;\n  text-align: center;\n  line-height: 0;\n}\n.am-slider-a1 .am-control-nav li {\n  margin: 0 6px;\n  display: inline-block;\n}\n.am-slider-a1 .am-control-nav li a {\n  width: 8px;\n  height: 8px;\n  display: block;\n  background-color: rgba(0, 0, 0, 0.5);\n  cursor: pointer;\n  text-indent: -9999px;\n  border-radius: 50%;\n  -webkit-box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);\n          box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);\n}\n.am-slider-a1 .am-control-nav li a:hover {\n  background-color: rgba(0, 0, 0, 0.7);\n}\n.am-slider-a1 .am-control-nav li a.am-active {\n  background-color: #0e90d2;\n  cursor: default;\n}\n.am-slider-a1 .am-direction-nav,\n.am-slider-a1 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: a2\n  */\n.am-slider-a2 {\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Control Nav */\n}\n.am-slider-a2 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-a2 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-a2 .am-control-nav {\n  width: 100%;\n  position: absolute;\n  bottom: 5px;\n  text-align: center;\n  line-height: 0;\n}\n.am-slider-a2 .am-control-nav li {\n  margin: 0 6px;\n  display: inline-block;\n}\n.am-slider-a2 .am-control-nav li a {\n  width: 8px;\n  height: 8px;\n  display: block;\n  background-color: rgba(0, 0, 0, 0.5);\n  cursor: pointer;\n  text-indent: -9999px;\n  -webkit-box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);\n          box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);\n}\n.am-slider-a2 .am-control-nav li a:hover {\n  background-color: rgba(0, 0, 0, 0.7);\n}\n.am-slider-a2 .am-control-nav li a.am-active {\n  background: #0e93d7;\n  cursor: default;\n}\n.am-slider-a2 .am-direction-nav,\n.am-slider-a2 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: a3\n  */\n.am-slider-a3 {\n  margin-bottom: 20px;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Control Nav */\n}\n.am-slider-a3 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-a3 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-a3 .am-control-nav {\n  width: 100%;\n  position: absolute;\n  bottom: -20px;\n  text-align: center;\n  height: 20px;\n  background-color: #000;\n  padding-top: 5px;\n  line-height: 0;\n}\n.am-slider-a3 .am-control-nav li {\n  margin: 0 6px;\n  display: inline-block;\n}\n.am-slider-a3 .am-control-nav li a {\n  width: 8px;\n  height: 8px;\n  display: block;\n  background-color: rgba(0, 0, 0, 0.5);\n  cursor: pointer;\n  text-indent: -9999px;\n  border-radius: 50%;\n  -webkit-box-shadow: inset 0 0 3px rgba(200, 200, 200, 0.3);\n          box-shadow: inset 0 0 3px rgba(200, 200, 200, 0.3);\n}\n.am-slider-a3 .am-control-nav li a:hover {\n  background-color: rgba(0, 0, 0, 0.7);\n}\n.am-slider-a3 .am-control-nav li a.am-active {\n  background: #0e90d2;\n  cursor: default;\n}\n.am-slider-a3 .am-direction-nav,\n.am-slider-a3 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: a4\n  */\n.am-slider-a4 {\n  margin-bottom: 30px;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Control Nav */\n}\n.am-slider-a4 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-a4 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-a4 .am-control-nav {\n  width: 100%;\n  position: absolute;\n  bottom: -15px;\n  text-align: center;\n  line-height: 0;\n}\n.am-slider-a4 .am-control-nav li {\n  margin: 0 6px;\n  display: inline-block;\n}\n.am-slider-a4 .am-control-nav li a {\n  width: 8px;\n  height: 8px;\n  display: block;\n  background-color: rgba(0, 0, 0, 0.5);\n  cursor: pointer;\n  text-indent: -9999px;\n  border-radius: 50%;\n  -webkit-box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);\n          box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);\n}\n.am-slider-a4 .am-control-nav li a:hover {\n  background-color: rgba(0, 0, 0, 0.7);\n}\n.am-slider-a4 .am-control-nav li a.am-active {\n  background-color: #0e90d2;\n  cursor: default;\n}\n.am-slider-a4 .am-direction-nav,\n.am-slider-a4 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: a5\n  */\n.am-slider-a5 {\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Control Nav */\n}\n.am-slider-a5 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-a5 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-a5 .am-control-nav {\n  width: 100%;\n  position: absolute;\n  text-align: center;\n  height: 6px;\n  display: table;\n  bottom: 0;\n  font-size: 0;\n  line-height: 0;\n}\n.am-slider-a5 .am-control-nav li {\n  display: table-cell;\n}\n.am-slider-a5 .am-control-nav li a {\n  width: 100%;\n  height: 6px;\n  display: block;\n  background-color: rgba(0, 0, 0, 0.5);\n  cursor: pointer;\n  text-indent: -9999px;\n}\n.am-slider-a5 .am-control-nav li a:hover {\n  background-color: rgba(0, 0, 0, 0.7);\n}\n.am-slider-a5 .am-control-nav li a.am-active {\n  background-color: #0e90d2;\n  cursor: default;\n}\n.am-slider-a5 .am-direction-nav,\n.am-slider-a5 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: b1\n  */\n.am-slider-b1 {\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Direction Nav */\n}\n.am-slider-b1 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-b1 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-b1 .am-direction-nav a {\n  -webkit-box-sizing: content-box;\n          box-sizing: content-box;\n  display: block;\n  width: 24px;\n  height: 24px;\n  padding: 8px 0;\n  margin: -20px 0 0;\n  position: absolute;\n  top: 50%;\n  z-index: 10;\n  overflow: hidden;\n  opacity: 0.45;\n  cursor: pointer;\n  color: #fff;\n  text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3);\n  background-color: rgba(0, 0, 0, 0.5);\n  font-size: 0;\n  text-align: center;\n  -webkit-transition: all .3s ease;\n  transition: all .3s ease;\n}\n.am-slider-b1 .am-direction-nav a:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f053\";\n  font-size: 24px;\n}\n.am-slider-b1 .am-direction-nav a.am-prev {\n  left: 0;\n  padding-right: 5px;\n  border-bottom-right-radius: 5px;\n  border-top-right-radius: 5px;\n}\n.am-slider-b1 .am-direction-nav a.am-next {\n  right: 0;\n  padding-left: 5px;\n  border-bottom-left-radius: 5px;\n  border-top-left-radius: 5px;\n}\n.am-slider-b1 .am-direction-nav a.am-next:before {\n  content: \"\\f054\";\n}\n.am-slider-b1 .am-direction-nav .am-disabled {\n  opacity: 0!important;\n  cursor: default;\n}\n.am-slider-b1:hover .am-prev {\n  opacity: 0.7;\n}\n.am-slider-b1:hover .am-prev:hover {\n  opacity: 1;\n}\n.am-slider-b1:hover .am-next {\n  opacity: 0.7;\n}\n.am-slider-b1:hover .am-next:hover {\n  opacity: 1;\n}\n.am-slider-b1 .am-control-nav,\n.am-slider-b1 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: b2\n  */\n.am-slider-b2 {\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Direction Nav */\n}\n.am-slider-b2 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-b2 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-b2 .am-direction-nav a {\n  -webkit-box-sizing: content-box;\n          box-sizing: content-box;\n  display: block;\n  width: 24px;\n  height: 24px;\n  padding: 4px;\n  margin: -16px 0 0;\n  position: absolute;\n  top: 50%;\n  z-index: 10;\n  overflow: hidden;\n  opacity: 0.45;\n  cursor: pointer;\n  color: #fff;\n  text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3);\n  background-color: rgba(0, 0, 0, 0.5);\n  font-size: 0;\n  text-align: center;\n  border-radius: 50%;\n  -webkit-transition: all .3s ease;\n  transition: all .3s ease;\n}\n.am-slider-b2 .am-direction-nav a:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f053\";\n  font-size: 16px;\n  line-height: 24px;\n}\n.am-slider-b2 .am-direction-nav a.am-prev {\n  left: 5px;\n}\n.am-slider-b2 .am-direction-nav a.am-next {\n  right: 5px;\n}\n.am-slider-b2 .am-direction-nav a.am-next:before {\n  content: \"\\f054\";\n}\n.am-slider-b2 .am-direction-nav .am-disabled {\n  opacity: 0!important;\n  cursor: default;\n}\n.am-slider-b2:hover .am-prev {\n  opacity: 0.7;\n}\n.am-slider-b2:hover .am-prev:hover {\n  opacity: 1;\n}\n.am-slider-b2:hover .am-next {\n  opacity: 0.7;\n}\n.am-slider-b2:hover .am-next:hover {\n  opacity: 1;\n}\n.am-slider-b2 .am-control-nav,\n.am-slider-b2 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: b3\n  */\n.am-slider-b3 {\n  margin: 15px 30px;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Direction Nav */\n}\n.am-slider-b3 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-b3 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-b3 .am-direction-nav a {\n  -webkit-box-sizing: content-box;\n          box-sizing: content-box;\n  display: block;\n  width: 24px;\n  height: 24px;\n  padding: 4px;\n  margin: -16px 0 0;\n  position: absolute;\n  top: 50%;\n  z-index: 10;\n  overflow: hidden;\n  opacity: 0.45;\n  cursor: pointer;\n  color: #333333;\n  text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3);\n  font-size: 0;\n  -webkit-transition: all .3s ease;\n  transition: all .3s ease;\n}\n.am-slider-b3 .am-direction-nav a:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f053\";\n  font-size: 24px;\n}\n.am-slider-b3 .am-direction-nav a.am-prev {\n  left: -25px;\n}\n.am-slider-b3 .am-direction-nav a.am-next {\n  right: -25px;\n  text-align: right;\n}\n.am-slider-b3 .am-direction-nav a.am-next:before {\n  content: \"\\f054\";\n}\n.am-slider-b3 .am-direction-nav .am-disabled {\n  opacity: 0!important;\n  cursor: default;\n}\n.am-slider-b3:hover .am-prev {\n  opacity: 0.7;\n}\n.am-slider-b3:hover .am-prev:hover {\n  opacity: 1;\n}\n.am-slider-b3:hover .am-next {\n  opacity: 0.7;\n}\n.am-slider-b3:hover .am-next:hover {\n  opacity: 1;\n}\n.am-slider-b3 .am-control-nav,\n.am-slider-b3 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: b4\n  */\n.am-slider-b4 {\n  margin: 15px 20px;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Direction Nav */\n}\n.am-slider-b4 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-b4 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-b4 .am-direction-nav a {\n  position: absolute;\n  top: 50%;\n  z-index: 10;\n  display: block;\n  -webkit-box-sizing: content-box;\n          box-sizing: content-box;\n  width: 24px;\n  height: 24px;\n  margin: -16px 0 0;\n  padding: 4px;\n  overflow: hidden;\n  opacity: 0.45;\n  background-color: rgba(0, 0, 0, 0.8);\n  cursor: pointer;\n  text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3);\n  font-size: 0;\n  border-radius: 50%;\n  text-align: center;\n  color: #fff;\n  -webkit-transition: all .3s ease;\n  transition: all .3s ease;\n}\n.am-slider-b4 .am-direction-nav a:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f053\";\n  font-size: 20px;\n  line-height: 24px;\n}\n.am-slider-b4 .am-direction-nav a.am-prev {\n  left: -15px;\n}\n.am-slider-b4 .am-direction-nav a.am-next {\n  right: -15px;\n}\n.am-slider-b4 .am-direction-nav a.am-next:before {\n  content: \"\\f054\";\n}\n.am-slider-b4 .am-direction-nav .am-disabled {\n  opacity: 0!important;\n  cursor: default;\n}\n.am-slider-b4:hover .am-prev {\n  opacity: 0.7;\n}\n.am-slider-b4:hover .am-prev:hover {\n  opacity: 0.9;\n}\n.am-slider-b4:hover .am-next {\n  opacity: 0.7;\n}\n.am-slider-b4:hover .am-next:hover {\n  opacity: 0.9;\n}\n.am-slider-b4 .am-control-nav,\n.am-slider-b4 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: c1\n  */\n.am-slider-c1 {\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Control Nav */\n}\n.am-slider-c1 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-c1 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-c1 .am-control-nav {\n  position: absolute;\n  bottom: 0;\n  display: table;\n  width: 100%;\n  height: 6px;\n  font-size: 0;\n  line-height: 0;\n  text-align: center;\n}\n.am-slider-c1 .am-control-nav li {\n  display: table-cell;\n  width: 1%;\n}\n.am-slider-c1 .am-control-nav li a {\n  width: 100%;\n  height: 6px;\n  display: block;\n  background-color: rgba(0, 0, 0, 0.7);\n  cursor: pointer;\n  text-indent: -9999px;\n}\n.am-slider-c1 .am-control-nav li a:hover {\n  background: rgba(0, 0, 0, 0.8);\n}\n.am-slider-c1 .am-control-nav li a.am-active {\n  background-color: #0e90d2;\n  cursor: default;\n}\n.am-slider-c1 .am-slider-desc {\n  background-color: rgba(0, 0, 0, 0.6);\n  position: absolute;\n  bottom: 6px;\n  padding: 8px;\n  width: 100%;\n  color: #fff;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-slider-c1 .am-direction-nav,\n.am-slider-c1 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: c2\n  */\n.am-slider-c2 {\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Control Nav */\n}\n.am-slider-c2 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-c2 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-c2 .am-control-nav {\n  position: absolute;\n  bottom: 15px;\n  right: 0;\n  height: 6px;\n  text-align: center;\n  font-size: 0;\n  line-height: 0;\n}\n.am-slider-c2 .am-control-nav li {\n  display: inline-block;\n  margin-right: 6px;\n}\n.am-slider-c2 .am-control-nav li a {\n  width: 6px;\n  height: 6px;\n  display: block;\n  background-color: rgba(255, 255, 255, 0.4);\n  cursor: pointer;\n  text-indent: -9999px;\n}\n.am-slider-c2 .am-control-nav li a:hover {\n  background: rgba(230, 230, 230, 0.4);\n}\n.am-slider-c2 .am-control-nav li a.am-active {\n  background-color: #0e90d2;\n  cursor: default;\n}\n.am-slider-c2 .am-slider-desc {\n  background-color: rgba(0, 0, 0, 0.6);\n  position: absolute;\n  bottom: 0;\n  padding: 8px 60px 8px 8px;\n  width: 100%;\n  color: #fff;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-slider-c2 .am-direction-nav,\n.am-slider-c2 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: c3\n  */\n.am-slider-c3 {\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Direction Nav */\n}\n.am-slider-c3 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-c3 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-c3 .am-slider-desc {\n  background-color: rgba(0, 0, 0, 0.6);\n  position: absolute;\n  bottom: 10px;\n  right: 60px;\n  height: 30px;\n  left: 0;\n  padding-right: 5px;\n  color: #fff;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-slider-c3 .am-slider-counter {\n  margin-right: 5px;\n  display: inline-block;\n  height: 30px;\n  background-color: #0e90d2;\n  width: 40px;\n  text-align: center;\n  line-height: 30px;\n  color: #eee;\n  font-size: 1rem;\n}\n.am-slider-c3 .am-slider-counter .am-active {\n  font-size: 1.8rem;\n  font-weight: bold;\n  color: #fff;\n}\n.am-slider-c3 .am-direction-nav a {\n  -webkit-box-sizing: content-box;\n          box-sizing: content-box;\n  display: block;\n  width: 24px;\n  height: 24px;\n  padding: 4px 0;\n  margin: -16px 0 0;\n  position: absolute;\n  top: 50%;\n  z-index: 10;\n  overflow: hidden;\n  opacity: 0.45;\n  cursor: pointer;\n  color: #fff;\n  text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3);\n  background-color: rgba(0, 0, 0, 0.5);\n  font-size: 0;\n  text-align: center;\n  -webkit-transition: all .3s ease;\n  transition: all .3s ease;\n}\n.am-slider-c3 .am-direction-nav a:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f053\";\n  font-size: 16px;\n  line-height: 24px;\n}\n.am-slider-c3 .am-direction-nav a.am-prev {\n  left: 0;\n  padding-right: 5px;\n}\n.am-slider-c3 .am-direction-nav a.am-next {\n  right: 0;\n  padding-left: 5px;\n}\n.am-slider-c3 .am-direction-nav a.am-next:before {\n  content: \"\\f054\";\n}\n.am-slider-c3 .am-direction-nav .am-disabled {\n  opacity: 0!important;\n  cursor: default;\n}\n.am-slider-c3:hover .am-prev {\n  opacity: 0.7;\n}\n.am-slider-c3:hover .am-prev:hover {\n  opacity: 1;\n}\n.am-slider-c3:hover .am-next {\n  opacity: 0.7;\n}\n.am-slider-c3:hover .am-next:hover {\n  opacity: 1;\n}\n.am-slider-c3 .am-control-nav,\n.am-slider-c3 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: c4\n  */\n.am-slider-c4 {\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Direction Nav */\n}\n.am-slider-c4 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-c4 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-c4 .am-slider-desc {\n  width: 100%;\n  background-color: rgba(0, 0, 0, 0.6);\n  position: absolute;\n  bottom: 0;\n  right: 0;\n  left: 0;\n  padding: 8px 40px;\n  color: #fff;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-slider-c4 .am-direction-nav a {\n  -webkit-box-sizing: content-box;\n          box-sizing: content-box;\n  display: block;\n  width: 24px;\n  height: 24px;\n  padding: 4px 0;\n  margin: 0;\n  position: absolute;\n  bottom: 4px;\n  z-index: 10;\n  overflow: hidden;\n  opacity: 0.45;\n  cursor: pointer;\n  text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3);\n  font-size: 0;\n  text-align: center;\n  color: rgba(0, 0, 0, 0.7);\n  -webkit-transition: all .3s ease;\n  transition: all .3s ease;\n}\n.am-slider-c4 .am-direction-nav a:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f053\";\n  font-size: 24px;\n}\n.am-slider-c4 .am-direction-nav a.am-prev {\n  left: 0;\n  padding-right: 5px;\n}\n.am-slider-c4 .am-direction-nav a.am-next {\n  right: 0;\n  padding-left: 5px;\n}\n.am-slider-c4 .am-direction-nav a.am-next:before {\n  content: \"\\f054\";\n}\n.am-slider-c4 .am-direction-nav .am-disabled {\n  opacity: 0!important;\n  cursor: default;\n}\n.am-slider-c4:hover .am-prev {\n  opacity: 0.7;\n}\n.am-slider-c4:hover .am-prev:hover {\n  opacity: 1;\n}\n.am-slider-c4:hover .am-next {\n  opacity: 0.7;\n}\n.am-slider-c4:hover .am-next:hover {\n  opacity: 1;\n}\n.am-slider-c4 .am-control-nav,\n.am-slider-c4 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: d1\n  */\n.am-slider-d1 {\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Direction Nav */\n}\n.am-slider-d1 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-d1 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-d1 .am-slider-desc {\n  padding: 8px 35px;\n  width: 100%;\n  color: #fff;\n  background-color: #0e90d2;\n}\n.am-slider-d1 .am-slider-title {\n  font-weight: normal;\n  margin-bottom: 2px;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-slider-d1 .am-slider-more {\n  color: #eeeeee;\n  font-size: 1.3rem;\n}\n.am-slider-d1 .am-direction-nav a {\n  -webkit-box-sizing: content-box;\n          box-sizing: content-box;\n  display: block;\n  width: 24px;\n  height: 24px;\n  margin: 0;\n  position: absolute;\n  bottom: 18px;\n  z-index: 10;\n  overflow: hidden;\n  opacity: 0.45;\n  cursor: pointer;\n  text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3);\n  font-size: 0;\n  text-align: center;\n  border: 1px solid rgba(255, 255, 255, 0.9);\n  color: rgba(255, 255, 255, 0.9);\n  border-radius: 50%;\n  -webkit-transition: all 03s ease;\n  transition: all 03s ease;\n}\n.am-slider-d1 .am-direction-nav a:before {\n  display: inline-block;\n  font: normal normal normal 1.6rem/1 \"FontAwesome\", sans-serif;\n  /*font-weight: normal; // 2\n  font-style: normal; // 2\n  vertical-align: baseline; // 3\n  line-height: 1; // 4*/\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n  content: \"\\f053\";\n  font-size: 16px;\n  line-height: 24px;\n}\n.am-slider-d1 .am-direction-nav a.am-prev {\n  left: 5px;\n}\n.am-slider-d1 .am-direction-nav a.am-next {\n  right: 5px;\n}\n.am-slider-d1 .am-direction-nav a.am-next:before {\n  content: \"\\f054\";\n}\n.am-slider-d1 .am-direction-nav .am-disabled {\n  opacity: 0!important;\n  cursor: default;\n}\n.am-slider-d1:hover .am-prev {\n  opacity: 0.7;\n}\n.am-slider-d1:hover .am-prev:hover {\n  opacity: 1;\n}\n.am-slider-d1:hover .am-next {\n  opacity: 0.7;\n}\n.am-slider-d1:hover .am-next:hover {\n  opacity: 1;\n}\n.am-slider-d1 .am-control-nav,\n.am-slider-d1 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: d2\n  */\n.am-slider-d2 {\n  margin-bottom: 20px;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Control Nav */\n}\n.am-slider-d2 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-d2 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-d2 .am-slider-desc {\n  position: absolute;\n  left: 10px;\n  bottom: 20px;\n  right: 50px;\n  color: #fff;\n}\n.am-slider-d2 .am-slider-content {\n  background-color: rgba(0, 0, 0, 0.7);\n  padding: 10px 6px;\n  margin-bottom: 10px;\n}\n.am-slider-d2 .am-slider-content p {\n  margin: 0;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n  font-size: 1.4rem;\n}\n.am-slider-d2 .am-slider-title {\n  font-weight: normal;\n  margin-bottom: 5px;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-slider-d2 .am-slider-more {\n  color: #eeeeee;\n  font-size: 1.3rem;\n  background-color: #0e90d2;\n  padding: 2px 10px;\n}\n.am-slider-d2 .am-control-nav {\n  width: 100%;\n  position: absolute;\n  bottom: -15px;\n  text-align: center;\n}\n.am-slider-d2 .am-control-nav li {\n  margin: 0 6px;\n  display: inline-block;\n}\n.am-slider-d2 .am-control-nav li a {\n  width: 8px;\n  height: 8px;\n  display: block;\n  background-color: rgba(0, 0, 0, 0.5);\n  cursor: pointer;\n  text-indent: -9999px;\n  border-radius: 50%;\n  font-size: 0;\n  line-height: 0;\n  -webkit-box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);\n          box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);\n}\n.am-slider-d2 .am-control-nav li a:hover {\n  background: rgba(0, 0, 0, 0.5);\n}\n.am-slider-d2 .am-control-nav li a.am-active {\n  background: #0e90d2;\n  cursor: default;\n}\n.am-slider-d2 .am-direction-nav,\n.am-slider-d2 .am-pauseplay {\n  display: none;\n}\n/**\n  * Slider Theme: d3\n  */\n.am-slider-d3 {\n  margin-bottom: 10px;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);\n  /* Control Nav */\n}\n.am-slider-d3 .am-viewport {\n  max-height: 2000px;\n  -webkit-transition: all 1s ease;\n  transition: all 1s ease;\n}\n.loading .am-slider-d3 .am-viewport {\n  max-height: 300px;\n}\n.am-slider-d3 .am-slider-desc {\n  position: absolute;\n  bottom: 0;\n  color: #fff;\n  width: 100%;\n  background-color: rgba(0, 0, 0, 0.7);\n  padding: 8px 5px;\n}\n.am-slider-d3 .am-slider-desc p {\n  margin: 0;\n  font-size: 1.3rem;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-slider-d3 .am-slider-title {\n  font-weight: normal;\n  margin-bottom: 5px;\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.am-slider-d3 .am-control-thumbs {\n  position: static;\n  overflow: hidden;\n}\n.am-slider-d3 .am-control-thumbs li {\n  padding: 12px 4px 4px;\n  position: relative;\n}\n.am-slider-d3 .am-control-thumbs img {\n  width: 100%;\n  display: block;\n  opacity: .85;\n  cursor: pointer;\n}\n.am-slider-d3 .am-control-thumbs img:hover {\n  opacity: 1;\n}\n.am-slider-d3 .am-control-thumbs .am-active {\n  opacity: 1;\n  cursor: default;\n}\n.am-slider-d3 .am-control-thumbs .am-active + i {\n  position: absolute;\n  top: 0;\n  left: 50%;\n  content: \"\";\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: middle;\n  border-top: 8px solid rgba(0, 0, 0, 0.7);\n  border-right: 8px solid transparent;\n  border-left: 8px solid transparent;\n  border-bottom: 0 dotted;\n  -webkit-transform: rotate(360deg);\n      -ms-transform: rotate(360deg);\n          transform: rotate(360deg);\n  margin-left: -4px;\n  -webkit-transition: all 0.2s;\n  transition: all 0.2s;\n}\n.am-slider-d3 .am-direction-nav,\n.am-slider-d3 .am-pauseplay {\n  display: none;\n}\n.am-slider-d3 .am-control-thumbs {\n  display: table;\n}\n.am-slider-d3 .am-control-thumbs li {\n  display: table-cell;\n  width: 1%;\n}\n[data-am-widget='tabs'] {\n  margin: 10px;\n}\n[data-am-widget='tabs'] .am-tabs-nav {\n  width: 100%;\n  padding: 0;\n  margin: 0;\n  list-style: none;\n  text-align: center;\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -ms-flexbox;\n  display: flex;\n}\n[data-am-widget='tabs'] .am-tabs-nav li {\n  -webkit-box-flex: 1;\n  -webkit-flex: 1;\n      -ms-flex: 1;\n          flex: 1;\n}\n[data-am-widget='tabs'] .am-tabs-nav a {\n  display: block;\n  word-wrap: normal;\n  /* for IE */\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n/**\n  * Tabs Theme: default\n  */\n.am-tabs-default .am-tabs-nav {\n  line-height: 40px;\n  background-color: #eeeeee;\n}\n.am-tabs-default .am-tabs-nav a {\n  color: #222222;\n  line-height: 42px;\n}\n.am-tabs-default .am-tabs-nav > .am-active a {\n  background-color: #0e90d2;\n  color: #fff;\n}\n/**\n  * Tabs Theme: d2\n  */\n.am-tabs-d2 .am-tabs-nav {\n  background-color: #eeeeee;\n}\n.am-tabs-d2 .am-tabs-nav li {\n  height: 42px;\n}\n.am-tabs-d2 .am-tabs-nav a {\n  color: #222222;\n  line-height: 42px;\n}\n.am-tabs-d2 .am-tabs-nav > .am-active {\n  position: relative;\n  background-color: #fcfcfc;\n  border-bottom: 2px solid #0e90d2;\n}\n.am-tabs-d2 .am-tabs-nav > .am-active a {\n  line-height: 40px;\n  color: #0e90d2;\n}\n.am-tabs-d2 .am-tabs-nav > .am-active:after {\n  position: absolute;\n  width: 0;\n  height: 0;\n  bottom: 0px;\n  left: 50%;\n  margin-left: -5px;\n  border: 6px rgba(0, 0, 0, 0) solid;\n  content: \"\";\n  z-index: 1;\n  border-bottom-color: #0e90d2;\n}\n.am-titlebar {\n  margin-top: 20px;\n  height: 45px;\n  font-size: 100%;\n}\n.am-titlebar h2 {\n  margin-top: 0;\n  margin-bottom: 0;\n  font-size: 1.6rem;\n}\n.am-titlebar .am-titlebar-title img {\n  height: 24px;\n  width: auto;\n}\n/**\n  * Titlebar Theme: default\n  */\n.am-titlebar-default {\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -ms-flexbox;\n  display: flex;\n  margin-left: 10px;\n  margin-right: 10px;\n  background-color: transparent;\n  border-bottom: 1px solid #dedede;\n  line-height: 44px;\n}\n.am-titlebar-default a {\n  color: #0e90d2;\n}\n.am-titlebar-default .am-titlebar-title {\n  position: relative;\n  padding-left: 12px;\n  color: #0e90d2;\n  font-size: 1.8rem;\n  text-align: left;\n  font-weight: bold;\n}\n.am-titlebar-default .am-titlebar-title:before {\n  content: \"\";\n  position: absolute;\n  left: 2px;\n  top: 8px;\n  bottom: 8px;\n  border-left: 3px solid #0e90d2;\n}\n.am-titlebar-default .am-titlebar-nav {\n  -webkit-box-flex: 1;\n  -webkit-flex: 1;\n      -ms-flex: 1;\n          flex: 1;\n  text-align: right;\n}\n.am-titlebar-default .am-titlebar-nav a {\n  margin-right: 10px;\n}\n.am-titlebar-default .am-titlebar-nav a:last-child {\n  margin-right: 5px;\n}\n/**\n  * Titlebar Theme: multi\n  */\n.am-titlebar-multi {\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -ms-flexbox;\n  display: flex;\n  background-color: #f5f5f5;\n  border-top: 2px solid #3bb4f2;\n  border-bottom: 1px solid #e8e8e8;\n}\n.am-titlebar-multi a {\n  color: #0e90d2;\n}\n.am-titlebar-multi .am-titlebar-title {\n  padding-left: 10px;\n  color: #0e90d2;\n  font-size: 1.8rem;\n  text-align: left;\n  font-weight: bold;\n  line-height: 42px;\n}\n.am-titlebar-multi .am-titlebar-nav {\n  -webkit-box-flex: 1;\n  -webkit-flex: 1;\n      -ms-flex: 1;\n          flex: 1;\n  text-align: right;\n  line-height: 42px;\n}\n.am-titlebar-multi .am-titlebar-nav a {\n  margin-right: 10px;\n}\n/**\n  * Titlebar Theme: cols\n  */\n.am-titlebar-cols {\n  position: relative;\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -ms-flexbox;\n  display: flex;\n  padding-left: 10px;\n  background-color: #f5f5f5;\n  color: #555555;\n  font-size: 18px;\n  border-top: 2px solid #e1e1e1;\n  line-height: 41px;\n}\n.am-titlebar-cols a {\n  color: #555555;\n}\n.am-titlebar-cols .am-titlebar-title {\n  color: #0e90d2;\n  margin-right: 15px;\n  border-bottom: 2px solid #0e90d2;\n  font-weight: bold;\n}\n.am-titlebar-cols .am-titlebar-title a {\n  color: #0e90d2;\n}\n.am-titlebar-cols .am-titlebar-nav {\n  -webkit-box-flex: 1;\n  -webkit-flex: 1;\n      -ms-flex: 1;\n          flex: 1;\n}\n.am-titlebar-cols .am-titlebar-nav a {\n  display: inline-block;\n  margin-right: 15px;\n  line-height: 41px;\n  border-bottom: 2px solid transparent;\n}\n.am-titlebar-cols .am-titlebar-nav a:hover {\n  color: #3c3c3c;\n  border-bottom-color: #0e90d2;\n}\n.am-titlebar-cols .am-titlebar-nav a:last-child {\n  margin-right: 10px;\n}\n.am-wechatpay .am-wechatpay-btn {\n  margin-top: 1rem;\n  margin-bottom: 1rem;\n}\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/base-component/amazeui/css/app.css",
    "content": "/* Write your styles */\nhtml,body{background: #444444;}\n/* 登陆logo */\n.myapp-login { background: #444444; background-size: 100%; height: 100%;}\n.myapp-login-logo-block { width: 100%;}\n.myapp-login-logo {width: 100%; text-align: center; padding-top: 30px;}\n.myapp-login-logo i { color: #eb602e; font-size: 120px;display: inline-block;}\n.myapp-login-logo-text {font-family: \"Lucida Grande\",Helvetica,Arial,\"Microsoft YaHei\",FreeSans,Arimo,\"Droid Sans\",\"wenquanyi micro hei\",\"Hiragino Sans GB\",\"Hiragino Sans GB W3\",FontAwesome,sans-serif;  color:#fff; font-weight: bold;font-size: 40px; margin-top: -40px; text-align: center; width: 100%;}\n.myapp-login-logo-text span {color: #eb602e;}\n.myapp-login-logo-text .info { padding-bottom: 30px; border-bottom: 1px solid #4d4d4d;font-family: FreeSans,Arimo,\"Droid Sans\",\"wenquanyi micro hei\",\"Hiragino Sans GB\",\"Hiragino Sans GB W3\",FontAwesome,sans-serif; width: 100%; font-weight: normal; font-size: 14px; color: #fff;}\n.login-font {font-size: 12px; font-family:\"wenquanyi micro hei\",\"Hiragino Sans GB\",\"Hiragino Sans GB W3\",FontAwesome,sans-serif; width: 100%; color: #5e5e5e; text-align: center; padding: 20px 0;}\n.login-font i {color: #eb602e; font-style: normal;}\n.login-font span { color: #fff;}\n.login-am-center { margin: 0 auto; float:none;}\n.login-am-center .am-form input { background: #565656; border: none;  font-size: 12px; line-height: 30px; text-indent: 10px;}\n.login-am-center .am-btn-default { width: 100%; background: #eb602e; border: none; color: #fff; font-size: 14px; line-height: 30px;}"
  },
  {
    "path": "open-layui-web/src/main/view/static/base-component/amazeui/js/amazeui.ie8polyfill.js",
    "content": "/*! Amaze UI v2.6.0 ~ IE8 Fucker | by Amaze UI Team | (c) 2016 AllMobilize, Inc. | Licensed under MIT | 2016-03-31T14:28:54+0800 */ \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/**\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.\nvar $Array = Array;\nvar ArrayPrototype = $Array.prototype;\nvar $Object = Object;\nvar ObjectPrototype = $Object.prototype;\nvar $Function = Function;\nvar FunctionPrototype = $Function.prototype;\nvar $String = String;\nvar StringPrototype = $String.prototype;\nvar $Number = Number;\nvar NumberPrototype = $Number.prototype;\nvar array_slice = ArrayPrototype.slice;\nvar array_splice = ArrayPrototype.splice;\nvar array_push = ArrayPrototype.push;\nvar array_unshift = ArrayPrototype.unshift;\nvar array_concat = ArrayPrototype.concat;\nvar array_join = ArrayPrototype.join;\nvar call = FunctionPrototype.call;\nvar apply = FunctionPrototype.apply;\nvar max = Math.max;\nvar min = Math.min;\n\n// Having a toString local variable name breaks in Opera so use to_string.\nvar to_string = ObjectPrototype.toString;\n\n/* global Symbol */\n/* eslint-disable one-var-declaration-per-line, no-redeclare */\nvar hasToStringTag = typeof Symbol === 'function' && typeof Symbol.toStringTag === 'symbol';\nvar 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\nvar 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; };\nvar 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 */\n\n/* inlined from http://npmjs.com/define-properties */\nvar supportsDescriptors = $Object.defineProperty && (function () {\n    try {\n        var obj = {};\n        $Object.defineProperty(obj, 'x', { enumerable: false, value: obj });\n        for (var _ in obj) { return false; }\n        return obj.x === obj;\n    } catch (e) { /* this is ES3 */\n        return false;\n    }\n}());\nvar 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)) { return; }\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)) { return; }\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 */\nvar isPrimitive = function isPrimitive(input) {\n    var type = typeof input;\n    return input === null || (type !== 'object' && type !== 'function');\n};\n\nvar isActualNaN = $Number.isNaN || function (x) { return x !== x; };\n\nvar 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\nvar Empty = function Empty() {};\n\ndefineProperties(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.\nvar owns = call.bind(ObjectPrototype.hasOwnProperty);\nvar toStr = call.bind(ObjectPrototype.toString);\nvar arraySlice = call.bind(array_slice);\nvar arraySliceApply = apply.bind(array_slice);\nvar strSlice = call.bind(StringPrototype.slice);\nvar strSplit = call.bind(StringPrototype.split);\nvar strIndexOf = call.bind(StringPrototype.indexOf);\nvar pushCall = call.bind(array_push);\nvar isEnum = call.bind(ObjectPrototype.propertyIsEnumerable);\nvar arraySort = call.bind(ArrayPrototype.sort);\n\n//\n// Array\n// =====\n//\n\nvar 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\"\nvar hasUnshiftReturnValueBug = [].unshift(0) !== 1;\ndefineProperties(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\ndefineProperties($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)\nvar boxedString = $Object('a');\nvar splitString = boxedString[0] !== 'a' || !(0 in boxedString);\n\nvar 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') { properlyBoxesNonStrict = false; }\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\ndefineProperties(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\ndefineProperties(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\ndefineProperties(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\ndefineProperties(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\ndefineProperties(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\nvar reduceCoercesToObject = false;\nif (ArrayPrototype.reduce) {\n    reduceCoercesToObject = typeof ArrayPrototype.reduce.call('es5', function (_, __, ___, list) { return list; }) === 'object';\n}\ndefineProperties(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\nvar reduceRightCoercesToObject = false;\nif (ArrayPrototype.reduceRight) {\n    reduceRightCoercesToObject = typeof ArrayPrototype.reduceRight.call('es5', function (_, __, ___, list) { return list; }) === 'object';\n}\ndefineProperties(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\nvar hasFirefox2IndexOfBug = ArrayPrototype.indexOf && [0, 1].indexOf(1, 2) !== -1;\ndefineProperties(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\nvar hasFirefox2LastIndexOfBug = ArrayPrototype.lastIndexOf && [0, 1].lastIndexOf(0, -3) !== -1;\ndefineProperties(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\nvar spliceNoopReturnsEmptyArray = (function () {\n    var a = [1, 2];\n    var result = a.splice();\n    return a.length === 2 && isArray(result) && result.length === 0;\n}());\ndefineProperties(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\nvar spliceWorksWithEmptyObject = (function () {\n    var obj = {};\n    ArrayPrototype.splice.call(obj, 0, 0, 1);\n    return obj.length === 1;\n}());\ndefineProperties(ArrayPrototype, {\n    splice: function splice(start, deleteCount) {\n        if (arguments.length === 0) { return []; }\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);\nvar 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}());\nvar 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}());\ndefineProperties(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\nvar originalJoin = ArrayPrototype.join;\nvar hasStringJoinBug;\ntry {\n    hasStringJoinBug = Array.prototype.join.call('123', ',') !== '1,2,3';\n} catch (e) {\n    hasStringJoinBug = true;\n}\nif (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\nvar hasJoinUndefinedBug = [1, 2].join(undefined) !== '1,2';\nif (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\nvar 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\nvar 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}());\ndefineProperties(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\nvar 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}());\ndefineProperties(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\ndefineProperties(ArrayPrototype, {\n    slice: function (start, end) {\n        var arr = isString(this) ? strSplit(this, '') : this;\n        return arraySliceApply(arr, arguments);\n    }\n}, splitString);\n\nvar sortIgnoresNonFunctions = (function () {\n    try {\n        [1, 2].sort(null);\n        [1, 2].sort({});\n        return true;\n    } catch (e) { /**/ }\n    return false;\n}());\nvar 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}());\nvar 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}());\ndefineProperties(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\nvar hasDontEnumBug = !({ 'toString': null }).propertyIsEnumerable('toString');\nvar hasProtoEnumBug = function () {}.propertyIsEnumerable('prototype');\nvar hasStringEnumBug = !owns('x', '0');\nvar equalsConstructorPrototype = function (o) {\n    var ctor = o.constructor;\n    return ctor && ctor.prototype === o;\n};\nvar 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};\nvar hasAutomationEqualityBug = (function () {\n    /* globals window */\n    if (typeof window === 'undefined') { return false; }\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}());\nvar equalsConstructorPrototypeIfNotBuggy = function (object) {\n    if (typeof window === 'undefined' || !hasAutomationEqualityBug) { return equalsConstructorPrototype(object); }\n    try {\n        return equalsConstructorPrototype(object);\n    } catch (e) {\n        return false;\n    }\n};\nvar dontEnums = [\n    'toString',\n    'toLocaleString',\n    'valueOf',\n    'hasOwnProperty',\n    'isPrototypeOf',\n    'propertyIsEnumerable',\n    'constructor'\n];\nvar 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\nvar isStandardArguments = function isArguments(value) {\n    return toStr(value) === '[object Arguments]';\n};\nvar 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};\nvar isArguments = isStandardArguments(arguments) ? isStandardArguments : isLegacyArguments;\n\ndefineProperties($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\nvar keysWorksWithArguments = $Object.keys && (function () {\n    // Safari 5.0 bug\n    return $Object.keys(arguments).length === 2;\n}(1, 2));\nvar keysHasArgumentsLengthBug = $Object.keys && (function () {\n    var argKeys = $Object.keys(arguments);\n    return arguments.length !== 1 || argKeys.length !== 1 || argKeys[0] !== 1;\n}(1));\nvar originalKeys = $Object.keys;\ndefineProperties($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\nvar hasNegativeMonthYearBug = new Date(-3509827329600292).getUTCMonth() !== 0;\nvar aNegativeTestDate = new Date(-1509842289600292);\nvar aPositiveTestDate = new Date(1449662400000);\nvar hasToUTCStringFormatBug = aNegativeTestDate.toUTCString() !== 'Mon, 01 Jan -45875 11:59:59 GMT';\nvar hasToDateStringFormatBug;\nvar hasToStringFormatBug;\nvar timeZoneOffset = aNegativeTestDate.getTimezoneOffset();\nif (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\nvar originalGetFullYear = call.bind(Date.prototype.getFullYear);\nvar originalGetMonth = call.bind(Date.prototype.getMonth);\nvar originalGetDate = call.bind(Date.prototype.getDate);\nvar originalGetUTCFullYear = call.bind(Date.prototype.getUTCFullYear);\nvar originalGetUTCMonth = call.bind(Date.prototype.getUTCMonth);\nvar originalGetUTCDate = call.bind(Date.prototype.getUTCDate);\nvar originalGetUTCDay = call.bind(Date.prototype.getUTCDay);\nvar originalGetUTCHours = call.bind(Date.prototype.getUTCHours);\nvar originalGetUTCMinutes = call.bind(Date.prototype.getUTCMinutes);\nvar originalGetUTCSeconds = call.bind(Date.prototype.getUTCSeconds);\nvar originalGetUTCMilliseconds = call.bind(Date.prototype.getUTCMilliseconds);\nvar dayName = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];\nvar monthName = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];\nvar daysInMonth = function daysInMonth(month, year) {\n    return originalGetDate(new Date(year, month, 0));\n};\n\ndefineProperties(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\ndefineProperties(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 `,`\ndefineProperties(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\nif (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.\nvar negativeDate = -62198755200000;\nvar negativeYearString = '-000001';\nvar hasNegativeDateBug = Date.prototype.toISOString && new Date(negativeDate).toISOString().indexOf(negativeYearString) === -1;\nvar hasSafari51DateBug = Date.prototype.toISOString && new Date(-1).toISOString() !== '1969-12-31T23:59:59.999Z';\n\nvar getTime = call.bind(Date.prototype.getTime);\n\ndefineProperties(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).\nvar 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}());\nif (!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\nvar supportsExtendedYears = Date.parse('+033658-09-27T01:46:40.000Z') === 1e15;\nvar 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'));\nvar doesNotParseY2KNewYear = isNaN(Date.parse('2000-01-01T00:00:00.000Z'));\nif (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\nif (!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\nvar 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\nvar 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\nvar 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};\ndefineProperties(NumberPrototype, { toFixed: toFixedShim }, hasToFixedBugs);\n\nvar hasToPrecisionUndefinedBug = (function () {\n    try {\n        return 1.0.toPrecision(undefined) === '1';\n    } catch (e) {\n        return true;\n    }\n}());\nvar originalToPrecision = NumberPrototype.toPrecision;\ndefineProperties(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\nif (\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) { return []; }\n        return strSplit(this, separator, limit);\n    };\n}\n\nvar str_replace = StringPrototype.replace;\nvar 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\nif (!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\nvar string_substr = StringPrototype.substr;\nvar hasNegativeSubstrBug = ''.substr && '0b'.substr(-1) !== 'b';\ndefineProperties(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\nvar 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';\nvar zeroWidth = '\\u200b';\nvar wsRegexChars = '[' + ws + ']';\nvar trimBeginRegexp = new RegExp('^' + wsRegexChars + wsRegexChars + '*');\nvar trimEndRegexp = new RegExp(wsRegexChars + wsRegexChars + '*$');\nvar hasTrimWhitespaceBug = StringPrototype.trim && (ws.trim() || !zeroWidth.trim());\ndefineProperties(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);\nvar trim = call.bind(String.prototype.trim);\n\nvar hasLastIndexBug = StringPrototype.lastIndexOf && 'abcあい'.lastIndexOf('あい', 2) !== -1;\ndefineProperties(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\nvar originalLastIndexOf = StringPrototype.lastIndexOf;\ndefineProperties(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 */\nif (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(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\nif (1 / parseFloat('-0') !== -Infinity) {\n    /* global parseFloat: true */\n    parseFloat = (function (origParseFloat) {\n        return function parseFloat(string) {\n            var inputString = trim(string);\n            var result = origParseFloat(inputString);\n            return result === 0 && strSlice(inputString, 0, 1) === '-' ? -0 : result;\n        };\n    }(parseFloat));\n}\n\nif (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\nif (supportsDescriptors) {\n    var ensureNonEnumerable = function (obj, prop) {\n        if (isEnum(obj, prop)) {\n            var desc = Object.getOwnPropertyDescriptor(obj, prop);\n            desc.enumerable = false;\n            Object.defineProperty(obj, prop, desc);\n        }\n    };\n    ensureNonEnumerable(Error.prototype, 'message');\n    if (Error.prototype.message !== '') {\n      Error.prototype.message = '';\n    }\n    ensureNonEnumerable(Error.prototype, 'name');\n}\n\nif (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\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\nvar call = Function.call;\nvar prototypeOfObject = Object.prototype;\nvar owns = call.bind(prototypeOfObject.hasOwnProperty);\nvar isEnumerable = call.bind(prototypeOfObject.propertyIsEnumerable);\nvar toStr = call.bind(prototypeOfObject.toString);\n\n// If JS engine supports accessors creating shortcuts.\nvar defineGetter;\nvar defineSetter;\nvar lookupGetter;\nvar lookupSetter;\nvar supportsAccessors = owns(prototypeOfObject, '__defineGetter__');\nif (supportsAccessors) {\n    /* eslint-disable no-underscore-dangle */\n    defineGetter = call.bind(prototypeOfObject.__defineGetter__);\n    defineSetter = call.bind(prototypeOfObject.__defineSetter__);\n    lookupGetter = call.bind(prototypeOfObject.__lookupGetter__);\n    lookupSetter = call.bind(prototypeOfObject.__lookupSetter__);\n    /* eslint-enable no-underscore-dangle */\n}\n\n// ES5 15.2.3.2\n// http://es5.github.com/#x15.2.3.2\nif (!Object.getPrototypeOf) {\n    // https://github.com/es-shims/es5-shim/issues#issue/2\n    // http://ejohn.org/blog/objectgetprototypeof/\n    // recommended by fschaefer on github\n    //\n    // sure, and webreflection says ^_^\n    // ... this will nerever possibly return null\n    // ... Opera Mini breaks here with infinite loops\n    Object.getPrototypeOf = function getPrototypeOf(object) {\n        /* eslint-disable no-proto */\n        var proto = object.__proto__;\n        /* eslint-enable no-proto */\n        if (proto || proto === null) {\n            return proto;\n        } else if (toStr(object.constructor) === '[object Function]') {\n            return object.constructor.prototype;\n        } else if (object instanceof Object) {\n          return prototypeOfObject;\n        } else {\n          // Correctly return null for Objects created with `Object.create(null)`\n          // (shammed or native) or `{ __proto__: null}`.  Also returns null for\n          // cross-realm objects on browsers that lack `__proto__` support (like\n          // IE <11), but that's the best we can do.\n          return null;\n        }\n    };\n}\n\n// ES5 15.2.3.3\n// http://es5.github.com/#x15.2.3.3\n\nvar doesGetOwnPropertyDescriptorWork = function doesGetOwnPropertyDescriptorWork(object) {\n    try {\n        object.sentinel = 0;\n        return Object.getOwnPropertyDescriptor(object, 'sentinel').value === 0;\n    } catch (exception) {\n        return false;\n    }\n};\n\n// check whether getOwnPropertyDescriptor works if it's given. Otherwise, shim partially.\nif (Object.defineProperty) {\n    var getOwnPropertyDescriptorWorksOnObject = doesGetOwnPropertyDescriptorWork({});\n    var getOwnPropertyDescriptorWorksOnDom = typeof document === 'undefined' ||\n    doesGetOwnPropertyDescriptorWork(document.createElement('div'));\n    if (!getOwnPropertyDescriptorWorksOnDom || !getOwnPropertyDescriptorWorksOnObject) {\n        var getOwnPropertyDescriptorFallback = Object.getOwnPropertyDescriptor;\n    }\n}\n\nif (!Object.getOwnPropertyDescriptor || getOwnPropertyDescriptorFallback) {\n    var ERR_NON_OBJECT = 'Object.getOwnPropertyDescriptor called on a non-object: ';\n\n    /* eslint-disable no-proto */\n    Object.getOwnPropertyDescriptor = function getOwnPropertyDescriptor(object, property) {\n        if ((typeof object !== 'object' && typeof object !== 'function') || object === null) {\n            throw new TypeError(ERR_NON_OBJECT + object);\n        }\n\n        // make a valiant attempt to use the real getOwnPropertyDescriptor\n        // for I8's DOM elements.\n        if (getOwnPropertyDescriptorFallback) {\n            try {\n                return getOwnPropertyDescriptorFallback.call(Object, object, property);\n            } catch (exception) {\n                // try the shim if the real one doesn't work\n            }\n        }\n\n        var descriptor;\n\n        // If object does not owns property return undefined immediately.\n        if (!owns(object, property)) {\n            return descriptor;\n        }\n\n        // If object has a property then it's for sure `configurable`, and\n        // probably `enumerable`. Detect enumerability though.\n        descriptor = {\n            enumerable: isEnumerable(object, property),\n            configurable: true\n        };\n\n        // If JS engine supports accessor properties then property may be a\n        // getter or setter.\n        if (supportsAccessors) {\n            // Unfortunately `__lookupGetter__` will return a getter even\n            // if object has own non getter property along with a same named\n            // inherited getter. To avoid misbehavior we temporary remove\n            // `__proto__` so that `__lookupGetter__` will return getter only\n            // if it's owned by an object.\n            var prototype = object.__proto__;\n            var notPrototypeOfObject = object !== prototypeOfObject;\n            // avoid recursion problem, breaking in Opera Mini when\n            // Object.getOwnPropertyDescriptor(Object.prototype, 'toString')\n            // or any other Object.prototype accessor\n            if (notPrototypeOfObject) {\n                object.__proto__ = prototypeOfObject;\n            }\n\n            var getter = lookupGetter(object, property);\n            var setter = lookupSetter(object, property);\n\n            if (notPrototypeOfObject) {\n                // Once we have getter and setter we can put values back.\n                object.__proto__ = prototype;\n            }\n\n            if (getter || setter) {\n                if (getter) {\n                    descriptor.get = getter;\n                }\n                if (setter) {\n                    descriptor.set = setter;\n                }\n                // If it was accessor property we're done and return here\n                // in order to avoid adding `value` to the descriptor.\n                return descriptor;\n            }\n        }\n\n        // If we got this far we know that object has an own property that is\n        // not an accessor so we set it as a value and return descriptor.\n        descriptor.value = object[property];\n        descriptor.writable = true;\n        return descriptor;\n    };\n    /* eslint-enable no-proto */\n}\n\n// ES5 15.2.3.4\n// http://es5.github.com/#x15.2.3.4\nif (!Object.getOwnPropertyNames) {\n    Object.getOwnPropertyNames = function getOwnPropertyNames(object) {\n        return Object.keys(object);\n    };\n}\n\n// ES5 15.2.3.5\n// http://es5.github.com/#x15.2.3.5\nif (!Object.create) {\n\n    // Contributed by Brandon Benvie, October, 2012\n    var createEmpty;\n    var supportsProto = !({ __proto__: null } instanceof Object);\n                        // the following produces false positives\n                        // in Opera Mini => not a reliable check\n                        // Object.prototype.__proto__ === null\n\n    // Check for document.domain and active x support\n    // No need to use active x approach when document.domain is not set\n    // see https://github.com/es-shims/es5-shim/issues/150\n    // variation of https://github.com/kitcambridge/es5-shim/commit/4f738ac066346\n    /* global ActiveXObject */\n    var shouldUseActiveX = function shouldUseActiveX() {\n        // return early if document.domain not set\n        if (!document.domain) {\n            return false;\n        }\n\n        try {\n            return !!new ActiveXObject('htmlfile');\n        } catch (exception) {\n            return false;\n        }\n    };\n\n    // This supports IE8 when document.domain is used\n    // see https://github.com/es-shims/es5-shim/issues/150\n    // variation of https://github.com/kitcambridge/es5-shim/commit/4f738ac066346\n    var getEmptyViaActiveX = function getEmptyViaActiveX() {\n        var empty;\n        var xDoc;\n\n        xDoc = new ActiveXObject('htmlfile');\n\n        xDoc.write('<script><\\/script>');\n        xDoc.close();\n\n        empty = xDoc.parentWindow.Object.prototype;\n        xDoc = null;\n\n        return empty;\n    };\n\n    // The original implementation using an iframe\n    // before the activex approach was added\n    // see https://github.com/es-shims/es5-shim/issues/150\n    var getEmptyViaIFrame = function getEmptyViaIFrame() {\n        var iframe = document.createElement('iframe');\n        var parent = document.body || document.documentElement;\n        var empty;\n\n        iframe.style.display = 'none';\n        parent.appendChild(iframe);\n        /* eslint-disable no-script-url */\n        iframe.src = 'javascript:';\n        /* eslint-enable no-script-url */\n\n        empty = iframe.contentWindow.Object.prototype;\n        parent.removeChild(iframe);\n        iframe = null;\n\n        return empty;\n    };\n\n    /* global document */\n    if (supportsProto || typeof document === 'undefined') {\n        createEmpty = function () {\n            return { __proto__: null };\n        };\n    } else {\n        // In old IE __proto__ can't be used to manually set `null`, nor does\n        // any other method exist to make an object that inherits from nothing,\n        // aside from Object.prototype itself. Instead, create a new global\n        // object and *steal* its Object.prototype and strip it bare. This is\n        // used as the prototype to create nullary objects.\n        createEmpty = function () {\n            // Determine which approach to use\n            // see https://github.com/es-shims/es5-shim/issues/150\n            var empty = shouldUseActiveX() ? getEmptyViaActiveX() : getEmptyViaIFrame();\n\n            delete empty.constructor;\n            delete empty.hasOwnProperty;\n            delete empty.propertyIsEnumerable;\n            delete empty.isPrototypeOf;\n            delete empty.toLocaleString;\n            delete empty.toString;\n            delete empty.valueOf;\n\n            var Empty = function Empty() {};\n            Empty.prototype = empty;\n            // short-circuit future calls\n            createEmpty = function () {\n                return new Empty();\n            };\n            return new Empty();\n        };\n    }\n\n    Object.create = function create(prototype, properties) {\n\n        var object;\n        var Type = function Type() {}; // An empty constructor.\n\n        if (prototype === null) {\n            object = createEmpty();\n        } else {\n            if (typeof prototype !== 'object' && typeof prototype !== 'function') {\n                // In the native implementation `parent` can be `null`\n                // OR *any* `instanceof Object`  (Object|Function|Array|RegExp|etc)\n                // Use `typeof` tho, b/c in old IE, DOM elements are not `instanceof Object`\n                // like they are in modern browsers. Using `Object.create` on DOM elements\n                // is...err...probably inappropriate, but the native version allows for it.\n                throw new TypeError('Object prototype may only be an Object or null'); // same msg as Chrome\n            }\n            Type.prototype = prototype;\n            object = new Type();\n            // IE has no built-in implementation of `Object.getPrototypeOf`\n            // neither `__proto__`, but this manually setting `__proto__` will\n            // guarantee that `Object.getPrototypeOf` will work as expected with\n            // objects created using `Object.create`\n            /* eslint-disable no-proto */\n            object.__proto__ = prototype;\n            /* eslint-enable no-proto */\n        }\n\n        if (properties !== void 0) {\n            Object.defineProperties(object, properties);\n        }\n\n        return object;\n    };\n}\n\n// ES5 15.2.3.6\n// http://es5.github.com/#x15.2.3.6\n\n// Patch for WebKit and IE8 standard mode\n// Designed by hax <hax.github.com>\n// related issue: https://github.com/es-shims/es5-shim/issues#issue/5\n// IE8 Reference:\n//     http://msdn.microsoft.com/en-us/library/dd282900.aspx\n//     http://msdn.microsoft.com/en-us/library/dd229916.aspx\n// WebKit Bugs:\n//     https://bugs.webkit.org/show_bug.cgi?id=36423\n\nvar doesDefinePropertyWork = function doesDefinePropertyWork(object) {\n    try {\n        Object.defineProperty(object, 'sentinel', {});\n        return 'sentinel' in object;\n    } catch (exception) {\n        return false;\n    }\n};\n\n// check whether defineProperty works if it's given. Otherwise,\n// shim partially.\nif (Object.defineProperty) {\n    var definePropertyWorksOnObject = doesDefinePropertyWork({});\n    var definePropertyWorksOnDom = typeof document === 'undefined' ||\n        doesDefinePropertyWork(document.createElement('div'));\n    if (!definePropertyWorksOnObject || !definePropertyWorksOnDom) {\n        var definePropertyFallback = Object.defineProperty,\n            definePropertiesFallback = Object.defineProperties;\n    }\n}\n\nif (!Object.defineProperty || definePropertyFallback) {\n    var ERR_NON_OBJECT_DESCRIPTOR = 'Property description must be an object: ';\n    var ERR_NON_OBJECT_TARGET = 'Object.defineProperty called on non-object: ';\n    var ERR_ACCESSORS_NOT_SUPPORTED = 'getters & setters can not be defined on this javascript engine';\n\n    Object.defineProperty = function defineProperty(object, property, descriptor) {\n        if ((typeof object !== 'object' && typeof object !== 'function') || object === null) {\n            throw new TypeError(ERR_NON_OBJECT_TARGET + object);\n        }\n        if ((typeof descriptor !== 'object' && typeof descriptor !== 'function') || descriptor === null) {\n            throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR + descriptor);\n        }\n        // make a valiant attempt to use the real defineProperty\n        // for I8's DOM elements.\n        if (definePropertyFallback) {\n            try {\n                return definePropertyFallback.call(Object, object, property, descriptor);\n            } catch (exception) {\n                // try the shim if the real one doesn't work\n            }\n        }\n\n        // If it's a data property.\n        if ('value' in descriptor) {\n            // fail silently if 'writable', 'enumerable', or 'configurable'\n            // are requested but not supported\n            /*\n            // alternate approach:\n            if ( // can't implement these features; allow false but not true\n                ('writable' in descriptor && !descriptor.writable) ||\n                ('enumerable' in descriptor && !descriptor.enumerable) ||\n                ('configurable' in descriptor && !descriptor.configurable)\n            ))\n                throw new RangeError(\n                    'This implementation of Object.defineProperty does not support configurable, enumerable, or writable.'\n                );\n            */\n\n            if (supportsAccessors && (lookupGetter(object, property) || lookupSetter(object, property))) {\n                // As accessors are supported only on engines implementing\n                // `__proto__` we can safely override `__proto__` while defining\n                // a property to make sure that we don't hit an inherited\n                // accessor.\n                /* eslint-disable no-proto */\n                var prototype = object.__proto__;\n                object.__proto__ = prototypeOfObject;\n                // Deleting a property anyway since getter / setter may be\n                // defined on object itself.\n                delete object[property];\n                object[property] = descriptor.value;\n                // Setting original `__proto__` back now.\n                object.__proto__ = prototype;\n                /* eslint-enable no-proto */\n            } else {\n                object[property] = descriptor.value;\n            }\n        } else {\n            if (!supportsAccessors && (('get' in descriptor) || ('set' in descriptor))) {\n                throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED);\n            }\n            // If we got that far then getters and setters can be defined !!\n            if ('get' in descriptor) {\n                defineGetter(object, property, descriptor.get);\n            }\n            if ('set' in descriptor) {\n                defineSetter(object, property, descriptor.set);\n            }\n        }\n        return object;\n    };\n}\n\n// ES5 15.2.3.7\n// http://es5.github.com/#x15.2.3.7\nif (!Object.defineProperties || definePropertiesFallback) {\n    Object.defineProperties = function defineProperties(object, properties) {\n        // make a valiant attempt to use the real defineProperties\n        if (definePropertiesFallback) {\n            try {\n                return definePropertiesFallback.call(Object, object, properties);\n            } catch (exception) {\n                // try the shim if the real one doesn't work\n            }\n        }\n\n        Object.keys(properties).forEach(function (property) {\n            if (property !== '__proto__') {\n                Object.defineProperty(object, property, properties[property]);\n            }\n        });\n        return object;\n    };\n}\n\n// ES5 15.2.3.8\n// http://es5.github.com/#x15.2.3.8\nif (!Object.seal) {\n    Object.seal = function seal(object) {\n        if (Object(object) !== object) {\n            throw new TypeError('Object.seal can only be called on Objects.');\n        }\n        // this is misleading and breaks feature-detection, but\n        // allows \"securable\" code to \"gracefully\" degrade to working\n        // but insecure code.\n        return object;\n    };\n}\n\n// ES5 15.2.3.9\n// http://es5.github.com/#x15.2.3.9\nif (!Object.freeze) {\n    Object.freeze = function freeze(object) {\n        if (Object(object) !== object) {\n            throw new TypeError('Object.freeze can only be called on Objects.');\n        }\n        // this is misleading and breaks feature-detection, but\n        // allows \"securable\" code to \"gracefully\" degrade to working\n        // but insecure code.\n        return object;\n    };\n}\n\n// detect a Rhino bug and patch it\ntry {\n    Object.freeze(function () {});\n} catch (exception) {\n    Object.freeze = (function (freezeObject) {\n        return function freeze(object) {\n            if (typeof object === 'function') {\n                return object;\n            } else {\n                return freezeObject(object);\n            }\n        };\n    }(Object.freeze));\n}\n\n// ES5 15.2.3.10\n// http://es5.github.com/#x15.2.3.10\nif (!Object.preventExtensions) {\n    Object.preventExtensions = function preventExtensions(object) {\n        if (Object(object) !== object) {\n            throw new TypeError('Object.preventExtensions can only be called on Objects.');\n        }\n        // this is misleading and breaks feature-detection, but\n        // allows \"securable\" code to \"gracefully\" degrade to working\n        // but insecure code.\n        return object;\n    };\n}\n\n// ES5 15.2.3.11\n// http://es5.github.com/#x15.2.3.11\nif (!Object.isSealed) {\n    Object.isSealed = function isSealed(object) {\n        if (Object(object) !== object) {\n            throw new TypeError('Object.isSealed can only be called on Objects.');\n        }\n        return false;\n    };\n}\n\n// ES5 15.2.3.12\n// http://es5.github.com/#x15.2.3.12\nif (!Object.isFrozen) {\n    Object.isFrozen = function isFrozen(object) {\n        if (Object(object) !== object) {\n            throw new TypeError('Object.isFrozen can only be called on Objects.');\n        }\n        return false;\n    };\n}\n\n// ES5 15.2.3.13\n// http://es5.github.com/#x15.2.3.13\nif (!Object.isExtensible) {\n    Object.isExtensible = function isExtensible(object) {\n        // 1. If Type(O) is not Object throw a TypeError exception.\n        if (Object(object) !== object) {\n            throw new TypeError('Object.isExtensible can only be called on Objects.');\n        }\n        // 2. Return the Boolean value of the [[Extensible]] internal property of O.\n        var name = '';\n        while (owns(object, name)) {\n            name += '?';\n        }\n        object[name] = true;\n        var returnValue = owns(object, name);\n        delete object[name];\n        return returnValue;\n    };\n}\n\n}));\n\n// Console-polyfill. MIT license.\n// https://github.com/paulmillr/console-polyfill\n// Make it safe to do console.log() always.\n(function(global) {\n  'use strict';\n  global.console = global.console || {};\n  var con = global.console;\n  var prop, method;\n  var empty = {};\n  var dummy = function() {};\n  var properties = 'memory'.split(',');\n  var methods = ('assert,clear,count,debug,dir,dirxml,error,exception,group,' +\n  'groupCollapsed,groupEnd,info,log,markTimeline,profile,profiles,profileEnd,' +\n  'show,table,time,timeEnd,timeline,timelineEnd,timeStamp,trace,warn').split(',');\n  while (prop = properties.pop()) if (!con[prop]) con[prop] = empty;\n  while (method = methods.pop()) if (typeof con[method] !== 'function') con[method] = dummy;\n  // Using `this` for web workers & supports Browserify / Webpack.\n})(typeof window === 'undefined' ? this : window);\n\n!window.addEventListener && (function (WindowPrototype, DocumentPrototype, ElementPrototype, addEventListener, removeEventListener, dispatchEvent, registry) {\n  WindowPrototype[addEventListener] = DocumentPrototype[addEventListener] = ElementPrototype[addEventListener] = function (type, listener) {\n    var target = this;\n\n    registry.unshift([target, type, listener, function (event) {\n      event.currentTarget = target;\n      event.preventDefault = function () { event.returnValue = false };\n      event.stopPropagation = function () { event.cancelBubble = true };\n      event.target = event.srcElement || target;\n\n      listener.call(target, event);\n    }]);\n\n    this.attachEvent(\"on\" + type, registry[0][3]);\n  };\n\n  WindowPrototype[removeEventListener] = DocumentPrototype[removeEventListener] = ElementPrototype[removeEventListener] = function (type, listener) {\n    for (var index = 0, register; register = registry[index]; ++index) {\n      if (register[0] == this && register[1] == type && register[2] == listener) {\n        return this.detachEvent(\"on\" + type, registry.splice(index, 1)[0][3]);\n      }\n    }\n  };\n\n  WindowPrototype[dispatchEvent] = DocumentPrototype[dispatchEvent] = ElementPrototype[dispatchEvent] = function (eventObject) {\n    return this.fireEvent(\"on\" + eventObject.type, eventObject);\n  };\n})(Window.prototype, HTMLDocument.prototype, Element.prototype, \"addEventListener\", \"removeEventListener\", \"dispatchEvent\", []);\n\n/**\n * Module: rem - v1.3.4\n * Description: A polyfill to parse CSS links and rewrite pixel equivalents into head for non supporting browsers\n * Date Built: 2014-07-02\n * Copyright (c) 2014  | Chuck Carpenter <chuck.carpenter@me.com>,Lucas Serven <lserven@gmail.com>;\n * @see https://github.com/chuckcarpenter/REM-unit-polyfill\n**/\n\n(function (window, undefined) {\n  \"use strict\";\n  // test for REM unit support\n  var cssremunit =  function() {\n      var div = document.createElement( 'div' );\n      div.style.cssText = 'font-size: 1rem;';\n\n      return (/rem/).test(div.style.fontSize);\n    },\n\n  // filter returned links for stylesheets\n    isStyleSheet = function () {\n      var styles = document.getElementsByTagName('link'),\n        filteredLinks = [];\n\n      for ( var i = 0; i < styles.length; i++) {\n        if ( styles[i].rel.toLowerCase() === 'stylesheet' && styles[i].getAttribute('data-norem') === null ) {\n\n          filteredLinks.push( styles[i].href );\n        }\n      }\n\n      return filteredLinks;\n    },\n\n    processLinks = function () {\n      //prepare to match each link\n      for( var i = 0; i < links.length; i++ ){\n        xhr( links[i], storeCSS );\n      }\n    },\n\n    storeCSS = function ( response, link ) {\n\n      preCSS.push(response.responseText);\n      CSSLinks.push(link);\n\n      if( CSSLinks.length === links.length ){\n        for( var j = 0; j <  CSSLinks.length; j++ ){\n          matchCSS( preCSS[j], CSSLinks[j] );\n        }\n\n        if( ( links = importLinks.slice(0) ).length > 0 ){ //after finishing all current links, set links equal to the new imports found\n          CSSLinks = [];\n          preCSS = [];\n          importLinks = [];\n          processLinks();\n        } else {\n          buildCSS();\n        }\n      }\n    },\n\n    matchCSS = function ( sheetCSS, link ) { // collect all of the rules from the xhr response texts and match them to a pattern\n      var clean = removeMediaQueries( sheetCSS ).replace(/\\/\\*[\\s\\S]*?\\*\\//g, ''), // remove MediaQueries and comments\n        pattern = /[\\w\\d\\s\\-\\/\\\\\\[\\]:,.'\"*()<>+~%#^$_=|@]+\\{[\\w\\d\\s\\-\\/\\\\%#:!;,.'\"*()]+\\d*\\.?\\d+rem[\\w\\d\\s\\-\\/\\\\%#:!;,.'\"*()]*\\}/g, //find selectors that use rem in one or more of their rules\n        current = clean.match(pattern),\n        remPattern =/\\d*\\.?\\d+rem/g,\n        remCurrent = clean.match(remPattern),\n        sheetPathPattern = /(.*\\/)/,\n        sheetPath = sheetPathPattern.exec(link)[0], //relative path to css file specified in @import\n        importPattern = /@import (?:url\\()?['\"]?([^'\\)\"]*)['\"]?\\)?[^;]*/gm, //matches all @import variations outlined at: https://developer.mozilla.org/en-US/docs/Web/CSS/@import\n        importStatement;\n\n      while( (importStatement = importPattern.exec(sheetCSS)) !== null ){\n        if( importStatement[1].indexOf(\"/\") === 0 ) { // check if the value of importStatement[1] is a root relative path, in which case it shouldn't be concatenated with sheetPath\n          importLinks.push( importStatement[1] );\n        } else {\n          importLinks.push( sheetPath + importStatement[1] );\n        }\n      }\n\n      if( current !== null && current.length !== 0 ){\n        found = found.concat( current ); // save all of the blocks of rules with rem in a property\n        foundProps = foundProps.concat( remCurrent ); // save all of the properties with rem\n      }\n    },\n\n    buildCSS = function () { // first build each individual rule from elements in the found array and then add it to the string of rules.\n      var pattern = /[\\w\\d\\s\\-\\/\\\\%#:,.'\"*()]+\\d*\\.?\\d+rem[\\w\\d\\s\\-\\/\\\\%#:!,.'\"*()]*[;}]/g; // find properties with rem values in them\n      for( var i = 0; i < found.length; i++ ){\n        rules = rules + found[i].substr(0,found[i].indexOf(\"{\")+1); // save the selector portion of each rule with a rem value\n        var current = found[i].match( pattern );\n        for( var j = 0; j<current.length; j++ ){ // build a new set of with only the selector and properties that have rem in the value\n          rules = rules + current[j];\n          if( j === current.length-1 && rules[rules.length-1] !== \"}\" ){\n            rules = rules + \"\\n}\";\n          }\n        }\n      }\n\n      parseCSS();\n    },\n\n    parseCSS = function () { // replace each set of parentheses with evaluated content\n      for( var i = 0; i < foundProps.length; i++ ){\n        css[i] = Math.round( parseFloat(foundProps[i].substr(0,foundProps[i].length-3)*fontSize) ) + 'px';\n      }\n\n      loadCSS();\n    },\n\n    loadCSS = function () { // replace and load the new rules\n      for( var i = 0; i < css.length; i++ ){ // only run this loop as many times as css has entries\n        if( css[i] ){\n          rules = rules.replace( foundProps[i],css[i] ); // replace old rules with our processed rules\n        }\n      }\n      var remcss = document.createElement( 'style' );\n      remcss.setAttribute( 'type', 'text/css' );\n      remcss.id = 'remReplace';\n      document.getElementsByTagName( 'head' )[0].appendChild( remcss );   // create the new element\n      if( remcss.styleSheet ) {\n        remcss.styleSheet.cssText = rules; // IE8 will not support innerHTML on read-only elements, such as STYLE\n      } else {\n        remcss.appendChild( document.createTextNode( rules ) );\n      }\n    },\n\n    xhr = function ( url, callback ) { // create new XMLHttpRequest object and run it\n      try {\n        //try to create a request object\n        //arranging the two conditions this way is for IE7/8's benefit\n        //so that it works with any combination of ActiveX or Native XHR settings,\n        //as long as one or the other is enabled; but if both are enabled\n        //it prefers ActiveX, which means it still works with local files\n        //(Native XHR in IE7/8 is blocked and throws \"access is denied\",\n        // but ActiveX is permitted if the user allows it [default is to prompt])\n        var xhr = window.ActiveXObject ? ( new ActiveXObject('Microsoft.XMLHTTP') || new ActiveXObject('Msxml2.XMLHTTP') ) : new XMLHttpRequest();\n\n        xhr.open( 'GET', url, true );\n        xhr.onreadystatechange = function() {\n          if ( xhr.readyState === 4 ){\n            callback(xhr, url);\n          } // else { callback function on AJAX error }\n        };\n\n        xhr.send( null );\n      } catch (e){\n        if ( window.XDomainRequest ) {\n          var xdr = new XDomainRequest();\n          xdr.open('get', url);\n          xdr.onload = function() {\n            callback(xdr, url);\n          };\n          xdr.onerror = function() {\n            return false; // xdr load fail\n          };\n          xdr.send();\n        }\n      }\n    },\n\n  // Remove queries.\n    removeMediaQueries = function(css) {\n      // Test for Media Query support\n      if ( !window.matchMedia && !window.msMatchMedia ) {\n        // If the browser doesn't support media queries, we find all @media declarations in the CSS and remove them.\n        // Note: Since @rules can't be nested in the CSS spec, we're safe to just check for the closest following \"}}\" to the \"@media\".\n        css = css.replace(/@media[\\s\\S]*?\\}\\s*\\}/g, \"\");\n      }\n\n      return css;\n    };\n\n  if( !cssremunit() ){ // this checks if the rem value is supported\n    var rules = '', // initialize the rules variable in this scope so it can be used later\n      links = isStyleSheet(), // initialize the array holding the sheets urls for use later\n      importLinks = [], //initialize the array holding the import sheet urls for use later\n      found = [], // initialize the array holding the found rules for use later\n      foundProps = [], // initialize the array holding the found properties for use later\n      preCSS = [], // initialize array that holds css before being parsed\n      CSSLinks = [], //initialize array holding css links returned from xhr\n      css = [], // initialize the array holding the parsed rules for use later\n      fontSize = '';\n\n    // Notice: rem is a \"root em\" that means that in case when html element size was changed by css\n    // or style we should not change document.documentElement.fontSize to 1em - only body size should be changed\n    // to 1em for calculation\n\n    fontSize = (function () {\n      var doc = document,\n        docElement = doc.documentElement,\n        body = doc.body || doc.createElement('body'),\n        isFakeBody = !doc.body,\n        div = doc.createElement('div'),\n        currentSize = body.style.fontSize,\n        size;\n\n      if ( isFakeBody ) {\n        docElement.appendChild( body );\n      }\n\n      div.style.cssText = 'width:1em; position:absolute; visibility:hidden; padding: 0;';\n\n      body.style.fontSize = '1em';\n\n      body.appendChild( div );\n      size = div.offsetWidth;\n\n      if ( isFakeBody ) {\n        docElement.removeChild( body );\n      }\n      else {\n        body.removeChild( div );\n        body.style.fontSize = currentSize;\n      }\n\n      return size;\n    }());\n\n    processLinks();\n  } // else { do nothing, you are awesome and have REM support }\n\n})(window);\n\n/*! Respond.js v1.4.2: min/max-width media query polyfill\n * Copyright 2014 Scott Jehl\n * Licensed under MIT\n * http://j.mp/respondjs */\n\n!function(a){\"use strict\";a.matchMedia=a.matchMedia||function(a){var b,c=a.documentElement,d=c.firstElementChild||c.firstChild,e=a.createElement(\"body\"),f=a.createElement(\"div\");return f.id=\"mq-test-1\",f.style.cssText=\"position:absolute;top:-100em\",e.style.background=\"none\",e.appendChild(f),function(a){return f.innerHTML='&shy;<style media=\"'+a+'\"> #mq-test-1 { width: 42px; }</style>',c.insertBefore(e,d),b=42===f.offsetWidth,c.removeChild(e),{matches:b,media:a}}}(a.document)}(this),function(a){\"use strict\";function b(){v(!0)}var c={};a.respond=c,c.update=function(){};var d=[],e=function(){var b=!1;try{b=new a.XMLHttpRequest}catch(c){b=new a.ActiveXObject(\"Microsoft.XMLHTTP\")}return function(){return b}}(),f=function(a,b){var c=e();c&&(c.open(\"GET\",a,!0),c.onreadystatechange=function(){4!==c.readyState||200!==c.status&&304!==c.status||b(c.responseText)},4!==c.readyState&&c.send(null))},g=function(a){return a.replace(c.regex.minmaxwh,\"\").match(c.regex.other)};if(c.ajax=f,c.queue=d,c.unsupportedmq=g,c.regex={media:/@media[^\\{]+\\{([^\\{\\}]*\\{[^\\}\\{]*\\})+/gi,keyframes:/@(?:\\-(?:o|moz|webkit)\\-)?keyframes[^\\{]+\\{(?:[^\\{\\}]*\\{[^\\}\\{]*\\})+[^\\}]*\\}/gi,comments:/\\/\\*[^*]*\\*+([^/][^*]*\\*+)*\\//gi,urls:/(url\\()['\"]?([^\\/\\)'\"][^:\\)'\"]+)['\"]?(\\))/g,findStyles:/@media *([^\\{]+)\\{([\\S\\s]+?)$/,only:/(only\\s+)?([a-zA-Z]+)\\s?/,minw:/\\(\\s*min\\-width\\s*:\\s*(\\s*[0-9\\.]+)(px|em)\\s*\\)/,maxw:/\\(\\s*max\\-width\\s*:\\s*(\\s*[0-9\\.]+)(px|em)\\s*\\)/,minmaxwh:/\\(\\s*m(in|ax)\\-(height|width)\\s*:\\s*(\\s*[0-9\\.]+)(px|em)\\s*\\)/gi,other:/\\([^\\)]*\\)/g},c.mediaQueriesSupported=a.matchMedia&&null!==a.matchMedia(\"only all\")&&a.matchMedia(\"only all\").matches,!c.mediaQueriesSupported){var h,i,j,k=a.document,l=k.documentElement,m=[],n=[],o=[],p={},q=30,r=k.getElementsByTagName(\"head\")[0]||l,s=k.getElementsByTagName(\"base\")[0],t=r.getElementsByTagName(\"link\"),u=function(){var a,b=k.createElement(\"div\"),c=k.body,d=l.style.fontSize,e=c&&c.style.fontSize,f=!1;return b.style.cssText=\"position:absolute;font-size:1em;width:1em\",c||(c=f=k.createElement(\"body\"),c.style.background=\"none\"),l.style.fontSize=\"100%\",c.style.fontSize=\"100%\",c.appendChild(b),f&&l.insertBefore(c,l.firstChild),a=b.offsetWidth,f?l.removeChild(c):c.removeChild(b),l.style.fontSize=d,e&&(c.style.fontSize=e),a=j=parseFloat(a)},v=function(b){var c=\"clientWidth\",d=l[c],e=\"CSS1Compat\"===k.compatMode&&d||k.body[c]||d,f={},g=t[t.length-1],p=(new Date).getTime();if(b&&h&&q>p-h)return a.clearTimeout(i),i=a.setTimeout(v,q),void 0;h=p;for(var s in m)if(m.hasOwnProperty(s)){var w=m[s],x=w.minw,y=w.maxw,z=null===x,A=null===y,B=\"em\";x&&(x=parseFloat(x)*(x.indexOf(B)>-1?j||u():1)),y&&(y=parseFloat(y)*(y.indexOf(B)>-1?j||u():1)),w.hasquery&&(z&&A||!(z||e>=x)||!(A||y>=e))||(f[w.media]||(f[w.media]=[]),f[w.media].push(n[w.rules]))}for(var C in o)o.hasOwnProperty(C)&&o[C]&&o[C].parentNode===r&&r.removeChild(o[C]);o.length=0;for(var D in f)if(f.hasOwnProperty(D)){var E=k.createElement(\"style\"),F=f[D].join(\"\\n\");E.type=\"text/css\",E.media=D,r.insertBefore(E,g.nextSibling),E.styleSheet?E.styleSheet.cssText=F:E.appendChild(k.createTextNode(F)),o.push(E)}},w=function(a,b,d){var e=a.replace(c.regex.comments,\"\").replace(c.regex.keyframes,\"\").match(c.regex.media),f=e&&e.length||0;b=b.substring(0,b.lastIndexOf(\"/\"));var h=function(a){return a.replace(c.regex.urls,\"$1\"+b+\"$2$3\")},i=!f&&d;b.length&&(b+=\"/\"),i&&(f=1);for(var j=0;f>j;j++){var k,l,o,p;i?(k=d,n.push(h(a))):(k=e[j].match(c.regex.findStyles)&&RegExp.$1,n.push(RegExp.$2&&h(RegExp.$2))),o=k.split(\",\"),p=o.length;for(var q=0;p>q;q++)l=o[q],g(l)||m.push({media:l.split(\"(\")[0].match(c.regex.only)&&RegExp.$2||\"all\",rules:n.length-1,hasquery:l.indexOf(\"(\")>-1,minw:l.match(c.regex.minw)&&parseFloat(RegExp.$1)+(RegExp.$2||\"\"),maxw:l.match(c.regex.maxw)&&parseFloat(RegExp.$1)+(RegExp.$2||\"\")})}v()},x=function(){if(d.length){var b=d.shift();f(b.href,function(c){w(c,b.href,b.media),p[b.href]=!0,a.setTimeout(function(){x()},0)})}},y=function(){for(var b=0;b<t.length;b++){var c=t[b],e=c.href,f=c.media,g=c.rel&&\"stylesheet\"===c.rel.toLowerCase();e&&g&&!p[e]&&(c.styleSheet&&c.styleSheet.rawCssText?(w(c.styleSheet.rawCssText,e,f),p[e]=!0):(!/^([a-zA-Z:]*\\/\\/)/.test(e)&&!s||e.replace(RegExp.$1,\"\").split(\"/\")[0]===a.location.host)&&(\"//\"===e.substring(0,2)&&(e=a.location.protocol+e),d.push({href:e,media:f})))}x()};y(),c.update=y,c.getEmValue=u,a.addEventListener?a.addEventListener(\"resize\",b,!1):a.attachEvent&&a.attachEvent(\"onresize\",b)}}(this);"
  },
  {
    "path": "open-layui-web/src/main/view/static/base-component/amazeui/js/amazeui.js",
    "content": "/*! Amaze UI v2.6.0 | by Amaze UI Team | (c) 2016 AllMobilize, Inc. | Licensed under MIT | 2016-03-31T14:28:54+0800 */ \n(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory(require(\"jquery\"));\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([\"jquery\"], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"AMUI\"] = factory(require(\"jquery\"));\n\telse\n\t\troot[\"AMUI\"] = factory(root[\"jQuery\"]);\n})(this, function(__WEBPACK_EXTERNAL_MODULE_1__) {\nreturn /******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId])\n/******/ \t\t\treturn installedModules[moduleId].exports;\n\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\texports: {},\n/******/ \t\t\tid: moduleId,\n/******/ \t\t\tloaded: false\n/******/ \t\t};\n\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.loaded = true;\n\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n\n\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(0);\n/******/ })\n/************************************************************************/\n/******/ ([\n/* 0 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\t__webpack_require__(3);\n\t__webpack_require__(4);\n\t__webpack_require__(5);\n\t__webpack_require__(6);\n\t__webpack_require__(7);\n\t__webpack_require__(8);\n\t__webpack_require__(9);\n\t__webpack_require__(10);\n\t__webpack_require__(11);\n\t__webpack_require__(14);\n\t__webpack_require__(15);\n\t__webpack_require__(16);\n\t__webpack_require__(17);\n\t__webpack_require__(18);\n\t__webpack_require__(19);\n\t__webpack_require__(20);\n\t__webpack_require__(21);\n\t__webpack_require__(22);\n\t__webpack_require__(24);\n\t__webpack_require__(25);\n\t__webpack_require__(23);\n\t__webpack_require__(27);\n\t__webpack_require__(28);\n\t__webpack_require__(29);\n\t__webpack_require__(30);\n\t__webpack_require__(31);\n\t__webpack_require__(32);\n\t__webpack_require__(33);\n\t__webpack_require__(26);\n\t__webpack_require__(34);\n\t__webpack_require__(35);\n\t__webpack_require__(36);\n\t__webpack_require__(37);\n\t__webpack_require__(38);\n\t__webpack_require__(39);\n\t__webpack_require__(40);\n\t__webpack_require__(41);\n\t__webpack_require__(42);\n\t__webpack_require__(43);\n\t__webpack_require__(44);\n\t__webpack_require__(45);\n\t__webpack_require__(46);\n\t__webpack_require__(47);\n\t__webpack_require__(48);\n\t__webpack_require__(49);\n\t__webpack_require__(50);\n\t__webpack_require__(51);\n\t__webpack_require__(52);\n\t__webpack_require__(53);\n\t__webpack_require__(54);\n\n\tmodule.exports = $.AMUI = UI;\n\n\n/***/ },\n/* 1 */\n/***/ function(module, exports) {\n\n\tmodule.exports = __WEBPACK_EXTERNAL_MODULE_1__;\n\n/***/ },\n/* 2 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\t/* jshint -W040 */\n\n\tvar $ = __webpack_require__(1);\n\n\tif (typeof $ === 'undefined') {\n\t  throw new Error('Amaze UI 2.x requires jQuery :-(\\n' +\n\t  '\\u7231\\u4e0a\\u4e00\\u5339\\u91ce\\u9a6c\\uff0c\\u53ef\\u4f60' +\n\t  '\\u7684\\u5bb6\\u91cc\\u6ca1\\u6709\\u8349\\u539f\\u2026');\n\t}\n\n\tvar UI = $.AMUI || {};\n\tvar $win = $(window);\n\tvar doc = window.document;\n\tvar $html = $('html');\n\n\tUI.VERSION = '2.6.0';\n\n\tUI.support = {};\n\n\tUI.support.transition = (function() {\n\t  var transitionEnd = (function() {\n\t    // https://developer.mozilla.org/en-US/docs/Web/Events/transitionend#Browser_compatibility\n\t    var element = doc.body || doc.documentElement;\n\t    var transEndEventNames = {\n\t      WebkitTransition: 'webkitTransitionEnd',\n\t      MozTransition: 'transitionend',\n\t      OTransition: 'oTransitionEnd otransitionend',\n\t      transition: 'transitionend'\n\t    };\n\n\t    for (var name in transEndEventNames) {\n\t      if (element.style[name] !== undefined) {\n\t        return transEndEventNames[name];\n\t      }\n\t    }\n\t  })();\n\n\t  return transitionEnd && {end: transitionEnd};\n\t})();\n\n\tUI.support.animation = (function() {\n\t  var animationEnd = (function() {\n\t    var element = doc.body || doc.documentElement;\n\t    var animEndEventNames = {\n\t      WebkitAnimation: 'webkitAnimationEnd',\n\t      MozAnimation: 'animationend',\n\t      OAnimation: 'oAnimationEnd oanimationend',\n\t      animation: 'animationend'\n\t    };\n\n\t    for (var name in animEndEventNames) {\n\t      if (element.style[name] !== undefined) {\n\t        return animEndEventNames[name];\n\t      }\n\t    }\n\t  })();\n\n\t  return animationEnd && {end: animationEnd};\n\t})();\n\n\t/* jshint -W069 */\n\tUI.support.touch = (\n\t('ontouchstart' in window &&\n\tnavigator.userAgent.toLowerCase().match(/mobile|tablet/)) ||\n\t(window.DocumentTouch && document instanceof window.DocumentTouch) ||\n\t(window.navigator['msPointerEnabled'] &&\n\twindow.navigator['msMaxTouchPoints'] > 0) || //IE 10\n\t(window.navigator['pointerEnabled'] &&\n\twindow.navigator['maxTouchPoints'] > 0) || //IE >=11\n\tfalse);\n\n\t// https://developer.mozilla.org/zh-CN/docs/DOM/MutationObserver\n\tUI.support.mutationobserver = (window.MutationObserver ||\n\twindow.WebKitMutationObserver || null);\n\n\t// https://github.com/Modernizr/Modernizr/blob/924c7611c170ef2dc502582e5079507aff61e388/feature-detects/forms/validation.js#L20\n\tUI.support.formValidation = (typeof document.createElement('form').\n\t  checkValidity === 'function');\n\n\tUI.utils = {};\n\n\t/**\n\t * Debounce function\n\t * @param {function} func  Function to be debounced\n\t * @param {number} wait Function execution threshold in milliseconds\n\t * @param {bool} immediate  Whether the function should be called at\n\t *                          the beginning of the delay instead of the\n\t *                          end. Default is false.\n\t * @desc Executes a function when it stops being invoked for n seconds\n\t * @via  _.debounce() http://underscorejs.org\n\t */\n\tUI.utils.debounce = function(func, wait, immediate) {\n\t  var timeout;\n\t  return function() {\n\t    var context = this;\n\t    var args = arguments;\n\t    var later = function() {\n\t      timeout = null;\n\t      if (!immediate) {\n\t        func.apply(context, args);\n\t      }\n\t    };\n\t    var callNow = immediate && !timeout;\n\n\t    clearTimeout(timeout);\n\t    timeout = setTimeout(later, wait);\n\n\t    if (callNow) {\n\t      func.apply(context, args);\n\t    }\n\t  };\n\t};\n\n\tUI.utils.isInView = function(element, options) {\n\t  var $element = $(element);\n\t  var visible = !!($element.width() || $element.height()) &&\n\t    $element.css('display') !== 'none';\n\n\t  if (!visible) {\n\t    return false;\n\t  }\n\n\t  var windowLeft = $win.scrollLeft();\n\t  var windowTop = $win.scrollTop();\n\t  var offset = $element.offset();\n\t  var left = offset.left;\n\t  var top = offset.top;\n\n\t  options = $.extend({topOffset: 0, leftOffset: 0}, options);\n\n\t  return (top + $element.height() >= windowTop &&\n\t  top - options.topOffset <= windowTop + $win.height() &&\n\t  left + $element.width() >= windowLeft &&\n\t  left - options.leftOffset <= windowLeft + $win.width());\n\t};\n\n\t/* jshint -W054 */\n\tUI.utils.parseOptions = UI.utils.options = function(string) {\n\t  if ($.isPlainObject(string)) {\n\t    return string;\n\t  }\n\n\t  var start = (string ? string.indexOf('{') : -1);\n\t  var options = {};\n\n\t  if (start != -1) {\n\t    try {\n\t      options = (new Function('',\n\t        'var json = ' + string.substr(start) +\n\t        '; return JSON.parse(JSON.stringify(json));'))();\n\t    } catch (e) {\n\t    }\n\t  }\n\n\t  return options;\n\t};\n\n\t/* jshint +W054 */\n\n\tUI.utils.generateGUID = function(namespace) {\n\t  var uid = namespace + '-' || 'am-';\n\n\t  do {\n\t    uid += Math.random().toString(36).substring(2, 7);\n\t  } while (document.getElementById(uid));\n\n\t  return uid;\n\t};\n\n\t// @see https://davidwalsh.name/get-absolute-url\n\tUI.utils.getAbsoluteUrl = (function() {\n\t  var a;\n\n\t  return function(url) {\n\t    if (!a) {\n\t      a = document.createElement('a');\n\t    }\n\n\t    a.href = url;\n\n\t    return a.href;\n\t  };\n\t})();\n\n\t/**\n\t * Plugin AMUI Component to jQuery\n\t *\n\t * @param {String} name - plugin name\n\t * @param {Function} Component - plugin constructor\n\t * @param {Object} [pluginOption]\n\t * @param {String} pluginOption.dataOptions\n\t * @param {Function} pluginOption.methodCall - custom method call\n\t * @param {Function} pluginOption.before\n\t * @param {Function} pluginOption.after\n\t * @since v2.4.1\n\t */\n\tUI.plugin = function UIPlugin(name, Component, pluginOption) {\n\t  var old = $.fn[name];\n\t  pluginOption = pluginOption || {};\n\n\t  $.fn[name] = function(option) {\n\t    var allArgs = Array.prototype.slice.call(arguments, 0);\n\t    var args = allArgs.slice(1);\n\t    var propReturn;\n\t    var $set = this.each(function() {\n\t      var $this = $(this);\n\t      var dataName = 'amui.' + name;\n\t      var dataOptionsName = pluginOption.dataOptions || ('data-am-' + name);\n\t      var instance = $this.data(dataName);\n\t      var options = $.extend({},\n\t        UI.utils.parseOptions($this.attr(dataOptionsName)),\n\t        typeof option === 'object' && option);\n\n\t      if (!instance && option === 'destroy') {\n\t        return;\n\t      }\n\n\t      if (!instance) {\n\t        $this.data(dataName, (instance = new Component(this, options)));\n\t      }\n\n\t      // custom method call\n\t      if (pluginOption.methodCall) {\n\t        pluginOption.methodCall.call($this, allArgs, instance);\n\t      } else {\n\t        // before method call\n\t        pluginOption.before &&\n\t        pluginOption.before.call($this, allArgs, instance);\n\n\t        if (typeof option === 'string') {\n\t          propReturn = typeof instance[option] === 'function' ?\n\t            instance[option].apply(instance, args) : instance[option];\n\t        }\n\n\t        // after method call\n\t        pluginOption.after && pluginOption.after.call($this, allArgs, instance);\n\t      }\n\t    });\n\n\t    return (propReturn === undefined) ? $set : propReturn;\n\t  };\n\n\t  $.fn[name].Constructor = Component;\n\n\t  // no conflict\n\t  $.fn[name].noConflict = function() {\n\t    $.fn[name] = old;\n\t    return this;\n\t  };\n\n\t  UI[name] = Component;\n\t};\n\n\t// http://blog.alexmaccaw.com/css-transitions\n\t$.fn.emulateTransitionEnd = function(duration) {\n\t  var called = false;\n\t  var $el = this;\n\n\t  $(this).one(UI.support.transition.end, function() {\n\t    called = true;\n\t  });\n\n\t  var callback = function() {\n\t    if (!called) {\n\t      $($el).trigger(UI.support.transition.end);\n\t    }\n\t    $el.transitionEndTimmer = undefined;\n\t  };\n\t  this.transitionEndTimmer = setTimeout(callback, duration);\n\t  return this;\n\t};\n\n\t$.fn.redraw = function() {\n\t  return this.each(function() {\n\t    /* jshint unused:false */\n\t    var redraw = this.offsetHeight;\n\t  });\n\t};\n\n\t/* jshint unused:true */\n\n\t$.fn.transitionEnd = function(callback) {\n\t  var endEvent = UI.support.transition.end;\n\t  var dom = this;\n\n\t  function fireCallBack(e) {\n\t    callback.call(this, e);\n\t    endEvent && dom.off(endEvent, fireCallBack);\n\t  }\n\n\t  if (callback && endEvent) {\n\t    dom.on(endEvent, fireCallBack);\n\t  }\n\n\t  return this;\n\t};\n\n\t$.fn.removeClassRegEx = function() {\n\t  return this.each(function(regex) {\n\t    var classes = $(this).attr('class');\n\n\t    if (!classes || !regex) {\n\t      return false;\n\t    }\n\n\t    var classArray = [];\n\t    classes = classes.split(' ');\n\n\t    for (var i = 0, len = classes.length; i < len; i++) {\n\t      if (!classes[i].match(regex)) {\n\t        classArray.push(classes[i]);\n\t      }\n\t    }\n\n\t    $(this).attr('class', classArray.join(' '));\n\t  });\n\t};\n\n\t//\n\t$.fn.alterClass = function(removals, additions) {\n\t  var self = this;\n\n\t  if (removals.indexOf('*') === -1) {\n\t    // Use native jQuery methods if there is no wildcard matching\n\t    self.removeClass(removals);\n\t    return !additions ? self : self.addClass(additions);\n\t  }\n\n\t  var classPattern = new RegExp('\\\\s' +\n\t  removals.\n\t    replace(/\\*/g, '[A-Za-z0-9-_]+').\n\t    split(' ').\n\t    join('\\\\s|\\\\s') +\n\t  '\\\\s', 'g');\n\n\t  self.each(function(i, it) {\n\t    var cn = ' ' + it.className + ' ';\n\t    while (classPattern.test(cn)) {\n\t      cn = cn.replace(classPattern, ' ');\n\t    }\n\t    it.className = $.trim(cn);\n\t  });\n\n\t  return !additions ? self : self.addClass(additions);\n\t};\n\n\t// handle multiple browsers for requestAnimationFrame()\n\t// http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/\n\t// https://github.com/gnarf/jquery-requestAnimationFrame\n\tUI.utils.rAF = (function() {\n\t  return window.requestAnimationFrame ||\n\t    window.webkitRequestAnimationFrame ||\n\t    window.mozRequestAnimationFrame ||\n\t    window.oRequestAnimationFrame ||\n\t      // if all else fails, use setTimeout\n\t    function(callback) {\n\t      return window.setTimeout(callback, 1000 / 60); // shoot for 60 fps\n\t    };\n\t})();\n\n\t// handle multiple browsers for cancelAnimationFrame()\n\tUI.utils.cancelAF = (function() {\n\t  return window.cancelAnimationFrame ||\n\t    window.webkitCancelAnimationFrame ||\n\t    window.mozCancelAnimationFrame ||\n\t    window.oCancelAnimationFrame ||\n\t    function(id) {\n\t      window.clearTimeout(id);\n\t    };\n\t})();\n\n\t// via http://davidwalsh.name/detect-scrollbar-width\n\tUI.utils.measureScrollbar = function() {\n\t  if (document.body.clientWidth >= window.innerWidth) {\n\t    return 0;\n\t  }\n\n\t  // if ($html.width() >= window.innerWidth) return;\n\t  // var scrollbarWidth = window.innerWidth - $html.width();\n\t  var $measure = $('<div ' +\n\t  'style=\"width: 100px;height: 100px;overflow: scroll;' +\n\t  'position: absolute;top: -9999px;\"></div>');\n\n\t  $(document.body).append($measure);\n\n\t  var scrollbarWidth = $measure[0].offsetWidth - $measure[0].clientWidth;\n\n\t  $measure.remove();\n\n\t  return scrollbarWidth;\n\t};\n\n\tUI.utils.imageLoader = function($image, callback) {\n\t  function loaded() {\n\t    callback($image[0]);\n\t  }\n\n\t  function bindLoad() {\n\t    this.one('load', loaded);\n\t    if (/MSIE (\\d+\\.\\d+);/.test(navigator.userAgent)) {\n\t      var src = this.attr('src');\n\t      var param = src.match(/\\?/) ? '&' : '?';\n\n\t      param += 'random=' + (new Date()).getTime();\n\t      this.attr('src', src + param);\n\t    }\n\t  }\n\n\t  if (!$image.attr('src')) {\n\t    loaded();\n\t    return;\n\t  }\n\n\t  if ($image[0].complete || $image[0].readyState === 4) {\n\t    loaded();\n\t  } else {\n\t    bindLoad.call($image);\n\t  }\n\t};\n\n\t/**\n\t * https://github.com/cho45/micro-template.js\n\t * (c) cho45 http://cho45.github.com/mit-license\n\t */\n\t/* jshint -W109 */\n\tUI.template = function(id, data) {\n\t  var me = UI.template;\n\n\t  if (!me.cache[id]) {\n\t    me.cache[id] = (function() {\n\t      var name = id;\n\t      var string = /^[\\w\\-]+$/.test(id) ?\n\t        me.get(id) : (name = 'template(string)', id); // no warnings\n\n\t      var line = 1;\n\t      var body = ('try { ' + (me.variable ?\n\t      'var ' + me.variable + ' = this.stash;' : 'with (this.stash) { ') +\n\t      \"this.ret += '\" +\n\t      string.\n\t        replace(/<%/g, '\\x11').replace(/%>/g, '\\x13'). // if you want other tag, just edit this line\n\t        replace(/'(?![^\\x11\\x13]+?\\x13)/g, '\\\\x27').\n\t        replace(/^\\s*|\\s*$/g, '').\n\t        replace(/\\n/g, function() {\n\t          return \"';\\nthis.line = \" + (++line) + \"; this.ret += '\\\\n\";\n\t        }).\n\t        replace(/\\x11-(.+?)\\x13/g, \"' + ($1) + '\").\n\t        replace(/\\x11=(.+?)\\x13/g, \"' + this.escapeHTML($1) + '\").\n\t        replace(/\\x11(.+?)\\x13/g, \"'; $1; this.ret += '\") +\n\t      \"'; \" + (me.variable ? \"\" : \"}\") + \"return this.ret;\" +\n\t      \"} catch (e) { throw 'TemplateError: ' + e + ' (on \" + name +\n\t      \"' + ' line ' + this.line + ')'; } \" +\n\t      \"//@ sourceURL=\" + name + \"\\n\" // source map\n\t      ).replace(/this\\.ret \\+= '';/g, '');\n\t      /* jshint -W054 */\n\t      var func = new Function(body);\n\t      var map = {\n\t        '&': '&amp;',\n\t        '<': '&lt;',\n\t        '>': '&gt;',\n\t        '\\x22': '&#x22;',\n\t        '\\x27': '&#x27;'\n\t      };\n\t      var escapeHTML = function(string) {\n\t        return ('' + string).replace(/[&<>\\'\\\"]/g, function(_) {\n\t          return map[_];\n\t        });\n\t      };\n\n\t      return function(stash) {\n\t        return func.call(me.context = {\n\t          escapeHTML: escapeHTML,\n\t          line: 1,\n\t          ret: '',\n\t          stash: stash\n\t        });\n\t      };\n\t    })();\n\t  }\n\n\t  return data ? me.cache[id](data) : me.cache[id];\n\t};\n\t/* jshint +W109 */\n\t/* jshint +W054 */\n\n\tUI.template.cache = {};\n\n\tUI.template.get = function(id) {\n\t  if (id) {\n\t    var element = document.getElementById(id);\n\t    return element && element.innerHTML || '';\n\t  }\n\t};\n\n\t// Dom mutation watchers\n\tUI.DOMWatchers = [];\n\tUI.DOMReady = false;\n\tUI.ready = function(callback) {\n\t  UI.DOMWatchers.push(callback);\n\t  if (UI.DOMReady) {\n\t    // console.log('Ready call');\n\t    callback(document);\n\t  }\n\t};\n\n\tUI.DOMObserve = function(elements, options, callback) {\n\t  var Observer = UI.support.mutationobserver;\n\t  if (!Observer) {\n\t    return;\n\t  }\n\n\t  options = $.isPlainObject(options) ?\n\t    options : {childList: true, subtree: true};\n\n\t  callback = typeof callback === 'function' && callback || function() {\n\t  };\n\n\t  $(elements).each(function() {\n\t    var element = this;\n\t    var $element = $(element);\n\n\t    if ($element.data('am.observer')) {\n\t      return;\n\t    }\n\n\t    try {\n\t      var observer = new Observer(UI.utils.debounce(\n\t        function(mutations, instance) {\n\t        callback.call(element, mutations, instance);\n\t        // trigger this event manually if MutationObserver not supported\n\t        $element.trigger('changed.dom.amui');\n\t      }, 50));\n\n\t      observer.observe(element, options);\n\n\t      $element.data('am.observer', observer);\n\t    } catch (e) {\n\t    }\n\t  });\n\t};\n\n\t$.fn.DOMObserve = function(options, callback) {\n\t  return this.each(function() {\n\t    UI.DOMObserve(this, options, callback);\n\t  });\n\t};\n\n\tif (UI.support.touch) {\n\t  $html.addClass('am-touch');\n\t}\n\n\t$(document).on('changed.dom.amui', function(e) {\n\t  var element = e.target;\n\n\t  // TODO: just call changed element's watcher\n\t  //       every watcher callback should have a key\n\t  //       use like this: <div data-am-observe='key1, key2'>\n\t  //       get keys via $(element).data('amObserve')\n\t  //       call functions store with these keys\n\t  $.each(UI.DOMWatchers, function(i, watcher) {\n\t    watcher(element);\n\t  });\n\t});\n\n\t$(function() {\n\t  var $body = $('body');\n\n\t  UI.DOMReady = true;\n\n\t  // Run default init\n\t  $.each(UI.DOMWatchers, function(i, watcher) {\n\t    watcher(document);\n\t  });\n\n\t  // watches DOM\n\t  UI.DOMObserve('[data-am-observe]');\n\n\t  $html.removeClass('no-js').addClass('js');\n\n\t  UI.support.animation && $html.addClass('cssanimations');\n\n\t  // iOS standalone mode\n\t  if (window.navigator.standalone) {\n\t    $html.addClass('am-standalone');\n\t  }\n\n\t  $('.am-topbar-fixed-top').length &&\n\t  $body.addClass('am-with-topbar-fixed-top');\n\n\t  $('.am-topbar-fixed-bottom').length &&\n\t  $body.addClass('am-with-topbar-fixed-bottom');\n\n\t  // Remove responsive classes in .am-layout\n\t  var $layout = $('.am-layout');\n\t  $layout.find('[class*=\"md-block-grid\"]').alterClass('md-block-grid-*');\n\t  $layout.find('[class*=\"lg-block-grid\"]').alterClass('lg-block-grid');\n\n\t  // widgets not in .am-layout\n\t  $('[data-am-widget]').each(function() {\n\t    var $widget = $(this);\n\t    // console.log($widget.parents('.am-layout').length)\n\t    if ($widget.parents('.am-layout').length === 0) {\n\t      $widget.addClass('am-no-layout');\n\t    }\n\t  });\n\t});\n\n\tmodule.exports = UI;\n\n\n/***/ },\n/* 3 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t/*! Hammer.JS - v2.0.6 - 2015-12-23\n\t * http://hammerjs.github.io/\n\t *\n\t * Copyright (c) 2015 Jorik Tangelder;\n\t * Licensed under the MIT license */\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\n\tvar VENDOR_PREFIXES = ['', 'webkit', 'Moz', 'MS', 'ms', 'o'];\n\tvar TEST_ELEMENT = document.createElement('div');\n\n\tvar TYPE_FUNCTION = 'function';\n\n\tvar round = Math.round;\n\tvar abs = Math.abs;\n\tvar now = Date.now;\n\n\t/**\n\t * set a timeout with a given scope\n\t * @param {Function} fn\n\t * @param {Number} timeout\n\t * @param {Object} context\n\t * @returns {number}\n\t */\n\tfunction setTimeoutContext(fn, timeout, context) {\n\t  return setTimeout(bindFn(fn, context), timeout);\n\t}\n\n\t/**\n\t * if the argument is an array, we want to execute the fn on each entry\n\t * if it aint an array we don't want to do a thing.\n\t * this is used by all the methods that accept a single and array argument.\n\t * @param {*|Array} arg\n\t * @param {String} fn\n\t * @param {Object} [context]\n\t * @returns {Boolean}\n\t */\n\tfunction invokeArrayArg(arg, fn, context) {\n\t  if (Array.isArray(arg)) {\n\t    each(arg, context[fn], context);\n\t    return true;\n\t  }\n\t  return false;\n\t}\n\n\t/**\n\t * walk objects and arrays\n\t * @param {Object} obj\n\t * @param {Function} iterator\n\t * @param {Object} context\n\t */\n\tfunction each(obj, iterator, context) {\n\t  var i;\n\n\t  if (!obj) {\n\t    return;\n\t  }\n\n\t  if (obj.forEach) {\n\t    obj.forEach(iterator, context);\n\t  } else if (obj.length !== undefined) {\n\t    i = 0;\n\t    while (i < obj.length) {\n\t      iterator.call(context, obj[i], i, obj);\n\t      i++;\n\t    }\n\t  } else {\n\t    for (i in obj) {\n\t      obj.hasOwnProperty(i) && iterator.call(context, obj[i], i, obj);\n\t    }\n\t  }\n\t}\n\n\t/**\n\t * wrap a method with a deprecation warning and stack trace\n\t * @param {Function} method\n\t * @param {String} name\n\t * @param {String} message\n\t * @returns {Function} A new function wrapping the supplied method.\n\t */\n\tfunction deprecate(method, name, message) {\n\t  var deprecationMessage = 'DEPRECATED METHOD: ' + name + '\\n' + message + ' AT \\n';\n\t  return function() {\n\t    var e = new Error('get-stack-trace');\n\t    var stack = e && e.stack ? e.stack.replace(/^[^\\(]+?[\\n$]/gm, '')\n\t      .replace(/^\\s+at\\s+/gm, '')\n\t      .replace(/^Object.<anonymous>\\s*\\(/gm, '{anonymous}()@') : 'Unknown Stack Trace';\n\n\t    var log = window.console && (window.console.warn || window.console.log);\n\t    if (log) {\n\t      log.call(window.console, deprecationMessage, stack);\n\t    }\n\t    return method.apply(this, arguments);\n\t  };\n\t}\n\n\t/**\n\t * extend object.\n\t * means that properties in dest will be overwritten by the ones in src.\n\t * @param {Object} target\n\t * @param {...Object} objects_to_assign\n\t * @returns {Object} target\n\t */\n\tvar assign;\n\tif (typeof Object.assign !== 'function') {\n\t  assign = function assign(target) {\n\t    if (target === undefined || target === null) {\n\t      throw new TypeError('Cannot convert undefined or null to object');\n\t    }\n\n\t    var output = Object(target);\n\t    for (var index = 1; index < arguments.length; index++) {\n\t      var source = arguments[index];\n\t      if (source !== undefined && source !== null) {\n\t        for (var nextKey in source) {\n\t          if (source.hasOwnProperty(nextKey)) {\n\t            output[nextKey] = source[nextKey];\n\t          }\n\t        }\n\t      }\n\t    }\n\t    return output;\n\t  };\n\t} else {\n\t  assign = Object.assign;\n\t}\n\n\t/**\n\t * extend object.\n\t * means that properties in dest will be overwritten by the ones in src.\n\t * @param {Object} dest\n\t * @param {Object} src\n\t * @param {Boolean=false} [merge]\n\t * @returns {Object} dest\n\t */\n\tvar extend = deprecate(function extend(dest, src, merge) {\n\t  var keys = Object.keys(src);\n\t  var i = 0;\n\t  while (i < keys.length) {\n\t    if (!merge || (merge && dest[keys[i]] === undefined)) {\n\t      dest[keys[i]] = src[keys[i]];\n\t    }\n\t    i++;\n\t  }\n\t  return dest;\n\t}, 'extend', 'Use `assign`.');\n\n\t/**\n\t * merge the values from src in the dest.\n\t * means that properties that exist in dest will not be overwritten by src\n\t * @param {Object} dest\n\t * @param {Object} src\n\t * @returns {Object} dest\n\t */\n\tvar merge = deprecate(function merge(dest, src) {\n\t  return extend(dest, src, true);\n\t}, 'merge', 'Use `assign`.');\n\n\t/**\n\t * simple class inheritance\n\t * @param {Function} child\n\t * @param {Function} base\n\t * @param {Object} [properties]\n\t */\n\tfunction inherit(child, base, properties) {\n\t  var baseP = base.prototype,\n\t    childP;\n\n\t  childP = child.prototype = Object.create(baseP);\n\t  childP.constructor = child;\n\t  childP._super = baseP;\n\n\t  if (properties) {\n\t    assign(childP, properties);\n\t  }\n\t}\n\n\t/**\n\t * simple function bind\n\t * @param {Function} fn\n\t * @param {Object} context\n\t * @returns {Function}\n\t */\n\tfunction bindFn(fn, context) {\n\t  return function boundFn() {\n\t    return fn.apply(context, arguments);\n\t  };\n\t}\n\n\t/**\n\t * let a boolean value also be a function that must return a boolean\n\t * this first item in args will be used as the context\n\t * @param {Boolean|Function} val\n\t * @param {Array} [args]\n\t * @returns {Boolean}\n\t */\n\tfunction boolOrFn(val, args) {\n\t  if (typeof val == TYPE_FUNCTION) {\n\t    return val.apply(args ? args[0] || undefined : undefined, args);\n\t  }\n\t  return val;\n\t}\n\n\t/**\n\t * use the val2 when val1 is undefined\n\t * @param {*} val1\n\t * @param {*} val2\n\t * @returns {*}\n\t */\n\tfunction ifUndefined(val1, val2) {\n\t  return (val1 === undefined) ? val2 : val1;\n\t}\n\n\t/**\n\t * addEventListener with multiple events at once\n\t * @param {EventTarget} target\n\t * @param {String} types\n\t * @param {Function} handler\n\t */\n\tfunction addEventListeners(target, types, handler) {\n\t  each(splitStr(types), function(type) {\n\t    target.addEventListener(type, handler, false);\n\t  });\n\t}\n\n\t/**\n\t * removeEventListener with multiple events at once\n\t * @param {EventTarget} target\n\t * @param {String} types\n\t * @param {Function} handler\n\t */\n\tfunction removeEventListeners(target, types, handler) {\n\t  each(splitStr(types), function(type) {\n\t    target.removeEventListener(type, handler, false);\n\t  });\n\t}\n\n\t/**\n\t * find if a node is in the given parent\n\t * @method hasParent\n\t * @param {HTMLElement} node\n\t * @param {HTMLElement} parent\n\t * @return {Boolean} found\n\t */\n\tfunction hasParent(node, parent) {\n\t  while (node) {\n\t    if (node == parent) {\n\t      return true;\n\t    }\n\t    node = node.parentNode;\n\t  }\n\t  return false;\n\t}\n\n\t/**\n\t * small indexOf wrapper\n\t * @param {String} str\n\t * @param {String} find\n\t * @returns {Boolean} found\n\t */\n\tfunction inStr(str, find) {\n\t  return str.indexOf(find) > -1;\n\t}\n\n\t/**\n\t * split string on whitespace\n\t * @param {String} str\n\t * @returns {Array} words\n\t */\n\tfunction splitStr(str) {\n\t  return str.trim().split(/\\s+/g);\n\t}\n\n\t/**\n\t * find if a array contains the object using indexOf or a simple polyFill\n\t * @param {Array} src\n\t * @param {String} find\n\t * @param {String} [findByKey]\n\t * @return {Boolean|Number} false when not found, or the index\n\t */\n\tfunction inArray(src, find, findByKey) {\n\t  if (src.indexOf && !findByKey) {\n\t    return src.indexOf(find);\n\t  } else {\n\t    var i = 0;\n\t    while (i < src.length) {\n\t      if ((findByKey && src[i][findByKey] == find) || (!findByKey && src[i] === find)) {\n\t        return i;\n\t      }\n\t      i++;\n\t    }\n\t    return -1;\n\t  }\n\t}\n\n\t/**\n\t * convert array-like objects to real arrays\n\t * @param {Object} obj\n\t * @returns {Array}\n\t */\n\tfunction toArray(obj) {\n\t  return Array.prototype.slice.call(obj, 0);\n\t}\n\n\t/**\n\t * unique array with objects based on a key (like 'id') or just by the array's value\n\t * @param {Array} src [{id:1},{id:2},{id:1}]\n\t * @param {String} [key]\n\t * @param {Boolean} [sort=False]\n\t * @returns {Array} [{id:1},{id:2}]\n\t */\n\tfunction uniqueArray(src, key, sort) {\n\t  var results = [];\n\t  var values = [];\n\t  var i = 0;\n\n\t  while (i < src.length) {\n\t    var val = key ? src[i][key] : src[i];\n\t    if (inArray(values, val) < 0) {\n\t      results.push(src[i]);\n\t    }\n\t    values[i] = val;\n\t    i++;\n\t  }\n\n\t  if (sort) {\n\t    if (!key) {\n\t      results = results.sort();\n\t    } else {\n\t      results = results.sort(function sortUniqueArray(a, b) {\n\t        return a[key] > b[key];\n\t      });\n\t    }\n\t  }\n\n\t  return results;\n\t}\n\n\t/**\n\t * get the prefixed property\n\t * @param {Object} obj\n\t * @param {String} property\n\t * @returns {String|Undefined} prefixed\n\t */\n\tfunction prefixed(obj, property) {\n\t  var prefix, prop;\n\t  var camelProp = property[0].toUpperCase() + property.slice(1);\n\n\t  var i = 0;\n\t  while (i < VENDOR_PREFIXES.length) {\n\t    prefix = VENDOR_PREFIXES[i];\n\t    prop = (prefix) ? prefix + camelProp : property;\n\n\t    if (prop in obj) {\n\t      return prop;\n\t    }\n\t    i++;\n\t  }\n\t  return undefined;\n\t}\n\n\t/**\n\t * get a unique id\n\t * @returns {number} uniqueId\n\t */\n\tvar _uniqueId = 1;\n\tfunction uniqueId() {\n\t  return _uniqueId++;\n\t}\n\n\t/**\n\t * get the window object of an element\n\t * @param {HTMLElement} element\n\t * @returns {DocumentView|Window}\n\t */\n\tfunction getWindowForElement(element) {\n\t  var doc = element.ownerDocument || element;\n\t  return (doc.defaultView || doc.parentWindow || window);\n\t}\n\n\tvar MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i;\n\n\tvar SUPPORT_TOUCH = ('ontouchstart' in window);\n\tvar SUPPORT_POINTER_EVENTS = prefixed(window, 'PointerEvent') !== undefined;\n\tvar SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent);\n\n\tvar INPUT_TYPE_TOUCH = 'touch';\n\tvar INPUT_TYPE_PEN = 'pen';\n\tvar INPUT_TYPE_MOUSE = 'mouse';\n\tvar INPUT_TYPE_KINECT = 'kinect';\n\n\tvar COMPUTE_INTERVAL = 25;\n\n\tvar INPUT_START = 1;\n\tvar INPUT_MOVE = 2;\n\tvar INPUT_END = 4;\n\tvar INPUT_CANCEL = 8;\n\n\tvar DIRECTION_NONE = 1;\n\tvar DIRECTION_LEFT = 2;\n\tvar DIRECTION_RIGHT = 4;\n\tvar DIRECTION_UP = 8;\n\tvar DIRECTION_DOWN = 16;\n\n\tvar DIRECTION_HORIZONTAL = DIRECTION_LEFT | DIRECTION_RIGHT;\n\tvar DIRECTION_VERTICAL = DIRECTION_UP | DIRECTION_DOWN;\n\tvar DIRECTION_ALL = DIRECTION_HORIZONTAL | DIRECTION_VERTICAL;\n\n\tvar PROPS_XY = ['x', 'y'];\n\tvar PROPS_CLIENT_XY = ['clientX', 'clientY'];\n\n\t/**\n\t * create new input type manager\n\t * @param {Manager} manager\n\t * @param {Function} callback\n\t * @returns {Input}\n\t * @constructor\n\t */\n\tfunction Input(manager, callback) {\n\t  var self = this;\n\t  this.manager = manager;\n\t  this.callback = callback;\n\t  this.element = manager.element;\n\t  this.target = manager.options.inputTarget;\n\n\t  // smaller wrapper around the handler, for the scope and the enabled state of the manager,\n\t  // so when disabled the input events are completely bypassed.\n\t  this.domHandler = function(ev) {\n\t    if (boolOrFn(manager.options.enable, [manager])) {\n\t      self.handler(ev);\n\t    }\n\t  };\n\n\t  this.init();\n\n\t}\n\n\tInput.prototype = {\n\t  /**\n\t   * should handle the inputEvent data and trigger the callback\n\t   * @virtual\n\t   */\n\t  handler: function() { },\n\n\t  /**\n\t   * bind the events\n\t   */\n\t  init: function() {\n\t    this.evEl && addEventListeners(this.element, this.evEl, this.domHandler);\n\t    this.evTarget && addEventListeners(this.target, this.evTarget, this.domHandler);\n\t    this.evWin && addEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler);\n\t  },\n\n\t  /**\n\t   * unbind the events\n\t   */\n\t  destroy: function() {\n\t    this.evEl && removeEventListeners(this.element, this.evEl, this.domHandler);\n\t    this.evTarget && removeEventListeners(this.target, this.evTarget, this.domHandler);\n\t    this.evWin && removeEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler);\n\t  }\n\t};\n\n\t/**\n\t * create new input type manager\n\t * called by the Manager constructor\n\t * @param {Hammer} manager\n\t * @returns {Input}\n\t */\n\tfunction createInputInstance(manager) {\n\t  var Type;\n\t  var inputClass = manager.options.inputClass;\n\n\t  if (inputClass) {\n\t    Type = inputClass;\n\t  } else if (SUPPORT_POINTER_EVENTS) {\n\t    Type = PointerEventInput;\n\t  } else if (SUPPORT_ONLY_TOUCH) {\n\t    Type = TouchInput;\n\t  } else if (!SUPPORT_TOUCH) {\n\t    Type = MouseInput;\n\t  } else {\n\t    Type = TouchMouseInput;\n\t  }\n\t  return new (Type)(manager, inputHandler);\n\t}\n\n\t/**\n\t * handle input events\n\t * @param {Manager} manager\n\t * @param {String} eventType\n\t * @param {Object} input\n\t */\n\tfunction inputHandler(manager, eventType, input) {\n\t  var pointersLen = input.pointers.length;\n\t  var changedPointersLen = input.changedPointers.length;\n\t  var isFirst = (eventType & INPUT_START && (pointersLen - changedPointersLen === 0));\n\t  var isFinal = (eventType & (INPUT_END | INPUT_CANCEL) && (pointersLen - changedPointersLen === 0));\n\n\t  input.isFirst = !!isFirst;\n\t  input.isFinal = !!isFinal;\n\n\t  if (isFirst) {\n\t    manager.session = {};\n\t  }\n\n\t  // source event is the normalized value of the domEvents\n\t  // like 'touchstart, mouseup, pointerdown'\n\t  input.eventType = eventType;\n\n\t  // compute scale, rotation etc\n\t  computeInputData(manager, input);\n\n\t  // emit secret event\n\t  manager.emit('hammer.input', input);\n\n\t  manager.recognize(input);\n\t  manager.session.prevInput = input;\n\t}\n\n\t/**\n\t * extend the data with some usable properties like scale, rotate, velocity etc\n\t * @param {Object} manager\n\t * @param {Object} input\n\t */\n\tfunction computeInputData(manager, input) {\n\t  var session = manager.session;\n\t  var pointers = input.pointers;\n\t  var pointersLength = pointers.length;\n\n\t  // store the first input to calculate the distance and direction\n\t  if (!session.firstInput) {\n\t    session.firstInput = simpleCloneInputData(input);\n\t  }\n\n\t  // to compute scale and rotation we need to store the multiple touches\n\t  if (pointersLength > 1 && !session.firstMultiple) {\n\t    session.firstMultiple = simpleCloneInputData(input);\n\t  } else if (pointersLength === 1) {\n\t    session.firstMultiple = false;\n\t  }\n\n\t  var firstInput = session.firstInput;\n\t  var firstMultiple = session.firstMultiple;\n\t  var offsetCenter = firstMultiple ? firstMultiple.center : firstInput.center;\n\n\t  var center = input.center = getCenter(pointers);\n\t  input.timeStamp = now();\n\t  input.deltaTime = input.timeStamp - firstInput.timeStamp;\n\n\t  input.angle = getAngle(offsetCenter, center);\n\t  input.distance = getDistance(offsetCenter, center);\n\n\t  computeDeltaXY(session, input);\n\t  input.offsetDirection = getDirection(input.deltaX, input.deltaY);\n\n\t  var overallVelocity = getVelocity(input.deltaTime, input.deltaX, input.deltaY);\n\t  input.overallVelocityX = overallVelocity.x;\n\t  input.overallVelocityY = overallVelocity.y;\n\t  input.overallVelocity = (abs(overallVelocity.x) > abs(overallVelocity.y)) ? overallVelocity.x : overallVelocity.y;\n\n\t  input.scale = firstMultiple ? getScale(firstMultiple.pointers, pointers) : 1;\n\t  input.rotation = firstMultiple ? getRotation(firstMultiple.pointers, pointers) : 0;\n\n\t  input.maxPointers = !session.prevInput ? input.pointers.length : ((input.pointers.length >\n\t  session.prevInput.maxPointers) ? input.pointers.length : session.prevInput.maxPointers);\n\n\t  computeIntervalInputData(session, input);\n\n\t  // find the correct target\n\t  var target = manager.element;\n\t  if (hasParent(input.srcEvent.target, target)) {\n\t    target = input.srcEvent.target;\n\t  }\n\t  input.target = target;\n\t}\n\n\tfunction computeDeltaXY(session, input) {\n\t  var center = input.center;\n\t  var offset = session.offsetDelta || {};\n\t  var prevDelta = session.prevDelta || {};\n\t  var prevInput = session.prevInput || {};\n\n\t  if (input.eventType === INPUT_START || prevInput.eventType === INPUT_END) {\n\t    prevDelta = session.prevDelta = {\n\t      x: prevInput.deltaX || 0,\n\t      y: prevInput.deltaY || 0\n\t    };\n\n\t    offset = session.offsetDelta = {\n\t      x: center.x,\n\t      y: center.y\n\t    };\n\t  }\n\n\t  input.deltaX = prevDelta.x + (center.x - offset.x);\n\t  input.deltaY = prevDelta.y + (center.y - offset.y);\n\t}\n\n\t/**\n\t * velocity is calculated every x ms\n\t * @param {Object} session\n\t * @param {Object} input\n\t */\n\tfunction computeIntervalInputData(session, input) {\n\t  var last = session.lastInterval || input,\n\t    deltaTime = input.timeStamp - last.timeStamp,\n\t    velocity, velocityX, velocityY, direction;\n\n\t  if (input.eventType != INPUT_CANCEL && (deltaTime > COMPUTE_INTERVAL || last.velocity === undefined)) {\n\t    var deltaX = input.deltaX - last.deltaX;\n\t    var deltaY = input.deltaY - last.deltaY;\n\n\t    var v = getVelocity(deltaTime, deltaX, deltaY);\n\t    velocityX = v.x;\n\t    velocityY = v.y;\n\t    velocity = (abs(v.x) > abs(v.y)) ? v.x : v.y;\n\t    direction = getDirection(deltaX, deltaY);\n\n\t    session.lastInterval = input;\n\t  } else {\n\t    // use latest velocity info if it doesn't overtake a minimum period\n\t    velocity = last.velocity;\n\t    velocityX = last.velocityX;\n\t    velocityY = last.velocityY;\n\t    direction = last.direction;\n\t  }\n\n\t  input.velocity = velocity;\n\t  input.velocityX = velocityX;\n\t  input.velocityY = velocityY;\n\t  input.direction = direction;\n\t}\n\n\t/**\n\t * create a simple clone from the input used for storage of firstInput and firstMultiple\n\t * @param {Object} input\n\t * @returns {Object} clonedInputData\n\t */\n\tfunction simpleCloneInputData(input) {\n\t  // make a simple copy of the pointers because we will get a reference if we don't\n\t  // we only need clientXY for the calculations\n\t  var pointers = [];\n\t  var i = 0;\n\t  while (i < input.pointers.length) {\n\t    pointers[i] = {\n\t      clientX: round(input.pointers[i].clientX),\n\t      clientY: round(input.pointers[i].clientY)\n\t    };\n\t    i++;\n\t  }\n\n\t  return {\n\t    timeStamp: now(),\n\t    pointers: pointers,\n\t    center: getCenter(pointers),\n\t    deltaX: input.deltaX,\n\t    deltaY: input.deltaY\n\t  };\n\t}\n\n\t/**\n\t * get the center of all the pointers\n\t * @param {Array} pointers\n\t * @return {Object} center contains `x` and `y` properties\n\t */\n\tfunction getCenter(pointers) {\n\t  var pointersLength = pointers.length;\n\n\t  // no need to loop when only one touch\n\t  if (pointersLength === 1) {\n\t    return {\n\t      x: round(pointers[0].clientX),\n\t      y: round(pointers[0].clientY)\n\t    };\n\t  }\n\n\t  var x = 0, y = 0, i = 0;\n\t  while (i < pointersLength) {\n\t    x += pointers[i].clientX;\n\t    y += pointers[i].clientY;\n\t    i++;\n\t  }\n\n\t  return {\n\t    x: round(x / pointersLength),\n\t    y: round(y / pointersLength)\n\t  };\n\t}\n\n\t/**\n\t * calculate the velocity between two points. unit is in px per ms.\n\t * @param {Number} deltaTime\n\t * @param {Number} x\n\t * @param {Number} y\n\t * @return {Object} velocity `x` and `y`\n\t */\n\tfunction getVelocity(deltaTime, x, y) {\n\t  return {\n\t    x: x / deltaTime || 0,\n\t    y: y / deltaTime || 0\n\t  };\n\t}\n\n\t/**\n\t * get the direction between two points\n\t * @param {Number} x\n\t * @param {Number} y\n\t * @return {Number} direction\n\t */\n\tfunction getDirection(x, y) {\n\t  if (x === y) {\n\t    return DIRECTION_NONE;\n\t  }\n\n\t  if (abs(x) >= abs(y)) {\n\t    return x < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT;\n\t  }\n\t  return y < 0 ? DIRECTION_UP : DIRECTION_DOWN;\n\t}\n\n\t/**\n\t * calculate the absolute distance between two points\n\t * @param {Object} p1 {x, y}\n\t * @param {Object} p2 {x, y}\n\t * @param {Array} [props] containing x and y keys\n\t * @return {Number} distance\n\t */\n\tfunction getDistance(p1, p2, props) {\n\t  if (!props) {\n\t    props = PROPS_XY;\n\t  }\n\t  var x = p2[props[0]] - p1[props[0]],\n\t    y = p2[props[1]] - p1[props[1]];\n\n\t  return Math.sqrt((x * x) + (y * y));\n\t}\n\n\t/**\n\t * calculate the angle between two coordinates\n\t * @param {Object} p1\n\t * @param {Object} p2\n\t * @param {Array} [props] containing x and y keys\n\t * @return {Number} angle\n\t */\n\tfunction getAngle(p1, p2, props) {\n\t  if (!props) {\n\t    props = PROPS_XY;\n\t  }\n\t  var x = p2[props[0]] - p1[props[0]],\n\t    y = p2[props[1]] - p1[props[1]];\n\t  return Math.atan2(y, x) * 180 / Math.PI;\n\t}\n\n\t/**\n\t * calculate the rotation degrees between two pointersets\n\t * @param {Array} start array of pointers\n\t * @param {Array} end array of pointers\n\t * @return {Number} rotation\n\t */\n\tfunction getRotation(start, end) {\n\t  return getAngle(end[1], end[0], PROPS_CLIENT_XY) + getAngle(start[1], start[0], PROPS_CLIENT_XY);\n\t}\n\n\t/**\n\t * calculate the scale factor between two pointersets\n\t * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out\n\t * @param {Array} start array of pointers\n\t * @param {Array} end array of pointers\n\t * @return {Number} scale\n\t */\n\tfunction getScale(start, end) {\n\t  return getDistance(end[0], end[1], PROPS_CLIENT_XY) / getDistance(start[0], start[1], PROPS_CLIENT_XY);\n\t}\n\n\tvar MOUSE_INPUT_MAP = {\n\t  mousedown: INPUT_START,\n\t  mousemove: INPUT_MOVE,\n\t  mouseup: INPUT_END\n\t};\n\n\tvar MOUSE_ELEMENT_EVENTS = 'mousedown';\n\tvar MOUSE_WINDOW_EVENTS = 'mousemove mouseup';\n\n\t/**\n\t * Mouse events input\n\t * @constructor\n\t * @extends Input\n\t */\n\tfunction MouseInput() {\n\t  this.evEl = MOUSE_ELEMENT_EVENTS;\n\t  this.evWin = MOUSE_WINDOW_EVENTS;\n\n\t  this.allow = true; // used by Input.TouchMouse to disable mouse events\n\t  this.pressed = false; // mousedown state\n\n\t  Input.apply(this, arguments);\n\t}\n\n\tinherit(MouseInput, Input, {\n\t  /**\n\t   * handle mouse events\n\t   * @param {Object} ev\n\t   */\n\t  handler: function MEhandler(ev) {\n\t    var eventType = MOUSE_INPUT_MAP[ev.type];\n\n\t    // on start we want to have the left mouse button down\n\t    if (eventType & INPUT_START && ev.button === 0) {\n\t      this.pressed = true;\n\t    }\n\n\t    if (eventType & INPUT_MOVE && ev.which !== 1) {\n\t      eventType = INPUT_END;\n\t    }\n\n\t    // mouse must be down, and mouse events are allowed (see the TouchMouse input)\n\t    if (!this.pressed || !this.allow) {\n\t      return;\n\t    }\n\n\t    if (eventType & INPUT_END) {\n\t      this.pressed = false;\n\t    }\n\n\t    this.callback(this.manager, eventType, {\n\t      pointers: [ev],\n\t      changedPointers: [ev],\n\t      pointerType: INPUT_TYPE_MOUSE,\n\t      srcEvent: ev\n\t    });\n\t  }\n\t});\n\n\tvar POINTER_INPUT_MAP = {\n\t  pointerdown: INPUT_START,\n\t  pointermove: INPUT_MOVE,\n\t  pointerup: INPUT_END,\n\t  pointercancel: INPUT_CANCEL,\n\t  pointerout: INPUT_CANCEL\n\t};\n\n\t// in IE10 the pointer types is defined as an enum\n\tvar IE10_POINTER_TYPE_ENUM = {\n\t  2: INPUT_TYPE_TOUCH,\n\t  3: INPUT_TYPE_PEN,\n\t  4: INPUT_TYPE_MOUSE,\n\t  5: INPUT_TYPE_KINECT // see https://twitter.com/jacobrossi/status/480596438489890816\n\t};\n\n\tvar POINTER_ELEMENT_EVENTS = 'pointerdown';\n\tvar POINTER_WINDOW_EVENTS = 'pointermove pointerup pointercancel';\n\n\t// IE10 has prefixed support, and case-sensitive\n\tif (window.MSPointerEvent && !window.PointerEvent) {\n\t  POINTER_ELEMENT_EVENTS = 'MSPointerDown';\n\t  POINTER_WINDOW_EVENTS = 'MSPointerMove MSPointerUp MSPointerCancel';\n\t}\n\n\t/**\n\t * Pointer events input\n\t * @constructor\n\t * @extends Input\n\t */\n\tfunction PointerEventInput() {\n\t  this.evEl = POINTER_ELEMENT_EVENTS;\n\t  this.evWin = POINTER_WINDOW_EVENTS;\n\n\t  Input.apply(this, arguments);\n\n\t  this.store = (this.manager.session.pointerEvents = []);\n\t}\n\n\tinherit(PointerEventInput, Input, {\n\t  /**\n\t   * handle mouse events\n\t   * @param {Object} ev\n\t   */\n\t  handler: function PEhandler(ev) {\n\t    var store = this.store;\n\t    var removePointer = false;\n\n\t    var eventTypeNormalized = ev.type.toLowerCase().replace('ms', '');\n\t    var eventType = POINTER_INPUT_MAP[eventTypeNormalized];\n\t    var pointerType = IE10_POINTER_TYPE_ENUM[ev.pointerType] || ev.pointerType;\n\n\t    var isTouch = (pointerType == INPUT_TYPE_TOUCH);\n\n\t    // get index of the event in the store\n\t    var storeIndex = inArray(store, ev.pointerId, 'pointerId');\n\n\t    // start and mouse must be down\n\t    if (eventType & INPUT_START && (ev.button === 0 || isTouch)) {\n\t      if (storeIndex < 0) {\n\t        store.push(ev);\n\t        storeIndex = store.length - 1;\n\t      }\n\t    } else if (eventType & (INPUT_END | INPUT_CANCEL)) {\n\t      removePointer = true;\n\t    }\n\n\t    // it not found, so the pointer hasn't been down (so it's probably a hover)\n\t    if (storeIndex < 0) {\n\t      return;\n\t    }\n\n\t    // update the event in the store\n\t    store[storeIndex] = ev;\n\n\t    this.callback(this.manager, eventType, {\n\t      pointers: store,\n\t      changedPointers: [ev],\n\t      pointerType: pointerType,\n\t      srcEvent: ev\n\t    });\n\n\t    if (removePointer) {\n\t      // remove from the store\n\t      store.splice(storeIndex, 1);\n\t    }\n\t  }\n\t});\n\n\tvar SINGLE_TOUCH_INPUT_MAP = {\n\t  touchstart: INPUT_START,\n\t  touchmove: INPUT_MOVE,\n\t  touchend: INPUT_END,\n\t  touchcancel: INPUT_CANCEL\n\t};\n\n\tvar SINGLE_TOUCH_TARGET_EVENTS = 'touchstart';\n\tvar SINGLE_TOUCH_WINDOW_EVENTS = 'touchstart touchmove touchend touchcancel';\n\n\t/**\n\t * Touch events input\n\t * @constructor\n\t * @extends Input\n\t */\n\tfunction SingleTouchInput() {\n\t  this.evTarget = SINGLE_TOUCH_TARGET_EVENTS;\n\t  this.evWin = SINGLE_TOUCH_WINDOW_EVENTS;\n\t  this.started = false;\n\n\t  Input.apply(this, arguments);\n\t}\n\n\tinherit(SingleTouchInput, Input, {\n\t  handler: function TEhandler(ev) {\n\t    var type = SINGLE_TOUCH_INPUT_MAP[ev.type];\n\n\t    // should we handle the touch events?\n\t    if (type === INPUT_START) {\n\t      this.started = true;\n\t    }\n\n\t    if (!this.started) {\n\t      return;\n\t    }\n\n\t    var touches = normalizeSingleTouches.call(this, ev, type);\n\n\t    // when done, reset the started state\n\t    if (type & (INPUT_END | INPUT_CANCEL) && touches[0].length - touches[1].length === 0) {\n\t      this.started = false;\n\t    }\n\n\t    this.callback(this.manager, type, {\n\t      pointers: touches[0],\n\t      changedPointers: touches[1],\n\t      pointerType: INPUT_TYPE_TOUCH,\n\t      srcEvent: ev\n\t    });\n\t  }\n\t});\n\n\t/**\n\t * @this {TouchInput}\n\t * @param {Object} ev\n\t * @param {Number} type flag\n\t * @returns {undefined|Array} [all, changed]\n\t */\n\tfunction normalizeSingleTouches(ev, type) {\n\t  var all = toArray(ev.touches);\n\t  var changed = toArray(ev.changedTouches);\n\n\t  if (type & (INPUT_END | INPUT_CANCEL)) {\n\t    all = uniqueArray(all.concat(changed), 'identifier', true);\n\t  }\n\n\t  return [all, changed];\n\t}\n\n\tvar TOUCH_INPUT_MAP = {\n\t  touchstart: INPUT_START,\n\t  touchmove: INPUT_MOVE,\n\t  touchend: INPUT_END,\n\t  touchcancel: INPUT_CANCEL\n\t};\n\n\tvar TOUCH_TARGET_EVENTS = 'touchstart touchmove touchend touchcancel';\n\n\t/**\n\t * Multi-user touch events input\n\t * @constructor\n\t * @extends Input\n\t */\n\tfunction TouchInput() {\n\t  this.evTarget = TOUCH_TARGET_EVENTS;\n\t  this.targetIds = {};\n\n\t  Input.apply(this, arguments);\n\t}\n\n\tinherit(TouchInput, Input, {\n\t  handler: function MTEhandler(ev) {\n\t    var type = TOUCH_INPUT_MAP[ev.type];\n\t    var touches = getTouches.call(this, ev, type);\n\t    if (!touches) {\n\t      return;\n\t    }\n\n\t    this.callback(this.manager, type, {\n\t      pointers: touches[0],\n\t      changedPointers: touches[1],\n\t      pointerType: INPUT_TYPE_TOUCH,\n\t      srcEvent: ev\n\t    });\n\t  }\n\t});\n\n\t/**\n\t * @this {TouchInput}\n\t * @param {Object} ev\n\t * @param {Number} type flag\n\t * @returns {undefined|Array} [all, changed]\n\t */\n\tfunction getTouches(ev, type) {\n\t  var allTouches = toArray(ev.touches);\n\t  var targetIds = this.targetIds;\n\n\t  // when there is only one touch, the process can be simplified\n\t  if (type & (INPUT_START | INPUT_MOVE) && allTouches.length === 1) {\n\t    targetIds[allTouches[0].identifier] = true;\n\t    return [allTouches, allTouches];\n\t  }\n\n\t  var i,\n\t    targetTouches,\n\t    changedTouches = toArray(ev.changedTouches),\n\t    changedTargetTouches = [],\n\t    target = this.target;\n\n\t  // get target touches from touches\n\t  targetTouches = allTouches.filter(function(touch) {\n\t    return hasParent(touch.target, target);\n\t  });\n\n\t  // collect touches\n\t  if (type === INPUT_START) {\n\t    i = 0;\n\t    while (i < targetTouches.length) {\n\t      targetIds[targetTouches[i].identifier] = true;\n\t      i++;\n\t    }\n\t  }\n\n\t  // filter changed touches to only contain touches that exist in the collected target ids\n\t  i = 0;\n\t  while (i < changedTouches.length) {\n\t    if (targetIds[changedTouches[i].identifier]) {\n\t      changedTargetTouches.push(changedTouches[i]);\n\t    }\n\n\t    // cleanup removed touches\n\t    if (type & (INPUT_END | INPUT_CANCEL)) {\n\t      delete targetIds[changedTouches[i].identifier];\n\t    }\n\t    i++;\n\t  }\n\n\t  if (!changedTargetTouches.length) {\n\t    return;\n\t  }\n\n\t  return [\n\t    // merge targetTouches with changedTargetTouches so it contains ALL touches, including 'end' and 'cancel'\n\t    uniqueArray(targetTouches.concat(changedTargetTouches), 'identifier', true),\n\t    changedTargetTouches\n\t  ];\n\t}\n\n\t/**\n\t * Combined touch and mouse input\n\t *\n\t * Touch has a higher priority then mouse, and while touching no mouse events are allowed.\n\t * This because touch devices also emit mouse events while doing a touch.\n\t *\n\t * @constructor\n\t * @extends Input\n\t */\n\tfunction TouchMouseInput() {\n\t  Input.apply(this, arguments);\n\n\t  var handler = bindFn(this.handler, this);\n\t  this.touch = new TouchInput(this.manager, handler);\n\t  this.mouse = new MouseInput(this.manager, handler);\n\t}\n\n\tinherit(TouchMouseInput, Input, {\n\t  /**\n\t   * handle mouse and touch events\n\t   * @param {Hammer} manager\n\t   * @param {String} inputEvent\n\t   * @param {Object} inputData\n\t   */\n\t  handler: function TMEhandler(manager, inputEvent, inputData) {\n\t    var isTouch = (inputData.pointerType == INPUT_TYPE_TOUCH),\n\t      isMouse = (inputData.pointerType == INPUT_TYPE_MOUSE);\n\n\t    // when we're in a touch event, so  block all upcoming mouse events\n\t    // most mobile browser also emit mouseevents, right after touchstart\n\t    if (isTouch) {\n\t      this.mouse.allow = false;\n\t    } else if (isMouse && !this.mouse.allow) {\n\t      return;\n\t    }\n\n\t    // reset the allowMouse when we're done\n\t    if (inputEvent & (INPUT_END | INPUT_CANCEL)) {\n\t      this.mouse.allow = true;\n\t    }\n\n\t    this.callback(manager, inputEvent, inputData);\n\t  },\n\n\t  /**\n\t   * remove the event listeners\n\t   */\n\t  destroy: function destroy() {\n\t    this.touch.destroy();\n\t    this.mouse.destroy();\n\t  }\n\t});\n\n\tvar PREFIXED_TOUCH_ACTION = prefixed(TEST_ELEMENT.style, 'touchAction');\n\tvar NATIVE_TOUCH_ACTION = PREFIXED_TOUCH_ACTION !== undefined;\n\n\t// magical touchAction value\n\tvar TOUCH_ACTION_COMPUTE = 'compute';\n\tvar TOUCH_ACTION_AUTO = 'auto';\n\tvar TOUCH_ACTION_MANIPULATION = 'manipulation'; // not implemented\n\tvar TOUCH_ACTION_NONE = 'none';\n\tvar TOUCH_ACTION_PAN_X = 'pan-x';\n\tvar TOUCH_ACTION_PAN_Y = 'pan-y';\n\n\t/**\n\t * Touch Action\n\t * sets the touchAction property or uses the js alternative\n\t * @param {Manager} manager\n\t * @param {String} value\n\t * @constructor\n\t */\n\tfunction TouchAction(manager, value) {\n\t  this.manager = manager;\n\t  this.set(value);\n\t}\n\n\tTouchAction.prototype = {\n\t  /**\n\t   * set the touchAction value on the element or enable the polyfill\n\t   * @param {String} value\n\t   */\n\t  set: function(value) {\n\t    // find out the touch-action by the event handlers\n\t    if (value == TOUCH_ACTION_COMPUTE) {\n\t      value = this.compute();\n\t    }\n\n\t    if (NATIVE_TOUCH_ACTION && this.manager.element.style) {\n\t      this.manager.element.style[PREFIXED_TOUCH_ACTION] = value;\n\t    }\n\t    this.actions = value.toLowerCase().trim();\n\t  },\n\n\t  /**\n\t   * just re-set the touchAction value\n\t   */\n\t  update: function() {\n\t    this.set(this.manager.options.touchAction);\n\t  },\n\n\t  /**\n\t   * compute the value for the touchAction property based on the recognizer's settings\n\t   * @returns {String} value\n\t   */\n\t  compute: function() {\n\t    var actions = [];\n\t    each(this.manager.recognizers, function(recognizer) {\n\t      if (boolOrFn(recognizer.options.enable, [recognizer])) {\n\t        actions = actions.concat(recognizer.getTouchAction());\n\t      }\n\t    });\n\t    return cleanTouchActions(actions.join(' '));\n\t  },\n\n\t  /**\n\t   * this method is called on each input cycle and provides the preventing of the browser behavior\n\t   * @param {Object} input\n\t   */\n\t  preventDefaults: function(input) {\n\t    // not needed with native support for the touchAction property\n\t    if (NATIVE_TOUCH_ACTION) {\n\t      return;\n\t    }\n\n\t    var srcEvent = input.srcEvent;\n\t    var direction = input.offsetDirection;\n\n\t    // if the touch action did prevented once this session\n\t    if (this.manager.session.prevented) {\n\t      srcEvent.preventDefault();\n\t      return;\n\t    }\n\n\t    var actions = this.actions;\n\t    var hasNone = inStr(actions, TOUCH_ACTION_NONE);\n\t    var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y);\n\t    var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X);\n\n\t    if (hasNone) {\n\t      //do not prevent defaults if this is a tap gesture\n\n\t      var isTapPointer = input.pointers.length === 1;\n\t      var isTapMovement = input.distance < 2;\n\t      var isTapTouchTime = input.deltaTime < 250;\n\n\t      if (isTapPointer && isTapMovement && isTapTouchTime) {\n\t        return;\n\t      }\n\t    }\n\n\t    if (hasPanX && hasPanY) {\n\t      // `pan-x pan-y` means browser handles all scrolling/panning, do not prevent\n\t      return;\n\t    }\n\n\t    if (hasNone ||\n\t      (hasPanY && direction & DIRECTION_HORIZONTAL) ||\n\t      (hasPanX && direction & DIRECTION_VERTICAL)) {\n\t      return this.preventSrc(srcEvent);\n\t    }\n\t  },\n\n\t  /**\n\t   * call preventDefault to prevent the browser's default behavior (scrolling in most cases)\n\t   * @param {Object} srcEvent\n\t   */\n\t  preventSrc: function(srcEvent) {\n\t    this.manager.session.prevented = true;\n\t    srcEvent.preventDefault();\n\t  }\n\t};\n\n\t/**\n\t * when the touchActions are collected they are not a valid value, so we need to clean things up. *\n\t * @param {String} actions\n\t * @returns {*}\n\t */\n\tfunction cleanTouchActions(actions) {\n\t  // none\n\t  if (inStr(actions, TOUCH_ACTION_NONE)) {\n\t    return TOUCH_ACTION_NONE;\n\t  }\n\n\t  var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X);\n\t  var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y);\n\n\t  // if both pan-x and pan-y are set (different recognizers\n\t  // for different directions, e.g. horizontal pan but vertical swipe?)\n\t  // we need none (as otherwise with pan-x pan-y combined none of these\n\t  // recognizers will work, since the browser would handle all panning\n\t  if (hasPanX && hasPanY) {\n\t    return TOUCH_ACTION_NONE;\n\t  }\n\n\t  // pan-x OR pan-y\n\t  if (hasPanX || hasPanY) {\n\t    return hasPanX ? TOUCH_ACTION_PAN_X : TOUCH_ACTION_PAN_Y;\n\t  }\n\n\t  // manipulation\n\t  if (inStr(actions, TOUCH_ACTION_MANIPULATION)) {\n\t    return TOUCH_ACTION_MANIPULATION;\n\t  }\n\n\t  return TOUCH_ACTION_AUTO;\n\t}\n\n\t/**\n\t * Recognizer flow explained; *\n\t * All recognizers have the initial state of POSSIBLE when a input session starts.\n\t * The definition of a input session is from the first input until the last input, with all it's movement in it. *\n\t * Example session for mouse-input: mousedown -> mousemove -> mouseup\n\t *\n\t * On each recognizing cycle (see Manager.recognize) the .recognize() method is executed\n\t * which determines with state it should be.\n\t *\n\t * If the recognizer has the state FAILED, CANCELLED or RECOGNIZED (equals ENDED), it is reset to\n\t * POSSIBLE to give it another change on the next cycle.\n\t *\n\t *               Possible\n\t *                  |\n\t *            +-----+---------------+\n\t *            |                     |\n\t *      +-----+-----+               |\n\t *      |           |               |\n\t *   Failed      Cancelled          |\n\t *                          +-------+------+\n\t *                          |              |\n\t *                      Recognized       Began\n\t *                                         |\n\t *                                      Changed\n\t *                                         |\n\t *                                  Ended/Recognized\n\t */\n\tvar STATE_POSSIBLE = 1;\n\tvar STATE_BEGAN = 2;\n\tvar STATE_CHANGED = 4;\n\tvar STATE_ENDED = 8;\n\tvar STATE_RECOGNIZED = STATE_ENDED;\n\tvar STATE_CANCELLED = 16;\n\tvar STATE_FAILED = 32;\n\n\t/**\n\t * Recognizer\n\t * Every recognizer needs to extend from this class.\n\t * @constructor\n\t * @param {Object} options\n\t */\n\tfunction Recognizer(options) {\n\t  this.options = assign({}, this.defaults, options || {});\n\n\t  this.id = uniqueId();\n\n\t  this.manager = null;\n\n\t  // default is enable true\n\t  this.options.enable = ifUndefined(this.options.enable, true);\n\n\t  this.state = STATE_POSSIBLE;\n\n\t  this.simultaneous = {};\n\t  this.requireFail = [];\n\t}\n\n\tRecognizer.prototype = {\n\t  /**\n\t   * @virtual\n\t   * @type {Object}\n\t   */\n\t  defaults: {},\n\n\t  /**\n\t   * set options\n\t   * @param {Object} options\n\t   * @return {Recognizer}\n\t   */\n\t  set: function(options) {\n\t    assign(this.options, options);\n\n\t    // also update the touchAction, in case something changed about the directions/enabled state\n\t    this.manager && this.manager.touchAction.update();\n\t    return this;\n\t  },\n\n\t  /**\n\t   * recognize simultaneous with an other recognizer.\n\t   * @param {Recognizer} otherRecognizer\n\t   * @returns {Recognizer} this\n\t   */\n\t  recognizeWith: function(otherRecognizer) {\n\t    if (invokeArrayArg(otherRecognizer, 'recognizeWith', this)) {\n\t      return this;\n\t    }\n\n\t    var simultaneous = this.simultaneous;\n\t    otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);\n\t    if (!simultaneous[otherRecognizer.id]) {\n\t      simultaneous[otherRecognizer.id] = otherRecognizer;\n\t      otherRecognizer.recognizeWith(this);\n\t    }\n\t    return this;\n\t  },\n\n\t  /**\n\t   * drop the simultaneous link. it doesnt remove the link on the other recognizer.\n\t   * @param {Recognizer} otherRecognizer\n\t   * @returns {Recognizer} this\n\t   */\n\t  dropRecognizeWith: function(otherRecognizer) {\n\t    if (invokeArrayArg(otherRecognizer, 'dropRecognizeWith', this)) {\n\t      return this;\n\t    }\n\n\t    otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);\n\t    delete this.simultaneous[otherRecognizer.id];\n\t    return this;\n\t  },\n\n\t  /**\n\t   * recognizer can only run when an other is failing\n\t   * @param {Recognizer} otherRecognizer\n\t   * @returns {Recognizer} this\n\t   */\n\t  requireFailure: function(otherRecognizer) {\n\t    if (invokeArrayArg(otherRecognizer, 'requireFailure', this)) {\n\t      return this;\n\t    }\n\n\t    var requireFail = this.requireFail;\n\t    otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);\n\t    if (inArray(requireFail, otherRecognizer) === -1) {\n\t      requireFail.push(otherRecognizer);\n\t      otherRecognizer.requireFailure(this);\n\t    }\n\t    return this;\n\t  },\n\n\t  /**\n\t   * drop the requireFailure link. it does not remove the link on the other recognizer.\n\t   * @param {Recognizer} otherRecognizer\n\t   * @returns {Recognizer} this\n\t   */\n\t  dropRequireFailure: function(otherRecognizer) {\n\t    if (invokeArrayArg(otherRecognizer, 'dropRequireFailure', this)) {\n\t      return this;\n\t    }\n\n\t    otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);\n\t    var index = inArray(this.requireFail, otherRecognizer);\n\t    if (index > -1) {\n\t      this.requireFail.splice(index, 1);\n\t    }\n\t    return this;\n\t  },\n\n\t  /**\n\t   * has require failures boolean\n\t   * @returns {boolean}\n\t   */\n\t  hasRequireFailures: function() {\n\t    return this.requireFail.length > 0;\n\t  },\n\n\t  /**\n\t   * if the recognizer can recognize simultaneous with an other recognizer\n\t   * @param {Recognizer} otherRecognizer\n\t   * @returns {Boolean}\n\t   */\n\t  canRecognizeWith: function(otherRecognizer) {\n\t    return !!this.simultaneous[otherRecognizer.id];\n\t  },\n\n\t  /**\n\t   * You should use `tryEmit` instead of `emit` directly to check\n\t   * that all the needed recognizers has failed before emitting.\n\t   * @param {Object} input\n\t   */\n\t  emit: function(input) {\n\t    var self = this;\n\t    var state = this.state;\n\n\t    function emit(event) {\n\t      self.manager.emit(event, input);\n\t    }\n\n\t    // 'panstart' and 'panmove'\n\t    if (state < STATE_ENDED) {\n\t      emit(self.options.event + stateStr(state));\n\t    }\n\n\t    emit(self.options.event); // simple 'eventName' events\n\n\t    if (input.additionalEvent) { // additional event(panleft, panright, pinchin, pinchout...)\n\t      emit(input.additionalEvent);\n\t    }\n\n\t    // panend and pancancel\n\t    if (state >= STATE_ENDED) {\n\t      emit(self.options.event + stateStr(state));\n\t    }\n\t  },\n\n\t  /**\n\t   * Check that all the require failure recognizers has failed,\n\t   * if true, it emits a gesture event,\n\t   * otherwise, setup the state to FAILED.\n\t   * @param {Object} input\n\t   */\n\t  tryEmit: function(input) {\n\t    if (this.canEmit()) {\n\t      return this.emit(input);\n\t    }\n\t    // it's failing anyway\n\t    this.state = STATE_FAILED;\n\t  },\n\n\t  /**\n\t   * can we emit?\n\t   * @returns {boolean}\n\t   */\n\t  canEmit: function() {\n\t    var i = 0;\n\t    while (i < this.requireFail.length) {\n\t      if (!(this.requireFail[i].state & (STATE_FAILED | STATE_POSSIBLE))) {\n\t        return false;\n\t      }\n\t      i++;\n\t    }\n\t    return true;\n\t  },\n\n\t  /**\n\t   * update the recognizer\n\t   * @param {Object} inputData\n\t   */\n\t  recognize: function(inputData) {\n\t    // make a new copy of the inputData\n\t    // so we can change the inputData without messing up the other recognizers\n\t    var inputDataClone = assign({}, inputData);\n\n\t    // is is enabled and allow recognizing?\n\t    if (!boolOrFn(this.options.enable, [this, inputDataClone])) {\n\t      this.reset();\n\t      this.state = STATE_FAILED;\n\t      return;\n\t    }\n\n\t    // reset when we've reached the end\n\t    if (this.state & (STATE_RECOGNIZED | STATE_CANCELLED | STATE_FAILED)) {\n\t      this.state = STATE_POSSIBLE;\n\t    }\n\n\t    this.state = this.process(inputDataClone);\n\n\t    // the recognizer has recognized a gesture\n\t    // so trigger an event\n\t    if (this.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED | STATE_CANCELLED)) {\n\t      this.tryEmit(inputDataClone);\n\t    }\n\t  },\n\n\t  /**\n\t   * return the state of the recognizer\n\t   * the actual recognizing happens in this method\n\t   * @virtual\n\t   * @param {Object} inputData\n\t   * @returns {Const} STATE\n\t   */\n\t  process: function(inputData) { }, // jshint ignore:line\n\n\t  /**\n\t   * return the preferred touch-action\n\t   * @virtual\n\t   * @returns {Array}\n\t   */\n\t  getTouchAction: function() { },\n\n\t  /**\n\t   * called when the gesture isn't allowed to recognize\n\t   * like when another is being recognized or it is disabled\n\t   * @virtual\n\t   */\n\t  reset: function() { }\n\t};\n\n\t/**\n\t * get a usable string, used as event postfix\n\t * @param {Const} state\n\t * @returns {String} state\n\t */\n\tfunction stateStr(state) {\n\t  if (state & STATE_CANCELLED) {\n\t    return 'cancel';\n\t  } else if (state & STATE_ENDED) {\n\t    return 'end';\n\t  } else if (state & STATE_CHANGED) {\n\t    return 'move';\n\t  } else if (state & STATE_BEGAN) {\n\t    return 'start';\n\t  }\n\t  return '';\n\t}\n\n\t/**\n\t * direction cons to string\n\t * @param {Const} direction\n\t * @returns {String}\n\t */\n\tfunction directionStr(direction) {\n\t  if (direction == DIRECTION_DOWN) {\n\t    return 'down';\n\t  } else if (direction == DIRECTION_UP) {\n\t    return 'up';\n\t  } else if (direction == DIRECTION_LEFT) {\n\t    return 'left';\n\t  } else if (direction == DIRECTION_RIGHT) {\n\t    return 'right';\n\t  }\n\t  return '';\n\t}\n\n\t/**\n\t * get a recognizer by name if it is bound to a manager\n\t * @param {Recognizer|String} otherRecognizer\n\t * @param {Recognizer} recognizer\n\t * @returns {Recognizer}\n\t */\n\tfunction getRecognizerByNameIfManager(otherRecognizer, recognizer) {\n\t  var manager = recognizer.manager;\n\t  if (manager) {\n\t    return manager.get(otherRecognizer);\n\t  }\n\t  return otherRecognizer;\n\t}\n\n\t/**\n\t * This recognizer is just used as a base for the simple attribute recognizers.\n\t * @constructor\n\t * @extends Recognizer\n\t */\n\tfunction AttrRecognizer() {\n\t  Recognizer.apply(this, arguments);\n\t}\n\n\tinherit(AttrRecognizer, Recognizer, {\n\t  /**\n\t   * @namespace\n\t   * @memberof AttrRecognizer\n\t   */\n\t  defaults: {\n\t    /**\n\t     * @type {Number}\n\t     * @default 1\n\t     */\n\t    pointers: 1\n\t  },\n\n\t  /**\n\t   * Used to check if it the recognizer receives valid input, like input.distance > 10.\n\t   * @memberof AttrRecognizer\n\t   * @param {Object} input\n\t   * @returns {Boolean} recognized\n\t   */\n\t  attrTest: function(input) {\n\t    var optionPointers = this.options.pointers;\n\t    return optionPointers === 0 || input.pointers.length === optionPointers;\n\t  },\n\n\t  /**\n\t   * Process the input and return the state for the recognizer\n\t   * @memberof AttrRecognizer\n\t   * @param {Object} input\n\t   * @returns {*} State\n\t   */\n\t  process: function(input) {\n\t    var state = this.state;\n\t    var eventType = input.eventType;\n\n\t    var isRecognized = state & (STATE_BEGAN | STATE_CHANGED);\n\t    var isValid = this.attrTest(input);\n\n\t    // on cancel input and we've recognized before, return STATE_CANCELLED\n\t    if (isRecognized && (eventType & INPUT_CANCEL || !isValid)) {\n\t      return state | STATE_CANCELLED;\n\t    } else if (isRecognized || isValid) {\n\t      if (eventType & INPUT_END) {\n\t        return state | STATE_ENDED;\n\t      } else if (!(state & STATE_BEGAN)) {\n\t        return STATE_BEGAN;\n\t      }\n\t      return state | STATE_CHANGED;\n\t    }\n\t    return STATE_FAILED;\n\t  }\n\t});\n\n\t/**\n\t * Pan\n\t * Recognized when the pointer is down and moved in the allowed direction.\n\t * @constructor\n\t * @extends AttrRecognizer\n\t */\n\tfunction PanRecognizer() {\n\t  AttrRecognizer.apply(this, arguments);\n\n\t  this.pX = null;\n\t  this.pY = null;\n\t}\n\n\tinherit(PanRecognizer, AttrRecognizer, {\n\t  /**\n\t   * @namespace\n\t   * @memberof PanRecognizer\n\t   */\n\t  defaults: {\n\t    event: 'pan',\n\t    threshold: 10,\n\t    pointers: 1,\n\t    direction: DIRECTION_ALL\n\t  },\n\n\t  getTouchAction: function() {\n\t    var direction = this.options.direction;\n\t    var actions = [];\n\t    if (direction & DIRECTION_HORIZONTAL) {\n\t      actions.push(TOUCH_ACTION_PAN_Y);\n\t    }\n\t    if (direction & DIRECTION_VERTICAL) {\n\t      actions.push(TOUCH_ACTION_PAN_X);\n\t    }\n\t    return actions;\n\t  },\n\n\t  directionTest: function(input) {\n\t    var options = this.options;\n\t    var hasMoved = true;\n\t    var distance = input.distance;\n\t    var direction = input.direction;\n\t    var x = input.deltaX;\n\t    var y = input.deltaY;\n\n\t    // lock to axis?\n\t    if (!(direction & options.direction)) {\n\t      if (options.direction & DIRECTION_HORIZONTAL) {\n\t        direction = (x === 0) ? DIRECTION_NONE : (x < 0) ? DIRECTION_LEFT : DIRECTION_RIGHT;\n\t        hasMoved = x != this.pX;\n\t        distance = Math.abs(input.deltaX);\n\t      } else {\n\t        direction = (y === 0) ? DIRECTION_NONE : (y < 0) ? DIRECTION_UP : DIRECTION_DOWN;\n\t        hasMoved = y != this.pY;\n\t        distance = Math.abs(input.deltaY);\n\t      }\n\t    }\n\t    input.direction = direction;\n\t    return hasMoved && distance > options.threshold && direction & options.direction;\n\t  },\n\n\t  attrTest: function(input) {\n\t    return AttrRecognizer.prototype.attrTest.call(this, input) &&\n\t      (this.state & STATE_BEGAN || (!(this.state & STATE_BEGAN) && this.directionTest(input)));\n\t  },\n\n\t  emit: function(input) {\n\n\t    this.pX = input.deltaX;\n\t    this.pY = input.deltaY;\n\n\t    var direction = directionStr(input.direction);\n\n\t    if (direction) {\n\t      input.additionalEvent = this.options.event + direction;\n\t    }\n\t    this._super.emit.call(this, input);\n\t  }\n\t});\n\n\t/**\n\t * Pinch\n\t * Recognized when two or more pointers are moving toward (zoom-in) or away from each other (zoom-out).\n\t * @constructor\n\t * @extends AttrRecognizer\n\t */\n\tfunction PinchRecognizer() {\n\t  AttrRecognizer.apply(this, arguments);\n\t}\n\n\tinherit(PinchRecognizer, AttrRecognizer, {\n\t  /**\n\t   * @namespace\n\t   * @memberof PinchRecognizer\n\t   */\n\t  defaults: {\n\t    event: 'pinch',\n\t    threshold: 0,\n\t    pointers: 2\n\t  },\n\n\t  getTouchAction: function() {\n\t    return [TOUCH_ACTION_NONE];\n\t  },\n\n\t  attrTest: function(input) {\n\t    return this._super.attrTest.call(this, input) &&\n\t      (Math.abs(input.scale - 1) > this.options.threshold || this.state & STATE_BEGAN);\n\t  },\n\n\t  emit: function(input) {\n\t    if (input.scale !== 1) {\n\t      var inOut = input.scale < 1 ? 'in' : 'out';\n\t      input.additionalEvent = this.options.event + inOut;\n\t    }\n\t    this._super.emit.call(this, input);\n\t  }\n\t});\n\n\t/**\n\t * Press\n\t * Recognized when the pointer is down for x ms without any movement.\n\t * @constructor\n\t * @extends Recognizer\n\t */\n\tfunction PressRecognizer() {\n\t  Recognizer.apply(this, arguments);\n\n\t  this._timer = null;\n\t  this._input = null;\n\t}\n\n\tinherit(PressRecognizer, Recognizer, {\n\t  /**\n\t   * @namespace\n\t   * @memberof PressRecognizer\n\t   */\n\t  defaults: {\n\t    event: 'press',\n\t    pointers: 1,\n\t    time: 251, // minimal time of the pointer to be pressed\n\t    threshold: 9 // a minimal movement is ok, but keep it low\n\t  },\n\n\t  getTouchAction: function() {\n\t    return [TOUCH_ACTION_AUTO];\n\t  },\n\n\t  process: function(input) {\n\t    var options = this.options;\n\t    var validPointers = input.pointers.length === options.pointers;\n\t    var validMovement = input.distance < options.threshold;\n\t    var validTime = input.deltaTime > options.time;\n\n\t    this._input = input;\n\n\t    // we only allow little movement\n\t    // and we've reached an end event, so a tap is possible\n\t    if (!validMovement || !validPointers || (input.eventType & (INPUT_END | INPUT_CANCEL) && !validTime)) {\n\t      this.reset();\n\t    } else if (input.eventType & INPUT_START) {\n\t      this.reset();\n\t      this._timer = setTimeoutContext(function() {\n\t        this.state = STATE_RECOGNIZED;\n\t        this.tryEmit();\n\t      }, options.time, this);\n\t    } else if (input.eventType & INPUT_END) {\n\t      return STATE_RECOGNIZED;\n\t    }\n\t    return STATE_FAILED;\n\t  },\n\n\t  reset: function() {\n\t    clearTimeout(this._timer);\n\t  },\n\n\t  emit: function(input) {\n\t    if (this.state !== STATE_RECOGNIZED) {\n\t      return;\n\t    }\n\n\t    if (input && (input.eventType & INPUT_END)) {\n\t      this.manager.emit(this.options.event + 'up', input);\n\t    } else {\n\t      this._input.timeStamp = now();\n\t      this.manager.emit(this.options.event, this._input);\n\t    }\n\t  }\n\t});\n\n\t/**\n\t * Rotate\n\t * Recognized when two or more pointer are moving in a circular motion.\n\t * @constructor\n\t * @extends AttrRecognizer\n\t */\n\tfunction RotateRecognizer() {\n\t  AttrRecognizer.apply(this, arguments);\n\t}\n\n\tinherit(RotateRecognizer, AttrRecognizer, {\n\t  /**\n\t   * @namespace\n\t   * @memberof RotateRecognizer\n\t   */\n\t  defaults: {\n\t    event: 'rotate',\n\t    threshold: 0,\n\t    pointers: 2\n\t  },\n\n\t  getTouchAction: function() {\n\t    return [TOUCH_ACTION_NONE];\n\t  },\n\n\t  attrTest: function(input) {\n\t    return this._super.attrTest.call(this, input) &&\n\t      (Math.abs(input.rotation) > this.options.threshold || this.state & STATE_BEGAN);\n\t  }\n\t});\n\n\t/**\n\t * Swipe\n\t * Recognized when the pointer is moving fast (velocity), with enough distance in the allowed direction.\n\t * @constructor\n\t * @extends AttrRecognizer\n\t */\n\tfunction SwipeRecognizer() {\n\t  AttrRecognizer.apply(this, arguments);\n\t}\n\n\tinherit(SwipeRecognizer, AttrRecognizer, {\n\t  /**\n\t   * @namespace\n\t   * @memberof SwipeRecognizer\n\t   */\n\t  defaults: {\n\t    event: 'swipe',\n\t    threshold: 10,\n\t    velocity: 0.3,\n\t    direction: DIRECTION_HORIZONTAL | DIRECTION_VERTICAL,\n\t    pointers: 1\n\t  },\n\n\t  getTouchAction: function() {\n\t    return PanRecognizer.prototype.getTouchAction.call(this);\n\t  },\n\n\t  attrTest: function(input) {\n\t    var direction = this.options.direction;\n\t    var velocity;\n\n\t    if (direction & (DIRECTION_HORIZONTAL | DIRECTION_VERTICAL)) {\n\t      velocity = input.overallVelocity;\n\t    } else if (direction & DIRECTION_HORIZONTAL) {\n\t      velocity = input.overallVelocityX;\n\t    } else if (direction & DIRECTION_VERTICAL) {\n\t      velocity = input.overallVelocityY;\n\t    }\n\n\t    return this._super.attrTest.call(this, input) &&\n\t      direction & input.offsetDirection &&\n\t      input.distance > this.options.threshold &&\n\t      input.maxPointers == this.options.pointers &&\n\t      abs(velocity) > this.options.velocity && input.eventType & INPUT_END;\n\t  },\n\n\t  emit: function(input) {\n\t    var direction = directionStr(input.offsetDirection);\n\t    if (direction) {\n\t      this.manager.emit(this.options.event + direction, input);\n\t    }\n\n\t    this.manager.emit(this.options.event, input);\n\t  }\n\t});\n\n\t/**\n\t * A tap is ecognized when the pointer is doing a small tap/click. Multiple taps are recognized if they occur\n\t * between the given interval and position. The delay option can be used to recognize multi-taps without firing\n\t * a single tap.\n\t *\n\t * The eventData from the emitted event contains the property `tapCount`, which contains the amount of\n\t * multi-taps being recognized.\n\t * @constructor\n\t * @extends Recognizer\n\t */\n\tfunction TapRecognizer() {\n\t  Recognizer.apply(this, arguments);\n\n\t  // previous time and center,\n\t  // used for tap counting\n\t  this.pTime = false;\n\t  this.pCenter = false;\n\n\t  this._timer = null;\n\t  this._input = null;\n\t  this.count = 0;\n\t}\n\n\tinherit(TapRecognizer, Recognizer, {\n\t  /**\n\t   * @namespace\n\t   * @memberof PinchRecognizer\n\t   */\n\t  defaults: {\n\t    event: 'tap',\n\t    pointers: 1,\n\t    taps: 1,\n\t    interval: 300, // max time between the multi-tap taps\n\t    time: 250, // max time of the pointer to be down (like finger on the screen)\n\t    threshold: 9, // a minimal movement is ok, but keep it low\n\t    posThreshold: 10 // a multi-tap can be a bit off the initial position\n\t  },\n\n\t  getTouchAction: function() {\n\t    return [TOUCH_ACTION_MANIPULATION];\n\t  },\n\n\t  process: function(input) {\n\t    var options = this.options;\n\n\t    var validPointers = input.pointers.length === options.pointers;\n\t    var validMovement = input.distance < options.threshold;\n\t    var validTouchTime = input.deltaTime < options.time;\n\n\t    this.reset();\n\n\t    if ((input.eventType & INPUT_START) && (this.count === 0)) {\n\t      return this.failTimeout();\n\t    }\n\n\t    // we only allow little movement\n\t    // and we've reached an end event, so a tap is possible\n\t    if (validMovement && validTouchTime && validPointers) {\n\t      if (input.eventType != INPUT_END) {\n\t        return this.failTimeout();\n\t      }\n\n\t      var validInterval = this.pTime ? (input.timeStamp - this.pTime < options.interval) : true;\n\t      var validMultiTap = !this.pCenter || getDistance(this.pCenter, input.center) < options.posThreshold;\n\n\t      this.pTime = input.timeStamp;\n\t      this.pCenter = input.center;\n\n\t      if (!validMultiTap || !validInterval) {\n\t        this.count = 1;\n\t      } else {\n\t        this.count += 1;\n\t      }\n\n\t      this._input = input;\n\n\t      // if tap count matches we have recognized it,\n\t      // else it has began recognizing...\n\t      var tapCount = this.count % options.taps;\n\t      if (tapCount === 0) {\n\t        // no failing requirements, immediately trigger the tap event\n\t        // or wait as long as the multitap interval to trigger\n\t        if (!this.hasRequireFailures()) {\n\t          return STATE_RECOGNIZED;\n\t        } else {\n\t          this._timer = setTimeoutContext(function() {\n\t            this.state = STATE_RECOGNIZED;\n\t            this.tryEmit();\n\t          }, options.interval, this);\n\t          return STATE_BEGAN;\n\t        }\n\t      }\n\t    }\n\t    return STATE_FAILED;\n\t  },\n\n\t  failTimeout: function() {\n\t    this._timer = setTimeoutContext(function() {\n\t      this.state = STATE_FAILED;\n\t    }, this.options.interval, this);\n\t    return STATE_FAILED;\n\t  },\n\n\t  reset: function() {\n\t    clearTimeout(this._timer);\n\t  },\n\n\t  emit: function() {\n\t    if (this.state == STATE_RECOGNIZED) {\n\t      this._input.tapCount = this.count;\n\t      this.manager.emit(this.options.event, this._input);\n\t    }\n\t  }\n\t});\n\n\t/**\n\t * Simple way to create a manager with a default set of recognizers.\n\t * @param {HTMLElement} element\n\t * @param {Object} [options]\n\t * @constructor\n\t */\n\tfunction Hammer(element, options) {\n\t  options = options || {};\n\t  options.recognizers = ifUndefined(options.recognizers, Hammer.defaults.preset);\n\t  return new Manager(element, options);\n\t}\n\n\t/**\n\t * @const {string}\n\t */\n\tHammer.VERSION = '2.0.6';\n\n\t/**\n\t * default settings\n\t * @namespace\n\t */\n\tHammer.defaults = {\n\t  /**\n\t   * set if DOM events are being triggered.\n\t   * But this is slower and unused by simple implementations, so disabled by default.\n\t   * @type {Boolean}\n\t   * @default false\n\t   */\n\t  domEvents: false,\n\n\t  /**\n\t   * The value for the touchAction property/fallback.\n\t   * When set to `compute` it will magically set the correct value based on the added recognizers.\n\t   * @type {String}\n\t   * @default compute\n\t   */\n\t  touchAction: TOUCH_ACTION_COMPUTE,\n\n\t  /**\n\t   * @type {Boolean}\n\t   * @default true\n\t   */\n\t  enable: true,\n\n\t  /**\n\t   * EXPERIMENTAL FEATURE -- can be removed/changed\n\t   * Change the parent input target element.\n\t   * If Null, then it is being set the to main element.\n\t   * @type {Null|EventTarget}\n\t   * @default null\n\t   */\n\t  inputTarget: null,\n\n\t  /**\n\t   * force an input class\n\t   * @type {Null|Function}\n\t   * @default null\n\t   */\n\t  inputClass: null,\n\n\t  /**\n\t   * Default recognizer setup when calling `Hammer()`\n\t   * When creating a new Manager these will be skipped.\n\t   * @type {Array}\n\t   */\n\t  preset: [\n\t    // RecognizerClass, options, [recognizeWith, ...], [requireFailure, ...]\n\t    [RotateRecognizer, {enable: false}],\n\t    [PinchRecognizer, {enable: false}, ['rotate']],\n\t    [SwipeRecognizer, {direction: DIRECTION_HORIZONTAL}],\n\t    [PanRecognizer, {direction: DIRECTION_HORIZONTAL}, ['swipe']],\n\t    [TapRecognizer],\n\t    [TapRecognizer, {event: 'doubletap', taps: 2}, ['tap']],\n\t    [PressRecognizer]\n\t  ],\n\n\t  /**\n\t   * Some CSS properties can be used to improve the working of Hammer.\n\t   * Add them to this method and they will be set when creating a new Manager.\n\t   * @namespace\n\t   */\n\t  cssProps: {\n\t    /**\n\t     * Disables text selection to improve the dragging gesture. Mainly for desktop browsers.\n\t     * @type {String}\n\t     * @default 'none'\n\t     */\n\t    userSelect: 'none',\n\n\t    /**\n\t     * Disable the Windows Phone grippers when pressing an element.\n\t     * @type {String}\n\t     * @default 'none'\n\t     */\n\t    touchSelect: 'none',\n\n\t    /**\n\t     * Disables the default callout shown when you touch and hold a touch target.\n\t     * On iOS, when you touch and hold a touch target such as a link, Safari displays\n\t     * a callout containing information about the link. This property allows you to disable that callout.\n\t     * @type {String}\n\t     * @default 'none'\n\t     */\n\t    touchCallout: 'none',\n\n\t    /**\n\t     * Specifies whether zooming is enabled. Used by IE10>\n\t     * @type {String}\n\t     * @default 'none'\n\t     */\n\t    contentZooming: 'none',\n\n\t    /**\n\t     * Specifies that an entire element should be draggable instead of its contents. Mainly for desktop browsers.\n\t     * @type {String}\n\t     * @default 'none'\n\t     */\n\t    userDrag: 'none',\n\n\t    /**\n\t     * Overrides the highlight color shown when the user taps a link or a JavaScript\n\t     * clickable element in iOS. This property obeys the alpha value, if specified.\n\t     * @type {String}\n\t     * @default 'rgba(0,0,0,0)'\n\t     */\n\t    tapHighlightColor: 'rgba(0,0,0,0)'\n\t  }\n\t};\n\n\tvar STOP = 1;\n\tvar FORCED_STOP = 2;\n\n\t/**\n\t * Manager\n\t * @param {HTMLElement} element\n\t * @param {Object} [options]\n\t * @constructor\n\t */\n\tfunction Manager(element, options) {\n\t  this.options = assign({}, Hammer.defaults, options || {});\n\n\t  this.options.inputTarget = this.options.inputTarget || element;\n\n\t  this.handlers = {};\n\t  this.session = {};\n\t  this.recognizers = [];\n\n\t  this.element = element;\n\t  this.input = createInputInstance(this);\n\t  this.touchAction = new TouchAction(this, this.options.touchAction);\n\n\t  toggleCssProps(this, true);\n\n\t  each(this.options.recognizers, function(item) {\n\t    var recognizer = this.add(new (item[0])(item[1]));\n\t    item[2] && recognizer.recognizeWith(item[2]);\n\t    item[3] && recognizer.requireFailure(item[3]);\n\t  }, this);\n\t}\n\n\tManager.prototype = {\n\t  /**\n\t   * set options\n\t   * @param {Object} options\n\t   * @returns {Manager}\n\t   */\n\t  set: function(options) {\n\t    assign(this.options, options);\n\n\t    // Options that need a little more setup\n\t    if (options.touchAction) {\n\t      this.touchAction.update();\n\t    }\n\t    if (options.inputTarget) {\n\t      // Clean up existing event listeners and reinitialize\n\t      this.input.destroy();\n\t      this.input.target = options.inputTarget;\n\t      this.input.init();\n\t    }\n\t    return this;\n\t  },\n\n\t  /**\n\t   * stop recognizing for this session.\n\t   * This session will be discarded, when a new [input]start event is fired.\n\t   * When forced, the recognizer cycle is stopped immediately.\n\t   * @param {Boolean} [force]\n\t   */\n\t  stop: function(force) {\n\t    this.session.stopped = force ? FORCED_STOP : STOP;\n\t  },\n\n\t  /**\n\t   * run the recognizers!\n\t   * called by the inputHandler function on every movement of the pointers (touches)\n\t   * it walks through all the recognizers and tries to detect the gesture that is being made\n\t   * @param {Object} inputData\n\t   */\n\t  recognize: function(inputData) {\n\t    var session = this.session;\n\t    if (session.stopped) {\n\t      return;\n\t    }\n\n\t    // run the touch-action polyfill\n\t    this.touchAction.preventDefaults(inputData);\n\n\t    var recognizer;\n\t    var recognizers = this.recognizers;\n\n\t    // this holds the recognizer that is being recognized.\n\t    // so the recognizer's state needs to be BEGAN, CHANGED, ENDED or RECOGNIZED\n\t    // if no recognizer is detecting a thing, it is set to `null`\n\t    var curRecognizer = session.curRecognizer;\n\n\t    // reset when the last recognizer is recognized\n\t    // or when we're in a new session\n\t    if (!curRecognizer || (curRecognizer && curRecognizer.state & STATE_RECOGNIZED)) {\n\t      curRecognizer = session.curRecognizer = null;\n\t    }\n\n\t    var i = 0;\n\t    while (i < recognizers.length) {\n\t      recognizer = recognizers[i];\n\n\t      // find out if we are allowed try to recognize the input for this one.\n\t      // 1.   allow if the session is NOT forced stopped (see the .stop() method)\n\t      // 2.   allow if we still haven't recognized a gesture in this session, or the this recognizer is the one\n\t      //      that is being recognized.\n\t      // 3.   allow if the recognizer is allowed to run simultaneous with the current recognized recognizer.\n\t      //      this can be setup with the `recognizeWith()` method on the recognizer.\n\t      if (session.stopped !== FORCED_STOP && ( // 1\n\t        !curRecognizer || recognizer == curRecognizer || // 2\n\t        recognizer.canRecognizeWith(curRecognizer))) { // 3\n\t        recognizer.recognize(inputData);\n\t      } else {\n\t        recognizer.reset();\n\t      }\n\n\t      // if the recognizer has been recognizing the input as a valid gesture, we want to store this one as the\n\t      // current active recognizer. but only if we don't already have an active recognizer\n\t      if (!curRecognizer && recognizer.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED)) {\n\t        curRecognizer = session.curRecognizer = recognizer;\n\t      }\n\t      i++;\n\t    }\n\t  },\n\n\t  /**\n\t   * get a recognizer by its event name.\n\t   * @param {Recognizer|String} recognizer\n\t   * @returns {Recognizer|Null}\n\t   */\n\t  get: function(recognizer) {\n\t    if (recognizer instanceof Recognizer) {\n\t      return recognizer;\n\t    }\n\n\t    var recognizers = this.recognizers;\n\t    for (var i = 0; i < recognizers.length; i++) {\n\t      if (recognizers[i].options.event == recognizer) {\n\t        return recognizers[i];\n\t      }\n\t    }\n\t    return null;\n\t  },\n\n\t  /**\n\t   * add a recognizer to the manager\n\t   * existing recognizers with the same event name will be removed\n\t   * @param {Recognizer} recognizer\n\t   * @returns {Recognizer|Manager}\n\t   */\n\t  add: function(recognizer) {\n\t    if (invokeArrayArg(recognizer, 'add', this)) {\n\t      return this;\n\t    }\n\n\t    // remove existing\n\t    var existing = this.get(recognizer.options.event);\n\t    if (existing) {\n\t      this.remove(existing);\n\t    }\n\n\t    this.recognizers.push(recognizer);\n\t    recognizer.manager = this;\n\n\t    this.touchAction.update();\n\t    return recognizer;\n\t  },\n\n\t  /**\n\t   * remove a recognizer by name or instance\n\t   * @param {Recognizer|String} recognizer\n\t   * @returns {Manager}\n\t   */\n\t  remove: function(recognizer) {\n\t    if (invokeArrayArg(recognizer, 'remove', this)) {\n\t      return this;\n\t    }\n\n\t    recognizer = this.get(recognizer);\n\n\t    // let's make sure this recognizer exists\n\t    if (recognizer) {\n\t      var recognizers = this.recognizers;\n\t      var index = inArray(recognizers, recognizer);\n\n\t      if (index !== -1) {\n\t        recognizers.splice(index, 1);\n\t        this.touchAction.update();\n\t      }\n\t    }\n\n\t    return this;\n\t  },\n\n\t  /**\n\t   * bind event\n\t   * @param {String} events\n\t   * @param {Function} handler\n\t   * @returns {EventEmitter} this\n\t   */\n\t  on: function(events, handler) {\n\t    var handlers = this.handlers;\n\t    each(splitStr(events), function(event) {\n\t      handlers[event] = handlers[event] || [];\n\t      handlers[event].push(handler);\n\t    });\n\t    return this;\n\t  },\n\n\t  /**\n\t   * unbind event, leave emit blank to remove all handlers\n\t   * @param {String} events\n\t   * @param {Function} [handler]\n\t   * @returns {EventEmitter} this\n\t   */\n\t  off: function(events, handler) {\n\t    var handlers = this.handlers;\n\t    each(splitStr(events), function(event) {\n\t      if (!handler) {\n\t        delete handlers[event];\n\t      } else {\n\t        handlers[event] && handlers[event].splice(inArray(handlers[event], handler), 1);\n\t      }\n\t    });\n\t    return this;\n\t  },\n\n\t  /**\n\t   * emit event to the listeners\n\t   * @param {String} event\n\t   * @param {Object} data\n\t   */\n\t  emit: function(event, data) {\n\t    // we also want to trigger dom events\n\t    if (this.options.domEvents) {\n\t      triggerDomEvent(event, data);\n\t    }\n\n\t    // no handlers, so skip it all\n\t    var handlers = this.handlers[event] && this.handlers[event].slice();\n\t    if (!handlers || !handlers.length) {\n\t      return;\n\t    }\n\n\t    data.type = event;\n\t    data.preventDefault = function() {\n\t      data.srcEvent.preventDefault();\n\t    };\n\n\t    var i = 0;\n\t    while (i < handlers.length) {\n\t      handlers[i](data);\n\t      i++;\n\t    }\n\t  },\n\n\t  /**\n\t   * destroy the manager and unbinds all events\n\t   * it doesn't unbind dom events, that is the user own responsibility\n\t   */\n\t  destroy: function() {\n\t    this.element && toggleCssProps(this, false);\n\n\t    this.handlers = {};\n\t    this.session = {};\n\t    this.input.destroy();\n\t    this.element = null;\n\t  }\n\t};\n\n\t/**\n\t * add/remove the css properties as defined in manager.options.cssProps\n\t * @param {Manager} manager\n\t * @param {Boolean} add\n\t */\n\tfunction toggleCssProps(manager, add) {\n\t  var element = manager.element;\n\t  if (!element.style) {\n\t    return;\n\t  }\n\t  each(manager.options.cssProps, function(value, name) {\n\t    element.style[prefixed(element.style, name)] = add ? value : '';\n\t  });\n\t}\n\n\t/**\n\t * trigger dom event\n\t * @param {String} event\n\t * @param {Object} data\n\t */\n\tfunction triggerDomEvent(event, data) {\n\t  var gestureEvent = document.createEvent('Event');\n\t  gestureEvent.initEvent(event, true, true);\n\t  gestureEvent.gesture = data;\n\t  data.target.dispatchEvent(gestureEvent);\n\t}\n\n\tassign(Hammer, {\n\t  INPUT_START: INPUT_START,\n\t  INPUT_MOVE: INPUT_MOVE,\n\t  INPUT_END: INPUT_END,\n\t  INPUT_CANCEL: INPUT_CANCEL,\n\n\t  STATE_POSSIBLE: STATE_POSSIBLE,\n\t  STATE_BEGAN: STATE_BEGAN,\n\t  STATE_CHANGED: STATE_CHANGED,\n\t  STATE_ENDED: STATE_ENDED,\n\t  STATE_RECOGNIZED: STATE_RECOGNIZED,\n\t  STATE_CANCELLED: STATE_CANCELLED,\n\t  STATE_FAILED: STATE_FAILED,\n\n\t  DIRECTION_NONE: DIRECTION_NONE,\n\t  DIRECTION_LEFT: DIRECTION_LEFT,\n\t  DIRECTION_RIGHT: DIRECTION_RIGHT,\n\t  DIRECTION_UP: DIRECTION_UP,\n\t  DIRECTION_DOWN: DIRECTION_DOWN,\n\t  DIRECTION_HORIZONTAL: DIRECTION_HORIZONTAL,\n\t  DIRECTION_VERTICAL: DIRECTION_VERTICAL,\n\t  DIRECTION_ALL: DIRECTION_ALL,\n\n\t  Manager: Manager,\n\t  Input: Input,\n\t  TouchAction: TouchAction,\n\n\t  TouchInput: TouchInput,\n\t  MouseInput: MouseInput,\n\t  PointerEventInput: PointerEventInput,\n\t  TouchMouseInput: TouchMouseInput,\n\t  SingleTouchInput: SingleTouchInput,\n\n\t  Recognizer: Recognizer,\n\t  AttrRecognizer: AttrRecognizer,\n\t  Tap: TapRecognizer,\n\t  Pan: PanRecognizer,\n\t  Swipe: SwipeRecognizer,\n\t  Pinch: PinchRecognizer,\n\t  Rotate: RotateRecognizer,\n\t  Press: PressRecognizer,\n\n\t  on: addEventListeners,\n\t  off: removeEventListeners,\n\t  each: each,\n\t  merge: merge,\n\t  extend: extend,\n\t  assign: assign,\n\t  inherit: inherit,\n\t  bindFn: bindFn,\n\t  prefixed: prefixed\n\t});\n\n\t// jquery.hammer.js\n\t// This jQuery plugin is just a small wrapper around the Hammer() class.\n\t// It also extends the Manager.emit method by triggering jQuery events.\n\t// $(element).hammer(options).bind(\"pan\", myPanHandler);\n\t// The Hammer instance is stored at $element.data(\"hammer\").\n\t// https://github.com/hammerjs/jquery.hammer.js\n\n\t(function($, Hammer) {\n\t  function hammerify(el, options) {\n\t    var $el = $(el);\n\t    if (!$el.data('hammer')) {\n\t      $el.data('hammer', new Hammer($el[0], options));\n\t    }\n\t  }\n\n\t  $.fn.hammer = function(options) {\n\t    return this.each(function() {\n\t      hammerify(this, options);\n\t    });\n\t  };\n\n\t  // extend the emit method to also trigger jQuery events\n\t  Hammer.Manager.prototype.emit = (function(originalEmit) {\n\t    return function(type, data) {\n\t      originalEmit.call(this, type, data);\n\t      $(this.element).trigger({\n\t        type: type,\n\t        gesture: data\n\t      });\n\t    };\n\t  })(Hammer.Manager.prototype.emit);\n\t})($, Hammer);\n\n\tmodule.exports = UI.Hammer = Hammer;\n\n\n/***/ },\n/* 4 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar UI = __webpack_require__(2);\n\n\t/* jshint -W101, -W106 */\n\t/**\n\t * Add to Homescreen v3.2.2\n\t * (c) 2015 Matteo Spinelli\n\t * @license: http://cubiq.org/license\n\t */\n\n\t// Check for addEventListener browser support (prevent errors in IE<9)\n\tvar _eventListener = 'addEventListener' in window;\n\n\t// Check if document is loaded, needed by autostart\n\tvar _DOMReady = false;\n\tif (document.readyState === 'complete') {\n\t  _DOMReady = true;\n\t} else if (_eventListener) {\n\t  window.addEventListener('load', loaded, false);\n\t}\n\n\tfunction loaded() {\n\t  window.removeEventListener('load', loaded, false);\n\t  _DOMReady = true;\n\t}\n\n\t// regex used to detect if app has been added to the homescreen\n\tvar _reSmartURL = /\\/ath(\\/)?$/;\n\tvar _reQueryString = /([\\?&]ath=[^&]*$|&ath=[^&]*(&))/;\n\n\t// singleton\n\tvar _instance;\n\tfunction ath(options) {\n\t  _instance = _instance || new ath.Class(options);\n\n\t  return _instance;\n\t}\n\n\t// message in all supported languages\n\tath.intl = {\n\t  en_us: {\n\t    ios: 'To add this web app to the home screen: tap %icon and then <strong>Add to Home Screen</strong>.',\n\t    android: 'To add this web app to the home screen open the browser option menu and tap on <strong>Add to homescreen</strong>. <small>The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon <span class=\"ath-action-icon\">icon</span>.</small>'\n\t  },\n\n\t  zh_cn: {\n\t    ios: '如要把应用程式加至主屏幕,请点击%icon, 然后<strong>加至主屏幕</strong>',\n\t    android: 'To add this web app to the home screen open the browser option menu and tap on <strong>Add to homescreen</strong>. <small>The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon <span class=\"ath-action-icon\">icon</span>.</small>'\n\t  },\n\n\t  zh_tw: {\n\t    ios: '如要把應用程式加至主屏幕, 請點擊%icon, 然後<strong>加至主屏幕</strong>.',\n\t    android: 'To add this web app to the home screen open the browser option menu and tap on <strong>Add to homescreen</strong>. <small>The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon <span class=\"ath-action-icon\">icon</span>.</small>'\n\t  }\n\t};\n\n\t// Add 2 characters language support (Android mostly)\n\tfor (var lang in ath.intl) {\n\t  ath.intl[lang.substr(0, 2)] = ath.intl[lang];\n\t}\n\n\t// default options\n\tath.defaults = {\n\t  appID: 'org.cubiq.addtohome',\t\t// local storage name (no need to change)\n\t  fontSize: 15,\t\t\t\t// base font size, used to properly resize the popup based on viewport scale factor\n\t  debug: false,\t\t\t\t// override browser checks\n\t  logging: false,\t\t\t\t// log reasons for showing or not showing to js console; defaults to true when debug is true\n\t  modal: false,\t\t\t\t// prevent further actions until the message is closed\n\t  mandatory: false,\t\t\t// you can't proceed if you don't add the app to the homescreen\n\t  autostart: true,\t\t\t// show the message automatically\n\t  skipFirstVisit: false,\t\t// show only to returning visitors (ie: skip the first time you visit)\n\t  startDelay: 1,\t\t\t\t// display the message after that many seconds from page load\n\t  lifespan: 15,\t\t\t\t// life of the message in seconds\n\t  displayPace: 1440,\t\t\t// minutes before the message is shown again (0: display every time, default 24 hours)\n\t  maxDisplayCount: 0,\t\t\t// absolute maximum number of times the message will be shown to the user (0: no limit)\n\t  icon: true,\t\t\t\t\t// add touch icon to the message\n\t  message: '',\t\t\t\t// the message can be customized\n\t  validLocation: [],\t\t\t// list of pages where the message will be shown (array of regexes)\n\t  onInit: null,\t\t\t\t// executed on instance creation\n\t  onShow: null,\t\t\t\t// executed when the message is shown\n\t  onRemove: null,\t\t\t\t// executed when the message is removed\n\t  onAdd: null,\t\t\t\t// when the application is launched the first time from the homescreen (guesstimate)\n\t  onPrivate: null,\t\t\t// executed if user is in private mode\n\t  privateModeOverride: false,\t// show the message even in private mode (very rude)\n\t  detectHomescreen: false\t\t// try to detect if the site has been added to the homescreen (false | true | 'hash' | 'queryString' | 'smartURL')\n\t};\n\n\t// browser info and capability\n\tvar _ua = window.navigator.userAgent;\n\n\tvar _nav = window.navigator;\n\t_extend(ath, {\n\t  hasToken: document.location.hash == '#ath' || _reSmartURL.test(document.location.href) || _reQueryString.test(document.location.search),\n\t  isRetina: window.devicePixelRatio && window.devicePixelRatio > 1,\n\t  isIDevice: (/iphone|ipod|ipad/i).test(_ua),\n\t  isMobileChrome: _ua.indexOf('Android') > -1 && (/Chrome\\/[.0-9]*/).test(_ua) && _ua.indexOf(\"Version\") == -1,\n\t  isMobileIE: _ua.indexOf('Windows Phone') > -1,\n\t  language: _nav.language && _nav.language.toLowerCase().replace('-', '_') || ''\n\t});\n\n\t// falls back to en_us if language is unsupported\n\tath.language = ath.language && ath.language in ath.intl ? ath.language : 'en_us';\n\n\tath.isMobileSafari = ath.isIDevice && _ua.indexOf('Safari') > -1 && _ua.indexOf('CriOS') < 0;\n\tath.OS = ath.isIDevice ? 'ios' : ath.isMobileChrome ? 'android' : ath.isMobileIE ? 'windows' : 'unsupported';\n\n\tath.OSVersion = _ua.match(/(OS|Android) (\\d+[_\\.]\\d+)/);\n\tath.OSVersion = ath.OSVersion && ath.OSVersion[2] ? +ath.OSVersion[2].replace('_', '.') : 0;\n\n\tath.isStandalone = 'standalone' in window.navigator && window.navigator.standalone;\n\tath.isTablet = (ath.isMobileSafari && _ua.indexOf('iPad') > -1) || (ath.isMobileChrome && _ua.indexOf('Mobile') < 0);\n\n\tath.isCompatible = (ath.isMobileSafari && ath.OSVersion >= 6) || ath.isMobileChrome;\t// TODO: add winphone\n\n\tvar _defaultSession = {\n\t  lastDisplayTime: 0,\t\t\t// last time we displayed the message\n\t  returningVisitor: false,\t// is this the first time you visit\n\t  displayCount: 0,\t\t\t// number of times the message has been shown\n\t  optedout: false,\t\t\t// has the user opted out\n\t  added: false\t\t\t\t// has been actually added to the homescreen\n\t};\n\n\tath.removeSession = function(appID) {\n\t  try {\n\t    if (!localStorage) {\n\t      throw new Error('localStorage is not defined');\n\t    }\n\n\t    localStorage.removeItem(appID || ath.defaults.appID);\n\t  } catch (e) {\n\t    // we are most likely in private mode\n\t  }\n\t};\n\n\tath.doLog = function(logStr) {\n\t  if (this.options.logging) {\n\t    console.log(logStr);\n\t  }\n\t};\n\n\tath.Class = function(options) {\n\t  // class methods\n\t  this.doLog = ath.doLog;\n\n\t  // merge default options with user config\n\t  this.options = _extend({}, ath.defaults);\n\t  _extend(this.options, options);\n\t  // override defaults that are dependent on each other\n\t  if (this.options.debug) {\n\t    this.options.logging = true;\n\t  }\n\n\t  // IE<9 so exit (I hate you, really)\n\t  if (!_eventListener) {\n\t    return;\n\t  }\n\n\t  // normalize some options\n\t  this.options.mandatory = this.options.mandatory && ( 'standalone' in window.navigator || this.options.debug );\n\t  this.options.modal = this.options.modal || this.options.mandatory;\n\t  if (this.options.mandatory) {\n\t    this.options.startDelay = -0.5;\t\t// make the popup hasty\n\t  }\n\t  this.options.detectHomescreen = this.options.detectHomescreen === true ? 'hash' : this.options.detectHomescreen;\n\n\t  // setup the debug environment\n\t  if (this.options.debug) {\n\t    ath.isCompatible = true;\n\t    ath.OS = typeof this.options.debug == 'string' ? this.options.debug : ath.OS == 'unsupported' ? 'android' : ath.OS;\n\t    ath.OSVersion = ath.OS == 'ios' ? '8' : '4';\n\t  }\n\n\t  // the element the message will be appended to\n\t  this.container = document.documentElement;\n\n\t  // load session\n\t  this.session = this.getItem(this.options.appID);\n\t  this.session = this.session ? JSON.parse(this.session) : undefined;\n\n\t  // user most likely came from a direct link containing our token, we don't need it and we remove it\n\t  if (ath.hasToken && ( !ath.isCompatible || !this.session )) {\n\t    ath.hasToken = false;\n\t    _removeToken();\n\t  }\n\n\t  // the device is not supported\n\t  if (!ath.isCompatible) {\n\t    this.doLog(\"Add to homescreen: not displaying callout because device not supported\");\n\t    return;\n\t  }\n\n\t  this.session = this.session || _defaultSession;\n\n\t  // check if we can use the local storage\n\t  try {\n\t    if (!localStorage) {\n\t      throw new Error('localStorage is not defined');\n\t    }\n\n\t    localStorage.setItem(this.options.appID, JSON.stringify(this.session));\n\t    ath.hasLocalStorage = true;\n\t  } catch (e) {\n\t    // we are most likely in private mode\n\t    ath.hasLocalStorage = false;\n\n\t    if (this.options.onPrivate) {\n\t      this.options.onPrivate.call(this);\n\t    }\n\t  }\n\n\t  // check if this is a valid location\n\t  var isValidLocation = !this.options.validLocation.length;\n\t  for (var i = this.options.validLocation.length; i--;) {\n\t    if (this.options.validLocation[i].test(document.location.href)) {\n\t      isValidLocation = true;\n\t      break;\n\t    }\n\t  }\n\n\t  // check compatibility with old versions of add to homescreen. Opt-out if an old session is found\n\t  if (this.getItem('addToHome')) {\n\t    this.optOut();\n\t  }\n\n\t  // critical errors:\n\t  if (this.session.optedout) {\n\t    this.doLog(\"Add to homescreen: not displaying callout because user opted out\");\n\t    return;\n\t  }\n\t  if (this.session.added) {\n\t    this.doLog(\"Add to homescreen: not displaying callout because already added to the homescreen\");\n\t    return;\n\t  }\n\t  if (!isValidLocation) {\n\t    this.doLog(\"Add to homescreen: not displaying callout because not a valid location\");\n\t    return;\n\t  }\n\n\t  // check if the app is in stand alone mode\n\t  if (ath.isStandalone) {\n\t    // execute the onAdd event if we haven't already\n\t    if (!this.session.added) {\n\t      this.session.added = true;\n\t      this.updateSession();\n\n\t      if (this.options.onAdd && ath.hasLocalStorage) {\t// double check on localstorage to avoid multiple calls to the custom event\n\t        this.options.onAdd.call(this);\n\t      }\n\t    }\n\n\t    this.doLog(\"Add to homescreen: not displaying callout because in standalone mode\");\n\t    return;\n\t  }\n\n\t  // (try to) check if the page has been added to the homescreen\n\t  if (this.options.detectHomescreen) {\n\t    // the URL has the token, we are likely coming from the homescreen\n\t    if (ath.hasToken) {\n\t      _removeToken();\t\t// we don't actually need the token anymore, we remove it to prevent redistribution\n\n\t      // this is called the first time the user opens the app from the homescreen\n\t      if (!this.session.added) {\n\t        this.session.added = true;\n\t        this.updateSession();\n\n\t        if (this.options.onAdd && ath.hasLocalStorage) {\t// double check on localstorage to avoid multiple calls to the custom event\n\t          this.options.onAdd.call(this);\n\t        }\n\t      }\n\n\t      this.doLog(\"Add to homescreen: not displaying callout because URL has token, so we are likely coming from homescreen\");\n\t      return;\n\t    }\n\n\t    // URL doesn't have the token, so add it\n\t    if (this.options.detectHomescreen == 'hash') {\n\t      history.replaceState('', window.document.title, document.location.href + '#ath');\n\t    } else if (this.options.detectHomescreen == 'smartURL') {\n\t      history.replaceState('', window.document.title, document.location.href.replace(/(\\/)?$/, '/ath$1'));\n\t    } else {\n\t      history.replaceState('', window.document.title, document.location.href + (document.location.search ? '&' : '?' ) + 'ath=');\n\t    }\n\t  }\n\n\t  // check if this is a returning visitor\n\t  if (!this.session.returningVisitor) {\n\t    this.session.returningVisitor = true;\n\t    this.updateSession();\n\n\t    // we do not show the message if this is your first visit\n\t    if (this.options.skipFirstVisit) {\n\t      this.doLog(\"Add to homescreen: not displaying callout because skipping first visit\");\n\t      return;\n\t    }\n\t  }\n\n\t  // we do no show the message in private mode\n\t  if (!this.options.privateModeOverride && !ath.hasLocalStorage) {\n\t    this.doLog(\"Add to homescreen: not displaying callout because browser is in private mode\");\n\t    return;\n\t  }\n\n\t  // all checks passed, ready to display\n\t  this.ready = true;\n\n\t  if (this.options.onInit) {\n\t    this.options.onInit.call(this);\n\t  }\n\n\t  if (this.options.autostart) {\n\t    this.doLog(\"Add to homescreen: autostart displaying callout\");\n\t    this.show();\n\t  }\n\t};\n\n\tath.Class.prototype = {\n\t  // event type to method conversion\n\t  events: {\n\t    load: '_delayedShow',\n\t    error: '_delayedShow',\n\t    orientationchange: 'resize',\n\t    resize: 'resize',\n\t    scroll: 'resize',\n\t    click: 'remove',\n\t    touchmove: '_preventDefault',\n\t    transitionend: '_removeElements',\n\t    webkitTransitionEnd: '_removeElements',\n\t    MSTransitionEnd: '_removeElements'\n\t  },\n\n\t  handleEvent: function(e) {\n\t    var type = this.events[e.type];\n\t    if (type) {\n\t      this[type](e);\n\t    }\n\t  },\n\n\t  show: function(force) {\n\t    // in autostart mode wait for the document to be ready\n\t    if (this.options.autostart && !_DOMReady) {\n\t      setTimeout(this.show.bind(this), 50);\n\t      // we are not displaying callout because DOM not ready, but don't log that because\n\t      // it would log too frequently\n\t      return;\n\t    }\n\n\t    // message already on screen\n\t    if (this.shown) {\n\t      this.doLog(\"Add to homescreen: not displaying callout because already shown on screen\");\n\t      return;\n\t    }\n\n\t    var now = Date.now();\n\t    var lastDisplayTime = this.session.lastDisplayTime;\n\n\t    if (force !== true) {\n\t      // this is needed if autostart is disabled and you programmatically call the show() method\n\t      if (!this.ready) {\n\t        this.doLog(\"Add to homescreen: not displaying callout because not ready\");\n\t        return;\n\t      }\n\n\t      // we obey the display pace (prevent the message to popup too often)\n\t      if (now - lastDisplayTime < this.options.displayPace * 60000) {\n\t        this.doLog(\"Add to homescreen: not displaying callout because displayed recently\");\n\t        return;\n\t      }\n\n\t      // obey the maximum number of display count\n\t      if (this.options.maxDisplayCount && this.session.displayCount >= this.options.maxDisplayCount) {\n\t        this.doLog(\"Add to homescreen: not displaying callout because displayed too many times already\");\n\t        return;\n\t      }\n\t    }\n\n\t    this.shown = true;\n\n\t    // increment the display count\n\t    this.session.lastDisplayTime = now;\n\t    this.session.displayCount++;\n\t    this.updateSession();\n\n\t    // try to get the highest resolution application icon\n\t    if (!this.applicationIcon) {\n\t      if (ath.OS == 'ios') {\n\t        this.applicationIcon = document.querySelector('head link[rel^=apple-touch-icon][sizes=\"152x152\"],head link[rel^=apple-touch-icon][sizes=\"144x144\"],head link[rel^=apple-touch-icon][sizes=\"120x120\"],head link[rel^=apple-touch-icon][sizes=\"114x114\"],head link[rel^=apple-touch-icon]');\n\t      } else {\n\t        this.applicationIcon = document.querySelector('head link[rel^=\"shortcut icon\"][sizes=\"196x196\"],head link[rel^=apple-touch-icon]');\n\t      }\n\t    }\n\n\t    var message = '';\n\n\t    if (typeof this.options.message == 'object' && ath.language in this.options.message) {\t\t// use custom language message\n\t      message = this.options.message[ath.language][ath.OS];\n\t    } else if (typeof this.options.message == 'object' && ath.OS in this.options.message) {\t\t// use custom os message\n\t      message = this.options.message[ath.OS];\n\t    } else if (this.options.message in ath.intl) {\t\t\t\t// you can force the locale\n\t      message = ath.intl[this.options.message][ath.OS];\n\t    } else if (this.options.message !== '') {\t\t\t\t\t\t// use a custom message\n\t      message = this.options.message;\n\t    } else if (ath.OS in ath.intl[ath.language]) {\t\t\t\t// otherwise we use our message\n\t      message = ath.intl[ath.language][ath.OS];\n\t    }\n\n\t    // add the action icon\n\t    message = '<p>' + message.replace('%icon', '<span class=\"ath-action-icon\">icon</span>') + '</p>';\n\n\t    // create the message container\n\t    this.viewport = document.createElement('div');\n\t    this.viewport.className = 'ath-viewport';\n\t    if (this.options.modal) {\n\t      this.viewport.className += ' ath-modal';\n\t    }\n\t    if (this.options.mandatory) {\n\t      this.viewport.className += ' ath-mandatory';\n\t    }\n\t    this.viewport.style.position = 'absolute';\n\n\t    // create the actual message element\n\t    this.element = document.createElement('div');\n\t    this.element.className = 'ath-container ath-' + ath.OS + ' ath-' + ath.OS + (ath.OSVersion + '').substr(0, 1) + ' ath-' + (ath.isTablet ? 'tablet' : 'phone');\n\t    this.element.style.cssText = '-webkit-transition-property:-webkit-transform,opacity;-webkit-transition-duration:0s;-webkit-transition-timing-function:ease-out;transition-property:transform,opacity;transition-duration:0s;transition-timing-function:ease-out;';\n\t    this.element.style.webkitTransform = 'translate3d(0,-' + window.innerHeight + 'px,0)';\n\t    this.element.style.transform = 'translate3d(0,-' + window.innerHeight + 'px,0)';\n\n\t    // add the application icon\n\t    if (this.options.icon && this.applicationIcon) {\n\t      this.element.className += ' ath-icon';\n\t      this.img = document.createElement('img');\n\t      this.img.className = 'ath-application-icon';\n\t      this.img.addEventListener('load', this, false);\n\t      this.img.addEventListener('error', this, false);\n\n\t      this.img.src = this.applicationIcon.href;\n\t      this.element.appendChild(this.img);\n\t    }\n\n\t    this.element.innerHTML += message;\n\n\t    // we are not ready to show, place the message out of sight\n\t    this.viewport.style.left = '-99999em';\n\n\t    // attach all elements to the DOM\n\t    this.viewport.appendChild(this.element);\n\t    this.container.appendChild(this.viewport);\n\n\t    // if we don't have to wait for an image to load, show the message right away\n\t    if (this.img) {\n\t      this.doLog(\"Add to homescreen: not displaying callout because waiting for img to load\");\n\t    } else {\n\t      this._delayedShow();\n\t    }\n\t  },\n\n\t  _delayedShow: function(e) {\n\t    setTimeout(this._show.bind(this), this.options.startDelay * 1000 + 500);\n\t  },\n\n\t  _show: function() {\n\t    var that = this;\n\n\t    // update the viewport size and orientation\n\t    this.updateViewport();\n\n\t    // reposition/resize the message on orientation change\n\t    window.addEventListener('resize', this, false);\n\t    window.addEventListener('scroll', this, false);\n\t    window.addEventListener('orientationchange', this, false);\n\n\t    if (this.options.modal) {\n\t      // lock any other interaction\n\t      document.addEventListener('touchmove', this, true);\n\t    }\n\n\t    // Enable closing after 1 second\n\t    if (!this.options.mandatory) {\n\t      setTimeout(function() {\n\t        that.element.addEventListener('click', that, true);\n\t      }, 1000);\n\t    }\n\n\t    // kick the animation\n\t    setTimeout(function() {\n\t      that.element.style.webkitTransitionDuration = '1.2s';\n\t      that.element.style.transitionDuration = '1.2s';\n\t      that.element.style.webkitTransform = 'translate3d(0,0,0)';\n\t      that.element.style.transform = 'translate3d(0,0,0)';\n\t    }, 0);\n\n\t    // set the destroy timer\n\t    if (this.options.lifespan) {\n\t      this.removeTimer = setTimeout(this.remove.bind(this), this.options.lifespan * 1000);\n\t    }\n\n\t    // fire the custom onShow event\n\t    if (this.options.onShow) {\n\t      this.options.onShow.call(this);\n\t    }\n\t  },\n\n\t  remove: function() {\n\t    clearTimeout(this.removeTimer);\n\n\t    // clear up the event listeners\n\t    if (this.img) {\n\t      this.img.removeEventListener('load', this, false);\n\t      this.img.removeEventListener('error', this, false);\n\t    }\n\n\t    window.removeEventListener('resize', this, false);\n\t    window.removeEventListener('scroll', this, false);\n\t    window.removeEventListener('orientationchange', this, false);\n\t    document.removeEventListener('touchmove', this, true);\n\t    this.element.removeEventListener('click', this, true);\n\n\t    // remove the message element on transition end\n\t    this.element.addEventListener('transitionend', this, false);\n\t    this.element.addEventListener('webkitTransitionEnd', this, false);\n\t    this.element.addEventListener('MSTransitionEnd', this, false);\n\n\t    // start the fade out animation\n\t    this.element.style.webkitTransitionDuration = '0.3s';\n\t    this.element.style.opacity = '0';\n\t  },\n\n\t  _removeElements: function() {\n\t    this.element.removeEventListener('transitionend', this, false);\n\t    this.element.removeEventListener('webkitTransitionEnd', this, false);\n\t    this.element.removeEventListener('MSTransitionEnd', this, false);\n\n\t    // remove the message from the DOM\n\t    this.container.removeChild(this.viewport);\n\n\t    this.shown = false;\n\n\t    // fire the custom onRemove event\n\t    if (this.options.onRemove) {\n\t      this.options.onRemove.call(this);\n\t    }\n\t  },\n\n\t  updateViewport: function() {\n\t    if (!this.shown) {\n\t      return;\n\t    }\n\n\t    this.viewport.style.width = window.innerWidth + 'px';\n\t    this.viewport.style.height = window.innerHeight + 'px';\n\t    this.viewport.style.left = window.scrollX + 'px';\n\t    this.viewport.style.top = window.scrollY + 'px';\n\n\t    var clientWidth = document.documentElement.clientWidth;\n\n\t    this.orientation = clientWidth > document.documentElement.clientHeight ? 'landscape' : 'portrait';\n\n\t    var screenWidth = ath.OS == 'ios' ? this.orientation == 'portrait' ? screen.width : screen.height : screen.width;\n\t    this.scale = screen.width > clientWidth ? 1 : screenWidth / window.innerWidth;\n\n\t    this.element.style.fontSize = this.options.fontSize / this.scale + 'px';\n\t  },\n\n\t  resize: function() {\n\t    clearTimeout(this.resizeTimer);\n\t    this.resizeTimer = setTimeout(this.updateViewport.bind(this), 100);\n\t  },\n\n\t  updateSession: function() {\n\t    if (ath.hasLocalStorage === false) {\n\t      return;\n\t    }\n\n\t    if (localStorage) {\n\t      localStorage.setItem(this.options.appID, JSON.stringify(this.session));\n\t    }\n\t  },\n\n\t  clearSession: function() {\n\t    this.session = _defaultSession;\n\t    this.updateSession();\n\t  },\n\n\t  getItem: function(item) {\n\t    try {\n\t      if (!localStorage) {\n\t        throw new Error('localStorage is not defined');\n\t      }\n\n\t      return localStorage.getItem(item);\n\t    } catch (e) {\n\t      // Preventing exception for some browsers when fetching localStorage key\n\t      ath.hasLocalStorage = false;\n\t    }\n\t  },\n\n\t  optOut: function() {\n\t    this.session.optedout = true;\n\t    this.updateSession();\n\t  },\n\n\t  optIn: function() {\n\t    this.session.optedout = false;\n\t    this.updateSession();\n\t  },\n\n\t  clearDisplayCount: function() {\n\t    this.session.displayCount = 0;\n\t    this.updateSession();\n\t  },\n\n\t  _preventDefault: function(e) {\n\t    e.preventDefault();\n\t    e.stopPropagation();\n\t  }\n\t};\n\n\t// utility\n\tfunction _extend(target, obj) {\n\t  for (var i in obj) {\n\t    target[i] = obj[i];\n\t  }\n\n\t  return target;\n\t}\n\n\tfunction _removeToken() {\n\t  if (document.location.hash == '#ath') {\n\t    history.replaceState('', window.document.title, document.location.href.split('#')[0]);\n\t  }\n\n\t  if (_reSmartURL.test(document.location.href)) {\n\t    history.replaceState('', window.document.title, document.location.href.replace(_reSmartURL, '$1'));\n\t  }\n\n\t  if (_reQueryString.test(document.location.search)) {\n\t    history.replaceState('', window.document.title, document.location.href.replace(_reQueryString, '$2'));\n\t  }\n\t}\n\n\t/* jshint +W101, +W106 */\n\n\tath.VERSION = '3.2.2';\n\n\tmodule.exports = UI.addToHomescreen = ath;\n\n\n/***/ },\n/* 5 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\n\t/**\n\t * @via https://github.com/Minwe/bootstrap/blob/master/js/alert.js\n\t * @copyright Copyright 2013 Twitter, Inc.\n\t * @license Apache 2.0\n\t */\n\n\t// Alert Class\n\t// NOTE: removeElement option is unavailable now\n\tvar Alert = function(element, options) {\n\t  var _this = this;\n\t  this.options = $.extend({}, Alert.DEFAULTS, options);\n\t  this.$element = $(element);\n\n\t  this.$element\n\t    .addClass('am-fade am-in')\n\t    .on('click.alert.amui', '.am-close', function() {\n\t      _this.close();\n\t    });\n\t};\n\n\tAlert.DEFAULTS = {\n\t  removeElement: true\n\t};\n\n\tAlert.prototype.close = function() {\n\t  var $element = this.$element;\n\n\t  $element.trigger('close.alert.amui').removeClass('am-in');\n\n\t  function processAlert() {\n\t    $element.trigger('closed.alert.amui').remove();\n\t  }\n\n\t  UI.support.transition && $element.hasClass('am-fade') ?\n\t    $element\n\t      .one(UI.support.transition.end, processAlert)\n\t      .emulateTransitionEnd(200) :\n\t    processAlert();\n\t};\n\n\t// plugin\n\tUI.plugin('alert', Alert);\n\n\t// Init code\n\t$(document).on('click.alert.amui.data-api', '[data-am-alert]', function(e) {\n\t  var $target = $(e.target);\n\t  $target.is('.am-close') && $(this).alert('close');\n\t});\n\n\tmodule.exports = Alert;\n\n\n/***/ },\n/* 6 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\n\t/**\n\t * @via https://github.com/twbs/bootstrap/blob/master/js/button.js\n\t * @copyright (c) 2011-2014 Twitter, Inc\n\t * @license The MIT License\n\t */\n\n\tvar Button = function(element, options) {\n\t  this.$element = $(element);\n\t  this.options = $.extend({}, Button.DEFAULTS, options);\n\t  this.isLoading = false;\n\t  this.hasSpinner = false;\n\t};\n\n\tButton.DEFAULTS = {\n\t  loadingText: 'loading...',\n\t  disabledClassName: 'am-disabled',\n\t  spinner: undefined\n\t};\n\n\tButton.prototype.setState = function(state, stateText) {\n\t  var $element = this.$element;\n\t  var disabled = 'disabled';\n\t  var data = $element.data();\n\t  var options = this.options;\n\t  var val = $element.is('input') ? 'val' : 'html';\n\t  var stateClassName = 'am-btn-' + state + ' ' + options.disabledClassName;\n\n\t  state += 'Text';\n\n\t  if (!options.resetText) {\n\t    options.resetText = $element[val]();\n\t  }\n\n\t  // add spinner for element with html()\n\t  if (UI.support.animation && options.spinner &&\n\t    val === 'html' && !this.hasSpinner) {\n\t    options.loadingText = '<span class=\"am-icon-' + options.spinner +\n\t      ' am-icon-spin\"></span>' + options.loadingText;\n\n\t    this.hasSpinner = true;\n\t  }\n\n\t  stateText = stateText ||\n\t    (data[state] === undefined ? options[state] : data[state]);\n\n\t  $element[val](stateText);\n\n\t  // push to event loop to allow forms to submit\n\t  setTimeout($.proxy(function() {\n\t    // TODO: add stateClass for other states\n\t    if (state === 'loadingText') {\n\t      $element.addClass(stateClassName).attr(disabled, disabled);\n\t      this.isLoading = true;\n\t    } else if (this.isLoading) {\n\t      $element.removeClass(stateClassName).removeAttr(disabled);\n\t      this.isLoading = false;\n\t    }\n\t  }, this), 0);\n\t};\n\n\tButton.prototype.toggle = function() {\n\t  var changed = true;\n\t  var $element = this.$element;\n\t  var $parent = this.$element.parent('[class*=\"am-btn-group\"]');\n\n\t  if ($parent.length) {\n\t    var $input = this.$element.find('input');\n\n\t    if ($input.prop('type') == 'radio') {\n\t      if ($input.prop('checked') && $element.hasClass('am-active')) {\n\t        changed = false;\n\t      } else {\n\t        $parent.find('.am-active').removeClass('am-active');\n\t      }\n\t    }\n\n\t    if (changed) {\n\t      $input.prop('checked',\n\t        !$element.hasClass('am-active')).trigger('change');\n\t    }\n\t  }\n\n\t  if (changed) {\n\t    $element.toggleClass('am-active');\n\t    if (!$element.hasClass('am-active')) {\n\t      $element.blur();\n\t    }\n\t  }\n\t};\n\n\tUI.plugin('button', Button, {\n\t  dataOptions: 'data-am-loading',\n\t  methodCall: function(args, instance) {\n\t    if (args[0] === 'toggle') {\n\t      instance.toggle();\n\t    } else if (typeof args[0] === 'string') {\n\t      instance.setState.apply(instance, args);\n\t    }\n\t  }\n\t});\n\n\t// Init code\n\t$(document).on('click.button.amui.data-api', '[data-am-button]', function(e) {\n\t  e.preventDefault();\n\t  var $btn = $(e.target);\n\n\t  if (!$btn.hasClass('am-btn')) {\n\t    $btn = $btn.closest('.am-btn');\n\t  }\n\n\t  $btn.button('toggle');\n\t});\n\n\tUI.ready(function(context) {\n\t  $('[data-am-loading]', context).button();\n\t});\n\n\tmodule.exports = UI.button = Button;\n\n\n/***/ },\n/* 7 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\n\t/**\n\t * @via https://github.com/twbs/bootstrap/blob/master/js/collapse.js\n\t * @copyright (c) 2011-2014 Twitter, Inc\n\t * @license The MIT License\n\t */\n\n\tvar Collapse = function(element, options) {\n\t  this.$element = $(element);\n\t  this.options = $.extend({}, Collapse.DEFAULTS, options);\n\t  this.transitioning = null;\n\n\t  if (this.options.parent) {\n\t    this.$parent = $(this.options.parent);\n\t  }\n\n\t  if (this.options.toggle) {\n\t    this.toggle();\n\t  }\n\t};\n\n\tCollapse.DEFAULTS = {\n\t  toggle: true\n\t};\n\n\tCollapse.prototype.open = function() {\n\t  if (this.transitioning || this.$element.hasClass('am-in')) {\n\t    return;\n\t  }\n\n\t  var startEvent = $.Event('open.collapse.amui');\n\t  this.$element.trigger(startEvent);\n\n\t  if (startEvent.isDefaultPrevented()) {\n\t    return;\n\t  }\n\n\t  var actives = this.$parent && this.$parent.find('> .am-panel > .am-in');\n\n\t  if (actives && actives.length) {\n\t    var hasData = actives.data('amui.collapse');\n\n\t    if (hasData && hasData.transitioning) {\n\t      return;\n\t    }\n\n\t    Plugin.call(actives, 'close');\n\n\t    hasData || actives.data('amui.collapse', null);\n\t  }\n\n\t  this.$element\n\t    .removeClass('am-collapse')\n\t    .addClass('am-collapsing').height(0);\n\n\t  this.transitioning = 1;\n\n\t  var complete = function() {\n\t    this.$element\n\t      .removeClass('am-collapsing')\n\t      .addClass('am-collapse am-in')\n\t      .height('')\n\t      .trigger('opened.collapse.amui');\n\t    this.transitioning = 0;\n\t  };\n\n\t  if (!UI.support.transition) {\n\t    return complete.call(this);\n\t  }\n\n\t  var scrollHeight = this.$element[0].scrollHeight;\n\n\t  this.$element\n\t    .one(UI.support.transition.end, $.proxy(complete, this))\n\t    .emulateTransitionEnd(300)\n\t    .css({height: scrollHeight}); // 当折叠的容器有 padding 时，如果用 height() 只能设置内容的宽度\n\t};\n\n\tCollapse.prototype.close = function() {\n\t  if (this.transitioning || !this.$element.hasClass('am-in')) {\n\t    return;\n\t  }\n\n\t  var startEvent = $.Event('close.collapse.amui');\n\t  this.$element.trigger(startEvent);\n\n\t  if (startEvent.isDefaultPrevented()) {\n\t    return;\n\t  }\n\n\t  this.$element.height(this.$element.height()).redraw();\n\n\t  this.$element.addClass('am-collapsing').\n\t    removeClass('am-collapse am-in');\n\n\t  this.transitioning = 1;\n\n\t  var complete = function() {\n\t    this.transitioning = 0;\n\t    this.$element\n\t      .trigger('closed.collapse.amui')\n\t      .removeClass('am-collapsing')\n\t      .addClass('am-collapse');\n\t    // css({height: '0'});\n\t  };\n\n\t  if (!UI.support.transition) {\n\t    return complete.call(this);\n\t  }\n\n\t  this.$element.height(0)\n\t    .one(UI.support.transition.end, $.proxy(complete, this))\n\t    .emulateTransitionEnd(300);\n\t};\n\n\tCollapse.prototype.toggle = function() {\n\t  this[this.$element.hasClass('am-in') ? 'close' : 'open']();\n\t};\n\n\t// Collapse Plugin\n\tfunction Plugin(option) {\n\t  return this.each(function() {\n\t    var $this = $(this);\n\t    var data = $this.data('amui.collapse');\n\t    var options = $.extend({}, Collapse.DEFAULTS,\n\t      UI.utils.options($this.attr('data-am-collapse')),\n\t      typeof option == 'object' && option);\n\n\t    if (!data && options.toggle && option === 'open') {\n\t      option = !option;\n\t    }\n\n\t    if (!data) {\n\t      $this.data('amui.collapse', (data = new Collapse(this, options)));\n\t    }\n\n\t    if (typeof option == 'string') {\n\t      data[option]();\n\t    }\n\t  });\n\t}\n\n\t$.fn.collapse = Plugin;\n\n\t// Init code\n\t$(document).on('click.collapse.amui.data-api', '[data-am-collapse]',\n\t  function(e) {\n\t    var href;\n\t    var $this = $(this);\n\t    var options = UI.utils.options($this.attr('data-am-collapse'));\n\t    var target = options.target ||\n\t      e.preventDefault() ||\n\t      (href = $this.attr('href')) &&\n\t      href.replace(/.*(?=#[^\\s]+$)/, '');\n\t    var $target = $(target);\n\t    var data = $target.data('amui.collapse');\n\t    var option = data ? 'toggle' : options;\n\t    var parent = options.parent;\n\t    var $parent = parent && $(parent);\n\n\t    if (!data || !data.transitioning) {\n\t      if ($parent) {\n\t        // '[data-am-collapse*=\"{parent: \\'' + parent + '\"]\n\t        $parent.find('[data-am-collapse]').not($this).addClass('am-collapsed');\n\t      }\n\n\t      $this[$target.hasClass('am-in') ?\n\t        'addClass' : 'removeClass']('am-collapsed');\n\t    }\n\n\t    Plugin.call($target, option);\n\t  });\n\n\tmodule.exports = UI.collapse = Collapse;\n\n\t// TODO: 更好的 target 选择方式\n\t//       折叠的容器必须没有 border/padding 才能正常处理，否则动画会有一些小问题\n\t//       寻找更好的未知高度 transition 动画解决方案，max-height 之类的就算了\n\n\n/***/ },\n/* 8 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\tvar $doc = $(document);\n\n\t/**\n\t * bootstrap-datepicker.js\n\t * @via http://www.eyecon.ro/bootstrap-datepicker\n\t * @license http://www.apache.org/licenses/LICENSE-2.0\n\t */\n\tvar Datepicker = function(element, options) {\n\t  this.$element = $(element);\n\t  this.options = $.extend({}, Datepicker.DEFAULTS, options);\n\t  this.format = DPGlobal.parseFormat(this.options.format);\n\n\t  this.$element.data('date', this.options.date);\n\t  this.language = this.getLocale(this.options.locale);\n\t  this.theme = this.options.theme;\n\t  this.$picker = $(DPGlobal.template).appendTo('body').on({\n\t    click: $.proxy(this.click, this)\n\t    // mousedown: $.proxy(this.mousedown, this)\n\t  });\n\n\t  this.isInput = this.$element.is('input');\n\t  this.component = this.$element.is('.am-datepicker-date') ?\n\t    this.$element.find('.am-datepicker-add-on') : false;\n\n\t  if (this.isInput) {\n\t    this.$element.on({\n\t      'click.datepicker.amui': $.proxy(this.open, this),\n\t      // blur: $.proxy(this.close, this),\n\t      'keyup.datepicker.amui': $.proxy(this.update, this)\n\t    });\n\t  } else {\n\t    if (this.component) {\n\t      this.component.on('click.datepicker.amui', $.proxy(this.open, this));\n\t    } else {\n\t      this.$element.on('click.datepicker.amui', $.proxy(this.open, this));\n\t    }\n\t  }\n\n\t  this.minViewMode = this.options.minViewMode;\n\n\t  if (typeof this.minViewMode === 'string') {\n\t    switch (this.minViewMode) {\n\t      case 'months':\n\t        this.minViewMode = 1;\n\t        break;\n\t      case 'years':\n\t        this.minViewMode = 2;\n\t        break;\n\t      default:\n\t        this.minViewMode = 0;\n\t        break;\n\t    }\n\t  }\n\n\t  this.viewMode = this.options.viewMode;\n\n\t  if (typeof this.viewMode === 'string') {\n\t    switch (this.viewMode) {\n\t      case 'months':\n\t        this.viewMode = 1;\n\t        break;\n\t      case 'years':\n\t        this.viewMode = 2;\n\t        break;\n\t      default:\n\t        this.viewMode = 0;\n\t        break;\n\t    }\n\t  }\n\n\t  this.startViewMode = this.viewMode;\n\t  this.weekStart = ((this.options.weekStart ||\n\t  Datepicker.locales[this.language].weekStart || 0) % 7);\n\t  this.weekEnd = ((this.weekStart + 6) % 7);\n\t  this.onRender = this.options.onRender;\n\n\t  this.setTheme();\n\t  this.fillDow();\n\t  this.fillMonths();\n\t  this.update();\n\t  this.showMode();\n\t};\n\n\tDatepicker.DEFAULTS = {\n\t  locale: 'zh_CN',\n\t  format: 'yyyy-mm-dd',\n\t  weekStart: undefined,\n\t  viewMode: 0,\n\t  minViewMode: 0,\n\t  date: '',\n\t  theme: '',\n\t  autoClose: 1,\n\t  onRender: function(date) {\n\t    return '';\n\t  }\n\t};\n\n\tDatepicker.prototype.open = function(e) {\n\t  this.$picker.show();\n\t  this.height = this.component ?\n\t    this.component.outerHeight() : this.$element.outerHeight();\n\n\t  this.place();\n\t  $(window).on('resize.datepicker.amui', $.proxy(this.place, this));\n\t  if (e) {\n\t    e.stopPropagation();\n\t    e.preventDefault();\n\t  }\n\t  var that = this;\n\t  $doc.on('mousedown.datapicker.amui touchstart.datepicker.amui', function(ev) {\n\t    if ($(ev.target).closest('.am-datepicker').length === 0) {\n\t      that.close();\n\t    }\n\t  });\n\t  this.$element.trigger({\n\t    type: 'open.datepicker.amui',\n\t    date: this.date\n\t  });\n\t};\n\n\tDatepicker.prototype.close = function() {\n\t  this.$picker.hide();\n\t  $(window).off('resize.datepicker.amui', this.place);\n\t  this.viewMode = this.startViewMode;\n\t  this.showMode();\n\t  if (!this.isInput) {\n\t    $(document).off('mousedown.datapicker.amui touchstart.datepicker.amui',\n\t      this.close);\n\t  }\n\t  // this.set();\n\t  this.$element.trigger({\n\t    type: 'close.datepicker.amui',\n\t    date: this.date\n\t  });\n\t};\n\n\tDatepicker.prototype.set = function() {\n\t  var formatted = DPGlobal.formatDate(this.date, this.format);\n\t  var $input;\n\n\t  if (!this.isInput) {\n\t    if (this.component) {\n\t      $input = this.$element.find('input').attr('value', formatted);\n\t    }\n\n\t    this.$element.data('date', formatted);\n\t  } else {\n\t    $input = this.$element.attr('value', formatted);\n\t  }\n\n\t  // fixes https://github.com/amazeui/amazeui/issues/711\n\t  $input && $input.trigger('change');\n\t};\n\n\tDatepicker.prototype.setValue = function(newDate) {\n\t  if (typeof newDate === 'string') {\n\t    this.date = DPGlobal.parseDate(newDate, this.format);\n\t  } else {\n\t    this.date = new Date(newDate);\n\t  }\n\t  this.set();\n\n\t  this.viewDate = new Date(this.date.getFullYear(),\n\t    this.date.getMonth(), 1, 0, 0, 0, 0);\n\n\t  this.fill();\n\t};\n\n\tDatepicker.prototype.place = function() {\n\t  var offset = this.component ?\n\t    this.component.offset() : this.$element.offset();\n\t  var $width = this.component ?\n\t    this.component.width() : this.$element.width();\n\t  var top = offset.top + this.height;\n\t  var left = offset.left;\n\t  var right = $doc.width() - offset.left - $width;\n\t  var isOutView = this.isOutView();\n\n\t  this.$picker.removeClass('am-datepicker-right');\n\t  this.$picker.removeClass('am-datepicker-up');\n\n\t  if ($doc.width() > 640) {\n\t    if (isOutView.outRight) {\n\t      this.$picker.addClass('am-datepicker-right');\n\t      this.$picker.css({\n\t        top: top,\n\t        left: 'auto',\n\t        right: right\n\t      });\n\t      return;\n\t    }\n\t    if (isOutView.outBottom) {\n\t      this.$picker.addClass('am-datepicker-up');\n\t      top = offset.top - this.$picker.outerHeight(true);\n\t    }\n\t  } else {\n\t    left = 0;\n\t  }\n\n\t  this.$picker.css({\n\t    top: top,\n\t    left: left\n\t  });\n\t};\n\n\tDatepicker.prototype.update = function(newDate) {\n\t  this.date = DPGlobal.parseDate(\n\t    typeof newDate === 'string' ? newDate : (this.isInput ?\n\t      this.$element.prop('value') : this.$element.data('date')),\n\t    this.format\n\t  );\n\t  this.viewDate = new Date(this.date.getFullYear(),\n\t    this.date.getMonth(), 1, 0, 0, 0, 0);\n\t  this.fill();\n\t};\n\n\t// Days of week\n\tDatepicker.prototype.fillDow = function() {\n\t  var dowCount = this.weekStart;\n\t  var html = '<tr>';\n\t  while (dowCount < this.weekStart + 7) {\n\t    // NOTE: do % then add 1\n\t    html += '<th class=\"am-datepicker-dow\">' +\n\t    Datepicker.locales[this.language].daysMin[(dowCount++) % 7] +\n\t    '</th>';\n\t  }\n\t  html += '</tr>';\n\n\t  this.$picker.find('.am-datepicker-days thead').append(html);\n\t};\n\n\tDatepicker.prototype.fillMonths = function() {\n\t  var html = '';\n\t  var i = 0;\n\t  while (i < 12) {\n\t    html += '<span class=\"am-datepicker-month\">' +\n\t    Datepicker.locales[this.language].monthsShort[i++] + '</span>';\n\t  }\n\t  this.$picker.find('.am-datepicker-months td').append(html);\n\t};\n\n\tDatepicker.prototype.fill = function() {\n\t  var d = new Date(this.viewDate);\n\t  var year = d.getFullYear();\n\t  var month = d.getMonth();\n\t  var currentDate = this.date.valueOf();\n\n\t  var prevMonth = new Date(year, month - 1, 28, 0, 0, 0, 0);\n\t  var day = DPGlobal\n\t    .getDaysInMonth(prevMonth.getFullYear(), prevMonth.getMonth());\n\n\t  var daysSelect = this.$picker\n\t    .find('.am-datepicker-days .am-datepicker-select');\n\n\t  if (this.language === 'zh_CN') {\n\t    daysSelect.text(year + Datepicker.locales[this.language].year[0] +\n\t    ' ' + Datepicker.locales[this.language].months[month]);\n\t  } else {\n\t    daysSelect.text(Datepicker.locales[this.language].months[month] +\n\t    ' ' + year);\n\t  }\n\n\t  prevMonth.setDate(day);\n\t  prevMonth.setDate(day - (prevMonth.getDay() - this.weekStart + 7) % 7);\n\n\t  var nextMonth = new Date(prevMonth);\n\t  nextMonth.setDate(nextMonth.getDate() + 42);\n\t  nextMonth = nextMonth.valueOf();\n\t  var html = [];\n\n\t  var className;\n\t  var prevY;\n\t  var prevM;\n\n\t  while (prevMonth.valueOf() < nextMonth) {\n\t    if (prevMonth.getDay() === this.weekStart) {\n\t      html.push('<tr>');\n\t    }\n\n\t    className = this.onRender(prevMonth, 0);\n\t    prevY = prevMonth.getFullYear();\n\t    prevM = prevMonth.getMonth();\n\n\t    if ((prevM < month && prevY === year) || prevY < year) {\n\t      className += ' am-datepicker-old';\n\t    } else if ((prevM > month && prevY === year) || prevY > year) {\n\t      className += ' am-datepicker-new';\n\t    }\n\n\t    if (prevMonth.valueOf() === currentDate) {\n\t      className += ' am-active';\n\t    }\n\t    html.push('<td class=\"am-datepicker-day ' +\n\t    className + '\">' + prevMonth.getDate() + '</td>');\n\n\t    if (prevMonth.getDay() === this.weekEnd) {\n\t      html.push('</tr>');\n\t    }\n\n\t    prevMonth.setDate(prevMonth.getDate() + 1);\n\t  }\n\n\t  this.$picker.find('.am-datepicker-days tbody')\n\t    .empty().append(html.join(''));\n\n\t  var currentYear = this.date.getFullYear();\n\t  var months = this.$picker.find('.am-datepicker-months')\n\t    .find('.am-datepicker-select')\n\t    .text(year);\n\t  months = months.end()\n\t    .find('span').removeClass('am-active').removeClass('am-disabled');\n\n\t  var monthLen = 0;\n\n\t  while (monthLen < 12) {\n\t    if (this.onRender(d.setFullYear(year, monthLen), 1)) {\n\t      months.eq(monthLen).addClass('am-disabled');\n\t    }\n\t    monthLen++;\n\t  }\n\n\t  if (currentYear === year) {\n\t    months.eq(this.date.getMonth())\n\t        .removeClass('am-disabled')\n\t        .addClass('am-active');\n\t  }\n\n\t  html = '';\n\t  year = parseInt(year / 10, 10) * 10;\n\t  var yearCont = this.$picker\n\t    .find('.am-datepicker-years')\n\t    .find('.am-datepicker-select')\n\t    .text(year + '-' + (year + 9))\n\t    .end()\n\t    .find('td');\n\t  var yearClassName;\n\t  // fixes https://github.com/amazeui/amazeui/issues/770\n\t  // maybe not need now\n\t  var viewDate = new Date(this.viewDate);\n\n\t  year -= 1;\n\n\t  for (var i = -1; i < 11; i++) {\n\t    yearClassName = this.onRender(viewDate.setFullYear(year), 2);\n\t    html += '<span class=\"' + yearClassName + '' +\n\t    (i === -1 || i === 10 ? ' am-datepicker-old' : '') +\n\t    (currentYear === year ? ' am-active' : '') + '\">' + year + '</span>';\n\t    year += 1;\n\t  }\n\t  yearCont.html(html);\n\t};\n\n\tDatepicker.prototype.click = function(event) {\n\t  event.stopPropagation();\n\t  event.preventDefault();\n\t  var month;\n\t  var year;\n\t  var $dayActive = this.$picker.find('.am-datepicker-days').find('.am-active');\n\t  var $months = this.$picker.find('.am-datepicker-months');\n\t  var $monthIndex = $months.find('.am-active').index();\n\n\t  var $target = $(event.target).closest('span, td, th');\n\t  if ($target.length === 1) {\n\t    switch ($target[0].nodeName.toLowerCase()) {\n\t      case 'th':\n\t        switch ($target[0].className) {\n\t          case 'am-datepicker-switch':\n\t            this.showMode(1);\n\t            break;\n\t          case 'am-datepicker-prev':\n\t          case 'am-datepicker-next':\n\t            this.viewDate['set' + DPGlobal.modes[this.viewMode].navFnc].call(\n\t              this.viewDate,\n\t              this.viewDate\n\t                ['get' + DPGlobal.modes[this.viewMode].navFnc]\n\t                .call(this.viewDate) +\n\t              DPGlobal.modes[this.viewMode].navStep *\n\t              ($target[0].className === 'am-datepicker-prev' ? -1 : 1)\n\t            );\n\t            this.fill();\n\t            this.set();\n\t            break;\n\t        }\n\t        break;\n\t      case 'span':\n\t        if ($target.is('.am-disabled')) {\n\t          return;\n\t        }\n\n\t        if ($target.is('.am-datepicker-month')) {\n\t          month = $target.parent().find('span').index($target);\n\n\t          if ($target.is('.am-active')) {\n\t            this.viewDate.setMonth(month, $dayActive.text());\n\t          } else {\n\t            this.viewDate.setMonth(month);\n\t          }\n\n\t        } else {\n\t          year = parseInt($target.text(), 10) || 0;\n\t          if ($target.is('.am-active')) {\n\t            this.viewDate.setFullYear(year, $monthIndex, $dayActive.text());\n\t          } else {\n\t            this.viewDate.setFullYear(year);\n\t          }\n\n\t        }\n\n\t        if (this.viewMode !== 0) {\n\t          this.date = new Date(this.viewDate);\n\t          this.$element.trigger({\n\t            type: 'changeDate.datepicker.amui',\n\t            date: this.date,\n\t            viewMode: DPGlobal.modes[this.viewMode].clsName\n\t          });\n\t        }\n\n\t        this.showMode(-1);\n\t        this.fill();\n\t        this.set();\n\t        break;\n\t      case 'td':\n\t        if ($target.is('.am-datepicker-day') && !$target.is('.am-disabled')) {\n\t          var day = parseInt($target.text(), 10) || 1;\n\t          month = this.viewDate.getMonth();\n\t          if ($target.is('.am-datepicker-old')) {\n\t            month -= 1;\n\t          } else if ($target.is('.am-datepicker-new')) {\n\t            month += 1;\n\t          }\n\t          year = this.viewDate.getFullYear();\n\t          this.date = new Date(year, month, day, 0, 0, 0, 0);\n\t          this.viewDate = new Date(year, month, Math.min(28, day), 0, 0, 0, 0);\n\t          this.fill();\n\t          this.set();\n\t          this.$element.trigger({\n\t            type: 'changeDate.datepicker.amui',\n\t            date: this.date,\n\t            viewMode: DPGlobal.modes[this.viewMode].clsName\n\t          });\n\n\t          this.options.autoClose && this.close();\n\t        }\n\t        break;\n\t    }\n\t  }\n\t};\n\n\tDatepicker.prototype.mousedown = function(event) {\n\t  event.stopPropagation();\n\t  event.preventDefault();\n\t};\n\n\tDatepicker.prototype.showMode = function(dir) {\n\t  if (dir) {\n\t    this.viewMode = Math.max(this.minViewMode,\n\t      Math.min(2, this.viewMode + dir));\n\t  }\n\n\t  this.$picker.find('>div').hide().\n\t    filter('.am-datepicker-' + DPGlobal.modes[this.viewMode].clsName).show();\n\t};\n\n\tDatepicker.prototype.isOutView = function() {\n\t  var offset = this.component ?\n\t    this.component.offset() : this.$element.offset();\n\t  var isOutView = {\n\t    outRight: false,\n\t    outBottom: false\n\t  };\n\t  var $picker = this.$picker;\n\t  var width = offset.left + $picker.outerWidth(true);\n\t  var height = offset.top + $picker.outerHeight(true) +\n\t    this.$element.innerHeight();\n\n\t  if (width > $doc.width()) {\n\t    isOutView.outRight = true;\n\t  }\n\t  if (height > $doc.height()) {\n\t    isOutView.outBottom = true;\n\t  }\n\t  return isOutView;\n\t};\n\n\tDatepicker.prototype.getLocale = function(locale) {\n\t  if (!locale) {\n\t    locale = navigator.language && navigator.language.split('-');\n\t    locale[1] = locale[1].toUpperCase();\n\t    locale = locale.join('_');\n\t  }\n\n\t  if (!Datepicker.locales[locale]) {\n\t    locale = 'en_US';\n\t  }\n\t  return locale;\n\t};\n\n\tDatepicker.prototype.setTheme = function() {\n\t  if (this.theme) {\n\t    this.$picker.addClass('am-datepicker-' + this.theme);\n\t  }\n\t};\n\n\t// Datepicker locales\n\tDatepicker.locales = {\n\t  en_US: {\n\t    days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',\n\t      'Friday', 'Saturday'],\n\t    daysShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],\n\t    daysMin: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'],\n\t    months: ['January', 'February', 'March', 'April', 'May', 'June',\n\t      'July', 'August', 'September', 'October', 'November', 'December'],\n\t    monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',\n\t      'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],\n\t    weekStart: 0\n\t  },\n\t  zh_CN: {\n\t    days: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],\n\t    daysShort: ['周日', '周一', '周二', '周三', '周四', '周五', '周六'],\n\t    daysMin: ['日', '一', '二', '三', '四', '五', '六'],\n\t    months: ['一月', '二月', '三月', '四月', '五月', '六月', '七月',\n\t      '八月', '九月', '十月', '十一月', '十二月'],\n\t    monthsShort: ['一月', '二月', '三月', '四月', '五月', '六月',\n\t      '七月', '八月', '九月', '十月', '十一月', '十二月'],\n\t    weekStart: 1,\n\t    year: ['年']\n\t  }\n\t};\n\n\tvar DPGlobal = {\n\t  modes: [\n\t    {\n\t      clsName: 'days',\n\t      navFnc: 'Month',\n\t      navStep: 1\n\t    },\n\t    {\n\t      clsName: 'months',\n\t      navFnc: 'FullYear',\n\t      navStep: 1\n\t    },\n\t    {\n\t      clsName: 'years',\n\t      navFnc: 'FullYear',\n\t      navStep: 10\n\t    }\n\t  ],\n\n\t  isLeapYear: function(year) {\n\t    return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0));\n\t  },\n\n\t  getDaysInMonth: function(year, month) {\n\t    return [31, (DPGlobal.isLeapYear(year) ? 29 : 28),\n\t      31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];\n\t  },\n\n\t  parseFormat: function(format) {\n\t    var separator = format.match(/[.\\/\\-\\s].*?/);\n\t    var parts = format.split(/\\W+/);\n\n\t    if (!separator || !parts || parts.length === 0) {\n\t      throw new Error('Invalid date format.');\n\t    }\n\n\t    return {\n\t      separator: separator,\n\t      parts: parts\n\t    };\n\t  },\n\n\t  parseDate: function(date, format) {\n\t    var parts = date.split(format.separator);\n\t    var val;\n\t    date = new Date();\n\n\t    date.setHours(0);\n\t    date.setMinutes(0);\n\t    date.setSeconds(0);\n\t    date.setMilliseconds(0);\n\n\t    if (parts.length === format.parts.length) {\n\t      var year = date.getFullYear();\n\t      var day = date.getDate();\n\t      var month = date.getMonth();\n\n\t      for (var i = 0, cnt = format.parts.length; i < cnt; i++) {\n\t        val = parseInt(parts[i], 10) || 1;\n\t        switch (format.parts[i]) {\n\t          case 'dd':\n\t          case 'd':\n\t            day = val;\n\t            date.setDate(val);\n\t            break;\n\t          case 'mm':\n\t          case 'm':\n\t            month = val - 1;\n\t            date.setMonth(val - 1);\n\t            break;\n\t          case 'yy':\n\t            year = 2000 + val;\n\t            date.setFullYear(2000 + val);\n\t            break;\n\t          case 'yyyy':\n\t            year = val;\n\t            date.setFullYear(val);\n\t            break;\n\t        }\n\t      }\n\t      date = new Date(year, month, day, 0, 0, 0);\n\t    }\n\t    return date;\n\t  },\n\n\t  formatDate: function(date, format) {\n\t    var val = {\n\t      d: date.getDate(),\n\t      m: date.getMonth() + 1,\n\t      yy: date.getFullYear().toString().substring(2),\n\t      yyyy: date.getFullYear()\n\t    };\n\t    var dateArray = [];\n\n\t    val.dd = (val.d < 10 ? '0' : '') + val.d;\n\t    val.mm = (val.m < 10 ? '0' : '') + val.m;\n\n\t    for (var i = 0, cnt = format.parts.length; i < cnt; i++) {\n\t      dateArray.push(val[format.parts[i]]);\n\t    }\n\t    return dateArray.join(format.separator);\n\t  },\n\n\t  headTemplate: '<thead>' +\n\t  '<tr class=\"am-datepicker-header\">' +\n\t  '<th class=\"am-datepicker-prev\">' +\n\t  '<i class=\"am-datepicker-prev-icon\"></i></th>' +\n\t  '<th colspan=\"5\" class=\"am-datepicker-switch\">' +\n\t  '<div class=\"am-datepicker-select\"></div></th>' +\n\t  '<th class=\"am-datepicker-next\"><i class=\"am-datepicker-next-icon\"></i>' +\n\t  '</th></tr></thead>',\n\n\t  contTemplate: '<tbody><tr><td colspan=\"7\"></td></tr></tbody>'\n\t};\n\n\tDPGlobal.template = '<div class=\"am-datepicker am-datepicker-dropdown\">' +\n\t'<div class=\"am-datepicker-caret\"></div>' +\n\t'<div class=\"am-datepicker-days\">' +\n\t'<table class=\"am-datepicker-table\">' +\n\tDPGlobal.headTemplate +\n\t'<tbody></tbody>' +\n\t'</table>' +\n\t'</div>' +\n\t'<div class=\"am-datepicker-months\">' +\n\t'<table class=\"am-datepicker-table\">' +\n\tDPGlobal.headTemplate +\n\tDPGlobal.contTemplate +\n\t'</table>' +\n\t'</div>' +\n\t'<div class=\"am-datepicker-years\">' +\n\t'<table class=\"am-datepicker-table\">' +\n\tDPGlobal.headTemplate +\n\tDPGlobal.contTemplate +\n\t'</table>' +\n\t'</div>' +\n\t'</div>';\n\n\t// jQuery plugin\n\tUI.plugin('datepicker', Datepicker);\n\n\t// Init code\n\tUI.ready(function(context) {\n\t  $('[data-am-datepicker]').datepicker();\n\t});\n\n\tmodule.exports = UI.datepicker = Datepicker;\n\n\t// TODO: 1. 载入动画\n\t//       2. less 优化\n\n\n/***/ },\n/* 9 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\tvar $doc = $(document);\n\tvar transition = UI.support.transition;\n\n\tvar Dimmer = function() {\n\t  this.id = UI.utils.generateGUID('am-dimmer');\n\t  this.$element = $(Dimmer.DEFAULTS.tpl, {\n\t    id: this.id\n\t  });\n\n\t  this.inited = false;\n\t  this.scrollbarWidth = 0;\n\t  this.$used = $([]);\n\t};\n\n\tDimmer.DEFAULTS = {\n\t  tpl: '<div class=\"am-dimmer\" data-am-dimmer></div>'\n\t};\n\n\tDimmer.prototype.init = function() {\n\t  if (!this.inited) {\n\t    $(document.body).append(this.$element);\n\t    this.inited = true;\n\t    $doc.trigger('init.dimmer.amui');\n\t    this.$element.on('touchmove.dimmer.amui', function(e) {\n\t      e.preventDefault();\n\t    });\n\t  }\n\n\t  return this;\n\t};\n\n\tDimmer.prototype.open = function(relatedElement) {\n\t  if (!this.inited) {\n\t    this.init();\n\t  }\n\n\t  var $element = this.$element;\n\n\t  // 用于多重调用\n\t  if (relatedElement) {\n\t    this.$used = this.$used.add($(relatedElement));\n\t  }\n\n\t  this.checkScrollbar().setScrollbar();\n\n\t  $element.show().trigger('open.dimmer.amui');\n\n\t  transition && $element.off(transition.end);\n\n\t  setTimeout(function() {\n\t    $element.addClass('am-active');\n\t  }, 0);\n\n\t  return this;\n\t};\n\n\tDimmer.prototype.close = function(relatedElement, force) {\n\t  this.$used = this.$used.not($(relatedElement));\n\n\t  if (!force && this.$used.length) {\n\t    return this;\n\t  }\n\n\t  var $element = this.$element;\n\n\t  $element.removeClass('am-active').trigger('close.dimmer.amui');\n\n\t  function complete() {\n\t    $element.hide();\n\t    this.resetScrollbar();\n\t  }\n\n\t  // transition ? $element.one(transition.end, $.proxy(complete, this)) :\n\t  complete.call(this);\n\n\t  return this;\n\t};\n\n\tDimmer.prototype.checkScrollbar = function() {\n\t  this.scrollbarWidth = UI.utils.measureScrollbar();\n\n\t  return this;\n\t};\n\n\tDimmer.prototype.setScrollbar = function() {\n\t  var $body = $(document.body);\n\t  var bodyPaddingRight = parseInt(($body.css('padding-right') || 0), 10);\n\n\t  if (this.scrollbarWidth) {\n\t    $body.css('padding-right', bodyPaddingRight + this.scrollbarWidth);\n\t  }\n\n\t  $body.addClass('am-dimmer-active');\n\n\t  return this;\n\t};\n\n\tDimmer.prototype.resetScrollbar = function() {\n\t  $(document.body).css('padding-right', '').removeClass('am-dimmer-active');\n\n\t  return this;\n\t};\n\n\tmodule.exports = UI.dimmer = new Dimmer();\n\n\n/***/ },\n/* 10 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\tvar animation = UI.support.animation;\n\n\t/**\n\t * @via https://github.com/Minwe/bootstrap/blob/master/js/dropdown.js\n\t * @copyright (c) 2011-2014 Twitter, Inc\n\t * @license The MIT License\n\t */\n\n\t// var toggle = '[data-am-dropdown] > .am-dropdown-toggle';\n\n\tvar Dropdown = function(element, options) {\n\t  this.options = $.extend({}, Dropdown.DEFAULTS, options);\n\n\t  options = this.options;\n\n\t  this.$element = $(element);\n\t  this.$toggle = this.$element.find(options.selector.toggle);\n\t  this.$dropdown = this.$element.find(options.selector.dropdown);\n\t  this.$boundary = (options.boundary === window) ? $(window) :\n\t    this.$element.closest(options.boundary);\n\t  this.$justify = (options.justify && $(options.justify).length &&\n\t  $(options.justify)) || undefined;\n\n\t  !this.$boundary.length && (this.$boundary = $(window));\n\n\t  this.active = this.$element.hasClass('am-active') ? true : false;\n\t  this.animating = null;\n\n\t  this.events();\n\t};\n\n\tDropdown.DEFAULTS = {\n\t  animation: 'am-animation-slide-top-fixed',\n\t  boundary: window,\n\t  justify: undefined,\n\t  selector: {\n\t    dropdown: '.am-dropdown-content',\n\t    toggle: '.am-dropdown-toggle'\n\t  },\n\t  trigger: 'click'\n\t};\n\n\tDropdown.prototype.toggle = function() {\n\t  this.clear();\n\n\t  if (this.animating) {\n\t    return;\n\t  }\n\n\t  this[this.active ? 'close' : 'open']();\n\t};\n\n\tDropdown.prototype.open = function(e) {\n\t  var $toggle = this.$toggle;\n\t  var $element = this.$element;\n\t  var $dropdown = this.$dropdown;\n\n\t  if ($toggle.is('.am-disabled, :disabled')) {\n\t    return;\n\t  }\n\n\t  if (this.active) {\n\t    return;\n\t  }\n\n\t  $element.trigger('open.dropdown.amui').addClass('am-active');\n\n\t  $toggle.trigger('focus');\n\n\t  this.checkDimensions();\n\n\t  var complete = $.proxy(function() {\n\t    $element.trigger('opened.dropdown.amui');\n\t    this.active = true;\n\t    this.animating = 0;\n\t  }, this);\n\n\t  if (animation) {\n\t    this.animating = 1;\n\t    $dropdown.addClass(this.options.animation).\n\t      on(animation.end + '.open.dropdown.amui', $.proxy(function() {\n\t        complete();\n\t        $dropdown.removeClass(this.options.animation);\n\t      }, this));\n\t  } else {\n\t    complete();\n\t  }\n\t};\n\n\tDropdown.prototype.close = function() {\n\t  if (!this.active) {\n\t    return;\n\t  }\n\n\t  // fix #165\n\t  // var animationName = this.options.animation + ' am-animation-reverse';\n\t  var animationName = 'am-dropdown-animation';\n\t  var $element = this.$element;\n\t  var $dropdown = this.$dropdown;\n\n\t  $element.trigger('close.dropdown.amui');\n\n\t  var complete = $.proxy(function complete() {\n\t    $element.\n\t      removeClass('am-active').\n\t      trigger('closed.dropdown.amui');\n\t    this.active = false;\n\t    this.animating = 0;\n\t    this.$toggle.blur();\n\t  }, this);\n\n\t  if (animation) {\n\t    $dropdown.removeClass(this.options.animation);\n\t    $dropdown.addClass(animationName);\n\t    this.animating = 1;\n\t    // animation\n\t    $dropdown.one(animation.end + '.close.dropdown.amui', function() {\n\t      $dropdown.removeClass(animationName);\n\t      complete();\n\t    });\n\t  } else {\n\t    complete();\n\t  }\n\t};\n\n\tDropdown.prototype.enable = function() {\n\t  this.$toggle.prop('disabled', false);\n\t},\n\n\tDropdown.prototype.disable = function() {\n\t  this.$toggle.prop('disabled', true);\n\t},\n\n\tDropdown.prototype.checkDimensions = function() {\n\t  if (!this.$dropdown.length) {\n\t    return;\n\t  }\n\n\t  var $dropdown = this.$dropdown;\n\t  var offset = $dropdown.offset();\n\t  var width = $dropdown.outerWidth();\n\t  var boundaryWidth = this.$boundary.width();\n\t  var boundaryOffset = $.isWindow(this.boundary) && this.$boundary.offset() ?\n\t    this.$boundary.offset().left : 0;\n\n\t  if (this.$justify) {\n\t    // jQuery.fn.width() is really...\n\t    $dropdown.css({'min-width': this.$justify.css('width')});\n\t  }\n\n\t  if ((width + (offset.left - boundaryOffset)) > boundaryWidth) {\n\t    this.$element.addClass('am-dropdown-flip');\n\t  }\n\t};\n\n\tDropdown.prototype.clear = function() {\n\t  $('[data-am-dropdown]').not(this.$element).each(function() {\n\t    var data = $(this).data('amui.dropdown');\n\t    data && data.close();\n\t  });\n\t};\n\n\tDropdown.prototype.events = function() {\n\t  var eventNS = 'dropdown.amui';\n\t  // triggers = this.options.trigger.split(' '),\n\t  var $toggle = this.$toggle;\n\n\t  $toggle.on('click.' + eventNS, $.proxy(function(e) {\n\t    e.preventDefault();\n\t    this.toggle();\n\t  }, this));\n\n\t  /*for (var i = triggers.length; i--;) {\n\t   var trigger = triggers[i];\n\n\t   if (trigger === 'click') {\n\t   $toggle.on('click.' + eventNS, $.proxy(this.toggle, this))\n\t   }\n\n\t   if (trigger === 'focus' || trigger === 'hover') {\n\t   var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focusin';\n\t   var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout';\n\n\t   this.$element.on(eventIn + '.' + eventNS, $.proxy(this.open, this))\n\t   .on(eventOut + '.' + eventNS, $.proxy(this.close, this));\n\t   }\n\t   }*/\n\n\t  $(document).on('keydown.dropdown.amui', $.proxy(function(e) {\n\t    e.keyCode === 27 && this.active && this.close();\n\t  }, this)).on('click.outer.dropdown.amui', $.proxy(function(e) {\n\t    // var $target = $(e.target);\n\n\t    if (this.active &&\n\t      (this.$element[0] === e.target || !this.$element.find(e.target).length)) {\n\t      this.close();\n\t    }\n\t  }, this));\n\t};\n\n\t// Dropdown Plugin\n\tUI.plugin('dropdown', Dropdown);\n\n\t// Init code\n\tUI.ready(function(context) {\n\t  $('[data-am-dropdown]', context).dropdown();\n\t});\n\n\t$(document).on('click.dropdown.amui.data-api', '.am-dropdown form',\n\t  function(e) {\n\t    e.stopPropagation();\n\t  });\n\n\tmodule.exports = UI.dropdown = Dropdown;\n\n\t// TODO: 1. 处理链接 focus\n\t//       2. 增加 mouseenter / mouseleave 选项\n\t//       3. 宽度适应\n\n\n/***/ },\n/* 11 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t/* WEBPACK VAR INJECTION */(function(setImmediate) {var $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\n\t// MODIFIED:\n\t// - LINE 252: add `<i></i>`\n\t// - namespace\n\t// - Init code\n\t// TODO: start after x ms when pause on actions\n\n\t/*\n\t * jQuery FlexSlider v2.6.0\n\t * Copyright 2012 WooThemes\n\t * Contributing Author: Tyler Smith\n\t */\n\n\tvar focused = true;\n\n\t// FlexSlider: Object Instance\n\t$.flexslider = function(el, options) {\n\t  var slider = $(el);\n\n\t  // making variables public\n\t  slider.vars = $.extend({}, $.flexslider.defaults, options);\n\n\t  var namespace = slider.vars.namespace,\n\t    msGesture = window.navigator && window.navigator.msPointerEnabled && window.MSGesture,\n\t    touch = (( \"ontouchstart\" in window ) || msGesture || window.DocumentTouch && document instanceof DocumentTouch) && slider.vars.touch,\n\t  // depricating this idea, as devices are being released with both of these events\n\t    eventType = \"click touchend MSPointerUp keyup\",\n\t    watchedEvent = \"\",\n\t    watchedEventClearTimer,\n\t    vertical = slider.vars.direction === \"vertical\",\n\t    reverse = slider.vars.reverse,\n\t    carousel = (slider.vars.itemWidth > 0),\n\t    fade = slider.vars.animation === \"fade\",\n\t    asNav = slider.vars.asNavFor !== \"\",\n\t    methods = {};\n\n\t  // Store a reference to the slider object\n\t  $.data(el, 'flexslider', slider);\n\n\t  // Private slider methods\n\t  methods = {\n\t    init: function() {\n\t      slider.animating = false;\n\t      // Get current slide and make sure it is a number\n\t      slider.currentSlide = parseInt((slider.vars.startAt ? slider.vars.startAt : 0), 10);\n\t      if (isNaN(slider.currentSlide)) {\n\t        slider.currentSlide = 0;\n\t      }\n\t      slider.animatingTo = slider.currentSlide;\n\t      slider.atEnd = (slider.currentSlide === 0 || slider.currentSlide === slider.last);\n\t      slider.containerSelector = slider.vars.selector.substr(0, slider.vars.selector.search(' '));\n\t      slider.slides = $(slider.vars.selector, slider);\n\t      slider.container = $(slider.containerSelector, slider);\n\t      slider.count = slider.slides.length;\n\t      // SYNC:\n\t      slider.syncExists = $(slider.vars.sync).length > 0;\n\t      // SLIDE:\n\t      if (slider.vars.animation === \"slide\") {\n\t        slider.vars.animation = \"swing\";\n\t      }\n\t      slider.prop = (vertical) ? \"top\" : \"marginLeft\";\n\t      slider.args = {};\n\t      // SLIDESHOW:\n\t      slider.manualPause = false;\n\t      slider.stopped = false;\n\t      //PAUSE WHEN INVISIBLE\n\t      slider.started = false;\n\t      slider.startTimeout = null;\n\t      // TOUCH/USECSS:\n\t      slider.transitions = !slider.vars.video && !fade && slider.vars.useCSS && (function() {\n\t        var obj = document.createElement('div'),\n\t          props = ['perspectiveProperty', 'WebkitPerspective', 'MozPerspective', 'OPerspective', 'msPerspective'];\n\t        for (var i in props) {\n\t          if (obj.style[props[i]] !== undefined) {\n\t            slider.pfx = props[i].replace('Perspective', '').toLowerCase();\n\t            slider.prop = \"-\" + slider.pfx + \"-transform\";\n\t            return true;\n\t          }\n\t        }\n\t        return false;\n\t      }());\n\t      slider.ensureAnimationEnd = '';\n\t      // CONTROLSCONTAINER:\n\t      if (slider.vars.controlsContainer !== \"\") slider.controlsContainer = $(slider.vars.controlsContainer).length > 0 && $(slider.vars.controlsContainer);\n\t      // MANUAL:\n\t      if (slider.vars.manualControls !== \"\") slider.manualControls = $(slider.vars.manualControls).length > 0 && $(slider.vars.manualControls);\n\n\t      // CUSTOM DIRECTION NAV:\n\t      if (slider.vars.customDirectionNav !== \"\") slider.customDirectionNav = $(slider.vars.customDirectionNav).length === 2 && $(slider.vars.customDirectionNav);\n\n\t      // RANDOMIZE:\n\t      if (slider.vars.randomize) {\n\t        slider.slides.sort(function() {\n\t          return (Math.round(Math.random()) - 0.5);\n\t        });\n\t        slider.container.empty().append(slider.slides);\n\t      }\n\n\t      slider.doMath();\n\n\t      // INIT\n\t      slider.setup(\"init\");\n\n\t      // CONTROLNAV:\n\t      if (slider.vars.controlNav) {\n\t        methods.controlNav.setup();\n\t      }\n\n\t      // DIRECTIONNAV:\n\t      if (slider.vars.directionNav) {\n\t        methods.directionNav.setup();\n\t      }\n\n\t      // KEYBOARD:\n\t      if (slider.vars.keyboard && ($(slider.containerSelector).length === 1 || slider.vars.multipleKeyboard)) {\n\t        $(document).bind('keyup', function(event) {\n\t          var keycode = event.keyCode;\n\t          if (!slider.animating && (keycode === 39 || keycode === 37)) {\n\t            var target = (keycode === 39) ? slider.getTarget('next') :\n\t              (keycode === 37) ? slider.getTarget('prev') : false;\n\t            slider.flexAnimate(target, slider.vars.pauseOnAction);\n\t          }\n\t        });\n\t      }\n\t      // MOUSEWHEEL:\n\t      if (slider.vars.mousewheel) {\n\t        slider.bind('mousewheel', function(event, delta, deltaX, deltaY) {\n\t          event.preventDefault();\n\t          var target = (delta < 0) ? slider.getTarget('next') : slider.getTarget('prev');\n\t          slider.flexAnimate(target, slider.vars.pauseOnAction);\n\t        });\n\t      }\n\n\t      // PAUSEPLAY\n\t      if (slider.vars.pausePlay) {\n\t        methods.pausePlay.setup();\n\t      }\n\n\t      //PAUSE WHEN INVISIBLE\n\t      if (slider.vars.slideshow && slider.vars.pauseInvisible) {\n\t        methods.pauseInvisible.init();\n\t      }\n\n\t      // SLIDSESHOW\n\t      if (slider.vars.slideshow) {\n\t        if (slider.vars.pauseOnHover) {\n\t          slider.hover(function() {\n\t            if (!slider.manualPlay && !slider.manualPause) {slider.pause();}\n\t          }, function() {\n\t            if (!slider.manualPause && !slider.manualPlay && !slider.stopped) {slider.play();}\n\t          });\n\t        }\n\t        // initialize animation\n\t        // If we're visible, or we don't use PageVisibility API\n\t        if (!slider.vars.pauseInvisible || !methods.pauseInvisible.isHidden()) {\n\t          (slider.vars.initDelay > 0) ? slider.startTimeout = setTimeout(slider.play, slider.vars.initDelay) : slider.play();\n\t        }\n\t      }\n\n\t      // ASNAV:\n\t      if (asNav) {methods.asNav.setup();}\n\n\t      // TOUCH\n\t      if (touch && slider.vars.touch) {methods.touch();}\n\n\t      // FADE&&SMOOTHHEIGHT || SLIDE:\n\t      if (!fade || (fade && slider.vars.smoothHeight)) {$(window).bind(\"resize orientationchange focus\", methods.resize);}\n\n\t      slider.find(\"img\").attr(\"draggable\", \"false\");\n\n\t      // API: start() Callback\n\t      setTimeout(function() {\n\t        slider.vars.start(slider);\n\t      }, 200);\n\t    },\n\t    asNav: {\n\t      setup: function() {\n\t        slider.asNav = true;\n\t        slider.animatingTo = Math.floor(slider.currentSlide / slider.move);\n\t        slider.currentItem = slider.currentSlide;\n\t        slider.slides.removeClass(namespace + \"active-slide\").eq(slider.currentItem).addClass(namespace + \"active-slide\");\n\t        if (!msGesture) {\n\t          slider.slides.on(eventType, function(e) {\n\t            e.preventDefault();\n\t            var $slide = $(this),\n\t              target = $slide.index();\n\t            var posFromLeft = $slide.offset().left - $(slider).scrollLeft(); // Find position of slide relative to left of slider container\n\t            if (posFromLeft <= 0 && $slide.hasClass(namespace + 'active-slide')) {\n\t              slider.flexAnimate(slider.getTarget(\"prev\"), true);\n\t            } else if (!$(slider.vars.asNavFor).data('flexslider').animating && !$slide.hasClass(namespace + \"active-slide\")) {\n\t              slider.direction = (slider.currentItem < target) ? \"next\" : \"prev\";\n\t              slider.flexAnimate(target, slider.vars.pauseOnAction, false, true, true);\n\t            }\n\t          });\n\t        } else {\n\t          el._slider = slider;\n\t          slider.slides.each(function() {\n\t            var that = this;\n\t            that._gesture = new MSGesture();\n\t            that._gesture.target = that;\n\t            that.addEventListener(\"MSPointerDown\", function(e) {\n\t              e.preventDefault();\n\t              if (e.currentTarget._gesture) {\n\t                e.currentTarget._gesture.addPointer(e.pointerId);\n\t              }\n\t            }, false);\n\t            that.addEventListener(\"MSGestureTap\", function(e) {\n\t              e.preventDefault();\n\t              var $slide = $(this),\n\t                target = $slide.index();\n\t              if (!$(slider.vars.asNavFor).data('flexslider').animating && !$slide.hasClass('active')) {\n\t                slider.direction = (slider.currentItem < target) ? \"next\" : \"prev\";\n\t                slider.flexAnimate(target, slider.vars.pauseOnAction, false, true, true);\n\t              }\n\t            });\n\t          });\n\t        }\n\t      }\n\t    },\n\t    controlNav: {\n\t      setup: function() {\n\t        if (!slider.manualControls) {\n\t          methods.controlNav.setupPaging();\n\t        } else { // MANUALCONTROLS:\n\t          methods.controlNav.setupManual();\n\t        }\n\t      },\n\t      setupPaging: function() {\n\t        var type = (slider.vars.controlNav === \"thumbnails\") ? 'control-thumbs' : 'control-paging',\n\t          j = 1,\n\t          item,\n\t          slide;\n\n\t        slider.controlNavScaffold = $('<ol class=\"' + namespace + 'control-nav ' + namespace + type + '\"></ol>');\n\n\t        if (slider.pagingCount > 1) {\n\t          for (var i = 0; i < slider.pagingCount; i++) {\n\t            slide = slider.slides.eq(i);\n\t            if (undefined === slide.attr('data-thumb-alt')) {\n\t              slide.attr('data-thumb-alt', '');\n\t            }\n\t            altText = ( '' !== slide.attr('data-thumb-alt') ) ? altText = ' alt=\"' + slide.attr('data-thumb-alt') + '\"' : '';\n\t            item = (slider.vars.controlNav === \"thumbnails\") ? '<img src=\"' + slide.attr( 'data-thumb' ) + '\"' + altText + '/>' : '<a href=\"#\">' + j + '</a>';\n\t            if ('thumbnails' === slider.vars.controlNav && true === slider.vars.thumbCaptions) {\n\t              var captn = slide.attr('data-thumbcaption');\n\t              if ('' !== captn && undefined !== captn) {item += '<span class=\"' + namespace + 'caption\">' + captn + '</span>';}\n\t            }\n\t            // slider.controlNavScaffold.append('<li>' + item + '</li>');\n\t            slider.controlNavScaffold.append('<li>' + item + '<i></i></li>');\n\t            j++;\n\t          }\n\t        }\n\n\t        // CONTROLSCONTAINER:\n\t        (slider.controlsContainer) ? $(slider.controlsContainer).append(slider.controlNavScaffold) : slider.append(slider.controlNavScaffold);\n\t        methods.controlNav.set();\n\n\t        methods.controlNav.active();\n\n\t        slider.controlNavScaffold.delegate('a, img', eventType, function(event) {\n\t          event.preventDefault();\n\n\t          if (watchedEvent === \"\" || watchedEvent === event.type) {\n\t            var $this = $(this),\n\t              target = slider.controlNav.index($this);\n\n\t            if (!$this.hasClass(namespace + 'active')) {\n\t              slider.direction = (target > slider.currentSlide) ? \"next\" : \"prev\";\n\t              slider.flexAnimate(target, slider.vars.pauseOnAction);\n\t            }\n\t          }\n\n\t          // setup flags to prevent event duplication\n\t          if (watchedEvent === \"\") {\n\t            watchedEvent = event.type;\n\t          }\n\t          methods.setToClearWatchedEvent();\n\n\t        });\n\t      },\n\t      setupManual: function() {\n\t        slider.controlNav = slider.manualControls;\n\t        methods.controlNav.active();\n\n\t        slider.controlNav.bind(eventType, function(event) {\n\t          event.preventDefault();\n\n\t          if (watchedEvent === \"\" || watchedEvent === event.type) {\n\t            var $this = $(this),\n\t              target = slider.controlNav.index($this);\n\n\t            if (!$this.hasClass(namespace + 'active')) {\n\t              (target > slider.currentSlide) ? slider.direction = \"next\" : slider.direction = \"prev\";\n\t              slider.flexAnimate(target, slider.vars.pauseOnAction);\n\t            }\n\t          }\n\n\t          // setup flags to prevent event duplication\n\t          if (watchedEvent === \"\") {\n\t            watchedEvent = event.type;\n\t          }\n\t          methods.setToClearWatchedEvent();\n\t        });\n\t      },\n\t      set: function() {\n\t        var selector = (slider.vars.controlNav === \"thumbnails\") ? 'img' : 'a';\n\t        slider.controlNav = $('.' + namespace + 'control-nav li ' + selector, (slider.controlsContainer) ? slider.controlsContainer : slider);\n\t      },\n\t      active: function() {\n\t        slider.controlNav.removeClass(namespace + \"active\").eq(slider.animatingTo).addClass(namespace + \"active\");\n\t      },\n\t      update: function(action, pos) {\n\t        if (slider.pagingCount > 1 && action === \"add\") {\n\t          slider.controlNavScaffold.append($('<li><a href=\"#\">' + slider.count + '</a></li>'));\n\t        } else if (slider.pagingCount === 1) {\n\t          slider.controlNavScaffold.find('li').remove();\n\t        } else {\n\t          slider.controlNav.eq(pos).closest('li').remove();\n\t        }\n\t        methods.controlNav.set();\n\t        (slider.pagingCount > 1 && slider.pagingCount !== slider.controlNav.length) ? slider.update(pos, action) : methods.controlNav.active();\n\t      }\n\t    },\n\t    directionNav: {\n\t      setup: function() {\n\t        var directionNavScaffold = $('<ul class=\"' + namespace + 'direction-nav\"><li class=\"' + namespace + 'nav-prev\"><a class=\"' + namespace + 'prev\" href=\"#\">' + slider.vars.prevText + '</a></li><li class=\"' + namespace + 'nav-next\"><a class=\"' + namespace + 'next\" href=\"#\">' + slider.vars.nextText + '</a></li></ul>');\n\n\t        // CUSTOM DIRECTION NAV:\n\t        if (slider.customDirectionNav) {\n\t          slider.directionNav = slider.customDirectionNav;\n\t        } else if (slider.controlsContainer) { // CONTROLSCONTAINER:\n\t          $(slider.controlsContainer).append(directionNavScaffold);\n\t          slider.directionNav = $('.' + namespace + 'direction-nav li a', slider.controlsContainer);\n\t        } else {\n\t          slider.append(directionNavScaffold);\n\t          slider.directionNav = $('.' + namespace + 'direction-nav li a', slider);\n\t        }\n\n\t        methods.directionNav.update();\n\n\t        slider.directionNav.bind(eventType, function(event) {\n\t          event.preventDefault();\n\t          var target;\n\n\t          if (watchedEvent === \"\" || watchedEvent === event.type) {\n\t            target = ($(this).hasClass(namespace + 'next')) ? slider.getTarget('next') : slider.getTarget('prev');\n\t            slider.flexAnimate(target, slider.vars.pauseOnAction);\n\t          }\n\n\t          // setup flags to prevent event duplication\n\t          if (watchedEvent === \"\") {\n\t            watchedEvent = event.type;\n\t          }\n\t          methods.setToClearWatchedEvent();\n\t        });\n\t      },\n\t      update: function() {\n\t        var disabledClass = namespace + 'disabled';\n\t        if (slider.pagingCount === 1) {\n\t          slider.directionNav.addClass(disabledClass).attr('tabindex', '-1');\n\t        } else if (!slider.vars.animationLoop) {\n\t          if (slider.animatingTo === 0) {\n\t            slider.directionNav.removeClass(disabledClass).filter('.' + namespace + \"prev\").addClass(disabledClass).attr('tabindex', '-1');\n\t          } else if (slider.animatingTo === slider.last) {\n\t            slider.directionNav.removeClass(disabledClass).filter('.' + namespace + \"next\").addClass(disabledClass).attr('tabindex', '-1');\n\t          } else {\n\t            slider.directionNav.removeClass(disabledClass).removeAttr('tabindex');\n\t          }\n\t        } else {\n\t          slider.directionNav.removeClass(disabledClass).removeAttr('tabindex');\n\t        }\n\t      }\n\t    },\n\t    pausePlay: {\n\t      setup: function() {\n\t        var pausePlayScaffold = $('<div class=\"' + namespace + 'pauseplay\"><a href=\"#\"></a></div>');\n\n\t        // CONTROLSCONTAINER:\n\t        if (slider.controlsContainer) {\n\t          slider.controlsContainer.append(pausePlayScaffold);\n\t          slider.pausePlay = $('.' + namespace + 'pauseplay a', slider.controlsContainer);\n\t        } else {\n\t          slider.append(pausePlayScaffold);\n\t          slider.pausePlay = $('.' + namespace + 'pauseplay a', slider);\n\t        }\n\n\t        methods.pausePlay.update((slider.vars.slideshow) ? namespace + 'pause' : namespace + 'play');\n\n\t        slider.pausePlay.bind(eventType, function(event) {\n\t          event.preventDefault();\n\n\t          if (watchedEvent === \"\" || watchedEvent === event.type) {\n\t            if ($(this).hasClass(namespace + 'pause')) {\n\t              slider.manualPause = true;\n\t              slider.manualPlay = false;\n\t              slider.pause();\n\t            } else {\n\t              slider.manualPause = false;\n\t              slider.manualPlay = true;\n\t              slider.play();\n\t            }\n\t          }\n\n\t          // setup flags to prevent event duplication\n\t          if (watchedEvent === \"\") {\n\t            watchedEvent = event.type;\n\t          }\n\t          methods.setToClearWatchedEvent();\n\t        });\n\t      },\n\t      update: function(state) {\n\t        (state === \"play\") ? slider.pausePlay.removeClass(namespace + 'pause').addClass(namespace + 'play').html(slider.vars.playText) : slider.pausePlay.removeClass(namespace + 'play').addClass(namespace + 'pause').html(slider.vars.pauseText);\n\t      }\n\t    },\n\t    touch: function() {\n\t      var startX,\n\t        startY,\n\t        offset,\n\t        cwidth,\n\t        dx,\n\t        startT,\n\t        onTouchStart,\n\t        onTouchMove,\n\t        onTouchEnd,\n\t        scrolling = false,\n\t        localX = 0,\n\t        localY = 0,\n\t        accDx = 0;\n\n\t      if (!msGesture) {\n\t        onTouchStart = function(e) {\n\t          if (slider.animating) {\n\t            e.preventDefault();\n\t          } else if (( window.navigator.msPointerEnabled ) || e.touches.length === 1) {\n\t            slider.pause();\n\t            // CAROUSEL:\n\t            cwidth = (vertical) ? slider.h : slider.w;\n\t            startT = Number(new Date());\n\t            // CAROUSEL:\n\n\t            // Local vars for X and Y points.\n\t            localX = e.touches[0].pageX;\n\t            localY = e.touches[0].pageY;\n\n\t            offset = (carousel && reverse && slider.animatingTo === slider.last) ? 0 :\n\t              (carousel && reverse) ? slider.limit - (((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.animatingTo) :\n\t                (carousel && slider.currentSlide === slider.last) ? slider.limit :\n\t                  (carousel) ? ((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.currentSlide :\n\t                    (reverse) ? (slider.last - slider.currentSlide + slider.cloneOffset) * cwidth : (slider.currentSlide + slider.cloneOffset) * cwidth;\n\t            startX = (vertical) ? localY : localX;\n\t            startY = (vertical) ? localX : localY;\n\n\t            el.addEventListener('touchmove', onTouchMove, false);\n\t            el.addEventListener('touchend', onTouchEnd, false);\n\t          }\n\t        };\n\n\t        onTouchMove = function(e) {\n\t          // Local vars for X and Y points.\n\n\t          localX = e.touches[0].pageX;\n\t          localY = e.touches[0].pageY;\n\n\t          dx = (vertical) ? startX - localY : startX - localX;\n\t          scrolling = (vertical) ? (Math.abs(dx) < Math.abs(localX - startY)) : (Math.abs(dx) < Math.abs(localY - startY));\n\n\t          var fxms = 500;\n\n\t          if (!scrolling || Number(new Date()) - startT > fxms) {\n\t            e.preventDefault();\n\t            if (!fade && slider.transitions) {\n\t              if (!slider.vars.animationLoop) {\n\t                dx = dx / ((slider.currentSlide === 0 && dx < 0 || slider.currentSlide === slider.last && dx > 0) ? (Math.abs(dx) / cwidth + 2) : 1);\n\t              }\n\t              slider.setProps(offset + dx, \"setTouch\");\n\t            }\n\t          }\n\t        };\n\n\t        onTouchEnd = function(e) {\n\t          // finish the touch by undoing the touch session\n\t          el.removeEventListener('touchmove', onTouchMove, false);\n\n\t          if (slider.animatingTo === slider.currentSlide && !scrolling && !(dx === null)) {\n\t            var updateDx = (reverse) ? -dx : dx,\n\t              target = (updateDx > 0) ? slider.getTarget('next') : slider.getTarget('prev');\n\n\t            if (slider.canAdvance(target) && (Number(new Date()) - startT < 550 && Math.abs(updateDx) > 50 || Math.abs(updateDx) > cwidth / 2)) {\n\t              slider.flexAnimate(target, slider.vars.pauseOnAction);\n\t            } else {\n\t              if (!fade) {slider.flexAnimate(slider.currentSlide, slider.vars.pauseOnAction, true);}\n\t            }\n\t          }\n\t          el.removeEventListener('touchend', onTouchEnd, false);\n\n\t          startX = null;\n\t          startY = null;\n\t          dx = null;\n\t          offset = null;\n\t        };\n\n\t        el.addEventListener('touchstart', onTouchStart, false);\n\t      } else {\n\t        el.style.msTouchAction = \"none\";\n\t        el._gesture = new MSGesture();\n\t        el._gesture.target = el;\n\t        el.addEventListener(\"MSPointerDown\", onMSPointerDown, false);\n\t        el._slider = slider;\n\t        el.addEventListener(\"MSGestureChange\", onMSGestureChange, false);\n\t        el.addEventListener(\"MSGestureEnd\", onMSGestureEnd, false);\n\n\t        function onMSPointerDown(e) {\n\t          e.stopPropagation();\n\t          if (slider.animating) {\n\t            e.preventDefault();\n\t          } else {\n\t            slider.pause();\n\t            el._gesture.addPointer(e.pointerId);\n\t            accDx = 0;\n\t            cwidth = (vertical) ? slider.h : slider.w;\n\t            startT = Number(new Date());\n\t            // CAROUSEL:\n\n\t            offset = (carousel && reverse && slider.animatingTo === slider.last) ? 0 :\n\t              (carousel && reverse) ? slider.limit - (((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.animatingTo) :\n\t                (carousel && slider.currentSlide === slider.last) ? slider.limit :\n\t                  (carousel) ? ((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.currentSlide :\n\t                    (reverse) ? (slider.last - slider.currentSlide + slider.cloneOffset) * cwidth : (slider.currentSlide + slider.cloneOffset) * cwidth;\n\t          }\n\t        }\n\n\t        function onMSGestureChange(e) {\n\t          e.stopPropagation();\n\t          var slider = e.target._slider;\n\t          if (!slider) {\n\t            return;\n\t          }\n\t          var transX = -e.translationX,\n\t            transY = -e.translationY;\n\n\t          //Accumulate translations.\n\t          accDx = accDx + ((vertical) ? transY : transX);\n\t          dx = accDx;\n\t          scrolling = (vertical) ? (Math.abs(accDx) < Math.abs(-transX)) : (Math.abs(accDx) < Math.abs(-transY));\n\n\t          if (e.detail === e.MSGESTURE_FLAG_INERTIA) {\n\t            setImmediate(function() {\n\t              el._gesture.stop();\n\t            });\n\n\t            return;\n\t          }\n\n\t          if (!scrolling || Number(new Date()) - startT > 500) {\n\t            e.preventDefault();\n\t            if (!fade && slider.transitions) {\n\t              if (!slider.vars.animationLoop) {\n\t                dx = accDx / ((slider.currentSlide === 0 && accDx < 0 || slider.currentSlide === slider.last && accDx > 0) ? (Math.abs(accDx) / cwidth + 2) : 1);\n\t              }\n\t              slider.setProps(offset + dx, \"setTouch\");\n\t            }\n\t          }\n\t        }\n\n\t        function onMSGestureEnd(e) {\n\t          e.stopPropagation();\n\t          var slider = e.target._slider;\n\t          if (!slider) {\n\t            return;\n\t          }\n\t          if (slider.animatingTo === slider.currentSlide && !scrolling && !(dx === null)) {\n\t            var updateDx = (reverse) ? -dx : dx,\n\t              target = (updateDx > 0) ? slider.getTarget('next') : slider.getTarget('prev');\n\n\t            if (slider.canAdvance(target) && (Number(new Date()) - startT < 550 && Math.abs(updateDx) > 50 || Math.abs(updateDx) > cwidth / 2)) {\n\t              slider.flexAnimate(target, slider.vars.pauseOnAction);\n\t            } else {\n\t              if (!fade) {slider.flexAnimate(slider.currentSlide, slider.vars.pauseOnAction, true);}\n\t            }\n\t          }\n\n\t          startX = null;\n\t          startY = null;\n\t          dx = null;\n\t          offset = null;\n\t          accDx = 0;\n\t        }\n\t      }\n\t    },\n\t    resize: function() {\n\t      if (!slider.animating && slider.is(':visible')) {\n\t        if (!carousel) {slider.doMath()};\n\n\t        if (fade) {\n\t          // SMOOTH HEIGHT:\n\t          methods.smoothHeight();\n\t        } else if (carousel) { //CAROUSEL:\n\t          slider.slides.width(slider.computedW);\n\t          slider.update(slider.pagingCount);\n\t          slider.setProps();\n\t        }\n\t        else if (vertical) { //VERTICAL:\n\t          slider.viewport.height(slider.h);\n\t          slider.setProps(slider.h, \"setTotal\");\n\t        } else {\n\t          // SMOOTH HEIGHT:\n\t          if (slider.vars.smoothHeight) {methods.smoothHeight();}\n\t          slider.newSlides.width(slider.computedW);\n\t          slider.setProps(slider.computedW, \"setTotal\");\n\t        }\n\t      }\n\t    },\n\t    smoothHeight: function(dur) {\n\t      if (!vertical || fade) {\n\t        var $obj = (fade) ? slider : slider.viewport;\n\t        (dur) ? $obj.animate({\"height\": slider.slides.eq(slider.animatingTo).height()}, dur) : $obj.height(slider.slides.eq(slider.animatingTo).height());\n\t      }\n\t    },\n\t    sync: function(action) {\n\t      var $obj = $(slider.vars.sync).data(\"flexslider\"),\n\t        target = slider.animatingTo;\n\n\t      switch (action) {\n\t        case \"animate\":\n\t          $obj.flexAnimate(target, slider.vars.pauseOnAction, false, true);\n\t          break;\n\t        case \"play\":\n\t          if (!$obj.playing && !$obj.asNav) {\n\t            $obj.play();\n\t          }\n\t          break;\n\t        case \"pause\":\n\t          $obj.pause();\n\t          break;\n\t      }\n\t    },\n\t    uniqueID: function($clone) {\n\t      // Append _clone to current level and children elements with id attributes\n\t      $clone.filter('[id]').add($clone.find('[id]')).each(function() {\n\t        var $this = $(this);\n\t        $this.attr('id', $this.attr('id') + '_clone');\n\t      });\n\t      return $clone;\n\t    },\n\t    pauseInvisible: {\n\t      visProp: null,\n\t      init: function() {\n\t        var visProp = methods.pauseInvisible.getHiddenProp();\n\t        if (visProp) {\n\t          var evtname = visProp.replace(/[H|h]idden/,'') + 'visibilitychange';\n\t          document.addEventListener(evtname, function() {\n\t            if (methods.pauseInvisible.isHidden()) {\n\t              if(slider.startTimeout) {\n\t                clearTimeout(slider.startTimeout); //If clock is ticking, stop timer and prevent from starting while invisible\n\t              } else {\n\t                slider.pause(); //Or just pause\n\t              }\n\t            }\n\t            else {\n\t              if(slider.started) {\n\t                slider.play(); //Initiated before, just play\n\t              } else {\n\t                if (slider.vars.initDelay > 0) {\n\t                  setTimeout(slider.play, slider.vars.initDelay);\n\t                } else {\n\t                  slider.play(); //Didn't init before: simply init or wait for it\n\t                }\n\t              }\n\t            }\n\t          });\n\t        }\n\t      },\n\t      isHidden: function() {\n\t        var prop = methods.pauseInvisible.getHiddenProp();\n\t        if (!prop) {\n\t          return false;\n\t        }\n\t        return document[prop];\n\t      },\n\t      getHiddenProp: function() {\n\t        var prefixes = ['webkit','moz','ms','o'];\n\t        // if 'hidden' is natively supported just return it\n\t        if ('hidden' in document) {\n\t          return 'hidden';\n\t        }\n\t        // otherwise loop over all the known prefixes until we find one\n\t        for (var i = 0; i < prefixes.length; i++ ) {\n\t          if ((prefixes[i] + 'Hidden') in document) {\n\t            return prefixes[i] + 'Hidden';\n\t          }\n\t        }\n\t        // otherwise it's not supported\n\t        return null;\n\t      }\n\t    },\n\t    setToClearWatchedEvent: function() {\n\t      clearTimeout(watchedEventClearTimer);\n\t      watchedEventClearTimer = setTimeout(function() {\n\t        watchedEvent = \"\";\n\t      }, 3000);\n\t    }\n\t  };\n\n\t  // public methods\n\t  slider.flexAnimate = function(target, pause, override, withSync, fromNav) {\n\t    if (!slider.vars.animationLoop && target !== slider.currentSlide) {\n\t      slider.direction = (target > slider.currentSlide) ? \"next\" : \"prev\";\n\t    }\n\n\t    if (asNav && slider.pagingCount === 1) slider.direction = (slider.currentItem < target) ? \"next\" : \"prev\";\n\n\t    if (!slider.animating && (slider.canAdvance(target, fromNav) || override) && slider.is(\":visible\")) {\n\t      if (asNav && withSync) {\n\t        var master = $(slider.vars.asNavFor).data('flexslider');\n\t        slider.atEnd = target === 0 || target === slider.count - 1;\n\t        master.flexAnimate(target, true, false, true, fromNav);\n\t        slider.direction = (slider.currentItem < target) ? \"next\" : \"prev\";\n\t        master.direction = slider.direction;\n\n\t        if (Math.ceil((target + 1) / slider.visible) - 1 !== slider.currentSlide && target !== 0) {\n\t          slider.currentItem = target;\n\t          slider.slides.removeClass(namespace + \"active-slide\").eq(target).addClass(namespace + \"active-slide\");\n\t          target = Math.floor(target / slider.visible);\n\t        } else {\n\t          slider.currentItem = target;\n\t          slider.slides.removeClass(namespace + \"active-slide\").eq(target).addClass(namespace + \"active-slide\");\n\t          return false;\n\t        }\n\t      }\n\n\t      slider.animating = true;\n\t      slider.animatingTo = target;\n\n\t      // SLIDESHOW:\n\t      if (pause) {slider.pause();}\n\n\t      // API: before() animation Callback\n\t      slider.vars.before(slider);\n\n\t      // SYNC:\n\t      if (slider.syncExists && !fromNav) {methods.sync(\"animate\");}\n\n\t      // CONTROLNAV\n\t      if (slider.vars.controlNav) {methods.controlNav.active();}\n\n\t      // !CAROUSEL:\n\t      // CANDIDATE: slide active class (for add/remove slide)\n\t      if (!carousel) {slider.slides.removeClass(namespace + 'active-slide').eq(target).addClass(namespace + 'active-slide');}\n\n\t      // INFINITE LOOP:\n\t      // CANDIDATE: atEnd\n\t      slider.atEnd = target === 0 || target === slider.last;\n\n\t      // DIRECTIONNAV:\n\t      if (slider.vars.directionNav) {methods.directionNav.update();}\n\n\t      if (target === slider.last) {\n\t        // API: end() of cycle Callback\n\t        slider.vars.end(slider);\n\t        // SLIDESHOW && !INFINITE LOOP:\n\t        if (!slider.vars.animationLoop) {slider.pause();}\n\t      }\n\n\t      // SLIDE:\n\t      if (!fade) {\n\t        var dimension = (vertical) ? slider.slides.filter(':first').height() : slider.computedW,\n\t          margin, slideString, calcNext;\n\n\t        // INFINITE LOOP / REVERSE:\n\t        if (carousel) {\n\t          //margin = (slider.vars.itemWidth > slider.w) ? slider.vars.itemMargin * 2 : slider.vars.itemMargin;\n\t          margin = slider.vars.itemMargin;\n\t          calcNext = ((slider.itemW + margin) * slider.move) * slider.animatingTo;\n\t          slideString = (calcNext > slider.limit && slider.visible !== 1) ? slider.limit : calcNext;\n\t        } else if (slider.currentSlide === 0 && target === slider.count - 1 && slider.vars.animationLoop && slider.direction !== \"next\") {\n\t          slideString = (reverse) ? (slider.count + slider.cloneOffset) * dimension : 0;\n\t        } else if (slider.currentSlide === slider.last && target === 0 && slider.vars.animationLoop && slider.direction !== \"prev\") {\n\t          slideString = (reverse) ? 0 : (slider.count + 1) * dimension;\n\t        } else {\n\t          slideString = (reverse) ? ((slider.count - 1) - target + slider.cloneOffset) * dimension : (target + slider.cloneOffset) * dimension;\n\t        }\n\t        slider.setProps(slideString, \"\", slider.vars.animationSpeed);\n\t        if (slider.transitions) {\n\t          if (!slider.vars.animationLoop || !slider.atEnd) {\n\t            slider.animating = false;\n\t            slider.currentSlide = slider.animatingTo;\n\t          }\n\n\t          // Unbind previous transitionEnd events and re-bind new transitionEnd event\n\t          slider.container.unbind(\"webkitTransitionEnd transitionend\");\n\t          slider.container.bind(\"webkitTransitionEnd transitionend\", function() {\n\t            clearTimeout(slider.ensureAnimationEnd);\n\t            slider.wrapup(dimension);\n\t          });\n\n\t          // Insurance for the ever-so-fickle transitionEnd event\n\t          clearTimeout(slider.ensureAnimationEnd);\n\t          slider.ensureAnimationEnd = setTimeout(function() {\n\t            slider.wrapup(dimension);\n\t          }, slider.vars.animationSpeed + 100);\n\n\t        } else {\n\t          slider.container.animate(slider.args, slider.vars.animationSpeed, slider.vars.easing, function(){\n\t            slider.wrapup(dimension);\n\t          });\n\t        }\n\t      } else { // FADE:\n\t        if (!touch) {\n\t          //slider.slides.eq(slider.currentSlide).fadeOut(slider.vars.animationSpeed, slider.vars.easing);\n\t          //slider.slides.eq(target).fadeIn(slider.vars.animationSpeed, slider.vars.easing, slider.wrapup);\n\n\t          slider.slides.eq(slider.currentSlide).css({\"zIndex\": 1}).animate({\"opacity\": 0}, slider.vars.animationSpeed, slider.vars.easing);\n\t          slider.slides.eq(target).css({\"zIndex\": 2}).animate({\"opacity\": 1}, slider.vars.animationSpeed, slider.vars.easing, slider.wrapup);\n\n\t        } else {\n\t          slider.slides.eq(slider.currentSlide).css({\n\t            \"opacity\": 0,\n\t            \"zIndex\": 1\n\t          });\n\t          slider.slides.eq(target).css({\"opacity\": 1, \"zIndex\": 2});\n\t          slider.wrapup(dimension);\n\t        }\n\t      }\n\t      // SMOOTH HEIGHT:\n\t      if (slider.vars.smoothHeight) {methods.smoothHeight(slider.vars.animationSpeed)};\n\t    }\n\t  };\n\t  slider.wrapup = function(dimension) {\n\t    // SLIDE:\n\t    if (!fade && !carousel) {\n\t      if (slider.currentSlide === 0 && slider.animatingTo === slider.last && slider.vars.animationLoop) {\n\t        slider.setProps(dimension, \"jumpEnd\");\n\t      } else if (slider.currentSlide === slider.last && slider.animatingTo === 0 && slider.vars.animationLoop) {\n\t        slider.setProps(dimension, \"jumpStart\");\n\t      }\n\t    }\n\t    slider.animating = false;\n\t    slider.currentSlide = slider.animatingTo;\n\t    // API: after() animation Callback\n\t    slider.vars.after(slider);\n\t  };\n\n\t  // SLIDESHOW:\n\t  slider.animateSlides = function() {\n\t    if (!slider.animating && focused) {slider.flexAnimate(slider.getTarget(\"next\"));}\n\t  };\n\t  // SLIDESHOW:\n\t  slider.pause = function() {\n\t    clearInterval(slider.animatedSlides);\n\t    slider.animatedSlides = null;\n\t    slider.playing = false;\n\t    // PAUSEPLAY:\n\t    if (slider.vars.pausePlay) {methods.pausePlay.update(\"play\");}\n\t    // SYNC:\n\t    if (slider.syncExists) {methods.sync(\"pause\");}\n\t  };\n\t  // SLIDESHOW:\n\t  slider.play = function() {\n\t    if (slider.playing) {clearInterval(slider.animatedSlides);}\n\t    slider.animatedSlides = slider.animatedSlides || setInterval(slider.animateSlides, slider.vars.slideshowSpeed);\n\t    slider.started = slider.playing = true;\n\t    // PAUSEPLAY:\n\t    if (slider.vars.pausePlay) {methods.pausePlay.update(\"pause\");}\n\t    // SYNC:\n\t    if (slider.syncExists) {methods.sync(\"play\");}\n\t  };\n\t  // STOP:\n\t  slider.stop = function() {\n\t    slider.pause();\n\t    slider.stopped = true;\n\t  };\n\t  slider.canAdvance = function(target, fromNav) {\n\t    // ASNAV:\n\t    var last = (asNav) ? slider.pagingCount - 1 : slider.last;\n\t    return (fromNav) ? true :\n\t      (asNav && slider.currentItem === slider.count - 1 && target === 0 && slider.direction === \"prev\") ? true :\n\t        (asNav && slider.currentItem === 0 && target === slider.pagingCount - 1 && slider.direction !== \"next\") ? false :\n\t          (target === slider.currentSlide && !asNav) ? false :\n\t            (slider.vars.animationLoop) ? true :\n\t              (slider.atEnd && slider.currentSlide === 0 && target === last && slider.direction !== \"next\") ? false :\n\t                (slider.atEnd && slider.currentSlide === last && target === 0 && slider.direction === \"next\") ? false :\n\t                  true;\n\t  };\n\t  slider.getTarget = function(dir) {\n\t    slider.direction = dir;\n\t    if (dir === \"next\") {\n\t      return (slider.currentSlide === slider.last) ? 0 : slider.currentSlide + 1;\n\t    } else {\n\t      return (slider.currentSlide === 0) ? slider.last : slider.currentSlide - 1;\n\t    }\n\t  };\n\n\t  // SLIDE:\n\t  slider.setProps = function(pos, special, dur) {\n\t    var target = (function() {\n\t      var posCheck = (pos) ? pos : ((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.animatingTo,\n\t        posCalc = (function() {\n\t          if (carousel) {\n\t            return (special === \"setTouch\") ? pos :\n\t              (reverse && slider.animatingTo === slider.last) ? 0 :\n\t                (reverse) ? slider.limit - (((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.animatingTo) :\n\t                  (slider.animatingTo === slider.last) ? slider.limit : posCheck;\n\t          } else {\n\t            switch (special) {\n\t              case \"setTotal\":\n\t                return (reverse) ? ((slider.count - 1) - slider.currentSlide + slider.cloneOffset) * pos : (slider.currentSlide + slider.cloneOffset) * pos;\n\t              case \"setTouch\":\n\t                return (reverse) ? pos : pos;\n\t              case \"jumpEnd\":\n\t                return (reverse) ? pos : slider.count * pos;\n\t              case \"jumpStart\":\n\t                return (reverse) ? slider.count * pos : pos;\n\t              default:\n\t                return pos;\n\t            }\n\t          }\n\t        }());\n\n\t      return (posCalc * -1) + \"px\";\n\t    }());\n\n\t    if (slider.transitions) {\n\t      target = (vertical) ? \"translate3d(0,\" + target + \",0)\" : \"translate3d(\" + target + \",0,0)\";\n\t      dur = (dur !== undefined) ? (dur / 1000) + \"s\" : \"0s\";\n\t      slider.container.css(\"-\" + slider.pfx + \"-transition-duration\", dur);\n\t      slider.container.css(\"transition-duration\", dur);\n\t    }\n\n\t    slider.args[slider.prop] = target;\n\t    if (slider.transitions || dur === undefined) {slider.container.css(slider.args);}\n\n\t    slider.container.css('transform', target);\n\t  };\n\n\t  slider.setup = function(type) {\n\t    // SLIDE:\n\t    if (!fade) {\n\t      var sliderOffset, arr;\n\n\t      if (type === \"init\") {\n\t        slider.viewport = $('<div class=\"' + namespace + 'viewport\"></div>').css({\n\t          \"overflow\": \"hidden\",\n\t          \"position\": \"relative\"\n\t        }).appendTo(slider).append(slider.container);\n\t        // INFINITE LOOP:\n\t        slider.cloneCount = 0;\n\t        slider.cloneOffset = 0;\n\t        // REVERSE:\n\t        if (reverse) {\n\t          arr = $.makeArray(slider.slides).reverse();\n\t          slider.slides = $(arr);\n\t          slider.container.empty().append(slider.slides);\n\t        }\n\t      }\n\t      // INFINITE LOOP && !CAROUSEL:\n\t      if (slider.vars.animationLoop && !carousel) {\n\t        slider.cloneCount = 2;\n\t        slider.cloneOffset = 1;\n\t        // clear out old clones\n\t        if (type !== \"init\") { slider.container.find('.clone').remove(); }\n\t        slider.container.append(methods.uniqueID(slider.slides.first().clone().addClass('clone')).attr('aria-hidden', 'true'))\n\t          .prepend(methods.uniqueID(slider.slides.last().clone().addClass('clone')).attr('aria-hidden', 'true'));\n\t      }\n\t      slider.newSlides = $(slider.vars.selector, slider);\n\n\t      sliderOffset = (reverse) ? slider.count - 1 - slider.currentSlide + slider.cloneOffset : slider.currentSlide + slider.cloneOffset;\n\t      // VERTICAL:\n\t      if (vertical && !carousel) {\n\t        slider.container.height((slider.count + slider.cloneCount) * 200 + \"%\").css(\"position\", \"absolute\").width(\"100%\");\n\t        setTimeout(function() {\n\t          slider.newSlides.css({\"display\": \"block\"});\n\t          slider.doMath();\n\t          slider.viewport.height(slider.h);\n\t          slider.setProps(sliderOffset * slider.h, \"init\");\n\t        }, (type === \"init\") ? 100 : 0);\n\t      } else {\n\t        slider.container.width((slider.count + slider.cloneCount) * 200 + \"%\");\n\t        slider.setProps(sliderOffset * slider.computedW, \"init\");\n\t        setTimeout(function() {\n\t          slider.doMath();\n\t          slider.newSlides.css({\"width\": slider.computedW, \"marginRight\" : slider.computedM, \"float\": \"left\", \"display\": \"block\"});\n\n\t          // SMOOTH HEIGHT:\n\t          if (slider.vars.smoothHeight) {methods.smoothHeight();}\n\t        }, (type === \"init\") ? 100 : 0);\n\t      }\n\t    } else { // FADE:\n\t      slider.slides.css({\n\t        \"width\": \"100%\",\n\t        \"float\": \"left\",\n\t        \"marginRight\": \"-100%\",\n\t        \"position\": \"relative\"\n\t      });\n\t      if (type === \"init\") {\n\t        if (!touch) {\n\t          //slider.slides.eq(slider.currentSlide).fadeIn(slider.vars.animationSpeed, slider.vars.easing);\n\t          if (slider.vars.fadeFirstSlide == false) {\n\t            slider.slides.css({ \"opacity\": 0, \"display\": \"block\", \"zIndex\": 1 }).eq(slider.currentSlide).css({\"zIndex\": 2}).css({\"opacity\": 1});\n\t          } else {\n\t            slider.slides.css({ \"opacity\": 0, \"display\": \"block\", \"zIndex\": 1 }).eq(slider.currentSlide).css({\"zIndex\": 2}).animate({\"opacity\": 1},slider.vars.animationSpeed,slider.vars.easing);\n\t          }\n\t        } else {\n\t          slider.slides.css({ \"opacity\": 0, \"display\": \"block\", \"webkitTransition\": \"opacity \" + slider.vars.animationSpeed / 1000 + \"s ease\", \"zIndex\": 1 }).eq(slider.currentSlide).css({ \"opacity\": 1, \"zIndex\": 2});\n\t        }\n\t      }\n\t      // SMOOTH HEIGHT:\n\t      if (slider.vars.smoothHeight) {methods.smoothHeight();}\n\t    }\n\t    // !CAROUSEL:\n\t    // CANDIDATE: active slide\n\t    if (!carousel) {slider.slides.removeClass(namespace + \"active-slide\").eq(slider.currentSlide).addClass(namespace + \"active-slide\");}\n\n\t    //FlexSlider: init() Callback\n\t    slider.vars.init(slider);\n\t  };\n\n\t  slider.doMath = function() {\n\t    var slide = slider.slides.first(),\n\t      slideMargin = slider.vars.itemMargin,\n\t      minItems = slider.vars.minItems,\n\t      maxItems = slider.vars.maxItems;\n\n\t    slider.w = (slider.viewport === undefined) ? slider.width() : slider.viewport.width();\n\t    slider.h = slide.height();\n\t    slider.boxPadding = slide.outerWidth() - slide.width();\n\n\t    // CAROUSEL:\n\t    if (carousel) {\n\t      slider.itemT = slider.vars.itemWidth + slideMargin;\n\t      slider.itemM = slideMargin;\n\t      slider.minW = (minItems) ? minItems * slider.itemT : slider.w;\n\t      slider.maxW = (maxItems) ? (maxItems * slider.itemT) - slideMargin : slider.w;\n\t      slider.itemW = (slider.minW > slider.w) ? (slider.w - (slideMargin * (minItems - 1))) / minItems :\n\t        (slider.maxW < slider.w) ? (slider.w - (slideMargin * (maxItems - 1))) / maxItems :\n\t          (slider.vars.itemWidth > slider.w) ? slider.w : slider.vars.itemWidth;\n\n\t      slider.visible = Math.floor(slider.w / (slider.itemW));\n\t      slider.move = (slider.vars.move > 0 && slider.vars.move < slider.visible ) ? slider.vars.move : slider.visible;\n\t      slider.pagingCount = Math.ceil(((slider.count - slider.visible) / slider.move) + 1);\n\t      slider.last = slider.pagingCount - 1;\n\t      slider.limit = (slider.pagingCount === 1) ? 0 :\n\t        (slider.vars.itemWidth > slider.w) ? (slider.itemW * (slider.count - 1)) + (slideMargin * (slider.count - 1)) : ((slider.itemW + slideMargin) * slider.count) - slider.w - slideMargin;\n\t    } else {\n\t      slider.itemW = slider.w;\n\t      slider.itemM = slideMargin;\n\t      slider.pagingCount = slider.count;\n\t      slider.last = slider.count - 1;\n\t    }\n\t    slider.computedW = slider.itemW - slider.boxPadding;\n\t    slider.computedM = slider.itemM;\n\t  };\n\n\t  slider.update = function(pos, action) {\n\t    slider.doMath();\n\n\t    // update currentSlide and slider.animatingTo if necessary\n\t    if (!carousel) {\n\t      if (pos < slider.currentSlide) {\n\t        slider.currentSlide += 1;\n\t      } else if (pos <= slider.currentSlide && pos !== 0) {\n\t        slider.currentSlide -= 1;\n\t      }\n\t      slider.animatingTo = slider.currentSlide;\n\t    }\n\n\t    // update controlNav\n\t    if (slider.vars.controlNav && !slider.manualControls) {\n\t      if ((action === \"add\" && !carousel) || slider.pagingCount > slider.controlNav.length) {\n\t        methods.controlNav.update(\"add\");\n\t      } else if ((action === \"remove\" && !carousel) || slider.pagingCount < slider.controlNav.length) {\n\t        if (carousel && slider.currentSlide > slider.last) {\n\t          slider.currentSlide -= 1;\n\t          slider.animatingTo -= 1;\n\t        }\n\t        methods.controlNav.update(\"remove\", slider.last);\n\t      }\n\t    }\n\t    // update directionNav\n\t    if (slider.vars.directionNav) {methods.directionNav.update();}\n\n\t  };\n\n\t  slider.addSlide = function(obj, pos) {\n\t    var $obj = $(obj);\n\n\t    slider.count += 1;\n\t    slider.last = slider.count - 1;\n\n\t    // append new slide\n\t    if (vertical && reverse) {\n\t      (pos !== undefined) ? slider.slides.eq(slider.count - pos).after($obj) : slider.container.prepend($obj);\n\t    } else {\n\t      (pos !== undefined) ? slider.slides.eq(pos).before($obj) : slider.container.append($obj);\n\t    }\n\n\t    // update currentSlide, animatingTo, controlNav, and directionNav\n\t    slider.update(pos, \"add\");\n\n\t    // update slider.slides\n\t    slider.slides = $(slider.vars.selector + ':not(.clone)', slider);\n\t    // re-setup the slider to accomdate new slide\n\t    slider.setup();\n\n\t    //FlexSlider: added() Callback\n\t    slider.vars.added(slider);\n\t  };\n\t  slider.removeSlide = function(obj) {\n\t    var pos = (isNaN(obj)) ? slider.slides.index($(obj)) : obj;\n\n\t    // update count\n\t    slider.count -= 1;\n\t    slider.last = slider.count - 1;\n\n\t    // remove slide\n\t    if (isNaN(obj)) {\n\t      $(obj, slider.slides).remove();\n\t    } else {\n\t      (vertical && reverse) ? slider.slides.eq(slider.last).remove() : slider.slides.eq(obj).remove();\n\t    }\n\n\t    // update currentSlide, animatingTo, controlNav, and directionNav\n\t    slider.doMath();\n\t    slider.update(pos, \"remove\");\n\n\t    // update slider.slides\n\t    slider.slides = $(slider.vars.selector + ':not(.clone)', slider);\n\t    // re-setup the slider to accomdate new slide\n\t    slider.setup();\n\n\t    // FlexSlider: removed() Callback\n\t    slider.vars.removed(slider);\n\t  };\n\n\t  //FlexSlider: Initialize\n\t  methods.init();\n\t};\n\n\t// Ensure the slider isn't focussed if the window loses focus.\n\t$(window).blur(function(e) {\n\t  focused = false;\n\t}).focus(function(e) {\n\t  focused = true;\n\t});\n\n\t// FlexSlider: Default Settings\n\t$.flexslider.defaults = {\n\t  namespace: 'am-',             // {NEW} String: Prefix string attached to the class of every element generated by the plugin\n\t  selector: '.am-slides > li',       // {NEW} Selector: Must match a simple pattern. '{container} > {slide}' -- Ignore pattern at your own peril\n\t  animation: 'slide',              // String: Select your animation type, 'fade' or 'slide'\n\t  easing: 'swing',                // {NEW} String: Determines the easing method used in jQuery transitions. jQuery easing plugin is supported!\n\t  direction: 'horizontal',        // String: Select the sliding direction, \"horizontal\" or \"vertical\"\n\t  reverse: false,                 // {NEW} Boolean: Reverse the animation direction\n\t  animationLoop: true,            // Boolean: Should the animation loop? If false, directionNav will received \"disable\" classes at either end\n\t  smoothHeight: false,            // {NEW} Boolean: Allow height of the slider to animate smoothly in horizontal mode\n\t  startAt: 0,                     // Integer: The slide that the slider should start on. Array notation (0 = first slide)\n\t  slideshow: true,                // Boolean: Animate slider automatically\n\t  slideshowSpeed: 5000,           // Integer: Set the speed of the slideshow cycling, in milliseconds\n\t  animationSpeed: 600,            // Integer: Set the speed of animations, in milliseconds\n\t  initDelay: 0,                   // {NEW} Integer: Set an initialization delay, in milliseconds\n\t  randomize: false,               // Boolean: Randomize slide order\n\t  fadeFirstSlide: true,           // Boolean: Fade in the first slide when animation type is \"fade\"\n\t  thumbCaptions: false,           // Boolean: Whether or not to put captions on thumbnails when using the \"thumbnails\" controlNav.\n\n\t  // Usability features\n\t  pauseOnAction: true,            // Boolean: Pause the slideshow when interacting with control elements, highly recommended.\n\t  pauseOnHover: false,            // Boolean: Pause the slideshow when hovering over slider, then resume when no longer hovering\n\t  pauseInvisible: true,   \t\t// {NEW} Boolean: Pause the slideshow when tab is invisible, resume when visible. Provides better UX, lower CPU usage.\n\t  useCSS: true,                   // {NEW} Boolean: Slider will use CSS3 transitions if available\n\t  touch: true,                    // {NEW} Boolean: Allow touch swipe navigation of the slider on touch-enabled devices\n\t  video: false,                   // {NEW} Boolean: If using video in the slider, will prevent CSS3 3D Transforms to avoid graphical glitches\n\n\t  // Primary Controls\n\t  controlNav: true,               // Boolean: Create navigation for paging control of each slide? Note: Leave true for manualControls usage\n\t  directionNav: true,             // Boolean: Create navigation for previous/next navigation? (true/false)\n\t  prevText: ' ',           // String: Set the text for the \"previous\" directionNav item\n\t  nextText: ' ',               // String: Set the text for the \"next\" directionNav item\n\n\t  // Secondary Navigation\n\t  keyboard: true,                 // Boolean: Allow slider navigating via keyboard left/right keys\n\t  multipleKeyboard: false,        // {NEW} Boolean: Allow keyboard navigation to affect multiple sliders. Default behavior cuts out keyboard navigation with more than one slider present.\n\t  mousewheel: false,              // {UPDATED} Boolean: Requires jquery.mousewheel.js (https://github.com/brandonaaron/jquery-mousewheel) - Allows slider navigating via mousewheel\n\t  pausePlay: false,               // Boolean: Create pause/play dynamic element\n\t  pauseText: 'Pause',             // String: Set the text for the 'pause' pausePlay item\n\t  playText: 'Play',               // String: Set the text for the 'play' pausePlay item\n\n\t  //  Special properties\n\t  controlsContainer: '',          // {UPDATED} jQuery Object/Selector: Declare which container the navigation elements should be appended too. Default container is the FlexSlider element. Example use would be $('.flexslider-container'). Property is ignored if given element is not found.\n\t  manualControls: '',             // {UPDATED} jQuery Object/Selector: Declare custom control navigation. Examples would be $(\".flex-control-nav li\") or \"#tabs-nav li img\", etc. The number of elements in your controlNav should match the number of slides/tabs.\n\t  customDirectionNav: '',         // {NEW} jQuery Object/Selector: Custom prev / next button. Must be two jQuery elements. In order to make the events work they have to have the classes \"prev\" and \"next\" (plus namespace)\n\t  sync: '',                       // {NEW} Selector: Mirror the actions performed on this slider with another slider. Use with care.\n\t  asNavFor: '',                   // {NEW} Selector: Internal property exposed for turning the slider into a thumbnail navigation for another slider\n\n\t  // Carousel Options\n\t  itemWidth: 0,                   // {NEW} Integer: Box-model width of individual carousel items, including horizontal borders and padding.\n\t  itemMargin: 0,                  // {NEW} Integer: Margin between carousel items.\n\t  minItems: 1,                    // {NEW} Integer: Minimum number of carousel items that should be visible. Items will resize fluidly when below this.\n\t  maxItems: 0,                    // {NEW} Integer: Maxmimum number of carousel items that should be visible. Items will resize fluidly when above this limit.\n\t  move: 0,                        // {NEW} Integer: Number of carousel items that should move on animation. If 0, slider will move all visible items.\n\t  allowOneSlide: true,           // {NEW} Boolean: Whether or not to allow a slider comprised of a single slide\n\n\t  // Callback API\n\t  start: function() {\n\t  },            // Callback: function(slider) - Fires when the slider loads the first slide\n\t  before: function() {\n\t  },           // Callback: function(slider) - Fires asynchronously with each slider animation\n\t  after: function() {\n\t  },            // Callback: function(slider) - Fires after each slider animation completes\n\t  end: function() {\n\t  },              // Callback: function(slider) - Fires when the slider reaches the last slide (asynchronous)\n\t  added: function() {\n\t  },            // {NEW} Callback: function(slider) - Fires after a slide is added\n\t  removed: function() {\n\t  },           // {NEW} Callback: function(slider) - Fires after a slide is removed\n\t  init: function() {\n\t  }             // {NEW} Callback: function(slider) - Fires after the slider is initially setup\n\t};\n\n\t// FlexSlider: Plugin Function\n\t$.fn.flexslider = function(options) {\n\t  var args = Array.prototype.slice.call(arguments, 1);\n\t  if (options === undefined) {options = {};}\n\n\t  if (typeof options === 'object') {\n\t    return this.each(function() {\n\t      var $this = $(this);\n\t      var selector = (options.selector) ? options.selector : '.am-slides > li';\n\t      var $slides = $this.find(selector);\n\n\t      if (($slides.length === 1 && options.allowOneSlide === true) || $slides.length === 0) {\n\t        $slides.fadeIn(400);\n\t        if (options.start) {options.start($this);}\n\t      } else if ($this.data('flexslider') === undefined) {\n\t        new $.flexslider(this, options);\n\t      }\n\t    });\n\t  } else {\n\t    // Helper strings to quickly pecdrform functions on the slider\n\t    var $slider = $(this).data('flexslider');\n\t    var methodReturn;\n\t    switch (options) {\n\t      case 'next':\n\t        $slider.flexAnimate($slider.getTarget('next'), true);\n\t        break;\n\t      case 'prev':\n\t      case 'previous':\n\t        $slider.flexAnimate($slider.getTarget('prev'), true);\n\t        break;\n\t      default:\n\t        if (typeof options === 'number') {\n\t          $slider.flexAnimate(options, true);\n\t        } else if (typeof options === 'string') {\n\t          methodReturn = (typeof $slider[options] === 'function') ?\n\t            $slider[options].apply($slider, args) : $slider[options];\n\t        }\n\t    }\n\n\t    return methodReturn === undefined ? this : methodReturn;\n\t  }\n\t};\n\n\t// Init code\n\tUI.ready(function(context) {\n\t  $('[data-am-flexslider]', context).each(function(i, item) {\n\t    var $slider = $(item);\n\t    var options = UI.utils.parseOptions($slider.data('amFlexslider'));\n\n\t    options.before = function(slider) {\n\t      if (slider._pausedTimer) {\n\t        window.clearTimeout(slider._pausedTimer);\n\t        slider._pausedTimer = null;\n\t      }\n\t    };\n\n\t    options.after = function(slider) {\n\t      var pauseTime = slider.vars.playAfterPaused;\n\t      if (pauseTime && !isNaN(pauseTime) && !slider.playing) {\n\t        if (!slider.manualPause && !slider.manualPlay && !slider.stopped) {\n\t          slider._pausedTimer = window.setTimeout(function() {\n\t            slider.play();\n\t          }, pauseTime);\n\t        }\n\t      }\n\t    };\n\n\t    $slider.flexslider(options);\n\t  });\n\t});\n\n\tmodule.exports = $.flexslider;\n\n\t/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(12).setImmediate))\n\n/***/ },\n/* 12 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t/* WEBPACK VAR INJECTION */(function(setImmediate, clearImmediate) {var nextTick = __webpack_require__(13).nextTick;\n\tvar apply = Function.prototype.apply;\n\tvar slice = Array.prototype.slice;\n\tvar immediateIds = {};\n\tvar nextImmediateId = 0;\n\n\t// DOM APIs, for completeness\n\n\texports.setTimeout = function() {\n\t  return new Timeout(apply.call(setTimeout, window, arguments), clearTimeout);\n\t};\n\texports.setInterval = function() {\n\t  return new Timeout(apply.call(setInterval, window, arguments), clearInterval);\n\t};\n\texports.clearTimeout =\n\texports.clearInterval = function(timeout) { timeout.close(); };\n\n\tfunction Timeout(id, clearFn) {\n\t  this._id = id;\n\t  this._clearFn = clearFn;\n\t}\n\tTimeout.prototype.unref = Timeout.prototype.ref = function() {};\n\tTimeout.prototype.close = function() {\n\t  this._clearFn.call(window, this._id);\n\t};\n\n\t// Does not start the time, just sets up the members needed.\n\texports.enroll = function(item, msecs) {\n\t  clearTimeout(item._idleTimeoutId);\n\t  item._idleTimeout = msecs;\n\t};\n\n\texports.unenroll = function(item) {\n\t  clearTimeout(item._idleTimeoutId);\n\t  item._idleTimeout = -1;\n\t};\n\n\texports._unrefActive = exports.active = function(item) {\n\t  clearTimeout(item._idleTimeoutId);\n\n\t  var msecs = item._idleTimeout;\n\t  if (msecs >= 0) {\n\t    item._idleTimeoutId = setTimeout(function onTimeout() {\n\t      if (item._onTimeout)\n\t        item._onTimeout();\n\t    }, msecs);\n\t  }\n\t};\n\n\t// That's not how node.js implements it but the exposed api is the same.\n\texports.setImmediate = typeof setImmediate === \"function\" ? setImmediate : function(fn) {\n\t  var id = nextImmediateId++;\n\t  var args = arguments.length < 2 ? false : slice.call(arguments, 1);\n\n\t  immediateIds[id] = true;\n\n\t  nextTick(function onNextTick() {\n\t    if (immediateIds[id]) {\n\t      // fn.call() is faster so we optimize for the common use-case\n\t      // @see http://jsperf.com/call-apply-segu\n\t      if (args) {\n\t        fn.apply(null, args);\n\t      } else {\n\t        fn.call(null);\n\t      }\n\t      // Prevent ids from leaking\n\t      exports.clearImmediate(id);\n\t    }\n\t  });\n\n\t  return id;\n\t};\n\n\texports.clearImmediate = typeof clearImmediate === \"function\" ? clearImmediate : function(id) {\n\t  delete immediateIds[id];\n\t};\n\t/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(12).setImmediate, __webpack_require__(12).clearImmediate))\n\n/***/ },\n/* 13 */\n/***/ function(module, exports) {\n\n\t// shim for using process in browser\n\n\tvar process = module.exports = {};\n\tvar queue = [];\n\tvar draining = false;\n\tvar currentQueue;\n\tvar queueIndex = -1;\n\n\tfunction cleanUpNextTick() {\n\t    draining = false;\n\t    if (currentQueue.length) {\n\t        queue = currentQueue.concat(queue);\n\t    } else {\n\t        queueIndex = -1;\n\t    }\n\t    if (queue.length) {\n\t        drainQueue();\n\t    }\n\t}\n\n\tfunction drainQueue() {\n\t    if (draining) {\n\t        return;\n\t    }\n\t    var timeout = setTimeout(cleanUpNextTick);\n\t    draining = true;\n\n\t    var len = queue.length;\n\t    while(len) {\n\t        currentQueue = queue;\n\t        queue = [];\n\t        while (++queueIndex < len) {\n\t            if (currentQueue) {\n\t                currentQueue[queueIndex].run();\n\t            }\n\t        }\n\t        queueIndex = -1;\n\t        len = queue.length;\n\t    }\n\t    currentQueue = null;\n\t    draining = false;\n\t    clearTimeout(timeout);\n\t}\n\n\tprocess.nextTick = function (fun) {\n\t    var args = new Array(arguments.length - 1);\n\t    if (arguments.length > 1) {\n\t        for (var i = 1; i < arguments.length; i++) {\n\t            args[i - 1] = arguments[i];\n\t        }\n\t    }\n\t    queue.push(new Item(fun, args));\n\t    if (queue.length === 1 && !draining) {\n\t        setTimeout(drainQueue, 0);\n\t    }\n\t};\n\n\t// v8 likes predictible objects\n\tfunction Item(fun, array) {\n\t    this.fun = fun;\n\t    this.array = array;\n\t}\n\tItem.prototype.run = function () {\n\t    this.fun.apply(null, this.array);\n\t};\n\tprocess.title = 'browser';\n\tprocess.browser = true;\n\tprocess.env = {};\n\tprocess.argv = [];\n\tprocess.version = ''; // empty string to avoid regexp issues\n\tprocess.versions = {};\n\n\tfunction noop() {}\n\n\tprocess.on = noop;\n\tprocess.addListener = noop;\n\tprocess.once = noop;\n\tprocess.off = noop;\n\tprocess.removeListener = noop;\n\tprocess.removeAllListeners = noop;\n\tprocess.emit = noop;\n\n\tprocess.binding = function (name) {\n\t    throw new Error('process.binding is not supported');\n\t};\n\n\tprocess.cwd = function () { return '/' };\n\tprocess.chdir = function (dir) {\n\t    throw new Error('process.chdir is not supported');\n\t};\n\tprocess.umask = function() { return 0; };\n\n\n/***/ },\n/* 14 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar UI = __webpack_require__(2);\n\n\t/* jshint unused: false */\n\t/* jshint -W101, -W116, -W109 */\n\n\t/*! iScroll v5.1.3\n\t * (c) 2008-2014 Matteo Spinelli\n\t * http://cubiq.org/license\n\t */\n\n\tvar rAF = window.requestAnimationFrame ||\n\t  window.webkitRequestAnimationFrame ||\n\t  window.mozRequestAnimationFrame ||\n\t  window.oRequestAnimationFrame ||\n\t  window.msRequestAnimationFrame ||\n\t  function(callback) {\n\t    window.setTimeout(callback, 1000 / 60);\n\t  };\n\n\tvar utils = (function() {\n\t  var me = {};\n\n\t  var _elementStyle = document.createElement('div').style;\n\t  var _vendor = (function() {\n\t    var vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'],\n\t      transform,\n\t      i = 0,\n\t      l = vendors.length;\n\n\t    for (; i < l; i++) {\n\t      transform = vendors[i] + 'ransform';\n\t      if (transform in _elementStyle) return vendors[i].substr(0, vendors[i].length - 1);\n\t    }\n\n\t    return false;\n\t  })();\n\n\t  function _prefixStyle(style) {\n\t    if (_vendor === false) return false;\n\t    if (_vendor === '') return style;\n\t    return _vendor + style.charAt(0).toUpperCase() + style.substr(1);\n\t  }\n\n\t  me.getTime = Date.now || function getTime() {\n\t    return new Date().getTime();\n\t  };\n\n\t  me.extend = function(target, obj) {\n\t    for (var i in obj) {\n\t      target[i] = obj[i];\n\t    }\n\t  };\n\n\t  me.addEvent = function(el, type, fn, capture) {\n\t    el.addEventListener(type, fn, !!capture);\n\t  };\n\n\t  me.removeEvent = function(el, type, fn, capture) {\n\t    el.removeEventListener(type, fn, !!capture);\n\t  };\n\n\t  me.prefixPointerEvent = function(pointerEvent) {\n\t    return window.MSPointerEvent ?\n\t    'MSPointer' + pointerEvent.charAt(9).toUpperCase() + pointerEvent.substr(10) :\n\t      pointerEvent;\n\t  };\n\n\t  me.momentum = function(current, start, time, lowerMargin, wrapperSize, deceleration) {\n\t    var distance = current - start,\n\t      speed = Math.abs(distance) / time,\n\t      destination,\n\t      duration;\n\n\t    deceleration = deceleration === undefined ? 0.0006 : deceleration;\n\n\t    destination = current + ( speed * speed ) / ( 2 * deceleration ) * ( distance < 0 ? -1 : 1 );\n\t    duration = speed / deceleration;\n\n\t    if (destination < lowerMargin) {\n\t      destination = wrapperSize ? lowerMargin - ( wrapperSize / 2.5 * ( speed / 8 ) ) : lowerMargin;\n\t      distance = Math.abs(destination - current);\n\t      duration = distance / speed;\n\t    } else if (destination > 0) {\n\t      destination = wrapperSize ? wrapperSize / 2.5 * ( speed / 8 ) : 0;\n\t      distance = Math.abs(current) + destination;\n\t      duration = distance / speed;\n\t    }\n\n\t    return {\n\t      destination: Math.round(destination),\n\t      duration: duration\n\t    };\n\t  };\n\n\t  var _transform = _prefixStyle('transform');\n\n\t  me.extend(me, {\n\t    hasTransform: _transform !== false,\n\t    hasPerspective: _prefixStyle('perspective') in _elementStyle,\n\t    hasTouch: 'ontouchstart' in window,\n\t    hasPointer: window.PointerEvent || window.MSPointerEvent, // IE10 is prefixed\n\t    hasTransition: _prefixStyle('transition') in _elementStyle\n\t  });\n\n\t  // This should find all Android browsers lower than build 535.19 (both stock browser and webview)\n\t  me.isBadAndroid = /Android /.test(window.navigator.appVersion) && !(/Chrome\\/\\d/.test(window.navigator.appVersion));\n\n\t  me.extend(me.style = {}, {\n\t    transform: _transform,\n\t    transitionTimingFunction: _prefixStyle('transitionTimingFunction'),\n\t    transitionDuration: _prefixStyle('transitionDuration'),\n\t    transitionDelay: _prefixStyle('transitionDelay'),\n\t    transformOrigin: _prefixStyle('transformOrigin')\n\t  });\n\n\t  me.hasClass = function(e, c) {\n\t    var re = new RegExp(\"(^|\\\\s)\" + c + \"(\\\\s|$)\");\n\t    return re.test(e.className);\n\t  };\n\n\t  me.addClass = function(e, c) {\n\t    if (me.hasClass(e, c)) {\n\t      return;\n\t    }\n\n\t    var newclass = e.className.split(' ');\n\t    newclass.push(c);\n\t    e.className = newclass.join(' ');\n\t  };\n\n\t  me.removeClass = function(e, c) {\n\t    if (!me.hasClass(e, c)) {\n\t      return;\n\t    }\n\n\t    var re = new RegExp(\"(^|\\\\s)\" + c + \"(\\\\s|$)\", 'g');\n\t    e.className = e.className.replace(re, ' ');\n\t  };\n\n\t  me.offset = function(el) {\n\t    var left = -el.offsetLeft,\n\t      top = -el.offsetTop;\n\n\t    // jshint -W084\n\t    while (el = el.offsetParent) {\n\t      left -= el.offsetLeft;\n\t      top -= el.offsetTop;\n\t    }\n\t    // jshint +W084\n\n\t    return {\n\t      left: left,\n\t      top: top\n\t    };\n\t  };\n\n\t  me.preventDefaultException = function(el, exceptions) {\n\t    for (var i in exceptions) {\n\t      if (exceptions[i].test(el[i])) {\n\t        return true;\n\t      }\n\t    }\n\n\t    return false;\n\t  };\n\n\t  me.extend(me.eventType = {}, {\n\t    touchstart: 1,\n\t    touchmove: 1,\n\t    touchend: 1,\n\n\t    mousedown: 2,\n\t    mousemove: 2,\n\t    mouseup: 2,\n\n\t    pointerdown: 3,\n\t    pointermove: 3,\n\t    pointerup: 3,\n\n\t    MSPointerDown: 3,\n\t    MSPointerMove: 3,\n\t    MSPointerUp: 3\n\t  });\n\n\t  me.extend(me.ease = {}, {\n\t    quadratic: {\n\t      style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',\n\t      fn: function(k) {\n\t        return k * ( 2 - k );\n\t      }\n\t    },\n\t    circular: {\n\t      style: 'cubic-bezier(0.1, 0.57, 0.1, 1)',\t// Not properly \"circular\" but this looks better, it should be (0.075, 0.82, 0.165, 1)\n\t      fn: function(k) {\n\t        return Math.sqrt(1 - ( --k * k ));\n\t      }\n\t    },\n\t    back: {\n\t      style: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)',\n\t      fn: function(k) {\n\t        var b = 4;\n\t        return ( k = k - 1 ) * k * ( ( b + 1 ) * k + b ) + 1;\n\t      }\n\t    },\n\t    bounce: {\n\t      style: '',\n\t      fn: function(k) {\n\t        if (( k /= 1 ) < ( 1 / 2.75 )) {\n\t          return 7.5625 * k * k;\n\t        } else if (k < ( 2 / 2.75 )) {\n\t          return 7.5625 * ( k -= ( 1.5 / 2.75 ) ) * k + 0.75;\n\t        } else if (k < ( 2.5 / 2.75 )) {\n\t          return 7.5625 * ( k -= ( 2.25 / 2.75 ) ) * k + 0.9375;\n\t        } else {\n\t          return 7.5625 * ( k -= ( 2.625 / 2.75 ) ) * k + 0.984375;\n\t        }\n\t      }\n\t    },\n\t    elastic: {\n\t      style: '',\n\t      fn: function(k) {\n\t        var f = 0.22,\n\t          e = 0.4;\n\n\t        if (k === 0) {\n\t          return 0;\n\t        }\n\t        if (k == 1) {\n\t          return 1;\n\t        }\n\n\t        return ( e * Math.pow(2, -10 * k) * Math.sin(( k - f / 4 ) * ( 2 * Math.PI ) / f) + 1 );\n\t      }\n\t    }\n\t  });\n\n\t  me.tap = function(e, eventName) {\n\t    var ev = document.createEvent('Event');\n\t    ev.initEvent(eventName, true, true);\n\t    ev.pageX = e.pageX;\n\t    ev.pageY = e.pageY;\n\t    e.target.dispatchEvent(ev);\n\t  };\n\n\t  me.click = function(e) {\n\t    var target = e.target,\n\t      ev;\n\n\t    if (!(/(SELECT|INPUT|TEXTAREA)/i).test(target.tagName)) {\n\t      ev = document.createEvent('MouseEvents');\n\t      ev.initMouseEvent('click', true, true, e.view, 1,\n\t        target.screenX, target.screenY, target.clientX, target.clientY,\n\t        e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,\n\t        0, null);\n\n\t      ev._constructed = true;\n\t      target.dispatchEvent(ev);\n\t    }\n\t  };\n\n\t  return me;\n\t})();\n\n\tfunction IScroll(el, options) {\n\t  this.wrapper = typeof el == 'string' ? document.querySelector(el) : el;\n\t  this.scroller = this.wrapper.children[0];\n\t  this.scrollerStyle = this.scroller.style;\t\t// cache style for better performance\n\n\t  this.options = {\n\n\t    // INSERT POINT: OPTIONS\n\n\t    startX: 0,\n\t    startY: 0,\n\t    scrollY: true,\n\t    directionLockThreshold: 5,\n\t    momentum: true,\n\n\t    bounce: true,\n\t    bounceTime: 600,\n\t    bounceEasing: '',\n\n\t    preventDefault: true,\n\t    preventDefaultException: {tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT)$/},\n\n\t    HWCompositing: true,\n\t    useTransition: true,\n\t    useTransform: true\n\t  };\n\n\t  for (var i in options) {\n\t    this.options[i] = options[i];\n\t  }\n\n\t  // Normalize options\n\t  this.translateZ = this.options.HWCompositing && utils.hasPerspective ? ' translateZ(0)' : '';\n\n\t  this.options.useTransition = utils.hasTransition && this.options.useTransition;\n\t  this.options.useTransform = utils.hasTransform && this.options.useTransform;\n\n\t  this.options.eventPassthrough = this.options.eventPassthrough === true ? 'vertical' : this.options.eventPassthrough;\n\t  this.options.preventDefault = !this.options.eventPassthrough && this.options.preventDefault;\n\n\t  // If you want eventPassthrough I have to lock one of the axes\n\t  this.options.scrollY = this.options.eventPassthrough == 'vertical' ? false : this.options.scrollY;\n\t  this.options.scrollX = this.options.eventPassthrough == 'horizontal' ? false : this.options.scrollX;\n\n\t  // With eventPassthrough we also need lockDirection mechanism\n\t  this.options.freeScroll = this.options.freeScroll && !this.options.eventPassthrough;\n\t  this.options.directionLockThreshold = this.options.eventPassthrough ? 0 : this.options.directionLockThreshold;\n\n\t  this.options.bounceEasing = typeof this.options.bounceEasing == 'string' ? utils.ease[this.options.bounceEasing] || utils.ease.circular : this.options.bounceEasing;\n\n\t  this.options.resizePolling = this.options.resizePolling === undefined ? 60 : this.options.resizePolling;\n\n\t  if (this.options.tap === true) {\n\t    this.options.tap = 'tap';\n\t  }\n\n\t  // INSERT POINT: NORMALIZATION\n\n\t  // Some defaults\n\t  this.x = 0;\n\t  this.y = 0;\n\t  this.directionX = 0;\n\t  this.directionY = 0;\n\t  this._events = {};\n\n\t  // INSERT POINT: DEFAULTS\n\n\t  this._init();\n\t  this.refresh();\n\n\t  this.scrollTo(this.options.startX, this.options.startY);\n\t  this.enable();\n\t}\n\n\tIScroll.prototype = {\n\t  version: '5.1.3',\n\n\t  _init: function() {\n\t    this._initEvents();\n\n\t    // INSERT POINT: _init\n\n\t  },\n\n\t  destroy: function() {\n\t    this._initEvents(true);\n\n\t    this._execEvent('destroy');\n\t  },\n\n\t  _transitionEnd: function(e) {\n\t    if (e.target != this.scroller || !this.isInTransition) {\n\t      return;\n\t    }\n\n\t    this._transitionTime();\n\t    if (!this.resetPosition(this.options.bounceTime)) {\n\t      this.isInTransition = false;\n\t      this._execEvent('scrollEnd');\n\t    }\n\t  },\n\n\t  _start: function(e) {\n\t    // React to left mouse button only\n\t    if (utils.eventType[e.type] != 1) {\n\t      if (e.button !== 0) {\n\t        return;\n\t      }\n\t    }\n\n\t    if (!this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated)) {\n\t      return;\n\t    }\n\n\t    if (this.options.preventDefault && !utils.isBadAndroid && !utils.preventDefaultException(e.target, this.options.preventDefaultException)) {\n\t      e.preventDefault();\n\t    }\n\n\t    var point = e.touches ? e.touches[0] : e,\n\t      pos;\n\n\t    this.initiated = utils.eventType[e.type];\n\t    this.moved = false;\n\t    this.distX = 0;\n\t    this.distY = 0;\n\t    this.directionX = 0;\n\t    this.directionY = 0;\n\t    this.directionLocked = 0;\n\n\t    this._transitionTime();\n\n\t    this.startTime = utils.getTime();\n\n\t    if (this.options.useTransition && this.isInTransition) {\n\t      this.isInTransition = false;\n\t      pos = this.getComputedPosition();\n\t      this._translate(Math.round(pos.x), Math.round(pos.y));\n\t      this._execEvent('scrollEnd');\n\t    } else if (!this.options.useTransition && this.isAnimating) {\n\t      this.isAnimating = false;\n\t      this._execEvent('scrollEnd');\n\t    }\n\n\t    this.startX = this.x;\n\t    this.startY = this.y;\n\t    this.absStartX = this.x;\n\t    this.absStartY = this.y;\n\t    this.pointX = point.pageX;\n\t    this.pointY = point.pageY;\n\n\t    this._execEvent('beforeScrollStart');\n\t  },\n\n\t  _move: function(e) {\n\t    if (!this.enabled || utils.eventType[e.type] !== this.initiated) {\n\t      return;\n\t    }\n\n\t    if (this.options.preventDefault) {\t// increases performance on Android? TODO: check!\n\t      e.preventDefault();\n\t    }\n\n\t    var point = e.touches ? e.touches[0] : e,\n\t      deltaX = point.pageX - this.pointX,\n\t      deltaY = point.pageY - this.pointY,\n\t      timestamp = utils.getTime(),\n\t      newX, newY,\n\t      absDistX, absDistY;\n\n\t    this.pointX = point.pageX;\n\t    this.pointY = point.pageY;\n\n\t    this.distX += deltaX;\n\t    this.distY += deltaY;\n\t    absDistX = Math.abs(this.distX);\n\t    absDistY = Math.abs(this.distY);\n\n\t    // We need to move at least 10 pixels for the scrolling to initiate\n\t    if (timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10)) {\n\t      return;\n\t    }\n\n\t    // If you are scrolling in one direction lock the other\n\t    if (!this.directionLocked && !this.options.freeScroll) {\n\t      if (absDistX > absDistY + this.options.directionLockThreshold) {\n\t        this.directionLocked = 'h';\t\t// lock horizontally\n\t      } else if (absDistY >= absDistX + this.options.directionLockThreshold) {\n\t        this.directionLocked = 'v';\t\t// lock vertically\n\t      } else {\n\t        this.directionLocked = 'n';\t\t// no lock\n\t      }\n\t    }\n\n\t    if (this.directionLocked == 'h') {\n\t      if (this.options.eventPassthrough == 'vertical') {\n\t        e.preventDefault();\n\t      } else if (this.options.eventPassthrough == 'horizontal') {\n\t        this.initiated = false;\n\t        return;\n\t      }\n\n\t      deltaY = 0;\n\t    } else if (this.directionLocked == 'v') {\n\t      if (this.options.eventPassthrough == 'horizontal') {\n\t        e.preventDefault();\n\t      } else if (this.options.eventPassthrough == 'vertical') {\n\t        this.initiated = false;\n\t        return;\n\t      }\n\n\t      deltaX = 0;\n\t    }\n\n\t    deltaX = this.hasHorizontalScroll ? deltaX : 0;\n\t    deltaY = this.hasVerticalScroll ? deltaY : 0;\n\n\t    newX = this.x + deltaX;\n\t    newY = this.y + deltaY;\n\n\t    // Slow down if outside of the boundaries\n\t    if (newX > 0 || newX < this.maxScrollX) {\n\t      newX = this.options.bounce ? this.x + deltaX / 3 : newX > 0 ? 0 : this.maxScrollX;\n\t    }\n\t    if (newY > 0 || newY < this.maxScrollY) {\n\t      newY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY;\n\t    }\n\n\t    this.directionX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0;\n\t    this.directionY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0;\n\n\t    if (!this.moved) {\n\t      this._execEvent('scrollStart');\n\t    }\n\n\t    this.moved = true;\n\n\t    this._translate(newX, newY);\n\n\t    /* REPLACE START: _move */\n\n\t    if (timestamp - this.startTime > 300) {\n\t      this.startTime = timestamp;\n\t      this.startX = this.x;\n\t      this.startY = this.y;\n\t    }\n\n\t    /* REPLACE END: _move */\n\n\t  },\n\n\t  _end: function(e) {\n\t    if (!this.enabled || utils.eventType[e.type] !== this.initiated) {\n\t      return;\n\t    }\n\n\t    if (this.options.preventDefault && !utils.preventDefaultException(e.target, this.options.preventDefaultException)) {\n\t      e.preventDefault();\n\t    }\n\n\t    var point = e.changedTouches ? e.changedTouches[0] : e,\n\t      momentumX,\n\t      momentumY,\n\t      duration = utils.getTime() - this.startTime,\n\t      newX = Math.round(this.x),\n\t      newY = Math.round(this.y),\n\t      distanceX = Math.abs(newX - this.startX),\n\t      distanceY = Math.abs(newY - this.startY),\n\t      time = 0,\n\t      easing = '';\n\n\t    this.isInTransition = 0;\n\t    this.initiated = 0;\n\t    this.endTime = utils.getTime();\n\n\t    // reset if we are outside of the boundaries\n\t    if (this.resetPosition(this.options.bounceTime)) {\n\t      return;\n\t    }\n\n\t    this.scrollTo(newX, newY);\t// ensures that the last position is rounded\n\n\t    // we scrolled less than 10 pixels\n\t    if (!this.moved) {\n\t      if (this.options.tap) {\n\t        utils.tap(e, this.options.tap);\n\t      }\n\n\t      if (this.options.click) {\n\t        utils.click(e);\n\t      }\n\n\t      this._execEvent('scrollCancel');\n\t      return;\n\t    }\n\n\t    if (this._events.flick && duration < 200 && distanceX < 100 && distanceY < 100) {\n\t      this._execEvent('flick');\n\t      return;\n\t    }\n\n\t    // start momentum animation if needed\n\t    if (this.options.momentum && duration < 300) {\n\t      momentumX = this.hasHorizontalScroll ? utils.momentum(this.x, this.startX, duration, this.maxScrollX, this.options.bounce ? this.wrapperWidth : 0, this.options.deceleration) : {\n\t        destination: newX,\n\t        duration: 0\n\t      };\n\t      momentumY = this.hasVerticalScroll ? utils.momentum(this.y, this.startY, duration, this.maxScrollY, this.options.bounce ? this.wrapperHeight : 0, this.options.deceleration) : {\n\t        destination: newY,\n\t        duration: 0\n\t      };\n\t      newX = momentumX.destination;\n\t      newY = momentumY.destination;\n\t      time = Math.max(momentumX.duration, momentumY.duration);\n\t      this.isInTransition = 1;\n\t    }\n\n\t    // INSERT POINT: _end\n\n\t    if (newX != this.x || newY != this.y) {\n\t      // change easing function when scroller goes out of the boundaries\n\t      if (newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY) {\n\t        easing = utils.ease.quadratic;\n\t      }\n\n\t      this.scrollTo(newX, newY, time, easing);\n\t      return;\n\t    }\n\n\t    this._execEvent('scrollEnd');\n\t  },\n\n\t  _resize: function() {\n\t    var that = this;\n\n\t    clearTimeout(this.resizeTimeout);\n\n\t    this.resizeTimeout = setTimeout(function() {\n\t      that.refresh();\n\t    }, this.options.resizePolling);\n\t  },\n\n\t  resetPosition: function(time) {\n\t    var x = this.x,\n\t      y = this.y;\n\n\t    time = time || 0;\n\n\t    if (!this.hasHorizontalScroll || this.x > 0) {\n\t      x = 0;\n\t    } else if (this.x < this.maxScrollX) {\n\t      x = this.maxScrollX;\n\t    }\n\n\t    if (!this.hasVerticalScroll || this.y > 0) {\n\t      y = 0;\n\t    } else if (this.y < this.maxScrollY) {\n\t      y = this.maxScrollY;\n\t    }\n\n\t    if (x == this.x && y == this.y) {\n\t      return false;\n\t    }\n\n\t    this.scrollTo(x, y, time, this.options.bounceEasing);\n\n\t    return true;\n\t  },\n\n\t  disable: function() {\n\t    this.enabled = false;\n\t  },\n\n\t  enable: function() {\n\t    this.enabled = true;\n\t  },\n\n\t  refresh: function() {\n\t    var rf = this.wrapper.offsetHeight;\t\t// Force reflow\n\n\t    this.wrapperWidth = this.wrapper.clientWidth;\n\t    this.wrapperHeight = this.wrapper.clientHeight;\n\n\t    /* REPLACE START: refresh */\n\n\t    this.scrollerWidth = this.scroller.offsetWidth;\n\t    this.scrollerHeight = this.scroller.offsetHeight;\n\n\t    this.maxScrollX = this.wrapperWidth - this.scrollerWidth;\n\t    this.maxScrollY = this.wrapperHeight - this.scrollerHeight;\n\n\t    /* REPLACE END: refresh */\n\n\t    this.hasHorizontalScroll = this.options.scrollX && this.maxScrollX < 0;\n\t    this.hasVerticalScroll = this.options.scrollY && this.maxScrollY < 0;\n\n\t    if (!this.hasHorizontalScroll) {\n\t      this.maxScrollX = 0;\n\t      this.scrollerWidth = this.wrapperWidth;\n\t    }\n\n\t    if (!this.hasVerticalScroll) {\n\t      this.maxScrollY = 0;\n\t      this.scrollerHeight = this.wrapperHeight;\n\t    }\n\n\t    this.endTime = 0;\n\t    this.directionX = 0;\n\t    this.directionY = 0;\n\n\t    this.wrapperOffset = utils.offset(this.wrapper);\n\n\t    this._execEvent('refresh');\n\n\t    this.resetPosition();\n\n\t    // INSERT POINT: _refresh\n\n\t  },\n\n\t  on: function(type, fn) {\n\t    if (!this._events[type]) {\n\t      this._events[type] = [];\n\t    }\n\n\t    this._events[type].push(fn);\n\t  },\n\n\t  off: function(type, fn) {\n\t    if (!this._events[type]) {\n\t      return;\n\t    }\n\n\t    var index = this._events[type].indexOf(fn);\n\n\t    if (index > -1) {\n\t      this._events[type].splice(index, 1);\n\t    }\n\t  },\n\n\t  _execEvent: function(type) {\n\t    if (!this._events[type]) {\n\t      return;\n\t    }\n\n\t    var i = 0,\n\t      l = this._events[type].length;\n\n\t    if (!l) {\n\t      return;\n\t    }\n\n\t    for (; i < l; i++) {\n\t      this._events[type][i].apply(this, [].slice.call(arguments, 1));\n\t    }\n\t  },\n\n\t  scrollBy: function(x, y, time, easing) {\n\t    x = this.x + x;\n\t    y = this.y + y;\n\t    time = time || 0;\n\n\t    this.scrollTo(x, y, time, easing);\n\t  },\n\n\t  scrollTo: function(x, y, time, easing) {\n\t    easing = easing || utils.ease.circular;\n\n\t    this.isInTransition = this.options.useTransition && time > 0;\n\n\t    if (!time || (this.options.useTransition && easing.style)) {\n\t      this._transitionTimingFunction(easing.style);\n\t      this._transitionTime(time);\n\t      this._translate(x, y);\n\t    } else {\n\t      this._animate(x, y, time, easing.fn);\n\t    }\n\t  },\n\n\t  scrollToElement: function(el, time, offsetX, offsetY, easing) {\n\t    el = el.nodeType ? el : this.scroller.querySelector(el);\n\n\t    if (!el) {\n\t      return;\n\t    }\n\n\t    var pos = utils.offset(el);\n\n\t    pos.left -= this.wrapperOffset.left;\n\t    pos.top -= this.wrapperOffset.top;\n\n\t    // if offsetX/Y are true we center the element to the screen\n\t    if (offsetX === true) {\n\t      offsetX = Math.round(el.offsetWidth / 2 - this.wrapper.offsetWidth / 2);\n\t    }\n\t    if (offsetY === true) {\n\t      offsetY = Math.round(el.offsetHeight / 2 - this.wrapper.offsetHeight / 2);\n\t    }\n\n\t    pos.left -= offsetX || 0;\n\t    pos.top -= offsetY || 0;\n\n\t    pos.left = pos.left > 0 ? 0 : pos.left < this.maxScrollX ? this.maxScrollX : pos.left;\n\t    pos.top = pos.top > 0 ? 0 : pos.top < this.maxScrollY ? this.maxScrollY : pos.top;\n\n\t    time = time === undefined || time === null || time === 'auto' ? Math.max(Math.abs(this.x - pos.left), Math.abs(this.y - pos.top)) : time;\n\n\t    this.scrollTo(pos.left, pos.top, time, easing);\n\t  },\n\n\t  _transitionTime: function(time) {\n\t    time = time || 0;\n\n\t    this.scrollerStyle[utils.style.transitionDuration] = time + 'ms';\n\n\t    if (!time && utils.isBadAndroid) {\n\t      this.scrollerStyle[utils.style.transitionDuration] = '0.001s';\n\t    }\n\n\t    // INSERT POINT: _transitionTime\n\n\t  },\n\n\t  _transitionTimingFunction: function(easing) {\n\t    this.scrollerStyle[utils.style.transitionTimingFunction] = easing;\n\n\t    // INSERT POINT: _transitionTimingFunction\n\n\t  },\n\n\t  _translate: function(x, y) {\n\t    if (this.options.useTransform) {\n\n\t      /* REPLACE START: _translate */\n\n\t      this.scrollerStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.translateZ;\n\n\t      /* REPLACE END: _translate */\n\n\t    } else {\n\t      x = Math.round(x);\n\t      y = Math.round(y);\n\t      this.scrollerStyle.left = x + 'px';\n\t      this.scrollerStyle.top = y + 'px';\n\t    }\n\n\t    this.x = x;\n\t    this.y = y;\n\n\t    // INSERT POINT: _translate\n\n\t  },\n\n\t  _initEvents: function(remove) {\n\t    var eventType = remove ? utils.removeEvent : utils.addEvent,\n\t      target = this.options.bindToWrapper ? this.wrapper : window;\n\n\t    eventType(window, 'orientationchange', this);\n\t    eventType(window, 'resize', this);\n\n\t    if (this.options.click) {\n\t      eventType(this.wrapper, 'click', this, true);\n\t    }\n\n\t    if (!this.options.disableMouse) {\n\t      eventType(this.wrapper, 'mousedown', this);\n\t      eventType(target, 'mousemove', this);\n\t      eventType(target, 'mousecancel', this);\n\t      eventType(target, 'mouseup', this);\n\t    }\n\n\t    if (utils.hasPointer && !this.options.disablePointer) {\n\t      eventType(this.wrapper, utils.prefixPointerEvent('pointerdown'), this);\n\t      eventType(target, utils.prefixPointerEvent('pointermove'), this);\n\t      eventType(target, utils.prefixPointerEvent('pointercancel'), this);\n\t      eventType(target, utils.prefixPointerEvent('pointerup'), this);\n\t    }\n\n\t    if (utils.hasTouch && !this.options.disableTouch) {\n\t      eventType(this.wrapper, 'touchstart', this);\n\t      eventType(target, 'touchmove', this);\n\t      eventType(target, 'touchcancel', this);\n\t      eventType(target, 'touchend', this);\n\t    }\n\n\t    eventType(this.scroller, 'transitionend', this);\n\t    eventType(this.scroller, 'webkitTransitionEnd', this);\n\t    eventType(this.scroller, 'oTransitionEnd', this);\n\t    eventType(this.scroller, 'MSTransitionEnd', this);\n\t  },\n\n\t  getComputedPosition: function() {\n\t    var matrix = window.getComputedStyle(this.scroller, null),\n\t      x, y;\n\n\t    if (this.options.useTransform) {\n\t      matrix = matrix[utils.style.transform].split(')')[0].split(', ');\n\t      x = +(matrix[12] || matrix[4]);\n\t      y = +(matrix[13] || matrix[5]);\n\t    } else {\n\t      x = +matrix.left.replace(/[^-\\d.]/g, '');\n\t      y = +matrix.top.replace(/[^-\\d.]/g, '');\n\t    }\n\n\t    return {x: x, y: y};\n\t  },\n\n\t  _animate: function(destX, destY, duration, easingFn) {\n\t    var that = this,\n\t      startX = this.x,\n\t      startY = this.y,\n\t      startTime = utils.getTime(),\n\t      destTime = startTime + duration;\n\n\t    function step() {\n\t      var now = utils.getTime(),\n\t        newX, newY,\n\t        easing;\n\n\t      if (now >= destTime) {\n\t        that.isAnimating = false;\n\t        that._translate(destX, destY);\n\n\t        if (!that.resetPosition(that.options.bounceTime)) {\n\t          that._execEvent('scrollEnd');\n\t        }\n\n\t        return;\n\t      }\n\n\t      now = ( now - startTime ) / duration;\n\t      easing = easingFn(now);\n\t      newX = ( destX - startX ) * easing + startX;\n\t      newY = ( destY - startY ) * easing + startY;\n\t      that._translate(newX, newY);\n\n\t      if (that.isAnimating) {\n\t        rAF(step);\n\t      }\n\t    }\n\n\t    this.isAnimating = true;\n\t    step();\n\t  },\n\t  handleEvent: function(e) {\n\t    switch (e.type) {\n\t      case 'touchstart':\n\t      case 'pointerdown':\n\t      case 'MSPointerDown':\n\t      case 'mousedown':\n\t        this._start(e);\n\t        break;\n\t      case 'touchmove':\n\t      case 'pointermove':\n\t      case 'MSPointerMove':\n\t      case 'mousemove':\n\t        this._move(e);\n\t        break;\n\t      case 'touchend':\n\t      case 'pointerup':\n\t      case 'MSPointerUp':\n\t      case 'mouseup':\n\t      case 'touchcancel':\n\t      case 'pointercancel':\n\t      case 'MSPointerCancel':\n\t      case 'mousecancel':\n\t        this._end(e);\n\t        break;\n\t      case 'orientationchange':\n\t      case 'resize':\n\t        this._resize();\n\t        break;\n\t      case 'transitionend':\n\t      case 'webkitTransitionEnd':\n\t      case 'oTransitionEnd':\n\t      case 'MSTransitionEnd':\n\t        this._transitionEnd(e);\n\t        break;\n\t      case 'wheel':\n\t      case 'DOMMouseScroll':\n\t      case 'mousewheel':\n\t        this._wheel(e);\n\t        break;\n\t      case 'keydown':\n\t        this._key(e);\n\t        break;\n\t      case 'click':\n\t        if (!e._constructed) {\n\t          e.preventDefault();\n\t          e.stopPropagation();\n\t        }\n\t        break;\n\t    }\n\t  }\n\t};\n\n\tIScroll.utils = utils;\n\n\tmodule.exports = UI.iScroll = IScroll;\n\n\t/* jshint unused: true */\n\t/* jshint +W101, +W116, +W109 */\n\n\n/***/ },\n/* 15 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\tvar dimmer = __webpack_require__(9);\n\tvar $doc = $(document);\n\tvar supportTransition = UI.support.transition;\n\n\t/**\n\t * @reference https://github.com/nolimits4web/Framework7/blob/master/src/js/modals.js\n\t * @license https://github.com/nolimits4web/Framework7/blob/master/LICENSE\n\t */\n\n\tvar Modal = function(element, options) {\n\t  this.options = $.extend({}, Modal.DEFAULTS, options || {});\n\t  this.$element = $(element);\n\t  this.$dialog =   this.$element.find('.am-modal-dialog');\n\n\t  if (!this.$element.attr('id')) {\n\t    this.$element.attr('id', UI.utils.generateGUID('am-modal'));\n\t  }\n\n\t  this.isPopup = this.$element.hasClass('am-popup');\n\t  this.isActions = this.$element.hasClass('am-modal-actions');\n\t  this.isPrompt = this.$element.hasClass('am-modal-prompt');\n\t  this.isLoading = this.$element.hasClass('am-modal-loading');\n\t  this.active = this.transitioning = this.relatedTarget = null;\n\t  this.dimmer = this.options.dimmer ? dimmer : {\n\t    open: function() {},\n\t    close: function() {}\n\t  };\n\n\t  this.events();\n\t};\n\n\tModal.DEFAULTS = {\n\t  className: {\n\t    active: 'am-modal-active',\n\t    out: 'am-modal-out'\n\t  },\n\t  selector: {\n\t    modal: '.am-modal',\n\t    active: '.am-modal-active'\n\t  },\n\t  closeViaDimmer: true,\n\t  cancelable: true,\n\t  onConfirm: function() {\n\t  },\n\t  onCancel: function() {\n\t  },\n\t  closeOnCancel: true,\n\t  closeOnConfirm: true,\n\t  dimmer: true,\n\t  height: undefined,\n\t  width: undefined,\n\t  duration: 300, // must equal the CSS transition duration\n\t  transitionEnd: supportTransition && supportTransition.end + '.modal.amui'\n\t};\n\n\tModal.prototype.toggle = function(relatedTarget) {\n\t  return this.active ? this.close() : this.open(relatedTarget);\n\t};\n\n\tModal.prototype.open = function(relatedTarget) {\n\t  var $element = this.$element;\n\t  var options = this.options;\n\t  var isPopup = this.isPopup;\n\t  var width = options.width;\n\t  var height = options.height;\n\t  var style = {};\n\n\t  if (this.active) {\n\t    return;\n\t  }\n\n\t  if (!this.$element.length) {\n\t    return;\n\t  }\n\n\t  // callback hook\n\t  relatedTarget && (this.relatedTarget = relatedTarget);\n\n\t  // 判断如果还在动画，就先触发之前的closed事件\n\t  if (this.transitioning) {\n\t    clearTimeout($element.transitionEndTimmer);\n\t    $element.transitionEndTimmer = null;\n\t    $element.trigger(options.transitionEnd)\n\t      .off(options.transitionEnd);\n\t  }\n\n\t  isPopup && this.$element.show();\n\n\t  this.active = true;\n\n\t  $element.trigger($.Event('open.modal.amui', {relatedTarget: relatedTarget}));\n\n\t  this.dimmer.open($element);\n\n\t  $element.show().redraw();\n\n\t  // apply Modal width/height if set\n\t  if (!isPopup && !this.isActions) {\n\t    if (width) {\n\t      style.width =  parseInt(width, 10) + 'px';\n\t    }\n\n\t    if (height) {\n\t      style.height = parseInt(height, 10) + 'px';\n\t    }\n\n\t    this.$dialog.css(style);\n\t  }\n\n\t  $element\n\t    .removeClass(options.className.out)\n\t    .addClass(options.className.active);\n\n\t  this.transitioning = 1;\n\n\t  var complete = function() {\n\t    $element.trigger(\n\t      $.Event('opened.modal.amui', {relatedTarget: relatedTarget})\n\t    );\n\t    this.transitioning = 0;\n\n\t    // Prompt auto focus\n\t    if (this.isPrompt) {\n\t      this.$dialog.find('input').eq(0).focus();\n\t    }\n\t  };\n\n\t  if (!supportTransition) {\n\t    return complete.call(this);\n\t  }\n\n\t  $element\n\t    .one(options.transitionEnd, $.proxy(complete, this))\n\t    .emulateTransitionEnd(options.duration);\n\t};\n\n\tModal.prototype.close = function(relatedTarget) {\n\t  if (!this.active) {\n\t    return;\n\t  }\n\n\t  var $element = this.$element;\n\t  var options = this.options;\n\t  var isPopup = this.isPopup;\n\n\t  // 判断如果还在动画，就先触发之前的opened事件\n\t  if (this.transitioning) {\n\t    clearTimeout($element.transitionEndTimmer);\n\t    $element.transitionEndTimmer = null;\n\t    $element.trigger(options.transitionEnd).off(options.transitionEnd);\n\t    this.dimmer.close($element, true);\n\t  }\n\n\t  this.$element.trigger($.Event('close.modal.amui',\n\t    {relatedTarget: relatedTarget}));\n\n\t  this.transitioning = 1;\n\n\t  var complete = function() {\n\t    $element.trigger('closed.modal.amui');\n\t    isPopup && $element.removeClass(options.className.out);\n\t    $element.hide();\n\t    this.transitioning = 0;\n\t    // 不强制关闭 Dimmer，以便多个 Modal 可以共享 Dimmer\n\t    this.dimmer.close($element, false);\n\t    this.active = false;\n\t  };\n\n\t  $element.removeClass(options.className.active).\n\t    addClass(options.className.out);\n\n\t  if (!supportTransition) {\n\t    return complete.call(this);\n\t  }\n\n\t  $element.one(options.transitionEnd, $.proxy(complete, this))\n\t    .emulateTransitionEnd(options.duration);\n\t};\n\n\tModal.prototype.events = function() {\n\t  var options = this.options;\n\t  var _this = this;\n\t  var $element = this.$element;\n\t  var $ipt = $element.find('.am-modal-prompt-input');\n\t  var $confirm = $element.find('[data-am-modal-confirm]');\n\t  var $cancel = $element.find('[data-am-modal-cancel]');\n\t  var getData = function() {\n\t    var data = [];\n\t    $ipt.each(function() {\n\t      data.push($(this).val());\n\t    });\n\n\t    return (data.length === 0) ? undefined :\n\t      ((data.length === 1) ? data[0] : data);\n\t  };\n\n\t  // close via Esc key\n\t  if (this.options.cancelable) {\n\t    $element.on('keyup.modal.amui', function(e) {\n\t        if (_this.active && e.which === 27) {\n\t          $element.trigger('cancel.modal.amui');\n\t          _this.close();\n\t        }\n\t      });\n\t  }\n\n\t  // Close Modal when dimmer clicked\n\t  if (this.options.dimmer && this.options.closeViaDimmer && !this.isLoading) {\n\t    this.dimmer.$element.on('click.dimmer.modal.amui', function(e) {\n\t      _this.close();\n\t    });\n\t  }\n\n\t  // Close Modal when button clicked\n\t  $element.on('click.close.modal.amui', '[data-am-modal-close], .am-modal-btn', function(e) {\n\t      e.preventDefault();\n\t      var $this = $(this);\n\n\t      if ($this.is($confirm)) {\n\t        options.closeOnConfirm && _this.close();\n\t      } else if ($this.is($cancel)) {\n\t        options.closeOnCancel && _this.close();\n\t      } else {\n\t        _this.close();\n\t      }\n\t    });\n\n\t  $confirm.on('click.confirm.modal.amui',\n\t    function() {\n\t      $element.trigger($.Event('confirm.modal.amui', {\n\t        trigger: this\n\t      }));\n\t    });\n\n\t  $cancel.on('click.cancel.modal.amui', function() {\n\t      $element.trigger($.Event('cancel.modal.amui', {\n\t        trigger: this\n\t      }));\n\t    });\n\n\t  $element.on('confirm.modal.amui', function(e) {\n\t    e.data = getData();\n\t    _this.options.onConfirm.call(_this, e);\n\t  }).on('cancel.modal.amui', function(e) {\n\t    e.data = getData();\n\t    _this.options.onCancel.call(_this, e);\n\t  });\n\t};\n\n\tfunction Plugin(option, relatedTarget) {\n\t  return this.each(function() {\n\t    var $this = $(this);\n\t    var data = $this.data('amui.modal');\n\t    var options = typeof option == 'object' && option;\n\n\t    if (!data) {\n\t      $this.data('amui.modal', (data = new Modal(this, options)));\n\t    }\n\n\t    if (typeof option == 'string') {\n\t      data[option] && data[option](relatedTarget);\n\t    } else {\n\t      data.toggle(option && option.relatedTarget || undefined);\n\t    }\n\t  });\n\t}\n\n\t$.fn.modal = Plugin;\n\n\t// Init\n\t$doc.on('click.modal.amui.data-api', '[data-am-modal]', function() {\n\t  var $this = $(this);\n\t  var options = UI.utils.parseOptions($this.attr('data-am-modal'));\n\t  var $target = $(options.target ||\n\t  (this.href && this.href.replace(/.*(?=#[^\\s]+$)/, '')));\n\t  var option = $target.data('amui.modal') ? 'toggle' : options;\n\n\t  Plugin.call($target, option, this);\n\t});\n\n\tmodule.exports = UI.modal = Modal;\n\n\n/***/ },\n/* 16 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\t__webpack_require__(3);\n\n\tvar $win = $(window);\n\tvar $doc = $(document);\n\tvar scrollPos;\n\n\t/**\n\t * @via https://github.com/uikit/uikit/blob/master/src/js/offcanvas.js\n\t * @license https://github.com/uikit/uikit/blob/master/LICENSE.md\n\t */\n\n\tvar OffCanvas = function(element, options) {\n\t  this.$element = $(element);\n\t  this.options = $.extend({}, OffCanvas.DEFAULTS, options);\n\t  this.active = null;\n\t  this.bindEvents();\n\t};\n\n\tOffCanvas.DEFAULTS = {\n\t  duration: 300,\n\t  effect: 'overlay' // {push|overlay}, push is too expensive\n\t};\n\n\tOffCanvas.prototype.open = function(relatedElement) {\n\t  var _this = this;\n\t  var $element = this.$element;\n\n\t  if (!$element.length || $element.hasClass('am-active')) {\n\t    return;\n\t  }\n\n\t  var effect = this.options.effect;\n\t  var $html = $('html');\n\t  var $body = $('body');\n\t  var $bar = $element.find('.am-offcanvas-bar').first();\n\t  var dir = $bar.hasClass('am-offcanvas-bar-flip') ? -1 : 1;\n\n\t  $bar.addClass('am-offcanvas-bar-' + effect);\n\n\t  scrollPos = {x: window.scrollX, y: window.scrollY};\n\n\t  $element.addClass('am-active');\n\n\t  $body.css({\n\t    width: window.innerWidth,\n\t    height: $win.height()\n\t  }).addClass('am-offcanvas-page');\n\n\t  if (effect !== 'overlay') {\n\t    $body.css({\n\t      'margin-left': $bar.outerWidth() * dir\n\t    }).width(); // force redraw\n\t  }\n\n\t  $html.css('margin-top', scrollPos.y * -1);\n\n\t  setTimeout(function() {\n\t    $bar.addClass('am-offcanvas-bar-active').width();\n\t  }, 0);\n\n\t  $element.trigger('open.offcanvas.amui');\n\n\t  this.active = 1;\n\n\t  // Close OffCanvas when none content area clicked\n\t  $element.on('click.offcanvas.amui', function(e) {\n\t    var $target = $(e.target);\n\n\t    if ($target.hasClass('am-offcanvas-bar')) {\n\t      return;\n\t    }\n\n\t    if ($target.parents('.am-offcanvas-bar').first().length) {\n\t      return;\n\t    }\n\n\t    // https://developer.mozilla.org/zh-CN/docs/DOM/event.stopImmediatePropagation\n\t    e.stopImmediatePropagation();\n\n\t    _this.close();\n\t  });\n\n\t  $html.on('keydown.offcanvas.amui', function(e) {\n\t    (e.keyCode === 27) && _this.close();\n\t  });\n\t};\n\n\tOffCanvas.prototype.close = function(relatedElement) {\n\t  var _this = this;\n\t  var $html = $('html');\n\t  var $body = $('body');\n\t  var $element = this.$element;\n\t  var $bar = $element.find('.am-offcanvas-bar').first();\n\n\t  if (!$element.length || !this.active || !$element.hasClass('am-active')) {\n\t    return;\n\t  }\n\n\t  $element.trigger('close.offcanvas.amui');\n\n\t  function complete() {\n\t    $body\n\t      .removeClass('am-offcanvas-page')\n\t      .css({\n\t        width: '',\n\t        height: '',\n\t        'margin-left': '',\n\t        'margin-right': ''\n\t      });\n\t    $element.removeClass('am-active');\n\t    $bar.removeClass('am-offcanvas-bar-active');\n\t    $html.css('margin-top', '');\n\t    window.scrollTo(scrollPos.x, scrollPos.y);\n\t    $element.trigger('closed.offcanvas.amui');\n\t    _this.active = 0;\n\t  }\n\n\t  if (UI.support.transition) {\n\t    setTimeout(function() {\n\t      $bar.removeClass('am-offcanvas-bar-active');\n\t    }, 0);\n\n\t    $body.css('margin-left', '').one(UI.support.transition.end, function() {\n\t      complete();\n\t    }).emulateTransitionEnd(this.options.duration);\n\t  } else {\n\t    complete();\n\t  }\n\n\t  $element.off('click.offcanvas.amui');\n\t  $html.off('.offcanvas.amui');\n\t};\n\n\tOffCanvas.prototype.bindEvents = function() {\n\t  var _this = this;\n\t  $doc.on('click.offcanvas.amui', '[data-am-dismiss=\"offcanvas\"]', function(e) {\n\t      e.preventDefault();\n\t      _this.close();\n\t    });\n\n\t  $win.on('resize.offcanvas.amui orientationchange.offcanvas.amui',\n\t    function() {\n\t      _this.active && _this.close();\n\t    });\n\n\t  this.$element.hammer().on('swipeleft swipeleft', function(e) {\n\t    e.preventDefault();\n\t    _this.close();\n\t  });\n\n\t  return this;\n\t};\n\n\tfunction Plugin(option, relatedElement) {\n\t  var args = Array.prototype.slice.call(arguments, 1);\n\n\t  return this.each(function() {\n\t    var $this = $(this);\n\t    var data = $this.data('amui.offcanvas');\n\t    var options = $.extend({}, typeof option == 'object' && option);\n\n\t    if (!data) {\n\t      $this.data('amui.offcanvas', (data = new OffCanvas(this, options)));\n\t      (!option || typeof option == 'object') && data.open(relatedElement);\n\t    }\n\n\t    if (typeof option == 'string') {\n\t      data[option] && data[option].apply(data, args);\n\t    }\n\t  });\n\t}\n\n\t$.fn.offCanvas = Plugin;\n\n\t// Init code\n\t$doc.on('click.offcanvas.amui', '[data-am-offcanvas]', function(e) {\n\t  e.preventDefault();\n\t  var $this = $(this);\n\t  var options = UI.utils.parseOptions($this.data('amOffcanvas'));\n\t  var $target = $(options.target ||\n\t  (this.href && this.href.replace(/.*(?=#[^\\s]+$)/, '')));\n\t  var option = $target.data('amui.offcanvas') ? 'open' : options;\n\n\t  Plugin.call($target, option, this);\n\t});\n\n\tmodule.exports = UI.offcanvas = OffCanvas;\n\n\t// TODO: 优化动画效果\n\t// http://dbushell.github.io/Responsive-Off-Canvas-Menu/step4.html\n\n\n/***/ },\n/* 17 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\n\t/**\n\t * @via https://github.com/manuelstofer/pinchzoom/blob/master/src/pinchzoom.js\n\t * @license the MIT License.\n\t */\n\n\tvar definePinchZoom = function($) {\n\t  /**\n\t   * Pinch zoom using jQuery\n\t   * @version 0.0.2\n\t   * @author Manuel Stofer <mst@rtp.ch>\n\t   * @param el\n\t   * @param options\n\t   * @constructor\n\t   */\n\t  var PinchZoom = function(el, options) {\n\t      this.el = $(el);\n\t      this.zoomFactor = 1;\n\t      this.lastScale = 1;\n\t      this.offset = {\n\t        x: 0,\n\t        y: 0\n\t      };\n\t      this.options = $.extend({}, this.defaults, options);\n\t      this.setupMarkup();\n\t      this.bindEvents();\n\t      this.update();\n\t      // default enable.\n\t      this.enable();\n\n\t    },\n\t    sum = function(a, b) {\n\t      return a + b;\n\t    },\n\t    isCloseTo = function(value, expected) {\n\t      return value > expected - 0.01 && value < expected + 0.01;\n\t    };\n\n\t  PinchZoom.prototype = {\n\n\t    defaults: {\n\t      tapZoomFactor: 2,\n\t      zoomOutFactor: 1.3,\n\t      animationDuration: 300,\n\t      animationInterval: 5,\n\t      maxZoom: 5,\n\t      minZoom: 0.5,\n\t      lockDragAxis: false,\n\t      use2d: false,\n\t      zoomStartEventName: 'pz_zoomstart',\n\t      zoomEndEventName: 'pz_zoomend',\n\t      dragStartEventName: 'pz_dragstart',\n\t      dragEndEventName: 'pz_dragend',\n\t      doubleTapEventName: 'pz_doubletap'\n\t    },\n\n\t    /**\n\t     * Event handler for 'dragstart'\n\t     * @param event\n\t     */\n\t    handleDragStart: function(event) {\n\t      this.el.trigger(this.options.dragStartEventName);\n\t      this.stopAnimation();\n\t      this.lastDragPosition = false;\n\t      this.hasInteraction = true;\n\t      this.handleDrag(event);\n\t    },\n\n\t    /**\n\t     * Event handler for 'drag'\n\t     * @param event\n\t     */\n\t    handleDrag: function(event) {\n\n\t      if (this.zoomFactor > 1.0) {\n\t        var touch = this.getTouches(event)[0];\n\t        this.drag(touch, this.lastDragPosition);\n\t        this.offset = this.sanitizeOffset(this.offset);\n\t        this.lastDragPosition = touch;\n\t      }\n\t    },\n\n\t    handleDragEnd: function() {\n\t      this.el.trigger(this.options.dragEndEventName);\n\t      this.end();\n\t    },\n\n\t    /**\n\t     * Event handler for 'zoomstart'\n\t     * @param event\n\t     */\n\t    handleZoomStart: function(event) {\n\t      this.el.trigger(this.options.zoomStartEventName);\n\t      this.stopAnimation();\n\t      this.lastScale = 1;\n\t      this.nthZoom = 0;\n\t      this.lastZoomCenter = false;\n\t      this.hasInteraction = true;\n\t    },\n\n\t    /**\n\t     * Event handler for 'zoom'\n\t     * @param event\n\t     */\n\t    handleZoom: function(event, newScale) {\n\n\t      // a relative scale factor is used\n\t      var touchCenter = this.getTouchCenter(this.getTouches(event)),\n\t        scale = newScale / this.lastScale;\n\t      this.lastScale = newScale;\n\n\t      // the first touch events are thrown away since they are not precise\n\t      this.nthZoom += 1;\n\t      if (this.nthZoom > 3) {\n\n\t        this.scale(scale, touchCenter);\n\t        this.drag(touchCenter, this.lastZoomCenter);\n\t      }\n\t      this.lastZoomCenter = touchCenter;\n\t    },\n\n\t    handleZoomEnd: function() {\n\t      this.el.trigger(this.options.zoomEndEventName);\n\t      this.end();\n\t    },\n\n\t    /**\n\t     * Event handler for 'doubletap'\n\t     * @param event\n\t     */\n\t    handleDoubleTap: function(event) {\n\t      var center = this.getTouches(event)[0],\n\t        zoomFactor = this.zoomFactor > 1 ? 1 : this.options.tapZoomFactor,\n\t        startZoomFactor = this.zoomFactor,\n\t        updateProgress = (function(progress) {\n\t          this.scaleTo(startZoomFactor + progress * (zoomFactor - startZoomFactor), center);\n\t        }).bind(this);\n\n\t      if (this.hasInteraction) {\n\t        return;\n\t      }\n\t      if (startZoomFactor > zoomFactor) {\n\t        center = this.getCurrentZoomCenter();\n\t      }\n\n\t      this.animate(this.options.animationDuration, this.options.animationInterval, updateProgress, this.swing);\n\t      this.el.trigger(this.options.doubleTapEventName);\n\t    },\n\n\t    /**\n\t     * Max / min values for the offset\n\t     * @param offset\n\t     * @return {Object} the sanitized offset\n\t     */\n\t    sanitizeOffset: function(offset) {\n\t      var maxX = (this.zoomFactor - 1) * this.getContainerX(),\n\t        maxY = (this.zoomFactor - 1) * this.getContainerY(),\n\t        maxOffsetX = Math.max(maxX, 0),\n\t        maxOffsetY = Math.max(maxY, 0),\n\t        minOffsetX = Math.min(maxX, 0),\n\t        minOffsetY = Math.min(maxY, 0);\n\n\t      return {\n\t        x: Math.min(Math.max(offset.x, minOffsetX), maxOffsetX),\n\t        y: Math.min(Math.max(offset.y, minOffsetY), maxOffsetY)\n\t      };\n\t    },\n\n\t    /**\n\t     * Scale to a specific zoom factor (not relative)\n\t     * @param zoomFactor\n\t     * @param center\n\t     */\n\t    scaleTo: function(zoomFactor, center) {\n\t      this.scale(zoomFactor / this.zoomFactor, center);\n\t    },\n\n\t    /**\n\t     * Scales the element from specified center\n\t     * @param scale\n\t     * @param center\n\t     */\n\t    scale: function(scale, center) {\n\t      scale = this.scaleZoomFactor(scale);\n\t      this.addOffset({\n\t        x: (scale - 1) * (center.x + this.offset.x),\n\t        y: (scale - 1) * (center.y + this.offset.y)\n\t      });\n\t    },\n\n\t    /**\n\t     * Scales the zoom factor relative to current state\n\t     * @param scale\n\t     * @return the actual scale (can differ because of max min zoom factor)\n\t     */\n\t    scaleZoomFactor: function(scale) {\n\t      var originalZoomFactor = this.zoomFactor;\n\t      this.zoomFactor *= scale;\n\t      this.zoomFactor = Math.min(this.options.maxZoom, Math.max(this.zoomFactor, this.options.minZoom));\n\t      return this.zoomFactor / originalZoomFactor;\n\t    },\n\n\t    /**\n\t     * Drags the element\n\t     * @param center\n\t     * @param lastCenter\n\t     */\n\t    drag: function(center, lastCenter) {\n\t      if (lastCenter) {\n\t        if (this.options.lockDragAxis) {\n\t          // lock scroll to position that was changed the most\n\t          if (Math.abs(center.x - lastCenter.x) > Math.abs(center.y - lastCenter.y)) {\n\t            this.addOffset({\n\t              x: -(center.x - lastCenter.x),\n\t              y: 0\n\t            });\n\t          }\n\t          else {\n\t            this.addOffset({\n\t              y: -(center.y - lastCenter.y),\n\t              x: 0\n\t            });\n\t          }\n\t        }\n\t        else {\n\t          this.addOffset({\n\t            y: -(center.y - lastCenter.y),\n\t            x: -(center.x - lastCenter.x)\n\t          });\n\t        }\n\t      }\n\t    },\n\n\t    /**\n\t     * Calculates the touch center of multiple touches\n\t     * @param touches\n\t     * @return {Object}\n\t     */\n\t    getTouchCenter: function(touches) {\n\t      return this.getVectorAvg(touches);\n\t    },\n\n\t    /**\n\t     * Calculates the average of multiple vectors (x, y values)\n\t     */\n\t    getVectorAvg: function(vectors) {\n\t      return {\n\t        x: vectors.map(function(v) {\n\t          return v.x;\n\t        }).reduce(sum) / vectors.length,\n\t        y: vectors.map(function(v) {\n\t          return v.y;\n\t        }).reduce(sum) / vectors.length\n\t      };\n\t    },\n\n\t    /**\n\t     * Adds an offset\n\t     * @param offset the offset to add\n\t     * @return return true when the offset change was accepted\n\t     */\n\t    addOffset: function(offset) {\n\t      this.offset = {\n\t        x: this.offset.x + offset.x,\n\t        y: this.offset.y + offset.y\n\t      };\n\t    },\n\n\t    sanitize: function() {\n\t      if (this.zoomFactor < this.options.zoomOutFactor) {\n\t        this.zoomOutAnimation();\n\t      } else if (this.isInsaneOffset(this.offset)) {\n\t        this.sanitizeOffsetAnimation();\n\t      }\n\t    },\n\n\t    /**\n\t     * Checks if the offset is ok with the current zoom factor\n\t     * @param offset\n\t     * @return {Boolean}\n\t     */\n\t    isInsaneOffset: function(offset) {\n\t      var sanitizedOffset = this.sanitizeOffset(offset);\n\t      return sanitizedOffset.x !== offset.x ||\n\t        sanitizedOffset.y !== offset.y;\n\t    },\n\n\t    /**\n\t     * Creates an animation moving to a sane offset\n\t     */\n\t    sanitizeOffsetAnimation: function() {\n\t      var targetOffset = this.sanitizeOffset(this.offset),\n\t        startOffset = {\n\t          x: this.offset.x,\n\t          y: this.offset.y\n\t        },\n\t        updateProgress = (function(progress) {\n\t          this.offset.x = startOffset.x + progress * (targetOffset.x - startOffset.x);\n\t          this.offset.y = startOffset.y + progress * (targetOffset.y - startOffset.y);\n\t          this.update();\n\t        }).bind(this);\n\n\t      this.animate(\n\t        this.options.animationDuration,\n\t        this.options.animationInterval,\n\t        updateProgress,\n\t        this.swing\n\t      );\n\t    },\n\n\t    /**\n\t     * Zooms back to the original position,\n\t     * (no offset and zoom factor 1)\n\t     */\n\t    zoomOutAnimation: function() {\n\t      var startZoomFactor = this.zoomFactor,\n\t        zoomFactor = 1,\n\t        center = this.getCurrentZoomCenter(),\n\t        updateProgress = (function(progress) {\n\t          this.scaleTo(startZoomFactor + progress * (zoomFactor - startZoomFactor), center);\n\t        }).bind(this);\n\n\t      this.animate(\n\t        this.options.animationDuration,\n\t        this.options.animationInterval,\n\t        updateProgress,\n\t        this.swing\n\t      );\n\t    },\n\n\t    /**\n\t     * Updates the aspect ratio\n\t     */\n\t    updateAspectRatio: function() {\n\t      // this.setContainerY(this.getContainerX() / this.getAspectRatio());\n\t      // @modified\n\t      this.setContainerY()\n\t    },\n\n\t    /**\n\t     * Calculates the initial zoom factor (for the element to fit into the container)\n\t     * @return the initial zoom factor\n\t     */\n\t    getInitialZoomFactor: function() {\n\t      // use .offsetWidth instead of width()\n\t      // because jQuery-width() return the original width but Zepto-width() will calculate width with transform.\n\t      // the same as .height()\n\t      return this.container[0].offsetWidth / this.el[0].offsetWidth;\n\t    },\n\n\t    /**\n\t     * Calculates the aspect ratio of the element\n\t     * @return the aspect ratio\n\t     */\n\t    getAspectRatio: function() {\n\t      return this.el[0].offsetWidth / this.el[0].offsetHeight;\n\t    },\n\n\t    /**\n\t     * Calculates the virtual zoom center for the current offset and zoom factor\n\t     * (used for reverse zoom)\n\t     * @return {Object} the current zoom center\n\t     */\n\t    getCurrentZoomCenter: function() {\n\n\t      // uses following formula to calculate the zoom center x value\n\t      // offset_left / offset_right = zoomcenter_x / (container_x - zoomcenter_x)\n\t      var length = this.container[0].offsetWidth * this.zoomFactor,\n\t        offsetLeft = this.offset.x,\n\t        offsetRight = length - offsetLeft - this.container[0].offsetWidth,\n\t        widthOffsetRatio = offsetLeft / offsetRight,\n\t        centerX = widthOffsetRatio * this.container[0].offsetWidth / (widthOffsetRatio + 1),\n\n\t      // the same for the zoomcenter y\n\t        height = this.container[0].offsetHeight * this.zoomFactor,\n\t        offsetTop = this.offset.y,\n\t        offsetBottom = height - offsetTop - this.container[0].offsetHeight,\n\t        heightOffsetRatio = offsetTop / offsetBottom,\n\t        centerY = heightOffsetRatio * this.container[0].offsetHeight / (heightOffsetRatio + 1);\n\n\t      // prevents division by zero\n\t      if (offsetRight === 0) {\n\t        centerX = this.container[0].offsetWidth;\n\t      }\n\t      if (offsetBottom === 0) {\n\t        centerY = this.container[0].offsetHeight;\n\t      }\n\n\t      return {\n\t        x: centerX,\n\t        y: centerY\n\t      };\n\t    },\n\n\t    canDrag: function() {\n\t      return !isCloseTo(this.zoomFactor, 1);\n\t    },\n\n\t    /**\n\t     * Returns the touches of an event relative to the container offset\n\t     * @param event\n\t     * @return array touches\n\t     */\n\t    getTouches: function(event) {\n\t      var position = this.container.offset();\n\t      return Array.prototype.slice.call(event.touches).map(function(touch) {\n\t        return {\n\t          x: touch.pageX - position.left,\n\t          y: touch.pageY - position.top\n\t        };\n\t      });\n\t    },\n\n\t    /**\n\t     * Animation loop\n\t     * does not support simultaneous animations\n\t     * @param duration\n\t     * @param interval\n\t     * @param framefn\n\t     * @param timefn\n\t     * @param callback\n\t     */\n\t    animate: function(duration, interval, framefn, timefn, callback) {\n\t      var startTime = new Date().getTime(),\n\t        renderFrame = (function() {\n\t          if (!this.inAnimation) {\n\t            return;\n\t          }\n\t          var frameTime = new Date().getTime() - startTime,\n\t            progress = frameTime / duration;\n\t          if (frameTime >= duration) {\n\t            framefn(1);\n\t            if (callback) {\n\t              callback();\n\t            }\n\t            this.update();\n\t            this.stopAnimation();\n\t            this.update();\n\t          } else {\n\t            if (timefn) {\n\t              progress = timefn(progress);\n\t            }\n\t            framefn(progress);\n\t            this.update();\n\t            setTimeout(renderFrame, interval);\n\t          }\n\t        }).bind(this);\n\t      this.inAnimation = true;\n\t      renderFrame();\n\t    },\n\n\t    /**\n\t     * Stops the animation\n\t     */\n\t    stopAnimation: function() {\n\t      this.inAnimation = false;\n\t    },\n\n\t    /**\n\t     * Swing timing function for animations\n\t     * @param p\n\t     * @return {Number}\n\t     */\n\t    swing: function(p) {\n\t      return -Math.cos(p * Math.PI) / 2 + 0.5;\n\t    },\n\n\t    getContainerX: function() {\n\t      // return this.container[0].offsetWidth;\n\t      // @modified\n\t      return window.innerWidth\n\t    },\n\n\t    getContainerY: function() {\n\t      // return this.container[0].offsetHeight;\n\t      // @modified\n\t      return window.innerHeight\n\t    },\n\n\t    setContainerY: function(y) {\n\t      // return this.container.height(y);\n\t      // @modified\n\t      var t = window.innerHeight;\n\t      return this.el.css({height: t}), this.container.height(t);\n\t    },\n\n\t    /**\n\t     * Creates the expected html structure\n\t     */\n\t    setupMarkup: function() {\n\t      this.container = $('<div class=\"pinch-zoom-container\"></div>');\n\t      this.el.before(this.container);\n\t      this.container.append(this.el);\n\n\t      this.container.css({\n\t        'overflow': 'hidden',\n\t        'position': 'relative'\n\t      });\n\n\t      // Zepto doesn't recognize `webkitTransform..` style\n\t      this.el.css({\n\t        '-webkit-transform-origin': '0% 0%',\n\t        '-moz-transform-origin': '0% 0%',\n\t        '-ms-transform-origin': '0% 0%',\n\t        '-o-transform-origin': '0% 0%',\n\t        'transform-origin': '0% 0%',\n\t        'position': 'absolute'\n\t      });\n\t    },\n\n\t    end: function() {\n\t      this.hasInteraction = false;\n\t      this.sanitize();\n\t      this.update();\n\t    },\n\n\t    /**\n\t     * Binds all required event listeners\n\t     */\n\t    bindEvents: function() {\n\t      detectGestures(this.container.get(0), this);\n\t      // Zepto and jQuery both know about `on`\n\t      $(window).on('resize', this.update.bind(this));\n\t      $(this.el).find('img').on('load', this.update.bind(this));\n\t    },\n\n\t    /**\n\t     * Updates the css values according to the current zoom factor and offset\n\t     */\n\t    update: function() {\n\n\t      if (this.updatePlaned) {\n\t        return;\n\t      }\n\t      this.updatePlaned = true;\n\n\t      setTimeout((function() {\n\t        this.updatePlaned = false;\n\t        this.updateAspectRatio();\n\n\t        var zoomFactor = this.getInitialZoomFactor() * this.zoomFactor,\n\t          offsetX = -this.offset.x / zoomFactor,\n\t          offsetY = -this.offset.y / zoomFactor,\n\t          transform3d = 'scale3d(' + zoomFactor + ', ' + zoomFactor + ',1) ' +\n\t            'translate3d(' + offsetX + 'px,' + offsetY + 'px,0px)',\n\t          transform2d = 'scale(' + zoomFactor + ', ' + zoomFactor + ') ' +\n\t            'translate(' + offsetX + 'px,' + offsetY + 'px)',\n\t          removeClone = (function() {\n\t            if (this.clone) {\n\t              this.clone.remove();\n\t              delete this.clone;\n\t            }\n\t          }).bind(this);\n\n\t        // Scale 3d and translate3d are faster (at least on ios)\n\t        // but they also reduce the quality.\n\t        // PinchZoom uses the 3d transformations during interactions\n\t        // after interactions it falls back to 2d transformations\n\t        if (!this.options.use2d || this.hasInteraction || this.inAnimation) {\n\t          this.is3d = true;\n\t          removeClone();\n\t          this.el.css({\n\t            '-webkit-transform': transform3d,\n\t            '-o-transform': transform2d,\n\t            '-ms-transform': transform2d,\n\t            '-moz-transform': transform2d,\n\t            'transform': transform3d\n\t          });\n\t        } else {\n\n\t          // When changing from 3d to 2d transform webkit has some glitches.\n\t          // To avoid this, a copy of the 3d transformed element is displayed in the\n\t          // foreground while the element is converted from 3d to 2d transform\n\t          if (this.is3d) {\n\t            this.clone = this.el.clone();\n\t            this.clone.css('pointer-events', 'none');\n\t            this.clone.appendTo(this.container);\n\t            setTimeout(removeClone, 200);\n\t          }\n\t          this.el.css({\n\t            '-webkit-transform': transform2d,\n\t            '-o-transform': transform2d,\n\t            '-ms-transform': transform2d,\n\t            '-moz-transform': transform2d,\n\t            'transform': transform2d\n\t          });\n\t          this.is3d = false;\n\t        }\n\t      }).bind(this), 0);\n\t    },\n\n\t    /**\n\t     * Enables event handling for gestures\n\t     */\n\t    enable: function() {\n\t      this.enabled = true;\n\t    },\n\n\t    /**\n\t     * Disables event handling for gestures\n\t     */\n\t    disable: function() {\n\t      this.enabled = false;\n\t    }\n\t  };\n\n\t  var detectGestures = function(el, target) {\n\t    var interaction = null,\n\t      fingers = 0,\n\t      lastTouchStart = null,\n\t      startTouches = null,\n\n\t      setInteraction = function(newInteraction, event) {\n\t        if (interaction !== newInteraction) {\n\n\t          if (interaction && !newInteraction) {\n\t            switch (interaction) {\n\t              case \"zoom\":\n\t                target.handleZoomEnd(event);\n\t                break;\n\t              case 'drag':\n\t                target.handleDragEnd(event);\n\t                break;\n\t            }\n\t          }\n\n\t          switch (newInteraction) {\n\t            case 'zoom':\n\t              target.handleZoomStart(event);\n\t              break;\n\t            case 'drag':\n\t              target.handleDragStart(event);\n\t              break;\n\t          }\n\t        }\n\t        interaction = newInteraction;\n\t      },\n\n\t      updateInteraction = function(event) {\n\t        if (fingers === 2) {\n\t          setInteraction('zoom');\n\t        } else if (fingers === 1 && target.canDrag()) {\n\t          setInteraction('drag', event);\n\t        } else {\n\t          setInteraction(null, event);\n\t        }\n\t      },\n\n\t      targetTouches = function(touches) {\n\t        return Array.prototype.slice.call(touches).map(function(touch) {\n\t          return {\n\t            x: touch.pageX,\n\t            y: touch.pageY\n\t          };\n\t        });\n\t      },\n\n\t      getDistance = function(a, b) {\n\t        var x, y;\n\t        x = a.x - b.x;\n\t        y = a.y - b.y;\n\t        return Math.sqrt(x * x + y * y);\n\t      },\n\n\t      calculateScale = function(startTouches, endTouches) {\n\t        var startDistance = getDistance(startTouches[0], startTouches[1]),\n\t          endDistance = getDistance(endTouches[0], endTouches[1]);\n\t        return endDistance / startDistance;\n\t      },\n\n\t      cancelEvent = function(event) {\n\t        event.stopPropagation();\n\t        event.preventDefault();\n\t      },\n\n\t      detectDoubleTap = function(event) {\n\t        var time = (new Date()).getTime();\n\n\t        if (fingers > 1) {\n\t          lastTouchStart = null;\n\t        }\n\n\t        if (time - lastTouchStart < 300) {\n\t          cancelEvent(event);\n\n\t          target.handleDoubleTap(event);\n\t          switch (interaction) {\n\t            case \"zoom\":\n\t              target.handleZoomEnd(event);\n\t              break;\n\t            case 'drag':\n\t              target.handleDragEnd(event);\n\t              break;\n\t          }\n\t        }\n\n\t        if (fingers === 1) {\n\t          lastTouchStart = time;\n\t        }\n\t      },\n\t      firstMove = true;\n\n\t    el.addEventListener('touchstart', function(event) {\n\t      if (target.enabled) {\n\t        firstMove = true;\n\t        fingers = event.touches.length;\n\t        detectDoubleTap(event);\n\t      }\n\t    });\n\n\t    el.addEventListener('touchmove', function(event) {\n\t      if (target.enabled) {\n\t        if (firstMove) {\n\t          updateInteraction(event);\n\t          if (interaction) {\n\t            cancelEvent(event);\n\t          }\n\t          startTouches = targetTouches(event.touches);\n\t        } else {\n\t          switch (interaction) {\n\t            case 'zoom':\n\t              target.handleZoom(event, calculateScale(startTouches, targetTouches(event.touches)));\n\t              break;\n\t            case 'drag':\n\t              target.handleDrag(event);\n\t              break;\n\t          }\n\t          if (interaction) {\n\t            cancelEvent(event);\n\t            target.update();\n\t          }\n\t        }\n\n\t        firstMove = false;\n\t      }\n\t    });\n\n\t    el.addEventListener('touchend', function(event) {\n\t      if (target.enabled) {\n\t        fingers = event.touches.length;\n\t        updateInteraction(event);\n\t      }\n\t    });\n\t  };\n\n\t  return PinchZoom;\n\t};\n\n\tmodule.exports = UI.pichzoom = definePinchZoom($);\n\n\n/***/ },\n/* 18 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\tvar $w = $(window);\n\n\t/**\n\t * @reference https://github.com/nolimits4web/Framework7/blob/master/src/js/modals.js\n\t * @license https://github.com/nolimits4web/Framework7/blob/master/LICENSE\n\t */\n\n\tvar Popover = function(element, options) {\n\t  this.options = $.extend({}, Popover.DEFAULTS, options);\n\t  this.$element = $(element);\n\t  this.active = null;\n\t  this.$popover = (this.options.target && $(this.options.target)) || null;\n\n\t  this.init();\n\t  this._bindEvents();\n\t};\n\n\tPopover.DEFAULTS = {\n\t  theme: null,\n\t  trigger: 'click',\n\t  content: '',\n\t  open: false,\n\t  target: null,\n\t  tpl: '<div class=\"am-popover\">' +\n\t    '<div class=\"am-popover-inner\"></div>' +\n\t    '<div class=\"am-popover-caret\"></div></div>'\n\t};\n\n\tPopover.prototype.init = function() {\n\t  var _this = this;\n\t  var $element = this.$element;\n\t  var $popover;\n\n\t  if (!this.options.target) {\n\t    this.$popover = this.getPopover();\n\t    this.setContent();\n\t  }\n\n\t  $popover = this.$popover;\n\n\t  $popover.appendTo($('body'));\n\n\t  this.sizePopover();\n\n\t  function sizePopover() {\n\t    _this.sizePopover();\n\t  }\n\n\t  // TODO: 监听页面内容变化，重新调整位置\n\n\t  $element.on('open.popover.amui', function() {\n\t    $(window).on('resize.popover.amui', UI.utils.debounce(sizePopover, 50));\n\t  });\n\n\t  $element.on('close.popover.amui', function() {\n\t    $(window).off('resize.popover.amui', sizePopover);\n\t  });\n\n\t  this.options.open && this.open();\n\t};\n\n\tPopover.prototype.sizePopover = function sizePopover() {\n\t  var $element = this.$element;\n\t  var $popover = this.$popover;\n\n\t  if (!$popover || !$popover.length) {\n\t    return;\n\t  }\n\n\t  var popWidth = $popover.outerWidth();\n\t  var popHeight = $popover.outerHeight();\n\t  var $popCaret = $popover.find('.am-popover-caret');\n\t  var popCaretSize = ($popCaret.outerWidth() / 2) || 8;\n\t  // 取不到 $popCaret.outerHeight() 的值，所以直接加 8\n\t  var popTotalHeight = popHeight + 8; // $popCaret.outerHeight();\n\n\t  var triggerWidth = $element.outerWidth();\n\t  var triggerHeight = $element.outerHeight();\n\t  var triggerOffset = $element.offset();\n\t  var triggerRect = $element[0].getBoundingClientRect();\n\n\t  var winHeight = $w.height();\n\t  var winWidth = $w.width();\n\t  var popTop = 0;\n\t  var popLeft = 0;\n\t  var diff = 0;\n\t  var spacing = 2;\n\t  var popPosition = 'top';\n\n\t  $popover.css({left: '', top: ''}).removeClass('am-popover-left ' +\n\t  'am-popover-right am-popover-top am-popover-bottom');\n\n\t  // $popCaret.css({left: '', top: ''});\n\n\t  if (popTotalHeight - spacing < triggerRect.top + spacing) {\n\t    // Popover on the top of trigger\n\t    popTop = triggerOffset.top - popTotalHeight - spacing;\n\t  } else if (popTotalHeight <\n\t    winHeight - triggerRect.top - triggerRect.height) {\n\t    // On bottom\n\t    popPosition = 'bottom';\n\t    popTop = triggerOffset.top + triggerHeight + popCaretSize + spacing;\n\t  } else { // On middle\n\t    popPosition = 'middle';\n\t    popTop = triggerHeight / 2 + triggerOffset.top - popHeight / 2;\n\t  }\n\n\t  // Horizontal Position\n\t  if (popPosition === 'top' || popPosition === 'bottom') {\n\t    popLeft = triggerWidth / 2 + triggerOffset.left - popWidth / 2;\n\n\t    diff = popLeft;\n\n\t    if (popLeft < 5) {\n\t      popLeft = 5;\n\t    }\n\n\t    if (popLeft + popWidth > winWidth) {\n\t      popLeft = (winWidth - popWidth - 20);\n\t      // console.log('left %d, win %d, popw %d', popLeft, winWidth, popWidth);\n\t    }\n\n\t    if (popPosition === 'top') {\n\t      // This is the Popover position, NOT caret position\n\t      // Popover on the Top of trigger, caret on the bottom of Popover\n\t      $popover.addClass('am-popover-top');\n\t    }\n\n\t    if (popPosition === 'bottom') {\n\t      $popover.addClass('am-popover-bottom');\n\t    }\n\n\t    diff = diff - popLeft;\n\t    // $popCaret.css({left: (popWidth / 2 - popCaretSize + diff) + 'px'});\n\n\t  } else if (popPosition === 'middle') {\n\t    popLeft = triggerOffset.left - popWidth - popCaretSize;\n\t    $popover.addClass('am-popover-left');\n\t    if (popLeft < 5) {\n\t      popLeft = triggerOffset.left + triggerWidth + popCaretSize;\n\t      $popover.removeClass('am-popover-left').addClass('am-popover-right');\n\t    }\n\n\t    if (popLeft + popWidth > winWidth) {\n\t      popLeft = winWidth - popWidth - 5;\n\t      $popover.removeClass('am-popover-left').addClass('am-popover-right');\n\t    }\n\t    // $popCaret.css({top: (popHeight / 2 - popCaretSize / 2) + 'px'});\n\t  }\n\n\t  // Apply position style\n\t  $popover.css({top: popTop + 'px', left: popLeft + 'px'});\n\t};\n\n\tPopover.prototype.toggle = function() {\n\t  return this[this.active ? 'close' : 'open']();\n\t};\n\n\tPopover.prototype.open = function() {\n\t  var $popover = this.$popover;\n\n\t  this.$element.trigger('open.popover.amui');\n\t  this.sizePopover();\n\t  $popover.show().addClass('am-active');\n\t  this.active = true;\n\t};\n\n\tPopover.prototype.close = function() {\n\t  var $popover = this.$popover;\n\n\t  this.$element.trigger('close.popover.amui');\n\n\t  $popover\n\t    .removeClass('am-active')\n\t    .trigger('closed.popover.amui')\n\t    .hide();\n\n\t  this.active = false;\n\t};\n\n\tPopover.prototype.getPopover = function() {\n\t  var uid = UI.utils.generateGUID('am-popover');\n\t  var theme = [];\n\n\t  if (this.options.theme) {\n\t    $.each(this.options.theme.split(' '), function(i, item) {\n\t      theme.push('am-popover-' + $.trim(item));\n\t    });\n\t  }\n\n\t  return $(this.options.tpl).attr('id', uid).addClass(theme.join(' '));\n\t};\n\n\tPopover.prototype.setContent = function(content) {\n\t  content = content || this.options.content;\n\t  this.$popover && this.$popover.find('.am-popover-inner')\n\t    .empty().html(content);\n\t};\n\n\tPopover.prototype._bindEvents = function() {\n\t  var eventNS = 'popover.amui';\n\t  var triggers = this.options.trigger.split(' ');\n\n\t  for (var i = triggers.length; i--;) {\n\t    var trigger = triggers[i];\n\n\t    if (trigger === 'click') {\n\t      this.$element.on('click.' + eventNS, $.proxy(this.toggle, this));\n\t    } else { // hover or focus\n\t      var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin';\n\t      var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout';\n\n\t      this.$element.on(eventIn + '.' + eventNS, $.proxy(this.open, this));\n\t      this.$element.on(eventOut + '.' + eventNS, $.proxy(this.close, this));\n\t    }\n\t  }\n\t};\n\n\tPopover.prototype.destroy = function() {\n\t  this.$element.off('.popover.amui').removeData('amui.popover');\n\t  this.$popover.remove();\n\t};\n\n\tUI.plugin('popover', Popover);\n\n\t// Init code\n\tUI.ready(function(context) {\n\t  $('[data-am-popover]', context).popover();\n\t});\n\n\tmodule.exports = Popover;\n\n\t// TODO: 允许用户定义位置\n\n\n/***/ },\n/* 19 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar UI = __webpack_require__(2);\n\n\tvar Progress = (function() {\n\t  /**\n\t   * NProgress (c) 2013, Rico Sta. Cruz\n\t   * @via http://ricostacruz.com/nprogress\n\t   */\n\n\t  var NProgress = {};\n\n\t  NProgress.version = '0.2.0';\n\n\t  var Settings = NProgress.settings = {\n\t    minimum: 0.08,\n\t    easing: 'ease',\n\t    positionUsing: '',\n\t    speed: 200,\n\t    trickle: true,\n\t    trickleRate: 0.02,\n\t    trickleSpeed: 800,\n\t    showSpinner: true,\n\t    parent: 'body',\n\t    barSelector: '[role=\"nprogress-bar\"]',\n\t    spinnerSelector: '[role=\"nprogress-spinner\"]',\n\t    template: '<div class=\"nprogress-bar\" role=\"nprogress-bar\">' +\n\t    '<div class=\"nprogress-peg\"></div></div>' +\n\t    '<div class=\"nprogress-spinner\" role=\"nprogress-spinner\">' +\n\t    '<div class=\"nprogress-spinner-icon\"></div></div>'\n\t  };\n\n\t  /**\n\t   * Updates configuration.\n\t   *\n\t   *     NProgress.configure({\n\t   *       minimum: 0.1\n\t   *     });\n\t   */\n\t  NProgress.configure = function(options) {\n\t    var key, value;\n\t    for (key in options) {\n\t      value = options[key];\n\t      if (value !== undefined && options.hasOwnProperty(key)) Settings[key] = value;\n\t    }\n\n\t    return this;\n\t  };\n\n\t  /**\n\t   * Last number.\n\t   */\n\n\t  NProgress.status = null;\n\n\t  /**\n\t   * Sets the progress bar status, where `n` is a number from `0.0` to `1.0`.\n\t   *\n\t   *     NProgress.set(0.4);\n\t   *     NProgress.set(1.0);\n\t   */\n\n\t  NProgress.set = function(n) {\n\t    var started = NProgress.isStarted();\n\n\t    n = clamp(n, Settings.minimum, 1);\n\t    NProgress.status = (n === 1 ? null : n);\n\n\t    var progress = NProgress.render(!started),\n\t      bar      = progress.querySelector(Settings.barSelector),\n\t      speed    = Settings.speed,\n\t      ease     = Settings.easing;\n\n\t    progress.offsetWidth; /* Repaint */\n\n\t    queue(function(next) {\n\t      // Set positionUsing if it hasn't already been set\n\t      if (Settings.positionUsing === '') Settings.positionUsing = NProgress.getPositioningCSS();\n\n\t      // Add transition\n\t      css(bar, barPositionCSS(n, speed, ease));\n\n\t      if (n === 1) {\n\t        // Fade out\n\t        css(progress, {\n\t          transition: 'none',\n\t          opacity: 1\n\t        });\n\t        progress.offsetWidth; /* Repaint */\n\n\t        setTimeout(function() {\n\t          css(progress, {\n\t            transition: 'all ' + speed + 'ms linear',\n\t            opacity: 0\n\t          });\n\t          setTimeout(function() {\n\t            NProgress.remove();\n\t            next();\n\t          }, speed);\n\t        }, speed);\n\t      } else {\n\t        setTimeout(next, speed);\n\t      }\n\t    });\n\n\t    return this;\n\t  };\n\n\t  NProgress.isStarted = function() {\n\t    return typeof NProgress.status === 'number';\n\t  };\n\n\t  /**\n\t   * Shows the progress bar.\n\t   * This is the same as setting the status to 0%, except that it doesn't go backwards.\n\t   *\n\t   *     NProgress.start();\n\t   *\n\t   */\n\t  NProgress.start = function() {\n\t    if (!NProgress.status) NProgress.set(0);\n\n\t    var work = function() {\n\t      setTimeout(function() {\n\t        if (!NProgress.status) return;\n\t        NProgress.trickle();\n\t        work();\n\t      }, Settings.trickleSpeed);\n\t    };\n\n\t    if (Settings.trickle) work();\n\n\t    return this;\n\t  };\n\n\t  /**\n\t   * Hides the progress bar.\n\t   * This is the *sort of* the same as setting the status to 100%, with the\n\t   * difference being `done()` makes some placebo effect of some realistic motion.\n\t   *\n\t   *     NProgress.done();\n\t   *\n\t   * If `true` is passed, it will show the progress bar even if its hidden.\n\t   *\n\t   *     NProgress.done(true);\n\t   */\n\n\t  NProgress.done = function(force) {\n\t    if (!force && !NProgress.status) return this;\n\n\t    return NProgress.inc(0.3 + 0.5 * Math.random()).set(1);\n\t  };\n\n\t  /**\n\t   * Increments by a random amount.\n\t   */\n\n\t  NProgress.inc = function(amount) {\n\t    var n = NProgress.status;\n\n\t    if (!n) {\n\t      return NProgress.start();\n\t    } else {\n\t      if (typeof amount !== 'number') {\n\t        amount = (1 - n) * clamp(Math.random() * n, 0.1, 0.95);\n\t      }\n\n\t      n = clamp(n + amount, 0, 0.994);\n\t      return NProgress.set(n);\n\t    }\n\t  };\n\n\t  NProgress.trickle = function() {\n\t    return NProgress.inc(Math.random() * Settings.trickleRate);\n\t  };\n\n\t  /**\n\t   * Waits for all supplied jQuery promises and\n\t   * increases the progress as the promises resolve.\n\t   *\n\t   * @param $promise jQUery Promise\n\t   */\n\t  (function() {\n\t    var initial = 0, current = 0;\n\n\t    NProgress.promise = function($promise) {\n\t      if (!$promise || $promise.state() === \"resolved\") {\n\t        return this;\n\t      }\n\n\t      if (current === 0) {\n\t        NProgress.start();\n\t      }\n\n\t      initial++;\n\t      current++;\n\n\t      $promise.always(function() {\n\t        current--;\n\t        if (current === 0) {\n\t          initial = 0;\n\t          NProgress.done();\n\t        } else {\n\t          NProgress.set((initial - current) / initial);\n\t        }\n\t      });\n\n\t      return this;\n\t    };\n\n\t  })();\n\n\t  /**\n\t   * (Internal) renders the progress bar markup based on the `template`\n\t   * setting.\n\t   */\n\n\t  NProgress.render = function(fromStart) {\n\t    if (NProgress.isRendered()) return document.getElementById('nprogress');\n\n\t    addClass(document.documentElement, 'nprogress-busy');\n\n\t    var progress = document.createElement('div');\n\t    progress.id = 'nprogress';\n\t    progress.innerHTML = Settings.template;\n\n\t    var bar      = progress.querySelector(Settings.barSelector),\n\t      perc     = fromStart ? '-100' : toBarPerc(NProgress.status || 0),\n\t      parent   = document.querySelector(Settings.parent),\n\t      spinner;\n\n\t    css(bar, {\n\t      transition: 'all 0 linear',\n\t      transform: 'translate3d(' + perc + '%,0,0)'\n\t    });\n\n\t    if (!Settings.showSpinner) {\n\t      spinner = progress.querySelector(Settings.spinnerSelector);\n\t      spinner && removeElement(spinner);\n\t    }\n\n\t    if (parent != document.body) {\n\t      addClass(parent, 'nprogress-custom-parent');\n\t    }\n\n\t    parent.appendChild(progress);\n\t    return progress;\n\t  };\n\n\t  /**\n\t   * Removes the element. Opposite of render().\n\t   */\n\n\t  NProgress.remove = function() {\n\t    removeClass(document.documentElement, 'nprogress-busy');\n\t    removeClass(document.querySelector(Settings.parent), 'nprogress-custom-parent');\n\t    var progress = document.getElementById('nprogress');\n\t    progress && removeElement(progress);\n\t  };\n\n\t  /**\n\t   * Checks if the progress bar is rendered.\n\t   */\n\n\t  NProgress.isRendered = function() {\n\t    return !!document.getElementById('nprogress');\n\t  };\n\n\t  /**\n\t   * Determine which positioning CSS rule to use.\n\t   */\n\n\t  NProgress.getPositioningCSS = function() {\n\t    // Sniff on document.body.style\n\t    var bodyStyle = document.body.style;\n\n\t    // Sniff prefixes\n\t    var vendorPrefix = ('WebkitTransform' in bodyStyle) ? 'Webkit' :\n\t      ('MozTransform' in bodyStyle) ? 'Moz' :\n\t        ('msTransform' in bodyStyle) ? 'ms' :\n\t          ('OTransform' in bodyStyle) ? 'O' : '';\n\n\t    if (vendorPrefix + 'Perspective' in bodyStyle) {\n\t      // Modern browsers with 3D support, e.g. Webkit, IE10\n\t      return 'translate3d';\n\t    } else if (vendorPrefix + 'Transform' in bodyStyle) {\n\t      // Browsers without 3D support, e.g. IE9\n\t      return 'translate';\n\t    } else {\n\t      // Browsers without translate() support, e.g. IE7-8\n\t      return 'margin';\n\t    }\n\t  };\n\n\t  /**\n\t   * Helpers\n\t   */\n\n\t  function clamp(n, min, max) {\n\t    if (n < min) return min;\n\t    if (n > max) return max;\n\t    return n;\n\t  }\n\n\t  /**\n\t   * (Internal) converts a percentage (`0..1`) to a bar translateX\n\t   * percentage (`-100%..0%`).\n\t   */\n\n\t  function toBarPerc(n) {\n\t    return (-1 + n) * 100;\n\t  }\n\n\n\t  /**\n\t   * (Internal) returns the correct CSS for changing the bar's\n\t   * position given an n percentage, and speed and ease from Settings\n\t   */\n\n\t  function barPositionCSS(n, speed, ease) {\n\t    var barCSS;\n\n\t    if (Settings.positionUsing === 'translate3d') {\n\t      barCSS = { transform: 'translate3d('+toBarPerc(n)+'%,0,0)' };\n\t    } else if (Settings.positionUsing === 'translate') {\n\t      barCSS = { transform: 'translate('+toBarPerc(n)+'%,0)' };\n\t    } else {\n\t      barCSS = { 'margin-left': toBarPerc(n)+'%' };\n\t    }\n\n\t    barCSS.transition = 'all '+speed+'ms '+ease;\n\n\t    return barCSS;\n\t  }\n\n\t  /**\n\t   * (Internal) Queues a function to be executed.\n\t   */\n\n\t  var queue = (function() {\n\t    var pending = [];\n\n\t    function next() {\n\t      var fn = pending.shift();\n\t      if (fn) {\n\t        fn(next);\n\t      }\n\t    }\n\n\t    return function(fn) {\n\t      pending.push(fn);\n\t      if (pending.length == 1) next();\n\t    };\n\t  })();\n\n\t  /**\n\t   * (Internal) Applies css properties to an element, similar to the jQuery\n\t   * css method.\n\t   *\n\t   * While this helper does assist with vendor prefixed property names, it\n\t   * does not perform any manipulation of values prior to setting styles.\n\t   */\n\n\t  var css = (function() {\n\t    var cssPrefixes = [ 'Webkit', 'O', 'Moz', 'ms' ],\n\t      cssProps    = {};\n\n\t    function camelCase(string) {\n\t      return string.replace(/^-ms-/, 'ms-').replace(/-([\\da-z])/gi, function(match, letter) {\n\t        return letter.toUpperCase();\n\t      });\n\t    }\n\n\t    function getVendorProp(name) {\n\t      var style = document.body.style;\n\t      if (name in style) return name;\n\n\t      var i = cssPrefixes.length,\n\t        capName = name.charAt(0).toUpperCase() + name.slice(1),\n\t        vendorName;\n\t      while (i--) {\n\t        vendorName = cssPrefixes[i] + capName;\n\t        if (vendorName in style) return vendorName;\n\t      }\n\n\t      return name;\n\t    }\n\n\t    function getStyleProp(name) {\n\t      name = camelCase(name);\n\t      return cssProps[name] || (cssProps[name] = getVendorProp(name));\n\t    }\n\n\t    function applyCss(element, prop, value) {\n\t      prop = getStyleProp(prop);\n\t      element.style[prop] = value;\n\t    }\n\n\t    return function(element, properties) {\n\t      var args = arguments,\n\t        prop,\n\t        value;\n\n\t      if (args.length == 2) {\n\t        for (prop in properties) {\n\t          value = properties[prop];\n\t          if (value !== undefined && properties.hasOwnProperty(prop)) applyCss(element, prop, value);\n\t        }\n\t      } else {\n\t        applyCss(element, args[1], args[2]);\n\t      }\n\t    }\n\t  })();\n\n\t  /**\n\t   * (Internal) Determines if an element or space separated list of class names contains a class name.\n\t   */\n\n\t  function hasClass(element, name) {\n\t    var list = typeof element == 'string' ? element : classList(element);\n\t    return list.indexOf(' ' + name + ' ') >= 0;\n\t  }\n\n\t  /**\n\t   * (Internal) Adds a class to an element.\n\t   */\n\n\t  function addClass(element, name) {\n\t    var oldList = classList(element),\n\t      newList = oldList + name;\n\n\t    if (hasClass(oldList, name)) return;\n\n\t    // Trim the opening space.\n\t    element.className = newList.substring(1);\n\t  }\n\n\t  /**\n\t   * (Internal) Removes a class from an element.\n\t   */\n\n\t  function removeClass(element, name) {\n\t    var oldList = classList(element),\n\t      newList;\n\n\t    if (!hasClass(element, name)) return;\n\n\t    // Replace the class name.\n\t    newList = oldList.replace(' ' + name + ' ', ' ');\n\n\t    // Trim the opening and closing spaces.\n\t    element.className = newList.substring(1, newList.length - 1);\n\t  }\n\n\t  /**\n\t   * (Internal) Gets a space separated list of the class names on the element.\n\t   * The list is wrapped with a single space on each end to facilitate finding\n\t   * matches within the list.\n\t   */\n\n\t  function classList(element) {\n\t    return (' ' + (element.className || '') + ' ').replace(/\\s+/gi, ' ');\n\t  }\n\n\t  /**\n\t   * (Internal) Removes an element from the DOM.\n\t   */\n\n\t  function removeElement(element) {\n\t    element && element.parentNode && element.parentNode.removeChild(element);\n\t  }\n\n\t  return NProgress;\n\t})();\n\n\tmodule.exports = UI.progress = Progress;\n\n\n/***/ },\n/* 20 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\tvar PinchZoom = __webpack_require__(17);\n\tvar Hammer = __webpack_require__(3);\n\tvar animation = UI.support.animation;\n\tvar transition = UI.support.transition;\n\n\t/**\n\t * PureView\n\t * @desc Image browser for Mobile\n\t * @param element\n\t * @param options\n\t * @constructor\n\t */\n\n\tvar PureView = function(element, options) {\n\t  this.$element = $(element);\n\t  this.$body = $(document.body);\n\t  this.options = $.extend({}, PureView.DEFAULTS, options);\n\t  this.$pureview = $(this.options.tpl).attr('id',\n\t    UI.utils.generateGUID('am-pureview'));\n\n\t  this.$slides = null;\n\t  this.transitioning = null;\n\t  this.scrollbarWidth = 0;\n\n\t  this.init();\n\t};\n\n\tPureView.DEFAULTS = {\n\t  tpl: '<div class=\"am-pureview am-pureview-bar-active\">' +\n\t  '<ul class=\"am-pureview-slider\"></ul>' +\n\t  '<ul class=\"am-pureview-direction\">' +\n\t  '<li class=\"am-pureview-prev\"><a href=\"\"></a></li>' +\n\t  '<li class=\"am-pureview-next\"><a href=\"\"></a></li></ul>' +\n\t  '<ol class=\"am-pureview-nav\"></ol>' +\n\t  '<div class=\"am-pureview-bar am-active\">' +\n\t  '<span class=\"am-pureview-title\"></span>' +\n\t  '<div class=\"am-pureview-counter\"><span class=\"am-pureview-current\"></span> / ' +\n\t  '<span class=\"am-pureview-total\"></span></div></div>' +\n\t  '<div class=\"am-pureview-actions am-active\">' +\n\t  '<a href=\"javascript: void(0)\" class=\"am-icon-chevron-left\" ' +\n\t  'data-am-close=\"pureview\"></a></div>' +\n\t  '</div>',\n\n\t  className: {\n\t    prevSlide: 'am-pureview-slide-prev',\n\t    nextSlide: 'am-pureview-slide-next',\n\t    onlyOne: 'am-pureview-only',\n\t    active: 'am-active',\n\t    barActive: 'am-pureview-bar-active',\n\t    activeBody: 'am-pureview-active'\n\t  },\n\n\t  selector: {\n\t    slider: '.am-pureview-slider',\n\t    close: '[data-am-close=\"pureview\"]',\n\t    total: '.am-pureview-total',\n\t    current: '.am-pureview-current',\n\t    title: '.am-pureview-title',\n\t    actions: '.am-pureview-actions',\n\t    bar: '.am-pureview-bar',\n\t    pinchZoom: '.am-pinch-zoom',\n\t    nav: '.am-pureview-nav'\n\t  },\n\n\t  shareBtn: false,\n\n\t  // press to toggle Toolbar\n\t  toggleToolbar: true,\n\n\t  // 从何处获取图片，img 可以使用 data-rel 指定大图\n\t  target: 'img',\n\n\t  // 微信 Webview 中调用微信的图片浏览器\n\t  // 实现图片保存、分享好友、收藏图片等功能\n\t  weChatImagePreview: true\n\t};\n\n\tPureView.prototype.init = function() {\n\t  var _this = this;\n\t  var options = this.options;\n\t  var $element = this.$element;\n\t  var $pureview = this.$pureview;\n\n\t  this.refreshSlides();\n\n\t  $('body').append($pureview);\n\n\t  this.$title = $pureview.find(options.selector.title);\n\t  this.$current = $pureview.find(options.selector.current);\n\t  this.$bar = $pureview.find(options.selector.bar);\n\t  this.$actions = $pureview.find(options.selector.actions);\n\n\t  if (options.shareBtn) {\n\t    this.$actions.append('<a href=\"javascript: void(0)\" ' +\n\t    'class=\"am-icon-share-square-o\" data-am-toggle=\"share\"></a>');\n\t  }\n\n\t  this.$element.on('click.pureview.amui', options.target, function(e) {\n\t    e.preventDefault();\n\t    var clicked = _this.$images.index(this);\n\n\t    // Invoke WeChat ImagePreview in WeChat\n\t    // TODO: detect WeChat before init\n\t    if (options.weChatImagePreview && window.WeixinJSBridge) {\n\t      window.WeixinJSBridge.invoke('imagePreview', {\n\t        current: _this.imgUrls[clicked],\n\t        urls: _this.imgUrls\n\t      });\n\t    } else {\n\t      _this.open(clicked);\n\t    }\n\t  });\n\n\t  $pureview.find('.am-pureview-direction').\n\t    on('click.direction.pureview.amui', 'li', function(e) {\n\t      e.preventDefault();\n\n\t      if ($(this).is('.am-pureview-prev')) {\n\t        _this.prevSlide();\n\t      } else {\n\t        _this.nextSlide();\n\t      }\n\t    });\n\n\t  // Nav Contorl\n\t  $pureview.find(options.selector.nav).on('click.nav.pureview.amui', 'li',\n\t    function() {\n\t      var index = _this.$navItems.index($(this));\n\t      _this.activate(_this.$slides.eq(index));\n\t    });\n\n\t  // Close Icon\n\t  $pureview.find(options.selector.close).\n\t    on('click.close.pureview.amui', function(e) {\n\t      e.preventDefault();\n\t      _this.close();\n\t    });\n\n\t  this.$slider.hammer().on('swipeleft.pureview.amui', function(e) {\n\t    e.preventDefault();\n\t    _this.nextSlide();\n\t  }).on('swiperight.pureview.amui', function(e) {\n\t    e.preventDefault();\n\t    _this.prevSlide();\n\t  }).on('press.pureview.amui', function(e) {\n\t    e.preventDefault();\n\t    options.toggleToolbar && _this.toggleToolBar();\n\t  });\n\n\t  this.$slider.data('hammer').get('swipe').set({\n\t    direction: Hammer.DIRECTION_HORIZONTAL,\n\t    velocity: 0.35\n\t  });\n\n\t  // Observe DOM\n\t  $element.DOMObserve({\n\t    childList: true,\n\t    subtree: true\n\t  }, function(mutations, observer) {\n\t    // _this.refreshSlides();\n\t    // console.log('mutations[0].type);\n\t  });\n\n\t  // NOTE:\n\t  // trigger this event manually if MutationObserver not supported\n\t  //   when new images appended, or call refreshSlides()\n\t  // if (!UI.support.mutationobserver) $element.trigger('changed.dom.amui')\n\t  $element.on('changed.dom.amui', function(e) {\n\t    e.stopPropagation();\n\t    _this.refreshSlides();\n\t  });\n\n\t  $(document).on('keydown.pureview.amui', $.proxy(function(e) {\n\t    var keyCode = e.keyCode;\n\t    if (keyCode == 37) {\n\t      this.prevSlide();\n\t    } else if (keyCode == 39) {\n\t      this.nextSlide();\n\t    } else if (keyCode == 27) {\n\t      this.close();\n\t    }\n\t  }, this));\n\t};\n\n\tPureView.prototype.refreshSlides = function() {\n\t  // update images collections\n\t  this.$images = this.$element.find(this.options.target);\n\t  var _this = this;\n\t  var options = this.options;\n\t  var $pureview = this.$pureview;\n\t  var $slides = $([]);\n\t  var $navItems = $([]);\n\t  var $images = this.$images;\n\t  var total = $images.length;\n\t  this.$slider = $pureview.find(options.selector.slider);\n\t  this.$nav = $pureview.find(options.selector.nav);\n\t  var viewedFlag = 'data-am-pureviewed';\n\t  // for WeChat Image Preview\n\t  this.imgUrls = this.imgUrls || [];\n\n\t  if (!total) {\n\t    return;\n\t  }\n\n\t  if (total === 1) {\n\t    $pureview.addClass(options.className.onlyOne);\n\t  }\n\n\t  $images.not('[' + viewedFlag + ']').each(function(i, item) {\n\t    var src;\n\t    var title;\n\n\t    // get image URI from link's href attribute\n\t    if (item.nodeName === 'A') {\n\t      src = item.href; // to absolute path\n\t      title = item.title || '';\n\t    } else {\n\t      // NOTE: `data-rel` should be a full URL, otherwise,\n\t      //        WeChat images preview will not work\n\t      src = $(item).data('rel') || item.src; // <img src='' data-rel='' />\n\t      src = UI.utils.getAbsoluteUrl(src);\n\t      title = $(item).attr('alt') || '';\n\t    }\n\n\t    // add pureviewed flag\n\t    item.setAttribute(viewedFlag, '1');\n\n\t    // hide bar: wechat_webview_type=1\n\t    // http://tmt.io/wechat/  not working?\n\t    _this.imgUrls.push(src);\n\n\t    $slides = $slides.add($('<li data-src=\"' + src + '\" data-title=\"' + title +\n\t    '\"></li>'));\n\t    $navItems = $navItems.add($('<li>' + (i + 1) + '</li>'));\n\t  });\n\n\t  $pureview.find(options.selector.total).text(total);\n\n\t  this.$slider.append($slides);\n\t  this.$nav.append($navItems);\n\t  this.$navItems = this.$nav.find('li');\n\t  this.$slides = this.$slider.find('li');\n\t};\n\n\tPureView.prototype.loadImage = function($slide, callback) {\n\t  var appendedFlag = 'image-appended';\n\n\t  if (!$slide.data(appendedFlag)) {\n\t    var $img = $('<img>', {\n\t      src: $slide.data('src'),\n\t      alt: $slide.data('title')\n\t    });\n\n\t    $slide.html($img).wrapInner('<div class=\"am-pinch-zoom\"></div>').redraw();\n\n\t    var $pinchWrapper = $slide.find(this.options.selector.pinchZoom);\n\t    $pinchWrapper.data('amui.pinchzoom', new PinchZoom($pinchWrapper[0], {}));\n\t    $slide.data('image-appended', true);\n\t  }\n\n\t  callback && callback.call(this);\n\t};\n\n\tPureView.prototype.activate = function($slide) {\n\t  var options = this.options;\n\t  var $slides = this.$slides;\n\t  var activeIndex = $slides.index($slide);\n\t  var title = $slide.data('title') || '';\n\t  var active = options.className.active;\n\n\t  if ($slides.find('.' + active).is($slide)) {\n\t    return;\n\t  }\n\n\t  if (this.transitioning) {\n\t    return;\n\t  }\n\n\t  this.loadImage($slide, function() {\n\t    UI.utils.imageLoader($slide.find('img'), function(image) {\n\t      $slide.find('.am-pinch-zoom').addClass('am-pureview-loaded');\n\t      $(image).addClass('am-img-loaded');\n\t    });\n\t  });\n\n\t  this.transitioning = 1;\n\n\t  this.$title.text(title);\n\t  this.$current.text(activeIndex + 1);\n\t  $slides.removeClass();\n\t  $slide.addClass(active);\n\t  $slides.eq(activeIndex - 1).addClass(options.className.prevSlide);\n\t  $slides.eq(activeIndex + 1).addClass(options.className.nextSlide);\n\n\t  this.$navItems.removeClass().\n\t    eq(activeIndex).addClass(options.className.active);\n\n\t  if (transition) {\n\t    $slide.one(transition.end, $.proxy(function() {\n\t      this.transitioning = 0;\n\t    }, this)).emulateTransitionEnd(300);\n\t  } else {\n\t    this.transitioning = 0;\n\t  }\n\n\t  // TODO: pre-load next image\n\t};\n\n\tPureView.prototype.nextSlide = function() {\n\t  if (this.$slides.length === 1) {\n\t    return;\n\t  }\n\n\t  var $slides = this.$slides;\n\t  var $active = $slides.filter('.am-active');\n\t  var activeIndex = $slides.index($active);\n\t  var rightSpring = 'am-animation-right-spring';\n\n\t  if (activeIndex + 1 >= $slides.length) { // last one\n\t    animation && $active.addClass(rightSpring).on(animation.end, function() {\n\t      $active.removeClass(rightSpring);\n\t    });\n\t  } else {\n\t    this.activate($slides.eq(activeIndex + 1));\n\t  }\n\t};\n\n\tPureView.prototype.prevSlide = function() {\n\t  if (this.$slides.length === 1) {\n\t    return;\n\t  }\n\n\t  var $slides = this.$slides;\n\t  var $active = $slides.filter('.am-active');\n\t  var activeIndex = this.$slides.index(($active));\n\t  var leftSpring = 'am-animation-left-spring';\n\n\t  if (activeIndex === 0) { // first one\n\t    animation && $active.addClass(leftSpring).on(animation.end, function() {\n\t      $active.removeClass(leftSpring);\n\t    });\n\t  } else {\n\t    this.activate($slides.eq(activeIndex - 1));\n\t  }\n\t};\n\n\tPureView.prototype.toggleToolBar = function() {\n\t  this.$pureview.toggleClass(this.options.className.barActive);\n\t};\n\n\tPureView.prototype.open = function(index) {\n\t  var active = index || 0;\n\t  this.checkScrollbar();\n\t  this.setScrollbar();\n\t  this.activate(this.$slides.eq(active));\n\t  this.$pureview.show().redraw().addClass(this.options.className.active);\n\t  this.$body.addClass(this.options.className.activeBody);\n\t};\n\n\tPureView.prototype.close = function() {\n\t  var options = this.options;\n\n\t  this.$pureview.removeClass(options.className.active);\n\t  this.$slides.removeClass();\n\n\t  function resetBody() {\n\t    this.$pureview.hide();\n\t    this.$body.removeClass(options.className.activeBody);\n\t    this.resetScrollbar();\n\t  }\n\n\t  if (transition) {\n\t    this.$pureview.one(transition.end, $.proxy(resetBody, this)).\n\t      emulateTransitionEnd(300);\n\t  } else {\n\t    resetBody.call(this);\n\t  }\n\t};\n\n\tPureView.prototype.checkScrollbar = function() {\n\t  this.scrollbarWidth = UI.utils.measureScrollbar();\n\t};\n\n\tPureView.prototype.setScrollbar = function() {\n\t  var bodyPaddingRight = parseInt((this.$body.css('padding-right') || 0), 10);\n\t  if (this.scrollbarWidth) {\n\t    this.$body.css('padding-right', bodyPaddingRight + this.scrollbarWidth);\n\t  }\n\t};\n\n\tPureView.prototype.resetScrollbar = function() {\n\t  this.$body.css('padding-right', '');\n\t};\n\n\tUI.plugin('pureview', PureView);\n\n\t// Init code\n\tUI.ready(function(context) {\n\t  $('[data-am-pureview]', context).pureview();\n\t});\n\n\tmodule.exports = PureView;\n\n\t// TODO: 1. 动画改进\n\t//       2. 改变图片的时候恢复 Zoom\n\t//       3. 选项\n\t//       4. 图片高度问题：由于 PinchZoom 的原因，过高的图片如果设置看了滚动，则放大以后显示不全\n\n\n/***/ },\n/* 21 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\n\t/**\n\t * @via https://github.com/uikit/uikit/blob/master/src/js/scrollspy.js\n\t * @license https://github.com/uikit/uikit/blob/master/LICENSE.md\n\t */\n\n\tvar ScrollSpy = function(element, options) {\n\t  if (!UI.support.animation) {\n\t    return;\n\t  }\n\n\t  this.options = $.extend({}, ScrollSpy.DEFAULTS, options);\n\t  this.$element = $(element);\n\n\t  var checkViewRAF = function() {\n\t    UI.utils.rAF.call(window, $.proxy(this.checkView, this));\n\t  }.bind(this);\n\n\t  this.$window = $(window).on('scroll.scrollspy.amui', checkViewRAF)\n\t    .on('resize.scrollspy.amui orientationchange.scrollspy.amui',\n\t    UI.utils.debounce(checkViewRAF, 50));\n\n\t  this.timer = this.inViewState = this.initInView = null;\n\n\t  checkViewRAF();\n\t};\n\n\tScrollSpy.DEFAULTS = {\n\t  animation: 'fade',\n\t  className: {\n\t    inView: 'am-scrollspy-inview',\n\t    init: 'am-scrollspy-init'\n\t  },\n\t  repeat: true,\n\t  delay: 0,\n\t  topOffset: 0,\n\t  leftOffset: 0\n\t};\n\n\tScrollSpy.prototype.checkView = function() {\n\t  var $element = this.$element;\n\t  var options = this.options;\n\t  var inView = UI.utils.isInView($element, options);\n\t  var animation = options.animation ?\n\t  ' am-animation-' + options.animation : '';\n\n\t  if (inView && !this.inViewState) {\n\t    if (this.timer) {\n\t      clearTimeout(this.timer);\n\t    }\n\n\t    if (!this.initInView) {\n\t      $element.addClass(options.className.init);\n\t      this.offset = $element.offset();\n\t      this.initInView = true;\n\n\t      $element.trigger('init.scrollspy.amui');\n\t    }\n\n\t    this.timer = setTimeout(function() {\n\t      if (inView) {\n\t        $element.addClass(options.className.inView + animation).width();\n\t      }\n\t    }, options.delay);\n\n\t    this.inViewState = true;\n\t    $element.trigger('inview.scrollspy.amui');\n\t  }\n\n\t  if (!inView && this.inViewState && options.repeat) {\n\t    $element.removeClass(options.className.inView + animation);\n\n\t    this.inViewState = false;\n\n\t    $element.trigger('outview.scrollspy.amui');\n\t  }\n\t};\n\n\tScrollSpy.prototype.check = function() {\n\t  UI.utils.rAF.call(window, $.proxy(this.checkView, this));\n\t};\n\n\t// Sticky Plugin\n\tUI.plugin('scrollspy', ScrollSpy);\n\n\t// Init code\n\tUI.ready(function(context) {\n\t  $('[data-am-scrollspy]', context).scrollspy();\n\t});\n\n\tmodule.exports = ScrollSpy;\n\n\n/***/ },\n/* 22 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\t__webpack_require__(23);\n\n\t/**\n\t * @via https://github.com/uikit/uikit/\n\t * @license https://github.com/uikit/uikit/blob/master/LICENSE.md\n\t */\n\n\t// ScrollSpyNav Class\n\tvar ScrollSpyNav = function(element, options) {\n\t  this.options = $.extend({}, ScrollSpyNav.DEFAULTS, options);\n\t  this.$element = $(element);\n\t  this.anchors = [];\n\n\t  this.$links = this.$element.find('a[href^=\"#\"]').each(function(i, link) {\n\t    this.anchors.push($(link).attr('href'));\n\t  }.bind(this));\n\n\t  this.$targets = $(this.anchors.join(', '));\n\n\t  var processRAF = function() {\n\t    UI.utils.rAF.call(window, $.proxy(this.process, this));\n\t  }.bind(this);\n\n\t  this.$window = $(window).on('scroll.scrollspynav.amui', processRAF)\n\t    .on('resize.scrollspynav.amui orientationchange.scrollspynav.amui',\n\t    UI.utils.debounce(processRAF, 50));\n\n\t  processRAF();\n\t  this.scrollProcess();\n\t};\n\n\tScrollSpyNav.DEFAULTS = {\n\t  className: {\n\t    active: 'am-active'\n\t  },\n\t  closest: false,\n\t  smooth: true,\n\t  offsetTop: 0\n\t};\n\n\tScrollSpyNav.prototype.process = function() {\n\t  var scrollTop = this.$window.scrollTop();\n\t  var options = this.options;\n\t  var inViews = [];\n\t  var $links = this.$links;\n\n\t  var $targets = this.$targets;\n\n\t  $targets.each(function(i, target) {\n\t    if (UI.utils.isInView(target, options)) {\n\t      inViews.push(target);\n\t    }\n\t  });\n\n\t  // console.log(inViews.length);\n\n\t  if (inViews.length) {\n\t    var $target;\n\n\t    $.each(inViews, function(i, item) {\n\t      if ($(item).offset().top >= scrollTop) {\n\t        $target = $(item);\n\t        return false; // break\n\t      }\n\t    });\n\n\t    if (!$target) {\n\t      return;\n\t    }\n\n\t    if (options.closest) {\n\t      $links.closest(options.closest).removeClass(options.className.active);\n\t      $links.filter('a[href=\"#' + $target.attr('id') + '\"]').\n\t        closest(options.closest).addClass(options.className.active);\n\t    } else {\n\t      $links.removeClass(options.className.active).\n\t        filter('a[href=\"#' + $target.attr('id') + '\"]').\n\t        addClass(options.className.active);\n\t    }\n\t  }\n\t};\n\n\tScrollSpyNav.prototype.scrollProcess = function() {\n\t  var $links = this.$links;\n\t  var options = this.options;\n\n\t  // smoothScroll\n\t  if (options.smooth && $.fn.smoothScroll) {\n\t    $links.on('click', function(e) {\n\t      e.preventDefault();\n\n\t      var $this = $(this);\n\t      var $target = $($this.attr('href'));\n\n\t      if (!$target) {\n\t        return;\n\t      }\n\n\t      var offsetTop = options.offsetTop &&\n\t        !isNaN(parseInt(options.offsetTop)) && parseInt(options.offsetTop) || 0;\n\n\t      $(window).smoothScroll({position: $target.offset().top - offsetTop});\n\t    });\n\t  }\n\t};\n\n\t// ScrollSpyNav Plugin\n\tUI.plugin('scrollspynav', ScrollSpyNav);\n\n\t// Init code\n\tUI.ready(function(context) {\n\t  $('[data-am-scrollspy-nav]', context).scrollspynav();\n\t});\n\n\tmodule.exports = ScrollSpyNav;\n\n\t// TODO: 1. 算法改进\n\t//       2. 多级菜单支持\n\t//       3. smooth scroll pushState\n\n\n/***/ },\n/* 23 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\tvar rAF = UI.utils.rAF;\n\tvar cAF = UI.utils.cancelAF;\n\n\t/**\n\t * Smooth Scroll\n\t * @param position\n\t * @via http://mir.aculo.us/2014/01/19/scrolling-dom-elements-to-the-top-a-zepto-plugin/\n\t */\n\n\t// Usage: $(window).smoothScroll([options])\n\n\t// only allow one scroll to top operation to be in progress at a time,\n\t// which is probably what you want\n\tvar smoothScrollInProgress = false;\n\n\tvar SmoothScroll = function(element, options) {\n\t  options = options || {};\n\n\t  var $this = $(element);\n\t  var targetY = parseInt(options.position) || SmoothScroll.DEFAULTS.position;\n\t  var initialY = $this.scrollTop();\n\t  var lastY = initialY;\n\t  var delta = targetY - initialY;\n\t  // duration in ms, make it a bit shorter for short distances\n\t  // this is not scientific and you might want to adjust this for\n\t  // your preferences\n\t  var speed = options.speed ||\n\t      Math.min(750, Math.min(1500, Math.abs(initialY - targetY)));\n\t  // temp variables (t will be a position between 0 and 1, y is the calculated scrollTop)\n\t  var start;\n\t  var t;\n\t  var y;\n\t  var cancelScroll = function() {\n\t      abort();\n\t    };\n\n\t  // abort if already in progress or nothing to scroll\n\t  if (smoothScrollInProgress) {\n\t    return;\n\t  }\n\n\t  if (delta === 0) {\n\t    return;\n\t  }\n\n\t  // quint ease-in-out smoothing, from\n\t  // https://github.com/madrobby/scripty2/blob/master/src/effects/transitions/penner.js#L127-L136\n\t  function smooth(pos) {\n\t    if ((pos /= 0.5) < 1) {\n\t      return 0.5 * Math.pow(pos, 5);\n\t    }\n\n\t    return 0.5 * (Math.pow((pos - 2), 5) + 2);\n\t  }\n\n\t  function abort() {\n\t    $this.off('touchstart.smoothscroll.amui', cancelScroll);\n\t    smoothScrollInProgress = false;\n\t  }\n\n\t  // when there's a touch detected while scrolling is in progress, abort\n\t  // the scrolling (emulates native scrolling behavior)\n\t  $this.on('touchstart.smoothscroll.amui', cancelScroll);\n\t  smoothScrollInProgress = true;\n\n\t  // start rendering away! note the function given to frame\n\t  // is named \"render\" so we can reference it again further down\n\t  function render(now) {\n\t    if (!smoothScrollInProgress) {\n\t      return;\n\t    }\n\t    if (!start) {\n\t      start = now;\n\t    }\n\n\t    // calculate t, position of animation in [0..1]\n\t    t = Math.min(1, Math.max((now - start) / speed, 0));\n\t    // calculate the new scrollTop position (don't forget to smooth)\n\t    y = Math.round(initialY + delta * smooth(t));\n\t    // bracket scrollTop so we're never over-scrolling\n\t    if (delta > 0 && y > targetY) {\n\t      y = targetY;\n\t    }\n\t    if (delta < 0 && y < targetY) {\n\t      y = targetY;\n\t    }\n\n\t    // only actually set scrollTop if there was a change fromt he last frame\n\t    if (lastY != y) {\n\t      $this.scrollTop(y);\n\t    }\n\n\t    lastY = y;\n\t    // if we're not done yet, queue up an other frame to render,\n\t    // or clean up\n\t    if (y !== targetY) {\n\t      cAF(scrollRAF);\n\t      scrollRAF = rAF(render);\n\t    } else {\n\t      cAF(scrollRAF);\n\t      abort();\n\t    }\n\t  }\n\n\t  var scrollRAF = rAF(render);\n\t};\n\n\tSmoothScroll.DEFAULTS = {\n\t  position: 0\n\t};\n\n\t$.fn.smoothScroll = function(option) {\n\t  return this.each(function() {\n\t    new SmoothScroll(this, option);\n\t  });\n\t};\n\n\t// Init code\n\t$(document).on('click.smoothScroll.amui.data-api', '[data-am-smooth-scroll]',\n\t  function(e) {\n\t    e.preventDefault();\n\t    var options = UI.utils.parseOptions($(this).data('amSmoothScroll'));\n\n\t    $(window).smoothScroll(options);\n\t  });\n\n\tmodule.exports = SmoothScroll;\n\n\n/***/ },\n/* 24 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\t// require('./ui.dropdown');\n\n\t// Make jQuery :contains Case-Insensitive\n\t$.expr[':'].containsNC = function(elem, i, match, array) {\n\t  return (elem.textContent || elem.innerText || '').toLowerCase().\n\t      indexOf((match[3] || '').toLowerCase()) >= 0;\n\t};\n\n\t/**\n\t * Selected\n\t * @desc HTML select replacer\n\t * @via https://github.com/silviomoreto/bootstrap-select\n\t * @license https://github.com/silviomoreto/bootstrap-select/blob/master/LICENSE\n\t * @param element\n\t * @param options\n\t * @constructor\n\t */\n\n\tvar Selected = function(element, options) {\n\t  this.$element = $(element);\n\t  this.options = $.extend({}, Selected.DEFAULTS, {\n\t    placeholder: element.getAttribute('placeholder') ||\n\t    Selected.DEFAULTS.placeholder\n\t  }, options);\n\t  this.$originalOptions = this.$element.find('option');\n\t  this.multiple = element.multiple;\n\t  this.$selector = null;\n\t  this.initialized = false;\n\t  this.init();\n\t};\n\n\tSelected.DEFAULTS = {\n\t  btnWidth: null,\n\t  btnSize: null,\n\t  btnStyle: 'default',\n\t  dropUp: 0,\n\t  maxHeight: null,\n\t  maxChecked: null,\n\t  placeholder: '点击选择...',\n\t  selectedClass: 'am-checked',\n\t  disabledClass: 'am-disabled',\n\t  searchBox: false,\n\t  tpl: '<div class=\"am-selected am-dropdown ' +\n\t  '<%= dropUp ? \\'am-dropdown-up\\': \\'\\' %>\" id=\"<%= id %>\" data-am-dropdown>' +\n\t  '  <button type=\"button\" class=\"am-selected-btn am-btn am-dropdown-toggle\">' +\n\t  '    <span class=\"am-selected-status am-fl\"></span>' +\n\t  '    <i class=\"am-selected-icon am-icon-caret-' +\n\t  '<%= dropUp ? \\'up\\' : \\'down\\' %>\"></i>' +\n\t  '  </button>' +\n\t  '  <div class=\"am-selected-content am-dropdown-content\">' +\n\t  '    <h2 class=\"am-selected-header\">' +\n\t  '<span class=\"am-icon-chevron-left\">返回</span></h2>' +\n\t  '   <% if (searchBox) { %>' +\n\t  '   <div class=\"am-selected-search\">' +\n\t  '     <input autocomplete=\"off\" class=\"am-form-field am-input-sm\" />' +\n\t  '   </div>' +\n\t  '   <% } %>' +\n\t  '    <ul class=\"am-selected-list\">' +\n\t  '      <% for (var i = 0; i < options.length; i++) { %>' +\n\t  '       <% var option = options[i] %>' +\n\t  '       <% if (option.header) { %>' +\n\t  '  <li data-group=\"<%= option.group %>\" class=\"am-selected-list-header\">' +\n\t  '       <%= option.text %></li>' +\n\t  '       <% } else { %>' +\n\t  '       <li class=\"<%= option.classNames%>\" ' +\n\t  '         data-index=\"<%= option.index %>\" ' +\n\t  '         data-group=\"<%= option.group || 0 %>\" ' +\n\t  '         data-value=\"<%= option.value %>\" >' +\n\t  '         <span class=\"am-selected-text\"><%= option.text %></span>' +\n\t  '         <i class=\"am-icon-check\"></i></li>' +\n\t  '      <% } %>' +\n\t  '      <% } %>' +\n\t  '    </ul>' +\n\t  '    <div class=\"am-selected-hint\"></div>' +\n\t  '  </div>' +\n\t  '</div>',\n\t  listTpl:   '<% for (var i = 0; i < options.length; i++) { %>' +\n\t  '       <% var option = options[i] %>' +\n\t  '       <% if (option.header) { %>' +\n\t  '  <li data-group=\"<%= option.group %>\" class=\"am-selected-list-header\">' +\n\t  '       <%= option.text %></li>' +\n\t  '       <% } else { %>' +\n\t  '       <li class=\"<%= option.classNames %>\" ' +\n\t  '         data-index=\"<%= option.index %>\" ' +\n\t  '         data-group=\"<%= option.group || 0 %>\" ' +\n\t  '         data-value=\"<%= option.value %>\" >' +\n\t  '         <span class=\"am-selected-text\"><%= option.text %></span>' +\n\t  '         <i class=\"am-icon-check\"></i></li>' +\n\t  '      <% } %>' +\n\t  '      <% } %>'\n\t};\n\n\tSelected.prototype.init = function() {\n\t  var _this = this;\n\t  var $element = this.$element;\n\t  var options = this.options;\n\n\t  $element.hide();\n\n\t  var data = {\n\t    id: UI.utils.generateGUID('am-selected'),\n\t    multiple: this.multiple,\n\t    options: [],\n\t    searchBox: options.searchBox,\n\t    dropUp: options.dropUp,\n\t    placeholder: options.placeholder\n\t  };\n\n\t  this.$selector = $(UI.template(this.options.tpl, data));\n\t  // set select button styles\n\t  this.$selector.css({width: this.options.btnWidth});\n\n\t  if (this.$element[0].disabled) {\n\t    this.$selector.addClass(options.disabledClass);\n\t  }\n\n\t  this.$list = this.$selector.find('.am-selected-list');\n\t  this.$searchField = this.$selector.find('.am-selected-search input');\n\t  this.$hint = this.$selector.find('.am-selected-hint');\n\n\t  var $selectorBtn = this.$selector.find('.am-selected-btn');\n\t  var btnClassNames = [];\n\n\t  options.btnSize && btnClassNames.push('am-btn-' + options.btnSize);\n\t  options.btnStyle && btnClassNames.push('am-btn-' + options.btnStyle);\n\t  $selectorBtn.addClass(btnClassNames.join(' '));\n\n\t  this.$selector.dropdown({\n\t    justify: $selectorBtn\n\t  });\n\n\t  // set list height\n\t  if (options.maxHeight) {\n\t    this.$selector.find('.am-selected-list').css({\n\t      'max-height': options.maxHeight,\n\t      'overflow-y': 'scroll'\n\t    });\n\t  }\n\n\t  // set hint text\n\t  var hint = [];\n\t  var min = $element.attr('minchecked');\n\t  var max = $element.attr('maxchecked') || options.maxChecked;\n\n\t  this.maxChecked = max || Infinity;\n\n\t  if ($element[0].required) {\n\t    hint.push('必选');\n\t  }\n\n\t  if (min || max) {\n\t    min && hint.push('至少选择 ' + min + ' 项');\n\t    max && hint.push('至多选择 ' + max + ' 项');\n\t  }\n\n\t  this.$hint.text(hint.join('，'));\n\n\t  // render dropdown list\n\t  this.renderOptions();\n\n\t  // append $selector after <select>\n\t  this.$element.after(this.$selector);\n\t  this.dropdown = this.$selector.data('amui.dropdown');\n\t  this.$status = this.$selector.find('.am-selected-status');\n\n\t  // #try to fixes #476\n\t  setTimeout(function() {\n\t    _this.syncData();\n\t    _this.initialized = true;\n\t  }, 0);\n\n\t  this.bindEvents();\n\t};\n\n\tSelected.prototype.renderOptions = function() {\n\t  var $element = this.$element;\n\t  var options = this.options;\n\t  var optionItems = [];\n\t  var $optgroup = $element.find('optgroup');\n\t  this.$originalOptions = this.$element.find('option');\n\n\t  // 单选框使用 JS 禁用已经选择的 option 以后，\n\t  // 浏览器会重新选定第一个 option，但有一定延迟，致使 JS 获取 value 时返回 null\n\t  if (!this.multiple && ($element.val() === null)) {\n\t    this.$originalOptions.length &&\n\t    (this.$originalOptions.get(0).selected = true);\n\t  }\n\n\t  function pushOption(index, item, group) {\n\t    if (item.value === '') {\n\t      // skip to next iteration\n\t      // @see http://stackoverflow.com/questions/481601/how-to-skip-to-next-iteration-in-jquery-each-util\n\t      return true;\n\t    }\n\n\t    var classNames = '';\n\t    item.disabled && (classNames += options.disabledClass);\n\t    !item.disabled && item.selected && (classNames += options.selectedClass);\n\n\t    optionItems.push({\n\t      group: group,\n\t      index: index,\n\t      classNames: classNames,\n\t      text: item.text,\n\t      value: item.value\n\t    });\n\t  }\n\n\t  // select with option groups\n\t  if ($optgroup.length) {\n\t    $optgroup.each(function(i) {\n\t      // push group name\n\t      optionItems.push({\n\t        header: true,\n\t        group: i + 1,\n\t        text: this.label\n\t      });\n\n\t      $optgroup.eq(i).find('option').each(function(index, item) {\n\t        pushOption(index, item, i);\n\t      });\n\t    });\n\t  } else {\n\t    // without option groups\n\t    this.$originalOptions.each(function(index, item) {\n\t      pushOption(index, item, null);\n\t    });\n\t  }\n\n\t  this.$list.html(UI.template(options.listTpl, {options: optionItems}));\n\t  this.$shadowOptions = this.$list.find('> li').\n\t    not('.am-selected-list-header');\n\t};\n\n\tSelected.prototype.setChecked = function(item) {\n\t  var options = this.options;\n\t  var $item = $(item);\n\t  var isChecked = $item.hasClass(options.selectedClass);\n\n\t  if (this.multiple) {\n\t    // multiple\n\t    var checkedLength = this.$list.find('.' + options.selectedClass).length;\n\n\t    if (!isChecked && this.maxChecked <= checkedLength) {\n\t      this.$element.trigger('checkedOverflow.selected.amui', {\n\t        selected: this\n\t      });\n\n\t      return false;\n\t    }\n\t  } else {\n\t    if (isChecked) {\n\t      return false;\n\t    }\n\n\t    this.dropdown.close();\n\t    this.$shadowOptions.not($item).removeClass(options.selectedClass);\n\t  }\n\n\t  $item.toggleClass(options.selectedClass);\n\t  this.syncData(item);\n\t};\n\n\t/**\n\t * syncData\n\t * @desc if `item` set, only sync `item` related option\n\t * @param {Object} item\n\t */\n\tSelected.prototype.syncData = function(item) {\n\t  var _this = this;\n\t  var options = this.options;\n\t  var status = [];\n\t  var $checked = $([]);\n\n\t  this.$shadowOptions.filter('.' + options.selectedClass).each(function() {\n\t    var $this = $(this);\n\t    status.push($this.find('.am-selected-text').text());\n\n\t    if (!item) {\n\t      $checked = $checked.add(_this.$originalOptions\n\t        .filter('[value=\"' + $this.data('value') + '\"]')\n\t        .prop('selected', true));\n\t    }\n\t  });\n\n\t  if (item) {\n\t    var $item = $(item);\n\t    this.$originalOptions\n\t      .filter('[value=\"' + $item.data('value') + '\"]')\n\t      .prop('selected', $item.hasClass(options.selectedClass));\n\t  } else {\n\t    this.$originalOptions.not($checked).prop('selected', false);\n\t  }\n\n\t  // nothing selected\n\t  if (!this.$element.val()) {\n\t    status = [options.placeholder];\n\t  }\n\n\t  this.$status.text(status.join(', '));\n\n\t  // Do not trigger change event on initializing\n\t  this.initialized && this.$element.trigger('change');\n\t};\n\n\tSelected.prototype.bindEvents = function() {\n\t  var _this = this;\n\t  var header = 'am-selected-list-header';\n\t  var handleKeyup = UI.utils.debounce(function(e) {\n\t    _this.$shadowOptions.not('.' + header).hide().\n\t     filter(':containsNC(\"' + e.target.value + '\")').show();\n\t  }, 100);\n\n\t  this.$list.on('click', '> li', function(e) {\n\t    var $this = $(this);\n\t    !$this.hasClass(_this.options.disabledClass) &&\n\t      !$this.hasClass(header) && _this.setChecked(this);\n\t  });\n\n\t  // simple search with jQuery :contains\n\t  this.$searchField.on('keyup.selected.amui', handleKeyup);\n\n\t  // empty search keywords\n\t  this.$selector.on('closed.dropdown.amui', function() {\n\t    _this.$searchField.val('');\n\t    _this.$shadowOptions.css({display: ''});\n\t  });\n\n\t  // work with Validator\n\t  // @since 2.5\n\t  this.$element.on('validated.field.validator.amui', function(e) {\n\t    if (e.validity) {\n\t      var valid = e.validity.valid;\n\t      var errorClassName = 'am-invalid';\n\n\t      _this.$selector[(!valid ? 'add' : 'remove') + 'Class'](errorClassName);\n\t    }\n\t  });\n\n\t  // observe DOM\n\t  if (UI.support.mutationobserver) {\n\t    this.observer = new UI.support.mutationobserver(function() {\n\t      _this.$element.trigger('changed.selected.amui');\n\t    });\n\n\t    this.observer.observe(this.$element[0], {\n\t      childList: true,\n\t      attributes: true,\n\t      subtree: true,\n\t      characterData: true\n\t    });\n\t  }\n\n\t  // custom event\n\t  this.$element.on('changed.selected.amui', function() {\n\t    _this.renderOptions();\n\t    _this.syncData();\n\t  });\n\t};\n\n\t// @since: 2.5\n\tSelected.prototype.select = function(item) {\n\t  var $item;\n\n\t  if (typeof item === 'number') {\n\t    $item = this.$list.find('> li').not('.am-selected-list-header').eq(item);\n\t  } else if (typeof item === 'string') {\n\t    $item = this.$list.find(item);\n\t  } else {\n\t    $item = $(item);\n\t  }\n\n\t  $item.trigger('click');\n\t},\n\n\t// @since: 2.5\n\tSelected.prototype.enable = function() {\n\t  this.$element.prop('disable', false);\n\t  this.$selector.dropdown('enable');\n\t},\n\n\t// @since: 2.5\n\tSelected.prototype.disable = function() {\n\t  this.$element.prop('disable', true);\n\t  this.$selector.dropdown('disable');\n\t},\n\n\tSelected.prototype.destroy = function() {\n\t  this.$element.removeData('amui.selected').show();\n\t  this.$selector.remove();\n\t};\n\n\tUI.plugin('selected', Selected);\n\n\t// Conflict with jQuery form\n\t// https://github.com/malsup/form/blob/6bf24a5f6d8be65f4e5491863180c09356d9dadd/jquery.form.js#L1240-L1258\n\t// https://github.com/allmobilize/amazeui/issues/379\n\t// @deprecated: $.fn.selected = $.fn.selectIt = Plugin;\n\n\t// New way to resolve conflict:\n\t// @see https://github.com/amazeui/amazeui/issues/781#issuecomment-158873541\n\n\tUI.ready(function(context) {\n\t  $('[data-am-selected]', context).selected();\n\t});\n\n\tmodule.exports = Selected;\n\n\n/***/ },\n/* 25 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\t__webpack_require__(15);\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\tvar QRCode = __webpack_require__(26);\n\tvar doc = document;\n\tvar $doc = $(doc);\n\n\tvar Share = function(options) {\n\t  this.options = $.extend({}, Share.DEFAULTS, options || {});\n\t  this.$element = null;\n\t  this.$wechatQr = null;\n\t  this.pics = null;\n\t  this.inited = false;\n\t  this.active = false;\n\t  // this.init();\n\t};\n\n\tShare.DEFAULTS = {\n\t  sns: ['weibo', 'qq', 'qzone', 'tqq', 'wechat', 'renren'],\n\t  title: '分享到',\n\t  cancel: '取消',\n\t  closeOnShare: true,\n\t  id: UI.utils.generateGUID('am-share'),\n\t  desc: 'Hi，孤夜观天象，发现一个不错的西西，分享一下下 ;-)',\n\t  via: 'Amaze UI',\n\t  tpl: '<div class=\"am-share am-modal-actions\" id=\"<%= id %>\">' +\n\t  '<h3 class=\"am-share-title\"><%= title %></h3>' +\n\t  '<ul class=\"am-share-sns am-avg-sm-3\">' +\n\t  '<% for(var i = 0; i < sns.length; i++) {%>' +\n\t  '<li>' +\n\t  '<a href=\"<%= sns[i].shareUrl %>\" ' +\n\t  'data-am-share-to=\"<%= sns[i].id %>\" >' +\n\t  '<i class=\"am-icon-<%= sns[i].icon %>\"></i>' +\n\t  '<span><%= sns[i].title %></span>' +\n\t  '</a></li>' +\n\t  '<% } %></ul>' +\n\t  '<div class=\"am-share-footer\">' +\n\t  '<button class=\"am-btn am-btn-default am-btn-block\" ' +\n\t  'data-am-share-close><%= cancel %></button></div>' +\n\t  '</div>'\n\t};\n\n\tShare.SNS = {\n\t  weibo: {\n\t    title: '新浪微博',\n\t    url: 'http://service.weibo.com/share/share.php',\n\t    width: 620,\n\t    height: 450,\n\t    icon: 'weibo'\n\t  },\n\t  // url          链接地址\n\t  // title:”,     分享的文字内容(可选，默认为所在页面的title)\n\t  // appkey:”,    您申请的应用appkey,显示分享来源(可选)\n\t  // pic:”,       分享图片的路径(可选)\n\t  // ralateUid:”, 关联用户的UID，分享微博会@该用户(可选)\n\t  // NOTE: 会自动抓取图片，不用指定 pic\n\n\t  qq: {\n\t    title: 'QQ 好友',\n\t    url: 'http://connect.qq.com/widget/shareqq/index.html',\n\t    icon: 'qq'\n\t  },\n\t  // url:,\n\t  // title:'',    分享标题(可选)\n\t  // pics:'',     分享图片的路径(可选)\n\t  // summary:'',  分享摘要(可选)\n\t  // site:'',     分享来源 如：腾讯网(可选)\n\t  // desc: ''     发送给用户的消息\n\t  // NOTE: 经过测试，最终发给用户的只有 url 和 desc\n\n\t  qzone: {\n\t    title: 'QQ 空间',\n\t    url: 'http://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey',\n\t    icon: 'star'\n\t  },\n\t  // http://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?url=xxx&title=xxx&desc=&summary=&site=\n\t  // url:,\n\t  // title:'',    分享标题(可选)\n\t  // desc:'',     默认分享理由(可选)\n\t  // summary:'',  分享摘要(可选)\n\t  // site:'',     分享来源 如：腾讯网(可选)\n\t  // pics:'',     分享图片的路径(可选)，不会自动抓取，多个图片用|分隔\n\n\t  tqq: {\n\t    title: '腾讯微博',\n\t    url: 'http://v.t.qq.com/share/share.php',\n\t    icon: 'tencent-weibo'\n\t  },\n\t  // url=xx&title=&appkey=801cf76d3cfc44ada52ec13114e84a96\n\t  // url\n\t  // title\n\t  // pic 多个图片用 | 分隔\n\t  // appkey\n\t  // NOTE: 不会自动抓取图片\n\n\t  wechat: {\n\t    title: '微信',\n\t    url: '[qrcode]',\n\t    icon: 'wechat'\n\t  },\n\t  // 生成一个二维码 供用户扫描\n\t  // 相关接口 https://github.com/zxlie/WeixinApi\n\n\t  renren: {\n\t    title: '人人网',\n\t    url: 'http://widget.renren.com/dialog/share',\n\t    icon: 'renren'\n\t  },\n\t  // http://widget.renren.com/dialog/share?resourceUrl=www&srcUrl=www&title=ww&description=xxx\n\t  // 550 * 400\n\t  // resourceUrl : '', // 分享的资源Url\n\t  // srcUrl : '',\t     // 分享的资源来源Url,\n\t  //                   //   默认为header中的Referer,如果分享失败可以调整此值为resourceUrl试试\n\t  // pic : '',\t\t // 分享的主题图片，会自动抓取\n\t  // title : '',\t\t // 分享的标题\n\t  // description : ''\t // 分享的详细描述\n\t  // NOTE: 经过测试，直接使用 url 参数即可\n\n\t  douban: {\n\t    title: '豆瓣',\n\t    url: 'http://www.douban.com/recommend/',\n\t    icon: 'share-alt'\n\t  },\n\t  // http://www.douban.com/service/sharebutton\n\t  // 450 * 330\n\t  // http://www.douban.com/share/service?bm=1&image=&href=xxx&updated=&name=\n\t  // href 链接\n\t  // name 标题\n\n\t  /* void (function() {\n\t   var d = document, e = encodeURIComponent,\n\t   s1 = window.getSelection, s2 = d.getSelection,\n\t   s3 = d.selection, s = s1 ? s1()\n\t   : s2 ? s2() : s3 ? s3.createRange().text : '',\n\t   r = 'http://www.douban.com/recommend/?url=&title=&sel=&v=1&r=1'\n\t   })();\n\t   */\n\n\t  // tsohu: '',\n\t  // http://t.sohu.com/third/post.jsp?url=&title=&content=utf-8&pic=\n\n\t  // print: '',\n\n\t  mail: {\n\t    title: '邮件分享',\n\t    url: 'mailto:',\n\t    icon: 'envelope-o'\n\t  },\n\n\t  sms: {\n\t    title: '短信分享',\n\t    url: 'sms:',\n\t    icon: 'comment'\n\t  }\n\t};\n\n\tShare.prototype.render = function() {\n\t  var options = this.options;\n\t  var snsData = [];\n\t  var title = encodeURIComponent(doc.title);\n\t  var link = encodeURIComponent(doc.location);\n\t  var msgBody = '?body=' + title + link;\n\n\t  options.sns.forEach(function(item, i) {\n\t    if (Share.SNS[item]) {\n\t      var tmp = Share.SNS[item];\n\t      var shareUrl;\n\n\t      tmp.id = item;\n\n\t      if (item === 'mail') {\n\t        shareUrl = msgBody + '&subject=' + options.desc;\n\t      } else if (item === 'sms') {\n\t        shareUrl = msgBody;\n\t      } else {\n\t        shareUrl = '?url=' + link + '&title=' + title;\n\t      }\n\n\t      tmp.shareUrl = tmp.url + shareUrl;\n\n\t      snsData.push(tmp);\n\t    }\n\t  });\n\n\t  return UI.template(options.tpl, $.extend({}, options, {sns: snsData}));\n\t};\n\n\tShare.prototype.init = function() {\n\t  if (this.inited) {\n\t    return;\n\t  }\n\n\t  var me = this;\n\t  var shareItem = '[data-am-share-to]';\n\n\t  $doc.ready($.proxy(function() {\n\t    $('body').append(this.render()); // append share DOM to body\n\t    this.$element = $('#' + this.options.id);\n\n\t    this.$element.find('[data-am-share-close]').\n\t      on('click.share.amui', function() {\n\t        me.close();\n\t      });\n\t  }, this));\n\n\t  $doc.on('click.share.amui', shareItem, $.proxy(function(e) {\n\t    var $clicked = $(e.target);\n\t    var $target = $clicked.is(shareItem) && $clicked ||\n\t      $clicked.parent(shareItem);\n\t    var sns = $target.attr('data-am-share-to');\n\n\t    if (!(sns === 'mail' || sns === 'sms')) {\n\t      e.preventDefault();\n\t      this.shareTo(sns, this.setData(sns));\n\t    }\n\n\t    this.close();\n\t  }, this));\n\n\t  this.inited = true;\n\t};\n\n\tShare.prototype.open = function() {\n\t  !this.inited && this.init();\n\t  this.$element && this.$element.modal('open');\n\t  this.$element.trigger('open.share.amui');\n\t  this.active = true;\n\t};\n\n\tShare.prototype.close = function() {\n\t  this.$element && this.$element.modal('close');\n\t  this.$element.trigger('close.share.amui');\n\t  this.active = false;\n\t};\n\n\tShare.prototype.toggle = function() {\n\t  this.active ? this.close() : this.open();\n\t};\n\n\tShare.prototype.setData = function(sns) {\n\t  if (!sns) {\n\t    return;\n\t  }\n\n\t  var shareData = {\n\t    url: doc.location,\n\t    title: doc.title\n\t  };\n\t  var desc = this.options.desc;\n\t  var imgSrc = this.pics || [];\n\t  var qqReg = /^(qzone|qq|tqq)$/;\n\n\t  if (qqReg.test(sns) && !imgSrc.length) {\n\t    var allImages = doc.images;\n\n\t    for (var i = 0; i < allImages.length && i < 10; i++) {\n\t      !!allImages[i].src && imgSrc.push(encodeURIComponent(allImages[i].src));\n\t    }\n\n\t    this.pics = imgSrc; // 缓存图片\n\t  }\n\n\t  switch (sns) {\n\t    case 'qzone':\n\t      shareData.desc = desc;\n\t      shareData.site = this.options.via;\n\t      shareData.pics = imgSrc.join('|');\n\t      // TODO: 抓取图片多张\n\t      break;\n\t    case 'qq':\n\t      shareData.desc = desc;\n\t      shareData.site = this.options.via;\n\t      shareData.pics = imgSrc[0];\n\t      // 抓取一张图片\n\t      break;\n\t    case 'tqq':\n\t      // 抓取图片多张\n\t      shareData.pic = imgSrc.join('|');\n\t      break;\n\t  }\n\n\t  return shareData;\n\t};\n\n\tShare.prototype.shareTo = function(sns, data) {\n\t  var snsInfo = Share.SNS[sns];\n\n\t  if (!snsInfo) {\n\t    return;\n\t  }\n\n\t  if (sns === 'wechat' || sns === 'weixin') {\n\t    return this.wechatQr();\n\t  }\n\n\t  var query = [];\n\t  for (var key in data) {\n\t    if (data[key]) {\n\t      // 避免 encode 图片分隔符 |\n\t      query.push(key.toString() + '=' + ((key === 'pic' || key === 'pics') ?\n\t        data[key] : encodeURIComponent(data[key])));\n\t    }\n\t  }\n\n\t  window.open(snsInfo.url + '?' + query.join('&'));\n\t};\n\n\tShare.prototype.wechatQr = function() {\n\t  if (!this.$wechatQr) {\n\t    var qrId = UI.utils.generateGUID('am-share-wechat');\n\t    var $qr = $('<div class=\"am-modal am-modal-no-btn am-share-wechat-qr\">' +\n\t    '<div class=\"am-modal-dialog\"><div class=\"am-modal-hd\">分享到微信 ' +\n\t    '<a href=\"\" class=\"am-close am-close-spin\" ' +\n\t    'data-am-modal-close>&times;</a> </div>' +\n\t    '<div class=\"am-modal-bd\">' +\n\t    '<div class=\"am-share-wx-qr\"></div>' +\n\t    '<div class=\"am-share-wechat-tip\">' +\n\t    '打开微信，点击底部的<em>发现</em>，<br/> ' +\n\t    '使用<em>扫一扫</em>将网页分享至朋友圈</div></div></div></div>');\n\n\t    $qr.attr('id', qrId);\n\n\t    var qrNode = new QRCode({\n\t      render: 'canvas',\n\t      correctLevel: 0,\n\t      text: doc.location.href,\n\t      width: 180,\n\t      height: 180,\n\t      background: '#fff',\n\t      foreground: '#000'\n\t    });\n\n\t    $qr.find('.am-share-wx-qr').html(qrNode);\n\n\t    $qr.appendTo($('body'));\n\n\t    this.$wechatQr = $('#' + qrId);\n\t  }\n\n\t  this.$wechatQr.modal('open');\n\t};\n\n\tvar share = new Share();\n\n\t$doc.on('click.share.amui.data-api', '[data-am-toggle=\"share\"]', function(e) {\n\t  e.preventDefault();\n\t  share.toggle();\n\t});\n\n\tmodule.exports = UI.share = share;\n\n\n/***/ },\n/* 26 */\n/***/ function(module, exports, __webpack_require__) {\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\n\t/**\n\t * @ver 1.1.0\n\t * @via https://github.com/aralejs/qrcode/blob/master/src/qrcode.js\n\t * @license http://aralejs.org/\n\t */\n\n\tvar qrcodeAlgObjCache = [];\n\n\t/**\n\t * 二维码构造函数，主要用于绘制\n\t * @param  {Object} opt 传递参数\n\t * @return {String} qrcode\n\t * @constructor\n\t */\n\tvar QRCode = function(opt) {\n\t  if (typeof opt === 'string') { // 只编码ASCII字符串\n\t    opt = {\n\t      text: opt\n\t    };\n\t  }\n\t  // 设置默认参数\n\t  this.options = $.extend({}, {\n\t    text: \"\",\n\t    render: \"\",\n\t    width: 256,\n\t    height: 256,\n\t    correctLevel: 3,\n\t    background: \"#ffffff\",\n\t    foreground: \"#000000\"\n\t  }, opt);\n\n\t  // 使用QRCodeAlg创建二维码结构\n\t  var qrCodeAlg = null;\n\t  for (var i = 0, l = qrcodeAlgObjCache.length; i < l; i++) {\n\t    if (qrcodeAlgObjCache[i].text == this.options.text && qrcodeAlgObjCache[i].text.correctLevel == this.options.correctLevel) {\n\t      qrCodeAlg = qrcodeAlgObjCache[i].obj;\n\t      break;\n\t    }\n\t  }\n\t  if (i == l) {\n\t    qrCodeAlg = new QRCodeAlg(this.options.text, this.options.correctLevel);\n\t    qrcodeAlgObjCache.push({\n\t      text: this.options.text,\n\t      correctLevel: this.options.correctLevel,\n\t      obj: qrCodeAlg\n\t    });\n\t  }\n\n\t  if (this.options.render) {\n\t    switch (this.options.render) {\n\t      case \"canvas\":\n\t        return this.createCanvas(qrCodeAlg);\n\t      case \"table\":\n\t        return this.createTable(qrCodeAlg);\n\t      case \"svg\":\n\t        return this.createSVG(qrCodeAlg);\n\t      default:\n\t        return this.createDefault(qrCodeAlg);\n\t    }\n\t  }\n\t  return this.createDefault(qrCodeAlg);\n\t};\n\t/**\n\t * 使用Canvas来画二维码\n\t * @return {}\n\t */\n\n\tQRCode.prototype.createDefault = function(qrCodeAlg) {\n\t  var canvas = document.createElement('canvas');\n\t  if (canvas.getContext)\n\t    return this.createCanvas(qrCodeAlg);\n\t  if (!!document.createElementNS && !!document.createElementNS(SVG_NS, 'svg').createSVGRect)\n\t    return this.createSVG(qrCodeAlg);\n\t  return this.createTable(qrCodeAlg);\n\t};\n\tQRCode.prototype.createCanvas = function(qrCodeAlg) {\n\t  //创建canvas节点\n\t  var canvas = document.createElement('canvas');\n\t  canvas.width = this.options.width;\n\t  canvas.height = this.options.height;\n\t  var ctx = canvas.getContext('2d');\n\n\t  //计算每个点的长宽\n\t  var tileW = (this.options.width / qrCodeAlg.getModuleCount()).toPrecision(4);\n\t  var tileH = this.options.height / qrCodeAlg.getModuleCount().toPrecision(4);\n\n\t  //绘制\n\t  for (var row = 0; row < qrCodeAlg.getModuleCount(); row++) {\n\t    for (var col = 0; col < qrCodeAlg.getModuleCount(); col++) {\n\t      ctx.fillStyle = qrCodeAlg.modules[row][col] ? this.options.foreground : this.options.background;\n\t      var w = (Math.ceil((col + 1) * tileW) - Math.floor(col * tileW));\n\t      var h = (Math.ceil((row + 1) * tileW) - Math.floor(row * tileW));\n\t      ctx.fillRect(Math.round(col * tileW), Math.round(row * tileH), w, h);\n\t    }\n\t  }\n\t  //返回绘制的节点\n\t  return canvas;\n\t};\n\t/**\n\t * 使用table来绘制二维码\n\t * @return {}\n\t */\n\tQRCode.prototype.createTable = function(qrCodeAlg) {\n\t  //创建table节点\n\t  var s = [];\n\t  s.push('<table style=\"border:0px; margin:0px; padding:0px; border-collapse:collapse; background-color: ' +\n\t  this.options.background +\n\t  ';\">');\n\t  // 计算每个节点的长宽；取整，防止点之间出现分离\n\t  var tileW = -1, tileH = -1, caculateW = -1, caculateH = -1;\n\t  tileW = caculateW = Math.floor(this.options.width / qrCodeAlg.getModuleCount());\n\t  tileH = caculateH = Math.floor(this.options.height / qrCodeAlg.getModuleCount());\n\t  if (caculateW <= 0) {\n\t    if (qrCodeAlg.getModuleCount() < 80) {\n\t      tileW = 2;\n\t    } else {\n\t      tileW = 1;\n\t    }\n\t  }\n\t  if (caculateH <= 0) {\n\t    if (qrCodeAlg.getModuleCount() < 80) {\n\t      tileH = 2;\n\t    } else {\n\t      tileH = 1;\n\t    }\n\t  }\n\n\t  // 绘制二维码\n\t  foreTd = '<td style=\"border:0px; margin:0px; padding:0px; width:' + tileW + 'px; background-color: ' + this.options.foreground + '\"></td>',\n\t    backTd = '<td style=\"border:0px; margin:0px; padding:0px; width:' + tileW + 'px; background-color: ' + this.options.background + '\"></td>',\n\t    l = qrCodeAlg.getModuleCount();\n\n\t  for (var row = 0; row < l; row++) {\n\t    s.push('<tr style=\"border:0px; margin:0px; padding:0px; height: ' + tileH + 'px\">');\n\t    for (var col = 0; col < l; col++) {\n\t      s.push(qrCodeAlg.modules[row][col] ? foreTd : backTd);\n\t    }\n\t    s.push('</tr>');\n\t  }\n\t  s.push('</table>');\n\t  var span = document.createElement(\"span\");\n\t  span.innerHTML = s.join('');\n\n\t  return span.firstChild;\n\t};\n\n\t/**\n\t * 使用SVG开绘制二维码\n\t * @return {}\n\t */\n\tQRCode.prototype.createSVG = function(qrCodeAlg) {\n\t  var x, dx, y, dy,\n\t    moduleCount = qrCodeAlg.getModuleCount(),\n\t    scale = this.options.height / this.options.width,\n\t    svg = '<svg xmlns=\"http://www.w3.org/2000/svg\" '\n\t      + 'width=\"' + this.options.width + 'px\" height=\"' + this.options.height + 'px\" '\n\t      + 'viewbox=\"0 0 ' + moduleCount * 10 + ' ' + moduleCount * 10 * scale + '\">',\n\t    rectHead = '<path ',\n\t    foreRect = ' style=\"stroke-width:0.5;stroke:' + this.options.foreground\n\t      + ';fill:' + this.options.foreground + ';\"></path>',\n\t    backRect = ' style=\"stroke-width:0.5;stroke:' + this.options.background\n\t      + ';fill:' + this.options.background + ';\"></path>';\n\n\t  // draw in the svg\n\t  for (var row = 0; row < moduleCount; row++) {\n\t    for (var col = 0; col < moduleCount; col++) {\n\t      x = col * 10;\n\t      y = row * 10 * scale;\n\t      dx = (col + 1) * 10;\n\t      dy = (row + 1) * 10 * scale;\n\n\t      svg += rectHead + 'd=\"M ' + x + ',' + y\n\t      + ' L ' + dx + ',' + y\n\t      + ' L ' + dx + ',' + dy\n\t      + ' L ' + x + ',' + dy\n\t      + ' Z\"';\n\n\t      svg += qrCodeAlg.modules[row][col] ? foreRect : backRect;\n\t    }\n\t  }\n\n\t  svg += '</svg>';\n\n\t  // return just built svg\n\t  return $(svg)[0];\n\t};\n\n\t/**\n\t * 获取单个字符的utf8编码\n\t * unicode BMP平面约65535个字符\n\t * @param {num} code\n\t * return {array}\n\t */\n\tfunction unicodeFormat8(code) {\n\t  // 1 byte\n\t  if (code < 128) {\n\t    return [code];\n\t    // 2 bytes\n\t  } else if (code < 2048) {\n\t    c0 = 192 + (code >> 6);\n\t    c1 = 128 + (code & 63);\n\t    return [c0, c1];\n\t    // 3 bytes\n\t  } else {\n\t    c0 = 224 + (code >> 12);\n\t    c1 = 128 + (code >> 6 & 63);\n\t    c2 = 128 + (code & 63);\n\t    return [c0, c1, c2];\n\t  }\n\t}\n\n\t/**\n\t * 获取字符串的utf8编码字节串\n\t * @param {string} string\n\t * @return {array}\n\t */\n\tfunction getUTF8Bytes(string) {\n\t  var utf8codes = [];\n\t  for (var i = 0; i < string.length; i++) {\n\t    var code = string.charCodeAt(i);\n\t    var utf8 = unicodeFormat8(code);\n\t    for (var j = 0; j < utf8.length; j++) {\n\t      utf8codes.push(utf8[j]);\n\t    }\n\t  }\n\t  return utf8codes;\n\t}\n\n\t/**\n\t * 二维码算法实现\n\t * @param {string} data              要编码的信息字符串\n\t * @param {num} errorCorrectLevel 纠错等级\n\t */\n\tfunction QRCodeAlg(data, errorCorrectLevel) {\n\t  this.typeNumber = -1; // 版本\n\t  this.errorCorrectLevel = errorCorrectLevel;\n\t  this.modules = null;  // 二维矩阵，存放最终结果\n\t  this.moduleCount = 0; // 矩阵大小\n\t  this.dataCache = null; // 数据缓存\n\t  this.rsBlocks = null; // 版本数据信息\n\t  this.totalDataCount = -1; // 可使用的数据量\n\t  this.data = data;\n\t  this.utf8bytes = getUTF8Bytes(data);\n\t  this.make();\n\t}\n\n\tQRCodeAlg.prototype = {\n\t  constructor: QRCodeAlg,\n\t  /**\n\t   * 获取二维码矩阵大小\n\t   * @return {num} 矩阵大小\n\t   */\n\t  getModuleCount: function() {\n\t    return this.moduleCount;\n\t  },\n\t  /**\n\t   * 编码\n\t   */\n\t  make: function() {\n\t    this.getRightType();\n\t    this.dataCache = this.createData();\n\t    this.createQrcode();\n\t  },\n\t  /**\n\t   * 设置二位矩阵功能图形\n\t   * @param  {bool} test 表示是否在寻找最好掩膜阶段\n\t   * @param  {num} maskPattern 掩膜的版本\n\t   */\n\t  makeImpl: function(maskPattern) {\n\n\t    this.moduleCount = this.typeNumber * 4 + 17;\n\t    this.modules = new Array(this.moduleCount);\n\n\t    for (var row = 0; row < this.moduleCount; row++) {\n\n\t      this.modules[row] = new Array(this.moduleCount);\n\n\t    }\n\t    this.setupPositionProbePattern(0, 0);\n\t    this.setupPositionProbePattern(this.moduleCount - 7, 0);\n\t    this.setupPositionProbePattern(0, this.moduleCount - 7);\n\t    this.setupPositionAdjustPattern();\n\t    this.setupTimingPattern();\n\t    this.setupTypeInfo(true, maskPattern);\n\n\t    if (this.typeNumber >= 7) {\n\t      this.setupTypeNumber(true);\n\t    }\n\t    this.mapData(this.dataCache, maskPattern);\n\t  },\n\t  /**\n\t   * 设置二维码的位置探测图形\n\t   * @param  {num} row 探测图形的中心横坐标\n\t   * @param  {num} col 探测图形的中心纵坐标\n\t   */\n\t  setupPositionProbePattern: function(row, col) {\n\n\t    for (var r = -1; r <= 7; r++) {\n\n\t      if (row + r <= -1 || this.moduleCount <= row + r) continue;\n\n\t      for (var c = -1; c <= 7; c++) {\n\n\t        if (col + c <= -1 || this.moduleCount <= col + c) continue;\n\n\t        if ((0 <= r && r <= 6 && (c == 0 || c == 6)) || (0 <= c && c <= 6 && (r == 0 || r == 6)) || (2 <= r && r <= 4 && 2 <= c && c <= 4)) {\n\t          this.modules[row + r][col + c] = true;\n\t        } else {\n\t          this.modules[row + r][col + c] = false;\n\t        }\n\t      }\n\t    }\n\t  },\n\t  /**\n\t   * 创建二维码\n\t   * @return {[type]} [description]\n\t   */\n\t  createQrcode: function() {\n\n\t    var minLostPoint = 0;\n\t    var pattern = 0;\n\t    var bestModules = null;\n\n\t    for (var i = 0; i < 8; i++) {\n\n\t      this.makeImpl(i);\n\n\t      var lostPoint = QRUtil.getLostPoint(this);\n\t      if (i == 0 || minLostPoint > lostPoint) {\n\t        minLostPoint = lostPoint;\n\t        pattern = i;\n\t        bestModules = this.modules;\n\t      }\n\t    }\n\t    this.modules = bestModules;\n\t    this.setupTypeInfo(false, pattern);\n\n\t    if (this.typeNumber >= 7) {\n\t      this.setupTypeNumber(false);\n\t    }\n\n\t  },\n\t  /**\n\t   * 设置定位图形\n\t   * @return {[type]} [description]\n\t   */\n\t  setupTimingPattern: function() {\n\n\t    for (var r = 8; r < this.moduleCount - 8; r++) {\n\t      if (this.modules[r][6] != null) {\n\t        continue;\n\t      }\n\t      this.modules[r][6] = (r % 2 == 0);\n\n\t      if (this.modules[6][r] != null) {\n\t        continue;\n\t      }\n\t      this.modules[6][r] = (r % 2 == 0);\n\t    }\n\t  },\n\t  /**\n\t   * 设置矫正图形\n\t   * @return {[type]} [description]\n\t   */\n\t  setupPositionAdjustPattern: function() {\n\n\t    var pos = QRUtil.getPatternPosition(this.typeNumber);\n\n\t    for (var i = 0; i < pos.length; i++) {\n\n\t      for (var j = 0; j < pos.length; j++) {\n\n\t        var row = pos[i];\n\t        var col = pos[j];\n\n\t        if (this.modules[row][col] != null) {\n\t          continue;\n\t        }\n\n\t        for (var r = -2; r <= 2; r++) {\n\n\t          for (var c = -2; c <= 2; c++) {\n\n\t            if (r == -2 || r == 2 || c == -2 || c == 2 || (r == 0 && c == 0)) {\n\t              this.modules[row + r][col + c] = true;\n\t            } else {\n\t              this.modules[row + r][col + c] = false;\n\t            }\n\t          }\n\t        }\n\t      }\n\t    }\n\t  },\n\t  /**\n\t   * 设置版本信息（7以上版本才有）\n\t   * @param  {bool} test 是否处于判断最佳掩膜阶段\n\t   * @return {[type]}      [description]\n\t   */\n\t  setupTypeNumber: function(test) {\n\n\t    var bits = QRUtil.getBCHTypeNumber(this.typeNumber);\n\n\t    for (var i = 0; i < 18; i++) {\n\t      var mod = (!test && ((bits >> i) & 1) == 1);\n\t      this.modules[Math.floor(i / 3)][i % 3 + this.moduleCount - 8 - 3] = mod;\n\t      this.modules[i % 3 + this.moduleCount - 8 - 3][Math.floor(i / 3)] = mod;\n\t    }\n\t  },\n\t  /**\n\t   * 设置格式信息（纠错等级和掩膜版本）\n\t   * @param  {bool} test\n\t   * @param  {num} maskPattern 掩膜版本\n\t   * @return {}\n\t   */\n\t  setupTypeInfo: function(test, maskPattern) {\n\n\t    var data = (QRErrorCorrectLevel[this.errorCorrectLevel] << 3) | maskPattern;\n\t    var bits = QRUtil.getBCHTypeInfo(data);\n\n\t    // vertical\n\t    for (var i = 0; i < 15; i++) {\n\n\t      var mod = (!test && ((bits >> i) & 1) == 1);\n\n\t      if (i < 6) {\n\t        this.modules[i][8] = mod;\n\t      } else if (i < 8) {\n\t        this.modules[i + 1][8] = mod;\n\t      } else {\n\t        this.modules[this.moduleCount - 15 + i][8] = mod;\n\t      }\n\n\t      // horizontal\n\t      var mod = (!test && ((bits >> i) & 1) == 1);\n\n\t      if (i < 8) {\n\t        this.modules[8][this.moduleCount - i - 1] = mod;\n\t      } else if (i < 9) {\n\t        this.modules[8][15 - i - 1 + 1] = mod;\n\t      } else {\n\t        this.modules[8][15 - i - 1] = mod;\n\t      }\n\t    }\n\n\t    // fixed module\n\t    this.modules[this.moduleCount - 8][8] = (!test);\n\n\t  },\n\t  /**\n\t   * 数据编码\n\t   * @return {[type]} [description]\n\t   */\n\t  createData: function() {\n\t    var buffer = new QRBitBuffer();\n\t    var lengthBits = this.typeNumber > 9 ? 16 : 8;\n\t    buffer.put(4, 4); //添加模式\n\t    buffer.put(this.utf8bytes.length, lengthBits);\n\t    for (var i = 0, l = this.utf8bytes.length; i < l; i++) {\n\t      buffer.put(this.utf8bytes[i], 8);\n\t    }\n\t    if (buffer.length + 4 <= this.totalDataCount * 8) {\n\t      buffer.put(0, 4);\n\t    }\n\n\t    // padding\n\t    while (buffer.length % 8 != 0) {\n\t      buffer.putBit(false);\n\t    }\n\n\t    // padding\n\t    while (true) {\n\n\t      if (buffer.length >= this.totalDataCount * 8) {\n\t        break;\n\t      }\n\t      buffer.put(QRCodeAlg.PAD0, 8);\n\n\t      if (buffer.length >= this.totalDataCount * 8) {\n\t        break;\n\t      }\n\t      buffer.put(QRCodeAlg.PAD1, 8);\n\t    }\n\t    return this.createBytes(buffer);\n\t  },\n\t  /**\n\t   * 纠错码编码\n\t   * @param  {buffer} buffer 数据编码\n\t   * @return {[type]}\n\t   */\n\t  createBytes: function(buffer) {\n\n\t    var offset = 0;\n\n\t    var maxDcCount = 0;\n\t    var maxEcCount = 0;\n\n\t    var length = this.rsBlock.length / 3;\n\n\t    var rsBlocks = new Array();\n\n\t    for (var i = 0; i < length; i++) {\n\n\t      var count = this.rsBlock[i * 3 + 0];\n\t      var totalCount = this.rsBlock[i * 3 + 1];\n\t      var dataCount = this.rsBlock[i * 3 + 2];\n\n\t      for (var j = 0; j < count; j++) {\n\t        rsBlocks.push([dataCount, totalCount]);\n\t      }\n\t    }\n\n\t    var dcdata = new Array(rsBlocks.length);\n\t    var ecdata = new Array(rsBlocks.length);\n\n\t    for (var r = 0; r < rsBlocks.length; r++) {\n\n\t      var dcCount = rsBlocks[r][0];\n\t      var ecCount = rsBlocks[r][1] - dcCount;\n\n\t      maxDcCount = Math.max(maxDcCount, dcCount);\n\t      maxEcCount = Math.max(maxEcCount, ecCount);\n\n\t      dcdata[r] = new Array(dcCount);\n\n\t      for (var i = 0; i < dcdata[r].length; i++) {\n\t        dcdata[r][i] = 0xff & buffer.buffer[i + offset];\n\t      }\n\t      offset += dcCount;\n\n\t      var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount);\n\t      var rawPoly = new QRPolynomial(dcdata[r], rsPoly.getLength() - 1);\n\n\t      var modPoly = rawPoly.mod(rsPoly);\n\t      ecdata[r] = new Array(rsPoly.getLength() - 1);\n\t      for (var i = 0; i < ecdata[r].length; i++) {\n\t        var modIndex = i + modPoly.getLength() - ecdata[r].length;\n\t        ecdata[r][i] = (modIndex >= 0) ? modPoly.get(modIndex) : 0;\n\t      }\n\t    }\n\n\t    var data = new Array(this.totalDataCount);\n\t    var index = 0;\n\n\t    for (var i = 0; i < maxDcCount; i++) {\n\t      for (var r = 0; r < rsBlocks.length; r++) {\n\t        if (i < dcdata[r].length) {\n\t          data[index++] = dcdata[r][i];\n\t        }\n\t      }\n\t    }\n\n\t    for (var i = 0; i < maxEcCount; i++) {\n\t      for (var r = 0; r < rsBlocks.length; r++) {\n\t        if (i < ecdata[r].length) {\n\t          data[index++] = ecdata[r][i];\n\t        }\n\t      }\n\t    }\n\n\t    return data;\n\n\t  },\n\t  /**\n\t   * 布置模块，构建最终信息\n\t   * @param  {} data\n\t   * @param  {} maskPattern\n\t   * @return {}\n\t   */\n\t  mapData: function(data, maskPattern) {\n\n\t    var inc = -1;\n\t    var row = this.moduleCount - 1;\n\t    var bitIndex = 7;\n\t    var byteIndex = 0;\n\n\t    for (var col = this.moduleCount - 1; col > 0; col -= 2) {\n\n\t      if (col == 6) col--;\n\n\t      while (true) {\n\n\t        for (var c = 0; c < 2; c++) {\n\n\t          if (this.modules[row][col - c] == null) {\n\n\t            var dark = false;\n\n\t            if (byteIndex < data.length) {\n\t              dark = (((data[byteIndex] >>> bitIndex) & 1) == 1);\n\t            }\n\n\t            var mask = QRUtil.getMask(maskPattern, row, col - c);\n\n\t            if (mask) {\n\t              dark = !dark;\n\t            }\n\n\t            this.modules[row][col - c] = dark;\n\t            bitIndex--;\n\n\t            if (bitIndex == -1) {\n\t              byteIndex++;\n\t              bitIndex = 7;\n\t            }\n\t          }\n\t        }\n\n\t        row += inc;\n\n\t        if (row < 0 || this.moduleCount <= row) {\n\t          row -= inc;\n\t          inc = -inc;\n\t          break;\n\t        }\n\t      }\n\t    }\n\t  }\n\n\t};\n\t/**\n\t * 填充字段\n\t */\n\tQRCodeAlg.PAD0 = 0xEC;\n\tQRCodeAlg.PAD1 = 0x11;\n\n\n\t//---------------------------------------------------------------------\n\t// 纠错等级对应的编码\n\t//---------------------------------------------------------------------\n\n\tvar QRErrorCorrectLevel = [1, 0, 3, 2];\n\n\t//---------------------------------------------------------------------\n\t// 掩膜版本\n\t//---------------------------------------------------------------------\n\n\tvar QRMaskPattern = {\n\t  PATTERN000: 0,\n\t  PATTERN001: 1,\n\t  PATTERN010: 2,\n\t  PATTERN011: 3,\n\t  PATTERN100: 4,\n\t  PATTERN101: 5,\n\t  PATTERN110: 6,\n\t  PATTERN111: 7\n\t};\n\n\t//---------------------------------------------------------------------\n\t// 工具类\n\t//---------------------------------------------------------------------\n\n\tvar QRUtil = {\n\n\t  /*\n\t   每个版本矫正图形的位置\n\t   */\n\t  PATTERN_POSITION_TABLE: [\n\t    [],\n\t    [6, 18],\n\t    [6, 22],\n\t    [6, 26],\n\t    [6, 30],\n\t    [6, 34],\n\t    [6, 22, 38],\n\t    [6, 24, 42],\n\t    [6, 26, 46],\n\t    [6, 28, 50],\n\t    [6, 30, 54],\n\t    [6, 32, 58],\n\t    [6, 34, 62],\n\t    [6, 26, 46, 66],\n\t    [6, 26, 48, 70],\n\t    [6, 26, 50, 74],\n\t    [6, 30, 54, 78],\n\t    [6, 30, 56, 82],\n\t    [6, 30, 58, 86],\n\t    [6, 34, 62, 90],\n\t    [6, 28, 50, 72, 94],\n\t    [6, 26, 50, 74, 98],\n\t    [6, 30, 54, 78, 102],\n\t    [6, 28, 54, 80, 106],\n\t    [6, 32, 58, 84, 110],\n\t    [6, 30, 58, 86, 114],\n\t    [6, 34, 62, 90, 118],\n\t    [6, 26, 50, 74, 98, 122],\n\t    [6, 30, 54, 78, 102, 126],\n\t    [6, 26, 52, 78, 104, 130],\n\t    [6, 30, 56, 82, 108, 134],\n\t    [6, 34, 60, 86, 112, 138],\n\t    [6, 30, 58, 86, 114, 142],\n\t    [6, 34, 62, 90, 118, 146],\n\t    [6, 30, 54, 78, 102, 126, 150],\n\t    [6, 24, 50, 76, 102, 128, 154],\n\t    [6, 28, 54, 80, 106, 132, 158],\n\t    [6, 32, 58, 84, 110, 136, 162],\n\t    [6, 26, 54, 82, 110, 138, 166],\n\t    [6, 30, 58, 86, 114, 142, 170]\n\t  ],\n\n\t  G15: (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0),\n\t  G18: (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0),\n\t  G15_MASK: (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1),\n\n\t  /*\n\t   BCH编码格式信息\n\t   */\n\t  getBCHTypeInfo: function(data) {\n\t    var d = data << 10;\n\t    while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) >= 0) {\n\t      d ^= (QRUtil.G15 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15)));\n\t    }\n\t    return ((data << 10) | d) ^ QRUtil.G15_MASK;\n\t  },\n\t  /*\n\t   BCH编码版本信息\n\t   */\n\t  getBCHTypeNumber: function(data) {\n\t    var d = data << 12;\n\t    while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) >= 0) {\n\t      d ^= (QRUtil.G18 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18)));\n\t    }\n\t    return (data << 12) | d;\n\t  },\n\t  /*\n\t   获取BCH位信息\n\t   */\n\t  getBCHDigit: function(data) {\n\n\t    var digit = 0;\n\n\t    while (data != 0) {\n\t      digit++;\n\t      data >>>= 1;\n\t    }\n\n\t    return digit;\n\t  },\n\t  /*\n\t   获取版本对应的矫正图形位置\n\t   */\n\t  getPatternPosition: function(typeNumber) {\n\t    return QRUtil.PATTERN_POSITION_TABLE[typeNumber - 1];\n\t  },\n\t  /*\n\t   掩膜算法\n\t   */\n\t  getMask: function(maskPattern, i, j) {\n\n\t    switch (maskPattern) {\n\n\t      case QRMaskPattern.PATTERN000:\n\t        return (i + j) % 2 == 0;\n\t      case QRMaskPattern.PATTERN001:\n\t        return i % 2 == 0;\n\t      case QRMaskPattern.PATTERN010:\n\t        return j % 3 == 0;\n\t      case QRMaskPattern.PATTERN011:\n\t        return (i + j) % 3 == 0;\n\t      case QRMaskPattern.PATTERN100:\n\t        return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 == 0;\n\t      case QRMaskPattern.PATTERN101:\n\t        return (i * j) % 2 + (i * j) % 3 == 0;\n\t      case QRMaskPattern.PATTERN110:\n\t        return ((i * j) % 2 + (i * j) % 3) % 2 == 0;\n\t      case QRMaskPattern.PATTERN111:\n\t        return ((i * j) % 3 + (i + j) % 2) % 2 == 0;\n\n\t      default:\n\t        throw new Error(\"bad maskPattern:\" + maskPattern);\n\t    }\n\t  },\n\t  /*\n\t   获取RS的纠错多项式\n\t   */\n\t  getErrorCorrectPolynomial: function(errorCorrectLength) {\n\n\t    var a = new QRPolynomial([1], 0);\n\n\t    for (var i = 0; i < errorCorrectLength; i++) {\n\t      a = a.multiply(new QRPolynomial([1, QRMath.gexp(i)], 0));\n\t    }\n\n\t    return a;\n\t  },\n\t  /*\n\t   获取评价\n\t   */\n\t  getLostPoint: function(qrCode) {\n\n\t    var moduleCount = qrCode.getModuleCount(),\n\t      lostPoint = 0,\n\t      darkCount = 0;\n\n\t    for (var row = 0; row < moduleCount; row++) {\n\n\t      var sameCount = 0;\n\t      var head = qrCode.modules[row][0];\n\n\t      for (var col = 0; col < moduleCount; col++) {\n\n\t        var current = qrCode.modules[row][col];\n\n\t        //level 3 评价\n\t        if (col < moduleCount - 6) {\n\t          if (current && !qrCode.modules[row][col + 1] && qrCode.modules[row][col + 2] && qrCode.modules[row][col + 3] && qrCode.modules[row][col + 4] && !qrCode.modules[row][col + 5] && qrCode.modules[row][col + 6]) {\n\t            if (col < moduleCount - 10) {\n\t              if (qrCode.modules[row][col + 7] && qrCode.modules[row][col + 8] && qrCode.modules[row][col + 9] && qrCode.modules[row][col + 10]) {\n\t                lostPoint += 40;\n\t              }\n\t            } else if (col > 3) {\n\t              if (qrCode.modules[row][col - 1] && qrCode.modules[row][col - 2] && qrCode.modules[row][col - 3] && qrCode.modules[row][col - 4]) {\n\t                lostPoint += 40;\n\t              }\n\t            }\n\n\t          }\n\t        }\n\n\t        //level 2 评价\n\t        if ((row < moduleCount - 1) && (col < moduleCount - 1)) {\n\t          var count = 0;\n\t          if (current) count++;\n\t          if (qrCode.modules[row + 1][col]) count++;\n\t          if (qrCode.modules[row][col + 1]) count++;\n\t          if (qrCode.modules[row + 1][col + 1]) count++;\n\t          if (count == 0 || count == 4) {\n\t            lostPoint += 3;\n\t          }\n\t        }\n\n\t        //level 1 评价\n\t        if (head ^ current) {\n\t          sameCount++;\n\t        } else {\n\t          head = current;\n\t          if (sameCount >= 5) {\n\t            lostPoint += (3 + sameCount - 5);\n\t          }\n\t          sameCount = 1;\n\t        }\n\n\t        //level 4 评价\n\t        if (current) {\n\t          darkCount++;\n\t        }\n\n\t      }\n\t    }\n\n\t    for (var col = 0; col < moduleCount; col++) {\n\n\t      var sameCount = 0;\n\t      var head = qrCode.modules[0][col];\n\n\t      for (var row = 0; row < moduleCount; row++) {\n\n\t        var current = qrCode.modules[row][col];\n\n\t        //level 3 评价\n\t        if (row < moduleCount - 6) {\n\t          if (current && !qrCode.modules[row + 1][col] && qrCode.modules[row + 2][col] && qrCode.modules[row + 3][col] && qrCode.modules[row + 4][col] && !qrCode.modules[row + 5][col] && qrCode.modules[row + 6][col]) {\n\t            if (row < moduleCount - 10) {\n\t              if (qrCode.modules[row + 7][col] && qrCode.modules[row + 8][col] && qrCode.modules[row + 9][col] && qrCode.modules[row + 10][col]) {\n\t                lostPoint += 40;\n\t              }\n\t            } else if (row > 3) {\n\t              if (qrCode.modules[row - 1][col] && qrCode.modules[row - 2][col] && qrCode.modules[row - 3][col] && qrCode.modules[row - 4][col]) {\n\t                lostPoint += 40;\n\t              }\n\t            }\n\t          }\n\t        }\n\n\t        //level 1 评价\n\t        if (head ^ current) {\n\t          sameCount++;\n\t        } else {\n\t          head = current;\n\t          if (sameCount >= 5) {\n\t            lostPoint += (3 + sameCount - 5);\n\t          }\n\t          sameCount = 1;\n\t        }\n\n\t      }\n\t    }\n\n\t    // LEVEL4\n\n\t    var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;\n\t    lostPoint += ratio * 10;\n\n\t    return lostPoint;\n\t  }\n\n\t};\n\n\n\t//---------------------------------------------------------------------\n\t// QRMath使用的数学工具\n\t//---------------------------------------------------------------------\n\n\tvar QRMath = {\n\t  /*\n\t   将n转化为a^m\n\t   */\n\t  glog: function(n) {\n\n\t    if (n < 1) {\n\t      throw new Error(\"glog(\" + n + \")\");\n\t    }\n\n\t    return QRMath.LOG_TABLE[n];\n\t  },\n\t  /*\n\t   将a^m转化为n\n\t   */\n\t  gexp: function(n) {\n\n\t    while (n < 0) {\n\t      n += 255;\n\t    }\n\n\t    while (n >= 256) {\n\t      n -= 255;\n\t    }\n\n\t    return QRMath.EXP_TABLE[n];\n\t  },\n\n\t  EXP_TABLE: new Array(256),\n\n\t  LOG_TABLE: new Array(256)\n\n\t};\n\n\tfor (var i = 0; i < 8; i++) {\n\t  QRMath.EXP_TABLE[i] = 1 << i;\n\t}\n\tfor (var i = 8; i < 256; i++) {\n\t  QRMath.EXP_TABLE[i] = QRMath.EXP_TABLE[i - 4] ^ QRMath.EXP_TABLE[i - 5] ^ QRMath.EXP_TABLE[i - 6] ^ QRMath.EXP_TABLE[i - 8];\n\t}\n\tfor (var i = 0; i < 255; i++) {\n\t  QRMath.LOG_TABLE[QRMath.EXP_TABLE[i]] = i;\n\t}\n\n\t//---------------------------------------------------------------------\n\t// QRPolynomial 多项式\n\t//---------------------------------------------------------------------\n\t/**\n\t * 多项式类\n\t * @param {Array} num   系数\n\t * @param {num} shift a^shift\n\t */\n\tfunction QRPolynomial(num, shift) {\n\n\t  if (num.length == undefined) {\n\t    throw new Error(num.length + \"/\" + shift);\n\t  }\n\n\t  var offset = 0;\n\n\t  while (offset < num.length && num[offset] == 0) {\n\t    offset++;\n\t  }\n\n\t  this.num = new Array(num.length - offset + shift);\n\t  for (var i = 0; i < num.length - offset; i++) {\n\t    this.num[i] = num[i + offset];\n\t  }\n\t}\n\n\tQRPolynomial.prototype = {\n\n\t  get: function(index) {\n\t    return this.num[index];\n\t  },\n\n\t  getLength: function() {\n\t    return this.num.length;\n\t  },\n\t  /**\n\t   * 多项式乘法\n\t   * @param  {QRPolynomial} e 被乘多项式\n\t   * @return {[type]}   [description]\n\t   */\n\t  multiply: function(e) {\n\n\t    var num = new Array(this.getLength() + e.getLength() - 1);\n\n\t    for (var i = 0; i < this.getLength(); i++) {\n\t      for (var j = 0; j < e.getLength(); j++) {\n\t        num[i + j] ^= QRMath.gexp(QRMath.glog(this.get(i)) + QRMath.glog(e.get(j)));\n\t      }\n\t    }\n\n\t    return new QRPolynomial(num, 0);\n\t  },\n\t  /**\n\t   * 多项式模运算\n\t   * @param  {QRPolynomial} e 模多项式\n\t   * @return {}\n\t   */\n\t  mod: function(e) {\n\t    var tl = this.getLength(),\n\t      el = e.getLength();\n\t    if (tl - el < 0) {\n\t      return this;\n\t    }\n\t    var num = new Array(tl);\n\t    for (var i = 0; i < tl; i++) {\n\t      num[i] = this.get(i);\n\t    }\n\t    while (num.length >= el) {\n\t      var ratio = QRMath.glog(num[0]) - QRMath.glog(e.get(0));\n\n\t      for (var i = 0; i < e.getLength(); i++) {\n\t        num[i] ^= QRMath.gexp(QRMath.glog(e.get(i)) + ratio);\n\t      }\n\t      while (num[0] == 0) {\n\t        num.shift();\n\t      }\n\t    }\n\t    return new QRPolynomial(num, 0);\n\t  }\n\t};\n\n\t//---------------------------------------------------------------------\n\t// RS_BLOCK_TABLE\n\t//---------------------------------------------------------------------\n\t/*\n\t 二维码各个版本信息[块数, 每块中的数据块数, 每块中的信息块数]\n\t */\n\tvar RS_BLOCK_TABLE = [\n\n\t  // L\n\t  // M\n\t  // Q\n\t  // H\n\n\t  // 1\n\t  [1, 26, 19],\n\t  [1, 26, 16],\n\t  [1, 26, 13],\n\t  [1, 26, 9],\n\n\t  // 2\n\t  [1, 44, 34],\n\t  [1, 44, 28],\n\t  [1, 44, 22],\n\t  [1, 44, 16],\n\n\t  // 3\n\t  [1, 70, 55],\n\t  [1, 70, 44],\n\t  [2, 35, 17],\n\t  [2, 35, 13],\n\n\t  // 4\n\t  [1, 100, 80],\n\t  [2, 50, 32],\n\t  [2, 50, 24],\n\t  [4, 25, 9],\n\n\t  // 5\n\t  [1, 134, 108],\n\t  [2, 67, 43],\n\t  [2, 33, 15, 2, 34, 16],\n\t  [2, 33, 11, 2, 34, 12],\n\n\t  // 6\n\t  [2, 86, 68],\n\t  [4, 43, 27],\n\t  [4, 43, 19],\n\t  [4, 43, 15],\n\n\t  // 7\n\t  [2, 98, 78],\n\t  [4, 49, 31],\n\t  [2, 32, 14, 4, 33, 15],\n\t  [4, 39, 13, 1, 40, 14],\n\n\t  // 8\n\t  [2, 121, 97],\n\t  [2, 60, 38, 2, 61, 39],\n\t  [4, 40, 18, 2, 41, 19],\n\t  [4, 40, 14, 2, 41, 15],\n\n\t  // 9\n\t  [2, 146, 116],\n\t  [3, 58, 36, 2, 59, 37],\n\t  [4, 36, 16, 4, 37, 17],\n\t  [4, 36, 12, 4, 37, 13],\n\n\t  // 10\n\t  [2, 86, 68, 2, 87, 69],\n\t  [4, 69, 43, 1, 70, 44],\n\t  [6, 43, 19, 2, 44, 20],\n\t  [6, 43, 15, 2, 44, 16],\n\n\t  // 11\n\t  [4, 101, 81],\n\t  [1, 80, 50, 4, 81, 51],\n\t  [4, 50, 22, 4, 51, 23],\n\t  [3, 36, 12, 8, 37, 13],\n\n\t  // 12\n\t  [2, 116, 92, 2, 117, 93],\n\t  [6, 58, 36, 2, 59, 37],\n\t  [4, 46, 20, 6, 47, 21],\n\t  [7, 42, 14, 4, 43, 15],\n\n\t  // 13\n\t  [4, 133, 107],\n\t  [8, 59, 37, 1, 60, 38],\n\t  [8, 44, 20, 4, 45, 21],\n\t  [12, 33, 11, 4, 34, 12],\n\n\t  // 14\n\t  [3, 145, 115, 1, 146, 116],\n\t  [4, 64, 40, 5, 65, 41],\n\t  [11, 36, 16, 5, 37, 17],\n\t  [11, 36, 12, 5, 37, 13],\n\n\t  // 15\n\t  [5, 109, 87, 1, 110, 88],\n\t  [5, 65, 41, 5, 66, 42],\n\t  [5, 54, 24, 7, 55, 25],\n\t  [11, 36, 12],\n\n\t  // 16\n\t  [5, 122, 98, 1, 123, 99],\n\t  [7, 73, 45, 3, 74, 46],\n\t  [15, 43, 19, 2, 44, 20],\n\t  [3, 45, 15, 13, 46, 16],\n\n\t  // 17\n\t  [1, 135, 107, 5, 136, 108],\n\t  [10, 74, 46, 1, 75, 47],\n\t  [1, 50, 22, 15, 51, 23],\n\t  [2, 42, 14, 17, 43, 15],\n\n\t  // 18\n\t  [5, 150, 120, 1, 151, 121],\n\t  [9, 69, 43, 4, 70, 44],\n\t  [17, 50, 22, 1, 51, 23],\n\t  [2, 42, 14, 19, 43, 15],\n\n\t  // 19\n\t  [3, 141, 113, 4, 142, 114],\n\t  [3, 70, 44, 11, 71, 45],\n\t  [17, 47, 21, 4, 48, 22],\n\t  [9, 39, 13, 16, 40, 14],\n\n\t  // 20\n\t  [3, 135, 107, 5, 136, 108],\n\t  [3, 67, 41, 13, 68, 42],\n\t  [15, 54, 24, 5, 55, 25],\n\t  [15, 43, 15, 10, 44, 16],\n\n\t  // 21\n\t  [4, 144, 116, 4, 145, 117],\n\t  [17, 68, 42],\n\t  [17, 50, 22, 6, 51, 23],\n\t  [19, 46, 16, 6, 47, 17],\n\n\t  // 22\n\t  [2, 139, 111, 7, 140, 112],\n\t  [17, 74, 46],\n\t  [7, 54, 24, 16, 55, 25],\n\t  [34, 37, 13],\n\n\t  // 23\n\t  [4, 151, 121, 5, 152, 122],\n\t  [4, 75, 47, 14, 76, 48],\n\t  [11, 54, 24, 14, 55, 25],\n\t  [16, 45, 15, 14, 46, 16],\n\n\t  // 24\n\t  [6, 147, 117, 4, 148, 118],\n\t  [6, 73, 45, 14, 74, 46],\n\t  [11, 54, 24, 16, 55, 25],\n\t  [30, 46, 16, 2, 47, 17],\n\n\t  // 25\n\t  [8, 132, 106, 4, 133, 107],\n\t  [8, 75, 47, 13, 76, 48],\n\t  [7, 54, 24, 22, 55, 25],\n\t  [22, 45, 15, 13, 46, 16],\n\n\t  // 26\n\t  [10, 142, 114, 2, 143, 115],\n\t  [19, 74, 46, 4, 75, 47],\n\t  [28, 50, 22, 6, 51, 23],\n\t  [33, 46, 16, 4, 47, 17],\n\n\t  // 27\n\t  [8, 152, 122, 4, 153, 123],\n\t  [22, 73, 45, 3, 74, 46],\n\t  [8, 53, 23, 26, 54, 24],\n\t  [12, 45, 15, 28, 46, 16],\n\n\t  // 28\n\t  [3, 147, 117, 10, 148, 118],\n\t  [3, 73, 45, 23, 74, 46],\n\t  [4, 54, 24, 31, 55, 25],\n\t  [11, 45, 15, 31, 46, 16],\n\n\t  // 29\n\t  [7, 146, 116, 7, 147, 117],\n\t  [21, 73, 45, 7, 74, 46],\n\t  [1, 53, 23, 37, 54, 24],\n\t  [19, 45, 15, 26, 46, 16],\n\n\t  // 30\n\t  [5, 145, 115, 10, 146, 116],\n\t  [19, 75, 47, 10, 76, 48],\n\t  [15, 54, 24, 25, 55, 25],\n\t  [23, 45, 15, 25, 46, 16],\n\n\t  // 31\n\t  [13, 145, 115, 3, 146, 116],\n\t  [2, 74, 46, 29, 75, 47],\n\t  [42, 54, 24, 1, 55, 25],\n\t  [23, 45, 15, 28, 46, 16],\n\n\t  // 32\n\t  [17, 145, 115],\n\t  [10, 74, 46, 23, 75, 47],\n\t  [10, 54, 24, 35, 55, 25],\n\t  [19, 45, 15, 35, 46, 16],\n\n\t  // 33\n\t  [17, 145, 115, 1, 146, 116],\n\t  [14, 74, 46, 21, 75, 47],\n\t  [29, 54, 24, 19, 55, 25],\n\t  [11, 45, 15, 46, 46, 16],\n\n\t  // 34\n\t  [13, 145, 115, 6, 146, 116],\n\t  [14, 74, 46, 23, 75, 47],\n\t  [44, 54, 24, 7, 55, 25],\n\t  [59, 46, 16, 1, 47, 17],\n\n\t  // 35\n\t  [12, 151, 121, 7, 152, 122],\n\t  [12, 75, 47, 26, 76, 48],\n\t  [39, 54, 24, 14, 55, 25],\n\t  [22, 45, 15, 41, 46, 16],\n\n\t  // 36\n\t  [6, 151, 121, 14, 152, 122],\n\t  [6, 75, 47, 34, 76, 48],\n\t  [46, 54, 24, 10, 55, 25],\n\t  [2, 45, 15, 64, 46, 16],\n\n\t  // 37\n\t  [17, 152, 122, 4, 153, 123],\n\t  [29, 74, 46, 14, 75, 47],\n\t  [49, 54, 24, 10, 55, 25],\n\t  [24, 45, 15, 46, 46, 16],\n\n\t  // 38\n\t  [4, 152, 122, 18, 153, 123],\n\t  [13, 74, 46, 32, 75, 47],\n\t  [48, 54, 24, 14, 55, 25],\n\t  [42, 45, 15, 32, 46, 16],\n\n\t  // 39\n\t  [20, 147, 117, 4, 148, 118],\n\t  [40, 75, 47, 7, 76, 48],\n\t  [43, 54, 24, 22, 55, 25],\n\t  [10, 45, 15, 67, 46, 16],\n\n\t  // 40\n\t  [19, 148, 118, 6, 149, 119],\n\t  [18, 75, 47, 31, 76, 48],\n\t  [34, 54, 24, 34, 55, 25],\n\t  [20, 45, 15, 61, 46, 16]\n\t];\n\n\t/**\n\t * 根据数据获取对应版本\n\t * @return {[type]} [description]\n\t */\n\tQRCodeAlg.prototype.getRightType = function() {\n\t  for (var typeNumber = 1; typeNumber < 41; typeNumber++) {\n\t    var rsBlock = RS_BLOCK_TABLE[(typeNumber - 1) * 4 + this.errorCorrectLevel];\n\t    if (rsBlock == undefined) {\n\t      throw new Error(\"bad rs block @ typeNumber:\" + typeNumber + \"/errorCorrectLevel:\" + this.errorCorrectLevel);\n\t    }\n\t    var length = rsBlock.length / 3;\n\t    var totalDataCount = 0;\n\t    for (var i = 0; i < length; i++) {\n\t      var count = rsBlock[i * 3 + 0];\n\t      var dataCount = rsBlock[i * 3 + 2];\n\t      totalDataCount += dataCount * count;\n\t    }\n\n\t    var lengthBytes = typeNumber > 9 ? 2 : 1;\n\t    if (this.utf8bytes.length + lengthBytes < totalDataCount || typeNumber == 40) {\n\t      this.typeNumber = typeNumber;\n\t      this.rsBlock = rsBlock;\n\t      this.totalDataCount = totalDataCount;\n\t      break;\n\t    }\n\t  }\n\t};\n\n\t//---------------------------------------------------------------------\n\t// QRBitBuffer\n\t//---------------------------------------------------------------------\n\n\tfunction QRBitBuffer() {\n\t  this.buffer = new Array();\n\t  this.length = 0;\n\t}\n\n\tQRBitBuffer.prototype = {\n\n\t  get: function(index) {\n\t    var bufIndex = Math.floor(index / 8);\n\t    return ((this.buffer[bufIndex] >>> (7 - index % 8)) & 1);\n\t  },\n\n\t  put: function(num, length) {\n\t    for (var i = 0; i < length; i++) {\n\t      this.putBit(((num >>> (length - i - 1)) & 1));\n\t    }\n\t  },\n\n\t  putBit: function(bit) {\n\n\t    var bufIndex = Math.floor(this.length / 8);\n\t    if (this.buffer.length <= bufIndex) {\n\t      this.buffer.push(0);\n\t    }\n\n\t    if (bit) {\n\t      this.buffer[bufIndex] |= (0x80 >>> (this.length % 8));\n\t    }\n\n\t    this.length++;\n\t  }\n\t};\n\t/**\n\t * 获取单个字符的utf8编码\n\t * unicode BMP平面约65535个字符\n\t * @param {num} code\n\t * return {array}\n\t */\n\tfunction unicodeFormat8(code) {\n\t  // 1 byte\n\t  if (code < 128) {\n\t    return [code];\n\t    // 2 bytes\n\t  } else if (code < 2048) {\n\t    c0 = 192 + (code >> 6);\n\t    c1 = 128 + (code & 63);\n\t    return [c0, c1];\n\t    // 3 bytes\n\t  } else {\n\t    c0 = 224 + (code >> 12);\n\t    c1 = 128 + (code >> 6 & 63);\n\t    c2 = 128 + (code & 63);\n\t    return [c0, c1, c2];\n\t  }\n\t}\n\n\t/**\n\t * 获取字符串的utf8编码字节串\n\t * @param {string} string\n\t * @return {array}\n\t */\n\tfunction getUTF8Bytes(string) {\n\t  var utf8codes = [];\n\t  for (var i = 0; i < string.length; i++) {\n\t    var code = string.charCodeAt(i);\n\t    var utf8 = unicodeFormat8(code);\n\t    for (var j = 0; j < utf8.length; j++) {\n\t      utf8codes.push(utf8[j]);\n\t    }\n\t  }\n\t  return utf8codes;\n\t}\n\n\t/**\n\t * 二维码算法实现\n\t * @param {string} data              要编码的信息字符串\n\t * @param {num} errorCorrectLevel 纠错等级\n\t */\n\tfunction QRCodeAlg(data, errorCorrectLevel) {\n\t  this.typeNumber = -1; //版本\n\t  this.errorCorrectLevel = errorCorrectLevel;\n\t  this.modules = null;  //二维矩阵，存放最终结果\n\t  this.moduleCount = 0; //矩阵大小\n\t  this.dataCache = null; //数据缓存\n\t  this.rsBlocks = null; //版本数据信息\n\t  this.totalDataCount = -1; //可使用的数据量\n\t  this.data = data;\n\t  this.utf8bytes = getUTF8Bytes(data);\n\t  this.make();\n\t}\n\n\tQRCodeAlg.prototype = {\n\t  constructor: QRCodeAlg,\n\t  /**\n\t   * 获取二维码矩阵大小\n\t   * @return {num} 矩阵大小\n\t   */\n\t  getModuleCount: function() {\n\t    return this.moduleCount;\n\t  },\n\t  /**\n\t   * 编码\n\t   */\n\t  make: function() {\n\t    this.getRightType();\n\t    this.dataCache = this.createData();\n\t    this.createQrcode();\n\t  },\n\t  /**\n\t   * 设置二位矩阵功能图形\n\t   * @param  {bool} test 表示是否在寻找最好掩膜阶段\n\t   * @param  {num} maskPattern 掩膜的版本\n\t   */\n\t  makeImpl: function(maskPattern) {\n\n\t    this.moduleCount = this.typeNumber * 4 + 17;\n\t    this.modules = new Array(this.moduleCount);\n\n\t    for (var row = 0; row < this.moduleCount; row++) {\n\n\t      this.modules[row] = new Array(this.moduleCount);\n\n\t    }\n\t    this.setupPositionProbePattern(0, 0);\n\t    this.setupPositionProbePattern(this.moduleCount - 7, 0);\n\t    this.setupPositionProbePattern(0, this.moduleCount - 7);\n\t    this.setupPositionAdjustPattern();\n\t    this.setupTimingPattern();\n\t    this.setupTypeInfo(true, maskPattern);\n\n\t    if (this.typeNumber >= 7) {\n\t      this.setupTypeNumber(true);\n\t    }\n\t    this.mapData(this.dataCache, maskPattern);\n\t  },\n\t  /**\n\t   * 设置二维码的位置探测图形\n\t   * @param  {num} row 探测图形的中心横坐标\n\t   * @param  {num} col 探测图形的中心纵坐标\n\t   */\n\t  setupPositionProbePattern: function(row, col) {\n\n\t    for (var r = -1; r <= 7; r++) {\n\n\t      if (row + r <= -1 || this.moduleCount <= row + r) continue;\n\n\t      for (var c = -1; c <= 7; c++) {\n\n\t        if (col + c <= -1 || this.moduleCount <= col + c) continue;\n\n\t        if ((0 <= r && r <= 6 && (c == 0 || c == 6)) || (0 <= c && c <= 6 && (r == 0 || r == 6)) || (2 <= r && r <= 4 && 2 <= c && c <= 4)) {\n\t          this.modules[row + r][col + c] = true;\n\t        } else {\n\t          this.modules[row + r][col + c] = false;\n\t        }\n\t      }\n\t    }\n\t  },\n\t  /**\n\t   * 创建二维码\n\t   * @return {[type]} [description]\n\t   */\n\t  createQrcode: function() {\n\n\t    var minLostPoint = 0;\n\t    var pattern = 0;\n\t    var bestModules = null;\n\n\t    for (var i = 0; i < 8; i++) {\n\n\t      this.makeImpl(i);\n\n\t      var lostPoint = QRUtil.getLostPoint(this);\n\t      if (i == 0 || minLostPoint > lostPoint) {\n\t        minLostPoint = lostPoint;\n\t        pattern = i;\n\t        bestModules = this.modules;\n\t      }\n\t    }\n\t    this.modules = bestModules;\n\t    this.setupTypeInfo(false, pattern);\n\n\t    if (this.typeNumber >= 7) {\n\t      this.setupTypeNumber(false);\n\t    }\n\n\t  },\n\t  /**\n\t   * 设置定位图形\n\t   * @return {[type]} [description]\n\t   */\n\t  setupTimingPattern: function() {\n\n\t    for (var r = 8; r < this.moduleCount - 8; r++) {\n\t      if (this.modules[r][6] != null) {\n\t        continue;\n\t      }\n\t      this.modules[r][6] = (r % 2 == 0);\n\n\t      if (this.modules[6][r] != null) {\n\t        continue;\n\t      }\n\t      this.modules[6][r] = (r % 2 == 0);\n\t    }\n\t  },\n\t  /**\n\t   * 设置矫正图形\n\t   * @return {[type]} [description]\n\t   */\n\t  setupPositionAdjustPattern: function() {\n\n\t    var pos = QRUtil.getPatternPosition(this.typeNumber);\n\n\t    for (var i = 0; i < pos.length; i++) {\n\n\t      for (var j = 0; j < pos.length; j++) {\n\n\t        var row = pos[i];\n\t        var col = pos[j];\n\n\t        if (this.modules[row][col] != null) {\n\t          continue;\n\t        }\n\n\t        for (var r = -2; r <= 2; r++) {\n\n\t          for (var c = -2; c <= 2; c++) {\n\n\t            if (r == -2 || r == 2 || c == -2 || c == 2 || (r == 0 && c == 0)) {\n\t              this.modules[row + r][col + c] = true;\n\t            } else {\n\t              this.modules[row + r][col + c] = false;\n\t            }\n\t          }\n\t        }\n\t      }\n\t    }\n\t  },\n\t  /**\n\t   * 设置版本信息（7以上版本才有）\n\t   * @param  {bool} test 是否处于判断最佳掩膜阶段\n\t   * @return {[type]}      [description]\n\t   */\n\t  setupTypeNumber: function(test) {\n\n\t    var bits = QRUtil.getBCHTypeNumber(this.typeNumber);\n\n\t    for (var i = 0; i < 18; i++) {\n\t      var mod = (!test && ((bits >> i) & 1) == 1);\n\t      this.modules[Math.floor(i / 3)][i % 3 + this.moduleCount - 8 - 3] = mod;\n\t      this.modules[i % 3 + this.moduleCount - 8 - 3][Math.floor(i / 3)] = mod;\n\t    }\n\t  },\n\t  /**\n\t   * 设置格式信息（纠错等级和掩膜版本）\n\t   * @param  {bool} test\n\t   * @param  {num} maskPattern 掩膜版本\n\t   * @return {}\n\t   */\n\t  setupTypeInfo: function(test, maskPattern) {\n\n\t    var data = (QRErrorCorrectLevel[this.errorCorrectLevel] << 3) | maskPattern;\n\t    var bits = QRUtil.getBCHTypeInfo(data);\n\n\t    // vertical\n\t    for (var i = 0; i < 15; i++) {\n\n\t      var mod = (!test && ((bits >> i) & 1) == 1);\n\n\t      if (i < 6) {\n\t        this.modules[i][8] = mod;\n\t      } else if (i < 8) {\n\t        this.modules[i + 1][8] = mod;\n\t      } else {\n\t        this.modules[this.moduleCount - 15 + i][8] = mod;\n\t      }\n\n\t      // horizontal\n\t      var mod = (!test && ((bits >> i) & 1) == 1);\n\n\t      if (i < 8) {\n\t        this.modules[8][this.moduleCount - i - 1] = mod;\n\t      } else if (i < 9) {\n\t        this.modules[8][15 - i - 1 + 1] = mod;\n\t      } else {\n\t        this.modules[8][15 - i - 1] = mod;\n\t      }\n\t    }\n\n\t    // fixed module\n\t    this.modules[this.moduleCount - 8][8] = (!test);\n\n\t  },\n\t  /**\n\t   * 数据编码\n\t   * @return {[type]} [description]\n\t   */\n\t  createData: function() {\n\t    var buffer = new QRBitBuffer();\n\t    var lengthBits = this.typeNumber > 9 ? 16 : 8;\n\t    buffer.put(4, 4); //添加模式\n\t    buffer.put(this.utf8bytes.length, lengthBits);\n\t    for (var i = 0, l = this.utf8bytes.length; i < l; i++) {\n\t      buffer.put(this.utf8bytes[i], 8);\n\t    }\n\t    if (buffer.length + 4 <= this.totalDataCount * 8) {\n\t      buffer.put(0, 4);\n\t    }\n\n\t    // padding\n\t    while (buffer.length % 8 != 0) {\n\t      buffer.putBit(false);\n\t    }\n\n\t    // padding\n\t    while (true) {\n\n\t      if (buffer.length >= this.totalDataCount * 8) {\n\t        break;\n\t      }\n\t      buffer.put(QRCodeAlg.PAD0, 8);\n\n\t      if (buffer.length >= this.totalDataCount * 8) {\n\t        break;\n\t      }\n\t      buffer.put(QRCodeAlg.PAD1, 8);\n\t    }\n\t    return this.createBytes(buffer);\n\t  },\n\t  /**\n\t   * 纠错码编码\n\t   * @param  {buffer} buffer 数据编码\n\t   * @return {[type]}\n\t   */\n\t  createBytes: function(buffer) {\n\n\t    var offset = 0;\n\n\t    var maxDcCount = 0;\n\t    var maxEcCount = 0;\n\n\t    var length = this.rsBlock.length / 3;\n\n\t    var rsBlocks = new Array();\n\n\t    for (var i = 0; i < length; i++) {\n\n\t      var count = this.rsBlock[i * 3 + 0];\n\t      var totalCount = this.rsBlock[i * 3 + 1];\n\t      var dataCount = this.rsBlock[i * 3 + 2];\n\n\t      for (var j = 0; j < count; j++) {\n\t        rsBlocks.push([dataCount, totalCount]);\n\t      }\n\t    }\n\n\t    var dcdata = new Array(rsBlocks.length);\n\t    var ecdata = new Array(rsBlocks.length);\n\n\t    for (var r = 0; r < rsBlocks.length; r++) {\n\n\t      var dcCount = rsBlocks[r][0];\n\t      var ecCount = rsBlocks[r][1] - dcCount;\n\n\t      maxDcCount = Math.max(maxDcCount, dcCount);\n\t      maxEcCount = Math.max(maxEcCount, ecCount);\n\n\t      dcdata[r] = new Array(dcCount);\n\n\t      for (var i = 0; i < dcdata[r].length; i++) {\n\t        dcdata[r][i] = 0xff & buffer.buffer[i + offset];\n\t      }\n\t      offset += dcCount;\n\n\t      var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount);\n\t      var rawPoly = new QRPolynomial(dcdata[r], rsPoly.getLength() - 1);\n\n\t      var modPoly = rawPoly.mod(rsPoly);\n\t      ecdata[r] = new Array(rsPoly.getLength() - 1);\n\t      for (var i = 0; i < ecdata[r].length; i++) {\n\t        var modIndex = i + modPoly.getLength() - ecdata[r].length;\n\t        ecdata[r][i] = (modIndex >= 0) ? modPoly.get(modIndex) : 0;\n\t      }\n\t    }\n\n\t    var data = new Array(this.totalDataCount);\n\t    var index = 0;\n\n\t    for (var i = 0; i < maxDcCount; i++) {\n\t      for (var r = 0; r < rsBlocks.length; r++) {\n\t        if (i < dcdata[r].length) {\n\t          data[index++] = dcdata[r][i];\n\t        }\n\t      }\n\t    }\n\n\t    for (var i = 0; i < maxEcCount; i++) {\n\t      for (var r = 0; r < rsBlocks.length; r++) {\n\t        if (i < ecdata[r].length) {\n\t          data[index++] = ecdata[r][i];\n\t        }\n\t      }\n\t    }\n\n\t    return data;\n\n\t  },\n\t  /**\n\t   * 布置模块，构建最终信息\n\t   * @param  {} data\n\t   * @param  {} maskPattern\n\t   * @return {}\n\t   */\n\t  mapData: function(data, maskPattern) {\n\n\t    var inc = -1;\n\t    var row = this.moduleCount - 1;\n\t    var bitIndex = 7;\n\t    var byteIndex = 0;\n\n\t    for (var col = this.moduleCount - 1; col > 0; col -= 2) {\n\n\t      if (col == 6) col--;\n\n\t      while (true) {\n\n\t        for (var c = 0; c < 2; c++) {\n\n\t          if (this.modules[row][col - c] == null) {\n\n\t            var dark = false;\n\n\t            if (byteIndex < data.length) {\n\t              dark = (((data[byteIndex] >>> bitIndex) & 1) == 1);\n\t            }\n\n\t            var mask = QRUtil.getMask(maskPattern, row, col - c);\n\n\t            if (mask) {\n\t              dark = !dark;\n\t            }\n\n\t            this.modules[row][col - c] = dark;\n\t            bitIndex--;\n\n\t            if (bitIndex == -1) {\n\t              byteIndex++;\n\t              bitIndex = 7;\n\t            }\n\t          }\n\t        }\n\n\t        row += inc;\n\n\t        if (row < 0 || this.moduleCount <= row) {\n\t          row -= inc;\n\t          inc = -inc;\n\t          break;\n\t        }\n\t      }\n\t    }\n\t  }\n\n\t};\n\t/**\n\t * 填充字段\n\t */\n\tQRCodeAlg.PAD0 = 0xEC;\n\tQRCodeAlg.PAD1 = 0x11;\n\n\n\t//---------------------------------------------------------------------\n\t// 纠错等级对应的编码\n\t//---------------------------------------------------------------------\n\n\tvar QRErrorCorrectLevel = [1, 0, 3, 2];\n\n\t//---------------------------------------------------------------------\n\t// 掩膜版本\n\t//---------------------------------------------------------------------\n\n\tvar QRMaskPattern = {\n\t  PATTERN000: 0,\n\t  PATTERN001: 1,\n\t  PATTERN010: 2,\n\t  PATTERN011: 3,\n\t  PATTERN100: 4,\n\t  PATTERN101: 5,\n\t  PATTERN110: 6,\n\t  PATTERN111: 7\n\t};\n\n\t//---------------------------------------------------------------------\n\t// 工具类\n\t//---------------------------------------------------------------------\n\n\tvar QRUtil = {\n\n\t  /*\n\t   每个版本矫正图形的位置\n\t   */\n\t  PATTERN_POSITION_TABLE: [\n\t    [],\n\t    [6, 18],\n\t    [6, 22],\n\t    [6, 26],\n\t    [6, 30],\n\t    [6, 34],\n\t    [6, 22, 38],\n\t    [6, 24, 42],\n\t    [6, 26, 46],\n\t    [6, 28, 50],\n\t    [6, 30, 54],\n\t    [6, 32, 58],\n\t    [6, 34, 62],\n\t    [6, 26, 46, 66],\n\t    [6, 26, 48, 70],\n\t    [6, 26, 50, 74],\n\t    [6, 30, 54, 78],\n\t    [6, 30, 56, 82],\n\t    [6, 30, 58, 86],\n\t    [6, 34, 62, 90],\n\t    [6, 28, 50, 72, 94],\n\t    [6, 26, 50, 74, 98],\n\t    [6, 30, 54, 78, 102],\n\t    [6, 28, 54, 80, 106],\n\t    [6, 32, 58, 84, 110],\n\t    [6, 30, 58, 86, 114],\n\t    [6, 34, 62, 90, 118],\n\t    [6, 26, 50, 74, 98, 122],\n\t    [6, 30, 54, 78, 102, 126],\n\t    [6, 26, 52, 78, 104, 130],\n\t    [6, 30, 56, 82, 108, 134],\n\t    [6, 34, 60, 86, 112, 138],\n\t    [6, 30, 58, 86, 114, 142],\n\t    [6, 34, 62, 90, 118, 146],\n\t    [6, 30, 54, 78, 102, 126, 150],\n\t    [6, 24, 50, 76, 102, 128, 154],\n\t    [6, 28, 54, 80, 106, 132, 158],\n\t    [6, 32, 58, 84, 110, 136, 162],\n\t    [6, 26, 54, 82, 110, 138, 166],\n\t    [6, 30, 58, 86, 114, 142, 170]\n\t  ],\n\n\t  G15: (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0),\n\t  G18: (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0),\n\t  G15_MASK: (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1),\n\n\t  /*\n\t   BCH编码格式信息\n\t   */\n\t  getBCHTypeInfo: function(data) {\n\t    var d = data << 10;\n\t    while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) >= 0) {\n\t      d ^= (QRUtil.G15 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15)));\n\t    }\n\t    return ((data << 10) | d) ^ QRUtil.G15_MASK;\n\t  },\n\t  /*\n\t   BCH编码版本信息\n\t   */\n\t  getBCHTypeNumber: function(data) {\n\t    var d = data << 12;\n\t    while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) >= 0) {\n\t      d ^= (QRUtil.G18 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18)));\n\t    }\n\t    return (data << 12) | d;\n\t  },\n\t  /*\n\t   获取BCH位信息\n\t   */\n\t  getBCHDigit: function(data) {\n\n\t    var digit = 0;\n\n\t    while (data != 0) {\n\t      digit++;\n\t      data >>>= 1;\n\t    }\n\n\t    return digit;\n\t  },\n\t  /*\n\t   获取版本对应的矫正图形位置\n\t   */\n\t  getPatternPosition: function(typeNumber) {\n\t    return QRUtil.PATTERN_POSITION_TABLE[typeNumber - 1];\n\t  },\n\t  /*\n\t   掩膜算法\n\t   */\n\t  getMask: function(maskPattern, i, j) {\n\n\t    switch (maskPattern) {\n\n\t      case QRMaskPattern.PATTERN000:\n\t        return (i + j) % 2 == 0;\n\t      case QRMaskPattern.PATTERN001:\n\t        return i % 2 == 0;\n\t      case QRMaskPattern.PATTERN010:\n\t        return j % 3 == 0;\n\t      case QRMaskPattern.PATTERN011:\n\t        return (i + j) % 3 == 0;\n\t      case QRMaskPattern.PATTERN100:\n\t        return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 == 0;\n\t      case QRMaskPattern.PATTERN101:\n\t        return (i * j) % 2 + (i * j) % 3 == 0;\n\t      case QRMaskPattern.PATTERN110:\n\t        return ((i * j) % 2 + (i * j) % 3) % 2 == 0;\n\t      case QRMaskPattern.PATTERN111:\n\t        return ((i * j) % 3 + (i + j) % 2) % 2 == 0;\n\n\t      default:\n\t        throw new Error(\"bad maskPattern:\" + maskPattern);\n\t    }\n\t  },\n\t  /*\n\t   获取RS的纠错多项式\n\t   */\n\t  getErrorCorrectPolynomial: function(errorCorrectLength) {\n\n\t    var a = new QRPolynomial([1], 0);\n\n\t    for (var i = 0; i < errorCorrectLength; i++) {\n\t      a = a.multiply(new QRPolynomial([1, QRMath.gexp(i)], 0));\n\t    }\n\n\t    return a;\n\t  },\n\t  /*\n\t   获取评价\n\t   */\n\t  getLostPoint: function(qrCode) {\n\n\t    var moduleCount = qrCode.getModuleCount(),\n\t      lostPoint = 0,\n\t      darkCount = 0;\n\n\t    for (var row = 0; row < moduleCount; row++) {\n\n\t      var sameCount = 0;\n\t      var head = qrCode.modules[row][0];\n\n\t      for (var col = 0; col < moduleCount; col++) {\n\n\t        var current = qrCode.modules[row][col];\n\n\t        //level 3 评价\n\t        if (col < moduleCount - 6) {\n\t          if (current && !qrCode.modules[row][col + 1] && qrCode.modules[row][col + 2] && qrCode.modules[row][col + 3] && qrCode.modules[row][col + 4] && !qrCode.modules[row][col + 5] && qrCode.modules[row][col + 6]) {\n\t            if (col < moduleCount - 10) {\n\t              if (qrCode.modules[row][col + 7] && qrCode.modules[row][col + 8] && qrCode.modules[row][col + 9] && qrCode.modules[row][col + 10]) {\n\t                lostPoint += 40;\n\t              }\n\t            } else if (col > 3) {\n\t              if (qrCode.modules[row][col - 1] && qrCode.modules[row][col - 2] && qrCode.modules[row][col - 3] && qrCode.modules[row][col - 4]) {\n\t                lostPoint += 40;\n\t              }\n\t            }\n\n\t          }\n\t        }\n\n\t        //level 2 评价\n\t        if ((row < moduleCount - 1) && (col < moduleCount - 1)) {\n\t          var count = 0;\n\t          if (current) count++;\n\t          if (qrCode.modules[row + 1][col]) count++;\n\t          if (qrCode.modules[row][col + 1]) count++;\n\t          if (qrCode.modules[row + 1][col + 1]) count++;\n\t          if (count == 0 || count == 4) {\n\t            lostPoint += 3;\n\t          }\n\t        }\n\n\t        //level 1 评价\n\t        if (head ^ current) {\n\t          sameCount++;\n\t        } else {\n\t          head = current;\n\t          if (sameCount >= 5) {\n\t            lostPoint += (3 + sameCount - 5);\n\t          }\n\t          sameCount = 1;\n\t        }\n\n\t        //level 4 评价\n\t        if (current) {\n\t          darkCount++;\n\t        }\n\n\t      }\n\t    }\n\n\t    for (var col = 0; col < moduleCount; col++) {\n\n\t      var sameCount = 0;\n\t      var head = qrCode.modules[0][col];\n\n\t      for (var row = 0; row < moduleCount; row++) {\n\n\t        var current = qrCode.modules[row][col];\n\n\t        //level 3 评价\n\t        if (row < moduleCount - 6) {\n\t          if (current && !qrCode.modules[row + 1][col] && qrCode.modules[row + 2][col] && qrCode.modules[row + 3][col] && qrCode.modules[row + 4][col] && !qrCode.modules[row + 5][col] && qrCode.modules[row + 6][col]) {\n\t            if (row < moduleCount - 10) {\n\t              if (qrCode.modules[row + 7][col] && qrCode.modules[row + 8][col] && qrCode.modules[row + 9][col] && qrCode.modules[row + 10][col]) {\n\t                lostPoint += 40;\n\t              }\n\t            } else if (row > 3) {\n\t              if (qrCode.modules[row - 1][col] && qrCode.modules[row - 2][col] && qrCode.modules[row - 3][col] && qrCode.modules[row - 4][col]) {\n\t                lostPoint += 40;\n\t              }\n\t            }\n\t          }\n\t        }\n\n\t        //level 1 评价\n\t        if (head ^ current) {\n\t          sameCount++;\n\t        } else {\n\t          head = current;\n\t          if (sameCount >= 5) {\n\t            lostPoint += (3 + sameCount - 5);\n\t          }\n\t          sameCount = 1;\n\t        }\n\n\t      }\n\t    }\n\n\t    // LEVEL4\n\n\t    var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;\n\t    lostPoint += ratio * 10;\n\n\t    return lostPoint;\n\t  }\n\n\t};\n\n\n\t//---------------------------------------------------------------------\n\t// QRMath使用的数学工具\n\t//---------------------------------------------------------------------\n\n\tvar QRMath = {\n\t  /*\n\t   将n转化为a^m\n\t   */\n\t  glog: function(n) {\n\n\t    if (n < 1) {\n\t      throw new Error(\"glog(\" + n + \")\");\n\t    }\n\n\t    return QRMath.LOG_TABLE[n];\n\t  },\n\t  /*\n\t   将a^m转化为n\n\t   */\n\t  gexp: function(n) {\n\n\t    while (n < 0) {\n\t      n += 255;\n\t    }\n\n\t    while (n >= 256) {\n\t      n -= 255;\n\t    }\n\n\t    return QRMath.EXP_TABLE[n];\n\t  },\n\n\t  EXP_TABLE: new Array(256),\n\n\t  LOG_TABLE: new Array(256)\n\n\t};\n\n\tfor (var i = 0; i < 8; i++) {\n\t  QRMath.EXP_TABLE[i] = 1 << i;\n\t}\n\tfor (var i = 8; i < 256; i++) {\n\t  QRMath.EXP_TABLE[i] = QRMath.EXP_TABLE[i - 4] ^ QRMath.EXP_TABLE[i - 5] ^ QRMath.EXP_TABLE[i - 6] ^ QRMath.EXP_TABLE[i - 8];\n\t}\n\tfor (var i = 0; i < 255; i++) {\n\t  QRMath.LOG_TABLE[QRMath.EXP_TABLE[i]] = i;\n\t}\n\n\t//---------------------------------------------------------------------\n\t// QRPolynomial 多项式\n\t//---------------------------------------------------------------------\n\t/**\n\t * 多项式类\n\t * @param {Array} num   系数\n\t * @param {num} shift a^shift\n\t */\n\tfunction QRPolynomial(num, shift) {\n\n\t  if (num.length == undefined) {\n\t    throw new Error(num.length + \"/\" + shift);\n\t  }\n\n\t  var offset = 0;\n\n\t  while (offset < num.length && num[offset] == 0) {\n\t    offset++;\n\t  }\n\n\t  this.num = new Array(num.length - offset + shift);\n\t  for (var i = 0; i < num.length - offset; i++) {\n\t    this.num[i] = num[i + offset];\n\t  }\n\t}\n\n\tQRPolynomial.prototype = {\n\n\t  get: function(index) {\n\t    return this.num[index];\n\t  },\n\n\t  getLength: function() {\n\t    return this.num.length;\n\t  },\n\t  /**\n\t   * 多项式乘法\n\t   * @param  {QRPolynomial} e 被乘多项式\n\t   * @return {[type]}   [description]\n\t   */\n\t  multiply: function(e) {\n\n\t    var num = new Array(this.getLength() + e.getLength() - 1);\n\n\t    for (var i = 0; i < this.getLength(); i++) {\n\t      for (var j = 0; j < e.getLength(); j++) {\n\t        num[i + j] ^= QRMath.gexp(QRMath.glog(this.get(i)) + QRMath.glog(e.get(j)));\n\t      }\n\t    }\n\n\t    return new QRPolynomial(num, 0);\n\t  },\n\t  /**\n\t   * 多项式模运算\n\t   * @param  {QRPolynomial} e 模多项式\n\t   * @return {}\n\t   */\n\t  mod: function(e) {\n\t    var tl = this.getLength(),\n\t      el = e.getLength();\n\t    if (tl - el < 0) {\n\t      return this;\n\t    }\n\t    var num = new Array(tl);\n\t    for (var i = 0; i < tl; i++) {\n\t      num[i] = this.get(i);\n\t    }\n\t    while (num.length >= el) {\n\t      var ratio = QRMath.glog(num[0]) - QRMath.glog(e.get(0));\n\n\t      for (var i = 0; i < e.getLength(); i++) {\n\t        num[i] ^= QRMath.gexp(QRMath.glog(e.get(i)) + ratio);\n\t      }\n\t      while (num[0] == 0) {\n\t        num.shift();\n\t      }\n\t    }\n\t    return new QRPolynomial(num, 0);\n\t  }\n\t};\n\n\t//---------------------------------------------------------------------\n\t// RS_BLOCK_TABLE\n\t//---------------------------------------------------------------------\n\t/*\n\t 二维码各个版本信息[块数, 每块中的数据块数, 每块中的信息块数]\n\t */\n\tRS_BLOCK_TABLE = [\n\n\t  // L\n\t  // M\n\t  // Q\n\t  // H\n\n\t  // 1\n\t  [1, 26, 19],\n\t  [1, 26, 16],\n\t  [1, 26, 13],\n\t  [1, 26, 9],\n\n\t  // 2\n\t  [1, 44, 34],\n\t  [1, 44, 28],\n\t  [1, 44, 22],\n\t  [1, 44, 16],\n\n\t  // 3\n\t  [1, 70, 55],\n\t  [1, 70, 44],\n\t  [2, 35, 17],\n\t  [2, 35, 13],\n\n\t  // 4\n\t  [1, 100, 80],\n\t  [2, 50, 32],\n\t  [2, 50, 24],\n\t  [4, 25, 9],\n\n\t  // 5\n\t  [1, 134, 108],\n\t  [2, 67, 43],\n\t  [2, 33, 15, 2, 34, 16],\n\t  [2, 33, 11, 2, 34, 12],\n\n\t  // 6\n\t  [2, 86, 68],\n\t  [4, 43, 27],\n\t  [4, 43, 19],\n\t  [4, 43, 15],\n\n\t  // 7\n\t  [2, 98, 78],\n\t  [4, 49, 31],\n\t  [2, 32, 14, 4, 33, 15],\n\t  [4, 39, 13, 1, 40, 14],\n\n\t  // 8\n\t  [2, 121, 97],\n\t  [2, 60, 38, 2, 61, 39],\n\t  [4, 40, 18, 2, 41, 19],\n\t  [4, 40, 14, 2, 41, 15],\n\n\t  // 9\n\t  [2, 146, 116],\n\t  [3, 58, 36, 2, 59, 37],\n\t  [4, 36, 16, 4, 37, 17],\n\t  [4, 36, 12, 4, 37, 13],\n\n\t  // 10\n\t  [2, 86, 68, 2, 87, 69],\n\t  [4, 69, 43, 1, 70, 44],\n\t  [6, 43, 19, 2, 44, 20],\n\t  [6, 43, 15, 2, 44, 16],\n\n\t  // 11\n\t  [4, 101, 81],\n\t  [1, 80, 50, 4, 81, 51],\n\t  [4, 50, 22, 4, 51, 23],\n\t  [3, 36, 12, 8, 37, 13],\n\n\t  // 12\n\t  [2, 116, 92, 2, 117, 93],\n\t  [6, 58, 36, 2, 59, 37],\n\t  [4, 46, 20, 6, 47, 21],\n\t  [7, 42, 14, 4, 43, 15],\n\n\t  // 13\n\t  [4, 133, 107],\n\t  [8, 59, 37, 1, 60, 38],\n\t  [8, 44, 20, 4, 45, 21],\n\t  [12, 33, 11, 4, 34, 12],\n\n\t  // 14\n\t  [3, 145, 115, 1, 146, 116],\n\t  [4, 64, 40, 5, 65, 41],\n\t  [11, 36, 16, 5, 37, 17],\n\t  [11, 36, 12, 5, 37, 13],\n\n\t  // 15\n\t  [5, 109, 87, 1, 110, 88],\n\t  [5, 65, 41, 5, 66, 42],\n\t  [5, 54, 24, 7, 55, 25],\n\t  [11, 36, 12],\n\n\t  // 16\n\t  [5, 122, 98, 1, 123, 99],\n\t  [7, 73, 45, 3, 74, 46],\n\t  [15, 43, 19, 2, 44, 20],\n\t  [3, 45, 15, 13, 46, 16],\n\n\t  // 17\n\t  [1, 135, 107, 5, 136, 108],\n\t  [10, 74, 46, 1, 75, 47],\n\t  [1, 50, 22, 15, 51, 23],\n\t  [2, 42, 14, 17, 43, 15],\n\n\t  // 18\n\t  [5, 150, 120, 1, 151, 121],\n\t  [9, 69, 43, 4, 70, 44],\n\t  [17, 50, 22, 1, 51, 23],\n\t  [2, 42, 14, 19, 43, 15],\n\n\t  // 19\n\t  [3, 141, 113, 4, 142, 114],\n\t  [3, 70, 44, 11, 71, 45],\n\t  [17, 47, 21, 4, 48, 22],\n\t  [9, 39, 13, 16, 40, 14],\n\n\t  // 20\n\t  [3, 135, 107, 5, 136, 108],\n\t  [3, 67, 41, 13, 68, 42],\n\t  [15, 54, 24, 5, 55, 25],\n\t  [15, 43, 15, 10, 44, 16],\n\n\t  // 21\n\t  [4, 144, 116, 4, 145, 117],\n\t  [17, 68, 42],\n\t  [17, 50, 22, 6, 51, 23],\n\t  [19, 46, 16, 6, 47, 17],\n\n\t  // 22\n\t  [2, 139, 111, 7, 140, 112],\n\t  [17, 74, 46],\n\t  [7, 54, 24, 16, 55, 25],\n\t  [34, 37, 13],\n\n\t  // 23\n\t  [4, 151, 121, 5, 152, 122],\n\t  [4, 75, 47, 14, 76, 48],\n\t  [11, 54, 24, 14, 55, 25],\n\t  [16, 45, 15, 14, 46, 16],\n\n\t  // 24\n\t  [6, 147, 117, 4, 148, 118],\n\t  [6, 73, 45, 14, 74, 46],\n\t  [11, 54, 24, 16, 55, 25],\n\t  [30, 46, 16, 2, 47, 17],\n\n\t  // 25\n\t  [8, 132, 106, 4, 133, 107],\n\t  [8, 75, 47, 13, 76, 48],\n\t  [7, 54, 24, 22, 55, 25],\n\t  [22, 45, 15, 13, 46, 16],\n\n\t  // 26\n\t  [10, 142, 114, 2, 143, 115],\n\t  [19, 74, 46, 4, 75, 47],\n\t  [28, 50, 22, 6, 51, 23],\n\t  [33, 46, 16, 4, 47, 17],\n\n\t  // 27\n\t  [8, 152, 122, 4, 153, 123],\n\t  [22, 73, 45, 3, 74, 46],\n\t  [8, 53, 23, 26, 54, 24],\n\t  [12, 45, 15, 28, 46, 16],\n\n\t  // 28\n\t  [3, 147, 117, 10, 148, 118],\n\t  [3, 73, 45, 23, 74, 46],\n\t  [4, 54, 24, 31, 55, 25],\n\t  [11, 45, 15, 31, 46, 16],\n\n\t  // 29\n\t  [7, 146, 116, 7, 147, 117],\n\t  [21, 73, 45, 7, 74, 46],\n\t  [1, 53, 23, 37, 54, 24],\n\t  [19, 45, 15, 26, 46, 16],\n\n\t  // 30\n\t  [5, 145, 115, 10, 146, 116],\n\t  [19, 75, 47, 10, 76, 48],\n\t  [15, 54, 24, 25, 55, 25],\n\t  [23, 45, 15, 25, 46, 16],\n\n\t  // 31\n\t  [13, 145, 115, 3, 146, 116],\n\t  [2, 74, 46, 29, 75, 47],\n\t  [42, 54, 24, 1, 55, 25],\n\t  [23, 45, 15, 28, 46, 16],\n\n\t  // 32\n\t  [17, 145, 115],\n\t  [10, 74, 46, 23, 75, 47],\n\t  [10, 54, 24, 35, 55, 25],\n\t  [19, 45, 15, 35, 46, 16],\n\n\t  // 33\n\t  [17, 145, 115, 1, 146, 116],\n\t  [14, 74, 46, 21, 75, 47],\n\t  [29, 54, 24, 19, 55, 25],\n\t  [11, 45, 15, 46, 46, 16],\n\n\t  // 34\n\t  [13, 145, 115, 6, 146, 116],\n\t  [14, 74, 46, 23, 75, 47],\n\t  [44, 54, 24, 7, 55, 25],\n\t  [59, 46, 16, 1, 47, 17],\n\n\t  // 35\n\t  [12, 151, 121, 7, 152, 122],\n\t  [12, 75, 47, 26, 76, 48],\n\t  [39, 54, 24, 14, 55, 25],\n\t  [22, 45, 15, 41, 46, 16],\n\n\t  // 36\n\t  [6, 151, 121, 14, 152, 122],\n\t  [6, 75, 47, 34, 76, 48],\n\t  [46, 54, 24, 10, 55, 25],\n\t  [2, 45, 15, 64, 46, 16],\n\n\t  // 37\n\t  [17, 152, 122, 4, 153, 123],\n\t  [29, 74, 46, 14, 75, 47],\n\t  [49, 54, 24, 10, 55, 25],\n\t  [24, 45, 15, 46, 46, 16],\n\n\t  // 38\n\t  [4, 152, 122, 18, 153, 123],\n\t  [13, 74, 46, 32, 75, 47],\n\t  [48, 54, 24, 14, 55, 25],\n\t  [42, 45, 15, 32, 46, 16],\n\n\t  // 39\n\t  [20, 147, 117, 4, 148, 118],\n\t  [40, 75, 47, 7, 76, 48],\n\t  [43, 54, 24, 22, 55, 25],\n\t  [10, 45, 15, 67, 46, 16],\n\n\t  // 40\n\t  [19, 148, 118, 6, 149, 119],\n\t  [18, 75, 47, 31, 76, 48],\n\t  [34, 54, 24, 34, 55, 25],\n\t  [20, 45, 15, 61, 46, 16]\n\t];\n\n\t/**\n\t * 根据数据获取对应版本\n\t * @return {[type]} [description]\n\t */\n\tQRCodeAlg.prototype.getRightType = function() {\n\t  for (var typeNumber = 1; typeNumber < 41; typeNumber++) {\n\t    var rsBlock = RS_BLOCK_TABLE[(typeNumber - 1) * 4 + this.errorCorrectLevel];\n\t    if (rsBlock == undefined) {\n\t      throw new Error('bad rs block @ typeNumber:' + typeNumber + '/errorCorrectLevel:' + this.errorCorrectLevel);\n\t    }\n\t    var length = rsBlock.length / 3;\n\t    var totalDataCount = 0;\n\t    for (var i = 0; i < length; i++) {\n\t      var count = rsBlock[i * 3 + 0];\n\t      var dataCount = rsBlock[i * 3 + 2];\n\t      totalDataCount += dataCount * count;\n\t    }\n\n\t    var lengthBytes = typeNumber > 9 ? 2 : 1;\n\t    if (this.utf8bytes.length + lengthBytes < totalDataCount || typeNumber == 40) {\n\t      this.typeNumber = typeNumber;\n\t      this.rsBlock = rsBlock;\n\t      this.totalDataCount = totalDataCount;\n\t      break;\n\t    }\n\t  }\n\t};\n\n\t// ---------------------------------------------------------------------\n\t// QRBitBuffer\n\t// ---------------------------------------------------------------------\n\n\tfunction QRBitBuffer() {\n\t  this.buffer = new Array();\n\t  this.length = 0;\n\t}\n\n\tQRBitBuffer.prototype = {\n\t  get: function(index) {\n\t    var bufIndex = Math.floor(index / 8);\n\t    return ((this.buffer[bufIndex] >>> (7 - index % 8)) & 1);\n\t  },\n\n\t  put: function(num, length) {\n\t    for (var i = 0; i < length; i++) {\n\t      this.putBit(((num >>> (length - i - 1)) & 1));\n\t    }\n\t  },\n\n\t  putBit: function(bit) {\n\n\t    var bufIndex = Math.floor(this.length / 8);\n\t    if (this.buffer.length <= bufIndex) {\n\t      this.buffer.push(0);\n\t    }\n\n\t    if (bit) {\n\t      this.buffer[bufIndex] |= (0x80 >>> (this.length % 8));\n\t    }\n\n\t    this.length++;\n\t  }\n\t};\n\n\t$.fn.qrcode = function QRCodePlugin(option) {\n\t  return this.each(function() {\n\t    $(this).append(new QRCode(option));\n\t  });\n\t};\n\n\tmodule.exports = UI.qrcode = QRCode;\n\n\n/***/ },\n/* 27 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\n\t/**\n\t * @via https://github.com/uikit/uikit/blob/master/src/js/addons/sticky.js\n\t * @license https://github.com/uikit/uikit/blob/master/LICENSE.md\n\t */\n\n\t// Sticky Class\n\tvar Sticky = function(element, options) {\n\t  var _this = this;\n\n\t  this.options = $.extend({}, Sticky.DEFAULTS, options);\n\t  this.$element = $(element);\n\t  this.sticked = null;\n\t  this.inited = null;\n\t  this.$holder = undefined;\n\n\t  this.$window = $(window).\n\t    on('scroll.sticky.amui',\n\t    UI.utils.debounce($.proxy(this.checkPosition, this), 10)).\n\t    on('resize.sticky.amui orientationchange.sticky.amui',\n\t    UI.utils.debounce(function() {\n\t      _this.reset(true, function() {\n\t        _this.checkPosition();\n\t      });\n\t    }, 50)).\n\t    on('load.sticky.amui', $.proxy(this.checkPosition, this));\n\n\t  // the `.offset()` is diff between jQuery & Zepto.js\n\t  // jQuery: return `top` and `left`\n\t  // Zepto.js: return `top`, `left`, `width`, `height`\n\t  this.offset = this.$element.offset();\n\n\t  this.init();\n\t};\n\n\tSticky.DEFAULTS = {\n\t  top: 0,\n\t  bottom: 0,\n\t  animation: '',\n\t  className: {\n\t    sticky: 'am-sticky',\n\t    resetting: 'am-sticky-resetting',\n\t    stickyBtm: 'am-sticky-bottom',\n\t    animationRev: 'am-animation-reverse'\n\t  }\n\t};\n\n\tSticky.prototype.init = function() {\n\t  var result = this.check();\n\n\t  if (!result) {\n\t    return false;\n\t  }\n\n\t  var $element = this.$element;\n\t  var $elementMargin = '';\n\n\t  $.each($element.css(\n\t      ['marginTop', 'marginRight', 'marginBottom', 'marginLeft']),\n\t    function(name, value) {\n\t      return $elementMargin += ' ' + value;\n\t    });\n\n\t  var $holder = $('<div class=\"am-sticky-placeholder\"></div>').css({\n\t    height: $element.css('position') !== 'absolute' ?\n\t      $element.outerHeight() : '',\n\t    float: $element.css('float') != 'none' ? $element.css('float') : '',\n\t    margin: $elementMargin\n\t  });\n\n\t  this.$holder = $element.css('margin', 0).wrap($holder).parent();\n\t  this.inited = 1;\n\n\t  return true;\n\t};\n\n\tSticky.prototype.reset = function(force, cb) {\n\t  var options = this.options;\n\t  var $element = this.$element;\n\t  var animation = (options.animation) ?\n\t  ' am-animation-' + options.animation : '';\n\t  var complete = function() {\n\t    $element.css({position: '', top: '', width: '', left: '', margin: 0});\n\t    $element.removeClass([\n\t      animation,\n\t      options.className.animationRev,\n\t      options.className.sticky,\n\t      options.className.resetting\n\t    ].join(' '));\n\n\t    this.animating = false;\n\t    this.sticked = false;\n\t    this.offset = $element.offset();\n\t    cb && cb();\n\t  }.bind(this);\n\n\t  $element.addClass(options.className.resetting);\n\n\t  if (!force && options.animation && UI.support.animation) {\n\n\t    this.animating = true;\n\n\t    $element.removeClass(animation).one(UI.support.animation.end, function() {\n\t      complete();\n\t    }).width(); // force redraw\n\n\t    $element.addClass(animation + ' ' + options.className.animationRev);\n\t  } else {\n\t    complete();\n\t  }\n\t};\n\n\tSticky.prototype.check = function() {\n\t  if (!this.$element.is(':visible')) {\n\t    return false;\n\t  }\n\n\t  var media = this.options.media;\n\n\t  if (media) {\n\t    switch (typeof(media)) {\n\t      case 'number':\n\t        if (window.innerWidth < media) {\n\t          return false;\n\t        }\n\t        break;\n\n\t      case 'string':\n\t        if (window.matchMedia && !window.matchMedia(media).matches) {\n\t          return false;\n\t        }\n\t        break;\n\t    }\n\t  }\n\n\t  return true;\n\t};\n\n\tSticky.prototype.checkPosition = function() {\n\t  if (!this.inited) {\n\t    var initialized = this.init();\n\t    if (!initialized) {\n\t      return;\n\t    }\n\t  }\n\n\t  var options = this.options;\n\t  var scrollTop = this.$window.scrollTop();\n\t  var offsetTop = options.top;\n\t  var offsetBottom = options.bottom;\n\t  var $element = this.$element;\n\t  var animation = (options.animation) ?\n\t    ' am-animation-' + options.animation : '';\n\t  var className = [options.className.sticky, animation].join(' ');\n\n\t  if (typeof offsetBottom == 'function') {\n\t    offsetBottom = offsetBottom(this.$element);\n\t  }\n\n\t  var checkResult = (scrollTop > this.$holder.offset().top);\n\n\t  if (!this.sticked && checkResult) {\n\t    $element.addClass(className);\n\t  } else if (this.sticked && !checkResult) {\n\t    this.reset();\n\t  }\n\n\t  this.$holder.css({\n\t    height: $element.is(':visible') && $element.css('position') !== 'absolute' ?\n\t      $element.outerHeight() : ''\n\t  });\n\n\t  if (checkResult) {\n\t    $element.css({\n\t      top: offsetTop,\n\t      left: this.$holder.offset().left,\n\t      width: this.$holder.width()\n\t    });\n\n\t    /*\n\t     if (offsetBottom) {\n\t     // （底部边距 + 元素高度 > 窗口高度） 时定位到底部\n\t     if ((offsetBottom + this.offset.height > $(window).height()) &&\n\t     (scrollTop + $(window).height() >= scrollHeight - offsetBottom)) {\n\t     $element.addClass(options.className.stickyBtm).\n\t     css({top: $(window).height() - offsetBottom - this.offset.height});\n\t     } else {\n\t     $element.removeClass(options.className.stickyBtm).css({top: offsetTop});\n\t     }\n\t     }\n\t     */\n\t  }\n\n\t  this.sticked = checkResult;\n\t};\n\n\t// Sticky Plugin\n\tUI.plugin('sticky', Sticky);\n\n\t// Init code\n\t$(window).on('load', function() {\n\t  $('[data-am-sticky]').sticky();\n\t});\n\n\tmodule.exports = Sticky;\n\n\n/***/ },\n/* 28 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\tvar Hammer = __webpack_require__(3);\n\tvar supportTransition = UI.support.transition;\n\tvar animation = UI.support.animation;\n\n\t/**\n\t * @via https://github.com/twbs/bootstrap/blob/master/js/tab.js\n\t * @copyright 2011-2014 Twitter, Inc.\n\t * @license MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n\t */\n\n\t/**\n\t * Tabs\n\t * @param {HTMLElement} element\n\t * @param {Object} options\n\t * @constructor\n\t */\n\tvar Tabs = function(element, options) {\n\t  this.$element = $(element);\n\t  this.options = $.extend({}, Tabs.DEFAULTS, options || {});\n\t  this.transitioning = this.activeIndex = null;\n\n\t  this.refresh();\n\t  this.init();\n\t};\n\n\tTabs.DEFAULTS = {\n\t  selector: {\n\t    nav: '> .am-tabs-nav',\n\t    content: '> .am-tabs-bd',\n\t    panel: '> .am-tab-panel'\n\t  },\n\t  activeClass: 'am-active'\n\t};\n\n\tTabs.prototype.refresh = function() {\n\t  var selector = this.options.selector;\n\n\t  this.$tabNav = this.$element.find(selector.nav);\n\t  this.$navs = this.$tabNav.find('a');\n\n\t  this.$content = this.$element.find(selector.content);\n\t  this.$tabPanels = this.$content.find(selector.panel);\n\n\t  var $active = this.$tabNav.find('> .' + this.options.activeClass);\n\n\t  // Activate the first Tab when no active Tab or multiple active Tabs\n\t  if ($active.length !== 1) {\n\t    this.open(0);\n\t  } else {\n\t    this.activeIndex = this.$navs.index($active.children('a'));\n\t  }\n\t};\n\n\tTabs.prototype.init = function() {\n\t  var _this = this;\n\t  var options = this.options;\n\n\t  this.$element.on('click.tabs.amui', options.selector.nav + ' a', function(e) {\n\t    e.preventDefault();\n\t    _this.open($(this));\n\t  });\n\n\t  // TODO: nested Tabs touch events\n\t  if (!options.noSwipe) {\n\t    if (!this.$content.length) {\n\t      return this;\n\t    }\n\n\t    var hammer = new Hammer.Manager(this.$content[0]);\n\t    var swipe = new Hammer.Swipe({\n\t      direction: Hammer.DIRECTION_HORIZONTAL\n\t      // threshold: 40\n\t    });\n\n\t    hammer.add(swipe);\n\n\t    hammer.on('swipeleft', UI.utils.debounce(function(e) {\n\t      e.preventDefault();\n\t      _this.goTo('next');\n\t    }, 100));\n\n\t    hammer.on('swiperight', UI.utils.debounce(function(e) {\n\t      e.preventDefault();\n\t      _this.goTo('prev');\n\t    }, 100));\n\n\t    this._hammer = hammer;\n\t  }\n\t};\n\n\t/**\n\t * Open $nav tab\n\t * @param {jQuery|HTMLElement|Number} $nav\n\t * @returns {Tabs}\n\t */\n\tTabs.prototype.open = function($nav) {\n\t  var activeClass = this.options.activeClass;\n\t  var activeIndex = typeof $nav === 'number' ? $nav : this.$navs.index($($nav));\n\n\t  $nav = typeof $nav === 'number' ? this.$navs.eq(activeIndex) : $($nav);\n\n\t  if (!$nav ||\n\t    !$nav.length ||\n\t    this.transitioning ||\n\t    $nav.parent('li').hasClass(activeClass)) {\n\t    return;\n\t  }\n\n\t  var $tabNav = this.$tabNav;\n\t  var href = $nav.attr('href');\n\t  var regexHash = /^#.+$/;\n\t  var $target = regexHash.test(href) && this.$content.find(href) ||\n\t    this.$tabPanels.eq(activeIndex);\n\t  var previous = $tabNav.find('.' + activeClass + ' a')[0];\n\t  var e = $.Event('open.tabs.amui', {\n\t    relatedTarget: previous\n\t  });\n\n\t  $nav.trigger(e);\n\n\t  if (e.isDefaultPrevented()) {\n\t    return;\n\t  }\n\n\t  // activate Tab nav\n\t  this.activate($nav.closest('li'), $tabNav);\n\n\t  // activate Tab content\n\t  this.activate($target, this.$content, function() {\n\t    $nav.trigger({\n\t      type: 'opened.tabs.amui',\n\t      relatedTarget: previous\n\t    });\n\t  });\n\n\t  this.activeIndex = activeIndex;\n\t};\n\n\tTabs.prototype.activate = function($element, $container, callback) {\n\t  this.transitioning = true;\n\n\t  var activeClass = this.options.activeClass;\n\t  var $active = $container.find('> .' + activeClass);\n\t  var transition = callback && supportTransition && !!$active.length;\n\n\t  $active.removeClass(activeClass + ' am-in');\n\n\t  $element.addClass(activeClass);\n\n\t  if (transition) {\n\t    $element.redraw(); // reflow for transition\n\t    $element.addClass('am-in');\n\t  } else {\n\t    $element.removeClass('am-fade');\n\t  }\n\n\t  var complete = $.proxy(function complete() {\n\t    callback && callback();\n\t    this.transitioning = false;\n\t  }, this);\n\n\t  transition ? $active.one(supportTransition.end, complete) : complete();\n\t};\n\n\t/**\n\t * Go to `next` or `prev` tab\n\t * @param {String} direction - `next` or `prev`\n\t */\n\tTabs.prototype.goTo = function(direction) {\n\t  var navIndex = this.activeIndex;\n\t  var isNext = direction === 'next';\n\t  var spring = isNext ? 'am-animation-right-spring' :\n\t    'am-animation-left-spring';\n\n\t  if ((isNext && navIndex + 1 >= this.$navs.length) || // last one\n\t    (!isNext && navIndex === 0)) { // first one\n\t    var $panel = this.$tabPanels.eq(navIndex);\n\n\t    animation && $panel.addClass(spring).on(animation.end, function() {\n\t      $panel.removeClass(spring);\n\t    });\n\t  } else {\n\t    this.open(isNext ? navIndex + 1 : navIndex - 1);\n\t  }\n\t};\n\n\tTabs.prototype.destroy = function() {\n\t  this.$element.off('.tabs.amui');\n\t  Hammer.off(this.$content[0], 'swipeleft swiperight');\n\t  this._hammer && this._hammer.destroy();\n\t  $.removeData(this.$element, 'amui.tabs');\n\t};\n\n\t// Plugin\n\tfunction Plugin(option) {\n\t  var args = Array.prototype.slice.call(arguments, 1);\n\t  var methodReturn;\n\n\t  this.each(function() {\n\t    var $this = $(this);\n\t    var $tabs = $this.is('.am-tabs') && $this || $this.closest('.am-tabs');\n\t    var data = $tabs.data('amui.tabs');\n\t    var options = $.extend({}, UI.utils.parseOptions($this.data('amTabs')),\n\t      $.isPlainObject(option) && option);\n\n\t    if (!data) {\n\t      $tabs.data('amui.tabs', (data = new Tabs($tabs[0], options)));\n\t    }\n\n\t    if (typeof option === 'string') {\n\t      if (option === 'open' && $this.is('.am-tabs-nav a')) {\n\t        data.open($this);\n\t      } else {\n\t        methodReturn = typeof data[option] === 'function' ?\n\t          data[option].apply(data, args) : data[option];\n\t      }\n\t    }\n\t  });\n\n\t  return methodReturn === undefined ? this : methodReturn;\n\t}\n\n\t$.fn.tabs = Plugin;\n\n\t// Init code\n\tUI.ready(function(context) {\n\t  $('[data-am-tabs]', context).tabs();\n\t});\n\n\t$(document).on('click.tabs.amui.data-api', '[data-am-tabs] .am-tabs-nav a',\n\t  function(e) {\n\t  e.preventDefault();\n\t  Plugin.call($(this), 'open');\n\t});\n\n\tmodule.exports = UI.tabs = Tabs;\n\n\t// TODO: 1. Ajax 支持\n\t//       2. touch 事件处理逻辑优化\n\n\n/***/ },\n/* 29 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\n\t/**\n\t * UCheck\n\t * @via https://github.com/designmodo/Flat-UI/blob/8ef98df23ba7f5033e596a9bd05b53b535a9fe99/js/radiocheck.js\n\t * @license CC BY 3.0 & MIT\n\t * @param {HTMLElement} element\n\t * @param {object} options\n\t * @constructor\n\t */\n\n\tvar UCheck = function(element, options) {\n\t  this.options = $.extend({}, UCheck.DEFAULTS, options);\n\t  // this.options = $.extend({}, UCheck.DEFAULTS, this.$element.data(), options);\n\t  this.$element = $(element);\n\t  this.init();\n\t};\n\n\tUCheck.DEFAULTS = {\n\t  checkboxClass: 'am-ucheck-checkbox',\n\t  radioClass: 'am-ucheck-radio',\n\t  checkboxTpl: '<span class=\"am-ucheck-icons\">' +\n\t  '<i class=\"am-icon-unchecked\"></i><i class=\"am-icon-checked\"></i></span>',\n\t  radioTpl: '<span class=\"am-ucheck-icons\">' +\n\t  '<i class=\"am-icon-unchecked\"></i><i class=\"am-icon-checked\"></i></span>'\n\t};\n\n\tUCheck.prototype.init = function() {\n\t  var $element = this.$element;\n\t  var element = $element[0];\n\t  var options = this.options;\n\n\t  if (element.type === 'checkbox') {\n\t    $element.addClass(options.checkboxClass)\n\t      .after(options.checkboxTpl);\n\t  } else if (element.type === 'radio') {\n\t    $element.addClass(options.radioClass)\n\t      .after(options.radioTpl);\n\t  }\n\t};\n\n\tUCheck.prototype.check = function() {\n\t  this.$element\n\t    .prop('checked', true)\n\t    .trigger('change.ucheck.amui')\n\t    .trigger('checked.ucheck.amui');\n\t},\n\n\tUCheck.prototype.uncheck = function() {\n\t  this.$element\n\t    .prop('checked', false)\n\t    // trigger `change` event for form validation, etc.\n\t    // @see https://forum.jquery.com/topic/should-chk-prop-checked-true-trigger-change-event\n\t    .trigger('change')\n\t    .trigger('unchecked.ucheck.amui');\n\t},\n\n\tUCheck.prototype.toggle = function() {\n\t  this.$element.\n\t    prop('checked', function(i, value) {\n\t      return !value;\n\t    })\n\t    .trigger('change.ucheck.amui')\n\t    .trigger('toggled.ucheck.amui');\n\t},\n\n\tUCheck.prototype.disable = function() {\n\t  this.$element\n\t    .prop('disabled', true)\n\t    .trigger('change.ucheck.amui')\n\t    .trigger('disabled.ucheck.amui');\n\t},\n\n\tUCheck.prototype.enable = function() {\n\t  this.$element.prop('disabled', false);\n\t  this.$element.trigger('change.ucheck.amui').trigger('enabled.ucheck.amui');\n\t},\n\n\tUCheck.prototype.destroy = function() {\n\t  this.$element\n\t    .removeData('amui.ucheck')\n\t    .removeClass(this.options.checkboxClass + ' ' + this.options.radioClass)\n\t    .next('.am-ucheck-icons')\n\t    .remove()\n\t  .end()\n\t    .trigger('destroyed.ucheck.amui');\n\t};\n\n\tUI.plugin('uCheck', UCheck, {\n\t  after: function() {\n\t    // Adding 'am-nohover' class for touch devices\n\t    if (UI.support.touch) {\n\t      this.parent().hover(function() {\n\t        $(this).addClass('am-nohover');\n\t      }, function() {\n\t        $(this).removeClass('am-nohover');\n\t      });\n\t    }\n\t  }\n\t});\n\n\tUI.ready(function(context) {\n\t  $('[data-am-ucheck]', context).uCheck();\n\t});\n\n\tmodule.exports = UCheck;\n\n\t// TODO: 与表单验证结合使用的情况\n\n\n/***/ },\n/* 30 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\n\tvar Validator = function(element, options) {\n\t  this.options = $.extend({}, Validator.DEFAULTS, options);\n\t  this.options.patterns = $.extend({}, Validator.patterns,\n\t    this.options.patterns);\n\t  var locales = this.options.locales;\n\t  !Validator.validationMessages[locales] && (this.options.locales = 'zh_CN');\n\t  this.$element = $(element);\n\t  this.init();\n\t};\n\n\tValidator.DEFAULTS = {\n\t  debug: false,\n\t  locales: 'zh_CN',\n\t  H5validation: false,\n\t  H5inputType: ['email', 'url', 'number'],\n\t  patterns: {},\n\t  patternClassPrefix: 'js-pattern-',\n\t  activeClass: 'am-active',\n\t  inValidClass: 'am-field-error',\n\t  validClass: 'am-field-valid',\n\n\t  validateOnSubmit: true,\n\t  alwaysRevalidate: false,\n\t  // Elements to validate with allValid (only validating visible elements)\n\t  // :input: selects all input, textarea, select and button elements.\n\t  // @since 2.5: move `:visible` to `ignore` option (became to `:hidden`)\n\t  allFields: ':input:not(:submit, :button, :disabled, .am-novalidate)',\n\n\t  // ignored elements\n\t  // @since 2.5\n\t  ignore: ':hidden:not([data-am-selected], .am-validate)',\n\n\t  // Custom events\n\t  customEvents: 'validate',\n\n\t  // Keyboard events\n\t  keyboardFields: ':input:not(:submit, :button, :disabled, .am-novalidate)',\n\t  keyboardEvents: 'focusout, change', // keyup, focusin\n\n\t  // bind `keyup` event to active field\n\t  activeKeyup: false,\n\t  textareaMaxlenthKeyup: true,\n\n\t  // Mouse events\n\t  pointerFields: 'input[type=\"range\"]:not(:disabled, .am-novalidate), ' +\n\t  'input[type=\"radio\"]:not(:disabled, .am-novalidate), ' +\n\t  'input[type=\"checkbox\"]:not(:disabled, .am-novalidate), ' +\n\t  'select:not(:disabled, .am-novalidate), ' +\n\t  'option:not(:disabled, .am-novalidate)',\n\t  pointerEvents: 'click',\n\n\t  onValid: function(validity) {\n\t  },\n\n\t  onInValid: function(validity) {\n\t  },\n\n\t  markValid: function(validity) {\n\t    // this is Validator instance\n\t    var options = this.options;\n\t    var $field = $(validity.field);\n\t    var $parent = $field.closest('.am-form-group');\n\n\t    $field.addClass(options.validClass).removeClass(options.inValidClass);\n\t    $parent.addClass('am-form-success').removeClass('am-form-error');\n\t    options.onValid.call(this, validity);\n\t  },\n\n\t  markInValid: function(validity) {\n\t    var options = this.options;\n\t    var $field = $(validity.field);\n\t    var $parent = $field.closest('.am-form-group');\n\n\t    $field.addClass(options.inValidClass + ' ' + options.activeClass).\n\t      removeClass(options.validClass);\n\t    $parent.addClass('am-form-error').removeClass('am-form-success');\n\t    options.onInValid.call(this, validity);\n\t  },\n\n\t  validate: function(validity) {\n\t    // return validity;\n\t  },\n\n\t  submit: null\n\t};\n\n\tValidator.VERSION = '2.6.0';\n\n\t/* jshint -W101 */\n\tValidator.patterns = {\n\t  email: /^((([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+(\\.([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(\\\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-zA-Z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-zA-Z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-zA-Z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-zA-Z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.)+(([a-zA-Z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-zA-Z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-zA-Z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-zA-Z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.?$/,\n\n\t  url: /^(https?|ftp):\\/\\/(((([a-zA-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-zA-Z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-zA-Z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-zA-Z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-zA-Z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.)+(([a-zA-Z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-zA-Z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-zA-Z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-zA-Z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.?)(:\\d*)?)(\\/((([a-zA-Z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&'\\(\\)\\*\\+,;=]|:|@)+(\\/(([a-zA-Z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&'\\(\\)\\*\\+,;=]|:|@)*)*)?)?(\\?((([a-zA-Z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&'\\(\\)\\*\\+,;=]|:|@)|[\\uE000-\\uF8FF]|\\/|\\?)*)?(\\#((([a-zA-Z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&'\\(\\)\\*\\+,;=]|:|@)|\\/|\\?)*)?$/,\n\n\t  // Number, including positive, negative, and floating decimal\n\t  number: /^-?(?:\\d+|\\d{1,3}(?:,\\d{3})+)?(?:\\.\\d+)?$/,\n\t  dateISO: /^\\d{4}[\\/\\-]\\d{1,2}[\\/\\-]\\d{1,2}$/,\n\t  integer: /^-?\\d+$/\n\t};\n\t/* jshint +W101 */\n\n\tValidator.validationMessages = {\n\t  zh_CN: {\n\t    valueMissing: '请填写（选择）此字段',\n\t    customError: {\n\t      tooShort: '至少填写 %s 个字符',\n\t      checkedOverflow: '至多选择 %s 项',\n\t      checkedUnderflow: '至少选择 %s 项'\n\t    },\n\t    patternMismatch: '请按照要求的格式填写',\n\t    rangeOverflow: '请填写小于等于 %s 的值',\n\t    rangeUnderflow: '请填写大于等于 %s 的值',\n\t    stepMismatch: '',\n\t    tooLong: '至多填写 %s 个字符',\n\t    typeMismatch: '请按照要求的类型填写'\n\t  }\n\t};\n\n\tValidator.ERROR_MAP = {\n\t  tooShort: 'minlength',\n\t  checkedOverflow: 'maxchecked',\n\t  checkedUnderflow: 'minchecked',\n\t  rangeOverflow: 'max',\n\t  rangeUnderflow: 'min',\n\t  tooLong: 'maxlength'\n\t};\n\n\t// TODO: 考虑表单元素不是 form 子元素的情形\n\t// TODO: change/click/focusout 同时触发时处理重复\n\t// TODO: 显示提示信息\n\n\tValidator.prototype.init = function() {\n\t  var _this = this;\n\t  var $element = this.$element;\n\t  var options = this.options;\n\n\t  // using H5 form validation if option set and supported\n\t  if (options.H5validation && UI.support.formValidation) {\n\t    return false;\n\t  }\n\n\t  // disable HTML5 form validation\n\t  $element.attr('novalidate', 'novalidate');\n\n\t  function regexToPattern(regex) {\n\t    var pattern = regex.toString();\n\t    return pattern.substring(1, pattern.length - 1);\n\t  }\n\n\t  // add pattern to H5 input type\n\t  $.each(options.H5inputType, function(i, type) {\n\t    var $field = $element.find('input[type=' + type + ']');\n\t    if (!$field.attr('pattern') &&\n\t      !$field.is('[class*=' + options.patternClassPrefix + ']')) {\n\t      $field.attr('pattern', regexToPattern(options.patterns[type]));\n\t    }\n\t  });\n\n\t  // add pattern to .js-pattern-xx\n\t  $.each(options.patterns, function(key, value) {\n\t    var $field = $element.find('.' + options.patternClassPrefix + key);\n\t    !$field.attr('pattern') && $field.attr('pattern', regexToPattern(value));\n\t  });\n\n\t  $element.on('submit.validator.amui', function(e) {\n\t    // user custom submit handler\n\t    if (typeof options.submit === 'function') {\n\t      return options.submit.call(_this, e);\n\t    }\n\n\t    if (options.validateOnSubmit) {\n\t      var formValidity = _this.isFormValid();\n\n\t      // sync validate, return result\n\t      if ($.type(formValidity) === 'boolean') {\n\t        return formValidity;\n\t      }\n\n\t      if ($element.data('amui.checked')) {\n\t        return true;\n\t      } else {\n\t        $.when(formValidity).then(function() {\n\t          // done, submit form\n\t          $element.data('amui.checked', true).submit();\n\t        }, function() {\n\t          // fail\n\t          $element.data('amui.checked', false).\n\t            find('.' + options.inValidClass).eq(0).focus();\n\t        });\n\t        return false;\n\t      }\n\t    }\n\t  });\n\n\t  function bindEvents(fields, eventFlags, debounce) {\n\t    var events = eventFlags.split(',');\n\t    var validate = function(e) {\n\t      // console.log(e.type);\n\t      _this.validate(this);\n\t    };\n\n\t    if (debounce) {\n\t      validate = UI.utils.debounce(validate, debounce);\n\t    }\n\n\t    $.each(events, function(i, event) {\n\t      $element.on(event + '.validator.amui', fields, validate);\n\t    });\n\t  }\n\n\t  bindEvents(':input', options.customEvents);\n\t  bindEvents(options.keyboardFields, options.keyboardEvents);\n\t  bindEvents(options.pointerFields, options.pointerEvents);\n\n\t  if (options.textareaMaxlenthKeyup) {\n\t    bindEvents('textarea[maxlength]', 'keyup', 50);\n\t  }\n\n\t  if (options.activeKeyup) {\n\t    bindEvents('.am-active', 'keyup', 50);\n\t  }\n\n\t  /*if (options.errorMessage === 'tooltip') {\n\t    this.$tooltip = $('<div></div>', {\n\t      'class': 'am-validator-message',\n\t      id: UI.utils.generateGUID('am-validator-message')\n\t    });\n\n\t    $(document.body).append(this.$tooltip);\n\t  }*/\n\t};\n\n\tValidator.prototype.isValid = function(field) {\n\t  var $field = $(field);\n\t  var options = this.options;\n\t  // valid field not has been validated\n\t  if ($field.data('validity') === undefined || options.alwaysRevalidate) {\n\t    this.validate(field);\n\t  }\n\n\t  return $field.data('validity') && $field.data('validity').valid;\n\t};\n\n\tValidator.prototype.validate = function(field) {\n\t  var _this = this;\n\t  var $element = this.$element;\n\t  var options = this.options;\n\t  var $field = $(field);\n\n\t  // Validate equal, e.g. confirm password\n\t  var equalTo = $field.data('equalTo');\n\t  if (equalTo) {\n\t    $field.attr('pattern', '^' + $element.find(equalTo).val() + '$');\n\t  }\n\n\t  var pattern = $field.attr('pattern') || false;\n\t  var re = new RegExp(pattern);\n\t  var $radioGroup = null;\n\t  var $checkboxGroup = null;\n\t  // if checkbox, return `:chcked` length\n\t  // NOTE: checkbox and radio should have name attribute\n\t  var value = ($field.is('[type=checkbox]')) ?\n\t    ($checkboxGroup = $element.find('input[name=\"' + field.name + '\"]')).\n\t      filter(':checked').length : ($field.is('[type=radio]') ?\n\t  ($radioGroup = this.$element.find('input[name=\"' + field.name + '\"]')).\n\t    filter(':checked').length > 0 : $field.val());\n\n\t  // if checkbox, valid the first input of checkbox group\n\t  $field = ($checkboxGroup && $checkboxGroup.length) ?\n\t    $checkboxGroup.first() : $field;\n\n\t  var required = ($field.attr('required') !== undefined) &&\n\t    ($field.attr('required') !== 'false');\n\t  var maxLength = parseInt($field.attr('maxlength'), 10);\n\t  var minLength = parseInt($field.attr('minlength'), 10);\n\t  var min = Number($field.attr('min'));\n\t  var max = Number($field.attr('max'));\n\t  var validity = this.createValidity({field: $field[0], valid: true});\n\n\t  // Debug\n\t  if (options.debug && window.console) {\n\t    console.log('Validate: value -> [' + value + ', regex -> [' + re +\n\t    '], required -> ' + required);\n\t    console.log('Regex test: ' + re.test(value) + ', Pattern: ' + pattern);\n\t  }\n\n\t  // check value length\n\t  if (!isNaN(maxLength) && value.length > maxLength) {\n\t    validity.valid = false;\n\t    validity.tooLong = true;\n\t  }\n\n\t  if (!isNaN(minLength) && value.length < minLength) {\n\t    validity.valid = false;\n\t    validity.customError = 'tooShort';\n\t  }\n\n\t  // check minimum and maximum\n\t  // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Input\n\t  // TODO: 日期验证最小值和最大值 min/max\n\t  if (!isNaN(min) && Number(value) < min) {\n\t    validity.valid = false;\n\t    validity.rangeUnderflow = true;\n\t  }\n\n\t  if (!isNaN(max) && Number(value) > max) {\n\t    validity.valid = false;\n\t    validity.rangeOverflow = true;\n\t  }\n\n\t  // check required\n\t  if (required && !value) {\n\t    validity.valid = false;\n\t    validity.valueMissing = true;\n\t  } else if (($checkboxGroup || $field.is('select[multiple=\"multiple\"]')) &&\n\t    value) {\n\t    // check checkboxes / multiple select with `minchecked`/`maxchecked` attr\n\t    // var $multipleField = $checkboxGroup ? $checkboxGroup.first() : $field;\n\n\t    // if is select[multiple=\"multiple\"], return selected length\n\t    value = $checkboxGroup ? value : value.length;\n\n\t    // at least checked\n\t    var minChecked = parseInt($field.attr('minchecked'), 10);\n\t    // at most checked\n\t    var maxChecked = parseInt($field.attr('maxchecked'), 10);\n\n\t    if (!isNaN(minChecked) && value < minChecked) {\n\t      // console.log('At least [%d] items checked！', maxChecked);\n\t      validity.valid = false;\n\t      validity.customError = 'checkedUnderflow';\n\t    }\n\n\t    if (!isNaN(maxChecked) && value > maxChecked) {\n\t      // console.log('At most [%d] items checked！', maxChecked);\n\t      validity.valid = false;\n\t      validity.customError = 'checkedOverflow';\n\t    }\n\t  } else if (pattern && !re.test(value) && value) { // check pattern\n\t    validity.valid = false;\n\t    validity.patternMismatch = true;\n\t  }\n\n\t  var validateComplete = function(validity) {\n\t    this.markField(validity);\n\n\t    var event = $.Event('validated.field.validator.amui');\n\t    event.validity = validity;\n\n\t    $field.trigger(event).data('validity', validity);\n\n\t    // validate the radios/checkboxes with the same name\n\t    var $fields = $radioGroup || $checkboxGroup;\n\t    if ($fields) {\n\t      $fields.not($field).data('validity', validity).each(function() {\n\t        validity.field = this;\n\t        _this.markField(validity);\n\t      });\n\t    }\n\n\t    return validity;\n\t  };\n\n\t  // Run custom validate\n\t  // NOTE: async custom validate should return Deferred project\n\t  var customValidate;\n\t  (typeof options.validate === 'function') &&\n\t    (customValidate = options.validate.call(this, validity));\n\n\t  // Deferred\n\t  if (customValidate) {\n\t    var dfd = new $.Deferred();\n\t    $field.data('amui.dfdValidity', dfd.promise());\n\t    return $.when(customValidate).always(function(validity) {\n\t      dfd[validity.valid ? 'resolve' : 'reject'](validity);\n\t      validateComplete.call(_this, validity);\n\t    });\n\t  }\n\n\t  validateComplete.call(this, validity);\n\t};\n\n\tValidator.prototype.markField = function(validity) {\n\t  var options = this.options;\n\t  var flag = 'mark' + (validity.valid ? '' : 'In') + 'Valid';\n\t  options[flag] && options[flag].call(this, validity);\n\t};\n\n\t// check all fields in the form are valid\n\tValidator.prototype.validateForm = function() {\n\t  var _this = this;\n\t  var $element = this.$element;\n\t  var options = this.options;\n\t  var $allFields = $element.find(options.allFields).not(options.ignore);\n\t  var radioNames = [];\n\t  var valid = true;\n\t  var formValidity = [];\n\t  var $inValidFields = $([]);\n\t  var promises = [];\n\t  // for async validate\n\t  var async = false;\n\n\t  $element.trigger('validate.form.validator.amui');\n\n\t  // Filter radio with the same name and keep only one,\n\t  //   since they will be checked as a group by validate()\n\t  var $filteredFields = $allFields.filter(function(index) {\n\t    var name;\n\t    if (this.tagName === 'INPUT' && this.type === 'radio') {\n\t      name = this.name;\n\t      if (radioNames[name] === true) {\n\t        return false;\n\t      }\n\t      radioNames[name] = true;\n\t    }\n\t    return true;\n\t  });\n\n\t  $filteredFields.each(function() {\n\t    var $this = $(this);\n\t    var fieldValid = _this.isValid(this);\n\t    var fieldValidity = $this.data('validity');\n\n\t    valid = !!fieldValid && valid;\n\t    formValidity.push(fieldValidity);\n\n\t    if (!fieldValid) {\n\t      $inValidFields = $inValidFields.add($(this), $element);\n\t    }\n\n\t    // async validity\n\t    var promise = $this.data('amui.dfdValidity');\n\n\t    if (promise) {\n\t      promises.push(promise);\n\t      async = true;\n\t    } else {\n\t      // convert sync validity to Promise\n\t      var dfd = new $.Deferred();\n\t      promises.push(dfd.promise());\n\t      dfd[fieldValid ? 'resolve' : 'reject'](fieldValidity);\n\t    }\n\t  });\n\n\t  // NOTE: If there are async validity, the valid may be not exact result.\n\t  var validity = {\n\t    valid: valid,\n\t    $invalidFields: $inValidFields,\n\t    validity: formValidity,\n\t    promises: promises,\n\t    async: async\n\t  };\n\n\t  $element.trigger('validated.form.validator.amui', validity);\n\n\t  return validity;\n\t};\n\n\tValidator.prototype.isFormValid = function() {\n\t  var _this = this;\n\t  var formValidity = this.validateForm();\n\t  var triggerValid = function(type) {\n\t    _this.$element.trigger(type + '.validator.amui');\n\t  };\n\n\t  if (formValidity.async) {\n\t    var masterDfd = new $.Deferred();\n\n\t    $.when.apply(null, formValidity.promises).then(function() {\n\t      masterDfd.resolve();\n\t      triggerValid('valid');\n\t    }, function() {\n\t      masterDfd.reject();\n\t      triggerValid('invalid');\n\t    });\n\n\t    return masterDfd.promise();\n\t  } else {\n\t    if (!formValidity.valid) {\n\t      var $first = formValidity.$invalidFields.first();\n\n\t      // Selected plugin support\n\t      // @since 2.5\n\t      if ($first.is('[data-am-selected]')) {\n\t        $first = $first.next('.am-selected').find('.am-selected-btn');\n\t      }\n\n\t      $first.focus();\n\t      triggerValid('invalid');\n\t      return false;\n\t    }\n\n\t    triggerValid('valid');\n\t    return true;\n\t  }\n\t};\n\n\t// customErrors:\n\t//    1. tooShort\n\t//    2. checkedOverflow\n\t//    3. checkedUnderflow\n\tValidator.prototype.createValidity = function(validity) {\n\t  return $.extend({\n\t    customError: validity.customError || false,\n\t    patternMismatch: validity.patternMismatch || false,\n\t    rangeOverflow: validity.rangeOverflow || false, // higher than maximum\n\t    rangeUnderflow: validity.rangeUnderflow || false, // lower than  minimum\n\t    stepMismatch: validity.stepMismatch || false,\n\t    tooLong: validity.tooLong || false,\n\t    // value is not in the correct syntax\n\t    typeMismatch: validity.typeMismatch || false,\n\t    valid: validity.valid || true,\n\t    // Returns true if the element has no value but is a required field\n\t    valueMissing: validity.valueMissing || false\n\t  }, validity);\n\t};\n\n\tValidator.prototype.getValidationMessage = function(validity) {\n\t  var messages = Validator.validationMessages[this.options.locales];\n\t  var error;\n\t  var message;\n\t  var placeholder = '%s';\n\t  var $field = $(validity.field);\n\n\t  if ($field.is('[type=\"checkbox\"]') || $field.is('[type=\"radio\"]')) {\n\t    $field = this.$element.find('[name=' + $field.attr('name') + ']').first();\n\t  }\n\n\t  // get error name\n\t  $.each(validity, function(key, val) {\n\t    // skip `field` and `valid`\n\t    if (key === 'field' || key === 'valid') {\n\t      return key;\n\t    }\n\n\t    // Amaze UI custom error type\n\t    if (key === 'customError' && val) {\n\t      error = val;\n\t      messages = messages.customError;\n\t      return false;\n\t    }\n\n\t    // W3C specs error type\n\t    if (val === true) {\n\t      error = key;\n\t      return false;\n\t    }\n\t  });\n\n\t  message = messages[error] || undefined;\n\n\t  if (message && Validator.ERROR_MAP[error]) {\n\t    message = message.replace(placeholder,\n\t      $field.attr(Validator.ERROR_MAP[error]) || '规定的');\n\t  }\n\n\t  return message;\n\t};\n\n\t// remove valid mark\n\tValidator.prototype.removeMark = function() {\n\t  this.$element\n\t    .find('.am-form-success, .am-form-error, .' + this.options.inValidClass +\n\t      ', .' + this.options.validClass)\n\t    .removeClass([\n\t      'am-form-success',\n\t      'am-form-error',\n\t      this.options.inValidClass,\n\t      this.options.validClass\n\t    ].join(' '));\n\t};\n\n\t// @since 2.5\n\tValidator.prototype.destroy = function() {\n\t  this.removeMark();\n\n\t  // Remove data\n\t  // - Validator.prototype.init -> $element.data('amui.checked')\n\t  // - Validator.prototype.validateForm\n\t  // - Validator.prototype.isValid\n\t  this.$element.removeData('amui.validator amui.checked')\n\t    .off('.validator.amui')\n\t    .find(this.options.allFields).removeData('validity amui.dfdValidity');\n\t};\n\n\tUI.plugin('validator', Validator);\n\n\t// init code\n\tUI.ready(function(context) {\n\t  $('[data-am-validator]', context).validator();\n\t});\n\n\tmodule.exports = Validator;\n\n\n/***/ },\n/* 31 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar UI = __webpack_require__(2);\n\n\tvar cookie = {\n\t  get: function(name) {\n\t    var cookieName = encodeURIComponent(name) + '=';\n\t    var cookieStart = document.cookie.indexOf(cookieName);\n\t    var cookieValue = null;\n\t    var cookieEnd;\n\n\t    if (cookieStart > -1) {\n\t      cookieEnd = document.cookie.indexOf(';', cookieStart);\n\t      if (cookieEnd == -1) {\n\t        cookieEnd = document.cookie.length;\n\t      }\n\t      cookieValue = decodeURIComponent(document.cookie.substring(cookieStart +\n\t      cookieName.length, cookieEnd));\n\t    }\n\n\t    return cookieValue;\n\t  },\n\n\t  set: function(name, value, expires, path, domain, secure) {\n\t    var cookieText = encodeURIComponent(name) + '=' +\n\t      encodeURIComponent(value);\n\n\t    if (expires instanceof Date) {\n\t      cookieText += '; expires=' + expires.toUTCString();\n\t    }\n\n\t    if (path) {\n\t      cookieText += '; path=' + path;\n\t    }\n\n\t    if (domain) {\n\t      cookieText += '; domain=' + domain;\n\t    }\n\n\t    if (secure) {\n\t      cookieText += '; secure';\n\t    }\n\n\t    document.cookie = cookieText;\n\t  },\n\n\t  unset: function(name, path, domain, secure) {\n\t    this.set(name, '', new Date(0), path, domain, secure);\n\t  }\n\t};\n\n\tUI.utils = UI.utils || {};\n\n\tmodule.exports = UI.utils.cookie = cookie;\n\n\n/***/ },\n/* 32 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\t/**\n\t * @via https://github.com/sindresorhus/screenfull.js\n\t * @license MIT © Sindre Sorhus\n\t */\n\n\tvar UI = __webpack_require__(2);\n\tvar screenfull = (function() {\n\t  var keyboardAllowed = typeof Element !== 'undefined' &&\n\t    'ALLOW_KEYBOARD_INPUT' in Element;\n\n\t  var fn = (function() {\n\t    var val;\n\t    var valLength;\n\n\t    var fnMap = [\n\t      [\n\t        'requestFullscreen',\n\t        'exitFullscreen',\n\t        'fullscreenElement',\n\t        'fullscreenEnabled',\n\t        'fullscreenchange',\n\t        'fullscreenerror'\n\t      ],\n\t      // new WebKit\n\t      [\n\t        'webkitRequestFullscreen',\n\t        'webkitExitFullscreen',\n\t        'webkitFullscreenElement',\n\t        'webkitFullscreenEnabled',\n\t        'webkitfullscreenchange',\n\t        'webkitfullscreenerror'\n\n\t      ],\n\t      // old WebKit (Safari 5.1)\n\t      [\n\t        'webkitRequestFullScreen',\n\t        'webkitCancelFullScreen',\n\t        'webkitCurrentFullScreenElement',\n\t        'webkitCancelFullScreen',\n\t        'webkitfullscreenchange',\n\t        'webkitfullscreenerror'\n\n\t      ],\n\t      [\n\t        'mozRequestFullScreen',\n\t        'mozCancelFullScreen',\n\t        'mozFullScreenElement',\n\t        'mozFullScreenEnabled',\n\t        'mozfullscreenchange',\n\t        'mozfullscreenerror'\n\t      ],\n\t      [\n\t        'msRequestFullscreen',\n\t        'msExitFullscreen',\n\t        'msFullscreenElement',\n\t        'msFullscreenEnabled',\n\t        'MSFullscreenChange',\n\t        'MSFullscreenError'\n\t      ]\n\t    ];\n\n\t    var i = 0;\n\t    var l = fnMap.length;\n\t    var ret = {};\n\n\t    for (; i < l; i++) {\n\t      val = fnMap[i];\n\t      if (val && val[1] in document) {\n\t        for (i = 0, valLength = val.length; i < valLength; i++) {\n\t          ret[fnMap[0][i]] = val[i];\n\t        }\n\t        return ret;\n\t      }\n\t    }\n\n\t    return false;\n\t  })();\n\n\t  var screenfull = {\n\t    request: function(elem) {\n\t      var request = fn.requestFullscreen;\n\n\t      elem = elem || document.documentElement;\n\n\t      // Work around Safari 5.1 bug: reports support for\n\t      // keyboard in fullscreen even though it doesn't.\n\t      // Browser sniffing, since the alternative with\n\t      // setTimeout is even worse.\n\t      if (/5\\.1[\\.\\d]* Safari/.test(navigator.userAgent)) {\n\t        elem[request]();\n\t      } else {\n\t        elem[request](keyboardAllowed && Element.ALLOW_KEYBOARD_INPUT);\n\t      }\n\t    },\n\t    exit: function() {\n\t      document[fn.exitFullscreen]();\n\t    },\n\t    toggle: function(elem) {\n\t      if (this.isFullscreen) {\n\t        this.exit();\n\t      } else {\n\t        this.request(elem);\n\t      }\n\t    },\n\t    raw: fn\n\t  };\n\n\t  if (!fn) {\n\t    return false;\n\t  }\n\n\t  Object.defineProperties(screenfull, {\n\t    isFullscreen: {\n\t      get: function() {\n\t        return !!document[fn.fullscreenElement];\n\t      }\n\t    },\n\t    element: {\n\t      enumerable: true,\n\t      get: function() {\n\t        return document[fn.fullscreenElement];\n\t      }\n\t    },\n\t    enabled: {\n\t      enumerable: true,\n\t      get: function() {\n\t        // Coerce to boolean in case of old WebKit\n\t        return !!document[fn.fullscreenEnabled];\n\t      }\n\t    }\n\t  });\n\n\t  screenfull.VERSION = '3.0.0';\n\n\t  return screenfull;\n\t})();\n\n\tmodule.exports = UI.fullscreen = screenfull;\n\n\n/***/ },\n/* 33 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\tUI.support.geolocation = window.navigator && window.navigator.geolocation;\n\n\tvar geo = UI.support.geolocation;\n\n\tvar Geolocation = function(options) {\n\t  this.options = options || {};\n\t};\n\n\tGeolocation.MESSAGES = {\n\t  unsupportedBrowser: 'Browser does not support location services',\n\t  permissionDenied: 'You have rejected access to your location',\n\t  positionUnavailable: 'Unable to determine your location',\n\t  timeout: 'Service timeout has been reached'\n\t};\n\n\tGeolocation.ERROR_CODE = {\n\t  0: 'unsupportedBrowser',\n\t  1: 'permissionDenied',\n\t  2: 'positionUnavailable',\n\t  3: 'timeout'\n\t};\n\n\tGeolocation.prototype.get = function(options) {\n\t  var _this = this;\n\t  options = $.extend({}, this.options, options);\n\t  var deferred = new $.Deferred();\n\n\t  if (geo) {\n\t    this.watchID = geo.getCurrentPosition(function(position) {\n\t      deferred.resolve.call(_this, position);\n\t    }, function(error) {\n\t      deferred.reject(Geolocation.MESSAGES[Geolocation.ERROR_CODE[error.code]]);\n\t    }, options);\n\t  } else {\n\t    deferred.reject(Geolocation.MESSAGES.unsupportedBrowser);\n\t  }\n\n\t  return deferred.promise();\n\t};\n\n\tGeolocation.prototype.watch = function(options) {\n\t  if (!geo) {\n\t    return;\n\t  }\n\n\t  options = $.extend({}, this.options, options);\n\n\t  if (!$.isFunction(options.done)) {\n\t    return;\n\t  }\n\n\t  this.clearWatch();\n\n\t  var fail = $.isFunction(options.fail) ? options.fail : null;\n\n\t  this.watchID = geo.watchPosition(options.done, fail, options);\n\n\t  return this.watchID;\n\t};\n\n\tGeolocation.prototype.clearWatch = function() {\n\t  if (!geo || !this.watchID) {\n\t    return;\n\t  }\n\t  geo.clearWatch(this.watchID);\n\t  this.watchID = null;\n\t};\n\n\tmodule.exports = UI.Geolocation = Geolocation;\n\n\n/***/ },\n/* 34 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t/* WEBPACK VAR INJECTION */(function(global) {'use strict';\n\n\tvar UI = __webpack_require__(2);\n\n\t/**\n\t * store.js\n\t * @via https://github.com/marcuswestin/store.js\n\t * @license https://github.com/marcuswestin/store.js/blob/master/LICENSE\n\t */\n\n\tvar store = {};\n\tvar win = (typeof window != 'undefined' ? window : global);\n\tvar localStorageName = 'localStorage';\n\tvar storage;\n\n\tstore.disabled = false;\n\tstore.version = '1.3.20';\n\n\tstore.set = function(key, value) {\n\t};\n\n\tstore.get = function(key, defaultVal) {\n\t};\n\n\tstore.has = function(key) {\n\t  return store.get(key) !== undefined;\n\t};\n\n\tstore.remove = function(key) {\n\t};\n\n\tstore.clear = function() {\n\t};\n\n\tstore.transact = function(key, defaultVal, transactionFn) {\n\t  if (transactionFn == null) {\n\t    transactionFn = defaultVal;\n\t    defaultVal = null;\n\t  }\n\t  if (defaultVal == null) {\n\t    defaultVal = {};\n\t  }\n\n\t  var val = store.get(key, defaultVal);\n\t  transactionFn(val);\n\t  store.set(key, val);\n\t};\n\n\tstore.getAll = function() {\n\t};\n\n\tstore.forEach = function() {\n\t};\n\n\tstore.serialize = function(value) {\n\t  return JSON.stringify(value);\n\t};\n\n\tstore.deserialize = function(value) {\n\t  if (typeof value != 'string') {\n\t    return undefined;\n\t  }\n\n\t  try {\n\t    return JSON.parse(value);\n\t  } catch (e) {\n\t    return value || undefined;\n\t  }\n\t};\n\n\t// Functions to encapsulate questionable FireFox 3.6.13 behavior\n\t// when about.config::dom.storage.enabled === false\n\t// See https://github.com/marcuswestin/store.js/issues#issue/13\n\tfunction isLocalStorageNameSupported() {\n\t  try {\n\t    return (localStorageName in win && win[localStorageName]);\n\t  } catch (err) {\n\t    return false;\n\t  }\n\t}\n\n\tif (isLocalStorageNameSupported()) {\n\t  storage = win[localStorageName];\n\n\t  store.set = function(key, val) {\n\t    if (val === undefined) {\n\t      return store.remove(key);\n\t    }\n\t    storage.setItem(key, store.serialize(val));\n\t    return val;\n\t  };\n\n\t  store.get = function(key, defaultVal) {\n\t    var val = store.deserialize(storage.getItem(key));\n\t    return (val === undefined ? defaultVal : val);\n\t  };\n\n\t  store.remove = function(key) {\n\t    storage.removeItem(key);\n\t  };\n\n\t  store.clear = function() {\n\t    storage.clear();\n\t  };\n\n\t  store.getAll = function() {\n\t    var ret = {};\n\t    store.forEach(function(key, val) {\n\t      ret[key] = val;\n\t    });\n\t    return ret;\n\t  };\n\n\t  store.forEach = function(callback) {\n\t    for (var i = 0; i < storage.length; i++) {\n\t      var key = storage.key(i);\n\t      callback(key, store.get(key));\n\t    }\n\t  };\n\t}\n\n\ttry {\n\t  var testKey = '__storejs__';\n\t  store.set(testKey, testKey);\n\t  if (store.get(testKey) != testKey) {\n\t    store.disabled = true;\n\t  }\n\t  store.remove(testKey);\n\t} catch (e) {\n\t  store.disabled = true;\n\t}\n\n\tstore.enabled = !store.disabled;\n\n\tmodule.exports = UI.store = store;\n\n\t/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))\n\n/***/ },\n/* 35 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\t__webpack_require__(7);\n\n\tfunction accordionInit() {\n\t  var $accordion = $('[data-am-widget=\"accordion\"]');\n\t  var selector = {\n\t    item: '.am-accordion-item',\n\t    title: '.am-accordion-title',\n\t    body: '.am-accordion-bd',\n\t    disabled: '.am-disabled'\n\t  };\n\n\t  $accordion.each(function(i, item) {\n\t    var options = UI.utils.parseOptions($(item).attr('data-am-accordion'));\n\t    var $title = $(item).find(selector.title);\n\n\t    $title.on('click.accordion.amui', function() {\n\t      var $collapse = $(this).next(selector.body);\n\t      var $parent = $(this).parent(selector.item);\n\t      var data = $collapse.data('amui.collapse');\n\n\t      if ($parent.is(selector.disabled)) {\n\t        return;\n\t      }\n\n\t      $parent.toggleClass('am-active');\n\n\t      if (!data) {\n\t        $collapse.collapse();\n\t      } else {\n\t        $collapse.collapse('toggle');\n\t      }\n\n\t      !options.multiple &&\n\t      $(item).children('.am-active').\n\t        not($parent).not(selector.disabled).removeClass('am-active').\n\t        find(selector.body + '.am-in').collapse('close');\n\t    });\n\t  });\n\t}\n\n\t// Init on DOM ready\n\t$(accordionInit);\n\n\tmodule.exports = UI.accordion = {\n\t  VERSION: '2.1.0',\n\t  init: accordionInit\n\t};\n\n\n/***/ },\n/* 36 */\n/***/ function(module, exports) {\n\n\t'use strict';\n\n\tmodule.exports = {\n\t  VERSION: '2.0.1'\n\t};\n\n\n/***/ },\n/* 37 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\n\tfunction duoshuoInit() {\n\t  var $dsThread = $('.ds-thread');\n\t  var dsShortName = $dsThread.parent('[data-am-widget=\"duoshuo\"]').\n\t    attr('data-ds-short-name');\n\t  var dsSrc = (document.location.protocol == 'https:' ? 'https:' : 'http:') +\n\t    '//static.duoshuo.com/embed.js';\n\n\t  if (!$dsThread.length || !dsShortName) {\n\t    return;\n\t  }\n\n\t  window.duoshuoQuery = {\n\t    short_name: dsShortName\n\t  };\n\n\t  // 已经有多说脚本\n\t  if ($('script[src=\"' + dsSrc + '\"]').length) {\n\t    return;\n\t  }\n\n\t  var $dsJS = $('<script>', {\n\t    async: true,\n\t    type: 'text/javascript',\n\t    src: dsSrc,\n\t    charset: 'utf-8'\n\t  });\n\n\t  $('body').append($dsJS);\n\t}\n\n\t$(window).on('load', duoshuoInit);\n\n\tmodule.exports = UI.duoshuo = {\n\t  VERSION: '2.0.1',\n\t  init: duoshuoInit\n\t};\n\n\n/***/ },\n/* 38 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\t__webpack_require__(20);\n\n\t/**\n\t * Is Images zoomable\n\t * @return {Boolean}\n\t */\n\t$.isImgZoomAble = function(element) {\n\t  var t = new Image();\n\t  t.src = element.src;\n\n\t  var zoomAble = ($(element).width() < t.width);\n\n\t  if (zoomAble) {\n\t    $(element).closest('.am-figure').addClass('am-figure-zoomable');\n\t  }\n\n\t  return zoomAble;\n\t};\n\n\tfunction figureInit() {\n\t  $('.am-figure').each(function(i, item) {\n\t    var options = UI.utils.parseOptions($(item).attr('data-am-figure'));\n\t    var $item = $(item);\n\t    var data;\n\n\t    if (options.pureview) {\n\t      if (options.pureview === 'auto') {\n\t        var zoomAble = $.isImgZoomAble($item.find('img')[0]);\n\t        zoomAble && $item.pureview();\n\t      } else {\n\t        $item.addClass('am-figure-zoomable').pureview();\n\t      }\n\t    }\n\n\t    data = $item.data('amui.pureview');\n\n\t    if (data) {\n\t      $item.on('click', ':not(img)', function() {\n\t        data.open(0);\n\t      });\n\t    }\n\t  });\n\t}\n\n\t$(window).on('load', figureInit);\n\n\tmodule.exports = UI.figure = {\n\t  VERSION: '2.0.3',\n\t  init: figureInit\n\t};\n\n\n/***/ },\n/* 39 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\t__webpack_require__(15);\n\tvar addToHS = __webpack_require__(4);\n\tvar cookie = __webpack_require__(31);\n\n\tfunction footerInit() {\n\t  // modal mode\n\t  $('.am-footer-ysp').on('click', function() {\n\t    $('#am-footer-modal').modal();\n\t  });\n\n\t  var options = UI.utils.parseOptions($('.am-footer').data('amFooter'));\n\t  options.addToHS && addToHS();\n\n\t  // switch mode\n\t  // switch to desktop\n\t  $('[data-rel=\"desktop\"]').on('click', function(e) {\n\t    e.preventDefault();\n\t    if (window.AMPlatform) { // front end\n\t      window.AMPlatform.util.goDesktop();\n\t    } else { // back end\n\t      cookie.set('allmobilize', 'desktop', '', '/');\n\t      window.location = window.location;\n\t    }\n\t  });\n\t}\n\n\t$(footerInit);\n\n\tmodule.exports = UI.footer = {\n\t  VERSION: '3.1.2',\n\t  init: footerInit\n\t};\n\n\n/***/ },\n/* 40 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\t__webpack_require__(20);\n\n\tfunction galleryInit() {\n\t  var $gallery = $('[data-am-widget=\"gallery\"]');\n\n\t  $gallery.each(function() {\n\t    var options = UI.utils.parseOptions($(this).attr('data-am-gallery'));\n\n\t    if (options.pureview) {\n\t      (typeof options.pureview === 'object') ?\n\t        $(this).pureview(options.pureview) : $(this).pureview();\n\t    }\n\t  });\n\t}\n\n\t$(galleryInit);\n\n\tmodule.exports = UI.gallery = {\n\t  VERSION: '3.0.0',\n\t  init: galleryInit\n\t};\n\n\n/***/ },\n/* 41 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\t__webpack_require__(23);\n\n\tfunction goTopInit() {\n\t  var $goTop = $('[data-am-widget=\"gotop\"]');\n\t  var $fixed = $goTop.filter('.am-gotop-fixed');\n\t  var $win = $(window);\n\n\t  if ($goTop.data('init')) {\n\t    return;\n\t  }\n\n\t  $goTop.find('a').on('click', function(e) {\n\t    e.preventDefault();\n\t    $win.smoothScroll();\n\t  });\n\n\t  function checkPosition() {\n\t    $fixed[($win.scrollTop() > 50 ? 'add' : 'remove') + 'Class']('am-active');\n\t  }\n\n\t  checkPosition();\n\n\t  $win.on('scroll.gotop.amui', UI.utils.debounce(checkPosition, 100));\n\n\t  $goTop.data('init', true);\n\t}\n\n\t$(goTopInit);\n\n\tmodule.exports = UI.gotop = {\n\t  VERSION: '4.0.2',\n\t  init: goTopInit\n\t};\n\n\n/***/ },\n/* 42 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\n\tfunction headerInit() {\n\t  $('[data-am-widget=\"header\"]').each(function() {\n\t    if ($(this).hasClass('am-header-fixed')) {\n\t      $('body').addClass('am-with-fixed-header');\n\t      return false;\n\t    }\n\t  });\n\t}\n\n\t$(headerInit);\n\n\tmodule.exports = UI.header = {\n\t  VERSION: '2.0.0',\n\t  init: headerInit\n\t};\n\n\n/***/ },\n/* 43 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar UI = __webpack_require__(2);\n\n\tmodule.exports = UI.intro = {\n\t  VERSION: '4.0.2',\n\t  init: function() {}\n\t};\n\n\n/***/ },\n/* 44 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar UI = __webpack_require__(2);\n\n\tmodule.exports = UI.listNews = {\n\t  VERSION: '4.0.0',\n\t  init: function() {}\n\t};\n\n\n/***/ },\n/* 45 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t/* jshint strict: false, maxlen: 200 */\n\t/* global BMap */\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\n\tfunction addMapApi(callback) {\n\t  var $mapApi0 = $('<script />', {\n\t    id: 'am-map-api-0'\n\t  });\n\n\t  $('body').append($mapApi0);\n\n\t  $mapApi0.on('load', function() {\n\t    console.log('load');\n\t    var $mapApi1 = $('<script/>', {\n\t      id: 'am-map-api-1'\n\t    });\n\n\t    $('body').append($mapApi1);\n\n\t    $mapApi1.on('load', function() {\n\t      var script = document.createElement('script');\n\t      script.textContent = '(' + callback.toString() + ')();';\n\t      $('body')[0].appendChild(script);\n\t    }).attr('src', 'http://api.map.baidu.com/getscript' +\n\t      '?type=quick&file=feature' +\n\t      '&ak=WVAXZ05oyNRXS5egLImmentg&t=20140109092002');\n\t  }).attr('src', 'http://api.map.baidu.com/getscript' +\n\t  '?type=quick&file=api&ak=WVAXZ05oyNRXS5egLImmentg&t=20140109092002');\n\n\t  // jQuery 中 `load` 事件触发有问题，动态设置 src 属性才会触发 `load` 事件\n\t  // $mapApi0 = $('<script />', {src: 'xxx'}); 这样的写法在 Zepto.js 中则没有问题\n\t}\n\n\tfunction addBdMap() {\n\t  // 如果使用 $ 选择符，minify 以后会报错: $ is undefined\n\t  // 即使传入 $ 也无效，改为使用原生方法\n\t  // 这个函数作为 callback 会插入到 body 以后才执行，应该是 $ 引用错误导致\n\t  var content = document.querySelector('.am-map');\n\t  var defaultLng = 116.331398; // 经度默认值\n\t  var defaultLat = 39.897445;  // 纬度默认值\n\t  var name = content.getAttribute('data-name');\n\t  var address = content.getAttribute('data-address');\n\t  var lng = content.getAttribute('data-longitude') || defaultLng;\n\t  var lat = content.getAttribute('data-latitude') || defaultLat;\n\t  var setZoom = content.getAttribute('data-setZoom') || 17;\n\t  var icon = content.getAttribute('data-icon');\n\n\t  var map = new BMap.Map('bd-map');\n\n\t  // 实例化一个地理坐标点\n\t  var point = new BMap.Point(lng, lat);\n\n\t  // 设初始化地图, options: 3-18\n\t  map.centerAndZoom(point, setZoom);\n\n\t  // 添加地图缩放控件\n\t  if (content.getAttribute('data-zoomControl')) {\n\t    map.addControl(new BMap.ZoomControl());\n\t  }\n\n\t  // 添加比例尺控件\n\t  if (content.getAttribute('data-scaleControl')) {\n\t    map.addControl(new BMap.ScaleControl());\n\t  }\n\n\t  // 创建标准与自定义 icon\n\t  var marker = new BMap.Marker(point);\n\t  if (icon) {\n\t    marker.setIcon(new BMap.Icon(icon, new BMap.Size(40, 40)));\n\t  }\n\n\t  var opts = {\n\t    width: 200,     // 信息窗口宽度\n\t    // height: 'auto',     // 信息窗口高度\n\t    title: name // 信息窗口标题\n\t  };\n\n\t  // 创建信息窗口对象\n\t  var infoWindow = new BMap.InfoWindow('地址：' + address, opts);\n\n\t  // 创建地址解析器实例\n\t  var myGeo = new BMap.Geocoder();\n\n\t  // 判断有没有使用经纬度\n\t  if (lng == defaultLng && lat == defaultLat) {\n\t    // 使用地址反解析来设置地图\n\t    // 将地址解析结果显示在地图上,并调整地图视野\n\t    myGeo.getPoint(address, function(point) {\n\t      if (point) {\n\t        map.centerAndZoom(point, setZoom);\n\t        marker.setPosition(point);\n\t        map.addOverlay(marker);\n\t        map.openInfoWindow(infoWindow, point); // 开启信息窗口\n\t      }\n\t    }, '');\n\n\t  } else {\n\t    // 使用经纬度来设置地图\n\t    myGeo.getLocation(point, function(result) {\n\t      map.centerAndZoom(point, setZoom);\n\t      marker.setPosition(point);\n\t      map.addOverlay(marker);\n\t      if (address) {\n\t        map.openInfoWindow(infoWindow, point); // 开启信息窗口\n\t      } else {\n\t        map.openInfoWindow(new BMap.InfoWindow(address, opts), point); // 开启信息窗口\n\t      }\n\t    });\n\t  }\n\t}\n\n\tvar mapInit = function() {\n\t  $('.am-map').length && addMapApi(addBdMap);\n\t};\n\n\t$(mapInit);\n\n\tmodule.exports = UI.map = {\n\t  VERSION: '2.0.2',\n\t  init: mapInit\n\t};\n\n\n/***/ },\n/* 46 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\n\tfunction mechatInit() {\n\t  if (!$('#mechat').length) {\n\t    return;\n\t  }\n\n\t  var $mechat = $('[data-am-widget=\"mechat\"]');\n\t  var unitid = $mechat.data('am-mechat-unitid');\n\t  var $mechatData = $('<script>', {\n\t    charset: 'utf-8',\n\t    src: 'http://mechatim.com/js/unit/button.js?id=' + unitid\n\t  });\n\n\t  $('body').append($mechatData);\n\t}\n\n\t// Lazy load\n\t$(window).on('load', mechatInit);\n\n\tmodule.exports = UI.mechat = {\n\t  VERSION: '2.0.1',\n\t  init: mechatInit\n\t};\n\n\n/***/ },\n/* 47 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\tvar IScroll = __webpack_require__(14);\n\t__webpack_require__(16);\n\t__webpack_require__(7);\n\n\tvar menuInit = function() {\n\t  var $menus = $('[data-am-widget=\"menu\"]');\n\n\t  $menus.find('.am-menu-nav .am-parent > a').on('click', function(e) {\n\t    e.preventDefault();\n\t    var $clicked = $(this);\n\t    var $parent = $clicked.parent();\n\t    var $subMenu = $clicked.next('.am-menu-sub');\n\n\t    $parent.toggleClass('am-open');\n\t    $subMenu.collapse('toggle');\n\t    $parent.siblings('.am-parent').removeClass('am-open')\n\t      .children('.am-menu-sub.am-in').collapse('close');\n\t  });\n\n\t  // Dropdown/slideDown menu\n\t  $menus.\n\t    filter('[data-am-menu-collapse]').\n\t    find('> .am-menu-toggle').\n\t    on('click', function(e) {\n\t      e.preventDefault();\n\t      var $this = $(this);\n\t      var $nav = $this.next('.am-menu-nav');\n\n\t      $this.toggleClass('am-active');\n\n\t      $nav.collapse('toggle');\n\t    });\n\n\t  // OffCanvas menu\n\t  $menus.\n\t    filter('[data-am-menu-offcanvas]').\n\t    find('> .am-menu-toggle').\n\t    on('click', function(e) {\n\t      e.preventDefault();\n\t      var $this = $(this);\n\t      var $nav = $this.next('.am-offcanvas');\n\n\t      $this.toggleClass('am-active');\n\n\t      $nav.offCanvas('open');\n\t    });\n\n\t  // Close offCanvas when link clicked\n\t  var autoCloseOffCanvas = '.am-offcanvas[data-dismiss-on=\"click\"]';\n\t  var $autoCloseOffCanvas = $(autoCloseOffCanvas);\n\n\t  $autoCloseOffCanvas.find('a').not('.am-parent>a').on('click', function(e) {\n\t    $(this).parents(autoCloseOffCanvas).offCanvas('close');\n\t  });\n\n\t  // one theme\n\t  $menus.filter('.am-menu-one').each(function(index) {\n\t    var $this = $(this);\n\t    var $wrap = $('<div class=\"am-menu-nav-sub-wrap\"></div>');\n\t    var allWidth = 0;\n\t    var $nav = $this.find('.am-menu-nav');\n\t    var $navTopItem = $nav.children('li');\n\t    var prevIndex;\n\n\t    $navTopItem.filter('.am-parent').each(function(index) {\n\t      $(this).attr('data-rel', '#am-menu-sub-' + index);\n\t      $(this).\n\t        find('.am-menu-sub').\n\t        attr('id', 'am-menu-sub-' + index).\n\t        appendTo($wrap);\n\t    });\n\n\t    $this.append($wrap);\n\n\t    $nav.wrap('<div class=\"am-menu-nav-wrap\" id=\"am-menu-' + index + '\">');\n\n\t    // $navTopItem.eq(0).addClass('am-active');\n\n\t    // 计算出所有 li 宽度\n\t    $navTopItem.each(function(i) {\n\t      allWidth += parseFloat($(this).css('width'));\n\t    });\n\n\t    $nav.width(allWidth);\n\n\t    var menuScroll = new IScroll('#am-menu-' + index, {\n\t      eventPassthrough: true,\n\t      scrollX: true,\n\t      scrollY: false,\n\t      preventDefault: false\n\t    });\n\n\t    $navTopItem.on('click', function() {\n\t      var $clicked = $(this);\n\t      $clicked.addClass('am-active').siblings().removeClass('am-active');\n\n\t      $wrap.find('.am-menu-sub.am-in').collapse('close');\n\n\t      if ($clicked.is('.am-parent')) {\n\t        !$clicked.hasClass('.am-open') &&\n\t        $wrap.find($clicked.attr('data-rel')).collapse('open');\n\t      } else {\n\t        $clicked.siblings().removeClass('am-open');\n\t      }\n\n\t      // 第一次调用，没有prevIndex\n\t      if (prevIndex === undefined) {\n\t        prevIndex = $(this).index() ? 0 : 1;\n\t      }\n\n\t      // 判断方向\n\t      var dir = $(this).index() > prevIndex;\n\t      var target = $(this)[dir ? 'next' : 'prev']();\n\n\t      // 点击的按钮，显示一半\n\t      var offset = target.offset() || $(this).offset();\n\t      var within = $this.offset();\n\n\t      // 父类左边距\n\t      var listOffset;\n\t      var parentLeft = parseInt($this.css('padding-left'));\n\n\t      if (dir ? offset.left + offset.width > within.left + within.width :\n\t        offset.left < within.left) {\n\t        listOffset = $nav.offset();\n\t        menuScroll.scrollTo(dir ?\n\t        within.width - offset.left + listOffset.left -\n\t        offset.width - parentLeft :\n\t        listOffset.left - offset.left, 0, 400);\n\t      }\n\n\t      prevIndex = $(this).index();\n\n\t    });\n\n\t    $this.on('touchmove', function(event) {\n\t      event.preventDefault();\n\t    });\n\t  });\n\t};\n\n\t$(menuInit);\n\n\tmodule.exports = UI.menu = {\n\t  VERSION: '4.0.3',\n\t  init: menuInit\n\t};\n\n\n/***/ },\n/* 48 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\tvar share = __webpack_require__(25);\n\tvar QRCode = __webpack_require__(26);\n\t__webpack_require__(15);\n\n\tfunction navbarInit() {\n\t  var $navBar = $('[data-am-widget=\"navbar\"]');\n\n\t  if (!$navBar.length) {\n\t    return;\n\t  }\n\n\t  var $win = $(window);\n\t  var $body = $('body');\n\t  var $navBarNav = $navBar.find('.am-navbar-nav');\n\t  var $navItems = $navBar.find('li');\n\t  var navItemsCounter = $navItems.length;\n\t  var configItems = $navBarNav.attr('class') &&\n\t    parseInt($navBarNav.attr('class').\n\t      match(/am-avg-sm-(\\d+)/)[1]) || 3;\n\t  var navMinWidth = 60; // 每个 li 最小宽度\n\t  var offsetWidth = 16;\n\t  var $share = $navItems.filter('[data-am-navbar-share]');\n\t  var $qrcode = $navItems.filter('[data-am-navbar-qrcode]');\n\t  var activeStatus = 'am-active';\n\t  var $moreActions = $('<ul class=\"am-navbar-actions\"></ul>', {\n\t    id: UI.utils.generateGUID('am-navbar-actions')\n\t  });\n\t  var $moreLink = $('<li class=\"am-navbar-labels am-navbar-more\">' +\n\t  '<a href=\"javascript: void(0);\">' +\n\t  '<span class=\"am-icon-angle-up\"></span>' +\n\t  '<span class=\"am-navbar-label\">更多</span></a></li>');\n\n\t  // 如果有 Fix 的工具栏则设置 body 的 padding-bottom\n\t  if ($navBar.css('position') == 'fixed') {\n\t    $body.addClass('am-with-fixed-navbar');\n\t  }\n\n\t  if ($qrcode.length) {\n\t    var qrId = 'am-navbar-qrcode';\n\t    $qrModal = $('#' + qrId);\n\n\t    if (!$qrModal.length) {\n\t      var qrImg = $qrcode.attr('data-am-navbar-qrcode');\n\t      var $qrModal = $('<div class=\"am-modal am-modal-no-btn\" id=\"\">' +\n\t      '<div class=\"am-modal-dialog\">' +\n\t      '<div class=\"am-modal-bd\"></div></div>' +\n\t      '</div>', {\n\t        id: qrId\n\t      });\n\t      var $qrContainer = $qrModal.find('.am-modal-bd');\n\n\t      // 判断上传自定义的二维码没有，否则生成二维码\n\t      if (qrImg) {\n\t        $qrContainer.html('<img src=\"' + qrImg + '\"/>');\n\t      } else {\n\t        var qrnode = new QRCode({\n\t          render: 'canvas',\n\t          correctLevel: 0,\n\t          text: window.location.href,\n\t          width: 200,\n\t          height: 200,\n\t          background: '#fff',\n\t          foreground: '#000'\n\t        });\n\t        $qrContainer.html(qrnode);\n\t      }\n\n\t      $body.append($qrModal);\n\t    }\n\n\t    $qrcode.on('click', function(e) {\n\t      e.preventDefault();\n\t      $qrModal.modal();\n\t    });\n\t  }\n\n\t  if (navItemsCounter > configItems && navItemsCounter > calcSuiteItems()) {\n\t    initActions();\n\t  }\n\n\t  // console.log('NavItems: %d, config: %d, best: %d',\n\t  //    navItemsCounter, configItems, calcSuiteItems());\n\n\t  function initActions() {\n\t    $navBarNav.append($moreLink);\n\n\t    $navBarNav.\n\t      find('li').\n\t      not('.am-navbar-more').\n\t      slice(calcSuiteItems() - 1).\n\t      appendTo($moreActions);\n\n\t    // Append more actions\n\t    $navBar.append($moreActions);\n\t  }\n\n\t  function checkNavBarItems() {\n\t    if (calcSuiteItems() >= navItemsCounter) {\n\t      // 显示所有链接，隐藏 more\n\t      $moreLink.hide();\n\t      $moreActions.find('li').insertBefore($moreLink);\n\t      return;\n\t    }\n\n\t    !$navBar.find('.am-navbar-actions').length && initActions();\n\n\t    $moreLink.show();\n\n\t    if ($navBarNav.find('li').length < calcSuiteItems()) {\n\t      $moreActions.find('li').\n\t        slice(0, calcSuiteItems() - $navBarNav.find('li').length).\n\t        insertBefore($moreLink);\n\t    } else if ($navBarNav.find('li').length > calcSuiteItems()) {\n\t      if ($moreActions.find('li').length) {\n\t        $navBarNav.find('li').not($moreLink).slice(calcSuiteItems() - 1).\n\t          insertBefore($moreActions.find('li').first());\n\t      } else {\n\t        $navBarNav.find('li').not($moreLink).slice(calcSuiteItems() - 1).\n\t          appendTo($moreActions);\n\t      }\n\t    }\n\t  }\n\n\t  /**\n\t   * 计算最适合显示的条目个数\n\t   * @returns {number}\n\t   */\n\t  function calcSuiteItems() {\n\t    return Math.floor(($win.width() - offsetWidth) / navMinWidth);\n\t  }\n\n\t  $navBar.on('click.navbar.amui', '.am-navbar-more', function(e) {\n\t    e.preventDefault();\n\n\t    $moreLink[$moreActions.hasClass(activeStatus) ?\n\t      'removeClass' : 'addClass'](activeStatus);\n\n\t    $moreActions.toggleClass(activeStatus);\n\t  });\n\n\t  if ($share.length) {\n\t    $share.on('click.navbar.amui', function(e) {\n\t      e.preventDefault();\n\t      share.toggle();\n\t    });\n\t  }\n\n\t  $win.on('resize.navbar.amui orientationchange.navbar.amui',\n\t    UI.utils.debounce(checkNavBarItems, 150));\n\t}\n\n\t// DOMContent ready\n\t$(navbarInit);\n\n\tmodule.exports = UI.navbar = {\n\t  VERSION: '2.0.2',\n\t  init: navbarInit\n\t};\n\n\n/***/ },\n/* 49 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar UI = __webpack_require__(2);\n\n\tmodule.exports = UI.pagination = {\n\t  VERSION: '3.0.1'\n\t};\n\n\n/***/ },\n/* 50 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\tvar IScroll = __webpack_require__(14);\n\t__webpack_require__(20);\n\n\t/**\n\t * 表格滚动\n\t * @param {number} index ID 标识，多个 paragraph 里面多个 table\n\t */\n\t$.fn.scrollTable = function(index) {\n\t  var $this = $(this);\n\t  var $parent;\n\n\t  $this.wrap('<div class=\"am-paragraph-table-container\" ' +\n\t  'id=\"am-paragraph-table-' + index + '\">' +\n\t  '<div class=\"am-paragraph-table-scroller\"></div></div>');\n\n\t  $parent = $this.parent();\n\t  $parent.width($this.width());\n\t  $parent.height($this.height());\n\n\t  new IScroll('#am-paragraph-table-' + index, {\n\t    eventPassthrough: true,\n\t    scrollX: true,\n\t    scrollY: false,\n\t    preventDefault: false\n\t  });\n\t};\n\n\tfunction paragraphInit() {\n\t  var $paragraph = $('[data-am-widget=\"paragraph\"]');\n\n\t  $paragraph.each(function(index) {\n\t    var $this = $(this);\n\t    var options = UI.utils.parseOptions($this.attr('data-am-paragraph'));\n\t    var $index = index;\n\n\t    if (options.pureview) {\n\t      $this.pureview();\n\t    }\n\n\t    if (options.tableScrollable) {\n\t      $this.find('table').each(function(index) {\n\t        if ($(this).width() > $(window).width()) {\n\t          $(this).scrollTable($index + '-' + index);\n\t        }\n\t      });\n\t    }\n\t  });\n\t}\n\n\t$(window).on('load', paragraphInit);\n\n\tmodule.exports = UI.paragraph = {\n\t  VERSION: '2.0.1',\n\t  init: paragraphInit\n\t};\n\n\n/***/ },\n/* 51 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\t__webpack_require__(11);\n\n\tfunction sliderInit() {\n\t  var $sliders = $('[data-am-widget=\"slider\"]');\n\t  $sliders.not('.am-slider-manual').each(function(i, item) {\n\t    var options = UI.utils.parseOptions($(item).attr('data-am-slider'));\n\t    $(item).flexslider(options);\n\t  });\n\t}\n\n\t$(sliderInit);\n\n\tmodule.exports = UI.slider = {\n\t  VERSION: '3.0.1',\n\t  init: sliderInit\n\t};\n\n\n/***/ },\n/* 52 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\t__webpack_require__(28);\n\n\tfunction tabsInit() {\n\t  $('[data-am-widget=\"tabs\"]').each(function() {\n\t    var options = $(this).data('amTabsNoswipe') ? {noSwipe: 1} : {};\n\t    $(this).tabs(options);\n\t  });\n\t}\n\n\t$(tabsInit);\n\n\tmodule.exports = UI.tab = {\n\t  VERSION: '4.0.1',\n\t  init: tabsInit\n\t};\n\n\n/***/ },\n/* 53 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar UI = __webpack_require__(2);\n\n\tmodule.exports = UI.titlebar = {\n\t  VERSION: '4.0.1'\n\t};\n\n\n/***/ },\n/* 54 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\n\tvar $ = __webpack_require__(1);\n\tvar UI = __webpack_require__(2);\n\n\tvar isWeChat = window.navigator.userAgent.indexOf('MicroMessenger') > -1;\n\n\t/* global wx,alert */\n\n\tfunction appendWeChatSDK(callback) {\n\t  var $weChatSDK = $('<script/>', {\n\t    id: 'wechat-sdk'\n\t  });\n\n\t  $('body').append($weChatSDK);\n\n\t  $weChatSDK.on('load', function() {\n\t    callback && callback();\n\t  }).attr('src', 'http://res.wx.qq.com/open/js/jweixin-1.0.0.js');\n\t}\n\n\tfunction payHandler() {\n\t  var $paymentBtn = $('[data-am-widget=\"wechatpay\"]');\n\n\t  if (!isWeChat) {\n\t    $paymentBtn.hide();\n\t    return false;\n\t  }\n\n\t  $paymentBtn.on('click', '.am-wechatpay-btn', function(e) {\n\t    e.preventDefault();\n\t    var options = UI.utils.parseOptions($(this).parent().data('wechatPay'));\n\t    // console.log(options);\n\t    // alert('pay button clicked');\n\t    if (!window.wx) {\n\t      alert('没有微信 JS SDK');\n\t      return;\n\t    }\n\n\t    wx.checkJsApi({\n\t      jsApiList: ['chooseWXPay'],\n\t      success: function(res) {\n\t        if (res.checkResult.chooseWXPay) {\n\t          wx.chooseWXPay(options);\n\t        } else {\n\t          alert('微信版本不支持支付接口或没有开启！');\n\t        }\n\t      },\n\t      fail: function() {\n\t        alert('调用 checkJsApi 接口时发生错误!');\n\t      }\n\t    });\n\t  });\n\t}\n\n\tvar payInit = payHandler;\n\n\t// Init on DOM ready\n\t$(payInit);\n\n\tmodule.exports = UI.pay = {\n\t  VERSION: '1.0.0',\n\t  init: payInit\n\t};\n\n\n/***/ }\n/******/ ])\n});\n;"
  },
  {
    "path": "open-layui-web/src/main/view/static/base-component/amazeui/js/amazeui.widgets.helper.js",
    "content": "/*! Amaze UI v2.6.0 ~ Handlebars helper | by Amaze UI Team | (c) 2016 AllMobilize, Inc. | Licensed under MIT | 2016-03-31T14:28:54+0800 */ \n(function(undefined) {\n  'use strict';\n\n  var registerIfCondHelper = function(hbs) {\n    hbs.registerHelper('ifCond', function(v1, operator, v2, options) {\n      switch (operator) {\n        case '==':\n          return (v1 == v2) ? options.fn(this) : options.inverse(this);\n          break;\n        case '===':\n          return (v1 === v2) ? options.fn(this) : options.inverse(this);\n          break;\n        case '<':\n          return (v1 < v2) ? options.fn(this) : options.inverse(this);\n          break;\n        case '<=':\n          return (v1 <= v2) ? options.fn(this) : options.inverse(this);\n          break;\n        case '>':\n          return (v1 > v2) ? options.fn(this) : options.inverse(this);\n          break;\n        case '>=':\n          return (v1 >= v2) ? options.fn(this) : options.inverse(this);\n          break;\n        default:\n          return options.inverse(this);\n          break;\n      }\n      return options.inverse(this);\n    });\n  };\n\n  if (typeof module !== 'undefined' && module.exports) {\n    module.exports = registerIfCondHelper;\n  }\n\n  this.Handlebars && registerIfCondHelper(this.Handlebars);\n}).call(this);\n\n(function(undefined){\n  'use strict';\n\n  var registerAMUIPartials = function(hbs) {\n    hbs.registerPartial('accordion', \"{{#this}}\\n  <section data-am-widget=\\\"accordion\\\" class=\\\"am-accordion {{#if theme}}am-accordion-{{theme}}{{else}}am-accordion-default{{/if}}{{#if widgetId}} {{widgetId}}{{/if}}{{#if className}} {{className}}{{/if}}\\\"{{#if id}} id=\\\"{{id}}\\\"{{/if}} data-am-accordion='{ {{#if options.multiple}}\\\"multiple\\\": true{{/if}} }'>\\n    {{#each content}}\\n      <dl class=\\\"am-accordion-item{{#if active}} am-active{{/if}}{{#if disabled}} am-disabled{{/if}}\\\">\\n        <dt class=\\\"am-accordion-title\\\">\\n          {{{title}}}\\n        </dt>\\n        <dd class=\\\"am-accordion-bd am-collapse {{#if active}}am-in{{/if}}\\\">\\n          <!-- 规避 Collapase 处理有 padding 的折叠内容计算计算有误问题， 加一个容器 -->\\n          <div class=\\\"am-accordion-content\\\">\\n            {{{content}}}\\n          </div>\\n        </dd>\\n      </dl>\\n    {{/each}}\\n  </section>\\n{{/this}}\\n\");\n\n    hbs.registerPartial('divider', \"{{#this}}\\n  <hr data-am-widget=\\\"divider\\\" style=\\\"{{#if options.width}}width:{{{options.width}}};{{/if}}{{#if options.height}}height:{{{options.height}}};{{/if}}\\\" class=\\\"am-divider {{#if theme}}am-divider-{{theme}}{{else}}am-divider-default{{/if}}{{#if widgetId}} {{widgetId}}{{/if}}{{#if className}} {{className}}{{/if}}\\\"{{#if id}} id=\\\"{{id}}\\\"{{/if}} />\\n{{/this}}\\n\");\n\n    hbs.registerPartial('duoshuo', \"{{#this}}\\n  <div data-am-widget=\\\"duoshuo\\\" class=\\\"am-duoshuo{{#if theme}} am-duoshuo-{{theme}}{{else}} am-duoshuo-default{{/if}}{{#if widgetId}} {{widgetId}}{{/if}}{{#if className}} {{className}}{{/if}}\\\"{{#if id}} id=\\\"{{id}}\\\"{{/if}} {{#if options.shortName}}data-ds-short-name=\\\"{{options.shortName}}\\\"{{/if}}>\\n    <div class=\\\"ds-thread\\\" {{#if content}}{{#each content}}{{#ifCond @key '==' 'threadKey'}}  data-thread-key=\\\"{{this}}\\\"{{else}} data-{{@key}}=\\\"{{this}}\\\"{{/ifCond}}{{/each}}{{/if}}>\\n    </div>\\n  </div>\\n{{/this}}\");\n\n    hbs.registerPartial('figure', \"{{#this}}\\n  <figure data-am-widget=\\\"figure\\\" class=\\\"am am-figure {{#if theme}}am-figure-{{theme}}{{else}}am-figure-default{{/if}} {{#if widgetId}} {{widgetId}}{{/if}}{{#if className}} {{className}}{{/if}}\\\" {{#if id}}\\n      id=\\\"{{id}}\\\"{{/if}}  data-am-figure=\\\"{ {{#if options.zoomAble}} pureview: '{{options.zoomAble}}'{{/if}} }\\\">\\n    {{#if content.link}}<a href=\\\"{{content.link}}\\\" title=\\\"{{content.figcaption}}\\\" class=\\\"{{className}}\\\">{{/if}}\\n\\n    {{#if options.figcaptionPosition}}\\n      {{#ifCond options.figcaptionPosition '==' 'top'}}\\n        {{#if content.figcaption}}\\n          <figcaption class=\\\"am-figure-capition-top\\\">\\n            {{content.figcaption}}\\n          </figcaption>\\n        {{/if}}\\n      {{/ifCond}}\\n    {{/if}}\\n\\n    {{#if content.img}}\\n      <img src=\\\"{{content.img}}\\\" {{#if content.rel}}data-rel=\\\"{{content.rel}}\\\"{{/if}} alt=\\\"{{#if content.imgAlt}}{{content.imgAlt}}{{else}}{{content.figcaption}}{{/if}}\\\"/>\\n    {{/if}}\\n    {{#if options.figcaptionPosition}}\\n      {{#ifCond options.figcaptionPosition '==' 'bottom'}}\\n        {{#if content.figcaption}}\\n          <figcaption class=\\\"am-figure-capition-btm\\\">\\n            {{content.figcaption}}\\n          </figcaption>\\n        {{/if}}\\n      {{/ifCond}}\\n    {{else}}\\n      {{#if content.figcaption}}\\n        <figcaption class=\\\"am-figure-capition-btm\\\">\\n          {{content.figcaption}}\\n        </figcaption>\\n      {{/if}}\\n    {{/if}}\\n\\n    {{#if content.link}}</a>{{/if}}\\n  </figure>\\n{{/this}}\\n\");\n\n    hbs.registerPartial('footer', \"{{#this}}\\n  <footer data-am-widget=\\\"footer\\\"\\n          class=\\\"am-footer {{#if theme}}am-footer-{{theme}}{{else}}am-footer-default {{/if}}{{#if widgetId}} {{widgetId}}{{/if}}{{#if className}} {{className}}{{/if}}\\\"\\n          {{#if id}}id=\\\"{{id}}\\\"{{/if}} data-am-footer=\\\"{ {{#if options.addToHS}}addToHS: 1{{/if}} }\\\">\\n    <div class=\\\"am-footer-switch\\\">\\n    <span class=\\\"{{#if options.modal}}am-footer-ysp{{/if}}\\\" data-rel=\\\"mobile\\\"\\n          data-am-modal=\\\"{target: '#am-switch-mode'}\\\">\\n      {{#unless content.switchName}}\\n        {{#ifCond content.lang '==' 'en'}}\\n          Mobile\\n        {{else}}\\n          云适配版\\n        {{/ifCond}}\\n      {{else}}\\n        {{content.switchName}}\\n      {{/unless}}\\n    </span>\\n      <span class=\\\"am-footer-divider\\\"> | </span>\\n      <a id=\\\"godesktop\\\" data-rel=\\\"desktop\\\" class=\\\"am-footer-desktop\\\" href=\\\"javascript:\\\">\\n        {{#ifCond content.lang '==' 'en'}}\\n          Desktop\\n        {{else}}\\n          电脑版\\n        {{/ifCond}}\\n      </a>\\n    </div>\\n    <div class=\\\"am-footer-miscs {{#if options.textPosition}}am-text-left{{/if}}\\\">\\n\\n      {{#if options.techSupportCo}}\\n        {{#ifCond content.lang '==' 'en'}}\\n          <p>Supported by {{#if options.techSupportSite}}<a href=\\\"{{options.techSupportSite}}\\\"\\n                                                            title=\\\"{{options.techSupportCo}}\\\"\\n                                                            target=\\\"_blank\\\"> class=\\\"{{className}}\\\"{{{options.techSupportCo}}}</a>{{else}}{{{options.techSupportCo}}}{{/if}}\\n            .</p>\\n        {{else}}\\n          <p>由 {{#if options.techSupportSite}}<a href=\\\"{{options.techSupportSite}}\\\" title=\\\"{{options.techSupportCo}}\\\"\\n                                                target=\\\"_blank\\\" class=\\\"{{techSupportClassName}}\\\">{{{options.techSupportCo}}}</a>{{else}}{{{options.techSupportCo}}}{{/if}}\\n            提供技术支持</p>\\n        {{/ifCond}}\\n      {{/if}}\\n      {{#each content.companyInfo}}\\n        <p>{{{detail}}}</p>\\n      {{/each}}\\n    </div>\\n  </footer>\\n\\n  <div id=\\\"am-footer-modal\\\"\\n       class=\\\"am-modal am-modal-no-btn am-switch-mode-m {{#if theme}}am-switch-mode-m-{{theme}}{{/if}}\\\">\\n    <div class=\\\"am-modal-dialog\\\">\\n      <div class=\\\"am-modal-hd am-modal-footer-hd\\\">\\n        <a href=\\\"javascript:void(0)\\\" data-dismiss=\\\"modal\\\" class=\\\"am-close am-close-spin {{className}}\\\" data-am-modal-close>&times;</a>\\n      </div>\\n      <div class=\\\"am-modal-bd\\\">\\n        {{#ifCond content.lang '==' 'en'}}\\n          You are visiting\\n        {{else}}\\n          您正在浏览的是\\n        {{/ifCond}}\\n\\n        <span class=\\\"am-switch-mode-owner\\\">\\n          {{#if content.owner}}\\n            {{content.owner}}\\n          {{else}}\\n            云适配\\n          {{/if}}\\n        </span>\\n\\n        <span class=\\\"am-switch-mode-slogan\\\">\\n          {{#if content.slogan}}\\n            {{{content.slogan}}}\\n          {{else}}\\n            {{#ifCond content.lang '==' 'en'}}\\n              mobilized version for your device.\\n            {{else}}\\n              为您当前手机订制的移动网站。\\n            {{/ifCond}}\\n          {{/if}}\\n        </span>\\n      </div>\\n    </div>\\n  </div>\\n{{/this}}\\n\");\n\n    hbs.registerPartial('gallery', \"{{#this}}\\n  <ul data-am-widget=\\\"gallery\\\" class=\\\"am-gallery{{#if options.cols}} am-avg-sm-{{options.cols}}{{else}} am-avg-sm-2{{/if}}\\n  am-avg-md-3 am-avg-lg-4 {{#if\\n  theme}}am-gallery-{{theme}}{{else}}am-gallery-default{{/if}}{{#if widgetId}} {{widgetId}}{{/if}}{{#if className}} {{className}}{{/if}}\\\" data-am-gallery=\\\"{ {{#if options.gallery}}pureview: true{{/if}} }\\\" {{#if id}}id=\\\"{{id}}\\\"{{/if}}>\\n    {{#each content}}\\n      <li>\\n        <div class=\\\"am-gallery-item\\\">\\n          {{#if link}}\\n            <a href=\\\"{{link}}\\\" class=\\\"{{className}}\\\">\\n              {{#if img}}<img src=\\\"{{img}}\\\" {{#if rel}}data-rel=\\\"{{rel}}\\\"{{/if}} alt=\\\"{{title}}\\\"/>{{/if}}\\n              {{#if title}}\\n                <h3 class=\\\"am-gallery-title\\\">{{{title}}}</h3>\\n              {{/if}}\\n              {{#if desc}}\\n                <div class=\\\"am-gallery-desc\\\">{{{desc}}}</div>\\n              {{/if}}\\n            </a>\\n          {{else}}\\n            {{#if img}}<img src=\\\"{{img}}\\\" {{#if rel}}data-rel=\\\"{{rel}}\\\"{{/if}} alt=\\\"{{title}}\\\"/>{{/if}}\\n            {{#if title}}\\n              <h3 class=\\\"am-gallery-title\\\">{{{title}}}</h3>\\n            {{/if}}\\n            {{#if desc}}\\n              <div class=\\\"am-gallery-desc\\\">{{{desc}}}</div>\\n            {{/if}}\\n          {{/if}}\\n        </div>\\n      </li>\\n    {{/each}}\\n  </ul>\\n{{/this}}\\n\");\n\n    hbs.registerPartial('gotop', \"{{#this}}\\n  <div data-am-widget=\\\"gotop\\\" class=\\\"am-gotop {{#if theme}}am-gotop-{{theme}}{{else}}am-gotop-default{{/if}}{{#if widgetId}} {{widgetId}}{{/if}}{{#if className}} {{className}}{{/if}}\\\" {{#if id}}id=\\\"{{id}}\\\"{{/if}}>\\n    <a href=\\\"#top\\\" title=\\\"{{content.title}}\\\">\\n      {{#if content.title}}\\n        <span class=\\\"am-gotop-title\\\">{{content.title}}</span>\\n      {{/if}}\\n      {{#if content.customIcon}}\\n        <img class=\\\"am-gotop-icon-custom\\\" src=\\\"{{content.customIcon}}\\\" />\\n      {{else}}\\n        {{#if content.icon}}\\n          <i class=\\\"am-gotop-icon am-icon-{{content.icon}}\\\"></i>\\n        {{else}}\\n          <i class=\\\"am-gotop-icon am-icon-chevron-up\\\"></i>\\n        {{/if}}\\n      {{/if}}\\n    </a>\\n  </div>\\n{{/this}}\\n\");\n\n    hbs.registerPartial('header', \"{{#this}}\\n  <header data-am-widget=\\\"header\\\"\\n          class=\\\"am-header{{#if theme}} am-header-{{theme}}{{else}} am-header-default{{/if}}{{#if options.fixed}} am-header-fixed{{/if}}{{#if widgetId}} {{widgetId}}{{/if}}{{#if className}} {{className}}{{/if}}\\\"{{#if id}}\\n          id=\\\"{{id}}\\\"{{/if}}>\\n    {{#if content.left}}\\n      <div class=\\\"am-header-left am-header-nav\\\">\\n        {{#each content.left}}\\n          <a href=\\\"{{link}}\\\" class=\\\"{{className}}\\\">\\n            {{#if title}}\\n              <span class=\\\"am-header-nav-title\\\">\\n                {{title}}\\n              </span>\\n            {{/if}}\\n\\n            {{# if customIcon}}\\n              <img class=\\\"am-header-icon-custom\\\" src=\\\"{{customIcon}}\\\" alt=\\\"\\\"/>\\n            {{else}}\\n              {{#if icon}}\\n                <i class=\\\"am-header-icon am-icon-{{icon}}\\\"></i>\\n              {{/if}}\\n            {{/if}}\\n          </a>\\n        {{/each}}\\n      </div>\\n    {{/if}}\\n\\n    {{#if content.title}}\\n      <h1 class=\\\"am-header-title\\\">\\n        {{#if content.link}}\\n          <a href=\\\"{{content.link}}\\\" class=\\\"{{content.className}}\\\">\\n            {{{content.title}}}\\n          </a>\\n        {{else}}\\n          {{{content.title}}}\\n        {{/if}}\\n      </h1>\\n    {{/if}}\\n\\n    {{#if content.right}}\\n      <div class=\\\"am-header-right am-header-nav\\\">\\n        {{#each content.right}}\\n          <a href=\\\"{{link}}\\\" class=\\\"{{className}}\\\">\\n            {{#if title}}\\n              <span class=\\\"am-header-nav-title\\\">\\n                {{title}}\\n              </span>\\n            {{/if}}\\n\\n            {{# if customIcon}}\\n              <img class=\\\"am-header-icon-custom\\\" src=\\\"{{customIcon}}\\\" alt=\\\"\\\"/>\\n            {{else}}\\n              {{#if icon}}\\n                <i class=\\\"am-header-icon am-icon-{{icon}}\\\"></i>\\n              {{/if}}\\n            {{/if}}\\n          </a>\\n        {{/each}}\\n      </div>\\n    {{/if}}\\n  </header>\\n{{/this}}\\n\");\n\n    hbs.registerPartial('intro', \"{{#this }}\\n  <div data-am-widget=\\\"intro\\\"\\n       class=\\\"am-intro am-cf {{#if theme}}am-intro-{{theme}}{{else}}am-intro-default{{/if}}{{#if widgetId}} {{widgetId}}{{/if}}{{#if className}} {{className}}{{/if}}\\\"\\n       {{#if id}}id=\\\"{{id}}\\\"{{/if}}>\\n    {{#if content.title}}\\n      <div class=\\\"am-intro-hd\\\">\\n        <h2 class=\\\"am-intro-title\\\">{{{content.title}}}</h2>\\n        {{#if content.more.link}}\\n          {{#ifCond options.position '==' 'top'}}\\n            <a class=\\\"am-intro-more am-intro-more-top {{content.more.className}}\\\" href=\\\"{{content.more.link}}\\\">{{content.more.title}}</a>\\n          {{/ifCond}}\\n        {{/if}}\\n      </div>\\n    {{/if}}\\n\\n    <div class=\\\"am-g am-intro-bd\\\">\\n      {{#if content.left}}\\n        <div\\n            class=\\\"am-intro-left {{#if options.leftCols}}am-u-sm-{{options.leftCols}}{{/if}}\\\">{{{content.left}}}</div>\\n      {{/if}}\\n      {{#if content.right}}\\n        <div\\n            class=\\\"am-intro-right {{#if options.rightCols}}am-u-sm-{{options.rightCols}}{{/if}}\\\">{{{content.right}}}</div>\\n      {{/if}}\\n    </div>\\n    {{#ifCond options.position '==' 'bottom'}}\\n      <div class=\\\"am-intro-more-bottom\\\">\\n        <a class=\\\"am-btn am-btn-default {{content.more.className}}\\\"\\n           href=\\\"{{content.more.link}}\\\">{{content.more.title}}</a>\\n      </div>\\n    {{/ifCond}}\\n  </div>\\n{{/this}}\\n\");\n\n    hbs.registerPartial('list_news', \"{{#this}}\\n  <div data-am-widget=\\\"list_news\\\" class=\\\"am-list-news{{#if theme}} am-list-news-{{theme}}{{else}} am-list-news-default{{/if}}{{#if widgetId}} {{widgetId}}{{/if}}{{#if className}} {{className}}{{/if}}\\\" {{#if id}}id=\\\"{{id}}\\\"{{/if}}>\\n  <!--列表标题-->\\n  {{#if content.header.title}}\\n    <div class=\\\"am-list-news-hd am-cf\\\">\\n      {{#if content.header.link}} <!--带更多链接-->\\n        <a href=\\\"{{content.header.link}}\\\" class=\\\"{{content.header.className}}\\\">\\n          <h2>{{{content.header.title}}}</h2>\\n          {{#ifCond content.header.morePosition '==' 'top'}}\\n            <span class=\\\"am-list-news-more am-fr\\\">{{{content.header.moreText}}}</span>\\n          {{/ifCond}}\\n        </a>\\n      {{else}} <!--不带更多链接-->\\n        <h2>{{{content.header.title}}}</h2>\\n      {{/if}}\\n    </div>\\n  {{/if}}\\n\\n  <div class=\\\"am-list-news-bd\\\">\\n  <ul class=\\\"am-list\\\">\\n  {{#ifCond options.type '==' 'thumb'}}\\n    {{#ifCond options.thumbPosition '==' 'top'}} <!--缩略图在标题上方-->\\n    {{#each content.main}}\\n      <li class=\\\"am-g{{#if date}} am-list-item-dated{{/if}}{{#if desc}} am-list-item-desced{{/if}}{{#if img}} am-list-item-thumbed am-list-item-thumb-top{{/if}}\\\">\\n        {{!--\\n          am-list-item-dated - 带日期\\n          am-list-item-desced - 带描述\\n          am-list-item-thumbed - 带缩略图的\\n        --}}\\n        {{#if img}}\\n        <div class=\\\"am-list-thumb am-u-sm-12\\\">\\n          <a href=\\\"{{link}}\\\" class=\\\"{{className}}\\\">\\n            <img src=\\\"{{img}}\\\" alt=\\\"{{title}}\\\"/>\\n          </a>\\n          {{#if thumbAddition}}\\n            <div class=\\\"am-list-thumb-addon\\\">{{{thumbAddition}}}</div>\\n          {{/if}}\\n        </div>\\n        {{/if}}\\n\\n        <div class=\\\"{{#if img}}{{/if}} am-list-main\\\">\\n          {{#if title}}\\n            <h3 class=\\\"am-list-item-hd\\\"><a href=\\\"{{link}}\\\" class=\\\"{{className}}\\\">{{{title}}}</a></h3>\\n          {{/if}}\\n\\n          {{#if date}}\\n            <span class=\\\"am-list-date\\\">{{date}}</span>\\n          {{/if}}\\n\\n          {{#if desc}}\\n            <div class=\\\"am-list-item-text\\\">{{{desc}}}</div>\\n          {{/if}}\\n\\n          {{#if mainAddition}}\\n            <div class=\\\"am-list-news-addon\\\">{{{mainAddition}}}</div>\\n          {{/if}}\\n        </div>\\n      </li>\\n    {{/each}}\\n    {{/ifCond}}\\n\\n    {{#ifCond options.thumbPosition '==' 'bottom-left'}} <!--缩略图在标题下方居左-->\\n    {{#each content.main}}\\n      <li class=\\\"am-g{{#if date}} am-list-item-dated{{/if}}{{#if desc}} am-list-item-desced{{/if}}{{#if img}} am-list-item-thumbed am-list-item-thumb-bottom-left{{/if}}\\\">\\n        {{!--\\n          am-list-item-dated - 带日期\\n          am-list-item-desced - 带描述\\n          am-list-item-thumbed - 带缩略图的\\n        --}}\\n        {{#if title}}\\n          <h3 class=\\\"am-list-item-hd\\\"><a href=\\\"{{link}}\\\" class=\\\"{{className}}\\\">{{{title}}}</a></h3>\\n        {{/if}}\\n        {{#if img}}\\n        <div class=\\\"am-u-sm-4 am-list-thumb\\\">\\n          <a href=\\\"{{link}}\\\" class=\\\"{{className}}\\\">\\n            <img src=\\\"{{img}}\\\" alt=\\\"{{title}}\\\"/>\\n          </a>\\n          {{#if thumbAddition}}\\n            <div class=\\\"am-list-thumb-addon\\\">{{{thumbAddition}}}</div>\\n          {{/if}}\\n        </div>\\n        {{/if}}\\n\\n        <div class=\\\"{{#if img}} am-u-sm-8 {{/if}} am-list-main\\\">\\n          {{#if date}}\\n            <span class=\\\"am-list-date\\\">{{date}}</span>\\n          {{/if}}\\n\\n          {{#if desc}}\\n            <div class=\\\"am-list-item-text\\\">{{{desc}}}</div>\\n          {{/if}}\\n\\n          {{#if mainAddition}}\\n            <div class=\\\"am-list-news-addon\\\">{{{mainAddition}}}</div>\\n          {{/if}}\\n        </div>\\n      </li>\\n    {{/each}}\\n    {{/ifCond}}\\n\\n    {{#ifCond options.thumbPosition '==' 'bottom-right'}} <!--缩略图在标题下方居右-->\\n    {{#each content.main}}\\n      <li class=\\\"am-g{{#if date}} am-list-item-dated{{/if}}{{#if desc}} am-list-item-desced{{/if}}{{#if img}} am-list-item-thumbed am-list-item-thumb-bottom-right{{/if}}\\\">\\n        {{!--\\n          am-list-item-dated - 带日期\\n          am-list-item-desced - 带描述\\n          am-list-item-thumbed - 带缩略图的\\n        --}}\\n        {{#if title}}\\n          <h3 class=\\\"am-list-item-hd\\\"><a href=\\\"{{link}}\\\" class=\\\"{{className}}\\\">{{{title}}}</a></h3>\\n        {{/if}}\\n\\n        <div class=\\\"{{#if img}} am-u-sm-8{{/if}} am-list-main\\\">\\n          {{#if date}}\\n            <span class=\\\"am-list-date\\\">{{date}}</span>\\n          {{/if}}\\n\\n          {{#if desc}}\\n            <div class=\\\"am-list-item-text\\\">{{{desc}}}</div>\\n          {{/if}}\\n\\n          {{#if mainAddition}}\\n            <div class=\\\"am-list-news-addon\\\">{{{mainAddition}}}</div>\\n          {{/if}}\\n        </div>\\n        {{#if img}}\\n        <div class=\\\"am-list-thumb am-u-sm-4\\\">\\n          <a href=\\\"{{link}}\\\" class=\\\"{{className}}\\\">\\n            <img src=\\\"{{img}}\\\" alt=\\\"{{title}}\\\"/>\\n          </a>\\n          {{#if thumbAddition}}\\n            <div class=\\\"am-list-thumb-addon\\\">{{{thumbAddition}}}</div>\\n          {{/if}}\\n        </div>\\n        {{/if}}\\n      </li>\\n    {{/each}}\\n    {{/ifCond}}\\n\\n    {{#ifCond options.thumbPosition '==' 'left'}} <!--缩略图在标题左边-->\\n    {{#each content.main}}\\n      <li class=\\\"am-g{{#if date}} am-list-item-dated{{/if}}{{#if desc}} am-list-item-desced{{/if}}{{#if img}} am-list-item-thumbed am-list-item-thumb-left{{/if}}\\\">\\n        {{!--\\n          am-list-item-dated - 带日期\\n          am-list-item-desced - 带描述\\n          am-list-item-thumbed - 带缩略图的\\n        --}}\\n        {{#if img}}\\n        <div class=\\\"am-u-sm-4 am-list-thumb\\\">\\n          <a href=\\\"{{link}}\\\" class=\\\"{{className}}\\\">\\n            <img src=\\\"{{img}}\\\" alt=\\\"{{title}}\\\"/>\\n          </a>\\n          {{#if thumbAddition}}\\n            <div class=\\\"am-list-thumb-addon\\\">{{{thumbAddition}}}</div>\\n          {{/if}}\\n        </div>\\n        {{/if}}\\n\\n        <div class=\\\"{{#if img}} am-u-sm-8{{/if}} am-list-main\\\">\\n          {{#if title}}\\n            <h3 class=\\\"am-list-item-hd\\\"><a href=\\\"{{link}}\\\" class=\\\"{{className}}\\\">{{{title}}}</a></h3>\\n          {{/if}}\\n          {{#if date}}\\n            <span class=\\\"am-list-date\\\">{{date}}</span>\\n          {{/if}}\\n\\n          {{#if desc}}\\n            <div class=\\\"am-list-item-text\\\">{{{desc}}}</div>\\n          {{/if}}\\n\\n          {{#if mainAddition}}\\n            <div class=\\\"am-list-news-addon\\\">{{{mainAddition}}}</div>\\n          {{/if}}\\n        </div>\\n      </li>\\n    {{/each}}\\n    {{/ifCond}}\\n\\n    {{#ifCond options.thumbPosition '==' 'right'}} <!--缩略图在标题右边-->\\n    {{#each content.main}}\\n      <li class=\\\"am-g{{#if date}} am-list-item-dated{{/if}}{{#if desc}} am-list-item-desced{{/if}}{{#if img}} am-list-item-thumbed am-list-item-thumb-right{{/if}}\\\">\\n        {{!--\\n          am-list-item-dated - 带日期\\n          am-list-item-desced - 带描述\\n          am-list-item-thumbed - 带缩略图的\\n        --}}\\n        <div class=\\\"{{#if img}} am-u-sm-8{{/if}} am-list-main\\\">\\n          {{#if title}}\\n            <h3 class=\\\"am-list-item-hd\\\"><a href=\\\"{{link}}\\\" class=\\\"{{className}}\\\">{{{title}}}</a></h3>\\n          {{/if}}\\n\\n          {{#if date}}\\n            <span class=\\\"am-list-date\\\">{{date}}</span>\\n          {{/if}}\\n\\n          {{#if desc}}\\n            <div class=\\\"am-list-item-text\\\">{{{desc}}}</div>\\n          {{/if}}\\n\\n          {{#if mainAddition}}\\n            <div class=\\\"am-list-news-addon\\\">{{{mainAddition}}}</div>\\n          {{/if}}\\n        </div>\\n        {{#if img}}\\n          <div class=\\\"am-u-sm-4 am-list-thumb\\\">\\n            <a href=\\\"{{link}}\\\" class=\\\"{{className}}\\\">\\n              <img src=\\\"{{img}}\\\" alt=\\\"{{title}}\\\"/>\\n            </a>\\n            {{#if thumbAddition}}\\n              <div class=\\\"am-list-thumb-addon\\\">{{{thumbAddition}}}</div>\\n            {{/if}}\\n          </div>\\n        {{/if}}\\n      </li>\\n    {{/each}}\\n    {{/ifCond}}\\n\\n  {{else}}{{!--不带缩略图--}}\\n    {{#each content.main}}\\n      <li class=\\\"am-g{{#if date}} am-list-item-dated{{/if}}{{#if desc}} am-list-item-desced{{/if}}{{#if img}} am-list-item-thumbed{{/if}}\\\">\\n        {{!--\\n          am-list-item-dated - 带日期\\n          am-list-item-desced - 带描述\\n          am-list-item-thumbed - 带缩略图的\\n        --}}\\n        {{#if title}}\\n          <a href=\\\"{{link}}\\\" class=\\\"am-list-item-hd {{className}}\\\">{{{title}}}</a>\\n        {{/if}}\\n\\n        {{#if date}}\\n          <span class=\\\"am-list-date\\\">{{date}}</span>\\n        {{/if}}\\n\\n        {{#if desc}}\\n          <div class=\\\"am-list-item-text\\\">{{{desc}}}</div>\\n        {{/if}}\\n\\n        {{#if mainAddition}}\\n          <div class=\\\"am-list-news-addon\\\">{{{mainAddition}}}</div>\\n        {{/if}}\\n      </li>\\n    {{/each}}\\n  {{/ifCond}}\\n  </ul>\\n  </div>\\n\\n  {{#ifCond content.header.morePosition '==' 'bottom'}}<!--更多在底部-->\\n    {{#if content.header.link}}\\n      <div class=\\\"am-list-news-ft\\\">\\n        <a class=\\\"am-list-news-more am-btn am-btn-default {{content.header.className}}\\\" href=\\\"{{content.header.link}}\\\">{{{content.header.moreText}}}</a>\\n      </div>\\n    {{/if}}\\n  {{/ifCond}}\\n  </div>\\n{{/this}}\\n\");\n\n    hbs.registerPartial('map', \"{{#this}}\\n  <div data-am-widget=\\\"map\\\" class=\\\"am-map {{#if theme}}am-map-{{theme}}{{else}}am-map-default{{/if}}{{#if widgetId}} {{widgetId}}{{/if}}{{#if className}} {{className}}{{/if}}\\\"\\n      data-name=\\\"{{options.name}}\\\" data-address=\\\"{{options.address}}\\\" data-longitude=\\\"{{options.longitude}}\\\" data-latitude=\\\"{{options.latitude}}\\\" data-scaleControl=\\\"{{options.scaleControl}}\\\" data-zoomControl=\\\"{{options.zoomControl}}\\\" data-setZoom=\\\"{{options.setZoom}}\\\" data-icon=\\\"{{options.icon}}\\\">\\n    <div id=\\\"bd-map\\\"></div>\\n  </div>\\n{{/this}}\");\n\n    hbs.registerPartial('mechat', \"{{#this}}\\n  <section data-am-widget=\\\"mechat\\\" class=\\\"am-mechat{{#if theme}} am-mechat-{{theme}}{{else}} am-mechat-default{{/if}}{{#if widgetId}} {{widgetId}}{{/if}}{{#if className}} {{className}}{{/if}}\\\" {{#if id}} id=\\\"{{id}}\\\" {{/if}} {{#if options.unitid}}data-am-mechat-unitid=\\\"{{options.unitid}}\\\"{{/if}}>\\n    <div id=\\\"mechat\\\"></div>\\n  </section>\\n{{/this}}\");\n\n    hbs.registerPartial('menu', \"{{#this}}\\n  <nav data-am-widget=\\\"menu\\\" class=\\\"am-menu {{#if theme}} am-menu-{{theme}}{{else}} am-menu-default{{/if}}{{#if widgetId}} {{widgetId}}{{/if}}{{#if className}} {{className}}{{/if}}\\\" {{options.dataset}} {{#if id}}id=\\\"{{id}}\\\"{{/if}}\\n    {{#ifCond theme '==' 'dropdown1'}} data-am-menu-collapse{{/ifCond}}\\n    {{#ifCond theme '==' 'dropdown2'}} data-am-menu-collapse{{/ifCond}}\\n    {{#ifCond theme '==' 'slide1'}} data-am-menu-collapse{{/ifCond}}\\n    {{#ifCond theme '==' 'offcanvas1'}} data-am-menu-offcanvas{{/ifCond}}\\n    {{#ifCond theme '==' 'offcanvas2'}} data-am-menu-offcanvas{{/ifCond}}> {{!-- 与模板深耦合，与 JS 浅耦合 --}}\\n    <a href=\\\"javascript: void(0)\\\" class=\\\"am-menu-toggle\\\">\\n      {{#if options.toggleTitle}}\\n        <span class=\\\"am-menu-toggle-title\\\">{{options.toggleTitle}}</span>\\n      {{/if}}\\n      {{#if options.toggleCustomIcon}}\\n        <img src=\\\"{{options.toggleCustomIcon}}\\\" alt=\\\"Menu Toggle\\\"/>\\n      {{else}}\\n        {{#if options.toggleIcon}}\\n          <i class=\\\"am-menu-toggle-icon am-icon-{{options.toggleIcon}}\\\"></i>\\n          {{else}}\\n          <i class=\\\"am-menu-toggle-icon am-icon-bars\\\"></i>\\n        {{/if}}\\n      {{/if}}\\n    </a>\\n\\n    {{!-- offCanvas menu Wrap --}}\\n    {{!-- 问题：方便用户，但是与主题名称（类名）耦合过深 --}}\\n    {{#ifCond theme '==' 'offcanvas1'}}\\n    <div class=\\\"am-offcanvas\\\" {{#if options.closeOffCanvasOnclick}}data-dismiss-on=\\\"click\\\"{{/if}}>\\n      <div class=\\\"am-offcanvas-bar{{#if options.offCanvasFlip}} am-offcanvas-bar-flip{{/if}}\\\">\\n    {{/ifCond}}\\n    {{#ifCond theme '==' 'offcanvas2'}}\\n    <div class=\\\"am-offcanvas\\\">\\n      <div class=\\\"am-offcanvas-bar{{#if options.offCanvasFlip}} am-offcanvas-bar-flip{{/if}}\\\">\\n    {{/ifCond}}\\n\\n    {{#if content}}\\n      <ul class=\\\"am-menu-nav {{#if options.cols}}am-avg-sm-{{options\\n      .cols}}{{else}}am-avg-sm-1{{/if}}{{#ifCond theme '==' 'dropdown1'}} am-collapse{{/ifCond}}{{#ifCond theme\\n      '==' 'dropdown2'}} am-collapse{{/ifCond}}{{#ifCond theme\\n      '==' 'slide1'}} am-collapse{{/ifCond}}\\\">\\n        {{#each content}}\\n          <li class=\\\"{{#if subMenu}}am-parent{{/if}}{{#if className}} {{className}}{{/if}}\\\">\\n            <a href=\\\"{{link}}\\\" class=\\\"{{className}}\\\" {{#if target}}target=\\\"{{target}}\\\" {{/if}}>{{{title}}}</a>\\n            {{#if subMenu}}\\n              <ul class=\\\"am-menu-sub am-collapse {{#if subCols}} am-avg-sm-{{subCols}}{{else}}\\n              am-avg-sm-1{{/if}} {{subMenuClassName}}\\\">\\n                {{#each subMenu}}\\n                  <li class=\\\"{{#if subMenu}} am-parent{{/if}}{{#if className}} {{className}}{{/if}}\\\">\\n                    <a href=\\\"{{link}}\\\" class=\\\"{{className}}\\\" {{#if target}}target=\\\"{{target}}\\\" {{/if}}>{{{title}}}</a>\\n                  </li>\\n                {{/each}}\\n                {{!-- 显示进入栏目链接 --}}\\n                {{#if channelLink}}\\n                  <li class=\\\"am-menu-nav-channel\\\"><a href=\\\"{{link}}\\\" class=\\\"{{className}}\\\" title=\\\"{{title}}\\\">{{{channelLink}}}</a></li>\\n                {{/if}}\\n              </ul>\\n            {{/if}}\\n          </li>\\n        {{/each}}\\n      </ul>\\n    {{/if}}\\n\\n    {{#ifCond theme '==' 'offcanvas1'}}\\n      </div>\\n    </div>\\n    {{/ifCond}}\\n    {{#ifCond theme '==' 'offcanvas2'}}\\n      </div>\\n    </div>\\n    {{/ifCond}}\\n    {{!-- 不要问我为什么这样写，我也不想这样 --}}\\n  </nav>\\n{{/this}}\\n\");\n\n    hbs.registerPartial('navbar', \"{{#this}}\\n  <div data-am-widget=\\\"navbar\\\" class=\\\"am-navbar am-cf {{#if theme}}am-navbar-{{theme}}{{else}}am-navbar-default{{/if}} {{#if options.iconPosition}}am-navbar-inline{{/if}}{{#if widgetId}} {{widgetId}}{{/if}}{{#if className}} {{className}}{{/if}}\\\"\\n      id=\\\"{{id}}\\\">\\n    {{#if content}}\\n      <ul class=\\\"am-navbar-nav am-cf {{#if options.cols}}am-avg-sm-{{options.cols}}{{/if}}\\\">\\n        {{#each content}}\\n          <li {{{dataApi}}}>\\n            <a href=\\\"{{link}}\\\" class=\\\"{{className}}\\\">\\n              {{#if customIcon}}\\n                <img src=\\\"{{customIcon}}\\\" alt=\\\"{{title}}\\\"/>\\n              {{else}}\\n                {{#if icon}}\\n                  <span class=\\\"am-icon-{{icon}}\\\"></span>\\n                {{/if}}\\n              {{/if}}\\n              {{#if title}}\\n                <span class=\\\"am-navbar-label\\\">{{title}}</span>\\n              {{/if}}\\n            </a>\\n          </li>\\n        {{/each}}\\n      </ul>\\n    {{/if}}\\n  </div>\\n{{/this}}\\n\");\n\n    hbs.registerPartial('pagination', \"{{#this}}\\n  <ul data-am-widget=\\\"pagination\\\"\\n      class=\\\"am-pagination {{#if theme}}am-pagination-{{theme}}{{else}}am-pagination-default{{/if}}{{#if widgetId}} {{widgetId}}{{/if}}{{#if className}} {{className}}{{/if}}\\\"\\n      {{#if id}}id=\\\"{{id}}\\\"{{/if}}>\\n\\n    {{#if content.firstTitle}}\\n      <li class=\\\"am-pagination-first {{content.firstClassName}}\\\">\\n        <a href=\\\"{{content.firstLink}}\\\" class=\\\"{{content.firstClassName}}\\\">{{{content.firstTitle}}}</a>\\n      </li>\\n    {{/if}}\\n\\n    {{#if content.prevTitle}}\\n      <li class=\\\"am-pagination-prev {{content.prevClassName}}\\\">\\n        <a href=\\\"{{content.prevLink}}\\\" class=\\\"{{content.prevClassName}}\\\">{{{content.prevTitle}}}</a>\\n      </li>\\n    {{/if}}\\n\\n    {{! 移除 options.select，根据主题来判断结构，无奈 handlebars 逻辑处理...}}\\n\\n    {{#if content.page}}\\n      {{#ifCond theme '==' 'select'}}\\n        <li class=\\\"am-pagination-select\\\">\\n          <select>\\n            {{#each content.page}}\\n              <option value=\\\"{{link}}\\\" class=\\\"{{className}}\\\">{{title}}{{#if ../content.total}}\\n                / {{../../content.total}}{{/if}}\\n              </option>\\n            {{/each}}\\n          </select>\\n        </li>\\n      {{else}}\\n        {{#ifCond theme '==' 'one'}}\\n          <li class=\\\"am-pagination-select\\\">\\n            <select>\\n              {{#each content.page}}\\n                {{content.total}}\\n                <option value=\\\"{{link}}\\\" class=\\\"{{className}}\\\">{{title}}{{#if ../content.total}}\\n                  / {{../../content.total}}{{/if}}\\n                </option>\\n              {{/each}}\\n            </select>\\n          </li>\\n        {{else}}\\n          {{#each content.page}}\\n            <li class=\\\"{{className}}\\\">\\n              <a href=\\\"{{link}}\\\" class=\\\"{{className}}\\\">{{{title}}}</a>\\n            </li>\\n          {{/each}}\\n        {{/ifCond}}\\n      {{/ifCond}}\\n\\n    {{/if}}\\n\\n    {{#if content.nextTitle}}\\n      <li class=\\\"am-pagination-next {{content.nextClassName}}\\\">\\n        <a href=\\\"{{content.nextLink}}\\\" class=\\\"{{content.nextClassName}}\\\">{{{content.nextTitle}}}</a>\\n      </li>\\n    {{/if}}\\n\\n    {{#if content.lastTitle}}\\n      <li class=\\\"am-pagination-last {{content.lastClassName}}\\\">\\n        <a href=\\\"{{content.lastLink}}\\\" class=\\\"{{content.lastClassName}}\\\">{{{content.lastTitle}}}</a>\\n      </li>\\n    {{/if}}\\n  </ul>\\n{{/this}}\\n\");\n\n    hbs.registerPartial('paragraph', \"{{#this}}\\n  <article data-am-widget=\\\"paragraph\\\"\\n           class=\\\"am-paragraph {{#if theme}}am-paragraph-{{theme}}{{else}}am-paragraph-default{{/if}}{{#if widgetId}} {{widgetId}}{{/if}}{{#if className}} {{className}}{{/if}}\\\"\\n           {{#if id}}id=\\\"{{id}}\\\"{{/if}}\\n           data-am-paragraph=\\\"{ {{#if options.tableScrollable}}tableScrollable: true,{{/if}} {{#if options.imgLightbox}}pureview: true{{/if}} }\\\">\\n\\n    {{#if content}}\\n      {{{ content.content }}}\\n    {{/if}}\\n  </article>\\n{{/this}}\\n\");\n\n    hbs.registerPartial('slider', \"{{#this}}\\n  <div data-am-widget=\\\"slider\\\" class=\\\"am-slider {{#if theme}}am-slider-{{theme}}{{else}}am-slider-default{{/if}}{{#if widgetId}} {{widgetId}}{{/if}}{{#if className}} {{className}}{{/if}}\\\" data-am-slider='{{sliderConfig}}' {{#if id}}id=\\\"{{id}}\\\"{{/if}}>\\n  <ul class=\\\"am-slides\\\">\\n    {{#each content}}\\n      <li{{#if thumb}} data-thumb=\\\"{{thumb}}\\\"{{/if}}>\\n        {{#if link}}\\n          <a href=\\\"{{link}}\\\" class=\\\"{{className}}\\\">\\n        {{/if}}\\n        {{#if img}}\\n        \\t<img src=\\\"{{img}}\\\">\\n        {{/if}}\\n        {{#if desc}}\\n          <div class=\\\"am-slider-desc\\\">{{{desc}}}</div>\\n        {{/if}}\\n        {{#if link}}</a>{{/if}} {{!--/end link--}}\\n      </li>\\n    {{/each}}\\n  </ul>\\n</div>\\n{{/this}}\");\n\n    hbs.registerPartial('tabs', \"{{#this}}\\n  <div data-am-widget=\\\"tabs\\\"\\n       class=\\\"am-tabs{{#if theme}} am-tabs-{{theme}}{{else}} am-tabs-default{{/if}}{{#if widgetId}} {{widgetId}}{{/if}}{{#if className}} {{className}}{{/if}}\\\"\\n       {{#if id}}id=\\\"{{id}}\\\"{{/if}} {{#if options.noSwipe}}data-am-tabs-noswipe=\\\"1\\\"{{/if}}>\\n    {{#if content}}\\n      <ul class=\\\"am-tabs-nav am-cf\\\">\\n        {{#each content}}\\n          <li class=\\\"{{#if active}}am-active{{/if}}\\\"><a href=\\\"[data-tab-panel-{{@index}}]\\\">{{{title}}}</a></li>\\n        {{/each}}\\n      </ul>\\n      <div class=\\\"am-tabs-bd\\\">\\n        {{#each content}}\\n          <div data-tab-panel-{{@index}} class=\\\"am-tab-panel {{#if active}}am-active{{/if}}\\\">\\n            {{{content}}}\\n          </div>\\n        {{/each}}\\n      </div>\\n    {{/if}}\\n  </div>\\n{{/this}}\\n\");\n\n    hbs.registerPartial('titlebar', \"{{#this}}\\n<div data-am-widget=\\\"titlebar\\\" class=\\\"am-titlebar {{#if theme}}am-titlebar-{{theme}}{{else}}am-titlebar-default{{/if}}{{#if widgetId}} {{widgetId}}{{/if}}{{#if className}} {{className}}{{/if}}\\\" {{#if id}}id=\\\"{{id}}\\\"{{/if}}>\\n  {{#if content.title}}\\n    <h2 class=\\\"am-titlebar-title {{#unless content.link}}{{content.className}}{{/unless}}\\\">\\n      {{#if content.link}}\\n        <a href=\\\"{{content.link}}\\\" class=\\\"{{content.className}}\\\">{{{content.title}}}</a>\\n      {{else}}\\n        {{{content.title}}}\\n      {{/if}}\\n    </h2>\\n  {{/if}}\\n\\n  {{#if content.nav}}\\n    <nav class=\\\"am-titlebar-nav\\\">\\n      {{#each content.nav}}\\n        <a href=\\\"{{link}}\\\" class=\\\"{{className}}\\\">{{{title}}}</a>\\n      {{/each}}\\n    </nav>\\n  {{/if}}\\n</div>\\n{{/this}}\\n\");\n\n    hbs.registerPartial('wechatpay', \"{{#this}}\\n  <div data-am-widget=\\\"wechatpay\\\" class=\\\"am-wechatpay{{#if theme}} am-wechatpay-{{theme}}{{else}} am-wechatpay-default{{/if}}{{#if widgetId}} {{widgetId}}{{/if}}{{#if className}} {{className}}{{/if}}\\\"{{#if id}} id=\\\"{{id}}\\\"{{/if}} data-wechat-pay=\\\"{ {{#each content.order}} {{@key}}: '{{this}}',{{/each}} }\\\">\\n      <button type=\\\"button\\\" class=\\\"am-btn am-btn-primary am-btn-block am-wechatpay-btn\\\">\\n        {{#if content.title}}\\n          {{content.title}}\\n        {{else}}\\n          微信支付\\n        {{/if}}\\n      </button>\\n  </div>\\n{{/this}}\\n\");\n\n  };\n\n  if (typeof module !== 'undefined' && module.exports) {\n    module.exports = registerAMUIPartials;\n  }\n\n  this.Handlebars && registerAMUIPartials(this.Handlebars);\n}).call(this);\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/base-component/amazeui/js/app.js",
    "content": "(function($) {\n  'use strict';\n\n  $(function() {\n    var $fullText = $('.admin-fullText');\n    $('#admin-fullscreen').on('click', function() {\n      $.AMUI.fullscreen.toggle();\n    });\n\n    $(document).on($.AMUI.fullscreen.raw.fullscreenchange, function() {\n      $fullText.text($.AMUI.fullscreen.isFullscreen ? '退出全屏' : '开启全屏');\n    });\n  });\n})(jQuery);\n\n\n/*全局配置tab控制*/\n$(function() {\n  var tabCounter = 0;\n  var $tab = $('#admin-tab-body-index');\n  var $nav = $tab.find('.am-tabs-nav');\n  var $bd = $tab.find('.am-tabs-bd');\n\n  function addTab() {\n    var nav = '<li><span class=\"am-icon-close\"></span>' +\n        '<a href=\"javascript: void(0)\">标签 ' + tabCounter + '</a></li>';\n    var content = '<div class=\"am-tab-panel\">动态插入的标签内容' + tabCounter + '</div>';\n\n    $nav.append(nav);\n    $bd.append(content);\n    tabCounter++;\n    $tab.tabs('refresh');\n  }\n\n  // 动态添加标签页\n  $('.js-append-tab').on('click', function() {\n    addTab();\n  });\n\n  /**\n   * 动态添加tab\n   */\n  $(document).on('click','.admin-open-new-tab',function(){\n    var iframeUrl = $(this).attr('iframe-url');\n    var iframeName = $(this).attr('iframe-name');\n    var iframeUuid = $(this).attr('iframe-uuid');\n    if(!iframeUrl || !iframeUuid){\n      return;\n    }\n    addIframeTal(iframeUrl,iframeName,iframeUuid);\n  });\n\n  /**\n   * 刷新当前tab页面\n   */\n  $(document).on('click','.am-tab-refresh',function(){\n    var clickIndex = 0;\n    var iframeUuid = $(this).attr('iframe-uuid');\n    $('#admin-tab-body-index>ul>li').each(function(index){\n      if($(this).attr('iframe-uuid') == iframeUuid){\n        clickIndex = index;\n        return;\n      }\n    });\n    //console.log($($('#admin-tab-body-index .am-tabs-bd .am-tab-panel')[clickIndex]).find('iframe')[0])\n    $('.admin-iframe-html')[clickIndex].contentWindow.location.reload(true);\n  });\n\n\n  function addIframeTal(iframeUrl,tabName,iframeUuid){\n    var haveFlg = false;\n    //判断是否打开了该标签页，不能重复打开标签页\n    $('#admin-tab-body-index>ul>li').each(function(index){\n      if($(this).attr('iframe-uuid') == iframeUuid){\n        $tab.tabs('open',index);\n        haveFlg = true;\n        return;\n      }\n    });\n    if(haveFlg == true){\n      return;\n    }\n\n    //不存在该tab则新建tab\n    var nav = '<li iframe-uuid=\"'+iframeUuid+'\">' +\n        '<span class=\"am-tab-refresh am-icon-refresh\" iframe-url=\"'+iframeUrl+'\" iframe-uuid=\"'+iframeUuid+'\"></span>' +\n        '<span class=\"am-icon-close\"></span>' +\n        '<a href=\"javascript: void(0)\" iframe-uuid=\"'+iframeUuid+'\">' + tabName + '</a></li>';\n    var content = '<div class=\"am-tab-panel\" style=\"height: 100%\"><iframe src=\"'+iframeUrl+'\" class=\"admin-iframe-html\" style=\"width: 100%;height: 100%;\"></iframe></div>';\n    $nav.append(nav);\n    $bd.append(content);\n    $tab.tabs('refresh');\n    //$('#admin-tab-body-index').tabs('open',$('#admin-tab-body-index>ul>li').length -1);\n    setTimeout(\"$('#admin-tab-body-index').tabs('open',$('#admin-tab-body-index>ul>li').length -1);\",50);\n  }\n\n\n\n  // 移除标签页\n  $nav.on('click', '.am-icon-close', function() {\n    var $item = $(this).closest('li');\n    var index = $nav.children('li').index($item);\n\n    $item.remove();\n    $bd.find('.am-tab-panel').eq(index).remove();\n\n    $tab.tabs('open', index > 0 ? index - 1 : index + 1);\n    $tab.tabs('refresh');\n  });\n\n  /**\n   * 左移tab标签\n   */\n  $('.admin-tab-left').on('click',function(){\n    moveToRight();\n  });\n\n  function moveToLeft(){\n    //需要显示的下一个tab\n    var getCurrentFlg = false;\n    var currentTab = 0;\n    //需要添加的margin-left总数\n    var addMargin = 0;\n    var tabLength = $('.admin-tab-show').width();\n    var allTabLength = 0;\n    var oneMarginLeft = parseInt($($('#admin-tab-body-index>ul>li')[0]).css('margin-left'));\n    $('#admin-tab-body-index>ul>li').each(function(index){\n      allTabLength = allTabLength + $(this).width();\n      if(parseInt($(this).css('margin-left')) == 0 && getCurrentFlg == false){\n        currentTab = index;\n        getCurrentFlg = true;\n      }\n    });\n    if((allTabLength + oneMarginLeft)> tabLength){\n      /*$('#admin-tab-body-index>ul>li').css('margin-left',(oneMarginLeft-100)+'px')*/\n      for(var i=0;i<$('#admin-tab-body-index>ul>li').length;i++){\n        if(i == currentTab+1){\n          break;\n        }\n        if(i==currentTab){\n          addMargin = parseInt($($('#admin-tab-body-index>ul>li')[i]).css('margin-left')) - $($('#admin-tab-body-index>ul>li')[currentTab]).width() -20;\n        }else{\n          addMargin = parseInt($($('#admin-tab-body-index>ul>li')[i]).css('margin-left')) - $($('#admin-tab-body-index>ul>li')[currentTab]).width();\n        }\n        //$($('#admin-tab-body-index>ul>li')[i]).animate({'margin-left':addMargin+'px'},\"fast\");\n        $($('#admin-tab-body-index>ul>li')[i]).css('margin-left',addMargin+'px');\n      }\n    }\n  }\n  /**\n   * 右移tab标签\n   */\n  $('.admin-tab-right').on('click',function(){\n    moveToLeft();\n  });\n\n  function moveToRight(){\n//需要显示的下一个tab\n    var getCurrentFlg = false;\n    var currentTab = 0;\n    //需要添加的margin-left总数\n    var addMargin = 0;\n    var tabLength = $('.admin-tab-show').width();\n    var allTabLength = 0;\n    var oneMarginLeft = parseInt($($('#admin-tab-body-index>ul>li')[0]).css('margin-left'));\n    $('#admin-tab-body-index>ul>li').each(function(index){\n      allTabLength = allTabLength + $(this).width();\n      if(parseInt($(this).css('margin-left')) == 0 && getCurrentFlg == false){\n        currentTab = index;\n        getCurrentFlg = true;\n      }\n    });\n    if(currentTab != 0){\n      for(var i=0;i<$('#admin-tab-body-index>ul>li').length;i++){\n        if(parseInt($($('#admin-tab-body-index>ul>li')[i]).css('margin-left')) !=0){\n          if((currentTab - 1) == i ){\n            addMargin = parseInt($($('#admin-tab-body-index>ul>li')[i]).css('margin-left')) + $($('#admin-tab-body-index>ul>li')[currentTab-1]).width()+20;\n          }else{\n            addMargin = parseInt($($('#admin-tab-body-index>ul>li')[i]).css('margin-left')) + $($('#admin-tab-body-index>ul>li')[currentTab-1]).width();\n          }\n          //$($('#admin-tab-body-index>ul>li')[i]).animate({'margin-left':addMargin+'px'},\"fast\");\n          $($('#admin-tab-body-index>ul>li')[i]).css('margin-left',addMargin+'px');\n        }\n      }\n    }\n  }\n\n  $('.admin-tab-right-close-all').on('click', function () {\n    if($('.am-icon-close').length == 0){\n      return;\n    }\n    layer.confirm('是否确定删除其他TAB选项卡', {icon: 3,skin: 'layer-ext-moon', title: '提示'}, function (index) {\n      //do something\n      $('.am-icon-close').each(function(index){\n        var $item = $(this).closest('li');\n        var index = $nav.children('li').index($item);\n        $item.remove();\n        $bd.find('.am-tab-panel').eq(index).remove();\n      });\n      $tab.tabs('open', 0);\n      $tab.tabs('refresh');\n      layer.close(index);\n    });\n  });\n});\n\n/**\n * 页面执行完加载左侧列表\n */\n(function () {\n  var html = '';\n  var mainClick = \"$('#admin-tab-body-index').tabs('open', 0);\";\n  html = html + '<li><a href=\"javascript:void(0);\" iframe-uuid=\"' + TAB_JSON.list[0].listUuid + '\" onclick=\"' + mainClick + '\" class=\"admin-open-new-tab\">' +\n      '<span class=\"' + TAB_JSON.list[0].listIcon + '\"></span> ' + TAB_JSON.list[0].listName + ' ' +\n      '<span class=\"' + TAB_JSON.list[0].listRightIcon + ' am-fr am-margin-right ' + TAB_JSON.list[0].listNumberColor + '\">' +\n      '' + TAB_JSON.list[0].listNumber + '</span></a></li>';\n  for (var i = 1; i < TAB_JSON.list.length; i++) {\n    if (TAB_JSON.list[i].isHtml == true) {\n      html = html + '<li><a href=\"javascript:void(0);\" iframe-uuid=\"' + TAB_JSON.list[i].listUuid + '\" class=\"admin-open-new-tab\">' +\n          '<span class=\"' + TAB_JSON.list[i].listIcon + '\"></span> ' + TAB_JSON.list[i].listName + ' ' +\n          '<span class=\"' + TAB_JSON.list[i].listRightIcon + ' am-fr am-margin-right ' + TAB_JSON.list[i].listNumberColor + '\">' +\n          '' + TAB_JSON.list[i].listNumber + '</span></a></li>';\n    } else {\n      var subListIdName = 'collapse' + i;\n      var subListId = \"{target: '#\" + subListIdName + \"'}\";\n      html = html + '<li class=\"admin-parent\">' +\n          '<a class=\"am-cf am-collapsed\" data-am-collapse=\"' + subListId + '\"><span class=\"' + TAB_JSON.list[i].listIcon + '\">' +\n          '</span> ' + TAB_JSON.list[i].listName + ' <span class=\"' + TAB_JSON.list[i].listRightIcon + ' am-fr am-margin-right\"></span></a>';\n      if (TAB_JSON.list[i].subList.length == 0) {\n        html = html + '</li>';\n        break;\n      } else {\n        html = html + '<ul class=\"am-list admin-sidebar-sub am-collapse\" id=\"' + subListIdName + '\">';\n        for (var j = 0; j < TAB_JSON.list[i].subList.length; j++) {\n          html = html + ' <li><a href=\"javascript:void(0);\" iframe-url=\"' + TAB_JSON.list[i].subList[j].listUrl + '\" ' +\n              'iframe-name=\"' + TAB_JSON.list[i].subList[j].listName + '\" iframe-uuid=\"' + TAB_JSON.list[i].subList[j].listUuid + '\" class=\"am-cf admin-open-new-tab\">' +\n              '<span class=\"' + TAB_JSON.list[i].subList[j].listIcon + '\"></span> ' + TAB_JSON.list[i].subList[j].listName + '' +\n              '<span class=\"' + TAB_JSON.list[i].subList[j].listRightIcon + ' am-fr am-margin-right ' + TAB_JSON.list[i].subList[j].listNumberColor + '\">' +\n              '' + TAB_JSON.list[i].subList[j].listNumber + '</span>' +\n              '</a></li>'\n        }\n        html = html + '</ul> </li>';\n      }\n    }\n  }\n\n  $('#admin-list-config').html(html);\n})();\n\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/base-component/amazeui/js/area.js",
    "content": "﻿/*\n*\t全国三级城市联动 js版\n*/\nfunction Dsy(){\n\tthis.Items = {};\n}\nDsy.prototype.add = function(id,iArray){\n\tthis.Items[id] = iArray;\n}\nDsy.prototype.Exists = function(id){\n\tif(typeof(this.Items[id]) == \"undefined\") return false;\n\treturn true;\n}\n\nfunction change(v){\n\tvar str=\"0\";\n\tfor(i=0;i<v;i++){\n\t\tstr+=(\"_\"+(document.getElementById(s[i]).selectedIndex-1));\n\t};\n\tvar ss=document.getElementById(s[v]);\n\twith(ss){\n\t\tlength = 0;\n\t\toptions[0]=new Option(opt0[v],opt0[v]);\n\t\tif(v && document.getElementById(s[v-1]).selectedIndex>0 || !v){\n\t\t\tif(dsy.Exists(str)){\n\t\t\t\tar = dsy.Items[str];\n\t\t\t\tfor(i=0;i<ar.length;i++){\n\t\t\t\t\toptions[length]=new Option(ar[i],ar[i]);\n\t\t\t\t}//end for\n\t\t\t\tif(v){ options[0].selected = true; }\n\t\t\t}\n\t\t}//end if v\n\t\tif(++v<s.length){change(v);}\n\t}//End with\n}\n\nvar dsy = new Dsy();\n\ndsy.add(\"0\",[\"北京市\",\"天津市\",\"上海市\",\"重庆市\",\"河北省\",\"山西省\",\"内蒙古\",\"辽宁省\",\"吉林省\",\"黑龙江省\",\"江苏省\",\"浙江省\",\"安徽省\",\"福建省\",\"江西省\",\"山东省\",\"河南省\",\"湖北省\",\"湖南省\",\"广东省\",\"广西\",\"海南省\",\"四川省\",\"贵州省\",\"云南省\",\"西藏\",\"陕西省\",\"甘肃省\",\"青海省\",\"宁夏\",\"新疆\",\"香港\",\"澳门\",\"台湾省\"]);\ndsy.add(\"0_0_0\",[\"东城区\",\"西城区\",\"崇文区\",\"宣武区\",\"朝阳区\",\"丰台区\",\"石景山区\",\"海淀区\",\"门头沟区\",\"房山区\",\"通州区\",\"顺义区\",\"昌平区\",\"大兴区\",\"怀柔区\",\"平谷区\",\"密云县\",\"延庆县\",\"延庆镇\"]);\ndsy.add(\"0_0\",[\"北京市\"]);\ndsy.add(\"0_1_0\",[\"和平区\",\"河东区\",\"河西区\",\"南开区\",\"河北区\",\"红桥区\",\"塘沽区\",\"汉沽区\",\"大港区\",\"东丽区\",\"西青区\",\"津南区\",\"北辰区\",\"武清区\",\"宝坻区\",\"蓟县\",\"宁河县\",\"芦台镇\",\"静海县\",\"静海镇\"]);\ndsy.add(\"0_1\",[\"天津市\"]);\ndsy.add(\"0_2_0\",[\"黄浦区\",\"卢湾区\",\"徐汇区\",\"长宁区\",\"静安区\",\"普陀区\",\"闸北区\",\"虹口区\",\"杨浦区\",\"闵行区\",\"宝山区\",\"嘉定区\",\"浦东新区\",\"金山区\",\"松江区\",\"青浦区\",\"南汇区\",\"奉贤区\",\"崇明县\",\"城桥镇\"]);\ndsy.add(\"0_2\",[\"上海市\"]);\ndsy.add(\"0_3_0\",[\"渝中区\",\"大渡口区\",\"江北区\",\"沙坪坝区\",\"九龙坡区\",\"南岸区\",\"北碚区\",\"万盛区\",\"双桥区\",\"渝北区\",\"巴南区\",\"万州区\",\"涪陵区\",\"黔江区\",\"长寿区\",\"合川市\",\"永川区市\",\"江津市\",\"南川市\",\"綦江县\",\"潼南县\",\"铜梁县\",\"大足县\",\"荣昌县\",\"璧山县\",\"垫江县\",\"武隆县\",\"丰都县\",\"城口县\",\"梁平县\",\"开县\",\"巫溪县\",\"巫山县\",\"奉节县\",\"云阳县\",\"忠县\",\"石柱土家族自治县\",\"彭水苗族土家族自治县\",\"酉阳土家族苗族自治县\",\"秀山土家族苗族自治县\"]);\ndsy.add(\"0_3\",[\"重庆市\"]);\ndsy.add(\"0_4_0\",[\"长安区\",\"桥东区\",\"桥西区\",\"新华区\",\"裕华区\",\"井陉矿区\",\"辛集市\",\"藁城市\",\"晋州市\",\"新乐市\",\"鹿泉市\",\"井陉县\",\"微水镇\",\"正定县\",\"正定镇\",\"栾城县\",\"栾城镇\",\"行唐县\",\"龙州镇\",\"灵寿县\",\"灵寿镇\",\"高邑县\",\"高邑镇\",\"深泽县\",\"深泽镇\",\"赞皇县\",\"赞皇镇\",\"无极县\",\"无极镇\",\"平山县\",\"平山镇\",\"元氏县\",\"槐阳镇\",\"赵县\",\"赵州镇\"]);\ndsy.add(\"0_4_1\",[\"桥西区\",\"桥东区\",\"宣化区\",\"下花园区\",\"宣化县\",\"张家口市宣化区\",\"张北县\",\"张北镇\",\"康保县\",\"康保镇\",\"沽源县\",\"平定堡镇\",\"尚义县\",\"南壕堑镇\",\"蔚县\",\"蔚州镇\",\"阳原县\",\"西城镇\",\"怀安县\",\"柴沟堡镇\",\"万全县\",\"孔家庄镇\",\"怀来县\",\"沙城镇\",\"涿鹿县\",\"涿鹿镇\",\"赤城县\",\"赤城镇\",\"崇礼县\",\"西湾子镇\"]);\ndsy.add(\"0_4_2\",[\"双桥区\",\"双滦区\",\"鹰手营子矿区\",\"承德县\",\"下板城镇\",\"兴隆县\",\"兴隆镇\",\"平泉县\",\"平泉镇\",\"滦平县\",\"滦平镇\",\"隆化县\",\"隆化镇\",\"丰宁满族自治县\",\"大阁镇\",\"宽城满族自治县\",\"宽城镇\",\"围场满族蒙古族自治县\",\"围场镇\"]);\ndsy.add(\"0_4_3\",[\"海港区\",\"山海关区\",\"北戴河区\",\"昌黎县\",\"昌黎镇\",\"抚宁县\",\"抚宁镇\",\"卢龙县\",\"卢龙镇\",\"青龙满族自治县\",\"青龙镇\"]);\ndsy.add(\"0_4_4\",[\"路北区\",\"路南区\",\"古冶区\",\"开平区\",\"丰润区\",\"丰南区\",\"遵化市\",\"迁安市\",\"滦县\",\"滦州镇\",\"滦南县\",\"倴城镇\",\"乐亭县\",\"乐亭镇\",\"迁西县\",\"兴城镇\",\"玉田县\",\"玉田镇\",\"唐海县\",\"唐海镇\"]);\ndsy.add(\"0_4_5\",[\"安次区\",\"广阳区\",\"霸州市\",\"三河市\",\"固安县\",\"固安镇\",\"永清县\",\"永清镇\",\"香河县\",\"淑阳镇\",\"大城县\",\"平舒镇\",\"文安县\",\"文安镇\",\"大厂回族自治县\",\"大厂镇\"]);\ndsy.add(\"0_4_6\",[\"新市区\",\"北市区\",\"南市区\",\"定州市\",\"涿州市\",\"安国市\",\"高碑店市\",\"满城县\",\"满城镇\",\"清苑县\",\"清苑镇\",\"易县\",\"易州镇\",\"徐水县\",\"安肃镇\",\"涞源县\",\"涞源镇\",\"定兴县\",\"定兴镇\",\"顺平县\",\"蒲阳镇\",\"唐县\",\"仁厚镇\",\"望都县\",\"望都镇\",\"涞水县\",\"涞水镇\",\"高阳县\",\"高阳镇\",\"安新县\",\"安新镇\",\"雄县\",\"雄州镇\",\"容城县\",\"容城镇\",\"曲阳县\",\"恒州镇\",\"阜平县\",\"阜平镇\",\"博野县\",\"博陵镇\",\"蠡县\",\"蠡吾镇\"]);\ndsy.add(\"0_4_7\",[\"桃城区\",\"冀州市\",\"深州市\",\"枣强县\",\"枣强镇\",\"武邑县\",\"武邑镇\",\"武强县\",\"武强镇\",\"饶阳县\",\"饶阳镇\",\"安平县\",\"安平镇\",\"故城县\",\"郑口镇\",\"景县\",\"景州镇\",\"阜城县\",\"阜城镇\"]);\ndsy.add(\"0_4_8\",[\"运河区\",\"新华区\",\"泊头市\",\"任丘市\",\"黄骅市\",\"河间市\",\"沧县\",\"沧州市新华区\",\"青县\",\"清州镇\",\"东光县\",\"东光镇\",\"海兴县\",\"苏基镇\",\"盐山县\",\"盐山镇\",\"肃宁县\",\"肃宁镇\",\"南皮县\",\"南皮镇\",\"吴桥县\",\"桑园镇\",\"献县\",\"乐寿镇\",\"孟村回族自治县\",\"孟村镇\"]);\ndsy.add(\"0_4_9\",[\"桥东区\",\"桥西区\",\"南宫市\",\"沙河市\",\"邢台县\",\"邢台市桥东区\",\"临城县\",\"临城镇\",\"内丘县\",\"内丘镇\",\"柏乡县\",\"柏乡镇\",\"隆尧县\",\"隆尧镇\",\"任县\",\"任城镇\",\"南和县\",\"和阳镇\",\"宁晋县\",\"凤凰镇\",\"巨鹿县\",\"巨鹿镇\",\"新河县\",\"新河镇\",\"广宗县\",\"广宗镇\",\"平乡县\",\"丰州镇\",\"威县\",\"洺州镇\",\"清河县\",\"葛仙庄镇\",\"临西县\",\"临西镇\"]);\ndsy.add(\"0_4_10\",[\"丛台区\",\"邯山区\",\"复兴区\",\"峰峰矿区\",\"武安市\",\"邯郸县\",\"南堡乡东小屯村\",\"临漳县\",\"临漳镇\",\"成安县\",\"成安镇\",\"大名县\",\"大名镇\",\"涉县\",\"涉城镇\",\"磁县\",\"磁州镇\",\"肥乡县\",\"肥乡镇\",\"永年县\",\"临洺关镇\",\"邱县\",\"新马头镇\",\"鸡泽县\",\"鸡泽镇\",\"广平县\",\"广平镇\",\"馆陶县\",\"馆陶镇\",\"魏县\",\"魏城镇\",\"曲周县\",\"曲周镇\"]);\ndsy.add(\"0_4\",[\"石家庄市\",\"张家口市\",\"承德市\",\"秦皇岛市\",\"唐山市\",\"廊坊市\",\"保定市\",\"衡水市\",\"沧州市\",\"邢台市\",\"邯郸市\"]);\ndsy.add(\"0_5_0\",[\"杏花岭区\",\"小店区\",\"迎泽区\",\"尖草坪区\",\"万柏林区\",\"晋源区\",\"古交市\",\"清徐县\",\"清源镇\",\"阳曲县\",\"黄寨镇\",\"娄烦县\",\"娄烦镇\"]);\ndsy.add(\"0_5_1\",[\"朔城区\",\"平鲁区\",\"山阴县\",\"岱岳乡\",\"应县\",\"金城镇\",\"右玉县\",\"新城镇\",\"怀仁县\",\"云中镇\"]);\ndsy.add(\"0_5_2\",[\"城区\",\"矿区\",\"南郊区\",\"新荣区\",\"阳高县\",\"龙泉镇\",\"天镇县\",\"玉泉镇\",\"广灵县\",\"壶泉镇\",\"灵丘县\",\"武灵镇\",\"浑源县\",\"永安镇\",\"左云县\",\"云兴镇\",\"大同县\",\"西坪镇\"]);\ndsy.add(\"0_5_3\",[\"城区\",\"矿区\",\"郊区\",\"平定县\",\"冠山镇\",\"盂县\",\"秀水镇\"]);\ndsy.add(\"0_5_4\",[\"城区\",\"郊区\",\"潞城市\",\"长治县\",\"韩店镇\",\"襄垣县\",\"古韩镇\",\"屯留县\",\"麟绛镇\",\"平顺县\",\"青羊镇\",\"黎城县\",\"黎侯镇\",\"壶关县\",\"龙泉镇\",\"长子县\",\"丹朱镇\",\"武乡县\",\"丰州镇\",\"沁县\",\"定昌镇\",\"沁源县\",\"沁河镇\"]);\ndsy.add(\"0_5_5\",[\"城区\",\"高平市\",\"泽州县\",\"南村镇\",\"沁水县\",\"龙港镇\",\"阳城县\",\"凤城镇\",\"陵川县\",\"崇文镇\"]);\ndsy.add(\"0_5_6\",[\"忻府区\",\"原平市\",\"定襄县\",\"晋昌镇\",\"五台县\",\"台城镇\",\"代县\",\"上馆镇\",\"繁峙县\",\"繁城镇\",\"宁武县\",\"凤凰镇\",\"静乐县\",\"鹅城镇\",\"神池县\",\"龙泉镇\",\"五寨县\",\"砚城镇\",\"岢岚县\",\"岚漪镇\",\"河曲县\",\"文笔镇\",\"保德县\",\"东关镇\",\"偏关县\",\"新关镇\"]);\ndsy.add(\"0_5_7\",[\"榆次区\",\"介休市\",\"榆社县\",\"箕城镇\",\"左权县\",\"辽阳镇\",\"和顺县\",\"义兴镇\",\"昔阳县\",\"乐平镇\",\"寿阳县\",\"朝阳镇\",\"太谷县\",\"明星镇\",\"祁县\",\"昭余镇\",\"平遥县\",\"古陶镇\",\"灵石县\",\"翠峰镇\"]);\ndsy.add(\"0_5_8\",[\"尧都区\",\"侯马市\",\"霍州市\",\"曲沃县\",\"乐昌镇\",\"翼城县\",\"唐兴镇\",\"襄汾县\",\"新城镇\",\"洪洞县\",\"大槐树镇\",\"古县\",\"岳阳镇\",\"安泽县\",\"府城镇\",\"浮山县\",\"天坛镇\",\"吉县\",\"吉昌镇\",\"乡宁县\",\"昌宁镇\",\"蒲县\",\"蒲城镇\",\"大宁县\",\"昕水镇\",\"永和县\",\"芝河镇\",\"隰县\",\"龙泉镇\",\"汾西县\",\"永安镇\"]);\ndsy.add(\"0_5_9\",[\"离石区\",\"孝义市\",\"汾阳市\",\"文水县\",\"凤城镇\",\"中阳县\",\"宁乡镇\",\"兴县\",\"蔚汾镇\",\"临县\",\"临泉镇\",\"方山县\",\"圪洞镇\",\"柳林县\",\"柳林镇\",\"岚县\",\"东村镇\",\"交口县\",\"水头镇\",\"交城县\",\"天宁镇\",\"石楼县\",\"灵泉镇\"]);\ndsy.add(\"0_5_10\",[\"盐湖区\",\"永济市\",\"河津市\",\"芮城县\",\"古魏镇\",\"临猗县\",\"猗氏镇\",\"万荣县\",\"解店镇\",\"新绛县\",\"龙兴镇\",\"稷山县\",\"稷峰镇\",\"闻喜县\",\"桐城镇\",\"夏县\",\"瑶峰镇\",\"绛县\",\"古绛镇\",\"平陆县\",\"圣人涧镇\",\"垣曲县\",\"新城镇\"]);\ndsy.add(\"0_5\",[\"太原市\",\"朔州市\",\"大同市\",\"阳泉市\",\"长治市\",\"晋城市\",\"忻州市\",\"晋中市\",\"临汾市\",\"吕梁市\",\"运城市\"]);\ndsy.add(\"0_6_0\",[\"回民区\",\"新城区\",\"玉泉区\",\"赛罕区\",\"托克托县\",\"双河镇\",\"武川县\",\"可可以力更镇\",\"和林格尔县\",\"城关镇\",\"清水河县\",\"城关镇\",\"土默特左旗\",\"察素齐镇\"]);\ndsy.add(\"0_6_1\",[\"昆都仑区\",\"东河区\",\"青山区\",\"石拐区\",\"白云矿区\",\"九原区\",\"固阳县\",\"金山镇\",\"土默特右旗\",\"萨拉齐镇\",\"达尔罕茂明安联合旗\",\"百灵庙镇\"]);\ndsy.add(\"0_6_2\",[\"海勃湾区\",\"海南区\",\"乌达区\"]);\ndsy.add(\"0_6_3\",[\"红山区\",\"元宝山区\",\"松山区\",\"宁城县\",\"天义镇\",\"林西县\",\"林西镇\",\"阿鲁科尔沁旗\",\"天山镇\",\"巴林左旗\",\"林东镇\",\"巴林右旗\",\"大板镇\",\"克什克腾旗\",\"经棚镇\",\"翁牛特旗\",\"乌丹镇\",\"喀喇沁旗\",\"锦山镇\",\"敖汉旗\",\"新惠镇\"]);\ndsy.add(\"0_6_4\",[\"科尔沁区\",\"霍林郭勒市\",\"开鲁县\",\"开鲁镇\",\"库伦旗\",\"库伦镇\",\"奈曼旗\",\"大沁他拉镇\",\"扎鲁特旗\",\"鲁北镇\",\"科尔沁左翼中旗\",\"保康镇\",\"科尔沁左翼后旗\",\"甘旗卡镇\"]);\ndsy.add(\"0_6_5\",[\"海拉尔区\",\"满洲里市\",\"扎兰屯市\",\"牙克石市\",\"根河市\",\"额尔古纳市\",\"阿荣旗\",\"那吉镇\",\"新巴尔虎右旗\",\"阿拉坦额莫勒镇\",\"新巴尔虎左旗\",\"阿穆古郎镇\",\"陈巴尔虎旗\",\"巴彦库仁镇\",\"鄂伦春自治旗\",\"阿里河镇\",\"鄂温克族自治旗\",\"巴彦托海镇\",\"莫力达瓦达斡尔族自治旗\",\"尼尔基镇\"]);\ndsy.add(\"0_6_6\",[\"东胜区\",\"达拉特旗\",\"树林召镇\",\"准格尔旗\",\"薛家湾镇\",\"鄂托克前旗\",\"敖勒召其镇\",\"鄂托克旗\",\"乌兰镇\",\"杭锦旗\",\"锡尼镇\",\"乌审旗\",\"嘎鲁图镇\",\"伊金霍洛旗\",\"阿勒腾席热镇\"]);\ndsy.add(\"0_6_7\",[\"集宁区\",\"丰镇市\",\"卓资县\",\"卓资山镇\",\"化德县\",\"长顺镇\",\"商都县\",\"商都镇\",\"兴和县\",\"城关镇\",\"凉城县\",\"岱海镇\",\"察哈尔右翼前旗\",\"土贵乌拉镇\",\"察哈尔右翼中旗\",\"科布尔镇\",\"察哈尔右翼后旗\",\"白音察干镇\",\"四子王旗\",\"乌兰花镇\"]);\ndsy.add(\"0_6_8\",[\"临河区\",\"五原县\",\"隆兴昌镇\",\"磴口县\",\"巴彦高勒镇\",\"乌拉特前旗\",\"乌拉山镇\",\"乌拉特中旗\",\"海流图镇\",\"乌拉特后旗\",\"巴音宝力格镇\",\"杭锦后旗\",\"陕坝镇\"]);\ndsy.add(\"0_6_9\",[\"乌兰浩特市\",\"阿尔山市\",\"突泉县\",\"突泉镇\",\"科尔沁右翼前旗\",\"大坝沟镇\",\"科尔沁右翼中旗\",\"巴彦呼硕镇\",\"扎赉特旗\",\"音德尔镇\"]);\ndsy.add(\"0_6_10\",[\"锡林浩特市\",\"二连浩特市\",\"多伦县\",\"多伦淖尔镇\",\"阿巴嘎旗\",\"别力古台镇\",\"苏尼特左旗\",\"满都拉图镇\",\"苏尼特右旗\",\"赛汉塔拉镇\",\"东乌珠穆沁旗\",\"乌里雅斯太镇\",\"西乌珠穆沁旗\",\"巴拉嘎尔郭勒镇\",\"太仆寺旗\",\"宝昌镇\",\"镶黄旗\",\"新宝拉格镇\",\"正镶白旗\",\"明安图镇\",\"正蓝旗\",\"上都镇\"]);\ndsy.add(\"0_6_11\",[\"巴彦浩特镇\",\"阿拉善右旗\",\"额肯呼都格镇\",\"额济纳旗\",\"达来呼布镇\"]);\ndsy.add(\"0_6\",[\"呼和浩特市\",\"包头市\",\"乌海市\",\"赤峰市\",\"通辽市\",\"呼伦贝尔市\",\"鄂尔多斯市\",\"乌兰察布市\",\"巴彦淖尔市\",\"兴安盟\",\"锡林郭勒盟\",\"阿拉善盟\"]);\ndsy.add(\"0_7_0\",[\"沈河区\",\"和平区\",\"大东区\",\"皇姑区\",\"铁西区\",\"苏家屯区\",\"东陵区\",\"新城子区\",\"于洪区\",\"新民市\",\"辽中县\",\"辽中镇\",\"康平县\",\"康平镇\",\"法库县\",\"法库镇\"]);\ndsy.add(\"0_7_1\",[\"双塔区\",\"龙城区\",\"北票市\",\"凌源市\",\"朝阳县\",\"朝阳市双塔区\",\"建平县\",\"喀喇沁左翼蒙古族自治县\",\"大城子镇\"]);\ndsy.add(\"0_7_2\",[\"海州区\",\"新邱区\",\"太平区\",\"清河门区\",\"细河区\",\"彰武县\",\"彰武镇\",\"阜新蒙古族自治县\",\"阜新镇\"]);\ndsy.add(\"0_7_3\",[\"银州区\",\"清河区\",\"调兵山市\",\"开原市\",\"铁岭县\",\"铁岭市银州区\",\"西丰县\",\"西丰镇\",\"昌图县\",\"昌图镇\"]);\ndsy.add(\"0_7_4\",[\"顺城区\",\"新抚区\",\"东洲区\",\"望花区\",\"抚顺县\",\"抚顺市顺城区\",\"新宾满族自治县\",\"新宾镇\",\"清原满族自治县\",\"清原镇\"]);\ndsy.add(\"0_7_5\",[\"平山区\",\"溪湖区\",\"明山区\",\"南芬区\",\"本溪满族自治县\",\"小市镇\",\"桓仁满族自治县\",\"桓仁镇\"]);\ndsy.add(\"0_7_6\",[\"白塔区\",\"文圣区\",\"宏伟区\",\"弓长岭区\",\"太子河区\",\"灯塔市\",\"辽阳县\",\"首山镇\"]);\ndsy.add(\"0_7_7\",[\"铁东区\",\"铁西区\",\"立山区\",\"千山区\",\"海城市\",\"台安县\",\"台安镇\",\"岫岩满族自治县\",\"岫岩镇\"]);\ndsy.add(\"0_7_8\",[\"振兴区\",\"元宝区\",\"振安区\",\"凤城市\",\"东港市\",\"宽甸满族自治县\",\"宽甸镇\"]);\ndsy.add(\"0_7_9\",[\"西岗区\",\"中山区\",\"沙河口区\",\"甘井子区\",\"旅顺口区\",\"金州区\",\"瓦房店市\",\"普兰店市\",\"庄河市\",\"长海县\",\"大长山岛镇\"]);\ndsy.add(\"0_7_10\",[\"站前区\",\"西市区\",\"鲅鱼圈区\",\"老边区\",\"大石桥市\",\"盖州市\"]);\ndsy.add(\"0_7_11\",[\"兴隆台区\",\"双台子区\",\"大洼县\",\"大洼镇\",\"盘山县\",\"盘锦市双台子区\"]);\ndsy.add(\"0_7_12\",[\"太和区\",\"古塔区\",\"凌河区\",\"凌海市\",\"北宁市\",\"黑山县\",\"黑山镇\",\"义县\",\"义州镇\"]);\ndsy.add(\"0_7_13\",[\"龙港区\",\"连山区\",\"南票区\",\"兴城市\",\"绥中县\",\"绥中镇\",\"建昌县\",\"建昌镇\"]);\ndsy.add(\"0_7\",[\"沈阳市\",\"朝阳市\",\"阜新市\",\"铁岭市\",\"抚顺市\",\"本溪市\",\"辽阳市\",\"鞍山市\",\"丹东市\",\"大连市\",\"营口市\",\"盘锦市\",\"锦州市\",\"葫芦岛市\"]);\ndsy.add(\"0_8_0\",[\"朝阳区\",\"南关区\",\"宽城区\",\"二道区\",\"绿园区\",\"双阳区\",\"德惠市\",\"九台市\",\"榆树市\",\"农安县\",\"农安镇\"]);\ndsy.add(\"0_8_1\",[\"洮北区\",\"大安市\",\"洮南市\",\"镇赉县\",\"镇赉镇\",\"通榆县\",\"开通镇\"]);\ndsy.add(\"0_8_2\",[\"宁江区\",\"扶余县\",\"三岔河镇\",\"长岭县\",\"长岭镇\",\"乾安县\",\"乾安镇\",\"前郭尔罗斯蒙古族自治县\",\"前郭镇\"]);\ndsy.add(\"0_8_3\",[\"船营区\",\"龙潭区\",\"昌邑区\",\"丰满区\",\"磐石市\",\"蛟河市\",\"桦甸市\",\"舒兰市\",\"永吉县\",\"口前镇\"]);\ndsy.add(\"0_8_4\",[\"铁西区\",\"铁东区\",\"双辽市\",\"公主岭市\",\"梨树县\",\"梨树镇\",\"伊通满族自治县\",\"伊通镇\"]);\ndsy.add(\"0_8_5\",[\"龙山区\",\"西安区\",\"东丰县\",\"东丰镇\",\"东辽县\",\"白泉镇\"]);\ndsy.add(\"0_8_6\",[\"东昌区\",\"二道江区\",\"梅河口市\",\"集安市\",\"通化县\",\"快大茂镇\",\"辉南县\",\"朝阳镇\",\"柳河县\",\"柳河镇\"]);\ndsy.add(\"0_8_7\",[\"八道江区\",\"临江市\",\"江源县\",\"孙家堡子镇\",\"抚松县\",\"抚松镇\",\"靖宇县\",\"靖宇镇\",\"长白朝鲜族自治县\",\"长白镇\"]);\ndsy.add(\"0_8_8\",[\"延吉市\",\"图们市\",\"敦化市\",\"珲春市\",\"龙井市\",\"和龙市\",\"汪清县\",\"汪清镇\",\"安图县\",\"明月镇\"]);\ndsy.add(\"0_8\",[\"长春市\",\"白城市\",\"松原市\",\"吉林市\",\"四平市\",\"辽源市\",\"通化市\",\"白山市\",\"延边州\"]);\ndsy.add(\"0_9_0\",[\"松北区\",\"道里区\",\"南岗区\",\"道外区\",\"香坊区\",\"动力区\",\"平房区\",\"呼兰区\",\"双城市\",\"尚志市\",\"五常市\",\"阿城市\",\"依兰县\",\"依兰镇\",\"方正县\",\"方正镇\",\"宾县\",\"宾州镇\",\"巴彦县\",\"巴彦镇\",\"木兰县\",\"木兰镇\",\"通河县\",\"通河镇\",\"延寿县\",\"延寿镇\"]);\ndsy.add(\"0_9_1\",[\"建华区\",\"龙沙区\",\"铁锋区\",\"昂昂溪区\",\"富拉尔基区\",\"碾子山区\",\"梅里斯达斡尔族区\",\"讷河市\",\"龙江县\",\"龙江镇\",\"依安县\",\"依安镇\",\"泰来县\",\"泰来镇\",\"甘南县\",\"甘南镇\",\"富裕县\",\"富裕镇\",\"克山县\",\"克山镇\",\"克东县\",\"克东镇\",\"拜泉县\",\"拜泉镇\"]);\ndsy.add(\"0_9_2\",[\"桃山区\",\"新兴区\",\"茄子河区\",\"勃利县\",\"勃利镇\"]);\ndsy.add(\"0_9_3\",[\"爱辉区\",\"北安市\",\"五大连池市\",\"嫩江县\",\"嫩江镇\",\"逊克县\",\"边疆镇\",\"孙吴县\",\"孙吴镇\"]);\ndsy.add(\"0_9_4\",[\"萨尔图区\",\"龙凤区\",\"让胡路区\",\"大同区\",\"红岗区\",\"肇州县\",\"肇州镇\",\"肇源县\",\"肇源镇\",\"林甸县\",\"林甸镇\",\"杜尔伯特蒙古族自治县\",\"泰康镇\"]);\ndsy.add(\"0_9_5\",[\"兴山区\",\"向阳区\",\"工农区\",\"南山区\",\"兴安区\",\"东山区\",\"萝北县\",\"凤翔镇\",\"绥滨县\",\"绥滨镇\"]);\ndsy.add(\"0_9_6\",[\"伊春区\",\"南岔区\",\"友好区\",\"西林区\",\"翠峦区\",\"新青区\",\"美溪区\",\"金山屯区\",\"五营区\",\"乌马河区\",\"汤旺河区\",\"带岭区\",\"乌伊岭区\",\"红星区\",\"上甘岭区\",\"铁力市\",\"嘉荫县\",\"朝阳镇\"]);\ndsy.add(\"0_9_7\",[\"前进区\",\"永红区\",\"向阳区\",\"东风区\",\"郊区\",\"同江市\",\"富锦市\",\"桦南县\",\"桦南镇\",\"桦川县\",\"悦来镇\",\"汤原县\",\"汤原镇\",\"抚远县\",\"抚远镇\"]);\ndsy.add(\"0_9_8\",[\"尖山区\",\"岭东区\",\"四方台区\",\"宝山区\",\"集贤县\",\"福利镇\",\"友谊县\",\"友谊镇\",\"宝清县\",\"宝清镇\",\"饶河县\",\"饶河镇\"]);\ndsy.add(\"0_9_9\",[\"鸡冠区\",\"恒山区\",\"滴道区\",\"梨树区\",\"城子河区\",\"麻山区\",\"虎林市\",\"密山市\",\"鸡东县\",\"鸡东镇\"]);\ndsy.add(\"0_9_10\",[\"爱民区\",\"东安区\",\"阳明区\",\"西安区\",\"穆棱市\",\"绥芬河市\",\"海林市\",\"宁安市\",\"东宁县\",\"东宁镇\",\"林口县\",\"林口镇\"]);\ndsy.add(\"0_9_11\",[\"北林区\",\"安达市\",\"肇东市\",\"海伦市\",\"望奎县\",\"望奎镇\",\"兰西县\",\"兰西镇\",\"青冈县\",\"青冈镇\",\"庆安县\",\"庆安镇\",\"明水县\",\"明水镇\",\"绥棱县\",\"绥棱镇\"]);\ndsy.add(\"0_9_12\",[\"呼玛县\",\"呼玛镇\",\"塔河县\",\"塔河镇\",\"漠河县\",\"西林吉镇\"]);\ndsy.add(\"0_9\",[\"哈尔滨市\",\"齐齐哈尔市\",\"七台河市\",\"黑河市\",\"大庆市\",\"鹤岗市\",\"伊春市\",\"佳木斯市\",\"双鸭山市\",\"鸡西市\",\"牡丹江市\",\"绥化市\",\"大兴安岭地区\"]);\ndsy.add(\"0_10_0\",[\"玄武区\",\"白下区\",\"秦淮区\",\"建邺区\",\"鼓楼区\",\"下关区\",\"浦口区\",\"六合区\",\"栖霞区\",\"雨花台区\",\"江宁区\",\"溧水县\",\"永阳镇\",\"高淳县\",\"淳溪镇\"]);\ndsy.add(\"0_10_1\",[\"云龙区\",\"鼓楼区\",\"九里区\",\"贾汪区\",\"泉山区\",\"邳州市\",\"新沂市\",\"铜山县\",\"铜山镇\",\"睢宁县\",\"睢城镇\",\"沛县\",\"沛城镇\",\"丰县\",\"凤城镇\"]);\ndsy.add(\"0_10_2\",[\"新浦区\",\"连云区\",\"海州区\",\"赣榆县\",\"青口镇\",\"灌云县\",\"伊山镇\",\"东海县\",\"牛山镇\",\"灌南县\",\"新安镇\"]);\ndsy.add(\"0_10_3\",[\"宿城区\",\"宿豫区\",\"沭阳县\",\"沭城镇\",\"泗阳县\",\"众兴镇\",\"泗洪县\",\"青阳镇\"]);\ndsy.add(\"0_10_4\",[\"清河区\",\"清浦区\",\"楚州区\",\"淮阴区\",\"金湖县\",\"黎城镇\",\"盱眙县\",\"盱城镇\",\"洪泽县\",\"高良涧镇\",\"涟水县\",\"涟城镇\"]);\ndsy.add(\"0_10_5\",[\"亭湖区\",\"盐都区\",\"东台市\",\"大丰市\",\"射阳县\",\"合德镇\",\"阜宁县\",\"阜城镇\",\"滨海县\",\"东坎镇\",\"响水县\",\"响水镇\",\"建湖县\",\"近湖镇\"]);\ndsy.add(\"0_10_6\",[\"维扬区\",\"广陵区\",\"邗江区\",\"仪征市\",\"江都市\",\"高邮市\",\"宝应县\",\"安宜镇\"]);\ndsy.add(\"0_10_7\",[\"海陵区\",\"高港区\",\"靖江市\",\"泰兴市\",\"姜堰市\",\"兴化市\"]);\ndsy.add(\"0_10_8\",[\"崇川区\",\"港闸区\",\"海门市\",\"启东市\",\"通州市\",\"如皋市\",\"如东县\",\"掘港镇\",\"海安县\",\"海安镇\"]);\ndsy.add(\"0_10_9\",[\"京口区\",\"润州区\",\"丹徒区\",\"扬中市\",\"丹阳市\",\"句容市\"]);\ndsy.add(\"0_10_10\",[\"钟楼区\",\"天宁区\",\"戚墅堰区\",\"新北区\",\"武进区\",\"金坛市\",\"溧阳市\"]);\ndsy.add(\"0_10_11\",[\"崇安区\",\"南长区\",\"北塘区\",\"滨湖区\",\"惠山区\",\"锡山区\",\"江阴市\",\"宜兴市\"]);\ndsy.add(\"0_10_12\",[\"金阊区\",\"沧浪区\",\"平江区\",\"虎丘区\",\"吴中区\",\"相城区\",\"吴江市\",\"昆山市\",\"太仓市\",\"常熟市\",\"张家港市\"]);\ndsy.add(\"0_10\",[\"南京市\",\"徐州市\",\"连云港市\",\"宿迁市\",\"淮安市\",\"盐城市\",\"扬州市\",\"泰州市\",\"南通市\",\"镇江市\",\"常州市\",\"无锡市\",\"苏州市\"]);\ndsy.add(\"0_11_0\",[\"拱墅区\",\"上城区\",\"下城区\",\"江干区\",\"西湖区\",\"滨江区\",\"余杭区\",\"萧山区\",\"临安市\",\"富阳市\",\"建德市\",\"桐庐县\",\"淳安县\",\"千岛湖镇\"]);\ndsy.add(\"0_11_1\",[\"吴兴区\",\"南浔区\",\"长兴县\",\"雉城镇\",\"德清县\",\"武康镇\",\"安吉县\",\"递铺镇\"]);\ndsy.add(\"0_11_2\",[\"南湖区\",\"秀洲区\",\"平湖市\",\"海宁市\",\"桐乡市\",\"嘉善县\",\"魏塘镇\",\"海盐县\",\"武原镇\"]);\ndsy.add(\"0_11_3\",[\"定海区\",\"普陀区\",\"岱山县\",\"高亭镇\",\"嵊泗县\",\"菜园镇\"]);\ndsy.add(\"0_11_4\",[\"海曙区\",\"江东区\",\"江北区\",\"北仑区\",\"镇海区\",\"鄞州区\",\"慈溪市\",\"余姚市\",\"奉化市\",\"宁海县\",\"象山县\"]);\ndsy.add(\"0_11_5\",[\"越城区\",\"诸暨市\",\"上虞市\",\"嵊州市\",\"绍兴县\",\"新昌县\",\"城关镇\"]);\ndsy.add(\"0_11_6\",[\"柯城区\",\"衢江区\",\"江山市\",\"常山县\",\"天马镇\",\"开化县\",\"城关镇\",\"龙游县\"]);\ndsy.add(\"0_11_7\",[\"婺城区\",\"金东区\",\"兰溪市\",\"永康市\",\"义乌市\",\"东阳市\",\"武义县\",\"浦江县\",\"磐安县\",\"安文镇\"]);\ndsy.add(\"0_11_8\",[\"椒江区\",\"黄岩区\",\"路桥区\",\"临海市\",\"温岭市\",\"三门县\",\"海游镇\",\"天台县\",\"仙居县\",\"玉环县\",\"珠港镇\"]);\ndsy.add(\"0_11_9\",[\"鹿城区\",\"龙湾区\",\"瓯海区\",\"瑞安市\",\"乐清市\",\"永嘉县\",\"上塘镇\",\"文成县\",\"大峃镇\",\"平阳县\",\"昆阳镇\",\"泰顺县\",\"罗阳镇\",\"洞头县\",\"北岙镇\",\"苍南县\",\"灵溪镇\"]);\ndsy.add(\"0_11_10\",[\"莲都区\",\"龙泉市\",\"缙云县\",\"五云镇\",\"青田县\",\"鹤城镇\",\"云和县\",\"云和镇\",\"遂昌县\",\"妙高镇\",\"松阳县\",\"西屏镇\",\"庆元县\",\"松源镇\",\"景宁畲族自治县\",\"鹤溪镇\"]);\ndsy.add(\"0_11\",[\"杭州市\",\"湖州市\",\"嘉兴市\",\"舟山市\",\"宁波市\",\"绍兴市\",\"衢州市\",\"金华市\",\"台州市\",\"温州市\",\"丽水市\"]);\ndsy.add(\"0_12_0\",[\"庐阳区\",\"瑶海区\",\"蜀山区\",\"包河区\",\"长丰县\",\"水湖镇\",\"肥东县\",\"店埠镇\",\"肥西县\",\"上派镇\"]);\ndsy.add(\"0_12_1\",[\"埇桥区\",\"砀山县\",\"砀城镇\",\"萧县\",\"龙城镇\",\"灵璧县\",\"灵城镇\",\"泗县\",\"泗城镇\"]);\ndsy.add(\"0_12_2\",[\"相山区\",\"杜集区\",\"烈山区\",\"濉溪县\",\"濉溪镇\"]);\ndsy.add(\"0_12_3\",[\"谯城区\",\"涡阳县\",\"城关镇\",\"蒙城县\",\"城关镇\",\"利辛县\",\"城关镇\"]);\ndsy.add(\"0_12_4\",[\"颍州区\",\"颍东区\",\"颍泉区\",\"界首市\",\"临泉县\",\"城关镇\",\"太和县\",\"城关镇\",\"阜南县\",\"城关镇\",\"颍上县\",\"慎城镇\"]);\ndsy.add(\"0_12_5\",[\"蚌山区\",\"龙子湖区\",\"禹会区\",\"淮上区\",\"怀远县\",\"城关镇\",\"五河县\",\"城关镇\",\"固镇县\",\"城关镇\"]);\ndsy.add(\"0_12_6\",[\"田家庵区\",\"大通区\",\"谢家集区\",\"八公山区\",\"潘集区\",\"凤台县\",\"城关镇\"]);\ndsy.add(\"0_12_7\",[\"琅区\",\"南谯区\",\"明光市\",\"天长市\",\"来安县\",\"新安镇\",\"全椒县\",\"襄河镇\",\"定远县\",\"定城镇\",\"凤阳县\",\"府城镇\"]);\ndsy.add(\"0_12_8\",[\"雨山区\",\"花山区\",\"金家庄区\",\"当涂县\",\"姑孰镇\"]);\ndsy.add(\"0_12_9\",[\"镜湖区\",\"弋江区\",\"三山区\",\"鸠江区\",\"芜湖县\",\"湾镇\",\"繁昌县\",\"繁阳镇\",\"南陵县\",\"籍山镇\"]);\ndsy.add(\"0_12_10\",[\"铜官山区\",\"狮子山区\",\"郊区\",\"铜陵县\",\"五松镇\"]);\ndsy.add(\"0_12_11\",[\"迎江区\",\"大观区\",\"宜秀区\",\"桐城市\",\"怀宁县\",\"高河镇\",\"枞阳县\",\"枞阳镇\",\"潜山县\",\"梅城镇\",\"太湖县\",\"晋熙镇\",\"宿松县\",\"孚玉镇\",\"望江县\",\"雷阳镇\",\"岳西县\",\"天堂镇\"]);\ndsy.add(\"0_12_12\",[\"屯溪区\",\"黄山区\",\"徽州区\",\"歙县\",\"徽城镇\",\"休宁县\",\"海阳镇\",\"黟县\",\"碧阳镇\",\"祁门县\",\"祁山镇\"]);\ndsy.add(\"0_12_13\",[\"金安区\",\"裕安区\",\"寿县\",\"寿春镇\",\"霍邱县\",\"城关镇\",\"舒城县\",\"城关镇\",\"金寨县\",\"梅山镇\",\"霍山县\",\"衡山镇\"]);\ndsy.add(\"0_12_14\",[\"居巢区\",\"庐江县\",\"庐城镇\",\"无为县\",\"无城镇\",\"含山县\",\"环峰镇\",\"和县\",\"历阳镇\"]);\ndsy.add(\"0_12_15\",[\"贵池区\",\"东至县\",\"尧渡镇\",\"石台县\",\"七里镇\",\"青阳县\",\"蓉城镇\"]);\ndsy.add(\"0_12_16\",[\"宣州区\",\"宁国市\",\"郎溪县\",\"建平镇\",\"广德县\",\"桃州镇\",\"泾县\",\"泾川镇\",\"旌德县\",\"旌阳镇\",\"绩溪县\",\"华阳镇\"]);\ndsy.add(\"0_12\",[\"合肥市\",\"宿州市\",\"淮北市\",\"亳州市\",\"阜阳市\",\"蚌埠市\",\"淮南市\",\"滁州市\",\"马鞍山市\",\"芜湖市\",\"铜陵市\",\"安庆市\",\"黄山市\",\"六安市\",\"巢湖市\",\"池州市\",\"宣城市\"]);\ndsy.add(\"0_13_0\",[\"鼓楼区\",\"台江区\",\"仓山区\",\"马尾区\",\"晋安区\",\"福清市\",\"长乐市\",\"闽侯县\",\"连江县\",\"凤城镇\",\"罗源县\",\"凤山镇\",\"闽清县\",\"梅城镇\",\"永泰县\",\"樟城镇\",\"平潭县\",\"潭城镇\"]);\ndsy.add(\"0_13_1\",[\"延平区\",\"邵武市\",\"武夷山市\",\"建瓯市\",\"建阳市\",\"顺昌县\",\"浦城县\",\"光泽县\",\"杭川镇\",\"松溪县\",\"松源镇\",\"政和县\",\"熊山镇\"]);\ndsy.add(\"0_13_2\",[\"城厢区\",\"涵江区\",\"荔城区\",\"秀屿区\",\"仙游县\"]);\ndsy.add(\"0_13_3\",[\"梅列区\",\"三元区\",\"永安市\",\"明溪县\",\"雪峰镇\",\"清流县\",\"龙津镇\",\"宁化县\",\"翠江镇\",\"大田县\",\"均溪镇\",\"尤溪县\",\"城关镇\",\"沙县\",\"将乐县\",\"古镛镇\",\"泰宁县\",\"杉城镇\",\"建宁县\",\"濉城镇\"]);\ndsy.add(\"0_13_4\",[\"鲤城区\",\"丰泽区\",\"洛江区\",\"泉港区\",\"石狮市\",\"晋江市\",\"南安市\",\"惠安县\",\"螺城镇\",\"安溪县\",\"凤城镇\",\"永春县\",\"桃城镇\",\"德化县\",\"浔中镇\",\"金门县\",\"☆\"]);\ndsy.add(\"0_13_5\",[\"思明区\",\"海沧区\",\"湖里区\",\"集美区\",\"同安区\",\"翔安区\"]);\ndsy.add(\"0_13_6\",[\"芗城区\",\"龙文区\",\"龙海市\",\"云霄县\",\"云陵镇\",\"漳浦县\",\"绥安镇\",\"诏安县\",\"南诏镇\",\"长泰县\",\"武安镇\",\"东山县\",\"西埔镇\",\"南靖县\",\"山城镇\",\"平和县\",\"小溪镇\",\"华安县\",\"华丰镇\"]);\ndsy.add(\"0_13_7\",[\"新罗区\",\"漳平市\",\"长汀县\",\"汀州镇\",\"永定县\",\"凤城镇\",\"上杭县\",\"临江镇\",\"武平县\",\"平川镇\",\"连城县\",\"莲峰镇\"]);\ndsy.add(\"0_13_8\",[\"蕉城区\",\"福安市\",\"福鼎市\",\"寿宁县\",\"鳌阳镇\",\"霞浦县\",\"柘荣县\",\"双城镇\",\"屏南县\",\"古峰镇\",\"古田县\",\"周宁县\",\"狮城镇\"]);\ndsy.add(\"0_13\",[\"福州市\",\"南平市\",\"莆田市\",\"三明市\",\"泉州市\",\"厦门市\",\"漳州市\",\"龙岩市\",\"宁德市\"]);\ndsy.add(\"0_14_0\",[\"东湖区\",\"西湖区\",\"青云谱区\",\"湾里区\",\"青山湖区\",\"南昌县\",\"莲塘镇\",\"新建县\",\"长堎镇\",\"安义县\",\"龙津镇\",\"进贤县\",\"民和镇\"]);\ndsy.add(\"0_14_1\",[\"浔阳区\",\"庐山区\",\"瑞昌市\",\"九江县\",\"沙河街镇\",\"武宁县\",\"新宁镇\",\"修水县\",\"义宁镇\",\"永修县\",\"涂埠镇\",\"德安县\",\"蒲亭镇\",\"星子县\",\"南康镇\",\"都昌县\",\"都昌镇\",\"湖口县\",\"双钟镇\",\"彭泽县\",\"龙城镇\"]);\ndsy.add(\"0_14_2\",[\"珠山区\",\"昌江区\",\"乐平市\",\"浮梁县\",\"浮梁镇\"]);\ndsy.add(\"0_14_3\",[\"月湖区\",\"贵溪市\",\"余江县\",\"邓埠镇\"]);\ndsy.add(\"0_14_4\",[\"渝水区\",\"分宜县\",\"分宜镇\"]);\ndsy.add(\"0_14_5\",[\"安源区\",\"湘东区\",\"莲花县\",\"琴亭镇\",\"上栗县\",\"上栗镇\",\"芦溪县\",\"芦溪镇\"]);\ndsy.add(\"0_14_6\",[\"章贡区\",\"瑞金市\",\"南康市\",\"赣县\",\"梅林镇\",\"信丰县\",\"嘉定镇\",\"大余县\",\"南安镇\",\"上犹县\",\"东山镇\",\"崇义县\",\"横水镇\",\"安远县\",\"欣山镇\",\"龙南县\",\"龙南镇\",\"定南县\",\"历市镇\",\"全南县\",\"城厢镇\",\"宁都县\",\"梅江镇\",\"于都县\",\"贡江镇\",\"兴国县\",\"潋江镇\",\"会昌县\",\"文武坝镇\",\"寻乌县\",\"长宁镇\",\"石城县\",\"琴江镇\"]);\ndsy.add(\"0_14_7\",[\"信州区\",\"德兴市\",\"上饶县\",\"旭日镇\",\"广丰县\",\"永丰镇\",\"玉山县\",\"冰溪镇\",\"铅山县\",\"河口镇\",\"横峰县\",\"岑阳镇\",\"弋阳县\",\"弋江镇\",\"余干县\",\"玉亭镇\",\"鄱阳县\",\"鄱阳镇\",\"万年县\",\"陈营镇\",\"婺源县\",\"紫阳镇\"]);\ndsy.add(\"0_14_8\",[\"临川区\",\"南城县\",\"建昌镇\",\"黎川县\",\"日峰镇\",\"南丰县\",\"琴城镇\",\"崇仁县\",\"巴山镇\",\"乐安县\",\"鳌溪镇\",\"宜黄县\",\"凤冈镇\",\"金溪县\",\"秀谷镇\",\"资溪县\",\"鹤城镇\",\"东乡县\",\"孝岗镇\",\"广昌县\",\"旴江镇\"]);\ndsy.add(\"0_14_9\",[\"袁州区\",\"丰城市\",\"樟树市\",\"高安市\",\"奉新县\",\"冯川镇\",\"万载县\",\"上高县\",\"宜丰县\",\"新昌镇\",\"靖安县\",\"双溪镇\",\"铜鼓县\",\"永宁镇\"]);\ndsy.add(\"0_14_10\",[\"吉州区\",\"青原区\",\"井冈山市\",\"厦坪镇\",\"吉安县\",\"敦厚镇\",\"吉水县\",\"文峰镇\",\"峡江县\",\"水边镇\",\"新干县\",\"金川镇\",\"永丰县\",\"恩江镇\",\"泰和县\",\"澄江镇\",\"遂川县\",\"泉江镇\",\"万安县\",\"芙蓉镇\",\"安福县\",\"平都镇\",\"永新县\",\"禾川镇\"]);\ndsy.add(\"0_14\",[\"南昌市\",\"九江市\",\"景德镇市\",\"鹰潭市\",\"新余市\",\"萍乡市\",\"赣州市\",\"上饶市\",\"抚州市\",\"宜春市\",\"吉安市\"]);\ndsy.add(\"0_15_0\",[\"市中区\",\"历下区\",\"槐荫区\",\"天桥区\",\"历城区\",\"长清区\",\"章丘市\",\"平阴县\",\"平阴镇\",\"济阳县\",\"济阳镇\",\"商河县\"]);\ndsy.add(\"0_15_1\",[\"市南区\",\"市北区\",\"四方区\",\"黄岛区\",\"崂山区\",\"城阳区\",\"李沧区\",\"胶州市\",\"即墨市\",\"平度市\",\"胶南市\",\"莱西市\"]);\ndsy.add(\"0_15_2\",[\"东昌府区\",\"临清市\",\"阳谷县\",\"莘县\",\"茌平县\",\"东阿县\",\"冠县\",\"冠城镇\",\"高唐县\"]);\ndsy.add(\"0_15_3\",[\"德城区\",\"乐陵市\",\"禹城市\",\"陵县\",\"陵城镇\",\"平原县\",\"夏津县\",\"夏津镇\",\"武城县\",\"武城镇\",\"齐河县\",\"晏城镇\",\"临邑县\",\"宁津县\",\"宁津镇\",\"庆云县\",\"庆云镇\"]);\ndsy.add(\"0_15_4\",[\"东营区\",\"河口区\",\"垦利县\",\"垦利镇\",\"利津县\",\"利津镇\",\"广饶县\",\"广饶镇\"]);\ndsy.add(\"0_15_5\",[\"张店区\",\"淄川区\",\"博山区\",\"临淄区\",\"周村区\",\"桓台县\",\"索镇\",\"高青县\",\"田镇\",\"沂源县\",\"南麻镇\"]);\ndsy.add(\"0_15_6\",[\"潍城区\",\"寒亭区\",\"坊子区\",\"奎文区\",\"安丘市\",\"昌邑市\",\"高密市\",\"青州市\",\"诸城市\",\"寿光市\",\"临朐县\",\"昌乐县\"]);\ndsy.add(\"0_15_7\",[\"莱山区\",\"芝罘区\",\"福山区\",\"牟平区\",\"栖霞市\",\"海阳市\",\"龙口市\",\"莱阳市\",\"莱州市\",\"蓬莱市\",\"招远市\",\"长岛县\",\"南长山镇\"]);\ndsy.add(\"0_15_8\",[\"环翠区\",\"荣成市\",\"乳山市\",\"文登市\"]);\ndsy.add(\"0_15_9\",[\"东港区\",\"岚山区\",\"五莲县\",\"洪凝镇\",\"莒县\",\"城阳镇\"]);\ndsy.add(\"0_15_10\",[\"兰山区\",\"罗庄区\",\"河东区\",\"郯城县\",\"郯城镇\",\"苍山县\",\"卞庄镇\",\"莒南县\",\"十字路镇\",\"沂水县\",\"沂水镇\",\"蒙阴县\",\"蒙阴镇\",\"平邑县\",\"平邑镇\",\"费县\",\"费城镇\",\"沂南县\",\"界湖镇\",\"临沭县\",\"临沭镇\"]);\ndsy.add(\"0_15_11\",[\"薛城区\",\"市中区\",\"峄城区\",\"台儿庄区\",\"山亭区\",\"滕州市\"]);\ndsy.add(\"0_15_12\",[\"市中区\",\"任城区\",\"曲阜市\",\"兖州市\",\"邹城市\",\"微山县\",\"鱼台县\",\"谷亭镇\",\"金乡县\",\"金乡镇\",\"嘉祥县\",\"嘉祥镇\",\"汶上县\",\"汶上镇\",\"泗水县\",\"梁山县\",\"梁山镇\"]);\ndsy.add(\"0_15_13\",[\"泰山区\",\"岱岳区\",\"新泰市\",\"肥城市\",\"宁阳县\",\"宁阳镇\",\"东平县\",\"东平镇\"]);\ndsy.add(\"0_15_14\",[\"莱城区\",\"钢城区\"]);\ndsy.add(\"0_15_15\",[\"滨城区\",\"惠民县\",\"惠民镇\",\"阳信县\",\"阳信镇\",\"无棣县\",\"无棣镇\",\"沾化县\",\"富国镇\",\"博兴县\",\"博兴镇\",\"邹平县\"]);\ndsy.add(\"0_15_16\",[\"牡丹区\",\"曹县\",\"曹城镇\",\"定陶县\",\"定陶镇\",\"成武县\",\"成武镇\",\"单县\",\"单城镇\",\"巨野县\",\"巨野镇\",\"郓城县\",\"郓城镇\",\"鄄城县\",\"鄄城镇\",\"东明县\",\"城关镇\"]);\ndsy.add(\"0_15\",[\"济南市\",\"青岛市\",\"聊城市\",\"德州市\",\"东营市\",\"淄博市\",\"潍坊市\",\"烟台市\",\"威海市\",\"日照市\",\"临沂市\",\"枣庄市\",\"济宁市\",\"泰安市\",\"莱芜市\",\"滨州市\",\"菏泽市\"]);\ndsy.add(\"0_16_0\",[\"中原区\",\"二七区\",\"管城回族区\",\"金水区\",\"上街区\",\"惠济区\",\"新郑市\",\"登封市\",\"新密市\",\"巩义市\",\"荥阳市\",\"中牟县\",\"城关镇\"]);\ndsy.add(\"0_16_1\",[\"鼓楼区\",\"龙亭区\",\"顺河回族区\",\"禹王台区\",\"金明区\",\"杞县\",\"城关镇\",\"通许县\",\"城关镇\",\"尉氏县\",\"城关镇\",\"开封县\",\"城关镇\",\"兰考县\",\"城关镇\"]);\ndsy.add(\"0_16_2\",[\"湖滨区\",\"义马市\",\"灵宝市\",\"渑池县\",\"城关镇\",\"陕县\",\"大营镇\",\"卢氏县\",\"城关镇\"]);\ndsy.add(\"0_16_3\",[\"西工区\",\"老城区\",\"瀍河回族区\",\"涧西区\",\"吉利区\",\"洛龙区\",\"偃师市\",\"孟津县\",\"城关镇\",\"新安县\",\"城关镇\",\"栾川县\",\"城关镇\",\"嵩县\",\"城关镇\",\"汝阳县\",\"城关镇\",\"宜阳县\",\"城关镇\",\"洛宁县\",\"城关镇\",\"伊川县\",\"城关镇\"]);\ndsy.add(\"0_16_4\",[\"解放区\",\"山阳区\",\"中站区\",\"马村区\",\"孟州市\",\"沁阳市\",\"修武县\",\"城关镇\",\"博爱县\",\"清化镇\",\"武陟县\",\"木城镇\",\"温县\",\"温泉镇\"]);\ndsy.add(\"0_16_5\",[\"卫滨区\",\"红旗区\",\"凤泉区\",\"牧野区\",\"卫辉市\",\"辉县市\",\"新乡县\",\"新乡市红旗区\",\"获嘉县\",\"城关镇\",\"原阳县\",\"城关镇\",\"延津县\",\"城关镇\",\"封丘县\",\"城关镇\",\"长垣县\",\"城关镇\"]);\ndsy.add(\"0_16_6\",[\"淇滨区\",\"山城区\",\"鹤山区\",\"浚县\",\"城关镇\",\"淇县\",\"朝歌镇\"]);\ndsy.add(\"0_16_7\",[\"北关区\",\"文峰区\",\"殷都区\",\"龙安区\",\"林州市\",\"安阳县\",\"安阳市北关区\",\"汤阴县\",\"城关镇\",\"滑县\",\"道口镇\",\"内黄县\",\"城关镇\"]);\ndsy.add(\"0_16_8\",[\"华龙区\",\"清丰县\",\"城关镇\",\"南乐县\",\"城关镇\",\"范县\",\"城关镇\",\"台前县\",\"城关镇\",\"濮阳县\",\"城关镇\"]);\ndsy.add(\"0_16_9\",[\"梁园区\",\"睢阳区\",\"永城市\",\"虞城县\",\"城关镇\",\"民权县\",\"城关镇\",\"宁陵县\",\"城关镇\",\"睢县\",\"城关镇\",\"夏邑县\",\"城关镇\",\"柘城县\",\"城关镇\"]);\ndsy.add(\"0_16_10\",[\"魏都区\",\"禹州市\",\"长葛市\",\"许昌县\",\"许昌市魏都区\",\"鄢陵县\",\"安陵镇\",\"襄城县\",\"城关镇\"]);\ndsy.add(\"0_16_11\",[\"源汇区\",\"郾城区\",\"召陵区\",\"舞阳县\",\"舞泉镇\",\"临颍县\",\"城关镇\"]);\ndsy.add(\"0_16_12\",[\"新华区\",\"卫东区\",\"湛河区\",\"石龙区\",\"舞钢市\",\"汝州市\",\"宝丰县\",\"城关镇\",\"叶县\",\"昆阳镇\",\"鲁山县\",\"鲁阳镇\",\"郏县\",\"城关镇\"]);\ndsy.add(\"0_16_13\",[\"卧龙区\",\"宛城区\",\"邓州市\",\"南召县\",\"城关镇\",\"方城县\",\"城关镇\",\"西峡县\",\"镇平县\",\"城关镇\",\"内乡县\",\"城关镇\",\"淅川县\",\"社旗县\",\"赊店镇\",\"唐河县\",\"新野县\",\"城关镇\",\"桐柏县\",\"城关镇\"]);\ndsy.add(\"0_16_14\",[\"河区\",\"平桥区\",\"息县\",\"城关镇\",\"淮滨县\",\"城关镇\",\"潢川县\",\"光山县\",\"固始县\",\"城关镇\",\"商城县\",\"城关镇\",\"罗山县\",\"城关镇\",\"新县\",\"新集镇\"]);\ndsy.add(\"0_16_15\",[\"川汇区\",\"项城市\",\"扶沟县\",\"城关镇\",\"西华县\",\"城关镇\",\"商水县\",\"城关镇\",\"太康县\",\"城关镇\",\"鹿邑县\",\"城关镇\",\"郸城县\",\"城关镇\",\"淮阳县\",\"城关镇\",\"沈丘县\",\"槐店镇\"]);\ndsy.add(\"0_16_16\",[\"驿城区\",\"确山县\",\"盘龙镇\",\"泌阳县\",\"泌水镇\",\"遂平县\",\"灈阳镇\",\"西平县\",\"上蔡县\",\"蔡都镇\",\"汝南县\",\"汝宁镇\",\"平舆县\",\"古槐镇\",\"新蔡县\",\"古吕镇\",\"正阳县\",\"真阳镇\"]);\ndsy.add(\"0_16\",[\"郑州市\",\"开封市\",\"三门峡市\",\"洛阳市\",\"焦作市\",\"新乡市\",\"鹤壁市\",\"安阳市\",\"濮阳市\",\"商丘市\",\"许昌市\",\"漯河市\",\"平顶山市\",\"南阳市\",\"信阳市\",\"周口市\",\"驻马店市\",\"济源市\"]);\ndsy.add(\"0_17_0\",[\"江岸区\",\"江汉区\",\"硚口区\",\"汉阳区\",\"武昌区\",\"青山区\",\"洪山区\",\"东西湖区\",\"汉南区\",\"蔡甸区\",\"江夏区\",\"黄陂区\",\"新洲区\"]);\ndsy.add(\"0_17_1\",[\"张湾区\",\"茅箭区\",\"丹江口市\",\"郧县\",\"城关镇\",\"竹山县\",\"城关镇\",\"房县\",\"城关镇\",\"郧西县\",\"城关镇\",\"竹溪县\",\"城关镇\"]);\ndsy.add(\"0_17_2\",[\"襄城区\",\"樊城区\",\"襄阳区\",\"老河口市\",\"枣阳市\",\"宜城市\",\"南漳县\",\"城关镇\",\"谷城县\",\"城关镇\",\"保康县\",\"城关镇\"]);\ndsy.add(\"0_17_3\",[\"东宝区\",\"掇刀区\",\"钟祥市\",\"沙洋县\",\"沙洋镇\",\"京山县\",\"新市镇\"]);\ndsy.add(\"0_17_4\",[\"孝南区\",\"应城市\",\"安陆市\",\"汉川市\",\"孝昌县\",\"花园镇\",\"大悟县\",\"城关镇\",\"云梦县\",\"城关镇\"]);\ndsy.add(\"0_17_5\",[\"黄州区\",\"麻城市\",\"武穴市\",\"红安县\",\"城关镇\",\"罗田县\",\"凤山镇\",\"英山县\",\"温泉镇\",\"浠水县\",\"清泉镇\",\"蕲春县\",\"漕河镇\",\"黄梅县\",\"黄梅镇\",\"团风县\",\"团风镇\"]);\ndsy.add(\"0_17_6\",[\"鄂城区\",\"梁子湖区\",\"华容区\"]);\ndsy.add(\"0_17_7\",[\"黄石港区\",\"西塞山区\",\"下陆区\",\"铁山区\",\"大冶市\",\"阳新县\",\"兴国镇\"]);\ndsy.add(\"0_17_8\",[\"咸安区\",\"赤壁市\",\"嘉鱼县\",\"鱼岳镇\",\"通城县\",\"隽水镇\",\"崇阳县\",\"天城镇\",\"通山县\",\"通羊镇\"]);\ndsy.add(\"0_17_9\",[\"沙市区\",\"荆州区\",\"石首市\",\"洪湖市\",\"松滋市\",\"江陵县\",\"郝穴镇\",\"公安县\",\"斗湖堤镇\",\"监利县\",\"容城镇\"]);\ndsy.add(\"0_17_10\",[\"西陵区\",\"伍家岗区\",\"点军区\",\"猇亭区\",\"夷陵区\",\"枝江市\",\"宜都市\",\"当阳市\",\"远安县\",\"鸣凤镇\",\"兴山县\",\"古夫镇\",\"秭归县\",\"茅坪镇\",\"长阳土家族自治县\",\"龙舟坪镇\",\"五峰土家族自治县\",\"五峰镇\"]);\ndsy.add(\"0_17_11\",[\"曾都区\",\"广水市\"]);\ndsy.add(\"0_17_12\",[\"仙桃市\",\"天门市\",\"潜江市\",\"神农架林区\",\"松柏镇\"]);\ndsy.add(\"0_17_13\",[\"恩施市\",\"利川市\",\"建始县\",\"业州镇\",\"巴东县\",\"信陵镇\",\"宣恩县\",\"珠山镇\",\"咸丰县\",\"高乐山镇\",\"来凤县\",\"翔凤镇\",\"鹤峰县\",\"容美镇\"]);\ndsy.add(\"0_17\",[\"武汉市\",\"十堰市\",\"襄樊市\",\"荆门市\",\"孝感市\",\"黄冈市\",\"鄂州市\",\"黄石市\",\"咸宁市\",\"荆州市\",\"宜昌市\",\"随州市\",\"省直辖县级行政单位\",\"恩施州\"]);\ndsy.add(\"0_18_0\",[\"长沙市\",\"岳麓区\",\"芙蓉区\",\"天心区\",\"开福区\",\"雨花区\",\"浏阳市\",\"长沙县\",\"星沙镇\",\"望城县\",\"高塘岭镇\",\"宁乡县\",\"玉潭镇\"]);\ndsy.add(\"0_18_1\",[\"永定区\",\"武陵源区\",\"慈利县\",\"零阳镇\",\"桑植县\",\"澧源镇\"]);\ndsy.add(\"0_18_2\",[\"武陵区\",\"鼎城区\",\"津市市\",\"安乡县\",\"城关镇\",\"汉寿县\",\"龙阳镇\",\"澧县\",\"澧阳镇\",\"临澧县\",\"安福镇\",\"桃源县\",\"漳江镇\",\"石门县\",\"楚江镇\"]);\ndsy.add(\"0_18_3\",[\"赫山区\",\"资阳区\",\"沅江市\",\"南县\",\"南洲镇\",\"桃江县\",\"桃花江镇\",\"安化县\",\"东坪镇\"]);\ndsy.add(\"0_18_4\",[\"岳阳楼区\",\"君山区\",\"云溪区\",\"汨罗市\",\"临湘市\",\"岳阳县\",\"荣家湾镇\",\"华容县\",\"城关镇\",\"湘阴县\",\"文星镇\",\"平江县\",\"汉昌镇\"]);\ndsy.add(\"0_18_5\",[\"天元区\",\"荷塘区\",\"芦淞区\",\"石峰区\",\"醴陵市\",\"株洲县\",\"渌口镇\",\"攸县\",\"城关镇\",\"茶陵县\",\"城关镇\",\"炎陵县\",\"霞阳镇\"]);\ndsy.add(\"0_18_6\",[\"岳塘区\",\"雨湖区\",\"湘乡市\",\"韶山市\",\"湘潭县\",\"易俗河镇\"]);\ndsy.add(\"0_18_7\",[\"雁峰区\",\"珠晖区\",\"石鼓区\",\"蒸湘区\",\"南岳区\",\"常宁市\",\"耒阳市\",\"衡阳县\",\"西渡镇\",\"衡南县\",\"云集镇\",\"衡山县\",\"开云镇\",\"衡东县\",\"城关镇\",\"祁东县\",\"洪桥镇\"]);\ndsy.add(\"0_18_8\",[\"北湖区\",\"苏仙区\",\"资兴市\",\"桂阳县\",\"城关镇\",\"永兴县\",\"城关镇\",\"宜章县\",\"城关镇\",\"嘉禾县\",\"城关镇\",\"临武县\",\"城关镇\",\"汝城县\",\"城关镇\",\"桂东县\",\"城关镇\",\"安仁县\",\"城关镇\"]);\ndsy.add(\"0_18_9\",[\"冷水滩区\",\"零陵区\",\"东安县\",\"白牙市镇\",\"道县\",\"道江镇\",\"宁远县\",\"舜陵镇\",\"江永县\",\"潇浦镇\",\"蓝山县\",\"塔峰镇\",\"新田县\",\"龙泉镇\",\"双牌县\",\"泷泊镇\",\"祁阳县\",\"浯溪镇\",\"江华瑶族自治县\",\"沱江镇\"]);\ndsy.add(\"0_18_10\",[\"双清区\",\"大祥区\",\"北塔区\",\"武冈市\",\"邵东县\",\"两市镇\",\"邵阳县\",\"塘渡口镇\",\"新邵县\",\"酿溪镇\",\"隆回县\",\"桃洪镇\",\"洞口县\",\"洞口镇\",\"绥宁县\",\"长铺镇\",\"新宁县\",\"金石镇\",\"城步苗族自治县\",\"儒林镇\"]);\ndsy.add(\"0_18_11\",[\"鹤城区\",\"洪江市\",\"沅陵县\",\"沅陵镇\",\"辰溪县\",\"辰阳镇\",\"溆浦县\",\"卢峰镇\",\"中方县\",\"中方镇\",\"会同县\",\"林城镇\",\"麻阳苗族自治县\",\"高村镇\",\"新晃侗族自治县\",\"新晃镇\",\"芷江侗族自治县\",\"芷江镇\",\"靖州苗族侗族自治县\",\"渠阳镇\",\"通道侗族自治县\",\"双江镇\"]);\ndsy.add(\"0_18_12\",[\"娄星区\",\"冷水江市\",\"涟源市\",\"双峰县\",\"永丰镇\",\"新化县\",\"上梅镇\"]);\ndsy.add(\"0_18_13\",[\"吉首市\",\"泸溪县\",\"白沙镇\",\"凤凰县\",\"沱江镇\",\"花垣县\",\"花垣镇\",\"保靖县\",\"迁陵镇\",\"古丈县\",\"古阳镇\",\"永顺县\",\"灵溪镇\",\"龙山县\"]);\ndsy.add(\"0_18\",[\"长沙市\",\"张家界市\",\"常德市\",\"益阳市\",\"岳阳市\",\"株洲市\",\"湘潭市\",\"衡阳市\",\"郴州市\",\"永州市\",\"邵阳市\",\"怀化市\",\"娄底市\",\"湘西州\"]);\ndsy.add(\"0_19_0\",[\"越秀区\",\"荔湾区\",\"海珠区\",\"天河区\",\"白云区\",\"黄埔区\",\"番禺区\",\"花都区\",\"南沙区\",\"萝岗区\",\"增城市\",\"从化市\"]);\ndsy.add(\"0_19_1\",[\"福田区\",\"罗湖区\",\"南山区\",\"宝安区\",\"龙岗区\",\"盐田区\"]);\ndsy.add(\"0_19_2\",[\"清城区\",\"英德市\",\"连州市\",\"佛冈县\",\"石角镇\",\"阳山县\",\"阳城镇\",\"清新县\",\"太和镇\",\"连山壮族瑶族自治县\",\"吉田镇\",\"连南瑶族自治县\",\"三江镇\"]);\ndsy.add(\"0_19_3\",[\"浈江区\",\"武江区\",\"曲江区\",\"乐昌市\",\"南雄市\",\"始兴县\",\"太平镇\",\"仁化县\",\"仁化镇\",\"翁源县\",\"龙仙镇\",\"新丰县\",\"乳源瑶族自治县\",\"乳城镇\"]);\ndsy.add(\"0_19_4\",[\"源城区\",\"紫金县\",\"紫城镇\",\"龙川县\",\"老隆镇\",\"连平县\",\"元善镇\",\"和平县\",\"阳明镇\",\"东源县\",\"仙塘镇\"]);\ndsy.add(\"0_19_5\",[\"梅江区\",\"兴宁市\",\"梅县\",\"程江镇\",\"大埔县\",\"湖寮镇\",\"丰顺县\",\"汤坑镇\",\"五华县\",\"水寨镇\",\"平远县\",\"大柘镇\",\"蕉岭县\",\"蕉城镇\"]);\ndsy.add(\"0_19_6\",[\"湘桥区\",\"潮安县\",\"庵埠镇\",\"饶平县\",\"黄冈镇\"]);\ndsy.add(\"0_19_7\",[\"金平区\",\"濠江区\",\"龙湖区\",\"潮阳区\",\"潮南区\",\"澄海区\",\"南澳县\",\"后宅镇\"]);\ndsy.add(\"0_19_8\",[\"榕城区\",\"普宁市\",\"揭东县\",\"曲溪镇\",\"揭西县\",\"河婆镇\",\"惠来县\",\"惠城镇\"]);\ndsy.add(\"0_19_9\",[\"城区\",\"陆丰市\",\"海丰县\",\"海城镇\",\"陆河县\",\"河田镇\"]);\ndsy.add(\"0_19_10\",[\"惠城区\",\"惠阳区\",\"博罗县\",\"罗阳镇\",\"惠东县\",\"龙门县\"]);\ndsy.add(\"0_19_12\",[\"香洲区\",\"斗门区\",\"金湾区\"]);\ndsy.add(\"0_19_14\",[\"江海区\",\"蓬江区\",\"新会区\",\"恩平市\",\"台山市\",\"开平市\",\"鹤山市\"]);\ndsy.add(\"0_19_15\",[\"禅城区\",\"南海区\",\"顺德区\",\"三水区\",\"高明区\"]);\ndsy.add(\"0_19_16\",[\"端州区\",\"鼎湖区\",\"高要市\",\"四会市\",\"广宁县\",\"南街镇\",\"怀集县\",\"怀城镇\",\"封开县\",\"江口镇\",\"德庆县\"]);\ndsy.add(\"0_19_17\",[\"云城区\",\"罗定市\",\"云安县\",\"六都镇\",\"新兴县\",\"新城镇\",\"郁南县\",\"都城镇\"]);\ndsy.add(\"0_19_18\",[\"江城区\",\"阳春市\",\"阳西县\",\"织镇\",\"阳东县\",\"东城镇\"]);\ndsy.add(\"0_19_19\",[\"茂南区\",\"茂港区\",\"化州市\",\"信宜市\",\"高州市\",\"电白县\",\"水东镇\"]);\ndsy.add(\"0_19_20\",[\"赤坎区\",\"霞山区\",\"坡头区\",\"麻章区\",\"吴川市\",\"廉江市\",\"雷州市\",\"遂溪县\",\"遂城镇\",\"徐闻县\",\"撤销广州市东山区\",\"芳村区\",\"设立广州市南沙区\",\"萝岗区\"]);\ndsy.add(\"0_19\",[\"广州市\",\"深圳市\",\"清远市\",\"韶关市\",\"河源市\",\"梅州市\",\"潮州市\",\"汕头市\",\"揭阳市\",\"汕尾市\",\"惠州市\",\"东莞市\",\"珠海市\",\"中山市\",\"江门市\",\"佛山市\",\"肇庆市\",\"云浮市\",\"阳江市\",\"茂名市\",\"湛江市\"]);\ndsy.add(\"0_20_0\",[\"青秀区\",\"兴宁区\",\"江南区\",\"西乡塘区\",\"良庆区\",\"邕宁区\",\"武鸣县\",\"横县\",\"宾阳县\",\"上林县\",\"隆安县\",\"马山县\"]);\ndsy.add(\"0_20_1\",[\"象山区\",\"叠彩区\",\"秀峰区\",\"七星区\",\"雁山区\",\"阳朔县\",\"阳朔镇\",\"临桂县\",\"临桂镇\",\"灵川县\",\"灵川镇\",\"全州县\",\"全州镇\",\"兴安县\",\"兴安镇\",\"永福县\",\"永福镇\",\"灌阳县\",\"灌阳镇\",\"资源县\",\"资源镇\",\"平乐县\",\"平乐镇\",\"荔浦县\",\"荔城镇\",\"龙胜各族自治县\",\"龙胜镇\",\"恭城瑶族自治县\",\"恭城镇\"]);\ndsy.add(\"0_20_2\",[\"城中区\",\"鱼峰区\",\"柳南区\",\"柳北区\",\"柳江县\",\"拉堡镇\",\"柳城县\",\"大埔镇\",\"鹿寨县\",\"鹿寨镇\",\"融安县\",\"长安镇\",\"三江侗族自治县\",\"古宜镇\",\"融水苗族自治县\",\"融水镇\"]);\ndsy.add(\"0_20_3\",[\"万秀区\",\"蝶山区\",\"长洲区\",\"岑溪市\",\"苍梧县\",\"龙圩镇\",\"藤县\",\"藤州镇\",\"蒙山县\",\"蒙山镇\"]);\ndsy.add(\"0_20_4\",[\"港北区\",\"港南区\",\"覃塘区\",\"桂平市\",\"平南县\",\"平南镇\"]);\ndsy.add(\"0_20_5\",[\"玉州区\",\"北流市\",\"兴业县\",\"石南镇\",\"容县\",\"容州镇\",\"陆川县\",\"陆城镇\",\"博白县\",\"博白镇\"]);\ndsy.add(\"0_20_6\",[\"钦南区\",\"钦北区\",\"灵山县\",\"灵城镇\",\"浦北县\",\"小江镇\"]);\ndsy.add(\"0_20_7\",[\"海城区\",\"银海区\",\"铁山港区\",\"合浦县\",\"廉州镇\"]);\ndsy.add(\"0_20_8\",[\"港口区\",\"防城区\",\"东兴市\",\"上思县\",\"思阳镇\"]);\ndsy.add(\"0_20_9\",[\"江州区\",\"凭祥市\",\"扶绥县\",\"新宁镇\",\"大新县\",\"桃城镇\",\"天等县\",\"天等镇\",\"宁明县\",\"城中镇\",\"龙州县\",\"龙州镇\"]);\ndsy.add(\"0_20_10\",[\"右江区\",\"田阳县\",\"田州镇\",\"田东县\",\"平马镇\",\"平果县\",\"马头镇\",\"德保县\",\"城关镇\",\"靖西县\",\"新靖镇\",\"那坡县\",\"城厢镇\",\"凌云县\",\"泗城镇\",\"乐业县\",\"同乐镇\",\"西林县\",\"八达镇\",\"田林县\",\"乐里镇\",\"隆林各族自治县\",\"新州镇\"]);\ndsy.add(\"0_20_11\",[\"金城江区\",\"宜州市\",\"南丹县\",\"城关镇\",\"天峨县\",\"六排镇\",\"凤山县\",\"凤城镇\",\"东兰县\",\"东兰镇\",\"巴马瑶族自治县\",\"巴马镇\",\"都安瑶族自治县\",\"安阳镇\",\"大化瑶族自治县\",\"大化镇\",\"罗城仫佬族自治县\",\"东门镇\",\"环江毛南族自治县\",\"思恩镇\"]);\ndsy.add(\"0_20_12\",[\"兴宾区\",\"合山市\",\"象州县\",\"象州镇\",\"武宣县\",\"武宣镇\",\"忻城县\",\"城关镇\",\"金秀瑶族自治县\",\"金秀镇\"]);\ndsy.add(\"0_20_13\",[\"八步区\",\"昭平县\",\"昭平镇\",\"钟山县\",\"钟山镇\",\"富川瑶族自治县\",\"富阳镇\"]);\ndsy.add(\"0_20\",[\"南宁市\",\"桂林市\",\"柳州市\",\"梧州市\",\"贵港市\",\"玉林市\",\"钦州市\",\"北海市\",\"防城港市\",\"崇左市\",\"百色市\",\"河池市\",\"来宾市\",\"贺州市\"]);\ndsy.add(\"0_21_0\",[\"龙华区\",\"秀英区\",\"琼山区\",\"美兰区\"]);\ndsy.add(\"0_21_2\",[\"文昌市\",\"琼海市\",\"万宁市\",\"五指山市\",\"东方市\",\"儋州市\",\"临高县\",\"临城镇\",\"澄迈县\",\"金江镇\",\"定安县\",\"定城镇\",\"屯昌县\",\"屯城镇\",\"昌江黎族自治县\",\"石碌镇\",\"白沙黎族自治县\",\"牙叉镇\",\"琼中黎族苗族自治县\",\"营根镇\",\"陵水黎族自治县\",\"椰林镇\",\"保亭黎族苗族自治县\",\"保城镇\",\"乐东黎族自治县\",\"抱由镇\"]);\ndsy.add(\"0_21\",[\"海口市\",\"三亚市\",\"省直辖行政单位\"]);\ndsy.add(\"0_22_0\",[\"青羊区\",\"锦江区\",\"金牛区\",\"武侯区\",\"成华区\",\"龙泉驿区\",\"青白江区\",\"新都区\",\"温江区\",\"都江堰市\",\"彭州市\",\"邛崃市\",\"崇州市\",\"金堂县\",\"赵镇\",\"双流县\",\"郫县\",\"郫筒镇\",\"大邑县\",\"晋原镇\",\"蒲江县\",\"鹤山镇\",\"新津县\",\"五津镇\"]);\ndsy.add(\"0_22_1\",[\"市中区\",\"元坝区\",\"朝天区\",\"旺苍县\",\"东河镇\",\"青川县\",\"乔庄镇\",\"剑阁县\",\"下寺镇\",\"苍溪县\",\"陵江镇\"]);\ndsy.add(\"0_22_2\",[\"涪城区\",\"游仙区\",\"江油市\",\"三台县\",\"潼川镇\",\"盐亭县\",\"云溪镇\",\"安县\",\"花荄镇\",\"梓潼县\",\"文昌镇\",\"北川羌族自治县\",\"曲山镇\",\"平武县\",\"龙安镇\"]);\ndsy.add(\"0_22_3\",[\"旌阳区\",\"什邡市\",\"广汉市\",\"绵竹市\",\"罗江县\",\"罗江镇\",\"中江县\",\"凯江镇\"]);\ndsy.add(\"0_22_4\",[\"顺庆区\",\"高坪区\",\"嘉陵区\",\"阆中市\",\"南部县\",\"南隆镇\",\"营山县\",\"朗池镇\",\"蓬安县\",\"周口镇\",\"仪陇县\",\"新政镇\",\"西充县\",\"晋城镇\"]);\ndsy.add(\"0_22_5\",[\"广安区\",\"华蓥市\",\"岳池县\",\"九龙镇\",\"武胜县\",\"沿口镇\",\"邻水县\",\"鼎屏镇\"]);\ndsy.add(\"0_22_6\",[\"船山区\",\"安居区\",\"蓬溪县\",\"赤城镇\",\"射洪县\",\"太和镇\",\"大英县\",\"蓬莱镇\"]);\ndsy.add(\"0_22_7\",[\"市中区\",\"东兴区\",\"威远县\",\"严陵镇\",\"资中县\",\"重龙镇\",\"隆昌县\",\"金鹅镇\"]);\ndsy.add(\"0_22_8\",[\"市中区\",\"沙湾区\",\"五通桥区\",\"金口河区\",\"峨眉山市\",\"犍为县\",\"玉津镇\",\"井研县\",\"研城镇\",\"夹江县\",\"漹城镇\",\"沐川县\",\"沐溪镇\",\"峨边彝族自治县\",\"沙坪镇\",\"马边彝族自治县\",\"民建镇\"]);\ndsy.add(\"0_22_9\",[\"自流井区\",\"大安区\",\"贡井区\",\"沿滩区\",\"荣县\",\"旭阳镇\",\"富顺县\",\"富世镇\"]);\ndsy.add(\"0_22_10\",[\"江阳区\",\"纳溪区\",\"龙马潭区\",\"泸县\",\"福集镇\",\"合江县\",\"合江镇\",\"叙永县\",\"叙永镇\",\"古蔺县\",\"古蔺镇\"]);\ndsy.add(\"0_22_11\",[\"翠屏区\",\"宜宾县\",\"柏溪镇\",\"南溪县\",\"南溪镇\",\"江安县\",\"江安镇\",\"长宁县\",\"长宁镇\",\"高县\",\"庆符镇\",\"筠连县\",\"筠连镇\",\"珙县\",\"巡场镇\",\"兴文县\",\"中城镇\",\"屏山县\",\"屏山镇\"]);\ndsy.add(\"0_22_12\",[\"东区\",\"西区\",\"仁和区\",\"米易县\",\"攀莲镇\",\"盐边县\",\"桐子林镇\"]);\ndsy.add(\"0_22_13\",[\"巴州区\",\"通江县\",\"诺江镇\",\"南江县\",\"南江镇\",\"平昌县\",\"江口镇\"]);\ndsy.add(\"0_22_14\",[\"通川区\",\"万源市\",\"达县\",\"南外镇\",\"宣汉县\",\"东乡镇\",\"开江县\",\"新宁镇\",\"大竹县\",\"竹阳镇\",\"渠县\",\"渠江镇\"]);\ndsy.add(\"0_22_15\",[\"雁江区\",\"简阳市\",\"乐至县\",\"天池镇\",\"安岳县\",\"岳阳镇\"]);\ndsy.add(\"0_22_16\",[\"东坡区\",\"仁寿县\",\"文林镇\",\"彭山县\",\"凤鸣镇\",\"洪雅县\",\"洪川镇\",\"丹棱县\",\"丹棱镇\",\"青神县\",\"城厢镇\"]);\ndsy.add(\"0_22_17\",[\"雨城区\",\"名山县\",\"蒙阳镇\",\"荥经县\",\"严道镇\",\"汉源县\",\"富林镇\",\"石棉县\",\"新棉镇\",\"天全县\",\"城厢镇\",\"芦山县\",\"芦阳镇\",\"宝兴县\",\"穆坪镇\"]);\ndsy.add(\"0_22_18\",[\"马尔康县\",\"马尔康镇\",\"汶川县\",\"威州镇\",\"理县\",\"杂谷脑镇\",\"茂县\",\"凤仪镇\",\"松潘县\",\"进安镇\",\"九寨沟县\",\"永乐镇\",\"金川县\",\"金川镇\",\"小金县\",\"美兴镇\",\"黑水县\",\"芦花镇\",\"壤塘县\",\"壤柯镇\",\"阿坝县\",\"阿坝镇\",\"若尔盖县\",\"达扎寺镇\",\"红原县\",\"邛溪镇\"]);\ndsy.add(\"0_22_19\",[\"康定县\",\"炉城镇\",\"泸定县\",\"泸桥镇\",\"丹巴县\",\"章谷镇\",\"九龙县\",\"呷尔镇\",\"雅江县\",\"河口镇\",\"道孚县\",\"鲜水镇\",\"炉霍县\",\"新都镇\",\"甘孜县\",\"甘孜镇\",\"新龙县\",\"茹龙镇\",\"德格县\",\"更庆镇\",\"白玉县\",\"建设镇\",\"石渠县\",\"尼呷镇\",\"色达县\",\"色柯镇\",\"理塘县\",\"高城镇\",\"巴塘县\",\"夏邛镇\",\"乡城县\",\"桑披镇\",\"稻城县\",\"金珠镇\",\"得荣县\",\"松麦镇\"]);\ndsy.add(\"0_22_20\",[\"西昌市\",\"盐源县\",\"盐井镇\",\"德昌县\",\"德州镇\",\"会理县\",\"城关镇\",\"会东县\",\"会东镇\",\"宁南县\",\"披砂镇\",\"普格县\",\"普基镇\",\"布拖县\",\"特木里镇\",\"金阳县\",\"天地坝镇\",\"昭觉县\",\"新城镇\",\"喜德县\",\"光明镇\",\"冕宁县\",\"城厢镇\",\"越西县\",\"越城镇\",\"甘洛县\",\"新市坝镇\",\"美姑县\",\"巴普镇\",\"雷波县\",\"锦城镇\",\"木里藏族自治县\",\"乔瓦镇\"]);\ndsy.add(\"0_22\",[\"成都市\",\"广元市\",\"绵阳市\",\"德阳市\",\"南充市\",\"广安市\",\"遂宁市\",\"内江市\",\"乐山市\",\"自贡市\",\"泸州市\",\"宜宾市\",\"攀枝花市\",\"巴中市\",\"达州市\",\"资阳市\",\"眉山市\",\"雅安市\",\"阿坝州\",\"甘孜州\",\"凉山州\"]);\ndsy.add(\"0_23_0\",[\"乌当区\",\"南明区\",\"云岩区\",\"花溪区\",\"白云区\",\"小河区\",\"清镇市\",\"开阳县\",\"城关镇\",\"修文县\",\"龙场镇\",\"息烽县\",\"永靖镇\"]);\ndsy.add(\"0_23_1\",[\"钟山区\",\"盘县\",\"红果镇\",\"六枝特区\",\"平寨镇\",\"水城县\"]);\ndsy.add(\"0_23_2\",[\"红花岗区\",\"汇川区\",\"赤水市\",\"仁怀市\",\"遵义县\",\"南白镇\",\"桐梓县\",\"娄山关镇\",\"绥阳县\",\"洋川镇\",\"正安县\",\"凤仪镇\",\"凤冈县\",\"龙泉镇\",\"湄潭县\",\"湄江镇\",\"余庆县\",\"白泥镇\",\"习水县\",\"东皇镇\",\"道真仡佬族苗族自治县\",\"玉溪镇\",\"务川仡佬族苗族自治县\",\"都濡镇\"]);\ndsy.add(\"0_23_3\",[\"西秀区\",\"平坝县\",\"城关镇\",\"普定县\",\"城关镇\",\"关岭布依族苗族自治县\",\"关索镇\",\"镇宁布依族苗族自治县\",\"城关镇\",\"紫云苗族布依族自治县\",\"松山镇\"]);\ndsy.add(\"0_23_4\",[\"毕节市\",\"大方县\",\"大方镇\",\"黔西县\",\"城关镇\",\"金沙县\",\"城关镇\",\"织金县\",\"城关镇\",\"纳雍县\",\"雍熙镇\",\"赫章县\",\"城关镇\",\"威宁彝族回族苗族自治县\",\"草海镇\"]);\ndsy.add(\"0_23_5\",[\"铜仁市\",\"江口县\",\"双江镇\",\"石阡县\",\"汤山镇\",\"思南县\",\"思唐镇\",\"德江县\",\"青龙镇\",\"玉屏侗族自治县\",\"平溪镇\",\"印江土家族苗族自治县\",\"峨岭镇\",\"沿河土家族自治县\",\"和平镇\",\"松桃苗族自治县\",\"蓼皋镇\",\"万山特区\",\"万山镇\"]);\ndsy.add(\"0_23_6\",[\"凯里市\",\"黄平县\",\"新州镇\",\"施秉县\",\"城关镇\",\"三穗县\",\"八弓镇\",\"镇远县\",\"阳镇\",\"岑巩县\",\"思旸镇\",\"天柱县\",\"凤城镇\",\"锦屏县\",\"三江镇\",\"剑河县\",\"革东镇\",\"台江县\",\"台拱镇\",\"黎平县\",\"德凤镇\",\"榕江县\",\"古州镇\",\"从江县\",\"丙妹镇\",\"雷山县\",\"丹江镇\",\"麻江县\",\"杏山镇\",\"丹寨县\",\"龙泉镇\"]);\ndsy.add(\"0_23_7\",[\"都匀市\",\"福泉市\",\"荔波县\",\"玉屏镇\",\"贵定县\",\"城关镇\",\"瓮安县\",\"雍阳镇\",\"独山县\",\"城关镇\",\"平塘县\",\"平湖镇\",\"罗甸县\",\"龙坪镇\",\"长顺县\",\"长寨镇\",\"龙里县\",\"龙山镇\",\"惠水县\",\"和平镇\",\"三都水族自治县\",\"三合镇\"]);\ndsy.add(\"0_23_8\",[\"兴义市\",\"兴仁县\",\"城关镇\",\"普安县\",\"盘水镇\",\"晴隆县\",\"莲城镇\",\"贞丰县\",\"珉谷镇\",\"望谟县\",\"复兴镇\",\"册亨县\",\"者楼镇\",\"安龙县\",\"新安镇\",\"剑河县人民政府驻地由柳川镇迁至革东镇\"]);\ndsy.add(\"0_23\",[\"贵阳市\",\"六盘水市\",\"遵义市\",\"安顺市\",\"毕节地区\",\"铜仁地区\",\"黔东南州\",\"黔南州\",\"黔西南州\"]);\ndsy.add(\"0_24_0\",[\"盘龙区\",\"五华区\",\"官渡区\",\"西山区\",\"东川区\",\"安宁市\",\"呈贡县\",\"龙城镇\",\"晋宁县\",\"昆阳镇\",\"富民县\",\"永定镇\",\"宜良县\",\"匡远镇\",\"嵩明县\",\"嵩阳镇\",\"石林彝族自治县\",\"鹿阜镇\",\"禄劝彝族苗族自治县\",\"屏山镇\",\"寻甸回族彝族自治县\",\"仁德镇\"]);\ndsy.add(\"0_24_1\",[\"麒麟区\",\"宣威市\",\"马龙县\",\"通泉镇\",\"沾益县\",\"西平镇\",\"富源县\",\"中安镇\",\"罗平县\",\"罗雄镇\",\"师宗县\",\"丹凤镇\",\"陆良县\",\"中枢镇\",\"会泽县\",\"金钟镇\"]);\ndsy.add(\"0_24_2\",[\"红塔区\",\"江川县\",\"大街镇\",\"澄江县\",\"凤麓镇\",\"通海县\",\"秀山镇\",\"华宁县\",\"宁州镇\",\"易门县\",\"龙泉镇\",\"峨山彝族自治县\",\"双江镇\",\"新平彝族傣族自治县\",\"桂山镇\",\"元江哈尼族彝族傣族自治县\",\"澧江镇\"]);\ndsy.add(\"0_24_3\",[\"隆阳区\",\"施甸县\",\"甸阳镇\",\"腾冲县\",\"腾越镇\",\"龙陵县\",\"龙山镇\",\"昌宁县\",\"田园镇\"]);\ndsy.add(\"0_24_4\",[\"昭阳区\",\"鲁甸县\",\"文屏镇\",\"巧家县\",\"新华镇\",\"盐津县\",\"盐井镇\",\"大关县\",\"翠华镇\",\"永善县\",\"溪落渡镇\",\"绥江县\",\"中城镇\",\"镇雄县\",\"乌峰镇\",\"彝良县\",\"角奎镇\",\"威信县\",\"扎西镇\",\"水富县\",\"向家坝镇\"]);\ndsy.add(\"0_24_5\",[\"古城区\",\"永胜县\",\"永北镇\",\"华坪县\",\"中心镇\",\"玉龙纳西族自治县\",\"黄山镇\",\"宁蒗彝族自治县\",\"大兴镇\"]);\ndsy.add(\"0_24_6\",[\"翠云区\",\"普洱哈尼族彝族自治县\",\"宁洱镇\",\"墨江哈尼族自治县\",\"联珠镇\",\"景东彝族自治县\",\"锦屏镇\",\"景谷傣族彝族自治县\",\"威远镇\",\"镇沅彝族哈尼族拉祜族自治县\",\"恩乐镇\",\"江城哈尼族彝族自治县\",\"勐烈镇\",\"孟连傣族拉祜族佤族自治县\",\"娜允镇\",\"澜沧拉祜族自治县\",\"勐朗镇\",\"西盟佤族自治县\",\"勐梭镇\"]);\ndsy.add(\"0_24_7\",[\"临翔区\",\"凤庆县\",\"凤山镇\",\"云县\",\"爱华镇\",\"永德县\",\"德党镇\",\"镇康县\",\"南伞镇\",\"双江拉祜族佤族布朗族傣族自治县\",\"勐勐镇\",\"耿马傣族佤族自治县\",\"耿马镇\",\"沧源佤族自治县\",\"勐董镇\"]);\ndsy.add(\"0_24_8\",[\"潞西市\",\"瑞丽市\",\"梁河县\",\"遮岛镇\",\"盈江县\",\"平原镇\",\"陇川县\",\"章凤镇\"]);\ndsy.add(\"0_24_9\",[\"泸水县六库镇\",\"泸水县\",\"六库镇\",\"福贡县\",\"上帕镇\",\"贡山独龙族怒族自治县\",\"茨开镇\",\"兰坪白族普米族自治县\",\"金顶镇\"]);\ndsy.add(\"0_24_10\",[\"香格里拉县\",\"建塘镇\",\"德钦县\",\"升平镇\",\"维西傈僳族自治县\",\"保和镇\"]);\ndsy.add(\"0_24_11\",[\"大理市\",\"祥云县\",\"祥城镇\",\"宾川县\",\"金牛镇\",\"弥渡县\",\"弥城镇\",\"永平县\",\"博南镇\",\"云龙县\",\"诺邓镇\",\"洱源县\",\"茈碧湖镇\",\"剑川县\",\"金华镇\",\"鹤庆县\",\"云鹤镇\",\"漾濞彝族自治县\",\"苍山西镇\",\"南涧彝族自治县\",\"南涧镇\",\"巍山彝族回族自治县\",\"南诏镇\"]);\ndsy.add(\"0_24_12\",[\"楚雄市\",\"双柏县\",\"妥甸镇\",\"牟定县\",\"共和镇\",\"南华县\",\"龙川镇\",\"姚安县\",\"栋川镇\",\"大姚县\",\"金碧镇\",\"永仁县\",\"永定镇\",\"元谋县\",\"元马镇\",\"武定县\",\"狮山镇\",\"禄丰县\",\"金山镇\"]);\ndsy.add(\"0_24_13\",[\"蒙自县\",\"文澜镇\",\"个旧市\",\"开远市\",\"绿春县\",\"大兴镇\",\"建水县\",\"临安镇\",\"石屏县\",\"异龙镇\",\"弥勒县\",\"弥阳镇\",\"泸西县\",\"中枢镇\",\"元阳县\",\"南沙镇\",\"红河县\",\"迤萨镇\",\"金平苗族瑶族傣族自治县\",\"金河镇\",\"河口瑶族自治县\",\"河口镇\",\"屏边苗族自治县\",\"玉屏镇\"]);\ndsy.add(\"0_24_14\",[\"文山县\",\"开化镇\",\"砚山县\",\"江那镇\",\"西畴县\",\"西洒镇\",\"麻栗坡县\",\"麻栗镇\",\"马关县\",\"马白镇\",\"丘北县\",\"锦屏镇\",\"广南县\",\"莲城镇\",\"富宁县\",\"新华镇\"]);\ndsy.add(\"0_24_15\",[\"景洪市\",\"勐海县\",\"勐海镇\",\"勐腊县\",\"勐腊镇\"]);\ndsy.add(\"0_24\",[\"昆明市\",\"曲靖市\",\"玉溪市\",\"保山市\",\"昭通市\",\"丽江市\",\"思茅市\",\"临沧市\",\"德宏州\",\"怒江州\",\"迪庆州\",\"大理州\",\"楚雄州\",\"红河州\",\"文山州\",\"西双版纳州\"]);\ndsy.add(\"0_25_0\",[\"城关区\",\"林周县\",\"甘丹曲果镇\",\"当雄县\",\"当曲卡镇\",\"尼木县\",\"塔荣镇\",\"曲水县\",\"曲水镇\",\"堆龙德庆县\",\"东嘎镇\",\"达孜县\",\"德庆镇\",\"墨竹工卡县\",\"工卡镇\"]);\ndsy.add(\"0_25_1\",[\"那曲县\",\"那曲镇\",\"嘉黎县\",\"阿扎镇\",\"比如县\",\"比如镇\",\"聂荣县\",\"聂荣镇\",\"安多县\",\"帕那镇\",\"申扎县\",\"申扎镇\",\"索县\",\"亚拉镇\",\"班戈县\",\"普保镇\",\"巴青县\",\"拉西镇\",\"尼玛县\",\"尼玛镇\"]);\ndsy.add(\"0_25_2\",[\"昌都县\",\"城关镇\",\"江达县\",\"江达镇\",\"贡觉县\",\"莫洛镇\",\"类乌齐县\",\"桑多镇\",\"丁青县\",\"丁青镇\",\"察雅县\",\"烟多镇\",\"八宿县\",\"白玛镇\",\"左贡县\",\"旺达镇\",\"芒康县\",\"嘎托镇\",\"洛隆县\",\"孜托镇\",\"边坝县\",\"草卡镇\"]);\ndsy.add(\"0_25_3\",[\"林芝县\",\"八一镇\",\"工布江达县\",\"工布江达镇\",\"米林县\",\"米林镇\",\"墨脱县\",\"墨脱镇\",\"波密县\",\"扎木镇\",\"察隅县\",\"竹瓦根镇\",\"朗县\",\"朗镇\"]);\ndsy.add(\"0_25_4\",[\"乃东县\",\"泽当镇\",\"扎囊县\",\"扎塘镇\",\"贡嘎县\",\"吉雄镇\",\"桑日县\",\"桑日镇\",\"琼结县\",\"琼结镇\",\"曲松县\",\"曲松镇\",\"措美县\",\"措美镇\",\"洛扎县\",\"洛扎镇\",\"加查县\",\"安绕镇\",\"隆子县\",\"隆子镇\",\"错那县\",\"错那镇\",\"浪卡子县\",\"浪卡子镇\"]);\ndsy.add(\"0_25_5\",[\"日喀则市\",\"南木林县\",\"南木林镇\",\"江孜县\",\"江孜镇\",\"定日县\",\"协格尔镇\",\"萨迦县\",\"萨迦镇\",\"拉孜县\",\"曲下镇\",\"昂仁县\",\"卡嘎镇\",\"谢通门县\",\"卡嘎镇\",\"白朗县\",\"洛江镇\",\"仁布县\",\"德吉林镇\",\"康马县\",\"康马镇\",\"定结县\",\"江嘎镇\",\"仲巴县\",\"拉让乡\",\"亚东县\",\"下司马镇\",\"吉隆县\",\"宗嘎镇\",\"聂拉木县\",\"聂拉木镇\",\"萨嘎县\",\"加加镇\",\"岗巴县\",\"岗巴镇\"]);\ndsy.add(\"0_25_6\",[\"噶尔县\",\"狮泉河镇\",\"普兰县\",\"普兰镇\",\"札达县\",\"托林镇\",\"日土县\",\"日土镇\",\"革吉县\",\"革吉镇\",\"改则县\",\"改则镇\",\"措勤县\",\"措勤镇\",\"林芝县人民政府驻地由林芝镇迁至八一镇\"]);\ndsy.add(\"0_25\",[\"拉萨市\",\"那曲地区\",\"昌都地区\",\"林芝地区\",\"山南地区\",\"日喀则地区\",\"阿里地区\"]);\ndsy.add(\"0_26_0\",[\"莲湖区\",\"新城区\",\"碑林区\",\"灞桥区\",\"未央区\",\"雁塔区\",\"阎良区\",\"临潼区\",\"长安区\",\"蓝田县\",\"蓝关镇\",\"周至县\",\"二曲镇\",\"户县\",\"甘亭镇\",\"高陵县\",\"鹿苑镇\"]);\ndsy.add(\"0_26_1\",[\"宝塔区\",\"延长县\",\"七里村镇\",\"延川县\",\"延川镇\",\"子长县\",\"瓦窑堡镇\",\"安塞县\",\"真武洞镇\",\"志丹县\",\"保安镇\",\"吴起县\",\"吴旗镇\",\"甘泉县\",\"城关镇\",\"富县\",\"富城镇\",\"洛川县\",\"凤栖镇\",\"宜川县\",\"丹州镇\",\"黄龙县\",\"石堡镇\",\"黄陵县\",\"桥山镇\"]);\ndsy.add(\"0_26_2\",[\"耀州区\",\"王益区\",\"印台区\",\"宜君县\",\"城关镇\"]);\ndsy.add(\"0_26_3\",[\"临渭区\",\"华阴市\",\"韩城市\",\"华县\",\"华州镇\",\"潼关县\",\"城关镇\",\"大荔县\",\"城关镇\",\"蒲城县\",\"城关镇\",\"澄城县\",\"城关镇\",\"白水县\",\"城关镇\",\"合阳县\",\"城关镇\",\"富平县\",\"窦村镇\"]);\ndsy.add(\"0_26_4\",[\"秦都区\",\"杨陵区\",\"渭城区\",\"兴平市\",\"三原县\",\"城关镇\",\"泾阳县\",\"泾干镇\",\"乾县\",\"城关镇\",\"礼泉县\",\"城关镇\",\"永寿县\",\"监军镇\",\"彬县\",\"城关镇\",\"长武县\",\"昭仁镇\",\"旬邑县\",\"城关镇\",\"淳化县\",\"城关镇\",\"武功县\",\"普集镇\"]);\ndsy.add(\"0_26_5\",[\"渭滨区\",\"金台区\",\"陈仓区\",\"凤翔县\",\"城关镇\",\"岐山县\",\"凤鸣镇\",\"扶风县\",\"城关镇\",\"眉县\",\"首善镇\",\"陇县\",\"城关镇\",\"千阳县\",\"城关镇\",\"麟游县\",\"九成宫镇\",\"凤县\",\"双石铺镇\",\"太白县\",\"嘴头镇\"]);\ndsy.add(\"0_26_6\",[\"汉台区\",\"南郑县\",\"城关镇\",\"城固县\",\"博望镇\",\"洋县\",\"洋州镇\",\"西乡县\",\"城关镇\",\"勉县\",\"勉阳镇\",\"宁强县\",\"汉源镇\",\"略阳县\",\"城关镇\",\"镇巴县\",\"泾洋镇\",\"留坝县\",\"城关镇\",\"佛坪县\",\"袁家庄镇\"]);\ndsy.add(\"0_26_7\",[\"榆阳区\",\"神木县\",\"神木镇\",\"府谷县\",\"府谷镇\",\"横山县\",\"横山镇\",\"靖边县\",\"张家畔镇\",\"定边县\",\"定边镇\",\"绥德县\",\"名州镇\",\"米脂县\",\"银州镇\",\"佳县\",\"佳芦镇\",\"吴堡县\",\"宋家川镇\",\"清涧县\",\"宽洲镇\",\"子洲县\",\"双湖峪镇\"]);\ndsy.add(\"0_26_8\",[\"汉滨区\",\"汉阴县\",\"城关镇\",\"石泉县\",\"城关镇\",\"宁陕县\",\"城关镇\",\"紫阳县\",\"城关镇\",\"岚皋县\",\"城关镇\",\"平利县\",\"城关镇\",\"镇坪县\",\"城关镇\",\"旬阳县\",\"城关镇\",\"白河县\",\"城关镇\"]);\ndsy.add(\"0_26_9\",[\"商州区\",\"洛南县\",\"城关镇\",\"丹凤县\",\"龙驹寨镇\",\"商南县\",\"城关镇\",\"山阳县\",\"城关镇\",\"镇安县\",\"永乐镇\",\"柞水县\",\"乾佑镇\"]);\ndsy.add(\"0_26\",[\"西安市\",\"延安市\",\"铜川市\",\"渭南市\",\"咸阳市\",\"宝鸡市\",\"汉中市\",\"榆林市\",\"安康市\",\"商洛市\"]);\ndsy.add(\"0_27_0\",[\"城关区\",\"七里河区\",\"西固区\",\"安宁区\",\"红古区\",\"永登县\",\"城关镇\",\"皋兰县\",\"石洞镇\",\"榆中县\",\"城关镇\"]);\ndsy.add(\"0_27_1\",[\"金昌市\",\"金川区\",\"永昌县\",\"城关镇\"]);\ndsy.add(\"0_27_2\",[\"白银区\",\"平川区\",\"靖远县\",\"乌兰镇\",\"会宁县\",\"会师镇\",\"景泰县\",\"一条山镇\"]);\ndsy.add(\"0_27_3\",[\"秦州区\",\"麦积区\",\"清水县\",\"永清镇\",\"秦安县\",\"兴国镇\",\"甘谷县\",\"大像山镇\",\"武山县\",\"城关镇\",\"张家川回族自治县\",\"张家川镇\"]);\ndsy.add(\"0_27_4\",[\"凉州区\",\"民勤县\",\"城关镇\",\"古浪县\",\"古浪镇\",\"天祝藏族自治县\",\"华藏寺镇\"]);\ndsy.add(\"0_27_5\",[\"肃州区\",\"玉门市\",\"敦煌市\",\"金塔县\",\"金塔镇\",\"安西县\",\"渊泉镇\",\"肃北蒙古族自治县\",\"党城湾镇\",\"阿克塞哈萨克族自治县\",\"红柳湾镇\"]);\ndsy.add(\"0_27_6\",[\"甘州区\",\"民乐县\",\"洪水镇\",\"临泽县\",\"沙河镇\",\"高台县\",\"城关镇\",\"山丹县\",\"清泉镇\",\"肃南裕固族自治县\",\"红湾寺镇\"]);\ndsy.add(\"0_27_7\",[\"西峰区\",\"庆城县\",\"庆城镇\",\"环县\",\"环城镇\",\"华池县\",\"柔远镇\",\"合水县\",\"西华池镇\",\"正宁县\",\"山河镇\",\"宁县\",\"新宁镇\",\"镇原县\",\"城关镇\"]);\ndsy.add(\"0_27_8\",[\"崆峒区\",\"泾川县\",\"城关镇\",\"灵台县\",\"中台镇\",\"崇信县\",\"锦屏镇\",\"华亭县\",\"东华镇\",\"庄浪县\",\"水洛镇\",\"静宁县\",\"城关镇\"]);\ndsy.add(\"0_27_9\",[\"安定区\",\"通渭县\",\"平襄镇\",\"临洮县\",\"洮阳镇\",\"漳县\",\"武阳镇\",\"岷县\",\"岷阳镇\",\"渭源县\",\"清源镇\",\"陇西县\",\"巩昌镇\"]);\ndsy.add(\"0_27_10\",[\"武都区\",\"成县\",\"城关镇\",\"宕昌县\",\"城关镇\",\"康县\",\"文县\",\"城关镇\",\"西和县\",\"汉源镇\",\"礼县\",\"城关镇\",\"两当县\",\"城关镇\",\"徽县\",\"城关镇\"]);\ndsy.add(\"0_27_11\",[\"临夏市\",\"临夏县\",\"韩集镇\",\"康乐县\",\"附城镇\",\"永靖县\",\"刘家峡镇\",\"广河县\",\"城关镇\",\"和政县\",\"城关镇\",\"东乡族自治县\",\"锁南坝镇\",\"积石山保安族东乡族撒拉族自治县\",\"吹麻滩镇\"]);\ndsy.add(\"0_27_12\",[\"合作市\",\"临潭县\",\"城关镇\",\"卓尼县\",\"柳林镇\",\"舟曲县\",\"城关镇\",\"迭部县\",\"电尕镇\",\"玛曲县\",\"尼玛镇\",\"碌曲县\",\"玛艾镇\",\"夏河县\",\"拉卜楞镇\"]);\ndsy.add(\"0_27\",[\"兰州市\",\"嘉峪关市\",\"白银市\",\"天水市\",\"武威市\",\"酒泉市\",\"张掖市\",\"庆阳市\",\"平凉市\",\"定西市\",\"陇南市\",\"临夏州\",\"甘南州\"]);\ndsy.add(\"0_28_0\",[\"城中区\",\"城东区\",\"城西区\",\"城北区\",\"大通回族土族自治县\",\"桥头镇\",\"湟源县\",\"城关镇\",\"湟中县\",\"鲁沙尔镇\"]);\ndsy.add(\"0_28_1\",[\"平安县\",\"平安镇\",\"乐都县\",\"碾伯镇\",\"民和回族土族自治县\",\"川口镇\",\"互助土族自治县\",\"威远镇\",\"化隆回族自治县\",\"巴燕镇\",\"循化撒拉族自治县\",\"积石镇\"]);\ndsy.add(\"0_28_2\",[\"海晏县\",\"三角城镇\",\"祁连县\",\"八宝镇\",\"刚察县\",\"沙柳河镇\",\"门源回族自治县\",\"浩门镇\"]);\ndsy.add(\"0_28_3\",[\"共和县\",\"恰卜恰镇\",\"同德县\",\"尕巴松多镇\",\"贵德县\",\"河阴镇\",\"兴海县\",\"子科滩镇\",\"贵南县\",\"茫曲镇\"]);\ndsy.add(\"0_28_4\",[\"同仁县\",\"隆务镇\",\"尖扎县\",\"马克唐镇\",\"泽库县\",\"泽曲镇\",\"河南蒙古族自治县\",\"优干宁镇\"]);\ndsy.add(\"0_28_5\",[\"玛沁县\",\"大武镇\",\"班玛县\",\"赛来塘镇\",\"甘德县\",\"柯曲镇\",\"达日县\",\"吉迈镇\",\"久治县\",\"智青松多镇\",\"玛多县\",\"黄河乡\"]);\ndsy.add(\"0_28_6\",[\"玉树县\",\"结古镇\",\"杂多县\",\"萨呼腾镇\",\"称多县\",\"称文镇\",\"治多县\",\"加吉博洛镇\",\"囊谦县\",\"香达镇\",\"曲麻莱县\",\"约改镇\"]);\ndsy.add(\"0_28_7\",[\"德令哈市\",\"格尔木市\",\"乌兰县\",\"希里沟镇\",\"都兰县\",\"察汗乌苏镇\",\"天峻县\",\"新源镇\"]);\ndsy.add(\"0_28\",[\"西宁市\",\"海东地区\",\"海北州\",\"海南州\",\"黄南州\",\"果洛州\",\"玉树州\",\"海西州\"]);\ndsy.add(\"0_29_0\",[\"兴庆区\",\"金凤区\",\"西夏区\",\"灵武市\",\"永宁县\",\"杨和镇\",\"贺兰县\",\"习岗镇\"]);\ndsy.add(\"0_29_1\",[\"大武口区\",\"惠农区\",\"平罗县\",\"城关镇\"]);\ndsy.add(\"0_29_2\",[\"利通区\",\"青铜峡市\",\"盐池县\",\"花马池镇\",\"同心县\",\"豫海镇\"]);\ndsy.add(\"0_29_3\",[\"原州区\",\"西吉县\",\"吉强镇\",\"隆德县\",\"城关镇\",\"泾源县\",\"香水镇\",\"彭阳县\",\"白阳镇\"]);\ndsy.add(\"0_29_4\",[\"沙坡头区\",\"中宁县\",\"海原县\"]);\ndsy.add(\"0_29\",[\"银川市\",\"石嘴山市\",\"吴忠市\",\"固原市\",\"中卫市\"]);\ndsy.add(\"0_30_0\",[\"天山区\",\"沙依巴克区\",\"新市区\",\"水磨沟区\",\"头屯河区\",\"达坂城区\",\"东山区\",\"乌鲁木齐县\",\"乌鲁木齐市水磨沟区\"]);\ndsy.add(\"0_30_1\",[\"克拉玛依区\",\"独山子区\",\"白碱滩区\",\"乌尔禾区\"]);\ndsy.add(\"0_30_2\",[\"石河子市\",\"阿拉尔市\",\"图木舒克市\",\"五家渠市\"]);\ndsy.add(\"0_30_3\",[\"喀什市\",\"疏附县\",\"托克扎克镇\",\"疏勒县\",\"疏勒镇\",\"英吉沙县\",\"英吉沙镇\",\"泽普县\",\"泽普镇\",\"莎车县\",\"莎车镇\",\"叶城县\",\"喀格勒克镇\",\"麦盖提县\",\"麦盖提镇\",\"岳普湖县\",\"岳普湖镇\",\"伽师县\",\"巴仁镇\",\"巴楚县\",\"巴楚镇\",\"塔什库尔干塔吉克自治县\",\"塔什库尔干镇\"]);\ndsy.add(\"0_30_4\",[\"阿克苏市\",\"温宿县\",\"温宿镇\",\"库车县\",\"库车镇\",\"沙雅县\",\"沙雅镇\",\"新和县\",\"新和镇\",\"拜城县\",\"拜城镇\",\"乌什县\",\"乌什镇\",\"阿瓦提县\",\"阿瓦提镇\",\"柯坪县\",\"柯坪镇\"]);\ndsy.add(\"0_30_5\",[\"和田市\",\"和田县\",\"墨玉县\",\"喀拉喀什镇\",\"皮山县\",\"固玛镇\",\"洛浦县\",\"洛浦镇\",\"策勒县\",\"策勒镇\",\"于田县\",\"木尕拉镇\",\"民丰县\",\"尼雅镇\"]);\ndsy.add(\"0_30_6\",[\"吐鲁番市\",\"鄯善县\",\"鄯善镇\",\"托克逊县\",\"托克逊镇\"]);\ndsy.add(\"0_30_7\",[\"哈密市\",\"伊吾县\",\"伊吾镇\",\"巴里坤哈萨克自治县\",\"巴里坤镇\"]);\ndsy.add(\"0_30_8\",[\"阿图什市\",\"阿克陶县\",\"阿克陶镇\",\"阿合奇县\",\"阿合奇镇\",\"乌恰县\",\"乌恰镇\"]);\ndsy.add(\"0_30_9\",[\"博乐市\",\"精河县\",\"精河镇\",\"温泉县\",\"博格达尔镇\"]);\ndsy.add(\"0_30_10\",[\"昌吉市\",\"阜康市\",\"米泉市\",\"呼图壁县\",\"呼图壁镇\",\"玛纳斯县\",\"玛纳斯镇\",\"奇台县\",\"奇台镇\",\"吉木萨尔县\",\"吉木萨尔镇\",\"木垒哈萨克自治县\",\"木垒镇\"]);\ndsy.add(\"0_30_11\",[\"库尔勒市\",\"轮台县\",\"轮台镇\",\"尉犁县\",\"尉犁镇\",\"若羌县\",\"若羌镇\",\"且末县\",\"且末镇\",\"和静县\",\"和静镇\",\"和硕县\",\"特吾里克镇\",\"博湖县\",\"博湖镇\",\"焉耆回族自治县\",\"焉耆镇\"]);\ndsy.add(\"0_30_12\",[\"伊宁市\",\"奎屯市\",\"伊宁县\",\"吉里于孜镇\",\"霍城县\",\"水定镇\",\"巩留县\",\"巩留镇\",\"新源县\",\"新源镇\",\"昭苏县\",\"昭苏镇\",\"特克斯县\",\"特克斯镇\",\"尼勒克县\",\"尼勒克镇\",\"察布查尔锡伯自治县\",\"察布查尔镇\"]);\ndsy.add(\"0_30_13\",[\"塔城市\",\"乌苏市\",\"额敏县\",\"额敏镇\",\"沙湾县\",\"三道河子镇\",\"托里县\",\"托里镇\",\"裕民县\",\"哈拉布拉镇\",\"和布克赛尔蒙古自治县\",\"和布克赛尔镇\"]);\ndsy.add(\"0_30_14\",[\"阿勒泰市\",\"布尔津县\",\"布尔津镇\",\"富蕴县\",\"库额尔齐斯镇\",\"福海县\",\"哈巴河县\",\"青河县\",\"吉木乃县\"]);\ndsy.add(\"0_30\",[\"乌鲁木齐市\",\"克拉玛依市\",\"自治区直辖县级行政单位\",\"喀什地区\",\"阿克苏地区\",\"和田地区\",\"吐鲁番地区\",\"哈密地区\",\"克孜勒苏柯州\",\"博尔塔拉州\",\"昌吉州\",\"巴音郭楞州\",\"伊犁州\",\"塔城地区\",\"阿勒泰地区\"]);\ndsy.add(\"0_31_0\",[\"中西区\",\"东区\",\"九龙城区\",\"观塘区\",\"南区\",\"深水埗区\",\"湾仔区\",\"黄大仙区\",\"油尖旺区\",\"离岛区\",\"葵青区\",\"北区\",\"西贡区\",\"沙田区\",\"屯门区\",\"大埔区\",\"荃湾区\",\"元朗区\"]);\ndsy.add(\"0_31\",[\"香港特别行政区\"]);\ndsy.add(\"0_32_0\",[\"澳门特别行政区\"]);\ndsy.add(\"0_32\",[\"澳门特别行政区\"]);\ndsy.add(\"0_33_0\",[\" \"]);\ndsy.add(\"0_33\",[\"台北\",\"高雄\",\"台中\",\"花莲\",\"基隆\",\"嘉义\",\"金门\",\"连江\",\"苗栗\",\"南投\",\"澎湖\",\"屏东\",\"台东\",\"台南\",\"桃园\",\"新竹\",\"宜兰\",\"云林\",\"彰化\"]);\ndsy.add(\"0\",[\"北京市\",\"天津市\",\"上海市\",\"重庆市\",\"河北省\",\"山西省\",\"内蒙古\",\"辽宁省\",\"吉林省\",\"黑龙江省\",\"江苏省\",\"浙江省\",\"安徽省\",\"福建省\",\"江西省\",\"山东省\",\"河南省\",\"湖北省\",\"湖南省\",\"广东省\",\"广西\",\"海南省\",\"四川省\",\"贵州省\",\"云南省\",\"西藏\",\"陕西省\",\"甘肃省\",\"青海省\",\"宁夏\",\"新疆\",\"香港\",\"澳门\",\"台湾省\"]);\n\nvar s=[\"s_province\",\"s_city\",\"s_county\"];//三个select的name\nvar opt0 = [\"省份\",\"地级市\",\"市、县级市\"];//初始值\nfunction _init_area(){  //初始化函数\n\tfor(i=0;i<s.length-1;i++){\n\t  document.getElementById(s[i]).onchange=new Function(\"change(\"+(i+1)+\")\");\n\t}\n\tchange(0);\n}\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/base-component/amazeui/js/config.js",
    "content": "/**\n * Created by huzhihui on 2016/9/30.\n */\n\n/**\n * 全局列表json\n * @type {{}}\n */\nvar TAB_JSON = {\n    list: [\n        {\n            listName: '首页',/*tab名称*/\n            listUrl: 'pages/dashboard.html',/*页面路径*/\n            listUuid: 'uuid-main',/*tab唯一标识*/\n            listIcon: 'am-icon-home',/*左侧显示图标*/\n            listRightIcon: '',/*右侧显示图标*/\n            listNumber: '',/*右侧显示数字数据*/\n            listNumberColor: 'am-badge am-badge-secondary',/*右侧显示数字数据样式*/\n            isHtml: true/*是否是页面，false为折叠tab*/\n        },\n        {\n            listName: '页面模版',\n            listUrl: '',\n            listUuid: 'uuid-moban',\n            listIcon: 'am-icon-file',\n            listRightIcon: 'am-icon-angle-right',\n            listNumber: '',\n            listNumberColor: '',\n            isHtml: false,\n            subList: [\n                {\n                    listName: '个人资料',\n                    listUrl: 'html/personal-data.html',\n                    listUuid: 'uuid-personal-data',\n                    listIcon: 'am-icon-check',\n                    listRightIcon: 'am-icon-star',\n                    listNumber: '',\n                    listNumberColor: 'admin-icon-yellow',\n                    isHtml: true\n                },\n                {\n                    listName: '帮助页',\n                    listUrl: 'html/main.html',\n                    listUuid: 'uuid-help',\n                    listIcon: 'am-icon-puzzle-piece',\n                    listRightIcon: '',\n                    listNumber: '20',\n                    listNumberColor: 'am-badge am-badge-secondary',\n                    isHtml: true\n                }\n            ]\n        }\n    ]     \n};\n\n\n$.ajax({  \n    url:\"/permissions/current\",  \n    type:\"get\",  \n    async:false,\n    success:function(data){\n\t   \t if(!$.isArray(data)){\n\t   \t\t location.href='/login.html';\n\t   \t\t return;\n\t   \t }\n\t   \t  \n    }\n});\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/base-component/amazeui/js/iscroll.js",
    "content": "/*! iScroll v5.2.0 ~ (c) 2008-2016 Matteo Spinelli ~ http://cubiq.org/license */\n(function (window, document, Math) {\nvar rAF = window.requestAnimationFrame\t||\n\twindow.webkitRequestAnimationFrame\t||\n\twindow.mozRequestAnimationFrame\t\t||\n\twindow.oRequestAnimationFrame\t\t||\n\twindow.msRequestAnimationFrame\t\t||\n\tfunction (callback) { window.setTimeout(callback, 1000 / 60); };\n\nvar utils = (function () {\n\tvar me = {};\n\n\tvar _elementStyle = document.createElement('div').style;\n\tvar _vendor = (function () {\n\t\tvar vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'],\n\t\t\ttransform,\n\t\t\ti = 0,\n\t\t\tl = vendors.length;\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\ttransform = vendors[i] + 'ransform';\n\t\t\tif ( transform in _elementStyle ) return vendors[i].substr(0, vendors[i].length-1);\n\t\t}\n\n\t\treturn false;\n\t})();\n\n\tfunction _prefixStyle (style) {\n\t\tif ( _vendor === false ) return false;\n\t\tif ( _vendor === '' ) return style;\n\t\treturn _vendor + style.charAt(0).toUpperCase() + style.substr(1);\n\t}\n\n\tme.getTime = Date.now || function getTime () { return new Date().getTime(); };\n\n\tme.extend = function (target, obj) {\n\t\tfor ( var i in obj ) {\n\t\t\ttarget[i] = obj[i];\n\t\t}\n\t};\n\n\tme.addEvent = function (el, type, fn, capture) {\n\t\tel.addEventListener(type, fn, !!capture);\n\t};\n\n\tme.removeEvent = function (el, type, fn, capture) {\n\t\tel.removeEventListener(type, fn, !!capture);\n\t};\n\n\tme.prefixPointerEvent = function (pointerEvent) {\n\t\treturn window.MSPointerEvent ?\n\t\t\t'MSPointer' + pointerEvent.charAt(7).toUpperCase() + pointerEvent.substr(8):\n\t\t\tpointerEvent;\n\t};\n\n\tme.momentum = function (current, start, time, lowerMargin, wrapperSize, deceleration) {\n\t\tvar distance = current - start,\n\t\t\tspeed = Math.abs(distance) / time,\n\t\t\tdestination,\n\t\t\tduration;\n\n\t\tdeceleration = deceleration === undefined ? 0.0006 : deceleration;\n\n\t\tdestination = current + ( speed * speed ) / ( 2 * deceleration ) * ( distance < 0 ? -1 : 1 );\n\t\tduration = speed / deceleration;\n\n\t\tif ( destination < lowerMargin ) {\n\t\t\tdestination = wrapperSize ? lowerMargin - ( wrapperSize / 2.5 * ( speed / 8 ) ) : lowerMargin;\n\t\t\tdistance = Math.abs(destination - current);\n\t\t\tduration = distance / speed;\n\t\t} else if ( destination > 0 ) {\n\t\t\tdestination = wrapperSize ? wrapperSize / 2.5 * ( speed / 8 ) : 0;\n\t\t\tdistance = Math.abs(current) + destination;\n\t\t\tduration = distance / speed;\n\t\t}\n\n\t\treturn {\n\t\t\tdestination: Math.round(destination),\n\t\t\tduration: duration\n\t\t};\n\t};\n\n\tvar _transform = _prefixStyle('transform');\n\n\tme.extend(me, {\n\t\thasTransform: _transform !== false,\n\t\thasPerspective: _prefixStyle('perspective') in _elementStyle,\n\t\thasTouch: 'ontouchstart' in window,\n\t\thasPointer: !!(window.PointerEvent || window.MSPointerEvent), // IE10 is prefixed\n\t\thasTransition: _prefixStyle('transition') in _elementStyle\n\t});\n\n\t/*\n\tThis should find all Android browsers lower than build 535.19 (both stock browser and webview)\n\t- galaxy S2 is ok\n    - 2.3.6 : `AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1`\n    - 4.0.4 : `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`\n   - galaxy S3 is badAndroid (stock brower, webview)\n     `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`\n   - galaxy S4 is badAndroid (stock brower, webview)\n     `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`\n   - galaxy S5 is OK\n     `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)`\n   - galaxy S6 is OK\n     `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)`\n  */\n\tme.isBadAndroid = (function() {\n\t\tvar appVersion = window.navigator.appVersion;\n\t\t// Android browser is not a chrome browser.\n\t\tif (/Android/.test(appVersion) && !(/Chrome\\/\\d/.test(appVersion))) {\n\t\t\tvar safariVersion = appVersion.match(/Safari\\/(\\d+.\\d)/);\n\t\t\tif(safariVersion && typeof safariVersion === \"object\" && safariVersion.length >= 2) {\n\t\t\t\treturn parseFloat(safariVersion[1]) < 535.19;\n\t\t\t} else {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t})();\n\n\tme.extend(me.style = {}, {\n\t\ttransform: _transform,\n\t\ttransitionTimingFunction: _prefixStyle('transitionTimingFunction'),\n\t\ttransitionDuration: _prefixStyle('transitionDuration'),\n\t\ttransitionDelay: _prefixStyle('transitionDelay'),\n\t\ttransformOrigin: _prefixStyle('transformOrigin')\n\t});\n\n\tme.hasClass = function (e, c) {\n\t\tvar re = new RegExp(\"(^|\\\\s)\" + c + \"(\\\\s|$)\");\n\t\treturn re.test(e.className);\n\t};\n\n\tme.addClass = function (e, c) {\n\t\tif ( me.hasClass(e, c) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar newclass = e.className.split(' ');\n\t\tnewclass.push(c);\n\t\te.className = newclass.join(' ');\n\t};\n\n\tme.removeClass = function (e, c) {\n\t\tif ( !me.hasClass(e, c) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar re = new RegExp(\"(^|\\\\s)\" + c + \"(\\\\s|$)\", 'g');\n\t\te.className = e.className.replace(re, ' ');\n\t};\n\n\tme.offset = function (el) {\n\t\tvar left = -el.offsetLeft,\n\t\t\ttop = -el.offsetTop;\n\n\t\t// jshint -W084\n\t\twhile (el = el.offsetParent) {\n\t\t\tleft -= el.offsetLeft;\n\t\t\ttop -= el.offsetTop;\n\t\t}\n\t\t// jshint +W084\n\n\t\treturn {\n\t\t\tleft: left,\n\t\t\ttop: top\n\t\t};\n\t};\n\n\tme.preventDefaultException = function (el, exceptions) {\n\t\tfor ( var i in exceptions ) {\n\t\t\tif ( exceptions[i].test(el[i]) ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t};\n\n\tme.extend(me.eventType = {}, {\n\t\ttouchstart: 1,\n\t\ttouchmove: 1,\n\t\ttouchend: 1,\n\n\t\tmousedown: 2,\n\t\tmousemove: 2,\n\t\tmouseup: 2,\n\n\t\tpointerdown: 3,\n\t\tpointermove: 3,\n\t\tpointerup: 3,\n\n\t\tMSPointerDown: 3,\n\t\tMSPointerMove: 3,\n\t\tMSPointerUp: 3\n\t});\n\n\tme.extend(me.ease = {}, {\n\t\tquadratic: {\n\t\t\tstyle: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',\n\t\t\tfn: function (k) {\n\t\t\t\treturn k * ( 2 - k );\n\t\t\t}\n\t\t},\n\t\tcircular: {\n\t\t\tstyle: 'cubic-bezier(0.1, 0.57, 0.1, 1)',\t// Not properly \"circular\" but this looks better, it should be (0.075, 0.82, 0.165, 1)\n\t\t\tfn: function (k) {\n\t\t\t\treturn Math.sqrt( 1 - ( --k * k ) );\n\t\t\t}\n\t\t},\n\t\tback: {\n\t\t\tstyle: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)',\n\t\t\tfn: function (k) {\n\t\t\t\tvar b = 4;\n\t\t\t\treturn ( k = k - 1 ) * k * ( ( b + 1 ) * k + b ) + 1;\n\t\t\t}\n\t\t},\n\t\tbounce: {\n\t\t\tstyle: '',\n\t\t\tfn: function (k) {\n\t\t\t\tif ( ( k /= 1 ) < ( 1 / 2.75 ) ) {\n\t\t\t\t\treturn 7.5625 * k * k;\n\t\t\t\t} else if ( k < ( 2 / 2.75 ) ) {\n\t\t\t\t\treturn 7.5625 * ( k -= ( 1.5 / 2.75 ) ) * k + 0.75;\n\t\t\t\t} else if ( k < ( 2.5 / 2.75 ) ) {\n\t\t\t\t\treturn 7.5625 * ( k -= ( 2.25 / 2.75 ) ) * k + 0.9375;\n\t\t\t\t} else {\n\t\t\t\t\treturn 7.5625 * ( k -= ( 2.625 / 2.75 ) ) * k + 0.984375;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\telastic: {\n\t\t\tstyle: '',\n\t\t\tfn: function (k) {\n\t\t\t\tvar f = 0.22,\n\t\t\t\t\te = 0.4;\n\n\t\t\t\tif ( k === 0 ) { return 0; }\n\t\t\t\tif ( k == 1 ) { return 1; }\n\n\t\t\t\treturn ( e * Math.pow( 2, - 10 * k ) * Math.sin( ( k - f / 4 ) * ( 2 * Math.PI ) / f ) + 1 );\n\t\t\t}\n\t\t}\n\t});\n\n\tme.tap = function (e, eventName) {\n\t\tvar ev = document.createEvent('Event');\n\t\tev.initEvent(eventName, true, true);\n\t\tev.pageX = e.pageX;\n\t\tev.pageY = e.pageY;\n\t\te.target.dispatchEvent(ev);\n\t};\n\n\tme.click = function (e) {\n\t\tvar target = e.target,\n\t\t\tev;\n\n\t\tif ( !(/(SELECT|INPUT|TEXTAREA)/i).test(target.tagName) ) {\n\t\t\t// https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/initMouseEvent\n\t\t\t// initMouseEvent is deprecated.\n\t\t\tev = document.createEvent(window.MouseEvent ? 'MouseEvents' : 'Event');\n\t\t\tev.initEvent('click', true, true);\n\t\t\tev.view = e.view || window;\n\t\t\tev.detail = 1;\n\t\t\tev.screenX = target.screenX || 0;\n\t\t\tev.screenY = target.screenY || 0;\n\t\t\tev.clientX = target.clientX || 0;\n\t\t\tev.clientY = target.clientY || 0;\n\t\t\tev.ctrlKey = !!e.ctrlKey;\n\t\t\tev.altKey = !!e.altKey;\n\t\t\tev.shiftKey = !!e.shiftKey;\n\t\t\tev.metaKey = !!e.metaKey;\n\t\t\tev.button = 0;\n\t\t\tev.relatedTarget = null;\n\t\t\tev._constructed = true;\n\t\t\ttarget.dispatchEvent(ev);\n\t\t}\n\t};\n\n\treturn me;\n})();\nfunction IScroll (el, options) {\n\tthis.wrapper = typeof el == 'string' ? document.querySelector(el) : el;\n\tthis.scroller = this.wrapper.children[0];\n\tthis.scrollerStyle = this.scroller.style;\t\t// cache style for better performance\n\n\tthis.options = {\n\n\t\tresizeScrollbars: true,\n\n\t\tmouseWheelSpeed: 20,\n\n\t\tsnapThreshold: 0.334,\n\n// INSERT POINT: OPTIONS\n\t\tdisablePointer : !utils.hasPointer,\n\t\tdisableTouch : utils.hasPointer || !utils.hasTouch,\n\t\tdisableMouse : utils.hasPointer || utils.hasTouch,\n\t\tstartX: 0,\n\t\tstartY: 0,\n\t\tscrollY: true,\n\t\tdirectionLockThreshold: 5,\n\t\tmomentum: true,\n\n\t\tbounce: true,\n\t\tbounceTime: 600,\n\t\tbounceEasing: '',\n\n\t\tpreventDefault: true,\n\t\tpreventDefaultException: { tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT)$/ },\n\n\t\tHWCompositing: true,\n\t\tuseTransition: true,\n\t\tuseTransform: true,\n\t\tbindToWrapper: typeof window.onmousedown === \"undefined\"\n\t};\n\n\tfor ( var i in options ) {\n\t\tthis.options[i] = options[i];\n\t}\n\n\t// Normalize options\n\tthis.translateZ = this.options.HWCompositing && utils.hasPerspective ? ' translateZ(0)' : '';\n\n\tthis.options.useTransition = utils.hasTransition && this.options.useTransition;\n\tthis.options.useTransform = utils.hasTransform && this.options.useTransform;\n\n\tthis.options.eventPassthrough = this.options.eventPassthrough === true ? 'vertical' : this.options.eventPassthrough;\n\tthis.options.preventDefault = !this.options.eventPassthrough && this.options.preventDefault;\n\n\t// If you want eventPassthrough I have to lock one of the axes\n\tthis.options.scrollY = this.options.eventPassthrough == 'vertical' ? false : this.options.scrollY;\n\tthis.options.scrollX = this.options.eventPassthrough == 'horizontal' ? false : this.options.scrollX;\n\n\t// With eventPassthrough we also need lockDirection mechanism\n\tthis.options.freeScroll = this.options.freeScroll && !this.options.eventPassthrough;\n\tthis.options.directionLockThreshold = this.options.eventPassthrough ? 0 : this.options.directionLockThreshold;\n\n\tthis.options.bounceEasing = typeof this.options.bounceEasing == 'string' ? utils.ease[this.options.bounceEasing] || utils.ease.circular : this.options.bounceEasing;\n\n\tthis.options.resizePolling = this.options.resizePolling === undefined ? 60 : this.options.resizePolling;\n\n\tif ( this.options.tap === true ) {\n\t\tthis.options.tap = 'tap';\n\t}\n\n\t// https://github.com/cubiq/iscroll/issues/1029\n\tif (!this.options.useTransition && !this.options.useTransform) {\n\t\tif(!(/relative|absolute/i).test(this.scrollerStyle.position)) {\n\t\t\tthis.scrollerStyle.position = \"relative\";\n\t\t}\n\t}\n\n\tif ( this.options.shrinkScrollbars == 'scale' ) {\n\t\tthis.options.useTransition = false;\n\t}\n\n\tthis.options.invertWheelDirection = this.options.invertWheelDirection ? -1 : 1;\n\n// INSERT POINT: NORMALIZATION\n\n\t// Some defaults\n\tthis.x = 0;\n\tthis.y = 0;\n\tthis.directionX = 0;\n\tthis.directionY = 0;\n\tthis._events = {};\n\n// INSERT POINT: DEFAULTS\n\n\tthis._init();\n\tthis.refresh();\n\n\tthis.scrollTo(this.options.startX, this.options.startY);\n\tthis.enable();\n}\n\nIScroll.prototype = {\n\tversion: '5.2.0',\n\n\t_init: function () {\n\t\tthis._initEvents();\n\n\t\tif ( this.options.scrollbars || this.options.indicators ) {\n\t\t\tthis._initIndicators();\n\t\t}\n\n\t\tif ( this.options.mouseWheel ) {\n\t\t\tthis._initWheel();\n\t\t}\n\n\t\tif ( this.options.snap ) {\n\t\t\tthis._initSnap();\n\t\t}\n\n\t\tif ( this.options.keyBindings ) {\n\t\t\tthis._initKeys();\n\t\t}\n\n// INSERT POINT: _init\n\n\t},\n\n\tdestroy: function () {\n\t\tthis._initEvents(true);\n\t\tclearTimeout(this.resizeTimeout);\n \t\tthis.resizeTimeout = null;\n\t\tthis._execEvent('destroy');\n\t},\n\n\t_transitionEnd: function (e) {\n\t\tif ( e.target != this.scroller || !this.isInTransition ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._transitionTime();\n\t\tif ( !this.resetPosition(this.options.bounceTime) ) {\n\t\t\tthis.isInTransition = false;\n\t\t\tthis._execEvent('scrollEnd');\n\t\t}\n\t},\n\n\t_start: function (e) {\n\t\t// React to left mouse button only\n\t\tif ( utils.eventType[e.type] != 1 ) {\n\t\t  // for button property\n\t\t  // http://unixpapa.com/js/mouse.html\n\t\t  var button;\n\t    if (!e.which) {\n\t      /* IE case */\n\t      button = (e.button < 2) ? 0 :\n\t               ((e.button == 4) ? 1 : 2);\n\t    } else {\n\t      /* All others */\n\t      button = e.button;\n\t    }\n\t\t\tif ( button !== 0 ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tif ( !this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( this.options.preventDefault && !utils.isBadAndroid && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) {\n\t\t\te.preventDefault();\n\t\t}\n\n\t\tvar point = e.touches ? e.touches[0] : e,\n\t\t\tpos;\n\n\t\tthis.initiated\t= utils.eventType[e.type];\n\t\tthis.moved\t\t= false;\n\t\tthis.distX\t\t= 0;\n\t\tthis.distY\t\t= 0;\n\t\tthis.directionX = 0;\n\t\tthis.directionY = 0;\n\t\tthis.directionLocked = 0;\n\n\t\tthis.startTime = utils.getTime();\n\n\t\tif ( this.options.useTransition && this.isInTransition ) {\n\t\t\tthis._transitionTime();\n\t\t\tthis.isInTransition = false;\n\t\t\tpos = this.getComputedPosition();\n\t\t\tthis._translate(Math.round(pos.x), Math.round(pos.y));\n\t\t\tthis._execEvent('scrollEnd');\n\t\t} else if ( !this.options.useTransition && this.isAnimating ) {\n\t\t\tthis.isAnimating = false;\n\t\t\tthis._execEvent('scrollEnd');\n\t\t}\n\n\t\tthis.startX    = this.x;\n\t\tthis.startY    = this.y;\n\t\tthis.absStartX = this.x;\n\t\tthis.absStartY = this.y;\n\t\tthis.pointX    = point.pageX;\n\t\tthis.pointY    = point.pageY;\n\n\t\tthis._execEvent('beforeScrollStart');\n\t},\n\n\t_move: function (e) {\n\t\tif ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( this.options.preventDefault ) {\t// increases performance on Android? TODO: check!\n\t\t\te.preventDefault();\n\t\t}\n\n\t\tvar point\t\t= e.touches ? e.touches[0] : e,\n\t\t\tdeltaX\t\t= point.pageX - this.pointX,\n\t\t\tdeltaY\t\t= point.pageY - this.pointY,\n\t\t\ttimestamp\t= utils.getTime(),\n\t\t\tnewX, newY,\n\t\t\tabsDistX, absDistY;\n\n\t\tthis.pointX\t\t= point.pageX;\n\t\tthis.pointY\t\t= point.pageY;\n\n\t\tthis.distX\t\t+= deltaX;\n\t\tthis.distY\t\t+= deltaY;\n\t\tabsDistX\t\t= Math.abs(this.distX);\n\t\tabsDistY\t\t= Math.abs(this.distY);\n\n\t\t// We need to move at least 10 pixels for the scrolling to initiate\n\t\tif ( timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If you are scrolling in one direction lock the other\n\t\tif ( !this.directionLocked && !this.options.freeScroll ) {\n\t\t\tif ( absDistX > absDistY + this.options.directionLockThreshold ) {\n\t\t\t\tthis.directionLocked = 'h';\t\t// lock horizontally\n\t\t\t} else if ( absDistY >= absDistX + this.options.directionLockThreshold ) {\n\t\t\t\tthis.directionLocked = 'v';\t\t// lock vertically\n\t\t\t} else {\n\t\t\t\tthis.directionLocked = 'n';\t\t// no lock\n\t\t\t}\n\t\t}\n\n\t\tif ( this.directionLocked == 'h' ) {\n\t\t\tif ( this.options.eventPassthrough == 'vertical' ) {\n\t\t\t\te.preventDefault();\n\t\t\t} else if ( this.options.eventPassthrough == 'horizontal' ) {\n\t\t\t\tthis.initiated = false;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tdeltaY = 0;\n\t\t} else if ( this.directionLocked == 'v' ) {\n\t\t\tif ( this.options.eventPassthrough == 'horizontal' ) {\n\t\t\t\te.preventDefault();\n\t\t\t} else if ( this.options.eventPassthrough == 'vertical' ) {\n\t\t\t\tthis.initiated = false;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tdeltaX = 0;\n\t\t}\n\n\t\tdeltaX = this.hasHorizontalScroll ? deltaX : 0;\n\t\tdeltaY = this.hasVerticalScroll ? deltaY : 0;\n\n\t\tnewX = this.x + deltaX;\n\t\tnewY = this.y + deltaY;\n\n\t\t// Slow down if outside of the boundaries\n\t\tif ( newX > 0 || newX < this.maxScrollX ) {\n\t\t\tnewX = this.options.bounce ? this.x + deltaX / 3 : newX > 0 ? 0 : this.maxScrollX;\n\t\t}\n\t\tif ( newY > 0 || newY < this.maxScrollY ) {\n\t\t\tnewY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY;\n\t\t}\n\n\t\tthis.directionX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0;\n\t\tthis.directionY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0;\n\n\t\tif ( !this.moved ) {\n\t\t\tthis._execEvent('scrollStart');\n\t\t}\n\n\t\tthis.moved = true;\n\n\t\tthis._translate(newX, newY);\n\n/* REPLACE START: _move */\n\n\t\tif ( timestamp - this.startTime > 300 ) {\n\t\t\tthis.startTime = timestamp;\n\t\t\tthis.startX = this.x;\n\t\t\tthis.startY = this.y;\n\t\t}\n\n/* REPLACE END: _move */\n\n\t},\n\n\t_end: function (e) {\n\t\tif ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( this.options.preventDefault && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) {\n\t\t\te.preventDefault();\n\t\t}\n\n\t\tvar point = e.changedTouches ? e.changedTouches[0] : e,\n\t\t\tmomentumX,\n\t\t\tmomentumY,\n\t\t\tduration = utils.getTime() - this.startTime,\n\t\t\tnewX = Math.round(this.x),\n\t\t\tnewY = Math.round(this.y),\n\t\t\tdistanceX = Math.abs(newX - this.startX),\n\t\t\tdistanceY = Math.abs(newY - this.startY),\n\t\t\ttime = 0,\n\t\t\teasing = '';\n\n\t\tthis.isInTransition = 0;\n\t\tthis.initiated = 0;\n\t\tthis.endTime = utils.getTime();\n\n\t\t// reset if we are outside of the boundaries\n\t\tif ( this.resetPosition(this.options.bounceTime) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.scrollTo(newX, newY);\t// ensures that the last position is rounded\n\n\t\t// we scrolled less than 10 pixels\n\t\tif ( !this.moved ) {\n\t\t\tif ( this.options.tap ) {\n\t\t\t\tutils.tap(e, this.options.tap);\n\t\t\t}\n\n\t\t\tif ( this.options.click ) {\n\t\t\t\tutils.click(e);\n\t\t\t}\n\n\t\t\tthis._execEvent('scrollCancel');\n\t\t\treturn;\n\t\t}\n\n\t\tif ( this._events.flick && duration < 200 && distanceX < 100 && distanceY < 100 ) {\n\t\t\tthis._execEvent('flick');\n\t\t\treturn;\n\t\t}\n\n\t\t// start momentum animation if needed\n\t\tif ( this.options.momentum && duration < 300 ) {\n\t\t\tmomentumX = this.hasHorizontalScroll ? utils.momentum(this.x, this.startX, duration, this.maxScrollX, this.options.bounce ? this.wrapperWidth : 0, this.options.deceleration) : { destination: newX, duration: 0 };\n\t\t\tmomentumY = this.hasVerticalScroll ? utils.momentum(this.y, this.startY, duration, this.maxScrollY, this.options.bounce ? this.wrapperHeight : 0, this.options.deceleration) : { destination: newY, duration: 0 };\n\t\t\tnewX = momentumX.destination;\n\t\t\tnewY = momentumY.destination;\n\t\t\ttime = Math.max(momentumX.duration, momentumY.duration);\n\t\t\tthis.isInTransition = 1;\n\t\t}\n\n\n\t\tif ( this.options.snap ) {\n\t\t\tvar snap = this._nearestSnap(newX, newY);\n\t\t\tthis.currentPage = snap;\n\t\t\ttime = this.options.snapSpeed || Math.max(\n\t\t\t\t\tMath.max(\n\t\t\t\t\t\tMath.min(Math.abs(newX - snap.x), 1000),\n\t\t\t\t\t\tMath.min(Math.abs(newY - snap.y), 1000)\n\t\t\t\t\t), 300);\n\t\t\tnewX = snap.x;\n\t\t\tnewY = snap.y;\n\n\t\t\tthis.directionX = 0;\n\t\t\tthis.directionY = 0;\n\t\t\teasing = this.options.bounceEasing;\n\t\t}\n\n// INSERT POINT: _end\n\n\t\tif ( newX != this.x || newY != this.y ) {\n\t\t\t// change easing function when scroller goes out of the boundaries\n\t\t\tif ( newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY ) {\n\t\t\t\teasing = utils.ease.quadratic;\n\t\t\t}\n\n\t\t\tthis.scrollTo(newX, newY, time, easing);\n\t\t\treturn;\n\t\t}\n\n\t\tthis._execEvent('scrollEnd');\n\t},\n\n\t_resize: function () {\n\t\tvar that = this;\n\n\t\tclearTimeout(this.resizeTimeout);\n\n\t\tthis.resizeTimeout = setTimeout(function () {\n\t\t\tthat.refresh();\n\t\t}, this.options.resizePolling);\n\t},\n\n\tresetPosition: function (time) {\n\t\tvar x = this.x,\n\t\t\ty = this.y;\n\n\t\ttime = time || 0;\n\n\t\tif ( !this.hasHorizontalScroll || this.x > 0 ) {\n\t\t\tx = 0;\n\t\t} else if ( this.x < this.maxScrollX ) {\n\t\t\tx = this.maxScrollX;\n\t\t}\n\n\t\tif ( !this.hasVerticalScroll || this.y > 0 ) {\n\t\t\ty = 0;\n\t\t} else if ( this.y < this.maxScrollY ) {\n\t\t\ty = this.maxScrollY;\n\t\t}\n\n\t\tif ( x == this.x && y == this.y ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tthis.scrollTo(x, y, time, this.options.bounceEasing);\n\n\t\treturn true;\n\t},\n\n\tdisable: function () {\n\t\tthis.enabled = false;\n\t},\n\n\tenable: function () {\n\t\tthis.enabled = true;\n\t},\n\n\trefresh: function () {\n\t\tvar rf = this.wrapper.offsetHeight;\t\t// Force reflow\n\n\t\tthis.wrapperWidth\t= this.wrapper.clientWidth;\n\t\tthis.wrapperHeight\t= this.wrapper.clientHeight;\n\n/* REPLACE START: refresh */\n\n\t\tthis.scrollerWidth\t= this.scroller.offsetWidth;\n\t\tthis.scrollerHeight\t= this.scroller.offsetHeight;\n\n\t\tthis.maxScrollX\t\t= this.wrapperWidth - this.scrollerWidth;\n\t\tthis.maxScrollY\t\t= this.wrapperHeight - this.scrollerHeight;\n\n/* REPLACE END: refresh */\n\n\t\tthis.hasHorizontalScroll\t= this.options.scrollX && this.maxScrollX < 0;\n\t\tthis.hasVerticalScroll\t\t= this.options.scrollY && this.maxScrollY < 0;\n\n\t\tif ( !this.hasHorizontalScroll ) {\n\t\t\tthis.maxScrollX = 0;\n\t\t\tthis.scrollerWidth = this.wrapperWidth;\n\t\t}\n\n\t\tif ( !this.hasVerticalScroll ) {\n\t\t\tthis.maxScrollY = 0;\n\t\t\tthis.scrollerHeight = this.wrapperHeight;\n\t\t}\n\n\t\tthis.endTime = 0;\n\t\tthis.directionX = 0;\n\t\tthis.directionY = 0;\n\n\t\tthis.wrapperOffset = utils.offset(this.wrapper);\n\n\t\tthis._execEvent('refresh');\n\n\t\tthis.resetPosition();\n\n// INSERT POINT: _refresh\n\n\t},\n\n\ton: function (type, fn) {\n\t\tif ( !this._events[type] ) {\n\t\t\tthis._events[type] = [];\n\t\t}\n\n\t\tthis._events[type].push(fn);\n\t},\n\n\toff: function (type, fn) {\n\t\tif ( !this._events[type] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar index = this._events[type].indexOf(fn);\n\n\t\tif ( index > -1 ) {\n\t\t\tthis._events[type].splice(index, 1);\n\t\t}\n\t},\n\n\t_execEvent: function (type) {\n\t\tif ( !this._events[type] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar i = 0,\n\t\t\tl = this._events[type].length;\n\n\t\tif ( !l ) {\n\t\t\treturn;\n\t\t}\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tthis._events[type][i].apply(this, [].slice.call(arguments, 1));\n\t\t}\n\t},\n\n\tscrollBy: function (x, y, time, easing) {\n\t\tx = this.x + x;\n\t\ty = this.y + y;\n\t\ttime = time || 0;\n\n\t\tthis.scrollTo(x, y, time, easing);\n\t},\n\n\tscrollTo: function (x, y, time, easing) {\n\t\teasing = easing || utils.ease.circular;\n\n\t\tthis.isInTransition = this.options.useTransition && time > 0;\n\t\tvar transitionType = this.options.useTransition && easing.style;\n\t\tif ( !time || transitionType ) {\n\t\t\t\tif(transitionType) {\n\t\t\t\t\tthis._transitionTimingFunction(easing.style);\n\t\t\t\t\tthis._transitionTime(time);\n\t\t\t\t}\n\t\t\tthis._translate(x, y);\n\t\t} else {\n\t\t\tthis._animate(x, y, time, easing.fn);\n\t\t}\n\t},\n\n\tscrollToElement: function (el, time, offsetX, offsetY, easing) {\n\t\tel = el.nodeType ? el : this.scroller.querySelector(el);\n\n\t\tif ( !el ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar pos = utils.offset(el);\n\n\t\tpos.left -= this.wrapperOffset.left;\n\t\tpos.top  -= this.wrapperOffset.top;\n\n\t\t// if offsetX/Y are true we center the element to the screen\n\t\tif ( offsetX === true ) {\n\t\t\toffsetX = Math.round(el.offsetWidth / 2 - this.wrapper.offsetWidth / 2);\n\t\t}\n\t\tif ( offsetY === true ) {\n\t\t\toffsetY = Math.round(el.offsetHeight / 2 - this.wrapper.offsetHeight / 2);\n\t\t}\n\n\t\tpos.left -= offsetX || 0;\n\t\tpos.top  -= offsetY || 0;\n\n\t\tpos.left = pos.left > 0 ? 0 : pos.left < this.maxScrollX ? this.maxScrollX : pos.left;\n\t\tpos.top  = pos.top  > 0 ? 0 : pos.top  < this.maxScrollY ? this.maxScrollY : pos.top;\n\n\t\ttime = time === undefined || time === null || time === 'auto' ? Math.max(Math.abs(this.x-pos.left), Math.abs(this.y-pos.top)) : time;\n\n\t\tthis.scrollTo(pos.left, pos.top, time, easing);\n\t},\n\n\t_transitionTime: function (time) {\n\t\tif (!this.options.useTransition) {\n\t\t\treturn;\n\t\t}\n\t\ttime = time || 0;\n\t\tvar durationProp = utils.style.transitionDuration;\n\t\tif(!durationProp) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.scrollerStyle[durationProp] = time + 'ms';\n\n\t\tif ( !time && utils.isBadAndroid ) {\n\t\t\tthis.scrollerStyle[durationProp] = '0.0001ms';\n\t\t\t// remove 0.0001ms\n\t\t\tvar self = this;\n\t\t\trAF(function() {\n\t\t\t\tif(self.scrollerStyle[durationProp] === '0.0001ms') {\n\t\t\t\t\tself.scrollerStyle[durationProp] = '0s';\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\n\t\tif ( this.indicators ) {\n\t\t\tfor ( var i = this.indicators.length; i--; ) {\n\t\t\t\tthis.indicators[i].transitionTime(time);\n\t\t\t}\n\t\t}\n\n\n// INSERT POINT: _transitionTime\n\n\t},\n\n\t_transitionTimingFunction: function (easing) {\n\t\tthis.scrollerStyle[utils.style.transitionTimingFunction] = easing;\n\n\n\t\tif ( this.indicators ) {\n\t\t\tfor ( var i = this.indicators.length; i--; ) {\n\t\t\t\tthis.indicators[i].transitionTimingFunction(easing);\n\t\t\t}\n\t\t}\n\n\n// INSERT POINT: _transitionTimingFunction\n\n\t},\n\n\t_translate: function (x, y) {\n\t\tif ( this.options.useTransform ) {\n\n/* REPLACE START: _translate */\n\n\t\t\tthis.scrollerStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.translateZ;\n\n/* REPLACE END: _translate */\n\n\t\t} else {\n\t\t\tx = Math.round(x);\n\t\t\ty = Math.round(y);\n\t\t\tthis.scrollerStyle.left = x + 'px';\n\t\t\tthis.scrollerStyle.top = y + 'px';\n\t\t}\n\n\t\tthis.x = x;\n\t\tthis.y = y;\n\n\n\tif ( this.indicators ) {\n\t\tfor ( var i = this.indicators.length; i--; ) {\n\t\t\tthis.indicators[i].updatePosition();\n\t\t}\n\t}\n\n\n// INSERT POINT: _translate\n\n\t},\n\n\t_initEvents: function (remove) {\n\t\tvar eventType = remove ? utils.removeEvent : utils.addEvent,\n\t\t\ttarget = this.options.bindToWrapper ? this.wrapper : window;\n\n\t\teventType(window, 'orientationchange', this);\n\t\teventType(window, 'resize', this);\n\n\t\tif ( this.options.click ) {\n\t\t\teventType(this.wrapper, 'click', this, true);\n\t\t}\n\n\t\tif ( !this.options.disableMouse ) {\n\t\t\teventType(this.wrapper, 'mousedown', this);\n\t\t\teventType(target, 'mousemove', this);\n\t\t\teventType(target, 'mousecancel', this);\n\t\t\teventType(target, 'mouseup', this);\n\t\t}\n\n\t\tif ( utils.hasPointer && !this.options.disablePointer ) {\n\t\t\teventType(this.wrapper, utils.prefixPointerEvent('pointerdown'), this);\n\t\t\teventType(target, utils.prefixPointerEvent('pointermove'), this);\n\t\t\teventType(target, utils.prefixPointerEvent('pointercancel'), this);\n\t\t\teventType(target, utils.prefixPointerEvent('pointerup'), this);\n\t\t}\n\n\t\tif ( utils.hasTouch && !this.options.disableTouch ) {\n\t\t\teventType(this.wrapper, 'touchstart', this);\n\t\t\teventType(target, 'touchmove', this);\n\t\t\teventType(target, 'touchcancel', this);\n\t\t\teventType(target, 'touchend', this);\n\t\t}\n\n\t\teventType(this.scroller, 'transitionend', this);\n\t\teventType(this.scroller, 'webkitTransitionEnd', this);\n\t\teventType(this.scroller, 'oTransitionEnd', this);\n\t\teventType(this.scroller, 'MSTransitionEnd', this);\n\t},\n\n\tgetComputedPosition: function () {\n\t\tvar matrix = window.getComputedStyle(this.scroller, null),\n\t\t\tx, y;\n\n\t\tif ( this.options.useTransform ) {\n\t\t\tmatrix = matrix[utils.style.transform].split(')')[0].split(', ');\n\t\t\tx = +(matrix[12] || matrix[4]);\n\t\t\ty = +(matrix[13] || matrix[5]);\n\t\t} else {\n\t\t\tx = +matrix.left.replace(/[^-\\d.]/g, '');\n\t\t\ty = +matrix.top.replace(/[^-\\d.]/g, '');\n\t\t}\n\n\t\treturn { x: x, y: y };\n\t},\n\t_initIndicators: function () {\n\t\tvar interactive = this.options.interactiveScrollbars,\n\t\t\tcustomStyle = typeof this.options.scrollbars != 'string',\n\t\t\tindicators = [],\n\t\t\tindicator;\n\n\t\tvar that = this;\n\n\t\tthis.indicators = [];\n\n\t\tif ( this.options.scrollbars ) {\n\t\t\t// Vertical scrollbar\n\t\t\tif ( this.options.scrollY ) {\n\t\t\t\tindicator = {\n\t\t\t\t\tel: createDefaultScrollbar('v', interactive, this.options.scrollbars),\n\t\t\t\t\tinteractive: interactive,\n\t\t\t\t\tdefaultScrollbars: true,\n\t\t\t\t\tcustomStyle: customStyle,\n\t\t\t\t\tresize: this.options.resizeScrollbars,\n\t\t\t\t\tshrink: this.options.shrinkScrollbars,\n\t\t\t\t\tfade: this.options.fadeScrollbars,\n\t\t\t\t\tlistenX: false\n\t\t\t\t};\n\n\t\t\t\tthis.wrapper.appendChild(indicator.el);\n\t\t\t\tindicators.push(indicator);\n\t\t\t}\n\n\t\t\t// Horizontal scrollbar\n\t\t\tif ( this.options.scrollX ) {\n\t\t\t\tindicator = {\n\t\t\t\t\tel: createDefaultScrollbar('h', interactive, this.options.scrollbars),\n\t\t\t\t\tinteractive: interactive,\n\t\t\t\t\tdefaultScrollbars: true,\n\t\t\t\t\tcustomStyle: customStyle,\n\t\t\t\t\tresize: this.options.resizeScrollbars,\n\t\t\t\t\tshrink: this.options.shrinkScrollbars,\n\t\t\t\t\tfade: this.options.fadeScrollbars,\n\t\t\t\t\tlistenY: false\n\t\t\t\t};\n\n\t\t\t\tthis.wrapper.appendChild(indicator.el);\n\t\t\t\tindicators.push(indicator);\n\t\t\t}\n\t\t}\n\n\t\tif ( this.options.indicators ) {\n\t\t\t// TODO: check concat compatibility\n\t\t\tindicators = indicators.concat(this.options.indicators);\n\t\t}\n\n\t\tfor ( var i = indicators.length; i--; ) {\n\t\t\tthis.indicators.push( new Indicator(this, indicators[i]) );\n\t\t}\n\n\t\t// TODO: check if we can use array.map (wide compatibility and performance issues)\n\t\tfunction _indicatorsMap (fn) {\n\t\t\tif (that.indicators) {\n\t\t\t\tfor ( var i = that.indicators.length; i--; ) {\n\t\t\t\t\tfn.call(that.indicators[i]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( this.options.fadeScrollbars ) {\n\t\t\tthis.on('scrollEnd', function () {\n\t\t\t\t_indicatorsMap(function () {\n\t\t\t\t\tthis.fade();\n\t\t\t\t});\n\t\t\t});\n\n\t\t\tthis.on('scrollCancel', function () {\n\t\t\t\t_indicatorsMap(function () {\n\t\t\t\t\tthis.fade();\n\t\t\t\t});\n\t\t\t});\n\n\t\t\tthis.on('scrollStart', function () {\n\t\t\t\t_indicatorsMap(function () {\n\t\t\t\t\tthis.fade(1);\n\t\t\t\t});\n\t\t\t});\n\n\t\t\tthis.on('beforeScrollStart', function () {\n\t\t\t\t_indicatorsMap(function () {\n\t\t\t\t\tthis.fade(1, true);\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\n\n\t\tthis.on('refresh', function () {\n\t\t\t_indicatorsMap(function () {\n\t\t\t\tthis.refresh();\n\t\t\t});\n\t\t});\n\n\t\tthis.on('destroy', function () {\n\t\t\t_indicatorsMap(function () {\n\t\t\t\tthis.destroy();\n\t\t\t});\n\n\t\t\tdelete this.indicators;\n\t\t});\n\t},\n\n\t_initWheel: function () {\n\t\tutils.addEvent(this.wrapper, 'wheel', this);\n\t\tutils.addEvent(this.wrapper, 'mousewheel', this);\n\t\tutils.addEvent(this.wrapper, 'DOMMouseScroll', this);\n\n\t\tthis.on('destroy', function () {\n\t\t\tclearTimeout(this.wheelTimeout);\n\t\t\tthis.wheelTimeout = null;\n\t\t\tutils.removeEvent(this.wrapper, 'wheel', this);\n\t\t\tutils.removeEvent(this.wrapper, 'mousewheel', this);\n\t\t\tutils.removeEvent(this.wrapper, 'DOMMouseScroll', this);\n\t\t});\n\t},\n\n\t_wheel: function (e) {\n\t\tif ( !this.enabled ) {\n\t\t\treturn;\n\t\t}\n\n\t\te.preventDefault();\n\n\t\tvar wheelDeltaX, wheelDeltaY,\n\t\t\tnewX, newY,\n\t\t\tthat = this;\n\n\t\tif ( this.wheelTimeout === undefined ) {\n\t\t\tthat._execEvent('scrollStart');\n\t\t}\n\n\t\t// Execute the scrollEnd event after 400ms the wheel stopped scrolling\n\t\tclearTimeout(this.wheelTimeout);\n\t\tthis.wheelTimeout = setTimeout(function () {\n\t\t\tif(!that.options.snap) {\n\t\t\t\tthat._execEvent('scrollEnd');\n\t\t\t}\n\t\t\tthat.wheelTimeout = undefined;\n\t\t}, 400);\n\n\t\tif ( 'deltaX' in e ) {\n\t\t\tif (e.deltaMode === 1) {\n\t\t\t\twheelDeltaX = -e.deltaX * this.options.mouseWheelSpeed;\n\t\t\t\twheelDeltaY = -e.deltaY * this.options.mouseWheelSpeed;\n\t\t\t} else {\n\t\t\t\twheelDeltaX = -e.deltaX;\n\t\t\t\twheelDeltaY = -e.deltaY;\n\t\t\t}\n\t\t} else if ( 'wheelDeltaX' in e ) {\n\t\t\twheelDeltaX = e.wheelDeltaX / 120 * this.options.mouseWheelSpeed;\n\t\t\twheelDeltaY = e.wheelDeltaY / 120 * this.options.mouseWheelSpeed;\n\t\t} else if ( 'wheelDelta' in e ) {\n\t\t\twheelDeltaX = wheelDeltaY = e.wheelDelta / 120 * this.options.mouseWheelSpeed;\n\t\t} else if ( 'detail' in e ) {\n\t\t\twheelDeltaX = wheelDeltaY = -e.detail / 3 * this.options.mouseWheelSpeed;\n\t\t} else {\n\t\t\treturn;\n\t\t}\n\n\t\twheelDeltaX *= this.options.invertWheelDirection;\n\t\twheelDeltaY *= this.options.invertWheelDirection;\n\n\t\tif ( !this.hasVerticalScroll ) {\n\t\t\twheelDeltaX = wheelDeltaY;\n\t\t\twheelDeltaY = 0;\n\t\t}\n\n\t\tif ( this.options.snap ) {\n\t\t\tnewX = this.currentPage.pageX;\n\t\t\tnewY = this.currentPage.pageY;\n\n\t\t\tif ( wheelDeltaX > 0 ) {\n\t\t\t\tnewX--;\n\t\t\t} else if ( wheelDeltaX < 0 ) {\n\t\t\t\tnewX++;\n\t\t\t}\n\n\t\t\tif ( wheelDeltaY > 0 ) {\n\t\t\t\tnewY--;\n\t\t\t} else if ( wheelDeltaY < 0 ) {\n\t\t\t\tnewY++;\n\t\t\t}\n\n\t\t\tthis.goToPage(newX, newY);\n\n\t\t\treturn;\n\t\t}\n\n\t\tnewX = this.x + Math.round(this.hasHorizontalScroll ? wheelDeltaX : 0);\n\t\tnewY = this.y + Math.round(this.hasVerticalScroll ? wheelDeltaY : 0);\n\n\t\tthis.directionX = wheelDeltaX > 0 ? -1 : wheelDeltaX < 0 ? 1 : 0;\n\t\tthis.directionY = wheelDeltaY > 0 ? -1 : wheelDeltaY < 0 ? 1 : 0;\n\n\t\tif ( newX > 0 ) {\n\t\t\tnewX = 0;\n\t\t} else if ( newX < this.maxScrollX ) {\n\t\t\tnewX = this.maxScrollX;\n\t\t}\n\n\t\tif ( newY > 0 ) {\n\t\t\tnewY = 0;\n\t\t} else if ( newY < this.maxScrollY ) {\n\t\t\tnewY = this.maxScrollY;\n\t\t}\n\n\t\tthis.scrollTo(newX, newY, 0);\n\n// INSERT POINT: _wheel\n\t},\n\n\t_initSnap: function () {\n\t\tthis.currentPage = {};\n\n\t\tif ( typeof this.options.snap == 'string' ) {\n\t\t\tthis.options.snap = this.scroller.querySelectorAll(this.options.snap);\n\t\t}\n\n\t\tthis.on('refresh', function () {\n\t\t\tvar i = 0, l,\n\t\t\t\tm = 0, n,\n\t\t\t\tcx, cy,\n\t\t\t\tx = 0, y,\n\t\t\t\tstepX = this.options.snapStepX || this.wrapperWidth,\n\t\t\t\tstepY = this.options.snapStepY || this.wrapperHeight,\n\t\t\t\tel;\n\n\t\t\tthis.pages = [];\n\n\t\t\tif ( !this.wrapperWidth || !this.wrapperHeight || !this.scrollerWidth || !this.scrollerHeight ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( this.options.snap === true ) {\n\t\t\t\tcx = Math.round( stepX / 2 );\n\t\t\t\tcy = Math.round( stepY / 2 );\n\n\t\t\t\twhile ( x > -this.scrollerWidth ) {\n\t\t\t\t\tthis.pages[i] = [];\n\t\t\t\t\tl = 0;\n\t\t\t\t\ty = 0;\n\n\t\t\t\t\twhile ( y > -this.scrollerHeight ) {\n\t\t\t\t\t\tthis.pages[i][l] = {\n\t\t\t\t\t\t\tx: Math.max(x, this.maxScrollX),\n\t\t\t\t\t\t\ty: Math.max(y, this.maxScrollY),\n\t\t\t\t\t\t\twidth: stepX,\n\t\t\t\t\t\t\theight: stepY,\n\t\t\t\t\t\t\tcx: x - cx,\n\t\t\t\t\t\t\tcy: y - cy\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\ty -= stepY;\n\t\t\t\t\t\tl++;\n\t\t\t\t\t}\n\n\t\t\t\t\tx -= stepX;\n\t\t\t\t\ti++;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tel = this.options.snap;\n\t\t\t\tl = el.length;\n\t\t\t\tn = -1;\n\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\tif ( i === 0 || el[i].offsetLeft <= el[i-1].offsetLeft ) {\n\t\t\t\t\t\tm = 0;\n\t\t\t\t\t\tn++;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( !this.pages[m] ) {\n\t\t\t\t\t\tthis.pages[m] = [];\n\t\t\t\t\t}\n\n\t\t\t\t\tx = Math.max(-el[i].offsetLeft, this.maxScrollX);\n\t\t\t\t\ty = Math.max(-el[i].offsetTop, this.maxScrollY);\n\t\t\t\t\tcx = x - Math.round(el[i].offsetWidth / 2);\n\t\t\t\t\tcy = y - Math.round(el[i].offsetHeight / 2);\n\n\t\t\t\t\tthis.pages[m][n] = {\n\t\t\t\t\t\tx: x,\n\t\t\t\t\t\ty: y,\n\t\t\t\t\t\twidth: el[i].offsetWidth,\n\t\t\t\t\t\theight: el[i].offsetHeight,\n\t\t\t\t\t\tcx: cx,\n\t\t\t\t\t\tcy: cy\n\t\t\t\t\t};\n\n\t\t\t\t\tif ( x > this.maxScrollX ) {\n\t\t\t\t\t\tm++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.goToPage(this.currentPage.pageX || 0, this.currentPage.pageY || 0, 0);\n\n\t\t\t// Update snap threshold if needed\n\t\t\tif ( this.options.snapThreshold % 1 === 0 ) {\n\t\t\t\tthis.snapThresholdX = this.options.snapThreshold;\n\t\t\t\tthis.snapThresholdY = this.options.snapThreshold;\n\t\t\t} else {\n\t\t\t\tthis.snapThresholdX = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].width * this.options.snapThreshold);\n\t\t\t\tthis.snapThresholdY = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].height * this.options.snapThreshold);\n\t\t\t}\n\t\t});\n\n\t\tthis.on('flick', function () {\n\t\t\tvar time = this.options.snapSpeed || Math.max(\n\t\t\t\t\tMath.max(\n\t\t\t\t\t\tMath.min(Math.abs(this.x - this.startX), 1000),\n\t\t\t\t\t\tMath.min(Math.abs(this.y - this.startY), 1000)\n\t\t\t\t\t), 300);\n\n\t\t\tthis.goToPage(\n\t\t\t\tthis.currentPage.pageX + this.directionX,\n\t\t\t\tthis.currentPage.pageY + this.directionY,\n\t\t\t\ttime\n\t\t\t);\n\t\t});\n\t},\n\n\t_nearestSnap: function (x, y) {\n\t\tif ( !this.pages.length ) {\n\t\t\treturn { x: 0, y: 0, pageX: 0, pageY: 0 };\n\t\t}\n\n\t\tvar i = 0,\n\t\t\tl = this.pages.length,\n\t\t\tm = 0;\n\n\t\t// Check if we exceeded the snap threshold\n\t\tif ( Math.abs(x - this.absStartX) < this.snapThresholdX &&\n\t\t\tMath.abs(y - this.absStartY) < this.snapThresholdY ) {\n\t\t\treturn this.currentPage;\n\t\t}\n\n\t\tif ( x > 0 ) {\n\t\t\tx = 0;\n\t\t} else if ( x < this.maxScrollX ) {\n\t\t\tx = this.maxScrollX;\n\t\t}\n\n\t\tif ( y > 0 ) {\n\t\t\ty = 0;\n\t\t} else if ( y < this.maxScrollY ) {\n\t\t\ty = this.maxScrollY;\n\t\t}\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tif ( x >= this.pages[i][0].cx ) {\n\t\t\t\tx = this.pages[i][0].x;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tl = this.pages[i].length;\n\n\t\tfor ( ; m < l; m++ ) {\n\t\t\tif ( y >= this.pages[0][m].cy ) {\n\t\t\t\ty = this.pages[0][m].y;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif ( i == this.currentPage.pageX ) {\n\t\t\ti += this.directionX;\n\n\t\t\tif ( i < 0 ) {\n\t\t\t\ti = 0;\n\t\t\t} else if ( i >= this.pages.length ) {\n\t\t\t\ti = this.pages.length - 1;\n\t\t\t}\n\n\t\t\tx = this.pages[i][0].x;\n\t\t}\n\n\t\tif ( m == this.currentPage.pageY ) {\n\t\t\tm += this.directionY;\n\n\t\t\tif ( m < 0 ) {\n\t\t\t\tm = 0;\n\t\t\t} else if ( m >= this.pages[0].length ) {\n\t\t\t\tm = this.pages[0].length - 1;\n\t\t\t}\n\n\t\t\ty = this.pages[0][m].y;\n\t\t}\n\n\t\treturn {\n\t\t\tx: x,\n\t\t\ty: y,\n\t\t\tpageX: i,\n\t\t\tpageY: m\n\t\t};\n\t},\n\n\tgoToPage: function (x, y, time, easing) {\n\t\teasing = easing || this.options.bounceEasing;\n\n\t\tif ( x >= this.pages.length ) {\n\t\t\tx = this.pages.length - 1;\n\t\t} else if ( x < 0 ) {\n\t\t\tx = 0;\n\t\t}\n\n\t\tif ( y >= this.pages[x].length ) {\n\t\t\ty = this.pages[x].length - 1;\n\t\t} else if ( y < 0 ) {\n\t\t\ty = 0;\n\t\t}\n\n\t\tvar posX = this.pages[x][y].x,\n\t\t\tposY = this.pages[x][y].y;\n\n\t\ttime = time === undefined ? this.options.snapSpeed || Math.max(\n\t\t\tMath.max(\n\t\t\t\tMath.min(Math.abs(posX - this.x), 1000),\n\t\t\t\tMath.min(Math.abs(posY - this.y), 1000)\n\t\t\t), 300) : time;\n\n\t\tthis.currentPage = {\n\t\t\tx: posX,\n\t\t\ty: posY,\n\t\t\tpageX: x,\n\t\t\tpageY: y\n\t\t};\n\n\t\tthis.scrollTo(posX, posY, time, easing);\n\t},\n\n\tnext: function (time, easing) {\n\t\tvar x = this.currentPage.pageX,\n\t\t\ty = this.currentPage.pageY;\n\n\t\tx++;\n\n\t\tif ( x >= this.pages.length && this.hasVerticalScroll ) {\n\t\t\tx = 0;\n\t\t\ty++;\n\t\t}\n\n\t\tthis.goToPage(x, y, time, easing);\n\t},\n\n\tprev: function (time, easing) {\n\t\tvar x = this.currentPage.pageX,\n\t\t\ty = this.currentPage.pageY;\n\n\t\tx--;\n\n\t\tif ( x < 0 && this.hasVerticalScroll ) {\n\t\t\tx = 0;\n\t\t\ty--;\n\t\t}\n\n\t\tthis.goToPage(x, y, time, easing);\n\t},\n\n\t_initKeys: function (e) {\n\t\t// default key bindings\n\t\tvar keys = {\n\t\t\tpageUp: 33,\n\t\t\tpageDown: 34,\n\t\t\tend: 35,\n\t\t\thome: 36,\n\t\t\tleft: 37,\n\t\t\tup: 38,\n\t\t\tright: 39,\n\t\t\tdown: 40\n\t\t};\n\t\tvar i;\n\n\t\t// if you give me characters I give you keycode\n\t\tif ( typeof this.options.keyBindings == 'object' ) {\n\t\t\tfor ( i in this.options.keyBindings ) {\n\t\t\t\tif ( typeof this.options.keyBindings[i] == 'string' ) {\n\t\t\t\t\tthis.options.keyBindings[i] = this.options.keyBindings[i].toUpperCase().charCodeAt(0);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthis.options.keyBindings = {};\n\t\t}\n\n\t\tfor ( i in keys ) {\n\t\t\tthis.options.keyBindings[i] = this.options.keyBindings[i] || keys[i];\n\t\t}\n\n\t\tutils.addEvent(window, 'keydown', this);\n\n\t\tthis.on('destroy', function () {\n\t\t\tutils.removeEvent(window, 'keydown', this);\n\t\t});\n\t},\n\n\t_key: function (e) {\n\t\tif ( !this.enabled ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar snap = this.options.snap,\t// we are using this alot, better to cache it\n\t\t\tnewX = snap ? this.currentPage.pageX : this.x,\n\t\t\tnewY = snap ? this.currentPage.pageY : this.y,\n\t\t\tnow = utils.getTime(),\n\t\t\tprevTime = this.keyTime || 0,\n\t\t\tacceleration = 0.250,\n\t\t\tpos;\n\n\t\tif ( this.options.useTransition && this.isInTransition ) {\n\t\t\tpos = this.getComputedPosition();\n\n\t\t\tthis._translate(Math.round(pos.x), Math.round(pos.y));\n\t\t\tthis.isInTransition = false;\n\t\t}\n\n\t\tthis.keyAcceleration = now - prevTime < 200 ? Math.min(this.keyAcceleration + acceleration, 50) : 0;\n\n\t\tswitch ( e.keyCode ) {\n\t\t\tcase this.options.keyBindings.pageUp:\n\t\t\t\tif ( this.hasHorizontalScroll && !this.hasVerticalScroll ) {\n\t\t\t\t\tnewX += snap ? 1 : this.wrapperWidth;\n\t\t\t\t} else {\n\t\t\t\t\tnewY += snap ? 1 : this.wrapperHeight;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase this.options.keyBindings.pageDown:\n\t\t\t\tif ( this.hasHorizontalScroll && !this.hasVerticalScroll ) {\n\t\t\t\t\tnewX -= snap ? 1 : this.wrapperWidth;\n\t\t\t\t} else {\n\t\t\t\t\tnewY -= snap ? 1 : this.wrapperHeight;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase this.options.keyBindings.end:\n\t\t\t\tnewX = snap ? this.pages.length-1 : this.maxScrollX;\n\t\t\t\tnewY = snap ? this.pages[0].length-1 : this.maxScrollY;\n\t\t\t\tbreak;\n\t\t\tcase this.options.keyBindings.home:\n\t\t\t\tnewX = 0;\n\t\t\t\tnewY = 0;\n\t\t\t\tbreak;\n\t\t\tcase this.options.keyBindings.left:\n\t\t\t\tnewX += snap ? -1 : 5 + this.keyAcceleration>>0;\n\t\t\t\tbreak;\n\t\t\tcase this.options.keyBindings.up:\n\t\t\t\tnewY += snap ? 1 : 5 + this.keyAcceleration>>0;\n\t\t\t\tbreak;\n\t\t\tcase this.options.keyBindings.right:\n\t\t\t\tnewX -= snap ? -1 : 5 + this.keyAcceleration>>0;\n\t\t\t\tbreak;\n\t\t\tcase this.options.keyBindings.down:\n\t\t\t\tnewY -= snap ? 1 : 5 + this.keyAcceleration>>0;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\treturn;\n\t\t}\n\n\t\tif ( snap ) {\n\t\t\tthis.goToPage(newX, newY);\n\t\t\treturn;\n\t\t}\n\n\t\tif ( newX > 0 ) {\n\t\t\tnewX = 0;\n\t\t\tthis.keyAcceleration = 0;\n\t\t} else if ( newX < this.maxScrollX ) {\n\t\t\tnewX = this.maxScrollX;\n\t\t\tthis.keyAcceleration = 0;\n\t\t}\n\n\t\tif ( newY > 0 ) {\n\t\t\tnewY = 0;\n\t\t\tthis.keyAcceleration = 0;\n\t\t} else if ( newY < this.maxScrollY ) {\n\t\t\tnewY = this.maxScrollY;\n\t\t\tthis.keyAcceleration = 0;\n\t\t}\n\n\t\tthis.scrollTo(newX, newY, 0);\n\n\t\tthis.keyTime = now;\n\t},\n\n\t_animate: function (destX, destY, duration, easingFn) {\n\t\tvar that = this,\n\t\t\tstartX = this.x,\n\t\t\tstartY = this.y,\n\t\t\tstartTime = utils.getTime(),\n\t\t\tdestTime = startTime + duration;\n\n\t\tfunction step () {\n\t\t\tvar now = utils.getTime(),\n\t\t\t\tnewX, newY,\n\t\t\t\teasing;\n\n\t\t\tif ( now >= destTime ) {\n\t\t\t\tthat.isAnimating = false;\n\t\t\t\tthat._translate(destX, destY);\n\n\t\t\t\tif ( !that.resetPosition(that.options.bounceTime) ) {\n\t\t\t\t\tthat._execEvent('scrollEnd');\n\t\t\t\t}\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tnow = ( now - startTime ) / duration;\n\t\t\teasing = easingFn(now);\n\t\t\tnewX = ( destX - startX ) * easing + startX;\n\t\t\tnewY = ( destY - startY ) * easing + startY;\n\t\t\tthat._translate(newX, newY);\n\n\t\t\tif ( that.isAnimating ) {\n\t\t\t\trAF(step);\n\t\t\t}\n\t\t}\n\n\t\tthis.isAnimating = true;\n\t\tstep();\n\t},\n\thandleEvent: function (e) {\n\t\tswitch ( e.type ) {\n\t\t\tcase 'touchstart':\n\t\t\tcase 'pointerdown':\n\t\t\tcase 'MSPointerDown':\n\t\t\tcase 'mousedown':\n\t\t\t\tthis._start(e);\n\t\t\t\tbreak;\n\t\t\tcase 'touchmove':\n\t\t\tcase 'pointermove':\n\t\t\tcase 'MSPointerMove':\n\t\t\tcase 'mousemove':\n\t\t\t\tthis._move(e);\n\t\t\t\tbreak;\n\t\t\tcase 'touchend':\n\t\t\tcase 'pointerup':\n\t\t\tcase 'MSPointerUp':\n\t\t\tcase 'mouseup':\n\t\t\tcase 'touchcancel':\n\t\t\tcase 'pointercancel':\n\t\t\tcase 'MSPointerCancel':\n\t\t\tcase 'mousecancel':\n\t\t\t\tthis._end(e);\n\t\t\t\tbreak;\n\t\t\tcase 'orientationchange':\n\t\t\tcase 'resize':\n\t\t\t\tthis._resize();\n\t\t\t\tbreak;\n\t\t\tcase 'transitionend':\n\t\t\tcase 'webkitTransitionEnd':\n\t\t\tcase 'oTransitionEnd':\n\t\t\tcase 'MSTransitionEnd':\n\t\t\t\tthis._transitionEnd(e);\n\t\t\t\tbreak;\n\t\t\tcase 'wheel':\n\t\t\tcase 'DOMMouseScroll':\n\t\t\tcase 'mousewheel':\n\t\t\t\tthis._wheel(e);\n\t\t\t\tbreak;\n\t\t\tcase 'keydown':\n\t\t\t\tthis._key(e);\n\t\t\t\tbreak;\n\t\t\tcase 'click':\n\t\t\t\tif ( this.enabled && !e._constructed ) {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\te.stopPropagation();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n};\nfunction createDefaultScrollbar (direction, interactive, type) {\n\tvar scrollbar = document.createElement('div'),\n\t\tindicator = document.createElement('div');\n\n\tif ( type === true ) {\n\t\tscrollbar.style.cssText = 'position:absolute;z-index:9999';\n\t\tindicator.style.cssText = '-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;position:absolute;background:rgba(0,0,0,0.5);border:1px solid rgba(255,255,255,0.9);border-radius:3px';\n\t}\n\n\tindicator.className = 'iScrollIndicator';\n\n\tif ( direction == 'h' ) {\n\t\tif ( type === true ) {\n\t\t\tscrollbar.style.cssText += ';height:7px;left:2px;right:2px;bottom:0';\n\t\t\tindicator.style.height = '100%';\n\t\t}\n\t\tscrollbar.className = 'iScrollHorizontalScrollbar';\n\t} else {\n\t\tif ( type === true ) {\n\t\t\tscrollbar.style.cssText += ';width:7px;bottom:2px;top:2px;right:1px';\n\t\t\tindicator.style.width = '100%';\n\t\t}\n\t\tscrollbar.className = 'iScrollVerticalScrollbar';\n\t}\n\n\tscrollbar.style.cssText += ';overflow:hidden';\n\n\tif ( !interactive ) {\n\t\tscrollbar.style.pointerEvents = 'none';\n\t}\n\n\tscrollbar.appendChild(indicator);\n\n\treturn scrollbar;\n}\n\nfunction Indicator (scroller, options) {\n\tthis.wrapper = typeof options.el == 'string' ? document.querySelector(options.el) : options.el;\n\tthis.wrapperStyle = this.wrapper.style;\n\tthis.indicator = this.wrapper.children[0];\n\tthis.indicatorStyle = this.indicator.style;\n\tthis.scroller = scroller;\n\n\tthis.options = {\n\t\tlistenX: true,\n\t\tlistenY: true,\n\t\tinteractive: false,\n\t\tresize: true,\n\t\tdefaultScrollbars: false,\n\t\tshrink: false,\n\t\tfade: false,\n\t\tspeedRatioX: 0,\n\t\tspeedRatioY: 0\n\t};\n\n\tfor ( var i in options ) {\n\t\tthis.options[i] = options[i];\n\t}\n\n\tthis.sizeRatioX = 1;\n\tthis.sizeRatioY = 1;\n\tthis.maxPosX = 0;\n\tthis.maxPosY = 0;\n\n\tif ( this.options.interactive ) {\n\t\tif ( !this.options.disableTouch ) {\n\t\t\tutils.addEvent(this.indicator, 'touchstart', this);\n\t\t\tutils.addEvent(window, 'touchend', this);\n\t\t}\n\t\tif ( !this.options.disablePointer ) {\n\t\t\tutils.addEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this);\n\t\t\tutils.addEvent(window, utils.prefixPointerEvent('pointerup'), this);\n\t\t}\n\t\tif ( !this.options.disableMouse ) {\n\t\t\tutils.addEvent(this.indicator, 'mousedown', this);\n\t\t\tutils.addEvent(window, 'mouseup', this);\n\t\t}\n\t}\n\n\tif ( this.options.fade ) {\n\t\tthis.wrapperStyle[utils.style.transform] = this.scroller.translateZ;\n\t\tvar durationProp = utils.style.transitionDuration;\n\t\tif(!durationProp) {\n\t\t\treturn;\n\t\t}\n\t\tthis.wrapperStyle[durationProp] = utils.isBadAndroid ? '0.0001ms' : '0ms';\n\t\t// remove 0.0001ms\n\t\tvar self = this;\n\t\tif(utils.isBadAndroid) {\n\t\t\trAF(function() {\n\t\t\t\tif(self.wrapperStyle[durationProp] === '0.0001ms') {\n\t\t\t\t\tself.wrapperStyle[durationProp] = '0s';\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\tthis.wrapperStyle.opacity = '0';\n\t}\n}\n\nIndicator.prototype = {\n\thandleEvent: function (e) {\n\t\tswitch ( e.type ) {\n\t\t\tcase 'touchstart':\n\t\t\tcase 'pointerdown':\n\t\t\tcase 'MSPointerDown':\n\t\t\tcase 'mousedown':\n\t\t\t\tthis._start(e);\n\t\t\t\tbreak;\n\t\t\tcase 'touchmove':\n\t\t\tcase 'pointermove':\n\t\t\tcase 'MSPointerMove':\n\t\t\tcase 'mousemove':\n\t\t\t\tthis._move(e);\n\t\t\t\tbreak;\n\t\t\tcase 'touchend':\n\t\t\tcase 'pointerup':\n\t\t\tcase 'MSPointerUp':\n\t\t\tcase 'mouseup':\n\t\t\tcase 'touchcancel':\n\t\t\tcase 'pointercancel':\n\t\t\tcase 'MSPointerCancel':\n\t\t\tcase 'mousecancel':\n\t\t\t\tthis._end(e);\n\t\t\t\tbreak;\n\t\t}\n\t},\n\n\tdestroy: function () {\n\t\tif ( this.options.fadeScrollbars ) {\n\t\t\tclearTimeout(this.fadeTimeout);\n\t\t\tthis.fadeTimeout = null;\n\t\t}\n\t\tif ( this.options.interactive ) {\n\t\t\tutils.removeEvent(this.indicator, 'touchstart', this);\n\t\t\tutils.removeEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this);\n\t\t\tutils.removeEvent(this.indicator, 'mousedown', this);\n\n\t\t\tutils.removeEvent(window, 'touchmove', this);\n\t\t\tutils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this);\n\t\t\tutils.removeEvent(window, 'mousemove', this);\n\n\t\t\tutils.removeEvent(window, 'touchend', this);\n\t\t\tutils.removeEvent(window, utils.prefixPointerEvent('pointerup'), this);\n\t\t\tutils.removeEvent(window, 'mouseup', this);\n\t\t}\n\n\t\tif ( this.options.defaultScrollbars ) {\n\t\t\tthis.wrapper.parentNode.removeChild(this.wrapper);\n\t\t}\n\t},\n\n\t_start: function (e) {\n\t\tvar point = e.touches ? e.touches[0] : e;\n\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\n\t\tthis.transitionTime();\n\n\t\tthis.initiated = true;\n\t\tthis.moved = false;\n\t\tthis.lastPointX\t= point.pageX;\n\t\tthis.lastPointY\t= point.pageY;\n\n\t\tthis.startTime\t= utils.getTime();\n\n\t\tif ( !this.options.disableTouch ) {\n\t\t\tutils.addEvent(window, 'touchmove', this);\n\t\t}\n\t\tif ( !this.options.disablePointer ) {\n\t\t\tutils.addEvent(window, utils.prefixPointerEvent('pointermove'), this);\n\t\t}\n\t\tif ( !this.options.disableMouse ) {\n\t\t\tutils.addEvent(window, 'mousemove', this);\n\t\t}\n\n\t\tthis.scroller._execEvent('beforeScrollStart');\n\t},\n\n\t_move: function (e) {\n\t\tvar point = e.touches ? e.touches[0] : e,\n\t\t\tdeltaX, deltaY,\n\t\t\tnewX, newY,\n\t\t\ttimestamp = utils.getTime();\n\n\t\tif ( !this.moved ) {\n\t\t\tthis.scroller._execEvent('scrollStart');\n\t\t}\n\n\t\tthis.moved = true;\n\n\t\tdeltaX = point.pageX - this.lastPointX;\n\t\tthis.lastPointX = point.pageX;\n\n\t\tdeltaY = point.pageY - this.lastPointY;\n\t\tthis.lastPointY = point.pageY;\n\n\t\tnewX = this.x + deltaX;\n\t\tnewY = this.y + deltaY;\n\n\t\tthis._pos(newX, newY);\n\n// INSERT POINT: indicator._move\n\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\t},\n\n\t_end: function (e) {\n\t\tif ( !this.initiated ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.initiated = false;\n\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\n\t\tutils.removeEvent(window, 'touchmove', this);\n\t\tutils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this);\n\t\tutils.removeEvent(window, 'mousemove', this);\n\n\t\tif ( this.scroller.options.snap ) {\n\t\t\tvar snap = this.scroller._nearestSnap(this.scroller.x, this.scroller.y);\n\n\t\t\tvar time = this.options.snapSpeed || Math.max(\n\t\t\t\t\tMath.max(\n\t\t\t\t\t\tMath.min(Math.abs(this.scroller.x - snap.x), 1000),\n\t\t\t\t\t\tMath.min(Math.abs(this.scroller.y - snap.y), 1000)\n\t\t\t\t\t), 300);\n\n\t\t\tif ( this.scroller.x != snap.x || this.scroller.y != snap.y ) {\n\t\t\t\tthis.scroller.directionX = 0;\n\t\t\t\tthis.scroller.directionY = 0;\n\t\t\t\tthis.scroller.currentPage = snap;\n\t\t\t\tthis.scroller.scrollTo(snap.x, snap.y, time, this.scroller.options.bounceEasing);\n\t\t\t}\n\t\t}\n\n\t\tif ( this.moved ) {\n\t\t\tthis.scroller._execEvent('scrollEnd');\n\t\t}\n\t},\n\n\ttransitionTime: function (time) {\n\t\ttime = time || 0;\n\t\tvar durationProp = utils.style.transitionDuration;\n\t\tif(!durationProp) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.indicatorStyle[durationProp] = time + 'ms';\n\n\t\tif ( !time && utils.isBadAndroid ) {\n\t\t\tthis.indicatorStyle[durationProp] = '0.0001ms';\n\t\t\t// remove 0.0001ms\n\t\t\tvar self = this;\n\t\t\trAF(function() {\n\t\t\t\tif(self.indicatorStyle[durationProp] === '0.0001ms') {\n\t\t\t\t\tself.indicatorStyle[durationProp] = '0s';\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t},\n\n\ttransitionTimingFunction: function (easing) {\n\t\tthis.indicatorStyle[utils.style.transitionTimingFunction] = easing;\n\t},\n\n\trefresh: function () {\n\t\tthis.transitionTime();\n\n\t\tif ( this.options.listenX && !this.options.listenY ) {\n\t\t\tthis.indicatorStyle.display = this.scroller.hasHorizontalScroll ? 'block' : 'none';\n\t\t} else if ( this.options.listenY && !this.options.listenX ) {\n\t\t\tthis.indicatorStyle.display = this.scroller.hasVerticalScroll ? 'block' : 'none';\n\t\t} else {\n\t\t\tthis.indicatorStyle.display = this.scroller.hasHorizontalScroll || this.scroller.hasVerticalScroll ? 'block' : 'none';\n\t\t}\n\n\t\tif ( this.scroller.hasHorizontalScroll && this.scroller.hasVerticalScroll ) {\n\t\t\tutils.addClass(this.wrapper, 'iScrollBothScrollbars');\n\t\t\tutils.removeClass(this.wrapper, 'iScrollLoneScrollbar');\n\n\t\t\tif ( this.options.defaultScrollbars && this.options.customStyle ) {\n\t\t\t\tif ( this.options.listenX ) {\n\t\t\t\t\tthis.wrapper.style.right = '8px';\n\t\t\t\t} else {\n\t\t\t\t\tthis.wrapper.style.bottom = '8px';\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tutils.removeClass(this.wrapper, 'iScrollBothScrollbars');\n\t\t\tutils.addClass(this.wrapper, 'iScrollLoneScrollbar');\n\n\t\t\tif ( this.options.defaultScrollbars && this.options.customStyle ) {\n\t\t\t\tif ( this.options.listenX ) {\n\t\t\t\t\tthis.wrapper.style.right = '2px';\n\t\t\t\t} else {\n\t\t\t\t\tthis.wrapper.style.bottom = '2px';\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tvar r = this.wrapper.offsetHeight;\t// force refresh\n\n\t\tif ( this.options.listenX ) {\n\t\t\tthis.wrapperWidth = this.wrapper.clientWidth;\n\t\t\tif ( this.options.resize ) {\n\t\t\t\tthis.indicatorWidth = Math.max(Math.round(this.wrapperWidth * this.wrapperWidth / (this.scroller.scrollerWidth || this.wrapperWidth || 1)), 8);\n\t\t\t\tthis.indicatorStyle.width = this.indicatorWidth + 'px';\n\t\t\t} else {\n\t\t\t\tthis.indicatorWidth = this.indicator.clientWidth;\n\t\t\t}\n\n\t\t\tthis.maxPosX = this.wrapperWidth - this.indicatorWidth;\n\n\t\t\tif ( this.options.shrink == 'clip' ) {\n\t\t\t\tthis.minBoundaryX = -this.indicatorWidth + 8;\n\t\t\t\tthis.maxBoundaryX = this.wrapperWidth - 8;\n\t\t\t} else {\n\t\t\t\tthis.minBoundaryX = 0;\n\t\t\t\tthis.maxBoundaryX = this.maxPosX;\n\t\t\t}\n\n\t\t\tthis.sizeRatioX = this.options.speedRatioX || (this.scroller.maxScrollX && (this.maxPosX / this.scroller.maxScrollX));\n\t\t}\n\n\t\tif ( this.options.listenY ) {\n\t\t\tthis.wrapperHeight = this.wrapper.clientHeight;\n\t\t\tif ( this.options.resize ) {\n\t\t\t\tthis.indicatorHeight = Math.max(Math.round(this.wrapperHeight * this.wrapperHeight / (this.scroller.scrollerHeight || this.wrapperHeight || 1)), 8);\n\t\t\t\tthis.indicatorStyle.height = this.indicatorHeight + 'px';\n\t\t\t} else {\n\t\t\t\tthis.indicatorHeight = this.indicator.clientHeight;\n\t\t\t}\n\n\t\t\tthis.maxPosY = this.wrapperHeight - this.indicatorHeight;\n\n\t\t\tif ( this.options.shrink == 'clip' ) {\n\t\t\t\tthis.minBoundaryY = -this.indicatorHeight + 8;\n\t\t\t\tthis.maxBoundaryY = this.wrapperHeight - 8;\n\t\t\t} else {\n\t\t\t\tthis.minBoundaryY = 0;\n\t\t\t\tthis.maxBoundaryY = this.maxPosY;\n\t\t\t}\n\n\t\t\tthis.maxPosY = this.wrapperHeight - this.indicatorHeight;\n\t\t\tthis.sizeRatioY = this.options.speedRatioY || (this.scroller.maxScrollY && (this.maxPosY / this.scroller.maxScrollY));\n\t\t}\n\n\t\tthis.updatePosition();\n\t},\n\n\tupdatePosition: function () {\n\t\tvar x = this.options.listenX && Math.round(this.sizeRatioX * this.scroller.x) || 0,\n\t\t\ty = this.options.listenY && Math.round(this.sizeRatioY * this.scroller.y) || 0;\n\n\t\tif ( !this.options.ignoreBoundaries ) {\n\t\t\tif ( x < this.minBoundaryX ) {\n\t\t\t\tif ( this.options.shrink == 'scale' ) {\n\t\t\t\t\tthis.width = Math.max(this.indicatorWidth + x, 8);\n\t\t\t\t\tthis.indicatorStyle.width = this.width + 'px';\n\t\t\t\t}\n\t\t\t\tx = this.minBoundaryX;\n\t\t\t} else if ( x > this.maxBoundaryX ) {\n\t\t\t\tif ( this.options.shrink == 'scale' ) {\n\t\t\t\t\tthis.width = Math.max(this.indicatorWidth - (x - this.maxPosX), 8);\n\t\t\t\t\tthis.indicatorStyle.width = this.width + 'px';\n\t\t\t\t\tx = this.maxPosX + this.indicatorWidth - this.width;\n\t\t\t\t} else {\n\t\t\t\t\tx = this.maxBoundaryX;\n\t\t\t\t}\n\t\t\t} else if ( this.options.shrink == 'scale' && this.width != this.indicatorWidth ) {\n\t\t\t\tthis.width = this.indicatorWidth;\n\t\t\t\tthis.indicatorStyle.width = this.width + 'px';\n\t\t\t}\n\n\t\t\tif ( y < this.minBoundaryY ) {\n\t\t\t\tif ( this.options.shrink == 'scale' ) {\n\t\t\t\t\tthis.height = Math.max(this.indicatorHeight + y * 3, 8);\n\t\t\t\t\tthis.indicatorStyle.height = this.height + 'px';\n\t\t\t\t}\n\t\t\t\ty = this.minBoundaryY;\n\t\t\t} else if ( y > this.maxBoundaryY ) {\n\t\t\t\tif ( this.options.shrink == 'scale' ) {\n\t\t\t\t\tthis.height = Math.max(this.indicatorHeight - (y - this.maxPosY) * 3, 8);\n\t\t\t\t\tthis.indicatorStyle.height = this.height + 'px';\n\t\t\t\t\ty = this.maxPosY + this.indicatorHeight - this.height;\n\t\t\t\t} else {\n\t\t\t\t\ty = this.maxBoundaryY;\n\t\t\t\t}\n\t\t\t} else if ( this.options.shrink == 'scale' && this.height != this.indicatorHeight ) {\n\t\t\t\tthis.height = this.indicatorHeight;\n\t\t\t\tthis.indicatorStyle.height = this.height + 'px';\n\t\t\t}\n\t\t}\n\n\t\tthis.x = x;\n\t\tthis.y = y;\n\n\t\tif ( this.scroller.options.useTransform ) {\n\t\t\tthis.indicatorStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.scroller.translateZ;\n\t\t} else {\n\t\t\tthis.indicatorStyle.left = x + 'px';\n\t\t\tthis.indicatorStyle.top = y + 'px';\n\t\t}\n\t},\n\n\t_pos: function (x, y) {\n\t\tif ( x < 0 ) {\n\t\t\tx = 0;\n\t\t} else if ( x > this.maxPosX ) {\n\t\t\tx = this.maxPosX;\n\t\t}\n\n\t\tif ( y < 0 ) {\n\t\t\ty = 0;\n\t\t} else if ( y > this.maxPosY ) {\n\t\t\ty = this.maxPosY;\n\t\t}\n\n\t\tx = this.options.listenX ? Math.round(x / this.sizeRatioX) : this.scroller.x;\n\t\ty = this.options.listenY ? Math.round(y / this.sizeRatioY) : this.scroller.y;\n\n\t\tthis.scroller.scrollTo(x, y);\n\t},\n\n\tfade: function (val, hold) {\n\t\tif ( hold && !this.visible ) {\n\t\t\treturn;\n\t\t}\n\n\t\tclearTimeout(this.fadeTimeout);\n\t\tthis.fadeTimeout = null;\n\n\t\tvar time = val ? 250 : 500,\n\t\t\tdelay = val ? 0 : 300;\n\n\t\tval = val ? '1' : '0';\n\n\t\tthis.wrapperStyle[utils.style.transitionDuration] = time + 'ms';\n\n\t\tthis.fadeTimeout = setTimeout((function (val) {\n\t\t\tthis.wrapperStyle.opacity = val;\n\t\t\tthis.visible = +val;\n\t\t}).bind(this, val), delay);\n\t}\n};\n\nIScroll.utils = utils;\n\nif ( typeof module != 'undefined' && module.exports ) {\n\tmodule.exports = IScroll;\n} else if ( typeof define == 'function' && define.amd ) {\n        define( function () { return IScroll; } );\n} else {\n\twindow.IScroll = IScroll;\n}\n\n})(window, document, Math);\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/base-component/amazeui/js/summernote.js",
    "content": "/**\n * Super simple wysiwyg editor v0.8.2\n * http://summernote.org/\n *\n * summernote.js\n * Copyright 2013-2016 Alan Hong. and other contributors\n * summernote may be freely distributed under the MIT license./\n *\n * Date: 2016-08-07T05:11Z\n */\n(function (factory) {\n  /* global define */\n  if (typeof define === 'function' && define.amd) {\n    // AMD. Register as an anonymous module.\n    define(['jquery'], factory);\n  } else if (typeof module === 'object' && module.exports) {\n    // Node/CommonJS\n    module.exports = factory(require('jquery'));\n  } else {\n    // Browser globals\n    factory(window.jQuery);\n  }\n}(function ($) {\n  'use strict';\n\n  /**\n   * @class core.func\n   *\n   * func utils (for high-order func's arg)\n   *\n   * @singleton\n   * @alternateClassName func\n   */\n  var func = (function () {\n    var eq = function (itemA) {\n      return function (itemB) {\n        return itemA === itemB;\n      };\n    };\n\n    var eq2 = function (itemA, itemB) {\n      return itemA === itemB;\n    };\n\n    var peq2 = function (propName) {\n      return function (itemA, itemB) {\n        return itemA[propName] === itemB[propName];\n      };\n    };\n\n    var ok = function () {\n      return true;\n    };\n\n    var fail = function () {\n      return false;\n    };\n\n    var not = function (f) {\n      return function () {\n        return !f.apply(f, arguments);\n      };\n    };\n\n    var and = function (fA, fB) {\n      return function (item) {\n        return fA(item) && fB(item);\n      };\n    };\n\n    var self = function (a) {\n      return a;\n    };\n\n    var invoke = function (obj, method) {\n      return function () {\n        return obj[method].apply(obj, arguments);\n      };\n    };\n\n    var idCounter = 0;\n\n    /**\n     * generate a globally-unique id\n     *\n     * @param {String} [prefix]\n     */\n    var uniqueId = function (prefix) {\n      var id = ++idCounter + '';\n      return prefix ? prefix + id : id;\n    };\n\n    /**\n     * returns bnd (bounds) from rect\n     *\n     * - IE Compatibility Issue: http://goo.gl/sRLOAo\n     * - Scroll Issue: http://goo.gl/sNjUc\n     *\n     * @param {Rect} rect\n     * @return {Object} bounds\n     * @return {Number} bounds.top\n     * @return {Number} bounds.left\n     * @return {Number} bounds.width\n     * @return {Number} bounds.height\n     */\n    var rect2bnd = function (rect) {\n      var $document = $(document);\n      return {\n        top: rect.top + $document.scrollTop(),\n        left: rect.left + $document.scrollLeft(),\n        width: rect.right - rect.left,\n        height: rect.bottom - rect.top\n      };\n    };\n\n    /**\n     * returns a copy of the object where the keys have become the values and the values the keys.\n     * @param {Object} obj\n     * @return {Object}\n     */\n    var invertObject = function (obj) {\n      var inverted = {};\n      for (var key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          inverted[obj[key]] = key;\n        }\n      }\n      return inverted;\n    };\n\n    /**\n     * @param {String} namespace\n     * @param {String} [prefix]\n     * @return {String}\n     */\n    var namespaceToCamel = function (namespace, prefix) {\n      prefix = prefix || '';\n      return prefix + namespace.split('.').map(function (name) {\n        return name.substring(0, 1).toUpperCase() + name.substring(1);\n      }).join('');\n    };\n\n    /**\n     * Returns a function, that, as long as it continues to be invoked, will not\n     * be triggered. The function will be called after it stops being called for\n     * N milliseconds. If `immediate` is passed, trigger the function on the\n     * leading edge, instead of the trailing.\n     * @param {Function} func\n     * @param {Number} wait\n     * @param {Boolean} immediate\n     * @return {Function}\n     */\n    var debounce = function (func, wait, immediate) {\n      var timeout;\n      return function () {\n        var context = this, args = arguments;\n        var later = function () {\n          timeout = null;\n          if (!immediate) {\n            func.apply(context, args);\n          }\n        };\n        var callNow = immediate && !timeout;\n        clearTimeout(timeout);\n        timeout = setTimeout(later, wait);\n        if (callNow) {\n          func.apply(context, args);\n        }\n      };\n    };\n\n    return {\n      eq: eq,\n      eq2: eq2,\n      peq2: peq2,\n      ok: ok,\n      fail: fail,\n      self: self,\n      not: not,\n      and: and,\n      invoke: invoke,\n      uniqueId: uniqueId,\n      rect2bnd: rect2bnd,\n      invertObject: invertObject,\n      namespaceToCamel: namespaceToCamel,\n      debounce: debounce\n    };\n  })();\n\n  /**\n   * @class core.list\n   *\n   * list utils\n   *\n   * @singleton\n   * @alternateClassName list\n   */\n  var list = (function () {\n    /**\n     * returns the first item of an array.\n     *\n     * @param {Array} array\n     */\n    var head = function (array) {\n      return array[0];\n    };\n\n    /**\n     * returns the last item of an array.\n     *\n     * @param {Array} array\n     */\n    var last = function (array) {\n      return array[array.length - 1];\n    };\n\n    /**\n     * returns everything but the last entry of the array.\n     *\n     * @param {Array} array\n     */\n    var initial = function (array) {\n      return array.slice(0, array.length - 1);\n    };\n\n    /**\n     * returns the rest of the items in an array.\n     *\n     * @param {Array} array\n     */\n    var tail = function (array) {\n      return array.slice(1);\n    };\n\n    /**\n     * returns item of array\n     */\n    var find = function (array, pred) {\n      for (var idx = 0, len = array.length; idx < len; idx ++) {\n        var item = array[idx];\n        if (pred(item)) {\n          return item;\n        }\n      }\n    };\n\n    /**\n     * returns true if all of the values in the array pass the predicate truth test.\n     */\n    var all = function (array, pred) {\n      for (var idx = 0, len = array.length; idx < len; idx ++) {\n        if (!pred(array[idx])) {\n          return false;\n        }\n      }\n      return true;\n    };\n\n    /**\n     * returns index of item\n     */\n    var indexOf = function (array, item) {\n      return $.inArray(item, array);\n    };\n\n    /**\n     * returns true if the value is present in the list.\n     */\n    var contains = function (array, item) {\n      return indexOf(array, item) !== -1;\n    };\n\n    /**\n     * get sum from a list\n     *\n     * @param {Array} array - array\n     * @param {Function} fn - iterator\n     */\n    var sum = function (array, fn) {\n      fn = fn || func.self;\n      return array.reduce(function (memo, v) {\n        return memo + fn(v);\n      }, 0);\n    };\n  \n    /**\n     * returns a copy of the collection with array type.\n     * @param {Collection} collection - collection eg) node.childNodes, ...\n     */\n    var from = function (collection) {\n      var result = [], idx = -1, length = collection.length;\n      while (++idx < length) {\n        result[idx] = collection[idx];\n      }\n      return result;\n    };\n\n    /**\n     * returns whether list is empty or not\n     */\n    var isEmpty = function (array) {\n      return !array || !array.length;\n    };\n  \n    /**\n     * cluster elements by predicate function.\n     *\n     * @param {Array} array - array\n     * @param {Function} fn - predicate function for cluster rule\n     * @param {Array[]}\n     */\n    var clusterBy = function (array, fn) {\n      if (!array.length) { return []; }\n      var aTail = tail(array);\n      return aTail.reduce(function (memo, v) {\n        var aLast = last(memo);\n        if (fn(last(aLast), v)) {\n          aLast[aLast.length] = v;\n        } else {\n          memo[memo.length] = [v];\n        }\n        return memo;\n      }, [[head(array)]]);\n    };\n  \n    /**\n     * returns a copy of the array with all false values removed\n     *\n     * @param {Array} array - array\n     * @param {Function} fn - predicate function for cluster rule\n     */\n    var compact = function (array) {\n      var aResult = [];\n      for (var idx = 0, len = array.length; idx < len; idx ++) {\n        if (array[idx]) { aResult.push(array[idx]); }\n      }\n      return aResult;\n    };\n\n    /**\n     * produces a duplicate-free version of the array\n     *\n     * @param {Array} array\n     */\n    var unique = function (array) {\n      var results = [];\n\n      for (var idx = 0, len = array.length; idx < len; idx ++) {\n        if (!contains(results, array[idx])) {\n          results.push(array[idx]);\n        }\n      }\n\n      return results;\n    };\n\n    /**\n     * returns next item.\n     * @param {Array} array\n     */\n    var next = function (array, item) {\n      var idx = indexOf(array, item);\n      if (idx === -1) { return null; }\n\n      return array[idx + 1];\n    };\n\n    /**\n     * returns prev item.\n     * @param {Array} array\n     */\n    var prev = function (array, item) {\n      var idx = indexOf(array, item);\n      if (idx === -1) { return null; }\n\n      return array[idx - 1];\n    };\n\n    return { head: head, last: last, initial: initial, tail: tail,\n             prev: prev, next: next, find: find, contains: contains,\n             all: all, sum: sum, from: from, isEmpty: isEmpty,\n             clusterBy: clusterBy, compact: compact, unique: unique };\n  })();\n\n  var isSupportAmd = typeof define === 'function' && define.amd;\n\n  /**\n   * returns whether font is installed or not.\n   *\n   * @param {String} fontName\n   * @return {Boolean}\n   */\n  var isFontInstalled = function (fontName) {\n    var testFontName = fontName === 'Comic Sans MS' ? 'Courier New' : 'Comic Sans MS';\n    var $tester = $('<div>').css({\n      position: 'absolute',\n      left: '-9999px',\n      top: '-9999px',\n      fontSize: '200px'\n    }).text('mmmmmmmmmwwwwwww').appendTo(document.body);\n\n    var originalWidth = $tester.css('fontFamily', testFontName).width();\n    var width = $tester.css('fontFamily', fontName + ',' + testFontName).width();\n\n    $tester.remove();\n\n    return originalWidth !== width;\n  };\n\n  var userAgent = navigator.userAgent;\n  var isMSIE = /MSIE|Trident/i.test(userAgent);\n  var browserVersion;\n  if (isMSIE) {\n    var matches = /MSIE (\\d+[.]\\d+)/.exec(userAgent);\n    if (matches) {\n      browserVersion = parseFloat(matches[1]);\n    }\n    matches = /Trident\\/.*rv:([0-9]{1,}[\\.0-9]{0,})/.exec(userAgent);\n    if (matches) {\n      browserVersion = parseFloat(matches[1]);\n    }\n  }\n\n  var isEdge = /Edge\\/\\d+/.test(userAgent);\n\n  var hasCodeMirror = !!window.CodeMirror;\n  if (!hasCodeMirror && isSupportAmd && typeof require !== 'undefined') {\n    if (typeof require.resolve !== 'undefined') {\n      try {\n        // If CodeMirror can't be resolved, `require.resolve` will throw an\n        // exception and `hasCodeMirror` won't be set to `true`.\n        require.resolve('codemirror');\n        hasCodeMirror = true;\n      } catch (e) {\n        // Do nothing.\n      }\n    } else if (typeof eval('require').specified !== 'undefined') {\n      hasCodeMirror = eval('require').specified('codemirror');\n    }\n  }\n\n  /**\n   * @class core.agent\n   *\n   * Object which check platform and agent\n   *\n   * @singleton\n   * @alternateClassName agent\n   */\n  var agent = {\n    isMac: navigator.appVersion.indexOf('Mac') > -1,\n    isMSIE: isMSIE,\n    isEdge: isEdge,\n    isFF: !isEdge && /firefox/i.test(userAgent),\n    isPhantom: /PhantomJS/i.test(userAgent),\n    isWebkit: !isEdge && /webkit/i.test(userAgent),\n    isChrome: !isEdge && /chrome/i.test(userAgent),\n    isSafari: !isEdge && /safari/i.test(userAgent),\n    browserVersion: browserVersion,\n    jqueryVersion: parseFloat($.fn.jquery),\n    isSupportAmd: isSupportAmd,\n    hasCodeMirror: hasCodeMirror,\n    isFontInstalled: isFontInstalled,\n    isW3CRangeSupport: !!document.createRange\n  };\n\n\n  var NBSP_CHAR = String.fromCharCode(160);\n  var ZERO_WIDTH_NBSP_CHAR = '\\ufeff';\n\n  /**\n   * @class core.dom\n   *\n   * Dom functions\n   *\n   * @singleton\n   * @alternateClassName dom\n   */\n  var dom = (function () {\n    /**\n     * @method isEditable\n     *\n     * returns whether node is `note-editable` or not.\n     *\n     * @param {Node} node\n     * @return {Boolean}\n     */\n    var isEditable = function (node) {\n      return node && $(node).hasClass('note-editable');\n    };\n\n    /**\n     * @method isControlSizing\n     *\n     * returns whether node is `note-control-sizing` or not.\n     *\n     * @param {Node} node\n     * @return {Boolean}\n     */\n    var isControlSizing = function (node) {\n      return node && $(node).hasClass('note-control-sizing');\n    };\n\n    /**\n     * @method makePredByNodeName\n     *\n     * returns predicate which judge whether nodeName is same\n     *\n     * @param {String} nodeName\n     * @return {Function}\n     */\n    var makePredByNodeName = function (nodeName) {\n      nodeName = nodeName.toUpperCase();\n      return function (node) {\n        return node && node.nodeName.toUpperCase() === nodeName;\n      };\n    };\n\n    /**\n     * @method isText\n     *\n     *\n     *\n     * @param {Node} node\n     * @return {Boolean} true if node's type is text(3)\n     */\n    var isText = function (node) {\n      return node && node.nodeType === 3;\n    };\n\n    /**\n     * @method isElement\n     *\n     *\n     *\n     * @param {Node} node\n     * @return {Boolean} true if node's type is element(1)\n     */\n    var isElement = function (node) {\n      return node && node.nodeType === 1;\n    };\n\n    /**\n     * ex) br, col, embed, hr, img, input, ...\n     * @see http://www.w3.org/html/wg/drafts/html/master/syntax.html#void-elements\n     */\n    var isVoid = function (node) {\n      return node && /^BR|^IMG|^HR|^IFRAME|^BUTTON/.test(node.nodeName.toUpperCase());\n    };\n\n    var isPara = function (node) {\n      if (isEditable(node)) {\n        return false;\n      }\n\n      // Chrome(v31.0), FF(v25.0.1) use DIV for paragraph\n      return node && /^DIV|^P|^LI|^H[1-7]/.test(node.nodeName.toUpperCase());\n    };\n\n    var isHeading = function (node) {\n      return node && /^H[1-7]/.test(node.nodeName.toUpperCase());\n    };\n\n    var isPre = makePredByNodeName('PRE');\n\n    var isLi = makePredByNodeName('LI');\n\n    var isPurePara = function (node) {\n      return isPara(node) && !isLi(node);\n    };\n\n    var isTable = makePredByNodeName('TABLE');\n\n    var isData = makePredByNodeName('DATA');\n\n    var isInline = function (node) {\n      return !isBodyContainer(node) &&\n             !isList(node) &&\n             !isHr(node) &&\n             !isPara(node) &&\n             !isTable(node) &&\n             !isBlockquote(node) &&\n             !isData(node);\n    };\n\n    var isList = function (node) {\n      return node && /^UL|^OL/.test(node.nodeName.toUpperCase());\n    };\n\n    var isHr = makePredByNodeName('HR');\n\n    var isCell = function (node) {\n      return node && /^TD|^TH/.test(node.nodeName.toUpperCase());\n    };\n\n    var isBlockquote = makePredByNodeName('BLOCKQUOTE');\n\n    var isBodyContainer = function (node) {\n      return isCell(node) || isBlockquote(node) || isEditable(node);\n    };\n\n    var isAnchor = makePredByNodeName('A');\n\n    var isParaInline = function (node) {\n      return isInline(node) && !!ancestor(node, isPara);\n    };\n\n    var isBodyInline = function (node) {\n      return isInline(node) && !ancestor(node, isPara);\n    };\n\n    var isBody = makePredByNodeName('BODY');\n\n    /**\n     * returns whether nodeB is closest sibling of nodeA\n     *\n     * @param {Node} nodeA\n     * @param {Node} nodeB\n     * @return {Boolean}\n     */\n    var isClosestSibling = function (nodeA, nodeB) {\n      return nodeA.nextSibling === nodeB ||\n             nodeA.previousSibling === nodeB;\n    };\n\n    /**\n     * returns array of closest siblings with node\n     *\n     * @param {Node} node\n     * @param {function} [pred] - predicate function\n     * @return {Node[]}\n     */\n    var withClosestSiblings = function (node, pred) {\n      pred = pred || func.ok;\n\n      var siblings = [];\n      if (node.previousSibling && pred(node.previousSibling)) {\n        siblings.push(node.previousSibling);\n      }\n      siblings.push(node);\n      if (node.nextSibling && pred(node.nextSibling)) {\n        siblings.push(node.nextSibling);\n      }\n      return siblings;\n    };\n\n    /**\n     * blank HTML for cursor position\n     * - [workaround] old IE only works with &nbsp;\n     * - [workaround] IE11 and other browser works with bogus br\n     */\n    var blankHTML = agent.isMSIE && agent.browserVersion < 11 ? '&nbsp;' : '<br>';\n\n    /**\n     * @method nodeLength\n     *\n     * returns #text's text size or element's childNodes size\n     *\n     * @param {Node} node\n     */\n    var nodeLength = function (node) {\n      if (isText(node)) {\n        return node.nodeValue.length;\n      }\n      \n      if (node) {\n        return node.childNodes.length;\n      }\n      \n      return 0;\n      \n    };\n\n    /**\n     * returns whether node is empty or not.\n     *\n     * @param {Node} node\n     * @return {Boolean}\n     */\n    var isEmpty = function (node) {\n      var len = nodeLength(node);\n\n      if (len === 0) {\n        return true;\n      } else if (!isText(node) && len === 1 && node.innerHTML === blankHTML) {\n        // ex) <p><br></p>, <span><br></span>\n        return true;\n      } else if (list.all(node.childNodes, isText) && node.innerHTML === '') {\n        // ex) <p></p>, <span></span>\n        return true;\n      }\n\n      return false;\n    };\n\n    /**\n     * padding blankHTML if node is empty (for cursor position)\n     */\n    var paddingBlankHTML = function (node) {\n      if (!isVoid(node) && !nodeLength(node)) {\n        node.innerHTML = blankHTML;\n      }\n    };\n\n    /**\n     * find nearest ancestor predicate hit\n     *\n     * @param {Node} node\n     * @param {Function} pred - predicate function\n     */\n    var ancestor = function (node, pred) {\n      while (node) {\n        if (pred(node)) { return node; }\n        if (isEditable(node)) { break; }\n\n        node = node.parentNode;\n      }\n      return null;\n    };\n\n    /**\n     * find nearest ancestor only single child blood line and predicate hit\n     *\n     * @param {Node} node\n     * @param {Function} pred - predicate function\n     */\n    var singleChildAncestor = function (node, pred) {\n      node = node.parentNode;\n\n      while (node) {\n        if (nodeLength(node) !== 1) { break; }\n        if (pred(node)) { return node; }\n        if (isEditable(node)) { break; }\n\n        node = node.parentNode;\n      }\n      return null;\n    };\n\n    /**\n     * returns new array of ancestor nodes (until predicate hit).\n     *\n     * @param {Node} node\n     * @param {Function} [optional] pred - predicate function\n     */\n    var listAncestor = function (node, pred) {\n      pred = pred || func.fail;\n\n      var ancestors = [];\n      ancestor(node, function (el) {\n        if (!isEditable(el)) {\n          ancestors.push(el);\n        }\n\n        return pred(el);\n      });\n      return ancestors;\n    };\n\n    /**\n     * find farthest ancestor predicate hit\n     */\n    var lastAncestor = function (node, pred) {\n      var ancestors = listAncestor(node);\n      return list.last(ancestors.filter(pred));\n    };\n\n    /**\n     * returns common ancestor node between two nodes.\n     *\n     * @param {Node} nodeA\n     * @param {Node} nodeB\n     */\n    var commonAncestor = function (nodeA, nodeB) {\n      var ancestors = listAncestor(nodeA);\n      for (var n = nodeB; n; n = n.parentNode) {\n        if ($.inArray(n, ancestors) > -1) { return n; }\n      }\n      return null; // difference document area\n    };\n\n    /**\n     * listing all previous siblings (until predicate hit).\n     *\n     * @param {Node} node\n     * @param {Function} [optional] pred - predicate function\n     */\n    var listPrev = function (node, pred) {\n      pred = pred || func.fail;\n\n      var nodes = [];\n      while (node) {\n        if (pred(node)) { break; }\n        nodes.push(node);\n        node = node.previousSibling;\n      }\n      return nodes;\n    };\n\n    /**\n     * listing next siblings (until predicate hit).\n     *\n     * @param {Node} node\n     * @param {Function} [pred] - predicate function\n     */\n    var listNext = function (node, pred) {\n      pred = pred || func.fail;\n\n      var nodes = [];\n      while (node) {\n        if (pred(node)) { break; }\n        nodes.push(node);\n        node = node.nextSibling;\n      }\n      return nodes;\n    };\n\n    /**\n     * listing descendant nodes\n     *\n     * @param {Node} node\n     * @param {Function} [pred] - predicate function\n     */\n    var listDescendant = function (node, pred) {\n      var descendants = [];\n      pred = pred || func.ok;\n\n      // start DFS(depth first search) with node\n      (function fnWalk(current) {\n        if (node !== current && pred(current)) {\n          descendants.push(current);\n        }\n        for (var idx = 0, len = current.childNodes.length; idx < len; idx++) {\n          fnWalk(current.childNodes[idx]);\n        }\n      })(node);\n\n      return descendants;\n    };\n\n    /**\n     * wrap node with new tag.\n     *\n     * @param {Node} node\n     * @param {Node} tagName of wrapper\n     * @return {Node} - wrapper\n     */\n    var wrap = function (node, wrapperName) {\n      var parent = node.parentNode;\n      var wrapper = $('<' + wrapperName + '>')[0];\n\n      parent.insertBefore(wrapper, node);\n      wrapper.appendChild(node);\n\n      return wrapper;\n    };\n\n    /**\n     * insert node after preceding\n     *\n     * @param {Node} node\n     * @param {Node} preceding - predicate function\n     */\n    var insertAfter = function (node, preceding) {\n      var next = preceding.nextSibling, parent = preceding.parentNode;\n      if (next) {\n        parent.insertBefore(node, next);\n      } else {\n        parent.appendChild(node);\n      }\n      return node;\n    };\n\n    /**\n     * append elements.\n     *\n     * @param {Node} node\n     * @param {Collection} aChild\n     */\n    var appendChildNodes = function (node, aChild) {\n      $.each(aChild, function (idx, child) {\n        node.appendChild(child);\n      });\n      return node;\n    };\n\n    /**\n     * returns whether boundaryPoint is left edge or not.\n     *\n     * @param {BoundaryPoint} point\n     * @return {Boolean}\n     */\n    var isLeftEdgePoint = function (point) {\n      return point.offset === 0;\n    };\n\n    /**\n     * returns whether boundaryPoint is right edge or not.\n     *\n     * @param {BoundaryPoint} point\n     * @return {Boolean}\n     */\n    var isRightEdgePoint = function (point) {\n      return point.offset === nodeLength(point.node);\n    };\n\n    /**\n     * returns whether boundaryPoint is edge or not.\n     *\n     * @param {BoundaryPoint} point\n     * @return {Boolean}\n     */\n    var isEdgePoint = function (point) {\n      return isLeftEdgePoint(point) || isRightEdgePoint(point);\n    };\n\n    /**\n     * returns whether node is left edge of ancestor or not.\n     *\n     * @param {Node} node\n     * @param {Node} ancestor\n     * @return {Boolean}\n     */\n    var isLeftEdgeOf = function (node, ancestor) {\n      while (node && node !== ancestor) {\n        if (position(node) !== 0) {\n          return false;\n        }\n        node = node.parentNode;\n      }\n\n      return true;\n    };\n\n    /**\n     * returns whether node is right edge of ancestor or not.\n     *\n     * @param {Node} node\n     * @param {Node} ancestor\n     * @return {Boolean}\n     */\n    var isRightEdgeOf = function (node, ancestor) {\n      if (!ancestor) {\n        return false;\n      }\n      while (node && node !== ancestor) {\n        if (position(node) !== nodeLength(node.parentNode) - 1) {\n          return false;\n        }\n        node = node.parentNode;\n      }\n\n      return true;\n    };\n\n    /**\n     * returns whether point is left edge of ancestor or not.\n     * @param {BoundaryPoint} point\n     * @param {Node} ancestor\n     * @return {Boolean}\n     */\n    var isLeftEdgePointOf = function (point, ancestor) {\n      return isLeftEdgePoint(point) && isLeftEdgeOf(point.node, ancestor);\n    };\n\n    /**\n     * returns whether point is right edge of ancestor or not.\n     * @param {BoundaryPoint} point\n     * @param {Node} ancestor\n     * @return {Boolean}\n     */\n    var isRightEdgePointOf = function (point, ancestor) {\n      return isRightEdgePoint(point) && isRightEdgeOf(point.node, ancestor);\n    };\n\n    /**\n     * returns offset from parent.\n     *\n     * @param {Node} node\n     */\n    var position = function (node) {\n      var offset = 0;\n      while ((node = node.previousSibling)) {\n        offset += 1;\n      }\n      return offset;\n    };\n\n    var hasChildren = function (node) {\n      return !!(node && node.childNodes && node.childNodes.length);\n    };\n\n    /**\n     * returns previous boundaryPoint\n     *\n     * @param {BoundaryPoint} point\n     * @param {Boolean} isSkipInnerOffset\n     * @return {BoundaryPoint}\n     */\n    var prevPoint = function (point, isSkipInnerOffset) {\n      var node, offset;\n\n      if (point.offset === 0) {\n        if (isEditable(point.node)) {\n          return null;\n        }\n\n        node = point.node.parentNode;\n        offset = position(point.node);\n      } else if (hasChildren(point.node)) {\n        node = point.node.childNodes[point.offset - 1];\n        offset = nodeLength(node);\n      } else {\n        node = point.node;\n        offset = isSkipInnerOffset ? 0 : point.offset - 1;\n      }\n\n      return {\n        node: node,\n        offset: offset\n      };\n    };\n\n    /**\n     * returns next boundaryPoint\n     *\n     * @param {BoundaryPoint} point\n     * @param {Boolean} isSkipInnerOffset\n     * @return {BoundaryPoint}\n     */\n    var nextPoint = function (point, isSkipInnerOffset) {\n      var node, offset;\n\n      if (nodeLength(point.node) === point.offset) {\n        if (isEditable(point.node)) {\n          return null;\n        }\n\n        node = point.node.parentNode;\n        offset = position(point.node) + 1;\n      } else if (hasChildren(point.node)) {\n        node = point.node.childNodes[point.offset];\n        offset = 0;\n      } else {\n        node = point.node;\n        offset = isSkipInnerOffset ? nodeLength(point.node) : point.offset + 1;\n      }\n\n      return {\n        node: node,\n        offset: offset\n      };\n    };\n\n    /**\n     * returns whether pointA and pointB is same or not.\n     *\n     * @param {BoundaryPoint} pointA\n     * @param {BoundaryPoint} pointB\n     * @return {Boolean}\n     */\n    var isSamePoint = function (pointA, pointB) {\n      return pointA.node === pointB.node && pointA.offset === pointB.offset;\n    };\n\n    /**\n     * returns whether point is visible (can set cursor) or not.\n     *\n     * @param {BoundaryPoint} point\n     * @return {Boolean}\n     */\n    var isVisiblePoint = function (point) {\n      if (isText(point.node) || !hasChildren(point.node) || isEmpty(point.node)) {\n        return true;\n      }\n\n      var leftNode = point.node.childNodes[point.offset - 1];\n      var rightNode = point.node.childNodes[point.offset];\n      if ((!leftNode || isVoid(leftNode)) && (!rightNode || isVoid(rightNode))) {\n        return true;\n      }\n\n      return false;\n    };\n\n    /**\n     * @method prevPointUtil\n     *\n     * @param {BoundaryPoint} point\n     * @param {Function} pred\n     * @return {BoundaryPoint}\n     */\n    var prevPointUntil = function (point, pred) {\n      while (point) {\n        if (pred(point)) {\n          return point;\n        }\n\n        point = prevPoint(point);\n      }\n\n      return null;\n    };\n\n    /**\n     * @method nextPointUntil\n     *\n     * @param {BoundaryPoint} point\n     * @param {Function} pred\n     * @return {BoundaryPoint}\n     */\n    var nextPointUntil = function (point, pred) {\n      while (point) {\n        if (pred(point)) {\n          return point;\n        }\n\n        point = nextPoint(point);\n      }\n\n      return null;\n    };\n\n    /**\n     * returns whether point has character or not.\n     *\n     * @param {Point} point\n     * @return {Boolean}\n     */\n    var isCharPoint = function (point) {\n      if (!isText(point.node)) {\n        return false;\n      }\n\n      var ch = point.node.nodeValue.charAt(point.offset - 1);\n      return ch && (ch !== ' ' && ch !== NBSP_CHAR);\n    };\n\n    /**\n     * @method walkPoint\n     *\n     * @param {BoundaryPoint} startPoint\n     * @param {BoundaryPoint} endPoint\n     * @param {Function} handler\n     * @param {Boolean} isSkipInnerOffset\n     */\n    var walkPoint = function (startPoint, endPoint, handler, isSkipInnerOffset) {\n      var point = startPoint;\n\n      while (point) {\n        handler(point);\n\n        if (isSamePoint(point, endPoint)) {\n          break;\n        }\n\n        var isSkipOffset = isSkipInnerOffset &&\n                           startPoint.node !== point.node &&\n                           endPoint.node !== point.node;\n        point = nextPoint(point, isSkipOffset);\n      }\n    };\n\n    /**\n     * @method makeOffsetPath\n     *\n     * return offsetPath(array of offset) from ancestor\n     *\n     * @param {Node} ancestor - ancestor node\n     * @param {Node} node\n     */\n    var makeOffsetPath = function (ancestor, node) {\n      var ancestors = listAncestor(node, func.eq(ancestor));\n      return ancestors.map(position).reverse();\n    };\n\n    /**\n     * @method fromOffsetPath\n     *\n     * return element from offsetPath(array of offset)\n     *\n     * @param {Node} ancestor - ancestor node\n     * @param {array} offsets - offsetPath\n     */\n    var fromOffsetPath = function (ancestor, offsets) {\n      var current = ancestor;\n      for (var i = 0, len = offsets.length; i < len; i++) {\n        if (current.childNodes.length <= offsets[i]) {\n          current = current.childNodes[current.childNodes.length - 1];\n        } else {\n          current = current.childNodes[offsets[i]];\n        }\n      }\n      return current;\n    };\n\n    /**\n     * @method splitNode\n     *\n     * split element or #text\n     *\n     * @param {BoundaryPoint} point\n     * @param {Object} [options]\n     * @param {Boolean} [options.isSkipPaddingBlankHTML] - default: false\n     * @param {Boolean} [options.isNotSplitEdgePoint] - default: false\n     * @return {Node} right node of boundaryPoint\n     */\n    var splitNode = function (point, options) {\n      var isSkipPaddingBlankHTML = options && options.isSkipPaddingBlankHTML;\n      var isNotSplitEdgePoint = options && options.isNotSplitEdgePoint;\n\n      // edge case\n      if (isEdgePoint(point) && (isText(point.node) || isNotSplitEdgePoint)) {\n        if (isLeftEdgePoint(point)) {\n          return point.node;\n        } else if (isRightEdgePoint(point)) {\n          return point.node.nextSibling;\n        }\n      }\n\n      // split #text\n      if (isText(point.node)) {\n        return point.node.splitText(point.offset);\n      } else {\n        var childNode = point.node.childNodes[point.offset];\n        var clone = insertAfter(point.node.cloneNode(false), point.node);\n        appendChildNodes(clone, listNext(childNode));\n\n        if (!isSkipPaddingBlankHTML) {\n          paddingBlankHTML(point.node);\n          paddingBlankHTML(clone);\n        }\n\n        return clone;\n      }\n    };\n\n    /**\n     * @method splitTree\n     *\n     * split tree by point\n     *\n     * @param {Node} root - split root\n     * @param {BoundaryPoint} point\n     * @param {Object} [options]\n     * @param {Boolean} [options.isSkipPaddingBlankHTML] - default: false\n     * @param {Boolean} [options.isNotSplitEdgePoint] - default: false\n     * @return {Node} right node of boundaryPoint\n     */\n    var splitTree = function (root, point, options) {\n      // ex) [#text, <span>, <p>]\n      var ancestors = listAncestor(point.node, func.eq(root));\n\n      if (!ancestors.length) {\n        return null;\n      } else if (ancestors.length === 1) {\n        return splitNode(point, options);\n      }\n\n      return ancestors.reduce(function (node, parent) {\n        if (node === point.node) {\n          node = splitNode(point, options);\n        }\n\n        return splitNode({\n          node: parent,\n          offset: node ? dom.position(node) : nodeLength(parent)\n        }, options);\n      });\n    };\n\n    /**\n     * split point\n     *\n     * @param {Point} point\n     * @param {Boolean} isInline\n     * @return {Object}\n     */\n    var splitPoint = function (point, isInline) {\n      // find splitRoot, container\n      //  - inline: splitRoot is a child of paragraph\n      //  - block: splitRoot is a child of bodyContainer\n      var pred = isInline ? isPara : isBodyContainer;\n      var ancestors = listAncestor(point.node, pred);\n      var topAncestor = list.last(ancestors) || point.node;\n\n      var splitRoot, container;\n      if (pred(topAncestor)) {\n        splitRoot = ancestors[ancestors.length - 2];\n        container = topAncestor;\n      } else {\n        splitRoot = topAncestor;\n        container = splitRoot.parentNode;\n      }\n\n      // if splitRoot is exists, split with splitTree\n      var pivot = splitRoot && splitTree(splitRoot, point, {\n        isSkipPaddingBlankHTML: isInline,\n        isNotSplitEdgePoint: isInline\n      });\n\n      // if container is point.node, find pivot with point.offset\n      if (!pivot && container === point.node) {\n        pivot = point.node.childNodes[point.offset];\n      }\n\n      return {\n        rightNode: pivot,\n        container: container\n      };\n    };\n\n    var create = function (nodeName) {\n      return document.createElement(nodeName);\n    };\n\n    var createText = function (text) {\n      return document.createTextNode(text);\n    };\n\n    /**\n     * @method remove\n     *\n     * remove node, (isRemoveChild: remove child or not)\n     *\n     * @param {Node} node\n     * @param {Boolean} isRemoveChild\n     */\n    var remove = function (node, isRemoveChild) {\n      if (!node || !node.parentNode) { return; }\n      if (node.removeNode) { return node.removeNode(isRemoveChild); }\n\n      var parent = node.parentNode;\n      if (!isRemoveChild) {\n        var nodes = [];\n        var i, len;\n        for (i = 0, len = node.childNodes.length; i < len; i++) {\n          nodes.push(node.childNodes[i]);\n        }\n\n        for (i = 0, len = nodes.length; i < len; i++) {\n          parent.insertBefore(nodes[i], node);\n        }\n      }\n\n      parent.removeChild(node);\n    };\n\n    /**\n     * @method removeWhile\n     *\n     * @param {Node} node\n     * @param {Function} pred\n     */\n    var removeWhile = function (node, pred) {\n      while (node) {\n        if (isEditable(node) || !pred(node)) {\n          break;\n        }\n\n        var parent = node.parentNode;\n        remove(node);\n        node = parent;\n      }\n    };\n\n    /**\n     * @method replace\n     *\n     * replace node with provided nodeName\n     *\n     * @param {Node} node\n     * @param {String} nodeName\n     * @return {Node} - new node\n     */\n    var replace = function (node, nodeName) {\n      if (node.nodeName.toUpperCase() === nodeName.toUpperCase()) {\n        return node;\n      }\n\n      var newNode = create(nodeName);\n\n      if (node.style.cssText) {\n        newNode.style.cssText = node.style.cssText;\n      }\n\n      appendChildNodes(newNode, list.from(node.childNodes));\n      insertAfter(newNode, node);\n      remove(node);\n\n      return newNode;\n    };\n\n    var isTextarea = makePredByNodeName('TEXTAREA');\n\n    /**\n     * @param {jQuery} $node\n     * @param {Boolean} [stripLinebreaks] - default: false\n     */\n    var value = function ($node, stripLinebreaks) {\n      var val = isTextarea($node[0]) ? $node.val() : $node.html();\n      if (stripLinebreaks) {\n        return val.replace(/[\\n\\r]/g, '');\n      }\n      return val;\n    };\n\n    /**\n     * @method html\n     *\n     * get the HTML contents of node\n     *\n     * @param {jQuery} $node\n     * @param {Boolean} [isNewlineOnBlock]\n     */\n    var html = function ($node, isNewlineOnBlock) {\n      var markup = value($node);\n\n      if (isNewlineOnBlock) {\n        var regexTag = /<(\\/?)(\\b(?!!)[^>\\s]*)(.*?)(\\s*\\/?>)/g;\n        markup = markup.replace(regexTag, function (match, endSlash, name) {\n          name = name.toUpperCase();\n          var isEndOfInlineContainer = /^DIV|^TD|^TH|^P|^LI|^H[1-7]/.test(name) &&\n                                       !!endSlash;\n          var isBlockNode = /^BLOCKQUOTE|^TABLE|^TBODY|^TR|^HR|^UL|^OL/.test(name);\n\n          return match + ((isEndOfInlineContainer || isBlockNode) ? '\\n' : '');\n        });\n        markup = $.trim(markup);\n      }\n\n      return markup;\n    };\n\n    var posFromPlaceholder = function (placeholder) {\n      var $placeholder = $(placeholder);\n      var pos = $placeholder.offset();\n      var height = $placeholder.outerHeight(true); // include margin\n\n      return {\n        left: pos.left,\n        top: pos.top + height\n      };\n    };\n\n    var attachEvents = function ($node, events) {\n      Object.keys(events).forEach(function (key) {\n        $node.on(key, events[key]);\n      });\n    };\n\n    var detachEvents = function ($node, events) {\n      Object.keys(events).forEach(function (key) {\n        $node.off(key, events[key]);\n      });\n    };\n\n    return {\n      /** @property {String} NBSP_CHAR */\n      NBSP_CHAR: NBSP_CHAR,\n      /** @property {String} ZERO_WIDTH_NBSP_CHAR */\n      ZERO_WIDTH_NBSP_CHAR: ZERO_WIDTH_NBSP_CHAR,\n      /** @property {String} blank */\n      blank: blankHTML,\n      /** @property {String} emptyPara */\n      emptyPara: '<p>' + blankHTML + '</p>',\n      makePredByNodeName: makePredByNodeName,\n      isEditable: isEditable,\n      isControlSizing: isControlSizing,\n      isText: isText,\n      isElement: isElement,\n      isVoid: isVoid,\n      isPara: isPara,\n      isPurePara: isPurePara,\n      isHeading: isHeading,\n      isInline: isInline,\n      isBlock: func.not(isInline),\n      isBodyInline: isBodyInline,\n      isBody: isBody,\n      isParaInline: isParaInline,\n      isPre: isPre,\n      isList: isList,\n      isTable: isTable,\n      isData: isData,\n      isCell: isCell,\n      isBlockquote: isBlockquote,\n      isBodyContainer: isBodyContainer,\n      isAnchor: isAnchor,\n      isDiv: makePredByNodeName('DIV'),\n      isLi: isLi,\n      isBR: makePredByNodeName('BR'),\n      isSpan: makePredByNodeName('SPAN'),\n      isB: makePredByNodeName('B'),\n      isU: makePredByNodeName('U'),\n      isS: makePredByNodeName('S'),\n      isI: makePredByNodeName('I'),\n      isImg: makePredByNodeName('IMG'),\n      isTextarea: isTextarea,\n      isEmpty: isEmpty,\n      isEmptyAnchor: func.and(isAnchor, isEmpty),\n      isClosestSibling: isClosestSibling,\n      withClosestSiblings: withClosestSiblings,\n      nodeLength: nodeLength,\n      isLeftEdgePoint: isLeftEdgePoint,\n      isRightEdgePoint: isRightEdgePoint,\n      isEdgePoint: isEdgePoint,\n      isLeftEdgeOf: isLeftEdgeOf,\n      isRightEdgeOf: isRightEdgeOf,\n      isLeftEdgePointOf: isLeftEdgePointOf,\n      isRightEdgePointOf: isRightEdgePointOf,\n      prevPoint: prevPoint,\n      nextPoint: nextPoint,\n      isSamePoint: isSamePoint,\n      isVisiblePoint: isVisiblePoint,\n      prevPointUntil: prevPointUntil,\n      nextPointUntil: nextPointUntil,\n      isCharPoint: isCharPoint,\n      walkPoint: walkPoint,\n      ancestor: ancestor,\n      singleChildAncestor: singleChildAncestor,\n      listAncestor: listAncestor,\n      lastAncestor: lastAncestor,\n      listNext: listNext,\n      listPrev: listPrev,\n      listDescendant: listDescendant,\n      commonAncestor: commonAncestor,\n      wrap: wrap,\n      insertAfter: insertAfter,\n      appendChildNodes: appendChildNodes,\n      position: position,\n      hasChildren: hasChildren,\n      makeOffsetPath: makeOffsetPath,\n      fromOffsetPath: fromOffsetPath,\n      splitTree: splitTree,\n      splitPoint: splitPoint,\n      create: create,\n      createText: createText,\n      remove: remove,\n      removeWhile: removeWhile,\n      replace: replace,\n      html: html,\n      value: value,\n      posFromPlaceholder: posFromPlaceholder,\n      attachEvents: attachEvents,\n      detachEvents: detachEvents\n    };\n  })();\n\n  /**\n   * @param {jQuery} $note\n   * @param {Object} options\n   * @return {Context}\n   */\n  var Context = function ($note, options) {\n    var self = this;\n\n    var ui = $.summernote.ui;\n    this.memos = {};\n    this.modules = {};\n    this.layoutInfo = {};\n    this.options = options;\n\n    /**\n     * create layout and initialize modules and other resources\n     */\n    this.initialize = function () {\n      this.layoutInfo = ui.createLayout($note, options);\n      this._initialize();\n      $note.hide();\n      return this;\n    };\n\n    /**\n     * destroy modules and other resources and remove layout\n     */\n    this.destroy = function () {\n      this._destroy();\n      $note.removeData('summernote');\n      ui.removeLayout($note, this.layoutInfo);\n    };\n\n    /**\n     * destory modules and other resources and initialize it again\n     */\n    this.reset = function () {\n      var disabled = self.isDisabled();\n      this.code(dom.emptyPara);\n      this._destroy();\n      this._initialize();\n\n      if (disabled) {\n        self.disable();\n      }\n    };\n\n    this._initialize = function () {\n      // add optional buttons\n      var buttons = $.extend({}, this.options.buttons);\n      Object.keys(buttons).forEach(function (key) {\n        self.memo('button.' + key, buttons[key]);\n      });\n\n      var modules = $.extend({}, this.options.modules, $.summernote.plugins || {});\n\n      // add and initialize modules\n      Object.keys(modules).forEach(function (key) {\n        self.module(key, modules[key], true);\n      });\n\n      Object.keys(this.modules).forEach(function (key) {\n        self.initializeModule(key);\n      });\n    };\n\n    this._destroy = function () {\n      // destroy modules with reversed order\n      Object.keys(this.modules).reverse().forEach(function (key) {\n        self.removeModule(key);\n      });\n\n      Object.keys(this.memos).forEach(function (key) {\n        self.removeMemo(key);\n      });\n    };\n\n    this.code = function (html) {\n      var isActivated = this.invoke('codeview.isActivated');\n\n      if (html === undefined) {\n        this.invoke('codeview.sync');\n        return isActivated ? this.layoutInfo.codable.val() : this.layoutInfo.editable.html();\n      } else {\n        if (isActivated) {\n          this.layoutInfo.codable.val(html);\n        } else {\n          this.layoutInfo.editable.html(html);\n        }\n        $note.val(html);\n        this.triggerEvent('change', html);\n      }\n    };\n\n    this.isDisabled = function () {\n      return this.layoutInfo.editable.attr('contenteditable') === 'false';\n    };\n\n    this.enable = function () {\n      this.layoutInfo.editable.attr('contenteditable', true);\n      this.invoke('toolbar.activate', true);\n    };\n\n    this.disable = function () {\n      // close codeview if codeview is opend\n      if (this.invoke('codeview.isActivated')) {\n        this.invoke('codeview.deactivate');\n      }\n      this.layoutInfo.editable.attr('contenteditable', false);\n      this.invoke('toolbar.deactivate', true);\n    };\n\n    this.triggerEvent = function () {\n      var namespace = list.head(arguments);\n      var args = list.tail(list.from(arguments));\n\n      var callback = this.options.callbacks[func.namespaceToCamel(namespace, 'on')];\n      if (callback) {\n        callback.apply($note[0], args);\n      }\n      $note.trigger('summernote.' + namespace, args);\n    };\n\n    this.initializeModule = function (key) {\n      var module = this.modules[key];\n      module.shouldInitialize = module.shouldInitialize || func.ok;\n      if (!module.shouldInitialize()) {\n        return;\n      }\n\n      // initialize module\n      if (module.initialize) {\n        module.initialize();\n      }\n\n      // attach events\n      if (module.events) {\n        dom.attachEvents($note, module.events);\n      }\n    };\n\n    this.module = function (key, ModuleClass, withoutIntialize) {\n      if (arguments.length === 1) {\n        return this.modules[key];\n      }\n\n      this.modules[key] = new ModuleClass(this);\n\n      if (!withoutIntialize) {\n        this.initializeModule(key);\n      }\n    };\n\n    this.removeModule = function (key) {\n      var module = this.modules[key];\n      if (module.shouldInitialize()) {\n        if (module.events) {\n          dom.detachEvents($note, module.events);\n        }\n\n        if (module.destroy) {\n          module.destroy();\n        }\n      }\n\n      delete this.modules[key];\n    };\n\n    this.memo = function (key, obj) {\n      if (arguments.length === 1) {\n        return this.memos[key];\n      }\n      this.memos[key] = obj;\n    };\n\n    this.removeMemo = function (key) {\n      if (this.memos[key] && this.memos[key].destroy) {\n        this.memos[key].destroy();\n      }\n\n      delete this.memos[key];\n    };\n\n    this.createInvokeHandler = function (namespace, value) {\n      return function (event) {\n        event.preventDefault();\n        self.invoke(namespace, value || $(event.target).closest('[data-value]').data('value'));\n      };\n    };\n\n    this.invoke = function () {\n      var namespace = list.head(arguments);\n      var args = list.tail(list.from(arguments));\n\n      var splits = namespace.split('.');\n      var hasSeparator = splits.length > 1;\n      var moduleName = hasSeparator && list.head(splits);\n      var methodName = hasSeparator ? list.last(splits) : list.head(splits);\n\n      var module = this.modules[moduleName || 'editor'];\n      if (!moduleName && this[methodName]) {\n        return this[methodName].apply(this, args);\n      } else if (module && module[methodName] && module.shouldInitialize()) {\n        return module[methodName].apply(module, args);\n      }\n    };\n\n    return this.initialize();\n  };\n\n  $.fn.extend({\n    /**\n     * Summernote API\n     *\n     * @param {Object|String}\n     * @return {this}\n     */\n    summernote: function () {\n      var type = $.type(list.head(arguments));\n      var isExternalAPICalled = type === 'string';\n      var hasInitOptions = type === 'object';\n\n      var options = hasInitOptions ? list.head(arguments) : {};\n\n      options = $.extend({}, $.summernote.options, options);\n      options.langInfo = $.extend(true, {}, $.summernote.lang['en-US'], $.summernote.lang[options.lang]);\n      options.icons = $.extend(true, {}, $.summernote.options.icons, options.icons);\n\n      this.each(function (idx, note) {\n        var $note = $(note);\n        if (!$note.data('summernote')) {\n          var context = new Context($note, options);\n          $note.data('summernote', context);\n          $note.data('summernote').triggerEvent('init', context.layoutInfo);\n        }\n      });\n\n      var $note = this.first();\n      if ($note.length) {\n        var context = $note.data('summernote');\n        if (isExternalAPICalled) {\n          return context.invoke.apply(context, list.from(arguments));\n        } else if (options.focus) {\n          context.invoke('editor.focus');\n        }\n      }\n\n      return this;\n    }\n  });\n\n\n  var Renderer = function (markup, children, options, callback) {\n    this.render = function ($parent) {\n      var $node = $(markup);\n\n      if (options && options.contents) {\n        $node.html(options.contents);\n      }\n\n      if (options && options.className) {\n        $node.addClass(options.className);\n      }\n\n      if (options && options.data) {\n        $.each(options.data, function (k, v) {\n          $node.attr('data-' + k, v);\n        });\n      }\n\n      if (options && options.click) {\n        $node.on('click', options.click);\n      }\n\n      if (children) {\n        var $container = $node.find('.note-children-container');\n        children.forEach(function (child) {\n          child.render($container.length ? $container : $node);\n        });\n      }\n\n      if (callback) {\n        callback($node, options);\n      }\n\n      if (options && options.callback) {\n        options.callback($node);\n      }\n\n      if ($parent) {\n        $parent.append($node);\n      }\n\n      return $node;\n    };\n  };\n\n  var renderer = {\n    create: function (markup, callback) {\n      return function () {\n        var children = $.isArray(arguments[0]) ? arguments[0] : [];\n        var options = typeof arguments[1] === 'object' ? arguments[1] : arguments[0];\n        if (options && options.children) {\n          children = options.children;\n        }\n        return new Renderer(markup, children, options, callback);\n      };\n    }\n  };\n\n  var editor = renderer.create('<div class=\"note-editor note-frame panel panel-default\"/>');\n  var toolbar = renderer.create('<div class=\"note-toolbar panel-heading\"/>');\n  var editingArea = renderer.create('<div class=\"note-editing-area\"/>');\n  var codable = renderer.create('<textarea class=\"note-codable\"/>');\n  var editable = renderer.create('<div class=\"note-editable panel-body\" contentEditable=\"true\"/>');\n  var statusbar = renderer.create([\n    '<div class=\"note-statusbar\">',\n    '  <div class=\"note-resizebar\">',\n    '    <div class=\"note-icon-bar\"/>',\n    '    <div class=\"note-icon-bar\"/>',\n    '    <div class=\"note-icon-bar\"/>',\n    '  </div>',\n    '</div>'\n  ].join(''));\n\n  var airEditor = renderer.create('<div class=\"note-editor\"/>');\n  var airEditable = renderer.create('<div class=\"note-editable\" contentEditable=\"true\"/>');\n\n  var buttonGroup = renderer.create('<div class=\"note-btn-group btn-group\">');\n  var button = renderer.create('<button type=\"button\" class=\"note-btn btn btn-default btn-sm\" tabindex=\"-1\">', function ($node, options) {\n    if (options && options.tooltip) {\n      $node.attr({\n        title: options.tooltip\n      }).tooltip({\n        container: 'body',\n        trigger: 'hover',\n        placement: 'bottom'\n      });\n    }\n  });\n\n  var dropdown = renderer.create('<div class=\"dropdown-menu\">', function ($node, options) {\n    var markup = $.isArray(options.items) ? options.items.map(function (item) {\n      var value = (typeof item === 'string') ? item : (item.value || '');\n      var content = options.template ? options.template(item) : item;\n      return '<li><a href=\"#\" data-value=\"' + value + '\">' + content + '</a></li>';\n    }).join('') : options.items;\n\n    $node.html(markup);\n  });\n\n  var dropdownCheck = renderer.create('<div class=\"dropdown-menu note-check\">', function ($node, options) {\n    var markup = $.isArray(options.items) ? options.items.map(function (item) {\n      var value = (typeof item === 'string') ? item : (item.value || '');\n      var content = options.template ? options.template(item) : item;\n      return '<li><a href=\"#\" data-value=\"' + value + '\">' + icon(options.checkClassName) + ' ' + content + '</a></li>';\n    }).join('') : options.items;\n    $node.html(markup);\n  });\n\n  var palette = renderer.create('<div class=\"note-color-palette\"/>', function ($node, options) {\n    var contents = [];\n    for (var row = 0, rowSize = options.colors.length; row < rowSize; row++) {\n      var eventName = options.eventName;\n      var colors = options.colors[row];\n      var buttons = [];\n      for (var col = 0, colSize = colors.length; col < colSize; col++) {\n        var color = colors[col];\n        buttons.push([\n          '<button type=\"button\" class=\"note-color-btn\"',\n          'style=\"background-color:', color, '\" ',\n          'data-event=\"', eventName, '\" ',\n          'data-value=\"', color, '\" ',\n          'title=\"', color, '\" ',\n          'data-toggle=\"button\" tabindex=\"-1\"></button>'\n        ].join(''));\n      }\n      contents.push('<div class=\"note-color-row\">' + buttons.join('') + '</div>');\n    }\n    $node.html(contents.join(''));\n\n    $node.find('.note-color-btn').tooltip({\n      container: 'body',\n      trigger: 'hover',\n      placement: 'bottom'\n    });\n  });\n\n  var dialog = renderer.create('<div class=\"modal\" aria-hidden=\"false\" tabindex=\"-1\"/>', function ($node, options) {\n    if (options.fade) {\n      $node.addClass('fade');\n    }\n    $node.html([\n      '<div class=\"modal-dialog\">',\n      '  <div class=\"modal-content\">',\n      (options.title ?\n      '    <div class=\"modal-header\">' +\n      '      <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>' +\n      '      <h4 class=\"modal-title\">' + options.title + '</h4>' +\n      '    </div>' : ''\n      ),\n      '    <div class=\"modal-body\">' + options.body + '</div>',\n      (options.footer ?\n      '    <div class=\"modal-footer\">' + options.footer + '</div>' : ''\n      ),\n      '  </div>',\n      '</div>'\n    ].join(''));\n  });\n\n  var popover = renderer.create([\n    '<div class=\"note-popover popover in\">',\n    '  <div class=\"arrow\"/>',\n    '  <div class=\"popover-content note-children-container\"/>',\n    '</div>'\n  ].join(''), function ($node, options) {\n    var direction = typeof options.direction !== 'undefined' ? options.direction : 'bottom';\n\n    $node.addClass(direction);\n\n    if (options.hideArrow) {\n      $node.find('.arrow').hide();\n    }\n  });\n\n  var icon = function (iconClassName, tagName) {\n    tagName = tagName || 'i';\n    return '<' + tagName + ' class=\"' + iconClassName + '\"/>';\n  };\n\n  var ui = {\n    editor: editor,\n    toolbar: toolbar,\n    editingArea: editingArea,\n    codable: codable,\n    editable: editable,\n    statusbar: statusbar,\n    airEditor: airEditor,\n    airEditable: airEditable,\n    buttonGroup: buttonGroup,\n    button: button,\n    dropdown: dropdown,\n    dropdownCheck: dropdownCheck,\n    palette: palette,\n    dialog: dialog,\n    popover: popover,\n    icon: icon,\n\n    toggleBtn: function ($btn, isEnable) {\n      $btn.toggleClass('disabled', !isEnable);\n      $btn.attr('disabled', !isEnable);\n    },\n\n    toggleBtnActive: function ($btn, isActive) {\n      $btn.toggleClass('active', isActive);\n    },\n\n    onDialogShown: function ($dialog, handler) {\n      $dialog.one('shown.bs.modal', handler);\n    },\n\n    onDialogHidden: function ($dialog, handler) {\n      $dialog.one('hidden.bs.modal', handler);\n    },\n\n    showDialog: function ($dialog) {\n      $dialog.modal('show');\n    },\n\n    hideDialog: function ($dialog) {\n      $dialog.modal('hide');\n    },\n\n    createLayout: function ($note, options) {\n      var $editor = (options.airMode ? ui.airEditor([\n        ui.editingArea([\n          ui.airEditable()\n        ])\n      ]) : ui.editor([\n        ui.toolbar(),\n        ui.editingArea([\n          ui.codable(),\n          ui.editable()\n        ]),\n        ui.statusbar()\n      ])).render();\n\n      $editor.insertAfter($note);\n\n      return {\n        note: $note,\n        editor: $editor,\n        toolbar: $editor.find('.note-toolbar'),\n        editingArea: $editor.find('.note-editing-area'),\n        editable: $editor.find('.note-editable'),\n        codable: $editor.find('.note-codable'),\n        statusbar: $editor.find('.note-statusbar')\n      };\n    },\n\n    removeLayout: function ($note, layoutInfo) {\n      $note.html(layoutInfo.editable.html());\n      layoutInfo.editor.remove();\n      $note.show();\n    }\n  };\n\n  $.summernote = $.summernote || {\n    lang: {}\n  };\n\n  $.extend($.summernote.lang, {\n    'en-US': {\n      font: {\n        bold: 'Bold',\n        italic: 'Italic',\n        underline: 'Underline',\n        clear: 'Remove Font Style',\n        height: 'Line Height',\n        name: 'Font Family',\n        strikethrough: 'Strikethrough',\n        subscript: 'Subscript',\n        superscript: 'Superscript',\n        size: 'Font Size'\n      },\n      image: {\n        image: 'Picture',\n        insert: 'Insert Image',\n        resizeFull: 'Resize Full',\n        resizeHalf: 'Resize Half',\n        resizeQuarter: 'Resize Quarter',\n        floatLeft: 'Float Left',\n        floatRight: 'Float Right',\n        floatNone: 'Float None',\n        shapeRounded: 'Shape: Rounded',\n        shapeCircle: 'Shape: Circle',\n        shapeThumbnail: 'Shape: Thumbnail',\n        shapeNone: 'Shape: None',\n        dragImageHere: 'Drag image or text here',\n        dropImage: 'Drop image or Text',\n        selectFromFiles: 'Select from files',\n        maximumFileSize: 'Maximum file size',\n        maximumFileSizeError: 'Maximum file size exceeded.',\n        url: 'Image URL',\n        remove: 'Remove Image'\n      },\n      video: {\n        video: 'Video',\n        videoLink: 'Video Link',\n        insert: 'Insert Video',\n        url: 'Video URL?',\n        providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion or Youku)'\n      },\n      link: {\n        link: 'Link',\n        insert: 'Insert Link',\n        unlink: 'Unlink',\n        edit: 'Edit',\n        textToDisplay: 'Text to display',\n        url: 'To what URL should this link go?',\n        openInNewWindow: 'Open in new window'\n      },\n      table: {\n        table: 'Table'\n      },\n      hr: {\n        insert: 'Insert Horizontal Rule'\n      },\n      style: {\n        style: 'Style',\n        normal: 'Normal',\n        blockquote: 'Quote',\n        pre: 'Code',\n        h1: 'Header 1',\n        h2: 'Header 2',\n        h3: 'Header 3',\n        h4: 'Header 4',\n        h5: 'Header 5',\n        h6: 'Header 6'\n      },\n      lists: {\n        unordered: 'Unordered list',\n        ordered: 'Ordered list'\n      },\n      options: {\n        help: 'Help',\n        fullscreen: 'Full Screen',\n        codeview: 'Code View'\n      },\n      paragraph: {\n        paragraph: 'Paragraph',\n        outdent: 'Outdent',\n        indent: 'Indent',\n        left: 'Align left',\n        center: 'Align center',\n        right: 'Align right',\n        justify: 'Justify full'\n      },\n      color: {\n        recent: 'Recent Color',\n        more: 'More Color',\n        background: 'Background Color',\n        foreground: 'Foreground Color',\n        transparent: 'Transparent',\n        setTransparent: 'Set transparent',\n        reset: 'Reset',\n        resetToDefault: 'Reset to default'\n      },\n      shortcut: {\n        shortcuts: 'Keyboard shortcuts',\n        close: 'Close',\n        textFormatting: 'Text formatting',\n        action: 'Action',\n        paragraphFormatting: 'Paragraph formatting',\n        documentStyle: 'Document Style',\n        extraKeys: 'Extra keys'\n      },\n      help: {\n        'insertParagraph': 'Insert Paragraph',\n        'undo': 'Undoes the last command',\n        'redo': 'Redoes the last command',\n        'tab': 'Tab',\n        'untab': 'Untab',\n        'bold': 'Set a bold style',\n        'italic': 'Set a italic style',\n        'underline': 'Set a underline style',\n        'strikethrough': 'Set a strikethrough style',\n        'removeFormat': 'Clean a style',\n        'justifyLeft': 'Set left align',\n        'justifyCenter': 'Set center align',\n        'justifyRight': 'Set right align',\n        'justifyFull': 'Set full align',\n        'insertUnorderedList': 'Toggle unordered list',\n        'insertOrderedList': 'Toggle ordered list',\n        'outdent': 'Outdent on current paragraph',\n        'indent': 'Indent on current paragraph',\n        'formatPara': 'Change current block\\'s format as a paragraph(P tag)',\n        'formatH1': 'Change current block\\'s format as H1',\n        'formatH2': 'Change current block\\'s format as H2',\n        'formatH3': 'Change current block\\'s format as H3',\n        'formatH4': 'Change current block\\'s format as H4',\n        'formatH5': 'Change current block\\'s format as H5',\n        'formatH6': 'Change current block\\'s format as H6',\n        'insertHorizontalRule': 'Insert horizontal rule',\n        'linkDialog.show': 'Show Link Dialog'\n      },\n      history: {\n        undo: 'Undo',\n        redo: 'Redo'\n      },\n      specialChar: {\n        specialChar: 'SPECIAL CHARACTERS',\n        select: 'Select Special characters'\n      }\n    }\n  });\n\n\n  /**\n   * @class core.key\n   *\n   * Object for keycodes.\n   *\n   * @singleton\n   * @alternateClassName key\n   */\n  var key = (function () {\n    var keyMap = {\n      'BACKSPACE': 8,\n      'TAB': 9,\n      'ENTER': 13,\n      'SPACE': 32,\n\n      // Arrow\n      'LEFT': 37,\n      'UP': 38,\n      'RIGHT': 39,\n      'DOWN': 40,\n\n      // Number: 0-9\n      'NUM0': 48,\n      'NUM1': 49,\n      'NUM2': 50,\n      'NUM3': 51,\n      'NUM4': 52,\n      'NUM5': 53,\n      'NUM6': 54,\n      'NUM7': 55,\n      'NUM8': 56,\n\n      // Alphabet: a-z\n      'B': 66,\n      'E': 69,\n      'I': 73,\n      'J': 74,\n      'K': 75,\n      'L': 76,\n      'R': 82,\n      'S': 83,\n      'U': 85,\n      'V': 86,\n      'Y': 89,\n      'Z': 90,\n\n      'SLASH': 191,\n      'LEFTBRACKET': 219,\n      'BACKSLASH': 220,\n      'RIGHTBRACKET': 221\n    };\n\n    return {\n      /**\n       * @method isEdit\n       *\n       * @param {Number} keyCode\n       * @return {Boolean}\n       */\n      isEdit: function (keyCode) {\n        return list.contains([\n          keyMap.BACKSPACE,\n          keyMap.TAB,\n          keyMap.ENTER,\n          keyMap.SPACE\n        ], keyCode);\n      },\n      /**\n       * @method isMove\n       *\n       * @param {Number} keyCode\n       * @return {Boolean}\n       */\n      isMove: function (keyCode) {\n        return list.contains([\n          keyMap.LEFT,\n          keyMap.UP,\n          keyMap.RIGHT,\n          keyMap.DOWN\n        ], keyCode);\n      },\n      /**\n       * @property {Object} nameFromCode\n       * @property {String} nameFromCode.8 \"BACKSPACE\"\n       */\n      nameFromCode: func.invertObject(keyMap),\n      code: keyMap\n    };\n  })();\n\n  var range = (function () {\n\n    /**\n     * return boundaryPoint from TextRange, inspired by Andy Na's HuskyRange.js\n     *\n     * @param {TextRange} textRange\n     * @param {Boolean} isStart\n     * @return {BoundaryPoint}\n     *\n     * @see http://msdn.microsoft.com/en-us/library/ie/ms535872(v=vs.85).aspx\n     */\n    var textRangeToPoint = function (textRange, isStart) {\n      var container = textRange.parentElement(), offset;\n  \n      var tester = document.body.createTextRange(), prevContainer;\n      var childNodes = list.from(container.childNodes);\n      for (offset = 0; offset < childNodes.length; offset++) {\n        if (dom.isText(childNodes[offset])) {\n          continue;\n        }\n        tester.moveToElementText(childNodes[offset]);\n        if (tester.compareEndPoints('StartToStart', textRange) >= 0) {\n          break;\n        }\n        prevContainer = childNodes[offset];\n      }\n  \n      if (offset !== 0 && dom.isText(childNodes[offset - 1])) {\n        var textRangeStart = document.body.createTextRange(), curTextNode = null;\n        textRangeStart.moveToElementText(prevContainer || container);\n        textRangeStart.collapse(!prevContainer);\n        curTextNode = prevContainer ? prevContainer.nextSibling : container.firstChild;\n  \n        var pointTester = textRange.duplicate();\n        pointTester.setEndPoint('StartToStart', textRangeStart);\n        var textCount = pointTester.text.replace(/[\\r\\n]/g, '').length;\n  \n        while (textCount > curTextNode.nodeValue.length && curTextNode.nextSibling) {\n          textCount -= curTextNode.nodeValue.length;\n          curTextNode = curTextNode.nextSibling;\n        }\n  \n        /* jshint ignore:start */\n        var dummy = curTextNode.nodeValue; // enforce IE to re-reference curTextNode, hack\n        /* jshint ignore:end */\n  \n        if (isStart && curTextNode.nextSibling && dom.isText(curTextNode.nextSibling) &&\n            textCount === curTextNode.nodeValue.length) {\n          textCount -= curTextNode.nodeValue.length;\n          curTextNode = curTextNode.nextSibling;\n        }\n  \n        container = curTextNode;\n        offset = textCount;\n      }\n  \n      return {\n        cont: container,\n        offset: offset\n      };\n    };\n    \n    /**\n     * return TextRange from boundary point (inspired by google closure-library)\n     * @param {BoundaryPoint} point\n     * @return {TextRange}\n     */\n    var pointToTextRange = function (point) {\n      var textRangeInfo = function (container, offset) {\n        var node, isCollapseToStart;\n  \n        if (dom.isText(container)) {\n          var prevTextNodes = dom.listPrev(container, func.not(dom.isText));\n          var prevContainer = list.last(prevTextNodes).previousSibling;\n          node =  prevContainer || container.parentNode;\n          offset += list.sum(list.tail(prevTextNodes), dom.nodeLength);\n          isCollapseToStart = !prevContainer;\n        } else {\n          node = container.childNodes[offset] || container;\n          if (dom.isText(node)) {\n            return textRangeInfo(node, 0);\n          }\n  \n          offset = 0;\n          isCollapseToStart = false;\n        }\n  \n        return {\n          node: node,\n          collapseToStart: isCollapseToStart,\n          offset: offset\n        };\n      };\n  \n      var textRange = document.body.createTextRange();\n      var info = textRangeInfo(point.node, point.offset);\n  \n      textRange.moveToElementText(info.node);\n      textRange.collapse(info.collapseToStart);\n      textRange.moveStart('character', info.offset);\n      return textRange;\n    };\n    \n    /**\n     * Wrapped Range\n     *\n     * @constructor\n     * @param {Node} sc - start container\n     * @param {Number} so - start offset\n     * @param {Node} ec - end container\n     * @param {Number} eo - end offset\n     */\n    var WrappedRange = function (sc, so, ec, eo) {\n      this.sc = sc;\n      this.so = so;\n      this.ec = ec;\n      this.eo = eo;\n  \n      // nativeRange: get nativeRange from sc, so, ec, eo\n      var nativeRange = function () {\n        if (agent.isW3CRangeSupport) {\n          var w3cRange = document.createRange();\n          w3cRange.setStart(sc, so);\n          w3cRange.setEnd(ec, eo);\n\n          return w3cRange;\n        } else {\n          var textRange = pointToTextRange({\n            node: sc,\n            offset: so\n          });\n\n          textRange.setEndPoint('EndToEnd', pointToTextRange({\n            node: ec,\n            offset: eo\n          }));\n\n          return textRange;\n        }\n      };\n\n      this.getPoints = function () {\n        return {\n          sc: sc,\n          so: so,\n          ec: ec,\n          eo: eo\n        };\n      };\n\n      this.getStartPoint = function () {\n        return {\n          node: sc,\n          offset: so\n        };\n      };\n\n      this.getEndPoint = function () {\n        return {\n          node: ec,\n          offset: eo\n        };\n      };\n\n      /**\n       * select update visible range\n       */\n      this.select = function () {\n        var nativeRng = nativeRange();\n        if (agent.isW3CRangeSupport) {\n          var selection = document.getSelection();\n          if (selection.rangeCount > 0) {\n            selection.removeAllRanges();\n          }\n          selection.addRange(nativeRng);\n        } else {\n          nativeRng.select();\n        }\n        \n        return this;\n      };\n\n      /**\n       * Moves the scrollbar to start container(sc) of current range\n       *\n       * @return {WrappedRange}\n       */\n      this.scrollIntoView = function (container) {\n        var height = $(container).height();\n        if (container.scrollTop + height < this.sc.offsetTop) {\n          container.scrollTop += Math.abs(container.scrollTop + height - this.sc.offsetTop);\n        }\n\n        return this;\n      };\n\n      /**\n       * @return {WrappedRange}\n       */\n      this.normalize = function () {\n\n        /**\n         * @param {BoundaryPoint} point\n         * @param {Boolean} isLeftToRight\n         * @return {BoundaryPoint}\n         */\n        var getVisiblePoint = function (point, isLeftToRight) {\n          if ((dom.isVisiblePoint(point) && !dom.isEdgePoint(point)) ||\n              (dom.isVisiblePoint(point) && dom.isRightEdgePoint(point) && !isLeftToRight) ||\n              (dom.isVisiblePoint(point) && dom.isLeftEdgePoint(point) && isLeftToRight) ||\n              (dom.isVisiblePoint(point) && dom.isBlock(point.node) && dom.isEmpty(point.node))) {\n            return point;\n          }\n\n          // point on block's edge\n          var block = dom.ancestor(point.node, dom.isBlock);\n          if (((dom.isLeftEdgePointOf(point, block) || dom.isVoid(dom.prevPoint(point).node)) && !isLeftToRight) ||\n              ((dom.isRightEdgePointOf(point, block) || dom.isVoid(dom.nextPoint(point).node)) && isLeftToRight)) {\n\n            // returns point already on visible point\n            if (dom.isVisiblePoint(point)) {\n              return point;\n            }\n            // reverse direction \n            isLeftToRight = !isLeftToRight;\n          }\n\n          var nextPoint = isLeftToRight ? dom.nextPointUntil(dom.nextPoint(point), dom.isVisiblePoint) :\n                                          dom.prevPointUntil(dom.prevPoint(point), dom.isVisiblePoint);\n          return nextPoint || point;\n        };\n\n        var endPoint = getVisiblePoint(this.getEndPoint(), false);\n        var startPoint = this.isCollapsed() ? endPoint : getVisiblePoint(this.getStartPoint(), true);\n\n        return new WrappedRange(\n          startPoint.node,\n          startPoint.offset,\n          endPoint.node,\n          endPoint.offset\n        );\n      };\n\n      /**\n       * returns matched nodes on range\n       *\n       * @param {Function} [pred] - predicate function\n       * @param {Object} [options]\n       * @param {Boolean} [options.includeAncestor]\n       * @param {Boolean} [options.fullyContains]\n       * @return {Node[]}\n       */\n      this.nodes = function (pred, options) {\n        pred = pred || func.ok;\n\n        var includeAncestor = options && options.includeAncestor;\n        var fullyContains = options && options.fullyContains;\n\n        // TODO compare points and sort\n        var startPoint = this.getStartPoint();\n        var endPoint = this.getEndPoint();\n\n        var nodes = [];\n        var leftEdgeNodes = [];\n\n        dom.walkPoint(startPoint, endPoint, function (point) {\n          if (dom.isEditable(point.node)) {\n            return;\n          }\n\n          var node;\n          if (fullyContains) {\n            if (dom.isLeftEdgePoint(point)) {\n              leftEdgeNodes.push(point.node);\n            }\n            if (dom.isRightEdgePoint(point) && list.contains(leftEdgeNodes, point.node)) {\n              node = point.node;\n            }\n          } else if (includeAncestor) {\n            node = dom.ancestor(point.node, pred);\n          } else {\n            node = point.node;\n          }\n\n          if (node && pred(node)) {\n            nodes.push(node);\n          }\n        }, true);\n\n        return list.unique(nodes);\n      };\n\n      /**\n       * returns commonAncestor of range\n       * @return {Element} - commonAncestor\n       */\n      this.commonAncestor = function () {\n        return dom.commonAncestor(sc, ec);\n      };\n\n      /**\n       * returns expanded range by pred\n       *\n       * @param {Function} pred - predicate function\n       * @return {WrappedRange}\n       */\n      this.expand = function (pred) {\n        var startAncestor = dom.ancestor(sc, pred);\n        var endAncestor = dom.ancestor(ec, pred);\n\n        if (!startAncestor && !endAncestor) {\n          return new WrappedRange(sc, so, ec, eo);\n        }\n\n        var boundaryPoints = this.getPoints();\n\n        if (startAncestor) {\n          boundaryPoints.sc = startAncestor;\n          boundaryPoints.so = 0;\n        }\n\n        if (endAncestor) {\n          boundaryPoints.ec = endAncestor;\n          boundaryPoints.eo = dom.nodeLength(endAncestor);\n        }\n\n        return new WrappedRange(\n          boundaryPoints.sc,\n          boundaryPoints.so,\n          boundaryPoints.ec,\n          boundaryPoints.eo\n        );\n      };\n\n      /**\n       * @param {Boolean} isCollapseToStart\n       * @return {WrappedRange}\n       */\n      this.collapse = function (isCollapseToStart) {\n        if (isCollapseToStart) {\n          return new WrappedRange(sc, so, sc, so);\n        } else {\n          return new WrappedRange(ec, eo, ec, eo);\n        }\n      };\n\n      /**\n       * splitText on range\n       */\n      this.splitText = function () {\n        var isSameContainer = sc === ec;\n        var boundaryPoints = this.getPoints();\n\n        if (dom.isText(ec) && !dom.isEdgePoint(this.getEndPoint())) {\n          ec.splitText(eo);\n        }\n\n        if (dom.isText(sc) && !dom.isEdgePoint(this.getStartPoint())) {\n          boundaryPoints.sc = sc.splitText(so);\n          boundaryPoints.so = 0;\n\n          if (isSameContainer) {\n            boundaryPoints.ec = boundaryPoints.sc;\n            boundaryPoints.eo = eo - so;\n          }\n        }\n\n        return new WrappedRange(\n          boundaryPoints.sc,\n          boundaryPoints.so,\n          boundaryPoints.ec,\n          boundaryPoints.eo\n        );\n      };\n\n      /**\n       * delete contents on range\n       * @return {WrappedRange}\n       */\n      this.deleteContents = function () {\n        if (this.isCollapsed()) {\n          return this;\n        }\n\n        var rng = this.splitText();\n        var nodes = rng.nodes(null, {\n          fullyContains: true\n        });\n\n        // find new cursor point\n        var point = dom.prevPointUntil(rng.getStartPoint(), function (point) {\n          return !list.contains(nodes, point.node);\n        });\n\n        var emptyParents = [];\n        $.each(nodes, function (idx, node) {\n          // find empty parents\n          var parent = node.parentNode;\n          if (point.node !== parent && dom.nodeLength(parent) === 1) {\n            emptyParents.push(parent);\n          }\n          dom.remove(node, false);\n        });\n\n        // remove empty parents\n        $.each(emptyParents, function (idx, node) {\n          dom.remove(node, false);\n        });\n\n        return new WrappedRange(\n          point.node,\n          point.offset,\n          point.node,\n          point.offset\n        ).normalize();\n      };\n      \n      /**\n       * makeIsOn: return isOn(pred) function\n       */\n      var makeIsOn = function (pred) {\n        return function () {\n          var ancestor = dom.ancestor(sc, pred);\n          return !!ancestor && (ancestor === dom.ancestor(ec, pred));\n        };\n      };\n  \n      // isOnEditable: judge whether range is on editable or not\n      this.isOnEditable = makeIsOn(dom.isEditable);\n      // isOnList: judge whether range is on list node or not\n      this.isOnList = makeIsOn(dom.isList);\n      // isOnAnchor: judge whether range is on anchor node or not\n      this.isOnAnchor = makeIsOn(dom.isAnchor);\n      // isOnCell: judge whether range is on cell node or not\n      this.isOnCell = makeIsOn(dom.isCell);\n      // isOnData: judge whether range is on data node or not\n      this.isOnData = makeIsOn(dom.isData);\n\n      /**\n       * @param {Function} pred\n       * @return {Boolean}\n       */\n      this.isLeftEdgeOf = function (pred) {\n        if (!dom.isLeftEdgePoint(this.getStartPoint())) {\n          return false;\n        }\n\n        var node = dom.ancestor(this.sc, pred);\n        return node && dom.isLeftEdgeOf(this.sc, node);\n      };\n\n      /**\n       * returns whether range was collapsed or not\n       */\n      this.isCollapsed = function () {\n        return sc === ec && so === eo;\n      };\n\n      /**\n       * wrap inline nodes which children of body with paragraph\n       *\n       * @return {WrappedRange}\n       */\n      this.wrapBodyInlineWithPara = function () {\n        if (dom.isBodyContainer(sc) && dom.isEmpty(sc)) {\n          sc.innerHTML = dom.emptyPara;\n          return new WrappedRange(sc.firstChild, 0, sc.firstChild, 0);\n        }\n\n        /**\n         * [workaround] firefox often create range on not visible point. so normalize here.\n         *  - firefox: |<p>text</p>|\n         *  - chrome: <p>|text|</p>\n         */\n        var rng = this.normalize();\n        if (dom.isParaInline(sc) || dom.isPara(sc)) {\n          return rng;\n        }\n\n        // find inline top ancestor\n        var topAncestor;\n        if (dom.isInline(rng.sc)) {\n          var ancestors = dom.listAncestor(rng.sc, func.not(dom.isInline));\n          topAncestor = list.last(ancestors);\n          if (!dom.isInline(topAncestor)) {\n            topAncestor = ancestors[ancestors.length - 2] || rng.sc.childNodes[rng.so];\n          }\n        } else {\n          topAncestor = rng.sc.childNodes[rng.so > 0 ? rng.so - 1 : 0];\n        }\n\n        // siblings not in paragraph\n        var inlineSiblings = dom.listPrev(topAncestor, dom.isParaInline).reverse();\n        inlineSiblings = inlineSiblings.concat(dom.listNext(topAncestor.nextSibling, dom.isParaInline));\n\n        // wrap with paragraph\n        if (inlineSiblings.length) {\n          var para = dom.wrap(list.head(inlineSiblings), 'p');\n          dom.appendChildNodes(para, list.tail(inlineSiblings));\n        }\n\n        return this.normalize();\n      };\n\n      /**\n       * insert node at current cursor\n       *\n       * @param {Node} node\n       * @return {Node}\n       */\n      this.insertNode = function (node) {\n        var rng = this.wrapBodyInlineWithPara().deleteContents();\n        var info = dom.splitPoint(rng.getStartPoint(), dom.isInline(node));\n\n        if (info.rightNode) {\n          info.rightNode.parentNode.insertBefore(node, info.rightNode);\n        } else {\n          info.container.appendChild(node);\n        }\n\n        return node;\n      };\n\n      /**\n       * insert html at current cursor\n       */\n      this.pasteHTML = function (markup) {\n        var contentsContainer = $('<div></div>').html(markup)[0];\n        var childNodes = list.from(contentsContainer.childNodes);\n\n        var rng = this.wrapBodyInlineWithPara().deleteContents();\n\n        return childNodes.reverse().map(function (childNode) {\n          return rng.insertNode(childNode);\n        }).reverse();\n      };\n  \n      /**\n       * returns text in range\n       *\n       * @return {String}\n       */\n      this.toString = function () {\n        var nativeRng = nativeRange();\n        return agent.isW3CRangeSupport ? nativeRng.toString() : nativeRng.text;\n      };\n\n      /**\n       * returns range for word before cursor\n       *\n       * @param {Boolean} [findAfter] - find after cursor, default: false\n       * @return {WrappedRange}\n       */\n      this.getWordRange = function (findAfter) {\n        var endPoint = this.getEndPoint();\n\n        if (!dom.isCharPoint(endPoint)) {\n          return this;\n        }\n\n        var startPoint = dom.prevPointUntil(endPoint, function (point) {\n          return !dom.isCharPoint(point);\n        });\n\n        if (findAfter) {\n          endPoint = dom.nextPointUntil(endPoint, function (point) {\n            return !dom.isCharPoint(point);\n          });\n        }\n\n        return new WrappedRange(\n          startPoint.node,\n          startPoint.offset,\n          endPoint.node,\n          endPoint.offset\n        );\n      };\n  \n      /**\n       * create offsetPath bookmark\n       *\n       * @param {Node} editable\n       */\n      this.bookmark = function (editable) {\n        return {\n          s: {\n            path: dom.makeOffsetPath(editable, sc),\n            offset: so\n          },\n          e: {\n            path: dom.makeOffsetPath(editable, ec),\n            offset: eo\n          }\n        };\n      };\n\n      /**\n       * create offsetPath bookmark base on paragraph\n       *\n       * @param {Node[]} paras\n       */\n      this.paraBookmark = function (paras) {\n        return {\n          s: {\n            path: list.tail(dom.makeOffsetPath(list.head(paras), sc)),\n            offset: so\n          },\n          e: {\n            path: list.tail(dom.makeOffsetPath(list.last(paras), ec)),\n            offset: eo\n          }\n        };\n      };\n\n      /**\n       * getClientRects\n       * @return {Rect[]}\n       */\n      this.getClientRects = function () {\n        var nativeRng = nativeRange();\n        return nativeRng.getClientRects();\n      };\n    };\n\n  /**\n   * @class core.range\n   *\n   * Data structure\n   *  * BoundaryPoint: a point of dom tree\n   *  * BoundaryPoints: two boundaryPoints corresponding to the start and the end of the Range\n   *\n   * See to http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Position\n   *\n   * @singleton\n   * @alternateClassName range\n   */\n    return {\n      /**\n       * create Range Object From arguments or Browser Selection\n       *\n       * @param {Node} sc - start container\n       * @param {Number} so - start offset\n       * @param {Node} ec - end container\n       * @param {Number} eo - end offset\n       * @return {WrappedRange}\n       */\n      create: function (sc, so, ec, eo) {\n        if (arguments.length === 4) {\n          return new WrappedRange(sc, so, ec, eo);\n        } else if (arguments.length === 2) { //collapsed\n          ec = sc;\n          eo = so;\n          return new WrappedRange(sc, so, ec, eo);\n        } else {\n          var wrappedRange = this.createFromSelection();\n          if (!wrappedRange && arguments.length === 1) {\n            wrappedRange = this.createFromNode(arguments[0]);\n            return wrappedRange.collapse(dom.emptyPara === arguments[0].innerHTML);\n          }\n          return wrappedRange;\n        }\n      },\n\n      createFromSelection: function () {\n        var sc, so, ec, eo;\n        if (agent.isW3CRangeSupport) {\n          var selection = document.getSelection();\n          if (!selection || selection.rangeCount === 0) {\n            return null;\n          } else if (dom.isBody(selection.anchorNode)) {\n            // Firefox: returns entire body as range on initialization.\n            // We won't never need it.\n            return null;\n          }\n\n          var nativeRng = selection.getRangeAt(0);\n          sc = nativeRng.startContainer;\n          so = nativeRng.startOffset;\n          ec = nativeRng.endContainer;\n          eo = nativeRng.endOffset;\n        } else { // IE8: TextRange\n          var textRange = document.selection.createRange();\n          var textRangeEnd = textRange.duplicate();\n          textRangeEnd.collapse(false);\n          var textRangeStart = textRange;\n          textRangeStart.collapse(true);\n\n          var startPoint = textRangeToPoint(textRangeStart, true),\n          endPoint = textRangeToPoint(textRangeEnd, false);\n\n          // same visible point case: range was collapsed.\n          if (dom.isText(startPoint.node) && dom.isLeftEdgePoint(startPoint) &&\n              dom.isTextNode(endPoint.node) && dom.isRightEdgePoint(endPoint) &&\n              endPoint.node.nextSibling === startPoint.node) {\n            startPoint = endPoint;\n          }\n\n          sc = startPoint.cont;\n          so = startPoint.offset;\n          ec = endPoint.cont;\n          eo = endPoint.offset;\n        }\n\n        return new WrappedRange(sc, so, ec, eo);\n      },\n\n      /**\n       * @method \n       * \n       * create WrappedRange from node\n       *\n       * @param {Node} node\n       * @return {WrappedRange}\n       */\n      createFromNode: function (node) {\n        var sc = node;\n        var so = 0;\n        var ec = node;\n        var eo = dom.nodeLength(ec);\n\n        // browsers can't target a picture or void node\n        if (dom.isVoid(sc)) {\n          so = dom.listPrev(sc).length - 1;\n          sc = sc.parentNode;\n        }\n        if (dom.isBR(ec)) {\n          eo = dom.listPrev(ec).length - 1;\n          ec = ec.parentNode;\n        } else if (dom.isVoid(ec)) {\n          eo = dom.listPrev(ec).length;\n          ec = ec.parentNode;\n        }\n\n        return this.create(sc, so, ec, eo);\n      },\n\n      /**\n       * create WrappedRange from node after position\n       *\n       * @param {Node} node\n       * @return {WrappedRange}\n       */\n      createFromNodeBefore: function (node) {\n        return this.createFromNode(node).collapse(true);\n      },\n\n      /**\n       * create WrappedRange from node after position\n       *\n       * @param {Node} node\n       * @return {WrappedRange}\n       */\n      createFromNodeAfter: function (node) {\n        return this.createFromNode(node).collapse();\n      },\n\n      /**\n       * @method \n       * \n       * create WrappedRange from bookmark\n       *\n       * @param {Node} editable\n       * @param {Object} bookmark\n       * @return {WrappedRange}\n       */\n      createFromBookmark: function (editable, bookmark) {\n        var sc = dom.fromOffsetPath(editable, bookmark.s.path);\n        var so = bookmark.s.offset;\n        var ec = dom.fromOffsetPath(editable, bookmark.e.path);\n        var eo = bookmark.e.offset;\n        return new WrappedRange(sc, so, ec, eo);\n      },\n\n      /**\n       * @method \n       *\n       * create WrappedRange from paraBookmark\n       *\n       * @param {Object} bookmark\n       * @param {Node[]} paras\n       * @return {WrappedRange}\n       */\n      createFromParaBookmark: function (bookmark, paras) {\n        var so = bookmark.s.offset;\n        var eo = bookmark.e.offset;\n        var sc = dom.fromOffsetPath(list.head(paras), bookmark.s.path);\n        var ec = dom.fromOffsetPath(list.last(paras), bookmark.e.path);\n\n        return new WrappedRange(sc, so, ec, eo);\n      }\n    };\n  })();\n\n  /**\n   * @class core.async\n   *\n   * Async functions which returns `Promise`\n   *\n   * @singleton\n   * @alternateClassName async\n   */\n  var async = (function () {\n    /**\n     * @method readFileAsDataURL\n     *\n     * read contents of file as representing URL\n     *\n     * @param {File} file\n     * @return {Promise} - then: dataUrl\n     */\n    var readFileAsDataURL = function (file) {\n      return $.Deferred(function (deferred) {\n        $.extend(new FileReader(), {\n          onload: function (e) {\n            var dataURL = e.target.result;\n            deferred.resolve(dataURL);\n          },\n          onerror: function () {\n            deferred.reject(this);\n          }\n        }).readAsDataURL(file);\n      }).promise();\n    };\n  \n    /**\n     * @method createImage\n     *\n     * create `<image>` from url string\n     *\n     * @param {String} url\n     * @return {Promise} - then: $image\n     */\n    var createImage = function (url) {\n      return $.Deferred(function (deferred) {\n        var $img = $('<img>');\n\n        $img.one('load', function () {\n          $img.off('error abort');\n          deferred.resolve($img);\n        }).one('error abort', function () {\n          $img.off('load').detach();\n          deferred.reject($img);\n        }).css({\n          display: 'none'\n        }).appendTo(document.body).attr('src', url);\n      }).promise();\n    };\n\n    return {\n      readFileAsDataURL: readFileAsDataURL,\n      createImage: createImage\n    };\n  })();\n\n  /**\n   * @class editing.History\n   *\n   * Editor History\n   *\n   */\n  var History = function ($editable) {\n    var stack = [], stackOffset = -1;\n    var editable = $editable[0];\n\n    var makeSnapshot = function () {\n      var rng = range.create(editable);\n      var emptyBookmark = {s: {path: [], offset: 0}, e: {path: [], offset: 0}};\n\n      return {\n        contents: $editable.html(),\n        bookmark: (rng ? rng.bookmark(editable) : emptyBookmark)\n      };\n    };\n\n    var applySnapshot = function (snapshot) {\n      if (snapshot.contents !== null) {\n        $editable.html(snapshot.contents);\n      }\n      if (snapshot.bookmark !== null) {\n        range.createFromBookmark(editable, snapshot.bookmark).select();\n      }\n    };\n\n    /**\n    * @method rewind\n    * Rewinds the history stack back to the first snapshot taken.\n    * Leaves the stack intact, so that \"Redo\" can still be used.\n    */\n    this.rewind = function () {\n      // Create snap shot if not yet recorded\n      if ($editable.html() !== stack[stackOffset].contents) {\n        this.recordUndo();\n      }\n\n      // Return to the first available snapshot.\n      stackOffset = 0;\n\n      // Apply that snapshot.\n      applySnapshot(stack[stackOffset]);\n    };\n\n    /**\n    * @method reset\n    * Resets the history stack completely; reverting to an empty editor.\n    */\n    this.reset = function () {\n      // Clear the stack.\n      stack = [];\n\n      // Restore stackOffset to its original value.\n      stackOffset = -1;\n\n      // Clear the editable area.\n      $editable.html('');\n\n      // Record our first snapshot (of nothing).\n      this.recordUndo();\n    };\n\n    /**\n     * undo\n     */\n    this.undo = function () {\n      // Create snap shot if not yet recorded\n      if ($editable.html() !== stack[stackOffset].contents) {\n        this.recordUndo();\n      }\n\n      if (0 < stackOffset) {\n        stackOffset--;\n        applySnapshot(stack[stackOffset]);\n      }\n    };\n\n    /**\n     * redo\n     */\n    this.redo = function () {\n      if (stack.length - 1 > stackOffset) {\n        stackOffset++;\n        applySnapshot(stack[stackOffset]);\n      }\n    };\n\n    /**\n     * recorded undo\n     */\n    this.recordUndo = function () {\n      stackOffset++;\n\n      // Wash out stack after stackOffset\n      if (stack.length > stackOffset) {\n        stack = stack.slice(0, stackOffset);\n      }\n\n      // Create new snapshot and push it to the end\n      stack.push(makeSnapshot());\n    };\n  };\n\n  /**\n   * @class editing.Style\n   *\n   * Style\n   *\n   */\n  var Style = function () {\n    /**\n     * @method jQueryCSS\n     *\n     * [workaround] for old jQuery\n     * passing an array of style properties to .css()\n     * will result in an object of property-value pairs.\n     * (compability with version < 1.9)\n     *\n     * @private\n     * @param  {jQuery} $obj\n     * @param  {Array} propertyNames - An array of one or more CSS properties.\n     * @return {Object}\n     */\n    var jQueryCSS = function ($obj, propertyNames) {\n      if (agent.jqueryVersion < 1.9) {\n        var result = {};\n        $.each(propertyNames, function (idx, propertyName) {\n          result[propertyName] = $obj.css(propertyName);\n        });\n        return result;\n      }\n      return $obj.css.call($obj, propertyNames);\n    };\n\n    /**\n     * returns style object from node\n     *\n     * @param {jQuery} $node\n     * @return {Object}\n     */\n    this.fromNode = function ($node) {\n      var properties = ['font-family', 'font-size', 'text-align', 'list-style-type', 'line-height'];\n      var styleInfo = jQueryCSS($node, properties) || {};\n      styleInfo['font-size'] = parseInt(styleInfo['font-size'], 10);\n      return styleInfo;\n    };\n\n    /**\n     * paragraph level style\n     *\n     * @param {WrappedRange} rng\n     * @param {Object} styleInfo\n     */\n    this.stylePara = function (rng, styleInfo) {\n      $.each(rng.nodes(dom.isPara, {\n        includeAncestor: true\n      }), function (idx, para) {\n        $(para).css(styleInfo);\n      });\n    };\n\n    /**\n     * insert and returns styleNodes on range.\n     *\n     * @param {WrappedRange} rng\n     * @param {Object} [options] - options for styleNodes\n     * @param {String} [options.nodeName] - default: `SPAN`\n     * @param {Boolean} [options.expandClosestSibling] - default: `false`\n     * @param {Boolean} [options.onlyPartialContains] - default: `false`\n     * @return {Node[]}\n     */\n    this.styleNodes = function (rng, options) {\n      rng = rng.splitText();\n\n      var nodeName = options && options.nodeName || 'SPAN';\n      var expandClosestSibling = !!(options && options.expandClosestSibling);\n      var onlyPartialContains = !!(options && options.onlyPartialContains);\n\n      if (rng.isCollapsed()) {\n        return [rng.insertNode(dom.create(nodeName))];\n      }\n\n      var pred = dom.makePredByNodeName(nodeName);\n      var nodes = rng.nodes(dom.isText, {\n        fullyContains: true\n      }).map(function (text) {\n        return dom.singleChildAncestor(text, pred) || dom.wrap(text, nodeName);\n      });\n\n      if (expandClosestSibling) {\n        if (onlyPartialContains) {\n          var nodesInRange = rng.nodes();\n          // compose with partial contains predication\n          pred = func.and(pred, function (node) {\n            return list.contains(nodesInRange, node);\n          });\n        }\n\n        return nodes.map(function (node) {\n          var siblings = dom.withClosestSiblings(node, pred);\n          var head = list.head(siblings);\n          var tails = list.tail(siblings);\n          $.each(tails, function (idx, elem) {\n            dom.appendChildNodes(head, elem.childNodes);\n            dom.remove(elem);\n          });\n          return list.head(siblings);\n        });\n      } else {\n        return nodes;\n      }\n    };\n\n    /**\n     * get current style on cursor\n     *\n     * @param {WrappedRange} rng\n     * @return {Object} - object contains style properties.\n     */\n    this.current = function (rng) {\n      var $cont = $(!dom.isElement(rng.sc) ? rng.sc.parentNode : rng.sc);\n      var styleInfo = this.fromNode($cont);\n\n      // document.queryCommandState for toggle state\n      // [workaround] prevent Firefox nsresult: \"0x80004005 (NS_ERROR_FAILURE)\"\n      try {\n        styleInfo = $.extend(styleInfo, {\n          'font-bold': document.queryCommandState('bold') ? 'bold' : 'normal',\n          'font-italic': document.queryCommandState('italic') ? 'italic' : 'normal',\n          'font-underline': document.queryCommandState('underline') ? 'underline' : 'normal',\n          'font-subscript': document.queryCommandState('subscript') ? 'subscript' : 'normal',\n          'font-superscript': document.queryCommandState('superscript') ? 'superscript' : 'normal',\n          'font-strikethrough': document.queryCommandState('strikethrough') ? 'strikethrough' : 'normal'\n        });\n      } catch (e) {}\n\n      // list-style-type to list-style(unordered, ordered)\n      if (!rng.isOnList()) {\n        styleInfo['list-style'] = 'none';\n      } else {\n        var orderedTypes = ['circle', 'disc', 'disc-leading-zero', 'square'];\n        var isUnordered = $.inArray(styleInfo['list-style-type'], orderedTypes) > -1;\n        styleInfo['list-style'] = isUnordered ? 'unordered' : 'ordered';\n      }\n\n      var para = dom.ancestor(rng.sc, dom.isPara);\n      if (para && para.style['line-height']) {\n        styleInfo['line-height'] = para.style.lineHeight;\n      } else {\n        var lineHeight = parseInt(styleInfo['line-height'], 10) / parseInt(styleInfo['font-size'], 10);\n        styleInfo['line-height'] = lineHeight.toFixed(1);\n      }\n\n      styleInfo.anchor = rng.isOnAnchor() && dom.ancestor(rng.sc, dom.isAnchor);\n      styleInfo.ancestors = dom.listAncestor(rng.sc, dom.isEditable);\n      styleInfo.range = rng;\n\n      return styleInfo;\n    };\n  };\n\n\n  /**\n   * @class editing.Bullet\n   *\n   * @alternateClassName Bullet\n   */\n  var Bullet = function () {\n    var self = this;\n\n    /**\n     * toggle ordered list\n     */\n    this.insertOrderedList = function (editable) {\n      this.toggleList('OL', editable);\n    };\n\n    /**\n     * toggle unordered list\n     */\n    this.insertUnorderedList = function (editable) {\n      this.toggleList('UL', editable);\n    };\n\n    /**\n     * indent\n     */\n    this.indent = function (editable) {\n      var self = this;\n      var rng = range.create(editable).wrapBodyInlineWithPara();\n\n      var paras = rng.nodes(dom.isPara, { includeAncestor: true });\n      var clustereds = list.clusterBy(paras, func.peq2('parentNode'));\n\n      $.each(clustereds, function (idx, paras) {\n        var head = list.head(paras);\n        if (dom.isLi(head)) {\n          self.wrapList(paras, head.parentNode.nodeName);\n        } else {\n          $.each(paras, function (idx, para) {\n            $(para).css('marginLeft', function (idx, val) {\n              return (parseInt(val, 10) || 0) + 25;\n            });\n          });\n        }\n      });\n\n      rng.select();\n    };\n\n    /**\n     * outdent\n     */\n    this.outdent = function (editable) {\n      var self = this;\n      var rng = range.create(editable).wrapBodyInlineWithPara();\n\n      var paras = rng.nodes(dom.isPara, { includeAncestor: true });\n      var clustereds = list.clusterBy(paras, func.peq2('parentNode'));\n\n      $.each(clustereds, function (idx, paras) {\n        var head = list.head(paras);\n        if (dom.isLi(head)) {\n          self.releaseList([paras]);\n        } else {\n          $.each(paras, function (idx, para) {\n            $(para).css('marginLeft', function (idx, val) {\n              val = (parseInt(val, 10) || 0);\n              return val > 25 ? val - 25 : '';\n            });\n          });\n        }\n      });\n\n      rng.select();\n    };\n\n    /**\n     * toggle list\n     *\n     * @param {String} listName - OL or UL\n     */\n    this.toggleList = function (listName, editable) {\n      var rng = range.create(editable).wrapBodyInlineWithPara();\n\n      var paras = rng.nodes(dom.isPara, { includeAncestor: true });\n      var bookmark = rng.paraBookmark(paras);\n      var clustereds = list.clusterBy(paras, func.peq2('parentNode'));\n\n      // paragraph to list\n      if (list.find(paras, dom.isPurePara)) {\n        var wrappedParas = [];\n        $.each(clustereds, function (idx, paras) {\n          wrappedParas = wrappedParas.concat(self.wrapList(paras, listName));\n        });\n        paras = wrappedParas;\n      // list to paragraph or change list style\n      } else {\n        var diffLists = rng.nodes(dom.isList, {\n          includeAncestor: true\n        }).filter(function (listNode) {\n          return !$.nodeName(listNode, listName);\n        });\n\n        if (diffLists.length) {\n          $.each(diffLists, function (idx, listNode) {\n            dom.replace(listNode, listName);\n          });\n        } else {\n          paras = this.releaseList(clustereds, true);\n        }\n      }\n\n      range.createFromParaBookmark(bookmark, paras).select();\n    };\n\n    /**\n     * @param {Node[]} paras\n     * @param {String} listName\n     * @return {Node[]}\n     */\n    this.wrapList = function (paras, listName) {\n      var head = list.head(paras);\n      var last = list.last(paras);\n\n      var prevList = dom.isList(head.previousSibling) && head.previousSibling;\n      var nextList = dom.isList(last.nextSibling) && last.nextSibling;\n\n      var listNode = prevList || dom.insertAfter(dom.create(listName || 'UL'), last);\n\n      // P to LI\n      paras = paras.map(function (para) {\n        return dom.isPurePara(para) ? dom.replace(para, 'LI') : para;\n      });\n\n      // append to list(<ul>, <ol>)\n      dom.appendChildNodes(listNode, paras);\n\n      if (nextList) {\n        dom.appendChildNodes(listNode, list.from(nextList.childNodes));\n        dom.remove(nextList);\n      }\n\n      return paras;\n    };\n\n    /**\n     * @method releaseList\n     *\n     * @param {Array[]} clustereds\n     * @param {Boolean} isEscapseToBody\n     * @return {Node[]}\n     */\n    this.releaseList = function (clustereds, isEscapseToBody) {\n      var releasedParas = [];\n\n      $.each(clustereds, function (idx, paras) {\n        var head = list.head(paras);\n        var last = list.last(paras);\n\n        var headList = isEscapseToBody ? dom.lastAncestor(head, dom.isList) :\n                                         head.parentNode;\n        var lastList = headList.childNodes.length > 1 ? dom.splitTree(headList, {\n          node: last.parentNode,\n          offset: dom.position(last) + 1\n        }, {\n          isSkipPaddingBlankHTML: true\n        }) : null;\n\n        var middleList = dom.splitTree(headList, {\n          node: head.parentNode,\n          offset: dom.position(head)\n        }, {\n          isSkipPaddingBlankHTML: true\n        });\n\n        paras = isEscapseToBody ? dom.listDescendant(middleList, dom.isLi) :\n                                  list.from(middleList.childNodes).filter(dom.isLi);\n\n        // LI to P\n        if (isEscapseToBody || !dom.isList(headList.parentNode)) {\n          paras = paras.map(function (para) {\n            return dom.replace(para, 'P');\n          });\n        }\n\n        $.each(list.from(paras).reverse(), function (idx, para) {\n          dom.insertAfter(para, headList);\n        });\n\n        // remove empty lists\n        var rootLists = list.compact([headList, middleList, lastList]);\n        $.each(rootLists, function (idx, rootList) {\n          var listNodes = [rootList].concat(dom.listDescendant(rootList, dom.isList));\n          $.each(listNodes.reverse(), function (idx, listNode) {\n            if (!dom.nodeLength(listNode)) {\n              dom.remove(listNode, true);\n            }\n          });\n        });\n\n        releasedParas = releasedParas.concat(paras);\n      });\n\n      return releasedParas;\n    };\n  };\n\n\n  /**\n   * @class editing.Typing\n   *\n   * Typing\n   *\n   */\n  var Typing = function () {\n\n    // a Bullet instance to toggle lists off\n    var bullet = new Bullet();\n\n    /**\n     * insert tab\n     *\n     * @param {WrappedRange} rng\n     * @param {Number} tabsize\n     */\n    this.insertTab = function (rng, tabsize) {\n      var tab = dom.createText(new Array(tabsize + 1).join(dom.NBSP_CHAR));\n      rng = rng.deleteContents();\n      rng.insertNode(tab, true);\n\n      rng = range.create(tab, tabsize);\n      rng.select();\n    };\n\n    /**\n     * insert paragraph\n     */\n    this.insertParagraph = function (editable) {\n      var rng = range.create(editable);\n\n      // deleteContents on range.\n      rng = rng.deleteContents();\n\n      // Wrap range if it needs to be wrapped by paragraph\n      rng = rng.wrapBodyInlineWithPara();\n\n      // finding paragraph\n      var splitRoot = dom.ancestor(rng.sc, dom.isPara);\n\n      var nextPara;\n      // on paragraph: split paragraph\n      if (splitRoot) {\n        // if it is an empty line with li\n        if (dom.isEmpty(splitRoot) && dom.isLi(splitRoot)) {\n          // toogle UL/OL and escape\n          bullet.toggleList(splitRoot.parentNode.nodeName);\n          return;\n        // if it is an empty line with para on blockquote\n        } else if (dom.isEmpty(splitRoot) && dom.isPara(splitRoot) && dom.isBlockquote(splitRoot.parentNode)) {\n          // escape blockquote\n          dom.insertAfter(splitRoot, splitRoot.parentNode);\n          nextPara = splitRoot;\n        // if new line has content (not a line break)\n        } else {\n          nextPara = dom.splitTree(splitRoot, rng.getStartPoint());\n\n          var emptyAnchors = dom.listDescendant(splitRoot, dom.isEmptyAnchor);\n          emptyAnchors = emptyAnchors.concat(dom.listDescendant(nextPara, dom.isEmptyAnchor));\n\n          $.each(emptyAnchors, function (idx, anchor) {\n            dom.remove(anchor);\n          });\n\n          // replace empty heading or pre with P tag\n          if ((dom.isHeading(nextPara) || dom.isPre(nextPara)) && dom.isEmpty(nextPara)) {\n            nextPara = dom.replace(nextPara, 'p');\n          }\n        }\n      // no paragraph: insert empty paragraph\n      } else {\n        var next = rng.sc.childNodes[rng.so];\n        nextPara = $(dom.emptyPara)[0];\n        if (next) {\n          rng.sc.insertBefore(nextPara, next);\n        } else {\n          rng.sc.appendChild(nextPara);\n        }\n      }\n\n      range.create(nextPara, 0).normalize().select().scrollIntoView(editable);\n    };\n  };\n\n  /**\n   * @class editing.Table\n   *\n   * Table\n   *\n   */\n  var Table = function () {\n    /**\n     * handle tab key\n     *\n     * @param {WrappedRange} rng\n     * @param {Boolean} isShift\n     */\n    this.tab = function (rng, isShift) {\n      var cell = dom.ancestor(rng.commonAncestor(), dom.isCell);\n      var table = dom.ancestor(cell, dom.isTable);\n      var cells = dom.listDescendant(table, dom.isCell);\n\n      var nextCell = list[isShift ? 'prev' : 'next'](cells, cell);\n      if (nextCell) {\n        range.create(nextCell, 0).select();\n      }\n    };\n\n    /**\n     * create empty table element\n     *\n     * @param {Number} rowCount\n     * @param {Number} colCount\n     * @return {Node}\n     */\n    this.createTable = function (colCount, rowCount, options) {\n      var tds = [], tdHTML;\n      for (var idxCol = 0; idxCol < colCount; idxCol++) {\n        tds.push('<td>' + dom.blank + '</td>');\n      }\n      tdHTML = tds.join('');\n\n      var trs = [], trHTML;\n      for (var idxRow = 0; idxRow < rowCount; idxRow++) {\n        trs.push('<tr>' + tdHTML + '</tr>');\n      }\n      trHTML = trs.join('');\n      var $table = $('<table>' + trHTML + '</table>');\n      if (options && options.tableClassName) {\n        $table.addClass(options.tableClassName);\n      }\n\n      return $table[0];\n    };\n  };\n\n\n  var KEY_BOGUS = 'bogus';\n\n  /**\n   * @class Editor\n   */\n  var Editor = function (context) {\n    var self = this;\n\n    var $note = context.layoutInfo.note;\n    var $editor = context.layoutInfo.editor;\n    var $editable = context.layoutInfo.editable;\n    var options = context.options;\n    var lang = options.langInfo;\n\n    var editable = $editable[0];\n    var lastRange = null;\n\n    var style = new Style();\n    var table = new Table();\n    var typing = new Typing();\n    var bullet = new Bullet();\n    var history = new History($editable);\n\n    this.initialize = function () {\n      // bind custom events\n      $editable.on('keydown', function (event) {\n        if (event.keyCode === key.code.ENTER) {\n          context.triggerEvent('enter', event);\n        }\n        context.triggerEvent('keydown', event);\n\n        if (!event.isDefaultPrevented()) {\n          if (options.shortcuts) {\n            self.handleKeyMap(event);\n          } else {\n            self.preventDefaultEditableShortCuts(event);\n          }\n        }\n      }).on('keyup', function (event) {\n        context.triggerEvent('keyup', event);\n      }).on('focus', function (event) {\n        context.triggerEvent('focus', event);\n      }).on('blur', function (event) {\n        context.triggerEvent('blur', event);\n      }).on('mousedown', function (event) {\n        context.triggerEvent('mousedown', event);\n      }).on('mouseup', function (event) {\n        context.triggerEvent('mouseup', event);\n      }).on('scroll', function (event) {\n        context.triggerEvent('scroll', event);\n      }).on('paste', function (event) {\n        context.triggerEvent('paste', event);\n      });\n\n      // init content before set event\n      $editable.html(dom.html($note) || dom.emptyPara);\n\n      // [workaround] IE doesn't have input events for contentEditable\n      // - see: https://goo.gl/4bfIvA\n      var changeEventName = agent.isMSIE ? 'DOMCharacterDataModified DOMSubtreeModified DOMNodeInserted' : 'input';\n      $editable.on(changeEventName, func.debounce(function () {\n        context.triggerEvent('change', $editable.html());\n      }, 250));\n\n      $editor.on('focusin', function (event) {\n        context.triggerEvent('focusin', event);\n      }).on('focusout', function (event) {\n        context.triggerEvent('focusout', event);\n      });\n\n      if (!options.airMode) {\n        if (options.width) {\n          $editor.outerWidth(options.width);\n        }\n        if (options.height) {\n          $editable.outerHeight(options.height);\n        }\n        if (options.maxHeight) {\n          $editable.css('max-height', options.maxHeight);\n        }\n        if (options.minHeight) {\n          $editable.css('min-height', options.minHeight);\n        }\n      }\n\n      history.recordUndo();\n    };\n\n    this.destroy = function () {\n      $editable.off();\n    };\n\n    this.handleKeyMap = function (event) {\n      var keyMap = options.keyMap[agent.isMac ? 'mac' : 'pc'];\n      var keys = [];\n\n      if (event.metaKey) { keys.push('CMD'); }\n      if (event.ctrlKey && !event.altKey) { keys.push('CTRL'); }\n      if (event.shiftKey) { keys.push('SHIFT'); }\n\n      var keyName = key.nameFromCode[event.keyCode];\n      if (keyName) {\n        keys.push(keyName);\n      }\n\n      var eventName = keyMap[keys.join('+')];\n      if (eventName) {\n        event.preventDefault();\n        context.invoke(eventName);\n      } else if (key.isEdit(event.keyCode)) {\n        this.afterCommand();\n      }\n    };\n\n    this.preventDefaultEditableShortCuts = function (event) {\n      // B(Bold, 66) / I(Italic, 73) / U(Underline, 85)\n      if ((event.ctrlKey || event.metaKey) &&\n        list.contains([66, 73, 85], event.keyCode)) {\n        event.preventDefault();\n      }\n    };\n\n    /**\n     * create range\n     * @return {WrappedRange}\n     */\n    this.createRange = function () {\n      this.focus();\n      return range.create(editable);\n    };\n\n    /**\n     * saveRange\n     *\n     * save current range\n     *\n     * @param {Boolean} [thenCollapse=false]\n     */\n    this.saveRange = function (thenCollapse) {\n      lastRange = this.createRange();\n      if (thenCollapse) {\n        lastRange.collapse().select();\n      }\n    };\n\n    /**\n     * restoreRange\n     *\n     * restore lately range\n     */\n    this.restoreRange = function () {\n      if (lastRange) {\n        lastRange.select();\n        this.focus();\n      }\n    };\n\n    this.saveTarget = function (node) {\n      $editable.data('target', node);\n    };\n\n    this.clearTarget = function () {\n      $editable.removeData('target');\n    };\n\n    this.restoreTarget = function () {\n      return $editable.data('target');\n    };\n\n    /**\n     * currentStyle\n     *\n     * current style\n     * @return {Object|Boolean} unfocus\n     */\n    this.currentStyle = function () {\n      var rng = range.create();\n      if (rng) {\n        rng = rng.normalize();\n      }\n      return rng ? style.current(rng) : style.fromNode($editable);\n    };\n\n    /**\n     * style from node\n     *\n     * @param {jQuery} $node\n     * @return {Object}\n     */\n    this.styleFromNode = function ($node) {\n      return style.fromNode($node);\n    };\n\n    /**\n     * undo\n     */\n    this.undo = function () {\n      context.triggerEvent('before.command', $editable.html());\n      history.undo();\n      context.triggerEvent('change', $editable.html());\n    };\n    context.memo('help.undo', lang.help.undo);\n\n    /**\n     * redo\n     */\n    this.redo = function () {\n      context.triggerEvent('before.command', $editable.html());\n      history.redo();\n      context.triggerEvent('change', $editable.html());\n    };\n    context.memo('help.redo', lang.help.redo);\n\n    /**\n     * before command\n     */\n    var beforeCommand = this.beforeCommand = function () {\n      context.triggerEvent('before.command', $editable.html());\n      // keep focus on editable before command execution\n      self.focus();\n    };\n\n    /**\n     * after command\n     * @param {Boolean} isPreventTrigger\n     */\n    var afterCommand = this.afterCommand = function (isPreventTrigger) {\n      history.recordUndo();\n      if (!isPreventTrigger) {\n        context.triggerEvent('change', $editable.html());\n      }\n    };\n\n    /* jshint ignore:start */\n    // native commands(with execCommand), generate function for execCommand\n    var commands = ['bold', 'italic', 'underline', 'strikethrough', 'superscript', 'subscript',\n                    'justifyLeft', 'justifyCenter', 'justifyRight', 'justifyFull',\n                    'formatBlock', 'removeFormat',\n                    'backColor', 'foreColor', 'fontName'];\n\n    for (var idx = 0, len = commands.length; idx < len; idx ++) {\n      this[commands[idx]] = (function (sCmd) {\n        return function (value) {\n          beforeCommand();\n          document.execCommand(sCmd, false, value);\n          afterCommand(true);\n        };\n      })(commands[idx]);\n      context.memo('help.' + commands[idx], lang.help[commands[idx]]);\n    }\n    /* jshint ignore:end */\n\n    /**\n     * handle tab key\n     */\n    this.tab = function () {\n      var rng = this.createRange();\n      if (rng.isCollapsed() && rng.isOnCell()) {\n        table.tab(rng);\n      } else {\n        beforeCommand();\n        typing.insertTab(rng, options.tabSize);\n        afterCommand();\n      }\n    };\n    context.memo('help.tab', lang.help.tab);\n\n    /**\n     * handle shift+tab key\n     */\n    this.untab = function () {\n      var rng = this.createRange();\n      if (rng.isCollapsed() && rng.isOnCell()) {\n        table.tab(rng, true);\n      }\n    };\n    context.memo('help.untab', lang.help.untab);\n\n    /**\n     * run given function between beforeCommand and afterCommand\n     */\n    this.wrapCommand = function (fn) {\n      return function () {\n        beforeCommand();\n        fn.apply(self, arguments);\n        afterCommand();\n      };\n    };\n\n    /**\n     * insert paragraph\n     */\n    this.insertParagraph = this.wrapCommand(function () {\n      typing.insertParagraph(editable);\n    });\n    context.memo('help.insertParagraph', lang.help.insertParagraph);\n\n    this.insertOrderedList = this.wrapCommand(function () {\n      bullet.insertOrderedList(editable);\n    });\n    context.memo('help.insertOrderedList', lang.help.insertOrderedList);\n\n    this.insertUnorderedList = this.wrapCommand(function () {\n      bullet.insertUnorderedList(editable);\n    });\n    context.memo('help.insertUnorderedList', lang.help.insertUnorderedList);\n\n    this.indent = this.wrapCommand(function () {\n      bullet.indent(editable);\n    });\n    context.memo('help.indent', lang.help.indent);\n\n    this.outdent = this.wrapCommand(function () {\n      bullet.outdent(editable);\n    });\n    context.memo('help.outdent', lang.help.outdent);\n\n    /**\n     * insert image\n     *\n     * @param {String} src\n     * @param {String|Function} param\n     * @return {Promise}\n     */\n    this.insertImage = function (src, param) {\n      return async.createImage(src, param).then(function ($image) {\n        beforeCommand();\n\n        if (typeof param === 'function') {\n          param($image);\n        } else {\n          if (typeof param === 'string') {\n            $image.attr('data-filename', param);\n          }\n          $image.css('width', Math.min($editable.width(), $image.width()));\n        }\n\n        $image.show();\n        range.create(editable).insertNode($image[0]);\n        range.createFromNodeAfter($image[0]).select();\n        afterCommand();\n      }).fail(function (e) {\n        context.triggerEvent('image.upload.error', e);\n      });\n    };\n\n    /**\n     * insertImages\n     * @param {File[]} files\n     */\n    this.insertImages = function (files) {\n      $.each(files, function (idx, file) {\n        var filename = file.name;\n        if (options.maximumImageFileSize && options.maximumImageFileSize < file.size) {\n          context.triggerEvent('image.upload.error', lang.image.maximumFileSizeError);\n        } else {\n          async.readFileAsDataURL(file).then(function (dataURL) {\n            return self.insertImage(dataURL, filename);\n          }).fail(function () {\n            context.triggerEvent('image.upload.error');\n          });\n        }\n      });\n    };\n\n    /**\n     * insertImagesOrCallback\n     * @param {File[]} files\n     */\n    this.insertImagesOrCallback = function (files) {\n      var callbacks = options.callbacks;\n\n      // If onImageUpload options setted\n      if (callbacks.onImageUpload) {\n        context.triggerEvent('image.upload', files);\n      // else insert Image as dataURL\n      } else {\n        this.insertImages(files);\n      }\n    };\n\n    /**\n     * insertNode\n     * insert node\n     * @param {Node} node\n     */\n    this.insertNode = this.wrapCommand(function (node) {\n      var rng = this.createRange();\n      rng.insertNode(node);\n      range.createFromNodeAfter(node).select();\n    });\n\n    /**\n     * insert text\n     * @param {String} text\n     */\n    this.insertText = this.wrapCommand(function (text) {\n      var rng = this.createRange();\n      var textNode = rng.insertNode(dom.createText(text));\n      range.create(textNode, dom.nodeLength(textNode)).select();\n    });\n\n    /**\n     * return selected plain text\n     * @return {String} text\n     */\n    this.getSelectedText = function () {\n      var rng = this.createRange();\n\n      // if range on anchor, expand range with anchor\n      if (rng.isOnAnchor()) {\n        rng = range.createFromNode(dom.ancestor(rng.sc, dom.isAnchor));\n      }\n\n      return rng.toString();\n    };\n\n    /**\n     * paste HTML\n     * @param {String} markup\n     */\n    this.pasteHTML = this.wrapCommand(function (markup) {\n      var contents = this.createRange().pasteHTML(markup);\n      range.createFromNodeAfter(list.last(contents)).select();\n    });\n\n    /**\n     * formatBlock\n     *\n     * @param {String} tagName\n     */\n    this.formatBlock = this.wrapCommand(function (tagName) {\n      // [workaround] for MSIE, IE need `<`\n      tagName = agent.isMSIE ? '<' + tagName + '>' : tagName;\n      document.execCommand('FormatBlock', false, tagName);\n    });\n\n    this.formatPara = function () {\n      this.formatBlock('P');\n    };\n    context.memo('help.formatPara', lang.help.formatPara);\n\n    /* jshint ignore:start */\n    for (var idx = 1; idx <= 6; idx ++) {\n      this['formatH' + idx] = function (idx) {\n        return function () {\n          this.formatBlock('H' + idx);\n        };\n      }(idx);\n      context.memo('help.formatH'+idx, lang.help['formatH' + idx]);\n    };\n    /* jshint ignore:end */\n\n    /**\n     * fontSize\n     *\n     * @param {String} value - px\n     */\n    this.fontSize = function (value) {\n      var rng = this.createRange();\n\n      if (rng && rng.isCollapsed()) {\n        var spans = style.styleNodes(rng);\n        var firstSpan = list.head(spans);\n\n        $(spans).css({\n          'font-size': value + 'px'\n        });\n\n        // [workaround] added styled bogus span for style\n        //  - also bogus character needed for cursor position\n        if (firstSpan && !dom.nodeLength(firstSpan)) {\n          firstSpan.innerHTML = dom.ZERO_WIDTH_NBSP_CHAR;\n          range.createFromNodeAfter(firstSpan.firstChild).select();\n          $editable.data(KEY_BOGUS, firstSpan);\n        }\n      } else {\n        beforeCommand();\n        $(style.styleNodes(rng)).css({\n          'font-size': value + 'px'\n        });\n        afterCommand();\n      }\n    };\n\n    /**\n     * insert horizontal rule\n     */\n    this.insertHorizontalRule = this.wrapCommand(function () {\n      var hrNode = this.createRange().insertNode(dom.create('HR'));\n      if (hrNode.nextSibling) {\n        range.create(hrNode.nextSibling, 0).normalize().select();\n      }\n    });\n    context.memo('help.insertHorizontalRule', lang.help.insertHorizontalRule);\n\n    /**\n     * remove bogus node and character\n     */\n    this.removeBogus = function () {\n      var bogusNode = $editable.data(KEY_BOGUS);\n      if (!bogusNode) {\n        return;\n      }\n\n      var textNode = list.find(list.from(bogusNode.childNodes), dom.isText);\n\n      var bogusCharIdx = textNode.nodeValue.indexOf(dom.ZERO_WIDTH_NBSP_CHAR);\n      if (bogusCharIdx !== -1) {\n        textNode.deleteData(bogusCharIdx, 1);\n      }\n\n      if (dom.isEmpty(bogusNode)) {\n        dom.remove(bogusNode);\n      }\n\n      $editable.removeData(KEY_BOGUS);\n    };\n\n    /**\n     * lineHeight\n     * @param {String} value\n     */\n    this.lineHeight = this.wrapCommand(function (value) {\n      style.stylePara(this.createRange(), {\n        lineHeight: value\n      });\n    });\n\n    /**\n     * unlink\n     *\n     * @type command\n     */\n    this.unlink = function () {\n      var rng = this.createRange();\n      if (rng.isOnAnchor()) {\n        var anchor = dom.ancestor(rng.sc, dom.isAnchor);\n        rng = range.createFromNode(anchor);\n        rng.select();\n\n        beforeCommand();\n        document.execCommand('unlink');\n        afterCommand();\n      }\n    };\n\n    /**\n     * create link (command)\n     *\n     * @param {Object} linkInfo\n     */\n    this.createLink = this.wrapCommand(function (linkInfo) {\n      var linkUrl = linkInfo.url;\n      var linkText = linkInfo.text;\n      var isNewWindow = linkInfo.isNewWindow;\n      var rng = linkInfo.range || this.createRange();\n      var isTextChanged = rng.toString() !== linkText;\n\n      // handle spaced urls from input\n      if (typeof linkUrl === 'string') {\n        linkUrl = linkUrl.trim();\n      }\n\n      if (options.onCreateLink) {\n        linkUrl = options.onCreateLink(linkUrl);\n      }\n\n      var anchors = [];\n      if (isTextChanged) {\n        rng = rng.deleteContents();\n        var anchor = rng.insertNode($('<A>' + linkText + '</A>')[0]);\n        anchors.push(anchor);\n      } else {\n        anchors = style.styleNodes(rng, {\n          nodeName: 'A',\n          expandClosestSibling: true,\n          onlyPartialContains: true\n        });\n      }\n\n      $.each(anchors, function (idx, anchor) {\n        // if url doesn't match an URL schema, set http:// as default\n        linkUrl = /^[A-Za-z][A-Za-z0-9+-.]*\\:[\\/\\/]?/.test(linkUrl) ?\n          linkUrl : 'http://' + linkUrl;\n\n        $(anchor).attr('href', linkUrl);\n        if (isNewWindow) {\n          $(anchor).attr('target', '_blank');\n        } else {\n          $(anchor).removeAttr('target');\n        }\n      });\n\n      var startRange = range.createFromNodeBefore(list.head(anchors));\n      var startPoint = startRange.getStartPoint();\n      var endRange = range.createFromNodeAfter(list.last(anchors));\n      var endPoint = endRange.getEndPoint();\n\n      range.create(\n        startPoint.node,\n        startPoint.offset,\n        endPoint.node,\n        endPoint.offset\n      ).select();\n    });\n\n    /**\n     * returns link info\n     *\n     * @return {Object}\n     * @return {WrappedRange} return.range\n     * @return {String} return.text\n     * @return {Boolean} [return.isNewWindow=true]\n     * @return {String} [return.url=\"\"]\n     */\n    this.getLinkInfo = function () {\n      var rng = this.createRange().expand(dom.isAnchor);\n\n      // Get the first anchor on range(for edit).\n      var $anchor = $(list.head(rng.nodes(dom.isAnchor)));\n\n      return {\n        range: rng,\n        text: rng.toString(),\n        isNewWindow: $anchor.length ? $anchor.attr('target') === '_blank' : false,\n        url: $anchor.length ? $anchor.attr('href') : ''\n      };\n    };\n\n    /**\n     * setting color\n     *\n     * @param {Object} sObjColor  color code\n     * @param {String} sObjColor.foreColor foreground color\n     * @param {String} sObjColor.backColor background color\n     */\n    this.color = this.wrapCommand(function (colorInfo) {\n      var foreColor = colorInfo.foreColor;\n      var backColor = colorInfo.backColor;\n\n      if (foreColor) { document.execCommand('foreColor', false, foreColor); }\n      if (backColor) { document.execCommand('backColor', false, backColor); }\n    });\n\n    /**\n     * insert Table\n     *\n     * @param {String} dimension of table (ex : \"5x5\")\n     */\n    this.insertTable = this.wrapCommand(function (dim) {\n      var dimension = dim.split('x');\n\n      var rng = this.createRange().deleteContents();\n      rng.insertNode(table.createTable(dimension[0], dimension[1], options));\n    });\n\n    /**\n     * float me\n     *\n     * @param {String} value\n     */\n    this.floatMe = this.wrapCommand(function (value) {\n      var $target = $(this.restoreTarget());\n      $target.css('float', value);\n    });\n\n    /**\n     * resize overlay element\n     * @param {String} value\n     */\n    this.resize = this.wrapCommand(function (value) {\n      var $target = $(this.restoreTarget());\n      $target.css({\n        width: value * 100 + '%',\n        height: ''\n      });\n    });\n\n    /**\n     * @param {Position} pos\n     * @param {jQuery} $target - target element\n     * @param {Boolean} [bKeepRatio] - keep ratio\n     */\n    this.resizeTo = function (pos, $target, bKeepRatio) {\n      var imageSize;\n      if (bKeepRatio) {\n        var newRatio = pos.y / pos.x;\n        var ratio = $target.data('ratio');\n        imageSize = {\n          width: ratio > newRatio ? pos.x : pos.y / ratio,\n          height: ratio > newRatio ? pos.x * ratio : pos.y\n        };\n      } else {\n        imageSize = {\n          width: pos.x,\n          height: pos.y\n        };\n      }\n\n      $target.css(imageSize);\n    };\n\n    /**\n     * remove media object\n     */\n    this.removeMedia = this.wrapCommand(function () {\n      var $target = $(this.restoreTarget()).detach();\n      context.triggerEvent('media.delete', $target, $editable);\n    });\n\n    /**\n     * returns whether editable area has focus or not.\n     */\n    this.hasFocus = function () {\n      return $editable.is(':focus');\n    };\n\n    /**\n     * set focus\n     */\n    this.focus = function () {\n      // [workaround] Screen will move when page is scolled in IE.\n      //  - do focus when not focused\n      if (!this.hasFocus()) {\n        $editable.focus();\n      }\n    };\n\n    /**\n     * returns whether contents is empty or not.\n     * @return {Boolean}\n     */\n    this.isEmpty = function () {\n      return dom.isEmpty($editable[0]) || dom.emptyPara === $editable.html();\n    };\n\n    /**\n     * Removes all contents and restores the editable instance to an _emptyPara_.\n     */\n    this.empty = function () {\n      context.invoke('code', dom.emptyPara);\n    };\n  };\n\n  var Clipboard = function (context) {\n    var self = this;\n\n    var $editable = context.layoutInfo.editable;\n\n    this.events = {\n      'summernote.keydown': function (we, e) {\n        if (self.needKeydownHook()) {\n          if ((e.ctrlKey || e.metaKey) && e.keyCode === key.code.V) {\n            context.invoke('editor.saveRange');\n            self.$paste.focus();\n\n            setTimeout(function () {\n              self.pasteByHook();\n            }, 0);\n          }\n        }\n      }\n    };\n\n    this.needKeydownHook = function () {\n      return (agent.isMSIE && agent.browserVersion > 10) || agent.isFF;\n    };\n\n    this.initialize = function () {\n      // [workaround] getting image from clipboard\n      //  - IE11 and Firefox: CTRL+v hook\n      //  - Webkit: event.clipboardData\n      if (this.needKeydownHook()) {\n        this.$paste = $('<div tabindex=\"-1\" />').attr('contenteditable', true).css({\n          position: 'absolute',\n          left: -100000,\n          opacity: 0\n        });\n        $editable.before(this.$paste);\n\n        this.$paste.on('paste', function (event) {\n          context.triggerEvent('paste', event);\n        });\n      } else {\n        $editable.on('paste', this.pasteByEvent);\n      }\n    };\n\n    this.destroy = function () {\n      if (this.needKeydownHook()) {\n        this.$paste.remove();\n        this.$paste = null;\n      }\n    };\n\n    this.pasteByHook = function () {\n      var node = this.$paste[0].firstChild;\n\n      if (dom.isImg(node)) {\n        var dataURI = node.src;\n        var decodedData = atob(dataURI.split(',')[1]);\n        var array = new Uint8Array(decodedData.length);\n        for (var i = 0; i < decodedData.length; i++) {\n          array[i] = decodedData.charCodeAt(i);\n        }\n\n        var blob = new Blob([array], { type: 'image/png' });\n        blob.name = 'clipboard.png';\n\n        context.invoke('editor.restoreRange');\n        context.invoke('editor.focus');\n        context.invoke('editor.insertImagesOrCallback', [blob]);\n      } else {\n        var pasteContent = $('<div />').html(this.$paste.html()).html();\n        context.invoke('editor.restoreRange');\n        context.invoke('editor.focus');\n\n        if (pasteContent) {\n          context.invoke('editor.pasteHTML', pasteContent);\n        }\n      }\n\n      this.$paste.empty();\n    };\n\n    /**\n     * paste by clipboard event\n     *\n     * @param {Event} event\n     */\n    this.pasteByEvent = function (event) {\n      var clipboardData = event.originalEvent.clipboardData;\n      if (clipboardData && clipboardData.items && clipboardData.items.length) {\n        var item = list.head(clipboardData.items);\n        if (item.kind === 'file' && item.type.indexOf('image/') !== -1) {\n          context.invoke('editor.insertImagesOrCallback', [item.getAsFile()]);\n        }\n        context.invoke('editor.afterCommand');\n      }\n    };\n  };\n\n  var Dropzone = function (context) {\n    var $document = $(document);\n    var $editor = context.layoutInfo.editor;\n    var $editable = context.layoutInfo.editable;\n    var options = context.options;\n    var lang = options.langInfo;\n    var documentEventHandlers = {};\n\n    var $dropzone = $([\n      '<div class=\"note-dropzone\">',\n      '  <div class=\"note-dropzone-message\"/>',\n      '</div>'\n    ].join('')).prependTo($editor);\n\n    var detachDocumentEvent = function () {\n      Object.keys(documentEventHandlers).forEach(function (key) {\n        $document.off(key.substr(2).toLowerCase(), documentEventHandlers[key]);\n      });\n      documentEventHandlers = {};\n    };\n\n    /**\n     * attach Drag and Drop Events\n     */\n    this.initialize = function () {\n      if (options.disableDragAndDrop) {\n        // prevent default drop event\n        documentEventHandlers.onDrop = function (e) {\n          e.preventDefault();\n        };\n        $document.on('drop', documentEventHandlers.onDrop);\n      } else {\n        this.attachDragAndDropEvent();\n      }\n    };\n\n    /**\n     * attach Drag and Drop Events\n     */\n    this.attachDragAndDropEvent = function () {\n      var collection = $(),\n          $dropzoneMessage = $dropzone.find('.note-dropzone-message');\n\n      documentEventHandlers.onDragenter = function (e) {\n        var isCodeview = context.invoke('codeview.isActivated');\n        var hasEditorSize = $editor.width() > 0 && $editor.height() > 0;\n        if (!isCodeview && !collection.length && hasEditorSize) {\n          $editor.addClass('dragover');\n          $dropzone.width($editor.width());\n          $dropzone.height($editor.height());\n          $dropzoneMessage.text(lang.image.dragImageHere);\n        }\n        collection = collection.add(e.target);\n      };\n\n      documentEventHandlers.onDragleave = function (e) {\n        collection = collection.not(e.target);\n        if (!collection.length) {\n          $editor.removeClass('dragover');\n        }\n      };\n\n      documentEventHandlers.onDrop = function () {\n        collection = $();\n        $editor.removeClass('dragover');\n      };\n\n      // show dropzone on dragenter when dragging a object to document\n      // -but only if the editor is visible, i.e. has a positive width and height\n      $document.on('dragenter', documentEventHandlers.onDragenter)\n        .on('dragleave', documentEventHandlers.onDragleave)\n        .on('drop', documentEventHandlers.onDrop);\n\n      // change dropzone's message on hover.\n      $dropzone.on('dragenter', function () {\n        $dropzone.addClass('hover');\n        $dropzoneMessage.text(lang.image.dropImage);\n      }).on('dragleave', function () {\n        $dropzone.removeClass('hover');\n        $dropzoneMessage.text(lang.image.dragImageHere);\n      });\n\n      // attach dropImage\n      $dropzone.on('drop', function (event) {\n        var dataTransfer = event.originalEvent.dataTransfer;\n\n        if (dataTransfer && dataTransfer.files && dataTransfer.files.length) {\n          event.preventDefault();\n          $editable.focus();\n          context.invoke('editor.insertImagesOrCallback', dataTransfer.files);\n        } else {\n          $.each(dataTransfer.types, function (idx, type) {\n            var content = dataTransfer.getData(type);\n\n            if (type.toLowerCase().indexOf('text') > -1) {\n              context.invoke('editor.pasteHTML', content);\n            } else {\n              $(content).each(function () {\n                context.invoke('editor.insertNode', this);\n              });\n            }\n          });\n        }\n      }).on('dragover', false); // prevent default dragover event\n    };\n\n    this.destroy = function () {\n      detachDocumentEvent();\n    };\n  };\n\n\n  var CodeMirror;\n  if (agent.hasCodeMirror) {\n    if (agent.isSupportAmd) {\n      require(['codemirror'], function (cm) {\n        CodeMirror = cm;\n      });\n    } else {\n      CodeMirror = window.CodeMirror;\n    }\n  }\n\n  /**\n   * @class Codeview\n   */\n  var Codeview = function (context) {\n    var $editor = context.layoutInfo.editor;\n    var $editable = context.layoutInfo.editable;\n    var $codable = context.layoutInfo.codable;\n    var options = context.options;\n\n    this.sync = function () {\n      var isCodeview = this.isActivated();\n      if (isCodeview && agent.hasCodeMirror) {\n        $codable.data('cmEditor').save();\n      }\n    };\n\n    /**\n     * @return {Boolean}\n     */\n    this.isActivated = function () {\n      return $editor.hasClass('codeview');\n    };\n\n    /**\n     * toggle codeview\n     */\n    this.toggle = function () {\n      if (this.isActivated()) {\n        this.deactivate();\n      } else {\n        this.activate();\n      }\n      context.triggerEvent('codeview.toggled');\n    };\n\n    /**\n     * activate code view\n     */\n    this.activate = function () {\n      $codable.val(dom.html($editable, options.prettifyHtml));\n      $codable.height($editable.height());\n\n      context.invoke('toolbar.updateCodeview', true);\n      $editor.addClass('codeview');\n      $codable.focus();\n\n      // activate CodeMirror as codable\n      if (agent.hasCodeMirror) {\n        var cmEditor = CodeMirror.fromTextArea($codable[0], options.codemirror);\n\n        // CodeMirror TernServer\n        if (options.codemirror.tern) {\n          var server = new CodeMirror.TernServer(options.codemirror.tern);\n          cmEditor.ternServer = server;\n          cmEditor.on('cursorActivity', function (cm) {\n            server.updateArgHints(cm);\n          });\n        }\n\n        // CodeMirror hasn't Padding.\n        cmEditor.setSize(null, $editable.outerHeight());\n        $codable.data('cmEditor', cmEditor);\n      }\n    };\n\n    /**\n     * deactivate code view\n     */\n    this.deactivate = function () {\n      // deactivate CodeMirror as codable\n      if (agent.hasCodeMirror) {\n        var cmEditor = $codable.data('cmEditor');\n        $codable.val(cmEditor.getValue());\n        cmEditor.toTextArea();\n      }\n\n      var value = dom.value($codable, options.prettifyHtml) || dom.emptyPara;\n      var isChange = $editable.html() !== value;\n\n      $editable.html(value);\n      $editable.height(options.height ? $codable.height() : 'auto');\n      $editor.removeClass('codeview');\n\n      if (isChange) {\n        context.triggerEvent('change', $editable.html(), $editable);\n      }\n\n      $editable.focus();\n\n      context.invoke('toolbar.updateCodeview', false);\n    };\n\n    this.destroy = function () {\n      if (this.isActivated()) {\n        this.deactivate();\n      }\n    };\n  };\n\n  var EDITABLE_PADDING = 24;\n\n  var Statusbar = function (context) {\n    var $document = $(document);\n    var $statusbar = context.layoutInfo.statusbar;\n    var $editable = context.layoutInfo.editable;\n    var options = context.options;\n\n    this.initialize = function () {\n      if (options.airMode || options.disableResizeEditor) {\n        return;\n      }\n\n      $statusbar.on('mousedown', function (event) {\n        event.preventDefault();\n        event.stopPropagation();\n\n        var editableTop = $editable.offset().top - $document.scrollTop();\n\n        $document.on('mousemove', function (event) {\n          var height = event.clientY - (editableTop + EDITABLE_PADDING);\n\n          height = (options.minheight > 0) ? Math.max(height, options.minheight) : height;\n          height = (options.maxHeight > 0) ? Math.min(height, options.maxHeight) : height;\n\n          $editable.height(height);\n        }).one('mouseup', function () {\n          $document.off('mousemove');\n        });\n      });\n    };\n\n    this.destroy = function () {\n      $statusbar.off();\n      $statusbar.remove();\n    };\n  };\n\n  var Fullscreen = function (context) {\n    var $editor = context.layoutInfo.editor;\n    var $toolbar = context.layoutInfo.toolbar;\n    var $editable = context.layoutInfo.editable;\n    var $codable = context.layoutInfo.codable;\n\n    var $window = $(window);\n    var $scrollbar = $('html, body');\n\n    /**\n     * toggle fullscreen\n     */\n    this.toggle = function () {\n      var resize = function (size) {\n        $editable.css('height', size.h);\n        $codable.css('height', size.h);\n        if ($codable.data('cmeditor')) {\n          $codable.data('cmeditor').setsize(null, size.h);\n        }\n      };\n\n      $editor.toggleClass('fullscreen');\n      if (this.isFullscreen()) {\n        $editable.data('orgHeight', $editable.css('height'));\n\n        $window.on('resize', function () {\n          resize({\n            h: $window.height() - $toolbar.outerHeight()\n          });\n        }).trigger('resize');\n\n        $scrollbar.css('overflow', 'hidden');\n      } else {\n        $window.off('resize');\n        resize({\n          h: $editable.data('orgHeight')\n        });\n        $scrollbar.css('overflow', 'visible');\n      }\n\n      context.invoke('toolbar.updateFullscreen', this.isFullscreen());\n    };\n\n    this.isFullscreen = function () {\n      return $editor.hasClass('fullscreen');\n    };\n  };\n\n  var Handle = function (context) {\n    var self = this;\n\n    var $document = $(document);\n    var $editingArea = context.layoutInfo.editingArea;\n    var options = context.options;\n\n    this.events = {\n      'summernote.mousedown': function (we, e) {\n        if (self.update(e.target)) {\n          e.preventDefault();\n        }\n      },\n      'summernote.keyup summernote.scroll summernote.change summernote.dialog.shown': function () {\n        self.update();\n      }\n    };\n\n    this.initialize = function () {\n      this.$handle = $([\n        '<div class=\"note-handle\">',\n        '<div class=\"note-control-selection\">',\n        '<div class=\"note-control-selection-bg\"></div>',\n        '<div class=\"note-control-holder note-control-nw\"></div>',\n        '<div class=\"note-control-holder note-control-ne\"></div>',\n        '<div class=\"note-control-holder note-control-sw\"></div>',\n        '<div class=\"',\n        (options.disableResizeImage ? 'note-control-holder' : 'note-control-sizing'),\n        ' note-control-se\"></div>',\n        (options.disableResizeImage ? '' : '<div class=\"note-control-selection-info\"></div>'),\n        '</div>',\n        '</div>'\n      ].join('')).prependTo($editingArea);\n\n      this.$handle.on('mousedown', function (event) {\n        if (dom.isControlSizing(event.target)) {\n          event.preventDefault();\n          event.stopPropagation();\n\n          var $target = self.$handle.find('.note-control-selection').data('target'),\n              posStart = $target.offset(),\n              scrollTop = $document.scrollTop();\n\n          $document.on('mousemove', function (event) {\n            context.invoke('editor.resizeTo', {\n              x: event.clientX - posStart.left,\n              y: event.clientY - (posStart.top - scrollTop)\n            }, $target, !event.shiftKey);\n\n            self.update($target[0]);\n          }).one('mouseup', function (e) {\n            e.preventDefault();\n            $document.off('mousemove');\n            context.invoke('editor.afterCommand');\n          });\n\n          if (!$target.data('ratio')) { // original ratio.\n            $target.data('ratio', $target.height() / $target.width());\n          }\n        }\n      });\n    };\n\n    this.destroy = function () {\n      this.$handle.remove();\n    };\n\n    this.update = function (target) {\n      var isImage = dom.isImg(target);\n      var $selection = this.$handle.find('.note-control-selection');\n\n      context.invoke('imagePopover.update', target);\n\n      if (isImage) {\n        var $image = $(target);\n        var pos = $image.position();\n\n        // include margin\n        var imageSize = {\n          w: $image.outerWidth(true),\n          h: $image.outerHeight(true)\n        };\n\n        $selection.css({\n          display: 'block',\n          left: pos.left,\n          top: pos.top,\n          width: imageSize.w,\n          height: imageSize.h\n        }).data('target', $image); // save current image element.\n\n        var sizingText = imageSize.w + 'x' + imageSize.h;\n        $selection.find('.note-control-selection-info').text(sizingText);\n        context.invoke('editor.saveTarget', target);\n      } else {\n        this.hide();\n      }\n\n      return isImage;\n    };\n\n    /**\n     * hide\n     *\n     * @param {jQuery} $handle\n     */\n    this.hide = function () {\n      context.invoke('editor.clearTarget');\n      this.$handle.children().hide();\n    };\n  };\n\n  var AutoLink = function (context) {\n    var self = this;\n    var defaultScheme = 'http://';\n    var linkPattern = /^([A-Za-z][A-Za-z0-9+-.]*\\:[\\/\\/]?|mailto:[A-Z0-9._%+-]+@)?(www\\.)?(.+)$/i;\n\n    this.events = {\n      'summernote.keyup': function (we, e) {\n        if (!e.isDefaultPrevented()) {\n          self.handleKeyup(e);\n        }\n      },\n      'summernote.keydown': function (we, e) {\n        self.handleKeydown(e);\n      }\n    };\n\n    this.initialize = function () {\n      this.lastWordRange = null;\n    };\n\n    this.destroy = function () {\n      this.lastWordRange = null;\n    };\n\n    this.replace = function () {\n      if (!this.lastWordRange) {\n        return;\n      }\n\n      var keyword = this.lastWordRange.toString();\n      var match = keyword.match(linkPattern);\n\n      if (match && (match[1] || match[2])) {\n        var link = match[1] ? keyword : defaultScheme + keyword;\n        var node = $('<a />').html(keyword).attr('href', link)[0];\n\n        this.lastWordRange.insertNode(node);\n        this.lastWordRange = null;\n        context.invoke('editor.focus');\n      }\n\n    };\n\n    this.handleKeydown = function (e) {\n      if (list.contains([key.code.ENTER, key.code.SPACE], e.keyCode)) {\n        var wordRange = context.invoke('editor.createRange').getWordRange();\n        this.lastWordRange = wordRange;\n      }\n    };\n\n    this.handleKeyup = function (e) {\n      if (list.contains([key.code.ENTER, key.code.SPACE], e.keyCode)) {\n        this.replace();\n      }\n    };\n  };\n\n  /**\n   * textarea auto sync.\n   */\n  var AutoSync = function (context) {\n    var $note = context.layoutInfo.note;\n\n    this.events = {\n      'summernote.change': function () {\n        $note.val(context.invoke('code'));\n      }\n    };\n\n    this.shouldInitialize = function () {\n      return dom.isTextarea($note[0]);\n    };\n  };\n\n  var Placeholder = function (context) {\n    var self = this;\n    var $editingArea = context.layoutInfo.editingArea;\n    var options = context.options;\n\n    this.events = {\n      'summernote.init summernote.change': function () {\n        self.update();\n      },\n      'summernote.codeview.toggled': function () {\n        self.update();\n      }\n    };\n\n    this.shouldInitialize = function () {\n      return !!options.placeholder;\n    };\n\n    this.initialize = function () {\n      this.$placeholder = $('<div class=\"note-placeholder\">');\n      this.$placeholder.on('click', function () {\n        context.invoke('focus');\n      }).text(options.placeholder).prependTo($editingArea);\n    };\n\n    this.destroy = function () {\n      this.$placeholder.remove();\n    };\n\n    this.update = function () {\n      var isShow = !context.invoke('codeview.isActivated') && context.invoke('editor.isEmpty');\n      this.$placeholder.toggle(isShow);\n    };\n  };\n\n  var Buttons = function (context) {\n    var self = this;\n    var ui = $.summernote.ui;\n\n    var $toolbar = context.layoutInfo.toolbar;\n    var options = context.options;\n    var lang = options.langInfo;\n\n    var invertedKeyMap = func.invertObject(options.keyMap[agent.isMac ? 'mac' : 'pc']);\n\n    var representShortcut = this.representShortcut = function (editorMethod) {\n      var shortcut = invertedKeyMap[editorMethod];\n      if (!options.shortcuts || !shortcut) {\n        return '';\n      }\n      \n      if (agent.isMac) {\n        shortcut = shortcut.replace('CMD', '⌘').replace('SHIFT', '⇧');\n      }\n\n      shortcut = shortcut.replace('BACKSLASH', '\\\\')\n                         .replace('SLASH', '/')\n                         .replace('LEFTBRACKET', '[')\n                         .replace('RIGHTBRACKET', ']');\n\n      return ' (' + shortcut + ')';\n    };\n\n    this.initialize = function () {\n      this.addToolbarButtons();\n      this.addImagePopoverButtons();\n      this.addLinkPopoverButtons();\n      this.fontInstalledMap = {};\n    };\n\n    this.destroy = function () {\n      delete this.fontInstalledMap;\n    };\n\n    this.isFontInstalled = function (name) {\n      if (!self.fontInstalledMap.hasOwnProperty(name)) {\n        self.fontInstalledMap[name] = agent.isFontInstalled(name) ||\n          list.contains(options.fontNamesIgnoreCheck, name);\n      }\n\n      return self.fontInstalledMap[name];\n    };\n\n    this.addToolbarButtons = function () {\n      context.memo('button.style', function () {\n        return ui.buttonGroup([\n          ui.button({\n            className: 'dropdown-toggle',\n            contents: ui.icon(options.icons.magic) + ' ' + ui.icon(options.icons.caret, 'span'),\n            tooltip: lang.style.style,\n            data: {\n              toggle: 'dropdown'\n            }\n          }),\n          ui.dropdown({\n            className: 'dropdown-style',\n            items: context.options.styleTags,\n            template: function (item) {\n\n              if (typeof item === 'string') {\n                item = { tag: item, title: (lang.style.hasOwnProperty(item) ? lang.style[item] : item) };\n              }\n\n              var tag = item.tag;\n              var title = item.title;\n              var style = item.style ? ' style=\"' + item.style + '\" ' : '';\n              var className = item.className ? ' class=\"' + item.className + '\"' : '';\n\n              return '<' + tag + style + className + '>' + title + '</' + tag +  '>';\n            },\n            click: context.createInvokeHandler('editor.formatBlock')\n          })\n        ]).render();\n      });\n\n      context.memo('button.bold', function () {\n        return ui.button({\n          className: 'note-btn-bold',\n          contents: ui.icon(options.icons.bold),\n          tooltip: lang.font.bold + representShortcut('bold'),\n          click: context.createInvokeHandler('editor.bold')\n        }).render();\n      });\n\n      context.memo('button.italic', function () {\n        return ui.button({\n          className: 'note-btn-italic',\n          contents: ui.icon(options.icons.italic),\n          tooltip: lang.font.italic + representShortcut('italic'),\n          click: context.createInvokeHandler('editor.italic')\n        }).render();\n      });\n\n      context.memo('button.underline', function () {\n        return ui.button({\n          className: 'note-btn-underline',\n          contents: ui.icon(options.icons.underline),\n          tooltip: lang.font.underline + representShortcut('underline'),\n          click: context.createInvokeHandler('editor.underline')\n        }).render();\n      });\n\n      context.memo('button.clear', function () {\n        return ui.button({\n          contents: ui.icon(options.icons.eraser),\n          tooltip: lang.font.clear + representShortcut('removeFormat'),\n          click: context.createInvokeHandler('editor.removeFormat')\n        }).render();\n      });\n\n      context.memo('button.strikethrough', function () {\n        return ui.button({\n          className: 'note-btn-strikethrough',\n          contents: ui.icon(options.icons.strikethrough),\n          tooltip: lang.font.strikethrough + representShortcut('strikethrough'),\n          click: context.createInvokeHandler('editor.strikethrough')\n        }).render();\n      });\n\n      context.memo('button.superscript', function () {\n        return ui.button({\n          className: 'note-btn-superscript',\n          contents: ui.icon(options.icons.superscript),\n          tooltip: lang.font.superscript,\n          click: context.createInvokeHandler('editor.superscript')\n        }).render();\n      });\n\n      context.memo('button.subscript', function () {\n        return ui.button({\n          className: 'note-btn-subscript',\n          contents: ui.icon(options.icons.subscript),\n          tooltip: lang.font.subscript,\n          click: context.createInvokeHandler('editor.subscript')\n        }).render();\n      });\n\n      context.memo('button.fontname', function () {\n        return ui.buttonGroup([\n          ui.button({\n            className: 'dropdown-toggle',\n            contents: '<span class=\"note-current-fontname\"/> ' + ui.icon(options.icons.caret, 'span'),\n            tooltip: lang.font.name,\n            data: {\n              toggle: 'dropdown'\n            }\n          }),\n          ui.dropdownCheck({\n            className: 'dropdown-fontname',\n            checkClassName: options.icons.menuCheck,\n            items: options.fontNames.filter(self.isFontInstalled),\n            template: function (item) {\n              return '<span style=\"font-family:' + item + '\">' + item + '</span>';\n            },\n            click: context.createInvokeHandler('editor.fontName')\n          })\n        ]).render();\n      });\n\n      context.memo('button.fontsize', function () {\n        return ui.buttonGroup([\n          ui.button({\n            className: 'dropdown-toggle',\n            contents: '<span class=\"note-current-fontsize\"/>' + ui.icon(options.icons.caret, 'span'),\n            tooltip: lang.font.size,\n            data: {\n              toggle: 'dropdown'\n            }\n          }),\n          ui.dropdownCheck({\n            className: 'dropdown-fontsize',\n            checkClassName: options.icons.menuCheck,\n            items: options.fontSizes,\n            click: context.createInvokeHandler('editor.fontSize')\n          })\n        ]).render();\n      });\n\n      context.memo('button.color', function () {\n        return ui.buttonGroup({\n          className: 'note-color',\n          children: [\n            ui.button({\n              className: 'note-current-color-button',\n              contents: ui.icon(options.icons.font + ' note-recent-color'),\n              tooltip: lang.color.recent,\n              click: function (e) {\n                var $button = $(e.currentTarget);\n                context.invoke('editor.color', {\n                  backColor: $button.attr('data-backColor'),\n                  foreColor: $button.attr('data-foreColor')\n                });\n              },\n              callback: function ($button) {\n                var $recentColor = $button.find('.note-recent-color');\n                $recentColor.css('background-color', '#FFFF00');\n                $button.attr('data-backColor', '#FFFF00');\n              }\n            }),\n            ui.button({\n              className: 'dropdown-toggle',\n              contents: ui.icon(options.icons.caret, 'span'),\n              tooltip: lang.color.more,\n              data: {\n                toggle: 'dropdown'\n              }\n            }),\n            ui.dropdown({\n              items: [\n                '<li>',\n                '<div class=\"btn-group\">',\n                '  <div class=\"note-palette-title\">' + lang.color.background + '</div>',\n                '  <div>',\n                '    <button type=\"button\" class=\"note-color-reset btn btn-default\" data-event=\"backColor\" data-value=\"inherit\">',\n                lang.color.transparent,\n                '    </button>',\n                '  </div>',\n                '  <div class=\"note-holder\" data-event=\"backColor\"/>',\n                '</div>',\n                '<div class=\"btn-group\">',\n                '  <div class=\"note-palette-title\">' + lang.color.foreground + '</div>',\n                '  <div>',\n                '    <button type=\"button\" class=\"note-color-reset btn btn-default\" data-event=\"removeFormat\" data-value=\"foreColor\">',\n                lang.color.resetToDefault,\n                '    </button>',\n                '  </div>',\n                '  <div class=\"note-holder\" data-event=\"foreColor\"/>',\n                '</div>',\n                '</li>'\n              ].join(''),\n              callback: function ($dropdown) {\n                $dropdown.find('.note-holder').each(function () {\n                  var $holder = $(this);\n                  $holder.append(ui.palette({\n                    colors: options.colors,\n                    eventName: $holder.data('event')\n                  }).render());\n                });\n              },\n              click: function (event) {\n                var $button = $(event.target);\n                var eventName = $button.data('event');\n                var value = $button.data('value');\n\n                if (eventName && value) {\n                  var key = eventName === 'backColor' ? 'background-color' : 'color';\n                  var $color = $button.closest('.note-color').find('.note-recent-color');\n                  var $currentButton = $button.closest('.note-color').find('.note-current-color-button');\n\n                  $color.css(key, value);\n                  $currentButton.attr('data-' + eventName, value);\n                  context.invoke('editor.' + eventName, value);\n                }\n              }\n            })\n          ]\n        }).render();\n      });\n\n      context.memo('button.ul',  function () {\n        return ui.button({\n          contents: ui.icon(options.icons.unorderedlist),\n          tooltip: lang.lists.unordered + representShortcut('insertUnorderedList'),\n          click: context.createInvokeHandler('editor.insertUnorderedList')\n        }).render();\n      });\n\n      context.memo('button.ol', function () {\n        return ui.button({\n          contents: ui.icon(options.icons.orderedlist),\n          tooltip: lang.lists.ordered + representShortcut('insertOrderedList'),\n          click:  context.createInvokeHandler('editor.insertOrderedList')\n        }).render();\n      });\n\n      var justifyLeft = ui.button({\n        contents: ui.icon(options.icons.alignLeft),\n        tooltip: lang.paragraph.left + representShortcut('justifyLeft'),\n        click: context.createInvokeHandler('editor.justifyLeft')\n      });\n\n      var justifyCenter = ui.button({\n        contents: ui.icon(options.icons.alignCenter),\n        tooltip: lang.paragraph.center + representShortcut('justifyCenter'),\n        click: context.createInvokeHandler('editor.justifyCenter')\n      });\n\n      var justifyRight = ui.button({\n        contents: ui.icon(options.icons.alignRight),\n        tooltip: lang.paragraph.right + representShortcut('justifyRight'),\n        click: context.createInvokeHandler('editor.justifyRight')\n      });\n\n      var justifyFull = ui.button({\n        contents: ui.icon(options.icons.alignJustify),\n        tooltip: lang.paragraph.justify + representShortcut('justifyFull'),\n        click: context.createInvokeHandler('editor.justifyFull')\n      });\n\n      var outdent = ui.button({\n        contents: ui.icon(options.icons.outdent),\n        tooltip: lang.paragraph.outdent + representShortcut('outdent'),\n        click: context.createInvokeHandler('editor.outdent')\n      });\n\n      var indent = ui.button({\n        contents: ui.icon(options.icons.indent),\n        tooltip: lang.paragraph.indent + representShortcut('indent'),\n        click: context.createInvokeHandler('editor.indent')\n      });\n\n      context.memo('button.justifyLeft', func.invoke(justifyLeft, 'render'));\n      context.memo('button.justifyCenter', func.invoke(justifyCenter, 'render'));\n      context.memo('button.justifyRight', func.invoke(justifyRight, 'render'));\n      context.memo('button.justifyFull', func.invoke(justifyFull, 'render'));\n      context.memo('button.outdent', func.invoke(outdent, 'render'));\n      context.memo('button.indent', func.invoke(indent, 'render'));\n\n      context.memo('button.paragraph', function () {\n        return ui.buttonGroup([\n          ui.button({\n            className: 'dropdown-toggle',\n            contents: ui.icon(options.icons.alignLeft) + ' ' + ui.icon(options.icons.caret, 'span'),\n            tooltip: lang.paragraph.paragraph,\n            data: {\n              toggle: 'dropdown'\n            }\n          }),\n          ui.dropdown([\n            ui.buttonGroup({\n              className: 'note-align',\n              children: [justifyLeft, justifyCenter, justifyRight, justifyFull]\n            }),\n            ui.buttonGroup({\n              className: 'note-list',\n              children: [outdent, indent]\n            })\n          ])\n        ]).render();\n      });\n\n      context.memo('button.height', function () {\n        return ui.buttonGroup([\n          ui.button({\n            className: 'dropdown-toggle',\n            contents: ui.icon(options.icons.textHeight) + ' ' + ui.icon(options.icons.caret, 'span'),\n            tooltip: lang.font.height,\n            data: {\n              toggle: 'dropdown'\n            }\n          }),\n          ui.dropdownCheck({\n            items: options.lineHeights,\n            checkClassName: options.icons.menuCheck,\n            className: 'dropdown-line-height',\n            click: context.createInvokeHandler('editor.lineHeight')\n          })\n        ]).render();\n      });\n\n      context.memo('button.table', function () {\n        return ui.buttonGroup([\n          ui.button({\n            className: 'dropdown-toggle',\n            contents: ui.icon(options.icons.table) + ' ' + ui.icon(options.icons.caret, 'span'),\n            tooltip: lang.table.table,\n            data: {\n              toggle: 'dropdown'\n            }\n          }),\n          ui.dropdown({\n            className: 'note-table',\n            items: [\n              '<div class=\"note-dimension-picker\">',\n              '  <div class=\"note-dimension-picker-mousecatcher\" data-event=\"insertTable\" data-value=\"1x1\"/>',\n              '  <div class=\"note-dimension-picker-highlighted\"/>',\n              '  <div class=\"note-dimension-picker-unhighlighted\"/>',\n              '</div>',\n              '<div class=\"note-dimension-display\">1 x 1</div>'\n            ].join('')\n          })\n        ], {\n          callback: function ($node) {\n            var $catcher = $node.find('.note-dimension-picker-mousecatcher');\n            $catcher.css({\n              width: options.insertTableMaxSize.col + 'em',\n              height: options.insertTableMaxSize.row + 'em'\n            }).mousedown(context.createInvokeHandler('editor.insertTable'))\n              .on('mousemove', self.tableMoveHandler);\n          }\n        }).render();\n      });\n\n      context.memo('button.link', function () {\n        return ui.button({\n          contents: ui.icon(options.icons.link),\n          tooltip: lang.link.link + representShortcut('linkDialog.show'),\n          click: context.createInvokeHandler('linkDialog.show')\n        }).render();\n      });\n\n      context.memo('button.picture', function () {\n        return ui.button({\n          contents: ui.icon(options.icons.picture),\n          tooltip: lang.image.image,\n          click: context.createInvokeHandler('imageDialog.show')\n        }).render();\n      });\n\n      context.memo('button.video', function () {\n        return ui.button({\n          contents: ui.icon(options.icons.video),\n          tooltip: lang.video.video,\n          click: context.createInvokeHandler('videoDialog.show')\n        }).render();\n      });\n\n      context.memo('button.hr', function () {\n        return ui.button({\n          contents: ui.icon(options.icons.minus),\n          tooltip: lang.hr.insert + representShortcut('insertHorizontalRule'),\n          click: context.createInvokeHandler('editor.insertHorizontalRule')\n        }).render();\n      });\n\n      context.memo('button.fullscreen', function () {\n        return ui.button({\n          className: 'btn-fullscreen',\n          contents: ui.icon(options.icons.arrowsAlt),\n          tooltip: lang.options.fullscreen,\n          click: context.createInvokeHandler('fullscreen.toggle')\n        }).render();\n      });\n\n      context.memo('button.codeview', function () {\n        return ui.button({\n          className: 'btn-codeview',\n          contents: ui.icon(options.icons.code),\n          tooltip: lang.options.codeview,\n          click: context.createInvokeHandler('codeview.toggle')\n        }).render();\n      });\n\n      context.memo('button.redo', function () {\n        return ui.button({\n          contents: ui.icon(options.icons.redo),\n          tooltip: lang.history.redo + representShortcut('redo'),\n          click: context.createInvokeHandler('editor.redo')\n        }).render();\n      });\n\n      context.memo('button.undo', function () {\n        return ui.button({\n          contents: ui.icon(options.icons.undo),\n          tooltip: lang.history.undo + representShortcut('undo'),\n          click: context.createInvokeHandler('editor.undo')\n        }).render();\n      });\n\n      context.memo('button.help', function () {\n        return ui.button({\n          contents: ui.icon(options.icons.question),\n          tooltip: lang.options.help,\n          click: context.createInvokeHandler('helpDialog.show')\n        }).render();\n      });\n    };\n\n    /**\n     * image : [\n     *   ['imagesize', ['imageSize100', 'imageSize50', 'imageSize25']],\n     *   ['float', ['floatLeft', 'floatRight', 'floatNone' ]],\n     *   ['remove', ['removeMedia']]\n     * ],\n     */\n    this.addImagePopoverButtons = function () {\n      // Image Size Buttons\n      context.memo('button.imageSize100', function () {\n        return ui.button({\n          contents: '<span class=\"note-fontsize-10\">100%</span>',\n          tooltip: lang.image.resizeFull,\n          click: context.createInvokeHandler('editor.resize', '1')\n        }).render();\n      });\n      context.memo('button.imageSize50', function () {\n        return  ui.button({\n          contents: '<span class=\"note-fontsize-10\">50%</span>',\n          tooltip: lang.image.resizeHalf,\n          click: context.createInvokeHandler('editor.resize', '0.5')\n        }).render();\n      });\n      context.memo('button.imageSize25', function () {\n        return ui.button({\n          contents: '<span class=\"note-fontsize-10\">25%</span>',\n          tooltip: lang.image.resizeQuarter,\n          click: context.createInvokeHandler('editor.resize', '0.25')\n        }).render();\n      });\n\n      // Float Buttons\n      context.memo('button.floatLeft', function () {\n        return ui.button({\n          contents: ui.icon(options.icons.alignLeft),\n          tooltip: lang.image.floatLeft,\n          click: context.createInvokeHandler('editor.floatMe', 'left')\n        }).render();\n      });\n\n      context.memo('button.floatRight', function () {\n        return ui.button({\n          contents: ui.icon(options.icons.alignRight),\n          tooltip: lang.image.floatRight,\n          click: context.createInvokeHandler('editor.floatMe', 'right')\n        }).render();\n      });\n\n      context.memo('button.floatNone', function () {\n        return ui.button({\n          contents: ui.icon(options.icons.alignJustify),\n          tooltip: lang.image.floatNone,\n          click: context.createInvokeHandler('editor.floatMe', 'none')\n        }).render();\n      });\n\n      // Remove Buttons\n      context.memo('button.removeMedia', function () {\n        return ui.button({\n          contents: ui.icon(options.icons.trash),\n          tooltip: lang.image.remove,\n          click: context.createInvokeHandler('editor.removeMedia')\n        }).render();\n      });\n    };\n\n    this.addLinkPopoverButtons = function () {\n      context.memo('button.linkDialogShow', function () {\n        return ui.button({\n          contents: ui.icon(options.icons.link),\n          tooltip: lang.link.edit,\n          click: context.createInvokeHandler('linkDialog.show')\n        }).render();\n      });\n\n      context.memo('button.unlink', function () {\n        return ui.button({\n          contents: ui.icon(options.icons.unlink),\n          tooltip: lang.link.unlink,\n          click: context.createInvokeHandler('editor.unlink')\n        }).render();\n      });\n    };\n\n    this.build = function ($container, groups) {\n      for (var groupIdx = 0, groupLen = groups.length; groupIdx < groupLen; groupIdx++) {\n        var group = groups[groupIdx];\n        var groupName = group[0];\n        var buttons = group[1];\n\n        var $group = ui.buttonGroup({\n          className: 'note-' + groupName\n        }).render();\n\n        for (var idx = 0, len = buttons.length; idx < len; idx++) {\n          var button = context.memo('button.' + buttons[idx]);\n          if (button) {\n            $group.append(typeof button === 'function' ? button(context) : button);\n          }\n        }\n        $group.appendTo($container);\n      }\n    };\n\n    this.updateCurrentStyle = function () {\n      var styleInfo = context.invoke('editor.currentStyle');\n      this.updateBtnStates({\n        '.note-btn-bold': function () {\n          return styleInfo['font-bold'] === 'bold';\n        },\n        '.note-btn-italic': function () {\n          return styleInfo['font-italic'] === 'italic';\n        },\n        '.note-btn-underline': function () {\n          return styleInfo['font-underline'] === 'underline';\n        },\n        '.note-btn-subscript': function () {\n          return styleInfo['font-subscript'] === 'subscript';\n        },\n        '.note-btn-superscript': function () {\n          return styleInfo['font-superscript'] === 'superscript';\n        },\n        '.note-btn-strikethrough': function () {\n          return styleInfo['font-strikethrough'] === 'strikethrough';\n        }\n      });\n\n      if (styleInfo['font-family']) {\n        var fontNames = styleInfo['font-family'].split(',').map(function (name) {\n          return name.replace(/[\\'\\\"]/g, '')\n            .replace(/\\s+$/, '')\n            .replace(/^\\s+/, '');\n        });\n        var fontName = list.find(fontNames, self.isFontInstalled);\n\n        $toolbar.find('.dropdown-fontname li a').each(function () {\n          // always compare string to avoid creating another func.\n          var isChecked = ($(this).data('value') + '') === (fontName + '');\n          this.className = isChecked ? 'checked' : '';\n        });\n        $toolbar.find('.note-current-fontname').text(fontName);\n      }\n\n      if (styleInfo['font-size']) {\n        var fontSize = styleInfo['font-size'];\n        $toolbar.find('.dropdown-fontsize li a').each(function () {\n          // always compare with string to avoid creating another func.\n          var isChecked = ($(this).data('value') + '') === (fontSize + '');\n          this.className = isChecked ? 'checked' : '';\n        });\n        $toolbar.find('.note-current-fontsize').text(fontSize);\n      }\n\n      if (styleInfo['line-height']) {\n        var lineHeight = styleInfo['line-height'];\n        $toolbar.find('.dropdown-line-height li a').each(function () {\n          // always compare with string to avoid creating another func.\n          var isChecked = ($(this).data('value') + '') === (lineHeight + '');\n          this.className = isChecked ? 'checked' : '';\n        });\n      }\n    };\n\n    this.updateBtnStates = function (infos) {\n      $.each(infos, function (selector, pred) {\n        ui.toggleBtnActive($toolbar.find(selector), pred());\n      });\n    };\n\n    this.tableMoveHandler = function (event) {\n      var PX_PER_EM = 18;\n      var $picker = $(event.target.parentNode); // target is mousecatcher\n      var $dimensionDisplay = $picker.next();\n      var $catcher = $picker.find('.note-dimension-picker-mousecatcher');\n      var $highlighted = $picker.find('.note-dimension-picker-highlighted');\n      var $unhighlighted = $picker.find('.note-dimension-picker-unhighlighted');\n\n      var posOffset;\n      // HTML5 with jQuery - e.offsetX is undefined in Firefox\n      if (event.offsetX === undefined) {\n        var posCatcher = $(event.target).offset();\n        posOffset = {\n          x: event.pageX - posCatcher.left,\n          y: event.pageY - posCatcher.top\n        };\n      } else {\n        posOffset = {\n          x: event.offsetX,\n          y: event.offsetY\n        };\n      }\n\n      var dim = {\n        c: Math.ceil(posOffset.x / PX_PER_EM) || 1,\n        r: Math.ceil(posOffset.y / PX_PER_EM) || 1\n      };\n\n      $highlighted.css({ width: dim.c + 'em', height: dim.r + 'em' });\n      $catcher.data('value', dim.c + 'x' + dim.r);\n\n      if (3 < dim.c && dim.c < options.insertTableMaxSize.col) {\n        $unhighlighted.css({ width: dim.c + 1 + 'em'});\n      }\n\n      if (3 < dim.r && dim.r < options.insertTableMaxSize.row) {\n        $unhighlighted.css({ height: dim.r + 1 + 'em'});\n      }\n\n      $dimensionDisplay.html(dim.c + ' x ' + dim.r);\n    };\n  };\n\n  var Toolbar = function (context) {\n    var ui = $.summernote.ui;\n\n    var $note = context.layoutInfo.note;\n    var $toolbar = context.layoutInfo.toolbar;\n    var options = context.options;\n\n    this.shouldInitialize = function () {\n      return !options.airMode;\n    };\n\n    this.initialize = function () {\n      options.toolbar = options.toolbar || [];\n\n      if (!options.toolbar.length) {\n        $toolbar.hide();\n      } else {\n        context.invoke('buttons.build', $toolbar, options.toolbar);\n      }\n\n      if (options.toolbarContainer) {\n        $toolbar.appendTo(options.toolbarContainer);\n      }\n\n      $note.on('summernote.keyup summernote.mouseup summernote.change', function () {\n        context.invoke('buttons.updateCurrentStyle');\n      });\n\n      context.invoke('buttons.updateCurrentStyle');\n    };\n\n    this.destroy = function () {\n      $toolbar.children().remove();\n    };\n\n    this.updateFullscreen = function (isFullscreen) {\n      ui.toggleBtnActive($toolbar.find('.btn-fullscreen'), isFullscreen);\n    };\n\n    this.updateCodeview = function (isCodeview) {\n      ui.toggleBtnActive($toolbar.find('.btn-codeview'), isCodeview);\n      if (isCodeview) {\n        this.deactivate();\n      } else {\n        this.activate();\n      }\n    };\n\n    this.activate = function (isIncludeCodeview) {\n      var $btn = $toolbar.find('button');\n      if (!isIncludeCodeview) {\n        $btn = $btn.not('.btn-codeview');\n      }\n      ui.toggleBtn($btn, true);\n    };\n\n    this.deactivate = function (isIncludeCodeview) {\n      var $btn = $toolbar.find('button');\n      if (!isIncludeCodeview) {\n        $btn = $btn.not('.btn-codeview');\n      }\n      ui.toggleBtn($btn, false);\n    };\n  };\n\n  var LinkDialog = function (context) {\n    var self = this;\n    var ui = $.summernote.ui;\n\n    var $editor = context.layoutInfo.editor;\n    var options = context.options;\n    var lang = options.langInfo;\n\n    this.initialize = function () {\n      var $container = options.dialogsInBody ? $(document.body) : $editor;\n\n      var body = '<div class=\"form-group\">' +\n                   '<label>' + lang.link.textToDisplay + '</label>' +\n                   '<input class=\"note-link-text form-control\" type=\"text\" />' +\n                 '</div>' +\n                 '<div class=\"form-group\">' +\n                   '<label>' + lang.link.url + '</label>' +\n                   '<input class=\"note-link-url form-control\" type=\"text\" value=\"http://\" />' +\n                 '</div>' +\n                 (!options.disableLinkTarget ?\n                   '<div class=\"checkbox\">' +\n                     '<label>' + '<input type=\"checkbox\" checked> ' + lang.link.openInNewWindow + '</label>' +\n                   '</div>' : ''\n                 );\n      var footer = '<button href=\"#\" class=\"btn btn-primary note-link-btn disabled\" disabled>' + lang.link.insert + '</button>';\n\n      this.$dialog = ui.dialog({\n        className: 'link-dialog',\n        title: lang.link.insert,\n        fade: options.dialogsFade,\n        body: body,\n        footer: footer\n      }).render().appendTo($container);\n    };\n\n    this.destroy = function () {\n      ui.hideDialog(this.$dialog);\n      this.$dialog.remove();\n    };\n\n    this.bindEnterKey = function ($input, $btn) {\n      $input.on('keypress', function (event) {\n        if (event.keyCode === key.code.ENTER) {\n          $btn.trigger('click');\n        }\n      });\n    };\n\n    /**\n     * toggle update button\n     */\n    this.toggleLinkBtn = function ($linkBtn, $linkText, $linkUrl) {\n      ui.toggleBtn($linkBtn, $linkText.val() && $linkUrl.val());\n    };\n\n    /**\n     * Show link dialog and set event handlers on dialog controls.\n     *\n     * @param {Object} linkInfo\n     * @return {Promise}\n     */\n    this.showLinkDialog = function (linkInfo) {\n      return $.Deferred(function (deferred) {\n        var $linkText = self.$dialog.find('.note-link-text'),\n        $linkUrl = self.$dialog.find('.note-link-url'),\n        $linkBtn = self.$dialog.find('.note-link-btn'),\n        $openInNewWindow = self.$dialog.find('input[type=checkbox]');\n\n        ui.onDialogShown(self.$dialog, function () {\n          context.triggerEvent('dialog.shown');\n\n          // if no url was given, copy text to url\n          if (!linkInfo.url) {\n            linkInfo.url = linkInfo.text;\n          }\n\n          $linkText.val(linkInfo.text);\n\n          var handleLinkTextUpdate = function () {\n            self.toggleLinkBtn($linkBtn, $linkText, $linkUrl);\n            // if linktext was modified by keyup,\n            // stop cloning text from linkUrl\n            linkInfo.text = $linkText.val();\n          };\n\n          $linkText.on('input', handleLinkTextUpdate).on('paste', function () {\n            setTimeout(handleLinkTextUpdate, 0);\n          });\n\n          var handleLinkUrlUpdate = function () {\n            self.toggleLinkBtn($linkBtn, $linkText, $linkUrl);\n            // display same link on `Text to display` input\n            // when create a new link\n            if (!linkInfo.text) {\n              $linkText.val($linkUrl.val());\n            }\n          };\n\n          $linkUrl.on('input', handleLinkUrlUpdate).on('paste', function () {\n            setTimeout(handleLinkUrlUpdate, 0);\n          }).val(linkInfo.url).trigger('focus');\n\n          self.toggleLinkBtn($linkBtn, $linkText, $linkUrl);\n          self.bindEnterKey($linkUrl, $linkBtn);\n          self.bindEnterKey($linkText, $linkBtn);\n\n          $openInNewWindow.prop('checked', linkInfo.isNewWindow);\n\n          $linkBtn.one('click', function (event) {\n            event.preventDefault();\n\n            deferred.resolve({\n              range: linkInfo.range,\n              url: $linkUrl.val(),\n              text: $linkText.val(),\n              isNewWindow: $openInNewWindow.is(':checked')\n            });\n            self.$dialog.modal('hide');\n          });\n        });\n\n        ui.onDialogHidden(self.$dialog, function () {\n          // detach events\n          $linkText.off('input paste keypress');\n          $linkUrl.off('input paste keypress');\n          $linkBtn.off('click');\n\n          if (deferred.state() === 'pending') {\n            deferred.reject();\n          }\n        });\n\n        ui.showDialog(self.$dialog);\n      }).promise();\n    };\n\n    /**\n     * @param {Object} layoutInfo\n     */\n    this.show = function () {\n      var linkInfo = context.invoke('editor.getLinkInfo');\n\n      context.invoke('editor.saveRange');\n      this.showLinkDialog(linkInfo).then(function (linkInfo) {\n        context.invoke('editor.restoreRange');\n        context.invoke('editor.createLink', linkInfo);\n      }).fail(function () {\n        context.invoke('editor.restoreRange');\n      });\n    };\n    context.memo('help.linkDialog.show', options.langInfo.help['linkDialog.show']);\n  };\n\n  var LinkPopover = function (context) {\n    var self = this;\n    var ui = $.summernote.ui;\n\n    var options = context.options;\n\n    this.events = {\n      'summernote.keyup summernote.mouseup summernote.change summernote.scroll': function () {\n        self.update();\n      },\n      'summernote.dialog.shown': function () {\n        self.hide();\n      }\n    };\n\n    this.shouldInitialize = function () {\n      return !list.isEmpty(options.popover.link);\n    };\n\n    this.initialize = function () {\n      this.$popover = ui.popover({\n        className: 'note-link-popover',\n        callback: function ($node) {\n          var $content = $node.find('.popover-content');\n          $content.prepend('<span><a target=\"_blank\"></a>&nbsp;</span>');\n        }\n      }).render().appendTo('body');\n      var $content = this.$popover.find('.popover-content');\n\n      context.invoke('buttons.build', $content, options.popover.link);\n    };\n\n    this.destroy = function () {\n      this.$popover.remove();\n    };\n\n    this.update = function () {\n      // Prevent focusing on editable when invoke('code') is executed\n      if (!context.invoke('editor.hasFocus')) {\n        this.hide();\n        return;\n      }\n\n      var rng = context.invoke('editor.createRange');\n      if (rng.isCollapsed() && rng.isOnAnchor()) {\n        var anchor = dom.ancestor(rng.sc, dom.isAnchor);\n        var href = $(anchor).attr('href');\n        this.$popover.find('a').attr('href', href).html(href);\n\n        var pos = dom.posFromPlaceholder(anchor);\n        this.$popover.css({\n          display: 'block',\n          left: pos.left,\n          top: pos.top\n        });\n      } else {\n        this.hide();\n      }\n    };\n\n    this.hide = function () {\n      this.$popover.hide();\n    };\n  };\n\n  var ImageDialog = function (context) {\n    var self = this;\n    var ui = $.summernote.ui;\n\n    var $editor = context.layoutInfo.editor;\n    var options = context.options;\n    var lang = options.langInfo;\n\n    this.initialize = function () {\n      var $container = options.dialogsInBody ? $(document.body) : $editor;\n\n      var imageLimitation = '';\n      if (options.maximumImageFileSize) {\n        var unit = Math.floor(Math.log(options.maximumImageFileSize) / Math.log(1024));\n        var readableSize = (options.maximumImageFileSize / Math.pow(1024, unit)).toFixed(2) * 1 +\n                           ' ' + ' KMGTP'[unit] + 'B';\n        imageLimitation = '<small>' + lang.image.maximumFileSize + ' : ' + readableSize + '</small>';\n      }\n\n      var body = '<div class=\"form-group note-group-select-from-files\">' +\n                   '<label>' + lang.image.selectFromFiles + '</label>' +\n                   '<input class=\"note-image-input form-control\" type=\"file\" name=\"files\" accept=\"image/*\" multiple=\"multiple\" />' +\n                   imageLimitation +\n                 '</div>' +\n                 '<div class=\"form-group note-group-image-url\" style=\"overflow:auto;\">' +\n                   '<label>' + lang.image.url + '</label>' +\n                   '<input class=\"note-image-url form-control col-md-12\" type=\"text\" />' +\n                 '</div>';\n      var footer = '<button href=\"#\" class=\"btn btn-primary note-image-btn disabled\" disabled>' + lang.image.insert + '</button>';\n\n      this.$dialog = ui.dialog({\n        title: lang.image.insert,\n        fade: options.dialogsFade,\n        body: body,\n        footer: footer\n      }).render().appendTo($container);\n    };\n\n    this.destroy = function () {\n      ui.hideDialog(this.$dialog);\n      this.$dialog.remove();\n    };\n\n    this.bindEnterKey = function ($input, $btn) {\n      $input.on('keypress', function (event) {\n        if (event.keyCode === key.code.ENTER) {\n          $btn.trigger('click');\n        }\n      });\n    };\n\n    this.show = function () {\n      context.invoke('editor.saveRange');\n      this.showImageDialog().then(function (data) {\n        // [workaround] hide dialog before restore range for IE range focus\n        ui.hideDialog(self.$dialog);\n        context.invoke('editor.restoreRange');\n\n        if (typeof data === 'string') { // image url\n          context.invoke('editor.insertImage', data);\n        } else { // array of files\n          context.invoke('editor.insertImagesOrCallback', data);\n        }\n      }).fail(function () {\n        context.invoke('editor.restoreRange');\n      });\n    };\n\n    /**\n     * show image dialog\n     *\n     * @param {jQuery} $dialog\n     * @return {Promise}\n     */\n    this.showImageDialog = function () {\n      return $.Deferred(function (deferred) {\n        var $imageInput = self.$dialog.find('.note-image-input'),\n            $imageUrl = self.$dialog.find('.note-image-url'),\n            $imageBtn = self.$dialog.find('.note-image-btn');\n\n        ui.onDialogShown(self.$dialog, function () {\n          context.triggerEvent('dialog.shown');\n\n          // Cloning imageInput to clear element.\n          $imageInput.replaceWith($imageInput.clone()\n            .on('change', function () {\n              deferred.resolve(this.files || this.value);\n            })\n            .val('')\n          );\n\n          $imageBtn.click(function (event) {\n            event.preventDefault();\n\n            deferred.resolve($imageUrl.val());\n          });\n\n          $imageUrl.on('keyup paste', function () {\n            var url = $imageUrl.val();\n            ui.toggleBtn($imageBtn, url);\n          }).val('').trigger('focus');\n          self.bindEnterKey($imageUrl, $imageBtn);\n        });\n\n        ui.onDialogHidden(self.$dialog, function () {\n          $imageInput.off('change');\n          $imageUrl.off('keyup paste keypress');\n          $imageBtn.off('click');\n\n          if (deferred.state() === 'pending') {\n            deferred.reject();\n          }\n        });\n\n        ui.showDialog(self.$dialog);\n      });\n    };\n  };\n\n  var ImagePopover = function (context) {\n    var ui = $.summernote.ui;\n\n    var options = context.options;\n\n    this.shouldInitialize = function () {\n      return !list.isEmpty(options.popover.image);\n    };\n\n    this.initialize = function () {\n      this.$popover = ui.popover({\n        className: 'note-image-popover'\n      }).render().appendTo('body');\n      var $content = this.$popover.find('.popover-content');\n\n      context.invoke('buttons.build', $content, options.popover.image);\n    };\n\n    this.destroy = function () {\n      this.$popover.remove();\n    };\n\n    this.update = function (target) {\n      if (dom.isImg(target)) {\n        var pos = dom.posFromPlaceholder(target);\n        this.$popover.css({\n          display: 'block',\n          left: pos.left,\n          top: pos.top\n        });\n      } else {\n        this.hide();\n      }\n    };\n\n    this.hide = function () {\n      this.$popover.hide();\n    };\n  };\n\n  var VideoDialog = function (context) {\n    var self = this;\n    var ui = $.summernote.ui;\n\n    var $editor = context.layoutInfo.editor;\n    var options = context.options;\n    var lang = options.langInfo;\n\n    this.initialize = function () {\n      var $container = options.dialogsInBody ? $(document.body) : $editor;\n\n      var body = '<div class=\"form-group row-fluid\">' +\n          '<label>' + lang.video.url + ' <small class=\"text-muted\">' + lang.video.providers + '</small></label>' +\n          '<input class=\"note-video-url form-control span12\" type=\"text\" />' +\n          '</div>';\n      var footer = '<button href=\"#\" class=\"btn btn-primary note-video-btn disabled\" disabled>' + lang.video.insert + '</button>';\n\n      this.$dialog = ui.dialog({\n        title: lang.video.insert,\n        fade: options.dialogsFade,\n        body: body,\n        footer: footer\n      }).render().appendTo($container);\n    };\n\n    this.destroy = function () {\n      ui.hideDialog(this.$dialog);\n      this.$dialog.remove();\n    };\n\n    this.bindEnterKey = function ($input, $btn) {\n      $input.on('keypress', function (event) {\n        if (event.keyCode === key.code.ENTER) {\n          $btn.trigger('click');\n        }\n      });\n    };\n\n    this.createVideoNode = function (url) {\n      // video url patterns(youtube, instagram, vimeo, dailymotion, youku, mp4, ogg, webm)\n      var ytRegExp = /^(?:https?:\\/\\/)?(?:www\\.)?(?:youtu\\.be\\/|youtube\\.com\\/(?:embed\\/|v\\/|watch\\?v=|watch\\?.+&v=))((\\w|-){11})(?:\\S+)?$/;\n      var ytMatch = url.match(ytRegExp);\n\n      var igRegExp = /(?:www\\.|\\/\\/)instagram\\.com\\/p\\/(.[a-zA-Z0-9_-]*)/;\n      var igMatch = url.match(igRegExp);\n\n      var vRegExp = /\\/\\/vine\\.co\\/v\\/([a-zA-Z0-9]+)/;\n      var vMatch = url.match(vRegExp);\n\n      var vimRegExp = /\\/\\/(player\\.)?vimeo\\.com\\/([a-z]*\\/)*([0-9]{6,11})[?]?.*/;\n      var vimMatch = url.match(vimRegExp);\n\n      var dmRegExp = /.+dailymotion.com\\/(video|hub)\\/([^_]+)[^#]*(#video=([^_&]+))?/;\n      var dmMatch = url.match(dmRegExp);\n\n      var youkuRegExp = /\\/\\/v\\.youku\\.com\\/v_show\\/id_(\\w+)=*\\.html/;\n      var youkuMatch = url.match(youkuRegExp);\n\n      var mp4RegExp = /^.+.(mp4|m4v)$/;\n      var mp4Match = url.match(mp4RegExp);\n\n      var oggRegExp = /^.+.(ogg|ogv)$/;\n      var oggMatch = url.match(oggRegExp);\n\n      var webmRegExp = /^.+.(webm)$/;\n      var webmMatch = url.match(webmRegExp);\n\n      var $video;\n      if (ytMatch && ytMatch[1].length === 11) {\n        var youtubeId = ytMatch[1];\n        $video = $('<iframe>')\n            .attr('frameborder', 0)\n            .attr('src', '//www.youtube.com/embed/' + youtubeId)\n            .attr('width', '640').attr('height', '360');\n      } else if (igMatch && igMatch[0].length) {\n        $video = $('<iframe>')\n            .attr('frameborder', 0)\n            .attr('src', 'https://instagram.com/p/' + igMatch[1] + '/embed/')\n            .attr('width', '612').attr('height', '710')\n            .attr('scrolling', 'no')\n            .attr('allowtransparency', 'true');\n      } else if (vMatch && vMatch[0].length) {\n        $video = $('<iframe>')\n            .attr('frameborder', 0)\n            .attr('src', vMatch[0] + '/embed/simple')\n            .attr('width', '600').attr('height', '600')\n            .attr('class', 'vine-embed');\n      } else if (vimMatch && vimMatch[3].length) {\n        $video = $('<iframe webkitallowfullscreen mozallowfullscreen allowfullscreen>')\n            .attr('frameborder', 0)\n            .attr('src', '//player.vimeo.com/video/' + vimMatch[3])\n            .attr('width', '640').attr('height', '360');\n      } else if (dmMatch && dmMatch[2].length) {\n        $video = $('<iframe>')\n            .attr('frameborder', 0)\n            .attr('src', '//www.dailymotion.com/embed/video/' + dmMatch[2])\n            .attr('width', '640').attr('height', '360');\n      } else if (youkuMatch && youkuMatch[1].length) {\n        $video = $('<iframe webkitallowfullscreen mozallowfullscreen allowfullscreen>')\n            .attr('frameborder', 0)\n            .attr('height', '498')\n            .attr('width', '510')\n            .attr('src', '//player.youku.com/embed/' + youkuMatch[1]);\n      } else if (mp4Match || oggMatch || webmMatch) {\n        $video = $('<video controls>')\n            .attr('src', url)\n            .attr('width', '640').attr('height', '360');\n      } else {\n        // this is not a known video link. Now what, Cat? Now what?\n        return false;\n      }\n\n      $video.addClass('note-video-clip');\n\n      return $video[0];\n    };\n\n    this.show = function () {\n      var text = context.invoke('editor.getSelectedText');\n      context.invoke('editor.saveRange');\n      this.showVideoDialog(text).then(function (url) {\n        // [workaround] hide dialog before restore range for IE range focus\n        ui.hideDialog(self.$dialog);\n        context.invoke('editor.restoreRange');\n\n        // build node\n        var $node = self.createVideoNode(url);\n\n        if ($node) {\n          // insert video node\n          context.invoke('editor.insertNode', $node);\n        }\n      }).fail(function () {\n        context.invoke('editor.restoreRange');\n      });\n    };\n\n    /**\n     * show image dialog\n     *\n     * @param {jQuery} $dialog\n     * @return {Promise}\n     */\n    this.showVideoDialog = function (text) {\n      return $.Deferred(function (deferred) {\n        var $videoUrl = self.$dialog.find('.note-video-url'),\n            $videoBtn = self.$dialog.find('.note-video-btn');\n\n        ui.onDialogShown(self.$dialog, function () {\n          context.triggerEvent('dialog.shown');\n\n          $videoUrl.val(text).on('input', function () {\n            ui.toggleBtn($videoBtn, $videoUrl.val());\n          }).trigger('focus');\n\n          $videoBtn.click(function (event) {\n            event.preventDefault();\n\n            deferred.resolve($videoUrl.val());\n          });\n\n          self.bindEnterKey($videoUrl, $videoBtn);\n        });\n\n        ui.onDialogHidden(self.$dialog, function () {\n          $videoUrl.off('input');\n          $videoBtn.off('click');\n\n          if (deferred.state() === 'pending') {\n            deferred.reject();\n          }\n        });\n\n        ui.showDialog(self.$dialog);\n      });\n    };\n  };\n\n  var HelpDialog = function (context) {\n    var self = this;\n    var ui = $.summernote.ui;\n\n    var $editor = context.layoutInfo.editor;\n    var options = context.options;\n    var lang = options.langInfo;\n\n    this.createShortCutList = function () {\n      var keyMap = options.keyMap[agent.isMac ? 'mac' : 'pc'];\n      return Object.keys(keyMap).map(function (key) {\n        var command = keyMap[key];\n        var $row = $('<div><div class=\"help-list-item\"/></div>');\n        $row.append($('<label><kbd>' + key + '</kdb></label>').css({\n          'width': 180,\n          'margin-right': 10\n        })).append($('<span/>').html(context.memo('help.' + command) || command));\n        return $row.html();\n      }).join('');\n    };\n\n    this.initialize = function () {\n      var $container = options.dialogsInBody ? $(document.body) : $editor;\n\n      var body = [\n        '<p class=\"text-center\">',\n        '<a href=\"http://summernote.org/\" target=\"_blank\">Summernote 0.8.2</a> · ',\n        '<a href=\"https://github.com/summernote/summernote\" target=\"_blank\">Project</a> · ',\n        '<a href=\"https://github.com/summernote/summernote/issues\" target=\"_blank\">Issues</a>',\n        '</p>'\n      ].join('');\n\n      this.$dialog = ui.dialog({\n        title: lang.options.help,\n        fade: options.dialogsFade,\n        body: this.createShortCutList(),\n        footer: body,\n        callback: function ($node) {\n          $node.find('.modal-body').css({\n            'max-height': 300,\n            'overflow': 'scroll'\n          });\n        }\n      }).render().appendTo($container);\n    };\n\n    this.destroy = function () {\n      ui.hideDialog(this.$dialog);\n      this.$dialog.remove();\n    };\n\n    /**\n     * show help dialog\n     *\n     * @return {Promise}\n     */\n    this.showHelpDialog = function () {\n      return $.Deferred(function (deferred) {\n        ui.onDialogShown(self.$dialog, function () {\n          context.triggerEvent('dialog.shown');\n          deferred.resolve();\n        });\n        ui.showDialog(self.$dialog);\n      }).promise();\n    };\n\n    this.show = function () {\n      context.invoke('editor.saveRange');\n      this.showHelpDialog().then(function () {\n        context.invoke('editor.restoreRange');\n      });\n    };\n  };\n\n  var AirPopover = function (context) {\n    var self = this;\n    var ui = $.summernote.ui;\n\n    var options = context.options;\n\n    var AIR_MODE_POPOVER_X_OFFSET = 20;\n\n    this.events = {\n      'summernote.keyup summernote.mouseup summernote.scroll': function () {\n        self.update();\n      },\n      'summernote.change summernote.dialog.shown': function () {\n        self.hide();\n      },\n      'summernote.focusout': function (we, e) {\n        // [workaround] Firefox doesn't support relatedTarget on focusout\n        //  - Ignore hide action on focus out in FF.\n        if (agent.isFF) {\n          return;\n        }\n\n        if (!e.relatedTarget || !dom.ancestor(e.relatedTarget, func.eq(self.$popover[0]))) {\n          self.hide();\n        }\n      }\n    };\n\n    this.shouldInitialize = function () {\n      return options.airMode && !list.isEmpty(options.popover.air);\n    };\n\n    this.initialize = function () {\n      this.$popover = ui.popover({\n        className: 'note-air-popover'\n      }).render().appendTo('body');\n      var $content = this.$popover.find('.popover-content');\n\n      context.invoke('buttons.build', $content, options.popover.air);\n    };\n\n    this.destroy = function () {\n      this.$popover.remove();\n    };\n\n    this.update = function () {\n      var styleInfo = context.invoke('editor.currentStyle');\n      if (styleInfo.range && !styleInfo.range.isCollapsed()) {\n        var rect = list.last(styleInfo.range.getClientRects());\n        if (rect) {\n          var bnd = func.rect2bnd(rect);\n          this.$popover.css({\n            display: 'block',\n            left: Math.max(bnd.left + bnd.width / 2, 0) - AIR_MODE_POPOVER_X_OFFSET,\n            top: bnd.top + bnd.height\n          });\n        }\n      } else {\n        this.hide();\n      }\n    };\n\n    this.hide = function () {\n      this.$popover.hide();\n    };\n  };\n\n  var HintPopover = function (context) {\n    var self = this;\n    var ui = $.summernote.ui;\n\n    var POPOVER_DIST = 5;\n    var hint = context.options.hint || [];\n    var direction = context.options.hintDirection || 'bottom';\n    var hints = $.isArray(hint) ? hint : [hint];\n\n    this.events = {\n      'summernote.keyup': function (we, e) {\n        if (!e.isDefaultPrevented()) {\n          self.handleKeyup(e);\n        }\n      },\n      'summernote.keydown': function (we, e) {\n        self.handleKeydown(e);\n      },\n      'summernote.dialog.shown': function () {\n        self.hide();\n      }\n    };\n\n    this.shouldInitialize = function () {\n      return hints.length > 0;\n    };\n\n    this.initialize = function () {\n      this.lastWordRange = null;\n      this.$popover = ui.popover({\n        className: 'note-hint-popover',\n        hideArrow: true,\n        direction: ''\n      }).render().appendTo('body');\n\n      this.$popover.hide();\n\n      this.$content = this.$popover.find('.popover-content');\n\n      this.$content.on('click', '.note-hint-item', function () {\n        self.$content.find('.active').removeClass('active');\n        $(this).addClass('active');\n        self.replace();\n      });\n    };\n\n    this.destroy = function () {\n      this.$popover.remove();\n    };\n\n    this.selectItem = function ($item) {\n      this.$content.find('.active').removeClass('active');\n      $item.addClass('active');\n\n      this.$content[0].scrollTop = $item[0].offsetTop - (this.$content.innerHeight() / 2);\n    };\n\n    this.moveDown = function () {\n      var $current = this.$content.find('.note-hint-item.active');\n      var $next = $current.next();\n\n      if ($next.length) {\n        this.selectItem($next);\n      } else {\n        var $nextGroup = $current.parent().next();\n\n        if (!$nextGroup.length) {\n          $nextGroup = this.$content.find('.note-hint-group').first();\n        }\n\n        this.selectItem($nextGroup.find('.note-hint-item').first());\n      }\n    };\n\n    this.moveUp = function () {\n      var $current = this.$content.find('.note-hint-item.active');\n      var $prev = $current.prev();\n\n      if ($prev.length) {\n        this.selectItem($prev);\n      } else {\n        var $prevGroup = $current.parent().prev();\n\n        if (!$prevGroup.length) {\n          $prevGroup = this.$content.find('.note-hint-group').last();\n        }\n\n        this.selectItem($prevGroup.find('.note-hint-item').last());\n      }\n    };\n\n    this.replace = function () {\n      var $item = this.$content.find('.note-hint-item.active');\n\n      if ($item.length) {\n        var node = this.nodeFromItem($item);\n        this.lastWordRange.insertNode(node);\n        range.createFromNode(node).collapse().select();\n\n        this.lastWordRange = null;\n        this.hide();\n        context.invoke('editor.focus');\n      }\n\n    };\n\n    this.nodeFromItem = function ($item) {\n      var hint = hints[$item.data('index')];\n      var item = $item.data('item');\n      var node = hint.content ? hint.content(item) : item;\n      if (typeof node === 'string') {\n        node = dom.createText(node);\n      }\n      return node;\n    };\n\n    this.createItemTemplates = function (hintIdx, items) {\n      var hint = hints[hintIdx];\n      return items.map(function (item, idx) {\n        var $item = $('<div class=\"note-hint-item\"/>');\n        $item.append(hint.template ? hint.template(item) : item + '');\n        $item.data({\n          'index': hintIdx,\n          'item': item\n        });\n\n        if (hintIdx === 0 && idx === 0) {\n          $item.addClass('active');\n        }\n        return $item;\n      });\n    };\n\n    this.handleKeydown = function (e) {\n      if (!this.$popover.is(':visible')) {\n        return;\n      }\n\n      if (e.keyCode === key.code.ENTER) {\n        e.preventDefault();\n        this.replace();\n      } else if (e.keyCode === key.code.UP) {\n        e.preventDefault();\n        this.moveUp();\n      } else if (e.keyCode === key.code.DOWN) {\n        e.preventDefault();\n        this.moveDown();\n      }\n    };\n\n    this.searchKeyword = function (index, keyword, callback) {\n      var hint = hints[index];\n      if (hint && hint.match.test(keyword) && hint.search) {\n        var matches = hint.match.exec(keyword);\n        hint.search(matches[1], callback);\n      } else {\n        callback();\n      }\n    };\n\n    this.createGroup = function (idx, keyword) {\n      var $group = $('<div class=\"note-hint-group note-hint-group-' + idx + '\"/>');\n      this.searchKeyword(idx, keyword, function (items) {\n        items = items || [];\n        if (items.length) {\n          $group.html(self.createItemTemplates(idx, items));\n          self.show();\n        }\n      });\n\n      return $group;\n    };\n\n    this.handleKeyup = function (e) {\n      if (list.contains([key.code.ENTER, key.code.UP, key.code.DOWN], e.keyCode)) {\n        if (e.keyCode === key.code.ENTER) {\n          if (this.$popover.is(':visible')) {\n            return;\n          }\n        }\n      } else {\n        var wordRange = context.invoke('editor.createRange').getWordRange();\n        var keyword = wordRange.toString();\n        if (hints.length && keyword) {\n          this.$content.empty();\n\n          var bnd = func.rect2bnd(list.last(wordRange.getClientRects()));\n          if (bnd) {\n\n            this.$popover.hide();\n\n            this.lastWordRange = wordRange;\n\n            hints.forEach(function (hint, idx) {\n              if (hint.match.test(keyword)) {\n                self.createGroup(idx, keyword).appendTo(self.$content);\n              }\n            });\n\n            // set position for popover after group is created\n            if (direction === 'top') {\n              this.$popover.css({\n                left: bnd.left,\n                top: bnd.top - this.$popover.outerHeight() - POPOVER_DIST\n              });\n            } else {\n              this.$popover.css({\n                left: bnd.left,\n                top: bnd.top + bnd.height + POPOVER_DIST\n              });\n            }\n\n          }\n        } else {\n          this.hide();\n        }\n      }\n    };\n\n    this.show = function () {\n      this.$popover.show();\n    };\n\n    this.hide = function () {\n      this.$popover.hide();\n    };\n  };\n\n\n  $.summernote = $.extend($.summernote, {\n    version: '0.8.2',\n    ui: ui,\n    dom: dom,\n\n    plugins: {},\n\n    options: {\n      modules: {\n        'editor': Editor,\n        'clipboard': Clipboard,\n        'dropzone': Dropzone,\n        'codeview': Codeview,\n        'statusbar': Statusbar,\n        'fullscreen': Fullscreen,\n        'handle': Handle,\n        // FIXME: HintPopover must be front of autolink\n        //  - Script error about range when Enter key is pressed on hint popover\n        'hintPopover': HintPopover,\n        'autoLink': AutoLink,\n        'autoSync': AutoSync,\n        'placeholder': Placeholder,\n        'buttons': Buttons,\n        'toolbar': Toolbar,\n        'linkDialog': LinkDialog,\n        'linkPopover': LinkPopover,\n        'imageDialog': ImageDialog,\n        'imagePopover': ImagePopover,\n        'videoDialog': VideoDialog,\n        'helpDialog': HelpDialog,\n        'airPopover': AirPopover\n      },\n\n      buttons: {},\n      \n      lang: 'en-US',\n\n      // toolbar\n      toolbar: [\n        ['style', ['style']],\n        ['font', ['bold', 'underline', 'clear']],\n        ['fontname', ['fontname']],\n        ['color', ['color']],\n        ['para', ['ul', 'ol', 'paragraph']],\n        ['table', ['table']],\n        ['insert', ['link', 'picture', 'video']],\n        ['view', ['fullscreen', 'codeview', 'help']]\n      ],\n\n      // popover\n      popover: {\n        image: [\n          ['imagesize', ['imageSize100', 'imageSize50', 'imageSize25']],\n          ['float', ['floatLeft', 'floatRight', 'floatNone']],\n          ['remove', ['removeMedia']]\n        ],\n        link: [\n          ['link', ['linkDialogShow', 'unlink']]\n        ],\n        air: [\n          ['color', ['color']],\n          ['font', ['bold', 'underline', 'clear']],\n          ['para', ['ul', 'paragraph']],\n          ['table', ['table']],\n          ['insert', ['link', 'picture']]\n        ]\n      },\n\n      // air mode: inline editor\n      airMode: false,\n\n      width: null,\n      height: null,\n\n      focus: false,\n      tabSize: 4,\n      styleWithSpan: true,\n      shortcuts: true,\n      textareaAutoSync: true,\n      direction: null,\n\n      styleTags: ['p', 'blockquote', 'pre', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'],\n\n      fontNames: [\n        'Arial', 'Arial Black', 'Comic Sans MS', 'Courier New',\n        'Helvetica Neue', 'Helvetica', 'Impact', 'Lucida Grande',\n        'Tahoma', 'Times New Roman', 'Verdana'\n      ],\n\n      fontSizes: ['8', '9', '10', '11', '12', '14', '18', '24', '36'],\n\n      // pallete colors(n x n)\n      colors: [\n        ['#000000', '#424242', '#636363', '#9C9C94', '#CEC6CE', '#EFEFEF', '#F7F7F7', '#FFFFFF'],\n        ['#FF0000', '#FF9C00', '#FFFF00', '#00FF00', '#00FFFF', '#0000FF', '#9C00FF', '#FF00FF'],\n        ['#F7C6CE', '#FFE7CE', '#FFEFC6', '#D6EFD6', '#CEDEE7', '#CEE7F7', '#D6D6E7', '#E7D6DE'],\n        ['#E79C9C', '#FFC69C', '#FFE79C', '#B5D6A5', '#A5C6CE', '#9CC6EF', '#B5A5D6', '#D6A5BD'],\n        ['#E76363', '#F7AD6B', '#FFD663', '#94BD7B', '#73A5AD', '#6BADDE', '#8C7BC6', '#C67BA5'],\n        ['#CE0000', '#E79439', '#EFC631', '#6BA54A', '#4A7B8C', '#3984C6', '#634AA5', '#A54A7B'],\n        ['#9C0000', '#B56308', '#BD9400', '#397B21', '#104A5A', '#085294', '#311873', '#731842'],\n        ['#630000', '#7B3900', '#846300', '#295218', '#083139', '#003163', '#21104A', '#4A1031']\n      ],\n\n      lineHeights: ['1.0', '1.2', '1.4', '1.5', '1.6', '1.8', '2.0', '3.0'],\n\n      tableClassName: 'table table-bordered',\n\n      insertTableMaxSize: {\n        col: 10,\n        row: 10\n      },\n\n      dialogsInBody: false,\n      dialogsFade: false,\n\n      maximumImageFileSize: null,\n\n      callbacks: {\n        onInit: null,\n        onFocus: null,\n        onBlur: null,\n        onEnter: null,\n        onKeyup: null,\n        onKeydown: null,\n        onImageUpload: null,\n        onImageUploadError: null\n      },\n\n      codemirror: {\n        mode: 'text/html',\n        htmlMode: true,\n        lineNumbers: true\n      },\n\n      keyMap: {\n        pc: {\n          'ENTER': 'insertParagraph',\n          'CTRL+Z': 'undo',\n          'CTRL+Y': 'redo',\n          'TAB': 'tab',\n          'SHIFT+TAB': 'untab',\n          'CTRL+B': 'bold',\n          'CTRL+I': 'italic',\n          'CTRL+U': 'underline',\n          'CTRL+SHIFT+S': 'strikethrough',\n          'CTRL+BACKSLASH': 'removeFormat',\n          'CTRL+SHIFT+L': 'justifyLeft',\n          'CTRL+SHIFT+E': 'justifyCenter',\n          'CTRL+SHIFT+R': 'justifyRight',\n          'CTRL+SHIFT+J': 'justifyFull',\n          'CTRL+SHIFT+NUM7': 'insertUnorderedList',\n          'CTRL+SHIFT+NUM8': 'insertOrderedList',\n          'CTRL+LEFTBRACKET': 'outdent',\n          'CTRL+RIGHTBRACKET': 'indent',\n          'CTRL+NUM0': 'formatPara',\n          'CTRL+NUM1': 'formatH1',\n          'CTRL+NUM2': 'formatH2',\n          'CTRL+NUM3': 'formatH3',\n          'CTRL+NUM4': 'formatH4',\n          'CTRL+NUM5': 'formatH5',\n          'CTRL+NUM6': 'formatH6',\n          'CTRL+ENTER': 'insertHorizontalRule',\n          'CTRL+K': 'linkDialog.show'\n        },\n\n        mac: {\n          'ENTER': 'insertParagraph',\n          'CMD+Z': 'undo',\n          'CMD+SHIFT+Z': 'redo',\n          'TAB': 'tab',\n          'SHIFT+TAB': 'untab',\n          'CMD+B': 'bold',\n          'CMD+I': 'italic',\n          'CMD+U': 'underline',\n          'CMD+SHIFT+S': 'strikethrough',\n          'CMD+BACKSLASH': 'removeFormat',\n          'CMD+SHIFT+L': 'justifyLeft',\n          'CMD+SHIFT+E': 'justifyCenter',\n          'CMD+SHIFT+R': 'justifyRight',\n          'CMD+SHIFT+J': 'justifyFull',\n          'CMD+SHIFT+NUM7': 'insertUnorderedList',\n          'CMD+SHIFT+NUM8': 'insertOrderedList',\n          'CMD+LEFTBRACKET': 'outdent',\n          'CMD+RIGHTBRACKET': 'indent',\n          'CMD+NUM0': 'formatPara',\n          'CMD+NUM1': 'formatH1',\n          'CMD+NUM2': 'formatH2',\n          'CMD+NUM3': 'formatH3',\n          'CMD+NUM4': 'formatH4',\n          'CMD+NUM5': 'formatH5',\n          'CMD+NUM6': 'formatH6',\n          'CMD+ENTER': 'insertHorizontalRule',\n          'CMD+K': 'linkDialog.show'\n        }\n      },\n      icons: {\n        'align': 'note-icon-align',\n        'alignCenter': 'note-icon-align-center',\n        'alignJustify': 'note-icon-align-justify',\n        'alignLeft': 'note-icon-align-left',\n        'alignRight': 'note-icon-align-right',\n        'indent': 'note-icon-align-indent',\n        'outdent': 'note-icon-align-outdent',\n        'arrowsAlt': 'note-icon-arrows-alt',\n        'bold': 'note-icon-bold',\n        'caret': 'note-icon-caret',\n        'circle': 'note-icon-circle',\n        'close': 'note-icon-close',\n        'code': 'note-icon-code',\n        'eraser': 'note-icon-eraser',\n        'font': 'note-icon-font',\n        'frame': 'note-icon-frame',\n        'italic': 'note-icon-italic',\n        'link': 'note-icon-link',\n        'unlink': 'note-icon-chain-broken',\n        'magic': 'note-icon-magic',\n        'menuCheck': 'note-icon-check',\n        'minus': 'note-icon-minus',\n        'orderedlist': 'note-icon-orderedlist',\n        'pencil': 'note-icon-pencil',\n        'picture': 'note-icon-picture',\n        'question': 'note-icon-question',\n        'redo': 'note-icon-redo',\n        'square': 'note-icon-square',\n        'strikethrough': 'note-icon-strikethrough',\n        'subscript': 'note-icon-subscript',\n        'superscript': 'note-icon-superscript',\n        'table': 'note-icon-table',\n        'textHeight': 'note-icon-text-height',\n        'trash': 'note-icon-trash',\n        'underline': 'note-icon-underline',\n        'undo': 'note-icon-undo',\n        'unorderedlist': 'note-icon-unorderedlist',\n        'video': 'note-icon-video'\n      }\n    }\n  });\n\n}));\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/base-component/layer/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": "open-layui-web/src/main/view/static/base-component/layer/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": "open-layui-web/src/main/view/static/css/bootstrap-treeview.css",
    "content": "/* =========================================================\n * bootstrap-treeview.css v2.0.0\n * =========================================================\n * Copyright 2013 Jonathan Miles\n * Project URL : http://www.jondmiles.com/bootstrap-treeview\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.treeview .list-group-item {\n\tcursor: pointer;\n}\n\n.treeview span.indent {\n\tmargin-left: 10px;\n\tmargin-right: 10px;\n}\n\n.treeview span.icon {\n\twidth: 12px;\n\tmargin-right: 5px;\n}\n\n.treeview .node-disabled {\n\tcolor: silver;\n\tcursor: not-allowed;\n}\n\n.treeview .node-hidden {\n\tdisplay: none;\n}\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/css/font-awesome/css/font-awesome.css",
    "content": "/*!\n *  Font Awesome 4.7.0 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.7.0');\n  src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'), url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg');\n  font-weight: normal;\n  font-style: normal;\n}\n.fa {\n  display: inline-block;\n  font: normal normal normal 14px/1 FontAwesome;\n  font-size: inherit;\n  text-rendering: auto;\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.33333333em;\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.28571429em;\n  text-align: center;\n}\n.fa-ul {\n  padding-left: 0;\n  margin-left: 2.14285714em;\n  list-style-type: none;\n}\n.fa-ul > li {\n  position: relative;\n}\n.fa-li {\n  position: absolute;\n  left: -2.14285714em;\n  width: 2.14285714em;\n  top: 0.14285714em;\n  text-align: center;\n}\n.fa-li.fa-lg {\n  left: -1.85714286em;\n}\n.fa-border {\n  padding: .2em .25em .15em;\n  border: solid 0.08em #eeeeee;\n  border-radius: .1em;\n}\n.fa-pull-left {\n  float: left;\n}\n.fa-pull-right {\n  float: right;\n}\n.fa.fa-pull-left {\n  margin-right: .3em;\n}\n.fa.fa-pull-right {\n  margin-left: .3em;\n}\n/* Deprecated as of 4.4.0 */\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: fa-spin 2s infinite linear;\n  animation: fa-spin 2s infinite linear;\n}\n.fa-pulse {\n  -webkit-animation: fa-spin 1s infinite steps(8);\n  animation: fa-spin 1s infinite steps(8);\n}\n@-webkit-keyframes fa-spin {\n  0% {\n    -webkit-transform: rotate(0deg);\n    transform: rotate(0deg);\n  }\n  100% {\n    -webkit-transform: rotate(359deg);\n    transform: rotate(359deg);\n  }\n}\n@keyframes fa-spin {\n  0% {\n    -webkit-transform: rotate(0deg);\n    transform: rotate(0deg);\n  }\n  100% {\n    -webkit-transform: rotate(359deg);\n    transform: rotate(359deg);\n  }\n}\n.fa-rotate-90 {\n  -ms-filter: \"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)\";\n  -webkit-transform: rotate(90deg);\n  -ms-transform: rotate(90deg);\n  transform: rotate(90deg);\n}\n.fa-rotate-180 {\n  -ms-filter: \"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)\";\n  -webkit-transform: rotate(180deg);\n  -ms-transform: rotate(180deg);\n  transform: rotate(180deg);\n}\n.fa-rotate-270 {\n  -ms-filter: \"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)\";\n  -webkit-transform: rotate(270deg);\n  -ms-transform: rotate(270deg);\n  transform: rotate(270deg);\n}\n.fa-flip-horizontal {\n  -ms-filter: \"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)\";\n  -webkit-transform: scale(-1, 1);\n  -ms-transform: scale(-1, 1);\n  transform: scale(-1, 1);\n}\n.fa-flip-vertical {\n  -ms-filter: \"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)\";\n  -webkit-transform: scale(1, -1);\n  -ms-transform: scale(1, -1);\n  transform: scale(1, -1);\n}\n:root .fa-rotate-90,\n:root .fa-rotate-180,\n:root .fa-rotate-270,\n:root .fa-flip-horizontal,\n:root .fa-flip-vertical {\n  filter: none;\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-remove:before,\n.fa-close:before,\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\";\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-photo:before,\n.fa-image:before,\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-bar-chart-o:before,\n.fa-bar-chart:before {\n  content: \"\\f080\";\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-f:before,\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-feed:before,\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-navicon:before,\n.fa-reorder:before,\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: \"\\f0d6\";\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-desc:before {\n  content: \"\\f0dd\";\n}\n.fa-sort-up:before,\n.fa-sort-asc: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-mail-reply-all:before,\n.fa-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: \"\\f145\";\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.fa-gratipay: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-space-shuttle:before {\n  content: \"\\f197\";\n}\n.fa-slack:before {\n  content: \"\\f198\";\n}\n.fa-envelope-square:before {\n  content: \"\\f199\";\n}\n.fa-wordpress:before {\n  content: \"\\f19a\";\n}\n.fa-openid:before {\n  content: \"\\f19b\";\n}\n.fa-institution:before,\n.fa-bank:before,\n.fa-university:before {\n  content: \"\\f19c\";\n}\n.fa-mortar-board:before,\n.fa-graduation-cap:before {\n  content: \"\\f19d\";\n}\n.fa-yahoo:before {\n  content: \"\\f19e\";\n}\n.fa-google:before {\n  content: \"\\f1a0\";\n}\n.fa-reddit:before {\n  content: \"\\f1a1\";\n}\n.fa-reddit-square:before {\n  content: \"\\f1a2\";\n}\n.fa-stumbleupon-circle:before {\n  content: \"\\f1a3\";\n}\n.fa-stumbleupon:before {\n  content: \"\\f1a4\";\n}\n.fa-delicious:before {\n  content: \"\\f1a5\";\n}\n.fa-digg:before {\n  content: \"\\f1a6\";\n}\n.fa-pied-piper-pp:before {\n  content: \"\\f1a7\";\n}\n.fa-pied-piper-alt:before {\n  content: \"\\f1a8\";\n}\n.fa-drupal:before {\n  content: \"\\f1a9\";\n}\n.fa-joomla:before {\n  content: \"\\f1aa\";\n}\n.fa-language:before {\n  content: \"\\f1ab\";\n}\n.fa-fax:before {\n  content: \"\\f1ac\";\n}\n.fa-building:before {\n  content: \"\\f1ad\";\n}\n.fa-child:before {\n  content: \"\\f1ae\";\n}\n.fa-paw:before {\n  content: \"\\f1b0\";\n}\n.fa-spoon:before {\n  content: \"\\f1b1\";\n}\n.fa-cube:before {\n  content: \"\\f1b2\";\n}\n.fa-cubes:before {\n  content: \"\\f1b3\";\n}\n.fa-behance:before {\n  content: \"\\f1b4\";\n}\n.fa-behance-square:before {\n  content: \"\\f1b5\";\n}\n.fa-steam:before {\n  content: \"\\f1b6\";\n}\n.fa-steam-square:before {\n  content: \"\\f1b7\";\n}\n.fa-recycle:before {\n  content: \"\\f1b8\";\n}\n.fa-automobile:before,\n.fa-car:before {\n  content: \"\\f1b9\";\n}\n.fa-cab:before,\n.fa-taxi:before {\n  content: \"\\f1ba\";\n}\n.fa-tree:before {\n  content: \"\\f1bb\";\n}\n.fa-spotify:before {\n  content: \"\\f1bc\";\n}\n.fa-deviantart:before {\n  content: \"\\f1bd\";\n}\n.fa-soundcloud:before {\n  content: \"\\f1be\";\n}\n.fa-database:before {\n  content: \"\\f1c0\";\n}\n.fa-file-pdf-o:before {\n  content: \"\\f1c1\";\n}\n.fa-file-word-o:before {\n  content: \"\\f1c2\";\n}\n.fa-file-excel-o:before {\n  content: \"\\f1c3\";\n}\n.fa-file-powerpoint-o:before {\n  content: \"\\f1c4\";\n}\n.fa-file-photo-o:before,\n.fa-file-picture-o:before,\n.fa-file-image-o:before {\n  content: \"\\f1c5\";\n}\n.fa-file-zip-o:before,\n.fa-file-archive-o:before {\n  content: \"\\f1c6\";\n}\n.fa-file-sound-o:before,\n.fa-file-audio-o:before {\n  content: \"\\f1c7\";\n}\n.fa-file-movie-o:before,\n.fa-file-video-o:before {\n  content: \"\\f1c8\";\n}\n.fa-file-code-o:before {\n  content: \"\\f1c9\";\n}\n.fa-vine:before {\n  content: \"\\f1ca\";\n}\n.fa-codepen:before {\n  content: \"\\f1cb\";\n}\n.fa-jsfiddle:before {\n  content: \"\\f1cc\";\n}\n.fa-life-bouy:before,\n.fa-life-buoy:before,\n.fa-life-saver:before,\n.fa-support:before,\n.fa-life-ring:before {\n  content: \"\\f1cd\";\n}\n.fa-circle-o-notch:before {\n  content: \"\\f1ce\";\n}\n.fa-ra:before,\n.fa-resistance:before,\n.fa-rebel:before {\n  content: \"\\f1d0\";\n}\n.fa-ge:before,\n.fa-empire:before {\n  content: \"\\f1d1\";\n}\n.fa-git-square:before {\n  content: \"\\f1d2\";\n}\n.fa-git:before {\n  content: \"\\f1d3\";\n}\n.fa-y-combinator-square:before,\n.fa-yc-square:before,\n.fa-hacker-news:before {\n  content: \"\\f1d4\";\n}\n.fa-tencent-weibo:before {\n  content: \"\\f1d5\";\n}\n.fa-qq:before {\n  content: \"\\f1d6\";\n}\n.fa-wechat:before,\n.fa-weixin:before {\n  content: \"\\f1d7\";\n}\n.fa-send:before,\n.fa-paper-plane:before {\n  content: \"\\f1d8\";\n}\n.fa-send-o:before,\n.fa-paper-plane-o:before {\n  content: \"\\f1d9\";\n}\n.fa-history:before {\n  content: \"\\f1da\";\n}\n.fa-circle-thin:before {\n  content: \"\\f1db\";\n}\n.fa-header:before {\n  content: \"\\f1dc\";\n}\n.fa-paragraph:before {\n  content: \"\\f1dd\";\n}\n.fa-sliders:before {\n  content: \"\\f1de\";\n}\n.fa-share-alt:before {\n  content: \"\\f1e0\";\n}\n.fa-share-alt-square:before {\n  content: \"\\f1e1\";\n}\n.fa-bomb:before {\n  content: \"\\f1e2\";\n}\n.fa-soccer-ball-o:before,\n.fa-futbol-o:before {\n  content: \"\\f1e3\";\n}\n.fa-tty:before {\n  content: \"\\f1e4\";\n}\n.fa-binoculars:before {\n  content: \"\\f1e5\";\n}\n.fa-plug:before {\n  content: \"\\f1e6\";\n}\n.fa-slideshare:before {\n  content: \"\\f1e7\";\n}\n.fa-twitch:before {\n  content: \"\\f1e8\";\n}\n.fa-yelp:before {\n  content: \"\\f1e9\";\n}\n.fa-newspaper-o:before {\n  content: \"\\f1ea\";\n}\n.fa-wifi:before {\n  content: \"\\f1eb\";\n}\n.fa-calculator:before {\n  content: \"\\f1ec\";\n}\n.fa-paypal:before {\n  content: \"\\f1ed\";\n}\n.fa-google-wallet:before {\n  content: \"\\f1ee\";\n}\n.fa-cc-visa:before {\n  content: \"\\f1f0\";\n}\n.fa-cc-mastercard:before {\n  content: \"\\f1f1\";\n}\n.fa-cc-discover:before {\n  content: \"\\f1f2\";\n}\n.fa-cc-amex:before {\n  content: \"\\f1f3\";\n}\n.fa-cc-paypal:before {\n  content: \"\\f1f4\";\n}\n.fa-cc-stripe:before {\n  content: \"\\f1f5\";\n}\n.fa-bell-slash:before {\n  content: \"\\f1f6\";\n}\n.fa-bell-slash-o:before {\n  content: \"\\f1f7\";\n}\n.fa-trash:before {\n  content: \"\\f1f8\";\n}\n.fa-copyright:before {\n  content: \"\\f1f9\";\n}\n.fa-at:before {\n  content: \"\\f1fa\";\n}\n.fa-eyedropper:before {\n  content: \"\\f1fb\";\n}\n.fa-paint-brush:before {\n  content: \"\\f1fc\";\n}\n.fa-birthday-cake:before {\n  content: \"\\f1fd\";\n}\n.fa-area-chart:before {\n  content: \"\\f1fe\";\n}\n.fa-pie-chart:before {\n  content: \"\\f200\";\n}\n.fa-line-chart:before {\n  content: \"\\f201\";\n}\n.fa-lastfm:before {\n  content: \"\\f202\";\n}\n.fa-lastfm-square:before {\n  content: \"\\f203\";\n}\n.fa-toggle-off:before {\n  content: \"\\f204\";\n}\n.fa-toggle-on:before {\n  content: \"\\f205\";\n}\n.fa-bicycle:before {\n  content: \"\\f206\";\n}\n.fa-bus:before {\n  content: \"\\f207\";\n}\n.fa-ioxhost:before {\n  content: \"\\f208\";\n}\n.fa-angellist:before {\n  content: \"\\f209\";\n}\n.fa-cc:before {\n  content: \"\\f20a\";\n}\n.fa-shekel:before,\n.fa-sheqel:before,\n.fa-ils:before {\n  content: \"\\f20b\";\n}\n.fa-meanpath:before {\n  content: \"\\f20c\";\n}\n.fa-buysellads:before {\n  content: \"\\f20d\";\n}\n.fa-connectdevelop:before {\n  content: \"\\f20e\";\n}\n.fa-dashcube:before {\n  content: \"\\f210\";\n}\n.fa-forumbee:before {\n  content: \"\\f211\";\n}\n.fa-leanpub:before {\n  content: \"\\f212\";\n}\n.fa-sellsy:before {\n  content: \"\\f213\";\n}\n.fa-shirtsinbulk:before {\n  content: \"\\f214\";\n}\n.fa-simplybuilt:before {\n  content: \"\\f215\";\n}\n.fa-skyatlas:before {\n  content: \"\\f216\";\n}\n.fa-cart-plus:before {\n  content: \"\\f217\";\n}\n.fa-cart-arrow-down:before {\n  content: \"\\f218\";\n}\n.fa-diamond:before {\n  content: \"\\f219\";\n}\n.fa-ship:before {\n  content: \"\\f21a\";\n}\n.fa-user-secret:before {\n  content: \"\\f21b\";\n}\n.fa-motorcycle:before {\n  content: \"\\f21c\";\n}\n.fa-street-view:before {\n  content: \"\\f21d\";\n}\n.fa-heartbeat:before {\n  content: \"\\f21e\";\n}\n.fa-venus:before {\n  content: \"\\f221\";\n}\n.fa-mars:before {\n  content: \"\\f222\";\n}\n.fa-mercury:before {\n  content: \"\\f223\";\n}\n.fa-intersex:before,\n.fa-transgender:before {\n  content: \"\\f224\";\n}\n.fa-transgender-alt:before {\n  content: \"\\f225\";\n}\n.fa-venus-double:before {\n  content: \"\\f226\";\n}\n.fa-mars-double:before {\n  content: \"\\f227\";\n}\n.fa-venus-mars:before {\n  content: \"\\f228\";\n}\n.fa-mars-stroke:before {\n  content: \"\\f229\";\n}\n.fa-mars-stroke-v:before {\n  content: \"\\f22a\";\n}\n.fa-mars-stroke-h:before {\n  content: \"\\f22b\";\n}\n.fa-neuter:before {\n  content: \"\\f22c\";\n}\n.fa-genderless:before {\n  content: \"\\f22d\";\n}\n.fa-facebook-official:before {\n  content: \"\\f230\";\n}\n.fa-pinterest-p:before {\n  content: \"\\f231\";\n}\n.fa-whatsapp:before {\n  content: \"\\f232\";\n}\n.fa-server:before {\n  content: \"\\f233\";\n}\n.fa-user-plus:before {\n  content: \"\\f234\";\n}\n.fa-user-times:before {\n  content: \"\\f235\";\n}\n.fa-hotel:before,\n.fa-bed:before {\n  content: \"\\f236\";\n}\n.fa-viacoin:before {\n  content: \"\\f237\";\n}\n.fa-train:before {\n  content: \"\\f238\";\n}\n.fa-subway:before {\n  content: \"\\f239\";\n}\n.fa-medium:before {\n  content: \"\\f23a\";\n}\n.fa-yc:before,\n.fa-y-combinator:before {\n  content: \"\\f23b\";\n}\n.fa-optin-monster:before {\n  content: \"\\f23c\";\n}\n.fa-opencart:before {\n  content: \"\\f23d\";\n}\n.fa-expeditedssl:before {\n  content: \"\\f23e\";\n}\n.fa-battery-4:before,\n.fa-battery:before,\n.fa-battery-full:before {\n  content: \"\\f240\";\n}\n.fa-battery-3:before,\n.fa-battery-three-quarters:before {\n  content: \"\\f241\";\n}\n.fa-battery-2:before,\n.fa-battery-half:before {\n  content: \"\\f242\";\n}\n.fa-battery-1:before,\n.fa-battery-quarter:before {\n  content: \"\\f243\";\n}\n.fa-battery-0:before,\n.fa-battery-empty:before {\n  content: \"\\f244\";\n}\n.fa-mouse-pointer:before {\n  content: \"\\f245\";\n}\n.fa-i-cursor:before {\n  content: \"\\f246\";\n}\n.fa-object-group:before {\n  content: \"\\f247\";\n}\n.fa-object-ungroup:before {\n  content: \"\\f248\";\n}\n.fa-sticky-note:before {\n  content: \"\\f249\";\n}\n.fa-sticky-note-o:before {\n  content: \"\\f24a\";\n}\n.fa-cc-jcb:before {\n  content: \"\\f24b\";\n}\n.fa-cc-diners-club:before {\n  content: \"\\f24c\";\n}\n.fa-clone:before {\n  content: \"\\f24d\";\n}\n.fa-balance-scale:before {\n  content: \"\\f24e\";\n}\n.fa-hourglass-o:before {\n  content: \"\\f250\";\n}\n.fa-hourglass-1:before,\n.fa-hourglass-start:before {\n  content: \"\\f251\";\n}\n.fa-hourglass-2:before,\n.fa-hourglass-half:before {\n  content: \"\\f252\";\n}\n.fa-hourglass-3:before,\n.fa-hourglass-end:before {\n  content: \"\\f253\";\n}\n.fa-hourglass:before {\n  content: \"\\f254\";\n}\n.fa-hand-grab-o:before,\n.fa-hand-rock-o:before {\n  content: \"\\f255\";\n}\n.fa-hand-stop-o:before,\n.fa-hand-paper-o:before {\n  content: \"\\f256\";\n}\n.fa-hand-scissors-o:before {\n  content: \"\\f257\";\n}\n.fa-hand-lizard-o:before {\n  content: \"\\f258\";\n}\n.fa-hand-spock-o:before {\n  content: \"\\f259\";\n}\n.fa-hand-pointer-o:before {\n  content: \"\\f25a\";\n}\n.fa-hand-peace-o:before {\n  content: \"\\f25b\";\n}\n.fa-trademark:before {\n  content: \"\\f25c\";\n}\n.fa-registered:before {\n  content: \"\\f25d\";\n}\n.fa-creative-commons:before {\n  content: \"\\f25e\";\n}\n.fa-gg:before {\n  content: \"\\f260\";\n}\n.fa-gg-circle:before {\n  content: \"\\f261\";\n}\n.fa-tripadvisor:before {\n  content: \"\\f262\";\n}\n.fa-odnoklassniki:before {\n  content: \"\\f263\";\n}\n.fa-odnoklassniki-square:before {\n  content: \"\\f264\";\n}\n.fa-get-pocket:before {\n  content: \"\\f265\";\n}\n.fa-wikipedia-w:before {\n  content: \"\\f266\";\n}\n.fa-safari:before {\n  content: \"\\f267\";\n}\n.fa-chrome:before {\n  content: \"\\f268\";\n}\n.fa-firefox:before {\n  content: \"\\f269\";\n}\n.fa-opera:before {\n  content: \"\\f26a\";\n}\n.fa-internet-explorer:before {\n  content: \"\\f26b\";\n}\n.fa-tv:before,\n.fa-television:before {\n  content: \"\\f26c\";\n}\n.fa-contao:before {\n  content: \"\\f26d\";\n}\n.fa-500px:before {\n  content: \"\\f26e\";\n}\n.fa-amazon:before {\n  content: \"\\f270\";\n}\n.fa-calendar-plus-o:before {\n  content: \"\\f271\";\n}\n.fa-calendar-minus-o:before {\n  content: \"\\f272\";\n}\n.fa-calendar-times-o:before {\n  content: \"\\f273\";\n}\n.fa-calendar-check-o:before {\n  content: \"\\f274\";\n}\n.fa-industry:before {\n  content: \"\\f275\";\n}\n.fa-map-pin:before {\n  content: \"\\f276\";\n}\n.fa-map-signs:before {\n  content: \"\\f277\";\n}\n.fa-map-o:before {\n  content: \"\\f278\";\n}\n.fa-map:before {\n  content: \"\\f279\";\n}\n.fa-commenting:before {\n  content: \"\\f27a\";\n}\n.fa-commenting-o:before {\n  content: \"\\f27b\";\n}\n.fa-houzz:before {\n  content: \"\\f27c\";\n}\n.fa-vimeo:before {\n  content: \"\\f27d\";\n}\n.fa-black-tie:before {\n  content: \"\\f27e\";\n}\n.fa-fonticons:before {\n  content: \"\\f280\";\n}\n.fa-reddit-alien:before {\n  content: \"\\f281\";\n}\n.fa-edge:before {\n  content: \"\\f282\";\n}\n.fa-credit-card-alt:before {\n  content: \"\\f283\";\n}\n.fa-codiepie:before {\n  content: \"\\f284\";\n}\n.fa-modx:before {\n  content: \"\\f285\";\n}\n.fa-fort-awesome:before {\n  content: \"\\f286\";\n}\n.fa-usb:before {\n  content: \"\\f287\";\n}\n.fa-product-hunt:before {\n  content: \"\\f288\";\n}\n.fa-mixcloud:before {\n  content: \"\\f289\";\n}\n.fa-scribd:before {\n  content: \"\\f28a\";\n}\n.fa-pause-circle:before {\n  content: \"\\f28b\";\n}\n.fa-pause-circle-o:before {\n  content: \"\\f28c\";\n}\n.fa-stop-circle:before {\n  content: \"\\f28d\";\n}\n.fa-stop-circle-o:before {\n  content: \"\\f28e\";\n}\n.fa-shopping-bag:before {\n  content: \"\\f290\";\n}\n.fa-shopping-basket:before {\n  content: \"\\f291\";\n}\n.fa-hashtag:before {\n  content: \"\\f292\";\n}\n.fa-bluetooth:before {\n  content: \"\\f293\";\n}\n.fa-bluetooth-b:before {\n  content: \"\\f294\";\n}\n.fa-percent:before {\n  content: \"\\f295\";\n}\n.fa-gitlab:before {\n  content: \"\\f296\";\n}\n.fa-wpbeginner:before {\n  content: \"\\f297\";\n}\n.fa-wpforms:before {\n  content: \"\\f298\";\n}\n.fa-envira:before {\n  content: \"\\f299\";\n}\n.fa-universal-access:before {\n  content: \"\\f29a\";\n}\n.fa-wheelchair-alt:before {\n  content: \"\\f29b\";\n}\n.fa-question-circle-o:before {\n  content: \"\\f29c\";\n}\n.fa-blind:before {\n  content: \"\\f29d\";\n}\n.fa-audio-description:before {\n  content: \"\\f29e\";\n}\n.fa-volume-control-phone:before {\n  content: \"\\f2a0\";\n}\n.fa-braille:before {\n  content: \"\\f2a1\";\n}\n.fa-assistive-listening-systems:before {\n  content: \"\\f2a2\";\n}\n.fa-asl-interpreting:before,\n.fa-american-sign-language-interpreting:before {\n  content: \"\\f2a3\";\n}\n.fa-deafness:before,\n.fa-hard-of-hearing:before,\n.fa-deaf:before {\n  content: \"\\f2a4\";\n}\n.fa-glide:before {\n  content: \"\\f2a5\";\n}\n.fa-glide-g:before {\n  content: \"\\f2a6\";\n}\n.fa-signing:before,\n.fa-sign-language:before {\n  content: \"\\f2a7\";\n}\n.fa-low-vision:before {\n  content: \"\\f2a8\";\n}\n.fa-viadeo:before {\n  content: \"\\f2a9\";\n}\n.fa-viadeo-square:before {\n  content: \"\\f2aa\";\n}\n.fa-snapchat:before {\n  content: \"\\f2ab\";\n}\n.fa-snapchat-ghost:before {\n  content: \"\\f2ac\";\n}\n.fa-snapchat-square:before {\n  content: \"\\f2ad\";\n}\n.fa-pied-piper:before {\n  content: \"\\f2ae\";\n}\n.fa-first-order:before {\n  content: \"\\f2b0\";\n}\n.fa-yoast:before {\n  content: \"\\f2b1\";\n}\n.fa-themeisle:before {\n  content: \"\\f2b2\";\n}\n.fa-google-plus-circle:before,\n.fa-google-plus-official:before {\n  content: \"\\f2b3\";\n}\n.fa-fa:before,\n.fa-font-awesome:before {\n  content: \"\\f2b4\";\n}\n.fa-handshake-o:before {\n  content: \"\\f2b5\";\n}\n.fa-envelope-open:before {\n  content: \"\\f2b6\";\n}\n.fa-envelope-open-o:before {\n  content: \"\\f2b7\";\n}\n.fa-linode:before {\n  content: \"\\f2b8\";\n}\n.fa-address-book:before {\n  content: \"\\f2b9\";\n}\n.fa-address-book-o:before {\n  content: \"\\f2ba\";\n}\n.fa-vcard:before,\n.fa-address-card:before {\n  content: \"\\f2bb\";\n}\n.fa-vcard-o:before,\n.fa-address-card-o:before {\n  content: \"\\f2bc\";\n}\n.fa-user-circle:before {\n  content: \"\\f2bd\";\n}\n.fa-user-circle-o:before {\n  content: \"\\f2be\";\n}\n.fa-user-o:before {\n  content: \"\\f2c0\";\n}\n.fa-id-badge:before {\n  content: \"\\f2c1\";\n}\n.fa-drivers-license:before,\n.fa-id-card:before {\n  content: \"\\f2c2\";\n}\n.fa-drivers-license-o:before,\n.fa-id-card-o:before {\n  content: \"\\f2c3\";\n}\n.fa-quora:before {\n  content: \"\\f2c4\";\n}\n.fa-free-code-camp:before {\n  content: \"\\f2c5\";\n}\n.fa-telegram:before {\n  content: \"\\f2c6\";\n}\n.fa-thermometer-4:before,\n.fa-thermometer:before,\n.fa-thermometer-full:before {\n  content: \"\\f2c7\";\n}\n.fa-thermometer-3:before,\n.fa-thermometer-three-quarters:before {\n  content: \"\\f2c8\";\n}\n.fa-thermometer-2:before,\n.fa-thermometer-half:before {\n  content: \"\\f2c9\";\n}\n.fa-thermometer-1:before,\n.fa-thermometer-quarter:before {\n  content: \"\\f2ca\";\n}\n.fa-thermometer-0:before,\n.fa-thermometer-empty:before {\n  content: \"\\f2cb\";\n}\n.fa-shower:before {\n  content: \"\\f2cc\";\n}\n.fa-bathtub:before,\n.fa-s15:before,\n.fa-bath:before {\n  content: \"\\f2cd\";\n}\n.fa-podcast:before {\n  content: \"\\f2ce\";\n}\n.fa-window-maximize:before {\n  content: \"\\f2d0\";\n}\n.fa-window-minimize:before {\n  content: \"\\f2d1\";\n}\n.fa-window-restore:before {\n  content: \"\\f2d2\";\n}\n.fa-times-rectangle:before,\n.fa-window-close:before {\n  content: \"\\f2d3\";\n}\n.fa-times-rectangle-o:before,\n.fa-window-close-o:before {\n  content: \"\\f2d4\";\n}\n.fa-bandcamp:before {\n  content: \"\\f2d5\";\n}\n.fa-grav:before {\n  content: \"\\f2d6\";\n}\n.fa-etsy:before {\n  content: \"\\f2d7\";\n}\n.fa-imdb:before {\n  content: \"\\f2d8\";\n}\n.fa-ravelry:before {\n  content: \"\\f2d9\";\n}\n.fa-eercast:before {\n  content: \"\\f2da\";\n}\n.fa-microchip:before {\n  content: \"\\f2db\";\n}\n.fa-snowflake-o:before {\n  content: \"\\f2dc\";\n}\n.fa-superpowers:before {\n  content: \"\\f2dd\";\n}\n.fa-wpexplorer:before {\n  content: \"\\f2de\";\n}\n.fa-meetup:before {\n  content: \"\\f2e0\";\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.sr-only-focusable:active,\n.sr-only-focusable:focus {\n  position: static;\n  width: auto;\n  height: auto;\n  margin: 0;\n  overflow: visible;\n  clip: auto;\n}\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/css/login.css",
    "content": "*{\n    font: 13px/1.5 '微软雅黑', Verdana, Helvetica, Arial, sans-serif;\n    -webkit-box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    -box-sizing: border-box;\n    padding:0;\n    margin:0;\n    list-style:none;\n    box-sizing: border-box;\n}\n\nbody,html{\n    height:100%;\n    overflow:hidden;\n}\nbody{\n    background:url(../img/login/bg.png) no-repeat center;\n    background-size: cover;\n}\na{\n    color:#27A9E3;\n    text-decoration:none;\n    cursor:pointer;\n}\n.login{\n    margin: 150px auto 0 auto;\n    min-height: 420px;\n    max-width: 420px;\n    padding: 40px;\n    background-color: #ffffff;\n    margin-left: auto;\n    margin-right: auto;\n    border-radius: 4px;\n    /* overflow-x: hidden; */\n    box-sizing: border-box;\n}\na.logo{\n    display: block;\n    height: 58px;\n    width: 167px;\n    margin: 0 auto 30px auto;\n    background-size: 167px 42px;\n}\n.message {\n    margin: 10px 0 0 -58px;\n    padding: 18px 10px 18px 60px;\n    background: #189F92;\n    position: relative;\n    color: #fff;\n    font-size: 16px;\n}\n#darkbannerwrap {\n    background: url(../img/login/aiwrap.png);\n    width: 18px;\n    height: 10px;\n    margin: 0 0 20px -58px;\n    position: relative;\n}\n\ninput[type=text],\ninput[type=file],\ninput[type=password],\ninput[type=email], select {\n    border: 1px solid #DCDEE0;\n    vertical-align: middle;\n    border-radius: 3px;\n    height: 50px;\n    padding: 0px 16px;\n    font-size: 14px;\n    color: #555555;\n    outline:none;\n    width:100%;\n}\ninput[type=text]:focus,\ninput[type=file]:focus,\ninput[type=password]:focus,\ninput[type=email]:focus, select:focus {\n    border: 1px solid #27A9E3;\n}\n\n\ninput[type=submit],\nbutton{\n    display: inline-block;\n    vertical-align: middle;\n    padding: 12px 24px;\n    margin: 0px;\n    font-size: 18px;\n    line-height: 24px;\n    text-align: center;\n    white-space: nowrap;\n    vertical-align: middle;\n    cursor: pointer;\n    color: #ffffff;\n    background-color: #189F92;\n    border-radius: 3px;\n    border: none;\n    -webkit-appearance: none;\n    outline:none;\n    width:100%;\n}\nhr.hr15 {\n    height: 15px;\n    border: none;\n    margin: 0px;\n    padding: 0px;\n    width: 100%;\n}\nhr.hr20 {\n    height: 20px;\n    border: none;\n    margin: 0px;\n    padding: 0px;\n    width: 100%;\n}\n\n.copyright{\n    font-size:14px;\n    color:rgba(255,255,255,0.85);\n    display:block;\n    position:absolute;\n    bottom:15px;\n    right:15px;\n}"
  },
  {
    "path": "open-layui-web/src/main/view/static/css/simple-line-icons/css/simple-line-icons.css",
    "content": "@font-face {\n  font-family: 'simple-line-icons';\n  src: url('../fonts/Simple-Line-Icons.eot?v=2.4.0');\n  src: url('../fonts/Simple-Line-Icons.eot?v=2.4.0#iefix') format('embedded-opentype'), url('../fonts/Simple-Line-Icons.woff2?v=2.4.0') format('woff2'), url('../fonts/Simple-Line-Icons.ttf?v=2.4.0') format('truetype'), url('../fonts/Simple-Line-Icons.woff?v=2.4.0') format('woff'), url('../fonts/Simple-Line-Icons.svg?v=2.4.0#simple-line-icons') format('svg');\n  font-weight: normal;\n  font-style: normal;\n}\n/*\n Use the following CSS code if you want to have a class per icon.\n Instead of a list of all class selectors, you can use the generic [class*=\"icon-\"] selector, but it's slower:\n*/\n.icon-user,\n.icon-people,\n.icon-user-female,\n.icon-user-follow,\n.icon-user-following,\n.icon-user-unfollow,\n.icon-login,\n.icon-logout,\n.icon-emotsmile,\n.icon-phone,\n.icon-call-end,\n.icon-call-in,\n.icon-call-out,\n.icon-map,\n.icon-location-pin,\n.icon-direction,\n.icon-directions,\n.icon-compass,\n.icon-layers,\n.icon-menu,\n.icon-list,\n.icon-options-vertical,\n.icon-options,\n.icon-arrow-down,\n.icon-arrow-left,\n.icon-arrow-right,\n.icon-arrow-up,\n.icon-arrow-up-circle,\n.icon-arrow-left-circle,\n.icon-arrow-right-circle,\n.icon-arrow-down-circle,\n.icon-check,\n.icon-clock,\n.icon-plus,\n.icon-minus,\n.icon-close,\n.icon-event,\n.icon-exclamation,\n.icon-organization,\n.icon-trophy,\n.icon-screen-smartphone,\n.icon-screen-desktop,\n.icon-plane,\n.icon-notebook,\n.icon-mustache,\n.icon-mouse,\n.icon-magnet,\n.icon-energy,\n.icon-disc,\n.icon-cursor,\n.icon-cursor-move,\n.icon-crop,\n.icon-chemistry,\n.icon-speedometer,\n.icon-shield,\n.icon-screen-tablet,\n.icon-magic-wand,\n.icon-hourglass,\n.icon-graduation,\n.icon-ghost,\n.icon-game-controller,\n.icon-fire,\n.icon-eyeglass,\n.icon-envelope-open,\n.icon-envelope-letter,\n.icon-bell,\n.icon-badge,\n.icon-anchor,\n.icon-wallet,\n.icon-vector,\n.icon-speech,\n.icon-puzzle,\n.icon-printer,\n.icon-present,\n.icon-playlist,\n.icon-pin,\n.icon-picture,\n.icon-handbag,\n.icon-globe-alt,\n.icon-globe,\n.icon-folder-alt,\n.icon-folder,\n.icon-film,\n.icon-feed,\n.icon-drop,\n.icon-drawer,\n.icon-docs,\n.icon-doc,\n.icon-diamond,\n.icon-cup,\n.icon-calculator,\n.icon-bubbles,\n.icon-briefcase,\n.icon-book-open,\n.icon-basket-loaded,\n.icon-basket,\n.icon-bag,\n.icon-action-undo,\n.icon-action-redo,\n.icon-wrench,\n.icon-umbrella,\n.icon-trash,\n.icon-tag,\n.icon-support,\n.icon-frame,\n.icon-size-fullscreen,\n.icon-size-actual,\n.icon-shuffle,\n.icon-share-alt,\n.icon-share,\n.icon-rocket,\n.icon-question,\n.icon-pie-chart,\n.icon-pencil,\n.icon-note,\n.icon-loop,\n.icon-home,\n.icon-grid,\n.icon-graph,\n.icon-microphone,\n.icon-music-tone-alt,\n.icon-music-tone,\n.icon-earphones-alt,\n.icon-earphones,\n.icon-equalizer,\n.icon-like,\n.icon-dislike,\n.icon-control-start,\n.icon-control-rewind,\n.icon-control-play,\n.icon-control-pause,\n.icon-control-forward,\n.icon-control-end,\n.icon-volume-1,\n.icon-volume-2,\n.icon-volume-off,\n.icon-calendar,\n.icon-bulb,\n.icon-chart,\n.icon-ban,\n.icon-bubble,\n.icon-camrecorder,\n.icon-camera,\n.icon-cloud-download,\n.icon-cloud-upload,\n.icon-envelope,\n.icon-eye,\n.icon-flag,\n.icon-heart,\n.icon-info,\n.icon-key,\n.icon-link,\n.icon-lock,\n.icon-lock-open,\n.icon-magnifier,\n.icon-magnifier-add,\n.icon-magnifier-remove,\n.icon-paper-clip,\n.icon-paper-plane,\n.icon-power,\n.icon-refresh,\n.icon-reload,\n.icon-settings,\n.icon-star,\n.icon-symbol-female,\n.icon-symbol-male,\n.icon-target,\n.icon-credit-card,\n.icon-paypal,\n.icon-social-tumblr,\n.icon-social-twitter,\n.icon-social-facebook,\n.icon-social-instagram,\n.icon-social-linkedin,\n.icon-social-pinterest,\n.icon-social-github,\n.icon-social-google,\n.icon-social-reddit,\n.icon-social-skype,\n.icon-social-dribbble,\n.icon-social-behance,\n.icon-social-foursqare,\n.icon-social-soundcloud,\n.icon-social-spotify,\n.icon-social-stumbleupon,\n.icon-social-youtube,\n.icon-social-dropbox,\n.icon-social-vkontakte,\n.icon-social-steam {\n  font-family: 'simple-line-icons';\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.icon-user:before {\n  content: \"\\e005\";\n}\n.icon-people:before {\n  content: \"\\e001\";\n}\n.icon-user-female:before {\n  content: \"\\e000\";\n}\n.icon-user-follow:before {\n  content: \"\\e002\";\n}\n.icon-user-following:before {\n  content: \"\\e003\";\n}\n.icon-user-unfollow:before {\n  content: \"\\e004\";\n}\n.icon-login:before {\n  content: \"\\e066\";\n}\n.icon-logout:before {\n  content: \"\\e065\";\n}\n.icon-emotsmile:before {\n  content: \"\\e021\";\n}\n.icon-phone:before {\n  content: \"\\e600\";\n}\n.icon-call-end:before {\n  content: \"\\e048\";\n}\n.icon-call-in:before {\n  content: \"\\e047\";\n}\n.icon-call-out:before {\n  content: \"\\e046\";\n}\n.icon-map:before {\n  content: \"\\e033\";\n}\n.icon-location-pin:before {\n  content: \"\\e096\";\n}\n.icon-direction:before {\n  content: \"\\e042\";\n}\n.icon-directions:before {\n  content: \"\\e041\";\n}\n.icon-compass:before {\n  content: \"\\e045\";\n}\n.icon-layers:before {\n  content: \"\\e034\";\n}\n.icon-menu:before {\n  content: \"\\e601\";\n}\n.icon-list:before {\n  content: \"\\e067\";\n}\n.icon-options-vertical:before {\n  content: \"\\e602\";\n}\n.icon-options:before {\n  content: \"\\e603\";\n}\n.icon-arrow-down:before {\n  content: \"\\e604\";\n}\n.icon-arrow-left:before {\n  content: \"\\e605\";\n}\n.icon-arrow-right:before {\n  content: \"\\e606\";\n}\n.icon-arrow-up:before {\n  content: \"\\e607\";\n}\n.icon-arrow-up-circle:before {\n  content: \"\\e078\";\n}\n.icon-arrow-left-circle:before {\n  content: \"\\e07a\";\n}\n.icon-arrow-right-circle:before {\n  content: \"\\e079\";\n}\n.icon-arrow-down-circle:before {\n  content: \"\\e07b\";\n}\n.icon-check:before {\n  content: \"\\e080\";\n}\n.icon-clock:before {\n  content: \"\\e081\";\n}\n.icon-plus:before {\n  content: \"\\e095\";\n}\n.icon-minus:before {\n  content: \"\\e615\";\n}\n.icon-close:before {\n  content: \"\\e082\";\n}\n.icon-event:before {\n  content: \"\\e619\";\n}\n.icon-exclamation:before {\n  content: \"\\e617\";\n}\n.icon-organization:before {\n  content: \"\\e616\";\n}\n.icon-trophy:before {\n  content: \"\\e006\";\n}\n.icon-screen-smartphone:before {\n  content: \"\\e010\";\n}\n.icon-screen-desktop:before {\n  content: \"\\e011\";\n}\n.icon-plane:before {\n  content: \"\\e012\";\n}\n.icon-notebook:before {\n  content: \"\\e013\";\n}\n.icon-mustache:before {\n  content: \"\\e014\";\n}\n.icon-mouse:before {\n  content: \"\\e015\";\n}\n.icon-magnet:before {\n  content: \"\\e016\";\n}\n.icon-energy:before {\n  content: \"\\e020\";\n}\n.icon-disc:before {\n  content: \"\\e022\";\n}\n.icon-cursor:before {\n  content: \"\\e06e\";\n}\n.icon-cursor-move:before {\n  content: \"\\e023\";\n}\n.icon-crop:before {\n  content: \"\\e024\";\n}\n.icon-chemistry:before {\n  content: \"\\e026\";\n}\n.icon-speedometer:before {\n  content: \"\\e007\";\n}\n.icon-shield:before {\n  content: \"\\e00e\";\n}\n.icon-screen-tablet:before {\n  content: \"\\e00f\";\n}\n.icon-magic-wand:before {\n  content: \"\\e017\";\n}\n.icon-hourglass:before {\n  content: \"\\e018\";\n}\n.icon-graduation:before {\n  content: \"\\e019\";\n}\n.icon-ghost:before {\n  content: \"\\e01a\";\n}\n.icon-game-controller:before {\n  content: \"\\e01b\";\n}\n.icon-fire:before {\n  content: \"\\e01c\";\n}\n.icon-eyeglass:before {\n  content: \"\\e01d\";\n}\n.icon-envelope-open:before {\n  content: \"\\e01e\";\n}\n.icon-envelope-letter:before {\n  content: \"\\e01f\";\n}\n.icon-bell:before {\n  content: \"\\e027\";\n}\n.icon-badge:before {\n  content: \"\\e028\";\n}\n.icon-anchor:before {\n  content: \"\\e029\";\n}\n.icon-wallet:before {\n  content: \"\\e02a\";\n}\n.icon-vector:before {\n  content: \"\\e02b\";\n}\n.icon-speech:before {\n  content: \"\\e02c\";\n}\n.icon-puzzle:before {\n  content: \"\\e02d\";\n}\n.icon-printer:before {\n  content: \"\\e02e\";\n}\n.icon-present:before {\n  content: \"\\e02f\";\n}\n.icon-playlist:before {\n  content: \"\\e030\";\n}\n.icon-pin:before {\n  content: \"\\e031\";\n}\n.icon-picture:before {\n  content: \"\\e032\";\n}\n.icon-handbag:before {\n  content: \"\\e035\";\n}\n.icon-globe-alt:before {\n  content: \"\\e036\";\n}\n.icon-globe:before {\n  content: \"\\e037\";\n}\n.icon-folder-alt:before {\n  content: \"\\e039\";\n}\n.icon-folder:before {\n  content: \"\\e089\";\n}\n.icon-film:before {\n  content: \"\\e03a\";\n}\n.icon-feed:before {\n  content: \"\\e03b\";\n}\n.icon-drop:before {\n  content: \"\\e03e\";\n}\n.icon-drawer:before {\n  content: \"\\e03f\";\n}\n.icon-docs:before {\n  content: \"\\e040\";\n}\n.icon-doc:before {\n  content: \"\\e085\";\n}\n.icon-diamond:before {\n  content: \"\\e043\";\n}\n.icon-cup:before {\n  content: \"\\e044\";\n}\n.icon-calculator:before {\n  content: \"\\e049\";\n}\n.icon-bubbles:before {\n  content: \"\\e04a\";\n}\n.icon-briefcase:before {\n  content: \"\\e04b\";\n}\n.icon-book-open:before {\n  content: \"\\e04c\";\n}\n.icon-basket-loaded:before {\n  content: \"\\e04d\";\n}\n.icon-basket:before {\n  content: \"\\e04e\";\n}\n.icon-bag:before {\n  content: \"\\e04f\";\n}\n.icon-action-undo:before {\n  content: \"\\e050\";\n}\n.icon-action-redo:before {\n  content: \"\\e051\";\n}\n.icon-wrench:before {\n  content: \"\\e052\";\n}\n.icon-umbrella:before {\n  content: \"\\e053\";\n}\n.icon-trash:before {\n  content: \"\\e054\";\n}\n.icon-tag:before {\n  content: \"\\e055\";\n}\n.icon-support:before {\n  content: \"\\e056\";\n}\n.icon-frame:before {\n  content: \"\\e038\";\n}\n.icon-size-fullscreen:before {\n  content: \"\\e057\";\n}\n.icon-size-actual:before {\n  content: \"\\e058\";\n}\n.icon-shuffle:before {\n  content: \"\\e059\";\n}\n.icon-share-alt:before {\n  content: \"\\e05a\";\n}\n.icon-share:before {\n  content: \"\\e05b\";\n}\n.icon-rocket:before {\n  content: \"\\e05c\";\n}\n.icon-question:before {\n  content: \"\\e05d\";\n}\n.icon-pie-chart:before {\n  content: \"\\e05e\";\n}\n.icon-pencil:before {\n  content: \"\\e05f\";\n}\n.icon-note:before {\n  content: \"\\e060\";\n}\n.icon-loop:before {\n  content: \"\\e064\";\n}\n.icon-home:before {\n  content: \"\\e069\";\n}\n.icon-grid:before {\n  content: \"\\e06a\";\n}\n.icon-graph:before {\n  content: \"\\e06b\";\n}\n.icon-microphone:before {\n  content: \"\\e063\";\n}\n.icon-music-tone-alt:before {\n  content: \"\\e061\";\n}\n.icon-music-tone:before {\n  content: \"\\e062\";\n}\n.icon-earphones-alt:before {\n  content: \"\\e03c\";\n}\n.icon-earphones:before {\n  content: \"\\e03d\";\n}\n.icon-equalizer:before {\n  content: \"\\e06c\";\n}\n.icon-like:before {\n  content: \"\\e068\";\n}\n.icon-dislike:before {\n  content: \"\\e06d\";\n}\n.icon-control-start:before {\n  content: \"\\e06f\";\n}\n.icon-control-rewind:before {\n  content: \"\\e070\";\n}\n.icon-control-play:before {\n  content: \"\\e071\";\n}\n.icon-control-pause:before {\n  content: \"\\e072\";\n}\n.icon-control-forward:before {\n  content: \"\\e073\";\n}\n.icon-control-end:before {\n  content: \"\\e074\";\n}\n.icon-volume-1:before {\n  content: \"\\e09f\";\n}\n.icon-volume-2:before {\n  content: \"\\e0a0\";\n}\n.icon-volume-off:before {\n  content: \"\\e0a1\";\n}\n.icon-calendar:before {\n  content: \"\\e075\";\n}\n.icon-bulb:before {\n  content: \"\\e076\";\n}\n.icon-chart:before {\n  content: \"\\e077\";\n}\n.icon-ban:before {\n  content: \"\\e07c\";\n}\n.icon-bubble:before {\n  content: \"\\e07d\";\n}\n.icon-camrecorder:before {\n  content: \"\\e07e\";\n}\n.icon-camera:before {\n  content: \"\\e07f\";\n}\n.icon-cloud-download:before {\n  content: \"\\e083\";\n}\n.icon-cloud-upload:before {\n  content: \"\\e084\";\n}\n.icon-envelope:before {\n  content: \"\\e086\";\n}\n.icon-eye:before {\n  content: \"\\e087\";\n}\n.icon-flag:before {\n  content: \"\\e088\";\n}\n.icon-heart:before {\n  content: \"\\e08a\";\n}\n.icon-info:before {\n  content: \"\\e08b\";\n}\n.icon-key:before {\n  content: \"\\e08c\";\n}\n.icon-link:before {\n  content: \"\\e08d\";\n}\n.icon-lock:before {\n  content: \"\\e08e\";\n}\n.icon-lock-open:before {\n  content: \"\\e08f\";\n}\n.icon-magnifier:before {\n  content: \"\\e090\";\n}\n.icon-magnifier-add:before {\n  content: \"\\e091\";\n}\n.icon-magnifier-remove:before {\n  content: \"\\e092\";\n}\n.icon-paper-clip:before {\n  content: \"\\e093\";\n}\n.icon-paper-plane:before {\n  content: \"\\e094\";\n}\n.icon-power:before {\n  content: \"\\e097\";\n}\n.icon-refresh:before {\n  content: \"\\e098\";\n}\n.icon-reload:before {\n  content: \"\\e099\";\n}\n.icon-settings:before {\n  content: \"\\e09a\";\n}\n.icon-star:before {\n  content: \"\\e09b\";\n}\n.icon-symbol-female:before {\n  content: \"\\e09c\";\n}\n.icon-symbol-male:before {\n  content: \"\\e09d\";\n}\n.icon-target:before {\n  content: \"\\e09e\";\n}\n.icon-credit-card:before {\n  content: \"\\e025\";\n}\n.icon-paypal:before {\n  content: \"\\e608\";\n}\n.icon-social-tumblr:before {\n  content: \"\\e00a\";\n}\n.icon-social-twitter:before {\n  content: \"\\e009\";\n}\n.icon-social-facebook:before {\n  content: \"\\e00b\";\n}\n.icon-social-instagram:before {\n  content: \"\\e609\";\n}\n.icon-social-linkedin:before {\n  content: \"\\e60a\";\n}\n.icon-social-pinterest:before {\n  content: \"\\e60b\";\n}\n.icon-social-github:before {\n  content: \"\\e60c\";\n}\n.icon-social-google:before {\n  content: \"\\e60d\";\n}\n.icon-social-reddit:before {\n  content: \"\\e60e\";\n}\n.icon-social-skype:before {\n  content: \"\\e60f\";\n}\n.icon-social-dribbble:before {\n  content: \"\\e00d\";\n}\n.icon-social-behance:before {\n  content: \"\\e610\";\n}\n.icon-social-foursqare:before {\n  content: \"\\e611\";\n}\n.icon-social-soundcloud:before {\n  content: \"\\e612\";\n}\n.icon-social-spotify:before {\n  content: \"\\e613\";\n}\n.icon-social-stumbleupon:before {\n  content: \"\\e614\";\n}\n.icon-social-youtube:before {\n  content: \"\\e008\";\n}\n.icon-social-dropbox:before {\n  content: \"\\e00c\";\n}\n.icon-social-vkontakte:before {\n  content: \"\\e618\";\n}\n.icon-social-steam:before {\n  content: \"\\e620\";\n}\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/css/style.css",
    "content": "@charset \"UTF-8\";\n/*!\n * CoreUI - Open Source Bootstrap Admin Template\n * @version v1.0.6\n * @link http://coreui.io\n * Copyright (c) 2017 creativeLabs Łukasz Holeczek\n * @license MIT\n */\n/*!\n * Bootstrap v4.0.0-beta.2 (https://getbootstrap.com)\n * Copyright 2011-2017 The Bootstrap Authors\n * Copyright 2011-2017 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n:root {\n  --blue: #20a8d8;\n  --indigo: #6610f2;\n  --purple: #6f42c1;\n  --pink: #e83e8c;\n  --red: #f86c6b;\n  --orange: #f8cb00;\n  --yellow: #ffc107;\n  --green: #4dbd74;\n  --teal: #20c997;\n  --cyan: #63c2de;\n  --white: #fff;\n  --gray: #536c79;\n  --gray-dark: #29363d;\n  --blue: #20a8d8;\n  --indigo: #6610f2;\n  --purple: #6f42c1;\n  --pink: #e83e8c;\n  --red: #f86c6b;\n  --orange: #f8cb00;\n  --yellow: #ffc107;\n  --green: #4dbd74;\n  --teal: #20c997;\n  --cyan: #63c2de;\n  --white: #fff;\n  --gray: #536c79;\n  --primary: #20a8d8;\n  --secondary: #a4b7c1;\n  --success: #4dbd74;\n  --info: #63c2de;\n  --warning: #ffc107;\n  --danger: #f86c6b;\n  --light: #f0f3f5;\n  --dark: #29363d;\n  --breakpoint-xs: 0;\n  --breakpoint-sm: 576px;\n  --breakpoint-md: 768px;\n  --breakpoint-lg: 992px;\n  --breakpoint-xl: 1200px;\n  --font-family-sans-serif: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";\n  --font-family-monospace: \"SFMono-Regular\", Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace; }\n\n@media print {\n  *,\n  *::before,\n  *::after {\n    text-shadow: none !important;\n    box-shadow: none !important; }\n  a,\n  a:visited {\n    text-decoration: underline; }\n  abbr[title]::after {\n    content: \" (\" attr(title) \")\"; }\n  pre {\n    white-space: pre-wrap !important; }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid; }\n  thead {\n    display: table-header-group; }\n  tr,\n  img {\n    page-break-inside: avoid; }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3; }\n  h2,\n  h3 {\n    page-break-after: avoid; }\n  .navbar {\n    display: none; }\n  .badge {\n    border: 1px solid #000; }\n  .table {\n    border-collapse: collapse !important; }\n  .table td,\n  .table th {\n    background-color: #fff !important; }\n  .table-bordered th,\n  .table-bordered td {\n    border: 1px solid #ddd !important; } }\n\n*,\n*::before,\n*::after {\n  box-sizing: border-box; }\n\nhtml {\n  font-family: sans-serif;\n  line-height: 1.15;\n  -webkit-text-size-adjust: 100%;\n  -ms-text-size-adjust: 100%;\n  -ms-overflow-style: scrollbar;\n  -webkit-tap-highlight-color: transparent; }\n\n@-ms-viewport {\n  width: device-width; }\n\narticle, aside, dialog, figcaption, figure, footer, header, hgroup, main, nav, section {\n  display: block; }\n\nbody {\n  margin: 0;\n  font-family: Verdana, Arial, Helvetica,-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";\n  font-size: 0.875rem;\n  font-weight: 400;\n  line-height: 1.5;\n  color: #151b1e;\n  text-align: left;\n  background-color: #e4e5e6; }\n\n[tabindex=\"-1\"]:focus {\n  outline: none !important; }\n\nhr {\n  box-sizing: content-box;\n  height: 0;\n  overflow: visible; }\n\nh1, h2, h3, h4, h5, h6 {\n  margin-top: 0;\n  margin-bottom: 0.5rem; }\n\np {\n  margin-top: 0;\n  margin-bottom: 1rem; }\n\nabbr[title],\nabbr[data-original-title] {\n  text-decoration: underline;\n  -webkit-text-decoration: underline dotted;\n  text-decoration: underline dotted;\n  cursor: help;\n  border-bottom: 0; }\n\naddress {\n  margin-bottom: 1rem;\n  font-style: normal;\n  line-height: inherit; }\n\nol,\nul,\ndl {\n  margin-top: 0;\n  margin-bottom: 1rem; }\n\nol ol,\nul ul,\nol ul,\nul ol {\n  margin-bottom: 0; }\n\ndt {\n  font-weight: 700; }\n\ndd {\n  margin-bottom: .5rem;\n  margin-left: 0; }\n\nblockquote {\n  margin: 0 0 1rem; }\n\ndfn {\n  font-style: italic; }\n\nb,\nstrong {\n  font-weight: bolder; }\n\nsmall {\n  font-size: 80%; }\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline; }\n\nsub {\n  bottom: -.25em; }\n\nsup {\n  top: -.5em; }\n\na {\n  color: #20a8d8;\n  text-decoration: none;\n  background-color: transparent;\n  -webkit-text-decoration-skip: objects; }\na:hover {\n  color: #167495;\n  text-decoration: underline; }\n\na:not([href]):not([tabindex]) {\n  color: inherit;\n  text-decoration: none; }\na:not([href]):not([tabindex]):focus, a:not([href]):not([tabindex]):hover {\n  color: inherit;\n  text-decoration: none; }\na:not([href]):not([tabindex]):focus {\n  outline: 0; }\n\npre,\ncode,\nkbd,\nsamp {\n  font-family: monospace, monospace;\n  font-size: 1em; }\n\npre {\n  margin-top: 0;\n  margin-bottom: 1rem;\n  overflow: auto;\n  -ms-overflow-style: scrollbar; }\n\nfigure {\n  margin: 0 0 1rem; }\n\nimg {\n  vertical-align: middle;\n  border-style: none; }\n\nsvg:not(:root) {\n  overflow: hidden; }\n\na,\narea,\nbutton,\n[role=\"button\"],\ninput:not([type=\"range\"]),\nlabel,\nselect,\nsummary,\ntextarea {\n  -ms-touch-action: manipulation;\n  touch-action: manipulation; }\n\ntable {\n  border-collapse: collapse; }\n\ncaption {\n  padding-top: 0.75rem;\n  padding-bottom: 0.75rem;\n  color: #536c79;\n  text-align: left;\n  caption-side: bottom; }\n\nth {\n  text-align: inherit; }\n\nlabel {\n  display: inline-block;\n  margin-bottom: .5rem; }\n\nbutton {\n  border-radius: 0; }\n\nbutton:focus {\n  outline: 1px dotted;\n  outline: 5px auto -webkit-focus-ring-color; }\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n  margin: 0;\n  font-family: inherit;\n  font-size: inherit;\n  line-height: inherit; }\n\nbutton,\ninput {\n  overflow: visible; }\n\nbutton,\nselect {\n  text-transform: none; }\n\nbutton,\nhtml [type=\"button\"],\n[type=\"reset\"],\n[type=\"submit\"] {\n  -webkit-appearance: button; }\n\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n  padding: 0;\n  border-style: none; }\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  box-sizing: border-box;\n  padding: 0; }\n\ninput[type=\"date\"],\ninput[type=\"time\"],\ninput[type=\"datetime-local\"],\ninput[type=\"month\"] {\n  -webkit-appearance: listbox; }\n\ntextarea {\n  overflow: auto;\n  resize: vertical; }\n\nfieldset {\n  min-width: 0;\n  padding: 0;\n  margin: 0;\n  border: 0; }\n\nlegend {\n  display: block;\n  width: 100%;\n  max-width: 100%;\n  padding: 0;\n  margin-bottom: .5rem;\n  font-size: 1.5rem;\n  line-height: inherit;\n  color: inherit;\n  white-space: normal; }\n\nprogress {\n  vertical-align: baseline; }\n\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n  height: auto; }\n\n[type=\"search\"] {\n  outline-offset: -2px;\n  -webkit-appearance: none; }\n\n[type=\"search\"]::-webkit-search-cancel-button,\n[type=\"search\"]::-webkit-search-decoration {\n  -webkit-appearance: none; }\n\n::-webkit-file-upload-button {\n  font: inherit;\n  -webkit-appearance: button; }\n\noutput {\n  display: inline-block; }\n\nsummary {\n  display: list-item; }\n\ntemplate {\n  display: none; }\n\n[hidden] {\n  display: none !important; }\n\nh1, h2, h3, h4, h5, h6,\n.h1, .h2, .h3, .h4, .h5, .h6 {\n  margin-bottom: 0.5rem;\n  font-family: inherit;\n  font-weight: 500;\n  line-height: 1.2;\n  color: inherit; }\n\nh1, .h1 {\n  font-size: 2.1875rem; }\n\nh2, .h2 {\n  font-size: 1.75rem; }\n\nh3, .h3 {\n  font-size: 1.53125rem; }\n\nh4, .h4 {\n  font-size: 1.3125rem; }\n\nh5, .h5 {\n  font-size: 1.09375rem; }\n\nh6, .h6 {\n  font-size: 0.875rem; }\n\n.lead {\n  font-size: 1.09375rem;\n  font-weight: 300; }\n\n.display-1 {\n  font-size: 6rem;\n  font-weight: 300;\n  line-height: 1.2; }\n\n.display-2 {\n  font-size: 5.5rem;\n  font-weight: 300;\n  line-height: 1.2; }\n\n.display-3 {\n  font-size: 4.5rem;\n  font-weight: 300;\n  line-height: 1.2; }\n\n.display-4 {\n  font-size: 3.5rem;\n  font-weight: 300;\n  line-height: 1.2; }\n\nhr {\n  margin-top: 1rem;\n  margin-bottom: 1rem;\n  border: 0;\n  border-top: 1px solid rgba(0, 0, 0, 0.1); }\n\nsmall,\n.small {\n  font-size: 80%;\n  font-weight: 400; }\n\nmark,\n.mark {\n  padding: 0.2em;\n  background-color: #fcf8e3; }\n\n.list-unstyled {\n  padding-left: 0;\n  list-style: none; }\n\n.list-inline {\n  padding-left: 0;\n  list-style: none; }\n\n.list-inline-item {\n  display: inline-block; }\n.list-inline-item:not(:last-child) {\n  margin-right: 5px; }\n\n.initialism {\n  font-size: 90%;\n  text-transform: uppercase; }\n\n.blockquote {\n  margin-bottom: 1rem;\n  font-size: 1.09375rem; }\n\n.blockquote-footer {\n  display: block;\n  font-size: 80%;\n  color: #536c79; }\n.blockquote-footer::before {\n  content: \"\\2014 \\00A0\"; }\n\n.img-fluid {\n  max-width: 100%;\n  height: auto; }\n\n.img-thumbnail {\n  padding: 0.25rem;\n  background-color: #e4e5e6;\n  border: 1px solid #ddd;\n  transition: all 0.2s ease-in-out;\n  max-width: 100%;\n  height: auto; }\n\n.figure {\n  display: inline-block; }\n\n.figure-img {\n  margin-bottom: 0.5rem;\n  line-height: 1; }\n\n.figure-caption {\n  font-size: 90%;\n  color: #536c79; }\n\ncode,\nkbd,\npre,\nsamp {\n  font-family: \"SFMono-Regular\", Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace; }\n\ncode {\n  padding: 0.2rem 0.4rem;\n  font-size: 90%;\n  color: #bd4147;\n  background-color: #f0f3f5; }\na > code {\n  padding: 0;\n  color: inherit;\n  background-color: inherit; }\n\nkbd {\n  padding: 0.2rem 0.4rem;\n  font-size: 90%;\n  color: #fff;\n  background-color: #151b1e; }\nkbd kbd {\n  padding: 0;\n  font-size: 100%;\n  font-weight: 700; }\n\npre {\n  display: block;\n  margin-top: 0;\n  margin-bottom: 1rem;\n  font-size: 90%;\n  color: #151b1e; }\npre code {\n  padding: 0;\n  font-size: inherit;\n  color: inherit;\n  background-color: transparent;\n  border-radius: 0; }\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll; }\n\n.container {\n  width: 100%;\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-right: auto;\n  margin-left: auto; }\n@media (min-width: 576px) {\n  .container {\n    max-width: 540px; } }\n@media (min-width: 768px) {\n  .container {\n    max-width: 720px; } }\n@media (min-width: 992px) {\n  .container {\n    max-width: 960px; } }\n@media (min-width: 1200px) {\n  .container {\n    max-width: 1140px; } }\n\n.container-fluid {\n  width: 100%;\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-right: auto;\n  margin-left: auto; }\n\n.row {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-wrap: wrap;\n  flex-wrap: wrap;\n  margin-right: -15px;\n  margin-left: -15px; }\n\n.no-gutters {\n  margin-right: 0;\n  margin-left: 0; }\n.no-gutters > .col,\n.no-gutters > [class*=\"col-\"] {\n  padding-right: 0;\n  padding-left: 0; }\n\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,\n.col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm,\n.col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md,\n.col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg,\n.col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl,\n.col-xl-auto {\n  position: relative;\n  width: 100%;\n  min-height: 1px;\n  padding-right: 15px;\n  padding-left: 15px; }\n\n.col {\n  -ms-flex-preferred-size: 0;\n  flex-basis: 0;\n  -ms-flex-positive: 1;\n  flex-grow: 1;\n  max-width: 100%; }\n\n.col-auto {\n  -ms-flex: 0 0 auto;\n  flex: 0 0 auto;\n  width: auto;\n  max-width: none; }\n\n.col-1 {\n  -ms-flex: 0 0 8.33333%;\n  flex: 0 0 8.33333%;\n  max-width: 8.33333%; }\n\n.col-2 {\n  -ms-flex: 0 0 16.66667%;\n  flex: 0 0 16.66667%;\n  max-width: 16.66667%; }\n\n.col-3 {\n  -ms-flex: 0 0 25%;\n  flex: 0 0 25%;\n  max-width: 25%; }\n\n.col-4 {\n  -ms-flex: 0 0 33.33333%;\n  flex: 0 0 33.33333%;\n  max-width: 33.33333%; }\n\n.col-5 {\n  -ms-flex: 0 0 41.66667%;\n  flex: 0 0 41.66667%;\n  max-width: 41.66667%; }\n\n.col-6 {\n  -ms-flex: 0 0 50%;\n  flex: 0 0 50%;\n  max-width: 50%; }\n\n.col-7 {\n  -ms-flex: 0 0 58.33333%;\n  flex: 0 0 58.33333%;\n  max-width: 58.33333%; }\n\n.col-8 {\n  -ms-flex: 0 0 66.66667%;\n  flex: 0 0 66.66667%;\n  max-width: 66.66667%; }\n\n.col-9 {\n  -ms-flex: 0 0 75%;\n  flex: 0 0 75%;\n  max-width: 75%; }\n\n.col-10 {\n  -ms-flex: 0 0 83.33333%;\n  flex: 0 0 83.33333%;\n  max-width: 83.33333%; }\n\n.col-11 {\n  -ms-flex: 0 0 91.66667%;\n  flex: 0 0 91.66667%;\n  max-width: 91.66667%; }\n\n.col-12 {\n  -ms-flex: 0 0 100%;\n  flex: 0 0 100%;\n  max-width: 100%; }\n\n.order-first {\n  -ms-flex-order: -1;\n  order: -1; }\n\n.order-1 {\n  -ms-flex-order: 1;\n  order: 1; }\n\n.order-2 {\n  -ms-flex-order: 2;\n  order: 2; }\n\n.order-3 {\n  -ms-flex-order: 3;\n  order: 3; }\n\n.order-4 {\n  -ms-flex-order: 4;\n  order: 4; }\n\n.order-5 {\n  -ms-flex-order: 5;\n  order: 5; }\n\n.order-6 {\n  -ms-flex-order: 6;\n  order: 6; }\n\n.order-7 {\n  -ms-flex-order: 7;\n  order: 7; }\n\n.order-8 {\n  -ms-flex-order: 8;\n  order: 8; }\n\n.order-9 {\n  -ms-flex-order: 9;\n  order: 9; }\n\n.order-10 {\n  -ms-flex-order: 10;\n  order: 10; }\n\n.order-11 {\n  -ms-flex-order: 11;\n  order: 11; }\n\n.order-12 {\n  -ms-flex-order: 12;\n  order: 12; }\n\n.offset-1 {\n  margin-left: 8.33333%; }\n\n.offset-2 {\n  margin-left: 16.66667%; }\n\n.offset-3 {\n  margin-left: 25%; }\n\n.offset-4 {\n  margin-left: 33.33333%; }\n\n.offset-5 {\n  margin-left: 41.66667%; }\n\n.offset-6 {\n  margin-left: 50%; }\n\n.offset-7 {\n  margin-left: 58.33333%; }\n\n.offset-8 {\n  margin-left: 66.66667%; }\n\n.offset-9 {\n  margin-left: 75%; }\n\n.offset-10 {\n  margin-left: 83.33333%; }\n\n.offset-11 {\n  margin-left: 91.66667%; }\n\n@media (min-width: 576px) {\n  .col-sm {\n    -ms-flex-preferred-size: 0;\n    flex-basis: 0;\n    -ms-flex-positive: 1;\n    flex-grow: 1;\n    max-width: 100%; }\n  .col-sm-auto {\n    -ms-flex: 0 0 auto;\n    flex: 0 0 auto;\n    width: auto;\n    max-width: none; }\n  .col-sm-1 {\n    -ms-flex: 0 0 8.33333%;\n    flex: 0 0 8.33333%;\n    max-width: 8.33333%; }\n  .col-sm-2 {\n    -ms-flex: 0 0 16.66667%;\n    flex: 0 0 16.66667%;\n    max-width: 16.66667%; }\n  .col-sm-3 {\n    -ms-flex: 0 0 25%;\n    flex: 0 0 25%;\n    max-width: 25%; }\n  .col-sm-4 {\n    -ms-flex: 0 0 33.33333%;\n    flex: 0 0 33.33333%;\n    max-width: 33.33333%; }\n  .col-sm-5 {\n    -ms-flex: 0 0 41.66667%;\n    flex: 0 0 41.66667%;\n    max-width: 41.66667%; }\n  .col-sm-6 {\n    -ms-flex: 0 0 50%;\n    flex: 0 0 50%;\n    max-width: 50%; }\n  .col-sm-7 {\n    -ms-flex: 0 0 58.33333%;\n    flex: 0 0 58.33333%;\n    max-width: 58.33333%; }\n  .col-sm-8 {\n    -ms-flex: 0 0 66.66667%;\n    flex: 0 0 66.66667%;\n    max-width: 66.66667%; }\n  .col-sm-9 {\n    -ms-flex: 0 0 75%;\n    flex: 0 0 75%;\n    max-width: 75%; }\n  .col-sm-10 {\n    -ms-flex: 0 0 83.33333%;\n    flex: 0 0 83.33333%;\n    max-width: 83.33333%; }\n  .col-sm-11 {\n    -ms-flex: 0 0 91.66667%;\n    flex: 0 0 91.66667%;\n    max-width: 91.66667%; }\n  .col-sm-12 {\n    -ms-flex: 0 0 100%;\n    flex: 0 0 100%;\n    max-width: 100%; }\n  .order-sm-first {\n    -ms-flex-order: -1;\n    order: -1; }\n  .order-sm-1 {\n    -ms-flex-order: 1;\n    order: 1; }\n  .order-sm-2 {\n    -ms-flex-order: 2;\n    order: 2; }\n  .order-sm-3 {\n    -ms-flex-order: 3;\n    order: 3; }\n  .order-sm-4 {\n    -ms-flex-order: 4;\n    order: 4; }\n  .order-sm-5 {\n    -ms-flex-order: 5;\n    order: 5; }\n  .order-sm-6 {\n    -ms-flex-order: 6;\n    order: 6; }\n  .order-sm-7 {\n    -ms-flex-order: 7;\n    order: 7; }\n  .order-sm-8 {\n    -ms-flex-order: 8;\n    order: 8; }\n  .order-sm-9 {\n    -ms-flex-order: 9;\n    order: 9; }\n  .order-sm-10 {\n    -ms-flex-order: 10;\n    order: 10; }\n  .order-sm-11 {\n    -ms-flex-order: 11;\n    order: 11; }\n  .order-sm-12 {\n    -ms-flex-order: 12;\n    order: 12; }\n  .offset-sm-0 {\n    margin-left: 0; }\n  .offset-sm-1 {\n    margin-left: 8.33333%; }\n  .offset-sm-2 {\n    margin-left: 16.66667%; }\n  .offset-sm-3 {\n    margin-left: 25%; }\n  .offset-sm-4 {\n    margin-left: 33.33333%; }\n  .offset-sm-5 {\n    margin-left: 41.66667%; }\n  .offset-sm-6 {\n    margin-left: 50%; }\n  .offset-sm-7 {\n    margin-left: 58.33333%; }\n  .offset-sm-8 {\n    margin-left: 66.66667%; }\n  .offset-sm-9 {\n    margin-left: 75%; }\n  .offset-sm-10 {\n    margin-left: 83.33333%; }\n  .offset-sm-11 {\n    margin-left: 91.66667%; } }\n\n@media (min-width: 768px) {\n  .col-md {\n    -ms-flex-preferred-size: 0;\n    flex-basis: 0;\n    -ms-flex-positive: 1;\n    flex-grow: 1;\n    max-width: 100%; }\n  .col-md-auto {\n    -ms-flex: 0 0 auto;\n    flex: 0 0 auto;\n    width: auto;\n    max-width: none; }\n  .col-md-1 {\n    -ms-flex: 0 0 8.33333%;\n    flex: 0 0 8.33333%;\n    max-width: 8.33333%; }\n  .col-md-2 {\n    -ms-flex: 0 0 16.66667%;\n    flex: 0 0 16.66667%;\n    max-width: 16.66667%; }\n  .col-md-3 {\n    -ms-flex: 0 0 25%;\n    flex: 0 0 25%;\n    max-width: 25%; }\n  .col-md-4 {\n    -ms-flex: 0 0 33.33333%;\n    flex: 0 0 33.33333%;\n    max-width: 33.33333%; }\n  .col-md-5 {\n    -ms-flex: 0 0 41.66667%;\n    flex: 0 0 41.66667%;\n    max-width: 41.66667%; }\n  .col-md-6 {\n    -ms-flex: 0 0 50%;\n    flex: 0 0 50%;\n    max-width: 50%; }\n  .col-md-7 {\n    -ms-flex: 0 0 58.33333%;\n    flex: 0 0 58.33333%;\n    max-width: 58.33333%; }\n  .col-md-8 {\n    -ms-flex: 0 0 66.66667%;\n    flex: 0 0 66.66667%;\n    max-width: 66.66667%; }\n  .col-md-9 {\n    -ms-flex: 0 0 75%;\n    flex: 0 0 75%;\n    max-width: 75%; }\n  .col-md-10 {\n    -ms-flex: 0 0 83.33333%;\n    flex: 0 0 83.33333%;\n    max-width: 83.33333%; }\n  .col-md-11 {\n    -ms-flex: 0 0 91.66667%;\n    flex: 0 0 91.66667%;\n    max-width: 91.66667%; }\n  .col-md-12 {\n    -ms-flex: 0 0 100%;\n    flex: 0 0 100%;\n    max-width: 100%; }\n  .order-md-first {\n    -ms-flex-order: -1;\n    order: -1; }\n  .order-md-1 {\n    -ms-flex-order: 1;\n    order: 1; }\n  .order-md-2 {\n    -ms-flex-order: 2;\n    order: 2; }\n  .order-md-3 {\n    -ms-flex-order: 3;\n    order: 3; }\n  .order-md-4 {\n    -ms-flex-order: 4;\n    order: 4; }\n  .order-md-5 {\n    -ms-flex-order: 5;\n    order: 5; }\n  .order-md-6 {\n    -ms-flex-order: 6;\n    order: 6; }\n  .order-md-7 {\n    -ms-flex-order: 7;\n    order: 7; }\n  .order-md-8 {\n    -ms-flex-order: 8;\n    order: 8; }\n  .order-md-9 {\n    -ms-flex-order: 9;\n    order: 9; }\n  .order-md-10 {\n    -ms-flex-order: 10;\n    order: 10; }\n  .order-md-11 {\n    -ms-flex-order: 11;\n    order: 11; }\n  .order-md-12 {\n    -ms-flex-order: 12;\n    order: 12; }\n  .offset-md-0 {\n    margin-left: 0; }\n  .offset-md-1 {\n    margin-left: 8.33333%; }\n  .offset-md-2 {\n    margin-left: 16.66667%; }\n  .offset-md-3 {\n    margin-left: 25%; }\n  .offset-md-4 {\n    margin-left: 33.33333%; }\n  .offset-md-5 {\n    margin-left: 41.66667%; }\n  .offset-md-6 {\n    margin-left: 50%; }\n  .offset-md-7 {\n    margin-left: 58.33333%; }\n  .offset-md-8 {\n    margin-left: 66.66667%; }\n  .offset-md-9 {\n    margin-left: 75%; }\n  .offset-md-10 {\n    margin-left: 83.33333%; }\n  .offset-md-11 {\n    margin-left: 91.66667%; } }\n\n@media (min-width: 992px) {\n  .col-lg {\n    -ms-flex-preferred-size: 0;\n    flex-basis: 0;\n    -ms-flex-positive: 1;\n    flex-grow: 1;\n    max-width: 100%; }\n  .col-lg-auto {\n    -ms-flex: 0 0 auto;\n    flex: 0 0 auto;\n    width: auto;\n    max-width: none; }\n  .col-lg-1 {\n    -ms-flex: 0 0 8.33333%;\n    flex: 0 0 8.33333%;\n    max-width: 8.33333%; }\n  .col-lg-2 {\n    -ms-flex: 0 0 16.66667%;\n    flex: 0 0 16.66667%;\n    max-width: 16.66667%; }\n  .col-lg-3 {\n    -ms-flex: 0 0 25%;\n    flex: 0 0 25%;\n    max-width: 25%; }\n  .col-lg-4 {\n    -ms-flex: 0 0 33.33333%;\n    flex: 0 0 33.33333%;\n    max-width: 33.33333%; }\n  .col-lg-5 {\n    -ms-flex: 0 0 41.66667%;\n    flex: 0 0 41.66667%;\n    max-width: 41.66667%; }\n  .col-lg-6 {\n    -ms-flex: 0 0 50%;\n    flex: 0 0 50%;\n    max-width: 50%; }\n  .col-lg-7 {\n    -ms-flex: 0 0 58.33333%;\n    flex: 0 0 58.33333%;\n    max-width: 58.33333%; }\n  .col-lg-8 {\n    -ms-flex: 0 0 66.66667%;\n    flex: 0 0 66.66667%;\n    max-width: 66.66667%; }\n  .col-lg-9 {\n    -ms-flex: 0 0 75%;\n    flex: 0 0 75%;\n    max-width: 75%; }\n  .col-lg-10 {\n    -ms-flex: 0 0 83.33333%;\n    flex: 0 0 83.33333%;\n    max-width: 83.33333%; }\n  .col-lg-11 {\n    -ms-flex: 0 0 91.66667%;\n    flex: 0 0 91.66667%;\n    max-width: 91.66667%; }\n  .col-lg-12 {\n    -ms-flex: 0 0 100%;\n    flex: 0 0 100%;\n    max-width: 100%; }\n  .order-lg-first {\n    -ms-flex-order: -1;\n    order: -1; }\n  .order-lg-1 {\n    -ms-flex-order: 1;\n    order: 1; }\n  .order-lg-2 {\n    -ms-flex-order: 2;\n    order: 2; }\n  .order-lg-3 {\n    -ms-flex-order: 3;\n    order: 3; }\n  .order-lg-4 {\n    -ms-flex-order: 4;\n    order: 4; }\n  .order-lg-5 {\n    -ms-flex-order: 5;\n    order: 5; }\n  .order-lg-6 {\n    -ms-flex-order: 6;\n    order: 6; }\n  .order-lg-7 {\n    -ms-flex-order: 7;\n    order: 7; }\n  .order-lg-8 {\n    -ms-flex-order: 8;\n    order: 8; }\n  .order-lg-9 {\n    -ms-flex-order: 9;\n    order: 9; }\n  .order-lg-10 {\n    -ms-flex-order: 10;\n    order: 10; }\n  .order-lg-11 {\n    -ms-flex-order: 11;\n    order: 11; }\n  .order-lg-12 {\n    -ms-flex-order: 12;\n    order: 12; }\n  .offset-lg-0 {\n    margin-left: 0; }\n  .offset-lg-1 {\n    margin-left: 8.33333%; }\n  .offset-lg-2 {\n    margin-left: 16.66667%; }\n  .offset-lg-3 {\n    margin-left: 25%; }\n  .offset-lg-4 {\n    margin-left: 33.33333%; }\n  .offset-lg-5 {\n    margin-left: 41.66667%; }\n  .offset-lg-6 {\n    margin-left: 50%; }\n  .offset-lg-7 {\n    margin-left: 58.33333%; }\n  .offset-lg-8 {\n    margin-left: 66.66667%; }\n  .offset-lg-9 {\n    margin-left: 75%; }\n  .offset-lg-10 {\n    margin-left: 83.33333%; }\n  .offset-lg-11 {\n    margin-left: 91.66667%; } }\n\n@media (min-width: 1200px) {\n  .col-xl {\n    -ms-flex-preferred-size: 0;\n    flex-basis: 0;\n    -ms-flex-positive: 1;\n    flex-grow: 1;\n    max-width: 100%; }\n  .col-xl-auto {\n    -ms-flex: 0 0 auto;\n    flex: 0 0 auto;\n    width: auto;\n    max-width: none; }\n  .col-xl-1 {\n    -ms-flex: 0 0 8.33333%;\n    flex: 0 0 8.33333%;\n    max-width: 8.33333%; }\n  .col-xl-2 {\n    -ms-flex: 0 0 16.66667%;\n    flex: 0 0 16.66667%;\n    max-width: 16.66667%; }\n  .col-xl-3 {\n    -ms-flex: 0 0 25%;\n    flex: 0 0 25%;\n    max-width: 25%; }\n  .col-xl-4 {\n    -ms-flex: 0 0 33.33333%;\n    flex: 0 0 33.33333%;\n    max-width: 33.33333%; }\n  .col-xl-5 {\n    -ms-flex: 0 0 41.66667%;\n    flex: 0 0 41.66667%;\n    max-width: 41.66667%; }\n  .col-xl-6 {\n    -ms-flex: 0 0 50%;\n    flex: 0 0 50%;\n    max-width: 50%; }\n  .col-xl-7 {\n    -ms-flex: 0 0 58.33333%;\n    flex: 0 0 58.33333%;\n    max-width: 58.33333%; }\n  .col-xl-8 {\n    -ms-flex: 0 0 66.66667%;\n    flex: 0 0 66.66667%;\n    max-width: 66.66667%; }\n  .col-xl-9 {\n    -ms-flex: 0 0 75%;\n    flex: 0 0 75%;\n    max-width: 75%; }\n  .col-xl-10 {\n    -ms-flex: 0 0 83.33333%;\n    flex: 0 0 83.33333%;\n    max-width: 83.33333%; }\n  .col-xl-11 {\n    -ms-flex: 0 0 91.66667%;\n    flex: 0 0 91.66667%;\n    max-width: 91.66667%; }\n  .col-xl-12 {\n    -ms-flex: 0 0 100%;\n    flex: 0 0 100%;\n    max-width: 100%; }\n  .order-xl-first {\n    -ms-flex-order: -1;\n    order: -1; }\n  .order-xl-1 {\n    -ms-flex-order: 1;\n    order: 1; }\n  .order-xl-2 {\n    -ms-flex-order: 2;\n    order: 2; }\n  .order-xl-3 {\n    -ms-flex-order: 3;\n    order: 3; }\n  .order-xl-4 {\n    -ms-flex-order: 4;\n    order: 4; }\n  .order-xl-5 {\n    -ms-flex-order: 5;\n    order: 5; }\n  .order-xl-6 {\n    -ms-flex-order: 6;\n    order: 6; }\n  .order-xl-7 {\n    -ms-flex-order: 7;\n    order: 7; }\n  .order-xl-8 {\n    -ms-flex-order: 8;\n    order: 8; }\n  .order-xl-9 {\n    -ms-flex-order: 9;\n    order: 9; }\n  .order-xl-10 {\n    -ms-flex-order: 10;\n    order: 10; }\n  .order-xl-11 {\n    -ms-flex-order: 11;\n    order: 11; }\n  .order-xl-12 {\n    -ms-flex-order: 12;\n    order: 12; }\n  .offset-xl-0 {\n    margin-left: 0; }\n  .offset-xl-1 {\n    margin-left: 8.33333%; }\n  .offset-xl-2 {\n    margin-left: 16.66667%; }\n  .offset-xl-3 {\n    margin-left: 25%; }\n  .offset-xl-4 {\n    margin-left: 33.33333%; }\n  .offset-xl-5 {\n    margin-left: 41.66667%; }\n  .offset-xl-6 {\n    margin-left: 50%; }\n  .offset-xl-7 {\n    margin-left: 58.33333%; }\n  .offset-xl-8 {\n    margin-left: 66.66667%; }\n  .offset-xl-9 {\n    margin-left: 75%; }\n  .offset-xl-10 {\n    margin-left: 83.33333%; }\n  .offset-xl-11 {\n    margin-left: 91.66667%; } }\n\n.table {\n  width: 100%;\n  max-width: 100%;\n  margin-bottom: 1rem;\n  background-color: transparent; }\n.table th,\n.table td {\n  padding: 0.75rem;\n  vertical-align: top;\n  border-top: 1px solid #c2cfd6; }\n.table thead th {\n  vertical-align: bottom;\n  border-bottom: 2px solid #c2cfd6; }\n.table tbody + tbody {\n  border-top: 2px solid #c2cfd6; }\n.table .table {\n  background-color: #e4e5e6; }\n\n.table-sm th,\n.table-sm td {\n  padding: 0.3rem; }\n\n.table-bordered {\n  border: 1px solid #c2cfd6; }\n.table-bordered th,\n.table-bordered td {\n  border: 1px solid #c2cfd6; }\n.table-bordered thead th,\n.table-bordered thead td {\n  border-bottom-width: 2px; }\n\n.table-striped tbody tr:nth-of-type(odd) {\n  background-color: rgba(0, 0, 0, 0.05); }\n\n.table-hover tbody tr:hover {\n  background-color: rgba(0, 0, 0, 0.075); }\n\n.table-primary,\n.table-primary > th,\n.table-primary > td {\n  background-color: #c1e7f4; }\n\n.table-hover .table-primary:hover {\n  background-color: #abdff0; }\n.table-hover .table-primary:hover > td,\n.table-hover .table-primary:hover > th {\n  background-color: #abdff0; }\n\n.table-secondary,\n.table-secondary > th,\n.table-secondary > td {\n  background-color: #e6ebee; }\n\n.table-hover .table-secondary:hover {\n  background-color: #d7dfe4; }\n.table-hover .table-secondary:hover > td,\n.table-hover .table-secondary:hover > th {\n  background-color: #d7dfe4; }\n\n.table-success,\n.table-success > th,\n.table-success > td {\n  background-color: #cdedd8; }\n\n.table-hover .table-success:hover {\n  background-color: #bae6c9; }\n.table-hover .table-success:hover > td,\n.table-hover .table-success:hover > th {\n  background-color: #bae6c9; }\n\n.table-info,\n.table-info > th,\n.table-info > td {\n  background-color: #d3eef6; }\n\n.table-hover .table-info:hover {\n  background-color: #bee6f2; }\n.table-hover .table-info:hover > td,\n.table-hover .table-info:hover > th {\n  background-color: #bee6f2; }\n\n.table-warning,\n.table-warning > th,\n.table-warning > td {\n  background-color: #ffeeba; }\n\n.table-hover .table-warning:hover {\n  background-color: #ffe8a1; }\n.table-hover .table-warning:hover > td,\n.table-hover .table-warning:hover > th {\n  background-color: #ffe8a1; }\n\n.table-danger,\n.table-danger > th,\n.table-danger > td {\n  background-color: #fdd6d6; }\n\n.table-hover .table-danger:hover {\n  background-color: #fcbebe; }\n.table-hover .table-danger:hover > td,\n.table-hover .table-danger:hover > th {\n  background-color: #fcbebe; }\n\n.table-light,\n.table-light > th,\n.table-light > td {\n  background-color: #fbfcfc; }\n\n.table-hover .table-light:hover {\n  background-color: #ecf1f1; }\n.table-hover .table-light:hover > td,\n.table-hover .table-light:hover > th {\n  background-color: #ecf1f1; }\n\n.table-dark,\n.table-dark > th,\n.table-dark > td {\n  background-color: #c3c7c9; }\n\n.table-hover .table-dark:hover {\n  background-color: #b6babd; }\n.table-hover .table-dark:hover > td,\n.table-hover .table-dark:hover > th {\n  background-color: #b6babd; }\n\n.table-active,\n.table-active > th,\n.table-active > td {\n  background-color: rgba(0, 0, 0, 0.075); }\n\n.table-hover .table-active:hover {\n  background-color: rgba(0, 0, 0, 0.075); }\n.table-hover .table-active:hover > td,\n.table-hover .table-active:hover > th {\n  background-color: rgba(0, 0, 0, 0.075); }\n\n.table .thead-dark th {\n  color: #e4e5e6;\n  background-color: #151b1e;\n  border-color: #252f35; }\n\n.table .thead-light th {\n  color: #3e515b;\n  background-color: #c2cfd6;\n  border-color: #c2cfd6; }\n\n.table-dark {\n  color: #e4e5e6;\n  background-color: #151b1e; }\n.table-dark th,\n.table-dark td,\n.table-dark thead th {\n  border-color: #252f35; }\n.table-dark.table-bordered {\n  border: 0; }\n.table-dark.table-striped tbody tr:nth-of-type(odd) {\n  background-color: rgba(255, 255, 255, 0.05); }\n.table-dark.table-hover tbody tr:hover {\n  background-color: rgba(255, 255, 255, 0.075); }\n\n@media (max-width: 575px) {\n  .table-responsive-sm {\n    display: block;\n    width: 100%;\n    overflow-x: auto;\n    -webkit-overflow-scrolling: touch;\n    -ms-overflow-style: -ms-autohiding-scrollbar; }\n  .table-responsive-sm.table-bordered {\n    border: 0; } }\n\n@media (max-width: 767px) {\n  .table-responsive-md {\n    display: block;\n    width: 100%;\n    overflow-x: auto;\n    -webkit-overflow-scrolling: touch;\n    -ms-overflow-style: -ms-autohiding-scrollbar; }\n  .table-responsive-md.table-bordered {\n    border: 0; } }\n\n@media (max-width: 991px) {\n  .table-responsive-lg {\n    display: block;\n    width: 100%;\n    overflow-x: auto;\n    -webkit-overflow-scrolling: touch;\n    -ms-overflow-style: -ms-autohiding-scrollbar; }\n  .table-responsive-lg.table-bordered {\n    border: 0; } }\n\n@media (max-width: 1199px) {\n  .table-responsive-xl {\n    display: block;\n    width: 100%;\n    overflow-x: auto;\n    -webkit-overflow-scrolling: touch;\n    -ms-overflow-style: -ms-autohiding-scrollbar; }\n  .table-responsive-xl.table-bordered {\n    border: 0; } }\n\n.table-responsive {\n  display: block;\n  width: 100%;\n  overflow-x: auto;\n  -webkit-overflow-scrolling: touch;\n  -ms-overflow-style: -ms-autohiding-scrollbar; }\n.table-responsive.table-bordered {\n  border: 0; }\n\n.form-control {\n  display: block;\n  width: 100%;\n  padding: 0.375rem 0.75rem;\n  font-size: 0.875rem;\n  line-height: 1.5;\n  color: #3e515b;\n  background-color: #fff;\n  background-image: none;\n  background-clip: padding-box;\n  border: 1px solid #c2cfd6;\n  border-radius: 0;\n  transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; }\n.form-control::-ms-expand {\n  background-color: transparent;\n  border: 0; }\n.form-control:focus {\n  color: #3e515b;\n  background-color: #fff;\n  border-color: #8ad4ee;\n  outline: none;\n  box-shadow: 0 0 0 0.2rem rgba(32, 168, 216, 0.25); }\n.form-control::-webkit-input-placeholder {\n  color: #536c79;\n  opacity: 1; }\n.form-control:-ms-input-placeholder {\n  color: #536c79;\n  opacity: 1; }\n.form-control::-ms-input-placeholder {\n  color: #536c79;\n  opacity: 1; }\n.form-control::placeholder {\n  color: #536c79;\n  opacity: 1; }\n.form-control:disabled, .form-control[readonly] {\n  background-color: #c2cfd6;\n  opacity: 1; }\n\nselect.form-control:not([size]):not([multiple]) {\n  height: calc(2.0625rem + 2px); }\n\nselect.form-control:focus::-ms-value {\n  color: #3e515b;\n  background-color: #fff; }\n\n.form-control-file,\n.form-control-range {\n  display: block; }\n\n.col-form-label {\n  padding-top: calc(0.375rem + 1px);\n  padding-bottom: calc(0.375rem + 1px);\n  margin-bottom: 0;\n  line-height: 1.5; }\n\n.col-form-label-lg {\n  padding-top: calc(0.5rem + 1px);\n  padding-bottom: calc(0.5rem + 1px);\n  font-size: 1.09375rem;\n  line-height: 1.5; }\n\n.col-form-label-sm {\n  padding-top: calc(0.25rem + 1px);\n  padding-bottom: calc(0.25rem + 1px);\n  font-size: 0.76563rem;\n  line-height: 1.5; }\n\n.col-form-legend {\n  padding-top: 0.375rem;\n  padding-bottom: 0.375rem;\n  margin-bottom: 0;\n  font-size: 0.875rem; }\n\n.form-control-plaintext {\n  padding-top: 0.375rem;\n  padding-bottom: 0.375rem;\n  margin-bottom: 0;\n  line-height: 1.5;\n  background-color: transparent;\n  border: solid transparent;\n  border-width: 1px 0; }\n.form-control-plaintext.form-control-sm, .input-group-sm > .form-control-plaintext.form-control,\n.input-group-sm > .form-control-plaintext.input-group-addon,\n.input-group-sm > .input-group-btn > .form-control-plaintext.btn, .form-control-plaintext.form-control-lg, .input-group-lg > .form-control-plaintext.form-control,\n.input-group-lg > .form-control-plaintext.input-group-addon,\n.input-group-lg > .input-group-btn > .form-control-plaintext.btn {\n  padding-right: 0;\n  padding-left: 0; }\n\n.form-control-sm, .input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n  padding: 0.25rem 0.5rem;\n  font-size: 0.76563rem;\n  line-height: 1.5; }\n\nselect.form-control-sm:not([size]):not([multiple]), .input-group-sm > select.form-control:not([size]):not([multiple]),\n.input-group-sm > select.input-group-addon:not([size]):not([multiple]),\n.input-group-sm > .input-group-btn > select.btn:not([size]):not([multiple]) {\n  height: calc(1.64844rem + 2px); }\n\n.form-control-lg, .input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n  padding: 0.5rem 1rem;\n  font-size: 1.09375rem;\n  line-height: 1.5; }\n\nselect.form-control-lg:not([size]):not([multiple]), .input-group-lg > select.form-control:not([size]):not([multiple]),\n.input-group-lg > select.input-group-addon:not([size]):not([multiple]),\n.input-group-lg > .input-group-btn > select.btn:not([size]):not([multiple]) {\n  height: calc(2.64063rem + 2px); }\n\n.form-group {\n  margin-bottom: 1rem; }\n\n.form-text {\n  display: block;\n  margin-top: 0.25rem; }\n\n.form-row {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-wrap: wrap;\n  flex-wrap: wrap;\n  margin-right: -5px;\n  margin-left: -5px; }\n.form-row > .col,\n.form-row > [class*=\"col-\"] {\n  padding-right: 5px;\n  padding-left: 5px; }\n\n.form-check {\n  position: relative;\n  display: block;\n  margin-bottom: 0.5rem; }\n.form-check.disabled .form-check-label {\n  color: #536c79; }\n\n.form-check-label {\n  padding-left: 1.25rem;\n  margin-bottom: 0; }\n\n.form-check-input {\n  position: absolute;\n  margin-top: 0.25rem;\n  margin-left: -1.25rem; }\n\n.form-check-inline {\n  display: inline-block;\n  margin-right: 0.75rem; }\n.form-check-inline .form-check-label {\n  vertical-align: middle; }\n\n.valid-feedback {\n  display: none;\n  margin-top: .25rem;\n  font-size: .875rem;\n  color: #4dbd74; }\n\n.valid-tooltip {\n  position: absolute;\n  top: 100%;\n  z-index: 5;\n  display: none;\n  width: 250px;\n  padding: .5rem;\n  margin-top: .1rem;\n  font-size: .875rem;\n  line-height: 1;\n  color: #fff;\n  background-color: rgba(77, 189, 116, 0.8);\n  border-radius: .2rem; }\n\n.was-validated .form-control:valid, .form-control.is-valid, .was-validated\n.custom-select:valid,\n.custom-select.is-valid {\n  border-color: #4dbd74; }\n.was-validated .form-control:valid:focus, .form-control.is-valid:focus, .was-validated\n.custom-select:valid:focus,\n.custom-select.is-valid:focus {\n  box-shadow: 0 0 0 0.2rem rgba(77, 189, 116, 0.25); }\n.was-validated .form-control:valid ~ .valid-feedback,\n.was-validated .form-control:valid ~ .valid-tooltip, .form-control.is-valid ~ .valid-feedback,\n.form-control.is-valid ~ .valid-tooltip, .was-validated\n.custom-select:valid ~ .valid-feedback,\n.was-validated\n.custom-select:valid ~ .valid-tooltip,\n.custom-select.is-valid ~ .valid-feedback,\n.custom-select.is-valid ~ .valid-tooltip {\n  display: block; }\n\n.was-validated .form-check-input:valid + .form-check-label, .form-check-input.is-valid + .form-check-label {\n  color: #4dbd74; }\n\n.was-validated .custom-control-input:valid ~ .custom-control-indicator, .custom-control-input.is-valid ~ .custom-control-indicator {\n  background-color: rgba(77, 189, 116, 0.25); }\n\n.was-validated .custom-control-input:valid ~ .custom-control-description, .custom-control-input.is-valid ~ .custom-control-description {\n  color: #4dbd74; }\n\n.was-validated .custom-file-input:valid ~ .custom-file-control, .custom-file-input.is-valid ~ .custom-file-control {\n  border-color: #4dbd74; }\n.was-validated .custom-file-input:valid ~ .custom-file-control::before, .custom-file-input.is-valid ~ .custom-file-control::before {\n  border-color: inherit; }\n\n.was-validated .custom-file-input:valid:focus, .custom-file-input.is-valid:focus {\n  box-shadow: 0 0 0 0.2rem rgba(77, 189, 116, 0.25); }\n\n.invalid-feedback {\n  display: none;\n  margin-top: .25rem;\n  font-size: .875rem;\n  color: #f86c6b; }\n\n.invalid-tooltip {\n  position: absolute;\n  top: 100%;\n  z-index: 5;\n  display: none;\n  width: 250px;\n  padding: .5rem;\n  margin-top: .1rem;\n  font-size: .875rem;\n  line-height: 1;\n  color: #fff;\n  background-color: rgba(248, 108, 107, 0.8);\n  border-radius: .2rem; }\n\n.was-validated .form-control:invalid, .form-control.is-invalid, .was-validated\n.custom-select:invalid,\n.custom-select.is-invalid {\n  border-color: #f86c6b; }\n.was-validated .form-control:invalid:focus, .form-control.is-invalid:focus, .was-validated\n.custom-select:invalid:focus,\n.custom-select.is-invalid:focus {\n  box-shadow: 0 0 0 0.2rem rgba(248, 108, 107, 0.25); }\n.was-validated .form-control:invalid ~ .invalid-feedback,\n.was-validated .form-control:invalid ~ .invalid-tooltip, .form-control.is-invalid ~ .invalid-feedback,\n.form-control.is-invalid ~ .invalid-tooltip, .was-validated\n.custom-select:invalid ~ .invalid-feedback,\n.was-validated\n.custom-select:invalid ~ .invalid-tooltip,\n.custom-select.is-invalid ~ .invalid-feedback,\n.custom-select.is-invalid ~ .invalid-tooltip {\n  display: block; }\n\n.was-validated .form-check-input:invalid + .form-check-label, .form-check-input.is-invalid + .form-check-label {\n  color: #f86c6b; }\n\n.was-validated .custom-control-input:invalid ~ .custom-control-indicator, .custom-control-input.is-invalid ~ .custom-control-indicator {\n  background-color: rgba(248, 108, 107, 0.25); }\n\n.was-validated .custom-control-input:invalid ~ .custom-control-description, .custom-control-input.is-invalid ~ .custom-control-description {\n  color: #f86c6b; }\n\n.was-validated .custom-file-input:invalid ~ .custom-file-control, .custom-file-input.is-invalid ~ .custom-file-control {\n  border-color: #f86c6b; }\n.was-validated .custom-file-input:invalid ~ .custom-file-control::before, .custom-file-input.is-invalid ~ .custom-file-control::before {\n  border-color: inherit; }\n\n.was-validated .custom-file-input:invalid:focus, .custom-file-input.is-invalid:focus {\n  box-shadow: 0 0 0 0.2rem rgba(248, 108, 107, 0.25); }\n\n.form-inline {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-flow: row wrap;\n  flex-flow: row wrap;\n  -ms-flex-align: center;\n  align-items: center; }\n.form-inline .form-check {\n  width: 100%; }\n@media (min-width: 576px) {\n  .form-inline label {\n    display: -ms-flexbox;\n    display: flex;\n    -ms-flex-align: center;\n    align-items: center;\n    -ms-flex-pack: center;\n    justify-content: center;\n    margin-bottom: 0; }\n  .form-inline .form-group {\n    display: -ms-flexbox;\n    display: flex;\n    -ms-flex: 0 0 auto;\n    flex: 0 0 auto;\n    -ms-flex-flow: row wrap;\n    flex-flow: row wrap;\n    -ms-flex-align: center;\n    align-items: center;\n    margin-bottom: 0; }\n  .form-inline .form-control {\n    display: inline-block;\n    width: auto;\n    vertical-align: middle; }\n  .form-inline .form-control-plaintext {\n    display: inline-block; }\n  .form-inline .input-group {\n    width: auto; }\n  .form-inline .form-check {\n    display: -ms-flexbox;\n    display: flex;\n    -ms-flex-align: center;\n    align-items: center;\n    -ms-flex-pack: center;\n    justify-content: center;\n    width: auto;\n    margin-top: 0;\n    margin-bottom: 0; }\n  .form-inline .form-check-label {\n    padding-left: 0; }\n  .form-inline .form-check-input {\n    position: relative;\n    margin-top: 0;\n    margin-right: 0.25rem;\n    margin-left: 0; }\n  .form-inline .custom-control {\n    display: -ms-flexbox;\n    display: flex;\n    -ms-flex-align: center;\n    align-items: center;\n    -ms-flex-pack: center;\n    justify-content: center;\n    padding-left: 0; }\n  .form-inline .custom-control-indicator {\n    position: static;\n    display: inline-block;\n    margin-right: 0.25rem;\n    vertical-align: text-bottom; }\n  .form-inline .has-feedback .form-control-feedback {\n    top: 0; } }\n\n.btn {\n  display: inline-block;\n  font-weight: 400;\n  text-align: center;\n  white-space: nowrap;\n  vertical-align: middle;\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n  border: 1px solid transparent;\n  padding: 0.375rem 0.75rem;\n  font-size: 0.875rem;\n  line-height: 1.5;\n  transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; }\n.btn:focus, .btn:hover {\n  text-decoration: none; }\n.btn:focus, .btn.focus {\n  outline: 0;\n  box-shadow: 0 0 0 0.2rem rgba(32, 168, 216, 0.25); }\n.btn.disabled, .btn:disabled {\n  opacity: .65; }\n.btn:not([disabled]):not(.disabled):active, .btn:not([disabled]):not(.disabled).active {\n  background-image: none; }\n\na.btn.disabled,\nfieldset[disabled] a.btn {\n  pointer-events: none; }\n\n.btn-primary {\n  color: #fff;\n  background-color: #20a8d8;\n  border-color: #20a8d8; }\n.btn-primary:hover {\n  color: #fff;\n  background-color: #1b8eb7;\n  border-color: #1985ac; }\n.btn-primary:focus, .btn-primary.focus {\n  box-shadow: 0 0 0 0.2rem rgba(32, 168, 216, 0.5); }\n.btn-primary.disabled, .btn-primary:disabled {\n  background-color: #20a8d8;\n  border-color: #20a8d8; }\n.btn-primary:not([disabled]):not(.disabled):active, .btn-primary:not([disabled]):not(.disabled).active,\n.show > .btn-primary.dropdown-toggle {\n  color: #fff;\n  background-color: #1985ac;\n  border-color: #187da0;\n  box-shadow: 0 0 0 0.2rem rgba(32, 168, 216, 0.5); }\n\n.btn-secondary {\n  color: #111;\n  background-color: #a4b7c1;\n  border-color: #a4b7c1; }\n.btn-secondary:hover {\n  color: #111;\n  background-color: #8da5b2;\n  border-color: #869fac; }\n.btn-secondary:focus, .btn-secondary.focus {\n  box-shadow: 0 0 0 0.2rem rgba(164, 183, 193, 0.5); }\n.btn-secondary.disabled, .btn-secondary:disabled {\n  background-color: #a4b7c1;\n  border-color: #a4b7c1; }\n.btn-secondary:not([disabled]):not(.disabled):active, .btn-secondary:not([disabled]):not(.disabled).active,\n.show > .btn-secondary.dropdown-toggle {\n  color: #111;\n  background-color: #869fac;\n  border-color: #7e99a7;\n  box-shadow: 0 0 0 0.2rem rgba(164, 183, 193, 0.5); }\n\n.btn-success {\n  color: #fff;\n  background-color: #4dbd74;\n  border-color: #4dbd74; }\n.btn-success:hover {\n  color: #fff;\n  background-color: #3ea662;\n  border-color: #3a9d5d; }\n.btn-success:focus, .btn-success.focus {\n  box-shadow: 0 0 0 0.2rem rgba(77, 189, 116, 0.5); }\n.btn-success.disabled, .btn-success:disabled {\n  background-color: #4dbd74;\n  border-color: #4dbd74; }\n.btn-success:not([disabled]):not(.disabled):active, .btn-success:not([disabled]):not(.disabled).active,\n.show > .btn-success.dropdown-toggle {\n  color: #fff;\n  background-color: #3a9d5d;\n  border-color: #379457;\n  box-shadow: 0 0 0 0.2rem rgba(77, 189, 116, 0.5); }\n\n.btn-info {\n  color: #111;\n  background-color: #63c2de;\n  border-color: #63c2de; }\n.btn-info:hover {\n  color: #111;\n  background-color: #43b6d7;\n  border-color: #39b2d5; }\n.btn-info:focus, .btn-info.focus {\n  box-shadow: 0 0 0 0.2rem rgba(99, 194, 222, 0.5); }\n.btn-info.disabled, .btn-info:disabled {\n  background-color: #63c2de;\n  border-color: #63c2de; }\n.btn-info:not([disabled]):not(.disabled):active, .btn-info:not([disabled]):not(.disabled).active,\n.show > .btn-info.dropdown-toggle {\n  color: #fff;\n  background-color: #39b2d5;\n  border-color: #2eadd3;\n  box-shadow: 0 0 0 0.2rem rgba(99, 194, 222, 0.5); }\n\n.btn-warning {\n  color: #111;\n  background-color: #ffc107;\n  border-color: #ffc107; }\n.btn-warning:hover {\n  color: #111;\n  background-color: #e0a800;\n  border-color: #d39e00; }\n.btn-warning:focus, .btn-warning.focus {\n  box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); }\n.btn-warning.disabled, .btn-warning:disabled {\n  background-color: #ffc107;\n  border-color: #ffc107; }\n.btn-warning:not([disabled]):not(.disabled):active, .btn-warning:not([disabled]):not(.disabled).active,\n.show > .btn-warning.dropdown-toggle {\n  color: #111;\n  background-color: #d39e00;\n  border-color: #c69500;\n  box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); }\n\n.btn-danger {\n  color: #fff;\n  background-color: #f86c6b;\n  border-color: #f86c6b; }\n.btn-danger:hover {\n  color: #fff;\n  background-color: #f64846;\n  border-color: #f63c3a; }\n.btn-danger:focus, .btn-danger.focus {\n  box-shadow: 0 0 0 0.2rem rgba(248, 108, 107, 0.5); }\n.btn-danger.disabled, .btn-danger:disabled {\n  background-color: #f86c6b;\n  border-color: #f86c6b; }\n.btn-danger:not([disabled]):not(.disabled):active, .btn-danger:not([disabled]):not(.disabled).active,\n.show > .btn-danger.dropdown-toggle {\n  color: #fff;\n  background-color: #f63c3a;\n  border-color: #f5302e;\n  box-shadow: 0 0 0 0.2rem rgba(248, 108, 107, 0.5); }\n\n.btn-light {\n  color: #111;\n  background-color: #f0f3f5;\n  border-color: #f0f3f5; }\n.btn-light:hover {\n  color: #111;\n  background-color: #d9e1e6;\n  border-color: #d1dbe1; }\n.btn-light:focus, .btn-light.focus {\n  box-shadow: 0 0 0 0.2rem rgba(240, 243, 245, 0.5); }\n.btn-light.disabled, .btn-light:disabled {\n  background-color: #f0f3f5;\n  border-color: #f0f3f5; }\n.btn-light:not([disabled]):not(.disabled):active, .btn-light:not([disabled]):not(.disabled).active,\n.show > .btn-light.dropdown-toggle {\n  color: #111;\n  background-color: #d1dbe1;\n  border-color: #cad4dc;\n  box-shadow: 0 0 0 0.2rem rgba(240, 243, 245, 0.5); }\n\n.btn-dark {\n  color: #fff;\n  background-color: #29363d;\n  border-color: #29363d; }\n.btn-dark:hover {\n  color: #fff;\n  background-color: #1a2226;\n  border-color: #151b1f; }\n.btn-dark:focus, .btn-dark.focus {\n  box-shadow: 0 0 0 0.2rem rgba(41, 54, 61, 0.5); }\n.btn-dark.disabled, .btn-dark:disabled {\n  background-color: #29363d;\n  border-color: #29363d; }\n.btn-dark:not([disabled]):not(.disabled):active, .btn-dark:not([disabled]):not(.disabled).active,\n.show > .btn-dark.dropdown-toggle {\n  color: #fff;\n  background-color: #151b1f;\n  border-color: #0f1417;\n  box-shadow: 0 0 0 0.2rem rgba(41, 54, 61, 0.5); }\n\n.btn-outline-primary {\n  color: #20a8d8;\n  background-color: transparent;\n  background-image: none;\n  border-color: #20a8d8; }\n.btn-outline-primary:hover {\n  color: #fff;\n  background-color: #20a8d8;\n  border-color: #20a8d8; }\n.btn-outline-primary:focus, .btn-outline-primary.focus {\n  box-shadow: 0 0 0 0.2rem rgba(32, 168, 216, 0.5); }\n.btn-outline-primary.disabled, .btn-outline-primary:disabled {\n  color: #20a8d8;\n  background-color: transparent; }\n.btn-outline-primary:not([disabled]):not(.disabled):active, .btn-outline-primary:not([disabled]):not(.disabled).active,\n.show > .btn-outline-primary.dropdown-toggle {\n  color: #fff;\n  background-color: #20a8d8;\n  border-color: #20a8d8;\n  box-shadow: 0 0 0 0.2rem rgba(32, 168, 216, 0.5); }\n\n.btn-outline-secondary {\n  color: #a4b7c1;\n  background-color: transparent;\n  background-image: none;\n  border-color: #a4b7c1; }\n.btn-outline-secondary:hover {\n  color: #fff;\n  background-color: #a4b7c1;\n  border-color: #a4b7c1; }\n.btn-outline-secondary:focus, .btn-outline-secondary.focus {\n  box-shadow: 0 0 0 0.2rem rgba(164, 183, 193, 0.5); }\n.btn-outline-secondary.disabled, .btn-outline-secondary:disabled {\n  color: #a4b7c1;\n  background-color: transparent; }\n.btn-outline-secondary:not([disabled]):not(.disabled):active, .btn-outline-secondary:not([disabled]):not(.disabled).active,\n.show > .btn-outline-secondary.dropdown-toggle {\n  color: #fff;\n  background-color: #a4b7c1;\n  border-color: #a4b7c1;\n  box-shadow: 0 0 0 0.2rem rgba(164, 183, 193, 0.5); }\n\n.btn-outline-success {\n  color: #4dbd74;\n  background-color: transparent;\n  background-image: none;\n  border-color: #4dbd74; }\n.btn-outline-success:hover {\n  color: #fff;\n  background-color: #4dbd74;\n  border-color: #4dbd74; }\n.btn-outline-success:focus, .btn-outline-success.focus {\n  box-shadow: 0 0 0 0.2rem rgba(77, 189, 116, 0.5); }\n.btn-outline-success.disabled, .btn-outline-success:disabled {\n  color: #4dbd74;\n  background-color: transparent; }\n.btn-outline-success:not([disabled]):not(.disabled):active, .btn-outline-success:not([disabled]):not(.disabled).active,\n.show > .btn-outline-success.dropdown-toggle {\n  color: #fff;\n  background-color: #4dbd74;\n  border-color: #4dbd74;\n  box-shadow: 0 0 0 0.2rem rgba(77, 189, 116, 0.5); }\n\n.btn-outline-info {\n  color: #63c2de;\n  background-color: transparent;\n  background-image: none;\n  border-color: #63c2de; }\n.btn-outline-info:hover {\n  color: #fff;\n  background-color: #63c2de;\n  border-color: #63c2de; }\n.btn-outline-info:focus, .btn-outline-info.focus {\n  box-shadow: 0 0 0 0.2rem rgba(99, 194, 222, 0.5); }\n.btn-outline-info.disabled, .btn-outline-info:disabled {\n  color: #63c2de;\n  background-color: transparent; }\n.btn-outline-info:not([disabled]):not(.disabled):active, .btn-outline-info:not([disabled]):not(.disabled).active,\n.show > .btn-outline-info.dropdown-toggle {\n  color: #fff;\n  background-color: #63c2de;\n  border-color: #63c2de;\n  box-shadow: 0 0 0 0.2rem rgba(99, 194, 222, 0.5); }\n\n.btn-outline-warning {\n  color: #ffc107;\n  background-color: transparent;\n  background-image: none;\n  border-color: #ffc107; }\n.btn-outline-warning:hover {\n  color: #fff;\n  background-color: #ffc107;\n  border-color: #ffc107; }\n.btn-outline-warning:focus, .btn-outline-warning.focus {\n  box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); }\n.btn-outline-warning.disabled, .btn-outline-warning:disabled {\n  color: #ffc107;\n  background-color: transparent; }\n.btn-outline-warning:not([disabled]):not(.disabled):active, .btn-outline-warning:not([disabled]):not(.disabled).active,\n.show > .btn-outline-warning.dropdown-toggle {\n  color: #fff;\n  background-color: #ffc107;\n  border-color: #ffc107;\n  box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); }\n\n.btn-outline-danger {\n  color: #f86c6b;\n  background-color: transparent;\n  background-image: none;\n  border-color: #f86c6b; }\n.btn-outline-danger:hover {\n  color: #fff;\n  background-color: #f86c6b;\n  border-color: #f86c6b; }\n.btn-outline-danger:focus, .btn-outline-danger.focus {\n  box-shadow: 0 0 0 0.2rem rgba(248, 108, 107, 0.5); }\n.btn-outline-danger.disabled, .btn-outline-danger:disabled {\n  color: #f86c6b;\n  background-color: transparent; }\n.btn-outline-danger:not([disabled]):not(.disabled):active, .btn-outline-danger:not([disabled]):not(.disabled).active,\n.show > .btn-outline-danger.dropdown-toggle {\n  color: #fff;\n  background-color: #f86c6b;\n  border-color: #f86c6b;\n  box-shadow: 0 0 0 0.2rem rgba(248, 108, 107, 0.5); }\n\n.btn-outline-light {\n  color: #f0f3f5;\n  background-color: transparent;\n  background-image: none;\n  border-color: #f0f3f5; }\n.btn-outline-light:hover {\n  color: #151b1e;\n  background-color: #f0f3f5;\n  border-color: #f0f3f5; }\n.btn-outline-light:focus, .btn-outline-light.focus {\n  box-shadow: 0 0 0 0.2rem rgba(240, 243, 245, 0.5); }\n.btn-outline-light.disabled, .btn-outline-light:disabled {\n  color: #f0f3f5;\n  background-color: transparent; }\n.btn-outline-light:not([disabled]):not(.disabled):active, .btn-outline-light:not([disabled]):not(.disabled).active,\n.show > .btn-outline-light.dropdown-toggle {\n  color: #151b1e;\n  background-color: #f0f3f5;\n  border-color: #f0f3f5;\n  box-shadow: 0 0 0 0.2rem rgba(240, 243, 245, 0.5); }\n\n.btn-outline-dark {\n  color: #29363d;\n  background-color: transparent;\n  background-image: none;\n  border-color: #29363d; }\n.btn-outline-dark:hover {\n  color: #fff;\n  background-color: #29363d;\n  border-color: #29363d; }\n.btn-outline-dark:focus, .btn-outline-dark.focus {\n  box-shadow: 0 0 0 0.2rem rgba(41, 54, 61, 0.5); }\n.btn-outline-dark.disabled, .btn-outline-dark:disabled {\n  color: #29363d;\n  background-color: transparent; }\n.btn-outline-dark:not([disabled]):not(.disabled):active, .btn-outline-dark:not([disabled]):not(.disabled).active,\n.show > .btn-outline-dark.dropdown-toggle {\n  color: #fff;\n  background-color: #29363d;\n  border-color: #29363d;\n  box-shadow: 0 0 0 0.2rem rgba(41, 54, 61, 0.5); }\n\n.btn-link {\n  font-weight: 400;\n  color: #20a8d8;\n  background-color: transparent; }\n.btn-link:hover {\n  color: #167495;\n  text-decoration: underline;\n  background-color: transparent;\n  border-color: transparent; }\n.btn-link:focus, .btn-link.focus {\n  border-color: transparent;\n  box-shadow: none; }\n.btn-link:disabled, .btn-link.disabled {\n  color: #536c79; }\n\n.btn-lg, .btn-group-lg > .btn {\n  padding: 0.5rem 1rem;\n  font-size: 1.09375rem;\n  line-height: 1.5; }\n\n.btn-sm, .btn-group-sm > .btn {\n  padding: 0.25rem 0.5rem;\n  font-size: 0.76563rem;\n  line-height: 1.5; }\n\n.btn-block {\n  display: block;\n  width: 100%; }\n\n.btn-block + .btn-block {\n  margin-top: 0.5rem; }\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%; }\n\n.fade {\n  opacity: 0;\n  transition: opacity 0.15s linear; }\n.fade.show {\n  opacity: 1; }\n\n.collapse {\n  display: none; }\n.collapse.show {\n  display: block; }\n\ntr.collapse.show {\n  display: table-row; }\n\ntbody.collapse.show {\n  display: table-row-group; }\n\n.collapsing {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  transition: height 0.35s ease; }\n\n.dropup,\n.dropdown {\n  position: relative; }\n\n.dropdown-toggle::after {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  margin-left: 0.255em;\n  vertical-align: 0.255em;\n  content: \"\";\n  border-top: 0.3em solid;\n  border-right: 0.3em solid transparent;\n  border-bottom: 0;\n  border-left: 0.3em solid transparent; }\n\n.dropdown-toggle:empty::after {\n  margin-left: 0; }\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: 10rem;\n  padding: 0 0;\n  margin: 0.125rem 0 0;\n  font-size: 0.875rem;\n  color: #151b1e;\n  text-align: left;\n  list-style: none;\n  background-color: #fff;\n  background-clip: padding-box;\n  border: 1px solid #c2cfd6; }\n\n.dropup .dropdown-menu {\n  margin-top: 0;\n  margin-bottom: 0.125rem; }\n\n.dropup .dropdown-toggle::after {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  margin-left: 0.255em;\n  vertical-align: 0.255em;\n  content: \"\";\n  border-top: 0;\n  border-right: 0.3em solid transparent;\n  border-bottom: 0.3em solid;\n  border-left: 0.3em solid transparent; }\n\n.dropup .dropdown-toggle:empty::after {\n  margin-left: 0; }\n\n.dropdown-divider {\n  height: 0;\n  margin: 0.5rem 0;\n  overflow: hidden;\n  border-top: 1px solid #f0f3f5; }\n\n.dropdown-item {\n  display: block;\n  width: 100%;\n  padding: 0.25rem 1.5rem;\n  clear: both;\n  font-weight: 400;\n  color: #151b1e;\n  text-align: inherit;\n  white-space: nowrap;\n  background: none;\n  border: 0; }\n.dropdown-item:focus, .dropdown-item:hover {\n  color: #0b0e0f;\n  text-decoration: none;\n  background-color: #f0f3f5; }\n.dropdown-item.active, .dropdown-item:active {\n  color: #fff;\n  text-decoration: none;\n  background-color: #20a8d8; }\n.dropdown-item.disabled, .dropdown-item:disabled {\n  color: #536c79;\n  background-color: transparent; }\n\n.dropdown-menu.show {\n  display: block; }\n\n.dropdown-header {\n  display: block;\n  padding: 0 1.5rem;\n  margin-bottom: 0;\n  font-size: 0.76563rem;\n  color: #536c79;\n  white-space: nowrap; }\n\n.btn-group,\n.btn-group-vertical {\n  position: relative;\n  display: -ms-inline-flexbox;\n  display: inline-flex;\n  vertical-align: middle; }\n.btn-group > .btn,\n.btn-group-vertical > .btn {\n  position: relative;\n  -ms-flex: 0 1 auto;\n  flex: 0 1 auto; }\n.btn-group > .btn:hover,\n.btn-group-vertical > .btn:hover {\n  z-index: 2; }\n.btn-group > .btn:focus, .btn-group > .btn:active, .btn-group > .btn.active,\n.btn-group-vertical > .btn:focus,\n.btn-group-vertical > .btn:active,\n.btn-group-vertical > .btn.active {\n  z-index: 2; }\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.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-left: -1px; }\n\n.btn-toolbar {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-wrap: wrap;\n  flex-wrap: wrap;\n  -ms-flex-pack: start;\n  justify-content: flex-start; }\n.btn-toolbar .input-group {\n  width: auto; }\n\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n  border-radius: 0; }\n\n.btn-group > .btn:first-child {\n  margin-left: 0; }\n\n.btn-group > .btn-group {\n  float: left; }\n\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n  border-radius: 0; }\n\n.btn + .dropdown-toggle-split {\n  padding-right: 0.5625rem;\n  padding-left: 0.5625rem; }\n.btn + .dropdown-toggle-split::after {\n  margin-left: 0; }\n\n.btn-sm + .dropdown-toggle-split, .btn-group-sm > .btn + .dropdown-toggle-split {\n  padding-right: 0.375rem;\n  padding-left: 0.375rem; }\n\n.btn-lg + .dropdown-toggle-split, .btn-group-lg > .btn + .dropdown-toggle-split {\n  padding-right: 0.75rem;\n  padding-left: 0.75rem; }\n\n.btn-group-vertical {\n  -ms-flex-direction: column;\n  flex-direction: column;\n  -ms-flex-align: start;\n  align-items: flex-start;\n  -ms-flex-pack: center;\n  justify-content: center; }\n.btn-group-vertical .btn,\n.btn-group-vertical .btn-group {\n  width: 100%; }\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.btn-group-vertical > .btn:not(:first-child):not(:last-child) {\n  border-radius: 0; }\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n  border-radius: 0; }\n\n[data-toggle=\"buttons\"] > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn input[type=\"checkbox\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"checkbox\"] {\n  position: absolute;\n  clip: rect(0, 0, 0, 0);\n  pointer-events: none; }\n\n.input-group {\n  position: relative;\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-align: stretch;\n  align-items: stretch;\n  width: 100%; }\n.input-group .form-control {\n  position: relative;\n  z-index: 2;\n  -ms-flex: 1 1 auto;\n  flex: 1 1 auto;\n  width: 1%;\n  margin-bottom: 0; }\n.input-group .form-control:focus, .input-group .form-control:active, .input-group .form-control:hover {\n  z-index: 3; }\n\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-align: center;\n  align-items: center; }\n\n.input-group-addon,\n.input-group-btn {\n  white-space: nowrap; }\n\n.input-group-addon {\n  padding: 0.375rem 0.75rem;\n  margin-bottom: 0;\n  font-size: 0.875rem;\n  font-weight: 400;\n  line-height: 1.5;\n  color: #3e515b;\n  text-align: center;\n  background-color: #f0f3f5;\n  border: 1px solid #c2cfd6; }\n.input-group-addon.form-control-sm,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .input-group-addon.btn {\n  padding: 0.25rem 0.5rem;\n  font-size: 0.76563rem; }\n.input-group-addon.form-control-lg,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .input-group-addon.btn {\n  padding: 0.5rem 1rem;\n  font-size: 1.09375rem; }\n.input-group-addon input[type=\"radio\"],\n.input-group-addon input[type=\"checkbox\"] {\n  margin-top: 0; }\n\n.input-group-addon:not(:last-child) {\n  border-right: 0; }\n\n.form-control + .input-group-addon:not(:first-child) {\n  border-left: 0; }\n\n.input-group-btn {\n  position: relative;\n  -ms-flex-align: stretch;\n  align-items: stretch;\n  font-size: 0;\n  white-space: nowrap; }\n.input-group-btn > .btn {\n  position: relative; }\n.input-group-btn > .btn + .btn {\n  margin-left: -1px; }\n.input-group-btn > .btn:focus, .input-group-btn > .btn:active, .input-group-btn > .btn:hover {\n  z-index: 3; }\n.input-group-btn:first-child > .btn + .btn {\n  margin-left: 0; }\n.input-group-btn:not(:last-child) > .btn,\n.input-group-btn:not(:last-child) > .btn-group {\n  margin-right: -1px; }\n.input-group-btn:not(:first-child) > .btn,\n.input-group-btn:not(:first-child) > .btn-group {\n  z-index: 2;\n  margin-left: 0; }\n.input-group-btn:not(:first-child) > .btn:first-child,\n.input-group-btn:not(:first-child) > .btn-group:first-child {\n  margin-left: -1px; }\n.input-group-btn:not(:first-child) > .btn:focus, .input-group-btn:not(:first-child) > .btn:active, .input-group-btn:not(:first-child) > .btn:hover,\n.input-group-btn:not(:first-child) > .btn-group:focus,\n.input-group-btn:not(:first-child) > .btn-group:active,\n.input-group-btn:not(:first-child) > .btn-group:hover {\n  z-index: 3; }\n\n.custom-control {\n  position: relative;\n  display: -ms-inline-flexbox;\n  display: inline-flex;\n  min-height: 1.5rem;\n  padding-left: 1.5rem;\n  margin-right: 1rem; }\n\n.custom-control-input {\n  position: absolute;\n  z-index: -1;\n  opacity: 0; }\n.custom-control-input:checked ~ .custom-control-indicator {\n  color: #fff;\n  background-color: #20a8d8; }\n.custom-control-input:focus ~ .custom-control-indicator {\n  box-shadow: 0 0 0 1px #e4e5e6, 0 0 0 0.2rem rgba(32, 168, 216, 0.25); }\n.custom-control-input:active ~ .custom-control-indicator {\n  color: #fff;\n  background-color: #b6e4f4; }\n.custom-control-input:disabled ~ .custom-control-indicator {\n  background-color: #c2cfd6; }\n.custom-control-input:disabled ~ .custom-control-description {\n  color: #536c79; }\n\n.custom-control-indicator {\n  position: absolute;\n  top: 0.25rem;\n  left: 0;\n  display: block;\n  width: 1rem;\n  height: 1rem;\n  pointer-events: none;\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n  background-color: #ddd;\n  background-repeat: no-repeat;\n  background-position: center center;\n  background-size: 50% 50%; }\n\n.custom-checkbox .custom-control-input:checked ~ .custom-control-indicator {\n  background-image: url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E\"); }\n\n.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-indicator {\n  background-color: #20a8d8;\n  background-image: url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='%23fff' d='M0 2h4'/%3E%3C/svg%3E\"); }\n\n.custom-radio .custom-control-indicator {\n  border-radius: 50%; }\n\n.custom-radio .custom-control-input:checked ~ .custom-control-indicator {\n  background-image: url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E\"); }\n\n.custom-controls-stacked {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-direction: column;\n  flex-direction: column; }\n.custom-controls-stacked .custom-control {\n  margin-bottom: 0.25rem; }\n.custom-controls-stacked .custom-control + .custom-control {\n  margin-left: 0; }\n\n.custom-select {\n  display: inline-block;\n  max-width: 100%;\n  height: calc(2.0625rem + 2px);\n  padding: 0.375rem 1.75rem 0.375rem 0.75rem;\n  line-height: 1.5;\n  color: #3e515b;\n  vertical-align: middle;\n  background: #fff url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='%23333' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E\") no-repeat right 0.75rem center;\n  background-size: 8px 10px;\n  border: 1px solid #c2cfd6;\n  border-radius: 0;\n  -webkit-appearance: none;\n  -moz-appearance: none;\n  appearance: none; }\n.custom-select:focus {\n  border-color: #8ad4ee;\n  outline: none; }\n.custom-select:focus::-ms-value {\n  color: #3e515b;\n  background-color: #fff; }\n.custom-select[multiple] {\n  height: auto;\n  background-image: none; }\n.custom-select:disabled {\n  color: #536c79;\n  background-color: #c2cfd6; }\n.custom-select::-ms-expand {\n  opacity: 0; }\n\n.custom-select-sm {\n  height: calc(1.64844rem + 2px);\n  padding-top: 0.375rem;\n  padding-bottom: 0.375rem;\n  font-size: 75%; }\n\n.custom-file {\n  position: relative;\n  display: inline-block;\n  max-width: 100%;\n  height: calc(2.0625rem + 2px);\n  margin-bottom: 0; }\n\n.custom-file-input {\n  min-width: 14rem;\n  max-width: 100%;\n  height: calc(2.0625rem + 2px);\n  margin: 0;\n  opacity: 0; }\n.custom-file-input:focus ~ .custom-file-control {\n  box-shadow: 0 0 0 0.075rem #fff, 0 0 0 0.2rem #20a8d8; }\n\n.custom-file-control {\n  position: absolute;\n  top: 0;\n  right: 0;\n  left: 0;\n  z-index: 5;\n  height: calc(2.0625rem + 2px);\n  padding: 0.375rem 0.75rem;\n  line-height: 1.5;\n  color: #3e515b;\n  pointer-events: none;\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n  background-color: #fff;\n  border: 1px solid #c2cfd6; }\n.custom-file-control:lang(en):empty::after {\n  content: \"Choose file...\"; }\n.custom-file-control::before {\n  position: absolute;\n  top: -1px;\n  right: -1px;\n  bottom: -1px;\n  z-index: 6;\n  display: block;\n  height: calc(2.0625rem + 2px);\n  padding: 0.375rem 0.75rem;\n  line-height: 1.5;\n  color: #3e515b;\n  background-color: #f0f3f5;\n  border: 1px solid #c2cfd6; }\n.custom-file-control:lang(en)::before {\n  content: \"Browse\"; }\n\n.nav {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-wrap: wrap;\n  flex-wrap: wrap;\n  padding-left: 0;\n  margin-bottom: 0;\n  list-style: none; }\n\n.nav-link, .navbar .dropdown-toggle {\n  display: block;\n  padding: 0.5rem 1rem; }\n.nav-link:focus, .navbar .dropdown-toggle:focus, .nav-link:hover, .navbar .dropdown-toggle:hover {\n  text-decoration: none; }\n.nav-link.disabled, .navbar .disabled.dropdown-toggle {\n  color: #536c79; }\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd; }\n.nav-tabs .nav-item {\n  margin-bottom: -1px; }\n.nav-tabs .nav-link, .nav-tabs .navbar .dropdown-toggle, .navbar .nav-tabs .dropdown-toggle {\n  border: 1px solid transparent; }\n.nav-tabs .nav-link:focus, .nav-tabs .navbar .dropdown-toggle:focus, .navbar .nav-tabs .dropdown-toggle:focus, .nav-tabs .nav-link:hover, .nav-tabs .navbar .dropdown-toggle:hover, .navbar .nav-tabs .dropdown-toggle:hover {\n  border-color: #c2cfd6 #c2cfd6 #ddd; }\n.nav-tabs .nav-link.disabled, .nav-tabs .navbar .disabled.dropdown-toggle, .navbar .nav-tabs .disabled.dropdown-toggle {\n  color: #536c79;\n  background-color: transparent;\n  border-color: transparent; }\n.nav-tabs .nav-link.active, .nav-tabs .navbar .active.dropdown-toggle, .navbar .nav-tabs .active.dropdown-toggle,\n.nav-tabs .nav-item.show .nav-link,\n.nav-tabs .nav-item.show .navbar .dropdown-toggle, .navbar\n.nav-tabs .nav-item.show .dropdown-toggle {\n  color: #3e515b;\n  background-color: #e4e5e6;\n  border-color: #ddd #ddd #e4e5e6; }\n.nav-tabs .dropdown-menu {\n  margin-top: -1px; }\n\n.nav-pills .nav-link.active, .nav-pills .navbar .active.dropdown-toggle, .navbar .nav-pills .active.dropdown-toggle,\n.nav-pills .show > .nav-link,\n.nav-pills .navbar .show > .dropdown-toggle, .navbar\n.nav-pills .show > .dropdown-toggle {\n  color: #fff;\n  background-color: #20a8d8; }\n\n.nav-fill .nav-item {\n  -ms-flex: 1 1 auto;\n  flex: 1 1 auto;\n  text-align: center; }\n\n.nav-justified .nav-item {\n  -ms-flex-preferred-size: 0;\n  flex-basis: 0;\n  -ms-flex-positive: 1;\n  flex-grow: 1;\n  text-align: center; }\n\n.tab-content > .tab-pane {\n  display: none; }\n\n.tab-content > .active {\n  display: block; }\n\n.navbar {\n  position: relative;\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-wrap: wrap;\n  flex-wrap: wrap;\n  -ms-flex-align: center;\n  align-items: center;\n  -ms-flex-pack: justify;\n  justify-content: space-between;\n  padding: 0.5rem 1rem; }\n.navbar > .container,\n.navbar > .container-fluid {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-wrap: wrap;\n  flex-wrap: wrap;\n  -ms-flex-align: center;\n  align-items: center;\n  -ms-flex-pack: justify;\n  justify-content: space-between; }\n\n.navbar-brand {\n  display: inline-block;\n  padding-top: 0.33594rem;\n  padding-bottom: 0.33594rem;\n  margin-right: 1rem;\n  font-size: 1.09375rem;\n  line-height: inherit;\n  white-space: nowrap; }\n.navbar-brand:focus, .navbar-brand:hover {\n  text-decoration: none; }\n\n.navbar-nav {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-direction: column;\n  flex-direction: column;\n  padding-left: 0;\n  margin-bottom: 0;\n  list-style: none; }\n.navbar-nav .nav-link, .navbar-nav .navbar .dropdown-toggle, .navbar .navbar-nav .dropdown-toggle {\n  padding-right: 0;\n  padding-left: 0; }\n.navbar-nav .dropdown-menu {\n  position: static;\n  float: none; }\n\n.navbar-text {\n  display: inline-block;\n  padding-top: 0.5rem;\n  padding-bottom: 0.5rem; }\n\n.navbar-collapse {\n  -ms-flex-preferred-size: 100%;\n  flex-basis: 100%;\n  -ms-flex-positive: 1;\n  flex-grow: 1;\n  -ms-flex-align: center;\n  align-items: center; }\n\n.navbar-toggler {\n  padding: 0.25rem 0.75rem;\n  font-size: 1.09375rem;\n  line-height: 1;\n  background: transparent;\n  border: 1px solid transparent; }\n.navbar-toggler:focus, .navbar-toggler:hover {\n  text-decoration: none; }\n\n.navbar-toggler-icon {\n  display: inline-block;\n  width: 1.5em;\n  height: 1.5em;\n  vertical-align: middle;\n  content: \"\";\n  background: no-repeat center center;\n  background-size: 100% 100%; }\n\n@media (max-width: 575px) {\n  .navbar-expand-sm > .container,\n  .navbar-expand-sm > .container-fluid {\n    padding-right: 0;\n    padding-left: 0; } }\n\n@media (min-width: 576px) {\n  .navbar-expand-sm {\n    -ms-flex-flow: row nowrap;\n    flex-flow: row nowrap;\n    -ms-flex-pack: start;\n    justify-content: flex-start; }\n  .navbar-expand-sm .navbar-nav {\n    -ms-flex-direction: row;\n    flex-direction: row; }\n  .navbar-expand-sm .navbar-nav .dropdown-menu {\n    position: absolute; }\n  .navbar-expand-sm .navbar-nav .dropdown-menu-right {\n    right: 0;\n    left: auto; }\n  .navbar-expand-sm .navbar-nav .nav-link, .navbar-expand-sm .navbar-nav .navbar .dropdown-toggle, .navbar .navbar-expand-sm .navbar-nav .dropdown-toggle {\n    padding-right: .5rem;\n    padding-left: .5rem; }\n  .navbar-expand-sm > .container,\n  .navbar-expand-sm > .container-fluid {\n    -ms-flex-wrap: nowrap;\n    flex-wrap: nowrap; }\n  .navbar-expand-sm .navbar-collapse {\n    display: -ms-flexbox !important;\n    display: flex !important;\n    -ms-flex-preferred-size: auto;\n    flex-basis: auto; }\n  .navbar-expand-sm .navbar-toggler {\n    display: none; }\n  .navbar-expand-sm .dropup .dropdown-menu {\n    top: auto;\n    bottom: 100%; } }\n\n@media (max-width: 767px) {\n  .navbar-expand-md > .container,\n  .navbar-expand-md > .container-fluid {\n    padding-right: 0;\n    padding-left: 0; } }\n\n@media (min-width: 768px) {\n  .navbar-expand-md {\n    -ms-flex-flow: row nowrap;\n    flex-flow: row nowrap;\n    -ms-flex-pack: start;\n    justify-content: flex-start; }\n  .navbar-expand-md .navbar-nav {\n    -ms-flex-direction: row;\n    flex-direction: row; }\n  .navbar-expand-md .navbar-nav .dropdown-menu {\n    position: absolute; }\n  .navbar-expand-md .navbar-nav .dropdown-menu-right {\n    right: 0;\n    left: auto; }\n  .navbar-expand-md .navbar-nav .nav-link, .navbar-expand-md .navbar-nav .navbar .dropdown-toggle, .navbar .navbar-expand-md .navbar-nav .dropdown-toggle {\n    padding-right: .5rem;\n    padding-left: .5rem; }\n  .navbar-expand-md > .container,\n  .navbar-expand-md > .container-fluid {\n    -ms-flex-wrap: nowrap;\n    flex-wrap: nowrap; }\n  .navbar-expand-md .navbar-collapse {\n    display: -ms-flexbox !important;\n    display: flex !important;\n    -ms-flex-preferred-size: auto;\n    flex-basis: auto; }\n  .navbar-expand-md .navbar-toggler {\n    display: none; }\n  .navbar-expand-md .dropup .dropdown-menu {\n    top: auto;\n    bottom: 100%; } }\n\n@media (max-width: 991px) {\n  .navbar-expand-lg > .container,\n  .navbar-expand-lg > .container-fluid {\n    padding-right: 0;\n    padding-left: 0; } }\n\n@media (min-width: 992px) {\n  .navbar-expand-lg {\n    -ms-flex-flow: row nowrap;\n    flex-flow: row nowrap;\n    -ms-flex-pack: start;\n    justify-content: flex-start; }\n  .navbar-expand-lg .navbar-nav {\n    -ms-flex-direction: row;\n    flex-direction: row; }\n  .navbar-expand-lg .navbar-nav .dropdown-menu {\n    position: absolute; }\n  .navbar-expand-lg .navbar-nav .dropdown-menu-right {\n    right: 0;\n    left: auto; }\n  .navbar-expand-lg .navbar-nav .nav-link, .navbar-expand-lg .navbar-nav .navbar .dropdown-toggle, .navbar .navbar-expand-lg .navbar-nav .dropdown-toggle {\n    padding-right: .5rem;\n    padding-left: .5rem; }\n  .navbar-expand-lg > .container,\n  .navbar-expand-lg > .container-fluid {\n    -ms-flex-wrap: nowrap;\n    flex-wrap: nowrap; }\n  .navbar-expand-lg .navbar-collapse {\n    display: -ms-flexbox !important;\n    display: flex !important;\n    -ms-flex-preferred-size: auto;\n    flex-basis: auto; }\n  .navbar-expand-lg .navbar-toggler {\n    display: none; }\n  .navbar-expand-lg .dropup .dropdown-menu {\n    top: auto;\n    bottom: 100%; } }\n\n@media (max-width: 1199px) {\n  .navbar-expand-xl > .container,\n  .navbar-expand-xl > .container-fluid {\n    padding-right: 0;\n    padding-left: 0; } }\n\n@media (min-width: 1200px) {\n  .navbar-expand-xl {\n    -ms-flex-flow: row nowrap;\n    flex-flow: row nowrap;\n    -ms-flex-pack: start;\n    justify-content: flex-start; }\n  .navbar-expand-xl .navbar-nav {\n    -ms-flex-direction: row;\n    flex-direction: row; }\n  .navbar-expand-xl .navbar-nav .dropdown-menu {\n    position: absolute; }\n  .navbar-expand-xl .navbar-nav .dropdown-menu-right {\n    right: 0;\n    left: auto; }\n  .navbar-expand-xl .navbar-nav .nav-link, .navbar-expand-xl .navbar-nav .navbar .dropdown-toggle, .navbar .navbar-expand-xl .navbar-nav .dropdown-toggle {\n    padding-right: .5rem;\n    padding-left: .5rem; }\n  .navbar-expand-xl > .container,\n  .navbar-expand-xl > .container-fluid {\n    -ms-flex-wrap: nowrap;\n    flex-wrap: nowrap; }\n  .navbar-expand-xl .navbar-collapse {\n    display: -ms-flexbox !important;\n    display: flex !important;\n    -ms-flex-preferred-size: auto;\n    flex-basis: auto; }\n  .navbar-expand-xl .navbar-toggler {\n    display: none; }\n  .navbar-expand-xl .dropup .dropdown-menu {\n    top: auto;\n    bottom: 100%; } }\n\n.navbar-expand {\n  -ms-flex-flow: row nowrap;\n  flex-flow: row nowrap;\n  -ms-flex-pack: start;\n  justify-content: flex-start; }\n.navbar-expand > .container,\n.navbar-expand > .container-fluid {\n  padding-right: 0;\n  padding-left: 0; }\n.navbar-expand .navbar-nav {\n  -ms-flex-direction: row;\n  flex-direction: row; }\n.navbar-expand .navbar-nav .dropdown-menu {\n  position: absolute; }\n.navbar-expand .navbar-nav .dropdown-menu-right {\n  right: 0;\n  left: auto; }\n.navbar-expand .navbar-nav .nav-link, .navbar-expand .navbar-nav .navbar .dropdown-toggle, .navbar .navbar-expand .navbar-nav .dropdown-toggle {\n  padding-right: .5rem;\n  padding-left: .5rem; }\n.navbar-expand > .container,\n.navbar-expand > .container-fluid {\n  -ms-flex-wrap: nowrap;\n  flex-wrap: nowrap; }\n.navbar-expand .navbar-collapse {\n  display: -ms-flexbox !important;\n  display: flex !important;\n  -ms-flex-preferred-size: auto;\n  flex-basis: auto; }\n.navbar-expand .navbar-toggler {\n  display: none; }\n.navbar-expand .dropup .dropdown-menu {\n  top: auto;\n  bottom: 100%; }\n\n.navbar-light .navbar-brand {\n  color: rgba(0, 0, 0, 0.9); }\n.navbar-light .navbar-brand:focus, .navbar-light .navbar-brand:hover {\n  color: rgba(0, 0, 0, 0.9); }\n\n.navbar-light .navbar-nav .nav-link, .navbar-light .navbar-nav .navbar .dropdown-toggle, .navbar .navbar-light .navbar-nav .dropdown-toggle {\n  color: rgba(0, 0, 0, 0.5); }\n.navbar-light .navbar-nav .nav-link:focus, .navbar-light .navbar-nav .navbar .dropdown-toggle:focus, .navbar .navbar-light .navbar-nav .dropdown-toggle:focus, .navbar-light .navbar-nav .nav-link:hover, .navbar-light .navbar-nav .navbar .dropdown-toggle:hover, .navbar .navbar-light .navbar-nav .dropdown-toggle:hover {\n  color: rgba(0, 0, 0, 0.7); }\n.navbar-light .navbar-nav .nav-link.disabled, .navbar-light .navbar-nav .navbar .disabled.dropdown-toggle, .navbar .navbar-light .navbar-nav .disabled.dropdown-toggle {\n  color: rgba(0, 0, 0, 0.3); }\n\n.navbar-light .navbar-nav .show > .nav-link, .navbar-light .navbar-nav .navbar .show > .dropdown-toggle, .navbar .navbar-light .navbar-nav .show > .dropdown-toggle,\n.navbar-light .navbar-nav .active > .nav-link,\n.navbar-light .navbar-nav .navbar .active > .dropdown-toggle, .navbar\n.navbar-light .navbar-nav .active > .dropdown-toggle,\n.navbar-light .navbar-nav .nav-link.show,\n.navbar-light .navbar-nav .navbar .show.dropdown-toggle, .navbar\n.navbar-light .navbar-nav .show.dropdown-toggle,\n.navbar-light .navbar-nav .nav-link.active,\n.navbar-light .navbar-nav .navbar .active.dropdown-toggle, .navbar\n.navbar-light .navbar-nav .active.dropdown-toggle {\n  color: rgba(0, 0, 0, 0.9); }\n\n.navbar-light .navbar-toggler {\n  color: rgba(0, 0, 0, 0.5);\n  border-color: rgba(0, 0, 0, 0.1); }\n\n.navbar-light .navbar-toggler-icon {\n  background-image: url(\"data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(0, 0, 0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E\"); }\n\n.navbar-light .navbar-text {\n  color: rgba(0, 0, 0, 0.5); }\n.navbar-light .navbar-text a {\n  color: rgba(0, 0, 0, 0.9); }\n.navbar-light .navbar-text a:focus, .navbar-light .navbar-text a:hover {\n  color: rgba(0, 0, 0, 0.9); }\n\n.navbar-dark .navbar-brand {\n  color: #fff; }\n.navbar-dark .navbar-brand:focus, .navbar-dark .navbar-brand:hover {\n  color: #fff; }\n\n.navbar-dark .navbar-nav .nav-link, .navbar-dark .navbar-nav .navbar .dropdown-toggle, .navbar .navbar-dark .navbar-nav .dropdown-toggle {\n  color: rgba(255, 255, 255, 0.5); }\n.navbar-dark .navbar-nav .nav-link:focus, .navbar-dark .navbar-nav .navbar .dropdown-toggle:focus, .navbar .navbar-dark .navbar-nav .dropdown-toggle:focus, .navbar-dark .navbar-nav .nav-link:hover, .navbar-dark .navbar-nav .navbar .dropdown-toggle:hover, .navbar .navbar-dark .navbar-nav .dropdown-toggle:hover {\n  color: rgba(255, 255, 255, 0.75); }\n.navbar-dark .navbar-nav .nav-link.disabled, .navbar-dark .navbar-nav .navbar .disabled.dropdown-toggle, .navbar .navbar-dark .navbar-nav .disabled.dropdown-toggle {\n  color: rgba(255, 255, 255, 0.25); }\n\n.navbar-dark .navbar-nav .show > .nav-link, .navbar-dark .navbar-nav .navbar .show > .dropdown-toggle, .navbar .navbar-dark .navbar-nav .show > .dropdown-toggle,\n.navbar-dark .navbar-nav .active > .nav-link,\n.navbar-dark .navbar-nav .navbar .active > .dropdown-toggle, .navbar\n.navbar-dark .navbar-nav .active > .dropdown-toggle,\n.navbar-dark .navbar-nav .nav-link.show,\n.navbar-dark .navbar-nav .navbar .show.dropdown-toggle, .navbar\n.navbar-dark .navbar-nav .show.dropdown-toggle,\n.navbar-dark .navbar-nav .nav-link.active,\n.navbar-dark .navbar-nav .navbar .active.dropdown-toggle, .navbar\n.navbar-dark .navbar-nav .active.dropdown-toggle {\n  color: #fff; }\n\n.navbar-dark .navbar-toggler {\n  color: rgba(255, 255, 255, 0.5);\n  border-color: rgba(255, 255, 255, 0.1); }\n\n.navbar-dark .navbar-toggler-icon {\n  background-image: url(\"data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E\"); }\n\n.navbar-dark .navbar-text {\n  color: rgba(255, 255, 255, 0.5); }\n.navbar-dark .navbar-text a {\n  color: #fff; }\n.navbar-dark .navbar-text a:focus, .navbar-dark .navbar-text a:hover {\n  color: #fff; }\n\n.card {\n  position: relative;\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-direction: column;\n  flex-direction: column;\n  min-width: 0;\n  word-wrap: break-word;\n  background-color: #fff;\n  background-clip: border-box;\n  border: 1px solid #c2cfd6; }\n.card > hr {\n  margin-right: 0;\n  margin-left: 0; }\n\n.card-body, .card-block {\n  -ms-flex: 1 1 auto;\n  flex: 1 1 auto;\n  padding: 1.25rem; }\n\n.card-title {\n  margin-bottom: 0.75rem; }\n\n.card-subtitle {\n  margin-top: -0.375rem;\n  margin-bottom: 0; }\n\n.card-text:last-child {\n  margin-bottom: 0; }\n\n.card-link:hover {\n  text-decoration: none; }\n\n.card-link + .card-link {\n  margin-left: 1.25rem; }\n\n.card-header {\n  padding: 0.75rem 1.25rem;\n  margin-bottom: 0;\n  background-color: #f0f3f5;\n  border-bottom: 1px solid #c2cfd6; }\n.card-header + .list-group .list-group-item:first-child {\n  border-top: 0; }\n\n.card-footer {\n  padding: 0.75rem 1.25rem;\n  background-color: #f0f3f5;\n  border-top: 1px solid #c2cfd6; }\n\n.card-header-tabs {\n  margin-right: -0.625rem;\n  margin-bottom: -0.75rem;\n  margin-left: -0.625rem;\n  border-bottom: 0; }\n\n.card-header-pills {\n  margin-right: -0.625rem;\n  margin-left: -0.625rem; }\n\n.card-img-overlay {\n  position: absolute;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 1.25rem; }\n\n.card-img {\n  width: 100%; }\n\n.card-img-top {\n  width: 100%; }\n\n.card-img-bottom {\n  width: 100%; }\n\n.card-deck {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-direction: column;\n  flex-direction: column; }\n.card-deck .card {\n  margin-bottom: 15px; }\n@media (min-width: 576px) {\n  .card-deck {\n    -ms-flex-flow: row wrap;\n    flex-flow: row wrap;\n    margin-right: -15px;\n    margin-left: -15px; }\n  .card-deck .card {\n    display: -ms-flexbox;\n    display: flex;\n    -ms-flex: 1 0 0%;\n    flex: 1 0 0%;\n    -ms-flex-direction: column;\n    flex-direction: column;\n    margin-right: 15px;\n    margin-bottom: 0;\n    margin-left: 15px; } }\n\n.card-group {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-direction: column;\n  flex-direction: column; }\n.card-group .card {\n  margin-bottom: 15px; }\n@media (min-width: 576px) {\n  .card-group {\n    -ms-flex-flow: row wrap;\n    flex-flow: row wrap; }\n  .card-group .card {\n    -ms-flex: 1 0 0%;\n    flex: 1 0 0%;\n    margin-bottom: 0; }\n  .card-group .card + .card {\n    margin-left: 0;\n    border-left: 0; } }\n\n.card-columns .card {\n  margin-bottom: 0.75rem; }\n\n@media (min-width: 576px) {\n  .card-columns {\n    -webkit-column-count: 3;\n    column-count: 3;\n    -webkit-column-gap: 1.25rem;\n    column-gap: 1.25rem; }\n  .card-columns .card {\n    display: inline-block;\n    width: 100%; } }\n\n.breadcrumb {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-wrap: wrap;\n  flex-wrap: wrap;\n  padding: 0.75rem 1rem;\n  margin-bottom: 1.5rem;\n  list-style: none;\n  background-color: #fff; }\n\n.breadcrumb-item + .breadcrumb-item::before {\n  display: inline-block;\n  padding-right: 0.5rem;\n  padding-left: 0.5rem;\n  color: #536c79;\n  content: \"/\"; }\n\n.breadcrumb-item + .breadcrumb-item:hover::before {\n  text-decoration: underline; }\n\n.breadcrumb-item + .breadcrumb-item:hover::before {\n  text-decoration: none; }\n\n.breadcrumb-item.active {\n  color: #536c79; }\n\n.pagination {\n  display: -ms-flexbox;\n  display: flex;\n  padding-left: 0;\n  list-style: none; }\n\n.page-item:first-child .page-link, .pagination-datatables li:first-child .page-link, .pagination li:first-child .page-link, .page-item:first-child .pagination-datatables li a, .pagination-datatables li .page-item:first-child a, .pagination-datatables li:first-child a, .page-item:first-child .pagination li a, .pagination li .page-item:first-child a, .pagination li:first-child a {\n  margin-left: 0; }\n\n.page-item.active .page-link, .pagination-datatables li.active .page-link, .pagination li.active .page-link, .page-item.active .pagination-datatables li a, .pagination-datatables li .page-item.active a, .pagination-datatables li.active a, .page-item.active .pagination li a, .pagination li .page-item.active a, .pagination li.active a {\n  z-index: 2;\n  color: #fff;\n  background-color: #20a8d8;\n  border-color: #20a8d8; }\n\n.page-item.disabled .page-link, .pagination-datatables li.disabled .page-link, .pagination li.disabled .page-link, .page-item.disabled .pagination-datatables li a, .pagination-datatables li .page-item.disabled a, .pagination-datatables li.disabled a, .page-item.disabled .pagination li a, .pagination li .page-item.disabled a, .pagination li.disabled a {\n  color: #536c79;\n  pointer-events: none;\n  background-color: #fff;\n  border-color: #ddd; }\n\n.page-link, .pagination-datatables li a, .pagination li a {\n  position: relative;\n  display: block;\n  padding: 0.5rem 0.75rem;\n  margin-left: -1px;\n  line-height: 1.25;\n  color: #20a8d8;\n  background-color: #fff;\n  border: 1px solid #ddd; }\n.page-link:focus, .pagination-datatables li a:focus, .pagination li a:focus, .page-link:hover, .pagination-datatables li a:hover, .pagination li a:hover {\n  color: #167495;\n  text-decoration: none;\n  background-color: #c2cfd6;\n  border-color: #ddd; }\n\n.pagination-lg .page-link, .pagination-lg .pagination-datatables li a, .pagination-datatables li .pagination-lg a, .pagination-lg .pagination li a, .pagination li .pagination-lg a {\n  padding: 0.75rem 1.5rem;\n  font-size: 1.09375rem;\n  line-height: 1.5; }\n\n.pagination-sm .page-link, .pagination-sm .pagination-datatables li a, .pagination-datatables li .pagination-sm a, .pagination-sm .pagination li a, .pagination li .pagination-sm a {\n  padding: 0.25rem 0.5rem;\n  font-size: 0.76563rem;\n  line-height: 1.5; }\n\n.badge {\n  display: inline-block;\n  padding: 0.25em 0.4em;\n  font-size: 75%;\n  font-weight: 700;\n  line-height: 1;\n  text-align: center;\n  white-space: nowrap;\n  vertical-align: baseline; }\n.badge:empty {\n  display: none; }\n\n.btn .badge {\n  position: relative;\n  top: -1px; }\n\n.badge-pill {\n  padding-right: 0.6em;\n  padding-left: 0.6em; }\n\n.badge-primary {\n  color: #fff;\n  background-color: #20a8d8; }\n.badge-primary[href]:focus, .badge-primary[href]:hover {\n  color: #fff;\n  text-decoration: none;\n  background-color: #1985ac; }\n\n.badge-secondary {\n  color: #111;\n  background-color: #a4b7c1; }\n.badge-secondary[href]:focus, .badge-secondary[href]:hover {\n  color: #111;\n  text-decoration: none;\n  background-color: #869fac; }\n\n.badge-success {\n  color: #fff;\n  background-color: #4dbd74; }\n.badge-success[href]:focus, .badge-success[href]:hover {\n  color: #fff;\n  text-decoration: none;\n  background-color: #3a9d5d; }\n\n.badge-info {\n  color: #111;\n  background-color: #63c2de; }\n.badge-info[href]:focus, .badge-info[href]:hover {\n  color: #111;\n  text-decoration: none;\n  background-color: #39b2d5; }\n\n.badge-warning {\n  color: #111;\n  background-color: #ffc107; }\n.badge-warning[href]:focus, .badge-warning[href]:hover {\n  color: #111;\n  text-decoration: none;\n  background-color: #d39e00; }\n\n.badge-danger {\n  color: #fff;\n  background-color: #f86c6b; }\n.badge-danger[href]:focus, .badge-danger[href]:hover {\n  color: #fff;\n  text-decoration: none;\n  background-color: #f63c3a; }\n\n.badge-light {\n  color: #111;\n  background-color: #f0f3f5; }\n.badge-light[href]:focus, .badge-light[href]:hover {\n  color: #111;\n  text-decoration: none;\n  background-color: #d1dbe1; }\n\n.badge-dark {\n  color: #fff;\n  background-color: #29363d; }\n.badge-dark[href]:focus, .badge-dark[href]:hover {\n  color: #fff;\n  text-decoration: none;\n  background-color: #151b1f; }\n\n.jumbotron {\n  padding: 2rem 1rem;\n  margin-bottom: 2rem;\n  background-color: #c2cfd6; }\n@media (min-width: 576px) {\n  .jumbotron {\n    padding: 4rem 2rem; } }\n\n.jumbotron-fluid {\n  padding-right: 0;\n  padding-left: 0; }\n\n.alert {\n  position: relative;\n  padding: 0.75rem 1.25rem;\n  margin-bottom: 1rem;\n  border: 1px solid transparent; }\n\n.alert-heading {\n  color: inherit; }\n\n.alert-link {\n  font-weight: 700; }\n\n.alert-dismissible .close {\n  position: absolute;\n  top: 0;\n  right: 0;\n  padding: 0.75rem 1.25rem;\n  color: inherit; }\n\n.alert-primary {\n  color: #115770;\n  background-color: #d2eef7;\n  border-color: #c1e7f4; }\n.alert-primary hr {\n  border-top-color: #abdff0; }\n.alert-primary .alert-link {\n  color: #0a3544; }\n\n.alert-secondary {\n  color: #555f64;\n  background-color: #edf1f3;\n  border-color: #e6ebee; }\n.alert-secondary hr {\n  border-top-color: #d7dfe4; }\n.alert-secondary .alert-link {\n  color: #3e4548; }\n\n.alert-success {\n  color: #28623c;\n  background-color: #dbf2e3;\n  border-color: #cdedd8; }\n.alert-success hr {\n  border-top-color: #bae6c9; }\n.alert-success .alert-link {\n  color: #193e26; }\n\n.alert-info {\n  color: #336573;\n  background-color: #e0f3f8;\n  border-color: #d3eef6; }\n.alert-info hr {\n  border-top-color: #bee6f2; }\n.alert-info .alert-link {\n  color: #234650; }\n\n.alert-warning {\n  color: #856404;\n  background-color: #fff3cd;\n  border-color: #ffeeba; }\n.alert-warning hr {\n  border-top-color: #ffe8a1; }\n.alert-warning .alert-link {\n  color: #533f03; }\n\n.alert-danger {\n  color: #813838;\n  background-color: #fee2e1;\n  border-color: #fdd6d6; }\n.alert-danger hr {\n  border-top-color: #fcbebe; }\n.alert-danger .alert-link {\n  color: #5d2929; }\n\n.alert-light {\n  color: #7d7e7f;\n  background-color: #fcfdfd;\n  border-color: #fbfcfc; }\n.alert-light hr {\n  border-top-color: #ecf1f1; }\n.alert-light .alert-link {\n  color: #646565; }\n\n.alert-dark {\n  color: #151c20;\n  background-color: #d4d7d8;\n  border-color: #c3c7c9; }\n.alert-dark hr {\n  border-top-color: #b6babd; }\n.alert-dark .alert-link {\n  color: #010101; }\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 1rem 0; }\n  to {\n    background-position: 0 0; } }\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 1rem 0; }\n  to {\n    background-position: 0 0; } }\n\n.progress {\n  display: -ms-flexbox;\n  display: flex;\n  height: 1rem;\n  overflow: hidden;\n  font-size: 0.65625rem;\n  background-color: #f0f3f5; }\n\n.progress-bar {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-align: center;\n  align-items: center;\n  -ms-flex-pack: center;\n  justify-content: center;\n  color: #fff;\n  background-color: #20a8d8; }\n\n.progress-bar-striped {\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: 1rem 1rem; }\n\n.progress-bar-animated {\n  -webkit-animation: progress-bar-stripes 1s linear infinite;\n  animation: progress-bar-stripes 1s linear infinite; }\n\n.media {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-align: start;\n  align-items: flex-start; }\n\n.media-body {\n  -ms-flex: 1;\n  flex: 1; }\n\n.list-group {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-direction: column;\n  flex-direction: column;\n  padding-left: 0;\n  margin-bottom: 0; }\n\n.list-group-item-action {\n  width: 100%;\n  color: #3e515b;\n  text-align: inherit; }\n.list-group-item-action:focus, .list-group-item-action:hover {\n  color: #3e515b;\n  text-decoration: none;\n  background-color: #f0f3f5; }\n.list-group-item-action:active {\n  color: #151b1e;\n  background-color: #c2cfd6; }\n\n.list-group-item {\n  position: relative;\n  display: block;\n  padding: 0.75rem 1.25rem;\n  margin-bottom: -1px;\n  background-color: #fff;\n  border: 1px solid rgba(0, 0, 0, 0.125); }\n.list-group-item:last-child {\n  margin-bottom: 0; }\n.list-group-item:focus, .list-group-item:hover {\n  text-decoration: none; }\n.list-group-item.disabled, .list-group-item:disabled {\n  color: #536c79;\n  background-color: #fff; }\n.list-group-item.active {\n  z-index: 2;\n  color: #fff;\n  background-color: #20a8d8;\n  border-color: #20a8d8; }\n\n.list-group-flush .list-group-item {\n  border-right: 0;\n  border-left: 0;\n  border-radius: 0; }\n\n.list-group-flush:first-child .list-group-item:first-child {\n  border-top: 0; }\n\n.list-group-flush:last-child .list-group-item:last-child {\n  border-bottom: 0; }\n\n.list-group-item-primary {\n  color: #115770;\n  background-color: #c1e7f4; }\n\na.list-group-item-primary,\nbutton.list-group-item-primary {\n  color: #115770; }\na.list-group-item-primary:focus, a.list-group-item-primary:hover,\nbutton.list-group-item-primary:focus,\nbutton.list-group-item-primary:hover {\n  color: #115770;\n  background-color: #abdff0; }\na.list-group-item-primary.active,\nbutton.list-group-item-primary.active {\n  color: #fff;\n  background-color: #115770;\n  border-color: #115770; }\n\n.list-group-item-secondary {\n  color: #555f64;\n  background-color: #e6ebee; }\n\na.list-group-item-secondary,\nbutton.list-group-item-secondary {\n  color: #555f64; }\na.list-group-item-secondary:focus, a.list-group-item-secondary:hover,\nbutton.list-group-item-secondary:focus,\nbutton.list-group-item-secondary:hover {\n  color: #555f64;\n  background-color: #d7dfe4; }\na.list-group-item-secondary.active,\nbutton.list-group-item-secondary.active {\n  color: #fff;\n  background-color: #555f64;\n  border-color: #555f64; }\n\n.list-group-item-success {\n  color: #28623c;\n  background-color: #cdedd8; }\n\na.list-group-item-success,\nbutton.list-group-item-success {\n  color: #28623c; }\na.list-group-item-success:focus, a.list-group-item-success:hover,\nbutton.list-group-item-success:focus,\nbutton.list-group-item-success:hover {\n  color: #28623c;\n  background-color: #bae6c9; }\na.list-group-item-success.active,\nbutton.list-group-item-success.active {\n  color: #fff;\n  background-color: #28623c;\n  border-color: #28623c; }\n\n.list-group-item-info {\n  color: #336573;\n  background-color: #d3eef6; }\n\na.list-group-item-info,\nbutton.list-group-item-info {\n  color: #336573; }\na.list-group-item-info:focus, a.list-group-item-info:hover,\nbutton.list-group-item-info:focus,\nbutton.list-group-item-info:hover {\n  color: #336573;\n  background-color: #bee6f2; }\na.list-group-item-info.active,\nbutton.list-group-item-info.active {\n  color: #fff;\n  background-color: #336573;\n  border-color: #336573; }\n\n.list-group-item-warning {\n  color: #856404;\n  background-color: #ffeeba; }\n\na.list-group-item-warning,\nbutton.list-group-item-warning {\n  color: #856404; }\na.list-group-item-warning:focus, a.list-group-item-warning:hover,\nbutton.list-group-item-warning:focus,\nbutton.list-group-item-warning:hover {\n  color: #856404;\n  background-color: #ffe8a1; }\na.list-group-item-warning.active,\nbutton.list-group-item-warning.active {\n  color: #fff;\n  background-color: #856404;\n  border-color: #856404; }\n\n.list-group-item-danger {\n  color: #813838;\n  background-color: #fdd6d6; }\n\na.list-group-item-danger,\nbutton.list-group-item-danger {\n  color: #813838; }\na.list-group-item-danger:focus, a.list-group-item-danger:hover,\nbutton.list-group-item-danger:focus,\nbutton.list-group-item-danger:hover {\n  color: #813838;\n  background-color: #fcbebe; }\na.list-group-item-danger.active,\nbutton.list-group-item-danger.active {\n  color: #fff;\n  background-color: #813838;\n  border-color: #813838; }\n\n.list-group-item-light {\n  color: #7d7e7f;\n  background-color: #fbfcfc; }\n\na.list-group-item-light,\nbutton.list-group-item-light {\n  color: #7d7e7f; }\na.list-group-item-light:focus, a.list-group-item-light:hover,\nbutton.list-group-item-light:focus,\nbutton.list-group-item-light:hover {\n  color: #7d7e7f;\n  background-color: #ecf1f1; }\na.list-group-item-light.active,\nbutton.list-group-item-light.active {\n  color: #fff;\n  background-color: #7d7e7f;\n  border-color: #7d7e7f; }\n\n.list-group-item-dark {\n  color: #151c20;\n  background-color: #c3c7c9; }\n\na.list-group-item-dark,\nbutton.list-group-item-dark {\n  color: #151c20; }\na.list-group-item-dark:focus, a.list-group-item-dark:hover,\nbutton.list-group-item-dark:focus,\nbutton.list-group-item-dark:hover {\n  color: #151c20;\n  background-color: #b6babd; }\na.list-group-item-dark.active,\nbutton.list-group-item-dark.active {\n  color: #fff;\n  background-color: #151c20;\n  border-color: #151c20; }\n\n.close {\n  float: right;\n  font-size: 1.3125rem;\n  font-weight: 700;\n  line-height: 1;\n  color: #000;\n  text-shadow: 0 1px 0 #fff;\n  opacity: .5; }\n.close:focus, .close:hover {\n  color: #000;\n  text-decoration: none;\n  opacity: .75; }\n\nbutton.close {\n  padding: 0;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none; }\n\n.modal-open {\n  overflow: hidden; }\n\n.modal {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1050;\n  display: none;\n  overflow: hidden;\n  outline: 0; }\n.modal.fade .modal-dialog {\n  transition: -webkit-transform 0.3s ease-out;\n  transition: transform 0.3s ease-out;\n  transition: transform 0.3s ease-out, -webkit-transform 0.3s ease-out;\n  -webkit-transform: translate(0, -25%);\n  transform: translate(0, -25%); }\n.modal.show .modal-dialog {\n  -webkit-transform: translate(0, 0);\n  transform: translate(0, 0); }\n\n.modal-open .modal {\n  overflow-x: hidden;\n  overflow-y: auto; }\n\n.modal-dialog {\n  position: relative;\n  width: auto;\n  margin: 10px;\n  pointer-events: none; }\n\n.modal-content {\n  position: relative;\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-direction: column;\n  flex-direction: column;\n  pointer-events: auto;\n  background-color: #fff;\n  background-clip: padding-box;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  outline: 0; }\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000; }\n.modal-backdrop.fade {\n  opacity: 0; }\n.modal-backdrop.show {\n  opacity: 0.5; }\n\n.modal-header {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-align: start;\n  align-items: flex-start;\n  -ms-flex-pack: justify;\n  justify-content: space-between;\n  padding: 15px;\n  border-bottom: 1px solid #c2cfd6; }\n.modal-header .close {\n  padding: 15px;\n  margin: -15px -15px -15px auto; }\n\n.modal-title {\n  margin-bottom: 0;\n  line-height: 1.5; }\n\n.modal-body {\n  position: relative;\n  -ms-flex: 1 1 auto;\n  flex: 1 1 auto;\n  padding: 15px; }\n\n.modal-footer {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-align: center;\n  align-items: center;\n  -ms-flex-pack: end;\n  justify-content: flex-end;\n  padding: 15px;\n  border-top: 1px solid #c2cfd6; }\n.modal-footer > :not(:first-child) {\n  margin-left: .25rem; }\n.modal-footer > :not(:last-child) {\n  margin-right: .25rem; }\n\n.modal-scrollbar-measure {\n  position: absolute;\n  top: -9999px;\n  width: 50px;\n  height: 50px;\n  overflow: scroll; }\n\n@media (min-width: 576px) {\n  .modal-dialog {\n    max-width: 500px;\n    margin: 30px auto; }\n  .modal-sm {\n    max-width: 300px; } }\n\n@media (min-width: 992px) {\n  .modal-lg {\n    max-width: 800px; } }\n\n.tooltip {\n  position: absolute;\n  z-index: 1070;\n  display: block;\n  margin: 0;\n  font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";\n  font-style: normal;\n  font-weight: 400;\n  line-height: 1.5;\n  text-align: left;\n  text-align: start;\n  text-decoration: none;\n  text-shadow: none;\n  text-transform: none;\n  letter-spacing: normal;\n  word-break: normal;\n  word-spacing: normal;\n  white-space: normal;\n  line-break: auto;\n  font-size: 0.76563rem;\n  word-wrap: break-word;\n  opacity: 0; }\n.tooltip.show {\n  opacity: 0.9; }\n.tooltip .arrow {\n  position: absolute;\n  display: block;\n  width: 5px;\n  height: 5px; }\n.tooltip .arrow::before {\n  position: absolute;\n  border-color: transparent;\n  border-style: solid; }\n.tooltip.bs-tooltip-top, .tooltip.bs-tooltip-auto[x-placement^=\"top\"] {\n  padding: 5px 0; }\n.tooltip.bs-tooltip-top .arrow, .tooltip.bs-tooltip-auto[x-placement^=\"top\"] .arrow {\n  bottom: 0; }\n.tooltip.bs-tooltip-top .arrow::before, .tooltip.bs-tooltip-auto[x-placement^=\"top\"] .arrow::before {\n  margin-left: -3px;\n  content: \"\";\n  border-width: 5px 5px 0;\n  border-top-color: #000; }\n.tooltip.bs-tooltip-right, .tooltip.bs-tooltip-auto[x-placement^=\"right\"] {\n  padding: 0 5px; }\n.tooltip.bs-tooltip-right .arrow, .tooltip.bs-tooltip-auto[x-placement^=\"right\"] .arrow {\n  left: 0; }\n.tooltip.bs-tooltip-right .arrow::before, .tooltip.bs-tooltip-auto[x-placement^=\"right\"] .arrow::before {\n  margin-top: -3px;\n  content: \"\";\n  border-width: 5px 5px 5px 0;\n  border-right-color: #000; }\n.tooltip.bs-tooltip-bottom, .tooltip.bs-tooltip-auto[x-placement^=\"bottom\"] {\n  padding: 5px 0; }\n.tooltip.bs-tooltip-bottom .arrow, .tooltip.bs-tooltip-auto[x-placement^=\"bottom\"] .arrow {\n  top: 0; }\n.tooltip.bs-tooltip-bottom .arrow::before, .tooltip.bs-tooltip-auto[x-placement^=\"bottom\"] .arrow::before {\n  margin-left: -3px;\n  content: \"\";\n  border-width: 0 5px 5px;\n  border-bottom-color: #000; }\n.tooltip.bs-tooltip-left, .tooltip.bs-tooltip-auto[x-placement^=\"left\"] {\n  padding: 0 5px; }\n.tooltip.bs-tooltip-left .arrow, .tooltip.bs-tooltip-auto[x-placement^=\"left\"] .arrow {\n  right: 0; }\n.tooltip.bs-tooltip-left .arrow::before, .tooltip.bs-tooltip-auto[x-placement^=\"left\"] .arrow::before {\n  right: 0;\n  margin-top: -3px;\n  content: \"\";\n  border-width: 5px 0 5px 5px;\n  border-left-color: #000; }\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #fff;\n  text-align: center;\n  background-color: #000; }\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1060;\n  display: block;\n  max-width: 276px;\n  font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";\n  font-style: normal;\n  font-weight: 400;\n  line-height: 1.5;\n  text-align: left;\n  text-align: start;\n  text-decoration: none;\n  text-shadow: none;\n  text-transform: none;\n  letter-spacing: normal;\n  word-break: normal;\n  word-spacing: normal;\n  white-space: normal;\n  line-break: auto;\n  font-size: 0.76563rem;\n  word-wrap: break-word;\n  background-color: #fff;\n  background-clip: padding-box;\n  border: 1px solid rgba(0, 0, 0, 0.2); }\n.popover .arrow {\n  position: absolute;\n  display: block;\n  width: 0.8rem;\n  height: 0.4rem; }\n.popover .arrow::before,\n.popover .arrow::after {\n  position: absolute;\n  display: block;\n  border-color: transparent;\n  border-style: solid; }\n.popover .arrow::before {\n  content: \"\";\n  border-width: 0.8rem; }\n.popover .arrow::after {\n  content: \"\";\n  border-width: 0.8rem; }\n.popover.bs-popover-top, .popover.bs-popover-auto[x-placement^=\"top\"] {\n  margin-bottom: 0.8rem; }\n.popover.bs-popover-top .arrow, .popover.bs-popover-auto[x-placement^=\"top\"] .arrow {\n  bottom: 0; }\n.popover.bs-popover-top .arrow::before, .popover.bs-popover-auto[x-placement^=\"top\"] .arrow::before,\n.popover.bs-popover-top .arrow::after, .popover.bs-popover-auto[x-placement^=\"top\"] .arrow::after {\n  border-bottom-width: 0; }\n.popover.bs-popover-top .arrow::before, .popover.bs-popover-auto[x-placement^=\"top\"] .arrow::before {\n  bottom: -0.8rem;\n  margin-left: -0.8rem;\n  border-top-color: rgba(0, 0, 0, 0.25); }\n.popover.bs-popover-top .arrow::after, .popover.bs-popover-auto[x-placement^=\"top\"] .arrow::after {\n  bottom: calc((0.8rem - 1px) * -1);\n  margin-left: -0.8rem;\n  border-top-color: #fff; }\n.popover.bs-popover-right, .popover.bs-popover-auto[x-placement^=\"right\"] {\n  margin-left: 0.8rem; }\n.popover.bs-popover-right .arrow, .popover.bs-popover-auto[x-placement^=\"right\"] .arrow {\n  left: 0; }\n.popover.bs-popover-right .arrow::before, .popover.bs-popover-auto[x-placement^=\"right\"] .arrow::before,\n.popover.bs-popover-right .arrow::after, .popover.bs-popover-auto[x-placement^=\"right\"] .arrow::after {\n  margin-top: -0.8rem;\n  border-left-width: 0; }\n.popover.bs-popover-right .arrow::before, .popover.bs-popover-auto[x-placement^=\"right\"] .arrow::before {\n  left: -0.8rem;\n  border-right-color: rgba(0, 0, 0, 0.25); }\n.popover.bs-popover-right .arrow::after, .popover.bs-popover-auto[x-placement^=\"right\"] .arrow::after {\n  left: calc((0.8rem - 1px) * -1);\n  border-right-color: #fff; }\n.popover.bs-popover-bottom, .popover.bs-popover-auto[x-placement^=\"bottom\"] {\n  margin-top: 0.8rem; }\n.popover.bs-popover-bottom .arrow, .popover.bs-popover-auto[x-placement^=\"bottom\"] .arrow {\n  top: 0; }\n.popover.bs-popover-bottom .arrow::before, .popover.bs-popover-auto[x-placement^=\"bottom\"] .arrow::before,\n.popover.bs-popover-bottom .arrow::after, .popover.bs-popover-auto[x-placement^=\"bottom\"] .arrow::after {\n  margin-left: -0.8rem;\n  border-top-width: 0; }\n.popover.bs-popover-bottom .arrow::before, .popover.bs-popover-auto[x-placement^=\"bottom\"] .arrow::before {\n  top: -0.8rem;\n  border-bottom-color: rgba(0, 0, 0, 0.25); }\n.popover.bs-popover-bottom .arrow::after, .popover.bs-popover-auto[x-placement^=\"bottom\"] .arrow::after {\n  top: calc((0.8rem - 1px) * -1);\n  border-bottom-color: #fff; }\n.popover.bs-popover-bottom .popover-header::before, .popover.bs-popover-auto[x-placement^=\"bottom\"] .popover-header::before {\n  position: absolute;\n  top: 0;\n  left: 50%;\n  display: block;\n  width: 20px;\n  margin-left: -10px;\n  content: \"\";\n  border-bottom: 1px solid #f7f7f7; }\n.popover.bs-popover-left, .popover.bs-popover-auto[x-placement^=\"left\"] {\n  margin-right: 0.8rem; }\n.popover.bs-popover-left .arrow, .popover.bs-popover-auto[x-placement^=\"left\"] .arrow {\n  right: 0; }\n.popover.bs-popover-left .arrow::before, .popover.bs-popover-auto[x-placement^=\"left\"] .arrow::before,\n.popover.bs-popover-left .arrow::after, .popover.bs-popover-auto[x-placement^=\"left\"] .arrow::after {\n  margin-top: -0.8rem;\n  border-right-width: 0; }\n.popover.bs-popover-left .arrow::before, .popover.bs-popover-auto[x-placement^=\"left\"] .arrow::before {\n  right: -0.8rem;\n  border-left-color: rgba(0, 0, 0, 0.25); }\n.popover.bs-popover-left .arrow::after, .popover.bs-popover-auto[x-placement^=\"left\"] .arrow::after {\n  right: calc((0.8rem - 1px) * -1);\n  border-left-color: #fff; }\n\n.popover-header {\n  padding: 0.5rem 0.75rem;\n  margin-bottom: 0;\n  font-size: 0.875rem;\n  color: inherit;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb; }\n.popover-header:empty {\n  display: none; }\n\n.popover-body {\n  padding: 0.5rem 0.75rem;\n  color: #151b1e; }\n\n.carousel {\n  position: relative; }\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden; }\n\n.carousel-item {\n  position: relative;\n  display: none;\n  -ms-flex-align: center;\n  align-items: center;\n  width: 100%;\n  transition: -webkit-transform 0.6s ease;\n  transition: transform 0.6s ease;\n  transition: transform 0.6s ease, -webkit-transform 0.6s ease;\n  -webkit-backface-visibility: hidden;\n  backface-visibility: hidden;\n  -webkit-perspective: 1000px;\n  perspective: 1000px; }\n\n.carousel-item.active,\n.carousel-item-next,\n.carousel-item-prev {\n  display: block; }\n\n.carousel-item-next,\n.carousel-item-prev {\n  position: absolute;\n  top: 0; }\n\n.carousel-item-next.carousel-item-left,\n.carousel-item-prev.carousel-item-right {\n  -webkit-transform: translateX(0);\n  transform: translateX(0); }\n@supports ((-webkit-transform-style: preserve-3d) or (transform-style: preserve-3d)) {\n  .carousel-item-next.carousel-item-left,\n  .carousel-item-prev.carousel-item-right {\n    -webkit-transform: translate3d(0, 0, 0);\n    transform: translate3d(0, 0, 0); } }\n\n.carousel-item-next,\n.active.carousel-item-right {\n  -webkit-transform: translateX(100%);\n  transform: translateX(100%); }\n@supports ((-webkit-transform-style: preserve-3d) or (transform-style: preserve-3d)) {\n  .carousel-item-next,\n  .active.carousel-item-right {\n    -webkit-transform: translate3d(100%, 0, 0);\n    transform: translate3d(100%, 0, 0); } }\n\n.carousel-item-prev,\n.active.carousel-item-left {\n  -webkit-transform: translateX(-100%);\n  transform: translateX(-100%); }\n@supports ((-webkit-transform-style: preserve-3d) or (transform-style: preserve-3d)) {\n  .carousel-item-prev,\n  .active.carousel-item-left {\n    -webkit-transform: translate3d(-100%, 0, 0);\n    transform: translate3d(-100%, 0, 0); } }\n\n.carousel-control-prev,\n.carousel-control-next {\n  position: absolute;\n  top: 0;\n  bottom: 0;\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-align: center;\n  align-items: center;\n  -ms-flex-pack: center;\n  justify-content: center;\n  width: 15%;\n  color: #fff;\n  text-align: center;\n  opacity: 0.5; }\n.carousel-control-prev:focus, .carousel-control-prev:hover,\n.carousel-control-next:focus,\n.carousel-control-next:hover {\n  color: #fff;\n  text-decoration: none;\n  outline: 0;\n  opacity: .9; }\n\n.carousel-control-prev {\n  left: 0; }\n\n.carousel-control-next {\n  right: 0; }\n\n.carousel-control-prev-icon,\n.carousel-control-next-icon {\n  display: inline-block;\n  width: 20px;\n  height: 20px;\n  background: transparent no-repeat center center;\n  background-size: 100% 100%; }\n\n.carousel-control-prev-icon {\n  background-image: url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E\"); }\n\n.carousel-control-next-icon {\n  background-image: url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3E%3C/svg%3E\"); }\n\n.carousel-indicators {\n  position: absolute;\n  right: 0;\n  bottom: 10px;\n  left: 0;\n  z-index: 15;\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-pack: center;\n  justify-content: center;\n  padding-left: 0;\n  margin-right: 15%;\n  margin-left: 15%;\n  list-style: none; }\n.carousel-indicators li {\n  position: relative;\n  -ms-flex: 0 1 auto;\n  flex: 0 1 auto;\n  width: 30px;\n  height: 3px;\n  margin-right: 3px;\n  margin-left: 3px;\n  text-indent: -999px;\n  background-color: rgba(255, 255, 255, 0.5); }\n.carousel-indicators li::before {\n  position: absolute;\n  top: -10px;\n  left: 0;\n  display: inline-block;\n  width: 100%;\n  height: 10px;\n  content: \"\"; }\n.carousel-indicators li::after {\n  position: absolute;\n  bottom: -10px;\n  left: 0;\n  display: inline-block;\n  width: 100%;\n  height: 10px;\n  content: \"\"; }\n.carousel-indicators .active {\n  background-color: #fff; }\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: #fff;\n  text-align: center; }\n\n.align-baseline {\n  vertical-align: baseline !important; }\n\n.align-top {\n  vertical-align: top !important; }\n\n.align-middle {\n  vertical-align: middle !important; }\n\n.align-bottom {\n  vertical-align: bottom !important; }\n\n.align-text-bottom {\n  vertical-align: text-bottom !important; }\n\n.align-text-top {\n  vertical-align: text-top !important; }\n\n.bg-primary {\n  background-color: #20a8d8 !important; }\n\na.bg-primary:focus, a.bg-primary:hover {\n  background-color: #1985ac !important; }\n\n.bg-secondary {\n  background-color: #a4b7c1 !important; }\n\na.bg-secondary:focus, a.bg-secondary:hover {\n  background-color: #869fac !important; }\n\n.bg-success {\n  background-color: #4dbd74 !important; }\n\na.bg-success:focus, a.bg-success:hover {\n  background-color: #3a9d5d !important; }\n\n.bg-info {\n  background-color: #63c2de !important; }\n\na.bg-info:focus, a.bg-info:hover {\n  background-color: #39b2d5 !important; }\n\n.bg-warning {\n  background-color: #ffc107 !important; }\n\na.bg-warning:focus, a.bg-warning:hover {\n  background-color: #d39e00 !important; }\n\n.bg-danger {\n  background-color: #f86c6b !important; }\n\na.bg-danger:focus, a.bg-danger:hover {\n  background-color: #f63c3a !important; }\n\n.bg-light {\n  background-color: #f0f3f5 !important; }\n\na.bg-light:focus, a.bg-light:hover {\n  background-color: #d1dbe1 !important; }\n\n.bg-dark {\n  background-color: #29363d !important; }\n\na.bg-dark:focus, a.bg-dark:hover {\n  background-color: #151b1f !important; }\n\n.bg-white {\n  background-color: #fff !important; }\n\n.bg-transparent {\n  background-color: transparent !important; }\n\n.border {\n  border: 1px solid #c2cfd6 !important; }\n\n.border-0 {\n  border: 0 !important; }\n\n.border-top-0 {\n  border-top: 0 !important; }\n\n.border-right-0 {\n  border-right: 0 !important; }\n\n.border-bottom-0 {\n  border-bottom: 0 !important; }\n\n.border-left-0 {\n  border-left: 0 !important; }\n\n.border-primary {\n  border-color: #20a8d8 !important; }\n\n.border-secondary {\n  border-color: #a4b7c1 !important; }\n\n.border-success {\n  border-color: #4dbd74 !important; }\n\n.border-info {\n  border-color: #63c2de !important; }\n\n.border-warning {\n  border-color: #ffc107 !important; }\n\n.border-danger {\n  border-color: #f86c6b !important; }\n\n.border-light {\n  border-color: #f0f3f5 !important; }\n\n.border-dark {\n  border-color: #29363d !important; }\n\n.border-white {\n  border-color: #fff !important; }\n\n.rounded {\n  border-radius: 0.25rem !important; }\n\n.rounded-top {\n  border-top-left-radius: 0.25rem !important;\n  border-top-right-radius: 0.25rem !important; }\n\n.rounded-right {\n  border-top-right-radius: 0.25rem !important;\n  border-bottom-right-radius: 0.25rem !important; }\n\n.rounded-bottom {\n  border-bottom-right-radius: 0.25rem !important;\n  border-bottom-left-radius: 0.25rem !important; }\n\n.rounded-left {\n  border-top-left-radius: 0.25rem !important;\n  border-bottom-left-radius: 0.25rem !important; }\n\n.rounded-circle {\n  border-radius: 50% !important; }\n\n.rounded-0 {\n  border-radius: 0 !important; }\n\n.clearfix::after {\n  display: block;\n  clear: both;\n  content: \"\"; }\n\n.d-none {\n  display: none !important; }\n\n.d-inline {\n  display: inline !important; }\n\n.d-inline-block {\n  display: inline-block !important; }\n\n.d-block {\n  display: block !important; }\n\n.d-table {\n  display: table !important; }\n\n.d-table-row {\n  display: table-row !important; }\n\n.d-table-cell {\n  display: table-cell !important; }\n\n.d-flex {\n  display: -ms-flexbox !important;\n  display: flex !important; }\n\n.d-inline-flex {\n  display: -ms-inline-flexbox !important;\n  display: inline-flex !important; }\n\n@media (min-width: 576px) {\n  .d-sm-none {\n    display: none !important; }\n  .d-sm-inline {\n    display: inline !important; }\n  .d-sm-inline-block {\n    display: inline-block !important; }\n  .d-sm-block {\n    display: block !important; }\n  .d-sm-table {\n    display: table !important; }\n  .d-sm-table-row {\n    display: table-row !important; }\n  .d-sm-table-cell {\n    display: table-cell !important; }\n  .d-sm-flex {\n    display: -ms-flexbox !important;\n    display: flex !important; }\n  .d-sm-inline-flex {\n    display: -ms-inline-flexbox !important;\n    display: inline-flex !important; } }\n\n@media (min-width: 768px) {\n  .d-md-none {\n    display: none !important; }\n  .d-md-inline {\n    display: inline !important; }\n  .d-md-inline-block {\n    display: inline-block !important; }\n  .d-md-block {\n    display: block !important; }\n  .d-md-table {\n    display: table !important; }\n  .d-md-table-row {\n    display: table-row !important; }\n  .d-md-table-cell {\n    display: table-cell !important; }\n  .d-md-flex {\n    display: -ms-flexbox !important;\n    display: flex !important; }\n  .d-md-inline-flex {\n    display: -ms-inline-flexbox !important;\n    display: inline-flex !important; } }\n\n@media (min-width: 992px) {\n  .d-lg-none {\n    display: none !important; }\n  .d-lg-inline {\n    display: inline !important; }\n  .d-lg-inline-block {\n    display: inline-block !important; }\n  .d-lg-block {\n    display: block !important; }\n  .d-lg-table {\n    display: table !important; }\n  .d-lg-table-row {\n    display: table-row !important; }\n  .d-lg-table-cell {\n    display: table-cell !important; }\n  .d-lg-flex {\n    display: -ms-flexbox !important;\n    display: flex !important; }\n  .d-lg-inline-flex {\n    display: -ms-inline-flexbox !important;\n    display: inline-flex !important; } }\n\n@media (min-width: 1200px) {\n  .d-xl-none {\n    display: none !important; }\n  .d-xl-inline {\n    display: inline !important; }\n  .d-xl-inline-block {\n    display: inline-block !important; }\n  .d-xl-block {\n    display: block !important; }\n  .d-xl-table {\n    display: table !important; }\n  .d-xl-table-row {\n    display: table-row !important; }\n  .d-xl-table-cell {\n    display: table-cell !important; }\n  .d-xl-flex {\n    display: -ms-flexbox !important;\n    display: flex !important; }\n  .d-xl-inline-flex {\n    display: -ms-inline-flexbox !important;\n    display: inline-flex !important; } }\n\n.d-print-block {\n  display: none !important; }\n@media print {\n  .d-print-block {\n    display: block !important; } }\n\n.d-print-inline {\n  display: none !important; }\n@media print {\n  .d-print-inline {\n    display: inline !important; } }\n\n.d-print-inline-block {\n  display: none !important; }\n@media print {\n  .d-print-inline-block {\n    display: inline-block !important; } }\n\n@media print {\n  .d-print-none {\n    display: none !important; } }\n\n.embed-responsive {\n  position: relative;\n  display: block;\n  width: 100%;\n  padding: 0;\n  overflow: hidden; }\n.embed-responsive::before {\n  display: block;\n  content: \"\"; }\n.embed-responsive .embed-responsive-item,\n.embed-responsive iframe,\n.embed-responsive embed,\n.embed-responsive object,\n.embed-responsive video {\n  position: absolute;\n  top: 0;\n  bottom: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n  border: 0; }\n\n.embed-responsive-21by9::before {\n  padding-top: 42.85714%; }\n\n.embed-responsive-16by9::before {\n  padding-top: 56.25%; }\n\n.embed-responsive-4by3::before {\n  padding-top: 75%; }\n\n.embed-responsive-1by1::before {\n  padding-top: 100%; }\n\n.flex-row {\n  -ms-flex-direction: row !important;\n  flex-direction: row !important; }\n\n.flex-column {\n  -ms-flex-direction: column !important;\n  flex-direction: column !important; }\n\n.flex-row-reverse {\n  -ms-flex-direction: row-reverse !important;\n  flex-direction: row-reverse !important; }\n\n.flex-column-reverse {\n  -ms-flex-direction: column-reverse !important;\n  flex-direction: column-reverse !important; }\n\n.flex-wrap {\n  -ms-flex-wrap: wrap !important;\n  flex-wrap: wrap !important; }\n\n.flex-nowrap {\n  -ms-flex-wrap: nowrap !important;\n  flex-wrap: nowrap !important; }\n\n.flex-wrap-reverse {\n  -ms-flex-wrap: wrap-reverse !important;\n  flex-wrap: wrap-reverse !important; }\n\n.justify-content-start {\n  -ms-flex-pack: start !important;\n  justify-content: flex-start !important; }\n\n.justify-content-end {\n  -ms-flex-pack: end !important;\n  justify-content: flex-end !important; }\n\n.justify-content-center {\n  -ms-flex-pack: center !important;\n  justify-content: center !important; }\n\n.justify-content-between {\n  -ms-flex-pack: justify !important;\n  justify-content: space-between !important; }\n\n.justify-content-around {\n  -ms-flex-pack: distribute !important;\n  justify-content: space-around !important; }\n\n.align-items-start {\n  -ms-flex-align: start !important;\n  align-items: flex-start !important; }\n\n.align-items-end {\n  -ms-flex-align: end !important;\n  align-items: flex-end !important; }\n\n.align-items-center {\n  -ms-flex-align: center !important;\n  align-items: center !important; }\n\n.align-items-baseline {\n  -ms-flex-align: baseline !important;\n  align-items: baseline !important; }\n\n.align-items-stretch {\n  -ms-flex-align: stretch !important;\n  align-items: stretch !important; }\n\n.align-content-start {\n  -ms-flex-line-pack: start !important;\n  align-content: flex-start !important; }\n\n.align-content-end {\n  -ms-flex-line-pack: end !important;\n  align-content: flex-end !important; }\n\n.align-content-center {\n  -ms-flex-line-pack: center !important;\n  align-content: center !important; }\n\n.align-content-between {\n  -ms-flex-line-pack: justify !important;\n  align-content: space-between !important; }\n\n.align-content-around {\n  -ms-flex-line-pack: distribute !important;\n  align-content: space-around !important; }\n\n.align-content-stretch {\n  -ms-flex-line-pack: stretch !important;\n  align-content: stretch !important; }\n\n.align-self-auto {\n  -ms-flex-item-align: auto !important;\n  align-self: auto !important; }\n\n.align-self-start {\n  -ms-flex-item-align: start !important;\n  align-self: flex-start !important; }\n\n.align-self-end {\n  -ms-flex-item-align: end !important;\n  align-self: flex-end !important; }\n\n.align-self-center {\n  -ms-flex-item-align: center !important;\n  align-self: center !important; }\n\n.align-self-baseline {\n  -ms-flex-item-align: baseline !important;\n  align-self: baseline !important; }\n\n.align-self-stretch {\n  -ms-flex-item-align: stretch !important;\n  align-self: stretch !important; }\n\n@media (min-width: 576px) {\n  .flex-sm-row {\n    -ms-flex-direction: row !important;\n    flex-direction: row !important; }\n  .flex-sm-column {\n    -ms-flex-direction: column !important;\n    flex-direction: column !important; }\n  .flex-sm-row-reverse {\n    -ms-flex-direction: row-reverse !important;\n    flex-direction: row-reverse !important; }\n  .flex-sm-column-reverse {\n    -ms-flex-direction: column-reverse !important;\n    flex-direction: column-reverse !important; }\n  .flex-sm-wrap {\n    -ms-flex-wrap: wrap !important;\n    flex-wrap: wrap !important; }\n  .flex-sm-nowrap {\n    -ms-flex-wrap: nowrap !important;\n    flex-wrap: nowrap !important; }\n  .flex-sm-wrap-reverse {\n    -ms-flex-wrap: wrap-reverse !important;\n    flex-wrap: wrap-reverse !important; }\n  .justify-content-sm-start {\n    -ms-flex-pack: start !important;\n    justify-content: flex-start !important; }\n  .justify-content-sm-end {\n    -ms-flex-pack: end !important;\n    justify-content: flex-end !important; }\n  .justify-content-sm-center {\n    -ms-flex-pack: center !important;\n    justify-content: center !important; }\n  .justify-content-sm-between {\n    -ms-flex-pack: justify !important;\n    justify-content: space-between !important; }\n  .justify-content-sm-around {\n    -ms-flex-pack: distribute !important;\n    justify-content: space-around !important; }\n  .align-items-sm-start {\n    -ms-flex-align: start !important;\n    align-items: flex-start !important; }\n  .align-items-sm-end {\n    -ms-flex-align: end !important;\n    align-items: flex-end !important; }\n  .align-items-sm-center {\n    -ms-flex-align: center !important;\n    align-items: center !important; }\n  .align-items-sm-baseline {\n    -ms-flex-align: baseline !important;\n    align-items: baseline !important; }\n  .align-items-sm-stretch {\n    -ms-flex-align: stretch !important;\n    align-items: stretch !important; }\n  .align-content-sm-start {\n    -ms-flex-line-pack: start !important;\n    align-content: flex-start !important; }\n  .align-content-sm-end {\n    -ms-flex-line-pack: end !important;\n    align-content: flex-end !important; }\n  .align-content-sm-center {\n    -ms-flex-line-pack: center !important;\n    align-content: center !important; }\n  .align-content-sm-between {\n    -ms-flex-line-pack: justify !important;\n    align-content: space-between !important; }\n  .align-content-sm-around {\n    -ms-flex-line-pack: distribute !important;\n    align-content: space-around !important; }\n  .align-content-sm-stretch {\n    -ms-flex-line-pack: stretch !important;\n    align-content: stretch !important; }\n  .align-self-sm-auto {\n    -ms-flex-item-align: auto !important;\n    align-self: auto !important; }\n  .align-self-sm-start {\n    -ms-flex-item-align: start !important;\n    align-self: flex-start !important; }\n  .align-self-sm-end {\n    -ms-flex-item-align: end !important;\n    align-self: flex-end !important; }\n  .align-self-sm-center {\n    -ms-flex-item-align: center !important;\n    align-self: center !important; }\n  .align-self-sm-baseline {\n    -ms-flex-item-align: baseline !important;\n    align-self: baseline !important; }\n  .align-self-sm-stretch {\n    -ms-flex-item-align: stretch !important;\n    align-self: stretch !important; } }\n\n@media (min-width: 768px) {\n  .flex-md-row {\n    -ms-flex-direction: row !important;\n    flex-direction: row !important; }\n  .flex-md-column {\n    -ms-flex-direction: column !important;\n    flex-direction: column !important; }\n  .flex-md-row-reverse {\n    -ms-flex-direction: row-reverse !important;\n    flex-direction: row-reverse !important; }\n  .flex-md-column-reverse {\n    -ms-flex-direction: column-reverse !important;\n    flex-direction: column-reverse !important; }\n  .flex-md-wrap {\n    -ms-flex-wrap: wrap !important;\n    flex-wrap: wrap !important; }\n  .flex-md-nowrap {\n    -ms-flex-wrap: nowrap !important;\n    flex-wrap: nowrap !important; }\n  .flex-md-wrap-reverse {\n    -ms-flex-wrap: wrap-reverse !important;\n    flex-wrap: wrap-reverse !important; }\n  .justify-content-md-start {\n    -ms-flex-pack: start !important;\n    justify-content: flex-start !important; }\n  .justify-content-md-end {\n    -ms-flex-pack: end !important;\n    justify-content: flex-end !important; }\n  .justify-content-md-center {\n    -ms-flex-pack: center !important;\n    justify-content: center !important; }\n  .justify-content-md-between {\n    -ms-flex-pack: justify !important;\n    justify-content: space-between !important; }\n  .justify-content-md-around {\n    -ms-flex-pack: distribute !important;\n    justify-content: space-around !important; }\n  .align-items-md-start {\n    -ms-flex-align: start !important;\n    align-items: flex-start !important; }\n  .align-items-md-end {\n    -ms-flex-align: end !important;\n    align-items: flex-end !important; }\n  .align-items-md-center {\n    -ms-flex-align: center !important;\n    align-items: center !important; }\n  .align-items-md-baseline {\n    -ms-flex-align: baseline !important;\n    align-items: baseline !important; }\n  .align-items-md-stretch {\n    -ms-flex-align: stretch !important;\n    align-items: stretch !important; }\n  .align-content-md-start {\n    -ms-flex-line-pack: start !important;\n    align-content: flex-start !important; }\n  .align-content-md-end {\n    -ms-flex-line-pack: end !important;\n    align-content: flex-end !important; }\n  .align-content-md-center {\n    -ms-flex-line-pack: center !important;\n    align-content: center !important; }\n  .align-content-md-between {\n    -ms-flex-line-pack: justify !important;\n    align-content: space-between !important; }\n  .align-content-md-around {\n    -ms-flex-line-pack: distribute !important;\n    align-content: space-around !important; }\n  .align-content-md-stretch {\n    -ms-flex-line-pack: stretch !important;\n    align-content: stretch !important; }\n  .align-self-md-auto {\n    -ms-flex-item-align: auto !important;\n    align-self: auto !important; }\n  .align-self-md-start {\n    -ms-flex-item-align: start !important;\n    align-self: flex-start !important; }\n  .align-self-md-end {\n    -ms-flex-item-align: end !important;\n    align-self: flex-end !important; }\n  .align-self-md-center {\n    -ms-flex-item-align: center !important;\n    align-self: center !important; }\n  .align-self-md-baseline {\n    -ms-flex-item-align: baseline !important;\n    align-self: baseline !important; }\n  .align-self-md-stretch {\n    -ms-flex-item-align: stretch !important;\n    align-self: stretch !important; } }\n\n@media (min-width: 992px) {\n  .flex-lg-row {\n    -ms-flex-direction: row !important;\n    flex-direction: row !important; }\n  .flex-lg-column {\n    -ms-flex-direction: column !important;\n    flex-direction: column !important; }\n  .flex-lg-row-reverse {\n    -ms-flex-direction: row-reverse !important;\n    flex-direction: row-reverse !important; }\n  .flex-lg-column-reverse {\n    -ms-flex-direction: column-reverse !important;\n    flex-direction: column-reverse !important; }\n  .flex-lg-wrap {\n    -ms-flex-wrap: wrap !important;\n    flex-wrap: wrap !important; }\n  .flex-lg-nowrap {\n    -ms-flex-wrap: nowrap !important;\n    flex-wrap: nowrap !important; }\n  .flex-lg-wrap-reverse {\n    -ms-flex-wrap: wrap-reverse !important;\n    flex-wrap: wrap-reverse !important; }\n  .justify-content-lg-start {\n    -ms-flex-pack: start !important;\n    justify-content: flex-start !important; }\n  .justify-content-lg-end {\n    -ms-flex-pack: end !important;\n    justify-content: flex-end !important; }\n  .justify-content-lg-center {\n    -ms-flex-pack: center !important;\n    justify-content: center !important; }\n  .justify-content-lg-between {\n    -ms-flex-pack: justify !important;\n    justify-content: space-between !important; }\n  .justify-content-lg-around {\n    -ms-flex-pack: distribute !important;\n    justify-content: space-around !important; }\n  .align-items-lg-start {\n    -ms-flex-align: start !important;\n    align-items: flex-start !important; }\n  .align-items-lg-end {\n    -ms-flex-align: end !important;\n    align-items: flex-end !important; }\n  .align-items-lg-center {\n    -ms-flex-align: center !important;\n    align-items: center !important; }\n  .align-items-lg-baseline {\n    -ms-flex-align: baseline !important;\n    align-items: baseline !important; }\n  .align-items-lg-stretch {\n    -ms-flex-align: stretch !important;\n    align-items: stretch !important; }\n  .align-content-lg-start {\n    -ms-flex-line-pack: start !important;\n    align-content: flex-start !important; }\n  .align-content-lg-end {\n    -ms-flex-line-pack: end !important;\n    align-content: flex-end !important; }\n  .align-content-lg-center {\n    -ms-flex-line-pack: center !important;\n    align-content: center !important; }\n  .align-content-lg-between {\n    -ms-flex-line-pack: justify !important;\n    align-content: space-between !important; }\n  .align-content-lg-around {\n    -ms-flex-line-pack: distribute !important;\n    align-content: space-around !important; }\n  .align-content-lg-stretch {\n    -ms-flex-line-pack: stretch !important;\n    align-content: stretch !important; }\n  .align-self-lg-auto {\n    -ms-flex-item-align: auto !important;\n    align-self: auto !important; }\n  .align-self-lg-start {\n    -ms-flex-item-align: start !important;\n    align-self: flex-start !important; }\n  .align-self-lg-end {\n    -ms-flex-item-align: end !important;\n    align-self: flex-end !important; }\n  .align-self-lg-center {\n    -ms-flex-item-align: center !important;\n    align-self: center !important; }\n  .align-self-lg-baseline {\n    -ms-flex-item-align: baseline !important;\n    align-self: baseline !important; }\n  .align-self-lg-stretch {\n    -ms-flex-item-align: stretch !important;\n    align-self: stretch !important; } }\n\n@media (min-width: 1200px) {\n  .flex-xl-row {\n    -ms-flex-direction: row !important;\n    flex-direction: row !important; }\n  .flex-xl-column {\n    -ms-flex-direction: column !important;\n    flex-direction: column !important; }\n  .flex-xl-row-reverse {\n    -ms-flex-direction: row-reverse !important;\n    flex-direction: row-reverse !important; }\n  .flex-xl-column-reverse {\n    -ms-flex-direction: column-reverse !important;\n    flex-direction: column-reverse !important; }\n  .flex-xl-wrap {\n    -ms-flex-wrap: wrap !important;\n    flex-wrap: wrap !important; }\n  .flex-xl-nowrap {\n    -ms-flex-wrap: nowrap !important;\n    flex-wrap: nowrap !important; }\n  .flex-xl-wrap-reverse {\n    -ms-flex-wrap: wrap-reverse !important;\n    flex-wrap: wrap-reverse !important; }\n  .justify-content-xl-start {\n    -ms-flex-pack: start !important;\n    justify-content: flex-start !important; }\n  .justify-content-xl-end {\n    -ms-flex-pack: end !important;\n    justify-content: flex-end !important; }\n  .justify-content-xl-center {\n    -ms-flex-pack: center !important;\n    justify-content: center !important; }\n  .justify-content-xl-between {\n    -ms-flex-pack: justify !important;\n    justify-content: space-between !important; }\n  .justify-content-xl-around {\n    -ms-flex-pack: distribute !important;\n    justify-content: space-around !important; }\n  .align-items-xl-start {\n    -ms-flex-align: start !important;\n    align-items: flex-start !important; }\n  .align-items-xl-end {\n    -ms-flex-align: end !important;\n    align-items: flex-end !important; }\n  .align-items-xl-center {\n    -ms-flex-align: center !important;\n    align-items: center !important; }\n  .align-items-xl-baseline {\n    -ms-flex-align: baseline !important;\n    align-items: baseline !important; }\n  .align-items-xl-stretch {\n    -ms-flex-align: stretch !important;\n    align-items: stretch !important; }\n  .align-content-xl-start {\n    -ms-flex-line-pack: start !important;\n    align-content: flex-start !important; }\n  .align-content-xl-end {\n    -ms-flex-line-pack: end !important;\n    align-content: flex-end !important; }\n  .align-content-xl-center {\n    -ms-flex-line-pack: center !important;\n    align-content: center !important; }\n  .align-content-xl-between {\n    -ms-flex-line-pack: justify !important;\n    align-content: space-between !important; }\n  .align-content-xl-around {\n    -ms-flex-line-pack: distribute !important;\n    align-content: space-around !important; }\n  .align-content-xl-stretch {\n    -ms-flex-line-pack: stretch !important;\n    align-content: stretch !important; }\n  .align-self-xl-auto {\n    -ms-flex-item-align: auto !important;\n    align-self: auto !important; }\n  .align-self-xl-start {\n    -ms-flex-item-align: start !important;\n    align-self: flex-start !important; }\n  .align-self-xl-end {\n    -ms-flex-item-align: end !important;\n    align-self: flex-end !important; }\n  .align-self-xl-center {\n    -ms-flex-item-align: center !important;\n    align-self: center !important; }\n  .align-self-xl-baseline {\n    -ms-flex-item-align: baseline !important;\n    align-self: baseline !important; }\n  .align-self-xl-stretch {\n    -ms-flex-item-align: stretch !important;\n    align-self: stretch !important; } }\n\n.float-left {\n  float: left !important; }\n\n.float-right {\n  float: right !important; }\n\n.float-none {\n  float: none !important; }\n\n@media (min-width: 576px) {\n  .float-sm-left {\n    float: left !important; }\n  .float-sm-right {\n    float: right !important; }\n  .float-sm-none {\n    float: none !important; } }\n\n@media (min-width: 768px) {\n  .float-md-left {\n    float: left !important; }\n  .float-md-right {\n    float: right !important; }\n  .float-md-none {\n    float: none !important; } }\n\n@media (min-width: 992px) {\n  .float-lg-left {\n    float: left !important; }\n  .float-lg-right {\n    float: right !important; }\n  .float-lg-none {\n    float: none !important; } }\n\n@media (min-width: 1200px) {\n  .float-xl-left {\n    float: left !important; }\n  .float-xl-right {\n    float: right !important; }\n  .float-xl-none {\n    float: none !important; } }\n\n.position-static {\n  position: static !important; }\n\n.position-relative {\n  position: relative !important; }\n\n.position-absolute {\n  position: absolute !important; }\n\n.position-fixed {\n  position: fixed !important; }\n\n.position-sticky {\n  position: -webkit-sticky !important;\n  position: sticky !important; }\n\n.fixed-top {\n  position: fixed;\n  top: 0;\n  right: 0;\n  left: 0;\n  z-index: 1030; }\n\n.fixed-bottom {\n  position: fixed;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1030; }\n\n@supports ((position: -webkit-sticky) or (position: sticky)) {\n  .sticky-top {\n    position: -webkit-sticky;\n    position: sticky;\n    top: 0;\n    z-index: 1020; } }\n\n.sr-only {\n  position: absolute;\n  width: 1px;\n  height: 1px;\n  padding: 0;\n  overflow: hidden;\n  clip: rect(0, 0, 0, 0);\n  white-space: nowrap;\n  -webkit-clip-path: inset(50%);\n  clip-path: inset(50%);\n  border: 0; }\n\n.sr-only-focusable:active, .sr-only-focusable:focus {\n  position: static;\n  width: auto;\n  height: auto;\n  overflow: visible;\n  clip: auto;\n  white-space: normal;\n  -webkit-clip-path: none;\n  clip-path: none; }\n\n.w-25 {\n  width: 25% !important; }\n\n.w-50 {\n  width: 50% !important; }\n\n.w-75 {\n  width: 75% !important; }\n\n.w-100 {\n  width: 100% !important; }\n\n.h-25 {\n  height: 25% !important; }\n\n.h-50 {\n  height: 50% !important; }\n\n.h-75 {\n  height: 75% !important; }\n\n.h-100 {\n  height: 100% !important; }\n\n.mw-100 {\n  max-width: 100% !important; }\n\n.mh-100 {\n  max-height: 100% !important; }\n\n.m-0 {\n  margin: 0 !important; }\n\n.mt-0,\n.my-0 {\n  margin-top: 0 !important; }\n\n.mr-0,\n.mx-0 {\n  margin-right: 0 !important; }\n\n.mb-0,\n.my-0 {\n  margin-bottom: 0 !important; }\n\n.ml-0,\n.mx-0 {\n  margin-left: 0 !important; }\n\n.m-1 {\n  margin: 0.25rem !important; }\n\n.mt-1,\n.my-1 {\n  margin-top: 0.25rem !important; }\n\n.mr-1,\n.mx-1 {\n  margin-right: 0.25rem !important; }\n\n.mb-1,\n.my-1 {\n  margin-bottom: 0.25rem !important; }\n\n.ml-1,\n.mx-1 {\n  margin-left: 0.25rem !important; }\n\n.m-2 {\n  margin: 0.5rem !important; }\n\n.mt-2,\n.my-2 {\n  margin-top: 0.5rem !important; }\n\n.mr-2,\n.mx-2 {\n  margin-right: 0.5rem !important; }\n\n.mb-2,\n.my-2 {\n  margin-bottom: 0.5rem !important; }\n\n.ml-2,\n.mx-2 {\n  margin-left: 0.5rem !important; }\n\n.m-3 {\n  margin: 1rem !important; }\n\n.mt-3,\n.my-3 {\n  margin-top: 1rem !important; }\n\n.mr-3,\n.mx-3 {\n  margin-right: 1rem !important; }\n\n.mb-3,\n.my-3 {\n  margin-bottom: 1rem !important; }\n\n.ml-3,\n.mx-3 {\n  margin-left: 1rem !important; }\n\n.m-4 {\n  margin: 1.5rem !important; }\n\n.mt-4,\n.my-4 {\n  margin-top: 1.5rem !important; }\n\n.mr-4,\n.mx-4 {\n  margin-right: 1.5rem !important; }\n\n.mb-4,\n.my-4 {\n  margin-bottom: 1.5rem !important; }\n\n.ml-4,\n.mx-4 {\n  margin-left: 1.5rem !important; }\n\n.m-5 {\n  margin: 3rem !important; }\n\n.mt-5,\n.my-5 {\n  margin-top: 3rem !important; }\n\n.mr-5,\n.mx-5 {\n  margin-right: 3rem !important; }\n\n.mb-5,\n.my-5 {\n  margin-bottom: 3rem !important; }\n\n.ml-5,\n.mx-5 {\n  margin-left: 3rem !important; }\n\n.p-0 {\n  padding: 0 !important; }\n\n.pt-0,\n.py-0 {\n  padding-top: 0 !important; }\n\n.pr-0,\n.px-0 {\n  padding-right: 0 !important; }\n\n.pb-0,\n.py-0 {\n  padding-bottom: 0 !important; }\n\n.pl-0,\n.px-0 {\n  padding-left: 0 !important; }\n\n.p-1 {\n  padding: 0.25rem !important; }\n\n.pt-1,\n.py-1 {\n  padding-top: 0.25rem !important; }\n\n.pr-1,\n.px-1 {\n  padding-right: 0.25rem !important; }\n\n.pb-1,\n.py-1 {\n  padding-bottom: 0.25rem !important; }\n\n.pl-1,\n.px-1 {\n  padding-left: 0.25rem !important; }\n\n.p-2 {\n  padding: 0.5rem !important; }\n\n.pt-2,\n.py-2 {\n  padding-top: 0.5rem !important; }\n\n.pr-2,\n.px-2 {\n  padding-right: 0.5rem !important; }\n\n.pb-2,\n.py-2 {\n  padding-bottom: 0.5rem !important; }\n\n.pl-2,\n.px-2 {\n  padding-left: 0.5rem !important; }\n\n.p-3 {\n  padding: 1rem !important; }\n\n.pt-3,\n.py-3 {\n  padding-top: 1rem !important; }\n\n.pr-3,\n.px-3 {\n  padding-right: 1rem !important; }\n\n.pb-3,\n.py-3 {\n  padding-bottom: 1rem !important; }\n\n.pl-3,\n.px-3 {\n  padding-left: 1rem !important; }\n\n.p-4 {\n  padding: 1.5rem !important; }\n\n.pt-4,\n.py-4 {\n  padding-top: 1.5rem !important; }\n\n.pr-4,\n.px-4 {\n  padding-right: 1.5rem !important; }\n\n.pb-4,\n.py-4 {\n  padding-bottom: 1.5rem !important; }\n\n.pl-4,\n.px-4 {\n  padding-left: 1.5rem !important; }\n\n.p-5 {\n  padding: 3rem !important; }\n\n.pt-5,\n.py-5 {\n  padding-top: 3rem !important; }\n\n.pr-5,\n.px-5 {\n  padding-right: 3rem !important; }\n\n.pb-5,\n.py-5 {\n  padding-bottom: 3rem !important; }\n\n.pl-5,\n.px-5 {\n  padding-left: 3rem !important; }\n\n.m-auto {\n  margin: auto !important; }\n\n.mt-auto,\n.my-auto {\n  margin-top: auto !important; }\n\n.mr-auto,\n.mx-auto {\n  margin-right: auto !important; }\n\n.mb-auto,\n.my-auto {\n  margin-bottom: auto !important; }\n\n.ml-auto,\n.mx-auto {\n  margin-left: auto !important; }\n\n@media (min-width: 576px) {\n  .m-sm-0 {\n    margin: 0 !important; }\n  .mt-sm-0,\n  .my-sm-0 {\n    margin-top: 0 !important; }\n  .mr-sm-0,\n  .mx-sm-0 {\n    margin-right: 0 !important; }\n  .mb-sm-0,\n  .my-sm-0 {\n    margin-bottom: 0 !important; }\n  .ml-sm-0,\n  .mx-sm-0 {\n    margin-left: 0 !important; }\n  .m-sm-1 {\n    margin: 0.25rem !important; }\n  .mt-sm-1,\n  .my-sm-1 {\n    margin-top: 0.25rem !important; }\n  .mr-sm-1,\n  .mx-sm-1 {\n    margin-right: 0.25rem !important; }\n  .mb-sm-1,\n  .my-sm-1 {\n    margin-bottom: 0.25rem !important; }\n  .ml-sm-1,\n  .mx-sm-1 {\n    margin-left: 0.25rem !important; }\n  .m-sm-2 {\n    margin: 0.5rem !important; }\n  .mt-sm-2,\n  .my-sm-2 {\n    margin-top: 0.5rem !important; }\n  .mr-sm-2,\n  .mx-sm-2 {\n    margin-right: 0.5rem !important; }\n  .mb-sm-2,\n  .my-sm-2 {\n    margin-bottom: 0.5rem !important; }\n  .ml-sm-2,\n  .mx-sm-2 {\n    margin-left: 0.5rem !important; }\n  .m-sm-3 {\n    margin: 1rem !important; }\n  .mt-sm-3,\n  .my-sm-3 {\n    margin-top: 1rem !important; }\n  .mr-sm-3,\n  .mx-sm-3 {\n    margin-right: 1rem !important; }\n  .mb-sm-3,\n  .my-sm-3 {\n    margin-bottom: 1rem !important; }\n  .ml-sm-3,\n  .mx-sm-3 {\n    margin-left: 1rem !important; }\n  .m-sm-4 {\n    margin: 1.5rem !important; }\n  .mt-sm-4,\n  .my-sm-4 {\n    margin-top: 1.5rem !important; }\n  .mr-sm-4,\n  .mx-sm-4 {\n    margin-right: 1.5rem !important; }\n  .mb-sm-4,\n  .my-sm-4 {\n    margin-bottom: 1.5rem !important; }\n  .ml-sm-4,\n  .mx-sm-4 {\n    margin-left: 1.5rem !important; }\n  .m-sm-5 {\n    margin: 3rem !important; }\n  .mt-sm-5,\n  .my-sm-5 {\n    margin-top: 3rem !important; }\n  .mr-sm-5,\n  .mx-sm-5 {\n    margin-right: 3rem !important; }\n  .mb-sm-5,\n  .my-sm-5 {\n    margin-bottom: 3rem !important; }\n  .ml-sm-5,\n  .mx-sm-5 {\n    margin-left: 3rem !important; }\n  .p-sm-0 {\n    padding: 0 !important; }\n  .pt-sm-0,\n  .py-sm-0 {\n    padding-top: 0 !important; }\n  .pr-sm-0,\n  .px-sm-0 {\n    padding-right: 0 !important; }\n  .pb-sm-0,\n  .py-sm-0 {\n    padding-bottom: 0 !important; }\n  .pl-sm-0,\n  .px-sm-0 {\n    padding-left: 0 !important; }\n  .p-sm-1 {\n    padding: 0.25rem !important; }\n  .pt-sm-1,\n  .py-sm-1 {\n    padding-top: 0.25rem !important; }\n  .pr-sm-1,\n  .px-sm-1 {\n    padding-right: 0.25rem !important; }\n  .pb-sm-1,\n  .py-sm-1 {\n    padding-bottom: 0.25rem !important; }\n  .pl-sm-1,\n  .px-sm-1 {\n    padding-left: 0.25rem !important; }\n  .p-sm-2 {\n    padding: 0.5rem !important; }\n  .pt-sm-2,\n  .py-sm-2 {\n    padding-top: 0.5rem !important; }\n  .pr-sm-2,\n  .px-sm-2 {\n    padding-right: 0.5rem !important; }\n  .pb-sm-2,\n  .py-sm-2 {\n    padding-bottom: 0.5rem !important; }\n  .pl-sm-2,\n  .px-sm-2 {\n    padding-left: 0.5rem !important; }\n  .p-sm-3 {\n    padding: 1rem !important; }\n  .pt-sm-3,\n  .py-sm-3 {\n    padding-top: 1rem !important; }\n  .pr-sm-3,\n  .px-sm-3 {\n    padding-right: 1rem !important; }\n  .pb-sm-3,\n  .py-sm-3 {\n    padding-bottom: 1rem !important; }\n  .pl-sm-3,\n  .px-sm-3 {\n    padding-left: 1rem !important; }\n  .p-sm-4 {\n    padding: 1.5rem !important; }\n  .pt-sm-4,\n  .py-sm-4 {\n    padding-top: 1.5rem !important; }\n  .pr-sm-4,\n  .px-sm-4 {\n    padding-right: 1.5rem !important; }\n  .pb-sm-4,\n  .py-sm-4 {\n    padding-bottom: 1.5rem !important; }\n  .pl-sm-4,\n  .px-sm-4 {\n    padding-left: 1.5rem !important; }\n  .p-sm-5 {\n    padding: 3rem !important; }\n  .pt-sm-5,\n  .py-sm-5 {\n    padding-top: 3rem !important; }\n  .pr-sm-5,\n  .px-sm-5 {\n    padding-right: 3rem !important; }\n  .pb-sm-5,\n  .py-sm-5 {\n    padding-bottom: 3rem !important; }\n  .pl-sm-5,\n  .px-sm-5 {\n    padding-left: 3rem !important; }\n  .m-sm-auto {\n    margin: auto !important; }\n  .mt-sm-auto,\n  .my-sm-auto {\n    margin-top: auto !important; }\n  .mr-sm-auto,\n  .mx-sm-auto {\n    margin-right: auto !important; }\n  .mb-sm-auto,\n  .my-sm-auto {\n    margin-bottom: auto !important; }\n  .ml-sm-auto,\n  .mx-sm-auto {\n    margin-left: auto !important; } }\n\n@media (min-width: 768px) {\n  .m-md-0 {\n    margin: 0 !important; }\n  .mt-md-0,\n  .my-md-0 {\n    margin-top: 0 !important; }\n  .mr-md-0,\n  .mx-md-0 {\n    margin-right: 0 !important; }\n  .mb-md-0,\n  .my-md-0 {\n    margin-bottom: 0 !important; }\n  .ml-md-0,\n  .mx-md-0 {\n    margin-left: 0 !important; }\n  .m-md-1 {\n    margin: 0.25rem !important; }\n  .mt-md-1,\n  .my-md-1 {\n    margin-top: 0.25rem !important; }\n  .mr-md-1,\n  .mx-md-1 {\n    margin-right: 0.25rem !important; }\n  .mb-md-1,\n  .my-md-1 {\n    margin-bottom: 0.25rem !important; }\n  .ml-md-1,\n  .mx-md-1 {\n    margin-left: 0.25rem !important; }\n  .m-md-2 {\n    margin: 0.5rem !important; }\n  .mt-md-2,\n  .my-md-2 {\n    margin-top: 0.5rem !important; }\n  .mr-md-2,\n  .mx-md-2 {\n    margin-right: 0.5rem !important; }\n  .mb-md-2,\n  .my-md-2 {\n    margin-bottom: 0.5rem !important; }\n  .ml-md-2,\n  .mx-md-2 {\n    margin-left: 0.5rem !important; }\n  .m-md-3 {\n    margin: 1rem !important; }\n  .mt-md-3,\n  .my-md-3 {\n    margin-top: 1rem !important; }\n  .mr-md-3,\n  .mx-md-3 {\n    margin-right: 1rem !important; }\n  .mb-md-3,\n  .my-md-3 {\n    margin-bottom: 1rem !important; }\n  .ml-md-3,\n  .mx-md-3 {\n    margin-left: 1rem !important; }\n  .m-md-4 {\n    margin: 1.5rem !important; }\n  .mt-md-4,\n  .my-md-4 {\n    margin-top: 1.5rem !important; }\n  .mr-md-4,\n  .mx-md-4 {\n    margin-right: 1.5rem !important; }\n  .mb-md-4,\n  .my-md-4 {\n    margin-bottom: 1.5rem !important; }\n  .ml-md-4,\n  .mx-md-4 {\n    margin-left: 1.5rem !important; }\n  .m-md-5 {\n    margin: 3rem !important; }\n  .mt-md-5,\n  .my-md-5 {\n    margin-top: 3rem !important; }\n  .mr-md-5,\n  .mx-md-5 {\n    margin-right: 3rem !important; }\n  .mb-md-5,\n  .my-md-5 {\n    margin-bottom: 3rem !important; }\n  .ml-md-5,\n  .mx-md-5 {\n    margin-left: 3rem !important; }\n  .p-md-0 {\n    padding: 0 !important; }\n  .pt-md-0,\n  .py-md-0 {\n    padding-top: 0 !important; }\n  .pr-md-0,\n  .px-md-0 {\n    padding-right: 0 !important; }\n  .pb-md-0,\n  .py-md-0 {\n    padding-bottom: 0 !important; }\n  .pl-md-0,\n  .px-md-0 {\n    padding-left: 0 !important; }\n  .p-md-1 {\n    padding: 0.25rem !important; }\n  .pt-md-1,\n  .py-md-1 {\n    padding-top: 0.25rem !important; }\n  .pr-md-1,\n  .px-md-1 {\n    padding-right: 0.25rem !important; }\n  .pb-md-1,\n  .py-md-1 {\n    padding-bottom: 0.25rem !important; }\n  .pl-md-1,\n  .px-md-1 {\n    padding-left: 0.25rem !important; }\n  .p-md-2 {\n    padding: 0.5rem !important; }\n  .pt-md-2,\n  .py-md-2 {\n    padding-top: 0.5rem !important; }\n  .pr-md-2,\n  .px-md-2 {\n    padding-right: 0.5rem !important; }\n  .pb-md-2,\n  .py-md-2 {\n    padding-bottom: 0.5rem !important; }\n  .pl-md-2,\n  .px-md-2 {\n    padding-left: 0.5rem !important; }\n  .p-md-3 {\n    padding: 1rem !important; }\n  .pt-md-3,\n  .py-md-3 {\n    padding-top: 1rem !important; }\n  .pr-md-3,\n  .px-md-3 {\n    padding-right: 1rem !important; }\n  .pb-md-3,\n  .py-md-3 {\n    padding-bottom: 1rem !important; }\n  .pl-md-3,\n  .px-md-3 {\n    padding-left: 1rem !important; }\n  .p-md-4 {\n    padding: 1.5rem !important; }\n  .pt-md-4,\n  .py-md-4 {\n    padding-top: 1.5rem !important; }\n  .pr-md-4,\n  .px-md-4 {\n    padding-right: 1.5rem !important; }\n  .pb-md-4,\n  .py-md-4 {\n    padding-bottom: 1.5rem !important; }\n  .pl-md-4,\n  .px-md-4 {\n    padding-left: 1.5rem !important; }\n  .p-md-5 {\n    padding: 3rem !important; }\n  .pt-md-5,\n  .py-md-5 {\n    padding-top: 3rem !important; }\n  .pr-md-5,\n  .px-md-5 {\n    padding-right: 3rem !important; }\n  .pb-md-5,\n  .py-md-5 {\n    padding-bottom: 3rem !important; }\n  .pl-md-5,\n  .px-md-5 {\n    padding-left: 3rem !important; }\n  .m-md-auto {\n    margin: auto !important; }\n  .mt-md-auto,\n  .my-md-auto {\n    margin-top: auto !important; }\n  .mr-md-auto,\n  .mx-md-auto {\n    margin-right: auto !important; }\n  .mb-md-auto,\n  .my-md-auto {\n    margin-bottom: auto !important; }\n  .ml-md-auto,\n  .mx-md-auto {\n    margin-left: auto !important; } }\n\n@media (min-width: 992px) {\n  .m-lg-0 {\n    margin: 0 !important; }\n  .mt-lg-0,\n  .my-lg-0 {\n    margin-top: 0 !important; }\n  .mr-lg-0,\n  .mx-lg-0 {\n    margin-right: 0 !important; }\n  .mb-lg-0,\n  .my-lg-0 {\n    margin-bottom: 0 !important; }\n  .ml-lg-0,\n  .mx-lg-0 {\n    margin-left: 0 !important; }\n  .m-lg-1 {\n    margin: 0.25rem !important; }\n  .mt-lg-1,\n  .my-lg-1 {\n    margin-top: 0.25rem !important; }\n  .mr-lg-1,\n  .mx-lg-1 {\n    margin-right: 0.25rem !important; }\n  .mb-lg-1,\n  .my-lg-1 {\n    margin-bottom: 0.25rem !important; }\n  .ml-lg-1,\n  .mx-lg-1 {\n    margin-left: 0.25rem !important; }\n  .m-lg-2 {\n    margin: 0.5rem !important; }\n  .mt-lg-2,\n  .my-lg-2 {\n    margin-top: 0.5rem !important; }\n  .mr-lg-2,\n  .mx-lg-2 {\n    margin-right: 0.5rem !important; }\n  .mb-lg-2,\n  .my-lg-2 {\n    margin-bottom: 0.5rem !important; }\n  .ml-lg-2,\n  .mx-lg-2 {\n    margin-left: 0.5rem !important; }\n  .m-lg-3 {\n    margin: 1rem !important; }\n  .mt-lg-3,\n  .my-lg-3 {\n    margin-top: 1rem !important; }\n  .mr-lg-3,\n  .mx-lg-3 {\n    margin-right: 1rem !important; }\n  .mb-lg-3,\n  .my-lg-3 {\n    margin-bottom: 1rem !important; }\n  .ml-lg-3,\n  .mx-lg-3 {\n    margin-left: 1rem !important; }\n  .m-lg-4 {\n    margin: 1.5rem !important; }\n  .mt-lg-4,\n  .my-lg-4 {\n    margin-top: 1.5rem !important; }\n  .mr-lg-4,\n  .mx-lg-4 {\n    margin-right: 1.5rem !important; }\n  .mb-lg-4,\n  .my-lg-4 {\n    margin-bottom: 1.5rem !important; }\n  .ml-lg-4,\n  .mx-lg-4 {\n    margin-left: 1.5rem !important; }\n  .m-lg-5 {\n    margin: 3rem !important; }\n  .mt-lg-5,\n  .my-lg-5 {\n    margin-top: 3rem !important; }\n  .mr-lg-5,\n  .mx-lg-5 {\n    margin-right: 3rem !important; }\n  .mb-lg-5,\n  .my-lg-5 {\n    margin-bottom: 3rem !important; }\n  .ml-lg-5,\n  .mx-lg-5 {\n    margin-left: 3rem !important; }\n  .p-lg-0 {\n    padding: 0 !important; }\n  .pt-lg-0,\n  .py-lg-0 {\n    padding-top: 0 !important; }\n  .pr-lg-0,\n  .px-lg-0 {\n    padding-right: 0 !important; }\n  .pb-lg-0,\n  .py-lg-0 {\n    padding-bottom: 0 !important; }\n  .pl-lg-0,\n  .px-lg-0 {\n    padding-left: 0 !important; }\n  .p-lg-1 {\n    padding: 0.25rem !important; }\n  .pt-lg-1,\n  .py-lg-1 {\n    padding-top: 0.25rem !important; }\n  .pr-lg-1,\n  .px-lg-1 {\n    padding-right: 0.25rem !important; }\n  .pb-lg-1,\n  .py-lg-1 {\n    padding-bottom: 0.25rem !important; }\n  .pl-lg-1,\n  .px-lg-1 {\n    padding-left: 0.25rem !important; }\n  .p-lg-2 {\n    padding: 0.5rem !important; }\n  .pt-lg-2,\n  .py-lg-2 {\n    padding-top: 0.5rem !important; }\n  .pr-lg-2,\n  .px-lg-2 {\n    padding-right: 0.5rem !important; }\n  .pb-lg-2,\n  .py-lg-2 {\n    padding-bottom: 0.5rem !important; }\n  .pl-lg-2,\n  .px-lg-2 {\n    padding-left: 0.5rem !important; }\n  .p-lg-3 {\n    padding: 1rem !important; }\n  .pt-lg-3,\n  .py-lg-3 {\n    padding-top: 1rem !important; }\n  .pr-lg-3,\n  .px-lg-3 {\n    padding-right: 1rem !important; }\n  .pb-lg-3,\n  .py-lg-3 {\n    padding-bottom: 1rem !important; }\n  .pl-lg-3,\n  .px-lg-3 {\n    padding-left: 1rem !important; }\n  .p-lg-4 {\n    padding: 1.5rem !important; }\n  .pt-lg-4,\n  .py-lg-4 {\n    padding-top: 1.5rem !important; }\n  .pr-lg-4,\n  .px-lg-4 {\n    padding-right: 1.5rem !important; }\n  .pb-lg-4,\n  .py-lg-4 {\n    padding-bottom: 1.5rem !important; }\n  .pl-lg-4,\n  .px-lg-4 {\n    padding-left: 1.5rem !important; }\n  .p-lg-5 {\n    padding: 3rem !important; }\n  .pt-lg-5,\n  .py-lg-5 {\n    padding-top: 3rem !important; }\n  .pr-lg-5,\n  .px-lg-5 {\n    padding-right: 3rem !important; }\n  .pb-lg-5,\n  .py-lg-5 {\n    padding-bottom: 3rem !important; }\n  .pl-lg-5,\n  .px-lg-5 {\n    padding-left: 3rem !important; }\n  .m-lg-auto {\n    margin: auto !important; }\n  .mt-lg-auto,\n  .my-lg-auto {\n    margin-top: auto !important; }\n  .mr-lg-auto,\n  .mx-lg-auto {\n    margin-right: auto !important; }\n  .mb-lg-auto,\n  .my-lg-auto {\n    margin-bottom: auto !important; }\n  .ml-lg-auto,\n  .mx-lg-auto {\n    margin-left: auto !important; } }\n\n@media (min-width: 1200px) {\n  .m-xl-0 {\n    margin: 0 !important; }\n  .mt-xl-0,\n  .my-xl-0 {\n    margin-top: 0 !important; }\n  .mr-xl-0,\n  .mx-xl-0 {\n    margin-right: 0 !important; }\n  .mb-xl-0,\n  .my-xl-0 {\n    margin-bottom: 0 !important; }\n  .ml-xl-0,\n  .mx-xl-0 {\n    margin-left: 0 !important; }\n  .m-xl-1 {\n    margin: 0.25rem !important; }\n  .mt-xl-1,\n  .my-xl-1 {\n    margin-top: 0.25rem !important; }\n  .mr-xl-1,\n  .mx-xl-1 {\n    margin-right: 0.25rem !important; }\n  .mb-xl-1,\n  .my-xl-1 {\n    margin-bottom: 0.25rem !important; }\n  .ml-xl-1,\n  .mx-xl-1 {\n    margin-left: 0.25rem !important; }\n  .m-xl-2 {\n    margin: 0.5rem !important; }\n  .mt-xl-2,\n  .my-xl-2 {\n    margin-top: 0.5rem !important; }\n  .mr-xl-2,\n  .mx-xl-2 {\n    margin-right: 0.5rem !important; }\n  .mb-xl-2,\n  .my-xl-2 {\n    margin-bottom: 0.5rem !important; }\n  .ml-xl-2,\n  .mx-xl-2 {\n    margin-left: 0.5rem !important; }\n  .m-xl-3 {\n    margin: 1rem !important; }\n  .mt-xl-3,\n  .my-xl-3 {\n    margin-top: 1rem !important; }\n  .mr-xl-3,\n  .mx-xl-3 {\n    margin-right: 1rem !important; }\n  .mb-xl-3,\n  .my-xl-3 {\n    margin-bottom: 1rem !important; }\n  .ml-xl-3,\n  .mx-xl-3 {\n    margin-left: 1rem !important; }\n  .m-xl-4 {\n    margin: 1.5rem !important; }\n  .mt-xl-4,\n  .my-xl-4 {\n    margin-top: 1.5rem !important; }\n  .mr-xl-4,\n  .mx-xl-4 {\n    margin-right: 1.5rem !important; }\n  .mb-xl-4,\n  .my-xl-4 {\n    margin-bottom: 1.5rem !important; }\n  .ml-xl-4,\n  .mx-xl-4 {\n    margin-left: 1.5rem !important; }\n  .m-xl-5 {\n    margin: 3rem !important; }\n  .mt-xl-5,\n  .my-xl-5 {\n    margin-top: 3rem !important; }\n  .mr-xl-5,\n  .mx-xl-5 {\n    margin-right: 3rem !important; }\n  .mb-xl-5,\n  .my-xl-5 {\n    margin-bottom: 3rem !important; }\n  .ml-xl-5,\n  .mx-xl-5 {\n    margin-left: 3rem !important; }\n  .p-xl-0 {\n    padding: 0 !important; }\n  .pt-xl-0,\n  .py-xl-0 {\n    padding-top: 0 !important; }\n  .pr-xl-0,\n  .px-xl-0 {\n    padding-right: 0 !important; }\n  .pb-xl-0,\n  .py-xl-0 {\n    padding-bottom: 0 !important; }\n  .pl-xl-0,\n  .px-xl-0 {\n    padding-left: 0 !important; }\n  .p-xl-1 {\n    padding: 0.25rem !important; }\n  .pt-xl-1,\n  .py-xl-1 {\n    padding-top: 0.25rem !important; }\n  .pr-xl-1,\n  .px-xl-1 {\n    padding-right: 0.25rem !important; }\n  .pb-xl-1,\n  .py-xl-1 {\n    padding-bottom: 0.25rem !important; }\n  .pl-xl-1,\n  .px-xl-1 {\n    padding-left: 0.25rem !important; }\n  .p-xl-2 {\n    padding: 0.5rem !important; }\n  .pt-xl-2,\n  .py-xl-2 {\n    padding-top: 0.5rem !important; }\n  .pr-xl-2,\n  .px-xl-2 {\n    padding-right: 0.5rem !important; }\n  .pb-xl-2,\n  .py-xl-2 {\n    padding-bottom: 0.5rem !important; }\n  .pl-xl-2,\n  .px-xl-2 {\n    padding-left: 0.5rem !important; }\n  .p-xl-3 {\n    padding: 1rem !important; }\n  .pt-xl-3,\n  .py-xl-3 {\n    padding-top: 1rem !important; }\n  .pr-xl-3,\n  .px-xl-3 {\n    padding-right: 1rem !important; }\n  .pb-xl-3,\n  .py-xl-3 {\n    padding-bottom: 1rem !important; }\n  .pl-xl-3,\n  .px-xl-3 {\n    padding-left: 1rem !important; }\n  .p-xl-4 {\n    padding: 1.5rem !important; }\n  .pt-xl-4,\n  .py-xl-4 {\n    padding-top: 1.5rem !important; }\n  .pr-xl-4,\n  .px-xl-4 {\n    padding-right: 1.5rem !important; }\n  .pb-xl-4,\n  .py-xl-4 {\n    padding-bottom: 1.5rem !important; }\n  .pl-xl-4,\n  .px-xl-4 {\n    padding-left: 1.5rem !important; }\n  .p-xl-5 {\n    padding: 3rem !important; }\n  .pt-xl-5,\n  .py-xl-5 {\n    padding-top: 3rem !important; }\n  .pr-xl-5,\n  .px-xl-5 {\n    padding-right: 3rem !important; }\n  .pb-xl-5,\n  .py-xl-5 {\n    padding-bottom: 3rem !important; }\n  .pl-xl-5,\n  .px-xl-5 {\n    padding-left: 3rem !important; }\n  .m-xl-auto {\n    margin: auto !important; }\n  .mt-xl-auto,\n  .my-xl-auto {\n    margin-top: auto !important; }\n  .mr-xl-auto,\n  .mx-xl-auto {\n    margin-right: auto !important; }\n  .mb-xl-auto,\n  .my-xl-auto {\n    margin-bottom: auto !important; }\n  .ml-xl-auto,\n  .mx-xl-auto {\n    margin-left: auto !important; } }\n\n.text-justify {\n  text-align: justify !important; }\n\n.text-nowrap {\n  white-space: nowrap !important; }\n\n.text-truncate {\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap; }\n\n.text-left {\n  text-align: left !important; }\n\n.text-right {\n  text-align: right !important; }\n\n.text-center {\n  text-align: center !important; }\n\n@media (min-width: 576px) {\n  .text-sm-left {\n    text-align: left !important; }\n  .text-sm-right {\n    text-align: right !important; }\n  .text-sm-center {\n    text-align: center !important; } }\n\n@media (min-width: 768px) {\n  .text-md-left {\n    text-align: left !important; }\n  .text-md-right {\n    text-align: right !important; }\n  .text-md-center {\n    text-align: center !important; } }\n\n@media (min-width: 992px) {\n  .text-lg-left {\n    text-align: left !important; }\n  .text-lg-right {\n    text-align: right !important; }\n  .text-lg-center {\n    text-align: center !important; } }\n\n@media (min-width: 1200px) {\n  .text-xl-left {\n    text-align: left !important; }\n  .text-xl-right {\n    text-align: right !important; }\n  .text-xl-center {\n    text-align: center !important; } }\n\n.text-lowercase {\n  text-transform: lowercase !important; }\n\n.text-uppercase {\n  text-transform: uppercase !important; }\n\n.text-capitalize {\n  text-transform: capitalize !important; }\n\n.font-weight-light {\n  font-weight: 300 !important; }\n\n.font-weight-normal {\n  font-weight: 400 !important; }\n\n.font-weight-bold {\n  font-weight: 700 !important; }\n\n.font-italic {\n  font-style: italic !important; }\n\n.text-white {\n  color: #fff !important; }\n\n.text-primary {\n  color: #20a8d8 !important; }\n\na.text-primary:focus, a.text-primary:hover {\n  color: #1985ac !important; }\n\n.text-secondary {\n  color: #a4b7c1 !important; }\n\na.text-secondary:focus, a.text-secondary:hover {\n  color: #869fac !important; }\n\n.text-success {\n  color: #4dbd74 !important; }\n\na.text-success:focus, a.text-success:hover {\n  color: #3a9d5d !important; }\n\n.text-info {\n  color: #63c2de !important; }\n\na.text-info:focus, a.text-info:hover {\n  color: #39b2d5 !important; }\n\n.text-warning {\n  color: #ffc107 !important; }\n\na.text-warning:focus, a.text-warning:hover {\n  color: #d39e00 !important; }\n\n.text-danger {\n  color: #f86c6b !important; }\n\na.text-danger:focus, a.text-danger:hover {\n  color: #f63c3a !important; }\n\n.text-light {\n  color: #f0f3f5 !important; }\n\na.text-light:focus, a.text-light:hover {\n  color: #d1dbe1 !important; }\n\n.text-dark {\n  color: #29363d !important; }\n\na.text-dark:focus, a.text-dark:hover {\n  color: #151b1f !important; }\n\n.text-muted {\n  color: #536c79 !important; }\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.visible {\n  visibility: visible !important; }\n\n.invisible {\n  visibility: hidden !important; }\n\nbody {\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-font-smoothing: antialiased; }\n\n.font-xs {\n  font-size: .75rem !important; }\n\n.font-sm {\n  font-size: .85rem !important; }\n\n.font-lg {\n  font-size: 1rem !important; }\n\n.font-xl {\n  font-size: 1.25rem !important; }\n\n.font-2xl {\n  font-size: 1.5rem !important; }\n\n.font-3xl {\n  font-size: 1.75rem !important; }\n\n.font-4xl {\n  font-size: 2rem !important; }\n\n.font-5xl {\n  font-size: 2.5rem !important; }\n\n.animated {\n  -webkit-animation-duration: 1s;\n  animation-duration: 1s; }\n\n.animated.infinite {\n  -webkit-animation-iteration-count: infinite;\n  animation-iteration-count: infinite; }\n\n.animated.hinge {\n  -webkit-animation-duration: 2s;\n  animation-duration: 2s; }\n\n@-webkit-keyframes fadeIn {\n  from {\n    opacity: 0; }\n  to {\n    opacity: 1; } }\n\n@keyframes fadeIn {\n  from {\n    opacity: 0; }\n  to {\n    opacity: 1; } }\n\n.fadeIn {\n  -webkit-animation-name: fadeIn;\n  animation-name: fadeIn; }\n\n.aside-menu {\n  z-index: 1019;\n  width: 250px;\n  color: #29363d;\n  background: #fff;\n  border-left: 1px solid #c2cfd6; }\n.aside-menu .nav-tabs {\n  border-color: #c2cfd6; }\n.aside-menu .nav-tabs .nav-link, .aside-menu .nav-tabs .navbar .dropdown-toggle, .navbar .aside-menu .nav-tabs .dropdown-toggle {\n  padding: 0.75rem 1rem;\n  color: #151b1e;\n  border-top: 0; }\n.aside-menu .nav-tabs .nav-link.active, .aside-menu .nav-tabs .navbar .active.dropdown-toggle, .navbar .aside-menu .nav-tabs .active.dropdown-toggle {\n  color: #20a8d8;\n  border-right-color: #c2cfd6;\n  border-left-color: #c2cfd6; }\n.aside-menu .nav-tabs .nav-item:first-child .nav-link, .aside-menu .nav-tabs .nav-item:first-child .navbar .dropdown-toggle, .navbar .aside-menu .nav-tabs .nav-item:first-child .dropdown-toggle {\n  border-left: 0; }\n.aside-menu .tab-content {\n  position: relative;\n  overflow-x: hidden;\n  overflow-y: auto;\n  border: 0;\n  border-top: 1px solid #c2cfd6;\n  -ms-overflow-style: -ms-autohiding-scrollbar; }\n.aside-menu .tab-content::-webkit-scrollbar {\n  width: 10px;\n  margin-left: -10px;\n  -webkit-appearance: none; }\n.aside-menu .tab-content::-webkit-scrollbar-track {\n  background-color: white;\n  border-right: 1px solid #f2f2f2;\n  border-left: 1px solid #f2f2f2; }\n.aside-menu .tab-content::-webkit-scrollbar-thumb {\n  height: 50px;\n  background-color: #e6e6e6;\n  background-clip: content-box;\n  border-color: transparent;\n  border-style: solid;\n  border-width: 1px 2px; }\n.aside-menu .tab-content .tab-pane {\n  padding: 0; }\n\n.img-avatar {\n  border-radius: 50em; }\n\n.avatar {\n  position: relative;\n  display: inline-block;\n  width: 36px; }\n.avatar .img-avatar {\n  width: 36px;\n  height: 36px; }\n.avatar .avatar-status {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  display: block;\n  width: 10px;\n  height: 10px;\n  border: 1px solid #fff;\n  border-radius: 50em; }\n\n.avatar.avatar-xs {\n  position: relative;\n  display: inline-block;\n  width: 20px; }\n.avatar.avatar-xs .img-avatar {\n  width: 20px;\n  height: 20px; }\n.avatar.avatar-xs .avatar-status {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  display: block;\n  width: 8px;\n  height: 8px;\n  border: 1px solid #fff;\n  border-radius: 50em; }\n\n.avatar.avatar-sm {\n  position: relative;\n  display: inline-block;\n  width: 24px; }\n.avatar.avatar-sm .img-avatar {\n  width: 24px;\n  height: 24px; }\n.avatar.avatar-sm .avatar-status {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  display: block;\n  width: 8px;\n  height: 8px;\n  border: 1px solid #fff;\n  border-radius: 50em; }\n\n.avatar.avatar-lg {\n  position: relative;\n  display: inline-block;\n  width: 72px; }\n.avatar.avatar-lg .img-avatar {\n  width: 72px;\n  height: 72px; }\n.avatar.avatar-lg .avatar-status {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  display: block;\n  width: 12px;\n  height: 12px;\n  border: 1px solid #fff;\n  border-radius: 50em; }\n\n.avatars-stack .avatar.avatar-xs {\n  margin-right: -10px; }\n\n.avatars-stack .avatar {\n  margin-right: -15px;\n  transition: margin-left 0.25s, margin-right 0.25s; }\n.avatars-stack .avatar:hover {\n  margin-right: 0 !important; }\n\n.badge-pill {\n  border-radius: 10rem; }\n\n.breadcrumb-menu {\n  margin-left: auto; }\n.breadcrumb-menu::before {\n  display: none; }\n.breadcrumb-menu .btn-group {\n  vertical-align: top; }\n.breadcrumb-menu .btn {\n  padding: 0 0.75rem;\n  color: #536c79;\n  vertical-align: top;\n  border: 0; }\n.breadcrumb-menu .btn:hover, .breadcrumb-menu .btn.active {\n  color: #151b1e;\n  background: transparent; }\n.breadcrumb-menu .open .btn {\n  color: #151b1e;\n  background: transparent; }\n.breadcrumb-menu .dropdown-menu {\n  min-width: 180px;\n  line-height: 1.5; }\n\n.breadcrumb {\n  position: relative;\n  border-bottom: 1px solid #c2cfd6; }\n\nbutton {\n  cursor: pointer; }\n\n.btn .badge {\n  position: absolute;\n  top: 2px;\n  right: 6px;\n  font-size: 9px; }\n\n.btn-transparent {\n  color: #fff;\n  background-color: transparent;\n  border-color: transparent; }\n\n.btn [class^=\"icon-\"], .btn [class*=\" icon-\"] {\n  display: inline-block;\n  margin-top: -2px;\n  vertical-align: middle; }\n\n.btn-facebook,\n.btn-twitter,\n.btn-linkedin,\n.btn-flickr,\n.btn-tumblr,\n.btn-xing,\n.btn-github,\n.btn-html5,\n.btn-openid,\n.btn-stack-overflow,\n.btn-youtube,\n.btn-css3,\n.btn-dribbble,\n.btn-google-plus,\n.btn-instagram,\n.btn-pinterest,\n.btn-vk,\n.btn-yahoo,\n.btn-behance,\n.btn-dropbox,\n.btn-reddit,\n.btn-spotify,\n.btn-vine,\n.btn-foursquare,\n.btn-vimeo {\n  position: relative;\n  overflow: hidden;\n  color: #fff !important;\n  text-align: center;\n  padding: 0.375rem 0.75rem;\n  font-size: 0.875rem;\n  line-height: 1.5;\n  border: 0; }\n.btn-facebook::before,\n.btn-twitter::before,\n.btn-linkedin::before,\n.btn-flickr::before,\n.btn-tumblr::before,\n.btn-xing::before,\n.btn-github::before,\n.btn-html5::before,\n.btn-openid::before,\n.btn-stack-overflow::before,\n.btn-youtube::before,\n.btn-css3::before,\n.btn-dribbble::before,\n.btn-google-plus::before,\n.btn-instagram::before,\n.btn-pinterest::before,\n.btn-vk::before,\n.btn-yahoo::before,\n.btn-behance::before,\n.btn-dropbox::before,\n.btn-reddit::before,\n.btn-spotify::before,\n.btn-vine::before,\n.btn-foursquare::before,\n.btn-vimeo::before {\n  position: absolute;\n  top: 0;\n  left: 0;\n  display: block;\n  font-family: \"FontAwesome\";\n  font-style: normal;\n  font-weight: normal;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-font-smoothing: antialiased; }\n.btn-facebook:hover,\n.btn-twitter:hover,\n.btn-linkedin:hover,\n.btn-flickr:hover,\n.btn-tumblr:hover,\n.btn-xing:hover,\n.btn-github:hover,\n.btn-html5:hover,\n.btn-openid:hover,\n.btn-stack-overflow:hover,\n.btn-youtube:hover,\n.btn-css3:hover,\n.btn-dribbble:hover,\n.btn-google-plus:hover,\n.btn-instagram:hover,\n.btn-pinterest:hover,\n.btn-vk:hover,\n.btn-yahoo:hover,\n.btn-behance:hover,\n.btn-dropbox:hover,\n.btn-reddit:hover,\n.btn-spotify:hover,\n.btn-vine:hover,\n.btn-foursquare:hover,\n.btn-vimeo:hover {\n  color: #fff; }\n.btn-facebook.icon span,\n.btn-twitter.icon span,\n.btn-linkedin.icon span,\n.btn-flickr.icon span,\n.btn-tumblr.icon span,\n.btn-xing.icon span,\n.btn-github.icon span,\n.btn-html5.icon span,\n.btn-openid.icon span,\n.btn-stack-overflow.icon span,\n.btn-youtube.icon span,\n.btn-css3.icon span,\n.btn-dribbble.icon span,\n.btn-google-plus.icon span,\n.btn-instagram.icon span,\n.btn-pinterest.icon span,\n.btn-vk.icon span,\n.btn-yahoo.icon span,\n.btn-behance.icon span,\n.btn-dropbox.icon span,\n.btn-reddit.icon span,\n.btn-spotify.icon span,\n.btn-vine.icon span,\n.btn-foursquare.icon span,\n.btn-vimeo.icon span {\n  display: none; }\n.btn-facebook.text::before,\n.btn-twitter.text::before,\n.btn-linkedin.text::before,\n.btn-flickr.text::before,\n.btn-tumblr.text::before,\n.btn-xing.text::before,\n.btn-github.text::before,\n.btn-html5.text::before,\n.btn-openid.text::before,\n.btn-stack-overflow.text::before,\n.btn-youtube.text::before,\n.btn-css3.text::before,\n.btn-dribbble.text::before,\n.btn-google-plus.text::before,\n.btn-instagram.text::before,\n.btn-pinterest.text::before,\n.btn-vk.text::before,\n.btn-yahoo.text::before,\n.btn-behance.text::before,\n.btn-dropbox.text::before,\n.btn-reddit.text::before,\n.btn-spotify.text::before,\n.btn-vine.text::before,\n.btn-foursquare.text::before,\n.btn-vimeo.text::before {\n  display: none; }\n.btn-facebook.text span,\n.btn-twitter.text span,\n.btn-linkedin.text span,\n.btn-flickr.text span,\n.btn-tumblr.text span,\n.btn-xing.text span,\n.btn-github.text span,\n.btn-html5.text span,\n.btn-openid.text span,\n.btn-stack-overflow.text span,\n.btn-youtube.text span,\n.btn-css3.text span,\n.btn-dribbble.text span,\n.btn-google-plus.text span,\n.btn-instagram.text span,\n.btn-pinterest.text span,\n.btn-vk.text span,\n.btn-yahoo.text span,\n.btn-behance.text span,\n.btn-dropbox.text span,\n.btn-reddit.text span,\n.btn-spotify.text span,\n.btn-vine.text span,\n.btn-foursquare.text span,\n.btn-vimeo.text span {\n  margin-left: 0 !important; }\n.btn-facebook::before,\n.btn-twitter::before,\n.btn-linkedin::before,\n.btn-flickr::before,\n.btn-tumblr::before,\n.btn-xing::before,\n.btn-github::before,\n.btn-html5::before,\n.btn-openid::before,\n.btn-stack-overflow::before,\n.btn-youtube::before,\n.btn-css3::before,\n.btn-dribbble::before,\n.btn-google-plus::before,\n.btn-instagram::before,\n.btn-pinterest::before,\n.btn-vk::before,\n.btn-yahoo::before,\n.btn-behance::before,\n.btn-dropbox::before,\n.btn-reddit::before,\n.btn-spotify::before,\n.btn-vine::before,\n.btn-foursquare::before,\n.btn-vimeo::before {\n  width: 2.0625rem;\n  height: 2.0625rem;\n  padding: 0.375rem 0;\n  font-size: 0.875rem;\n  line-height: 1.5; }\n.btn-facebook span,\n.btn-twitter span,\n.btn-linkedin span,\n.btn-flickr span,\n.btn-tumblr span,\n.btn-xing span,\n.btn-github span,\n.btn-html5 span,\n.btn-openid span,\n.btn-stack-overflow span,\n.btn-youtube span,\n.btn-css3 span,\n.btn-dribbble span,\n.btn-google-plus span,\n.btn-instagram span,\n.btn-pinterest span,\n.btn-vk span,\n.btn-yahoo span,\n.btn-behance span,\n.btn-dropbox span,\n.btn-reddit span,\n.btn-spotify span,\n.btn-vine span,\n.btn-foursquare span,\n.btn-vimeo span {\n  margin-left: 2.0625rem; }\n.btn-facebook.icon,\n.btn-twitter.icon,\n.btn-linkedin.icon,\n.btn-flickr.icon,\n.btn-tumblr.icon,\n.btn-xing.icon,\n.btn-github.icon,\n.btn-html5.icon,\n.btn-openid.icon,\n.btn-stack-overflow.icon,\n.btn-youtube.icon,\n.btn-css3.icon,\n.btn-dribbble.icon,\n.btn-google-plus.icon,\n.btn-instagram.icon,\n.btn-pinterest.icon,\n.btn-vk.icon,\n.btn-yahoo.icon,\n.btn-behance.icon,\n.btn-dropbox.icon,\n.btn-reddit.icon,\n.btn-spotify.icon,\n.btn-vine.icon,\n.btn-foursquare.icon,\n.btn-vimeo.icon {\n  width: 2.0625rem;\n  height: 2.0625rem; }\n.btn-facebook.btn-lg, .btn-group-lg > .btn-facebook.btn,\n.btn-twitter.btn-lg,\n.btn-group-lg > .btn-twitter.btn,\n.btn-linkedin.btn-lg,\n.btn-group-lg > .btn-linkedin.btn,\n.btn-flickr.btn-lg,\n.btn-group-lg > .btn-flickr.btn,\n.btn-tumblr.btn-lg,\n.btn-group-lg > .btn-tumblr.btn,\n.btn-xing.btn-lg,\n.btn-group-lg > .btn-xing.btn,\n.btn-github.btn-lg,\n.btn-group-lg > .btn-github.btn,\n.btn-html5.btn-lg,\n.btn-group-lg > .btn-html5.btn,\n.btn-openid.btn-lg,\n.btn-group-lg > .btn-openid.btn,\n.btn-stack-overflow.btn-lg,\n.btn-group-lg > .btn-stack-overflow.btn,\n.btn-youtube.btn-lg,\n.btn-group-lg > .btn-youtube.btn,\n.btn-css3.btn-lg,\n.btn-group-lg > .btn-css3.btn,\n.btn-dribbble.btn-lg,\n.btn-group-lg > .btn-dribbble.btn,\n.btn-google-plus.btn-lg,\n.btn-group-lg > .btn-google-plus.btn,\n.btn-instagram.btn-lg,\n.btn-group-lg > .btn-instagram.btn,\n.btn-pinterest.btn-lg,\n.btn-group-lg > .btn-pinterest.btn,\n.btn-vk.btn-lg,\n.btn-group-lg > .btn-vk.btn,\n.btn-yahoo.btn-lg,\n.btn-group-lg > .btn-yahoo.btn,\n.btn-behance.btn-lg,\n.btn-group-lg > .btn-behance.btn,\n.btn-dropbox.btn-lg,\n.btn-group-lg > .btn-dropbox.btn,\n.btn-reddit.btn-lg,\n.btn-group-lg > .btn-reddit.btn,\n.btn-spotify.btn-lg,\n.btn-group-lg > .btn-spotify.btn,\n.btn-vine.btn-lg,\n.btn-group-lg > .btn-vine.btn,\n.btn-foursquare.btn-lg,\n.btn-group-lg > .btn-foursquare.btn,\n.btn-vimeo.btn-lg,\n.btn-group-lg > .btn-vimeo.btn {\n  padding: 0.5rem 1rem;\n  font-size: 1.09375rem;\n  line-height: 1.5;\n  border: 0; }\n.btn-facebook.btn-lg::before, .btn-group-lg > .btn-facebook.btn::before,\n.btn-twitter.btn-lg::before,\n.btn-group-lg > .btn-twitter.btn::before,\n.btn-linkedin.btn-lg::before,\n.btn-group-lg > .btn-linkedin.btn::before,\n.btn-flickr.btn-lg::before,\n.btn-group-lg > .btn-flickr.btn::before,\n.btn-tumblr.btn-lg::before,\n.btn-group-lg > .btn-tumblr.btn::before,\n.btn-xing.btn-lg::before,\n.btn-group-lg > .btn-xing.btn::before,\n.btn-github.btn-lg::before,\n.btn-group-lg > .btn-github.btn::before,\n.btn-html5.btn-lg::before,\n.btn-group-lg > .btn-html5.btn::before,\n.btn-openid.btn-lg::before,\n.btn-group-lg > .btn-openid.btn::before,\n.btn-stack-overflow.btn-lg::before,\n.btn-group-lg > .btn-stack-overflow.btn::before,\n.btn-youtube.btn-lg::before,\n.btn-group-lg > .btn-youtube.btn::before,\n.btn-css3.btn-lg::before,\n.btn-group-lg > .btn-css3.btn::before,\n.btn-dribbble.btn-lg::before,\n.btn-group-lg > .btn-dribbble.btn::before,\n.btn-google-plus.btn-lg::before,\n.btn-group-lg > .btn-google-plus.btn::before,\n.btn-instagram.btn-lg::before,\n.btn-group-lg > .btn-instagram.btn::before,\n.btn-pinterest.btn-lg::before,\n.btn-group-lg > .btn-pinterest.btn::before,\n.btn-vk.btn-lg::before,\n.btn-group-lg > .btn-vk.btn::before,\n.btn-yahoo.btn-lg::before,\n.btn-group-lg > .btn-yahoo.btn::before,\n.btn-behance.btn-lg::before,\n.btn-group-lg > .btn-behance.btn::before,\n.btn-dropbox.btn-lg::before,\n.btn-group-lg > .btn-dropbox.btn::before,\n.btn-reddit.btn-lg::before,\n.btn-group-lg > .btn-reddit.btn::before,\n.btn-spotify.btn-lg::before,\n.btn-group-lg > .btn-spotify.btn::before,\n.btn-vine.btn-lg::before,\n.btn-group-lg > .btn-vine.btn::before,\n.btn-foursquare.btn-lg::before,\n.btn-group-lg > .btn-foursquare.btn::before,\n.btn-vimeo.btn-lg::before,\n.btn-group-lg > .btn-vimeo.btn::before {\n  width: 2.64063rem;\n  height: 2.64063rem;\n  padding: 0.5rem 0;\n  font-size: 1.09375rem;\n  line-height: 1.5; }\n.btn-facebook.btn-lg span, .btn-group-lg > .btn-facebook.btn span,\n.btn-twitter.btn-lg span, .btn-group-lg > .btn-twitter.btn span,\n.btn-linkedin.btn-lg span, .btn-group-lg > .btn-linkedin.btn span,\n.btn-flickr.btn-lg span, .btn-group-lg > .btn-flickr.btn span,\n.btn-tumblr.btn-lg span, .btn-group-lg > .btn-tumblr.btn span,\n.btn-xing.btn-lg span, .btn-group-lg > .btn-xing.btn span,\n.btn-github.btn-lg span, .btn-group-lg > .btn-github.btn span,\n.btn-html5.btn-lg span, .btn-group-lg > .btn-html5.btn span,\n.btn-openid.btn-lg span, .btn-group-lg > .btn-openid.btn span,\n.btn-stack-overflow.btn-lg span, .btn-group-lg > .btn-stack-overflow.btn span,\n.btn-youtube.btn-lg span, .btn-group-lg > .btn-youtube.btn span,\n.btn-css3.btn-lg span, .btn-group-lg > .btn-css3.btn span,\n.btn-dribbble.btn-lg span, .btn-group-lg > .btn-dribbble.btn span,\n.btn-google-plus.btn-lg span, .btn-group-lg > .btn-google-plus.btn span,\n.btn-instagram.btn-lg span, .btn-group-lg > .btn-instagram.btn span,\n.btn-pinterest.btn-lg span, .btn-group-lg > .btn-pinterest.btn span,\n.btn-vk.btn-lg span, .btn-group-lg > .btn-vk.btn span,\n.btn-yahoo.btn-lg span, .btn-group-lg > .btn-yahoo.btn span,\n.btn-behance.btn-lg span, .btn-group-lg > .btn-behance.btn span,\n.btn-dropbox.btn-lg span, .btn-group-lg > .btn-dropbox.btn span,\n.btn-reddit.btn-lg span, .btn-group-lg > .btn-reddit.btn span,\n.btn-spotify.btn-lg span, .btn-group-lg > .btn-spotify.btn span,\n.btn-vine.btn-lg span, .btn-group-lg > .btn-vine.btn span,\n.btn-foursquare.btn-lg span, .btn-group-lg > .btn-foursquare.btn span,\n.btn-vimeo.btn-lg span, .btn-group-lg > .btn-vimeo.btn span {\n  margin-left: 2.64063rem; }\n.btn-facebook.btn-lg.icon, .btn-group-lg > .btn-facebook.icon.btn,\n.btn-twitter.btn-lg.icon,\n.btn-group-lg > .btn-twitter.icon.btn,\n.btn-linkedin.btn-lg.icon,\n.btn-group-lg > .btn-linkedin.icon.btn,\n.btn-flickr.btn-lg.icon,\n.btn-group-lg > .btn-flickr.icon.btn,\n.btn-tumblr.btn-lg.icon,\n.btn-group-lg > .btn-tumblr.icon.btn,\n.btn-xing.btn-lg.icon,\n.btn-group-lg > .btn-xing.icon.btn,\n.btn-github.btn-lg.icon,\n.btn-group-lg > .btn-github.icon.btn,\n.btn-html5.btn-lg.icon,\n.btn-group-lg > .btn-html5.icon.btn,\n.btn-openid.btn-lg.icon,\n.btn-group-lg > .btn-openid.icon.btn,\n.btn-stack-overflow.btn-lg.icon,\n.btn-group-lg > .btn-stack-overflow.icon.btn,\n.btn-youtube.btn-lg.icon,\n.btn-group-lg > .btn-youtube.icon.btn,\n.btn-css3.btn-lg.icon,\n.btn-group-lg > .btn-css3.icon.btn,\n.btn-dribbble.btn-lg.icon,\n.btn-group-lg > .btn-dribbble.icon.btn,\n.btn-google-plus.btn-lg.icon,\n.btn-group-lg > .btn-google-plus.icon.btn,\n.btn-instagram.btn-lg.icon,\n.btn-group-lg > .btn-instagram.icon.btn,\n.btn-pinterest.btn-lg.icon,\n.btn-group-lg > .btn-pinterest.icon.btn,\n.btn-vk.btn-lg.icon,\n.btn-group-lg > .btn-vk.icon.btn,\n.btn-yahoo.btn-lg.icon,\n.btn-group-lg > .btn-yahoo.icon.btn,\n.btn-behance.btn-lg.icon,\n.btn-group-lg > .btn-behance.icon.btn,\n.btn-dropbox.btn-lg.icon,\n.btn-group-lg > .btn-dropbox.icon.btn,\n.btn-reddit.btn-lg.icon,\n.btn-group-lg > .btn-reddit.icon.btn,\n.btn-spotify.btn-lg.icon,\n.btn-group-lg > .btn-spotify.icon.btn,\n.btn-vine.btn-lg.icon,\n.btn-group-lg > .btn-vine.icon.btn,\n.btn-foursquare.btn-lg.icon,\n.btn-group-lg > .btn-foursquare.icon.btn,\n.btn-vimeo.btn-lg.icon,\n.btn-group-lg > .btn-vimeo.icon.btn {\n  width: 2.64063rem;\n  height: 2.64063rem; }\n.btn-facebook.btn-sm, .btn-group-sm > .btn-facebook.btn,\n.btn-twitter.btn-sm,\n.btn-group-sm > .btn-twitter.btn,\n.btn-linkedin.btn-sm,\n.btn-group-sm > .btn-linkedin.btn,\n.btn-flickr.btn-sm,\n.btn-group-sm > .btn-flickr.btn,\n.btn-tumblr.btn-sm,\n.btn-group-sm > .btn-tumblr.btn,\n.btn-xing.btn-sm,\n.btn-group-sm > .btn-xing.btn,\n.btn-github.btn-sm,\n.btn-group-sm > .btn-github.btn,\n.btn-html5.btn-sm,\n.btn-group-sm > .btn-html5.btn,\n.btn-openid.btn-sm,\n.btn-group-sm > .btn-openid.btn,\n.btn-stack-overflow.btn-sm,\n.btn-group-sm > .btn-stack-overflow.btn,\n.btn-youtube.btn-sm,\n.btn-group-sm > .btn-youtube.btn,\n.btn-css3.btn-sm,\n.btn-group-sm > .btn-css3.btn,\n.btn-dribbble.btn-sm,\n.btn-group-sm > .btn-dribbble.btn,\n.btn-google-plus.btn-sm,\n.btn-group-sm > .btn-google-plus.btn,\n.btn-instagram.btn-sm,\n.btn-group-sm > .btn-instagram.btn,\n.btn-pinterest.btn-sm,\n.btn-group-sm > .btn-pinterest.btn,\n.btn-vk.btn-sm,\n.btn-group-sm > .btn-vk.btn,\n.btn-yahoo.btn-sm,\n.btn-group-sm > .btn-yahoo.btn,\n.btn-behance.btn-sm,\n.btn-group-sm > .btn-behance.btn,\n.btn-dropbox.btn-sm,\n.btn-group-sm > .btn-dropbox.btn,\n.btn-reddit.btn-sm,\n.btn-group-sm > .btn-reddit.btn,\n.btn-spotify.btn-sm,\n.btn-group-sm > .btn-spotify.btn,\n.btn-vine.btn-sm,\n.btn-group-sm > .btn-vine.btn,\n.btn-foursquare.btn-sm,\n.btn-group-sm > .btn-foursquare.btn,\n.btn-vimeo.btn-sm,\n.btn-group-sm > .btn-vimeo.btn {\n  padding: 0.25rem 0.5rem;\n  font-size: 0.76563rem;\n  line-height: 1.5;\n  border: 0; }\n.btn-facebook.btn-sm::before, .btn-group-sm > .btn-facebook.btn::before,\n.btn-twitter.btn-sm::before,\n.btn-group-sm > .btn-twitter.btn::before,\n.btn-linkedin.btn-sm::before,\n.btn-group-sm > .btn-linkedin.btn::before,\n.btn-flickr.btn-sm::before,\n.btn-group-sm > .btn-flickr.btn::before,\n.btn-tumblr.btn-sm::before,\n.btn-group-sm > .btn-tumblr.btn::before,\n.btn-xing.btn-sm::before,\n.btn-group-sm > .btn-xing.btn::before,\n.btn-github.btn-sm::before,\n.btn-group-sm > .btn-github.btn::before,\n.btn-html5.btn-sm::before,\n.btn-group-sm > .btn-html5.btn::before,\n.btn-openid.btn-sm::before,\n.btn-group-sm > .btn-openid.btn::before,\n.btn-stack-overflow.btn-sm::before,\n.btn-group-sm > .btn-stack-overflow.btn::before,\n.btn-youtube.btn-sm::before,\n.btn-group-sm > .btn-youtube.btn::before,\n.btn-css3.btn-sm::before,\n.btn-group-sm > .btn-css3.btn::before,\n.btn-dribbble.btn-sm::before,\n.btn-group-sm > .btn-dribbble.btn::before,\n.btn-google-plus.btn-sm::before,\n.btn-group-sm > .btn-google-plus.btn::before,\n.btn-instagram.btn-sm::before,\n.btn-group-sm > .btn-instagram.btn::before,\n.btn-pinterest.btn-sm::before,\n.btn-group-sm > .btn-pinterest.btn::before,\n.btn-vk.btn-sm::before,\n.btn-group-sm > .btn-vk.btn::before,\n.btn-yahoo.btn-sm::before,\n.btn-group-sm > .btn-yahoo.btn::before,\n.btn-behance.btn-sm::before,\n.btn-group-sm > .btn-behance.btn::before,\n.btn-dropbox.btn-sm::before,\n.btn-group-sm > .btn-dropbox.btn::before,\n.btn-reddit.btn-sm::before,\n.btn-group-sm > .btn-reddit.btn::before,\n.btn-spotify.btn-sm::before,\n.btn-group-sm > .btn-spotify.btn::before,\n.btn-vine.btn-sm::before,\n.btn-group-sm > .btn-vine.btn::before,\n.btn-foursquare.btn-sm::before,\n.btn-group-sm > .btn-foursquare.btn::before,\n.btn-vimeo.btn-sm::before,\n.btn-group-sm > .btn-vimeo.btn::before {\n  width: 1.64844rem;\n  height: 1.64844rem;\n  padding: 0.25rem 0;\n  font-size: 0.76563rem;\n  line-height: 1.5; }\n.btn-facebook.btn-sm span, .btn-group-sm > .btn-facebook.btn span,\n.btn-twitter.btn-sm span, .btn-group-sm > .btn-twitter.btn span,\n.btn-linkedin.btn-sm span, .btn-group-sm > .btn-linkedin.btn span,\n.btn-flickr.btn-sm span, .btn-group-sm > .btn-flickr.btn span,\n.btn-tumblr.btn-sm span, .btn-group-sm > .btn-tumblr.btn span,\n.btn-xing.btn-sm span, .btn-group-sm > .btn-xing.btn span,\n.btn-github.btn-sm span, .btn-group-sm > .btn-github.btn span,\n.btn-html5.btn-sm span, .btn-group-sm > .btn-html5.btn span,\n.btn-openid.btn-sm span, .btn-group-sm > .btn-openid.btn span,\n.btn-stack-overflow.btn-sm span, .btn-group-sm > .btn-stack-overflow.btn span,\n.btn-youtube.btn-sm span, .btn-group-sm > .btn-youtube.btn span,\n.btn-css3.btn-sm span, .btn-group-sm > .btn-css3.btn span,\n.btn-dribbble.btn-sm span, .btn-group-sm > .btn-dribbble.btn span,\n.btn-google-plus.btn-sm span, .btn-group-sm > .btn-google-plus.btn span,\n.btn-instagram.btn-sm span, .btn-group-sm > .btn-instagram.btn span,\n.btn-pinterest.btn-sm span, .btn-group-sm > .btn-pinterest.btn span,\n.btn-vk.btn-sm span, .btn-group-sm > .btn-vk.btn span,\n.btn-yahoo.btn-sm span, .btn-group-sm > .btn-yahoo.btn span,\n.btn-behance.btn-sm span, .btn-group-sm > .btn-behance.btn span,\n.btn-dropbox.btn-sm span, .btn-group-sm > .btn-dropbox.btn span,\n.btn-reddit.btn-sm span, .btn-group-sm > .btn-reddit.btn span,\n.btn-spotify.btn-sm span, .btn-group-sm > .btn-spotify.btn span,\n.btn-vine.btn-sm span, .btn-group-sm > .btn-vine.btn span,\n.btn-foursquare.btn-sm span, .btn-group-sm > .btn-foursquare.btn span,\n.btn-vimeo.btn-sm span, .btn-group-sm > .btn-vimeo.btn span {\n  margin-left: 1.64844rem; }\n.btn-facebook.btn-sm.icon, .btn-group-sm > .btn-facebook.icon.btn,\n.btn-twitter.btn-sm.icon,\n.btn-group-sm > .btn-twitter.icon.btn,\n.btn-linkedin.btn-sm.icon,\n.btn-group-sm > .btn-linkedin.icon.btn,\n.btn-flickr.btn-sm.icon,\n.btn-group-sm > .btn-flickr.icon.btn,\n.btn-tumblr.btn-sm.icon,\n.btn-group-sm > .btn-tumblr.icon.btn,\n.btn-xing.btn-sm.icon,\n.btn-group-sm > .btn-xing.icon.btn,\n.btn-github.btn-sm.icon,\n.btn-group-sm > .btn-github.icon.btn,\n.btn-html5.btn-sm.icon,\n.btn-group-sm > .btn-html5.icon.btn,\n.btn-openid.btn-sm.icon,\n.btn-group-sm > .btn-openid.icon.btn,\n.btn-stack-overflow.btn-sm.icon,\n.btn-group-sm > .btn-stack-overflow.icon.btn,\n.btn-youtube.btn-sm.icon,\n.btn-group-sm > .btn-youtube.icon.btn,\n.btn-css3.btn-sm.icon,\n.btn-group-sm > .btn-css3.icon.btn,\n.btn-dribbble.btn-sm.icon,\n.btn-group-sm > .btn-dribbble.icon.btn,\n.btn-google-plus.btn-sm.icon,\n.btn-group-sm > .btn-google-plus.icon.btn,\n.btn-instagram.btn-sm.icon,\n.btn-group-sm > .btn-instagram.icon.btn,\n.btn-pinterest.btn-sm.icon,\n.btn-group-sm > .btn-pinterest.icon.btn,\n.btn-vk.btn-sm.icon,\n.btn-group-sm > .btn-vk.icon.btn,\n.btn-yahoo.btn-sm.icon,\n.btn-group-sm > .btn-yahoo.icon.btn,\n.btn-behance.btn-sm.icon,\n.btn-group-sm > .btn-behance.icon.btn,\n.btn-dropbox.btn-sm.icon,\n.btn-group-sm > .btn-dropbox.icon.btn,\n.btn-reddit.btn-sm.icon,\n.btn-group-sm > .btn-reddit.icon.btn,\n.btn-spotify.btn-sm.icon,\n.btn-group-sm > .btn-spotify.icon.btn,\n.btn-vine.btn-sm.icon,\n.btn-group-sm > .btn-vine.icon.btn,\n.btn-foursquare.btn-sm.icon,\n.btn-group-sm > .btn-foursquare.icon.btn,\n.btn-vimeo.btn-sm.icon,\n.btn-group-sm > .btn-vimeo.icon.btn {\n  width: 1.64844rem;\n  height: 1.64844rem; }\n\n.btn-facebook {\n  background: #3b5998; }\n.btn-facebook::before {\n  content: \"\\f09a\";\n  background: #344e86; }\n.btn-facebook:hover {\n  background: #344e86; }\n.btn-facebook:hover::before {\n  background: #2d4373; }\n\n.btn-twitter {\n  background: #00aced; }\n.btn-twitter::before {\n  content: \"\\f099\";\n  background: #0099d4; }\n.btn-twitter:hover {\n  background: #0099d4; }\n.btn-twitter:hover::before {\n  background: #0087ba; }\n\n.btn-linkedin {\n  background: #4875b4; }\n.btn-linkedin::before {\n  content: \"\\f0e1\";\n  background: #4169a2; }\n.btn-linkedin:hover {\n  background: #4169a2; }\n.btn-linkedin:hover::before {\n  background: #395d90; }\n\n.btn-flickr {\n  background: #ff0084; }\n.btn-flickr::before {\n  content: \"\\f16e\";\n  background: #e60077; }\n.btn-flickr:hover {\n  background: #e60077; }\n.btn-flickr:hover::before {\n  background: #cc006a; }\n\n.btn-tumblr {\n  background: #32506d; }\n.btn-tumblr::before {\n  content: \"\\f173\";\n  background: #2a435c; }\n.btn-tumblr:hover {\n  background: #2a435c; }\n.btn-tumblr:hover::before {\n  background: #22364a; }\n\n.btn-xing {\n  background: #026466; }\n.btn-xing::before {\n  content: \"\\f168\";\n  background: #024b4d; }\n.btn-xing:hover {\n  background: #024b4d; }\n.btn-xing:hover::before {\n  background: #013334; }\n\n.btn-github {\n  background: #4183c4; }\n.btn-github::before {\n  content: \"\\f09b\";\n  background: #3876b4; }\n.btn-github:hover {\n  background: #3876b4; }\n.btn-github:hover::before {\n  background: #3269a0; }\n\n.btn-html5 {\n  background: #e34f26; }\n.btn-html5::before {\n  content: \"\\f13b\";\n  background: #d4431b; }\n.btn-html5:hover {\n  background: #d4431b; }\n.btn-html5:hover::before {\n  background: #be3c18; }\n\n.btn-openid {\n  background: #f78c40; }\n.btn-openid::before {\n  content: \"\\f19b\";\n  background: #f67d28; }\n.btn-openid:hover {\n  background: #f67d28; }\n.btn-openid:hover::before {\n  background: #f56f0f; }\n\n.btn-stack-overflow {\n  background: #fe7a15; }\n.btn-stack-overflow::before {\n  content: \"\\f16c\";\n  background: #f86c01; }\n.btn-stack-overflow:hover {\n  background: #f86c01; }\n.btn-stack-overflow:hover::before {\n  background: #df6101; }\n\n.btn-css3 {\n  background: #0170ba; }\n.btn-css3::before {\n  content: \"\\f13c\";\n  background: #0161a1; }\n.btn-css3:hover {\n  background: #0161a1; }\n.btn-css3:hover::before {\n  background: #015187; }\n\n.btn-youtube {\n  background: #b00; }\n.btn-youtube::before {\n  content: \"\\f167\";\n  background: #a20000; }\n.btn-youtube:hover {\n  background: #a20000; }\n.btn-youtube:hover::before {\n  background: #880000; }\n\n.btn-dribbble {\n  background: #ea4c89; }\n.btn-dribbble::before {\n  content: \"\\f17d\";\n  background: #e7357a; }\n.btn-dribbble:hover {\n  background: #e7357a; }\n.btn-dribbble:hover::before {\n  background: #e51e6b; }\n\n.btn-google-plus {\n  background: #d34836; }\n.btn-google-plus::before {\n  content: \"\\f0d5\";\n  background: #c43d2b; }\n.btn-google-plus:hover {\n  background: #c43d2b; }\n.btn-google-plus:hover::before {\n  background: #b03626; }\n\n.btn-instagram {\n  background: #517fa4; }\n.btn-instagram::before {\n  content: \"\\f16d\";\n  background: #497293; }\n.btn-instagram:hover {\n  background: #497293; }\n.btn-instagram:hover::before {\n  background: #406582; }\n\n.btn-pinterest {\n  background: #cb2027; }\n.btn-pinterest::before {\n  content: \"\\f0d2\";\n  background: #b51d23; }\n.btn-pinterest:hover {\n  background: #b51d23; }\n.btn-pinterest:hover::before {\n  background: #9f191f; }\n\n.btn-vk {\n  background: #45668e; }\n.btn-vk::before {\n  content: \"\\f189\";\n  background: #3d5a7d; }\n.btn-vk:hover {\n  background: #3d5a7d; }\n.btn-vk:hover::before {\n  background: #344d6c; }\n\n.btn-yahoo {\n  background: #400191; }\n.btn-yahoo::before {\n  content: \"\\f19e\";\n  background: #350178; }\n.btn-yahoo:hover {\n  background: #350178; }\n.btn-yahoo:hover::before {\n  background: #2a015e; }\n\n.btn-behance {\n  background: #1769ff; }\n.btn-behance::before {\n  content: \"\\f1b4\";\n  background: #0059fd; }\n.btn-behance:hover {\n  background: #0059fd; }\n.btn-behance:hover::before {\n  background: #0050e3; }\n\n.btn-dropbox {\n  background: #007ee5; }\n.btn-dropbox::before {\n  content: \"\\f16b\";\n  background: #0070cc; }\n.btn-dropbox:hover {\n  background: #0070cc; }\n.btn-dropbox:hover::before {\n  background: #0062b2; }\n\n.btn-reddit {\n  background: #ff4500; }\n.btn-reddit::before {\n  content: \"\\f1a1\";\n  background: #e63e00; }\n.btn-reddit:hover {\n  background: #e63e00; }\n.btn-reddit:hover::before {\n  background: #cc3700; }\n\n.btn-spotify {\n  background: #7ab800; }\n.btn-spotify::before {\n  content: \"\\f1bc\";\n  background: #699f00; }\n.btn-spotify:hover {\n  background: #699f00; }\n.btn-spotify:hover::before {\n  background: #588500; }\n\n.btn-vine {\n  background: #00bf8f; }\n.btn-vine::before {\n  content: \"\\f1ca\";\n  background: #00a67c; }\n.btn-vine:hover {\n  background: #00a67c; }\n.btn-vine:hover::before {\n  background: #008c69; }\n\n.btn-foursquare {\n  background: #1073af; }\n.btn-foursquare::before {\n  content: \"\\f180\";\n  background: #0e6498; }\n.btn-foursquare:hover {\n  background: #0e6498; }\n.btn-foursquare:hover::before {\n  background: #0c5480; }\n\n.btn-vimeo {\n  background: #aad450; }\n.btn-vimeo::before {\n  content: \"\\f194\";\n  background: #a0cf3c; }\n.btn-vimeo:hover {\n  background: #a0cf3c; }\n.btn-vimeo:hover::before {\n  background: #93c130; }\n\n.callout {\n  position: relative;\n  padding: 0 1rem;\n  margin: 1rem 0;\n  border: 0 solid #c2cfd6;\n  border-left-width: .25rem; }\n.callout .chart-wrapper {\n  position: absolute;\n  top: 10px;\n  left: 50%;\n  float: right;\n  width: 50%; }\n\n.callout-bordered {\n  border: 1px solid #c2cfd6;\n  border-left-width: .25rem; }\n\n.callout code {\n  border-radius: .25rem; }\n\n.callout h4 {\n  margin-top: 0;\n  margin-bottom: .25rem; }\n\n.callout p:last-child {\n  margin-bottom: 0; }\n\n.callout + .callout {\n  margin-top: -0.25rem; }\n\n.callout-default {\n  border-left-color: #536c79; }\n.callout-default h4 {\n  color: #536c79; }\n\n.callout-primary {\n  border-left-color: #20a8d8; }\n.callout-primary h4 {\n  color: #20a8d8; }\n\n.callout-secondary {\n  border-left-color: #a4b7c1; }\n.callout-secondary h4 {\n  color: #a4b7c1; }\n\n.callout-success {\n  border-left-color: #4dbd74; }\n.callout-success h4 {\n  color: #4dbd74; }\n\n.callout-info {\n  border-left-color: #63c2de; }\n.callout-info h4 {\n  color: #63c2de; }\n\n.callout-warning {\n  border-left-color: #ffc107; }\n.callout-warning h4 {\n  color: #ffc107; }\n\n.callout-danger {\n  border-left-color: #f86c6b; }\n.callout-danger h4 {\n  color: #f86c6b; }\n\n.callout-light {\n  border-left-color: #f0f3f5; }\n.callout-light h4 {\n  color: #f0f3f5; }\n\n.callout-dark {\n  border-left-color: #29363d; }\n.callout-dark h4 {\n  color: #29363d; }\n\n.card {\n  margin-bottom: 1.5rem; }\n.card.bg-primary {\n  border-color: #187da0; }\n.card.bg-primary .card-header {\n  background-color: #1e9ecb;\n  border-color: #187da0; }\n.card.bg-secondary {\n  border-color: #7e99a7; }\n.card.bg-secondary .card-header {\n  background-color: #9bb0bb;\n  border-color: #7e99a7; }\n.card.bg-success {\n  border-color: #379457; }\n.card.bg-success .card-header {\n  background-color: #44b76c;\n  border-color: #379457; }\n.card.bg-info {\n  border-color: #2eadd3; }\n.card.bg-info .card-header {\n  background-color: #56bddb;\n  border-color: #2eadd3; }\n.card.bg-warning {\n  border-color: #c69500; }\n.card.bg-warning .card-header {\n  background-color: #f7b900;\n  border-color: #c69500; }\n.card.bg-danger {\n  border-color: #f5302e; }\n.card.bg-danger .card-header {\n  background-color: #f75d5c;\n  border-color: #f5302e; }\n.card.bg-light {\n  border-color: #cad4dc; }\n.card.bg-light .card-header {\n  background-color: #e7ecef;\n  border-color: #cad4dc; }\n.card.bg-dark {\n  border-color: #0f1417; }\n.card.bg-dark .card-header {\n  background-color: #232e34;\n  border-color: #0f1417; }\n\n.text-white .text-muted {\n  color: rgba(255, 255, 255, 0.6) !important; }\n\n.card-header .icon-bg {\n  display: inline-body;\n  padding: 0.75rem 1.25rem !important;\n  margin-top: -0.75rem;\n  margin-right: 1.25rem;\n  margin-bottom: -0.75rem;\n  margin-left: -1.25rem;\n  line-height: inherit;\n  color: #151b1e;\n  vertical-align: bottom;\n  background: transparent;\n  border-right: 1px solid #c2cfd6; }\n\n.card-header .nav.nav-tabs {\n  margin-top: -0.75rem;\n  margin-bottom: -0.75rem;\n  border-bottom: 0; }\n.card-header .nav.nav-tabs .nav-item {\n  border-top: 0; }\n.card-header .nav.nav-tabs .nav-link, .card-header .nav.nav-tabs .navbar .dropdown-toggle, .navbar .card-header .nav.nav-tabs .dropdown-toggle {\n  padding: 0.75rem 0.625rem;\n  color: #536c79;\n  border-top: 0; }\n.card-header .nav.nav-tabs .nav-link.active, .card-header .nav.nav-tabs .navbar .active.dropdown-toggle, .navbar .card-header .nav.nav-tabs .active.dropdown-toggle {\n  color: #151b1e;\n  background: #fff; }\n\n.card-header.card-header-inverse {\n  color: #fff; }\n\n.card-header .btn {\n  margin-top: -0.375rem; }\n\n.card-header .btn-sm, .card-header .btn-group-sm > .btn {\n  margin-top: -0.25rem; }\n\n.card-header .btn-lg, .card-header .btn-group-lg > .btn {\n  margin-top: -0.5rem; }\n\n.card-footer ul {\n  display: table;\n  width: 100%;\n  padding: 0;\n  margin: 0;\n  table-layout: fixed; }\n.card-footer ul li {\n  display: table-cell;\n  padding: 0 1.25rem;\n  text-align: center; }\n\n[class*=\"card-outline-\"] .card-body, [class*=\"card-outline-\"] .card-block {\n  background: #fff !important; }\n\n[class*=\"card-outline-\"].card-outline-top {\n  border-top-width: 2px;\n  border-right-color: #c2cfd6;\n  border-bottom-color: #c2cfd6;\n  border-left-color: #c2cfd6; }\n\n.card-accent-primary {\n  border-top-width: 2px;\n  border-top-color: #20a8d8; }\n\n.card-accent-secondary {\n  border-top-width: 2px;\n  border-top-color: #a4b7c1; }\n\n.card-accent-success {\n  border-top-width: 2px;\n  border-top-color: #4dbd74; }\n\n.card-accent-info {\n  border-top-width: 2px;\n  border-top-color: #63c2de; }\n\n.card-accent-warning {\n  border-top-width: 2px;\n  border-top-color: #ffc107; }\n\n.card-accent-danger {\n  border-top-width: 2px;\n  border-top-color: #f86c6b; }\n\n.card-accent-light {\n  border-top-width: 2px;\n  border-top-color: #f0f3f5; }\n\n.card-accent-dark {\n  border-top-width: 2px;\n  border-top-color: #29363d; }\n\n.card-header > i {\n  margin-right: 0.5rem; }\n\n.card-header .card-actions {\n  position: absolute;\n  top: 0;\n  right: 0; }\n.card-header .card-actions a, .card-header .card-actions button {\n  display: block;\n  float: left;\n  width: 50px;\n  padding: 0.75rem 0;\n  margin: 0 !important;\n  color: #151b1e;\n  text-align: center;\n  background: transparent;\n  border: 0;\n  border-left: 1px solid #c2cfd6;\n  box-shadow: 0; }\n.card-header .card-actions a:hover, .card-header .card-actions button:hover {\n  text-decoration: none; }\n.card-header .card-actions a [class^=\"icon-\"], .card-header .card-actions a [class*=\" icon-\"], .card-header .card-actions button [class^=\"icon-\"], .card-header .card-actions button [class*=\" icon-\"] {\n  display: inline-body;\n  vertical-align: middle; }\n.card-header .card-actions a i, .card-header .card-actions button i {\n  display: inline-body;\n  transition: .4s; }\n.card-header .card-actions a .r180, .card-header .card-actions button .r180 {\n  -webkit-transform: rotate(180deg);\n  transform: rotate(180deg); }\n.card-header .card-actions .input-group {\n  width: 230px;\n  margin: 6px; }\n.card-header .card-actions .input-group .input-group-addon {\n  background: #fff; }\n.card-header .card-actions .input-group input {\n  border-left: 0; }\n\n.card-full {\n  margin-top: -1rem;\n  margin-right: -15px;\n  margin-left: -15px;\n  border: 0;\n  border-bottom: 1px solid #c2cfd6; }\n\n@media (min-width: 576px) {\n  .card-columns.cols-2 {\n    -webkit-column-count: 2;\n    column-count: 2; } }\n\n.card.drag, .card .drag {\n  cursor: move; }\n\n.card-placeholder {\n  background: rgba(0, 0, 0, 0.025);\n  border: 1px dashed #a4b7c1; }\n\n.chart-wrapper canvas {\n  width: 100% !important; }\n\nbase-chart.chart {\n  display: block !important; }\n\n.dropdown-item {\n  position: relative;\n  padding: 10px 20px;\n  border-bottom: 1px solid #c2cfd6; }\n.dropdown-item:last-child {\n  border-bottom: 0; }\n.dropdown-item i {\n  display: inline-block;\n  width: 20px;\n  margin-right: 10px;\n  margin-left: -10px;\n  color: #c2cfd6;\n  text-align: center; }\n.dropdown-item .badge {\n  position: absolute;\n  right: 10px;\n  margin-top: 2px; }\n\n.dropdown-header {\n  padding: 8px 20px;\n  background: #f0f3f5;\n  border-bottom: 1px solid #c2cfd6; }\n.dropdown-header .btn {\n  margin-top: -7px;\n  color: #536c79; }\n.dropdown-header .btn:hover {\n  color: #151b1e; }\n.dropdown-header .btn.pull-right {\n  margin-right: -20px; }\n\n.dropdown-menu-lg {\n  width: 250px; }\n\n.app-header .navbar-nav .dropdown-menu {\n  position: absolute; }\n\n.app-header .navbar-nav .dropdown-menu-right {\n  right: 0;\n  left: auto; }\n\n.app-header .navbar-nav .dropdown-menu-left {\n  right: auto;\n  left: 0; }\n\n.app-footer {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-wrap: wrap;\n  flex-wrap: wrap;\n  -ms-flex-align: center;\n  align-items: center;\n  padding: 0 1rem;\n  color: #151b1e;\n  background: #f0f3f5;\n  border-top: 1px solid #c2cfd6; }\n\n.row.row-equal {\n  padding-right: 7.5px;\n  padding-left: 7.5px;\n  margin-right: -15px;\n  margin-left: -15px; }\n.row.row-equal [class*=\"col-\"] {\n  padding-right: 7.5px;\n  padding-left: 7.5px; }\n\n.main .container-fluid {\n  padding: 0 30px; }\n\n.input-group-addon,\n.input-group-btn {\n  min-width: 40px;\n  white-space: nowrap;\n  vertical-align: middle; }\n\n#loading-bar,\n#loading-bar-spinner {\n  -webkit-pointer-events: none;\n  pointer-events: none;\n  transition: 350ms linear all; }\n\n#loading-bar.ng-enter,\n#loading-bar.ng-leave.ng-leave-active,\n#loading-bar-spinner.ng-enter,\n#loading-bar-spinner.ng-leave.ng-leave-active {\n  opacity: 0; }\n\n#loading-bar.ng-enter.ng-enter-active,\n#loading-bar.ng-leave,\n#loading-bar-spinner.ng-enter.ng-enter-active,\n#loading-bar-spinner.ng-leave {\n  opacity: 1; }\n\n#loading-bar .bar {\n  position: fixed;\n  top: 0;\n  left: 0;\n  z-index: 20002;\n  width: 100%;\n  height: 2px;\n  background: #20a8d8;\n  border-top-right-radius: 1px;\n  border-bottom-right-radius: 1px;\n  transition: width 350ms; }\n\n#loading-bar .peg {\n  position: absolute;\n  top: 0;\n  right: 0;\n  width: 70px;\n  height: 2px;\n  border-radius: 100%;\n  -ms-box-shadow: #29d 1px 0 6px 1px;\n  box-shadow: #29d 1px 0 6px 1px;\n  opacity: .45; }\n\n#loading-bar-spinner {\n  position: fixed;\n  top: 10px;\n  left: 10px;\n  z-index: 10002;\n  display: block; }\n\n#loading-bar-spinner .spinner-icon {\n  width: 14px;\n  height: 14px;\n  border: solid 2px transparent;\n  border-top-color: #29d;\n  border-left-color: #29d;\n  border-radius: 50%;\n  -webkit-animation: loading-bar-spinner 400ms linear infinite;\n  animation: loading-bar-spinner 400ms linear infinite; }\n\n@-webkit-keyframes loading-bar-spinner {\n  0% {\n    -webkit-transform: rotate(0deg);\n    transform: rotate(0deg); }\n  100% {\n    -webkit-transform: rotate(360deg);\n    transform: rotate(360deg); } }\n\n@keyframes loading-bar-spinner {\n  0% {\n    -webkit-transform: rotate(0deg);\n    transform: rotate(0deg);\n    transform: rotate(0deg); }\n  100% {\n    -webkit-transform: rotate(360deg);\n    transform: rotate(360deg);\n    transform: rotate(360deg); } }\n\n.pace {\n  -webkit-pointer-events: none;\n  pointer-events: none;\n  -moz-user-select: none;\n  -webkit-user-select: none;\n  -ms-user-select: none;\n  user-select: none; }\n\n.pace-inactive {\n  display: none; }\n\n.pace .pace-progress {\n  position: fixed;\n  top: 0;\n  right: 100%;\n  z-index: 2000;\n  width: 100%;\n  height: 2px;\n  background: #20a8d8; }\n\n.modal-primary .modal-content {\n  border-color: #20a8d8; }\n\n.modal-primary .modal-header {\n  color: #fff;\n  background-color: #20a8d8; }\n\n.modal-secondary .modal-content {\n  border-color: #a4b7c1; }\n\n.modal-secondary .modal-header {\n  color: #fff;\n  background-color: #a4b7c1; }\n\n.modal-success .modal-content {\n  border-color: #4dbd74; }\n\n.modal-success .modal-header {\n  color: #fff;\n  background-color: #4dbd74; }\n\n.modal-info .modal-content {\n  border-color: #63c2de; }\n\n.modal-info .modal-header {\n  color: #fff;\n  background-color: #63c2de; }\n\n.modal-warning .modal-content {\n  border-color: #ffc107; }\n\n.modal-warning .modal-header {\n  color: #fff;\n  background-color: #ffc107; }\n\n.modal-danger .modal-content {\n  border-color: #f86c6b; }\n\n.modal-danger .modal-header {\n  color: #fff;\n  background-color: #f86c6b; }\n\n.modal-light .modal-content {\n  border-color: #f0f3f5; }\n\n.modal-light .modal-header {\n  color: #fff;\n  background-color: #f0f3f5; }\n\n.modal-dark .modal-content {\n  border-color: #29363d; }\n\n.modal-dark .modal-header {\n  color: #fff;\n  background-color: #29363d; }\n\n.nav-tabs .nav-link, .nav-tabs .navbar .dropdown-toggle, .navbar .nav-tabs .dropdown-toggle {\n  color: #536c79; }\n.nav-tabs .nav-link.active, .nav-tabs .navbar .active.dropdown-toggle, .navbar .nav-tabs .active.dropdown-toggle {\n  color: #29363d;\n  background: #fff;\n  border-color: #c2cfd6;\n  border-bottom-color: #fff; }\n.nav-tabs .nav-link.active:focus, .nav-tabs .navbar .active.dropdown-toggle:focus, .navbar .nav-tabs .active.dropdown-toggle:focus {\n  background: #fff;\n  border-color: #c2cfd6;\n  border-bottom-color: #fff; }\n\n.tab-content {\n  margin-top: -1px;\n  background: #fff;\n  border: 1px solid #c2cfd6; }\n.tab-content .tab-pane {\n  padding: 1rem; }\n\n.card-block .tab-content {\n  margin-top: 0;\n  border: 0; }\n\n.app-header.navbar {\n  position: relative;\n  -ms-flex-direction: row;\n  flex-direction: row;\n  height: 55px;\n  padding: 0;\n  margin: 0;\n  background-color: #fff;\n  border-bottom: 1px solid #c2cfd6; }\n.app-header.navbar .navbar-brand {\n  display: inline-block;\n  width: 155px;\n  height: 55px;\n  padding: 0.5rem 1rem;\n  margin-right: 0;\n  background-color: #fff;\n  background-image: url(\"../img/logo.png\");\n  background-repeat: no-repeat;\n  background-position: center center;\n  background-size: 70px auto;\n  border-bottom: 1px solid #c2cfd6; }\n.app-header.navbar .navbar-toggler {\n  min-width: 50px;\n  padding: 0.25rem 0; }\n.app-header.navbar .navbar-toggler:hover .navbar-toggler-icon {\n  background-image: url(\"data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='%2329363d' stroke-width='2.25' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E\"); }\n.app-header.navbar .navbar-toggler-icon {\n  height: 23px;\n  background-image: url(\"data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='%23536c79' stroke-width='2.25' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E\"); }\n.app-header.navbar .navbar-nav {\n  -ms-flex-direction: row;\n  flex-direction: row;\n  -ms-flex-align: center;\n  align-items: center; }\n.app-header.navbar .nav-item {\n  position: relative;\n  min-width: 50px;\n  margin: 0 !important;\n  text-align: center; }\n.app-header.navbar .nav-item button {\n  margin: 0 auto; }\n.app-header.navbar .nav-item .nav-link, .app-header.navbar .nav-item .dropdown-toggle {\n  padding-top: 0;\n  padding-bottom: 0;\n  background: 0;\n  border: 0; }\n.app-header.navbar .nav-item .nav-link .badge, .app-header.navbar .nav-item .dropdown-toggle .badge {\n  position: absolute;\n  top: 50%;\n  left: 50%;\n  margin-top: -16px;\n  margin-left: 0; }\n.app-header.navbar .nav-item .nav-link > .img-avatar, .app-header.navbar .nav-item .dropdown-toggle > .img-avatar {\n  height: 35px;\n  margin: 0 10px; }\n.app-header.navbar .dropdown-menu {\n  padding-bottom: 0;\n  line-height: 1.5; }\n.app-header.navbar .dropdown-item {\n  min-width: 180px; }\n\n.navbar-brand {\n  color: #29363d; }\n.navbar-brand:focus, .navbar-brand:hover {\n  color: #29363d; }\n\n.navbar-nav .nav-link, .navbar-nav .navbar .dropdown-toggle, .navbar .navbar-nav .dropdown-toggle {\n  color: #536c79; }\n.navbar-nav .nav-link:focus, .navbar-nav .navbar .dropdown-toggle:focus, .navbar .navbar-nav .dropdown-toggle:focus, .navbar-nav .nav-link:hover, .navbar-nav .navbar .dropdown-toggle:hover, .navbar .navbar-nav .dropdown-toggle:hover {\n  color: #29363d; }\n\n.navbar-nav .open > .nav-link, .navbar-nav .navbar .open > .dropdown-toggle, .navbar .navbar-nav .open > .dropdown-toggle, .navbar-nav .open > .nav-link:focus, .navbar-nav .navbar .open > .dropdown-toggle:focus, .navbar .navbar-nav .open > .dropdown-toggle:focus, .navbar-nav .open > .nav-link:hover, .navbar-nav .navbar .open > .dropdown-toggle:hover, .navbar .navbar-nav .open > .dropdown-toggle:hover,\n.navbar-nav .active > .nav-link,\n.navbar-nav .navbar .active > .dropdown-toggle, .navbar\n.navbar-nav .active > .dropdown-toggle,\n.navbar-nav .active > .nav-link:focus,\n.navbar-nav .navbar .active > .dropdown-toggle:focus, .navbar\n.navbar-nav .active > .dropdown-toggle:focus,\n.navbar-nav .active > .nav-link:hover,\n.navbar-nav .navbar .active > .dropdown-toggle:hover, .navbar\n.navbar-nav .active > .dropdown-toggle:hover,\n.navbar-nav .nav-link.open,\n.navbar-nav .navbar .open.dropdown-toggle, .navbar\n.navbar-nav .open.dropdown-toggle,\n.navbar-nav .nav-link.open:focus,\n.navbar-nav .navbar .open.dropdown-toggle:focus, .navbar\n.navbar-nav .open.dropdown-toggle:focus,\n.navbar-nav .nav-link.open:hover,\n.navbar-nav .navbar .open.dropdown-toggle:hover, .navbar\n.navbar-nav .open.dropdown-toggle:hover,\n.navbar-nav .nav-link.active,\n.navbar-nav .navbar .active.dropdown-toggle, .navbar\n.navbar-nav .active.dropdown-toggle,\n.navbar-nav .nav-link.active:focus,\n.navbar-nav .navbar .active.dropdown-toggle:focus, .navbar\n.navbar-nav .active.dropdown-toggle:focus,\n.navbar-nav .nav-link.active:hover,\n.navbar-nav .navbar .active.dropdown-toggle:hover, .navbar\n.navbar-nav .active.dropdown-toggle:hover {\n  color: #29363d; }\n\n.navbar-divider {\n  background-color: rgba(0, 0, 0, 0.075); }\n\n@media (min-width: 992px) {\n  .brand-minimized .app-header.navbar .navbar-brand {\n    width: 50px;\n    background-color: #fff;\n    background-image: url(\"../img/logo-symbol.png\");\n    background-size: 24px;\n    border-bottom: 1px solid #c2cfd6; } }\n\n.progress-xs {\n  height: 4px; }\n\n.progress-sm {\n  height: 8px; }\n\n.progress-white {\n  background-color: rgba(255, 255, 255, 0.2) !important; }\n.progress-white .progress-bar {\n  background-color: #fff; }\n\n.sidebar {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-direction: column;\n  flex-direction: column;\n  padding: 0;\n  color: #fff;\n  background: #29363d; }\n.sidebar .sidebar-close {\n  position: absolute;\n  right: 0;\n  display: none;\n  padding: 0 1rem;\n  font-size: 24px;\n  font-weight: 800;\n  line-height: 55px;\n  color: #fff;\n  background: 0;\n  border: 0;\n  opacity: .8; }\n.sidebar .sidebar-close:hover {\n  opacity: 1; }\n.sidebar .sidebar-header {\n  -ms-flex: 0 0 auto;\n  flex: 0 0 auto;\n  padding: 0.75rem 1rem;\n  text-align: center;\n  background: rgba(0, 0, 0, 0.2); }\n.sidebar .sidebar-form .form-control {\n  color: #fff;\n  background: #151b1f;\n  border: 0; }\n.sidebar .sidebar-form .form-control::-webkit-input-placeholder {\n  color: rgba(255, 255, 255, 0.7); }\n.sidebar .sidebar-form .form-control:-ms-input-placeholder {\n  color: rgba(255, 255, 255, 0.7); }\n.sidebar .sidebar-form .form-control::-ms-input-placeholder {\n  color: rgba(255, 255, 255, 0.7); }\n.sidebar .sidebar-form .form-control::placeholder {\n  color: rgba(255, 255, 255, 0.7); }\n.sidebar .sidebar-nav {\n  position: relative;\n  -ms-flex: 1;\n  flex: 1;\n  overflow-x: hidden;\n  overflow-y: auto;\n  -ms-overflow-style: -ms-autohiding-scrollbar;\n  width: 200px; }\n.sidebar .sidebar-nav::-webkit-scrollbar {\n  position: absolute;\n  width: 10px;\n  margin-left: -10px;\n  -webkit-appearance: none; }\n.sidebar .sidebar-nav::-webkit-scrollbar-track {\n  background-color: #33444c;\n  border-right: 1px solid #1f292e;\n  border-left: 1px solid #1f292e; }\n.sidebar .sidebar-nav::-webkit-scrollbar-thumb {\n  height: 50px;\n  background-color: #151b1f;\n  background-clip: content-box;\n  border-color: transparent;\n  border-style: solid;\n  border-width: 1px 2px; }\n.sidebar .nav {\n  width: 200px;\n  -ms-flex-direction: column;\n  flex-direction: column;\n  min-height: 100%; }\n.sidebar .nav-title {\n  padding: 0.75rem 1rem;\n  font-size: 11px;\n  font-weight: 600;\n  color: #c2cfd6;\n  text-transform: uppercase; }\n.sidebar .nav-divider, .sidebar .divider {\n  height: 10px; }\n.sidebar .nav-item {\n  position: relative;\n  margin: 0;\n  transition: background .3s ease-in-out; }\n.sidebar .nav-dropdown-items {\n  max-height: 0;\n  padding: 0;\n  margin: 0;\n  overflow-y: hidden;\n  transition: max-height .3s ease-in-out; }\n.sidebar .nav-dropdown-items .nav-item {\n  padding: 0;\n  list-style: none; }\n.sidebar .nav-link, .sidebar .navbar .dropdown-toggle, .navbar .sidebar .dropdown-toggle {\n  display: block;\n  padding: 0.75rem 1rem;\n  color: #fff;\n  text-decoration: none;\n  background: transparent; }\n.sidebar .nav-link i, .sidebar .navbar .dropdown-toggle i, .navbar .sidebar .dropdown-toggle i {\n  display: inline-block;\n  width: 20px;\n  margin: 0 0.5rem 0 0;\n  font-size: 14px;\n  color: #536c79;\n  text-align: center; }\n.sidebar .nav-link .badge, .sidebar .navbar .dropdown-toggle .badge, .navbar .sidebar .dropdown-toggle .badge {\n  float: right;\n  margin-top: 2px; }\n.sidebar .nav-link.active, .sidebar .navbar .active.dropdown-toggle, .navbar .sidebar .active.dropdown-toggle {\n  color: #fff;\n  background: #33444c; }\n.sidebar .nav-link.active i, .sidebar .navbar .active.dropdown-toggle i, .navbar .sidebar .active.dropdown-toggle i {\n  color: #20a8d8; }\n.sidebar .nav-link:hover, .sidebar .navbar .dropdown-toggle:hover, .navbar .sidebar .dropdown-toggle:hover {\n  color: #fff;\n  background: #20a8d8; }\n.sidebar .nav-link:hover i, .sidebar .navbar .dropdown-toggle:hover i, .navbar .sidebar .dropdown-toggle:hover i {\n  color: #fff; }\n.sidebar .nav-link:hover.nav-dropdown-toggle::before, .sidebar .navbar .dropdown-toggle:hover.nav-dropdown-toggle::before, .navbar .sidebar .dropdown-toggle:hover.nav-dropdown-toggle::before {\n  background-image: url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 11 14'%3E%3Cpath fill='%23fff' d='M9.148 2.352l-4.148 4.148 4.148 4.148q0.148 0.148 0.148 0.352t-0.148 0.352l-1.297 1.297q-0.148 0.148-0.352 0.148t-0.352-0.148l-5.797-5.797q-0.148-0.148-0.148-0.352t0.148-0.352l5.797-5.797q0.148-0.148 0.352-0.148t0.352 0.148l1.297 1.297q0.148 0.148 0.148 0.352t-0.148 0.352z'/%3E%3C/svg%3E\"); }\n.sidebar .nav-link.nav-link-primary, .sidebar .navbar .nav-link-primary.dropdown-toggle, .navbar .sidebar .nav-link-primary.dropdown-toggle {\n  background: #20a8d8; }\n.sidebar .nav-link.nav-link-primary i, .sidebar .navbar .nav-link-primary.dropdown-toggle i, .navbar .sidebar .nav-link-primary.dropdown-toggle i {\n  color: rgba(255, 255, 255, 0.7); }\n.sidebar .nav-link.nav-link-primary:hover, .sidebar .navbar .nav-link-primary.dropdown-toggle:hover, .navbar .sidebar .nav-link-primary.dropdown-toggle:hover {\n  background: #1d97c2 !important; }\n.sidebar .nav-link.nav-link-primary:hover i, .sidebar .navbar .nav-link-primary.dropdown-toggle:hover i, .navbar .sidebar .nav-link-primary.dropdown-toggle:hover i {\n  color: #fff; }\n.sidebar .nav-link.nav-link-secondary, .sidebar .navbar .nav-link-secondary.dropdown-toggle, .navbar .sidebar .nav-link-secondary.dropdown-toggle {\n  background: #a4b7c1; }\n.sidebar .nav-link.nav-link-secondary i, .sidebar .navbar .nav-link-secondary.dropdown-toggle i, .navbar .sidebar .nav-link-secondary.dropdown-toggle i {\n  color: rgba(255, 255, 255, 0.7); }\n.sidebar .nav-link.nav-link-secondary:hover, .sidebar .navbar .nav-link-secondary.dropdown-toggle:hover, .navbar .sidebar .nav-link-secondary.dropdown-toggle:hover {\n  background: #95abb7 !important; }\n.sidebar .nav-link.nav-link-secondary:hover i, .sidebar .navbar .nav-link-secondary.dropdown-toggle:hover i, .navbar .sidebar .nav-link-secondary.dropdown-toggle:hover i {\n  color: #fff; }\n.sidebar .nav-link.nav-link-success, .sidebar .navbar .nav-link-success.dropdown-toggle, .navbar .sidebar .nav-link-success.dropdown-toggle {\n  background: #4dbd74; }\n.sidebar .nav-link.nav-link-success i, .sidebar .navbar .nav-link-success.dropdown-toggle i, .navbar .sidebar .nav-link-success.dropdown-toggle i {\n  color: rgba(255, 255, 255, 0.7); }\n.sidebar .nav-link.nav-link-success:hover, .sidebar .navbar .nav-link-success.dropdown-toggle:hover, .navbar .sidebar .nav-link-success.dropdown-toggle:hover {\n  background: #41af67 !important; }\n.sidebar .nav-link.nav-link-success:hover i, .sidebar .navbar .nav-link-success.dropdown-toggle:hover i, .navbar .sidebar .nav-link-success.dropdown-toggle:hover i {\n  color: #fff; }\n.sidebar .nav-link.nav-link-info, .sidebar .navbar .nav-link-info.dropdown-toggle, .navbar .sidebar .nav-link-info.dropdown-toggle {\n  background: #63c2de; }\n.sidebar .nav-link.nav-link-info i, .sidebar .navbar .nav-link-info.dropdown-toggle i, .navbar .sidebar .nav-link-info.dropdown-toggle i {\n  color: rgba(255, 255, 255, 0.7); }\n.sidebar .nav-link.nav-link-info:hover, .sidebar .navbar .nav-link-info.dropdown-toggle:hover, .navbar .sidebar .nav-link-info.dropdown-toggle:hover {\n  background: #4ebada !important; }\n.sidebar .nav-link.nav-link-info:hover i, .sidebar .navbar .nav-link-info.dropdown-toggle:hover i, .navbar .sidebar .nav-link-info.dropdown-toggle:hover i {\n  color: #fff; }\n.sidebar .nav-link.nav-link-warning, .sidebar .navbar .nav-link-warning.dropdown-toggle, .navbar .sidebar .nav-link-warning.dropdown-toggle {\n  background: #ffc107; }\n.sidebar .nav-link.nav-link-warning i, .sidebar .navbar .nav-link-warning.dropdown-toggle i, .navbar .sidebar .nav-link-warning.dropdown-toggle i {\n  color: rgba(255, 255, 255, 0.7); }\n.sidebar .nav-link.nav-link-warning:hover, .sidebar .navbar .nav-link-warning.dropdown-toggle:hover, .navbar .sidebar .nav-link-warning.dropdown-toggle:hover {\n  background: #edb100 !important; }\n.sidebar .nav-link.nav-link-warning:hover i, .sidebar .navbar .nav-link-warning.dropdown-toggle:hover i, .navbar .sidebar .nav-link-warning.dropdown-toggle:hover i {\n  color: #fff; }\n.sidebar .nav-link.nav-link-danger, .sidebar .navbar .nav-link-danger.dropdown-toggle, .navbar .sidebar .nav-link-danger.dropdown-toggle {\n  background: #f86c6b; }\n.sidebar .nav-link.nav-link-danger i, .sidebar .navbar .nav-link-danger.dropdown-toggle i, .navbar .sidebar .nav-link-danger.dropdown-toggle i {\n  color: rgba(255, 255, 255, 0.7); }\n.sidebar .nav-link.nav-link-danger:hover, .sidebar .navbar .nav-link-danger.dropdown-toggle:hover, .navbar .sidebar .nav-link-danger.dropdown-toggle:hover {\n  background: #f75453 !important; }\n.sidebar .nav-link.nav-link-danger:hover i, .sidebar .navbar .nav-link-danger.dropdown-toggle:hover i, .navbar .sidebar .nav-link-danger.dropdown-toggle:hover i {\n  color: #fff; }\n.sidebar .nav-link.nav-link-light, .sidebar .navbar .nav-link-light.dropdown-toggle, .navbar .sidebar .nav-link-light.dropdown-toggle {\n  background: #f0f3f5; }\n.sidebar .nav-link.nav-link-light i, .sidebar .navbar .nav-link-light.dropdown-toggle i, .navbar .sidebar .nav-link-light.dropdown-toggle i {\n  color: rgba(255, 255, 255, 0.7); }\n.sidebar .nav-link.nav-link-light:hover, .sidebar .navbar .nav-link-light.dropdown-toggle:hover, .navbar .sidebar .nav-link-light.dropdown-toggle:hover {\n  background: #e1e7eb !important; }\n.sidebar .nav-link.nav-link-light:hover i, .sidebar .navbar .nav-link-light.dropdown-toggle:hover i, .navbar .sidebar .nav-link-light.dropdown-toggle:hover i {\n  color: #fff; }\n.sidebar .nav-link.nav-link-dark, .sidebar .navbar .nav-link-dark.dropdown-toggle, .navbar .sidebar .nav-link-dark.dropdown-toggle {\n  background: #29363d; }\n.sidebar .nav-link.nav-link-dark i, .sidebar .navbar .nav-link-dark.dropdown-toggle i, .navbar .sidebar .nav-link-dark.dropdown-toggle i {\n  color: rgba(255, 255, 255, 0.7); }\n.sidebar .nav-link.nav-link-dark:hover, .sidebar .navbar .nav-link-dark.dropdown-toggle:hover, .navbar .sidebar .nav-link-dark.dropdown-toggle:hover {\n  background: #1f292e !important; }\n.sidebar .nav-link.nav-link-dark:hover i, .sidebar .navbar .nav-link-dark.dropdown-toggle:hover i, .navbar .sidebar .nav-link-dark.dropdown-toggle:hover i {\n  color: #fff; }\n.sidebar .nav-dropdown-toggle {\n  position: relative; }\n.sidebar .nav-dropdown-toggle::before {\n  position: absolute;\n  top: 50%;\n  right: 1rem;\n  display: block;\n  width: 8px;\n  height: 8px;\n  padding: 0;\n  margin-top: -4px;\n  content: \"\";\n  background-image: url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 11 14'%3E%3Cpath fill='%23536c79' d='M9.148 2.352l-4.148 4.148 4.148 4.148q0.148 0.148 0.148 0.352t-0.148 0.352l-1.297 1.297q-0.148 0.148-0.352 0.148t-0.352-0.148l-5.797-5.797q-0.148-0.148-0.148-0.352t0.148-0.352l5.797-5.797q0.148-0.148 0.352-0.148t0.352 0.148l1.297 1.297q0.148 0.148 0.148 0.352t-0.148 0.352z'/%3E%3C/svg%3E\");\n  background-repeat: no-repeat;\n  background-position: center;\n  transition: -webkit-transform .3s;\n  transition: transform .3s;\n  transition: transform .3s, -webkit-transform .3s; }\n.sidebar .nav-dropdown.open {\n  background: rgba(0, 0, 0, 0.2); }\n.sidebar .nav-dropdown.open > .nav-dropdown-items {\n  max-height: 1000px; }\n.sidebar .nav-dropdown.open .nav-link, .sidebar .nav-dropdown.open .navbar .dropdown-toggle, .navbar .sidebar .nav-dropdown.open .dropdown-toggle {\n  color: #fff;\n  border-left: 0 !important; }\n.sidebar .nav-dropdown.open > .nav-link.nav-dropdown-toggle::before, .sidebar .navbar .nav-dropdown.open > .nav-dropdown-toggle.dropdown-toggle::before, .navbar .sidebar .nav-dropdown.open > .nav-dropdown-toggle.dropdown-toggle::before {\n  -webkit-transform: rotate(-90deg);\n  transform: rotate(-90deg); }\n.sidebar .nav-dropdown.open .nav-dropdown.open {\n  border-left: 0; }\n.sidebar .nav-label {\n  display: block;\n  padding: 0.09375rem 1rem;\n  color: #c2cfd6; }\n.sidebar .nav-label:hover {\n  color: #fff;\n  text-decoration: none; }\n.sidebar .nav-label i {\n  width: 20px;\n  margin: -3px 0.5rem 0 0;\n  font-size: 10px;\n  color: #536c79;\n  text-align: center;\n  vertical-align: middle; }\n.sidebar .progress {\n  background-color: #485f6b !important; }\n.sidebar .sidebar-footer {\n  -ms-flex: 0 0 auto;\n  flex: 0 0 auto;\n  padding: 0.75rem 1rem;\n  background: rgba(0, 0, 0, 0.2); }\n.sidebar .sidebar-minimizer {\n  position: relative;\n  -ms-flex: 0 0 50px;\n  flex: 0 0 50px;\n  background-color: rgba(0, 0, 0, 0.2);\n  border: 0; }\n.sidebar .sidebar-minimizer::before {\n  position: absolute;\n  top: 0;\n  right: 0;\n  width: 50px;\n  height: 50px;\n  content: \"\";\n  background-image: url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 11 14'%3E%3Cpath fill='%23536c79' d='M9.148 2.352l-4.148 4.148 4.148 4.148q0.148 0.148 0.148 0.352t-0.148 0.352l-1.297 1.297q-0.148 0.148-0.352 0.148t-0.352-0.148l-5.797-5.797q-0.148-0.148-0.148-0.352t0.148-0.352l5.797-5.797q0.148-0.148 0.352-0.148t0.352 0.148l1.297 1.297q0.148 0.148 0.148 0.352t-0.148 0.352z'/%3E%3C/svg%3E\");\n  background-repeat: no-repeat;\n  background-position: center;\n  background-size: 12.5px;\n  transition: .3s; }\n.sidebar .sidebar-minimizer:focus, .sidebar .sidebar-minimizer.focus {\n  outline: 0; }\n.sidebar .sidebar-minimizer:hover {\n  background-color: rgba(0, 0, 0, 0.3); }\n.sidebar .sidebar-minimizer:hover::before {\n  background-image: url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 11 14'%3E%3Cpath fill='%23fff' d='M9.148 2.352l-4.148 4.148 4.148 4.148q0.148 0.148 0.148 0.352t-0.148 0.352l-1.297 1.297q-0.148 0.148-0.352 0.148t-0.352-0.148l-5.797-5.797q-0.148-0.148-0.148-0.352t0.148-0.352l5.797-5.797q0.148-0.148 0.352-0.148t0.352 0.148l1.297 1.297q0.148 0.148 0.148 0.352t-0.148 0.352z'/%3E%3C/svg%3E\"); }\n\n@media (min-width: 992px) {\n  .sidebar-compact .sidebar .sidebar-nav {\n    width: 150px; }\n  .sidebar-compact .sidebar .nav {\n    width: 150px; }\n  .sidebar-compact .sidebar .nav .nav-title {\n    text-align: center; }\n  .sidebar-compact .sidebar .nav .nav-item {\n    width: 150px;\n    border-left: 0 !important; }\n  .sidebar-compact .sidebar .nav .nav-item .nav-link, .sidebar-compact .sidebar .nav .nav-item .navbar .dropdown-toggle, .navbar .sidebar-compact .sidebar .nav .nav-item .dropdown-toggle {\n    text-align: center; }\n  .sidebar-compact .sidebar .nav .nav-item .nav-link i, .sidebar-compact .sidebar .nav .nav-item .navbar .dropdown-toggle i, .navbar .sidebar-compact .sidebar .nav .nav-item .dropdown-toggle i {\n    display: block;\n    width: 100%;\n    margin: 0.25rem 0;\n    font-size: 24px; }\n  .sidebar-compact .sidebar .nav .nav-item .nav-link .badge, .sidebar-compact .sidebar .nav .nav-item .navbar .dropdown-toggle .badge, .navbar .sidebar-compact .sidebar .nav .nav-item .dropdown-toggle .badge {\n    position: absolute;\n    top: 18px;\n    right: 10px; }\n  .sidebar-compact .sidebar .nav .nav-item .nav-link.nav-dropdown-toggle::before, .sidebar-compact .sidebar .nav .nav-item .navbar .nav-dropdown-toggle.dropdown-toggle::before, .navbar .sidebar-compact .sidebar .nav .nav-item .nav-dropdown-toggle.dropdown-toggle::before {\n    top: 30px; }\n  .sidebar-minimized .hidden-cn {\n    display: none; }\n  .sidebar-minimized .sidebar {\n    z-index: 1019; }\n  .sidebar-minimized .sidebar .sidebar-nav {\n    overflow: visible;\n    width: 50px; }\n  .sidebar-minimized .sidebar .nav {\n    width: 50px; }\n  .sidebar-minimized .sidebar .nav-divider, .sidebar-minimized .sidebar .divider,\n  .sidebar-minimized .sidebar .nav-title,\n  .sidebar-minimized .sidebar .sidebar-footer,\n  .sidebar-minimized .sidebar .sidebar-form,\n  .sidebar-minimized .sidebar .sidebar-header {\n    display: none; }\n  .sidebar-minimized .sidebar .sidebar-minimizer::before {\n    width: 100%;\n    -webkit-transform: rotate(-180deg);\n    transform: rotate(-180deg); }\n  .sidebar-minimized .sidebar .nav-item {\n    width: 50px;\n    overflow: hidden;\n    border-left: 0 !important; }\n  .sidebar-minimized .sidebar .nav-item:hover {\n    width: 250px;\n    overflow: visible; }\n  .sidebar-minimized .sidebar .nav-item:hover > .nav-link, .sidebar-minimized .sidebar .navbar .nav-item:hover > .dropdown-toggle, .navbar .sidebar-minimized .sidebar .nav-item:hover > .dropdown-toggle {\n    background: #20a8d8; }\n  .sidebar-minimized .sidebar .nav-item:hover > .nav-link i, .sidebar-minimized .sidebar .navbar .nav-item:hover > .dropdown-toggle i, .navbar .sidebar-minimized .sidebar .nav-item:hover > .dropdown-toggle i {\n    color: #fff; }\n  .sidebar-minimized .sidebar .nav-link, .sidebar-minimized .sidebar .navbar .dropdown-toggle, .navbar .sidebar-minimized .sidebar .dropdown-toggle {\n    position: relative;\n    padding-left: 0;\n    margin: 0;\n    white-space: nowrap;\n    border-left: 0 !important; }\n  .sidebar-minimized .sidebar .nav-link i, .sidebar-minimized .sidebar .navbar .dropdown-toggle i, .navbar .sidebar-minimized .sidebar .dropdown-toggle i {\n    display: block;\n    float: left;\n    width: 50px;\n    font-size: 18px; }\n  .sidebar-minimized .sidebar .nav-link .badge, .sidebar-minimized .sidebar .navbar .dropdown-toggle .badge, .navbar .sidebar-minimized .sidebar .dropdown-toggle .badge {\n    position: absolute;\n    right: 15px;\n    display: none; }\n  .sidebar-minimized .sidebar .nav-link:hover, .sidebar-minimized .sidebar .navbar .dropdown-toggle:hover, .navbar .sidebar-minimized .sidebar .dropdown-toggle:hover {\n    width: 250px;\n    background: #20a8d8; }\n  .sidebar-minimized .sidebar .nav-link:hover .badge, .sidebar-minimized .sidebar .navbar .dropdown-toggle:hover .badge, .navbar .sidebar-minimized .sidebar .dropdown-toggle:hover .badge {\n    display: inline; }\n  .sidebar-minimized .sidebar .nav-link.nav-dropdown-toggle::before, .sidebar-minimized .sidebar .navbar .nav-dropdown-toggle.dropdown-toggle::before, .navbar .sidebar-minimized .sidebar .nav-dropdown-toggle.dropdown-toggle::before {\n    display: none; }\n  .sidebar-minimized .sidebar .nav-dropdown-items .nav-item {\n    width: 200px; }\n  .sidebar-minimized .sidebar .nav-dropdown-items .nav-item .nav-link, .sidebar-minimized .sidebar .nav-dropdown-items .nav-item .navbar .dropdown-toggle, .navbar .sidebar-minimized .sidebar .nav-dropdown-items .nav-item .dropdown-toggle {\n    width: 200px; }\n  .sidebar-minimized .sidebar .nav > .nav-dropdown > .nav-dropdown-items {\n    display: none;\n    max-height: 1000px;\n    background: #29363d; }\n  .sidebar-minimized .sidebar .nav > .nav-dropdown:hover {\n    background: #20a8d8; }\n  .sidebar-minimized .sidebar .nav > .nav-dropdown:hover > .nav-dropdown-items {\n    position: absolute;\n    left: 50px;\n    display: inline; } }\n\n.switch.switch-default {\n  position: relative;\n  display: inline-block;\n  vertical-align: top;\n  width: 40px;\n  height: 24px;\n  background-color: transparent;\n  cursor: pointer; }\n.switch.switch-default .switch-input {\n  position: absolute;\n  top: 0;\n  left: 0;\n  opacity: 0; }\n.switch.switch-default .switch-label {\n  position: relative;\n  display: block;\n  height: inherit;\n  font-size: 10px;\n  font-weight: 600;\n  text-transform: uppercase;\n  background-color: #fff;\n  border: 1px solid #c2cfd6;\n  border-radius: 2px;\n  transition: opacity background .15s ease-out; }\n.switch.switch-default .switch-input:checked ~ .switch-label::before {\n  opacity: 0; }\n.switch.switch-default .switch-input:checked ~ .switch-label::after {\n  opacity: 1; }\n.switch.switch-default .switch-handle {\n  position: absolute;\n  top: 2px;\n  left: 2px;\n  width: 20px;\n  height: 20px;\n  background: #fff;\n  border: 1px solid #c2cfd6;\n  border-radius: 1px;\n  transition: left .15s ease-out; }\n.switch.switch-default .switch-input:checked ~ .switch-handle {\n  left: 18px; }\n.switch.switch-default.switch-lg {\n  width: 48px;\n  height: 28px; }\n.switch.switch-default.switch-lg .switch-label {\n  font-size: 12px; }\n.switch.switch-default.switch-lg .switch-handle {\n  width: 24px;\n  height: 24px; }\n.switch.switch-default.switch-lg .switch-input:checked ~ .switch-handle {\n  left: 22px; }\n.switch.switch-default.switch-sm {\n  width: 32px;\n  height: 20px; }\n.switch.switch-default.switch-sm .switch-label {\n  font-size: 8px; }\n.switch.switch-default.switch-sm .switch-handle {\n  width: 16px;\n  height: 16px; }\n.switch.switch-default.switch-sm .switch-input:checked ~ .switch-handle {\n  left: 14px; }\n.switch.switch-default.switch-xs {\n  width: 24px;\n  height: 16px; }\n.switch.switch-default.switch-xs .switch-label {\n  font-size: 7px; }\n.switch.switch-default.switch-xs .switch-handle {\n  width: 12px;\n  height: 12px; }\n.switch.switch-default.switch-xs .switch-input:checked ~ .switch-handle {\n  left: 10px; }\n\n.switch.switch-text {\n  position: relative;\n  display: inline-block;\n  vertical-align: top;\n  width: 48px;\n  height: 24px;\n  background-color: transparent;\n  cursor: pointer; }\n.switch.switch-text .switch-input {\n  position: absolute;\n  top: 0;\n  left: 0;\n  opacity: 0; }\n.switch.switch-text .switch-label {\n  position: relative;\n  display: block;\n  height: inherit;\n  font-size: 10px;\n  font-weight: 600;\n  text-transform: uppercase;\n  background-color: #fff;\n  border: 1px solid #c2cfd6;\n  border-radius: 2px;\n  transition: opacity background .15s ease-out; }\n.switch.switch-text .switch-label::before,\n.switch.switch-text .switch-label::after {\n  position: absolute;\n  top: 50%;\n  width: 50%;\n  margin-top: -.5em;\n  line-height: 1;\n  text-align: center;\n  transition: inherit; }\n.switch.switch-text .switch-label::before {\n  right: 1px;\n  color: #c2cfd6;\n  content: attr(data-off); }\n.switch.switch-text .switch-label::after {\n  left: 1px;\n  color: #fff;\n  content: attr(data-on);\n  opacity: 0; }\n.switch.switch-text .switch-input:checked ~ .switch-label::before {\n  opacity: 0; }\n.switch.switch-text .switch-input:checked ~ .switch-label::after {\n  opacity: 1; }\n.switch.switch-text .switch-handle {\n  position: absolute;\n  top: 2px;\n  left: 2px;\n  width: 20px;\n  height: 20px;\n  background: #fff;\n  border: 1px solid #c2cfd6;\n  border-radius: 1px;\n  transition: left .15s ease-out; }\n.switch.switch-text .switch-input:checked ~ .switch-handle {\n  left: 26px; }\n.switch.switch-text.switch-lg {\n  width: 56px;\n  height: 28px; }\n.switch.switch-text.switch-lg .switch-label {\n  font-size: 12px; }\n.switch.switch-text.switch-lg .switch-handle {\n  width: 24px;\n  height: 24px; }\n.switch.switch-text.switch-lg .switch-input:checked ~ .switch-handle {\n  left: 30px; }\n.switch.switch-text.switch-sm {\n  width: 40px;\n  height: 20px; }\n.switch.switch-text.switch-sm .switch-label {\n  font-size: 8px; }\n.switch.switch-text.switch-sm .switch-handle {\n  width: 16px;\n  height: 16px; }\n.switch.switch-text.switch-sm .switch-input:checked ~ .switch-handle {\n  left: 22px; }\n.switch.switch-text.switch-xs {\n  width: 32px;\n  height: 16px; }\n.switch.switch-text.switch-xs .switch-label {\n  font-size: 7px; }\n.switch.switch-text.switch-xs .switch-handle {\n  width: 12px;\n  height: 12px; }\n.switch.switch-text.switch-xs .switch-input:checked ~ .switch-handle {\n  left: 18px; }\n\n.switch.switch-icon {\n  position: relative;\n  display: inline-block;\n  vertical-align: top;\n  width: 48px;\n  height: 24px;\n  background-color: transparent;\n  cursor: pointer; }\n.switch.switch-icon .switch-input {\n  position: absolute;\n  top: 0;\n  left: 0;\n  opacity: 0; }\n.switch.switch-icon .switch-label {\n  position: relative;\n  display: block;\n  height: inherit;\n  font-family: FontAwesome;\n  font-size: 10px;\n  font-weight: 600;\n  text-transform: uppercase;\n  background-color: #fff;\n  border: 1px solid #c2cfd6;\n  border-radius: 2px;\n  transition: opacity background .15s ease-out; }\n.switch.switch-icon .switch-label::before,\n.switch.switch-icon .switch-label::after {\n  position: absolute;\n  top: 50%;\n  width: 50%;\n  margin-top: -.5em;\n  line-height: 1;\n  text-align: center;\n  transition: inherit; }\n.switch.switch-icon .switch-label::before {\n  right: 1px;\n  color: #c2cfd6;\n  content: attr(data-off); }\n.switch.switch-icon .switch-label::after {\n  left: 1px;\n  color: #fff;\n  content: attr(data-on);\n  opacity: 0; }\n.switch.switch-icon .switch-input:checked ~ .switch-label::before {\n  opacity: 0; }\n.switch.switch-icon .switch-input:checked ~ .switch-label::after {\n  opacity: 1; }\n.switch.switch-icon .switch-handle {\n  position: absolute;\n  top: 2px;\n  left: 2px;\n  width: 20px;\n  height: 20px;\n  background: #fff;\n  border: 1px solid #c2cfd6;\n  border-radius: 1px;\n  transition: left .15s ease-out; }\n.switch.switch-icon .switch-input:checked ~ .switch-handle {\n  left: 26px; }\n.switch.switch-icon.switch-lg {\n  width: 56px;\n  height: 28px; }\n.switch.switch-icon.switch-lg .switch-label {\n  font-size: 12px; }\n.switch.switch-icon.switch-lg .switch-handle {\n  width: 24px;\n  height: 24px; }\n.switch.switch-icon.switch-lg .switch-input:checked ~ .switch-handle {\n  left: 30px; }\n.switch.switch-icon.switch-sm {\n  width: 40px;\n  height: 20px; }\n.switch.switch-icon.switch-sm .switch-label {\n  font-size: 8px; }\n.switch.switch-icon.switch-sm .switch-handle {\n  width: 16px;\n  height: 16px; }\n.switch.switch-icon.switch-sm .switch-input:checked ~ .switch-handle {\n  left: 22px; }\n.switch.switch-icon.switch-xs {\n  width: 32px;\n  height: 16px; }\n.switch.switch-icon.switch-xs .switch-label {\n  font-size: 7px; }\n.switch.switch-icon.switch-xs .switch-handle {\n  width: 12px;\n  height: 12px; }\n.switch.switch-icon.switch-xs .switch-input:checked ~ .switch-handle {\n  left: 18px; }\n\n.switch.switch-3d {\n  position: relative;\n  display: inline-block;\n  vertical-align: top;\n  width: 40px;\n  height: 24px;\n  background-color: transparent;\n  cursor: pointer; }\n.switch.switch-3d .switch-input {\n  position: absolute;\n  top: 0;\n  left: 0;\n  opacity: 0; }\n.switch.switch-3d .switch-label {\n  position: relative;\n  display: block;\n  height: inherit;\n  font-size: 10px;\n  font-weight: 600;\n  text-transform: uppercase;\n  background-color: #f0f3f5;\n  border: 1px solid #c2cfd6;\n  border-radius: 2px;\n  transition: opacity background .15s ease-out; }\n.switch.switch-3d .switch-input:checked ~ .switch-label::before {\n  opacity: 0; }\n.switch.switch-3d .switch-input:checked ~ .switch-label::after {\n  opacity: 1; }\n.switch.switch-3d .switch-handle {\n  position: absolute;\n  top: 0;\n  left: 0;\n  width: 24px;\n  height: 24px;\n  background: #fff;\n  border: 1px solid #c2cfd6;\n  border-radius: 1px;\n  transition: left .15s ease-out;\n  border: 0;\n  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3); }\n.switch.switch-3d .switch-input:checked ~ .switch-handle {\n  left: 16px; }\n.switch.switch-3d.switch-lg {\n  width: 48px;\n  height: 28px; }\n.switch.switch-3d.switch-lg .switch-label {\n  font-size: 12px; }\n.switch.switch-3d.switch-lg .switch-handle {\n  width: 28px;\n  height: 28px; }\n.switch.switch-3d.switch-lg .switch-input:checked ~ .switch-handle {\n  left: 20px; }\n.switch.switch-3d.switch-sm {\n  width: 32px;\n  height: 20px; }\n.switch.switch-3d.switch-sm .switch-label {\n  font-size: 8px; }\n.switch.switch-3d.switch-sm .switch-handle {\n  width: 20px;\n  height: 20px; }\n.switch.switch-3d.switch-sm .switch-input:checked ~ .switch-handle {\n  left: 12px; }\n.switch.switch-3d.switch-xs {\n  width: 24px;\n  height: 16px; }\n.switch.switch-3d.switch-xs .switch-label {\n  font-size: 7px; }\n.switch.switch-3d.switch-xs .switch-handle {\n  width: 16px;\n  height: 16px; }\n.switch.switch-3d.switch-xs .switch-input:checked ~ .switch-handle {\n  left: 8px; }\n\n.switch-pill .switch-label, .switch.switch-3d .switch-label,\n.switch-pill .switch-handle, .switch.switch-3d .switch-handle {\n  border-radius: 50em !important; }\n\n.switch-pill .switch-label::before, .switch.switch-3d .switch-label::before {\n  right: 2px !important; }\n\n.switch-pill .switch-label::after, .switch.switch-3d .switch-label::after {\n  left: 2px !important; }\n\n.switch-primary > .switch-input:checked ~ .switch-label {\n  background: #20a8d8 !important;\n  border-color: #1985ac; }\n\n.switch-primary > .switch-input:checked ~ .switch-handle {\n  border-color: #1985ac; }\n\n.switch-primary-outline > .switch-input:checked ~ .switch-label {\n  background: #fff !important;\n  border-color: #20a8d8; }\n.switch-primary-outline > .switch-input:checked ~ .switch-label::after {\n  color: #20a8d8; }\n\n.switch-primary-outline > .switch-input:checked ~ .switch-handle {\n  border-color: #20a8d8; }\n\n.switch-primary-outline-alt > .switch-input:checked ~ .switch-label {\n  background: #fff !important;\n  border-color: #20a8d8; }\n.switch-primary-outline-alt > .switch-input:checked ~ .switch-label::after {\n  color: #20a8d8; }\n\n.switch-primary-outline-alt > .switch-input:checked ~ .switch-handle {\n  background: #20a8d8 !important;\n  border-color: #20a8d8; }\n\n.switch-secondary > .switch-input:checked ~ .switch-label {\n  background: #a4b7c1 !important;\n  border-color: #869fac; }\n\n.switch-secondary > .switch-input:checked ~ .switch-handle {\n  border-color: #869fac; }\n\n.switch-secondary-outline > .switch-input:checked ~ .switch-label {\n  background: #fff !important;\n  border-color: #a4b7c1; }\n.switch-secondary-outline > .switch-input:checked ~ .switch-label::after {\n  color: #a4b7c1; }\n\n.switch-secondary-outline > .switch-input:checked ~ .switch-handle {\n  border-color: #a4b7c1; }\n\n.switch-secondary-outline-alt > .switch-input:checked ~ .switch-label {\n  background: #fff !important;\n  border-color: #a4b7c1; }\n.switch-secondary-outline-alt > .switch-input:checked ~ .switch-label::after {\n  color: #a4b7c1; }\n\n.switch-secondary-outline-alt > .switch-input:checked ~ .switch-handle {\n  background: #a4b7c1 !important;\n  border-color: #a4b7c1; }\n\n.switch-success > .switch-input:checked ~ .switch-label {\n  background: #4dbd74 !important;\n  border-color: #3a9d5d; }\n\n.switch-success > .switch-input:checked ~ .switch-handle {\n  border-color: #3a9d5d; }\n\n.switch-success-outline > .switch-input:checked ~ .switch-label {\n  background: #fff !important;\n  border-color: #4dbd74; }\n.switch-success-outline > .switch-input:checked ~ .switch-label::after {\n  color: #4dbd74; }\n\n.switch-success-outline > .switch-input:checked ~ .switch-handle {\n  border-color: #4dbd74; }\n\n.switch-success-outline-alt > .switch-input:checked ~ .switch-label {\n  background: #fff !important;\n  border-color: #4dbd74; }\n.switch-success-outline-alt > .switch-input:checked ~ .switch-label::after {\n  color: #4dbd74; }\n\n.switch-success-outline-alt > .switch-input:checked ~ .switch-handle {\n  background: #4dbd74 !important;\n  border-color: #4dbd74; }\n\n.switch-info > .switch-input:checked ~ .switch-label {\n  background: #63c2de !important;\n  border-color: #39b2d5; }\n\n.switch-info > .switch-input:checked ~ .switch-handle {\n  border-color: #39b2d5; }\n\n.switch-info-outline > .switch-input:checked ~ .switch-label {\n  background: #fff !important;\n  border-color: #63c2de; }\n.switch-info-outline > .switch-input:checked ~ .switch-label::after {\n  color: #63c2de; }\n\n.switch-info-outline > .switch-input:checked ~ .switch-handle {\n  border-color: #63c2de; }\n\n.switch-info-outline-alt > .switch-input:checked ~ .switch-label {\n  background: #fff !important;\n  border-color: #63c2de; }\n.switch-info-outline-alt > .switch-input:checked ~ .switch-label::after {\n  color: #63c2de; }\n\n.switch-info-outline-alt > .switch-input:checked ~ .switch-handle {\n  background: #63c2de !important;\n  border-color: #63c2de; }\n\n.switch-warning > .switch-input:checked ~ .switch-label {\n  background: #ffc107 !important;\n  border-color: #d39e00; }\n\n.switch-warning > .switch-input:checked ~ .switch-handle {\n  border-color: #d39e00; }\n\n.switch-warning-outline > .switch-input:checked ~ .switch-label {\n  background: #fff !important;\n  border-color: #ffc107; }\n.switch-warning-outline > .switch-input:checked ~ .switch-label::after {\n  color: #ffc107; }\n\n.switch-warning-outline > .switch-input:checked ~ .switch-handle {\n  border-color: #ffc107; }\n\n.switch-warning-outline-alt > .switch-input:checked ~ .switch-label {\n  background: #fff !important;\n  border-color: #ffc107; }\n.switch-warning-outline-alt > .switch-input:checked ~ .switch-label::after {\n  color: #ffc107; }\n\n.switch-warning-outline-alt > .switch-input:checked ~ .switch-handle {\n  background: #ffc107 !important;\n  border-color: #ffc107; }\n\n.switch-danger > .switch-input:checked ~ .switch-label {\n  background: #f86c6b !important;\n  border-color: #f63c3a; }\n\n.switch-danger > .switch-input:checked ~ .switch-handle {\n  border-color: #f63c3a; }\n\n.switch-danger-outline > .switch-input:checked ~ .switch-label {\n  background: #fff !important;\n  border-color: #f86c6b; }\n.switch-danger-outline > .switch-input:checked ~ .switch-label::after {\n  color: #f86c6b; }\n\n.switch-danger-outline > .switch-input:checked ~ .switch-handle {\n  border-color: #f86c6b; }\n\n.switch-danger-outline-alt > .switch-input:checked ~ .switch-label {\n  background: #fff !important;\n  border-color: #f86c6b; }\n.switch-danger-outline-alt > .switch-input:checked ~ .switch-label::after {\n  color: #f86c6b; }\n\n.switch-danger-outline-alt > .switch-input:checked ~ .switch-handle {\n  background: #f86c6b !important;\n  border-color: #f86c6b; }\n\n.switch-light > .switch-input:checked ~ .switch-label {\n  background: #f0f3f5 !important;\n  border-color: #d1dbe1; }\n\n.switch-light > .switch-input:checked ~ .switch-handle {\n  border-color: #d1dbe1; }\n\n.switch-light-outline > .switch-input:checked ~ .switch-label {\n  background: #fff !important;\n  border-color: #f0f3f5; }\n.switch-light-outline > .switch-input:checked ~ .switch-label::after {\n  color: #f0f3f5; }\n\n.switch-light-outline > .switch-input:checked ~ .switch-handle {\n  border-color: #f0f3f5; }\n\n.switch-light-outline-alt > .switch-input:checked ~ .switch-label {\n  background: #fff !important;\n  border-color: #f0f3f5; }\n.switch-light-outline-alt > .switch-input:checked ~ .switch-label::after {\n  color: #f0f3f5; }\n\n.switch-light-outline-alt > .switch-input:checked ~ .switch-handle {\n  background: #f0f3f5 !important;\n  border-color: #f0f3f5; }\n\n.switch-dark > .switch-input:checked ~ .switch-label {\n  background: #29363d !important;\n  border-color: #151b1f; }\n\n.switch-dark > .switch-input:checked ~ .switch-handle {\n  border-color: #151b1f; }\n\n.switch-dark-outline > .switch-input:checked ~ .switch-label {\n  background: #fff !important;\n  border-color: #29363d; }\n.switch-dark-outline > .switch-input:checked ~ .switch-label::after {\n  color: #29363d; }\n\n.switch-dark-outline > .switch-input:checked ~ .switch-handle {\n  border-color: #29363d; }\n\n.switch-dark-outline-alt > .switch-input:checked ~ .switch-label {\n  background: #fff !important;\n  border-color: #29363d; }\n.switch-dark-outline-alt > .switch-input:checked ~ .switch-label::after {\n  color: #29363d; }\n\n.switch-dark-outline-alt > .switch-input:checked ~ .switch-handle {\n  background: #29363d !important;\n  border-color: #29363d; }\n\n.table-outline {\n  border: 1px solid #c2cfd6; }\n.table-outline td {\n  vertical-align: middle; }\n\n.table-align-middle td {\n  vertical-align: middle; }\n\n.table-clear td {\n  border: 0; }\n\n.social-box {\n  min-height: 160px;\n  margin-bottom: 1.5rem;\n  text-align: center;\n  background: #fff;\n  border: 1px solid #c2cfd6; }\n.social-box i {\n  display: block;\n  margin: -1px -1px 0;\n  font-size: 40px;\n  line-height: 90px;\n  background: #c2cfd6; }\n.social-box .chart-wrapper {\n  height: 90px;\n  margin: -90px 0 0; }\n.social-box .chart-wrapper canvas {\n  width: 100% !important;\n  height: 90px !important; }\n.social-box ul {\n  padding: 10px 0;\n  list-style: none; }\n.social-box ul li {\n  display: block;\n  float: left;\n  width: 50%; }\n.social-box ul li:first-child {\n  border-right: 1px solid #c2cfd6; }\n.social-box ul li strong {\n  display: block;\n  font-size: 20px; }\n.social-box ul li span {\n  font-size: 10px;\n  font-weight: 500;\n  color: #c2cfd6;\n  text-transform: uppercase; }\n.social-box.facebook i {\n  color: #fff;\n  background: #3b5998; }\n.social-box.twitter i {\n  color: #fff;\n  background: #00aced; }\n.social-box.linkedin i {\n  color: #fff;\n  background: #4875b4; }\n.social-box.google-plus i {\n  color: #fff;\n  background: #d34836; }\n\n.horizontal-bars {\n  padding: 0;\n  margin: 0;\n  list-style: none; }\n.horizontal-bars li {\n  position: relative;\n  height: 40px;\n  line-height: 40px;\n  vertical-align: middle; }\n.horizontal-bars li .title {\n  width: 100px;\n  font-size: 12px;\n  font-weight: 600;\n  color: #536c79;\n  vertical-align: middle; }\n.horizontal-bars li .bars {\n  position: absolute;\n  top: 15px;\n  width: 100%;\n  padding-left: 100px; }\n.horizontal-bars li .bars .progress:first-child {\n  margin-bottom: 2px; }\n.horizontal-bars li.legend {\n  text-align: center; }\n.horizontal-bars li.legend .badge {\n  display: inline-block;\n  width: 8px;\n  height: 8px;\n  padding: 0; }\n.horizontal-bars li.divider {\n  height: 40px; }\n.horizontal-bars li.divider i {\n  margin: 0 !important; }\n.horizontal-bars.type-2 li {\n  overflow: hidden; }\n.horizontal-bars.type-2 li i {\n  display: inline-block;\n  margin-right: 1rem;\n  margin-left: 5px;\n  font-size: 18px;\n  line-height: 40px; }\n.horizontal-bars.type-2 li .title {\n  display: inline-block;\n  width: auto;\n  margin-top: -9px;\n  font-size: 0.875rem;\n  font-weight: normal;\n  line-height: 40px;\n  color: #151b1e; }\n.horizontal-bars.type-2 li .value {\n  float: right;\n  font-weight: 600; }\n.horizontal-bars.type-2 li .bars {\n  position: absolute;\n  top: auto;\n  bottom: 0;\n  padding: 0; }\n\n.icons-list {\n  padding: 0;\n  margin: 0;\n  list-style: none; }\n.icons-list li {\n  position: relative;\n  height: 40px;\n  vertical-align: middle; }\n.icons-list li i {\n  display: block;\n  float: left;\n  width: 35px !important;\n  height: 35px !important;\n  margin: 2px;\n  line-height: 35px !important;\n  text-align: center; }\n.icons-list li .desc {\n  height: 40px;\n  margin-left: 50px;\n  border-bottom: 1px solid #c2cfd6; }\n.icons-list li .desc .title {\n  padding: 2px 0 0;\n  margin: 0; }\n.icons-list li .desc small {\n  display: block;\n  margin-top: -4px;\n  color: #536c79; }\n.icons-list li .value {\n  position: absolute;\n  top: 2px;\n  right: 45px;\n  text-align: right; }\n.icons-list li .value strong {\n  display: block;\n  margin-top: -3px; }\n.icons-list li .actions {\n  position: absolute;\n  top: -4px;\n  right: 10px;\n  width: 40px;\n  height: 40px;\n  line-height: 40px;\n  text-align: center; }\n.icons-list li .actions i {\n  float: none;\n  width: auto;\n  height: auto;\n  padding: 0;\n  margin: 0;\n  line-height: normal; }\n.icons-list li.divider {\n  height: 40px; }\n.icons-list li.divider i {\n  width: auto;\n  height: auto;\n  margin: 2px 0 0;\n  font-size: 18px; }\n\n@media all and (-ms-high-contrast: none) {\n  html {\n    display: -ms-flexbox;\n    display: flex;\n    -ms-flex-direction: column;\n    flex-direction: column; } }\n\n.app,\napp-dashboard,\napp-root {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-direction: column;\n  flex-direction: column;\n  min-height: 100vh; }\n\n.app-header {\n  -ms-flex: 0 0 55px;\n  flex: 0 0 55px; }\n\n.app-footer {\n  -ms-flex: 0 0 50px;\n  flex: 0 0 50px; }\n\n.app-body {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-direction: row;\n  flex-direction: row;\n  -ms-flex-positive: 1;\n  flex-grow: 1;\n  overflow-x: hidden; }\n.app-body .main {\n  -ms-flex: 1;\n  flex: 1;\n  min-width: 0; }\n.app-body .sidebar {\n  -ms-flex: 0 0 200px;\n  flex: 0 0 200px;\n  -ms-flex-order: -1;\n  order: -1; }\n.app-body .aside-menu {\n  -ms-flex: 0 0 250px;\n  flex: 0 0 250px; }\n\n.header-fixed .app-header {\n  position: fixed;\n  z-index: 1020;\n  width: 100%; }\n\n.header-fixed .app-body {\n  margin-top: 55px; }\n\n.sidebar-hidden .sidebar {\n  margin-left: -200px; }\n\n.sidebar-fixed .sidebar {\n  position: fixed;\n  z-index: 1019;\n  width: 200px;\n  height: calc(100vh - 55px); }\n\n.sidebar-fixed .main, .sidebar-fixed .app-footer {\n  margin-left: 200px; }\n\n.sidebar-fixed.sidebar-hidden .main, .sidebar-fixed.sidebar-hidden .app-footer {\n  margin-left: 0; }\n\n.sidebar-off-canvas .sidebar {\n  position: fixed;\n  z-index: 1019;\n  height: calc(100vh - 55px); }\n\n@media (min-width: 992px) {\n  .sidebar-compact .sidebar {\n    -ms-flex: 0 0 150px;\n    flex: 0 0 150px; }\n  .sidebar-compact.sidebar-hidden .sidebar {\n    margin-left: -150px; }\n  .sidebar-compact.sidebar-fixed .main, .sidebar-compact.sidebar-fixed .app-footer {\n    margin-left: 150px; }\n  .sidebar-compact.sidebar-fixed .sidebar {\n    width: 150px; }\n  .sidebar-compact.sidebar-fixed.sidebar-hidden .main, .sidebar-compact.sidebar-fixed.sidebar-hidden .app-footer {\n    margin-left: 0; }\n  .sidebar-minimized .sidebar {\n    -ms-flex: 0 0 50px;\n    flex: 0 0 50px; }\n  .sidebar-minimized.sidebar-hidden .sidebar {\n    margin-left: -50px; }\n  .sidebar-minimized.sidebar-fixed .main, .sidebar-minimized.sidebar-fixed .app-footer {\n    margin-left: 50px; }\n  .sidebar-minimized.sidebar-fixed .sidebar {\n    width: 50px; }\n  .sidebar-minimized.sidebar-fixed.sidebar-hidden .main, .sidebar-minimized.sidebar-fixed.sidebar-hidden .app-footer {\n    margin-left: 0; } }\n\n.aside-menu-hidden .aside-menu {\n  margin-right: -250px; }\n\n.aside-menu-fixed .aside-menu {\n  position: fixed;\n  right: 0;\n  height: 100%; }\n.aside-menu-fixed .aside-menu .tab-content {\n  height: calc(100vh - 2.375rem - 55px); }\n\n.aside-menu-fixed .main, .aside-menu-fixed .app-footer {\n  margin-right: 250px; }\n\n.aside-menu-fixed.aside-menu-hidden .main, .aside-menu-fixed.aside-menu-hidden .app-footer {\n  margin-right: 0; }\n\n.aside-menu-off-canvas .aside-menu {\n  position: fixed;\n  right: 0;\n  z-index: 1019;\n  height: 100%; }\n.aside-menu-off-canvas .aside-menu .tab-content {\n  height: calc(100vh - 2.375rem - 55px); }\n\n.breadcrumb-fixed .main {\n  padding-top: 3.875rem; }\n\n.breadcrumb-fixed .breadcrumb {\n  position: fixed;\n  top: 55px;\n  right: 0;\n  left: 0;\n  z-index: 1018; }\n\n.breadcrumb-fixed .main:nth-child(2) .breadcrumb {\n  right: 250px;\n  left: 200px; }\n\n.breadcrumb-fixed .main:first-child .breadcrumb {\n  right: 250px;\n  left: 0; }\n\n.breadcrumb-fixed .main:last-child .breadcrumb {\n  right: 0; }\n\n.breadcrumb-fixed.sidebar-minimized .main .breadcrumb {\n  left: 50px; }\n\n.breadcrumb-fixed.sidebar-hidden .main .breadcrumb, .breadcrumb-fixed.sidebar-off-canvas .main .breadcrumb {\n  left: 0; }\n\n.breadcrumb-fixed.aside-menu-hidden .main .breadcrumb, .breadcrumb-fixed.aside-menu-off-canvas .main .breadcrumb {\n  right: 0; }\n\n.footer-fixed .app-footer {\n  position: fixed;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1020;\n  height: 50px; }\n\n.footer-fixed .app-body {\n  margin-bottom: 50px; }\n\n.app-header,\n.app-footer,\n.sidebar,\n.main,\n.aside-menu {\n  transition: margin-left 0.25s, margin-right 0.25s, width 0.25s, flex 0.25s;\n  transition: margin-left 0.25s, margin-right 0.25s, width 0.25s, flex 0.25s, -ms-flex 0.25s; }\n\n.sidebar-nav {\n  transition: width 0.25s; }\n\n.breadcrumb {\n  transition: left 0.25s, right 0.25s, width 0.25s; }\n\n@media (max-width: 991px) {\n  .app-header.navbar {\n    position: fixed !important;\n    z-index: 1020;\n    width: 100%;\n    text-align: center;\n    background-color: #fff;\n    border-bottom: 1px solid #c2cfd6; }\n  .app-header.navbar .navbar-toggler {\n    color: #536c79; }\n  .app-header.navbar .navbar-brand {\n    position: absolute;\n    left: 50%;\n    margin-left: -77.5px; }\n  .app-body {\n    margin-top: 55px; }\n  .breadcrumb-fixed .main:nth-child(2) .breadcrumb {\n    right: auto;\n    left: auto;\n    width: 100%; }\n  .sidebar {\n    position: fixed;\n    z-index: 1019;\n    width: 220px;\n    height: calc(100vh - 55px);\n    margin-left: -220px; }\n  .sidebar .sidebar-nav,\n  .sidebar .nav {\n    width: 220px;\n    min-height: calc(100vh - 55px); }\n  .sidebar .sidebar-minimizer {\n    display: none; }\n  .main, .app-footer {\n    margin-left: 0 !important; }\n  .sidebar-hidden .sidebar {\n    margin-left: -220px; }\n  .sidebar-mobile-show .sidebar {\n    width: 220px;\n    margin-left: 0; }\n  .sidebar-mobile-show .main {\n    margin-right: -220px !important;\n    margin-left: 220px !important; } }\n\nhr.transparent {\n  border-top: 1px solid transparent; }\n\n.bg-primary,\n.bg-success,\n.bg-info,\n.bg-warning,\n.bg-danger,\n.bg-inverse {\n  color: #fff; }\n\n.b-a-0 {\n  border: 0 !important; }\n\n.b-t-0 {\n  border-top: 0 !important; }\n\n.b-r-0 {\n  border-right: 0 !important; }\n\n.b-b-0 {\n  border-bottom: 0 !important; }\n\n.b-l-0 {\n  border-left: 0 !important; }\n\n.b-a-1 {\n  border: 1px solid #c2cfd6 !important; }\n\n.b-t-1 {\n  border-top: 1px solid #c2cfd6 !important; }\n\n.b-r-1 {\n  border-right: 1px solid #c2cfd6 !important; }\n\n.b-b-1 {\n  border-bottom: 1px solid #c2cfd6 !important; }\n\n.b-l-1 {\n  border-left: 1px solid #c2cfd6 !important; }\n\n.b-a-2 {\n  border: 2px solid #c2cfd6 !important; }\n\n.b-t-2 {\n  border-top: 2px solid #c2cfd6 !important; }\n\n.b-r-2 {\n  border-right: 2px solid #c2cfd6 !important; }\n\n.b-b-2 {\n  border-bottom: 2px solid #c2cfd6 !important; }\n\n.b-l-2 {\n  border-left: 2px solid #c2cfd6 !important; }\n\n@media (max-width: 575px) {\n  .d-down-none {\n    display: none !important; } }\n\n@media (max-width: 767px) {\n  .d-sm-down-none {\n    display: none !important; } }\n\n@media (max-width: 991px) {\n  .d-md-down-none {\n    display: none !important; } }\n\n@media (max-width: 1199px) {\n  .d-lg-down-none {\n    display: none !important; } }\n\n.d-xl-down-none {\n  display: none !important; }\n\n.label-pill {\n  border-radius: 1rem !important; }\n\n.open > a, .show > a {\n  outline: 0; }\n\n.navbar .dropdown-toggle .img-avatar {\n  height: 35px;\n  margin: 0 10px; }\n\n*[dir=\"rtl\"] {\n  direction: rtl;\n  unicode-bidi: embed; }\n*[dir=\"rtl\"] ul {\n  -webkit-padding-start: 0; }\n*[dir=\"rtl\"] table tr th {\n  text-align: right; }\n*[dir=\"rtl\"] .breadcrumb-item {\n  float: right; }\n*[dir=\"rtl\"] .breadcrumb-menu {\n  right: auto;\n  left: 1rem; }\n*[dir=\"rtl\"] .dropdown-item {\n  text-align: right; }\n*[dir=\"rtl\"] .dropdown-item i {\n  margin-right: -10px;\n  margin-left: 10px; }\n*[dir=\"rtl\"] .dropdown-item .badge {\n  right: auto;\n  left: 10px; }\n*[dir=\"rtl\"] .sidebar-hidden .sidebar {\n  margin-right: -200px; }\n*[dir=\"rtl\"] .sidebar-fixed .main, *[dir=\"rtl\"] .sidebar-fixed .app-footer {\n  margin-right: 200px; }\n*[dir=\"rtl\"] .sidebar-fixed.sidebar-hidden .main, *[dir=\"rtl\"] .sidebar-fixed.sidebar-hidden .app-footer {\n  margin-right: 0; }\n*[dir=\"rtl\"] .sidebar-minimized .sidebar {\n  -ms-flex: 0 0 50px;\n  flex: 0 0 50px; }\n*[dir=\"rtl\"] .sidebar-minimized.sidebar-hidden .sidebar {\n  margin-right: -50px;\n  margin-left: 0; }\n*[dir=\"rtl\"] .sidebar-minimized.sidebar-fixed .main, *[dir=\"rtl\"] .sidebar-minimized.sidebar-fixed .app-footer {\n  margin-right: 50px; }\n*[dir=\"rtl\"] .sidebar-minimized.sidebar-fixed.sidebar-hidden .main, *[dir=\"rtl\"] .sidebar-minimized.sidebar-fixed.sidebar-hidden .app-footer {\n  margin-left: 0; }\n*[dir=\"rtl\"] .aside-menu-hidden .aside-menu {\n  margin-right: 0;\n  margin-left: -250px; }\n*[dir=\"rtl\"] .aside-menu-fixed .aside-menu {\n  right: auto;\n  left: 0; }\n*[dir=\"rtl\"] .aside-menu-fixed .main, *[dir=\"rtl\"] .aside-menu-fixed .app-footer {\n  margin-left: 250px; }\n*[dir=\"rtl\"] .aside-menu-fixed.aside-menu-hidden .main, *[dir=\"rtl\"] .aside-menu-fixed.aside-menu-hidden .app-footer {\n  margin-left: 0; }\n*[dir=\"rtl\"] .aside-menu-off-canvas .aside-menu {\n  position: fixed;\n  right: 0;\n  z-index: 1019;\n  height: 100%; }\n*[dir=\"rtl\"] .aside-menu-off-canvas .aside-menu .tab-content {\n  height: calc(100vh - 2.375rem - 55px); }\n*[dir=\"rtl\"] .sidebar .sidebar-nav .nav .nav-item .nav-link, *[dir=\"rtl\"] .sidebar .sidebar-nav .nav .nav-item .navbar .dropdown-toggle, .navbar *[dir=\"rtl\"] .sidebar .sidebar-nav .nav .nav-item .dropdown-toggle {\n  direction: rtl; }\n*[dir=\"rtl\"] .sidebar .sidebar-nav .nav .nav-item .nav-link i, *[dir=\"rtl\"] .sidebar .sidebar-nav .nav .nav-item .navbar .dropdown-toggle i, .navbar *[dir=\"rtl\"] .sidebar .sidebar-nav .nav .nav-item .dropdown-toggle i {\n  margin: 0 0 0 0.5rem; }\n*[dir=\"rtl\"] .sidebar .sidebar-nav .nav .nav-item .nav-link .badge, *[dir=\"rtl\"] .sidebar .sidebar-nav .nav .nav-item .navbar .dropdown-toggle .badge, .navbar *[dir=\"rtl\"] .sidebar .sidebar-nav .nav .nav-item .dropdown-toggle .badge {\n  float: left;\n  margin-top: 2px; }\n*[dir=\"rtl\"] .sidebar .sidebar-nav .nav .nav-item .nav-link.nav-dropdown-toggle::before, *[dir=\"rtl\"] .sidebar .sidebar-nav .nav .nav-item .navbar .nav-dropdown-toggle.dropdown-toggle::before, .navbar *[dir=\"rtl\"] .sidebar .sidebar-nav .nav .nav-item .nav-dropdown-toggle.dropdown-toggle::before {\n  position: absolute;\n  right: auto !important;\n  left: 1rem;\n  -webkit-transform: rotate(180deg);\n  transform: rotate(180deg); }\n*[dir=\"rtl\"] .sidebar .sidebar-nav .nav .nav-item.nav-dropdown.open > .nav-link.nav-dropdown-toggle::before, *[dir=\"rtl\"] .sidebar .sidebar-nav .nav .navbar .nav-item.nav-dropdown.open > .nav-dropdown-toggle.dropdown-toggle::before, .navbar *[dir=\"rtl\"] .sidebar .sidebar-nav .nav .nav-item.nav-dropdown.open > .nav-dropdown-toggle.dropdown-toggle::before {\n  -webkit-transform: rotate(270deg);\n  transform: rotate(270deg); }\n*[dir=\"rtl\"] .sidebar-minimized .sidebar .nav-link, *[dir=\"rtl\"] .sidebar-minimized .sidebar .navbar .dropdown-toggle, .navbar *[dir=\"rtl\"] .sidebar-minimized .sidebar .dropdown-toggle {\n  padding-right: 0; }\n*[dir=\"rtl\"] .sidebar-minimized .sidebar .nav-link i, *[dir=\"rtl\"] .sidebar-minimized .sidebar .navbar .dropdown-toggle i, .navbar *[dir=\"rtl\"] .sidebar-minimized .sidebar .dropdown-toggle i {\n  float: right;\n  padding: 0;\n  margin: 0; }\n*[dir=\"rtl\"] .sidebar-minimized .sidebar .nav-link .badge, *[dir=\"rtl\"] .sidebar-minimized .sidebar .navbar .dropdown-toggle .badge, .navbar *[dir=\"rtl\"] .sidebar-minimized .sidebar .dropdown-toggle .badge {\n  right: auto;\n  left: 15px; }\n*[dir=\"rtl\"] .sidebar-minimized .sidebar .nav > .nav-dropdown:hover > .nav-dropdown-items {\n  right: 50px;\n  left: 0; }\n*[dir=\"rtl\"] .horizontal-bars li .bars {\n  padding-right: 100px;\n  padding-left: 0; }\n*[dir=\"rtl\"] .horizontal-bars li .bars .progress:first-child {\n  margin-bottom: 2px; }\n*[dir=\"rtl\"] .horizontal-bars.type-2 li i {\n  margin-right: 5px;\n  margin-left: 1rem; }\n*[dir=\"rtl\"] .horizontal-bars.type-2 li .value {\n  float: left;\n  font-weight: 600; }\n*[dir=\"rtl\"] .horizontal-bars.type-2 li .bars {\n  padding: 0; }\n*[dir=\"rtl\"] .icons-list li {\n  position: relative;\n  height: 40px;\n  vertical-align: middle; }\n*[dir=\"rtl\"] .icons-list li i {\n  float: right; }\n*[dir=\"rtl\"] .icons-list li .desc {\n  margin-right: 50px;\n  margin-left: 0; }\n*[dir=\"rtl\"] .icons-list li .value {\n  right: auto;\n  left: 45px;\n  text-align: left; }\n*[dir=\"rtl\"] .icons-list li .value strong {\n  display: block;\n  margin-top: -3px; }\n*[dir=\"rtl\"] .icons-list li .actions {\n  right: auto;\n  left: 10px; }\n*[dir=\"rtl\"] .callout {\n  border: 0 solid #c2cfd6;\n  border-right-width: .25rem; }\n*[dir=\"rtl\"] .callout.callout-primary {\n  border-right-color: #20a8d8; }\n*[dir=\"rtl\"] .callout.callout-secondary {\n  border-right-color: #a4b7c1; }\n*[dir=\"rtl\"] .callout.callout-success {\n  border-right-color: #4dbd74; }\n*[dir=\"rtl\"] .callout.callout-info {\n  border-right-color: #63c2de; }\n*[dir=\"rtl\"] .callout.callout-warning {\n  border-right-color: #ffc107; }\n*[dir=\"rtl\"] .callout.callout-danger {\n  border-right-color: #f86c6b; }\n*[dir=\"rtl\"] .callout.callout-light {\n  border-right-color: #f0f3f5; }\n*[dir=\"rtl\"] .callout.callout-dark {\n  border-right-color: #29363d; }\n*[dir=\"rtl\"] .callout .chart-wrapper {\n  left: 0;\n  float: left; }\n*[dir=\"rtl\"] .callout-default {\n  border-right-color: #536c79; }\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/css/treetable/jquery.treetable.css",
    "content": "table.treetable span.indenter {\n  display: inline-block;\n  margin: 0;\n  padding: 0;\n  text-align: right;\n\n  /* Disable text selection of nodes (for better D&D UX) */\n  user-select: none;\n  -khtml-user-select: none;\n  -moz-user-select: none;\n  -o-user-select: none;\n  -webkit-user-select: none;\n\n  /* Force content-box box model for indenter (Bootstrap compatibility) */\n  -webkit-box-sizing: content-box;\n  -moz-box-sizing: content-box;\n  box-sizing: content-box;\n\n  width: 19px;\n}\n\ntable.treetable span.indenter a {\n  background-position: left center;\n  background-repeat: no-repeat;\n  display: inline-block;\n  text-decoration: none;\n  width: 19px;\n}\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/css/treetable/jquery.treetable.theme.default.css",
    "content": "table.treetable {\n  border: 1px solid #888;\n  border-collapse: collapse;\n  font-size: 1.0em;\n  line-height: 1;\n  margin: .6em 0 1.8em 0;\n  width: 100%;\n}\n\ntable.treetable caption {\n  font-size: .9em;\n  font-weight: bold;\n  margin-bottom: .2em;\n}\n\ntable.treetable thead {\n  background: #aaa url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAZCAYAAADwkER/AAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAD9JREFUeNpsxzEKgDAQAMHlQEhpYWuTF+RV+X+fmLU7ItgMDGoPYAXwJPOHkWxFbd9W1Dt7oZ4BTNSCeqDGOwDlRyvLRZQgvgAAAABJRU5ErkJggg==) repeat-x top left;\n  font-size: .9em;\n}\n\ntable.treetable thead tr th {\n  border: 1px solid #888;\n  font-weight: normal;\n  padding: .3em 1em .1em 1em;\n  text-align: left;\n}\n\ntable.treetable tbody tr td {\n  cursor: default;\n  padding: .3em 1em;\n  height: 35px;\n}\n\ntable.treetable span {\n  background-position: center left;\n  background-repeat: no-repeat;\n  padding: .2em 0 .2em 1.5em;\n}\n\ntable.treetable span.file {\n  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAADoSURBVBgZBcExblNBGAbA2ceegTRBuIKOgiihSZNTcC5LUHAihNJR0kGKCDcYJY6D3/77MdOinTvzAgCw8ysThIvn/VojIyMjIyPP+bS1sUQIV2s95pBDDvmbP/mdkft83tpYguZq5Jh/OeaYh+yzy8hTHvNlaxNNczm+la9OTlar1UdA/+C2A4trRCnD3jS8BB1obq2Gk6GU6QbQAS4BUaYSQAf4bhhKKTFdAzrAOwAxEUAH+KEM01SY3gM6wBsEAQB0gJ+maZoC3gI6iPYaAIBJsiRmHU0AALOeFC3aK2cWAACUXe7+AwO0lc9eTHYTAAAAAElFTkSuQmCC);\n}\n\ntable.treetable span.folder {\n  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAGrSURBVDjLxZO7ihRBFIa/6u0ZW7GHBUV0UQQTZzd3QdhMQxOfwMRXEANBMNQX0MzAzFAwEzHwARbNFDdwEd31Mj3X7a6uOr9BtzNjYjKBJ6nicP7v3KqcJFaxhBVtZUAK8OHlld2st7Xl3DJPVONP+zEUV4HqL5UDYHr5xvuQAjgl/Qs7TzvOOVAjxjlC+ePSwe6DfbVegLVuT4r14eTr6zvA8xSAoBLzx6pvj4l+DZIezuVkG9fY2H7YRQIMZIBwycmzH1/s3F8AapfIPNF3kQk7+kw9PWBy+IZOdg5Ug3mkAATy/t0usovzGeCUWTjCz0B+Sj0ekfdvkZ3abBv+U4GaCtJ1iEm6ANQJ6fEzrG/engcKw/wXQvEKxSEKQxRGKE7Izt+DSiwBJMUSm71rguMYhQKrBygOIRStf4TiFFRBvbRGKiQLWP29yRSHKBTtfdBmHs0BUpgvtgF4yRFR+NUKi0XZcYjCeCG2smkzLAHkbRBmP0/Uk26O5YnUActBp1GsAI+S5nRJJJal5K1aAMrq0d6Tm9uI6zjyf75dAe6tx/SsWeD//o2/Ab6IH3/h25pOAAAAAElFTkSuQmCC);\n}\n\ntable.treetable tr.collapsed span.indenter a {\n  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAHlJREFUeNrcU1sNgDAQ6wgmcAM2MICGGlg1gJnNzWQcvwQGy1j4oUl/7tH0mpwzM7SgQyO+EZAUWh2MkkzSWhJwuRAlHYsJwEwyvs1gABDuzqoJcTw5qxaIJN0bgQRgIjnlmn1heSO5PE6Y2YXe+5Cr5+h++gs12AcAS6FS+7YOsj4AAAAASUVORK5CYII=);\n}\n\ntable.treetable tr.expanded span.indenter a {\n  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAHFJREFUeNpi/P//PwMlgImBQsA44C6gvhfa29v3MzAwOODRc6CystIRbxi0t7fjDJjKykpGYrwwi1hxnLHQ3t7+jIGBQRJJ6HllZaUUKYEYRYBPOB0gBShKwKGA////48VtbW3/8clTnBIH3gCKkzJgAGvBX0dDm0sCAAAAAElFTkSuQmCC);\n}\n\ntable.treetable tr.branch {\n  background-color: #f9f9f9;\n}\n\ntable.treetable tr.selected {\n  background-color: #3875d7;\n  color: #fff;\n}\n\ntable.treetable tr span.indenter a {\n  outline: none; /* Expander shows outline after upgrading to 3.0 (#141) */\n}\n\ntable.treetable tr.collapsed.selected span.indenter a {\n  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAFpJREFUeNpi/P//PwMlgHHADWD4//8/NtyAQxwD45KAAQdKDfj//////fgMIsYAZIMw1DKREFwODAwM/4kNRKq64AADA4MjFDOQ6gKyY4HodMA49PMCxQYABgAVYHsjyZ1x7QAAAABJRU5ErkJggg==);\n}\n\ntable.treetable tr.expanded.selected span.indenter a {\n  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAFtJREFUeNpi/P//PwMlgImBQsA44C6giQENDAwM//HgBmLCAF/AMBLjBUeixf///48L7/+PCvZjU4fPAAc0AxywqcMXCwegGJ1NckL6jx5wpKYDxqGXEkkCgAEAmrqBIejdgngAAAAASUVORK5CYII=);\n}\n\ntable.treetable tr.accept {\n  background-color: #a3bce4;\n  color: #fff\n}\n\ntable.treetable tr.collapsed.accept td span.indenter a {\n  background-image: url(data:image/x-png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAFpJREFUeNpi/P//PwMlgHHADWD4//8/NtyAQxwD45KAAQdKDfj//////fgMIsYAZIMw1DKREFwODAwM/4kNRKq64AADA4MjFDOQ6gKyY4HodMA49PMCxQYABgAVYHsjyZ1x7QAAAABJRU5ErkJggg==);\n}\n\ntable.treetable tr.expanded.accept td span.indenter a {\n  background-image: url(data:image/x-png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAFtJREFUeNpi/P//PwMlgImBQsA44C6giQENDAwM//HgBmLCAF/AMBLjBUeixf///48L7/+PCvZjU4fPAAc0AxywqcMXCwegGJ1NckL6jx5wpKYDxqGXEkkCgAEAmrqBIejdgngAAAAASUVORK5CYII=);\n}\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/css/treetable/screen.css",
    "content": "body {\n  background: #ddd;\n  color: #000;\n  font-family: Helvetica, Arial, sans-serif;\n  line-height: 1.5;\n  margin: 0;\n  padding: 0;\n}\n\n#main {\n  background: #fff;\n  border-left: 20px solid #eee;\n  border-right: 20px solid #eee;\n  margin: 0 auto;\n  max-width: 800px;\n  padding: 20px;\n}\n\npre.listing {\n  background: #eee;\n  border: 1px solid #ccc;\n  margin: .6em 0 .3em 0;\n  padding: .1em .3em;\n}\n\npre.listing b {\n  color: #f00;\n}\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/css/your_style.css",
    "content": "/*\n * It is advised not to edit the smartadmin_production.css\n * as this will override any changes you make in the \n * later versions of this theme. \n * \n * We advise that you use use this CSS to override \n * SmartAdmin styles. \n * \n * Rename the stylesheet to whatever your liking so it will stay\n * unique to you with each update of SmartAdmin.\n */\n\n/*\n * INDEX\n * \n * - HTML\n * - BODY\n * - CUSTOM STYLES\n */"
  },
  {
    "path": "open-layui-web/src/main/view/static/css/ztree/awesomeStyle/awesome.css",
    "content": "/*-------------------------------------\nzTree Style using fontawesome instead of images\n\nversion:    1.1\nauthor:     Mike King\nemail:      mikkelking @ hotmail . com\nwebsite:    http://code.google.com/p/jquerytree/\n\n-------------------------------------*/\n/* Definitions ----------------------*/\n/* End of Definitions ---------------*/\n/* Imports  -------------------------*/\n/* End of Imports  ------------------*/\n.ztree * {\n  padding: 0;\n  margin: 0;\n  font-size: 12px;\n  font-family: Verdana, Arial, Helvetica, AppleGothic, sans-serif;\n  background-color: #af0000;\n}\n.ztree {\n  margin: 0;\n  padding: 5px;\n  color: #ffffff;\n  background-color: #af0000;\n}\n.ztree li {\n  padding: 0;\n  margin: 0;\n  list-style: none;\n  line-height: 17px;\n  text-align: left;\n  white-space: nowrap;\n  outline: 0;\n}\n.ztree li ul {\n  margin: 0px;\n  padding: 0 0 0 18px;\n}\n.ztree li a {\n  padding-right: 3px;\n  margin: 0;\n  cursor: pointer;\n  height: 17px;\n  color: #ffffff;\n  background-color: transparent;\n  text-decoration: none;\n  vertical-align: top;\n  display: inline-block;\n}\n.ztree li a input.rename {\n  height: 14px;\n  width: 80px;\n  padding: 0;\n  margin: 0;\n  color: #af0000;\n  background-color: #ffffff;\n  font-size: 12px;\n  border: 1px #585956 solid;\n  *border: 0px;\n}\n.ztree li a:hover {\n  text-decoration: underline;\n}\n.ztree li a.curSelectedNode {\n  padding-top: 0px;\n  background-color: #af4040;\n  color: #ffff00;\n  height: 17px;\n  opacity: 0.8;\n}\n.ztree li a.curSelectedNode_Edit {\n  padding-top: 0px;\n  background-color: transparent;\n  color: #ffff00;\n  height: 17px;\n  border: 1px #666 solid;\n  opacity: 0.8;\n}\n.ztree li a.tmpTargetNode_inner {\n  padding-top: 0px;\n  background-color: #aaa;\n  color: #ffff00;\n  height: 17px;\n  border: 1px #666 solid;\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n.ztree li span {\n  line-height: 17px;\n  margin-right: 2px;\n  background-color: transparent;\n}\n.ztree li span.button {\n  line-height: 0;\n  margin: 0;\n  padding: 0;\n  width: 15px;\n  height: 17px;\n  display: inline-block;\n  vertical-align: top;\n  border: 0px solid;\n  cursor: pointer;\n  outline: none;\n  background-color: transparent;\n  background-repeat: no-repeat;\n  background-attachment: scroll;\n}\n.ztree li span.button::before {\n  color: #ffffff;\n  font-family: FontAwesome;\n  padding-top: 10px;\n}\n.ztree li span.button.chk {\n  margin: 0px;\n  cursor: auto;\n  width: 12px;\n  display: inline-block;\n  padding-top: 10px;\n  padding-left: 2px;\n}\n.ztree li span.button.chk.checkbox_false_full::before {\n  content: \"\\f096\";\n}\n.ztree li span.button.chk.checkbox_false_full_focus::before {\n  content: \"\\f096\";\n  color: #ffff00;\n}\n.ztree li span.button.chk.checkbox_false_part::before {\n  content: \"\\f096\";\n  color: #aaaaaa;\n}\n.ztree li span.button.chk.checkbox_false_part_focus::before {\n  content: \"\\f096\";\n  color: #cad96c;\n}\n.ztree li span.button.chk.checkbox_false_disable::before {\n  content: \"\\f096\";\n  color: #808080;\n}\n.ztree li span.button.chk.checkbox_true_full::before {\n  content: \"\\f046\";\n}\n.ztree li span.button.chk.checkbox_true_full_focus::before {\n  content: \"\\f046\";\n}\n.ztree li span.button.chk.checkbox_true_part::before {\n  content: \"\\f14a\";\n}\n.ztree li span.button.chk.checkbox_true_part_focus::before {\n  content: \"\\f14a\";\n  color: #ffff00;\n}\n.ztree li span.button.chk.checkbox_true_full_focus::before {\n  content: \"\\f046\";\n  color: #ffff00;\n}\n.ztree li span.button.chk.checkbox_true_part::before {\n  content: \"\\f046\";\n  color: #aaaaaa;\n}\n.ztree li span.button.chk.checkbox_true_part_focus::before {\n  content: \"\\f046\";\n  color: #cad96c;\n}\n.ztree li span.button.chk.checkbox_true_disable::before {\n  content: \"\\f046\";\n  color: #808080;\n}\n.ztree li span.button.chk.radio_false_full::before {\n  content: \"\\f10c\";\n}\n.ztree li span.button.chk.radio_false_full_focus::before {\n  content: \"\\f10c\";\n  color: #ffff00;\n}\n.ztree li span.button.chk.radio_false_part::before {\n  content: \"\\f10c\";\n  color: #aaaaaa;\n}\n.ztree li span.button.chk.radio_false_part_focus::before {\n  content: \"\\f10c\";\n  color: #ffff00;\n}\n.ztree li span.button.chk.radio_false_disable::before {\n  content: \"\\f1db\";\n  color: #808080;\n}\n.ztree li span.button.chk.radio_true_full::before {\n  content: \"\\f192\";\n}\n.ztree li span.button.chk.radio_true_full_focus::before {\n  content: \"\\f192\";\n  color: #ffff00;\n}\n.ztree li span.button.chk.radio_true_part::before {\n  content: \"\\f192\";\n  color: #aaaaaa;\n}\n.ztree li span.button.chk.radio_true_part_focus::before {\n  content: \"\\f192\";\n  color: #aaaaaa;\n}\n.ztree li span.button.chk.radio_true_disable::before {\n  content: \"\\f1db\";\n  color: #808080;\n}\n.ztree li span.button.switch {\n  width: 15px;\n  height: 17px;\n}\n.ztree li span.button.root_open::before {\n  content: \"\\f078\";\n  padding-top: 10px;\n  padding-left: 2px;\n  display: inline-block;\n}\n.ztree li span.button.root_close::before {\n  content: \"\\f115\";\n  padding-top: 10px;\n  padding-left: 2px;\n  display: inline-block;\n}\n.ztree li span.button.roots_open::before {\n  content: \"\\f078\";\n  padding-top: 10px;\n  padding-left: 2px;\n  display: inline-block;\n}\n.ztree li span.button.roots_close::before {\n  content: \"\\f054\";\n  padding-top: 10px;\n  padding-left: 2px;\n  display: inline-block;\n}\n.ztree li span.button.center_open::before {\n  content: \"\\f078\";\n  padding-top: 10px;\n  padding-left: 2px;\n  display: inline-block;\n}\n.ztree li span.button.center_close::before {\n  content: \"\\f054\";\n  padding-top: 10px;\n  padding-left: 2px;\n  display: inline-block;\n}\n.ztree li span.button.bottom_open::before {\n  content: \"\\f078\";\n  padding-top: 10px;\n  padding-left: 2px;\n  display: inline-block;\n}\n.ztree li span.button.bottom_close::before {\n  content: \"\\f054\";\n  padding-top: 10px;\n  padding-left: 2px;\n  display: inline-block;\n}\n.ztree li span.button.root_docu {\n  background: none;\n}\n.ztree li span.button.roots_docu::before {\n  content: \"\\f022\";\n  padding-left: 2px;\n  display: inline-block;\n  color: #ffffff;\n}\n.ztree li span.button.center_docu::before {\n  padding-top: 10px;\n  padding-left: 2px;\n  display: inline-block;\n  color: #ffffff;\n}\n.ztree li span.button.bottom_docu::before {\n  padding-top: 10px;\n  padding-left: 2px;\n  display: inline-block;\n  color: #ffffff;\n}\n.ztree li span.button.noline_docu {\n  background: none;\n}\n.ztree li span.button.ico_open::before {\n  content: \"\\f115\";\n  font-family: FontAwesome;\n  padding-top: 10px;\n  padding-left: 2px;\n  display: inline-block;\n  color: #ffffff;\n}\n.ztree li span.button.ico_close::before {\n  content: \"\\f114\";\n  font-family: FontAwesome;\n  padding-top: 10px;\n  padding-left: 2px;\n  display: inline-block;\n  color: #ffffff;\n}\n.ztree li span.button.ico_docu::before {\n  content: \"\\f022\";\n  font-family: FontAwesome;\n  padding-top: 10px;\n  padding-left: 2px;\n  display: inline-block;\n  color: #ffffff;\n}\n.ztree li span.button.edit {\n  margin-left: 4px;\n  margin-right: -1px;\n  vertical-align: top;\n  *vertical-align: middle;\n  padding-top: 10px;\n}\n.ztree li span.button.edit::before {\n  content: \"\\f044\";\n  font-family: FontAwesome;\n}\n.ztree li span.button.remove {\n  margin-left: 4px;\n  margin-right: -1px;\n  vertical-align: top;\n  *vertical-align: middle;\n  padding-top: 10px;\n}\n.ztree li span.button.remove::before {\n  content: \"\\f1f8\";\n  font-family: FontAwesome;\n}\n.ztree li span.button.add {\n  margin-left: 4px;\n  margin-right: -1px;\n  vertical-align: top;\n  *vertical-align: middle;\n  padding-top: 10px;\n}\n.ztree li span.button.add::before {\n  content: \"\\f067\";\n  font-family: FontAwesome;\n}\n.ztree li span.button.ico_loading {\n  margin-right: 2px;\n  background: url(./img/loading.gif) no-repeat scroll 0 0 transparent;\n  vertical-align: top;\n  *vertical-align: middle;\n}\nul.tmpTargetzTree {\n  background-color: #FFE6B0;\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\nspan.tmpzTreeMove_arrow {\n  width: 16px;\n  height: 17px;\n  display: inline-block;\n  padding: 0;\n  margin: 2px 0 0 1px;\n  border: 0 none;\n  position: absolute;\n  background-color: transparent;\n  background-attachment: scroll;\n}\nspan.tmpzTreeMove_arrow::before {\n  content: \"\\f04b\";\n  font-family: FontAwesome;\n  color: #ffff00;\n}\nul.ztree.zTreeDragUL {\n  margin: 0;\n  padding: 0;\n  position: absolute;\n  width: auto;\n  height: auto;\n  overflow: hidden;\n  background-color: #cfcfcf;\n  border: 1px #ffff00 dotted;\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n.ztreeMask {\n  z-index: 10000;\n  background-color: #cfcfcf;\n  opacity: 0.0;\n  filter: alpha(opacity=0);\n  position: absolute;\n}\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/css/ztree/awesomeStyle/awesome.less",
    "content": "/*-------------------------------------\nzTree Style using fontawesome instead of images\n\nversion:    1.1\nauthor:     Mike King\nemail:      mikkelking @ hotmail . com\nwebsite:    http://code.google.com/p/jquerytree/\n\n-------------------------------------*/\n\n/* Definitions ----------------------*/\n@font-size: 12px;\n// Regular icon and text color is white, which suits any medium -> dark background \n@color-normal: white;\n// Background color\n@color-bg: #af0000;\n// Highlight color\n@color-highlight: yellow;\n// Partially selected (checkboxes, radio buttons)\n@color-partial: #aaaaaa;\n// Partially selected and focused (checkboxes, radio buttons)\n@color-partfocus: #cad96c;\n// Disabled altogether\n@color-disabled: #808080;\n// Editing color\n@color-edit: yellow;\n@w: 15px;\n@h: 17px;\n@pad-left: 2px;\n@pad-top: 10px;\n/* End of Definitions ---------------*/\n\n/* Imports  -------------------------*/\n@import \"fa.less\";\n/* End of Imports  ------------------*/\n\n.ztree * {padding:0; margin:0; font-size:@font-size; font-family: Verdana, Arial, Helvetica, AppleGothic, sans-serif; background-color: @color-bg;}\n.ztree {\n    margin:0; padding:5px; color:@color-normal; background-color: @color-bg;\n    li {\n        padding:0; margin:0; list-style:none; line-height:17px; text-align:left; white-space:nowrap; outline:0;\n        ul { \n            margin: 0px; padding:0 0 0 18px;\n        }\n        ul.line { }\n        a {padding-right:3px; margin:0; cursor:pointer; height:@h; color:@color-normal; background-color: transparent; \n            text-decoration:none; vertical-align:top; display: inline-block;\n            input.rename {height:14px; width:80px; padding:0; margin:0;\n                          color: @color-bg; background-color: @color-normal;\n                        font-size:@font-size; border:1px #585956 solid; *border:0px}\n        }\n        a:hover {text-decoration:underline}\n        a.curSelectedNode {padding-top:0px; background-color:#af4040; color:@color-highlight; height:@h; opacity:0.8;}\n        a.curSelectedNode_Edit {padding-top:0px; background-color:transparent; color:@color-highlight; height:@h; border:1px #666 solid; opacity:0.8;}\n        a.tmpTargetNode_inner {padding-top:0px; background-color:#aaa; color:@color-highlight; height:@h; border:1px #666 solid;\n          opacity:0.8; filter:alpha(opacity=80)}\n        a.tmpTargetNode_prev {}\n        a.tmpTargetNode_next {}\n        span {line-height:@h; margin-right:2px; background-color:transparent;}\n        span.button {line-height:0; margin:0; padding: 0; width:@w; height:@h; display: inline-block; vertical-align:top;\n          border:0px solid; cursor: pointer;outline:none;\n          background-color:transparent; background-repeat:no-repeat; background-attachment: scroll;\n \n            &::before{color: @color-normal; font-family: FontAwesome; padding-top:@pad-top;}\n            &.chk { margin:0px; cursor: auto; width: 12px;\n                display: inline-block;padding-top:@pad-top;padding-left:@pad-left;\n                \n                &.checkbox_false_full::before {content: @fa-square-o;}\n                &.checkbox_false_full_focus::before {content: @fa-square-o; color:@color-highlight;}\n                &.checkbox_false_part::before {content: @fa-square-o;color: @color-partial;}\n                &.checkbox_false_part_focus::before {content: @fa-square-o; color:@color-partfocus;}\n                &.checkbox_false_disable::before {content: @fa-square-o; color:@color-disabled;}\n                &.checkbox_true_full::before {content: @fa-check-square-o;}\n                &.checkbox_true_full_focus::before {content: @fa-check-square-o;}\n                &.checkbox_true_part::before {content: @fa-check-square;}\n                &.checkbox_true_part_focus::before {content: @fa-check-square; color: @color-highlight}\n                &.checkbox_true_full_focus::before {content: @fa-check-square-o; color: @color-highlight}\n                &.checkbox_true_part::before {content: @fa-check-square-o;color: @color-partial}\n                &.checkbox_true_part_focus::before {content: @fa-check-square-o;color: @color-partfocus;}\n                &.checkbox_true_disable::before {content: @fa-check-square-o;color: @color-disabled}\n                 \n                &.radio_false_full::before {content: @fa-circle-o;}\n                &.radio_false_full_focus::before {content: @fa-circle-o;color: @color-highlight}\n                &.radio_false_part::before {content: @fa-circle-o;color: @color-partial}\n                &.radio_false_part_focus::before {content: @fa-circle-o;color: @color-highlight}\n                &.radio_false_disable::before {content: @fa-circle-thin;color: @color-disabled}\n                &.radio_true_full::before {content: @fa-dot-circle-o;}\n                &.radio_true_full_focus::before {content: @fa-dot-circle-o;color: @color-highlight}\n                &.radio_true_part::before {content: @fa-dot-circle-o;color: @color-partial}\n                &.radio_true_part_focus::before {content: @fa-dot-circle-o;color: @color-partial;}\n                &.radio_true_disable::before {content: @fa-circle-thin;color: @color-disabled}\n                \n            }\n            &.switch  {width:@w; height:@h}\n            &.root_open::before{content: @fa-chevron-down;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;}\n            &.root_close::before{content: @fa-folder-open-o;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;}\n            &.roots_open::before{content: @fa-chevron-down;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;}\n            &.roots_close::before{content: @fa-chevron-right;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;}\n            &.center_open::before{content: @fa-chevron-down;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;}\n            &.center_close::before{content: @fa-chevron-right;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;}\n            &.bottom_open::before{content: @fa-chevron-down;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;}\n            &.bottom_close::before{content: @fa-chevron-right;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;}  \n            &.noline_open{}\n            &.noline_close{}\n            &.root_docu{ background:none;}\n            &.roots_docu::before{content: @fa-list-alt;padding-left:@pad-left;display: inline-block;color:@color-normal;}\n            &.center_docu::before{padding-top:@pad-top;padding-left:@pad-left;display: inline-block;color:@color-normal;}\n            &.bottom_docu::before{padding-top:@pad-top;padding-left:@pad-left;display: inline-block;color:@color-normal;}\n            &.noline_docu{ background:none;}\n    \n            &.ico_open::before {content: @fa-folder-open-o;font-family: FontAwesome;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;color:@color-normal;}\n            &.ico_close::before {content: @fa-folder-o;font-family: FontAwesome;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;color:@color-normal;}\n            &.ico_docu::before{content: @fa-list-alt;font-family: FontAwesome;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;color:@color-normal;}\n            \n            &.edit {margin-left:4px; margin-right: -1px;  vertical-align:top; *vertical-align:middle;padding-top:@pad-top;}\n            &.edit::before{content: @fa-pencil-square-o;font-family: FontAwesome;}\n    \n            &.remove {margin-left:4px; margin-right: -1px;  vertical-align:top; *vertical-align:middle;padding-top:@pad-top;}\n            &.remove::before{content: @fa-trash;font-family: FontAwesome;}\n\n    \n            &.add {margin-left:4px; margin-right: -1px; vertical-align:top; *vertical-align:middle;padding-top:@pad-top;}\n            &.add::before{content: @fa-plus;font-family: FontAwesome;}\n\n            &.ico_loading{margin-right:2px; background:url(./img/loading.gif) no-repeat scroll 0 0 transparent; vertical-align:top; *vertical-align:middle}\n        }\n\n    }\n}\n\n\nul.tmpTargetzTree {background-color:#FFE6B0; opacity:0.8; filter:alpha(opacity=80)}\n\n// this is the arrow that moves \nspan.tmpzTreeMove_arrow{width:16px; height:@h; display: inline-block; \n                                padding:0; margin:2px 0 0 1px; border:0 none; position:absolute;\n                                background-color:transparent;  background-attachment: scroll;\n                                 }\nspan.tmpzTreeMove_arrow::before{content: @fa-play;font-family: FontAwesome;color: @color-highlight;\n                                 }\n// outline\n\nul.ztree.zTreeDragUL {margin:0; padding:0; position:absolute; width:auto; height:auto;overflow:hidden; \n             background-color:#cfcfcf; border:1px @color-highlight 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"
  },
  {
    "path": "open-layui-web/src/main/view/static/css/ztree/awesomeStyle/fa.less",
    "content": "@fa-glass: \"\\f000\";\n@fa-music: \"\\f001\";\n@fa-search: \"\\f002\";\n@fa-envelope-o: \"\\f003\";\n@fa-heart: \"\\f004\";\n@fa-star: \"\\f005\";\n@fa-star-o: \"\\f006\";\n@fa-user: \"\\f007\";\n@fa-film: \"\\f008\";\n@fa-th-large: \"\\f009\";\n@fa-th: \"\\f00a\";\n@fa-th-list: \"\\f00b\";\n@fa-check: \"\\f00c\";\n@fa-times: \"\\f00d\";\n@fa-search-plus: \"\\f00e\";\n@fa-search-minus: \"\\f010\";\n@fa-power-off: \"\\f011\";\n@fa-signal: \"\\f012\";\n@fa-cog: \"\\f013\";\n@fa-trash-o: \"\\f014\";\n@fa-home: \"\\f015\";\n@fa-file-o: \"\\f016\";\n@fa-clock-o: \"\\f017\";\n@fa-road: \"\\f018\";\n@fa-download: \"\\f019\";\n@fa-arrow-circle-o-down: \"\\f01a\";\n@fa-arrow-circle-o-up: \"\\f01b\";\n@fa-inbox: \"\\f01c\";\n@fa-play-circle-o: \"\\f01d\";\n@fa-repeat: \"\\f01e\";\n@fa-refresh: \"\\f021\";\n@fa-list-alt: \"\\f022\";\n@fa-lock: \"\\f023\";\n@fa-flag: \"\\f024\";\n@fa-headphones: \"\\f025\";\n@fa-volume-off: \"\\f026\";\n@fa-volume-down: \"\\f027\";\n@fa-volume-up: \"\\f028\";\n@fa-qrcode: \"\\f029\";\n@fa-barcode: \"\\f02a\";\n@fa-tag: \"\\f02b\";\n@fa-tags: \"\\f02c\";\n@fa-book: \"\\f02d\";\n@fa-bookmark: \"\\f02e\";\n@fa-print: \"\\f02f\";\n@fa-camera: \"\\f030\";\n@fa-font: \"\\f031\";\n@fa-bold: \"\\f032\";\n@fa-italic: \"\\f033\";\n@fa-text-height: \"\\f034\";\n@fa-text-width: \"\\f035\";\n@fa-align-left: \"\\f036\";\n@fa-align-center: \"\\f037\";\n@fa-align-right: \"\\f038\";\n@fa-align-justify: \"\\f039\";\n@fa-list: \"\\f03a\";\n@fa-outdent: \"\\f03b\";\n@fa-indent: \"\\f03c\";\n@fa-video-camera: \"\\f03d\";\n@fa-picture-o: \"\\f03e\";\n@fa-pencil: \"\\f040\";\n@fa-map-marker: \"\\f041\";\n@fa-adjust: \"\\f042\";\n@fa-tint: \"\\f043\";\n@fa-pencil-square-o: \"\\f044\";\n@fa-share-square-o: \"\\f045\";\n@fa-check-square-o: \"\\f046\";\n@fa-arrows: \"\\f047\";\n@fa-step-backward: \"\\f048\";\n@fa-fast-backward: \"\\f049\";\n@fa-backward: \"\\f04a\";\n@fa-play: \"\\f04b\";\n@fa-pause: \"\\f04c\";\n@fa-stop: \"\\f04d\";\n@fa-forward: \"\\f04e\";\n@fa-fast-forward: \"\\f050\";\n@fa-step-forward: \"\\f051\";\n@fa-eject: \"\\f052\";\n@fa-chevron-left: \"\\f053\";\n@fa-chevron-right: \"\\f054\";\n@fa-plus-circle: \"\\f055\";\n@fa-minus-circle: \"\\f056\";\n@fa-times-circle: \"\\f057\";\n@fa-check-circle: \"\\f058\";\n@fa-question-circle: \"\\f059\";\n@fa-info-circle: \"\\f05a\";\n@fa-crosshairs: \"\\f05b\";\n@fa-times-circle-o: \"\\f05c\";\n@fa-check-circle-o: \"\\f05d\";\n@fa-ban: \"\\f05e\";\n@fa-arrow-left: \"\\f060\";\n@fa-arrow-right: \"\\f061\";\n@fa-arrow-up: \"\\f062\";\n@fa-arrow-down: \"\\f063\";\n@fa-share: \"\\f064\";\n@fa-expand: \"\\f065\";\n@fa-compress: \"\\f066\";\n@fa-plus: \"\\f067\";\n@fa-minus: \"\\f068\";\n@fa-asterisk: \"\\f069\";\n@fa-exclamation-circle: \"\\f06a\";\n@fa-gift: \"\\f06b\";\n@fa-leaf: \"\\f06c\";\n@fa-fire: \"\\f06d\";\n@fa-eye: \"\\f06e\";\n@fa-eye-slash: \"\\f070\";\n@fa-exclamation-triangle: \"\\f071\";\n@fa-plane: \"\\f072\";\n@fa-calendar: \"\\f073\";\n@fa-random: \"\\f074\";\n@fa-comment: \"\\f075\";\n@fa-magnet: \"\\f076\";\n@fa-chevron-up: \"\\f077\";\n@fa-chevron-down: \"\\f078\";\n@fa-retweet: \"\\f079\";\n@fa-shopping-cart: \"\\f07a\";\n@fa-folder: \"\\f07b\";\n@fa-folder-open: \"\\f07c\";\n@fa-arrows-v: \"\\f07d\";\n@fa-arrows-h: \"\\f07e\";\n@fa-bar-chart: \"\\f080\";\n@fa-twitter-square: \"\\f081\";\n@fa-facebook-square: \"\\f082\";\n@fa-camera-retro: \"\\f083\";\n@fa-key: \"\\f084\";\n@fa-cogs: \"\\f085\";\n@fa-comments: \"\\f086\";\n@fa-thumbs-o-up: \"\\f087\";\n@fa-thumbs-o-down: \"\\f088\";\n@fa-star-half: \"\\f089\";\n@fa-heart-o: \"\\f08a\";\n@fa-sign-out: \"\\f08b\";\n@fa-linkedin-square: \"\\f08c\";\n@fa-thumb-tack: \"\\f08d\";\n@fa-external-link: \"\\f08e\";\n@fa-sign-in: \"\\f090\";\n@fa-trophy: \"\\f091\";\n@fa-github-square: \"\\f092\";\n@fa-upload: \"\\f093\";\n@fa-lemon-o: \"\\f094\";\n@fa-phone: \"\\f095\";\n@fa-square-o: \"\\f096\";\n@fa-bookmark-o: \"\\f097\";\n@fa-phone-square: \"\\f098\";\n@fa-twitter: \"\\f099\";\n@fa-facebook: \"\\f09a\";\n@fa-github: \"\\f09b\";\n@fa-unlock: \"\\f09c\";\n@fa-credit-card: \"\\f09d\";\n@fa-rss: \"\\f09e\";\n@fa-hdd-o: \"\\f0a0\";\n@fa-bullhorn: \"\\f0a1\";\n@fa-bell: \"\\f0f3\";\n@fa-certificate: \"\\f0a3\";\n@fa-hand-o-right: \"\\f0a4\";\n@fa-hand-o-left: \"\\f0a5\";\n@fa-hand-o-up: \"\\f0a6\";\n@fa-hand-o-down: \"\\f0a7\";\n@fa-arrow-circle-left: \"\\f0a8\";\n@fa-arrow-circle-right: \"\\f0a9\";\n@fa-arrow-circle-up: \"\\f0aa\";\n@fa-arrow-circle-down: \"\\f0ab\";\n@fa-globe: \"\\f0ac\";\n@fa-wrench: \"\\f0ad\";\n@fa-tasks: \"\\f0ae\";\n@fa-filter: \"\\f0b0\";\n@fa-briefcase: \"\\f0b1\";\n@fa-arrows-alt: \"\\f0b2\";\n@fa-users: \"\\f0c0\";\n@fa-link: \"\\f0c1\";\n@fa-cloud: \"\\f0c2\";\n@fa-flask: \"\\f0c3\";\n@fa-scissors: \"\\f0c4\";\n@fa-files-o: \"\\f0c5\";\n@fa-paperclip: \"\\f0c6\";\n@fa-floppy-o: \"\\f0c7\";\n@fa-square: \"\\f0c8\";\n@fa-bars: \"\\f0c9\";\n@fa-list-ul: \"\\f0ca\";\n@fa-list-ol: \"\\f0cb\";\n@fa-strikethrough: \"\\f0cc\";\n@fa-underline: \"\\f0cd\";\n@fa-table: \"\\f0ce\";\n@fa-magic: \"\\f0d0\";\n@fa-truck: \"\\f0d1\";\n@fa-pinterest: \"\\f0d2\";\n@fa-pinterest-square: \"\\f0d3\";\n@fa-google-plus-square: \"\\f0d4\";\n@fa-google-plus: \"\\f0d5\";\n@fa-money: \"\\f0d6\";\n@fa-caret-down: \"\\f0d7\";\n@fa-caret-up: \"\\f0d8\";\n@fa-caret-left: \"\\f0d9\";\n@fa-caret-right: \"\\f0da\";\n@fa-columns: \"\\f0db\";\n@fa-sort: \"\\f0dc\";\n@fa-sort-desc: \"\\f0dd\";\n@fa-sort-asc: \"\\f0de\";\n@fa-envelope: \"\\f0e0\";\n@fa-linkedin: \"\\f0e1\";\n@fa-undo: \"\\f0e2\";\n@fa-gavel: \"\\f0e3\";\n@fa-tachometer: \"\\f0e4\";\n@fa-comment-o: \"\\f0e5\";\n@fa-comments-o: \"\\f0e6\";\n@fa-bolt: \"\\f0e7\";\n@fa-sitemap: \"\\f0e8\";\n@fa-umbrella: \"\\f0e9\";\n@fa-clipboard: \"\\f0ea\";\n@fa-lightbulb-o: \"\\f0eb\";\n@fa-exchange: \"\\f0ec\";\n@fa-cloud-download: \"\\f0ed\";\n@fa-cloud-upload: \"\\f0ee\";\n@fa-user-md: \"\\f0f0\";\n@fa-stethoscope: \"\\f0f1\";\n@fa-suitcase: \"\\f0f2\";\n@fa-bell-o: \"\\f0a2\";\n@fa-coffee: \"\\f0f4\";\n@fa-cutlery: \"\\f0f5\";\n@fa-file-text-o: \"\\f0f6\";\n@fa-building-o: \"\\f0f7\";\n@fa-hospital-o: \"\\f0f8\";\n@fa-ambulance: \"\\f0f9\";\n@fa-medkit: \"\\f0fa\";\n@fa-fighter-jet: \"\\f0fb\";\n@fa-beer: \"\\f0fc\";\n@fa-h-square: \"\\f0fd\";\n@fa-plus-square: \"\\f0fe\";\n@fa-angle-double-left: \"\\f100\";\n@fa-angle-double-right: \"\\f101\";\n@fa-angle-double-up: \"\\f102\";\n@fa-angle-double-down: \"\\f103\";\n@fa-angle-left: \"\\f104\";\n@fa-angle-right: \"\\f105\";\n@fa-angle-up: \"\\f106\";\n@fa-angle-down: \"\\f107\";\n@fa-desktop: \"\\f108\";\n@fa-laptop: \"\\f109\";\n@fa-tablet: \"\\f10a\";\n@fa-mobile: \"\\f10b\";\n@fa-circle-o: \"\\f10c\";\n@fa-quote-left: \"\\f10d\";\n@fa-quote-right: \"\\f10e\";\n@fa-spinner: \"\\f110\";\n@fa-circle: \"\\f111\";\n@fa-reply: \"\\f112\";\n@fa-github-alt: \"\\f113\";\n@fa-folder-o: \"\\f114\";\n@fa-folder-open-o: \"\\f115\";\n@fa-smile-o: \"\\f118\";\n@fa-frown-o: \"\\f119\";\n@fa-meh-o: \"\\f11a\";\n@fa-gamepad: \"\\f11b\";\n@fa-keyboard-o: \"\\f11c\";\n@fa-flag-o: \"\\f11d\";\n@fa-flag-checkered: \"\\f11e\";\n@fa-terminal: \"\\f120\";\n@fa-code: \"\\f121\";\n@fa-reply-all: \"\\f122\";\n@fa-star-half-o: \"\\f123\";\n@fa-location-arrow: \"\\f124\";\n@fa-crop: \"\\f125\";\n@fa-code-fork: \"\\f126\";\n@fa-chain-broken: \"\\f127\";\n@fa-question: \"\\f128\";\n@fa-info: \"\\f129\";\n@fa-exclamation: \"\\f12a\";\n@fa-superscript: \"\\f12b\";\n@fa-subscript: \"\\f12c\";\n@fa-eraser: \"\\f12d\";\n@fa-puzzle-piece: \"\\f12e\";\n@fa-microphone: \"\\f130\";\n@fa-microphone-slash: \"\\f131\";\n@fa-shield: \"\\f132\";\n@fa-calendar-o: \"\\f133\";\n@fa-fire-extinguisher: \"\\f134\";\n@fa-rocket: \"\\f135\";\n@fa-maxcdn: \"\\f136\";\n@fa-chevron-circle-left: \"\\f137\";\n@fa-chevron-circle-right: \"\\f138\";\n@fa-chevron-circle-up: \"\\f139\";\n@fa-chevron-circle-down: \"\\f13a\";\n@fa-html5: \"\\f13b\";\n@fa-css3: \"\\f13c\";\n@fa-anchor: \"\\f13d\";\n@fa-unlock-alt: \"\\f13e\";\n@fa-bullseye: \"\\f140\";\n@fa-ellipsis-h: \"\\f141\";\n@fa-ellipsis-v: \"\\f142\";\n@fa-rss-square: \"\\f143\";\n@fa-play-circle: \"\\f144\";\n@fa-ticket: \"\\f145\";\n@fa-minus-square: \"\\f146\";\n@fa-minus-square-o: \"\\f147\";\n@fa-level-up: \"\\f148\";\n@fa-level-down: \"\\f149\";\n@fa-check-square: \"\\f14a\";\n@fa-pencil-square: \"\\f14b\";\n@fa-external-link-square: \"\\f14c\";\n@fa-share-square: \"\\f14d\";\n@fa-compass: \"\\f14e\";\n@fa-caret-square-o-down: \"\\f150\";\n@fa-caret-square-o-up: \"\\f151\";\n@fa-caret-square-o-right: \"\\f152\";\n@fa-eur: \"\\f153\";\n@fa-gbp: \"\\f154\";\n@fa-usd: \"\\f155\";\n@fa-inr: \"\\f156\";\n@fa-jpy: \"\\f157\";\n@fa-rub: \"\\f158\";\n@fa-krw: \"\\f159\";\n@fa-btc: \"\\f15a\";\n@fa-file: \"\\f15b\";\n@fa-file-text: \"\\f15c\";\n@fa-sort-alpha-asc: \"\\f15d\";\n@fa-sort-alpha-desc: \"\\f15e\";\n@fa-sort-amount-asc: \"\\f160\";\n@fa-sort-amount-desc: \"\\f161\";\n@fa-sort-numeric-asc: \"\\f162\";\n@fa-sort-numeric-desc: \"\\f163\";\n@fa-thumbs-up: \"\\f164\";\n@fa-thumbs-down: \"\\f165\";\n@fa-youtube-square: \"\\f166\";\n@fa-youtube: \"\\f167\";\n@fa-xing: \"\\f168\";\n@fa-xing-square: \"\\f169\";\n@fa-youtube-play: \"\\f16a\";\n@fa-dropbox: \"\\f16b\";\n@fa-stack-overflow: \"\\f16c\";\n@fa-instagram: \"\\f16d\";\n@fa-flickr: \"\\f16e\";\n@fa-adn: \"\\f170\";\n@fa-bitbucket: \"\\f171\";\n@fa-bitbucket-square: \"\\f172\";\n@fa-tumblr: \"\\f173\";\n@fa-tumblr-square: \"\\f174\";\n@fa-long-arrow-down: \"\\f175\";\n@fa-long-arrow-up: \"\\f176\";\n@fa-long-arrow-left: \"\\f177\";\n@fa-long-arrow-right: \"\\f178\";\n@fa-apple: \"\\f179\";\n@fa-windows: \"\\f17a\";\n@fa-android: \"\\f17b\";\n@fa-linux: \"\\f17c\";\n@fa-dribbble: \"\\f17d\";\n@fa-skype: \"\\f17e\";\n@fa-foursquare: \"\\f180\";\n@fa-trello: \"\\f181\";\n@fa-female: \"\\f182\";\n@fa-male: \"\\f183\";\n@fa-gittip: \"\\f184\";\n@fa-sun-o: \"\\f185\";\n@fa-moon-o: \"\\f186\";\n@fa-archive: \"\\f187\";\n@fa-bug: \"\\f188\";\n@fa-vk: \"\\f189\";\n@fa-weibo: \"\\f18a\";\n@fa-cf: \"\\f18b\";\n@fa-pagelines: \"\\f18c\";\n@fa-stack-exchange: \"\\f18d\";\n@fa-arrow-circle-o-right: \"\\f18e\";\n@fa-arrow-circle-o-left: \"\\f190\";\n@fa-caret-square-o-left: \"\\f191\";\n@fa-dot-circle-o: \"\\f192\";\n@fa-wheelchair: \"\\f193\";\n@fa-vimeo-square: \"\\f194\";\n@fa-try: \"\\f195\";\n@fa-plus-square-o: \"\\f196\";\n@fa-space-shuttle: \"\\f197\";\n@fa-slack: \"\\f198\";\n@fa-envelope-square: \"\\f199\";\n@fa-wordpress: \"\\f19a\";\n@fa-openid: \"\\f19b\";\n@fa-university: \"\\f19c\";\n@fa-graduation-cap: \"\\f19d\";\n@fa-yahoo: \"\\f19e\";\n@fa-google: \"\\f1a0\";\n@fa-reddit: \"\\f1a1\";\n@fa-reddit-square: \"\\f1a2\";\n@fa-stumbleupon-circle: \"\\f1a3\";\n@fa-stumbleupon: \"\\f1a4\";\n@fa-delicious: \"\\f1a5\";\n@fa-digg: \"\\f1a6\";\n@fa-pied-piper: \"\\f1a7\";\n@fa-pied-piper-alt: \"\\f1a8\";\n@fa-drupal: \"\\f1a9\";\n@fa-joomla: \"\\f1aa\";\n@fa-language: \"\\f1ab\";\n@fa-fax: \"\\f1ac\";\n@fa-building: \"\\f1ad\";\n@fa-child: \"\\f1ae\";\n@fa-paw: \"\\f1b0\";\n@fa-spoon: \"\\f1b1\";\n@fa-cube: \"\\f1b2\";\n@fa-cubes: \"\\f1b3\";\n@fa-behance: \"\\f1b4\";\n@fa-behance-square: \"\\f1b5\";\n@fa-steam: \"\\f1b6\";\n@fa-steam-square: \"\\f1b7\";\n@fa-recycle: \"\\f1b8\";\n@fa-car: \"\\f1b9\";\n@fa-taxi: \"\\f1ba\";\n@fa-tree: \"\\f1bb\";\n@fa-spotify: \"\\f1bc\";\n@fa-deviantart: \"\\f1bd\";\n@fa-soundcloud: \"\\f1be\";\n@fa-database: \"\\f1c0\";\n@fa-file-pdf-o: \"\\f1c1\";\n@fa-file-word-o: \"\\f1c2\";\n@fa-file-excel-o: \"\\f1c3\";\n@fa-file-powerpoint-o: \"\\f1c4\";\n@fa-file-image-o: \"\\f1c5\";\n@fa-file-archive-o: \"\\f1c6\";\n@fa-file-audio-o: \"\\f1c7\";\n@fa-file-video-o: \"\\f1c8\";\n@fa-file-code-o: \"\\f1c9\";\n@fa-vine: \"\\f1ca\";\n@fa-codepen: \"\\f1cb\";\n@fa-jsfiddle: \"\\f1cc\";\n@fa-life-ring: \"\\f1cd\";\n@fa-circle-o-notch: \"\\f1ce\";\n@fa-rebel: \"\\f1d0\";\n@fa-empire: \"\\f1d1\";\n@fa-git-square: \"\\f1d2\";\n@fa-git: \"\\f1d3\";\n@fa-hacker-news: \"\\f1d4\";\n@fa-tencent-weibo: \"\\f1d5\";\n@fa-qq: \"\\f1d6\";\n@fa-weixin: \"\\f1d7\";\n@fa-paper-plane: \"\\f1d8\";\n@fa-paper-plane-o: \"\\f1d9\";\n@fa-history: \"\\f1da\";\n@fa-circle-thin: \"\\f1db\";\n@fa-header: \"\\f1dc\";\n@fa-paragraph: \"\\f1dd\";\n@fa-sliders: \"\\f1de\";\n@fa-share-alt: \"\\f1e0\";\n@fa-share-alt-square: \"\\f1e1\";\n@fa-bomb: \"\\f1e2\";\n@fa-futbol-o: \"\\f1e3\";\n@fa-tty: \"\\f1e4\";\n@fa-binoculars: \"\\f1e5\";\n@fa-plug: \"\\f1e6\";\n@fa-slideshare: \"\\f1e7\";\n@fa-twitch: \"\\f1e8\";\n@fa-yelp: \"\\f1e9\";\n@fa-newspaper-o: \"\\f1ea\";\n@fa-wifi: \"\\f1eb\";\n@fa-calculator: \"\\f1ec\";\n@fa-paypal: \"\\f1ed\";\n@fa-google-wallet: \"\\f1ee\";\n@fa-cc-visa: \"\\f1f0\";\n@fa-cc-mastercard: \"\\f1f1\";\n@fa-cc-discover: \"\\f1f2\";\n@fa-cc-amex: \"\\f1f3\";\n@fa-cc-paypal: \"\\f1f4\";\n@fa-cc-stripe: \"\\f1f5\";\n@fa-bell-slash: \"\\f1f6\";\n@fa-bell-slash-o: \"\\f1f7\";\n@fa-trash: \"\\f1f8\";\n@fa-copyright: \"\\f1f9\";\n@fa-at: \"\\f1fa\";\n@fa-eyedropper: \"\\f1fb\";\n@fa-paint-brush: \"\\f1fc\";\n@fa-birthday-cake: \"\\f1fd\";\n@fa-area-chart: \"\\f1fe\";\n@fa-pie-chart: \"\\f200\";\n@fa-line-chart: \"\\f201\";\n@fa-lastfm: \"\\f202\";\n@fa-lastfm-square: \"\\f203\";\n@fa-toggle-off: \"\\f204\";\n@fa-toggle-on: \"\\f205\";\n@fa-bicycle: \"\\f206\";\n@fa-bus: \"\\f207\";\n@fa-ioxhost: \"\\f208\";\n@fa-angellist: \"\\f209\";\n@fa-cc: \"\\f20a\";\n@fa-ils: \"\\f20b\";\n@fa-meanpath: \"\\f20c\";\n\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/css/ztree/demo.css",
    "content": "html, 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;}\nbody {color: #2f332a;font: 15px/21px Arial, Helvetica, simsun, sans-serif;background: #f0f6e4 \\9;}\nh1, h2, h3, h4, h5, h6 {color: #2f332a;font-weight: bold;font-family: Helvetica, Arial, sans-serif;padding-bottom: 5px;}\nh1 {font-size: 24px;line-height: 34px;text-align: center;}\nh2 {font-size: 14px;line-height: 24px;padding-top: 5px;}\nh6 {font-weight: normal;font-size: 12px;letter-spacing: 1px;line-height: 24px;text-align: center;}\na {color:#3C6E31;text-decoration: underline;}\na:hover {background-color:#3C6E31;color:white;}\ninput.radio {margin: 0 2px 0 8px;}\ninput.radio.first {margin-left:0;}\ninput.empty {color: lightgray;}\ncode {color: #2f332a;}\n.highlight_red {color:#A60000;}\n.highlight_green {color:#A7F43D;}\nli {list-style: circle;font-size: 12px;}\nli.title {list-style: none;}\nul.list {margin-left: 17px;}\n\ndiv.content_wrap {width: 600px;height:380px;}\ndiv.content_wrap div.left{float: left;width: 250px;}\ndiv.content_wrap div.right{float: right;width: 340px;}\ndiv.zTreeDemoBackground {width:250px;height:362px;text-align:left;}\n\nul.ztree {margin-top: 10px;border: 1px solid #617775;background: #f0f6e4;width:220px;height:360px;overflow-y:scroll;overflow-x:auto;}\nul.log {border: 1px solid #617775;background: #f0f6e4;width:300px;height:170px;overflow: hidden;}\nul.log.small {height:45px;}\nul.log li {color: #666666;list-style: none;padding-left: 10px;}\nul.log li.dark {background-color: #E3E3E3;}\n\n/* ruler */\ndiv.ruler {height:20px; width:220px; background-color:#f0f6e4;border: 1px solid #333; margin-bottom: 5px; cursor: pointer}\ndiv.ruler div.cursor {height:20px; width:30px; background-color:#3C6E31; color:white; text-align: right; padding-right: 5px; cursor: pointer}"
  },
  {
    "path": "open-layui-web/src/main/view/static/css/ztree/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.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"
  },
  {
    "path": "open-layui-web/src/main/view/static/css/ztree/zTreeStyle/zTreeStyle.css",
    "content": "/*-------------------------------------\nzTree Style\n\nversion:\t3.4\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": "open-layui-web/src/main/view/static/editor-app/app.js",
    "content": "/*\n * Activiti Modeler component part of the Activiti project\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * \n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n */\n'use strict';\n\nvar activitiModeler = angular.module('activitiModeler', [\n  'ngCookies',\n  'ngResource',\n  'ngSanitize',\n  'ngRoute',\n  'ngDragDrop',\n  'mgcrea.ngStrap', \n  'ngGrid',\n  'ngAnimate',\n  'pascalprecht.translate',\n  'duScroll'\n]);\n\nvar activitiModule = activitiModeler;\n\nactivitiModeler\n  // Initialize routes\n  .config(['$selectProvider', '$translateProvider', function ($selectProvider, $translateProvider) {\n\n      // Override caret for bs-select directive\n      angular.extend($selectProvider.defaults, {\n          caretHtml: '&nbsp;<i class=\"icon icon-caret-down\"></i>'\n      });\n        \n        // Initialize angular-translate\n        $translateProvider.useStaticFilesLoader({\n            prefix: './editor-app/i18n/',\n            suffix: '.json'\n        });\n\n        $translateProvider.preferredLanguage('en');\n\n        // remember language\n        $translateProvider.useCookieStorage();\n        \n  }])\n  .run(['$rootScope', '$timeout', '$modal', '$translate', '$location', '$window', '$http', '$q',\n        function($rootScope, $timeout, $modal, $translate, $location, $window, $http, $q) {\n\t  \n\t\t\t  $rootScope.config = ACTIVITI.CONFIG;\n\t\t\t  \n\t\t\t  $rootScope.editorInitialized = false;\n\t\t      \n\t\t      $rootScope.editorFactory = $q.defer();\n\t\t\n\t\t      $rootScope.forceSelectionRefresh = false;\n\t\t\n\t\t      $rootScope.ignoreChanges = false; // by default never ignore changes\n\t\t      \n\t\t      $rootScope.validationErrors = [];\n\t\t      \n\t\t      $rootScope.staticIncludeVersion = Date.now();\n\n\t\t\t  /**\n\t\t       * A 'safer' apply that avoids concurrent updates (which $apply allows).\n\t\t       */\n\t\t      $rootScope.safeApply = function(fn) {\n\t\t          var phase = this.$root.$$phase;\n\t\t          if(phase == '$apply' || phase == '$digest') {\n\t\t              if(fn && (typeof(fn) === 'function')) {\n\t\t                  fn();\n\t\t              }\n\t\t          } else {\n\t\t              this.$apply(fn);\n\t\t          }\n\t\t      };\n\t  \n\t  \n            /**\n             * Initialize the event bus: couple all Oryx events with a dispatch of the\n             * event of the event bus. This way, it gets much easier to attach custom logic\n             * to any event.\n             */\n\n            /* Helper method to fetch model from server (always needed) */\n            function fetchModel(modelId) {\n\n                var modelUrl = KISBPM.URL.getModel(modelId);\n\n                $http({method: 'GET', url: modelUrl}).\n                    success(function (data, status, headers, config) {\n                        $rootScope.editor = new ORYX.Editor(data);\n                        $rootScope.modelData = angular.fromJson(data);\n                        $rootScope.editorFactory.resolve();\n                    }).\n                    error(function (data, status, headers, config) {\n                      console.log('Error loading model with id ' + modelId + ' ' + data);\n                    });\n            }\n\n\n            function initScrollHandling() {\n                var canvasSection = jQuery('#canvasSection');\n                canvasSection.scroll(function() {\n\n                    // Hides the resizer and quick menu items during scrolling\n\n                    var selectedElements = $rootScope.editor.selection;\n                    var subSelectionElements = $rootScope.editor._subSelection;\n\n                    $rootScope.selectedElements = selectedElements;\n                    $rootScope.subSelectionElements = subSelectionElements;\n                    if (selectedElements && selectedElements.length > 0) {\n                    \t$rootScope.selectedElementBeforeScrolling = selectedElements[0];\n                    }\n\n                    jQuery('.Oryx_button').each(function(i, obj) {\n                    \t$rootScope.orginalOryxButtonStyle = obj.style.display;\n                    \tobj.style.display = 'none';\n                    });\n                    \n                    jQuery('.resizer_southeast').each(function(i, obj) {\n                    \t$rootScope.orginalResizerSEStyle = obj.style.display;\n                        obj.style.display = 'none';\n                    });\n                    jQuery('.resizer_northwest').each(function(i, obj) {\n                    \t$rootScope.orginalResizerNWStyle = obj.style.display;\n                        obj.style.display = 'none';\n                    });\n                    $rootScope.editor.handleEvents({type:ORYX.CONFIG.EVENT_CANVAS_SCROLL});\n                });\n\n                canvasSection.scrollStopped(function(){\n\n                    // Puts the quick menu items and resizer back when scroll is stopped.\n\n                    $rootScope.editor.setSelection([]); // needed cause it checks for element changes and does nothing if the elements are the same\n                    $rootScope.editor.setSelection($rootScope.selectedElements, $rootScope.subSelectionElements);\n                    $rootScope.selectedElements = undefined;\n                    $rootScope.subSelectionElements = undefined;\n\n                    function handleDisplayProperty(obj) {\n                        if (jQuery(obj).position().top > 0) {\n                            obj.style.display = 'block';\n                        } else {\n                            obj.style.display = 'none';\n                        }\n                    }\n\n                    jQuery('.Oryx_button').each(function(i, obj) {\n                        handleDisplayProperty(obj);\n                    });\n                    \n                    jQuery('.resizer_southeast').each(function(i, obj) {\n                        handleDisplayProperty(obj);\n                    });\n                    jQuery('.resizer_northwest').each(function(i, obj) {\n                        handleDisplayProperty(obj);\n                    });\n\n                });\n            }\n\n            /**\n             * Initialize the Oryx Editor when the content has been loaded\n             */\n            $rootScope.$on('$includeContentLoaded', function (event) {\n\t            if (!$rootScope.editorInitialized) {\n\n\t            \tORYX._loadPlugins();\n\t\n\t                var modelId = EDITOR.UTIL.getParameterByName('modelId');\n\t                fetchModel(modelId);\n\t\n\t                $rootScope.window = {};\n\t                var updateWindowSize = function() {\n\t                    $rootScope.window.width = $window.innerWidth;\n\t                    $rootScope.window.height  = $window.innerHeight;\n\t                };\n\t\n\t                // Window resize hook\n\t                angular.element($window).bind('resize', function() {\n\t                    $rootScope.safeApply(updateWindowSize());\n\t                });\n\t\n\t                $rootScope.$watch('window.forceRefresh', function(newValue) {\n\t                    if(newValue) {\n\t                        $timeout(function() {\n\t                            updateWindowSize();\n\t                            $rootScope.window.forceRefresh = false;\n\t                        });\n\t                    }\n\t                });\n\t\n\t                updateWindowSize();\n\n\t                // Hook in resizing of main panels when window resizes\n\t                // TODO: perhaps move to a separate JS-file?\n\t                jQuery(window).resize(function () {\n\n\t                    // Calculate the offset based on the bottom of the module header\n\t                    var offset = jQuery(\"#editor-header\").offset();\n\t                    var propSectionHeight = jQuery('#propertySection').height();\n\t                    var canvas = jQuery('#canvasSection');\n\t                    var mainHeader = jQuery('#main-header');\n\n\t                    if (offset == undefined || offset === null\n\t                        || propSectionHeight === undefined || propSectionHeight === null\n\t                        || canvas === undefined || canvas === null || mainHeader === null) {\n\t                        return;\n\t                    }\n\t                    \n\t                    if ($rootScope.editor)\n\t                \t{\n\t        \t        \tvar selectedElements = $rootScope.editor.selection;\n\t        \t            var subSelectionElements = $rootScope.editor._subSelection;\n\t        \t\n\t        \t            $rootScope.selectedElements = selectedElements;\n\t        \t            $rootScope.subSelectionElements = subSelectionElements;\n\t        \t            if (selectedElements && selectedElements.length > 0)\n\t        \t            {\n\t        \t            \t$rootScope.selectedElementBeforeScrolling = selectedElements[0];\n\t        \t            \t\n\t        \t            \t$rootScope.editor.setSelection([]); // needed cause it checks for element changes and does nothing if the elements are the same\n\t        \t                $rootScope.editor.setSelection($rootScope.selectedElements, $rootScope.subSelectionElements);\n\t        \t                $rootScope.selectedElements = undefined;\n\t        \t                $rootScope.subSelectionElements = undefined;\n\t        \t            }\n\t                \t}\n\n\t                    var totalAvailable = jQuery(window).height() - offset.top - mainHeader.height() - 21;\n\t                    canvas.height(totalAvailable - propSectionHeight);\n\t                    jQuery('#paletteSection').height(totalAvailable);\n\n\t                    // Update positions of the resize-markers, according to the canvas\n\n\t                    var actualCanvas = null;\n\t                    if (canvas && canvas[0].children[1]) {\n\t                        actualCanvas = canvas[0].children[1];\n\t                    }\n\n\t                    var canvasTop = canvas.position().top;\n\t                    var canvasLeft = canvas.position().left;\n\t                    var canvasHeight = canvas[0].clientHeight;\n\t                    var canvasWidth = canvas[0].clientWidth;\n\t                    var iconCenterOffset = 8;\n\t                    var widthDiff = 0;\n\n\t                    var actualWidth = 0;\n\t                    if(actualCanvas) {\n\t                        // In some browsers, the SVG-element clientwidth isn't available, so we revert to the parent\n\t                        actualWidth = actualCanvas.clientWidth || actualCanvas.parentNode.clientWidth;\n\t                    }\n\n\n\t                    if(actualWidth < canvas[0].clientWidth) {\n\t                        widthDiff = actualWidth - canvas[0].clientWidth;\n\t                        // In case the canvas is smaller than the actual viewport, the resizers should be moved\n\t                        canvasLeft -= widthDiff / 2;\n\t                        canvasWidth += widthDiff;\n\t                    }\n\n\t                    var iconWidth = 17;\n\t                    var iconOffset = 20;\n\n\t                    var north = jQuery('#canvas-grow-N');\n\t                    north.css('top', canvasTop + iconOffset + 'px');\n\t                    north.css('left', canvasLeft - 10 + (canvasWidth - iconWidth) / 2 + 'px');\n\n\t                    var south = jQuery('#canvas-grow-S');\n\t                    south.css('top', (canvasTop + canvasHeight - iconOffset - iconCenterOffset) +  'px');\n\t                    south.css('left', canvasLeft - 10 + (canvasWidth - iconWidth) / 2 + 'px');\n\n\t                    var east = jQuery('#canvas-grow-E');\n\t                    east.css('top', canvasTop - 10 + (canvasHeight - iconWidth) / 2 + 'px');\n\t                    east.css('left', (canvasLeft + canvasWidth - iconOffset - iconCenterOffset) + 'px');\n\n\t                    var west = jQuery('#canvas-grow-W');\n\t                    west.css('top', canvasTop -10 + (canvasHeight - iconWidth) / 2 + 'px');\n\t                    west.css('left', canvasLeft + iconOffset + 'px');\n\n\t                    north = jQuery('#canvas-shrink-N');\n\t                    north.css('top', canvasTop + iconOffset + 'px');\n\t                    north.css('left', canvasLeft + 10 + (canvasWidth - iconWidth) / 2 + 'px');\n\n\t                    south = jQuery('#canvas-shrink-S');\n\t                    south.css('top', (canvasTop + canvasHeight - iconOffset - iconCenterOffset) +  'px');\n\t                    south.css('left', canvasLeft +10 + (canvasWidth - iconWidth) / 2 + 'px');\n\n\t                    east = jQuery('#canvas-shrink-E');\n\t                    east.css('top', canvasTop + 10 + (canvasHeight - iconWidth) / 2 +  'px');\n\t                    east.css('left', (canvasLeft + canvasWidth - iconOffset - iconCenterOffset) + 'px');\n\n\t                    west = jQuery('#canvas-shrink-W');\n\t                    west.css('top', canvasTop + 10 + (canvasHeight - iconWidth) / 2 + 'px');\n\t                    west.css('left', canvasLeft + iconOffset + 'px');\n\t                });\n\n\t                jQuery(window).trigger('resize');\n\n\t                jQuery.fn.scrollStopped = function(callback) {\n\t                    jQuery(this).scroll(function(){\n\t                        var self = this, $this = jQuery(self);\n\t                        if ($this.data('scrollTimeout')) {\n\t                            clearTimeout($this.data('scrollTimeout'));\n\t                        }\n\t                        $this.data('scrollTimeout', setTimeout(callback,50,self));\n\t                    });\n\t                };\n\t                \n\t                // Always needed, cause the DOM element on which the scroll event listeners are attached are changed for every new model\n\t                initScrollHandling();\n\t                \n\t                $rootScope.editorInitialized = true;\n\t            }\n            });\n\n            /**\n             * Initialize the event bus: couple all Oryx events with a dispatch of the\n             * event of the event bus. This way, it gets much easier to attach custom logic\n             * to any event.\n             */\n\n            $rootScope.editorFactory.promise.then(function() {\n\n                KISBPM.eventBus.editor = $rootScope.editor;\n\n                var eventMappings = [\n                    { oryxType : ORYX.CONFIG.EVENT_SELECTION_CHANGED, kisBpmType : KISBPM.eventBus.EVENT_TYPE_SELECTION_CHANGE },\n                    { oryxType : ORYX.CONFIG.EVENT_DBLCLICK, kisBpmType : KISBPM.eventBus.EVENT_TYPE_DOUBLE_CLICK },\n                    { oryxType : ORYX.CONFIG.EVENT_MOUSEOUT, kisBpmType : KISBPM.eventBus.EVENT_TYPE_MOUSE_OUT },\n                    { oryxType : ORYX.CONFIG.EVENT_MOUSEOVER, kisBpmType : KISBPM.eventBus.EVENT_TYPE_MOUSE_OVER }\n\n                ];\n\n                eventMappings.forEach(function(eventMapping) {\n                    $rootScope.editor.registerOnEvent(eventMapping.oryxType, function(event) {\n                        KISBPM.eventBus.dispatch(eventMapping.kisBpmType, event);\n                    });\n                });\n                \n                $rootScope.editor.registerOnEvent(ORYX.CONFIG.EVENT_SHAPEREMOVED, function (event) {\n    \t    \t\tvar validateButton = document.getElementById(event.shape.resourceId + \"-validate-button\");\n    \t    \t\tif (validateButton)\n    \t    \t\t{\n    \t    \t\t\tvalidateButton.style.display = 'none';\n    \t    \t\t}\n                });\n\n                // The Oryx canvas is ready (we know since we're in this promise callback) and the\n                // event bus is ready. The editor is now ready for use\n                KISBPM.eventBus.dispatch(KISBPM.eventBus.EVENT_TYPE_EDITOR_READY, {type : KISBPM.eventBus.EVENT_TYPE_EDITOR_READY});\n\n            });\n            \n            // Alerts\n            $rootScope.alerts = {\n                queue: []\n            };\n          \n            $rootScope.showAlert = function(alert) {\n                if(alert.queue.length > 0) {\n                    alert.current = alert.queue.shift();\n                    // Start timout for message-pruning\n                    alert.timeout = $timeout(function() {\n                        if (alert.queue.length == 0) {\n                            alert.current = undefined;\n                            alert.timeout = undefined;\n                        } else {\n                            $rootScope.showAlert(alert);\n                        }\n                    }, (alert.current.type == 'error' ? 5000 : 1000));\n                } else {\n                    $rootScope.alerts.current = undefined;\n                }\n            };\n          \n            $rootScope.addAlert = function(message, type) {\n                var newAlert = {message: message, type: type};\n                if (!$rootScope.alerts.timeout) {\n                    // Timeout for message queue is not running, start one\n                    $rootScope.alerts.queue.push(newAlert);\n                    $rootScope.showAlert($rootScope.alerts);\n                } else {\n                    $rootScope.alerts.queue.push(newAlert);\n                }\n            };\n          \n            $rootScope.dismissAlert = function() {\n                if (!$rootScope.alerts.timeout) {\n                    $rootScope.alerts.current = undefined;\n                } else {\n                    $timeout.cancel($rootScope.alerts.timeout);\n                    $rootScope.alerts.timeout = undefined;\n                    $rootScope.showAlert($rootScope.alerts);\n                }\n            };\n          \n            $rootScope.addAlertPromise = function(promise, type) {\n                if (promise) {\n                    promise.then(function(data) {\n                        $rootScope.addAlert(data, type);\n                    });\n                }\n            };\n          \n        }\n  ])\n\n    // Moment-JS date-formatting filter\n    .filter('dateformat', function() {\n        return function(date, format) {\n            if (date) {\n                if (format) {\n                    return moment(date).format(format);\n                } else {\n                    return moment(date).calendar();\n                }\n            }\n            return '';\n        };\n    });\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/editor-app/editor/css/editor.css",
    "content": "body, html {\n    font-family: tahoma,arial,helvetica,sans-serif;\n    font-size: 12px;\n}\n\n/*********\n * SVG Style\n */\n\ntext,\ntext * {\n    cursor:default;\n    -webkit-user-select: none;\n}\n\n/*********\n * HEADER SECTION\n *\n */\n\n#oryx_canvas_htmlContainer {\n\n}\n\n.ORYX_Editor {\n    background: white;\n    border: none;\n    margin:-5px;\n    margin-top:0px;\n    width:1200px;\n    height:600px;\n}\n\n.icon-large {\n\twidth:18px !important;\n}\n\n#oryxcanvas {\n\twidth:1200px;\n\theight:600px;\n}\n\n/** Resizer for the Canvas **/\n.canvas_resize_indicator_area {\n\n\tmargin\t\t:auto;\n\tdisplay\t\t:block;\n\theight\t\t:30px;\n\tleft\t\t:20%;\n\tposition\t:absolute;\n\ttext-align\t:center;\n\ttop\t\t\t:0;\n\twidth\t\t:60%;\n\n}\n\n.canvas_resize_indicator {\n\n\twidth\t\t: 15px;\n\theight\t\t: 15px;\n\tposition\t: absolute;\n\tdisplay\t\t: block;\n\tmargin\t\t: auto;\n\topacity\t\t: 0.6;\n}\n\n.canvas_resize_indicator:hover {\n\n\topacity\t\t: 1.0;\n}\n/** End Resizer **/\n\n.Oryx_down {\n\n}\n\n.Oryx_button img {\n\twidth:16px;\n\theight:16px;\n\ttop:0px;\n\tleft:0px;\n\tline-height: 16px;\n}\n\n.Oryx_Right .Oryx_button,\n.Oryx_Left .Oryx_button,\n.Oryx_Top .Oryx_button,\n.Oryx_Bottom .Oryx_button {\n\topacity: 0.5;\n}\n\n.Oryx_button.x-opacity-0 {\n\topacity: 0;\n\tdisplay:none;\n}\n\n.Oryx_button.x-opacity-10 {\n\topacity: 0.1;\n}\n\n.Oryx_button.x-opacity-20 {\n\topacity: 0.2;\n}\n\n.Oryx_button.x-opacity-50 {\n\topacity: 0.5;\n}\n\n.Oryx_Right:hover .Oryx_button,\n.Oryx_Left:hover .Oryx_button,\n.Oryx_Top:hover .Oryx_button,\n.Oryx_Bottom:hover .Oryx_button {\n\topacity: 0.7;\n\tdisplay:block;\n}\n\n\n.Oryx_button img {\n\ttop:0px;\n}\n\n.Oryx_Left img {\n\ttop:0px;\n}\n\n.Oryx_button {\n\twidth:24px;\n\theight:24px;\n\tpadding:2px;\n\tposition:absolute;\n\tbackground-color: #ffffff;\n\tbackground-color: rgba(255,255,255,0.7);\n\tcursor: pointer;\n}\n\n.Oryx_button_with_caption {\n\twidth:inherit;\n\theight:16px;\n\tpadding:4px;\n\tposition:absolute;\n}\n\n/*** Resizer ***/\n\n.resizer_southeast,\n.resizer_northwest {\n\twidth:12px;\n\theight:12px;\n\tposition:relative;\n\tbackground-color: transparent;\n\tbackground-repeat:no-repeat;\n}\n\n/*** Selection Frame ***/\n\n.Oryx_SelectionFrame{\n\tposition:absolute;\n\tborder:1px dotted gray;\n\tbackground:none;\n}\n\n.LoadingIndicator {\n    background-image: url('../../images/loading.gif');\n}\n\n.Oryx_hover, .Oryx_button:hover {\n    background-color: #999999;\n    background-color: rgba(193, 229, 238, 0.7);\n    opacity: 1 !important;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n}\n\n.ValidateButton {\n    width:24px;\n    height:24px;\n    padding:2px;\n    position:absolute;\n    cursor: pointer;\n}\n\n.ValidateButton:hover {\n    background-color: #999999;\n    background-color: rgba(193, 229, 238, 0.7);\n    opacity: 1 !important;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n}\n\n.resizer_southeast {\n    background-image:url(../../images/se-handle-dark.gif);\n    cursor: se-resize;\n    background-position: 4px 4px;\n}\n\n.resizer_northwest {\n    background-image:url(../../images/nw-handle-dark.gif);\n    cursor: nw-resize;\n    background-position: -2px -2px;\n}\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/editor-app/editor/oryx.debug.js",
    "content": "/**\n * @namespace Oryx name space for different utility methods\n * @name ORYX.Utils\n*/\n\nif(!ORYX) var ORYX = {};\n\nORYX.Utils = {\n    /**\n     * General helper method for parsing a param out of current location url\n     * @example\n     * // Current url in Browser => \"http://oryx.org?param=value\"\n     * ORYX.Utils.getParamFromUrl(\"param\") // => \"value\" \n     * @param {Object} name\n     */\n    getParamFromUrl: function(name){\n        name = name.replace(/[\\[]/, \"\\\\\\[\").replace(/[\\]]/, \"\\\\\\]\");\n        var regexS = \"[\\\\?&]\" + name + \"=([^&#]*)\";\n        var regex = new RegExp(regexS);\n        var results = regex.exec(window.location.href);\n        if (results == null) {\n            return null;\n        }\n        else {\n            return results[1];\n        }\n    },\n\t\n\tadjustLightness: function(){\n\t\treturn arguments[0];\t\n\t},\n\t\n\tadjustGradient: function(gradient, reference){\n\t\t\n\t\tif (ORYX.CONFIG.DISABLE_GRADIENT && gradient){\n\t\t\n\t\t\tvar col = reference.getAttributeNS(null, \"stop-color\") || \"#ffffff\";\n\t\t\t\n\t\t\t$A(gradient.getElementsByTagName(\"stop\")).each(function(stop){\n\t\t\t\tif (stop == reference){ return; }\n\t\t\t\tstop.setAttributeNS(null, \"stop-color\", col);\n\t\t\t});\n\t\t}\n\t}\n}\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nXMLNS = {\n\tATOM:\t\"http://www.w3.org/2005/Atom\",\n\tXHTML:\t\"http://www.w3.org/1999/xhtml\",\n\tERDF:\t\"http://purl.org/NET/erdf/profile\",\n\tRDFS:\t\"http://www.w3.org/2000/01/rdf-schema#\",\n\tRDF:\t\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\",\n\tRAZIEL: \"http://b3mn.org/Raziel\",\n\n\tSCHEMA: \"\"\n};\n\n//TODO kann kickstart sich vielleicht auch um die erzeugung von paketen/\n// namespaces k???mmern? z.b. requireNamespace(\"ORYX.Core.SVG\");\nvar Kickstart = {\n \tstarted: false,\n\tcallbacks: [],\n\talreadyLoaded: [],\n\tPATH: '',\n\n\tload: function() { Kickstart.kick(); },\n\n\tkick: function() {\n\t\t//console.profile(\"loading\");\n\t\tif(!Kickstart.started) {\n\t\t\tKickstart.started = true;\n\t\t\tKickstart.callbacks.each(function(callback){\n\t\t\t\t// call the registered callback asynchronously.\n\t\t\t\twindow.setTimeout(callback, 1);\n\t\t\t});\n\t\t}\n\t},\n\n\tregister: function(callback) {\n\t\t//TODO Add some mutual exclusion between kick and register calls.\n\t\twith(Kickstart) {\n\t\t\tif(started) window.setTimeout(callback, 1);\n\t\t\telse Kickstart.callbacks.push(callback)\n\t\t}\n\t},\n\n\t/**\n\t * Loads a js, assuring that it has only been downloaded once.\n\t * @param {String} url the script to load.\n\t */\n\trequire: function(url) {\n\t\t// if not already loaded, include it.\n\t\tif(Kickstart.alreadyLoaded.member(url))\n\t\t\treturn false;\n\t\treturn Kickstart.include(url);\n\t},\n\n\t/**\n\t * Loads a js, regardless of whether it has only been already downloaded.\n\t * @param {String} url the script to load.\n\t */\n\tinclude: function(url) {\n\n\t\t// prepare a script tag and place it in html head.\n\t\tvar head = document.getElementsByTagNameNS(XMLNS.XHTML, 'head')[0];\n\t\tvar s = document.createElementNS(XMLNS.XHTML, \"script\");\n\t\ts.setAttributeNS(XMLNS.XHTML, 'type', 'text/javascript');\n\t   \ts.src = Kickstart.PATH + url;\n\n\t\t//TODO macht es sinn, dass neue skript als letztes kind in den head\n\t\t// einzubinden (stichwort reihenfolge der skript tags)?\n\t   \thead.appendChild(s);\n\n\t\t// remember this url.\n\t\tKickstart.alreadyLoaded.push(url);\n\n\t\treturn true;\n\t}\n}\n\n// register kickstart as the new onload event listener on current window.\n// previous listener(s) are triggered to launch with kickstart.\nEvent.observe(window, 'load', Kickstart.load);/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nvar ERDF = {\n\n\tLITERAL: 0x01,\n\tRESOURCE: 0x02,\n\tDELIMITERS: ['.', '-'],\n\tHASH: '#',\n\tHYPHEN: \"-\",\n\n\tschemas: [],\n\tcallback: undefined,\n\tlog: undefined,\n\n\tinit: function(callback) {\n\t\t\n\t\t// init logging.\n\t\t//ERDF.log = Log4js.getLogger(\"oryx\");\n\t\t//ERDF.log.setLevel(Log4js.Level.ALL);\n\t\t//ERDF.log.addAppender(new ConsoleAppender(ERDF.log, false));\n\n\t\t//if(ERDF.log.isTraceEnabled())\n\t\t//\tERDF.log.trace(\"ERDF Parser is initialized.\");\n\n\t\t// register callbacks and default schemas.\n\t\tERDF.callback = callback;\n\t\tERDF.registerSchema('schema', XMLNS.SCHEMA);\n\t\tERDF.registerSchema('rdfs', XMLNS.RDFS);\n\t},\n\n\trun: function() {\n\n\t\t//if(ERDF.log.isTraceEnabled())\n\t\t//\tERDF.log.trace(\"ERDF Parser is running.\");\n\n\t\t// do the work.\n\t\treturn ERDF._checkProfile() && ERDF.parse();\n\t},\n\t\n\tparse: function() {\n\t\t\n\t\t//(ERDF.log.isDebugEnabled())\n\t\t//\tERDF.log.debug(\"Begin parsing document metadata.\");\n\t\t\n\t\t// time measuring\n\t\tERDF.__startTime = new Date();\n\n\t\tvar bodies = document.getElementsByTagNameNS(XMLNS.XHTML, 'body');\n\t\tvar subject = {type: ERDF.RESOURCE, value: ''};\n\n\t\tvar result = ERDF._parseDocumentMetadata() &&\n\t\t\tERDF._parseFromTag(bodies[0], subject);\n\t\t\t\n\t\t// time measuring\n\t\tERDF.__stopTime = new Date();\n\n\t\tvar duration = (ERDF.__stopTime - ERDF.__startTime)/1000.;\n\t\t//alert('ERDF parsing took ' + duration + ' s.');\n\t\t\n\t\treturn result;\n\t},\n\t\n\t_parseDocumentMetadata: function() {\n\n\t\t// get links from head element.\n\t\tvar heads = document.getElementsByTagNameNS(XMLNS.XHTML, 'head');\n\t\tvar links = heads[0].getElementsByTagNameNS(XMLNS.XHTML, 'link');\n\t\tvar metas = heads[0].getElementsByTagNameNS(XMLNS.XHTML, 'meta');\n\n\t\t// process links first, since they could contain schema definitions.\n\t\t$A(links).each(function(link) {\n\t\t\tvar properties = link.getAttribute('rel');\n\t\t\tvar reversedProperties = link.getAttribute('rev');\n\t\t\tvar value = link.getAttribute('href');\n\t\t\t\n\t\t\tERDF._parseTriplesFrom(\n\t\t\t\tERDF.RESOURCE, '',\n\t\t\t\tproperties,\n\t\t\t\tERDF.RESOURCE, value);\n\t\t\t\t\n\t\t\tERDF._parseTriplesFrom(\n\t\t\t\tERDF.RESOURCE, value,\n\t\t\t\treversedProperties,\n\t\t\t\tERDF.RESOURCE, '');\n\t\t});\n\n\t\t// continue with metas.\n\t\t$A(metas).each(function(meta) {\n\t\t\tvar property = meta.getAttribute('name');\n\t\t\tvar value = meta.getAttribute('content');\n\t\t\t\n\t\t\tERDF._parseTriplesFrom(\n\t\t\t\tERDF.RESOURCE, '',\n\t\t\t\tproperty,\n\t\t\t\tERDF.LITERAL, value);\n\t\t});\n\n\t\treturn true;\n\t},\n\t\n\t_parseFromTag: function(node, subject, depth) {\n\t\t\n\t\t// avoid parsing non-xhtml content.\n\t\tif(!node || !node.namespaceURI || node.namespaceURI != XMLNS.XHTML) { return; }\n\t\t\n\t\t// housekeeping.\n\t\tif(!depth) depth=0;\n\t\tvar id = node.getAttribute('id');\n\n\t\t// some logging.\n\t\t//if(ERDF.log.isTraceEnabled())\n\t\t//\tERDF.log.trace(\">\".times(depth) + \" Parsing \" + node.nodeName + \" (\"+node.nodeType+\") for data on \" +\n\t\t//\t\t((subject.type == ERDF.RESOURCE) ? ('&lt;' + subject.value + '&gt;') : '') +\n\t\t//\t\t((subject.type == ERDF.LITERAL) ? '\"' + subject.value + '\"' : ''));\n\t\t\n\t\t/* triple finding! */\n\t\t\n\t\t// in a-tags...\n\t\tif(node.nodeName.endsWith(':a') || node.nodeName == 'a') {\n\t\t\tvar properties = node.getAttribute('rel');\n\t\t\tvar reversedProperties = node.getAttribute('rev');\n\t\t\tvar value = node.getAttribute('href');\n\t\t\tvar title = node.getAttribute('title');\n\t\t\tvar content = node.textContent;\n\n\t\t\t// rel triples\n\t\t\tERDF._parseTriplesFrom(\n\t\t\t\tsubject.type, subject.value,\n\t\t\t\tproperties,\n\t\t\t\tERDF.RESOURCE, value,\n\t\t\t\tfunction(triple) {\n\t\t\t\t\tvar label = title? title : content;\n\t\t\t\t\t\n\t\t\t\t\t// label triples\n\t\t\t\t\tERDF._parseTriplesFrom(\n\t\t\t\t\t\ttriple.object.type, triple.object.value,\n\t\t\t\t\t\t'rdfs.label',\n\t\t\t\t\t\tERDF.LITERAL, label);\n\t\t\t\t});\n\n\t\t\t// rev triples\n\t\t\tERDF._parseTriplesFrom(\n\t\t\t\tsubject.type, subject.value,\n\t\t\t\treversedProperties,\n\t\t\t\tERDF.RESOURCE, '');\n\t\t\t\t\n\t\t\t// type triples\n\t\t\tERDF._parseTypeTriplesFrom(\n\t\t\t\tsubject.type, subject.value,\n\t\t\t\tproperties);\n\n\t\t// in img-tags...\n\t\t} else if(node.nodeName.endsWith(':img') || node.nodeName == 'img') {\n\t\t\tvar properties = node.getAttribute('class');\n\t\t\tvar value = node.getAttribute('src');\n\t\t\tvar alt = node.getAttribute('alt');\n\n\t\t\tERDF._parseTriplesFrom(\n\t\t\t\tsubject.type, subject.value,\n\t\t\t\tproperties,\n\t\t\t\tERDF.RESOURCE, value,\n\t\t\t\tfunction(triple) {\n\t\t\t\t\tvar label = alt;\n\t\t\t\t\t\n\t\t\t\t\t// label triples\n\t\t\t\t\tERDF._parseTriplesFrom(\n\t\t\t\t\t\ttriple.object.type, triple.object.value,\n\t\t\t\t\t\t'rdfs.label',\n\t\t\t\t\t\tERDF.LITERAL, label);\n\t\t\t\t});\n\n\t\t}\n\t\t\n\t\t// in every tag\n\t\tvar properties = node.getAttribute('class');\n\t\tvar title = node.getAttribute('title');\n\t\tvar content = node.textContent;\n\t\tvar label = title ? title : content;\n\t\t\n\t\t// regular triples\n\t\tERDF._parseTriplesFrom(\n\t\t\tsubject.type, subject.value,\n\t\t\tproperties,\n\t\t\tERDF.LITERAL, label);\n\n\t\tif(id) subject = {type: ERDF.RESOURCE, value: ERDF.HASH+id};\n\t\t\n\t\t// type triples\n\t\tERDF._parseTypeTriplesFrom(\n\t\t\tsubject.type, subject.value,\n\t\t\tproperties);\n\n\t\t// parse all children that are element nodes.\n\t\tvar children = node.childNodes;\n\t\tif(children) $A(children).each(function(_node) {\n\t\t\tif(_node.nodeType == _node.ELEMENT_NODE)\n\t\t\t\tERDF._parseFromTag(_node, subject, depth+1); });\n\t},\n\t\n\t_parseTriplesFrom: function(subjectType, subject, properties,\n\t\tobjectType, object, callback) {\n\t\t\n\t\tif(!properties) return;\n\t\tproperties.toLowerCase().split(' ').each( function(property) {\n\t\t\t\n\t\t\t//if(ERDF.log.isTraceEnabled())\n\t\t\t//\tERDF.log.trace(\"Going for property \" + property);\n\n\t\t\tvar schema = ERDF.schemas.find( function(schema) {\n\t\t\t\treturn false || ERDF.DELIMITERS.find( function(delimiter) {\n\t\t\t\t\treturn property.startsWith(schema.prefix + delimiter);\n\t\t\t\t});\n\t\t\t});\n\t\t\t\n\t\t\tif(schema && object) {\n\t\t\t\tproperty = property.substring(\n\t\t\t\t\tschema.prefix.length+1, property.length);\n\t\t\t\tvar triple = ERDF.registerTriple(\n\t\t\t\t\tnew ERDF.Resource(subject),\n\t\t\t\t\t{prefix: schema.prefix, name: property},\n\t\t\t\t\t(objectType == ERDF.RESOURCE) ?\n\t\t\t\t\t\tnew ERDF.Resource(object) :\n\t\t\t\t\t\tnew ERDF.Literal(object));\n\t\t\t\t\t\t\n\t\t\t\tif(callback) callback(triple);\n\t\t\t}\n\t\t});\n\t},\n\t\n\t_parseTypeTriplesFrom: function(subjectType, subject, properties, callback) {\n\t\t\n\t\tif(!properties) return;\n\t\tproperties.toLowerCase().split(' ').each( function(property) {\n\t\t\t\n\t\t\t//if(ERDF.log.isTraceEnabled())\n\t\t\t//\tERDF.log.trace(\"Going for property \" + property);\n\t\t\t\t\n\t\t\tvar schema = ERDF.schemas.find( function(schema) {\n\t\t\t\treturn false || ERDF.DELIMITERS.find( function(delimiter) {\n\t\t\t\t\treturn property.startsWith(ERDF.HYPHEN + schema.prefix + delimiter);\n\t\t\t\t});\n\t\t\t});\n\t\t\t\n\t\t\tif(schema && subject) {\n\t\t\t\tproperty = property.substring(schema.prefix.length+2, property.length);\n\t\t\t\tvar triple = ERDF.registerTriple(\n\t\t\t\t\t(subjectType == ERDF.RESOURCE) ?\n\t\t\t\t\t\tnew ERDF.Resource(subject) :\n\t\t\t\t\t\tnew ERDF.Literal(subject),\n\t\t\t\t\t{prefix: 'rdf', name: 'type'},\n\t\t\t\t\tnew ERDF.Resource(schema.namespace+property));\n\t\t\t\tif(callback) callback(triple);\n\t\t\t}\n\t\t});\n\t},\n\t\n\t/**\n\t * Checks for ERDF profile declaration in head of document.\n\t */\n\t_checkProfile: function() {\n\n\t\t// get profiles from head element.\n\t\tvar heads = document.getElementsByTagNameNS(XMLNS.XHTML, 'head');\n\t\tvar profiles = heads[0].getAttribute(\"profile\");\n\t\tvar found = false;\n\n\t\t// if erdf profile is contained.\n\t\tif(profiles && profiles.split(\" \").member(XMLNS.ERDF)) {\n\n\t\t\t// pass check.\n\t\t\t//if(ERDF.log.isTraceEnabled())\n\t\t\t//\tERDF.log.trace(\"Found ERDF profile \" + XMLNS.ERDF);\n\t\t\treturn true;\n\t\t\t\n\t\t} else {\n\t\t\n\t\t\t// otherwise fail check.\n\t\t\t//if(ERDF.log.isFatalEnabled())\n\t\t\t//\tERDF.log.fatal(\"No ERDF profile found.\");\n\t\t\treturn false;\n\t\t}\n\t},\n\t\n\t__stripHashes: function(s) {\n\t\treturn (s && (typeof s.substring == 'function') && s.substring(0, 1)=='#') ? s.substring(1, s.length) : s;\n\t},\n\t\n\tregisterSchema: function(prefix, namespace) {\n\t\t\n\t\t// TODO check whether already registered, if so, complain.\n\t\tERDF.schemas.push({\n\t\t\tprefix: prefix,\n\t\t\tnamespace: namespace\n\t\t});\n\t\t\n\t\t//if(ERDF.log.isDebugEnabled())\n\t\t//\tERDF.log.debug(\"Prefix '\"+prefix+\"' for '\"+namespace+\"' registered.\");\n\t},\n\t\n\tregisterTriple: function(subject, predicate, object) {\n\t\t\n\t\t// if prefix is schema, this is a schema definition.\n\t\tif(predicate.prefix.toLowerCase() == 'schema')\n\t\t\tthis.registerSchema(predicate.name, object.value);\n\t\t\t\n\t\tvar triple = new ERDF.Triple(subject, predicate, object);\n\t\tERDF.callback(triple);\n\t\t\n\t\t//if(ERDF.log.isInfoEnabled())\n\t\t//\tERDF.log.info(triple)\n\t\t\n\t\t// return the registered triple.\n\t\treturn triple;\n\t},\n\t\n\t__enhanceObject: function() {\n\t\t\n\t\t/* Resource state querying methods */\n\t\tthis.isResource = function() {\n\t\t\treturn this.type == ERDF.RESOURCE };\n\t\tthis.isLocal = function() {\n\t\t\treturn this.isResource() && this.value.startsWith('#') };\n\t\tthis.isCurrentDocument = function() {\n\t\t\treturn this.isResource() && (this.value == '') };\n\t\t\n\t\t/* Resource getter methods.*/\n\t\tthis.getId = function() {\n\t\t\treturn this.isLocal() ? ERDF.__stripHashes(this.value) : false; };\n\n\t\t/* Liiteral state querying methods  */\n\t\tthis.isLiteral = function() {\n\t\t\treturn this.type == ERDF.LIITERAL };\n\t},\n\t\n\tserialize: function(literal) {\n\t\t\n\t\tif(!literal){\n\t\t\treturn \"\";\n\t\t}else if(literal.constructor == String) {\n\t\t\treturn literal;\n\t\t} else if(literal.constructor == Boolean) {\n\t\t\treturn literal? 'true':'false';\n\t\t} else {\n\t\t\treturn literal.toString();\n\t\t}\n\t}\n};\n\n\nERDF.Triple = function(subject, predicate, object) {\n\t\n\tthis.subject = subject;\n\tthis.predicate = predicate;\n\tthis.object = object;\n\t\n\tthis.toString = function() {\n\t\t\n\t\treturn \"[ERDF.Triple] \" +\n\t\t\tthis.subject.toString() + ' ' +\n\t\t\tthis.predicate.prefix + ':' + this.predicate.name + ' ' +\n\t\t\tthis.object.toString();\n\t\t};\n};\n\nERDF.Resource = function(uri) {\n\t\n\tthis.type = ERDF.RESOURCE;\n\tthis.value = uri;\n\tERDF.__enhanceObject.apply(this);\n\t\n\tthis.toString = function() {\n\t\treturn '&lt;' + this.value + '&gt;';\n\t}\n\t\n};\n\nERDF.Literal = function(literal) {\n\t\n\tthis.type = ERDF.LITERAL;\n\tthis.value = ERDF.serialize(literal);\n\tERDF.__enhanceObject.apply(this);\n\n\tthis.toString = function() {\n\t\treturn '\"' + this.value + '\"';\n\t}\n};/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/*\n * Save and triple generation behaviour. Use this area to configure\n * data management to your needs.\n */\nvar USE_ASYNCHRONOUS_REQUESTS =\t\ttrue;\nvar DISCARD_UNUSED_TRIPLES =\t\t\ttrue;\nvar PREFER_SPANS_OVER_DIVS =\t\t\ttrue;\nvar PREFER_TITLE_OVER_TEXTNODE =\t\tfalse;\nvar RESOURCE_ID_PREFIX =\t\t\t\t'resource';\n\nvar SHOW_DEBUG_ALERTS_WHEN_SAVING =\tfalse;\nvar SHOW_EXTENDED_DEBUG_INFORMATION =\tfalse;\n\n/*\n * Back end specific workarounds.\n */\n\nvar USE_ARESS_WORKAROUNDS =\t\ttrue;\n\n/*\n * Data management constants. Do not change these, as they are used\n * both internally and externally to communicate on events and to identify\n * command object actions in triple production and embedding rules.\n */\n\n// Resource constants\nvar RESOURCE_CREATED =\t\t\t0x01;\nvar RESOURCE_REMOVED =\t\t\t0x02;\nvar RESOURCE_SAVED =\t\t\t\t0x04;\nvar RESOURCE_RELOADED =\t\t\t0x08;\nvar RESOURCE_SYNCHRONIZED = \t\t0x10;\n\n// Triple constants\nvar TRIPLE_REMOVE =\t0x01;\nvar TRIPLE_ADD =\t\t0x02;\nvar TRIPLE_RELOAD =\t0x04;\nvar TRIPLE_SAVE =\t\t0x08;\n\nvar PROCESSDATA_REF = 'processdata';\n\n// HTTP status code constants\n//\n//// 2xx\n//const 200_OK =\t\t\t'Ok';\n//const 201_CREATED =\t\t'Created';\n//const 202_ACCEPTED =\t\t'Accepted';\n//const 204_NO_CONTENT =\t'No Content';\n//\n//// 3xx\n//const 301_MOVED_PERMANENTLY =\t'Moved Permanently';\n//const 302_MOVED_TEMPORARILY =\t'Moved Temporarily';\n//const 304_NOT_MODIFIED =\t\t'Not Modified';\n//\n//// 4xx\n//const 400_BAD_REQUEST =\t'Bad Request';\n//const 401_UNAUTHORIZED =\t'Unauthorized';\n//const 403_FORBIDDEN =\t\t'Forbidden';\n//const 404_NOT_FOUND =\t\t'Not Found';\n//const 409_CONFLICT =\t\t'Conflict';\n//\n//// 5xx\n//const 500_INTERNAL_SERVER_ERROR =\t\t'Internal Server Error';\n//const 501_NOT_IMPLEMENTED =\t\t\t'Not Implemented';\n//const 502_BAD_GATEWAY =\t\t\t\t'Bad Gateway';\n//const 503_SERVICE_UNAVAILABLE =\t\t'Service Unavailable';\n//\n/**\n * The Data Management object. Use this one when interacting with page internal\n * data. Initialize data management by DataManager.init();\n * @class DataManager\n */\nvar DataManager = {\n\t\n\t/**\n\t * The init method should be called once in the DataManagers lifetime.\n\t * It causes the DataManager to initialize itself, the erdf parser, do all\n\t * neccessary registrations and configurations, to run the parser and\n\t * from then on deliver all resulting triples.\n\t * No parameters needed are needed in a call to this method.\n\t */\n\tinit: function() {\n\t\tERDF.init(DataManager._registerTriple);\n\t\tDataManager.__synclocal();\n\t},\n\t\n\t/**\n\t * This triple array is meant to be the whole knowledge of the DataManager.\n\t */\n\t_triples: [],\n\t\n\t/**\n\t * This method is meant for callback from erdf parsing. It is not to be\n\t * used in another way than to add triples to the triple store.\n\t * @param {Object} triple the triple to add to the triple store.\n\t */\n\t_registerTriple: function(triple) {\n\t\tDataManager._triples.push(triple)\n\t},\n\t\n\t/**\n\t * The __synclocal method is for internal usage only.\n\t * It performs synchronization with the local document, that is, the triple\n\t * store is adjustet to the content of the document, which could have been\n\t * changed by any other applications running on the same page.\n\t */\n\t__synclocal: function() {\n\t\tDataManager._triples = [];\n\t\tERDF.run();\n\t},\n\t\n\t/**\n\t * Makes the shape passed into this method synchronize itself with the DOM.\n\t * This method returns the shapes resource object for further manipulation.\n\t * @param {Object} shape\n\t */\n\t__synchronizeShape: function(shape) {\n\n\t\tvar r = ResourceManager.getResource(shape.resourceId);\n\t\tvar serialize = shape.serialize();\n\n\t\t// store all serialize values\n\t\tserialize.each( function(ser) {\n\t\t\t\n\t\t\tvar resource = (ser.type == 'resource');\n\t\t\tvar _triple = new ERDF.Triple(\n\t\t\t\tnew ERDF.Resource(shape.resourceId),\n\t\t\t\t{prefix: ser.prefix, name: ser.name},\n\t\t\t\tresource ?\n\t\t\t\t\tnew ERDF.Resource(ser.value) :\n\t\t\t\t\tnew ERDF.Literal(ser.value)\n\t\t\t);\n\t\t\tDataManager.setObject(_triple);\n\t\t});\n\t\t\n\t\treturn r;\n\t},\n\n\t__storeShape: function(shape) {\n\t\t\n\t\t// first synchronize the shape,\n\t\tvar resource = DataManager.__synchronizeShape(shape);\n\t\t\n\t\t// then save the synchronized dom.\n\t\tresource.save();\n\t},\n\t\t\n\t__forceExistance: function(shape) {\n\t\t\n\t\tif(!$(shape.resourceId)) {\n\t\t\t\n\t\t\tif(!$$('.' + PROCESSDATA_REF)[0])\n\t\t\t\tDataManager.graft(XMLNS.XHTML,\n\t\t\t\t\tdocument.getElementsByTagNameNS(XMLNS.XHTML, 'body').item(0), ['div', {'class': PROCESSDATA_REF, 'style':'display:none;'}]);\n\t\t\t\t\n\t\t\t// object is literal\n\t\t\tDataManager.graft(XMLNS.XHTML,\n\t\t\t\t$$('.' + PROCESSDATA_REF)[0], [\n\t\t\t\t\n\t\t\t\t'div', {\n                    'id': shape.resourceId,\n                    //This should be done in a more dynamic way!!!!!\n                    'class': (shape instanceof ORYX.Core.Canvas) ? \"-oryx-canvas\" : undefined\n                }\n\t\t\t]);\n\t\t\t\n\t\t} else {\n\t\t\tvar resource = $(shape.resourceId)\n\t\t\tvar children = $A(resource.childNodes)\n\t\t\tchildren.each( function(child) {\n\t\t\t\tresource.removeChild(child);\n\t\t\t});\n\t\t};\n\t},\n\t\n\t__persistShape: function(shape) {\n\n\t\t// a shape serialization.\n\t\tvar shapeData = shape.serialize();\n\t\t\n\t\t// initialize a triple array and construct a shape resource\n\t\t// to be used in triple generation.\n\t\tvar triplesArray = [];\n\t\tvar shapeResource = new ERDF.Resource(shape.resourceId);\n\n\t\t// remove all triples for this particular shape's resource\n\t\tDataManager.removeTriples( DataManager.query(\n\t\t\tshapeResource, undefined, undefined));\n\n\t\t// for each data set in the shape's serialization\n\t\tshapeData.each( function(data) {\n\n\t\t\t// construct a triple's value\n\t\t\tvar value = (data.type == 'resource') ?\n\t\t\t\tnew ERDF.Resource(data.value) :\n\t\t\t\tnew ERDF.Literal(data.value);\n\n\t\t\t// construct triple and add it to the DOM.\n\t\t\tDataManager.addTriple( new ERDF.Triple(\n\t\t\t\tshapeResource,\n\t\t\t\t{prefix: data.prefix, name: data.name},\n\t\t\t\tvalue\n\t\t\t));\n\t\t});\n\t},\n\t\n\t__persistDOM: function(facade) {\n\n\t\t// getChildShapes gets all shapes (nodes AND edges), deep flag\n\t\t// makes it return a flattened child hierarchy.\n\t\t\n\t\tvar canvas = facade.getCanvas();\n\t\tvar shapes = canvas.getChildShapes(true);\n\t\tvar result = '';\n\t\t\n\t\t// persist all shapes.\n\t\tshapes.each( function(shape) {\n\t\t\tDataManager.__forceExistance(shape);\n\t\t});\n\t\t//DataManager.__synclocal();\n\t\t\n\t\tDataManager.__renderCanvas(facade);\n\t\tresult += DataManager.serialize(\n\t\t\t\t$(ERDF.__stripHashes(facade.getCanvas().resourceId)), true);\n\t\t\t\t\n\t\tshapes.each( function(shape) {\n\t\t\t\n\t\t\tDataManager.__persistShape(shape);\n\t\t\tresult += DataManager.serialize(\n\t\t\t\t$(ERDF.__stripHashes(shape.resourceId)), true);\n\t\t});\n\t\t\n\t\t//result += DataManager.__renderCanvas(facade);\n\t\t\n\t\treturn result;\n\t},\n\n\t__renderCanvas: function(facade) {\n\n\t\tvar canvas = facade.getCanvas();\n\t\tvar stencilSets = facade.getStencilSets();\n\t\tvar shapes = canvas.getChildShapes(true);\n\t\t\n\t\tDataManager.__forceExistance(canvas);\n\t\t\n\t\tDataManager.__persistShape(canvas);\n\t\t\n\t\tvar shapeResource = new ERDF.Resource(canvas.resourceId);\n\n\t\t// remove all triples for this particular shape's resource\n\t\tDataManager.removeTriples( DataManager.query(\n\t\t\tshapeResource, undefined, undefined));\n\n\t\tDataManager.addTriple( new ERDF.Triple(\n\t\t\tshapeResource,\n\t\t\t{prefix: \"oryx\", name: \"mode\"},\n\t\t\tnew ERDF.Literal(\"writable\")\n\t\t));\n\n\t\tDataManager.addTriple( new ERDF.Triple(\n\t\t\tshapeResource,\n\t\t\t{prefix: \"oryx\", name: \"mode\"},\n\t\t\tnew ERDF.Literal(\"fullscreen\")\n\t\t));\n\n\t\tstencilSets.values().each(function(stencilset) {\n\t\t\tDataManager.addTriple( new ERDF.Triple(\n\t\t\t\tshapeResource,\n\t\t\t\t{prefix: \"oryx\", name: \"stencilset\"},\n\t\t\t\tnew ERDF.Resource(stencilset.source().replace(/&/g, \"%26\"))\n\t\t\t));\n\t\t\t\n\t\t\tDataManager.addTriple( new ERDF.Triple(\n\t\t\t\tshapeResource,\n\t\t\t\t{prefix: \"oryx\", name: \"ssnamespace\"},\n\t\t\t\tnew ERDF.Resource(stencilset.namespace())\n\t\t\t));\n\t\t\t\n\t\t\tstencilset.extensions().keys().each(function(extension) {\n\t\t\t\tDataManager.addTriple( new ERDF.Triple(\n\t\t\t\t\tshapeResource,\n\t\t\t\t\t{prefix: \"oryx\", name: \"ssextension\"},\n\t\t\t\t\tnew ERDF.Literal(extension)\n\t\t\t\t));\n\t\t\t});\n\t\t});\n\t\t\t\t\t\t\n\t\tshapes.each(function(shape) {\n\t\t\tDataManager.addTriple( new ERDF.Triple(\n\t\t\t\tshapeResource,\n\t\t\t\t{prefix: \"oryx\", name: \"render\"},\n\t\t\t\tnew ERDF.Resource(\"#\" + shape.resourceId)\n\t\t\t));\n\t\t});\n\t},\n\n\t__counter: 0,\n\t__provideId: function() {\n\t\t\n\t\twhile($(RESOURCE_ID_PREFIX+DataManager.__counter))\n\t\t\tDataManager.__counter++;\n\t\t\t\n\t\treturn RESOURCE_ID_PREFIX+DataManager.__counter;\n\t},\n\t\t\n\tserializeDOM: function(facade) {\n\t\t\n\t\treturn DataManager.__persistDOM(facade);\n\t},\n\t\n\tsyncGlobal: function(facade) {\n\t\t\n\t\treturn DataManager.__syncglobal(facade);\n\t},\n\t\n\t/**\n\t * This method is used to synchronize local DOM with remote resources.\n\t * Local changes are commited to the server, and remote changes are\n\t * performed to the local document.\n\t * @param {Object} facade The facade of the editor that holds certain\n\t * resource representations as shapes.\n\t */\n\t__syncglobal: function(facade) {\n\n\t\t// getChildShapes gets all shapes (nodes AND edges), deep flag\n\t\t// makes it return a flattened child hierarchy.\n\t\t\n\t\tvar canvas = facade.getCanvas();\n\t\tvar shapes = canvas.getChildShapes(true);\n\n\t\t// create dummy resource representations in the dom\n\t\t// for all shapes that were newly created.\n\n\t\tshapes.select( function(shape) {\n\n\t\t\t// select shapes without resource id.\n\n\t\t\treturn !($(shape.resourceId));\n\n\t\t}).each( function(shape) {\n\n\t\t\t// create new resources for them.\n\t\t\tif(USE_ARESS_WORKAROUNDS) {\n\t\t\t\t\n\t\t\t\t/*\n\t\t\t\t * This is a workaround due to a bug in aress. Resources are\n\t\t\t\t * ignoring changes to raziel:type property once they are\n\t\t\t\t * created. As long as this is not fixed, the resource is now\n\t\t\t\t * being created using a randomly guessed id, this temporary id\n\t\t\t\t * is then used in references and the appropriate div is being\n\t\t\t\t * populated with properties.\n\t\t\t\t * \n\t\t\t\t * AFTER THIS PHASE THE DATA IS INCONSISTENT AS REFERENCES POINT\n\t\t\t\t * TO IDS THAT ARE UNKNOWN TO THE BACK END.\n\t\t\t\t * \n\t\t\t\t * After the resource is actually created in aress, it gets an id\n\t\t\t\t * that is persistent. All shapes are then being populated with the\n\t\t\t\t * correct id references and stored on the server.\n\t\t\t\t * \n\t\t\t\t * AFTER THE SAVE PROCESS HAS RETURNED, THE DATA IS CONSISTENT\n\t\t\t\t * REGARDING THE ID REFERENCES AGAIN.\n\t\t\t\t */\n\t\t\t\t\n\t\t\t\tvar razielType = shape.properties['raziel-type'];\n\t\t\t\t\n\t\t\t\tvar div = '<div xmlns=\"http://www.w3.org/1999/xhtml\">' +\n\t\t\t\t\t'<span class=\"raziel-type\">'+razielType+'</span></div>';\n\n\t\t\t\tvar r = ResourceManager.__createResource(div);\n\t\t\t\tshape.resourceId = r.id();\n\t\t\t\t\n\t\t\t} else {\n\t\t\n\t\t\t\tvar r = ResourceManager.__createResource();\n\t\t\t\tshape.resourceId = r.id();\n\t\t\t}\n\n\t\t});\n\n\t\tshapes.each( function(shape) {\n\t\t\t\n\t\t\t// store all shapes.\n\t\t\tDataManager.__storeShape(shape);\n\t\t});\n\t},\n\t\n\t/**\n\t * This method serializes a single div into a string that satisfies the\n\t * client/server communication protocol. It ingnores all elements that have\n\t * an attribute named class that includes 'transient'.\n\t * @param {Object} node the element to serialize.\n\t * @param {Object} preserveNamespace whether to preserve the parent's\n\t *                 namespace. If you are not sure about namespaces, provide\n\t *                 just the element to be serialized.\n\t */\n\tserialize: function(node, preserveNamespace) {\n\n\t\tif (node.nodeType == node.ELEMENT_NODE) {\n\t\t\t// serialize an element node.\n\t\t\t\n\t\t\tvar children = $A(node.childNodes);\n\t\t\tvar attributes = $A(node.attributes);\n\t\t\tvar clazz = new String(node.getAttribute('class'));\n\t\t\tvar ignore = clazz.split(' ').member('transient');\n\n\t\t\t// ignore transients.\n\n\t\t\tif(ignore)\n\t\t\t\treturn '';\n\n\t\t\t// start serialization.\n\t\t\t\n\t\t\tvar result = '<' + node.nodeName;\n\t\t\t\n\t\t\t// preserve namespace?\n\t\t\tif(!preserveNamespace) \n\t\t\t\tresult += ' xmlns=\"' + (node.namespaceURI ? node.namespaceURI : XMLNS.XHTML) + '\" xmlns:oryx=\"http://oryx-editor.org\"';\n\t\t\t\n\t\t\t// add all attributes.\n\t\t\t\n\t\t\tattributes.each(function(attribute) {\n\t\t\t\tresult += ' ' + attribute.nodeName + '=\"' +\n\t\t\t\t\tattribute.nodeValue + '\"';});\n\t\t\t\n\t\t\t// close if no children.\n\t\t\t\n\t\t\tif(children.length == 0)\n\t\t\t\tresult += '/>';\n\t\t\t\t\n\t\t\telse {\n\t\t\t\t\n\t\t\t\t// serialize all children.\n\t\t\t\t\n\t\t\t\tresult += '>';\n\t\t\t\tchildren.each(function(_node) {\n\t\t\t\t\tresult += DataManager.serialize(_node, true)});\n\t\t\t\tresult += '</' + node.nodeName + '>'\n\t\t\t}\n\n\t\t\treturn result;\n\t\t\t\n\t\t} else if (node.nodeType == node.TEXT_NODE) {\n\t\t\t\n\t\t\t// serialize a text node.\n\t\t\treturn  node.nodeValue;\n\t\t}\n\t\t\n\t\t//TODO serialize cdata areas also.\n\t\t//TODO work on namespace awareness.\n\t},\n\n\taddTriple: function(triple) {\n\n\t\t// assert the subject is a resource\n\t\t\n\t\tif(!triple.subject.type == ERDF.LITERAL)\n\t\t\tthrow 'Cannot add the triple ' + triple.toString() +\n\t\t\t\t' because the subject is not a resource.'\n\t\t\n\t\t// get the element which represents this triple's subject.\n\t\tvar elementId = ERDF.__stripHashes(triple.subject.value);\n\t\tvar element = $(elementId);\n\t\t\t\t\n\t\t// assert the subject is inside this document.\n\t\tif(!element)\n\t\t\tthrow 'Cannot add the triple ' + triple.toString() +\n\t\t\t\t' because the subject \"'+elementId+'\" is not in the document.';\n\n\t\tif(triple.object.type == ERDF.LITERAL)\n\n\t\t\t// object is literal\n\t\t\tDataManager.graft(XMLNS.XHTML, element, [\n\t\t\t\t'span', {'class': (triple.predicate.prefix + \"-\" +\n\t\t\t\t\ttriple.predicate.name)}, triple.object.value.escapeHTML()\n\t\t\t]);\n\t\t\t\n\t\telse {\n\n\t\t\t// object is resource\n\t\t\tDataManager.graft(XMLNS.XHTML, element, [\n\t\t\t\t'a', {'rel': (triple.predicate.prefix + \"-\" +\n\t\t\t\t\ttriple.predicate.name), 'href': triple.object.value}\n\t\t\t]);\n\t\t\t\n\t\t}\n\n\t\treturn true;\n\t},\n\t\n\tremoveTriples: function(triples) {\n\n\t\t// alert('Removing ' +triples.length+' triples.');\n\n\t\t// from all the triples select those ...\n\t\tvar removed = triples.select(\n\n\t\t\tfunction(triple) {\n\t\t\t\t\n\t\t\t\t// TODO remove also from triple store.\n\t\t\t\t// ... that were actually removed.\n\t\t\t\treturn DataManager.__removeTriple(triple);\n\t\t\t});\n\t\t\n\t\t// sync and return removed triples.\n\t\t// DataManager.__synclocal();\n\t\treturn removed;\n\t},\n\t\n\tremoveTriple: function(triple) {\n\t\t\n\t\t// remember whether the triple was actually removed.\n\t\tvar result = DataManager.__removeTriple(triple);\n\n\t\t// sync and return removed triples.\n\t\t// DataManager.__synclocal();\n\t\treturn result;\n\t},\n\n\t__removeTriple: function(triple) {\n\t\t\n\t\t// assert the subject is a resource\n\t\tif(!triple.subject.type == ERDF.LITERAL)\n\t\t\n\t\t\tthrow 'Cannot remove the triple ' + triple.toString() +\n\t\t\t\t' because the subject is not a resource.';\n\n\t\t// get the element which represents this triple's subject.\n\t\tvar elementId = ERDF.__stripHashes(triple.subject.value);\n\t\tvar element = $(elementId);\n\n\t\t// assert the subject is inside this document.\n\t\tif(!element)\n\t\t\n\t\t\tthrow 'Cannot remove the triple ' + triple.toString() +\n\t\t\t\t' because the subject is not in the document.';\n\t  \n\t\tif(triple.object.type == ERDF.LITERAL) {\n\t  \n  \t\t\t// continue searching actively for the triple.\n\t\t\tvar result = DataManager.__removeTripleRecursively(triple, element);\n\t\t\treturn result;\n\t\t}\n\t},\n\n\t__removeTripleRecursively: function(triple, continueFrom) {  \n\n\t\t// return when this node is not an element node.\n\t\tif(continueFrom.nodeType != continueFrom.ELEMENT_NODE)\n\t\t\treturn false;\n\t\t\n\t\tvar classes = new String(continueFrom.getAttribute('class'));\n\t\tvar children = $A(continueFrom.childNodes);\n\t\t\n\t\tif(classes.include(triple.predicate.prefix + '-' + triple.predicate.name)) {\n\t\t  \n\t\t\tvar content = continueFrom.textContent;\n\t\t\tif(\t(triple.object.type == ERDF.LITERAL) &&\n\t\t\t\t(triple.object.value == content))\n\n\t\t\t\tcontinueFrom.parentNode.removeChild(continueFrom);\n\t\t\t\n\t\t\treturn true;\n\t\t  \n\t\t} else {\n\t\t \n\t\t\tchildren.each(function(_node) {\n\t\t\tDataManager.__removeTripleRecursively(triple, _node)});\n\t\t\treturn false;\n\t\t}\n\n\t},\n\n\t/**\n\t * graft() function\n\t * Originally by Sean M. Burke from interglacial.com, altered for usage with\n\t * SVG and namespace (xmlns) support. Be sure you understand xmlns before\n\t * using this funtion, as it creates all grafted elements in the xmlns\n\t * provided by you and all element's attribures in default xmlns. If you\n\t * need to graft elements in a certain xmlns and wish to assign attributes\n\t * in both that and another xmlns, you will need to do stepwise grafting,\n\t * adding non-default attributes yourself or you'll have to enhance this\n\t * function. Latter, I would appreciate: martin???apfelfabrik.de\n\t * @param {Object} namespace The namespace in which\n\t * \t\t\t\t\telements should be grafted.\n\t * @param {Object} parent The element that should contain the grafted\n\t * \t\t\t\t\tstructure after the function returned.\n\t * @param {Object} t the crafting structure.\n\t * @param {Object} doc the document in which grafting is performed.\n\t */\n\tgraft: function(namespace, parent, t, doc) {\n\t\t\n\t    doc = (doc || (parent && parent.ownerDocument) || document);\n\t    var e;\n\t    if(t === undefined) {\n\t        echo( \"Can't graft an undefined value\");\n\t    } else if(t.constructor == String) {\n\t        e = doc.createTextNode( t );\n\t    } else {\n\t        for(var i = 0; i < t.length; i++) {\n\t            if( i === 0 && t[i].constructor == String ) {\n\t\t\t\t\tvar snared = t[i].match( /^([a-z][a-z0-9]*)\\.([^\\s\\.]+)$/i );\n\t                if( snared ) {\n\t                    e = doc.createElementNS(namespace, snared[1]);\n\t                    e.setAttributeNS(null, 'class', snared[2] );\n\t                    continue;\n\t                }\n\t                snared = t[i].match( /^([a-z][a-z0-9]*)$/i );\n\t                if( snared ) {\n\t                    e = doc.createElementNS(namespace, snared[1]);  // but no class\n\t                    continue;\n\t                }\n\t\n\t                // Otherwise:\n\t                e = doc.createElementNS(namespace, \"span\");\n\t                e.setAttribute(null, \"class\", \"namelessFromLOL\" );\n\t            }\n\t\n\t            if( t[i] === undefined ) {\n\t                echo(\"Can't graft an undefined value in a list!\");\n\t            } else if( t[i].constructor == String || t[i].constructor == Array) {\n\t                this.graft(namespace, e, t[i], doc );\n\t            } else if(  t[i].constructor == Number ) {\n\t                this.graft(namespace, e, t[i].toString(), doc );\n\t            } else if(  t[i].constructor == Object ) {\n\t                // hash's properties => element's attributes\n\t                for(var k in t[i]) { e.setAttributeNS(null, k, t[i][k] ); }\n\t            } else if(  t[i].constructor == Boolean ) {\n\t                this.graft(namespace, e, t[i] ? 'true' : 'false', doc );\n\t\t\t\t} else\n\t\t\t\t\tthrow \"Object \" + t[i] + \" is inscrutable as an graft arglet.\";\n\t        }\n\t    }\n\t\t\n\t\tif(parent) parent.appendChild(e);\n\t\n\t    return Element.extend(e); // return the topmost created node\n\t},\n\n\tsetObject: function(triple) {\n\n\t\t/**\n\t\t * Erwartungen von Arvid an diese Funktion:\n\t\t * - Es existiert genau ein triple mit dem Subjekt und Praedikat,\n\t\t *   das uebergeben wurde, und dieses haelt uebergebenes Objekt.\n\t\t */\n\n\t\tvar triples = DataManager.query(\n\t\t\ttriple.subject,\n\t\t\ttriple.predicate,\n\t\t\tundefined\n\t\t);\n\t\t\n\t\tDataManager.removeTriples(triples);\n\n\t\tDataManager.addTriple(triple);\n\n\t\treturn true;\n\t},\n\t\n\tquery: function(subject, predicate, object) {\n\n\t\t/*\n\t\t * Typical triple.\n\t\t *\t{value: subject, type: subjectType},\n\t\t *\t{prefix: schema.prefix, name: property},\n\t\t *\t{value: object, type: objectType});\n\t\t */\t\n\t\t \t\n\t\treturn DataManager._triples.select(function(triple) {\n\t\t\t\n\t\t\tvar select = ((subject) ?\n\t\t\t\t(triple.subject.type == subject.type) &&\n\t\t\t\t(triple.subject.value == subject.value) : true);\n\t\t\tif(predicate) {\n\t\t\t\tselect = select && ((predicate.prefix) ?\n\t\t\t\t\t(triple.predicate.prefix == predicate.prefix) : true);\n\t\t\t\tselect = select && ((predicate.name) ?\n\t\t\t\t\t(triple.predicate.name == predicate.name) : true);\n\t\t\t}\n\t\t\tselect = select && ((object) ?\n\t\t\t\t(triple.object.type == object.type) &&\n\t\t\t\t(triple.object.value == object.value) : true);\n\t\t\treturn select;\n\t\t});\n\t}\n}\n\nKickstart.register(DataManager.init);\n\nfunction assert(expr, m) { if(!expr) throw m; };\n\nfunction DMCommand(action, triple) {\n\t\n\t// store action and triple.\n\tthis.action = action;\n\tthis.triple = triple;\n\t\n\tthis.toString = function() {\n\t\treturn 'Command('+action+', '+triple+')';\n\t};\n}\n\nfunction DMCommandHandler(nextHandler) {\n\t\n\t/**\n\t * Private method to set the next handler in the Chain of Responsibility\n\t * (see http://en.wikipedia.org/wiki/Chain-of-responsibility_pattern for\n\t * details).\n\t * @param {DMCommandHandler} handler The handler that is next in the chain.\n\t */\n\tthis.__setNext = function(handler) {\n\t\tvar _next = this.__next;\n\t\tthis.__next = nextHandler;\n\t\treturn _next ? _next : true;\n\t};\n\tthis.__setNext(nextHandler);\n\n\t/**\n\t * Invokes the next handler. If there is no next handler, this method\n\t * returns false, otherwise it forwards the result of the handling.\n\t * @param {Object} command The command object to be processed.\n\t */\n\tthis.__invokeNext = function(command) {\n\t\treturn this.__next ? this.__next.handle(command) : false;\n\t};\n\t\n\t/**\n\t * Handles a command. The abstract method process() is called with the\n\t * command object that has been passed. If the process method catches the\n\t * command (returns true on completion), the handle() method returns true.\n\t * If the process() method doesn't catch the command, the next handler will\n\t * be invoked.\n\t * @param {Object} command The command object to be processed.\n\t */\n\tthis.handle = function(command) {\n\t\treturn this.process(command) ? true : this.__invokeNext(command);\n\t}\n\t\n\t/**\n\t * Empty process() method returning false. If javascript knew abstract\n\t * class members, this would be one.\n\t * @param {Object} command The command object to process.\n\t */\n\tthis.process = function(command) { return false; };\n};\n\n/**\n * This Handler manages the addition and the removal of meta elements in the\n * head of the document.\n * @param {DMCommandHandler} next The handler that is next in the chain.\n */\nfunction MetaTagHandler(next) {\n\t\n\tDMCommandHandler.apply(this, [next]);\n\tthis.process = function(command) {\n\t\t\n\t\twith(command.triple) {\n\t\t\t\n\t\t\t/* assert prerequisites */\n\t\t\tif( !(\n\t\t\t\t(subject instanceof ERDF.Resource) &&\n\t\t\t\t(subject.isCurrentDocument()) &&\n\t\t\t\t(object instanceof ERDF.Literal)\n\t\t\t))\treturn false;\n\t\t}\n\t\t\n\t};\n};\n\nvar chain =\tnew MetaTagHandler();\nvar command = new DMCommand(TRIPLE_ADD, new ERDF.Triple(\n\tnew ERDF.Resource(''),\n\t'rdf:tool',\n\tnew ERDF.Literal('')\n));\n\n/*\nif(chain.handle(command))\n\talert('Handled!');\n*/\n\nResourceManager = {\n\t\n\t__corrupt: false,\n\t__latelyCreatedResource: undefined,\n\t__listeners: $H(),\n\t__token: 1,\n\t\n\taddListener: function(listener, mask) {\n\n\t\tif(!(listener instanceof Function))\n\t\t\tthrow 'Resource event listener is not a function!';\n\t\tif(!(mask))\n\t\t\tthrow 'Invalid mask for resource event listener registration.';\n\n\t\t// construct controller and token.\n\t\tvar controller = {listener: listener, mask: mask};\n\t\tvar token = ResourceManager.__token++;\n\t\t\n\t\t// add new listener.\n\t\tResourceManager.__listeners[token] = controller;\n\t\t\n\t\t// return the token generated.\n\t\treturn token;\n\t},\n\t\n\tremoveListener: function(token) {\n\t\t\n\t\t// remove the listener with the token and return it.\n\t\treturn ResourceManager.__listners.remove(token);\n\t},\n\t\n\t__Event: function(action, resourceId) {\n\t\tthis.action = action;\n\t\tthis.resourceId = resourceId;\n\t},\n\t\n\t__dispatchEvent: function(event) {\n\t\t\n\t\t// get all listeners. for each listener, ...\n\t\tResourceManager.__listeners.values().each(function(controller) {\n\t\t\t\n\t\t\t// .. if listener subscribed to this type of event ...\n\t\t\tif(event.action & controller.mask)\n\t\t\t\treturn controller.listener(event);\n\t\t});\n\t},\n\n\tgetResource: function(id) {\n\n\t\t// get all possible resources for this.\n\t\tid = ERDF.__stripHashes(id);\n\t\tvar resources = DataManager.query(\n\t\t\tnew ERDF.Resource('#'+id),\n\t\t\t{prefix: 'raziel', name: 'entry'},\n\t\t\tundefined\n\t\t);\n\n\t\t// check for consistency.\n\t\tif((resources.length == 1) && (resources[0].object.isResource())) {\n\t\t\tvar entryUrl = resources[0].object.value;\n\t\t\treturn new ResourceManager.__Resource(id, entryUrl);\n\t\t}\n\n\t\t// else throw an error message.\n\t\tthrow ('Resource with id ' +id+ ' not recognized as such. ' +\n\t\t\t((resources.length > 1) ?\n\t\t\t\t' There is more than one raziel:entry URL.' :\n\t\t\t\t' There is no raziel:entry URL.'));\n\n\t\treturn false;\n\t},\n\n\t__createResource: function(alternativeDiv) {\n\t\t\n\t\tvar collectionUrls = DataManager.query(\n\t\t\tnew ERDF.Resource(''),\n\t\t\t// TODO This will become raziel:collection in near future.\n\t\t\t{prefix: 'raziel', name: 'collection'},\n\t\t\tundefined\n\t\t);\n\n\t\t// check for consistency.\n\t\t\n\t\tif(\t(collectionUrls.length == 1) &&\n\t\t\t(collectionUrls[0].object.isResource())) {\n\n\t\t\t// get the collection url.\n\t\t\t\n\t\t\tvar collectionUrl = collectionUrls[0].object.value;\n\t\t\tvar resource = undefined;\n\t\t\t\n\t\t\t// if there is an old id, serialize the dummy div from there,\n\t\t\t// otherwise create a dummy div on the fly.\n\t\t\t\n\t\t\tvar serialization = alternativeDiv? alternativeDiv : \n\t\t\t\t\t'<div xmlns=\"http://www.w3.org/1999/xhtml\"></div>';\n\t\t\t\t\t\n\t\t\tResourceManager.__request(\n\t\t\t\t'POST', collectionUrl, serialization,\n\n\t\t\t\t// on success\n\t\t\t\tfunction() {\n\t\t\t\t\t\n\t\t\t\t\t// get div and id that have been generated by the server.\n\t\t\t\t\t\n\t\t\t\t\tvar response = (this.responseXML);\n\t\t\t\t\tvar div = response.childNodes[0];\n\t\t\t\t\tvar id = div.getAttribute('id');\n\t\t\t\t\t\n\t\t\t\t\t// store div in DOM\n\t\t\t\t\tif(!$$('.' + PROCESSDATA_REF)[0])\n\t\t\t\t\t\tDataManager.graft(XMLNS.XHTML,\n\t\t\t\t\t\t\tdocument.getElementsByTagNameNS(XMLNS.XHTML, 'body').item(0), ['div', {'class': PROCESSDATA_REF, 'style':'display:none;'}]);\n\t\t\t\t\n\t\t\t\t\t$$('.' + PROCESSDATA_REF)[0].appendChild(div.cloneNode(true));\n\n\t\t\t\t\t// parse local erdf data once more.\n\t\t\t\t\t\n\t\t\t\t\tDataManager.__synclocal();\n\t\t\t\t\t\n\t\t\t\t\t// get new resource object.\n\n\t\t\t\t\tresource = new ResourceManager.getResource(id);\n\n\t\t\t\t\t// set up an action informing of the creation.\n\t\t\t\t\t\n\t\t\t\t\tResourceManager.__resourceActionSucceeded(\n\t\t\t\t\t\tthis, RESOURCE_CREATED, undefined);\n\t\t\t\t},\n\n\t\t\t\tfunction() { ResourceManager.__resourceActionFailed(\n\t\t\t\t\tthis, RESOURCE_CREATED, undefined);},\n\t\t\t\tfalse\n\t\t\t);\n\t\t\t\n\t\t\treturn resource;\n\t\t}\n\t\t\n\t\t// else\n\t\tthrow 'Could not create resource! raziel:collection URL is missing!';\n\t\treturn false;\n\n\t},\n\t\n\t__Resource: function(id, url) {\n\t\t\n\t\tthis.__id = id;\n\t\tthis.__url = url;\n\t\t\n\t\t/*\n\t\t * Process URL is no longer needed to refer to the shape element on the\n\t\t * canvas. AReSS uses the id's to gather information on fireing\n\t\t * behaviour now.\n\t\t */\n\t\t\n//\t\t// find the process url.\t\t\n//\t\tvar processUrl = undefined;\n//\t\t\n//\t\tvar urls = DataManager.query(\n//\t\t\tnew ERDF.Resource('#'+this.__id),\n//\t\t\t{prefix: 'raziel', name: 'process'},\n//\t\t\tundefined\n//\t\t);\n//\t\t\n//\t\tif(urls.length == 0) { throw 'The resource with the id ' +id+ ' has no process url.'};\n//\t\t\n//\t\turls.each( function(triple) {\n//\t\t\t\n//\t\t\t// if there are more urls, use the last one.\n//\t\t\tprocessUrl = triple.object.value;\n//\t\t});\n//\t\t\n//\t\tthis.__processUrl = processUrl;\n//\n//\t\t// convenience function for getting the process url.\n//\t\tthis.processUrl = function() {\n//\t\t\treturn this.__processUrl;\n//\t\t}\n\n\n\t\t// convenience finction for getting the id.\n\t\tthis.id = function() {\n\t\t\treturn this.__id;\n\t\t}\n\n\t\t// convenience finction for getting the entry url.\n\t\tthis.url = function() {\n\t\t\treturn this.__url;\n\t\t}\n\t\t\n\t\tthis.reload = function() {\n\t\t\tvar _url = this.__url;\n\t\t\tvar _id = this.__id;\n\t\t\tResourceManager.__request(\n\t\t\t\t'GET', _url, null,\n\t\t\t\tfunction() { ResourceManager.__resourceActionSucceeded(\n\t\t\t\t\tthis, RESOURCE_RELOADED, _id); },\n\t\t\t\tfunction() { ResourceManager.__resourceActionFailed(\n\t\t\t\t\tthis, RESURCE_RELOADED, _id); },\n\t\t\t\tUSE_ASYNCHRONOUS_REQUESTS\n\t\t\t);\n\t\t};\n\t\t\n\t\tthis.save = function(synchronize) {\n\t\t\tvar _url = this.__url;\n\t\t\tvar _id = this.__id;\n\t\t\tdata = DataManager.serialize($(_id));\n\t\t\tResourceManager.__request(\n\t\t\t\t'PUT', _url, data,\n\t\t\t\tfunction() { ResourceManager.__resourceActionSucceeded(\n\t\t\t\t\tthis, synchronize ? RESOURCE_SAVED | RESOURCE_SYNCHRONIZED : RESOURCE_SAVED, _id); },\n\t\t\t\tfunction() { ResourceManager.__resourceActionFailed(\n\t\t\t\t\tthis, synchronize ? RESOURCE_SAVED | RESOURCE_SYNCHRONIZED : RESOURCE.SAVED, _id); },\n\t\t\t\tUSE_ASYNCHRONOUS_REQUESTS\n\t\t\t);\n\t\t};\n\t\t\n\t\tthis.remove = function() {\n\t\t\tvar _url = this.__url;\n\t\t\tvar _id = this.__id;\n\t\t\tResourceManager.__request(\n\t\t\t\t'DELETE', _url, null,\n\t\t\t\tfunction() { ResourceManager.__resourceActionSucceeded(\n\t\t\t\t\tthis, RESOURCE_REMOVED, _id); },\n\t\t\t\tfunction() { ResourceManager.__resourceActionFailed(\n\t\t\t\t\tthis, RESOURCE_REMOVED, _id);},\n\t\t\t\tUSE_ASYNCHRONOUS_REQUESTS\n\t\t\t);\n\t\t};\n\t},\n\n\trequest: function(url, requestOptions) {\n\n\t\tvar options = {\n\t\t\tmethod:       'get',\n\t\t\tasynchronous: true,\n\t\t\tparameters:   {}\n\t\t};\n\n\t\tObject.extend(options, requestOptions || {});\n \t\t\n\t\tvar params = Hash.toQueryString(options.parameters);\n\t\tif (params) \n\t\t\turl += (url.include('?') ? '&' : '?') + params;\n   \n\t\treturn ResourceManager.__request(\n\t\t\toptions.method, \n\t\t\turl, \n\t\t\toptions.data, \n\t\t\t(options.onSuccess instanceof Function ? function() { options.onSuccess(this); } : undefined ), \n\t\t\t(options.onFailure instanceof Function ? function() { options.onFailure(this); } : undefined ), \n\t\t\toptions.asynchronous && USE_ASYNCHRONOUS_REQUESTS,\n\t\t\toptions.headers);\n\t},\n\t\n\t__request: function(method, url, data, success, error, async, headers) {\n\t\t\n\t\t// get a request object\n\t\tvar httpRequest = Try.these(\n\n\t\t\t/* do the Mozilla/Safari/Opera stuff */\n\t\t\tfunction() { return new XMLHttpRequest(); },\n\t\t\t\n\t\t\t/* do the IE stuff */\n\t\t\tfunction() { return new ActiveXObject(\"Msxml2.XMLHTTP\"); },\n\t\t\tfunction() { return new ActiveXObject(\"Microsoft.XMLHTTP\") }\n\t\t);\n\n\t\t// if there is no request object ...\n        if (!httpRequest) {\n\t\t\tif(!this.__corrupt)\n\t\t\t\tthrow 'This browser does not provide any AJAX functionality. You will not be able to use the software provided with the page you are viewing. Please consider installing appropriate extensions.';\n\t\t\tthis.__corrupt = true;\n\t\t\treturn false;\n        }\n\t\t\n\t\tif(success instanceof Function)\n\t\t\thttpRequest.onload = success;\n\t\tif(error instanceof Function) {\n\t\t\thttpRequest.onerror = error;\n\t\t}\n\t\t\n\t\tvar h = $H(headers)\n\t\th.keys().each(function(key) {\n\t\t\t\n\t\t\thttpRequest.setRequestHeader(key, h[key]);\n\t\t}); \n\t\t\n\t\ttry {\n\n\t\t\tif(SHOW_DEBUG_ALERTS_WHEN_SAVING)\n\t\t\t\n\t\t\t\talert(method + ' ' + url + '\\n' +\n\t\t\t\t\tSHOW_EXTENDED_DEBUG_INFORMATION ? data : '');\n\n\t\t\t// TODO Remove synchronous calls to the server as soon as xenodot\n\t\t\t// handles asynchronous requests without failure.\n\t        httpRequest.open(method, url, !async?false:true);\n\t        httpRequest.send(data);\n\t\t\t\n\t\t} catch(e) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n    },\n\n\t__resourceActionSucceeded: function(transport, action, id) {\n\t\t\n\t\tvar status = transport.status;\n\t\tvar response = transport.responseText;\n\t\t\n\t\tif(SHOW_DEBUG_ALERTS_WHEN_SAVING)\n\n\t\t\talert(status + ' ' + url + '\\n' +\n\t\t\t\tSHOW_EXTENDED_DEBUG_INFORMATION ? data : '');\n\n\t\t// if the status code is not in 2xx, throw an error.\n\t\tif(status >= 300)\n\t\t\tthrow 'The server responded with an error: ' + status + '\\n' + (SHOW_EXTENDED_DEBUG_INFORMATION ? + data : 'If you need additional information here, including the data sent by the server, consider setting SHOW_EXTENDED_DEBUG_INFORMATION to true.');\n\n\t\tswitch(action) {\n\t\t\t\n\t\t\tcase RESOURCE_REMOVED:\n\n\t\t\t\t// get div and id\n\t\t\t\tvar response = (transport.responseXML);\n\t\t\t\tvar div = response.childNodes[0];\n\t\t\t\tvar id = div.getAttribute('id');\n\t\t\t\t\n\t\t\t\t// remove the resource from DOM\n\t\t\t\tvar localDiv = document.getElementById(id);\n\t\t\t\tlocalDiv.parentNode.removeChild(localDiv);\n\t\t\t\tbreak;\n\n\t\t\tcase RESOURCE_CREATED:\n\n\t\t\t\t// nothing remains to be done.\n\t\t\t\tbreak;\n\t\n\t\t\tcase RESOURCE_SAVED | RESOURCE_SYNCHRONIZED:\n\n\t\t\t\tDataManager.__synclocal();\n\n\t\t\tcase RESOURCE_SAVED:\n\n\t\t\t\t// nothing remains to be done.\n\t\t\t\tbreak;\n\n\t\t\tcase RESOURCE_RELOADED:\n\t\t\t\n\t\t\t\t// get div and id\n\t\t\t\tvar response = (transport.responseXML);\n\t\t\t\tvar div = response.childNodes[0];\n\t\t\t\tvar id = div.getAttribute('id');\n\t\t\t\t\n\t\t\t\t// remove the local resource representation from DOM\n\t\t\t\tvar localDiv = document.getElementById(id)\n\t\t\t\tlocalDiv.parentNode.removeChild(localDiv);\n\t\t\t\t\n\t\t\t\t// store div in DOM\n\t\t\t\tif(!$$(PROCESSDATA_REF)[0])\n\t\t\t\t\tDataManager.graft(XMLNS.XHTML,\n\t\t\t\t\t\tdocument.getElementsByTagNameNS(XMLNS.XHTML, 'body').item(0), ['div', {'class': PROCESSDATA_REF, 'style':'display:none;'}]);\n\t\t\t\t\n\t\t\t\t$$(PROCESSDATA_REF)[0].appendChild(div.cloneNode(true));\n\t\t\t\tDataManager.__synclocal();\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tDataManager.__synclocal();\n\n\t\t}\n\t\t \n\t\t// dispatch to all listeners ...\n\t\tResourceManager.__dispatchEvent(\n\n\t\t\t// ... an event describing the change that happened here.\n\t\t\tnew ResourceManager.__Event(action, id)\n\t\t);\n\t},\n\n\t__resourceActionFailed: function(transport, action, id) {\n\t\tthrow \"Fatal: Resource action failed. There is something horribly \" +\n\t\t\t\"wrong with either the server, the transport protocol or your \" +\n\t\t\t\"online status. Sure you're online?\";\n\t}\n}/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * The super class for all classes in ORYX. Adds some OOP feeling to javascript.\n * See article \"Object Oriented Super Class Method Calling with JavaScript\" on\n * http://truecode.blogspot.com/2006/08/object-oriented-super-class-method.html\n * for a documentation on this. Fairly good article that points out errors in\n * Douglas Crockford's inheritance and super method calling approach.\n * Worth reading.\n * @class Clazz\n */\nvar Clazz = function() {};\n\n/**\n * Empty constructor.\n * @methodOf Clazz.prototype\n */\nClazz.prototype.construct = function() {};\n\n/**\n * Can be used to build up inheritances of classes.\n * @example\n * var MyClass = Clazz.extend({\n *   construct: function(myParam){\n *     // Do sth.\n *   }\n * });\n * var MySubClass = MyClass.extend({\n *   construct: function(myParam){\n *     // Use this to call constructor of super class\n *     arguments.callee.$.construct.apply(this, arguments);\n *     // Do sth.\n *   }\n * });\n * @param {Object} def The definition of the new class.\n */\nClazz.extend = function(def) {\n    var classDef = function() {\n        if (arguments[0] !== Clazz) { this.construct.apply(this, arguments); }\n    };\n    \n    var proto = new this(Clazz);\n    var superClass = this.prototype;\n    \n    for (var n in def) {\n        var item = def[n];                        \n        if (item instanceof Function) item.$ = superClass;\n        proto[n] = item;\n    }\n\n    classDef.prototype = proto;\n    \n    //Give this new class the same static extend method    \n    classDef.extend = this.extend;        \n    return classDef;\n};/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nif(!ORYX) var ORYX = {};\n\nif(!ORYX.CONFIG) ORYX.CONFIG = {};\n\n/**\n * This file contains URI constants that may be used for XMLHTTPRequests.\n */\n\nORYX.CONFIG.ROOT_PATH =\t\t\t\t\t\"editor/\"; //TODO: Remove last slash!!\nORYX.CONFIG.EXPLORER_PATH =\t\t\t\t\"explorer\";\nORYX.CONFIG.LIBS_PATH =\t\t\t\t\t\"libs\";\n\n/**\n * Regular Config\n */\t\nORYX.CONFIG.SERVER_HANDLER_ROOT = \t\t\t\"service\";\nORYX.CONFIG.SERVER_EDITOR_HANDLER =\t\t\tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/editor\";\nORYX.CONFIG.SERVER_MODEL_HANDLER =\t\t\tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/model\";\nORYX.CONFIG.STENCILSET_HANDLER = \t\t\tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/editor_stencilset?embedsvg=true&url=true&namespace=\";    \nORYX.CONFIG.STENCIL_SETS_URL = \t\t\t\tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/editor_stencilset\";\n\nORYX.CONFIG.PLUGINS_CONFIG =\t\t\t\t\"editor-app/plugins.xml\";\nORYX.CONFIG.SYNTAXCHECKER_URL =\t\t\t\tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/syntaxchecker\";\nORYX.CONFIG.DEPLOY_URL = \t\t\t\t\tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/model/deploy\";\nORYX.CONFIG.MODEL_LIST_URL = \t\t\t\tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/models\";\nORYX.CONFIG.FORM_FLOW_LIST_URL = \t\t\tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/formflows\";\nORYX.CONFIG.FORM_FLOW_IMAGE_URL = \t\t\tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/formflow\";\nORYX.CONFIG.FORM_LIST_URL = \t\t\t\tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/forms\";\nORYX.CONFIG.FORM_IMAGE_URL = \t\t\t\tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/form\";\nORYX.CONFIG.SUB_PROCESS_LIST_URL = \t\t\tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/subprocesses\";\nORYX.CONFIG.SUB_PROCESS_IMAGE_URL = \t\tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/subprocess\";\nORYX.CONFIG.TEST_SERVICE_URL = \t\t\t\tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/service/\";\n\nORYX.CONFIG.SERVICE_LIST_URL = \t\t\t\tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/services\";\nORYX.CONFIG.CONDITION_ELEMENT_LIST_URL = \tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/conditionelements\";\nORYX.CONFIG.VARIABLEDEF_ELEMENT_LIST_URL = \tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/variabledefinitionelements\";\nORYX.CONFIG.VALIDATOR_LIST_URL = \t\t\tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/validators\";\n\nORYX.CONFIG.SS_EXTENSIONS_FOLDER =\t\t\tORYX.CONFIG.ROOT_PATH + \"stencilsets/extensions/\";\nORYX.CONFIG.SS_EXTENSIONS_CONFIG =\t\t\tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/editor_ssextensions\";\t\nORYX.CONFIG.ORYX_NEW_URL =\t\t\t\t\t\"/new\";\t\nORYX.CONFIG.BPMN_LAYOUTER =\t\t\t\t\tORYX.CONFIG.ROOT_PATH + \"bpmnlayouter\";\n\nORYX.CONFIG.EXPRESSION_METADATA_URL = \t\t\tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/expression-metadata\";\nORYX.CONFIG.DATASOURCE_METADATA_URL = \t\t\tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/datasource-metadata\";/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nif(!ORYX) var ORYX = {};\n\nif(!ORYX.CONFIG) ORYX.CONFIG = {};\n\n/**\n * Signavio specific variables\n */\nORYX.CONFIG.BACKEND_SWITCH \t\t= \t\ttrue;\nORYX.CONFIG.PANEL_LEFT_WIDTH \t= \t\t250;\nORYX.CONFIG.PANEL_RIGHT_COLLAPSED \t= \ttrue;\nORYX.CONFIG.PANEL_RIGHT_WIDTH\t= \t\t300;\nORYX.CONFIG.APPNAME = \t\t\t\t\t'KISBPM';\nORYX.CONFIG.WEB_URL = \t\t\t\t\t\".\";\n\nORYX.CONFIG.BLANK_IMAGE = ORYX.CONFIG.LIBS_PATH + '/ext-2.0.2/resources/images/default/s.gif';\n\n/* Specify offset of header */\nORYX.CONFIG.OFFSET_HEADER = 61;\n\n/* Show grid line while dragging */\nORYX.CONFIG.SHOW_GRIDLINE = \t\t\ttrue;\n\n\t/* Editor-Mode */\nORYX.CONFIG.MODE_READONLY =\t\t\t\t\"readonly\";\nORYX.CONFIG.MODE_FULLSCREEN =\t\t\t\"fullscreen\";\nORYX.CONFIG.WINDOW_HEIGHT = \t\t\t800;\t\nORYX.CONFIG.PREVENT_LOADINGMASK_AT_READY = false;\n\n\t/* Plugins */\nORYX.CONFIG.PLUGINS_ENABLED =\t\t\ttrue;\nORYX.CONFIG.PLUGINS_FOLDER =\t\t\t\"Plugins/\";\n\nORYX.CONFIG.BPMN20_SCHEMA_VALIDATION_ON = true;\n\n\t/* Namespaces */\nORYX.CONFIG.NAMESPACE_ORYX =\t\t\t\"http://www.b3mn.org/oryx\";\nORYX.CONFIG.NAMESPACE_SVG =\t\t\t\t\"http://www.w3.org/2000/svg\";\n\n\t/* UI */\nORYX.CONFIG.CANVAS_WIDTH =\t\t\t\t1200; \nORYX.CONFIG.CANVAS_HEIGHT =\t\t\t\t1050;\nORYX.CONFIG.CANVAS_RESIZE_INTERVAL =\t100;\nORYX.CONFIG.CANVAS_MIN_WIDTH =  800;\nORYX.CONFIG.CANVAS_MIN_HEIGHT =  300;\nORYX.CONFIG.SELECTED_AREA_PADDING =\t\t4;\nORYX.CONFIG.CANVAS_BACKGROUND_COLOR =\t\"none\";\nORYX.CONFIG.GRID_DISTANCE =\t\t\t\t30;\nORYX.CONFIG.GRID_ENABLED =\t\t\t\ttrue;\nORYX.CONFIG.ZOOM_OFFSET =\t\t\t\t0.1;\nORYX.CONFIG.DEFAULT_SHAPE_MARGIN =\t\t60;\nORYX.CONFIG.SCALERS_SIZE =\t\t\t\t7;\nORYX.CONFIG.MINIMUM_SIZE =\t\t\t\t20;\nORYX.CONFIG.MAXIMUM_SIZE =\t\t\t\t10000;\nORYX.CONFIG.OFFSET_MAGNET =\t\t\t\t15;\nORYX.CONFIG.OFFSET_EDGE_LABEL_TOP =\t\t8;\nORYX.CONFIG.OFFSET_EDGE_LABEL_BOTTOM =\t8;\nORYX.CONFIG.OFFSET_EDGE_BOUNDS =\t\t5;\nORYX.CONFIG.COPY_MOVE_OFFSET =\t\t\t30;\n\t\nORYX.CONFIG.BORDER_OFFSET =\t\t\t\t14;\n\nORYX.CONFIG.MAX_NUM_SHAPES_NO_GROUP\t=\t20; // Updated so the form editor shows all elements at once\n\nORYX.CONFIG.SHAPEMENU_CREATE_OFFSET_CORNER = 30;\nORYX.CONFIG.SHAPEMENU_CREATE_OFFSET = 45;\n\n\t/* Shape-Menu Align */\nORYX.CONFIG.SHAPEMENU_RIGHT =\t\t\t\"Oryx_Right\";\nORYX.CONFIG.SHAPEMENU_BOTTOM =\t\t\t\"Oryx_Bottom\";\nORYX.CONFIG.SHAPEMENU_LEFT =\t\t\t\"Oryx_Left\";\nORYX.CONFIG.SHAPEMENU_TOP =\t\t\t\t\"Oryx_Top\";\n\n\n\t/* Morph-Menu Item */\nORYX.CONFIG.MORPHITEM_DISABLED =\t\t\"Oryx_MorphItem_disabled\";\n\n\t/* Property type names */\nORYX.CONFIG.TYPE_STRING =\t\t\t\t\"string\";\nORYX.CONFIG.TYPE_BOOLEAN =\t\t\t\t\"boolean\";\nORYX.CONFIG.TYPE_INTEGER =\t\t\t\t\"integer\";\nORYX.CONFIG.TYPE_FLOAT =\t\t\t\t\"float\";\nORYX.CONFIG.TYPE_COLOR =\t\t\t\t\"color\";\nORYX.CONFIG.TYPE_DATE =\t\t\t\t\t\"date\";\nORYX.CONFIG.TYPE_CHOICE =\t\t\t\t\"choice\";\nORYX.CONFIG.TYPE_URL =\t\t\t\t\t\"url\";\nORYX.CONFIG.TYPE_DIAGRAM_LINK =\t\t\t\"diagramlink\";\nORYX.CONFIG.TYPE_COMPLEX =\t\t\t\t\"complex\";\nORYX.CONFIG.TYPE_MULTIPLECOMPLEX =\t\t\"multiplecomplex\";\nORYX.CONFIG.TYPE_TEXT =\t\t\t\t\t\"text\";\nORYX.CONFIG.TYPE_KISBPM_MULTIINSTANCE =\t\"kisbpm-multiinstance\";\nORYX.CONFIG.TYPE_MODEL_LINK =\t\t\t\"modellink\";\nORYX.CONFIG.TYPE_FORM_FLOW_LINK =\t\t\"formflowlink\";\nORYX.CONFIG.TYPE_FORM_LINK =\t\t\t\"formlink\";\nORYX.CONFIG.TYPE_SUB_PROCESS_LINK =\t\t\"subprocesslink\";\nORYX.CONFIG.TYPE_SERVICE_LINK =\t\t\t\"servicelink\";\nORYX.CONFIG.TYPE_CONDITIONS =\t\t\t\"conditions\";\nORYX.CONFIG.TYPE_VARIABLES = \t\t\t\"variables\";\nORYX.CONFIG.TYPE_LISTENER =\t\t\t\t\"listener\";\nORYX.CONFIG.TYPE_EPC_FREQ = \t\t\t\"epcfrequency\";\nORYX.CONFIG.TYPE_GLOSSARY_LINK =\t\t\"glossarylink\";\nORYX.CONFIG.TYPE_EXPRESSION = \t\t\t\"expression\";\nORYX.CONFIG.TYPE_DATASOURCE = \t\t\t\"datasource\";\nORYX.CONFIG.TYPE_DATASOURCE_MINIMAL =\t\"datasource-minimal\";\nORYX.CONFIG.TYPE_VALIDATORS =\t\t\t\"validators\";\n\n\t\n\t/* Vertical line distance of multiline labels */\nORYX.CONFIG.LABEL_LINE_DISTANCE =\t\t2;\nORYX.CONFIG.LABEL_DEFAULT_LINE_HEIGHT =\t12;\n\n\t/* Open Morph Menu with Hover */\nORYX.CONFIG.ENABLE_MORPHMENU_BY_HOVER = false;\n\n\n\t/* Editor constants come here */\nORYX.CONFIG.EDITOR_ALIGN_BOTTOM =\t\t0x01;\nORYX.CONFIG.EDITOR_ALIGN_MIDDLE =\t\t0x02;\nORYX.CONFIG.EDITOR_ALIGN_TOP =\t\t\t0x04;\nORYX.CONFIG.EDITOR_ALIGN_LEFT =\t\t\t0x08;\nORYX.CONFIG.EDITOR_ALIGN_CENTER =\t\t0x10;\nORYX.CONFIG.EDITOR_ALIGN_RIGHT =\t\t0x20;\nORYX.CONFIG.EDITOR_ALIGN_SIZE =\t\t\t0x30;\n\n\t/* Event types */\nORYX.CONFIG.EVENT_MOUSEDOWN =\t\t\t\"mousedown\";\nORYX.CONFIG.EVENT_MOUSEUP =\t\t\t\t\"mouseup\";\nORYX.CONFIG.EVENT_MOUSEOVER =\t\t\t\"mouseover\";\nORYX.CONFIG.EVENT_MOUSEOUT =\t\t\t\"mouseout\";\nORYX.CONFIG.EVENT_MOUSEMOVE =\t\t\t\"mousemove\";\nORYX.CONFIG.EVENT_DBLCLICK =\t\t\t\"dblclick\";\nORYX.CONFIG.EVENT_KEYDOWN =\t\t\t\t\"keydown\";\nORYX.CONFIG.EVENT_KEYUP =\t\t\t\t\"keyup\";\n\nORYX.CONFIG.EVENT_LOADED =\t\t\t\t\"editorloaded\";\nORYX.CONFIG.EVENT_SAVED =\t\t\t\t\"editorSaved\";\n\t\nORYX.CONFIG.EVENT_EXECUTE_COMMANDS =\t\t\"executeCommands\";\nORYX.CONFIG.EVENT_STENCIL_SET_LOADED =\t\t\"stencilSetLoaded\";\nORYX.CONFIG.EVENT_SELECTION_CHANGED =\t\t\"selectionchanged\";\nORYX.CONFIG.EVENT_SHAPEADDED =\t\t\t\t\"shapeadded\";\nORYX.CONFIG.EVENT_SHAPEREMOVED =\t\t\t\"shaperemoved\";\nORYX.CONFIG.EVENT_PROPERTY_CHANGED =\t\t\"propertyChanged\";\nORYX.CONFIG.EVENT_DRAGDROP_START =\t\t\t\"dragdrop.start\";\nORYX.CONFIG.EVENT_SHAPE_MENU_CLOSE =\t\t\"shape.menu.close\";\nORYX.CONFIG.EVENT_DRAGDROP_END =\t\t\t\"dragdrop.end\";\nORYX.CONFIG.EVENT_RESIZE_START =\t\t\t\"resize.start\";\nORYX.CONFIG.EVENT_RESIZE_END =\t\t\t\t\"resize.end\";\nORYX.CONFIG.EVENT_DRAGDOCKER_DOCKED =\t\t\"dragDocker.docked\";\nORYX.CONFIG.EVENT_HIGHLIGHT_SHOW =\t\t\t\"highlight.showHighlight\";\nORYX.CONFIG.EVENT_HIGHLIGHT_HIDE =\t\t\t\"highlight.hideHighlight\";\nORYX.CONFIG.EVENT_LOADING_ENABLE =\t\t\t\"loading.enable\";\nORYX.CONFIG.EVENT_LOADING_DISABLE =\t\t\t\"loading.disable\";\nORYX.CONFIG.EVENT_LOADING_STATUS =\t\t\t\"loading.status\";\nORYX.CONFIG.EVENT_OVERLAY_SHOW =\t\t\t\"overlay.show\";\nORYX.CONFIG.EVENT_OVERLAY_HIDE =\t\t\t\"overlay.hide\";\nORYX.CONFIG.EVENT_ARRANGEMENT_TOP =\t\t\t\"arrangement.setToTop\";\nORYX.CONFIG.EVENT_ARRANGEMENT_BACK =\t\t\"arrangement.setToBack\";\nORYX.CONFIG.EVENT_ARRANGEMENT_FORWARD =\t\t\"arrangement.setForward\";\nORYX.CONFIG.EVENT_ARRANGEMENT_BACKWARD =\t\"arrangement.setBackward\";\nORYX.CONFIG.EVENT_PROPWINDOW_PROP_CHANGED =\t\"propertyWindow.propertyChanged\";\nORYX.CONFIG.EVENT_LAYOUT_ROWS =\t\t\t\t\"layout.rows\";\nORYX.CONFIG.EVENT_LAYOUT_BPEL =\t\t\t\t\"layout.BPEL\";\nORYX.CONFIG.EVENT_LAYOUT_BPEL_VERTICAL =    \"layout.BPEL.vertical\";\nORYX.CONFIG.EVENT_LAYOUT_BPEL_HORIZONTAL =  \"layout.BPEL.horizontal\";\nORYX.CONFIG.EVENT_LAYOUT_BPEL_SINGLECHILD = \"layout.BPEL.singlechild\";\nORYX.CONFIG.EVENT_LAYOUT_BPEL_AUTORESIZE =\t\"layout.BPEL.autoresize\";\nORYX.CONFIG.EVENT_AUTOLAYOUT_LAYOUT =\t\t\"autolayout.layout\";\nORYX.CONFIG.EVENT_UNDO_EXECUTE =\t\t\t\"undo.execute\";\nORYX.CONFIG.EVENT_UNDO_ROLLBACK =\t\t\t\"undo.rollback\";\nORYX.CONFIG.EVENT_BUTTON_UPDATE =           \"toolbar.button.update\";\nORYX.CONFIG.EVENT_LAYOUT = \t\t\t\t\t\"layout.dolayout\";\nORYX.CONFIG.EVENT_GLOSSARY_LINK_EDIT = \t\t\"glossary.link.edit\";\nORYX.CONFIG.EVENT_GLOSSARY_SHOW =\t\t\t\"glossary.show.info\";\nORYX.CONFIG.EVENT_GLOSSARY_NEW =\t\t\t\"glossary.show.new\";\nORYX.CONFIG.EVENT_DOCKERDRAG = \t\t\t\t\"dragTheDocker\";\nORYX.CONFIG.EVENT_CANVAS_SCROLL = \t\t\t\"canvas.scroll\";\n\t\nORYX.CONFIG.EVENT_SHOW_PROPERTYWINDOW =\t\t\"propertywindow.show\";\nORYX.CONFIG.EVENT_ABOUT_TO_SAVE = \"file.aboutToSave\";\n\t\n\t/* Selection Shapes Highlights */\nORYX.CONFIG.SELECTION_HIGHLIGHT_SIZE =\t\t\t\t5;\nORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR =\t\t\t\t\"#4444FF\";\nORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR2 =\t\t\t\"#9999FF\";\n\t\nORYX.CONFIG.SELECTION_HIGHLIGHT_STYLE_CORNER = \t\t\"corner\";\nORYX.CONFIG.SELECTION_HIGHLIGHT_STYLE_RECTANGLE = \t\"rectangle\";\n\t\nORYX.CONFIG.SELECTION_VALID_COLOR =\t\t\t\t\t\"#00FF00\";\nORYX.CONFIG.SELECTION_INVALID_COLOR =\t\t\t\t\"#FF0000\";\n\n\nORYX.CONFIG.DOCKER_DOCKED_COLOR =\t\t\"#00FF00\";\nORYX.CONFIG.DOCKER_UNDOCKED_COLOR =\t\t\"#FF0000\";\nORYX.CONFIG.DOCKER_SNAP_OFFSET =\t\t10;\n\t\t\n\t/* Copy & Paste */\nORYX.CONFIG.EDIT_OFFSET_PASTE =\t\t\t10;\n\n\t/* Key-Codes */\nORYX.CONFIG.KEY_CODE_X = \t\t\t\t88;\nORYX.CONFIG.KEY_CODE_C = \t\t\t\t67;\nORYX.CONFIG.KEY_CODE_V = \t\t\t\t86;\nORYX.CONFIG.KEY_CODE_DELETE = \t\t\t46;\nORYX.CONFIG.KEY_CODE_META =\t\t\t\t224;\nORYX.CONFIG.KEY_CODE_BACKSPACE =\t\t8;\nORYX.CONFIG.KEY_CODE_LEFT =\t\t\t\t37;\nORYX.CONFIG.KEY_CODE_RIGHT =\t\t\t39;\nORYX.CONFIG.KEY_CODE_UP =\t\t\t\t38;\nORYX.CONFIG.KEY_CODE_DOWN =\t\t\t\t40;\n\n\t// TODO Determine where the lowercase constants are still used and remove them from here.\nORYX.CONFIG.KEY_Code_enter =\t\t\t12;\nORYX.CONFIG.KEY_Code_left =\t\t\t\t37;\nORYX.CONFIG.KEY_Code_right =\t\t\t39;\nORYX.CONFIG.KEY_Code_top =\t\t\t\t38;\nORYX.CONFIG.KEY_Code_bottom =\t\t\t40;\n\n/* Supported Meta Keys */\n\t\nORYX.CONFIG.META_KEY_META_CTRL = \t\t\"metactrl\";\nORYX.CONFIG.META_KEY_ALT = \t\t\t\t\"alt\";\nORYX.CONFIG.META_KEY_SHIFT = \t\t\t\"shift\";\n\n/* Key Actions */\n\nORYX.CONFIG.KEY_ACTION_DOWN = \t\t\t\"down\";\nORYX.CONFIG.KEY_ACTION_UP = \t\t\t\"up\";\n\n\n/* Form Rowlayouting */\nORYX.CONFIG.FORM_ROW_WIDTH =            350;\nORYX.CONFIG.FORM_GROUP_MARGIN =            5;\nORYX.CONFIG.FORM_GROUP_EMPTY_HEIGHT =   100;\n\n/* Form element types */\nORYX.CONFIG.FORM_ELEMENT_ID_PREFIX = \t\t\t\t'http://b3mn.org/stencilset/xforms';\nORYX.CONFIG.FORM_ELEMENT_TYPE_ROOT = \t\t\t\t'http://b3mn.org/stencilset/xforms#XForm';\nORYX.CONFIG.FORM_ELEMENT_TYPE_GROUP = \t\t\t\t'http://b3mn.org/stencilset/xforms#Group';\nORYX.CONFIG.FORM_ELEMENT_TYPE_REPEATING_GROUP =\t\t'http://b3mn.org/stencilset/xforms#RepeatingGroup';\nORYX.CONFIG.FORM_ELEMENT_TYPE_LABEL_FIELD = \t\t'http://b3mn.org/stencilset/xforms#LabelField';\n\t\n\t/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nfunction printf() {\n\t\n\tvar result = arguments[0];\n\tfor (var i=1; i<arguments.length; i++)\n\t\tresult = result.replace('%' + (i-1), arguments[i]);\n\treturn result;\n}\n\n// oryx constants.\nvar ORYX_LOGLEVEL_TRACE = 5;\nvar ORYX_LOGLEVEL_DEBUG = 4;\nvar ORYX_LOGLEVEL_INFO = 3;\nvar ORYX_LOGLEVEL_WARN = 2;\nvar ORYX_LOGLEVEL_ERROR = 1;\nvar ORYX_LOGLEVEL_FATAL = 0;\nvar ORYX_LOGLEVEL = 3;\nvar ORYX_CONFIGURATION_DELAY = 100;\nvar ORYX_CONFIGURATION_WAIT_ATTEMPTS = 10;\n\nif(!ORYX) var ORYX = {};\n\nORYX = Object.extend(ORYX, {\n\n\t//set the path in the config.js file!!!!\n\tPATH: ORYX.CONFIG.ROOT_PATH,\n\t//CONFIGURATION: \"config.js\",\n\n\tURLS: [],\n\n\talreadyLoaded: [],\n\n\tconfigrationRetries: 0,\n\n\tVersion: '0.1.1',\n\n\tavailablePlugins: [],\n\n\t/**\n\t * The ORYX.Log logger.\n\t */\n\tLog: {\n\t\n\t\t__appenders: [\n\t\t\t{ \n\t\t\t\tappend: function(message) {\n\t\t\t\t\tif(typeof(console) !== \"undefined\" && console.log !== undefined) {\n\t\t\t\t\t\tconsole.log(message); \n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t],\n\t\n\t\ttrace: function() {\tif(ORYX_LOGLEVEL >= ORYX_LOGLEVEL_TRACE)\n\t\t\tORYX.Log.__log('TRACE', arguments); },\n\t\tdebug: function() { if(ORYX_LOGLEVEL >= ORYX_LOGLEVEL_DEBUG)\n\t\t\tORYX.Log.__log('DEBUG', arguments); },\n\t\tinfo: function() { if(ORYX_LOGLEVEL >= ORYX_LOGLEVEL_INFO)\n\t\t\tORYX.Log.__log('INFO', arguments); },\n\t\twarn: function() { if(ORYX_LOGLEVEL >= ORYX_LOGLEVEL_WARN)\n\t\t\tORYX.Log.__log('WARN', arguments); },\n\t\terror: function() { if(ORYX_LOGLEVEL >= ORYX_LOGLEVEL_ERROR)\n\t\t\tORYX.Log.__log('ERROR', arguments); },\n\t\tfatal: function() { if(ORYX_LOGLEVEL >= ORYX_LOGLEVEL_FATAL)\n\t\t\tORYX.Log.__log('FATAL', arguments); },\n\t\t\n\t\t__log: function(prefix, messageParts) {\n\t\t\t\n\t\t\tmessageParts[0] = (new Date()).getTime() + \" \"\n\t\t\t\t+ prefix + \" \" + messageParts[0];\n\t\t\tvar message = printf.apply(null, messageParts);\n\t\t\t\n\t\t\tORYX.Log.__appenders.each(function(appender) {\n\t\t\t\tappender.append(message);\n\t\t\t});\n\t\t},\n\t\t\n\t\taddAppender: function(appender) {\n\t\t\tORYX.Log.__appenders.push(appender);\n\t\t}\n\t},\n\n\t/**\n\t * First bootstrapping layer. The Oryx loading procedure begins. In this\n\t * step, all preliminaries that are not in the responsibility of Oryx to be\n\t * met have to be checked here, such as the existance of the prototpe\n\t * library in the current execution environment. After that, the second\n\t * bootstrapping layer is being invoked. Failing to ensure that any\n\t * preliminary condition is not met has to fail with an error.\n\t */\n\tload: function() {\n\t\t\n\t\tORYX.Log.debug(\"Oryx begins loading procedure.\");\n\t\t\n\t\t// check for prototype\n\t\tif( (typeof Prototype=='undefined') ||\n\t\t\t(typeof Element == 'undefined') ||\n\t\t\t(typeof Element.Methods=='undefined') ||\n\t\t\tparseFloat(Prototype.Version.split(\".\")[0] + \".\" +\n\t\t\t\tPrototype.Version.split(\".\")[1]) < 1.5)\n\n\t\t\tthrow(\"Application requires the Prototype JavaScript framework >= 1.5.3\");\n\t\t\n\t\tORYX.Log.debug(\"Prototype > 1.5 found.\");\n\n\t\t// continue loading.\n\t\tORYX._load();\n\t},\n\n\t/**\n\t * Second bootstrapping layer. The oryx configuration is checked. When not\n\t * yet loaded, config.js is being requested from the server. A repeated\n\t * error in retrieving the configuration will result in an error to be\n\t * thrown after a certain time of retries. Once the configuration is there,\n\t * all urls that are registered with oryx loading are being requested from\n\t * the server. Once everything is loaded, the third layer is being invoked.\n\t */\n\t_load: function() {\n\t/*\n\t\t// if configuration not there already,\n\t\tif(!(ORYX.CONFIG)) {\n\t\t\t\n\t\t\t// if this is the first attempt...\n\t\t\tif(ORYX.configrationRetries == 0) {\n\t\t\t\t\n\t\t\t\t// get the path and filename.\n\t\t\t\tvar configuration = ORYX.PATH + ORYX.CONFIGURATION;\n\t\n\t\t\t\tORYX.Log.debug(\"Configuration not found, loading from '%0'.\",\n\t\t\t\t\tconfiguration);\n\t\t\t\t\n\t\t\t\t// require configuration file.\n\t\t\t\tKickstart.require(configuration);\n\t\t\t\t\n\t\t\t// else if attempts exceeded ...\n\t\t\t} else if(ORYX.configrationRetries >= ORYX_CONFIGURATION_WAIT_ATTEMPTS) {\n\t\t\t\t\n\t\t\t\tthrow \"Tried to get configuration\" +\n\t\t\t\t\tORYX_CONFIGURATION_WAIT_ATTEMPTS +\n\t\t\t\t\t\" times from '\" + configuration + \"'. Giving up.\"\n\t\t\t\t\t\n\t\t\t} else if(ORYX.configrationRetries > 0){\n\t\t\t\t\n\t\t\t\t// point out how many attempts are left...\n\t\t\t\tORYX.Log.debug(\"Waiting once more (%0 attempts left)\",\n\t\t\t\t\t(ORYX_CONFIGURATION_WAIT_ATTEMPTS -\n\t\t\t\t\t\tORYX.configrationRetries));\n\n\t\t\t}\n\t\t\t\n\t\t\t// any case: continue in a moment with increased retry count.\n\t\t\tORYX.configrationRetries++;\n\t\t\twindow.setTimeout(ORYX._load, ORYX_CONFIGURATION_DELAY);\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tORYX.Log.info(\"Configuration loaded.\");\n\t\t\n\t\t// load necessary scripts.\n\t\tORYX.URLS.each(function(url) {\n\t\t\tORYX.Log.debug(\"Requireing '%0'\", url);\n\t\t\tKickstart.require(ORYX.PATH + url) });\n\t*/\n\t\t// configurate logging and load plugins.\n\t\tORYX.loadPlugins();\n\t},\n\n\t/**\n\t * Third bootstrapping layer. This is where first the plugin coniguration\n\t * file is loaded into oryx, analyzed, and where all plugins are being\n\t * requested by the server. Afterwards, all editor instances will be\n\t * initialized.\n\t */\n\tloadPlugins: function() {\n\t\t\n\t\t// load plugins if enabled.\n\t\tif(ORYX.CONFIG.PLUGINS_ENABLED)\n\t\t\tORYX._loadPlugins()\n\t\telse\n\t\t\tORYX.Log.warn(\"Ignoring plugins, loading Core only.\");\n\n\t\t// init the editor instances.\n\t\tinit();\n\t},\n\t\n\t_loadPlugins: function() {\n\n\t\t// load plugin configuration file.\n\t\tvar source = ORYX.CONFIG.PLUGINS_CONFIG;\n\n\t\tORYX.Log.debug(\"Loading plugin configuration from '%0'.\", source);\n\t\n\t\tnew Ajax.Request(source, {\n\t\t\tasynchronous: false,\n\t\t\tmethod: 'get',\n\t\t\tonSuccess: function(result) {\n\n\t\t\t\t/*\n\t\t\t\t * This is the method that is being called when the plugin\n\t\t\t\t * configuration was successfully loaded from the server. The\n\t\t\t\t * file has to be processed and the contents need to be\n\t\t\t\t * considered for further plugin requireation.\n\t\t\t\t */\n\t\t\t\t\n\t\t\t\tORYX.Log.info(\"Plugin configuration file loaded.\");\n\t\t\n\t\t\t\t// get plugins.xml content\n\t\t\t\tvar resultXml = result.responseXML;\n\t\t\t\t\n\t\t\t\t// TODO: Describe how properties are handled.\n\t\t\t\t// Get the globale Properties\n\t\t\t\tvar globalProperties = [];\n\t\t\t\tvar preferences = $A(resultXml.getElementsByTagName(\"properties\"));\n\t\t\t\tpreferences.each( function(p) {\n\n\t\t\t\t\tvar props = $A(p.childNodes);\n\t\t\t\t\tprops.each( function(prop) {\n\t\t\t\t\t\tvar property = new Hash(); \n\t\t\t\t\t\t\n\t\t\t\t\t\t// get all attributes from the node and set to global properties\n\t\t\t\t\t\tvar attributes = $A(prop.attributes)\n\t\t\t\t\t\tattributes.each(function(attr){property[attr.nodeName] = attr.nodeValue});\t\t\t\t\n\t\t\t\t\t\tif(attributes.length > 0) { globalProperties.push(property) };\t\t\t\t\n\t\t\t\t\t});\n\t\t\t\t});\n\n\t\t\t\t\n\t\t\t\t// TODO Why are we using XML if we don't respect structure anyway?\n\t\t\t\t// for each plugin element in the configuration..\n\t\t\t\tvar plugin = resultXml.getElementsByTagName(\"plugin\");\n\t\t\t\t$A(plugin).each( function(node) {\n\t\t\t\t\t\n\t\t\t\t\t// get all element's attributes.\n\t\t\t\t\t// TODO: What about: var pluginData = $H(node.attributes) !?\n\t\t\t\t\tvar pluginData = new Hash();\n\t\t\t\t\t$A(node.attributes).each( function(attr){\n\t\t\t\t\t\tpluginData[attr.nodeName] = attr.nodeValue});\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t// ensure there's a name attribute.\n\t\t\t\t\tif(!pluginData['name']) {\n\t\t\t\t\t\tORYX.Log.error(\"A plugin is not providing a name. Ingnoring this plugin.\");\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t// ensure there's a source attribute.\n\t\t\t\t\tif(!pluginData['source']) {\n\t\t\t\t\t\tORYX.Log.error(\"Plugin with name '%0' doesn't provide a source attribute.\", pluginData['name']);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t// Get all private Properties\n\t\t\t\t\tvar propertyNodes = node.getElementsByTagName(\"property\");\n\t\t\t\t\tvar properties = [];\n\t\t\t\t\t$A(propertyNodes).each(function(prop) {\n\t\t\t\t\t\tvar property = new Hash(); \n\t\t\t\t\t\t\n\t\t\t\t\t\t// Get all Attributes from the Node\t\t\t\n\t\t\t\t\t\tvar attributes = $A(prop.attributes)\n\t\t\t\t\t\tattributes.each(function(attr){property[attr.nodeName] = attr.nodeValue});\t\t\t\t\n\t\t\t\t\t\tif(attributes.length > 0) { properties.push(property) };\t\n\t\t\t\t\t\n\t\t\t\t\t});\n\t\t\t\t\t\n\t\t\t\t\t// Set all Global-Properties to the Properties\n\t\t\t\t\tproperties = properties.concat(globalProperties);\n\t\t\t\t\t\n\t\t\t\t\t// Set Properties to Plugin-Data\n\t\t\t\t\tpluginData['properties'] = properties;\n\t\t\t\t\t\n\t\t\t\t\t// Get the RequieredNodes\n\t\t\t\t\tvar requireNodes = node.getElementsByTagName(\"requires\");\n\t\t\t\t\tvar requires;\n\t\t\t\t\t$A(requireNodes).each(function(req) {\t\t\t\n\t\t\t\t\t\tvar namespace = $A(req.attributes).find(function(attr){ return attr.name == \"namespace\"})\n\t\t\t\t\t\tif( namespace && namespace.nodeValue ){\n\t\t\t\t\t\t\tif( !requires ){\n\t\t\t\t\t\t\t\trequires = {namespaces:[]}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\t\trequires.namespaces.push(namespace.nodeValue)\n\t\t\t\t\t\t} \n\t\t\t\t\t});\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t// Set Requires to the Plugin-Data, if there is one\n\t\t\t\t\tif( requires ){\n\t\t\t\t\t\tpluginData['requires'] = requires;\n\t\t\t\t\t}\n\n\n\t\t\t\t\t// Get the RequieredNodes\n\t\t\t\t\tvar notUsesInNodes = node.getElementsByTagName(\"notUsesIn\");\n\t\t\t\t\tvar notUsesIn;\n\t\t\t\t\t$A(notUsesInNodes).each(function(not) {\t\t\t\n\t\t\t\t\t\tvar namespace = $A(not.attributes).find(function(attr){ return attr.name == \"namespace\"})\n\t\t\t\t\t\tif( namespace && namespace.nodeValue ){\n\t\t\t\t\t\t\tif( !notUsesIn ){\n\t\t\t\t\t\t\t\tnotUsesIn = {namespaces:[]}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\t\tnotUsesIn.namespaces.push(namespace.nodeValue)\n\t\t\t\t\t\t} \n\t\t\t\t\t});\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t// Set Requires to the Plugin-Data, if there is one\n\t\t\t\t\tif( notUsesIn ){\n\t\t\t\t\t\tpluginData['notUsesIn'] = notUsesIn;\n\t\t\t\t\t}\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\tvar url = ORYX.PATH + ORYX.CONFIG.PLUGINS_FOLDER + pluginData['source'];\n\t\t\n\t\t\t\t\tORYX.Log.debug(\"Requireing '%0'\", url);\n\t\t\n\t\t\t\t\t// Add the Script-Tag to the Site\n\t\t\t\t\t//Kickstart.require(url);\n\t\t\n\t\t\t\t\tORYX.Log.info(\"Plugin '%0' successfully loaded.\", pluginData['name']);\n\t\t\n\t\t\t\t\t// Add the Plugin-Data to all available Plugins\n\t\t\t\t\tORYX.availablePlugins.push(pluginData);\n\t\t\n\t\t\t\t});\n\t\t\n\t\t\t},\n\t\t\tonFailure:this._loadPluginsOnFails\n\t\t});\n\n\t},\n\n\t_loadPluginsOnFails: function(result) {\n\n\t\tORYX.Log.error(\"Plugin configuration file not available.\");\n\t}\n});\n\n\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespaces\n */\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\nif(!ORYX.Core.SVG) {ORYX.Core.SVG = {};}\n\n\n/**\n * EditPathHandler\n * \n * Edit SVG paths' coordinates according to specified from-to movement and\n * horizontal and vertical scaling factors. \n * The resulting path's d attribute is stored in instance variable d.\n * \n * @constructor\n */\nORYX.Core.SVG.EditPathHandler = Clazz.extend({\n\t\n\tconstruct: function() {\n\t\targuments.callee.$.construct.apply(this, arguments);\n\t\t\n\t\tthis.x = 0;\n\t\tthis.y = 0;\n\t\tthis.oldX = 0;\n\t\tthis.oldY = 0;\n\t\tthis.deltaWidth = 1;\n\t\tthis.deltaHeight = 1;\n\t\t\n\t\tthis.d = \"\";\n\t},\n\t\n\t/**\n\t * init\n\t * \n\t * @param {float} x Target point's x-coordinate\n\t * @param {float} y Target point's y-coordinate\n\t * @param {float} oldX Reference point's x-coordinate\n\t * @param {float} oldY Reference point's y-coordinate\n\t * @param {float} deltaWidth Horizontal scaling factor\n\t * @param {float} deltaHeight Vertical scaling factor\n\t */\n\tinit: function(x, y, oldX, oldY, deltaWidth, deltaHeight) {\n\t\tthis.x = x;\n\t\tthis.y = y;\n\t\tthis.oldX = oldX;\n\t\tthis.oldY = oldY;\n\t\tthis.deltaWidth = deltaWidth;\n\t\tthis.deltaHeight = deltaHeight;\n\t\t\n\t\tthis.d = \"\";\n\t},\n\n\t/**\n\t * editPointsAbs\n\t * \n\t * @param {Array} points Array of absolutePoints\n\t */\n\teditPointsAbs: function(points) {\n\t\tif(points instanceof Array) {\n\t\t\tvar newPoints = [];\n\t\t\tvar x, y;\n\t\t\tfor(var i = 0; i < points.length; i++) {\n\t\t\t\tx = (parseFloat(points[i]) - this.oldX)*this.deltaWidth + this.x;\n\t\t\t\ti++;\n\t\t\t\ty = (parseFloat(points[i]) - this.oldY)*this.deltaHeight + this.y;\n\t\t\t\tnewPoints.push(x);\n\t\t\t\tnewPoints.push(y);\n\t\t\t}\n\t\t\t\n\t\t\treturn newPoints;\n\t\t} else {\n\t\t\t//TODO error\n\t\t}\n\t},\n\t\n\t/**\n\t * editPointsRel\n\t * \n\t * @param {Array} points Array of absolutePoints\n\t */\n\teditPointsRel: function(points) {\n\t\tif(points instanceof Array) {\n\t\t\tvar newPoints = [];\n\t\t\tvar x, y;\n\t\t\tfor(var i = 0; i < points.length; i++) {\n\t\t\t\tx = parseFloat(points[i])*this.deltaWidth;\n\t\t\t\ti++;\n\t\t\t\ty = parseFloat(points[i])*this.deltaHeight;\n\t\t\t\tnewPoints.push(x);\n\t\t\t\tnewPoints.push(y);\n\t\t\t}\n\t\t\t\n\t\t\treturn newPoints;\n\t\t} else {\n\t\t\t//TODO error\n\t\t}\n\t},\n\n\t/**\n\t * arcAbs - A\n\t * \n\t * @param {Number} rx\n\t * @param {Number} ry\n\t * @param {Number} xAxisRotation\n\t * @param {Boolean} largeArcFlag\n\t * @param {Boolean} sweepFlag\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tarcAbs: function(rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) {\n\t    var pointsAbs = this.editPointsAbs([x, y]);\n\t\tvar pointsRel = this.editPointsRel([rx, ry]);\n\t\t\n\t\tthis.d = this.d.concat(\" A\" + pointsRel[0] + \" \" + pointsRel[1] + \n\t\t\t\t\t\t\t\t\" \" + xAxisRotation + \" \" + largeArcFlag + \n\t\t\t\t\t\t\t\t\" \" + sweepFlag + \" \" + pointsAbs[0] + \" \" +\n\t\t\t\t\t\t\t\tpointsAbs[1] + \" \");\t\t\t\t\t\n\t},\n\n\t/**\n\t * arcRel - a\n\t * \n\t * @param {Number} rx\n\t * @param {Number} ry\n\t * @param {Number} xAxisRotation\n\t * @param {Boolean} largeArcFlag\n\t * @param {Boolean} sweepFlag\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tarcRel: function(rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) {\n\t\tvar pointsRel = this.editPointsRel([rx, ry, x, y]);\n\t\t\n\t\tthis.d = this.d.concat(\" a\" + pointsRel[0] + \" \" + pointsRel[1] + \n\t\t\t\t\t\t\t\t\" \" + xAxisRotation + \" \" + largeArcFlag + \n\t\t\t\t\t\t\t\t\" \" + sweepFlag + \" \" + pointsRel[2] + \" \" +\n\t\t\t\t\t\t\t\tpointsRel[3] + \" \");\t\n\t},\n\n\t/**\n\t * curvetoCubicAbs - C\n\t * \n\t * @param {Number} x1\n\t * @param {Number} y1\n\t * @param {Number} x2\n\t * @param {Number} y2\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoCubicAbs: function(x1, y1, x2, y2, x, y) {\n\t    var pointsAbs = this.editPointsAbs([x1, y1, x2, y2, x, y]);\n\t\t\n\t\tthis.d = this.d.concat(\" C\" + pointsAbs[0] + \" \" + pointsAbs[1] + \n\t\t\t\t\t\t\t\t\" \" + pointsAbs[2] + \" \" + pointsAbs[3] + \n\t\t\t\t\t\t\t\t\" \" + pointsAbs[4] + \" \" + pointsAbs[5] + \" \");\t\n\t},\n\n\t/**\n\t * curvetoCubicRel - c\n\t * \n\t * @param {Number} x1\n\t * @param {Number} y1\n\t * @param {Number} x2\n\t * @param {Number} y2\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoCubicRel: function(x1, y1, x2, y2, x, y) {\n\t    var pointsRel = this.editPointsRel([x1, y1, x2, y2, x, y]);\n\t\t\n\t\tthis.d = this.d.concat(\" c\" + pointsRel[0] + \" \" + pointsRel[1] + \n\t\t\t\t\t\t\t\t\" \" + pointsRel[2] + \" \" + pointsRel[3] + \n\t\t\t\t\t\t\t\t\" \" + pointsRel[4] + \" \" + pointsRel[5] + \" \");\t\n\t},\n\n\t/**\n\t * linetoHorizontalAbs - H\n\t * \n\t * @param {Number} x\n\t */\n\tlinetoHorizontalAbs: function(x) {\n\t    var pointsAbs = this.editPointsAbs([x, 0]);\n\t\t\n\t\tthis.d = this.d.concat(\" H\" + pointsAbs[0] + \" \");\t\n\t},\n\n\t/**\n\t * linetoHorizontalRel - h\n\t * \n\t * @param {Number} x\n\t */\n\tlinetoHorizontalRel: function(x) {\n\t    var pointsRel = this.editPointsRel([x, 0]);\n\t\t\n\t\tthis.d = this.d.concat(\" h\" + pointsRel[0] + \" \");\t\n\t},\n\n\t/**\n\t * linetoAbs - L\n\t * \n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tlinetoAbs: function(x, y) {\n\t    var pointsAbs = this.editPointsAbs([x, y]);\n\t\t\n\t\tthis.d = this.d.concat(\" L\" + pointsAbs[0] + \" \" + pointsAbs[1] + \" \");\n\t},\n\n\t/**\n\t * linetoRel - l\n\t * \n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tlinetoRel: function(x, y) {\n\t    var pointsRel = this.editPointsRel([x, y]);\n\t\t\n\t\tthis.d = this.d.concat(\" l\" + pointsRel[0] + \" \" + pointsRel[1] + \" \");\n\t},\n\n\t/**\n\t * movetoAbs - M\n\t * \n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tmovetoAbs: function(x, y) {\n\t    var pointsAbs = this.editPointsAbs([x, y]);\n\t\t\n\t\tthis.d = this.d.concat(\" M\" + pointsAbs[0] + \" \" + pointsAbs[1] + \" \");\n\t},\n\n\t/**\n\t * movetoRel - m\n\t * \n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tmovetoRel: function(x, y) {\n\t    var pointsRel;\n\t\tif(this.d === \"\") {\n\t\t\tpointsRel = this.editPointsAbs([x, y]);\n\t\t} else {\n\t\t\tpointsRel = this.editPointsRel([x, y]);\n\t\t}\n\t\t\n\t\tthis.d = this.d.concat(\" m\" + pointsRel[0] + \" \" + pointsRel[1] + \" \");\n\t},\n\n\t/**\n\t * curvetoQuadraticAbs - Q\n\t * \n\t * @param {Number} x1\n\t * @param {Number} y1\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoQuadraticAbs: function(x1, y1, x, y) {\n\t    var pointsAbs = this.editPointsAbs([x1, y1, x, y]);\n\t\t\n\t\tthis.d = this.d.concat(\" Q\" + pointsAbs[0] + \" \" + pointsAbs[1] + \" \" +\n\t\t\t\t\t\t\t\tpointsAbs[2] + \" \" + pointsAbs[3] + \" \");\n\t},\n\n\t/**\n\t * curvetoQuadraticRel - q\n\t * \n\t * @param {Number} x1\n\t * @param {Number} y1\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoQuadraticRel: function(x1, y1, x, y) {\n\t    var pointsRel = this.editPointsRel([x1, y1, x, y]);\n\t\t\n\t\tthis.d = this.d.concat(\" q\" + pointsRel[0] + \" \" + pointsRel[1] + \" \" +\n\t\t\t\t\t\t\t\tpointsRel[2] + \" \" + pointsRel[3] + \" \");\n\t},\n\n\t/**\n\t * curvetoCubicSmoothAbs - S\n\t * \n\t * @param {Number} x2\n\t * @param {Number} y2\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoCubicSmoothAbs: function(x2, y2, x, y) {\n\t    var pointsAbs = this.editPointsAbs([x2, y2, x, y]);\n\t\t\n\t\tthis.d = this.d.concat(\" S\" + pointsAbs[0] + \" \" + pointsAbs[1] + \" \" +\n\t\t\t\t\t\t\t\tpointsAbs[2] + \" \" + pointsAbs[3] + \" \");\n\t},\n\n\t/**\n\t * curvetoCubicSmoothRel - s\n\t * \n\t * @param {Number} x2\n\t * @param {Number} y2\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoCubicSmoothRel: function(x2, y2, x, y) {\n\t    var pointsRel = this.editPointsRel([x2, y2, x, y]);\n\t\t\n\t\tthis.d = this.d.concat(\" s\" + pointsRel[0] + \" \" + pointsRel[1] + \" \" +\n\t\t\t\t\t\t\t\tpointsRel[2] + \" \" + pointsRel[3] + \" \");\n\t},\n\n\t/**\n\t * curvetoQuadraticSmoothAbs - T\n\t * \n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoQuadraticSmoothAbs: function(x, y) {\n\t    var pointsAbs = this.editPointsAbs([x, y]);\n\t\t\n\t\tthis.d = this.d.concat(\" T\" + pointsAbs[0] + \" \" + pointsAbs[1] + \" \");\n\t},\n\n\t/**\n\t * curvetoQuadraticSmoothRel - t\n\t * \n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoQuadraticSmoothRel: function(x, y) {\n\t    var pointsRel = this.editPointsRel([x, y]);\n\t\t\n\t\tthis.d = this.d.concat(\" t\" + pointsRel[0] + \" \" + pointsRel[1] + \" \");\n\t},\n\n\t/**\n\t * linetoVerticalAbs - V\n\t * \n\t * @param {Number} y\n\t */\n\tlinetoVerticalAbs: function(y) {\n\t    var pointsAbs = this.editPointsAbs([0, y]);\n\t\t\n\t\tthis.d = this.d.concat(\" V\" + pointsAbs[1] + \" \");\n\t},\n\n\t/**\n\t * linetoVerticalRel - v\n\t * \n\t * @param {Number} y\n\t */\n\tlinetoVerticalRel: function(y) {\n\t    var pointsRel = this.editPointsRel([0, y]);\n\t\t\n\t\tthis.d = this.d.concat(\" v\" + pointsRel[1] + \" \");\n\t},\n\n\t/**\n\t * closePath - z or Z\n\t */\n\tclosePath: function() {\n\t    this.d = this.d.concat(\" z\");\n\t}\n\n});/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespaces\n */\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\nif(!ORYX.Core.SVG) {ORYX.Core.SVG = {};}\n\n\n/**\n * MinMaxPathHandler\n * \n * Determine the minimum and maximum of a SVG path's absolute coordinates.\n * For relative coordinates the absolute value is computed for consideration.\n * The values are stored in attributes minX, minY, maxX, and maxY.\n * \n * @constructor\n */\nORYX.Core.SVG.MinMaxPathHandler = Clazz.extend({\n\t\n\tconstruct: function() {\n\t\targuments.callee.$.construct.apply(this, arguments);\n\t\t\n\t\tthis.minX = undefined;\n\t\tthis.minY = undefined;\n\t\tthis.maxX = undefined;\n\t\tthis.maxY = undefined;\n\t\t\n\t\tthis._lastAbsX = undefined;\n\t\tthis._lastAbsY = undefined;\n\t},\n\n\t/**\n\t * Store minimal and maximal coordinates of passed points to attributes minX, maxX, minY, maxY\n\t * \n\t * @param {Array} points Array of absolutePoints\n\t */\n\tcalculateMinMax: function(points) {\n\t\tif(points instanceof Array) {\n\t\t\tvar x, y;\n\t\t\tfor(var i = 0; i < points.length; i++) {\n\t\t\t\tx = parseFloat(points[i]);\n\t\t\t\ti++;\n\t\t\t\ty = parseFloat(points[i]);\n\t\t\t\t\n\t\t\t\tthis.minX = (this.minX !== undefined) ? Math.min(this.minX, x) : x;\n\t\t\t\tthis.maxX = (this.maxX !== undefined) ? Math.max(this.maxX, x) : x;\n\t\t\t\tthis.minY = (this.minY !== undefined) ? Math.min(this.minY, y) : y;\n\t\t\t\tthis.maxY = (this.maxY !== undefined) ? Math.max(this.maxY, y) : y;\n\t\t\t\t\t\n\t\t\t\tthis._lastAbsX = x;\n\t\t\t\tthis._lastAbsY = y;\n\t\t\t}\n\t\t} else {\n\t\t\t//TODO error\n\t\t}\n\t},\n\n\t/**\n\t * arcAbs - A\n\t * \n\t * @param {Number} rx\n\t * @param {Number} ry\n\t * @param {Number} xAxisRotation\n\t * @param {Boolean} largeArcFlag\n\t * @param {Boolean} sweepFlag\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tarcAbs: function(rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) {\n\t    this.calculateMinMax([x, y]);\n\t},\n\n\t/**\n\t * arcRel - a\n\t * \n\t * @param {Number} rx\n\t * @param {Number} ry\n\t * @param {Number} xAxisRotation\n\t * @param {Boolean} largeArcFlag\n\t * @param {Boolean} sweepFlag\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tarcRel: function(rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) {\n\t    this.calculateMinMax([this._lastAbsX + x, this._lastAbsY + y]);\n\t},\n\n\t/**\n\t * curvetoCubicAbs - C\n\t * \n\t * @param {Number} x1\n\t * @param {Number} y1\n\t * @param {Number} x2\n\t * @param {Number} y2\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoCubicAbs: function(x1, y1, x2, y2, x, y) {\n\t    this.calculateMinMax([x1, y1, x2, y2, x, y]);\n\t},\n\n\t/**\n\t * curvetoCubicRel - c\n\t * \n\t * @param {Number} x1\n\t * @param {Number} y1\n\t * @param {Number} x2\n\t * @param {Number} y2\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoCubicRel: function(x1, y1, x2, y2, x, y) {\n\t    this.calculateMinMax([this._lastAbsX + x1, this._lastAbsY + y1,\n\t\t\t\t\t\t\t  this._lastAbsX + x2, this._lastAbsY + y2,\n\t\t\t\t\t\t\t  this._lastAbsX + x, this._lastAbsY + y]);\n\t},\n\n\t/**\n\t * linetoHorizontalAbs - H\n\t * \n\t * @param {Number} x\n\t */\n\tlinetoHorizontalAbs: function(x) {\n\t    this.calculateMinMax([x, this._lastAbsY]);\n\t},\n\n\t/**\n\t * linetoHorizontalRel - h\n\t * \n\t * @param {Number} x\n\t */\n\tlinetoHorizontalRel: function(x) {\n\t    this.calculateMinMax([this._lastAbsX + x, this._lastAbsY]);\n\t},\n\n\t/**\n\t * linetoAbs - L\n\t * \n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tlinetoAbs: function(x, y) {\n\t    this.calculateMinMax([x, y]);\n\t},\n\n\t/**\n\t * linetoRel - l\n\t * \n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tlinetoRel: function(x, y) {\n\t    this.calculateMinMax([this._lastAbsX + x, this._lastAbsY + y]);\n\t},\n\n\t/**\n\t * movetoAbs - M\n\t * \n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tmovetoAbs: function(x, y) {\n\t    this.calculateMinMax([x, y]);\n\t},\n\n\t/**\n\t * movetoRel - m\n\t * \n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tmovetoRel: function(x, y) {\n\t    if(this._lastAbsX && this._lastAbsY) {\n\t\t\tthis.calculateMinMax([this._lastAbsX + x, this._lastAbsY + y]);\n\t\t} else {\n\t\t\tthis.calculateMinMax([x, y]);\n\t\t}\n\t},\n\n\t/**\n\t * curvetoQuadraticAbs - Q\n\t * \n\t * @param {Number} x1\n\t * @param {Number} y1\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoQuadraticAbs: function(x1, y1, x, y) {\n\t    this.calculateMinMax([x1, y1, x, y]);\n\t},\n\n\t/**\n\t * curvetoQuadraticRel - q\n\t * \n\t * @param {Number} x1\n\t * @param {Number} y1\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoQuadraticRel: function(x1, y1, x, y) {\n\t    this.calculateMinMax([this._lastAbsX + x1, this._lastAbsY + y1, this._lastAbsX + x, this._lastAbsY + y]);\n\t},\n\n\t/**\n\t * curvetoCubicSmoothAbs - S\n\t * \n\t * @param {Number} x2\n\t * @param {Number} y2\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoCubicSmoothAbs: function(x2, y2, x, y) {\n\t    this.calculateMinMax([x2, y2, x, y]);\n\t},\n\n\t/**\n\t * curvetoCubicSmoothRel - s\n\t * \n\t * @param {Number} x2\n\t * @param {Number} y2\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoCubicSmoothRel: function(x2, y2, x, y) {\n\t    this.calculateMinMax([this._lastAbsX + x2, this._lastAbsY + y2, this._lastAbsX + x, this._lastAbsY + y]);\n\t},\n\n\t/**\n\t * curvetoQuadraticSmoothAbs - T\n\t * \n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoQuadraticSmoothAbs: function(x, y) {\n\t    this.calculateMinMax([x, y]);\n\t},\n\n\t/**\n\t * curvetoQuadraticSmoothRel - t\n\t * \n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoQuadraticSmoothRel: function(x, y) {\n\t    this.calculateMinMax([this._lastAbsX + x, this._lastAbsY + y]);\n\t},\n\n\t/**\n\t * linetoVerticalAbs - V\n\t * \n\t * @param {Number} y\n\t */\n\tlinetoVerticalAbs: function(y) {\n\t    this.calculateMinMax([this._lastAbsX, y]);\n\t},\n\n\t/**\n\t * linetoVerticalRel - v\n\t * \n\t * @param {Number} y\n\t */\n\tlinetoVerticalRel: function(y) {\n\t    this.calculateMinMax([this._lastAbsX, this._lastAbsY + y]);\n\t},\n\n\t/**\n\t * closePath - z or Z\n\t */\n\tclosePath: function() {\n\t    return;// do nothing\n\t}\n\n});/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespaces\n */\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\nif(!ORYX.Core.SVG) {ORYX.Core.SVG = {};}\n\n\n/**\n * PathHandler\n * \n * Determine absolute points of a SVG path. The coordinates are stored \n * sequentially in the attribute points (x-coordinates at even indices,\n * y-coordinates at odd indices).\n * \n * @constructor\n */\nORYX.Core.SVG.PointsPathHandler = Clazz.extend({\n\t\n\tconstruct: function() {\n\t\targuments.callee.$.construct.apply(this, arguments);\n\t\t\n\t\tthis.points = [];\n\t\t\n\t\tthis._lastAbsX = undefined;\n\t\tthis._lastAbsY = undefined;\n\t},\n\n\t/**\n\t * addPoints\n\t * \n\t * @param {Array} points Array of absolutePoints\n\t */\n\taddPoints: function(points) {\n\t\tif(points instanceof Array) {\n\t\t\tvar x, y;\n\t\t\tfor(var i = 0; i < points.length; i++) {\n\t\t\t\tx = parseFloat(points[i]);\n\t\t\t\ti++;\n\t\t\t\ty = parseFloat(points[i]);\n\t\t\t\t\n\t\t\t\tthis.points.push(x);\n\t\t\t\tthis.points.push(y);\n\t\t\t\t//this.points.push({x:x, y:y});\n\t\t\t\t\t\n\t\t\t\tthis._lastAbsX = x;\n\t\t\t\tthis._lastAbsY = y;\n\t\t\t}\n\t\t} else {\n\t\t\t//TODO error\n\t\t}\n\t},\n\n\t/**\n\t * arcAbs - A\n\t * \n\t * @param {Number} rx\n\t * @param {Number} ry\n\t * @param {Number} xAxisRotation\n\t * @param {Boolean} largeArcFlag\n\t * @param {Boolean} sweepFlag\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tarcAbs: function(rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) {\n\t    this.addPoints([x, y]);\n\t},\n\n\t/**\n\t * arcRel - a\n\t * \n\t * @param {Number} rx\n\t * @param {Number} ry\n\t * @param {Number} xAxisRotation\n\t * @param {Boolean} largeArcFlag\n\t * @param {Boolean} sweepFlag\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tarcRel: function(rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) {\n\t    this.addPoints([this._lastAbsX + x, this._lastAbsY + y]);\n\t},\n\n\t/**\n\t * curvetoCubicAbs - C\n\t * \n\t * @param {Number} x1\n\t * @param {Number} y1\n\t * @param {Number} x2\n\t * @param {Number} y2\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoCubicAbs: function(x1, y1, x2, y2, x, y) {\n\t    this.addPoints([x, y]);\n\t},\n\n\t/**\n\t * curvetoCubicRel - c\n\t * \n\t * @param {Number} x1\n\t * @param {Number} y1\n\t * @param {Number} x2\n\t * @param {Number} y2\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoCubicRel: function(x1, y1, x2, y2, x, y) {\n\t    this.addPoints([this._lastAbsX + x, this._lastAbsY + y]);\n\t},\n\n\t/**\n\t * linetoHorizontalAbs - H\n\t * \n\t * @param {Number} x\n\t */\n\tlinetoHorizontalAbs: function(x) {\n\t    this.addPoints([x, this._lastAbsY]);\n\t},\n\n\t/**\n\t * linetoHorizontalRel - h\n\t * \n\t * @param {Number} x\n\t */\n\tlinetoHorizontalRel: function(x) {\n\t    this.addPoints([this._lastAbsX + x, this._lastAbsY]);\n\t},\n\n\t/**\n\t * linetoAbs - L\n\t * \n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tlinetoAbs: function(x, y) {\n\t    this.addPoints([x, y]);\n\t},\n\n\t/**\n\t * linetoRel - l\n\t * \n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tlinetoRel: function(x, y) {\n\t    this.addPoints([this._lastAbsX + x, this._lastAbsY + y]);\n\t},\n\n\t/**\n\t * movetoAbs - M\n\t * \n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tmovetoAbs: function(x, y) {\n\t    this.addPoints([x, y]);\n\t},\n\n\t/**\n\t * movetoRel - m\n\t * \n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tmovetoRel: function(x, y) {\n\t    if(this._lastAbsX && this._lastAbsY) {\n\t\t\tthis.addPoints([this._lastAbsX + x, this._lastAbsY + y]);\n\t\t} else {\n\t\t\tthis.addPoints([x, y]);\n\t\t}\n\t},\n\n\t/**\n\t * curvetoQuadraticAbs - Q\n\t * \n\t * @param {Number} x1\n\t * @param {Number} y1\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoQuadraticAbs: function(x1, y1, x, y) {\n\t    this.addPoints([x, y]);\n\t},\n\n\t/**\n\t * curvetoQuadraticRel - q\n\t * \n\t * @param {Number} x1\n\t * @param {Number} y1\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoQuadraticRel: function(x1, y1, x, y) {\n\t    this.addPoints([this._lastAbsX + x, this._lastAbsY + y]);\n\t},\n\n\t/**\n\t * curvetoCubicSmoothAbs - S\n\t * \n\t * @param {Number} x2\n\t * @param {Number} y2\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoCubicSmoothAbs: function(x2, y2, x, y) {\n\t    this.addPoints([x, y]);\n\t},\n\n\t/**\n\t * curvetoCubicSmoothRel - s\n\t * \n\t * @param {Number} x2\n\t * @param {Number} y2\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoCubicSmoothRel: function(x2, y2, x, y) {\n\t    this.addPoints([this._lastAbsX + x, this._lastAbsY + y]);\n\t},\n\n\t/**\n\t * curvetoQuadraticSmoothAbs - T\n\t * \n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoQuadraticSmoothAbs: function(x, y) {\n\t    this.addPoints([x, y]);\n\t},\n\n\t/**\n\t * curvetoQuadraticSmoothRel - t\n\t * \n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoQuadraticSmoothRel: function(x, y) {\n\t    this.addPoints([this._lastAbsX + x, this._lastAbsY + y]);\n\t},\n\n\t/**\n\t * linetoVerticalAbs - V\n\t * \n\t * @param {Number} y\n\t */\n\tlinetoVerticalAbs: function(y) {\n\t    this.addPoints([this._lastAbsX, y]);\n\t},\n\n\t/**\n\t * linetoVerticalRel - v\n\t * \n\t * @param {Number} y\n\t */\n\tlinetoVerticalRel: function(y) {\n\t    this.addPoints([this._lastAbsX, this._lastAbsY + y]);\n\t},\n\n\t/**\n\t * closePath - z or Z\n\t */\n\tclosePath: function() {\n\t    return;// do nothing\n\t}\n\n});/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n *\n * Config variables\n */\nNAMESPACE_ORYX = \"http://www.b3mn.org/oryx\";\nNAMESPACE_SVG = \"http://www.w3.org/2000/svg/\";\n\n/**\n * @classDescription This class wraps the manipulation of a SVG marker.\n * @namespace ORYX.Core.SVG\n * uses Inheritance (Clazz)\n * uses Prototype 1.5.0\n *\n */\n\n/**\n * Init package\n */\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\nif(!ORYX.Core.SVG) {ORYX.Core.SVG = {};}\n\nORYX.Core.SVG.SVGMarker = Clazz.extend({\n\n\t/**\n\t * Constructor\n\t * @param markerElement {SVGMarkerElement}\n\t */\n\tconstruct: function(markerElement) {\n\t\targuments.callee.$.construct.apply(this, arguments);\n\n\t\tthis.id = undefined;\n\t\tthis.element = markerElement;\n\t\tthis.refX = undefined;\n\t\tthis.refY = undefined;\n\t\tthis.markerWidth = undefined;\n\t\tthis.markerHeight = undefined;\n\t\tthis.oldRefX = undefined;\n\t\tthis.oldRefY = undefined;\n\t\tthis.oldMarkerWidth = undefined;\n\t\tthis.oldMarkerHeight = undefined;\n\t\tthis.optional = false;\n\t\tthis.enabled = true;\n\t\tthis.minimumLength = undefined;\n\t\tthis.resize = false;\n\n\t\tthis.svgShapes = [];\n\n\t\tthis._init(); //initialisation of all the properties declared above.\n\t},\n\n\t/**\n\t * Initializes the values that are defined in the constructor.\n\t */\n\t_init: function() {\n\t\t//check if this.element is a SVGMarkerElement\n\t\tif(!( this.element == \"[object SVGMarkerElement]\")) {\n\t\t\tthrow \"SVGMarker: Argument is not an instance of SVGMarkerElement.\";\n\t\t}\n\n\t\tthis.id = this.element.getAttributeNS(null, \"id\");\n\t\t\n\t\t//init svg marker attributes\n\t\tvar refXValue = this.element.getAttributeNS(null, \"refX\");\n\t\tif(refXValue) {\n\t\t\tthis.refX = parseFloat(refXValue);\n\t\t} else {\n\t\t\tthis.refX = 0;\n\t\t}\n\t\tvar refYValue = this.element.getAttributeNS(null, \"refY\");\n\t\tif(refYValue) {\n\t\t\tthis.refY = parseFloat(refYValue);\n\t\t} else {\n\t\t\tthis.refY = 0;\n\t\t}\n\t\tvar markerWidthValue = this.element.getAttributeNS(null, \"markerWidth\");\n\t\tif(markerWidthValue) {\n\t\t\tthis.markerWidth = parseFloat(markerWidthValue);\n\t\t} else {\n\t\t\tthis.markerWidth = 3;\n\t\t}\n\t\tvar markerHeightValue = this.element.getAttributeNS(null, \"markerHeight\");\n\t\tif(markerHeightValue) {\n\t\t\tthis.markerHeight = parseFloat(markerHeightValue);\n\t\t} else {\n\t\t\tthis.markerHeight = 3;\n\t\t}\n\n\t\tthis.oldRefX = this.refX;\n\t\tthis.oldRefY = this.refY;\n\t\tthis.oldMarkerWidth = this.markerWidth;\n\t\tthis.oldMarkerHeight = this.markerHeight;\n\n\t\t//init oryx attributes\n\t\tvar optionalAttr = this.element.getAttributeNS(NAMESPACE_ORYX, \"optional\");\n\t\tif(optionalAttr) {\n\t\t\toptionalAttr = optionalAttr.strip();\n\t\t\tthis.optional = (optionalAttr.toLowerCase() === \"yes\");\n\t\t} else {\n\t\t\tthis.optional = false;\n\t\t}\n\n\t\tvar enabledAttr = this.element.getAttributeNS(NAMESPACE_ORYX, \"enabled\");\n\t\tif(enabledAttr) {\n\t\t\tenabledAttr = enabledAttr.strip();\n\t\t\tthis.enabled = !(enabledAttr.toLowerCase() === \"no\");\n\t\t} else {\n\t\t\tthis.enabled = true;\n\t\t}\n\n\t\tvar minLengthAttr = this.element.getAttributeNS(NAMESPACE_ORYX, \"minimumLength\");\n\t\tif(minLengthAttr) {\n\t\t\tthis.minimumLength = parseFloat(minLengthAttr);\n\t\t}\n\n\t\tvar resizeAttr = this.element.getAttributeNS(NAMESPACE_ORYX, \"resize\");\n\t\tif(resizeAttr) {\n\t\t\tresizeAttr = resizeAttr.strip();\n\t\t\tthis.resize = (resizeAttr.toLowerCase() === \"yes\");\n\t\t} else {\n\t\t\tthis.resize = false;\n\t\t}\n\n\t\t//init SVGShape objects\n\t\t//this.svgShapes = this._getSVGShapes(this.element);\n\t},\n\n\t/**\n\t *\n\t */\n\t_getSVGShapes: function(svgElement) {\n\t\tif(svgElement.hasChildNodes) {\n\t\t\tvar svgShapes = [];\n\t\t\tvar me = this;\n\t\t\t$A(svgElement.childNodes).each(function(svgChild) {\n\t\t\t\ttry {\n\t\t\t\t\tvar svgShape = new ORYX.Core.SVG.SVGShape(svgChild);\n\t\t\t\t\tsvgShapes.push(svgShape);\n\t\t\t\t} catch (e) {\n\t\t\t\t\tsvgShapes = svgShapes.concat(me._getSVGShapes(svgChild));\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn svgShapes;\n\t\t}\n\t},\n\n\t/**\n\t * Writes the changed values into the SVG marker.\n\t */\n\tupdate: function() {\n\t\t//TODO mache marker resizebar!!! aber erst wenn der rest der connectingshape funzt!\n\n//\t\t//update marker attributes\n//\t\tif(this.refX != this.oldRefX) {\n//\t\t\tthis.element.setAttributeNS(null, \"refX\", this.refX);\n//\t\t}\n//\t\tif(this.refY != this.oldRefY) {\n//\t\t\tthis.element.setAttributeNS(null, \"refY\", this.refY);\n//\t\t}\n//\t\tif(this.markerWidth != this.oldMarkerWidth) {\n//\t\t\tthis.element.setAttributeNS(null, \"markerWidth\", this.markerWidth);\n//\t\t}\n//\t\tif(this.markerHeight != this.oldMarkerHeight) {\n//\t\t\tthis.element.setAttributeNS(null, \"markerHeight\", this.markerHeight);\n//\t\t}\n//\n//\t\t//update SVGShape objects\n//\t\tvar widthDelta = this.markerWidth / this.oldMarkerWidth;\n//\t\tvar heightDelta = this.markerHeight / this.oldMarkerHeight;\n//\t\tif(widthDelta != 1 && heightDelta != 1) {\n//\t\t\tthis.svgShapes.each(function(svgShape) {\n//\n//\t\t\t});\n//\t\t}\n\n\t\t//update old values to prepare the next update\n\t\tthis.oldRefX = this.refX;\n\t\tthis.oldRefY = this.refY;\n\t\tthis.oldMarkerWidth = this.markerWidth;\n\t\tthis.oldMarkerHeight = this.markerHeight;\n\t},\n\t\n\ttoString: function() { return (this.element) ? \"SVGMarker \" + this.element.id : \"SVGMarker \" + this.element;}\n });/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n *\n * Config variables\n */\nNAMESPACE_ORYX = \"http://www.b3mn.org/oryx\";\nNAMESPACE_SVG = \"http://www.w3.org/2000/svg/\";\n\n/**\n * @classDescription This class wraps the manipulation of a SVG basic shape or a path.\n * @namespace ORYX.Core.SVG\n * uses Inheritance (Clazz)\n * uses Prototype 1.5.0\n * uses PathParser by Kevin Lindsey (http://kevlindev.com/)\n * uses MinMaxPathHandler\n * uses EditPathHandler\n *\n */\n\n//init package\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\nif(!ORYX.Core.SVG) {ORYX.Core.SVG = {};}\n\nORYX.Core.SVG.SVGShape = Clazz.extend({\n\n\t/**\n\t * Constructor\n\t * @param svgElem {SVGElement} An SVGElement that is a basic shape or a path.\n\t */\n\tconstruct: function(svgElem) {\n\t\targuments.callee.$.construct.apply(this, arguments);\n\n\t\tthis.type;\n\t\tthis.element = svgElem;\n\t\tthis.x = undefined;\n\t\tthis.y = undefined;\n\t\tthis.width = undefined;\n\t\tthis.height = undefined;\n\t\tthis.oldX = undefined;\n\t\tthis.oldY = undefined;\n\t\tthis.oldWidth = undefined;\n\t\tthis.oldHeight = undefined;\n\t\tthis.radiusX = undefined;\n\t\tthis.radiusY = undefined;\n\t\tthis.isHorizontallyResizable = false;\n\t\tthis.isVerticallyResizable = false;\n\t\t//this.anchors = [];\n\t\tthis.anchorLeft = false;\n\t\tthis.anchorRight = false;\n\t\tthis.anchorTop = false;\n\t\tthis.anchorBottom = false;\n\t\t\n\t\t//attributes of path elements of edge objects\n\t\tthis.allowDockers = true;\n\t\tthis.resizeMarkerMid = false;\n\n\t\tthis.editPathParser;\n\t\tthis.editPathHandler;\n\n\t\tthis.init(); //initialisation of all the properties declared above.\n\t},\n\n\t/**\n\t * Initializes the values that are defined in the constructor.\n\t */\n\tinit: function() {\n\n\t\t/**initialize position and size*/\n\t\tif(ORYX.Editor.checkClassType(this.element, SVGRectElement) || ORYX.Editor.checkClassType(this.element, SVGImageElement)) {\n\t\t\tthis.type = \"Rect\";\n\t\t\t\n\t\t\tvar xAttr = this.element.getAttributeNS(null, \"x\");\n\t\t\tif(xAttr) {\n\t\t\t\tthis.oldX = parseFloat(xAttr);\n\t\t\t} else {\n\t\t\t\tthrow \"Missing attribute in element \" + this.element;\n\t\t\t}\n\t\t\tvar yAttr = this.element.getAttributeNS(null, \"y\");\n\t\t\tif(yAttr) {\n\t\t\t\tthis.oldY = parseFloat(yAttr);\n\t\t\t} else {\n\t\t\t\tthrow \"Missing attribute in element \" + this.element;\n\t\t\t}\n\t\t\tvar widthAttr = this.element.getAttributeNS(null, \"width\");\n\t\t\tif(widthAttr) {\n\t\t\t\tthis.oldWidth = parseFloat(widthAttr);\n\t\t\t} else {\n\t\t\t\tthrow \"Missing attribute in element \" + this.element;\n\t\t\t}\n\t\t\tvar heightAttr = this.element.getAttributeNS(null, \"height\");\n\t\t\tif(heightAttr) {\n\t\t\t\tthis.oldHeight = parseFloat(heightAttr);\n\t\t\t} else {\n\t\t\t\tthrow \"Missing attribute in element \" + this.element;\n\t\t\t}\n\n\t\t} else if(ORYX.Editor.checkClassType(this.element, SVGCircleElement)) {\n\t\t\tthis.type = \"Circle\";\n\t\t\t\n\t\t\tvar cx = undefined;\n\t\t\tvar cy = undefined;\n\t\t\t//var r = undefined;\n\n\t\t\tvar cxAttr = this.element.getAttributeNS(null, \"cx\");\n\t\t\tif(cxAttr) {\n\t\t\t\tcx = parseFloat(cxAttr);\n\t\t\t} else {\n\t\t\t\tthrow \"Missing attribute in element \" + this.element;\n\t\t\t}\n\t\t\tvar cyAttr = this.element.getAttributeNS(null, \"cy\");\n\t\t\tif(cyAttr) {\n\t\t\t\tcy = parseFloat(cyAttr);\n\t\t\t} else {\n\t\t\t\tthrow \"Missing attribute in element \" + this.element;\n\t\t\t}\n\t\t\tvar rAttr = this.element.getAttributeNS(null, \"r\");\n\t\t\tif(rAttr) {\n\t\t\t\t//r = parseFloat(rAttr);\n\t\t\t\tthis.radiusX = parseFloat(rAttr);\n\t\t\t} else {\n\t\t\t\tthrow \"Missing attribute in element \" + this.element;\n\t\t\t}\n\t\t\tthis.oldX = cx - this.radiusX;\n\t\t\tthis.oldY = cy - this.radiusX;\n\t\t\tthis.oldWidth = 2*this.radiusX;\n\t\t\tthis.oldHeight = 2*this.radiusX;\n\n\t\t} else if(ORYX.Editor.checkClassType(this.element, SVGEllipseElement)) {\n\t\t\tthis.type = \"Ellipse\";\n\t\t\t\n\t\t\tvar cx = undefined;\n\t\t\tvar cy = undefined;\n\t\t\t//var rx = undefined;\n\t\t\t//var ry = undefined;\n\t\t\tvar cxAttr = this.element.getAttributeNS(null, \"cx\");\n\t\t\tif(cxAttr) {\n\t\t\t\tcx = parseFloat(cxAttr);\n\t\t\t} else {\n\t\t\t\tthrow \"Missing attribute in element \" + this.element;\n\t\t\t}\n\t\t\tvar cyAttr = this.element.getAttributeNS(null, \"cy\");\n\t\t\tif(cyAttr) {\n\t\t\t\tcy = parseFloat(cyAttr);\n\t\t\t} else {\n\t\t\t\tthrow \"Missing attribute in element \" + this.element;\n\t\t\t}\n\t\t\tvar rxAttr = this.element.getAttributeNS(null, \"rx\");\n\t\t\tif(rxAttr) {\n\t\t\t\tthis.radiusX = parseFloat(rxAttr);\n\t\t\t} else {\n\t\t\t\tthrow \"Missing attribute in element \" + this.element;\n\t\t\t}\n\t\t\tvar ryAttr = this.element.getAttributeNS(null, \"ry\");\n\t\t\tif(ryAttr) {\n\t\t\t\tthis.radiusY = parseFloat(ryAttr);\n\t\t\t} else {\n\t\t\t\tthrow \"Missing attribute in element \" + this.element;\n\t\t\t}\n\t\t\tthis.oldX = cx - this.radiusX;\n\t\t\tthis.oldY = cy - this.radiusY;\n\t\t\tthis.oldWidth = 2*this.radiusX;\n\t\t\tthis.oldHeight = 2*this.radiusY;\n\n\t\t} else if(ORYX.Editor.checkClassType(this.element, SVGLineElement)) {\n\t\t\tthis.type = \"Line\";\n\t\t\t\n\t\t\tvar x1 = undefined;\n\t\t\tvar y1 = undefined;\n\t\t\tvar x2 = undefined;\n\t\t\tvar y2 = undefined;\n\t\t\tvar x1Attr = this.element.getAttributeNS(null, \"x1\");\n\t\t\tif(x1Attr) {\n\t\t\t\tx1 = parseFloat(x1Attr);\n\t\t\t} else {\n\t\t\t\tthrow \"Missing attribute in element \" + this.element;\n\t\t\t}\n\t\t\tvar y1Attr = this.element.getAttributeNS(null, \"y1\");\n\t\t\tif(y1Attr) {\n\t\t\t\ty1 = parseFloat(y1Attr);\n\t\t\t} else {\n\t\t\t\tthrow \"Missing attribute in element \" + this.element;\n\t\t\t}\n\t\t\tvar x2Attr = this.element.getAttributeNS(null, \"x2\");\n\t\t\tif(x2Attr) {\n\t\t\t\tx2 = parseFloat(x2Attr);\n\t\t\t} else {\n\t\t\t\tthrow \"Missing attribute in element \" + this.element;\n\t\t\t}\n\t\t\tvar y2Attr = this.element.getAttributeNS(null, \"y2\");\n\t\t\tif(y2Attr) {\n\t\t\t\ty2 = parseFloat(y2Attr);\n\t\t\t} else {\n\t\t\t\tthrow \"Missing attribute in element \" + this.element;\n\t\t\t}\n\t\t\tthis.oldX = Math.min(x1,x2);\n\t\t\tthis.oldY = Math.min(y1,y2);\n\t\t\tthis.oldWidth = Math.abs(x1-x2);\n\t\t\tthis.oldHeight = Math.abs(y1-y2);\n\n\t\t} else if(ORYX.Editor.checkClassType(this.element, SVGPolylineElement) || ORYX.Editor.checkClassType(this.element, SVGPolygonElement)) {\n\t\t\tthis.type = \"Polyline\";\n\t\t\t\n\t\t\tvar pointsArray = [];\n\t\t\tif (this.element.points&&this.element.points.numberOfItems){\n\t\t\t    for(var i=0, size=this.element.points.numberOfItems; i<size; i++){\n\t\t\t        pointsArray.push(this.element.points.getItem(i).x)\n\t\t\t        pointsArray.push(this.element.points.getItem(i).y)\n\t\t\t    }\n\t\t\t} else {\n\t\t\t\tvar points = this.element.getAttributeNS(null, \"points\");\n\t\t\t\tif(points) {\n\t\t\t\t\tpoints = points.replace(/,/g , \" \");\n\t\t\t\t\tpointsArray = points.split(\" \");\n\t\t\t\t\tpointsArray = pointsArray.without(\"\");\n\t\t\t\t} else {\n\t\t\t\t\tthrow \"Missing attribute in element \" + this.element;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\n\t\t\tif(pointsArray && pointsArray.length && pointsArray.length > 1) {\n\t\t\t\tvar minX = parseFloat(pointsArray[0]);\n\t\t\t\tvar minY = parseFloat(pointsArray[1]);\n\t\t\t\tvar maxX = parseFloat(pointsArray[0]);\n\t\t\t\tvar maxY = parseFloat(pointsArray[1]);\n\n\t\t\t\tfor(var i = 0; i < pointsArray.length; i++) {\n\t\t\t\t\tminX = Math.min(minX, parseFloat(pointsArray[i]));\n\t\t\t\t\tmaxX = Math.max(maxX, parseFloat(pointsArray[i]));\n\t\t\t\t\ti++;\n\t\t\t\t\tminY = Math.min(minY, parseFloat(pointsArray[i]));\n\t\t\t\t\tmaxY = Math.max(maxY, parseFloat(pointsArray[i]));\n\t\t\t\t}\n\n\t\t\t\tthis.oldX = minX;\n\t\t\t\tthis.oldY = minY;\n\t\t\t\tthis.oldWidth = maxX-minX;\n\t\t\t\tthis.oldHeight = maxY-minY;\n\t\t\t} else {\n\t\t\t\tthrow \"Missing attribute in element \" + this.element;\n\t\t\t}\n\n\t\t} else if(ORYX.Editor.checkClassType(this.element, SVGPathElement)) {\n\t\t\tthis.type = \"Path\";\n\t\t\t\n\t\t\tthis.editPathParser = new PathParser();\n\t\t\tthis.editPathHandler = new ORYX.Core.SVG.EditPathHandler();\n\t\t\tthis.editPathParser.setHandler(this.editPathHandler);\n\t\t\n\t\t\tvar parser = new PathParser();\n\t\t\tvar handler = new ORYX.Core.SVG.MinMaxPathHandler();\n\t\t\tparser.setHandler(handler);\n\t\t\tparser.parsePath(this.element);\n\n\t\t\tthis.oldX = handler.minX;\n\t\t\tthis.oldY = handler.minY;\n\t\t\tthis.oldWidth = handler.maxX - handler.minX;\n\t\t\tthis.oldHeight = handler.maxY - handler.minY;\n\n\t\t\tdelete parser;\n\t\t\tdelete handler;\n\t\t} else {\n\t\t\tthrow \"Element is not a shape.\";\n\t\t}\n\n\t\t/** initialize attributes of oryx namespace */\n\t\t//resize\n\t\tvar resizeAttr = this.element.getAttributeNS(NAMESPACE_ORYX, \"resize\");\n\t\tif(resizeAttr) {\n\t\t\tresizeAttr = resizeAttr.toLowerCase();\n\t\t\tif(resizeAttr.match(/horizontal/)) {\n\t\t\t\tthis.isHorizontallyResizable = true;\n\t\t\t} else {\n\t\t\t\tthis.isHorizontallyResizable = false;\n\t\t\t}\n\t\t\tif(resizeAttr.match(/vertical/)) {\n\t\t\t\tthis.isVerticallyResizable = true;\n\t\t\t} else {\n\t\t\t\tthis.isVerticallyResizable = false;\n\t\t\t}\n\t\t} else {\n\t\t\tthis.isHorizontallyResizable = false;\n\t\t\tthis.isVerticallyResizable = false;\n\t\t}\n\n\t\t//anchors\n\t\tvar anchorAttr = this.element.getAttributeNS(NAMESPACE_ORYX, \"anchors\");\n\t\tif(anchorAttr) {\n\t\t\tanchorAttr = anchorAttr.replace(\"/,/g\", \" \");\n\t\t\tvar anchors = anchorAttr.split(\" \").without(\"\");\n\t\t\t\n\t\t\tfor(var i = 0; i < anchors.length; i++) {\n\t\t\t\tswitch(anchors[i].toLowerCase()) {\n\t\t\t\t\tcase \"left\":\n\t\t\t\t\t\tthis.anchorLeft = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"right\":\n\t\t\t\t\t\tthis.anchorRight = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"top\":\n\t\t\t\t\t\tthis.anchorTop = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"bottom\":\n\t\t\t\t\t\tthis.anchorBottom = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\t//allowDockers and resizeMarkerMid\n\t\tif(ORYX.Editor.checkClassType(this.element, SVGPathElement)) {\n\t\t\tvar allowDockersAttr = this.element.getAttributeNS(NAMESPACE_ORYX, \"allowDockers\"); \n\t\t\tif(allowDockersAttr) {\n\t\t\t\tif(allowDockersAttr.toLowerCase() === \"no\") {\n\t\t\t\t\tthis.allowDockers = false; \n\t\t\t\t} else {\n\t\t\t\t\tthis.allowDockers = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tvar resizeMarkerMidAttr = this.element.getAttributeNS(NAMESPACE_ORYX, \"resizeMarker-mid\"); \n\t\t\tif(resizeMarkerMidAttr) {\n\t\t\t\tif(resizeMarkerMidAttr.toLowerCase() === \"yes\") {\n\t\t\t\t\tthis.resizeMarkerMid = true; \n\t\t\t\t} else {\n\t\t\t\t\tthis.resizeMarkerMid = false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\t\n\t\t\t\n\t\tthis.x = this.oldX;\n\t\tthis.y = this.oldY;\n\t\tthis.width = this.oldWidth;\n\t\tthis.height = this.oldHeight;\n\t},\n\n\t/**\n\t * Writes the changed values into the SVG element.\n\t */\n\tupdate: function() {\n\t\t\n\t\tif(this.x !== this.oldX || this.y !== this.oldY || this.width !== this.oldWidth || this.height !== this.oldHeight) {\n\t\t\tswitch(this.type) {\n\t\t\t\tcase \"Rect\":\n\t\t\t\t\tif(this.x !== this.oldX) this.element.setAttributeNS(null, \"x\", this.x);\n\t\t\t\t\tif(this.y !== this.oldY) this.element.setAttributeNS(null, \"y\", this.y);\n\t\t\t\t \tif(this.width !== this.oldWidth) this.element.setAttributeNS(null, \"width\", this.width);\n\t\t\t\t\tif(this.height !== this.oldHeight) this.element.setAttributeNS(null, \"height\", this.height);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"Circle\":\n\t\t\t\t\t//calculate the radius\n\t\t\t\t\t//var r;\n//\t\t\t\t\tif(this.width/this.oldWidth <= this.height/this.oldHeight) {\n//\t\t\t\t\t\tthis.radiusX = ((this.width > this.height) ? this.width : this.height)/2.0;\n//\t\t\t\t\t} else {\n\t\t\t\t\t \tthis.radiusX = ((this.width < this.height) ? this.width : this.height)/2.0;\n\t\t\t\t\t//}\n\t\n\t\t\t\t\tthis.element.setAttributeNS(null, \"cx\", this.x + this.width/2.0);\n\t\t\t\t\tthis.element.setAttributeNS(null, \"cy\", this.y + this.height/2.0);\n\t\t\t\t\tthis.element.setAttributeNS(null, \"r\", this.radiusX);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"Ellipse\":\n\t\t\t\t\tthis.radiusX = this.width/2;\n\t\t\t\t\tthis.radiusY = this.height/2;\n\t\n\t\t\t\t\tthis.element.setAttributeNS(null, \"cx\", this.x + this.radiusX);\n\t\t\t\t\tthis.element.setAttributeNS(null, \"cy\", this.y + this.radiusY);\n\t\t\t\t\tthis.element.setAttributeNS(null, \"rx\", this.radiusX);\n\t\t\t\t\tthis.element.setAttributeNS(null, \"ry\", this.radiusY);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"Line\":\n\t\t\t\t\tif(this.x !== this.oldX)\n\t\t\t\t\t\tthis.element.setAttributeNS(null, \"x1\", this.x);\n\t\t\t\t\t\t\n\t\t\t\t\tif(this.y !== this.oldY)\n\t\t\t\t\t\tthis.element.setAttributeNS(null, \"y1\", this.y);\n\t\t\t\t\t\t\n\t\t\t\t\tif(this.x !== this.oldX || this.width !== this.oldWidth)\n\t\t\t\t\t\tthis.element.setAttributeNS(null, \"x2\", this.x + this.width);\n\t\t\t\t\t\n\t\t\t\t\tif(this.y !== this.oldY || this.height !== this.oldHeight)\n\t\t\t\t\t\tthis.element.setAttributeNS(null, \"y2\", this.y + this.height);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"Polyline\":\n\t\t\t\t\tvar points = this.element.getAttributeNS(null, \"points\");\n\t\t\t\t\tif(points) {\n\t\t\t\t\t\tpoints = points.replace(/,/g, \" \").split(\" \").without(\"\");\n\t\n\t\t\t\t\t\tif(points && points.length && points.length > 1) {\n\t\n\t\t\t\t\t\t\t//TODO what if oldWidth == 0?\n\t\t\t\t\t\t\tvar widthDelta = (this.oldWidth === 0) ? 0 : this.width / this.oldWidth;\n\t\t\t\t\t\t    var heightDelta = (this.oldHeight === 0) ? 0 : this.height / this.oldHeight;\n\t\n\t\t\t\t\t\t\tvar updatedPoints = \"\";\n\t\t\t\t\t\t    for(var i = 0; i < points.length; i++) {\n\t\t\t\t\t\t\t\tvar x = (parseFloat(points[i])-this.oldX)*widthDelta + this.x;\n\t\t\t\t\t\t\t\ti++;\n\t\t\t\t\t\t\t\tvar y = (parseFloat(points[i])-this.oldY)*heightDelta + this.y;\n\t\t    \t\t\t\t\tupdatedPoints += x + \" \" + y + \" \";\n\t\t\t\t\t\t    }\n\t\t\t\t\t\t\tthis.element.setAttributeNS(null, \"points\", updatedPoints);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t//TODO error\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t//TODO error\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"Path\":\n\t\t\t\t\t//calculate scaling delta\n\t\t\t\t\t//TODO what if oldWidth == 0?\n\t\t\t\t\tvar widthDelta = (this.oldWidth === 0) ? 0 : this.width / this.oldWidth;\n\t\t\t\t\tvar heightDelta = (this.oldHeight === 0) ? 0 : this.height / this.oldHeight;\n\t\n\t\t\t\t\t//use path parser to edit each point of the path\n\t\t\t\t\tthis.editPathHandler.init(this.x, this.y, this.oldX, this.oldY, widthDelta, heightDelta);\n\t\t\t\t\tthis.editPathParser.parsePath(this.element);\n\t\n\t\t\t\t\t//change d attribute of path\n\t\t\t\t\tthis.element.setAttributeNS(null, \"d\", this.editPathHandler.d);\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tthis.oldX = this.x;\n\t\t\tthis.oldY = this.y;\n\t\t\tthis.oldWidth = this.width;\n\t\t\tthis.oldHeight = this.height;\n\t\t}\n\t\t\n\t\t// Remove cached variables\n\t\tdelete this.visible;\n\t\tdelete this.handler;\n\t},\n\t\n\tisPointIncluded: function(pointX, pointY) {\n\n\t\t// Check if there are the right arguments and if the node is visible\n\t\tif(!pointX || !pointY || !this.isVisible()) {\n\t\t\treturn false;\n\t\t}\n\n\t\tswitch(this.type) {\n\t\t\tcase \"Rect\":\n\t\t\t\treturn (pointX >= this.x && pointX <= this.x + this.width &&\n\t\t\t\t\t\tpointY >= this.y && pointY <= this.y+this.height);\n\t\t\t\tbreak;\n\t\t\tcase \"Circle\":\n\t\t\t\t//calculate the radius\n//\t\t\t\tvar r;\n//\t\t\t\tif(this.width/this.oldWidth <= this.height/this.oldHeight) {\n//\t\t\t\t\tr = ((this.width > this.height) ? this.width : this.height)/2.0;\n//\t\t\t\t} else {\n//\t\t\t\t \tr = ((this.width < this.height) ? this.width : this.height)/2.0;\n//\t\t\t\t}\n\t\t\t\treturn ORYX.Core.Math.isPointInEllipse(pointX, pointY, this.x + this.width/2.0, this.y + this.height/2.0, this.radiusX, this.radiusX);\n\t\t\t\tbreak;\n\t\t\tcase \"Ellipse\":\n\t\t\t\treturn ORYX.Core.Math.isPointInEllipse(pointX, pointY, this.x + this.radiusX, this.y + this.radiusY, this.radiusX, this.radiusY);\t\t\t\n\t\t\t\tbreak;\n\t\t\tcase \"Line\":\n\t\t\t\treturn ORYX.Core.Math.isPointInLine(pointX, pointY, this.x, this.y, this.x + this.width, this.y + this.height);\n\t\t\t\tbreak;\n\t\t\tcase \"Polyline\":\n\t\t\t\tvar points = this.element.getAttributeNS(null, \"points\");\n\t\n\t\t\t\tif(points) {\n\t\t\t\t\tpoints = points.replace(/,/g , \" \").split(\" \").without(\"\");\n\t\n\t\t\t\t\tpoints = points.collect(function(n) {\n\t\t\t\t\t\treturn parseFloat(n);\n\t\t\t\t\t});\n\t\t\t\t\t\n\t\t\t\t\treturn ORYX.Core.Math.isPointInPolygone(pointX, pointY, points);\n\t\t\t\t} else {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"Path\":\n\t\t\t\t\n\t\t\t\t// Cache Path handler\n\t\t\t\tif (!this.handler) {\n\t\t\t\t\tvar parser = new PathParser();\n\t\t\t\t\tthis.handler = new ORYX.Core.SVG.PointsPathHandler();\n\t\t\t\t\tparser.setHandler(this.handler);\n\t\t\t\t\tparser.parsePath(this.element);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\treturn ORYX.Core.Math.isPointInPolygone(pointX, pointY, this.handler.points);\n\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\treturn false;\n\t\t}\n\t},\n\n\t/**\n\t * Returns true if the element is visible\n\t * @param {SVGElement} elem\n\t * @return boolean\n\t */\n\tisVisible: function(elem) {\n\t\t\n\t\tif (this.visible !== undefined){\n\t\t\treturn this.visible;\n\t\t}\n\t\t\t\n\t\tif (!elem) {\n\t\t\telem = this.element;\n\t\t}\n\n\t\tvar hasOwnerSVG = false;\n\t\ttry { \n\t\t\thasOwnerSVG = !!elem.ownerSVGElement;\n\t\t} catch(e){}\n\t\t\n\t\t// Is SVG context\n\t\tif ( hasOwnerSVG ) {\n\t\t\t// IF G-Element\n\t\t\tif (ORYX.Editor.checkClassType(elem, SVGGElement)) {\n\t\t\t\tif (elem.className && elem.className.baseVal == \"me\") {\n\t\t\t\t\tthis.visible = true;\n\t\t\t\t\treturn this.visible;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check if fill or stroke is set\n\t\t\tvar fill = elem.getAttributeNS(null, \"fill\");\n\t\t\tvar stroke = elem.getAttributeNS(null, \"stroke\");\n\t\t\tif (fill && fill == \"none\" && stroke && stroke == \"none\") {\n\t\t\t\tthis.visible = false;\n\t\t\t} else {\n\t\t\t\t// Check if displayed\n\t\t\t\tvar attr = elem.getAttributeNS(null, \"display\");\n\t\t\t\tif(!attr)\n\t\t\t\t\tthis.visible = this.isVisible(elem.parentNode);\n\t\t\t\telse if (attr == \"none\") \n\t\t\t\t\tthis.visible = false;\n\t\t\t\telse\n\t\t\t\t\tthis.visible = true;\n\t\t\t}\n\t\t} else {\n\t\t\tthis.visible = true;\n\t\t}\n\t\t\n\t\treturn this.visible;\n\t},\n\n\ttoString: function() { return (this.element) ? \"SVGShape \" + this.element.id : \"SVGShape \" + this.element;}\n });/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespaces\n */\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\nif(!ORYX.Core.SVG) {ORYX.Core.SVG = {};}\n\n/**\n * @classDescription Class for adding text to a shape.\n * \n */\nORYX.Core.SVG.Label = Clazz.extend({\n\t\n\t_characterSets:[\n\t\t\"%W\",\n\t\t\"@\",\n\t\t\"m\",\n\t\t\"wDGMOQ?????#+=<>~^\",\n\t\t\"ABCHKNRSUVXZ??????????&\",\n\t\t\"bdghnopqux???????????ETY1234567890?????_????${}*????`???????????\",\n\t\t\"aeksvyz?????FLP????????????????\",\n\t\t\"c-\",\n\t\t\"rtJ\\\"/()[]:;!|\\\\\",\n\t\t\"fjI., \",\n\t\t\"'\",\n\t\t\"il\"\n\t\t],\n\t_characterSetValues:[15,14,13,11,10,9,8,7,6,5,4,3],\n\n\t/**\n\t * Constructor\n\t * @param options {Object} :\n\t * \ttextElement\n\t * \n\t */\n\tconstruct: function(options) {\n\t\targuments.callee.$.construct.apply(this, arguments);\n\t\t\n\t\tif(!options.textElement) {\n\t\t\tthrow \"Label: No parameter textElement.\" \n\t\t} else if (!ORYX.Editor.checkClassType( options.textElement, SVGTextElement ) ) {\n\t\t\tthrow \"Label: Parameter textElement is not an SVGTextElement.\"\t\n\t\t}\n\t\t\n\t\tthis.invisibleRenderPoint = -5000;\n\t\t\n\t\tthis.node = options.textElement;\n\t\t\n\t\t\n\t\tthis.node.setAttributeNS(null, 'stroke-width', '0pt');\n\t\tthis.node.setAttributeNS(null, 'letter-spacing', '-0.01px');\n\t\t\n\t\tthis.shapeId = options.shapeId;\n\t\t\n\t\tthis.id;\n\t\t\n\t\tthis.fitToElemId;\n\t\t\n\t\tthis.edgePosition;\n\t\t\n\t\tthis.x;\n\t\tthis.y;\n\t\tthis.oldX;\n\t\tthis.oldY;\n\t\t\n\t\tthis.isVisible = true;\n\t\t\n\t\tthis._text;\n\t\tthis._verticalAlign;\n\t\tthis._horizontalAlign;\n\t\tthis._rotate;\n\t\tthis._rotationPoint;\n\t\t\n\t\t//this.anchors = [];\n\t\tthis.anchorLeft;\n\t\tthis.anchorRight;\n\t\tthis.anchorTop;\n\t\tthis.anchorBottom;\n\t\t\n\t\tthis._isChanged = true;\n\n\t\t//if the text element already has an id, don't change it.\n\t\tvar _id = this.node.getAttributeNS(null, 'id');\n\t\tif(_id) {\n\t\t\tthis.id = _id;\n\t\t}\n\t\t\n\t\t//initialization\t\n\t\t\n\t\t//set referenced element the text is fit to\n\t\tthis.fitToElemId = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'fittoelem');\n\t\tif(this.fitToElemId)\n\t\t\tthis.fitToElemId = this.shapeId + this.fitToElemId;\n\t\t\n\t\t//set alignment\t\n\t\tvar alignValues = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'align');\n\t\tif(alignValues) {\n\t\t\talignValues = alignValues.replace(/,/g, \" \");\n\t\t\talignValues = alignValues.split(\" \");\n\t\t\talignValues = alignValues.without(\"\");\n\t\t\t\n\t\t\talignValues.each((function(alignValue) {\n\t\t\t\tswitch (alignValue) {\n\t\t\t\t\tcase 'top':\n\t\t\t\t\tcase 'middle':\n\t\t\t\t\tcase 'bottom':\n\t\t\t\t\t\tif(!this._verticalAlign){this._originVerticalAlign = this._verticalAlign = alignValue;}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'left':\n\t\t\t\t\tcase 'center':\n\t\t\t\t\tcase 'right':\n\t\t\t\t\t\tif(!this._horizontalAlign){this._originHorizontalAlign = this._horizontalAlign = alignValue;}\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}).bind(this));\n\t\t}\n\t\t\n\t\t//set edge position (only in case the label belongs to an edge)\n\t\tthis.edgePosition = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'edgePosition');\n\t\tif(this.edgePosition) {\n\t\t\tthis.originEdgePosition = this.edgePosition = this.edgePosition.toLowerCase();\n\t\t}\n\t\t\n\t\t\n\t\t//get offset top\n\t\tthis.offsetTop = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'offsetTop') || ORYX.CONFIG.OFFSET_EDGE_LABEL_TOP;\n\t\tif(this.offsetTop) {\n\t\t\tthis.offsetTop = parseInt(this.offsetTop);\n\t\t}\n\t\t\n\t\t//get offset top\n\t\tthis.offsetBottom = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'offsetBottom') || ORYX.CONFIG.OFFSET_EDGE_LABEL_BOTTOM;\n\t\tif(this.offsetBottom) {\n\t\t\tthis.offsetBottom = parseInt(this.offsetBottom);\n\t\t}\n\t\t\n\t\t\t\t\n\t\t//set rotation\n\t\tvar rotateValue = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'rotate');\n\t\tif(rotateValue) {\n\t\t\ttry {\n\t\t\t\tthis._rotate = parseFloat(rotateValue);\n\t\t\t} catch (e) {\n\t\t\t\tthis._rotate = 0;\n\t\t\t}\n\t\t} else {\n\t\t\tthis._rotate = 0;\n\t\t}\n\t\t\n\t\t//anchors\n\t\tvar anchorAttr = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, \"anchors\");\n\t\tif(anchorAttr) {\n\t\t\tanchorAttr = anchorAttr.replace(\"/,/g\", \" \");\n\t\t\tvar anchors = anchorAttr.split(\" \").without(\"\");\n\t\t\t\n\t\t\tfor(var i = 0; i < anchors.length; i++) {\n\t\t\t\tswitch(anchors[i].toLowerCase()) {\n\t\t\t\t\tcase \"left\":\n\t\t\t\t\t\tthis.originAnchorLeft = this.anchorLeft = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"right\":\n\t\t\t\t\t\tthis.originAnchorRight = this.anchorRight = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"top\":\n\t\t\t\t\t\tthis.originAnchorTop = this.anchorTop = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"bottom\":\n\t\t\t\t\t\tthis.originAnchorBottom = this.anchorBottom = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\t//if no alignment defined, set default alignment\n\t\tif(!this._verticalAlign) { this._verticalAlign = 'bottom'; }\n\t\tif(!this._horizontalAlign) { this._horizontalAlign = 'left'; }\n\n\t\tvar xValue = this.node.getAttributeNS(null, 'x');\n\t\tif(xValue) {\n\t\t\tthis.oldX = this.x = parseFloat(xValue);\n\t\t} else {\n\t\t\t//TODO error\n\t\t}\n\t\t\n\t\tvar yValue = this.node.getAttributeNS(null, 'y');\n\t\tif(yValue) {\n\t\t\tthis.oldY = this.y = parseFloat(yValue);\n\t\t} else {\n\t\t\t//TODO error\n\t\t}\n\t\t\n\t\t//set initial text\n\t\tthis.text(this.node.textContent);\n\t},\n\t\n\t/**\n\t * Reset the anchor position to the original value\n\t * which was specified in the stencil set\n\t * \n\t */\n\tresetAnchorPosition: function(){\n\t\tthis.anchorLeft = this.originAnchorLeft || false;\n\t\tthis.anchorRight = this.originAnchorRight || false;\n\t\tthis.anchorTop = this.originAnchorTop || false;\n\t\tthis.anchorBottom = this.originAnchorBottom || false;\n\t},\n\t\n\tisOriginAnchorLeft: function(){ return this.originAnchorLeft || false; },\n\tisOriginAnchorRight: function(){ return this.originAnchorRight || false; },\n\tisOriginAnchorTop: function(){ return this.originAnchorTop || false; },\n\tisOriginAnchorBottom: function(){ return this.originAnchorBottom || false; },\n\t\n\t\n\tisAnchorLeft: function(){ return this.anchorLeft || false; },\n\tisAnchorRight: function(){ return this.anchorRight || false; },\n\tisAnchorTop: function(){ return this.anchorTop || false; },\n\tisAnchorBottom: function(){ return this.anchorBottom || false; },\n\t\n\t/**\n\t * Returns the x coordinate\n\t * @return {number}\n\t */\n\tgetX: function(){\n\t\ttry {\n\t\t\tvar x = this.node.x.baseVal.getItem(0).value;\n\t\t\tswitch(this.horizontalAlign()){\n\t\t\t\tcase \"left\": return x;\n\t\t\t\tcase \"center\": return x - (this.getWidth()/2);\n\t\t\t\tcase \"right\": return x - this.getWidth();\n\t\t\t}\n\t\t\treturn this.node.getBBox().x;\n\t\t} catch(e){\n\t\t\treturn this.x;\n\t\t}\n\t},\n\t\t\n\tsetX: function(x){\n\t\tif (this.position)\n\t\t\tthis.position.x = x;\n\t\telse \n\t\t\tthis.setOriginX(x);\n\t},\n\t\n\t\n\t/**\n\t * Returns the y coordinate\n\t * @return {number}\n\t */\n\tgetY: function(){\n\t\ttry {\n\t\t\treturn this.node.getBBox().y;\n\t\t} catch(e){\n\t\t\treturn this.y;\n\t\t}\n\t},\n\t\n\tsetY: function(y){\n\t\tif (this.position)\n\t\t\tthis.position.y = y;\n\t\telse \n\t\t\tthis.setOriginY(y);\n\t},\n\t\n\tsetOriginX: function(x){\n\t\tthis.x = x;\n\t},\n\t\n\tsetOriginY: function(y){\n\t\tthis.y = y;\n\t},\n\n\t\n\t/**\n\t * Returns the width of the label\n\t * @return {number}\n\t */\n\tgetWidth: function(){\n\t\ttry {\n\t\t\ttry {\n\t\t\t\tvar width, cn = this.node.childNodes;\n\t\t\t\tif (cn.length == 0) {\n\t\t\t\t\twidth = this.node.getBBox().width;\n\t\t\t\t} else {\n\t\t\t\t\tfor (var i = 0, size = cn.length; i < size; ++i) {\n\t\t\t\t\t\tvar w = cn[i].getComputedTextLength();\n\t\t\t\t\t\tif (\"undefined\" == typeof width || width < w) {\n\t\t\t\t\t\t\twidth = w;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn width+(width%2==0?0:1);\n\t\t\t} catch (ee) {\n\t\t\t\treturn this.node.getBBox().width;\n\t\t\t}\n\t\t} catch(e){\n\t\t\treturn 0;\n\t\t}\n\t},\n\t\n\tgetOriginUpperLeft: function(){\n\t\tvar x = this.x, y = this.y;\n\t\tswitch (this._horizontalAlign){\n\t\t\tcase 'center' :\n\t\t\t\tx -= this.getWidth()/2;\n\t\t\t\tbreak;\n\t\t\tcase 'right' :\n\t\t\t\tx -= this.getWidth();\n\t\t\t\tbreak;\n\t\t}\n\t\tswitch (this._verticalAlign){\n\t\t\tcase 'middle' :\n\t\t\t\ty -= this.getHeight()/2;\n\t\t\t\tbreak;\n\t\t\tcase 'bottom' :\n\t\t\t\ty -= this.getHeight();\n\t\t\t\tbreak;\n\t\t}\n\t\treturn {x:x, y:y};\n\t},\n\t\n\t/**\n\t * Returns the height of the label\n\t * @return {number}\n\t */\n\tgetHeight: function(){\n\t\ttry {\n\t\t\treturn this.node.getBBox().height;\n\t\t} catch(e){\n\t\t\treturn 0;\n\t\t}\n\t},\n\t\n\t/**\n\t * Returns the relative center position of the label \n\t * to its parent shape.\n\t * @return {Object}\n\t */\n\tgetCenter: function(){\n\t\tvar up = {x: this.getX(), y: this.getY()};\n\t\tup.x += this.getWidth()/2;\n\t\tup.y += this.getHeight()/2;\n\t\treturn up;\n\t},\n\t\n\t/**\n\t * Sets the position of a label relative to the parent.\n\t * @param {Object} position\n\t */\n\tsetPosition: function(position){\n\t\tif (!position || position.x === undefined || position.y === undefined) {\n\t\t\tdelete this.position;\n\t\t} else {\n\t\t\tthis.position = position;\n\t\t}\n\t\t\n\t\tif (this.position){\n\t\t\tdelete this._referencePoint;\n\t\t\tdelete this.edgePosition;\n\t\t}\n\t\t\n\t\tthis._isChanged = true;\n\t\tthis.update();\n\t},\n\t\n\t/**\n\t * Return the position\n\t */\n\tgetPosition: function(){\n\t\treturn this.position;\n\t},\n\t\n\tsetReferencePoint: function(ref){\n\t\tif (ref) {\n\t\t\tthis._referencePoint = ref;\n\t\t} else {\n\t\t\tdelete this._referencePoint;\n\t\t}\n\t\tif (this._referencePoint){\n\t\t\tdelete this.position;\n\t\t}\n\t},\n\t\n\tgetReferencePoint: function(){\n\t\treturn this._referencePoint || undefined;\n\t},\n\t\n\tchanged: function() {\n\t\tthis._isChanged = true;\n\t},\n\t\n\t/**\n\t * Register a callback which will be called if the label\n\t * was rendered.\n\t * @param {Object} fn\n\t */\n\tregisterOnChange: function(fn){\n\t\tif (!this.changeCallbacks){\n\t\t\tthis.changeCallbacks = [];\n\t\t}\n\t\tif (fn instanceof Function && !this.changeCallbacks.include(fn)){\n\t\t\tthis.changeCallbacks.push(fn);\n\t\t}\n\t},\n\t\n\t/**\n\t * Unregister the callback for changes.\n\t * @param {Object} fn\n\t */\n\tunregisterOnChange: function(fn){\n\t\tif (this.changeCallbacks && fn instanceof Function && this.changeCallbacks.include(fn)){\n\t\t\tthis.changeCallbacks = this.changeCallbacks.without(fn);\n\t\t}\n\t},\n\t\n\t/**\n\t * Returns TRUE if the labe is currently in\n\t * the update mechanism.\n\t * @return {Boolean}\n\t */\n\tisUpdating: function(){\n\t\treturn !!this._isUpdating;\t\n\t},\n\t\n\t\n\tgetOriginEdgePosition: function(){\n\t\treturn this.originEdgePosition;\t\n\t},\n\t\n\t/**\n\t * Returns the edgeposition.\n\t * \n\t * @return {String} \"starttop\", \"startmiddle\", \"startbottom\", \n\t * \"midtop\", \"midbottom\", \"endtop\", \"endbottom\" or null\n\t */\n\tgetEdgePosition: function(){\n\t\treturn this.edgePosition || null;\t\n\t},\n\t\n\t/**\n\t * Set the edge position, must be one of the valid\n\t * edge positions (see getEdgePosition).\n\t * Removes the reference point and the absolute position as well.\n\t * \n\t * @param {Object} position\n\t */\n\tsetEdgePosition: function(position){\n\t\tif ([\"starttop\", \"startmiddle\", \"startbottom\", \n\t\t\t\"midtop\", \"midbottom\", \"endtop\", \"endbottom\"].include(position)){\n\t\t\tthis.edgePosition = position;\n\t\t\tdelete this.position;\n\t\t\tdelete this._referencePoint;\n\t\t} else {\n\t\t\tdelete this.edgePosition;\n\t\t}\n\t},\n\t\n\t/**\n\t * Update the SVG text element.\n\t */\n\tupdate: function(force) {\n\t\t\n\t\tvar x = this.x, y = this.y;\n\t\tif (this.position){\n\t\t\tx = this.position.x;\n\t\t\ty = this.position.y;\n\t\t}\n\t\tx = Math.floor(x); y = Math.floor(y);\n\t\t\n\t\tif(this._isChanged || x !== this.oldX || y !== this.oldY || force === true) {\n\t\t\tif (this.isVisible) {\n\t\t\t\tthis._isChanged = false;\n\t\t\t\tthis._isUpdating = true;\n\t\t\t\t\n\t\t\t\tthis.node.setAttributeNS(null, 'x', x);\n\t\t\t\tthis.node.setAttributeNS(null, 'y', y);\n\t\t\t\tthis.node.removeAttributeNS(null, \"fill-opacity\");\n\t\t\t\t\n\t\t\t\t//this.node.setAttributeNS(null, 'font-size', this._fontSize);\n\t\t\t\t//this.node.setAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'align', this._horizontalAlign + \" \" + this._verticalAlign);\n\t\t\t\t\n\t\t\t\tthis.oldX = x;\n\t\t\t\tthis.oldY = y;\n\t\t\t\t\n\t\t\t\t//set rotation\n\t\t\t\tif (!this.position && !this.getReferencePoint()) {\n\t\t\t\t\tif (this._rotate !== undefined) {\n\t\t\t\t\t\tif (this._rotationPoint) \n\t\t\t\t\t\t\tthis.node.setAttributeNS(null, 'transform', 'rotate(' + this._rotate + ' ' + Math.floor(this._rotationPoint.x) + ' ' + Math.floor(this._rotationPoint.y) + ')');\n\t\t\t\t\t\telse \n\t\t\t\t\t\t\tthis.node.setAttributeNS(null, 'transform', 'rotate(' + this._rotate + ' ' + Math.floor(x) + ' ' + Math.floor(y) + ')');\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tthis.node.removeAttributeNS(null, 'transform');\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tvar textLines = this._text.split(\"\\n\");\n\t\t\t\twhile (textLines.last() == \"\") \n\t\t\t\t\ttextLines.pop();\n\t\t\t\t\n\t\t\t\t\n\t\t\t\tif (this.node.ownerDocument) {\n\t\t\t\t\t// Only reset the tspans if the text \n\t\t\t\t\t// has changed or has to be wrapped\n\t\t\t\t\tif (this.fitToElemId || this._textHasChanged){\n\t\t\t\t\t\tthis.node.textContent = \"\"; // Remove content\n\t\t\t\t\t\ttextLines.each((function(textLine, index){\n\t\t\t\t\t\t\tvar tspan = this.node.ownerDocument.createElementNS(ORYX.CONFIG.NAMESPACE_SVG, 'tspan');\n\t\t\t\t\t\t\ttspan.textContent = textLine.trim();\n\t\t\t\t\t\t\tif (this.fitToElemId) {\n\t\t\t\t\t\t\t\ttspan.setAttributeNS(null, 'x', this.invisibleRenderPoint);\n\t\t\t\t\t\t\t\ttspan.setAttributeNS(null, 'y', this.invisibleRenderPoint);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t * Chrome's getBBox() method fails, if a text node contains an empty tspan element.\n\t\t\t\t\t\t\t * So, we add a whitespace to such a tspan element.\n\t\t\t\t\t\t\t */\n\t\t\t\t\t\t\tif(tspan.textContent === \"\") {\n\t\t\t\t\t\t\t\ttspan.textContent = \" \";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t//append tspan to text node\n\t\t\t\t\t\t\tthis.node.appendChild(tspan);\n\t\t\t\t\t\t}).bind(this));\n\t\t\t\t\t\tdelete this._textHasChanged;\n\t\t\t\t\t\tdelete this.indices;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t//Work around for Mozilla bug 293581\n\t\t\t\t\tif (this.isVisible && this.fitToElemId) {\n\t\t\t\t\t\tthis.node.setAttributeNS(null, 'visibility', 'hidden');\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif (this.fitToElemId) {\n\t\t\t\t\t\twindow.setTimeout(this._checkFittingToReferencedElem.bind(this), 0);\n\t\t\t\t\t\t//this._checkFittingToReferencedElem();\n\t\t\t\t\t} else {\n\t\t\t\t\t\twindow.setTimeout(this._positionText.bind(this), 0);\n\t\t\t\t\t\t//this._positionText();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.node.textContent = \"\";\n\t\t\t\t//this.node.setAttributeNS(null, \"fill-opacity\", \"0.2\");\n\t\t\t}\n\t\t}\n\t},\n\t\n\t_checkFittingToReferencedElem: function() {\n\t\ttry {\n\t\t\tvar tspans = $A(this.node.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'tspan'));\n\t\t\t\n\t\t\t//only do this in firefox 3. all other browsers do not support word wrapping!!!!!\n\t\t\t//if (/Firefox[\\/\\s](\\d+\\.\\d+)/.test(navigator.userAgent) && new Number(RegExp.$1)>=3) {\n\t\t\t\tvar newtspans = [];\n\t\t\t\t\n\t\t\t\tvar refNode = this.node.ownerDocument.getElementById(this.fitToElemId);\n\t\t\t\t\n\t\t\t\tif (refNode) {\n\t\t\t\t\tvar refbb = refNode.getBBox();\n\t\t\t\t\t\n\t\t\t\t\tvar fontSize = this.getFontSize();\n\t\t\t\t\t\n\t\t\t\t\tfor (var j = 0; j < tspans.length; j++) {\n\t\t\t\t\t\tvar tspan = tspans[j];\n\t\t\t\t\t\t\n\t\t\t\t\t\tvar textLength = this._getRenderedTextLength(tspan, undefined, undefined, fontSize);\n\t\t\t\t\t\t\n\t\t\t\t\t\tvar refBoxLength = (this._rotate != 0 \n\t\t\t\t\t\t\t\t&& this._rotate % 180 != 0 \n\t\t\t\t\t\t\t\t&& this._rotate % 90 == 0 ? \n\t\t\t\t\t\t\t\t\t\trefbb.height : refbb.width);\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (textLength > refBoxLength) {\n\t\t\t\t\t\t\n\t\t\t\t\t\t\tvar startIndex = 0;\n\t\t\t\t\t\t\tvar lastSeperatorIndex = 0;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tvar numOfChars = this.getTrimmedTextLength(tspan.textContent);\n\t\t\t\t\t\t\tfor (var i = 0; i < numOfChars; i++) {\n\t\t\t\t\t\t\t\tvar sslength = this._getRenderedTextLength(tspan, startIndex, i-startIndex, fontSize);\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tif (sslength > refBoxLength - 2) {\n\t\t\t\t\t\t\t\t\tvar newtspan = this.node.ownerDocument.createElementNS(ORYX.CONFIG.NAMESPACE_SVG, 'tspan');\n\t\t\t\t\t\t\t\t\tif (lastSeperatorIndex <= startIndex) {\n\t\t\t\t\t\t\t\t\t\tlastSeperatorIndex = (i == 0) ? i : i-1;\n\t\t\t\t\t\t\t\t\t\tnewtspan.textContent = tspan.textContent.slice(startIndex, lastSeperatorIndex).trim();\n\t\t\t\t\t\t\t\t\t\t//lastSeperatorIndex = i;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\t\tnewtspan.textContent = tspan.textContent.slice(startIndex, ++lastSeperatorIndex).trim();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tnewtspan.setAttributeNS(null, 'x', this.invisibleRenderPoint);\n\t\t\t\t\t\t\t\t\tnewtspan.setAttributeNS(null, 'y', this.invisibleRenderPoint);\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t//insert tspan to text node\n\t\t\t\t\t\t\t\t\t//this.node.insertBefore(newtspan, tspan);\n\t\t\t\t\t\t\t\t\tnewtspans.push(newtspan);\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tstartIndex = lastSeperatorIndex;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\tvar curChar = tspan.textContent.charAt(i);\n\t\t\t\t\t\t\t\t\tif (curChar == ' ' ||\n\t\t\t\t\t\t\t\t\tcurChar == '-' ||\n\t\t\t\t\t\t\t\t\tcurChar == \".\" ||\n\t\t\t\t\t\t\t\t\tcurChar == \",\" ||\n\t\t\t\t\t\t\t\t\tcurChar == \";\" ||\n\t\t\t\t\t\t\t\t\tcurChar == \":\") {\n\t\t\t\t\t\t\t\t\t\tlastSeperatorIndex = i;\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\t\n\t\t\t\t\t\t\ttspan.textContent = tspan.textContent.slice(startIndex).trim();\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tnewtspans.push(tspan);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\twhile (this.node.hasChildNodes()) \n\t\t\t\t\t\tthis.node.removeChild(this.node.childNodes[0]);\n\t\t\t\t\t\n\t\t\t\t\twhile (newtspans.length > 0) {\n\t\t\t\t\t\tthis.node.appendChild(newtspans.shift());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t//}\n\t\t} catch (e) {\n\t\t\tORYX.Log.fatal(\"Error \" + e);\n\t\t}\n\t\twindow.setTimeout(this._positionText.bind(this), 0);\n\t\t//this._positionText();\n\t},\n\t\n\t/**\n\t * This is a work around method for Mozilla bug 293581.\n\t * Before the method getComputedTextLength works, the text has to be rendered.\n\t */\n\t_positionText: function() {\n\t\ttry {\n\t\t\t\n\t\t\tvar tspans = this.node.childNodes;\n\t\t\t\n\t\t\tvar fontSize = this.getFontSize(this.node); \n\t\t\t\n\t\t\tvar invalidTSpans = [];\n\t\t\t\n\t\t\tvar x = this.x, y = this.y;\n\t\t\tif (this.position){\n\t\t\t\tx = this.position.x;\n\t\t\t\ty = this.position.y;\n\t\t\t}\n\t\t\tx = Math.floor(x); y = Math.floor(y);\n\t\t\t\n\t\t\tvar i = 0, indic = []; // Cache indices if the _positionText is called again, before update is called \n\t\t\tvar is =(this.indices || $R(0,tspans.length-1).toArray());\n\t\t\tvar length = is.length;\n\t\t\tis.each((function(index){\n\t\t\t\tif (\"undefined\" == typeof index){\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tvar tspan = tspans[i++];\n\t\t\t\t\n\t\t\t\tif(tspan.textContent.trim() === \"\") {\n\t\t\t\t\tinvalidTSpans.push(tspan);\n\t\t\t\t} else {\n\t\t\t\t\t//set vertical position\n\t\t\t\t\tvar dy = 0;\n\t\t\t\t\tswitch (this._verticalAlign) {\n\t\t\t\t\t\tcase 'bottom':\n\t\t\t\t\t\t\tdy = -(length - index - 1) * (fontSize);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'middle':\n\t\t\t\t\t\t\tdy = -(length / 2.0 - index - 1) * (fontSize);\n\t\t\t\t\t\t\tdy -= ORYX.CONFIG.LABEL_LINE_DISTANCE / 2;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'top':\n\t\t\t\t\t\t\tdy = index * (fontSize);\n\t\t\t\t\t\t\tdy += fontSize;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\ttspan.setAttributeNS(null, 'dy', Math.floor(dy));\n\t\t\t\t\t\n\t\t\t\t\ttspan.setAttributeNS(null, 'x', x);\n\t\t\t\t\ttspan.setAttributeNS(null, 'y', y);\n\t\t\t\t\tindic.push(index);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t}).bind(this));\n\t\t\t\n\t\t\tindic.length = tspans.length;\n\t\t\tthis.indices = this.indices || indic;\n\t\t\t\n\t\t\tinvalidTSpans.each(function(tspan) {\n\t\t\t\tthis.node.removeChild(tspan)\n\t\t\t}.bind(this));\n\t\t\t\n\t\t\t//set horizontal alignment\n\t\t\tswitch (this._horizontalAlign) {\n\t\t\t\tcase 'left':\n\t\t\t\t\tthis.node.setAttributeNS(null, 'text-anchor', 'start');\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'center':\n\t\t\t\t\tthis.node.setAttributeNS(null, 'text-anchor', 'middle');\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'right':\n\t\t\t\t\tthis.node.setAttributeNS(null, 'text-anchor', 'end');\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\t\t} catch(e) {\n\t\t\t//console.log(e);\n\t\t\tthis._isChanged = true;\n\t\t}\n\t\t\n\t\t\n\t\tif(this.isVisible) {\n\t\t\tthis.node.removeAttributeNS(null, 'visibility');\n\t\t}\t\t\n\t\t\n\t\t\n\t\t// Finished\n\t\tdelete this._isUpdating;\n\t\t\n\t\t// Raise change event\n\t\t(this.changeCallbacks||[]).each(function(fn){\n\t\t\tfn.apply(fn);\n\t\t})\n\t\t\t\t\n\t},\n\t\n\t/**\n\t * Returns the text length of the text content of an SVG tspan element.\n\t * For all browsers but Firefox 3 the values are estimated.\n\t * @param {TSpanSVGElement} tspan\n\t * @param {int} startIndex Optional, for sub strings\n\t * @param {int} endIndex Optional, for sub strings\n\t */\n\t_getRenderedTextLength: function(tspan, startIndex, endIndex, fontSize) {\n\t\t//if (/Firefox[\\/\\s](\\d+\\.\\d+)/.test(navigator.userAgent) && new Number(RegExp.$1) >= 3) {\n\t\t\tif(startIndex === undefined) {\n//test string: abcdefghijklmnopqrstuvwxyz????????????????,.-#+ 1234567890?????ABCDEFGHIJKLMNOPQRSTUVWXYZ;:_'*???????????????!\"????$%&/()=?[]{}|<>'~????`\\^?????????@?????????????????\n//\t\t\t\tfor(var i = 0; i < tspan.textContent.length; i++) {\n//\t\t\t\t\tconsole.log(tspan.textContent.charAt(i), tspan.getSubStringLength(i,1), this._estimateCharacterWidth(tspan.textContent.charAt(i))*(fontSize/14.0));\n//\t\t\t\t}\n\t\t\t\treturn tspan.getComputedTextLength();\n\t\t\t} else {\n\t\t\t\treturn tspan.getSubStringLength(startIndex, endIndex);\n\t\t\t}\n\t\t/*} else {\n\t\t\tif(startIndex === undefined) {\n\t\t\t\treturn this._estimateTextWidth(tspan.textContent, fontSize);\n\t\t\t} else {\n\t\t\t\treturn this._estimateTextWidth(tspan.textContent.substr(startIndex, endIndex).trim(), fontSize);\n\t\t\t}\n\t\t}*/\n\t},\n\t\n\t/**\n\t * Estimates the text width for a string.\n\t * Used for word wrapping in all browser but FF3.\n\t * @param {Object} text\n\t */\n\t_estimateTextWidth: function(text, fontSize) {\n\t\tvar sum = 0.0;\n\t\tfor(var i = 0; i < text.length; i++) {\n\t\t\tsum += this._estimateCharacterWidth(text.charAt(i));\n\t\t}\n\t\t\n\t\treturn sum*(fontSize/14.0);\n\t},\n\t\n\t/**\n\t * Estimates the width of a single character for font size 14.\n\t * Used for word wrapping in all browser but FF3.\n\t * @param {Object} character\n\t */\n\t_estimateCharacterWidth: function(character) {\n\t\tfor(var i = 0; i < this._characterSets.length; i++) {\n \t\t\tif(this._characterSets[i].indexOf(character) >= 0) {\n\t\t\t\treturn this._characterSetValues[i];\n\t\t\t}\n \t\t}\t\n\t\treturn 9;\n \t},\n\t\n\tgetReferencedElementWidth: function() {\n\t\tvar refNode = this.node.ownerDocument.getElementById(this.fitToElemId);\n\t\t\n\t\tif(refNode) {\n\t\t\tvar refbb = refNode.getBBox();\n\t\t\t\t\n\t\t\tif(refbb) {\n\t\t\t\treturn (this._rotate != 0 \n\t\t\t\t\t\t&& this._rotate % 180 != 0 \n\t\t\t\t\t\t&& this._rotate % 90 == 0 ? \n\t\t\t\t\t\t\t\trefbb.height : refbb.width);\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn undefined;\n\t},\n\t\n\t/**\n\t * If no parameter is provided, this method returns the current text.\n\t * @param text {String} Optional. Replaces the old text with this one.\n\t */\n\ttext: function() {\n\t\tswitch (arguments.length) {\n\t\t\tcase 0:\n\t\t\t\treturn this._text\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase 1:\n\t\t\t\tvar oldText = this._text;\n\t\t\t\tif(arguments[0]) {\n\t\t\t\t\t// Filter out multiple spaces to fix issue in chrome for line-wrapping\n\t\t\t\t\tthis._text = arguments[0].toString();\n\t\t\t\t\tif(this._text != null && this._text != undefined) {\n\t\t\t\t\t\tthis._text = this._text.replace(/ {2,}/g,' ');\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tthis._text = \"\";\n\t\t\t\t}\n\t\t\t\tif(oldText !== this._text) {\n\t\t\t\t\tthis._isChanged = true;\n\t\t\t\t\tthis._textHasChanged = true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t\t\n\t\t\tdefault: \n\t\t\t\t//TODO error\n\t\t\t\tbreak;\n\t\t}\n\t},\n\t\n\tgetOriginVerticalAlign: function(){\n\t\treturn this._originVerticalAlign;\n\t},\n\t\n\tverticalAlign: function() {\n\t\tswitch(arguments.length) {\n\t\t\tcase 0:\n\t\t\t\treturn this._verticalAlign;\n\t\t\tcase 1:\n\t\t\t\tif(['top', 'middle', 'bottom'].member(arguments[0])) {\n\t\t\t\t\tvar oldValue = this._verticalAlign;\n\t\t\t\t\tthis._verticalAlign = arguments[0];\n\t\t\t\t\tif(this._verticalAlign !== oldValue) {\n\t\t\t\t\t\tthis._isChanged = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t\t\n\t\t\tdefault:\n\t\t\t\t//TODO error\n\t\t\t\tbreak;\n\t\t}\n\t},\n\t\n\tgetOriginHorizontalAlign: function(){\n\t\treturn this._originHorizontalAlign;\n\t},\n\t\n\thorizontalAlign: function() {\n\t\tswitch(arguments.length) {\n\t\t\tcase 0:\n\t\t\t\treturn this._horizontalAlign;\n\t\t\tcase 1:\n\t\t\t\tif(['left', 'center', 'right'].member(arguments[0])) {\n\t\t\t\t\tvar oldValue = this._horizontalAlign;\n\t\t\t\t\tthis._horizontalAlign = arguments[0];\n\t\t\t\t\tif(this._horizontalAlign !== oldValue) {\n\t\t\t\t\t\tthis._isChanged = true;\n\t\t\t\t\t}\t\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t\t\n\t\t\tdefault:\n\t\t\t\t//TODO error\n\t\t\t\tbreak;\n\t\t}\n\t},\n\t\n\trotate: function() {\n\t\tswitch(arguments.length) {\n\t\t\tcase 0:\n\t\t\t\treturn this._rotate;\n\t\t\tcase 1:\n\t\t\t\tif (this._rotate != arguments[0]) {\n\t\t\t\t\tthis._rotate = arguments[0];\n\t\t\t\t\tthis._rotationPoint = undefined;\n\t\t\t\t\tthis._isChanged = true;\n\t\t\t\t}\n\t\t\tcase 2:\n\t\t\t\tif(this._rotate != arguments[0] ||\n\t\t\t\t   !this._rotationPoint ||\n\t\t\t\t   this._rotationPoint.x != arguments[1].x ||\n\t\t\t\t   this._rotationPoint.y != arguments[1].y) {\n\t\t\t\t\tthis._rotate = arguments[0];\n\t\t\t\t\tthis._rotationPoint = arguments[1];\n\t\t\t\t\tthis._isChanged = true;\n\t\t\t\t}\n\t\t\t\t\n\t\t}\n\t},\n\t\n\thide: function() {\n\t\tif(this.isVisible) {\n\t\t\tthis.isVisible = false;\n\t\t\tthis._isChanged = true;\n\t\t}\n\t},\n\t\n\tshow: function() {\n\t\tif(!this.isVisible) {\n\t\t\tthis.isVisible = true;\n\t\t\tthis._isChanged = true;\n\n\t\t\t// Since text is removed from the tspan when \"hidden\", mark\n\t\t\t// the text as changed to get it redrawn\n\t\t\tthis._textHasChanged = true;\n\t\t}\n\t},\n\t\n\t/**\n\t * iterates parent nodes till it finds a SVG font-size\n\t * attribute.\n\t * @param {SVGElement} node\n\t */\n\tgetInheritedFontSize: function(node) {\n\t\tif(!node || !node.getAttributeNS)\n\t\t\treturn;\n\t\t\t\n\t\tvar attr = node.getAttributeNS(null, \"font-size\");\n\t\tif(attr) {\n\t\t\treturn parseFloat(attr);\n\t\t} else if(!ORYX.Editor.checkClassType(node, SVGSVGElement)) {\n\t\t\treturn this.getInheritedFontSize(node.parentNode);\n\t\t}\n\t},\n\t\n\tgetFontSize: function(node) {\n\t\tvar tspans = this.node.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'tspan');\n\t\t\t\n\t\t//trying to get an inherited font-size attribute\n\t\t//NO CSS CONSIDERED!\n\t\tvar fontSize = this.getInheritedFontSize(this.node); \n\t\t\n\t\tif (!fontSize) {\n\t\t\t//because this only works in firefox 3, all other browser use the default line height\n\t\t\tif (tspans[0] && /Firefox[\\/\\s](\\d+\\.\\d+)/.test(navigator.userAgent) && new Number(RegExp.$1) >= 3) {\n\t\t\t\tfontSize = tspans[0].getExtentOfChar(0).height;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tfontSize = ORYX.CONFIG.LABEL_DEFAULT_LINE_HEIGHT;\n\t\t\t}\n\t\t\t\n\t\t\t//handling of unsupported method in webkit\n\t\t\tif (fontSize <= 0) {\n\t\t\t\tfontSize = ORYX.CONFIG.LABEL_DEFAULT_LINE_HEIGHT;\n\t\t\t}\n\t\t}\n\t\t\n\t\tif(fontSize)\n\t\t\tthis.node.setAttribute(\"oryx:fontSize\", fontSize);\n\t\t\n\t\treturn fontSize;\n\t},\n\t\n\t/**\n\t * Get trimmed text length for use with\n\t * getExtentOfChar and getSubStringLength.\n\t * @param {String} text\n\t */\n\tgetTrimmedTextLength: function(text) {\n\t\ttext = text.strip().gsub('  ', ' ');\n\t\t\n\t\tvar oldLength;\n\t\tdo {\n\t\t\toldLength = text.length;\n\t\t\ttext = text.gsub('  ', ' ');\n\t\t} while (oldLength > text.length);\n\n\t\treturn text.length;\n\t},\n\t\n\t/**\n\t * Returns the offset from\n\t * edge to the label which is \n\t * positioned under the edge\n\t * @return {int}\n\t */\n\tgetOffsetBottom: function(){\n\t\treturn this.offsetBottom;\n\t},\n\t\n\t\t\n\t/**\n\t * Returns the offset from\n\t * edge to the label which is \n\t * positioned over the edge\n\t * @return {int}\n\t */\n\tgetOffsetTop: function(){\n\t\treturn this.offsetTop;\n\t},\n\t\n\t/**\n\t * \n\t * @param {Object} obj\n\t */\n\tdeserialize: function(obj, shape){\n\t\tif (obj && \"undefined\" != typeof obj.x && \"undefined\" != typeof obj.y){\t\t\t\n\t\t\tthis.setPosition({x:obj.x, y:obj.y});\n\t\t\t\n\t\t\tif (\"undefined\" != typeof obj.distance){\n\t\t\t\tvar from = shape.dockers[obj.from];\n\t\t\t\tvar to = shape.dockers[obj.to];\n\t\t\t\tif (from && to){\n\t\t\t\t\tthis.setReferencePoint({\n\t\t\t\t\t\tdirty : true,\n\t\t\t\t\t\tdistance : obj.distance,\n\t\t\t\t\t\tintersection : {x: obj.x, y: obj.y},\n\t\t\t\t\t\torientation : obj.orientation,\n\t\t\t\t\t\tsegment: {\n\t\t\t\t\t\t\tfrom: from,\n\t\t\t\t\t\t\tfromIndex: obj.from,\n\t\t\t\t\t\t\tfromPosition: from.bounds.center(),\n\t\t\t\t\t\t\tto: to,\n\t\t\t\t\t\t\ttoIndex: obj.to,\n\t\t\t\t\t\t\ttoPosition: to.bounds.center()\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\n\t\t\tif (obj.left) this.anchorLeft = true;\n\t\t\tif (obj.right) this.anchorRight = true;\n\t\t\tif (obj.top) this.anchorTop = true;\n\t\t\tif (obj.bottom) this.anchorBottom = true;\n\t\t\tif (obj.valign) this.verticalAlign(obj.valign);\n\t\t\tif (obj.align) this.horizontalAlign(obj.align);\n\t\t\t\n\t\t} else if (obj && \"undefined\" != typeof obj.edge){\n\t\t\tthis.setEdgePosition(obj.edge);\n\t\t}\n\t},\n\n\t/**\n\t * \n\t * @return {Object}\n\t */\n\tserialize: function(){\n\t\t\n\t\t// On edge position\n\t\tif (this.getEdgePosition()){\n\t\t\tif (this.getOriginEdgePosition() !== this.getEdgePosition()){\n\t\t\t\treturn {edge: this.getEdgePosition()};\n\t\t\t} else {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\t\t\n\t\t// On self defined position\n\t\tif (this.position){\n\t\t\tvar pos = {x: this.position.x, y: this.position.y};\n\t\t\tif (this.isAnchorLeft() && this.isAnchorLeft() !== this.isOriginAnchorLeft()){\n\t\t\t\tpos.left = true;\n\t\t\t}\n\t\t\tif (this.isAnchorRight() && this.isAnchorRight() !== this.isOriginAnchorRight()){\n\t\t\t\tpos.right = true;\n\t\t\t}\n\t\t\tif (this.isAnchorTop() && this.isAnchorTop() !== this.isOriginAnchorTop()){\n\t\t\t\tpos.top = true;\n\t\t\t}\n\t\t\tif (this.isAnchorBottom() && this.isAnchorBottom() !== this.isOriginAnchorBottom()){\n\t\t\t\tpos.bottom = true;\n\t\t\t}\n\t\t\t\n\t\t\tif (this.getOriginVerticalAlign() !== this.verticalAlign()){\n\t\t\t\tpos.valign = this.verticalAlign();\n\t\t\t}\n\t\t\tif (this.getOriginHorizontalAlign() !== this.horizontalAlign()){\n\t\t\t\tpos.align = this.horizontalAlign();\n\t\t\t}\n\t\t\t\n\t\t\treturn pos;\n\t\t}\n\t\t\n\t\t// On reference point which is interesting for edges\n\t\tif (this.getReferencePoint()){\n\t\t\tvar ref = this.getReferencePoint();\n\t\t\treturn {\n\t\t\t\tdistance : ref.distance,\n\t\t\t\tx : ref.intersection.x,\n\t\t\t\ty : ref.intersection.y,\n\t\t\t\tfrom : ref.segment.fromIndex,\n\t\t\t\tto : ref.segment.toIndex,\n\t\t\t\torientation : ref.orientation,\n\t\t\t\tvalign : this.verticalAlign(),\n\t\t\t\talign : this.horizontalAlign()\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t},\n\t\n\ttoString: function() { return \"Label \" + this.id }\n });/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespaces\n */\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\nif(!ORYX.Core.Math) {ORYX.Core.Math = {};}\n\t\n/**\n * Calculate the middle point between two given points\n * @param {x:double, y:double} point1\n * @param {x:double, y:double} point2\n * @return the middle point\n */\nORYX.Core.Math.midPoint = function(point1, point2) {\n\treturn \t{\n\t\t\t\tx: (point1.x + point2.x) / 2.0,\n\t\t\t\ty: (point1.y + point2.y) / 2.0\n\t\t\t}\n}\n\t\t\t\n/**\n * Returns a TRUE if the point is over a line (defined by\n * point1 and point 2). In Addition a threshold can be set,\n * which defines the weight of those line.\n * \n * @param {int} pointX - Point X\n * @param {int} pointY - Point Y\n * @param {int} lPoint1X - Line first Point X\n * @param {int} lPoint1Y - Line first Point Y\n * @param {int} lPoint2X - Line second Point X\n * @param {int} lPoint2Y - Line second Point y\n * @param {int} offset {optional} - maximal distance to line\n * @class ORYX.Core.Math.prototype\n */\nORYX.Core.Math.isPointInLine = function (pointX, pointY, lPoint1X, lPoint1Y, lPoint2X, lPoint2Y, offset) {\n\n\toffset = offset ? Math.abs(offset) : 1;\n\t\n\t// Check if the edge is vertical\n\tif(Math.abs(lPoint1X-lPoint2X)<=offset && Math.abs(pointX-lPoint1X)<=offset && pointY-Math.max(lPoint1Y, lPoint2Y)<=offset && Math.min(lPoint1Y, lPoint2Y)-pointY<=offset) {\n\t\treturn true\n\t}\n\n\t// Check if the edge is horizontal\n\tif(Math.abs(lPoint1Y-lPoint2Y)<=offset && Math.abs(pointY-lPoint1Y)<=offset && pointX-Math.max(lPoint1X, lPoint2X)<=offset && Math.min(lPoint1X, lPoint2X)-pointX<=offset) {\n\t\treturn true\n\t}\n\n\tif(pointX > Math.max(lPoint1X, lPoint2X) || pointX < Math.min(lPoint1X, lPoint2X)) {\n\t\treturn false\n\t}\n\n\tif(pointY > Math.max(lPoint1Y, lPoint2Y) || pointY < Math.min(lPoint1Y, lPoint2Y)) {\n\t\treturn false\n\t}\n\t\t\t\n\tvar s = (lPoint1Y - lPoint2Y) / (lPoint1X - lPoint2X);\n\t\n\treturn \tMath.abs(pointY - ((s * pointX) + lPoint1Y - s * lPoint1X)) < offset\n}\n\n/**\n * Get a boolean if the point is in the polygone\n * \n */\nORYX.Core.Math.isPointInEllipse = function (pointX, pointY, cx, cy, rx, ry) {\n\n\tif(cx === undefined || cy === undefined || rx === undefined || ry === undefined) {\n\t\tthrow \"ORYX.Core.Math.isPointInEllipse needs a ellipse with these properties: x, y, radiusX, radiusY\"\n\t} \n\t\n    var tx = (pointX - cx) / rx;\n    var ty = (pointY - cy) / ry;\n\t\n    return tx * tx + ty * ty < 1.0;\n}\n\t\n/**\n * Get a boolean if the point is in the polygone\n * @param {int} pointX\n * @param {int} pointY\n * @param {[int]} Cornerpoints of the Polygone (x,y,x,y,...)\n */\nORYX.Core.Math.isPointInPolygone = function(pointX, pointY, polygone){\n\n\tif (arguments.length < 3) {\n\t\tthrow \"ORYX.Core.Math.isPointInPolygone needs two arguments\"\n\t}\n\t\n\tvar lastIndex = polygone.length-1;\n\t\n\tif (polygone[0] !== polygone[lastIndex - 1] || polygone[1] !== polygone[lastIndex]) {\n\t\tpolygone.push(polygone[0]);\n\t\tpolygone.push(polygone[1]);\n\t}\n\t\n\tvar crossings = 0;\n\n\tvar x1, y1, x2, y2, d;\n\t\n    for (var i = 0; i < polygone.length - 3; ) {\n        x1=polygone[i];\n        y1=polygone[++i];\n        x2=polygone[++i];\n        y2=polygone[i+1];\n        d=(pointY - y1) * (x2 - x1) - (pointX - x1) * (y2 - y1);\n\n        if ((y1 >= pointY) != (y2 >= pointY)) {\n            crossings += y2 - y1 >= 0 ? d >= 0 : d <= 0;\n        }\n        if (!d && Math.min(x1,x2) <= pointX && pointX <= Math.max(x1,x2)\n            && Math.min(y1,y2) <= pointY && pointY <= Math.max(y1,y2)) {\n            return true;\n        }\n    }\n\treturn (crossings%2)?true:false;\n}\n\n/**\n *\tCalculates the distance between a point and a line. It is also testable, if \n *  the distance orthogonal to the line, matches the segment of the line.\n *  \n *  @param {float} lineP1\n *  \tThe starting point of the line segment\n *  @param {float} lineP2\n *  \tThe end point of the line segment\n *  @param {Point} point\n *  \tThe point to calculate the distance to.\n *  @param {boolean} toSegmentOnly\n *  \tFlag to signal if only the segment of the line shell be evaluated.\n */\nORYX.Core.Math.distancePointLinie = function(\n\t\t\t\t\t\t\t\t\tlineP1, \n\t\t\t\t\t\t\t\t\tlineP2, \n\t\t\t\t\t\t\t\t\tpoint, \n\t\t\t\t\t\t\t\t\ttoSegmentOnly) {\n\t\n\tvar intersectionPoint = \n\t\t\t\tORYX.Core.Math.getPointOfIntersectionPointLine(lineP1, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tlineP2, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tpoint, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttoSegmentOnly);\n\t\n\tif(!intersectionPoint) {\n\t\treturn null;\n\t}\n\t\n\treturn ORYX.Core.Math.getDistancePointToPoint(point, intersectionPoint);\n};\n\n/**\n * Calculates the distance between two points.\n * \n * @param {point} point1\n * @param {point} point2\n */\nORYX.Core.Math.getDistancePointToPoint = function(point1, point2) {\n\treturn Math.sqrt(Math.pow(point1.x - point2.x, 2) + Math.pow(point1.y - point2.y, 2));\n};\n\n/**\n * Calculates the relative distance of a point which is between two other points.\n * \n * @param {point} between1\n * @param {point} between2\n * @param {point} point\n */\nORYX.Core.Math.getDistanceBetweenTwoPoints = function(between1, between2, point) {\n\treturn \tORYX.Core.Math.getDistancePointToPoint(point, between1) /\n\t\t\tORYX.Core.Math.getDistancePointToPoint(between1, between2);\n};\n\n\n/**\n * Returns true, if the point is of the left hand\n * side of the regarding the line.\n * \n * @param {point} lineP1 Line first point\n * @param {point} lineP2 Line second point\n * @param {point} point\n */\nORYX.Core.Math.pointIsLeftOfLine = function(lineP1, lineP2, point){\n\t\n\tvar vec1 = ORYX.Core.Math.getVector(lineP1, lineP2);\n\tvar vec2 = ORYX.Core.Math.getVector(lineP1, point);\n\t// if the cross produkt is more than 0\n\treturn ((vec1.x*vec2.y) - (vec2.x*vec1.y)) > 0\n};\n\n/**\n * Calculates the a point which is relatively between two other points.\n * \n * @param {point} point1\n * @param {point} point2\n * @param {number} relative Relative which is between 0 and 1\n */\nORYX.Core.Math.getPointBetweenTwoPoints = function(point1, point2, relative) {\n\trelative = Math.max(Math.min(relative || 0, 1), 0);\n\t\n\tif (relative === 0){\n\t\treturn point1;\n\t} else if (relative === 1){\n\t\treturn point2;\n\t}\n\t\n\treturn {\n\t\tx: point1.x + ((point2.x - point1.x) * relative),\n\t\ty: point1.y + ((point2.y - point1.y) * relative)\n\t}\n};\n\n\n/**\n * Returns the vector of the both points\n *\n * @param {point} point1\n * @param {point} point2\n */\nORYX.Core.Math.getVector = function(point1, point2){\n\treturn {\n\t\tx: point2.x - point1.x,\n\t\ty: point2.y - point1.y\n\t}\n}\n\n/**\n * Returns the an identity vector of the given vector, \n * which has the length ot one.\n *\n * @param {point} vector\n * or \n * @param {point} point1\n * @param {point} point2\n */\nORYX.Core.Math.getIdentityVector = function(vector){\n\t\n\tif (arguments.length == 2){\n\t\tvector = ORYX.Core.Math.getVector(arguments[0], arguments[1]);\n\t}\n\t\n\tvar length = Math.sqrt((vector.x*vector.x)+(vector.y*vector.y))\n\treturn {\n\t\tx: vector.x / (length || 1),\n\t\ty: vector.y / (length || 1)\n\t}\n}\n\n\nORYX.Core.Math.getOrthogonalIdentityVector = function(point1, point2){\n\tvar vec = arguments.length == 1 ? point1 : ORYX.Core.Math.getIdentityVector(point1, point2);\n\treturn {\n\t\tx: vec.y,\n\t\ty: -vec.x\n\t}\n}\n\n\n/**\n * Returns the intersection point of a line and a point that defines a line\n * orthogonal to the given line.\n * \n *  @param {float} lineP1\n *  \tThe starting point of the line segment\n *  @param {float} lineP2\n *  \tThe end point of the line segment\n *  @param {Point} point\n *  \tThe point to calculate the distance to.\n *  @param {boolean} onSegmentOnly\n *  \tFlag to signal if only the segment of the line shell be evaluated.\n */\nORYX.Core.Math.getPointOfIntersectionPointLine = function(\n\t\t\t\t\t\t\t\t\t\t\t\t\tlineP1, \n\t\t\t\t\t\t\t\t\t\t\t\t\tlineP2, \n\t\t\t\t\t\t\t\t\t\t\t\t\tpoint, \n\t\t\t\t\t\t\t\t\t\t\t\t\tonSegmentOnly) {\n\n\t/* \n\t * [P3 - P1 - u(P2 - P1)] dot (P2 - P1) = 0\n\t * u =((x3-x1)(x2-x1)+(y3-y1)(y2-y1))/(p2-p1)??\n\t */\n\tvar denominator = Math.pow(lineP2.x - lineP1.x, 2) \n\t\t\t\t\t\t+ Math.pow(lineP2.y - lineP1.y, 2);\n\tif(denominator == 0) {\n\t\treturn undefined;\n\t}\n\t\n\tvar u = ((point.x - lineP1.x) * (lineP2.x - lineP1.x)  \n\t\t\t+ (point.y - lineP1.y) * (lineP2.y - lineP1.y))\n\t\t\t/ denominator;\n\t\t\t\n\tif(onSegmentOnly) {\n\t\tif (!(0 <= u && u <= 1)) {\n\t\t\treturn undefined;\n\t\t}\n\t}\n\t\n\tpointOfIntersection = new Object();\n\tpointOfIntersection.x = lineP1.x + u * (lineP2.x - lineP1.x);\n\tpointOfIntersection.y = lineP1.y + u * (lineP2.y - lineP1.y);\t\n\t\n\treturn pointOfIntersection;\t\t\t\t\t\t\t\t\t\t\t\t\n};\n\n/**\n * Translated the point with the given matrix.\n * @param {Point} point\n * @param {Matrix} matrix \n * @return {Object} Includes x, y\n */\nORYX.Core.Math.getTranslatedPoint = function(point, matrix){\n\tvar x = matrix.a*point.x+matrix.c*point.y+matrix.e*1;\n\tvar y = matrix.b*point.x+matrix.d*point.y+matrix.f*1;\n    return {x:x, y:y}\n}\n\n\n/**\n * Returns the inverse matrix of the given SVG transformation matrix\n * @param {SVGTransformationMatrix} matrix\n * @return {Matrix}\n */\nORYX.Core.Math.getInverseMatrix = function(matrix){\n\n\tvar det = ORYX.Core.Math.getDeterminant(matrix), m = matrix;\n\t// +-     -+\n\t// | a c e |\n\t// | b d f |\n\t// | 0 0 1 |\n\t// +-     -+\n\treturn {\n\t\ta: det * ((m.d*1)-(m.f*0)),\n\t\tb: det * ((m.f*0)-(m.b*1)),\n\t\tc: det * ((m.e*0)-(m.c*1)),\n\t\td: det * ((m.a*1)-(m.e*0)),\n\t\te: det * ((m.c*m.f)-(m.e*m.d)),\n\t\tf: det * ((m.e*m.b)-(m.a*m.f))\n\t}\n}\n\n/**\n * Returns the determinant of the svg transformation matrix\n * @param {SVGTranformationMatrix} matrix\n * @return {Number}\n *\n */\nORYX.Core.Math.getDeterminant = function(m){\n\t// a11a22a33+a12a23a31+a13a21a32-a13a22a31-a12a21a33-a11a23a32\n\treturn (m.a*m.d*1)+(m.c*m.f*0)+(m.e*m.b*0)-(m.e*m.d*0)-(m.c*m.b*1)-(m.a*m.f*0);\n}\n\n/**\n * Returns the bounding box of the given node. Translates the \n * origin bounding box with the tranlation matrix.\n * @param {SVGElement} node\n * @return {Object} Includes x, y, width, height\n */\nORYX.Core.Math.getTranslatedBoundingBox = function(node){\n\tvar matrix = node.getCTM();\n\tvar bb = node.getBBox();\n\tvar ul = ORYX.Core.Math.getTranslatedPoint({x:bb.x, y:bb.y}, matrix);\n\tvar ll = ORYX.Core.Math.getTranslatedPoint({x:bb.x, y:bb.y+bb.height}, matrix);\n\tvar ur = ORYX.Core.Math.getTranslatedPoint({x:bb.x+bb.width, y:bb.y}, matrix);\n\tvar lr = ORYX.Core.Math.getTranslatedPoint({x:bb.x+bb.width, y:bb.y+bb.height}, matrix);\n\t\n\tvar minPoint = {\n\t    x: Math.min(ul.x, ll.x, ur.x, lr.x),\n\t    y: Math.min(ul.y, ll.y, ur.y, lr.y)\n\t}\n\tvar maxPoint = {\n\t    x: Math.max(ul.x, ll.x, ur.x, lr.x),\n\t    y: Math.max(ul.y, ll.y, ur.y, lr.y)\n\t}\n\treturn {\n\t    x: minPoint.x,\n\t    y: minPoint.y,\n\t    width: maxPoint.x - minPoint.x,\n\t    height: maxPoint.y - minPoint.y\n\t}\n};\n\n\n/**\n * Returns the angle of the given line, which is representated by the two points\n * @param {Point} p1\n * @param {Point} p2\n * @return {Number} 0 <= x <= 359.99999\n */\nORYX.Core.Math.getAngle = function(p1, p2){\n\tif(p1.x == p2.x && p1.y == p2.y)\n\t\treturn 0;\n\n\tvar angle = Math.asin(Math.sqrt(Math.pow(p1.y-p2.y, 2))\n\t\t\t\t/(Math.sqrt(Math.pow(p2.x-p1.x, 2)+Math.pow(p1.y-p2.y, 2))))\n\t\t\t\t*180/Math.PI;\n\t\n\tif(p2.x >= p1.x && p2.y <= p1.y)\n\t\treturn angle;\n\telse if(p2.x < p1.x && p2.y <= p1.y)\n\t\treturn 180 - angle;\n\telse if(p2.x < p1.x && p2.y > p1.y)\n\t\treturn 180 + angle;\n\telse\n\t\treturn 360 - angle;\n};\n\n\n/**\n * Implementation of the cohen-sutherland algorithm\n */\nnew function(){\n\t\n\tvar RIGHT = 2, TOP = 8,  BOTTOM = 4, LEFT = 1;\n\t\n \tfunction computeOutCode (x, y, xmin, ymin, xmax, ymax) {\n\t\tvar code = 0;\n\t\tif (y > ymax)\n\t\t    code |= TOP;\n\t\telse if (y < ymin)\n\t\t    code |= BOTTOM;\n\t\tif (x > xmax)\n\t\t    code |= RIGHT;\n\t\telse if (x < xmin)\n\t\t    code |= LEFT;\n\t\treturn code;\n\t}\n\t\n\t/**\n\t * Returns TRUE if the rectangle is over the edge and has intersection points or includes it\n\t * @param {Object} x1 Point A of the line\n\t * @param {Object} y1\n\t * @param {Object} x2 Point B of the line\n\t * @param {Object} y2\n\t * @param {Object} xmin Point A of the rectangle\n\t * @param {Object} ymin\n\t * @param {Object} xmax Point B of the rectangle\n\t * @param {Object} ymax\n\t */\n\tORYX.Core.Math.isRectOverLine = function(x1, y1, x2, y2, xmin, ymin, xmax, ymax){\n\t\treturn !!ORYX.Core.Math.clipLineOnRect.apply(ORYX.Core.Math, arguments);\n\t}\n\t\n\t/**\n\t * Returns the clipped line on the given rectangle. If there is \n\t * no intersection, it will return NULL.\n\t *  \n\t * @param {Object} x1 Point A of the line\n\t * @param {Object} y1\n\t * @param {Object} x2 Point B of the line\n\t * @param {Object} y2\n\t * @param {Object} xmin Point A of the rectangle\n\t * @param {Object} ymin\n\t * @param {Object} xmax Point B of the rectangle\n\t * @param {Object} ymax\n\t */\n\tORYX.Core.Math.clipLineOnRect = function(x1, y1, x2, y2, xmin, ymin, xmax, ymax){\n        //Outcodes for P0, P1, and whatever point lies outside the clip rectangle\n        var outcode0, outcode1, outcodeOut, hhh = 0;\n        var accept = false, done = false;\n \n        //compute outcodes\n        outcode0 = computeOutCode(x1, y1, xmin, ymin, xmax, ymax);\n        outcode1 = computeOutCode(x2, y2, xmin, ymin, xmax, ymax);\n \n        do {\n            if ((outcode0 | outcode1) == 0 ){\n                accept = true;\n                done = true;\n            } else if ( (outcode0 & outcode1) > 0 ) {\n                done = true;\n            } else {\n                //failed both tests, so calculate the line segment to clip\n                //from an outside point to an intersection with clip edge\n                var x = 0, y = 0;\n                //At least one endpoint is outside the clip rectangle; pick it.\n                outcodeOut = outcode0 != 0 ? outcode0: outcode1;\n                //Now find the intersection point;\n                //use formulas y = y0 + slope * (x - x0), x = x0 + (1/slope)* (y - y0)\n                if ( (outcodeOut & TOP) > 0 ) {\n                    x = x1 + (x2 - x1) * (ymax - y1)/(y2 - y1);\n                    y = ymax;\n                } else if ((outcodeOut & BOTTOM) > 0 ) {\n                    x = x1 + (x2 - x1) * (ymin - y1)/(y2 - y1);\n                    y = ymin;\n                } else if ((outcodeOut & RIGHT)> 0) {\n                    y = y1 + (y2 - y1) * (xmax - x1)/(x2 - x1);\n                    x = xmax;\n                } else if ((outcodeOut & LEFT) > 0) {\n                    y = y1 + (y2 - y1) * (xmin - x1)/(x2 - x1);\n                    x = xmin;\n                }\n\t\t\t\t\n                //Now we move outside point to intersection point to clip\n                //and get ready for next pass.\n                if (outcodeOut == outcode0) {\n                    x1 = x;\n                    y1 = y;\n                    outcode0 = computeOutCode (x1, y1, xmin, ymin, xmax, ymax);\n                } else {\n                    x2 = x;\n                    y2 = y;\n                    outcode1 = computeOutCode (x2, y2, xmin, ymin, xmax, ymax);\n                }\n            }\n            hhh ++;\n        } while (done  != true && hhh < 5000);\n \n        if(accept) {\n            return {a:{x:x1, y:y1}, b:{x:x2, y:y2}};\n        }\n\t\treturn null;\n    }\n}();\n\n\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespace\n */\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\nif(!ORYX.Core.StencilSet) {ORYX.Core.StencilSet = {};}\n\n/**\n * Class Stencil\n * uses Prototpye 1.5.0\n * uses Inheritance\n * \n * This class represents one stencil of a stencil set.\n */\nORYX.Core.StencilSet.Stencil = {\n\n\t/**\n\t * Constructor\n\t */\n\tconstruct: function(jsonStencil, namespace, source, stencilSet, propertyPackages, defaultPosition) {\n\t\targuments.callee.$.construct.apply(this, arguments); // super();\n\t\t\n\t\t// check arguments and set defaults.\n\t\tif(!jsonStencil) throw \"Stencilset seems corrupt.\";\n\t\tif(!namespace) throw \"Stencil does not provide namespace.\";\n\t\tif(!source) throw \"Stencil does not provide SVG source.\";\n\t\tif(!stencilSet) throw \"Fatal internal error loading stencilset.\";\n\t\t//if(!propertyPackages) throw \"Fatal internal error loading stencilset.\";\n\t\t\n\t\tthis._source = source;\n\t\tthis._jsonStencil = jsonStencil;\n\t\tthis._stencilSet = stencilSet;\n\t\tthis._namespace = namespace;\n\t\tthis._propertyPackages = propertyPackages;\n\t\t\n\t\tif(defaultPosition && !this._jsonStencil.position) \n\t\t\tthis._jsonStencil.position = defaultPosition;\n\t\t\n\t\tthis._view;\n\t\tthis._properties = new Hash();\n\n\t\t// check stencil consistency and set defaults.\n\t\t/*with(this._jsonStencil) {\n\t\t\t\n\t\t\tif(!type) throw \"Stencil does not provide type.\";\n\t\t\tif((type != \"edge\") && (type != \"node\"))\n\t\t\t\tthrow \"Stencil type must be 'edge' or 'node'.\";\n\t\t\tif(!id || id == \"\") throw \"Stencil does not provide valid id.\";\n\t\t\tif(!title || title == \"\")\n\t\t\t\tthrow \"Stencil does not provide title\";\n\t\t\tif(!description) { description = \"\"; };\n\t\t\tif(!groups) { groups = []; }\n\t\t\tif(!roles) { roles = []; }\n\n\t\t\t// add id of stencil to its roles\n\t\t\troles.push(id);\n\t\t}*/\n\t\t\n\t\t//init all JSON values\n\t\tif(!this._jsonStencil.type || !(this._jsonStencil.type === \"edge\" || this._jsonStencil.type === \"node\")) {\n\t\t\tthrow \"ORYX.Core.StencilSet.Stencil(construct): Type is not defined.\";\n\t\t}\n\t\tif(!this._jsonStencil.id || this._jsonStencil.id === \"\") {\n\t\t\tthrow \"ORYX.Core.StencilSet.Stencil(construct): Id is not defined.\";\n\t\t}\n\t\tif(!this._jsonStencil.title || this._jsonStencil.title === \"\") {\n\t\t\tthrow \"ORYX.Core.StencilSet.Stencil(construct): Title is not defined.\";\n\t\t}\n\n\t\tif(!this._jsonStencil.description) { this._jsonStencil.description = \"\"; };\n\t\tif(!this._jsonStencil.groups) { this._jsonStencil.groups = []; }\n\t\tif(!this._jsonStencil.roles) { this._jsonStencil.roles = []; }\n\t\t\n\t\t//add id of stencil to its roles\n\t\tthis._jsonStencil.roles.push(this._jsonStencil.id);\n\n\t\t//prepend namespace to each role\n\t\tthis._jsonStencil.roles.each((function(role, index) {\n\t\t\tthis._jsonStencil.roles[index] = namespace + role;\n\t\t}).bind(this));\n\n\t\t//delete duplicate roles\n\t\tthis._jsonStencil.roles = this._jsonStencil.roles.uniq();\n\n\t\t//make id unique by prepending namespace of stencil set\n\t\tthis._jsonStencil.id = namespace + this._jsonStencil.id;\n\n\t\tthis.postProcessProperties();\n\t\t\n\t\t// init serialize callback\n\t\tif(!this._jsonStencil.serialize) {\n\t\t\tthis._jsonStencil.serialize = {};\n\t\t\t//this._jsonStencil.serialize = function(shape, data) { return data;};\n\t\t}\n\t\t\n\t\t// init deserialize callback\n\t\tif(!this._jsonStencil.deserialize) {\n\t\t\tthis._jsonStencil.deserialize = {};\n\t\t\t//this._jsonStencil.deserialize = function(shape, data) { return data;};\n\t\t}\n\t\t\n\t\t// init layout callback\n\t\tif(!this._jsonStencil.layout) {\n\t\t\tthis._jsonStencil.layout = []\n\t\t\t//this._jsonStencil.layout = function() {return true;}\n\t\t}\n\t\t\n\t\t//TODO does not work correctly, if the url does not exist\n\t\t//How to guarantee that the view is loaded correctly before leaving the constructor???\n\t\tvar url = source + \"view/\" + jsonStencil.view;\n\t\t// override content type when this is webkit.\n\t\t\n\t\tif(this._jsonStencil.view.trim().match(/</)) {\n\t\t\tvar parser\t= new DOMParser();\t\t\n\t\t\tvar xml \t= parser.parseFromString( this._jsonStencil.view ,\"text/xml\");\n\t\t\t\n\t\t\t//check if result is a SVG document\n\t\t\tif( ORYX.Editor.checkClassType( xml.documentElement, SVGSVGElement )) {\n\t\n\t\t\t\tthis._view = xml.documentElement;\n\t\t\t\t\n\t\t\t} else {\n\t\t\t\tthrow \"ORYX.Core.StencilSet.Stencil(_loadSVGOnSuccess): The response is not a SVG document.\"\n\t\t\t}\n\t\t} else {\n\t\t\tnew Ajax.Request(\n\t\t\t\turl, {\n\t\t\t\t\tasynchronous:false, method:'get',\n\t\t\t\t\tonSuccess:this._loadSVGOnSuccess.bind(this),\n\t\t\t\t\tonFailure:this._loadSVGOnFailure.bind(this)\n\t\t\t});\n\t\t}\n\t},\n\n\tpostProcessProperties: function() {\n\n\t\t// init property packages\n\t\tif(this._jsonStencil.propertyPackages && this._jsonStencil.propertyPackages instanceof Array) {\n\t\t\t\n\t\t\tthis._jsonStencil.propertyPackages.each((function(ppId) {\n\t\t\t\tvar pp = this._propertyPackages[ppId];\n\t\t\t\t\n\t\t\t\tif(pp) {\n\t\t\t\t\tpp.each((function(prop){\n\t\t\t\t\t\tvar oProp = new ORYX.Core.StencilSet.Property(prop, this._namespace, this);\n\t\t\t\t\t\tthis._properties[oProp.prefix() + \"-\" + oProp.id()] = oProp;\n\t\t\t\t\t\t\n\t\t\t\t\t}).bind(this));\n\t\t\t\t}\n\t\t\t}).bind(this));\n\t\t}\n\t\t\n\t\t// init properties\n\t\tif(this._jsonStencil.properties && this._jsonStencil.properties instanceof Array) {\n\t\t\tthis._jsonStencil.properties.each((function(prop) {\n\t\t\t\tvar oProp = new ORYX.Core.StencilSet.Property(prop, this._namespace, this);\n\t\t\t\tthis._properties[oProp.prefix() + \"-\" + oProp.id()] = oProp;\n\t\t\t}).bind(this));\n\t\t}\n\n\t},\n\n\t/**\n\t * @param {ORYX.Core.StencilSet.Stencil} stencil\n\t * @return {Boolean} True, if stencil has the same namespace and type.\n\t */\n\tequals: function(stencil) {\n\t\treturn (this.id() === stencil.id());\n\t},\n\n\tstencilSet: function() {\n\t\treturn this._stencilSet;\n\t},\n\n\ttype: function() {\n\t\treturn this._jsonStencil.type;\n\t},\n\n\tnamespace: function() {\n\t\treturn this._namespace;\n\t},\n\n\tid: function() {\n\t\treturn this._jsonStencil.id;\n\t},\n    \n    idWithoutNs: function(){\n        return this.id().replace(this.namespace(),\"\");\n    },\n\n\ttitle: function() {\n\t\treturn ORYX.Core.StencilSet.getTranslation(this._jsonStencil, \"title\");\n\t},\n\n\tdescription: function() {\n\t\treturn ORYX.Core.StencilSet.getTranslation(this._jsonStencil, \"description\");\n\t},\n\t\n\tgroups: function() {\n\t\treturn ORYX.Core.StencilSet.getTranslation(this._jsonStencil, \"groups\");\n\t},\n\t\n\tposition: function() {\n\t\treturn (isNaN(this._jsonStencil.position) ? 0 : this._jsonStencil.position);\n\t},\n\n\tview: function() {\n\t\treturn this._view.cloneNode(true) || this._view;\n\t},\n\n\ticon: function() {\n\t\treturn this._jsonStencil.icon;\n\t},\n\t\n\tfixedAspectRatio: function() {\n\t\treturn this._jsonStencil.fixedAspectRatio === true;\n\t},\n\t\n\thasMultipleRepositoryEntries: function() {\n\t\treturn (this.getRepositoryEntries().length > 0);\n\t},\n\t\n\tgetRepositoryEntries: function() {\n\t\treturn (this._jsonStencil.repositoryEntries) ?\n\t\t\t$A(this._jsonStencil.repositoryEntries) : $A([]);\n\t},\n\t\n\tproperties: function() {\n\t\treturn this._properties.values();\n\t},\n\n\tproperty: function(id) {\n\t\treturn this._properties[id];\n\t},\n\n\troles: function() {\n\t\treturn this._jsonStencil.roles;\n\t},\n\t\n\tdefaultAlign: function() {\n\t\tif(!this._jsonStencil.defaultAlign)\n\t\t\treturn \"east\";\n\t\treturn this._jsonStencil.defaultAlign;\n\t},\n\n\tserialize: function(shape, data) {\n\t\treturn this._jsonStencil.serialize;\n\t\t//return this._jsonStencil.serialize(shape, data);\n\t},\n\t\n\tdeserialize: function(shape, data) {\n\t\treturn this._jsonStencil.deserialize;\n\t\t//return this._jsonStencil.deserialize(shape, data);\n\t},\n\t\n\t// in which case is targetShape used?\n//\tlayout: function(shape, targetShape) {\n//\t\treturn this._jsonStencil.layout(shape, targetShape);\n//\t},\n\t// layout property to store events for layouting in plugins\n\tlayout: function(shape) {\n\t\treturn this._jsonStencil.layout\n\t},\n\t\n\taddProperty: function(property, namespace) {\n\t\tif(property && namespace) {\n\t\t\tvar oProp = new ORYX.Core.StencilSet.Property(property, namespace, this);\n\t\t\tthis._properties[oProp.prefix() + \"-\" + oProp.id()] = oProp;\n\t\t}\n\t},\n\t\n\tremoveProperty: function(propertyId) {\n\t\tif(propertyId) {\n\t\t\tvar oProp = this._properties.values().find(function(prop) {\n\t\t\t\treturn (propertyId == prop.id());\n\t\t\t});\n\t\t\tif(oProp)\n\t\t\t\tdelete this._properties[oProp.prefix() + \"-\" + oProp.id()];\n\t\t}\n\t},\n\n\t_loadSVGOnSuccess: function(result) {\n\t\t\n\t\tvar xml = null;\n\t\t\n\t\t/*\n\t\t * We want to get a dom object for the requested file. Unfortunately,\n\t\t * safari has some issues here. this is meant as a fallback for all\n\t\t * browsers that don't recognize the svg mimetype as XML but support\n\t\t * data: urls on Ajax calls.\n\t\t */\n\t\t\n\t\t// responseXML != undefined.\n\t\t// if(!(result.responseXML))\n\t\t\n\t\t\t// get the dom by data: url.\n\t\t\t// xml = _evenMoreEvilHack(result.responseText, 'text/xml');\n\t\t\n\t\t// else\n\t\t\n\t\t\t// get it the usual way.\n\t\t\txml = result.responseXML;\n\n\t\t//check if result is a SVG document\n\t\tif( ORYX.Editor.checkClassType( xml.documentElement, SVGSVGElement )) {\n\n\t\t\tthis._view = xml.documentElement;\n\t\t\t\n\t\t} else {\n\t\t\tthrow \"ORYX.Core.StencilSet.Stencil(_loadSVGOnSuccess): The response is not a SVG document.\"\n\t\t}\n\t},\n\n\t_loadSVGOnFailure: function(result) {\n\t\tthrow \"ORYX.Core.StencilSet.Stencil(_loadSVGOnFailure): Loading SVG document failed.\"\n\t},\n\n\ttoString: function() { return \"Stencil \" + this.title() + \" (\" + this.id() + \")\"; }\n};\n\nORYX.Core.StencilSet.Stencil = Clazz.extend(ORYX.Core.StencilSet.Stencil);\n\n/**\n * Transform a string into an xml document, the Safari way, as long as\n * the nightlies are broken. Even more evil version.\n * @param {Object} str\n * @param {Object} contentType\n */\nfunction _evenMoreEvilHack(str, contentType) {\n\t\n\t/*\n\t * This even more evil hack was taken from\n\t * http://web-graphics.com/mtarchive/001606.php#chatty004999\n\t */\n\t\n\tif (window.ActiveXObject) {\n\t\tvar d = new ActiveXObject(\"MSXML.DomDocument\");\n\t\td.loadXML(str);\n\t\treturn d;\n\t} else if (window.XMLHttpRequest) {\n\t\tvar req = new XMLHttpRequest;\n\t\treq.open(\"GET\", \"data:\" + (contentType || \"application/xml\") +\n\t\t\t\t\t\t\";charset=utf-8,\" + encodeURIComponent(str), false);\n\t\tif (req.overrideMimeType) {\n\t\t\treq.overrideMimeType(contentType);\n\t\t}\n\t\treq.send(null);\n\t\treturn req.responseXML;\n\t}\n}\n\n/**\n * Transform a string into an xml document, the Safari way, as long as\n * the nightlies are broken.\n * @param {Object} result the xml document object.\n */\nfunction _evilSafariHack(serializedXML) {\n\t\n\t/*\n\t *  The Dave way. Taken from:\n\t *  http://web-graphics.com/mtarchive/001606.php\n\t *  \n\t *  There is another possibility to parse XML in Safari, by implementing\n\t *  the DOMParser in javascript. However, in the latest nightlies of\n\t *  WebKit, DOMParser is already available, but still buggy. So, this is\n\t *  the best compromise for the time being.\n\t */\t\t\n\t\n\tvar xml = serializedXML;\n\tvar url = \"data:text/xml;charset=utf-8,\" + encodeURIComponent(xml);\n\tvar dom = null;\n\t\n\t// your standard AJAX stuff\n\tvar req = new XMLHttpRequest();\n\treq.open(\"GET\", url);\n\treq.onload = function() { dom = req.responseXML; }\n\treq.send(null);\n\t\n\treturn dom;\n}\n\t/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespace\n */\nif (!ORYX) {\n    var ORYX = {};\n}\nif (!ORYX.Core) {\n    ORYX.Core = {};\n}\nif (!ORYX.Core.StencilSet) {\n    ORYX.Core.StencilSet = {};\n}\n\n/**\n * Class Property\n * uses Prototpye 1.5.0\n * uses Inheritance\n */\nORYX.Core.StencilSet.Property = Clazz.extend({\n\n    /**\n     * Constructor\n     */\n    construct: function(jsonProp, namespace, stencil){\n        arguments.callee.$.construct.apply(this, arguments);\n        \n        this._jsonProp = jsonProp || ORYX.Log.error(\"Parameter jsonProp is not defined.\");\n        this._namespace = namespace || ORYX.Log.error(\"Parameter namespace is not defined.\");\n        this._stencil = stencil || ORYX.Log.error(\"Parameter stencil is not defined.\");\n        \n        this._items = {};\n        this._complexItems = {};\n        \n\t    // Flag to indicate whether or not the property should be hidden \n\t    // This can be for example when the stencil set is upgraded, but the model\n        // has a value for that specific property filled in which we still want to show.\n        // If the value is missing, the property can simply be not shown.\n        this._hidden = false;\n        \n        jsonProp.id = jsonProp.id || ORYX.Log.error(\"ORYX.Core.StencilSet.Property(construct): Id is not defined.\");\n\t\tjsonProp.id = jsonProp.id.toLowerCase();\n\t\t\n        if (!jsonProp.type) {\n            ORYX.Log.info(\"Type is not defined for stencil '%0', id '%1'. Falling back to 'String'.\", stencil, jsonProp.id);\n            jsonProp.type = \"string\";\n        }\n        else {\n            jsonProp.type = jsonProp.type.toLowerCase();\n        }\n        \n        jsonProp.prefix = jsonProp.prefix || \"oryx\";\n        jsonProp.title = jsonProp.title || \"\";\n        jsonProp.value = jsonProp.value || \"\";\n        jsonProp.description = jsonProp.description || \"\";\n        jsonProp.readonly = jsonProp.readonly || false;\n        jsonProp.optional = jsonProp.optional !== false;\n        \n        //init refToView\n        if (this._jsonProp.refToView) {\n            if (!(this._jsonProp.refToView instanceof Array)) {\n                this._jsonProp.refToView = [this._jsonProp.refToView];\n            }\n        }\n        else {\n            this._jsonProp.refToView = [];\n        }\n        \n\t\tvar globalMin = this.getMinForType(jsonProp.type);\n        if (jsonProp.min === undefined || jsonProp.min === null) {\n            jsonProp.min =globalMin;\n        } else if (jsonProp.min < globalMin) {\n\t\t\tjsonProp.min = globalMin;\n\t\t}\n        \n\t\tvar globalMax = this.getMaxForType(jsonProp.type);\n        if (jsonProp.max === undefined || jsonProp.max === null) {\n            jsonProp.max = globalMax;\n        } else if (jsonProp.max > globalMax) {\n\t\t\tjsonProp.min = globalMax;\n\t\t}\n        \n        if (!jsonProp.fillOpacity) {\n            jsonProp.fillOpacity = false;\n        }\n\t\t\n\t\tif (\"number\" != typeof jsonProp.lightness) {\n\t\t\tjsonProp.lightness = 1;\n\t\t} else {\n\t\t\tjsonProp.lightness = Math.max(0, Math.min(1, jsonProp.lightness));\n\t\t}\n        \n        if (!jsonProp.strokeOpacity) {\n            jsonProp.strokeOpacity = false;\n        }\n        \n        if (jsonProp.length === undefined || jsonProp.length === null) {\n            jsonProp.length = Number.MAX_VALUE;\n        }\n        \n        if (!jsonProp.wrapLines) {\n            jsonProp.wrapLines = false;\n        }\n        \n        if (!jsonProp.dateFormat) {\n            jsonProp.dateFormat = ORYX.I18N.PropertyWindow.dateFormat || \"m/d/y\";\n        }\n        \n        if (!jsonProp.fill) {\n            jsonProp.fill = false;\n        }\n        \n        if (!jsonProp.stroke) {\n            jsonProp.stroke = false;\n        }\n        \n        if(!jsonProp.inverseBoolean) {\n        \tjsonProp.inverseBoolean = false;\n        }\n\t\t\n\t\tif(!jsonProp.directlyEditable && jsonProp.directlyEditable != false) {\n        \tjsonProp.directlyEditable = true;\n        }\n\t\t\n\t\tif(jsonProp.visible !== false) {\n\t\t\tjsonProp.visible = true;\n\t\t}\n\t\t\n\t\tif(jsonProp.isList !== true) {\n\t\t\tjsonProp.isList = false;\n\t\t\t\n\t\t\tif(!jsonProp.list || !(jsonProp.list instanceof Array)) {\n\t\t\t\tjsonProp.list = [];\n\t\t\t}\t\n\t\t}\n\t\t\n\t\tif(!jsonProp.category) {\n\t\t\tif (jsonProp.popular) {\n\t\t\t\tjsonProp.category = \"popular\";\n\t\t\t} else {\n\t\t\t\tjsonProp.category = \"others\";\n\t\t\t}\n\t\t}\n\t\t\n\t\tif(!jsonProp.alwaysAppearInMultiselect) {\n\t\t\tjsonProp.alwaysAppearInMultiselect = false;\n\t\t}\n        \n        if (jsonProp.type === ORYX.CONFIG.TYPE_CHOICE) {\n            if (jsonProp.items && jsonProp.items instanceof Array) {\n                jsonProp.items.each((function(jsonItem){\n                \t// why is the item's value used as the key???\n                    this._items[jsonItem.value.toLowerCase()] = new ORYX.Core.StencilSet.PropertyItem(jsonItem, namespace, this);\n                }).bind(this));\n            }\n            else {\n                throw \"ORYX.Core.StencilSet.Property(construct): No property items defined.\"\n            }\n            // extended by Kerstin (start)\n        }\n        else \n            if (jsonProp.type === ORYX.CONFIG.TYPE_COMPLEX || jsonProp.type == ORYX.CONFIG.TYPE_MULTIPLECOMPLEX) {\n                if (jsonProp.complexItems && jsonProp.complexItems instanceof Array) {\n                    jsonProp.complexItems.each((function(jsonComplexItem){\n                        this._complexItems[jsonComplexItem.id.toLowerCase()] = new ORYX.Core.StencilSet.ComplexPropertyItem(jsonComplexItem, namespace, this);\n                    }).bind(this));\n                }\n            }\n        // extended by Kerstin (end)\n    },\n\t\n\tgetMinForType : function(type) {\n\t\tif (type.toLowerCase() == ORYX.CONFIG.TYPE_INTEGER) {\n\t\t\treturn -Math.pow(2,31)\n\t\t} else {\n\t\t\treturn -Number.MAX_VALUE+1;\n\t\t}\n\t}, \n\tgetMaxForType : function(type) {\n\t\tif (type.toLowerCase() == ORYX.CONFIG.TYPE_INTEGER) {\n\t\t\treturn Math.pow(2,31)-1\n\t\t} else {\n\t\t\treturn Number.MAX_VALUE;\n\t\t}\n\t},\n    \n    /**\n     * @param {ORYX.Core.StencilSet.Property} property\n     * @return {Boolean} True, if property has the same namespace and id.\n     */\n    equals: function(property){\n        return (this._namespace === property.namespace() &&\n        this.id() === property.id()) ? true : false;\n    },\n    \n    namespace: function(){\n        return this._namespace;\n    },\n    \n    stencil: function(){\n        return this._stencil;\n    },\n    \n    id: function(){\n        return this._jsonProp.id;\n    },\n    \n    prefix: function(){\n        return this._jsonProp.prefix;\n    },\n    \n    type: function(){\n        return this._jsonProp.type;\n    },\n    \n    inverseBoolean: function() {\n    \treturn this._jsonProp.inverseBoolean;\n    },\n\t\n\tcategory: function() {\n\t\treturn this._jsonProp.category;\n\t},\n\t\n\tsetCategory: function(value) {\n\t\tthis._jsonProp.category = value;\n\t},\n\t\n\tdirectlyEditable: function() {\n\t\treturn this._jsonProp.directlyEditable;\n\t},\n\t\n\tvisible: function() {\n\t\treturn this._jsonProp.visible;\n\t},\n    \n    title: function(){\n        return ORYX.Core.StencilSet.getTranslation(this._jsonProp, \"title\");\n    },\n    \n    value: function(){\n        return this._jsonProp.value;\n    },\n    \n    readonly: function(){\n        return this._jsonProp.readonly;\n    },\n    \n    optional: function(){\n        return this._jsonProp.optional;\n    },\n    \n    description: function(){\n        return ORYX.Core.StencilSet.getTranslation(this._jsonProp, \"description\");\n    },\n\t\n    /**\n     * An optional link to a SVG element so that the property affects the\n     * graphical representation of the stencil.\n     */\n    refToView: function(){\n        return this._jsonProp.refToView;\n    },\n    \n    /**\n     * If type is integer or float, min is the lower bounds of value.\n     */\n    min: function(){\n        return this._jsonProp.min;\n    },\n    \n    /**\n     * If type ist integer or float, max is the upper bounds of value.\n     */\n    max: function(){\n        return this._jsonProp.max;\n    },\n    \n    /**\n     * If type is float, this method returns if the fill-opacity property should\n     *  be set.\n     *  @return {Boolean}\n     */\n    fillOpacity: function(){\n        return this._jsonProp.fillOpacity;\n    },\n    \n    /**\n     * If type is float, this method returns if the stroke-opacity property should\n     *  be set.\n     *  @return {Boolean}\n     */\n    strokeOpacity: function(){\n        return this._jsonProp.strokeOpacity;\n    },\n    \n    /**\n     * If type is string or richtext, length is the maximum length of the text.\n     * TODO how long can a string be.\n     */\n    length: function(){\n        return this._jsonProp.length ? this._jsonProp.length : Number.MAX_VALUE;\n    },\n    \n    wrapLines: function(){\n        return this._jsonProp.wrapLines;\n    },\n    \n    /**\n     * If type is date, dateFormat specifies the format of the date. The format\n     * specification of the ext library is used:\n     *\n     * Format  Output      Description\n     *\t------  ----------  --------------------------------------------------------------\n     *\t  d      10         Day of the month, 2 digits with leading zeros\n     *\t  D      Wed        A textual representation of a day, three letters\n     *\t  j      10         Day of the month without leading zeros\n     *\t  l      Wednesday  A full textual representation of the day of the week\n     *\t  S      th         English ordinal day of month suffix, 2 chars (use with j)\n     *\t  w      3          Numeric representation of the day of the week\n     *\t  z      9          The julian date, or day of the year (0-365)\n     *\t  W      01         ISO-8601 2-digit week number of year, weeks starting on Monday (00-52)\n     *\t  F      January    A full textual representation of the month\n     *\t  m      01         Numeric representation of a month, with leading zeros\n     *\t  M      Jan        Month name abbreviation, three letters\n     *\t  n      1          Numeric representation of a month, without leading zeros\n     *\t  t      31         Number of days in the given month\n     *\t  L      0          Whether its a leap year (1 if it is a leap year, else 0)\n     *\t  Y      2007       A full numeric representation of a year, 4 digits\n     *\t  y      07         A two digit representation of a year\n     *\t  a      pm         Lowercase Ante meridiem and Post meridiem\n     *\t  A      PM         Uppercase Ante meridiem and Post meridiem\n     *\t  g      3          12-hour format of an hour without leading zeros\n     *\t  G      15         24-hour format of an hour without leading zeros\n     *\t  h      03         12-hour format of an hour with leading zeros\n     *\t  H      15         24-hour format of an hour with leading zeros\n     *\t  i      05         Minutes with leading zeros\n     *\t  s      01         Seconds, with leading zeros\n     *\t  O      -0600      Difference to Greenwich time (GMT) in hours\n     *\t  T      CST        Timezone setting of the machine running the code\n     *\t  Z      -21600     Timezone offset in seconds (negative if west of UTC, positive if east)\n     *\n     * Example:\n     *  F j, Y, g:i a  ->  January 10, 2007, 3:05 pm\n     */\n    dateFormat: function(){\n        return this._jsonProp.dateFormat;\n    },\n    \n    /**\n     * If type is color, this method returns if the fill property should\n     *  be set.\n     *  @return {Boolean}\n     */\n    fill: function(){\n        return this._jsonProp.fill;\n    },\n\t\n\t/**\n\t * Lightness defines the satiation of the color\n\t * 0 is the pure color\n\t * 1 is white\n\t * @return {Integer} lightness\n\t */\n\tlightness: function(){\n\t\treturn this._jsonProp.lightness;\n\t},\n    \n    /**\n     * If type is color, this method returns if the stroke property should\n     *  be set.\n     *  @return {Boolean}\n     */\n    stroke: function(){\n        return this._jsonProp.stroke;\n    },\n    \n    /**\n     * If type is choice, items is a hash map with all alternative values\n     * (PropertyItem objects) with id as keys.\n     */\n    items: function(){\n        return $H(this._items).values();\n    },\n    \n    item: function(value){\n        if (value) {\n\t\t\treturn this._items[value.toLowerCase()];\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n    },\n    \n    toString: function(){\n        return \"Property \" + this.title() + \" (\" + this.id() + \")\";\n    },\n    \n    complexItems: function(){\n        return $H(this._complexItems).values();\n    },\n    \n    complexItem: function(id){\n        if(id) {\n\t\t\treturn this._complexItems[id.toLowerCase()];\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t\t\n    },\n    \n    complexAttributeToView: function(){\n        return this._jsonProp.complexAttributeToView || \"\";\n    },\n    \n    isList: function() {\n    \treturn !!this._jsonProp.isList;\n    },\n    \n    getListItems: function() {\n    \treturn this._jsonProp.list;\n    },\n\t\n\t/**\n\t * If type is glossary link, the \n\t * type of category can be defined where\n\t * the link only can go to.\n\t * @return {String} The glossary category id \n\t */\n\tlinkableType: function(){\n\t\treturn this._jsonProp.linkableType || \"\";\n\t},\n\t\n\talwaysAppearInMultiselect : function() {\n\t\treturn this._jsonProp.alwaysAppearInMultiselect;\n\t},\n\t\n\tpopular: function() {\n\t\treturn this._jsonProp.popular || false;\n\t},\n\t\n\tsetPopular: function() {\n\t\tthis._jsonProp.popular = true;\n\t},\n\t\n\thide: function() {\n\t\tthis._hidden = true;\n\t},\n\t\n\tisHidden: function() {\n\t\treturn this._hidden;\n\t}\n\t\n});\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespace\n */\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\nif(!ORYX.Core.StencilSet) {ORYX.Core.StencilSet = {};}\n\n/**\n * Class Stencil\n * uses Prototpye 1.5.0\n * uses Inheritance\n */\nORYX.Core.StencilSet.PropertyItem = Clazz.extend({\n\n\t/**\n\t * Constructor\n\t */\n\tconstruct: function(jsonItem, namespace, property) {\n\t\targuments.callee.$.construct.apply(this, arguments);\n\n\t\tif(!jsonItem) {\n\t\t\tthrow \"ORYX.Core.StencilSet.PropertyItem(construct): Parameter jsonItem is not defined.\";\n\t\t}\n\t\tif(!namespace) {\n\t\t\tthrow \"ORYX.Core.StencilSet.PropertyItem(construct): Parameter namespace is not defined.\";\n\t\t}\n\t\tif(!property) {\n\t\t\tthrow \"ORYX.Core.StencilSet.PropertyItem(construct): Parameter property is not defined.\";\n\t\t}\n\t\t\n\t\tthis._jsonItem = jsonItem;\n\t\tthis._namespace = namespace;\n\t\tthis._property = property;\n\t\t\n\t\t//init all values\n\t\tif(!jsonItem.value) {\n\t\t\tthrow \"ORYX.Core.StencilSet.PropertyItem(construct): Value is not defined.\";\n\t\t}\n\t\t\n\t\tif(this._jsonItem.refToView) {\n\t\t\tif(!(this._jsonItem.refToView instanceof Array)) {\n\t\t\t\tthis._jsonItem.refToView = [this._jsonItem.refToView];\n\t\t\t}\n\t\t} else {\n\t\t\tthis._jsonItem.refToView = [];\n\t\t}\n\t},\n\n\t/**\n\t * @param {ORYX.Core.StencilSet.PropertyItem} item\n\t * @return {Boolean} True, if item has the same namespace and id.\n\t */\n\tequals: function(item) {\n\t\treturn (this.property().equals(item.property()) &&\n\t\t\tthis.value() === item.value());\n\t},\n\n\tnamespace: function() {\n\t\treturn this._namespace;\n\t},\n\n\tproperty: function() {\n\t\treturn this._property;\n\t},\n\n\tvalue: function() {\n\t\treturn this._jsonItem.value;\n\t},\n\t\n\ttitle: function() {\n\t\treturn ORYX.Core.StencilSet.getTranslation(this._jsonItem, \"title\");\n\t},\n\n\trefToView: function() {\n\t\treturn this._jsonItem.refToView;\n\t},\n\t\n\ticon: function() {\n\t\treturn (this._jsonItem.icon) ? this.property().stencil()._source + \"icons/\" + this._jsonItem.icon : \"\";\n\t},\n\n\ttoString: function() { return \"PropertyItem \" + this.property() + \" (\" + this.value() + \")\"; }\n});/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespaces\n */\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\nif(!ORYX.Core.StencilSet) {ORYX.Core.StencilSet = {};}\n\n/**\n * Class Stencil\n * uses Prototpye 1.5.0\n * uses Inheritance\n */\nORYX.Core.StencilSet.ComplexPropertyItem = Clazz.extend({\n\n\t/**\n\t * Constructor\n\t */\n\tconstruct: function(jsonItem, namespace, property) {\n\t\targuments.callee.$.construct.apply(this, arguments);\n\n\t\tif(!jsonItem) {\n\t\t\tthrow \"ORYX.Core.StencilSet.ComplexPropertyItem(construct): Parameter jsonItem is not defined.\";\n\t\t}\n\t\tif(!namespace) {\n\t\t\tthrow \"ORYX.Core.StencilSet.ComplexPropertyItem(construct): Parameter namespace is not defined.\";\n\t\t}\n\t\tif(!property) {\n\t\t\tthrow \"ORYX.Core.StencilSet.ComplexPropertyItem(construct): Parameter property is not defined.\";\n\t\t}\n\t\t\n\t\tthis._jsonItem = jsonItem;\n\t\tthis._namespace = namespace;\n\t\tthis._property = property;\n\t\tthis._items = new Hash();\n\t\tthis._complexItems = new Hash();\n\t\t\n\t\t//init all values\n\t\tif(!jsonItem.name) {\n\t\t\tthrow \"ORYX.Core.StencilSet.ComplexPropertyItem(construct): Name is not defined.\";\n\t\t}\n\t\t\n\t\tif(!jsonItem.type) {\n\t\t\tthrow \"ORYX.Core.StencilSet.ComplexPropertyItem(construct): Type is not defined.\";\n\t\t} else {\n\t\t\tjsonItem.type = jsonItem.type.toLowerCase();\n\t\t}\n\t\t\n\t\tif(jsonItem.type === ORYX.CONFIG.TYPE_CHOICE) {\n\t\t\tif(jsonItem.items && jsonItem.items instanceof Array) {\n\t\t\t\tjsonItem.items.each((function(item) {\n\t\t\t\t\tthis._items[item.value] = new ORYX.Core.StencilSet.PropertyItem(item, namespace, this);\n\t\t\t\t}).bind(this));\n\t\t\t} else {\n\t\t\t\tthrow \"ORYX.Core.StencilSet.Property(construct): No property items defined.\"\n\t\t\t}\n\t\t} else if(jsonItem.type === ORYX.CONFIG.TYPE_COMPLEX) {\n\t\t\tif(jsonItem.complexItems && jsonItem.complexItems instanceof Array) {\n\t\t\t\tjsonItem.complexItems.each((function(complexItem) {\n\t\t\t\t\tthis._complexItems[complexItem.id] = new ORYX.Core.StencilSet.ComplexPropertyItem(complexItem, namespace, this);\n\t\t\t\t}).bind(this));\n\t\t\t} else {\n\t\t\t\tthrow \"ORYX.Core.StencilSet.Property(construct): No property items defined.\"\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * @param {ORYX.Core.StencilSet.PropertyItem} item\n\t * @return {Boolean} True, if item has the same namespace and id.\n\t */\n\tequals: function(item) {\n\t\treturn (this.property().equals(item.property()) &&\n\t\t\tthis.name() === item.name());\n\t},\n\n\tnamespace: function() {\n\t\treturn this._namespace;\n\t},\n\n\tproperty: function() {\n\t\treturn this._property;\n\t},\n\n\tname: function() {\n\t\treturn ORYX.Core.StencilSet.getTranslation(this._jsonItem, \"name\");\n\t},\n\t\n\tid: function() {\n\t\treturn this._jsonItem.id;\n\t},\n\t\n\ttype: function() {\n\t\treturn this._jsonItem.type;\n\t},\n\t\n\toptional: function() {\n\t\treturn this._jsonItem.optional;\n\t},\n\t\n\twidth: function() {\n\t\treturn this._jsonItem.width;\n\t},\n\t\n\tvalue: function() {\n\t\treturn this._jsonItem.value;\n\t},\n\t\n\titems: function() {\n\t\treturn this._items.values();\n\t},\n\t\n\tcomplexItems: function() {\n\t\treturn this._complexItems.values();\n\t},\n\t\n\tdisable: function() {\n\t\treturn this._jsonItem.disable;\n\t}\n});/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespaces\n */\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\nif(!ORYX.Core.StencilSet) {ORYX.Core.StencilSet = {};}\n\n/**\n * Class Rules uses Prototpye 1.5.0 uses Inheritance\n * \n * This class implements the API to check the stencil sets' rules.\n */\nORYX.Core.StencilSet.Rules = {\n\n\t/**\n\t * Constructor\n\t */\n\tconstruct: function() {\n\t\targuments.callee.$.construct.apply(this, arguments);\n\n\t\tthis._stencilSets = [];\n\t\tthis._stencils = [];\n\t\tthis._containerStencils = [];\n\t\t\n\t\tthis._cachedConnectSET = new Hash();\n\t\tthis._cachedConnectSE = new Hash();\n\t\tthis._cachedConnectTE = new Hash();\n\t\tthis._cachedCardSE = new Hash();\n\t\tthis._cachedCardTE = new Hash();\n\t\tthis._cachedContainPC = new Hash();\n\t\tthis._cachedMorphRS = new Hash();\n\t\t\n\t\tthis._connectionRules = new Hash();\n\t\tthis._cardinalityRules = new Hash();\n\t\tthis._containmentRules = new Hash();\n\t\tthis._morphingRules = new Hash();\n\t\tthis._layoutRules = new Hash();\n\t},\n\t\n\t/**\n\t * Call this method to initialize the rules for a stencil set and all of its\n\t * active extensions.\n\t * \n\t * @param {Object}\n\t *            stencilSet\n\t */\n\tinitializeRules: function(stencilSet) {\n\t\t\n\t\tvar existingSS = this._stencilSets.find(function(ss) {\n\t\t\t\t\t\t\treturn (ss.namespace() == stencilSet.namespace());\n\t\t\t\t\t\t});\n\t\tif (existingSS) {\n\t\t\t// reinitialize all rules\n\t\t\tvar stencilsets = this._stencilSets.clone();\n\t\t\tstencilsets = stencilsets.without(existingSS);\n\t\t\tstencilsets.push(stencilSet);\n\t\t\t\n\t\t\tthis._stencilSets = [];\n\t\t\tthis._stencils = [];\n\t\t\tthis._containerStencils = [];\n\t\t\t\n\t\t\tthis._cachedConnectSET = new Hash();\n\t\t\tthis._cachedConnectSE = new Hash();\n\t\t\tthis._cachedConnectTE = new Hash();\n\t\t\tthis._cachedCardSE = new Hash();\n\t\t\tthis._cachedCardTE = new Hash();\n\t\t\tthis._cachedContainPC = new Hash();\n\t\t\tthis._cachedMorphRS = new Hash();\n\t\t\t\n\t\t\tthis._connectionRules = new Hash();\n\t\t\tthis._cardinalityRules = new Hash();\n\t\t\tthis._containmentRules = new Hash();\n\t\t\tthis._morphingRules = new Hash();\n\t\t\tthis._layoutRules = new Hash();\n\t\t\t\n\t\t\tstencilsets.each(function(ss){\n\t\t\t\tthis.initializeRules(ss);\n\t\t\t}.bind(this));\n\t\t\treturn;\n\t\t}\n\t\telse {\n\t\t\tthis._stencilSets.push(stencilSet);\n\t\t\t\n\t\t\tvar jsonRules = new Hash(stencilSet.jsonRules());\n\t\t\tvar namespace = stencilSet.namespace();\n\t\t\tvar stencils = stencilSet.stencils();\n\t\t\t\n\t\t\tstencilSet.extensions().values().each(function(extension) {\n\t\t\t\tif(extension.rules) {\n\t\t\t\t\tif(extension.rules.connectionRules)\n\t\t\t\t\t\tjsonRules.connectionRules = jsonRules.connectionRules.concat(extension.rules.connectionRules);\n\t\t\t\t\tif(extension.rules.cardinalityRules)\n\t\t\t\t\t\tjsonRules.cardinalityRules = jsonRules.cardinalityRules.concat(extension.rules.cardinalityRules);\n\t\t\t\t\tif(extension.rules.containmentRules)\n\t\t\t\t\t\tjsonRules.containmentRules = jsonRules.containmentRules.concat(extension.rules.containmentRules);\n\t\t\t\t\tif(extension.rules.morphingRules)\n\t\t\t\t\t\tjsonRules.morphingRules = jsonRules.morphingRules.concat(extension.rules.morphingRules);\n\t\t\t\t}\n\t\t\t\tif(extension.stencils) \n\t\t\t\t\tstencils = stencils.concat(extension.stencils);\n\t\t\t});\n\t\t\t\n\t\t\tthis._stencils = this._stencils.concat(stencilSet.stencils());\n\t\t\t\n\t\t\t// init connection rules\n\t\t\tvar cr = this._connectionRules;\n\t\t\tif (jsonRules.connectionRules) {\n\t\t\t\tjsonRules.connectionRules.each((function(rules){\n\t\t\t\t\tif (this._isRoleOfOtherNamespace(rules.role)) {\n\t\t\t\t\t\tif (!cr[rules.role]) {\n\t\t\t\t\t\t\tcr[rules.role] = new Hash();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tif (!cr[namespace + rules.role]) \n\t\t\t\t\t\t\tcr[namespace + rules.role] = new Hash();\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\trules.connects.each((function(connect){\n\t\t\t\t\t\tvar toRoles = [];\n\t\t\t\t\t\tif (connect.to) {\n\t\t\t\t\t\t\tif (!(connect.to instanceof Array)) {\n\t\t\t\t\t\t\t\tconnect.to = [connect.to];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconnect.to.each((function(to){\n\t\t\t\t\t\t\t\tif (this._isRoleOfOtherNamespace(to)) {\n\t\t\t\t\t\t\t\t\ttoRoles.push(to);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\ttoRoles.push(namespace + to);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}).bind(this));\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tvar role, from;\n\t\t\t\t\t\tif (this._isRoleOfOtherNamespace(rules.role)) \n\t\t\t\t\t\t\trole = rules.role;\n\t\t\t\t\t\telse \n\t\t\t\t\t\t\trole = namespace + rules.role;\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (this._isRoleOfOtherNamespace(connect.from)) \n\t\t\t\t\t\t\tfrom = connect.from;\n\t\t\t\t\t\telse \n\t\t\t\t\t\t\tfrom = namespace + connect.from;\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (!cr[role][from]) \n\t\t\t\t\t\t\tcr[role][from] = toRoles;\n\t\t\t\t\t\telse \n\t\t\t\t\t\t\tcr[role][from] = cr[role][from].concat(toRoles);\n\t\t\t\t\t\t\n\t\t\t\t\t}).bind(this));\n\t\t\t\t}).bind(this));\n\t\t\t}\n\t\t\t\n\t\t\t// init cardinality rules\n\t\t\tvar cardr = this._cardinalityRules;\n\t\t\tif (jsonRules.cardinalityRules) {\n\t\t\t\tjsonRules.cardinalityRules.each((function(rules){\n\t\t\t\t\tvar cardrKey;\n\t\t\t\t\tif (this._isRoleOfOtherNamespace(rules.role)) {\n\t\t\t\t\t\tcardrKey = rules.role;\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tcardrKey = namespace + rules.role;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif (!cardr[cardrKey]) {\n\t\t\t\t\t\tcardr[cardrKey] = {};\n\t\t\t\t\t\tfor (i in rules) {\n\t\t\t\t\t\t\tcardr[cardrKey][i] = rules[i];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tvar oe = new Hash();\n\t\t\t\t\tif (rules.outgoingEdges) {\n\t\t\t\t\t\trules.outgoingEdges.each((function(rule){\n\t\t\t\t\t\t\tif (this._isRoleOfOtherNamespace(rule.role)) {\n\t\t\t\t\t\t\t\toe[rule.role] = rule;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\toe[namespace + rule.role] = rule;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}).bind(this));\n\t\t\t\t\t}\n\t\t\t\t\tcardr[cardrKey].outgoingEdges = oe;\n\t\t\t\t\tvar ie = new Hash();\n\t\t\t\t\tif (rules.incomingEdges) {\n\t\t\t\t\t\trules.incomingEdges.each((function(rule){\n\t\t\t\t\t\t\tif (this._isRoleOfOtherNamespace(rule.role)) {\n\t\t\t\t\t\t\t\tie[rule.role] = rule;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tie[namespace + rule.role] = rule;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}).bind(this));\n\t\t\t\t\t}\n\t\t\t\t\tcardr[cardrKey].incomingEdges = ie;\n\t\t\t\t}).bind(this));\n\t\t\t}\n\t\t\t\n\t\t\t// init containment rules\n\t\t\tvar conr = this._containmentRules;\n\t\t\tif (jsonRules.containmentRules) {\n\t\t\t\tjsonRules.containmentRules.each((function(rules){\n\t\t\t\t\tvar conrKey;\n\t\t\t\t\tif (this._isRoleOfOtherNamespace(rules.role)) {\n\t\t\t\t\t\tconrKey = rules.role;\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tthis._containerStencils.push(namespace + rules.role);\n\t\t\t\t\t\tconrKey = namespace + rules.role;\n\t\t\t\t\t}\n\t\t\t\t\tif (!conr[conrKey]) {\n\t\t\t\t\t\tconr[conrKey] = [];\n\t\t\t\t\t}\n\t\t\t\t\t(rules.contains||[]).each((function(containRole){\n\t\t\t\t\t\tif (this._isRoleOfOtherNamespace(containRole)) {\n\t\t\t\t\t\t\tconr[conrKey].push(containRole);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tconr[conrKey].push(namespace + containRole);\n\t\t\t\t\t\t}\n\t\t\t\t\t}).bind(this));\n\t\t\t\t}).bind(this));\n\t\t\t}\n\t\t\t\n\t\t\t// init morphing rules\n\t\t\tvar morphr = this._morphingRules;\n\t\t\tif (jsonRules.morphingRules) {\n\t\t\t\tjsonRules.morphingRules.each((function(rules){\n\t\t\t\t\tvar morphrKey;\n\t\t\t\t\tif (this._isRoleOfOtherNamespace(rules.role)) {\n\t\t\t\t\t\tmorphrKey = rules.role;\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tmorphrKey = namespace + rules.role;\n\t\t\t\t\t}\n\t\t\t\t\tif (!morphr[morphrKey]) {\n\t\t\t\t\t\tmorphr[morphrKey] = [];\n\t\t\t\t\t}\n\t\t\t\t\tif(!rules.preserveBounds) {\n\t\t\t\t\t\trules.preserveBounds = false;\n\t\t\t\t\t}\n\t\t\t\t\trules.baseMorphs.each((function(baseMorphStencilId){\n\t\t\t\t\t\tvar morphStencil = this._getStencilById(namespace + baseMorphStencilId);\n\t\t\t\t\t\tif(morphStencil) {\n\t\t\t\t\t\t\tmorphr[morphrKey].push(morphStencil);\n\t\t\t\t\t\t}\n\t\t\t\t\t}).bind(this));\n\t\t\t\t}).bind(this));\n\t\t\t}\n\t\t\t\n\t\t\t// init layouting rules\n\t\t\tvar layoutRules = this._layoutRules;\n\t\t\tif (jsonRules.layoutRules) {\n\t\t\t\t\n\t\t\t\tvar getDirections = function(o){\n\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\"edgeRole\":o.edgeRole||undefined,\n\t\t\t\t\t\t\t\"t\": o[\"t\"]||1,\n\t\t\t\t\t\t\t\"r\": o[\"r\"]||1,\n\t\t\t\t\t\t\t\"b\": o[\"b\"]||1,\n\t\t\t\t\t\t\t\"l\": o[\"l\"]||1\n\t\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tjsonRules.layoutRules.each(function(rules){\n\t\t\t\t\tvar layoutKey;\n\t\t\t\t\tif (this._isRoleOfOtherNamespace(rules.role)) {\n\t\t\t\t\t\tlayoutKey = rules.role;\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tlayoutKey = namespace + rules.role;\n\t\t\t\t\t}\n\t\t\t\t\tif (!layoutRules[layoutKey]) {\n\t\t\t\t\t\tlayoutRules[layoutKey] = {};\n\t\t\t\t\t}\n\t\t\t\t\tif (rules[\"in\"]){\n\t\t\t\t\t\tlayoutRules[layoutKey][\"in\"] = getDirections(rules[\"in\"]);\n\t\t\t\t\t}\n\t\t\t\t\tif (rules[\"ins\"]){\n\t\t\t\t\t\tlayoutRules[layoutKey][\"ins\"] = (rules[\"ins\"]||[]).map(function(e){ return getDirections(e) })\n\t\t\t\t\t}\n\t\t\t\t\tif (rules[\"out\"]) {\n\t\t\t\t\t\tlayoutRules[layoutKey][\"out\"] = getDirections(rules[\"out\"]);\n\t\t\t\t\t}\n\t\t\t\t\tif (rules[\"outs\"]){\n\t\t\t\t\t\tlayoutRules[layoutKey][\"outs\"] = (rules[\"outs\"]||[]).map(function(e){ return getDirections(e) })\n\t\t\t\t\t}\n\t\t\t\t}.bind(this));\n\t\t\t}\t\t\t\n\t\t}\n\t},\n\t\n\t_getStencilById: function(id) {\n\t\treturn this._stencils.find(function(stencil) {\n\t\t\treturn stencil.id()==id;\n\t\t});\n\t},\n\t\n\t_cacheConnect: function(args) {\n\t\tresult = this._canConnect(args);\n\t\t\n\t\tif (args.sourceStencil && args.targetStencil) {\n\t\t\tvar source = this._cachedConnectSET[args.sourceStencil.id()];\n\t\t\t\n\t\t\tif(!source) {\n\t\t\t\tsource = new Hash();\n\t\t\t\tthis._cachedConnectSET[args.sourceStencil.id()] = source;\n\t\t\t}\n\t\t\t\n\t\t\tvar edge = source[args.edgeStencil.id()];\n\t\t\t\n\t\t\tif(!edge) {\n\t\t\t\tedge = new Hash();\n\t\t\t\tsource[args.edgeStencil.id()] = edge;\n\t\t\t}\n\t\t\t\n\t\t\tedge[args.targetStencil.id()] = result;\n\t\t\t\n\t\t} else if (args.sourceStencil) {\n\t\t\tvar source = this._cachedConnectSE[args.sourceStencil.id()];\n\t\t\t\n\t\t\tif(!source) {\n\t\t\t\tsource = new Hash();\n\t\t\t\tthis._cachedConnectSE[args.sourceStencil.id()] = source;\n\t\t\t}\n\t\t\t\n\t\t\tsource[args.edgeStencil.id()] = result;\n\n\t\t} else {\n\t\t\tvar target = this._cachedConnectTE[args.targetStencil.id()];\n\t\t\t\n\t\t\tif(!target) {\n\t\t\t\ttarget = new Hash();\n\t\t\t\tthis._cachedConnectTE[args.targetStencil.id()] = target;\n\t\t\t}\n\t\t\t\n\t\t\ttarget[args.edgeStencil.id()] = result;\n\t\t}\n\t\t\n\t\treturn result;\n\t},\n\t\n\t_cacheCard: function(args) {\n\t\t\t\n\t\tif(args.sourceStencil) {\n\t\t\tvar source = this._cachedCardSE[args.sourceStencil.id()]\n\t\t\t\n\t\t\tif(!source) {\n\t\t\t\tsource = new Hash();\n\t\t\t\tthis._cachedCardSE[args.sourceStencil.id()] = source;\n\t\t\t}\n\t\t\t\n\t\t\tvar max = this._getMaximumNumberOfOutgoingEdge(args);\n\t\t\tif(max == undefined)\n\t\t\t\tmax = -1;\n\t\t\t\t\n\t\t\tsource[args.edgeStencil.id()] = max;\n\t\t}\t\n\t\t\n\t\tif(args.targetStencil) {\n\t\t\tvar target = this._cachedCardTE[args.targetStencil.id()]\n\t\t\t\n\t\t\tif(!target) {\n\t\t\t\ttarget = new Hash();\n\t\t\t\tthis._cachedCardTE[args.targetStencil.id()] = target;\n\t\t\t}\n\t\t\t\n\t\t\tvar max = this._getMaximumNumberOfIncomingEdge(args);\n\t\t\tif(max == undefined)\n\t\t\t\tmax = -1;\n\t\t\t\t\n\t\t\ttarget[args.edgeStencil.id()] = max;\n\t\t}\n\t},\n\t\n\t_cacheContain: function(args) {\n\t\t\n\t\tvar result = [this._canContain(args), \n\t\t\t\t\t  this._getMaximumOccurrence(args.containingStencil, args.containedStencil)]\n\t\t\n\t\tif(result[1] == undefined) \n\t\t\tresult[1] = -1;\n\t\t\n\t\tvar children = this._cachedContainPC[args.containingStencil.id()];\n\t\t\n\t\tif(!children) {\n\t\t\tchildren = new Hash();\n\t\t\tthis._cachedContainPC[args.containingStencil.id()] = children;\n\t\t}\n\t\t\n\t\tchildren[args.containedStencil.id()] = result;\n\t\t\n\t\treturn result;\n\t},\n\t\n\t/**\n\t * Returns all stencils belonging to a morph group. (calculation result is\n\t * cached)\n\t */\n\t_cacheMorph: function(role) {\n\t\t\n\t\tvar morphs = this._cachedMorphRS[role];\n\t\t\n\t\tif(!morphs) {\n\t\t\tmorphs = [];\n\t\t\t\n\t\t\tif(this._morphingRules.keys().include(role)) {\n\t\t\t\tmorphs = this._stencils.select(function(stencil) {\n\t\t\t\t\treturn stencil.roles().include(role);\n\t\t\t\t});\n\t\t\t}\n\t\t\t\n\t\t\tthis._cachedMorphRS[role] = morphs;\n\t\t}\n\t\treturn morphs;\n\t},\n\t\n\t/** Begin connection rules' methods */\n\t\n\t/**\n\t * \n\t * @param {Object}\n\t *            args sourceStencil: ORYX.Core.StencilSet.Stencil | undefined\n\t *            sourceShape: ORYX.Core.Shape | undefined\n\t * \n\t * At least sourceStencil or sourceShape has to be specified\n\t * \n\t * @return {Array} Array of stencils of edges that can be outgoing edges of\n\t *         the source.\n\t */\n\toutgoingEdgeStencils: function(args) {\n\t\t// check arguments\n\t\tif(!args.sourceShape && !args.sourceStencil) {\n\t\t\treturn [];\n\t\t}\n\t\t\n\t\t// init arguments\n\t\tif(args.sourceShape) {\n\t\t\targs.sourceStencil = args.sourceShape.getStencil();\n\t\t}\n\t\t\n\t\tvar _edges = [];\n\t\t\n\t\t// test each edge, if it can connect to source\n\t\tthis._stencils.each((function(stencil) {\n\t\t\tif(stencil.type() === \"edge\") {\n\t\t\t\tvar newArgs = Object.clone(args);\n\t\t\t\tnewArgs.edgeStencil = stencil;\n\t\t\t\tif(this.canConnect(newArgs)) {\n\t\t\t\t\t_edges.push(stencil);\n\t\t\t\t}\n\t\t\t}\n\t\t}).bind(this));\n\n\t\treturn _edges;\n\t},\n\n\t/**\n\t * \n\t * @param {Object}\n\t *            args targetStencil: ORYX.Core.StencilSet.Stencil | undefined\n\t *            targetShape: ORYX.Core.Shape | undefined\n\t * \n\t * At least targetStencil or targetShape has to be specified\n\t * \n\t * @return {Array} Array of stencils of edges that can be incoming edges of\n\t *         the target.\n\t */\n\tincomingEdgeStencils: function(args) {\n\t\t// check arguments\n\t\tif(!args.targetShape && !args.targetStencil) {\n\t\t\treturn [];\n\t\t}\n\t\t\n\t\t// init arguments\n\t\tif(args.targetShape) {\n\t\t\targs.targetStencil = args.targetShape.getStencil();\n\t\t}\n\t\t\n\t\tvar _edges = [];\n\t\t\n\t\t// test each edge, if it can connect to source\n\t\tthis._stencils.each((function(stencil) {\n\t\t\tif(stencil.type() === \"edge\") {\n\t\t\t\tvar newArgs = Object.clone(args);\n\t\t\t\tnewArgs.edgeStencil = stencil;\n\t\t\t\tif(this.canConnect(newArgs)) {\n\t\t\t\t\t_edges.push(stencil);\n\t\t\t\t}\n\t\t\t}\n\t\t}).bind(this));\n\n\t\treturn _edges;\n\t},\n\t\n\t/**\n\t * \n\t * @param {Object}\n\t *            args edgeStencil: ORYX.Core.StencilSet.Stencil | undefined\n\t *            edgeShape: ORYX.Core.Edge | undefined targetStencil:\n\t *            ORYX.Core.StencilSet.Stencil | undefined targetShape:\n\t *            ORYX.Core.Node | undefined\n\t * \n\t * At least edgeStencil or edgeShape has to be specified!!!\n\t * \n\t * @return {Array} Returns an array of stencils that can be source of the\n\t *         specified edge.\n\t */\n\tsourceStencils: function(args) {\n\t\t// check arguments\n\t\tif(!args || \n\t\t   !args.edgeShape && !args.edgeStencil) {\n\t\t\treturn [];\n\t\t}\n\t\t\n\t\t// init arguments\n\t\tif(args.targetShape) {\n\t\t\targs.targetStencil = args.targetShape.getStencil();\n\t\t}\n\t\t\n\t\tif(args.edgeShape) {\n\t\t\targs.edgeStencil = args.edgeShape.getStencil();\n\t\t}\n\t\t\n\t\tvar _sources = [];\n\t\t\n\t\t// check each stencil, if it can be a source\n\t\tthis._stencils.each((function(stencil) {\n\t\t\tvar newArgs = Object.clone(args);\n\t\t\tnewArgs.sourceStencil = stencil;\n\t\t\tif(this.canConnect(newArgs)) {\n\t\t\t\t_sources.push(stencil);\n\t\t\t}\n\t\t}).bind(this));\n\n\t\treturn _sources;\n\t},\n\t\n\t/**\n\t * \n\t * @param {Object}\n\t *            args edgeStencil: ORYX.Core.StencilSet.Stencil | undefined\n\t *            edgeShape: ORYX.Core.Edge | undefined sourceStencil:\n\t *            ORYX.Core.StencilSet.Stencil | undefined sourceShape:\n\t *            ORYX.Core.Node | undefined\n\t * \n\t * At least edgeStencil or edgeShape has to be specified!!!\n\t * \n\t * @return {Array} Returns an array of stencils that can be target of the\n\t *         specified edge.\n\t */\n\ttargetStencils: function(args) {\n\t\t// check arguments\n\t\tif(!args || \n\t\t   !args.edgeShape && !args.edgeStencil) {\n\t\t\treturn [];\n\t\t}\n\t\t\n\t\t// init arguments\n\t\tif(args.sourceShape) {\n\t\t\targs.sourceStencil = args.sourceShape.getStencil();\n\t\t}\n\t\t\n\t\tif(args.edgeShape) {\n\t\t\targs.edgeStencil = args.edgeShape.getStencil();\n\t\t}\n\t\t\n\t\tvar _targets = [];\n\t\t\n\t\t// check stencil, if it can be a target\n\t\tthis._stencils.each((function(stencil) {\n\t\t\tvar newArgs = Object.clone(args);\n\t\t\tnewArgs.targetStencil = stencil;\n\t\t\tif(this.canConnect(newArgs)) {\n\t\t\t\t_targets.push(stencil);\n\t\t\t}\n\t\t}).bind(this));\n\n\t\treturn _targets;\n\t},\n\n\t/**\n\t * \n\t * @param {Object}\n\t *            args edgeStencil: ORYX.Core.StencilSet.Stencil edgeShape:\n\t *            ORYX.Core.Edge |undefined sourceStencil:\n\t *            ORYX.Core.StencilSet.Stencil | undefined sourceShape:\n\t *            ORYX.Core.Node |undefined targetStencil:\n\t *            ORYX.Core.StencilSet.Stencil | undefined targetShape:\n\t *            ORYX.Core.Node |undefined\n\t * \n\t * At least source or target has to be specified!!!\n\t * \n\t * @return {Boolean} Returns, if the edge can connect source and target.\n\t */\n\tcanConnect: function(args) {\t\n\t\t// check arguments\n\t\tif(!args ||\n\t\t   (!args.sourceShape && !args.sourceStencil &&\n\t\t    !args.targetShape && !args.targetStencil) ||\n\t\t    !args.edgeShape && !args.edgeStencil) {\n\t\t   \treturn false; \n\t\t}\n\t\t\n\t\t// init arguments\n\t\tif(args.sourceShape) {\n\t\t\targs.sourceStencil = args.sourceShape.getStencil();\n\t\t}\n\t\tif(args.targetShape) {\n\t\t\targs.targetStencil = args.targetShape.getStencil();\n\t\t}\n\t\tif(args.edgeShape) {\n\t\t\targs.edgeStencil = args.edgeShape.getStencil();\n\t\t}\n\t\t\n\t\tvar result;\n\t\t\n\t\tif(args.sourceStencil && args.targetStencil) {\n\t\t\tvar source = this._cachedConnectSET[args.sourceStencil.id()];\n\t\t\t\n\t\t\tif(!source)\n\t\t\t\tresult = this._cacheConnect(args);\n\t\t\telse {\n\t\t\t\tvar edge = source[args.edgeStencil.id()];\n\n\t\t\t\tif(!edge)\n\t\t\t\t\tresult = this._cacheConnect(args);\n\t\t\t\telse {\t\n\t\t\t\t\tvar target = edge[args.targetStencil.id()];\n\n\t\t\t\t\tif(target == undefined)\n\t\t\t\t\t\tresult = this._cacheConnect(args);\n\t\t\t\t\telse\n\t\t\t\t\t\tresult = target;\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (args.sourceStencil) {\t\n\t\t\tvar source = this._cachedConnectSE[args.sourceStencil.id()];\n\t\t\t\n\t\t\tif(!source)\n\t\t\t\tresult = this._cacheConnect(args);\n\t\t\telse {\n\t\t\t\tvar edge = source[args.edgeStencil.id()];\n\t\t\t\t\t\n\t\t\t\tif(edge == undefined)\n\t\t\t\t\tresult = this._cacheConnect(args);\n\t\t\t\telse\n\t\t\t\t\tresult = edge;\n\t\t\t}\n\t\t} else { // args.targetStencil\n\t\t\tvar target = this._cachedConnectTE[args.targetStencil.id()];\n\t\t\t\n\t\t\tif(!target)\n\t\t\t\tresult = this._cacheConnect(args);\n\t\t\telse {\n\t\t\t\tvar edge = target[args.edgeStencil.id()];\n\t\t\t\t\t\n\t\t\t\tif(edge == undefined)\n\t\t\t\t\tresult = this._cacheConnect(args);\n\t\t\t\telse\n\t\t\t\t\tresult = edge;\n\t\t\t}\n\t\t}\t\n\t\t\t\n\t\t// check cardinality\n\t\tif (result) {\n\t\t\tif(args.sourceShape) {\n\t\t\t\tvar source = this._cachedCardSE[args.sourceStencil.id()];\n\t\t\t\t\n\t\t\t\tif(!source) {\n\t\t\t\t\tthis._cacheCard(args);\n\t\t\t\t\tsource = this._cachedCardSE[args.sourceStencil.id()];\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tvar max = source[args.edgeStencil.id()];\n\t\t\t\t\n\t\t\t\tif(max == undefined) {\n\t\t\t\t\tthis._cacheCard(args);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tmax = source[args.edgeStencil.id()];\n\t\t\t\t\n\t\t\t\tif(max != -1) {\n\t\t\t\t\tresult = args.sourceShape.getOutgoingShapes().all(function(cs) {\n\t\t\t\t\t\t\t\tif((cs.getStencil().id() === args.edgeStencil.id()) && \n\t\t\t\t\t\t\t\t   ((args.edgeShape) ? cs !== args.edgeShape : true)) {\n\t\t\t\t\t\t\t\t\tmax--;\n\t\t\t\t\t\t\t\t\treturn (max > 0) ? true : false;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} \n\t\t\t\n\t\t\tif (args.targetShape) {\n\t\t\t\tvar target = this._cachedCardTE[args.targetStencil.id()];\n\t\t\t\t\n\t\t\t\tif(!target) {\n\t\t\t\t\tthis._cacheCard(args);\n\t\t\t\t\ttarget = this._cachedCardTE[args.targetStencil.id()];\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tvar max = target[args.edgeStencil.id()];\n\t\t\t\t\n\t\t\t\tif(max == undefined) {\n\t\t\t\t\tthis._cacheCard(args);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tmax = target[args.edgeStencil.id()];\n\t\t\t\t\n\t\t\t\tif(max != -1) {\n\t\t\t\t\tresult = args.targetShape.getIncomingShapes().all(function(cs){\n\t\t\t\t\t\t\t\tif ((cs.getStencil().id() === args.edgeStencil.id()) &&\n\t\t\t\t\t\t\t\t((args.edgeShape) ? cs !== args.edgeShape : true)) {\n\t\t\t\t\t\t\t\t\tmax--;\n\t\t\t\t\t\t\t\t\treturn (max > 0) ? true : false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn result;\n\t},\n\t\n\t/**\n\t * \n\t * @param {Object}\n\t *            args edgeStencil: ORYX.Core.StencilSet.Stencil edgeShape:\n\t *            ORYX.Core.Edge |undefined sourceStencil:\n\t *            ORYX.Core.StencilSet.Stencil | undefined sourceShape:\n\t *            ORYX.Core.Node |undefined targetStencil:\n\t *            ORYX.Core.StencilSet.Stencil | undefined targetShape:\n\t *            ORYX.Core.Node |undefined\n\t * \n\t * At least source or target has to be specified!!!\n\t * \n\t * @return {Boolean} Returns, if the edge can connect source and target.\n\t */\n\t_canConnect: function(args) {\n\t\t// check arguments\n\t\tif(!args ||\n\t\t   (!args.sourceShape && !args.sourceStencil &&\n\t\t    !args.targetShape && !args.targetStencil) ||\n\t\t    !args.edgeShape && !args.edgeStencil) {\n\t\t   \treturn false; \n\t\t}\n\t\t\n\t\t// init arguments\n\t\tif(args.sourceShape) {\n\t\t\targs.sourceStencil = args.sourceShape.getStencil();\n\t\t}\n\t\tif(args.targetShape) {\n\t\t\targs.targetStencil = args.targetShape.getStencil();\n\t\t}\n\t\tif(args.edgeShape) {\n\t\t\targs.edgeStencil = args.edgeShape.getStencil();\n\t\t}\n\n\t\t// 1. check connection rules\n\t\tvar resultCR;\n\t\t\n\t\t// get all connection rules for this edge\n\t\tvar edgeRules = this._getConnectionRulesOfEdgeStencil(args.edgeStencil);\n\n\t\t// check connection rules, if the source can be connected to the target\n\t\t// with the specified edge.\n\t\tif(edgeRules.keys().length === 0) {\n\t\t\tresultCR = false;\n\t\t} else {\n\t\t\tif(args.sourceStencil) {\n\t\t\t\tresultCR = args.sourceStencil.roles().any(function(sourceRole) {\n\t\t\t\t\tvar targetRoles = edgeRules[sourceRole];\n\n\t\t\t\t\tif(!targetRoles) {return false;}\n\t\t\n\t\t\t\t\tif(args.targetStencil) {\n\t\t\t\t\t\treturn (targetRoles.any(function(targetRole) {\n\t\t\t\t\t\t\treturn args.targetStencil.roles().member(targetRole);\n\t\t\t\t\t\t}));\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} else { // !args.sourceStencil -> there is args.targetStencil\n\t\t\t\tresultCR = edgeRules.values().any(function(targetRoles) {\n\t\t\t\t\treturn args.targetStencil.roles().any(function(targetRole) {\n\t\t\t\t\t\treturn targetRoles.member(targetRole);\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn resultCR;\n\t},\n\n\t/** End connection rules' methods */\n\n\n\t/** Begin containment rules' methods */\n\n\tisContainer: function(shape) {\n\t\treturn this._containerStencils.member(shape.getStencil().id());\n\t},\n\n\t/**\n\t * \n\t * @param {Object}\n\t *            args containingStencil: ORYX.Core.StencilSet.Stencil\n\t *            containingShape: ORYX.Core.AbstractShape containedStencil:\n\t *            ORYX.Core.StencilSet.Stencil containedShape: ORYX.Core.Shape\n\t */\n\tcanContain: function(args) {\n\t\tif(!args ||\n\t\t   !args.containingStencil && !args.containingShape ||\n\t\t   !args.containedStencil && !args.containedShape) {\n\t\t   \treturn false;\n\t\t}\n\t\t\n\t\t// init arguments\n\t\tif(args.containedShape) {\n\t\t\targs.containedStencil = args.containedShape.getStencil();\n\t\t}\n\t\t\n\t\tif(args.containingShape) {\n\t\t\targs.containingStencil = args.containingShape.getStencil();\n\t\t}\n\t\t\n\t\t//if(args.containingStencil.type() == 'edge' || args.containedStencil.type() == 'edge')\n\t\t//\treturn false;\n\t\tif(args.containedStencil.type() == 'edge') \n\t\t\treturn false;\n\t\t\n\t\tvar childValues;\n\t\t\n\t\tvar parent = this._cachedContainPC[args.containingStencil.id()];\n\t\t\n\t\tif(!parent)\n\t\t\tchildValues = this._cacheContain(args);\n\t\telse {\n\t\t\tchildValues = parent[args.containedStencil.id()];\n\t\t\t\n\t\t\tif(!childValues)\n\t\t\t\tchildValues = this._cacheContain(args);\n\t\t}\n\n\t\tif(!childValues[0])\n\t\t\treturn false;\n\t\telse if (childValues[1] == -1)\n\t\t\treturn true;\n\t\telse {\n\t\t\tif(args.containingShape) {\n\t\t\t\tvar max = childValues[1];\n\t\t\t\treturn args.containingShape.getChildShapes(false).all(function(as) {\n\t\t\t\t\tif(as.getStencil().id() === args.containedStencil.id()) {\n\t\t\t\t\t\tmax--;\n\t\t\t\t\t\treturn (max > 0) ? true : false;\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t},\n\t\n\t/**\n\t * \n\t * @param {Object}\n\t *            args containingStencil: ORYX.Core.StencilSet.Stencil\n\t *            containingShape: ORYX.Core.AbstractShape containedStencil:\n\t *            ORYX.Core.StencilSet.Stencil containedShape: ORYX.Core.Shape\n\t */\n\t_canContain: function(args) {\n\t\tif(!args ||\n\t\t   !args.containingStencil && !args.containingShape ||\n\t\t   !args.containedStencil && !args.containedShape) {\n\t\t   \treturn false;\n\t\t}\n\t\t\n\t\t// init arguments\n\t\tif(args.containedShape) {\n\t\t\targs.containedStencil = args.containedShape.getStencil();\n\t\t}\n\t\t\n\t\tif(args.containingShape) {\n\t\t\targs.containingStencil = args.containingShape.getStencil();\n\t\t}\n\t\t\n//\t\tif(args.containingShape) {\n//\t\t\tif(args.containingShape instanceof ORYX.Core.Edge) {\n//\t\t\t\t// edges cannot contain other shapes\n//\t\t\t\treturn false;\n//\t\t\t}\n//\t\t}\n\n\t\t\n\t\tvar result;\n\t\t\n\t\t// check containment rules\n\t\tresult = args.containingStencil.roles().any((function(role) {\n\t\t\tvar roles = this._containmentRules[role];\n\t\t\tif(roles) {\n\t\t\t\treturn roles.any(function(role) {\n\t\t\t\t\treturn args.containedStencil.roles().member(role);\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}).bind(this));\n\t\t\n\t\treturn result;\n\t},\n\t\n\t/** End containment rules' methods */\n\t\n\t\n\t/** Begin morphing rules' methods */\n\t\n\t/**\n\t * \n\t * @param {Object}\n\t *           args \n\t *            stencil: ORYX.Core.StencilSet.Stencil | undefined \n\t *            shape: ORYX.Core.Shape | undefined\n\t * \n\t * At least stencil or shape has to be specified\n\t * \n\t * @return {Array} Array of stencils that the passed stencil/shape can be\n\t *         transformed to (including the current stencil itself)\n\t */\n\tmorphStencils: function(args) {\n\t\t// check arguments\n\t\tif(!args.stencil && !args.shape) {\n\t\t\treturn [];\n\t\t}\n\t\t\n\t\t// init arguments\n\t\tif(args.shape) {\n\t\t\targs.stencil = args.shape.getStencil();\n\t\t}\n\t\t\n\t\tvar _morphStencils = [];\n\t\targs.stencil.roles().each(function(role) {\n\t\t\tthis._cacheMorph(role).each(function(stencil) {\n\t\t\t\t_morphStencils.push(stencil);\n\t\t\t})\n\t\t}.bind(this));\n\n\n\t\tvar baseMorphs = this.baseMorphs();\n\t\t// BaseMorphs should be in the front of the array\n\t\t_morphStencils = _morphStencils.uniq().sort(function(a,b){ return baseMorphs.include(a)&&!baseMorphs.include(b) ? -1 : (baseMorphs.include(b)&&!baseMorphs.include(a) ? 1 : 0)})\n\t\treturn _morphStencils;\n\t},\n\t\n\t/**\n\t * @return {Array} An array of all base morph stencils\n\t */\n\tbaseMorphs: function() {\n\t\tvar _baseMorphs = [];\n\t\tthis._morphingRules.each(function(pair) {\n\t\t\tpair.value.each(function(baseMorph) {\n\t\t\t\t_baseMorphs.push(baseMorph);\n\t\t\t});\n\t\t});\n\t\treturn _baseMorphs;\n\t},\n\t\n\t/**\n\t * Returns true if there are morphing rules defines\n\t * @return {boolean} \n\t */\n\tcontainsMorphingRules: function(){\n\t\treturn this._stencilSets.any(function(ss){ return !!ss.jsonRules().morphingRules});\n\t},\n\t\n\t/**\n\t * \n\t * @param {Object}\n\t *            args \n\t *            sourceStencil:\n\t *            ORYX.Core.StencilSet.Stencil | undefined \n\t *            sourceShape:\n\t *            ORYX.Core.Node |undefined \n\t *            targetStencil:\n\t *            ORYX.Core.StencilSet.Stencil | undefined \n\t *            targetShape:\n\t *            ORYX.Core.Node |undefined\n\t * \n\t * \n\t * @return {Stencil} Returns, the stencil for the connecting edge \n\t * or null if connection is not possible\n\t */\n\tconnectMorph: function(args) {\t\n\t\t// check arguments\n\t\tif(!args ||\n\t\t   (!args.sourceShape && !args.sourceStencil &&\n\t\t    !args.targetShape && !args.targetStencil)) {\n\t\t   \treturn false; \n\t\t}\n\t\t\n\t\t// init arguments\n\t\tif(args.sourceShape) {\n\t\t\targs.sourceStencil = args.sourceShape.getStencil();\n\t\t}\n\t\tif(args.targetShape) {\n\t\t\targs.targetStencil = args.targetShape.getStencil();\n\t\t}\n\t\t\n\t\tvar incoming = this.incomingEdgeStencils(args);\n\t\tvar outgoing = this.outgoingEdgeStencils(args);\n\t\t\n\t\tvar edgeStencils = incoming.select(function(e) { return outgoing.member(e); }); // intersection of sets\n\t\tvar baseEdgeStencils = this.baseMorphs().select(function(e) { return edgeStencils.member(e); }); // again: intersection of sets\n\t\t\n\t\tif(baseEdgeStencils.size()>0)\n\t\t\treturn baseEdgeStencils[0]; // return any of the possible base morphs\n\t\telse if(edgeStencils.size()>0)\n\t\t\treturn edgeStencils[0];\t// return any of the possible stencils\n\t\t\n\t\treturn null; //connection not possible\n\t},\n\t\n\t/**\n\t * Return true if the stencil should be located in the shape menu\n\t * @param {ORYX.Core.StencilSet.Stencil} morph\n\t * @return {Boolean} Returns true if the morphs in the morph group of the\n\t * specified morph shall be displayed in the shape menu\n\t */\n\tshowInShapeMenu: function(stencil) {\n\t\treturn \tthis._stencilSets.any(function(ss){\n\t\t\t\t    return ss.jsonRules().morphingRules\n\t\t\t\t\t\t\t.any(function(r){\n\t\t\t\t\t\t\t\treturn \tstencil.roles().include(ss.namespace() + r.role) \n\t\t\t\t\t\t\t\t\t\t&& r.showInShapeMenu !== false;\n\t\t\t\t\t\t\t})\n\t\t\t\t});\n\t},\n\t\n\tpreserveBounds: function(stencil) {\n\t\treturn this._stencilSets.any(function(ss) {\n\t\t\treturn ss.jsonRules().morphingRules.any(function(r) {\n\t\t\t\t\n\t\t\t\t\n\t\t\t\treturn stencil.roles().include(ss.namespace() + r.role) \n\t\t\t\t\t&& r.preserveBounds;\n\t\t\t})\n\t\t})\n\t},\n\t\n\t/** End morphing rules' methods */\n\n\n\t/** Begin layouting rules' methods */\n\t\n\t/**\n\t * Returns a set on \"in\" and \"out\" layouting rules for a given shape\n\t * @param {Object} shape\n\t * @param {Object} edgeShape (Optional)\n\t * @return {Object} \"in\" and \"out\" with a default value of {\"t\":1, \"r\":1, \"b\":1, \"r\":1} if not specified in the json\n\t */\n\tgetLayoutingRules : function(shape, edgeShape){\n\t\t\n\t\tif (!shape||!(shape instanceof ORYX.Core.Shape)){ return }\n\t\t\n\t\tvar layout = {\"in\":{},\"out\":{}};\n\t\t\n\t\tvar parseValues = function(o, v){\n\t\t\tif (o && o[v]){\n\t\t\t\t[\"t\",\"r\",\"b\",\"l\"].each(function(d){\n\t\t\t\t\tlayout[v][d]=Math.max(o[v][d],layout[v][d]||0);\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (o && o[v+\"s\"] instanceof Array){\n\t\t\t\t[\"t\",\"r\",\"b\",\"l\"].each(function(d){\n\t\t\t\t\tvar defaultRule = o[v+\"s\"].find(function(e){ return !e.edgeRole });\n\t\t\t\t\tvar edgeRule;\n\t\t\t\t\tif (edgeShape instanceof ORYX.Core.Edge) {\n\t\t\t\t\t\tedgeRule = o[v + \"s\"].find(function(e){return this._hasRole(edgeShape, e.edgeRole) }.bind(this));\n\t\t\t\t\t}\n\t\t\t\t\tlayout[v][d]=Math.max(edgeRule?edgeRule[d]:defaultRule[d],layout[v][d]||0);\n\t\t\t\t}.bind(this));\n\t\t\t}\n\t\t}.bind(this)\n\t\t\n\t\t// For each role\n\t\tshape.getStencil().roles().each(function(role) {\n\t\t\t// check if there are layout information\n\t\t\tif (this._layoutRules[role]){\n\t\t\t\t// if so, parse those information to the 'layout' variable\n\t\t\t\tparseValues(this._layoutRules[role], \"in\");\n\t\t\t\tparseValues(this._layoutRules[role], \"out\");\n\t\t\t}\n\t\t}.bind(this));\n\t\t\n\t\t// Make sure, that every attribute has an value,\n\t\t// otherwise set 1\n\t\t[\"in\",\"out\"].each(function(v){\n\t\t\t[\"t\",\"r\",\"b\",\"l\"].each(function(d){\n\t\t\t\t\tlayout[v][d]=layout[v][d]!==undefined?layout[v][d]:1;\n\t\t\t\t});\n\t\t})\n\t\t\n\t\treturn layout;\n\t},\n\t\n\t/** End layouting rules' methods */\n\t\n\t/** Helper methods */\n\n\t/**\n\t * Checks wether a shape contains the given role or the role is equal the stencil id \n\t * @param {ORYX.Core.Shape} shape\n\t * @param {String} role\n\t */\n\t_hasRole: function(shape, role){\n\t\tif (!(shape instanceof ORYX.Core.Shape)||!role){ return }\n\t\tvar isRole = shape.getStencil().roles().any(function(r){ return r == role});\n\t\t\n\t\treturn isRole || shape.getStencil().id() == (shape.getStencil().namespace()+role);\n\t},\n\n\t/**\n\t * \n\t * @param {String}\n\t *            role\n\t * \n\t * @return {Array} Returns an array of stencils that can act as role.\n\t */\n\t_stencilsWithRole: function(role) {\n\t\treturn this._stencils.findAll(function(stencil) {\n\t\t\treturn (stencil.roles().member(role)) ? true : false;\n\t\t});\n\t},\n\t\n\t/**\n\t * \n\t * @param {String}\n\t *            role\n\t * \n\t * @return {Array} Returns an array of stencils that can act as role and\n\t *         have the type 'edge'.\n\t */\n\t_edgesWithRole: function(role) {\n\t\treturn this._stencils.findAll(function(stencil) {\n\t\t\treturn (stencil.roles().member(role) && stencil.type() === \"edge\") ? true : false;\n\t\t});\n\t},\n\t\n\t/**\n\t * \n\t * @param {String}\n\t *            role\n\t * \n\t * @return {Array} Returns an array of stencils that can act as role and\n\t *         have the type 'node'.\n\t */\n\t_nodesWithRole: function(role) {\n\t\treturn this._stencils.findAll(function(stencil) {\n\t\t\treturn (stencil.roles().member(role) && stencil.type() === \"node\") ? true : false;\n\t\t});\n\t},\n\n\t/**\n\t * \n\t * @param {ORYX.Core.StencilSet.Stencil}\n\t *            parent\n\t * @param {ORYX.Core.StencilSet.Stencil}\n\t *            child\n\t * \n\t * @returns {Boolean} Returns the maximum occurrence of shapes of the\n\t *          stencil's type inside the parent.\n\t */\n\t_getMaximumOccurrence: function(parent, child) {\n\t\tvar max;\n\t\tchild.roles().each((function(role) {\n\t\t\tvar cardRule = this._cardinalityRules[role];\n\t\t\tif(cardRule && cardRule.maximumOccurrence) {\n\t\t\t\tif(max) {\n\t\t\t\t\tmax = Math.min(max, cardRule.maximumOccurrence);\n\t\t\t\t} else {\n\t\t\t\t\tmax = cardRule.maximumOccurrence;\n\t\t\t\t}\n\t\t\t}\n\t\t}).bind(this));\n\n\t\treturn max;\n\t},\n\n\n\t/**\n\t * \n\t * @param {Object}\n\t *            args sourceStencil: ORYX.Core.Node edgeStencil:\n\t *            ORYX.Core.StencilSet.Stencil\n\t * \n\t * @return {Boolean} Returns, the maximum number of outgoing edges of the\n\t *         type specified by edgeStencil of the sourceShape.\n\t */\n\t_getMaximumNumberOfOutgoingEdge: function(args) {\n\t\tif(!args ||\n\t\t   !args.sourceStencil ||\n\t\t   !args.edgeStencil) {\n\t\t   \treturn false;\n\t\t}\n\t\t\n\t\tvar max;\n\t\targs.sourceStencil.roles().each((function(role) {\n\t\t\tvar cardRule = this._cardinalityRules[role];\n\n\t\t\tif(cardRule && cardRule.outgoingEdges) {\n\t\t\t\targs.edgeStencil.roles().each(function(edgeRole) {\n\t\t\t\t\tvar oe = cardRule.outgoingEdges[edgeRole];\n\n\t\t\t\t\tif(oe && oe.maximum) {\n\t\t\t\t\t\tif(max) {\n\t\t\t\t\t\t\tmax = Math.min(max, oe.maximum);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tmax = oe.maximum;\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}).bind(this));\n\n\t\treturn max;\n\t},\n\t\n\t/**\n\t * \n\t * @param {Object}\n\t *            args targetStencil: ORYX.Core.StencilSet.Stencil edgeStencil:\n\t *            ORYX.Core.StencilSet.Stencil\n\t * \n\t * @return {Boolean} Returns the maximum number of incoming edges of the\n\t *         type specified by edgeStencil of the targetShape.\n\t */\n\t_getMaximumNumberOfIncomingEdge: function(args) {\n\t\tif(!args ||\n\t\t   !args.targetStencil ||\n\t\t   !args.edgeStencil) {\n\t\t   \treturn false;\n\t\t}\n\t\t\n\t\tvar max;\n\t\targs.targetStencil.roles().each((function(role) {\n\t\t\tvar cardRule = this._cardinalityRules[role];\n\t\t\tif(cardRule && cardRule.incomingEdges) {\n\t\t\t\targs.edgeStencil.roles().each(function(edgeRole) {\n\t\t\t\t\tvar ie = cardRule.incomingEdges[edgeRole];\n\t\t\t\t\tif(ie && ie.maximum) {\n\t\t\t\t\t\tif(max) {\n\t\t\t\t\t\t\tmax = Math.min(max, ie.maximum);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tmax = ie.maximum;\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}).bind(this));\n\n\t\treturn max;\n\t},\n\t\n\t/**\n\t * \n\t * @param {ORYX.Core.StencilSet.Stencil}\n\t *            edgeStencil\n\t * \n\t * @return {Hash} Returns a hash map of all connection rules for\n\t *         edgeStencil.\n\t */\n\t_getConnectionRulesOfEdgeStencil: function(edgeStencil) {\n\t\tvar edgeRules = new Hash();\n\t\tedgeStencil.roles().each((function(role) {\n\t\t\tif(this._connectionRules[role]) {\n\t\t\t\tthis._connectionRules[role].each(function(cr) {\n\t\t\t\t\tif(edgeRules[cr.key]) {\n\t\t\t\t\t\tedgeRules[cr.key] = edgeRules[cr.key].concat(cr.value);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tedgeRules[cr.key] = cr.value;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}).bind(this));\n\t\t\n\t\treturn edgeRules;\n\t},\n\t\n\t_isRoleOfOtherNamespace: function(role) {\n\t\treturn (role.indexOf(\"#\") > 0);\n\t},\n\n\ttoString: function() { return \"Rules\"; }\n}\nORYX.Core.StencilSet.Rules = Clazz.extend(ORYX.Core.StencilSet.Rules);\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespace\n */\nif (!ORYX) {\n    var ORYX = {};\n}\nif (!ORYX.Core) {\n    ORYX.Core = {};\n}\nif (!ORYX.Core.StencilSet) {\n    ORYX.Core.StencilSet = {};\n}\n\n/**\n * This class represents a stencil set. It offers methods for accessing\n *  the attributes of the stencil set description JSON file and the stencil set's\n *  stencils.\n */\nORYX.Core.StencilSet.StencilSet = Clazz.extend({\n\n    /**\n     * Constructor\n     * @param source {URL} A reference to the stencil set specification.\n     *\n     */\n    construct: function(source, modelMetaData, editorId){\n        arguments.callee.$.construct.apply(this, arguments);\n        \n        if (!source) {\n            throw \"ORYX.Core.StencilSet.StencilSet(construct): Parameter 'source' is not defined.\";\n        }\n        \n        if (source.endsWith(\"/\")) {\n            source = source.substr(0, source.length - 1);\n        }\n\t\t\n\t\tthis._extensions = new Hash();\n        \n        this._source = source;\n        this._baseUrl = source.substring(0, source.lastIndexOf(\"/\") + 1);\n        \n        this._jsonObject = {};\n        \n        this._stencils = new Hash();\n\t\tthis._availableStencils = new Hash();\n        \n\t\tif(ORYX.CONFIG.BACKEND_SWITCH) {\n\t\t\tthis._baseUrl = \"editor/stencilsets/bpmn2.0/\";\n\t\t\tthis._source = \"stencilsets/bpmn2.0/bpmn2.0.json\";\n\t\t\t\n\t\t\tnew Ajax.Request(ACTIVITI.CONFIG.contextRoot + '/editor/stencilset?version=' + Date.now(), {\n\t            asynchronous: false,\n\t            method: 'get',\n\t            onSuccess: this._init.bind(this),\n\t            onFailure: this._cancelInit.bind(this)\n\t        });\n\t\t\t\n\t\t} else {\n\t\t\tnew Ajax.Request(source, {\n\t            asynchronous: false,\n\t            method: 'get',\n\t            onSuccess: this._init.bind(this),\n\t            onFailure: this._cancelInit.bind(this)\n\t        });\n\t\t}\n        \n        if (this.errornous) \n            throw \"Loading stencil set \" + source + \" failed.\";\n    },\n    \n    /**\n     * Finds a root stencil in this stencil set. There may be many of these. If\n     * there are, the first one found will be used. In Firefox, this is the\n     * topmost definition in the stencil set description file.\n     */\n    findRootStencilName: function(){\n    \n        // find any stencil that may be root.\n        var rootStencil = this._stencils.values().find(function(stencil){\n            return stencil._jsonStencil.mayBeRoot\n        });\n        \n\t\t// if there is none, just guess the first.\n\t\tif (!rootStencil) {\n\t\t\tORYX.Log.warn(\"Did not find any stencil that may be root. Taking a guess.\");\n\t\t\trootStencil = this._stencils.values()[0];\n\t\t}\n\n        // return its id.\n        return rootStencil.id();\n    },\n    \n    /**\n     * @param {ORYX.Core.StencilSet.StencilSet} stencilSet\n     * @return {Boolean} True, if stencil set has the same namespace.\n     */\n    equals: function(stencilSet){\n        return (this.namespace() === stencilSet.namespace());\n    },\n    \n\t/**\n\t * \n\t * @param {Oryx.Core.StencilSet.Stencil} rootStencil If rootStencil is defined, it only returns stencils\n\t * \t\t\tthat could be (in)direct child of that stencil.\n\t */\n    stencils: function(rootStencil, rules, sortByGroup){\n\t\tif(rootStencil && rules) {\n\t\t\tvar stencils = this._availableStencils.values();\n\t\t\tvar containers = [rootStencil];\n\t\t\tvar checkedContainers = [];\n\t\t\t\n\t\t\tvar result = [];\n\t\t\t\n\t\t\twhile (containers.size() > 0) {\n\t\t\t\tvar container = containers.pop();\n\t\t\t\tcheckedContainers.push(container);\n\t\t\t\tvar children = stencils.findAll(function(stencil){\n\t\t\t\t\tvar args = {\n\t\t\t\t\t\tcontainingStencil: container,\n\t\t\t\t\t\tcontainedStencil: stencil\n\t\t\t\t\t};\n\t\t\t\t\treturn rules.canContain(args);\n\t\t\t\t});\n\t\t\t\tfor(var i = 0; i < children.size(); i++) {\n\t\t\t\t\tif (!checkedContainers.member(children[i])) {\n\t\t\t\t\t\tcontainers.push(children[i]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tresult = result.concat(children).uniq();\n\t\t\t}\n\t\t\t\n\t\t\t// Sort the result to the origin order\n\t\t\tresult = result.sortBy(function(stencil) {\n\t\t\t\treturn stencils.indexOf(stencil);\n\t\t\t});\n\t\t\t\n\t\t\t\n\t\t\tif(sortByGroup) {\n\t\t\t\tresult = result.sortBy(function(stencil) {\n\t\t\t\t\treturn stencil.groups().first();\n\t\t\t\t});\n\t\t\t}\n\t\t\t\n\t\t\tvar edges = stencils.findAll(function(stencil) {\n\t\t\t\treturn stencil.type() == \"edge\";\n\t\t\t});\n\t\t\tresult = result.concat(edges);\n\t\t\t\n\t\t\treturn result;\n\t\t\t\n\t\t} else {\n        \tif(sortByGroup) {\n\t\t\t\treturn this._availableStencils.values().sortBy(function(stencil) {\n\t\t\t\t\treturn stencil.groups().first();\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\treturn this._availableStencils.values();\n\t\t\t}\n\t\t}\n    },\n    \n    nodes: function(){\n        return this._availableStencils.values().findAll(function(stencil){\n            return (stencil.type() === 'node')\n        });\n    },\n    \n    edges: function(){\n        return this._availableStencils.values().findAll(function(stencil){\n            return (stencil.type() === 'edge')\n        });\n    },\n    \n    stencil: function(id){\n        return this._stencils[id];\n    },\n    \n    title: function(){\n        return ORYX.Core.StencilSet.getTranslation(this._jsonObject, \"title\");\n    },\n    \n    description: function(){\n        return ORYX.Core.StencilSet.getTranslation(this._jsonObject, \"description\");\n    },\n    \n    namespace: function(){\n        return this._jsonObject ? this._jsonObject.namespace : null;\n    },\n    \n    jsonRules: function(){\n        return this._jsonObject ? this._jsonObject.rules : null;\n    },\n    \n    source: function(){\n        return this._source;\n    },\n\t\n\textensions: function() {\n\t\treturn this._extensions;\n\t},\n\t\n\taddExtension: function(url) {\n\t\t\n\t\tnew Ajax.Request(url, {\n            method: 'GET',\n            asynchronous: false,\n\t\t\tonSuccess: (function(transport) {\n\t\t\t\tthis.addExtensionDirectly(transport.responseText);\n\t\t\t}).bind(this),\n\t\t\tonFailure: (function(transport) {\n\t\t\t\tORYX.Log.debug(\"Loading stencil set extension file failed. The request returned an error.\" + transport);\n\t\t\t}).bind(this),\n\t\t\tonException: (function(transport) {\n\t\t\t\tORYX.Log.debug(\"Loading stencil set extension file failed. The request returned an error.\" + transport);\n\t\t\t}).bind(this)\n\t\t\n\t\t});\n\t},\n\t\n\taddExtensionDirectly: function(str){\n\n\t\ttry {\n\t\t\teval(\"var jsonExtension = \" + str);\n\n\t\t\tif(!(jsonExtension[\"extends\"].endsWith(\"#\")))\n\t\t\t\t\tjsonExtension[\"extends\"] += \"#\";\n\t\t\t\t\t\n\t\t\tif(jsonExtension[\"extends\"] == this.namespace()) {\n\t\t\t\tthis._extensions[jsonExtension.namespace] = jsonExtension;\n\t\t\t\t\n\t\t\t\tvar defaultPosition = this._stencils.keys().size();\n\t\t\t\t//load new stencils\n\t\t\t\tif(jsonExtension.stencils) {\n\t\t\t\t\t$A(jsonExtension.stencils).each(function(stencil) {\n\t\t\t\t\t\tdefaultPosition++;\n\t\t\t\t\t\tvar oStencil = new ORYX.Core.StencilSet.Stencil(stencil, this.namespace(), this._baseUrl, this, undefined, defaultPosition);            \n\t\t\t\t\t\tthis._stencils[oStencil.id()] = oStencil;\n\t\t\t\t\t\tthis._availableStencils[oStencil.id()] = oStencil;\n\t\t\t\t\t}.bind(this));\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t//load additional properties\n\t\t\t\tif (jsonExtension.properties) {\n\t\t\t\t\tvar stencils = this._stencils.values();\n\t\t\t\t\t\n\t\t\t\t\tstencils.each(function(stencil){\n\t\t\t\t\t\tvar roles = stencil.roles();\n\t\t\t\t\t\t\n\t\t\t\t\t\tjsonExtension.properties.each(function(prop){\n\t\t\t\t\t\t\tprop.roles.any(function(role){\n\t\t\t\t\t\t\t\trole = jsonExtension[\"extends\"] + role;\n\t\t\t\t\t\t\t\tif (roles.member(role)) {\n\t\t\t\t\t\t\t\t\tprop.properties.each(function(property){\n\t\t\t\t\t\t\t\t\t\tstencil.addProperty(property, jsonExtension.namespace);\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse \n\t\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}.bind(this));\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t//remove stencil properties\n\t\t\t\tif(jsonExtension.removeproperties) {\n\t\t\t\t\tjsonExtension.removeproperties.each(function(remprop) {\n\t\t\t\t\t\tvar stencil = this.stencil(jsonExtension[\"extends\"] + remprop.stencil);\n\t\t\t\t\t\tif(stencil) {\n\t\t\t\t\t\t\tremprop.properties.each(function(propId) {\n\t\t\t\t\t\t\t\tstencil.removeProperty(propId);\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}.bind(this));\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t//remove stencils\n\t\t\t\tif(jsonExtension.removestencils) {\n\t\t\t\t\t$A(jsonExtension.removestencils).each(function(remstencil) {\n\t\t\t\t\t\tdelete this._availableStencils[jsonExtension[\"extends\"] + remstencil];\n\t\t\t\t\t}.bind(this));\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tORYX.Log.debug(\"StencilSet.addExtension: Something went wrong when initialising the stencil set extension. \" + e);\n\t\t}\t\n\t},\n\t\n\tremoveExtension: function(namespace) {\n\t\tvar jsonExtension = this._extensions[namespace];\n\t\tif(jsonExtension) {\n\t\t\t\n\t\t\t//unload extension's stencils\n\t\t\tif(jsonExtension.stencils) {\n\t\t\t\t$A(jsonExtension.stencils).each(function(stencil) {\n\t\t\t\t\tvar oStencil = new ORYX.Core.StencilSet.Stencil(stencil, this.namespace(), this._baseUrl, this);            \n\t\t\t\t\tdelete this._stencils[oStencil.id()]; // maybe not ??\n\t\t\t\t\tdelete this._availableStencils[oStencil.id()];\n\t\t\t\t}.bind(this));\n\t\t\t}\n\t\t\t\n\t\t\t//unload extension's properties\n\t\t\tif (jsonExtension.properties) {\n\t\t\t\tvar stencils = this._stencils.values();\n\t\t\t\t\n\t\t\t\tstencils.each(function(stencil){\n\t\t\t\t\tvar roles = stencil.roles();\n\t\t\t\t\t\n\t\t\t\t\tjsonExtension.properties.each(function(prop){\n\t\t\t\t\t\tprop.roles.any(function(role){\n\t\t\t\t\t\t\trole = jsonExtension[\"extends\"] + role;\n\t\t\t\t\t\t\tif (roles.member(role)) {\n\t\t\t\t\t\t\t\tprop.properties.each(function(property){\n\t\t\t\t\t\t\t\t\tstencil.removeProperty(property.id);\n\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\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse \n\t\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}.bind(this));\n\t\t\t}\n\t\t\t\n\t\t\t//restore removed stencil properties\n\t\t\tif(jsonExtension.removeproperties) {\n\t\t\t\tjsonExtension.removeproperties.each(function(remprop) {\n\t\t\t\t\tvar stencil = this.stencil(jsonExtension[\"extends\"] + remprop.stencil);\n\t\t\t\t\tif(stencil) {\n\t\t\t\t\t\tvar stencilJson = $A(this._jsonObject.stencils).find(function(s) { return s.id == stencil.id() });\n\t\t\t\t\t\tremprop.properties.each(function(propId) {\n\t\t\t\t\t\t\tvar propertyJson = $A(stencilJson.properties).find(function(p) { return p.id == propId });\n\t\t\t\t\t\t\tstencil.addProperty(propertyJson, this.namespace());\n\t\t\t\t\t\t}.bind(this));\n\t\t\t\t\t}\n\t\t\t\t}.bind(this));\n\t\t\t}\n\t\t\t\n\t\t\t//restore removed stencils\n\t\t\tif(jsonExtension.removestencils) {\n\t\t\t\t$A(jsonExtension.removestencils).each(function(remstencil) {\n\t\t\t\t\tvar sId = jsonExtension[\"extends\"] + remstencil;\n\t\t\t\t\tthis._availableStencils[sId] = this._stencils[sId];\n\t\t\t\t}.bind(this));\n\t\t\t}\n\t\t}\n\t\tdelete this._extensions[namespace];\n\t},\n    \n    __handleStencilset: function(response){\n    \n        try {\n            // using eval instead of prototype's parsing,\n            // since there are functions in this JSON.\n            eval(\"this._jsonObject =\" + response.responseText);\n        } \n        catch (e) {\n            throw \"Stenciset corrupt: \" + e;\n        }\n        \n        // assert it was parsed.\n        if (!this._jsonObject) {\n            throw \"Error evaluating stencilset. It may be corrupt.\";\n        }\n        \n        with (this._jsonObject) {\n        \n            // assert there is a namespace.\n            if (!namespace || namespace === \"\") \n                throw \"Namespace definition missing in stencilset.\";\n            \n            if (!(stencils instanceof Array)) \n                throw \"Stencilset corrupt.\";\n            \n            // assert namespace ends with '#'.\n            if (!namespace.endsWith(\"#\")) \n                namespace = namespace + \"#\";\n            \n            // assert title and description are strings.\n            if (!title) \n                title = \"\";\n            if (!description) \n                description = \"\";\n        }\n    },\n    \n    /**\n     * This method is called when the HTTP request to get the requested stencil\n     * set succeeds. The response is supposed to be a JSON representation\n     * according to the stencil set specification.\n     * @param {Object} response The JSON representation according to the\n     * \t\t\tstencil set specification.\n     */\n    _init: function(response){\n    \n        // init and check consistency.\n        this.__handleStencilset(response);\n\t\t\n\t\tvar pps = new Hash();\n\t\t\n\t\t// init property packages\n\t\tif(this._jsonObject.propertyPackages) {\n\t\t\t$A(this._jsonObject.propertyPackages).each((function(pp) {\n\t\t\t\tpps[pp.name] = pp.properties;\n\t\t\t}).bind(this));\n\t\t}\n\t\t\n\t\tvar defaultPosition = 0;\n\t\t\n        // init each stencil\n        $A(this._jsonObject.stencils).each((function(stencil){\n        \tdefaultPosition++;\n        \t\n            // instantiate normally.\n            var oStencil = new ORYX.Core.StencilSet.Stencil(stencil, this.namespace(), this._baseUrl, this, pps, defaultPosition);      \n\t\t\tthis._stencils[oStencil.id()] = oStencil;\n\t\t\tthis._availableStencils[oStencil.id()] = oStencil;\n            \n        }).bind(this));\n    },\n    \n    _cancelInit: function(response){\n        this.errornous = true;\n    },\n    \n    toString: function(){\n        return \"StencilSet \" + this.title() + \" (\" + this.namespace() + \")\";\n    }\n});\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespace\n */\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\nif(!ORYX.Core.StencilSet) {ORYX.Core.StencilSet = {};}\n\n/**\n * Class StencilSets\n * uses Prototpye 1.5.0\n * uses Inheritance\n *\n * Singleton\n */\n//storage for loaded stencil sets by namespace\nORYX.Core.StencilSet._stencilSetsByNamespace = new Hash();\n\n//storage for stencil sets by url\nORYX.Core.StencilSet._stencilSetsByUrl = new Hash();\t\n\n//storage for stencil set namespaces by editor instances\nORYX.Core.StencilSet._StencilSetNSByEditorInstance = new Hash();\n\n//storage for rules by editor instances\nORYX.Core.StencilSet._rulesByEditorInstance = new Hash();\n\n/**\n * \n * @param {String} editorId\n * \n * @return {Hash} Returns a hash map with all stencil sets that are loaded by\n * \t\t\t\t\tthe editor with the editorId.\n */\nORYX.Core.StencilSet.stencilSets = function(editorId) {\n\tvar stencilSetNSs = ORYX.Core.StencilSet._StencilSetNSByEditorInstance[editorId];\n\tvar stencilSets = new Hash();\n\tif(stencilSetNSs) {\n\t\tstencilSetNSs.each(function(stencilSetNS) {\n\t\t\tvar stencilSet = ORYX.Core.StencilSet.stencilSet(stencilSetNS)\n\t\t\tstencilSets[stencilSet.namespace()] = stencilSet;\n\t\t});\n\t}\n\treturn stencilSets;\n};\n\n/**\n * \n * @param {String} namespace\n * \n * @return {ORYX.Core.StencilSet.StencilSet} Returns the stencil set with the specified\n * \t\t\t\t\t\t\t\t\t\tnamespace.\n * \n * The method can handle namespace strings like\n *  http://www.example.org/stencilset\n *  http://www.example.org/stencilset#\n *  http://www.example.org/stencilset#ANode\n */\nORYX.Core.StencilSet.stencilSet = function(namespace) {\n\tORYX.Log.trace(\"Getting stencil set %0\", namespace);\n\tvar splitted = namespace.split(\"#\", 1);\n\tif(splitted.length === 1) {\n\t\tORYX.Log.trace(\"Getting stencil set %0\", splitted[0]);\n\t\treturn ORYX.Core.StencilSet._stencilSetsByNamespace[splitted[0] + \"#\"];\n\t} else {\n\t\treturn undefined;\n\t}\n};\n\n/**\n * \n * @param {String} id\n * \n * @return {ORYX.Core.StencilSet.Stencil} Returns the stencil specified by the id.\n * \n * The id must be unique and contains the namespace of the stencil's stencil set.\n * e.g. http://www.example.org/stencilset#ANode\n */\nORYX.Core.StencilSet.stencil = function(id) {\n\tORYX.Log.trace(\"Getting stencil for %0\", id);\n\tvar ss = ORYX.Core.StencilSet.stencilSet(id);\n\tif(ss) {\n\t\treturn ss.stencil(id);\n\t} else {\n\n\t\tORYX.Log.trace(\"Cannot fild stencil for %0\", id);\n\t\treturn undefined;\n\t}\n};\n\n/**\n * \n * @param {String} editorId\n * \n * @return {ORYX.Core.StencilSet.Rules} Returns the rules object for the editor\n * \t\t\t\t\t\t\t\t\tspecified by its editor id.\n */\nORYX.Core.StencilSet.rules = function(editorId) {\n\tif(!ORYX.Core.StencilSet._rulesByEditorInstance[editorId]) {\n\t\tORYX.Core.StencilSet._rulesByEditorInstance[editorId] = new ORYX.Core.StencilSet.Rules();\n\t}\n\treturn ORYX.Core.StencilSet._rulesByEditorInstance[editorId];\n};\n\n/**\n * \n * @param {String} url\n * @param {String} editorId\n * \n * Loads a stencil set from url, if it is not already loaded.\n * It also stores which editor instance loads the stencil set and \n * initializes the Rules object for the editor instance.\n */\nORYX.Core.StencilSet.loadStencilSet = function(url, modelMetaData, editorId) {\n\t\n\t// Alfresco: disable cache, because stencil sets are now flexible\n\t\n\t//var stencilSet = ORYX.Core.StencilSet._stencilSetsByUrl[url];\n\n\t//if(!stencilSet) {\n\t\t//load stencil set\n\t\tstencilSet = new ORYX.Core.StencilSet.StencilSet(url, modelMetaData, editorId);\n\t\t\n\t\t//store stencil set\n\t\tORYX.Core.StencilSet._stencilSetsByNamespace[stencilSet.namespace()] = stencilSet;\n\t\t\n\t\t//store stencil set by url\n\t\tORYX.Core.StencilSet._stencilSetsByUrl[url] = stencilSet;\n\t//}\n\t\n\tvar namespace = stencilSet.namespace();\n\t\n\t//store which editorInstance loads the stencil set\n\tif(ORYX.Core.StencilSet._StencilSetNSByEditorInstance[editorId]) {\n\t\tORYX.Core.StencilSet._StencilSetNSByEditorInstance[editorId].push(namespace);\n\t} else {\n\t\tORYX.Core.StencilSet._StencilSetNSByEditorInstance[editorId] = [namespace];\n\t}\n\n\t//store the rules for the editor instance\n\tif(ORYX.Core.StencilSet._rulesByEditorInstance[editorId]) {\n\t\tORYX.Core.StencilSet._rulesByEditorInstance[editorId].initializeRules(stencilSet);\n\t} else {\n\t\tvar rules = new ORYX.Core.StencilSet.Rules();\n\t\trules.initializeRules(stencilSet);\n\t\tORYX.Core.StencilSet._rulesByEditorInstance[editorId] = rules;\n\t}\n};\n\n/**\n * Returns the translation of an attribute in jsonObject specified by its name\n * according to navigator.language\n */\nORYX.Core.StencilSet.getTranslation = function(jsonObject, name) {\n\tvar lang = ORYX.I18N.Language.toLowerCase();\n\t\n\tvar result = jsonObject[name + \"_\" + lang];\n\t\n\tif(result)\n\t\treturn result;\n\t\t\n\tresult = jsonObject[name + \"_\" + lang.substr(0, 2)];\n\t\n\tif(result)\n\t\treturn result;\n\t\t\n\treturn jsonObject[name];\n};\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespaces\n */\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\n\n\n/**\n * @classDescription With Bounds you can set and get position and size of UIObjects.\n */\nORYX.Core.Command = Clazz.extend({\n\n\t/**\n\t * Constructor\n\t */\n\tconstruct: function() {\n\n\t},\n\t\n\texecute: function(){\n\t\tthrow \"Command.execute() has to be implemented!\"\n\t},\n\t\n\trollback: function(){\n\t\tthrow \"Command.rollback() has to be implemented!\"\n\t}\n\t\n\t\n });/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespaces\n */\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\n\n\n/**\n * @classDescription With Bounds you can set and get position and size of UIObjects.\n */\nORYX.Core.Bounds = {\n\n\t/**\n\t * Constructor\n\t */\n\tconstruct: function() {\n\t\tthis._changedCallbacks = []; //register a callback with changedCallacks.push(this.method.bind(this));\n\t\tthis.a = {};\n\t\tthis.b = {};\n\t\tthis.set.apply(this, arguments);\n\t\tthis.suspendChange = false;\n\t\tthis.changedWhileSuspend = false;\n\t},\n\t\n\t/**\n\t * Calls all registered callbacks.\n\t */\n\t_changed: function(sizeChanged) {\n\t\tif(!this.suspendChange) {\n\t\t\tthis._changedCallbacks.each(function(callback) {\n\t\t\t\tcallback(this, sizeChanged);\n\t\t\t}.bind(this));\n\t\t\tthis.changedWhileSuspend = false;\n\t\t} else\n\t\t\tthis.changedWhileSuspend = true;\n\t},\n\t\n\t/**\n\t * Registers a callback that is called, if the bounds changes.\n\t * @param callback {Function} The callback function.\n\t */\n\tregisterCallback: function(callback) {\n\t\tif(!this._changedCallbacks.member(callback)) {\n\t\t\tthis._changedCallbacks.push(callback);\t\n\t\t}\n\t},\n\t\n\t/**\n\t * Unregisters a callback.\n\t * @param callback {Function} The callback function.\n\t */\n\tunregisterCallback: function(callback) {\n\t\t\tthis._changedCallbacks = this._changedCallbacks.without(callback);\n\t},\n\t\n\t/**\n\t * Sets position and size of the shape dependent of four coordinates\n\t * (set(ax, ay, bx, by);), two points (set({x: ax, y: ay}, {x: bx, y: by});)\n\t * or one bound (set({a: {x: ax, y: ay}, b: {x: bx, y: by}});).\n\t */\n\tset: function() {\n\t\t\n\t\tvar changed = false;\n\t\t\n\t\tswitch (arguments.length) {\n\t\t\n\t\t\tcase 1:\n\t\t\t\tif(this.a.x !== arguments[0].a.x) {\n\t\t\t\t\tchanged = true;\n\t\t\t\t\tthis.a.x = arguments[0].a.x;\n\t\t\t\t}\n\t\t\t\tif(this.a.y !== arguments[0].a.y) {\n\t\t\t\t\tchanged = true;\n\t\t\t\t\tthis.a.y = arguments[0].a.y;\n\t\t\t\t}\n\t\t\t\tif(this.b.x !== arguments[0].b.x) {\n\t\t\t\t\tchanged = true;\n\t\t\t\t\tthis.b.x = arguments[0].b.x;\n\t\t\t\t}\n\t\t\t\tif(this.b.y !== arguments[0].b.y) {\n\t\t\t\t\tchanged = true;\n\t\t\t\t\tthis.b.y = arguments[0].b.y;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase 2:\n\t\t\t\tvar ax = Math.min(arguments[0].x, arguments[1].x);\n\t\t\t\tvar ay = Math.min(arguments[0].y, arguments[1].y);\n\t\t\t\tvar bx = Math.max(arguments[0].x, arguments[1].x);\n\t\t\t\tvar by = Math.max(arguments[0].y, arguments[1].y);\n\t\t\t\tif(this.a.x !== ax) {\n\t\t\t\t\tchanged = true;\n\t\t\t\t\tthis.a.x = ax;\n\t\t\t\t}\n\t\t\t\tif(this.a.y !== ay) {\n\t\t\t\t\tchanged = true;\n\t\t\t\t\tthis.a.y = ay;\n\t\t\t\t}\n\t\t\t\tif(this.b.x !== bx) {\n\t\t\t\t\tchanged = true;\n\t\t\t\t\tthis.b.x = bx;\n\t\t\t\t}\n\t\t\t\tif(this.b.y !== by) {\n\t\t\t\t\tchanged = true;\n\t\t\t\t\tthis.b.y = by;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase 4:\n\t\t\t\tvar ax = Math.min(arguments[0], arguments[2]);\n\t\t\t\tvar ay = Math.min(arguments[1], arguments[3]);\n\t\t\t\tvar bx = Math.max(arguments[0], arguments[2]);\n\t\t\t\tvar by = Math.max(arguments[1], arguments[3]);\n\t\t\t\tif(this.a.x !== ax) {\n\t\t\t\t\tchanged = true;\n\t\t\t\t\tthis.a.x = ax;\n\t\t\t\t}\n\t\t\t\tif(this.a.y !== ay) {\n\t\t\t\t\tchanged = true;\n\t\t\t\t\tthis.a.y = ay;\n\t\t\t\t}\n\t\t\t\tif(this.b.x !== bx) {\n\t\t\t\t\tchanged = true;\n\t\t\t\t\tthis.b.x = bx;\n\t\t\t\t}\n\t\t\t\tif(this.b.y !== by) {\n\t\t\t\t\tchanged = true;\n\t\t\t\t\tthis.b.y = by;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t\t\n\t\tif(changed) {\n\t\t\tthis._changed(true);\n\t\t}\n\t},\n\t\n\t/**\n\t * Moves the bounds so that the point p will be the new upper left corner.\n\t * @param {Point} p\n\t * or\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tmoveTo: function() {\n\t\t\n\t\tvar currentPosition = this.upperLeft();\n\t\tswitch (arguments.length) {\n\t\t\tcase 1:\n\t\t\t\tthis.moveBy({\n\t\t\t\t\tx: arguments[0].x - currentPosition.x,\n\t\t\t\t\ty: arguments[0].y - currentPosition.y\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\tthis.moveBy({\n\t\t\t\t\tx: arguments[0] - currentPosition.x,\n\t\t\t\t\ty: arguments[1] - currentPosition.y\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\t//TODO error\n\t\t}\n\t\t\n\t},\n\t\n\t/**\n\t * Moves the bounds relatively by p.\n\t * @param {Point} p\n\t * or\n\t * @param {Number} x\n\t * @param {Number} y\n\t * \n\t */\n\tmoveBy: function() {\n\t\tvar changed = false;\n\t\t\n\t\tswitch (arguments.length) {\n\t\t\tcase 1:\n\t\t\t\tvar p = arguments[0];\n\t\t\t\tif(p.x !== 0 || p.y !== 0) {\n\t\t\t\t\tchanged = true;\n\t\t\t\t\tthis.a.x += p.x;\n\t\t\t\t\tthis.b.x += p.x;\n\t\t\t\t\tthis.a.y += p.y;\n\t\t\t\t\tthis.b.y += p.y;\n\t\t\t\t}\n\t\t\t\tbreak;\t\n\t\t\tcase 2:\n\t\t\t\tvar x = arguments[0];\n\t\t\t\tvar y = arguments[1];\n\t\t\t\tif(x !== 0 || y !== 0) {\n\t\t\t\t\tchanged = true;\n\t\t\t\t\tthis.a.x += x;\n\t\t\t\t\tthis.b.x += x;\n\t\t\t\t\tthis.a.y += y;\n\t\t\t\t\tthis.b.y += y;\n\t\t\t\t}\n\t\t\t\tbreak;\t\n\t\t\tdefault:\n\t\t\t\t//TODO error\n\t\t}\n\t\t\n\t\tif(changed) {\n\t\t\tthis._changed();\n\t\t}\n\t},\n\t\n\t/***\n\t * Includes the bounds b into the current bounds.\n\t * @param {Bounds} b\n\t */\n\tinclude: function(b) {\n\t\t\n\t\tif( (this.a.x === undefined) && (this.a.y === undefined) &&\n\t\t\t(this.b.x === undefined) && (this.b.y === undefined)) {\n\t\t\treturn b;\n\t\t};\n\t\t\n\t\tvar cx = Math.min(this.a.x,b.a.x);\n\t\tvar cy = Math.min(this.a.y,b.a.y);\n\t\t\n\t\tvar dx = Math.max(this.b.x,b.b.x);\n\t\tvar dy = Math.max(this.b.y,b.b.y);\n\n\t\t\n\t\tthis.set(cx, cy, dx, dy);\n\t},\n\t\n\t/**\n\t * Relatively extends the bounds by p.\n\t * @param {Point} p\n\t */\n\textend: function(p) {\n\t\t\n\t\tif(p.x !== 0 || p.y !== 0) {\n\t\t\t// this is over cross for the case that a and b have same coordinates.\n\t\t\t//((this.a.x > this.b.x) ? this.a : this.b).x += p.x;\n\t\t\t//((this.b.y > this.a.y) ? this.b : this.a).y += p.y;\n\t\t\tthis.b.x += p.x;\n\t\t\tthis.b.y += p.y;\n\t\t\t\n\t\t\tthis._changed(true);\n\t\t}\n\t},\n\t\n\t/**\n\t * Widens the scope of the bounds by x.\n\t * @param {Number} x\n\t */\n\twiden: function(x) {\n\t\tif (x !== 0) {\n\t\t\tthis.suspendChange = true;\n\t\t\tthis.moveBy({x: -x, y: -x});\n\t\t\tthis.extend({x: 2*x, y: 2*x});\n\t\t\tthis.suspendChange = false;\n\t\t\tif(this.changedWhileSuspend) {\n\t\t\t\tthis._changed(true);\n\t\t\t}\n\t\t}\n\t},\n\t\n\t/**\n\t * Returns the upper left corner's point regardless of the\n\t * bound delimiter points.\n\t */\n\tupperLeft: function() {\n\t\tvar result = {};\n\t\tresult.x = this.a.x;\n\t\tresult.y = this.a.y;\n\t\treturn result;\n\t},\n\t\n\t/**\n\t * Returns the lower Right left corner's point regardless of the\n\t * bound delimiter points.\n\t */\n\tlowerRight: function() {\n\t\tvar result = {};\n\t\tresult.x = this.b.x;\n\t\tresult.y = this.b.y;\n\t\treturn result;\n\t},\n\t\n\t/**\n\t * @return {Number} Width of bounds.\n\t */\n\twidth: function() {\n\t\treturn this.b.x - this.a.x;\n\t},\n\t\n\t/**\n\t * @return {Number} Height of bounds.\n\t */\n\theight: function() {\n\t\treturn this.b.y - this.a.y;\n\t},\n\t\n\t/**\n\t * @return {Point} The center point of this bounds.\n\t */\n\tcenter: function() {\n\t\tvar center = {};\n\t\tcenter.x =(this.a.x + this.b.x)/2.0; \n\t\tcenter.y =(this.a.y + this.b.y)/2.0;\n\t\treturn center;\n\t},\n\n\t\n\t/**\n\t * @return {Point} The center point of this bounds relative to upperLeft.\n\t */\n\tmidPoint: function() {\n\t\t\n\t\tvar midpoint = {};\n\t\tmidpoint.x = (this.b.x - this.a.x)/2.0; \n\t\tmidpoint.y = (this.b.y - this.a.y)/2.0;\n\t\treturn midpoint;\n\t},\n\t\t\n\t/**\n\t * Moves the center point of this bounds to the new position.\n\t * @param p {Point} \n\t * or\n\t * @param x {Number}\n\t * @param y {Number}\n\t */\n\tcenterMoveTo: function() {\n\t\tvar currentPosition = this.center();\n\t\t\n\t\tswitch (arguments.length) {\n\t\t\t\n\t\t\tcase 1:\n\t\t\t\tthis.moveBy(arguments[0].x - currentPosition.x,\n\t\t\t\t\t\t\targuments[0].y - currentPosition.y);\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase 2:\n\t\t\t\tthis.moveBy(arguments[0] - currentPosition.x,\n\t\t\t\t\t\t\targuments[1] - currentPosition.y);\n\t\t\t\tbreak;\n\t\t}\n\t},\n\t\n\tisIncluded: function(point, offset) {\n\t\t\n\t\tvar pointX, pointY, offset;\n\n\t\t// Get the the two Points\t\n\t\tswitch(arguments.length) {\n\t\t\tcase 1:\n\t\t\t\tpointX = arguments[0].x;\n\t\t\t\tpointY = arguments[0].y;\n\t\t\t\toffset = 0;\n\t\t\t\t\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\tif(arguments[0].x && arguments[0].y) {\n\t\t\t\t\tpointX = arguments[0].x;\n\t\t\t\t\tpointY = arguments[0].y;\n\t\t\t\t\toffset = Math.abs(arguments[1]);\n\t\t\t\t} else {\n\t\t\t\t\tpointX = arguments[0];\n\t\t\t\t\tpointY = arguments[1];\n\t\t\t\t\toffset = 0;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 3:\n\t\t\t\tpointX = arguments[0];\n\t\t\t\tpointY = arguments[1];\n\t\t\t\toffset = Math.abs(arguments[2]);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthrow \"isIncluded needs one, two or three arguments\";\n\t\t}\n\t\t\t\t\n\t\tvar ul = this.upperLeft();\n\t\tvar lr = this.lowerRight();\n\t\t\n\t\tif(pointX >= ul.x - offset \n\t\t\t&& pointX <= lr.x + offset && pointY >= ul.y - offset \n\t\t\t&& pointY <= lr.y + offset)\n\t\t\treturn true;\n\t\telse \n\t\t\treturn false;\n\t},\n\t\n\t/**\n\t * @return {Bounds} A copy of this bounds.\n\t */\n\tclone: function() {\n\t\t\n\t\t//Returns a new bounds object without the callback\n\t\t// references of the original bounds\n\t\treturn new ORYX.Core.Bounds(this);\n\t},\n\t\n\ttoString: function() {\n\t\t\n\t\treturn \"( \"+this.a.x+\" | \"+this.a.y+\" )/( \"+this.b.x+\" | \"+this.b.y+\" )\";\n\t},\n\t\n\tserializeForERDF: function() {\n\n\t\treturn this.a.x+\",\"+this.a.y+\",\"+this.b.x+\",\"+this.b.y;\n\t}\n };\n \nORYX.Core.Bounds = Clazz.extend(ORYX.Core.Bounds);/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespaces\n */\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\n\n\n/**\n * @classDescription Abstract base class for all objects that have a graphical representation\n * within the editor.\n * @extends Clazz\n */\nORYX.Core.UIObject = {\n\t/**\n\t * Constructor of the UIObject class.\n\t */\n\tconstruct: function(options) {\t\n\t\t\n\t\tthis.isChanged = true;\t\t\t//Flag, if UIObject has been changed since last update.\n\t\tthis.isResized = true;\n\t\tthis.isVisible = true;\t\t\t//Flag, if UIObject's display attribute is set to 'inherit' or 'none'\n\t\tthis.isSelectable = false;\t\t//Flag, if UIObject is selectable.\n\t\tthis.isResizable = false;\t\t//Flag, if UIObject is resizable.\n\t\tthis.isMovable = false;\t\t\t//Flag, if UIObject is movable.\n\t\t\n\t\tthis.id = ORYX.Editor.provideId();\t//get unique id\n\t\tthis.parent = undefined;\t\t//parent is defined, if this object is added to another uiObject.\n\t\tthis.node = undefined;\t\t\t//this is a reference to the SVG representation, either locally or in DOM.\n\t\tthis.children = [];\t\t\t\t//array for all add uiObjects\n\t\t\n\t\tthis.bounds = new ORYX.Core.Bounds();\t\t//bounds with undefined values\n\n\t\tthis._changedCallback = this._changed.bind(this);\t//callback reference for calling _changed\n\t\tthis.bounds.registerCallback(this._changedCallback);\t//set callback in bounds\n\t\t\n\t\tif(options && options.eventHandlerCallback) {\n\t\t\tthis.eventHandlerCallback = options.eventHandlerCallback;\n\t\t}\n\t},\n\t\n\t/**\n\t * Sets isChanged flag to true. Callback for the bounds object.\n\t */\n\t_changed: function(bounds, isResized) {\n\t\tthis.isChanged = true;\n\t\tif(this.bounds == bounds)\n\t\t\tthis.isResized = isResized || this.isResized;\n\t},\n\t\n\t/**\n\t * If something changed, this method calls the refresh method that must be implemented by subclasses.\n\t */\n\tupdate: function() {\n\t\tif(this.isChanged) {\n\t\t\tthis.refresh();\n\t\t\tthis.isChanged = false;\n\t\t\t\n\t\t\t//call update of all children\n\t\t\tthis.children.each(function(value) {\n\t\t\t\tvalue.update();\n\t\t\t});\n\t\t}\n\t},\n\t\n\t/**\n\t * Is called in update method, if isChanged is set to true. Sub classes should call the super class method.\n\t */\n\trefresh: function() {\n\t\t\n\t},\n\t\n\t/**\n\t * @return {Array} Array of all child UIObjects.\n\t */\n\tgetChildren: function() {\n\t\treturn this.children.clone();\n\t},\n\t\n\t/**\n\t * @return {Array} Array of all parent UIObjects.\n\t */\n\tgetParents: function(){\n\t\tvar parents = [];\n\t\tvar parent = this.parent;\n\t\twhile(parent){\n\t\t\tparents.push(parent);\n\t\t\tparent = parent.parent;\n\t\t}\n\t\treturn parents;\n\t},\n\t\n\t/**\n\t * Returns TRUE if the given parent is one of the UIObjects parents or the UIObject themselves, otherwise FALSE.\n\t * @param {UIObject} parent\n\t * @return {Boolean} \n\t */\n\tisParent: function(parent){\n\t\tvar cparent = this;\n\t\twhile(cparent){\n\t\t\tif (cparent === parent){\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tcparent = cparent.parent;\n\t\t}\n\t\treturn false;\n\t},\n\t\n\t/**\n\t * @return {String} Id of this UIObject\n\t */\n\tgetId: function() {\n\t\treturn this.id;\n\t},\n\t\n\t/**\n\t * Method for accessing child uiObjects by id.\n\t * @param {String} id\n\t * @param {Boolean} deep\n\t * \n\t * @return {UIObject} If found, it returns the UIObject with id.\n\t */\n\tgetChildById: function(id, deep) {\n\t\treturn this.children.find(function(uiObj) {\n\t\t\tif(uiObj.getId() === id) {\n\t\t\t\treturn uiObj;\n\t\t\t} else {\n\t\t\t\tif(deep) {\n\t\t\t\t\tvar obj = uiObj.getChildById(id, deep);\n\t\t\t\t\tif(obj) {\n\t\t\t\t\t\treturn obj;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n\t\n\t/**\n\t * Adds an UIObject to this UIObject and sets the parent of the\n\t * added UIObject. It is also added to the SVG representation of this\n\t * UIObject.\n\t * @param {UIObject} uiObject\n\t */\n\tadd: function(uiObject) {\n\t\t//add uiObject, if it is not already a child of this object\n\t\tif (!(this.children.member(uiObject))) {\n\t\t\t//if uiObject is child of another parent, remove it from that parent.\n\t\t\tif(uiObject.parent) {\n\t\t\t\tuiObject.remove(uiObject);\n\t\t\t}\n\t\t\t\n\t\t\t//add uiObject to children\n\t\t\tthis.children.push(uiObject);\n\t\t\t\n\t\t\t//set parent reference\n\t\t\tuiObject.parent = this;\n\t\t\t\n\t\t\t//add uiObject.node to this.node\n\t\t\tuiObject.node = this.node.appendChild(uiObject.node);\n\t\t\t\n\t\t\t//register callback to get informed, if child is changed\n\t\t\tuiObject.bounds.registerCallback(this._changedCallback);\n\n\t\t\t//uiObject.update();\n\t\t} else {\n\t\t\tORYX.Log.info(\"add: ORYX.Core.UIObject is already a child of this object.\");\n\t\t}\n\t},\n\t\n\t/**\n\t * Removes UIObject from this UIObject. The SVG representation will also\n\t * be removed from this UIObject's SVG representation.\n\t * @param {UIObject} uiObject\n\t */\n\tremove: function(uiObject) {\n\t\t//if uiObject is a child of this object, remove it.\n\t\tif (this.children.member(uiObject)) {\n\t\t\t//remove uiObject from children\n\t\t\tthis.children = this._uiObjects.without(uiObject);\n\t\t\t\n\t\t\t//delete parent reference of uiObject\n\t\t\tuiObject.parent = undefined;\n\t\t\t\n\t\t\t//delete uiObject.node from this.node\n\t\t\tuiObject.node = this.node.removeChild(uiObject.node);\n\t\t\t\n\t\t\t//unregister callback to get informed, if child is changed\n\t\t\tuiObject.bounds.unregisterCallback(this._changedCallback);\n\t\t} else {\n\t\t\tORYX.Log.info(\"remove: ORYX.Core.UIObject is not a child of this object.\");\n\t\t}\n\t\t\n\t},\n\t\n\t/**\n\t * Calculates absolute bounds of this UIObject.\n\t */\n\tabsoluteBounds: function() {\n\t\tif(this.parent) {\n\t\t\tvar absUL = this.absoluteXY();\n\t\t\treturn new ORYX.Core.Bounds(absUL.x, absUL.y,\n\t\t\t\t\t\t\tabsUL.x + this.bounds.width(),\n\t\t\t\t\t\t\tabsUL.y + this.bounds.height());\n\t\t} else {\n\t\t\treturn this.bounds.clone();\n\t\t}\n\t},\n\n\t/**\n\t * @return {Point} The absolute position of this UIObject.\n\t */\n\tabsoluteXY: function() {\n\t\tif(this.parent) {\n\t\t\tvar pXY = this.parent.absoluteXY();\n\t\t\tvar result = {};\n\t\t\tresult.x = pXY.x + this.bounds.upperLeft().x;\n\t\t\tresult.y = pXY.y + this.bounds.upperLeft().y;\n\t\t\treturn result;\n\t\t} else {\n\t\t\tvar result = {};\n\t\t\tresult.x = this.bounds.upperLeft().x;\n\t\t\tresult.y = this.bounds.upperLeft().y;\n\t\t\treturn result;\n\t\t}\n\t},\n\n\t/**\n\t * @return {Point} The absolute position from the Center of this UIObject.\n\t */\n\tabsoluteCenterXY: function() {\n\t\tif(this.parent) {\n\t\t\tvar pXY = this.parent.absoluteXY();\t\n\t\t\tvar result = {};\n\t\t\tresult.x = pXY.x + this.bounds.center().x;\n\t\t\tresult.y = pXY.y + this.bounds.center().y;\n\t\t\treturn result;\n\t\t\t\n\t\t} else {\n\t\t\tvar result = {};\n\t\t\tresult.x = this.bounds.center().x;\n\t\t\tresult.y = this.bounds.center().y;\n\t\t\treturn result;\n\t\t}\n\t},\n\t\n\t/**\n\t * Hides this UIObject and all its children.\n\t */\n\thide: function() {\n\t\tthis.node.setAttributeNS(null, 'display', 'none');\n\t\tthis.isVisible = false;\n\t\tthis.children.each(function(uiObj) {\n\t\t\tuiObj.hide();\t\n\t\t});\n\t},\n\t\n\t/**\n\t * Enables visibility of this UIObject and all its children.\n\t */\n\tshow: function() {\n\t\tthis.node.setAttributeNS(null, 'display', 'inherit');\n\t\tthis.isVisible = true;\n\t\tthis.children.each(function(uiObj) {\n\t\t\tuiObj.show();\t\n\t\t});\t\t\n\t},\n\t\n\taddEventHandlers: function(node) {\n\t\t\n\t\tnode.addEventListener(ORYX.CONFIG.EVENT_MOUSEDOWN, this._delegateEvent.bind(this), false);\n\t\tnode.addEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, this._delegateEvent.bind(this), false);\t\n\t\tnode.addEventListener(ORYX.CONFIG.EVENT_MOUSEUP, this._delegateEvent.bind(this), false);\n\t\tnode.addEventListener(ORYX.CONFIG.EVENT_MOUSEOVER, this._delegateEvent.bind(this), false);\n\t\tnode.addEventListener(ORYX.CONFIG.EVENT_MOUSEOUT, this._delegateEvent.bind(this), false);\n\t\tnode.addEventListener('click', this._delegateEvent.bind(this), false);\n\t\tnode.addEventListener(ORYX.CONFIG.EVENT_DBLCLICK, this._delegateEvent.bind(this), false);\n\t\t\t\n\t},\n\t\t\n\t_delegateEvent: function(event) {\n\t\tif(this.eventHandlerCallback) {\n\t\t\tthis.eventHandlerCallback(event, this);\n\t\t}\n\t},\n\t\n\ttoString: function() { return \"UIObject \" + this.id }\n };\n ORYX.Core.UIObject = Clazz.extend(ORYX.Core.UIObject);/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespaces\n */\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\n\n/**\n * Top Level uiobject.\n * @class ORYX.Core.AbstractShape\n * @extends ORYX.Core.UIObject\n */\nORYX.Core.AbstractShape = ORYX.Core.UIObject.extend(\n/** @lends ORYX.Core.AbstractShape.prototype */\n{\n\n\t/**\n\t * Constructor\n\t */\n\tconstruct: function(options, stencil, facade) {\n\t\t\n\t\targuments.callee.$.construct.apply(this, arguments);\n\t\t\n\t\tthis.resourceId = ORYX.Editor.provideId(); //Id of resource in DOM\n\t\t\n\t\t// stencil reference\n\t\tthis._stencil = stencil;\n\t\t// if the stencil defines a super stencil that should be used for its instances, set it.\n\t\tif (this._stencil._jsonStencil.superId){\n\t\t\tstencilId = this._stencil.id()\n\t\t\tsuperStencilId = stencilId.substring(0, stencilId.indexOf(\"#\") + 1) + stencil._jsonStencil.superId;\n\t\t\tstencilSet =  this._stencil.stencilSet();\n\t\t\tthis._stencil = stencilSet.stencil(superStencilId);\n\t\t}\n\t\t\n\t\t//Hash map for all properties. Only stores the values of the properties.\n\t\tthis.properties = new Hash();\n\t\tthis.propertiesChanged = new Hash();\n\n\t\t// List of properties which are not included in the stencilset, \n\t\t// but which gets (de)serialized\n\t\tthis.hiddenProperties = new Hash();\n\t\t\n\t\t\n\t\t//Initialization of property map and initial value.\n\t\tthis._stencil.properties().each((function(property) {\n\t\t\tvar key = property.prefix() + \"-\" + property.id();\n\t\t\tthis.properties[key] = property.value();\n\t\t\tthis.propertiesChanged[key] = true;\n\t\t}).bind(this));\n\t\t\n\t\t// if super stencil was defined, also regard stencil's properties:\n\t\tif (stencil._jsonStencil.superId) {\n\t\t\tstencil.properties().each((function(property) {\n\t\t\t\tvar key = property.prefix() + \"-\" + property.id();\n\t\t\t\tvar value = property.value();\n\t\t\t\tvar oldValue = this.properties[key];\n\t\t\t\tthis.properties[key] = value;\n\t\t\t\tthis.propertiesChanged[key] = true;\n\n\t\t\t\t// Raise an event, to show that the property has changed\n\t\t\t\t// required for plugins like processLink.js\n\t\t\t\t//window.setTimeout( function(){\n\n\t\t\t\t\tthis._delegateEvent({\n\t\t\t\t\t\t\ttype\t: ORYX.CONFIG.EVENT_PROPERTY_CHANGED, \n\t\t\t\t\t\t\tname\t: key, \n\t\t\t\t\t\t\tvalue\t: value,\n\t\t\t\t\t\t\toldValue: oldValue\n\t\t\t\t\t\t});\n\n\t\t\t\t//}.bind(this), 10)\n\n\t\t\t}).bind(this));\n\t\t}\n\n\t},\n\n\tlayout: function() {\n\n\t},\n\t\n\t/**\n\t * Returns the stencil object specifiing the type of the shape.\n\t */\n\tgetStencil: function() {\n\t\treturn this._stencil;\n\t},\n\t\n\t/**\n\t * \n\t * @param {Object} resourceId\n\t */\n\tgetChildShapeByResourceId: function(resourceId) {\n\n\t\tresourceId = ERDF.__stripHashes(resourceId);\n\t\t\n\t\treturn this.getChildShapes(true).find(function(shape) {\n\t\t\t\t\treturn shape.resourceId == resourceId\n\t\t\t\t});\n\t},\n\t/**\n\t * \n\t * @param {Object} deep\n\t * @param {Object} iterator\n\t */\n\tgetChildShapes: function(deep, iterator) {\n\t\tvar result = [];\n\n\t\tthis.children.each(function(uiObject) {\n\t\t\tif(uiObject instanceof ORYX.Core.Shape && uiObject.isVisible ) {\n\t\t\t\tif(iterator) {\n\t\t\t\t\titerator(uiObject);\n\t\t\t\t}\n\t\t\t\tresult.push(uiObject);\n\t\t\t\tif(deep) {\n\t\t\t\t\tresult = result.concat(uiObject.getChildShapes(deep, iterator));\n\t\t\t\t} \n\t\t\t}\n\t\t});\n\n\t\treturn result;\n\t},\n    \n    /**\n     * @param {Object} shape\n     * @return {boolean} true if any of shape's childs is given shape\n     */\n    hasChildShape: function(shape){\n        return this.getChildShapes().any(function(child){\n            return (child === shape) || child.hasChildShape(shape);\n        });\n    },\n\t\n\t/**\n\t * \n\t * @param {Object} deep\n\t * @param {Object} iterator\n\t */\n\tgetChildNodes: function(deep, iterator) {\n\t\tvar result = [];\n\n\t\tthis.children.each(function(uiObject) {\n\t\t\tif(uiObject instanceof ORYX.Core.Node && uiObject.isVisible) {\n\t\t\t\tif(iterator) {\n\t\t\t\t\titerator(uiObject);\n\t\t\t\t}\n\t\t\t\tresult.push(uiObject);\n\t\t\t}\n\t\t\tif(uiObject instanceof ORYX.Core.Shape) {\n\t\t\t\tif(deep) {\n\t\t\t\t\tresult = result.concat(uiObject.getChildNodes(deep, iterator));\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn result;\n\t},\n\t\n\t/**\n\t * \n\t * @param {Object} deep\n\t * @param {Object} iterator\n\t */\n\tgetChildEdges: function(deep, iterator) {\n\t\tvar result = [];\n\n\t\tthis.children.each(function(uiObject) {\n\t\t\tif(uiObject instanceof ORYX.Core.Edge && uiObject.isVisible) {\n\t\t\t\tif(iterator) {\n\t\t\t\t\titerator(uiObject);\n\t\t\t\t}\n\t\t\t\tresult.push(uiObject);\n\t\t\t}\n\t\t\tif(uiObject instanceof ORYX.Core.Shape) {\n\t\t\t\tif(deep) {\n\t\t\t\t\tresult = result.concat(uiObject.getChildEdges(deep, iterator));\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn result;\n\t},\n\t\n\t/**\n\t * Returns a sorted array of ORYX.Core.Node objects.\n\t * Ordered in z Order, the last object has the highest z Order.\n\t */\n\t//TODO deep iterator\n\tgetAbstractShapesAtPosition: function() {\n\t\tvar x, y;\n\t\tswitch (arguments.length) {\n\t\t\tcase 1:\n\t\t\t\tx = arguments[0].x;\n\t\t\t\ty = arguments[0].y;\n\t\t\t\tbreak;\n\t\t\tcase 2:\t//two or more arguments\n\t\t\t\tx = arguments[0];\n\t\t\t\ty = arguments[1];\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthrow \"getAbstractShapesAtPosition needs 1 or 2 arguments!\"\n\t\t}\n\n\t\tif(this.isPointIncluded(x, y)) {\n\n\t\t\tvar result = [];\n\t\t\tresult.push(this);\n\n\t\t\t//check, if one child is at that position\t\t\t\t\t\t\n\t\t\t\n\t\t\t\n\t\t\tvar childNodes = this.getChildNodes();\n\t\t\tvar childEdges = this.getChildEdges();\n\t\t\t\n\t\t\t[childNodes, childEdges].each(function(ne){\n\t\t\t\tvar nodesAtPosition = new Hash();\n\t\t\t\t\n\t\t\t\tne.each(function(node) {\n\t\t\t\t\tif(!node.isVisible){ return }\n\t\t\t\t\tvar candidates = node.getAbstractShapesAtPosition( x , y );\n\t\t\t\t\tif(candidates.length > 0) {\n\t\t\t\t\t\tvar nodesInZOrder = $A(node.node.parentNode.childNodes);\n\t\t\t\t\t\tvar zOrderIndex = nodesInZOrder.indexOf(node.node);\n\t\t\t\t\t\tnodesAtPosition[zOrderIndex] = candidates;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\tnodesAtPosition.keys().sort().each(function(key) {\n\t\t\t\t\tresult = result.concat(nodesAtPosition[key]);\n\t\t\t\t});\n \t\t\t});\n\t\t\t\t\t\t\n\t\t\treturn result;\n\t\t\t\n\t\t} else {\n\t\t\treturn [];\n\t\t}\n\t},\n\t\n\t/**\n\t * \n\t * @param key {String} Must be 'prefix-id' of property\n\t * @param value {Object} Can be of type String or Number according to property type.\n\t */\n\tsetProperty: function(key, value, force) {\n\t\tvar oldValue = this.properties[key];\n\t\tif(oldValue !== value || force === true) {\n\t\t\tthis.properties[key] = value;\n\t\t\tthis.propertiesChanged[key] = true;\n\t\t\tthis._changed();\n\t\t\t\n\t\t\t// Raise an event, to show that the property has changed\n\t\t\t//window.setTimeout( function(){\n\n\t\t\tif (!this._isInSetProperty) {\n\t\t\t\tthis._isInSetProperty = true;\n\t\t\t\t\n\t\t\t\tthis._delegateEvent({\n\t\t\t\t\t\ttype\t: ORYX.CONFIG.EVENT_PROPERTY_CHANGED, \n\t\t\t\t\t\telements : [this],\n\t\t\t\t\t\tname\t: key, \n\t\t\t\t\t\tvalue\t: value,\n\t\t\t\t\t\toldValue: oldValue\n\t\t\t\t\t});\n\t\t\t\t\n\t\t\t\tdelete this._isInSetProperty;\n\t\t\t}\n\t\t\t//}.bind(this), 10)\n\t\t}\n\t},\n\t\n\t/**\n\t * Returns TRUE if one of the properties is flagged as dirty\n\t * @return {boolean}\n\t */\n\tisPropertyChanged: function(){\n\t\treturn this.propertiesChanged.any(function(property){ return property.value });\n\t},\n\n\t/**\n\t * \n\t * @param {String} Must be 'prefix-id' of property\n\t * @param {Object} Can be of type String or Number according to property type.\n\t */\n\tsetHiddenProperty: function(key, value) {\n\t\t// IF undefined, Delete\n\t\tif (value === undefined) {\n\t\t\tdelete this.hiddenProperties[key];\n\t\t\treturn;\n\t\t}\n\t\tvar oldValue = this.hiddenProperties[key];\n\t\tif (oldValue !== value) {\n\t\t\tthis.hiddenProperties[key] = value;\n\t\t}\n\t},\n\t/**\n\t * Calculate if the point is inside the Shape\n\t * @param {Point}\n\t */\n\tisPointIncluded: function(pointX, pointY, absoluteBounds) {\n\t\tvar absBounds = absoluteBounds ? absoluteBounds : this.absoluteBounds();\n\t\treturn absBounds.isIncluded(pointX, pointY);\n\t\t\t\t\n\t},\n\t\n\t/**\n\t * Get the serialized object\n\t * return Array with hash-entrees (prefix, name, value)\n\t * Following values will given:\n\t * \t\tType\n\t * \t\tProperties\n\t */\n\tserialize: function() {\n\t\tvar serializedObject = [];\n\t\t\n\t\t// Add the type\n\t\tserializedObject.push({name: 'type', prefix:'oryx', value: this.getStencil().id(), type: 'literal'});\t\n\t\n\t\t// Add hidden properties\n\t\tthis.hiddenProperties.each(function(prop){\n\t\t\tserializedObject.push({name: prop.key.replace(\"oryx-\", \"\"), prefix: \"oryx\", value: prop.value, type: 'literal'});\n\t\t}.bind(this));\n\t\t\n\t\t// Add all properties\n\t\tthis.getStencil().properties().each((function(property){\n\t\t\t\n\t\t\tvar prefix = property.prefix();\t// Get prefix\n\t\t\tvar name = property.id();\t\t// Get name\n\t\t\t\n\t\t\t//if(typeof this.properties[prefix+'-'+name] == 'boolean' || this.properties[prefix+'-'+name] != \"\")\n\t\t\t\tserializedObject.push({name: name, prefix: prefix, value: this.properties[prefix+'-'+name], type: 'literal'});\n\n\t\t}).bind(this));\n\t\t\n\t\treturn serializedObject;\n\t},\n\t\t\n\t\t\n\tdeserialize: function(serialize){\n\t\t// Search in Serialize\n\t\tvar initializedDocker = 0;\n\t\t\n\t\t// Sort properties so that the hidden properties are first in the list\n\t\tserialize = serialize.sort(function(a,b){ a = Number(this.properties.keys().member(a.prefix+\"-\"+a.name)); b = Number(this.properties.keys().member(b.prefix+\"-\"+b.name)); return a > b ? 1 : (a < b ? -1 : 0) }.bind(this));\n\t\t\n\t\tserialize.each((function(obj){\n\t\t\t\n\t\t\tvar name \t= obj.name;\n\t\t\tvar prefix \t= obj.prefix;\n\t\t\tvar value \t= obj.value;\n            \n            // Complex properties can be real json objects, encode them to a string\n            if (Object.prototype.toString.call(value) === \"Object\") value = JSON.stringify(value);\n\n\t\t\tswitch(prefix + \"-\" + name){\n\t\t\t\tcase 'raziel-parent': \n\t\t\t\t\t\t\t// Set parent\n\t\t\t\t\t\t\tif(!this.parent) {break};\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t// Set outgoing Shape\n\t\t\t\t\t\t\tvar parent = this.getCanvas().getChildShapeByResourceId(value);\n\t\t\t\t\t\t\tif(parent) {\n\t\t\t\t\t\t\t\tparent.add(this);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tbreak;\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\tdefault:\n\t\t\t\t\t\t\t// If list, eval as an array\n\t\t\t\t\t\t\tvar prop = this.getStencil().property(prefix+\"-\"+name);\n\t\t\t\t\t\t\tif (prop && prop.isList() && typeof value === \"string\"){\n\t\t\t\t\t\t\t\tif ((value||\"\").strip()&&!value.startsWith(\"[\")&&!value.startsWith(\"]\"))\n\t\t\t\t\t\t\t\t\tvalue = \"[\\\"\"+value.strip()+\"\\\"]\";\n\t\t\t\t\t\t\t\tvalue = ((value||\"\").strip()||\"[]\").evalJSON();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t// Set property\n\t\t\t\t\t\t\tif(this.properties.keys().member(prefix+\"-\"+name)) {\n\t\t\t\t\t\t\t\tthis.setProperty(prefix+\"-\"+name, value);\n\t\t\t\t\t\t\t} else if(!(name === \"bounds\"||name === \"parent\"||name === \"target\"||name === \"dockers\"||name === \"docker\"||name === \"outgoing\"||name === \"incoming\")) {\n\t\t\t\t\t\t\t\tthis.setHiddenProperty(prefix+\"-\"+name, value);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t}\n\t\t}).bind(this));\n\t},\n\t\n\ttoString: function() { return \"ORYX.Core.AbstractShape \" + this.id },\n    \n    /**\n     * Converts the shape to a JSON representation.\n     * @return {Object} A JSON object with included ORYX.Core.AbstractShape.JSONHelper and getShape() method.\n     */\n    toJSON: function(){\n        var json = {\n            resourceId: this.resourceId,\n            properties: jQuery.extend({}, this.properties, this.hiddenProperties).inject({}, function(props, prop){\n              var key = prop[0];\n              var value = prop[1];\n                \n              //If complex property, value should be a json object\n              if ( this.getStencil().property(key)\n                \t&& this.getStencil().property(key).type() === ORYX.CONFIG.TYPE_COMPLEX \n                \t&& Object.prototype.toString.call(value) === \"String\"){\n\t\t\t\t\t\t\n                  try {value = JSON.parse(value);} catch(error){}\n            \t  //try {value = JSON.parse(value);} catch(error){}\n              \n\t\t\t  // Parse date\n\t\t\t  } else if (value instanceof Date&&this.getStencil().property(key)){\n\t\t\t  \ttry {\n\t\t\t\t\tvalue = value.format(this.getStencil().property(key).dateFormat());\n\t\t\t\t} catch(e){}\n\t\t\t  }\n              \n              //Takes \"my_property\" instead of \"oryx-my_property\" as key\n              key = key.replace(/^[\\w_]+-/, \"\");\n              props[key] = value;\n              \n              return props;\n            }.bind(this)),\n            stencil: {\n                id: this.getStencil().idWithoutNs()\n            },\n            childShapes: this.getChildShapes().map(function(shape){\n                return shape.toJSON();\n            })\n        };\n        \n        if(this.getOutgoingShapes){\n            json.outgoing = this.getOutgoingShapes().map(function(shape){\n                return {\n                    resourceId: shape.resourceId\n                };\n            });\n        }\n        \n        if(this.bounds){\n            json.bounds = { \n                lowerRight: this.bounds.lowerRight(), \n                upperLeft: this.bounds.upperLeft() \n            };\n        }\n        \n        if(this.dockers){\n            json.dockers = this.dockers.map(function(docker){\n                var d = docker.getDockedShape() && docker.referencePoint ? docker.referencePoint : docker.bounds.center();\n                d.getDocker = function(){return docker;};\n                return d;\n            });\n        }\n        \n        jQuery.extend(json, ORYX.Core.AbstractShape.JSONHelper);\n        \n        // do not pollute the json attributes (for serialization), so put the corresponding\n        // shape is encapsulated in a method\n        json.getShape = function(){\n            return this;\n        }.bind(this);\n        \n        return json;\n    }\n });\n \n/**\n * @namespace Collection of methods which can be used on a shape json object (ORYX.Core.AbstractShape#toJSON()).\n * @example\n * jQuery.extend(shapeAsJson, ORYX.Core.AbstractShape.JSONHelper);\n */\nORYX.Core.AbstractShape.JSONHelper = {\n     /**\n      * Iterates over each child shape.\n      * @param {Object} iterator Iterator function getting a child shape and his parent as arguments.\n      * @param {boolean} [deep=false] Iterate recursively (childShapes of childShapes)\n      * @param {boolean} [modify=false] If true, the result of the iterator function is taken as new shape, return false to delete it. This enables modifying the object while iterating through the child shapes.\n      * @example\n      * // Increases the lowerRight x value of each direct child shape by one. \n      * myShapeAsJson.eachChild(function(shape, parentShape){\n      *     shape.bounds.lowerRight.x = shape.bounds.lowerRight.x + 1;\n      *     return shape;\n      * }, false, true);\n      */\n     eachChild: function(iterator, deep, modify){\n         if(!this.childShapes) return;\n         \n         var newChildShapes = []; //needed if modify = true\n         \n         this.childShapes.each(function(shape){\n\t\t \t if (!(shape.eachChild instanceof Function)){\n\t\t \t\tjQuery.extend(shape, ORYX.Core.AbstractShape.JSONHelper);\n\t\t\t }\n             var res = iterator(shape, this);\n             if(res) newChildShapes.push(res); //if false is returned, and modify = true, current shape is deleted.\n             \n             if(deep) shape.eachChild(iterator, deep, modify);\n         }.bind(this));\n         \n         if(modify) this.childShapes = newChildShapes;\n     },\n     \n\t getShape: function(){\n\t \treturn null;\n\t },\n     getChildShapes: function(deep){\n         var allShapes = this.childShapes;\n         \n         if(deep){\n             this.eachChild(function(shape){\n\t\t\t \t if (!(shape.getChildShapes instanceof Function)){\n\t\t\t \t\tjQuery.extend(shape, ORYX.Core.AbstractShape.JSONHelper);\n\t\t\t\t }\n                 allShapes = allShapes.concat(shape.getChildShapes(deep));\n             }, true);\n         }\n         \n         return allShapes;\n     },\n     \n     /**\n      * @return {String} Serialized JSON object\n      */\n     serialize: function(){\n         return JSON.stringify(this);\n     }\n }\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespaces\n */\nif(!ORYX) {var ORYX = {};}\n\n/**\n   @namespace Namespace for the Oryx core elements.\n   @name ORYX.Core\n*/\nif(!ORYX.Core) {ORYX.Core = {};}\n\n/**\n * @class Oryx canvas.\n * @extends ORYX.Core.AbstractShape\n *\n */\nORYX.Core.Canvas = ORYX.Core.AbstractShape.extend({\n    /** @lends ORYX.Core.Canvas.prototype */\n\n\t/**\n\t * Defines the current zoom level\n\t */\n\tzoomLevel:1,\n\n\t/**\n\t * Constructor\n\t */\n\tconstruct: function(options, stencil, facade) {\n\t\targuments.callee.$.construct.apply(this, arguments);\n\n\t\tif(!(options && options.width && options.height)) {\n\t\t\n\t\t\tORYX.Log.fatal(\"Canvas is missing mandatory parameters options.width and options.height.\");\n\t\t\treturn;\n\t\t}\n\t\tthis.facade = facade;\t\n\t\t//TODO: set document resource id\n\t\tthis.resourceId = options.id;\n\n\t\tthis.nodes = [];\n\t\t\n\t\tthis.edges = [];\n\t\t\n\t\t// Row highlighting states\n\t\tthis.colHighlightState = 0;\n\t\t\n\t\tthis.colHighlightEnabled = false; \n\t\t\n\t\t//init svg document\n\t\tthis.rootNode = ORYX.Editor.graft(\"http://www.w3.org/2000/svg\", options.parentNode,\n\t\t\t['svg', {id: this.id, width: options.width, height: options.height},\n\t\t\t\t['defs', {}]\n\t\t\t]);\n\t\t\t\n\t\tthis.rootNode.setAttribute(\"xmlns:xlink\", \"http://www.w3.org/1999/xlink\");\n\t\tthis.rootNode.setAttribute(\"xmlns:svg\", \"http://www.w3.org/2000/svg\");\n\n\t\tthis._htmlContainer = ORYX.Editor.graft(\"http://www.w3.org/1999/xhtml\", options.parentNode,\n\t\t\t['div', {id: \"oryx_canvas_htmlContainer\", style:\"position:absolute; top:5px\"}]);\n\n\t\t// Additional SVG-node BELOW the stencils to allow underlays (if that is even a word) by plugins\n\t\tthis.underlayNode = ORYX.Editor.graft(\"http://www.w3.org/2000/svg\", this.rootNode,\n\t\t\t\t['svg', {id: \"underlay-container\"}]);\n\t\t\n\t\t// Create 2 svg-elements in the svg-container\n\t\tthis.columnHightlight1 = ORYX.Editor.graft(\"http://www.w3.org/2000/svg\", this.underlayNode,\n\t\t\t\t['rect', {x: 0, width: ORYX.CONFIG.FORM_ROW_WIDTH + 35, height: \"100%\", style: \"fill: #fff6d5\", visibility: \"hidden\"}]);\n\t\t\n\t\tthis.columnHightlight2 = ORYX.Editor.graft(\"http://www.w3.org/2000/svg\", this.underlayNode,\n\t\t\t\t['rect', {x: ORYX.CONFIG.FORM_ROW_WIDTH + 35, width: ORYX.CONFIG.FORM_ROW_WIDTH + 25, height: \"100%\", style: \"fill: #fff6d5\", visibility: \"hidden\"}]);\n\t\t\n\t\tthis.node = ORYX.Editor.graft(\"http://www.w3.org/2000/svg\", this.rootNode,\n\t\t\t['g', {},\n\t\t\t\t['g', {\"class\": \"stencils\"},\n\t\t\t\t\t['g', {\"class\": \"me\"}],\n\t\t\t\t\t['g', {\"class\": \"children\"}],\n\t\t\t\t\t['g', {\"class\": \"edge\"}]\n\t\t\t\t],\n\t\t\t\t['g', {\"class\":\"svgcontainer\"}]\n\t\t\t]);\n\t\t\n\t\t/*\n\t\tvar off = 2 * ORYX.CONFIG.GRID_DISTANCE;\n\t\tvar size = 3;\n\t\tvar d = \"\";\n\t\tfor(var i = 0; i <= options.width; i += off)\n\t\t\tfor(var j = 0; j <= options.height; j += off)\n\t\t\t\td = d + \"M\" + (i - size) + \" \" + j + \" l\" + (2*size) + \" 0 m\" + (-size) + \" \" + (-size) + \" l0 \" + (2*size) + \" m0\" + (-size) + \" \";\n\t\t\t\t\t\t\t\n\t\tORYX.Editor.graft(\"http://www.w3.org/2000/svg\", this.node.firstChild.firstChild,\n\t\t\t['path', {d:d , stroke:'#000000', 'stroke-width':'0.15px'},]);\n\t\t*/\n\t\t\n\t\t//Global definition of default font for shapes\n\t\t//Definitions in the SVG definition of a stencil will overwrite these settings for\n\t\t// that stencil.\n\t\t/*if(navigator.platform.indexOf(\"Mac\") > -1) {\n\t\t\tthis.node.setAttributeNS(null, 'stroke', 'black');\n\t\t\tthis.node.setAttributeNS(null, 'stroke-width', '0.5px');\n\t\t\tthis.node.setAttributeNS(null, 'font-family', 'Skia');\n\t\t\t//this.node.setAttributeNS(null, 'letter-spacing', '2px');\n\t\t\tthis.node.setAttributeNS(null, 'font-size', ORYX.CONFIG.LABEL_DEFAULT_LINE_HEIGHT);\n\t\t} else {\n\t\t\tthis.node.setAttributeNS(null, 'stroke', 'none');\n\t\t\tthis.node.setAttributeNS(null, 'font-family', 'Verdana');\n\t\t\tthis.node.setAttributeNS(null, 'font-size', ORYX.CONFIG.LABEL_DEFAULT_LINE_HEIGHT);\n\t\t}*/\n\t\t\n\t\tthis.node.setAttributeNS(null, 'stroke', 'none');\n\t\tthis.node.setAttributeNS(null, 'font-family', 'Verdana, sans-serif');\n\t\tthis.node.setAttributeNS(null, 'font-size-adjust', 'none');\n\t\tthis.node.setAttributeNS(null, 'font-style', 'normal');\n\t\tthis.node.setAttributeNS(null, 'font-variant', 'normal');\n\t\tthis.node.setAttributeNS(null, 'font-weight', 'normal');\n\t\tthis.node.setAttributeNS(null, 'line-heigth', 'normal');\n\t\t\n\t\tthis.node.setAttributeNS(null, 'font-size', ORYX.CONFIG.LABEL_DEFAULT_LINE_HEIGHT);\n\t\t\t\n\t\tthis.bounds.set(0,0,options.width, options.height);\n\t\t\n\t\tthis.addEventHandlers(this.rootNode.parentNode);\n\t\t\n\t\t//disable context menu\n\t\tthis.rootNode.oncontextmenu = function() {return false;};\n\t},\n\t\n\tfocus: function(){\n\t\t\n\t\ttry {\n\t\t\t// Get a href\n\t\t\tif (!this.focusEl) \n\t\t\t{\n\t\t\t\tthis.focusEl = jQuery('body').append(jQuery('<a href=\"#\" class=\"x-grid3-focus x-grid3-focus-canvas\"/>'));\n\t\t\t\tthis.focusEl.swallowEvent(\"click\", true);\n\t\t\t}\n\t\t\t\n\t\t\t// Focus it\n\t\t\tthis.focusEl.focus.defer(1, this.focusEl);\n\t\t\tthis.focusEl.blur.defer(3, this.focusEl);\n\t\t\t\n\t\t} catch(e){}\n\t},\n\t\n\tsetHightlightState: function(state) {\n\t\tif(this.colHighlightEnabled && this.colHighlightState != state) {\n\t\t\tif(state == 0) {\n\t\t\t\tthis.columnHightlight1.setAttribute(\"visibility\", \"hidden\");\n\t\t\t\tthis.columnHightlight2.setAttribute(\"visibility\", \"hidden\");\n\t\t\t} else if(state == 1) {\n\t\t\t\tthis.columnHightlight1.setAttribute(\"visibility\", \"visible\");\n\t\t\t\tthis.columnHightlight2.setAttribute(\"visibility\", \"hidden\");\n\t\t\t} else if(state == 2) {\n\t\t\t\tthis.columnHightlight1.setAttribute(\"visibility\", \"hidden\");\n\t\t\t\tthis.columnHightlight2.setAttribute(\"visibility\", \"visible\");\n\t\t\t} else if(state == 3) {\n\t\t\t\tthis.columnHightlight1.setAttribute(\"visibility\", \"visible\");\n\t\t\t\tthis.columnHightlight2.setAttribute(\"visibility\", \"visible\");\n\t\t\t}\n\t\t\tthis.colHighlightState = state;\n\t\t}\n\t},\n\t\n\tsetHightlightStateBasedOnX : function(x) {\n\t\tif(x > ORYX.CONFIG.FORM_ROW_WIDTH + 30) {\n\t\t\tthis.setHightlightState(2);\n\t\t} else {\n\t\t\tthis.setHightlightState(1);\n\t\t}\n\t},\n\t\n\tupdate: function() {\n\t\t\n\t\tthis.nodes.each(function(node) {\n\t\t\tthis._traverseForUpdate(node);\n\t\t}.bind(this));\n\t\t\n\t\t// call stencil's layout callback\n\t\t// (needed for row layouting of xforms)\n\t\t//this.getStencil().layout(this);\n\t\t\n\t\tvar layoutEvents = this.getStencil().layout();\n\t\t\n\t\tif(layoutEvents) {\n\t\t\tlayoutEvents.each(function(event) {\n\t\t\n\t\t\t\t// setup additional attributes\n\t\t\t\tevent.shape = this;\n\t\t\t\tevent.forceExecution = true;\n\t\t\t\tevent.target = this.rootNode;\n\t\t\t\t\n\t\t\t\t// do layouting\n\t\t\t\t\n\t\t\t\tthis._delegateEvent(event);\n\t\t\t}.bind(this))\n\t\t}\n\t\t\n\t\tthis.nodes.invoke(\"_update\");\n\t\t\n\t\tthis.edges.invoke(\"_update\", true);\n\t\t\n\t\t/*this.children.each(function(child) {\n\t\t\tchild._update();\n\t\t});*/\n\t},\n\t\n\t_traverseForUpdate: function(shape) {\n\t\tvar childRet = shape.isChanged;\n\t\tshape.getChildNodes(false, function(child) {\n\t\t\tif(this._traverseForUpdate(child)) {\n\t\t\t\tchildRet = true;\n\t\t\t}\n\t\t}.bind(this));\n\t\t\n\t\tif(childRet) {\n\t\t\tshape.layout();\n\t\t\treturn true;\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t},\n\t\n\tlayout: function() {\n\t\t\n\t\t\n\t\t\n\t},\n\t\n\t/**\n\t * \n\t * @param {Object} deep\n\t * @param {Object} iterator\n\t */\n\tgetChildNodes: function(deep, iterator) {\n\t\tif(!deep && !iterator) {\n\t\t\treturn this.nodes.clone();\n\t\t} else {\n\t\t\tvar result = [];\n\t\t\tthis.nodes.each(function(uiObject) {\n\t\t\t\tif(iterator) {\n\t\t\t\t\titerator(uiObject);\n\t\t\t\t}\n\t\t\t\tresult.push(uiObject);\n\t\t\t\t\n\t\t\t\tif(deep && uiObject instanceof ORYX.Core.Shape) {\n\t\t\t\t\tresult = result.concat(uiObject.getChildNodes(deep, iterator));\n\t\t\t\t}\n\t\t\t});\n\t\n\t\t\treturn result;\n\t\t}\n\t},\n\t\n\t/**\n\t * buggy crap! use base class impl instead! \n\t * @param {Object} iterator\n\t */\n/*\tgetChildEdges: function(iterator) {\n\t\tif(iterator) {\n\t\t\tthis.edges.each(function(edge) {\n\t\t\t\titerator(edge);\n\t\t\t});\n\t\t}\n\t\t\n\t\treturn this.edges.clone();\n\t},\n*/\t\n\t/**\n\t * Overrides the UIObject.add method. Adds uiObject to the correct sub node.\n\t * @param {UIObject} uiObject\n\t */\n\tadd: function(uiObject, index, silent) {\n\t\t//if uiObject is child of another UIObject, remove it.\n\t\tif(uiObject instanceof ORYX.Core.UIObject) {\n\t\t\tif (!(this.children.member(uiObject))) {\n\t\t\t\t//if uiObject is child of another parent, remove it from that parent.\n\t\t\t\tif(uiObject.parent) {\n\t\t\t\t\tuiObject.parent.remove(uiObject, true);\n\t\t\t\t}\n\n\t\t\t\t//add uiObject to the Canvas\n\t\t\t\t//add uiObject to this Shape\n\t\t\t\tif(index != undefined)\n\t\t\t\t\tthis.children.splice(index, 0, uiObject);\n\t\t\t\telse\n\t\t\t\t\tthis.children.push(uiObject);\n\n\t\t\t\t//set parent reference\n\t\t\t\tuiObject.parent = this;\n\n\t\t\t\t//add uiObject.node to this.node depending on the type of uiObject\n\t\t\t\tif(uiObject instanceof ORYX.Core.Shape) {\n\t\t\t\t\tif(uiObject instanceof ORYX.Core.Edge) {\n\t\t\t\t\t\tuiObject.addMarkers(this.rootNode.getElementsByTagNameNS(NAMESPACE_SVG, \"defs\")[0]);\n\t\t\t\t\t\tuiObject.node = this.node.childNodes[0].childNodes[2].appendChild(uiObject.node);\n\t\t\t\t\t\tthis.edges.push(uiObject);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tuiObject.node = this.node.childNodes[0].childNodes[1].appendChild(uiObject.node);\n\t\t\t\t\t\tthis.nodes.push(uiObject);\n\t\t\t\t\t}\n\t\t\t\t} else {\t//UIObject\n\t\t\t\t\tuiObject.node = this.node.appendChild(uiObject.node);\n\t\t\t\t}\n\n\t\t\t\tuiObject.bounds.registerCallback(this._changedCallback);\n\t\t\t\t\t\n\t\t\t\tif(this.eventHandlerCallback && silent !== true)\n\t\t\t\t\tthis.eventHandlerCallback({type:ORYX.CONFIG.EVENT_SHAPEADDED,shape:uiObject})\n\t\t\t} else {\n\t\t\t\t\n\t\t\t\tORYX.Log.warn(\"add: ORYX.Core.UIObject is already a child of this object.\");\n\t\t\t}\n\t\t} else {\n\n\t\t\tORYX.Log.fatal(\"add: Parameter is not of type ORYX.Core.UIObject.\");\n\t\t}\n\t},\n\n\t/**\n\t * Overrides the UIObject.remove method. Removes uiObject.\n\t * @param {UIObject} uiObject\n\t */\n\tremove: function(uiObject, silent) {\n\t\t//if uiObject is a child of this object, remove it.\n\t\tif (this.children.member(uiObject)) {\n\t\t\t//remove uiObject from children\n\t\t\tvar parent = uiObject.parent;\n\t\t\t\t\t\t\n\t\t\tthis.children = this.children.without(uiObject);\n\n\t\t\t//delete parent reference of uiObject\n\t\t\tuiObject.parent = undefined;\n\n\t\t\t//delete uiObject.node from this.node\n\t\t\tif(uiObject instanceof ORYX.Core.Shape) {\n\t\t\t\tif(uiObject instanceof ORYX.Core.Edge) {\n\t\t\t\t\tuiObject.removeMarkers();\n\t\t\t\t\tuiObject.node = this.node.childNodes[0].childNodes[2].removeChild(uiObject.node);\n\t\t\t\t\tthis.edges = this.edges.without(uiObject);\n\t\t\t\t} else {\n\t\t\t\t\tuiObject.node = this.node.childNodes[0].childNodes[1].removeChild(uiObject.node);\n\t\t\t\t\tthis.nodes = this.nodes.without(uiObject);\n\t\t\t\t}\n\t\t\t} else {\t//UIObject\n\t\t\t\t\tuiObject.node = this.node.removeChild(uiObject.node);\n\t\t\t}\n\n\t\t\tif(this.eventHandlerCallback && silent !== true)\n\t\t\t\tthis.eventHandlerCallback({type:ORYX.CONFIG.EVENT_SHAPEREMOVED,shape:uiObject, parent:parent});\n\t\t\t\t\n\t\t\tuiObject.bounds.unregisterCallback(this._changedCallback);\n\t\t} else {\n\n\t\t\tORYX.Log.warn(\"remove: ORYX.Core.UIObject is not a child of this object.\");\n\t\t}\n\t},\n    \n    /**\n     * Creates shapes out of the given collection of shape objects and adds them to the canvas.\n     * @example \n     * canvas.addShapeObjects({\n         bounds:{ lowerRight:{ y:510, x:633 }, upperLeft:{ y:146, x:210 } },\n         resourceId:\"oryx_F0715955-50F2-403D-9851-C08CFE70F8BD\",\n         childShapes:[],\n         properties:{},\n         stencil:{\n           id:\"Subprocess\"\n         },\n         outgoing:[{resourceId: 'aShape'}],\n         target: {resourceId: 'aShape'}\n       });\n     * @param {Object} shapeObjects \n     * @param {Function} [eventHandler] An event handler passed to each newly created shape (as eventHandlerCallback)\n     * @return {Array} A collection of ORYX.Core.Shape\n     * @methodOf ORYX.Core.Canvas.prototype\n     */\n    addShapeObjects: function(shapeObjects, eventHandler){\n        if(!shapeObjects) return;\n\t\t\n\t\tthis.initializingShapes = true;\n        \n        /*FIXME This implementation is very evil! At first, all shapes are created on\n          canvas. In a second step, the attributes are applied. There must be a distinction\n          between the configuration phase (where the outgoings, for example, are just named),\n          and the creation phase (where the outgoings are evaluated). This must be reflected\n          in code to provide a nicer API/ implementation!!! */\n        \n        var addShape = function(shape, parent){\n            // Create a new Stencil\n            var stencil = ORYX.Core.StencilSet.stencil(this.getStencil().namespace() + shape.stencil.id );\n\n            // Create a new Shape\n            var ShapeClass = (stencil.type() == \"node\") ? ORYX.Core.Node : ORYX.Core.Edge;\n            var newShape = new ShapeClass(\n              {'eventHandlerCallback': eventHandler},\n              stencil, this.facade);\n            \n            // Set the resource id\n            newShape.resourceId = shape.resourceId;\n            newShape.node.id = \"svg-\" + shape.resourceId;\n\t\t\t\n            // Set parent to json object to be used later\n            // Due to the nested json structure, normally shape.parent is not set/ must not be set. \n            // In special cases, it can be easier to set this directly instead of a nested structure.\n            shape.parent = \"#\" + ((shape.parent && shape.parent.resourceId) || parent.resourceId);\n            \n            // Add the shape to the canvas\n            this.add( newShape );\n\n            return {\n              json: shape,\n              object: newShape\n            };\n        }.bind(this);\n        \n        /** Builds up recursively a flatted array of shapes, including a javascript object and json representation\n         * @param {Object} shape Any object that has Object#childShapes\n         */\n        var addChildShapesRecursively = function(shape){\n            var addedShapes = [];\n        \n            if (shape.childShapes && shape.childShapes.constructor == String)\n            {\n            \tshape.childShapes = JSON.parse(shape.childShapes);\n            }\n \n            shape.childShapes.each(function(childShape){\n              addedShapes.push(addShape(childShape, shape));\n              addedShapes = addedShapes.concat(addChildShapesRecursively(childShape));\n            });\n            \n            return addedShapes;\n        }.bind(this);\n\n        var shapes = addChildShapesRecursively({\n            childShapes: shapeObjects, \n            resourceId: this.resourceId\n        });\n                    \n\n        // prepare deserialisation parameter\n        shapes.each(\n            function(shape){\n            \tvar properties = [];\n                for(field in shape.json.properties){\n                    properties.push({\n                      prefix: 'oryx',\n                      name: field,\n                      value: shape.json.properties[field]\n                    });\n                  }\n                  \n                  // Outgoings\n                  shape.json.outgoing.each(function(out){\n                    properties.push({\n                      prefix: 'raziel',\n                      name: 'outgoing',\n                      value: \"#\"+out.resourceId\n                    });\n                  });\n                  \n                  // Target \n                  // (because of a bug, the first outgoing is taken when there is no target,\n                  // can be removed after some time)\n                  if(shape.object instanceof ORYX.Core.Edge) {\n\t                  var target = shape.json.target || shape.json.outgoing[0];\n\t                  if(target){\n\t                    properties.push({\n\t                      prefix: 'raziel',\n\t                      name: 'target',\n\t                      value: \"#\"+target.resourceId\n\t                    });\n\t                  }\n                  }\n                  \n                  // Bounds\n                  if (shape.json.bounds) {\n                      properties.push({\n                          prefix: 'oryx',\n                          name: 'bounds',\n                          value: shape.json.bounds.upperLeft.x + \",\" + shape.json.bounds.upperLeft.y + \",\" + shape.json.bounds.lowerRight.x + \",\" + shape.json.bounds.lowerRight.y\n                      });\n                  }\n                  \n                  //Dockers [{x:40, y:50}, {x:30, y:60}] => \"40 50 30 60  #\"\n                  if(shape.json.dockers){\n                    properties.push({\n                      prefix: 'oryx',\n                      name: 'dockers',\n                      value: shape.json.dockers.inject(\"\", function(dockersStr, docker){\n                        return dockersStr + docker.x + \" \" + docker.y + \" \";\n                      }) + \" #\"\n                    });\n                  }\n                  \n                  //Parent\n                  properties.push({\n                    prefix: 'raziel',\n                    name: 'parent',\n                    value: shape.json.parent\n                  });\n            \n                  shape.__properties = properties;\n\t         }.bind(this)\n        );\n  \n        // Deserialize the properties from the shapes\n        // This can't be done earlier because Shape#deserialize expects that all referenced nodes are already there\n        \n        // first, deserialize all nodes\n        shapes.each(function(shape) {\n        \tif(shape.object instanceof ORYX.Core.Node) {\n        \t\tshape.object.deserialize(shape.__properties, shape.json);\n        \t}\n        });\n        \n        // second, deserialize all edges\n        shapes.each(function(shape) {\n        \tif(shape.object instanceof ORYX.Core.Edge) {\n        \t\tshape.object.deserialize(shape.__properties, shape.json);\n\t\t\t\tshape.object._oldBounds = shape.object.bounds.clone();\n\t\t\t\tshape.object._update();\n        \t}\n        });\n       \n\t\tdelete this.initializingShapes;\n        return shapes.pluck(\"object\");\n    },\n    \n    /**\n     * Updates the size of the canvas, regarding to the containg shapes.\n     */\n    updateSize: function(){\n        // Check the size for the canvas\n        var maxWidth    = 0;\n        var maxHeight   = 0;\n        var offset      = 100;\n        this.getChildShapes(true, function(shape){\n            var b = shape.bounds;\n            maxWidth    = Math.max( maxWidth, b.lowerRight().x + offset)\n            maxHeight   = Math.max( maxHeight, b.lowerRight().y + offset)\n        }); \n        \n        if( this.bounds.width() < maxWidth || this.bounds.height() < maxHeight ){\n            this.setSize({width: Math.max(this.bounds.width(), maxWidth), height: Math.max(this.bounds.height(), maxHeight)})\n        }\n    },\n\n\tgetRootNode: function() {\n\t\treturn this.rootNode;\n\t},\n\t\n\tgetUnderlayNode: function() {\n\t\treturn this.underlayNode;\n\t},\n\t\n\tgetSvgContainer: function() {\n\t\treturn this.node.childNodes[1];\n\t},\n\t\n\tgetHTMLContainer: function() {\n\t\treturn this._htmlContainer;\n\t},\t\n\n\t/**\n\t * Return all elements of the same highest level\n\t * @param {Object} elements\n\t */\n\tgetShapesWithSharedParent: function(elements) {\n\n\t\t// If there is no elements, return []\n\t\tif(!elements || elements.length < 1) { return []; }\n\t\t// If there is one element, return this element\n\t\tif(elements.length == 1) { return elements;}\n\n\t\treturn elements.findAll(function(value){\n\t\t\tvar parentShape = value.parent;\n\t\t\twhile(parentShape){\n\t\t\t\tif(elements.member(parentShape)) return false;\n\t\t\t\tparentShape = parentShape.parent;\n\t\t\t}\n\t\t\treturn true;\n\t\t});\t\t\n\n\t},\n\n\tsetSize: function(size, dontSetBounds) {\n\t\tif(!size || !size.width || !size.height){return;};\n\t\t\n\t\tif(this.rootNode.parentNode){\n\t\t\tthis.rootNode.parentNode.style.width = size.width + 'px';\n\t\t\tthis.rootNode.parentNode.style.height = size.height + 'px';\n\t\t}\n\t\t\n\t\tthis.rootNode.setAttributeNS(null, 'width', size.width);\n\t\tthis.rootNode.setAttributeNS(null, 'height', size.height);\n\n\t\t//this._htmlContainer.style.top = \"-\" + (size.height + 4) + 'px';\t\t\n\t\tif( !dontSetBounds ){\n\t\t\tthis.bounds.set({a:{x:0,y:0},b:{x:size.width/this.zoomLevel,y:size.height/this.zoomLevel}});\n\t\t}\n\t},\n\t\n\t/**\n\t * Returns an SVG document of the current process.\n\t * @param {Boolean} escapeText Use true, if you want to parse it with an XmlParser,\n\t * \t\t\t\t\tfalse, if you want to use the SVG document in browser on client side.\n\t */\n\tgetSVGRepresentation: function(escapeText) {\n\t\t// Get the serialized svg image source\n        var svgClone = this.getRootNode().cloneNode(true);\n\t\t\n\t\tthis._removeInvisibleElements(svgClone);\n\t\t\n\t\tvar x1, y1, x2, y2;\n\t\tthis.getChildShapes(true).each(function(shape) {\n\t\t\tvar absBounds = shape.absoluteBounds();\n\t\t\tvar ul = absBounds.upperLeft();\n\t\t\tvar lr = absBounds.lowerRight();\n\t\t\tif(x1 == undefined) {\n\t\t\t\tx1 = ul.x;\n\t\t\t\ty1 = ul.y;\n\t\t\t\tx2 = lr.x;\n\t\t\t\ty2 = lr.y;\n\t\t\t} else {\n\t\t\t\tx1 = Math.min(x1, ul.x);\n\t\t\t\ty1 = Math.min(y1, ul.y);\n\t\t\t\tx2 = Math.max(x2, lr.x);\n\t\t\t\ty2 = Math.max(y2, lr.y);\n\t\t\t}\n\t\t});\n\t\t\n\t\tvar margin = 50;\n\t\tvar width, height, tx, ty;\n\t\tif(x1 == undefined) {\n\t\t\twidth = 0;\n\t\t\theight = 0;\n\t\t\ttx = 0;\n\t\t\tty = 0;\n\t\t} else {\n\t\t\twidth = x2;\n\t\t\theight = y2;\n\t\t\ttx = -x1+margin/2;\n\t\t\tty = -y1+margin/2;\n\t\t}\n\t\t\n        // Set the width and height\n        svgClone.setAttributeNS(null, 'width', width + margin);\n        svgClone.setAttributeNS(null, 'height', height + margin);\n\t\t\n\t\t//remove scale factor\n\t\tsvgClone.childNodes[1].removeAttributeNS(null, 'transform');\n\t\t\n\t\ttry{\n\t\t\tvar svgCont = svgClone.childNodes[1].childNodes[1];\n\t\t\tsvgCont.parentNode.removeChild(svgCont);\n\t\t} catch(e) {}\n\n\t\tif(escapeText) {\n\t\t\t$A(svgClone.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'tspan')).each(function(elem) {\n\t\t\t\telem.textContent = elem.textContent.escapeHTML();\n\t\t\t});\n\t\t\t\n\t\t\t$A(svgClone.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'text')).each(function(elem) {\n\t\t\t\tif(elem.childNodes.length == 0)\n\t\t\t\t\telem.textContent = elem.textContent.escapeHTML();\n\t\t\t});\n\t\t}\n\t\t\n\t\t// generating absolute urls for the pdf-exporter\n\t\t$A(svgClone.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'image')).each(function(elem) {\n\t\t\tvar href = elem.getAttributeNS(\"http://www.w3.org/1999/xlink\",\"href\");\n\t\t\t\n\t\t\tif(!href.match(\"^(http|https)://\")) {\n\t\t\t\thref = window.location.protocol + \"//\" + window.location.host + href;\n\t\t\t\telem.setAttributeNS(\"http://www.w3.org/1999/xlink\", \"href\", href);\n\t\t\t}\n\t\t});\n\t\t\n\t\t\n\t\t// escape all links\n\t\t$A(svgClone.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'a')).each(function(elem) {\n\t\t\telem.setAttributeNS(\"http://www.w3.org/1999/xlink\", \"xlink:href\", (elem.getAttributeNS(\"http://www.w3.org/1999/xlink\",\"href\")||\"\").escapeHTML());\n\t\t});\n\t\t\n        return svgClone;\n\t},\n\t\n\t/**   \n\t* Removes all nodes (and its children) that has the\n\t* attribute visibility set to \"hidden\"\n\t*/\n\t_removeInvisibleElements: function(element) {\n\t\tvar index = 0;\n\t\twhile(index < element.childNodes.length) {\n\t\t\tvar child = element.childNodes[index];\n\t\t\tif(child.getAttributeNS &&\n\t\t\t\tchild.getAttributeNS(null, \"visibility\") === \"hidden\") {\n\t\t\t\telement.removeChild(child);\n\t\t\t} else {\n\t\t\t\tthis._removeInvisibleElements(child);\n\t\t\t\tindex++; \n\t\t\t}\n\t\t}\n\t\t\n\t},\n\t\n\t/**\n\t * This method checks all shapes on the canvas and removes all shapes that\n\t * contain invalid bounds values or dockers values(NaN)\n\t */\n\t/*cleanUp: function(parent) {\n\t\tif (!parent) {\n\t\t\tparent = this;\n\t\t}\n\t\tparent.getChildShapes().each(function(shape){\n\t\t\tvar a = shape.bounds.a;\n\t\t\tvar b = shape.bounds.b;\n\t\t\tif (isNaN(a.x) || isNaN(a.y) || isNaN(b.x) || isNaN(b.y)) {\n\t\t\t\tparent.remove(shape);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tshape.getDockers().any(function(docker) {\n\t\t\t\t\ta = docker.bounds.a;\n\t\t\t\t\tb = docker.bounds.b;\n\t\t\t\t\tif (isNaN(a.x) || isNaN(a.y) || isNaN(b.x) || isNaN(b.y)) {\n\t\t\t\t\t\tparent.remove(shape);\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\treturn false;\n\t\t\t\t});\n\t\t\t\tshape.getMagnets().any(function(magnet) {\n\t\t\t\t\ta = magnet.bounds.a;\n\t\t\t\t\tb = magnet.bounds.b;\n\t\t\t\t\tif (isNaN(a.x) || isNaN(a.y) || isNaN(b.x) || isNaN(b.y)) {\n\t\t\t\t\t\tparent.remove(shape);\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\treturn false;\n\t\t\t\t});\n\t\t\t\tthis.cleanUp(shape);\n\t\t\t}\n\t\t}.bind(this));\n\t},*/\n\n\t_delegateEvent: function(event) {\n\t\tif(this.eventHandlerCallback && ( event.target == this.rootNode || event.target == this.rootNode.parentNode )) {\n\t\t\tthis.eventHandlerCallback(event, this);\n\t\t}\n\t},\n\t\n\ttoString: function() { return \"Canvas \" + this.id },\n    \n    /**\n     * Calls {@link ORYX.Core.AbstractShape#toJSON} and adds some stencil set information.\n     */\n    toJSON: function() {\n        var json = arguments.callee.$.toJSON.apply(this, arguments);\n        \n//\t\tif(ORYX.CONFIG.STENCILSET_HANDLER.length > 0) {\n//\t\t\tjson.stencilset = {\n//\t\t\t\turl: this.getStencil().stencilSet().namespace()\n//\t        };\n//\t\t} else {\n\t\t\tjson.stencilset = {\n\t\t\t\turl: this.getStencil().stencilSet().source(),\n\t\t\t\tnamespace: this.getStencil().stencilSet().namespace()\n\t        };\t\n//\t\t}\n        \n        \n        return json;\n    }\n });/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\nvar idCounter = 0;\nvar ID_PREFIX = \"resource\";\n\n/**\n * Main initialization method. To be called when loading\n * of the document, including all scripts, is completed.\n */\nfunction init() {\n\n\tORYX.Log.debug(\"Querying editor instances\");\n\n\t// Hack for WebKit to set the SVGElement-Classes\n\tORYX.Editor.setMissingClasses();\n    \n    // If someone wants to create the editor instance himself\n    if (window.onOryxResourcesLoaded) {\n        window.onOryxResourcesLoaded();\n    } \n    // Else fetch the model from server and display editor\n    else {\n\t\tvar modelId = window.location.search.substring(4);\n\t\tvar modelUrl = \"./service/model/\" + modelId + \"/json\";\n\n        ORYX.Editor.createByUrl(modelUrl);\n    }\n}\n\n/**\n   @namespace Global Oryx name space\n   @name ORYX\n*/\nif(!ORYX) {var ORYX = {};}\n\n/**\n * The Editor class.\n * @class ORYX.Editor\n * @extends Clazz\n * @param {Object} config An editor object, passed to {@link ORYX.Editor#loadSerialized}\n * @param {String} config.id Any ID that can be used inside the editor. If fullscreen=false, any HTML node with this id must be present to render the editor to this node.\n * @param {boolean} [config.fullscreen=true] Render editor in fullscreen mode or not.\n * @param {String} config.stencilset.url Stencil set URL.\n * @param {String} [config.stencil.id] Stencil type used for creating the canvas.  \n * @param {Object} config.properties Any properties applied to the canvas.\n*/\nORYX.Editor = {\n    /** @lends ORYX.Editor.prototype */\n\t// Defines the global dom event listener \n\tDOMEventListeners: new Hash(),\n\n\t// Defines the selection\n\tselection: [],\n\t\n\t// Defines the current zoom level\n\tzoomLevel:1.0,\n\n\tconstruct: function(config) {\n\t\t\n\t\t// initialization.\n\t\tthis._eventsQueue \t= [];\n\t\tthis.loadedPlugins \t= [];\n\t\tthis.pluginsData \t= [];\n\t\t\n\t\t\n\t\t//meta data about the model for the signavio warehouse\n\t\t//directory, new, name, description, revision, model (the model data)\n\t\t\n\t\tthis.modelMetaData = config;\n\t\t\n\t\tvar model = config;\n\t\t\n\t\tthis.id = model.modelId;\n\t\t\n\t\tif(config.model) {\n\t\t\tmodel = config.model;\n\t\t}\n\t\t\n        if(!this.id) {\n        \tthis.id = model.id;\n        \tif(!this.id) {\n        \t\tthis.id = ORYX.Editor.provideId();\n        \t}\n        }\n\t\t\n        // Defines if the editor should be fullscreen or not\n\t\tthis.fullscreen = config.fullscreen !== false;\n\t\t\n\t\t// Initialize the eventlistener\n\t\tthis._initEventListener();\n\n\t\t// Load particular stencilset\n\t\tif(ORYX.CONFIG.BACKEND_SWITCH) {\n\t\t\tvar ssUrl = (model.stencilset.namespace||model.stencilset.url).replace(\"#\", \"%23\");\n        \tORYX.Core.StencilSet.loadStencilSet(ssUrl, this.modelMetaData, this.id);\n\t\t} else {\n\t\t\tvar ssUrl = model.stencilset.url;\n        \tORYX.Core.StencilSet.loadStencilSet(ssUrl, this.modelMetaData, this.id);\n\t\t}\n\n\t\t// CREATES the canvas\n\t\tthis._createCanvas(model.stencil ? model.stencil.id : null, model.properties);\n\n\t\t// GENERATES the whole EXT.VIEWPORT\n\t\tthis._generateGUI();\n\n\t\t// Initializing of a callback to check loading ends\n\t\tvar loadPluginFinished \t= false;\n\t\tvar loadContentFinished = false;\n\t\tvar initFinished = function(){\t\n\t\t\tif( !loadPluginFinished || !loadContentFinished ){ return }\n\t\t\tthis._finishedLoading();\n\t\t}.bind(this)\n\t\t\n\t\t// LOAD the plugins\n\t\twindow.setTimeout(function(){\n\t\t\tthis.loadPlugins();\n\t\t\tloadPluginFinished = true;\n\t\t\tinitFinished();\n\t\t}.bind(this), 100);\n\n\t\t// LOAD the content of the current editor instance\n\t\twindow.setTimeout(function(){\n            this.loadSerialized(model, true); // Request the meta data as well\n            this.getCanvas().update();\n\t\t\tloadContentFinished = true;\n\t\t\tinitFinished();\n\t\t}.bind(this), 200);\n\t},\n\t\n\t_finishedLoading: function() {\n\t\t// Raise Loaded Event\n\t\tthis.handleEvents( {type:ORYX.CONFIG.EVENT_LOADED} )\n\t},\n\t\n\t_initEventListener: function(){\n\n\t\t// Register on Events\n\t\t\n\t\tdocument.documentElement.addEventListener(ORYX.CONFIG.EVENT_KEYDOWN, this.catchKeyDownEvents.bind(this), false);\n\t\tdocument.documentElement.addEventListener(ORYX.CONFIG.EVENT_KEYUP, this.catchKeyUpEvents.bind(this), false);\n\n\t\t// Enable Key up and down Event\n\t\tthis._keydownEnabled = \ttrue;\n\t\tthis._keyupEnabled =  \ttrue;\n\n\t\tthis.DOMEventListeners[ORYX.CONFIG.EVENT_MOUSEDOWN] = [];\n\t\tthis.DOMEventListeners[ORYX.CONFIG.EVENT_MOUSEUP] \t= [];\n\t\tthis.DOMEventListeners[ORYX.CONFIG.EVENT_MOUSEOVER] = [];\n\t\tthis.DOMEventListeners[ORYX.CONFIG.EVENT_MOUSEOUT] \t= [];\n\t\tthis.DOMEventListeners[ORYX.CONFIG.EVENT_SELECTION_CHANGED] = [];\n\t\tthis.DOMEventListeners[ORYX.CONFIG.EVENT_MOUSEMOVE] = [];\n\t\t\t\t\n\t},\n\t\n\t/**\n\t * Generate the whole viewport of the\n\t * Editor and initialized the Ext-Framework\n\t * \n\t */\n\t_generateGUI: function() {\n\n\t\t// Defines the layout height if it's NOT fullscreen\n\t\tvar layoutHeight \t= ORYX.CONFIG.WINDOW_HEIGHT;\n\t\tvar canvasParent\t= this.getCanvas().rootNode.parentNode;\n\t\t\n\t\tjQuery(\"#canvasSection\").append(canvasParent);\n\t\t\n\t\t// Set the editor to the center, and refresh the size\n\t \tcanvasParent.parentNode.setAttributeNS(null, 'align', 'center');\n\t \tcanvasParent.setAttributeNS(null, 'align', 'left');\n\t\tthis.getCanvas().setSize({\n\t\t\twidth\t: ORYX.CONFIG.CANVAS_WIDTH,\n\t\t\theight\t: ORYX.CONFIG.CANVAS_HEIGHT\n\t\t});\t\t\n\t\t\t\t\t\t\n\t},\n\t\n\tgetAvailablePlugins: function(){\n\t\tvar curAvailablePlugins=ORYX.availablePlugins.clone();\n\t\tcurAvailablePlugins.each(function(plugin){\n\t\t\tif(this.loadedPlugins.find(function(loadedPlugin){\n\t\t\t\treturn loadedPlugin.type==this.name;\n\t\t\t}.bind(plugin))){\n\t\t\t\tplugin.engaged=true;\n\t\t\t}else{\n\t\t\t\tplugin.engaged=false;\n\t\t\t}\n\t\t\t}.bind(this));\n\t\treturn curAvailablePlugins;\n\t},\n\n\tloadScript: function (url, callback){\n\t    var script = document.createElement(\"script\")\n\t    script.type = \"text/javascript\";\n\t    if (script.readyState){  //IE\n\t        script.onreadystatechange = function(){\n\t            if (script.readyState == \"loaded\" || script.readyState == \"complete\"){\n\t                script.onreadystatechange = null;\n\t                callback();\n\t            }\n        \t};\n    \t} else {  //Others\n\t        script.onload = function(){\n\t            callback();\n\t        };\n\t\t}\n\t    script.src = url;\n\t\tdocument.getElementsByTagName(\"head\")[0].appendChild(script);\n\t},\n\t/**\n\t * activate Plugin\n\t * \n\t * @param {String} name\n\t * @param {Function} callback\n\t * \t\tcallback(sucess, [errorCode])\n\t * \t\t\terrorCodes: NOTUSEINSTENCILSET, REQUIRESTENCILSET, NOTFOUND, YETACTIVATED\n\t */\n\tactivatePluginByName: function(name, callback, loadTry){\n\n\t\tvar match=this.getAvailablePlugins().find(function(value){return value.name==name});\n\t\tif(match && (!match.engaged || (match.engaged==='false'))){\t\t\n\t\t\t\tvar loadedStencilSetsNamespaces = this.getStencilSets().keys();\n\t\t\t\tvar facade = this._getPluginFacade();\n\t\t\t\tvar newPlugin;\n\t\t\t\tvar me=this;\n\t\t\t\tORYX.Log.debug(\"Initializing plugin '%0'\", match.name);\n\t\t\t\t\n\t\t\t\t\tif (!match.requires \t|| !match.requires.namespaces \t|| match.requires.namespaces.any(function(req){ return loadedStencilSetsNamespaces.indexOf(req) >= 0 }) ){\n\t\t\t\t\t\tif(!match.notUsesIn \t|| !match.notUsesIn.namespaces \t|| !match.notUsesIn.namespaces.any(function(req){ return loadedStencilSetsNamespaces.indexOf(req) >= 0 })){\n\t\n\t\t\t\t\ttry {\n\t\t\t\t\t\t\n\t\t\t\t\t\tvar className \t= eval(match.name);\n\t\t\t\t\t\t\tvar newPlugin = new className(facade, match);\n\t\t\t\t\t\t\tnewPlugin.type = match.name;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t// If there is an GUI-Plugin, they get all Plugins-Offer-Meta-Data\n\t\t\t\t\t\t\tif (newPlugin.registryChanged) \n\t\t\t\t\t\t\t\tnewPlugin.registryChanged(me.pluginsData);\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t// If there have an onSelection-Method it will pushed to the Editor Event-Handler\n\t\t\t\t\t\t\tif (newPlugin.onSelectionChanged) \n\t\t\t\t\t\t\t\tme.registerOnEvent(ORYX.CONFIG.EVENT_SELECTION_CHANGED, newPlugin.onSelectionChanged.bind(newPlugin));\n\t\t\t\t\t\t\tthis.loadedPlugins.push(newPlugin);\n\t\t\t\t\t\t\tthis.loadedPlugins.each(function(loaded){\n\t\t\t\t\t\t\t\tif(loaded.registryChanged)\n\t\t\t\t\t\t\t\t\tloaded.registryChanged(this.pluginsData);\n\t\t\t\t\t\t\t}.bind(me));\n\t\t\t\t\t\t\tcallback(true);\n\t\t\t\t\t\t\n\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\tORYX.Log.warn(\"Plugin %0 is not available\", match.name);\n\t\t\t\t\t\tif(!!loadTry){\n\t\t\t\t\t\t\tcallback(false,\"INITFAILED\");\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthis.loadScript(\"plugins/scripts/\"+match.source, this.activatePluginByName.bind(this,match.name,callback,true));\n\t\t\t\t\t}\n\t\t\t\t\t}else{\n\t\t\t\t\t\tcallback(false,\"NOTUSEINSTENCILSET\");\n\t\t\t\t\t\tORYX.Log.info(\"Plugin need a stencilset which is not loaded'\", match.name);\n\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\n\t\t\t\t} else {\n\t\t\t\t\tcallback(false,\"REQUIRESTENCILSET\");\n\t\t\t\t\tORYX.Log.info(\"Plugin need a stencilset which is not loaded'\", match.name);\n\t\t\t\t}\n\n\t\t\t\n\t\t\t}else{\n\t\t\t\tcallback(false, match?\"NOTFOUND\":\"YETACTIVATED\");\n\t\t\t\t//TODO error handling\n\t\t\t}\n\t},\n\n\t/**\n\t *  Laden der Plugins\n\t */\n\tloadPlugins: function() {\n\t\t\n\t\t// if there should be plugins but still are none, try again.\n\t\t// TODO this should wait for every plugin respectively.\n\t\t/*if (!ORYX.Plugins && ORYX.availablePlugins.length > 0) {\n\t\t\twindow.setTimeout(this.loadPlugins.bind(this), 100);\n\t\t\treturn;\n\t\t}*/\n\t\t\n\t\tvar me = this;\n\t\tvar newPlugins = [];\n\n\n\t\tvar loadedStencilSetsNamespaces = this.getStencilSets().keys();\n\n\t\t// Available Plugins will be initalize\n\t\tvar facade = this._getPluginFacade();\n\t\t\n\t\t// If there is an Array where all plugins are described, than only take those\n\t\t// (that comes from the usage of oryx with a mashup api)\n\t\tif( ORYX.MashupAPI && ORYX.MashupAPI.loadablePlugins && ORYX.MashupAPI.loadablePlugins instanceof Array ){\n\t\t\n\t\t\t// Get the plugins from the available plugins (those who are in the plugins.xml)\n\t\t\tORYX.availablePlugins = $A(ORYX.availablePlugins).findAll(function(value){\n\t\t\t\t\t\t\t\t\t\treturn ORYX.MashupAPI.loadablePlugins.include( value.name )\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\n\t\t\t// Add those plugins to the list, which are only in the loadablePlugins list\n\t\t\tORYX.MashupAPI.loadablePlugins.each(function( className ){\n\t\t\t\tif( !(ORYX.availablePlugins.find(function(val){ return val.name == className }))){\n\t\t\t\t\tORYX.availablePlugins.push( {name: className } );\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t\t\n\t\t\n\t\tORYX.availablePlugins.each(function(value) {\n\t\t\tORYX.Log.debug(\"Initializing plugin '%0'\", value.name);\n\t\t\t\tif( (!value.requires \t|| !value.requires.namespaces \t|| value.requires.namespaces.any(function(req){ return loadedStencilSetsNamespaces.indexOf(req) >= 0 }) ) &&\n\t\t\t\t\t(!value.notUsesIn \t|| !value.notUsesIn.namespaces \t|| !value.notUsesIn.namespaces.any(function(req){ return loadedStencilSetsNamespaces.indexOf(req) >= 0 }) )&&\n\t\t\t\t\t/*only load activated plugins or undefined */\n\t\t\t\t\t(value.engaged || (value.engaged===undefined)) ){\n\n\t\t\t\ttry {\n\t\t\t\t\tvar className \t= eval(value.name);\n\t\t\t\t\tif( className ){\n\t\t\t\t\t\tvar plugin\t\t= new className(facade, value);\n\t\t\t\t\t\tplugin.type\t\t= value.name;\n\t\t\t\t\t\tnewPlugins.push( plugin );\n\t\t\t\t\t\tplugin.engaged=true;\n\t\t\t\t\t}\n\t\t\t\t} catch(e) {\n\t\t\t\t\tORYX.Log.warn(\"Plugin %0 is not available %1\", value.name, e);\n\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t} else {\n\t\t\t\tORYX.Log.info(\"Plugin need a stencilset which is not loaded'\", value.name);\n\t\t\t}\n\t\t\t\n\t\t});\n\n\t\tnewPlugins.each(function(value) {\n\t\t\t// If there is an GUI-Plugin, they get all Plugins-Offer-Meta-Data\n\t\t\tif(value.registryChanged)\n\t\t\t\tvalue.registryChanged(me.pluginsData);\n\n\t\t\t// If there have an onSelection-Method it will pushed to the Editor Event-Handler\n\t\t\tif(value.onSelectionChanged)\n\t\t\t\tme.registerOnEvent(ORYX.CONFIG.EVENT_SELECTION_CHANGED, value.onSelectionChanged.bind(value));\n\t\t});\n\n\t\tthis.loadedPlugins = newPlugins;\n\t\t\n\t\tthis.registerPluginsOnKeyEvents();\n\t\t\n\t\tthis.setSelection();\n\t\t\n\t},\n\n\t/**\n\t * Creates the Canvas\n\t * @param {String} [stencilType] The stencil type used for creating the canvas. If not given, a stencil with myBeRoot = true from current stencil set is taken.\n\t * @param {Object} [canvasConfig] Any canvas properties (like language).\n\t */\n\t_createCanvas: function(stencilType, canvasConfig) {\n        if (stencilType) {\n            // Add namespace to stencilType\n            if (stencilType.search(/^http/) === -1) {\n                stencilType = this.getStencilSets().values()[0].namespace() + stencilType;\n            }\n        }\n        else {\n            // Get any root stencil type\n            stencilType = this.getStencilSets().values()[0].findRootStencilName();\n        }\n        \n\t\t// get the stencil associated with the type\n\t\tvar canvasStencil = ORYX.Core.StencilSet.stencil(stencilType);\n\t\t\t\n\t\tif (!canvasStencil) \n\t\t\tORYX.Log.fatal(\"Initialisation failed, because the stencil with the type %0 is not part of one of the loaded stencil sets.\", stencilType);\n\t\t\n\t\t// create all dom\n\t\t// TODO fix border, so the visible canvas has a double border and some spacing to the scrollbars\n\t\tvar div = ORYX.Editor.graft(\"http://www.w3.org/1999/xhtml\", null, ['div']);\n\t\t// set class for custom styling\n\t\tdiv.addClassName(\"ORYX_Editor\");\n\t\t\t\t\t\t\n\t\t// create the canvas\n\t\tthis._canvas = new ORYX.Core.Canvas({\n\t\t\twidth\t\t\t\t\t: ORYX.CONFIG.CANVAS_WIDTH,\n\t\t\theight\t\t\t\t\t: ORYX.CONFIG.CANVAS_HEIGHT,\n\t\t\t'eventHandlerCallback'\t: this.handleEvents.bind(this),\n\t\t\tid\t\t\t\t\t\t: this.id,\n\t\t\tparentNode\t\t\t\t: div\n\t\t}, canvasStencil, this._getPluginFacade());\n        \n        if (canvasConfig) {\n          // Migrate canvasConfig to an RDF-like structure\n          //FIXME this isn't nice at all because we don't want rdf any longer\n          var properties = [];\n          for(field in canvasConfig){\n            properties.push({\n              prefix: 'oryx',\n              name: field,\n              value: canvasConfig[field]\n            });\n          }\n            \n          this._canvas.deserialize(properties);\n        }\n\t\t\t\t\n\t},\n\n\t/**\n\t * Returns a per-editor singleton plugin facade.\n\t * To be used in plugin initialization.\n\t */\n\t_getPluginFacade: function() {\n\n\t\t// if there is no pluginfacade already created:\n\t\tif(!(this._pluginFacade))\n\n\t\t\t// create it.\n\t\t\tthis._pluginFacade = {\n\n\t\t\t\tactivatePluginByName:\t\tthis.activatePluginByName.bind(this),\n\t\t\t\t//deactivatePluginByName:\t\tthis.deactivatePluginByName.bind(this),\n\t\t\t\tgetAvailablePlugins:\tthis.getAvailablePlugins.bind(this),\n\t\t\t\toffer:\t\t\t\t\tthis.offer.bind(this),\n\t\t\t\tgetStencilSets:\t\t\tthis.getStencilSets.bind(this),\n\t\t\t\tgetStencilSetExtensionDefinition:function(){ return Object.clone(this.ss_extensions_def||{})}.bind(this),\n\t\t\t\tgetRules:\t\t\t\tthis.getRules.bind(this),\n\t\t\t\tloadStencilSet:\t\t\tthis.loadStencilSet.bind(this),\n\t\t\t\tcreateShape:\t\t\tthis.createShape.bind(this),\n\t\t\t\tdeleteShape:\t\t\tthis.deleteShape.bind(this),\n\t\t\t\tgetSelection:\t\t\tthis.getSelection.bind(this),\n\t\t\t\tsetSelection:\t\t\tthis.setSelection.bind(this),\n\t\t\t\tupdateSelection:\t\tthis.updateSelection.bind(this),\n\t\t\t\tgetCanvas:\t\t\t\tthis.getCanvas.bind(this),\n\t\t\t\t\n\t\t\t\timportJSON:\t\t\t\tthis.importJSON.bind(this),\n                getJSON:                this.getJSON.bind(this),\n                getSerializedJSON:      this.getSerializedJSON.bind(this),\n\t\t\t\t\n\t\t\t\texecuteCommands:\t\tthis.executeCommands.bind(this),\n\t\t\t\tisExecutingCommands:\tthis.isExecutingCommands.bind(this),\n\t\t\t\t\n\t\t\t\tregisterOnEvent:\t\tthis.registerOnEvent.bind(this),\n\t\t\t\tunregisterOnEvent:\t\tthis.unregisterOnEvent.bind(this),\n\t\t\t\traiseEvent:\t\t\t\tthis.handleEvents.bind(this),\n\t\t\t\tenableEvent:\t\t\tthis.enableEvent.bind(this),\n\t\t\t\tdisableEvent:\t\t\tthis.disableEvent.bind(this),\n\t\t\t\t\n\t\t\t\teventCoordinates:\t\tthis.eventCoordinates.bind(this),\n\t\t\t\teventCoordinatesXY:\t\tthis.eventCoordinatesXY.bind(this),\n\t\t\t\t\t\t\t\t\n\t\t\t\tgetModelMetaData:\t\tthis.getModelMetaData.bind(this)\n\t\t\t};\n\n\t\t// return it.\n\t\treturn this._pluginFacade;\n\t},\n\n\tisExecutingCommands: function(){\n\t\treturn !!this.commandExecuting;\n\t},\n\n\t/**\n\t * Implementes the command pattern\n\t * (The real usage of the command pattern\n\t * is implemented and shown in the Plugins/undo.js)\n\t *\n\t * @param <Oryx.Core.Command>[] Array of commands\n\t */\n\texecuteCommands: function(commands){\n\t\t\n\t\tif (!this.commandStack){\n\t\t\tthis.commandStack = [];\n\t\t}\n\t\tif (!this.commandStackExecuted){\n\t\t\tthis.commandStackExecuted = [];\n\t\t}\n\t\t\n\t\t\n\t\tthis.commandStack = [].concat(this.commandStack)\n\t\t\t\t\t\t\t  .concat(commands);\n\t\t\n\t\t// Check if already executes\n\t\tif (this.commandExecuting){ return; }\n\t\t\n\t\t// Start execution\n\t\tthis.commandExecuting = true;\n\t\t\n\t\t// Iterate over all commands\n\t\twhile(this.commandStack.length > 0){\n\t\t\tvar command = this.commandStack.shift();\n\t\t\t// and execute it\n\t\t\tcommand.execute();\n\t\t\tthis.commandStackExecuted.push(command);\n\t\t}\n\t\t\n\t\t// Raise event for executing commands\n\t\tthis.handleEvents({\n\t\t\ttype\t\t: ORYX.CONFIG.EVENT_EXECUTE_COMMANDS,\n\t\t\tcommands\t: this.commandStackExecuted\n\t\t});\n\t\t\n\t\t// Remove temporary vars\n\t\tdelete this.commandStack;\n\t\tdelete this.commandStackExecuted;\n\t\tdelete this.commandExecuting;\n\t\t\n\t\t\n\t\tthis.updateSelection();\n\n\t},\n\t\n    /**\n     * Returns JSON of underlying canvas (calls ORYX.Canvas#toJSON()).\n     * @return {Object} Returns JSON representation as JSON object.\n     */\n    getJSON: function(){\n    \tdelete Array.prototype.toJSON;\n        var canvasJSON = this.getCanvas().toJSON();\n        canvasJSON.ssextensions = this.getStencilSets().values()[0].extensions().keys().findAll(function(sse){ return !sse.endsWith('/meta#') });\n        return canvasJSON;\n    },\n    \n    /**\n     * Serializes a call to toJSON().\n     * @return {String} Returns JSON representation as string.\n     */\n    getSerializedJSON: function(){\n        return JSON.stringify(this.getJSON());\n    },\n    \n\t/**\n\t* Imports shapes in JSON as expected by {@link ORYX.Editor#loadSerialized}\n\t* @param {Object|String} jsonObject The (serialized) json object to be imported\n\t* @param {boolean } [noSelectionAfterImport=false] Set to true if no shapes should be selected after import\n\t* @throws {SyntaxError} If the serialized json object contains syntax errors\n\t*/\n\timportJSON: function(jsonObject, noSelectionAfterImport) {\n\t\t\n        try {\n            jsonObject = this.renewResourceIds(jsonObject);\n        } catch(error){\n            throw error;\n        }     \n\t\t//check, if the imported json model can be loaded in this editor\n\t\t// (stencil set has to fit)\n\t\tif(jsonObject.stencilset.namespace && jsonObject.stencilset.namespace !== this.getCanvas().getStencil().stencilSet().namespace()) {\n\t\t\talert(String.format(ORYX.I18N.JSONImport.wrongSS, jsonObject.stencilset.namespace, this.getCanvas().getStencil().stencilSet().namespace()));\n\t\t\treturn null;\n\t\t} else {\n\t\t\tvar commandClass = ORYX.Core.Command.extend({\n\t\t\tconstruct: function(jsonObject, loadSerializedCB, noSelectionAfterImport, facade){\n\t\t\t\tthis.jsonObject = jsonObject;\n\t\t\t\tthis.noSelection = noSelectionAfterImport;\n\t\t\t\tthis.facade = facade;\n\t\t\t\tthis.shapes;\n\t\t\t\tthis.connections = [];\n\t\t\t\tthis.parents = new Hash();\n\t\t\t\tthis.selection = this.facade.getSelection();\n\t\t\t\tthis.loadSerialized = loadSerializedCB;\n\t\t\t},\t\t\t\n\t\t\texecute: function(){\n\t\t\t\t\n\t\t\t\tif (!this.shapes) {\n\t\t\t\t\t// Import the shapes out of the serialization\t\t\n\t\t\t\t\tthis.shapes\t= this.loadSerialized( this.jsonObject );\t\t\n\t\t\t\t\t\n\t\t\t\t\t//store all connections\n\t\t\t\t\tthis.shapes.each(function(shape) {\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (shape.getDockers) {\n\t\t\t\t\t\t\tvar dockers = shape.getDockers();\n\t\t\t\t\t\t\tif (dockers) {\n\t\t\t\t\t\t\t\tif (dockers.length > 0) {\n\t\t\t\t\t\t\t\t\tthis.connections.push([dockers.first(), dockers.first().getDockedShape(), dockers.first().referencePoint]);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (dockers.length > 1) {\n\t\t\t\t\t\t\t\t\tthis.connections.push([dockers.last(), dockers.last().getDockedShape(), dockers.last().referencePoint]);\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\t\n\t\t\t\t\t\t//store parents\n\t\t\t\t\t\tthis.parents[shape.id] = shape.parent;\n\t\t\t\t\t}.bind(this));\n\t\t\t\t} else {\n\t\t\t\t\tthis.shapes.each(function(shape) {\n\t\t\t\t\t\tthis.parents[shape.id].add(shape);\n\t\t\t\t\t}.bind(this));\n\t\t\t\t\t\n\t\t\t\t\tthis.connections.each(function(con) {\n\t\t\t\t\t\tcon[0].setDockedShape(con[1]);\n\t\t\t\t\t\tcon[0].setReferencePoint(con[2]);\n\t\t\t\t\t\tcon[0].update();\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t//this.parents.values().uniq().invoke(\"update\");\n\t\t\t\tthis.facade.getCanvas().update();\t\t\t\n\t\t\t\t\t\n\t\t\t\tif(!this.noSelection)\n\t\t\t\t\tthis.facade.setSelection(this.shapes);\n\t\t\t\telse\n\t\t\t\t\tthis.facade.updateSelection();\n\t\t\t\t\t\n\t\t\t\t// call updateSize again, because during loadSerialized the edges' bounds  \n\t\t\t\t// are not yet initialized properly\n\t\t\t\tthis.facade.getCanvas().updateSize();\t\n\t\t\t\t\t\n\t\t\t\t},\n\t\t\t\trollback: function(){\n\t\t\t\t\tvar selection = this.facade.getSelection();\n\t\t\t\t\t\n\t\t\t\t\tthis.shapes.each(function(shape) {\n\t\t\t\t\t\tselection = selection.without(shape);\n\t\t\t\t\t\tthis.facade.deleteShape(shape);\n\t\t\t\t\t}.bind(this));\n\t\t\t\t\t\n\t\t\t\t\t/*this.parents.values().uniq().each(function(parent) {\n\t\t\t\t\t\tif(!this.shapes.member(parent))\n\t\t\t\t\t\t\tparent.update();\n\t\t\t\t\t}.bind(this));*/\n\t\t\t\t\t\n\t\t\t\t\tthis.facade.getCanvas().update();\n\t\t\t\t\t\n\t\t\t\t\tthis.facade.setSelection(selection);\n\t\t\t\t}\n\t\t\t})\n\t\t\t\n\t\t\tvar command = new commandClass(jsonObject, \n\t\t\t\t\t\t\t\t\t\t\tthis.loadSerialized.bind(this),\n\t\t\t\t\t\t\t\t\t\t\tnoSelectionAfterImport,\n\t\t\t\t\t\t\t\t\t\t\tthis._getPluginFacade());\n\t\t\t\n\t\t\tthis.executeCommands([command]);\t\n\t\t\t\n\t\t\treturn command.shapes.clone();\n\t\t}\n\t},\n    \n    /**\n     * This method renew all resource Ids and according references.\n     * Warning: The implementation performs a substitution on the serialized object for\n     * easier implementation. This results in a low performance which is acceptable if this\n     * is only used when importing models.\n     * @param {Object|String} jsonObject\n     * @throws {SyntaxError} If the serialized json object contains syntax errors.\n     * @return {Object} The jsonObject with renewed ids.\n     * @private\n     */\n    renewResourceIds: function(jsonObject){\n        // For renewing resource ids, a serialized and object version is needed\n        if(Object.prototype.toString.call(jsonObject) === \"String\"){\n            try {\n                var serJsonObject = jsonObject;\n                jsonObject = JSON.parse(jsonObject);\n            } catch(error){\n                throw new SyntaxError(error.message);\n            }\n        } else {\n            var serJsonObject = JSON.stringify(jsonObject);\n        }        \n        \n        // collect all resourceIds recursively\n        var collectResourceIds = function(shapes){\n            if(!shapes) return [];\n            \n            return shapes.map(function(shape){\n                return collectResourceIds(shape.childShapes).concat(shape.resourceId);\n            }).flatten();\n        }\n        var resourceIds = collectResourceIds(jsonObject.childShapes);\n        \n        // Replace each resource id by a new one\n        resourceIds.each(function(oldResourceId){\n            var newResourceId = ORYX.Editor.provideId();\n            serJsonObject = serJsonObject.replace(new RegExp(oldResourceId, 'g'), newResourceId);\n        });\n        \n        return JSON.parse(serJsonObject);\n    },\n\n    /**\n     * Loads serialized model to the oryx.\n     * @example\n     * editor.loadSerialized({\n     *    resourceId: \"mymodel1\",\n     *    childShapes: [\n     *       {\n     *          stencil:{ id:\"Subprocess\" },\n     *          outgoing:[{resourceId: 'aShape'}],\n     *          target: {resourceId: 'aShape'},\n     *          bounds:{ lowerRight:{ y:510, x:633 }, upperLeft:{ y:146, x:210 } },\n     *          resourceId: \"myshape1\",\n     *          childShapes:[],\n     *          properties:{},\n     *       }\n     *    ],\n     *    properties:{\n     *       language: \"English\"\n     *    },\n     *    stencilset:{\n     *       url:\"http://localhost:8080/oryx/stencilsets/bpmn1.1/bpmn1.1.json\"\n     *    },\n     *    stencil:{\n     *       id:\"BPMNDiagram\"\n     *    }\n     * });\n     * @param {Object} model Description of the model to load.\n     * @param {Array} [model.ssextensions] List of stenctil set extensions.\n     * @param {String} model.stencilset.url\n     * @param {String} model.stencil.id \n     * @param {Array} model.childShapes\n     * @param {Array} [model.properties]\n     * @param {String} model.resourceId\n     * @return {ORYX.Core.Shape[]} List of created shapes\n     * @methodOf ORYX.Editor.prototype\n     */\n    loadSerialized: function(model, requestMeta){\n        var canvas  = this.getCanvas();\n      \n        // Bugfix (cf. http://code.google.com/p/oryx-editor/issues/detail?id=240)\n        // Deserialize the canvas' stencil set extensions properties first!\n        this.loadSSExtensions(model.ssextensions);\n\t\t\n\t\t// Load Meta Data Extension if available\n\t\t// #Signavio\n\t\tif (requestMeta === true) {\n\t\t\tvar metaDataExtension = this.getExtensionForMetaData();\n\t\t\tif (metaDataExtension) {\n\t\t\t\tthis.loadSSExtension(metaDataExtension);\n\t\t\t}\n\t\t}\n\t\t\n        var shapes = this.getCanvas().addShapeObjects(model.childShapes, this.handleEvents.bind(this));\n        \n        if(model.properties) {\n        \tfor(key in model.properties) {\n        \t\tvar value = model.properties[key];\n\t\t\t\tvar prop = this.getCanvas().getStencil().property(\"oryx-\"+key);\n        \t\tif (!(typeof value === \"string\") && (!prop || !prop.isList())) {\n        \t\t\tvalue = JSON.stringify(value);\n        \t\t}\n            \tthis.getCanvas().setProperty(\"oryx-\" + key, value);\n            }\n        }\n        \n        \n        this.getCanvas().updateSize();\n\t\t\n\t\t// Force to update the selection\n\t\tthis.selection = [null];\n\t\tthis.setSelection([]);\n\t\t\n        return shapes;\n    },\n\t\n\t/**\n\t * Return the namespace of the extension which\n\t * provided all the self defined meta data\n\t * @return {String} Returns null if no extension is defined, otherwise the namespace\n\t *\n\t */\n\tgetExtensionForMetaData: function(){\n\t\tif (!this.ss_extensions_def||!(this.ss_extensions_def.extensions instanceof Array)){\n\t\t\treturn null;\n\t\t}\n\t\t\n\t\tvar stencilsets = this.getStencilSets();\n\t\tvar extension = this.ss_extensions_def.extensions.find(function(ex){\n\t\t\t\treturn !!stencilsets[ex[\"extends\"]] && ex.namespace.endsWith(\"/meta#\");\n\t\t\t});\n\t\t\t\n\t\treturn extension ? extension.namespace || null : null;\t\t\n\t},\n    \n    /**\n     * Calls ORYX.Editor.prototype.ss_extension_namespace for each element\n     * @param {Array} ss_extension_namespaces An array of stencil set extension namespaces.\n     */\n    loadSSExtensions: function(ss_extension_namespaces){\n        if(!ss_extension_namespaces) return;\n\n        ss_extension_namespaces.each(function(ss_extension_namespace){\n            this.loadSSExtension(ss_extension_namespace);\n        }.bind(this));\n    },\n\t\n\t/**\n\t* Loads a stencil set extension.\n\t* The stencil set extensions definiton file must already\n\t* be loaded when the editor is initialized.\n\t*/\n\tloadSSExtension: function(ss_extension_namespace) {\t\t\t\t\n\t\t\n\t\tif (this.ss_extensions_def) {\n\t\t\tvar extension = this.ss_extensions_def.extensions.find(function(ex){\n\t\t\t\treturn (ex.namespace == ss_extension_namespace);\n\t\t\t});\n\t\t\t\n\t\t\tif (!extension) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\tvar stencilset = this.getStencilSets()[extension[\"extends\"]];\n\t\t\t\n\t\t\tif (!stencilset) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\t// Check if absolute or relative url\n\t\t\tif ((extension[\"definition\"]||\"\").startsWith(\"/\")){\n\t\t\t\tstencilset.addExtension(extension[\"definition\"])\n\t\t\t} else {\n\t\t\t\tstencilset.addExtension(ORYX.CONFIG.SS_EXTENSIONS_FOLDER + extension[\"definition\"])\n\t\t\t}\n\t\t\t\n\t\t\t//stencilset.addExtension(\"/oryx/build/stencilsets/extensions/\" + extension[\"definition\"])\n\t\t\tthis.getRules().initializeRules(stencilset);\n\t\t\t\n\t\t\tthis._getPluginFacade().raiseEvent({\n\t\t\t\ttype: ORYX.CONFIG.EVENT_STENCIL_SET_LOADED\n\t\t\t});\n\t\t}\n\t\t\n\t},\n\n\tdisableEvent: function(eventType){\n\t\tif(eventType == ORYX.CONFIG.EVENT_KEYDOWN) {\n\t\t\tthis._keydownEnabled = false;\n\t\t}\n\t\tif(eventType == ORYX.CONFIG.EVENT_KEYUP) {\n\t\t\tthis._keyupEnabled = false;\n\t\t}\n\t\tif(this.DOMEventListeners.keys().member(eventType)) {\n\t\t\tvar value = this.DOMEventListeners.remove(eventType);\n\t\t\tthis.DOMEventListeners['disable_' + eventType] = value;\n\t\t}\n\t},\n\n\tenableEvent: function(eventType){\n\t\tif(eventType == ORYX.CONFIG.EVENT_KEYDOWN) {\n\t\t\tthis._keydownEnabled = true;\n\t\t}\n\t\t\n\t\tif(eventType == ORYX.CONFIG.EVENT_KEYUP) {\n\t\t\tthis._keyupEnabled = true;\n\t\t}\n\t\t\n\t\tif(this.DOMEventListeners.keys().member(\"disable_\" + eventType)) {\n\t\t\tvar value = this.DOMEventListeners.remove(\"disable_\" + eventType);\n\t\t\tthis.DOMEventListeners[eventType] = value;\n\t\t}\n\t},\n\n\t/**\n\t *  Methods for the PluginFacade\n\t */\n\tregisterOnEvent: function(eventType, callback) {\n\t\tif(!(this.DOMEventListeners.keys().member(eventType))) {\n\t\t\tthis.DOMEventListeners[eventType] = [];\n\t\t}\n\n\t\tthis.DOMEventListeners[eventType].push(callback);\n\t},\n\n\tunregisterOnEvent: function(eventType, callback) {\n\t\tif(this.DOMEventListeners.keys().member(eventType)) {\n\t\t\tthis.DOMEventListeners[eventType] = this.DOMEventListeners[eventType].without(callback);\n\t\t} else {\n\t\t\t// Event is not supported\n\t\t\t// TODO: Error Handling\n\t\t}\n\t},\n\n\tgetSelection: function() {\n\t\treturn this.selection || [];\n\t},\n\n\tgetStencilSets: function() { \n\t\treturn ORYX.Core.StencilSet.stencilSets(this.id); \n\t},\n\t\n\tgetRules: function() {\n\t\treturn ORYX.Core.StencilSet.rules(this.id);\n\t},\n\t\n\tloadStencilSet: function(source) {\n\t\ttry {\n\t\t\tORYX.Core.StencilSet.loadStencilSet(source, this.modelMetaData, this.id);\n\t\t\tthis.handleEvents({type:ORYX.CONFIG.EVENT_STENCIL_SET_LOADED});\n\t\t} catch (e) {\n\t\t\tORYX.Log.warn(\"Requesting stencil set file failed. (\" + e + \")\");\n\t\t}\n\t},\n\n\toffer: function(pluginData) {\n\t\tif(!this.pluginsData.member(pluginData)){\n\t\t\tthis.pluginsData.push(pluginData);\n\t\t}\n\t},\n\t\n\t/**\n\t * It creates an new event or adds the callback, if already existing,\n\t * for the key combination that the plugin passes in keyCodes attribute\n\t * of the offer method.\n\t * \n\t * The new key down event fits the schema:\n\t * \t\tkey.event[.metactrl][.alt][.shift].'thekeyCode'\n\t */\n\tregisterPluginsOnKeyEvents: function() {\n\t\tthis.pluginsData.each(function(pluginData) {\n\t\t\t\n\t\t\tif(pluginData.keyCodes) {\n\t\t\t\t\n\t\t\t\tpluginData.keyCodes.each(function(keyComb) {\n\t\t\t\t\tvar eventName = \"key.event\";\n\t\t\t\t\t\n\t\t\t\t\t/* Include key action */\n\t\t\t\t\teventName += '.' + keyComb.keyAction;\n\t\t\t\t\t\n\t\t\t\t\tif(keyComb.metaKeys) {\n\t\t\t\t\t\t/* Register on ctrl or apple meta key as meta key */\n\t\t\t\t\t\tif(keyComb.metaKeys.\n\t\t\t\t\t\t\tindexOf(ORYX.CONFIG.META_KEY_META_CTRL) > -1) {\n\t\t\t\t\t\t\t\teventName += \".\" + ORYX.CONFIG.META_KEY_META_CTRL;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t/* Register on alt key as meta key */\n\t\t\t\t\t\tif(keyComb.metaKeys.\n\t\t\t\t\t\t\tindexOf(ORYX.CONFIG.META_KEY_ALT) > -1) {\n\t\t\t\t\t\t\t\teventName += '.' + ORYX.CONFIG.META_KEY_ALT;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\t/* Register on shift key as meta key */\n\t\t\t\t\t\tif(keyComb.metaKeys.\n\t\t\t\t\t\t\tindexOf(ORYX.CONFIG.META_KEY_SHIFT) > -1) {\n\t\t\t\t\t\t\t\teventName += '.' + ORYX.CONFIG.META_KEY_SHIFT;\n\t\t\t\t\t\t}\t\t\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t/* Register on the actual key */\n\t\t\t\t\tif(keyComb.keyCode)\t{\n\t\t\t\t\t\teventName += '.' + keyComb.keyCode;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t/* Register the event */\n\t\t\t\t\tORYX.Log.debug(\"Register Plugin on Key Event: %0\", eventName);\n\t\t\t\t\tif (pluginData.toggle === true && pluginData.buttonInstance) {\n\t\t\t\t\t\tthis.registerOnEvent(eventName, function(){\n\t\t\t\t\t\t\tpluginData.buttonInstance.toggle(!pluginData.buttonInstance.pressed); // Toggle \n\t\t\t\t\t\t\tpluginData.functionality.call(pluginData, pluginData.buttonInstance, pluginData.buttonInstance.pressed); // Call function\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.registerOnEvent(eventName, pluginData.functionality)\n\t\t\t\t\t}\n\t\t\t\t\n\t\t\t\t}.bind(this));\n\t\t\t}\n\t\t}.bind(this));\n\t},\n\t\n\tisEqual: function(a,b){\n\t\treturn a === b || (a.length === b.length && a.all(function(r){ return b.include(r) }))\n\t},\n\t\n\tisDirty: function(a){\n\t\treturn a.any(function(shape){ return shape.isPropertyChanged() })\n\t},\n\n\tsetSelection: function(elements, subSelectionElement, force) {\n\t\t\n\t\tif (!elements) { elements = []; }\n\t\tif (!(elements instanceof Array)) { elements = [elements]; }\n\t\t\n\t\telements = elements.findAll(function(n){ return n && n instanceof ORYX.Core.Shape });\n\t\t\n\t\tif (elements[0] instanceof ORYX.Core.Canvas) {\n\t\t\telements = [];\n\t\t}\n\t\t\n\t\tif (!force && this.isEqual(this.selection, elements) && !this.isDirty(elements)){\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tthis.selection = elements;\n\t\tthis._subSelection = subSelectionElement;\n\t\t\n\t\tthis.handleEvents({type:ORYX.CONFIG.EVENT_SELECTION_CHANGED, elements:elements, subSelection: subSelectionElement, force: !!force})\n\t},\n\t\n\tupdateSelection: function() {\n\t\tthis.setSelection(this.selection, this._subSelection, true);\n\t\t/*var s = this.selection;\n\t\tthis.setSelection();\n\t\tthis.setSelection(s);*/\n\t},\n\n\tgetCanvas: function() {\n\t\treturn this._canvas;\n\t},\n\t\n\n\t/**\n\t*\toption = {\n\t*\t\ttype: string,\n\t*\t\tposition: {x:int, y:int},\n\t*\t\tconnectingType:\tuiObj-Class\n\t*\t\tconnectedShape: uiObj\n\t*\t\tdraggin: bool\n\t*\t\tnamespace: url\n\t*       parent: ORYX.Core.AbstractShape\n\t*\t\ttemplate: a template shape that the newly created inherits properties from.\n\t*\t\t}\n\t*/\n\tcreateShape: function(option) {\n\n\t\tif(option && option.serialize && option.serialize instanceof Array){\n\t\t\n\t\t\tvar type = option.serialize.find(function(obj){return (obj.prefix+\"-\"+obj.name) == \"oryx-type\"});\n\t\t\tvar stencil = ORYX.Core.StencilSet.stencil(type.value);\n\t\t\t\n\t\t\tif(stencil.type() == 'node'){\n\t\t\t\tvar newShapeObject = new ORYX.Core.Node({'eventHandlerCallback':this.handleEvents.bind(this)}, stencil, this._getPluginFacade());\t\n\t\t\t} else {\n\t\t\t\tvar newShapeObject = new ORYX.Core.Edge({'eventHandlerCallback':this.handleEvents.bind(this)}, stencil, this._getPluginFacade());\t\n\t\t\t}\n\t\t\n\t\t\tthis.getCanvas().add(newShapeObject);\n\t\t\tnewShapeObject.deserialize(option.serialize);\n\t\t\n\t\t\treturn newShapeObject;\n\t\t}\n\n\t\t// If there is no argument, throw an exception\n\t\tif(!option || !option.type || !option.namespace) { throw \"To create a new shape you have to give an argument with type and namespace\";}\n\t\t\n\t\tvar canvas = this.getCanvas();\n\t\tvar newShapeObject;\n\n\t\t// Get the shape type\n\t\tvar shapetype = option.type;\n\n\t\t// Get the stencil set\n\t\tvar sset = ORYX.Core.StencilSet.stencilSet(option.namespace);\n\t\t// Create an New Shape, dependents on an Edge or a Node\n\t\tif(sset.stencil(shapetype).type() == \"node\") {\n\t\t\tnewShapeObject = new ORYX.Core.Node({'eventHandlerCallback':this.handleEvents.bind(this)}, sset.stencil(shapetype), this._getPluginFacade())\n\t\t} else {\n\t\t\tnewShapeObject = new ORYX.Core.Edge({'eventHandlerCallback':this.handleEvents.bind(this)}, sset.stencil(shapetype), this._getPluginFacade())\n\t\t}\n\t\t\n\t\t// when there is a template, inherit the properties.\n\t\tif(option.template) {\n\n\t\t\tnewShapeObject._jsonStencil.properties = option.template._jsonStencil.properties;\n\t\t\tnewShapeObject.postProcessProperties();\n\t\t}\n\n\t\t// Add to the canvas\n\t\tif(option.parent && newShapeObject instanceof ORYX.Core.Node) {\n\t\t\toption.parent.add(newShapeObject);\n\t\t} else {\n\t\t\tcanvas.add(newShapeObject);\n\t\t}\n\t\t\n\t\t\n\t\t// Set the position\n\t\tvar point = option.position ? option.position : {x:100, y:200};\n\t\n\t\t\n\t\tvar con;\n\t\t// If there is create a shape and in the argument there is given an ConnectingType and is instance of an edge\n\t\tif(option.connectingType && option.connectedShape && !(newShapeObject instanceof ORYX.Core.Edge)) {\n\n\t\t\t// there will be create a new Edge\n\t\t\tcon = new ORYX.Core.Edge({'eventHandlerCallback':this.handleEvents.bind(this)}, sset.stencil(option.connectingType));\n\t\t\t\n\t\t\t// And both endings dockers will be referenced to the both shapes\n\t\t\tcon.dockers.first().setDockedShape(option.connectedShape);\n\t\t\t\n\t\t\tvar magnet = option.connectedShape.getDefaultMagnet()\n\t\t\tvar cPoint = magnet ? magnet.bounds.center() : option.connectedShape.bounds.midPoint();\n\t\t\tcon.dockers.first().setReferencePoint( cPoint );\n\t\t\tcon.dockers.last().setDockedShape(newShapeObject);\n\t\t\tcon.dockers.last().setReferencePoint(newShapeObject.getDefaultMagnet().bounds.center());\t\t\n\t\t\t\n\t\t\t// The Edge will be added to the canvas and be updated\n\t\t\tcanvas.add(con);\t\n\t\t\t//con.update();\n\t\t\t\n\t\t} \n\t\t\n\t\t// Move the new Shape to the position\n\t\tif(newShapeObject instanceof ORYX.Core.Edge && option.connectedShape) {\n\n\t\t\tnewShapeObject.dockers.first().setDockedShape(option.connectedShape);\n\t\t\t\n\t\t\tif( option.connectedShape instanceof ORYX.Core.Node ){\n\t\t\t\tnewShapeObject.dockers.first().setReferencePoint(option.connectedShape.getDefaultMagnet().bounds.center());\t\t\t\t\t\n\t\t\t\tnewShapeObject.dockers.last().bounds.centerMoveTo(point);\t\t\t\n\t\t\t} else {\n\t\t\t\tnewShapeObject.dockers.first().setReferencePoint(option.connectedShape.bounds.midPoint());\t\t\t\t\t\t\t\t\n\t\t\t}\n\t\t\t\n\t\t\tvar start = newShapeObject.dockers.first();\n        \tvar end = newShapeObject.dockers.last();\n        \t\n        \tif(start.getDockedShape() && end.getDockedShape()) {\n        \t\tvar startPoint = start.getAbsoluteReferencePoint();\n        \t\tvar endPoint = end.getAbsoluteReferencePoint();\n        \t\t\n        \t\tvar docker = newShapeObject.createDocker();\n        \t\tdocker.bounds.centerMoveTo({\n        \t\t\tx: startPoint.x + (endPont.x - startPoint.x) / 2,\n        \t\t\ty: startPoint.y + (endPont.y - startPoint.y) / 2\n        \t\t});\n        \t}\n\n\t\t} else {\n\t\t\t\n\t\t\tvar b = newShapeObject.bounds\n\t\t\tif( newShapeObject instanceof ORYX.Core.Node && newShapeObject.dockers.length == 1){\n\t\t\t\tb = newShapeObject.dockers.first().bounds\n\t\t\t}\n\t\t\t\n\t\t\tb.centerMoveTo(point);\n\t\t\t\n\t\t\tvar upL = b.upperLeft();\n\t\t\tb.moveBy( -Math.min(upL.x, 0) , -Math.min(upL.y, 0) )\n\t\t\t\n\t\t\tvar lwR = b.lowerRight();\n\t\t\tb.moveBy( -Math.max(lwR.x-canvas.bounds.width(), 0) , -Math.max(lwR.y-canvas.bounds.height(), 0) )\n\t\t\t\n\t\t}\n\t\t\n\t\t// Update the shape\n\t\tif (newShapeObject instanceof ORYX.Core.Edge) {\n\t\t\tnewShapeObject._update(false);\n\t\t}\n\t\t\n\t\t// And refresh the selection\n\t\tif(!(newShapeObject instanceof ORYX.Core.Edge)&&!(option.dontUpdateSelection)) {\n\t\t\tthis.setSelection([newShapeObject]);\n\t\t}\n\t\t\n\t\tif(con && con.alignDockers) {\n\t\t\t//con.alignDockers();\n\t\t} \n\t\tif(newShapeObject.alignDockers) {\n\t\t\tnewShapeObject.alignDockers();\n\t\t}\n\n\t\treturn newShapeObject;\n\t},\n\t\n\tdeleteShape: function(shape) {\n\t\t\n\t\tif (!shape || !shape.parent){ return }\n\t\t\n\t\t//remove shape from parent\n\t\t// this also removes it from DOM\n\t\tshape.parent.remove(shape);\n\t\t\n\t\t//delete references to outgoing edges\n\t\tshape.getOutgoingShapes().each(function(os) {\n\t\t\tvar docker = os.getDockers().first();\n\t\t\tif(docker && docker.getDockedShape() == shape) {\n\t\t\t\tdocker.setDockedShape(undefined);\n\t\t\t}\n\t\t});\n\t\t\n\t\t//delete references to incoming edges\n\t\tshape.getIncomingShapes().each(function(is) {\n\t\t\tvar docker = is.getDockers().last();\n\t\t\tif(docker && docker.getDockedShape() == shape) {\n\t\t\t\tdocker.setDockedShape(undefined);\n\t\t\t}\n\t\t});\n\t\t\n\t\t//delete references of the shape's dockers\n\t\tshape.getDockers().each(function(docker) {\n\t\t\tdocker.setDockedShape(undefined);\n\t\t});\n\t},\n\t\n\t/**\n\t * Returns an object with meta data about the model.\n\t * Like name, description, ...\n\t * \n\t * Empty object with the current backend.\n\t * \n\t * @return {Object} Meta data about the model\n\t */\n\tgetModelMetaData: function() {\n\t\treturn this.modelMetaData;\n\t},\n\n\t/* Event-Handler Methods */\n\t\n\t/**\n\t* Helper method to execute an event immediately. The event is not\n\t* scheduled in the _eventsQueue. Needed to handle Layout-Callbacks.\n\t*/\n\t_executeEventImmediately: function(eventObj) {\n\t\tif(this.DOMEventListeners.keys().member(eventObj.event.type)) {\n\t\t\tthis.DOMEventListeners[eventObj.event.type].each((function(value) {\n\t\t\t\tvalue(eventObj.event, eventObj.arg);\t\t\n\t\t\t}).bind(this));\n\t\t}\n\t},\n\n\t_executeEvents: function() {\n\t\tthis._queueRunning = true;\n\t\twhile(this._eventsQueue.length > 0) {\n\t\t\tvar val = this._eventsQueue.shift();\n\t\t\tthis._executeEventImmediately(val);\n\t\t}\n\t\tthis._queueRunning = false;\n\t},\n\t\n\t/**\n\t * Leitet die Events an die Editor-Spezifischen Event-Methoden weiter\n\t * @param {Object} event Event , welches gefeuert wurde\n\t * @param {Object} uiObj Target-UiObj\n\t */\n\thandleEvents: function(event, uiObj) {\n\t\t\n\t\tORYX.Log.trace(\"Dispatching event type %0 on %1\", event.type, uiObj);\n\n\t\tswitch(event.type) {\n\t\t\tcase ORYX.CONFIG.EVENT_MOUSEDOWN:\n\t\t\t\tthis._handleMouseDown(event, uiObj);\n\t\t\t\tbreak;\n\t\t\tcase ORYX.CONFIG.EVENT_MOUSEMOVE:\n\t\t\t\tthis._handleMouseMove(event, uiObj);\n\t\t\t\tbreak;\n\t\t\tcase ORYX.CONFIG.EVENT_MOUSEUP:\n\t\t\t\tthis._handleMouseUp(event, uiObj);\n\t\t\t\tbreak;\n\t\t\tcase ORYX.CONFIG.EVENT_MOUSEOVER:\n\t\t\t\tthis._handleMouseHover(event, uiObj);\n\t\t\t\tbreak;\n\t\t\tcase ORYX.CONFIG.EVENT_MOUSEOUT:\n\t\t\t\tthis._handleMouseOut(event, uiObj);\n\t\t\t\tbreak;\n\t\t}\n\t\t/* Force execution if necessary. Used while handle Layout-Callbacks. */\n\t\tif(event.forceExecution) {\n\t\t\tthis._executeEventImmediately({event: event, arg: uiObj});\n\t\t} else {\n\t\t\tthis._eventsQueue.push({event: event, arg: uiObj});\n\t\t}\n\t\t\n\t\tif(!this._queueRunning) {\n\t\t\tthis._executeEvents();\n\t\t}\n\t\t\n\t\t// TODO: Make this return whether no listener returned false.\n\t\t// So that, when one considers bubbling undesireable, it won't happen.\n\t\treturn false;\n\t},\n\n\tisValidEvent: function(e){\n\t\ttry {\n\t\t\tvar isInput = [\"INPUT\", \"TEXTAREA\"].include(e.target.tagName.toUpperCase());\n\t\t\tvar gridHasFocus = e.target.className.include(\"x-grid3-focus\") && !e.target.className.include(\"x-grid3-focus-canvas\");\n\t\t\treturn !isInput && !gridHasFocus;\n\t\t} catch(e){\n\t\t\treturn false;\n\t\t}\n\t},\n\n\tcatchKeyUpEvents: function(event) {\n\t\tif(!this._keyupEnabled) {\n\t\t\treturn;\n\t\t}\n\t\t/* assure we have the current event. */\n        if (!event) \n            event = window.event;\n        \n\t\t// Checks if the event comes from some input field\n\t\tif (!this.isValidEvent(event)){\n\t\t\treturn;\n\t\t}\n\t\t\n\t\t/* Create key up event type */\n\t\tvar keyUpEvent = this.createKeyCombEvent(event,\tORYX.CONFIG.KEY_ACTION_UP);\n\t\t\n\t\tORYX.Log.debug(\"Key Event to handle: %0\", keyUpEvent);\n\n\t\t/* forward to dispatching. */\n\t\tthis.handleEvents({type: keyUpEvent, event:event});\n\t},\n\t\n\t/**\n\t * Catches all key down events and forward the appropriated event to \n\t * dispatching concerning to the pressed keys.\n\t * \n\t * @param {Event} \n\t * \t\tThe key down event to handle\n\t */\n\tcatchKeyDownEvents: function(event) {\n\t\tif(!this._keydownEnabled) {\n\t\t\treturn;\n\t\t}\n\t\t/* Assure we have the current event. */\n        if (!event) \n            event = window.event;\n        \n\t\t/* Fixed in FF3 */\n\t\t// This is a mac-specific fix. The mozilla event object has no knowledge\n\t\t// of meta key modifier on osx, however, it is needed for certain\n\t\t// shortcuts. This fix adds the metaKey field to the event object, so\n\t\t// that all listeners that registered per Oryx plugin facade profit from\n\t\t// this. The original bug is filed in\n\t\t// https://bugzilla.mozilla.org/show_bug.cgi?id=418334\n\t\t//if (this.__currentKey == ORYX.CONFIG.KEY_CODE_META) {\n\t\t//\tevent.appleMetaKey = true;\n\t\t//}\n\t\t//this.__currentKey = pressedKey;\n\t\t\n\t\t// Checks if the event comes from some input field\n\t\tif (!this.isValidEvent(event)){\n\t\t\treturn;\n\t\t}\n\t\t\n\t\t/* Create key up event type */\n\t\tvar keyDownEvent = this.createKeyCombEvent(event, ORYX.CONFIG.KEY_ACTION_DOWN);\n\t\t\n\t\tORYX.Log.debug(\"Key Event to handle: %0\", keyDownEvent);\n\t\t\n\t\t/* Forward to dispatching. */\n\t\tthis.handleEvents({type: keyDownEvent,event: event});\n\t},\n\t\n\t/**\n\t * Creates the event type name concerning to the pressed keys.\n\t * \n\t * @param {Event} keyDownEvent\n\t * \t\tThe source keyDownEvent to build up the event name\n\t */\n\tcreateKeyCombEvent: function(keyEvent, keyAction) {\n\n\t\t/* Get the currently pressed key code. */\n        var pressedKey = keyEvent.which || keyEvent.keyCode;\n\t\t//this.__currentKey = pressedKey;\n\t\t\n\t\t/* Event name */\n\t\tvar eventName = \"key.event\";\n\t\t\n\t\t/* Key action */\n\t\tif(keyAction) {\n\t\t\teventName += \".\" + keyAction;\n\t\t}\n\t\t\n\t\t/* Ctrl or apple meta key is pressed */\n\t\tif(keyEvent.ctrlKey || keyEvent.metaKey) {\n\t\t\teventName += \".\" + ORYX.CONFIG.META_KEY_META_CTRL;\n\t\t}\n\t\t\n\t\t/* Alt key is pressed */\n\t\tif(keyEvent.altKey) {\n\t\t\teventName += \".\" + ORYX.CONFIG.META_KEY_ALT;\n\t\t}\n\t\t\n\t\t/* Alt key is pressed */\n\t\tif(keyEvent.shiftKey) {\n\t\t\teventName += \".\" + ORYX.CONFIG.META_KEY_SHIFT;\n\t\t}\n\t\t\n\t\t/* Return the composed event name */\n\t\treturn  eventName + \".\" + pressedKey;\n\t},\n\n\t_handleMouseDown: function(event, uiObj) {\n\t\t\n\t\t// get canvas.\n\t\tvar canvas = this.getCanvas();\n\t\t// Try to get the focus\n\t\tcanvas.focus()\n\t\n\t\t// find the shape that is responsible for this element's id.\n\t\tvar element = event.currentTarget;\n\t\tvar elementController = uiObj;\n\n\t\t// gather information on selection.\n\t\tvar currentIsSelectable = (elementController !== null) &&\n\t\t\t(elementController !== undefined) && (elementController.isSelectable);\n\t\tvar currentIsMovable = (elementController !== null) &&\n\t\t\t(elementController !== undefined) && (elementController.isMovable);\n\t\tvar modifierKeyPressed = event.shiftKey || event.ctrlKey;\n\t\tvar noObjectsSelected = this.selection.length === 0;\n\t\tvar currentIsSelected = this.selection.member(elementController);\n\n\n\t\t// Rule #1: When there is nothing selected, select the clicked object.\n\t\tif(currentIsSelectable && noObjectsSelected) {\n\n\t\t\tthis.setSelection([elementController]);\n\n\t\t\tORYX.Log.trace(\"Rule #1 applied for mouse down on %0\", element.id);\n\n\t\t// Rule #3: When at least one element is selected, and there is no\n\t\t// control key pressed, and the clicked object is not selected, select\n\t\t// the clicked object.\n\t\t} else if(currentIsSelectable && !noObjectsSelected &&\n\t\t\t!modifierKeyPressed && !currentIsSelected) {\n\n\t\t\tthis.setSelection([elementController]);\n\n\t\t\t//var objectType = elementController.readAttributes();\n\t\t\t//alert(objectType[0] + \": \" + objectType[1]);\n\n\t\t\tORYX.Log.trace(\"Rule #3 applied for mouse down on %0\", element.id);\n\n\t\t// Rule #4: When the control key is pressed, and the current object is\n\t\t// not selected, add it to the selection.\n\t\t} else if(currentIsSelectable && modifierKeyPressed\n\t\t\t&& !currentIsSelected) {\n\t\t\t\t\n\t\t\tvar newSelection = this.selection.clone();\n\t\t\tnewSelection.push(elementController)\n\t\t\tthis.setSelection(newSelection)\n\n\t\t\tORYX.Log.trace(\"Rule #4 applied for mouse down on %0\", element.id);\n\n\t\t// Rule #6\n\t\t} else if(currentIsSelectable && currentIsSelected &&\n\t\t\tmodifierKeyPressed) {\n\n\t\t\tvar newSelection = this.selection.clone();\n\t\t\tthis.setSelection(newSelection.without(elementController))\n\n\t\t\tORYX.Log.trace(\"Rule #6 applied for mouse down on %0\", elementController.id);\n\n\t\t// Rule #5: When there is at least one object selected and no control\n\t\t// key pressed, we're dragging.\n\t\t/*} else if(currentIsSelectable && !noObjectsSelected\n\t\t\t&& !modifierKeyPressed) {\n\n\t\t\tif(this.log.isTraceEnabled())\n\t\t\t\tthis.log.trace(\"Rule #5 applied for mouse down on \"+element.id);\n*/\n\t\t// Rule #2: When clicked on something that is neither\n\t\t// selectable nor movable, clear the selection, and return.\n\t\t} else if (!currentIsSelectable && !currentIsMovable) {\n\t\t\t\n\t\t\tthis.setSelection([]);\n\t\t\t\n\t\t\tORYX.Log.trace(\"Rule #2 applied for mouse down on %0\", element.id);\n\n\t\t\treturn;\n\n\t\t// Rule #7: When the current object is not selectable but movable,\n\t\t// it is probably a control. Leave the selection unchanged but set\n\t\t// the movedObject to the current one and enable Drag. Dockers will\n\t\t// be processed in the dragDocker plugin.\n\t\t} else if(!currentIsSelectable && currentIsMovable && !(elementController instanceof ORYX.Core.Controls.Docker)) {\n\t\t\t\n\t\t\t// TODO: If there is any moveable elements, do this in a plugin\n\t\t\t//ORYX.Core.UIEnableDrag(event, elementController);\n\n\t\t\tORYX.Log.trace(\"Rule #7 applied for mouse down on %0\", element.id);\n\t\t\n\t\t// Rule #8: When the element is selectable and is currently selected and no \n\t\t// modifier key is pressed\n\t\t} else if(currentIsSelectable && currentIsSelected &&\n\t\t\t!modifierKeyPressed) {\n\t\t\t\n\t\t\tthis._subSelection = this._subSelection != elementController ? elementController : undefined;\n\t\t\t\t\t\t\n\t\t\tthis.setSelection(this.selection, this._subSelection);\n\t\t\t\n\t\t\tORYX.Log.trace(\"Rule #8 applied for mouse down on %0\", element.id);\n\t\t}\n\t\t\n\t\t\n\t\t// prevent event from bubbling, return.\n\t\t//Event.stop(event);\n\t\treturn;\n\t},\n\n\t_handleMouseMove: function(event, uiObj) {\n\t\treturn;\n\t},\n\n\t_handleMouseUp: function(event, uiObj) {\n\t\t// get canvas.\n\t\tvar canvas = this.getCanvas();\n\n\t\t// find the shape that is responsible for this elemement's id.\n\t\tvar elementController = uiObj;\n\n\t\t//get event position\n\t\tvar evPos = this.eventCoordinates(event);\n\n\t\t//Event.stop(event);\n\t},\n\n\t_handleMouseHover: function(event, uiObj) {\n\t\treturn;\n\t},\n\n\t_handleMouseOut: function(event, uiObj) {\n\t\treturn;\n\t},\n\n\t/**\n\t * Calculates the event coordinates to SVG document coordinates.\n\t * @param {Event} event\n\t * @return {SVGPoint} The event coordinates in the SVG document\n\t */\n\teventCoordinates: function(event) {\n\n\t\tvar canvas = this.getCanvas();\n\n\t\tvar svgPoint = canvas.node.ownerSVGElement.createSVGPoint();\n\t\tsvgPoint.x = event.clientX;\n\t\tsvgPoint.y = event.clientY;\n\t\t\n\t\tvar additionalIEZoom = 1;\n        if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) {\n            var ua = navigator.userAgent;\n            if (ua.indexOf('MSIE') >= 0) {\n                //IE 10 and below\n                var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100);\n                if (zoom !== 100) {\n                    additionalIEZoom = zoom / 100\n                }\n            }\n        }\n        \n        if (additionalIEZoom !== 1) {\n            svgPoint.x = svgPoint.x * additionalIEZoom;\n            svgPoint.y = svgPoint.y * additionalIEZoom;\n        }\n\t\t\n\t\tvar matrix = canvas.node.getScreenCTM();\n\t\treturn svgPoint.matrixTransform(matrix.inverse());\n\t},\n\t\n\teventCoordinatesXY: function(x, y) {\n\n\t\tvar canvas = this.getCanvas();\n\n\t\tvar svgPoint = canvas.node.ownerSVGElement.createSVGPoint();\n\t\tsvgPoint.x = x;\n\t\tsvgPoint.y = y;\n\t\t\n\t\tvar additionalIEZoom = 1;\n        if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) {\n            var ua = navigator.userAgent;\n            if (ua.indexOf('MSIE') >= 0) {\n                //IE 10 and below\n                var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100);\n                if (zoom !== 100) {\n                    additionalIEZoom = zoom / 100\n                }\n            }\n        }\n        \n        if (additionalIEZoom !== 1) {\n            svgPoint.x = svgPoint.x * additionalIEZoom;\n            svgPoint.y = svgPoint.y * additionalIEZoom;\n        }\n\t\t\n\t\tvar matrix = canvas.node.getScreenCTM();\n\t\treturn svgPoint.matrixTransform(matrix.inverse());\n\t}\n};\nORYX.Editor = Clazz.extend(ORYX.Editor);\n\n/**\n * Creates a new ORYX.Editor instance by fetching a model from given url and passing it to the constructur\n * @param {String} modelUrl The JSON URL of a model.\n * @param {Object} config Editor config passed to the constructur, merged with the response of the request to modelUrl\n */\nORYX.Editor.createByUrl = function(modelUrl){\n    new Ajax.Request(modelUrl, {\n      method: 'GET',\n      onSuccess: function(transport) {\n    \tvar editorConfig = JSON.parse(transport.responseText);\n        new ORYX.Editor(editorConfig);\n      }.bind(this)\n    });\n}\n\n// TODO Implement namespace awareness on attribute level.\n/**\n * graft() function\n * Originally by Sean M. Burke from interglacial.com, altered for usage with\n * SVG and namespace (xmlns) support. Be sure you understand xmlns before\n * using this funtion, as it creates all grafted elements in the xmlns\n * provided by you and all element's attribures in default xmlns. If you\n * need to graft elements in a certain xmlns and wish to assign attributes\n * in both that and another xmlns, you will need to do stepwise grafting,\n * adding non-default attributes yourself or you'll have to enhance this\n * function. Latter, I would appreciate: martin???apfelfabrik.de\n * @param {Object} namespace The namespace in which\n * \t\t\t\t\telements should be grafted.\n * @param {Object} parent The element that should contain the grafted\n * \t\t\t\t\tstructure after the function returned.\n * @param {Object} t the crafting structure.\n * @param {Object} doc the document in which grafting is performed.\n */\nORYX.Editor.graft = function(namespace, parent, t, doc) {\n\n    doc = (doc || (parent && parent.ownerDocument) || document);\n    var e;\n    if(t === undefined) {\n        throw \"Can't graft an undefined value\";\n    } else if(t.constructor == String) {\n        e = doc.createTextNode( t );\n    } else {\n        for(var i = 0; i < t.length; i++) {\n            if( i === 0 && t[i].constructor == String ) {\n                var snared;\n                snared = t[i].match( /^([a-z][a-z0-9]*)\\.([^\\s\\.]+)$/i );\n                if( snared ) {\n                    e = doc.createElementNS(namespace, snared[1] );\n                    e.setAttributeNS(null, 'class', snared[2] );\n                    continue;\n                }\n                snared = t[i].match( /^([a-z][a-z0-9]*)$/i );\n                if( snared ) {\n                    e = doc.createElementNS(namespace, snared[1] );  // but no class\n                    continue;\n                }\n\n                // Otherwise:\n                e = doc.createElementNS(namespace, \"span\" );\n                e.setAttribute(null, \"class\", \"namelessFromLOL\" );\n            }\n\n            if( t[i] === undefined ) {\n                throw \"Can't graft an undefined value in a list!\";\n            } else if( t[i].constructor == String || t[i].constructor == Array ) {\n                this.graft(namespace, e, t[i], doc );\n            } else if(  t[i].constructor == Number ) {\n                this.graft(namespace, e, t[i].toString(), doc );\n            } else if(  t[i].constructor == Object ) {\n                // hash's properties => element's attributes\n                for(var k in t[i]) { e.setAttributeNS(null, k, t[i][k] ); }\n            } else {\n\n\t\t\t}\n        }\n    }\n\tif(parent && parent.appendChild) {\n\t    parent.appendChild( e );\n\t} else {\n\n\t}\n    return e; // return the topmost created node\n};\n\nORYX.Editor.provideId = function() {\n\tvar res = [], hex = '0123456789ABCDEF';\n\n\tfor (var i = 0; i < 36; i++) res[i] = Math.floor(Math.random()*0x10);\n\n\tres[14] = 4;\n\tres[19] = (res[19] & 0x3) | 0x8;\n\n\tfor (var i = 0; i < 36; i++) res[i] = hex[res[i]];\n\n\tres[8] = res[13] = res[18] = res[23] = '-';\n\n\treturn \"oryx_\" + res.join('');\n};\n\n/**\n * When working with Ext, conditionally the window needs to be resized. To do\n * so, use this class method. Resize is deferred until 100ms, and all subsequent\n * resizeBugFix calls are ignored until the initially requested resize is\n * performed.\n */\nORYX.Editor.resizeFix = function() {\n\tif (!ORYX.Editor._resizeFixTimeout) {\n\t\tORYX.Editor._resizeFixTimeout = window.setTimeout(function() {\n\t\t\twindow.resizeBy(1,1);\n\t\t\twindow.resizeBy(-1,-1);\n\t\t\tORYX.Editor._resizefixTimeout = null;\n\t\t}, 100); \n\t}\n};\n\nORYX.Editor.Cookie = {\n\t\n\tcallbacks:[],\n\t\t\n\tonChange: function( callback, interval ){\n\t\n\t\tthis.callbacks.push(callback);\n\t\tthis.start( interval )\n\t\n\t},\n\t\n\tstart: function( interval ){\n\t\t\n\t\tif( this.pe ){\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tvar currentString = document.cookie;\n\t\t\n\t\tthis.pe = new PeriodicalExecuter( function(){\n\t\t\t\n\t\t\tif( currentString != document.cookie ){\n\t\t\t\tcurrentString = document.cookie;\n\t\t\t\tthis.callbacks.each(function(callback){ callback(this.getParams()) }.bind(this));\n\t\t\t}\n\t\t\t\n\t\t}.bind(this), ( interval || 10000 ) / 1000);\t\n\t},\n\t\n\tstop: function(){\n\n\t\tif( this.pe ){\n\t\t\tthis.pe.stop();\n\t\t\tthis.pe = null;\n\t\t}\n\t},\n\t\t\n\tgetParams: function(){\n\t\tvar res = {};\n\t\t\n\t\tvar p = document.cookie;\n\t\tp.split(\"; \").each(function(param){ res[param.split(\"=\")[0]] = param.split(\"=\")[1];});\n\t\t\n\t\treturn res;\n\t},\t\n\t\n\ttoString: function(){\n\t\treturn document.cookie;\n\t}\n};\n\n/**\n * Workaround for SAFARI/Webkit, because\n * when trying to check SVGSVGElement of instanceof there is \n * raising an error\n * \n */\nORYX.Editor.SVGClassElementsAreAvailable = true;\nORYX.Editor.setMissingClasses = function() {\n\t\n\ttry {\n\t\tSVGElement;\n\t} catch(e) {\n\t\tORYX.Editor.SVGClassElementsAreAvailable = false;\n\t\tSVGSVGElement \t\t= document.createElementNS('http://www.w3.org/2000/svg', 'svg').toString();\n\t\tSVGGElement \t\t= document.createElementNS('http://www.w3.org/2000/svg', 'g').toString();\n\t\tSVGPathElement \t\t= document.createElementNS('http://www.w3.org/2000/svg', 'path').toString();\n\t\tSVGTextElement \t\t= document.createElementNS('http://www.w3.org/2000/svg', 'text').toString();\n\t\t//SVGMarkerElement \t= document.createElementNS('http://www.w3.org/2000/svg', 'marker').toString();\n\t\tSVGRectElement \t\t= document.createElementNS('http://www.w3.org/2000/svg', 'rect').toString();\n\t\tSVGImageElement \t= document.createElementNS('http://www.w3.org/2000/svg', 'image').toString();\n\t\tSVGCircleElement \t= document.createElementNS('http://www.w3.org/2000/svg', 'circle').toString();\n\t\tSVGEllipseElement \t= document.createElementNS('http://www.w3.org/2000/svg', 'ellipse').toString();\n\t\tSVGLineElement\t \t= document.createElementNS('http://www.w3.org/2000/svg', 'line').toString();\n\t\tSVGPolylineElement \t= document.createElementNS('http://www.w3.org/2000/svg', 'polyline').toString();\n\t\tSVGPolygonElement \t= document.createElementNS('http://www.w3.org/2000/svg', 'polygon').toString();\n\t\t\n\t}\n\t\n}\nORYX.Editor.checkClassType = function( classInst, classType ) {\n\t\n\tif( ORYX.Editor.SVGClassElementsAreAvailable ){\n\t\treturn classInst instanceof classType\n\t} else {\n\t\treturn classInst == classType\n\t}\n};\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespaces\n */\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\n\n\nnew function(){\n\t\n\tORYX.Core.UIEnableDrag = function(event, uiObj, option) {\n\t\n\t\tthis.uiObj = uiObj;\n\t\tvar upL = uiObj.bounds.upperLeft();\n\t\n\t\tvar a = uiObj.node.getScreenCTM();\n\t\tthis.faktorXY= {x: a.a, y: a.d};\n\t\t\n\t\tthis.scrollNode = uiObj.node.ownerSVGElement.parentNode.parentNode;\n\t\t\n\t\tthis.offSetPosition =  {\n\t\t\tx: Event.pointerX(event) - (upL.x * this.faktorXY.x),\n\t\t\ty: Event.pointerY(event) - (upL.y * this.faktorXY.y)};\n\t\n\t\tthis.offsetScroll\t= {x:this.scrollNode.scrollLeft,y:this.scrollNode.scrollTop};\n\t\t\t\n\t\tthis.dragCallback = ORYX.Core.UIDragCallback.bind(this);\n\t\tthis.disableCallback = ORYX.Core.UIDisableDrag.bind(this);\n\t\n\t\tthis.movedCallback = option ? option.movedCallback : undefined;\n\t\tthis.upCallback = option ? option.upCallback : undefined;\n\t\t\n\t\tdocument.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEUP, this.disableCallback, true);\n\t\tdocument.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, \tthis.dragCallback , false);\n\t\n\t};\n\t\n\tORYX.Core.UIDragCallback = function(event) {\n\t\n\t\tvar position = {\n\t\t\tx: Event.pointerX(event) - this.offSetPosition.x,\n\t\t\ty: Event.pointerY(event) - this.offSetPosition.y}\n\t\n\t\tposition.x \t-= this.offsetScroll.x - this.scrollNode.scrollLeft; \n\t\tposition.y \t-= this.offsetScroll.y - this.scrollNode.scrollTop;\n\t\n\t\tposition.x /= this.faktorXY.x;\n\t\tposition.y /= this.faktorXY.y;\n\t\n\t\tthis.uiObj.bounds.moveTo(position);\n\t\t//this.uiObj.update();\n\t\n\t\tif(this.movedCallback)\n\t\t\tthis.movedCallback(event);\n\t\t\n\t\t//Event.stop(event);\n\t\n\t};\n\t\n\tORYX.Core.UIDisableDrag = function(event) {\n\t\tdocument.documentElement.removeEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, this.dragCallback, false);\n\t\tdocument.documentElement.removeEventListener(ORYX.CONFIG.EVENT_MOUSEUP, this.disableCallback, true);\n\t\t\n\t\tif(this.upCallback)\n\t\t\tthis.upCallback(event);\n\t\t\t\n\t\tthis.upCallback = undefined;\n\t\tthis.movedCallback = undefined;\t\t\n\t\t\n\t\tEvent.stop(event);\t\n\t};\n\n\n\n\t\n\t/**\n\t * Implements a command to move docker by an offset.\n\t * \n\t * @class ORYX.Core.MoveDockersCommand\n\t * @param {Object} object An object with the docker id as key and docker and offset as object value\n\t * \n\t */\t\n\tORYX.Core.MoveDockersCommand = ORYX.Core.Command.extend({\n\t\tconstruct: function(dockers){\n\t\t\tthis.dockers \t= $H(dockers);\n\t\t\tthis.edges \t\t= $H({});\n\t\t},\n\t\texecute: function(){\n\t\t\tif (this.changes) {\n\t\t\t\tthis.executeAgain();\n\t\t\t\treturn;\n\t\t\t} else {\n\t\t\t\tthis.changes = $H({});\n\t\t\t}\n\t\t\t\n\t\t\tthis.dockers.values().each(function(docker){\n\t\t\t\tvar edge = docker.docker.parent;\n\t\t\t\tif (!edge){ return }\n\t\t\t\t\n\t\t\t\tif (!this.changes[edge.getId()]) {\n\t\t\t\t\tthis.changes[edge.getId()] = {\n\t\t\t\t\t\tedge\t\t\t\t: edge,\n\t\t\t\t\t\toldDockerPositions\t: edge.dockers.map(function(r){ return r.bounds.center() })\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tdocker.docker.bounds.moveBy(docker.offset);\n\t\t\t\tthis.edges[edge.getId()] = edge;\n\t\t\t\tdocker.docker.update();\n\t\t\t}.bind(this));\n\t\t\tthis.edges.each(function(edge){\n\t\t\t\tthis.updateEdge(edge.value);\n\t\t\t\tif (this.changes[edge.value.getId()])\n\t\t\t\t\tthis.changes[edge.value.getId()].dockerPositions = edge.value.dockers.map(function(r){ return r.bounds.center() })\n\t\t\t}.bind(this));\n\t\t},\n\t\tupdateEdge: function(edge){\n\t\t\tedge._update(true);\n\t\t\t[edge.getOutgoingShapes(), edge.getIncomingShapes()].flatten().invoke(\"_update\", [true])\n\t\t},\n\t\texecuteAgain: function(){\n\t\t\tthis.changes.values().each(function(change){\n\t\t\t\t// Reset the dockers\n\t\t\t\tthis.removeAllDocker(change.edge);\n\t\t\t\tchange.dockerPositions.each(function(pos, i){\t\n\t\t\t\t\tif (i==0||i==change.dockerPositions.length-1){ return }\t\t\t\t\t\n\t\t\t\t\tvar docker = change.edge.createDocker(undefined, pos);\n\t\t\t\t\tdocker.bounds.centerMoveTo(pos);\n\t\t\t\t\tdocker.update();\n\t\t\t\t}.bind(this));\n\t\t\t\tthis.updateEdge(change.edge);\n\t\t\t}.bind(this));\n\t\t},\n\t\trollback: function(){\n\t\t\tthis.changes.values().each(function(change){\n\t\t\t\t// Reset the dockers\n\t\t\t\tthis.removeAllDocker(change.edge);\n\t\t\t\tchange.oldDockerPositions.each(function(pos, i){\t\n\t\t\t\t\tif (i==0||i==change.oldDockerPositions.length-1){ return }\t\t\t\t\t\n\t\t\t\t\tvar docker = change.edge.createDocker(undefined, pos);\n\t\t\t\t\tdocker.bounds.centerMoveTo(pos);\n\t\t\t\t\tdocker.update();\n\t\t\t\t}.bind(this));\n\t\t\t\tthis.updateEdge(change.edge);\n\t\t\t}.bind(this));\n\t\t},\n\t\tremoveAllDocker: function(edge){\n\t\t\tedge.dockers.slice(1, edge.dockers.length-1).each(function(docker){\n\t\t\t\tedge.removeDocker(docker);\n\t\t\t})\n\t\t}\n\t});\n\t\n}();\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespaces\n */\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\n\n/**\n * @classDescription Base class for Shapes.\n * @extends ORYX.Core.AbstractShape\n */\nORYX.Core.Shape = {\n\n\t/**\n\t * Constructor\n\t */\n\tconstruct: function(options, stencil, facade) {\n\t\t// call base class constructor\n\t\targuments.callee.$.construct.apply(this, arguments);\n\t\t\n\t\tthis.facade = facade;\n\t\tthis.dockers = [];\n\t\tthis.magnets = [];\n\t\t\n\t\tthis._defaultMagnet;\n\t\t\n\t\tthis.incoming = [];\n\t\tthis.outgoing = [];\n\t\t\n\t\tthis.nodes = [];\n\t\t\n\t\tthis._dockerChangedCallback = this._dockerChanged.bind(this);\n\t\t\n\t\t//Hash map for all labels. Labels are not treated as children of shapes.\n\t\tthis._labels = new Hash();\n\t\t\n\t\t// create SVG node\n\t\tthis.node = ORYX.Editor.graft(\"http://www.w3.org/2000/svg\",\n\t\t\tnull,\n\t\t\t['g', {id:\"svg-\" + this.resourceId},\n\t\t\t\t['g', {\"class\": \"stencils\"},\n\t\t\t\t\t['g', {\"class\": \"me\"}],\n\t\t\t\t\t['g', {\"class\": \"children\", style:\"overflow:hidden\"}],\n\t\t\t\t\t['g', {\"class\": \"edge\"}]\n\t\t\t\t],\n\t\t\t\t['g', {\"class\": \"controls\"},\n\t\t\t\t\t['g', {\"class\": \"dockers\"}],\n\t\t\t\t\t['g', {\"class\": \"magnets\"}]\t\t\t\t\n\t\t\t\t]\n\t\t\t]);\n\t},\n\n\t/**\n\t * If changed flag is set, refresh method is called.\n\t */\n\tupdate: function() {\n\t\t//if(this.isChanged) {\n\t\t\t//this.layout();\n\t\t//}\n\t},\n\t\n\t/**\n\t * !!!Not called from any sub class!!!\n\t */\n\t_update: function() {\n\n\t},\n\t\n\t/**\n\t * Calls the super class refresh method\n\t *  and updates the svg elements that are referenced by a property.\n\t */\n\trefresh: function() {\n\t\t//call base class refresh method\n\t\targuments.callee.$.refresh.apply(this, arguments);\n\t\t\n\t\tif(this.node.ownerDocument) {\n\t\t\t//adjust SVG to properties' values\n\t\t\tvar me = this;\n\t\t\tthis.propertiesChanged.each((function(propChanged) {\n\t\t\t\tif(propChanged.value) {\n\t\t\t\t\tvar prop = this.properties[propChanged.key];\n\t\t\t\t\tvar property = this.getStencil().property(propChanged.key);\n\t\t\t\t\tif (property != undefined) {\n\t\t\t\t\t\tthis.propertiesChanged[propChanged.key] = false;\n\t\n\t\t\t\t\t\t//handle choice properties\n\t\t\t\t\t\tif(property.type() == ORYX.CONFIG.TYPE_CHOICE) {\n\t\t\t\t\t\t\t//iterate all references to SVG elements\n\t\t\t\t\t\t\tproperty.refToView().each((function(ref) {\n\t\t\t\t\t\t\t\t//if property is referencing a label, update the label\n\t\t\t\t\t\t\t\tif(ref !== \"\") {\n\t\t\t\t\t\t\t\t\tvar label = this._labels[this.id + ref];\n\t\t\t\t\t\t\t\t\tif (label && property.item(prop)) {\n\t\t\t\t\t\t\t\t\t\tlabel.text(property.item(prop).title());\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}).bind(this));\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t//if the choice's items are referencing SVG elements\n\t\t\t\t\t\t\t// show the selected and hide all other referenced SVG\n\t\t\t\t\t\t\t// elements\n\t\t\t\t\t\t\tvar refreshedSvgElements = new Hash();\n\t\t\t\t\t\t\tproperty.items().each((function(item) {\n\t\t\t\t\t\t\t\titem.refToView().each((function(itemRef) {\n\t\t\t\t\t\t\t\t\tif(itemRef == \"\") { return; }\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tvar svgElem = this.node.ownerDocument.getElementById(this.id + itemRef);\n\t\t\n\t\t\t\t\t\t\t\t\tif(!svgElem) { return; }\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t/* Do not refresh the same svg element multiple times */\n\t\t\t\t\t\t\t\t\tif(!refreshedSvgElements[svgElem.id] || prop == item.value()) {\n\t\t\t\t\t\t\t\t\t\tsvgElem.setAttributeNS(null, 'display', ((prop == item.value()) ? 'inherit' : 'none'));\n\t\t\t\t\t\t\t\t\t\trefreshedSvgElements[svgElem.id] = svgElem;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t// Reload the href if there is an image-tag\n\t\t\t\t\t\t\t\t\tif(ORYX.Editor.checkClassType(svgElem, SVGImageElement)) {\n\t\t\t\t\t\t\t\t\t\tsvgElem.setAttributeNS('http://www.w3.org/1999/xlink', 'href', svgElem.getAttributeNS('http://www.w3.org/1999/xlink', 'href'));\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}).bind(this));\n\t\t\t\t\t\t\t}).bind(this));\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t} else { //handle properties that are not of type choice\n\t\t\t\t\t\t\t//iterate all references to SVG elements\n\t\t\t\t\t\t\tproperty.refToView().each((function(ref) {\n\t\t\t\t\t\t\t\t//if the property does not reference an SVG element,\n\t\t\t\t\t\t\t\t// do nothing\n\n\t\t\t\t\t\t\t\tif(ref === \"\") { return; }\n\n\t\t\t\t\t\t\t\tvar refId = this.id + ref;\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tif (property.type() === ORYX.CONFIG.TYPE_KISBPM_MULTIINSTANCE)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tif (ref === \"multiinstance\") {\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\tvar svgElemParallel = this.node.ownerDocument.getElementById(this.id + 'parallel');\n\t\t\t\t\t\t\t\t\t\tif(svgElemParallel) \n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tif (prop === 'Parallel')\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tsvgElemParallel.setAttributeNS(null, 'display', 'inherit');\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tsvgElemParallel.setAttributeNS(null, 'display', 'none');\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\t\n\t\t\t\t\t\t\t\t\t\tvar svgElemSequential = this.node.ownerDocument.getElementById(this.id + 'sequential');\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\tif(svgElemSequential) \n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tif (prop === 'Sequential')\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tsvgElemSequential.setAttributeNS(null, 'display', 'inherit');\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tsvgElemSequential.setAttributeNS(null, 'display', 'none');\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}\n\t\t\t\t\t\t\t\t\treturn;\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\telse if (property.type() === \"cancelactivity\")\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tvar svgElemFrame = this.node.ownerDocument.getElementById(this.id + 'frame');\n\t\t\t\t\t\t\t\t\tvar svgElemFrame2 = this.node.ownerDocument.getElementById(this.id + 'frame2');\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tif (prop === 'true')\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tsvgElemFrame.setAttributeNS(null, 'display', 'inherit');\n\t\t\t\t\t\t\t\t\t\tsvgElemFrame2.setAttributeNS(null, 'display', 'inherit');\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tsvgElemFrame.setAttributeNS(null, 'display', 'none');\n\t\t\t\t\t\t\t\t\t\tsvgElemFrame2.setAttributeNS(null, 'display', 'none');\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\n\t\t\t\t\t\t\t\t//get the SVG element\n\t\t\t\t\t\t\t\tvar svgElem = this.node.ownerDocument.getElementById(refId);\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t//if the SVG element can not be found\n\t\t\t\t\t\t\t\tif(!svgElem || !(svgElem.ownerSVGElement)) { \n\t\t\t\t\t\t\t\t\t//if the referenced SVG element is a SVGAElement, it cannot\n\t\t\t\t\t\t\t\t\t// be found with getElementById (Firefox bug).\n\t\t\t\t\t\t\t\t\t// this is a work around\n\t\t\t\t\t\t\t\t\tif(property.type() === ORYX.CONFIG.TYPE_URL || property.type() === ORYX.CONFIG.TYPE_DIAGRAM_LINK) {\n\t\t\t\t\t\t\t\t\t\tvar svgElems = this.node.ownerDocument.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'a');\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\tsvgElem = $A(svgElems).find(function(elem) {\n\t\t\t\t\t\t\t\t\t\t\treturn elem.getAttributeNS(null, 'id') === refId;\n\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\tif(!svgElem) { return; } \n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t//this.propertiesChanged[propChanged.key] = true;\n\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\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\n\t\t\t\t\t\t\t\tif (property.complexAttributeToView()) {\n\t\t\t\t\t\t\t\t\tvar label = this._labels[refId];\n\t\t\t\t\t\t\t\t\tif (label) {\n\t\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t    \tpropJson = prop.evalJSON();\n\t\t\t\t\t\t\t\t\t    \tvar value = propJson[property.complexAttributeToView()]\n\t\t\t\t\t\t\t\t\t    \tlabel.text(value ? value : prop);\n\t\t\t\t\t\t\t\t\t    } catch (e) {\n\t\t\t\t\t\t\t\t\t    \tlabel.text(prop);\n\t\t\t\t\t\t\t\t\t    }\n\t\t\t\t\t\t\t\t\t}\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\tswitch (property.type()) {\n\t\t\t\t\t\t\t\t\t\tcase ORYX.CONFIG.TYPE_BOOLEAN:\t\n\t\t\t\t\t\t\t\t\t\t    if (typeof prop == \"string\")\n\t\t\t\t\t\t\t\t\t\t\t\tprop = prop === \"true\"\n\t\t\n\t\t\t\t\t\t\t\t\t\t\tsvgElem.setAttributeNS(null, 'display', (!(prop === property.inverseBoolean())) ? 'inherit' : 'none');\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tcase ORYX.CONFIG.TYPE_COLOR:\n\t\t\t\t\t\t\t\t\t\t\tif(property.fill()) {\n\t\t\t\t\t\t\t\t\t\t\t\tif (svgElem.tagName.toLowerCase() === \"stop\"){\n\t\t\t\t\t\t\t\t\t\t\t\t\tif (prop){\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (property.lightness() &&  property.lightness() !== 1){\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tprop = ORYX.Utils.adjustLightness(prop, property.lightness());\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tsvgElem.setAttributeNS(null, \"stop-color\", prop);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Adjust stop color of the others\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (svgElem.parentNode.tagName.toLowerCase() === \"radialgradient\"){\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tORYX.Utils.adjustGradient(svgElem.parentNode, svgElem);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t// If there is no value, set opaque\n\t\t\t\t\t\t\t\t\t\t\t\t\tif (svgElem.parentNode.tagName.toLowerCase() === \"radialgradient\"){\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t$A(svgElem.parentNode.getElementsByTagName('stop')).each(function(stop){\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstop.setAttributeNS(null, \"stop-opacity\", prop ? stop.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'default-stop-opacity') || 1 : 0);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}.bind(this))\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\t\tsvgElem.setAttributeNS(null, 'fill', prop);\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tif(property.stroke()) {\n\t\t\t\t\t\t\t\t\t\t\t\tsvgElem.setAttributeNS(null, 'stroke', prop);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tcase ORYX.CONFIG.TYPE_STRING:\n\t\t\t\t\t\t\t\t\t\t\tvar label = this._labels[refId];\n\t\t\t\t\t\t\t\t\t\t\tif (label) {\n\t\t\t\t\t\t\t\t\t\t\t\tlabel.text(prop);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tcase ORYX.CONFIG.TYPE_EXPRESSION:\n\t\t\t\t\t\t\t\t\t\t\tvar label = this._labels[refId];\n\t\t\t\t\t\t\t\t\t\t\tif (label) {\n\t\t\t\t\t\t\t\t\t\t\t\tlabel.text(prop);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tcase ORYX.CONFIG.TYPE_DATASOURCE:\n\t\t\t\t\t\t\t\t\t\t\tvar label = this._labels[refId];\n\t\t\t\t\t\t\t\t\t\t\tif (label) {\n\t\t\t\t\t\t\t\t\t\t\t\tlabel.text(prop);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tbreak;\t\n\t\t\t\t\t\t\t\t\t\tcase ORYX.CONFIG.TYPE_INTEGER:\n\t\t\t\t\t\t\t\t\t\t\tvar label = this._labels[refId];\n\t\t\t\t\t\t\t\t\t\t\tif (label) {\n\t\t\t\t\t\t\t\t\t\t\t\tlabel.text(prop);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tcase ORYX.CONFIG.TYPE_FLOAT:\n\t\t\t\t\t\t\t\t\t\t\tif(property.fillOpacity()) {\n\t\t\t\t\t\t\t\t\t\t\t\tsvgElem.setAttributeNS(null, 'fill-opacity', prop);\n\t\t\t\t\t\t\t\t\t\t\t} \n\t\t\t\t\t\t\t\t\t\t\tif(property.strokeOpacity()) {\n\t\t\t\t\t\t\t\t\t\t\t\tsvgElem.setAttributeNS(null, 'stroke-opacity', prop);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tif(!property.fillOpacity() && !property.strokeOpacity()) {\n\t\t\t\t\t\t\t\t\t\t\t\tvar label = this._labels[refId];\n\t\t\t\t\t\t\t\t\t\t\t\tif (label) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tlabel.text(prop);\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\tcase ORYX.CONFIG.TYPE_FORM_LINK:\n\t  \t\t\t\t\t\t\t\t\t\tif (ref == \"pimg\") {\n\t  \t\t\t\t\t\t\t\t\t\t\tvar onclickAttr = svgElem.getAttributeNodeNS('', 'onclick');\n\t  \t\t\t\t\t\t\t\t\t\t\tif(onclickAttr) {\n\t  \t\t\t\t\t\t\t\t\t\t\t\tif(prop && (\"\" + prop).length > 0) {\n\t  \t\t\t\t\t\t\t\t\t\t\t\t\tonclickAttr.textContent = \"window.location = '../service/editor?id=\" + prop + \"_form'\";\n\t  \t\t\t\t\t\t\t    \t   \t\t\t} else {\n\t  \t\t\t\t\t\t\t    \t   \t\t\t\tnewFormFacade = this.facade;\n\t  \t\t\t\t\t\t\t    \t   \t\t\t\tonclickAttr.textContent = \"displayNewFormDialog('\" + this.resourceId + \"');\";\n\t  \t\t\t\t\t\t\t    \t\t        }\n\t  \t\t\t\t\t\t\t\t\t\t\t}\n\t  \t\t\t\t\t\t\t\t\t\t} else if (ref == \"linkIndicator\") {\n\t  \t\t\t\t\t\t\t\t\t\t\tif (prop && prop.length > 0) {\n\t  \t\t\t\t\t\t\t\t\t\t\t\tsvgElem.setAttributeNS(null, 'display', 'inherit');\n\t  \t\t\t\t\t\t\t\t\t\t\t} else {\n\t  \t\t\t\t\t\t\t\t\t\t\t\tsvgElem.setAttributeNS(null, 'display', 'none');\n\t  \t\t\t\t\t\t\t\t\t\t\t}\n\t  \t\t\t\t\t\t\t\t\t\t}\n\t  \t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tcase ORYX.CONFIG.TYPE_URL:\n\t\t\t\t\t\t\t\t\t\tcase ORYX.CONFIG.TYPE_DIAGRAM_LINK:\n\t\t\t\t\t\t\t\t\t\t\t//TODO what is the dafault path?\n\t\t\t\t\t\t\t\t\t\t\tvar hrefAttr = svgElem.getAttributeNodeNS('http://www.w3.org/1999/xlink', 'xlink:href');\n\t\t\t\t\t\t\t\t\t\t\tif(hrefAttr) {\n\t\t\t\t\t\t\t\t\t\t\t\threfAttr.textContent = prop;\n\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\tsvgElem.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', prop);\n\t\t\t\t\t\t\t\t\t\t\t}\t\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\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}).bind(this));\n\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\t\n\t\t\t\t}\n\t\t\t}).bind(this));\n\t\t\t\n\t\t\t//update labels\n\t\t\tthis._labels.values().each(function(label) {\n\t\t\t\tlabel.update();\n\t\t\t});\n\t\t}\n\t},\n\t\n\tlayout: function() {\n\t\t//this.getStencil().layout(this)\n\t\tvar layoutEvents = this.getStencil().layout()\n\t\tif (layoutEvents) {\n\t\t\tlayoutEvents.each(function(event) {\n\t\t\t\t\n\t\t\t\t// setup additional attributes\n\t\t\t\tevent.shape = this;\n\t\t\t\tevent.forceExecution = true;\n\t\t\t\t\n\t\t\t\t// do layouting\n\t\t\t\tthis._delegateEvent(event);\n\t\t\t}.bind(this))\n\t\t\t\n\t\t}\n\t},\n\t\n\t/**\n\t * Returns an array of Label objects.\n\t */\n\tgetLabels: function() {\n\t\treturn this._labels.values();\n\t},\n\t\n\t/**\n\t * Returns the label for a given ref\n\t * @return {ORYX.Core.Label} Returns null if there is no label\n\t */\n\tgetLabel: function(ref){\n\t\tif (!ref){\n\t\t\treturn null;\n\t\t}\n\t\treturn (this._labels.find(function(o){\n\t\t\t\treturn o.key.endsWith(ref);\n\t\t\t})||{}).value || null;\n\t},\n\t\n\t/**\n\t * Hides all related labels\n\t * \n\t */\n\thideLabels: function(){\n\t\tthis.getLabels().invoke(\"hide\");\n\t},\n\n\t/**\n\t * Shows all related labels\n\t * \n\t */\n\tshowLabels: function(){\n\t\tvar labels = this.getLabels();\n\t\tlabels.invoke(\"show\");\n\t\tlabels.each(function(label) {\n\t\t\t\tlabel.update();\n\t\t});\n\t},\n\t\n\tsetOpacity: function(value, animate){\n\t\t\n\t\tvalue = Math.max(Math.min((typeof value == \"number\" ? value : 1.0), 1.0), 0.0);\n\t\t\t\t\n\t\tif (value !== 1.0){\n\t\t\tvalue = String(value);\n\t\t\tthis.node.setAttributeNS(null, \"fill-opacity\", value)\n\t\t\tthis.node.setAttributeNS(null, \"stroke-opacity\", value)\n\t\t} else {\n\t\t\tthis.node.removeAttributeNS(null, \"fill-opacity\");\n\t\t\tthis.node.removeAttributeNS(null, \"stroke-opacity\");\n\t\t}\n\t},\n\t\n\t/**\n\t * Returns an array of dockers of this object.\n\t */\n\tgetDockers: function() {\n\t\treturn this.dockers;\n\t},\n\t\n\tgetMagnets: function() {\n\t\treturn this.magnets;\n\t},\n\t\n\tgetDefaultMagnet: function() {\n\t\tif(this._defaultMagnet) {\n\t\t\treturn this._defaultMagnet;\n\t\t} else if (this.magnets.length > 0) {\n\t\t\treturn this.magnets[0];\n\t\t} else {\n\t\t\treturn undefined;\n\t\t}\n\t},\n\n\tgetParentShape: function() {\n\t\treturn this.parent;\n\t},\n\t\n\tgetIncomingShapes: function(iterator) {\n\t\tif(iterator) {\n\t\t\tthis.incoming.each(iterator);\n\t\t}\n\t\treturn this.incoming;\n\t},\n\t\n\tgetIncomingNodes: function(iterator) {\n        return this.incoming.select(function(incoming){\n            var isNode = (incoming instanceof ORYX.Core.Node);\n            if(isNode && iterator) iterator(incoming);\n            return isNode;\n        });\n    },\n\t\n\t\n\tgetOutgoingShapes: function(iterator) {\n\t\tif(iterator) {\n\t\t\tthis.outgoing.each(iterator);\n\t\t}\n\t\treturn this.outgoing;\n\t},\n    \n    getOutgoingNodes: function(iterator) {\n        return this.outgoing.select(function(out){\n            var isNode = (out instanceof ORYX.Core.Node);\n            if(isNode && iterator) iterator(out);\n            return isNode;\n        });\n    },\n\t\n\tgetAllDockedShapes: function(iterator) {\n\t\tvar result = this.incoming.concat(this.outgoing);\n\t\tif(iterator) {\n\t\t\tresult.each(iterator);\n\t\t}\n\t\treturn result\n\t},\n\n\tgetCanvas: function() {\n\t\tif(this.parent instanceof ORYX.Core.Canvas) {\n\t\t\treturn this.parent;\n\t\t} else if(this.parent instanceof ORYX.Core.Shape) {\n\t\t\treturn this.parent.getCanvas();\n\t\t} else {\n\t\t\treturn undefined;\n\t\t}\n\t},\n\t\n\t/**\n\t * \n\t * @param {Object} deep\n\t * @param {Object} iterator\n\t */\n\tgetChildNodes: function(deep, iterator) {\n\t\tif(!deep && !iterator) {\n\t\t\treturn this.nodes.clone();\n\t\t} else {\n\t\t\tvar result = [];\n\t\t\tthis.nodes.each(function(uiObject) {\n\t\t\t\tif(!uiObject.isVisible){return}\n\t\t\t\tif(iterator) {\n\t\t\t\t\titerator(uiObject);\n\t\t\t\t}\n\t\t\t\tresult.push(uiObject);\n\t\t\t\t\n\t\t\t\tif(deep && uiObject instanceof ORYX.Core.Shape) {\n\t\t\t\t\tresult = result.concat(uiObject.getChildNodes(deep, iterator));\n\t\t\t\t}\n\t\t\t});\n\t\n\t\t\treturn result;\n\t\t}\n\t},\n\t\n\t/**\n\t * Overrides the UIObject.add method. Adds uiObject to the correct sub node.\n\t * @param {UIObject} uiObject\n\t * @param {Number} index\n\t */\n\tadd: function(uiObject, index, silent) {\n\t\t//parameter has to be an UIObject, but\n\t\t// must not be an Edge.\n\t\tif(uiObject instanceof ORYX.Core.UIObject \n\t\t\t&& !(uiObject instanceof ORYX.Core.Edge)) {\n\t\t\t\n\t\t\tif (!(this.children.member(uiObject))) {\n\t\t\t\t//if uiObject is child of another parent, remove it from that parent.\n\t\t\t\tif(uiObject.parent) {\n\t\t\t\t\tuiObject.parent.remove(uiObject, true);\n\t\t\t\t}\n\n\t\t\t\t//add uiObject to this Shape\n\t\t\t\tif(index != undefined)\n\t\t\t\t\tthis.children.splice(index, 0, uiObject);\n\t\t\t\telse\n\t\t\t\t\tthis.children.push(uiObject);\n\n\t\t\t\t//set parent reference\n\t\t\t\tuiObject.parent = this;\n\n\t\t\t\t//add uiObject.node to this.node depending on the type of uiObject\n\t\t\t\tvar parent;\n\t\t\t\tif(uiObject instanceof ORYX.Core.Node) {\n\t\t\t\t\tparent = this.node.childNodes[0].childNodes[1];\n\t\t\t\t\tthis.nodes.push(uiObject);\n\t\t\t\t} else if(uiObject instanceof ORYX.Core.Controls.Control) {\n\t\t\t\t\tvar ctrls = this.node.childNodes[1];\n\t\t\t\t\tif(uiObject instanceof ORYX.Core.Controls.Docker) {\n\t\t\t\t\t\tparent = ctrls.childNodes[0];\n\t\t\t\t\t\tif (this.dockers.length >= 2){\n\t\t\t\t\t\t\tthis.dockers.splice(index!==undefined?Math.min(index, this.dockers.length-1):this.dockers.length-1, 0, uiObject);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.dockers.push(uiObject);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if(uiObject instanceof ORYX.Core.Controls.Magnet) {\n\t\t\t\t\t\tparent = ctrls.childNodes[1];\n\t\t\t\t\t\tthis.magnets.push(uiObject);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tparent = ctrls;\n\t\t\t\t\t}\n\t\t\t\t} else {\t//UIObject\n\t\t\t\t\tparent = this.node;\n\t\t\t\t}\n\n\t\t\t\tif(index != undefined && index < parent.childNodes.length)\n\t\t\t\t\tuiObject.node = parent.insertBefore(uiObject.node, parent.childNodes[index]);\n\t\t\t\telse\n\t\t\t\t\tuiObject.node = parent.appendChild(uiObject.node);\n\t\t\t\t\t\n\t\t\t\tthis._changed();\n\t\t\t\t//uiObject.bounds.registerCallback(this._changedCallback);\n\t\t\t\t\n\t\t\t\t\n\t\t\t\tif(this.eventHandlerCallback && silent !== true)\n\t\t\t\t\tthis.eventHandlerCallback({type:ORYX.CONFIG.EVENT_SHAPEADDED,shape:uiObject})\n\t\t\t\t\t\n\t\t\t} else {\n\n\t\t\t\tORYX.Log.warn(\"add: ORYX.Core.UIObject is already a child of this object.\");\n\t\t\t}\n\t\t} else {\n\n\t\t\tORYX.Log.warn(\"add: Parameter is not of type ORYX.Core.UIObject.\");\n\t\t}\n\t},\n\n\t/**\n\t * Overrides the UIObject.remove method. Removes uiObject.\n\t * @param {UIObject} uiObject\n\t */\n\tremove: function(uiObject, silent) {\n\t\t//if uiObject is a child of this object, remove it.\n\t\tif (this.children.member(uiObject)) {\n\t\t\t//remove uiObject from children\n\t\t\tvar parent = uiObject.parent;\n\n\t\t\tthis.children = this.children.without(uiObject);\n\n\t\t\t//delete parent reference of uiObject\n\t\t\tuiObject.parent = undefined;\n\n\t\t\t//delete uiObject.node from this.node\n\t\t\tif(uiObject instanceof ORYX.Core.Shape) {\n\t\t\t\tif(uiObject instanceof ORYX.Core.Edge) {\n\t\t\t\t\tuiObject.removeMarkers();\n\t\t\t\t\tuiObject.node = this.node.childNodes[0].childNodes[2].removeChild(uiObject.node);\n\t\t\t\t} else {\n\t\t\t\t\tuiObject.node = this.node.childNodes[0].childNodes[1].removeChild(uiObject.node);\n\t\t\t\t\tthis.nodes = this.nodes.without(uiObject);\n\t\t\t\t}\n\t\t\t} else if(uiObject instanceof ORYX.Core.Controls.Control) {\n\t\t\t\tif (uiObject instanceof ORYX.Core.Controls.Docker) {\n\t\t\t\t\tuiObject.node = this.node.childNodes[1].childNodes[0].removeChild(uiObject.node);\n\t\t\t\t\tthis.dockers = this.dockers.without(uiObject);\n\t\t\t\t} else if (uiObject instanceof ORYX.Core.Controls.Magnet) {\n\t\t\t\t\tuiObject.node = this.node.childNodes[1].childNodes[1].removeChild(uiObject.node);\n\t\t\t\t\tthis.magnets = this.magnets.without(uiObject);\n\t\t\t\t} else {\n\t\t\t\t\tuiObject.node = this.node.childNodes[1].removeChild(uiObject.node);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif(this.eventHandlerCallback && silent !== true)\n\t\t\t\tthis.eventHandlerCallback({type: ORYX.CONFIG.EVENT_SHAPEREMOVED, shape: uiObject, parent: parent});\n\t\t\t\n\t\t\tthis._changed();\n\t\t\t//uiObject.bounds.unregisterCallback(this._changedCallback);\n\t\t} else {\n\n\t\t\tORYX.Log.warn(\"remove: ORYX.Core.UIObject is not a child of this object.\");\n\t\t}\n\t},\n\t\n\t/**\n\t * Calculate the Border Intersection Point between two points\n\t * @param {PointA}\n\t * @param {PointB}\n\t */\n\tgetIntersectionPoint: function() {\n\t\t\t\n\t\tvar pointAX, pointAY, pointBX, pointBY;\n\t\t\n\t\t// Get the the two Points\t\n\t\tswitch(arguments.length) {\n\t\t\tcase 2:\n\t\t\t\tpointAX = arguments[0].x;\n\t\t\t\tpointAY = arguments[0].y;\n\t\t\t\tpointBX = arguments[1].x;\n\t\t\t\tpointBY = arguments[1].y;\n\t\t\t\tbreak;\n\t\t\tcase 4:\n\t\t\t\tpointAX = arguments[0];\n\t\t\t\tpointAY = arguments[1];\n\t\t\t\tpointBX = arguments[2];\n\t\t\t\tpointBY = arguments[3];\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthrow \"getIntersectionPoints needs two or four arguments\";\n\t\t}\n\t\t\n\t\t\n\t\t\n\t\t// Defined an include and exclude point\n\t\tvar includePointX, includePointY, excludePointX, excludePointY;\n\n\t\tvar bounds = this.absoluteBounds();\n\t\t\n\t\tif(this.isPointIncluded(pointAX, pointAY, bounds)){\n\t\t\tincludePointX = pointAX;\n\t\t\tincludePointY = pointAY;\n\t\t} else {\n\t\t\texcludePointX = pointAX;\n\t\t\texcludePointY = pointAY;\n\t\t}\n\n\t\tif(this.isPointIncluded(pointBX, pointBY, bounds)){\n\t\t\tincludePointX = pointBX;\n\t\t\tincludePointY = pointBY;\n\t\t} else {\n\t\t\texcludePointX = pointBX;\n\t\t\texcludePointY = pointBY;\n\t\t}\n\t\t\t\t\n\t\t// If there is no inclue or exclude Shape, than return\n\t\tif(!includePointX || !includePointY || !excludePointX || !excludePointY) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tvar midPointX = 0;\n\t\tvar midPointY = 0;\t\t\n\t\t\n\t\tvar refPointX, refPointY;\n\t\t\n\t\tvar minDifferent = 1;\n\t\t// Get the UpperLeft and LowerRight\n\t\t//var ul = bounds.upperLeft();\n\t\t//var lr = bounds.lowerRight();\n\t\t\n\t\tvar i = 0;\n\t\t\n\t\twhile(true) {\n\t\t\t// Calculate the midpoint of the current to points\t\n\t\t\tvar midPointX = Math.min(includePointX, excludePointX) + ((Math.max(includePointX, excludePointX) - Math.min(includePointX, excludePointX)) / 2.0);\n\t\t\tvar midPointY = Math.min(includePointY, excludePointY) + ((Math.max(includePointY, excludePointY) - Math.min(includePointY, excludePointY)) / 2.0);\n\t\t\t\n\t\t\t\n\t\t\t// Set the new midpoint by the means of the include of the bounds\n\t\t\tif(this.isPointIncluded(midPointX, midPointY, bounds)){\n\t\t\t\tincludePointX = midPointX;\n\t\t\t\tincludePointY = midPointY;\n\t\t\t} else {\n\t\t\t\texcludePointX = midPointX;\n\t\t\t\texcludePointY = midPointY;\n\t\t\t}\t\t\t\n\t\t\t\n\t\t\t// Calc the length of the line\n\t\t\tvar length = Math.sqrt(Math.pow(includePointX - excludePointX, 2) + Math.pow(includePointY - excludePointY, 2))\n\t\t\t// Calc a point one step from the include point\n\t\t\trefPointX = includePointX + ((excludePointX - includePointX) / length),\n\t\t\trefPointY = includePointY + ((excludePointY - includePointY) / length)\n\t\t\t\t\t\n\t\t\t\n\t\t\t// If the reference point not in the bounds, break\n\t\t\tif(!this.isPointIncluded(refPointX, refPointY, bounds)) {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\n\t\t}\n\n\t\t// Return the last includepoint\n\t\treturn {x:refPointX , y:refPointY};\n\t},\n\n   \n    \n    /**\n     * Calculate if the point is inside the Shape\n     * @param {PointX}\n     * @param {PointY} \n     */\n    isPointIncluded: function(){\n\t\treturn  false\n\t},\n\n\t/**\n\t * Returns TRUE if the given node\n\t * is a child node of the shapes node\n\t * @param {Element} node\n\t * @return {Boolean}\n\t *\n\t */\n\tcontainsNode: function(node){\n\t\tvar me = this.node.firstChild.firstChild;\n\t\twhile(node){\n\t\t\tif (node == me){\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tnode = node.parentNode;\n\t\t}\n\t\treturn false\n\t},\n    \n    /**\n     * Calculate if the point is over an special offset area\n     * @param {Point}\n     */\n    isPointOverOffset: function(){\n\t\treturn  this.isPointIncluded.apply( this , arguments )\n\t},\n\t\t\n\t_dockerChanged: function() {\n\n\t},\n\t\t\n\t/**\n\t * Create a Docker for this Edge\n\t *\n\t */\n\tcreateDocker: function(index, position) {\n\t\tvar docker = new ORYX.Core.Controls.Docker({eventHandlerCallback: this.eventHandlerCallback});\n\t\tdocker.bounds.registerCallback(this._dockerChangedCallback);\n\t\tif (position) {\n\t\t\tdocker.bounds.centerMoveTo(position);\n\t\t}\n\t\tthis.add(docker, index);\n\t\t\n\t\treturn docker\n\t},\n\n\t/**\n\t * Get the serialized object\n\t * return Array with hash-entrees (prefix, name, value)\n\t * Following values will given:\n\t * \t\tBounds\n\t * \t\tOutgoing Shapes\n\t * \t\tParent\n\t */\n\tserialize: function() {\n\t\tvar serializedObject = arguments.callee.$.serialize.apply(this);\n\n\t\t// Add the bounds\n\t\tserializedObject.push({name: 'bounds', prefix:'oryx', value: this.bounds.serializeForERDF(), type: 'literal'});\n\n\t\t// Add the outgoing shapes\n\t\tthis.getOutgoingShapes().each((function(followingShape){\n\t\t\tserializedObject.push({name: 'outgoing', prefix:'raziel', value: '#'+ERDF.__stripHashes(followingShape.resourceId), type: 'resource'});\t\t\t\n\t\t}).bind(this));\n\n\t\t// Add the parent shape, if the parent not the canvas\n\t\t//if(this.parent instanceof ORYX.Core.Shape){\n\t\t\tserializedObject.push({name: 'parent', prefix:'raziel', value: '#'+ERDF.__stripHashes(this.parent.resourceId), type: 'resource'});\t\n\t\t//}\t\t\t\n\t\t\n\t\treturn serializedObject;\n\t},\n\t\t\n\t\t\n\tdeserialize: function(serialize, json){\n\t\targuments.callee.$.deserialize.apply(this, arguments);\n\t\t\n\t\t// Set the Bounds\n\t\tvar bounds = serialize.find(function(ser){ return 'oryx-bounds' === (ser.prefix+\"-\"+ser.name) });\n\t\tif (bounds) {\n\t\t\tvar b = bounds.value.replace(/,/g, \" \").split(\" \").without(\"\");\n\t\t\tif (this instanceof ORYX.Core.Edge) {\n\t\t\t\tif (!this.dockers.first().isChanged)\n\t\t\t\t\tthis.dockers.first().bounds.centerMoveTo(parseFloat(b[0]), parseFloat(b[1]));\n\t\t\t\tif (!this.dockers.last().isChanged)\n\t\t\t\t\tthis.dockers.last().bounds.centerMoveTo(parseFloat(b[2]), parseFloat(b[3]));\n\t\t\t} else {\n\t\t\t\tthis.bounds.set(parseFloat(b[0]), parseFloat(b[1]), parseFloat(b[2]), parseFloat(b[3]));\n\t\t\t}\n\t\t}\n\t\t\n\t\tif (json && json.labels instanceof Array){\n\t\t\tjson.labels.each(function(slabel){\n\t\t\t\tvar label = this.getLabel(slabel.ref);\n\t\t\t\tif (label){\n\t\t\t\t\tlabel.deserialize(slabel, this);\n\t\t\t\t}\n\t\t\t}.bind(this))\n\t\t}\n\t},\n\t\n\ttoJSON: function(){\n\t\tvar json = arguments.callee.$.toJSON.apply(this, arguments);\n\t\t\n\t\tvar labels = [], id = this.id;\n\t\tthis._labels.each(function(obj){\n\t\t\tvar slabel = obj.value.serialize();\n\t\t\tif (slabel){\n\t\t\t\tslabel.ref = obj.key.replace(id, '');\n\t\t\t\tlabels.push(slabel);\n\t\t\t}\n\t\t});\n\t\t\n\t\tif (labels.length > 0){\n\t\t\tjson.labels = labels;\n\t\t}\n\t\treturn json;\n\t},\n\n\t\t\n\t/**\n\t * Private methods.\n\t */\n\n\t/**\n\t * Child classes have to overwrite this method for initializing a loaded\n\t * SVG representation.\n\t * @param {SVGDocument} svgDocument\n\t */\n\t_init: function(svgDocument) {\n\t\t//adjust ids\n\t\tthis._adjustIds(svgDocument, 0);\n\t},\n\n\t_adjustIds: function(element, idIndex) {\n\t\tif(element instanceof Element) {\n\t\t\tvar eid = element.getAttributeNS(null, 'id');\n\t\t\tif(eid && eid !== \"\") {\n\t\t\t\telement.setAttributeNS(null, 'id', this.id + eid);\n\t\t\t} else {\n\t\t\t\telement.setAttributeNS(null, 'id', this.id + \"_\" + this.id + \"_\" + idIndex);\n\t\t\t\tidIndex++;\n\t\t\t}\n\t\t\t\n\t\t\t// Replace URL in fill attribute\n\t\t\tvar fill = element.getAttributeNS(null, 'fill');\n\t\t\tif (fill&&fill.include(\"url(#\")){\n\t\t\t\tfill = fill.replace(/url\\(#/g, 'url(#'+this.id);\n\t\t\t\telement.setAttributeNS(null, 'fill', fill);\n\t\t\t}\n\t\t\t\n\t\t\tif(element.hasChildNodes()) {\n\t\t\t\tfor(var i = 0; i < element.childNodes.length; i++) {\n\t\t\t\t\tidIndex = this._adjustIds(element.childNodes[i], idIndex);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn idIndex;\n\t},\n\n\ttoString: function() { return \"ORYX.Core.Shape \" + this.getId() }\n};\nORYX.Core.Shape = ORYX.Core.AbstractShape.extend(ORYX.Core.Shape);/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespaces\n */\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\nif(!ORYX.Core.Controls) {ORYX.Core.Controls = {};}\n\n\n/**\n * @classDescription Abstract base class for all Controls.\n */\nORYX.Core.Controls.Control = ORYX.Core.UIObject.extend({\n\t\n\ttoString: function() { return \"Control \" + this.id; }\n });/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespaces\n */\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\nif(!ORYX.Core.Controls) {ORYX.Core.Controls = {};}\n\n\n/**\n * @classDescription Represents a movable docker that can be bound to a shape. Dockers are used\n * for positioning shape objects.\n * @extends {Control}\n * \n * TODO absoluteXY und absoluteCenterXY von einem Docker liefern falsche Werte!!!\n */\nORYX.Core.Controls.Docker = ORYX.Core.Controls.Control.extend({\n\t/**\n\t * Constructor\n\t */\n\tconstruct: function() {\n\t\targuments.callee.$.construct.apply(this, arguments);\n\t\t\n\t\tthis.isMovable = true;\t\t\t\t// Enables movability\n\t\tthis.bounds.set(0, 0, 16, 16);\t\t// Set the bounds\n\t\tthis.referencePoint = undefined;\t\t// Refrenzpoint \n\t\tthis._dockedShapeBounds = undefined;\t\t\n\t\tthis._dockedShape = undefined;\n\t\tthis._oldRefPoint1 = undefined;\n\t\tthis._oldRefPoint2 = undefined;\n\t\t\n\t\t//this.anchors = [];\n\t\tthis.anchorLeft;\n\t\tthis.anchorRight;\n\t\tthis.anchorTop;\n\t\tthis.anchorBottom;\n\n\t\tthis.node = ORYX.Editor.graft(\"http://www.w3.org/2000/svg\",\n\t\t\tnull,\n\t\t\t['g']);\n\n\t\t// The DockerNode reprasentation\n\t\tthis._dockerNode = ORYX.Editor.graft(\"http://www.w3.org/2000/svg\",\n\t\t\tthis.node,\n\t\t\t['g', {\"pointer-events\":\"all\"},\n\t\t\t\t\t['circle', {cx:\"8\", cy:\"8\", r:\"8\", stroke:\"none\", fill:\"none\"}],\n\t\t\t\t\t['circle', {cx:\"8\", cy:\"8\", r:\"3\", stroke:\"black\", fill:\"red\", \"stroke-width\":\"1\"}]\n\t\t\t\t]);\n\t\t\t\n\t\t// The ReferenzNode reprasentation\t\n\t\tthis._referencePointNode = ORYX.Editor.graft(\"http://www.w3.org/2000/svg\",\n\t\t\tthis.node,\t\n\t\t\t['g', {\"pointer-events\":\"none\"},\n\t\t\t\t['circle', {cx: this.bounds.upperLeft().x, cy: this.bounds.upperLeft().y, r: 3, fill:\"red\", \"fill-opacity\":0.4}]]);\n\n\t\t// Hide the Docker\n\t\tthis.hide();\n\t\t\n\t\t//Add to the EventHandler\n\t\tthis.addEventHandlers(this._dockerNode);\n\n\t\t// Buffer the Update Callback for un-/register on Event-Handler \n\t\tthis._updateCallback = this._changed.bind(this);\n\t},\n\t\n\tupdate: function() {\n\t\t// If there have an DockedShape\t\n\t\tif(this._dockedShape) {\n\t\t\tif(this._dockedShapeBounds && this._dockedShape instanceof ORYX.Core.Node) {\n\t\t\t\t// Calc the delta of width and height of the lastBounds and the current Bounds\n\t\t\t\tvar dswidth = this._dockedShapeBounds.width();\n\t\t\t\tvar dsheight = this._dockedShapeBounds.height();\n\t\t\t\tif(!dswidth)\n\t\t\t\t\tdswidth = 1;\n\t\t\t\tif(!dsheight)\n\t\t\t\t\tdsheight = 1;\t\n\t\t\t\tvar widthDelta = \tthis._dockedShape.bounds.width() \t/ dswidth;\n\t\t\t\tvar heightDelta = \tthis._dockedShape.bounds.height() \t/ dsheight;\n\t\t\t\t\n\t\t\t\t// If there is an different\n\t\t\t\tif(widthDelta !== 1.0 || heightDelta !== 1.0) {\n\t\t\t\t\t// Set the delta\n\t\t\t\t\tthis.referencePoint.x *= widthDelta;\n\t\t\t\t\tthis.referencePoint.y *= heightDelta;\n\t\t\t\t}\n\t\n\t\t\t\t// Clone these bounds\n\t\t\t\tthis._dockedShapeBounds = this._dockedShape.bounds.clone();\t\t\t\t\n\t\t\t}\n\t\t\t\n\t\t\t// Get the first and the last Docker of the parent Shape\n\t\t\tvar dockerIndex = this.parent.dockers.indexOf(this)\n\t\t\tvar dock1 = this;\n\t\t\tvar dock2 = this.parent.dockers.length > 1 ? \n\t\t\t\t\t\t\t(dockerIndex === 0?\t\t\t\t\t\t\t// If there is the first element\n\t\t\t\t\t\t\t \tthis.parent.dockers[dockerIndex + 1]:\t// then take the next docker\n\t\t\t\t\t\t\t\tthis.parent.dockers[dockerIndex - 1]):  // if not, then take the docker before\n\t\t\t\t\t\t\tundefined;\n\t\t\t\n\t\t\t// Calculate the first absolute Refenzpoint \n\t\t\tvar absoluteReferenzPoint1 = dock1.getDockedShape() ? \n\t\t\t\tdock1.getAbsoluteReferencePoint() : \n\t\t\t\tdock1.bounds.center();\n\n\t\t\t// Calculate the last absolute Refenzpoint \n\t\t\tvar absoluteReferenzPoint2 = dock2 && dock2.getDockedShape() ? \n\t\t\t\tdock2.getAbsoluteReferencePoint() : \n\t\t\t\tdock2 ? \n\t\t\t\t\tdock2.bounds.center() :\n\t\t\t\t\tundefined;\n\n\t\t\t// If there is no last absolute Referenzpoint\t\t\n\t\t\tif(!absoluteReferenzPoint2) {\n\t\t\t\t// Calculate from the middle of the DockedShape\n\t\t\t\tvar center = this._dockedShape.absoluteCenterXY();\n\t\t\t\tvar minDimension = this._dockedShape.bounds.width() * this._dockedShape.bounds.height(); \n\t\t\t\tabsoluteReferenzPoint2 = {\n\t\t\t\t\tx: absoluteReferenzPoint1.x + (center.x - absoluteReferenzPoint1.x) * -minDimension,\n\t\t\t\t\ty: absoluteReferenzPoint1.y + (center.y - absoluteReferenzPoint1.y) * -minDimension\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tvar newPoint = undefined;\n\t\t\t\n\t\t\t/*if (!this._oldRefPoint1 || !this._oldRefPoint2 ||\n\t\t\t\tabsoluteReferenzPoint1.x !== this._oldRefPoint1.x ||\n\t\t\t\tabsoluteReferenzPoint1.y !== this._oldRefPoint1.y ||\n\t\t\t\tabsoluteReferenzPoint2.x !== this._oldRefPoint2.x ||\n\t\t\t\tabsoluteReferenzPoint2.y !== this._oldRefPoint2.y) {*/\n\t\t\t\t\n\t\t\t\t// Get the new point for the Docker, calucalted by the intersection point of the Shape and the two points\n\t\t\t\tnewPoint = this._dockedShape.getIntersectionPoint(absoluteReferenzPoint1, absoluteReferenzPoint2);\n\t\t\t\t\n\t\t\t\t// If there is new point, take the referencepoint as the new point\n\t\t\t\tif(!newPoint) {\n\t\t\t\t\tnewPoint = this.getAbsoluteReferencePoint();\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif(this.parent && this.parent.parent) {\n\t\t\t\t\tvar grandParentPos = this.parent.parent.absoluteXY();\n\t\t\t\t\tnewPoint.x -= grandParentPos.x;\n\t\t\t\t\tnewPoint.y -= grandParentPos.y;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// Set the bounds to the new point\n\t\t\t\tthis.bounds.centerMoveTo(newPoint)\n\t\t\t\n\t\t\t\tthis._oldRefPoint1 = absoluteReferenzPoint1;\n\t\t\t\tthis._oldRefPoint2 = absoluteReferenzPoint2;\n\t\t\t} \n\t\t\t/*else {\n\t\t\t\tnewPoint = this.bounds.center();\n\t\t\t}*/\n\t\t\t\n\t\t\t\n\t//\t}\n\t\t\n\t\t// Call the super class\n\t\targuments.callee.$.update.apply(this, arguments);\n\t},\n\n\t/**\n\t * Calls the super class refresh method and updates the view of the docker.\n\t */\n\trefresh: function() {\n\t\targuments.callee.$.refresh.apply(this, arguments);\n\t\t\n\t\t// Refresh the dockers node\n\t\tvar p = this.bounds.upperLeft();\n\t\tthis._dockerNode.setAttributeNS(null, 'transform','translate(' + p.x + ', ' + p.y + ')');\n\t\t\n\t\t// Refresh the referencepoints node\n\t\tp = Object.clone(this.referencePoint);\n\t\t\n\t\tif(p && this._dockedShape){\n\t\t\tvar upL \n\t\t\tif(this.parent instanceof ORYX.Core.Edge) {\n\t\t\t\tupL = this._dockedShape.absoluteXY();\n\t\t\t} else {\n\t\t\t\tupL = this._dockedShape.bounds.upperLeft();\n\t\t\t}\n\t\t\tp.x += upL.x;\n\t\t\tp.y += upL.y;\n\t\t} else {\n\t\t\tp = this.bounds.center();\n\t\t}\t\t\t\n\n\t\tthis._referencePointNode.setAttributeNS(null, 'transform','translate(' + p.x + ', ' + p.y + ')');\n\t},\n\n\t/**\n\t * Set the reference point\n\t * @param {Object} point\n\t */\t\n\tsetReferencePoint: function(point) {\n\t\t// Set the referencepoint\n\t\tif(this.referencePoint !== point &&\n\t\t\t(!this.referencePoint || \n\t\t\t!point ||\n\t\t\tthis.referencePoint.x !== point.x || \n\t\t\tthis.referencePoint.y !== point.y)) {\n\t\t\t\t\n\t\t\tthis.referencePoint = point;\n\t\t\tthis._changed();\t\t\t\n\t\t}\n\n\t\t\n\t\t// Update directly, because the referencepoint has no influence of the bounds\n\t\t//this.refresh();\n\t},\n\t\n\t/**\n\t * Get the absolute referencepoint\n\t */\n\tgetAbsoluteReferencePoint: function() {\n\t\tif(!this.referencePoint || !this._dockedShape) {\n\t\t\treturn undefined;\n\t\t} else {\n\t\t\tvar absUL = this._dockedShape.absoluteXY();\n\t\t\treturn {\t\n\t\t\t\t\t\tx: this.referencePoint.x + absUL.x,\n\t\t\t\t\t\ty: this.referencePoint.y + absUL.y\n\t\t\t\t\t}\n\t\t}\n\t},\t\n\t\n\t/**\n\t * Set the docked Shape from the docker\n\t * @param {Object} shape\n\t */\n\tsetDockedShape: function(shape) {\n\n\t\t// If there is an old docked Shape\n\t\tif(this._dockedShape) {\n\t\t\tthis._dockedShape.bounds.unregisterCallback(this._updateCallback)\n\t\t\t\n\t\t\t// Delete the Shapes from the incoming and outgoing array\n\t\t\t// If this Docker the incoming of the Shape\n\t\t\tif(this === this.parent.dockers.first()) {\n\t\t\t\t\n\t\t\t\tthis.parent.incoming = this.parent.incoming.without(this._dockedShape);\n\t\t\t\tthis._dockedShape.outgoing = this._dockedShape.outgoing.without(this.parent);\n\t\t\t\n\t\t\t// If this Docker the outgoing of the Shape\t\n\t\t\t} else if (this === this.parent.dockers.last()){\n\t\n\t\t\t\tthis.parent.outgoing = this.parent.outgoing.without(this._dockedShape);\n\t\t\t\tthis._dockedShape.incoming = this._dockedShape.incoming.without(this.parent);\n\t\t\t\t\t\t\t\n\t\t\t}\n\t\t\t\n\t\t}\n\n\t\t\n\t\t// Set the new Shape\n\t\tthis._dockedShape = shape;\n\t\tthis._dockedShapeBounds = undefined;\n\t\tvar referencePoint = undefined;\n\t\t\n\t\t// If there is an Shape, register the updateCallback if there are changes in the shape bounds\n\t\tif(this._dockedShape) {\n\t\t\t\n\t\t\t// Add the Shapes to the incoming and outgoing array\n\t\t\t// If this Docker the incoming of the Shape\n\t\t\tif(this === this.parent.dockers.first()) {\n\t\t\t\t\n\t\t\t\tthis.parent.incoming.push(shape);\n\t\t\t\tshape.outgoing.push(this.parent);\n\t\t\t\n\t\t\t// If this Docker the outgoing of the Shape\t\n\t\t\t} else if (this === this.parent.dockers.last()){\n\t\n\t\t\t\tthis.parent.outgoing.push(shape);\n\t\t\t\tshape.incoming.push(this.parent);\n\t\t\t\t\t\t\t\n\t\t\t}\n\t\t\t\n\t\t\t// Get the bounds and set the new referencepoint\n\t\t\tvar bounds = this.bounds;\n\t\t\tvar absUL = shape.absoluteXY();\n\t\t\t\n\t\t\t/*if(shape.parent){\n\t\t\t\tvar b = shape.parent.bounds.upperLeft();\n\t\t\t\tabsUL.x -= b.x;\n\t\t\t\tabsUL.y -= b.y;\n\t\t\t}*/\n\t\t\t\n\t\t\treferencePoint = {\n\t\t\t\tx: bounds.center().x - absUL.x,\n\t\t\t\ty: bounds.center().y - absUL.y\n\t\t\t}\t\n\t\t\t\t\t\t\n\t\t\tthis._dockedShapeBounds = this._dockedShape.bounds.clone();\n\t\t\t\n\t\t\tthis._dockedShape.bounds.registerCallback(this._updateCallback);\n\t\t\t\n\t\t\t// Set the color of the docker as docked\n\t\t\tthis.setDockerColor(ORYX.CONFIG.DOCKER_DOCKED_COLOR);\t\t\t\t\n\t\t} else {\n\t\t\t// Set the color of the docker as undocked\n\t\t\tthis.setDockerColor(ORYX.CONFIG.DOCKER_UNDOCKED_COLOR);\n\t\t}\n\n\t\t// Set the referencepoint\n\t\tthis.setReferencePoint(referencePoint);\n\t\tthis._changed();\n\t\t//this.update();\n\t},\n\t\n\t/**\n\t * Get the docked Shape\n\t */\n\tgetDockedShape: function() {\n\t\treturn this._dockedShape;\n\t},\n\n\t/**\n\t * Returns TRUE if the docker has a docked shape\n\t */\n\tisDocked: function() {\n\t\treturn !!this._dockedShape;\n\t},\n\t\t\n\t/**\n\t * Set the Color of the Docker\n\t * @param {Object} color\n\t */\n\tsetDockerColor: function(color) {\n\t\tthis._dockerNode.lastChild.setAttributeNS(null, \"fill\", color);\n\t},\n\t\n\tpreventHiding: function(prevent){\n\t\tthis._preventHiding = Math.max(0, (this._preventHiding||0) + (prevent ? 1 : -1));\n\t},\n\t\n\t/**\n\t * Hides this UIObject and all its children.\n\t */\n\thide: function() {\n\t\tif (this._preventHiding){\n\t\t\treturn false;\n\t\t}\n\t\t\n\t\t// Hide docker and reference point\n\t\tthis.node.setAttributeNS(null, 'visibility', 'hidden');\n\t\tthis._referencePointNode.setAttributeNS(null, 'visibility', 'hidden');\n\t\t\n\t\tthis.children.each(function(uiObj) {\n\t\t\tuiObj.hide();\t\n\t\t});\t\t\t\t\n\t},\n\t\n\t/**\n\t * Enables visibility of this UIObject and all its children.\n\t */\n\tshow: function() {\n\t\t// Show docker\n\t\tthis.node.setAttributeNS(null, 'visibility', 'visible');\n\t\t\n\t\t// Hide reference point if the connected shape is an edge\n\t\tif (this.getDockedShape() instanceof ORYX.Core.Edge){\n\t\t\tthis._referencePointNode.setAttributeNS(null, 'visibility', 'hidden');\n\t\t} else {\n\t\t\tthis._referencePointNode.setAttributeNS(null, 'visibility', 'visible');\n\t\t}\n\t\t\n\t\tthis.children.each(function(uiObj) {\n\t\t\tuiObj.show();\t\n\t\t});\t\t\n\t},\n\t\n\ttoString: function() { return \"Docker \" + this.id }\n});/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespaces\n */\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\nif(!ORYX.Core.Controls) {ORYX.Core.Controls = {};}\n\n\n/**\n * @classDescription Represents a magnet that is part of another shape and can\n * be attached to dockers. Magnets are used for linking edge objects\n * to other Shape objects.\n * @extends {Control}\n */\nORYX.Core.Controls.Magnet = ORYX.Core.Controls.Control.extend({\n\t\t\n\t/**\n\t * Constructor\n\t */\n\tconstruct: function() {\n\t\targuments.callee.$.construct.apply(this, arguments);\n\t\t\n\t\t//this.anchors = [];\n\t\tthis.anchorLeft;\n\t\tthis.anchorRight;\n\t\tthis.anchorTop;\n\t\tthis.anchorBottom;\n\t\t\n\t\tthis.bounds.set(0, 0, 16, 16);\n\t\t\n\t\t//graft magnet's root node into owner's control group.\n\t\tthis.node = ORYX.Editor.graft(\"http://www.w3.org/2000/svg\",\n\t\t\tnull,\n\t\t\t['g', {\"pointer-events\":\"all\"},\n\t\t\t\t\t['circle', {cx:\"8\", cy:\"8\", r:\"4\", stroke:\"none\", fill:\"red\", \"fill-opacity\":\"0.3\"}],\n\t\t\t\t]);\n\t\t\t\n\t\tthis.hide();\n\t},\n\t\n\tupdate: function() {\n\t\targuments.callee.$.update.apply(this, arguments);\n\t\t\n\t\t//this.isChanged = true;\n\t},\n\t\n\t_update: function() {\t\t\n\t\targuments.callee.$.update.apply(this, arguments);\n\t\t\n\t\t//this.isChanged = true;\n\t},\n\t\n\trefresh: function() {\n\t\targuments.callee.$.refresh.apply(this, arguments);\n\n\t\tvar p = this.bounds.upperLeft();\n\t\t/*if(this.parent) {\n\t\t\tvar parentPos = this.parent.bounds.upperLeft();\n\t\t\tp.x += parentPos.x;\n\t\t\tp.y += parentPos.y;\n\t\t}*/\n\t\t\n\t\tthis.node.setAttributeNS(null, 'transform','translate(' + p.x + ', ' + p.y + ')');\n\t},\n\t\n\tshow: function() {\n\t\t//this.refresh();\n\t\targuments.callee.$.show.apply(this, arguments);\n\t},\n\t\n\ttoString: function() {\n\t\treturn \"Magnet \" + this.id;\n\t}\n});\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespaces\n */\nif (!ORYX) {\n    var ORYX = {};\n}\nif (!ORYX.Core) {\n    ORYX.Core = {};\n}\n\n/**\n * @classDescription Abstract base class for all Nodes.\n * @extends ORYX.Core.Shape\n */\nORYX.Core.Node = {\n\n    /**\n     * Constructor\n     * @param options {Object} A container for arguments.\n     * @param stencil {Stencil}\n     */\n    construct: function(options, stencil, facade){\n        arguments.callee.$.construct.apply(this, arguments);\n        \n        this.isSelectable = true;\n        this.isMovable = true;\n\t\tthis._dockerUpdated = false;\n\t\tthis.facade = facade;\n        \n        this._oldBounds = new ORYX.Core.Bounds(); //init bounds with undefined values\n        this._svgShapes = []; //array of all SVGShape objects of\n        // SVG representation\n        \n        //TODO vielleicht in shape verschieben?\n        this.minimumSize = undefined; // {width:..., height:...}\n        this.maximumSize = undefined;\n        \n        //TODO vielleicht in shape oder uiobject verschieben?\n        // vielleicht sogar isResizable ersetzen?\n        this.isHorizontallyResizable = false;\n        this.isVerticallyResizable = false;\n        \n        this.dataId = undefined;\n        \n        this._init(this._stencil.view());\n        this.forcedHeight = -1;\n    },\n        \n    /**\n     * This method checks whether the shape is resized correctly and calls the\n     * super class update method.\n     */\n    _update: function(){\n\t\t\n\t\tthis.dockers.invoke(\"update\");\n\t\tif (this.isChanged) {\n\n\t\t\tvar bounds = this.bounds;\n            var oldBounds = this._oldBounds;\n\t\t\t\t\t\t\n\t\t\tif (this.isResized) {\n\t\t\t\n\t\t\t\tvar widthDelta = bounds.width() / oldBounds.width();\n\t\t\t\tvar heightDelta = bounds.height() / oldBounds.height();\n\t\t\t\t\n\t\t\t\t//iterate over all relevant svg elements and resize them\n\t\t\t\tthis._svgShapes.each(function(svgShape){\n\t\t\t\t\t//adjust width\n\t\t\t\t\tif (svgShape.isHorizontallyResizable) {\n\t\t\t\t\t\tsvgShape.width = svgShape.oldWidth * widthDelta;\n\t\t\t\t\t}\n\t\t\t\t\t//adjust height\n\t\t\t\t\tif (svgShape.isVerticallyResizable) {\n\t\t\t\t\t\tsvgShape.height = svgShape.oldHeight * heightDelta;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t//check, if anchors are set\n\t\t\t\t\tvar anchorOffset;\n\t\t\t\t\tvar leftIncluded = svgShape.anchorLeft;\n\t\t\t\t\tvar rightIncluded = svgShape.anchorRight;\n\t\t\t\t\t\n\t\t\t\t\tif (rightIncluded) {\n\t\t\t\t\t\tanchorOffset = oldBounds.width() - (svgShape.oldX + svgShape.oldWidth);\n\t\t\t\t\t\tif (leftIncluded) {\n\t\t\t\t\t\t\tsvgShape.width = bounds.width() - svgShape.x - anchorOffset;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tsvgShape.x = bounds.width() - (anchorOffset + svgShape.width);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse \n\t\t\t\t\t\tif (!leftIncluded) {\n\t\t\t\t\t\t\tsvgShape.x = widthDelta * svgShape.oldX;\n\t\t\t\t\t\t\tif (!svgShape.isHorizontallyResizable) {\n\t\t\t\t\t\t\t\tsvgShape.x = svgShape.x + svgShape.width * widthDelta / 2 - svgShape.width / 2;\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\tvar topIncluded = svgShape.anchorTop;\n\t\t\t\t\tvar bottomIncluded = svgShape.anchorBottom;\n\t\t\t\t\t\n\t\t\t\t\tif (bottomIncluded) {\n\t\t\t\t\t\tanchorOffset = oldBounds.height() - (svgShape.oldY + svgShape.oldHeight);\n\t\t\t\t\t\tif (topIncluded) {\n\t\t\t\t\t\t\tsvgShape.height = bounds.height() - svgShape.y - anchorOffset;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t// Hack for choreography task layouting\n\t\t\t\t\t\t\tif (!svgShape._isYLocked) {\n\t\t\t\t\t\t\t\tsvgShape.y = bounds.height() - (anchorOffset + svgShape.height);\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\telse \n\t\t\t\t\t\tif (!topIncluded) {\n\t\t\t\t\t\t\tsvgShape.y = heightDelta * svgShape.oldY;\n\t\t\t\t\t\t\tif (!svgShape.isVerticallyResizable) {\n\t\t\t\t\t\t\t\tsvgShape.y = svgShape.y + svgShape.height * heightDelta / 2 - svgShape.height / 2;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\t//check, if the current bounds is unallowed horizontally or vertically resized\n\t\t\t\tvar p = {\n\t\t\t\t\tx: 0,\n\t\t\t\t\ty: 0\n\t\t\t\t};\n\t\t\t\tif (!this.isHorizontallyResizable && bounds.width() !== oldBounds.width()) {\n\t\t\t\t\tp.x = oldBounds.width() - bounds.width();\n\t\t\t\t}\n\t\t\t\tif (!this.isVerticallyResizable && bounds.height() !== oldBounds.height()) {\n\t\t\t\t\tp.y = oldBounds.height() - bounds.height();\n\t\t\t\t}\n\t\t\t\tif (p.x !== 0 || p.y !== 0) {\n\t\t\t\t\tbounds.extend(p);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t//check, if the current bounds are between maximum and minimum bounds\n\t\t\t\tp = {\n\t\t\t\t\tx: 0,\n\t\t\t\t\ty: 0\n\t\t\t\t};\n\t\t\t\tvar widthDifference, heightDifference;\n\t\t\t\tif (this.minimumSize) {\n\t\t\t\t\n\t\t\t\t\tORYX.Log.debug(\"Shape (%0)'s min size: (%1x%2)\", this, this.minimumSize.width, this.minimumSize.height);\n\t\t\t\t\twidthDifference = this.minimumSize.width - bounds.width();\n\t\t\t\t\tif (widthDifference > 0) {\n\t\t\t\t\t\tp.x += widthDifference;\n\t\t\t\t\t}\n\t\t\t\t\theightDifference = this.minimumSize.height - bounds.height();\n\t\t\t\t\tif (heightDifference > 0) {\n\t\t\t\t\t\tp.y += heightDifference;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (this.maximumSize) {\n\t\t\t\t\n\t\t\t\t\tORYX.Log.debug(\"Shape (%0)'s max size: (%1x%2)\", this, this.maximumSize.width, this.maximumSize.height);\n\t\t\t\t\twidthDifference = bounds.width() - this.maximumSize.width;\n\t\t\t\t\tif (widthDifference > 0) {\n\t\t\t\t\t\tp.x -= widthDifference;\n\t\t\t\t\t}\n\t\t\t\t\theightDifference = bounds.height() - this.maximumSize.height;\n\t\t\t\t\tif (heightDifference > 0) {\n\t\t\t\t\t\tp.y -= heightDifference;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (p.x !== 0 || p.y !== 0) {\n\t\t\t\t\tbounds.extend(p);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t//update magnets\n\t\t\t\t\n\t\t\t\tvar widthDelta = bounds.width() / oldBounds.width();\n\t\t\t\tvar heightDelta = bounds.height() / oldBounds.height();\n\t\t\t\t\n\t\t\t\tvar leftIncluded, rightIncluded, topIncluded, bottomIncluded, center, newX, newY;\n\t\t\t\t\n\t\t\t\tthis.magnets.each(function(magnet){\n\t\t\t\t\tleftIncluded = magnet.anchorLeft;\n\t\t\t\t\trightIncluded = magnet.anchorRight;\n\t\t\t\t\ttopIncluded = magnet.anchorTop;\n\t\t\t\t\tbottomIncluded = magnet.anchorBottom;\n\t\t\t\t\t\n\t\t\t\t\tcenter = magnet.bounds.center();\n\t\t\t\t\t\n\t\t\t\t\tif (leftIncluded) {\n\t\t\t\t\t\tnewX = center.x;\n\t\t\t\t\t}\n\t\t\t\t\telse \n\t\t\t\t\t\tif (rightIncluded) {\n\t\t\t\t\t\t\tnewX = bounds.width() - (oldBounds.width() - center.x)\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tnewX = center.x * widthDelta;\n\t\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif (topIncluded) {\n\t\t\t\t\t\tnewY = center.y;\n\t\t\t\t\t}\n\t\t\t\t\telse \n\t\t\t\t\t\tif (bottomIncluded) {\n\t\t\t\t\t\t\tnewY = bounds.height() - (oldBounds.height() - center.y);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tnewY = center.y * heightDelta;\n\t\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif (center.x !== newX || center.y !== newY) {\n\t\t\t\t\t\tmagnet.bounds.centerMoveTo(newX, newY);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\t//set new position of labels\n\t\t\t\tthis.getLabels().each(function(label){\n\t\t\t\t\t// Set the position dependings on it anchor\n\t\t\t\t\tif (!label.isAnchorLeft()) {\n\t\t\t\t\t\tif (label.isAnchorRight()) {\n\t\t\t\t\t\t\tlabel.setX(bounds.width() - (oldBounds.width() - label.oldX))\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlabel.setX((label.position?label.position.x:label.x) * widthDelta);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (!label.isAnchorTop()) {\n\t\t\t\t\t\tif (label.isAnchorBottom()) {\n\t\t\t\t\t\t\tlabel.setY(bounds.height() - (oldBounds.height() - label.oldY));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlabel.setY((label.position?label.position.y:label.y) * heightDelta);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t// If there is an position,\n\t\t\t\t\t// set the origin position as well\n\t\t\t\t\tif (label.position){\n\t\t\t\t\t\tif (!label.isOriginAnchorLeft()) {\n\t\t\t\t\t\t\tif (label.isOriginAnchorRight()) {\n\t\t\t\t\t\t\t\tlabel.setOriginX(bounds.width() - (oldBounds.width() - label.oldX))\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tlabel.setOriginX(label.x * widthDelta);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!label.isOriginAnchorTop()) {\n\t\t\t\t\t\t\tif (label.isOriginAnchorBottom()) {\n\t\t\t\t\t\t\t\tlabel.setOriginY(bounds.height() - (oldBounds.height() - label.oldY));\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tlabel.setOriginY(label.y * heightDelta);\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\t\n\t\t\t\t//update docker\n\t\t\t\tvar docker = this.dockers[0];\n\t\t\t\tif (docker) {\n\t\t\t\t\tdocker.bounds.unregisterCallback(this._dockerChangedCallback);\n\t\t\t\t\tif (!this._dockerUpdated) {\n\t\t\t\t\t\tdocker.bounds.centerMoveTo(this.bounds.center());\n\t\t\t\t\t\tthis._dockerUpdated = false;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tdocker.update();\n\t\t\t\t\tdocker.bounds.registerCallback(this._dockerChangedCallback);\n\t\t\t\t}\n\t\t\t\tthis.isResized = false;\n\t\t\t}\n            \n            this.refresh();\n\t\t\t\n\t\t\tthis.isChanged = false;\n\t\t\t\n\t\t\tthis._oldBounds = this.bounds.clone();\n        }\n\t\t\n\t\tthis.children.each(function(value) {\n\t\t\tif(!(value instanceof ORYX.Core.Controls.Docker)) {\n\t\t\t\tvalue._update();\n\t\t\t}\n\t\t});\n\t\t\n\t\tif (this.dockers.length > 0&&!this.dockers.first().getDockedShape()) {\n\t\t\tthis.dockers.each(function(docker){\n\t\t\t\tdocker.bounds.centerMoveTo(this.bounds.center())\n\t\t\t}.bind(this))\n\t\t}\n\t\t\n\t\t/*this.incoming.each((function(edge) {\n\t\t\tif(!(this.dockers[0] && this.dockers[0].getDockedShape() instanceof ORYX.Core.Node))\n\t\t\t\tedge._update(true);\n\t\t}).bind(this));\n\t\t\n\t\tthis.outgoing.each((function(edge) {\n\t\t\tif(!(this.dockers[0] && this.dockers[0].getDockedShape() instanceof ORYX.Core.Node))\n\t\t\t\tedge._update(true);\n\t\t}).bind(this)); */\n    },\n    \n    /**\n     * This method repositions and resizes the SVG representation\n     * of the shape.\n     */\n    refresh: function(){\n        arguments.callee.$.refresh.apply(this, arguments);\n        \n        /** Movement */\n        var x = this.bounds.upperLeft().x;\n        var y = this.bounds.upperLeft().y;\n        \n\t\t// Move owner element\n\t\tthis.node.firstChild.setAttributeNS(null, \"transform\", \"translate(\" + x + \", \" + y + \")\");\n\t\t// Move magnets\n\t\tthis.node.childNodes[1].childNodes[1].setAttributeNS(null, \"transform\", \"translate(\" + x + \", \" + y + \")\");\n        \n        /** Resize */\n        \n        //iterate over all relevant svg elements and update them\n        this._svgShapes.each(function(svgShape){\n            svgShape.update();\n        });\n    },\n    \n    _dockerChanged: function(){\n\t\tvar docker = this.dockers[0];\n        \n        //set the bounds of the the association\n        this.bounds.centerMoveTo(docker.bounds.center());\n        \n\t\tthis._dockerUpdated = true;\n        //this._update(true);\n    },\n    \n    /**\n     * This method traverses a tree of SVGElements and returns\n     * all SVGShape objects. For each basic shape or path element\n     * a SVGShape object is initialized.\n     *\n     * @param svgNode {SVGElement}\n     * @return {Array} Array of SVGShape objects\n     */\n    _initSVGShapes: function(svgNode){\n        var svgShapes = [];\n        try {\n            var svgShape = new ORYX.Core.SVG.SVGShape(svgNode);\n            svgShapes.push(svgShape);\n        } \n        catch (e) {\n            //do nothing\n        }\n        \n        if (svgNode.hasChildNodes()) {\n            for (var i = 0; i < svgNode.childNodes.length; i++) {\n                svgShapes = svgShapes.concat(this._initSVGShapes(svgNode.childNodes[i]));\n            }\n        }\n        \n        return svgShapes;\n    },\n    \n    /**\n     * Calculate if the point is inside the Shape\n     * @param {PointX}\n     * @param {PointY} \n     * @param {absoluteBounds} optional: for performance\n     */\n    isPointIncluded: function(pointX, pointY, absoluteBounds){\n        // If there is an arguments with the absoluteBounds\n        var absBounds = absoluteBounds && absoluteBounds instanceof ORYX.Core.Bounds ? absoluteBounds : this.absoluteBounds();\n        \n        if (!absBounds.isIncluded(pointX, pointY)) {\n\t\t\treturn false;\n\t\t} else {\n\t\t\t\n\t\t}\n\t\t\t\n        \n        //point = Object.clone(point);\n        var ul = absBounds.upperLeft();\n        var x = pointX - ul.x;\n        var y = pointY - ul.y;\t\t\n\t\n\t\tvar i=0;\n\t\tdo {\n\t\t\tvar isPointIncluded = this._svgShapes[i++].isPointIncluded( x, y );\n\t\t} while( !isPointIncluded && i < this._svgShapes.length)\n\t\t\n\t\treturn isPointIncluded;\n\n        /*return this._svgShapes.any(function(svgShape){\n            return svgShape.isPointIncluded(point);\n        });*/\n    },\n \n    \n    /**\n     * Calculate if the point is over an special offset area\n     * @param {Point}\n     */\n    isPointOverOffset: function( pointX, pointY ){       \n\t\tvar isOverEl = arguments.callee.$.isPointOverOffset.apply( this , arguments );\n\t\t\n\t\tif (isOverEl) {\n\t\t\t\t\t\t\n\t        // If there is an arguments with the absoluteBounds\n\t        var absBounds = this.absoluteBounds();\n\t        absBounds.widen( - ORYX.CONFIG.BORDER_OFFSET );\n\t\t\t\n\t        if ( !absBounds.isIncluded( pointX, pointY )) {\n\t            return true;\n\t        }\t\t\n\t\t}\n\t\t\n\t\treturn false;\n\t\t\n\t},\n\t   \n    serialize: function(){\n        var result = arguments.callee.$.serialize.apply(this);\n        \n        // Add the docker's bounds\n        // nodes only have at most one docker!\n        this.dockers.each((function(docker){\n\t\t\tif (docker.getDockedShape()) {\n\t\t\t\tvar center = docker.referencePoint;\n\t\t\t\tcenter = center ? center : docker.bounds.center();\n\t\t\t\tresult.push({\n\t\t\t\t\tname: 'docker',\n\t\t\t\t\tprefix: 'oryx',\n\t\t\t\t\tvalue: $H(center).values().join(','),\n\t\t\t\t\ttype: 'literal'\n\t\t\t\t});\n\t\t\t}\n        }).bind(this));\n        \n        // Get the spezific serialized object from the stencil\n        try {\n            //result = this.getStencil().serialize(this, result);\n\n\t\t\tvar serializeEvent = this.getStencil().serialize();\n\t\t\t\n\t\t\t/*\n\t\t\t * call serialize callback by reference, result should be found\n\t\t\t * in serializeEvent.result\n\t\t\t */\n\t\t\tif(serializeEvent.type) {\n\t\t\t\tserializeEvent.shape = this;\n\t\t\t\tserializeEvent.data = result;\n\t\t\t\tserializeEvent.result = undefined;\n\t\t\t\tserializeEvent.forceExecution = true;\n\t\t\t\t\n\t\t\t\tthis._delegateEvent(serializeEvent);\n\t\t\t\t\n\t\t\t\tif(serializeEvent.result) {\n\t\t\t\t\tresult = serializeEvent.result;\n\t\t\t\t}\n\t\t\t}\n        } \n        catch (e) {\n        }\n        return result;\n    },\n    \n    deserialize: function(data){\n    \targuments.callee.$.deserialize.apply(this, arguments);\n\t\t\n\t    try {\n            //data = this.getStencil().deserialize(this, data);\n\n\t\t\tvar deserializeEvent = this.getStencil().deserialize();\n\t\t\t\n\t\t\t/*\n\t\t\t * call serialize callback by reference, result should be found\n\t\t\t * in serializeEventInfo.result\n\t\t\t */\n\t\t\tif(deserializeEvent.type) {\n\t\t\t\tdeserializeEvent.shape = this;\n\t\t\t\tdeserializeEvent.data = data;\n\t\t\t\tdeserializeEvent.result = undefined;\n\t\t\t\tdeserializeEvent.forceExecution = true;\n\t\t\t\t\n\t\t\t\tthis._delegateEvent(deserializeEvent);\n\t\t\t\tif(deserializeEvent.result) {\n\t\t\t\t\tdata = deserializeEvent.result;\n\t\t\t\t}\n\t\t\t}\n        } \n        catch (e) {\n        }\n\t\t\n\t\t// Set the outgoing shapes\n\t\tvar outgoing = data.findAll(function(ser){ return (ser.prefix+\"-\"+ser.name) == 'raziel-outgoing'});\n\t\toutgoing.each((function(obj){\n\t\t\t// TODO: Look at Canvas\n\t\t\tif(!this.parent) {return};\n\t\t\t\t\t\t\t\t\n\t\t\t// Set outgoing Shape\n\t\t\tvar next = this.getCanvas().getChildShapeByResourceId(obj.value);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\tif(next){\n\t\t\t\tif(next instanceof ORYX.Core.Edge) {\n\t\t\t\t\t//Set the first docker of the next shape\n\t\t\t\t\tnext.dockers.first().setDockedShape(this);\n\t\t\t\t\tnext.dockers.first().setReferencePoint(next.dockers.first().bounds.center());\n\t\t\t\t} else if(next.dockers.length > 0) { //next is a node and next has a docker\n\t\t\t\t\tnext.dockers.first().setDockedShape(this);\n\t\t\t\t\t//next.dockers.first().setReferencePoint({x: this.bounds.width() / 2.0, y: this.bounds.height() / 2.0});\n\t\t\t\t}\n\t\t\t}\t\n\t\t\t\n\t\t}).bind(this));\n        \n        if (this.dockers.length === 1) {\n            var dockerPos;\n            dockerPos = data.find(function(entry){\n                return (entry.prefix + \"-\" + entry.name === \"oryx-dockers\");\n            });\n            \n            if (dockerPos) {\n                var points = dockerPos.value.replace(/,/g, \" \").split(\" \").without(\"\").without(\"#\");\n\t\t\t\tif (points.length === 2 && this.dockers[0].getDockedShape()) {\n                    this.dockers[0].setReferencePoint({\n                        x: parseFloat(points[0]),\n                        y: parseFloat(points[1])\n                    });\n                }\n                else {\n                    this.dockers[0].bounds.centerMoveTo(parseFloat(points[0]), parseFloat(points[1]));\n                }\n            }\n        }\n    },\n    \n    /**\n     * This method excepts the SVGDoucment that is the SVG representation\n     * of this shape.\n     * The bounds of the shape are calculated, the SVG representation's upper left point\n     * is moved to 0,0 and it the method sets if this shape is resizable.\n     *\n     * @param {SVGDocument} svgDocument\n     */\n    _init: function(svgDocument){\n        arguments.callee.$._init.apply(this, arguments);\n\t\t\n        var svgNode = svgDocument.getElementsByTagName(\"g\")[0]; //outer most g node\n        // set all required attributes\n        var attributeTitle = svgDocument.ownerDocument.createAttribute(\"title\");\n        attributeTitle.nodeValue = this.getStencil().title();\n        svgNode.setAttributeNode(attributeTitle);\n        \n        var attributeId = svgDocument.ownerDocument.createAttribute(\"id\");\n        attributeId.nodeValue = this.id;\n        svgNode.setAttributeNode(attributeId);\n        \n        // \n        var stencilTargetNode = this.node.childNodes[0].childNodes[0]; //<g class=me>\"\n        svgNode = stencilTargetNode.appendChild(svgNode);\n        \n        // Add to the EventHandler\n        this.addEventHandlers(svgNode.parentNode);\n        \n        /**set minimum and maximum size*/\n        var minSizeAttr = svgNode.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, \"minimumSize\");\n        if (minSizeAttr) {\n            minSizeAttr = minSizeAttr.replace(\"/,/g\", \" \");\n            var minSizeValues = minSizeAttr.split(\" \");\n            minSizeValues = minSizeValues.without(\"\");\n            \n            if (minSizeValues.length > 1) {\n                this.minimumSize = {\n                    width: parseFloat(minSizeValues[0]),\n                    height: parseFloat(minSizeValues[1])\n                };\n            }\n            else {\n                //set minimumSize to (1,1), so that width and height of the stencil can never be (0,0)\n                this.minimumSize = {\n                    width: 1,\n                    height: 1\n                };\n            }\n        }\n        \n        var maxSizeAttr = svgNode.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, \"maximumSize\");\n        if (maxSizeAttr) {\n            maxSizeAttr = maxSizeAttr.replace(\"/,/g\", \" \");\n            var maxSizeValues = maxSizeAttr.split(\" \");\n            maxSizeValues = maxSizeValues.without(\"\");\n            \n            if (maxSizeValues.length > 1) {\n                this.maximumSize = {\n                    width: parseFloat(maxSizeValues[0]),\n                    height: parseFloat(maxSizeValues[1])\n                };\n            }\n        }\n        \n        if (this.minimumSize && this.maximumSize &&\n        (this.minimumSize.width > this.maximumSize.width ||\n        this.minimumSize.height > this.maximumSize.height)) {\n        \n            //TODO wird verschluckt!!!\n            throw this + \": Minimum Size must be greater than maxiumSize.\";\n        }\n        \n        /**get current bounds and adjust it to upperLeft == (0,0)*/\n        //initialize all SVGShape objects\n        this._svgShapes = this._initSVGShapes(svgNode);\n        \n        //get upperLeft and lowerRight of stencil\n        var upperLeft = {\n            x: undefined,\n            y: undefined\n        };\n        var lowerRight = {\n            x: undefined,\n            y: undefined\n        };\n        var me = this;\n        this._svgShapes.each(function(svgShape){\n            upperLeft.x = (upperLeft.x !== undefined) ? Math.min(upperLeft.x, svgShape.x) : svgShape.x;\n            upperLeft.y = (upperLeft.y !== undefined) ? Math.min(upperLeft.y, svgShape.y) : svgShape.y;\n            lowerRight.x = (lowerRight.x !== undefined) ? Math.max(lowerRight.x, svgShape.x + svgShape.width) : svgShape.x + svgShape.width;\n            lowerRight.y = (lowerRight.y !== undefined) ? Math.max(lowerRight.y, svgShape.y + svgShape.height) : svgShape.y + svgShape.height;\n            \n            /** set if resizing is enabled */\n            //TODO isResizable durch die beiden anderen booleans ersetzen?\n            if (svgShape.isHorizontallyResizable) {\n                me.isHorizontallyResizable = true;\n                me.isResizable = true;\n            }\n            if (svgShape.isVerticallyResizable) {\n                me.isVerticallyResizable = true;\n                me.isResizable = true;\n            }\n            if (svgShape.anchorTop && svgShape.anchorBottom) {\n                me.isVerticallyResizable = true;\n                me.isResizable = true;\n            }\n            if (svgShape.anchorLeft && svgShape.anchorRight) {\n                me.isHorizontallyResizable = true;\n                me.isResizable = true;\n            }\n        });\n        \n        //move all SVGShapes by -upperLeft\n        this._svgShapes.each(function(svgShape){\n            svgShape.x -= upperLeft.x;\n            svgShape.y -= upperLeft.y;\n            svgShape.update();\n        });\n        \n        //set bounds of shape\n        //the offsets are also needed for positioning the magnets and the docker\n        var offsetX = upperLeft.x;\n        var offsetY = upperLeft.y;\n        \n        lowerRight.x -= offsetX;\n        lowerRight.y -= offsetY;\n        upperLeft.x = 0;\n        upperLeft.y = 0;\n        \n        //prevent that width or height of initial bounds is 0\n        if (lowerRight.x === 0) {\n            lowerRight.x = 1;\n        }\n        if (lowerRight.y === 0) {\n            lowerRight.y = 1;\n        }\n        \n        this._oldBounds.set(upperLeft, lowerRight);\n        this.bounds.set(upperLeft, lowerRight);\n        \n        /**initialize magnets */\n        \n        var magnets = svgDocument.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_ORYX, \"magnets\");\n        \n        if (magnets && magnets.length > 0) {\n        \n            magnets = $A(magnets[0].getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_ORYX, \"magnet\"));\n            \n            var me = this;\n            magnets.each(function(magnetElem){\n                var magnet = new ORYX.Core.Controls.Magnet({\n                    eventHandlerCallback: me.eventHandlerCallback\n                });\n                var cx = parseFloat(magnetElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, \"cx\"));\n                var cy = parseFloat(magnetElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, \"cy\"));\n                magnet.bounds.centerMoveTo({\n                    x: cx - offsetX,\n                    y: cy - offsetY\n                });\n                \n                //get anchors\n                var anchors = magnetElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, \"anchors\");\n                if (anchors) {\n                    anchors = anchors.replace(\"/,/g\", \" \");\n                    anchors = anchors.split(\" \").without(\"\");\n                    for(var i = 0; i < anchors.length; i++) {\n\t\t\t\t\t\tswitch(anchors[i].toLowerCase()) {\n\t\t\t\t\t\t\tcase \"left\":\n\t\t\t\t\t\t\t\tmagnet.anchorLeft = true;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase \"right\":\n\t\t\t\t\t\t\t\tmagnet.anchorRight = true;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase \"top\":\n\t\t\t\t\t\t\t\tmagnet.anchorTop = true;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase \"bottom\":\n\t\t\t\t\t\t\t\tmagnet.anchorBottom = true;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n                }\n                \n                me.add(magnet);\n                \n                //check, if magnet is default magnet\n                if (!this._defaultMagnet) {\n                    var defaultAttr = magnetElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, \"default\");\n                    if (defaultAttr && defaultAttr.toLowerCase() === \"yes\") {\n                        me._defaultMagnet = magnet;\n                    }\n                }\n            });\n        }\n        else {\n            // Add a Magnet in the Center of Shape\t\t\t\n            var magnet = new ORYX.Core.Controls.Magnet();\n            magnet.bounds.centerMoveTo(this.bounds.width() / 2, this.bounds.height() / 2);\n            this.add(magnet);\n        }\n        \n        /**initialize docker */\n        var dockerElem = svgDocument.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_ORYX, \"docker\");\n        \n        if (dockerElem && dockerElem.length > 0) {\n            dockerElem = dockerElem[0];\n            var docker = this.createDocker();\n            var cx = parseFloat(dockerElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, \"cx\"));\n            var cy = parseFloat(dockerElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, \"cy\"));\n            docker.bounds.centerMoveTo({\n                x: cx - offsetX,\n                y: cy - offsetY\n            });\n            \n            //get anchors\n            var anchors = dockerElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, \"anchors\");\n            if (anchors) {\n                anchors = anchors.replace(\"/,/g\", \" \");\n                anchors = anchors.split(\" \").without(\"\");\n                \n\t\t\t\tfor(var i = 0; i < anchors.length; i++) {\n\t\t\t\t\tswitch(anchors[i].toLowerCase()) {\n\t\t\t\t\t\tcase \"left\":\n\t\t\t\t\t\t\tdocker.anchorLeft = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"right\":\n\t\t\t\t\t\t\tdocker.anchorRight = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"top\":\n\t\t\t\t\t\t\tdocker.anchorTop = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"bottom\":\n\t\t\t\t\t\t\tdocker.anchorBottom = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n            }\n        }\n        \n        /**initialize labels*/\n        var textElems = svgNode.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'text');\n        $A(textElems).each((function(textElem){\n            var label = new ORYX.Core.SVG.Label({\n                textElement: textElem,\n\t\t\t\tshapeId: this.id\n            });\n            label.x -= offsetX;\n            label.y -= offsetY;\n            this._labels[label.id] = label;\n\t\t\t\n\t\t\tlabel.registerOnChange(this.layout.bind(this));\n\t\t\t\n\t\t\t// Only apply fitting on form-components\n\t\t\tif(this._stencil.id().indexOf(ORYX.CONFIG.FORM_ELEMENT_ID_PREFIX) == 0) {\n\t\t\t\tlabel.registerOnChange(this.fitToLabels.bind(this));\n\t\t\t}\n\t\t\t\n        }).bind(this));\n    },\n    \n    fitToLabels: function() {\n    \tvar y = 0;\n    \t\n    \tthis.getLabels().each(function(label){\n    \t\tvar lr = label.getY() + label.getHeight();\n    \t\tif(lr > y) {\n    \t\t\ty = lr;\n    \t\t}\n    \t});\n    \t\n    \tvar bounds = this.bounds;\n    \tvar boundsChanged = false;\n    \t\n    \tif(this.minimumSize) {\n    \t\t// Check if y-value exceeds the min-value. If not, stick to this value.\n    \t\tvar minHeight = this.minimumSize.height;\n    \t\tif(y < minHeight && bounds.height() > minHeight && minHeight > this.forcedHeight) {\n    \t\t\tbounds.set(bounds.upperLeft().x, bounds.upperLeft().y, bounds.lowerRight().x, bounds.upperLeft().y + minHeight);\n    \t\t\tboundsChanged = true;\n    \t\t} else if(y > minHeight && bounds.height() != y && y > this.forcedHeight){\n    \t\t\tbounds.set(bounds.upperLeft().x, bounds.upperLeft().y, bounds.lowerRight().x, bounds.upperLeft().y + y);\n    \t\t\tboundsChanged = true;\n    \t\t} else if(bounds.height() > this.forcedHeight && this.forcedHeight > 0) {\n    \t\t\tbounds.set(bounds.upperLeft().x, bounds.upperLeft().y, bounds.lowerRight().x, bounds.upperLeft().y + this.forcedHeight);\n    \t\t\tboundsChanged = true;\n    \t\t}\n    \t}\n    \t\n    \tif(boundsChanged) {\n    \t\t// Force facade to re-layout since bounds are changed AFTER layout has been performed\n    \t\tif(this.facade.getCanvas() != null) {\n\t\t\t\tthis.facade.getCanvas().update();\n\t\t\t}\n    \t\t\n    \t\t// Re-select if needed to force the select\n    \t\tif(this.facade.getSelection().member(this)) {\n    \t\t\tvar selectedNow = this.facade.getSelection();\n    \t\t\tthis.facade.setSelection([]);\n    \t\t\tthis.facade.setSelection(selectedNow);\n    \t\t}\n    \t}\n    },\n\t\n\t/**\n\t * Override the Method, that a docker is not shown\n\t *\n\t */\n\tcreateDocker: function() {\n\t\tvar docker = new ORYX.Core.Controls.Docker({eventHandlerCallback: this.eventHandlerCallback});\n\t\tdocker.bounds.registerCallback(this._dockerChangedCallback);\n\t\t\n\t\tthis.dockers.push( docker );\n\t\tdocker.parent = this;\n\t\tdocker.bounds.registerCallback(this._changedCallback);\t\t\n\t\t\n\t\treturn docker\t\t\n\t},\t\n    \n    toString: function(){\n        return this._stencil.title() + \" \" + this.id\n    }\n};\nORYX.Core.Node = ORYX.Core.Shape.extend(ORYX.Core.Node);\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nNAMESPACE_SVG = \"http://www.w3.org/2000/svg\";\nNAMESPACE_ORYX = \"http://www.b3mn.org/oryx\";\n\n\n/**\n * Init namespaces\n */\nif (!ORYX) {\n    var ORYX = {};\n}\nif (!ORYX.Core) {\n    ORYX.Core = {};\n}\n\n\n/**\n * @classDescription Abstract base class for all connections.\n * @extends {ORYX.Core.Shape}\n * @param options {Object}\n *\n * TODO da die verschiebung der Edge nicht ueber eine\n *  translation gemacht wird, die sich auch auf alle kind UIObjects auswirkt,\n *  muessen die kinder hier beim verschieben speziell betrachtet werden.\n *  Das sollte ueberarbeitet werden.\n *\n */\nORYX.Core.Edge = {\n    /**\n     * Constructor\n     * @param {Object} options\n     * @param {Stencil} stencil\n     */\n    construct: function(options, stencil, facade){\n        arguments.callee.$.construct.apply(this, arguments);\n        \n        this.isMovable = true;\n        this.isSelectable = true;\n\t\t\n\t\tthis._dockerUpdated = false;\n        \n        this._markers = new Hash(); //a hash map of SVGMarker objects where keys are the marker ids\n        this._paths = [];\n        this._interactionPaths = [];\n        this._dockersByPath = new Hash();\n        this._markersByPath = new Hash();\n\t\t\n\t\t/* Data structures to store positioning information of attached child nodes */ \n\t\tthis.attachedNodePositionData = new Hash();\n        \n        //TODO was muss hier initial erzeugt werden?\n        var stencilNode = this.node.childNodes[0].childNodes[0];\n        stencilNode = ORYX.Editor.graft(\"http://www.w3.org/2000/svg\", stencilNode, ['g', {\n            \"pointer-events\": \"painted\"\n        }]);\n        \n        //Add to the EventHandler\n        this.addEventHandlers(stencilNode.parentNode);\n        \n        \n        this._oldBounds = this.bounds.clone();\n        \n        //load stencil\n        this._init(this._stencil.view());\n        \n        if (stencil instanceof Array) {\n            this.deserialize(stencil);\n        }\n        \n    },\n    \n    _update: function(force){\n        if(this._dockerUpdated || this.isChanged || force) {\n\t\t  \n\t\t\tthis.dockers.invoke(\"update\");\n\t\t\t\n\t        if (false && (this.bounds.width() === 0 || this.bounds.height() === 0)) {\n\t\t\t\tvar width = this.bounds.width();\n\t\t\t\tvar height = this.bounds.height();\n\t            this.bounds.extend({\n\t                x: width === 0 ? 2 : 0,\n\t                y: height === 0 ? 2 : 0\n\t            });\n\t            this.bounds.moveBy({\n\t                x: width === 0 ? -1 : 0,\n\t                y: height === 0 ? -1 : 0\n\t            });\n            \n\t        }\n\t        \n\t        // TODO: Bounds muss abhaengig des Eltern-Shapes gesetzt werden\n\t        var upL = this.bounds.upperLeft();\n\t        var oldUpL = this._oldBounds.upperLeft();\n\t        var oldWidth = this._oldBounds.width() === 0 ? this.bounds.width() : this._oldBounds.width();\n\t        var oldHeight = this._oldBounds.height() === 0 ? this.bounds.height() : this._oldBounds.height();\n\t        var diffX = upL.x - oldUpL.x;\n\t        var diffY = upL.y - oldUpL.y;\n\t        var diffWidth = (this.bounds.width() / oldWidth) || 1;\n\t        var diffHeight = (this.bounds.height() / oldHeight) || 1;\n\t        \n\t        this.dockers.each((function(docker){\n\t            // Unregister on BoundsChangedCallback\n\t            docker.bounds.unregisterCallback(this._dockerChangedCallback);\n\t            \n\t            // If there is any changes at the edge and is there is not an DockersUpdate\n\t            // set the new bounds to the docker\n\t            if (!this._dockerUpdated) {\n\t                docker.bounds.moveBy(diffX, diffY);\n\t                \n\t                if (diffWidth !== 1 || diffHeight !== 1) {\n\t                    var relX = docker.bounds.upperLeft().x - upL.x;\n\t                    var relY = docker.bounds.upperLeft().y - upL.y;\n\t                    \n\t                    docker.bounds.moveTo(upL.x + relX * diffWidth, upL.y + relY * diffHeight);\n\t                }\n\t            }\n\t            // Do Docker update and register on DockersBoundChange\n\t            docker.update();\n\t            docker.bounds.registerCallback(this._dockerChangedCallback);\n\t            \n\t        }).bind(this));\n\t        \n\t        if (this._dockerUpdated) {\n\t            var a = this.dockers.first().bounds.center();\n\t            var b = this.dockers.first().bounds.center();\n\t            \n\t            this.dockers.each((function(docker){\n\t                var center = docker.bounds.center();\n\t                a.x = Math.min(a.x, center.x);\n\t                a.y = Math.min(a.y, center.y);\n\t                b.x = Math.max(b.x, center.x);\n\t                b.y = Math.max(b.y, center.y);\n\t            }).bind(this));\n\t            \n\t            //set the bounds of the the association\n\t            this.bounds.set(Object.clone(a), Object.clone(b));\n\t        }\n\t\t\t\n\t\t\tupL = this.bounds.upperLeft(); oldUpL = this._oldBounds.upperLeft();\n\t\t\tdiffWidth = (this.bounds.width() / (oldWidth||this.bounds.width())); diffHeight = (this.bounds.height() / (oldHeight||this.bounds.height())); \n\t        diffX = upL.x - oldUpL.x; diffY = upL.y - oldUpL.y;\n\t\t\t\t\t\n\t\t\t//reposition labels\n\t\t\tthis.getLabels().each(function(label) {\n\t\t\t\t\n\t\t\t\tif (label.getReferencePoint()){\n\t\t\t\t\tvar ref = label.getReferencePoint();\n\t\t\t\t\tvar from = ref.segment.from, to = ref.segment.to;\n\t\t\t\t\tif (!from || !from.parent || !to || !to.parent) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tvar fromPosition = from.bounds.center(), toPosition = to.bounds.center();\n\n\t\t\t\t\tif (fromPosition.x === ref.segment.fromPosition.x && fromPosition.y === ref.segment.fromPosition.y &&\n\t\t\t\t\t\ttoPosition.x === ref.segment.toPosition.x && toPosition.y === ref.segment.toPosition.y && !ref.dirty){\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif (!this.parent.initializingShapes) {\n\t\t\t\t\t\tvar oldDistance = ORYX.Core.Math.getDistanceBetweenTwoPoints(ref.segment.fromPosition, ref.segment.toPosition, ref.intersection);\n\t\t\t\t\t\tvar newIntersection = ORYX.Core.Math.getPointBetweenTwoPoints(fromPosition, toPosition, isNaN(oldDistance) ? 0.5 : oldDistance);\n\t\t\t\t\t\t\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * Set position\n\t\t\t\t\t\t */\n\t\t\t\t\t\t// Get the orthogonal identity vector of the current segment\n\t\t\t\t\t\tvar oiv = ORYX.Core.Math.getOrthogonalIdentityVector(fromPosition, toPosition);\n\t\t\t\t\t\tvar isHor = Math.abs(oiv.y)===1, isVer = Math.abs(oiv.x)===1;\n\t\t\t\t\t\toiv.x *= ref.distance; oiv.y *= ref.distance; \t\t\t\t// vector * distance\n\t\t\t\t\t\toiv.x += newIntersection.x; oiv.y += newIntersection.y; \t// vector + the intersection point\t\t\t\t\n\t\t\t\t\t\tvar mx = isHor && ref.orientation && (ref.iorientation||ref.orientation).endsWith(\"r\") ? -label.getWidth() : 0;\t\t\n\t\t\t\t\t\tvar my = isVer && ref.orientation && (ref.iorientation||ref.orientation).startsWith(\"l\") ? -label.getHeight()+2 : 0;\n\t\t\t\t\t\tlabel.setX(oiv.x+mx); label.setY(oiv.y+my);\n\t\t\t\t\t\t\n\t\t\t\t\t\t// Update the reference point\n\t\t\t\t\t\tthis.updateReferencePointOfLabel(label, newIntersection, from, to);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvar oiv = ORYX.Core.Math.getOrthogonalIdentityVector(fromPosition, toPosition);\n\t\t\t\t\t\toiv.x *= ref.distance; oiv.y *= ref.distance; // vector * distance\n\t\t\t\t\t\toiv.x += ref.intersection.x; oiv.y += ref.intersection.y; // vector + the intersection point\t\t\n\t\t\t\t\t\tlabel.setX(oiv.x); label.setY(oiv.y);\n\t\t\t\t\t\tref.segment.fromPosition = fromPosition; ref.segment.toPosition = toPosition;\t\t\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\treturn;\t\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// Update label position if no reference point is set\n\t\t\t\tif (label.position && !this.parent.initializingShapes){\n\t\t\t\t\tvar x = label.position.x + (diffX * (diffWidth||1));\n\t\t\t\t\tif (x > this.bounds.lowerRight().x){\n\t\t\t\t\t\tx += this.bounds.width()-(this.bounds.width()/(diffWidth||1));\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tvar y = label.position.y + (diffY * (diffHeight||1));\n\t\t\t\t\tif (y > this.bounds.lowerRight().y){\n\t\t\t\t\t\ty += this.bounds.height()-(this.bounds.height()/(diffHeight||1));\n\t\t\t\t\t}\n\t\t\t\t\tlabel.setX(x);label.setY(y);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tswitch (label.getEdgePosition()) {\n\t\t\t\t\tcase \"starttop\":\n\t\t\t\t\t\tvar angle = this._getAngle(this.dockers[0], this.dockers[1]);\n\t\t\t\t\t\tvar pos = this.dockers.first().bounds.center();\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (angle <= 90 || angle > 270) {\n\t\t\t\t\t\t\tlabel.horizontalAlign(\"left\");\n\t\t\t\t\t\t\tlabel.verticalAlign(\"bottom\");\n\t\t\t\t\t\t\tlabel.x = pos.x + label.getOffsetTop();\n\t\t\t\t\t\t\tlabel.y = pos.y - label.getOffsetTop();\n\t\t\t\t\t\t\tlabel.rotate(360 - angle, pos);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlabel.horizontalAlign(\"right\");\n\t\t\t\t\t\t\tlabel.verticalAlign(\"bottom\");\n\t\t\t\t\t\t\tlabel.x = pos.x - label.getOffsetTop();\n\t\t\t\t\t\t\tlabel.y = pos.y - label.getOffsetTop();\n\t\t\t\t\t\t\tlabel.rotate(180 - angle, pos);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase \"startmiddle\":\n\t\t\t\t\t\tvar angle = this._getAngle(this.dockers[0], this.dockers[1]);\n\t\t\t\t\t\tvar pos = this.dockers.first().bounds.center();\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (angle <= 90 || angle > 270) {\n\t\t\t\t\t\t\tlabel.horizontalAlign(\"left\");\n\t\t\t\t\t\t\tlabel.verticalAlign(\"bottom\");\n\t\t\t\t\t\t\tlabel.x = pos.x + 2;\n\t\t\t\t\t\t\tlabel.y = pos.y + 4;\n\t\t\t\t\t\t\tlabel.rotate(360 - angle, pos);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlabel.horizontalAlign(\"right\");\n\t\t\t\t\t\t\tlabel.verticalAlign(\"bottom\");\n\t\t\t\t\t\t\tlabel.x = pos.x + 1;\n\t\t\t\t\t\t\tlabel.y = pos.y + 4;\n\t\t\t\t\t\t\tlabel.rotate(180 - angle, pos);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\tcase \"startbottom\":\n\t\t\t\t\t\tvar angle = this._getAngle(this.dockers[0], this.dockers[1]);\n\t\t\t\t\t\tvar pos = this.dockers.first().bounds.center();\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (angle <= 90 || angle > 270) {\n\t\t\t\t\t\t\tlabel.horizontalAlign(\"left\");\n\t\t\t\t\t\t\tlabel.verticalAlign(\"top\");\n\t\t\t\t\t\t\tlabel.x = pos.x + label.getOffsetBottom();\n\t\t\t\t\t\t\tlabel.y = pos.y + label.getOffsetBottom();\n\t\t\t\t\t\t\tlabel.rotate(360 - angle, pos);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlabel.horizontalAlign(\"right\");\n\t\t\t\t\t\t\tlabel.verticalAlign(\"top\");\n\t\t\t\t\t\t\tlabel.x = pos.x - label.getOffsetBottom();\n\t\t\t\t\t\t\tlabel.y = pos.y + label.getOffsetBottom();\n\t\t\t\t\t\t\tlabel.rotate(180 - angle, pos);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"midtop\":\n\t\t\t\t\t\tvar numOfDockers = this.dockers.length;\n\t\t\t\t\t\tif(numOfDockers%2 == 0) {\n\t\t\t\t\t\t\tvar angle = this._getAngle(this.dockers[numOfDockers/2-1], this.dockers[numOfDockers/2])\n\t\t\t\t\t\t\tvar pos1 = this.dockers[numOfDockers/2-1].bounds.center();\n\t\t\t\t\t\t\tvar pos2 = this.dockers[numOfDockers/2].bounds.center();\n\t\t\t\t\t\t\tvar pos = {x:(pos1.x + pos2.x)/2.0, y:(pos1.y+pos2.y)/2.0};\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tlabel.horizontalAlign(\"center\");\n\t\t\t\t\t\t\tlabel.verticalAlign(\"bottom\");\n\t\t\t\t\t\t\tlabel.x = pos.x;\n\t\t\t\t\t\t\tlabel.y = pos.y - label.getOffsetTop();\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif (angle <= 90 || angle > 270) {\n\t\t\t\t\t\t\t\tlabel.rotate(360 - angle, pos);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tlabel.rotate(180 - angle, pos);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tvar index = parseInt(numOfDockers/2);\n\t\t\t\t\t\t\tvar angle = this._getAngle(this.dockers[index], this.dockers[index+1])\n\t\t\t\t\t\t\tvar pos = this.dockers[index].bounds.center();\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif (angle <= 90 || angle > 270) {\n\t\t\t\t\t\t\t\tlabel.horizontalAlign(\"left\");\n\t\t\t\t\t\t\t\tlabel.verticalAlign(\"bottom\");\n\t\t\t\t\t\t\t\tlabel.x = pos.x + label.getOffsetTop();\n\t\t\t\t\t\t\t\tlabel.y = pos.y - label.getOffsetTop();\n\t\t\t\t\t\t\t\tlabel.rotate(360 - angle, pos);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tlabel.horizontalAlign(\"right\");\n\t\t\t\t\t\t\t\tlabel.verticalAlign(\"bottom\");\n\t\t\t\t\t\t\t\tlabel.x = pos.x - label.getOffsetTop();\n\t\t\t\t\t\t\t\tlabel.y = pos.y - label.getOffsetTop();\n\t\t\t\t\t\t\t\tlabel.rotate(180 - angle, pos);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"midbottom\":\n\t\t\t\t\t\tvar numOfDockers = this.dockers.length;\n\t\t\t\t\t\tif(numOfDockers%2 == 0) {\n\t\t\t\t\t\t\tvar angle = this._getAngle(this.dockers[numOfDockers/2-1], this.dockers[numOfDockers/2])\n\t\t\t\t\t\t\tvar pos1 = this.dockers[numOfDockers/2-1].bounds.center();\n\t\t\t\t\t\t\tvar pos2 = this.dockers[numOfDockers/2].bounds.center();\n\t\t\t\t\t\t\tvar pos = {x:(pos1.x + pos2.x)/2.0, y:(pos1.y+pos2.y)/2.0};\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tlabel.horizontalAlign(\"center\");\n\t\t\t\t\t\t\tlabel.verticalAlign(\"top\");\n\t\t\t\t\t\t\tlabel.x = pos.x;\n\t\t\t\t\t\t\tlabel.y = pos.y + label.getOffsetTop();\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif (angle <= 90 || angle > 270) {\n\t\t\t\t\t\t\t\tlabel.rotate(360 - angle, pos);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tlabel.rotate(180 - angle, pos);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tvar index = parseInt(numOfDockers/2);\n\t\t\t\t\t\t\tvar angle = this._getAngle(this.dockers[index], this.dockers[index+1])\n\t\t\t\t\t\t\tvar pos = this.dockers[index].bounds.center();\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif (angle <= 90 || angle > 270) {\n\t\t\t\t\t\t\t\tlabel.horizontalAlign(\"left\");\n\t\t\t\t\t\t\t\tlabel.verticalAlign(\"top\");\n\t\t\t\t\t\t\t\tlabel.x = pos.x + label.getOffsetBottom();\n\t\t\t\t\t\t\t\tlabel.y = pos.y + label.getOffsetBottom();\n\t\t\t\t\t\t\t\tlabel.rotate(360 - angle, pos);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tlabel.horizontalAlign(\"right\");\n\t\t\t\t\t\t\t\tlabel.verticalAlign(\"top\");\n\t\t\t\t\t\t\t\tlabel.x = pos.x - label.getOffsetBottom();\n\t\t\t\t\t\t\t\tlabel.y = pos.y + label.getOffsetBottom();\n\t\t\t\t\t\t\t\tlabel.rotate(180 - angle, pos);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"endtop\":\n\t\t\t\t\t\tvar length = this.dockers.length;\n\t\t\t\t\t\tvar angle = this._getAngle(this.dockers[length-2], this.dockers[length-1]);\n\t\t\t\t\t\tvar pos = this.dockers.last().bounds.center();\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (angle <= 90 || angle > 270) {\n\t\t\t\t\t\t\tlabel.horizontalAlign(\"right\");\n\t\t\t\t\t\t\tlabel.verticalAlign(\"bottom\");\n\t\t\t\t\t\t\tlabel.x = pos.x - label.getOffsetTop();\n\t\t\t\t\t\t\tlabel.y = pos.y - label.getOffsetTop();\n\t\t\t\t\t\t\tlabel.rotate(360 - angle, pos);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlabel.horizontalAlign(\"left\");\n\t\t\t\t\t\t\tlabel.verticalAlign(\"bottom\");\n\t\t\t\t\t\t\tlabel.x = pos.x + label.getOffsetTop();\n\t\t\t\t\t\t\tlabel.y = pos.y - label.getOffsetTop();\n\t\t\t\t\t\t\tlabel.rotate(180 - angle, pos);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"endbottom\":\n\t\t\t\t\t\tvar length = this.dockers.length;\n\t\t\t\t\t\tvar angle = this._getAngle(this.dockers[length-2], this.dockers[length-1]);\n\t\t\t\t\t\tvar pos = this.dockers.last().bounds.center();\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (angle <= 90 || angle > 270) {\n\t\t\t\t\t\t\tlabel.horizontalAlign(\"right\");\n\t\t\t\t\t\t\tlabel.verticalAlign(\"top\");\n\t\t\t\t\t\t\tlabel.x = pos.x - label.getOffsetBottom();\n\t\t\t\t\t\t\tlabel.y = pos.y + label.getOffsetBottom();\n\t\t\t\t\t\t\tlabel.rotate(360 - angle, pos);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlabel.horizontalAlign(\"left\");\n\t\t\t\t\t\t\tlabel.verticalAlign(\"top\");\n\t\t\t\t\t\t\tlabel.x = pos.x + label.getOffsetBottom();\n\t\t\t\t\t\t\tlabel.y = pos.y + label.getOffsetBottom();\n\t\t\t\t\t\t\tlabel.rotate(180 - angle, pos);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}.bind(this));\n\t\t\t\n\t\t\tthis.children.each(function(value) {\n\t\t\t\tif(value instanceof ORYX.Core.Node) {\n\t\t\t\t\tthis.calculatePositionOfAttachedChildNode.call(this, value);\n\t\t\t\t}\n\t\t\t}.bind(this));\n\t\t\t\n\t\t\tthis.refreshAttachedNodes();\n\t\t\tthis.refresh();\n\t\t\t\n\t\t\tthis.isChanged = false;\n\t\t\tthis._dockerUpdated = false;\n\t\t\t\n\t\t\tthis._oldBounds = this.bounds.clone();\n        }\n\t\t\n\t\t\n  \t    // IE10 specific fix, start and end-markes get left behind when moving path\n\t\tvar userAgent = navigator.userAgent;\n\t\tif (navigator.appVersion.indexOf(\"MSIE 10\") !== -1 || (userAgent.indexOf('Trident') !== -1 && userAgent.indexOf('rv:11') !== -1)) \n\t\t{\n\t\t\tthis.node.parentNode.insertBefore(this.node, this.node);\n\t\t}\n    },\n\t\n\t/**\n\t *  Moves a point to the upperLeft of a node's bounds.\n\t *  \n\t *  @param {point} point\n\t *  \tThe point to move\n\t *  @param {ORYX.Core.Bounds} bounds\n\t *  \tThe Bounds of the related noe\n\t */\n\tmovePointToUpperLeftOfNode: function(point, bounds) {\n\t\tpoint.x -= bounds.width()/2;\n\t\tpoint.y -= bounds.height()/2;\n\t},\n\t\n\t/**\n\t * Refreshes the visual representation of edge's attached nodes.\n\t */\t\n\trefreshAttachedNodes: function() {\n\t\tthis.attachedNodePositionData.values().each(function(nodeData) {\n\t\t\tvar startPoint = nodeData.segment.docker1.bounds.center();\n\t\t\tvar endPoint = nodeData.segment.docker2.bounds.center();\n\t\t\tthis.relativizePoint(startPoint);\n\t\t\tthis.relativizePoint(endPoint);\n\t\t\t\n\t\t\tvar newNodePosition = new Object();\n\t\t\t\n\t\t\t/* Calculate new x-coordinate */\n\t\t\tnewNodePosition.x = startPoint.x \n\t\t\t\t\t\t\t\t+ nodeData.relativDistanceFromDocker1\n\t\t\t\t\t\t\t\t\t* (endPoint.x - startPoint.x);\n\t\t\t\n\t\t\t/* Calculate new y-coordinate */\n\t\t\tnewNodePosition.y = startPoint.y \n\t\t\t\t\t\t\t\t+ nodeData.relativDistanceFromDocker1\n\t\t\t\t\t\t\t\t\t* (endPoint.y - startPoint.y);\n\t\t\t\n\t\t\t/* Convert new position to the upper left of the node */\n\t\t\tthis.movePointToUpperLeftOfNode(newNodePosition, nodeData.node.bounds);\n\t\t\t\n\t\t\t/* Move node to its new position */\n\t\t\tnodeData.node.bounds.moveTo(newNodePosition);\n\t\t\tnodeData.node._update();\t\t\t\t\t\n\t\t\t\n\t\t}.bind(this));\n\t},\n\t\n\t/**\n\t * Calculates the position of an edge's child node. The node is placed on \n\t * the path of the edge.\n\t * \n\t * @param {node}\n\t * \t\tThe node to calculate the new position\n\t * @return {Point}\n\t * \t\tThe calculated upper left point of the node's shape.\n\t */\n\tcalculatePositionOfAttachedChildNode: function(node) {\n\t\t/* Initialize position */\n\t\tvar position = new Object();\n\t\tposition.x = 0;\n\t\tposition.y = 0;\n\t\t\n\t\t/* Case: Node was just added */\n\t\tif(!this.attachedNodePositionData[node.getId()]) {\n\t\t\tthis.attachedNodePositionData[node.getId()] = new Object();\n\t\t\tthis.attachedNodePositionData[node.getId()]\n\t\t\t\t\t.relativDistanceFromDocker1 = 0;\n\t\t\tthis.attachedNodePositionData[node.getId()].node = node;\n\t\t\tthis.attachedNodePositionData[node.getId()].segment = new Object();\n\t\t\tthis.findEdgeSegmentForNode(node);\n\t\t}else if(node.isChanged) {\n\t\t\tthis.findEdgeSegmentForNode(node);\n\t\t}\n\t\t\n\t\t\n\t\t\n\t},\n\t\n\t/**\n\t * Finds the appropriate edge segement for a node.\n\t * The segment is choosen, which has the smallest distance to the node.\n\t * \n\t * @param {ORYX.Core.Node} node\n\t * \t\tThe concerning node\n\t */\n\tfindEdgeSegmentForNode: function(node) {\n\t\tvar length = this.dockers.length;\n\t\tvar smallestDistance = undefined;\n\t\t\n\t\tfor(i=1;i<length;i++) {\n\t\t\tvar lineP1 = this.dockers[i-1].bounds.center();\n\t\t\tvar lineP2 = this.dockers[i].bounds.center();\n\t\t\tthis.relativizePoint(lineP1);\n\t\t\tthis.relativizePoint(lineP2);\n\t\t\t\n\t\t\tvar nodeCenterPoint = node.bounds.center();\n\t\t\tvar distance = ORYX.Core.Math.distancePointLinie(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tlineP1,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tlineP2, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnodeCenterPoint, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttrue);\n\t\t\t\n\t\t\tif((distance || distance == 0) && ((!smallestDistance && smallestDistance != 0) \n\t\t\t\t\t\t|| distance < smallestDistance)) {\n\t\t\t\t\n\t\t\t\tsmallestDistance = distance;\n\t\t\t\t\n\t\t\t\tthis.attachedNodePositionData[node.getId()].segment.docker1 = \n\t\t\t\t\t\t\t\t\t\t\t\t\tthis.dockers[i-1];\n\t\t\t\tthis.attachedNodePositionData[node.getId()].segment.docker2 = \n\t\t\t\t\t\t\t\t\t\t\t\t\tthis.dockers[i];\n\t\n\t\t\t}\n\t\t\t\n\t\t\t/* Either the distance does not match the segment or the distance\n\t\t\t * between docker1 and docker2 is 0\n\t\t\t * \n\t\t\t * In this case choose the nearest docker as attaching point.\n\t\t\t * \n\t\t\t */\n\t\t\tif(!distance && !smallestDistance && smallestDistance != 0) {\n\t\t\t\t(ORYX.Core.Math.getDistancePointToPoint(nodeCenterPoint, lineP1)\n\t\t\t\t\t< ORYX.Core.Math.getDistancePointToPoint(nodeCenterPoint, lineP2)) ?\n\t\t\t\t\tthis.attachedNodePositionData[node.getId()].relativDistanceFromDocker1 = 0 :\n\t\t\t\t\tthis.attachedNodePositionData[node.getId()].relativDistanceFromDocker1 = 1;\n\t\t\t\tthis.attachedNodePositionData[node.getId()].segment.docker1 = \n\t\t\t\t\t\t\t\t\t\t\t\t\tthis.dockers[i-1];\n\t\t\t\tthis.attachedNodePositionData[node.getId()].segment.docker2 = \n\t\t\t\t\t\t\t\t\t\t\t\t\tthis.dockers[i];\n\t\t\t}\n\t\t}\n\t\t\n\t\t/* Calculate position on edge segment for the node */\n\t\tif(smallestDistance || smallestDistance == 0) {\n\t\t\tthis.attachedNodePositionData[node.getId()].relativDistanceFromDocker1 =\n\t\t\tthis.getLineParameterForPosition(\n\t\t\t\t\tthis.attachedNodePositionData[node.getId()].segment.docker1,\n\t\t\t\t\tthis.attachedNodePositionData[node.getId()].segment.docker2,\n\t\t\t\t\tnode);\n\t\t}\n\t},\n\t\n\t\n\t/**\n\t *\n\t * @param {ORYX.Core.Node|Object} node or position\n\t * @return {Object} An object with the following attribute: {ORYX.Core.Docker} fromDocker, {ORYX.Core.Docker} toDocker, {X/Y} position, {int} distance\n\t */\n \tfindSegment: function(node){\n\t\t\n\t\tvar length = this.dockers.length;\n\t\tvar result;\n\t\t\n\t\tvar nodeCenterPoint = node instanceof ORYX.Core.UIObject ? node.bounds.center() : node;\n\t\t\t\n\t\tfor (i = 1; i < length; i++) {\n\t\t\tvar lineP1 = this.dockers[i - 1].bounds.center();\n\t\t\tvar lineP2 = this.dockers[i].bounds.center();\n\t\t\t\n\t\t\tvar distance = ORYX.Core.Math.distancePointLinie(lineP1, lineP2, nodeCenterPoint, true);\n\t\t\t\n\t\t\tif (typeof distance == \"number\" && (result === undefined || distance < result.distance)) {\n\t\t\t\tresult = {\n\t\t\t\t\tdistance: distance,\n\t\t\t\t\tfromDocker: this.dockers[i - 1],\n\t\t\t\t\ttoDocker: this.dockers[i]\n\t\t\t\t}\n\t\t\t\t\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t},\n\t\n\t/**\n\t * Returns the value of the scalar to determine the position of the node on \n\t * line defined by docker1 and docker2.\n\t * \n\t * @param {point} docker1\n\t * \t\tThe docker that defines the start of the line segment\n\t * @param {point} docker2\n\t * \t\tThe docker that defines the end of the line segment\n\t * @param {ORYX.Core.Node} node\n\t * \t\tThe concerning node\n\t * \n\t * @return {float} positionParameter\n\t * \t\tThe scalar value to determine the position on the line\n\t */\n\tgetLineParameterForPosition: function(docker1, docker2, node) {\n\t\tvar dockerPoint1 = docker1.bounds.center();\n\t\tvar dockerPoint2 = docker2.bounds.center();\n\t\tthis.relativizePoint(dockerPoint1);\n\t\tthis.relativizePoint(dockerPoint2);\n\t\t\n\t\tvar intersectionPoint = ORYX.Core.Math.getPointOfIntersectionPointLine(\n\t\t\t\t\t\t\t\t\tdockerPoint1,\n\t\t\t\t\t\t\t\t\tdockerPoint2,\n\t\t\t\t\t\t\t\t\tnode.bounds.center(), true);\n\t\tif(!intersectionPoint) {\n\t\t\treturn 0;\n\t\t}\n\t\t\n\t\tvar relativeDistance = \n\t\t\tORYX.Core.Math.getDistancePointToPoint(intersectionPoint, dockerPoint1) /\n\t\t\tORYX.Core.Math.getDistancePointToPoint(dockerPoint1, dockerPoint2);\n\t\t\n\t\treturn relativeDistance;\n\t},\n\t/**\n\t * Makes point relative to the upper left of the edge's bound.\n\t * \n\t * @param {point} point\n\t * \t\tThe point to relativize\n\t */\n\trelativizePoint: function(point) {\n\t\tpoint.x -= this.bounds.upperLeft().x;\n\t\tpoint.y -= this.bounds.upperLeft().y;\t\t\n\t},\n\t\n\t/**\n\t * Move the first and last docker and calls the refresh method.\n\t * Attention: This does not calculates intersection point between the\n\t * edge and the bounded nodes. This only works if only the nodes are\n\t * moves.\n\t *\n\t */\n\toptimizedUpdate: function(){\n\t\t\n\t\tvar updateDocker = function(docker){\n\t\t\tif (!docker._dockedShape || !docker._dockedShapeBounds)\n\t\t\t\treturn;\n\t\t\tvar off = {\n\t\t\t    x: docker._dockedShape.bounds.a.x - docker._dockedShapeBounds.a.x,\n\t\t\t    y: docker._dockedShape.bounds.a.y - docker._dockedShapeBounds.a.y\n\t\t\t};\n\t\t\tdocker.bounds.moveBy(off);\n\t\t\tdocker._dockedShapeBounds.moveBy(off);\n\t\t}\n\t\t\n\t\tupdateDocker(this.dockers.first());\n\t\tupdateDocker(this.dockers.last());\n\t\t\n\t\tthis.refresh();\n\t},\n    \n    refresh: function(){\n        //call base class refresh method\n        arguments.callee.$.refresh.apply(this, arguments);\n        \n        //TODO consider points for marker mids\n        var lastPoint;\n        this._paths.each((function(path, index){\n            var dockers = this._dockersByPath[path.id];\n            var c = undefined;\n\t\t\tvar d = undefined;\n            if (lastPoint) {\n                d = \"M\" + lastPoint.x + \" \" + lastPoint.y;\n            }\n            else {\n                c = dockers[0].bounds.center();\n                lastPoint = c;\n                \n                d = \"M\" + c.x + \" \" + c.y;\n            }\n            \n            for (var i = 1; i < dockers.length; i++) {\n                // for each docker, draw a line to the center\n                c = dockers[i].bounds.center();\n                d = d + \"L\" + c.x + \" \" + c.y + \" \";\n                lastPoint = c;\n            }\n            \n            path.setAttributeNS(null, \"d\", d);\n            this._interactionPaths[index].setAttributeNS(null, \"d\", d);\n            \n        }).bind(this));\n\t\t\n\t\t\n\t\t/* move child shapes of an edge */\n\t\tif(this.getChildNodes().length > 0) {\n\t        var x = this.bounds.upperLeft().x;\n\t        var y = this.bounds.upperLeft().y;\n\t        \n\t\t\tthis.node.firstChild.childNodes[1].setAttributeNS(null, \"transform\", \"translate(\" + x + \", \" + y + \")\");\n\t\t}\n\t\t\n    },\n    \n    /**\n     * Calculate the Border Intersection Point between two points\n     * @param {PointA}\n     * @param {PointB}\n     */\n    getIntersectionPoint: function(){\n    \n        var length = Math.floor(this.dockers.length / 2)\n        \n        return ORYX.Core.Math.midPoint(this.dockers[length - 1].bounds.center(), this.dockers[length].bounds.center())\n    },\n    \n\t/**\n     * Returns TRUE if the bounds is over the edge\n     * @param {Bounds}\n     *\n     */\n    isBoundsIncluded: function(bounds){\n\t\tvar dockers = this.dockers, size = dockers.length;\n\t\treturn dockers.any(function(docker, i){\n\t\t\tif (i == size-1){ return false; }\n\t\t\tvar a = docker.bounds.center();\n\t\t\tvar b = dockers[i+1].bounds.center();\n\t\t\t\n\t\t\treturn ORYX.Core.Math.isRectOverLine(a.x, a.y, b.x, b.y, bounds.a.x, bounds.a.y, bounds.b.x, bounds.b.y);\n\t\t});\n\t},\n    \n    /**\n     * Calculate if the point is inside the Shape\n     * @param {PointX}\n     * @param {PointY} \n     */\n    isPointIncluded: function(pointX, pointY){\n    \n        var isbetweenAB = this.absoluteBounds().isIncluded(pointX, pointY, \n\t\t\t\t\t\t\t\t\t\t\t\tORYX.CONFIG.OFFSET_EDGE_BOUNDS);\n        \n\t\tvar isPointIncluded = undefined;\n\t\t\n        if (isbetweenAB && this.dockers.length > 0) {\n\t\t\n\t\t\tvar i = 0;\n\t\t\tvar point1, point2;\n\t\t\t\n\t\t\t\n\t\t\tdo {\n\t\t\t\n\t\t\t\tpoint1 = this.dockers[i].bounds.center();\n\t\t\t\tpoint2 = this.dockers[++i].bounds.center();\n\t\t\t\t\n\t\t\t\tisPointIncluded = ORYX.Core.Math.isPointInLine(pointX, pointY, \n\t\t\t\t\t\t\t\t\t\t\tpoint1.x, point1.y, \n\t\t\t\t\t\t\t\t\t\t\tpoint2.x, point2.y, \n\t\t\t\t\t\t\t\t\t\t\tORYX.CONFIG.OFFSET_EDGE_BOUNDS);\n\t\t\t\t\n\t\t\t} while (!isPointIncluded && i < this.dockers.length - 1)\n\t\t\t\n\t\t}\n\t\t\n\t\treturn isPointIncluded;\n\n    },\n  \n    \n    /**\n     * Calculate if the point is over an special offset area\n     * @param {Point}\n     */\n    isPointOverOffset: function(){\n\t\treturn  false\n\t},\n\t\n\t/**\n\t * Returns TRUE if the given node\n\t * is a child node of the shapes node\n\t * @param {Element} node\n\t * @return {Boolean}\n\t *\n\t */\n\tcontainsNode: function(node){\n\t\tif (this._paths.include(node) || \n       \t\tthis._interactionPaths.include(node)){\n\t\t\treturn true;\t\t\n\t\t}\t\n\t\treturn false;\n\t},\n\t\n\t/**\n\t* Returns the angle of the line between two dockers\n\t* (0 - 359.99999999)\n\t*/\n\t_getAngle: function(docker1, docker2) {\n\t\tvar p1 = docker1 instanceof ORYX.Core.Controls.Docker ? docker1.absoluteCenterXY() : docker1;\n\t\tvar p2 = docker2 instanceof ORYX.Core.Controls.Docker ? docker2.absoluteCenterXY() : docker2;\n\t\t\n\t\treturn ORYX.Core.Math.getAngle(p1, p2);\n\t},\n\t    \n    alignDockers: function(){\n        this._update(true);\n        \n        var firstPoint = this.dockers.first().bounds.center();\n        var lastPoint = this.dockers.last().bounds.center();\n        \n        var deltaX = lastPoint.x - firstPoint.x;\n        var deltaY = lastPoint.y - firstPoint.y;\n        \n        var numOfDockers = this.dockers.length - 1;\n        \n        this.dockers.each((function(docker, index){\n            var part = index / numOfDockers;\n            docker.bounds.unregisterCallback(this._dockerChangedCallback);\n            docker.bounds.moveTo(firstPoint.x + part * deltaX, firstPoint.y + part * deltaY);\n            docker.bounds.registerCallback(this._dockerChangedCallback);\n        }).bind(this));\n        \n        this._dockerChanged();\n    },\n    \n\tadd: function(shape){\n        arguments.callee.$.add.apply(this, arguments);\n\t\t\n\t\t// If the new shape is a Docker which is not contained\n\t\tif (shape instanceof ORYX.Core.Controls.Docker && this.dockers.include(shape)){\n\t\t\t// Add it to the dockers list ordered by paths\t\t\n\t\t\tvar pathArray = this._dockersByPath.values()[0];\n\t\t\tif (pathArray) {\n\t\t\t\tpathArray.splice(this.dockers.indexOf(shape), 0, shape);\n\t\t\t}\n\t\t\t\n\t\t\t/* Perform nessary adjustments on the edge's child shapes */\n\t\t\tthis.handleChildShapesAfterAddDocker(shape);\n\t\t}\n\t},\n\t\n\t/**\n\t * Performs nessary adjustments on the edge's child shapes.\n\t * \n\t * @param {ORYX.Core.Controls.Docker} docker\n\t * \t\tThe added docker\n\t */\n\thandleChildShapesAfterAddDocker: function(docker) {\n\t\t/* Ensure type of Docker */\n\t\tif(!docker instanceof ORYX.Core.Controls.Docker) {return undefined;}\n\t\t\n\t\tvar index = this.dockers.indexOf(docker);\n\t\tif(!(0 < index && index < this.dockers.length - 1)) {\n\t\t/* Exception: Expect added docker between first and last node of the edge */\n\t\t\treturn undefined;\n\t\t} \n\t\t\t\n\t\t/* Get child nodes concerning the segment of the new docker */\n\t\tvar startDocker = this.dockers[index-1];\n\t\tvar endDocker = this.dockers[index+1];\n\t\t\n\t\t/* Adjust the position of edge's child nodes */\n\t\tvar segmentElements = \n\t\t\tthis.getAttachedNodePositionDataForSegment(startDocker, endDocker);\n\t\t\n\t\tvar lengthSegmentPart1 = ORYX.Core.Math.getDistancePointToPoint(\n\t\t\t\t\t\t\t\t\t\tstartDocker.bounds.center(),\n\t\t\t\t\t\t\t\t\t\tdocker.bounds.center());\n\t\tvar lengthSegmentPart2 = ORYX.Core.Math.getDistancePointToPoint(\n\t\t\t\t\t\t\t\t\t\tendDocker.bounds.center(),\n\t\t\t\t\t\t\t\t\t\tdocker.bounds.center());\n\t\t\t\t\t\t\t\t\t\t\n\t\tif(!(lengthSegmentPart1 + lengthSegmentPart2)) {return;}\n\t\t\n\t\tvar relativDockerPosition = lengthSegmentPart1 / (lengthSegmentPart1 + lengthSegmentPart2);\n\t\t\t\n\t\tsegmentElements.each(function(nodePositionData) {\n\t\t\t/* Assign child node to the new segment */\n\t\t\tif(nodePositionData.value.relativDistanceFromDocker1 < relativDockerPosition) {\n\t\t\t\t/* Case: before added Docker */\n\t\t\t\tnodePositionData.value.segment.docker2 = docker;\n\t\t\t\tnodePositionData.value.relativDistanceFromDocker1 = \n\t\t\t\t\tnodePositionData.value.relativDistanceFromDocker1 / relativDockerPosition;\n\t\t\t} else {\n\t\t\t\t/* Case: after added Docker */\n\t\t\t\tnodePositionData.value.segment.docker1 = docker;\n\t\t\t\tvar newFullDistance = 1 - relativDockerPosition;\n\t\t\t\tvar relativPartOfSegment = \n\t\t\t\t\t\t\tnodePositionData.value.relativDistanceFromDocker1\n\t\t\t\t\t\t\t- relativDockerPosition;\n\t\t\t\t\n\t\t\t\tnodePositionData.value.relativDistanceFromDocker1 = \n\t\t\t\t\t\t\t\t\t\trelativPartOfSegment / newFullDistance;\n\t\t\t\t\n\t\t\t}\n\t\t})\n\t\t\n\t\t\n\t\t// Update all labels reference points\n\t\tthis.getLabels().each(function(label){\n\n\t\t\tvar ref = label.getReferencePoint();\n\t\t\tif (!ref) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar index = this.dockers.indexOf(docker);\n\t\t\tif (index >= ref.segment.fromIndex && index <= ref.segment.toIndex){\n\t\t\t\t\n\t\t\t\tvar segment = this.findSegment(ref.intersection);\n\t\t\t\tif (!segment){ \n\t\t\t\t\t// Choose whether the first of the last segment\n\t\t\t\t\tsegment.fromDocker = ref.segment.fromIndex >= (this.dockers.length/2) ? this.dockers[0] : this.dockers[this.dockers.length-2]; \n\t\t\t\t\tsegment.toDocker = this.dockers[this.dockers.indexOf(from)+1]; // The next one if the to docker\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tvar fromPosition = segment.fromDocker.bounds.center(), toPosition = segment.toDocker.bounds.center();\n\t\t\t\n\t\t\t\tvar intersection = ORYX.Core.Math.getPointOfIntersectionPointLine(\n\t\t\t\t\t\t\t\t\t\tfromPosition, \t\t// P1 - Center of the first docker\n\t\t\t\t\t\t\t\t\t\ttoPosition, \t\t// P2 - Center of the second docker\n\t\t\t\t\t\t\t\t\t\tref.intersection, \t// P3 - Center of the label\n\t\t\t\t\t\t\t\t\t\ttrue);\n\t\t\t\t//var oldDistance = ORYX.Core.Math.getDistanceBetweenTwoPoints(ref.segment.fromPosition, ref.segment.toPosition, ref.intersection);\n\t\t\t\t//intersection = ORYX.Core.Math.getPointBetweenTwoPoints(fromPosition, toPosition, isNaN(oldDistance) ? 0.5 : (lengthOld*oldDistance)/lengthNew);\n\t\t\t\t\t\n\t\t\t\t// Update the reference point\n\t\t\t\tthis.updateReferencePointOfLabel(label, intersection, segment.fromDocker, segment.toDocker, true);\n\t\t\t}\n\t\t}.bind(this));\n\t\t\n\t\t/* Update attached nodes visual representation */\n\t\tthis.refreshAttachedNodes();\n\t},\n\t\n\t/**\n\t *\tReturns elements from {@link attachedNodePositiondata} that match the\n\t *  segement defined by startDocker and endDocker.\n\t *  \n\t *  @param {ORYX.Core.Controls.Docker} startDocker\n\t *  \tThe docker defining the begin of the segment.\n\t *  @param {ORYX.Core.Controls.Docker} endDocker\n\t *  \tThe docker defining the begin of the segment.\n\t *  \n\t *  @return {Hash} attachedNodePositionData\n\t *  \tChild elements matching the segment\n\t */\n\tgetAttachedNodePositionDataForSegment: function(startDocker, endDocker) {\n\t\t/* Ensure that the segment is defined correctly */\n\t\tif(!((startDocker instanceof ORYX.Core.Controls.Docker) \n\t\t\t&& (endDocker instanceof ORYX.Core.Controls.Docker))) {\n\t\t\t\treturn [];\n\t\t\t}\n\t\t\t\n\t\t/* Get elements of the segment */\n\t\tvar elementsOfSegment = \n\t\t\tthis.attachedNodePositionData.findAll(function(nodePositionData) {\n\t\t\t\treturn nodePositionData.value.segment.docker1 === startDocker &&\n\t\t\t\t\t\tnodePositionData.value.segment.docker2 === endDocker;\n\t\t\t});\n\t\t\n\t\t/* Return a Hash in each case */\n\t\tif(!elementsOfSegment) {return [];}\n\t\t\n\t\treturn elementsOfSegment;\n\t},\n\t\n\t/**\n\t * Removes an edge's child shape\n\t */\n\tremove: function(shape) {\n\t\targuments.callee.$.remove.apply(this, arguments);\n\t\t\n\t\tif(this.attachedNodePositionData[shape.getId()]) {\n\t\t\tdelete this.attachedNodePositionData[shape.getId()];\n\t\t}\n\t\t\n\t\t/* Adjust child shapes if neccessary */\n\t\tif(shape instanceof ORYX.Core.Controls.Docker) {\n\t\t\tthis.handleChildShapesAfterRemoveDocker(shape);\n\t\t}\n\t},\n\t\n\tupdateReferencePointOfLabel: function(label, intersection, from, to, dirty){\n\t\tif (!label.getReferencePoint() || !label.isVisible) {\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tvar ref = label.getReferencePoint();\n\t\t\n\t\t//\n\t\tif (ref.orientation && ref.orientation !== \"ce\"){\n\t\t\tvar angle = this._getAngle(from, to);\n\t\t\tif (ref.distance >= 0){\n\t\t\t\tif(angle == 0){\n\t\t\t\t\tlabel.horizontalAlign(\"left\");//ref.orientation == \"lr\" ? \"right\" : \"left\");\n\t\t\t\t\tlabel.verticalAlign(\"bottom\");\n\t\t\t\t} else if (angle > 0 && angle < 90){\n\t\t\t\t\tlabel.horizontalAlign(\"right\");\n\t\t\t\t\tlabel.verticalAlign(\"bottom\");\n\t\t\t\t} else if (angle == 90){\n\t\t\t\t\tlabel.horizontalAlign(\"right\");\n\t\t\t\t\tlabel.verticalAlign(\"top\");//ref.orientation == \"lr\" ? \"bottom\" : \"top\");\n\t\t\t\t} else if (angle > 90 && angle < 180){\n\t\t\t\t\tlabel.horizontalAlign(\"right\");\n\t\t\t\t\tlabel.verticalAlign(\"top\");\n\t\t\t\t} else if (angle == 180){\n\t\t\t\t\tlabel.horizontalAlign(\"left\");//ref.orientation == \"ur\" ? \"right\" : \"left\");\n\t\t\t\t\tlabel.verticalAlign(\"top\");\n\t\t\t\t} else if (angle > 180 && angle < 270){\n\t\t\t\t\tlabel.horizontalAlign(\"left\");\n\t\t\t\t\tlabel.verticalAlign(\"top\");\t\t\t\t\n\t\t\t\t} else if (angle == 270){\n\t\t\t\t\tlabel.horizontalAlign(\"left\");\n\t\t\t\t\tlabel.verticalAlign(\"top\");//ref.orientation == \"ll\" ? \"bottom\" : \"top\");\n\t\t\t\t} else if (angle > 270 && angle <= 360){\n\t\t\t\t\tlabel.horizontalAlign(\"left\");\n\t\t\t\t\tlabel.verticalAlign(\"bottom\");\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif(angle == 0){\n\t\t\t\t\tlabel.horizontalAlign(\"left\");//ref.orientation == \"ur\" ? \"right\" : \"left\");\n\t\t\t\t\tlabel.verticalAlign(\"top\");\n\t\t\t\t} else if (angle > 0 && angle < 90){\n\t\t\t\t\tlabel.horizontalAlign(\"left\");\n\t\t\t\t\tlabel.verticalAlign(\"top\");\n\t\t\t\t} else if (angle == 90){\n\t\t\t\t\tlabel.horizontalAlign(\"left\");\n\t\t\t\t\tlabel.verticalAlign(\"top\");//ref.orientation == \"ll\" ? \"bottom\" : \"top\");\n\t\t\t\t} else if (angle > 90 && angle < 180){\n\t\t\t\t\tlabel.horizontalAlign(\"left\");\n\t\t\t\t\tlabel.verticalAlign(\"bottom\");\n\t\t\t\t} else if (angle == 180){\n\t\t\t\t\tlabel.horizontalAlign(\"left\");//ref.orientation == \"lr\" ? \"right\" : \"left\");\n\t\t\t\t\tlabel.verticalAlign(\"bottom\");\n\t\t\t\t} else if (angle > 180 && angle < 270){\n\t\t\t\t\tlabel.horizontalAlign(\"right\");\n\t\t\t\t\tlabel.verticalAlign(\"bottom\");\n\t\t\t\t} else if (angle == 270){\n\t\t\t\t\tlabel.horizontalAlign(\"right\");\n\t\t\t\t\tlabel.verticalAlign(\"top\");//ref.orientation == \"lr\" ? \"bottom\" : \"top\");\n\t\t\t\t} else if (angle > 270 && angle <= 360){\n\t\t\t\t\tlabel.horizontalAlign(\"right\");\n\t\t\t\t\tlabel.verticalAlign(\"top\");\n\t\t\t\t}\t\t\t\n\t\t\t}\n\t\t\tref.iorientation = ref.iorientation || ref.orientation;\n\t\t\tref.orientation = (label.verticalAlign()==\"top\"?\"u\":\"l\") + (label.horizontalAlign()==\"left\"?\"l\":\"r\");\n\t\t}\n\t\n\t\tlabel.setReferencePoint(jQuery.extend({},{\n\t\t\t\tintersection: intersection,\n\t\t\t\tsegment: {\n\t\t\t\t\tfrom: from,\n\t\t\t\t\tfromIndex: this.dockers.indexOf(from),\n\t\t\t\t\tfromPosition: from.bounds.center(),\n\t\t\t\t\tto: to,\n\t\t\t\t\ttoIndex: this.dockers.indexOf(to),\n\t\t\t\t\ttoPosition: to.bounds.center()\n\t\t\t\t},\n\t\t\t\tdirty: dirty || false\n\t\t\t},ref))\n\t},\n\t/**\n\t * \tAdjusts the child shapes of an edges after a docker was removed.\n\t * \t\n\t *  @param{ORYX.Core.Controls.Docker} docker\n\t *  \tThe removed docker.\n\t */\n\thandleChildShapesAfterRemoveDocker: function(docker) {\n\t\t/* Ensure docker type */\n\t\tif(!(docker instanceof ORYX.Core.Controls.Docker)) {return;}\n\t\t\n\t\tthis.attachedNodePositionData.each(function(nodePositionData) {\n\t\t\tif(nodePositionData.value.segment.docker1 === docker) {\n\t\t\t\t/* The new start of the segment is the predecessor of docker2. */\n\t\t\t\tvar index = this.dockers.indexOf(nodePositionData.value.segment.docker2);\n\t\t\t\tif(index == -1) {return;}\n\t\t\t\tnodePositionData.value.segment.docker1 = this.dockers[index - 1];\n\t\t\t} \n\t\t\telse if(nodePositionData.value.segment.docker2 === docker) {\n\t\t\t\t/* The new end of the segment is the successor of docker1. */\n\t\t\t\tvar index = this.dockers.indexOf(nodePositionData.value.segment.docker1);\n\t\t\t\tif(index == -1) {return;}\n\t\t\t\tnodePositionData.value.segment.docker2 = this.dockers[index + 1];\n\t\t\t}\n\t\t}.bind(this));\n\t\t\n\t\t// Update all labels reference points\n\t\tthis.getLabels().each(function(label){\n\n\t\t\tvar ref = label.getReferencePoint();\n\t\t\tif (!ref) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar from = ref.segment.from;\n\t\t\tvar to = ref.segment.to;\n\t\t\t\n\t\t\tif (from !== docker && to !== docker){ \n\t\t\t\treturn; \n\t\t\t}\n\t\t\t\n\t\t\tvar segment = this.findSegment(ref.intersection);\n\t\t\tif (!segment){ \n\t\t\t\tfrom = segment.fromDocker;\n\t\t\t\tto = segment.toDocker;\n\t\t\t} else {\n\t\t\t\tfrom = from === docker ? this.dockers[this.dockers.indexOf(to)-1] : from;\n\t\t\t\tto = this.dockers[this.dockers.indexOf(from)+1];\n\t\t\t}\n\n\t\t\tvar intersection = ORYX.Core.Math.getPointOfIntersectionPointLine(from.bounds.center(), to.bounds.center(), ref.intersection, true);\t\t\t\n\t\t\t// Update the reference point\n\t\t\tthis.updateReferencePointOfLabel(label, intersection, from, to, true);\n\t\t}.bind(this));\n\t\t\n\t\t/* Update attached nodes visual representation */\n\t\tthis.refreshAttachedNodes();\n\t},\n\t\n\t/**\n     *@deprecated Use the .createDocker() Method and set the point via the bounds\n     */\n    addDocker: function(position, exDocker){\n        var lastDocker;\n\t\tvar result;\n        this._dockersByPath.any((function(pair){\n            return pair.value.any((function(docker, index){\n                if (!lastDocker) {\n                    lastDocker = docker;\n                    return false;\n                }\n                else {\n                    var point1 = lastDocker.bounds.center();\n                    var point2 = docker.bounds.center();\n                    \n                    var additionalIEZoom = 1;\n                    if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) {\n                        var ua = navigator.userAgent;\n                        if (ua.indexOf('MSIE') >= 0) {\n                            //IE 10 and below\n                            var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100);\n                            if (zoom !== 100) {\n                                additionalIEZoom = zoom / 100\n                            }\n                        }\n                    }\n                    \n                    if (additionalIEZoom !== 1) {\n                        position.x = position.x / additionalIEZoom;\n                        position.y = position.y / additionalIEZoom;\n                    }\n                    \n                    if (ORYX.Core.Math.isPointInLine(position.x, position.y, point1.x, point1.y, point2.x, point2.y, 10)) {\n                        var path = this._paths.find(function(path){\n                            return path.id === pair.key;\n                        });\n                        if (path) {\n                            var allowAttr = path.getAttributeNS(NAMESPACE_ORYX, 'allowDockers');\n                            if (allowAttr && allowAttr.toLowerCase() === \"no\") {\n                                return true;\n                            }\n                        }\n                        \n                        var newDocker = (exDocker) ? exDocker : this.createDocker(this.dockers.indexOf(lastDocker) + 1, position);\n\t\t\t\t\t\tnewDocker.bounds.centerMoveTo(position);\n                        if(exDocker)\n\t\t\t\t\t\t\tthis.add(newDocker, this.dockers.indexOf(lastDocker) + 1);\n\t\t\t\t\t\tresult = newDocker;\n                        return true;\n                    }\n                    else {\n                        lastDocker = docker;\n                        return false;\n                    }\n                }\n            }).bind(this));\n        }).bind(this));\n\t\treturn result;\n    },\n    \n    removeDocker: function(docker){\n        if (this.dockers.length > 2 && !(this.dockers.first() === docker)) {\n            this._dockersByPath.any((function(pair){\n                if (pair.value.member(docker)) {\n                    if (docker === pair.value.last()) {\n                        return true;\n                    }\n                    else {\n                        this.remove(docker);\n                        this._dockersByPath[pair.key] = pair.value.without(docker);\n                        this.isChanged = true;\n                        this._dockerChanged();\n                        return true;\n                    }\n                }\n                return false;\n            }).bind(this));\n        }\n    },\n\t\n\t/**\n\t * Removes all dockers from the edge which are on \n\t * the line between two dockers\n\t * @return {Object} Removed dockers in an indicied array \n\t * (key is the removed position of the docker, value is docker themselve)\n\t */\n\tremoveUnusedDockers:function(){\n\t\tvar marked = $H({});\n\t\t\n\t\tthis.dockers.each(function(docker, i){\n\t\t\tif (i==0||i==this.dockers.length-1){ return }\n\t\t\tvar previous = this.dockers[i-1];\n\t\t\t\n\t\t\t/* Do not consider already removed dockers */\n\t\t\tif(marked.values().indexOf(previous) != -1 && this.dockers[i-2]) {\n\t\t\t\tprevious = this.dockers[i-2];\n\t\t\t}\n\t\t\tvar next = this.dockers[i+1];\n\t\t\t\n\t\t\tvar cp = previous.getDockedShape() && previous.referencePoint ? previous.getAbsoluteReferencePoint() : previous.bounds.center();\n\t\t\tvar cn = next.getDockedShape() && next.referencePoint ? next.getAbsoluteReferencePoint() : next.bounds.center();\n\t\t\tvar cd = docker.bounds.center();\n\t\t\t\n\t\t\tif (ORYX.Core.Math.isPointInLine(cd.x, cd.y, cp.x, cp.y, cn.x, cn.y, 1)){\n\t\t\t\tmarked[i] = docker;\n\t\t\t}\n\t\t}.bind(this))\n\t\t\n\t\tmarked.each(function(docker){\n\t\t\tthis.removeDocker(docker.value);\n\t\t}.bind(this))\n\t\t\n\t\tif (marked.values().length > 0){\n\t\t\tthis._update(true);\n\t\t}\n\t\t\n\t\treturn marked;\n\t},\n    \n    /**\n     * Initializes the Edge after loading the SVG representation of the edge.\n     * @param {SVGDocument} svgDocument\n     */\n    _init: function(svgDocument){\n        arguments.callee.$._init.apply(this, arguments);\n        \n        var minPointX, minPointY, maxPointX, maxPointY;\n        \n        //init markers\n        var defs = svgDocument.getElementsByTagNameNS(NAMESPACE_SVG, \"defs\");\n        if (defs.length > 0) {\n            defs = defs[0];\n            var markerElements = $A(defs.getElementsByTagNameNS(NAMESPACE_SVG, \"marker\"));\n            var marker;\n            var me = this;\n            markerElements.each(function(markerElement){\n                try {\n                    marker = new ORYX.Core.SVG.SVGMarker(markerElement.cloneNode(true));\n                    me._markers[marker.id] = marker;\n                    var textElements = $A(marker.element.getElementsByTagNameNS(NAMESPACE_SVG, \"text\"));\n                    var label;\n                    textElements.each(function(textElement){\n                        label = new ORYX.Core.SVG.Label({\n                            textElement: textElement,\n\t\t\t\t\t\t\tshapeId: this.id\n                        });\n                        me._labels[label.id] = label;\n                    });\n                } \n                catch (e) {\n                }\n            });\n        }\n        \n        \n        var gs = svgDocument.getElementsByTagNameNS(NAMESPACE_SVG, \"g\");\n        if (gs.length <= 0) {\n            throw \"Edge: No g element found.\";\n        }\n        var g = gs[0];\n        \n        \n        g.setAttributeNS(null, \"id\", null);\n        \n        var isFirst = true;\n        \n        $A(g.childNodes).each((function(path, index){\n            if (ORYX.Editor.checkClassType(path, SVGPathElement)) {\n                path = path.cloneNode(false);\n                \n                var pathId = this.id + \"_\" + index;\n                path.setAttributeNS(null, \"id\", pathId);\n                this._paths.push(path);\n                \n                //check, if markers are set and update the id\n                var markersByThisPath = [];\n                var markerUrl = path.getAttributeNS(null, \"marker-start\");\n                \n                if (markerUrl && markerUrl !== \"\") {\n                    markerUrl = markerUrl.strip();\n                    markerUrl = markerUrl.replace(/^url\\(#/, '');\n                    \n                    var markerStartId = this.getValidMarkerId(markerUrl);\n                    path.setAttributeNS(null, \"marker-start\", \"url(#\" + markerStartId + \")\");\n                    \n                    markersByThisPath.push(this._markers[markerStartId]);\n                }\n                \n                markerUrl = path.getAttributeNS(null, \"marker-mid\");\n                \n                if (markerUrl && markerUrl !== \"\") {\n                    markerUrl = markerUrl.strip();\n                    markerUrl = markerUrl.replace(/^url\\(#/, '');\n                    var markerMidId = this.getValidMarkerId(markerUrl);\n                    path.setAttributeNS(null, \"marker-mid\", \"url(#\" + markerMidId + \")\");\n                    \n                    markersByThisPath.push(this._markers[markerMidId]);\n                }\n                \n                markerUrl = path.getAttributeNS(null, \"marker-end\");\n                \n                if (markerUrl && markerUrl !== \"\") {\n                    markerUrl = markerUrl.strip();\n                    \n                    var markerEndId = this.getValidMarkerId(markerUrl);\n                    path.setAttributeNS(null, \"marker-end\", \"url(#\" + markerEndId + \")\");\n                    \n                    markersByThisPath.push(this._markers[markerEndId]);\n                }\n                \n                this._markersByPath[pathId] = markersByThisPath;\n                \n                //init dockers\n                var parser = new PathParser();\n                var handler = new ORYX.Core.SVG.PointsPathHandler();\n                parser.setHandler(handler);\n                parser.parsePath(path);\n                \n                if (handler.points.length < 4) {\n                    throw \"Edge: Path has to have two or more points specified.\";\n                }\n                \n                this._dockersByPath[pathId] = [];\n                \n\t\t\t\tfor (var i = 0; i < handler.points.length; i += 2) {\n\t\t\t\t\t//handler.points.each((function(point, pIndex){\n\t\t\t\t\tvar x = handler.points[i];\n\t\t\t\t\tvar y = handler.points[i+1];\n\t\t\t\t\tif (isFirst || i > 0) {\n\t\t\t\t\t\tvar docker = new ORYX.Core.Controls.Docker({\n\t\t\t\t\t\t\teventHandlerCallback: this.eventHandlerCallback\n\t\t\t\t\t\t});\n\t\t\t\t\t\tdocker.bounds.centerMoveTo(x,y);\n\t\t\t\t\t\tdocker.bounds.registerCallback(this._dockerChangedCallback);\n\t\t\t\t\t\tthis.add(docker, this.dockers.length);\n\t\t\t\t\t\t\n\t\t\t\t\t\t//this._dockersByPath[pathId].push(docker);\n\t\t\t\t\t\t\n\t\t\t\t\t\t//calculate minPoint and maxPoint\n\t\t\t\t\t\tif (minPointX) {\n\t\t\t\t\t\t\tminPointX = Math.min(x, minPointX);\n\t\t\t\t\t\t\tminPointY = Math.min(y, minPointY);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tminPointX = x;\n\t\t\t\t\t\t\tminPointY = y;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (maxPointX) {\n\t\t\t\t\t\t\tmaxPointX = Math.max(x, maxPointX);\n\t\t\t\t\t\t\tmaxPointY = Math.max(y, maxPointY);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tmaxPointX = x;\n\t\t\t\t\t\t\tmaxPointY = y;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t//}).bind(this));\n\t\t\t\t}\n                isFirst = false;\n            }\n        }).bind(this));\n        \n        this.bounds.set(minPointX, minPointY, maxPointX, maxPointY);\n        \n        if (false&&(this.bounds.width() === 0 || this.bounds.height() === 0)) {\n\t\t\tvar width = this.bounds.width();\n\t\t\tvar height = this.bounds.height();\n\t\t\t\n            this.bounds.extend({\n                x: width === 0 ? 2 : 0,\n                y: height === 0 ? 2 : 0\n            });\n            \n            this.bounds.moveBy({\n                x: width === 0 ? -1 : 0,\n                y: height === 0 ? -1 : 0\n            });\n            \n        }\n        \n        this._oldBounds = this.bounds.clone();\n        \n        //add paths to this.node\n        this._paths.reverse();\n        var paths = [];\n        this._paths.each((function(path){\n            paths.push(this.node.childNodes[0].childNodes[0].childNodes[0].appendChild(path));\n        }).bind(this));\n        \n        this._paths = paths;\n        \n        //init interaction path\n        this._paths.each((function(path){\n            var iPath = path.cloneNode(false);\n\t\t\tiPath.setAttributeNS(null, \"id\", undefined);\n            iPath.setAttributeNS(null, \"stroke-width\", 10);\n            iPath.setAttributeNS(null, \"visibility\", \"hidden\");\n            iPath.setAttributeNS(null, \"stroke-dasharray\", null);\n            iPath.setAttributeNS(null, \"stroke\", \"black\");\n            iPath.setAttributeNS(null, \"fill\", \"none\");\n\t\t\tiPath.setAttributeNS(null, \"title\", this.getStencil().title());\n            this._interactionPaths.push(this.node.childNodes[0].childNodes[0].childNodes[0].appendChild(iPath));\n        }).bind(this));\n        \n        this._paths.reverse();\n        this._interactionPaths.reverse();\n\t\t\n\t\t/**initialize labels*/\n        var textElems = svgDocument.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'text');\n        \n\t\t$A(textElems).each((function(textElem){\n            var label = new ORYX.Core.SVG.Label({\n                textElement: textElem,\n\t\t\t\tshapeId: this.id\n            });\n            this.node.childNodes[0].childNodes[0].appendChild(label.node);\n            this._labels[label.id] = label;\n\t\t\t\n\t\t\tlabel.registerOnChange(this.layout.bind(this));\n        }).bind(this)); \n\t\t\n        \n        this.propertiesChanged.each(function(pair){\n            pair.value = true;\n        });\n        \n        \n        //if(this.dockers.length == 2) {\n        \t\n        \t\n        \t\n      //  }\n\t\t\n        //this._update(true);\n    },\n    \n    getValidMarkerId: function(markerUrl) {\n    \tif(markerUrl.indexOf(\"url(\\\"#\") >= 0) {\n            // Fix for IE9, additional quotes are added to the <id\n            var rawId = markerUrl.replace(/^url\\(\\\"#/, \"\").replace(/\\\"\\)$/, '');\n            return this.id + rawId;\n          } else {\n            markerUrl = markerUrl.replace(/^url\\(#/, '');\n            return this.id.concat(markerUrl.replace(/\\)$/, ''));\n          }\n    },\n    \n    /**\n     * Adds all necessary markers of this Edge to the SVG document.\n     * Has to be called, while this.node is part of DOM.\n     */\n    addMarkers: function(defs){\n        this._markers.each(function(marker){\n            if (!defs.ownerDocument.getElementById(marker.value.id)) {\n                marker.value.element = defs.appendChild(marker.value.element);\n            }\n        });\n    },\n    \n    /**\n     * Removes all necessary markers of this Edge from the SVG document.\n     * Has to be called, while this.node is part of DOM.\n     */\n    removeMarkers: function(){\n        var svgElement = this.node.ownerSVGElement;\n        if (svgElement) {\n            var defs = svgElement.getElementsByTagNameNS(NAMESPACE_SVG, \"defs\");\n            if (defs.length > 0) {\n                defs = defs[0];\n                this._markers.each(function(marker){\n                    var foundMarker = defs.ownerDocument.getElementById(marker.value.id);\n                    if (foundMarker) {\n                        marker.value.element = defs.removeChild(marker.value.element);\n                    }\n                });\n            }\n        }\n    },\n    \n    /**\n     * Calls when a docker has changed\n     */\n    _dockerChanged: function(){\n    \n        //this._update(true);\n\t\tthis._dockerUpdated = true;\n        \n    },\n    \n    serialize: function(){\n        var result = arguments.callee.$.serialize.apply(this);\n        \n        //add dockers triple\n        var value = \"\";\n        this._dockersByPath.each((function(pair){\n            pair.value.each(function(docker){\n                var position = docker.getDockedShape() && docker.referencePoint ? docker.referencePoint : docker.bounds.center();\n                value = value.concat(position.x + \" \" + position.y + \" \");\n            });\n            \n            value += \" # \";\n        }).bind(this));\n        result.push({\n            name: 'dockers',\n            prefix: 'oryx',\n            value: value,\n            type: 'literal'\n        });\n        \n        //add parent triple dependant on the dockedShapes\n        //TODO change this when canvas becomes a resource\n/*        var source = this.dockers.first().getDockedShape();\n        var target = this.dockers.last().getDockedShape();\n        var sharedParent;\n        if (source && target) {\n            //get shared parent\n            while (source.parent) {\n                source = source.parent;\n                if (source instanceof ORYX.Core.Canvas) {\n                    sharedParent = source;\n                    break;\n                }\n                else {\n                    var targetParent = target.parent;\n                    var found;\n                    while (targetParent) {\n                        if (source === targetParent) {\n                            sharedParent = source;\n                            found = true;\n                            break;\n                        }\n                        else {\n                            targetParent = targetParent.parent;\n                        }\n                    }\n                    if (found) {\n                        break;\n                    }\n                }\n            }\n        }\n        else \n            if (source) {\n                sharedParent = source.parent;\n            }\n            else \n                if (target) {\n                    sharedParent = target.parent;\n                }\n*/        \n        //if (sharedParent) {\n/*            result.push({\n                name: 'parent',\n                prefix: 'raziel',\n                //value: '#' + ERDF.__stripHashes(sharedParent.resourceId),\n                value: '#' + ERDF.__stripHashes(this.getCanvas().resourceId),\n                type: 'resource'\n            });*/\n        //}\n\t\t\n\t\t//serialize target and source\n\t\tvar lastDocker = this.dockers.last();\n\t\t\n\t\tvar target = lastDocker.getDockedShape();\n\t\t\n\t\tif(target) {\n\t\t\tresult.push({\n\t\t\t\tname: 'target',\n\t\t\t\tprefix: 'raziel',\n\t\t\t\tvalue: '#' + ERDF.__stripHashes(target.resourceId),\n\t\t\t\ttype: 'resource'\n\t\t\t});\n\t\t}\n        \n        try {\n            //result = this.getStencil().serialize(this, result);\n\t\t\tvar serializeEvent = this.getStencil().serialize();\n\t\t\t\n\t\t\t/*\n\t\t\t * call serialize callback by reference, result should be found\n\t\t\t * in serializeEvent.result\n\t\t\t */\n\t\t\tif(serializeEvent.type) {\n\t\t\t\tserializeEvent.shape = this;\n\t\t\t\tserializeEvent.data = result;\n\t\t\t\tserializeEvent.result = undefined;\n\t\t\t\tserializeEvent.forceExecution = true;\n\t\t\t\t\n\t\t\t\tthis._delegateEvent(serializeEvent);\n\t\t\t\t\n\t\t\t\tif(serializeEvent.result) {\n\t\t\t\t\tresult = serializeEvent.result;\n\t\t\t\t}\n\t\t\t}\n        } \n        catch (e) {\n        }\n        return result;\n    },\n    \n    deserialize: function(data){\n        try {\n            //data = this.getStencil().deserialize(this, data);\n\t\t\t\n\t\t\tvar deserializeEvent = this.getStencil().deserialize();\n\t\t\t\n\t\t\t/*\n\t\t\t * call serialize callback by reference, result should be found\n\t\t\t * in serializeEventInfo.result\n\t\t\t */\n\t\t\tif(deserializeEvent.type) {\n\t\t\t\tdeserializeEvent.shape = this;\n\t\t\t\tdeserializeEvent.data = data;\n\t\t\t\tdeserializeEvent.result = undefined;\n\t\t\t\tdeserializeEvent.forceExecution = true;\n\t\t\t\t\n\t\t\t\tthis._delegateEvent(deserializeEvent);\n\t\t\t\tif(deserializeEvent.result) {\n\t\t\t\t\tdata = deserializeEvent.result;\n\t\t\t\t}\n\t\t\t}\n        } \n        catch (e) {\n        }\n        \n\t\t// Set the outgoing shapes\n\t\tvar target = data.find(function(ser) {return (ser.prefix+\"-\"+ser.name) == 'raziel-target'});\n\t\tvar targetShape;\n\t\tif(target) {\n\t\t\ttargetShape = this.getCanvas().getChildShapeByResourceId(target.value);\n\t\t}\n\t\t\n\t\tvar outgoing = data.findAll(function(ser){ return (ser.prefix+\"-\"+ser.name) == 'raziel-outgoing'});\n\t\toutgoing.each((function(obj){\n\t\t\t// TODO: Look at Canvas\n\t\t\tif(!this.parent) {return};\n\t\t\t\t\t\t\t\t\n\t\t\t// Set outgoing Shape\n\t\t\tvar next = this.getCanvas().getChildShapeByResourceId(obj.value);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\tif(next){\n\t\t\t\tif(next == targetShape) {\n\t\t\t\t\t// If this is an edge, set the last docker to the next shape\n\t\t\t\t\tthis.dockers.last().setDockedShape(next);\n\t\t\t\t\tthis.dockers.last().setReferencePoint({x: next.bounds.width() / 2.0, y: next.bounds.height() / 2.0});\n\t\t\t\t} else if(next instanceof ORYX.Core.Edge) {\n\t\t\t\t\t//Set the first docker of the next shape\n\t\t\t\t\tnext.dockers.first().setDockedShape(this);\n\t\t\t\t\t//next.dockers.first().setReferencePoint({x: this.bounds.width() / 2.0, y: this.bounds.height() / 2.0});\n\t\t\t\t} /*else if(next.dockers.length > 0) { //next is a node and next has a docker\n\t\t\t\t\tnext.dockers.first().setDockedShape(this);\n\t\t\t\t\tnext.dockers.first().setReferencePoint({x: this.bounds.width() / 2.0, y: this.bounds.height() / 2.0});\n\t\t\t\t}*/\n\t\t\t}\t\n\t\t\t\n\t\t}).bind(this));\n\t\t\n        \n        var oryxDockers = data.find(function(obj){\n            return (obj.prefix === \"oryx\" &&\n            obj.name === \"dockers\");\n        });\n\t\t\n        if (oryxDockers) {\n            var dataByPath = oryxDockers.value.split(\"#\").without(\"\").without(\" \");\n            \n            dataByPath.each((function(data, index){\n                var values = data.replace(/,/g, \" \").split(\" \").without(\"\");\n                \n                //for each docker two values must be defined\n                if (values.length % 2 === 0) {\n                    var path = this._paths[index];\n                    \n                    if (path) {\n                        if (index === 0) {\n                            while (this._dockersByPath[path.id].length > 2) {\n                                this.removeDocker(this._dockersByPath[path.id][1]);\n                            }\n                        }\n                        else {\n                            while (this._dockersByPath[path.id].length > 1) {\n                                this.removeDocker(this._dockersByPath[path.id][0]);\n                            }\n                        }\n                        \n                        var dockersByPath = this._dockersByPath[path.id];\n                        \n                        if (index === 0) {\n                            //set position of first docker\n                            var x = parseFloat(values.shift());\n                            var y = parseFloat(values.shift());\n                            \n                            if (dockersByPath.first().getDockedShape()) {\n                                dockersByPath.first().setReferencePoint({\n                                    x: x,\n                                    y: y\n                                });\n                            }\n                            else {\n                                dockersByPath.first().bounds.centerMoveTo(x, y);\n                            }\n                        }\n                        \n                        //set position of last docker\n                        y = parseFloat(values.pop());\n                        x = parseFloat(values.pop());\n                        \n                        if (dockersByPath.last().getDockedShape()) {\n                            dockersByPath.last().setReferencePoint({\n                                x: x,\n                                y: y\n                            });\n                        } else {\n                            dockersByPath.last().bounds.centerMoveTo(x, y);\n                        }\n                        \n                        //add additional dockers\n                        for (var i = 0; i < values.length; i++) {\n                            x = parseFloat(values[i]);\n                            y = parseFloat(values[++i]);\n                            \n                            var newDocker = this.createDocker();\n                            newDocker.bounds.centerMoveTo(x, y);\n                            \n                            //this.dockers = this.dockers.without(newDocker);\n                            //this.dockers.splice(this.dockers.indexOf(dockersByPath.last()), 0, newDocker);\n                            //dockersByPath.splice(this.dockers.indexOf(dockersByPath.last()), 0, newDocker);\n\t\t\t\t\t\t}\n                    }\n                }\n            }).bind(this));\n        } else {\n            this.alignDockers();\n        }\n\t\t\n        arguments.callee.$.deserialize.apply(this, arguments);\n\t\t\n\t\tthis._changed();\n    },\n    \n    toString: function(){\n        return this.getStencil().title() + \" \" + this.id;\n    },\n    \n    /**\n     * @return {ORYX.Core.Shape} Returns last docked shape or null.\n     */\n    getTarget: function(){\n        return this.dockers.last() ? this.dockers.last().getDockedShape() : null;\n    },\n\t\n\t/**\n\t * @return {ORYX.Core.Shape} Returns the first docked shape or null\n\t */\n\tgetSource: function() {\n\t\treturn this.dockers.first() ? this.dockers.first().getDockedShape() : null;\n\t},\n\t\n\t/**\n\t * Checks whether the edge is at least docked to one shape.\n\t * \n\t * @return {boolean} True if edge is docked\n\t */\n\tisDocked: function() {\n\t\tvar isDocked = false;\n\t\tthis.dockers.each(function(docker) {\n\t\t\tif(docker.isDocked()) {\n\t\t\t\tisDocked = true;\n\t\t\t\tthrow $break;\n\t\t\t}\n\t\t});\n\t\treturn isDocked;\n\t},\n    \n    /**\n     * Calls {@link ORYX.Core.AbstractShape#toJSON} and add a some stencil set information.\n     */\n    toJSON: function() {\n        var json = arguments.callee.$.toJSON.apply(this, arguments);\n        \n        if(this.getTarget()) {\n            json.target = {\n                resourceId: this.getTarget().resourceId\n            };\n        }\n        \n        return json;\n    }\n};\nORYX.Core.Edge = ORYX.Core.Shape.extend(ORYX.Core.Edge);\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nif(!ORYX){ var ORYX = {} }\nif(!ORYX.Plugins){ ORYX.Plugins = {} }\n\n/**\n   This abstract plugin class can be used to build plugins on.\n   It provides some more basic functionality like registering events (on*-handlers)...\n   @example\n    ORYX.Plugins.MyPlugin = ORYX.Plugins.AbstractPlugin.extend({\n        construct: function() {\n            // Call super class constructor\n            arguments.callee.$.construct.apply(this, arguments);\n            \n            [...]\n        },\n        [...]\n    });\n   \n   @class ORYX.Plugins.AbstractPlugin\n   @constructor Creates a new instance\n   @author Willi Tscheschner\n*/\nORYX.Plugins.AbstractPlugin = Clazz.extend({\n    /** \n     * The facade which offer editor-specific functionality\n     * @type Facade\n     * @memberOf ORYX.Plugins.AbstractPlugin.prototype\n     */\n\tfacade: null,\n\t\n\tconstruct: function( facade ){\n\t\tthis.facade = facade;\n\t\t\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_LOADED, this.onLoaded.bind(this));\n\t},\n        \n    /**\n       Overwrite to handle load event. TODO: Document params!!!\n       @methodOf ORYX.Plugins.AbstractPlugin.prototype\n    */\n\tonLoaded: function(){},\n\t\n    /**\n       Overwrite to handle selection changed event. TODO: Document params!!!\n       @methodOf ORYX.Plugins.AbstractPlugin.prototype\n    */\n\tonSelectionChanged: function(){},\n\t\n    /**\n       Show overlay on given shape.\n       @methodOf ORYX.Plugins.AbstractPlugin.prototype\n       @example\n       showOverlay(\n           myShape,\n           { stroke: \"green\" },\n           ORYX.Editor.graft(\"http://www.w3.org/2000/svg\", null, ['path', {\n               \"title\": \"Click the element to execute it!\",\n               \"stroke-width\": 2.0,\n               \"stroke\": \"black\",\n               \"d\": \"M0,-5 L5,0 L0,5 Z\",\n               \"line-captions\": \"round\"\n           }])\n       )\n       @param {Oryx.XXX.Shape[]} shapes One shape or array of shapes the overlay should be put on\n       @param {Oryx.XXX.Attributes} attributes some attributes...\n       @param {Oryx.svg.node} svgNode The svg node which should be used as overlay\n       @param {String} [svgNode=\"NW\"] The svg node position where the overlay should be placed\n    */\n\tshowOverlay: function(shapes, attributes, svgNode, svgNodePosition ){\n\t\t\n\t\tif( !(shapes instanceof Array) ){\n\t\t\tshapes = [shapes]\n\t\t}\n\t\t\n\t\t// Define Shapes\n\t\tshapes = shapes.map(function(shape){\n\t\t\tvar el = shape;\n\t\t\tif( typeof shape == \"string\" ){\n\t\t\t\tel = this.facade.getCanvas().getChildShapeByResourceId( shape );\n\t\t\t\tel = el || this.facade.getCanvas().getChildById( shape, true );\n\t\t\t}\n\t\t\treturn el;\n\t\t}.bind(this)).compact();\n\t\t\n\t\t// Define unified id\n\t\tif( !this.overlayID ){\n\t\t\tthis.overlayID = this.type + ORYX.Editor.provideId();\n\t\t}\n\t\t\n\t\tthis.facade.raiseEvent({\n\t\t\ttype\t\t: ORYX.CONFIG.EVENT_OVERLAY_SHOW,\n\t\t\tid\t\t\t: this.overlayID,\n\t\t\tshapes\t\t: shapes,\n\t\t\tattributes \t: attributes,\n\t\t\tnode\t\t: svgNode,\n\t\t\tnodePosition: svgNodePosition || \"NW\"\n\t\t});\n\t\t\n\t},\n\t\n    /**\n       Hide current overlay.\n       @methodOf ORYX.Plugins.AbstractPlugin.prototype\n    */\n\thideOverlay: function(){\n\t\tthis.facade.raiseEvent({\n\t\t\ttype\t: ORYX.CONFIG.EVENT_OVERLAY_HIDE,\n\t\t\tid\t\t: this.overlayID\n\t\t});\t\t\n\t},\n\t\n    /**\n       Does a transformation with the given xslt stylesheet.\n       @methodOf ORYX.Plugins.AbstractPlugin.prototype\n       @param {String} data The data (e.g. eRDF) which should be transformed\n       @param {String} stylesheet URL of a stylesheet which should be used for transforming data.\n    */\n\tdoTransform: function( data, stylesheet ) {\t\t\n\t\t\n\t\tif( !stylesheet || !data ){\n\t\t\treturn \"\"\n\t\t}\n\n        var parser \t\t= new DOMParser();\n        var parsedData \t= parser.parseFromString(data, \"text/xml\");\n\t\tsource=stylesheet;\n\t\tnew Ajax.Request(source, {\n\t\t\tasynchronous: false,\n\t\t\tmethod: 'get',\n\t\t\tonSuccess: function(transport){\n\t\t\t\txsl = transport.responseText\n\t\t\t}.bind(this),\n\t\t\tonFailure: (function(transport){\n\t\t\t\tORYX.Log.error(\"XSL load failed\" + transport);\n\t\t\t}).bind(this)\n\t\t});\n        var xsltProcessor = new XSLTProcessor();\n\t\tvar domParser = new DOMParser();\n\t\tvar xslObject = domParser.parseFromString(xsl, \"text/xml\");\n        xsltProcessor.importStylesheet(xslObject);\n        \n        try {\n        \t\n            var newData \t\t= xsltProcessor.transformToFragment(parsedData, document);\n            var serializedData \t= (new XMLSerializer()).serializeToString(newData);\n            \n           \t/* Firefox 2 to 3 problem?! */\n            serializedData = !serializedData.startsWith(\"<?xml\") ? \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\"?>\" + serializedData : serializedData;\n            \n            return serializedData;\n            \n        }catch (error) {\n            return -1;\n        }\n        \n\t},\n\t\n\t/**\n\t * Opens a new window that shows the given XML content.\n\t * @methodOf ORYX.Plugins.AbstractPlugin.prototype\n\t * @param {Object} content The XML content to be shown.\n\t * @example\n\t * openDownloadWindow( \"my.xml\", \"<exampleXML />\" );\n\t */\n\topenXMLWindow: function(content) {\n\t\tvar win = window.open(\n\t\t   'data:application/xml,' + encodeURIComponent(\n\t\t     content\n\t\t   ),\n\t\t   '_blank', \"resizable=yes,width=600,height=600,toolbar=0,scrollbars=yes\"\n\t\t);\n\t},\n\t\n    /**\n     * Opens a download window for downloading the given content.\n     * @methodOf ORYX.Plugins.AbstractPlugin.prototype\n     * @param {String} filename The content's file name\n     * @param {String} content The content to download\n     */\n\topenDownloadWindow: function(filename, content) {\n\t\tvar win = window.open(\"\");\n\t\tif (win != null) {\n\t\t\twin.document.open();\n\t\t\twin.document.write(\"<html><body>\");\n\t\t\tvar submitForm = win.document.createElement(\"form\");\n\t\t\twin.document.body.appendChild(submitForm);\n\t\t\t\n\t\t\tvar createHiddenElement = function(name, value) {\n\t\t\t\tvar newElement = document.createElement(\"input\");\n\t\t\t\tnewElement.name=name;\n\t\t\t\tnewElement.type=\"hidden\";\n\t\t\t\tnewElement.value = value;\n\t\t\t\treturn newElement\n\t\t\t}\n\t\t\t\n\t\t\tsubmitForm.appendChild( createHiddenElement(\"download\", content) );\n\t\t\tsubmitForm.appendChild( createHiddenElement(\"file\", filename) );\n\t\t\t\n\t\t\t\n\t\t\tsubmitForm.method = \"POST\";\n\t\t\twin.document.write(\"</body></html>\");\n\t\t\twin.document.close();\n\t\t\tsubmitForm.action= ORYX.PATH + \"/download\";\n\t\t\tsubmitForm.submit();\n\t\t}\t\t\n\t},\n    \n    /**\n     * Serializes DOM.\n     * @methodOf ORYX.Plugins.AbstractPlugin.prototype\n     * @type {String} Serialized DOM\n     */\n    getSerializedDOM: function(){\n        // Force to set all resource IDs\n        var serializedDOM = DataManager.serializeDOM( this.facade );\n\n        //add namespaces\n        serializedDOM = '<?xml version=\"1.0\" encoding=\"utf-8\"?>' +\n        '<html xmlns=\"http://www.w3.org/1999/xhtml\" ' +\n        'xmlns:b3mn=\"http://b3mn.org/2007/b3mn\" ' +\n        'xmlns:ext=\"http://b3mn.org/2007/ext\" ' +\n        'xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\" ' +\n        'xmlns:atom=\"http://b3mn.org/2007/atom+xhtml\">' +\n        '<head profile=\"http://purl.org/NET/erdf/profile\">' +\n        '<link rel=\"schema.dc\" href=\"http://purl.org/dc/elements/1.1/\" />' +\n        '<link rel=\"schema.dcTerms\" href=\"http://purl.org/dc/terms/ \" />' +\n        '<link rel=\"schema.b3mn\" href=\"http://b3mn.org\" />' +\n        '<link rel=\"schema.oryx\" href=\"http://oryx-editor.org/\" />' +\n        '<link rel=\"schema.raziel\" href=\"http://raziel.org/\" />' +\n        '<base href=\"' +\n        location.href.split(\"?\")[0] +\n        '\" />' +\n        '</head><body>' +\n        serializedDOM +\n        '</body></html>';\n        \n        return serializedDOM;\n    },\n    \n    /**\n     * Sets the editor in read only mode: Edges/ dockers cannot be moved anymore,\n     * shapes cannot be selected anymore.\n     * @methodOf ORYX.Plugins.AbstractPlugin.prototype\n     */\n    enableReadOnlyMode: function(){\n        //Edges cannot be moved anymore\n        this.facade.disableEvent(ORYX.CONFIG.EVENT_MOUSEDOWN);\n        \n        // Stop the user from editing the diagram while the plugin is active\n        this._stopSelectionChange = function(){\n            if(this.facade.getSelection().length > 0) {\n                this.facade.setSelection([]);\n            }\n        };\n        this.facade.registerOnEvent(ORYX.CONFIG.EVENT_SELECTION_CHANGED, this._stopSelectionChange.bind(this));\n    },\n    /**\n     * Disables read only mode, see @see\n     * @methodOf ORYX.Plugins.AbstractPlugin.prototype\n     * @see ORYX.Plugins.AbstractPlugin.prototype.enableReadOnlyMode\n     */\n    disableReadOnlyMode: function(){\n        // Edges can be moved now again\n        this.facade.enableEvent(ORYX.CONFIG.EVENT_MOUSEDOWN);\n        \n        if (this._stopSelectionChange) {\n            this.facade.unregisterOnEvent(ORYX.CONFIG.EVENT_SELECTION_CHANGED, this._stopSelectionChange.bind(this));\n            this._stopSelectionChange = undefined;\n        }\n    },\n    \n    /**\n     * Extracts RDF from DOM.\n     * @methodOf ORYX.Plugins.AbstractPlugin.prototype\n     * @type {String} Extracted RFD. Null if there are transformation errors.\n     */\n    getRDFFromDOM: function(){\n        //convert to RDF\n\t\ttry {\n\t\t\tvar xsl = \"\";\n\t\t\tsource=ORYX.PATH + \"lib/extract-rdf.xsl\";\n\t\t\tnew Ajax.Request(source, {\n\t\t\t\tasynchronous: false,\n\t\t\t\tmethod: 'get',\n\t\t\t\tonSuccess: function(transport){\n\t\t\t\t\txsl = transport.responseText\n\t\t\t\t}.bind(this),\n\t\t\t\tonFailure: (function(transport){\n\t\t\t\t\tORYX.Log.error(\"XSL load failed\" + transport);\n\t\t\t\t}).bind(this)\n\t\t\t});\n\t\t\t\n\t\t\tvar domParser = new DOMParser();\n\t\t\tvar xmlObject = domParser.parseFromString(this.getSerializedDOM(), \"text/xml\");\n\t\t\tvar xslObject = domParser.parseFromString(xsl, \"text/xml\");\n\t\t\tvar xsltProcessor = new XSLTProcessor();\n\t\t\txsltProcessor.importStylesheet(xslObject);\n\t\t\tvar result = xsltProcessor.transformToFragment(xmlObject, document);\n\t\t\t\n\t\t\tvar serializer = new XMLSerializer();\n\t\t\t\n\t\t\treturn serializer.serializeToString(result);\n\t\t} catch(e){\n\t\t\tconsole.log(\"error serializing \" + e);\n\t\t\treturn \"\";\n\t\t}\n\n\t\t\n    },\n    \n    /**\n\t * Checks if a certain stencil set is loaded right now.\n\t * \n\t */\n\tisStencilSetExtensionLoaded: function(stencilSetExtensionNamespace) {\n\t\treturn this.facade.getStencilSets().values().any(\n\t\t\tfunction(ss){ \n\t\t\t\treturn ss.extensions().keys().any(\n\t\t\t\t\tfunction(extensionKey) {\n\t\t\t\t\t\treturn extensionKey == stencilSetExtensionNamespace;\n\t\t\t\t\t}.bind(this)\n\t\t\t\t);\n\t\t\t}.bind(this)\n\t\t);\n\t},\n\t\n\t/**\n\t * Raises an event so that registered layouters does\n\t * have the posiblility to layout the given shapes \n\t * For further reading, have a look into the AbstractLayouter\n\t * class\n\t * @param {Object} shapes\n\t */\n\tdoLayout: function(shapes){\n\t\t// Raises a do layout event\n\t\tif (this.facade.raiseEvent)\n\t\t{\n\t\t\tthis.facade.raiseEvent({\n\t\t\t\ttype\t\t: ORYX.CONFIG.EVENT_LAYOUT,\n\t\t\t\tshapes\t\t: shapes\n\t\t\t});\n\t\t}\n\t\telse\n\t\t{\n\t\t\tthis.facade.handleEvents({\n\t\t\t\ttype\t\t: ORYX.CONFIG.EVENT_LAYOUT,\n\t\t\t\tshapes\t\t: shapes\n\t\t\t});\n\t\t}\n\t},\n\t\n\t\n\t/**\n\t * Does a primitive layouting with the incoming/outgoing \n\t * edges (set the dockers to the right position) and if \n\t * necessary, it will be called the real layouting \n\t * @param {ORYX.Core.Node} node\n\t * @param {Array} edges\n\t */\n\tlayoutEdges : function(node, allEdges, offset){\t\t\n\n\t\tif (!this.facade.isExecutingCommands()){ return }\t\t\n\n\t\tvar Command = ORYX.Core.Command.extend({\n\t\t\tconstruct: function(edges, node, offset, plugin){\n\t\t\t\tthis.edges = edges;\n\t\t\t\tthis.node = node;\n\t\t\t\tthis.plugin = plugin;\n\t\t\t\tthis.offset = offset;\n\t\t\t\t\n\t\t\t\t// Get the new absolute center\n\t\t\t\tvar center = node.absoluteXY();\n\t\t\t\tthis.ulo = {x: center.x - offset.x, y:center.y - offset.y};\n\t\t\t\t\n\t\t\t\t\n\t\t\t},\n\t\t\texecute: function(){\n\t\t\t\t\n\t\t\t\tif (this.changes){\n\t\t\t\t\tthis.executeAgain();\n\t\t\t\t\treturn;\n\t\t\t\t} else {\n\t\t\t\t\tthis.changes = [];\n\t\t\t\t\tthis.edges.each(function(edge){\n\t\t\t\t\t\tthis.changes.push({\n\t\t\t\t\t\t\tedge: edge,\n\t\t\t\t\t\t\toldDockerPositions: edge.dockers.map(function(r){ return r.bounds.center() })\n\t\t\t\t\t\t})\n\t\t\t\t\t}.bind(this));\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// Find all edges, which are related to the node and\n\t\t\t\t// have more than two dockers\n\t\t\t\tthis.edges\n\t\t\t\t\t// Find all edges with more than two dockers\n\t\t\t\t\t.findAll(function(r){ return r.dockers.length > 2 }.bind(this))\n\t\t\t\t\t// For every edge, check second and one before last docker\n\t\t\t\t\t// if there are horizontal/vertical on the same level\n\t\t\t\t\t// and if so, align the the bounds \n\t\t\t\t\t.each(function(edge){\n\t\t\t\t\t\tif (edge.dockers.first().getDockedShape() === this.node){\n\t\t\t\t\t\t\tvar second = edge.dockers[1];\n\t\t\t\t\t\t\tif (this.align(second.bounds, edge.dockers.first())){ second.update(); }\n\t\t\t\t\t\t} else if (edge.dockers.last().getDockedShape() === this.node) {\n\t\t\t\t\t\t\tvar beforeLast = edge.dockers[edge.dockers.length-2];\n\t\t\t\t\t\t\tif (this.align(beforeLast.bounds, edge.dockers.last())){ beforeLast.update(); }\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t}\n\t\t\t\t\t\tedge._update(true);\n\t\t\t\t\t\tedge.removeUnusedDockers();\n\t\t\t\t\t\tif (this.isBendPointIncluded(edge)){\n\t\t\t\t\t\t\tthis.plugin.doLayout(edge);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t}.bind(this));\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t// Find all edges, which have only to dockers \n\t\t\t\t// and is located horizontal/vertical.\n\t\t\t\t// Do layout with those edges\n\t\t\t\tthis.edges\n\t\t\t\t\t// Find all edges with exactly two dockers\n\t\t\t\t\t.each(function(edge){\n\t\t\t\t\t\tif (edge.dockers.length == 2){\n\t\t\t\t\t\t\tvar p1 = edge.dockers.first().getAbsoluteReferencePoint() || edge.dockers.first().bounds.center();\n\t\t\t\t\t\t\tvar p2 = edge.dockers.last().getAbsoluteReferencePoint() || edge.dockers.first().bounds.center();\n\t\t\t\t\t\t\t// Find all horizontal/vertical edges\n\t\t\t\t\t\t\tif (Math.abs(-Math.abs(p1.x - p2.x) + Math.abs(this.offset.x)) < 2 || Math.abs(-Math.abs(p1.y - p2.y) + Math.abs(this.offset.y)) < 2){\n\t\t\t\t\t\t\t\tthis.plugin.doLayout(edge);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}.bind(this));\n\t\t\n\t\t\t\tthis.edges.each(function(edge, i){\n\t\t\t\t\tthis.changes[i].dockerPositions = edge.dockers.map(function(r){ return r.bounds.center() });\n\t\t\t\t}.bind(this));\n\t\t\t\t\n\t\t\t},\n\t\t\t/**\n\t\t\t * Align the bounds if the center is \n\t\t\t * the same than the old center\n\t\t\t * @params {Object} bounds\n\t\t\t * @params {Object} bounds2\n\t\t\t */\n\t\t\talign: function(bounds, refDocker){\n\t\t\t\t\n\t\t\t\tvar abRef = refDocker.getAbsoluteReferencePoint() || refDocker.bounds.center();\n\t\t\t\t\n\t\t\t\tvar xdif = bounds.center().x-abRef.x;\n\t\t\t\tvar ydif = bounds.center().y-abRef.y;\n\t\t\t\tif (Math.abs(-Math.abs(xdif) + Math.abs(this.offset.x)) < 3 && this.offset.xs === undefined){\n\t\t\t\t\tbounds.moveBy({x:-xdif, y:0})\n\t\t\t\t}\n\t\t\t\tif (Math.abs(-Math.abs(ydif) + Math.abs(this.offset.y)) < 3 && this.offset.ys === undefined){\n\t\t\t\t\tbounds.moveBy({y:-ydif, x:0})\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (this.offset.xs !== undefined || this.offset.ys !== undefined){\n\t\t\t\t\tvar absPXY = refDocker.getDockedShape().absoluteXY();\n\t\t\t\t\txdif = bounds.center().x-(absPXY.x+((abRef.x-absPXY.x)/this.offset.xs));\n\t\t\t\t\tydif = bounds.center().y-(absPXY.y+((abRef.y-absPXY.y)/this.offset.ys));\n\t\t\t\t\t\n\t\t\t\t\tif (Math.abs(-Math.abs(xdif) + Math.abs(this.offset.x)) < 3){\n\t\t\t\t\t\tbounds.moveBy({x:-(bounds.center().x-abRef.x), y:0})\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif (Math.abs(-Math.abs(ydif) + Math.abs(this.offset.y)) < 3){\n\t\t\t\t\t\tbounds.moveBy({y:-(bounds.center().y-abRef.y), x:0})\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\n\t\t\t/**\t\t\t\t\t\t\n\t\t\t * Returns a TRUE if there are bend point which overlay the shape\n\t\t\t */\n\t\t\tisBendPointIncluded: function(edge){\n\t\t\t\t// Get absolute bounds\n\t\t\t\tvar ab = edge.dockers.first().getDockedShape();\n\t\t\t\tvar bb = edge.dockers.last().getDockedShape();\n\t\t\t\t\n\t\t\t\tif (ab) {\n\t\t\t\t\tab = ab.absoluteBounds();\n\t\t\t\t\tab.widen(5);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (bb) {\n\t\t\t\t\tbb = bb.absoluteBounds();\n\t\t\t\t\tbb.widen(20); // Wide with 20 because of the arrow from the edge\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\treturn edge.dockers\n\t\t\t\t\t\t.any(function(docker, i){ \n\t\t\t\t\t\t\tvar c = docker.bounds.center();\n\t\t\t\t\t\t\t\t\t// Dont count first and last\n\t\t\t\t\t\t\treturn \ti != 0 && i != edge.dockers.length-1 && \n\t\t\t\t\t\t\t\t\t// Check if the point is included to the absolute bounds\n\t\t\t\t\t\t\t\t\t((ab && ab.isIncluded(c)) || (bb && bb.isIncluded(c)))\n\t\t\t\t\t\t})\n\t\t\t},\n\t\t\t\n\t\t\tremoveAllDocker: function(edge){\n\t\t\t\tedge.dockers.slice(1, edge.dockers.length-1).each(function(docker){\n\t\t\t\t\tedge.removeDocker(docker);\n\t\t\t\t})\n\t\t\t},\n\t\t\texecuteAgain: function(){\n\t\t\t\tthis.changes.each(function(change){\n\t\t\t\t\t// Reset the dockers\n\t\t\t\t\tthis.removeAllDocker(change.edge);\n\t\t\t\t\tchange.dockerPositions.each(function(pos, i){\t\n\t\t\t\t\t\tif (i==0||i==change.dockerPositions.length-1){ return }\t\t\t\t\t\n\t\t\t\t\t\tvar docker = change.edge.createDocker(undefined, pos);\n\t\t\t\t\t\tdocker.bounds.centerMoveTo(pos);\n\t\t\t\t\t\tdocker.update();\n\t\t\t\t\t}.bind(this));\n\t\t\t\t\tchange.edge._update(true);\n\t\t\t\t}.bind(this));\n\t\t\t},\n\t\t\trollback: function(){\t\t\t\t\t\n\t\t\t\tthis.changes.each(function(change){\n\t\t\t\t\t// Reset the dockers\n\t\t\t\t\tthis.removeAllDocker(change.edge);\n\t\t\t\t\tchange.oldDockerPositions.each(function(pos, i){\t\n\t\t\t\t\t\tif (i==0||i==change.oldDockerPositions.length-1){ return }\t\t\t\t\t\n\t\t\t\t\t\tvar docker = change.edge.createDocker(undefined, pos);\n\t\t\t\t\t\tdocker.bounds.centerMoveTo(pos);\n\t\t\t\t\t\tdocker.update();\n\t\t\t\t\t}.bind(this));\n\t\t\t\t\tchange.edge._update(true);\n\t\t\t\t}.bind(this));\n\t\t\t}\n\t\t});\n\t\t\n\t\tthis.facade.executeCommands([new Command(allEdges, node, offset, this)]);\n\n\t}\n});/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nif(!ORYX){ var ORYX = {} }\nif(!ORYX.Plugins){ ORYX.Plugins = {} }\n\n/**\n   This abstract plugin implements the core behaviour of layout\n   \n   @class ORYX.Plugins.AbstractLayouter\n   @constructor Creates a new instance\n   @author Willi Tscheschner\n*/\nORYX.Plugins.AbstractLayouter = ORYX.Plugins.AbstractPlugin.extend({\n\t\n\t/**\n\t * 'layouted' defined all types of shapes which will be layouted. \n\t * It can be one value or an array of values. The value\n\t * can be a Stencil ID (as String) or an class type of either \n\t * a ORYX.Core.Node or ORYX.Core.Edge\n     * @type Array|String|Object\n     * @memberOf ORYX.Plugins.AbstractLayouter.prototype\n\t */\n\tlayouted : [],\n\t\n\t/**\n\t * Constructor\n\t * @param {Object} facade\n\t * @memberOf ORYX.Plugins.AbstractLayouter.prototype\n\t */\n\tconstruct: function( facade ){\n\t\targuments.callee.$.construct.apply(this, arguments);\n\t\t\t\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_LAYOUT, this._initLayout.bind(this));\n\t},\n\t\n\t/**\n\t * Proofs if this shape should be layouted or not\n\t * @param {Object} shape\n     * @memberOf ORYX.Plugins.AbstractLayouter.prototype\n\t */\n\tisIncludedInLayout: function(shape){\n\t\tif (!(this.layouted instanceof Array)){\n\t\t\tthis.layouted = [this.layouted].compact();\n\t\t}\n\t\t\n\t\t// If there are no elements\n\t\tif (this.layouted.length <= 0) {\n\t\t\t// Return TRUE\n\t\t\treturn true;\n\t\t}\n\t\t\n\t\t// Return TRUE if there is any correlation between \n\t\t// the 'layouted' attribute and the shape themselve.\n\t\treturn this.layouted.any(function(s){\n\t\t\tif (typeof s == \"string\") {\n\t\t\t\treturn shape.getStencil().id().include(s);\n\t\t\t} else {\n\t\t\t\treturn shape instanceof s;\n\t\t\t}\n\t\t})\n\t},\n\t\n\t/**\n\t * Callback to start the layouting\n\t * @param {Object} event Layout event\n\t * @param {Object} shapes Given shapes\n     * @memberOf ORYX.Plugins.AbstractLayouter.prototype\n\t */\n\t_initLayout: function(event){\n\t\t\n\t\t// Get the shapes\n\t\tvar shapes = [event.shapes].flatten().compact();\n\t\t\n\t\t// Find all shapes which should be layouted\n\t\tvar toLayout = shapes.findAll(function(shape){\n\t\t\treturn this.isIncludedInLayout(shape) \n\t\t}.bind(this))\n\t\t\n\t\t// If there are shapes left \n\t\tif (toLayout.length > 0){\n\t\t\t// Do layout\n\t\t\tthis.layout(toLayout);\n\t\t}\n\t},\n\t\n\t/**\n\t * Implementation of layouting a set on shapes\n\t * @param {Object} shapes Given shapes\n     * @memberOf ORYX.Plugins.AbstractLayouter.prototype\n\t */\n\tlayout: function(shapes){\n\t\tthrow new Error(\"Layouter has to implement the layout function.\")\n\t}\n});/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nif (!ORYX.Plugins) \n    ORYX.Plugins = new Object();\n\nORYX.Plugins.Edit = Clazz.extend({\n    \n    construct: function(facade){\n    \n        this.facade = facade;\n        this.clipboard = new ORYX.Plugins.Edit.ClipBoard();\n        \n        //this.facade.registerOnEvent(ORYX.CONFIG.EVENT_KEYDOWN, this.keyHandler.bind(this));\n        \n        this.facade.offer({\n         name: ORYX.I18N.Edit.cut,\n         description: ORYX.I18N.Edit.cutDesc,\n         icon: ORYX.PATH + \"images/cut.png\",\n\t\t keyCodes: [{\n\t\t\t\tmetaKeys: [ORYX.CONFIG.META_KEY_META_CTRL],\n\t\t\t\tkeyCode: 88,\n\t\t\t\tkeyAction: ORYX.CONFIG.KEY_ACTION_DOWN\n\t\t\t}\n\t\t ],\n         functionality: this.callEdit.bind(this, this.editCut),\n         group: ORYX.I18N.Edit.group,\n         index: 1,\n         minShape: 1\n         });\n         \n        this.facade.offer({\n         name: ORYX.I18N.Edit.copy,\n         description: ORYX.I18N.Edit.copyDesc,\n         icon: ORYX.PATH + \"images/page_copy.png\",\n\t\t keyCodes: [{\n\t\t\t\tmetaKeys: [ORYX.CONFIG.META_KEY_META_CTRL],\n\t\t\t\tkeyCode: 67,\n\t\t\t\tkeyAction: ORYX.CONFIG.KEY_ACTION_DOWN\n\t\t\t}\n\t\t ],\n         functionality: this.callEdit.bind(this, this.editCopy, [true, false]),\n         group: ORYX.I18N.Edit.group,\n         index: 2,\n         minShape: 1\n         });\n         \n        this.facade.offer({\n         name: ORYX.I18N.Edit.paste,\n         description: ORYX.I18N.Edit.pasteDesc,\n         icon: ORYX.PATH + \"images/page_paste.png\",\n\t\t keyCodes: [{\n\t\t\t\tmetaKeys: [ORYX.CONFIG.META_KEY_META_CTRL],\n\t\t\t\tkeyCode: 86,\n\t\t\t\tkeyAction: ORYX.CONFIG.KEY_ACTION_DOWN\n\t\t\t}\n\t\t ],\n         functionality: this.callEdit.bind(this, this.editPaste),\n         isEnabled: this.clipboard.isOccupied.bind(this.clipboard),\n         group: ORYX.I18N.Edit.group,\n         index: 3,\n         minShape: 0,\n         maxShape: 0\n         });\n         \n        this.facade.offer({\n            name: ORYX.I18N.Edit.del,\n            description: ORYX.I18N.Edit.delDesc,\n            icon: ORYX.PATH + \"images/cross.png\",\n\t\t\tkeyCodes: [{\n\t\t\t\t\tmetaKeys: [ORYX.CONFIG.META_KEY_META_CTRL],\n\t\t\t\t\tkeyCode: 8,\n\t\t\t\t\tkeyAction: ORYX.CONFIG.KEY_ACTION_DOWN\n\t\t\t\t},\n\t\t\t\t{\t\n\t\t\t\t\tkeyCode: 46,\n\t\t\t\t\tkeyAction: ORYX.CONFIG.KEY_ACTION_DOWN\n\t\t\t\t}\n\t\t\t],\n            functionality: this.callEdit.bind(this, this.editDelete),\n            group: ORYX.I18N.Edit.group,\n            index: 4,\n            minShape: 1\n        });\n    },\n\t\n\tcallEdit: function(fn, args){\n\t\twindow.setTimeout(function(){\n\t\t\tfn.apply(this, (args instanceof Array ? args : []));\n\t\t}.bind(this), 1);\n\t},\n\t\n\t/**\n\t * Handles the mouse down event and starts the copy-move-paste action, if\n\t * control or meta key is pressed.\n\t */\n\thandleMouseDown: function(event) {\n\t\tif(this._controlPressed) {\n\t\t\tthis._controlPressed = false;\n\t\t\tthis.editCopy();\n//\t\t\tconsole.log(\"copiedEle: %0\",this.clipboard.shapesAsJson)\n//\t\t\tconsole.log(\"mousevent: %o\",event)\n\t\t\tthis.editPaste();\n\t\t\tevent.forceExecution = true;\n\t\t\tthis.facade.raiseEvent(event, this.clipboard.shapesAsJson);\n\t\t\t\n\t\t}\n\t},\n    \n    /**\n     * The key handler for this plugin. Every action from the set of cut, copy,\n     * paste and delete should be accessible trough simple keyboard shortcuts.\n     * This method checks whether any event triggers one of those actions.\n     *\n     * @param {Object} event The keyboard event that should be analysed for\n     *     triggering of this plugin.\n     */\n//    keyHandler: function(event){\n//        //TODO document what event.which is.\n//        \n//        ORYX.Log.debug(\"edit.js handles a keyEvent.\");\n//        \n//        // assure we have the current event.\n//        if (!event) \n//            event = window.event;\n//        \n//        \n//        // get the currently pressed key and state of control key.\n//        var pressedKey = event.which || event.keyCode;\n//        var ctrlPressed = event.ctrlKey;\n//        \n//        // if the object is to be deleted, do so, and return immediately.\n//        if ((pressedKey == ORYX.CONFIG.KEY_CODE_DELETE) ||\n//        ((pressedKey == ORYX.CONFIG.KEY_CODE_BACKSPACE) &&\n//        (event.metaKey || event.appleMetaKey))) {\n//        \n//            ORYX.Log.debug(\"edit.js deletes the shape.\");\n//            this.editDelete();\n//            return;\n//        }\n//        \n//         // if control key is not pressed, we're not interested anymore.\n//         if (!ctrlPressed)\n//         return;\n//         \n//         // when ctrl is pressed, switch trough the possibilities.\n//         switch (pressedKey) {\n//         \n//\t         // cut.\n//\t         case ORYX.CONFIG.KEY_CODE_X:\n//\t         this.editCut();\n//\t         break;\n//\t         \n//\t         // copy.\n//\t         case ORYX.CONFIG.KEY_CODE_C:\n//\t         this.editCopy();\n//\t         break;\n//\t         \n//\t         // paste.\n//\t         case ORYX.CONFIG.KEY_CODE_V:\n//\t         this.editPaste();\n//\t         break;\n//         }\n//    },\n\t\n    /**\n     * Returns a list of shapes which should be considered while copying.\n     * Besides the shapes of given ones, edges and attached nodes are added to the result set.\n     * If one of the given shape is a child of another given shape, it is not put into the result. \n     */\n    getAllShapesToConsider: function(shapes){\n        var shapesToConsider = []; // only top-level shapes\n        var childShapesToConsider = []; // all child shapes of top-level shapes\n        \n        shapes.each(function(shape){\n            //Throw away these shapes which have a parent in given shapes\n            isChildShapeOfAnother = shapes.any(function(s2){\n                return s2.hasChildShape(shape);\n            });\n            if(isChildShapeOfAnother) return;\n            \n            // This shape should be considered\n            shapesToConsider.push(shape);\n            // Consider attached nodes (e.g. intermediate events)\n            if (shape instanceof ORYX.Core.Node) {\n\t\t\t\tvar attached = shape.getOutgoingNodes();\n\t\t\t\tattached = attached.findAll(function(a){ return !shapes.include(a) });\n                shapesToConsider = shapesToConsider.concat(attached);\n            }\n            \n            childShapesToConsider = childShapesToConsider.concat(shape.getChildShapes(true));\n        }.bind(this));\n        \n        // All edges between considered child shapes should be considered\n        // Look for these edges having incoming and outgoing in childShapesToConsider\n        var edgesToConsider = this.facade.getCanvas().getChildEdges().select(function(edge){\n            // Ignore if already added\n            if(shapesToConsider.include(edge)) return false;\n            // Ignore if there are no docked shapes\n            if(edge.getAllDockedShapes().size() === 0) return false; \n            // True if all docked shapes are in considered child shapes\n            return edge.getAllDockedShapes().all(function(shape){\n                // Remember: Edges can have other edges on outgoing, that is why edges must not be included in childShapesToConsider\n                return shape instanceof ORYX.Core.Edge || childShapesToConsider.include(shape);\n            });\n        });\n        shapesToConsider = shapesToConsider.concat(edgesToConsider);\n        \n        return shapesToConsider;\n    },\n    \n    /**\n     * Performs the cut operation by first copy-ing and then deleting the\n     * current selection.\n     */\n    editCut: function(){\n        //TODO document why this returns false.\n        //TODO document what the magic boolean parameters are supposed to do.\n        \n        this.editCopy(false, true);\n        this.editDelete(true);\n        return false;\n    },\n    \n    /**\n     * Performs the copy operation.\n     * @param {Object} will_not_update ??\n     */\n    editCopy: function( will_update, useNoOffset ){\n        var selection = this.facade.getSelection();\n        \n        //if the selection is empty, do not remove the previously copied elements\n        if(selection.length == 0) return;\n        \n        this.clipboard.refresh(selection, this.getAllShapesToConsider(selection), this.facade.getCanvas().getStencil().stencilSet().namespace(), useNoOffset);\n\n        if( will_update ) this.facade.updateSelection();\n    },\n    \n    /**\n     * Performs the paste operation.\n     */\n    editPaste: function(){\n        // Create a new canvas with childShapes \n\t\t//and stencilset namespace to be JSON Import conform\n\t\tvar canvas = {\n            childShapes: this.clipboard.shapesAsJson,\n\t\t\tstencilset:{\n\t\t\t\tnamespace:this.clipboard.SSnamespace\n\t\t\t}\n        };\n        // Apply json helper to iterate over json object\n\t\tjQuery.extend(canvas, ORYX.Core.AbstractShape.JSONHelper);\n        \n        var childShapeResourceIds = canvas.getChildShapes(true).pluck(\"resourceId\");\n        var outgoings = {};\n        // Iterate over all shapes\n        canvas.eachChild(function(shape, parent){\n            // Throw away these references where referenced shape isn't copied\n            shape.outgoing = shape.outgoing.select(function(out){\n                return childShapeResourceIds.include(out.resourceId);\n            });\n\t\t\tshape.outgoing.each(function(out){\n\t\t\t\tif (!outgoings[out.resourceId]){ outgoings[out.resourceId] = []; }\n\t\t\t\toutgoings[out.resourceId].push(shape);\n\t\t\t});\n\t\t\t\n            return shape;\n        }.bind(this), true, true);\n        \n\n        // Iterate over all shapes\n        canvas.eachChild(function(shape, parent){\n            \n        \t// Check if there has a valid target\n            if(shape.target && !(childShapeResourceIds.include(shape.target.resourceId))){\n                shape.target = undefined;\n                shape.targetRemoved = true;\n            }\n    \t\t\n    \t\t// Check if the first docker is removed\n    \t\tif(\tshape.dockers && \n    \t\t\tshape.dockers.length >= 1 && \n    \t\t\tshape.dockers[0].getDocker &&\n    \t\t\t((shape.dockers[0].getDocker().getDockedShape() &&\n    \t\t\t!childShapeResourceIds.include(shape.dockers[0].getDocker().getDockedShape().resourceId)) || \n    \t\t\t!shape.getShape().dockers[0].getDockedShape()&&!outgoings[shape.resourceId])) {\n    \t\t\t\t\n    \t\t\tshape.sourceRemoved = true;\n    \t\t}\n\t\t\t\n            return shape;\n        }.bind(this), true, true);\n\n\t\t\n        // Iterate over top-level shapes\n        canvas.eachChild(function(shape, parent){\n            // All top-level shapes should get an offset in their bounds\n            // Move the shape occording to COPY_MOVE_OFFSET\n        \tif (this.clipboard.useOffset) {\n\t            shape.bounds = {\n\t                lowerRight: {\n\t                    x: shape.bounds.lowerRight.x + ORYX.CONFIG.COPY_MOVE_OFFSET,\n\t                    y: shape.bounds.lowerRight.y + ORYX.CONFIG.COPY_MOVE_OFFSET\n\t                },\n\t                upperLeft: {\n\t                    x: shape.bounds.upperLeft.x + ORYX.CONFIG.COPY_MOVE_OFFSET,\n\t                    y: shape.bounds.upperLeft.y + ORYX.CONFIG.COPY_MOVE_OFFSET\n\t                }\n\t            };\n        \t}\n            // Only apply offset to shapes with a target\n            if (shape.dockers){\n                shape.dockers = shape.dockers.map(function(docker, i){\n                    // If shape had a target but the copied does not have anyone anymore,\n                    // migrate the relative dockers to absolute ones.\n                    if( (shape.targetRemoved === true && i == shape.dockers.length - 1&&docker.getDocker) ||\n\t\t\t\t\t\t(shape.sourceRemoved === true && i == 0&&docker.getDocker)){\n\n                        docker = docker.getDocker().bounds.center();\n                    }\n\n\t\t\t\t\t// If it is the first docker and it has a docked shape, \n\t\t\t\t\t// just return the coordinates\n\t\t\t\t   \tif ((i == 0 && docker.getDocker instanceof Function && \n\t\t\t\t   \t\tshape.sourceRemoved !== true && (docker.getDocker().getDockedShape() || ((outgoings[shape.resourceId]||[]).length > 0 && (!(shape.getShape() instanceof ORYX.Core.Node) || outgoings[shape.resourceId][0].getShape() instanceof ORYX.Core.Node)))) || \n\t\t\t\t\t\t(i == shape.dockers.length - 1 && docker.getDocker instanceof Function && \n\t\t\t\t\t\tshape.targetRemoved !== true && (docker.getDocker().getDockedShape() || shape.target))){\n\t\t\t\t\t\t\t\n\t\t\t\t\t\treturn {\n                        \tx: docker.x, \n                        \ty: docker.y,\n                        \tgetDocker: docker.getDocker\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (this.clipboard.useOffset) {\n\t                    return {\n\t\t                        x: docker.x + ORYX.CONFIG.COPY_MOVE_OFFSET, \n\t\t                        y: docker.y + ORYX.CONFIG.COPY_MOVE_OFFSET,\n\t                        \tgetDocker: docker.getDocker\n\t\t                    };\n\t\t\t\t   \t} else {\n\t\t\t\t   \t\treturn {\n                        \tx: docker.x, \n                        \ty: docker.y,\n                        \tgetDocker: docker.getDocker\n\t\t\t\t\t\t};\n\t\t\t\t   \t}\n                }.bind(this));\n\n            } else if (shape.getShape() instanceof ORYX.Core.Node && shape.dockers && shape.dockers.length > 0 && (!shape.dockers.first().getDocker || shape.sourceRemoved === true || !(shape.dockers.first().getDocker().getDockedShape() || outgoings[shape.resourceId]))){\n            \t\n            \tshape.dockers = shape.dockers.map(function(docker, i){\n            \t\t\n                    if((shape.sourceRemoved === true && i == 0&&docker.getDocker)){\n                    \tdocker = docker.getDocker().bounds.center();\n                    }\n                    \n                    if (this.clipboard.useOffset) {\n\t            \t\treturn {\n\t                        x: docker.x + ORYX.CONFIG.COPY_MOVE_OFFSET, \n\t                        y: docker.y + ORYX.CONFIG.COPY_MOVE_OFFSET,\n\t                    \tgetDocker: docker.getDocker\n\t                    };\n                    } else {\n\t            \t\treturn {\n\t                        x: docker.x, \n\t                        y: docker.y,\n\t                    \tgetDocker: docker.getDocker\n\t                    };\n                    }\n            \t}.bind(this));\n            }\n            \n            return shape;\n        }.bind(this), false, true);\n\n        this.clipboard.useOffset = true;\n        this.facade.importJSON(canvas);\n    },\n    \n    /**\n     * Performs the delete operation. No more asking.\n     */\n    editDelete: function(){\n        var selection = this.facade.getSelection();\n        \n        var clipboard = new ORYX.Plugins.Edit.ClipBoard();\n        clipboard.refresh(selection, this.getAllShapesToConsider(selection));\n        \n\t\tvar command = new ORYX.Plugins.Edit.DeleteCommand(clipboard , this.facade);\n                                       \n\t\tthis.facade.executeCommands([command]);\n    }\n}); \n\nORYX.Plugins.Edit.ClipBoard = Clazz.extend({\n    construct: function(){\n        this.shapesAsJson = [];\n        this.selection = [];\n\t\tthis.SSnamespace=\"\";\n\t\tthis.useOffset=true;\n    },\n    isOccupied: function(){\n        return this.shapesAsJson.length > 0;\n    },\n    refresh: function(selection, shapes, namespace, useNoOffset){\n        this.selection = selection;\n        this.SSnamespace=namespace;\n        // Store outgoings, targets and parents to restore them later on\n        this.outgoings = {};\n        this.parents = {};\n        this.targets = {};\n        this.useOffset = useNoOffset !== true;\n        \n        this.shapesAsJson = shapes.map(function(shape){\n            var s = shape.toJSON();\n            s.parent = {resourceId : shape.getParentShape().resourceId};\n            s.parentIndex = shape.getParentShape().getChildShapes().indexOf(shape)\n            return s;\n        });\n    }\n});\n\nORYX.Plugins.Edit.DeleteCommand = ORYX.Core.Command.extend({\n    construct: function(clipboard, facade){\n        this.clipboard          = clipboard;\n        this.shapesAsJson       = clipboard.shapesAsJson;\n        this.facade             = facade;\n        \n        // Store dockers of deleted shapes to restore connections\n        this.dockers            = this.shapesAsJson.map(function(shapeAsJson) {\n            var shape = shapeAsJson.getShape();\n            var incomingDockers = shape.getIncomingShapes().map(function(s){return s.getDockers().last();});\n            var outgoingDockers = shape.getOutgoingShapes().map(function(s){return s.getDockers().first();});\n            var dockers = shape.getDockers().concat(incomingDockers, outgoingDockers).compact().map(function(docker){\n                return {\n                    object: docker,\n                    referencePoint: docker.referencePoint,\n                    dockedShape: docker.getDockedShape()\n                };\n            });\n            return dockers;\n        }).flatten();\n    },          \n    execute: function(){\n        this.shapesAsJson.each(function(shapeAsJson){\n            // Delete shape\n            this.facade.deleteShape(shapeAsJson.getShape());\n        }.bind(this));\n        \n        this.facade.setSelection([]);\n        this.facade.getCanvas().update();\t\t\n\t\tthis.facade.updateSelection();\n        \n    },\n    rollback: function(){\n        this.shapesAsJson.each(function(shapeAsJson) {\n            var shape = shapeAsJson.getShape();\n            var parent = this.facade.getCanvas().getChildShapeByResourceId(shapeAsJson.parent.resourceId) || this.facade.getCanvas();\n            parent.add(shape, shape.parentIndex);\n        }.bind(this));\n        \n        //reconnect shapes\n        this.dockers.each(function(d) {\n            d.object.setDockedShape(d.dockedShape);\n            d.object.setReferencePoint(d.referencePoint);\n        }.bind(this));\n        \n        this.facade.setSelection(this.selectedShapes);\n        this.facade.getCanvas().update();\t\n\t\tthis.facade.updateSelection();\n        \n    }\n});/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * @namespace Oryx name space for plugins\n * @name ORYX.Plugins\n*/\nif(!ORYX.Plugins)\n\tORYX.Plugins = new Object();\n\n/**\n * The view plugin offers all of zooming functionality accessible over the \n * tool bar. This are zoom in, zoom out, zoom to standard, zoom fit to model.\n * \n * @class ORYX.Plugins.View\n * @extends Clazz\n * @param {Object} facade The editor facade for plugins.\n*/\nORYX.Plugins.View = {\n\t/** @lends ORYX.Plugins.View.prototype */\n\tfacade: undefined,\n\n\tconstruct: function(facade, ownPluginData) {\n\t\tthis.facade = facade;\n\t\t//Standard Values\n\t\tthis.zoomLevel = 1.0;\n\t\tthis.maxFitToScreenLevel=1.5;\n\t\tthis.minZoomLevel = 0.1;\n\t\tthis.maxZoomLevel = 2.5;\n\t\tthis.diff=5; //difference between canvas and view port, s.th. like toolbar??\n\t\t\n\t\t//Read properties\n\t\tif (ownPluginData !== undefined && ownPluginData !== null) {\n\t\t\townPluginData.properties.each( function(property) {\t\t\t\n\t\t\t\tif (property.zoomLevel) {this.zoomLevel = Number(1.0);}\t\t\n\t\t\t\tif (property.maxFitToScreenLevel) {this.maxFitToScreenLevel=Number(property.maxFitToScreenLevel);}\n\t\t\t\tif (property.minZoomLevel) {this.minZoomLevel = Number(property.minZoomLevel);}\n\t\t\t\tif (property.maxZoomLevel) {this.maxZoomLevel = Number(property.maxZoomLevel);}\n\t\t\t}.bind(this));\n\t\t}\n\n\t\t\n\t\t/* Register zoom in */\n\t\tthis.facade.offer({\n\t\t\t'name':ORYX.I18N.View.zoomIn,\n\t\t\t'functionality': this.zoom.bind(this, [1.0 + ORYX.CONFIG.ZOOM_OFFSET]),\n\t\t\t'group': ORYX.I18N.View.group,\n\t\t\t'icon': ORYX.PATH + \"images/magnifier_zoom_in.png\",\n\t\t\t'description': ORYX.I18N.View.zoomInDesc,\n\t\t\t'index': 1,\n\t\t\t'minShape': 0,\n\t\t\t'maxShape': 0,\n\t\t\t'isEnabled': function(){return this.zoomLevel < this.maxZoomLevel }.bind(this)});\n\t\t\n\t\t/* Register zoom out */\n\t\tthis.facade.offer({\n\t\t\t'name':ORYX.I18N.View.zoomOut,\n\t\t\t'functionality': this.zoom.bind(this, [1.0 - ORYX.CONFIG.ZOOM_OFFSET]),\n\t\t\t'group': ORYX.I18N.View.group,\n\t\t\t'icon': ORYX.PATH + \"images/magnifier_zoom_out.png\",\n\t\t\t'description': ORYX.I18N.View.zoomOutDesc,\n\t\t\t'index': 2,\n\t\t\t'minShape': 0,\n\t\t\t'maxShape': 0,\n\t\t\t'isEnabled': function(){ return this._checkSize() }.bind(this)});\n\t\t\n\t\t/* Register zoom standard */\n\t\tthis.facade.offer({\n\t\t\t'name':ORYX.I18N.View.zoomStandard,\n\t\t\t'functionality': this.setAFixZoomLevel.bind(this, 1),\n\t\t\t'group': ORYX.I18N.View.group,\n\t\t\t'icon': ORYX.PATH + \"images/zoom_standard.png\",\n\t\t\t'cls' : 'icon-large',\n\t\t\t'description': ORYX.I18N.View.zoomStandardDesc,\n\t\t\t'index': 3,\n\t\t\t'minShape': 0,\n\t\t\t'maxShape': 0,\n\t\t\t'isEnabled': function(){return this.zoomLevel != 1}.bind(this)\n\t\t});\n\t\t\n\t\t/* Register zoom fit to model */\n\t\tthis.facade.offer({\n\t\t\t'name':ORYX.I18N.View.zoomFitToModel,\n\t\t\t'functionality': this.zoomFitToModel.bind(this),\n\t\t\t'group': ORYX.I18N.View.group,\n\t\t\t'icon': ORYX.PATH + \"images/image.png\",\n\t\t\t'description': ORYX.I18N.View.zoomFitToModelDesc,\n\t\t\t'index': 4,\n\t\t\t'minShape': 0,\n\t\t\t'maxShape': 0\n\t\t});\n\t},\n\t\n\t/**\n\t * It sets the zoom level to a fix value and call the zooming function.\n\t * \n\t * @param {Number} zoomLevel\n\t * \t\t\tthe zoom level\n\t */\n\tsetAFixZoomLevel : function(zoomLevel) {\n\t\tthis.zoomLevel = zoomLevel;\n\t\tthis._checkZoomLevelRange();\n\t\tthis.zoom(1);\n\t},\n\t\n\t/**\n\t * It does the actual zooming. It changes the viewable size of the canvas \n\t * and all to its child elements.\n\t * \n\t * @param {Number} factor\n\t * \t\tthe factor to adjust the zoom level\n\t */\n\tzoom: function(factor) {\n\t\t// TODO: Zoomen auf allen Objekten im SVG-DOM\n\t\t\n\t\tthis.zoomLevel *= factor;\n\t\tvar scrollNode \t= this.facade.getCanvas().getHTMLContainer().parentNode.parentNode;\n\t\tvar canvas \t\t= this.facade.getCanvas();\n\t\tvar newWidth \t= canvas.bounds.width()  * this.zoomLevel;\n\t\tvar newHeight \t= canvas.bounds.height() * this.zoomLevel;\n\t\t\n\t\t/* Set new top offset */\n\t\tvar offsetTop = (canvas.node.parentNode.parentNode.parentNode.offsetHeight - newHeight) / 2.0;\t\n\t\toffsetTop = offsetTop > 20 ? offsetTop - 20 : 0;\n\t\tcanvas.node.parentNode.parentNode.style.marginTop = offsetTop + \"px\";\n\t\toffsetTop += 5;\n\t\tcanvas.getHTMLContainer().style.top = offsetTop + \"px\";\n\t\t\n\t\t/*readjust scrollbar*/\n\t\tvar newScrollTop=\tscrollNode.scrollTop - Math.round((canvas.getHTMLContainer().parentNode.getHeight()-newHeight) / 2)+this.diff;\n\t\tvar newScrollLeft=\tscrollNode.scrollLeft - Math.round((canvas.getHTMLContainer().parentNode.getWidth()-newWidth) / 2)+this.diff;\n\t\t\n\t\t/* Set new Zoom-Level */\n\t\tcanvas.setSize({width: newWidth, height: newHeight}, true);\n\t\t\n\t\t/* Set Scale-Factor */\n\t\tcanvas.node.setAttributeNS(null, \"transform\", \"scale(\" +this.zoomLevel+ \")\");\t\n\n\t\t/* Refresh the Selection */\n\t\tthis.facade.updateSelection();\n\t\tscrollNode.scrollTop=newScrollTop;\n\t\tscrollNode.scrollLeft=newScrollLeft;\n\t\t\n\t\t/* Update the zoom-level*/\n\t\tcanvas.zoomLevel = this.zoomLevel;\n\t},\n\t\n\t\n\t/**\n\t * It calculates the zoom level to fit whole model into the visible area\n\t * of the canvas. Than the model gets zoomed and the position of the \n\t * scroll bars are adjusted.\n\t * \n\t */\n\tzoomFitToModel: function() {\n\t\t\n\t\t/* Get the size of the visible area of the canvas */\n\t\tvar scrollNode \t= this.facade.getCanvas().getHTMLContainer().parentNode.parentNode;\n\t\tvar visibleHeight = scrollNode.getHeight() - 30;\n\t\tvar visibleWidth = scrollNode.getWidth() - 30;\n\t\t\n\t\tvar nodes = this.facade.getCanvas().getChildShapes();\n\t\t\n\t\tif(!nodes || nodes.length < 1) {\n\t\t\treturn false;\t\t\t\n\t\t}\n\t\t\t\n\t\t/* Calculate size of canvas to fit the model */\n\t\tvar bounds = nodes[0].absoluteBounds().clone();\n\t\tnodes.each(function(node) {\n\t\t\tbounds.include(node.absoluteBounds().clone());\n\t\t});\n\t\t\n\t\t\n\t\t/* Set new Zoom Level */\n\t\tvar scaleFactorWidth =  visibleWidth / bounds.width();\n\t\tvar scaleFactorHeight = visibleHeight / bounds.height();\n\t\t\n\t\t/* Choose the smaller zoom level to fit the whole model */\n\t\tvar zoomFactor = scaleFactorHeight < scaleFactorWidth ? scaleFactorHeight : scaleFactorWidth;\n\t\t\n\t\t/*Test if maximum zoom is reached*/\n\t\tif(zoomFactor>this.maxFitToScreenLevel){zoomFactor=this.maxFitToScreenLevel}\n\t\t/* Do zooming */\n\t\tthis.setAFixZoomLevel(zoomFactor);\n\t\t\n\t\t/* Set scroll bar position */\n\t\tscrollNode.scrollTop = Math.round(bounds.upperLeft().y * this.zoomLevel) - 5;\n\t\tscrollNode.scrollLeft = Math.round(bounds.upperLeft().x * this.zoomLevel) - 5;\n\t\t\n\t},\n\t\n\t/**\n\t * It checks if the zoom level is less or equal to the level, which is required\n\t * to schow the whole canvas.\n\t * \n\t * @private\n\t */\n\t_checkSize:function(){\n\t\tvar canvasParent=this.facade.getCanvas().getHTMLContainer().parentNode;\n\t\tvar minForCanvas= Math.min((canvasParent.parentNode.getWidth()/canvasParent.getWidth()),(canvasParent.parentNode.getHeight()/canvasParent.getHeight()));\n\t\treturn 1.05 > minForCanvas;\n\t\t\n\t},\n\t/**\n\t * It checks if the zoom level is included in the definined zoom\n\t * level range.\n\t * \n\t * @private\n\t */\n\t_checkZoomLevelRange: function() {\n\t\t/*var canvasParent=this.facade.getCanvas().getHTMLContainer().parentNode;\n\t\tvar maxForCanvas= Math.max((canvasParent.parentNode.getWidth()/canvasParent.getWidth()),(canvasParent.parentNode.getHeight()/canvasParent.getHeight()));\n\t\tif(this.zoomLevel > maxForCanvas) {\n\t\t\tthis.zoomLevel = maxForCanvas;\t\t\t\n\t\t}*/\n\t\tif(this.zoomLevel < this.minZoomLevel) {\n\t\t\tthis.zoomLevel = this.minZoomLevel;\t\t\t\n\t\t}\n\t\t\n\t\tif(this.zoomLevel > this.maxZoomLevel) {\n\t\t\tthis.zoomLevel = this.maxZoomLevel;\t\t\t\n\t\t}\n\t}\n};\n\nORYX.Plugins.View = Clazz.extend(ORYX.Plugins.View);\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\nif(!Signavio){ var Signavio = {} };\n\tif (!Signavio.Core) { Signavio.Core = {} };\n\tSignavio.Core.Version = \"1.0\";\n\t\t\t/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nif (!Signavio) {\n\tvar Signavio = new Object();\n}\n\nif (!Signavio.Plugins) {\n\tSignavio.Plugins = new Object();\n}\n\nif (!Signavio.Plugins.Utils) {\n\tSignavio.Plugins.Utils = new Object();\n}\n\nif (!Signavio.Helper) {\n\tSignavio.Helper = new Object();\n}\n\n\nnew function() {\n\n\t/**\n\t * Provides an uniq id\n\t * @overwrite\n\t * @return {String}\n\t *\n\t */\n\tORYX.Editor.provideId = function() {\n\t\tvar res = [], hex = '0123456789ABCDEF';\n\t\n\t\tfor (var i = 0; i < 36; i++) res[i] = Math.floor(Math.random()*0x10);\n\t\n\t\tres[14] = 4;\n\t\tres[19] = (res[19] & 0x3) | 0x8;\n\t\n\t\tfor (var i = 0; i < 36; i++) res[i] = hex[res[i]];\n\t\n\t\tres[8] = res[13] = res[18] = res[23] = '-';\n\t\n\t\treturn \"sid-\" + res.join('');\n\t};\n\n\n}();\n\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nif (!ORYX.Plugins) {\n    ORYX.Plugins = new Object();\n}\n\n/**\n * This plugin is responsible for displaying loading indicators and to prevent\n * the user from accidently unloading the page by, e.g., pressing the backspace\n * button and returning to the previous site in history.\n * @param {Object} facade The editor plugin facade to register enhancements with.\n */\nORYX.Plugins.Loading = {\n\n    construct: function(facade){\n    \n        this.facade = facade;\n        \n        // The parent Node\n        this.node = ORYX.Editor.graft(\"http://www.w3.org/1999/xhtml\", this.facade.getCanvas().getHTMLContainer().parentNode, ['div', {\n            'class': 'LoadingIndicator'\n        }, '']);\n        \n        this.facade.registerOnEvent(ORYX.CONFIG.EVENT_LOADING_ENABLE, this.enableLoading.bind(this));\n        this.facade.registerOnEvent(ORYX.CONFIG.EVENT_LOADING_DISABLE, this.disableLoading.bind(this));\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_LOADING_STATUS, this.showStatus.bind(this));\n        \n        this.disableLoading();\n    },\n    \n    enableLoading: function(options){\n\t\tif(options.text) \n\t\t\tthis.node.innerHTML = options.text + \"...\";\n\t\telse\n\t\t\tthis.node.innerHTML = ORYX.I18N.Loading.waiting;\n\t\tthis.node.removeClassName('StatusIndicator');\n\t\tthis.node.addClassName('LoadingIndicator');\n        this.node.style.display = \"block\";\n\t\t\n\t\tvar pos = this.facade.getCanvas().rootNode.parentNode.parentNode.parentNode.parentNode;\n\n\t\tthis.node.style.top \t\t= pos.offsetTop + 'px';\n\t\tthis.node.style.left \t\t= pos.offsetLeft +'px';\n\t\t\t\t\t\n    },\n    \n    disableLoading: function(){\n        this.node.style.display = \"none\";\n    },\n\t\n\tshowStatus: function(options) {\n\t\tif(options.text) {\n\t\t\tthis.node.innerHTML = options.text;\n\t\t\tthis.node.addClassName('StatusIndicator');\n\t\t\tthis.node.removeClassName('LoadingIndicator');\n\t\t\tthis.node.style.display = 'block';\n\n\t\t\tvar pos = this.facade.getCanvas().rootNode.parentNode.parentNode.parentNode.parentNode;\n\n\t\t\tthis.node.style.top \t= pos.offsetTop + 'px';\n\t\t\tthis.node.style.left \t= pos.offsetLeft +'px';\n\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\tvar tout = options.timeout ? options.timeout : 2000;\n\t\t\t\n\t\t\twindow.setTimeout((function(){\n            \n                this.disableLoading();\n                \n            }).bind(this), tout);\n\t\t}\n\t\t\n\t}\n}\n\nORYX.Plugins.Loading = Clazz.extend(ORYX.Plugins.Loading);\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\nif (!ORYX.Plugins) {\n    ORYX.Plugins = new Object();\n}\n\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * This plugin is responsible for resizing the canvas.\n * @param {Object} facade The editor plugin facade to register enhancements with.\n */\nORYX.Plugins.CanvasResize = Clazz.extend({\n\n    construct: function(facade){\n\t\t\n        this.facade = facade;\n\t\tnew ORYX.Plugins.CanvasResizeButton( this.facade.getCanvas(), \"N\", this.resize.bind(this));\n\t\tnew ORYX.Plugins.CanvasResizeButton( this.facade.getCanvas(), \"W\", this.resize.bind(this));\n\t\tnew ORYX.Plugins.CanvasResizeButton( this.facade.getCanvas(), \"E\", this.resize.bind(this));\n\t\tnew ORYX.Plugins.CanvasResizeButton( this.facade.getCanvas(), \"S\", this.resize.bind(this));\n\t\t\n\t\twindow.setTimeout(function(){jQuery(window).trigger('resize');});\n\n    },\n    \n    resize: function( position, shrink ){\n    \t\n    \tresizeCanvas = function(position, extentionSize, facade) {\n        \tvar canvas \t\t= facade.getCanvas();\n    \t\tvar b \t\t\t= canvas.bounds;\n    \t\tvar scrollNode \t= facade.getCanvas().getHTMLContainer().parentNode.parentNode;\n    \t\t\n    \t\tif( position == \"E\" || position == \"W\"){\n    \t\t\tcanvas.setSize({width: (b.width() + extentionSize)*canvas.zoomLevel, height: (b.height())*canvas.zoomLevel})\n\n    \t\t} else if( position == \"S\" || position == \"N\"){\n    \t\t\tcanvas.setSize({width: (b.width())*canvas.zoomLevel, height: (b.height() + extentionSize)*canvas.zoomLevel})\n    \t\t}\n\n    \t\tif( position == \"N\" || position == \"W\"){\n    \t\t\t\n    \t\t\tvar move = position == \"N\" ? {x: 0, y: extentionSize}: {x: extentionSize, y: 0 };\n\n    \t\t\t// Move all children\n    \t\t\tcanvas.getChildNodes(false, function(shape){ shape.bounds.moveBy(move) })\n    \t\t\t// Move all dockers, when the edge has at least one docked shape\n    \t\t\tvar edges = canvas.getChildEdges().findAll(function(edge){ return edge.getAllDockedShapes().length > 0})\n    \t\t\tvar dockers = edges.collect(function(edge){ return edge.dockers.findAll(function(docker){ return !docker.getDockedShape() })}).flatten();\n    \t\t\tdockers.each(function(docker){ docker.bounds.moveBy(move)})\n    \t\t} else if( position == \"S\" ){\n    \t\t\tscrollNode.scrollTop += extentionSize;\n    \t\t} else if( position == \"E\" ){\n    \t\t\tscrollNode.scrollLeft += extentionSize;\n    \t\t}\n    \t\t\n    \t\tjQuery(window).trigger('resize');\n    \t\t\n    \t\tcanvas.update();\n    \t\tfacade.updateSelection();\n        }\n\t\t\n\t\tvar commandClass = ORYX.Core.Command.extend({\n\t\t\tconstruct: function(position, extentionSize, facade){\n\t\t\t\tthis.position = position;\n\t\t\t\tthis.extentionSize = extentionSize;\n\t\t\t\tthis.facade = facade;\n\t\t\t},\t\t\t\n\t\t\texecute: function(){\n\t\t\t\tresizeCanvas(this.position, this.extentionSize, this.facade);\n\t\t\t},\n\t\t\trollback: function(){\n\t\t\t\tresizeCanvas(this.position, -this.extentionSize, this.facade);\n\t\t\t},\n\t\t\tupdate:function(){\n\t\t\t}\n\t\t});\n\t\t\n\t\tvar extentionSize = ORYX.CONFIG.CANVAS_RESIZE_INTERVAL;\n\t\tif(shrink) extentionSize = -extentionSize;\n\t\tvar command = new commandClass(position, extentionSize, this.facade);\n\t\t\n\t\tthis.facade.executeCommands([command]);\n\t\t\t\n    }\n    \n});\n\n\nORYX.Plugins.CanvasResizeButton = Clazz.extend({\n\t\n\tconstruct: function(canvas, position, callback){\n\t\tthis.canvas = canvas;\n\t\tvar parentNode = canvas.getHTMLContainer().parentNode;\n\t\t\n\t\twindow.myParent=parentNode;\n\t\t\t\n\t\tvar actualScrollNode = jQuery('#canvasSection')[0];\n\t\tvar scrollNode \t= actualScrollNode;\n\t\tvar canvasNode = jQuery('#canvasSection').find(\".ORYX_Editor\")[0];\n\t\tvar svgRootNode = canvasNode.children[0];\n\t\t\n\t\tvar iconClass = 'glyphicon glyphicon-chevron-';\n\t\tvar iconClassShrink = 'glyphicon glyphicon-chevron-';\n\t\tif(position == 'N') {\n\t\t\ticonClass += 'up';\n\t\t\ticonClassShrink += 'down';\n\t\t} else if(position == 'S') {\n\t\t\ticonClass += 'down';\n\t\t\ticonClassShrink += 'up';\n\t\t} else if(position == 'E') {\n\t\t\ticonClass += 'right';\n\t\t\ticonClassShrink += 'left';\n\t\t} else if(position == 'W') {\n\t\t\ticonClass += 'left';\n\t\t\ticonClassShrink += 'right';\n\t\t}\n\t\t\n\t\t// The buttons\n\t\tvar idGrow = 'canvas-shrink-' + position;\n\t\tvar idShrink = 'canvas-grow-' + position;\n\t\t\n\t\tvar buttonGrow \t= ORYX.Editor.graft(\"http://www.w3.org/1999/xhtml\", parentNode, ['div', {'class': 'canvas_resize_indicator canvas_resize_indicator_grow' + ' ' + position, 'id': idGrow ,'title':ORYX.I18N.RESIZE.tipGrow+ORYX.I18N.RESIZE[position]},\n             ['i', {'class' : iconClass}]\n\t\t]);\n\t\tvar buttonShrink \t= ORYX.Editor.graft(\"http://www.w3.org/1999/xhtml\", parentNode, ['div', {'class': 'canvas_resize_indicator canvas_resize_indicator_shrink' + ' ' + position, 'id': idShrink ,'title':ORYX.I18N.RESIZE.tipGrow+ORYX.I18N.RESIZE[position]},\n             ['i', {'class' : iconClassShrink}]\n\t\t]);\n\t\t// Defines a callback which gives back\n\t\t// a boolean if the current mouse event \n\t\t// is over the particular button area\n\t\tvar offSetWidth = 60;\n\t\tvar isOverOffset = function(event) {\n\t\t\t\n\t\t\tvar isOverButton = event.target.id.indexOf(\"canvas-shrink\") != -1\n\t\t\t\t|| event.target.id.indexOf(\"canvas-grow\") != -1\n\t\t\t\t|| event.target.parentNode.id.indexOf(\"canvas-shrink\") != -1\n\t\t\t\t|| event.target.parentNode.id.indexOf(\"canvas-grow\") != -1;\n\t\t\tif(isOverButton) {\n\t\t\t\tif(event.target.id == idGrow || event.target.id == idShrink || \n\t\t\t\t\t\tevent.target.parentNode.id == idGrow || event.target.parentNode.id == idShrink ) {\n\t\t\t\t\treturn true;\n\t\t\t\t} else {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif(event.target!=parentNode && event.target!=scrollNode&& event.target!=scrollNode.firstChild&& event.target!=svgRootNode&& event.target!=scrollNode){ return false; }\n\t\t\t\n\t\t\t//if(inCanvas){offSetWidth=30}else{offSetWidth=30*2}\n\t\t\t//Safari work around\n\t\t\tvar X=event.offsetX !== undefined ? event.offsetX : event.layerX;\n\t\t\tvar Y=event.offsetY !== undefined ? event.offsetY : event.layerY;\n\t\t\t\n\t\t\tvar canvasOffset = 0;\n\t\t\tif(canvasNode.clientWidth < actualScrollNode.clientWidth) {\n              \tvar widthDiff = actualScrollNode.clientWidth -  canvasNode.clientWidth;\n              \tcanvasOffset = widthDiff / 2;\n            }\n\t\t\t\n\t\t\t\t// Adjust to relative location to the actual viewport\n\t\t\t\tY = Y - actualScrollNode.scrollTop;\n\t\t\t\tX = X - actualScrollNode.scrollLeft;\n\t\t\t\n\t\t\t\n\t\t\tif(position == \"N\"){\n\t\t\t\treturn  Y < offSetWidth;\n\t\t\t} else if(position == \"W\"){\n\t\t\t\treturn X < offSetWidth + canvasOffset;\n\t\t\t} else if(position == \"E\"){\n\t\t\t\treturn actualScrollNode.clientWidth - X < offSetWidth + canvasOffset;\n\t\t\t} else if(position == \"S\"){\n\t\t\t\treturn actualScrollNode.clientHeight - Y < offSetWidth;\n\t\t\t}\n\t\t\t\n\t\t\treturn false;\n\t\t};\n\t\t\n\t\tvar showButtons = (function() {\n\t\t\tbuttonGrow.show(); \n        \n\t\t\tvar w = canvas.bounds.width();\n\t\t\tvar h = canvas.bounds.height();\n        \n\t\t\tif(position==\"N\" && (h - ORYX.CONFIG.CANVAS_RESIZE_INTERVAL > ORYX.CONFIG.CANVAS_MIN_HEIGHT)) buttonShrink.show();\n\t\t\telse if(position==\"E\" && (w - ORYX.CONFIG.CANVAS_RESIZE_INTERVAL > ORYX.CONFIG.CANVAS_MIN_WIDTH)) buttonShrink.show();\n\t\t\telse if(position==\"S\" && (h - ORYX.CONFIG.CANVAS_RESIZE_INTERVAL > ORYX.CONFIG.CANVAS_MIN_HEIGHT)) buttonShrink.show();\n\t\t\telse if(position==\"W\" && (w - ORYX.CONFIG.CANVAS_RESIZE_INTERVAL > ORYX.CONFIG.CANVAS_MIN_WIDTH)) buttonShrink.show();\n\t\t\telse buttonShrink.hide();\n\t\t\t\n\n\t\t}).bind(this);\n        \n\t\tvar hideButtons = function() {\n\t\t\tbuttonGrow.hide(); \n\t\t\tbuttonShrink.hide();\n\t\t};\n        \n\t\t// If the mouse move is over the button area, show the button\n\t\tparentNode.parentNode.addEventListener(\tORYX.CONFIG.EVENT_MOUSEMOVE, \tfunction(event){ if( isOverOffset(event) ){showButtons();} else {hideButtons()}} , false );\n\t\t// If the mouse is over the button, show them\n\t\tbuttonGrow.addEventListener(\t\tORYX.CONFIG.EVENT_MOUSEOVER, \tfunction(event){showButtons();}, true );\n\t\tbuttonShrink.addEventListener(\t\tORYX.CONFIG.EVENT_MOUSEOVER, \tfunction(event){showButtons();}, true );\n\t\t// If the mouse is out, hide the button\n\t\t//scrollNode.addEventListener(\t\tORYX.CONFIG.EVENT_MOUSEOUT, \tfunction(event){button.hide()}, true )\n\t\tparentNode.parentNode.addEventListener(\tORYX.CONFIG.EVENT_MOUSEOUT, \tfunction(event){hideButtons()} , true );\n\t\t//svgRootNode.addEventListener(\tORYX.CONFIG.EVENT_MOUSEOUT, \tfunction(event){ inCanvas = false } , true );\n        \n\t\t// Hide the button initialy\n\t\thideButtons();\n\n\t\t// Add the callbacks\n\t    buttonGrow.addEventListener('click', function(){callback( position ); showButtons();}, true);\n\t    buttonShrink.addEventListener('click', function(){callback( position, true ); showButtons();}, true);\n\n\t}\n\t\n\n});\n\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nif (!ORYX.Plugins) \n    ORYX.Plugins = new Object();\n\nORYX.Plugins.RenameShapes = Clazz.extend({\n\n    facade: undefined,\n    \n    construct: function(facade){\n    \n        this.facade = facade;\n      \t\n        this.facade.registerOnEvent(ORYX.CONFIG.EVENT_CANVAS_SCROLL, this.hideField.bind(this)); \n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_DBLCLICK, this.actOnDBLClick.bind(this)); \n\t\tthis.facade.offer({\n\t\t keyCodes: [{\n\t\t\t\tkeyCode: 113, // F2-Key\n\t\t\t\tkeyAction: ORYX.CONFIG.KEY_ACTION_DOWN \n\t\t\t}\n\t\t ],\n         functionality: this.renamePerF2.bind(this)\n         });\n\t\t\n\t\t\n\t\tdocument.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEDOWN, this.hide.bind(this), true);\n    },\n\t\n\t/**\n\t * This method handles the \"F2\" key down event. The selected shape are looked\n\t * up and the editing of title/name of it gets started.\n\t */\n\trenamePerF2 : function() {\n\t\tvar selectedShapes = this.facade.getSelection();\n\t\tthis.actOnDBLClick(undefined, selectedShapes.first());\n\t},\n\t\n\tactOnDBLClick: function(evt, shape){\n\t\t\n\t\tif( !(shape instanceof ORYX.Core.Shape) ){ return; }\n\t\t\n\t\t// Destroys the old input, if there is one\n\t\tthis.destroy();\n\t\t\n\t\t// Get all properties which where at least one ref to view is set\n\t\tvar props = shape.getStencil().properties().findAll(function(item){ \n\t\t\treturn (item.refToView() \n\t\t\t\t\t&&  item.refToView().length > 0\n\t\t\t\t\t&&\titem.directlyEditable()); \n\t\t});\n\t\t// from these, get all properties where write access are and the type is String or Expression\n\t\tprops = props.findAll(function(item){ return !item.readonly() &&  (item.type() == ORYX.CONFIG.TYPE_STRING || item.type() == ORYX.CONFIG.TYPE_EXPRESSION || item.type() == ORYX.CONFIG.TYPE_DATASOURCE); });\n\t\t\n\t\t// Get all ref ids\n\t\tvar allRefToViews\t= props.collect(function(prop){ return prop.refToView(); }).flatten().compact();\n\t\t// Get all labels from the shape with the ref ids\n\t\tvar labels\t\t\t= shape.getLabels().findAll(function(label){ return allRefToViews.any(function(toView){ return label.id.endsWith(toView); }); });\n\t\t\n\t\t// If there are no referenced labels --> return\n\t\tif( labels.length == 0 ){ return; } \n\t\t\n\t\t// Define the nearest label\n\t\tvar nearestLabel \t= labels.length <= 1 ? labels[0] : null;\t\n\t\tif( !nearestLabel ){\n\t\t\tnearestLabel = labels.find(function(label){ return label.node == evt.target || label.node == evt.target.parentNode; });\n\t\t\tif( !nearestLabel ){\n\t\t\t\t\n\t\t\t\tvar evtCoord \t= this.facade.eventCoordinates(evt);\n\t\t\t\t\n\t\t\t\tvar additionalIEZoom = 1;\n                if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) {\n                    var ua = navigator.userAgent;\n                    if (ua.indexOf('MSIE') >= 0) {\n                        //IE 10 and below\n                        var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100);\n                        if (zoom !== 100) {\n                            additionalIEZoom = zoom / 100\n                        }\n                    }\n                }\n                \n                if (additionalIEZoom !== 1) {\n                     evtCoord.x = evtCoord.x / additionalIEZoom;\n                     evtCoord.y = evtCoord.y / additionalIEZoom;\n                }\n\n\t\t\t\tevtCoord.y += $(\"editor-header\").clientHeight - $(\"canvasSection\").scrollTop - 5;\n\t\t\t\tif (KISBPM.HEADER_CONFIG.showAppTitle == false)\n\t\t\t\t{\n\t\t\t\t\tevtCoord.y += 61;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tevtCoord.x -= $(\"canvasSection\").scrollLeft;\n\t\t\t\t\n\t\t\t\tvar trans\t\t= this.facade.getCanvas().rootNode.lastChild.getScreenCTM();\n\t\t\t\tevtCoord.x\t\t*= trans.a;\n\t\t\t\tevtCoord.y\t\t*= trans.d;\n\n\t\t\t\tvar diff = labels.collect(function(label){ \n\t\t\t\t\t\t\tvar center \t= this.getCenterPosition( label.node ); \n\t\t\t\t\t\t\tvar len \t= Math.sqrt( Math.pow(center.x - evtCoord.x, 2) + Math.pow(center.y - evtCoord.y, 2));\n\t\t\t\t\t\t\treturn {diff: len, label: label}; \n\t\t\t\t\t\t}.bind(this));\n\t\t\t\t\n\t\t\t\tdiff.sort(function(a, b){ return a.diff > b.diff; });\n\t\t\t\t\n\t\t\t\tnearestLabel = \tdiff[0].label;\n\n\t\t\t}\n\t\t}\n\t\t// Get the particular property for the label\n\t\tvar prop \t\t\t= props.find(function(item){ return item.refToView().any(function(toView){ return nearestLabel.id == shape.id + toView; });});\n\t\t\n\t\t// Get the center position from the nearest label\n\t\tvar width\t\t= Math.min(Math.max(100, shape.bounds.width()), 200);\n\t\tvar center \t\t= this.getCenterPosition( nearestLabel.node, shape );\n\t\tcenter.x\t\t-= (width/2);\n\t\tvar propId\t\t= prop.prefix() + \"-\" + prop.id();\n\t\tvar textInput = document.createElement(\"textarea\");\n\t\ttextInput.id = 'shapeTextInput';\n\t\ttextInput.style.position = 'absolute';\n\t\ttextInput.style.width = width + 'px';\n\t\ttextInput.style.left = (center.x < 10) ? 10 : center.x + 'px';\n\t\ttextInput.style.top = (center.y - 15) + 'px';\n\t\ttextInput.className = 'x-form-textarea x-form-field x_form_text_set_absolute';\n\t\ttextInput.value = shape.properties[propId];\n\t\tthis.oldValueText = shape.properties[propId];\n\t\tdocument.getElementById('canvasSection').appendChild(textInput);\n\t\tthis.shownTextField = textInput;\n\t\t\n\t\t\n\t\t// Value change listener needs to be defined now since we reference it in the text field\n\t\tthis.updateValueFunction = function(newValue, oldValue) {\n\t\t\tvar currentEl \t= shape;\n\t\t\tvar facade\t\t= this.facade;\n\t\t\t\n\t\t\tif (oldValue != newValue) {\n\t\t\t\t// Implement the specific command for property change\n\t\t\t\tvar commandClass = ORYX.Core.Command.extend({\n\t\t\t\t\tconstruct: function(){\n\t\t\t\t\t\tthis.el = currentEl;\n\t\t\t\t\t\tthis.propId = propId;\n\t\t\t\t\t\tthis.oldValue = oldValue;\n\t\t\t\t\t\tthis.newValue = newValue;\n\t\t\t\t\t\tthis.facade = facade;\n\t\t\t\t\t},\n\t\t\t\t\texecute: function(){\n\t\t\t\t\t\tthis.el.setProperty(this.propId, this.newValue);\n\t\t\t\t\t\t//this.el.update();\n\t\t\t\t\t\tthis.facade.setSelection([this.el]);\n\t\t\t\t\t\tthis.facade.getCanvas().update();\n\t\t\t\t\t\tthis.facade.updateSelection();\n\t\t\t\t\t},\n\t\t\t\t\trollback: function(){\n\t\t\t\t\t\tthis.el.setProperty(this.propId, this.oldValue);\n\t\t\t\t\t\t//this.el.update();\n\t\t\t\t\t\tthis.facade.setSelection([this.el]);\n\t\t\t\t\t\tthis.facade.getCanvas().update();\n\t\t\t\t\t\tthis.facade.updateSelection();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t// Instantiated the class\n\t\t\t\tvar command = new commandClass();\n\t\t\t\t\n\t\t\t\t// Execute the command\n\t\t\t\tthis.facade.executeCommands([command]);\n\t\t\t}\n\t\t}.bind(this);\n\t\t\t\n\t\tjQuery(\"#shapeTextInput\").focus();\n\t\t\n\t\tjQuery(\"#shapeTextInput\").autogrow();\n\t\t\t\n\t\t// Disable the keydown in the editor (that when hitting the delete button, the shapes not get deleted)\n\t\tthis.facade.disableEvent(ORYX.CONFIG.EVENT_KEYDOWN);\n\t\t\n\t},\n\t\n\tgetCenterPosition: function(svgNode, shape){\n\t\t\n\t\tif (!svgNode) { return {x:0, y:0}; }\n\t\t\n\t\tvar scale = this.facade.getCanvas().node.getScreenCTM();\n\t\tvar absoluteXY = shape.bounds.upperLeft();\n\t\t\n\t\tvar hasParent = true;\n\t\tvar searchShape = shape;\n\t\twhile (hasParent)\n\t\t{\n\t\t\tif (searchShape.getParentShape().getStencil().idWithoutNs() === 'BPMNDiagram')\n\t\t\t{\n\t\t\t\thasParent = false;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tvar parentXY = searchShape.getParentShape().bounds.upperLeft();\n\t\t\t\tabsoluteXY.x += parentXY.x;\n\t\t\t\tabsoluteXY.y += parentXY.y;\n\t\t\t\tsearchShape = searchShape.getParentShape();\n\t\t\t}\n\t\t}\n\t\t\n\t\tvar center = shape.bounds.midPoint();\n\t\tcenter.x += absoluteXY.x + scale.e;\n\t\tcenter.y += absoluteXY.y + scale.f;\n\t\t\n\t\tcenter.x *= scale.a;\n\t\tcenter.y *= scale.d;\n\t\t\n\t\tvar additionalIEZoom = 1;\n        if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) {\n            var ua = navigator.userAgent;\n            if (ua.indexOf('MSIE') >= 0) {\n                //IE 10 and below\n                var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100);\n                if (zoom !== 100) {\n                    additionalIEZoom = zoom / 100\n                }\n            }\n        }\n        \n        if (additionalIEZoom === 1) {\n             center.y = center.y - jQuery(\"#canvasSection\").offset().top + 5;\n             center.x -= jQuery(\"#canvasSection\").offset().left;\n        \n        } else {\n             var canvasOffsetLeft = jQuery(\"#canvasSection\").offset().left;\n             var canvasScrollLeft = jQuery(\"#canvasSection\").scrollLeft();\n             var canvasScrollTop = jQuery(\"#canvasSection\").scrollTop();\n             \n             var offset = scale.e - (canvasOffsetLeft * additionalIEZoom);\n             var additionaloffset = 0;\n             if (offset > 10) {\n                 additionaloffset = (offset / additionalIEZoom) - offset;\n             }\n             center.y = center.y - (jQuery(\"#canvasSection\").offset().top * additionalIEZoom) + 5 + ((canvasScrollTop * additionalIEZoom) - canvasScrollTop);\n             center.x = center.x - (canvasOffsetLeft * additionalIEZoom) + additionaloffset + ((canvasScrollLeft * additionalIEZoom) - canvasScrollLeft);\n        }\n\t\t\n\t\n\t\treturn center;\t\t\t\n\t},\n\t\n\thide: function(e){\n\t\tif (this.shownTextField && (!e || e.target !== this.shownTextField)) {\n\t\t\tvar newValue = this.shownTextField.value;\n\t\t\tif (newValue !== this.oldValueText)\n\t\t\t{\n\t\t\t\tthis.updateValueFunction(newValue, this.oldValueText);\n\t\t\t}\n\t\t\tthis.destroy();\n\t\t}\n\t},\n\t\n\thideField: function(e){\n\t\tif (this.shownTextField) {\n\t\t\tthis.destroy();\n\t\t}\n\t},\n\t\n\tdestroy: function(e){\n\t\tvar textInputComp = jQuery(\"#shapeTextInput\");\n\t\tif( textInputComp ){\n\t\t\ttextInputComp.remove(); \n\t\t\tdelete this.shownTextField; \n\t\t\t\n\t\t\tthis.facade.enableEvent(ORYX.CONFIG.EVENT_KEYDOWN);\n\t\t}\n\t}\n});\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nif(!ORYX.Plugins)\n\tORYX.Plugins = new Object();\n\n/**\n * Supports EPCs by offering a syntax check and export and import ability..\n * \n * \n */\nORYX.Plugins.ProcessLink = Clazz.extend({\n\n\tfacade: undefined,\n\n\t/**\n\t * Offers the plugin functionality:\n\t * \n\t */\n\tconstruct: function(facade) {\n\n\t\tthis.facade = facade;\n\t\t\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_PROPERTY_CHANGED, this.propertyChanged.bind(this) );\n\t\t\n\t},\n\n\n\t/**\n\t * \n\t * @param {Object} option\n\t */\n\tpropertyChanged: function( option, node){\n\n\t\tif( option.name !== \"oryx-refuri\" || !node instanceof ORYX.Core.Node ){ return }\n\t\t\n\t\t\n\t\tif( option.value && option.value.length > 0 && option.value != \"undefined\"){\n\t\t\t\n\t\t\tthis.show( node, option.value );\n\t\t\t\t\t\n\t\t} else {\n\n\t\t\tthis.hide( node );\n\n\t\t}\t\t\t\t\n\n\t},\n\t\n\t/**\n\t * Shows the Link for a particular shape with a specific url\n\t * \n\t * @param {Object} shape\n\t * @param {Object} url\n\t */\n\tshow: function( shape, url){\n\n\t\t\n\t\t// Generate the svg-representation of a link\n\t\tvar link  = ORYX.Editor.graft(\"http://www.w3.org/2000/svg\", null ,\n\t\t\t\t\t[ 'a',\n\t\t\t\t\t\t{'target': '_blank'},\n\t\t\t\t\t\t['path', \n\t\t\t\t\t\t\t{ \"stroke-width\": 1.0, \"stroke\":\"#00DD00\", \"fill\": \"#00AA00\", \"d\":  \"M3,3 l0,-2.5 l7.5,0 l0,-2.5 l7.5,4.5 l-7.5,3.5 l0,-2.5 l-8,0\", \"line-captions\": \"round\"}\n\t\t\t\t\t\t]\n\t\t\t\t\t]);\n\n\t\tvar link  = ORYX.Editor.graft(\"http://www.w3.org/2000/svg\", null ,\t\t\n\t\t\t\t\t\t[ 'a',\n\t\t\t\t\t\t\t{'target': '_blank'},\n\t\t\t\t\t\t\t['path', { \"style\": \"fill:#92BFFC;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.72\", \"d\": \"M0 1.44 L0 15.05 L11.91 15.05 L11.91 5.98 L7.37 1.44 L0 1.44 Z\"}],\n\t\t\t\t\t\t\t['path', { \"style\": \"stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.72;fill:none;\", \"transform\": \"translate(7.5, -8.5)\", \"d\": \"M0 10.51 L0 15.05 L4.54 15.05\"}],\n\t\t\t\t\t\t\t['path', { \"style\": \"fill:#f28226;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.72\", \"transform\": \"translate(-3, -1)\", \"d\": \"M0 8.81 L0 13.06 L5.95 13.06 L5.95 15.05 A50.2313 50.2313 -175.57 0 0 10.77 11.08 A49.9128 49.9128 -1.28 0 0 5.95 6.54 L5.95 8.81 L0 8.81 Z\"}],\n\t\t\t\t\t\t]);\n\n\t/*\n\t * \n\t * \t\t\t\t\t[ 'a',\n\t\t\t\t\t\t{'target': '_blank'},\n\t\t\t\t\t\t['path', { \"style\": \"fill:none;stroke-width:0.5px; stroke:#000000\", \"d\": \"M7,4 l0,2\"}],\n\t\t\t\t\t\t['path', { \"style\": \"fill:none;stroke-width:0.5px; stroke:#000000\", \"d\": \"M4,8 l-2,0 l0,6\"}],\n\t\t\t\t\t\t['path', { \"style\": \"fill:none;stroke-width:0.5px; stroke:#000000\", \"d\": \"M10,8 l2,0 l0,6\"}],\n\t\t\t\t\t\t['rect', { \"style\": \"fill:#96ff96;stroke:#000000;stroke-width:1\", \"width\": 6, \"height\": 4, \"x\": 4, \"y\": 0}],\n\t\t\t\t\t\t['rect', { \"style\": \"fill:#ffafff;stroke:#000000;stroke-width:1\", \"width\": 6, \"height\": 4, \"x\": 4, \"y\": 6}],\n\t\t\t\t\t\t['rect', { \"style\": \"fill:#96ff96;stroke:#000000;stroke-width:1\", \"width\": 6, \"height\": 4, \"x\": 0, \"y\": 12}],\n\t\t\t\t\t\t['rect', { \"style\": \"fill:#96ff96;stroke:#000000;stroke-width:1\", \"width\": 6, \"height\": 4, \"x\": 8, \"y\": 12}],\n\t\t\t\t\t\t['rect', { \"style\": \"fill:none;stroke:none;pointer-events:all\", \"width\": 14, \"height\": 16, \"x\": 0, \"y\": 0}]\n\t\t\t\t\t]);\n\t */\n\t\t\n\t\t// Set the link with the special namespace\n\t\tlink.setAttributeNS(\"http://www.w3.org/1999/xlink\", \"xlink:href\", url);\n\t\t\n\t\t\n\t\t// Shows the link in the overlay\t\t\t\t\t\n\t\tthis.facade.raiseEvent({\n\t\t\t\t\ttype: \t\t\tORYX.CONFIG.EVENT_OVERLAY_SHOW,\n\t\t\t\t\tid: \t\t\t\"arissupport.urlref_\" + shape.id,\n\t\t\t\t\tshapes: \t\t[shape],\n\t\t\t\t\tnode:\t\t\tlink,\n\t\t\t\t\tnodePosition:\t\"SE\"\n\t\t\t\t});\t\n\t\t\t\t\t\t\t\n\t},\t\n\n\t/**\n\t * Hides the Link for a particular shape\n\t * \n\t * @param {Object} shape\n\t */\n\thide: function( shape ){\n\n\t\tthis.facade.raiseEvent({\n\t\t\t\t\ttype: \t\t\tORYX.CONFIG.EVENT_OVERLAY_HIDE,\n\t\t\t\t\tid: \t\t\t\"arissupport.urlref_\" + shape.id\n\t\t\t\t});\t\n\t\t\t\t\t\t\t\n\t}\t\t\n});/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nArray.prototype.insertFrom = function(from, to){\n\tto \t\t\t= Math.max(0, to);\n\tfrom \t\t= Math.min( Math.max(0, from), this.length-1 );\n\t\t\n\tvar el \t\t= this[from];\n\tvar old \t= this.without(el);\n\tvar newA \t= old.slice(0, to);\n\tnewA.push(el);\n\tif(old.length > to ){\n\t\tnewA \t= newA.concat(old.slice(to))\n\t};\n\treturn newA;\n}\n\nif(!ORYX.Plugins)\n\tORYX.Plugins = new Object();\n\nORYX.Plugins.Arrangement = ORYX.Plugins.AbstractPlugin.extend({\n\n\tfacade: undefined,\n\n\tconstruct: function(facade) {\n\t\tthis.facade = facade;\n\n\t\t// Z-Ordering\n\t\t/** Hide for SIGNAVIO \n\t\t\n\t\tthis.facade.offer({\n\t\t\t'name':ORYX.I18N.Arrangement.btf,\n\t\t\t'functionality': this.setZLevel.bind(this, this.setToTop),\n\t\t\t'group': ORYX.I18N.Arrangement.groupZ,\n\t\t\t'icon': ORYX.PATH + \"images/shape_move_front.png\",\n\t\t\t'description': ORYX.I18N.Arrangement.btfDesc,\n\t\t\t'index': 1,\n\t\t\t'minShape': 1});\n\t\t\t\n\t\tthis.facade.offer({\n\t\t\t'name':ORYX.I18N.Arrangement.btb,\n\t\t\t'functionality': this.setZLevel.bind(this, this.setToBack),\n\t\t\t'group': ORYX.I18N.Arrangement.groupZ,\n\t\t\t'icon': ORYX.PATH + \"images/shape_move_back.png\",\n\t\t\t'description': ORYX.I18N.Arrangement.btbDesc,\n\t\t\t'index': 2,\n\t\t\t'minShape': 1});\n\n\t\tthis.facade.offer({\n\t\t\t'name':ORYX.I18N.Arrangement.bf,\n\t\t\t'functionality': this.setZLevel.bind(this, this.setForward),\n\t\t\t'group': ORYX.I18N.Arrangement.groupZ,\n\t\t\t'icon': ORYX.PATH + \"images/shape_move_forwards.png\",\n\t\t\t'description': ORYX.I18N.Arrangement.bfDesc,\n\t\t\t'index': 3,\n\t\t\t'minShape': 1});\n\n\t\tthis.facade.offer({\n\t\t\t'name':ORYX.I18N.Arrangement.bb,\n\t\t\t'functionality': this.setZLevel.bind(this, this.setBackward),\n\t\t\t'group': ORYX.I18N.Arrangement.groupZ,\n\t\t\t'icon': ORYX.PATH + \"images/shape_move_backwards.png\",\n\t\t\t'description': ORYX.I18N.Arrangement.bbDesc,\n\t\t\t'index': 4,\n\t\t\t'minShape': 1});\n\n\t\t// Aligment\n\t\tthis.facade.offer({\n\t\t\t'name':ORYX.I18N.Arrangement.ab,\n\t\t\t'functionality': this.alignShapes.bind(this, [ORYX.CONFIG.EDITOR_ALIGN_BOTTOM]),\n\t\t\t'group': ORYX.I18N.Arrangement.groupA,\n\t\t\t'icon': ORYX.PATH + \"images/shape_align_bottom.png\",\n\t\t\t'description': ORYX.I18N.Arrangement.abDesc,\n\t\t\t'index': 1,\n\t\t\t'minShape': 2});\n\n\n\n\t\tthis.facade.offer({\n\t\t\t'name':ORYX.I18N.Arrangement.at,\n\t\t\t'functionality': this.alignShapes.bind(this, [ORYX.CONFIG.EDITOR_ALIGN_TOP]),\n\t\t\t'group': ORYX.I18N.Arrangement.groupA,\n\t\t\t'icon': ORYX.PATH + \"images/shape_align_top.png\",\n\t\t\t'description': ORYX.I18N.Arrangement.atDesc,\n\t\t\t'index': 3,\n\t\t\t'minShape': 2});\n\n\t\tthis.facade.offer({\n\t\t\t'name':ORYX.I18N.Arrangement.al,\n\t\t\t'functionality': this.alignShapes.bind(this, [ORYX.CONFIG.EDITOR_ALIGN_LEFT]),\n\t\t\t'group': ORYX.I18N.Arrangement.groupA,\n\t\t\t'icon': ORYX.PATH + \"images/shape_align_left.png\",\n\t\t\t'description': ORYX.I18N.Arrangement.alDesc,\n\t\t\t'index': 4,\n\t\t\t'minShape': 2});\n\n\t\tthis.facade.offer({\n\t\t\t'name':ORYX.I18N.Arrangement.ar,\n\t\t\t'functionality': this.alignShapes.bind(this, [ORYX.CONFIG.EDITOR_ALIGN_RIGHT]),\n\t\t\t'group': ORYX.I18N.Arrangement.groupA,\n\t\t\t'icon': ORYX.PATH + \"images/shape_align_right.png\",\n\t\t\t'description': ORYX.I18N.Arrangement.arDesc,\n\t\t\t'index': 6,\n\t\t\t'minShape': 2});\n\n\t\t**/\n\t\t\n\t\tthis.facade.offer({\n\t\t\t'name':ORYX.I18N.Arrangement.am,\n\t\t\t'functionality': this.alignShapes.bind(this, [ORYX.CONFIG.EDITOR_ALIGN_MIDDLE]),\n\t\t\t'group': ORYX.I18N.Arrangement.groupA,\n\t\t\t'icon': ORYX.PATH + \"images/shape_align_middle.png\",\n\t\t\t'description': ORYX.I18N.Arrangement.amDesc,\n\t\t\t'index': 1,\n\t\t\t'minShape': 2});\n\t\t\t\n\t\tthis.facade.offer({\n\t\t\t'name':ORYX.I18N.Arrangement.ac,\n\t\t\t'functionality': this.alignShapes.bind(this, [ORYX.CONFIG.EDITOR_ALIGN_CENTER]),\n\t\t\t'group': ORYX.I18N.Arrangement.groupA,\n\t\t\t'icon': ORYX.PATH + \"images/shape_align_center.png\",\n\t\t\t'description': ORYX.I18N.Arrangement.acDesc,\n\t\t\t'index': 2,\n\t\t\t'minShape': 2});\n\n\t\t\t\n\t\tthis.facade.offer({\n\t\t\t'name':ORYX.I18N.Arrangement.as,\n\t\t\t'functionality': this.alignShapes.bind(this, [ORYX.CONFIG.EDITOR_ALIGN_SIZE]),\n\t\t\t'group': ORYX.I18N.Arrangement.groupA,\n\t\t\t'icon': ORYX.PATH + \"images/shape_align_size.png\",\n\t\t\t'description': ORYX.I18N.Arrangement.asDesc,\n\t\t\t'index': 3,\n\t\t\t'minShape': 2});\n\t\t\t\n\n\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_ARRANGEMENT_TOP, \tthis.setZLevel.bind(this, this.setToTop)\t);\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_ARRANGEMENT_BACK, \tthis.setZLevel.bind(this, this.setToBack)\t);\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_ARRANGEMENT_FORWARD, \tthis.setZLevel.bind(this, this.setForward)\t);\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_ARRANGEMENT_BACKWARD, \tthis.setZLevel.bind(this, this.setBackward)\t);\t\t\t\t\t\t\n\n\t\n\t},\n\t\n\tonSelectionChanged: function(elemnt){\n\t\tvar selection = this.facade.getSelection();\n\t\tif (selection.length === 1 && selection[0] instanceof ORYX.Core.Edge) {\n\t\t\tthis.setToTop(selection);\n\t\t}\n\t},\n\t\n\tsetZLevel:function(callback, event){\n\t\t\t\n\t\t//Command-Pattern for dragging one docker\n\t\tvar zLevelCommand = ORYX.Core.Command.extend({\n\t\t\tconstruct: function(callback, elements, facade){\n\t\t\t\tthis.callback \t= callback;\n\t\t\t\tthis.elements \t= elements;\n\t\t\t\t// For redo, the previous elements get stored\n\t\t\t\tthis.elAndIndex\t= elements.map(function(el){ return {el:el, previous:el.parent.children[el.parent.children.indexOf(el)-1]} })\n\t\t\t\tthis.facade\t\t= facade;\n\t\t\t},\t\t\t\n\t\t\texecute: function(){\n\t\t\t\t\n\t\t\t\t// Call the defined z-order callback with the elements\n\t\t\t\tthis.callback( this.elements )\t\t\t\n\t\t\t\tthis.facade.setSelection( this.elements )\n\t\t\t},\n\t\t\trollback: function(){\n\t\t\t\t\n\t\t\t\t// Sort all elements on the index of there containment\n\t\t\t\tvar sortedEl =\tthis.elAndIndex.sortBy( function( el ) {\n\t\t\t\t\t\t\t\t\tvar value \t= el.el;\n\t\t\t\t\t\t\t\t\tvar t \t\t= $A(value.node.parentNode.childNodes);\n\t\t\t\t\t\t\t\t\treturn t.indexOf(value.node);\n\t\t\t\t\t\t\t\t}); \n\t\t\t\t\n\t\t\t\t// Every element get setted back bevor the old previous element\n\t\t\t\tfor(var i=0; i<sortedEl.length; i++){\n\t\t\t\t\tvar el\t\t\t= sortedEl[i].el;\n\t\t\t\t\tvar p \t\t\t= el.parent;\t\t\t\n\t\t\t\t\tvar oldIndex \t= p.children.indexOf(el);\n\t\t\t\t\tvar newIndex \t= p.children.indexOf(sortedEl[i].previous);\n\t\t\t\t\tnewIndex\t\t= newIndex || 0\n\t\t\t\t\tp.children \t= p.children.insertFrom(oldIndex, newIndex)\t\t\t\n\t\t\t\t\tel.node.parentNode.insertBefore(el.node, el.node.parentNode.childNodes[newIndex+1]);\n\t\t\t\t}\n\n\t\t\t\t// Reset the selection\n\t\t\t\tthis.facade.setSelection( this.elements )\n\t\t\t}\n\t\t});\n\t\n\t\t// Instanziate the dockCommand\n\t\tvar command = new zLevelCommand(callback, this.facade.getSelection(), this.facade);\n\t\tif( event.excludeCommand ){\n\t\t\tcommand.execute();\n\t\t} else {\n\t\t\tthis.facade.executeCommands( [command] );\t\n\t\t}\n\t\t\n\t},\n\n\tsetToTop: function(elements) {\n\n\t\t// Sortieren des Arrays nach dem Index des SVGKnotens im Bezug auf dem Elternknoten.\n\t\tvar tmpElem =  elements.sortBy( function(value, index) {\n\t\t\tvar t = $A(value.node.parentNode.childNodes);\n\t\t\treturn t.indexOf(value.node);\n\t\t});\n\t\t// Sortiertes Array wird nach oben verschoben.\n\t\ttmpElem.each( function(value) {\n\t\t\tvar p = value.parent;\n\t\t\tif (p.children.last() === value){\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tp.children = p.children.without( value )\n\t\t\tp.children.push(value);\n\t\t\tvalue.node.parentNode.appendChild(value.node);\t\t\t\n\t\t});\n\t},\n\n\tsetToBack: function(elements) {\n\t\t// Sortieren des Arrays nach dem Index des SVGKnotens im Bezug auf dem Elternknoten.\n\t\tvar tmpElem =  elements.sortBy( function(value, index) {\n\t\t\tvar t = $A(value.node.parentNode.childNodes);\n\t\t\treturn t.indexOf(value.node);\n\t\t});\n\n\t\ttmpElem = tmpElem.reverse();\n\n\t\t// Sortiertes Array wird nach unten verschoben.\n\t\ttmpElem.each( function(value) {\n\t\t\tvar p = value.parent\n\t\t\tp.children = p.children.without( value )\n\t\t\tp.children.unshift( value );\n\t\t\tvalue.node.parentNode.insertBefore(value.node, value.node.parentNode.firstChild);\n\t\t});\n\t\t\n\t\t\n\t},\n\n\tsetBackward: function(elements) {\n\t\t// Sortieren des Arrays nach dem Index des SVGKnotens im Bezug auf dem Elternknoten.\n\t\tvar tmpElem =  elements.sortBy( function(value, index) {\n\t\t\tvar t = $A(value.node.parentNode.childNodes);\n\t\t\treturn t.indexOf(value.node);\n\t\t});\n\n\t\t// Reverse the elements\n\t\ttmpElem = tmpElem.reverse();\n\t\t\n\t\t// Delete all Nodes who are the next Node in the nodes-Array\n\t\tvar compactElem = tmpElem.findAll(function(el) {return !tmpElem.some(function(checkedEl){ return checkedEl.node == el.node.previousSibling})});\n\t\t\n\t\t// Sortiertes Array wird nach eine Ebene nach oben verschoben.\n\t\tcompactElem.each( function(el) {\n\t\t\tif(el.node.previousSibling === null) { return; }\n\t\t\tvar p \t\t= el.parent;\t\t\t\n\t\t\tvar index \t= p.children.indexOf(el);\n\t\t\tp.children \t= p.children.insertFrom(index, index-1)\t\t\t\n\t\t\tel.node.parentNode.insertBefore(el.node, el.node.previousSibling);\n\t\t});\n\t\t\n\t\t\n\t},\n\n\tsetForward: function(elements) {\n\t\t// Sortieren des Arrays nach dem Index des SVGKnotens im Bezug auf dem Elternknoten.\n\t\tvar tmpElem =  elements.sortBy( function(value, index) {\n\t\t\tvar t = $A(value.node.parentNode.childNodes);\n\t\t\treturn t.indexOf(value.node);\n\t\t});\n\n\n\t\t// Delete all Nodes who are the next Node in the nodes-Array\n\t\tvar compactElem = tmpElem.findAll(function(el) {return !tmpElem.some(function(checkedEl){ return checkedEl.node == el.node.nextSibling})});\n\t\n\t\t\t\n\t\t// Sortiertes Array wird eine Ebene nach unten verschoben.\n\t\tcompactElem.each( function(el) {\n\t\t\tvar nextNode = el.node.nextSibling\t\t\n\t\t\tif(nextNode === null) { return; }\n\t\t\tvar index \t= el.parent.children.indexOf(el);\n\t\t\tvar p \t\t= el.parent;\n\t\t\tp.children \t= p.children.insertFrom(index, index+1)\t\t\t\n\t\t\tel.node.parentNode.insertBefore(nextNode, el.node);\n\t\t});\n\t},\n\n\n\talignShapes: function(way) {\n\n\t\tvar elements = this.facade.getSelection();\n\n\t\t// Set the elements to all Top-Level elements\n\t\telements = this.facade.getCanvas().getShapesWithSharedParent(elements);\n\t\t// Get only nodes\n\t\telements = elements.findAll(function(value) {\n\t\t\treturn (value instanceof ORYX.Core.Node)\n\t\t});\n\t\t// Delete all attached intermediate events from the array\n\t\telements = elements.findAll(function(value) {\n\t\t\tvar d = value.getIncomingShapes()\n\t\t\treturn d.length == 0 || !elements.include(d[0])\n\t\t});\n\t\tif(elements.length < 2) { return; }\n\n\t\t// get bounds of all shapes.\n\t\tvar bounds = elements[0].absoluteBounds().clone();\n\t\telements.each(function(shape) {\n\t\t        bounds.include(shape.absoluteBounds().clone());\n\t\t});\n\t\t\n\t\t// get biggest width and heigth\n\t\tvar maxWidth = 0;\n\t\tvar maxHeight = 0;\n\t\telements.each(function(shape){\n\t\t\tmaxWidth = Math.max(shape.bounds.width(), maxWidth);\n\t\t\tmaxHeight = Math.max(shape.bounds.height(), maxHeight);\n\t\t});\n\n\t\tvar commandClass = ORYX.Core.Command.extend({\n\t\t\tconstruct: function(elements, bounds, maxHeight, maxWidth, way, plugin){\n\t\t\t\tthis.elements = elements;\n\t\t\t\tthis.bounds = bounds;\n\t\t\t\tthis.maxHeight = maxHeight;\n\t\t\t\tthis.maxWidth = maxWidth;\n\t\t\t\tthis.way = way;\n\t\t\t\tthis.facade = plugin.facade;\n\t\t\t\tthis.plugin = plugin;\n\t\t\t\tthis.orgPos = [];\n\t\t\t},\n\t\t\tsetBounds: function(shape, maxSize) {\n\t\t\t\tif(!maxSize)\n\t\t\t\t\tmaxSize = {width: ORYX.CONFIG.MAXIMUM_SIZE, height: ORYX.CONFIG.MAXIMUM_SIZE};\n\n\t\t\t\tif(!shape.bounds) { throw \"Bounds not definined.\" }\n\t\t\t\t\n\t\t\t\tvar newBounds = {\n                    a: {x: shape.bounds.upperLeft().x - (this.maxWidth - shape.bounds.width())/2,\n                        y: shape.bounds.upperLeft().y - (this.maxHeight - shape.bounds.height())/2},\n                    b: {x: shape.bounds.lowerRight().x + (this.maxWidth - shape.bounds.width())/2,\n                        y: shape.bounds.lowerRight().y + (this.maxHeight - shape.bounds.height())/2}\n\t            }\n\t\t\t\t\n\t\t\t\t/* If the new width of shape exceeds the maximum width, set width value to maximum. */\n\t\t\t\tif(this.maxWidth > maxSize.width) {\n\t\t\t\t\tnewBounds.a.x = shape.bounds.upperLeft().x - \n\t\t\t\t\t\t\t\t\t(maxSize.width - shape.bounds.width())/2;\n\t\t\t\t\t\n\t\t\t\t\tnewBounds.b.x =\tshape.bounds.lowerRight().x + (maxSize.width - shape.bounds.width())/2\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t/* If the new height of shape exceeds the maximum height, set height value to maximum. */\n\t\t\t\tif(this.maxHeight > maxSize.height) {\n\t\t\t\t\tnewBounds.a.y = shape.bounds.upperLeft().y - \n\t\t\t\t\t\t\t\t\t(maxSize.height - shape.bounds.height())/2;\n\t\t\t\t\t\n\t\t\t\t\tnewBounds.b.y =\tshape.bounds.lowerRight().y + (maxSize.height - shape.bounds.height())/2\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t/* set bounds of shape */\n\t\t\t\tshape.bounds.set(newBounds);\n\t\t\t\t\n\t\t\t},\t\t\t\n\t\t\texecute: function(){\n\t\t\t\t// align each shape according to the way that was specified.\n\t\t\t\tthis.elements.each(function(shape, index) {\n\t\t\t\t\tthis.orgPos[index] = shape.bounds.upperLeft();\n\t\t\t\t\t\n\t\t\t\t\tvar relBounds = this.bounds.clone();\n\t\t\t\t\tvar newCoordinates;\n\t\t\t\t\tif (shape.parent && !(shape.parent instanceof ORYX.Core.Canvas) ) {\n\t\t\t\t\t\tvar upL = shape.parent.absoluteBounds().upperLeft();\n\t\t\t\t\t\trelBounds.moveBy(-upL.x, -upL.y);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tswitch (this.way) {\n\t\t\t\t\t\t// align the shapes in the requested way.\n\t\t\t\t\t\tcase ORYX.CONFIG.EDITOR_ALIGN_BOTTOM:\n\t\t\t                newCoordinates = {\n\t\t\t\t\t\t\t\tx: shape.bounds.upperLeft().x,\n\t\t\t\t\t\t\t\ty: relBounds.b.y - shape.bounds.height()\n\t\t\t\t\t\t\t}; break;\n\t\t\n\t\t\t\t        case ORYX.CONFIG.EDITOR_ALIGN_MIDDLE:\n\t\t\t                newCoordinates = {\n\t\t\t\t\t\t\t\tx: shape.bounds.upperLeft().x,\n\t\t\t\t\t\t\t\ty: (relBounds.a.y + relBounds.b.y - shape.bounds.height()) / 2\n\t\t\t\t\t\t\t}; break;\n\t\t\n\t\t\t\t        case ORYX.CONFIG.EDITOR_ALIGN_TOP:\n\t\t\t                newCoordinates = {\n\t\t\t\t\t\t\t\tx: shape.bounds.upperLeft().x,\n\t\t\t\t\t\t\t\ty: relBounds.a.y\n\t\t\t\t\t\t\t}; break;\n\t\t\n\t\t\t\t        case ORYX.CONFIG.EDITOR_ALIGN_LEFT:\n\t\t\t                newCoordinates = {\n\t\t\t\t\t\t\t\tx: relBounds.a.x,\n\t\t\t\t\t\t\t\ty: shape.bounds.upperLeft().y\n\t\t\t\t\t\t\t}; break;\n\t\t\n\t\t\t\t        case ORYX.CONFIG.EDITOR_ALIGN_CENTER:\n\t\t\t                newCoordinates = {\n\t\t\t\t\t\t\t\tx: (relBounds.a.x + relBounds.b.x - shape.bounds.width()) / 2,\n\t\t\t\t\t\t\t\ty: shape.bounds.upperLeft().y\n\t\t\t\t\t\t\t}; break;\n\t\t\n\t\t\t\t        case ORYX.CONFIG.EDITOR_ALIGN_RIGHT:\n\t\t\t                newCoordinates = {\n\t\t\t\t\t\t\t\tx: relBounds.b.x - shape.bounds.width(),\n\t\t\t\t\t\t\t\ty: shape.bounds.upperLeft().y\n\t\t\t\t\t\t\t}; break;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\tcase ORYX.CONFIG.EDITOR_ALIGN_SIZE:\n\t\t\t\t\t\t\tif(shape.isResizable) {\n\t\t\t\t\t\t\t\tthis.orgPos[index] = {a: shape.bounds.upperLeft(), b: shape.bounds.lowerRight()};\n\t\t\t\t\t\t\t\tthis.setBounds(shape, shape.maximumSize);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif (newCoordinates){\n\t\t\t\t\t\tvar offset =  {\n\t\t\t\t\t\t\tx: shape.bounds.upperLeft().x - newCoordinates.x,\n\t\t\t\t\t\t\ty: shape.bounds.upperLeft().y - newCoordinates.y\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Set the new position\n\t\t\t\t\t\tshape.bounds.moveTo(newCoordinates);\n\t\t\t\t\t\tthis.plugin.layoutEdges(shape, shape.getAllDockedShapes(),offset);\n\t\t\t\t\t\t//shape.update()\n\t\t\t\t\t}\t\t\t\n\t\t\t\t}.bind(this));\n\t\t\n\t\t\t\t//this.facade.getCanvas().update();\n\t\t\t\t//this.facade.updateSelection();\n\t\t\t},\n\t\t\trollback: function(){\n\t\t\t\tthis.elements.each(function(shape, index) {\n\t\t\t\t\tif (this.way == ORYX.CONFIG.EDITOR_ALIGN_SIZE) {\n\t\t\t\t\t\tif(shape.isResizable) {shape.bounds.set(this.orgPos[index]);}\n\t\t\t\t\t} else {shape.bounds.moveTo(this.orgPos[index]);}\n\t\t\t\t}.bind(this));\n\t\t\t\t\n\t\t\t\t//this.facade.getCanvas().update();\n\t\t\t\t//this.facade.updateSelection();\n\t\t\t}\n\t\t})\n\t\t\n\t\tvar command = new commandClass(elements, bounds, maxHeight, maxWidth, parseInt(way), this);\n\t\t\n\t\tthis.facade.executeCommands([command]);\t\n\t}\n});/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nif (!ORYX.Plugins) \n    ORYX.Plugins = new Object();\n\nORYX.Plugins.Save = Clazz.extend({\n\t\n    facade: undefined,\n\t\n\tprocessURI: undefined,\n\t\n\tchangeSymbol : \"*\",\n\t\n    construct: function(facade){\n\t\tthis.facade = facade;\n\t\t\n\t\tdocument.addEventListener(\"keydown\", function(e){\n\t\t\tif (e.ctrlKey&&e.keyCode === 83){\n\t\t\t\tEvent.stop(e);\n\t\t\t}\n\t\t}, false);\n\t\t\n\t\twindow.onbeforeunload = this.onUnLoad.bind(this);\n\t\t\n\t\tthis.changeDifference = 0;\n\t\t\n\t\t// Register on event for executing commands --> store all commands in a stack\t\t \n\t\t// --> Execute\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_UNDO_EXECUTE, function(){ this.changeDifference++; this.updateTitle(); }.bind(this) );\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_EXECUTE_COMMANDS, function(){ this.changeDifference++; this.updateTitle(); }.bind(this) );\n\t\t// --> Saved from other places in the editor\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_SAVED, function(){ this.changeDifference = 0; this.updateTitle(); }.bind(this) );\n\t\t\n\t\t// --> Rollback\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_UNDO_ROLLBACK, function(){ this.changeDifference--; this.updateTitle(); }.bind(this) );\n\t\t\n\t\t//TODO very critical for load time performance!!!\n\t\t//this.serializedDOM = DataManager.__persistDOM(this.facade);\n\t\t\n\t\tthis.hasChanges = this._hasChanges.bind(this);\n\t},\n\t\n\tupdateTitle: function(){\n\t\t\n\t\tvar value = window.document.title || document.getElementsByTagName(\"title\")[0].childNodes[0].nodeValue;\n\t\t\n\t\tif (this.changeDifference === 0 && value.startsWith(this.changeSymbol)){\n\t\t\twindow.document.title = value.slice(1);\n\t\t} else if (this.changeDifference !== 0 && !value.startsWith(this.changeSymbol)){\n\t\t\twindow.document.title = this.changeSymbol + \"\" + value;\n\t\t}\n\t},\n\t\n\t_hasChanges: function() {\n\t  return this.changeDifference !== 0 || (this.facade.getModelMetaData()['new'] && this.facade.getCanvas().getChildShapes().size() > 0);\n\t},\n\t\n\tonUnLoad: function(){\n\t\tif(this._hasChanges()) {\n\t\t\treturn ORYX.I18N.Save.unsavedData;\n\t\t}\t\n\t}\n});\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nif(!ORYX.Plugins) \n\tORYX.Plugins = new Object();\n\nORYX.Plugins.DragDropResize = ORYX.Plugins.AbstractPlugin.extend({\n\n\t/**\n\t *\tConstructor\n\t *\t@param {Object} Facade: The Facade of the Editor\n\t */\n\tconstruct: function(facade) {\n\t\tthis.facade = facade;\n\n\t\t// Initialize variables\n\t\tthis.currentShapes \t\t= [];\t\t\t// Current selected Shapes\n\t\t//this.pluginsData \t\t= [];\t\t\t// Available Plugins\n\t\tthis.toMoveShapes \t\t= [];\t\t\t// Shapes there will be moved\n\t\tthis.distPoints \t\t= [];\t\t\t// Distance Points for Snap on Grid\n\t\tthis.isResizing \t\t= false;\t\t// Flag: If there was currently resized\n\t\tthis.dragEnable \t\t= false;\t\t// Flag: If Dragging is enabled\n\t\tthis.dragIntialized \t= false;\t\t// Flag: If the Dragging is initialized\n\t\tthis.edgesMovable\t\t= true;\t\t\t// Flag: If an edge is docked it is not movable\n\t\tthis.offSetPosition \t= {x: 0, y: 0};\t// Offset of the Dragging\n\t\tthis.faktorXY \t\t\t= {x: 1, y: 1};\t// The Current Zoom-Faktor\n\t\tthis.containmentParentNode;\t\t\t\t// the current future parent node for the dragged shapes\n\t\tthis.isAddingAllowed \t= false;\t\t// flag, if adding current selected shapes to containmentParentNode is allowed\n\t\tthis.isAttachingAllowed = false;\t\t// flag, if attaching to the current shape is allowed\n\t\t\n\t\tthis.callbackMouseMove\t= this.handleMouseMove.bind(this);\n\t\tthis.callbackMouseUp\t= this.handleMouseUp.bind(this);\n\t\t\n\t\t// Get the SVG-Containernode \n\t\tvar containerNode = this.facade.getCanvas().getSvgContainer();\n\t\t\n\t\t// Create the Selected Rectangle in the SVG\n\t\tthis.selectedRect = new ORYX.Plugins.SelectedRect(containerNode);\n\t\t\n\t\t// Show grid line if enabled\n\t\tif (ORYX.CONFIG.SHOW_GRIDLINE) {\n\t\t\tthis.vLine = new ORYX.Plugins.GridLine(containerNode, ORYX.Plugins.GridLine.DIR_VERTICAL);\n\t\t\tthis.hLine = new ORYX.Plugins.GridLine(containerNode, ORYX.Plugins.GridLine.DIR_HORIZONTAL);\n\t\t}\n\t\t\n\t\t// Get a HTML-ContainerNode\n\t\tcontainerNode = this.facade.getCanvas().getHTMLContainer();\n\t\t\n\t\tthis.scrollNode = this.facade.getCanvas().rootNode.parentNode.parentNode;\n\t\t\n\t\t// Create the southeastern button for resizing\n\t\tthis.resizerSE = new ORYX.Plugins.Resizer(containerNode, \"southeast\", this.facade);\n\t\tthis.resizerSE.registerOnResize(this.onResize.bind(this)); // register the resize callback\n\t\tthis.resizerSE.registerOnResizeEnd(this.onResizeEnd.bind(this)); // register the resize end callback\n\t\tthis.resizerSE.registerOnResizeStart(this.onResizeStart.bind(this)); // register the resize start callback\n\t\t\n\t\t// Create the northwestern button for resizing\n\t\tthis.resizerNW = new ORYX.Plugins.Resizer(containerNode, \"northwest\", this.facade);\n\t\tthis.resizerNW.registerOnResize(this.onResize.bind(this)); // register the resize callback\n\t\tthis.resizerNW.registerOnResizeEnd(this.onResizeEnd.bind(this)); // register the resize end callback\n\t\tthis.resizerNW.registerOnResizeStart(this.onResizeStart.bind(this)); // register the resize start callback\n\t\t\n\t\t// For the Drag and Drop\n\t\t// Register on MouseDown-Event on a Shape\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_MOUSEDOWN, this.handleMouseDown.bind(this));\n\t},\n\n\t/**\n\t * On Mouse Down\n\t *\n\t */\n\thandleMouseDown: function(event, uiObj) {\n\t\t// If the selection Bounds not intialized and the uiObj is not member of current selectio\n\t\t// then return\n\t\tif(!this.dragBounds || !this.currentShapes.member(uiObj) || !this.toMoveShapes.length) {return;};\n\t\t\n\t\t// Start Dragging\n\t\tthis.dragEnable = true;\n\t\tthis.dragIntialized = true;\n\t\tthis.edgesMovable = true;\n\n\t\t// Calculate the current zoom factor\n\t\tvar a = this.facade.getCanvas().node.getScreenCTM();\n\t\tthis.faktorXY.x = a.a;\n\t\tthis.faktorXY.y = a.d;\n\t\t\n\t\tvar eventX = Event.pointerX(event);\n\t\tvar eventY = Event.pointerY(event);\n\n\t\t// Set the offset position of dragging\n\t\tvar upL = this.dragBounds.upperLeft();\n\t\tthis.offSetPosition =  {\n\t\t\tx: eventX - (upL.x * this.faktorXY.x),\n\t\t\ty: eventY - (upL.y * this.faktorXY.y)};\n\t\t\n\t\tthis.offsetScroll\t= {x:this.scrollNode.scrollLeft,y:this.scrollNode.scrollTop};\n\t\t\t\n\t\t// Register on Global Mouse-MOVE Event\n\t\tdocument.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, this.callbackMouseMove, false);\t\n\t\t// Register on Global Mouse-UP Event\n\t\tdocument.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEUP, this.callbackMouseUp, true);\t\t\t\n\n\t\treturn;\n\t},\n\n\t/**\n\t * On Key Mouse Up\n\t *\n\t */\n\thandleMouseUp: function(event) {\n\t\t\n\t\t//disable containment highlighting\n\t\tthis.facade.raiseEvent({\n\t\t\t\t\t\t\t\t\ttype:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,\n\t\t\t\t\t\t\t\t\thighlightId:\"dragdropresize.contain\"\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\n\t\tthis.facade.raiseEvent({\n\t\t\t\t\t\t\t\t\ttype:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,\n\t\t\t\t\t\t\t\t\thighlightId:\"dragdropresize.attached\"\n\t\t\t\t\t\t\t\t});\n\n\t\t// If Dragging is finished\n\t\tif(this.dragEnable) {\n\t\t\n\t\t\t// and update the current selection\n\t\t\tif(!this.dragIntialized) {\n\t\t\t\t\n\t\t\t\t// Do Method after Dragging\n\t\t\t\tthis.afterDrag();\t\n\t\t\t\t\n\t\t\t\t// Check if the Shape is allowed to dock to the other Shape\t\t\t\t\t\t\n\t\t\t\tif ( \tthis.isAttachingAllowed &&\n\t\t\t\t\t\tthis.toMoveShapes.length == 1 && this.toMoveShapes[0] instanceof ORYX.Core.Node  &&\n\t\t\t\t\t\tthis.toMoveShapes[0].dockers.length > 0) {\n\t\t\t\t\t\n\t\t\t\t\t// Get the position and the docker\t\t\t\t\t\n\t\t\t\t\tvar position \t= this.facade.eventCoordinates( event );\t\n\t\t\t\t\tvar docker \t\t= this.toMoveShapes[0].dockers[0];\n\n\n\t\t\t\n\t\t\t\t\t//Command-Pattern for dragging several Shapes\n\t\t\t\t\tvar dockCommand = ORYX.Core.Command.extend({\n\t\t\t\t\t\tconstruct: function(docker, position, newDockedShape, facade){\n\t\t\t\t\t\t\tthis.docker \t\t= docker;\n\t\t\t\t\t\t\tthis.newPosition\t= position;\n\t\t\t\t\t\t\tthis.newDockedShape = newDockedShape;\n\t\t\t\t\t\t\tthis.newParent \t\t= newDockedShape.parent || facade.getCanvas();\n\t\t\t\t\t\t\tthis.oldPosition\t= docker.parent.bounds.center();\n\t\t\t\t\t\t\tthis.oldDockedShape\t= docker.getDockedShape();\n\t\t\t\t\t\t\tthis.oldParent \t\t= docker.parent.parent || facade.getCanvas();\n\t\t\t\t\t\t\tthis.facade\t\t\t= facade;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif( this.oldDockedShape ){\n\t\t\t\t\t\t\t\tthis.oldPosition = docker.parent.absoluteBounds().center();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t},\t\t\t\n\t\t\t\t\t\texecute: function(){\n\t\t\t\t\t\t\tthis.dock( this.newDockedShape, this.newParent,  this.newPosition );\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t// Raise Event for having the docked shape on top of the other shape\n\t\t\t\t\t\t\tthis.facade.raiseEvent({type:ORYX.CONFIG.EVENT_ARRANGEMENT_TOP, excludeCommand: true})\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t},\n\t\t\t\t\t\trollback: function(){\n\t\t\t\t\t\t\tthis.dock( this.oldDockedShape, this.oldParent, this.oldPosition );\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdock:function( toDockShape, parent, pos ){\n\t\t\t\t\t\t\t// Add to the same parent Shape\n\t\t\t\t\t\t\tparent.add( this.docker.parent )\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t// Set the Docker to the new Shape\n\t\t\t\t\t\t\tthis.docker.setDockedShape( undefined );\n\t\t\t\t\t\t\tthis.docker.bounds.centerMoveTo( pos )\t\t\t\t\n\t\t\t\t\t\t\tthis.docker.setDockedShape( toDockShape );\t\n\t\t\t\t\t\t\t//this.docker.update();\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tthis.facade.setSelection( [this.docker.parent] );\t\n\t\t\t\t\t\t\tthis.facade.getCanvas().update();\n\t\t\t\t\t\t\tthis.facade.updateSelection();\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\n\t\t\t\t\t// Instanziate the dockCommand\n\t\t\t\t\tvar commands = [new dockCommand(docker, position, this.containmentParentNode, this.facade)];\n\t\t\t\t\tthis.facade.executeCommands(commands);\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t// Check if adding is allowed to the other Shape\t\n\t\t\t\t} else if( this.isAddingAllowed ) {\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t// Refresh all Shapes --> Set the new Bounds\n\t\t\t\t\tthis.refreshSelectedShapes();\n\t\t\t\t\t\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tthis.facade.updateSelection();\n\t\t\t\t\t\t\t\n\t\t\t\t//this.currentShapes.each(function(shape) {shape.update()})\n\t\t\t\t// Raise Event: Dragging is finished\n\t\t\t\tthis.facade.raiseEvent({type:ORYX.CONFIG.EVENT_DRAGDROP_END});\n\t\t\t}\t\n\n\t\t\tif (this.vLine)\n\t\t\t\tthis.vLine.hide();\n\t\t\tif (this.hLine)\n\t\t\t\tthis.hLine.hide();\n\t\t}\n\n\t\t// Disable \n\t\tthis.dragEnable = false;\t\n\t\t\n\n\t\t// UnRegister on Global Mouse-UP/-Move Event\n\t\tdocument.documentElement.removeEventListener(ORYX.CONFIG.EVENT_MOUSEUP, this.callbackMouseUp, true);\t\n\t\tdocument.documentElement.removeEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, this.callbackMouseMove, false);\t\t\t\t\n\t\t\t\n\t\treturn;\n\t},\n\n\t/**\n\t* On Key Mouse Move\n\t*\n\t*/\n\thandleMouseMove: function(event) {\n\t\t// If dragging is not enabled, go return\n\t\tif(!this.dragEnable) { return };\n\t\t// If Dragging is initialized\n\t\tif(this.dragIntialized) {\n\t\t\t// Raise Event: Drag will be started\n\t\t\tthis.facade.raiseEvent({type:ORYX.CONFIG.EVENT_DRAGDROP_START});\n\t\t\tthis.dragIntialized = false;\n\t\t\t\n\t\t\t// And hide the resizers and the highlighting\n\t\t\tthis.resizerSE.hide();\n\t\t\tthis.resizerNW.hide();\n\t\t\t\n\t\t\t// if only edges are selected, containmentParentNode must be the canvas\n\t\t\tthis._onlyEdges = this.currentShapes.all(function(currentShape) {\n\t\t\t\treturn (currentShape instanceof ORYX.Core.Edge);\n\t\t\t});\n\t\t\t\n\t\t\t// Do method before Drag\n\t\t\tthis.beforeDrag();\n\t\t\t\n\t\t\tthis._currentUnderlyingNodes = [];\n\t\t\t\n\t\t}\n\n\t\t\t\n\t\t// Calculate the new position\n\t\tvar position = {\n\t\t\tx: Event.pointerX(event) - this.offSetPosition.x,\n\t\t\ty: Event.pointerY(event) - this.offSetPosition.y}\n\n\t\tposition.x \t-= this.offsetScroll.x - this.scrollNode.scrollLeft; \n\t\tposition.y \t-= this.offsetScroll.y - this.scrollNode.scrollTop;\n\t\t\n\t\t// If not the Control-Key are pressed\n\t\tvar modifierKeyPressed = event.shiftKey || event.ctrlKey;\n\t\tif(ORYX.CONFIG.GRID_ENABLED && !modifierKeyPressed) {\n\t\t\t// Snap the current position to the nearest Snap-Point\n\t\t\tposition = this.snapToGrid(position);\n\t\t} else {\n\t\t\tif (this.vLine)\n\t\t\t\tthis.vLine.hide();\n\t\t\tif (this.hLine)\n\t\t\t\tthis.hLine.hide();\n\t\t}\n\n\t\t// Adjust the point by the zoom faktor \n\t\tposition.x /= this.faktorXY.x;\n\t\tposition.y /= this.faktorXY.y;\n\n\t\t// Set that the position is not lower than zero\n\t\tposition.x = Math.max( 0 , position.x)\n\t\tposition.y = Math.max( 0 , position.y)\n\n\t\t// Set that the position is not bigger than the canvas\n\t\tvar c = this.facade.getCanvas();\n\t\tposition.x = Math.min( c.bounds.width() - this.dragBounds.width(), \t\tposition.x)\n\t\tposition.y = Math.min( c.bounds.height() - this.dragBounds.height(), \tposition.y)\t\n\t\t\t\t\t\t\n\n\t\t// Drag this bounds\n\t\tthis.dragBounds.moveTo(position);\n\n\t\t// Update all selected shapes and the selection rectangle\n\t\t//this.refreshSelectedShapes();\n\t\tthis.resizeRectangle(this.dragBounds);\n\n\t\tthis.isAttachingAllowed = false;\n\n\t\t//check, if a node can be added to the underlying node\n\t\tvar eventCoordinates = this.facade.eventCoordinates(event);\n\t\t\n\t\tvar additionalIEZoom = 1;\n        if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) {\n            var ua = navigator.userAgent;\n            if (ua.indexOf('MSIE') >= 0) {\n                //IE 10 and below\n                var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100);\n                if (zoom !== 100) {\n                    additionalIEZoom = zoom / 100\n                }\n            }\n        }\n        \n        if (additionalIEZoom !== 1) {\n             eventCoordinates.x = eventCoordinates.x / additionalIEZoom;\n             eventCoordinates.y = eventCoordinates.y / additionalIEZoom;\n        }\n\t\t\n\t\tvar underlyingNodes = $A(this.facade.getCanvas().getAbstractShapesAtPosition(eventCoordinates));\n\t\t\n\t\tvar checkIfAttachable = this.toMoveShapes.length == 1 && this.toMoveShapes[0] instanceof ORYX.Core.Node && this.toMoveShapes[0].dockers.length > 0\n\t\tcheckIfAttachable\t= checkIfAttachable && underlyingNodes.length != 1\n\t\t\n\t\t\t\n\t\tif (!checkIfAttachable &&\n\t\t\t\tunderlyingNodes.length === this._currentUnderlyingNodes.length  &&\n\t\t\t\tunderlyingNodes.all(function(node, index){return this._currentUnderlyingNodes[index] === node}.bind(this))) {\n\t\t\t\t\t\n\t\t\treturn\n\t\t\t\n\t\t} else if(this._onlyEdges) {\n\t\t\t\n\t\t\tthis.isAddingAllowed = true;\n\t\t\tthis.containmentParentNode = this.facade.getCanvas();\n\t\t\t\n\t\t} else {\n\t\t\n\t\t\t/* Check the containment and connection rules */\n\t\t\tvar options = {\n\t\t\t\tevent : event,\n\t\t\t\tunderlyingNodes : underlyingNodes,\n\t\t\t\tcheckIfAttachable : checkIfAttachable\n\t\t\t};\n\t\t\tthis.checkRules(options);\n\t\t\t\t\t\t\t\n\t\t}\n\t\t\n\t\tthis._currentUnderlyingNodes = underlyingNodes.reverse();\n\t\t\n\t\t//visualize the containment result\n\t\tif( this.isAttachingAllowed ) {\n\t\t\t\n\t\t\tthis.facade.raiseEvent({\n\t\t\t\t\t\t\t\t\ttype: \t\t\tORYX.CONFIG.EVENT_HIGHLIGHT_SHOW,\n\t\t\t\t\t\t\t\t\thighlightId: \t\"dragdropresize.attached\",\n\t\t\t\t\t\t\t\t\telements: \t\t[this.containmentParentNode],\n\t\t\t\t\t\t\t\t\tstyle: \t\t\tORYX.CONFIG.SELECTION_HIGHLIGHT_STYLE_RECTANGLE,\n\t\t\t\t\t\t\t\t\tcolor: \t\t\tORYX.CONFIG.SELECTION_VALID_COLOR\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\n\t\t} else {\n\t\t\t\n\t\t\tthis.facade.raiseEvent({\n\t\t\t\t\t\t\t\t\ttype:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,\n\t\t\t\t\t\t\t\t\thighlightId:\"dragdropresize.attached\"\n\t\t\t\t\t\t\t\t});\n\t\t}\n\t\t\n\t\tif( !this.isAttachingAllowed ){\n\t\t\tif( this.isAddingAllowed ) {\n\n\t\t\t\tthis.facade.raiseEvent({\n\t\t\t\t\t\t\t\t\t\ttype:ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW,\n\t\t\t\t\t\t\t\t\t\thighlightId:\"dragdropresize.contain\",\n\t\t\t\t\t\t\t\t\t\telements:[this.containmentParentNode],\n\t\t\t\t\t\t\t\t\t\tcolor: ORYX.CONFIG.SELECTION_VALID_COLOR\n\t\t\t\t\t\t\t\t\t});\n\n\t\t\t} else {\n\n\t\t\t\tthis.facade.raiseEvent({\n\t\t\t\t\t\t\t\t\t\ttype:ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW,\n\t\t\t\t\t\t\t\t\t\thighlightId:\"dragdropresize.contain\",\n\t\t\t\t\t\t\t\t\t\telements:[this.containmentParentNode],\n\t\t\t\t\t\t\t\t\t\tcolor: ORYX.CONFIG.SELECTION_INVALID_COLOR\n\t\t\t\t\t\t\t\t\t});\n\n\t\t\t}\n\t\t} else {\n\t\t\tthis.facade.raiseEvent({\n\t\t\t\t\t\t\t\t\ttype:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,\n\t\t\t\t\t\t\t\t\thighlightId:\"dragdropresize.contain\"\n\t\t\t\t\t\t\t\t});\t\t\t\n\t\t}\t\n\n\t\t// Stop the Event\n\t\t//Event.stop(event);\n\t\treturn;\n\t},\n\t\n//\t/**\n//\t * Rollbacks the docked shape of an edge, if the edge is not movable.\n//\t */\n//\tredockEdges: function() {\n//\t\tthis._undockedEdgesCommand.dockers.each(function(el){\n//\t\t\tel.docker.setDockedShape(el.dockedShape);\n//\t\t\tel.docker.setReferencePoint(el.refPoint);\n//\t\t})\n//\t},\n\t\n\t/**\n\t *  Checks the containment and connection rules for the selected shapes.\n\t */\n\tcheckRules : function(options) {\n\t\tvar event = options.event;\n\t\tvar underlyingNodes = options.underlyingNodes;\n\t\tvar checkIfAttachable = options.checkIfAttachable;\n\t\tvar noEdges = options.noEdges;\n\t\t\n\t\t//get underlying node that is not the same than one of the currently selected shapes or\n\t\t// a child of one of the selected shapes with the highest z Order.\n\t\t// The result is a shape or the canvas\n\t\tthis.containmentParentNode = underlyingNodes.reverse().find((function(node) {\n\t\t\treturn (node instanceof ORYX.Core.Canvas) || \n\t\t\t\t\t(((node instanceof ORYX.Core.Node) || ((node instanceof ORYX.Core.Edge) && !noEdges)) \n\t\t\t\t\t&& (!(this.currentShapes.member(node) || \n\t\t\t\t\t\t\tthis.currentShapes.any(function(shape) {\n\t\t\t\t\t\t\t\treturn (shape.children.length > 0 && shape.getChildNodes(true).member(node));\n\t\t\t\t\t\t\t}))));\n\t\t}).bind(this));\n\t\t\t\t\t\t\t\t\n\t\tif( checkIfAttachable ){\n\t\t\t\t\n\t\t\tthis.isAttachingAllowed\t= this.facade.getRules().canConnect({\n\t\t\t\t\t\t\t\t\t\t\t\tsourceShape:\tthis.containmentParentNode, \n\t\t\t\t\t\t\t\t\t\t\t\tedgeShape:\t\tthis.toMoveShapes[0], \n\t\t\t\t\t\t\t\t\t\t\t\ttargetShape:\tthis.toMoveShapes[0]\n\t\t\t\t\t\t\t\t\t\t\t\t});\t\t\t\t\t\t\n\t\t\t\n\t\t\tif ( this.isAttachingAllowed\t) {\n\t\t\t\tvar point = this.facade.eventCoordinates(event);\n\t\t\t\tthis.isAttachingAllowed\t= this.containmentParentNode.isPointOverOffset( point.x, point.y );\n\t\t\t}\t\t\t\t\t\t\n\t\t}\n\t\t\n\t\tif( !this.isAttachingAllowed ){\n\t\t\t//check all selected shapes, if they can be added to containmentParentNode\n\t\t\tthis.isAddingAllowed = this.toMoveShapes.all((function(currentShape) {\n\t\t\t\tif(currentShape instanceof ORYX.Core.Edge ||\n\t\t\t\t\tcurrentShape instanceof ORYX.Core.Controls.Docker ||\n\t\t\t\t\tthis.containmentParentNode === currentShape.parent) {\n\t\t\t\t\treturn true;\n\t\t\t\t} else if(this.containmentParentNode !== currentShape) {\n\t\t\t\t\t\n\t\t\t\t\tif(!(this.containmentParentNode instanceof ORYX.Core.Edge) || !noEdges) {\n\t\t\t\t\t\n\t\t\t\t\t\tif(this.facade.getRules().canContain({containingShape:this.containmentParentNode,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  containedShape:currentShape})) {\t  \t\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\treturn false;\n\t\t\t}).bind(this));\t\t\t\t\n\t\t}\n\t\t\n\t\tif(!this.isAttachingAllowed && !this.isAddingAllowed && \n\t\t\t\t(this.containmentParentNode instanceof ORYX.Core.Edge)) {\n\t\t\toptions.noEdges = true;\n\t\t\toptions.underlyingNodes.reverse();\n\t\t\tthis.checkRules(options);\t\t\t\n\t\t}\n\t},\n\t\n\t/**\n\t * Redraw the selected Shapes.\n\t *\n\t */\n\trefreshSelectedShapes: function() {\n\t\t// If the selection bounds not initialized, return\n\t\tif(!this.dragBounds) {return}\n\n\t\t// Calculate the offset between the bounds and the old bounds\n\t\tvar upL = this.dragBounds.upperLeft();\n\t\tvar oldUpL = this.oldDragBounds.upperLeft();\n\t\tvar offset = {\n\t\t\tx: upL.x - oldUpL.x,\n\t\t\ty: upL.y - oldUpL.y };\n\n\t\t// Instanciate the dragCommand\n\t\tvar commands = [new ORYX.Core.Command.Move(this.toMoveShapes, offset, this.containmentParentNode, this.currentShapes, this)];\n\t\t// If the undocked edges command is setted, add this command\n\t\tif( this._undockedEdgesCommand instanceof ORYX.Core.Command ){\n\t\t\tcommands.unshift( this._undockedEdgesCommand );\n\t\t}\n\t\t// Execute the commands\t\t\t\n\t\tthis.facade.executeCommands( commands );\t\n\n\t\t// copy the bounds to the old bounds\n\t\tif( this.dragBounds )\n\t\t\tthis.oldDragBounds = this.dragBounds.clone();\n\n\t},\n\t\n\t/**\n\t * Callback for Resize\n\t *\n\t */\n\tonResize: function(bounds) {\n\t\t// If the selection bounds not initialized, return\n\t\tif(!this.dragBounds) {return}\n\t\t\n\t\tthis.dragBounds = bounds;\n\t\tthis.isResizing = true;\n\n\t\t// Update the rectangle \n\t\tthis.resizeRectangle(this.dragBounds);\n\t},\n\t\n\tonResizeStart: function() {\n\t\tthis.facade.raiseEvent({type:ORYX.CONFIG.EVENT_RESIZE_START});\n\t},\n\n\tonResizeEnd: function() {\n\t\t\n\t\tif (!(this.currentShapes instanceof Array)||this.currentShapes.length<=0) {\n\t\t\treturn;\n\t\t}\n\t\t\n\t\t// If Resizing finished, the Shapes will be resize\n\t\tif(this.isResizing) {\n\t\t\t\n\t\t\tvar commandClass = ORYX.Core.Command.extend({\n\t\t\t\tconstruct: function(shape, newBounds, plugin){\n\t\t\t\t\tthis.shape = shape;\n\t\t\t\t\tthis.oldBounds = shape.bounds.clone();\n\t\t\t\t\tthis.newBounds = newBounds;\n\t\t\t\t\tthis.plugin = plugin;\n\t\t\t\t},\t\t\t\n\t\t\t\texecute: function(){\n\t\t\t\t\tthis.shape.bounds.set(this.newBounds.a, this.newBounds.b);\n\t\t\t\t\tthis.update(this.getOffset(this.oldBounds, this.newBounds));\n\t\t\t\t\t\n\t\t\t\t},\n\t\t\t\trollback: function(){\n\t\t\t\t\tthis.shape.bounds.set(this.oldBounds.a, this.oldBounds.b);\n\t\t\t\t\tthis.update(this.getOffset(this.newBounds, this.oldBounds))\n\t\t\t\t},\n\t\t\t\t\n\t\t\t\tgetOffset:function(b1, b2){\n\t\t\t\t\treturn {\n\t\t\t\t\t\tx: b2.a.x - b1.a.x,\n\t\t\t\t\t\ty: b2.a.y - b1.a.y,\n\t\t\t\t\t\txs: b2.width()/b1.width(),\n\t\t\t\t\t\tys: b2.height()/b1.height()\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tupdate:function(offset){\n\t\t\t\t\tthis.shape.getLabels().each(function(label) {\n\t\t\t\t\t\tlabel.changed();\n\t\t\t\t\t});\n\t\t\t\t\t\n\t\t\t\t\tvar allEdges = [].concat(this.shape.getIncomingShapes())\n\t\t\t\t\t\t.concat(this.shape.getOutgoingShapes())\n\t\t\t\t\t\t// Remove all edges which are included in the selection from the list\n\t\t\t\t\t\t.findAll(function(r){ return r instanceof ORYX.Core.Edge }.bind(this))\n\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\tthis.plugin.layoutEdges(this.shape, allEdges, offset);\n\n\t\t\t\t\tthis.plugin.facade.setSelection([this.shape]);\n\t\t\t\t\tthis.plugin.facade.getCanvas().update();\n\t\t\t\t\tthis.plugin.facade.updateSelection();\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t\tvar bounds = this.dragBounds.clone();\n\t\t\tvar shape = this.currentShapes[0];\n\t\t\t\n\t\t\tif(shape.parent) {\n\t\t\t\tvar parentPosition = shape.parent.absoluteXY();\n\t\t\t\tbounds.moveBy(-parentPosition.x, -parentPosition.y);\n\t\t\t}\n\t\t\t\t\n\t\t\tvar command = new commandClass(shape, bounds, this);\n\t\t\t\n\t\t\tthis.facade.executeCommands([command]);\n\t\t\t\n\t\t\tthis.isResizing = false;\n\t\t\t\n\t\t\tthis.facade.raiseEvent({type:ORYX.CONFIG.EVENT_RESIZE_END});\n\t\t}\n\t},\n\t\n\n\t/**\n\t * Prepare the Dragging\n\t *\n\t */\n\tbeforeDrag: function(){\n\n\t\tvar undockEdgeCommand = ORYX.Core.Command.extend({\n\t\t\tconstruct: function(moveShapes){\n\t\t\t\tthis.dockers = moveShapes.collect(function(shape){ return shape instanceof ORYX.Core.Controls.Docker ? {docker:shape, dockedShape:shape.getDockedShape(), refPoint:shape.referencePoint} : undefined }).compact();\n\t\t\t},\t\t\t\n\t\t\texecute: function(){\n\t\t\t\tthis.dockers.each(function(el){\n\t\t\t\t\tel.docker.setDockedShape(undefined);\n\t\t\t\t})\n\t\t\t},\n\t\t\trollback: function(){\n\t\t\t\tthis.dockers.each(function(el){\n\t\t\t\t\tel.docker.setDockedShape(el.dockedShape);\n\t\t\t\t\tel.docker.setReferencePoint(el.refPoint);\n\t\t\t\t\t//el.docker.update();\n\t\t\t\t})\n\t\t\t}\n\t\t});\n\t\t\n\t\tthis._undockedEdgesCommand = new undockEdgeCommand( this.toMoveShapes );\n\t\tthis._undockedEdgesCommand.execute();\t\n\t\t\n\t},\n\n\thideAllLabels: function(shape) {\n\t\t\t\n\t\t\t// Hide all labels from the shape\n\t\t\tshape.getLabels().each(function(label) {\n\t\t\t\tlabel.hide();\n\t\t\t});\n\t\t\t// Hide all labels from docked shapes\n\t\t\tshape.getAllDockedShapes().each(function(dockedShape) {\n\t\t\t\tvar labels = dockedShape.getLabels();\n\t\t\t\tif(labels.length > 0) {\n\t\t\t\t\tlabels.each(function(label) {\n\t\t\t\t\t\tlabel.hide();\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// Do this recursive for all child shapes\n\t\t\t// EXP-NICO use getShapes\n\t\t\tshape.getChildren().each((function(value) {\n\t\t\t\tif(value instanceof ORYX.Core.Shape)\n\t\t\t\t\tthis.hideAllLabels(value);\n\t\t\t}).bind(this));\n\t},\n\n\t/**\n\t * Finished the Dragging\n\t *\n\t */\n\tafterDrag: function(){\n\t\t\t\t\n\t},\n\n\t/**\n\t * Show all Labels at these shape\n\t * \n\t */\n\tshowAllLabels: function(shape) {\n\n\t\t\t// Show the label of these shape\n\t\t\t//shape.getLabels().each(function(label) {\n\t\t\tfor(var i=0; i<shape.length ;i++){\n\t\t\t\tvar label = shape[i];\n\t\t\t\tlabel.show();\n\t\t\t}//);\n\t\t\t// Show all labels at docked shapes\n\t\t\t//shape.getAllDockedShapes().each(function(dockedShape) {\n\t\t\tvar allDockedShapes = shape.getAllDockedShapes()\n\t\t\tfor(var i=0; i<allDockedShapes.length ;i++){\n\t\t\t\tvar dockedShape = allDockedShapes[i];\t\t\t\t\n\t\t\t\tvar labels = dockedShape.getLabels();\n\t\t\t\tif(labels.length > 0) {\n\t\t\t\t\tlabels.each(function(label) {\n\t\t\t\t\t\tlabel.show();\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}//);\n\n\t\t\t// Do this recursive\n\t\t\t//shape.children.each((function(value) {\n\t\t\tfor(var i=0; i<shape.children.length ;i++){\n\t\t\t\tvar value = shape.children[i];\t\n\t\t\t\tif(value instanceof ORYX.Core.Shape)\n\t\t\t\t\tthis.showAllLabels(value);\n\t\t\t}//).bind(this));\n\t},\n\n\t/**\n\t * Intialize Method, if there are new Plugins\n\t *\n\t */\n\t/*registryChanged: function(pluginsData) {\n\t\t// Save all new Plugin, sorted by group and index\n\t\tthis.pluginsData = pluginsData.sortBy( function(value) {\n\t\t\treturn (value.group + \"\" + value.index);\n\t\t});\n\t},*/\n\n\t/**\n\t * On the Selection-Changed\n\t *\n\t */\n\tonSelectionChanged: function(event) {\n\t\tvar elements = event.elements;\n\t\t\n\t\t// Reset the drag-variables\n\t\tthis.dragEnable = false;\n\t\tthis.dragIntialized = false;\n\t\tthis.resizerSE.hide();\n\t\tthis.resizerNW.hide();\n\n\t\t// If there is no elements\n\t\tif(!elements || elements.length == 0) {\n\t\t\t// Hide all things and reset all variables\n\t\t\tthis.selectedRect.hide();\n\t\t\tthis.currentShapes = [];\n\t\t\tthis.toMoveShapes = [];\n\t\t\tthis.dragBounds = undefined;\n\t\t\tthis.oldDragBounds = undefined;\n\t\t} else {\n\n\t\t\t// Set the current Shapes\n\t\t\tthis.currentShapes = elements;\n\n\t\t\t// Get all shapes with the highest parent in object hierarchy (canvas is the top most parent)\n\t\t\tvar topLevelElements = this.facade.getCanvas().getShapesWithSharedParent(elements);\n\t\t\tthis.toMoveShapes = topLevelElements;\n\t\t\t\n\t\t\tthis.toMoveShapes = this.toMoveShapes.findAll( function(shape) { return shape instanceof ORYX.Core.Node && \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t(shape.dockers.length === 0 || !elements.member(shape.dockers.first().getDockedShape()))});\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\telements.each((function(shape){\n\t\t\t\tif(!(shape instanceof ORYX.Core.Edge)) {return;}\n\t\t\t\t\n\t\t\t\tvar dks = shape.getDockers();\n\t\t\t\t\t\t\t\t\n\t\t\t\tvar hasF = elements.member(dks.first().getDockedShape());\n\t\t\t\tvar hasL = elements.member(dks.last().getDockedShape());\t\n\t\t\t\t\t\t\n//\t\t\t\tif(!hasL) {\n//\t\t\t\t\tthis.toMoveShapes.push(dks.last());\n//\t\t\t\t}\n//\t\t\t\tif(!hasF){\n//\t\t\t\t\tthis.toMoveShapes.push(dks.first())\n//\t\t\t\t} \n\t\t\t\t/* Enable movement of undocked edges */\n\t\t\t\tif(!hasF && !hasL) {\n\t\t\t\t\tvar isUndocked = !dks.first().getDockedShape() && !dks.last().getDockedShape();\n\t\t\t\t\tif(isUndocked) {\n\t\t\t\t\t\tthis.toMoveShapes = this.toMoveShapes.concat(dks);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif( shape.dockers.length > 2 && hasF && hasL){\n\t\t\t\t\tthis.toMoveShapes = this.toMoveShapes.concat(dks.findAll(function(el,index){ return index > 0 && index < dks.length-1}));\n\t\t\t\t}\n\t\t\t\t\n\t\t\t}).bind(this));\n\t\t\t\n\t\t\t// Calculate the new area-bounds of the selection\n\t\t\tvar newBounds = undefined;\n\t\t\tthis.toMoveShapes.each(function(value) {\n\t\t\t\tvar shape = value;\n\t\t\t\tif(value instanceof ORYX.Core.Controls.Docker) {\n\t\t\t\t\t/* Get the Shape */\n\t\t\t\t\tshape = value.parent;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif(!newBounds){\n\t\t\t\t\tnewBounds = shape.absoluteBounds();\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tnewBounds.include(shape.absoluteBounds());\n\t\t\t\t}\n\t\t\t}.bind(this));\n\t\t\t\n\t\t\tif(!newBounds){\n\t\t\t\telements.each(function(value){\n\t\t\t\t\tif(!newBounds) {\n\t\t\t\t\t\tnewBounds = value.absoluteBounds();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnewBounds.include(value.absoluteBounds());\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\t\n\t\t\t// Set the new bounds\n\t\t\tthis.dragBounds = newBounds;\n\t\t\tthis.oldDragBounds = newBounds.clone();\n\n\t\t\t// Update and show the rectangle\n\t\t\tthis.resizeRectangle(newBounds);\n\t\t\tthis.selectedRect.show();\n\t\t\t\n\t\t\t// Show the resize button, if there is only one element and this is resizeable\n\t\t\tif(elements.length == 1 && elements[0].isResizable) {\n\t\t\t\tvar aspectRatio = elements[0].getStencil().fixedAspectRatio() ? elements[0].bounds.width() / elements[0].bounds.height() : undefined;\n\t\t\t\tthis.resizerSE.setBounds(this.dragBounds, elements[0].minimumSize, elements[0].maximumSize, aspectRatio);\n\t\t\t\tthis.resizerSE.show();\n\t\t\t\tthis.resizerNW.setBounds(this.dragBounds, elements[0].minimumSize, elements[0].maximumSize, aspectRatio);\n\t\t\t\tthis.resizerNW.show();\n\t\t\t} else {\n\t\t\t\tthis.resizerSE.setBounds(undefined);\n\t\t\t\tthis.resizerNW.setBounds(undefined);\n\t\t\t}\n\n\t\t\t// If Snap-To-Grid is enabled, the Snap-Point will be calculate\n\t\t\tif(ORYX.CONFIG.GRID_ENABLED) {\n\n\t\t\t\t// Reset all points\n\t\t\t\tthis.distPoints = [];\n\n\t\t\t\tif (this.distPointTimeout)\n\t\t\t\t\twindow.clearTimeout(this.distPointTimeout)\n\t\t\t\t\n\t\t\t\tthis.distPointTimeout = window.setTimeout(function(){\n\t\t\t\t\t// Get all the shapes, there will consider at snapping\n\t\t\t\t\t// Consider only those elements who shares the same parent element\n\t\t\t\t\tvar distShapes = this.facade.getCanvas().getChildShapes(true).findAll(function(value){\n\t\t\t\t\t\tvar parentShape = value.parent;\n\t\t\t\t\t\twhile(parentShape){\n\t\t\t\t\t\t\tif(elements.member(parentShape)) return false;\n\t\t\t\t\t\t\tparentShape = parentShape.parent\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t})\n\t\t\t\t\t\n\t\t\t\t\t// The current selection will delete from this array\n\t\t\t\t\t//elements.each(function(shape) {\n\t\t\t\t\t//\tdistShapes = distShapes.without(shape);\n\t\t\t\t\t//});\n\n\t\t\t\t\t// For all these shapes\n\t\t\t\t\tdistShapes.each((function(value) {\n\t\t\t\t\t\tif(!(value instanceof ORYX.Core.Edge)) {\n\t\t\t\t\t\t\tvar ul = value.absoluteXY();\n\t\t\t\t\t\t\tvar width = value.bounds.width();\n\t\t\t\t\t\t\tvar height = value.bounds.height();\n\n\t\t\t\t\t\t\t// Add the upperLeft, center and lowerRight - Point to the distancePoints\n\t\t\t\t\t\t\tthis.distPoints.push({\n\t\t\t\t\t\t\t\tul: {\n\t\t\t\t\t\t\t\t\tx: ul.x,\n\t\t\t\t\t\t\t\t\ty: ul.y\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tc: {\n\t\t\t\t\t\t\t\t\tx: ul.x + (width / 2),\n\t\t\t\t\t\t\t\t\ty: ul.y + (height / 2)\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tlr: {\n\t\t\t\t\t\t\t\t\tx: ul.x + width,\n\t\t\t\t\t\t\t\t\ty: ul.y + height\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}).bind(this));\n\t\t\t\t\t\n\t\t\t\t}.bind(this), 10)\n\n\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Adjust an Point to the Snap Points\n\t *\n\t */\n\tsnapToGrid: function(position) {\n\n\t\t// Get the current Bounds\n\t\tvar bounds = this.dragBounds;\n\t\t\n\t\tvar point = {};\n\n\t\tvar ulThres = 6;\n\t\tvar cThres = 10;\n\t\tvar lrThres = 6;\n\n\t\tvar scale = this.vLine ? this.vLine.getScale() : 1;\n\t\t\n\t\tvar ul = { x: (position.x/scale), y: (position.y/scale)};\n\t\tvar c = { x: (position.x/scale) + (bounds.width()/2), y: (position.y/scale) + (bounds.height()/2)};\n\t\tvar lr = { x: (position.x/scale) + (bounds.width()), y: (position.y/scale) + (bounds.height())};\n\n\t\tvar offsetX, offsetY;\n\t\tvar gridX, gridY;\n\t\t\n\t\t// For each distant point\n\t\tthis.distPoints.each(function(value) {\n\n\t\t\tvar x, y, gx, gy;\n\t\t\tif (Math.abs(value.c.x-c.x) < cThres){\n\t\t\t\tx = value.c.x-c.x;\n\t\t\t\tgx = value.c.x;\n\t\t\t}/* else if (Math.abs(value.ul.x-ul.x) < ulThres){\n\t\t\t\tx = value.ul.x-ul.x;\n\t\t\t\tgx = value.ul.x;\n\t\t\t} else if (Math.abs(value.lr.x-lr.x) < lrThres){\n\t\t\t\tx = value.lr.x-lr.x;\n\t\t\t\tgx = value.lr.x;\n\t\t\t} */\n\t\t\t\n\n\t\t\tif (Math.abs(value.c.y-c.y) < cThres){\n\t\t\t\ty = value.c.y-c.y;\n\t\t\t\tgy = value.c.y;\n\t\t\t}/* else if (Math.abs(value.ul.y-ul.y) < ulThres){\n\t\t\t\ty = value.ul.y-ul.y;\n\t\t\t\tgy = value.ul.y;\n\t\t\t} else if (Math.abs(value.lr.y-lr.y) < lrThres){\n\t\t\t\ty = value.lr.y-lr.y;\n\t\t\t\tgy = value.lr.y;\n\t\t\t} */\n\n\t\t\tif (x !== undefined) {\n\t\t\t\toffsetX = offsetX === undefined ? x : (Math.abs(x) < Math.abs(offsetX) ? x : offsetX);\n\t\t\t\tif (offsetX === x)\n\t\t\t\t\tgridX = gx;\n\t\t\t}\n\n\t\t\tif (y !== undefined) {\n\t\t\t\toffsetY = offsetY === undefined ? y : (Math.abs(y) < Math.abs(offsetY) ? y : offsetY);\n\t\t\t\tif (offsetY === y)\n\t\t\t\t\tgridY = gy;\n\t\t\t}\n\t\t});\n\t\t\n\t\t\n\t\tif (offsetX !== undefined) {\n\t\t\tul.x += offsetX;\t\n\t\t\tul.x *= scale;\n\t\t\tif (this.vLine&&gridX)\n\t\t\t\tthis.vLine.update(gridX);\n\t\t} else {\n\t\t\tul.x = (position.x - (position.x % (ORYX.CONFIG.GRID_DISTANCE/2)));\n\t\t\tif (this.vLine)\n\t\t\t\tthis.vLine.hide()\n\t\t}\n\t\t\n\t\tif (offsetY !== undefined) {\t\n\t\t\tul.y += offsetY;\n\t\t\tul.y *= scale;\n\t\t\tif (this.hLine&&gridY)\n\t\t\t\tthis.hLine.update(gridY);\n\t\t} else {\n\t\t\tul.y = (position.y - (position.y % (ORYX.CONFIG.GRID_DISTANCE/2)));\n\t\t\tif (this.hLine)\n\t\t\t\tthis.hLine.hide();\n\t\t}\n\t\t\n\t\treturn ul;\n\t},\n\t\n\tshowGridLine: function(){\n\t\t\n\t},\n\n\n\t/**\n\t * Redraw of the Rectangle of the SelectedArea\n\t * @param {Object} bounds\n\t */\n\tresizeRectangle: function(bounds) {\n\t\t// Resize the Rectangle\n\t\tthis.selectedRect.resize(bounds);\n\t}\n\n});\n\n\nORYX.Plugins.SelectedRect = Clazz.extend({\n\n\tconstruct: function(parentId) {\n\n\t\tthis.parentId = parentId;\n\n\t\tthis.node = ORYX.Editor.graft(\"http://www.w3.org/2000/svg\", $(parentId),\n\t\t\t\t\t['g']);\n\n\t\tthis.dashedArea = ORYX.Editor.graft(\"http://www.w3.org/2000/svg\", this.node,\n\t\t\t['rect', {x: 0, y: 0,\n\t\t\t\t'stroke-width': 1, stroke: '#777777', fill: 'none',\n\t\t\t\t'stroke-dasharray': '2,2',\n\t\t\t\t'pointer-events': 'none'}]);\n\n\t\tthis.hide();\n\n\t},\n\n\thide: function() {\n\t\tthis.node.setAttributeNS(null, 'display', 'none');\n\t},\n\n\tshow: function() {\n\t\tthis.node.setAttributeNS(null, 'display', '');\n\t},\n\n\tresize: function(bounds) {\n\t\tvar upL = bounds.upperLeft();\n\n\t\tvar padding = ORYX.CONFIG.SELECTED_AREA_PADDING;\n\n\t\tthis.dashedArea.setAttributeNS(null, 'width', bounds.width() + 2*padding);\n\t\tthis.dashedArea.setAttributeNS(null, 'height', bounds.height() + 2*padding);\n\t\tthis.node.setAttributeNS(null, 'transform', \"translate(\"+ (upL.x - padding) +\", \"+ (upL.y - padding) +\")\");\n\t}\n\n\n});\n\n\n\nORYX.Plugins.GridLine = Clazz.extend({\n\t\n\tconstruct: function(parentId, direction) {\n\n\t\tif (ORYX.Plugins.GridLine.DIR_HORIZONTAL !== direction && ORYX.Plugins.GridLine.DIR_VERTICAL !== direction) {\n\t\t\tdirection = ORYX.Plugins.GridLine.DIR_HORIZONTAL\n\t\t}\n\t\t\n\t\n\t\tthis.parent = $(parentId);\n\t\tthis.direction = direction;\n\t\tthis.node = ORYX.Editor.graft(\"http://www.w3.org/2000/svg\", this.parent,\n\t\t\t\t\t['g']);\n\n\t\tthis.line = ORYX.Editor.graft(\"http://www.w3.org/2000/svg\", this.node,\n\t\t\t['path', {\n\t\t\t\t'stroke-width': 1, stroke: 'silver', fill: 'none',\n\t\t\t\t'stroke-dasharray': '5,5',\n\t\t\t\t'pointer-events': 'none'}]);\n\n\t\tthis.hide();\n\n\t},\n\n\thide: function() {\n\t\tthis.node.setAttributeNS(null, 'display', 'none');\n\t},\n\n\tshow: function() {\n\t\tthis.node.setAttributeNS(null, 'display', '');\n\t},\n\n\tgetScale: function(){\n\t\ttry {\n\t\t\treturn this.parent.parentNode.transform.baseVal.getItem(0).matrix.a;\n\t\t} catch(e) {\n\t\t\treturn 1;\n\t\t}\n\t},\n\t\n\tupdate: function(pos) {\n\t\t\n\t\tif (this.direction === ORYX.Plugins.GridLine.DIR_HORIZONTAL) {\n\t\t\tvar y = pos instanceof Object ? pos.y : pos; \n\t\t\tvar cWidth = this.parent.parentNode.parentNode.width.baseVal.value/this.getScale();\n\t\t\tthis.line.setAttributeNS(null, 'd', 'M 0 '+y+ ' L '+cWidth+' '+y);\n\t\t} else {\n\t\t\tvar x = pos instanceof Object ? pos.x : pos; \n\t\t\tvar cHeight = this.parent.parentNode.parentNode.height.baseVal.value/this.getScale();\n\t\t\tthis.line.setAttributeNS(null, 'd', 'M'+x+ ' 0 L '+x+' '+cHeight);\n\t\t}\n\t\t\n\t\tthis.show();\n\t}\n\n\n});\n\nORYX.Plugins.GridLine.DIR_HORIZONTAL = \"hor\";\nORYX.Plugins.GridLine.DIR_VERTICAL = \"ver\";\n\nORYX.Plugins.Resizer = Clazz.extend({\n\n\tconstruct: function(parentId, orientation, facade) {\n\n\t\tthis.parentId \t\t= parentId;\n\t\tthis.orientation\t= orientation;\n\t\tthis.facade\t\t\t= facade;\n\t\t\n\t\tthis.node = ORYX.Editor.graft(\"http://www.w3.org/1999/xhtml\", $('canvasSection'),\n\t\t\t['div', {'class': 'resizer_'+ this.orientation, style:'left:0px; top:0px;position:absolute;'}]);\n\n\t\tthis.node.addEventListener(ORYX.CONFIG.EVENT_MOUSEDOWN, this.handleMouseDown.bind(this), true);\n\t\tdocument.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEUP, \tthis.handleMouseUp.bind(this), \t\ttrue);\n\t\tdocument.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, \tthis.handleMouseMove.bind(this), \tfalse);\n\n\t\tthis.dragEnable = false;\n\t\tthis.offSetPosition = {x: 0, y: 0};\n\t\tthis.bounds = undefined;\n\n\t\tthis.canvasNode = this.facade.getCanvas().node;\n\n\t\tthis.minSize = undefined;\n\t\tthis.maxSize = undefined;\n\t\t\n\t\tthis.aspectRatio = undefined;\n\n\t\tthis.resizeCallbacks \t\t= [];\n\t\tthis.resizeStartCallbacks \t= [];\n\t\tthis.resizeEndCallbacks \t= [];\n\t\tthis.hide();\n\t\t\n\t\t// Calculate the Offset\n\t\tthis.scrollNode = this.node.parentNode.parentNode.parentNode;\n\n\t},\n\n\thandleMouseDown: function(event) {\n\t\tthis.dragEnable = true;\n\n\t\tthis.offsetScroll\t= {x:this.scrollNode.scrollLeft,y:this.scrollNode.scrollTop};\n\t\t\t\n\t\tthis.offSetPosition =  {\n\t\t\tx: Event.pointerX(event) - this.position.x,\n\t\t\ty: Event.pointerY(event) - this.position.y};\n\t\t\n\t\tthis.resizeStartCallbacks.each((function(value) {\n\t\t\tvalue(this.bounds);\n\t\t}).bind(this));\n\n\t},\n\n\thandleMouseUp: function(event) {\n\t\tthis.dragEnable = false;\n\t\tthis.containmentParentNode = null;\n\t\tthis.resizeEndCallbacks.each((function(value) {\n\t\t\tvalue(this.bounds);\n\t\t}).bind(this));\n\t\t\t\t\n\t},\n\n\thandleMouseMove: function(event) {\n\t\tif(!this.dragEnable) { return }\n\t\t\n\t\tif(event.shiftKey || event.ctrlKey) {\n\t\t\tthis.aspectRatio = this.bounds.width() / this.bounds.height();\n\t\t} else {\n\t\t\tthis.aspectRatio = undefined;\n\t\t}\n\n\t\tvar position = {\n\t\t\tx: Event.pointerX(event) - this.offSetPosition.x,\n\t\t\ty: Event.pointerY(event) - this.offSetPosition.y};\n\n\n\t\tposition.x \t-= this.offsetScroll.x - this.scrollNode.scrollLeft; \n\t\tposition.y \t-= this.offsetScroll.y - this.scrollNode.scrollTop;\n\t\t\n\t\tposition.x  = Math.min( position.x, this.facade.getCanvas().bounds.width());\n\t\tposition.y  = Math.min( position.y, this.facade.getCanvas().bounds.height());\n\t\t\n\t\tvar offset = {\n\t\t\tx: position.x - this.position.x,\n\t\t\ty: position.y - this.position.y\n\t\t};\n\t\t\n\t\tif(this.aspectRatio) {\n\t\t\t// fixed aspect ratio\n\t\t\tnewAspectRatio = (this.bounds.width()+offset.x) / (this.bounds.height()+offset.y);\n\t\t\tif(newAspectRatio>this.aspectRatio) {\n\t\t\t\toffset.x = this.aspectRatio * (this.bounds.height()+offset.y) - this.bounds.width();\n\t\t\t} else if(newAspectRatio<this.aspectRatio) {\n\t\t\t\toffset.y = (this.bounds.width()+offset.x) / this.aspectRatio - this.bounds.height();\n\t\t\t}\n\t\t}\n\t\t\n\t\t// respect minimum and maximum sizes of stencil\n\t\tif(this.orientation===\"northwest\") {\n\t\t\t\n\t\t\tif(this.bounds.width()-offset.x > this.maxSize.width) {\n\t\t\t\toffset.x = -(this.maxSize.width - this.bounds.width());\n\t\t\t\tif(this.aspectRatio)\n\t\t\t\t\toffset.y = this.aspectRatio * offset.x;\n\t\t\t}\n\t\t\tif(this.bounds.width()-offset.x < this.minSize.width) {\n\t\t\t\toffset.x = -(this.minSize.width - this.bounds.width());\n\t\t\t\tif(this.aspectRatio)\n\t\t\t\t\toffset.y = this.aspectRatio * offset.x;\n\t\t\t}\n\t\t\tif(this.bounds.height()-offset.y > this.maxSize.height) {\n\t\t\t\toffset.y = -(this.maxSize.height - this.bounds.height());\n\t\t\t\tif(this.aspectRatio)\n\t\t\t\t\toffset.x = offset.y / this.aspectRatio;\n\t\t\t}\n\t\t\tif(this.bounds.height()-offset.y < this.minSize.height) {\n\t\t\t\toffset.y = -(this.minSize.height - this.bounds.height());\n\t\t\t\tif(this.aspectRatio)\n\t\t\t\t\toffset.x = offset.y / this.aspectRatio;\n\t\t\t}\n\t\t\t\n\t\t} else { // defaults to southeast\n\t\t\tif(this.bounds.width()+offset.x > this.maxSize.width) {\n\t\t\t\toffset.x = this.maxSize.width - this.bounds.width();\n\t\t\t\tif(this.aspectRatio)\n\t\t\t\t\toffset.y = this.aspectRatio * offset.x;\n\t\t\t}\n\t\t\tif(this.bounds.width()+offset.x < this.minSize.width) {\n\t\t\t\toffset.x = this.minSize.width - this.bounds.width();\n\t\t\t\tif(this.aspectRatio)\n\t\t\t\t\toffset.y = this.aspectRatio * offset.x;\n\t\t\t}\n\t\t\tif(this.bounds.height()+offset.y > this.maxSize.height) {\n\t\t\t\toffset.y = this.maxSize.height - this.bounds.height();\n\t\t\t\tif(this.aspectRatio)\n\t\t\t\t\toffset.x = offset.y / this.aspectRatio;\n\t\t\t}\n\t\t\tif(this.bounds.height()+offset.y < this.minSize.height) {\n\t\t\t\toffset.y = this.minSize.height - this.bounds.height();\n\t\t\t\tif(this.aspectRatio)\n\t\t\t\t\toffset.x = offset.y / this.aspectRatio;\n\t\t\t}\n\t\t}\n\n\t\tif(this.orientation===\"northwest\") {\n\t\t\tthis.bounds.extend({x:-offset.x, y:-offset.y});\n\t\t\tthis.bounds.moveBy(offset);\n\t\t} else { // defaults to southeast\n\t\t\tthis.bounds.extend(offset);\n\t\t}\n\n\t\tthis.update();\n\n\t\tthis.resizeCallbacks.each((function(value) {\n\t\t\tvalue(this.bounds);\n\t\t}).bind(this));\n\n\t\tEvent.stop(event);\n\n\t},\n\t\n\tregisterOnResizeStart: function(callback) {\n\t\tif(!this.resizeStartCallbacks.member(callback)) {\n\t\t\tthis.resizeStartCallbacks.push(callback);\n\t\t}\n\t},\n\t\n\tunregisterOnResizeStart: function(callback) {\n\t\tif(this.resizeStartCallbacks.member(callback)) {\n\t\t\tthis.resizeStartCallbacks = this.resizeStartCallbacks.without(callback);\n\t\t}\n\t},\n\n\tregisterOnResizeEnd: function(callback) {\n\t\tif(!this.resizeEndCallbacks.member(callback)) {\n\t\t\tthis.resizeEndCallbacks.push(callback);\n\t\t}\n\t},\n\t\n\tunregisterOnResizeEnd: function(callback) {\n\t\tif(this.resizeEndCallbacks.member(callback)) {\n\t\t\tthis.resizeEndCallbacks = this.resizeEndCallbacks.without(callback);\n\t\t}\n\t},\n\t\t\n\tregisterOnResize: function(callback) {\n\t\tif(!this.resizeCallbacks.member(callback)) {\n\t\t\tthis.resizeCallbacks.push(callback);\n\t\t}\n\t},\n\n\tunregisterOnResize: function(callback) {\n\t\tif(this.resizeCallbacks.member(callback)) {\n\t\t\tthis.resizeCallbacks = this.resizeCallbacks.without(callback);\n\t\t}\n\t},\n\n\thide: function() {\n\t\tthis.node.style.display = \"none\";\n\t},\n\n\tshow: function() {\n\t\tif(this.bounds)\n\t\t\tthis.node.style.display = \"\";\n\t},\n\n\tsetBounds: function(bounds, min, max, aspectRatio) {\n\t\tthis.bounds = bounds;\n\n\t\tif(!min)\n\t\t\tmin = {width: ORYX.CONFIG.MINIMUM_SIZE, height: ORYX.CONFIG.MINIMUM_SIZE};\n\n\t\tif(!max)\n\t\t\tmax = {width: ORYX.CONFIG.MAXIMUM_SIZE, height: ORYX.CONFIG.MAXIMUM_SIZE};\n\n\t\tthis.minSize = min;\n\t\tthis.maxSize = max;\n\t\t\n\t\tthis.aspectRatio = aspectRatio;\n\n\t\tthis.update();\n\t},\n\n\tupdate: function() {\n\t\tif(!this.bounds) { return; }\n\n\t\tvar upL = this.bounds.upperLeft();\n\t\t\n\t\tif(this.bounds.width() < this.minSize.width)\t{ this.bounds.set(upL.x, upL.y, upL.x + this.minSize.width, upL.y + this.bounds.height());};\n\t\tif(this.bounds.height() < this.minSize.height)\t{ this.bounds.set(upL.x, upL.y, upL.x + this.bounds.width(), upL.y + this.minSize.height);};\n\t\tif(this.bounds.width() > this.maxSize.width)\t{ this.bounds.set(upL.x, upL.y, upL.x + this.maxSize.width, upL.y + this.bounds.height());};\n\t\tif(this.bounds.height() > this.maxSize.height)\t{ this.bounds.set(upL.x, upL.y, upL.x + this.bounds.width(), upL.y + this.maxSize.height);};\n\n\t\tvar a = this.canvasNode.getScreenCTM();\n\t    \n\t\tupL.x *= a.a;\n\t\tupL.y *= a.d;\n\t\t\n\t\tvar additionalIEZoom = 1;\n        if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) {\n            var ua = navigator.userAgent;\n            if (ua.indexOf('MSIE') >= 0) {\n                //IE 10 and below\n                var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100);\n                if (zoom !== 100) {\n                    additionalIEZoom = zoom / 100\n                }\n            }\n        }\n        \n        if (additionalIEZoom === 1) {\n             upL.y = upL.y - jQuery(\"#canvasSection\").offset().top + a.f;\n             upL.x = upL.x - jQuery(\"#canvasSection\").offset().left + a.e;\n        \n        } else {\n             var canvasOffsetLeft = jQuery(\"#canvasSection\").offset().left;\n             var canvasScrollLeft = jQuery(\"#canvasSection\").scrollLeft();\n             var canvasScrollTop = jQuery(\"#canvasSection\").scrollTop();\n             \n             var offset = a.e - (canvasOffsetLeft * additionalIEZoom);\n             var additionaloffset = 0;\n             if (offset > 10) {\n                 additionaloffset = (offset / additionalIEZoom) - offset;\n             }\n             upL.y = upL.y - (jQuery(\"#canvasSection\").offset().top * additionalIEZoom) + ((canvasScrollTop * additionalIEZoom) - canvasScrollTop) + a.f;\n             upL.x = upL.x - (canvasOffsetLeft * additionalIEZoom) + additionaloffset + ((canvasScrollLeft * additionalIEZoom) - canvasScrollLeft) + a.e;\n        }\n\t\t\n\t\tif(this.orientation===\"northwest\") {\n\t\t\tupL.x -= 13;\n\t\t\tupL.y -= 13;\n\t\t} else { // defaults to southeast\n\t\t\tupL.x +=  (a.a * this.bounds.width()) + 3 ;\n\t\t\tupL.y +=  (a.d * this.bounds.height())  + 3;\n\t\t}\n\t\t\n\t\tthis.position = upL;\n\n\t\tthis.node.style.left = this.position.x + \"px\";\n\t\tthis.node.style.top = this.position.y + \"px\";\n\t}\n});\n\n\n\n/**\n * Implements a Command to move shapes\n * \n */ \nORYX.Core.Command.Move = ORYX.Core.Command.extend({\n\tconstruct: function(moveShapes, offset, parent, selectedShapes, plugin){\n\t\tthis.moveShapes = moveShapes;\n\t\tthis.selectedShapes = selectedShapes;\n\t\tthis.offset \t= offset;\n\t\tthis.plugin\t\t= plugin;\n\t\t// Defines the old/new parents for the particular shape\n\t\tthis.newParents\t= moveShapes.collect(function(t){ return parent || t.parent });\n\t\tthis.oldParents\t= moveShapes.collect(function(shape){ return shape.parent });\n\t\tthis.dockedNodes= moveShapes.findAll(function(shape){ return shape instanceof ORYX.Core.Node && shape.dockers.length == 1}).collect(function(shape){ return {docker:shape.dockers[0], dockedShape:shape.dockers[0].getDockedShape(), refPoint:shape.dockers[0].referencePoint} });\n\t},\t\t\t\n\texecute: function(){\n\t\tthis.dockAllShapes()\t\t\t\t\n\t\t// Moves by the offset\n\t\tthis.move( this.offset);\n\t\t// Addes to the new parents\n\t\tthis.addShapeToParent( this.newParents ); \n\t\t// Set the selection to the current selection\n\t\tthis.selectCurrentShapes();\n\t\tthis.plugin.facade.getCanvas().update();\n\t\tthis.plugin.facade.updateSelection();\n\t},\n\trollback: function(){\n\t\t// Moves by the inverted offset\n\t\tvar offset = { x:-this.offset.x, y:-this.offset.y };\n\t\tthis.move( offset );\n\t\t// Addes to the old parents\n\t\tthis.addShapeToParent( this.oldParents ); \n\t\tthis.dockAllShapes(true)\t\n\t\t\n\t\t// Set the selection to the current selection\n\t\tthis.selectCurrentShapes();\n\t\tthis.plugin.facade.getCanvas().update();\n\t\tthis.plugin.facade.updateSelection();\n\t\t\n\t},\n\tmove:function(offset, doLayout){\n\t\t\n\t\t// Move all Shapes by these offset\n\t\tfor(var i=0; i<this.moveShapes.length ;i++){\n\t\t\tvar value = this.moveShapes[i];\t\t\t\t\t\n\t\t\tvalue.bounds.moveBy(offset);\n\t\t\t\n\t\t\tif (value instanceof ORYX.Core.Node) {\n\t\t\t\t\n\t\t\t\t(value.dockers||[]).each(function(d){\n\t\t\t\t\td.bounds.moveBy(offset);\n\t\t\t\t})\n\t\t\t\t\n\t\t\t\t// Update all Dockers of Child shapes\n\t\t\t\t/*var childShapesNodes = value.getChildShapes(true).findAll(function(shape){ return shape instanceof ORYX.Core.Node });\t\t\t\t\t\t\t\n\t\t\t\tvar childDockedShapes = childShapesNodes.collect(function(shape){ return shape.getAllDockedShapes() }).flatten().uniq();\t\t\t\t\t\t\t\n\t\t\t\tvar childDockedEdge = childDockedShapes.findAll(function(shape){ return shape instanceof ORYX.Core.Edge });\t\t\t\t\t\t\t\n\t\t\t\tchildDockedEdge = childDockedEdge.findAll(function(shape){ return shape.getAllDockedShapes().all(function(dsh){ return childShapesNodes.include(dsh) }) });\t\t\t\t\t\t\t\n\t\t\t\tvar childDockedDockers = childDockedEdge.collect(function(shape){ return shape.dockers }).flatten();\n\t\t\t\t\n\t\t\t\tfor (var j = 0; j < childDockedDockers.length; j++) {\n\t\t\t\t\tvar docker = childDockedDockers[j];\n\t\t\t\t\tif (!docker.getDockedShape() && !this.moveShapes.include(docker)) {\n\t\t\t\t\t\t//docker.bounds.moveBy(offset);\n\t\t\t\t\t\t//docker.update();\n\t\t\t\t\t}\n\t\t\t\t}*/\n\t\t\t\t\n\t\t\t\t\n\t\t\t\tvar allEdges = [].concat(value.getIncomingShapes())\n\t\t\t\t\t.concat(value.getOutgoingShapes())\n\t\t\t\t\t// Remove all edges which are included in the selection from the list\n\t\t\t\t\t.findAll(function(r){ return\tr instanceof ORYX.Core.Edge && !this.moveShapes.any(function(d){ return d == r || (d instanceof ORYX.Core.Controls.Docker && d.parent == r)}) }.bind(this))\n\t\t\t\t\t// Remove all edges which are between the node and a node contained in the selection from the list\n\t\t\t\t\t.findAll(function(r){ return \t(r.dockers.first().getDockedShape() == value || !this.moveShapes.include(r.dockers.first().getDockedShape())) &&  \n\t\t\t\t\t\t\t\t\t\t\t\t\t(r.dockers.last().getDockedShape() == value || !this.moveShapes.include(r.dockers.last().getDockedShape()))}.bind(this))\n\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t// Layout all outgoing/incoming edges\n\t\t\t\tthis.plugin.layoutEdges(value, allEdges, offset);\n\t\t\t\t\n\t\t\t\t\n\t\t\t\tvar allSameEdges = [].concat(value.getIncomingShapes())\n\t\t\t\t\t.concat(value.getOutgoingShapes())\n\t\t\t\t\t// Remove all edges which are included in the selection from the list\n\t\t\t\t\t.findAll(function(r){ return r instanceof ORYX.Core.Edge && r.dockers.first().isDocked() && r.dockers.last().isDocked() && !this.moveShapes.include(r) && !this.moveShapes.any(function(d){ return d == r || (d instanceof ORYX.Core.Controls.Docker && d.parent == r)}) }.bind(this))\n\t\t\t\t\t// Remove all edges which are included in the selection from the list\n\t\t\t\t\t.findAll(function(r){ return this.moveShapes.indexOf(r.dockers.first().getDockedShape()) > i ||  this.moveShapes.indexOf(r.dockers.last().getDockedShape()) > i}.bind(this))\n\n\t\t\t\tfor (var j = 0; j < allSameEdges.length; j++) {\n\t\t\t\t\tfor (var k = 1; k < allSameEdges[j].dockers.length-1; k++) {\n\t\t\t\t\t\tvar docker = allSameEdges[j].dockers[k];\n\t\t\t\t\t\tif (!docker.getDockedShape() && !this.moveShapes.include(docker)) {\n\t\t\t\t\t\t\tdocker.bounds.moveBy(offset);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\t\n\t\t\t\t\n\t\t\t\t/*var i=-1;\n\t\t\t\tvar nodes = value.getChildShapes(true);\n\t\t\t\tvar allEdges = [];\n\t\t\t\twhile(++i<nodes.length){\n\t\t\t\t\tvar edges = [].concat(nodes[i].getIncomingShapes())\n\t\t\t\t\t\t.concat(nodes[i].getOutgoingShapes())\n\t\t\t\t\t\t// Remove all edges which are included in the selection from the list\n\t\t\t\t\t\t.findAll(function(r){ return r instanceof ORYX.Core.Edge && !allEdges.include(r) && r.dockers.any(function(d){ return !value.bounds.isIncluded(d.bounds.center)})})\n\t\t\t\t\tallEdges = allEdges.concat(edges);\n\t\t\t\t\tif (edges.length <= 0){ continue }\n\t\t\t\t\t//this.plugin.layoutEdges(nodes[i], edges, offset);\n\t\t\t\t}*/\n\t\t\t}\n\t\t}\n\t\t\t\t\t\t\t\t\t\t\n\t},\n\tdockAllShapes: function(shouldDocked){\n\t\t// Undock all Nodes\n\t\tfor (var i = 0; i < this.dockedNodes.length; i++) {\n\t\t\tvar docker = this.dockedNodes[i].docker;\n\t\t\t\n\t\t\tdocker.setDockedShape( shouldDocked ? this.dockedNodes[i].dockedShape : undefined )\n\t\t\tif (docker.getDockedShape()) {\n\t\t\t\tdocker.setReferencePoint(this.dockedNodes[i].refPoint);\n\t\t\t\t//docker.update();\n\t\t\t}\n\t\t}\n\t},\n\t\n\taddShapeToParent:function( parents ){\n\t\t\n\t\t// For every Shape, add this and reset the position\t\t\n\t\tfor(var i=0; i<this.moveShapes.length ;i++){\n\t\t\tvar currentShape = this.moveShapes[i];\n\t\t\tif(currentShape instanceof ORYX.Core.Node &&\n\t\t\t   currentShape.parent !== parents[i]) {\n\t\t\t\t\n\t\t\t\t// Calc the new position\n\t\t\t\tvar unul = parents[i].absoluteXY();\n\t\t\t\tvar csul = currentShape.absoluteXY();\n\t\t\t\tvar x = csul.x - unul.x;\n\t\t\t\tvar y = csul.y - unul.y;\n\n\t\t\t\t// Add the shape to the new contained shape\n\t\t\t\tparents[i].add(currentShape);\n\t\t\t\t// Add all attached shapes as well\n\t\t\t\tcurrentShape.getOutgoingShapes((function(shape) {\n\t\t\t\t\tif(shape instanceof ORYX.Core.Node && !this.moveShapes.member(shape)) {\n\t\t\t\t\t\tparents[i].add(shape);\n\t\t\t\t\t}\n\t\t\t\t}).bind(this));\n\n\t\t\t\t// Set the new position\n\t\t\t\tif(currentShape instanceof ORYX.Core.Node && currentShape.dockers.length == 1){\n\t\t\t\t\tvar b = currentShape.bounds;\n\t\t\t\t\tx += b.width()/2;y += b.height()/2\n\t\t\t\t\tcurrentShape.dockers.first().bounds.centerMoveTo(x, y);\n\t\t\t\t} else {\n\t\t\t\t\tcurrentShape.bounds.moveTo(x, y);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t} \n\t\t\t\n\t\t\t// Update the shape\n\t\t\t//currentShape.update();\n\t\t\t\n\t\t}\n\t},\n\tselectCurrentShapes:function(){\n\t\tthis.plugin.facade.setSelection( this.selectedShapes );\n\t}\n});\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nif(!ORYX.Plugins)\n\tORYX.Plugins = new Object();\n\nORYX.Plugins.DragDocker = Clazz.extend({\n\n\t/**\n\t *\tConstructor\n\t *\t@param {Object} Facade: The Facade of the Editor\n\t */\n\tconstruct: function(facade) {\n\t\tthis.facade = facade;\n\t\t\n\t\t// Set the valid and invalid color\n\t\tthis.VALIDCOLOR \t= ORYX.CONFIG.SELECTION_VALID_COLOR;\n\t\tthis.INVALIDCOLOR \t= ORYX.CONFIG.SELECTION_INVALID_COLOR;\n\t\t\n\t\t// Define Variables \n\t\tthis.shapeSelection = undefined;\n\t\tthis.docker \t\t= undefined;\n\t\tthis.dockerParent   = undefined;\n\t\tthis.dockerSource \t= undefined;\n\t\tthis.dockerTarget \t= undefined;\n\t\tthis.lastUIObj \t\t= undefined;\n\t\tthis.isStartDocker \t= undefined;\n\t\tthis.isEndDocker \t= undefined;\n\t\tthis.undockTreshold\t= 10;\n\t\tthis.initialDockerPosition = undefined;\n\t\tthis.outerDockerNotMoved = undefined;\n\t\tthis.isValid \t\t= false;\n\t\t\n\t\t// For the Drag and Drop\n\t\t// Register on MouseDown-Event on a Docker\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_MOUSEDOWN, this.handleMouseDown.bind(this));\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_DOCKERDRAG, this.handleDockerDrag.bind(this));\n\n\t\t\n\t\t// Register on over/out to show / hide a docker\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_MOUSEOVER, this.handleMouseOver.bind(this));\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_MOUSEOUT, this.handleMouseOut.bind(this));\t\t\n\t\t\n\t\t\n\t},\n\t\n\t/**\n\t * MouseOut Handler\n\t *\n\t */\n\thandleMouseOut: function(event, uiObj) {\n\t\t// If there is a Docker, hide this\n\t\tif(!this.docker && uiObj instanceof ORYX.Core.Controls.Docker) {\n\t\t\tuiObj.hide();\n\t\t} else if(!this.docker && uiObj instanceof ORYX.Core.Edge) {\n\t\t\tuiObj.dockers.each(function(docker){\n\t\t\t\tdocker.hide();\n\t\t\t});\n\t\t}\n\t},\n\n\t/**\n\t * MouseOver Handler\n\t *\n\t */\n\thandleMouseOver: function(event, uiObj) {\n\t\t// If there is a Docker, show this\t\t\n\t\tif(!this.docker && uiObj instanceof ORYX.Core.Controls.Docker) {\n\t\t\tuiObj.show();\n\t\t} else if(!this.docker && uiObj instanceof ORYX.Core.Edge) {\n\t\t\tuiObj.dockers.each(function(docker){\n\t\t\t\tdocker.show();\n\t\t\t});\n\t\t}\n\t},\n\t/**\n\t * DockerDrag Handler\n\t * delegates the uiEvent of the drag event to the mouseDown function\n\t */\n\thandleDockerDrag: function(event, uiObj) {\n\t\tthis.handleMouseDown(event.uiEvent, uiObj);\n\t},\n\t\n\t/**\n\t * MouseDown Handler\n\t *\n\t */\t\n\thandleMouseDown: function(event, uiObj) {\n\t\t// If there is a Docker\n\t\tif(uiObj instanceof ORYX.Core.Controls.Docker && uiObj.isMovable) {\n\t\t\t\n\t\t\t/* Buffering shape selection and clear selection*/\n\t\t\tthis.shapeSelection = this.facade.getSelection();\n\t\t\tthis.facade.setSelection();\n\t\t\t\n\t\t\tthis.docker = uiObj;\n\t\t\tthis.initialDockerPosition = this.docker.bounds.center();\n\t\t\tthis.outerDockerNotMoved = false;\t\t\t\n\t\t\tthis.dockerParent = uiObj.parent;\n\t\t\t\n\t\t\t// Define command arguments\n\t\t\tthis._commandArg = {docker:uiObj, dockedShape:uiObj.getDockedShape(), refPoint:uiObj.referencePoint || uiObj.bounds.center()};\n\n\t\t\t// Show the Docker\n\t\t\tthis.docker.show();\n\t\t\t\n\t\t\t// If the Dockers Parent is an Edge, \n\t\t\t//  and the Docker is either the first or last Docker of the Edge\n\t\t\tif(uiObj.parent instanceof ORYX.Core.Edge && \n\t\t\t   \t(uiObj.parent.dockers.first() == uiObj || uiObj.parent.dockers.last() == uiObj)) {\n\t\t\t\t\n\t\t\t\t// Get the Edge Source or Target\n\t\t\t\tif(uiObj.parent.dockers.first() == uiObj && uiObj.parent.dockers.last().getDockedShape()) {\n\t\t\t\t\tthis.dockerTarget = uiObj.parent.dockers.last().getDockedShape();\n\t\t\t\t} else if(uiObj.parent.dockers.last() == uiObj && uiObj.parent.dockers.first().getDockedShape()) {\n\t\t\t\t\tthis.dockerSource = uiObj.parent.dockers.first().getDockedShape();\n\t\t\t\t}\n\t\t\t\t\n\t\t\t} else {\n\t\t\t\t// If there parent is not an Edge, undefined the Source and Target\n\t\t\t\tthis.dockerSource = undefined;\n\t\t\t\tthis.dockerTarget = undefined;\t\t\t\t\n\t\t\t}\n\t\t\n\t\t\tthis.isStartDocker = this.docker.parent.dockers.first() === this.docker;\n\t\t\tthis.isEndDocker = this.docker.parent.dockers.last() === this.docker;\n\t\t\t\t\t\n\t\t\t// add to canvas while dragging\n\t\t\tthis.facade.getCanvas().add(this.docker.parent);\n\t\t\t\n\t\t\t// Hide all Labels from Docker\n\t\t\tthis.docker.parent.getLabels().each(function(label) {\n\t\t\t\tlabel.hide();\n\t\t\t});\n\t\t\t\n\t\t\tvar eventCoordinates = this.facade.eventCoordinates(event);\n\t\t\tvar additionalIEZoom = 1;\n            if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) {\n                var ua = navigator.userAgent;\n                if (ua.indexOf('MSIE') >= 0) {\n                    //IE 10 and below\n                    var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100);\n                    if (zoom !== 100) {\n                        additionalIEZoom = zoom / 100\n                    }\n                }\n            }\n            \n            if (additionalIEZoom !== 1) {\n                eventCoordinates.x = eventCoordinates.x / additionalIEZoom;\n                eventCoordinates.y = eventCoordinates.y / additionalIEZoom;\n            }\n\t\t\t\n\t\t\t// Undocked the Docker from current Shape\n\t\t\tif ((!this.isStartDocker && !this.isEndDocker) || !this.docker.isDocked()) {\n\t\t\t\t\n\t\t\t\tthis.docker.setDockedShape(undefined);\n\t\t\t\t// Set the Docker to the center of the mouse pointer\n\t\t\t\tthis.docker.bounds.centerMoveTo(eventCoordinates);\n\t\t\t\tthis.dockerParent._update();\n\t\t\t} else {\n\t\t\t\tthis.outerDockerNotMoved = true;\n\t\t\t}\n\t\t\t\n\t\t\tvar option = {movedCallback: this.dockerMoved.bind(this), upCallback: this.dockerMovedFinished.bind(this)};\n\t\t\t\n\t\t\tthis.startEventPos = eventCoordinates;\n\t\t\t\n\t\t\t// Enable the Docker for Drag'n'Drop, give the mouseMove and mouseUp-Callback with\n\t\t\tORYX.Core.UIEnableDrag(event, uiObj, option);\n\t\t}\n\t},\n\t\n\t/**\n\t * Docker MouseMove Handler\n\t *\n\t */\n\tdockerMoved: function(event) {\n\t\tthis.outerDockerNotMoved = false;\n\t\tvar snapToMagnet = undefined;\n\t\t\n\t\tif (this.docker.parent) {\n\t\t\tif (this.isStartDocker || this.isEndDocker) {\n\t\t\t\n\t\t\t\t// Get the EventPosition and all Shapes on these point\n\t\t\t\tvar evPos = this.facade.eventCoordinates(event);\n\t\t\t\t\n\t\t\t\tvar additionalIEZoom = 1;\n\t            if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) {\n\t                var ua = navigator.userAgent;\n\t                if (ua.indexOf('MSIE') >= 0) {\n\t                    //IE 10 and below\n\t                    var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100);\n\t                    if (zoom !== 100) {\n\t                        additionalIEZoom = zoom / 100\n\t                    }\n\t                }\n\t            }\n\t            \n\t            if (additionalIEZoom !== 1) {\n\t            \tevPos.x = evPos.x / additionalIEZoom;\n\t            \tevPos.y = evPos.y / additionalIEZoom;\n\t            }\n\t\t\t\t\n\t\t\t\tif(this.docker.isDocked()) {\n\t\t\t\t\t/* Only consider start/end dockers if they are moved over a treshold */\n\t\t\t\t\tvar distanceDockerPointer = \n\t\t\t\t\t\tORYX.Core.Math.getDistancePointToPoint(evPos, this.initialDockerPosition);\n\t\t\t\t\tif(distanceDockerPointer < this.undockTreshold) {\n\t\t\t\t\t\tthis.outerDockerNotMoved = true;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t/* Undock the docker */\n\t\t\t\t\tthis.docker.setDockedShape(undefined);\n\t\t\t\t\t// Set the Docker to the center of the mouse pointer\n\t\t\t\t\t//this.docker.bounds.centerMoveTo(evPos);\n\t\t\t\t\tthis.dockerParent._update();\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tvar shapes = this.facade.getCanvas().getAbstractShapesAtPosition(evPos);\n\t\t\t\t\n\t\t\t\t// Get the top level Shape on these, but not the same as Dockers parent\n\t\t\t\tvar uiObj = shapes.pop();\n\t\t\t\tif (this.docker.parent === uiObj) {\n\t\t\t\t\tuiObj = shapes.pop();\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// If the top level Shape the same as the last Shape, then return\n\t\t\t\tif (this.lastUIObj == uiObj) {\n\t\t\t\t//return;\n\t\t\t\t\n\t\t\t\t// If the top level uiObj instance of Shape and this isn't the parent of the docker \n\t\t\t\t}\n\t\t\t\telse \n\t\t\t\t\tif (uiObj instanceof ORYX.Core.Shape) {\n\t\t\t\t\t\t\n\t\t\t\t\t\t// Ask by the StencilSet if the source, the edge and the target valid connections.\n\t\t\t\t\t\tif (this.docker.parent instanceof ORYX.Core.Edge) {\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tvar highestParent = this.getHighestParentBeforeCanvas(uiObj);\n\t\t\t\t\t\t\t/* Ensure that the shape to dock is not a child shape \n\t\t\t\t\t\t\t * of the same edge.\n\t\t\t\t\t\t\t */\n\t\t\t\t\t\t\tif (highestParent instanceof ORYX.Core.Edge && this.docker.parent === highestParent) \n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tthis.isValid = false;\n\t\t\t\t\t\t\t\tthis.dockerParent._update();\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tthis.isValid = false;\n\t\t\t\t\t\t\tvar curObj = uiObj, orgObj = uiObj;\n\t\t\t\t\t\t\twhile (!this.isValid && curObj && !(curObj instanceof ORYX.Core.Canvas))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tuiObj = curObj;\n\t\t\t\t\t\t\t\tthis.isValid = this.facade.getRules().canConnect({\n\t\t\t\t\t\t\t\t\t\t\tsourceShape: this.dockerSource ? // Is there a docked source \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tthis.dockerSource : // than set this\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t(this.isStartDocker ? // if not and if the Docker is the start docker\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tuiObj : // take the last uiObj\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tundefined), // if not set it to undefined;\n\t\t\t\t\t\t\t\t\t\t\tedgeShape: this.docker.parent,\n\t\t\t\t\t\t\t\t\t\t\ttargetShape: this.dockerTarget ? // Is there a docked target \n\t\t\t\t\t\t\t\t\t\t\tthis.dockerTarget : // than set this\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t(this.isEndDocker ? // if not and if the Docker is not the start docker\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tuiObj : // take the last uiObj\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tundefined) // if not set it to undefined;\n\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tcurObj = curObj.parent;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t// Reset uiObj if no \n\t\t\t\t\t\t\t// valid parent is found\n\t\t\t\t\t\t\tif (!this.isValid){\n\t\t\t\t\t\t\t\tuiObj = orgObj;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tthis.isValid = this.facade.getRules().canConnect({\n\t\t\t\t\t\t\t\tsourceShape: uiObj,\n\t\t\t\t\t\t\t\tedgeShape: this.docker.parent,\n\t\t\t\t\t\t\t\ttargetShape: this.docker.parent\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\t// If there is a lastUIObj, hide the magnets\n\t\t\t\t\t\tif (this.lastUIObj) {\n\t\t\t\t\t\t\tthis.hideMagnets(this.lastUIObj);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\t// If there is a valid connection, show the magnets\n\t\t\t\t\t\tif (this.isValid) {\n\t\t\t\t\t\t\tthis.showMagnets(uiObj);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\t// Set the Highlight Rectangle by these value\n\t\t\t\t\t\tthis.showHighlight(uiObj, this.isValid ? this.VALIDCOLOR : this.INVALIDCOLOR);\n\t\t\t\t\t\t\n\t\t\t\t\t\t// Buffer the current Shape\n\t\t\t\t\t\tthis.lastUIObj = uiObj;\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\t// If there is no top level Shape, then hide the highligting of the last Shape\n\t\t\t\t\t\tthis.hideHighlight();\n\t\t\t\t\t\tthis.lastUIObj ? this.hideMagnets(this.lastUIObj) : null;\n\t\t\t\t\t\tthis.lastUIObj = undefined;\n\t\t\t\t\t\tthis.isValid = false;\n\t\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// Snap to the nearest Magnet\n\t\t\t\tif (this.lastUIObj && this.isValid && !(event.shiftKey || event.ctrlKey)) {\n\t\t\t\t\tsnapToMagnet = this.lastUIObj.magnets.find(function(magnet){\n\t\t\t\t\t\treturn magnet.absoluteBounds().isIncluded(evPos);\n\t\t\t\t\t});\n\t\t\t\t\t\n\t\t\t\t\tif (snapToMagnet) {\n\t\t\t\t\t\tthis.docker.bounds.centerMoveTo(snapToMagnet.absoluteCenterXY());\n\t\t\t\t\t//this.docker.update()\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// Snap to on the nearest Docker of the same parent\n\t\tif(!(event.shiftKey || event.ctrlKey) && !snapToMagnet) {\n\t\t\tvar minOffset = ORYX.CONFIG.DOCKER_SNAP_OFFSET;\n\t\t\tvar nearestX = minOffset + 1;\n\t\t\tvar nearestY = minOffset + 1;\n\t\t\t\n\t\t\tvar dockerCenter = this.docker.bounds.center();\n\t\t\t\n\t\t\tif (this.docker.parent) {\n\t\t\t\t\n\t\t\t\tthis.docker.parent.dockers.each((function(docker){\n\t\t\t\t\tif (this.docker == docker) {\n\t\t\t\t\t\treturn\n\t\t\t\t\t};\n\t\t\t\t\t\n\t\t\t\t\tvar center = docker.referencePoint ? docker.getAbsoluteReferencePoint() : docker.bounds.center();\n\t\t\t\t\t\n\t\t\t\t\tnearestX = Math.abs(nearestX) > Math.abs(center.x - dockerCenter.x) ? center.x - dockerCenter.x : nearestX;\n\t\t\t\t\tnearestY = Math.abs(nearestY) > Math.abs(center.y - dockerCenter.y) ? center.y - dockerCenter.y : nearestY;\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t}).bind(this));\n\t\t\t\t\n\t\t\t\tif (Math.abs(nearestX) < minOffset || Math.abs(nearestY) < minOffset) {\n\t\t\t\t\tnearestX = Math.abs(nearestX) < minOffset ? nearestX : 0;\n\t\t\t\t\tnearestY = Math.abs(nearestY) < minOffset ? nearestY : 0;\n\t\t\t\t\t\n\t\t\t\t\tthis.docker.bounds.centerMoveTo(dockerCenter.x + nearestX, dockerCenter.y + nearestY);\n\t\t\t\t\t//this.docker.update()\n\t\t\t\t} else {\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\tvar previous = this.docker.parent.dockers[Math.max(this.docker.parent.dockers.indexOf(this.docker)-1, 0)];\n\t\t\t\t\tvar next = this.docker.parent.dockers[Math.min(this.docker.parent.dockers.indexOf(this.docker)+1, this.docker.parent.dockers.length-1)];\n\t\t\t\t\t\n\t\t\t\t\tif (previous && next && previous !== this.docker && next !== this.docker){\n\t\t\t\t\t\tvar cp = previous.bounds.center();\n\t\t\t\t\t\tvar cn = next.bounds.center();\n\t\t\t\t\t\tvar cd = this.docker.bounds.center();\n\t\t\t\t\t\t\n\t\t\t\t\t\t// Checks if the point is on the line between previous and next\n\t\t\t\t\t\tif (ORYX.Core.Math.isPointInLine(cd.x, cd.y, cp.x, cp.y, cn.x, cn.y, 10)) {\n\t\t\t\t\t\t\t// Get the rise\n\t\t\t\t\t\t\tvar raise = (Number(cn.y)-Number(cp.y))/(Number(cn.x)-Number(cp.x));\n\t\t\t\t\t\t\t// Calculate the intersection point\n\t\t\t\t\t\t\tvar intersecX = ((cp.y-(cp.x*raise))-(cd.y-(cd.x*(-Math.pow(raise,-1)))))/((-Math.pow(raise,-1))-raise);\n\t\t\t\t\t\t\tvar intersecY = (cp.y-(cp.x*raise))+(raise*intersecX);\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif(isNaN(intersecX) || isNaN(intersecY)) {return;}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tthis.docker.bounds.centerMoveTo(intersecX, intersecY);\n\t\t\t\t\t\t}\n\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\t//this.facade.getCanvas().update();\n\t\tthis.dockerParent._update();\n\t},\n\n\t/**\n\t * Docker MouseUp Handler\n\t *\n\t */\n\tdockerMovedFinished: function(event) {\n\t\t\n\t\t/* Reset to buffered shape selection */\n\t\tthis.facade.setSelection(this.shapeSelection);\n\t\t\n\t\t// Hide the border\n\t\tthis.hideHighlight();\n\t\t\n\t\t// Show all Labels from Docker\n\t\tthis.dockerParent.getLabels().each(function(label){\n\t\t\tlabel.show();\n\t\t\t//label.update();\n\t\t});\n\t\n\t\t// If there is a last top level Shape\n\t\tif(this.lastUIObj && (this.isStartDocker || this.isEndDocker)){\t\t\t\t\n\t\t\t// If there is a valid connection, the set as a docked Shape to them\n\t\t\tif(this.isValid) {\n\t\t\t\t\n\t\t\t\tthis.docker.setDockedShape(this.lastUIObj);\t\n\t\t\t\t\n\t\t\t\tthis.facade.raiseEvent({\n\t\t\t\t\ttype \t:ORYX.CONFIG.EVENT_DRAGDOCKER_DOCKED, \n\t\t\t\t\tdocker\t: this.docker,\n\t\t\t\t\tparent\t: this.docker.parent,\n\t\t\t\t\ttarget\t: this.lastUIObj\n\t\t\t\t});\n\t\t\t}\n\t\t\t\n\t\t\tthis.hideMagnets(this.lastUIObj);\n\t\t}\n\t\t\n\t\t// Hide the Docker\n\t\tthis.docker.hide();\n\t\t\n\t\tif(this.outerDockerNotMoved) {\n\t\t\t// Get the EventPosition and all Shapes on these point\n\t\t\tvar evPos = this.facade.eventCoordinates(event);\n\t\t\tvar shapes = this.facade.getCanvas().getAbstractShapesAtPosition(evPos);\n\t\t\t\n\t\t\t/* Remove edges from selection */\n\t\t\tvar shapeWithoutEdges = shapes.findAll(function(node) {\n\t\t\t\treturn node instanceof ORYX.Core.Node;\n\t\t\t});\n\t\t\tshapes = shapeWithoutEdges.length ? shapeWithoutEdges : shapes;\n\t\t\tthis.facade.setSelection(shapes);\n\t\t} else {\n\t\t\t//Command-Pattern for dragging one docker\n\t\t\tvar dragDockerCommand = ORYX.Core.Command.extend({\n\t\t\t\tconstruct: function(docker, newPos, oldPos, newDockedShape, oldDockedShape, facade){\n\t\t\t\t\tthis.docker \t\t= docker;\n\t\t\t\t\tthis.index\t\t\t= docker.parent.dockers.indexOf(docker);\n\t\t\t\t\tthis.newPosition\t= newPos;\n\t\t\t\t\tthis.newDockedShape = newDockedShape;\n\t\t\t\t\tthis.oldPosition\t= oldPos;\n\t\t\t\t\tthis.oldDockedShape\t= oldDockedShape;\n\t\t\t\t\tthis.facade\t\t\t= facade;\n\t\t\t\t\tthis.index\t\t\t= docker.parent.dockers.indexOf(docker);\n\t\t\t\t\tthis.shape\t\t\t= docker.parent;\n\t\t\t\t\t\n\t\t\t\t},\t\t\t\n\t\t\t\texecute: function(){\n\t\t\t\t\tif (!this.docker.parent){\n\t\t\t\t\t\tthis.docker = this.shape.dockers[this.index];\n\t\t\t\t\t}\n\t\t\t\t\tthis.dock( this.newDockedShape, this.newPosition );\n\t\t\t\t\tthis.removedDockers = this.shape.removeUnusedDockers();\n\t\t\t\t\tthis.facade.updateSelection();\n\t\t\t\t},\n\t\t\t\trollback: function(){\n\t\t\t\t\tthis.dock( this.oldDockedShape, this.oldPosition );\n\t\t\t\t\t(this.removedDockers||$H({})).each(function(d){\n\t\t\t\t\t\tthis.shape.add(d.value, Number(d.key));\n\t\t\t\t\t\tthis.shape._update(true);\n\t\t\t\t\t}.bind(this));\n\t\t\t\t\tthis.facade.updateSelection();\n\t\t\t\t},\n\t\t\t\tdock:function( toDockShape, pos ){\t\t\t\n\t\t\t\t\t// Set the Docker to the new Shape\n\t\t\t\t\tthis.docker.setDockedShape( undefined );\n\t\t\t\t\tif( toDockShape ){\t\t\t\n\t\t\t\t\t\tthis.docker.setDockedShape( toDockShape );\t\n\t\t\t\t\t\tthis.docker.setReferencePoint( pos );\n\t\t\t\t\t\t//this.docker.update();\t\n\t\t\t\t\t\t//this.docker.parent._update();\t\t\t\t\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.docker.bounds.centerMoveTo( pos );\n\t\t\t\t\t}\n\t\n\t\t\t\t\tthis.facade.getCanvas().update();\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t\t\n\t\t\tif (this.docker.parent){\n\t\t\t\t// Instanziate the dockCommand\n\t\t\t\tvar command = new dragDockerCommand(this.docker, this.docker.getDockedShape() ? this.docker.referencePoint : this.docker.bounds.center(), this._commandArg.refPoint, this.docker.getDockedShape(), this._commandArg.dockedShape, this.facade);\n\t\t\t\tthis.facade.executeCommands( [command] );\t\n\t\t\t}\n\t\t}\n\t\n\t\t// Update all Shapes\n\t\t//this.facade.updateSelection();\n\t\t\t\n\t\t// Undefined all variables\n\t\tthis.docker \t\t= undefined;\n\t\tthis.dockerParent   = undefined;\n\t\tthis.dockerSource \t= undefined;\n\t\tthis.dockerTarget \t= undefined;\t\n\t\tthis.lastUIObj \t\t= undefined;\t\t\n\t},\n\t\n\t/**\n\t * Hide the highlighting\n\t */\n\thideHighlight: function() {\n\t\tthis.facade.raiseEvent({type:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE, highlightId:'validDockedShape'});\n\t},\n\n\t/**\n\t * Show the highlighting\n\t *\n\t */\n\tshowHighlight: function(uiObj, color) {\n\t\t\n\t\tthis.facade.raiseEvent({\n\t\t\t\t\t\t\t\t\t\ttype:\t\tORYX.CONFIG.EVENT_HIGHLIGHT_SHOW, \n\t\t\t\t\t\t\t\t\t\thighlightId:'validDockedShape',\n\t\t\t\t\t\t\t\t\t\telements:\t[uiObj],\n\t\t\t\t\t\t\t\t\t\tcolor:\t\tcolor\n\t\t\t\t\t\t\t\t\t});\n\t},\n\t\n\tshowMagnets: function(uiObj){\n\t\tuiObj.magnets.each(function(magnet) {\n\t\t\tmagnet.show();\n\t\t});\n\t},\n\t\n\thideMagnets: function(uiObj){\n\t\tuiObj.magnets.each(function(magnet) {\n\t\t\tmagnet.hide();\n\t\t});\n\t},\n\t\n\tgetHighestParentBeforeCanvas: function(shape) {\n\t\tif(!(shape instanceof ORYX.Core.Shape)) {return undefined;}\n\t\t\n\t\tvar parent = shape.parent;\n\t\twhile(parent && !(parent.parent instanceof ORYX.Core.Canvas)) {\n\t\t\tparent = parent.parent;\n\t\t}\t\n\t\t\n\t\treturn parent;\t\t\n\t}\t\n\n});\n\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nif(!ORYX.Plugins)\n\tORYX.Plugins = new Object();\n\nORYX.Plugins.AddDocker = Clazz.extend({\n\n\t/**\n\t *\tConstructor\n\t *\t@param {Object} Facade: The Facade of the Editor\n\t */\n\tconstruct: function(facade) {\n\t\tthis.facade = facade;\n\t\tthis.enableAdd = false;\n\t\tthis.enableRemove = false;\n\t\t\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_MOUSEDOWN, this.handleMouseDown.bind(this));\n\t},\n\t\n\tsetEnableAdd: function(enable){\n\t\tthis.enableAdd = enable;\n\t\t\n\t\tif(this.enableAdd) {\n    \t\tjQuery(\"#add-bendpoint-button\").addClass('pressed');\n    \t} else {\n    \t\tjQuery(\"#add-bendpoint-button\").removeClass('pressed');\n    \t\tjQuery(\"#add-bendpoint-button\").blur();\n    \t}\n\t},\n\tsetEnableRemove: function(enable){\n\t\tthis.enableRemove = enable;\n\t\t\n\t\tif(this.enableRemove) {\n    \t\tjQuery(\"#remove-bendpoint-button\").addClass('pressed');\n    \t} else {\n    \t\tjQuery(\"#remove-bendpoint-button\").removeClass('pressed');\n    \t\tjQuery(\"#remove-bendpoint-button\").blur();\n    \t}\n\t},\n\t\n    enabledAdd: function(enable){\n        return this.enableAdd;\n    },\n    enabledRemove: function(){\n        return this.enableRemove;\n    },\n\t\n\t/**\n\t * MouseDown Handler\n\t *\n\t */\t\n\thandleMouseDown: function(event, uiObj) {\n\t\tif (this.enabledAdd() && uiObj instanceof ORYX.Core.Edge) {\n            this.newDockerCommand({\n                edge: uiObj,\n                position: this.facade.eventCoordinates(event)\n            });\n            this.setEnableAdd(false);\n            \n\t\t} else if (this.enabledRemove() &&\n\t\t\t\t   uiObj instanceof ORYX.Core.Controls.Docker &&\n\t\t\t\t   uiObj.parent instanceof ORYX.Core.Edge) {\n            this.newDockerCommand({\n                edge: uiObj.parent,\n                docker: uiObj\n            });\n            this.setEnableRemove(false);\n        }\n\t\tdocument.body.style.cursor = 'default';\n\t},\n    \n    // Options: edge (required), position (required if add), docker (required if delete)\n    newDockerCommand: function(options){\n        if(!options.edge)\n            return;\n\n        var commandClass = ORYX.Core.Command.extend({\n            construct: function(addEnabled, deleteEnabled, edge, docker, pos, facade){\n                this.addEnabled = addEnabled;\n                this.deleteEnabled = deleteEnabled;\n                this.edge = edge;\n                this.docker = docker;\n                this.pos = pos;\n                this.facade = facade;\n            },\n            execute: function(){\n                if (this.addEnabled) {\n\t\t\t\t\tif (!this.docker){\n                    \tthis.docker = this.edge.addDocker(this.pos);\n\t\t\t\t\t\tthis.index = this.edge.dockers.indexOf(this.docker);\n\t\t\t\t\t} else {\n                    \tthis.edge.add(this.docker, this.index);\n\t\t\t\t\t}\n                }\n                else if (this.deleteEnabled) {\n\t\t\t\t\tthis.index = this.edge.dockers.indexOf(this.docker);\n                    this.pos = this.docker.bounds.center();\n                    this.edge.removeDocker(this.docker);\n                }\n                this.edge.getLabels().invoke(\"show\");\n                this.facade.getCanvas().update();\n                this.facade.updateSelection();\n            },\n            rollback: function(){\n                if (this.addEnabled) {\n                    if (this.docker instanceof ORYX.Core.Controls.Docker) {\n                        this.edge.removeDocker(this.docker);\n                    }\n                }\n                else if (this.deleteEnabled) {\n                    this.edge.add(this.docker, this.index);\n                }\n                this.edge.getLabels().invoke(\"show\");\n                this.facade.getCanvas().update();\n                this.facade.updateSelection();\n            }\n        })\n        \n        var command = new commandClass(this.enabledAdd(), this.enabledRemove(), options.edge, options.docker, options.position, this.facade);\n        \n        this.facade.executeCommands([command]);\n    }\n});\n\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nif(!ORYX.Plugins)\n\tORYX.Plugins = new Object();\n\n ORYX.Plugins.SelectionFrame = Clazz.extend({\n\n\tconstruct: function(facade) {\n\t\tthis.facade = facade;\n\n\t\t// Register on MouseEvents\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_MOUSEDOWN, this.handleMouseDown.bind(this));\n\t\tdocument.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEUP, this.handleMouseUp.bind(this), true);\n\n\t\t// Some initiale variables\n\t\tthis.position \t\t= {x:0, y:0};\n\t\tthis.size \t\t\t= {width:0, height:0};\n\t\tthis.offsetPosition = {x: 0, y: 0};\n\n\t\t// (Un)Register Mouse-Move Event\n\t\tthis.moveCallback \t= undefined;\n\t\tthis.offsetScroll\t= {x:0,y:0};\n\t\t// HTML-Node of Selection-Frame\n\t\tthis.node = ORYX.Editor.graft(\"http://www.w3.org/1999/xhtml\", $('canvasSection'),\n\t\t\t['div', {'class':'Oryx_SelectionFrame'}]);\n\n\t\tthis.hide();\n\t},\n\n\thandleMouseDown: function(event, uiObj) {\n\t\t// If there is the Canvas\n\t\tif( uiObj instanceof ORYX.Core.Canvas ) {\n\t\t\t// Calculate the Offset\n\t\t\tvar scrollNode = uiObj.rootNode.parentNode.parentNode;\n\t\t\t\t\t\t\n\t\t\tvar a = this.facade.getCanvas().node.getScreenCTM();\n\t\t\tthis.offsetPosition = {\n\t\t\t\tx: a.e,\n\t\t\t\ty: a.f\n\t\t\t};\n\n\t\t\t// Set the new Position\n\t\t\tthis.setPos({\n\t\t\t    x: Event.pointerX(event) - jQuery(\"#canvasSection\").offset().left, \n\t\t\t\ty: Event.pointerY(event) - jQuery(\"#canvasSection\").offset().top + 5\n\t\t\t});\n\t\t\t\n\t\t\t// Reset the size\n\t\t\tthis.resize({width:0, height:0});\n\t\t\tthis.moveCallback = this.handleMouseMove.bind(this);\n\t\t\n\t\t\t// Register Mouse-Move Event\n\t\t\tdocument.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, this.moveCallback, false);\n\n\t\t\tthis.offsetScroll\t\t= {x:scrollNode.scrollLeft,y:scrollNode.scrollTop};\n\t\t\t\n\t\t\t// Show the Frame\n\t\t\tthis.show();\n\t\t}\n\n\t\tEvent.stop(event);\n\t},\n\n\thandleMouseUp: function(event) {\n\t\t// If there was an MouseMoving\n\t\tif(this.moveCallback) {\n\t\t\t// Hide the Frame\n\t\t\tthis.hide();\n\n\t\t\t// Unregister Mouse-Move\n\t\t\tdocument.documentElement.removeEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, this.moveCallback, false);\t\t\t\n\t\t\n\t\t\tthis.moveCallback = undefined;\n\n\t\t\tvar corrSVG = this.facade.getCanvas().node.getScreenCTM();\n\n\t\t\t// Calculate the positions of the Frame\n\t\t\tvar a = {\n\t\t\t\tx: this.size.width > 0 ? this.position.x : this.position.x + this.size.width,\n\t\t\t\ty: this.size.height > 0 ? this.position.y : this.position.y + this.size.height\n\t\t\t};\n\n\t\t\tvar b = {\n\t\t\t\tx: a.x + Math.abs(this.size.width),\n\t\t\t\ty: a.y + Math.abs(this.size.height)\n\t\t\t};\n\t\t\t\n\t\t\tvar additionalIEZoom = 1;\n            if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) {\n                var ua = navigator.userAgent;\n                if (ua.indexOf('MSIE') >= 0) {\n                    //IE 10 and below\n                    var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100);\n                    if (zoom !== 100) {\n                        additionalIEZoom = zoom / 100\n                    }\n                }\n            }\n            \n            if (additionalIEZoom === 1) {\n                a.x = a.x - (corrSVG.e - jQuery(\"#canvasSection\").offset().left);\n                a.y = a.y - (corrSVG.f - jQuery(\"#canvasSection\").offset().top);\n                b.x = b.x - (corrSVG.e - jQuery(\"#canvasSection\").offset().left);\n                b.y = b.y - (corrSVG.f - jQuery(\"#canvasSection\").offset().top);\n            \n            } else {\n                 var canvasOffsetLeft = jQuery(\"#canvasSection\").offset().left;\n                 var canvasScrollLeft = jQuery(\"#canvasSection\").scrollLeft();\n                 var canvasScrollTop = jQuery(\"#canvasSection\").scrollTop();\n                 \n                 var offset = a.e - (canvasOffsetLeft * additionalIEZoom);\n                 var additionaloffset = 0;\n                 if (offset > 10) {\n                     additionaloffset = (offset / additionalIEZoom) - offset;\n                 }\n                 \n                 a.x = a.x - (corrSVG.e - (canvasOffsetLeft * additionalIEZoom) + additionaloffset + ((canvasScrollLeft * additionalIEZoom) - canvasScrollLeft));\n                 a.y = a.y - (corrSVG.f - (jQuery(\"#canvasSection\").offset().top * additionalIEZoom) + ((canvasScrollTop * additionalIEZoom) - canvasScrollTop));\n                 b.x = b.x - (corrSVG.e - (canvasOffsetLeft * additionalIEZoom) + additionaloffset + ((canvasScrollLeft * additionalIEZoom) - canvasScrollLeft));\n                 b.y = b.y - (corrSVG.f - (jQuery(\"#canvasSection\").offset().top * additionalIEZoom) + ((canvasScrollTop * additionalIEZoom) - canvasScrollTop));\n            }\n\t\t\t\n\t\t\t\n\n\t\t\t// Fit to SVG-Coordinates\n\t\t\ta.x /= corrSVG.a; a.y /= corrSVG.d;\n\t\t\tb.x /= corrSVG.a; b.y /= corrSVG.d;\n\t\t\t\n\t\t\t// Calculate the elements from the childs of the canvas\n\t\t\tvar elements = this.facade.getCanvas().getChildShapes(true).findAll(function(value) {\n\t\t\t\tvar absBounds = value.absoluteBounds();\n\t\t\t\t\n\t\t\t\tvar bA = absBounds.upperLeft();\n\t\t\t\tvar bB = absBounds.lowerRight();\n\t\t\t\t\n\t\t\t\tif(bA.x > a.x && bA.y > a.y && bB.x < b.x && bB.y < b.y)\n\t\t\t\t\treturn true;\n\t\t\t\treturn false;\n\t\t\t});\n\n\t\t\t// Set the selection\n\t\t\tthis.facade.setSelection(elements);\n\t\t}\n\t},\n\n\thandleMouseMove: function(event) {\n\t\t// Calculate the size\n\t\tvar size = {\n\t\t\twidth\t: Event.pointerX(event) - this.position.x - jQuery(\"#canvasSection\").offset().left,\n\t\t\theight\t: Event.pointerY(event) - this.position.y - jQuery(\"#canvasSection\").offset().top + 5\n\t\t};\n\n\t\tvar scrollNode \t= this.facade.getCanvas().rootNode.parentNode.parentNode;\n\t\tsize.width \t\t-= this.offsetScroll.x - scrollNode.scrollLeft; \n\t\tsize.height \t-= this.offsetScroll.y - scrollNode.scrollTop;\n\t\t\t\t\t\t\n\t\t// Set the size\n\t\tthis.resize(size);\n\n\t\tEvent.stop(event);\n\t},\n\n\thide: function() {\n\t\tthis.node.style.display = \"none\";\n\t},\n\n\tshow: function() {\n\t\tthis.node.style.display = \"\";\n\t},\n\n\tsetPos: function(pos) {\n\t\t// Set the Position\n\t\tthis.node.style.top = pos.y + \"px\";\n\t\tthis.node.style.left = pos.x + \"px\";\n\t\tthis.position = pos;\n\t},\n\n\tresize: function(size) {\n\n\t\t// Calculate the negative offset\n\t\tthis.setPos(this.position);\n\t\tthis.size = Object.clone(size);\n\t\t\n\t\tif(size.width < 0) {\n\t\t\tthis.node.style.left = (this.position.x + size.width) + \"px\";\n\t\t\tsize.width = - size.width;\n\t\t}\n\t\tif(size.height < 0) {\n\t\t\tthis.node.style.top = (this.position.y + size.height) + \"px\";\n\t\t\tsize.height = - size.height;\n\t\t}\n\n\t\t// Set the size\n\t\tthis.node.style.width = size.width + \"px\";\n\t\tthis.node.style.height = size.height + \"px\";\n\t}\n\n});\n\n\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nif(!ORYX.Plugins)\n\tORYX.Plugins = new Object(); \n\nORYX.Plugins.ShapeHighlighting = Clazz.extend({\n\n\tconstruct: function(facade) {\n\t\t\n\t\tthis.parentNode = facade.getCanvas().getSvgContainer();\n\t\t\n\t\t// The parent Node\n\t\tthis.node = ORYX.Editor.graft(\"http://www.w3.org/2000/svg\", this.parentNode,\n\t\t\t\t\t['g']);\n\n\t\tthis.highlightNodes = {};\n\t\t\n\t\tfacade.registerOnEvent(ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW, this.setHighlight.bind(this));\n\t\tfacade.registerOnEvent(ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE, this.hideHighlight.bind(this));\t\t\n\n\t},\n\n\tsetHighlight: function(options) {\n\t\tif(options && options.highlightId){\n\t\t\tvar node = this.highlightNodes[options.highlightId];\n\t\t\t\n\t\t\tif(!node){\n\t\t\t\tnode= ORYX.Editor.graft(\"http://www.w3.org/2000/svg\", this.node,\n\t\t\t\t\t['path', {\n\t\t\t\t\t\t\"stroke-width\": 2.0, \"fill\":\"none\"\n\t\t\t\t\t\t}]);\t\n\t\t\t\n\t\t\t\tthis.highlightNodes[options.highlightId] = node;\n\t\t\t}\n\n\t\t\tif(options.elements && options.elements.length > 0) {\n\t\t\t\t\n\t\t\t\tthis.setAttributesByStyle( node, options );\n\t\t\t\tthis.show(node);\n\t\t\t\n\t\t\t} else {\n\t\t\t\n\t\t\t\tthis.hide(node);\t\t\t\n\t\t\t\n\t\t\t}\n\t\t\t\n\t\t}\n\t},\n\t\n\thideHighlight: function(options) {\n\t\tif(options && options.highlightId && this.highlightNodes[options.highlightId]){\n\t\t\tthis.hide(this.highlightNodes[options.highlightId]);\n\t\t}\t\t\n\t},\n\t\n\thide: function(node) {\n\t\tnode.setAttributeNS(null, 'display', 'none');\n\t},\n\n\tshow: function(node) {\n\t\tnode.setAttributeNS(null, 'display', '');\n\t},\n\t\n\tsetAttributesByStyle: function( node, options ){\n\t\t\n\t\t// If the style say, that it should look like a rectangle\n\t\tif( options.style && options.style == ORYX.CONFIG.SELECTION_HIGHLIGHT_STYLE_RECTANGLE ){\n\t\t\t\n\t\t\t// Set like this\n\t\t\tvar bo = options.elements[0].absoluteBounds();\n\t\t\t\n\t\t\tvar strWidth = options.strokewidth ? options.strokewidth \t: ORYX.CONFIG.BORDER_OFFSET\n\t\t\t\n\t\t\tnode.setAttributeNS(null, \"d\", this.getPathRectangle( bo.a, bo.b , strWidth ) );\n\t\t\tnode.setAttributeNS(null, \"stroke\", \t\toptions.color \t\t? options.color \t\t: ORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR);\n\t\t\tnode.setAttributeNS(null, \"stroke-opacity\", options.opacity \t? options.opacity \t\t: 0.2);\n\t\t\tnode.setAttributeNS(null, \"stroke-width\", \tstrWidth);\n\t\t\t\t\t\t\n\t\t} else if(options.elements.length == 1 \n\t\t\t\t\t&& options.elements[0] instanceof ORYX.Core.Edge &&\n\t\t\t\t\toptions.highlightId != \"selection\") {\n\t\t\t\n\t\t\t/* Highlight containment of edge's childs */\n\t\t\tvar path = this.getPathEdge(options.elements[0].dockers);\n\t\t\tif (path && path.length > 0)\n\t\t\t{\n\t\t\t\tnode.setAttributeNS(null, \"d\", path);\n\t\t\t}\n\t\t\tnode.setAttributeNS(null, \"stroke\", options.color ? options.color : ORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR);\n\t\t\tnode.setAttributeNS(null, \"stroke-opacity\", options.opacity ? options.opacity : 0.2);\n\t\t\tnode.setAttributeNS(null, \"stroke-width\", \tORYX.CONFIG.OFFSET_EDGE_BOUNDS);\n\t\t\t\n\t\t}else {\n\t\t\t// If not, set just the corners\n\t\t\tvar path = this.getPathByElements(options.elements);\n\t\t\tif (path && path.length > 0)\n\t\t\t{\n\t\t\t\tnode.setAttributeNS(null, \"d\", path);\n\t\t\t}\n\t\t\tnode.setAttributeNS(null, \"stroke\", options.color ? options.color : ORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR);\n\t\t\tnode.setAttributeNS(null, \"stroke-opacity\", options.opacity ? options.opacity : 1.0);\n\t\t\tnode.setAttributeNS(null, \"stroke-width\", \toptions.strokewidth ? options.strokewidth \t: 2.0);\n\t\t\t\t\t\t\n\t\t}\n\t},\n\t\n\tgetPathByElements: function(elements){\n\t\tif(!elements || elements.length <= 0) {return undefined}\n\t\t\n\t\t// Get the padding and the size\n\t\tvar padding = ORYX.CONFIG.SELECTED_AREA_PADDING;\n\t\t\n\t\tvar path = \"\"\n\t\t\n\t\t// Get thru all Elements\n\t\telements.each((function(element) {\n\t\t\tif(!element) {return}\n\t\t\t// Get the absolute Bounds and the two Points\n\t\t\tvar bounds = element.absoluteBounds();\n\t\t\tbounds.widen(padding)\n\t\t\tvar a = bounds.upperLeft();\n\t\t\tvar b = bounds.lowerRight();\n\t\t\t\n\t\t\tpath = path + this.getPath(a ,b);\n\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t}).bind(this));\n\n\t\treturn path;\n\t\t\n\t},\n\n\tgetPath: function(a, b){\n\t\t\t\t\n\t\treturn this.getPathCorners(a, b);\n\t\n\t},\n\t\t\t\n\tgetPathCorners: function(a, b){\n\n\t\tvar size = ORYX.CONFIG.SELECTION_HIGHLIGHT_SIZE;\n\t\t\t\t\n\t\tvar path = \"\"\n\n\t\t// Set: Upper left \n\t\tpath = path + \"M\" + a.x + \" \" + (a.y + size) + \" l0 -\" + size + \" l\" + size + \" 0 \";\n\t\t// Set: Lower left\n\t\tpath = path + \"M\" + a.x + \" \" + (b.y - size) + \" l0 \" + size + \" l\" + size + \" 0 \";\n\t\t// Set: Lower right\n\t\tpath = path + \"M\" + b.x + \" \" + (b.y - size) + \" l0 \" + size + \" l-\" + size + \" 0 \";\n\t\t// Set: Upper right\n\t\tpath = path + \"M\" + b.x + \" \" + (a.y + size) + \" l0 -\" + size + \" l-\" + size + \" 0 \";\n\t\t\n\t\treturn path;\n\t},\n\t\n\tgetPathRectangle: function(a, b, strokeWidth){\n\n\t\tvar size = ORYX.CONFIG.SELECTION_HIGHLIGHT_SIZE;\n\n\t\tvar path \t= \"\"\n\t\tvar offset \t= strokeWidth / 2.0;\n\t\t \n\t\t// Set: Upper left \n\t\tpath = path + \"M\" + (a.x + offset) + \" \" + (a.y);\n\t\tpath = path + \" L\" + (a.x + offset) + \" \" + (b.y - offset);\n\t\tpath = path + \" L\" + (b.x - offset) + \" \" + (b.y - offset);\n\t\tpath = path + \" L\" + (b.x - offset) + \" \" + (a.y + offset);\n\t\tpath = path + \" L\" + (a.x + offset) + \" \" + (a.y + offset);\n\n\t\treturn path;\n\t},\n\t\n\tgetPathEdge: function(edgeDockers) {\n\t\tvar length = edgeDockers.length;\n\t\tvar path = \"M\" + edgeDockers[0].bounds.center().x + \" \" \n\t\t\t\t\t+  edgeDockers[0].bounds.center().y;\n\t\t\n\t\tfor(i=1; i<length; i++) {\n\t\t\tvar dockerPoint = edgeDockers[i].bounds.center();\n\t\t\tpath = path + \" L\" + dockerPoint.x + \" \" +  dockerPoint.y;\n\t\t}\n\t\t\n\t\treturn path;\n\t}\n\t\n});\n\n \nORYX.Plugins.HighlightingSelectedShapes = Clazz.extend({\n\n\tconstruct: function(facade) {\n\t\tthis.facade = facade;\n\t\tthis.opacityFull = 0.9;\n\t\tthis.opacityLow = 0.4;\n\n\t\t// Register on Dragging-Events for show/hide of ShapeMenu\n\t\t//this.facade.registerOnEvent(ORYX.CONFIG.EVENT_DRAGDROP_START, this.hide.bind(this));\n\t\t//this.facade.registerOnEvent(ORYX.CONFIG.EVENT_DRAGDROP_END,  this.show.bind(this));\t\t\n\t},\n\n\t/**\n\t * On the Selection-Changed\n\t *\n\t */\n\tonSelectionChanged: function(event) {\n\t\tif(event.elements && event.elements.length > 1) {\n\t\t\tthis.facade.raiseEvent({\n\t\t\t\t\t\t\t\t\t\ttype:\t\tORYX.CONFIG.EVENT_HIGHLIGHT_SHOW, \n\t\t\t\t\t\t\t\t\t\thighlightId:'selection',\n\t\t\t\t\t\t\t\t\t\telements:\tevent.elements.without(event.subSelection),\n\t\t\t\t\t\t\t\t\t\tcolor:\t\tORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR,\n\t\t\t\t\t\t\t\t\t\topacity: \t!event.subSelection ? this.opacityFull : this.opacityLow\n\t\t\t\t\t\t\t\t\t});\n\n\t\t\tif(event.subSelection){\n\t\t\t\tthis.facade.raiseEvent({\n\t\t\t\t\t\t\t\t\t\t\ttype:\t\tORYX.CONFIG.EVENT_HIGHLIGHT_SHOW, \n\t\t\t\t\t\t\t\t\t\t\thighlightId:'subselection',\n\t\t\t\t\t\t\t\t\t\t\telements:\t[event.subSelection],\n\t\t\t\t\t\t\t\t\t\t\tcolor:\t\tORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR,\n\t\t\t\t\t\t\t\t\t\t\topacity: \tthis.opacityFull\n\t\t\t\t\t\t\t\t\t\t});\t\n\t\t\t} else {\n\t\t\t\tthis.facade.raiseEvent({type:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE, highlightId:'subselection'});\t\t\t\t\n\t\t\t}\t\t\t\t\t\t\n\t\t\t\n\t\t} else {\n\t\t\tthis.facade.raiseEvent({type:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE, highlightId:'selection'});\n\t\t\tthis.facade.raiseEvent({type:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE, highlightId:'subselection'});\n\t\t}\t\t\n\t}\n});/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nif (!ORYX.Plugins) \n    ORYX.Plugins = new Object();\n\nORYX.Plugins.Overlay = Clazz.extend({\n\n    facade: undefined,\n\t\n\tstyleNode: undefined,\n    \n    construct: function(facade){\n\t\t\n        this.facade = facade;\n\n\t\tthis.changes = [];\n\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_OVERLAY_SHOW, this.show.bind(this));\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_OVERLAY_HIDE, this.hide.bind(this));\t\n\n\t\tthis.styleNode = document.createElement('style')\n\t\tthis.styleNode.setAttributeNS(null, 'type', 'text/css')\n\t\t\n\t\tdocument.getElementsByTagName('head')[0].appendChild( this.styleNode )\n\n    },\n\t\n\t/**\n\t * Show the overlay for specific nodes\n\t * @param {Object} options\n\t * \n\t * \tString\t\t\t\toptions.id\t\t- MUST - Define the id of the overlay (is needed for the hiding of this overlay)\t\t\n\t *\tORYX.Core.Shape[] \toptions.shapes \t- MUST - Define the Shapes for the changes\n\t * \tattr-name:value\t\toptions.changes\t- Defines all the changes which should be shown\n\t * \n\t * \n\t */\n\tshow: function( options ){\n\t\t\n\t\t// Checks if all arguments are available\n\t\tif( \t!options || \n\t\t\t\t!options.shapes || !options.shapes instanceof Array ||\n\t\t\t\t!options.id\t|| !options.id instanceof String || options.id.length == 0) { \n\t\t\t\t\n\t\t\t\t\treturn\n\t\t\t\t\t\n\t\t}\n\t\t\n\t\t//if( this.changes[options.id]){\n\t\t//\tthis.hide( options )\n\t\t//}\n\t\t\t\n\n\t\t// Checked if attributes are setted\n\t\tif( options.attributes ){\n\t\t\t\n\t\t\t// FOR EACH - Shape\n\t\t\toptions.shapes.each(function(el){\n\t\t\t\t\n\t\t\t\t// Checks if the node is a Shape\n\t\t\t\tif( !el instanceof ORYX.Core.Shape){ return }\n\t\t\t\t\n\t\t\t\tthis.setAttributes( el.node , options.attributes )\n\t\t\t\t\n\t\t\t}.bind(this))\n\n\t\t}\t\n\t\t\n\t\tvar isSVG = true\n\t\ttry {\n\t\t\tisSVG = options.node && options.node instanceof SVGElement;\n\t\t} catch(e){}\n\t\t\n\t\t// Checks if node is setted and if this is an SVGElement\t\t\n\t\tif ( options.node && isSVG) {\n\t\t\t\n\t\t\toptions[\"_temps\"] = []\n\t\t\t\t\t\t\n\t\t\t// FOR EACH - Node\n\t\t\toptions.shapes.each(function(el, index){\n\t\t\t\t\n\t\t\t\t// Checks if the node is a Shape\n\t\t\t\tif( !el instanceof ORYX.Core.Shape){ return }\n\t\t\t\t\n\t\t\t\tvar _temp = {}\n\t\t\t\t_temp.svg = options.dontCloneNode ? options.node : options.node.cloneNode( true );\n\t\t\t\t\n\t\t\t\t// Add the svg node to the ORYX-Shape\n\t\t\t\tel.node.firstChild.appendChild( _temp.svg )\t\t\n\t\t\t\t\n\t\t\t\t// If\n\t\t\t\tif (el instanceof ORYX.Core.Edge && !options.nodePosition) {\n\t\t\t\t\toptions['nodePosition'] = \"START\"\n\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t// If the node position is setted, it has to be transformed\n\t\t\t\tif( options.nodePosition ){\n\t\t\t\t\t\n\t\t\t\t\tvar b = el.bounds;\n\t\t\t\t\tvar p = options.nodePosition.toUpperCase();\n\t\t\t\t\t\n\t\t\t\t\t// Check the values of START and END\n\t\t\t\t\tif( el instanceof ORYX.Core.Node && p == \"START\"){\n\t\t\t\t\t\tp = \"NW\";\n\t\t\t\t\t} else if(el instanceof ORYX.Core.Node && p == \"END\"){\n\t\t\t\t\t\tp = \"SE\";\n\t\t\t\t\t} else if(el instanceof ORYX.Core.Edge && p == \"START\"){\n\t\t\t\t\t\tb = el.getDockers().first().bounds\n\t\t\t\t\t} else if(el instanceof ORYX.Core.Edge && p == \"END\"){\n\t\t\t\t\t\tb = el.getDockers().last().bounds\n\t\t\t\t\t}\n\n\t\t\t\t\t// Create a callback for the changing the position \n\t\t\t\t\t// depending on the position string\n\t\t\t\t\t_temp.callback = function(){\n\t\t\t\t\t\t\n\t\t\t\t\t\tvar x = 0; var y = 0;\n\t\t\t\t\t\t\n\t\t\t\t\t\tif( p == \"NW\" ){\n\t\t\t\t\t\t\t// Do Nothing\n\t\t\t\t\t\t} else if( p == \"N\" ) {\n\t\t\t\t\t\t\tx = b.width() / 2;\n\t\t\t\t\t\t} else if( p == \"NE\" ) {\n\t\t\t\t\t\t\tx = b.width();\n\t\t\t\t\t\t} else if( p == \"E\" ) {\n\t\t\t\t\t\t\tx = b.width(); y = b.height() / 2;\n\t\t\t\t\t\t} else if( p == \"SE\" ) {\n\t\t\t\t\t\t\tx = b.width(); y = b.height();\n\t\t\t\t\t\t} else if( p == \"S\" ) {\n\t\t\t\t\t\t\tx = b.width() / 2; y = b.height();\n\t\t\t\t\t\t} else if( p == \"SW\" ) {\n\t\t\t\t\t\t\ty = b.height();\n\t\t\t\t\t\t} else if( p == \"W\" ) {\n\t\t\t\t\t\t\ty = b.height() / 2;\n\t\t\t\t\t\t} else if( p == \"START\" || p == \"END\") {\n\t\t\t\t\t\t\tx = b.width() / 2; y = b.height() / 2;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tif( el instanceof ORYX.Core.Edge){\n\t\t\t\t\t\t\tx  += b.upperLeft().x ; y  += b.upperLeft().y ;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\t_temp.svg.setAttributeNS(null, \"transform\", \"translate(\" + x + \", \" + y + \")\")\n\t\t\t\t\t\n\t\t\t\t\t}.bind(this)\n\t\t\t\t\t\n\t\t\t\t\t_temp.element = el;\n\t\t\t\t\t_temp.callback();\n\t\t\t\t\t\n\t\t\t\t\tb.registerCallback( _temp.callback );\n\t\t\t\t\t\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t\n\t\t\t\toptions._temps.push( _temp )\t\n\t\t\t\t\n\t\t\t}.bind(this))\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t}\t\t\n\t\n\n\t\t// Store the changes\n\t\tif( !this.changes[options.id] ){\n\t\t\tthis.changes[options.id] = [];\n\t\t}\n\t\t\n\t\tthis.changes[options.id].push( options );\n\t\t\t\t\n\t},\n\t\n\t/**\n\t * Hide the overlay with the spefic id\n\t * @param {Object} options\n\t */\n\thide: function( options ){\n\t\t\n\t\t// Checks if all arguments are available\n\t\tif( \t!options || \n\t\t\t\t!options.id\t|| !options.id instanceof String || options.id.length == 0 ||\n\t\t\t\t!this.changes[options.id]) { \n\t\t\t\t\n\t\t\t\t\treturn\n\t\t\t\t\t\n\t\t}\t\t\n\t\t\n\t\t\n\t\t// Delete all added attributes\n\t\t// FOR EACH - Shape\n\t\tthis.changes[options.id].each(function(option){\n\t\t\t\n\t\t\toption.shapes.each(function(el, index){\n\t\t\t\t\n\t\t\t\t// Checks if the node is a Shape\n\t\t\t\tif( !el instanceof ORYX.Core.Shape){ return }\n\t\t\t\t\n\t\t\t\tthis.deleteAttributes( el.node )\n\t\t\t\t\t\t\t\n\t\t\t}.bind(this));\n\n\t\n\t\t\tif( option._temps ){\n\t\t\t\t\n\t\t\t\toption._temps.each(function(tmp){\n\t\t\t\t\t// Delete the added Node, if there is one\n\t\t\t\t\tif( tmp.svg && tmp.svg.parentNode ){\n\t\t\t\t\t\ttmp.svg.parentNode.removeChild( tmp.svg )\n\t\t\t\t\t}\n\t\t\n\t\t\t\t\t// If \n\t\t\t\t\tif( tmp.callback && tmp.element){\n\t\t\t\t\t\t// It has to be unregistered from the edge\n\t\t\t\t\t\ttmp.element.bounds.unregisterCallback( tmp.callback )\n\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t}.bind(this))\n\t\t\t\t\n\t\t\t}\n\t\t\n\t\t\t\n\t\t}.bind(this));\n\n\t\t\n\t\tthis.changes[options.id] = null;\n\t\t\n\t\t\n\t},\n\t\n\t\n\t/**\n\t * Set the given css attributes to that node\n\t * @param {HTMLElement} node\n\t * @param {Object} attributes\n\t */\n\tsetAttributes: function( node, attributes ) {\n\t\t\n\t\t\n\t\t// Get all the childs from ME\n\t\tvar childs = this.getAllChilds( node.firstChild.firstChild )\n\t\t\n\t\tvar ids = []\n\t\t\n\t\t// Add all Attributes which have relation to another node in this document and concate the pure id out of it\n\t\t// This is for example important for the markers of a edge\n\t\tchilds.each(function(e){ ids.push( $A(e.attributes).findAll(function(attr){ return attr.nodeValue.startsWith('url(#')}) )})\n\t\tids = ids.flatten().compact();\n\t\tids = ids.collect(function(s){return s.nodeValue}).uniq();\n\t\tids = ids.collect(function(s){return s.slice(5, s.length-1)})\n\t\t\n\t\t// Add the node ID to the id\n\t\tids.unshift( node.id + ' .me')\n\t\t\n\t\tvar attr\t\t\t\t= $H(attributes);\n        var attrValue\t\t\t= attr.toJSON().gsub(',', ';').gsub('\"', '');\n        var attrMarkerValue\t\t= attributes.stroke ? attrValue.slice(0, attrValue.length-1) + \"; fill:\" + attributes.stroke + \";}\" : attrValue;\n        var attrTextValue;\n        if( attributes.fill ){\n            var copyAttr        = Object.clone(attributes);\n        \tcopyAttr.fill\t\t= \"black\";\n        \tattrTextValue\t\t= $H(copyAttr).toJSON().gsub(',', ';').gsub('\"', '');\n        }\n                \t\n        // Create the CSS-Tags Style out of the ids and the attributes\n        csstags = ids.collect(function(s, i){return \"#\" + s + \" * \" + (!i? attrValue : attrMarkerValue) + \"\" + (attrTextValue ? \" #\" + s + \" text * \" + attrTextValue : \"\") })\n\t\t\n\t\t// Join all the tags\n\t\tvar s = csstags.join(\" \") + \"\\n\" \n\t\t\n\t\t// And add to the end of the style tag\n\t\tthis.styleNode.appendChild(document.createTextNode(s));\n\t\t\n\t\t\n\t},\n\t\n\t/**\n\t * Deletes all attributes which are\n\t * added in a special style sheet for that node\n\t * @param {HTMLElement} node \n\t */\n\tdeleteAttributes: function( node ) {\n\t\t\t\t\n\t\t// Get all children which contains the node id\t\t\n\t\tvar delEl = $A(this.styleNode.childNodes)\n\t\t\t\t\t .findAll(function(e){ return e.textContent.include( '#' + node.id ) });\n\t\t\n\t\t// Remove all of them\n\t\tdelEl.each(function(el){\n\t\t\tel.parentNode.removeChild(el);\n\t\t});\t\t\n\t},\n\t\n\tgetAllChilds: function( node ){\n\t\t\n\t\tvar childs = $A(node.childNodes)\n\t\t\n\t\t$A(node.childNodes).each(function( e ){ \n\t\t        childs.push( this.getAllChilds( e ) )\n\t\t}.bind(this))\n\n    \treturn childs.flatten();\n\t}\n\n    \n});\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nif (!ORYX.Plugins) \n    ORYX.Plugins = new Object();\n\nORYX.Plugins.KeysMove = ORYX.Plugins.AbstractPlugin.extend({\n\n    facade: undefined,\n    \n    construct: function(facade){\n    \n        this.facade = facade;\n        this.copyElements = [];\n        \n        //this.facade.registerOnEvent(ORYX.CONFIG.EVENT_KEYDOWN, this.keyHandler.bind(this));\n\n\t\t// SELECT ALL\n\t\tthis.facade.offer({\n\t\tkeyCodes: [{\n\t\t \t\tmetaKeys: [ORYX.CONFIG.META_KEY_META_CTRL],\n\t\t\t\tkeyCode: 65,\n\t\t\t\tkeyAction: ORYX.CONFIG.KEY_ACTION_DOWN \n\t\t\t}\n\t\t ],\n         functionality: this.selectAll.bind(this)\n         });\n\t\t \n\t\t// MOVE LEFT SMALL\t\t\n\t\tthis.facade.offer({\n\t\tkeyCodes: [{\n\t\t \t\tmetaKeys: [ORYX.CONFIG.META_KEY_META_CTRL],\n\t\t\t\tkeyCode: ORYX.CONFIG.KEY_CODE_LEFT,\n\t\t\t\tkeyAction: ORYX.CONFIG.KEY_ACTION_DOWN \n\t\t\t}\n\t\t ],\n         functionality: this.move.bind(this, ORYX.CONFIG.KEY_CODE_LEFT, false)\n         });\n\t\t \n\t\t // MOVE LEFT\n\t\t this.facade.offer({\n\t\t keyCodes: [{\n\t\t\t\tkeyCode: ORYX.CONFIG.KEY_CODE_LEFT,\n\t\t\t\tkeyAction: ORYX.CONFIG.KEY_ACTION_DOWN \n\t\t\t}\n\t\t ],\n         functionality: this.move.bind(this, ORYX.CONFIG.KEY_CODE_LEFT, true)\n         });\n\t\t \n\t\t// MOVE RIGHT SMALL\t\n\t\t this.facade.offer({\n\t\t keyCodes: [{\n\t\t \t\tmetaKeys: [ORYX.CONFIG.META_KEY_META_CTRL],\n\t\t\t\tkeyCode: ORYX.CONFIG.KEY_CODE_RIGHT,\n\t\t\t\tkeyAction: ORYX.CONFIG.KEY_ACTION_DOWN \n\t\t\t}\n\t\t ],\n         functionality: this.move.bind(this, ORYX.CONFIG.KEY_CODE_RIGHT, false)\n         });\n\t\t \n\t\t// MOVE RIGHT\t\n\t\t this.facade.offer({\n\t\t keyCodes: [{\n\t\t\t\tkeyCode: ORYX.CONFIG.KEY_CODE_RIGHT,\n\t\t\t\tkeyAction: ORYX.CONFIG.KEY_ACTION_DOWN \n\t\t\t}\n\t\t ],\n         functionality: this.move.bind(this, ORYX.CONFIG.KEY_CODE_RIGHT, true)\n         });\n\t\t \n\t\t// MOVE UP SMALL\t\n\t\t this.facade.offer({\n\t\t keyCodes: [{\n\t\t \t\tmetaKeys: [ORYX.CONFIG.META_KEY_META_CTRL],\n\t\t\t\tkeyCode: ORYX.CONFIG.KEY_CODE_UP,\n\t\t\t\tkeyAction: ORYX.CONFIG.KEY_ACTION_DOWN \n\t\t\t}\n\t\t ],\n         functionality: this.move.bind(this, ORYX.CONFIG.KEY_CODE_UP, false)\n         });\n\t\t \n\t\t// MOVE UP\t\n\t\t this.facade.offer({\n\t\t keyCodes: [{\n\t\t\t\tkeyCode: ORYX.CONFIG.KEY_CODE_UP,\n\t\t\t\tkeyAction: ORYX.CONFIG.KEY_ACTION_DOWN \n\t\t\t}\n\t\t ],\n         functionality: this.move.bind(this, ORYX.CONFIG.KEY_CODE_UP, true)\n         });\n\t\t \n\t\t// MOVE DOWN SMALL\t\n\t\t this.facade.offer({\n\t\t keyCodes: [{\n\t\t \t\tmetaKeys: [ORYX.CONFIG.META_KEY_META_CTRL],\n\t\t\t\tkeyCode: ORYX.CONFIG.KEY_CODE_DOWN,\n\t\t\t\tkeyAction: ORYX.CONFIG.KEY_ACTION_DOWN \n\t\t\t}\n\t\t ],\n         functionality: this.move.bind(this, ORYX.CONFIG.KEY_CODE_DOWN, false)\n         });\n\t\t \n\t\t// MOVE DOWN\t\n\t\t this.facade.offer({\n\t\t keyCodes: [{\n\t\t\t\tkeyCode: ORYX.CONFIG.KEY_CODE_DOWN,\n\t\t\t\tkeyAction: ORYX.CONFIG.KEY_ACTION_DOWN \n\t\t\t}\n\t\t ],\n         functionality: this.move.bind(this, ORYX.CONFIG.KEY_CODE_DOWN, true)\n         });\n\t\t \n         \n    },\n    \n\t/**\n\t * Select all shapes in the editor\n\t *\n\t */\n\tselectAll: function(e){\n    \tEvent.stop(e.event);\n\t\tthis.facade.setSelection(this.facade.getCanvas().getChildShapes(true))\n\t},\n\t\n\tmove: function(key, far, e) {\n\t\t\n    \tEvent.stop(e.event);\n\n\t\t// calculate the distance to move the objects and get the selection.\n\t\tvar distance = far? 20 : 5;\n\t\tvar selection = this.facade.getSelection();\n\t\tvar currentSelection = this.facade.getSelection();\n\t\tvar p = {x: 0, y: 0};\n\t\t\n\t\t// switch on the key pressed and populate the point to move by.\n\t\tswitch(key) {\n\n\t\t\tcase ORYX.CONFIG.KEY_CODE_LEFT:\n\t\t\t\tp.x = -1*distance;\n\t\t\t\tbreak;\n\t\t\tcase ORYX.CONFIG.KEY_CODE_RIGHT:\n\t\t\t\tp.x = distance;\n\t\t\t\tbreak;\n\t\t\tcase ORYX.CONFIG.KEY_CODE_UP:\n\t\t\t\tp.y = -1*distance;\n\t\t\t\tbreak;\n\t\t\tcase ORYX.CONFIG.KEY_CODE_DOWN:\n\t\t\t\tp.y = distance;\n\t\t\t\tbreak;\n\t\t}\n\t\t\n\t\t// move each shape in the selection by the point calculated and update it.\n\t\tselection = selection.findAll(function(shape){ \n\t\t\t// Check if this shape is docked to an shape in the selection\t\t\t\n\t\t\tif(shape instanceof ORYX.Core.Node && shape.dockers.length == 1 && selection.include( shape.dockers.first().getDockedShape() )){ \n\t\t\t\treturn false \n\t\t\t} \n\t\t\t\n\t\t\t// Check if any of the parent shape is included in the selection\n\t\t\tvar s = shape.parent; \n\t\t\tdo{ \n\t\t\t\tif(selection.include(s)){ \n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t}while(s = s.parent); \n\t\t\t\n\t\t\t// Otherwise, return true\n\t\t\treturn true;\n\t\t\t\n\t\t});\n\t\t\n\t\t/* Edges must not be movable, if only edges are selected and at least \n\t\t * one of them is docked.\n\t\t */\n\t\tvar edgesMovable = true;\n\t\tvar onlyEdgesSelected = selection.all(function(shape) {\n\t\t\tif(shape instanceof ORYX.Core.Edge) {\n\t\t\t\tif(shape.isDocked()) {\n\t\t\t\t\tedgesMovable = false;\n\t\t\t\t}\n\t\t\t\treturn true;\t\n\t\t\t}\n\t\t\treturn false;\n\t\t});\n\t\t\n\t\tif(onlyEdgesSelected && !edgesMovable) {\n\t\t\t/* Abort moving shapes */\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tselection = selection.map(function(shape){ \n\t\t\tif( shape instanceof ORYX.Core.Node ){\n\t\t\t\t/*if( shape.dockers.length == 1 ){\n\t\t\t\t\treturn shape.dockers.first()\n\t\t\t\t} else {*/\n\t\t\t\t\treturn shape\n\t\t\t\t//}\n\t\t\t} else if( shape instanceof ORYX.Core.Edge ) {\n\t\t\t\t\n\t\t\t\tvar dockers = shape.dockers;\n\t\t\t\t\n\t\t\t\tif( selection.include( shape.dockers.first().getDockedShape() ) ){\n\t\t\t\t\tdockers = dockers.without( shape.dockers.first() )\n\t\t\t\t}\n\n\t\t\t\tif( selection.include( shape.dockers.last().getDockedShape() ) ){\n\t\t\t\t\tdockers = dockers.without( shape.dockers.last() )\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\treturn dockers\t\n\t\t\t\t\t\t\t\n\t\t\t} else {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\n\t\t}).flatten().compact();\n\t\t\n\t\tif (selection.size() > 0) {\n\t\t\t\n\t\t\t//Stop moving at canvas borders\n\t\t\tvar selectionBounds = [ this.facade.getCanvas().bounds.lowerRight().x,\n\t\t\t                        this.facade.getCanvas().bounds.lowerRight().y,\n\t\t\t                        0,\n\t\t\t                        0 ];\n\t\t\tselection.each(function(s) {\n\t\t\t\tselectionBounds[0] = Math.min(selectionBounds[0], s.bounds.upperLeft().x);\n\t\t\t\tselectionBounds[1] = Math.min(selectionBounds[1], s.bounds.upperLeft().y);\n\t\t\t\tselectionBounds[2] = Math.max(selectionBounds[2], s.bounds.lowerRight().x);\n\t\t\t\tselectionBounds[3] = Math.max(selectionBounds[3], s.bounds.lowerRight().y);\n\t\t\t});\n\t\t\tif(selectionBounds[0]+p.x < 0)\n\t\t\t\tp.x = -selectionBounds[0];\n\t\t\tif(selectionBounds[1]+p.y < 0)\n\t\t\t\tp.y = -selectionBounds[1];\n\t\t\tif(selectionBounds[2]+p.x > this.facade.getCanvas().bounds.lowerRight().x)\n\t\t\t\tp.x = this.facade.getCanvas().bounds.lowerRight().x - selectionBounds[2];\n\t\t\tif(selectionBounds[3]+p.y > this.facade.getCanvas().bounds.lowerRight().y)\n\t\t\t\tp.y = this.facade.getCanvas().bounds.lowerRight().y - selectionBounds[3];\n\t\t\t\n\t\t\tif(p.x!=0 || p.y!=0) {\n\t\t\t\t// Instantiate the moveCommand\n\t\t\t\tvar commands = [new ORYX.Core.Command.Move(selection, p, null, currentSelection, this)];\n\t\t\t\t// Execute the commands\t\t\t\n\t\t\t\tthis.facade.executeCommands(commands);\n\t\t\t}\n\t\t\t\n\t\t}\n\t},\n\t\n\tgetUndockedCommant: function(shapes){\n\n\t\tvar undockEdgeCommand = ORYX.Core.Command.extend({\n\t\t\tconstruct: function(moveShapes){\n\t\t\t\tthis.dockers = moveShapes.collect(function(shape){ return shape instanceof ORYX.Core.Controls.Docker ? {docker:shape, dockedShape:shape.getDockedShape(), refPoint:shape.referencePoint} : undefined }).compact();\n\t\t\t},\t\t\t\n\t\t\texecute: function(){\n\t\t\t\tthis.dockers.each(function(el){\n\t\t\t\t\tel.docker.setDockedShape(undefined);\n\t\t\t\t})\n\t\t\t},\n\t\t\trollback: function(){\n\t\t\t\tthis.dockers.each(function(el){\n\t\t\t\t\tel.docker.setDockedShape(el.dockedShape);\n\t\t\t\t\tel.docker.setReferencePoint(el.refPoint);\n\t\t\t\t\t//el.docker.update();\n\t\t\t\t})\n\t\t\t}\n\t\t});\n\t\t\n\t\tcommand = new undockEdgeCommand( shapes );\n\t\tcommand.execute();\t\n\t\treturn command;\n\t},\n\t\n//    /**\n//     * The key handler for this plugin. Every action from the set of cut, copy,\n//     * paste and delete should be accessible trough simple keyboard shortcuts.\n//     * This method checks whether any event triggers one of those actions.\n//     *\n//     * @param {Object} event The keyboard event that should be analysed for\n//     *     triggering of this plugin.\n//     */\n//    keyHandler: function(event){\n//        //TODO document what event.which is.\n//        \n//        ORYX.Log.debug(\"keysMove.js handles a keyEvent.\");\n//        \n//        // assure we have the current event.\n//        if (!event) \n//            event = window.event;\n//        \n//        // get the currently pressed key and state of control key.\n//        var pressedKey = event.which || event.keyCode;\n//        var ctrlPressed = event.ctrlKey;\n//\n//\t\t// if the key is one of the arrow keys, forward to move and return.\n//\t\tif ([ORYX.CONFIG.KEY_CODE_LEFT, ORYX.CONFIG.KEY_CODE_RIGHT,\n//\t\t\tORYX.CONFIG.KEY_CODE_UP, ORYX.CONFIG.KEY_CODE_DOWN].include(pressedKey)) {\n//\t\t\t\n//\t\t\tthis.move(pressedKey, !ctrlPressed);\n//\t\t\treturn;\n//\t\t}\n//\t\t\n//    }\n\t\n});\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nif(!ORYX.Plugins) { ORYX.Plugins = {} }\nif(!ORYX.Plugins.Layouter) { ORYX.Plugins.Layouter = {} }\n\nnew function(){\n\t\n\t/**\n\t * Edge layouter is an implementation to layout an edge\n\t * @class ORYX.Plugins.Layouter.EdgeLayouter\n\t * @author Willi Tscheschner\n\t */\n\tORYX.Plugins.Layouter.EdgeLayouter = ORYX.Plugins.AbstractLayouter.extend({\n\t\t\n\t\t/**\n\t\t * Layout only Edges\n\t\t */\n\t\tlayouted : [\t\"http://b3mn.org/stencilset/bpmn1.1#SequenceFlow\", \n\t\t\t\t\t\t\"http://b3mn.org/stencilset/bpmn1.1#MessageFlow\",\n\t\t\t\t\t\t\"http://b3mn.org/stencilset/timjpdl3#SequenceFlow\", \n\t\t\t\t\t\t\"http://b3mn.org/stencilset/jbpm4#SequenceFlow\", \n\t\t\t\t\t\t\"http://b3mn.org/stencilset/bpmn2.0#MessageFlow\",\n\t\t\t\t\t\t\"http://b3mn.org/stencilset/bpmn2.0#SequenceFlow\", \n\t\t\t\t\t\t\"http://b3mn.org/stencilset/bpmn2.0choreography#MessageFlow\",\n\t\t\t\t\t\t\"http://b3mn.org/stencilset/bpmn2.0choreography#SequenceFlow\", \n\t\t\t\t\t\t\"http://b3mn.org/stencilset/bpmn2.0conversation#ConversationLink\",\n\t\t\t\t\t\t\"http://b3mn.org/stencilset/epc#ControlFlow\",\n\t\t\t\t\t\t\"http://www.signavio.com/stencilsets/processmap#ProcessLink\",\n\t\t\t\t\t\t\"http://www.signavio.com/stencilsets/organigram#connection\"],\n\t\t\n\t\t/**\n\t\t * Layout a set on edges\n\t\t * @param {Object} edges\n\t\t */\n\t\tlayout: function(edges){\n\t\t\tedges.each(function(edge){\n\t\t\t\tthis.doLayout(edge)\n\t\t\t}.bind(this))\n\t\t},\n\t\t\n\t\t/**\n\t\t * Layout one edge\n\t\t * @param {Object} edge\n\t\t */\n\t\tdoLayout: function(edge){\n\t\t\t// Get from and to node\n\t\t\tvar from \t= edge.getIncomingNodes()[0]; \n\t\t\tvar to \t\t= edge.getOutgoingNodes()[0];\n\t\t\t\n\t\t\t// Return if one is null\n\t\t\tif (!from || !to) { return }\n\t\t\t\n\t\t\tvar positions = this.getPositions(from, to, edge);\n\t\t\n\t\t\tif (positions.length > 0){\n\t\t\t\tthis.setDockers(edge, positions[0].a, positions[0].b);\n\t\t\t}\n\t\t\t\t\n\t\t},\n\t\t\n\t\t/**\n\t\t * Returns a set on positions which are not containt either \n\t\t * in the bounds in from or to.\n\t\t * @param {Object} from Shape where the edge is come from\n\t\t * @param {Object} to Shape where the edge is leading to\n\t\t * @param {Object} edge Edge between from and to\n\t\t */\n\t\tgetPositions : function(from, to, edge){\n\t\t\t\n\t\t\t// Get absolute bounds\n\t\t\tvar ab = from.absoluteBounds();\n\t\t\tvar bb = to.absoluteBounds();\n\t\t\t\n\t\t\t// Get center from and to\n\t\t\tvar a = ab.center();\n\t\t\tvar b = bb.center();\n\t\t\t\n\t\t\tvar am = ab.midPoint();\n\t\t\tvar bm = bb.midPoint();\n\t\t\n\t\t\t// Get first and last reference point\n\t\t\tvar first = Object.clone(edge.dockers.first().referencePoint);\n\t\t\tvar last = Object.clone(edge.dockers.last().referencePoint);\n\t\t\t// Get the absolute one\n\t\t\tvar aFirst = edge.dockers.first().getAbsoluteReferencePoint();\n\t\t\tvar aLast = edge.dockers.last().getAbsoluteReferencePoint(); \n\t\t\t\n\t\t\t// IF ------>\n\t\t\t// or  |\n\t\t\t//     V\n\t\t\t// Do nothing\n\t\t\tif (Math.abs(aFirst.x-aLast.x) < 1 || Math.abs(aFirst.y-aLast.y) < 1) {\n\t\t\t\treturn []\n\t\t\t}\n\t\t\t\n\t\t\t// Calc center position, between a and b\n\t\t\t// depending on there weight\n\t\t\tvar m = {}\n\t\t\tm.x = a.x < b.x ? \n\t\t\t\t\t(((b.x - bb.width()/2) - (a.x + ab.width()/2))/2) + (a.x + ab.width()/2): \n\t\t\t\t\t(((a.x - ab.width()/2) - (b.x + bb.width()/2))/2) + (b.x + bb.width()/2);\n\n\t\t\tm.y = a.y < b.y ? \n\t\t\t\t\t(((b.y - bb.height()/2) - (a.y + ab.height()/2))/2) + (a.y + ab.height()/2): \n\t\t\t\t\t(((a.y - ab.height()/2) - (b.y + bb.height()/2))/2) + (b.y + bb.height()/2);\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t// Enlarge both bounds with 10\n\t\t\tab.widen(5); // Wide the from less than \n\t\t\tbb.widen(20);// the to because of the arrow from the edge\n\t\t\t\t\t\t\t\t\n\t\t\tvar positions = [];\n\t\t\tvar off = this.getOffset.bind(this);\n\t\t\t\n\t\t\t// Checks ----+\n\t\t\t//            |\n\t\t\t//            V\n\t\t\tif (!ab.isIncluded(b.x, a.y)&&!bb.isIncluded(b.x, a.y)) {\n\t\t\t\tpositions.push({\n\t\t\t\t\ta : {x:b.x+off(last,bm,\"x\"),y:a.y+off(first,am,\"y\")},\n\t\t\t\t\tz : this.getWeight(from, a.x < b.x ? \"r\" : \"l\", to, a.y < b.y ? \"t\" : \"b\", edge)\n\t\t\t\t});\n\t\t\t}\n\t\t\t\t\t\t\n\t\t\t// Checks | \n\t\t\t//        +--->\n\t\t\tif (!ab.isIncluded(a.x, b.y)&&!bb.isIncluded(a.x, b.y)) {\n\t\t\t\tpositions.push({\n\t\t\t\t\ta : {x:a.x+off(first,am,\"x\"),y:b.y+off(last,bm,\"y\")},\n\t\t\t\t\tz : this.getWeight(from, a.y < b.y ? \"b\" : \"t\", to, a.x < b.x ? \"l\" : \"r\", edge)\n\t\t\t\t});\n\t\t\t}\n\t\t\t\t\t\t\n\t\t\t// Checks  --+\n\t\t\t//           |\n\t\t\t//           +--->\n\t\t\tif (!ab.isIncluded(m.x, a.y)&&!bb.isIncluded(m.x, b.y)) {\n\t\t\t\tpositions.push({\n\t\t\t\t\ta : {x:m.x,y:a.y+off(first,am,\"y\")},\n\t\t\t\t\tb : {x:m.x,y:b.y+off(last,bm,\"y\")},\n\t\t\t\t\tz : this.getWeight(from, \"r\", to, \"l\", edge, a.x > b.x)\n\t\t\t\t});\n\t\t\t}\n\t\t\t\n\t\t\t// Checks | \n\t\t\t//        +---+\n\t\t\t//            |\n\t\t\t//            V\n\t\t\tif (!ab.isIncluded(a.x, m.y)&&!bb.isIncluded(b.x, m.y)) {\n\t\t\t\tpositions.push({\n\t\t\t\t\ta : {x:a.x+off(first,am,\"x\"),y:m.y},\n\t\t\t\t\tb : {x:b.x+off(last,bm,\"x\"),y:m.y},\n\t\t\t\t\tz : this.getWeight(from, \"b\", to, \"t\", edge, a.y > b.y)\n\t\t\t\t});\n\t\t\t}\t\n\t\t\t\n\t\t\t// Sort DESC of weights\n\t\t\treturn positions.sort(function(a,b){ return a.z < b.z ? 1 : (a.z == b.z ? -1 : -1)});\n\t\t},\n\t\t\n\t\t/**\n\t\t * Returns a offset for the pos to the center of the bounds\n\t\t * \n\t\t * @param {Object} val\n\t\t * @param {Object} pos2\n\t\t * @param {String} dir Direction x|y\n\t\t */\n\t\tgetOffset: function(pos, pos2, dir){\n\t\t\treturn pos[dir] - pos2[dir];\n\t\t},\n\t\t\n\t\t/**\n\t\t * Returns a value which shows the weight for this configuration\n\t\t * \n\t\t * @param {Object} from Shape which is coming from\n\t\t * @param {String} d1 Direction where is goes\n\t\t * @param {Object} to Shape which goes to\n\t\t * @param {String} d2 Direction where it comes to\n\t\t * @param {Object} edge Edge between from and to\n\t\t * @param {Boolean} reverse Reverse the direction (e.g. \"r\" -> \"l\")\n\t\t */\n\t\tgetWeight: function(from, d1, to, d2, edge, reverse){\n\t\t\t\n\t\t\td1 = (d1||\"\").toLowerCase();\n\t\t\td2 = (d2||\"\").toLowerCase();\n\t\t\t\n\t\t\tif (![\"t\",\"r\",\"b\",\"l\"].include(d1)){ d1 = \"r\"}\n\t\t\tif (![\"t\",\"r\",\"b\",\"l\"].include(d2)){ d1 = \"l\"}\n\t\t\t\n\t\t\t// If reverse is set\n\t\t\tif (reverse) {\n\t\t\t\t// Reverse d1 and d2\n\t\t\t\td1 = d1==\"t\"?\"b\":(d1==\"r\"?\"l\":(d1==\"b\"?\"t\":(d1==\"l\"?\"r\":\"r\")))\n\t\t\t\td2 = d2==\"t\"?\"b\":(d2==\"r\"?\"l\":(d2==\"b\"?\"t\":(d2==\"l\"?\"r\":\"r\")))\n\t\t\t}\n\t\t\t\n\t\t\t\t\t\n\t\t\tvar weight = 0;\n\t\t\t// Get rules for from \"out\" and to \"in\"\n\t\t\tvar dr1 = this.facade.getRules().getLayoutingRules(from, edge)[\"out\"];\n\t\t\tvar dr2 = this.facade.getRules().getLayoutingRules(to, edge)[\"in\"];\n\n\t\t\tvar fromWeight = dr1[d1];\n\t\t\tvar toWeight = dr2[d2];\n\n\n\t\t\t/**\n\t\t\t * Return a true if the center 1 is in the same direction than center 2\n\t\t\t * @param {Object} direction\n\t\t\t * @param {Object} center1\n\t\t\t * @param {Object} center2\n\t\t\t */\n\t\t\tvar sameDirection = function(direction, center1, center2){\n\t\t\t\tswitch(direction){\n\t\t\t\t\tcase \"t\": return Math.abs(center1.x - center2.x) < 2 && center1.y < center2.y\n\t\t\t\t\tcase \"r\": return center1.x > center2.x && Math.abs(center1.y - center2.y) < 2\n\t\t\t\t\tcase \"b\": return Math.abs(center1.x - center2.x) < 2 && center1.y > center2.y\n\t\t\t\t\tcase \"l\": return center1.x < center2.x && Math.abs(center1.y - center2.y) < 2\n\t\t\t\t\tdefault: return false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check if there are same incoming edges from 'from'\n\t\t\tvar sameIncomingFrom = from\n\t\t\t\t\t\t\t\t.getIncomingShapes()\n\t\t\t\t\t\t\t\t.findAll(function(a){ return a instanceof ORYX.Core.Edge})\n\t\t\t\t\t\t\t\t.any(function(e){ \n\t\t\t\t\t\t\t\t\treturn sameDirection(d1, e.dockers[e.dockers.length-2].bounds.center(), e.dockers.last().bounds.center());\n\t\t\t\t\t\t\t\t});\n\n\t\t\t// Check if there are same outgoing edges from 'to'\n\t\t\tvar sameOutgoingTo = to\n\t\t\t\t\t\t\t\t.getOutgoingShapes()\n\t\t\t\t\t\t\t\t.findAll(function(a){ return a instanceof ORYX.Core.Edge})\n\t\t\t\t\t\t\t\t.any(function(e){ \n\t\t\t\t\t\t\t\t\treturn sameDirection(d2, e.dockers[1].bounds.center(), e.dockers.first().bounds.center());\n\t\t\t\t\t\t\t\t});\n\t\t\t\n\t\t\t// If there are equivalent edges, set 0\n\t\t\t//fromWeight = sameIncomingFrom ? 0 : fromWeight;\n\t\t\t//toWeight = sameOutgoingTo ? 0 : toWeight;\n\t\t\t\n\t\t\t// Get the sum of \"out\" and the direction plus \"in\" and the direction \t\t\t\t\t\t\n\t\t\treturn (sameIncomingFrom||sameOutgoingTo?0:fromWeight+toWeight);\n\t\t},\n\t\t\n\t\t/**\n\t\t * Removes all current dockers from the node \n\t\t * (except the start and end) and adds two new\n\t\t * dockers, on the position a and b.\n\t\t * @param {Object} edge\n\t\t * @param {Object} a\n\t\t * @param {Object} b\n\t\t */\n\t\tsetDockers: function(edge, a, b){\n\t\t\tif (!edge){ return }\n\t\t\t\n\t\t\t// Remove all dockers (implicit,\n\t\t\t// start and end dockers will not removed)\n\t\t\tedge.dockers.each(function(r){\n\t\t\t\tedge.removeDocker(r);\n\t\t\t});\n\t\t\t\n\t\t\t// For a and b (if exists), create\n\t\t\t// a new docker and set position\n\t\t\t[a, b].compact().each(function(pos){\n\t\t\t\tvar docker = edge.createDocker(undefined, pos);\n\t\t\t\tdocker.bounds.centerMoveTo(pos);\n\t\t\t});\n\t\t\t\n\t\t\t// Update all dockers from the edge\n\t\t\tedge.dockers.each(function(docker){\n\t\t\t\tdocker.update()\n\t\t\t})\n\t\t\t\n\t\t\t// Update edge\n\t\t\t//edge.refresh();\n\t\t\tedge._update(true);\n\t\t\t\n\t\t}\n\t});\n\t\n\t\n}()\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nif(!ORYX.Plugins)\n\tORYX.Plugins = new Object();\n\nnew function(){\n\t\n\tORYX.Plugins.BPMN2_0 = {\n\t\n\t\t/**\n\t\t *\tConstructor\n\t\t *\t@param {Object} Facade: The Facade of the Editor\n\t\t */\n\t\tconstruct: function(facade){\n\t\t\tthis.facade = facade;\n\t\t\t\n\t\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_DRAGDOCKER_DOCKED, this.handleDockerDocked.bind(this));\n\t\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_PROPWINDOW_PROP_CHANGED, this.handlePropertyChanged.bind(this));\n\t\t\tthis.facade.registerOnEvent('layout.bpmn2_0.pool', this.handleLayoutPool.bind(this));\n\t\t\tthis.facade.registerOnEvent('layout.bpmn2_0.subprocess', this.handleSubProcess.bind(this));\n\t\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_SHAPEREMOVED, this.handleShapeRemove.bind(this));\n\t\t\t\n\t\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_LOADED, this.afterLoad.bind(this));\n\t\t\t\n\n\t\t\tthis.namespace = undefined;\n\t\t},\n\t\t\n\t\t/**\n         * Force to update every pool\n         */\n        afterLoad: function(){\n                this.facade.getCanvas().getChildNodes().each(function(shape){\n                        if (shape.getStencil().id().endsWith(\"Pool\")) {\n                                this.handleLayoutPool({\n                                        shape: shape\n                                });\n                        }\n                }.bind(this))\n        },\n       \n        /**\n         * If a pool is selected and contains no lane,\n         * a lane is created automagically\n         */\n        onSelectionChanged: function(event) {\n                var selection = event.elements;\n               \n                if(selection && selection.length === 1) {\n                        var namespace = this.getNamespace();\n                        var shape = selection[0];\n                        if(shape.getStencil().idWithoutNs() === \"Pool\") {\n                                if(shape.getChildNodes().length === 0) {\n                                        // create a lane inside the selected pool\n                                        var option = {\n                                                        type:namespace + \"Lane\",\n                                                        position:{x:0,y:0},\n                                                        namespace:shape.getStencil().namespace(),\n                                                        parent:shape\n                                        };\n                                        this.facade.createShape(option);\n                                        this.facade.getCanvas().update();\n                                        this.facade.setSelection([shape]);\n                                }\n                        }\n                }\n               \n                // Preventing selection of all lanes but not the pool\n                if(selection.any(function(s){ return s instanceof ORYX.Core.Node && s.getStencil().id().endsWith(\"Lane\")})){\n                        var lanes = selection.findAll(function(s){\n                                return s instanceof ORYX.Core.Node && s.getStencil().id().endsWith(\"Lane\")\n                        });\n                       \n                        var pools = [];\n                        var unselectLanes = [];\n                        lanes.each(function(lane){\n                                pools.push(this.getParentPool(lane))\n                        }.bind(this));\n                       \n                        pools = pools.uniq().findAll(function(pool){\n                                var childLanes = this.getLanes(pool, true);\n                                if (childLanes.all(function(lane){ return lanes.include(lane)})){\n                                        unselectLanes = unselectLanes.concat(childLanes);\n                                        return true;\n                                } else if (selection.include(pool) && childLanes.any(function(lane){ return lanes.include(lane)})) {\n                                        unselectLanes = unselectLanes.concat(childLanes);\n                                        return true;\n                                } else {\n                                        return false;\n                                }\n                        }.bind(this))\n                       \n                        if (unselectLanes.length > 0 && pools.length > 0){\n                                selection = selection.without.apply(selection, unselectLanes);\n                                selection = selection.concat(pools);\n                                this.facade.setSelection(selection.uniq());\n                        }\n                }\n        },\n       \n        handleShapeRemove: function(option) {\n               \n                var sh                          = option.shape;\n                var parent                      = option.parent;\n                                       \n                if (sh instanceof ORYX.Core.Node && sh.getStencil().idWithoutNs() === \"Lane\" && this.facade.isExecutingCommands()) {\n               \n                        var pool = this.getParentPool(parent);\n                        if (pool&&pool.parent){        \n                       \n                                var isLeafFn = function(leaf){\n                                        return !leaf.getChildNodes().any(function(r){ return r.getStencil().idWithoutNs() === \"Lane\"});\n                                }\n                               \n                                var isLeaf = isLeafFn(sh);\n                                var parentHasMoreLanes = parent.getChildNodes().any(function(r){ return r.getStencil().idWithoutNs() === \"Lane\"});\n                               \n                                if (isLeaf && parentHasMoreLanes){\n                                       \n                                        var command = new ResizeLanesCommand(sh, parent, pool, this);\n                                        this.facade.executeCommands([command]);\n                                       \n                                } else if(      !isLeaf &&\n                                                        !this.facade.getSelection().any(function(select){ // Find one of the selection, which is a lane and child of \"sh\" and is a leaf lane\n                                                                        return  select instanceof ORYX.Core.Node && select.getStencil().idWithoutNs() === \"Lane\" &&\n                                                                                        select.isParent(sh) && isLeafFn(select);})) {\n                                                                                               \n                                        var Command = ORYX.Core.Command.extend({\n                                                construct: function(shape, facade) {\n                                                        this.children = shape.getChildNodes(true);\n                                                        this.facade = facade;\n                                                },\n                                                execute: function() {\n                                                        this.children.each(function(child){\n                                                                child.bounds.moveBy(30,0)\n                                                        });\n                                                        //this.facade.getCanvas().update();\n                                                },\n                                                rollback: function() {\n                                                        this.children.each(function(child){\n                                                                child.bounds.moveBy(-30,0)\n                                                        })\n                                                        //this.facade.getCanvas().update();\n                                                }\n                                        });\n                                        this.facade.executeCommands([new Command(sh, this.facade)]);\n                                       \n                                } else if (isLeaf&&!parentHasMoreLanes&&parent == pool){\n                                        parent.add(sh);\n                                }\n                        }\n               \n                }\n               \n        },\n\n\t\t\n\t\thashedSubProcesses: {},\n\t\t\n\t\thashChildShapes: function(shape){\n\t\t\tvar children = shape.getChildNodes();\n\t\t\tchildren.each(function(child){\n\t\t\t\tif (this.hashedSubProcesses[child.id]){\n\t\t\t\t\tthis.hashedSubProcesses[child.id] = child.absoluteXY();\n\t\t\t\t\tthis.hashedSubProcesses[child.id].width \t= child.bounds.width();\n\t\t\t\t\tthis.hashedSubProcesses[child.id].height \t= child.bounds.height();\n\t\t\t\t\tthis.hashChildShapes(child);\n\t\t\t\t}\n\t\t\t}.bind(this));\n\t\t},\n\t\n\t\t/**\n\t\t * Handle the layouting of a sub process.\n\t\t * Mainly to adjust the child dockers of a sub process. \n\t\t *\n\t\t */\n\t\thandleSubProcess : function(option) {\n\t\t\t\n\t\t\tvar sh = option.shape;\n\t\t\t\n\t\t\tif (!this.hashedSubProcesses[sh.id]) {\n\t\t\t\tthis.hashedSubProcesses[sh.id] = sh.absoluteXY();\n\t\t\t\tthis.hashedSubProcesses[sh.id].width \t= sh.bounds.width();\n\t\t\t\tthis.hashedSubProcesses[sh.id].height \t= sh.bounds.height();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\tvar offset = sh.absoluteXY();\n\t\t\toffset.x -= this.hashedSubProcesses[sh.id].x;\n\t\t\toffset.y -= this.hashedSubProcesses[sh.id].y;\n\t\t\t\n\t\t\tvar resized = this.hashedSubProcesses[sh.id].width !== sh.bounds.width() || this.hashedSubProcesses[sh.id].height !== sh.bounds.height();\n\t\t\t\n\t\t\tthis.hashedSubProcesses[sh.id] = sh.absoluteXY();\n\t\t\tthis.hashedSubProcesses[sh.id].width \t= sh.bounds.width();\n\t\t\tthis.hashedSubProcesses[sh.id].height \t= sh.bounds.height();\n\t\t\tthis.hashChildShapes(sh);\n\t\t\t\n\t\t\t\n\t\t\t// Move dockers only if currently is not resizing\n\t\t\tif (this.facade.isExecutingCommands()&&!resized) {\n\t\t\t\tthis.moveChildDockers(sh, offset);\n\t\t\t}\n\t\t},\n\t\t\n\t\tmoveChildDockers: function(shape, offset){\n\t\t\t\n\t\t\tif (!offset.x && !offset.y) {\n\t\t\t\treturn;\n\t\t\t} \n\t\t\t\n\t\t\tvar children = shape.getChildNodes(true);\n\t\t\t\n\t\t\t// Get all nodes\n\t\t\tvar dockers = children\n\t\t\t\t// Get all incoming and outgoing edges\n\t\t\t\t.map(function(node){\n\t\t\t\t\treturn [].concat(node.getIncomingShapes())\n\t\t\t\t\t\t\t.concat(node.getOutgoingShapes())\n\t\t\t\t})\n\t\t\t\t// Flatten all including arrays into one\n\t\t\t\t.flatten()\n\t\t\t\t// Get every edge only once\n\t\t\t\t.uniq()\n\t\t\t\t// Get all dockers\n\t\t\t\t.map(function(edge){\n\t\t\t\t\treturn edge.dockers.length > 2 ? \n\t\t\t\t\t\t\tedge.dockers.slice(1, edge.dockers.length-1) : \n\t\t\t\t\t\t\t[];\n\t\t\t\t})\n\t\t\t\t// Flatten the dockers lists\n\t\t\t\t.flatten();\n\t\n\t\t\tvar abs = shape.absoluteBounds();\n\t\t\tabs.moveBy(-offset.x, -offset.y)\n\t\t\tvar obj = {};\n\t\t\tdockers.each(function(docker){\n\t\t\t\t\n\t\t\t\tif (docker.isChanged){\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tvar off = Object.clone(offset);\n\t\t\t\t\n\t\t\t\tif (!abs.isIncluded(docker.bounds.center())){\n\t\t\t\t\tvar index \t= docker.parent.dockers.indexOf(docker);\n\t\t\t\t\tvar size\t= docker.parent.dockers.length;\n\t\t\t\t\tvar from \t= docker.parent.getSource();\n\t\t\t\t\tvar to \t\t= docker.parent.getTarget();\n\t\t\t\t\t\n\t\t\t\t\tvar bothAreIncluded = children.include(from) && children.include(to);\n\t\t\t\t\t\n\t\t\t\t\tif (!bothAreIncluded){\n\t\t\t\t\t\tvar previousIsOver = index !== 0 ? abs.isIncluded(docker.parent.dockers[index-1].bounds.center()) : false;\n\t\t\t\t\t\tvar nextIsOver = index !== size-1 ? abs.isIncluded(docker.parent.dockers[index+1].bounds.center()) : false;\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (!previousIsOver && !nextIsOver){ return; }\n\t\t\t\t\t\t\n\t\t\t\t\t\tvar ref = docker.parent.dockers[previousIsOver ? index-1 : index+1];\n\t\t\t\t\t\tif (Math.abs(-Math.abs(ref.bounds.center().x-docker.bounds.center().x)) < 2){\n\t\t\t\t\t\t\toff.y = 0;\n\t\t\t\t\t\t} else if(Math.abs(-Math.abs(ref.bounds.center().y-docker.bounds.center().y)) < 2){\n\t\t\t\t\t\t\toff.x = 0;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tobj[docker.getId()] = {\n\t\t\t\t\tdocker:docker,\n\t\t\t\t\toffset:off\n\t\t\t\t}\n\t\t\t})\n\t\t\t\n\t\t\t// Set dockers\n\t\t\tthis.facade.executeCommands([new ORYX.Core.MoveDockersCommand(obj)]);\n\t\t\t\t\n\t\t},\n\t\t\n\t\t/**\n\t\t * DragDocker.Docked Handler\n\t\t *\n\t\t */\t\n\t\thandleDockerDocked: function(options) {\n\t\t\tvar namespace = this.getNamespace();\n\t\t\t\n\t\t\tvar edge = options.parent;\n\t\t\tvar edgeSource = options.target;\n\t\t\t\n\t\t\tif(edge.getStencil().id() === namespace + \"SequenceFlow\") {\n\t\t\t\tvar isGateway = edgeSource.getStencil().groups().find(function(group) {\n\t\t\t\t\t\tif(group == \"Gateways\") \n\t\t\t\t\t\t\treturn group;\n\t\t\t\t\t});\n\t\t\t\tif(!isGateway && (edge.properties[\"oryx-conditiontype\"] == \"Expression\"))\n\t\t\t\t\t// show diamond on edge source\n\t\t\t\t\tedge.setProperty(\"oryx-showdiamondmarker\", true);\n\t\t\t\telse \n\t\t\t\t\t// do not show diamond on edge source\n\t\t\t\t\tedge.setProperty(\"oryx-showdiamondmarker\", false);\n\t\t\t\t\n\t\t\t\t// update edge rendering\n\t\t\t\t//edge.update();\n\t\t\t\t\n\t\t\t\tthis.facade.getCanvas().update();\n\t\t\t}\n\t\t},\n\t\t\n\t\t/**\n\t\t * PropertyWindow.PropertyChanged Handler\n\t\t */\n\t\thandlePropertyChanged: function(option) {\n\t\t\tvar namespace = this.getNamespace();\n\t\t\t\n\t\t\tvar shapes = option.elements;\n\t\t\tvar propertyKey = option.key;\n\t\t\tvar propertyValue = option.value;\n\t\t\t\n\t\t\tvar changed = false;\n\t\t\tshapes.each(function(shape){\n\t\t\t\tif((shape.getStencil().id() === namespace + \"SequenceFlow\") &&\n\t\t\t\t\t(propertyKey === \"oryx-conditiontype\")) {\n\t\t\t\t\t\n\t\t\t\t\tif(propertyValue != \"Expression\")\n\t\t\t\t\t\t// Do not show the Diamond\n\t\t\t\t\t\tshape.setProperty(\"oryx-showdiamondmarker\", false);\n\t\t\t\t\telse {\n\t\t\t\t\t\tvar incomingShapes = shape.getIncomingShapes();\n\t\t\t\t\t\t\n\t\t\t\t\t\tif(!incomingShapes) {\n\t\t\t\t\t\t\tshape.setProperty(\"oryx-showdiamondmarker\", true);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tvar incomingGateway = incomingShapes.find(function(aShape) {\n\t\t\t\t\t\t\tvar foundGateway = aShape.getStencil().groups().find(function(group) {\n\t\t\t\t\t\t\t\tif(group == \"Gateways\") \n\t\t\t\t\t\t\t\t\treturn group;\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif(foundGateway)\n\t\t\t\t\t\t\t\treturn foundGateway;\n\t\t\t\t\t\t});\n\t\t\t\t\t\t\n\t\t\t\t\t\tif(!incomingGateway) \n\t\t\t\t\t\t\t// show diamond on edge source\n\t\t\t\t\t\t\tshape.setProperty(\"oryx-showdiamondmarker\", true);\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\t// do not show diamond\n\t\t\t\t\t\t\tshape.setProperty(\"oryx-showdiamondmarker\", false);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tchanged = true;\n\t\t\t\t}\n\t\t\t}.bind(this));\n\t\t\t\n\t\t\tif(changed) {this.facade.getCanvas().update();}\n\t\t\t\n\t\t},\n\t\t\n\t\thashedPoolPositions : {},\n\t\thashedLaneDepth : {},\n\t\thashedBounds : {},\n\t\thashedPositions: {},\n\t\t\n\t\t/**\n         * Handler for layouting event 'layout.bpmn2_0.pool'\n         * @param {Object} event\n         */\n        handleLayoutPool: function(event){\n               \n               \n                var pool = event.shape;\n                var selection = this.facade.getSelection();\n                var currentShape = selection.include(pool) ? pool : selection.first();\n               \n                currentShape = currentShape || pool;\n               \n                this.currentPool = pool;\n               \n                // Check if it is a pool or a lane\n                if (!(currentShape.getStencil().id().endsWith(\"Pool\") || currentShape.getStencil().id().endsWith(\"Lane\"))) {\n                        return;\n                }\n               \n                // Check if the lane is within the pool and is not removed lately\n                if (currentShape !== pool && !currentShape.isParent(pool) && !this.hashedBounds[pool.id][currentShape.id]){\n                        return;\n                }\n               \n               \n                if (!this.hashedBounds[pool.id]) {\n                        this.hashedBounds[pool.id] = {};\n                }\n               \n                // Find all child lanes\n                var lanes = this.getLanes(pool);\n               \n                if (lanes.length <= 0) {\n                        return\n                }\n               \n                var allLanes = this.getLanes(pool, true), hp;\n                var considerForDockers = allLanes.clone();\n               \n                var hashedPositions = $H({});\n                allLanes.each(function(lane){\n                        hashedPositions[lane.id] = lane.bounds.upperLeft();\n                })\n               \n               \n               \n                // Show/hide caption regarding the number of lanes\n                if (lanes.length === 1 && this.getLanes(lanes.first()).length <= 0) {\n                        // TRUE if there is a caption\n                        lanes.first().setProperty(\"oryx-showcaption\", lanes.first().properties[\"oryx-name\"].trim().length > 0);\n                        var rect = lanes.first().node.getElementsByTagName(\"rect\");\n                        rect[0].setAttributeNS(null, \"display\", \"none\");\n                } else {\n                        allLanes.invoke(\"setProperty\", \"oryx-showcaption\", true);\n                        allLanes.each(function(lane){\n                                var rect = lane.node.getElementsByTagName(\"rect\");\n                                rect[0].removeAttributeNS(null, \"display\");\n                        })\n                }\n               \n                var deletedLanes = [];\n                var addedLanes = [];\n               \n                // Get all new lanes\n                var i=-1;\n                while (++i<allLanes.length) {\n                        if (!this.hashedBounds[pool.id][allLanes[i].id]){\n                                addedLanes.push(allLanes[i])\n                        }\n                }\n               \n                if (addedLanes.length > 0){\n                        currentShape = addedLanes.first();\n                }\n               \n               \n                // Get all deleted lanes\n                var resourceIds = $H(this.hashedBounds[pool.id]).keys();\n                var i=-1;\n                while (++i<resourceIds.length) {\n                        if (!allLanes.any(function(lane){ return lane.id == resourceIds[i]})){\n                                deletedLanes.push(this.hashedBounds[pool.id][resourceIds[i]]);\n                                selection = selection.without(function(r){ return r.id == resourceIds[i] });\n                        }\n                }              \n               \n                var height, width, x, y;\n               \n                if (deletedLanes.length > 0 || addedLanes.length > 0) {\n                       \n                        if (addedLanes.length === 1 && this.getLanes(addedLanes[0].parent).length === 1){\n                                // Set height from the pool\n                                height = this.adjustHeight(lanes, addedLanes[0].parent);\n                        } else {\n                                // Set height from the pool\n                                height = this.updateHeight(pool);\n                        }\n                        // Set width from the pool\n                        width = this.adjustWidth(lanes, pool.bounds.width());  \n                       \n                        pool.update();\n                }\n               \n                /**\n                 * Set width/height depending on the pool\n                 */\n                else if (pool == currentShape) {\n                       \n                        if (selection.length === 1 && this.isResized(pool, this.hashedPoolPositions[pool.id])) {\n                                var oldXY = this.hashedPoolPositions[pool.id].upperLeft();\n                                var xy = pool.bounds.upperLeft();\n                                var scale = 0;\n                                if (this.shouldScale(pool)){\n                                        var old = this.hashedPoolPositions[pool.id];\n                                        scale = old.height()/pool.bounds.height();\n                                }\n                       \n                                this.adjustLanes(pool, allLanes, oldXY.x - xy.x, oldXY.y - xy.y, scale);\n                        }\n                       \n                        // Set height from the pool\n                        height = this.adjustHeight(lanes, undefined, pool.bounds.height());\n                        // Set width from the pool\n                        width = this.adjustWidth(lanes, pool.bounds.width());          \n                }\n               \n                /**???\n                 * Set width/height depending on containing lanes\n                 */            \n                else {\n                       \n                        // Reposition the pool if one shape is selected and the upperleft has changed\n                        if (selection.length === 1 && this.isResized(currentShape, this.hashedBounds[pool.id][currentShape.id])){\n                                var oldXY = this.hashedBounds[pool.id][currentShape.id].upperLeft();\n                                var xy = currentShape.absoluteXY();\n                                x = oldXY.x - xy.x;\n                                y = oldXY.y - xy.y;\n                               \n                                // Adjust all other lanes beneath this lane\n                                if (x||y){\n                                        considerForDockers = considerForDockers.without(currentShape);\n                                        this.adjustLanes(pool, this.getAllExcludedLanes(pool, currentShape), x, 0);\n                                }\n                               \n                                // Adjust all child lanes\n                                var childLanes = this.getLanes(currentShape, true);\n                                if (childLanes.length > 0){\n                                        if (this.shouldScale(currentShape)){\n                                                var old = this.hashedBounds[pool.id][currentShape.id];\n                                                var scale = old.height()/currentShape.bounds.height();\n                                                this.adjustLanes(pool, childLanes, x, y, scale);\n                                        } else {\n                                                this.adjustLanes(pool, childLanes, x, y, 0);\n                                        }\n                                }\n                        }\n                       \n                        // Cache all bounds\n                        var changes = allLanes.map(function(lane){ return {\n                                shape: lane,\n                                bounds: lane.bounds.clone()\n                        } });\n                       \n                        // Get height and adjust child heights\n                        height = this.adjustHeight(lanes, currentShape);\n                        // Check if something has changed and maybe create a command\n                        this.checkForChanges(allLanes, changes);\n                       \n                        // Set width from the current shape\n                        width = this.adjustWidth(lanes, currentShape.bounds.width()+(this.getDepth(currentShape,pool)*30));\n                }\n               \n                this.setDimensions(pool, width, height, x, y);\n               \n               \n                if (this.facade.isExecutingCommands() && (deletedLanes.length === 0 || addedLanes.length !== 0)){\n                        // Update all dockers\n                        this.updateDockers(considerForDockers, pool);\n                       \n                        // Check if the order has changed\n                        if (this.hashedPositions[pool.id] && this.hashedPositions[pool.id].keys().any(function(key, i){\n                                        return (allLanes[i]||{}).id     !== key;\n                                })){\n                               \n                                var LanesHasBeenReordered = ORYX.Core.Command.extend({\n                                        construct: function(originPosition, newPosition, lanes, plugin, poolId) {\n                                                this.originPosition = Object.clone(originPosition);\n                                                this.newPosition = Object.clone(newPosition);\n                                                this.lanes = lanes;\n                                                this.plugin = plugin;\n                                                this.pool = poolId;\n                                        },\n                                        execute: function(){\n                                                if (!this.executed){\n                                                        this.executed = true;\n                                                        this.lanes.each(function(lane){\n                                                                if (this.newPosition[lane.id])\n                                                                        lane.bounds.moveTo(this.newPosition[lane.id])\n                                                        }.bind(this));\n                                                        this.plugin.hashedPositions[this.pool] = Object.clone(this.newPosition);\n                                                }\n                                        },\n                                        rollback: function(){\n                                                this.lanes.each(function(lane){\n                                                        if (this.originPosition[lane.id])\n                                                                lane.bounds.moveTo(this.originPosition[lane.id])\n                                                }.bind(this));\n                                                this.plugin.hashedPositions[this.pool] = Object.clone(this.originPosition);\n                                        }\n                                });\n                               \n                                var hp2 = $H({});\n                                allLanes.each(function(lane){\n                                        hp2[lane.id] = lane.bounds.upperLeft();\n                                })\n                       \n                                var command = new LanesHasBeenReordered(hashedPositions, hp2, allLanes, this, pool.id);\n                                this.facade.executeCommands([command]);\n                                       \n                        }\n                }\n               \n                this.hashedBounds[pool.id] = {};\n                this.hashedPositions[pool.id] = hashedPositions;\n               \n                var i=-1;\n                while (++i < allLanes.length) {\n                        // Cache positions\n                        this.hashedBounds[pool.id][allLanes[i].id] = allLanes[i].absoluteBounds();\n                       \n                        // Cache also the bounds of child shapes, mainly for child subprocesses\n                        this.hashChildShapes(allLanes[i]);\n               \n                        this.hashedLaneDepth[allLanes[i].id] = this.getDepth(allLanes[i], pool);\n                       \n                        this.forceToUpdateLane(allLanes[i]);\n                }\n               \n                this.hashedPoolPositions[pool.id] = pool.bounds.clone();\n               \n               \n                // Update selection\n                //this.facade.setSelection(selection);          \n        },\n       \n        shouldScale: function(element){\n                var childLanes = element.getChildNodes().findAll(function(shape){ return shape.getStencil().id().endsWith(\"Lane\") })\n                return childLanes.length > 1 || childLanes.any(function(lane){ return this.shouldScale(lane) }.bind(this))\n        },\n       \n        /**\n         * Lookup if some bounds has changed\n         * @param {Object} lanes\n         * @param {Object} changes\n         */\n        checkForChanges: function(lanes, changes){\n                // Check if something has changed\n                if (this.facade.isExecutingCommands() && changes.any(function(change){\n                        return change.shape.bounds.toString() !== change.bounds.toString();\n                })){\n                       \n                        var Command = ORYX.Core.Command.extend({\n                                                construct: function(changes) {\n                                                        this.oldState = changes;\n                                                        this.newState = changes.map(function(s){ return {shape:s.shape, bounds:s.bounds.clone()}});\n                                                },\n                                                execute: function(){\n                                                        if (this.executed){\n                                                                this.applyState(this.newState);\n                                                        }\n                                                        this.executed = true;\n                                                },\n                                                rollback: function(){\n                                                        this.applyState(this.oldState);\n                                                },\n                                                applyState: function(state){\n                                                        state.each(function(s){\n                                                                s.shape.bounds.set(s.bounds.upperLeft(), s.bounds.lowerRight());\n                                                        })\n                                                }\n                                        });\n                                       \n                        this.facade.executeCommands([new Command(changes)]);\n                }\n        },\n       \n        isResized: function(shape, bounds){\n               \n                if (!bounds||!shape){\n                        return false;\n                }\n               \n                var oldB = bounds;\n                //var oldXY = oldB.upperLeft();\n                //var xy = shape.absoluteXY();\n                return Math.round(oldB.width() - shape.bounds.width()) !== 0 || Math.round(oldB.height() - shape.bounds.height()) !== 0\n        },\n       \n        adjustLanes: function(pool, lanes, x, y, scale){\n               \n                scale = scale || 0;\n\n                // For every lane, adjust the child nodes with the offset\n                lanes.each(function(l){\n                        l.getChildNodes().each(function(child){\n                                if (!child.getStencil().id().endsWith(\"Lane\")){\n                                        var cy = scale ? child.bounds.center().y - (child.bounds.center().y/scale) : -y;\n                                        child.bounds.moveBy((x||0), -cy);\n                                       \n                                        if (scale&&child.getStencil().id().endsWith(\"Subprocess\")) {\n                                                this.moveChildDockers(child, {x:(0), y:-cy});\n                                        }\n                               \n                                }\n                        }.bind(this));\n                        this.hashedBounds[pool.id][l.id].moveBy(-(x||0), !scale?-y:0);\n                        if (scale) {\n                                l.isScaled = true;\n                        }\n                }.bind(this))\n               \n        },\n       \n        getAllExcludedLanes: function(parent, lane){\n                var lanes = [];\n                parent.getChildNodes().each(function(shape){\n                        if ((!lane || shape !== lane) && shape.getStencil().id().endsWith(\"Lane\")){\n                                lanes.push(shape);\n                                lanes = lanes.concat(this.getAllExcludedLanes(shape, lane));\n                        }\n                }.bind(this));\n                return lanes;\n        },\n       \n       \n        forceToUpdateLane: function(lane){\n               \n                if (lane.bounds.height() !== lane._svgShapes[0].height) {      \n                        lane.isChanged = true;\n                        lane.isResized = true;\n                        lane._update();\n                }\n        },\n       \n        getDepth: function(child, parent){\n               \n                var i=0;\n                while(child && child.parent && child !== parent){\n                        child = child.parent;\n                        ++i\n                }\n                return i;\n        },\n       \n        updateDepth: function(lane, fromDepth, toDepth){\n               \n                var xOffset = (fromDepth - toDepth) * 30;\n               \n                lane.getChildNodes().each(function(shape){\n                        shape.bounds.moveBy(xOffset, 0);\n                       \n                        [].concat(children[j].getIncomingShapes())\n                                        .concat(children[j].getOutgoingShapes())\n                                       \n                })\n               \n        },\n       \n        setDimensions: function(shape, width, height, x, y){\n                var isLane = shape.getStencil().id().endsWith(\"Lane\");\n                // Set the bounds\n                shape.bounds.set(\n                                isLane  ? 30 : (shape.bounds.a.x - (x || 0)),\n                                isLane  ? shape.bounds.a.y : (shape.bounds.a.y - (y || 0)),\n                                width   ? shape.bounds.a.x + width - (isLane?30:(x||0)) : shape.bounds.b.x,\n                                height  ? shape.bounds.a.y + height - (isLane?0:(y||0)) : shape.bounds.b.y\n                        );\n        },\n\n        setLanePosition: function(shape, y){\n               \n                shape.bounds.moveTo(30, y);\n       \n        },\n               \n        adjustWidth: function(lanes, width) {\n               \n                // Set width to each lane\n                (lanes||[]).each(function(lane){\n                        this.setDimensions(lane, width);\n                        this.adjustWidth(this.getLanes(lane), width-30);\n                }.bind(this));\n               \n                return width;\n        },\n       \n       \n        adjustHeight: function(lanes, changedLane, propagateHeight){\n               \n                var oldHeight = 0;\n                if (!changedLane && propagateHeight){\n                        var i=-1;\n                        while (++i<lanes.length){      \n                                oldHeight += lanes[i].bounds.height();          \n                        }\n                }\n               \n                var i=-1;\n                var height = 0;\n               \n                // Iterate trough every lane\n                while (++i<lanes.length){\n                       \n                        if (lanes[i] === changedLane) {\n                                // Propagate new height down to the children\n                                this.adjustHeight(this.getLanes(lanes[i]), undefined, lanes[i].bounds.height());\n                               \n                                lanes[i].bounds.set({x:30, y:height}, {x:lanes[i].bounds.width()+30, y:lanes[i].bounds.height()+height})\n                                                               \n                        } else if (!changedLane && propagateHeight) {\n                               \n                                var tempHeight = (lanes[i].bounds.height() * propagateHeight) / oldHeight;\n                                // Propagate height\n                                this.adjustHeight(this.getLanes(lanes[i]), undefined, tempHeight);\n                                // Set height propotional to the propagated and old height\n                                this.setDimensions(lanes[i], null, tempHeight);\n                                this.setLanePosition(lanes[i], height);\n                        } else {\n                                // Get height from children\n                                var tempHeight = this.adjustHeight(this.getLanes(lanes[i]), changedLane, propagateHeight);\n                                if (!tempHeight) {\n                                        tempHeight = lanes[i].bounds.height();\n                                }\n                                this.setDimensions(lanes[i], null, tempHeight);\n                                this.setLanePosition(lanes[i], height);\n                        }\n                       \n                        height += lanes[i].bounds.height();\n                }\n               \n                return height;\n               \n        },\n       \n       \n        updateHeight: function(root){\n               \n                var lanes = this.getLanes(root);\n               \n                if (lanes.length == 0){\n                        return root.bounds.height();\n                }\n               \n                var height = 0;\n                var i=-1;\n                while (++i < lanes.length) {\n                        this.setLanePosition(lanes[i], height);\n                        height += this.updateHeight(lanes[i]);\n                }\n               \n                this.setDimensions(root, null, height);\n               \n                return height;\n        },\n       \n        getOffset: function(lane, includePool, pool){\n               \n                var offset = {x:0,y:0};\n               \n               \n                /*var parent = lane;\n                 while(parent) {\n                                               \n                       \n                        var offParent = this.hashedBounds[pool.id][parent.id] ||(includePool === true ? this.hashedPoolPositions[parent.id] : undefined);\n                        if (offParent){\n                                var ul = parent.bounds.upperLeft();\n                                var ulo = offParent.upperLeft();\n                                offset.x += ul.x-ulo.x;\n                                offset.y += ul.y-ulo.y;\n                        }\n                       \n                        if (parent.getStencil().id().endsWith(\"Pool\")) {\n                                break;\n                        }\n                       \n                        parent = parent.parent;\n                }       */\n               \n                var offset = lane.absoluteXY();\n               \n                var hashed = this.hashedBounds[pool.id][lane.id] ||(includePool === true ? this.hashedPoolPositions[lane.id] : undefined);\n                if (hashed) {\n                        offset.x -= hashed.upperLeft().x;      \n                        offset.y -= hashed.upperLeft().y;              \n                } else {\n                        return {x:0,y:0}\n                }              \n                return offset;\n        },\n       \n        getNextLane: function(shape){\n                while(shape && !shape.getStencil().id().endsWith(\"Lane\")){\n                        if (shape instanceof ORYX.Core.Canvas) {\n                                return null;\n                        }\n                        shape = shape.parent;\n                }\n                return shape;\n        },\n       \n        getParentPool: function(shape){\n                while(shape && !shape.getStencil().id().endsWith(\"Pool\")){\n                        if (shape instanceof ORYX.Core.Canvas) {\n                                return null;\n                        }\n                        shape = shape.parent;\n                }\n                return shape;\n        },\n       \n        updateDockers: function(lanes, pool){\n               \n                var absPool = pool.absoluteBounds(), movedShapes = [];\n                var oldPool = (this.hashedPoolPositions[pool.id]||absPool).clone();\n               \n                var i=-1, j=-1, k=-1, l=-1, docker;\n                var dockers = {};\n               \n                while (++i < lanes.length) {\n                       \n                        if (!this.hashedBounds[pool.id][lanes[i].id]) {\n                                continue;\n                        }\n                       \n                        var isScaled = lanes[i].isScaled;\n                        delete lanes[i].isScaled;\n                        var children = lanes[i].getChildNodes();\n                        var absBounds = lanes[i].absoluteBounds();\n                        var oldBounds = (this.hashedBounds[pool.id][lanes[i].id]||absBounds);\n                        //oldBounds.moveBy((absBounds.upperLeft().x-lanes[i].bounds.upperLeft().x), (absBounds.upperLeft().y-lanes[i].bounds.upperLeft().y));\n                        var offset = this.getOffset(lanes[i], true, pool);\n                        var xOffsetDepth = 0;\n\n                        var depth = this.getDepth(lanes[i], pool);\n                        if ( this.hashedLaneDepth[lanes[i].id] !== undefined &&  this.hashedLaneDepth[lanes[i].id] !== depth) {\n                                xOffsetDepth = (this.hashedLaneDepth[lanes[i].id] - depth) * 30;\n                                offset.x += xOffsetDepth;\n                        }\n                       \n                        j=-1;\n                       \n                        while (++j < children.length) {\n                               \n                                if (xOffsetDepth && !children[j].getStencil().id().endsWith(\"Lane\")) {\n                                        movedShapes.push({xOffset:xOffsetDepth, shape: children[j]});\n                                        children[j].bounds.moveBy(xOffsetDepth, 0);\n                                }\n                               \n                                if (children[j].getStencil().id().endsWith(\"Subprocess\")) {\n                                        this.moveChildDockers(children[j], offset);\n                                }\n                               \n                                var edges = [].concat(children[j].getIncomingShapes())\n                                        .concat(children[j].getOutgoingShapes())\n                                        // Remove all edges which are included in the selection from the list\n                                        .findAll(function(r){ return r instanceof ORYX.Core.Edge })\n\n                                k=-1;\n                                while (++k < edges.length) {                    \n                                       \n                                        if (edges[k].getStencil().id().endsWith(\"MessageFlow\")) {\n                                                this.layoutEdges(children[j], [edges[k]], offset);\n                                                continue;\n                                        }\n                                       \n                                        l=-1;\n                                        while (++l < edges[k].dockers.length) {\n                                               \n                                                docker = edges[k].dockers[l];\n                                               \n                                                if (docker.getDockedShape()||docker.isChanged){\n                                                        continue;\n                                                }\n                                       \n                                       \n                                                pos = docker.bounds.center();\n                                               \n                                                // Check if the modified center included the new position\n                                                var isOverLane = oldBounds.isIncluded(pos);\n                                                // Check if the original center is over the pool\n                                                var isOutSidePool = !oldPool.isIncluded(pos);\n                                                var previousIsOverLane = l == 0 ? isOverLane : oldBounds.isIncluded(edges[k].dockers[l-1].bounds.center());\n                                                var nextIsOverLane = l == edges[k].dockers.length-1 ? isOverLane : oldBounds.isIncluded(edges[k].dockers[l+1].bounds.center());\n                                                var off = Object.clone(offset);\n                                               \n                                                // If the\n                                                if (isScaled && isOverLane && this.isResized(lanes[i], this.hashedBounds[pool.id][lanes[i].id])){\n                                                        var relY = (pos.y - absBounds.upperLeft().y + off.y);\n                                                        off.y -= (relY - (relY * (absBounds.height()/oldBounds.height())));\n                                                }\n                                               \n                                                // Check if the previous dockers docked shape is from this lane\n                                                // Otherwise, check if the docker is over the lane OR is outside the lane\n                                                // but the previous/next was over this lane\n                                                if (isOverLane){\n                                                        dockers[docker.id] = {docker: docker, offset:off};\n                                                }\n                                                /*else if (l == 1 && edges[k].dockers.length>2 && edges[k].dockers[l-1].isDocked()){\n                                                        var dockedLane = this.getNextLane(edges[k].dockers[l-1].getDockedShape());\n                                                        if (dockedLane != lanes[i])\n                                                                continue;\n                                                        dockers[docker.id] = {docker: docker, offset:offset};\n                                                }\n                                                // Check if the next dockers docked shape is from this lane\n                                                else if (l == edges[k].dockers.length-2 && edges[k].dockers.length>2 && edges[k].dockers[l+1].isDocked()){\n                                                        var dockedLane = this.getNextLane(edges[k].dockers[l+1].getDockedShape());\n                                                        if (dockedLane != lanes[i])\n                                                                continue;\n                                                        dockers[docker.id] = {docker: docker, offset:offset};\n                                                }\n                                                                                               \n                                                else if (isOutSidePool) {\n                                                        dockers[docker.id] = {docker: docker, offset:this.getOffset(lanes[i], true, pool)};\n                                                }*/\n                                               \n                                       \n                                        }\n                                }\n                                               \n                        }\n                }\n               \n                // Move the moved children\n                var MoveChildCommand = ORYX.Core.Command.extend({\n                        construct: function(state){\n                                this.state = state;\n                        },\n                        execute: function(){\n                                if (this.executed){\n                                        this.state.each(function(s){\n                                                s.shape.bounds.moveBy(s.xOffset, 0);\n                                        });\n                                }\n                                this.executed = true;\n                        },\n                        rollback: function(){\n                                this.state.each(function(s){\n                                        s.shape.bounds.moveBy(-s.xOffset, 0);\n                                });\n                        }\n                })\n               \n               \n                // Set dockers\n                this.facade.executeCommands([new ORYX.Core.MoveDockersCommand(dockers), new MoveChildCommand(movedShapes)]);\n\n        },\n       \n        moveBy: function(pos, offset){\n                pos.x += offset.x;\n                pos.y += offset.y;\n                return pos;\n        },\n       \n        getHashedBounds: function(shape){\n                return this.currentPool && this.hashedBounds[this.currentPool.id][shape.id] ? this.hashedBounds[this.currentPool.id][shape.id] : shape.absoluteBounds();\n        },\n       \n        /**\n         * Returns a set on all child lanes for the given Shape. If recursive is TRUE, also indirect children will be returned (default is FALSE)\n         * The set is sorted with first child the lowest y-coordinate and the last one the highest.\n         * @param {ORYX.Core.Shape} shape\n         * @param {boolean} recursive\n         */\n        getLanes: function(shape, recursive){\n                var namespace = this.getNamespace();\n            \n                // Get all the child lanes\n                var lanes = shape.getChildNodes(recursive||false).findAll(function(node) { return (node.getStencil().id() === namespace + \"Lane\"); });\n               \n                // Sort all lanes by there y coordinate\n                lanes = lanes.sort(function(a, b){\n                       \n                                        // Get y coordinates for upper left and lower right\n                                        var auy = Math.round(a.bounds.upperLeft().y);\n                                        var buy = Math.round(b.bounds.upperLeft().y);\n                                        var aly = Math.round(a.bounds.lowerRight().y);\n                                        var bly = Math.round(b.bounds.lowerRight().y);\n                                       \n                                        var ha  = this.getHashedBounds(a);\n                                        var hb  = this.getHashedBounds(b);\n                                       \n                                        // Get the old y coordinates\n                                        var oauy = Math.round(ha.upperLeft().y);\n                                        var obuy = Math.round(hb.upperLeft().y);\n                                        var oaly = Math.round(ha.lowerRight().y);\n                                        var obly = Math.round(hb.lowerRight().y);\n                                       \n                                        // If equal, than use the old one\n                                        if (auy == buy && aly == bly) {\n                                                auy = oauy; buy = obuy; aly = oaly; bly = obly;\n                                        }\n                                       \n                                        if (Math.round(a.bounds.height()-ha.height()) === 0 && Math.round(b.bounds.height()-hb.height()) === 0){\n                                                return auy < buy ? -1 : (auy > buy ? 1: 0);\n                                        }\n                                       \n                                        // Check if upper left and lower right is completely above/below\n                                        var above = auy < buy && aly < bly;\n                                        var below = auy > buy && aly > bly;\n                                        // Check if a is above b including the old values\n                                        var slightlyAboveBottom = auy < buy && aly >= bly && oaly < obly;\n                                        var slightlyAboveTop = auy >= buy && aly < bly && oauy < obuy;\n                                        // Check if a is below b including the old values\n                                        var slightlyBelowBottom = auy > buy && aly <= bly && oaly > obly;\n                                        var slightlyBelowTop = auy <= buy && aly > bly && oauy > obuy;\n                                       \n                                        // Return -1 if a is above b, 1 if b is above a, or 0 otherwise\n                                        return  (above || slightlyAboveBottom || slightlyAboveTop ? -1 : (below || slightlyBelowBottom || slightlyBelowTop ? 1 : 0))\n                                }.bind(this));\n                               \n                // Return lanes\n                return lanes;\n        },\n                       \n        getNamespace: function() {\n                if(!this.namespace) {\n                        var stencilsets = this.facade.getStencilSets();\n                        if(stencilsets.keys()) {\n                                this.namespace = stencilsets.keys()[0];\n                        } else {\n                                return undefined;\n                        }\n                }\n                return this.namespace;\n        }\n\t};\n\t\n\tvar ResizeLanesCommand = ORYX.Core.Command.extend({\n\n        construct: function(shape, parent, pool, plugin) {\n       \n                this.facade  = plugin.facade;\n                this.plugin  = plugin;\n                this.shape       = shape;\n                this.changes;\n               \n                this.pool       = pool;\n               \n                this.parent     = parent;\n               \n               \n                this.shapeChildren = [];\n               \n                /*\n                 * The Bounds have to be stored\n                 * separate because they would\n                 * otherwise also be influenced\n                 */\n                this.shape.getChildShapes().each(function(childShape) {\n                        this.shapeChildren.push({\n                                shape: childShape,\n                                bounds: {\n                                        a: {\n                                                x: childShape.bounds.a.x,\n                                                y: childShape.bounds.a.y\n                                        },\n                                        b: {\n                                                x: childShape.bounds.b.x,\n                                                y: childShape.bounds.b.y\n                                        }\n                                }\n                        });\n                }.bind(this));\n\n                this.shapeUpperLeft = this.shape.bounds.upperLeft();\n               \n                // If there is no parent,\n                // correct the abs position with the parents abs.\n                /*if (!this.shape.parent) {\n                        var pAbs = parent.absoluteXY();\n                        this.shapeUpperLeft.x += pAbs.x;\n                        this.shapeUpperLeft.y += pAbs.y;\n                }*/\n                this.parentHeight       = this.parent.bounds.height();\n\n        },\n       \n        getLeafLanes: function(lane){\n                var childLanes = this.plugin.getLanes(lane).map(function(child){\n                        return this.getLeafLanes(child);\n                }.bind(this)).flatten();\n                return childLanes.length > 0 ? childLanes : [lane];\n        },\n       \n        findNewLane: function(){\n               \n                var lanes = this.plugin.getLanes(this.parent);\n\n                var leafLanes = this.getLeafLanes(this.parent);\n                /*leafLanes = leafLanes.sort(function(a,b){\n                        var aupl = a.absoluteXY().y;\n                        var bupl = b.absoluteXY().y;\n                        return aupl < bupl ? -1 : (aupl > bupl ? 1 : 0)\n                })*/\n                this.lane = leafLanes.find(function(l){ return l.bounds.upperLeft().y >= this.shapeUpperLeft.y }.bind(this)) || leafLanes.last();\n                this.laneUpperLeft = this.lane.bounds.upperLeft();      \n        },\n       \n        execute: function() {\n               \n                if(this.changes) {\n                        this.executeAgain();\n                        return;\n                }\n\n                /*\n                 * Rescue all ChildShapes of the deleted\n                 * Shape into the lane that takes its\n                 * place\n                 */\n               \n                if (!this.lane){\n                        this.findNewLane();\n                }\n               \n                if(this.lane) {                \n                       \n                        var laUpL = this.laneUpperLeft;\n                        var shUpL = this.shapeUpperLeft;\n                       \n                        var depthChange = this.plugin.getDepth(this.lane, this.parent)-1;\n                                               \n                        this.changes = $H({});\n                       \n                        // Selected lane is BELOW the removed lane\n                        if (laUpL.y >= shUpL.y) {                              \n                                this.lane.getChildShapes().each(function(childShape) {\n                                       \n                                        /*\n                                         * Cache the changes for rollback\n                                         */\n                                        if(!this.changes[childShape.getId()]) {\n                                                this.changes[childShape.getId()] = this.computeChanges(childShape, this.lane, this.lane, this.shape.bounds.height());\n                                        }\n                                       \n                                        childShape.bounds.moveBy(0, this.shape.bounds.height());\n                                }.bind(this));\n                               \n                                this.plugin.hashChildShapes(this.lane);\n                               \n                                this.shapeChildren.each(function(shapeChild) {\n                                        shapeChild.shape.bounds.set(shapeChild.bounds);\n                                        shapeChild.shape.bounds.moveBy((shUpL.x-30)-(depthChange*30), 0);\n                                       \n                                        /*\n                                         * Cache the changes for rollback\n                                         */\n                                        if(!this.changes[shapeChild.shape.getId()]) {\n                                                this.changes[shapeChild.shape.getId()] = this.computeChanges(shapeChild.shape, this.shape, this.lane, 0);\n                                        }\n                                       \n                                        this.lane.add(shapeChild.shape);\n                                       \n                                }.bind(this));          \n                       \n                                this.lane.bounds.moveBy(0, shUpL.y-laUpL.y);\n                       \n                        // Selected lane is ABOVE the removed lane      \n                        } else if(shUpL.y > laUpL.y){\n                               \n                                this.shapeChildren.each(function(shapeChild) {\n                                        shapeChild.shape.bounds.set(shapeChild.bounds);        \n                                        shapeChild.shape.bounds.moveBy((shUpL.x-30)-(depthChange*30), this.lane.bounds.height());                      \n                                       \n                                        /*\n                                         * Cache the changes for rollback\n                                         */\n                                        if(!this.changes[shapeChild.shape.getId()]) {\n                                                this.changes[shapeChild.shape.getId()] = this.computeChanges(shapeChild.shape, this.shape, this.lane, 0);\n                                        }\n                                       \n                                        this.lane.add(shapeChild.shape);\n                                       \n                                }.bind(this));\n                        }\n                       \n                       \n\n                       \n                }\n                               \n                /*\n                 * Adjust the height of the lanes\n                 */\n                // Get the height values\n                var oldHeight   = this.lane.bounds.height();                            \n                var newHeight   = this.lane.length === 1 ? this.parentHeight : this.lane.bounds.height() + this.shape.bounds.height();\n\n                // Set height\n                this.setHeight(newHeight, oldHeight, this.parent, this.parentHeight, true);\n               \n                // Cache all sibling lanes\n                //this.changes[this.shape.getId()] = this.computeChanges(this.shape, this.parent, this.parent, 0);\n                this.plugin.getLanes(this.parent).each(function(childLane){\n                        if(!this.changes[childLane.getId()] && childLane !== this.lane && childLane !== this.shape) {\n                                this.changes[childLane.getId()] = this.computeChanges(childLane, this.parent, this.parent, 0);\n                        }\n                }.bind(this))\n                       \n                // Update\n                this.update();\n        },\n       \n        setHeight: function(newHeight, oldHeight, parent, parentHeight, store){\n               \n                // Set heigh of the lane\n                this.plugin.setDimensions(this.lane, this.lane.bounds.width(), newHeight);\n                this.plugin.hashedBounds[this.pool.id][this.lane.id] = this.lane.absoluteBounds();\n               \n                // Adjust child lanes\n                this.plugin.adjustHeight(this.plugin.getLanes(parent), this.lane);\n               \n                if (store === true){\n                        // Store changes\n                        this.changes[this.shape.getId()] = this.computeChanges(this.shape, parent, parent, 0, oldHeight, newHeight);    \n                }\n               \n                // Set parents height\n                this.plugin.setDimensions(parent, parent.bounds.width(), parentHeight);\n               \n                if (parent !== this.pool){\n                        this.plugin.setDimensions(this.pool, this.pool.bounds.width(), this.pool.bounds.height() + (newHeight-oldHeight));\n                }\n        },\n       \n        update: function(){\n               \n                // Hack to prevent the updating of the dockers\n                this.plugin.hashedBounds[this.pool.id][\"REMOVED\"] = true;\n                // Update\n                //this.facade.getCanvas().update();\n        },\n       \n        rollback: function() {\n               \n                var laUpL = this.laneUpperLeft;\n                var shUpL = this.shapeUpperLeft;\n                       \n                this.changes.each(function(pair) {\n                       \n                        var parent                      = pair.value.oldParent;\n                        var shape                       = pair.value.shape;\n                        var parentHeight        = pair.value.parentHeight;\n                        var oldHeight           = pair.value.oldHeight;\n                        var newHeight           = pair.value.newHeight;\n                       \n                        // Move siblings\n                        if (shape.getStencil().id().endsWith(\"Lane\")){\n                                shape.bounds.moveTo(pair.value.oldPosition);    \n                        }\n                       \n                        // If lane\n                        if(oldHeight) {                                \n                                this.setHeight(oldHeight, newHeight, parent, parent.bounds.height() + (oldHeight - newHeight));\n                                if (laUpL.y >= shUpL.y) {\n                                        this.lane.bounds.moveBy(0, this.shape.bounds.height()-1);\n                                }\n                        } else {\n                                parent.add(shape);\n                                shape.bounds.moveTo(pair.value.oldPosition);\n                               \n                        }\n\n                       \n                }.bind(this));\n               \n                // Update\n                //this.update();\n               \n        },\n       \n        executeAgain: function() {\n               \n                this.changes.each(function(pair) {\n                        var parent        = pair.value.newParent;\n                        var shape         = pair.value.shape;\n                        var newHeight = pair.value.newHeight;\n                        var oldHeight = pair.value.oldHeight;\n                       \n                        // If lane\n                        if(newHeight) {\n                                var laUpL = this.laneUpperLeft.y;\n                                var shUpL = this.shapeUpperLeft.y;\n                       \n                                if (laUpL >= shUpL) {\n                                        this.lane.bounds.moveBy(0, shUpL - laUpL);\n                                }\n                                this.setHeight(newHeight, oldHeight, parent, parent.bounds.height() + (newHeight-oldHeight));\n                        } else {\n                                parent.add(shape);\n                                shape.bounds.moveTo(pair.value.newPosition);\n                        }\n                       \n                }.bind(this));\n               \n                // Update\n                this.update();\n        },\n       \n        computeChanges: function(shape, oldParent, parent, yOffset, oldHeight, newHeight) {\n               \n                oldParent = this.changes[shape.getId()] ? this.changes[shape.getId()].oldParent : oldParent;\n                var oldPosition = this.changes[shape.getId()] ? this.changes[shape.getId()].oldPosition : shape.bounds.upperLeft();\n               \n                var sUl = shape.bounds.upperLeft();\n               \n                var pos = {x: sUl.x, y: sUl.y + yOffset};\n               \n                var changes = {\n                        shape           : shape,\n                        parentHeight: oldParent.bounds.height(),\n                        oldParent       : oldParent,\n                        oldPosition     : oldPosition,\n                        oldHeight       : oldHeight,\n                        newParent       : parent,\n                        newPosition : pos,\n                        newHeight       : newHeight\n                };\n                       \n                return changes;\n        }\n       \n\t});\n\n\t\t\n\tORYX.Plugins.BPMN2_0 = ORYX.Plugins.AbstractPlugin.extend(ORYX.Plugins.BPMN2_0);\n\t\n}()\t"
  },
  {
    "path": "open-layui-web/src/main/view/static/editor-app/libs/angular-dragdrop.min-1.0.3.js",
    "content": "/**\n * Implementing Drag and Drop functionality in AngularJS is easier than ever.\n * Demo: http://codef0rmer.github.com/angular-dragdrop/\n * \n * @version 1.0.3\n *\n * (c) 2013 Amit Gharat a.k.a codef0rmer <amit.2006.it@gmail.com> - amitgharat.wordpress.com\n */\nvar jqyoui=angular.module(\"ngDragDrop\",[]).service(\"ngDragDropService\",[\"$timeout\",\"$parse\",function($timeout,$parse){this.callEventCallback=function(scope,callbackName,event,ui){if(!callbackName){return}var args=[event,ui];var match=callbackName.match(/^(.+)\\((.+)\\)$/);if(match!==null){callbackName=match[1];values=eval(\"[\"+match[0].replace(/^(.+)\\(/,\"\").replace(/\\)/,\"\")+\"]\");args.push.apply(args,values)}scope[callbackName].apply(scope,args)};this.invokeDrop=function(e,t,n,r){var i=\"\",s=\"\",o={},u={},a=null,f={},l={},c,h,p=null,d=t.scope(),v=e.scope();i=e.attr(\"ng-model\");s=t.attr(\"ng-model\");c=v.$eval(i);h=d.$eval(s);p=t.find(\"[jqyoui-draggable]:last\");u=d.$eval(t.attr(\"jqyoui-droppable\"))||[];o=v.$eval(e.attr(\"jqyoui-draggable\"))||[];o.index=this.fixIndex(v,o,c);u.index=this.fixIndex(d,u,h);a=angular.isArray(c)?o.index:null;f=angular.isArray(c)?c[a]:c;if(angular.isArray(h)&&u&&u.index!==undefined){l=h[u.index]}else if(!angular.isArray(h)){l=h}else{l={}}if(o.animate===true){this.move(e,p.length>0?p:t,null,\"fast\",u,null);this.move(p.length>0&&!u.multiple?p:[],e.parent(\"[jqyoui-droppable]\"),jqyoui.startXY,\"fast\",u,function(){$timeout(function(){e.css({position:\"relative\",left:\"\",top:\"\"});p.css({position:\"relative\",left:\"\",top:\"\"});this.mutateDraggable(v,u,o,i,s,l,e);this.mutateDroppable(d,u,o,s,f,a);this.callEventCallback(d,u.onDrop,n,r)}.bind(this))}.bind(this))}else{$timeout(function(){this.mutateDraggable(v,u,o,i,s,l,e);this.mutateDroppable(d,u,o,s,f,a);this.callEventCallback(d,u.onDrop,n,r)}.bind(this))}};this.move=function(e,t,n,r,i,s){if(e.length===0){if(s){window.setTimeout(function(){s()},300)}return false}var o=9999,u=e.offset(),a=t&&t.is(\":visible\");if(n===null&&t.length>0){if(t.attr(\"jqyoui-draggable\")!==undefined&&t.attr(\"ng-model\")!==undefined&&t.is(\":visible\")&&i&&i.multiple){n=t.offset();if(i.stack===false){n.left+=t.outerWidth(true)}else{n.top+=t.outerHeight(true)}}else{n=t.css({visibility:\"hidden\",display:\"block\"}).offset();t.css({visibility:\"\",display:a?\"\":\"none\"})}}e.css({position:\"absolute\",\"z-index\":o}).css(u).animate(n,r,function(){if(s)s()})};this.mutateDroppable=function(e,t,n,r,i,s){var o=e.$eval(r);e.__dragItem=i;if(angular.isArray(o)){if(t&&t.index>=0){o[t.index]=i}else{o.push(i)}if(n&&n.placeholder===true){o[o.length-1][\"jqyoui_pos\"]=s}}else{$parse(r+\" = __dragItem\")(e);if(n&&n.placeholder===true){o[\"jqyoui_pos\"]=s}}};this.mutateDraggable=function(e,t,n,r,i,s,o){var u=angular.equals(angular.copy(s),{}),a=e.$eval(r);e.__dropItem=s;if(n&&n.placeholder){if(n.placeholder!=\"keep\"){if(angular.isArray(a)&&n.index!==undefined){a[n.index]=s}else{$parse(r+\" = __dropItem\")(e)}}}else{if(angular.isArray(a)){if(u){if(n&&n.placeholder!==true&&n.placeholder!==\"keep\"){a.splice(n.index,1)}}else{a[n.index]=s}}else{$parse(r+\" = __dropItem\")(e);if(e.$parent){$parse(r+\" = __dropItem\")(e.$parent)}}}o.css({\"z-index\":\"\",left:\"\",top:\"\"})};this.fixIndex=function(e,t,n){if(t.applyFilter&&angular.isArray(n)&&n.length>0){var r=e[t.applyFilter](),i=r[t.index],s=undefined;n.forEach(function(e,t){if(angular.equals(e,i)){s=t}});return s}return t.index}}]).directive(\"jqyouiDraggable\",[\"ngDragDropService\",function(e){return{require:\"?jqyouiDroppable\",restrict:\"A\",link:function(t,n,r){var i,s;var o=function(o,u){if(o){i=t.$eval(n.attr(\"jqyoui-draggable\"))||[];n.draggable({disabled:false}).draggable(t.$eval(r.jqyouiOptions)||{}).draggable({start:function(n,r){s=angular.element(this).css(\"z-index\");angular.element(this).css(\"z-index\",99999);jqyoui.startXY=angular.element(this).offset();e.callEventCallback(t,i.onStart,n,r)},stop:function(n,r){angular.element(this).css(\"z-index\",s);e.callEventCallback(t,i.onStop,n,r)},drag:function(n,r){e.callEventCallback(t,i.onDrag,n,r)}})}else{n.draggable({disabled:true})}};t.$watch(function(){return t.$eval(r.drag)},o);o()}}}]).directive(\"jqyouiDroppable\",[\"ngDragDropService\",function(e){return{restrict:\"A\",priority:1,link:function(t,n,r){var i=function(i,s){if(i){n.droppable({disabled:false}).droppable(t.$eval(r.jqyouiOptions)||{}).droppable({over:function(n,r){var i=t.$eval(angular.element(this).attr(\"jqyoui-droppable\"))||[];e.callEventCallback(t,i.onOver,n,r)},out:function(n,r){var i=t.$eval(angular.element(this).attr(\"jqyoui-droppable\"))||[];e.callEventCallback(t,i.onOut,n,r)},drop:function(t,n){e.invokeDrop(angular.element(n.draggable),angular.element(this),t,n)}})}else{n.droppable({disabled:true})}};t.$watch(function(){return t.$eval(r.drop)},i);i()}}}])\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/editor-app/libs/angular-mocks_1.2.13/angular-mocks.js",
    "content": "/**\n * @license AngularJS v1.2.13\n * (c) 2010-2014 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n\n'use strict';\n\n/**\n * @ngdoc overview\n * @name angular.mock\n * @description\n *\n * Namespace from 'angular-mocks.js' which contains testing related code.\n */\nangular.mock = {};\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ngMock.$browser\n *\n * @description\n * This service is a mock implementation of {@link ng.$browser}. It provides fake\n * implementation for commonly used browser apis that are hard to test, e.g. setTimeout, xhr,\n * cookies, etc...\n *\n * The api of this service is the same as that of the real {@link ng.$browser $browser}, except\n * that there are several helper methods available which can be used in tests.\n */\nangular.mock.$BrowserProvider = function() {\n  this.$get = function() {\n    return new angular.mock.$Browser();\n  };\n};\n\nangular.mock.$Browser = function() {\n  var self = this;\n\n  this.isMock = true;\n  self.$$url = \"http://server/\";\n  self.$$lastUrl = self.$$url; // used by url polling fn\n  self.pollFns = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = angular.noop;\n  self.$$incOutstandingRequestCount = angular.noop;\n\n\n  // register url polling fn\n\n  self.onUrlChange = function(listener) {\n    self.pollFns.push(\n      function() {\n        if (self.$$lastUrl != self.$$url) {\n          self.$$lastUrl = self.$$url;\n          listener(self.$$url);\n        }\n      }\n    );\n\n    return listener;\n  };\n\n  self.cookieHash = {};\n  self.lastCookieHash = {};\n  self.deferredFns = [];\n  self.deferredNextId = 0;\n\n  self.defer = function(fn, delay) {\n    delay = delay || 0;\n    self.deferredFns.push({time:(self.defer.now + delay), fn:fn, id: self.deferredNextId});\n    self.deferredFns.sort(function(a,b){ return a.time - b.time;});\n    return self.deferredNextId++;\n  };\n\n\n  /**\n   * @name ngMock.$browser#defer.now\n   * @propertyOf ngMock.$browser\n   *\n   * @description\n   * Current milliseconds mock time.\n   */\n  self.defer.now = 0;\n\n\n  self.defer.cancel = function(deferId) {\n    var fnIndex;\n\n    angular.forEach(self.deferredFns, function(fn, index) {\n      if (fn.id === deferId) fnIndex = index;\n    });\n\n    if (fnIndex !== undefined) {\n      self.deferredFns.splice(fnIndex, 1);\n      return true;\n    }\n\n    return false;\n  };\n\n\n  /**\n   * @name ngMock.$browser#defer.flush\n   * @methodOf ngMock.$browser\n   *\n   * @description\n   * Flushes all pending requests and executes the defer callbacks.\n   *\n   * @param {number=} number of milliseconds to flush. See {@link #defer.now}\n   */\n  self.defer.flush = function(delay) {\n    if (angular.isDefined(delay)) {\n      self.defer.now += delay;\n    } else {\n      if (self.deferredFns.length) {\n        self.defer.now = self.deferredFns[self.deferredFns.length-1].time;\n      } else {\n        throw new Error('No deferred tasks to be flushed');\n      }\n    }\n\n    while (self.deferredFns.length && self.deferredFns[0].time <= self.defer.now) {\n      self.deferredFns.shift().fn();\n    }\n  };\n\n  self.$$baseHref = '';\n  self.baseHref = function() {\n    return this.$$baseHref;\n  };\n};\nangular.mock.$Browser.prototype = {\n\n/**\n  * @name ngMock.$browser#poll\n  * @methodOf ngMock.$browser\n  *\n  * @description\n  * run all fns in pollFns\n  */\n  poll: function poll() {\n    angular.forEach(this.pollFns, function(pollFn){\n      pollFn();\n    });\n  },\n\n  addPollFn: function(pollFn) {\n    this.pollFns.push(pollFn);\n    return pollFn;\n  },\n\n  url: function(url, replace) {\n    if (url) {\n      this.$$url = url;\n      return this;\n    }\n\n    return this.$$url;\n  },\n\n  cookies:  function(name, value) {\n    if (name) {\n      if (angular.isUndefined(value)) {\n        delete this.cookieHash[name];\n      } else {\n        if (angular.isString(value) &&       //strings only\n            value.length <= 4096) {          //strict cookie storage limits\n          this.cookieHash[name] = value;\n        }\n      }\n    } else {\n      if (!angular.equals(this.cookieHash, this.lastCookieHash)) {\n        this.lastCookieHash = angular.copy(this.cookieHash);\n        this.cookieHash = angular.copy(this.cookieHash);\n      }\n      return this.cookieHash;\n    }\n  },\n\n  notifyWhenNoOutstandingRequests: function(fn) {\n    fn();\n  }\n};\n\n\n/**\n * @ngdoc object\n * @name ngMock.$exceptionHandlerProvider\n *\n * @description\n * Configures the mock implementation of {@link ng.$exceptionHandler} to rethrow or to log errors\n * passed into the `$exceptionHandler`.\n */\n\n/**\n * @ngdoc object\n * @name ngMock.$exceptionHandler\n *\n * @description\n * Mock implementation of {@link ng.$exceptionHandler} that rethrows or logs errors passed\n * into it. See {@link ngMock.$exceptionHandlerProvider $exceptionHandlerProvider} for configuration\n * information.\n *\n *\n * <pre>\n *   describe('$exceptionHandlerProvider', function() {\n *\n *     it('should capture log messages and exceptions', function() {\n *\n *       module(function($exceptionHandlerProvider) {\n *         $exceptionHandlerProvider.mode('log');\n *       });\n *\n *       inject(function($log, $exceptionHandler, $timeout) {\n *         $timeout(function() { $log.log(1); });\n *         $timeout(function() { $log.log(2); throw 'banana peel'; });\n *         $timeout(function() { $log.log(3); });\n *         expect($exceptionHandler.errors).toEqual([]);\n *         expect($log.assertEmpty());\n *         $timeout.flush();\n *         expect($exceptionHandler.errors).toEqual(['banana peel']);\n *         expect($log.log.logs).toEqual([[1], [2], [3]]);\n *       });\n *     });\n *   });\n * </pre>\n */\n\nangular.mock.$ExceptionHandlerProvider = function() {\n  var handler;\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$exceptionHandlerProvider#mode\n   * @methodOf ngMock.$exceptionHandlerProvider\n   *\n   * @description\n   * Sets the logging mode.\n   *\n   * @param {string} mode Mode of operation, defaults to `rethrow`.\n   *\n   *   - `rethrow`: If any errors are passed into the handler in tests, it typically\n   *                means that there is a bug in the application or test, so this mock will\n   *                make these tests fail.\n   *   - `log`: Sometimes it is desirable to test that an error is thrown, for this case the `log`\n   *            mode stores an array of errors in `$exceptionHandler.errors`, to allow later\n   *            assertion of them. See {@link ngMock.$log#assertEmpty assertEmpty()} and\n   *            {@link ngMock.$log#reset reset()}\n   */\n  this.mode = function(mode) {\n    switch(mode) {\n      case 'rethrow':\n        handler = function(e) {\n          throw e;\n        };\n        break;\n      case 'log':\n        var errors = [];\n\n        handler = function(e) {\n          if (arguments.length == 1) {\n            errors.push(e);\n          } else {\n            errors.push([].slice.call(arguments, 0));\n          }\n        };\n\n        handler.errors = errors;\n        break;\n      default:\n        throw new Error(\"Unknown mode '\" + mode + \"', only 'log'/'rethrow' modes are allowed!\");\n    }\n  };\n\n  this.$get = function() {\n    return handler;\n  };\n\n  this.mode('rethrow');\n};\n\n\n/**\n * @ngdoc service\n * @name ngMock.$log\n *\n * @description\n * Mock implementation of {@link ng.$log} that gathers all logged messages in arrays\n * (one array per logging level). These arrays are exposed as `logs` property of each of the\n * level-specific log function, e.g. for level `error` the array is exposed as `$log.error.logs`.\n *\n */\nangular.mock.$LogProvider = function() {\n  var debug = true;\n\n  function concat(array1, array2, index) {\n    return array1.concat(Array.prototype.slice.call(array2, index));\n  }\n\n  this.debugEnabled = function(flag) {\n    if (angular.isDefined(flag)) {\n      debug = flag;\n      return this;\n    } else {\n      return debug;\n    }\n  };\n\n  this.$get = function () {\n    var $log = {\n      log: function() { $log.log.logs.push(concat([], arguments, 0)); },\n      warn: function() { $log.warn.logs.push(concat([], arguments, 0)); },\n      info: function() { $log.info.logs.push(concat([], arguments, 0)); },\n      error: function() { $log.error.logs.push(concat([], arguments, 0)); },\n      debug: function() {\n        if (debug) {\n          $log.debug.logs.push(concat([], arguments, 0));\n        }\n      }\n    };\n\n    /**\n     * @ngdoc method\n     * @name ngMock.$log#reset\n     * @methodOf ngMock.$log\n     *\n     * @description\n     * Reset all of the logging arrays to empty.\n     */\n    $log.reset = function () {\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#log.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of messages logged using {@link ngMock.$log#log}.\n       *\n       * @example\n       * <pre>\n       * $log.log('Some Log');\n       * var first = $log.log.logs.unshift();\n       * </pre>\n       */\n      $log.log.logs = [];\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#info.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of messages logged using {@link ngMock.$log#info}.\n       *\n       * @example\n       * <pre>\n       * $log.info('Some Info');\n       * var first = $log.info.logs.unshift();\n       * </pre>\n       */\n      $log.info.logs = [];\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#warn.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of messages logged using {@link ngMock.$log#warn}.\n       *\n       * @example\n       * <pre>\n       * $log.warn('Some Warning');\n       * var first = $log.warn.logs.unshift();\n       * </pre>\n       */\n      $log.warn.logs = [];\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#error.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of messages logged using {@link ngMock.$log#error}.\n       *\n       * @example\n       * <pre>\n       * $log.error('Some Error');\n       * var first = $log.error.logs.unshift();\n       * </pre>\n       */\n      $log.error.logs = [];\n        /**\n       * @ngdoc property\n       * @name ngMock.$log#debug.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of messages logged using {@link ngMock.$log#debug}.\n       *\n       * @example\n       * <pre>\n       * $log.debug('Some Error');\n       * var first = $log.debug.logs.unshift();\n       * </pre>\n       */\n      $log.debug.logs = [];\n    };\n\n    /**\n     * @ngdoc method\n     * @name ngMock.$log#assertEmpty\n     * @methodOf ngMock.$log\n     *\n     * @description\n     * Assert that the all of the logging methods have no logged messages. If messages present, an\n     * exception is thrown.\n     */\n    $log.assertEmpty = function() {\n      var errors = [];\n      angular.forEach(['error', 'warn', 'info', 'log', 'debug'], function(logLevel) {\n        angular.forEach($log[logLevel].logs, function(log) {\n          angular.forEach(log, function (logItem) {\n            errors.push('MOCK $log (' + logLevel + '): ' + String(logItem) + '\\n' +\n                        (logItem.stack || ''));\n          });\n        });\n      });\n      if (errors.length) {\n        errors.unshift(\"Expected $log to be empty! Either a message was logged unexpectedly, or \"+\n          \"an expected log message was not checked and removed:\");\n        errors.push('');\n        throw new Error(errors.join('\\n---------\\n'));\n      }\n    };\n\n    $log.reset();\n    return $log;\n  };\n};\n\n\n/**\n * @ngdoc service\n * @name ngMock.$interval\n *\n * @description\n * Mock implementation of the $interval service.\n *\n * Use {@link ngMock.$interval#methods_flush `$interval.flush(millis)`} to\n * move forward by `millis` milliseconds and trigger any functions scheduled to run in that\n * time.\n *\n * @param {function()} fn A function that should be called repeatedly.\n * @param {number} delay Number of milliseconds between each function call.\n * @param {number=} [count=0] Number of times to repeat. If not set, or 0, will repeat\n *   indefinitely.\n * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise\n *   will invoke `fn` within the {@link ng.$rootScope.Scope#methods_$apply $apply} block.\n * @returns {promise} A promise which will be notified on each iteration.\n */\nangular.mock.$IntervalProvider = function() {\n  this.$get = ['$rootScope', '$q',\n       function($rootScope,   $q) {\n    var repeatFns = [],\n        nextRepeatId = 0,\n        now = 0;\n\n    var $interval = function(fn, delay, count, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          iteration = 0,\n          skipApply = (angular.isDefined(invokeApply) && !invokeApply);\n\n      count = (angular.isDefined(count)) ? count : 0,\n      promise.then(null, null, fn);\n\n      promise.$$intervalId = nextRepeatId;\n\n      function tick() {\n        deferred.notify(iteration++);\n\n        if (count > 0 && iteration >= count) {\n          var fnIndex;\n          deferred.resolve(iteration);\n\n          angular.forEach(repeatFns, function(fn, index) {\n            if (fn.id === promise.$$intervalId) fnIndex = index;\n          });\n\n          if (fnIndex !== undefined) {\n            repeatFns.splice(fnIndex, 1);\n          }\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }\n\n      repeatFns.push({\n        nextTime:(now + delay),\n        delay: delay,\n        fn: tick,\n        id: nextRepeatId,\n        deferred: deferred\n      });\n      repeatFns.sort(function(a,b){ return a.nextTime - b.nextTime;});\n\n      nextRepeatId++;\n      return promise;\n    };\n\n    $interval.cancel = function(promise) {\n      if(!promise) return false;\n      var fnIndex;\n\n      angular.forEach(repeatFns, function(fn, index) {\n        if (fn.id === promise.$$intervalId) fnIndex = index;\n      });\n\n      if (fnIndex !== undefined) {\n        repeatFns[fnIndex].deferred.reject('canceled');\n        repeatFns.splice(fnIndex, 1);\n        return true;\n      }\n\n      return false;\n    };\n\n    /**\n     * @ngdoc method\n     * @name ngMock.$interval#flush\n     * @methodOf ngMock.$interval\n     * @description\n     *\n     * Runs interval tasks scheduled to be run in the next `millis` milliseconds.\n     *\n     * @param {number=} millis maximum timeout amount to flush up until.\n     *\n     * @return {number} The amount of time moved forward.\n     */\n    $interval.flush = function(millis) {\n      now += millis;\n      while (repeatFns.length && repeatFns[0].nextTime <= now) {\n        var task = repeatFns[0];\n        task.fn();\n        task.nextTime += task.delay;\n        repeatFns.sort(function(a,b){ return a.nextTime - b.nextTime;});\n      }\n      return millis;\n    };\n\n    return $interval;\n  }];\n};\n\n\n/* jshint -W101 */\n/* The R_ISO8061_STR regex is never going to fit into the 100 char limit!\n * This directive should go inside the anonymous function but a bug in JSHint means that it would\n * not be enacted early enough to prevent the warning.\n */\nvar R_ISO8061_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?:\\:?(\\d\\d)(?:\\:?(\\d\\d)(?:\\.(\\d{3}))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d)))?$/;\n\nfunction jsonStringToDate(string) {\n  var match;\n  if (match = string.match(R_ISO8061_STR)) {\n    var date = new Date(0),\n        tzHour = 0,\n        tzMin  = 0;\n    if (match[9]) {\n      tzHour = int(match[9] + match[10]);\n      tzMin = int(match[9] + match[11]);\n    }\n    date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n    date.setUTCHours(int(match[4]||0) - tzHour,\n                     int(match[5]||0) - tzMin,\n                     int(match[6]||0),\n                     int(match[7]||0));\n    return date;\n  }\n  return string;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\n/**\n * @ngdoc object\n * @name angular.mock.TzDate\n * @description\n *\n * *NOTE*: this is not an injectable instance, just a globally available mock class of `Date`.\n *\n * Mock of the Date type which has its timezone specified via constructor arg.\n *\n * The main purpose is to create Date-like instances with timezone fixed to the specified timezone\n * offset, so that we can test code that depends on local timezone settings without dependency on\n * the time zone settings of the machine where the code is running.\n *\n * @param {number} offset Offset of the *desired* timezone in hours (fractions will be honored)\n * @param {(number|string)} timestamp Timestamp representing the desired time in *UTC*\n *\n * @example\n * !!!! WARNING !!!!!\n * This is not a complete Date object so only methods that were implemented can be called safely.\n * To make matters worse, TzDate instances inherit stuff from Date via a prototype.\n *\n * We do our best to intercept calls to \"unimplemented\" methods, but since the list of methods is\n * incomplete we might be missing some non-standard methods. This can result in errors like:\n * \"Date.prototype.foo called on incompatible Object\".\n *\n * <pre>\n * var newYearInBratislava = new TzDate(-1, '2009-12-31T23:00:00Z');\n * newYearInBratislava.getTimezoneOffset() => -60;\n * newYearInBratislava.getFullYear() => 2010;\n * newYearInBratislava.getMonth() => 0;\n * newYearInBratislava.getDate() => 1;\n * newYearInBratislava.getHours() => 0;\n * newYearInBratislava.getMinutes() => 0;\n * newYearInBratislava.getSeconds() => 0;\n * </pre>\n *\n */\nangular.mock.TzDate = function (offset, timestamp) {\n  var self = new Date(0);\n  if (angular.isString(timestamp)) {\n    var tsStr = timestamp;\n\n    self.origDate = jsonStringToDate(timestamp);\n\n    timestamp = self.origDate.getTime();\n    if (isNaN(timestamp))\n      throw {\n        name: \"Illegal Argument\",\n        message: \"Arg '\" + tsStr + \"' passed into TzDate constructor is not a valid date string\"\n      };\n  } else {\n    self.origDate = new Date(timestamp);\n  }\n\n  var localOffset = new Date(timestamp).getTimezoneOffset();\n  self.offsetDiff = localOffset*60*1000 - offset*1000*60*60;\n  self.date = new Date(timestamp + self.offsetDiff);\n\n  self.getTime = function() {\n    return self.date.getTime() - self.offsetDiff;\n  };\n\n  self.toLocaleDateString = function() {\n    return self.date.toLocaleDateString();\n  };\n\n  self.getFullYear = function() {\n    return self.date.getFullYear();\n  };\n\n  self.getMonth = function() {\n    return self.date.getMonth();\n  };\n\n  self.getDate = function() {\n    return self.date.getDate();\n  };\n\n  self.getHours = function() {\n    return self.date.getHours();\n  };\n\n  self.getMinutes = function() {\n    return self.date.getMinutes();\n  };\n\n  self.getSeconds = function() {\n    return self.date.getSeconds();\n  };\n\n  self.getMilliseconds = function() {\n    return self.date.getMilliseconds();\n  };\n\n  self.getTimezoneOffset = function() {\n    return offset * 60;\n  };\n\n  self.getUTCFullYear = function() {\n    return self.origDate.getUTCFullYear();\n  };\n\n  self.getUTCMonth = function() {\n    return self.origDate.getUTCMonth();\n  };\n\n  self.getUTCDate = function() {\n    return self.origDate.getUTCDate();\n  };\n\n  self.getUTCHours = function() {\n    return self.origDate.getUTCHours();\n  };\n\n  self.getUTCMinutes = function() {\n    return self.origDate.getUTCMinutes();\n  };\n\n  self.getUTCSeconds = function() {\n    return self.origDate.getUTCSeconds();\n  };\n\n  self.getUTCMilliseconds = function() {\n    return self.origDate.getUTCMilliseconds();\n  };\n\n  self.getDay = function() {\n    return self.date.getDay();\n  };\n\n  // provide this method only on browsers that already have it\n  if (self.toISOString) {\n    self.toISOString = function() {\n      return padNumber(self.origDate.getUTCFullYear(), 4) + '-' +\n            padNumber(self.origDate.getUTCMonth() + 1, 2) + '-' +\n            padNumber(self.origDate.getUTCDate(), 2) + 'T' +\n            padNumber(self.origDate.getUTCHours(), 2) + ':' +\n            padNumber(self.origDate.getUTCMinutes(), 2) + ':' +\n            padNumber(self.origDate.getUTCSeconds(), 2) + '.' +\n            padNumber(self.origDate.getUTCMilliseconds(), 3) + 'Z';\n    };\n  }\n\n  //hide all methods not implemented in this mock that the Date prototype exposes\n  var unimplementedMethods = ['getUTCDay',\n      'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds',\n      'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear',\n      'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds',\n      'setYear', 'toDateString', 'toGMTString', 'toJSON', 'toLocaleFormat', 'toLocaleString',\n      'toLocaleTimeString', 'toSource', 'toString', 'toTimeString', 'toUTCString', 'valueOf'];\n\n  angular.forEach(unimplementedMethods, function(methodName) {\n    self[methodName] = function() {\n      throw new Error(\"Method '\" + methodName + \"' is not implemented in the TzDate mock\");\n    };\n  });\n\n  return self;\n};\n\n//make \"tzDateInstance instanceof Date\" return true\nangular.mock.TzDate.prototype = Date.prototype;\n/* jshint +W101 */\n\nangular.mock.animate = angular.module('ngAnimateMock', ['ng'])\n\n  .config(['$provide', function($provide) {\n    var reflowQueue = [];\n\n    $provide.value('$$animateReflow', function(fn) {\n      reflowQueue.push(fn);\n      return angular.noop;\n    });\n\n    $provide.decorator('$animate', function($delegate) {\n      var animate = {\n        queue : [],\n        enabled : $delegate.enabled,\n        triggerReflow : function() {\n          if(reflowQueue.length === 0) {\n            throw new Error('No animation reflows present');\n          }\n          angular.forEach(reflowQueue, function(fn) {\n            fn();\n          });\n          reflowQueue = [];\n        }\n      };\n\n      angular.forEach(\n        ['enter','leave','move','addClass','removeClass','setClass'], function(method) {\n        animate[method] = function() {\n          animate.queue.push({\n            event : method,\n            element : arguments[0],\n            args : arguments\n          });\n          $delegate[method].apply($delegate, arguments);\n        };\n      });\n\n      return animate;\n    });\n\n  }]);\n\n\n/**\n * @ngdoc function\n * @name angular.mock.dump\n * @description\n *\n * *NOTE*: this is not an injectable instance, just a globally available function.\n *\n * Method for serializing util angular objects (scope, elements, etc..) into strings, useful for\n * debugging.\n *\n * This method is also available on window, where it can be used to display objects on debug\n * console.\n *\n * @param {*} object - any object to turn into string.\n * @return {string} a serialized string of the argument\n */\nangular.mock.dump = function(object) {\n  return serialize(object);\n\n  function serialize(object) {\n    var out;\n\n    if (angular.isElement(object)) {\n      object = angular.element(object);\n      out = angular.element('<div></div>');\n      angular.forEach(object, function(element) {\n        out.append(angular.element(element).clone());\n      });\n      out = out.html();\n    } else if (angular.isArray(object)) {\n      out = [];\n      angular.forEach(object, function(o) {\n        out.push(serialize(o));\n      });\n      out = '[ ' + out.join(', ') + ' ]';\n    } else if (angular.isObject(object)) {\n      if (angular.isFunction(object.$eval) && angular.isFunction(object.$apply)) {\n        out = serializeScope(object);\n      } else if (object instanceof Error) {\n        out = object.stack || ('' + object.name + ': ' + object.message);\n      } else {\n        // TODO(i): this prevents methods being logged,\n        // we should have a better way to serialize objects\n        out = angular.toJson(object, true);\n      }\n    } else {\n      out = String(object);\n    }\n\n    return out;\n  }\n\n  function serializeScope(scope, offset) {\n    offset = offset ||  '  ';\n    var log = [offset + 'Scope(' + scope.$id + '): {'];\n    for ( var key in scope ) {\n      if (Object.prototype.hasOwnProperty.call(scope, key) && !key.match(/^(\\$|this)/)) {\n        log.push('  ' + key + ': ' + angular.toJson(scope[key]));\n      }\n    }\n    var child = scope.$$childHead;\n    while(child) {\n      log.push(serializeScope(child, offset + '  '));\n      child = child.$$nextSibling;\n    }\n    log.push('}');\n    return log.join('\\n' + offset);\n  }\n};\n\n/**\n * @ngdoc object\n * @name ngMock.$httpBackend\n * @description\n * Fake HTTP backend implementation suitable for unit testing applications that use the\n * {@link ng.$http $http service}.\n *\n * *Note*: For fake HTTP backend implementation suitable for end-to-end testing or backend-less\n * development please see {@link ngMockE2E.$httpBackend e2e $httpBackend mock}.\n *\n * During unit testing, we want our unit tests to run quickly and have no external dependencies so\n * we don’t want to send {@link https://developer.mozilla.org/en/xmlhttprequest XHR} or\n * {@link http://en.wikipedia.org/wiki/JSONP JSONP} requests to a real server. All we really need is\n * to verify whether a certain request has been sent or not, or alternatively just let the\n * application make requests, respond with pre-trained responses and assert that the end result is\n * what we expect it to be.\n *\n * This mock implementation can be used to respond with static or dynamic responses via the\n * `expect` and `when` apis and their shortcuts (`expectGET`, `whenPOST`, etc).\n *\n * When an Angular application needs some data from a server, it calls the $http service, which\n * sends the request to a real server using $httpBackend service. With dependency injection, it is\n * easy to inject $httpBackend mock (which has the same API as $httpBackend) and use it to verify\n * the requests and respond with some testing data without sending a request to real server.\n *\n * There are two ways to specify what test data should be returned as http responses by the mock\n * backend when the code under test makes http requests:\n *\n * - `$httpBackend.expect` - specifies a request expectation\n * - `$httpBackend.when` - specifies a backend definition\n *\n *\n * # Request Expectations vs Backend Definitions\n *\n * Request expectations provide a way to make assertions about requests made by the application and\n * to define responses for those requests. The test will fail if the expected requests are not made\n * or they are made in the wrong order.\n *\n * Backend definitions allow you to define a fake backend for your application which doesn't assert\n * if a particular request was made or not, it just returns a trained response if a request is made.\n * The test will pass whether or not the request gets made during testing.\n *\n *\n * <table class=\"table\">\n *   <tr><th width=\"220px\"></th><th>Request expectations</th><th>Backend definitions</th></tr>\n *   <tr>\n *     <th>Syntax</th>\n *     <td>.expect(...).respond(...)</td>\n *     <td>.when(...).respond(...)</td>\n *   </tr>\n *   <tr>\n *     <th>Typical usage</th>\n *     <td>strict unit tests</td>\n *     <td>loose (black-box) unit testing</td>\n *   </tr>\n *   <tr>\n *     <th>Fulfills multiple requests</th>\n *     <td>NO</td>\n *     <td>YES</td>\n *   </tr>\n *   <tr>\n *     <th>Order of requests matters</th>\n *     <td>YES</td>\n *     <td>NO</td>\n *   </tr>\n *   <tr>\n *     <th>Request required</th>\n *     <td>YES</td>\n *     <td>NO</td>\n *   </tr>\n *   <tr>\n *     <th>Response required</th>\n *     <td>optional (see below)</td>\n *     <td>YES</td>\n *   </tr>\n * </table>\n *\n * In cases where both backend definitions and request expectations are specified during unit\n * testing, the request expectations are evaluated first.\n *\n * If a request expectation has no response specified, the algorithm will search your backend\n * definitions for an appropriate response.\n *\n * If a request didn't match any expectation or if the expectation doesn't have the response\n * defined, the backend definitions are evaluated in sequential order to see if any of them match\n * the request. The response from the first matched definition is returned.\n *\n *\n * # Flushing HTTP requests\n *\n * The $httpBackend used in production always responds to requests with responses asynchronously.\n * If we preserved this behavior in unit testing we'd have to create async unit tests, which are\n * hard to write, understand, and maintain. However, the testing mock can't respond\n * synchronously because that would change the execution of the code under test. For this reason the\n * mock $httpBackend has a `flush()` method, which allows the test to explicitly flush pending\n * requests and thus preserve the async api of the backend while allowing the test to execute\n * synchronously.\n *\n *\n * # Unit testing with mock $httpBackend\n * The following code shows how to setup and use the mock backend when unit testing a controller.\n * First we create the controller under test:\n *\n  <pre>\n  // The controller code\n  function MyController($scope, $http) {\n    var authToken;\n\n    $http.get('/auth.py').success(function(data, status, headers) {\n      authToken = headers('A-Token');\n      $scope.user = data;\n    });\n\n    $scope.saveMessage = function(message) {\n      var headers = { 'Authorization': authToken };\n      $scope.status = 'Saving...';\n\n      $http.post('/add-msg.py', message, { headers: headers } ).success(function(response) {\n        $scope.status = '';\n      }).error(function() {\n        $scope.status = 'ERROR!';\n      });\n    };\n  }\n  </pre>\n *\n * Now we setup the mock backend and create the test specs:\n *\n  <pre>\n    // testing controller\n    describe('MyController', function() {\n       var $httpBackend, $rootScope, createController;\n\n       beforeEach(inject(function($injector) {\n         // Set up the mock http service responses\n         $httpBackend = $injector.get('$httpBackend');\n         // backend definition util for all tests\n         $httpBackend.when('GET', '/auth.py').respond({userId: 'userX'}, {'A-Token': 'xxx'});\n\n         // Get hold of a scope (i.e. the root scope)\n         $rootScope = $injector.get('$rootScope');\n         // The $controller service is used to create instances of controllers\n         var $controller = $injector.get('$controller');\n\n         createController = function() {\n           return $controller('MyController', {'$scope' : $rootScope });\n         };\n       }));\n\n\n       afterEach(function() {\n         $httpBackend.verifyNoOutstandingExpectation();\n         $httpBackend.verifyNoOutstandingRequest();\n       });\n\n\n       it('should fetch authentication token', function() {\n         $httpBackend.expectGET('/auth.py');\n         var controller = createController();\n         $httpBackend.flush();\n       });\n\n\n       it('should send msg to server', function() {\n         var controller = createController();\n         $httpBackend.flush();\n\n         // now you don’t care about the authentication, but\n         // the controller will still send the request and\n         // $httpBackend will respond without you having to\n         // specify the expectation and response for this request\n\n         $httpBackend.expectPOST('/add-msg.py', 'message content').respond(201, '');\n         $rootScope.saveMessage('message content');\n         expect($rootScope.status).toBe('Saving...');\n         $httpBackend.flush();\n         expect($rootScope.status).toBe('');\n       });\n\n\n       it('should send auth header', function() {\n         var controller = createController();\n         $httpBackend.flush();\n\n         $httpBackend.expectPOST('/add-msg.py', undefined, function(headers) {\n           // check if the header was send, if it wasn't the expectation won't\n           // match the request and the test will fail\n           return headers['Authorization'] == 'xxx';\n         }).respond(201, '');\n\n         $rootScope.saveMessage('whatever');\n         $httpBackend.flush();\n       });\n    });\n   </pre>\n */\nangular.mock.$HttpBackendProvider = function() {\n  this.$get = ['$rootScope', createHttpBackendMock];\n};\n\n/**\n * General factory function for $httpBackend mock.\n * Returns instance for unit testing (when no arguments specified):\n *   - passing through is disabled\n *   - auto flushing is disabled\n *\n * Returns instance for e2e testing (when `$delegate` and `$browser` specified):\n *   - passing through (delegating request to real backend) is enabled\n *   - auto flushing is enabled\n *\n * @param {Object=} $delegate Real $httpBackend instance (allow passing through if specified)\n * @param {Object=} $browser Auto-flushing enabled if specified\n * @return {Object} Instance of $httpBackend mock\n */\nfunction createHttpBackendMock($rootScope, $delegate, $browser) {\n  var definitions = [],\n      expectations = [],\n      responses = [],\n      responsesPush = angular.bind(responses, responses.push),\n      copy = angular.copy;\n\n  function createResponse(status, data, headers) {\n    if (angular.isFunction(status)) return status;\n\n    return function() {\n      return angular.isNumber(status)\n          ? [status, data, headers]\n          : [200, status, data];\n    };\n  }\n\n  // TODO(vojta): change params to: method, url, data, headers, callback\n  function $httpBackend(method, url, data, callback, headers, timeout, withCredentials) {\n    var xhr = new MockXhr(),\n        expectation = expectations[0],\n        wasExpected = false;\n\n    function prettyPrint(data) {\n      return (angular.isString(data) || angular.isFunction(data) || data instanceof RegExp)\n          ? data\n          : angular.toJson(data);\n    }\n\n    function wrapResponse(wrapped) {\n      if (!$browser && timeout && timeout.then) timeout.then(handleTimeout);\n\n      return handleResponse;\n\n      function handleResponse() {\n        var response = wrapped.response(method, url, data, headers);\n        xhr.$$respHeaders = response[2];\n        callback(copy(response[0]), copy(response[1]), xhr.getAllResponseHeaders());\n      }\n\n      function handleTimeout() {\n        for (var i = 0, ii = responses.length; i < ii; i++) {\n          if (responses[i] === handleResponse) {\n            responses.splice(i, 1);\n            callback(-1, undefined, '');\n            break;\n          }\n        }\n      }\n    }\n\n    if (expectation && expectation.match(method, url)) {\n      if (!expectation.matchData(data))\n        throw new Error('Expected ' + expectation + ' with different data\\n' +\n            'EXPECTED: ' + prettyPrint(expectation.data) + '\\nGOT:      ' + data);\n\n      if (!expectation.matchHeaders(headers))\n        throw new Error('Expected ' + expectation + ' with different headers\\n' +\n                        'EXPECTED: ' + prettyPrint(expectation.headers) + '\\nGOT:      ' +\n                        prettyPrint(headers));\n\n      expectations.shift();\n\n      if (expectation.response) {\n        responses.push(wrapResponse(expectation));\n        return;\n      }\n      wasExpected = true;\n    }\n\n    var i = -1, definition;\n    while ((definition = definitions[++i])) {\n      if (definition.match(method, url, data, headers || {})) {\n        if (definition.response) {\n          // if $browser specified, we do auto flush all requests\n          ($browser ? $browser.defer : responsesPush)(wrapResponse(definition));\n        } else if (definition.passThrough) {\n          $delegate(method, url, data, callback, headers, timeout, withCredentials);\n        } else throw new Error('No response defined !');\n        return;\n      }\n    }\n    throw wasExpected ?\n        new Error('No response defined !') :\n        new Error('Unexpected request: ' + method + ' ' + url + '\\n' +\n                  (expectation ? 'Expected ' + expectation : 'No more request expected'));\n  }\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#when\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition.\n   *\n   * @param {string} method HTTP method.\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives\n   *   data string and returns true if the data is as expected.\n   * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header\n   *   object and returns true if the headers match the current definition.\n   * @returns {requestHandler} Returns an object with `respond` method that controls how a matched\n   *   request is handled.\n   *\n   *  - respond –\n   *      `{function([status,] data[, headers])|function(function(method, url, data, headers)}`\n   *    – The respond method takes a set of static data to be returned or a function that can return\n   *    an array containing response status (number), response data (string) and response headers\n   *    (Object).\n   */\n  $httpBackend.when = function(method, url, data, headers) {\n    var definition = new MockHttpExpectation(method, url, data, headers),\n        chain = {\n          respond: function(status, data, headers) {\n            definition.response = createResponse(status, data, headers);\n          }\n        };\n\n    if ($browser) {\n      chain.passThrough = function() {\n        definition.passThrough = true;\n      };\n    }\n\n    definitions.push(definition);\n    return chain;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenGET\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for GET requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenHEAD\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for HEAD requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenDELETE\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for DELETE requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenPOST\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for POST requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives\n   *   data string and returns true if the data is as expected.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenPUT\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for PUT requests.  For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives\n   *   data string and returns true if the data is as expected.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenJSONP\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for JSONP requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n  createShortMethods('when');\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expect\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation.\n   *\n   * @param {string} method HTTP method.\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that\n   *  receives data string and returns true if the data is as expected, or Object if request body\n   *  is in JSON format.\n   * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header\n   *   object and returns true if the headers match the current expectation.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *  request is handled.\n   *\n   *  - respond –\n   *    `{function([status,] data[, headers])|function(function(method, url, data, headers)}`\n   *    – The respond method takes a set of static data to be returned or a function that can return\n   *    an array containing response status (number), response data (string) and response headers\n   *    (Object).\n   */\n  $httpBackend.expect = function(method, url, data, headers) {\n    var expectation = new MockHttpExpectation(method, url, data, headers);\n    expectations.push(expectation);\n    return {\n      respond: function(status, data, headers) {\n        expectation.response = createResponse(status, data, headers);\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectGET\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for GET requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled. See #expect for more info.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectHEAD\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for HEAD requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectDELETE\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for DELETE requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectPOST\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for POST requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that\n   *  receives data string and returns true if the data is as expected, or Object if request body\n   *  is in JSON format.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectPUT\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for PUT requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that\n   *  receives data string and returns true if the data is as expected, or Object if request body\n   *  is in JSON format.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectPATCH\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for PATCH requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that\n   *  receives data string and returns true if the data is as expected, or Object if request body\n   *  is in JSON format.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectJSONP\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for JSONP requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n  createShortMethods('expect');\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#flush\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Flushes all pending requests using the trained responses.\n   *\n   * @param {number=} count Number of responses to flush (in the order they arrived). If undefined,\n   *   all pending requests will be flushed. If there are no pending requests when the flush method\n   *   is called an exception is thrown (as this typically a sign of programming error).\n   */\n  $httpBackend.flush = function(count) {\n    $rootScope.$digest();\n    if (!responses.length) throw new Error('No pending request to flush !');\n\n    if (angular.isDefined(count)) {\n      while (count--) {\n        if (!responses.length) throw new Error('No more pending request to flush !');\n        responses.shift()();\n      }\n    } else {\n      while (responses.length) {\n        responses.shift()();\n      }\n    }\n    $httpBackend.verifyNoOutstandingExpectation();\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#verifyNoOutstandingExpectation\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Verifies that all of the requests defined via the `expect` api were made. If any of the\n   * requests were not made, verifyNoOutstandingExpectation throws an exception.\n   *\n   * Typically, you would call this method following each test case that asserts requests using an\n   * \"afterEach\" clause.\n   *\n   * <pre>\n   *   afterEach($httpBackend.verifyNoOutstandingExpectation);\n   * </pre>\n   */\n  $httpBackend.verifyNoOutstandingExpectation = function() {\n    $rootScope.$digest();\n    if (expectations.length) {\n      throw new Error('Unsatisfied requests: ' + expectations.join(', '));\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#verifyNoOutstandingRequest\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Verifies that there are no outstanding requests that need to be flushed.\n   *\n   * Typically, you would call this method following each test case that asserts requests using an\n   * \"afterEach\" clause.\n   *\n   * <pre>\n   *   afterEach($httpBackend.verifyNoOutstandingRequest);\n   * </pre>\n   */\n  $httpBackend.verifyNoOutstandingRequest = function() {\n    if (responses.length) {\n      throw new Error('Unflushed requests: ' + responses.length);\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#resetExpectations\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Resets all request expectations, but preserves all backend definitions. Typically, you would\n   * call resetExpectations during a multiple-phase test when you want to reuse the same instance of\n   * $httpBackend mock.\n   */\n  $httpBackend.resetExpectations = function() {\n    expectations.length = 0;\n    responses.length = 0;\n  };\n\n  return $httpBackend;\n\n\n  function createShortMethods(prefix) {\n    angular.forEach(['GET', 'DELETE', 'JSONP'], function(method) {\n     $httpBackend[prefix + method] = function(url, headers) {\n       return $httpBackend[prefix](method, url, undefined, headers);\n     };\n    });\n\n    angular.forEach(['PUT', 'POST', 'PATCH'], function(method) {\n      $httpBackend[prefix + method] = function(url, data, headers) {\n        return $httpBackend[prefix](method, url, data, headers);\n      };\n    });\n  }\n}\n\nfunction MockHttpExpectation(method, url, data, headers) {\n\n  this.data = data;\n  this.headers = headers;\n\n  this.match = function(m, u, d, h) {\n    if (method != m) return false;\n    if (!this.matchUrl(u)) return false;\n    if (angular.isDefined(d) && !this.matchData(d)) return false;\n    if (angular.isDefined(h) && !this.matchHeaders(h)) return false;\n    return true;\n  };\n\n  this.matchUrl = function(u) {\n    if (!url) return true;\n    if (angular.isFunction(url.test)) return url.test(u);\n    return url == u;\n  };\n\n  this.matchHeaders = function(h) {\n    if (angular.isUndefined(headers)) return true;\n    if (angular.isFunction(headers)) return headers(h);\n    return angular.equals(headers, h);\n  };\n\n  this.matchData = function(d) {\n    if (angular.isUndefined(data)) return true;\n    if (data && angular.isFunction(data.test)) return data.test(d);\n    if (data && angular.isFunction(data)) return data(d);\n    if (data && !angular.isString(data)) return angular.equals(data, angular.fromJson(d));\n    return data == d;\n  };\n\n  this.toString = function() {\n    return method + ' ' + url;\n  };\n}\n\nfunction createMockXhr() {\n  return new MockXhr();\n}\n\nfunction MockXhr() {\n\n  // hack for testing $http, $httpBackend\n  MockXhr.$$lastInstance = this;\n\n  this.open = function(method, url, async) {\n    this.$$method = method;\n    this.$$url = url;\n    this.$$async = async;\n    this.$$reqHeaders = {};\n    this.$$respHeaders = {};\n  };\n\n  this.send = function(data) {\n    this.$$data = data;\n  };\n\n  this.setRequestHeader = function(key, value) {\n    this.$$reqHeaders[key] = value;\n  };\n\n  this.getResponseHeader = function(name) {\n    // the lookup must be case insensitive,\n    // that's why we try two quick lookups first and full scan last\n    var header = this.$$respHeaders[name];\n    if (header) return header;\n\n    name = angular.lowercase(name);\n    header = this.$$respHeaders[name];\n    if (header) return header;\n\n    header = undefined;\n    angular.forEach(this.$$respHeaders, function(headerVal, headerName) {\n      if (!header && angular.lowercase(headerName) == name) header = headerVal;\n    });\n    return header;\n  };\n\n  this.getAllResponseHeaders = function() {\n    var lines = [];\n\n    angular.forEach(this.$$respHeaders, function(value, key) {\n      lines.push(key + ': ' + value);\n    });\n    return lines.join('\\n');\n  };\n\n  this.abort = angular.noop;\n}\n\n\n/**\n * @ngdoc function\n * @name ngMock.$timeout\n * @description\n *\n * This service is just a simple decorator for {@link ng.$timeout $timeout} service\n * that adds a \"flush\" and \"verifyNoPendingTasks\" methods.\n */\n\nangular.mock.$TimeoutDecorator = function($delegate, $browser) {\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$timeout#flush\n   * @methodOf ngMock.$timeout\n   * @description\n   *\n   * Flushes the queue of pending tasks.\n   *\n   * @param {number=} delay maximum timeout amount to flush up until\n   */\n  $delegate.flush = function(delay) {\n    $browser.defer.flush(delay);\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$timeout#verifyNoPendingTasks\n   * @methodOf ngMock.$timeout\n   * @description\n   *\n   * Verifies that there are no pending tasks that need to be flushed.\n   */\n  $delegate.verifyNoPendingTasks = function() {\n    if ($browser.deferredFns.length) {\n      throw new Error('Deferred tasks to flush (' + $browser.deferredFns.length + '): ' +\n          formatPendingTasksAsString($browser.deferredFns));\n    }\n  };\n\n  function formatPendingTasksAsString(tasks) {\n    var result = [];\n    angular.forEach(tasks, function(task) {\n      result.push('{id: ' + task.id + ', ' + 'time: ' + task.time + '}');\n    });\n\n    return result.join(', ');\n  }\n\n  return $delegate;\n};\n\n/**\n *\n */\nangular.mock.$RootElementProvider = function() {\n  this.$get = function() {\n    return angular.element('<div ng-app></div>');\n  };\n};\n\n/**\n * @ngdoc overview\n * @name ngMock\n * @description\n *\n * # ngMock\n *\n * The `ngMock` module providers support to inject and mock Angular services into unit tests.\n * In addition, ngMock also extends various core ng services such that they can be\n * inspected and controlled in a synchronous manner within test code.\n *\n * {@installModule mock}\n *\n * <div doc-module-components=\"ngMock\"></div>\n *\n */\nangular.module('ngMock', ['ng']).provider({\n  $browser: angular.mock.$BrowserProvider,\n  $exceptionHandler: angular.mock.$ExceptionHandlerProvider,\n  $log: angular.mock.$LogProvider,\n  $interval: angular.mock.$IntervalProvider,\n  $httpBackend: angular.mock.$HttpBackendProvider,\n  $rootElement: angular.mock.$RootElementProvider\n}).config(['$provide', function($provide) {\n  $provide.decorator('$timeout', angular.mock.$TimeoutDecorator);\n}]);\n\n/**\n * @ngdoc overview\n * @name ngMockE2E\n * @description\n *\n * The `ngMockE2E` is an angular module which contains mocks suitable for end-to-end testing.\n * Currently there is only one mock present in this module -\n * the {@link ngMockE2E.$httpBackend e2e $httpBackend} mock.\n */\nangular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {\n  $provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator);\n}]);\n\n/**\n * @ngdoc object\n * @name ngMockE2E.$httpBackend\n * @description\n * Fake HTTP backend implementation suitable for end-to-end testing or backend-less development of\n * applications that use the {@link ng.$http $http service}.\n *\n * *Note*: For fake http backend implementation suitable for unit testing please see\n * {@link ngMock.$httpBackend unit-testing $httpBackend mock}.\n *\n * This implementation can be used to respond with static or dynamic responses via the `when` api\n * and its shortcuts (`whenGET`, `whenPOST`, etc) and optionally pass through requests to the\n * real $httpBackend for specific requests (e.g. to interact with certain remote apis or to fetch\n * templates from a webserver).\n *\n * As opposed to unit-testing, in an end-to-end testing scenario or in scenario when an application\n * is being developed with the real backend api replaced with a mock, it is often desirable for\n * certain category of requests to bypass the mock and issue a real http request (e.g. to fetch\n * templates or static files from the webserver). To configure the backend with this behavior\n * use the `passThrough` request handler of `when` instead of `respond`.\n *\n * Additionally, we don't want to manually have to flush mocked out requests like we do during unit\n * testing. For this reason the e2e $httpBackend automatically flushes mocked out requests\n * automatically, closely simulating the behavior of the XMLHttpRequest object.\n *\n * To setup the application to run with this http backend, you have to create a module that depends\n * on the `ngMockE2E` and your application modules and defines the fake backend:\n *\n * <pre>\n *   myAppDev = angular.module('myAppDev', ['myApp', 'ngMockE2E']);\n *   myAppDev.run(function($httpBackend) {\n *     phones = [{name: 'phone1'}, {name: 'phone2'}];\n *\n *     // returns the current list of phones\n *     $httpBackend.whenGET('/phones').respond(phones);\n *\n *     // adds a new phone to the phones array\n *     $httpBackend.whenPOST('/phones').respond(function(method, url, data) {\n *       phones.push(angular.fromJson(data));\n *     });\n *     $httpBackend.whenGET(/^\\/templates\\//).passThrough();\n *     //...\n *   });\n * </pre>\n *\n * Afterwards, bootstrap your app with this new module.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#when\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition.\n *\n * @param {string} method HTTP method.\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header\n *   object and returns true if the headers match the current definition.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n *\n *  - respond –\n *    `{function([status,] data[, headers])|function(function(method, url, data, headers)}`\n *    – The respond method takes a set of static data to be returned or a function that can return\n *    an array containing response status (number), response data (string) and response headers\n *    (Object).\n *  - passThrough – `{function()}` – Any request matching a backend definition with `passThrough`\n *    handler, will be pass through to the real backend (an XHR request will be made to the\n *    server.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenGET\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for GET requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenHEAD\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for HEAD requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenDELETE\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for DELETE requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenPOST\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for POST requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenPUT\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for PUT requests.  For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenPATCH\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for PATCH requests.  For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenJSONP\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for JSONP requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\nangular.mock.e2e = {};\nangular.mock.e2e.$httpBackendDecorator =\n  ['$rootScope', '$delegate', '$browser', createHttpBackendMock];\n\n\nangular.mock.clearDataCache = function() {\n  var key,\n      cache = angular.element.cache;\n\n  for(key in cache) {\n    if (Object.prototype.hasOwnProperty.call(cache,key)) {\n      var handle = cache[key].handle;\n\n      handle && angular.element(handle.elem).off();\n      delete cache[key];\n    }\n  }\n};\n\n\nif(window.jasmine || window.mocha) {\n\n  var currentSpec = null,\n      isSpecRunning = function() {\n        return !!currentSpec;\n      };\n\n\n  beforeEach(function() {\n    currentSpec = this;\n  });\n\n  afterEach(function() {\n    var injector = currentSpec.$injector;\n\n    currentSpec.$injector = null;\n    currentSpec.$modules = null;\n    currentSpec = null;\n\n    if (injector) {\n      injector.get('$rootElement').off();\n      injector.get('$browser').pollFns.length = 0;\n    }\n\n    angular.mock.clearDataCache();\n\n    // clean up jquery's fragment cache\n    angular.forEach(angular.element.fragments, function(val, key) {\n      delete angular.element.fragments[key];\n    });\n\n    MockXhr.$$lastInstance = null;\n\n    angular.forEach(angular.callbacks, function(val, key) {\n      delete angular.callbacks[key];\n    });\n    angular.callbacks.counter = 0;\n  });\n\n  /**\n   * @ngdoc function\n   * @name angular.mock.module\n   * @description\n   *\n   * *NOTE*: This function is also published on window for easy access.<br>\n   *\n   * This function registers a module configuration code. It collects the configuration information\n   * which will be used when the injector is created by {@link angular.mock.inject inject}.\n   *\n   * See {@link angular.mock.inject inject} for usage example\n   *\n   * @param {...(string|Function|Object)} fns any number of modules which are represented as string\n   *        aliases or as anonymous module initialization functions. The modules are used to\n   *        configure the injector. The 'ng' and 'ngMock' modules are automatically loaded. If an\n   *        object literal is passed they will be register as values in the module, the key being\n   *        the module name and the value being what is returned.\n   */\n  window.module = angular.mock.module = function() {\n    var moduleFns = Array.prototype.slice.call(arguments, 0);\n    return isSpecRunning() ? workFn() : workFn;\n    /////////////////////\n    function workFn() {\n      if (currentSpec.$injector) {\n        throw new Error('Injector already created, can not register a module!');\n      } else {\n        var modules = currentSpec.$modules || (currentSpec.$modules = []);\n        angular.forEach(moduleFns, function(module) {\n          if (angular.isObject(module) && !angular.isArray(module)) {\n            modules.push(function($provide) {\n              angular.forEach(module, function(value, key) {\n                $provide.value(key, value);\n              });\n            });\n          } else {\n            modules.push(module);\n          }\n        });\n      }\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name angular.mock.inject\n   * @description\n   *\n   * *NOTE*: This function is also published on window for easy access.<br>\n   *\n   * The inject function wraps a function into an injectable function. The inject() creates new\n   * instance of {@link AUTO.$injector $injector} per test, which is then used for\n   * resolving references.\n   *\n   *\n   * ## Resolving References (Underscore Wrapping)\n   * Often, we would like to inject a reference once, in a `beforeEach()` block and reuse this\n   * in multiple `it()` clauses. To be able to do this we must assign the reference to a variable\n   * that is declared in the scope of the `describe()` block. Since we would, most likely, want\n   * the variable to have the same name of the reference we have a problem, since the parameter\n   * to the `inject()` function would hide the outer variable.\n   *\n   * To help with this, the injected parameters can, optionally, be enclosed with underscores.\n   * These are ignored by the injector when the reference name is resolved.\n   *\n   * For example, the parameter `_myService_` would be resolved as the reference `myService`.\n   * Since it is available in the function body as _myService_, we can then assign it to a variable\n   * defined in an outer scope.\n   *\n   * ```\n   * // Defined out reference variable outside\n   * var myService;\n   *\n   * // Wrap the parameter in underscores\n   * beforeEach( inject( function(_myService_){\n   *   myService = _myService_;\n   * }));\n   *\n   * // Use myService in a series of tests.\n   * it('makes use of myService', function() {\n   *   myService.doStuff();\n   * });\n   *\n   * ```\n   *\n   * See also {@link angular.mock.module angular.mock.module}\n   *\n   * ## Example\n   * Example of what a typical jasmine tests looks like with the inject method.\n   * <pre>\n   *\n   *   angular.module('myApplicationModule', [])\n   *       .value('mode', 'app')\n   *       .value('version', 'v1.0.1');\n   *\n   *\n   *   describe('MyApp', function() {\n   *\n   *     // You need to load modules that you want to test,\n   *     // it loads only the \"ng\" module by default.\n   *     beforeEach(module('myApplicationModule'));\n   *\n   *\n   *     // inject() is used to inject arguments of all given functions\n   *     it('should provide a version', inject(function(mode, version) {\n   *       expect(version).toEqual('v1.0.1');\n   *       expect(mode).toEqual('app');\n   *     }));\n   *\n   *\n   *     // The inject and module method can also be used inside of the it or beforeEach\n   *     it('should override a version and test the new version is injected', function() {\n   *       // module() takes functions or strings (module aliases)\n   *       module(function($provide) {\n   *         $provide.value('version', 'overridden'); // override version here\n   *       });\n   *\n   *       inject(function(version) {\n   *         expect(version).toEqual('overridden');\n   *       });\n   *     });\n   *   });\n   *\n   * </pre>\n   *\n   * @param {...Function} fns any number of functions which will be injected using the injector.\n   */\n\n\n\n  var ErrorAddingDeclarationLocationStack = function(e, errorForStack) {\n    this.message = e.message;\n    this.name = e.name;\n    if (e.line) this.line = e.line;\n    if (e.sourceId) this.sourceId = e.sourceId;\n    if (e.stack && errorForStack)\n      this.stack = e.stack + '\\n' + errorForStack.stack;\n    if (e.stackArray) this.stackArray = e.stackArray;\n  };\n  ErrorAddingDeclarationLocationStack.prototype.toString = Error.prototype.toString;\n\n  window.inject = angular.mock.inject = function() {\n    var blockFns = Array.prototype.slice.call(arguments, 0);\n    var errorForStack = new Error('Declaration Location');\n    return isSpecRunning() ? workFn.call(currentSpec) : workFn;\n    /////////////////////\n    function workFn() {\n      var modules = currentSpec.$modules || [];\n\n      modules.unshift('ngMock');\n      modules.unshift('ng');\n      var injector = currentSpec.$injector;\n      if (!injector) {\n        injector = currentSpec.$injector = angular.injector(modules);\n      }\n      for(var i = 0, ii = blockFns.length; i < ii; i++) {\n        try {\n          /* jshint -W040 *//* Jasmine explicitly provides a `this` object when calling functions */\n          injector.invoke(blockFns[i] || angular.noop, this);\n          /* jshint +W040 */\n        } catch (e) {\n          if (e.stack && errorForStack) {\n            throw new ErrorAddingDeclarationLocationStack(e, errorForStack);\n          }\n          throw e;\n        } finally {\n          errorForStack = null;\n        }\n      }\n    }\n  };\n}\n\n\n})(window, window.angular);"
  },
  {
    "path": "open-layui-web/src/main/view/static/editor-app/libs/angular-resource_1.2.13/angular-resource.js",
    "content": "/**\n * @license AngularJS v1.2.13\n * (c) 2010-2014 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {'use strict';\n\nvar $resourceMinErr = angular.$$minErr('$resource');\n\n// Helper functions and regex to lookup a dotted path on an object\n// stopping at undefined/null.  The path must be composed of ASCII\n// identifiers (just like $parse)\nvar MEMBER_NAME_REGEX = /^(\\.[a-zA-Z_$][0-9a-zA-Z_$]*)+$/;\n\nfunction isValidDottedPath(path) {\n  return (path != null && path !== '' && path !== 'hasOwnProperty' &&\n      MEMBER_NAME_REGEX.test('.' + path));\n}\n\nfunction lookupDottedPath(obj, path) {\n  if (!isValidDottedPath(path)) {\n    throw $resourceMinErr('badmember', 'Dotted member path \"@{0}\" is invalid.', path);\n  }\n  var keys = path.split('.');\n  for (var i = 0, ii = keys.length; i < ii && obj !== undefined; i++) {\n    var key = keys[i];\n    obj = (obj !== null) ? obj[key] : undefined;\n  }\n  return obj;\n}\n\n/**\n * Create a shallow copy of an object and clear other fields from the destination\n */\nfunction shallowClearAndCopy(src, dst) {\n  dst = dst || {};\n\n  angular.forEach(dst, function(value, key){\n    delete dst[key];\n  });\n\n  for (var key in src) {\n    if (src.hasOwnProperty(key) && !(key.charAt(0) === '$' && key.charAt(1) === '$')) {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n/**\n * @ngdoc overview\n * @name ngResource\n * @description\n *\n * # ngResource\n *\n * The `ngResource` module provides interaction support with RESTful services\n * via the $resource service.\n *\n * {@installModule resource}\n *\n * <div doc-module-components=\"ngResource\"></div>\n *\n * See {@link ngResource.$resource `$resource`} for usage.\n */\n\n/**\n * @ngdoc object\n * @name ngResource.$resource\n * @requires $http\n *\n * @description\n * A factory which creates a resource object that lets you interact with\n * [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) server-side data sources.\n *\n * The returned resource object has action methods which provide high-level behaviors without\n * the need to interact with the low level {@link ng.$http $http} service.\n *\n * Requires the {@link ngResource `ngResource`} module to be installed.\n *\n * @param {string} url A parametrized URL template with parameters prefixed by `:` as in\n *   `/user/:username`. If you are using a URL with a port number (e.g.\n *   `http://example.com:8080/api`), it will be respected.\n *\n *   If you are using a url with a suffix, just add the suffix, like this:\n *   `$resource('http://example.com/resource.json')` or `$resource('http://example.com/:id.json')`\n *   or even `$resource('http://example.com/resource/:resource_id.:format')`\n *   If the parameter before the suffix is empty, :resource_id in this case, then the `/.` will be\n *   collapsed down to a single `.`.  If you need this sequence to appear and not collapse then you\n *   can escape it with `/\\.`.\n *\n * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in\n *   `actions` methods. If any of the parameter value is a function, it will be executed every time\n *   when a param value needs to be obtained for a request (unless the param was overridden).\n *\n *   Each key value in the parameter object is first bound to url template if present and then any\n *   excess keys are appended to the url search query after the `?`.\n *\n *   Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in\n *   URL `/path/greet?salutation=Hello`.\n *\n *   If the parameter value is prefixed with `@` then the value of that parameter is extracted from\n *   the data object (useful for non-GET operations).\n *\n * @param {Object.<Object>=} actions Hash with declaration of custom action that should extend the\n *   default set of resource actions. The declaration should be created in the format of {@link\n *   ng.$http#usage_parameters $http.config}:\n *\n *       {action1: {method:?, params:?, isArray:?, headers:?, ...},\n *        action2: {method:?, params:?, isArray:?, headers:?, ...},\n *        ...}\n *\n *   Where:\n *\n *   - **`action`** – {string} – The name of action. This name becomes the name of the method on\n *     your resource object.\n *   - **`method`** – {string} – HTTP request method. Valid methods are: `GET`, `POST`, `PUT`,\n *     `DELETE`, and `JSONP`.\n *   - **`params`** – {Object=} – Optional set of pre-bound parameters for this action. If any of\n *     the parameter value is a function, it will be executed every time when a param value needs to\n *     be obtained for a request (unless the param was overridden).\n *   - **`url`** – {string} – action specific `url` override. The url templating is supported just\n *     like for the resource-level urls.\n *   - **`isArray`** – {boolean=} – If true then the returned object for this action is an array,\n *     see `returns` section.\n *   - **`transformRequest`** –\n *     `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n *     transform function or an array of such functions. The transform function takes the http\n *     request body and headers and returns its transformed (typically serialized) version.\n *   - **`transformResponse`** –\n *     `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n *     transform function or an array of such functions. The transform function takes the http\n *     response body and headers and returns its transformed (typically deserialized) version.\n *   - **`cache`** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n *     GET request, otherwise if a cache instance built with\n *     {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n *     caching.\n *   - **`timeout`** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise} that\n *     should abort the request when resolved.\n *   - **`withCredentials`** - `{boolean}` - whether to set the `withCredentials` flag on the\n *     XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n *     requests with credentials} for more information.\n *   - **`responseType`** - `{string}` - see {@link\n *     https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType requestType}.\n *   - **`interceptor`** - `{Object=}` - The interceptor object has two optional methods -\n *     `response` and `responseError`. Both `response` and `responseError` interceptors get called\n *     with `http response` object. See {@link ng.$http $http interceptors}.\n *\n * @returns {Object} A resource \"class\" object with methods for the default set of resource actions\n *   optionally extended with custom `actions`. The default set contains these actions:\n *\n *       { 'get':    {method:'GET'},\n *         'save':   {method:'POST'},\n *         'query':  {method:'GET', isArray:true},\n *         'remove': {method:'DELETE'},\n *         'delete': {method:'DELETE'} };\n *\n *   Calling these methods invoke an {@link ng.$http} with the specified http method,\n *   destination and parameters. When the data is returned from the server then the object is an\n *   instance of the resource class. The actions `save`, `remove` and `delete` are available on it\n *   as  methods with the `$` prefix. This allows you to easily perform CRUD operations (create,\n *   read, update, delete) on server-side data like this:\n *   <pre>\n        var User = $resource('/user/:userId', {userId:'@id'});\n        var user = User.get({userId:123}, function() {\n          user.abc = true;\n          user.$save();\n        });\n     </pre>\n *\n *   It is important to realize that invoking a $resource object method immediately returns an\n *   empty reference (object or array depending on `isArray`). Once the data is returned from the\n *   server the existing reference is populated with the actual data. This is a useful trick since\n *   usually the resource is assigned to a model which is then rendered by the view. Having an empty\n *   object results in no rendering, once the data arrives from the server then the object is\n *   populated with the data and the view automatically re-renders itself showing the new data. This\n *   means that in most cases one never has to write a callback function for the action methods.\n *\n *   The action methods on the class object or instance object can be invoked with the following\n *   parameters:\n *\n *   - HTTP GET \"class\" actions: `Resource.action([parameters], [success], [error])`\n *   - non-GET \"class\" actions: `Resource.action([parameters], postData, [success], [error])`\n *   - non-GET instance actions:  `instance.$action([parameters], [success], [error])`\n *\n *   Success callback is called with (value, responseHeaders) arguments. Error callback is called\n *   with (httpResponse) argument.\n *\n *   Class actions return empty instance (with additional properties below).\n *   Instance actions return promise of the action.\n *\n *   The Resource instances and collection have these additional properties:\n *\n *   - `$promise`: the {@link ng.$q promise} of the original server interaction that created this\n *     instance or collection.\n *\n *     On success, the promise is resolved with the same resource instance or collection object,\n *     updated with data from server. This makes it easy to use in\n *     {@link ngRoute.$routeProvider resolve section of $routeProvider.when()} to defer view\n *     rendering until the resource(s) are loaded.\n *\n *     On failure, the promise is resolved with the {@link ng.$http http response} object, without\n *     the `resource` property.\n *\n *   - `$resolved`: `true` after first server interaction is completed (either with success or\n *      rejection), `false` before that. Knowing if the Resource has been resolved is useful in\n *      data-binding.\n *\n * @example\n *\n * # Credit card resource\n *\n * <pre>\n     // Define CreditCard class\n     var CreditCard = $resource('/user/:userId/card/:cardId',\n      {userId:123, cardId:'@id'}, {\n       charge: {method:'POST', params:{charge:true}}\n      });\n\n     // We can retrieve a collection from the server\n     var cards = CreditCard.query(function() {\n       // GET: /user/123/card\n       // server returns: [ {id:456, number:'1234', name:'Smith'} ];\n\n       var card = cards[0];\n       // each item is an instance of CreditCard\n       expect(card instanceof CreditCard).toEqual(true);\n       card.name = \"J. Smith\";\n       // non GET methods are mapped onto the instances\n       card.$save();\n       // POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'}\n       // server returns: {id:456, number:'1234', name: 'J. Smith'};\n\n       // our custom method is mapped as well.\n       card.$charge({amount:9.99});\n       // POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'}\n     });\n\n     // we can create an instance as well\n     var newCard = new CreditCard({number:'0123'});\n     newCard.name = \"Mike Smith\";\n     newCard.$save();\n     // POST: /user/123/card {number:'0123', name:'Mike Smith'}\n     // server returns: {id:789, number:'0123', name: 'Mike Smith'};\n     expect(newCard.id).toEqual(789);\n * </pre>\n *\n * The object returned from this function execution is a resource \"class\" which has \"static\" method\n * for each action in the definition.\n *\n * Calling these methods invoke `$http` on the `url` template with the given `method`, `params` and\n * `headers`.\n * When the data is returned from the server then the object is an instance of the resource type and\n * all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD\n * operations (create, read, update, delete) on server-side data.\n\n   <pre>\n     var User = $resource('/user/:userId', {userId:'@id'});\n     var user = User.get({userId:123}, function() {\n       user.abc = true;\n       user.$save();\n     });\n   </pre>\n *\n * It's worth noting that the success callback for `get`, `query` and other methods gets passed\n * in the response that came from the server as well as $http header getter function, so one\n * could rewrite the above example and get access to http headers as:\n *\n   <pre>\n     var User = $resource('/user/:userId', {userId:'@id'});\n     User.get({userId:123}, function(u, getResponseHeaders){\n       u.abc = true;\n       u.$save(function(u, putResponseHeaders) {\n         //u => saved user object\n         //putResponseHeaders => $http header getter\n       });\n     });\n   </pre>\n\n * # Creating a custom 'PUT' request\n * In this example we create a custom method on our resource to make a PUT request\n * <pre>\n *\t\tvar app = angular.module('app', ['ngResource', 'ngRoute']);\n *\n *\t\t// Some APIs expect a PUT request in the format URL/object/ID\n *\t\t// Here we are creating an 'update' method \n *\t\tapp.factory('Notes', ['$resource', function($resource) {\n *    return $resource('/notes/:id', null,\n *        {\n *            'update': { method:'PUT' }\n *        });\n *\t\t}]);\n *\n *\t\t// In our controller we get the ID from the URL using ngRoute and $routeParams\n *\t\t// We pass in $routeParams and our Notes factory along with $scope\n *\t\tapp.controller('NotesCtrl', ['$scope', '$routeParams', 'Notes',\n                                      function($scope, $routeParams, Notes) {\n *    // First get a note object from the factory\n *    var note = Notes.get({ id:$routeParams.id });\n *    $id = note.id;\n *\n *    // Now call update passing in the ID first then the object you are updating\n *    Notes.update({ id:$id }, note);\n *\n *    // This will PUT /notes/ID with the note object in the request payload\n *\t\t}]);\n * </pre>\n */\nangular.module('ngResource', ['ng']).\n  factory('$resource', ['$http', '$q', function($http, $q) {\n\n    var DEFAULT_ACTIONS = {\n      'get':    {method:'GET'},\n      'save':   {method:'POST'},\n      'query':  {method:'GET', isArray:true},\n      'remove': {method:'DELETE'},\n      'delete': {method:'DELETE'}\n    };\n    var noop = angular.noop,\n        forEach = angular.forEach,\n        extend = angular.extend,\n        copy = angular.copy,\n        isFunction = angular.isFunction;\n\n    /**\n     * We need our custom method because encodeURIComponent is too aggressive and doesn't follow\n     * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n     * segments:\n     *    segment       = *pchar\n     *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n     *    pct-encoded   = \"%\" HEXDIG HEXDIG\n     *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n     *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n     *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n     */\n    function encodeUriSegment(val) {\n      return encodeUriQuery(val, true).\n        replace(/%26/gi, '&').\n        replace(/%3D/gi, '=').\n        replace(/%2B/gi, '+');\n    }\n\n\n    /**\n     * This method is intended for encoding *key* or *value* parts of query component. We need a\n     * custom method because encodeURIComponent is too aggressive and encodes stuff that doesn't\n     * have to be encoded per http://tools.ietf.org/html/rfc3986:\n     *    query       = *( pchar / \"/\" / \"?\" )\n     *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n     *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n     *    pct-encoded   = \"%\" HEXDIG HEXDIG\n     *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n     *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n     */\n    function encodeUriQuery(val, pctEncodeSpaces) {\n      return encodeURIComponent(val).\n        replace(/%40/gi, '@').\n        replace(/%3A/gi, ':').\n        replace(/%24/g, '$').\n        replace(/%2C/gi, ',').\n        replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));\n    }\n\n    function Route(template, defaults) {\n      this.template = template;\n      this.defaults = defaults || {};\n      this.urlParams = {};\n    }\n\n    Route.prototype = {\n      setUrlParams: function(config, params, actionUrl) {\n        var self = this,\n            url = actionUrl || self.template,\n            val,\n            encodedVal;\n\n        var urlParams = self.urlParams = {};\n        forEach(url.split(/\\W/), function(param){\n          if (param === 'hasOwnProperty') {\n            throw $resourceMinErr('badname', \"hasOwnProperty is not a valid parameter name.\");\n          }\n          if (!(new RegExp(\"^\\\\d+$\").test(param)) && param &&\n               (new RegExp(\"(^|[^\\\\\\\\]):\" + param + \"(\\\\W|$)\").test(url))) {\n            urlParams[param] = true;\n          }\n        });\n        url = url.replace(/\\\\:/g, ':');\n\n        params = params || {};\n        forEach(self.urlParams, function(_, urlParam){\n          val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam];\n          if (angular.isDefined(val) && val !== null) {\n            encodedVal = encodeUriSegment(val);\n            url = url.replace(new RegExp(\":\" + urlParam + \"(\\\\W|$)\", \"g\"), function(match, p1) {\n              return encodedVal + p1;\n            });\n          } else {\n            url = url.replace(new RegExp(\"(\\/?):\" + urlParam + \"(\\\\W|$)\", \"g\"), function(match,\n                leadingSlashes, tail) {\n              if (tail.charAt(0) == '/') {\n                return tail;\n              } else {\n                return leadingSlashes + tail;\n              }\n            });\n          }\n        });\n\n        // strip trailing slashes and set the url\n        url = url.replace(/\\/+$/, '') || '/';\n        // then replace collapse `/.` if found in the last URL path segment before the query\n        // E.g. `http://url.com/id./format?q=x` becomes `http://url.com/id.format?q=x`\n        url = url.replace(/\\/\\.(?=\\w+($|\\?))/, '.');\n        // replace escaped `/\\.` with `/.`\n        config.url = url.replace(/\\/\\\\\\./, '/.');\n\n\n        // set params - delegate param encoding to $http\n        forEach(params, function(value, key){\n          if (!self.urlParams[key]) {\n            config.params = config.params || {};\n            config.params[key] = value;\n          }\n        });\n      }\n    };\n\n\n    function resourceFactory(url, paramDefaults, actions) {\n      var route = new Route(url);\n\n      actions = extend({}, DEFAULT_ACTIONS, actions);\n\n      function extractParams(data, actionParams){\n        var ids = {};\n        actionParams = extend({}, paramDefaults, actionParams);\n        forEach(actionParams, function(value, key){\n          if (isFunction(value)) { value = value(); }\n          ids[key] = value && value.charAt && value.charAt(0) == '@' ?\n            lookupDottedPath(data, value.substr(1)) : value;\n        });\n        return ids;\n      }\n\n      function defaultResponseInterceptor(response) {\n        return response.resource;\n      }\n\n      function Resource(value){\n        shallowClearAndCopy(value || {}, this);\n      }\n\n      forEach(actions, function(action, name) {\n        var hasBody = /^(POST|PUT|PATCH)$/i.test(action.method);\n\n        Resource[name] = function(a1, a2, a3, a4) {\n          var params = {}, data, success, error;\n\n          /* jshint -W086 */ /* (purposefully fall through case statements) */\n          switch(arguments.length) {\n          case 4:\n            error = a4;\n            success = a3;\n            //fallthrough\n          case 3:\n          case 2:\n            if (isFunction(a2)) {\n              if (isFunction(a1)) {\n                success = a1;\n                error = a2;\n                break;\n              }\n\n              success = a2;\n              error = a3;\n              //fallthrough\n            } else {\n              params = a1;\n              data = a2;\n              success = a3;\n              break;\n            }\n          case 1:\n            if (isFunction(a1)) success = a1;\n            else if (hasBody) data = a1;\n            else params = a1;\n            break;\n          case 0: break;\n          default:\n            throw $resourceMinErr('badargs',\n              \"Expected up to 4 arguments [params, data, success, error], got {0} arguments\",\n              arguments.length);\n          }\n          /* jshint +W086 */ /* (purposefully fall through case statements) */\n\n          var isInstanceCall = this instanceof Resource;\n          var value = isInstanceCall ? data : (action.isArray ? [] : new Resource(data));\n          var httpConfig = {};\n          var responseInterceptor = action.interceptor && action.interceptor.response ||\n                                    defaultResponseInterceptor;\n          var responseErrorInterceptor = action.interceptor && action.interceptor.responseError ||\n                                    undefined;\n\n          forEach(action, function(value, key) {\n            if (key != 'params' && key != 'isArray' && key != 'interceptor') {\n              httpConfig[key] = copy(value);\n            }\n          });\n\n          if (hasBody) httpConfig.data = data;\n          route.setUrlParams(httpConfig,\n                             extend({}, extractParams(data, action.params || {}), params),\n                             action.url);\n\n          var promise = $http(httpConfig).then(function(response) {\n            var data = response.data,\n                promise = value.$promise;\n\n            if (data) {\n              // Need to convert action.isArray to boolean in case it is undefined\n              // jshint -W018\n              if (angular.isArray(data) !== (!!action.isArray)) {\n                throw $resourceMinErr('badcfg', 'Error in resource configuration. Expected ' +\n                  'response to contain an {0} but got an {1}',\n                  action.isArray?'array':'object', angular.isArray(data)?'array':'object');\n              }\n              // jshint +W018\n              if (action.isArray) {\n                value.length = 0;\n                forEach(data, function(item) {\n                  value.push(new Resource(item));\n                });\n              } else {\n                shallowClearAndCopy(data, value);\n                value.$promise = promise;\n              }\n            }\n\n            value.$resolved = true;\n\n            response.resource = value;\n\n            return response;\n          }, function(response) {\n            value.$resolved = true;\n\n            (error||noop)(response);\n\n            return $q.reject(response);\n          });\n\n          promise = promise.then(\n              function(response) {\n                var value = responseInterceptor(response);\n                (success||noop)(value, response.headers);\n                return value;\n              },\n              responseErrorInterceptor);\n\n          if (!isInstanceCall) {\n            // we are creating instance / collection\n            // - set the initial promise\n            // - return the instance / collection\n            value.$promise = promise;\n            value.$resolved = false;\n\n            return value;\n          }\n\n          // instance call\n          return promise;\n        };\n\n\n        Resource.prototype['$' + name] = function(params, success, error) {\n          if (isFunction(params)) {\n            error = success; success = params; params = {};\n          }\n          var result = Resource[name].call(this, params, this, success, error);\n          return result.$promise || result;\n        };\n      });\n\n      Resource.bind = function(additionalParamDefaults){\n        return resourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions);\n      };\n\n      return Resource;\n    }\n\n    return resourceFactory;\n  }]);\n\n\n})(window, window.angular);\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/editor-app/libs/angular-route_1.2.13/angular-route.js",
    "content": "/**\n * @license AngularJS v1.2.13\n * (c) 2010-2014 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {'use strict';\n\n/**\n * @ngdoc overview\n * @name ngRoute\n * @description\n *\n * # ngRoute\n *\n * The `ngRoute` module provides routing and deeplinking services and directives for angular apps.\n *\n * ## Example\n * See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`.\n * \n * {@installModule route}\n *\n * <div doc-module-components=\"ngRoute\"></div>\n */\n /* global -ngRouteModule */\nvar ngRouteModule = angular.module('ngRoute', ['ng']).\n                        provider('$route', $RouteProvider);\n\n/**\n * @ngdoc object\n * @name ngRoute.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes.\n * \n * ## Example\n * See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`.\n *\n * ## Dependencies\n * Requires the {@link ngRoute `ngRoute`} module to be installed.\n */\nfunction $RouteProvider(){\n  function inherit(parent, extra) {\n    return angular.extend(new (angular.extend(function() {}, {prototype:parent}))(), extra);\n  }\n\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ngRoute.$routeProvider#when\n   * @methodOf ngRoute.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *      * `path` can contain named groups starting with a colon: e.g. `:name`. All characters up\n   *        to the next slash are matched and stored in `$routeParams` under the given `name`\n   *        when the route matches.\n   *      * `path` can contain named groups starting with a colon and ending with a star:\n   *        e.g.`:name*`. All characters are eagerly stored in `$routeParams` under the given `name`\n   *        when the route matches.\n   *      * `path` can contain optional named groups with a question mark: e.g.`:name?`.\n   *\n   *    For example, routes like `/color/:color/largecode/:largecode*\\/edit` will match\n   *    `/color/brown/largecode/code/with/slashs/edit` and extract:\n   *\n   *      * `color: brown`\n   *      * `largecode: code/with/slashs`.\n   *\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with\n   *      newly created scope or the name of a {@link angular.Module#controller registered\n   *      controller} if passed as a string.\n   *    - `controllerAs` – `{string=}` – A controller alias name. If present the controller will be\n   *      published to scope under the `controllerAs` name.\n   *    - `template` – `{string=|function()=}` – html template as a string or a function that\n   *      returns an html template as a string which should be used by {@link\n   *      ngRoute.directive:ngView ngView} or {@link ng.directive:ngInclude ngInclude} directives.\n   *      This property takes precedence over `templateUrl`.\n   *\n   *      If `template` is a function, it will be called with the following parameters:\n   *\n   *      - `{Array.<Object>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route\n   *\n   *    - `templateUrl` – `{string=|function()=}` – path or function that returns a path to an html\n   *      template that should be used by {@link ngRoute.directive:ngView ngView}.\n   *\n   *      If `templateUrl` is a function, it will be called with the following parameters:\n   *\n   *      - `{Array.<Object>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route\n   *\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, the router\n   *      will wait for them all to be resolved or one to be rejected before the controller is\n   *      instantiated.\n   *      If all the promises are resolved successfully, the values of the resolved promises are\n   *      injected and {@link ngRoute.$route#$routeChangeSuccess $routeChangeSuccess} event is\n   *      fired. If any of the promises are rejected the\n   *      {@link ngRoute.$route#$routeChangeError $routeChangeError} event is fired. The map object\n   *      is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is\n   *        resolved before its value is injected into the controller. Be aware that\n   *        `ngRoute.$routeParams` will still refer to the previous route within these resolve\n   *        functions.  Use `$route.current.params` to access the new route parameters, instead.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only `$location.search()`\n   *      or `$location.hash()` changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   *    - `[caseInsensitiveMatch=false]` - {boolean=} - match routes without being case sensitive\n   *\n   *      If the option is set to `true`, then the particular route can be matched without being\n   *      case sensitive\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = angular.extend(\n      {reloadOnSearch: true},\n      route,\n      path && pathRegExp(path, route)\n    );\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n            ? path.substr(0, path.length-1)\n            : path +'/';\n\n      routes[redirectPath] = angular.extend(\n        {redirectTo: path},\n        pathRegExp(redirectPath, route)\n      );\n    }\n\n    return this;\n  };\n\n   /**\n    * @param path {string} path\n    * @param opts {Object} options\n    * @return {?Object}\n    *\n    * @description\n    * Normalizes the given path, returning a regular expression\n    * and the original path.\n    *\n    * Inspired by pathRexp in visionmedia/express/lib/utils.js.\n    */\n  function pathRegExp(path, opts) {\n    var insensitive = opts.caseInsensitiveMatch,\n        ret = {\n          originalPath: path,\n          regexp: path\n        },\n        keys = ret.keys = [];\n\n    path = path\n      .replace(/([().])/g, '\\\\$1')\n      .replace(/(\\/)?:(\\w+)([\\?\\*])?/g, function(_, slash, key, option){\n        var optional = option === '?' ? option : null;\n        var star = option === '*' ? option : null;\n        keys.push({ name: key, optional: !!optional });\n        slash = slash || '';\n        return ''\n          + (optional ? '' : slash)\n          + '(?:'\n          + (optional ? slash : '')\n          + (star && '(.+?)' || '([^/]+)')\n          + (optional || '')\n          + ')'\n          + (optional || '');\n      })\n      .replace(/([\\/$\\*])/g, '\\\\$1');\n\n    ret.regexp = new RegExp('^' + path + '$', insensitive ? 'i' : '');\n    return ret;\n  }\n\n  /**\n   * @ngdoc method\n   * @name ngRoute.$routeProvider#otherwise\n   * @methodOf ngRoute.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope',\n               '$location',\n               '$routeParams',\n               '$q',\n               '$injector',\n               '$http',\n               '$templateCache',\n               '$sce',\n      function($rootScope, $location, $routeParams, $q, $injector, $http, $templateCache, $sce) {\n\n    /**\n     * @ngdoc object\n     * @name ngRoute.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * `$route` is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * Requires the {@link ngRoute `ngRoute`} module to be installed.\n     *\n     * You can define routes through {@link ngRoute.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with the\n     * {@link ngRoute.directive:ngView `ngView`} directive and the\n     * {@link ngRoute.$routeParams `$routeParams`} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngViewExample\" deps=\"angular-route.js\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngViewExample', ['ngRoute'])\n\n         .config(function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"protractorTest.js\">\n         it('should load and compile correct template', function() {\n           element(by.linkText('Moby: Ch1')).click();\n           var content = element(by.css('.doc-example-live [ng-view]')).getText();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element(by.partialLinkText('Scarlet')).click();\n\n           content = element(by.css('.doc-example-live [ng-view]')).getText();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ngRoute.$route#$routeChangeStart\n     * @eventOf ngRoute.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occur.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Object} angularEvent Synthetic event object.\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ngRoute.$route#$routeChangeSuccess\n     * @eventOf ngRoute.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ngRoute.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Object} angularEvent Synthetic event object.\n     * @param {Route} current Current route information.\n     * @param {Route|Undefined} previous Previous route information, or undefined if current is\n     * first route entered.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ngRoute.$route#$routeChangeError\n     * @eventOf ngRoute.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Object} angularEvent Synthetic event object\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ngRoute.$route#$routeUpdate\n     * @eventOf ngRoute.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ngRoute.$route#reload\n           * @methodOf ngRoute.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ngRoute.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param route {Object} route regexp to match the url against\n     * @return {?Object}\n     *\n     * @description\n     * Check if the route matches the current url.\n     *\n     * Inspired by match in\n     * visionmedia/express/lib/router/router.js.\n     */\n    function switchRouteMatcher(on, route) {\n      var keys = route.keys,\n          params = {};\n\n      if (!route.regexp) return null;\n\n      var m = route.regexp.exec(on);\n      if (!m) return null;\n\n      for (var i = 1, len = m.length; i < len; ++i) {\n        var key = keys[i - 1];\n\n        var val = 'string' == typeof m[i]\n              ? decodeURIComponent(m[i])\n              : m[i];\n\n        if (key && val) {\n          params[key.name] = val;\n        }\n      }\n      return params;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$$route === last.$$route\n          && angular.equals(next.pathParams, last.pathParams)\n          && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        angular.copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (angular.isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var locals = angular.extend({}, next.resolve),\n                  template, templateUrl;\n\n              angular.forEach(locals, function(value, key) {\n                locals[key] = angular.isString(value) ?\n                    $injector.get(value) : $injector.invoke(value);\n              });\n\n              if (angular.isDefined(template = next.template)) {\n                if (angular.isFunction(template)) {\n                  template = template(next.params);\n                }\n              } else if (angular.isDefined(templateUrl = next.templateUrl)) {\n                if (angular.isFunction(templateUrl)) {\n                  templateUrl = templateUrl(next.params);\n                }\n                templateUrl = $sce.getTrustedResourceUrl(templateUrl);\n                if (angular.isDefined(templateUrl)) {\n                  next.loadedTemplateUrl = templateUrl;\n                  template = $http.get(templateUrl, {cache: $templateCache}).\n                      then(function(response) { return response.data; });\n                }\n              }\n              if (angular.isDefined(template)) {\n                locals['$template'] = template;\n              }\n              return $q.all(locals);\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                angular.copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      angular.forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), route))) {\n          match = inherit(route, {\n            params: angular.extend({}, $location.search(), params),\n            pathParams: params});\n          match.$$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parameters\n     */\n    function interpolate(string, params) {\n      var result = [];\n      angular.forEach((string||'').split(':'), function(segment, i) {\n        if (i === 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\nngRouteModule.provider('$routeParams', $RouteParamsProvider);\n\n\n/**\n * @ngdoc object\n * @name ngRoute.$routeParams\n * @requires $route\n *\n * @description\n * The `$routeParams` service allows you to retrieve the current set of route parameters.\n *\n * Requires the {@link ngRoute `ngRoute`} module to be installed.\n *\n * The route parameters are a combination of {@link ng.$location `$location`}'s\n * {@link ng.$location#methods_search `search()`} and {@link ng.$location#methods_path `path()`}.\n * The `path` parameters are extracted when the {@link ngRoute.$route `$route`} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * Note that the `$routeParams` are only updated *after* a route change completes successfully.\n * This means that you cannot rely on `$routeParams` being correct in route resolve functions.\n * Instead you can use `$route.current.params` to access the new route's parameters.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = function() { return {}; };\n}\n\nngRouteModule.directive('ngView', ngViewFactory);\nngRouteModule.directive('ngView', ngViewFillContentFactory);\n\n\n/**\n * @ngdoc directive\n * @name ngRoute.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ngRoute.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * Requires the {@link ngRoute `ngRoute`} module to be installed.\n *\n * @animations\n * enter - animation is used to bring new content into the browser.\n * leave - animation is used to animate existing content away.\n *\n * The enter and leave animation occur concurrently.\n *\n * @scope\n * @priority 400\n * @param {string=} onload Expression to evaluate whenever the view updates.\n *\n * @param {string=} autoscroll Whether `ngView` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the view is updated.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the `autoscroll` attribute value evaluated\n *                    as an expression yields a truthy value.\n * @example\n    <example module=\"ngViewExample\" deps=\"angular-route.js\" animations=\"true\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl as main\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div class=\"view-animate-container\">\n            <div ng-view class=\"view-animate\"></div>\n          </div>\n          <hr />\n\n          <pre>$location.path() = {{main.$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{main.$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{main.$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{main.$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{main.$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        <div>\n          controller: {{book.name}}<br />\n          Book Id: {{book.params.bookId}}<br />\n        </div>\n      </file>\n\n      <file name=\"chapter.html\">\n        <div>\n          controller: {{chapter.name}}<br />\n          Book Id: {{chapter.params.bookId}}<br />\n          Chapter Id: {{chapter.params.chapterId}}\n        </div>\n      </file>\n\n      <file name=\"animations.css\">\n        .view-animate-container {\n          position:relative;\n          height:100px!important;\n          position:relative;\n          background:white;\n          border:1px solid black;\n          height:40px;\n          overflow:hidden;\n        }\n\n        .view-animate {\n          padding:10px;\n        }\n\n        .view-animate.ng-enter, .view-animate.ng-leave {\n          -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;\n          transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;\n\n          display:block;\n          width:100%;\n          border-left:1px solid black;\n\n          position:absolute;\n          top:0;\n          left:0;\n          right:0;\n          bottom:0;\n          padding:10px;\n        }\n\n        .view-animate.ng-enter {\n          left:100%;\n        }\n        .view-animate.ng-enter.ng-enter-active {\n          left:0;\n        }\n        .view-animate.ng-leave.ng-leave-active {\n          left:-100%;\n        }\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngViewExample', ['ngRoute', 'ngAnimate'],\n          function($routeProvider, $locationProvider) {\n            $routeProvider.when('/Book/:bookId', {\n              templateUrl: 'book.html',\n              controller: BookCntl,\n              controllerAs: 'book'\n            });\n            $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n              templateUrl: 'chapter.html',\n              controller: ChapterCntl,\n              controllerAs: 'chapter'\n            });\n\n            // configure html5 to get links working on jsfiddle\n            $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($route, $routeParams, $location) {\n          this.$route = $route;\n          this.$location = $location;\n          this.$routeParams = $routeParams;\n        }\n\n        function BookCntl($routeParams) {\n          this.name = \"BookCntl\";\n          this.params = $routeParams;\n        }\n\n        function ChapterCntl($routeParams) {\n          this.name = \"ChapterCntl\";\n          this.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"protractorTest.js\">\n        it('should load and compile correct template', function() {\n          element(by.linkText('Moby: Ch1')).click();\n          var content = element(by.css('.doc-example-live [ng-view]')).getText();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element(by.partialLinkText('Scarlet')).click();\n\n          content = element(by.css('.doc-example-live [ng-view]')).getText();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ngRoute.directive:ngView#$viewContentLoaded\n * @eventOf ngRoute.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nngViewFactory.$inject = ['$route', '$anchorScroll', '$animate'];\nfunction ngViewFactory(   $route,   $anchorScroll,   $animate) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    priority: 400,\n    transclude: 'element',\n    link: function(scope, $element, attr, ctrl, $transclude) {\n        var currentScope,\n            currentElement,\n            autoScrollExp = attr.autoscroll,\n            onloadExp = attr.onload || '';\n\n        scope.$on('$routeChangeSuccess', update);\n        update();\n\n        function cleanupLastView() {\n          if (currentScope) {\n            currentScope.$destroy();\n            currentScope = null;\n          }\n          if(currentElement) {\n            $animate.leave(currentElement);\n            currentElement = null;\n          }\n        }\n\n        function update() {\n          var locals = $route.current && $route.current.locals,\n              template = locals && locals.$template;\n\n          if (angular.isDefined(template)) {\n            var newScope = scope.$new();\n            var current = $route.current;\n\n            // Note: This will also link all children of ng-view that were contained in the original\n            // html. If that content contains controllers, ... they could pollute/change the scope.\n            // However, using ng-view on an element with additional content does not make sense...\n            // Note: We can't remove them in the cloneAttchFn of $transclude as that\n            // function is called before linking the content, which would apply child\n            // directives to non existing elements.\n            var clone = $transclude(newScope, function(clone) {\n              $animate.enter(clone, null, currentElement || $element, function onNgViewEnter () {\n                if (angular.isDefined(autoScrollExp)\n                  && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                  $anchorScroll();\n                }\n              });\n              cleanupLastView();\n            });\n\n            currentElement = clone;\n            currentScope = current.scope = newScope;\n            currentScope.$emit('$viewContentLoaded');\n            currentScope.$eval(onloadExp);\n          } else {\n            cleanupLastView();\n          }\n        }\n    }\n  };\n}\n\n// This directive is called during the $transclude call of the first `ngView` directive.\n// It will replace and compile the content of the element with the loaded template.\n// We need this directive so that the element content is already filled when\n// the link function of another directive on the same element as ngView\n// is called.\nngViewFillContentFactory.$inject = ['$compile', '$controller', '$route'];\nfunction ngViewFillContentFactory($compile, $controller, $route) {\n  return {\n    restrict: 'ECA',\n    priority: -400,\n    link: function(scope, $element) {\n      var current = $route.current,\n          locals = current.locals;\n\n      $element.html(locals.$template);\n\n      var link = $compile($element.contents());\n\n      if (current.controller) {\n        locals.$scope = scope;\n        var controller = $controller(current.controller, locals);\n        if (current.controllerAs) {\n          scope[current.controllerAs] = controller;\n        }\n        $element.data('$ngControllerController', controller);\n        $element.children().data('$ngControllerController', controller);\n      }\n\n      link(scope);\n    }\n  };\n}\n\n\n})(window, window.angular);\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/editor-app/libs/angular-sanitize_1.2.13/angular-sanitize.js",
    "content": "/**\n * @license AngularJS v1.2.13\n * (c) 2010-2014 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {'use strict';\n\nvar $sanitizeMinErr = angular.$$minErr('$sanitize');\n\n/**\n * @ngdoc overview\n * @name ngSanitize\n * @description\n *\n * # ngSanitize\n *\n * The `ngSanitize` module provides functionality to sanitize HTML.\n *\n * {@installModule sanitize}\n *\n * <div doc-module-components=\"ngSanitize\"></div>\n *\n * See {@link ngSanitize.$sanitize `$sanitize`} for usage.\n */\n\n/*\n * HTML Parser By Misko Hevery (misko@hevery.com)\n * based on:  HTML Parser By John Resig (ejohn.org)\n * Original code by Erik Arvidsson, Mozilla Public License\n * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js\n *\n * // Use like so:\n * htmlParser(htmlString, {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * });\n *\n */\n\n\n/**\n * @ngdoc service\n * @name ngSanitize.$sanitize\n * @function\n *\n * @description\n *   The input is sanitized by parsing the html into tokens. All safe tokens (from a whitelist) are\n *   then serialized back to properly escaped html string. This means that no unsafe input can make\n *   it into the returned string, however, since our parser is more strict than a typical browser\n *   parser, it's possible that some obscure input, which would be recognized as valid HTML by a\n *   browser, won't make it through the sanitizer.\n *   The whitelist is configured using the functions `aHrefSanitizationWhitelist` and\n *   `imgSrcSanitizationWhitelist` of {@link ng.$compileProvider `$compileProvider`}.\n *\n * @param {string} html Html input.\n * @returns {string} Sanitized html.\n *\n * @example\n   <doc:example module=\"ngSanitize\">\n   <doc:source>\n     <script>\n       function Ctrl($scope, $sce) {\n         $scope.snippet =\n           '<p style=\"color:blue\">an html\\n' +\n           '<em onmouseover=\"this.textContent=\\'PWN3D!\\'\">click here</em>\\n' +\n           'snippet</p>';\n         $scope.deliberatelyTrustDangerousSnippet = function() {\n           return $sce.trustAsHtml($scope.snippet);\n         };\n       }\n     </script>\n     <div ng-controller=\"Ctrl\">\n        Snippet: <textarea ng-model=\"snippet\" cols=\"60\" rows=\"3\"></textarea>\n       <table>\n         <tr>\n           <td>Directive</td>\n           <td>How</td>\n           <td>Source</td>\n           <td>Rendered</td>\n         </tr>\n         <tr id=\"bind-html-with-sanitize\">\n           <td>ng-bind-html</td>\n           <td>Automatically uses $sanitize</td>\n           <td><pre>&lt;div ng-bind-html=\"snippet\"&gt;<br/>&lt;/div&gt;</pre></td>\n           <td><div ng-bind-html=\"snippet\"></div></td>\n         </tr>\n         <tr id=\"bind-html-with-trust\">\n           <td>ng-bind-html</td>\n           <td>Bypass $sanitize by explicitly trusting the dangerous value</td>\n           <td>\n           <pre>&lt;div ng-bind-html=\"deliberatelyTrustDangerousSnippet()\"&gt;\n&lt;/div&gt;</pre>\n           </td>\n           <td><div ng-bind-html=\"deliberatelyTrustDangerousSnippet()\"></div></td>\n         </tr>\n         <tr id=\"bind-default\">\n           <td>ng-bind</td>\n           <td>Automatically escapes</td>\n           <td><pre>&lt;div ng-bind=\"snippet\"&gt;<br/>&lt;/div&gt;</pre></td>\n           <td><div ng-bind=\"snippet\"></div></td>\n         </tr>\n       </table>\n       </div>\n   </doc:source>\n   <doc:protractor>\n     it('should sanitize the html snippet by default', function() {\n       expect(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()).\n         toBe('<p>an html\\n<em>click here</em>\\nsnippet</p>');\n     });\n\n     it('should inline raw snippet if bound to a trusted value', function() {\n       expect(element(by.css('#bind-html-with-trust div')).getInnerHtml()).\n         toBe(\"<p style=\\\"color:blue\\\">an html\\n\" +\n              \"<em onmouseover=\\\"this.textContent='PWN3D!'\\\">click here</em>\\n\" +\n              \"snippet</p>\");\n     });\n\n     it('should escape snippet without any filter', function() {\n       expect(element(by.css('#bind-default div')).getInnerHtml()).\n         toBe(\"&lt;p style=\\\"color:blue\\\"&gt;an html\\n\" +\n              \"&lt;em onmouseover=\\\"this.textContent='PWN3D!'\\\"&gt;click here&lt;/em&gt;\\n\" +\n              \"snippet&lt;/p&gt;\");\n     });\n\n     it('should update', function() {\n       element(by.model('snippet')).clear();\n       element(by.model('snippet')).sendKeys('new <b onclick=\"alert(1)\">text</b>');\n       expect(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()).\n         toBe('new <b>text</b>');\n       expect(element(by.css('#bind-html-with-trust div')).getInnerHtml()).toBe(\n         'new <b onclick=\"alert(1)\">text</b>');\n       expect(element(by.css('#bind-default div')).getInnerHtml()).toBe(\n         \"new &lt;b onclick=\\\"alert(1)\\\"&gt;text&lt;/b&gt;\");\n     });\n   </doc:protractor>\n   </doc:example>\n */\nfunction $SanitizeProvider() {\n  this.$get = ['$$sanitizeUri', function($$sanitizeUri) {\n    return function(html) {\n      var buf = [];\n      htmlParser(html, htmlSanitizeWriter(buf, function(uri, isImage) {\n        return !/^unsafe/.test($$sanitizeUri(uri, isImage));\n      }));\n      return buf.join('');\n    };\n  }];\n}\n\nfunction sanitizeText(chars) {\n  var buf = [];\n  var writer = htmlSanitizeWriter(buf, angular.noop);\n  writer.chars(chars);\n  return buf.join('');\n}\n\n\n// Regular Expressions for parsing tags and attributes\nvar START_TAG_REGEXP =\n       /^<\\s*([\\w:-]+)((?:\\s+[\\w:-]+(?:\\s*=\\s*(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>\\s]+))?)*)\\s*(\\/?)\\s*>/,\n  END_TAG_REGEXP = /^<\\s*\\/\\s*([\\w:-]+)[^>]*>/,\n  ATTR_REGEXP = /([\\w:-]+)(?:\\s*=\\s*(?:(?:\"((?:[^\"])*)\")|(?:'((?:[^'])*)')|([^>\\s]+)))?/g,\n  BEGIN_TAG_REGEXP = /^</,\n  BEGING_END_TAGE_REGEXP = /^<\\s*\\//,\n  COMMENT_REGEXP = /<!--(.*?)-->/g,\n  DOCTYPE_REGEXP = /<!DOCTYPE([^>]*?)>/i,\n  CDATA_REGEXP = /<!\\[CDATA\\[(.*?)]]>/g,\n  // Match everything outside of normal chars and \" (quote character)\n  NON_ALPHANUMERIC_REGEXP = /([^\\#-~| |!])/g;\n\n\n// Good source of info about elements and attributes\n// http://dev.w3.org/html5/spec/Overview.html#semantics\n// http://simon.html5.org/html-elements\n\n// Safe Void Elements - HTML5\n// http://dev.w3.org/html5/spec/Overview.html#void-elements\nvar voidElements = makeMap(\"area,br,col,hr,img,wbr\");\n\n// Elements that you can, intentionally, leave open (and which close themselves)\n// http://dev.w3.org/html5/spec/Overview.html#optional-tags\nvar optionalEndTagBlockElements = makeMap(\"colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr\"),\n    optionalEndTagInlineElements = makeMap(\"rp,rt\"),\n    optionalEndTagElements = angular.extend({},\n                                            optionalEndTagInlineElements,\n                                            optionalEndTagBlockElements);\n\n// Safe Block Elements - HTML5\nvar blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap(\"address,article,\" +\n        \"aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,\" +\n        \"h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul\"));\n\n// Inline Elements - HTML5\nvar inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap(\"a,abbr,acronym,b,\" +\n        \"bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,\" +\n        \"samp,small,span,strike,strong,sub,sup,time,tt,u,var\"));\n\n\n// Special Elements (can contain anything)\nvar specialElements = makeMap(\"script,style\");\n\nvar validElements = angular.extend({},\n                                   voidElements,\n                                   blockElements,\n                                   inlineElements,\n                                   optionalEndTagElements);\n\n//Attributes that have href and hence need to be sanitized\nvar uriAttrs = makeMap(\"background,cite,href,longdesc,src,usemap\");\nvar validAttrs = angular.extend({}, uriAttrs, makeMap(\n    'abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'+\n    'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,'+\n    'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,'+\n    'scope,scrolling,shape,size,span,start,summary,target,title,type,'+\n    'valign,value,vspace,width'));\n\nfunction makeMap(str) {\n  var obj = {}, items = str.split(','), i;\n  for (i = 0; i < items.length; i++) obj[items[i]] = true;\n  return obj;\n}\n\n\n/**\n * @example\n * htmlParser(htmlString, {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * });\n *\n * @param {string} html string\n * @param {object} handler\n */\nfunction htmlParser( html, handler ) {\n  var index, chars, match, stack = [], last = html;\n  stack.last = function() { return stack[ stack.length - 1 ]; };\n\n  while ( html ) {\n    chars = true;\n\n    // Make sure we're not in a script or style element\n    if ( !stack.last() || !specialElements[ stack.last() ] ) {\n\n      // Comment\n      if ( html.indexOf(\"<!--\") === 0 ) {\n        // comments containing -- are not allowed unless they terminate the comment\n        index = html.indexOf(\"--\", 4);\n\n        if ( index >= 0 && html.lastIndexOf(\"-->\", index) === index) {\n          if (handler.comment) handler.comment( html.substring( 4, index ) );\n          html = html.substring( index + 3 );\n          chars = false;\n        }\n      // DOCTYPE\n      } else if ( DOCTYPE_REGEXP.test(html) ) {\n        match = html.match( DOCTYPE_REGEXP );\n\n        if ( match ) {\n          html = html.replace( match[0] , '');\n          chars = false;\n        }\n      // end tag\n      } else if ( BEGING_END_TAGE_REGEXP.test(html) ) {\n        match = html.match( END_TAG_REGEXP );\n\n        if ( match ) {\n          html = html.substring( match[0].length );\n          match[0].replace( END_TAG_REGEXP, parseEndTag );\n          chars = false;\n        }\n\n      // start tag\n      } else if ( BEGIN_TAG_REGEXP.test(html) ) {\n        match = html.match( START_TAG_REGEXP );\n\n        if ( match ) {\n          html = html.substring( match[0].length );\n          match[0].replace( START_TAG_REGEXP, parseStartTag );\n          chars = false;\n        }\n      }\n\n      if ( chars ) {\n        index = html.indexOf(\"<\");\n\n        var text = index < 0 ? html : html.substring( 0, index );\n        html = index < 0 ? \"\" : html.substring( index );\n\n        if (handler.chars) handler.chars( decodeEntities(text) );\n      }\n\n    } else {\n      html = html.replace(new RegExp(\"(.*)<\\\\s*\\\\/\\\\s*\" + stack.last() + \"[^>]*>\", 'i'),\n        function(all, text){\n          text = text.replace(COMMENT_REGEXP, \"$1\").replace(CDATA_REGEXP, \"$1\");\n\n          if (handler.chars) handler.chars( decodeEntities(text) );\n\n          return \"\";\n      });\n\n      parseEndTag( \"\", stack.last() );\n    }\n\n    if ( html == last ) {\n      throw $sanitizeMinErr('badparse', \"The sanitizer was unable to parse the following block \" +\n                                        \"of html: {0}\", html);\n    }\n    last = html;\n  }\n\n  // Clean up any remaining tags\n  parseEndTag();\n\n  function parseStartTag( tag, tagName, rest, unary ) {\n    tagName = angular.lowercase(tagName);\n    if ( blockElements[ tagName ] ) {\n      while ( stack.last() && inlineElements[ stack.last() ] ) {\n        parseEndTag( \"\", stack.last() );\n      }\n    }\n\n    if ( optionalEndTagElements[ tagName ] && stack.last() == tagName ) {\n      parseEndTag( \"\", tagName );\n    }\n\n    unary = voidElements[ tagName ] || !!unary;\n\n    if ( !unary )\n      stack.push( tagName );\n\n    var attrs = {};\n\n    rest.replace(ATTR_REGEXP,\n      function(match, name, doubleQuotedValue, singleQuotedValue, unquotedValue) {\n        var value = doubleQuotedValue\n          || singleQuotedValue\n          || unquotedValue\n          || '';\n\n        attrs[name] = decodeEntities(value);\n    });\n    if (handler.start) handler.start( tagName, attrs, unary );\n  }\n\n  function parseEndTag( tag, tagName ) {\n    var pos = 0, i;\n    tagName = angular.lowercase(tagName);\n    if ( tagName )\n      // Find the closest opened tag of the same type\n      for ( pos = stack.length - 1; pos >= 0; pos-- )\n        if ( stack[ pos ] == tagName )\n          break;\n\n    if ( pos >= 0 ) {\n      // Close all the open elements, up the stack\n      for ( i = stack.length - 1; i >= pos; i-- )\n        if (handler.end) handler.end( stack[ i ] );\n\n      // Remove the open elements from the stack\n      stack.length = pos;\n    }\n  }\n}\n\nvar hiddenPre=document.createElement(\"pre\");\nvar spaceRe = /^(\\s*)([\\s\\S]*?)(\\s*)$/;\n/**\n * decodes all entities into regular string\n * @param value\n * @returns {string} A string with decoded entities.\n */\nfunction decodeEntities(value) {\n  if (!value) { return ''; }\n\n  // Note: IE8 does not preserve spaces at the start/end of innerHTML\n  // so we must capture them and reattach them afterward\n  var parts = spaceRe.exec(value);\n  var spaceBefore = parts[1];\n  var spaceAfter = parts[3];\n  var content = parts[2];\n  if (content) {\n    hiddenPre.innerHTML=content.replace(/</g,\"&lt;\");\n    // innerText depends on styling as it doesn't display hidden elements.\n    // Therefore, it's better to use textContent not to cause unnecessary\n    // reflows. However, IE<9 don't support textContent so the innerText\n    // fallback is necessary.\n    content = 'textContent' in hiddenPre ?\n      hiddenPre.textContent : hiddenPre.innerText;\n  }\n  return spaceBefore + content + spaceAfter;\n}\n\n/**\n * Escapes all potentially dangerous characters, so that the\n * resulting string can be safely inserted into attribute or\n * element text.\n * @param value\n * @returns escaped text\n */\nfunction encodeEntities(value) {\n  return value.\n    replace(/&/g, '&amp;').\n    replace(NON_ALPHANUMERIC_REGEXP, function(value){\n      return '&#' + value.charCodeAt(0) + ';';\n    }).\n    replace(/</g, '&lt;').\n    replace(/>/g, '&gt;');\n}\n\n/**\n * create an HTML/XML writer which writes to buffer\n * @param {Array} buf use buf.jain('') to get out sanitized html string\n * @returns {object} in the form of {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * }\n */\nfunction htmlSanitizeWriter(buf, uriValidator){\n  var ignore = false;\n  var out = angular.bind(buf, buf.push);\n  return {\n    start: function(tag, attrs, unary){\n      tag = angular.lowercase(tag);\n      if (!ignore && specialElements[tag]) {\n        ignore = tag;\n      }\n      if (!ignore && validElements[tag] === true) {\n        out('<');\n        out(tag);\n        angular.forEach(attrs, function(value, key){\n          var lkey=angular.lowercase(key);\n          var isImage = (tag === 'img' && lkey === 'src') || (lkey === 'background');\n          if (validAttrs[lkey] === true &&\n            (uriAttrs[lkey] !== true || uriValidator(value, isImage))) {\n            out(' ');\n            out(key);\n            out('=\"');\n            out(encodeEntities(value));\n            out('\"');\n          }\n        });\n        out(unary ? '/>' : '>');\n      }\n    },\n    end: function(tag){\n        tag = angular.lowercase(tag);\n        if (!ignore && validElements[tag] === true) {\n          out('</');\n          out(tag);\n          out('>');\n        }\n        if (tag == ignore) {\n          ignore = false;\n        }\n      },\n    chars: function(chars){\n        if (!ignore) {\n          out(encodeEntities(chars));\n        }\n      }\n  };\n}\n\n\n// define ngSanitize module and register $sanitize service\nangular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider);\n\n/* global sanitizeText: false */\n\n/**\n * @ngdoc filter\n * @name ngSanitize.filter:linky\n * @function\n *\n * @description\n * Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and\n * plain email address links.\n *\n * Requires the {@link ngSanitize `ngSanitize`} module to be installed.\n *\n * @param {string} text Input text.\n * @param {string} target Window (_blank|_self|_parent|_top) or named frame to open links in.\n * @returns {string} Html-linkified text.\n *\n * @usage\n   <span ng-bind-html=\"linky_expression | linky\"></span>\n *\n * @example\n   <doc:example module=\"ngSanitize\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.snippet =\n             'Pretty text with some links:\\n'+\n             'http://angularjs.org/,\\n'+\n             'mailto:us@somewhere.org,\\n'+\n             'another@somewhere.org,\\n'+\n             'and one more: ftp://127.0.0.1/.';\n           $scope.snippetWithTarget = 'http://angularjs.org/';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n       Snippet: <textarea ng-model=\"snippet\" cols=\"60\" rows=\"3\"></textarea>\n       <table>\n         <tr>\n           <td>Filter</td>\n           <td>Source</td>\n           <td>Rendered</td>\n         </tr>\n         <tr id=\"linky-filter\">\n           <td>linky filter</td>\n           <td>\n             <pre>&lt;div ng-bind-html=\"snippet | linky\"&gt;<br>&lt;/div&gt;</pre>\n           </td>\n           <td>\n             <div ng-bind-html=\"snippet | linky\"></div>\n           </td>\n         </tr>\n         <tr id=\"linky-target\">\n          <td>linky target</td>\n          <td>\n            <pre>&lt;div ng-bind-html=\"snippetWithTarget | linky:'_blank'\"&gt;<br>&lt;/div&gt;</pre>\n          </td>\n          <td>\n            <div ng-bind-html=\"snippetWithTarget | linky:'_blank'\"></div>\n          </td>\n         </tr>\n         <tr id=\"escaped-html\">\n           <td>no filter</td>\n           <td><pre>&lt;div ng-bind=\"snippet\"&gt;<br>&lt;/div&gt;</pre></td>\n           <td><div ng-bind=\"snippet\"></div></td>\n         </tr>\n       </table>\n     </doc:source>\n     <doc:protractor>\n       it('should linkify the snippet with urls', function() {\n         expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()).\n             toBe('Pretty text with some links: http://angularjs.org/, us@somewhere.org, ' +\n                  'another@somewhere.org, and one more: ftp://127.0.0.1/.');\n         expect(element.all(by.css('#linky-filter a')).count()).toEqual(4);\n       });\n\n       it('should not linkify snippet without the linky filter', function() {\n         expect(element(by.id('escaped-html')).element(by.binding('snippet')).getText()).\n             toBe('Pretty text with some links: http://angularjs.org/, mailto:us@somewhere.org, ' +\n                  'another@somewhere.org, and one more: ftp://127.0.0.1/.');\n         expect(element.all(by.css('#escaped-html a')).count()).toEqual(0);\n       });\n\n       it('should update', function() {\n         element(by.model('snippet')).clear();\n         element(by.model('snippet')).sendKeys('new http://link.');\n         expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()).\n             toBe('new http://link.');\n         expect(element.all(by.css('#linky-filter a')).count()).toEqual(1);\n         expect(element(by.id('escaped-html')).element(by.binding('snippet')).getText())\n             .toBe('new http://link.');\n       });\n\n       it('should work with the target property', function() {\n        expect(element(by.id('linky-target')).\n            element(by.binding(\"snippetWithTarget | linky:'_blank'\")).getText()).\n            toBe('http://angularjs.org/');\n        expect(element(by.css('#linky-target a')).getAttribute('target')).toEqual('_blank');\n       });\n     </doc:protractor>\n   </doc:example>\n */\nangular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) {\n  var LINKY_URL_REGEXP =\n        /((ftp|https?):\\/\\/|(mailto:)?[A-Za-z0-9._%+-]+@)\\S*[^\\s.;,(){}<>]/,\n      MAILTO_REGEXP = /^mailto:/;\n\n  return function(text, target) {\n    if (!text) return text;\n    var match;\n    var raw = text;\n    var html = [];\n    var url;\n    var i;\n    while ((match = raw.match(LINKY_URL_REGEXP))) {\n      // We can not end in these as they are sometimes found at the end of the sentence\n      url = match[0];\n      // if we did not match ftp/http/mailto then assume mailto\n      if (match[2] == match[3]) url = 'mailto:' + url;\n      i = match.index;\n      addText(raw.substr(0, i));\n      addLink(url, match[0].replace(MAILTO_REGEXP, ''));\n      raw = raw.substring(i + match[0].length);\n    }\n    addText(raw);\n    return $sanitize(html.join(''));\n\n    function addText(text) {\n      if (!text) {\n        return;\n      }\n      html.push(sanitizeText(text));\n    }\n\n    function addLink(url, text) {\n      html.push('<a ');\n      if (angular.isDefined(target)) {\n        html.push('target=\"');\n        html.push(target);\n        html.push('\" ');\n      }\n      html.push('href=\"');\n      html.push(url);\n      html.push('\">');\n      addText(text);\n      html.push('</a>');\n    }\n  };\n}]);\n\n\n})(window, window.angular);\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/editor-app/libs/angular-translate-loader-static-files/.bower.json",
    "content": "{\n  \"name\": \"angular-translate-loader-static-files\",\n  \"version\": \"0.1.6\",\n  \"main\": \"./angular-translate-loader-static-files.js\",\n  \"dependencies\": {\n    \"angular\": \"1.0.8\",\n    \"angular-translate\": \"~1.1.1\"\n  },\n  \"homepage\": \"https://github.com/PascalPrecht/bower-angular-translate-loader-static-files\",\n  \"_release\": \"0.1.6\",\n  \"_resolution\": {\n    \"type\": \"version\",\n    \"tag\": \"0.1.6\",\n    \"commit\": \"eaac546d29d6cde45873e6bad9d18cdff071d983\"\n  },\n  \"_source\": \"git://github.com/PascalPrecht/bower-angular-translate-loader-static-files.git\",\n  \"_target\": \"0.1.6\",\n  \"_originalSource\": \"angular-translate-loader-static-files\"\n}"
  },
  {
    "path": "open-layui-web/src/main/view/static/editor-app/libs/angular-translate-loader-static-files/angular-translate-loader-static-files.js",
    "content": "/*!\n * angular-translate - v2.4.2 - 2014-10-21\n * http://github.com/angular-translate/angular-translate\n * Copyright (c) 2014 ; Licensed MIT\n */\nangular.module('pascalprecht.translate').factory('$translateStaticFilesLoader', [\n  '$q',\n  '$http',\n  function ($q, $http) {\n    return function (options) {\n      if (!options || (!angular.isString(options.prefix) || !angular.isString(options.suffix))) {\n        throw new Error('Couldn\\'t load static files, no prefix or suffix specified!');\n      }\n      var deferred = $q.defer();\n      $http(angular.extend({\n        url: [\n          options.prefix,\n          options.key,\n          options.suffix\n        ].join(''),\n        method: 'GET',\n        params: ''\n      }, options.$http)).success(function (data) {\n        deferred.resolve(data);\n      }).error(function (data) {\n        deferred.reject(options.key);\n      });\n      return deferred.promise;\n    };\n  }\n]);"
  },
  {
    "path": "open-layui-web/src/main/view/static/editor-app/libs/angular-translate-storage-cookie/.bower.json",
    "content": "{\n  \"name\": \"angular-translate-storage-cookie\",\n  \"version\": \"0.1.6\",\n  \"main\": \"./angular-translate-storage-cookie.js\",\n  \"dependencies\": {\n    \"angular\": \"1.0.8\",\n    \"angular-cookies\": \"1.0.8\",\n    \"angular-translate\": \"~1.1.1\"\n  },\n  \"homepage\": \"https://github.com/PascalPrecht/bower-angular-translate-storage-cookie\",\n  \"_release\": \"0.1.6\",\n  \"_resolution\": {\n    \"type\": \"version\",\n    \"tag\": \"0.1.6\",\n    \"commit\": \"fc9ea3275f0f9bf0a60ca073b58488d934a348ac\"\n  },\n  \"_source\": \"git://github.com/PascalPrecht/bower-angular-translate-storage-cookie.git\",\n  \"_target\": \"0.1.6\",\n  \"_originalSource\": \"angular-translate-storage-cookie\"\n}"
  },
  {
    "path": "open-layui-web/src/main/view/static/editor-app/libs/angular-translate-storage-cookie/angular-translate-storage-cookie.js",
    "content": "/*!\n * angular-translate - v2.4.2 - 2014-10-21\n * http://github.com/angular-translate/angular-translate\n * Copyright (c) 2014 ; Licensed MIT\n */\nangular.module('pascalprecht.translate').factory('$translateCookieStorage', [\n  '$cookieStore',\n  function ($cookieStore) {\n    var $translateCookieStorage = {\n        get: function (name) {\n          return $cookieStore.get(name);\n        },\n        set: function (name, value) {\n          $cookieStore.put(name, value);\n        }\n      };\n    return $translateCookieStorage;\n  }\n]);"
  },
  {
    "path": "open-layui-web/src/main/view/static/editor-app/libs/angular-translate_2.4.2/angular-translate.js",
    "content": "/*!\n * angular-translate - v2.4.2 - 2014-10-21\n * http://github.com/angular-translate/angular-translate\n * Copyright (c) 2014 ; Licensed MIT\n */\nangular.module('pascalprecht.translate', ['ng']).run([\n  '$translate',\n  function ($translate) {\n    var key = $translate.storageKey(), storage = $translate.storage();\n    if (storage) {\n      if (!storage.get(key)) {\n        if (angular.isString($translate.preferredLanguage())) {\n          $translate.use($translate.preferredLanguage());\n        } else {\n          storage.set(key, $translate.use());\n        }\n      } else {\n        $translate.use(storage.get(key));\n      }\n    } else if (angular.isString($translate.preferredLanguage())) {\n      $translate.use($translate.preferredLanguage());\n    }\n  }\n]);\nangular.module('pascalprecht.translate').provider('$translate', [\n  '$STORAGE_KEY',\n  function ($STORAGE_KEY) {\n    var $translationTable = {}, $preferredLanguage, $availableLanguageKeys = [], $languageKeyAliases, $fallbackLanguage, $fallbackWasString, $uses, $nextLang, $storageFactory, $storageKey = $STORAGE_KEY, $storagePrefix, $missingTranslationHandlerFactory, $interpolationFactory, $interpolatorFactories = [], $interpolationSanitizationStrategy = false, $loaderFactory, $cloakClassName = 'translate-cloak', $loaderOptions, $notFoundIndicatorLeft, $notFoundIndicatorRight, $postCompilingEnabled = false, NESTED_OBJECT_DELIMITER = '.', loaderCache;\n    var version = '2.4.2';\n    var getLocale = function () {\n      var nav = window.navigator;\n      return ((angular.isArray(nav.languages) ? nav.languages[0] : nav.language || nav.browserLanguage || nav.systemLanguage || nav.userLanguage) || '').split('-').join('_');\n    };\n    var indexOf = function (array, searchElement) {\n      for (var i = 0, len = array.length; i < len; i++) {\n        if (array[i] === searchElement) {\n          return i;\n        }\n      }\n      return -1;\n    };\n    var trim = function () {\n      return this.replace(/^\\s+|\\s+$/g, '');\n    };\n    var negotiateLocale = function (preferred) {\n      var avail = [], locale = angular.lowercase(preferred), i = 0, n = $availableLanguageKeys.length;\n      for (; i < n; i++) {\n        avail.push(angular.lowercase($availableLanguageKeys[i]));\n      }\n      if (indexOf(avail, locale) > -1) {\n        return preferred;\n      }\n      if ($languageKeyAliases) {\n        var alias;\n        for (var langKeyAlias in $languageKeyAliases) {\n          var hasWildcardKey = false;\n          var hasExactKey = Object.prototype.hasOwnProperty.call($languageKeyAliases, langKeyAlias) && angular.lowercase(langKeyAlias) === angular.lowercase(preferred);\n          if (langKeyAlias.slice(-1) === '*') {\n            hasWildcardKey = langKeyAlias.slice(0, -1) === preferred.slice(0, langKeyAlias.length - 1);\n          }\n          if (hasExactKey || hasWildcardKey) {\n            alias = $languageKeyAliases[langKeyAlias];\n            if (indexOf(avail, angular.lowercase(alias)) > -1) {\n              return alias;\n            }\n          }\n        }\n      }\n      var parts = preferred.split('_');\n      if (parts.length > 1 && indexOf(avail, angular.lowercase(parts[0])) > -1) {\n        return parts[0];\n      }\n      return preferred;\n    };\n    var translations = function (langKey, translationTable) {\n      if (!langKey && !translationTable) {\n        return $translationTable;\n      }\n      if (langKey && !translationTable) {\n        if (angular.isString(langKey)) {\n          return $translationTable[langKey];\n        }\n      } else {\n        if (!angular.isObject($translationTable[langKey])) {\n          $translationTable[langKey] = {};\n        }\n        angular.extend($translationTable[langKey], flatObject(translationTable));\n      }\n      return this;\n    };\n    this.translations = translations;\n    this.cloakClassName = function (name) {\n      if (!name) {\n        return $cloakClassName;\n      }\n      $cloakClassName = name;\n      return this;\n    };\n    var flatObject = function (data, path, result, prevKey) {\n      var key, keyWithPath, keyWithShortPath, val;\n      if (!path) {\n        path = [];\n      }\n      if (!result) {\n        result = {};\n      }\n      for (key in data) {\n        if (!Object.prototype.hasOwnProperty.call(data, key)) {\n          continue;\n        }\n        val = data[key];\n        if (angular.isObject(val)) {\n          flatObject(val, path.concat(key), result, key);\n        } else {\n          keyWithPath = path.length ? '' + path.join(NESTED_OBJECT_DELIMITER) + NESTED_OBJECT_DELIMITER + key : key;\n          if (path.length && key === prevKey) {\n            keyWithShortPath = '' + path.join(NESTED_OBJECT_DELIMITER);\n            result[keyWithShortPath] = '@:' + keyWithPath;\n          }\n          result[keyWithPath] = val;\n        }\n      }\n      return result;\n    };\n    this.addInterpolation = function (factory) {\n      $interpolatorFactories.push(factory);\n      return this;\n    };\n    this.useMessageFormatInterpolation = function () {\n      return this.useInterpolation('$translateMessageFormatInterpolation');\n    };\n    this.useInterpolation = function (factory) {\n      $interpolationFactory = factory;\n      return this;\n    };\n    this.useSanitizeValueStrategy = function (value) {\n      $interpolationSanitizationStrategy = value;\n      return this;\n    };\n    this.preferredLanguage = function (langKey) {\n      setupPreferredLanguage(langKey);\n      return this;\n    };\n    var setupPreferredLanguage = function (langKey) {\n      if (langKey) {\n        $preferredLanguage = langKey;\n      }\n      return $preferredLanguage;\n    };\n    this.translationNotFoundIndicator = function (indicator) {\n      this.translationNotFoundIndicatorLeft(indicator);\n      this.translationNotFoundIndicatorRight(indicator);\n      return this;\n    };\n    this.translationNotFoundIndicatorLeft = function (indicator) {\n      if (!indicator) {\n        return $notFoundIndicatorLeft;\n      }\n      $notFoundIndicatorLeft = indicator;\n      return this;\n    };\n    this.translationNotFoundIndicatorRight = function (indicator) {\n      if (!indicator) {\n        return $notFoundIndicatorRight;\n      }\n      $notFoundIndicatorRight = indicator;\n      return this;\n    };\n    this.fallbackLanguage = function (langKey) {\n      fallbackStack(langKey);\n      return this;\n    };\n    var fallbackStack = function (langKey) {\n      if (langKey) {\n        if (angular.isString(langKey)) {\n          $fallbackWasString = true;\n          $fallbackLanguage = [langKey];\n        } else if (angular.isArray(langKey)) {\n          $fallbackWasString = false;\n          $fallbackLanguage = langKey;\n        }\n        if (angular.isString($preferredLanguage) && indexOf($fallbackLanguage, $preferredLanguage) < 0) {\n          $fallbackLanguage.push($preferredLanguage);\n        }\n        return this;\n      } else {\n        if ($fallbackWasString) {\n          return $fallbackLanguage[0];\n        } else {\n          return $fallbackLanguage;\n        }\n      }\n    };\n    this.use = function (langKey) {\n      if (langKey) {\n        if (!$translationTable[langKey] && !$loaderFactory) {\n          throw new Error('$translateProvider couldn\\'t find translationTable for langKey: \\'' + langKey + '\\'');\n        }\n        $uses = langKey;\n        return this;\n      }\n      return $uses;\n    };\n    var storageKey = function (key) {\n      if (!key) {\n        if ($storagePrefix) {\n          return $storagePrefix + $storageKey;\n        }\n        return $storageKey;\n      }\n      $storageKey = key;\n    };\n    this.storageKey = storageKey;\n    this.useUrlLoader = function (url, options) {\n      return this.useLoader('$translateUrlLoader', angular.extend({ url: url }, options));\n    };\n    this.useStaticFilesLoader = function (options) {\n      return this.useLoader('$translateStaticFilesLoader', options);\n    };\n    this.useLoader = function (loaderFactory, options) {\n      $loaderFactory = loaderFactory;\n      $loaderOptions = options || {};\n      return this;\n    };\n    this.useLocalStorage = function () {\n      return this.useStorage('$translateLocalStorage');\n    };\n    this.useCookieStorage = function () {\n      return this.useStorage('$translateCookieStorage');\n    };\n    this.useStorage = function (storageFactory) {\n      $storageFactory = storageFactory;\n      return this;\n    };\n    this.storagePrefix = function (prefix) {\n      if (!prefix) {\n        return prefix;\n      }\n      $storagePrefix = prefix;\n      return this;\n    };\n    this.useMissingTranslationHandlerLog = function () {\n      return this.useMissingTranslationHandler('$translateMissingTranslationHandlerLog');\n    };\n    this.useMissingTranslationHandler = function (factory) {\n      $missingTranslationHandlerFactory = factory;\n      return this;\n    };\n    this.usePostCompiling = function (value) {\n      $postCompilingEnabled = !!value;\n      return this;\n    };\n    this.determinePreferredLanguage = function (fn) {\n      var locale = fn && angular.isFunction(fn) ? fn() : getLocale();\n      if (!$availableLanguageKeys.length) {\n        $preferredLanguage = locale;\n      } else {\n        $preferredLanguage = negotiateLocale(locale);\n      }\n      return this;\n    };\n    this.registerAvailableLanguageKeys = function (languageKeys, aliases) {\n      if (languageKeys) {\n        $availableLanguageKeys = languageKeys;\n        if (aliases) {\n          $languageKeyAliases = aliases;\n        }\n        return this;\n      }\n      return $availableLanguageKeys;\n    };\n    this.useLoaderCache = function (cache) {\n      if (cache === false) {\n        loaderCache = undefined;\n      } else if (cache === true) {\n        loaderCache = true;\n      } else if (typeof cache === 'undefined') {\n        loaderCache = '$translationCache';\n      } else if (cache) {\n        loaderCache = cache;\n      }\n      return this;\n    };\n    this.$get = [\n      '$log',\n      '$injector',\n      '$rootScope',\n      '$q',\n      function ($log, $injector, $rootScope, $q) {\n        var Storage, defaultInterpolator = $injector.get($interpolationFactory || '$translateDefaultInterpolation'), pendingLoader = false, interpolatorHashMap = {}, langPromises = {}, fallbackIndex, startFallbackIteration;\n        var $translate = function (translationId, interpolateParams, interpolationId) {\n          if (angular.isArray(translationId)) {\n            var translateAll = function (translationIds) {\n              var results = {};\n              var promises = [];\n              var translate = function (translationId) {\n                var deferred = $q.defer();\n                var regardless = function (value) {\n                  results[translationId] = value;\n                  deferred.resolve([\n                    translationId,\n                    value\n                  ]);\n                };\n                $translate(translationId, interpolateParams, interpolationId).then(regardless, regardless);\n                return deferred.promise;\n              };\n              for (var i = 0, c = translationIds.length; i < c; i++) {\n                promises.push(translate(translationIds[i]));\n              }\n              return $q.all(promises).then(function () {\n                return results;\n              });\n            };\n            return translateAll(translationId);\n          }\n          var deferred = $q.defer();\n          if (translationId) {\n            translationId = trim.apply(translationId);\n          }\n          var promiseToWaitFor = function () {\n              var promise = $preferredLanguage ? langPromises[$preferredLanguage] : langPromises[$uses];\n              fallbackIndex = 0;\n              if ($storageFactory && !promise) {\n                var langKey = Storage.get($storageKey);\n                promise = langPromises[langKey];\n                if ($fallbackLanguage && $fallbackLanguage.length) {\n                  var index = indexOf($fallbackLanguage, langKey);\n                  fallbackIndex = index === 0 ? 1 : 0;\n                  if (indexOf($fallbackLanguage, $preferredLanguage) < 0) {\n                    $fallbackLanguage.push($preferredLanguage);\n                  }\n                }\n              }\n              return promise;\n            }();\n          if (!promiseToWaitFor) {\n            determineTranslation(translationId, interpolateParams, interpolationId).then(deferred.resolve, deferred.reject);\n          } else {\n            promiseToWaitFor.then(function () {\n              determineTranslation(translationId, interpolateParams, interpolationId).then(deferred.resolve, deferred.reject);\n            }, deferred.reject);\n          }\n          return deferred.promise;\n        };\n        var applyNotFoundIndicators = function (translationId) {\n          if ($notFoundIndicatorLeft) {\n            translationId = [\n              $notFoundIndicatorLeft,\n              translationId\n            ].join(' ');\n          }\n          if ($notFoundIndicatorRight) {\n            translationId = [\n              translationId,\n              $notFoundIndicatorRight\n            ].join(' ');\n          }\n          return translationId;\n        };\n        var useLanguage = function (key) {\n          $uses = key;\n          $rootScope.$emit('$translateChangeSuccess', { language: key });\n          if ($storageFactory) {\n            Storage.set($translate.storageKey(), $uses);\n          }\n          defaultInterpolator.setLocale($uses);\n          angular.forEach(interpolatorHashMap, function (interpolator, id) {\n            interpolatorHashMap[id].setLocale($uses);\n          });\n          $rootScope.$emit('$translateChangeEnd', { language: key });\n        };\n        var loadAsync = function (key) {\n          if (!key) {\n            throw 'No language key specified for loading.';\n          }\n          var deferred = $q.defer();\n          $rootScope.$emit('$translateLoadingStart', { language: key });\n          pendingLoader = true;\n          var cache = loaderCache;\n          if (typeof cache === 'string') {\n            cache = $injector.get(cache);\n          }\n          var loaderOptions = angular.extend({}, $loaderOptions, {\n              key: key,\n              $http: angular.extend({}, { cache: cache }, $loaderOptions.$http)\n            });\n          $injector.get($loaderFactory)(loaderOptions).then(function (data) {\n            var translationTable = {};\n            $rootScope.$emit('$translateLoadingSuccess', { language: key });\n            if (angular.isArray(data)) {\n              angular.forEach(data, function (table) {\n                angular.extend(translationTable, flatObject(table));\n              });\n            } else {\n              angular.extend(translationTable, flatObject(data));\n            }\n            pendingLoader = false;\n            deferred.resolve({\n              key: key,\n              table: translationTable\n            });\n            $rootScope.$emit('$translateLoadingEnd', { language: key });\n          }, function (key) {\n            $rootScope.$emit('$translateLoadingError', { language: key });\n            deferred.reject(key);\n            $rootScope.$emit('$translateLoadingEnd', { language: key });\n          });\n          return deferred.promise;\n        };\n        if ($storageFactory) {\n          Storage = $injector.get($storageFactory);\n          if (!Storage.get || !Storage.set) {\n            throw new Error('Couldn\\'t use storage \\'' + $storageFactory + '\\', missing get() or set() method!');\n          }\n        }\n        if (angular.isFunction(defaultInterpolator.useSanitizeValueStrategy)) {\n          defaultInterpolator.useSanitizeValueStrategy($interpolationSanitizationStrategy);\n        }\n        if ($interpolatorFactories.length) {\n          angular.forEach($interpolatorFactories, function (interpolatorFactory) {\n            var interpolator = $injector.get(interpolatorFactory);\n            interpolator.setLocale($preferredLanguage || $uses);\n            if (angular.isFunction(interpolator.useSanitizeValueStrategy)) {\n              interpolator.useSanitizeValueStrategy($interpolationSanitizationStrategy);\n            }\n            interpolatorHashMap[interpolator.getInterpolationIdentifier()] = interpolator;\n          });\n        }\n        var getTranslationTable = function (langKey) {\n          var deferred = $q.defer();\n          if (Object.prototype.hasOwnProperty.call($translationTable, langKey)) {\n            deferred.resolve($translationTable[langKey]);\n          } else if (langPromises[langKey]) {\n            langPromises[langKey].then(function (data) {\n              translations(data.key, data.table);\n              deferred.resolve(data.table);\n            }, deferred.reject);\n          } else {\n            deferred.reject();\n          }\n          return deferred.promise;\n        };\n        var getFallbackTranslation = function (langKey, translationId, interpolateParams, Interpolator) {\n          var deferred = $q.defer();\n          getTranslationTable(langKey).then(function (translationTable) {\n            if (Object.prototype.hasOwnProperty.call(translationTable, translationId)) {\n              Interpolator.setLocale(langKey);\n              deferred.resolve(Interpolator.interpolate(translationTable[translationId], interpolateParams));\n              Interpolator.setLocale($uses);\n            } else {\n              deferred.reject();\n            }\n          }, deferred.reject);\n          return deferred.promise;\n        };\n        var getFallbackTranslationInstant = function (langKey, translationId, interpolateParams, Interpolator) {\n          var result, translationTable = $translationTable[langKey];\n          if (Object.prototype.hasOwnProperty.call(translationTable, translationId)) {\n            Interpolator.setLocale(langKey);\n            result = Interpolator.interpolate(translationTable[translationId], interpolateParams);\n            Interpolator.setLocale($uses);\n          }\n          return result;\n        };\n        var translateByHandler = function (translationId) {\n          if ($missingTranslationHandlerFactory) {\n            var resultString = $injector.get($missingTranslationHandlerFactory)(translationId, $uses);\n            if (resultString !== undefined) {\n              return resultString;\n            } else {\n              return translationId;\n            }\n          } else {\n            return translationId;\n          }\n        };\n        var resolveForFallbackLanguage = function (fallbackLanguageIndex, translationId, interpolateParams, Interpolator) {\n          var deferred = $q.defer();\n          if (fallbackLanguageIndex < $fallbackLanguage.length) {\n            var langKey = $fallbackLanguage[fallbackLanguageIndex];\n            getFallbackTranslation(langKey, translationId, interpolateParams, Interpolator).then(deferred.resolve, function () {\n              resolveForFallbackLanguage(fallbackLanguageIndex + 1, translationId, interpolateParams, Interpolator).then(deferred.resolve);\n            });\n          } else {\n            deferred.resolve(translateByHandler(translationId));\n          }\n          return deferred.promise;\n        };\n        var resolveForFallbackLanguageInstant = function (fallbackLanguageIndex, translationId, interpolateParams, Interpolator) {\n          var result;\n          if (fallbackLanguageIndex < $fallbackLanguage.length) {\n            var langKey = $fallbackLanguage[fallbackLanguageIndex];\n            result = getFallbackTranslationInstant(langKey, translationId, interpolateParams, Interpolator);\n            if (!result) {\n              result = resolveForFallbackLanguageInstant(fallbackLanguageIndex + 1, translationId, interpolateParams, Interpolator);\n            }\n          }\n          return result;\n        };\n        var fallbackTranslation = function (translationId, interpolateParams, Interpolator) {\n          return resolveForFallbackLanguage(startFallbackIteration > 0 ? startFallbackIteration : fallbackIndex, translationId, interpolateParams, Interpolator);\n        };\n        var fallbackTranslationInstant = function (translationId, interpolateParams, Interpolator) {\n          return resolveForFallbackLanguageInstant(startFallbackIteration > 0 ? startFallbackIteration : fallbackIndex, translationId, interpolateParams, Interpolator);\n        };\n        var determineTranslation = function (translationId, interpolateParams, interpolationId) {\n          var deferred = $q.defer();\n          var table = $uses ? $translationTable[$uses] : $translationTable, Interpolator = interpolationId ? interpolatorHashMap[interpolationId] : defaultInterpolator;\n          if (table && Object.prototype.hasOwnProperty.call(table, translationId)) {\n            var translation = table[translationId];\n            if (translation.substr(0, 2) === '@:') {\n              $translate(translation.substr(2), interpolateParams, interpolationId).then(deferred.resolve, deferred.reject);\n            } else {\n              deferred.resolve(Interpolator.interpolate(translation, interpolateParams));\n            }\n          } else {\n            var missingTranslationHandlerTranslation;\n            if ($missingTranslationHandlerFactory && !pendingLoader) {\n              missingTranslationHandlerTranslation = translateByHandler(translationId);\n            }\n            if ($uses && $fallbackLanguage && $fallbackLanguage.length) {\n              fallbackTranslation(translationId, interpolateParams, Interpolator).then(function (translation) {\n                deferred.resolve(translation);\n              }, function (_translationId) {\n                deferred.reject(applyNotFoundIndicators(_translationId));\n              });\n            } else if ($missingTranslationHandlerFactory && !pendingLoader && missingTranslationHandlerTranslation) {\n              deferred.resolve(missingTranslationHandlerTranslation);\n            } else {\n              deferred.reject(applyNotFoundIndicators(translationId));\n            }\n          }\n          return deferred.promise;\n        };\n        var determineTranslationInstant = function (translationId, interpolateParams, interpolationId) {\n          var result, table = $uses ? $translationTable[$uses] : $translationTable, Interpolator = interpolationId ? interpolatorHashMap[interpolationId] : defaultInterpolator;\n          if (table && Object.prototype.hasOwnProperty.call(table, translationId)) {\n            var translation = table[translationId];\n            if (translation.substr(0, 2) === '@:') {\n              result = determineTranslationInstant(translation.substr(2), interpolateParams, interpolationId);\n            } else {\n              result = Interpolator.interpolate(translation, interpolateParams);\n            }\n          } else {\n            var missingTranslationHandlerTranslation;\n            if ($missingTranslationHandlerFactory && !pendingLoader) {\n              missingTranslationHandlerTranslation = translateByHandler(translationId);\n            }\n            if ($uses && $fallbackLanguage && $fallbackLanguage.length) {\n              fallbackIndex = 0;\n              result = fallbackTranslationInstant(translationId, interpolateParams, Interpolator);\n            } else if ($missingTranslationHandlerFactory && !pendingLoader && missingTranslationHandlerTranslation) {\n              result = missingTranslationHandlerTranslation;\n            } else {\n              result = applyNotFoundIndicators(translationId);\n            }\n          }\n          return result;\n        };\n        $translate.preferredLanguage = function (langKey) {\n          if (langKey) {\n            setupPreferredLanguage(langKey);\n          }\n          return $preferredLanguage;\n        };\n        $translate.cloakClassName = function () {\n          return $cloakClassName;\n        };\n        $translate.fallbackLanguage = function (langKey) {\n          if (langKey !== undefined && langKey !== null) {\n            fallbackStack(langKey);\n            if ($loaderFactory) {\n              if ($fallbackLanguage && $fallbackLanguage.length) {\n                for (var i = 0, len = $fallbackLanguage.length; i < len; i++) {\n                  if (!langPromises[$fallbackLanguage[i]]) {\n                    langPromises[$fallbackLanguage[i]] = loadAsync($fallbackLanguage[i]);\n                  }\n                }\n              }\n            }\n            $translate.use($translate.use());\n          }\n          if ($fallbackWasString) {\n            return $fallbackLanguage[0];\n          } else {\n            return $fallbackLanguage;\n          }\n        };\n        $translate.useFallbackLanguage = function (langKey) {\n          if (langKey !== undefined && langKey !== null) {\n            if (!langKey) {\n              startFallbackIteration = 0;\n            } else {\n              var langKeyPosition = indexOf($fallbackLanguage, langKey);\n              if (langKeyPosition > -1) {\n                startFallbackIteration = langKeyPosition;\n              }\n            }\n          }\n        };\n        $translate.proposedLanguage = function () {\n          return $nextLang;\n        };\n        $translate.storage = function () {\n          return Storage;\n        };\n        $translate.use = function (key) {\n          if (!key) {\n            return $uses;\n          }\n          var deferred = $q.defer();\n          $rootScope.$emit('$translateChangeStart', { language: key });\n          var aliasedKey = negotiateLocale(key);\n          if (aliasedKey) {\n            key = aliasedKey;\n          }\n          if (!$translationTable[key] && $loaderFactory && !langPromises[key]) {\n            $nextLang = key;\n            langPromises[key] = loadAsync(key).then(function (translation) {\n              translations(translation.key, translation.table);\n              deferred.resolve(translation.key);\n              useLanguage(translation.key);\n              if ($nextLang === key) {\n                $nextLang = undefined;\n              }\n            }, function (key) {\n              if ($nextLang === key) {\n                $nextLang = undefined;\n              }\n              $rootScope.$emit('$translateChangeError', { language: key });\n              deferred.reject(key);\n              $rootScope.$emit('$translateChangeEnd', { language: key });\n            });\n          } else {\n            deferred.resolve(key);\n            useLanguage(key);\n          }\n          return deferred.promise;\n        };\n        $translate.storageKey = function () {\n          return storageKey();\n        };\n        $translate.isPostCompilingEnabled = function () {\n          return $postCompilingEnabled;\n        };\n        $translate.refresh = function (langKey) {\n          if (!$loaderFactory) {\n            throw new Error('Couldn\\'t refresh translation table, no loader registered!');\n          }\n          var deferred = $q.defer();\n          function resolve() {\n            deferred.resolve();\n            $rootScope.$emit('$translateRefreshEnd', { language: langKey });\n          }\n          function reject() {\n            deferred.reject();\n            $rootScope.$emit('$translateRefreshEnd', { language: langKey });\n          }\n          $rootScope.$emit('$translateRefreshStart', { language: langKey });\n          if (!langKey) {\n            var tables = [], loadingKeys = {};\n            if ($fallbackLanguage && $fallbackLanguage.length) {\n              for (var i = 0, len = $fallbackLanguage.length; i < len; i++) {\n                tables.push(loadAsync($fallbackLanguage[i]));\n                loadingKeys[$fallbackLanguage[i]] = true;\n              }\n            }\n            if ($uses && !loadingKeys[$uses]) {\n              tables.push(loadAsync($uses));\n            }\n            $q.all(tables).then(function (tableData) {\n              angular.forEach(tableData, function (data) {\n                if ($translationTable[data.key]) {\n                  delete $translationTable[data.key];\n                }\n                translations(data.key, data.table);\n              });\n              if ($uses) {\n                useLanguage($uses);\n              }\n              resolve();\n            });\n          } else if ($translationTable[langKey]) {\n            loadAsync(langKey).then(function (data) {\n              translations(data.key, data.table);\n              if (langKey === $uses) {\n                useLanguage($uses);\n              }\n              resolve();\n            }, reject);\n          } else {\n            reject();\n          }\n          return deferred.promise;\n        };\n        $translate.instant = function (translationId, interpolateParams, interpolationId) {\n          if (translationId === null || angular.isUndefined(translationId)) {\n            return translationId;\n          }\n          if (angular.isArray(translationId)) {\n            var results = {};\n            for (var i = 0, c = translationId.length; i < c; i++) {\n              results[translationId[i]] = $translate.instant(translationId[i], interpolateParams, interpolationId);\n            }\n            return results;\n          }\n          if (angular.isString(translationId) && translationId.length < 1) {\n            return translationId;\n          }\n          if (translationId) {\n            translationId = trim.apply(translationId);\n          }\n          var result, possibleLangKeys = [];\n          if ($preferredLanguage) {\n            possibleLangKeys.push($preferredLanguage);\n          }\n          if ($uses) {\n            possibleLangKeys.push($uses);\n          }\n          if ($fallbackLanguage && $fallbackLanguage.length) {\n            possibleLangKeys = possibleLangKeys.concat($fallbackLanguage);\n          }\n          for (var j = 0, d = possibleLangKeys.length; j < d; j++) {\n            var possibleLangKey = possibleLangKeys[j];\n            if ($translationTable[possibleLangKey]) {\n              if (typeof $translationTable[possibleLangKey][translationId] !== 'undefined') {\n                result = determineTranslationInstant(translationId, interpolateParams, interpolationId);\n              }\n            }\n            if (typeof result !== 'undefined') {\n              break;\n            }\n          }\n          if (!result && result !== '') {\n            result = defaultInterpolator.interpolate(translationId, interpolateParams);\n            if ($missingTranslationHandlerFactory && !pendingLoader) {\n              result = translateByHandler(translationId);\n            }\n          }\n          return result;\n        };\n        $translate.versionInfo = function () {\n          return version;\n        };\n        $translate.loaderCache = function () {\n          return loaderCache;\n        };\n        if ($loaderFactory) {\n          if (angular.equals($translationTable, {})) {\n            $translate.use($translate.use());\n          }\n          if ($fallbackLanguage && $fallbackLanguage.length) {\n            var processAsyncResult = function (translation) {\n              translations(translation.key, translation.table);\n              $rootScope.$emit('$translateChangeEnd', { language: translation.key });\n            };\n            for (var i = 0, len = $fallbackLanguage.length; i < len; i++) {\n              langPromises[$fallbackLanguage[i]] = loadAsync($fallbackLanguage[i]).then(processAsyncResult);\n            }\n          }\n        }\n        return $translate;\n      }\n    ];\n  }\n]);\nangular.module('pascalprecht.translate').factory('$translateDefaultInterpolation', [\n  '$interpolate',\n  function ($interpolate) {\n    var $translateInterpolator = {}, $locale, $identifier = 'default', $sanitizeValueStrategy = null, sanitizeValueStrategies = {\n        escaped: function (params) {\n          var result = {};\n          for (var key in params) {\n            if (Object.prototype.hasOwnProperty.call(params, key)) {\n              result[key] = angular.element('<div></div>').text(params[key]).html();\n            }\n          }\n          return result;\n        }\n      };\n    var sanitizeParams = function (params) {\n      var result;\n      if (angular.isFunction(sanitizeValueStrategies[$sanitizeValueStrategy])) {\n        result = sanitizeValueStrategies[$sanitizeValueStrategy](params);\n      } else {\n        result = params;\n      }\n      return result;\n    };\n    $translateInterpolator.setLocale = function (locale) {\n      $locale = locale;\n    };\n    $translateInterpolator.getInterpolationIdentifier = function () {\n      return $identifier;\n    };\n    $translateInterpolator.useSanitizeValueStrategy = function (value) {\n      $sanitizeValueStrategy = value;\n      return this;\n    };\n    $translateInterpolator.interpolate = function (string, interpolateParams) {\n      if ($sanitizeValueStrategy) {\n        interpolateParams = sanitizeParams(interpolateParams);\n      }\n      return $interpolate(string)(interpolateParams || {});\n    };\n    return $translateInterpolator;\n  }\n]);\nangular.module('pascalprecht.translate').constant('$STORAGE_KEY', 'NG_TRANSLATE_LANG_KEY');\nangular.module('pascalprecht.translate').directive('translate', [\n  '$translate',\n  '$q',\n  '$interpolate',\n  '$compile',\n  '$parse',\n  '$rootScope',\n  function ($translate, $q, $interpolate, $compile, $parse, $rootScope) {\n    return {\n      restrict: 'AE',\n      scope: true,\n      compile: function (tElement, tAttr) {\n        var translateValuesExist = tAttr.translateValues ? tAttr.translateValues : undefined;\n        var translateInterpolation = tAttr.translateInterpolation ? tAttr.translateInterpolation : undefined;\n        var translateValueExist = tElement[0].outerHTML.match(/translate-value-+/i);\n        var interpolateRegExp = '^(.*)(' + $interpolate.startSymbol() + '.*' + $interpolate.endSymbol() + ')(.*)';\n        return function linkFn(scope, iElement, iAttr) {\n          scope.interpolateParams = {};\n          scope.preText = '';\n          scope.postText = '';\n          iAttr.$observe('translate', function (translationId) {\n            if (angular.equals(translationId, '') || !angular.isDefined(translationId)) {\n              var interpolateMatches = iElement.text().match(interpolateRegExp);\n              if (angular.isArray(interpolateMatches)) {\n                scope.preText = interpolateMatches[1];\n                scope.postText = interpolateMatches[3];\n                scope.translationId = $interpolate(interpolateMatches[2])(scope.$parent);\n              } else {\n                scope.translationId = iElement.text().replace(/^\\s+|\\s+$/g, '');\n              }\n            } else {\n              scope.translationId = translationId;\n            }\n          });\n          iAttr.$observe('translateDefault', function (value) {\n            scope.defaultText = value;\n          });\n          if (translateValuesExist) {\n            iAttr.$observe('translateValues', function (interpolateParams) {\n              if (interpolateParams) {\n                scope.$parent.$watch(function () {\n                  angular.extend(scope.interpolateParams, $parse(interpolateParams)(scope.$parent));\n                });\n              }\n            });\n          }\n          if (translateValueExist) {\n            var fn = function (attrName) {\n              iAttr.$observe(attrName, function (value) {\n                scope.interpolateParams[angular.lowercase(attrName.substr(14, 1)) + attrName.substr(15)] = value;\n              });\n            };\n            for (var attr in iAttr) {\n              if (Object.prototype.hasOwnProperty.call(iAttr, attr) && attr.substr(0, 14) === 'translateValue' && attr !== 'translateValues') {\n                fn(attr);\n              }\n            }\n          }\n          var applyElementContent = function (value, scope, successful) {\n            if (!successful && typeof scope.defaultText !== 'undefined') {\n              value = scope.defaultText;\n            }\n            iElement.html(scope.preText + value + scope.postText);\n            var globallyEnabled = $translate.isPostCompilingEnabled();\n            var locallyDefined = typeof tAttr.translateCompile !== 'undefined';\n            var locallyEnabled = locallyDefined && tAttr.translateCompile !== 'false';\n            if (globallyEnabled && !locallyDefined || locallyEnabled) {\n              $compile(iElement.contents())(scope);\n            }\n          };\n          var updateTranslationFn = function () {\n              if (!translateValuesExist && !translateValueExist) {\n                return function () {\n                  var unwatch = scope.$watch('translationId', function (value) {\n                      if (scope.translationId && value) {\n                        $translate(value, {}, translateInterpolation).then(function (translation) {\n                          applyElementContent(translation, scope, true);\n                          unwatch();\n                        }, function (translationId) {\n                          applyElementContent(translationId, scope, false);\n                          unwatch();\n                        });\n                      }\n                    }, true);\n                };\n              } else {\n                return function () {\n                  var updateTranslations = function () {\n                    if (scope.translationId && scope.interpolateParams) {\n                      $translate(scope.translationId, scope.interpolateParams, translateInterpolation).then(function (translation) {\n                        applyElementContent(translation, scope, true);\n                      }, function (translationId) {\n                        applyElementContent(translationId, scope, false);\n                      });\n                    }\n                  };\n                  scope.$watch('interpolateParams', updateTranslations, true);\n                  scope.$watch('translationId', updateTranslations);\n                };\n              }\n            }();\n          var unbind = $rootScope.$on('$translateChangeSuccess', updateTranslationFn);\n          updateTranslationFn();\n          scope.$on('$destroy', unbind);\n        };\n      }\n    };\n  }\n]);\nangular.module('pascalprecht.translate').directive('translateCloak', [\n  '$rootScope',\n  '$translate',\n  function ($rootScope, $translate) {\n    return {\n      compile: function (tElement) {\n        var applyCloak = function () {\n            tElement.addClass($translate.cloakClassName());\n          }, removeCloak = function () {\n            tElement.removeClass($translate.cloakClassName());\n          }, removeListener = $rootScope.$on('$translateChangeEnd', function () {\n            removeCloak();\n            removeListener();\n            removeListener = null;\n          });\n        applyCloak();\n        return function linkFn(scope, iElement, iAttr) {\n          if (iAttr.translateCloak && iAttr.translateCloak.length) {\n            iAttr.$observe('translateCloak', function (translationId) {\n              $translate(translationId).then(removeCloak, applyCloak);\n            });\n          }\n        };\n      }\n    };\n  }\n]);\nangular.module('pascalprecht.translate').filter('translate', [\n  '$parse',\n  '$translate',\n  function ($parse, $translate) {\n    var translateFilter = function (translationId, interpolateParams, interpolation) {\n      if (!angular.isObject(interpolateParams)) {\n        interpolateParams = $parse(interpolateParams)(this);\n      }\n      return $translate.instant(translationId, interpolateParams, interpolation);\n    };\n    translateFilter.$stateful = true;\n    return translateFilter;\n  }\n]);"
  },
  {
    "path": "open-layui-web/src/main/view/static/editor-app/libs/bootstrap-daterangepicker_1.3.7/daterangepicker-bs3.css",
    "content": "/*!\n * Stylesheet for the Date Range Picker, for use with Bootstrap 3.x\n *\n * Copyright 2013 Dan Grossman ( http://www.dangrossman.info )\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Built for http://www.improvely.com\n */\n\n.daterangepicker.dropdown-menu {\n    max-width: none;\n    z-index: 3000;\n}\n\n.daterangepicker.opensleft .ranges, .daterangepicker.opensleft .calendar {\n    float: left;\n    margin: 4px;\n}\n\n.daterangepicker.opensright .ranges, .daterangepicker.opensright .calendar {\n    float: right;\n    margin: 4px;\n}\n\n.daterangepicker .ranges {\n    width: 160px;\n    text-align: left;\n}\n\n.daterangepicker .ranges .range_inputs>div {\n    float: left;\n}\n\n.daterangepicker .ranges .range_inputs>div:nth-child(2) {\n    padding-left: 11px;\n}\n\n.daterangepicker .calendar {\n    display: none;\n    max-width: 270px;\n}\n\n.daterangepicker.show-calendar .calendar {\n    display: block;\n}\n\n.daterangepicker .calendar.single .calendar-date {\n    border: none;\n}\n\n.daterangepicker .calendar th, .daterangepicker .calendar td {\n    font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;\n    white-space: nowrap;\n    text-align: center;\n    min-width: 32px;\n}\n\n.daterangepicker .daterangepicker_start_input label,\n.daterangepicker .daterangepicker_end_input label {\n    color: #333;\n    display: block;\n    font-size: 11px;\n    font-weight: normal;\n    height: 20px;\n    line-height: 20px;\n    margin-bottom: 2px;\n    text-shadow: #fff 1px 1px 0px;\n    text-transform: uppercase;\n    width: 74px;\n}\n\n.daterangepicker .ranges input {\n    font-size: 11px;\n}\n\n.daterangepicker .ranges .input-mini {\n    background-color: #eee;\n    border: 1px solid #ccc;\n    border-radius: 4px;\n    color: #555;\n    display: block;\n    font-size: 11px;\n    height: 30px;\n    line-height: 30px;\n    vertical-align: middle;\n    margin: 0 0 10px 0;\n    padding: 0 6px;\n    width: 74px;\n}\n\n.daterangepicker .ranges ul {\n    list-style: none;\n    margin: 0;\n    padding: 0;\n}\n\n.daterangepicker .ranges li {\n    font-size: 13px;\n    background: #f5f5f5;\n    border: 1px solid #f5f5f5;\n    color: #08c;\n    padding: 3px 12px;\n    margin-bottom: 8px;\n    -webkit-border-radius: 5px;\n    -moz-border-radius: 5px;\n    border-radius: 5px;\n    cursor: pointer;\n}\n\n.daterangepicker .ranges li.active, .daterangepicker .ranges li:hover {\n    background: #08c;\n    border: 1px solid #08c;\n    color: #fff;\n}\n\n.daterangepicker .calendar-date {\n    border: 1px solid #ddd;\n    padding: 4px;\n    border-radius: 4px;\n    background: #fff;\n}\n\n.daterangepicker .calendar-time {\n    text-align: center;\n    margin: 8px auto 0 auto;\n    line-height: 30px;\n}\n\n.daterangepicker {\n    position: absolute;\n    background: #fff;\n    top: 100px;\n    left: 20px;\n    padding: 4px;\n    margin-top: 1px;\n    -webkit-border-radius: 4px;\n    -moz-border-radius: 4px;\n    border-radius: 4px;\n}\n\n.daterangepicker.opensleft:before {\n    position: absolute;\n    top: -7px;\n    right: 9px;\n    display: inline-block;\n    border-right: 7px solid transparent;\n    border-bottom: 7px solid #ccc;\n    border-left: 7px solid transparent;\n    border-bottom-color: rgba(0, 0, 0, 0.2);\n    content: '';\n}\n\n.daterangepicker.opensleft:after {\n    position: absolute;\n    top: -6px;\n    right: 10px;\n    display: inline-block;\n    border-right: 6px solid transparent;\n    border-bottom: 6px solid #fff;\n    border-left: 6px solid transparent;\n    content: '';\n}\n\n.daterangepicker.opensright:before {\n    position: absolute;\n    top: -7px;\n    left: 9px;\n    display: inline-block;\n    border-right: 7px solid transparent;\n    border-bottom: 7px solid #ccc;\n    border-left: 7px solid transparent;\n    border-bottom-color: rgba(0, 0, 0, 0.2);\n    content: '';\n}\n\n.daterangepicker.opensright:after {\n    position: absolute;\n    top: -6px;\n    left: 10px;\n    display: inline-block;\n    border-right: 6px solid transparent;\n    border-bottom: 6px solid #fff;\n    border-left: 6px solid transparent;\n    content: '';\n}\n\n.daterangepicker table {\n    width: 100%;\n    margin: 0;\n}\n\n.daterangepicker td, .daterangepicker th {\n    text-align: center;\n    width: 20px;\n    height: 20px;\n    -webkit-border-radius: 4px;\n    -moz-border-radius: 4px;\n    border-radius: 4px;\n    cursor: pointer;\n    white-space: nowrap;\n}\n\n.daterangepicker td.off {\n    color: #999;\n}\n\n.daterangepicker td.disabled {\n    color: #999;\n}\n\n.daterangepicker td.available:hover, .daterangepicker th.available:hover {\n    background: #eee;\n}\n\n.daterangepicker td.in-range {\n    background: #ebf4f8;\n    -webkit-border-radius: 0;\n    -moz-border-radius: 0;\n    border-radius: 0;\n}\n\n.daterangepicker td.active, .daterangepicker td.active:hover {\n    background-color: #357ebd;\n    border-color: #3071a9;\n    color: #fff;\n}\n\n.daterangepicker td.week, .daterangepicker th.week {\n    font-size: 80%;\n    color: #ccc;\n}\n\n.daterangepicker select.monthselect, .daterangepicker select.yearselect {\n    font-size: 12px;\n    padding: 1px;\n    height: auto;\n    margin: 0;\n    cursor: default;\n}\n\n.daterangepicker select.monthselect {\n    margin-right: 2%;\n    width: 56%;\n}\n\n.daterangepicker select.yearselect {\n    width: 40%;\n}\n\n.daterangepicker select.hourselect, .daterangepicker select.minuteselect, .daterangepicker select.ampmselect {\n    width: 50px;\n    margin-bottom: 0;\n}\n\n.daterangepicker_start_input {\n    float: left;\n}\n\n.daterangepicker_end_input {\n    float: left;\n    padding-left: 11px\n}\n\n.daterangepicker th.month {\n    width: auto;\n}"
  },
  {
    "path": "open-layui-web/src/main/view/static/editor-app/libs/bootstrap-daterangepicker_1.3.7/daterangepicker.js",
    "content": "/**\n * @version: 1.3.7\n * @author: Dan Grossman http://www.dangrossman.info/\n * @date: 2014-04-29\n * @copyright: Copyright (c) 2012-2014 Dan Grossman. All rights reserved.\n * @license: Licensed under Apache License v2.0. See http://www.apache.org/licenses/LICENSE-2.0\n * @website: http://www.improvely.com/\n */\n!function ($, moment) {\n\n    var DateRangePicker = function (element, options, cb) {\n\n        // by default, the daterangepicker element is placed at the bottom of HTML body\n        this.parentEl = 'body';\n\n        //element that triggered the date range picker\n        this.element = $(element);\n\n        //create the picker HTML object\n        var DRPTemplate = '<div class=\"daterangepicker dropdown-menu\">' +\n            '<div class=\"calendar left\"></div>' +\n            '<div class=\"calendar right\"></div>' +\n            '<div class=\"ranges\">' +\n            '<div class=\"range_inputs\">' +\n            '<div class=\"daterangepicker_start_input\">' +\n            '<label for=\"daterangepicker_start\"></label>' +\n            '<input class=\"input-mini\" type=\"text\" name=\"daterangepicker_start\" value=\"\" disabled=\"disabled\" />' +\n            '</div>' +\n            '<div class=\"daterangepicker_end_input\">' +\n            '<label for=\"daterangepicker_end\"></label>' +\n            '<input class=\"input-mini\" type=\"text\" name=\"daterangepicker_end\" value=\"\" disabled=\"disabled\" />' +\n            '</div>' +\n            '<button class=\"applyBtn\" disabled=\"disabled\"></button>&nbsp;' +\n            '<button class=\"cancelBtn\"></button>' +\n            '</div>' +\n            '</div>' +\n            '</div>';\n\n        //custom options\n        if (typeof options !== 'object' || options === null)\n            options = {};\n\n        this.parentEl = (typeof options === 'object' && options.parentEl && $(options.parentEl).length) ? $(options.parentEl) : $(this.parentEl);\n        this.container = $(DRPTemplate).appendTo(this.parentEl);\n\n        this.setOptions(options, cb);\n\n        //apply CSS classes and labels to buttons\n        var c = this.container;\n        $.each(this.buttonClasses, function (idx, val) {\n            c.find('button').addClass(val);\n        });\n        this.container.find('.daterangepicker_start_input label').html(this.locale.fromLabel);\n        this.container.find('.daterangepicker_end_input label').html(this.locale.toLabel);\n        if (this.applyClass.length)\n            this.container.find('.applyBtn').addClass(this.applyClass);\n        if (this.cancelClass.length)\n            this.container.find('.cancelBtn').addClass(this.cancelClass);\n        this.container.find('.applyBtn').html(this.locale.applyLabel);\n        this.container.find('.cancelBtn').html(this.locale.cancelLabel);\n\n        //event listeners\n\n        this.container.find('.calendar')\n            .on('click.daterangepicker', '.prev', $.proxy(this.clickPrev, this))\n            .on('click.daterangepicker', '.next', $.proxy(this.clickNext, this))\n            .on('click.daterangepicker', 'td.available', $.proxy(this.clickDate, this))\n            .on('mouseenter.daterangepicker', 'td.available', $.proxy(this.enterDate, this))\n            .on('mouseleave.daterangepicker', 'td.available', $.proxy(this.updateFormInputs, this))\n            .on('change.daterangepicker', 'select.yearselect', $.proxy(this.updateMonthYear, this))\n            .on('change.daterangepicker', 'select.monthselect', $.proxy(this.updateMonthYear, this))\n            .on('change.daterangepicker', 'select.hourselect,select.minuteselect,select.ampmselect', $.proxy(this.updateTime, this));\n\n        this.container.find('.ranges')\n            .on('click.daterangepicker', 'button.applyBtn', $.proxy(this.clickApply, this))\n            .on('click.daterangepicker', 'button.cancelBtn', $.proxy(this.clickCancel, this))\n            .on('click.daterangepicker', '.daterangepicker_start_input,.daterangepicker_end_input', $.proxy(this.showCalendars, this))\n            .on('click.daterangepicker', 'li', $.proxy(this.clickRange, this))\n            .on('mouseenter.daterangepicker', 'li', $.proxy(this.enterRange, this))\n            .on('mouseleave.daterangepicker', 'li', $.proxy(this.updateFormInputs, this));\n\n        if (this.element.is('input')) {\n            this.element.on({\n                'click.daterangepicker': $.proxy(this.show, this),\n                'focus.daterangepicker': $.proxy(this.show, this),\n                'keyup.daterangepicker': $.proxy(this.updateFromControl, this)\n            });\n        } else {\n            this.element.on('click.daterangepicker', $.proxy(this.toggle, this));\n        }\n\n    };\n\n    DateRangePicker.prototype = {\n\n        constructor: DateRangePicker,\n\n        setOptions: function(options, callback) {\n\n            this.startDate = moment().startOf('day');\n            this.endDate = moment().endOf('day');\n            this.minDate = false;\n            this.maxDate = false;\n            this.dateLimit = false;\n\n            this.showDropdowns = false;\n            this.showWeekNumbers = false;\n            this.timePicker = false;\n            this.timePickerIncrement = 30;\n            this.timePicker12Hour = true;\n            this.singleDatePicker = false;\n            this.ranges = {};\n\n            this.opens = 'right';\n            if (this.element.hasClass('pull-right'))\n                this.opens = 'left';\n\n            this.buttonClasses = ['btn', 'btn-small'];\n            this.applyClass = 'btn-success';\n            this.cancelClass = 'btn-default';\n\n            this.format = 'MM/DD/YYYY';\n            this.separator = ' - ';\n\n            this.locale = {\n                applyLabel: 'Apply',\n                cancelLabel: 'Cancel',\n                fromLabel: 'From',\n                toLabel: 'To',\n                weekLabel: 'W',\n                customRangeLabel: 'Custom Range',\n                daysOfWeek: moment()._lang._weekdaysMin.slice(),\n                monthNames: moment()._lang._monthsShort.slice(),\n                firstDay: 0\n            };\n\n            this.cb = function () { };\n\n            if (typeof options.format === 'string')\n                this.format = options.format;\n\n            if (typeof options.separator === 'string')\n                this.separator = options.separator;\n\n            if (typeof options.startDate === 'string')\n                this.startDate = moment(options.startDate, this.format);\n\n            if (typeof options.endDate === 'string')\n                this.endDate = moment(options.endDate, this.format);\n\n            if (typeof options.minDate === 'string')\n                this.minDate = moment(options.minDate, this.format);\n\n            if (typeof options.maxDate === 'string')\n                this.maxDate = moment(options.maxDate, this.format);\n\n            if (typeof options.startDate === 'object')\n                this.startDate = moment(options.startDate);\n\n            if (typeof options.endDate === 'object')\n                this.endDate = moment(options.endDate);\n\n            if (typeof options.minDate === 'object')\n                this.minDate = moment(options.minDate);\n\n            if (typeof options.maxDate === 'object')\n                this.maxDate = moment(options.maxDate);\n\n            if (typeof options.applyClass === 'string')\n                this.applyClass = options.applyClass;\n\n            if (typeof options.cancelClass === 'string')\n                this.cancelClass = options.cancelClass;\n\n            if (typeof options.dateLimit === 'object')\n                this.dateLimit = options.dateLimit;\n\n            // update day names order to firstDay\n            if (typeof options.locale === 'object') {\n\n                if (typeof options.locale.daysOfWeek === 'object') {\n                    // Create a copy of daysOfWeek to avoid modification of original\n                    // options object for reusability in multiple daterangepicker instances\n                    this.locale.daysOfWeek = options.locale.daysOfWeek.slice();\n                }\n\n                if (typeof options.locale.monthNames === 'object') {\n                    this.locale.monthNames = options.locale.monthNames.slice();\n                }\n\n                if (typeof options.locale.firstDay === 'number') {\n                    this.locale.firstDay = options.locale.firstDay;\n                    var iterator = options.locale.firstDay;\n                    while (iterator > 0) {\n                        this.locale.daysOfWeek.push(this.locale.daysOfWeek.shift());\n                        iterator--;\n                    }\n                }\n\n                if (typeof options.locale.applyLabel === 'string') {\n                    this.locale.applyLabel = options.locale.applyLabel;\n                }\n\n                if (typeof options.locale.cancelLabel === 'string') {\n                    this.locale.cancelLabel = options.locale.cancelLabel;\n                }\n\n                if (typeof options.locale.fromLabel === 'string') {\n                    this.locale.fromLabel = options.locale.fromLabel;\n                }\n\n                if (typeof options.locale.toLabel === 'string') {\n                    this.locale.toLabel = options.locale.toLabel;\n                }\n\n                if (typeof options.locale.weekLabel === 'string') {\n                    this.locale.weekLabel = options.locale.weekLabel;\n                }\n\n                if (typeof options.locale.customRangeLabel === 'string') {\n                    this.locale.customRangeLabel = options.locale.customRangeLabel;\n                }\n            }\n\n            if (typeof options.opens === 'string')\n                this.opens = options.opens;\n\n            if (typeof options.showWeekNumbers === 'boolean') {\n                this.showWeekNumbers = options.showWeekNumbers;\n            }\n\n            if (typeof options.buttonClasses === 'string') {\n                this.buttonClasses = [options.buttonClasses];\n            }\n\n            if (typeof options.buttonClasses === 'object') {\n                this.buttonClasses = options.buttonClasses;\n            }\n\n            if (typeof options.showDropdowns === 'boolean') {\n                this.showDropdowns = options.showDropdowns;\n            }\n\n            if (typeof options.singleDatePicker === 'boolean') {\n                this.singleDatePicker = options.singleDatePicker;\n            }\n\n            if (typeof options.timePicker === 'boolean') {\n                this.timePicker = options.timePicker;\n            }\n\n            if (typeof options.timePickerIncrement === 'number') {\n                this.timePickerIncrement = options.timePickerIncrement;\n            }\n\n            if (typeof options.timePicker12Hour === 'boolean') {\n                this.timePicker12Hour = options.timePicker12Hour;\n            }\n\n            var start, end, range;\n\n            //if no start/end dates set, check if an input element contains initial values\n            if (typeof options.startDate === 'undefined' && typeof options.endDate === 'undefined') {\n                if ($(this.element).is('input[type=text]')) {\n                    var val = $(this.element).val();\n                    var split = val.split(this.separator);\n                    start = end = null;\n                    if (split.length == 2) {\n                        start = moment(split[0], this.format);\n                        end = moment(split[1], this.format);\n                    } else if (this.singleDatePicker) {\n                        start = moment(val, this.format);\n                        end = moment(val, this.format);\n                    }\n                    if (start !== null && end !== null) {\n                        this.startDate = start;\n                        this.endDate = end;\n                    }\n                }\n            }\n\n            if (typeof options.ranges === 'object') {\n                for (range in options.ranges) {\n\n                    start = moment(options.ranges[range][0]);\n                    end = moment(options.ranges[range][1]);\n\n                    // If we have a min/max date set, bound this range\n                    // to it, but only if it would otherwise fall\n                    // outside of the min/max.\n                    if (this.minDate && start.isBefore(this.minDate))\n                        start = moment(this.minDate);\n\n                    if (this.maxDate && end.isAfter(this.maxDate))\n                        end = moment(this.maxDate);\n\n                    // If the end of the range is before the minimum (if min is set) OR\n                    // the start of the range is after the max (also if set) don't display this\n                    // range option.\n                    if ((this.minDate && end.isBefore(this.minDate)) || (this.maxDate && start.isAfter(this.maxDate))) {\n                        continue;\n                    }\n\n                    this.ranges[range] = [start, end];\n                }\n\n                var list = '<ul>';\n                for (range in this.ranges) {\n                    list += '<li>' + range + '</li>';\n                }\n                list += '<li>' + this.locale.customRangeLabel + '</li>';\n                list += '</ul>';\n                this.container.find('.ranges ul').remove();\n                this.container.find('.ranges').prepend(list);\n            }\n\n            if (typeof callback === 'function') {\n                this.cb = callback;\n            }\n\n            if (!this.timePicker) {\n                this.startDate = this.startDate.startOf('day');\n                this.endDate = this.endDate.endOf('day');\n            }\n\n            if (this.singleDatePicker) {\n                this.opens = 'right';\n                this.container.find('.calendar.right').show();\n                this.container.find('.calendar.left').hide();\n                this.container.find('.ranges').hide();\n                if (!this.container.find('.calendar.right').hasClass('single'))\n                    this.container.find('.calendar.right').addClass('single');\n            } else {\n                this.container.find('.calendar.right').removeClass('single');\n                this.container.find('.ranges').show();\n            }\n\n            this.oldStartDate = this.startDate.clone();\n            this.oldEndDate = this.endDate.clone();\n            this.oldChosenLabel = this.chosenLabel;\n\n            this.leftCalendar = {\n                month: moment([this.startDate.year(), this.startDate.month(), 1, this.startDate.hour(), this.startDate.minute()]),\n                calendar: []\n            };\n\n            this.rightCalendar = {\n                month: moment([this.endDate.year(), this.endDate.month(), 1, this.endDate.hour(), this.endDate.minute()]),\n                calendar: []\n            };\n\n            if (this.opens == 'right') {\n                //swap calendar positions\n                var left = this.container.find('.calendar.left');\n                var right = this.container.find('.calendar.right');\n                left.removeClass('left').addClass('right');\n                right.removeClass('right').addClass('left');\n            }\n\n            if (typeof options.ranges === 'undefined' && !this.singleDatePicker) {\n                this.container.addClass('show-calendar');\n            }\n\n            this.container.addClass('opens' + this.opens);\n\n            this.updateView();\n            this.updateCalendars();\n\n        },\n\n        setStartDate: function(startDate) {\n            if (typeof startDate === 'string')\n                this.startDate = moment(startDate, this.format);\n\n            if (typeof startDate === 'object')\n                this.startDate = moment(startDate);\n\n            if (!this.timePicker)\n                this.startDate = this.startDate.startOf('day');\n\n            this.oldStartDate = this.startDate.clone();\n\n            this.updateView();\n            this.updateCalendars();\n        },\n\n        setEndDate: function(endDate) {\n            if (typeof endDate === 'string')\n                this.endDate = moment(endDate, this.format);\n\n            if (typeof endDate === 'object')\n                this.endDate = moment(endDate);\n\n            if (!this.timePicker)\n                this.endDate = this.endDate.endOf('day');\n\n            this.oldEndDate = this.endDate.clone();\n\n            this.updateView();\n            this.updateCalendars();\n        },\n\n        updateView: function () {\n            this.leftCalendar.month.month(this.startDate.month()).year(this.startDate.year());\n            this.rightCalendar.month.month(this.endDate.month()).year(this.endDate.year());\n            this.updateFormInputs();\n        },\n\n        updateFormInputs: function () {\n            this.container.find('input[name=daterangepicker_start]').val(this.startDate.format(this.format));\n            this.container.find('input[name=daterangepicker_end]').val(this.endDate.format(this.format));\n\n            if (this.startDate.isSame(this.endDate) || this.startDate.isBefore(this.endDate)) {\n                this.container.find('button.applyBtn').removeAttr('disabled');\n            } else {\n                this.container.find('button.applyBtn').attr('disabled', 'disabled');\n            }\n        },\n\n        updateFromControl: function () {\n            if (!this.element.is('input')) return;\n            if (!this.element.val().length) return;\n\n            var dateString = this.element.val().split(this.separator),\n                start = null,\n                end = null;\n\n            if(dateString.length === 2) {\n                start = moment(dateString[0], this.format);\n                end = moment(dateString[1], this.format);\n            }\n\n            if (this.singleDatePicker || start === null || end === null) {\n                start = moment(this.element.val(), this.format);\n                end = start;\n            }\n\n            if (end.isBefore(start)) return;\n\n            this.oldStartDate = this.startDate.clone();\n            this.oldEndDate = this.endDate.clone();\n\n            this.startDate = start;\n            this.endDate = end;\n\n            if (!this.startDate.isSame(this.oldStartDate) || !this.endDate.isSame(this.oldEndDate))\n                this.notify();\n\n            this.updateCalendars();\n        },\n\n        notify: function () {\n            this.updateView();\n            this.cb(this.startDate, this.endDate, this.chosenLabel);\n        },\n\n        move: function () {\n            var parentOffset = { top: 0, left: 0 };\n            if (!this.parentEl.is('body')) {\n                parentOffset = {\n                    top: this.parentEl.offset().top - this.parentEl.scrollTop(),\n                    left: this.parentEl.offset().left - this.parentEl.scrollLeft()\n                };\n            }\n\n            if (this.opens == 'left') {\n                this.container.css({\n                    top: this.element.offset().top + this.element.outerHeight() - parentOffset.top,\n                    right: $(window).width() - this.element.offset().left - this.element.outerWidth() - parentOffset.left,\n                    left: 'auto'\n                });\n                if (this.container.offset().left < 0) {\n                    this.container.css({\n                        right: 'auto',\n                        left: 9\n                    });\n                }\n            } else {\n                this.container.css({\n                    top: this.element.offset().top + this.element.outerHeight() - parentOffset.top,\n                    left: this.element.offset().left - parentOffset.left,\n                    right: 'auto'\n                });\n                if (this.container.offset().left + this.container.outerWidth() > $(window).width()) {\n                    this.container.css({\n                        left: 'auto',\n                        right: 0\n                    });\n                }\n            }\n        },\n\n        toggle: function (e) {\n            if (this.element.hasClass('active')) {\n                this.hide();\n            } else {\n                this.show();\n            }\n        },\n\n        show: function (e) {\n            this.element.addClass('active');\n            this.container.show();\n            this.move();\n\n            // Create a click proxy that is private to this instance of datepicker, for unbinding\n            this._outsideClickProxy = $.proxy(function (e) { this.outsideClick(e); }, this);\n            // Bind global datepicker mousedown for hiding and\n            $(document)\n                .on('mousedown.daterangepicker', this._outsideClickProxy)\n                // also explicitly play nice with Bootstrap dropdowns, which stopPropagation when clicking them\n                .on('click.daterangepicker', '[data-toggle=dropdown]', this._outsideClickProxy)\n                // and also close when focus changes to outside the picker (eg. tabbing between controls)\n                .on('focusin.daterangepicker', this._outsideClickProxy);\n\n            this.element.trigger('show.daterangepicker', this);\n        },\n\n        outsideClick: function (e) {\n            var target = $(e.target);\n            // if the page is clicked anywhere except within the daterangerpicker/button\n            // itself then call this.hide()\n            if (\n                target.closest(this.element).length ||\n                target.closest(this.container).length ||\n                target.closest('.calendar-date').length\n                ) return;\n            this.hide();\n        },\n\n        hide: function (e) {\n            $(document)\n                .off('mousedown.daterangepicker', this._outsideClickProxy)\n                .off('click.daterangepicker', this._outsideClickProxy)\n                .off('focusin.daterangepicker', this._outsideClickProxy);\n\n            this.element.removeClass('active');\n            this.container.hide();\n\n            if (!this.startDate.isSame(this.oldStartDate) || !this.endDate.isSame(this.oldEndDate))\n                this.notify();\n\n            this.oldStartDate = this.startDate.clone();\n            this.oldEndDate = this.endDate.clone();\n\n            this.element.trigger('hide.daterangepicker', this);\n        },\n\n        enterRange: function (e) {\n            // mouse pointer has entered a range label\n            var label = e.target.innerHTML;\n            if (label == this.locale.customRangeLabel) {\n                this.updateView();\n            } else {\n                var dates = this.ranges[label];\n                this.container.find('input[name=daterangepicker_start]').val(dates[0].format(this.format));\n                this.container.find('input[name=daterangepicker_end]').val(dates[1].format(this.format));\n            }\n        },\n\n        showCalendars: function() {\n            this.container.addClass('show-calendar');\n            this.move();\n        },\n\n        hideCalendars: function() {\n            this.container.removeClass('show-calendar');\n        },\n\n        updateInputText: function() {\n            if (this.element.is('input') && !this.singleDatePicker) {\n                this.element.val(this.startDate.format(this.format) + this.separator + this.endDate.format(this.format));\n            } else if (this.element.is('input')) {\n                this.element.val(this.startDate.format(this.format));\n            }\n        },\n\n        clickRange: function (e) {\n            var label = e.target.innerHTML;\n            this.chosenLabel = label;\n            if (label == this.locale.customRangeLabel) {\n                this.showCalendars();\n            } else {\n                var dates = this.ranges[label];\n\n                this.startDate = dates[0];\n                this.endDate = dates[1];\n\n                if (!this.timePicker) {\n                    this.startDate.startOf('day');\n                    this.endDate.endOf('day');\n                }\n\n                this.leftCalendar.month.month(this.startDate.month()).year(this.startDate.year()).hour(this.startDate.hour()).minute(this.startDate.minute());\n                this.rightCalendar.month.month(this.endDate.month()).year(this.endDate.year()).hour(this.endDate.hour()).minute(this.endDate.minute());\n                this.updateCalendars();\n\n                this.updateInputText();\n\n                this.hideCalendars();\n                this.hide();\n                this.element.trigger('apply.daterangepicker', this);\n            }\n        },\n\n        clickPrev: function (e) {\n            var cal = $(e.target).parents('.calendar');\n            if (cal.hasClass('left')) {\n                this.leftCalendar.month.subtract('month', 1);\n            } else {\n                this.rightCalendar.month.subtract('month', 1);\n            }\n            this.updateCalendars();\n        },\n\n        clickNext: function (e) {\n            var cal = $(e.target).parents('.calendar');\n            if (cal.hasClass('left')) {\n                this.leftCalendar.month.add('month', 1);\n            } else {\n                this.rightCalendar.month.add('month', 1);\n            }\n            this.updateCalendars();\n        },\n\n        enterDate: function (e) {\n\n            var title = $(e.target).attr('data-title');\n            var row = title.substr(1, 1);\n            var col = title.substr(3, 1);\n            var cal = $(e.target).parents('.calendar');\n\n            if (cal.hasClass('left')) {\n                this.container.find('input[name=daterangepicker_start]').val(this.leftCalendar.calendar[row][col].format(this.format));\n            } else {\n                this.container.find('input[name=daterangepicker_end]').val(this.rightCalendar.calendar[row][col].format(this.format));\n            }\n\n        },\n\n        clickDate: function (e) {\n            var title = $(e.target).attr('data-title');\n            var row = title.substr(1, 1);\n            var col = title.substr(3, 1);\n            var cal = $(e.target).parents('.calendar');\n\n            var startDate, endDate;\n            if (cal.hasClass('left')) {\n                startDate = this.leftCalendar.calendar[row][col];\n                endDate = this.endDate;\n                if (typeof this.dateLimit === 'object') {\n                    var maxDate = moment(startDate).add(this.dateLimit).startOf('day');\n                    if (endDate.isAfter(maxDate)) {\n                        endDate = maxDate;\n                    }\n                }\n            } else {\n                startDate = this.startDate;\n                endDate = this.rightCalendar.calendar[row][col];\n                if (typeof this.dateLimit === 'object') {\n                    var minDate = moment(endDate).subtract(this.dateLimit).startOf('day');\n                    if (startDate.isBefore(minDate)) {\n                        startDate = minDate;\n                    }\n                }\n            }\n\n            if (this.singleDatePicker && cal.hasClass('left')) {\n                endDate = startDate.clone();\n            } else if (this.singleDatePicker && cal.hasClass('right')) {\n                startDate = endDate.clone();\n            }\n\n            cal.find('td').removeClass('active');\n\n            if (startDate.isSame(endDate) || startDate.isBefore(endDate)) {\n                $(e.target).addClass('active');\n                this.startDate = startDate;\n                this.endDate = endDate;\n                this.chosenLabel = this.locale.customRangeLabel;\n            } else if (startDate.isAfter(endDate)) {\n                $(e.target).addClass('active');\n                var difference = this.endDate.diff(this.startDate);\n                this.startDate = startDate;\n                this.endDate = moment(startDate).add('ms', difference);\n                this.chosenLabel = this.locale.customRangeLabel;\n            }\n\n            this.leftCalendar.month.month(this.startDate.month()).year(this.startDate.year());\n            this.rightCalendar.month.month(this.endDate.month()).year(this.endDate.year());\n            this.updateCalendars();\n\n            if (!this.timePicker)\n                endDate.endOf('day');\n\n            if (this.singleDatePicker)\n                this.clickApply();\n        },\n\n        clickApply: function (e) {\n            this.updateInputText();\n            this.hide();\n            this.element.trigger('apply.daterangepicker', this);\n        },\n\n        clickCancel: function (e) {\n            this.startDate = this.oldStartDate;\n            this.endDate = this.oldEndDate;\n            this.chosenLabel = this.oldChosenLabel;\n            this.updateView();\n            this.updateCalendars();\n            this.hide();\n            this.element.trigger('cancel.daterangepicker', this);\n        },\n\n        updateMonthYear: function (e) {\n            var isLeft = $(e.target).closest('.calendar').hasClass('left'),\n                leftOrRight = isLeft ? 'left' : 'right',\n                cal = this.container.find('.calendar.'+leftOrRight);\n\n            // Month must be Number for new moment versions\n            var month = parseInt(cal.find('.monthselect').val(), 10);\n            var year = cal.find('.yearselect').val();\n\n            this[leftOrRight+'Calendar'].month.month(month).year(year);\n            this.updateCalendars();\n        },\n\n        updateTime: function(e) {\n\n            var cal = $(e.target).closest('.calendar'),\n                isLeft = cal.hasClass('left');\n\n            var hour = parseInt(cal.find('.hourselect').val(), 10);\n            var minute = parseInt(cal.find('.minuteselect').val(), 10);\n\n            if (this.timePicker12Hour) {\n                var ampm = cal.find('.ampmselect').val();\n                if (ampm === 'PM' && hour < 12)\n                    hour += 12;\n                if (ampm === 'AM' && hour === 12)\n                    hour = 0;\n            }\n\n            if (isLeft) {\n                var start = this.startDate.clone();\n                start.hour(hour);\n                start.minute(minute);\n                this.startDate = start;\n                this.leftCalendar.month.hour(hour).minute(minute);\n            } else {\n                var end = this.endDate.clone();\n                end.hour(hour);\n                end.minute(minute);\n                this.endDate = end;\n                this.rightCalendar.month.hour(hour).minute(minute);\n            }\n\n            this.updateCalendars();\n        },\n\n        updateCalendars: function () {\n            this.leftCalendar.calendar = this.buildCalendar(this.leftCalendar.month.month(), this.leftCalendar.month.year(), this.leftCalendar.month.hour(), this.leftCalendar.month.minute(), 'left');\n            this.rightCalendar.calendar = this.buildCalendar(this.rightCalendar.month.month(), this.rightCalendar.month.year(), this.rightCalendar.month.hour(), this.rightCalendar.month.minute(), 'right');\n            this.container.find('.calendar.left').empty().html(this.renderCalendar(this.leftCalendar.calendar, this.startDate, this.minDate, this.maxDate));\n            this.container.find('.calendar.right').empty().html(this.renderCalendar(this.rightCalendar.calendar, this.endDate, this.startDate, this.maxDate));\n\n            this.container.find('.ranges li').removeClass('active');\n            var customRange = true;\n            var i = 0;\n            for (var range in this.ranges) {\n                if (this.timePicker) {\n                    if (this.startDate.isSame(this.ranges[range][0]) && this.endDate.isSame(this.ranges[range][1])) {\n                        customRange = false;\n                        this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')')\n                            .addClass('active').html();\n                    }\n                } else {\n                    //ignore times when comparing dates if time picker is not enabled\n                    if (this.startDate.format('YYYY-MM-DD') == this.ranges[range][0].format('YYYY-MM-DD') && this.endDate.format('YYYY-MM-DD') == this.ranges[range][1].format('YYYY-MM-DD')) {\n                        customRange = false;\n                        this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')')\n                            .addClass('active').html();\n                    }\n                }\n                i++;\n            }\n            if (customRange) {\n                this.chosenLabel = this.container.find('.ranges li:last')\n                    .addClass('active').html();\n            }\n        },\n\n        buildCalendar: function (month, year, hour, minute, side) {\n            var firstDay = moment([year, month, 1]);\n            var lastMonth = moment(firstDay).subtract('month', 1).month();\n            var lastYear = moment(firstDay).subtract('month', 1).year();\n\n            var daysInLastMonth = moment([lastYear, lastMonth]).daysInMonth();\n\n            var dayOfWeek = firstDay.day();\n\n            var i;\n\n            //initialize a 6 rows x 7 columns array for the calendar\n            var calendar = [];\n            for (i = 0; i < 6; i++) {\n                calendar[i] = [];\n            }\n\n            //populate the calendar with date objects\n            var startDay = daysInLastMonth - dayOfWeek + this.locale.firstDay + 1;\n            if (startDay > daysInLastMonth)\n                startDay -= 7;\n\n            if (dayOfWeek == this.locale.firstDay)\n                startDay = daysInLastMonth - 6;\n\n            var curDate = moment([lastYear, lastMonth, startDay, 12, minute]);\n            var col, row;\n            for (i = 0, col = 0, row = 0; i < 42; i++, col++, curDate = moment(curDate).add('hour', 24)) {\n                if (i > 0 && col % 7 === 0) {\n                    col = 0;\n                    row++;\n                }\n                calendar[row][col] = curDate.clone().hour(hour);\n                curDate.hour(12);\n            }\n\n            return calendar;\n        },\n\n        renderDropdowns: function (selected, minDate, maxDate) {\n            var currentMonth = selected.month();\n            var monthHtml = '<select class=\"monthselect\">';\n            var inMinYear = false;\n            var inMaxYear = false;\n\n            for (var m = 0; m < 12; m++) {\n                if ((!inMinYear || m >= minDate.month()) && (!inMaxYear || m <= maxDate.month())) {\n                    monthHtml += \"<option value='\" + m + \"'\" +\n                        (m === currentMonth ? \" selected='selected'\" : \"\") +\n                        \">\" + this.locale.monthNames[m] + \"</option>\";\n                }\n            }\n            monthHtml += \"</select>\";\n\n            var currentYear = selected.year();\n            var maxYear = (maxDate && maxDate.year()) || (currentYear + 5);\n            var minYear = (minDate && minDate.year()) || (currentYear - 50);\n            var yearHtml = '<select class=\"yearselect\">';\n\n            for (var y = minYear; y <= maxYear; y++) {\n                yearHtml += '<option value=\"' + y + '\"' +\n                    (y === currentYear ? ' selected=\"selected\"' : '') +\n                    '>' + y + '</option>';\n            }\n\n            yearHtml += '</select>';\n\n            return monthHtml + yearHtml;\n        },\n\n        renderCalendar: function (calendar, selected, minDate, maxDate) {\n\n            var html = '<div class=\"calendar-date\">';\n            html += '<table class=\"table-condensed\">';\n            html += '<thead>';\n            html += '<tr>';\n\n            // add empty cell for week number\n            if (this.showWeekNumbers)\n                html += '<th></th>';\n\n            if (!minDate || minDate.isBefore(calendar[1][1])) {\n                html += '<th class=\"prev available\"><i class=\"fa fa-arrow-left icon-arrow-left glyphicon glyphicon-arrow-left\"></i></th>';\n            } else {\n                html += '<th></th>';\n            }\n\n            var dateHtml = this.locale.monthNames[calendar[1][1].month()] + calendar[1][1].format(\" YYYY\");\n\n            if (this.showDropdowns) {\n                dateHtml = this.renderDropdowns(calendar[1][1], minDate, maxDate);\n            }\n\n            html += '<th colspan=\"5\" class=\"month\">' + dateHtml + '</th>';\n            if (!maxDate || maxDate.isAfter(calendar[1][1])) {\n                html += '<th class=\"next available\"><i class=\"fa fa-arrow-right icon-arrow-right glyphicon glyphicon-arrow-right\"></i></th>';\n            } else {\n                html += '<th></th>';\n            }\n\n            html += '</tr>';\n            html += '<tr>';\n\n            // add week number label\n            if (this.showWeekNumbers)\n                html += '<th class=\"week\">' + this.locale.weekLabel + '</th>';\n\n            $.each(this.locale.daysOfWeek, function (index, dayOfWeek) {\n                html += '<th>' + dayOfWeek + '</th>';\n            });\n\n            html += '</tr>';\n            html += '</thead>';\n            html += '<tbody>';\n\n            for (var row = 0; row < 6; row++) {\n                html += '<tr>';\n\n                // add week number\n                if (this.showWeekNumbers)\n                    html += '<td class=\"week\">' + calendar[row][0].week() + '</td>';\n\n                for (var col = 0; col < 7; col++) {\n                    var cname = 'available ';\n                    cname += (calendar[row][col].month() == calendar[1][1].month()) ? '' : 'off';\n\n                    if ((minDate && calendar[row][col].isBefore(minDate, 'day')) || (maxDate && calendar[row][col].isAfter(maxDate, 'day'))) {\n                        cname = ' off disabled ';\n                    } else if (calendar[row][col].format('YYYY-MM-DD') == selected.format('YYYY-MM-DD')) {\n                        cname += ' active ';\n                        if (calendar[row][col].format('YYYY-MM-DD') == this.startDate.format('YYYY-MM-DD')) {\n                            cname += ' start-date ';\n                        }\n                        if (calendar[row][col].format('YYYY-MM-DD') == this.endDate.format('YYYY-MM-DD')) {\n                            cname += ' end-date ';\n                        }\n                    } else if (calendar[row][col] >= this.startDate && calendar[row][col] <= this.endDate) {\n                        cname += ' in-range ';\n                        if (calendar[row][col].isSame(this.startDate)) { cname += ' start-date '; }\n                        if (calendar[row][col].isSame(this.endDate)) { cname += ' end-date '; }\n                    }\n\n                    var title = 'r' + row + 'c' + col;\n                    html += '<td class=\"' + cname.replace(/\\s+/g, ' ').replace(/^\\s?(.*?)\\s?$/, '$1') + '\" data-title=\"' + title + '\">' + calendar[row][col].date() + '</td>';\n                }\n                html += '</tr>';\n            }\n\n            html += '</tbody>';\n            html += '</table>';\n            html += '</div>';\n\n            var i;\n            if (this.timePicker) {\n\n                html += '<div class=\"calendar-time\">';\n                html += '<select class=\"hourselect\">';\n                var start = 0;\n                var end = 23;\n                var selected_hour = selected.hour();\n                if (this.timePicker12Hour) {\n                    start = 1;\n                    end = 12;\n                    if (selected_hour >= 12)\n                        selected_hour -= 12;\n                    if (selected_hour === 0)\n                        selected_hour = 12;\n                }\n\n                for (i = start; i <= end; i++) {\n                    if (i == selected_hour) {\n                        html += '<option value=\"' + i + '\" selected=\"selected\">' + i + '</option>';\n                    } else {\n                        html += '<option value=\"' + i + '\">' + i + '</option>';\n                    }\n                }\n\n                html += '</select> : ';\n\n                html += '<select class=\"minuteselect\">';\n\n                for (i = 0; i < 60; i += this.timePickerIncrement) {\n                    var num = i;\n                    if (num < 10)\n                        num = '0' + num;\n                    if (i == selected.minute()) {\n                        html += '<option value=\"' + i + '\" selected=\"selected\">' + num + '</option>';\n                    } else {\n                        html += '<option value=\"' + i + '\">' + num + '</option>';\n                    }\n                }\n\n                html += '</select> ';\n\n                if (this.timePicker12Hour) {\n                    html += '<select class=\"ampmselect\">';\n                    if (selected.hour() >= 12) {\n                        html += '<option value=\"AM\">AM</option><option value=\"PM\" selected=\"selected\">PM</option>';\n                    } else {\n                        html += '<option value=\"AM\" selected=\"selected\">AM</option><option value=\"PM\">PM</option>';\n                    }\n                    html += '</select>';\n                }\n\n                html += '</div>';\n\n            }\n\n            return html;\n\n        },\n\n        remove: function() {\n\n            this.container.remove();\n            this.element.off('.daterangepicker');\n            this.element.removeData('daterangepicker');\n\n        }\n\n    };\n\n    $.fn.daterangepicker = function (options, cb) {\n        this.each(function () {\n            var el = $(this);\n            if (el.data('daterangepicker'))\n                el.data('daterangepicker').remove();\n            el.data('daterangepicker', new DateRangePicker(el, options, cb));\n        });\n        return this;\n    };\n\n}(window.jQuery, window.moment);"
  },
  {
    "path": "open-layui-web/src/main/view/static/editor-app/libs/jquery.autogrow-textarea.js",
    "content": "(function($)\n{\n    /**\n     * Auto-growing textareas; technique ripped from Facebook\n     *\n     * http://github.com/jaz303/jquery-grab-bag/tree/master/javascripts/jquery.autogrow-textarea.js\n     */\n    $.fn.autogrow = function(options)\n    {\n        return this.filter('textarea').each(function()\n        {\n            var self         = this;\n            var $self        = $(self);\n            var minHeight    = $self.height();\n            var noFlickerPad = $self.hasClass('autogrow-short') ? 0 : parseInt($self.css('lineHeight')) || 0;\n\n            var shadow = $('<div></div>').css({\n                position:    'absolute',\n                top:         -10000,\n                left:        -10000,\n                width:       $self.width(),\n                fontSize:    $self.css('fontSize'),\n                fontFamily:  $self.css('fontFamily'),\n                fontWeight:  $self.css('fontWeight'),\n                lineHeight:  $self.css('lineHeight'),\n                resize:      'none',\n                            'word-wrap': 'break-word'\n            }).appendTo(document.body);\n\n            var update = function(event)\n            {\n                var times = function(string, number)\n                {\n                    for (var i=0, r=''; i<number; i++) r += string;\n                    return r;\n                };\n\n                var val = self.value.replace(/</g, '&lt;')\n                                    .replace(/>/g, '&gt;')\n                                    .replace(/&/g, '&amp;')\n                                    .replace(/\\n$/, '<br/>&nbsp;')\n                                    .replace(/\\n/g, '<br/>')\n                                    .replace(/ {2,}/g, function(space){ return times('&nbsp;', space.length - 1) + ' ' });\n\n                                // Did enter get pressed?  Resize in this keydown event so that the flicker doesn't occur.\n                                if (event && event.data && event.data.event === 'keydown' && event.keyCode === 13) {\n                                        val += '<br />';\n                                }\n\n                shadow.css('width', $self.width());\n                shadow.html(val + (noFlickerPad === 0 ? '...' : '')); // Append '...' to resize pre-emptively.\n                $self.height(Math.max(shadow.height() + noFlickerPad, minHeight));\n            }\n\n            $self.change(update).keyup(update).keydown({event:'keydown'},update);\n            $(window).resize(update);\n\n            update();\n        });\n    };\n})(jQuery);"
  },
  {
    "path": "open-layui-web/src/main/view/static/editor-app/libs/ng-grid-2.0.7-min.js",
    "content": "(function(e,t){\"use strict\";var n=6,o=4,i=\"asc\",r=\"desc\",l=\"_ng_field_\",a=\"_ng_depth_\",s=\"_ng_hidden_\",c=\"_ng_column_\",g=/CUSTOM_FILTERS/g,d=/COL_FIELD/g,u=/DISPLAY_CELL_TEMPLATE/g,f=/EDITABLE_CELL_TEMPLATE/g,h=/<.+>/;e.ngGrid={},e.ngGrid.i18n={},angular.module(\"ngGrid.services\",[]);var p=angular.module(\"ngGrid.directives\",[]),m=angular.module(\"ngGrid.filters\",[]);angular.module(\"ngGrid\",[\"ngGrid.services\",\"ngGrid.directives\",\"ngGrid.filters\"]);var v=function(e,t,o,i){if(void 0===e.selectionProvider.selectedItems)return!0;var r,l=o.which||o.keyCode,a=!1,s=!1,c=void 0===e.selectionProvider.lastClickedRow?1:e.selectionProvider.lastClickedRow.rowIndex,g=e.columns.filter(function(e){return e.visible}),d=e.columns.filter(function(e){return e.pinned});if(e.col&&(r=g.indexOf(e.col)),37!==l&&38!==l&&39!==l&&40!==l&&9!==l&&13!==l)return!0;if(e.enableCellSelection){9===l&&o.preventDefault();var u=e.showSelectionCheckbox?1===e.col.index:0===e.col.index,f=1===e.$index||0===e.$index,h=e.$index===e.renderedColumns.length-1||e.$index===e.renderedColumns.length-2,p=g.indexOf(e.col)===g.length-1,m=d.indexOf(e.col)===d.length-1;if(37===l||9===l&&o.shiftKey){var v=0;u||(r-=1),f?u&&9===l&&o.shiftKey?(v=i.$canvas.width(),r=g.length-1,s=!0):v=i.$viewport.scrollLeft()-e.col.width:d.length>0&&(v=i.$viewport.scrollLeft()-g[r].width),i.$viewport.scrollLeft(v)}else(39===l||9===l&&!o.shiftKey)&&(h?p&&9===l&&!o.shiftKey?(i.$viewport.scrollLeft(0),r=e.showSelectionCheckbox?1:0,a=!0):i.$viewport.scrollLeft(i.$viewport.scrollLeft()+e.col.width):m&&i.$viewport.scrollLeft(0),p||(r+=1))}var w;w=e.configGroups.length>0?i.rowFactory.parsedData.filter(function(e){return!e.isAggRow}):i.filteredRows;var C=0;if(0!==c&&(38===l||13===l&&o.shiftKey||9===l&&o.shiftKey&&s)?C=-1:c!==w.length-1&&(40===l||13===l&&!o.shiftKey||9===l&&a)&&(C=1),C){var b=w[c+C];b.beforeSelectionChange(b,o)&&(b.continueSelection(o),e.$emit(\"ngGridEventDigestGridParent\"),e.selectionProvider.lastClickedRow.renderedRowIndex>=e.renderedRows.length-n-2?i.$viewport.scrollTop(i.$viewport.scrollTop()+e.rowHeight):n+2>=e.selectionProvider.lastClickedRow.renderedRowIndex&&i.$viewport.scrollTop(i.$viewport.scrollTop()-e.rowHeight))}return e.enableCellSelection&&setTimeout(function(){e.domAccessProvider.focusCellElement(e,e.renderedColumns.indexOf(g[r]))},3),!1};String.prototype.trim||(String.prototype.trim=function(){return this.replace(/^\\s+|\\s+$/g,\"\")}),Array.prototype.indexOf||(Array.prototype.indexOf=function(e){var t=this.length>>>0,n=Number(arguments[1])||0;for(n=0>n?Math.ceil(n):Math.floor(n),0>n&&(n+=t);t>n;n++)if(n in this&&this[n]===e)return n;return-1}),Array.prototype.filter||(Array.prototype.filter=function(e){var t=Object(this),n=t.length>>>0;if(\"function\"!=typeof e)throw new TypeError;for(var o=[],i=arguments[1],r=0;n>r;r++)if(r in t){var l=t[r];e.call(i,l,r,t)&&o.push(l)}return o}),m.filter(\"checkmark\",function(){return function(e){return e?\"✔\":\"✘\"}}),m.filter(\"ngColumns\",function(){return function(e){return e.filter(function(e){return!e.isAggCol})}}),angular.module(\"ngGrid.services\").factory(\"$domUtilityService\",[\"$utilityService\",function(e){var n={},o={},i=function(){var e=t(\"<div></div>\");e.appendTo(\"body\"),e.height(100).width(100).css(\"position\",\"absolute\").css(\"overflow\",\"scroll\"),e.append('<div style=\"height: 400px; width: 400px;\"></div>'),n.ScrollH=e.height()-e[0].clientHeight,n.ScrollW=e.width()-e[0].clientWidth,e.empty(),e.attr(\"style\",\"\"),e.append('<span style=\"font-family: Verdana, Helvetica, Sans-Serif; font-size: 14px;\"><strong>M</strong></span>'),n.LetterW=e.children().first().width(),e.remove()};return n.eventStorage={},n.AssignGridContainers=function(e,o,i){i.$root=t(o),i.$topPanel=i.$root.find(\".ngTopPanel\"),i.$groupPanel=i.$root.find(\".ngGroupPanel\"),i.$headerContainer=i.$topPanel.find(\".ngHeaderContainer\"),e.$headerContainer=i.$headerContainer,i.$headerScroller=i.$topPanel.find(\".ngHeaderScroller\"),i.$headers=i.$headerScroller.children(),i.$viewport=i.$root.find(\".ngViewport\"),i.$canvas=i.$viewport.find(\".ngCanvas\"),i.$footerPanel=i.$root.find(\".ngFooterPanel\"),e.$watch(function(){return i.$viewport.scrollLeft()},function(e){return i.$headerContainer.scrollLeft(e)}),n.UpdateGridLayout(e,i)},n.getRealWidth=function(e){var n=0,o={visibility:\"hidden\",display:\"block\"},i=e.parents().andSelf().not(\":visible\");return t.swap(i[0],o,function(){n=e.outerWidth()}),n},n.UpdateGridLayout=function(e,t){var o=t.$viewport.scrollTop();t.elementDims.rootMaxW=t.$root.width(),t.$root.is(\":hidden\")&&(t.elementDims.rootMaxW=n.getRealWidth(t.$root)),t.elementDims.rootMaxH=t.$root.height(),t.refreshDomSizes(),e.adjustScrollTop(o,!0)},n.numberOfGrids=0,n.BuildStyles=function(o,i,r){var l,a=i.config.rowHeight,s=i.$styleSheet,c=i.gridId,g=o.columns,d=0;s||(s=t(\"#\"+c),s[0]||(s=t(\"<style id='\"+c+\"' type='text/css' rel='stylesheet' />\").appendTo(i.$root))),s.empty();var u=o.totalRowWidth();l=\".\"+c+\" .ngCanvas { width: \"+u+\"px; }\"+\".\"+c+\" .ngRow { width: \"+u+\"px; }\"+\".\"+c+\" .ngCanvas { width: \"+u+\"px; }\"+\".\"+c+\" .ngHeaderScroller { width: \"+(u+n.ScrollH)+\"px}\";for(var f=0;g.length>f;f++){var h=g[f];h.visible!==!1&&(l+=\".\"+c+\" .col\"+f+\" { width: \"+h.width+\"px; left: \"+d+\"px; height: \"+a+\"px }\"+\".\"+c+\" .colt\"+f+\" { width: \"+h.width+\"px; }\",d+=h.width)}e.isIe?s[0].styleSheet.cssText=l:s[0].appendChild(document.createTextNode(l)),i.$styleSheet=s,o.adjustScrollLeft(i.$viewport.scrollLeft()),r&&n.digest(o)},n.setColLeft=function(t,n,i){if(i.$styleSheet){var r=o[t.index];r||(r=o[t.index]=RegExp(\".col\"+t.index+\" { width: [0-9]+px; left: [0-9]+px\"));var l=i.$styleSheet.html(),a=l.replace(r,\".col\"+t.index+\" { width: \"+t.width+\"px; left: \"+n+\"px\");e.isIe?setTimeout(function(){i.$styleSheet.html(a)}):i.$styleSheet.html(a)}},n.setColLeft.immediate=1,n.RebuildGrid=function(e,t){n.UpdateGridLayout(e,t),(null==t.config.maintainColumnRatios||t.config.maintainColumnRatios)&&t.configureColumnWidths(),e.adjustScrollLeft(t.$viewport.scrollLeft()),n.BuildStyles(e,t,!0)},n.digest=function(e){e.$root.$$phase||e.$digest()},n.ScrollH=17,n.ScrollW=17,n.LetterW=10,i(),n}]),angular.module(\"ngGrid.services\").factory(\"$sortService\",[\"$parse\",function(e){var t={};return t.colSortFnCache={},t.guessSortFn=function(e){var n=typeof e;switch(n){case\"number\":return t.sortNumber;case\"boolean\":return t.sortBool;case\"string\":return e.match(/^[-+]?[£$¤]?[\\d,.]+%?$/)?t.sortNumberStr:t.sortAlpha;default:return\"[object Date]\"===Object.prototype.toString.call(e)?t.sortDate:t.basicSort}},t.basicSort=function(e,t){return e===t?0:t>e?-1:1},t.sortNumber=function(e,t){return e-t},t.sortNumberStr=function(e,t){var n,o,i=!1,r=!1;return n=parseFloat(e.replace(/[^0-9.-]/g,\"\")),isNaN(n)&&(i=!0),o=parseFloat(t.replace(/[^0-9.-]/g,\"\")),isNaN(o)&&(r=!0),i&&r?0:i?1:r?-1:n-o},t.sortAlpha=function(e,t){var n=e.toLowerCase(),o=t.toLowerCase();return n===o?0:o>n?-1:1},t.sortDate=function(e,t){var n=e.getTime(),o=t.getTime();return n===o?0:o>n?-1:1},t.sortBool=function(e,t){return e&&t?0:e||t?e?1:-1:0},t.sortData=function(n,o){if(o&&n){var r,l,a=n.fields.length,s=n.fields,c=o.slice(0);o.sort(function(o,g){for(var d,u=0,f=0;0===u&&a>f;){r=n.columns[f],l=n.directions[f],d=t.getSortFn(r,c);var h=e(s[f])(o),p=e(s[f])(g);!h&&0!==h||!p&&0!==p?p||h?h?p||(u=-1):u=1:u=0:u=d(h,p),f++}return l===i?u:0-u})}},t.Sort=function(e,n){t.isSorting||(t.isSorting=!0,t.sortData(e,n),t.isSorting=!1)},t.getSortFn=function(n,o){var i,r;if(t.colSortFnCache[n.field])i=t.colSortFnCache[n.field];else if(void 0!==n.sortingAlgorithm)i=n.sortingAlgorithm,t.colSortFnCache[n.field]=n.sortingAlgorithm;else{if(r=o[0],!r)return i;i=t.guessSortFn(e(n.field)(r)),i?t.colSortFnCache[n.field]=i:i=t.sortAlpha}return i},t}]),angular.module(\"ngGrid.services\").factory(\"$utilityService\",[\"$parse\",function(n){var o=/function (.{1,})\\(/,i={visualLength:function(e){var n=document.getElementById(\"testDataLength\");return n||(n=document.createElement(\"SPAN\"),n.id=\"testDataLength\",n.style.visibility=\"hidden\",document.body.appendChild(n)),t(n).css(\"font\",t(e).css(\"font\")),t(n).css(\"font-size\",t(e).css(\"font-size\")),t(n).css(\"font-family\",t(e).css(\"font-family\")),n.innerHTML=t(e).text(),n.offsetWidth},forIn:function(e,t){for(var n in e)e.hasOwnProperty(n)&&t(e[n],n)},evalProperty:function(e,t){return n(t)(e)},endsWith:function(e,t){return e&&t&&\"string\"==typeof e?-1!==e.indexOf(t,e.length-t.length):!1},isNullOrUndefined:function(e){return void 0===e||null===e?!0:!1},getElementsByClassName:function(e){for(var t=[],n=RegExp(\"\\\\b\"+e+\"\\\\b\"),o=document.getElementsByTagName(\"*\"),i=0;o.length>i;i++){var r=o[i].className;n.test(r)&&t.push(o[i])}return t},newId:function(){var e=(new Date).getTime();return function(){return e+=1}}(),seti18n:function(t,n){var o=e.ngGrid.i18n[n];for(var i in o)t.i18n[i]=o[i]},getInstanceType:function(e){var t=o.exec(\"\"+e.constructor);if(t&&t.length>1){var n=t[1].replace(/^\\s+|\\s+$/g,\"\");return n}return\"\"},ieVersion:function(){var e=3,t=document.createElement(\"div\"),n=t.getElementsByTagName(\"i\");do t.innerHTML=\"<!--[if gt IE \"+ ++e+\"]><i></i><![endif]-->\";while(n[0]);return e>4?e:void 0}()};return t.extend(i,{isIe:function(){return void 0!==i.ieVersion}()}),i}]);var w=function(e,t,n,o){this.rowIndex=0,this.offsetTop=this.rowIndex*n,this.entity=e,this.label=e.gLabel,this.field=e.gField,this.depth=e.gDepth,this.parent=e.parent,this.children=e.children,this.aggChildren=e.aggChildren,this.aggIndex=e.aggIndex,this.collapsed=o,this.groupInitState=o,this.rowFactory=t,this.rowHeight=n,this.isAggRow=!0,this.offsetLeft=25*e.gDepth,this.aggLabelFilter=e.aggLabelFilter};w.prototype.toggleExpand=function(){this.collapsed=this.collapsed?!1:!0,this.orig&&(this.orig.collapsed=this.collapsed),this.notifyChildren()},w.prototype.setExpand=function(e){this.collapsed=e,this.notifyChildren()},w.prototype.notifyChildren=function(){for(var e=Math.max(this.rowFactory.aggCache.length,this.children.length),t=0;e>t;t++)if(this.aggChildren[t]&&(this.aggChildren[t].entity[s]=this.collapsed,this.collapsed&&this.aggChildren[t].setExpand(this.collapsed)),this.children[t]&&(this.children[t][s]=this.collapsed),t>this.aggIndex&&this.rowFactory.aggCache[t]){var n=this.rowFactory.aggCache[t],o=30*this.children.length;n.offsetTop=this.collapsed?n.offsetTop-o:n.offsetTop+o}this.rowFactory.renderedChange()},w.prototype.aggClass=function(){return this.collapsed?\"ngAggArrowCollapsed\":\"ngAggArrowExpanded\"},w.prototype.totalChildren=function(){if(this.aggChildren.length>0){var e=0,t=function(n){n.aggChildren.length>0?angular.forEach(n.aggChildren,function(e){t(e)}):e+=n.children.length};return t(this),e}return this.children.length},w.prototype.copy=function(){var e=new w(this.entity,this.rowFactory,this.rowHeight,this.groupInitState);return e.orig=this,e};var C=function(e,n,o,l,a,s){var c=this,d=e.colDef,u=500,f=0,p=null;c.colDef=e.colDef,c.width=d.width,c.groupIndex=0,c.isGroupedBy=!1,c.minWidth=d.minWidth?d.minWidth:50,c.maxWidth=d.maxWidth?d.maxWidth:9e3,c.enableCellEdit=void 0!==d.enableCellEdit?d.enableCellEdit:e.enableCellEdit||e.enableCellEditOnFocus,c.headerRowHeight=e.headerRowHeight,c.displayName=void 0===d.displayName?d.field:d.displayName,c.index=e.index,c.isAggCol=e.isAggCol,c.cellClass=d.cellClass,c.sortPriority=void 0,c.cellFilter=d.cellFilter?d.cellFilter:\"\",c.field=d.field,c.aggLabelFilter=d.cellFilter||d.aggLabelFilter,c.visible=s.isNullOrUndefined(d.visible)||d.visible,c.sortable=!1,c.resizable=!1,c.pinnable=!1,c.pinned=e.enablePinning&&d.pinned,c.originalIndex=null==e.originalIndex?c.index:e.originalIndex,c.groupable=s.isNullOrUndefined(d.groupable)||d.groupable,e.enableSort&&(c.sortable=s.isNullOrUndefined(d.sortable)||d.sortable),e.enableResize&&(c.resizable=s.isNullOrUndefined(d.resizable)||d.resizable),e.enablePinning&&(c.pinnable=s.isNullOrUndefined(d.pinnable)||d.pinnable),c.sortDirection=void 0,c.sortingAlgorithm=d.sortFn,c.headerClass=d.headerClass,c.cursor=c.sortable?\"pointer\":\"default\",c.headerCellTemplate=d.headerCellTemplate||a.get(\"headerCellTemplate.html\"),c.cellTemplate=d.cellTemplate||a.get(\"cellTemplate.html\").replace(g,c.cellFilter?\"|\"+c.cellFilter:\"\"),c.enableCellEdit&&(c.cellEditTemplate=a.get(\"cellEditTemplate.html\"),c.editableCellTemplate=d.editableCellTemplate||a.get(\"editableCellTemplate.html\")),d.cellTemplate&&!h.test(d.cellTemplate)&&(c.cellTemplate=t.ajax({type:\"GET\",url:d.cellTemplate,async:!1}).responseText),c.enableCellEdit&&d.editableCellTemplate&&!h.test(d.editableCellTemplate)&&(c.editableCellTemplate=t.ajax({type:\"GET\",url:d.editableCellTemplate,async:!1}).responseText),d.headerCellTemplate&&!h.test(d.headerCellTemplate)&&(c.headerCellTemplate=t.ajax({type:\"GET\",url:d.headerCellTemplate,async:!1}).responseText),c.colIndex=function(){var e=c.pinned?\"pinned \":\"\";return e+=\"col\"+c.index+\" colt\"+c.index,c.cellClass&&(e+=\" \"+c.cellClass),e},c.groupedByClass=function(){return c.isGroupedBy?\"ngGroupedByIcon\":\"ngGroupIcon\"},c.toggleVisible=function(){c.visible=!c.visible},c.showSortButtonUp=function(){return c.sortable?c.sortDirection===r:c.sortable},c.showSortButtonDown=function(){return c.sortable?c.sortDirection===i:c.sortable},c.noSortVisible=function(){return!c.sortDirection},c.sort=function(t){if(!c.sortable)return!0;var n=c.sortDirection===i?r:i;return c.sortDirection=n,e.sortCallback(c,t),!1},c.gripClick=function(){f++,1===f?p=setTimeout(function(){f=0},u):(clearTimeout(p),e.resizeOnDataCallback(c),f=0)},c.gripOnMouseDown=function(e){return n.isColumnResizing=!0,e.ctrlKey&&!c.pinned?(c.toggleVisible(),l.BuildStyles(n,o),!0):(e.target.parentElement.style.cursor=\"col-resize\",c.startMousePosition=e.clientX,c.origWidth=c.width,t(document).mousemove(c.onMouseMove),t(document).mouseup(c.gripOnMouseUp),!1)},c.onMouseMove=function(e){var t=e.clientX-c.startMousePosition,i=t+c.origWidth;return c.width=c.minWidth>i?c.minWidth:i>c.maxWidth?c.maxWidth:i,n.hasUserChangedGridColumnWidths=!0,l.BuildStyles(n,o),!1},c.gripOnMouseUp=function(e){return t(document).off(\"mousemove\",c.onMouseMove),t(document).off(\"mouseup\",c.gripOnMouseUp),e.target.parentElement.style.cursor=\"default\",l.digest(n),n.isColumnResizing=!1,!1},c.copy=function(){var t=new C(e,n,o,l,a);return t.isClone=!0,t.orig=c,t},c.setVars=function(e){c.orig=e,c.width=e.width,c.groupIndex=e.groupIndex,c.isGroupedBy=e.isGroupedBy,c.displayName=e.displayName,c.index=e.index,c.isAggCol=e.isAggCol,c.cellClass=e.cellClass,c.cellFilter=e.cellFilter,c.field=e.field,c.aggLabelFilter=e.aggLabelFilter,c.visible=e.visible,c.sortable=e.sortable,c.resizable=e.resizable,c.pinnable=e.pinnable,c.pinned=e.pinned,c.originalIndex=e.originalIndex,c.sortDirection=e.sortDirection,c.sortingAlgorithm=e.sortingAlgorithm,c.headerClass=e.headerClass,c.headerCellTemplate=e.headerCellTemplate,c.cellTemplate=e.cellTemplate,c.cellEditTemplate=e.cellEditTemplate}},b=function(e){this.outerHeight=null,this.outerWidth=null,t.extend(this,e)},S=function(e){this.previousColumn=null,this.grid=e};S.prototype.changeUserSelect=function(e,t){e.css({\"-webkit-touch-callout\":t,\"-webkit-user-select\":t,\"-khtml-user-select\":t,\"-moz-user-select\":\"none\"===t?\"-moz-none\":t,\"-ms-user-select\":t,\"user-select\":t})},S.prototype.focusCellElement=function(e,t){if(e.selectionProvider.lastClickedRow){var n=void 0!==t?t:this.previousColumn,o=e.selectionProvider.lastClickedRow.clone?e.selectionProvider.lastClickedRow.clone.elm:e.selectionProvider.lastClickedRow.elm;if(void 0!==n&&o){var i=angular.element(o[0].children).filter(function(){return 8!==this.nodeType}),r=Math.max(Math.min(e.renderedColumns.length-1,n),0);this.grid.config.showSelectionCheckbox&&angular.element(i[r]).scope()&&0===angular.element(i[r]).scope().col.index&&(r=1),i[r]&&i[r].children[1].children[0].focus(),this.previousColumn=n}}},S.prototype.selectionHandlers=function(e,t){var n=!1,o=this;t.bind(\"keydown\",function(i){if(16===i.keyCode)return o.changeUserSelect(t,\"none\",i),!0;if(!n){n=!0;var r=v(e,t,i,o.grid);return n=!1,r}return!0}),t.bind(\"keyup\",function(e){return 16===e.keyCode&&o.changeUserSelect(t,\"text\",e),!0})};var x=function(n,o,i,r){var l=this;l.colToMove=void 0,l.groupToMove=void 0,l.assignEvents=function(){n.config.jqueryUIDraggable&&!n.config.enablePinning?n.$groupPanel.droppable({addClasses:!1,drop:function(e){l.onGroupDrop(e)}}):(n.$groupPanel.on(\"mousedown\",l.onGroupMouseDown).on(\"dragover\",l.dragOver).on(\"drop\",l.onGroupDrop),n.$headerScroller.on(\"mousedown\",l.onHeaderMouseDown).on(\"dragover\",l.dragOver),n.config.enableColumnReordering&&!n.config.enablePinning&&n.$headerScroller.on(\"drop\",l.onHeaderDrop)),o.$watch(\"renderedColumns\",function(){r(l.setDraggables)})},l.dragStart=function(e){e.dataTransfer.setData(\"text\",\"\")},l.dragOver=function(e){e.preventDefault()},l.setDraggables=function(){if(n.config.jqueryUIDraggable)n.$root.find(\".ngHeaderSortColumn\").draggable({helper:\"clone\",appendTo:\"body\",stack:\"div\",addClasses:!1,start:function(e){l.onHeaderMouseDown(e)}}).droppable({drop:function(e){l.onHeaderDrop(e)}});else{var e=n.$root.find(\".ngHeaderSortColumn\");angular.forEach(e,function(e){e.className&&-1!==e.className.indexOf(\"ngHeaderSortColumn\")&&(e.setAttribute(\"draggable\",\"true\"),e.addEventListener&&e.addEventListener(\"dragstart\",l.dragStart))}),-1!==navigator.userAgent.indexOf(\"MSIE\")&&n.$root.find(\".ngHeaderSortColumn\").bind(\"selectstart\",function(){return this.dragDrop(),!1})}},l.onGroupMouseDown=function(e){var o=t(e.target);if(\"ngRemoveGroup\"!==o[0].className){var i=angular.element(o).scope();i&&(n.config.jqueryUIDraggable||(o.attr(\"draggable\",\"true\"),this.addEventListener&&this.addEventListener(\"dragstart\",l.dragStart),-1!==navigator.userAgent.indexOf(\"MSIE\")&&o.bind(\"selectstart\",function(){return this.dragDrop(),!1})),l.groupToMove={header:o,groupName:i.group,index:i.$index})}else l.groupToMove=void 0},l.onGroupDrop=function(e){e.stopPropagation();var i,r;l.groupToMove?(i=t(e.target).closest(\".ngGroupElement\"),\"ngGroupPanel\"===i.context.className?(o.configGroups.splice(l.groupToMove.index,1),o.configGroups.push(l.groupToMove.groupName)):(r=angular.element(i).scope(),r&&l.groupToMove.index!==r.$index&&(o.configGroups.splice(l.groupToMove.index,1),o.configGroups.splice(r.$index,0,l.groupToMove.groupName))),l.groupToMove=void 0,n.fixGroupIndexes()):l.colToMove&&(-1===o.configGroups.indexOf(l.colToMove.col)&&(i=t(e.target).closest(\".ngGroupElement\"),\"ngGroupPanel\"===i.context.className||\"ngGroupPanelDescription ng-binding\"===i.context.className?o.groupBy(l.colToMove.col):(r=angular.element(i).scope(),r&&o.removeGroup(r.$index))),l.colToMove=void 0),o.$$phase||o.$apply()},l.onHeaderMouseDown=function(e){var n=t(e.target).closest(\".ngHeaderSortColumn\"),o=angular.element(n).scope();o&&(l.colToMove={header:n,col:o.col})},l.onHeaderDrop=function(e){if(l.colToMove&&!l.colToMove.col.pinned){var r=t(e.target).closest(\".ngHeaderSortColumn\"),a=angular.element(r).scope();if(a){if(l.colToMove.col===a.col)return;o.columns.splice(l.colToMove.col.index,1),o.columns.splice(a.col.index,0,l.colToMove.col),n.fixColumnIndexes(),l.colToMove=void 0,i.digest(o)}}},l.assignGridEventHandlers=function(){-1===n.config.tabIndex?(n.$viewport.attr(\"tabIndex\",i.numberOfGrids),i.numberOfGrids++):n.$viewport.attr(\"tabIndex\",n.config.tabIndex);var r;t(e).resize(function(){clearTimeout(r),r=setTimeout(function(){i.RebuildGrid(o,n)},100)});var l;t(n.$root.parent()).on(\"resize\",function(){clearTimeout(l),l=setTimeout(function(){i.RebuildGrid(o,n)},100)})},l.assignGridEventHandlers(),l.assignEvents()},y=function(e,t){e.maxRows=function(){var n=Math.max(e.totalServerItems,t.data.length);return n},e.multiSelect=t.config.enableRowSelection&&t.config.multiSelect,e.selectedItemCount=t.selectedItemCount,e.maxPages=function(){return Math.ceil(e.maxRows()/e.pagingOptions.pageSize)},e.pageForward=function(){var t=e.pagingOptions.currentPage;e.totalServerItems>0?e.pagingOptions.currentPage=Math.min(t+1,e.maxPages()):e.pagingOptions.currentPage++},e.pageBackward=function(){var t=e.pagingOptions.currentPage;e.pagingOptions.currentPage=Math.max(t-1,1)},e.pageToFirst=function(){e.pagingOptions.currentPage=1},e.pageToLast=function(){var t=e.maxPages();e.pagingOptions.currentPage=t},e.cantPageForward=function(){var n=e.pagingOptions.currentPage,o=e.maxPages();return e.totalServerItems>0?n>=o:1>t.data.length},e.cantPageToLast=function(){return e.totalServerItems>0?e.cantPageForward():!0},e.cantPageBackward=function(){var t=e.pagingOptions.currentPage;return 1>=t}},T=function(i,r,l,a,c,g,d,u,f,p,m){var v={aggregateTemplate:void 0,afterSelectionChange:function(){},beforeSelectionChange:function(){return!0},checkboxCellTemplate:void 0,checkboxHeaderTemplate:void 0,columnDefs:void 0,data:[],dataUpdated:function(){},enableCellEdit:!1,enableCellEditOnFocus:!1,enableCellSelection:!1,enableColumnResize:!1,enableColumnReordering:!1,enableColumnHeavyVirt:!1,enablePaging:!1,enablePinning:!1,enableRowSelection:!0,enableSorting:!0,enableHighlighting:!1,excludeProperties:[],filterOptions:{filterText:\"\",useExternalFilter:!1},footerRowHeight:55,footerTemplate:void 0,groups:[],groupsCollapsedByDefault:!0,headerRowHeight:30,headerRowTemplate:void 0,jqueryUIDraggable:!1,jqueryUITheme:!1,keepLastSelected:!0,maintainColumnRatios:void 0,menuTemplate:void 0,multiSelect:!0,pagingOptions:{pageSizes:[250,500,1e3],pageSize:250,currentPage:1},pinSelectionCheckbox:!1,plugins:[],primaryKey:void 0,rowHeight:30,rowTemplate:void 0,selectedItems:[],selectWithCheckboxOnly:!1,showColumnMenu:!1,showFilter:!1,showFooter:!1,showGroupPanel:!1,showSelectionCheckbox:!1,sortInfo:{fields:[],columns:[],directions:[]},tabIndex:-1,totalServerItems:0,useExternalSorting:!1,i18n:\"en\",virtualizationThreshold:50},w=this;w.maxCanvasHt=0,w.config=t.extend(v,e.ngGrid.config,r),w.config.showSelectionCheckbox=w.config.showSelectionCheckbox&&w.config.enableColumnHeavyVirt===!1,w.config.enablePinning=w.config.enablePinning&&w.config.enableColumnHeavyVirt===!1,w.config.selectWithCheckboxOnly=w.config.selectWithCheckboxOnly&&w.config.showSelectionCheckbox!==!1,w.config.pinSelectionCheckbox=w.config.enablePinning,\"string\"==typeof r.columnDefs&&(w.config.columnDefs=i.$eval(r.columnDefs)),w.rowCache=[],w.rowMap=[],w.gridId=\"ng\"+d.newId(),w.$root=null,w.$groupPanel=null,w.$topPanel=null,w.$headerContainer=null,w.$headerScroller=null,w.$headers=null,w.$viewport=null,w.$canvas=null,w.rootDim=w.config.gridDim,w.data=[],w.lateBindColumns=!1,w.filteredRows=[],w.initTemplates=function(){var e=[\"rowTemplate\",\"aggregateTemplate\",\"headerRowTemplate\",\"checkboxCellTemplate\",\"checkboxHeaderTemplate\",\"menuTemplate\",\"footerTemplate\"],t=[];return angular.forEach(e,function(e){t.push(w.getTemplate(e))}),m.all(t)},w.getTemplate=function(e){var t=w.config[e],n=w.gridId+e+\".html\",o=m.defer();if(t&&!h.test(t))p.get(t,{cache:g}).success(function(e){g.put(n,e),o.resolve()}).error(function(){o.reject(\"Could not load template: \"+t)});else if(t)g.put(n,t),o.resolve();else{var i=e+\".html\";g.put(n,g.get(i)),o.resolve()}return o.promise},\"object\"==typeof w.config.data&&(w.data=w.config.data),w.calcMaxCanvasHeight=function(){var e;return e=w.config.groups.length>0?w.rowFactory.parsedData.filter(function(e){return!e[s]}).length*w.config.rowHeight:w.filteredRows.length*w.config.rowHeight},w.elementDims={scrollW:0,scrollH:0,rowIndexCellW:25,rowSelectedCellW:25,rootMaxW:0,rootMaxH:0},w.setRenderedRows=function(e){i.renderedRows.length=e.length;for(var t=0;e.length>t;t++)!i.renderedRows[t]||e[t].isAggRow||i.renderedRows[t].isAggRow?(i.renderedRows[t]=e[t].copy(),i.renderedRows[t].collapsed=e[t].collapsed,e[t].isAggRow||i.renderedRows[t].setVars(e[t])):i.renderedRows[t].setVars(e[t]),i.renderedRows[t].rowIndex=e[t].rowIndex,i.renderedRows[t].offsetTop=e[t].offsetTop,i.renderedRows[t].selected=e[t].selected,e[t].renderedRowIndex=t;w.refreshDomSizes(),i.$emit(\"ngGridEventRows\",e)},w.minRowsToRender=function(){var e=i.viewportDimHeight()||1;return Math.floor(e/w.config.rowHeight)},w.refreshDomSizes=function(){var e=new b;e.outerWidth=w.elementDims.rootMaxW,e.outerHeight=w.elementDims.rootMaxH,w.rootDim=e,w.maxCanvasHt=w.calcMaxCanvasHeight()},w.buildColumnDefsFromData=function(){w.config.columnDefs=[];var e=w.data[0];return e?(d.forIn(e,function(e,t){-1===w.config.excludeProperties.indexOf(t)&&w.config.columnDefs.push({field:t})}),void 0):(w.lateBoundColumns=!0,void 0)},w.buildColumns=function(){var e=w.config.columnDefs,t=[];if(e||(w.buildColumnDefsFromData(),e=w.config.columnDefs),w.config.showSelectionCheckbox&&t.push(new C({colDef:{field:\"✔\",width:w.elementDims.rowSelectedCellW,sortable:!1,resizable:!1,groupable:!1,headerCellTemplate:g.get(i.gridId+\"checkboxHeaderTemplate.html\"),cellTemplate:g.get(i.gridId+\"checkboxCellTemplate.html\"),pinned:w.config.pinSelectionCheckbox},index:0,headerRowHeight:w.config.headerRowHeight,sortCallback:w.sortData,resizeOnDataCallback:w.resizeOnData,enableResize:w.config.enableColumnResize,enableSort:w.config.enableSorting,enablePinning:w.config.enablePinning},i,w,a,g,d)),e.length>0){var n=w.config.showSelectionCheckbox?1:0,o=i.configGroups.length;i.configGroups.length=0,angular.forEach(e,function(e,r){r+=n;var l=new C({colDef:e,index:r+o,originalIndex:r,headerRowHeight:w.config.headerRowHeight,sortCallback:w.sortData,resizeOnDataCallback:w.resizeOnData,enableResize:w.config.enableColumnResize,enableSort:w.config.enableSorting,enablePinning:w.config.enablePinning,enableCellEdit:w.config.enableCellEdit||w.config.enableCellEditOnFocus},i,w,a,g,d),s=w.config.groups.indexOf(e.field);-1!==s&&(l.isGroupedBy=!0,i.configGroups.splice(s,0,l),l.groupIndex=i.configGroups.length),t.push(l)}),i.columns=t,w.config.groups.length>0&&w.rowFactory.getGrouping(w.config.groups)}},w.configureColumnWidths=function(){var e=[],t=[],n=0,o=0,r={};if(angular.forEach(i.columns,function(e,t){if(!d.isNullOrUndefined(e.originalIndex)){var n=e.originalIndex;w.config.showSelectionCheckbox&&(0===e.originalIndex&&e.visible&&(o+=25),n--),r[n]=t}}),angular.forEach(w.config.columnDefs,function(l,a){var s=i.columns[r[a]];l.index=a;var c,g=!1;if(d.isNullOrUndefined(l.width)?l.width=\"*\":(g=isNaN(l.width)?d.endsWith(l.width,\"%\"):!1,c=g?l.width:parseInt(l.width,10)),isNaN(c)&&!i.hasUserChangedGridColumnWidths){if(c=l.width,\"auto\"===c){s.width=s.minWidth,o+=s.width;var u=s;return i.$on(\"ngGridEventData\",function(){w.resizeOnData(u)}),void 0}if(-1!==c.indexOf(\"*\"))return s.visible!==!1&&(n+=c.length),e.push(l),void 0;if(g)return t.push(l),void 0;throw'unable to parse column width, use percentage (\"10%\",\"20%\", etc...) or \"*\" to use remaining width of grid'}s.visible!==!1&&(o+=s.width=parseInt(s.width,10))}),t.length>0){w.config.maintainColumnRatios=w.config.maintainColumnRatios!==!1;var l=0,s=0;angular.forEach(t,function(e){var t=i.columns[r[e.index]],n=e.width,o=parseInt(n.slice(0,-1),10)/100;l+=o,t.visible||(s+=o)});var c=l-s;angular.forEach(t,function(e){var t=i.columns[r[e.index]],n=e.width,a=parseInt(n.slice(0,-1),10)/100;a/=s>0?c:l;var g=w.rootDim.outerWidth*l;t.width=Math.floor(g*a),o+=t.width})}if(e.length>0){w.config.maintainColumnRatios=w.config.maintainColumnRatios!==!1;var g=w.rootDim.outerWidth-o;w.maxCanvasHt>i.viewportDimHeight()&&(g-=a.ScrollW);var u=Math.floor(g/n);angular.forEach(e,function(t,n){var l=i.columns[r[t.index]];l.width=u*t.width.length,l.visible!==!1&&(o+=l.width);var s=n===e.length-1;if(s&&w.rootDim.outerWidth>o){var c=w.rootDim.outerWidth-o;w.maxCanvasHt>i.viewportDimHeight()&&(c-=a.ScrollW),l.width+=c}})}},w.init=function(){return w.initTemplates().then(function(){i.selectionProvider=new D(w,i,f),i.domAccessProvider=new S(w),w.rowFactory=new R(w,i,a,g,d),w.searchProvider=new $(i,w,c),w.styleProvider=new L(i,w),i.$watch(\"configGroups\",function(e){var t=[];angular.forEach(e,function(e){t.push(e.field||e)}),w.config.groups=t,w.rowFactory.filteredRowsChanged(),i.$emit(\"ngGridEventGroups\",e)},!0),i.$watch(\"columns\",function(e){i.isColumnResizing||a.RebuildGrid(i,w),i.$emit(\"ngGridEventColumns\",e)},!0),i.$watch(function(){return r.i18n},function(e){d.seti18n(i,e)}),w.maxCanvasHt=w.calcMaxCanvasHeight(),w.config.sortInfo.fields&&w.config.sortInfo.fields.length>0&&i.$watch(function(){return w.config.sortInfo},function(){l.isSorting||(w.sortColumnsInit(),i.$emit(\"ngGridEventSorted\",w.config.sortInfo))},!0)})},w.resizeOnData=function(e){var n=e.minWidth,o=d.getElementsByClassName(\"col\"+e.index);angular.forEach(o,function(e,o){var i;if(0===o){var r=t(e).find(\".ngHeaderText\");i=d.visualLength(r)+10}else{var l=t(e).find(\".ngCellText\");i=d.visualLength(l)+10}i>n&&(n=i)}),e.width=e.longest=Math.min(e.maxWidth,n+7),a.BuildStyles(i,w,!0)},w.lastSortedColumns=[],w.sortData=function(e,n){if(n&&n.shiftKey&&w.config.sortInfo){var o=w.config.sortInfo.columns.indexOf(e);-1===o?(1===w.config.sortInfo.columns.length&&(w.config.sortInfo.columns[0].sortPriority=1),w.config.sortInfo.columns.push(e),e.sortPriority=w.config.sortInfo.columns.length,w.config.sortInfo.fields.push(e.field),w.config.sortInfo.directions.push(e.sortDirection),w.lastSortedColumns.push(e)):w.config.sortInfo.directions[o]=e.sortDirection}else{var r=t.isArray(e);w.config.sortInfo.columns.length=0,w.config.sortInfo.fields.length=0,w.config.sortInfo.directions.length=0;var l=function(e){w.config.sortInfo.columns.push(e),w.config.sortInfo.fields.push(e.field),w.config.sortInfo.directions.push(e.sortDirection),w.lastSortedColumns.push(e)};r?(w.clearSortingData(),angular.forEach(e,function(e,t){e.sortPriority=t+1,l(e)})):(w.clearSortingData(e),e.sortPriority=void 0,l(e))}w.sortActual(),w.searchProvider.evalFilter(),i.$emit(\"ngGridEventSorted\",w.config.sortInfo)},w.sortColumnsInit=function(){w.config.sortInfo.columns?w.config.sortInfo.columns.length=0:w.config.sortInfo.columns=[],angular.forEach(i.columns,function(e){var t=w.config.sortInfo.fields.indexOf(e.field);-1!==t&&(e.sortDirection=w.config.sortInfo.directions[t]||\"asc\",w.config.sortInfo.columns[t]=e)}),angular.forEach(w.config.sortInfo.columns,function(e){w.sortData(e)})},w.sortActual=function(){if(!w.config.useExternalSorting){var e=w.data.slice(0);angular.forEach(e,function(e,t){var n=w.rowMap[t];if(void 0!==n){var o=w.rowCache[n];void 0!==o&&(e.preSortSelected=o.selected,e.preSortIndex=t)}}),l.Sort(w.config.sortInfo,e),angular.forEach(e,function(e,t){w.rowCache[t].entity=e,w.rowCache[t].selected=e.preSortSelected,w.rowMap[e.preSortIndex]=t,delete e.preSortSelected,delete e.preSortIndex})}},w.clearSortingData=function(e){e?(angular.forEach(w.lastSortedColumns,function(t){e.index!==t.index&&(t.sortDirection=\"\",t.sortPriority=null)}),w.lastSortedColumns[0]=e,w.lastSortedColumns.length=1):(angular.forEach(w.lastSortedColumns,function(e){e.sortDirection=\"\",e.sortPriority=null}),w.lastSortedColumns=[])},w.fixColumnIndexes=function(){for(var e=0;i.columns.length>e;e++)i.columns[e].index=e},w.fixGroupIndexes=function(){angular.forEach(i.configGroups,function(e,t){e.groupIndex=t+1})},i.elementsNeedMeasuring=!0,i.columns=[],i.renderedRows=[],i.renderedColumns=[],i.headerRow=null,i.rowHeight=w.config.rowHeight,i.jqueryUITheme=w.config.jqueryUITheme,i.showSelectionCheckbox=w.config.showSelectionCheckbox,i.enableCellSelection=w.config.enableCellSelection,i.enableCellEditOnFocus=w.config.enableCellEditOnFocus,i.footer=null,i.selectedItems=w.config.selectedItems,i.multiSelect=w.config.multiSelect,i.showFooter=w.config.showFooter,i.footerRowHeight=i.showFooter?w.config.footerRowHeight:0,i.showColumnMenu=w.config.showColumnMenu,i.showMenu=!1,i.configGroups=[],i.gridId=w.gridId,i.enablePaging=w.config.enablePaging,i.pagingOptions=w.config.pagingOptions,i.i18n={},d.seti18n(i,w.config.i18n),i.adjustScrollLeft=function(e){for(var t=0,n=0,o=i.columns.length,r=[],l=!w.config.enableColumnHeavyVirt,s=0,c=function(e){l?r.push(e):i.renderedColumns[s]?i.renderedColumns[s].setVars(e):i.renderedColumns[s]=e.copy(),s++},g=0;o>g;g++){var d=i.columns[g];if(d.visible!==!1){var u=d.width+t;if(d.pinned){c(d);var f=g>0?e+n:e;a.setColLeft(d,f,w),n+=d.width}else u>=e&&e+w.rootDim.outerWidth>=t&&c(d);t+=d.width}}l&&(i.renderedColumns=r)},w.prevScrollTop=0,w.prevScrollIndex=0,i.adjustScrollTop=function(e,t){if(w.prevScrollTop!==e||t){e>0&&w.$viewport[0].scrollHeight-e<=w.$viewport.outerHeight()&&i.$emit(\"ngGridEventScroll\");\n    var r,l=Math.floor(e/w.config.rowHeight);if(w.filteredRows.length>w.config.virtualizationThreshold){if(e>w.prevScrollTop&&w.prevScrollIndex+o>l)return;if(w.prevScrollTop>e&&l>w.prevScrollIndex-o)return;r=new P(Math.max(0,l-n),l+w.minRowsToRender()+n)}else{var a=i.configGroups.length>0?w.rowFactory.parsedData.length:w.data.length;r=new P(0,Math.max(a,w.minRowsToRender()+n))}w.prevScrollTop=e,w.rowFactory.UpdateViewableRange(r),w.prevScrollIndex=l}},i.toggleShowMenu=function(){i.showMenu=!i.showMenu},i.toggleSelectAll=function(e,t){i.selectionProvider.toggleSelectAll(e,!1,t)},i.totalFilteredItemsLength=function(){return w.filteredRows.length},i.showGroupPanel=function(){return w.config.showGroupPanel},i.topPanelHeight=function(){return w.config.showGroupPanel===!0?w.config.headerRowHeight+32:w.config.headerRowHeight},i.viewportDimHeight=function(){return Math.max(0,w.rootDim.outerHeight-i.topPanelHeight()-i.footerRowHeight-2)},i.groupBy=function(e){if(!(1>w.data.length)&&e.groupable&&e.field){e.sortDirection||e.sort({shiftKey:i.configGroups.length>0?!0:!1});var t=i.configGroups.indexOf(e);-1===t?(e.isGroupedBy=!0,i.configGroups.push(e),e.groupIndex=i.configGroups.length):i.removeGroup(t),w.$viewport.scrollTop(0),a.digest(i)}},i.removeGroup=function(e){var t=i.columns.filter(function(t){return t.groupIndex===e+1})[0];t.isGroupedBy=!1,t.groupIndex=0,i.columns[e].isAggCol&&(i.columns.splice(e,1),i.configGroups.splice(e,1),w.fixGroupIndexes()),0===i.configGroups.length&&(w.fixColumnIndexes(),a.digest(i)),i.adjustScrollLeft(0)},i.togglePin=function(e){for(var t=e.index,n=0,o=0;i.columns.length>o&&i.columns[o].pinned;o++)n++;e.pinned&&(n=Math.max(e.originalIndex,n-1)),e.pinned=!e.pinned,i.columns.splice(t,1),i.columns.splice(n,0,e),w.fixColumnIndexes(),a.BuildStyles(i,w,!0),w.$viewport.scrollLeft(w.$viewport.scrollLeft()-e.width)},i.totalRowWidth=function(){for(var e=0,t=i.columns,n=0;t.length>n;n++)t[n].visible!==!1&&(e+=t[n].width);return e},i.headerScrollerDim=function(){var e=i.viewportDimHeight(),t=w.maxCanvasHt,n=t>e,o=new b;return o.autoFitHeight=!0,o.outerWidth=i.totalRowWidth(),n?o.outerWidth+=w.elementDims.scrollW:w.elementDims.scrollH>=t-e&&(o.outerWidth+=w.elementDims.scrollW),o}},P=function(e,t){this.topRow=e,this.bottomRow=t},I=function(e,t,n,o,i){this.entity=e,this.config=t,this.selectionProvider=n,this.rowIndex=o,this.utils=i,this.selected=n.getSelection(e),this.cursor=this.config.enableRowSelection?\"pointer\":\"default\",this.beforeSelectionChange=t.beforeSelectionChangeCallback,this.afterSelectionChange=t.afterSelectionChangeCallback,this.offsetTop=this.rowIndex*t.rowHeight,this.rowDisplayIndex=0};I.prototype.setSelection=function(e){this.selectionProvider.setSelection(this,e),this.selectionProvider.lastClickedRow=this},I.prototype.continueSelection=function(e){this.selectionProvider.ChangeSelection(this,e)},I.prototype.ensureEntity=function(e){this.entity!==e&&(this.entity=e,this.selected=this.selectionProvider.getSelection(this.entity))},I.prototype.toggleSelected=function(e){if(!this.config.enableRowSelection&&!this.config.enableCellSelection)return!0;var t=e.target||e;return\"checkbox\"===t.type&&\"ngSelectionCell ng-scope\"!==t.parentElement.className?!0:this.config.selectWithCheckboxOnly&&\"checkbox\"!==t.type?(this.selectionProvider.lastClickedRow=this,!0):(this.beforeSelectionChange(this,e)&&this.continueSelection(e),!1)},I.prototype.alternatingRowClass=function(){var e=0===this.rowIndex%2,t={ngRow:!0,selected:this.selected,even:e,odd:!e,\"ui-state-default\":this.config.jqueryUITheme&&e,\"ui-state-active\":this.config.jqueryUITheme&&!e};return t},I.prototype.getProperty=function(e){return this.utils.evalProperty(this.entity,e)},I.prototype.copy=function(){return this.clone=new I(this.entity,this.config,this.selectionProvider,this.rowIndex,this.utils),this.clone.isClone=!0,this.clone.elm=this.elm,this.clone.orig=this,this.clone},I.prototype.setVars=function(e){e.clone=this,this.entity=e.entity,this.selected=e.selected,this.orig=e};var R=function(e,t,o,i,r){var g=this;g.aggCache={},g.parentCache=[],g.dataChanged=!0,g.parsedData=[],g.rowConfig={},g.selectionProvider=t.selectionProvider,g.rowHeight=30,g.numberOfAggregates=0,g.groupedData=void 0,g.rowHeight=e.config.rowHeight,g.rowConfig={enableRowSelection:e.config.enableRowSelection,rowClasses:e.config.rowClasses,selectedItems:t.selectedItems,selectWithCheckboxOnly:e.config.selectWithCheckboxOnly,beforeSelectionChangeCallback:e.config.beforeSelectionChange,afterSelectionChangeCallback:e.config.afterSelectionChange,jqueryUITheme:e.config.jqueryUITheme,enableCellSelection:e.config.enableCellSelection,rowHeight:e.config.rowHeight},g.renderedRange=new P(0,e.minRowsToRender()+n),g.buildEntityRow=function(e,t){return new I(e,g.rowConfig,g.selectionProvider,t,r)},g.buildAggregateRow=function(t,n){var o=g.aggCache[t.aggIndex];return o||(o=new w(t,g,g.rowConfig.rowHeight,e.config.groupsCollapsedByDefault),g.aggCache[t.aggIndex]=o),o.rowIndex=n,o.offsetTop=n*g.rowConfig.rowHeight,o},g.UpdateViewableRange=function(e){g.renderedRange=e,g.renderedChange()},g.filteredRowsChanged=function(){e.lateBoundColumns&&e.filteredRows.length>0&&(e.config.columnDefs=void 0,e.buildColumns(),e.lateBoundColumns=!1,t.$evalAsync(function(){t.adjustScrollLeft(0)})),g.dataChanged=!0,e.config.groups.length>0&&g.getGrouping(e.config.groups),g.UpdateViewableRange(g.renderedRange)},g.renderedChange=function(){if(!g.groupedData||1>e.config.groups.length)return g.renderedChangeNoGroups(),e.refreshDomSizes(),void 0;g.wasGrouped=!0,g.parentCache=[];var t=0,n=g.parsedData.filter(function(e){return e.isAggRow?e.parent&&e.parent.collapsed?!1:!0:(e[s]||(e.rowIndex=t++),!e[s])});g.totalRows=n.length;for(var o=[],i=g.renderedRange.topRow;g.renderedRange.bottomRow>i;i++)n[i]&&(n[i].offsetTop=i*e.config.rowHeight,o.push(n[i]));e.setRenderedRows(o)},g.renderedChangeNoGroups=function(){for(var t=[],n=g.renderedRange.topRow;g.renderedRange.bottomRow>n;n++)e.filteredRows[n]&&(e.filteredRows[n].rowIndex=n,e.filteredRows[n].offsetTop=n*e.config.rowHeight,t.push(e.filteredRows[n]));e.setRenderedRows(t)},g.fixRowCache=function(){var t=e.data.length,n=t-e.rowCache.length;if(0>n)e.rowCache.length=e.rowMap.length=t;else for(var o=e.rowCache.length;t>o;o++)e.rowCache[o]=e.rowFactory.buildEntityRow(e.data[o],o)},g.parseGroupData=function(e){if(e.values)for(var t=0;e.values.length>t;t++)g.parentCache[g.parentCache.length-1].children.push(e.values[t]),g.parsedData.push(e.values[t]);else for(var n in e)if(n!==l&&n!==a&&n!==c&&e.hasOwnProperty(n)){var o=g.buildAggregateRow({gField:e[l],gLabel:n,gDepth:e[a],isAggRow:!0,_ng_hidden_:!1,children:[],aggChildren:[],aggIndex:g.numberOfAggregates,aggLabelFilter:e[c].aggLabelFilter},0);g.numberOfAggregates++,o.parent=g.parentCache[o.depth-1],o.parent&&(o.parent.collapsed=!1,o.parent.aggChildren.push(o)),g.parsedData.push(o),g.parentCache[o.depth]=o,g.parseGroupData(e[n])}},g.getGrouping=function(n){function d(e,t){return e.filter(function(e){return e.field===t})}g.aggCache=[],g.numberOfAggregates=0,g.groupedData={};for(var u=e.filteredRows,f=n.length,h=t.columns,p=0;u.length>p;p++){var m=u[p].entity;if(!m)return;u[p][s]=e.config.groupsCollapsedByDefault;for(var v=g.groupedData,w=0;n.length>w;w++){var b=n[w],S=d(h,b)[0],x=r.evalProperty(m,b);x=x?\"\"+x:\"null\",v[x]||(v[x]={}),v[l]||(v[l]=b),v[a]||(v[a]=w),v[c]||(v[c]=S),v=v[x]}v.values||(v.values=[]),v.values.push(u[p])}if(h.length>0)for(var y=0;n.length>y;y++)!h[y].isAggCol&&f>=y&&h.splice(0,0,new C({colDef:{field:\"\",width:25,sortable:!1,resizable:!1,headerCellTemplate:'<div class=\"ngAggHeader\"></div>',pinned:e.config.pinSelectionCheckbox},enablePinning:e.config.enablePinning,isAggCol:!0,headerRowHeight:e.config.headerRowHeight},t,e,o,i,r));e.fixColumnIndexes(),t.adjustScrollLeft(0),g.parsedData.length=0,g.parseGroupData(g.groupedData),g.fixRowCache()},e.config.groups.length>0&&e.filteredRows.length>0&&g.getGrouping(e.config.groups)},$=function(e,n,o){var i=this,r=[];i.extFilter=n.config.filterOptions.useExternalFilter,e.showFilter=n.config.showFilter,e.filterText=\"\",i.fieldMap={};var l=function(e,t,n){var i;for(var r in t)if(t.hasOwnProperty(r)){var a=n[r.toLowerCase()];if(!a)continue;var s=t[r];if(\"object\"==typeof s)return l(e,s,a);var c=null,g=null;if(a&&a.cellFilter&&(g=a.cellFilter.split(\":\"),c=o(g[0])),null!==s&&void 0!==s){if(\"function\"==typeof c){var d=\"\"+c(s,g[1]);i=e.regex.test(d)}else i=e.regex.test(\"\"+s);if(i)return!0}}return!1},a=function(e,t){var n,r=i.fieldMap[e.columnDisplay];if(!r)return!1;var l=r.cellFilter.split(\":\"),a=r.cellFilter?o(l[0]):null,s=t[e.column]||t[r.field.split(\".\")[0]];if(null===s||void 0===s)return!1;if(\"function\"==typeof a){var g=\"\"+a(\"object\"==typeof s?c(s,r.field):s,l[1]);n=e.regex.test(g)}else n=e.regex.test(\"object\"==typeof s?\"\"+c(s,r.field):\"\"+s);return n?!0:!1},s=function(e){for(var t=0,n=r.length;n>t;t++){var o,s=r[t];if(o=s.column?a(s,e):l(s,e,i.fieldMap),!o)return!1}return!0};i.evalFilter=function(){n.filteredRows=0===r.length?n.rowCache:n.rowCache.filter(function(e){return s(e.entity)});for(var e=0;n.filteredRows.length>e;e++)n.filteredRows[e].rowIndex=e;n.rowFactory.filteredRowsChanged()};var c=function(e,t){if(\"object\"!=typeof e||\"string\"!=typeof t)return e;var n=t.split(\".\"),o=e;if(n.length>1){for(var i=1,r=n.length;r>i;i++)if(o=o[n[i]],!o)return e;return o}return e},g=function(e,t){try{return RegExp(e,t)}catch(n){return RegExp(e.replace(/(\\^|\\$|\\(|\\)|<|>|\\[|\\]|\\{|\\}|\\\\|\\||\\.|\\*|\\+|\\?)/g,\"\\\\$1\"))}},d=function(e){r=[];var n;if(n=t.trim(e))for(var o=n.split(\";\"),i=0;o.length>i;i++){var l=o[i].split(\":\");if(l.length>1){var a=t.trim(l[0]),s=t.trim(l[1]);a&&s&&r.push({column:a,columnDisplay:a.replace(/\\s+/g,\"\").toLowerCase(),regex:g(s,\"i\")})}else{var c=t.trim(l[0]);c&&r.push({column:\"\",regex:g(c,\"i\")})}}};i.extFilter||e.$watch(\"columns\",function(e){for(var t=0;e.length>t;t++){var n=e[t];if(n.field)if(n.field.match(/\\./g)){for(var o=n.field.split(\".\"),r=i.fieldMap,l=0;o.length-1>l;l++)r[o[l]]=r[o[l]]||{},r=r[o[l]];r[o[o.length-1]]=n}else i.fieldMap[n.field.toLowerCase()]=n;n.displayName&&(i.fieldMap[n.displayName.toLowerCase().replace(/\\s+/g,\"\")]=n)}}),e.$watch(function(){return n.config.filterOptions.filterText},function(t){e.filterText=t}),e.$watch(\"filterText\",function(t){i.extFilter||(e.$emit(\"ngGridEventFilter\",t),d(t),i.evalFilter())})},D=function(e,t,n){var o=this;o.multi=e.config.multiSelect,o.selectedItems=e.config.selectedItems,o.selectedIndex=e.config.selectedIndex,o.lastClickedRow=void 0,o.ignoreSelectedItemChanges=!1,o.pKeyParser=n(e.config.primaryKey),o.ChangeSelection=function(n,i){var r=i.which||i.keyCode,l=40===r||38===r;if(i&&i.shiftKey&&!i.keyCode&&o.multi&&e.config.enableRowSelection){if(o.lastClickedRow){var a;a=t.configGroups.length>0?e.rowFactory.parsedData.filter(function(e){return!e.isAggRow}):e.filteredRows;var s=n.rowIndex,c=o.lastClickedRowIndex;if(s===c)return!1;c>s?(s^=c,c=s^c,s^=c,s--):c++;for(var g=[];s>=c;c++)g.push(a[c]);if(g[g.length-1].beforeSelectionChange(g,i)){for(var d=0;g.length>d;d++){var u=g[d],f=u.selected;u.selected=!f,u.clone&&(u.clone.selected=u.selected);var h=o.selectedItems.indexOf(u.entity);-1===h?o.selectedItems.push(u.entity):o.selectedItems.splice(h,1)}g[g.length-1].afterSelectionChange(g,i)}return o.lastClickedRow=n,o.lastClickedRowIndex=n.rowIndex,!0}}else o.multi?(!i.keyCode||l&&!e.config.selectWithCheckboxOnly)&&o.setSelection(n,!n.selected):o.lastClickedRow===n?o.setSelection(o.lastClickedRow,e.config.keepLastSelected?!0:!n.selected):(o.lastClickedRow&&o.setSelection(o.lastClickedRow,!1),o.setSelection(n,!n.selected));return o.lastClickedRow=n,o.lastClickedRowIndex=n.rowIndex,!0},o.getSelection=function(t){var n=!1;if(e.config.primaryKey){var i=o.pKeyParser(t);angular.forEach(o.selectedItems,function(e){i===o.pKeyParser(e)&&(n=!0)})}else n=-1!==o.selectedItems.indexOf(t);return n},o.setSelection=function(t,n){if(e.config.enableRowSelection){if(n)-1===o.selectedItems.indexOf(t.entity)&&(!o.multi&&o.selectedItems.length>0&&o.toggleSelectAll(!1,!0),o.selectedItems.push(t.entity));else{var i=o.selectedItems.indexOf(t.entity);-1!==i&&o.selectedItems.splice(i,1)}t.selected=n,t.orig&&(t.orig.selected=n),t.clone&&(t.clone.selected=n),t.afterSelectionChange(t)}},o.toggleSelectAll=function(t,n,i){var r=i?e.filteredRows:e.rowCache;if(n||e.config.beforeSelectionChange(r,t)){var l=o.selectedItems.length;l>0&&(o.selectedItems.length=0);for(var a=0;r.length>a;a++)r[a].selected=t,r[a].clone&&(r[a].clone.selected=t),t&&o.selectedItems.push(r[a].entity);n||e.config.afterSelectionChange(r,t)}}},L=function(e,t){e.headerCellStyle=function(e){return{height:e.headerRowHeight+\"px\"}},e.rowStyle=function(t){var n={top:t.offsetTop+\"px\",height:e.rowHeight+\"px\"};return t.isAggRow&&(n.left=t.offsetLeft),n},e.canvasStyle=function(){return{height:t.maxCanvasHt+\"px\"}},e.headerScrollerStyle=function(){return{height:t.config.headerRowHeight+\"px\"}},e.topPanelStyle=function(){return{width:t.rootDim.outerWidth+\"px\",height:e.topPanelHeight()+\"px\"}},e.headerStyle=function(){return{width:t.rootDim.outerWidth+\"px\",height:t.config.headerRowHeight+\"px\"}},e.groupPanelStyle=function(){return{width:t.rootDim.outerWidth+\"px\",height:\"32px\"}},e.viewportStyle=function(){return{width:t.rootDim.outerWidth+\"px\",height:e.viewportDimHeight()+\"px\"}},e.footerStyle=function(){return{width:t.rootDim.outerWidth+\"px\",height:e.footerRowHeight+\"px\"}}};p.directive(\"ngCellHasFocus\",[\"$domUtilityService\",function(e){var t=function(t){t.isFocused=!0,e.digest(t),t.$broadcast(\"ngGridEventStartCellEdit\"),t.$on(\"ngGridEventEndCellEdit\",function(){t.isFocused=!1,e.digest(t)})};return function(e,n){var o=!1,i=!1;e.editCell=function(){e.enableCellEditOnFocus||setTimeout(function(){t(e,n)},0)},n.bind(\"mousedown\",function(){return e.enableCellEditOnFocus?i=!0:n.focus(),!0}),n.bind(\"click\",function(o){e.enableCellEditOnFocus&&(o.preventDefault(),i=!1,t(e,n))}),n.bind(\"focus\",function(){return o=!0,e.enableCellEditOnFocus&&!i&&t(e,n),!0}),n.bind(\"blur\",function(){return o=!1,!0}),n.bind(\"keydown\",function(i){return e.enableCellEditOnFocus||(o&&37!==i.keyCode&&38!==i.keyCode&&39!==i.keyCode&&40!==i.keyCode&&9!==i.keyCode&&!i.shiftKey&&13!==i.keyCode&&t(e,n),o&&i.shiftKey&&i.keyCode>=65&&90>=i.keyCode&&t(e,n),27===i.keyCode&&n.focus()),!0})}}]),p.directive(\"ngCellText\",function(){return function(e,t){t.bind(\"mouseover\",function(e){e.preventDefault(),t.css({cursor:\"text\"})}),t.bind(\"mouseleave\",function(e){e.preventDefault(),t.css({cursor:\"default\"})})}}),p.directive(\"ngCell\",[\"$compile\",\"$domUtilityService\",function(e,t){var n={scope:!1,compile:function(){return{pre:function(t,n){var o,i=t.col.cellTemplate.replace(d,\"row.entity.\"+t.col.field);t.col.enableCellEdit?(o=t.col.cellEditTemplate,o=o.replace(u,i),o=o.replace(f,t.col.editableCellTemplate.replace(d,\"row.entity.\"+t.col.field))):o=i;var r=e(o)(t);t.enableCellSelection&&-1===r[0].className.indexOf(\"ngSelectionCell\")&&(r[0].setAttribute(\"tabindex\",0),r.addClass(\"ngCellElement\")),n.append(r)},post:function(e,n){e.enableCellSelection&&e.domAccessProvider.selectionHandlers(e,n),e.$on(\"ngGridEventDigestCell\",function(){t.digest(e)})}}}};return n}]),p.directive(\"ngEditCellIf\",[function(){return{transclude:\"element\",priority:1e3,terminal:!0,restrict:\"A\",compile:function(e,t,n){return function(e,t,o){var i,r;e.$watch(o.ngEditCellIf,function(o){i&&(i.remove(),i=void 0),r&&(r.$destroy(),r=void 0),o&&(r=e.$new(),n(r,function(e){i=e,t.after(e)}))})}}}}]),p.directive(\"ngGridFooter\",[\"$compile\",\"$templateCache\",function(e,t){var n={scope:!1,compile:function(){return{pre:function(n,o){0===o.children().length&&o.append(e(t.get(n.gridId+\"footerTemplate.html\"))(n))}}}};return n}]),p.directive(\"ngGridMenu\",[\"$compile\",\"$templateCache\",function(e,t){var n={scope:!1,compile:function(){return{pre:function(n,o){0===o.children().length&&o.append(e(t.get(n.gridId+\"menuTemplate.html\"))(n))}}}};return n}]),p.directive(\"ngGrid\",[\"$compile\",\"$filter\",\"$templateCache\",\"$sortService\",\"$domUtilityService\",\"$utilityService\",\"$timeout\",\"$parse\",\"$http\",\"$q\",function(e,n,o,i,r,l,a,s,c,g){var d={scope:!0,compile:function(){return{pre:function(d,u,f){var h=t(u),p=d.$eval(f.ngGrid);p.gridDim=new b({outerHeight:t(h).height(),outerWidth:t(h).width()});var m=new T(d,p,i,r,n,o,l,a,s,c,g);return m.init().then(function(){if(\"string\"==typeof p.columnDefs?d.$parent.$watch(p.columnDefs,function(e){return e?(m.lateBoundColumns=!1,d.columns=[],m.config.columnDefs=e,m.buildColumns(),m.eventProvider.assignEvents(),r.RebuildGrid(d,m),void 0):(m.refreshDomSizes(),m.buildColumns(),void 0)},!0):m.buildColumns(),\"string\"==typeof p.totalServerItems?d.$parent.$watch(p.totalServerItems,function(e){d.totalServerItems=angular.isDefined(e)?e:0}):d.totalServerItems=0,\"string\"==typeof p.data){var n=function(e){m.data=t.extend([],e),m.rowFactory.fixRowCache(),angular.forEach(m.data,function(e,t){var n=m.rowMap[t]||t;m.rowCache[n]&&m.rowCache[n].ensureEntity(e),m.rowMap[n]=t}),m.searchProvider.evalFilter(),m.configureColumnWidths(),m.refreshDomSizes(),m.config.sortInfo.fields.length>0&&(m.sortColumnsInit(),d.$emit(\"ngGridEventSorted\",m.config.sortInfo)),d.$emit(\"ngGridEventData\",m.gridId)};d.$parent.$watch(p.data,n),d.$parent.$watch(p.data+\".length\",function(){n(d.$eval(p.data))})}return m.footerController=new y(d,m),u.addClass(\"ngGrid\").addClass(\"\"+m.gridId),p.enableHighlighting||u.addClass(\"unselectable\"),p.jqueryUITheme&&u.addClass(\"ui-widget\"),u.append(e(o.get(\"gridTemplate.html\"))(d)),r.AssignGridContainers(d,u,m),m.eventProvider=new x(m,d,r,a),p.selectRow=function(e,t){m.rowCache[e]&&(m.rowCache[e].clone&&m.rowCache[e].clone.setSelection(t?!0:!1),m.rowCache[e].setSelection(t?!0:!1))},p.selectItem=function(e,t){p.selectRow(m.rowMap[e],t)},p.selectAll=function(e){d.toggleSelectAll(e)},p.selectVisible=function(e){d.toggleSelectAll(e,!0)},p.groupBy=function(e){if(e)d.groupBy(d.columns.filter(function(t){return t.field===e})[0]);else{var n=t.extend(!0,[],d.configGroups);angular.forEach(n,d.groupBy)}},p.sortBy=function(e){var t=d.columns.filter(function(t){return t.field===e})[0];t&&t.sort()},p.gridId=m.gridId,p.ngGrid=m,p.$gridScope=d,p.$gridServices={SortService:i,DomUtilityService:r,UtilityService:l},d.$on(\"ngGridEventDigestGrid\",function(){r.digest(d.$parent)}),d.$on(\"ngGridEventDigestGridParent\",function(){r.digest(d.$parent)}),d.$evalAsync(function(){d.adjustScrollLeft(0)}),angular.forEach(p.plugins,function(e){\"function\"==typeof e&&(e=new e),e.init(d.$new(),m,p.$gridServices),p.plugins[l.getInstanceType(e)]=e}),\"function\"==typeof p.init&&p.init(m,d),null})}}}};return d}]),p.directive(\"ngHeaderCell\",[\"$compile\",function(e){var t={scope:!1,compile:function(){return{pre:function(t,n){n.append(e(t.col.headerCellTemplate)(t))}}}};return t}]),p.directive(\"ngInput\",[function(){return{require:\"ngModel\",link:function(e,t,n,o){var i,r=e.$watch(\"ngModel\",function(){i=o.$modelValue,r()});t.bind(\"keydown\",function(n){switch(n.keyCode){case 37:case 38:case 39:case 40:n.stopPropagation();break;case 27:e.$$phase||e.$apply(function(){o.$setViewValue(i),t.blur()});break;case 13:(e.enableCellEditOnFocus&&e.totalFilteredItemsLength()-1>e.row.rowIndex&&e.row.rowIndex>0||e.enableCellEdit)&&t.blur()}return!0}),t.bind(\"click\",function(e){e.stopPropagation()}),t.bind(\"mousedown\",function(e){e.stopPropagation()}),e.$on(\"ngGridEventStartCellEdit\",function(){t.focus(),t.select()}),angular.element(t).bind(\"blur\",function(){e.$emit(\"ngGridEventEndCellEdit\")})}}}]),p.directive(\"ngRow\",[\"$compile\",\"$domUtilityService\",\"$templateCache\",function(e,t,n){var o={scope:!1,compile:function(){return{pre:function(o,i){if(o.row.elm=i,o.row.clone&&(o.row.clone.elm=i),o.row.isAggRow){var r=n.get(o.gridId+\"aggregateTemplate.html\");r=o.row.aggLabelFilter?r.replace(g,\"| \"+o.row.aggLabelFilter):r.replace(g,\"\"),i.append(e(r)(o))}else i.append(e(n.get(o.gridId+\"rowTemplate.html\"))(o));o.$on(\"ngGridEventDigestRow\",function(){t.digest(o)})}}}};return o}]),p.directive(\"ngViewport\",[function(){return function(e,t){var n,o,i=0;t.bind(\"scroll\",function(t){var r=t.target.scrollLeft,l=t.target.scrollTop;return e.$headerContainer&&e.$headerContainer.scrollLeft(r),e.adjustScrollLeft(r),e.adjustScrollTop(l),e.$root.$$phase||e.$digest(),o=r,i=l,n=!1,!0}),t.bind(\"mousewheel DOMMouseScroll\",function(){return n=!0,t.focus&&t.focus(),!0}),e.enableCellSelection||e.domAccessProvider.selectionHandlers(e,t)}}]),e.ngGrid.i18n.da={ngAggregateLabel:\"artikler\",ngGroupPanelDescription:\"Grupér rækker udfra en kolonne ved at trække dens overskift hertil.\",ngSearchPlaceHolder:\"Søg...\",ngMenuText:\"Vælg kolonner:\",ngShowingItemsLabel:\"Viste rækker:\",ngTotalItemsLabel:\"Rækker totalt:\",ngSelectedItemsLabel:\"Valgte rækker:\",ngPageSizeLabel:\"Side størrelse:\",ngPagerFirstTitle:\"Første side\",ngPagerNextTitle:\"Næste side\",ngPagerPrevTitle:\"Forrige side\",ngPagerLastTitle:\"Sidste side\"},e.ngGrid.i18n.de={ngAggregateLabel:\"artikel\",ngGroupPanelDescription:\"Ziehen Sie eine Spaltenüberschrift hier und legen Sie es der Gruppe nach dieser Spalte.\",ngSearchPlaceHolder:\"Suche...\",ngMenuText:\"Spalten auswählen:\",ngShowingItemsLabel:\"Zeige Artikel:\",ngTotalItemsLabel:\"Meiste Artikel:\",ngSelectedItemsLabel:\"Ausgewählte Artikel:\",ngPageSizeLabel:\"Größe Seite:\",ngPagerFirstTitle:\"Erste Page\",ngPagerNextTitle:\"Nächste Page\",ngPagerPrevTitle:\"Vorherige Page\",ngPagerLastTitle:\"Letzte Page\"},e.ngGrid.i18n.en={ngAggregateLabel:\"items\",ngGroupPanelDescription:\"Drag a column header here and drop it to group by that column.\",ngSearchPlaceHolder:\"Search...\",ngMenuText:\"Choose Columns:\",ngShowingItemsLabel:\"Showing Items:\",ngTotalItemsLabel:\"Total Items:\",ngSelectedItemsLabel:\"Selected Items:\",ngPageSizeLabel:\"Page Size:\",ngPagerFirstTitle:\"First Page\",ngPagerNextTitle:\"Next Page\",ngPagerPrevTitle:\"Previous Page\",ngPagerLastTitle:\"Last Page\"},e.ngGrid.i18n.es={ngAggregateLabel:\"Artículos\",ngGroupPanelDescription:\"Arrastre un encabezado de columna aquí y soltarlo para agrupar por esa columna.\",ngSearchPlaceHolder:\"Buscar...\",ngMenuText:\"Elegir columnas:\",ngShowingItemsLabel:\"Artículos Mostrando:\",ngTotalItemsLabel:\"Artículos Totales:\",ngSelectedItemsLabel:\"Artículos Seleccionados:\",ngPageSizeLabel:\"Tamaño de Página:\",ngPagerFirstTitle:\"Primera Página\",ngPagerNextTitle:\"Página Siguiente\",ngPagerPrevTitle:\"Página Anterior\",ngPagerLastTitle:\"Última Página\"},e.ngGrid.i18n.fr={ngAggregateLabel:\"articles\",ngGroupPanelDescription:\"Faites glisser un en-tête de colonne ici et déposez-le vers un groupe par cette colonne.\",ngSearchPlaceHolder:\"Recherche...\",ngMenuText:\"Choisir des colonnes:\",ngShowingItemsLabel:\"Articles Affichage des:\",ngTotalItemsLabel:\"Nombre total d'articles:\",ngSelectedItemsLabel:\"Éléments Articles:\",ngPageSizeLabel:\"Taille de page:\",ngPagerFirstTitle:\"Première page\",ngPagerNextTitle:\"Page Suivante\",ngPagerPrevTitle:\"Page précédente\",ngPagerLastTitle:\"Dernière page\"},e.ngGrid.i18n[\"pt-br\"]={ngAggregateLabel:\"items\",ngGroupPanelDescription:\"Arraste e solte uma coluna aqui para agrupar por essa coluna\",ngSearchPlaceHolder:\"Procurar...\",ngMenuText:\"Selecione as colunas:\",ngShowingItemsLabel:\"Mostrando os Items:\",ngTotalItemsLabel:\"Total de Items:\",ngSelectedItemsLabel:\"Items Selecionados:\",ngPageSizeLabel:\"Tamanho da Página:\",ngPagerFirstTitle:\"Primeira Página\",ngPagerNextTitle:\"Próxima Página\",ngPagerPrevTitle:\"Página Anterior\",ngPagerLastTitle:\"Última Página\"},e.ngGrid.i18n[\"zh-cn\"]={ngAggregateLabel:\"条目\",ngGroupPanelDescription:\"拖曳表头到此处以进行分组\",ngSearchPlaceHolder:\"搜索...\",ngMenuText:\"数据分组与选择列：\",ngShowingItemsLabel:\"当前显示条目：\",ngTotalItemsLabel:\"条目总数：\",ngSelectedItemsLabel:\"选中条目：\",ngPageSizeLabel:\"每页显示数：\",ngPagerFirstTitle:\"回到首页\",ngPagerNextTitle:\"下一页\",ngPagerPrevTitle:\"上一页\",ngPagerLastTitle:\"前往尾页\"},e.ngGrid.i18n[\"zh-tw\"]={ngAggregateLabel:\"筆\",ngGroupPanelDescription:\"拖拉表頭到此處以進行分組\",ngSearchPlaceHolder:\"搜尋...\",ngMenuText:\"選擇欄位：\",ngShowingItemsLabel:\"目前顯示筆數：\",ngTotalItemsLabel:\"總筆數：\",ngSelectedItemsLabel:\"選取筆數：\",ngPageSizeLabel:\"每頁顯示：\",ngPagerFirstTitle:\"第一頁\",ngPagerNextTitle:\"下一頁\",ngPagerPrevTitle:\"上一頁\",ngPagerLastTitle:\"最後頁\"},angular.module(\"ngGrid\").run([\"$templateCache\",function(e){e.put(\"aggregateTemplate.html\",'<div ng-click=\"row.toggleExpand()\" ng-style=\"rowStyle(row)\" class=\"ngAggregate\">    <span class=\"ngAggregateText\">{{row.label CUSTOM_FILTERS}} ({{row.totalChildren()}} {{AggItemsLabel}})</span>    <div class=\"{{row.aggClass()}}\"></div></div>'),e.put(\"cellEditTemplate.html\",'<div ng-cell-has-focus ng-dblclick=\"editCell()\">\t<div ng-edit-cell-if=\"!isFocused\">\t\t\tDISPLAY_CELL_TEMPLATE\t</div>\t<div ng-edit-cell-if=\"isFocused\">\t\tEDITABLE_CELL_TEMPLATE\t</div></div>'),e.put(\"cellTemplate.html\",'<div class=\"ngCellText\" ng-class=\"col.colIndex()\"><span ng-cell-text>{{COL_FIELD CUSTOM_FILTERS}}</span></div>'),e.put(\"checkboxCellTemplate.html\",'<div class=\"ngSelectionCell\"><input tabindex=\"-1\" class=\"ngSelectionCheckbox\" type=\"checkbox\" ng-checked=\"row.selected\" /></div>'),e.put(\"checkboxHeaderTemplate.html\",'<input class=\"ngSelectionHeader\" type=\"checkbox\" ng-show=\"multiSelect\" ng-model=\"allSelected\" ng-change=\"toggleSelectAll(allSelected, true)\"/>'),e.put(\"editableCellTemplate.html\",'<input ng-class=\"\\'colt\\' + col.index\" ng-input=\"COL_FIELD\" ng-model=\"COL_FIELD\" />'),e.put(\"footerTemplate.html\",'<div ng-show=\"showFooter\" class=\"ngFooterPanel\" ng-class=\"{\\'ui-widget-content\\': jqueryUITheme, \\'ui-corner-bottom\\': jqueryUITheme}\" ng-style=\"footerStyle()\">    <div class=\"ngTotalSelectContainer\" >        <div class=\"ngFooterTotalItems\" ng-class=\"{\\'ngNoMultiSelect\\': !multiSelect}\" >            <span class=\"ngLabel\">{{i18n.ngTotalItemsLabel}} {{maxRows()}}</span><span ng-show=\"filterText.length > 0\" class=\"ngLabel\">({{i18n.ngShowingItemsLabel}} {{totalFilteredItemsLength()}})</span>        </div>        <div class=\"ngFooterSelectedItems\" ng-show=\"multiSelect\">            <span class=\"ngLabel\">{{i18n.ngSelectedItemsLabel}} {{selectedItems.length}}</span>        </div>    </div>    <div class=\"ngPagerContainer\" style=\"float: right; margin-top: 10px;\" ng-show=\"enablePaging\" ng-class=\"{\\'ngNoMultiSelect\\': !multiSelect}\">        <div style=\"float:left; margin-right: 10px;\" class=\"ngRowCountPicker\">            <span style=\"float: left; margin-top: 3px;\" class=\"ngLabel\">{{i18n.ngPageSizeLabel}}</span>            <select style=\"float: left;height: 27px; width: 100px\" ng-model=\"pagingOptions.pageSize\" >                <option ng-repeat=\"size in pagingOptions.pageSizes\">{{size}}</option>            </select>        </div>        <div style=\"float:left; margin-right: 10px; line-height:25px;\" class=\"ngPagerControl\" style=\"float: left; min-width: 135px;\">            <button class=\"ngPagerButton\" ng-click=\"pageToFirst()\" ng-disabled=\"cantPageBackward()\" title=\"{{i18n.ngPagerFirstTitle}}\"><div class=\"ngPagerFirstTriangle\"><div class=\"ngPagerFirstBar\"></div></div></button>            <button class=\"ngPagerButton\" ng-click=\"pageBackward()\" ng-disabled=\"cantPageBackward()\" title=\"{{i18n.ngPagerPrevTitle}}\"><div class=\"ngPagerFirstTriangle ngPagerPrevTriangle\"></div></button>            <input class=\"ngPagerCurrent\" min=\"1\" max=\"{{maxPages()}}\" type=\"number\" style=\"width:50px; height: 24px; margin-top: 1px; padding: 0 4px;\" ng-model=\"pagingOptions.currentPage\"/>            <button class=\"ngPagerButton\" ng-click=\"pageForward()\" ng-disabled=\"cantPageForward()\" title=\"{{i18n.ngPagerNextTitle}}\"><div class=\"ngPagerLastTriangle ngPagerNextTriangle\"></div></button>            <button class=\"ngPagerButton\" ng-click=\"pageToLast()\" ng-disabled=\"cantPageToLast()\" title=\"{{i18n.ngPagerLastTitle}}\"><div class=\"ngPagerLastTriangle\"><div class=\"ngPagerLastBar\"></div></div></button>        </div>    </div></div>'),e.put(\"gridTemplate.html\",'<div class=\"ngTopPanel\" ng-class=\"{\\'ui-widget-header\\':jqueryUITheme, \\'ui-corner-top\\': jqueryUITheme}\" ng-style=\"topPanelStyle()\">    <div class=\"ngGroupPanel\" ng-show=\"showGroupPanel()\" ng-style=\"groupPanelStyle()\">        <div class=\"ngGroupPanelDescription\" ng-show=\"configGroups.length == 0\">{{i18n.ngGroupPanelDescription}}</div>        <ul ng-show=\"configGroups.length > 0\" class=\"ngGroupList\">            <li class=\"ngGroupItem\" ng-repeat=\"group in configGroups\">                <span class=\"ngGroupElement\">                    <span class=\"ngGroupName\">{{group.displayName}}                        <span ng-click=\"removeGroup($index)\" class=\"ngRemoveGroup\">x</span>                    </span>                    <span ng-hide=\"$last\" class=\"ngGroupArrow\"></span>                </span>            </li>        </ul>    </div>    <div class=\"ngHeaderContainer\" ng-style=\"headerStyle()\">        <div class=\"ngHeaderScroller\" ng-style=\"headerScrollerStyle()\" ng-include=\"gridId + \\'headerRowTemplate.html\\'\"></div>    </div>    <div ng-grid-menu></div></div><div class=\"ngViewport\" unselectable=\"on\" ng-viewport ng-class=\"{\\'ui-widget-content\\': jqueryUITheme}\" ng-style=\"viewportStyle()\">    <div class=\"ngCanvas\" ng-style=\"canvasStyle()\">        <div ng-style=\"rowStyle(row)\" ng-repeat=\"row in renderedRows\" ng-click=\"row.toggleSelected($event)\" ng-class=\"row.alternatingRowClass()\" ng-row></div>    </div></div><div ng-grid-footer></div>'),e.put(\"headerCellTemplate.html\",'<div class=\"ngHeaderSortColumn {{col.headerClass}}\" ng-style=\"{\\'cursor\\': col.cursor}\" ng-class=\"{ \\'ngSorted\\': !noSortVisible }\">    <div ng-click=\"col.sort($event)\" ng-class=\"\\'colt\\' + col.index\" class=\"ngHeaderText\">{{col.displayName}}</div>    <div class=\"ngSortButtonDown\" ng-show=\"col.showSortButtonDown()\"></div>    <div class=\"ngSortButtonUp\" ng-show=\"col.showSortButtonUp()\"></div>    <div class=\"ngSortPriority\">{{col.sortPriority}}</div>    <div ng-class=\"{ ngPinnedIcon: col.pinned, ngUnPinnedIcon: !col.pinned }\" ng-click=\"togglePin(col)\" ng-show=\"col.pinnable\"></div></div><div ng-show=\"col.resizable\" class=\"ngHeaderGrip\" ng-click=\"col.gripClick($event)\" ng-mousedown=\"col.gripOnMouseDown($event)\"></div>'),e.put(\"headerRowTemplate.html\",'<div ng-style=\"{ height: col.headerRowHeight }\" ng-repeat=\"col in renderedColumns\" ng-class=\"col.colIndex()\" class=\"ngHeaderCell\">\t<div class=\"ngVerticalBar\" ng-style=\"{height: col.headerRowHeight}\" ng-class=\"{ ngVerticalBarVisible: !$last }\">&nbsp;</div>\t<div ng-header-cell></div></div>'),e.put(\"menuTemplate.html\",'<div ng-show=\"showColumnMenu || showFilter\"  class=\"ngHeaderButton\" ng-click=\"toggleShowMenu()\">    <div class=\"ngHeaderButtonArrow\"></div></div><div ng-show=\"showMenu\" class=\"ngColMenu\">    <div ng-show=\"showFilter\">        <input placeholder=\"{{i18n.ngSearchPlaceHolder}}\" type=\"text\" ng-model=\"filterText\"/>    </div>    <div ng-show=\"showColumnMenu\">        <span class=\"ngMenuText\">{{i18n.ngMenuText}}</span>        <ul class=\"ngColList\">            <li class=\"ngColListItem\" ng-repeat=\"col in columns | ngColumns\">                <label><input ng-disabled=\"col.pinned\" type=\"checkbox\" class=\"ngColListCheckbox\" ng-model=\"col.visible\"/>{{col.displayName}}</label>\t\t\t\t<a title=\"Group By\" ng-class=\"col.groupedByClass()\" ng-show=\"col.groupable && col.visible\" ng-click=\"groupBy(col)\"></a>\t\t\t\t<span class=\"ngGroupingNumber\" ng-show=\"col.groupIndex > 0\">{{col.groupIndex}}</span>                      </li>        </ul>    </div></div>'),e.put(\"rowTemplate.html\",'<div ng-style=\"{ \\'cursor\\': row.cursor }\" ng-repeat=\"col in renderedColumns\" ng-class=\"col.colIndex()\" class=\"ngCell {{col.cellClass}}\">\t<div class=\"ngVerticalBar\" ng-style=\"{height: rowHeight}\" ng-class=\"{ ngVerticalBarVisible: !$last }\">&nbsp;</div>\t<div ng-cell></div></div>')}])})(window,jQuery);"
  },
  {
    "path": "open-layui-web/src/main/view/static/editor-app/libs/ui-utils.min-0.0.4.js",
    "content": "/**\n * angular-ui-utils - Swiss-Army-Knife of AngularJS tools (with no external dependencies!)\n * @version v0.0.4 - 2013-08-28\n * @link http://angular-ui.github.com\n * @license MIT License, http://www.opensource.org/licenses/MIT\n */\nangular.module(\"ui.event\",[]).directive(\"uiEvent\",[\"$parse\",function(a){return function(b,c,d){var e=b.$eval(d.uiEvent);angular.forEach(e,function(d,e){var f=a(d);c.bind(e,function(a){var c=Array.prototype.slice.call(arguments);c=c.splice(1),f(b,{$event:a,$params:c}),b.$$phase||b.$apply()})})}}]),angular.module(\"ui.format\",[]).filter(\"format\",function(){return function(a,b){var c=a;if(angular.isString(c)&&void 0!==b)if(angular.isArray(b)||angular.isObject(b)||(b=[b]),angular.isArray(b)){var d=b.length,e=function(a,c){return c=parseInt(c,10),c>=0&&d>c?b[c]:a};c=c.replace(/\\$([0-9]+)/g,e)}else angular.forEach(b,function(a,b){c=c.split(\":\"+b).join(a)});return c}}),angular.module(\"ui.highlight\",[]).filter(\"highlight\",function(){return function(a,b,c){return b||angular.isNumber(b)?(a=a.toString(),b=b.toString(),c?a.split(b).join('<span class=\"ui-match\">'+b+\"</span>\"):a.replace(new RegExp(b,\"gi\"),'<span class=\"ui-match\">$&</span>')):a}}),angular.module(\"ui.include\",[]).directive(\"uiInclude\",[\"$http\",\"$templateCache\",\"$anchorScroll\",\"$compile\",function(a,b,c,d){return{restrict:\"ECA\",terminal:!0,compile:function(e,f){var g=f.uiInclude||f.src,h=f.fragment||\"\",i=f.onload||\"\",j=f.autoscroll;return function(e,f){function k(){var k=++m,o=e.$eval(g),p=e.$eval(h);o?a.get(o,{cache:b}).success(function(a){if(k===m){l&&l.$destroy(),l=e.$new();var b;b=p?angular.element(\"<div/>\").html(a).find(p):angular.element(\"<div/>\").html(a).contents(),f.html(b),d(b)(l),!angular.isDefined(j)||j&&!e.$eval(j)||c(),l.$emit(\"$includeContentLoaded\"),e.$eval(i)}}).error(function(){k===m&&n()}):n()}var l,m=0,n=function(){l&&(l.$destroy(),l=null),f.html(\"\")};e.$watch(h,k),e.$watch(g,k)}}}}]),angular.module(\"ui.indeterminate\",[]).directive(\"uiIndeterminate\",[function(){return{compile:function(a,b){return b.type&&\"checkbox\"===b.type.toLowerCase()?function(a,b,c){a.$watch(c.uiIndeterminate,function(a){b[0].indeterminate=!!a})}:angular.noop}}}]),angular.module(\"ui.inflector\",[]).filter(\"inflector\",function(){function a(a){return a.replace(/^([a-z])|\\s+([a-z])/g,function(a){return a.toUpperCase()})}function b(a,b){return a.replace(/[A-Z]/g,function(a){return b+a})}var c={humanize:function(c){return a(b(c,\" \").split(\"_\").join(\" \"))},underscore:function(a){return a.substr(0,1).toLowerCase()+b(a.substr(1),\"_\").toLowerCase().split(\" \").join(\"_\")},variable:function(b){return b=b.substr(0,1).toLowerCase()+a(b.split(\"_\").join(\" \")).substr(1).split(\" \").join(\"\")}};return function(a,b){return b!==!1&&angular.isString(a)?(b=b||\"humanize\",c[b](a)):a}}),angular.module(\"ui.jq\",[]).value(\"uiJqConfig\",{}).directive(\"uiJq\",[\"uiJqConfig\",\"$timeout\",function(a,b){return{restrict:\"A\",compile:function(c,d){if(!angular.isFunction(c[d.uiJq]))throw new Error('ui-jq: The \"'+d.uiJq+'\" function does not exist');var e=a&&a[d.uiJq];return function(a,c,d){function f(){b(function(){c[d.uiJq].apply(c,g)},0,!1)}var g=[];d.uiOptions?(g=a.$eval(\"[\"+d.uiOptions+\"]\"),angular.isObject(e)&&angular.isObject(g[0])&&(g[0]=angular.extend({},e,g[0]))):e&&(g=[e]),d.ngModel&&c.is(\"select,input,textarea\")&&c.bind(\"change\",function(){c.trigger(\"input\")}),d.uiRefresh&&a.$watch(d.uiRefresh,function(){f()}),f()}}}}]),angular.module(\"ui.keypress\",[]).factory(\"keypressHelper\",[\"$parse\",function(a){var b={8:\"backspace\",9:\"tab\",13:\"enter\",27:\"esc\",32:\"space\",33:\"pageup\",34:\"pagedown\",35:\"end\",36:\"home\",37:\"left\",38:\"up\",39:\"right\",40:\"down\",45:\"insert\",46:\"delete\"},c=function(a){return a.charAt(0).toUpperCase()+a.slice(1)};return function(d,e,f,g){var h,i=[];h=e.$eval(g[\"ui\"+c(d)]),angular.forEach(h,function(b,c){var d,e;e=a(b),angular.forEach(c.split(\" \"),function(a){d={expression:e,keys:{}},angular.forEach(a.split(\"-\"),function(a){d.keys[a]=!0}),i.push(d)})}),f.bind(d,function(a){var c=!(!a.metaKey||a.ctrlKey),f=!!a.altKey,g=!!a.ctrlKey,h=!!a.shiftKey,j=a.keyCode;\"keypress\"===d&&!h&&j>=97&&122>=j&&(j-=32),angular.forEach(i,function(d){var i=d.keys[b[j]]||d.keys[j.toString()],k=!!d.keys.meta,l=!!d.keys.alt,m=!!d.keys.ctrl,n=!!d.keys.shift;i&&k===c&&l===f&&m===g&&n===h&&e.$apply(function(){d.expression(e,{$event:a})})})})}}]),angular.module(\"ui.keypress\").directive(\"uiKeydown\",[\"keypressHelper\",function(a){return{link:function(b,c,d){a(\"keydown\",b,c,d)}}}]),angular.module(\"ui.keypress\").directive(\"uiKeypress\",[\"keypressHelper\",function(a){return{link:function(b,c,d){a(\"keypress\",b,c,d)}}}]),angular.module(\"ui.keypress\").directive(\"uiKeyup\",[\"keypressHelper\",function(a){return{link:function(b,c,d){a(\"keyup\",b,c,d)}}}]),angular.module(\"ui.mask\",[]).value(\"uiMaskConfig\",{maskDefinitions:{9:/\\d/,A:/[a-zA-Z]/,\"*\":/[a-zA-Z0-9]/}}).directive(\"uiMask\",[\"uiMaskConfig\",function(a){return{priority:100,require:\"ngModel\",restrict:\"A\",compile:function(){var b=a;return function(a,c,d,e){function f(a){return angular.isDefined(a)?(s(a),N?(k(),l(),!0):j()):j()}function g(a){angular.isDefined(a)&&(D=a,N&&w())}function h(a){return N?(G=o(a||\"\"),I=n(G),e.$setValidity(\"mask\",I),I&&G.length?p(G):void 0):a}function i(a){return N?(G=o(a||\"\"),I=n(G),e.$viewValue=G.length?p(G):\"\",e.$setValidity(\"mask\",I),\"\"===G&&void 0!==e.$error.required&&e.$setValidity(\"required\",!1),I?G:void 0):a}function j(){return N=!1,m(),angular.isDefined(P)?c.attr(\"placeholder\",P):c.removeAttr(\"placeholder\"),angular.isDefined(Q)?c.attr(\"maxlength\",Q):c.removeAttr(\"maxlength\"),c.val(e.$modelValue),e.$viewValue=e.$modelValue,!1}function k(){G=K=o(e.$modelValue||\"\"),H=J=p(G),I=n(G);var a=I&&G.length?H:\"\";d.maxlength&&c.attr(\"maxlength\",2*B[B.length-1]),c.attr(\"placeholder\",D),c.val(a),e.$viewValue=a}function l(){O||(c.bind(\"blur\",t),c.bind(\"mousedown mouseup\",u),c.bind(\"input keyup click focus\",w),O=!0)}function m(){O&&(c.unbind(\"blur\",t),c.unbind(\"mousedown\",u),c.unbind(\"mouseup\",u),c.unbind(\"input\",w),c.unbind(\"keyup\",w),c.unbind(\"click\",w),c.unbind(\"focus\",w),O=!1)}function n(a){return a.length?a.length>=F:!0}function o(a){var b=\"\",c=C.slice();return a=a.toString(),angular.forEach(E,function(b){a=a.replace(b,\"\")}),angular.forEach(a.split(\"\"),function(a){c.length&&c[0].test(a)&&(b+=a,c.shift())}),b}function p(a){var b=\"\",c=B.slice();return angular.forEach(D.split(\"\"),function(d,e){a.length&&e===c[0]?(b+=a.charAt(0)||\"_\",a=a.substr(1),c.shift()):b+=d}),b}function q(a){var b=d.placeholder;return\"undefined\"!=typeof b&&b[a]?b[a]:\"_\"}function r(){return D.replace(/[_]+/g,\"_\").replace(/([^_]+)([a-zA-Z0-9])([^_])/g,\"$1$2_$3\").split(\"_\")}function s(a){var b=0;if(B=[],C=[],D=\"\",\"string\"==typeof a){F=0;var c=!1,d=a.split(\"\");angular.forEach(d,function(a,d){R.maskDefinitions[a]?(B.push(b),D+=q(d),C.push(R.maskDefinitions[a]),b++,c||F++):\"?\"===a?c=!0:(D+=a,b++)})}B.push(B.slice().pop()+1),E=r(),N=B.length>1?!0:!1}function t(){L=0,M=0,I&&0!==G.length||(H=\"\",c.val(\"\"),a.$apply(function(){e.$setViewValue(\"\")}))}function u(a){\"mousedown\"===a.type?c.bind(\"mouseout\",v):c.unbind(\"mouseout\",v)}function v(){M=A(this),c.unbind(\"mouseout\",v)}function w(b){b=b||{};var d=b.which,f=b.type;if(16!==d&&91!==d){var g,h=c.val(),i=J,j=o(h),k=K,l=!1,m=y(this)||0,n=L||0,q=m-n,r=B[0],s=B[j.length]||B.slice().shift(),t=M||0,u=A(this)>0,v=t>0,w=h.length>i.length||t&&h.length>i.length-t,C=h.length<i.length||t&&h.length===i.length-t,D=d>=37&&40>=d&&b.shiftKey,E=37===d,F=8===d||\"keyup\"!==f&&C&&-1===q,G=46===d||\"keyup\"!==f&&C&&0===q&&!v,H=(E||F||\"click\"===f)&&m>r;if(M=A(this),!D&&(!u||\"click\"!==f&&\"keyup\"!==f)){if(\"input\"===f&&C&&!v&&j===k){for(;F&&m>r&&!x(m);)m--;for(;G&&s>m&&-1===B.indexOf(m);)m++;var I=B.indexOf(m);j=j.substring(0,I)+j.substring(I+1),l=!0}for(g=p(j),J=g,K=j,c.val(g),l&&a.$apply(function(){e.$setViewValue(j)}),w&&r>=m&&(m=r+1),H&&m--,m=m>s?s:r>m?r:m;!x(m)&&m>r&&s>m;)m+=H?-1:1;(H&&s>m||w&&!x(n))&&m++,L=m,z(this,m)}}}function x(a){return B.indexOf(a)>-1}function y(a){if(void 0!==a.selectionStart)return a.selectionStart;if(document.selection){a.focus();var b=document.selection.createRange();return b.moveStart(\"character\",-a.value.length),b.text.length}return 0}function z(a,b){if(0!==a.offsetWidth&&0!==a.offsetHeight)if(a.setSelectionRange)a.focus(),a.setSelectionRange(b,b);else if(a.createTextRange){var c=a.createTextRange();c.collapse(!0),c.moveEnd(\"character\",b),c.moveStart(\"character\",b),c.select()}}function A(a){return void 0!==a.selectionStart?a.selectionEnd-a.selectionStart:document.selection?document.selection.createRange().text.length:0}var B,C,D,E,F,G,H,I,J,K,L,M,N=!1,O=!1,P=d.placeholder,Q=d.maxlength,R={};d.uiOptions?(R=a.$eval(\"[\"+d.uiOptions+\"]\"),angular.isObject(R[0])&&(R=function(a,b){for(var c in a)Object.prototype.hasOwnProperty.call(a,c)&&(b[c]?angular.extend(b[c],a[c]):b[c]=angular.copy(a[c]));return b}(b,R[0]))):R=b,d.$observe(\"uiMask\",f),d.$observe(\"placeholder\",g),e.$formatters.push(h),e.$parsers.push(i),c.bind(\"mousedown mouseup\",u),Array.prototype.indexOf||(Array.prototype.indexOf=function(a){\"use strict\";if(null===this)throw new TypeError;var b=Object(this),c=b.length>>>0;if(0===c)return-1;var d=0;if(arguments.length>1&&(d=Number(arguments[1]),d!==d?d=0:0!==d&&1/0!==d&&d!==-1/0&&(d=(d>0||-1)*Math.floor(Math.abs(d)))),d>=c)return-1;for(var e=d>=0?d:Math.max(c-Math.abs(d),0);c>e;e++)if(e in b&&b[e]===a)return e;return-1})}}}}]),angular.module(\"ui.reset\",[]).value(\"uiResetConfig\",null).directive(\"uiReset\",[\"uiResetConfig\",function(a){var b=null;return void 0!==a&&(b=a),{require:\"ngModel\",link:function(a,c,d,e){var f;f=angular.element('<a class=\"ui-reset\" />'),c.wrap('<span class=\"ui-resetwrap\" />').after(f),f.bind(\"click\",function(c){c.preventDefault(),a.$apply(function(){d.uiReset?e.$setViewValue(a.$eval(d.uiReset)):e.$setViewValue(b),e.$render()})})}}}]),angular.module(\"ui.route\",[]).directive(\"uiRoute\",[\"$location\",\"$parse\",function(a,b){return{restrict:\"AC\",scope:!0,compile:function(c,d){var e;if(d.uiRoute)e=\"uiRoute\";else if(d.ngHref)e=\"ngHref\";else{if(!d.href)throw new Error(\"uiRoute missing a route or href property on \"+c[0]);e=\"href\"}return function(c,d,f){function g(b){(hash=b.indexOf(\"#\"))>-1&&(b=b.substr(hash+1)),j=function(){i(c,a.path().indexOf(b)>-1)},j()}function h(b){(hash=b.indexOf(\"#\"))>-1&&(b=b.substr(hash+1)),j=function(){var d=new RegExp(\"^\"+b+\"$\",[\"i\"]);i(c,d.test(a.path()))},j()}var i=b(f.ngModel||f.routeModel||\"$uiRoute\").assign,j=angular.noop;switch(e){case\"uiRoute\":f.uiRoute?h(f.uiRoute):f.$observe(\"uiRoute\",h);break;case\"ngHref\":f.ngHref?g(f.ngHref):f.$observe(\"ngHref\",g);break;case\"href\":g(f.href)}c.$on(\"$routeChangeSuccess\",function(){j()}),c.$on(\"$stateChangeSuccess\",function(){j()})}}}}]),angular.module(\"ui.scrollfix\",[]).directive(\"uiScrollfix\",[\"$window\",function(a){\"use strict\";return{require:\"^?uiScrollfixTarget\",link:function(b,c,d,e){var f=c[0].offsetTop,g=e&&e.$element||angular.element(a);d.uiScrollfix?\"string\"==typeof d.uiScrollfix&&(\"-\"===d.uiScrollfix.charAt(0)?d.uiScrollfix=f-parseFloat(d.uiScrollfix.substr(1)):\"+\"===d.uiScrollfix.charAt(0)&&(d.uiScrollfix=f+parseFloat(d.uiScrollfix.substr(1)))):d.uiScrollfix=f,g.bind(\"scroll\",function(){var b;if(angular.isDefined(a.pageYOffset))b=a.pageYOffset;else{var e=document.compatMode&&\"BackCompat\"!==document.compatMode?document.documentElement:document.body;b=e.scrollTop}!c.hasClass(\"ui-scrollfix\")&&b>d.uiScrollfix?c.addClass(\"ui-scrollfix\"):c.hasClass(\"ui-scrollfix\")&&b<d.uiScrollfix&&c.removeClass(\"ui-scrollfix\")})}}}]).directive(\"uiScrollfixTarget\",[function(){\"use strict\";return{controller:function(a){this.$element=a}}}]),angular.module(\"ui.showhide\",[]).directive(\"uiShow\",[function(){return function(a,b,c){a.$watch(c.uiShow,function(a){a?b.addClass(\"ui-show\"):b.removeClass(\"ui-show\")})}}]).directive(\"uiHide\",[function(){return function(a,b,c){a.$watch(c.uiHide,function(a){a?b.addClass(\"ui-hide\"):b.removeClass(\"ui-hide\")})}}]).directive(\"uiToggle\",[function(){return function(a,b,c){a.$watch(c.uiToggle,function(a){a?b.removeClass(\"ui-hide\").addClass(\"ui-show\"):b.removeClass(\"ui-show\").addClass(\"ui-hide\")})}}]),angular.module(\"ui.unique\",[]).filter(\"unique\",[\"$parse\",function(a){return function(b,c){if(c===!1)return b;if((c||angular.isUndefined(c))&&angular.isArray(b)){var d=[],e=angular.isString(c)?a(c):function(a){return a},f=function(a){return angular.isObject(a)?e(a):a};angular.forEach(b,function(a){for(var b=!1,c=0;c<d.length;c++)if(angular.equals(f(d[c]),f(a))){b=!0;break}b||d.push(a)}),b=d}return b}}]),angular.module(\"ui.validate\",[]).directive(\"uiValidate\",function(){return{restrict:\"A\",require:\"ngModel\",link:function(a,b,c,d){function e(b){return angular.isString(b)?(a.$watch(b,function(){angular.forEach(g,function(a){a(d.$modelValue)})}),void 0):angular.isArray(b)?(angular.forEach(b,function(b){a.$watch(b,function(){angular.forEach(g,function(a){a(d.$modelValue)})})}),void 0):(angular.isObject(b)&&angular.forEach(b,function(b,c){angular.isString(b)&&a.$watch(b,function(){g[c](d.$modelValue)}),angular.isArray(b)&&angular.forEach(b,function(b){a.$watch(b,function(){g[c](d.$modelValue)})})}),void 0)}var f,g={},h=a.$eval(c.uiValidate);h&&(angular.isString(h)&&(h={validator:h}),angular.forEach(h,function(b,c){f=function(e){var f=a.$eval(b,{$value:e});return angular.isObject(f)&&angular.isFunction(f.then)?(f.then(function(){d.$setValidity(c,!0)},function(){d.$setValidity(c,!1)}),e):f?(d.$setValidity(c,!0),e):(d.$setValidity(c,!1),void 0)},g[c]=f,d.$formatters.push(f),d.$parsers.push(f)}),c.uiValidateWatch&&e(a.$eval(c.uiValidateWatch)))}}}),angular.module(\"ui.utils\",[\"ui.event\",\"ui.format\",\"ui.highlight\",\"ui.include\",\"ui.indeterminate\",\"ui.inflector\",\"ui.jq\",\"ui.keypress\",\"ui.mask\",\"ui.reset\",\"ui.route\",\"ui.scrollfix\",\"ui.showhide\",\"ui.unique\",\"ui.validate\"]);"
  },
  {
    "path": "open-layui-web/src/main/view/static/index.html",
    "content": "﻿<!DOCTYPE html>\n\n<html>\n\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">\n\t    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=1\">\n\t    <meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black\"> \n\t    <meta name=\"apple-mobile-web-app-capable\" content=\"yes\">\n\t    <meta name=\"format-detection\" content=\"telephone=no\">\n\t\t<title>后台管理系统</title>\n\t\t<link rel=\"stylesheet\" href=\"/lib/layui/css/layui.css\" media=\"all\" />\n\n\t\t<link rel=\"stylesheet\" href=\"/lib/skin/css/admin.css\" media=\"all\" />\n\n\t\t<link rel=\"stylesheet\" href=\"/lib/layui/css/global.css\" media=\"all\" />\n\t\t<link rel=\"stylesheet\" href=\"/css/font-awesome/css/font-awesome.css\" media=\"all\" />\n\t\t\n\t</head>\n\n<body class=\"layui-layout-body\">\n\n\t<div class=\"layui-layout layui-layout-admin\" >\n\t\t<!-- 头部 -->\n\t\t<div class=\"layui-header\">\n\t\t\t<div class=\"layui-logo\">\n\t\t\t\t<img src=\"/lib/skin/images/logo.png\"/>\n\t\t\t\t<cite>后台管理系统</cite>\n\t\t\t</div>\n\t\t\t<ul class=\"layui-nav layui-layout-left\">\n\t\t\t\t<li class=\"layui-nav-item\" lay-unselect>\n\t\t\t\t\t<a class=\"kit-side-fold\" title=\"侧边伸缩\"><i class=\"layui-icon layui-icon-shrink-right\"></i></a>\n\t\t\t\t</li>\n\t\t\t</ul>\n\t\t\t<ul class=\"layui-nav layui-layout-right\">\n\t\t\t\t<li class=\"layui-nav-item\">\n\t\t\t\t\t<a href='javascript:;' lay-id=\"-997\" data-url=\"pages/notice/noticePubList.html\"><i class=\"fa fa-envelope-o\" aria-hidden=\"true\" title=\"公告\" unreadNotice></i></a>\n\t\t\t\t</li>\n\t\t\t\t<li class=\"layui-nav-item\" lay-unselect>\n\t\t\t\t\t<a href=\"javascript:;\" class=\"admin-header-user\">\n\t\t\t\t\t\t<img class=\"layui-nav-img\"/>\n\t\t\t\t\t\t<span></span>\n\t\t\t\t\t</a>\n\t\t\t\t\t<dl class=\"layui-nav-child\">\n\t\t\t\t\t\t<dd>\n\t\t\t\t\t\t\t<a href='javascript:;' lay-id=\"-999\" data-url=\"pages/user/updateMyself.html\"><i class=\"fa fa-user-circle\" aria-hidden=\"true\"></i> 个人信息</a>\n\t\t\t\t\t\t</dd>\n\t\t\t\t\t\t<dd>\n\t\t\t\t\t\t\t<a href='javascript:;' lay-id=\"-998\" data-url=\"pages/user/updateHeadImg.html\"><i class=\"fa fa-drupal\" aria-hidden=\"true\"></i> 头像</a>\n\t\t\t\t\t\t</dd>\n\t\t\t\t\t\t<dd>\n\t\t\t\t\t\t\t<a href=\"javascript:;\" onclick=\"logout()\"><i class=\"fa fa-sign-out\" aria-hidden=\"true\"></i> 退出</a>\n\t\t\t\t\t\t</dd>\n\t\t\t\t\t</dl>\n\t\t\t\t</li>\n\t\t\t</ul>\n\t\t</div>\n\n\t\t<!-- 菜单 -->\n\t\t<div class=\"layui-side layui-bg-black\" id=\"admin-side\">\n\t\t\t<div class=\"layui-side-scroll\" id=\"admin-navbar-side\" lay-filter=\"side\" style=\"background-color: #001529;\">\n\t\t\t\t<ul id=\"menu\" class=\"layui-nav layui-nav-tree\" lay-filter=\"demo\">\n\n\t\t\t\t</ul>\n\t\t\t</div>\n\t\t</div>\n\n\n\t\t<!-- 主体部分 -->\n\t\t<div class=\"layui-body\"  id=\"admin-body\">\n\t\t\t<div class=\"layui-tab admin-nav-card layui-tab-brief\" lay-allowClose=\"true\" lay-filter=\"admin-tab\">\n\t\t\t\t<ul class=\"layui-tab-title\">\n\t\t\t\t\t<li class=\"layui-this\">\n\t\t\t\t\t\t<i class=\"fa fa-dashboard\" aria-hidden=\"true\"></i>\n\t\t\t\t\t\t<cite>Home</cite>\n\t\t\t\t\t</li>\n\t\t\t\t</ul>\n\t\t\t\t<div class=\"layui-tab-content\" style=\"min-height: 150px; padding: 5px;background-color: #f2f2f2;\">\n\t\t\t\t\t<div class=\"layui-tab-item layui-show\">\n\t\t\t\t\t\t<iframe src=\"pages/dashboard.html\"></iframe>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t</div>\n\n\t\t<!--<div class=\"layui-body\"  id=\"admin-body\">-->\n\t\t\t<!--<div class=\"layui-tab admin-nav-card layui-tab-brief\" lay-allowClose=\"true\" lay-filter=\"admin-tab\">-->\n\t\t\t\t<!--<ul class=\"layui-tab-title\" style=\"background-color: #002140;\">-->\n\t\t\t\t\t<!--<li class=\"layui-this\">-->\n\t\t\t\t\t\t<!--<i class=\"fa fa-dashboard\" aria-hidden=\"true\"></i>-->\n\t\t\t\t\t\t<!--<cite>Home</cite>-->\n\t\t\t\t\t<!--</li>-->\n\t\t\t\t<!--</ul>-->\n\t\t\t\t<!--<div class=\"layui-tab-content\" style=\"min-height: 150px; padding: 5px 0 0 0;background-color: #f2f2f2;\">-->\n\t\t\t\t\t<!--<div class=\"layui-tab-item layui-show\">-->\n\t\t\t\t\t\t<!--<iframe src=\"pages/dashboard.html\"></iframe>-->\n\t\t\t\t\t<!--</div>-->\n\t\t\t\t<!--</div>-->\n\t\t\t<!--</div>-->\n\t\t<!--</div>-->\n\n\n\n\t\t<div class=\"layui-footer footer footer-demo\" id=\"admin-footer\">\n\t\t\t<div>\n\t\t\t\t<p>OCP研发中心  2015-2017</p>\n\t\t\t</div>\n\t\t</div>\n\t\t<div class=\"site-tree-mobile layui-hide\">\n\t\t\t<i class=\"layui-icon\">&#xe602;</i>\n\t\t</div>\n\t\t<div class=\"site-mobile-shade\"></div>\n\n\t</div>\n\n\n<script type=\"text/javascript\" src=\"/lib/layui/layui.js\"></script>\n<script src=\"base-component/jquery/jquery.min.js\"></script>\n<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n<script type=\"text/javascript\" src=\"/js/main.js\"></script>\n\n<script>\n\n    $('.kit-side-fold').click(function(){\n        var isExapnd = $('.layui-layout-admin').hasClass('admin-nav-mini');\n        if (isExapnd) {\n            $('.layui-layout-admin').removeClass('admin-nav-mini');\n        } else {\n            $('.layui-layout-admin').addClass('admin-nav-mini');\n        }\n\t});\n</script>\n\n</body>\n\n</html>"
  },
  {
    "path": "open-layui-web/src/main/view/static/index.html.aaa",
    "content": "﻿<!DOCTYPE html>\n\n<html>\n\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">\n\t    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=1\">\n\t    <meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black\"> \n\t    <meta name=\"apple-mobile-web-app-capable\" content=\"yes\">\n\t    <meta name=\"format-detection\" content=\"telephone=no\">\n\t\t<title>后台管理系统</title>\n\t\t<link rel=\"stylesheet\" href=\"/lib/layui/css/layui.css\" media=\"all\" />\n\t\t<link rel=\"stylesheet\" href=\"/lib/layui/css/global.css\" media=\"all\" />\n\t\t<link rel=\"stylesheet\" href=\"/css/font-awesome/css/font-awesome.css\" media=\"all\" />\n\t\t\n\t</head>\n\n\t<body>\n\t\t<div class=\"layui-layout layui-layout-admin\" style=\"border-bottom: solid 5px #1aa094;\">\n\t\t    <!-- 标题栏 -->\n\t\t\t<div class=\"layui-header header header-demo\">\n                <div class=\"layui-main\">\n\t\t\t\t\t<div class=\"admin-login-box\">\n\t\t\t\t\t\t<a class=\"logo\" style=\"left: 0;\" href=\"/\">\n\t\t\t\t\t\t\t<span style=\"font-size: 22px;\">后台管理系统</span>\n\t\t\t\t\t\t</a>\n\t\t\t\t\t\t<div class=\"admin-side-toggle\">\n\t\t\t\t\t\t\t<i class=\"fa fa-bars\" aria-hidden=\"true\"></i>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t    <ul class=\"layui-nav\" pc>\n\t\t\t\t      \t<li class=\"layui-nav-item\">\n\t\t\t\t\t\t\t<a href='javascript:;' lay-id=\"-997\" data-url=\"pages/notice/noticePubList.html\"><i class=\"fa fa-envelope-o\" aria-hidden=\"true\" title=\"公告\" unreadNotice></i></a>\n\t\t\t\t\t\t</li>\n\t\t\t\t      <li class=\"layui-nav-item\" pc>\n\t\t\t\t        <a href=\"javascript:;\" class=\"admin-header-user\">\n\t                        <img />\n\t                        <span></span>\n\t                    </a>\n\t                    <dl class=\"layui-nav-child\">\n\t                        <dd>\n\t                            <a href='javascript:;' lay-id=\"-999\" data-url=\"pages/user/updateMyself.html\"><i class=\"fa fa-user-circle\" aria-hidden=\"true\"></i> 个人信息</a>\n\t                        </dd>\n\t                        <dd>\n\t                            <a href='javascript:;' lay-id=\"-998\" data-url=\"pages/user/updateHeadImg.html\"><i class=\"fa fa-drupal\" aria-hidden=\"true\"></i> 头像</a>\n\t                        </dd>\n\t                        <dd>\n\t                            <a href=\"javascript:;\" onclick=\"logout()\"><i class=\"fa fa-sign-out\" aria-hidden=\"true\"></i> 退出</a>\n\t                        </dd>\n\t                    </dl>\n\t\t\t\t      </li>\n\t\t\t\t    </ul>\n\t\t\t  </div>\n            </div>\n            <!-- 菜单 -->\n\t\t\t<div class=\"layui-side layui-bg-black\" id=\"admin-side\">\n\t\t\t\t<div class=\"layui-side-scroll\" id=\"admin-navbar-side\" lay-filter=\"side\">\n\t\t\t\t    <ul id=\"menu\" class=\"layui-nav layui-nav-tree\" lay-filter=\"demo\">\n\t\t\t\t    \n\t\t            </ul>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"layui-body\" style=\"bottom: 0;border-left: solid 2px #1AA094;\" id=\"admin-body\">\n\t\t\t\t<div class=\"layui-tab admin-nav-card layui-tab-brief\" lay-allowClose=\"true\" lay-filter=\"admin-tab\">\n\t\t\t\t\t<ul class=\"layui-tab-title\">\n\t\t\t\t\t\t<li class=\"layui-this\">\n\t\t\t\t\t\t\t<i class=\"fa fa-dashboard\" aria-hidden=\"true\"></i>\n\t\t\t\t\t\t\t<cite>Home</cite>\n\t\t\t\t\t\t</li>\n\t\t\t\t\t</ul>\n\t\t\t\t\t<div class=\"layui-tab-content\" style=\"min-height: 150px; padding: 5px 0 0 0;\">\n\t\t\t\t\t\t<div class=\"layui-tab-item layui-show\">\n\t\t\t\t\t\t\t<iframe src=\"pages/dashboard.html\"></iframe>\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</div>\n\t\t\t<div class=\"layui-footer footer footer-demo\" id=\"admin-footer\">\n\t\t\t\t<div>\n\t\t\t\t\t<p>OCP研发中心  2015-2017</p>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"site-tree-mobile layui-hide\">\n\t\t\t\t<i class=\"layui-icon\">&#xe602;</i>\n\t\t\t</div>\n\t\t\t<div class=\"site-mobile-shade\"></div>\n\t\t\t\n\t\t\t<script type=\"text/javascript\" src=\"/lib/layui/layui.js\"></script>\n\t\t\t<script src=\"base-component/jquery/jquery.min.js\"></script>\n\t\t\t<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n\t\t\t<script type=\"text/javascript\" src=\"/js/main.js\"></script>\n\t</div>\n</body>\n\n</html>"
  },
  {
    "path": "open-layui-web/src/main/view/static/index.html.bak1",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n    <title>OCP管理系统</title>\n    <meta name=\"description\" content=\"后台管理系统\">\n    <meta name=\"keywords\" content=\"OCP\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n    <meta name=\"renderer\" content=\"webkit\">\n    <meta http-equiv=\"Cache-Control\" content=\"no-siteapp\" />\n    <!--<link rel=\"icon\" type=\"image/png\" href=\"{{assets}}i/favicon.png\">-->\n    <!--<link rel=\"apple-touch-icon-precomposed\" href=\"{{assets}}i/app-icon72x72@2x.png\">\n    <meta name=\"apple-mobile-web-app-title\" content=\"Amaze UI\" />-->\n    <link rel=\"stylesheet\" href=\"base-component/amazeui/css/amazeui.min.css\"/>\n    <link rel=\"stylesheet\" href=\"assets/css/admin.css\">\n</head>\n<body>\n<!--[if lte IE 9]>\n<p class=\"browsehappy\">你正在使用<strong>过时</strong>的浏览器，Amaze UI 暂不支持。 请 <a href=\"http://browsehappy.com/\" target=\"_blank\">升级浏览器</a>\n    以获得更好的体验！</p>\n<![endif]-->\n\n<header class=\"am-topbar am-topbar-inverse admin-header\">\n    <div class=\"am-topbar-brand\">\n        <strong>OCP</strong> <small>&nbsp;&nbsp;微服务后台管理系统</small>\n    </div>\n\n    <button class=\"am-topbar-btn am-topbar-toggle am-btn am-btn-sm am-btn-success am-show-sm-only\" data-am-collapse=\"{target: '#topbar-collapse'}\"><span class=\"am-sr-only\">导航切换</span> <span class=\"am-icon-bars\"></span></button>\n\n    <div class=\"am-collapse am-topbar-collapse\" id=\"topbar-collapse\">\n\n        <ul class=\"am-nav am-nav-pills am-topbar-nav am-topbar-right admin-header-list\">\n            <li><a href=\"javascript:;\"><span class=\"am-icon-envelope-o\"></span> 收件箱 <span class=\"am-badge am-badge-warning\">5</span></a></li>\n            <li class=\"am-dropdown\" data-am-dropdown>\n                <a class=\"am-dropdown-toggle\" data-am-dropdown-toggle href=\"javascript:;\">\n                    <span class=\"am-icon-users\"></span> 管理员 <span class=\"am-icon-caret-down\"></span>\n                </a>\n                <ul class=\"am-dropdown-content\">\n                    <li><a href=\"#\"><span class=\"am-icon-user\"></span> 资料</a></li>\n                    <li><a href=\"#\"><span class=\"am-icon-cog\"></span> 设置</a></li>\n                    <li><a href=\"#\"><span class=\"am-icon-power-off\" onclick=\"logout()\"></span> 退出</a></li>\n                </ul>\n            </li>\n            <li class=\"am-hide-sm-only\"><a href=\"javascript:;\" id=\"admin-fullscreen\"><span class=\"am-icon-arrows-alt\"></span> <span class=\"admin-fullText\">开启全屏</span></a></li>\n        </ul>\n    </div>\n</header>\n\n<div class=\"am-cf admin-main\">\n    <!-- sidebar start -->\n    <div class=\"admin-sidebar am-offcanvas\" id=\"admin-offcanvas\">\n        <div class=\"am-offcanvas-bar admin-offcanvas-bar\">\n            <ul class=\"am-list admin-sidebar-list\" id=\"admin-list-config\">\n                <!-- 左侧列表配置 -->\n            </ul>\n            <div class=\"am-panel am-panel-default admin-sidebar-panel\">\n                <div class=\"am-panel-bd\">\n                    <p><span class=\"am-icon-bookmark\"></span> 公告</p>\n                    <p>时光静好，与君语；细水流年，与君同。—— huzhihui UI</p>\n                </div>\n            </div>\n\n            <div class=\"am-panel am-panel-default admin-sidebar-panel\">\n                <div class=\"am-panel-bd\">\n                    <p><span class=\"am-icon-tag\"></span> wiki</p>\n                    <p>Welcome to the huzhihui UI wiki!</p>\n                </div>\n            </div>\n        </div>\n    </div>\n    <!-- sidebar end -->\n\n    <!-- content start -->\n    <div class=\"admin-content\">\n        <div class=\"admin-content-body\">\n            <div class=\"am-tabs\" data-am-tabs=\"{noSwipe: 1}\" id=\"admin-tab-body-index\" style=\"height: 100%;position: relative;\">\n                <ul class=\"am-tabs-nav am-nav am-nav-tabs admin-tab-show\">\n\n                    <div class=\"admin-tab-left am-icon-chevron-left\"></div>\n                    <div class=\"admin-tab-right am-icon-chevron-right\"></div>\n                    <div class=\"admin-tab-right admin-tab-right-close-all am-icon-trash-o\" style=\"width: 40px\"></div>\n                    <!-- 分界线 -->\n                    <span class=\"admin-tab-min-hr\"></span>\n\n\n                    <li class=\"am-active admin-main-tab\">\n                        <span class=\"am-tab-refresh am-icon-refresh\" iframe-url=\"pages/dashboard.html\" iframe-uuid=\"uuid-main\"></span>\n                        <a href=\"javascript: void(0)\">首页</a>\n                    </li>\n                </ul>\n\n                <div class=\"am-tabs-bd admin-tab-show-body\">\n                    <div class=\"am-tab-panel am-active\" style=\"height: 100%\">\n                        <iframe src=\"pages/dashboard.html\" class=\"admin-iframe-html\" iframe-uuid=\"uuid-main\" style=\"width: 100%;height: 100%;\"></iframe>\n                    </div>\n                </div>\n            </div>\n        </div>\n\n        <footer class=\"admin-content-footer\">\n            <p class=\"am-padding-left admin-content-footer-p\">© 2014 AllMobilize, Inc. Licensed under MIT license.</p>\n        </footer>\n    </div>\n    <!-- content end -->\n\n</div>\n\n<a href=\"#\" class=\"am-icon-btn am-icon-th-list am-show-sm-only admin-menu\" data-am-offcanvas=\"{target: '#admin-offcanvas'}\"></a>\n\n<!--[if lt IE 9]>\n<script src=\"http://libs.baidu.com/jquery/1.11.1/jquery.min.js\"></script>\n<script src=\"http://cdn.staticfile.org/modernizr/2.8.3/modernizr.js\"></script>\n<script src=\"base-component/amazeui/js/amazeui.ie8polyfill.min.js\"></script>\n<![endif]-->\n\n<!--[if (gte IE 9)|!(IE)]><!-->\n<script src=\"base-component/jquery/jquery.min.js\"></script>\n<!--<![endif]-->\n<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n<script src=\"assets/js/config.js\"></script>\n<script src=\"assets/js/app.js\"></script>\n\n<script src=\"base-component/amazeui/js/amazeui.min.js\"></script>\n<script src=\"base-component/layer/layer.js\"></script>\n\n<script>\nfunction logout(){\n\t$.ajax({\n\t\ttype : 'get',\n\t\turl : '/logout',\n\t\tsuccess : function(data) {\n\t\t\tlocalStorage.removeItem(\"token\");\n\t\t\tlocation.href='/login.html';\n\t\t}\n\t});\n}\n</script>\n</body>\n</html>"
  },
  {
    "path": "open-layui-web/src/main/view/static/index.html.bak2",
    "content": "﻿<!DOCTYPE html>\n\n<html>\n\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">\n\t    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=1\">\n\t    <meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black\"> \n\t    <meta name=\"apple-mobile-web-app-capable\" content=\"yes\">\n\t    <meta name=\"format-detection\" content=\"telephone=no\">\n\t\t<title>后台管理系统</title>\n\t\t<link rel=\"stylesheet\" href=\"/lib/layui/css/layui.css\" media=\"all\" />\n\t\t<link rel=\"stylesheet\" href=\"/lib/layui/css/global.css\" media=\"all\" />\n\t\t<link rel=\"stylesheet\" href=\"/css/font-awesome/css/font-awesome.css\" media=\"all\" />\n\t\t\n\t</head>\n\n\t<body>\n\t\t<div class=\"layui-layout layui-layout-admin\" style=\"border-bottom: solid 5px #1aa094;\">\n\t\t    <!-- 标题栏 -->\n\t\t\t<div class=\"layui-header header header-demo\">\n                <div class=\"layui-main\">\n\t\t\t\t\t<div class=\"admin-login-box\">\n\t\t\t\t\t\t<a class=\"logo\" style=\"left: 0;\" href=\"/\">\n\t\t\t\t\t\t\t<span style=\"font-size: 22px;\">后台管理系统</span>\n\t\t\t\t\t\t</a>\n\t\t\t\t\t\t<div class=\"admin-side-toggle\">\n\t\t\t\t\t\t\t<i class=\"fa fa-bars\" aria-hidden=\"true\"></i>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t    <ul class=\"layui-nav\" pc>\n\t\t\t\t      \t<li class=\"layui-nav-item\">\n\t\t\t\t\t\t\t<a href='javascript:;' lay-id=\"-997\" data-url=\"pages/notice/noticePubList.html\"><i class=\"fa fa-envelope-o\" aria-hidden=\"true\" title=\"公告\" unreadNotice></i></a>\n\t\t\t\t\t\t</li>\n\t\t\t\t      <li class=\"layui-nav-item\" pc>\n\t\t\t\t        <a href=\"javascript:;\" class=\"admin-header-user\">\n\t                        <img />\n\t                        <span></span>\n\t                    </a>\n\t                    <dl class=\"layui-nav-child\">\n\t                        <dd>\n\t                            <a href='javascript:;' lay-id=\"-999\" data-url=\"pages/user/updateMyself.html\"><i class=\"fa fa-user-circle\" aria-hidden=\"true\"></i> 个人信息</a>\n\t                        </dd>\n\t                        <dd>\n\t                            <a href='javascript:;' lay-id=\"-998\" data-url=\"pages/user/updateHeadImg.html\"><i class=\"fa fa-drupal\" aria-hidden=\"true\"></i> 头像</a>\n\t                        </dd>\n\t                        <dd>\n\t                            <a href=\"javascript:;\" onclick=\"logout()\"><i class=\"fa fa-sign-out\" aria-hidden=\"true\"></i> 退出</a>\n\t                        </dd>\n\t                    </dl>\n\t\t\t\t      </li>\n\t\t\t\t    </ul>\n\t\t\t  </div>\n            </div>\n            <!-- 菜单 -->\n\t\t\t<div class=\"layui-side layui-bg-black\" id=\"admin-side\">\n\t\t\t\t<div class=\"layui-side-scroll\" id=\"admin-navbar-side\" lay-filter=\"side\">\n\t\t\t\t    <ul id=\"menu\" class=\"layui-nav layui-nav-tree\" lay-filter=\"demo\">\n\t\t\t\t    \n\t\t            </ul>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"layui-body\" style=\"bottom: 0;border-left: solid 2px #1AA094;\" id=\"admin-body\">\n\t\t\t\t<div class=\"layui-tab admin-nav-card layui-tab-brief\" lay-allowClose=\"true\" lay-filter=\"admin-tab\">\n\t\t\t\t\t<ul class=\"layui-tab-title\">\n\t\t\t\t\t\t<li class=\"layui-this\">\n\t\t\t\t\t\t\t<i class=\"fa fa-dashboard\" aria-hidden=\"true\"></i>\n\t\t\t\t\t\t\t<cite>Home</cite>\n\t\t\t\t\t\t</li>\n\t\t\t\t\t</ul>\n\t\t\t\t\t<div class=\"layui-tab-content\" style=\"min-height: 150px; padding: 5px 0 0 0;\">\n\t\t\t\t\t\t<div class=\"layui-tab-item layui-show\">\n\t\t\t\t\t\t\t<iframe src=\"pages/dashboard.html\"></iframe>\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</div>\n\t\t\t<div class=\"layui-footer footer footer-demo\" id=\"admin-footer\">\n\t\t\t\t<div>\n\t\t\t\t\t<p>OCP研发中心  2015-2017</p>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"site-tree-mobile layui-hide\">\n\t\t\t\t<i class=\"layui-icon\">&#xe602;</i>\n\t\t\t</div>\n\t\t\t<div class=\"site-mobile-shade\"></div>\n\t\t\t\n\t\t\t<script type=\"text/javascript\" src=\"/lib/layui/layui.js\"></script>\n\t\t\t<script src=\"base-component/jquery/jquery.min.js\"></script>\n\t\t\t<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n\t\t\t<script type=\"text/javascript\" src=\"/js/main.js\"></script>\n\t</div>\n</body>\n\n</html>"
  },
  {
    "path": "open-layui-web/src/main/view/static/js/app.js",
    "content": "/*****\n * CONFIGURATION\n */\n\n// Active ajax page loader\n$.ajaxLoad = true;\n\n//required when $.ajaxLoad = true\n//$.defaultPage = \"main\";\n$.subPagesDirectory = '/';\n$.page404 = '404';\n$.mainContent = $('#ui-view');\n$.breadcrumbContent = $('#breadcrumb-view');\n\n//Main navigation\n$.navigation = $('nav > ul.nav');\n\n$.panelIconOpened = 'icon-arrow-up';\n$.panelIconClosed = 'icon-arrow-down';\n\n//Default colours\n$.brandPrimary =  '#20a8d8';\n$.brandSuccess =  '#4dbd74';\n$.brandInfo =     '#63c2de';\n$.brandWarning =  '#f8cb00';\n$.brandDanger =   '#f86c6b';\n\n$.grayDark =      '#2a2c36';\n$.gray =          '#55595c';\n$.grayLight =     '#818a91';\n$.grayLighter =   '#d1d4d7';\n$.grayLightest =  '#f8f9fa';\n\n'use strict';\n\n/*****\n * ASYNC LOAD\n * Load JS files and CSS files asynchronously in ajax mode\n */\nfunction loadJS(jsFiles, pageScript) {\n\n  var i;\n  for(i = 0; i<jsFiles.length;i++){\n\n    var body = document.getElementsByTagName('body')[0];\n    var script = document.createElement('script');\n    script.type = 'text/javascript';\n    script.async = false;\n    script.src = jsFiles[i];\n    body.appendChild(script);\n  }\n\n  if (pageScript) {\n    var body = document.getElementsByTagName('body')[0];\n    var script = document.createElement('script');\n    script.type = 'text/javascript';\n    script.async = false;\n    script.src = pageScript;\n    body.appendChild(script);\n  }\n\n  init();\n}\n\nfunction loadCSS(cssFile, end, callback) {\n\n  var cssArray = {};\n\n  if (!cssArray[cssFile]) {\n    cssArray[cssFile] = true;\n\n    if (end == 1) {\n\n      var head = document.getElementsByTagName('head')[0];\n      var s = document.createElement('link');\n      s.setAttribute('rel', 'stylesheet');\n      s.setAttribute('type', 'text/css');\n      s.setAttribute('href', cssFile);\n\n      s.onload = callback;\n      head.appendChild(s);\n\n    } else {\n\n      var head = document.getElementsByTagName('head')[0];\n      var style = document.getElementById('main-style');\n\n      var s = document.createElement('link');\n      s.setAttribute('rel', 'stylesheet');\n      s.setAttribute('type', 'text/css');\n      s.setAttribute('href', cssFile);\n\n      s.onload = callback;\n      head.insertBefore(s, style);\n\n    }\n\n  } else if (callback) {\n    callback();\n  }\n\n}\n\n/****\n * AJAX LOAD\n * Load pages asynchronously in ajax mode\n */\n\nif ($.ajaxLoad) {\n\n  var paceOptions = {\n    elements: false,\n    restartOnRequestAfter: false\n  };\n\n  var url = location.hash.replace(/^#/, '');\n\n  if (url != '') {\n    setUpUrl(url);\n  } else if($.indexPage!=''){\n    setUpUrl($.indexPage);\n  } else {\n    setUpUrl($.defaultPage);\n  }\n\n  $(document).on('click', 'a[href!=\"#\"]', function(e) {\n    if ( $(this).parent().parent().hasClass('nav-tabs') || $(this).parent().parent().hasClass('nav-pills')||$(this).attr('href')==\"javascript:;\") {\n      e.preventDefault();\n    } else if ( $(this).attr('target') == '_top' ) {\n      e.preventDefault();\n      var target = $(e.currentTarget);\n      window.location = (target.attr('href'));\n    } else if ( $(this).attr('target') == '_blank' ) {\n      e.preventDefault();\n      var target = $(e.currentTarget);\n      window.open(target.attr('href'));\n    } else{\n      e.preventDefault();\n      var target = $(e.currentTarget);\n      if(target.attr('href')!=undefined) {\n        setUpUrl(target.attr('href'));\n      }\n    }\n  });\n}\n\n$(document).on('click', 'a[href=\"#\"]', function(e) {\n  e.preventDefault();\n});\n\nfunction setUpUrl(url) {\n  if(url.indexOf(\"@\") < 0) {\n    $('nav .nav li .nav-link').removeClass('active');\n    $('nav .nav li.nav-dropdown').removeClass('open');\n    $('nav .nav li:has(a[href=\"' + url.split('?')[0] + '\"])').addClass('open');\n    $('nav .nav a[href=\"' + url.split('?')[0] + '\"]').addClass('active');\n    loadPage(url);\n  }else\n  {\n    $('nav .nav li .nav-link').removeClass('active');\n    $('nav .nav li.nav-dropdown').removeClass('open');\n    $('nav .nav li:has(a[href=\"' + url.split('@')[0].split('?')[0] + '\"])').addClass('open');\n    $('nav .nav a[href=\"' + url.split('@')[0].split('?')[0] + '\"]').addClass('active');\n    loadPage(url.split('@')[1]);\n  }\n\n\n}\n\nfunction loadPage(url) {\n  $.ajax({\n    type : 'GET',\n    url : $.subPagesDirectory +'api/'+ url,\n    dataType : 'json',\n    beforeSend: function () {\n      $.breadcrumbContent.html(\"\");\n      $.mainContent.css({opacity: 0});\n    },\n    success : function(responseText) {\n      //加载面包屑\n      for(var index in responseText)\n      {\n        if(responseText[index].url!== null && typeof(responseText[index].url)!=\"undefined\"){\n          if(responseText[index].isleaf==\"Y\") {\n            $.breadcrumbContent.append(\"<li class='breadcrumb-item active'>\"\n                + responseText[index].name\n                + \"</li>\");\n          }else\n          {\n            $.breadcrumbContent.append(\"<li class='nav breadcrumb-item'>\"\n                + \"<a href='\" + responseText[index].url + \"'>\" + responseText[index].name + \"</a>\"\n                + \"</li>\");\n          }\n        }else{\n          if(responseText[index].isleaf==\"Y\") {\n            $.breadcrumbContent.append(\"<li class='breadcrumb-item active'>\"\n                + responseText[index].name\n                + \"</li>\");\n          }else\n          {\n            $.breadcrumbContent.append(\"<li class='breadcrumb-item'>\"\n                +responseText[index].name\n                +\"</li>\");\n          }\n\n        }\n      }\n      //加载页面\n      $('html, body').animate({scrollTop: 0}, 0);\n      $.mainContent.load($.subPagesDirectory + url, null, function (responseText,status,xhr) {\n        if(status==\"success\") {\n          window.location.hash=url;\n        }else{\n          window.location.href = $.page404;\n        }\n      }).delay(250).animate({opacity: 1}, 0);\n\n    },\n    error : function(XMLHttpRequest, textStatus, errorThrown) {\n      window.location.href = $.page404;\n    }\n  });\n}\n\n/****\n * MAIN NAVIGATION\n */\n\n$(document).ready(function($){\n\n  // Add class .active to current link - AJAX Mode off\n  $.navigation.find('a').each(function(){\n\n    var cUrl = String(window.location).split('?')[0];\n\n    if (cUrl.substr(cUrl.length - 1) == '#') {\n      cUrl = cUrl.slice(0,-1);\n    }\n\n    if ($($(this))[0].href==cUrl) {\n      $(this).addClass('active');\n\n      $(this).parents('ul').add(this).each(function(){\n        $(this).parent().addClass('open');\n      });\n    }\n  });\n\n  // Dropdown Menu\n  $.navigation.on('click', 'a', function(e){\n\n    if ($.ajaxLoad) {\n      e.preventDefault();\n    }\n\n    if ($(this).hasClass('nav-dropdown-toggle')) {\n      $(this).parent().toggleClass('open');\n      resizeBroadcast();\n    }\n  });\n\n  function resizeBroadcast() {\n\n    var timesRun = 0;\n    var interval = setInterval(function(){\n      timesRun += 1;\n      if(timesRun === 5){\n        clearInterval(interval);\n      }\n      window.dispatchEvent(new Event('resize'));\n    }, 62.5);\n  }\n\n  /* ---------- Main Menu Open/Close, Min/Full ---------- */\n  $('.sidebar-toggler').click(function(){\n    $('body').toggleClass('sidebar-hidden');\n    resizeBroadcast();\n  });\n\n  $('.sidebar-minimizer').click(function(){\n    $('body').toggleClass('sidebar-minimized');\n    resizeBroadcast();\n  });\n\n  $('.brand-minimizer').click(function(){\n    $('body').toggleClass('brand-minimized');\n  });\n\n  $('.aside-menu-toggler').click(function(){\n    $('body').toggleClass('aside-menu-hidden');\n    resizeBroadcast();\n  });\n\n  $('.mobile-sidebar-toggler').click(function(){\n    $('body').toggleClass('sidebar-mobile-show');\n    resizeBroadcast();\n  });\n\n  $('.sidebar-close').click(function(){\n    $('body').toggleClass('sidebar-opened').parent().toggleClass('sidebar-opened');\n  });\n\n  /* ---------- Disable moving to top ---------- */\n  $('a[href=\"#\"][data-top!=true]').click(function(e){\n    e.preventDefault();\n  });\n\n});\n\n/****\n * CARDS ACTIONS\n */\n\n$(document).on('click', '.card-actions a', function(e){\n  e.preventDefault();\n\n  if ($(this).hasClass('btn-close')) {\n    $(this).parent().parent().parent().fadeOut();\n  } else if ($(this).hasClass('btn-minimize')) {\n    var $target = $(this).parent().parent().next('.card-body');\n    if (!$(this).hasClass('collapsed')) {\n      $('i',$(this)).removeClass($.panelIconOpened).addClass($.panelIconClosed);\n    } else {\n      $('i',$(this)).removeClass($.panelIconClosed).addClass($.panelIconOpened);\n    }\n\n  } else if ($(this).hasClass('btn-setting')) {\n    $('#myModal').modal('show');\n  }\n\n});\n\nfunction capitalizeFirstLetter(string) {\n  return string.charAt(0).toUpperCase() + string.slice(1);\n}\n\nfunction init(url) {\n\n  /* ---------- Tooltip ---------- */\n  $('[rel=\"tooltip\"],[data-rel=\"tooltip\"]').tooltip({\"placement\":\"bottom\",delay: { show: 400, hide: 200 }});\n\n  /* ---------- Popover ---------- */\n  $('[rel=\"popover\"],[data-rel=\"popover\"],[data-toggle=\"popover\"]').popover();\n\n}\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/js/bootstrap/bootstrap-treeview.js",
    "content": "/* =========================================================\n * bootstrap-treeview.js v1.2.0\n * =========================================================\n * Copyright 2013 Jonathan Miles\n * Project URL : http://www.jondmiles.com/bootstrap-treeview\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;(function ($, window, document, undefined) {\n\n\t/*global jQuery, console*/\n\n\t'use strict';\n\n\tvar pluginName = 'treeview';\n\n\tvar _default = {};\n\n\t_default.settings = {\n\n\t\tinjectStyle: true,\n\n\t\tlevels: 2,\n\n\t\texpandIcon: 'glyphicon glyphicon-plus',\n\t\tcollapseIcon: 'glyphicon glyphicon-minus',\n\t\temptyIcon: 'glyphicon',\n\t\tnodeIcon: '',\n\t\tselectedIcon: '',\n\t\tcheckedIcon: 'glyphicon glyphicon-check',\n\t\tuncheckedIcon: 'glyphicon glyphicon-unchecked',\n\n\t\tcolor: undefined, // '#000000',\n\t\tbackColor: undefined, // '#FFFFFF',\n\t\tborderColor: undefined, // '#dddddd',\n\t\tonhoverColor: '#F5F5F5',\n\t\tselectedColor: '#FFFFFF',\n\t\tselectedBackColor: '#428bca',\n\t\tsearchResultColor: '#D9534F',\n\t\tsearchResultBackColor: undefined, //'#FFFFFF',\n\n\t\tenableLinks: false,\n\t\thighlightSelected: true,\n\t\thighlightSearchResults: true,\n\t\tshowBorder: true,\n\t\tshowIcon: true,\n\t\tshowCheckbox: false,\n\t\tshowTags: false,\n\t\tmultiSelect: false,\n\n\t\t// Event handlers\n\t\tonNodeChecked: undefined,\n\t\tonNodeCollapsed: undefined,\n\t\tonNodeDisabled: undefined,\n\t\tonNodeEnabled: undefined,\n\t\tonNodeExpanded: undefined,\n\t\tonNodeSelected: undefined,\n\t\tonNodeUnchecked: undefined,\n\t\tonNodeUnselected: undefined,\n\t\tonSearchComplete: undefined,\n\t\tonSearchCleared: undefined\n\t};\n\n\t_default.options = {\n\t\tsilent: false,\n\t\tignoreChildren: false\n\t};\n\n\t_default.searchOptions = {\n\t\tignoreCase: true,\n\t\texactMatch: false,\n\t\trevealResults: true\n\t};\n\n\tvar Tree = function (element, options) {\n\n\t\tthis.$element = $(element);\n\t\tthis.elementId = element.id;\n\t\tthis.styleId = this.elementId + '-style';\n\n\t\tthis.init(options);\n\n\t\treturn {\n\n\t\t\t// Options (public access)\n\t\t\toptions: this.options,\n\n\t\t\t// Initialize / destroy methods\n\t\t\tinit: $.proxy(this.init, this),\n\t\t\tremove: $.proxy(this.remove, this),\n\n\t\t\t// Get methods\n\t\t\tgetNode: $.proxy(this.getNode, this),\n\t\t\tgetParent: $.proxy(this.getParent, this),\n\t\t\tgetSiblings: $.proxy(this.getSiblings, this),\n\t\t\tgetSelected: $.proxy(this.getSelected, this),\n\t\t\tgetUnselected: $.proxy(this.getUnselected, this),\n\t\t\tgetExpanded: $.proxy(this.getExpanded, this),\n\t\t\tgetCollapsed: $.proxy(this.getCollapsed, this),\n\t\t\tgetChecked: $.proxy(this.getChecked, this),\n\t\t\tgetUnchecked: $.proxy(this.getUnchecked, this),\n\t\t\tgetDisabled: $.proxy(this.getDisabled, this),\n\t\t\tgetEnabled: $.proxy(this.getEnabled, this),\n\n\t\t\t// Select methods\n\t\t\tselectNode: $.proxy(this.selectNode, this),\n\t\t\tunselectNode: $.proxy(this.unselectNode, this),\n\t\t\ttoggleNodeSelected: $.proxy(this.toggleNodeSelected, this),\n\n\t\t\t// Expand / collapse methods\n\t\t\tcollapseAll: $.proxy(this.collapseAll, this),\n\t\t\tcollapseNode: $.proxy(this.collapseNode, this),\n\t\t\texpandAll: $.proxy(this.expandAll, this),\n\t\t\texpandNode: $.proxy(this.expandNode, this),\n\t\t\ttoggleNodeExpanded: $.proxy(this.toggleNodeExpanded, this),\n\t\t\trevealNode: $.proxy(this.revealNode, this),\n\n\t\t\t// Expand / collapse methods\n\t\t\tcheckAll: $.proxy(this.checkAll, this),\n\t\t\tcheckNode: $.proxy(this.checkNode, this),\n\t\t\tuncheckAll: $.proxy(this.uncheckAll, this),\n\t\t\tuncheckNode: $.proxy(this.uncheckNode, this),\n\t\t\ttoggleNodeChecked: $.proxy(this.toggleNodeChecked, this),\n\n\t\t\t// Disable / enable methods\n\t\t\tdisableAll: $.proxy(this.disableAll, this),\n\t\t\tdisableNode: $.proxy(this.disableNode, this),\n\t\t\tenableAll: $.proxy(this.enableAll, this),\n\t\t\tenableNode: $.proxy(this.enableNode, this),\n\t\t\ttoggleNodeDisabled: $.proxy(this.toggleNodeDisabled, this),\n\n\t\t\t// Search methods\n\t\t\tsearch: $.proxy(this.search, this),\n\t\t\tclearSearch: $.proxy(this.clearSearch, this)\n\t\t};\n\t};\n\n\tTree.prototype.init = function (options) {\n\n\t\tthis.tree = [];\n\t\tthis.nodes = [];\n\n\t\tif (options.data) {\n\t\t\tif (typeof options.data === 'string') {\n\t\t\t\toptions.data = $.parseJSON(options.data);\n\t\t\t}\n\t\t\tthis.tree = $.extend(true, [], options.data);\n\t\t\tdelete options.data;\n\t\t}\n\t\tthis.options = $.extend({}, _default.settings, options);\n\n\t\tthis.destroy();\n\t\tthis.subscribeEvents();\n\t\tthis.setInitialStates({ nodes: this.tree }, 0);\n\t\tthis.render();\n\t};\n\n\tTree.prototype.remove = function () {\n\t\tthis.destroy();\n\t\t$.removeData(this, pluginName);\n\t\t$('#' + this.styleId).remove();\n\t};\n\n\tTree.prototype.destroy = function () {\n\n\t\tif (!this.initialized) return;\n\n\t\tthis.$wrapper.remove();\n\t\tthis.$wrapper = null;\n\n\t\t// Switch off events\n\t\tthis.unsubscribeEvents();\n\n\t\t// Reset this.initialized flag\n\t\tthis.initialized = false;\n\t};\n\n\tTree.prototype.unsubscribeEvents = function () {\n\n\t\tthis.$element.off('click');\n\t\tthis.$element.off('nodeChecked');\n\t\tthis.$element.off('nodeCollapsed');\n\t\tthis.$element.off('nodeDisabled');\n\t\tthis.$element.off('nodeEnabled');\n\t\tthis.$element.off('nodeExpanded');\n\t\tthis.$element.off('nodeSelected');\n\t\tthis.$element.off('nodeUnchecked');\n\t\tthis.$element.off('nodeUnselected');\n\t\tthis.$element.off('searchComplete');\n\t\tthis.$element.off('searchCleared');\n\t};\n\n\tTree.prototype.subscribeEvents = function () {\n\n\t\tthis.unsubscribeEvents();\n\n\t\tthis.$element.on('click', $.proxy(this.clickHandler, this));\n\n\t\tif (typeof (this.options.onNodeChecked) === 'function') {\n\t\t\tthis.$element.on('nodeChecked', this.options.onNodeChecked);\n\t\t}\n\n\t\tif (typeof (this.options.onNodeCollapsed) === 'function') {\n\t\t\tthis.$element.on('nodeCollapsed', this.options.onNodeCollapsed);\n\t\t}\n\n\t\tif (typeof (this.options.onNodeDisabled) === 'function') {\n\t\t\tthis.$element.on('nodeDisabled', this.options.onNodeDisabled);\n\t\t}\n\n\t\tif (typeof (this.options.onNodeEnabled) === 'function') {\n\t\t\tthis.$element.on('nodeEnabled', this.options.onNodeEnabled);\n\t\t}\n\n\t\tif (typeof (this.options.onNodeExpanded) === 'function') {\n\t\t\tthis.$element.on('nodeExpanded', this.options.onNodeExpanded);\n\t\t}\n\n\t\tif (typeof (this.options.onNodeSelected) === 'function') {\n\t\t\tthis.$element.on('nodeSelected', this.options.onNodeSelected);\n\t\t}\n\n\t\tif (typeof (this.options.onNodeUnchecked) === 'function') {\n\t\t\tthis.$element.on('nodeUnchecked', this.options.onNodeUnchecked);\n\t\t}\n\n\t\tif (typeof (this.options.onNodeUnselected) === 'function') {\n\t\t\tthis.$element.on('nodeUnselected', this.options.onNodeUnselected);\n\t\t}\n\n\t\tif (typeof (this.options.onSearchComplete) === 'function') {\n\t\t\tthis.$element.on('searchComplete', this.options.onSearchComplete);\n\t\t}\n\n\t\tif (typeof (this.options.onSearchCleared) === 'function') {\n\t\t\tthis.$element.on('searchCleared', this.options.onSearchCleared);\n\t\t}\n\t};\n\n\t/*\n\t\tRecurse the tree structure and ensure all nodes have\n\t\tvalid initial states.  User defined states will be preserved.\n\t\tFor performance we also take this opportunity to\n\t\tindex nodes in a flattened structure\n\t*/\n\tTree.prototype.setInitialStates = function (node, level) {\n\n\t\tif (!node.nodes) return;\n\t\tlevel += 1;\n\n\t\tvar parent = node;\n\t\tvar _this = this;\n\t\t$.each(node.nodes, function checkStates(index, node) {\n\n\t\t\t// nodeId : unique, incremental identifier\n\t\t\tnode.nodeId = _this.nodes.length;\n\n\t\t\t// parentId : transversing up the tree\n\t\t\tnode.parentId = parent.nodeId;\n\n\t\t\t// if not provided set selectable default value\n\t\t\tif (!node.hasOwnProperty('selectable')) {\n\t\t\t\tnode.selectable = true;\n\t\t\t}\n\n\t\t\t// where provided we should preserve states\n\t\t\tnode.state = node.state || {};\n\n\t\t\t// set checked state; unless set always false\n\t\t\tif (!node.state.hasOwnProperty('checked')) {\n\t\t\t\tnode.state.checked = false;\n\t\t\t}\n\n\t\t\t// set enabled state; unless set always false\n\t\t\tif (!node.state.hasOwnProperty('disabled')) {\n\t\t\t\tnode.state.disabled = false;\n\t\t\t}\n\n\t\t\t// set expanded state; if not provided based on levels\n\t\t\tif (!node.state.hasOwnProperty('expanded')) {\n\t\t\t\tif (!node.state.disabled &&\n\t\t\t\t\t\t(level < _this.options.levels) &&\n\t\t\t\t\t\t(node.nodes && node.nodes.length > 0)) {\n\t\t\t\t\tnode.state.expanded = true;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tnode.state.expanded = false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// set selected state; unless set always false\n\t\t\tif (!node.state.hasOwnProperty('selected')) {\n\t\t\t\tnode.state.selected = false;\n\t\t\t}\n\n\t\t\t// index nodes in a flattened structure for use later\n\t\t\t_this.nodes.push(node);\n\n\t\t\t// recurse child nodes and transverse the tree\n\t\t\tif (node.nodes) {\n\t\t\t\t_this.setInitialStates(node, level);\n\t\t\t}\n\t\t});\n\t};\n\n\tTree.prototype.clickHandler = function (event) {\n\n\t\tif (!this.options.enableLinks) event.preventDefault();\n\n\t\tvar target = $(event.target);\n\t\tvar node = this.findNode(target);\n\t\tif (!node || node.state.disabled) return;\n\t\t\n\t\tvar classList = target.attr('class') ? target.attr('class').split(' ') : [];\n\t\tif ((classList.indexOf('expand-icon') !== -1)) {\n\n\t\t\tthis.toggleExpandedState(node, _default.options);\n\t\t\tthis.render();\n\t\t}\n\t\telse if ((classList.indexOf('check-icon') !== -1)) {\n\t\t\t\n\t\t\tthis.toggleCheckedState(node, _default.options);\n\t\t\tthis.render();\n\t\t}\n\t\telse {\n\t\t\t\n\t\t\tif (node.selectable) {\n\t\t\t\tthis.toggleSelectedState(node, _default.options);\n\t\t\t} else {\n\t\t\t\tthis.toggleExpandedState(node, _default.options);\n\t\t\t}\n\n\t\t\tthis.render();\n\t\t}\n\t};\n\n\t// Looks up the DOM for the closest parent list item to retrieve the\n\t// data attribute nodeid, which is used to lookup the node in the flattened structure.\n\tTree.prototype.findNode = function (target) {\n\n\t\tvar nodeId = target.closest('li.list-group-item').attr('data-nodeid');\n\t\tvar node = this.nodes[nodeId];\n\n\t\tif (!node) {\n\t\t\tconsole.log('Error: node does not exist');\n\t\t}\n\t\treturn node;\n\t};\n\n\tTree.prototype.toggleExpandedState = function (node, options) {\n\t\tif (!node) return;\n\t\tthis.setExpandedState(node, !node.state.expanded, options);\n\t};\n\n\tTree.prototype.setExpandedState = function (node, state, options) {\n\n\t\tif (state === node.state.expanded) return;\n\n\t\tif (state && node.nodes) {\n\n\t\t\t// Expand a node\n\t\t\tnode.state.expanded = true;\n\t\t\tif (!options.silent) {\n\t\t\t\tthis.$element.trigger('nodeExpanded', $.extend(true, {}, node));\n\t\t\t}\n\t\t}\n\t\telse if (!state) {\n\n\t\t\t// Collapse a node\n\t\t\tnode.state.expanded = false;\n\t\t\tif (!options.silent) {\n\t\t\t\tthis.$element.trigger('nodeCollapsed', $.extend(true, {}, node));\n\t\t\t}\n\n\t\t\t// Collapse child nodes\n\t\t\tif (node.nodes && !options.ignoreChildren) {\n\t\t\t\t$.each(node.nodes, $.proxy(function (index, node) {\n\t\t\t\t\tthis.setExpandedState(node, false, options);\n\t\t\t\t}, this));\n\t\t\t}\n\t\t}\n\t};\n\n\tTree.prototype.toggleSelectedState = function (node, options) {\n\t\tif (!node) return;\n\t\tthis.setSelectedState(node, !node.state.selected, options);\n\t};\n\n\tTree.prototype.setSelectedState = function (node, state, options) {\n\n\t\tif (state === node.state.selected) return;\n\n\t\tif (state) {\n\n\t\t\t// If multiSelect false, unselect previously selected\n\t\t\tif (!this.options.multiSelect) {\n\t\t\t\t$.each(this.findNodes('true', 'g', 'state.selected'), $.proxy(function (index, node) {\n\t\t\t\t\tthis.setSelectedState(node, false, options);\n\t\t\t\t}, this));\n\t\t\t}\n\n\t\t\t// Continue selecting node\n\t\t\tnode.state.selected = true;\n\t\t\tif (!options.silent) {\n\t\t\t\tthis.$element.trigger('nodeSelected', $.extend(true, {}, node));\n\t\t\t}\n\t\t}\n\t\telse {\n\n\t\t\t// Unselect node\n\t\t\tnode.state.selected = false;\n\t\t\tif (!options.silent) {\n\t\t\t\tthis.$element.trigger('nodeUnselected', $.extend(true, {}, node));\n\t\t\t}\n\t\t}\n\t};\n\n\tTree.prototype.toggleCheckedState = function (node, options) {\n\t\tif (!node) return;\n\t\tthis.setCheckedState(node, !node.state.checked, options);\n\t};\n\n\tTree.prototype.setCheckedState = function (node, state, options) {\n\n\t\tif (state === node.state.checked) return;\n\n\t\tif (state) {\n\n\t\t\t// Check node\n\t\t\tnode.state.checked = true;\n\n\t\t\tif (!options.silent) {\n\t\t\t\tthis.$element.trigger('nodeChecked', $.extend(true, {}, node));\n\t\t\t}\n\t\t}\n\t\telse {\n\n\t\t\t// Uncheck node\n\t\t\tnode.state.checked = false;\n\t\t\tif (!options.silent) {\n\t\t\t\tthis.$element.trigger('nodeUnchecked', $.extend(true, {}, node));\n\t\t\t}\n\t\t}\n\t};\n\n\tTree.prototype.setDisabledState = function (node, state, options) {\n\n\t\tif (state === node.state.disabled) return;\n\n\t\tif (state) {\n\n\t\t\t// Disable node\n\t\t\tnode.state.disabled = true;\n\n\t\t\t// Disable all other states\n\t\t\tthis.setExpandedState(node, false, options);\n\t\t\tthis.setSelectedState(node, false, options);\n\t\t\tthis.setCheckedState(node, false, options);\n\n\t\t\tif (!options.silent) {\n\t\t\t\tthis.$element.trigger('nodeDisabled', $.extend(true, {}, node));\n\t\t\t}\n\t\t}\n\t\telse {\n\n\t\t\t// Enabled node\n\t\t\tnode.state.disabled = false;\n\t\t\tif (!options.silent) {\n\t\t\t\tthis.$element.trigger('nodeEnabled', $.extend(true, {}, node));\n\t\t\t}\n\t\t}\n\t};\n\n\tTree.prototype.render = function () {\n\n\t\tif (!this.initialized) {\n\n\t\t\t// Setup first time only components\n\t\t\tthis.$element.addClass(pluginName);\n\t\t\tthis.$wrapper = $(this.template.list);\n\n\t\t\tthis.injectStyle();\n\n\t\t\tthis.initialized = true;\n\t\t}\n\n\t\tthis.$element.empty().append(this.$wrapper.empty());\n\n\t\t// Build tree\n\t\tthis.buildTree(this.tree, 0);\n\t};\n\n\t// Starting from the root node, and recursing down the\n\t// structure we build the tree one node at a time\n\tTree.prototype.buildTree = function (nodes, level) {\n\n\t\tif (!nodes) return;\n\t\tlevel += 1;\n\n\t\tvar _this = this;\n\t\t$.each(nodes, function addNodes(id, node) {\n\n\t\t\tvar treeItem = $(_this.template.item)\n\t\t\t\t.addClass('node-' + _this.elementId)\n\t\t\t\t.addClass(node.state.checked ? 'node-checked' : '')\n\t\t\t\t.addClass(node.state.disabled ? 'node-disabled': '')\n\t\t\t\t.addClass(node.state.selected ? 'node-selected' : '')\n\t\t\t\t.addClass(node.searchResult ? 'search-result' : '') \n\t\t\t\t.attr('data-nodeid', node.nodeId)\n\t\t\t\t.attr('style', _this.buildStyleOverride(node));\n\n\t\t\t// Add indent/spacer to mimic tree structure\n\t\t\tfor (var i = 0; i < (level - 1); i++) {\n\t\t\t\ttreeItem.append(_this.template.indent);\n\t\t\t}\n\n\t\t\t// Add expand, collapse or empty spacer icons\n\t\t\tvar classList = [];\n\t\t\tif (node.nodes) {\n\t\t\t\tclassList.push('expand-icon');\n\t\t\t\tif (node.state.expanded) {\n\t\t\t\t\tclassList.push(_this.options.collapseIcon);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tclassList.push(_this.options.expandIcon);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tclassList.push(_this.options.emptyIcon);\n\t\t\t}\n\n\t\t\ttreeItem\n\t\t\t\t.append($(_this.template.icon)\n\t\t\t\t\t.addClass(classList.join(' '))\n\t\t\t\t);\n\n\n\t\t\t// Add node icon\n\t\t\tif (_this.options.showIcon) {\n\t\t\t\t\n\t\t\t\tvar classList = ['node-icon'];\n\n\t\t\t\tclassList.push(node.icon || _this.options.nodeIcon);\n\t\t\t\tif (node.state.selected) {\n\t\t\t\t\tclassList.pop();\n\t\t\t\t\tclassList.push(node.selectedIcon || _this.options.selectedIcon || \n\t\t\t\t\t\t\t\t\tnode.icon || _this.options.nodeIcon);\n\t\t\t\t}\n\n\t\t\t\ttreeItem\n\t\t\t\t\t.append($(_this.template.icon)\n\t\t\t\t\t\t.addClass(classList.join(' '))\n\t\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Add check / unchecked icon\n\t\t\tif (_this.options.showCheckbox) {\n\n\t\t\t\tvar classList = ['check-icon'];\n\t\t\t\tif (node.state.checked) {\n\t\t\t\t\tclassList.push(_this.options.checkedIcon); \n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tclassList.push(_this.options.uncheckedIcon);\n\t\t\t\t}\n\n\t\t\t\ttreeItem\n\t\t\t\t\t.append($(_this.template.icon)\n\t\t\t\t\t\t.addClass(classList.join(' '))\n\t\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Add text\n\t\t\tif (_this.options.enableLinks) {\n\t\t\t\t// Add hyperlink\n\t\t\t\ttreeItem\n\t\t\t\t\t.append($(_this.template.link)\n\t\t\t\t\t\t.attr('href', node.href)\n\t\t\t\t\t\t.append(node.text)\n\t\t\t\t\t);\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// otherwise just text\n\t\t\t\ttreeItem\n\t\t\t\t\t.append(node.text);\n\t\t\t}\n\n\t\t\t// Add tags as badges\n\t\t\tif (_this.options.showTags && node.tags) {\n\t\t\t\t$.each(node.tags, function addTag(id, tag) {\n\t\t\t\t\ttreeItem\n\t\t\t\t\t\t.append($(_this.template.badge)\n\t\t\t\t\t\t\t.append(tag)\n\t\t\t\t\t\t);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Add item to the tree\n\t\t\t_this.$wrapper.append(treeItem);\n\n\t\t\t// Recursively add child ndoes\n\t\t\tif (node.nodes && node.state.expanded && !node.state.disabled) {\n\t\t\t\treturn _this.buildTree(node.nodes, level);\n\t\t\t}\n\t\t});\n\t};\n\n\t// Define any node level style override for\n\t// 1. selectedNode\n\t// 2. node|data assigned color overrides\n\tTree.prototype.buildStyleOverride = function (node) {\n\n\t\tif (node.state.disabled) return '';\n\n\t\tvar color = node.color;\n\t\tvar backColor = node.backColor;\n\n\t\tif (this.options.highlightSelected && node.state.selected) {\n\t\t\tif (this.options.selectedColor) {\n\t\t\t\tcolor = this.options.selectedColor;\n\t\t\t}\n\t\t\tif (this.options.selectedBackColor) {\n\t\t\t\tbackColor = this.options.selectedBackColor;\n\t\t\t}\n\t\t}\n\n\t\tif (this.options.highlightSearchResults && node.searchResult && !node.state.disabled) {\n\t\t\tif (this.options.searchResultColor) {\n\t\t\t\tcolor = this.options.searchResultColor;\n\t\t\t}\n\t\t\tif (this.options.searchResultBackColor) {\n\t\t\t\tbackColor = this.options.searchResultBackColor;\n\t\t\t}\n\t\t}\n\n\t\treturn 'color:' + color +\n\t\t\t';background-color:' + backColor + ';';\n\t};\n\n\t// Add inline style into head\n\tTree.prototype.injectStyle = function () {\n\n\t\tif (this.options.injectStyle && !document.getElementById(this.styleId)) {\n\t\t\t$('<style type=\"text/css\" id=\"' + this.styleId + '\"> ' + this.buildStyle() + ' </style>').appendTo('head');\n\t\t}\n\t};\n\n\t// Construct trees style based on user options\n\tTree.prototype.buildStyle = function () {\n\n\t\tvar style = '.node-' + this.elementId + '{';\n\n\t\tif (this.options.color) {\n\t\t\tstyle += 'color:' + this.options.color + ';';\n\t\t}\n\n\t\tif (this.options.backColor) {\n\t\t\tstyle += 'background-color:' + this.options.backColor + ';';\n\t\t}\n\n\t\tif (!this.options.showBorder) {\n\t\t\tstyle += 'border:none;';\n\t\t}\n\t\telse if (this.options.borderColor) {\n\t\t\tstyle += 'border:1px solid ' + this.options.borderColor + ';';\n\t\t}\n\t\tstyle += '}';\n\n\t\tif (this.options.onhoverColor) {\n\t\t\tstyle += '.node-' + this.elementId + ':not(.node-disabled):hover{' +\n\t\t\t\t'background-color:' + this.options.onhoverColor + ';' +\n\t\t\t'}';\n\t\t}\n\n\t\treturn this.css + style;\n\t};\n\n\tTree.prototype.template = {\n\t\tlist: '<ul class=\"list-group\"></ul>',\n\t\titem: '<li class=\"list-group-item\"></li>',\n\t\tindent: '<span class=\"indent\"></span>',\n\t\ticon: '<span class=\"icon\"></span>',\n\t\tlink: '<a href=\"#\" style=\"color:inherit;\"></a>',\n\t\tbadge: '<span class=\"badge\"></span>'\n\t};\n\n\tTree.prototype.css = '.treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px}.treeview .node-disabled{color:silver;cursor:not-allowed}'\n\n\n\t/**\n\t\tReturns a single node object that matches the given node id.\n\t\t@param {Number} nodeId - A node's unique identifier\n\t\t@return {Object} node - Matching node\n\t*/\n\tTree.prototype.getNode = function (nodeId) {\n\t\treturn this.nodes[nodeId];\n\t};\n\n\t/**\n\t\tReturns the parent node of a given node, if valid otherwise returns undefined.\n\t\t@param {Object|Number} identifier - A valid node or node id\n\t\t@returns {Object} node - The parent node\n\t*/\n\tTree.prototype.getParent = function (identifier) {\n\t\tvar node = this.identifyNode(identifier);\n\t\treturn this.nodes[node.parentId];\n\t};\n\n\t/**\n\t\tReturns an array of sibling nodes for a given node, if valid otherwise returns undefined.\n\t\t@param {Object|Number} identifier - A valid node or node id\n\t\t@returns {Array} nodes - Sibling nodes\n\t*/\n\tTree.prototype.getSiblings = function (identifier) {\n\t\tvar node = this.identifyNode(identifier);\n\t\tvar parent = this.getParent(node);\n\t\tvar nodes = parent ? parent.nodes : this.tree;\n\t\treturn nodes.filter(function (obj) {\n\t\t\t\treturn obj.nodeId !== node.nodeId;\n\t\t\t});\n\t};\n\n\t/**\n\t\tReturns an array of selected nodes.\n\t\t@returns {Array} nodes - Selected nodes\n\t*/\n\tTree.prototype.getSelected = function () {\n\t\treturn this.findNodes('true', 'g', 'state.selected');\n\t};\n\n\t/**\n\t\tReturns an array of unselected nodes.\n\t\t@returns {Array} nodes - Unselected nodes\n\t*/\n\tTree.prototype.getUnselected = function () {\n\t\treturn this.findNodes('false', 'g', 'state.selected');\n\t};\n\n\t/**\n\t\tReturns an array of expanded nodes.\n\t\t@returns {Array} nodes - Expanded nodes\n\t*/\n\tTree.prototype.getExpanded = function () {\n\t\treturn this.findNodes('true', 'g', 'state.expanded');\n\t};\n\n\t/**\n\t\tReturns an array of collapsed nodes.\n\t\t@returns {Array} nodes - Collapsed nodes\n\t*/\n\tTree.prototype.getCollapsed = function () {\n\t\treturn this.findNodes('false', 'g', 'state.expanded');\n\t};\n\n\t/**\n\t\tReturns an array of checked nodes.\n\t\t@returns {Array} nodes - Checked nodes\n\t*/\n\tTree.prototype.getChecked = function () {\n\t\treturn this.findNodes('true', 'g', 'state.checked');\n\t};\n\n\t/**\n\t\tReturns an array of unchecked nodes.\n\t\t@returns {Array} nodes - Unchecked nodes\n\t*/\n\tTree.prototype.getUnchecked = function () {\n\t\treturn this.findNodes('false', 'g', 'state.checked');\n\t};\n\n\t/**\n\t\tReturns an array of disabled nodes.\n\t\t@returns {Array} nodes - Disabled nodes\n\t*/\n\tTree.prototype.getDisabled = function () {\n\t\treturn this.findNodes('true', 'g', 'state.disabled');\n\t};\n\n\t/**\n\t\tReturns an array of enabled nodes.\n\t\t@returns {Array} nodes - Enabled nodes\n\t*/\n\tTree.prototype.getEnabled = function () {\n\t\treturn this.findNodes('false', 'g', 'state.disabled');\n\t};\n\n\n\t/**\n\t\tSet a node state to selected\n\t\t@param {Object|Number} identifiers - A valid node, node id or array of node identifiers\n\t\t@param {optional Object} options\n\t*/\n\tTree.prototype.selectNode = function (identifiers, options) {\n\t\tthis.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {\n\t\t\tthis.setSelectedState(node, true, options);\n\t\t}, this));\n\n\t\tthis.render();\n\t};\n\n\t/**\n\t\tSet a node state to unselected\n\t\t@param {Object|Number} identifiers - A valid node, node id or array of node identifiers\n\t\t@param {optional Object} options\n\t*/\n\tTree.prototype.unselectNode = function (identifiers, options) {\n\t\tthis.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {\n\t\t\tthis.setSelectedState(node, false, options);\n\t\t}, this));\n\n\t\tthis.render();\n\t};\n\n\t/**\n\t\tToggles a node selected state; selecting if unselected, unselecting if selected.\n\t\t@param {Object|Number} identifiers - A valid node, node id or array of node identifiers\n\t\t@param {optional Object} options\n\t*/\n\tTree.prototype.toggleNodeSelected = function (identifiers, options) {\n\t\tthis.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {\n\t\t\tthis.toggleSelectedState(node, options);\n\t\t}, this));\n\n\t\tthis.render();\n\t};\n\n\n\t/**\n\t\tCollapse all tree nodes\n\t\t@param {optional Object} options\n\t*/\n\tTree.prototype.collapseAll = function (options) {\n\t\tvar identifiers = this.findNodes('true', 'g', 'state.expanded');\n\t\tthis.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {\n\t\t\tthis.setExpandedState(node, false, options);\n\t\t}, this));\n\n\t\tthis.render();\n\t};\n\n\t/**\n\t\tCollapse a given tree node\n\t\t@param {Object|Number} identifiers - A valid node, node id or array of node identifiers\n\t\t@param {optional Object} options\n\t*/\n\tTree.prototype.collapseNode = function (identifiers, options) {\n\t\tthis.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {\n\t\t\tthis.setExpandedState(node, false, options);\n\t\t}, this));\n\n\t\tthis.render();\n\t};\n\n\t/**\n\t\tExpand all tree nodes\n\t\t@param {optional Object} options\n\t*/\n\tTree.prototype.expandAll = function (options) {\n\t\toptions = $.extend({}, _default.options, options);\n\n\t\tif (options && options.levels) {\n\t\t\tthis.expandLevels(this.tree, options.levels, options);\n\t\t}\n\t\telse {\n\t\t\tvar identifiers = this.findNodes('false', 'g', 'state.expanded');\n\t\t\tthis.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {\n\t\t\t\tthis.setExpandedState(node, true, options);\n\t\t\t}, this));\n\t\t}\n\n\t\tthis.render();\n\t};\n\n\t/**\n\t\tExpand a given tree node\n\t\t@param {Object|Number} identifiers - A valid node, node id or array of node identifiers\n\t\t@param {optional Object} options\n\t*/\n\tTree.prototype.expandNode = function (identifiers, options) {\n\t\tthis.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {\n\t\t\tthis.setExpandedState(node, true, options);\n\t\t\tif (node.nodes && (options && options.levels)) {\n\t\t\t\tthis.expandLevels(node.nodes, options.levels-1, options);\n\t\t\t}\n\t\t}, this));\n\n\t\tthis.render();\n\t};\n\n\tTree.prototype.expandLevels = function (nodes, level, options) {\n\t\toptions = $.extend({}, _default.options, options);\n\n\t\t$.each(nodes, $.proxy(function (index, node) {\n\t\t\tthis.setExpandedState(node, (level > 0) ? true : false, options);\n\t\t\tif (node.nodes) {\n\t\t\t\tthis.expandLevels(node.nodes, level-1, options);\n\t\t\t}\n\t\t}, this));\n\t};\n\n\t/**\n\t\tReveals a given tree node, expanding the tree from node to root.\n\t\t@param {Object|Number|Array} identifiers - A valid node, node id or array of node identifiers\n\t\t@param {optional Object} options\n\t*/\n\tTree.prototype.revealNode = function (identifiers, options) {\n\t\tthis.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {\n\t\t\tvar parentNode = this.getParent(node);\n\t\t\twhile (parentNode) {\n\t\t\t\tthis.setExpandedState(parentNode, true, options);\n\t\t\t\tparentNode = this.getParent(parentNode);\n\t\t\t};\n\t\t}, this));\n\n\t\tthis.render();\n\t};\n\n\t/**\n\t\tToggles a nodes expanded state; collapsing if expanded, expanding if collapsed.\n\t\t@param {Object|Number} identifiers - A valid node, node id or array of node identifiers\n\t\t@param {optional Object} options\n\t*/\n\tTree.prototype.toggleNodeExpanded = function (identifiers, options) {\n\t\tthis.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {\n\t\t\tthis.toggleExpandedState(node, options);\n\t\t}, this));\n\t\t\n\t\tthis.render();\n\t};\n\n\n\t/**\n\t\tCheck all tree nodes\n\t\t@param {optional Object} options\n\t*/\n\tTree.prototype.checkAll = function (options) {\n\t\tvar identifiers = this.findNodes('false', 'g', 'state.checked');\n\t\tthis.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {\n\t\t\tthis.setCheckedState(node, true, options);\n\t\t}, this));\n\n\t\tthis.render();\n\t};\n\n\t/**\n\t\tCheck a given tree node\n\t\t@param {Object|Number} identifiers - A valid node, node id or array of node identifiers\n\t\t@param {optional Object} options\n\t*/\n\tTree.prototype.checkNode = function (identifiers, options) {\n\t\tthis.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {\n\t\t\tthis.setCheckedState(node, true, options);\n\t\t}, this));\n\n\t\tthis.render();\n\t};\n\n\t/**\n\t\tUncheck all tree nodes\n\t\t@param {optional Object} options\n\t*/\n\tTree.prototype.uncheckAll = function (options) {\n\t\tvar identifiers = this.findNodes('true', 'g', 'state.checked');\n\t\tthis.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {\n\t\t\tthis.setCheckedState(node, false, options);\n\t\t}, this));\n\n\t\tthis.render();\n\t};\n\n\t/**\n\t\tUncheck a given tree node\n\t\t@param {Object|Number} identifiers - A valid node, node id or array of node identifiers\n\t\t@param {optional Object} options\n\t*/\n\tTree.prototype.uncheckNode = function (identifiers, options) {\n\t\tthis.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {\n\t\t\tthis.setCheckedState(node, false, options);\n\t\t}, this));\n\n\t\tthis.render();\n\t};\n\n\t/**\n\t\tToggles a nodes checked state; checking if unchecked, unchecking if checked.\n\t\t@param {Object|Number} identifiers - A valid node, node id or array of node identifiers\n\t\t@param {optional Object} options\n\t*/\n\tTree.prototype.toggleNodeChecked = function (identifiers, options) {\n\t\tthis.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {\n\t\t\tthis.toggleCheckedState(node, options);\n\t\t}, this));\n\n\t\tthis.render();\n\t};\n\n\n\t/**\n\t\tDisable all tree nodes\n\t\t@param {optional Object} options\n\t*/\n\tTree.prototype.disableAll = function (options) {\n\t\tvar identifiers = this.findNodes('false', 'g', 'state.disabled');\n\t\tthis.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {\n\t\t\tthis.setDisabledState(node, true, options);\n\t\t}, this));\n\n\t\tthis.render();\n\t};\n\n\t/**\n\t\tDisable a given tree node\n\t\t@param {Object|Number} identifiers - A valid node, node id or array of node identifiers\n\t\t@param {optional Object} options\n\t*/\n\tTree.prototype.disableNode = function (identifiers, options) {\n\t\tthis.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {\n\t\t\tthis.setDisabledState(node, true, options);\n\t\t}, this));\n\n\t\tthis.render();\n\t};\n\n\t/**\n\t\tEnable all tree nodes\n\t\t@param {optional Object} options\n\t*/\n\tTree.prototype.enableAll = function (options) {\n\t\tvar identifiers = this.findNodes('true', 'g', 'state.disabled');\n\t\tthis.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {\n\t\t\tthis.setDisabledState(node, false, options);\n\t\t}, this));\n\n\t\tthis.render();\n\t};\n\n\t/**\n\t\tEnable a given tree node\n\t\t@param {Object|Number} identifiers - A valid node, node id or array of node identifiers\n\t\t@param {optional Object} options\n\t*/\n\tTree.prototype.enableNode = function (identifiers, options) {\n\t\tthis.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {\n\t\t\tthis.setDisabledState(node, false, options);\n\t\t}, this));\n\n\t\tthis.render();\n\t};\n\n\t/**\n\t\tToggles a nodes disabled state; disabling is enabled, enabling if disabled.\n\t\t@param {Object|Number} identifiers - A valid node, node id or array of node identifiers\n\t\t@param {optional Object} options\n\t*/\n\tTree.prototype.toggleNodeDisabled = function (identifiers, options) {\n\t\tthis.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {\n\t\t\tthis.setDisabledState(node, !node.state.disabled, options);\n\t\t}, this));\n\n\t\tthis.render();\n\t};\n\n\n\t/**\n\t\tCommon code for processing multiple identifiers\n\t*/\n\tTree.prototype.forEachIdentifier = function (identifiers, options, callback) {\n\n\t\toptions = $.extend({}, _default.options, options);\n\n\t\tif (!(identifiers instanceof Array)) {\n\t\t\tidentifiers = [identifiers];\n\t\t}\n\n\t\t$.each(identifiers, $.proxy(function (index, identifier) {\n\t\t\tcallback(this.identifyNode(identifier), options);\n\t\t}, this));\t\n\t};\n\n\t/*\n\t\tIdentifies a node from either a node id or object\n\t*/\n\tTree.prototype.identifyNode = function (identifier) {\n\t\treturn ((typeof identifier) === 'number') ?\n\t\t\t\t\t\tthis.nodes[identifier] :\n\t\t\t\t\t\tidentifier;\n\t};\n\n\t/**\n\t\tSearches the tree for nodes (text) that match given criteria\n\t\t@param {String} pattern - A given string to match against\n\t\t@param {optional Object} options - Search criteria options\n\t\t@return {Array} nodes - Matching nodes\n\t*/\n\tTree.prototype.search = function (pattern, options) {\n\t\toptions = $.extend({}, _default.searchOptions, options);\n\n\t\tthis.clearSearch({ render: false });\n\n\t\tvar results = [];\n\t\tif (pattern && pattern.length > 0) {\n\n\t\t\tif (options.exactMatch) {\n\t\t\t\tpattern = '^' + pattern + '$';\n\t\t\t}\n\n\t\t\tvar modifier = 'g';\n\t\t\tif (options.ignoreCase) {\n\t\t\t\tmodifier += 'i';\n\t\t\t}\n\n\t\t\tresults = this.findNodes(pattern, modifier);\n\n\t\t\t// Add searchResult property to all matching nodes\n\t\t\t// This will be used to apply custom styles\n\t\t\t// and when identifying result to be cleared\n\t\t\t$.each(results, function (index, node) {\n\t\t\t\tnode.searchResult = true;\n\t\t\t})\n\t\t}\n\n\t\t// If revealResults, then render is triggered from revealNode\n\t\t// otherwise we just call render.\n\t\tif (options.revealResults) {\n\t\t\tthis.revealNode(results);\n\t\t}\n\t\telse {\n\t\t\tthis.render();\n\t\t}\n\n\t\tthis.$element.trigger('searchComplete', $.extend(true, {}, results));\n\n\t\treturn results;\n\t};\n\n\t/**\n\t\tClears previous search results\n\t*/\n\tTree.prototype.clearSearch = function (options) {\n\n\t\toptions = $.extend({}, { render: true }, options);\n\n\t\tvar results = $.each(this.findNodes('true', 'g', 'searchResult'), function (index, node) {\n\t\t\tnode.searchResult = false;\n\t\t});\n\n\t\tif (options.render) {\n\t\t\tthis.render();\t\n\t\t}\n\t\t\n\t\tthis.$element.trigger('searchCleared', $.extend(true, {}, results));\n\t};\n\n\t/**\n\t\tFind nodes that match a given criteria\n\t\t@param {String} pattern - A given string to match against\n\t\t@param {optional String} modifier - Valid RegEx modifiers\n\t\t@param {optional String} attribute - Attribute to compare pattern against\n\t\t@return {Array} nodes - Nodes that match your criteria\n\t*/\n\tTree.prototype.findNodes = function (pattern, modifier, attribute) {\n\n\t\tmodifier = modifier || 'g';\n\t\tattribute = attribute || 'text';\n\n\t\tvar _this = this;\n\t\treturn $.grep(this.nodes, function (node) {\n\t\t\tvar val = _this.getNodeValue(node, attribute);\n\t\t\tif (typeof val === 'string') {\n\t\t\t\treturn val.match(new RegExp(pattern, modifier));\n\t\t\t}\n\t\t});\n\t};\n\n\t/**\n\t\tRecursive find for retrieving nested attributes values\n\t\tAll values are return as strings, unless invalid\n\t\t@param {Object} obj - Typically a node, could be any object\n\t\t@param {String} attr - Identifies an object property using dot notation\n\t\t@return {String} value - Matching attributes string representation\n\t*/\n\tTree.prototype.getNodeValue = function (obj, attr) {\n\t\tvar index = attr.indexOf('.');\n\t\tif (index > 0) {\n\t\t\tvar _obj = obj[attr.substring(0, index)];\n\t\t\tvar _attr = attr.substring(index + 1, attr.length);\n\t\t\treturn this.getNodeValue(_obj, _attr);\n\t\t}\n\t\telse {\n\t\t\tif (obj.hasOwnProperty(attr)) {\n\t\t\t\treturn obj[attr].toString();\n\t\t\t}\n\t\t\telse {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t}\n\t};\n\n\tvar logError = function (message) {\n\t\tif (window.console) {\n\t\t\twindow.console.error(message);\n\t\t}\n\t};\n\n\t// Prevent against multiple instantiations,\n\t// handle updates and method calls\n\t$.fn[pluginName] = function (options, args) {\n\n\t\tvar result;\n\n\t\tthis.each(function () {\n\t\t\tvar _this = $.data(this, pluginName);\n\t\t\tif (typeof options === 'string') {\n\t\t\t\tif (!_this) {\n\t\t\t\t\tlogError('Not initialized, can not call method : ' + options);\n\t\t\t\t}\n\t\t\t\telse if (!$.isFunction(_this[options]) || options.charAt(0) === '_') {\n\t\t\t\t\tlogError('No such method : ' + options);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tif (!(args instanceof Array)) {\n\t\t\t\t\t\targs = [ args ];\n\t\t\t\t\t}\n\t\t\t\t\tresult = _this[options].apply(_this, args);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (typeof options === 'boolean') {\n\t\t\t\tresult = _this;\n\t\t\t}\n\t\t\telse {\n\t\t\t\t$.data(this, pluginName, new Tree(this, $.extend(true, {}, options)));\n\t\t\t}\n\t\t});\n\n\t\treturn result || this;\n\t};\n\n})(jQuery, window, document);\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/js/common.js",
    "content": "//form序列化为json\n$.fn.serializeObject = function()\n{\n    var o = {};\n    var a = this.serializeArray();\n    $.each(a, function() {\n        if (o[this.name] !== undefined) {\n            if (!o[this.name].push) {\n                o[this.name] = [o[this.name]];\n            }\n            o[this.name].push(this.value || '');\n        } else {\n            o[this.name] = this.value || '';\n        }\n    });\n    return o;\n};\n\n//获取url后的参数值\nfunction getUrlParam(key) {\n\tvar href = window.location.href;\n\tvar url = href.split(\"?\");\n\tif(url.length <= 1){\n\t\treturn \"\";\n\t}\n\tvar params = url[1].split(\"&\");\n\t\n\tfor(var i=0; i<params.length; i++){\n\t\tvar param = params[i].split(\"=\");\n\t\tif(key == param[0]){\n\t\t\treturn param[1];\n\t\t}\n\t}\n}"
  },
  {
    "path": "open-layui-web/src/main/view/static/js/dict.js",
    "content": "function showDictSelect(id, type, all) {\n\tvar data = getDict(type);\n\tvar select = $(\"#\" + id);\n\tselect.empty();\n\n\tif (all != undefined || all) {\n\t\tselect.append(\"<option value=''>全部</option>\");\n\t}\n\n\t$.each(data, function(k, v) {\n\t\tselect.append(\"<option value ='\" + k + \"'>\" + v + \"</option>\");\n\t});\n\n\treturn data;\n}\n\nfunction getDict(type) {\n\tvar v = sessionStorage[type];\n\tif (v == null || v == \"\") {\n\t\t$.ajax({\n\t\t\ttype : 'get',\n\t\t\turl : '/dicts?type=' + type,\n\t\t\tasync : false,\n\t\t\tsuccess : function(data) {\n\t\t\t\tv = {};\n\t\t\t\t$.each(data, function(i, d) {\n\t\t\t\t\tv[d.k] = d.val;\n\t\t\t\t});\n\n\t\t\t\tsessionStorage[type] = JSON.stringify(v);\n\t\t\t}\n\t\t});\n\t}\n\n\treturn JSON.parse(sessionStorage[type]);\n}\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/js/index.js",
    "content": "initMenu();\nfunction initMenu(){\n\t $.ajax({  \n\t     url:\"/permissions/current\",  \n\t     type:\"get\",  \n\t     async:false,\n\t     success:function(data){\n\t    \t if(!$.isArray(data)){\n\t    \t\t location.href='/login.html';\n\t    \t\t return;\n\t    \t }\n\t    \t var menu = $(\"#menu\");\n\t    \t $.each(data, function(i,item){\n\t             var a = $(\"<a href='javascript:;'></a>\");\n\t             \n\t             var css = item.css;\n\t             \n\t             if(css!=null && css!=\"\"){\n\t            \t a.append(\"<span class='fa \" + css +\"'></span>\");\n\t             }\n\t             a.append(\"<cite>\"+item.name+\"</cite>\");\n\t             a.attr(\"lay-id\", item.id);\n\t             \n\t             var href = item.href;\n\t             if(href != null && href != \"\"){\n\t                a.attr(\"href\", href);\n\t             }\n\t             \n\t             var li = $(\"<li class='layui-nav-item'></li>\");\n//\t             默认第一项不展开\n//\t             if (i == 0) {\n//\t            \t li.addClass(\"layui-nav-itemed\");\n//\t             }\n\t             li.append(a);\n\t             \n\t             //二级菜单\n\t             var child2 = item.child;\n\t             if(child2 != null && child2.length > 0){\n\t            \t $.each(child2, function(j,item2){\n\t            \t\t var ca = $(\"<a href='javascript:;'></a>\");\n                         ca.attr(\"data-url\", item2.href);\n                         ca.attr(\"lay-id\", item2.id);\n                         \n                         var css2 = item2.css;\n                         if(css2!=null && css2!=\"\"){\n                        \t ca.append(\"<i aria-hidden='true' class='fa \" + css2 +\"'></i>\");\n                         }\n                         \n                         ca.append(\"<cite>\"+item2.name+\"</cite>\");\n                         \n                         var dd = $(\"<dd class='layui-nav-child'></dd>\");\n                         dd.append(ca);\n                         \n                         var dl = $(\"<dl class='layui-nav-child'></dl>\");\n                         dl.append(dd);\n                         \n                         li.append(dl);\n\t            \t });\n\t            }\n\t            menu.append(li);\n\t        });\n\t     }\n\t });\n}\n\n// 登陆用户头像昵称\nshowLoginInfo();\nfunction showLoginInfo(){\n\t$.ajax({\n\t\ttype : 'get',\n\t\turl : '/users/current',\n\t\tasync : false,\n\t\tsuccess : function(data) {\n\t\t\t$(\".admin-header-user span\").text(data.nickname);\n\t\t\t\n\t\t\tvar pro = window.location.protocol;\n\t\t\tvar host = window.location.host;\n\t\t\tvar domain = pro + \"//\" + host;\n\t\t\t\n\t\t\tvar sex = data.sex;\n\t\t\tvar url = data.headImgUrl;\n\t\t\tif(url == null || url == \"\"){\n\t\t\t\tif(sex == 1){\n\t\t\t\t\turl = \"/img/avatars/sunny.png\";\n\t\t\t\t} else {\n\t\t\t\t\turl = \"/img/avatars/1.png\";\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\turl = domain + url;\n\t\t\t} else {\n\t\t\t\turl = domain + \"/statics\" + url;\n\t\t\t}\n\t\t\tvar img = $(\".admin-header-user img\");\n\t\t\timg.attr(\"src\", url);\n\t\t}\n\t});\n}\n\nshowUnreadNotice();\nfunction showUnreadNotice(){\n\t$.ajax({\n\t\ttype : 'get',\n\t\turl : '/notices/count-unread',\n\t\tsuccess : function(data) {\n\t\t\t$(\"[unreadNotice]\").each(function(){\n\t\t\t\tif(data>0){\n\t\t\t\t\t$(this).html(\"<span class='layui-badge'>\"+data+\"</span>\");\n\t\t\t\t}else{\n\t\t\t\t\t$(this).html(\"\");\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t}\n\t});\n}\n\nfunction logout(){\n\t$.ajax({\n\t\ttype : 'get',\n\t\turl : '/logout',\n\t\tsuccess : function(data) {\n\t\t\tlocalStorage.removeItem(\"token\");\n\t\t\tlocation.href='/login.html';\n\t\t}\n\t});\n}\n\nvar active;\n\nlayui.use(['layer', 'element'], function() {\n\tvar $ = layui.jquery,\n\tlayer = layui.layer;\n\tvar element = layui.element; //导航的hover效果、二级菜单等功能，需要依赖element模块\n    element.on('nav(demo)', function(elem){\n      //layer.msg(elem.text());\n    });\n\t\n\t  //触发事件  \n\t   active = {  \n\t       tabAdd: function(obj){\n\t    \t var lay_id = $(this).attr(\"lay-id\");\n\t    \t var title = $(this).html() + '<i class=\"layui-icon\" data-id=\"' + lay_id + '\"></i>';\n\t         //新增一个Tab项  \n\t         element.tabAdd('admin-tab', {  \n\t           title: title,\n\t           content: '<iframe src=\"' + $(this).attr('data-url') + '\"></iframe>',\n\t           id: lay_id\n\t         });  \n\t         element.tabChange(\"admin-tab\", lay_id);    \n\t       }, \n\t       tabDelete: function(lay_id){\n    \t      element.tabDelete(\"admin-tab\", lay_id);\n    \t   },\n\t       tabChange: function(lay_id){\n\t         element.tabChange('admin-tab', lay_id);\n\t       }  \n\t   };  \n\t   //添加tab  \n\t   $(document).on('click','a',function(){  \n\t       if(!$(this)[0].hasAttribute('data-url') || $(this).attr('data-url')===''){\n\t    \t   return;  \n\t       }\n\t       var tabs = $(\".layui-tab-title\").children();\n\t       var lay_id = $(this).attr(\"lay-id\");\n\n\t       for(var i = 0; i < tabs.length; i++) {\n\t           if($(tabs).eq(i).attr(\"lay-id\") == lay_id) { \n\t        \t   active.tabChange(lay_id);\n\t               return;  \n\t           }    \n\t       }  \n\t       active[\"tabAdd\"].call(this);  \n\t       resize();  \n\t   });  \n\t     \n\t   //iframe自适应  \n\t   function resize(){  \n\t       var $content = $('.admin-nav-card .layui-tab-content');  \n\t       $content.height($(this).height() - 147);  \n\t       $content.find('iframe').each(function() {  \n\t           $(this).height($content.height());  \n\t       });  \n\t   }  \n\t   $(window).on('resize', function() {  \n\t       var $content = $('.admin-nav-card .layui-tab-content');  \n\t       $content.height($(this).height() - 147);  \n\t       $content.find('iframe').each(function() {  \n\t           $(this).height($content.height());  \n\t       });  \n\t   }).resize();  \n\t   \n\t   //toggle左侧菜单  \n\t   $('.admin-side-toggle').on('click', function() {\n\t       var sideWidth = $('#admin-side').width();  \n\t       if(sideWidth === 200) {  \n\t           $('#admin-body').animate({  \n\t               left: '0'  \n\t           });\n\t           $('#admin-footer').animate({  \n\t               left: '0'  \n\t           });  \n\t           $('#admin-side').animate({  \n\t               width: '0'  \n\t           });  \n\t       } else {  \n\t           $('#admin-body').animate({  \n\t               left: '200px'  \n\t           });  \n\t           $('#admin-footer').animate({  \n\t               left: '200px'  \n\t           });  \n\t           $('#admin-side').animate({  \n\t               width: '200px'  \n\t               });  \n\t           }  \n\t       });\n\t   \n\t    //手机设备的简单适配\n\t    var treeMobile = $('.site-tree-mobile'),\n\t    shadeMobile = $('.site-mobile-shade');\n\t    treeMobile.on('click', function () {\n\t        $('body').addClass('site-mobile');\n\t    });\n\t    shadeMobile.on('click', function () {\n\t        $('body').removeClass('site-mobile');\n\t    });\n});"
  },
  {
    "path": "open-layui-web/src/main/view/static/js/jq.js",
    "content": "$.ajaxSetup({\n\tcache : false,\n\theaders : {\n\t\t\"access_token\" : localStorage.getItem(\"token\")\n\t},\n\terror : function(xhr, textStatus, errorThrown) {\n\t\tvar msg = xhr.responseText;\n\t\tvar response = JSON.parse(msg);\n\t\tvar code = response.code;\n\t\tvar message = response.message;\n\t\tif (code == 400) {\n\t\t\tlayer.msg(message);\n\t\t} else if (code == 401) {\n\t\t\tlocalStorage.removeItem(\"token\");\n\t\t\tlocation.href = '/login.html';\n\t\t} else if (code == 403) {\n\t\t\tconsole.log(\"未授权:\" + message);\n\t\t\tlayer.msg('未授权');\n\t\t} else if (code == 500) {\n\t\t\tlayer.msg('系统错误：' + message);\n\t\t}\n\t}\n});\n\nfunction buttonDel(data, permission, pers){\n\tif(permission != \"\"){\n\t\tif ($.inArray(permission, pers) < 0) {\n\t\t\treturn \"\";\n\t\t}\n\t}\n\t\n\tvar btn = $(\"<button class='layui-btn layui-btn-xs' title='删除' onclick='del(\\\"\" + data +\"\\\")'><i class='layui-icon'>&#xe640;</i></button>\");\n\treturn btn.prop(\"outerHTML\");\n}\n\nfunction buttonEdit(href, permission, pers){\n\tif(permission != \"\"){\n\t\tif ($.inArray(permission, pers) < 0) {\n\t\t\treturn \"\";\n\t\t}\n\t}\n\t\n\tvar btn = $(\"<button class='layui-btn layui-btn-xs' title='编辑' onclick='window.location=\\\"\" + href +\"\\\"'><i class='layui-icon'>&#xe642;</i></button>\");\n\treturn btn.prop(\"outerHTML\");\n}\n\nfunction buttonInfo(data, permission, pers){\n\tif(permission != \"\"){\n\t\tif ($.inArray(permission, pers) < 0) {\n\t\t\treturn \"\";\n\t\t}\n\t}\n\t\n\tvar btn = $(\"<button class='layui-btn layui-btn-xs' title='详情'  onclick='info(\\\"\" + data +\"\\\")'><i class='layui-icon'>&#xe642;</i></button>\");\n\treturn btn.prop(\"outerHTML\");\n}\n\n\n\nfunction buttonOps(data, permission, pers){\n\tif(permission != \"\"){\n\t\tif ($.inArray(permission, pers) < 0) {\n\t\t\treturn \"\";\n\t\t}\n\t}\n \n\tvar btn ;\n\tif(data.status=='UP'){\n\t\t btn = $(\"<button class='layui-btn layui-btn-xs' title='暂停'  onclick='ops(\\\"\" + data.app +\"\\\",\" + \"\\\"\" + data.instanceId +\"\\\",\" + \"\\\"\" + data.ip +\"\\\",\" + data.port+\",\"+1 +\")'><i class='layui-icon'>⏸</i></button>\");\n\t\t\n\t}else{\n\t\t btn = $(\"<button class='layui-btn layui-btn-xs' title='启动'  onclick='ops(\\\"\" + data.app +\"\\\",\" + \"\\\"\" + data.instanceId +\"\\\",\"   + \"\\\"\" + data.ip +\"\\\",\" + data.port+\",\"+3 +\")'><i class='layui-icon'>▶</i></button>\");\n\t\t\n\t}\n\t\n\treturn btn.prop(\"outerHTML\");\n}\n\n\nfunction buttonRefresh(data, permission, pers){\n\tif(permission != \"\"){\n\t\tif ($.inArray(permission, pers) < 0) {\n\t\t\treturn \"\";\n\t\t}\n\t}\n \n\tvar btn ;\n\t \n\tbtn = $(\"<button class='layui-btn layui-btn-xs' title='刷新'  onclick='ops(\\\"\" + data.app +\"\\\",\" + \"\\\"\" + data.instanceId +\"\\\",\"   + \"\\\"\" + data.ip +\"\\\",\" + data.port+\",\"+4 +\")'><i class='layui-icon'>ဂ</i></button>\");\n\t\n\t\t\n\n\t\n\treturn btn.prop(\"outerHTML\");\n} \n\nfunction buttonEInfo(data, permission, pers){\n\tif(permission != \"\"){\n\t\tif ($.inArray(permission, pers) < 0) {\n\t\t\treturn \"\";\n\t\t}\n\t}\n\tvar info ;\n\tinfo.ip =data.ip ;\n\tinfo.port= data.port ;\n\tinfo.operate = 5 ;\n\tvar btn = $(\"<button class='layui-btn layui-btn-xs' title='详情'  onclick='einfo(\\\"\" + info +\"\\\")'><i class='layui-icon'>&#xe642;</i></button>\");\n\treturn btn.prop(\"outerHTML\");\n}\n\n\nfunction deleteCurrentTab(){\n\tvar lay_id = $(parent.document).find(\"ul.layui-tab-title\").children(\"li.layui-this\").attr(\"lay-id\");\n\tparent.active.tabDelete(lay_id);\n}\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/js/libs/jquery.treetable.js",
    "content": "/*\n * jQuery treetable Plugin 3.2.0\n * http://ludo.cubicphuse.nl/jquery-treetable\n *\n * Copyright 2013, Ludo van den Boom\n * Dual licensed under the MIT or GPL Version 2 licenses.\n */\n(function($) {\n  var Node, Tree, methods;\n\n  Node = (function() {\n    function Node(row, tree, settings) {\n      var parentId;\n\n      this.row = row;\n      this.tree = tree;\n      this.settings = settings;\n\n      // TODO Ensure id/parentId is always a string (not int)\n      this.id = this.row.data(this.settings.nodeIdAttr);\n\n      // TODO Move this to a setParentId function?\n      parentId = this.row.data(this.settings.parentIdAttr);\n      if (parentId != null && parentId !== \"\") {\n        this.parentId = parentId;\n      }\n\n      this.treeCell = $(this.row.children(this.settings.columnElType)[this.settings.column]);\n      this.expander = $(this.settings.expanderTemplate);\n      this.indenter = $(this.settings.indenterTemplate);\n      this.children = [];\n      this.initialized = false;\n      this.treeCell.prepend(this.indenter);\n    }\n\n    Node.prototype.addChild = function(child) {\n      return this.children.push(child);\n    };\n\n    Node.prototype.ancestors = function() {\n      var ancestors, node;\n      node = this;\n      ancestors = [];\n      while (node = node.parentNode()) {\n        ancestors.push(node);\n      }\n      return ancestors;\n    };\n\n    Node.prototype.collapse = function() {\n      if (this.collapsed()) {\n        return this;\n      }\n\n      this.row.removeClass(\"expanded\").addClass(\"collapsed\");\n\n      this._hideChildren();\n      this.expander.attr(\"title\", this.settings.stringExpand);\n\n      if (this.initialized && this.settings.onNodeCollapse != null) {\n        this.settings.onNodeCollapse.apply(this);\n      }\n\n      return this;\n    };\n\n    Node.prototype.collapsed = function() {\n      return this.row.hasClass(\"collapsed\");\n    };\n\n    // TODO destroy: remove event handlers, expander, indenter, etc.\n\n    Node.prototype.expand = function() {\n      if (this.expanded()) {\n        return this;\n      }\n\n      this.row.removeClass(\"collapsed\").addClass(\"expanded\");\n\n      if (this.initialized && this.settings.onNodeExpand != null) {\n        this.settings.onNodeExpand.apply(this);\n      }\n\n      if ($(this.row).is(\":visible\")) {\n        this._showChildren();\n      }\n\n      this.expander.attr(\"title\", this.settings.stringCollapse);\n\n      return this;\n    };\n\n    Node.prototype.expanded = function() {\n      return this.row.hasClass(\"expanded\");\n    };\n\n    Node.prototype.hide = function() {\n      this._hideChildren();\n      this.row.hide();\n      return this;\n    };\n\n    Node.prototype.isBranchNode = function() {\n      if(this.children.length > 0 || this.row.data(this.settings.branchAttr) === true) {\n        return true;\n      } else {\n        return false;\n      }\n    };\n\n    Node.prototype.updateBranchLeafClass = function(){\n      this.row.removeClass('branch');\n      this.row.removeClass('leaf');\n      this.row.addClass(this.isBranchNode() ? 'branch' : 'leaf');\n    };\n\n    Node.prototype.level = function() {\n      return this.ancestors().length;\n    };\n\n    Node.prototype.parentNode = function() {\n      if (this.parentId != null) {\n        return this.tree[this.parentId];\n      } else {\n        return null;\n      }\n    };\n\n    Node.prototype.removeChild = function(child) {\n      var i = $.inArray(child, this.children);\n      return this.children.splice(i, 1)\n    };\n\n    Node.prototype.render = function() {\n      var handler,\n          settings = this.settings,\n          target;\n\n      if (settings.expandable === true && this.isBranchNode()) {\n        handler = function(e) {\n          $(this).parents(\"table\").treetable(\"node\", $(this).parents(\"tr\").data(settings.nodeIdAttr)).toggle();\n          return e.preventDefault();\n        };\n\n        this.indenter.html(this.expander);\n        target = settings.clickableNodeNames === true ? this.treeCell : this.expander;\n\n        target.off(\"click.treetable\").on(\"click.treetable\", handler);\n        target.off(\"keydown.treetable\").on(\"keydown.treetable\", function(e) {\n          if (e.keyCode == 13) {\n            handler.apply(this, [e]);\n          }\n        });\n      }\n\n      this.indenter[0].style.paddingLeft = \"\" + (this.level() * settings.indent) + \"px\";\n\n      return this;\n    };\n\n    Node.prototype.reveal = function() {\n      if (this.parentId != null) {\n        this.parentNode().reveal();\n      }\n      return this.expand();\n    };\n\n    Node.prototype.setParent = function(node) {\n      if (this.parentId != null) {\n        this.tree[this.parentId].removeChild(this);\n      }\n      this.parentId = node.id;\n      this.row.data(this.settings.parentIdAttr, node.id);\n      return node.addChild(this);\n    };\n\n    Node.prototype.show = function() {\n      if (!this.initialized) {\n        this._initialize();\n      }\n      this.row.show();\n      if (this.expanded()) {\n        this._showChildren();\n      }\n      return this;\n    };\n\n    Node.prototype.toggle = function() {\n      if (this.expanded()) {\n        this.collapse();\n      } else {\n        this.expand();\n      }\n      return this;\n    };\n\n    Node.prototype._hideChildren = function() {\n      var child, _i, _len, _ref, _results;\n      _ref = this.children;\n      _results = [];\n      for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n        child = _ref[_i];\n        _results.push(child.hide());\n      }\n      return _results;\n    };\n\n    Node.prototype._initialize = function() {\n      var settings = this.settings;\n\n      this.render();\n\n      if (settings.expandable === true && settings.initialState === \"collapsed\") {\n        this.collapse();\n      } else {\n        this.expand();\n      }\n\n      if (settings.onNodeInitialized != null) {\n        settings.onNodeInitialized.apply(this);\n      }\n\n      return this.initialized = true;\n    };\n\n    Node.prototype._showChildren = function() {\n      var child, _i, _len, _ref, _results;\n      _ref = this.children;\n      _results = [];\n      for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n        child = _ref[_i];\n        _results.push(child.show());\n      }\n      return _results;\n    };\n\n    return Node;\n  })();\n\n  Tree = (function() {\n    function Tree(table, settings) {\n      this.table = table;\n      this.settings = settings;\n      this.tree = {};\n\n      // Cache the nodes and roots in simple arrays for quick access/iteration\n      this.nodes = [];\n      this.roots = [];\n    }\n\n    Tree.prototype.collapseAll = function() {\n      var node, _i, _len, _ref, _results;\n      _ref = this.nodes;\n      _results = [];\n      for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n        node = _ref[_i];\n        _results.push(node.collapse());\n      }\n      return _results;\n    };\n\n    Tree.prototype.expandAll = function() {\n      var node, _i, _len, _ref, _results;\n      _ref = this.nodes;\n      _results = [];\n      for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n        node = _ref[_i];\n        _results.push(node.expand());\n      }\n      return _results;\n    };\n\n    Tree.prototype.findLastNode = function (node) {\n      if (node.children.length > 0) {\n        return this.findLastNode(node.children[node.children.length - 1]);\n      } else {\n        return node;\n      }\n    };\n\n    Tree.prototype.loadRows = function(rows) {\n      var node, row, i;\n\n      if (rows != null) {\n        for (i = 0; i < rows.length; i++) {\n          row = $(rows[i]);\n\n          if (row.data(this.settings.nodeIdAttr) != null) {\n            node = new Node(row, this.tree, this.settings);\n            this.nodes.push(node);\n            this.tree[node.id] = node;\n\n            if (node.parentId != null && this.tree[node.parentId]) {\n              this.tree[node.parentId].addChild(node);\n            } else {\n              this.roots.push(node);\n            }\n          }\n        }\n      }\n\n      for (i = 0; i < this.nodes.length; i++) {\n        node = this.nodes[i].updateBranchLeafClass();\n      }\n\n      return this;\n    };\n\n    Tree.prototype.move = function(node, destination) {\n      // Conditions:\n      // 1: +node+ should not be inserted as a child of +node+ itself.\n      // 2: +destination+ should not be the same as +node+'s current parent (this\n      //    prevents +node+ from being moved to the same location where it already\n      //    is).\n      // 3: +node+ should not be inserted in a location in a branch if this would\n      //    result in +node+ being an ancestor of itself.\n      var nodeParent = node.parentNode();\n      if (node !== destination && destination.id !== node.parentId && $.inArray(node, destination.ancestors()) === -1) {\n        node.setParent(destination);\n        this._moveRows(node, destination);\n\n        // Re-render parentNode if this is its first child node, and therefore\n        // doesn't have the expander yet.\n        if (node.parentNode().children.length === 1) {\n          node.parentNode().render();\n        }\n      }\n\n      if(nodeParent){\n        nodeParent.updateBranchLeafClass();\n      }\n      if(node.parentNode()){\n        node.parentNode().updateBranchLeafClass();\n      }\n      node.updateBranchLeafClass();\n      return this;\n    };\n\n    Tree.prototype.removeNode = function(node) {\n      // Recursively remove all descendants of +node+\n      this.unloadBranch(node);\n\n      // Remove node from DOM (<tr>)\n      node.row.remove();\n\n      // Remove node from parent children list\n      if (node.parentId != null) {\n        node.parentNode().removeChild(node);\n      }\n\n      // Clean up Tree object (so Node objects are GC-ed)\n      delete this.tree[node.id];\n      this.nodes.splice($.inArray(node, this.nodes), 1);\n\n      return this;\n    }\n\n    Tree.prototype.render = function() {\n      var root, _i, _len, _ref;\n      _ref = this.roots;\n      for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n        root = _ref[_i];\n\n        // Naming is confusing (show/render). I do not call render on node from\n        // here.\n        root.show();\n      }\n      return this;\n    };\n\n    Tree.prototype.sortBranch = function(node, sortFun) {\n      // First sort internal array of children\n      node.children.sort(sortFun);\n\n      // Next render rows in correct order on page\n      this._sortChildRows(node);\n\n      return this;\n    };\n\n    Tree.prototype.unloadBranch = function(node) {\n      // Use a copy of the children array to not have other functions interfere\n      // with this function if they manipulate the children array\n      // (eg removeNode).\n      var children = node.children.slice(0),\n          i;\n\n      for (i = 0; i < children.length; i++) {\n        this.removeNode(children[i]);\n      }\n\n      // Reset node's collection of children\n      node.children = [];\n\n      node.updateBranchLeafClass();\n\n      return this;\n    };\n\n    Tree.prototype._moveRows = function(node, destination) {\n      var children = node.children, i;\n\n      node.row.insertAfter(destination.row);\n      node.render();\n\n      // Loop backwards through children to have them end up on UI in correct\n      // order (see #112)\n      for (i = children.length - 1; i >= 0; i--) {\n        this._moveRows(children[i], node);\n      }\n    };\n\n    // Special _moveRows case, move children to itself to force sorting\n    Tree.prototype._sortChildRows = function(parentNode) {\n      return this._moveRows(parentNode, parentNode);\n    };\n\n    return Tree;\n  })();\n\n  // jQuery Plugin\n  methods = {\n    init: function(options, force) {\n      var settings;\n\n      settings = $.extend({\n        branchAttr: \"ttBranch\",\n        clickableNodeNames: false,\n        column: 0,\n        columnElType: \"td\", // i.e. 'td', 'th' or 'td,th'\n        expandable: false,\n        expanderTemplate: \"<a href='#'>&nbsp;</a>\",\n        indent: 19,\n        indenterTemplate: \"<span class='indenter'></span>\",\n        initialState: \"collapsed\",\n        nodeIdAttr: \"ttId\", // maps to data-tt-id\n        parentIdAttr: \"ttParentId\", // maps to data-tt-parent-id\n        stringExpand: \"Expand\",\n        stringCollapse: \"Collapse\",\n\n        // Events\n        onInitialized: null,\n        onNodeCollapse: null,\n        onNodeExpand: null,\n        onNodeInitialized: null\n      }, options);\n\n      return this.each(function() {\n        var el = $(this), tree;\n\n        if (force || el.data(\"treetable\") === undefined) {\n          tree = new Tree(this, settings);\n          tree.loadRows(this.rows).render();\n\n          el.addClass(\"treetable\").data(\"treetable\", tree);\n\n          if (settings.onInitialized != null) {\n            settings.onInitialized.apply(tree);\n          }\n        }\n\n        return el;\n      });\n    },\n\n    destroy: function() {\n      return this.each(function() {\n        return $(this).removeData(\"treetable\").removeClass(\"treetable\");\n      });\n    },\n\n    collapseAll: function() {\n      this.data(\"treetable\").collapseAll();\n      return this;\n    },\n\n    collapseNode: function(id) {\n      var node = this.data(\"treetable\").tree[id];\n\n      if (node) {\n        node.collapse();\n      } else {\n        throw new Error(\"Unknown node '\" + id + \"'\");\n      }\n\n      return this;\n    },\n\n    expandAll: function() {\n      this.data(\"treetable\").expandAll();\n      return this;\n    },\n\n    expandNode: function(id) {\n      var node = this.data(\"treetable\").tree[id];\n\n      if (node) {\n        if (!node.initialized) {\n          node._initialize();\n        }\n\n        node.expand();\n      } else {\n        throw new Error(\"Unknown node '\" + id + \"'\");\n      }\n\n      return this;\n    },\n\n    loadBranch: function(node, rows) {\n      var settings = this.data(\"treetable\").settings,\n          tree = this.data(\"treetable\").tree;\n\n      // TODO Switch to $.parseHTML\n      rows = $(rows);\n\n      if (node == null) { // Inserting new root nodes\n        this.append(rows);\n      } else {\n        var lastNode = this.data(\"treetable\").findLastNode(node);\n        rows.insertAfter(lastNode.row);\n      }\n\n      this.data(\"treetable\").loadRows(rows);\n\n      // Make sure nodes are properly initialized\n      rows.filter(\"tr\").each(function() {\n        tree[$(this).data(settings.nodeIdAttr)].show();\n      });\n\n      if (node != null) {\n        // Re-render parent to ensure expander icon is shown (#79)\n        node.render().expand();\n      }\n\n      return this;\n    },\n\n    move: function(nodeId, destinationId) {\n      var destination, node;\n\n      node = this.data(\"treetable\").tree[nodeId];\n      destination = this.data(\"treetable\").tree[destinationId];\n      this.data(\"treetable\").move(node, destination);\n\n      return this;\n    },\n\n    node: function(id) {\n      return this.data(\"treetable\").tree[id];\n    },\n\n    removeNode: function(id) {\n      var node = this.data(\"treetable\").tree[id];\n\n      if (node) {\n        this.data(\"treetable\").removeNode(node);\n      } else {\n        throw new Error(\"Unknown node '\" + id + \"'\");\n      }\n\n      return this;\n    },\n\n    reveal: function(id) {\n      var node = this.data(\"treetable\").tree[id];\n\n      if (node) {\n        node.reveal();\n      } else {\n        throw new Error(\"Unknown node '\" + id + \"'\");\n      }\n\n      return this;\n    },\n\n    sortBranch: function(node, columnOrFunction) {\n      var settings = this.data(\"treetable\").settings,\n          prepValue,\n          sortFun;\n\n      columnOrFunction = columnOrFunction || settings.column;\n      sortFun = columnOrFunction;\n\n      if ($.isNumeric(columnOrFunction)) {\n        sortFun = function(a, b) {\n          var extractValue, valA, valB;\n\n          extractValue = function(node) {\n            var val = node.row.find(\"td:eq(\" + columnOrFunction + \")\").text();\n            // Ignore trailing/leading whitespace and use uppercase values for\n            // case insensitive ordering\n            return $.trim(val).toUpperCase();\n          }\n\n          valA = extractValue(a);\n          valB = extractValue(b);\n\n          if (valA < valB) return -1;\n          if (valA > valB) return 1;\n          return 0;\n        };\n      }\n\n      this.data(\"treetable\").sortBranch(node, sortFun);\n      return this;\n    },\n\n    unloadBranch: function(node) {\n      this.data(\"treetable\").unloadBranch(node);\n      return this;\n    }\n  };\n\n  $.fn.treetable = function(method) {\n    if (methods[method]) {\n      return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));\n    } else if (typeof method === 'object' || !method) {\n      return methods.init.apply(this, arguments);\n    } else {\n      return $.error(\"Method \" + method + \" does not exist on jQuery.treetable\");\n    }\n  };\n\n  // Expose classes to world\n  this.TreeTable || (this.TreeTable = {});\n  this.TreeTable.Node = Node;\n  this.TreeTable.Tree = Tree;\n})(jQuery);\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/js/main.js",
    "content": "initMenu();\nfunction initMenu(){\n\t $.ajax({  \n\t     url:\"/permissions/current\",  \n\t     type:\"get\",  \n\t     async:false,\n\t     success:function(data){\n\t    \t if(!$.isArray(data)){\n\t    \t\t location.href='/login.html';\n\t    \t\t return;\n\t    \t }\n\t    \t var menu = $(\"#menu\");\n\t    \t $.each(data, function(i,item){\n\t             var a = $(\"<a href='javascript:;'></a>\");\n\t             \n\t             var css = item.css;\n\t             if(css!=null && css!=\"\"){\n\t            \t a.append(\"<i aria-hidden='true' class='fa \" + css +\"'></i>\");\n\t             }\n\t             a.append(\"<cite>\"+item.name+\"</cite>\");\n\t             a.attr(\"lay-id\", item.id);\n\t             \n\t             var href = item.href;\n\t             if(href != null && href != \"\"){\n\t                a.attr(\"data-url\", href);\n\t             }\n\t             \n\t             var li = $(\"<li class='layui-nav-item'></li>\");\n//\t             默认第一项不展开\n//\t             if (i == 0) {\n//\t            \t li.addClass(\"layui-nav-itemed\");\n//\t             }\n\t             li.append(a);\n\t             \n\t             //二级菜单\n\t             var child2 = item.child;\n\t             if(child2 != null && child2.length > 0){\n\t            \t $.each(child2, function(j,item2){\n\t            \t\t var ca = $(\"<a href='javascript:;'></a>\");\n                         ca.attr(\"data-url\", item2.href);\n                         ca.attr(\"lay-id\", item2.id);\n                         \n                         var css2 = item2.css;\n                         if(css2!=null && css2!=\"\"){\n                        \t ca.append(\"<i aria-hidden='true' class='fa \" + css2 +\"'></i>\");\n                         }\n                         \n                         ca.append(\"<cite>\"+item2.name+\"</cite>\");\n                         \n                         var dd = $(\"<dd class='layui-nav-child'></dd>\");\n                         dd.append(ca);\n                         \n                         var dl = $(\"<dl class='layui-nav-child'></dl>\");\n                         dl.append(dd);\n                         \n                         li.append(dl);\n\t            \t });\n\t            }\n\t            menu.append(li);\n\t        });\n\t     }\n\t });\n}\n\n// 登陆用户头像昵称\nshowLoginInfo();\nfunction showLoginInfo(){\n\t$.ajax({\n\t\ttype : 'get',\n\t\turl : '/users/current',\n\t\tasync : false,\n\t\tsuccess : function(data) {\n\t\t\t$(\".admin-header-user span\").text(data.nickname);\n\t\t\t\n\t\t\tvar pro = window.location.protocol;\n\t\t\tvar host = window.location.host;\n\t\t\tvar domain = pro + \"//\" + host;\n\t\t\t\n\t\t\tvar sex = data.sex;\n\t\t\tvar url = data.headImgUrl;\n\t\t\tif(url == null || url == \"\"){\n\t\t\t\tif(sex == 1){\n\t\t\t\t\turl = \"/img/avatars/sunny.png\";\n\t\t\t\t} else {\n\t\t\t\t\turl = \"/img/avatars/1.png\";\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\turl = domain + url;\n\t\t\t} else {\n\t\t\t\turl = domain + \"/statics\" + url;\n\t\t\t}\n\t\t\tvar img = $(\".admin-header-user img\");\n\t\t\timg.attr(\"src\", url);\n\t\t}\n\t});\n}\n\nshowUnreadNotice();\nfunction showUnreadNotice(){\n\t$.ajax({\n\t\ttype : 'get',\n\t\turl : '/notices/count-unread',\n\t\tsuccess : function(data) {\n\t\t\t$(\"[unreadNotice]\").each(function(){\n\t\t\t\tif(data>0){\n\t\t\t\t\t$(this).html(\"<span class='layui-badge'>\"+data+\"</span>\");\n\t\t\t\t}else{\n\t\t\t\t\t$(this).html(\"\");\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t}\n\t});\n}\n\nfunction logout(){\n\t$.ajax({\n\t\ttype : 'get',\n\t\turl : '/logout',\n\t\tsuccess : function(data) {\n\t\t\tlocalStorage.removeItem(\"token\");\n\t\t\tlocation.href='/login.html';\n\t\t}\n\t});\n}\n\nvar active;\n\nlayui.use(['layer', 'element'], function() {\n\tvar $ = layui.jquery,\n\tlayer = layui.layer;\n\tvar element = layui.element; //导航的hover效果、二级菜单等功能，需要依赖element模块\n    element.on('nav(demo)', function(elem){\n      //layer.msg(elem.text());\n    });\n\t\n\t  //触发事件  \n\t   active = {  \n\t       tabAdd: function(obj){\n\t    \t var lay_id = $(this).attr(\"lay-id\");\n\t    \t var title = $(this).html() + '<i class=\"layui-icon\" data-id=\"' + lay_id + '\"></i>';\n\t         //新增一个Tab项  \n\t         element.tabAdd('admin-tab', {  \n\t           title: title,\n\t           content: '<iframe src=\"' + $(this).attr('data-url') + '\"></iframe>',\n\t           id: lay_id\n\t         });  \n\t         element.tabChange(\"admin-tab\", lay_id);    \n\t       }, \n\t       tabDelete: function(lay_id){\n    \t      element.tabDelete(\"admin-tab\", lay_id);\n    \t   },\n\t       tabChange: function(lay_id){\n\t         element.tabChange('admin-tab', lay_id);\n\t       }  \n\t   };  \n\t   //添加tab  \n\t   $(document).on('click','a',function(){  \n\t       if(!$(this)[0].hasAttribute('data-url') || $(this).attr('data-url')===''){\n\t    \t   return;  \n\t       }\n\t       var tabs = $(\".layui-tab-title\").children();\n\t       var lay_id = $(this).attr(\"lay-id\");\n\n\t       for(var i = 0; i < tabs.length; i++) {\n\t           if($(tabs).eq(i).attr(\"lay-id\") == lay_id) { \n\t        \t   active.tabChange(lay_id);\n\t               return;  \n\t           }    \n\t       }  \n\t       active[\"tabAdd\"].call(this);  \n\t       resize();  \n\t   });  \n\t     \n\t   //iframe自适应  \n\t   function resize(){  \n\t       var $content = $('.admin-nav-card .layui-tab-content');  \n\t       $content.height($(this).height() - 147);  \n\t       $content.find('iframe').each(function() {  \n\t           $(this).height($content.height());  \n\t       });  \n\t   }  \n\t   $(window).on('resize', function() {  \n\t       var $content = $('.admin-nav-card .layui-tab-content');  \n\t       $content.height($(this).height() - 147);  \n\t       $content.find('iframe').each(function() {  \n\t           $(this).height($content.height());  \n\t       });  \n\t   }).resize();  \n\t   \n\t   //toggle左侧菜单  \n\t   $('.admin-side-toggle').on('click', function() {\n\t       var sideWidth = $('#admin-side').width();  \n\t       if(sideWidth === 200) {  \n\t           $('#admin-body').animate({  \n\t               left: '0'  \n\t           });\n\t           $('#admin-footer').animate({  \n\t               left: '0'  \n\t           });  \n\t           $('#admin-side').animate({  \n\t               width: '0'  \n\t           });  \n\t       } else {  \n\t           $('#admin-body').animate({  \n\t               left: '200px'  \n\t           });  \n\t           $('#admin-footer').animate({  \n\t               left: '200px'  \n\t           });  \n\t           $('#admin-side').animate({  \n\t               width: '200px'  \n\t               });  \n\t           }  \n\t       });\n\t   \n\t    //手机设备的简单适配\n\t    var treeMobile = $('.site-tree-mobile'),\n\t    shadeMobile = $('.site-mobile-shade');\n\t    treeMobile.on('click', function () {\n\t        $('body').addClass('site-mobile');\n\t    });\n\t    shadeMobile.on('click', function () {\n\t        $('body').removeClass('site-mobile');\n\t    });\n});"
  },
  {
    "path": "open-layui-web/src/main/view/static/js/main2.js",
    "content": "initMenu();\nfunction initMenu(){\n\t$.ajax({  \n\t     url:\"/permissions/current\",  \n\t     type:\"get\",  \n\t     async:false,\n\t     success:function(data){\n\t    \t if(!$.isArray(data)){\n\t    \t\t location.href='/login.html';\n\t    \t\t return;\n\t    \t }\n\t    \t var menu = $(\"#menu\");\n\t    \t $.each(data, function(i,item){\n\t             var a = $(\"<a href='javascript:;'</a>\");\n\t             \n\t             var css = item.css;\n\t             if(css!=null && css!=\"\"){\n\t            \t a.append(\"<i  class='fa \" + css +\"'></i>\");\n\t             }\n\t             var span1 = $(\"<span>\"+item.name+\"</span>\") ;           \n\t             a.append(span1);\n\t             a.attr(\"lay-id\", item.id);\n\t             \n\t             var href = item.href;\n\t             if(href != null && href != \"\"){\n\t                a.attr(\"href\", href);\n\t                a.attr(\"iframe-uuid\", \"uuid-main\");\n\t                a.attr(\"class\",\"admin-open-new-tab\");\n\t                \n\t                a.click(function(){\n\t                \t\n\t                \t$('#admin-tab-body-index').tabs('open', 0);\n\t                })\t\n\t             }\n\t             \n\t             var li = $(\"<li></li>\");\n//\t             默认第一项不展开\n//\t             if (i == 0) {\n//\t            \t li.addClass(\"layui-nav-itemed\");\n//\t             }\n\t             li.append(a);\n\t             \n\t             //二级菜单\n\t             var child2 = item.child;\n\t             if(child2 != null && child2.length > 0){\n\t            \t var dl = $(\"<ul class='am-list am-collapse admin-sidebar-sub am-in' id='collapse-nav\"+ item.id+\"'></ul>\");\n\t            \t span1.append(\"<span class='am-icon-angle-right am-fr am-margin-right'></span>\");\n\t            \t $.each(child2, function(j,item2){\n\t            \t\t var ca = $(\"<a href='javascript:;'></a>\");\n                        ca.attr(\"href\", item2.href);\n                        ca.attr(\"lay-id\", item2.id);\n                        \n                        \n                        li.attr(\"class\",\"admin-parent\");\n                        a.attr(\"data-am-collapse\",\"{target: '#collapse-nav\"+ item.id+\"'}\")\n                        var css2 = item2.css;\n                        if(css2!=null && css2!=\"\"){\n                       \t ca.append(\"<span class='fa \" + css2 +\"'></span>\");\n                        }\n                        \n                        ca.append(\"<span>\"+item2.name+\"</span>\");\n                        \n                        var dd = $(\"<li></<li>\");\n                        dd.append(ca);\n                        dl.append(dd);\n                       \n                        \n                       \n\t            \t });\n\t            \t li.append(dl);\n\t            }\n\t            menu.append(li);\n\t        });\n\t     }\n\t });\n}\n\n// 登陆用户头像昵称\nshowLoginInfo();\nfunction showLoginInfo(){\n\t$.ajax({\n\t\ttype : 'get',\n\t\turl : '/users/current',\n\t\tasync : false,\n\t\tsuccess : function(data) {\n\t\t\t$(\".admin-header-user span\").text(data.nickname);\n\t\t\t\n\t\t\tvar pro = window.location.protocol;\n\t\t\tvar host = window.location.host;\n\t\t\tvar domain = pro + \"//\" + host;\n\t\t\t\n\t\t\tvar sex = data.sex;\n\t\t\tvar url = data.headImgUrl;\n\t\t\tif(url == null || url == \"\"){\n\t\t\t\tif(sex == 1){\n\t\t\t\t\turl = \"/img/avatars/sunny.png\";\n\t\t\t\t} else {\n\t\t\t\t\turl = \"/img/avatars/1.png\";\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\turl = domain + url;\n\t\t\t} else {\n\t\t\t\turl = domain + \"/statics\" + url;\n\t\t\t}\n\t\t\tvar img = $(\".admin-header-user img\");\n\t\t\timg.attr(\"src\", url);\n\t\t}\n\t});\n}\n\nshowUnreadNotice();\nfunction showUnreadNotice(){\n\t$.ajax({\n\t\ttype : 'get',\n\t\turl : '/notices/count-unread',\n\t\tsuccess : function(data) {\n\t\t\t$(\"[unreadNotice]\").each(function(){\n\t\t\t\tif(data>0){\n\t\t\t\t\t$(this).html(\"<span class='layui-badge'>\"+data+\"</span>\");\n\t\t\t\t}else{\n\t\t\t\t\t$(this).html(\"\");\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t}\n\t});\n}\n\nfunction logout(){\n\t$.ajax({\n\t\ttype : 'get',\n\t\turl : '/logout',\n\t\tsuccess : function(data) {\n\t\t\tlocalStorage.removeItem(\"token\");\n\t\t\tlocation.href='/login.html';\n\t\t}\n\t});\n}\n\nvar active;\n\nlayui.use(['layer', 'element'], function() {\n\tvar $ = layui.jquery,\n\tlayer = layui.layer;\n\tvar element = layui.element; //导航的hover效果、二级菜单等功能，需要依赖element模块\n    element.on('nav(demo)', function(elem){\n      //layer.msg(elem.text());\n    });\n\t\n\t  //触发事件  \n\t   active = {  \n\t       tabAdd: function(obj){\n\t    \t var lay_id = $(this).attr(\"lay-id\");\n\t    \t var title = $(this).html() + '<i class=\"layui-icon\" data-id=\"' + lay_id + '\"></i>';\n\t         //新增一个Tab项  \n\t         element.tabAdd('admin-tab', {  \n\t           title: title,\n\t           content: '<iframe src=\"' + $(this).attr('data-url') + '\"></iframe>',\n\t           id: lay_id\n\t         });  \n\t         element.tabChange(\"admin-tab\", lay_id);    \n\t       }, \n\t       tabDelete: function(lay_id){\n    \t      element.tabDelete(\"admin-tab\", lay_id);\n    \t   },\n\t       tabChange: function(lay_id){\n\t         element.tabChange('admin-tab', lay_id);\n\t       }  \n\t   };  \n\t   //添加tab  \n\t   $(document).on('click','a',function(){  \n\t       if(!$(this)[0].hasAttribute('data-url') || $(this).attr('data-url')===''){\n\t    \t   return;  \n\t       }\n\t       var tabs = $(\".layui-tab-title\").children();\n\t       var lay_id = $(this).attr(\"lay-id\");\n\n\t       for(var i = 0; i < tabs.length; i++) {\n\t           if($(tabs).eq(i).attr(\"lay-id\") == lay_id) { \n\t        \t   active.tabChange(lay_id);\n\t               return;  \n\t           }    \n\t       }  \n\t       active[\"tabAdd\"].call(this);  \n\t       resize();  \n\t   });  \n\t     \n\t   //iframe自适应  \n\t   function resize(){  \n\t       var $content = $('.admin-nav-card .layui-tab-content');  \n\t       $content.height($(this).height() - 147);  \n\t       $content.find('iframe').each(function() {  \n\t           $(this).height($content.height());  \n\t       });  \n\t   }  \n\t   $(window).on('resize', function() {  \n\t       var $content = $('.admin-nav-card .layui-tab-content');  \n\t       $content.height($(this).height() - 147);  \n\t       $content.find('iframe').each(function() {  \n\t           $(this).height($content.height());  \n\t       });  \n\t   }).resize();  \n\t   \n\t   //toggle左侧菜单  \n\t   $('.admin-side-toggle').on('click', function() {\n\t       var sideWidth = $('#admin-side').width();  \n\t       if(sideWidth === 200) {  \n\t           $('#admin-body').animate({  \n\t               left: '0'  \n\t           });\n\t           $('#admin-footer').animate({  \n\t               left: '0'  \n\t           });  \n\t           $('#admin-side').animate({  \n\t               width: '0'  \n\t           });  \n\t       } else {  \n\t           $('#admin-body').animate({  \n\t               left: '200px'  \n\t           });  \n\t           $('#admin-footer').animate({  \n\t               left: '200px'  \n\t           });  \n\t           $('#admin-side').animate({  \n\t               width: '200px'  \n\t               });  \n\t           }  \n\t       });\n\t   \n\t    //手机设备的简单适配\n\t    var treeMobile = $('.site-tree-mobile'),\n\t    shadeMobile = $('.site-mobile-shade');\n\t    treeMobile.on('click', function () {\n\t        $('body').addClass('site-mobile');\n\t    });\n\t    shadeMobile.on('click', function () {\n\t        $('body').removeClass('site-mobile');\n\t    });\n});"
  },
  {
    "path": "open-layui-web/src/main/view/static/js/my/job.js",
    "content": "function checkCron() {\n\tvar cron = $(\"#cron\").val();\n\tif (cron != \"\") {\n\t\t$.ajax({\n\t\t\ttype : 'get',\n\t\t\turl : '/jobs?cron=' + cron,\n\t\t\tsuccess : function(data) {\n\t\t\t\tvar msg = \"正确\";\n\t\t\t\tif (!data) {\n\t\t\t\t\tmsg = \"cron表达式不对\";\n\t\t\t\t}\n\t\t\t\tlayer.msg(msg, {\n\t\t\t\t\tshift : -1,\n\t\t\t\t\ttime : 1000\n\t\t\t\t}, function() {\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t} else {\n\t\tlayer.msg(\"cron表达式不能为空\", {\n\t\t\tshift : -1,\n\t\t\ttime : 1000\n\t\t}, function() {\n\t\t});\n\t}\n}\n\nfunction initBeanNames() {\n\t$.ajax({\n\t\ttype : 'get',\n\t\turl : '/jobs/beans',\n\t\tasync : false,\n\t\tsuccess : function(data) {\n\t\t\tvar select = $(\"#springBeanName\");\n\t\t\tfor (var i = 0; i < data.length; i++) {\n\t\t\t\tvar v = data[i];\n\t\t\t\tselect.append(\"<option value='\" + v + \"'>\" + v + \"</option>\")\n\t\t\t}\n\t\t\t\n\t\t\t$(\"#springBeanName\").selectpicker('refresh');\n\t\t}\n\t});\n}\n\nfunction showMethods() {\n\tvar val = $(\"#springBeanName\").val();\n\tif (val == \"\") {\n\t\treturn;\n\t}\n\n\t$.ajax({\n\t\ttype : 'get',\n\t\turl : '/jobs/beans/' + val,\n\t\tasync : false,\n\t\tsuccess : function(data) {\n\t\t\tvar select = $(\"#methodName\");\n\t\t\tselect.empty();\n\t\t\tif (data.length == 0) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tfor (var i = 0; i < data.length; i++) {\n\t\t\t\tvar v = data[i];\n\t\t\t\tselect.append(\"<option value='\" + v + \"'>\" + v + \"</option>\")\n\t\t\t}\n\t\t}\n\t});\n}"
  },
  {
    "path": "open-layui-web/src/main/view/static/js/my/permission.js",
    "content": "function checkPermission() {\n\tvar pers = [];\n\t$.ajax({\n\t\ttype : 'get',\n\t\turl : '/permissions/owns',\n\t\tcontentType : \"application/json; charset=utf-8\",\n\t\tasync : false,\n\t\tsuccess : function(data) {\n\t\t\tpers = data;\n\t\t\t$(\"[permission]\").each(function() {\n\t\t\t\tvar per = $(this).attr(\"permission\");\n\t\t\t\tif ($.inArray(per, data) < 0) {\n\t\t\t\t\t$(this).hide();\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t});\n\t\n\treturn pers;\n}"
  },
  {
    "path": "open-layui-web/src/main/view/static/js/my/roles/role.js",
    "content": "function initRoles() {\n\t$.ajax({\n\t\ttype : 'get',\n\t\turl : '/roles/all',\n\t\tasync : false,\n\t\tsuccess : function(data) {\n\t\t\tvar r = $(\"#roles\");\n\n\t\t\tfor (var i = 0; i < data.length; i++) {\n\t\t\t\tvar d = data[i];\n\t\t\t\tvar id = d['id'];\n\t\t\t\tvar name = d['name'];\n\n\t\t\t\tvar t = \"<label><input type='checkbox' value='\" + id + \"'>\"\n\t\t\t\t\t\t+ name + \"</label> &nbsp&nbsp\";\n\n\t\t\t\tr.append(t);\n\t\t\t}\n\t\t}\n\t});\n}\n\nfunction getCheckedRoleIds() {\n\tvar ids = [];\n\t$(\"#roles input[type='checkbox']\").each(function() {\n\t\tif ($(this).prop(\"checked\")) {\n\t\t\tids.push($(this).val());\n\t\t}\n\t});\n\n\treturn ids;\n}\n\nfunction initRoleDatas(userId) {\n\t$.ajax({\n\t\ttype : 'get',\n\t\turl : '/roles?userId=' + userId,\n\t\tsuccess : function(data) {\n\t\t\tvar length = data.length;\n\t\t\tfor (var i = 0; i < length; i++) {\n\t\t\t\t$(\"input[type='checkbox']\").each(function() {\n\t\t\t\t\tvar v = $(this).val();\n\t\t\t\t\tif (v == data[i]['id']) {\n\t\t\t\t\t\t$(this).attr(\"checked\", true);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t});\n}"
  },
  {
    "path": "open-layui-web/src/main/view/static/js/my/ztree-menu.js",
    "content": "function getMenuTree() {\n\tvar root = {\n\t\tid : 0,\n\t\tname : \"root\",\n\t\topen : true,\n\t};\n\n\t$.ajax({\n\t\ttype : 'get',\n\t\turl : '/permissions/all',\n\t\tcontentType : \"application/json; charset=utf-8\",\n\t\tasync : false,\n\t\tsuccess : function(data) {\n\t\t\tvar length = data.length;\n\t\t\tvar children = [];\n\t\t\tfor (var i = 0; i < length; i++) {\n\t\t\t\tvar d = data[i];\n\t\t\t\tvar node = createNode(d);\n\t\t\t\tchildren[i] = node;\n\t\t\t}\n\n\t\t\troot.children = children;\n\t\t}\n\t});\n\n\treturn root;\n}\n\nfunction initMenuDatas(roleId){\n\t$.ajax({\n\t\ttype : 'get',\n\t\turl : '/permissions?roleId=' + roleId,\n\t\tsuccess : function(data) {\n\t\t\tvar length = data.length;\n\t\t\tvar ids = [];\n\t\t\tfor(var i=0; i<length; i++){\n\t\t\t\tids.push(data[i]['id']);\n\t\t\t}\n\t\t\t\n\t\t\tinitMenuCheck(ids);\n\t\t}\n\t});\n}\n\nfunction initMenuCheck(ids) {\n\tvar treeObj = $.fn.zTree.getZTreeObj(\"treeDemo\");\n\tvar length = ids.length;\n\tif(length > 0){\n\t\tvar node = treeObj.getNodeByParam(\"id\", 0, null);\n\t\ttreeObj.checkNode(node, true, false);\n\t}\n\t\n\tfor(var i=0; i<length; i++){\n\t\tvar node = treeObj.getNodeByParam(\"id\", ids[i], null);\n\t\ttreeObj.checkNode(node, true, false);\n\t}\n\t\n}\n\nfunction getCheckedMenuIds(){\n\tvar treeObj = $.fn.zTree.getZTreeObj(\"treeDemo\");\n\tvar nodes = treeObj.getCheckedNodes(true);\n\t\n\tvar length = nodes.length;\n\tvar ids = [];\n\tfor(var i=0; i<length; i++){\n\t\tvar n = nodes[i];\n\t\tvar id = n['id'];\n\t\tids.push(id);\n\t}\n\t\n\treturn ids;\n}\n\nfunction createNode(d) {\n\tvar id = d['id'];\n\tvar pId = d['parentId'];\n\tvar name = d['name'];\n\tvar child = d['child'];\n\n\tvar node = {\n\t\topen : true,\n\t\tid : id,\n\t\tname : name,\n\t\tpId : pId,\n\t};\n\n\tif (child != null) {\n\t\tvar length = child.length;\n\t\tif (length > 0) {\n\t\t\tvar children = [];\n\t\t\tfor (var i = 0; i < length; i++) {\n\t\t\t\tchildren[i] = createNode(child[i]);\n\t\t\t}\n\n\t\t\tnode.children = children;\n\t\t}\n\n\t}\n\treturn node;\n}\n\nfunction initParentMenuSelect(){\n\t$.ajax({\n        type : 'get',\n        url : '/permissions/parents',\n        async : false,\n        success : function(data) {\n            var select = $(\"#parentId\");\n            select.append(\"<option value='0'>root</option>\");\n            for(var i=0; i<data.length; i++){\n                var d = data[i];\n                var id = d['id'];\n                var name = d['name'];\n                \n                select.append(\"<option value='\"+ id +\"'>\" +name+\"</option>\");\n            }\n        }\n    });\n}\n\nfunction initModuleSelect(){\n    $.ajax({\n        type : 'get',\n        url : '/sys/module',\n        async : false,\n        success : function(data) {\n            var select = $(\"#moduleId\");\n            select.append(\"<option value=''>==请选择==</option>\");\n            for(var i=0; i<data.length; i++){\n                var d = data[i];\n                var id = d['id'];\n                var name = d['name'];\n                select.append(\"<option value='\"+ id +\"'>\" +name+\"</option>\");\n            }\n        }\n    });\n}\n\nfunction getParentServer() {\n    var moduleId = $(\"#moduleId option:selected\").val();\n    $.ajax({\n        type : 'post',\n        url : '/sys/server/list',\n        dataType:\"json\",\n        data:{moduleId:moduleId},\n        async:false,\n        cache: false,\n        success : function(data) {\n            var select = $(\"#parentId\");\n            select.html(\"\");\n            select.append(\"<option value='0'>root</option>\");\n            for(var i=0; i<data.length; i++){\n                var d = data[i];\n                var id = d['id'];\n                var name = d['name'];\n                select.append(\"<option value='\"+ id +\"'>\" +name+\"</option>\");\n            }\n        }\n    });\n}\n\nfunction getSettting() {\n\tvar setting = {\n\t\tcheck : {\n\t\t\tenable : true,\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\tasync : {\n\t\t\tenable : true,\n\t\t},\n\t\tdata : {\n\t\t\tsimpleData : {\n\t\t\t\tenable : true,\n\t\t\t\tidKey : \"id\",\n\t\t\t\tpIdKey : \"pId\",\n\t\t\t\trootPId : 0\n\t\t\t}\n\t\t},\n\t\tcallback : {\n\t\t\tonCheck : zTreeOnCheck\n\t\t}\n\t};\n\n\treturn setting;\n}\n\nfunction zTreeOnCheck(event, treeId, treeNode) {\n//\tconsole.log(treeNode.id + \", \" + treeNode.name + \",\" + treeNode.checked\n//\t\t\t+ \",\" + treeNode.pId);\n//\tconsole.log(JSON.stringify(treeNode));\n}"
  },
  {
    "path": "open-layui-web/src/main/view/static/js/my/ztree-service.js",
    "content": "function getMenuTree() {\n\tvar root = {\n\t\tid : 0,\n\t\tname : \"root\",\n\t\topen : true,\n\t};\n\n\t$.ajax({\n\t\ttype : 'get',\n\t\turl : '/services/all',\n\t\tcontentType : \"application/json; charset=utf-8\",\n\t\tasync : false,\n\t\tsuccess : function(data) {\n\t\t\tvar length = data.length;\n\t\t\tvar children = [];\n\t\t\tfor (var i = 0; i < length; i++) {\n\t\t\t\tvar d = data[i];\n\t\t\t\tvar node = createNode(d);\n\t\t\t\tchildren[i] = node;\n\t\t\t}\n\n\t\t\troot.children = children;\n\t\t}\n\t});\n\n\treturn root;\n}\n\nfunction initMenuDatas(clientId){\n\t$.ajax({\n\t\ttype : 'get',\n\t\turl : '/services?clientId=' + clientId,\n\t\tsuccess : function(data) {\n\t\t\tvar length = data.length;\n\t\t\tvar ids = [];\n\t\t\tfor(var i=0; i<length; i++){\n\t\t\t\tids.push(data[i]['id']);\n\t\t\t}\n\t\t\t\n\t\t\tinitMenuCheck(ids);\n\t\t}\n\t});\n}\n\nfunction initMenuCheck(ids) {\n\tvar treeObj = $.fn.zTree.getZTreeObj(\"treeDemo\");\n\tvar length = ids.length;\n\tif(length > 0){\n\t\tvar node = treeObj.getNodeByParam(\"id\", 0, null);\n\t\ttreeObj.checkNode(node, true, false);\n\t}\n\t\n\tfor(var i=0; i<length; i++){\n\t\tvar node = treeObj.getNodeByParam(\"id\", ids[i], null);\n\t\ttreeObj.checkNode(node, true, false);\n\t}\n\t\n}\n\nfunction getCheckedMenuIds(){\n\tvar treeObj = $.fn.zTree.getZTreeObj(\"treeDemo\");\n\tvar nodes = treeObj.getCheckedNodes(true);\n\t\n\tvar length = nodes.length;\n\tvar ids = [];\n\tfor(var i=0; i<length; i++){\n\t\tvar n = nodes[i];\n\t\tvar id = n['id'];\n\t\tids.push(id);\n\t}\n\t\n\treturn ids;\n}\n\nfunction createNode(d) {\n\tvar id = d['id'];\n\tvar pId = d['parentId'];\n\tvar name = d['name'];\n\tvar child = d['child'];\n\n\tvar node = {\n\t\topen : true,\n\t\tid : id,\n\t\tname : name,\n\t\tpId : pId,\n\t};\n\n\tif (child != null) {\n\t\tvar length = child.length;\n\t\tif (length > 0) {\n\t\t\tvar children = [];\n\t\t\tfor (var i = 0; i < length; i++) {\n\t\t\t\tchildren[i] = createNode(child[i]);\n\t\t\t}\n\n\t\t\tnode.children = children;\n\t\t}\n\n\t}\n\treturn node;\n}\n\nfunction initParentMenuSelect(){\n\t$.ajax({\n        type : 'get',\n        url : '/services/parents',\n        async : false,\n        success : function(data) {\n            var select = $(\"#parentId\");\n            select.append(\"<option value='0'>root</option>\");\n            for(var i=0; i<data.length; i++){\n                var d = data[i];\n                var id = d['id'];\n                var name = d['name'];\n                \n                select.append(\"<option value='\"+ id +\"'>\" +name+\"</option>\");\n            }\n        }\n    });\n}\n\nfunction initModuleSelect(){\n    $.ajax({\n        type : 'get',\n        url : '/sys/module',\n        async : false,\n        success : function(data) {\n            var select = $(\"#moduleId\");\n            select.append(\"<option value=''>==请选择==</option>\");\n            for(var i=0; i<data.length; i++){\n                var d = data[i];\n                var id = d['id'];\n                var name = d['name'];\n                select.append(\"<option value='\"+ id +\"'>\" +name+\"</option>\");\n            }\n        }\n    });\n}\n\nfunction getParentServer() {\n    var moduleId = $(\"#moduleId option:selected\").val();\n    $.ajax({\n        type : 'post',\n        url : '/sys/server/list',\n        dataType:\"json\",\n        data:{moduleId:moduleId},\n        async:false,\n        cache: false,\n        success : function(data) {\n            var select = $(\"#parentId\");\n            select.html(\"\");\n            select.append(\"<option value='0'>root</option>\");\n            for(var i=0; i<data.length; i++){\n                var d = data[i];\n                var id = d['id'];\n                var name = d['name'];\n                select.append(\"<option value='\"+ id +\"'>\" +name+\"</option>\");\n            }\n        }\n    });\n}\n\nfunction getSettting() {\n\tvar setting = {\n\t\tcheck : {\n\t\t\tenable : true,\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\tasync : {\n\t\t\tenable : true,\n\t\t},\n\t\tdata : {\n\t\t\tsimpleData : {\n\t\t\t\tenable : true,\n\t\t\t\tidKey : \"id\",\n\t\t\t\tpIdKey : \"pId\",\n\t\t\t\trootPId : 0\n\t\t\t}\n\t\t},\n\t\tcallback : {\n\t\t\tonCheck : zTreeOnCheck\n\t\t}\n\t};\n\n\treturn setting;\n}\n\nfunction zTreeOnCheck(event, treeId, treeNode) {\n//\tconsole.log(treeNode.id + \", \" + treeNode.name + \",\" + treeNode.checked\n//\t\t\t+ \",\" + treeNode.pId);\n//\tconsole.log(JSON.stringify(treeNode));\n}"
  },
  {
    "path": "open-layui-web/src/main/view/static/js/plugin/datatables/Chinese.lang",
    "content": "{\n\t\"sProcessing\":   \"处理中...\",\n\t\"sLengthMenu\":   \"显示 _MENU_ 项结果\",\n\t\"sZeroRecords\":  \"没有匹配结果\",\n\t\"sInfo\":         \"显示第 _START_ 至 _END_ 项结果，共 _TOTAL_ 项\",\n\t\"sInfoEmpty\":    \"显示第 0 至 0 项结果，共 0 项\",\n\t\"sInfoFiltered\": \"(由 _MAX_ 项结果过滤)\",\n\t\"sInfoPostFix\":  \"\",\n\t\"sSearch\":       \"搜索:\",\n\t\"sUrl\":          \"\",\n\t\"sEmptyTable\":     \"表中数据为空\",\n\t\"sLoadingRecords\": \"载入中...\",\n\t\"sInfoThousands\":  \",\",\n\t\"oPaginate\": {\n\t\t\"sFirst\":    \"首页\",\n\t\t\"sPrevious\": \"上页\",\n\t\t\"sNext\":     \"下页\",\n\t\t\"sLast\":     \"末页\"\n\t},\n\t\"oAria\": {\n\t\t\"sSortAscending\":  \": 以升序排列此列\",\n\t\t\"sSortDescending\": \": 以降序排列此列\"\n\t}\n}"
  },
  {
    "path": "open-layui-web/src/main/view/static/js/util/ajaxutils.js",
    "content": "/**\n * Created by nbfujx on 2017/12/28.\n */\n\n\nfunction getJSON (url) {\n    return new Promise( (resolve, reject) => {\n        var xhr = new XMLHttpRequest()\n        xhr.open('GET', url, true)\n\n        xhr.onreadystatechange = function () {\n            if (this.readyState === 4) {\n                if (this.status === 200) {\n                    debugger;\n                    if(this.responseText!=\"401\") {\n                        resolve(this.responseText, this)\n                    }else{\n                        window.location.href=\"/login\";\n                    }\n                } else {\n                    var resJson = { code: this.status, response: this.response }\n                    reject(resJson, this)\n                }\n            }\n        }\n\n        xhr.send()\n    })\n}\n\nfunction postJSON(url, data) {\n    return new Promise( (resolve, reject) => {\n        var xhr = new XMLHttpRequest()\n        xhr.open(\"POST\", url, true)\n        xhr.setRequestHeader(\"Content-type\", \"application/json\");\n\n        xhr.onreadystatechange = function () {\n            if (this.readyState === 4) {\n                if (this.status === 200) {\n                    if(this.responseText!=\"401\") {\n                        resolve(JSON.parse(this.responseText), this)\n                    }else{\n                        window.location.href=\"/login\";\n                    }\n                } else {\n                    var resJson = { code: this.status, response: this.response }\n                    reject(resJson, this)\n                }\n            }\n        }\n\n        xhr.send(JSON.stringify(data))\n    })\n}\n\nfunction serializeObject(form){\n    var o ={};\n    $.each(form.serializeArray(),function(index){\n        if(o[this['name']]){\n            o[this['name']] = o[this['name']] +\",\"+this['value'];\n\n        }else{\n            o[this['name']] = this['value'];\n        }\n    });\n    return o;\n}\n\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/layui/css/layui.css",
    "content": "/** layui-v2.3.0-rc1 MIT License By https://www.layui.com */\n .layui-inline,img{display:inline-block;vertical-align:middle}.layui-rate,li{list-style:none}h1,h2,h3,h4,h5,h6{font-weight:400}.layui-edge,.layui-header,.layui-inline,.layui-main{position:relative}.layui-btn,.layui-edge,.layui-inline,img{vertical-align:middle}.layui-btn,.layui-disabled,.layui-icon,.layui-unselect{-webkit-user-select:none;-ms-user-select:none;-moz-user-select:none}blockquote,body,button,dd,div,dl,dt,form,h1,h2,h3,h4,h5,h6,input,li,ol,p,pre,td,textarea,th,ul{margin:0;padding:0;-webkit-tap-highlight-color:rgba(0,0,0,0)}a:active,a:hover{outline:0}img{border:none}table{border-collapse:collapse;border-spacing:0}h4,h5,h6{font-size:100%}button,input,optgroup,option,select,textarea{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;outline:0}pre{white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word}body{line-height:24px;font:14px Helvetica Neue,Helvetica,PingFang SC,\\5FAE\\8F6F\\96C5\\9ED1,Tahoma,Arial,sans-serif}hr{height:1px;margin:10px 0;border:0;clear:both}a{color:#333;text-decoration:none}a:hover{color:#777}a cite{font-style:normal;*cursor:pointer}.layui-border-box,.layui-border-box *{box-sizing:border-box}.layui-box,.layui-box *{box-sizing:content-box}.layui-clear{clear:both;*zoom:1}.layui-clear:after{content:'\\20';clear:both;*zoom:1;display:block;height:0}.layui-inline{*display:inline;*zoom:1}.layui-edge{display:inline-block;width:0;height:0;border-width:6px;border-style:dashed;border-color:transparent;overflow:hidden}.layui-edge-top{top:-4px;border-bottom-color:#999;border-bottom-style:solid}.layui-edge-right{border-left-color:#999;border-left-style:solid}.layui-edge-bottom{top:2px;border-top-color:#999;border-top-style:solid}.layui-edge-left{border-right-color:#999;border-right-style:solid}.layui-elip{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-disabled,.layui-disabled:hover{color:#d2d2d2!important;cursor:not-allowed!important}.layui-circle{border-radius:100%}.layui-show{display:block!important}.layui-hide{display:none!important}@font-face{font-family:layui-icon;src:url(../font/iconfont.eot?v=230-rc1);src:url(../font/iconfont.eot?v=230-rc1#iefix) format('embedded-opentype'),url(../font/iconfont.svg?v=230-rc1#iconfont) format('svg'),url(../font/iconfont.woff?v=230-rc1) format('woff'),url(../font/iconfont.ttf?v=230-rc1) format('truetype')}.layui-icon{font-family:layui-icon!important;font-size:16px;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.layui-icon-reply-fill:before{content:\"\\e611\"}.layui-icon-set-fill:before{content:\"\\e614\"}.layui-icon-menu-fill:before{content:\"\\e60f\"}.layui-icon-search:before{content:\"\\e615\"}.layui-icon-share:before{content:\"\\e641\"}.layui-icon-set-sm:before{content:\"\\e620\"}.layui-icon-engine:before{content:\"\\e628\"}.layui-icon-close:before{content:\"\\1006\"}.layui-icon-close-fill:before{content:\"\\1007\"}.layui-icon-chart-screen:before{content:\"\\e629\"}.layui-icon-star:before{content:\"\\e600\"}.layui-icon-circle-dot:before{content:\"\\e617\"}.layui-icon-chat:before{content:\"\\e606\"}.layui-icon-release:before{content:\"\\e609\"}.layui-icon-list:before{content:\"\\e60a\"}.layui-icon-chart:before{content:\"\\e62c\"}.layui-icon-ok-circle:before{content:\"\\1005\"}.layui-icon-layim-theme:before{content:\"\\e61b\"}.layui-icon-table:before{content:\"\\e62d\"}.layui-icon-right:before{content:\"\\e602\"}.layui-icon-left:before{content:\"\\e603\"}.layui-icon-cart-simple:before{content:\"\\e698\"}.layui-icon-face-cry:before{content:\"\\e69c\"}.layui-icon-face-smile:before{content:\"\\e6af\"}.layui-icon-survey:before{content:\"\\e6b2\"}.layui-icon-tree:before{content:\"\\e62e\"}.layui-icon-upload-circle:before{content:\"\\e62f\"}.layui-icon-add-circle:before{content:\"\\e61f\"}.layui-icon-download-circle:before{content:\"\\e601\"}.layui-icon-templeate-1:before{content:\"\\e630\"}.layui-icon-util:before{content:\"\\e631\"}.layui-icon-face-surprised:before{content:\"\\e664\"}.layui-icon-edit:before{content:\"\\e642\"}.layui-icon-speaker:before{content:\"\\e645\"}.layui-icon-down:before{content:\"\\e61a\"}.layui-icon-file:before{content:\"\\e621\"}.layui-icon-layouts:before{content:\"\\e632\"}.layui-icon-rate-half:before{content:\"\\e6c9\"}.layui-icon-add-circle-fine:before{content:\"\\e608\"}.layui-icon-prev-circle:before{content:\"\\e633\"}.layui-icon-read:before{content:\"\\e705\"}.layui-icon-404:before{content:\"\\e61c\"}.layui-icon-carousel:before{content:\"\\e634\"}.layui-icon-help:before{content:\"\\e607\"}.layui-icon-code-circle:before{content:\"\\e635\"}.layui-icon-water:before{content:\"\\e636\"}.layui-icon-username:before{content:\"\\e66f\"}.layui-icon-find-fill:before{content:\"\\e670\"}.layui-icon-about:before{content:\"\\e60b\"}.layui-icon-location:before{content:\"\\e715\"}.layui-icon-up:before{content:\"\\e619\"}.layui-icon-pause:before{content:\"\\e651\"}.layui-icon-date:before{content:\"\\e637\"}.layui-icon-layim-uploadfile:before{content:\"\\e61d\"}.layui-icon-delete:before{content:\"\\e640\"}.layui-icon-play:before{content:\"\\e652\"}.layui-icon-top:before{content:\"\\e604\"}.layui-icon-friends:before{content:\"\\e612\"}.layui-icon-refresh-3:before{content:\"\\e9aa\"}.layui-icon-ok:before{content:\"\\e605\"}.layui-icon-layer:before{content:\"\\e638\"}.layui-icon-face-smile-fine:before{content:\"\\e60c\"}.layui-icon-dollar:before{content:\"\\e659\"}.layui-icon-group:before{content:\"\\e613\"}.layui-icon-layim-download:before{content:\"\\e61e\"}.layui-icon-picture-fine:before{content:\"\\e60d\"}.layui-icon-link:before{content:\"\\e64c\"}.layui-icon-diamond:before{content:\"\\e735\"}.layui-icon-log:before{content:\"\\e60e\"}.layui-icon-rate-solid:before{content:\"\\e67a\"}.layui-icon-fonts-del:before{content:\"\\e64f\"}.layui-icon-unlink:before{content:\"\\e64d\"}.layui-icon-fonts-clear:before{content:\"\\e639\"}.layui-icon-triangle-r:before{content:\"\\e623\"}.layui-icon-circle:before{content:\"\\e63f\"}.layui-icon-radio:before{content:\"\\e643\"}.layui-icon-align-center:before{content:\"\\e647\"}.layui-icon-align-right:before{content:\"\\e648\"}.layui-icon-align-left:before{content:\"\\e649\"}.layui-icon-loading-1:before{content:\"\\e63e\"}.layui-icon-return:before{content:\"\\e65c\"}.layui-icon-fonts-strong:before{content:\"\\e62b\"}.layui-icon-upload:before{content:\"\\e67c\"}.layui-icon-dialogue:before{content:\"\\e63a\"}.layui-icon-video:before{content:\"\\e6ed\"}.layui-icon-headset:before{content:\"\\e6fc\"}.layui-icon-cellphone-fine:before{content:\"\\e63b\"}.layui-icon-add-1:before{content:\"\\e654\"}.layui-icon-face-smile-b:before{content:\"\\e650\"}.layui-icon-fonts-html:before{content:\"\\e64b\"}.layui-icon-form:before{content:\"\\e63c\"}.layui-icon-cart:before{content:\"\\e657\"}.layui-icon-camera-fill:before{content:\"\\e65d\"}.layui-icon-tabs:before{content:\"\\e62a\"}.layui-icon-fonts-code:before{content:\"\\e64e\"}.layui-icon-fire:before{content:\"\\e756\"}.layui-icon-set:before{content:\"\\e716\"}.layui-icon-fonts-u:before{content:\"\\e646\"}.layui-icon-triangle-d:before{content:\"\\e625\"}.layui-icon-tips:before{content:\"\\e702\"}.layui-icon-picture:before{content:\"\\e64a\"}.layui-icon-more-vertical:before{content:\"\\e671\"}.layui-icon-flag:before{content:\"\\e66c\"}.layui-icon-loading:before{content:\"\\e63d\"}.layui-icon-fonts-i:before{content:\"\\e644\"}.layui-icon-refresh-1:before{content:\"\\e666\"}.layui-icon-rmb:before{content:\"\\e65e\"}.layui-icon-home:before{content:\"\\e68e\"}.layui-icon-user:before{content:\"\\e770\"}.layui-icon-notice:before{content:\"\\e667\"}.layui-icon-login-weibo:before{content:\"\\e675\"}.layui-icon-voice:before{content:\"\\e688\"}.layui-icon-upload-drag:before{content:\"\\e681\"}.layui-icon-login-qq:before{content:\"\\e676\"}.layui-icon-snowflake:before{content:\"\\e6b1\"}.layui-icon-file-b:before{content:\"\\e655\"}.layui-icon-template:before{content:\"\\e663\"}.layui-icon-auz:before{content:\"\\e672\"}.layui-icon-console:before{content:\"\\e665\"}.layui-icon-app:before{content:\"\\e653\"}.layui-icon-prev:before{content:\"\\e65a\"}.layui-icon-website:before{content:\"\\e7ae\"}.layui-icon-next:before{content:\"\\e65b\"}.layui-icon-component:before{content:\"\\e857\"}.layui-icon-more:before{content:\"\\e65f\"}.layui-icon-login-wechat:before{content:\"\\e677\"}.layui-icon-shrink-right:before{content:\"\\e668\"}.layui-icon-spread-left:before{content:\"\\e66b\"}.layui-icon-camera:before{content:\"\\e660\"}.layui-icon-note:before{content:\"\\e66e\"}.layui-icon-refresh:before{content:\"\\e669\"}.layui-icon-female:before{content:\"\\e661\"}.layui-icon-male:before{content:\"\\e662\"}.layui-icon-password:before{content:\"\\e673\"}.layui-icon-senior:before{content:\"\\e674\"}.layui-icon-theme:before{content:\"\\e66a\"}.layui-icon-tread:before{content:\"\\e6c5\"}.layui-icon-praise:before{content:\"\\e6c6\"}.layui-icon-star-fill:before{content:\"\\e658\"}.layui-icon-rate:before{content:\"\\e67b\"}.layui-icon-template-1:before{content:\"\\e656\"}.layui-icon-vercode:before{content:\"\\e679\"}.layui-icon-cellphone:before{content:\"\\e678\"}.layui-main{width:1140px;margin:0 auto}.layui-header{z-index:1000;height:60px}.layui-header a:hover{transition:all .5s;-webkit-transition:all .5s}.layui-side{position:fixed;left:0;top:0;bottom:0;z-index:999;width:200px;overflow-x:hidden}.layui-side-scroll{position:relative;width:220px;height:100%;overflow-x:hidden}.layui-body{position:absolute;left:200px;right:0;top:0;bottom:0;z-index:998;width:auto;overflow:hidden;overflow-y:auto;box-sizing:border-box}.layui-layout-body{overflow:hidden}.layui-layout-admin .layui-header{background-color:#23262E}.layui-layout-admin .layui-side{top:60px;width:200px;overflow-x:hidden}.layui-layout-admin .layui-body{top:60px;bottom:44px}.layui-layout-admin .layui-main{width:auto;margin:0 15px}.layui-layout-admin .layui-footer{position:fixed;left:200px;right:0;bottom:0;height:44px;line-height:44px;padding:0 15px;background-color:#eee}.layui-layout-admin .layui-logo{position:absolute;left:0;top:0;width:200px;height:100%;line-height:60px;text-align:center;color:#009688;font-size:16px}.layui-layout-admin .layui-header .layui-nav{background:0 0}.layui-layout-left{position:absolute!important;left:200px;top:0}.layui-layout-right{position:absolute!important;right:0;top:0}.layui-container{position:relative;margin:0 auto;padding:0 15px;box-sizing:border-box}.layui-fluid{position:relative;margin:0 auto;padding:0 15px}.layui-row:after,.layui-row:before{content:'';display:block;clear:both}.layui-col-lg1,.layui-col-lg10,.layui-col-lg11,.layui-col-lg12,.layui-col-lg2,.layui-col-lg3,.layui-col-lg4,.layui-col-lg5,.layui-col-lg6,.layui-col-lg7,.layui-col-lg8,.layui-col-lg9,.layui-col-md1,.layui-col-md10,.layui-col-md11,.layui-col-md12,.layui-col-md2,.layui-col-md3,.layui-col-md4,.layui-col-md5,.layui-col-md6,.layui-col-md7,.layui-col-md8,.layui-col-md9,.layui-col-sm1,.layui-col-sm10,.layui-col-sm11,.layui-col-sm12,.layui-col-sm2,.layui-col-sm3,.layui-col-sm4,.layui-col-sm5,.layui-col-sm6,.layui-col-sm7,.layui-col-sm8,.layui-col-sm9,.layui-col-xs1,.layui-col-xs10,.layui-col-xs11,.layui-col-xs12,.layui-col-xs2,.layui-col-xs3,.layui-col-xs4,.layui-col-xs5,.layui-col-xs6,.layui-col-xs7,.layui-col-xs8,.layui-col-xs9{position:relative;display:block;box-sizing:border-box}.layui-col-xs1,.layui-col-xs10,.layui-col-xs11,.layui-col-xs12,.layui-col-xs2,.layui-col-xs3,.layui-col-xs4,.layui-col-xs5,.layui-col-xs6,.layui-col-xs7,.layui-col-xs8,.layui-col-xs9{float:left}.layui-col-xs1{width:8.33333333%}.layui-col-xs2{width:16.66666667%}.layui-col-xs3{width:25%}.layui-col-xs4{width:33.33333333%}.layui-col-xs5{width:41.66666667%}.layui-col-xs6{width:50%}.layui-col-xs7{width:58.33333333%}.layui-col-xs8{width:66.66666667%}.layui-col-xs9{width:75%}.layui-col-xs10{width:83.33333333%}.layui-col-xs11{width:91.66666667%}.layui-col-xs12{width:100%}.layui-col-xs-offset1{margin-left:8.33333333%}.layui-col-xs-offset2{margin-left:16.66666667%}.layui-col-xs-offset3{margin-left:25%}.layui-col-xs-offset4{margin-left:33.33333333%}.layui-col-xs-offset5{margin-left:41.66666667%}.layui-col-xs-offset6{margin-left:50%}.layui-col-xs-offset7{margin-left:58.33333333%}.layui-col-xs-offset8{margin-left:66.66666667%}.layui-col-xs-offset9{margin-left:75%}.layui-col-xs-offset10{margin-left:83.33333333%}.layui-col-xs-offset11{margin-left:91.66666667%}.layui-col-xs-offset12{margin-left:100%}@media screen and (max-width:768px){.layui-hide-xs{display:none!important}.layui-show-xs-block{display:block!important}.layui-show-xs-inline{display:inline!important}.layui-show-xs-inline-block{display:inline-block!important}}@media screen and (min-width:768px){.layui-container{width:750px}.layui-hide-sm{display:none!important}.layui-show-sm-block{display:block!important}.layui-show-sm-inline{display:inline!important}.layui-show-sm-inline-block{display:inline-block!important}.layui-col-sm1,.layui-col-sm10,.layui-col-sm11,.layui-col-sm12,.layui-col-sm2,.layui-col-sm3,.layui-col-sm4,.layui-col-sm5,.layui-col-sm6,.layui-col-sm7,.layui-col-sm8,.layui-col-sm9{float:left}.layui-col-sm1{width:8.33333333%}.layui-col-sm2{width:16.66666667%}.layui-col-sm3{width:25%}.layui-col-sm4{width:33.33333333%}.layui-col-sm5{width:41.66666667%}.layui-col-sm6{width:50%}.layui-col-sm7{width:58.33333333%}.layui-col-sm8{width:66.66666667%}.layui-col-sm9{width:75%}.layui-col-sm10{width:83.33333333%}.layui-col-sm11{width:91.66666667%}.layui-col-sm12{width:100%}.layui-col-sm-offset1{margin-left:8.33333333%}.layui-col-sm-offset2{margin-left:16.66666667%}.layui-col-sm-offset3{margin-left:25%}.layui-col-sm-offset4{margin-left:33.33333333%}.layui-col-sm-offset5{margin-left:41.66666667%}.layui-col-sm-offset6{margin-left:50%}.layui-col-sm-offset7{margin-left:58.33333333%}.layui-col-sm-offset8{margin-left:66.66666667%}.layui-col-sm-offset9{margin-left:75%}.layui-col-sm-offset10{margin-left:83.33333333%}.layui-col-sm-offset11{margin-left:91.66666667%}.layui-col-sm-offset12{margin-left:100%}}@media screen and (min-width:992px){.layui-container{width:970px}.layui-hide-md{display:none!important}.layui-show-md-block{display:block!important}.layui-show-md-inline{display:inline!important}.layui-show-md-inline-block{display:inline-block!important}.layui-col-md1,.layui-col-md10,.layui-col-md11,.layui-col-md12,.layui-col-md2,.layui-col-md3,.layui-col-md4,.layui-col-md5,.layui-col-md6,.layui-col-md7,.layui-col-md8,.layui-col-md9{float:left}.layui-col-md1{width:8.33333333%}.layui-col-md2{width:16.66666667%}.layui-col-md3{width:25%}.layui-col-md4{width:33.33333333%}.layui-col-md5{width:41.66666667%}.layui-col-md6{width:50%}.layui-col-md7{width:58.33333333%}.layui-col-md8{width:66.66666667%}.layui-col-md9{width:75%}.layui-col-md10{width:83.33333333%}.layui-col-md11{width:91.66666667%}.layui-col-md12{width:100%}.layui-col-md-offset1{margin-left:8.33333333%}.layui-col-md-offset2{margin-left:16.66666667%}.layui-col-md-offset3{margin-left:25%}.layui-col-md-offset4{margin-left:33.33333333%}.layui-col-md-offset5{margin-left:41.66666667%}.layui-col-md-offset6{margin-left:50%}.layui-col-md-offset7{margin-left:58.33333333%}.layui-col-md-offset8{margin-left:66.66666667%}.layui-col-md-offset9{margin-left:75%}.layui-col-md-offset10{margin-left:83.33333333%}.layui-col-md-offset11{margin-left:91.66666667%}.layui-col-md-offset12{margin-left:100%}}@media screen and (min-width:1200px){.layui-container{width:1170px}.layui-hide-lg{display:none!important}.layui-show-lg-block{display:block!important}.layui-show-lg-inline{display:inline!important}.layui-show-lg-inline-block{display:inline-block!important}.layui-col-lg1,.layui-col-lg10,.layui-col-lg11,.layui-col-lg12,.layui-col-lg2,.layui-col-lg3,.layui-col-lg4,.layui-col-lg5,.layui-col-lg6,.layui-col-lg7,.layui-col-lg8,.layui-col-lg9{float:left}.layui-col-lg1{width:8.33333333%}.layui-col-lg2{width:16.66666667%}.layui-col-lg3{width:25%}.layui-col-lg4{width:33.33333333%}.layui-col-lg5{width:41.66666667%}.layui-col-lg6{width:50%}.layui-col-lg7{width:58.33333333%}.layui-col-lg8{width:66.66666667%}.layui-col-lg9{width:75%}.layui-col-lg10{width:83.33333333%}.layui-col-lg11{width:91.66666667%}.layui-col-lg12{width:100%}.layui-col-lg-offset1{margin-left:8.33333333%}.layui-col-lg-offset2{margin-left:16.66666667%}.layui-col-lg-offset3{margin-left:25%}.layui-col-lg-offset4{margin-left:33.33333333%}.layui-col-lg-offset5{margin-left:41.66666667%}.layui-col-lg-offset6{margin-left:50%}.layui-col-lg-offset7{margin-left:58.33333333%}.layui-col-lg-offset8{margin-left:66.66666667%}.layui-col-lg-offset9{margin-left:75%}.layui-col-lg-offset10{margin-left:83.33333333%}.layui-col-lg-offset11{margin-left:91.66666667%}.layui-col-lg-offset12{margin-left:100%}}.layui-col-space1{margin:-.5px}.layui-col-space1>*{padding:.5px}.layui-col-space3{margin:-1.5px}.layui-col-space3>*{padding:1.5px}.layui-col-space5{margin:-2.5px}.layui-col-space5>*{padding:2.5px}.layui-col-space8{margin:-3.5px}.layui-col-space8>*{padding:3.5px}.layui-col-space10{margin:-5px}.layui-col-space10>*{padding:5px}.layui-col-space12{margin:-6px}.layui-col-space12>*{padding:6px}.layui-col-space15{margin:-7.5px}.layui-col-space15>*{padding:7.5px}.layui-col-space18{margin:-9px}.layui-col-space18>*{padding:9px}.layui-col-space20{margin:-10px}.layui-col-space20>*{padding:10px}.layui-col-space22{margin:-11px}.layui-col-space22>*{padding:11px}.layui-col-space25{margin:-12.5px}.layui-col-space25>*{padding:12.5px}.layui-col-space30{margin:-15px}.layui-col-space30>*{padding:15px}.layui-btn,.layui-input,.layui-select,.layui-textarea,.layui-upload-button{outline:0;-webkit-appearance:none;transition:all .3s;-webkit-transition:all .3s;box-sizing:border-box}.layui-elem-quote{margin-bottom:10px;padding:15px;line-height:22px;border-left:5px solid #009688;border-radius:0 2px 2px 0;background-color:#f2f2f2}.layui-quote-nm{border-style:solid;border-width:1px 1px 1px 5px;background:0 0}.layui-elem-field{margin-bottom:10px;padding:0;border-width:1px;border-style:solid}.layui-elem-field legend{margin-left:20px;padding:0 10px;font-size:20px;font-weight:300}.layui-field-title{margin:10px 0 20px;border-width:1px 0 0}.layui-field-box{padding:10px 15px}.layui-field-title .layui-field-box{padding:10px 0}.layui-progress{position:relative;height:6px;border-radius:20px;background-color:#e2e2e2}.layui-progress-bar{position:absolute;left:0;top:0;width:0;max-width:100%;height:6px;border-radius:20px;text-align:right;background-color:#5FB878;transition:all .3s;-webkit-transition:all .3s}.layui-progress-big,.layui-progress-big .layui-progress-bar{height:18px;line-height:18px}.layui-progress-text{position:relative;top:-20px;line-height:18px;font-size:12px;color:#666}.layui-progress-big .layui-progress-text{position:static;padding:0 10px;color:#fff}.layui-collapse{border-width:1px;border-style:solid;border-radius:2px}.layui-colla-content,.layui-colla-item{border-top-width:1px;border-top-style:solid}.layui-colla-item:first-child{border-top:none}.layui-colla-title{position:relative;height:42px;line-height:42px;padding:0 15px 0 35px;color:#333;background-color:#f2f2f2;cursor:pointer;font-size:14px;overflow:hidden}.layui-colla-content{display:none;padding:10px 15px;line-height:22px;color:#666}.layui-colla-icon{position:absolute;left:15px;top:0;font-size:14px}.layui-card-body,.layui-card-header,.layui-form-label,.layui-form-mid,.layui-form-select,.layui-input-block,.layui-input-inline,.layui-textarea{position:relative}.layui-card{margin-bottom:15px;border-radius:2px;background-color:#fff;box-shadow:0 1px 2px 0 rgba(0,0,0,.05)}.layui-card:last-child{margin-bottom:0}.layui-card-header{height:42px;line-height:42px;padding:0 15px;border-bottom:1px solid #f6f6f6;color:#333;border-radius:2px 2px 0 0;font-size:14px}.layui-bg-black,.layui-bg-blue,.layui-bg-cyan,.layui-bg-green,.layui-bg-orange,.layui-bg-red{color:#fff!important}.layui-card-body{padding:10px 15px;line-height:24px}.layui-card-body[pad15]{padding:15px}.layui-card-body[pad20]{padding:20px}.layui-card-body .layui-table{margin:5px 0}.layui-card .layui-tab{margin:0}.layui-panel-window{position:relative;padding:15px;border-radius:0;border-top:5px solid #E6E6E6;background-color:#fff}.layui-bg-red{background-color:#FF5722!important}.layui-bg-orange{background-color:#FFB800!important}.layui-bg-green{background-color:#009688!important}.layui-bg-cyan{background-color:#2F4056!important}.layui-bg-blue{background-color:#1E9FFF!important}.layui-bg-black{background-color:#393D49!important}.layui-bg-gray{background-color:#eee!important;color:#666!important}.layui-badge-rim,.layui-colla-content,.layui-colla-item,.layui-collapse,.layui-elem-field,.layui-form-pane .layui-form-item[pane],.layui-form-pane .layui-form-label,.layui-input,.layui-layedit,.layui-layedit-tool,.layui-quote-nm,.layui-select,.layui-tab-bar,.layui-tab-card,.layui-tab-title,.layui-tab-title .layui-this:after,.layui-textarea{border-color:#e6e6e6}.layui-timeline-item:before,hr{background-color:#e6e6e6}.layui-text{line-height:22px;font-size:14px;color:#666}.layui-text h1,.layui-text h2,.layui-text h3{font-weight:500;color:#333}.layui-text h1{font-size:30px}.layui-text h2{font-size:24px}.layui-text h3{font-size:18px}.layui-text a:not(.layui-btn){color:#01AAED}.layui-text a:not(.layui-btn):hover{text-decoration:underline}.layui-text ul{padding:5px 0 5px 15px}.layui-text ul li{margin-top:5px;list-style-type:disc}.layui-text em,.layui-word-aux{color:#999!important;padding:0 5px!important}.layui-btn{display:inline-block;height:38px;line-height:38px;padding:0 18px;background-color:#009688;color:#fff;white-space:nowrap;text-align:center;font-size:14px;border:none;border-radius:2px;cursor:pointer}.layui-btn:hover{opacity:.8;filter:alpha(opacity=80);color:#fff}.layui-btn:active{opacity:1;filter:alpha(opacity=100)}.layui-btn+.layui-btn{margin-left:10px}.layui-btn-container{font-size:0}.layui-btn-container .layui-btn{margin-right:10px;margin-bottom:10px}.layui-btn-container .layui-btn+.layui-btn{margin-left:0}.layui-table .layui-btn-container .layui-btn{margin-bottom:9px}.layui-btn-radius{border-radius:100px}.layui-btn .layui-icon{margin-right:3px;font-size:18px;vertical-align:bottom;vertical-align:middle\\9}.layui-btn-primary{border:1px solid #C9C9C9;background-color:#fff;color:#555}.layui-btn-primary:hover{border-color:#009688;color:#333}.layui-btn-normal{background-color:#1E9FFF}.layui-btn-warm{background-color:#FFB800}.layui-btn-danger{background-color:#FF5722}.layui-btn-disabled,.layui-btn-disabled:active,.layui-btn-disabled:hover{border:1px solid #e6e6e6;background-color:#FBFBFB;color:#C9C9C9;cursor:not-allowed;opacity:1}.layui-btn-lg{height:44px;line-height:44px;padding:0 25px;font-size:16px}.layui-btn-sm{height:30px;line-height:30px;padding:0 10px;font-size:12px}.layui-btn-sm i{font-size:16px!important}.layui-btn-xs{height:22px;line-height:22px;padding:0 5px;font-size:12px}.layui-btn-xs i{font-size:14px!important}.layui-btn-group{display:inline-block;vertical-align:middle;font-size:0}.layui-btn-group .layui-btn{margin-left:0!important;margin-right:0!important;border-left:1px solid rgba(255,255,255,.5);border-radius:0}.layui-btn-group .layui-btn-primary{border-left:none}.layui-btn-group .layui-btn-primary:hover{border-color:#C9C9C9;color:#009688}.layui-btn-group .layui-btn:first-child{border-left:none;border-radius:2px 0 0 2px}.layui-btn-group .layui-btn-primary:first-child{border-left:1px solid #c9c9c9}.layui-btn-group .layui-btn:last-child{border-radius:0 2px 2px 0}.layui-btn-group .layui-btn+.layui-btn{margin-left:0}.layui-btn-group+.layui-btn-group{margin-left:10px}.layui-btn-fluid{width:100%}.layui-input,.layui-select,.layui-textarea{height:38px;line-height:1.3;line-height:38px\\9;border-width:1px;border-style:solid;background-color:#fff;border-radius:2px}.layui-input::-webkit-input-placeholder,.layui-select::-webkit-input-placeholder,.layui-textarea::-webkit-input-placeholder{line-height:1.3}.layui-input,.layui-textarea{display:block;width:100%;padding-left:10px}.layui-input:hover,.layui-textarea:hover{border-color:#D2D2D2!important}.layui-input:focus,.layui-textarea:focus{border-color:#C9C9C9!important}.layui-textarea{min-height:100px;height:auto;line-height:20px;padding:6px 10px;resize:vertical}.layui-select{padding:0 10px}.layui-form input[type=checkbox],.layui-form input[type=radio],.layui-form select{display:none}.layui-form [lay-ignore]{display:initial}.layui-form-item{margin-bottom:15px;clear:both;*zoom:1}.layui-form-item:after{content:'\\20';clear:both;*zoom:1;display:block;height:0}.layui-form-label{float:left;display:block;padding:9px 15px;width:80px;font-weight:400;line-height:20px;text-align:right}.layui-form-label-col{display:block;float:none;padding:9px 0;line-height:20px;text-align:left}.layui-form-item .layui-inline{margin-bottom:5px;margin-right:10px}.layui-input-block{margin-left:110px;min-height:36px}.layui-input-inline{display:inline-block;vertical-align:middle}.layui-form-item .layui-input-inline{float:left;width:190px;margin-right:10px}.layui-form-text .layui-input-inline{width:auto}.layui-form-mid{float:left;display:block;padding:9px 0!important;line-height:20px;margin-right:10px}.layui-form-danger+.layui-form-select .layui-input,.layui-form-danger:focus{border-color:#FF5722!important}.layui-form-select .layui-input{padding-right:30px;cursor:pointer}.layui-form-select .layui-edge{position:absolute;right:10px;top:50%;margin-top:-3px;cursor:pointer;border-width:6px;border-top-color:#c2c2c2;border-top-style:solid;transition:all .3s;-webkit-transition:all .3s}.layui-form-select dl{display:none;position:absolute;left:0;top:42px;padding:5px 0;z-index:999;min-width:100%;border:1px solid #d2d2d2;max-height:300px;overflow-y:auto;background-color:#fff;border-radius:2px;box-shadow:0 2px 4px rgba(0,0,0,.12);box-sizing:border-box}.layui-form-select dl dd,.layui-form-select dl dt{padding:0 10px;line-height:36px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.layui-form-select dl dt{font-size:12px;color:#999}.layui-form-select dl dd{cursor:pointer}.layui-form-select dl dd:hover{background-color:#f2f2f2}.layui-form-select .layui-select-group dd{padding-left:20px}.layui-form-select dl dd.layui-select-tips{padding-left:10px!important;color:#999}.layui-form-select dl dd.layui-this{background-color:#5FB878;color:#fff}.layui-form-checkbox,.layui-form-select dl dd.layui-disabled{background-color:#fff}.layui-form-selected dl{display:block}.layui-form-checkbox,.layui-form-checkbox *,.layui-form-switch{display:inline-block;vertical-align:middle}.layui-form-selected .layui-edge{margin-top:-9px;-webkit-transform:rotate(180deg);transform:rotate(180deg);margin-top:-3px\\9}:root .layui-form-selected .layui-edge{margin-top:-9px\\0/IE9}.layui-form-selectup dl{top:auto;bottom:42px}.layui-select-none{margin:5px 0;text-align:center;color:#999}.layui-select-disabled .layui-disabled{border-color:#eee!important}.layui-select-disabled .layui-edge{border-top-color:#d2d2d2}.layui-form-checkbox{position:relative;height:30px;line-height:30px;margin-right:10px;padding-right:30px;cursor:pointer;font-size:0;-webkit-transition:.1s linear;transition:.1s linear;box-sizing:border-box}.layui-form-checkbox span{padding:0 10px;height:100%;font-size:14px;border-radius:2px 0 0 2px;background-color:#d2d2d2;color:#fff;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.layui-form-checkbox:hover span{background-color:#c2c2c2}.layui-form-checkbox i{position:absolute;right:0;top:0;width:30px;height:28px;border:1px solid #d2d2d2;border-left:none;border-radius:0 2px 2px 0;color:#fff;font-size:20px;text-align:center}.layui-form-checkbox:hover i{border-color:#c2c2c2;color:#c2c2c2}.layui-form-checked,.layui-form-checked:hover{border-color:#5FB878}.layui-form-checked span,.layui-form-checked:hover span{background-color:#5FB878}.layui-form-checked i,.layui-form-checked:hover i{color:#5FB878}.layui-form-item .layui-form-checkbox{margin-top:4px}.layui-form-checkbox[lay-skin=primary]{height:auto!important;line-height:normal!important;border:none!important;margin-right:0;padding-right:0;background:0 0}.layui-form-checkbox[lay-skin=primary] span{float:right;padding-right:15px;line-height:18px;background:0 0;color:#666}.layui-form-checkbox[lay-skin=primary] i{position:relative;top:0;width:16px;height:16px;line-height:16px;border:1px solid #d2d2d2;font-size:12px;border-radius:2px;background-color:#fff;-webkit-transition:.1s linear;transition:.1s linear}.layui-form-checkbox[lay-skin=primary]:hover i{border-color:#5FB878;color:#fff}.layui-form-checked[lay-skin=primary] i{border-color:#5FB878;background-color:#5FB878;color:#fff}.layui-checkbox-disbaled[lay-skin=primary] span{background:0 0!important;color:#c2c2c2}.layui-checkbox-disbaled[lay-skin=primary]:hover i{border-color:#d2d2d2}.layui-form-item .layui-form-checkbox[lay-skin=primary]{margin-top:10px}.layui-form-switch{position:relative;height:22px;line-height:22px;min-width:35px;padding:0 5px;margin-top:8px;border:1px solid #d2d2d2;border-radius:20px;cursor:pointer;background-color:#fff;-webkit-transition:.1s linear;transition:.1s linear}.layui-form-switch i{position:absolute;left:5px;top:3px;width:16px;height:16px;border-radius:20px;background-color:#d2d2d2;-webkit-transition:.1s linear;transition:.1s linear}.layui-form-switch em{position:relative;top:0;width:25px;margin-left:21px;padding:0!important;text-align:center!important;color:#999!important;font-style:normal!important;font-size:12px}.layui-form-onswitch{border-color:#5FB878;background-color:#5FB878}.layui-checkbox-disbaled,.layui-checkbox-disbaled i{border-color:#e2e2e2!important}.layui-form-onswitch i{left:100%;margin-left:-21px;background-color:#fff}.layui-form-onswitch em{margin-left:5px;margin-right:21px;color:#fff!important}.layui-checkbox-disbaled span{background-color:#e2e2e2!important}.layui-checkbox-disbaled:hover i{color:#fff!important}[lay-radio]{display:none}.layui-form-radio,.layui-form-radio *{display:inline-block;vertical-align:middle}.layui-form-radio{line-height:28px;margin:6px 10px 0 0;padding-right:10px;cursor:pointer;font-size:0}.layui-form-radio *{font-size:14px}.layui-form-radio>i{margin-right:8px;font-size:22px;color:#c2c2c2}.layui-form-radio>i:hover,.layui-form-radioed>i{color:#5FB878}.layui-radio-disbaled>i{color:#e2e2e2!important}.layui-form-pane .layui-form-label{width:110px;padding:8px 15px;height:38px;line-height:20px;border-width:1px;border-style:solid;border-radius:2px 0 0 2px;text-align:center;background-color:#FBFBFB;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;box-sizing:border-box}.layui-form-pane .layui-input-inline{margin-left:-1px}.layui-form-pane .layui-input-block{margin-left:110px;left:-1px}.layui-form-pane .layui-input{border-radius:0 2px 2px 0}.layui-form-pane .layui-form-text .layui-form-label{float:none;width:100%;border-radius:2px;box-sizing:border-box;text-align:left}.layui-form-pane .layui-form-text .layui-input-inline{display:block;margin:0;top:-1px;clear:both}.layui-form-pane .layui-form-text .layui-input-block{margin:0;left:0;top:-1px}.layui-form-pane .layui-form-text .layui-textarea{min-height:100px;border-radius:0 0 2px 2px}.layui-form-pane .layui-form-checkbox{margin:4px 0 4px 10px}.layui-form-pane .layui-form-radio,.layui-form-pane .layui-form-switch{margin-top:6px;margin-left:10px}.layui-form-pane .layui-form-item[pane]{position:relative;border-width:1px;border-style:solid}.layui-form-pane .layui-form-item[pane] .layui-form-label{position:absolute;left:0;top:0;height:100%;border-width:0 1px 0 0}.layui-form-pane .layui-form-item[pane] .layui-input-inline{margin-left:110px}@media screen and (max-width:450px){.layui-form-item .layui-form-label{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-form-item .layui-inline{display:block;margin-right:0;margin-bottom:20px;clear:both}.layui-form-item .layui-inline:after{content:'\\20';clear:both;display:block;height:0}.layui-form-item .layui-input-inline{display:block;float:none;left:-3px;width:auto;margin:0 0 10px 112px}.layui-form-item .layui-input-inline+.layui-form-mid{margin-left:110px;top:-5px;padding:0}.layui-form-item .layui-form-checkbox{margin-right:5px;margin-bottom:5px}}.layui-layedit{border-width:1px;border-style:solid;border-radius:2px}.layui-layedit-tool{padding:3px 5px;border-bottom-width:1px;border-bottom-style:solid;font-size:0}.layedit-tool-fixed{position:fixed;top:0;border-top:1px solid #e2e2e2}.layui-layedit-tool .layedit-tool-mid,.layui-layedit-tool .layui-icon{display:inline-block;vertical-align:middle;text-align:center;font-size:14px}.layui-layedit-tool .layui-icon{position:relative;width:32px;height:30px;line-height:30px;margin:3px 5px;color:#777;cursor:pointer;border-radius:2px}.layui-layedit-tool .layui-icon:hover{color:#393D49}.layui-layedit-tool .layui-icon:active{color:#000}.layui-layedit-tool .layedit-tool-active{background-color:#e2e2e2;color:#000}.layui-layedit-tool .layui-disabled,.layui-layedit-tool .layui-disabled:hover{color:#d2d2d2;cursor:not-allowed}.layui-layedit-tool .layedit-tool-mid{width:1px;height:18px;margin:0 10px;background-color:#d2d2d2}.layedit-tool-html{width:50px!important;font-size:30px!important}.layedit-tool-b,.layedit-tool-code,.layedit-tool-help{font-size:16px!important}.layedit-tool-d,.layedit-tool-face,.layedit-tool-image,.layedit-tool-unlink{font-size:18px!important}.layedit-tool-image input{position:absolute;font-size:0;left:0;top:0;width:100%;height:100%;opacity:.01;filter:Alpha(opacity=1);cursor:pointer}.layui-layedit-iframe iframe{display:block;width:100%}#LAY_layedit_code{overflow:hidden}.layui-laypage{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;margin:10px 0;font-size:0}.layui-laypage>a:first-child,.layui-laypage>a:first-child em{border-radius:2px 0 0 2px}.layui-laypage>a:last-child,.layui-laypage>a:last-child em{border-radius:0 2px 2px 0}.layui-laypage>:first-child{margin-left:0!important}.layui-laypage>:last-child{margin-right:0!important}.layui-laypage a,.layui-laypage button,.layui-laypage input,.layui-laypage select,.layui-laypage span{border:1px solid #e2e2e2}.layui-laypage a,.layui-laypage span{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;padding:0 15px;height:28px;line-height:28px;margin:0 -1px 5px 0;background-color:#fff;color:#333;font-size:12px}.layui-laypage a:hover{color:#009688}.layui-laypage em{font-style:normal}.layui-laypage .layui-laypage-spr{color:#999;font-weight:700}.layui-laypage a{text-decoration:none}.layui-laypage .layui-laypage-curr{position:relative}.layui-laypage .layui-laypage-curr em{position:relative;color:#fff}.layui-laypage .layui-laypage-curr .layui-laypage-em{position:absolute;left:-1px;top:-1px;padding:1px;width:100%;height:100%;background-color:#009688}.layui-laypage-em{border-radius:2px}.layui-laypage-next em,.layui-laypage-prev em{font-family:Sim sun;font-size:16px}.layui-laypage .layui-laypage-count,.layui-laypage .layui-laypage-limits,.layui-laypage .layui-laypage-refresh,.layui-laypage .layui-laypage-skip{margin-left:10px;margin-right:10px;padding:0;border:none}.layui-laypage .layui-laypage-limits,.layui-laypage .layui-laypage-refresh{vertical-align:top}.layui-laypage .layui-laypage-refresh i{font-size:18px;cursor:pointer}.layui-laypage select{height:22px;padding:3px;border-radius:2px;cursor:pointer}.layui-laypage .layui-laypage-skip{height:30px;line-height:30px;color:#999}.layui-laypage button,.layui-laypage input{height:30px;line-height:30px;border-radius:2px;vertical-align:top;background-color:#fff;box-sizing:border-box}.layui-laypage input{display:inline-block;width:40px;margin:0 10px;padding:0 3px;text-align:center}.layui-laypage input:focus,.layui-laypage select:focus{border-color:#009688!important}.layui-laypage button{margin-left:10px;padding:0 10px;cursor:pointer}.layui-table,.layui-table-view{margin:10px 0}.layui-flow-more{margin:10px 0;text-align:center;color:#999;font-size:14px}.layui-flow-more a{height:32px;line-height:32px}.layui-flow-more a *{display:inline-block;vertical-align:top}.layui-flow-more a cite{padding:0 20px;border-radius:3px;background-color:#eee;color:#333;font-style:normal}.layui-flow-more a cite:hover{opacity:.8}.layui-flow-more a i{font-size:30px;color:#737383}.layui-table{width:100%;background-color:#fff;color:#666}.layui-table tr{transition:all .3s;-webkit-transition:all .3s}.layui-table th{text-align:left;font-weight:400}.layui-table tbody tr:hover,.layui-table thead tr,.layui-table-click,.layui-table-header,.layui-table-hover,.layui-table-mend,.layui-table-patch,.layui-table-tool,.layui-table[lay-even] tr:nth-child(even){background-color:#f2f2f2}.layui-table td,.layui-table th,.layui-table-fixed-r,.layui-table-header,.layui-table-page,.layui-table-tips-main,.layui-table-tool,.layui-table-view,.layui-table[lay-skin=line],.layui-table[lay-skin=row]{border-width:1px;border-style:solid;border-color:#e6e6e6}.layui-table td,.layui-table th{position:relative;padding:9px 15px;min-height:20px;line-height:20px;font-size:14px}.layui-table[lay-skin=line] td,.layui-table[lay-skin=line] th{border-width:0 0 1px}.layui-table[lay-skin=row] td,.layui-table[lay-skin=row] th{border-width:0 1px 0 0}.layui-table[lay-skin=nob] td,.layui-table[lay-skin=nob] th{border:none}.layui-table img{max-width:100px}.layui-table[lay-size=lg] td,.layui-table[lay-size=lg] th{padding:15px 30px}.layui-table-view .layui-table[lay-size=lg] .layui-table-cell{height:40px;line-height:40px}.layui-table[lay-size=sm] td,.layui-table[lay-size=sm] th{font-size:12px;padding:5px 10px}.layui-table-view .layui-table[lay-size=sm] .layui-table-cell{height:20px;line-height:20px}.layui-table[lay-data]{display:none}.layui-table-box,.layui-table-view{position:relative;overflow:hidden}.layui-table-view .layui-table{position:relative;width:auto;margin:0}.layui-table-body,.layui-table-header .layui-table,.layui-table-page{margin-bottom:-1px}.layui-table-view .layui-table[lay-skin=line]{border-width:0 1px 0 0}.layui-table-view .layui-table[lay-skin=row]{border-width:0 0 1px}.layui-table-view .layui-table td,.layui-table-view .layui-table th{padding:5px 0;border-top:none;border-left:none}.layui-table-view .layui-table td{cursor:default}.layui-table-view .layui-form-checkbox[lay-skin=primary] i{width:18px;height:18px}.layui-table-header{border-width:0 0 1px;overflow:hidden}.layui-table-sort{width:10px;height:20px;margin-left:5px;cursor:pointer!important}.layui-table-sort .layui-edge{position:absolute;left:5px;border-width:5px}.layui-table-sort .layui-table-sort-asc{top:4px;border-top:none;border-bottom-style:solid;border-bottom-color:#b2b2b2}.layui-table-sort .layui-table-sort-asc:hover{border-bottom-color:#666}.layui-table-sort .layui-table-sort-desc{bottom:4px;border-bottom:none;border-top-style:solid;border-top-color:#b2b2b2}.layui-table-sort .layui-table-sort-desc:hover{border-top-color:#666}.layui-table-sort[lay-sort=asc] .layui-table-sort-asc{border-bottom-color:#000}.layui-table-sort[lay-sort=desc] .layui-table-sort-desc{border-top-color:#000}.layui-table-cell{height:28px;line-height:28px;padding:0 15px;position:relative;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;box-sizing:border-box}.layui-table-cell .layui-form-checkbox[lay-skin=primary],.layui-table-cell .layui-form-radio[lay-skin=primary]{top:-1px;vertical-align:middle}.layui-table-cell .layui-form-radio{padding-right:0}.layui-table-cell .layui-form-radio>i{margin-right:0}.layui-table-cell .layui-table-link{color:#01AAED}.laytable-cell-checkbox,.laytable-cell-numbers,.laytable-cell-radio,.laytable-cell-space{padding:0;text-align:center}.layui-table-body{position:relative;overflow:auto;margin-right:-1px}.layui-table-body .layui-none{line-height:40px;text-align:center;color:#999}.layui-table-fixed{position:absolute;left:0;top:0}.layui-table-fixed .layui-table-body{overflow:hidden}.layui-table-fixed-l{box-shadow:0 -1px 8px rgba(0,0,0,.08)}.layui-table-fixed-r{left:auto;right:-1px;border-width:0 0 0 1px;box-shadow:-1px 0 8px rgba(0,0,0,.08)}.layui-table-fixed-r .layui-table-header{position:relative;overflow:visible}.layui-table-mend{position:absolute;right:-49px;top:0;height:100%;width:50px}.layui-table-tool{position:relative;width:100%;height:50px;line-height:30px;padding:10px 15px;border-width:0 0 1px}.layui-table-page{position:relative;width:100%;padding:7px 7px 0;border-width:1px 0 0;height:41px;font-size:12px}.layui-table-page>div{height:26px}.layui-table-page .layui-laypage{margin:0}.layui-table-page .layui-laypage a,.layui-table-page .layui-laypage span{height:26px;line-height:26px;margin-bottom:10px;border:none;background:0 0}.layui-table-page .layui-laypage a,.layui-table-page .layui-laypage span.layui-laypage-curr{padding:0 12px}.layui-table-page .layui-laypage span{margin-left:0;padding:0}.layui-table-page .layui-laypage .layui-laypage-prev{margin-left:-7px!important}.layui-table-page .layui-laypage .layui-laypage-curr .layui-laypage-em{left:0;top:0;padding:0}.layui-table-page .layui-laypage button,.layui-table-page .layui-laypage input{height:26px;line-height:26px}.layui-table-page .layui-laypage input{width:40px}.layui-table-page .layui-laypage button{padding:0 10px}.layui-table-page select{height:18px}.layui-table-view select[lay-ignore]{display:inline-block}.layui-table-patch .layui-table-cell{padding:0;width:30px}.layui-table-edit{position:absolute;left:0;top:0;width:100%;height:100%;padding:0 14px 1px;border-radius:0;box-shadow:1px 1px 20px rgba(0,0,0,.15)}.layui-table-edit:focus{border-color:#5FB878!important}select.layui-table-edit{padding:0 0 0 10px;border-color:#C9C9C9}.layui-table-view .layui-form-checkbox,.layui-table-view .layui-form-radio,.layui-table-view .layui-form-switch{top:0;margin:0;box-sizing:content-box}.layui-table-view .layui-form-checkbox{top:-1px;height:26px;line-height:26px}body .layui-table-tips .layui-layer-content{background:0 0;padding:0;box-shadow:0 1px 6px rgba(0,0,0,.1)}.layui-table-tips-main{margin:-44px 0 0 -1px;max-height:150px;padding:8px 15px;font-size:14px;overflow-y:scroll;background-color:#fff;color:#333}.layui-table-tips-c{position:absolute;right:-3px;top:-12px;width:18px;height:18px;padding:3px;text-align:center;font-weight:700;border-radius:100%;font-size:14px;cursor:pointer;background-color:#666}.layui-table-tips-c:hover{background-color:#999}.layui-upload-file{display:none!important;opacity:.01;filter:Alpha(opacity=1)}.layui-upload-drag,.layui-upload-form,.layui-upload-wrap{display:inline-block}.layui-upload-list{margin:10px 0}.layui-upload-choose{padding:0 10px;color:#999}.layui-upload-drag{position:relative;padding:30px;border:1px dashed #e2e2e2;background-color:#fff;text-align:center;cursor:pointer;color:#999}.layui-upload-drag .layui-icon{font-size:50px;color:#009688}.layui-upload-drag[lay-over]{border-color:#009688}.layui-upload-iframe{position:absolute;width:0;height:0;border:0;visibility:hidden}.layui-upload-wrap{position:relative;vertical-align:middle}.layui-upload-wrap .layui-upload-file{display:block!important;position:absolute;left:0;top:0;z-index:10;font-size:100px;width:100%;height:100%;opacity:.01;filter:Alpha(opacity=1);cursor:pointer}.layui-rate,.layui-rate *{display:inline-block;vertical-align:middle}.layui-rate{padding:10px 5px 10px 0;font-size:0}.layui-rate li i.layui-icon{font-size:20px;color:#FFB800;margin-right:5px;transition:all .3s;-webkit-transition:all .3s}.layui-rate li i:hover{cursor:pointer;transform:scale(1.12);-webkit-transform:scale(1.12)}.layui-rate[readonly] li i:hover{cursor:default;transform:scale(1)}.layui-code{position:relative;margin:10px 0;padding:15px;line-height:20px;border:1px solid #ddd;border-left-width:6px;background-color:#F2F2F2;color:#333;font-family:Courier New;font-size:12px}.layui-tree{line-height:26px}.layui-tree li{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-tree li .layui-tree-spread,.layui-tree li a{display:inline-block;vertical-align:top;height:26px;*display:inline;*zoom:1;cursor:pointer}.layui-tree li a{font-size:0}.layui-tree li a i{font-size:16px}.layui-tree li a cite{padding:0 6px;font-size:14px;font-style:normal}.layui-tree li i{padding-left:6px;color:#333;-moz-user-select:none}.layui-tree li .layui-tree-check{font-size:13px}.layui-tree li .layui-tree-check:hover{color:#009E94}.layui-tree li ul{display:none;margin-left:20px}.layui-tree li .layui-tree-enter{line-height:24px;border:1px dotted #000}.layui-tree-drag{display:none;position:absolute;left:-666px;top:-666px;background-color:#f2f2f2;padding:5px 10px;border:1px dotted #000;white-space:nowrap}.layui-tree-drag i{padding-right:5px}.layui-nav{position:relative;padding:0 20px;background-color:#393D49;color:#fff;border-radius:2px;font-size:0;box-sizing:border-box}.layui-nav *{font-size:14px}.layui-nav .layui-nav-item{position:relative;display:inline-block;*display:inline;*zoom:1;vertical-align:middle;line-height:60px}.layui-nav .layui-nav-item a{display:block;padding:0 20px;color:#fff;color:rgba(255,255,255,.7);transition:all .3s;-webkit-transition:all .3s}.layui-nav .layui-this:after,.layui-nav-bar,.layui-nav-tree .layui-nav-itemed:after{position:absolute;left:0;top:0;width:0;height:5px;background-color:#5FB878;transition:all .2s;-webkit-transition:all .2s}.layui-nav-bar{z-index:1000}.layui-nav .layui-nav-item a:hover,.layui-nav .layui-this a{color:#fff}.layui-nav .layui-this:after{content:'';top:auto;bottom:0;width:100%}.layui-nav-img{width:30px;height:30px;margin-right:10px;border-radius:50%}.layui-nav .layui-nav-more{content:'';width:0;height:0;border-style:solid dashed dashed;border-color:#fff transparent transparent;overflow:hidden;cursor:pointer;transition:all .2s;-webkit-transition:all .2s;position:absolute;top:50%;right:3px;margin-top:-3px;border-width:6px;border-top-color:rgba(255,255,255,.7)}.layui-nav .layui-nav-mored,.layui-nav-itemed>a .layui-nav-more{margin-top:-9px;border-style:dashed dashed solid;border-color:transparent transparent #fff}.layui-nav-child{display:none;position:absolute;left:0;top:65px;min-width:100%;line-height:36px;padding:5px 0;box-shadow:0 2px 4px rgba(0,0,0,.12);border:1px solid #d2d2d2;background-color:#fff;z-index:100;border-radius:2px;white-space:nowrap}.layui-nav .layui-nav-child a{color:#333}.layui-nav .layui-nav-child a:hover{background-color:#f2f2f2;color:#000}.layui-nav-child dd{position:relative}.layui-nav .layui-nav-child dd.layui-this a,.layui-nav-child dd.layui-this{background-color:#5FB878;color:#fff}.layui-nav-child dd.layui-this:after{display:none}.layui-nav-tree{width:200px;padding:0}.layui-nav-tree .layui-nav-item{display:block;width:100%;line-height:45px}.layui-nav-tree .layui-nav-item a{position:relative;height:45px;line-height:45px;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-nav-tree .layui-nav-item a:hover{background-color:#4E5465}.layui-nav-tree .layui-nav-bar{width:5px;height:0;background-color:#009688}.layui-nav-tree .layui-nav-child dd.layui-this,.layui-nav-tree .layui-nav-child dd.layui-this a,.layui-nav-tree .layui-this,.layui-nav-tree .layui-this>a,.layui-nav-tree .layui-this>a:hover{background-color:#009688;color:#fff}.layui-nav-tree .layui-this:after{display:none}.layui-nav-itemed>a,.layui-nav-tree .layui-nav-title a,.layui-nav-tree .layui-nav-title a:hover{color:#fff!important}.layui-nav-tree .layui-nav-child{position:relative;z-index:0;top:0;border:none;box-shadow:none}.layui-nav-tree .layui-nav-child a{height:40px;line-height:40px;color:#fff;color:rgba(255,255,255,.7)}.layui-nav-tree .layui-nav-child,.layui-nav-tree .layui-nav-child a:hover{background:0 0;color:#fff}.layui-nav-tree .layui-nav-more{right:10px}.layui-nav-itemed>.layui-nav-child{display:block;padding:0;background-color:rgba(0,0,0,.3)!important}.layui-nav-itemed>.layui-nav-child>.layui-this>.layui-nav-child{display:block}.layui-nav-side{position:fixed;top:0;bottom:0;left:0;overflow-x:hidden;z-index:999}.layui-bg-blue .layui-nav-bar,.layui-bg-blue .layui-nav-itemed:after,.layui-bg-blue .layui-this:after{background-color:#93D1FF}.layui-bg-blue .layui-nav-child dd.layui-this{background-color:#1E9FFF}.layui-bg-blue .layui-nav-itemed>a,.layui-nav-tree.layui-bg-blue .layui-nav-title a,.layui-nav-tree.layui-bg-blue .layui-nav-title a:hover{background-color:#007DDB!important}.layui-breadcrumb{visibility:hidden;font-size:0}.layui-breadcrumb>*{font-size:14px}.layui-breadcrumb a{color:#999!important}.layui-breadcrumb a:hover{color:#5FB878!important}.layui-breadcrumb a cite{color:#666;font-style:normal}.layui-breadcrumb span[lay-separator]{margin:0 10px;color:#999}.layui-tab{margin:10px 0;text-align:left!important}.layui-tab[overflow]>.layui-tab-title{overflow:hidden}.layui-tab-title{position:relative;left:0;height:40px;white-space:nowrap;font-size:0;border-bottom-width:1px;border-bottom-style:solid;transition:all .2s;-webkit-transition:all .2s}.layui-tab-title li{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;font-size:14px;transition:all .2s;-webkit-transition:all .2s;position:relative;line-height:40px;min-width:65px;padding:0 15px;text-align:center;cursor:pointer}.layui-tab-title li a{display:block}.layui-tab-title .layui-this{color:#000}.layui-tab-title .layui-this:after{position:absolute;left:0;top:0;content:'';width:100%;height:41px;border-width:1px;border-style:solid;border-bottom-color:#fff;border-radius:2px 2px 0 0;box-sizing:border-box;pointer-events:none}.layui-tab-bar{position:absolute;right:0;top:0;z-index:10;width:30px;height:39px;line-height:39px;border-width:1px;border-style:solid;border-radius:2px;text-align:center;background-color:#fff;cursor:pointer}.layui-tab-bar .layui-icon{position:relative;display:inline-block;top:3px;transition:all .3s;-webkit-transition:all .3s}.layui-tab-item{display:none}.layui-tab-more{padding-right:30px;height:auto!important;white-space:normal!important}.layui-tab-more li.layui-this:after{border-bottom-color:#e2e2e2;border-radius:2px}.layui-tab-more .layui-tab-bar .layui-icon{top:-2px;top:3px\\9;-webkit-transform:rotate(180deg);transform:rotate(180deg)}:root .layui-tab-more .layui-tab-bar .layui-icon{top:-2px\\0/IE9}.layui-tab-content{padding:10px}.layui-tab-title li .layui-tab-close{position:relative;display:inline-block;width:18px;height:18px;line-height:20px;margin-left:8px;top:1px;text-align:center;font-size:14px;color:#c2c2c2;transition:all .2s;-webkit-transition:all .2s}.layui-tab-title li .layui-tab-close:hover{border-radius:2px;background-color:#FF5722;color:#fff}.layui-tab-brief>.layui-tab-title .layui-this{color:#009688}.layui-tab-brief>.layui-tab-more li.layui-this:after,.layui-tab-brief>.layui-tab-title .layui-this:after{border:none;border-radius:0;border-bottom:2px solid #5FB878}.layui-tab-brief[overflow]>.layui-tab-title .layui-this:after{top:-1px}.layui-tab-card{border-width:1px;border-style:solid;border-radius:2px;box-shadow:0 2px 5px 0 rgba(0,0,0,.1)}.layui-tab-card>.layui-tab-title{background-color:#f2f2f2}.layui-tab-card>.layui-tab-title li{margin-right:-1px;margin-left:-1px}.layui-tab-card>.layui-tab-title .layui-this{background-color:#fff}.layui-tab-card>.layui-tab-title .layui-this:after{border-top:none;border-width:1px;border-bottom-color:#fff}.layui-tab-card>.layui-tab-title .layui-tab-bar{height:40px;line-height:40px;border-radius:0;border-top:none;border-right:none}.layui-tab-card>.layui-tab-more .layui-this{background:0 0;color:#5FB878}.layui-tab-card>.layui-tab-more .layui-this:after{border:none}.layui-timeline{padding-left:5px}.layui-timeline-item{position:relative;padding-bottom:20px}.layui-timeline-axis{position:absolute;left:-5px;top:0;z-index:10;width:20px;height:20px;line-height:20px;background-color:#fff;color:#5FB878;border-radius:50%;text-align:center;cursor:pointer}.layui-timeline-axis:hover{color:#FF5722}.layui-timeline-item:before{content:'';position:absolute;left:5px;top:0;z-index:0;width:1px;height:100%}.layui-timeline-item:last-child:before{display:none}.layui-timeline-item:first-child:before{display:block}.layui-timeline-content{padding-left:25px}.layui-timeline-title{position:relative;margin-bottom:10px}.layui-badge,.layui-badge-dot,.layui-badge-rim{position:relative;display:inline-block;padding:0 6px;font-size:12px;text-align:center;background-color:#FF5722;color:#fff;border-radius:2px}.layui-badge{height:18px;line-height:18px}.layui-badge-dot{width:8px;height:8px;padding:0;border-radius:50%}.layui-badge-rim{height:18px;line-height:18px;border-width:1px;border-style:solid;background-color:#fff;color:#666}.layui-btn .layui-badge,.layui-btn .layui-badge-dot{margin-left:5px}.layui-nav .layui-badge,.layui-nav .layui-badge-dot{position:absolute;top:50%;margin:-8px 6px 0}.layui-tab-title .layui-badge,.layui-tab-title .layui-badge-dot{left:5px;top:-2px}.layui-carousel{position:relative;left:0;top:0;background-color:#f8f8f8}.layui-carousel>[carousel-item]{position:relative;width:100%;height:100%;overflow:hidden}.layui-carousel>[carousel-item]:before{position:absolute;content:'\\e63d';left:50%;top:50%;width:100px;line-height:20px;margin:-10px 0 0 -50px;text-align:center;color:#c2c2c2;font-family:layui-icon!important;font-size:30px;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.layui-carousel>[carousel-item]>*{display:none;position:absolute;left:0;top:0;width:100%;height:100%;background-color:#f8f8f8;transition-duration:.3s;-webkit-transition-duration:.3s}.layui-carousel-updown>*{-webkit-transition:.3s ease-in-out up;transition:.3s ease-in-out up}.layui-carousel-arrow{display:none\\9;opacity:0;position:absolute;left:10px;top:50%;margin-top:-18px;width:36px;height:36px;line-height:36px;text-align:center;font-size:20px;border:0;border-radius:50%;background-color:rgba(0,0,0,.2);color:#fff;-webkit-transition-duration:.3s;transition-duration:.3s;cursor:pointer}.layui-carousel-arrow[lay-type=add]{left:auto!important;right:10px}.layui-carousel:hover .layui-carousel-arrow[lay-type=add],.layui-carousel[lay-arrow=always] .layui-carousel-arrow[lay-type=add]{right:20px}.layui-carousel[lay-arrow=always] .layui-carousel-arrow{opacity:1;left:20px}.layui-carousel[lay-arrow=none] .layui-carousel-arrow{display:none}.layui-carousel-arrow:hover,.layui-carousel-ind ul:hover{background-color:rgba(0,0,0,.35)}.layui-carousel:hover .layui-carousel-arrow{display:block\\9;opacity:1;left:20px}.layui-carousel-ind{position:relative;top:-35px;width:100%;line-height:0!important;text-align:center;font-size:0}.layui-carousel[lay-indicator=outside]{margin-bottom:30px}.layui-carousel[lay-indicator=outside] .layui-carousel-ind{top:10px}.layui-carousel[lay-indicator=outside] .layui-carousel-ind ul{background-color:rgba(0,0,0,.5)}.layui-carousel[lay-indicator=none] .layui-carousel-ind{display:none}.layui-carousel-ind ul{display:inline-block;padding:5px;background-color:rgba(0,0,0,.2);border-radius:10px;-webkit-transition-duration:.3s;transition-duration:.3s}.layui-carousel-ind li{display:inline-block;width:10px;height:10px;margin:0 3px;font-size:14px;background-color:#e2e2e2;background-color:rgba(255,255,255,.5);border-radius:50%;cursor:pointer;-webkit-transition-duration:.3s;transition-duration:.3s}.layui-carousel-ind li:hover{background-color:rgba(255,255,255,.7)}.layui-carousel-ind li.layui-this{background-color:#fff}.layui-carousel>[carousel-item]>.layui-carousel-next,.layui-carousel>[carousel-item]>.layui-carousel-prev,.layui-carousel>[carousel-item]>.layui-this{display:block}.layui-carousel>[carousel-item]>.layui-this{left:0}.layui-carousel>[carousel-item]>.layui-carousel-prev{left:-100%}.layui-carousel>[carousel-item]>.layui-carousel-next{left:100%}.layui-carousel>[carousel-item]>.layui-carousel-next.layui-carousel-left,.layui-carousel>[carousel-item]>.layui-carousel-prev.layui-carousel-right{left:0}.layui-carousel>[carousel-item]>.layui-this.layui-carousel-left{left:-100%}.layui-carousel>[carousel-item]>.layui-this.layui-carousel-right{left:100%}.layui-carousel[lay-anim=updown] .layui-carousel-arrow{left:50%!important;top:20px;margin:0 0 0 -18px}.layui-carousel[lay-anim=updown]>[carousel-item]>*,.layui-carousel[lay-anim=fade]>[carousel-item]>*{left:0!important}.layui-carousel[lay-anim=updown] .layui-carousel-arrow[lay-type=add]{top:auto!important;bottom:20px}.layui-carousel[lay-anim=updown] .layui-carousel-ind{position:absolute;top:50%;right:20px;width:auto;height:auto}.layui-carousel[lay-anim=updown] .layui-carousel-ind ul{padding:3px 5px}.layui-carousel[lay-anim=updown] .layui-carousel-ind li{display:block;margin:6px 0}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-this{top:0}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-carousel-prev{top:-100%}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-carousel-next{top:100%}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-carousel-next.layui-carousel-left,.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-carousel-prev.layui-carousel-right{top:0}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-this.layui-carousel-left{top:-100%}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-this.layui-carousel-right{top:100%}.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-carousel-next,.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-carousel-prev{opacity:0}.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-carousel-next.layui-carousel-left,.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-carousel-prev.layui-carousel-right{opacity:1}.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-this.layui-carousel-left,.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-this.layui-carousel-right{opacity:0}.layui-fixbar{position:fixed;right:15px;bottom:15px;z-index:9999}.layui-fixbar li{width:50px;height:50px;line-height:50px;margin-bottom:1px;text-align:center;cursor:pointer;font-size:30px;background-color:#9F9F9F;color:#fff;border-radius:2px;opacity:.95}.layui-fixbar li:hover{opacity:.85}.layui-fixbar li:active{opacity:1}.layui-fixbar .layui-fixbar-top{display:none;font-size:40px}body .layui-util-face{border:none;background:0 0}body .layui-util-face .layui-layer-content{padding:0;background-color:#fff;color:#666;box-shadow:none}.layui-util-face .layui-layer-TipsG{display:none}.layui-util-face ul{position:relative;width:372px;padding:10px;border:1px solid #D9D9D9;background-color:#fff;box-shadow:0 0 20px rgba(0,0,0,.2)}.layui-util-face ul li{cursor:pointer;float:left;border:1px solid #e8e8e8;height:22px;width:26px;overflow:hidden;margin:-1px 0 0 -1px;padding:4px 2px;text-align:center}.layui-util-face ul li:hover{position:relative;z-index:2;border:1px solid #eb7350;background:#fff9ec}.layui-anim{-webkit-animation-duration:.3s;animation-duration:.3s;-webkit-animation-fill-mode:both;animation-fill-mode:both}.layui-anim.layui-icon{display:inline-block}.layui-anim-loop{-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}.layui-trans,.layui-trans a{transition:all .3s;-webkit-transition:all .3s}@-webkit-keyframes layui-rotate{from{-webkit-transform:rotate(0)}to{-webkit-transform:rotate(360deg)}}@keyframes layui-rotate{from{transform:rotate(0)}to{transform:rotate(360deg)}}.layui-anim-rotate{-webkit-animation-name:layui-rotate;animation-name:layui-rotate;-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-timing-function:linear;animation-timing-function:linear}@-webkit-keyframes layui-up{from{-webkit-transform:translate3d(0,100%,0);opacity:.3}to{-webkit-transform:translate3d(0,0,0);opacity:1}}@keyframes layui-up{from{transform:translate3d(0,100%,0);opacity:.3}to{transform:translate3d(0,0,0);opacity:1}}.layui-anim-up{-webkit-animation-name:layui-up;animation-name:layui-up}@-webkit-keyframes layui-upbit{from{-webkit-transform:translate3d(0,30px,0);opacity:.3}to{-webkit-transform:translate3d(0,0,0);opacity:1}}@keyframes layui-upbit{from{transform:translate3d(0,30px,0);opacity:.3}to{transform:translate3d(0,0,0);opacity:1}}.layui-anim-upbit{-webkit-animation-name:layui-upbit;animation-name:layui-upbit}@-webkit-keyframes layui-scale{0%{opacity:.3;-webkit-transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1)}}@keyframes layui-scale{0%{opacity:.3;-ms-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-ms-transform:scale(1);transform:scale(1)}}.layui-anim-scale{-webkit-animation-name:layui-scale;animation-name:layui-scale}@-webkit-keyframes layui-scale-spring{0%{opacity:.5;-webkit-transform:scale(.5)}80%{opacity:.8;-webkit-transform:scale(1.1)}100%{opacity:1;-webkit-transform:scale(1)}}@keyframes layui-scale-spring{0%{opacity:.5;transform:scale(.5)}80%{opacity:.8;transform:scale(1.1)}100%{opacity:1;transform:scale(1)}}.layui-anim-scaleSpring{-webkit-animation-name:layui-scale-spring;animation-name:layui-scale-spring}@-webkit-keyframes layui-fadein{0%{opacity:0}100%{opacity:1}}@keyframes layui-fadein{0%{opacity:0}100%{opacity:1}}.layui-anim-fadein{-webkit-animation-name:layui-fadein;animation-name:layui-fadein}@-webkit-keyframes layui-fadeout{0%{opacity:1}100%{opacity:0}}@keyframes layui-fadeout{0%{opacity:1}100%{opacity:0}}.layui-anim-fadeout{-webkit-animation-name:layui-fadeout;animation-name:layui-fadeout}"
  },
  {
    "path": "open-layui-web/src/main/view/static/layui/css/layui.mobile.css",
    "content": "/** layui-v2.3.0-rc1 MIT License By https://www.layui.com */\n blockquote,body,button,dd,div,dl,dt,form,h1,h2,h3,h4,h5,h6,input,legend,li,ol,p,td,textarea,th,ul{margin:0;padding:0;-webkit-tap-highlight-color:rgba(0,0,0,0)}html{font:12px 'Helvetica Neue','PingFang SC',STHeitiSC-Light,Helvetica,Arial,sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}a,button,input{-webkit-tap-highlight-color:rgba(255,0,0,0)}a{text-decoration:none;background:0 0}a:active,a:hover{outline:0}table{border-collapse:collapse;border-spacing:0}li{list-style:none}b,strong{font-weight:700}h1,h2,h3,h4,h5,h6{font-weight:500}address,cite,dfn,em,var{font-style:normal}dfn{font-style:italic}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}img{border:0;vertical-align:bottom}.layui-inline,input,label{vertical-align:middle}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0;outline:0}button,select{text-transform:none}select{-webkit-appearance:none;border:none}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}@font-face{font-family:layui-icon;src:url(../font/iconfont.eot?v=1.0.7);src:url(../font/iconfont.eot?v=1.0.7#iefix) format('embedded-opentype'),url(../font/iconfont.woff?v=1.0.7) format('woff'),url(../font/iconfont.ttf?v=1.0.7) format('truetype'),url(../font/iconfont.svg?v=1.0.7#iconfont) format('svg')}.layui-icon{font-family:layui-icon!important;font-size:16px;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.layui-box,.layui-box *{-webkit-box-sizing:content-box!important;-moz-box-sizing:content-box!important;box-sizing:content-box!important}.layui-border-box,.layui-border-box *{-webkit-box-sizing:border-box!important;-moz-box-sizing:border-box!important;box-sizing:border-box!important}.layui-inline{position:relative;display:inline-block;*display:inline;*zoom:1}.layui-edge,.layui-upload-iframe{position:absolute;width:0;height:0}.layui-edge{border-style:dashed;border-color:transparent;overflow:hidden}.layui-elip{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-unselect{-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.layui-disabled,.layui-disabled:active{background-color:#d2d2d2!important;color:#fff!important;cursor:not-allowed!important}.layui-circle{border-radius:100%}.layui-show{display:block!important}.layui-hide{display:none!important}.layui-upload-iframe{border:0;visibility:hidden}.layui-upload-enter{border:1px solid #009E94;background-color:#009E94;color:#fff;-webkit-transform:scale(1.1);transform:scale(1.1)}@-webkit-keyframes layui-m-anim-scale{0%{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}@keyframes layui-m-anim-scale{0%{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}.layui-m-anim-scale{animation-name:layui-m-anim-scale;-webkit-animation-name:layui-m-anim-scale}@-webkit-keyframes layui-m-anim-up{0%{opacity:0;-webkit-transform:translateY(800px);transform:translateY(800px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes layui-m-anim-up{0%{opacity:0;-webkit-transform:translateY(800px);transform:translateY(800px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}.layui-m-anim-up{-webkit-animation-name:layui-m-anim-up;animation-name:layui-m-anim-up}@-webkit-keyframes layui-m-anim-left{0%{-webkit-transform:translateX(100%);transform:translateX(100%)}100%{-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes layui-m-anim-left{0%{-webkit-transform:translateX(100%);transform:translateX(100%)}100%{-webkit-transform:translateX(0);transform:translateX(0)}}.layui-m-anim-left{-webkit-animation-name:layui-m-anim-left;animation-name:layui-m-anim-left}@-webkit-keyframes layui-m-anim-right{0%{-webkit-transform:translateX(-100%);transform:translateX(-100%)}100%{-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes layui-m-anim-right{0%{-webkit-transform:translateX(-100%);transform:translateX(-100%)}100%{-webkit-transform:translateX(0);transform:translateX(0)}}.layui-m-anim-right{-webkit-animation-name:layui-m-anim-right;animation-name:layui-m-anim-right}@-webkit-keyframes layui-m-anim-lout{0%{-webkit-transform:translateX(0);transform:translateX(0)}100%{-webkit-transform:translateX(-100%);transform:translateX(-100%)}}@keyframes layui-m-anim-lout{0%{-webkit-transform:translateX(0);transform:translateX(0)}100%{-webkit-transform:translateX(-100%);transform:translateX(-100%)}}.layui-m-anim-lout{-webkit-animation-name:layui-m-anim-lout;animation-name:layui-m-anim-lout}@-webkit-keyframes layui-m-anim-rout{0%{-webkit-transform:translateX(0);transform:translateX(0)}100%{-webkit-transform:translateX(100%);transform:translateX(100%)}}@keyframes layui-m-anim-rout{0%{-webkit-transform:translateX(0);transform:translateX(0)}100%{-webkit-transform:translateX(100%);transform:translateX(100%)}}.layui-m-anim-rout{-webkit-animation-name:layui-m-anim-rout;animation-name:layui-m-anim-rout}.layui-m-layer{position:relative;z-index:19891014}.layui-m-layer *{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.layui-m-layermain,.layui-m-layershade{position:fixed;left:0;top:0;width:100%;height:100%}.layui-m-layershade{background-color:rgba(0,0,0,.7);pointer-events:auto}.layui-m-layermain{display:table;font-family:Helvetica,arial,sans-serif;pointer-events:none}.layui-m-layermain .layui-m-layersection{display:table-cell;vertical-align:middle;text-align:center}.layui-m-layerchild{position:relative;display:inline-block;text-align:left;background-color:#fff;font-size:14px;border-radius:5px;box-shadow:0 0 8px rgba(0,0,0,.1);pointer-events:auto;-webkit-overflow-scrolling:touch;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:.2s;animation-duration:.2s}.layui-m-layer0 .layui-m-layerchild{width:90%;max-width:640px}.layui-m-layer1 .layui-m-layerchild{border:none;border-radius:0}.layui-m-layer2 .layui-m-layerchild{width:auto;max-width:260px;min-width:40px;border:none;background:0 0;box-shadow:none;color:#fff}.layui-m-layerchild h3{padding:0 10px;height:60px;line-height:60px;font-size:16px;font-weight:400;border-radius:5px 5px 0 0;text-align:center}.layui-m-layerbtn span,.layui-m-layerchild h3{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-m-layercont{padding:50px 30px;line-height:22px;text-align:center}.layui-m-layer1 .layui-m-layercont{padding:0;text-align:left}.layui-m-layer2 .layui-m-layercont{text-align:center;padding:0;line-height:0}.layui-m-layer2 .layui-m-layercont i{width:25px;height:25px;margin-left:8px;display:inline-block;background-color:#fff;border-radius:100%;-webkit-animation:layui-m-anim-loading 1.4s infinite ease-in-out;animation:layui-m-anim-loading 1.4s infinite ease-in-out;-webkit-animation-fill-mode:both;animation-fill-mode:both}.layui-m-layerbtn,.layui-m-layerbtn span{position:relative;text-align:center;border-radius:0 0 5px 5px}.layui-m-layer2 .layui-m-layercont p{margin-top:20px}@-webkit-keyframes layui-m-anim-loading{0%,100%,80%{transform:scale(0);-webkit-transform:scale(0)}40%{transform:scale(1);-webkit-transform:scale(1)}}@keyframes layui-m-anim-loading{0%,100%,80%{transform:scale(0);-webkit-transform:scale(0)}40%{transform:scale(1);-webkit-transform:scale(1)}}.layui-m-layer2 .layui-m-layercont i:first-child{margin-left:0;-webkit-animation-delay:-.32s;animation-delay:-.32s}.layui-m-layer2 .layui-m-layercont i.layui-m-layerload{-webkit-animation-delay:-.16s;animation-delay:-.16s}.layui-m-layer2 .layui-m-layercont>div{line-height:22px;padding-top:7px;margin-bottom:20px;font-size:14px}.layui-m-layerbtn{display:box;display:-moz-box;display:-webkit-box;width:100%;height:50px;line-height:50px;font-size:0;border-top:1px solid #D0D0D0;background-color:#F2F2F2}.layui-m-layerbtn span{display:block;-moz-box-flex:1;box-flex:1;-webkit-box-flex:1;font-size:14px;cursor:pointer}.layui-m-layerbtn span[yes]{color:#40AFFE}.layui-m-layerbtn span[no]{border-right:1px solid #D0D0D0;border-radius:0 0 0 5px}.layui-m-layerbtn span:active{background-color:#F6F6F6}.layui-m-layerend{position:absolute;right:7px;top:10px;width:30px;height:30px;border:0;font-weight:400;background:0 0;cursor:pointer;-webkit-appearance:none;font-size:30px}.layui-m-layerend::after,.layui-m-layerend::before{position:absolute;left:5px;top:15px;content:'';width:18px;height:1px;background-color:#999;transform:rotate(45deg);-webkit-transform:rotate(45deg);border-radius:3px}.layui-m-layerend::after{transform:rotate(-45deg);-webkit-transform:rotate(-45deg)}body .layui-m-layer .layui-m-layer-footer{position:fixed;width:95%;max-width:100%;margin:0 auto;left:0;right:0;bottom:10px;background:0 0}.layui-m-layer-footer .layui-m-layercont{padding:20px;border-radius:5px 5px 0 0;background-color:rgba(255,255,255,.8)}.layui-m-layer-footer .layui-m-layerbtn{display:block;height:auto;background:0 0;border-top:none}.layui-m-layer-footer .layui-m-layerbtn span{background-color:rgba(255,255,255,.8)}.layui-m-layer-footer .layui-m-layerbtn span[no]{color:#FD482C;border-top:1px solid #c2c2c2;border-radius:0 0 5px 5px}.layui-m-layer-footer .layui-m-layerbtn span[yes]{margin-top:10px;border-radius:5px}body .layui-m-layer .layui-m-layer-msg{width:auto;max-width:90%;margin:0 auto;bottom:-150px;background-color:rgba(0,0,0,.7);color:#fff}.layui-m-layer-msg .layui-m-layercont{padding:10px 20px}"
  },
  {
    "path": "open-layui-web/src/main/view/static/layui/css/modules/code.css",
    "content": "/** layui-v2.3.0-rc1 MIT License By https://www.layui.com */\n html #layuicss-skincodecss{display:none;position:absolute;width:1989px}.layui-code-h3,.layui-code-view{position:relative;font-size:12px}.layui-code-view{display:block;margin:10px 0;padding:0;border:1px solid #e2e2e2;border-left-width:6px;background-color:#F2F2F2;color:#333;font-family:Courier New}.layui-code-h3{padding:0 10px;height:32px;line-height:32px;border-bottom:1px solid #e2e2e2}.layui-code-h3 a{position:absolute;right:10px;top:0;color:#999}.layui-code-view .layui-code-ol{position:relative;overflow:auto}.layui-code-view .layui-code-ol li{position:relative;margin-left:45px;line-height:20px;padding:0 5px;border-left:1px solid #e2e2e2;list-style-type:decimal-leading-zero;*list-style-type:decimal;background-color:#fff}.layui-code-view pre{margin:0}.layui-code-notepad{border:1px solid #0C0C0C;border-left-color:#3F3F3F;background-color:#0C0C0C;color:#C2BE9E}.layui-code-notepad .layui-code-h3{border-bottom:none}.layui-code-notepad .layui-code-ol li{background-color:#3F3F3F;border-left:none}"
  },
  {
    "path": "open-layui-web/src/main/view/static/layui/css/modules/laydate/default/laydate.css",
    "content": "/** layui-v2.3.0-rc1 MIT License By https://www.layui.com */\n .laydate-set-ym,.layui-laydate,.layui-laydate *,.layui-laydate-list{box-sizing:border-box}html #layuicss-laydate{display:none;position:absolute;width:1989px}.layui-laydate *{margin:0;padding:0}.layui-laydate{position:absolute;z-index:66666666;margin:5px 0;border-radius:2px;font-size:14px;-webkit-animation-duration:.3s;animation-duration:.3s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-name:laydate-upbit;animation-name:laydate-upbit}.layui-laydate-main{width:272px}.layui-laydate-content td,.layui-laydate-header *,.layui-laydate-list li{transition-duration:.3s;-webkit-transition-duration:.3s}@-webkit-keyframes laydate-upbit{from{-webkit-transform:translate3d(0,20px,0);opacity:.3}to{-webkit-transform:translate3d(0,0,0);opacity:1}}@keyframes laydate-upbit{from{transform:translate3d(0,20px,0);opacity:.3}to{transform:translate3d(0,0,0);opacity:1}}.layui-laydate-static{position:relative;z-index:0;display:inline-block;margin:0;-webkit-animation:none;animation:none}.laydate-ym-show .laydate-next-m,.laydate-ym-show .laydate-prev-m{display:none!important}.laydate-ym-show .laydate-next-y,.laydate-ym-show .laydate-prev-y{display:inline-block!important}.laydate-time-show .laydate-set-ym span[lay-type=month],.laydate-time-show .laydate-set-ym span[lay-type=year],.laydate-time-show .layui-laydate-header .layui-icon,.laydate-ym-show .laydate-set-ym span[lay-type=month]{display:none!important}.layui-laydate-header{position:relative;line-height:30px;padding:10px 70px 5px}.laydate-set-ym span,.layui-laydate-header i{padding:0 5px;cursor:pointer}.layui-laydate-header *{display:inline-block;vertical-align:bottom}.layui-laydate-header i{position:absolute;top:10px;color:#999;font-size:18px}.layui-laydate-header i.laydate-prev-y{left:15px}.layui-laydate-header i.laydate-prev-m{left:45px}.layui-laydate-header i.laydate-next-y{right:15px}.layui-laydate-header i.laydate-next-m{right:45px}.laydate-set-ym{width:100%;text-align:center;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.laydate-time-text{cursor:default!important}.layui-laydate-content{position:relative;padding:10px;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.layui-laydate-content table{border-collapse:collapse;border-spacing:0}.layui-laydate-content td,.layui-laydate-content th{width:36px;height:30px;padding:5px;text-align:center}.layui-laydate-content td{position:relative;cursor:pointer}.laydate-day-mark{position:absolute;left:0;top:0;width:100%;height:100%;line-height:30px;font-size:12px;overflow:hidden}.laydate-day-mark::after{position:absolute;content:'';right:2px;top:2px;width:5px;height:5px;border-radius:50%}.layui-laydate-footer{position:relative;height:46px;line-height:26px;padding:10px 20px}.layui-laydate-footer span{margin-right:15px;display:inline-block;cursor:pointer;font-size:12px}.layui-laydate-footer span:hover{color:#5FB878}.laydate-footer-btns{position:absolute;right:10px;top:10px}.laydate-footer-btns span{height:26px;line-height:26px;margin:0 0 0 -1px;padding:0 10px;border:1px solid #C9C9C9;background-color:#fff;white-space:nowrap;vertical-align:top;border-radius:2px}.layui-laydate-list>li,.layui-laydate-range .layui-laydate-main{display:inline-block;vertical-align:middle}.layui-laydate-list{position:absolute;left:0;top:0;width:100%;height:100%;padding:10px;background-color:#fff}.layui-laydate-list>li{position:relative;width:33.3%;height:36px;line-height:36px;margin:3px 0;text-align:center;cursor:pointer}.laydate-month-list>li{width:25%;margin:17px 0}.laydate-time-list>li{height:100%;margin:0;line-height:normal;cursor:default}.laydate-time-list p{position:relative;top:-4px;line-height:29px}.laydate-time-list ol{height:181px;overflow:hidden}.laydate-time-list>li:hover ol{overflow-y:auto}.laydate-time-list ol li{width:130%;padding-left:33px;line-height:30px;text-align:left;cursor:pointer}.layui-laydate-hint{position:absolute;top:115px;left:50%;width:250px;margin-left:-125px;line-height:20px;padding:15px;text-align:center;font-size:12px}.layui-laydate-range{width:546px}.layui-laydate-range .laydate-main-list-0 .laydate-next-m,.layui-laydate-range .laydate-main-list-0 .laydate-next-y,.layui-laydate-range .laydate-main-list-1 .laydate-prev-m,.layui-laydate-range .laydate-main-list-1 .laydate-prev-y{display:none}.layui-laydate-range .laydate-main-list-1 .layui-laydate-content{border-left:1px solid #e2e2e2}.layui-laydate,.layui-laydate-hint{border:1px solid #d2d2d2;box-shadow:0 2px 4px rgba(0,0,0,.12);background-color:#fff;color:#666}.layui-laydate-header{border-bottom:1px solid #e2e2e2}.layui-laydate-header i:hover,.layui-laydate-header span:hover{color:#5FB878}.layui-laydate-content{border-top:none 0;border-bottom:none 0}.layui-laydate-content th{font-weight:400;color:#333}.layui-laydate-content td{color:#666}.layui-laydate-content td.laydate-selected{background-color:#00F7DE}.laydate-selected:hover{background-color:#00F7DE!important}.layui-laydate-content td:hover,.layui-laydate-list li:hover{background-color:#eaeaea;color:#333}.laydate-time-list li ol{margin:0;padding:0;border:1px solid #e2e2e2;border-left-width:0}.laydate-time-list li:first-child ol{border-left-width:1px}.laydate-time-list>li:hover{background:0 0}.layui-laydate-content .laydate-day-next,.layui-laydate-content .laydate-day-prev{color:#d2d2d2}.laydate-selected.laydate-day-next,.laydate-selected.laydate-day-prev{background-color:#f8f8f8!important}.layui-laydate-footer{border-top:1px solid #e2e2e2}.layui-laydate-hint{color:#FF5722}.laydate-day-mark::after{background-color:#5FB878}.layui-laydate-content td.layui-this .laydate-day-mark::after{display:none}.layui-laydate-footer span[lay-type=date]{color:#5FB878}.layui-laydate .layui-this{background-color:#009688!important;color:#fff!important}.layui-laydate .laydate-disabled,.layui-laydate .laydate-disabled:hover{background:0 0!important;color:#d2d2d2!important;cursor:not-allowed!important;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.laydate-theme-molv{border:none}.laydate-theme-molv.layui-laydate-range{width:548px}.laydate-theme-molv .layui-laydate-main{width:274px}.laydate-theme-molv .layui-laydate-header{border:none;background-color:#009688}.laydate-theme-molv .layui-laydate-header i,.laydate-theme-molv .layui-laydate-header span{color:#f6f6f6}.laydate-theme-molv .layui-laydate-header i:hover,.laydate-theme-molv .layui-laydate-header span:hover{color:#fff}.laydate-theme-molv .layui-laydate-content{border:1px solid #e2e2e2;border-top:none;border-bottom:none}.laydate-theme-molv .laydate-main-list-1 .layui-laydate-content{border-left:none}.laydate-theme-grid .laydate-month-list>li,.laydate-theme-grid .laydate-year-list>li,.laydate-theme-grid .layui-laydate-content td,.laydate-theme-grid .layui-laydate-content thead,.laydate-theme-molv .layui-laydate-footer{border:1px solid #e2e2e2}.laydate-theme-grid .laydate-selected,.laydate-theme-grid .laydate-selected:hover{background-color:#f2f2f2!important;color:#009688!important}.laydate-theme-grid .laydate-selected.laydate-day-next,.laydate-theme-grid .laydate-selected.laydate-day-prev{color:#d2d2d2!important}.laydate-theme-grid .laydate-month-list,.laydate-theme-grid .laydate-year-list{margin:1px 0 0 1px}.laydate-theme-grid .laydate-month-list>li,.laydate-theme-grid .laydate-year-list>li{margin:0 -1px -1px 0}.laydate-theme-grid .laydate-year-list>li{height:43px;line-height:43px}.laydate-theme-grid .laydate-month-list>li{height:71px;line-height:71px}"
  },
  {
    "path": "open-layui-web/src/main/view/static/layui/css/modules/layer/default/layer.css",
    "content": "/** layui-v2.3.0-rc1 MIT License By https://www.layui.com */\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 #layuicss-layer{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;border-radius:2px;box-shadow:1px 1px 50px rgba(0,0,0,.3)}.layui-layer-close{position:absolute}.layui-layer-content{position:relative}.layui-layer-border{border:1px solid #B2B2B2;border:1px solid rgba(0,0,0,.1);box-shadow:1px 1px 5px rgba(0,0,0,.2)}.layui-layer-load{background:url(loading-1.gif) center center no-repeat #eee}.layui-layer-ico{background:url(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}.layui-layer-move{display:none;position:fixed;*position:absolute;left:0;top:0;width:100%;height:100%;cursor:move;opacity:0;filter:alpha(opacity=0);background-color:#fff;z-index:2147483647}.layui-layer-resize{position:absolute;width:15px;height:15px;right:0;bottom:0;cursor:se-resize}.layer-anim{-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:.3s;animation-duration:.3s}@-webkit-keyframes layer-bounceIn{0%{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}@keyframes layer-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-00{-webkit-animation-name:layer-bounceIn;animation-name:layer-bounceIn}@-webkit-keyframes layer-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 layer-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:layer-zoomInDown;animation-name:layer-zoomInDown}@-webkit-keyframes layer-fadeInUpBig{0%{opacity:0;-webkit-transform:translateY(2000px);transform:translateY(2000px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes layer-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:layer-fadeInUpBig;animation-name:layer-fadeInUpBig}@-webkit-keyframes layer-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 layer-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:layer-zoomInLeft;animation-name:layer-zoomInLeft}@-webkit-keyframes layer-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 layer-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:layer-rollIn;animation-name:layer-rollIn}@keyframes layer-fadeIn{0%{opacity:0}100%{opacity:1}}.layer-anim-05{-webkit-animation-name:layer-fadeIn;animation-name:layer-fadeIn}@-webkit-keyframes layer-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 layer-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:layer-shake;animation-name:layer-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:1px -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 15px 12px;pointer-events:auto;user-select:none;-webkit-user-select:none}.layui-layer-btn a{height:28px;line-height:28px;margin:5px 5px 0;padding:0 15px;border:1px solid #dedede;background-color:#fff;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:.8}.layui-layer-btn .layui-layer-btn0{border-color:#1E9FFF;background-color:#1E9FFF;color:#fff}.layui-layer-btn-l{text-align:left}.layui-layer-btn-c{text-align:center}.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 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(loading-0.gif) no-repeat}.layui-layer-loading .layui-layer-loading1{width:37px;height:37px;background:url(loading-1.gif) no-repeat}.layui-layer-ico16,.layui-layer-loading .layui-layer-loading2{width:32px;height:32px;background:url(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:8px 15px;font-size:12px;_float:left;border-radius:2px;box-shadow:1px 1px 3px rgba(0,0,0,.2);background-color:#000;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:#000}.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:5px;border-bottom-style:solid;border-bottom-color:#000}.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:5px 10px 10px;text-align:right;border-top:1px solid #E9E7E7}.layui-layer-lan .layui-layer-btn a{background:#fff;border-color:#E9E7E7;color:#333}.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;border-color:#009f95}.layui-layer-molv .layui-layer-btn .layui-layer-btn1{background:#92B8B1}.layui-layer-iconext{background:url(icon-ext.png) no-repeat}.layui-layer-prompt .layui-layer-input{display:block;width:230px;height:36px;margin:0 auto;line-height:30px;padding-left:10px;border:1px solid #e6e6e6;color:#333}.layui-layer-prompt textarea.layui-layer-input{width:300px;height:100px;line-height:20px;padding:6px 10px}.layui-layer-prompt .layui-layer-content{padding:20px}.layui-layer-prompt .layui-layer-btn{padding-top:0}.layui-layer-tab{box-shadow:1px 1px 50px rgba(0,0,0,.4)}.layui-layer-tab .layui-layer-title{padding-left:0;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;overflow:hidden;cursor:pointer}.layui-layer-tab .layui-layer-title span.layui-this{height:43px;border-left:1px solid #eee;border-right:1px solid #eee;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.layui-this{display:block}.layui-layer-photos{-webkit-animation-duration:.8s;animation-duration:.8s}.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}@-webkit-keyframes layer-bounceOut{100%{opacity:0;-webkit-transform:scale(.7);transform:scale(.7)}30%{-webkit-transform:scale(1.05);transform:scale(1.05)}0%{-webkit-transform:scale(1);transform:scale(1)}}@keyframes layer-bounceOut{100%{opacity:0;-webkit-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}30%{-webkit-transform:scale(1.05);-ms-transform:scale(1.05);transform:scale(1.05)}0%{-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}.layer-anim-close{-webkit-animation-name:layer-bounceOut;animation-name:layer-bounceOut;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:.2s;animation-duration:.2s}@media screen and (max-width:1100px){.layui-layer-iframe{overflow-y:auto;-webkit-overflow-scrolling:touch}}"
  },
  {
    "path": "open-layui-web/src/main/view/static/layui/lay/modules/carousel.js",
    "content": "/** layui-v2.3.0-rc1 MIT License By https://www.layui.com */\n ;layui.define(\"jquery\",function(e){\"use strict\";var i=layui.$,n=(layui.hint(),layui.device(),{config:{},set:function(e){var n=this;return n.config=i.extend({},n.config,e),n},on:function(e,i){return layui.onevent.call(this,t,e,i)}}),t=\"carousel\",a=\"layui-this\",l=\">*[carousel-item]>*\",o=\"layui-carousel-left\",r=\"layui-carousel-right\",d=\"layui-carousel-prev\",s=\"layui-carousel-next\",u=\"layui-carousel-arrow\",c=\"layui-carousel-ind\",m=function(e){var t=this;t.config=i.extend({},t.config,n.config,e),t.render()};m.prototype.config={width:\"600px\",height:\"280px\",full:!1,arrow:\"hover\",indicator:\"inside\",autoplay:!0,interval:3e3,anim:\"\",trigger:\"click\",index:0},m.prototype.render=function(){var e=this,n=e.config;n.elem=i(n.elem),n.elem[0]&&(e.elemItem=n.elem.find(l),n.index<0&&(n.index=0),n.index>=e.elemItem.length&&(n.index=e.elemItem.length-1),n.interval<800&&(n.interval=800),n.full?n.elem.css({position:\"fixed\",width:\"100%\",height:\"100%\",zIndex:9999}):n.elem.css({width:n.width,height:n.height}),n.elem.attr(\"lay-anim\",n.anim),e.elemItem.eq(n.index).addClass(a),e.elemItem.length<=1||(e.indicator(),e.arrow(),e.autoplay(),e.events()))},m.prototype.reload=function(e){var n=this;clearInterval(n.timer),n.config=i.extend({},n.config,e),n.render()},m.prototype.prevIndex=function(){var e=this,i=e.config,n=i.index-1;return n<0&&(n=e.elemItem.length-1),n},m.prototype.nextIndex=function(){var e=this,i=e.config,n=i.index+1;return n>=e.elemItem.length&&(n=0),n},m.prototype.addIndex=function(e){var i=this,n=i.config;e=e||1,n.index=n.index+e,n.index>=i.elemItem.length&&(n.index=0)},m.prototype.subIndex=function(e){var i=this,n=i.config;e=e||1,n.index=n.index-e,n.index<0&&(n.index=i.elemItem.length-1)},m.prototype.autoplay=function(){var e=this,i=e.config;i.autoplay&&(e.timer=setInterval(function(){e.slide()},i.interval))},m.prototype.arrow=function(){var e=this,n=e.config,t=i(['<button class=\"layui-icon '+u+'\" lay-type=\"sub\">'+(\"updown\"===n.anim?\"&#xe619;\":\"&#xe603;\")+\"</button>\",'<button class=\"layui-icon '+u+'\" lay-type=\"add\">'+(\"updown\"===n.anim?\"&#xe61a;\":\"&#xe602;\")+\"</button>\"].join(\"\"));n.elem.attr(\"lay-arrow\",n.arrow),n.elem.find(\".\"+u)[0]&&n.elem.find(\".\"+u).remove(),n.elem.append(t),t.on(\"click\",function(){var n=i(this),t=n.attr(\"lay-type\");e.slide(t)})},m.prototype.indicator=function(){var e=this,n=e.config,t=e.elemInd=i(['<div class=\"'+c+'\"><ul>',function(){var i=[];return layui.each(e.elemItem,function(e){i.push(\"<li\"+(n.index===e?' class=\"layui-this\"':\"\")+\"></li>\")}),i.join(\"\")}(),\"</ul></div>\"].join(\"\"));n.elem.attr(\"lay-indicator\",n.indicator),n.elem.find(\".\"+c)[0]&&n.elem.find(\".\"+c).remove(),n.elem.append(t),\"updown\"===n.anim&&t.css(\"margin-top\",-(t.height()/2)),t.find(\"li\").on(\"hover\"===n.trigger?\"mouseover\":n.trigger,function(){var t=i(this),a=t.index();a>n.index?e.slide(\"add\",a-n.index):a<n.index&&e.slide(\"sub\",n.index-a)})},m.prototype.slide=function(e,i){var n=this,l=n.elemItem,u=n.config,c=u.index,m=u.elem.attr(\"lay-filter\");n.haveSlide||(\"sub\"===e?(n.subIndex(i),l.eq(u.index).addClass(d),setTimeout(function(){l.eq(c).addClass(r),l.eq(u.index).addClass(r)},50)):(n.addIndex(i),l.eq(u.index).addClass(s),setTimeout(function(){l.eq(c).addClass(o),l.eq(u.index).addClass(o)},50)),setTimeout(function(){l.removeClass(a+\" \"+d+\" \"+s+\" \"+o+\" \"+r),l.eq(u.index).addClass(a),n.haveSlide=!1},300),n.elemInd.find(\"li\").eq(u.index).addClass(a).siblings().removeClass(a),n.haveSlide=!0,layui.event.call(this,t,\"change(\"+m+\")\",{index:u.index,prevIndex:c,item:l.eq(u.index)}))},m.prototype.events=function(){var e=this,i=e.config;i.elem.data(\"haveEvents\")||(i.elem.on(\"mouseenter\",function(){clearInterval(e.timer)}).on(\"mouseleave\",function(){e.autoplay()}),i.elem.data(\"haveEvents\",!0))},n.render=function(e){var i=new m(e);return i},e(t,n)});"
  },
  {
    "path": "open-layui-web/src/main/view/static/layui/lay/modules/code.js",
    "content": "/** layui-v2.3.0-rc1 MIT License By https://www.layui.com */\n ;layui.define(\"jquery\",function(e){\"use strict\";var a=layui.$,l=\"http://www.layui.com/doc/modules/code.html\";e(\"code\",function(e){var t=[];e=e||{},e.elem=a(e.elem||\".layui-code\"),e.about=!(\"about\"in e)||e.about,e.elem.each(function(){t.push(this)}),layui.each(t.reverse(),function(t,i){var c=a(i),o=c.html();(c.attr(\"lay-encode\")||e.encode)&&(o=o.replace(/&(?!#?[a-zA-Z0-9]+;)/g,\"&amp;\").replace(/</g,\"&lt;\").replace(/>/g,\"&gt;\").replace(/'/g,\"&#39;\").replace(/\"/g,\"&quot;\")),c.html('<ol class=\"layui-code-ol\"><li>'+o.replace(/[\\r\\t\\n]+/g,\"</li><li>\")+\"</li></ol>\"),c.find(\">.layui-code-h3\")[0]||c.prepend('<h3 class=\"layui-code-h3\">'+(c.attr(\"lay-title\")||e.title||\"code\")+(e.about?'<a href=\"'+l+'\" target=\"_blank\">layui.code</a>':\"\")+\"</h3>\");var d=c.find(\">.layui-code-ol\");c.addClass(\"layui-box layui-code-view\"),(c.attr(\"lay-skin\")||e.skin)&&c.addClass(\"layui-code-\"+(c.attr(\"lay-skin\")||e.skin)),(d.find(\"li\").length/100|0)>0&&d.css(\"margin-left\",(d.find(\"li\").length/100|0)+\"px\"),(c.attr(\"lay-height\")||e.height)&&d.css(\"max-height\",c.attr(\"lay-height\")||e.height)})})}).addcss(\"modules/code.css\",\"skincodecss\");"
  },
  {
    "path": "open-layui-web/src/main/view/static/layui/lay/modules/element.js",
    "content": "/** layui-v2.3.0-rc1 MIT License By https://www.layui.com */\n ;layui.define(\"jquery\",function(t){\"use strict\";var a=layui.$,i=(layui.hint(),layui.device()),e=\"element\",l=\"layui-this\",n=\"layui-show\",s=function(){this.config={}};s.prototype.set=function(t){var i=this;return a.extend(!0,i.config,t),i},s.prototype.on=function(t,a){return layui.onevent.call(this,e,t,a)},s.prototype.tabAdd=function(t,i){var e=\".layui-tab-title\",l=a(\".layui-tab[lay-filter=\"+t+\"]\"),n=l.children(e),s=n.children(\".layui-tab-bar\"),o=l.children(\".layui-tab-content\"),r='<li lay-id=\"'+(i.id||\"\")+'\"'+(i.attr?' lay-attr=\"'+i.attr+'\"':\"\")+\">\"+(i.title||\"unnaming\")+\"</li>\";return s[0]?s.before(r):n.append(r),o.append('<div class=\"layui-tab-item\">'+(i.content||\"\")+\"</div>\"),f.hideTabMore(!0),f.tabAuto(),this},s.prototype.tabDelete=function(t,i){var e=\".layui-tab-title\",l=a(\".layui-tab[lay-filter=\"+t+\"]\"),n=l.children(e),s=n.find('>li[lay-id=\"'+i+'\"]');return f.tabDelete(null,s),this},s.prototype.tabChange=function(t,i){var e=\".layui-tab-title\",l=a(\".layui-tab[lay-filter=\"+t+\"]\"),n=l.children(e),s=n.find('>li[lay-id=\"'+i+'\"]');return f.tabClick.call(s[0],null,null,s),this},s.prototype.tab=function(t){t=t||{},b.on(\"click\",t.headerElem,function(i){var e=a(this).index();f.tabClick.call(this,i,e,null,t)})},s.prototype.progress=function(t,i){var e=\"layui-progress\",l=a(\".\"+e+\"[lay-filter=\"+t+\"]\"),n=l.find(\".\"+e+\"-bar\"),s=n.find(\".\"+e+\"-text\");return n.css(\"width\",i),s.text(i),this};var o=\".layui-nav\",r=\"layui-nav-item\",c=\"layui-nav-bar\",u=\"layui-nav-tree\",d=\"layui-nav-child\",y=\"layui-nav-more\",h=\"layui-anim layui-anim-upbit\",f={tabClick:function(t,i,s,o){o=o||{};var r=s||a(this),i=i||r.parent().children(\"li\").index(r),c=o.headerElem?r.parent():r.parents(\".layui-tab\").eq(0),u=o.bodyElem?a(o.bodyElem):c.children(\".layui-tab-content\").children(\".layui-tab-item\"),d=r.find(\"a\"),y=c.attr(\"lay-filter\");\"javascript:;\"!==d.attr(\"href\")&&\"_blank\"===d.attr(\"target\")||(r.addClass(l).siblings().removeClass(l),u.eq(i).addClass(n).siblings().removeClass(n)),layui.event.call(this,e,\"tab(\"+y+\")\",{elem:c,index:i})},tabDelete:function(t,i){var n=i||a(this).parent(),s=n.index(),o=n.parents(\".layui-tab\").eq(0),r=o.children(\".layui-tab-content\").children(\".layui-tab-item\"),c=o.attr(\"lay-filter\");n.hasClass(l)&&(n.next()[0]?f.tabClick.call(n.next()[0],null,s+1):n.prev()[0]&&f.tabClick.call(n.prev()[0],null,s-1)),n.remove(),r.eq(s).remove(),setTimeout(function(){f.tabAuto()},50),layui.event.call(this,e,\"tabDelete(\"+c+\")\",{elem:o,index:s})},tabAuto:function(){var t=\"layui-tab-more\",e=\"layui-tab-bar\",l=\"layui-tab-close\",n=this;a(\".layui-tab\").each(function(){var s=a(this),o=s.children(\".layui-tab-title\"),r=(s.children(\".layui-tab-content\").children(\".layui-tab-item\"),'lay-stope=\"tabmore\"'),c=a('<span class=\"layui-unselect layui-tab-bar\" '+r+\"><i \"+r+' class=\"layui-icon\">&#xe61a;</i></span>');if(n===window&&8!=i.ie&&f.hideTabMore(!0),s.attr(\"lay-allowClose\")&&o.find(\"li\").each(function(){var t=a(this);if(!t.find(\".\"+l)[0]){var i=a('<i class=\"layui-icon layui-unselect '+l+'\">&#x1006;</i>');i.on(\"click\",f.tabDelete),t.append(i)}}),\"string\"!=typeof s.attr(\"lay-unauto\"))if(o.prop(\"scrollWidth\")>o.outerWidth()+1){if(o.find(\".\"+e)[0])return;o.append(c),s.attr(\"overflow\",\"\"),c.on(\"click\",function(a){o[this.title?\"removeClass\":\"addClass\"](t),this.title=this.title?\"\":\"收缩\"})}else o.find(\".\"+e).remove(),s.removeAttr(\"overflow\")})},hideTabMore:function(t){var i=a(\".layui-tab-title\");t!==!0&&\"tabmore\"===a(t.target).attr(\"lay-stope\")||(i.removeClass(\"layui-tab-more\"),i.find(\".layui-tab-bar\").attr(\"title\",\"\"))},clickThis:function(){var t=a(this),i=t.parents(o),n=i.attr(\"lay-filter\"),s=t.parent(),c=t.siblings(\".\"+d),y=\"string\"==typeof s.attr(\"lay-unselect\");\"javascript:;\"!==t.attr(\"href\")&&\"_blank\"===t.attr(\"target\")||y||c[0]||(i.find(\".\"+l).removeClass(l),s.addClass(l)),i.hasClass(u)&&(c.removeClass(h),c[0]&&(s[\"none\"===c.css(\"display\")?\"addClass\":\"removeClass\"](r+\"ed\"),\"all\"===i.attr(\"lay-shrink\")&&s.siblings().removeClass(r+\"ed\"))),layui.event.call(this,e,\"nav(\"+n+\")\",t)},collapse:function(){var t=a(this),i=t.find(\".layui-colla-icon\"),l=t.siblings(\".layui-colla-content\"),s=t.parents(\".layui-collapse\").eq(0),o=s.attr(\"lay-filter\"),r=\"none\"===l.css(\"display\");if(\"string\"==typeof s.attr(\"lay-accordion\")){var c=s.children(\".layui-colla-item\").children(\".\"+n);c.siblings(\".layui-colla-title\").children(\".layui-colla-icon\").html(\"&#xe602;\"),c.removeClass(n)}l[r?\"addClass\":\"removeClass\"](n),i.html(r?\"&#xe61a;\":\"&#xe602;\"),layui.event.call(this,e,\"collapse(\"+o+\")\",{title:t,content:l,show:r})}};s.prototype.init=function(t,e){var l=function(){return e?'[lay-filter=\"'+e+'\"]':\"\"}(),s={tab:function(){f.tabAuto.call({})},nav:function(){var t=200,e={},s={},p={},b=function(l,o,r){var c=a(this),f=c.find(\".\"+d);o.hasClass(u)?l.css({top:c.position().top,height:c.children(\"a\").outerHeight(),opacity:1}):(f.addClass(h),l.css({left:c.position().left+parseFloat(c.css(\"marginLeft\")),top:c.position().top+c.height()-l.height()}),e[r]=setTimeout(function(){l.css({width:c.width(),opacity:1})},i.ie&&i.ie<10?0:t),clearTimeout(p[r]),\"block\"===f.css(\"display\")&&clearTimeout(s[r]),s[r]=setTimeout(function(){f.addClass(n),c.find(\".\"+y).addClass(y+\"d\")},300))};a(o+l).each(function(i){var l=a(this),o=a('<span class=\"'+c+'\"></span>'),h=l.find(\".\"+r);l.find(\".\"+c)[0]||(l.append(o),h.on(\"mouseenter\",function(){b.call(this,o,l,i)}).on(\"mouseleave\",function(){l.hasClass(u)||(clearTimeout(s[i]),s[i]=setTimeout(function(){l.find(\".\"+d).removeClass(n),l.find(\".\"+y).removeClass(y+\"d\")},300))}),l.on(\"mouseleave\",function(){clearTimeout(e[i]),p[i]=setTimeout(function(){l.hasClass(u)?o.css({height:0,top:o.position().top+o.height()/2,opacity:0}):o.css({width:0,left:o.position().left+o.width()/2,opacity:0})},t)})),h.find(\"a\").each(function(){var t=a(this),i=(t.parent(),t.siblings(\".\"+d));i[0]&&!t.children(\".\"+y)[0]&&t.append('<span class=\"'+y+'\"></span>'),t.off(\"click\",f.clickThis).on(\"click\",f.clickThis)})})},breadcrumb:function(){var t=\".layui-breadcrumb\";a(t+l).each(function(){var t=a(this),i=\"lay-separator\",e=t.attr(i)||\"/\",l=t.find(\"a\");l.next(\"span[\"+i+\"]\")[0]||(l.each(function(t){t!==l.length-1&&a(this).after(\"<span \"+i+\">\"+e+\"</span>\")}),t.css(\"visibility\",\"visible\"))})},progress:function(){var t=\"layui-progress\";a(\".\"+t+l).each(function(){var i=a(this),e=i.find(\".layui-progress-bar\"),l=e.attr(\"lay-percent\");e.css(\"width\",function(){return/^.+\\/.+$/.test(l)?100*new Function(\"return \"+l)()+\"%\":l}()),i.attr(\"lay-showPercent\")&&setTimeout(function(){e.html('<span class=\"'+t+'-text\">'+l+\"</span>\")},350)})},collapse:function(){var t=\"layui-collapse\";a(\".\"+t+l).each(function(){var t=a(this).find(\".layui-colla-item\");t.each(function(){var t=a(this),i=t.find(\".layui-colla-title\"),e=t.find(\".layui-colla-content\"),l=\"none\"===e.css(\"display\");i.find(\".layui-colla-icon\").remove(),i.append('<i class=\"layui-icon layui-colla-icon\">'+(l?\"&#xe602;\":\"&#xe61a;\")+\"</i>\"),i.off(\"click\",f.collapse).on(\"click\",f.collapse)})})}};return s[t]?s[t]():layui.each(s,function(t,a){a()})},s.prototype.render=s.prototype.init;var p=new s,b=a(document);p.render();var v=\".layui-tab-title li\";b.on(\"click\",v,f.tabClick),b.on(\"click\",f.hideTabMore),a(window).on(\"resize\",f.tabAuto),t(e,p)});"
  },
  {
    "path": "open-layui-web/src/main/view/static/layui/lay/modules/flow.js",
    "content": "/** layui-v2.3.0-rc1 MIT License By https://www.layui.com */\n ;layui.define(\"jquery\",function(e){\"use strict\";var l=layui.$,o=function(e){},t='<i class=\"layui-anim layui-anim-rotate layui-anim-loop layui-icon \">&#xe63e;</i>';o.prototype.load=function(e){var o,i,n,r,a=this,c=0;e=e||{};var f=l(e.elem);if(f[0]){var m=l(e.scrollElem||document),u=e.mb||50,s=!(\"isAuto\"in e)||e.isAuto,v=e.end||\"没有更多了\",y=e.scrollElem&&e.scrollElem!==document,d=\"<cite>加载更多</cite>\",h=l('<div class=\"layui-flow-more\"><a href=\"javascript:;\">'+d+\"</a></div>\");f.find(\".layui-flow-more\")[0]||f.append(h);var p=function(e,t){e=l(e),h.before(e),t=0==t||null,t?h.html(v):h.find(\"a\").html(d),i=t,o=null,n&&n()},g=function(){o=!0,h.find(\"a\").html(t),\"function\"==typeof e.done&&e.done(++c,p)};if(g(),h.find(\"a\").on(\"click\",function(){l(this);i||o||g()}),e.isLazyimg)var n=a.lazyimg({elem:e.elem+\" img\",scrollElem:e.scrollElem});return s?(m.on(\"scroll\",function(){var e=l(this),t=e.scrollTop();r&&clearTimeout(r),i||(r=setTimeout(function(){var i=y?e.height():l(window).height(),n=y?e.prop(\"scrollHeight\"):document.documentElement.scrollHeight;n-t-i<=u&&(o||g())},100))}),a):a}},o.prototype.lazyimg=function(e){var o,t=this,i=0;e=e||{};var n=l(e.scrollElem||document),r=e.elem||\"img\",a=e.scrollElem&&e.scrollElem!==document,c=function(e,l){var o=n.scrollTop(),r=o+l,c=a?function(){return e.offset().top-n.offset().top+o}():e.offset().top;if(c>=o&&c<=r&&!e.attr(\"src\")){var m=e.attr(\"lay-src\");layui.img(m,function(){var l=t.lazyimg.elem.eq(i);e.attr(\"src\",m).removeAttr(\"lay-src\"),l[0]&&f(l),i++})}},f=function(e,o){var f=a?(o||n).height():l(window).height(),m=n.scrollTop(),u=m+f;if(t.lazyimg.elem=l(r),e)c(e,f);else for(var s=0;s<t.lazyimg.elem.length;s++){var v=t.lazyimg.elem.eq(s),y=a?function(){return v.offset().top-n.offset().top+m}():v.offset().top;if(c(v,f),i=s,y>u)break}};if(f(),!o){var m;n.on(\"scroll\",function(){var e=l(this);m&&clearTimeout(m),m=setTimeout(function(){f(null,e)},50)}),o=!0}return f},e(\"flow\",new o)});"
  },
  {
    "path": "open-layui-web/src/main/view/static/layui/lay/modules/form.js",
    "content": "/** layui-v2.3.0-rc1 MIT License By https://www.layui.com */\n ;layui.define(\"layer\",function(e){\"use strict\";var i=layui.$,t=layui.layer,a=layui.hint(),n=layui.device(),l=\"form\",r=\".layui-form\",s=\"layui-this\",c=\"layui-hide\",o=\"layui-disabled\",u=function(){this.config={verify:{required:[/[\\S]+/,\"必填项不能为空\"],phone:[/^1\\d{10}$/,\"请输入正确的手机号\"],email:[/^([a-zA-Z0-9_\\.\\-])+\\@(([a-zA-Z0-9\\-])+\\.)+([a-zA-Z0-9]{2,4})+$/,\"邮箱格式不正确\"],url:[/(^#)|(^http(s*):\\/\\/[^\\s]+\\.[^\\s]+)/,\"链接格式不正确\"],number:function(e){if(!e||isNaN(e))return\"只能填写数字\"},date:[/^(\\d{4})[-\\/](\\d{1}|0\\d{1}|1[0-2])([-\\/](\\d{1}|0\\d{1}|[1-2][0-9]|3[0-1]))*$/,\"日期格式不正确\"],identity:[/(^\\d{15}$)|(^\\d{17}(x|X|\\d)$)/,\"请输入正确的身份证号\"]}}};u.prototype.set=function(e){var t=this;return i.extend(!0,t.config,e),t},u.prototype.verify=function(e){var t=this;return i.extend(!0,t.config.verify,e),t},u.prototype.on=function(e,i){return layui.onevent.call(this,l,e,i)},u.prototype.val=function(e,t){var a=i(r+'[lay-filter=\"'+e+'\"]');a.each(function(e,a){var n=i(this);layui.each(t,function(e,i){var t,a=n.find('[name=\"'+e+'\"]');a[0]&&(t=a[0].type,\"checkbox\"===t?a[0].checked=i:\"radio\"===t?a.each(function(){this.value===i&&(this.checked=!0)}):a.val(i))})}),f.render(null,e)},u.prototype.render=function(e,t){var n=this,u=i(r+function(){return t?'[lay-filter=\"'+t+'\"]':\"\"}()),d={select:function(){var e,t=\"请选择\",a=\"layui-form-select\",n=\"layui-select-title\",r=\"layui-select-none\",d=\"\",f=u.find(\"select\"),v=function(t,l){i(t.target).parent().hasClass(n)&&!l||(i(\".\"+a).removeClass(a+\"ed \"+a+\"up\"),e&&d&&e.val(d)),e=null},h=function(t,u,f){var h,p=i(this),m=t.find(\".\"+n),k=m.find(\"input\"),g=t.find(\"dl\"),x=g.children(\"dd\"),b=this.selectedIndex;if(!u){var C=function(){var e=t.offset().top+t.outerHeight()+5-y.scrollTop(),i=g.outerHeight();b=p[0].selectedIndex,t.addClass(a+\"ed\"),x.removeClass(c),x.eq(b).addClass(s).siblings().removeClass(s),e+i>y.height()&&e>=i&&t.addClass(a+\"up\")},w=function(e){t.removeClass(a+\"ed \"+a+\"up\"),k.blur(),h=null,e||$(k.val(),function(e){e&&(d=g.find(\".\"+s).html(),k&&k.val(d))})};m.on(\"click\",function(e){t.hasClass(a+\"ed\")?w():(v(e,!0),C()),g.find(\".\"+r).remove()}),m.find(\".layui-edge\").on(\"click\",function(){k.focus()}),k.on(\"keyup\",function(e){var i=e.keyCode;9===i&&C()}).on(\"keydown\",function(e){var i=e.keyCode;9===i&&w();var t=function(i,a){var n,l;if(e.preventDefault(),a=function(){return a&&a[0]?a:h&&h[0]?h:x.eq(b)}(),l=a[i](),n=a[i](\"dd\"),l[0])return h=a[i](),!n[0]||n.hasClass(o)?t(i,h):void n.addClass(s).siblings().removeClass(s)};38===i&&t(\"prev\"),40===i&&t(\"next\"),13===i&&(e.preventDefault(),g.children(\"dd.\"+s).trigger(\"click\"))});var $=function(e,t,a){var n=0;layui.each(x,function(){var t=i(this),l=t.text(),r=l.indexOf(e)===-1;(\"\"===e||\"blur\"===a?e!==l:r)&&n++,\"keyup\"===a&&t[r?\"addClass\":\"removeClass\"](c)});var l=n===x.length;return t(l),l},T=function(e){var i=this.value,t=e.keyCode;return 9!==t&&13!==t&&37!==t&&38!==t&&39!==t&&40!==t&&($(i,function(e){e?g.find(\".\"+r)[0]||g.append('<p class=\"'+r+'\">无匹配项</p>'):g.find(\".\"+r).remove()},\"keyup\"),void(\"\"===i&&g.find(\".\"+r).remove()))};f&&k.on(\"keyup\",T).on(\"blur\",function(t){var a=p[0].selectedIndex;e=k,d=i(p[0].options[a]).html(),setTimeout(function(){$(k.val(),function(e){d||k.val(\"\")},\"blur\")},200)}),x.on(\"click\",function(){var e=i(this),a=e.attr(\"lay-value\"),n=p.attr(\"lay-filter\");return!e.hasClass(o)&&(e.hasClass(\"layui-select-tips\")?k.val(\"\"):(k.val(e.text()),e.addClass(s)),e.siblings().removeClass(s),p.val(a).removeClass(\"layui-form-danger\"),layui.event.call(this,l,\"select(\"+n+\")\",{elem:p[0],value:a,othis:t}),w(!0),!1)}),t.find(\"dl>dt\").on(\"click\",function(e){return!1}),i(document).off(\"click\",v).on(\"click\",v)}};f.each(function(e,l){var r=i(this),c=r.next(\".\"+a),u=this.disabled,d=l.value,f=i(l.options[l.selectedIndex]),v=l.options[0];if(\"string\"==typeof r.attr(\"lay-ignore\"))return r.show();var y=\"string\"==typeof r.attr(\"lay-search\"),p=v?v.value?t:v.innerHTML||t:t,m=i(['<div class=\"'+(y?\"\":\"layui-unselect \")+a,(u?\" layui-select-disabled\":\"\")+'\">','<div class=\"'+n+'\">','<input type=\"text\" placeholder=\"'+p+'\" '+('value=\"'+(d?f.html():\"\")+'\"')+(y?\"\":\" readonly\")+' class=\"layui-input'+(y?\"\":\" layui-unselect\")+(u?\" \"+o:\"\")+'\">','<i class=\"layui-edge\"></i></div>','<dl class=\"layui-anim layui-anim-upbit'+(r.find(\"optgroup\")[0]?\" layui-select-group\":\"\")+'\">',function(e){var i=[];return layui.each(e,function(e,a){0!==e||a.value?\"optgroup\"===a.tagName.toLowerCase()?i.push(\"<dt>\"+a.label+\"</dt>\"):i.push('<dd lay-value=\"'+a.value+'\" class=\"'+(d===a.value?s:\"\")+(a.disabled?\" \"+o:\"\")+'\">'+a.innerHTML+\"</dd>\"):i.push('<dd lay-value=\"\" class=\"layui-select-tips\">'+(a.innerHTML||t)+\"</dd>\")}),0===i.length&&i.push('<dd lay-value=\"\" class=\"'+o+'\">没有选项</dd>'),i.join(\"\")}(r.find(\"*\"))+\"</dl>\",\"</div>\"].join(\"\"));c[0]&&c.remove(),r.after(m),h.call(this,m,u,y)})},checkbox:function(){var e={checkbox:[\"layui-form-checkbox\",\"layui-form-checked\",\"checkbox\"],_switch:[\"layui-form-switch\",\"layui-form-onswitch\",\"switch\"]},t=u.find(\"input[type=checkbox]\"),a=function(e,t){var a=i(this);e.on(\"click\",function(){var i=a.attr(\"lay-filter\"),n=(a.attr(\"lay-text\")||\"\").split(\"|\");a[0].disabled||(a[0].checked?(a[0].checked=!1,e.removeClass(t[1]).find(\"em\").text(n[1])):(a[0].checked=!0,e.addClass(t[1]).find(\"em\").text(n[0])),layui.event.call(a[0],l,t[2]+\"(\"+i+\")\",{elem:a[0],value:a[0].value,othis:e}))})};t.each(function(t,n){var l=i(this),r=l.attr(\"lay-skin\"),s=(l.attr(\"lay-text\")||\"\").split(\"|\"),c=this.disabled;\"switch\"===r&&(r=\"_\"+r);var u=e[r]||e.checkbox;if(\"string\"==typeof l.attr(\"lay-ignore\"))return l.show();var d=l.next(\".\"+u[0]),f=i(['<div class=\"layui-unselect '+u[0],n.checked?\" \"+u[1]:\"\",c?\" layui-checkbox-disbaled \"+o:\"\",'\"',r?' lay-skin=\"'+r+'\"':\"\",\">\",function(){var e=n.title.replace(/\\s/g,\"\"),i={checkbox:[e?\"<span>\"+n.title+\"</span>\":\"\",'<i class=\"layui-icon layui-icon-ok\"></i>'].join(\"\"),_switch:\"<em>\"+((n.checked?s[0]:s[1])||\"\")+\"</em><i></i>\"};return i[r]||i.checkbox}(),\"</div>\"].join(\"\"));d[0]&&d.remove(),l.after(f),a.call(this,f,u)})},radio:function(){var e=\"layui-form-radio\",t=[\"&#xe643;\",\"&#xe63f;\"],a=u.find(\"input[type=radio]\"),n=function(a){var n=i(this),s=\"layui-anim-scaleSpring\";a.on(\"click\",function(){var c=n[0].name,o=n.parents(r),u=n.attr(\"lay-filter\"),d=o.find(\"input[name=\"+c.replace(/(\\.|#|\\[|\\])/g,\"\\\\$1\")+\"]\");n[0].disabled||(layui.each(d,function(){var a=i(this).next(\".\"+e);this.checked=!1,a.removeClass(e+\"ed\"),a.find(\".layui-icon\").removeClass(s).html(t[1])}),n[0].checked=!0,a.addClass(e+\"ed\"),a.find(\".layui-icon\").addClass(s).html(t[0]),layui.event.call(n[0],l,\"radio(\"+u+\")\",{elem:n[0],value:n[0].value,othis:a}))})};a.each(function(a,l){var r=i(this),s=r.next(\".\"+e),c=this.disabled;if(\"string\"==typeof r.attr(\"lay-ignore\"))return r.show();s[0]&&s.remove();var u=i(['<div class=\"layui-unselect '+e,l.checked?\" \"+e+\"ed\":\"\",(c?\" layui-radio-disbaled \"+o:\"\")+'\">','<i class=\"layui-anim layui-icon\">'+t[l.checked?0:1]+\"</i>\",\"<div>\"+function(){var e=l.title||\"\";return\"string\"==typeof r.next().attr(\"lay-radio\")&&(e=r.next().html(),r.next().remove()),e}()+\"</div>\",\"</div>\"].join(\"\"));r.after(u),n.call(this,u)})}};return e?d[e]?d[e]():a.error(\"不支持的\"+e+\"表单渲染\"):layui.each(d,function(e,i){i()}),n};var d=function(){var e=i(this),a=f.config.verify,s=null,c=\"layui-form-danger\",o={},u=e.parents(r),d=u.find(\"*[lay-verify]\"),v=e.parents(\"form\")[0],y=u.find(\"input,select,textarea\"),h=e.attr(\"lay-filter\");if(layui.each(d,function(e,l){var r=i(this),o=r.attr(\"lay-verify\").split(\"|\"),u=r.attr(\"lay-verType\"),d=r.val();if(r.removeClass(c),layui.each(o,function(e,i){var o,f=\"\",v=\"function\"==typeof a[i];if(a[i]){var o=v?f=a[i](d,l):!a[i][0].test(d);if(f=f||a[i][1],o)return\"tips\"===u?t.tips(f,function(){return\"string\"==typeof r.attr(\"lay-ignore\")||\"select\"!==l.tagName.toLowerCase()&&!/^checkbox|radio$/.test(l.type)?r:r.next()}(),{tips:1}):\"alert\"===u?t.alert(f,{title:\"提示\",shadeClose:!0}):t.msg(f,{icon:5,shift:6}),n.android||n.ios||l.focus(),r.addClass(c),s=!0}}),s)return s}),s)return!1;var p={};return layui.each(y,function(e,i){if(i.name=(i.name||\"\").replace(/^\\s*|\\s*&/,\"\"),i.name){if(/^.*\\[\\]$/.test(i.name)){var t=i.name.match(/^(.*)\\[\\]$/g)[0];p[t]=0|p[t],i.name=i.name.replace(/^(.*)\\[\\]$/,\"$1[\"+p[t]++ +\"]\")}/^checkbox|radio$/.test(i.type)&&!i.checked||(o[i.name]=i.value)}}),layui.event.call(this,l,\"submit(\"+h+\")\",{elem:this,form:v,field:o})},f=new u,v=i(document),y=i(window);f.render(),v.on(\"reset\",r,function(){var e=i(this).attr(\"lay-filter\");setTimeout(function(){f.render(null,e)},50)}),v.on(\"submit\",r,d).on(\"click\",\"*[lay-submit]\",d),e(l,f)});"
  },
  {
    "path": "open-layui-web/src/main/view/static/layui/lay/modules/jquery.js",
    "content": "/** layui-v2.3.0-rc1 MIT License By https://www.layui.com */\n ;!function(e,t){\"object\"==typeof module&&\"object\"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error(\"jQuery requires a window with a document\");return t(e)}:t(e)}(\"undefined\"!=typeof window?window:this,function(e,t){function n(e){var t=!!e&&\"length\"in e&&e.length,n=pe.type(e);return\"function\"!==n&&!pe.isWindow(e)&&(\"array\"===n||0===t||\"number\"==typeof t&&t>0&&t-1 in e)}function r(e,t,n){if(pe.isFunction(t))return pe.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return pe.grep(e,function(e){return e===t!==n});if(\"string\"==typeof t){if(Ce.test(t))return pe.filter(t,e,n);t=pe.filter(t,e)}return pe.grep(e,function(e){return pe.inArray(e,t)>-1!==n})}function i(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}function o(e){var t={};return pe.each(e.match(De)||[],function(e,n){t[n]=!0}),t}function a(){re.addEventListener?(re.removeEventListener(\"DOMContentLoaded\",s),e.removeEventListener(\"load\",s)):(re.detachEvent(\"onreadystatechange\",s),e.detachEvent(\"onload\",s))}function s(){(re.addEventListener||\"load\"===e.event.type||\"complete\"===re.readyState)&&(a(),pe.ready())}function u(e,t,n){if(void 0===n&&1===e.nodeType){var r=\"data-\"+t.replace(_e,\"-$1\").toLowerCase();if(n=e.getAttribute(r),\"string\"==typeof n){try{n=\"true\"===n||\"false\"!==n&&(\"null\"===n?null:+n+\"\"===n?+n:qe.test(n)?pe.parseJSON(n):n)}catch(i){}pe.data(e,t,n)}else n=void 0}return n}function l(e){var t;for(t in e)if((\"data\"!==t||!pe.isEmptyObject(e[t]))&&\"toJSON\"!==t)return!1;return!0}function c(e,t,n,r){if(He(e)){var i,o,a=pe.expando,s=e.nodeType,u=s?pe.cache:e,l=s?e[a]:e[a]&&a;if(l&&u[l]&&(r||u[l].data)||void 0!==n||\"string\"!=typeof t)return l||(l=s?e[a]=ne.pop()||pe.guid++:a),u[l]||(u[l]=s?{}:{toJSON:pe.noop}),\"object\"!=typeof t&&\"function\"!=typeof t||(r?u[l]=pe.extend(u[l],t):u[l].data=pe.extend(u[l].data,t)),o=u[l],r||(o.data||(o.data={}),o=o.data),void 0!==n&&(o[pe.camelCase(t)]=n),\"string\"==typeof t?(i=o[t],null==i&&(i=o[pe.camelCase(t)])):i=o,i}}function f(e,t,n){if(He(e)){var r,i,o=e.nodeType,a=o?pe.cache:e,s=o?e[pe.expando]:pe.expando;if(a[s]){if(t&&(r=n?a[s]:a[s].data)){pe.isArray(t)?t=t.concat(pe.map(t,pe.camelCase)):t in r?t=[t]:(t=pe.camelCase(t),t=t in r?[t]:t.split(\" \")),i=t.length;for(;i--;)delete r[t[i]];if(n?!l(r):!pe.isEmptyObject(r))return}(n||(delete a[s].data,l(a[s])))&&(o?pe.cleanData([e],!0):fe.deleteExpando||a!=a.window?delete a[s]:a[s]=void 0)}}}function d(e,t,n,r){var i,o=1,a=20,s=r?function(){return r.cur()}:function(){return pe.css(e,t,\"\")},u=s(),l=n&&n[3]||(pe.cssNumber[t]?\"\":\"px\"),c=(pe.cssNumber[t]||\"px\"!==l&&+u)&&Me.exec(pe.css(e,t));if(c&&c[3]!==l){l=l||c[3],n=n||[],c=+u||1;do o=o||\".5\",c/=o,pe.style(e,t,c+l);while(o!==(o=s()/u)&&1!==o&&--a)}return n&&(c=+c||+u||0,i=n[1]?c+(n[1]+1)*n[2]:+n[2],r&&(r.unit=l,r.start=c,r.end=i)),i}function p(e){var t=ze.split(\"|\"),n=e.createDocumentFragment();if(n.createElement)for(;t.length;)n.createElement(t.pop());return n}function h(e,t){var n,r,i=0,o=\"undefined\"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||\"*\"):\"undefined\"!=typeof e.querySelectorAll?e.querySelectorAll(t||\"*\"):void 0;if(!o)for(o=[],n=e.childNodes||e;null!=(r=n[i]);i++)!t||pe.nodeName(r,t)?o.push(r):pe.merge(o,h(r,t));return void 0===t||t&&pe.nodeName(e,t)?pe.merge([e],o):o}function g(e,t){for(var n,r=0;null!=(n=e[r]);r++)pe._data(n,\"globalEval\",!t||pe._data(t[r],\"globalEval\"))}function m(e){Be.test(e.type)&&(e.defaultChecked=e.checked)}function y(e,t,n,r,i){for(var o,a,s,u,l,c,f,d=e.length,y=p(t),v=[],x=0;x<d;x++)if(a=e[x],a||0===a)if(\"object\"===pe.type(a))pe.merge(v,a.nodeType?[a]:a);else if(Ue.test(a)){for(u=u||y.appendChild(t.createElement(\"div\")),l=(We.exec(a)||[\"\",\"\"])[1].toLowerCase(),f=Xe[l]||Xe._default,u.innerHTML=f[1]+pe.htmlPrefilter(a)+f[2],o=f[0];o--;)u=u.lastChild;if(!fe.leadingWhitespace&&$e.test(a)&&v.push(t.createTextNode($e.exec(a)[0])),!fe.tbody)for(a=\"table\"!==l||Ve.test(a)?\"<table>\"!==f[1]||Ve.test(a)?0:u:u.firstChild,o=a&&a.childNodes.length;o--;)pe.nodeName(c=a.childNodes[o],\"tbody\")&&!c.childNodes.length&&a.removeChild(c);for(pe.merge(v,u.childNodes),u.textContent=\"\";u.firstChild;)u.removeChild(u.firstChild);u=y.lastChild}else v.push(t.createTextNode(a));for(u&&y.removeChild(u),fe.appendChecked||pe.grep(h(v,\"input\"),m),x=0;a=v[x++];)if(r&&pe.inArray(a,r)>-1)i&&i.push(a);else if(s=pe.contains(a.ownerDocument,a),u=h(y.appendChild(a),\"script\"),s&&g(u),n)for(o=0;a=u[o++];)Ie.test(a.type||\"\")&&n.push(a);return u=null,y}function v(){return!0}function x(){return!1}function b(){try{return re.activeElement}catch(e){}}function w(e,t,n,r,i,o){var a,s;if(\"object\"==typeof t){\"string\"!=typeof n&&(r=r||n,n=void 0);for(s in t)w(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&(\"string\"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),i===!1)i=x;else if(!i)return e;return 1===o&&(a=i,i=function(e){return pe().off(e),a.apply(this,arguments)},i.guid=a.guid||(a.guid=pe.guid++)),e.each(function(){pe.event.add(this,t,i,r,n)})}function T(e,t){return pe.nodeName(e,\"table\")&&pe.nodeName(11!==t.nodeType?t:t.firstChild,\"tr\")?e.getElementsByTagName(\"tbody\")[0]||e.appendChild(e.ownerDocument.createElement(\"tbody\")):e}function C(e){return e.type=(null!==pe.find.attr(e,\"type\"))+\"/\"+e.type,e}function E(e){var t=it.exec(e.type);return t?e.type=t[1]:e.removeAttribute(\"type\"),e}function N(e,t){if(1===t.nodeType&&pe.hasData(e)){var n,r,i,o=pe._data(e),a=pe._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;r<i;r++)pe.event.add(t,n,s[n][r])}a.data&&(a.data=pe.extend({},a.data))}}function k(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!fe.noCloneEvent&&t[pe.expando]){i=pe._data(t);for(r in i.events)pe.removeEvent(t,r,i.handle);t.removeAttribute(pe.expando)}\"script\"===n&&t.text!==e.text?(C(t).text=e.text,E(t)):\"object\"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),fe.html5Clone&&e.innerHTML&&!pe.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):\"input\"===n&&Be.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)}}function S(e,t,n,r){t=oe.apply([],t);var i,o,a,s,u,l,c=0,f=e.length,d=f-1,p=t[0],g=pe.isFunction(p);if(g||f>1&&\"string\"==typeof p&&!fe.checkClone&&rt.test(p))return e.each(function(i){var o=e.eq(i);g&&(t[0]=p.call(this,i,o.html())),S(o,t,n,r)});if(f&&(l=y(t,e[0].ownerDocument,!1,e,r),i=l.firstChild,1===l.childNodes.length&&(l=i),i||r)){for(s=pe.map(h(l,\"script\"),C),a=s.length;c<f;c++)o=l,c!==d&&(o=pe.clone(o,!0,!0),a&&pe.merge(s,h(o,\"script\"))),n.call(e[c],o,c);if(a)for(u=s[s.length-1].ownerDocument,pe.map(s,E),c=0;c<a;c++)o=s[c],Ie.test(o.type||\"\")&&!pe._data(o,\"globalEval\")&&pe.contains(u,o)&&(o.src?pe._evalUrl&&pe._evalUrl(o.src):pe.globalEval((o.text||o.textContent||o.innerHTML||\"\").replace(ot,\"\")));l=i=null}return e}function A(e,t,n){for(var r,i=t?pe.filter(t,e):e,o=0;null!=(r=i[o]);o++)n||1!==r.nodeType||pe.cleanData(h(r)),r.parentNode&&(n&&pe.contains(r.ownerDocument,r)&&g(h(r,\"script\")),r.parentNode.removeChild(r));return e}function D(e,t){var n=pe(t.createElement(e)).appendTo(t.body),r=pe.css(n[0],\"display\");return n.detach(),r}function j(e){var t=re,n=lt[e];return n||(n=D(e,t),\"none\"!==n&&n||(ut=(ut||pe(\"<iframe frameborder='0' width='0' height='0'/>\")).appendTo(t.documentElement),t=(ut[0].contentWindow||ut[0].contentDocument).document,t.write(),t.close(),n=D(e,t),ut.detach()),lt[e]=n),n}function L(e,t){return{get:function(){return e()?void delete this.get:(this.get=t).apply(this,arguments)}}}function H(e){if(e in Et)return e;for(var t=e.charAt(0).toUpperCase()+e.slice(1),n=Ct.length;n--;)if(e=Ct[n]+t,e in Et)return e}function q(e,t){for(var n,r,i,o=[],a=0,s=e.length;a<s;a++)r=e[a],r.style&&(o[a]=pe._data(r,\"olddisplay\"),n=r.style.display,t?(o[a]||\"none\"!==n||(r.style.display=\"\"),\"\"===r.style.display&&Re(r)&&(o[a]=pe._data(r,\"olddisplay\",j(r.nodeName)))):(i=Re(r),(n&&\"none\"!==n||!i)&&pe._data(r,\"olddisplay\",i?n:pe.css(r,\"display\"))));for(a=0;a<s;a++)r=e[a],r.style&&(t&&\"none\"!==r.style.display&&\"\"!==r.style.display||(r.style.display=t?o[a]||\"\":\"none\"));return e}function _(e,t,n){var r=bt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||\"px\"):t}function F(e,t,n,r,i){for(var o=n===(r?\"border\":\"content\")?4:\"width\"===t?1:0,a=0;o<4;o+=2)\"margin\"===n&&(a+=pe.css(e,n+Oe[o],!0,i)),r?(\"content\"===n&&(a-=pe.css(e,\"padding\"+Oe[o],!0,i)),\"margin\"!==n&&(a-=pe.css(e,\"border\"+Oe[o]+\"Width\",!0,i))):(a+=pe.css(e,\"padding\"+Oe[o],!0,i),\"padding\"!==n&&(a+=pe.css(e,\"border\"+Oe[o]+\"Width\",!0,i)));return a}function M(t,n,r){var i=!0,o=\"width\"===n?t.offsetWidth:t.offsetHeight,a=ht(t),s=fe.boxSizing&&\"border-box\"===pe.css(t,\"boxSizing\",!1,a);if(re.msFullscreenElement&&e.top!==e&&t.getClientRects().length&&(o=Math.round(100*t.getBoundingClientRect()[n])),o<=0||null==o){if(o=gt(t,n,a),(o<0||null==o)&&(o=t.style[n]),ft.test(o))return o;i=s&&(fe.boxSizingReliable()||o===t.style[n]),o=parseFloat(o)||0}return o+F(t,n,r||(s?\"border\":\"content\"),i,a)+\"px\"}function O(e,t,n,r,i){return new O.prototype.init(e,t,n,r,i)}function R(){return e.setTimeout(function(){Nt=void 0}),Nt=pe.now()}function P(e,t){var n,r={height:e},i=0;for(t=t?1:0;i<4;i+=2-t)n=Oe[i],r[\"margin\"+n]=r[\"padding\"+n]=e;return t&&(r.opacity=r.width=e),r}function B(e,t,n){for(var r,i=($.tweeners[t]||[]).concat($.tweeners[\"*\"]),o=0,a=i.length;o<a;o++)if(r=i[o].call(n,t,e))return r}function W(e,t,n){var r,i,o,a,s,u,l,c,f=this,d={},p=e.style,h=e.nodeType&&Re(e),g=pe._data(e,\"fxshow\");n.queue||(s=pe._queueHooks(e,\"fx\"),null==s.unqueued&&(s.unqueued=0,u=s.empty.fire,s.empty.fire=function(){s.unqueued||u()}),s.unqueued++,f.always(function(){f.always(function(){s.unqueued--,pe.queue(e,\"fx\").length||s.empty.fire()})})),1===e.nodeType&&(\"height\"in t||\"width\"in t)&&(n.overflow=[p.overflow,p.overflowX,p.overflowY],l=pe.css(e,\"display\"),c=\"none\"===l?pe._data(e,\"olddisplay\")||j(e.nodeName):l,\"inline\"===c&&\"none\"===pe.css(e,\"float\")&&(fe.inlineBlockNeedsLayout&&\"inline\"!==j(e.nodeName)?p.zoom=1:p.display=\"inline-block\")),n.overflow&&(p.overflow=\"hidden\",fe.shrinkWrapBlocks()||f.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],St.exec(i)){if(delete t[r],o=o||\"toggle\"===i,i===(h?\"hide\":\"show\")){if(\"show\"!==i||!g||void 0===g[r])continue;h=!0}d[r]=g&&g[r]||pe.style(e,r)}else l=void 0;if(pe.isEmptyObject(d))\"inline\"===(\"none\"===l?j(e.nodeName):l)&&(p.display=l);else{g?\"hidden\"in g&&(h=g.hidden):g=pe._data(e,\"fxshow\",{}),o&&(g.hidden=!h),h?pe(e).show():f.done(function(){pe(e).hide()}),f.done(function(){var t;pe._removeData(e,\"fxshow\");for(t in d)pe.style(e,t,d[t])});for(r in d)a=B(h?g[r]:0,r,f),r in g||(g[r]=a.start,h&&(a.end=a.start,a.start=\"width\"===r||\"height\"===r?1:0))}}function I(e,t){var n,r,i,o,a;for(n in e)if(r=pe.camelCase(n),i=t[r],o=e[n],pe.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),a=pe.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}function $(e,t,n){var r,i,o=0,a=$.prefilters.length,s=pe.Deferred().always(function(){delete u.elem}),u=function(){if(i)return!1;for(var t=Nt||R(),n=Math.max(0,l.startTime+l.duration-t),r=n/l.duration||0,o=1-r,a=0,u=l.tweens.length;a<u;a++)l.tweens[a].run(o);return s.notifyWith(e,[l,o,n]),o<1&&u?n:(s.resolveWith(e,[l]),!1)},l=s.promise({elem:e,props:pe.extend({},t),opts:pe.extend(!0,{specialEasing:{},easing:pe.easing._default},n),originalProperties:t,originalOptions:n,startTime:Nt||R(),duration:n.duration,tweens:[],createTween:function(t,n){var r=pe.Tween(e,l.opts,t,n,l.opts.specialEasing[t]||l.opts.easing);return l.tweens.push(r),r},stop:function(t){var n=0,r=t?l.tweens.length:0;if(i)return this;for(i=!0;n<r;n++)l.tweens[n].run(1);return t?(s.notifyWith(e,[l,1,0]),s.resolveWith(e,[l,t])):s.rejectWith(e,[l,t]),this}}),c=l.props;for(I(c,l.opts.specialEasing);o<a;o++)if(r=$.prefilters[o].call(l,e,c,l.opts))return pe.isFunction(r.stop)&&(pe._queueHooks(l.elem,l.opts.queue).stop=pe.proxy(r.stop,r)),r;return pe.map(c,B,l),pe.isFunction(l.opts.start)&&l.opts.start.call(e,l),pe.fx.timer(pe.extend(u,{elem:e,anim:l,queue:l.opts.queue})),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always)}function z(e){return pe.attr(e,\"class\")||\"\"}function X(e){return function(t,n){\"string\"!=typeof t&&(n=t,t=\"*\");var r,i=0,o=t.toLowerCase().match(De)||[];if(pe.isFunction(n))for(;r=o[i++];)\"+\"===r.charAt(0)?(r=r.slice(1)||\"*\",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function U(e,t,n,r){function i(s){var u;return o[s]=!0,pe.each(e[s]||[],function(e,s){var l=s(t,n,r);return\"string\"!=typeof l||a||o[l]?a?!(u=l):void 0:(t.dataTypes.unshift(l),i(l),!1)}),u}var o={},a=e===Qt;return i(t.dataTypes[0])||!o[\"*\"]&&i(\"*\")}function V(e,t){var n,r,i=pe.ajaxSettings.flatOptions||{};for(r in t)void 0!==t[r]&&((i[r]?e:n||(n={}))[r]=t[r]);return n&&pe.extend(!0,e,n),e}function Y(e,t,n){for(var r,i,o,a,s=e.contents,u=e.dataTypes;\"*\"===u[0];)u.shift(),void 0===i&&(i=e.mimeType||t.getResponseHeader(\"Content-Type\"));if(i)for(a in s)if(s[a]&&s[a].test(i)){u.unshift(a);break}if(u[0]in n)o=u[0];else{for(a in n){if(!u[0]||e.converters[a+\" \"+u[0]]){o=a;break}r||(r=a)}o=o||r}if(o)return o!==u[0]&&u.unshift(o),n[o]}function J(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];for(o=c.shift();o;)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if(\"*\"===o)o=u;else if(\"*\"!==u&&u!==o){if(a=l[u+\" \"+o]||l[\"* \"+o],!a)for(i in l)if(s=i.split(\" \"),s[1]===o&&(a=l[u+\" \"+s[0]]||l[\"* \"+s[0]])){a===!0?a=l[i]:l[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(f){return{state:\"parsererror\",error:a?f:\"No conversion from \"+u+\" to \"+o}}}return{state:\"success\",data:t}}function G(e){return e.style&&e.style.display||pe.css(e,\"display\")}function K(e){for(;e&&1===e.nodeType;){if(\"none\"===G(e)||\"hidden\"===e.type)return!0;e=e.parentNode}return!1}function Q(e,t,n,r){var i;if(pe.isArray(t))pe.each(t,function(t,i){n||rn.test(e)?r(e,i):Q(e+\"[\"+(\"object\"==typeof i&&null!=i?t:\"\")+\"]\",i,n,r)});else if(n||\"object\"!==pe.type(t))r(e,t);else for(i in t)Q(e+\"[\"+i+\"]\",t[i],n,r)}function Z(){try{return new e.XMLHttpRequest}catch(t){}}function ee(){try{return new e.ActiveXObject(\"Microsoft.XMLHTTP\")}catch(t){}}function te(e){return pe.isWindow(e)?e:9===e.nodeType&&(e.defaultView||e.parentWindow)}var ne=[],re=e.document,ie=ne.slice,oe=ne.concat,ae=ne.push,se=ne.indexOf,ue={},le=ue.toString,ce=ue.hasOwnProperty,fe={},de=\"1.12.3\",pe=function(e,t){return new pe.fn.init(e,t)},he=/^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g,ge=/^-ms-/,me=/-([\\da-z])/gi,ye=function(e,t){return t.toUpperCase()};pe.fn=pe.prototype={jquery:de,constructor:pe,selector:\"\",length:0,toArray:function(){return ie.call(this)},get:function(e){return null!=e?e<0?this[e+this.length]:this[e]:ie.call(this)},pushStack:function(e){var t=pe.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e){return pe.each(this,e)},map:function(e){return this.pushStack(pe.map(this,function(t,n){return e.call(t,n,t)}))},slice:function(){return this.pushStack(ie.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(n>=0&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:ae,sort:ne.sort,splice:ne.splice},pe.extend=pe.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for(\"boolean\"==typeof a&&(l=a,a=arguments[s]||{},s++),\"object\"==typeof a||pe.isFunction(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(i=arguments[s]))for(r in i)e=a[r],n=i[r],a!==n&&(l&&n&&(pe.isPlainObject(n)||(t=pe.isArray(n)))?(t?(t=!1,o=e&&pe.isArray(e)?e:[]):o=e&&pe.isPlainObject(e)?e:{},a[r]=pe.extend(l,o,n)):void 0!==n&&(a[r]=n));return a},pe.extend({expando:\"jQuery\"+(de+Math.random()).replace(/\\D/g,\"\"),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isFunction:function(e){return\"function\"===pe.type(e)},isArray:Array.isArray||function(e){return\"array\"===pe.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){var t=e&&e.toString();return!pe.isArray(e)&&t-parseFloat(t)+1>=0},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},isPlainObject:function(e){var t;if(!e||\"object\"!==pe.type(e)||e.nodeType||pe.isWindow(e))return!1;try{if(e.constructor&&!ce.call(e,\"constructor\")&&!ce.call(e.constructor.prototype,\"isPrototypeOf\"))return!1}catch(n){return!1}if(!fe.ownFirst)for(t in e)return ce.call(e,t);for(t in e);return void 0===t||ce.call(e,t)},type:function(e){return null==e?e+\"\":\"object\"==typeof e||\"function\"==typeof e?ue[le.call(e)]||\"object\":typeof e},globalEval:function(t){t&&pe.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(ge,\"ms-\").replace(me,ye)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t){var r,i=0;if(n(e))for(r=e.length;i<r&&t.call(e[i],i,e[i])!==!1;i++);else for(i in e)if(t.call(e[i],i,e[i])===!1)break;return e},trim:function(e){return null==e?\"\":(e+\"\").replace(he,\"\")},makeArray:function(e,t){var r=t||[];return null!=e&&(n(Object(e))?pe.merge(r,\"string\"==typeof e?[e]:e):ae.call(r,e)),r},inArray:function(e,t,n){var r;if(t){if(se)return se.call(t,e,n);for(r=t.length,n=n?n<0?Math.max(0,r+n):n:0;n<r;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;)e[i++]=t[r++];if(n!==n)for(;void 0!==t[r];)e[i++]=t[r++];return e.length=i,e},grep:function(e,t,n){for(var r,i=[],o=0,a=e.length,s=!n;o<a;o++)r=!t(e[o],o),r!==s&&i.push(e[o]);return i},map:function(e,t,r){var i,o,a=0,s=[];if(n(e))for(i=e.length;a<i;a++)o=t(e[a],a,r),null!=o&&s.push(o);else for(a in e)o=t(e[a],a,r),null!=o&&s.push(o);return oe.apply([],s)},guid:1,proxy:function(e,t){var n,r,i;if(\"string\"==typeof t&&(i=e[t],t=e,e=i),pe.isFunction(e))return n=ie.call(arguments,2),r=function(){return e.apply(t||this,n.concat(ie.call(arguments)))},r.guid=e.guid=e.guid||pe.guid++,r},now:function(){return+new Date},support:fe}),\"function\"==typeof Symbol&&(pe.fn[Symbol.iterator]=ne[Symbol.iterator]),pe.each(\"Boolean Number String Function Array Date RegExp Object Error Symbol\".split(\" \"),function(e,t){ue[\"[object \"+t+\"]\"]=t.toLowerCase()});var ve=function(e){function t(e,t,n,r){var i,o,a,s,u,l,f,p,h=t&&t.ownerDocument,g=t?t.nodeType:9;if(n=n||[],\"string\"!=typeof e||!e||1!==g&&9!==g&&11!==g)return n;if(!r&&((t?t.ownerDocument||t:B)!==H&&L(t),t=t||H,_)){if(11!==g&&(l=ye.exec(e)))if(i=l[1]){if(9===g){if(!(a=t.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(h&&(a=h.getElementById(i))&&R(t,a)&&a.id===i)return n.push(a),n}else{if(l[2])return Q.apply(n,t.getElementsByTagName(e)),n;if((i=l[3])&&w.getElementsByClassName&&t.getElementsByClassName)return Q.apply(n,t.getElementsByClassName(i)),n}if(w.qsa&&!X[e+\" \"]&&(!F||!F.test(e))){if(1!==g)h=t,p=e;else if(\"object\"!==t.nodeName.toLowerCase()){for((s=t.getAttribute(\"id\"))?s=s.replace(xe,\"\\\\$&\"):t.setAttribute(\"id\",s=P),f=N(e),o=f.length,u=de.test(s)?\"#\"+s:\"[id='\"+s+\"']\";o--;)f[o]=u+\" \"+d(f[o]);p=f.join(\",\"),h=ve.test(e)&&c(t.parentNode)||t}if(p)try{return Q.apply(n,h.querySelectorAll(p)),n}catch(m){}finally{s===P&&t.removeAttribute(\"id\")}}}return S(e.replace(se,\"$1\"),t,n,r)}function n(){function e(n,r){return t.push(n+\" \")>T.cacheLength&&delete e[t.shift()],e[n+\" \"]=r}var t=[];return e}function r(e){return e[P]=!0,e}function i(e){var t=H.createElement(\"div\");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function o(e,t){for(var n=e.split(\"|\"),r=n.length;r--;)T.attrHandle[n[r]]=t}function a(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||V)-(~e.sourceIndex||V);if(r)return r;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function s(e){return function(t){var n=t.nodeName.toLowerCase();return\"input\"===n&&t.type===e}}function u(e){return function(t){var n=t.nodeName.toLowerCase();return(\"input\"===n||\"button\"===n)&&t.type===e}}function l(e){return r(function(t){return t=+t,r(function(n,r){for(var i,o=e([],n.length,t),a=o.length;a--;)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}function c(e){return e&&\"undefined\"!=typeof e.getElementsByTagName&&e}function f(){}function d(e){for(var t=0,n=e.length,r=\"\";t<n;t++)r+=e[t].value;return r}function p(e,t,n){var r=t.dir,i=n&&\"parentNode\"===r,o=I++;return t.first?function(t,n,o){for(;t=t[r];)if(1===t.nodeType||i)return e(t,n,o)}:function(t,n,a){var s,u,l,c=[W,o];if(a){for(;t=t[r];)if((1===t.nodeType||i)&&e(t,n,a))return!0}else for(;t=t[r];)if(1===t.nodeType||i){if(l=t[P]||(t[P]={}),u=l[t.uniqueID]||(l[t.uniqueID]={}),(s=u[r])&&s[0]===W&&s[1]===o)return c[2]=s[2];if(u[r]=c,c[2]=e(t,n,a))return!0}}}function h(e){return e.length>1?function(t,n,r){for(var i=e.length;i--;)if(!e[i](t,n,r))return!1;return!0}:e[0]}function g(e,n,r){for(var i=0,o=n.length;i<o;i++)t(e,n[i],r);return r}function m(e,t,n,r,i){for(var o,a=[],s=0,u=e.length,l=null!=t;s<u;s++)(o=e[s])&&(n&&!n(o,r,i)||(a.push(o),l&&t.push(s)));return a}function y(e,t,n,i,o,a){return i&&!i[P]&&(i=y(i)),o&&!o[P]&&(o=y(o,a)),r(function(r,a,s,u){var l,c,f,d=[],p=[],h=a.length,y=r||g(t||\"*\",s.nodeType?[s]:s,[]),v=!e||!r&&t?y:m(y,d,e,s,u),x=n?o||(r?e:h||i)?[]:a:v;if(n&&n(v,x,s,u),i)for(l=m(x,p),i(l,[],s,u),c=l.length;c--;)(f=l[c])&&(x[p[c]]=!(v[p[c]]=f));if(r){if(o||e){if(o){for(l=[],c=x.length;c--;)(f=x[c])&&l.push(v[c]=f);o(null,x=[],l,u)}for(c=x.length;c--;)(f=x[c])&&(l=o?ee(r,f):d[c])>-1&&(r[l]=!(a[l]=f))}}else x=m(x===a?x.splice(h,x.length):x),o?o(null,a,x,u):Q.apply(a,x)})}function v(e){for(var t,n,r,i=e.length,o=T.relative[e[0].type],a=o||T.relative[\" \"],s=o?1:0,u=p(function(e){return e===t},a,!0),l=p(function(e){return ee(t,e)>-1},a,!0),c=[function(e,n,r){var i=!o&&(r||n!==A)||((t=n).nodeType?u(e,n,r):l(e,n,r));return t=null,i}];s<i;s++)if(n=T.relative[e[s].type])c=[p(h(c),n)];else{if(n=T.filter[e[s].type].apply(null,e[s].matches),n[P]){for(r=++s;r<i&&!T.relative[e[r].type];r++);return y(s>1&&h(c),s>1&&d(e.slice(0,s-1).concat({value:\" \"===e[s-2].type?\"*\":\"\"})).replace(se,\"$1\"),n,s<r&&v(e.slice(s,r)),r<i&&v(e=e.slice(r)),r<i&&d(e))}c.push(n)}return h(c)}function x(e,n){var i=n.length>0,o=e.length>0,a=function(r,a,s,u,l){var c,f,d,p=0,h=\"0\",g=r&&[],y=[],v=A,x=r||o&&T.find.TAG(\"*\",l),b=W+=null==v?1:Math.random()||.1,w=x.length;for(l&&(A=a===H||a||l);h!==w&&null!=(c=x[h]);h++){if(o&&c){for(f=0,a||c.ownerDocument===H||(L(c),s=!_);d=e[f++];)if(d(c,a||H,s)){u.push(c);break}l&&(W=b)}i&&((c=!d&&c)&&p--,r&&g.push(c))}if(p+=h,i&&h!==p){for(f=0;d=n[f++];)d(g,y,a,s);if(r){if(p>0)for(;h--;)g[h]||y[h]||(y[h]=G.call(u));y=m(y)}Q.apply(u,y),l&&!r&&y.length>0&&p+n.length>1&&t.uniqueSort(u)}return l&&(W=b,A=v),g};return i?r(a):a}var b,w,T,C,E,N,k,S,A,D,j,L,H,q,_,F,M,O,R,P=\"sizzle\"+1*new Date,B=e.document,W=0,I=0,$=n(),z=n(),X=n(),U=function(e,t){return e===t&&(j=!0),0},V=1<<31,Y={}.hasOwnProperty,J=[],G=J.pop,K=J.push,Q=J.push,Z=J.slice,ee=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},te=\"checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped\",ne=\"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",re=\"(?:\\\\\\\\.|[\\\\w-]|[^\\\\x00-\\\\xa0])+\",ie=\"\\\\[\"+ne+\"*(\"+re+\")(?:\"+ne+\"*([*^$|!~]?=)\"+ne+\"*(?:'((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\"|(\"+re+\"))|)\"+ne+\"*\\\\]\",oe=\":(\"+re+\")(?:\\\\((('((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\")|((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\"+ie+\")*)|.*)\\\\)|)\",ae=new RegExp(ne+\"+\",\"g\"),se=new RegExp(\"^\"+ne+\"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\"+ne+\"+$\",\"g\"),ue=new RegExp(\"^\"+ne+\"*,\"+ne+\"*\"),le=new RegExp(\"^\"+ne+\"*([>+~]|\"+ne+\")\"+ne+\"*\"),ce=new RegExp(\"=\"+ne+\"*([^\\\\]'\\\"]*?)\"+ne+\"*\\\\]\",\"g\"),fe=new RegExp(oe),de=new RegExp(\"^\"+re+\"$\"),pe={ID:new RegExp(\"^#(\"+re+\")\"),CLASS:new RegExp(\"^\\\\.(\"+re+\")\"),TAG:new RegExp(\"^(\"+re+\"|[*])\"),ATTR:new RegExp(\"^\"+ie),PSEUDO:new RegExp(\"^\"+oe),CHILD:new RegExp(\"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\"+ne+\"*(even|odd|(([+-]|)(\\\\d*)n|)\"+ne+\"*(?:([+-]|)\"+ne+\"*(\\\\d+)|))\"+ne+\"*\\\\)|)\",\"i\"),bool:new RegExp(\"^(?:\"+te+\")$\",\"i\"),needsContext:new RegExp(\"^\"+ne+\"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\"+ne+\"*((?:-\\\\d)?\\\\d*)\"+ne+\"*\\\\)|)(?=[^-]|$)\",\"i\")},he=/^(?:input|select|textarea|button)$/i,ge=/^h\\d$/i,me=/^[^{]+\\{\\s*\\[native \\w/,ye=/^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,ve=/[+~]/,xe=/'|\\\\/g,be=new RegExp(\"\\\\\\\\([\\\\da-f]{1,6}\"+ne+\"?|(\"+ne+\")|.)\",\"ig\"),we=function(e,t,n){var r=\"0x\"+t-65536;return r!==r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},Te=function(){L()};try{Q.apply(J=Z.call(B.childNodes),B.childNodes),J[B.childNodes.length].nodeType}catch(Ce){Q={apply:J.length?function(e,t){K.apply(e,Z.call(t))}:function(e,t){for(var n=e.length,r=0;e[n++]=t[r++];);e.length=n-1}}}w=t.support={},E=t.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return!!t&&\"HTML\"!==t.nodeName},L=t.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:B;return r!==H&&9===r.nodeType&&r.documentElement?(H=r,q=H.documentElement,_=!E(H),(n=H.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener(\"unload\",Te,!1):n.attachEvent&&n.attachEvent(\"onunload\",Te)),w.attributes=i(function(e){return e.className=\"i\",!e.getAttribute(\"className\")}),w.getElementsByTagName=i(function(e){return e.appendChild(H.createComment(\"\")),!e.getElementsByTagName(\"*\").length}),w.getElementsByClassName=me.test(H.getElementsByClassName),w.getById=i(function(e){return q.appendChild(e).id=P,!H.getElementsByName||!H.getElementsByName(P).length}),w.getById?(T.find.ID=function(e,t){if(\"undefined\"!=typeof t.getElementById&&_){var n=t.getElementById(e);return n?[n]:[]}},T.filter.ID=function(e){var t=e.replace(be,we);return function(e){return e.getAttribute(\"id\")===t}}):(delete T.find.ID,T.filter.ID=function(e){var t=e.replace(be,we);return function(e){var n=\"undefined\"!=typeof e.getAttributeNode&&e.getAttributeNode(\"id\");return n&&n.value===t}}),T.find.TAG=w.getElementsByTagName?function(e,t){return\"undefined\"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):w.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if(\"*\"===e){for(;n=o[i++];)1===n.nodeType&&r.push(n);return r}return o},T.find.CLASS=w.getElementsByClassName&&function(e,t){if(\"undefined\"!=typeof t.getElementsByClassName&&_)return t.getElementsByClassName(e)},M=[],F=[],(w.qsa=me.test(H.querySelectorAll))&&(i(function(e){q.appendChild(e).innerHTML=\"<a id='\"+P+\"'></a><select id='\"+P+\"-\\r\\\\' msallowcapture=''><option selected=''></option></select>\",e.querySelectorAll(\"[msallowcapture^='']\").length&&F.push(\"[*^$]=\"+ne+\"*(?:''|\\\"\\\")\"),e.querySelectorAll(\"[selected]\").length||F.push(\"\\\\[\"+ne+\"*(?:value|\"+te+\")\"),e.querySelectorAll(\"[id~=\"+P+\"-]\").length||F.push(\"~=\"),e.querySelectorAll(\":checked\").length||F.push(\":checked\"),e.querySelectorAll(\"a#\"+P+\"+*\").length||F.push(\".#.+[+~]\")}),i(function(e){var t=H.createElement(\"input\");t.setAttribute(\"type\",\"hidden\"),e.appendChild(t).setAttribute(\"name\",\"D\"),e.querySelectorAll(\"[name=d]\").length&&F.push(\"name\"+ne+\"*[*^$|!~]?=\"),e.querySelectorAll(\":enabled\").length||F.push(\":enabled\",\":disabled\"),e.querySelectorAll(\"*,:x\"),F.push(\",.*:\")})),(w.matchesSelector=me.test(O=q.matches||q.webkitMatchesSelector||q.mozMatchesSelector||q.oMatchesSelector||q.msMatchesSelector))&&i(function(e){w.disconnectedMatch=O.call(e,\"div\"),O.call(e,\"[s!='']:x\"),M.push(\"!=\",oe)}),F=F.length&&new RegExp(F.join(\"|\")),M=M.length&&new RegExp(M.join(\"|\")),t=me.test(q.compareDocumentPosition),R=t||me.test(q.contains)?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)for(;t=t.parentNode;)if(t===e)return!0;return!1},U=t?function(e,t){if(e===t)return j=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n?n:(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1,1&n||!w.sortDetached&&t.compareDocumentPosition(e)===n?e===H||e.ownerDocument===B&&R(B,e)?-1:t===H||t.ownerDocument===B&&R(B,t)?1:D?ee(D,e)-ee(D,t):0:4&n?-1:1)}:function(e,t){if(e===t)return j=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,s=[e],u=[t];if(!i||!o)return e===H?-1:t===H?1:i?-1:o?1:D?ee(D,e)-ee(D,t):0;if(i===o)return a(e,t);for(n=e;n=n.parentNode;)s.unshift(n);for(n=t;n=n.parentNode;)u.unshift(n);for(;s[r]===u[r];)r++;return r?a(s[r],u[r]):s[r]===B?-1:u[r]===B?1:0},H):H},t.matches=function(e,n){return t(e,null,null,n)},t.matchesSelector=function(e,n){if((e.ownerDocument||e)!==H&&L(e),n=n.replace(ce,\"='$1']\"),w.matchesSelector&&_&&!X[n+\" \"]&&(!M||!M.test(n))&&(!F||!F.test(n)))try{var r=O.call(e,n);if(r||w.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(i){}return t(n,H,null,[e]).length>0},t.contains=function(e,t){return(e.ownerDocument||e)!==H&&L(e),R(e,t)},t.attr=function(e,t){(e.ownerDocument||e)!==H&&L(e);var n=T.attrHandle[t.toLowerCase()],r=n&&Y.call(T.attrHandle,t.toLowerCase())?n(e,t,!_):void 0;return void 0!==r?r:w.attributes||!_?e.getAttribute(t):(r=e.getAttributeNode(t))&&r.specified?r.value:null},t.error=function(e){throw new Error(\"Syntax error, unrecognized expression: \"+e)},t.uniqueSort=function(e){var t,n=[],r=0,i=0;if(j=!w.detectDuplicates,D=!w.sortStable&&e.slice(0),e.sort(U),j){for(;t=e[i++];)t===e[i]&&(r=n.push(i));for(;r--;)e.splice(n[r],1)}return D=null,e},C=t.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+=C(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r++];)n+=C(t);return n},T=t.selectors={cacheLength:50,createPseudo:r,match:pe,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(be,we),e[3]=(e[3]||e[4]||e[5]||\"\").replace(be,we),\"~=\"===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]||t.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]&&t.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return pe.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||\"\":n&&fe.test(n)&&(t=N(n,!0))&&(t=n.indexOf(\")\",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(be,we).toLowerCase();return\"*\"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=$[e+\" \"];return t||(t=new RegExp(\"(^|\"+ne+\")\"+e+\"(\"+ne+\"|$)\"))&&$(e,function(e){return t.test(\"string\"==typeof e.className&&e.className||\"undefined\"!=typeof e.getAttribute&&e.getAttribute(\"class\")||\"\")})},ATTR:function(e,n,r){return function(i){var o=t.attr(i,e);return null==o?\"!=\"===n:!n||(o+=\"\",\"=\"===n?o===r:\"!=\"===n?o!==r:\"^=\"===n?r&&0===o.indexOf(r):\"*=\"===n?r&&o.indexOf(r)>-1:\"$=\"===n?r&&o.slice(-r.length)===r:\"~=\"===n?(\" \"+o.replace(ae,\" \")+\" \").indexOf(r)>-1:\"|=\"===n&&(o===r||o.slice(0,r.length+1)===r+\"-\"))}},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,u){var l,c,f,d,p,h,g=o!==a?\"nextSibling\":\"previousSibling\",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!u&&!s,x=!1;if(m){if(o){for(;g;){for(d=t;d=d[g];)if(s?d.nodeName.toLowerCase()===y:1===d.nodeType)return!1;h=g=\"only\"===e&&!h&&\"nextSibling\"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){for(d=m,f=d[P]||(d[P]={}),c=f[d.uniqueID]||(f[d.uniqueID]={}),\nl=c[e]||[],p=l[0]===W&&l[1],x=p&&l[2],d=p&&m.childNodes[p];d=++p&&d&&d[g]||(x=p=0)||h.pop();)if(1===d.nodeType&&++x&&d===t){c[e]=[W,p,x];break}}else if(v&&(d=t,f=d[P]||(d[P]={}),c=f[d.uniqueID]||(f[d.uniqueID]={}),l=c[e]||[],p=l[0]===W&&l[1],x=p),x===!1)for(;(d=++p&&d&&d[g]||(x=p=0)||h.pop())&&((s?d.nodeName.toLowerCase()!==y:1!==d.nodeType)||!++x||(v&&(f=d[P]||(d[P]={}),c=f[d.uniqueID]||(f[d.uniqueID]={}),c[e]=[W,x]),d!==t)););return x-=i,x===r||x%r===0&&x/r>=0}}},PSEUDO:function(e,n){var i,o=T.pseudos[e]||T.setFilters[e.toLowerCase()]||t.error(\"unsupported pseudo: \"+e);return o[P]?o(n):o.length>1?(i=[e,e,\"\",n],T.setFilters.hasOwnProperty(e.toLowerCase())?r(function(e,t){for(var r,i=o(e,n),a=i.length;a--;)r=ee(e,i[a]),e[r]=!(t[r]=i[a])}):function(e){return o(e,0,i)}):o}},pseudos:{not:r(function(e){var t=[],n=[],i=k(e.replace(se,\"$1\"));return i[P]?r(function(e,t,n,r){for(var o,a=i(e,null,r,[]),s=e.length;s--;)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,r,o){return t[0]=e,i(t,null,o,n),t[0]=null,!n.pop()}}),has:r(function(e){return function(n){return t(e,n).length>0}}),contains:r(function(e){return e=e.replace(be,we),function(t){return(t.textContent||t.innerText||C(t)).indexOf(e)>-1}}),lang:r(function(e){return de.test(e||\"\")||t.error(\"unsupported lang: \"+e),e=e.replace(be,we).toLowerCase(),function(t){var n;do if(n=_?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===q},focus:function(e){return e===H.activeElement&&(!H.hasFocus||H.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.nodeType<6)return!1;return!0},parent:function(e){return!T.pseudos.empty(e)},header:function(e){return ge.test(e.nodeName)},input:function(e){return he.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\"))||\"text\"===t.toLowerCase())},first:l(function(){return[0]}),last:l(function(e,t){return[t-1]}),eq:l(function(e,t,n){return[n<0?n+t:n]}),even:l(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:l(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:l(function(e,t,n){for(var r=n<0?n+t:n;--r>=0;)e.push(r);return e}),gt:l(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}},T.pseudos.nth=T.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})T.pseudos[b]=s(b);for(b in{submit:!0,reset:!0})T.pseudos[b]=u(b);return f.prototype=T.filters=T.pseudos,T.setFilters=new f,N=t.tokenize=function(e,n){var r,i,o,a,s,u,l,c=z[e+\" \"];if(c)return n?0:c.slice(0);for(s=e,u=[],l=T.preFilter;s;){r&&!(i=ue.exec(s))||(i&&(s=s.slice(i[0].length)||s),u.push(o=[])),r=!1,(i=le.exec(s))&&(r=i.shift(),o.push({value:r,type:i[0].replace(se,\" \")}),s=s.slice(r.length));for(a in T.filter)!(i=pe[a].exec(s))||l[a]&&!(i=l[a](i))||(r=i.shift(),o.push({value:r,type:a,matches:i}),s=s.slice(r.length));if(!r)break}return n?s.length:s?t.error(e):z(e,u).slice(0)},k=t.compile=function(e,t){var n,r=[],i=[],o=X[e+\" \"];if(!o){for(t||(t=N(e)),n=t.length;n--;)o=v(t[n]),o[P]?r.push(o):i.push(o);o=X(e,x(i,r)),o.selector=e}return o},S=t.select=function(e,t,n,r){var i,o,a,s,u,l=\"function\"==typeof e&&e,f=!r&&N(e=l.selector||e);if(n=n||[],1===f.length){if(o=f[0]=f[0].slice(0),o.length>2&&\"ID\"===(a=o[0]).type&&w.getById&&9===t.nodeType&&_&&T.relative[o[1].type]){if(t=(T.find.ID(a.matches[0].replace(be,we),t)||[])[0],!t)return n;l&&(t=t.parentNode),e=e.slice(o.shift().value.length)}for(i=pe.needsContext.test(e)?0:o.length;i--&&(a=o[i],!T.relative[s=a.type]);)if((u=T.find[s])&&(r=u(a.matches[0].replace(be,we),ve.test(o[0].type)&&c(t.parentNode)||t))){if(o.splice(i,1),e=r.length&&d(o),!e)return Q.apply(n,r),n;break}}return(l||k(e,f))(r,t,!_,n,!t||ve.test(e)&&c(t.parentNode)||t),n},w.sortStable=P.split(\"\").sort(U).join(\"\")===P,w.detectDuplicates=!!j,L(),w.sortDetached=i(function(e){return 1&e.compareDocumentPosition(H.createElement(\"div\"))}),i(function(e){return e.innerHTML=\"<a href='#'></a>\",\"#\"===e.firstChild.getAttribute(\"href\")})||o(\"type|href|height|width\",function(e,t,n){if(!n)return e.getAttribute(t,\"type\"===t.toLowerCase()?1:2)}),w.attributes&&i(function(e){return e.innerHTML=\"<input/>\",e.firstChild.setAttribute(\"value\",\"\"),\"\"===e.firstChild.getAttribute(\"value\")})||o(\"value\",function(e,t,n){if(!n&&\"input\"===e.nodeName.toLowerCase())return e.defaultValue}),i(function(e){return null==e.getAttribute(\"disabled\")})||o(te,function(e,t,n){var r;if(!n)return e[t]===!0?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),t}(e);pe.find=ve,pe.expr=ve.selectors,pe.expr[\":\"]=pe.expr.pseudos,pe.uniqueSort=pe.unique=ve.uniqueSort,pe.text=ve.getText,pe.isXMLDoc=ve.isXML,pe.contains=ve.contains;var xe=function(e,t,n){for(var r=[],i=void 0!==n;(e=e[t])&&9!==e.nodeType;)if(1===e.nodeType){if(i&&pe(e).is(n))break;r.push(e)}return r},be=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},we=pe.expr.match.needsContext,Te=/^<([\\w-]+)\\s*\\/?>(?:<\\/\\1>|)$/,Ce=/^.[^:#\\[\\.,]*$/;pe.filter=function(e,t,n){var r=t[0];return n&&(e=\":not(\"+e+\")\"),1===t.length&&1===r.nodeType?pe.find.matchesSelector(r,e)?[r]:[]:pe.find.matches(e,pe.grep(t,function(e){return 1===e.nodeType}))},pe.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if(\"string\"!=typeof e)return this.pushStack(pe(e).filter(function(){for(t=0;t<i;t++)if(pe.contains(r[t],this))return!0}));for(t=0;t<i;t++)pe.find(e,r[t],n);return n=this.pushStack(i>1?pe.unique(n):n),n.selector=this.selector?this.selector+\" \"+e:e,n},filter:function(e){return this.pushStack(r(this,e||[],!1))},not:function(e){return this.pushStack(r(this,e||[],!0))},is:function(e){return!!r(this,\"string\"==typeof e&&we.test(e)?pe(e):e||[],!1).length}});var Ee,Ne=/^(?:\\s*(<[\\w\\W]+>)[^>]*|#([\\w-]*))$/,ke=pe.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||Ee,\"string\"==typeof e){if(r=\"<\"===e.charAt(0)&&\">\"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:Ne.exec(e),!r||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof pe?t[0]:t,pe.merge(this,pe.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:re,!0)),Te.test(r[1])&&pe.isPlainObject(t))for(r in t)pe.isFunction(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}if(i=re.getElementById(r[2]),i&&i.parentNode){if(i.id!==r[2])return Ee.find(e);this.length=1,this[0]=i}return this.context=re,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):pe.isFunction(e)?\"undefined\"!=typeof n.ready?n.ready(e):e(pe):(void 0!==e.selector&&(this.selector=e.selector,this.context=e.context),pe.makeArray(e,this))};ke.prototype=pe.fn,Ee=pe(re);var Se=/^(?:parents|prev(?:Until|All))/,Ae={children:!0,contents:!0,next:!0,prev:!0};pe.fn.extend({has:function(e){var t,n=pe(e,this),r=n.length;return this.filter(function(){for(t=0;t<r;t++)if(pe.contains(this,n[t]))return!0})},closest:function(e,t){for(var n,r=0,i=this.length,o=[],a=we.test(e)||\"string\"!=typeof e?pe(e,t||this.context):0;r<i;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(n.nodeType<11&&(a?a.index(n)>-1:1===n.nodeType&&pe.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(o.length>1?pe.uniqueSort(o):o)},index:function(e){return e?\"string\"==typeof e?pe.inArray(this[0],pe(e)):pe.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(pe.uniqueSort(pe.merge(this.get(),pe(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),pe.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return xe(e,\"parentNode\")},parentsUntil:function(e,t,n){return xe(e,\"parentNode\",n)},next:function(e){return i(e,\"nextSibling\")},prev:function(e){return i(e,\"previousSibling\")},nextAll:function(e){return xe(e,\"nextSibling\")},prevAll:function(e){return xe(e,\"previousSibling\")},nextUntil:function(e,t,n){return xe(e,\"nextSibling\",n)},prevUntil:function(e,t,n){return xe(e,\"previousSibling\",n)},siblings:function(e){return be((e.parentNode||{}).firstChild,e)},children:function(e){return be(e.firstChild)},contents:function(e){return pe.nodeName(e,\"iframe\")?e.contentDocument||e.contentWindow.document:pe.merge([],e.childNodes)}},function(e,t){pe.fn[e]=function(n,r){var i=pe.map(this,t,n);return\"Until\"!==e.slice(-5)&&(r=n),r&&\"string\"==typeof r&&(i=pe.filter(r,i)),this.length>1&&(Ae[e]||(i=pe.uniqueSort(i)),Se.test(e)&&(i=i.reverse())),this.pushStack(i)}});var De=/\\S+/g;pe.Callbacks=function(e){e=\"string\"==typeof e?o(e):pe.extend({},e);var t,n,r,i,a=[],s=[],u=-1,l=function(){for(i=e.once,r=t=!0;s.length;u=-1)for(n=s.shift();++u<a.length;)a[u].apply(n[0],n[1])===!1&&e.stopOnFalse&&(u=a.length,n=!1);e.memory||(n=!1),t=!1,i&&(a=n?[]:\"\")},c={add:function(){return a&&(n&&!t&&(u=a.length-1,s.push(n)),function r(t){pe.each(t,function(t,n){pe.isFunction(n)?e.unique&&c.has(n)||a.push(n):n&&n.length&&\"string\"!==pe.type(n)&&r(n)})}(arguments),n&&!t&&l()),this},remove:function(){return pe.each(arguments,function(e,t){for(var n;(n=pe.inArray(t,a,n))>-1;)a.splice(n,1),n<=u&&u--}),this},has:function(e){return e?pe.inArray(e,a)>-1:a.length>0},empty:function(){return a&&(a=[]),this},disable:function(){return i=s=[],a=n=\"\",this},disabled:function(){return!a},lock:function(){return i=!0,n||c.disable(),this},locked:function(){return!!i},fireWith:function(e,n){return i||(n=n||[],n=[e,n.slice?n.slice():n],s.push(n),t||l()),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!r}};return c},pe.extend({Deferred:function(e){var t=[[\"resolve\",\"done\",pe.Callbacks(\"once memory\"),\"resolved\"],[\"reject\",\"fail\",pe.Callbacks(\"once memory\"),\"rejected\"],[\"notify\",\"progress\",pe.Callbacks(\"memory\")]],n=\"pending\",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return pe.Deferred(function(n){pe.each(t,function(t,o){var a=pe.isFunction(e[t])&&e[t];i[o[1]](function(){var e=a&&a.apply(this,arguments);e&&pe.isFunction(e.promise)?e.promise().progress(n.notify).done(n.resolve).fail(n.reject):n[o[0]+\"With\"](this===r?n.promise():this,a?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?pe.extend(e,r):r}},i={};return r.pipe=r.then,pe.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,n,r,i=0,o=ie.call(arguments),a=o.length,s=1!==a||e&&pe.isFunction(e.promise)?a:0,u=1===s?e:pe.Deferred(),l=function(e,n,r){return function(i){n[e]=this,r[e]=arguments.length>1?ie.call(arguments):i,r===t?u.notifyWith(n,r):--s||u.resolveWith(n,r)}};if(a>1)for(t=new Array(a),n=new Array(a),r=new Array(a);i<a;i++)o[i]&&pe.isFunction(o[i].promise)?o[i].promise().progress(l(i,n,t)).done(l(i,r,o)).fail(u.reject):--s;return s||u.resolveWith(r,o),u.promise()}});var je;pe.fn.ready=function(e){return pe.ready.promise().done(e),this},pe.extend({isReady:!1,readyWait:1,holdReady:function(e){e?pe.readyWait++:pe.ready(!0)},ready:function(e){(e===!0?--pe.readyWait:pe.isReady)||(pe.isReady=!0,e!==!0&&--pe.readyWait>0||(je.resolveWith(re,[pe]),pe.fn.triggerHandler&&(pe(re).triggerHandler(\"ready\"),pe(re).off(\"ready\"))))}}),pe.ready.promise=function(t){if(!je)if(je=pe.Deferred(),\"complete\"===re.readyState||\"loading\"!==re.readyState&&!re.documentElement.doScroll)e.setTimeout(pe.ready);else if(re.addEventListener)re.addEventListener(\"DOMContentLoaded\",s),e.addEventListener(\"load\",s);else{re.attachEvent(\"onreadystatechange\",s),e.attachEvent(\"onload\",s);var n=!1;try{n=null==e.frameElement&&re.documentElement}catch(r){}n&&n.doScroll&&!function i(){if(!pe.isReady){try{n.doScroll(\"left\")}catch(t){return e.setTimeout(i,50)}a(),pe.ready()}}()}return je.promise(t)},pe.ready.promise();var Le;for(Le in pe(fe))break;fe.ownFirst=\"0\"===Le,fe.inlineBlockNeedsLayout=!1,pe(function(){var e,t,n,r;n=re.getElementsByTagName(\"body\")[0],n&&n.style&&(t=re.createElement(\"div\"),r=re.createElement(\"div\"),r.style.cssText=\"position:absolute;border:0;width:0;height:0;top:0;left:-9999px\",n.appendChild(r).appendChild(t),\"undefined\"!=typeof t.style.zoom&&(t.style.cssText=\"display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1\",fe.inlineBlockNeedsLayout=e=3===t.offsetWidth,e&&(n.style.zoom=1)),n.removeChild(r))}),function(){var e=re.createElement(\"div\");fe.deleteExpando=!0;try{delete e.test}catch(t){fe.deleteExpando=!1}e=null}();var He=function(e){var t=pe.noData[(e.nodeName+\" \").toLowerCase()],n=+e.nodeType||1;return(1===n||9===n)&&(!t||t!==!0&&e.getAttribute(\"classid\")===t)},qe=/^(?:\\{[\\w\\W]*\\}|\\[[\\w\\W]*\\])$/,_e=/([A-Z])/g;pe.extend({cache:{},noData:{\"applet \":!0,\"embed \":!0,\"object \":\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"},hasData:function(e){return e=e.nodeType?pe.cache[e[pe.expando]]:e[pe.expando],!!e&&!l(e)},data:function(e,t,n){return c(e,t,n)},removeData:function(e,t){return f(e,t)},_data:function(e,t,n){return c(e,t,n,!0)},_removeData:function(e,t){return f(e,t,!0)}}),pe.fn.extend({data:function(e,t){var n,r,i,o=this[0],a=o&&o.attributes;if(void 0===e){if(this.length&&(i=pe.data(o),1===o.nodeType&&!pe._data(o,\"parsedAttrs\"))){for(n=a.length;n--;)a[n]&&(r=a[n].name,0===r.indexOf(\"data-\")&&(r=pe.camelCase(r.slice(5)),u(o,r,i[r])));pe._data(o,\"parsedAttrs\",!0)}return i}return\"object\"==typeof e?this.each(function(){pe.data(this,e)}):arguments.length>1?this.each(function(){pe.data(this,e,t)}):o?u(o,e,pe.data(o,e)):void 0},removeData:function(e){return this.each(function(){pe.removeData(this,e)})}}),pe.extend({queue:function(e,t,n){var r;if(e)return t=(t||\"fx\")+\"queue\",r=pe._data(e,t),n&&(!r||pe.isArray(n)?r=pe._data(e,t,pe.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||\"fx\";var n=pe.queue(e,t),r=n.length,i=n.shift(),o=pe._queueHooks(e,t),a=function(){pe.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 pe._data(e,n)||pe._data(e,n,{empty:pe.Callbacks(\"once memory\").add(function(){pe._removeData(e,t+\"queue\"),pe._removeData(e,n)})})}}),pe.fn.extend({queue:function(e,t){var n=2;return\"string\"!=typeof e&&(t=e,e=\"fx\",n--),arguments.length<n?pe.queue(this[0],e):void 0===t?this:this.each(function(){var n=pe.queue(this,e,t);pe._queueHooks(this,e),\"fx\"===e&&\"inprogress\"!==n[0]&&pe.dequeue(this,e)})},dequeue:function(e){return this.each(function(){pe.dequeue(this,e)})},clearQueue:function(e){return this.queue(e||\"fx\",[])},promise:function(e,t){var n,r=1,i=pe.Deferred(),o=this,a=this.length,s=function(){--r||i.resolveWith(o,[o])};for(\"string\"!=typeof e&&(t=e,e=void 0),e=e||\"fx\";a--;)n=pe._data(o[a],e+\"queueHooks\"),n&&n.empty&&(r++,n.empty.add(s));return s(),i.promise(t)}}),function(){var e;fe.shrinkWrapBlocks=function(){if(null!=e)return e;e=!1;var t,n,r;return n=re.getElementsByTagName(\"body\")[0],n&&n.style?(t=re.createElement(\"div\"),r=re.createElement(\"div\"),r.style.cssText=\"position:absolute;border:0;width:0;height:0;top:0;left:-9999px\",n.appendChild(r).appendChild(t),\"undefined\"!=typeof t.style.zoom&&(t.style.cssText=\"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:1px;width:1px;zoom:1\",t.appendChild(re.createElement(\"div\")).style.width=\"5px\",e=3!==t.offsetWidth),n.removeChild(r),e):void 0}}();var Fe=/[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/.source,Me=new RegExp(\"^(?:([+-])=|)(\"+Fe+\")([a-z%]*)$\",\"i\"),Oe=[\"Top\",\"Right\",\"Bottom\",\"Left\"],Re=function(e,t){return e=t||e,\"none\"===pe.css(e,\"display\")||!pe.contains(e.ownerDocument,e)},Pe=function(e,t,n,r,i,o,a){var s=0,u=e.length,l=null==n;if(\"object\"===pe.type(n)){i=!0;for(s in n)Pe(e,t,s,n[s],!0,o,a)}else if(void 0!==r&&(i=!0,pe.isFunction(r)||(a=!0),l&&(a?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(pe(e),n)})),t))for(;s<u;s++)t(e[s],n,a?r:r.call(e[s],s,t(e[s],n)));return i?e:l?t.call(e):u?t(e[0],n):o},Be=/^(?:checkbox|radio)$/i,We=/<([\\w:-]+)/,Ie=/^$|\\/(?:java|ecma)script/i,$e=/^\\s+/,ze=\"abbr|article|aside|audio|bdi|canvas|data|datalist|details|dialog|figcaption|figure|footer|header|hgroup|main|mark|meter|nav|output|picture|progress|section|summary|template|time|video\";!function(){var e=re.createElement(\"div\"),t=re.createDocumentFragment(),n=re.createElement(\"input\");e.innerHTML=\"  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>\",fe.leadingWhitespace=3===e.firstChild.nodeType,fe.tbody=!e.getElementsByTagName(\"tbody\").length,fe.htmlSerialize=!!e.getElementsByTagName(\"link\").length,fe.html5Clone=\"<:nav></:nav>\"!==re.createElement(\"nav\").cloneNode(!0).outerHTML,n.type=\"checkbox\",n.checked=!0,t.appendChild(n),fe.appendChecked=n.checked,e.innerHTML=\"<textarea>x</textarea>\",fe.noCloneChecked=!!e.cloneNode(!0).lastChild.defaultValue,t.appendChild(e),n=re.createElement(\"input\"),n.setAttribute(\"type\",\"radio\"),n.setAttribute(\"checked\",\"checked\"),n.setAttribute(\"name\",\"t\"),e.appendChild(n),fe.checkClone=e.cloneNode(!0).cloneNode(!0).lastChild.checked,fe.noCloneEvent=!!e.addEventListener,e[pe.expando]=1,fe.attributes=!e.getAttribute(pe.expando)}();var Xe={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:fe.htmlSerialize?[0,\"\",\"\"]:[1,\"X<div>\",\"</div>\"]};Xe.optgroup=Xe.option,Xe.tbody=Xe.tfoot=Xe.colgroup=Xe.caption=Xe.thead,Xe.th=Xe.td;var Ue=/<|&#?\\w+;/,Ve=/<tbody/i;!function(){var t,n,r=re.createElement(\"div\");for(t in{submit:!0,change:!0,focusin:!0})n=\"on\"+t,(fe[t]=n in e)||(r.setAttribute(n,\"t\"),fe[t]=r.attributes[n].expando===!1);r=null}();var Ye=/^(?:input|select|textarea)$/i,Je=/^key/,Ge=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ke=/^(?:focusinfocus|focusoutblur)$/,Qe=/^([^.]*)(?:\\.(.+)|)/;pe.event={global:{},add:function(e,t,n,r,i){var o,a,s,u,l,c,f,d,p,h,g,m=pe._data(e);if(m){for(n.handler&&(u=n,n=u.handler,i=u.selector),n.guid||(n.guid=pe.guid++),(a=m.events)||(a=m.events={}),(c=m.handle)||(c=m.handle=function(e){return\"undefined\"==typeof pe||e&&pe.event.triggered===e.type?void 0:pe.event.dispatch.apply(c.elem,arguments)},c.elem=e),t=(t||\"\").match(De)||[\"\"],s=t.length;s--;)o=Qe.exec(t[s])||[],p=g=o[1],h=(o[2]||\"\").split(\".\").sort(),p&&(l=pe.event.special[p]||{},p=(i?l.delegateType:l.bindType)||p,l=pe.event.special[p]||{},f=pe.extend({type:p,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&pe.expr.match.needsContext.test(i),namespace:h.join(\".\")},u),(d=a[p])||(d=a[p]=[],d.delegateCount=0,l.setup&&l.setup.call(e,r,h,c)!==!1||(e.addEventListener?e.addEventListener(p,c,!1):e.attachEvent&&e.attachEvent(\"on\"+p,c))),l.add&&(l.add.call(e,f),f.handler.guid||(f.handler.guid=n.guid)),i?d.splice(d.delegateCount++,0,f):d.push(f),pe.event.global[p]=!0);e=null}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,d,p,h,g,m=pe.hasData(e)&&pe._data(e);if(m&&(c=m.events)){for(t=(t||\"\").match(De)||[\"\"],l=t.length;l--;)if(s=Qe.exec(t[l])||[],p=g=s[1],h=(s[2]||\"\").split(\".\").sort(),p){for(f=pe.event.special[p]||{},p=(r?f.delegateType:f.bindType)||p,d=c[p]||[],s=s[2]&&new RegExp(\"(^|\\\\.)\"+h.join(\"\\\\.(?:.*\\\\.|)\")+\"(\\\\.|$)\"),u=o=d.length;o--;)a=d[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&(\"**\"!==r||!a.selector)||(d.splice(o,1),a.selector&&d.delegateCount--,f.remove&&f.remove.call(e,a));u&&!d.length&&(f.teardown&&f.teardown.call(e,h,m.handle)!==!1||pe.removeEvent(e,p,m.handle),delete c[p])}else for(p in c)pe.event.remove(e,p+t[l],n,r,!0);pe.isEmptyObject(c)&&(delete m.handle,pe._removeData(e,\"events\"))}},trigger:function(t,n,r,i){var o,a,s,u,l,c,f,d=[r||re],p=ce.call(t,\"type\")?t.type:t,h=ce.call(t,\"namespace\")?t.namespace.split(\".\"):[];if(s=c=r=r||re,3!==r.nodeType&&8!==r.nodeType&&!Ke.test(p+pe.event.triggered)&&(p.indexOf(\".\")>-1&&(h=p.split(\".\"),p=h.shift(),h.sort()),a=p.indexOf(\":\")<0&&\"on\"+p,t=t[pe.expando]?t:new pe.Event(p,\"object\"==typeof t&&t),t.isTrigger=i?2:3,t.namespace=h.join(\".\"),t.rnamespace=t.namespace?new RegExp(\"(^|\\\\.)\"+h.join(\"\\\\.(?:.*\\\\.|)\")+\"(\\\\.|$)\"):null,t.result=void 0,t.target||(t.target=r),n=null==n?[t]:pe.makeArray(n,[t]),l=pe.event.special[p]||{},i||!l.trigger||l.trigger.apply(r,n)!==!1)){if(!i&&!l.noBubble&&!pe.isWindow(r)){for(u=l.delegateType||p,Ke.test(u+p)||(s=s.parentNode);s;s=s.parentNode)d.push(s),c=s;c===(r.ownerDocument||re)&&d.push(c.defaultView||c.parentWindow||e)}for(f=0;(s=d[f++])&&!t.isPropagationStopped();)t.type=f>1?u:l.bindType||p,o=(pe._data(s,\"events\")||{})[t.type]&&pe._data(s,\"handle\"),o&&o.apply(s,n),o=a&&s[a],o&&o.apply&&He(s)&&(t.result=o.apply(s,n),t.result===!1&&t.preventDefault());if(t.type=p,!i&&!t.isDefaultPrevented()&&(!l._default||l._default.apply(d.pop(),n)===!1)&&He(r)&&a&&r[p]&&!pe.isWindow(r)){c=r[a],c&&(r[a]=null),pe.event.triggered=p;try{r[p]()}catch(g){}pe.event.triggered=void 0,c&&(r[a]=c)}return t.result}},dispatch:function(e){e=pe.event.fix(e);var t,n,r,i,o,a=[],s=ie.call(arguments),u=(pe._data(this,\"events\")||{})[e.type]||[],l=pe.event.special[e.type]||{};if(s[0]=e,e.delegateTarget=this,!l.preDispatch||l.preDispatch.call(this,e)!==!1){for(a=pe.event.handlers.call(this,e,u),t=0;(i=a[t++])&&!e.isPropagationStopped();)for(e.currentTarget=i.elem,n=0;(o=i.handlers[n++])&&!e.isImmediatePropagationStopped();)e.rnamespace&&!e.rnamespace.test(o.namespace)||(e.handleObj=o,e.data=o.data,r=((pe.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,s),void 0!==r&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()));return l.postDispatch&&l.postDispatch.call(this,e),e.result}},handlers:function(e,t){var n,r,i,o,a=[],s=t.delegateCount,u=e.target;if(s&&u.nodeType&&(\"click\"!==e.type||isNaN(e.button)||e.button<1))for(;u!=this;u=u.parentNode||this)if(1===u.nodeType&&(u.disabled!==!0||\"click\"!==e.type)){for(r=[],n=0;n<s;n++)o=t[n],i=o.selector+\" \",void 0===r[i]&&(r[i]=o.needsContext?pe(i,this).index(u)>-1:pe.find(i,this,null,[u]).length),r[i]&&r.push(o);r.length&&a.push({elem:u,handlers:r})}return s<t.length&&a.push({elem:this,handlers:t.slice(s)}),a},fix:function(e){if(e[pe.expando])return e;var t,n,r,i=e.type,o=e,a=this.fixHooks[i];for(a||(this.fixHooks[i]=a=Ge.test(i)?this.mouseHooks:Je.test(i)?this.keyHooks:{}),r=a.props?this.props.concat(a.props):this.props,e=new pe.Event(o),t=r.length;t--;)n=r[t],e[n]=o[n];return e.target||(e.target=o.srcElement||re),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,a.filter?a.filter(e,o):e},props:\"altKey bubbles cancelable ctrlKey currentTarget detail 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,t){var n,r,i,o=t.button,a=t.fromElement;return null==e.pageX&&null!=t.clientX&&(r=e.target.ownerDocument||re,i=r.documentElement,n=r.body,e.pageX=t.clientX+(i&&i.scrollLeft||n&&n.scrollLeft||0)-(i&&i.clientLeft||n&&n.clientLeft||0),e.pageY=t.clientY+(i&&i.scrollTop||n&&n.scrollTop||0)-(i&&i.clientTop||n&&n.clientTop||0)),!e.relatedTarget&&a&&(e.relatedTarget=a===e.target?t.toElement:a),e.which||void 0===o||(e.which=1&o?1:2&o?3:4&o?2:0),e}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==b()&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:\"focusin\"},blur:{trigger:function(){if(this===b()&&this.blur)return this.blur(),!1},delegateType:\"focusout\"},click:{trigger:function(){if(pe.nodeName(this,\"input\")&&\"checkbox\"===this.type&&this.click)return this.click(),!1},_default:function(e){return pe.nodeName(e.target,\"a\")}},beforeunload:{postDispatch:function(e){void 0!==e.result&&e.originalEvent&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n){var r=pe.extend(new pe.Event,n,{type:e,isSimulated:!0});pe.event.trigger(r,null,t),r.isDefaultPrevented()&&n.preventDefault()}},pe.removeEvent=re.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n)}:function(e,t,n){var r=\"on\"+t;e.detachEvent&&(\"undefined\"==typeof e[r]&&(e[r]=null),e.detachEvent(r,n))},pe.Event=function(e,t){return this instanceof pe.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||void 0===e.defaultPrevented&&e.returnValue===!1?v:x):this.type=e,t&&pe.extend(this,t),this.timeStamp=e&&e.timeStamp||pe.now(),void(this[pe.expando]=!0)):new pe.Event(e,t)},pe.Event.prototype={constructor:pe.Event,isDefaultPrevented:x,isPropagationStopped:x,isImmediatePropagationStopped:x,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=v,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=v,e&&!this.isSimulated&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){var e=this.originalEvent;this.isImmediatePropagationStopped=v,e&&e.stopImmediatePropagation&&e.stopImmediatePropagation(),this.stopPropagation()}},pe.each({mouseenter:\"mouseover\",mouseleave:\"mouseout\",pointerenter:\"pointerover\",pointerleave:\"pointerout\"},function(e,t){pe.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return i&&(i===r||pe.contains(r,i))||(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),fe.submit||(pe.event.special.submit={setup:function(){return!pe.nodeName(this,\"form\")&&void pe.event.add(this,\"click._submit keypress._submit\",function(e){var t=e.target,n=pe.nodeName(t,\"input\")||pe.nodeName(t,\"button\")?pe.prop(t,\"form\"):void 0;n&&!pe._data(n,\"submit\")&&(pe.event.add(n,\"submit._submit\",function(e){e._submitBubble=!0}),pe._data(n,\"submit\",!0))})},postDispatch:function(e){e._submitBubble&&(delete e._submitBubble,this.parentNode&&!e.isTrigger&&pe.event.simulate(\"submit\",this.parentNode,e))},teardown:function(){return!pe.nodeName(this,\"form\")&&void pe.event.remove(this,\"._submit\")}}),fe.change||(pe.event.special.change={setup:function(){return Ye.test(this.nodeName)?(\"checkbox\"!==this.type&&\"radio\"!==this.type||(pe.event.add(this,\"propertychange._change\",function(e){\"checked\"===e.originalEvent.propertyName&&(this._justChanged=!0)}),pe.event.add(this,\"click._change\",function(e){this._justChanged&&!e.isTrigger&&(this._justChanged=!1),pe.event.simulate(\"change\",this,e)})),!1):void pe.event.add(this,\"beforeactivate._change\",function(e){var t=e.target;Ye.test(t.nodeName)&&!pe._data(t,\"change\")&&(pe.event.add(t,\"change._change\",function(e){!this.parentNode||e.isSimulated||e.isTrigger||pe.event.simulate(\"change\",this.parentNode,e)}),pe._data(t,\"change\",!0))})},handle:function(e){var t=e.target;if(this!==t||e.isSimulated||e.isTrigger||\"radio\"!==t.type&&\"checkbox\"!==t.type)return e.handleObj.handler.apply(this,arguments)},teardown:function(){return pe.event.remove(this,\"._change\"),!Ye.test(this.nodeName)}}),fe.focusin||pe.each({focus:\"focusin\",blur:\"focusout\"},function(e,t){var n=function(e){pe.event.simulate(t,e.target,pe.event.fix(e))};pe.event.special[t]={setup:function(){var r=this.ownerDocument||this,i=pe._data(r,t);i||r.addEventListener(e,n,!0),pe._data(r,t,(i||0)+1)},teardown:function(){var r=this.ownerDocument||this,i=pe._data(r,t)-1;i?pe._data(r,t,i):(r.removeEventListener(e,n,!0),pe._removeData(r,t))}}}),pe.fn.extend({on:function(e,t,n,r){return w(this,e,t,n,r)},one:function(e,t,n,r){return w(this,e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,pe(e.delegateTarget).off(r.namespace?r.origType+\".\"+r.namespace:r.origType,r.selector,r.handler),this;if(\"object\"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return t!==!1&&\"function\"!=typeof t||(n=t,t=void 0),n===!1&&(n=x),this.each(function(){pe.event.remove(this,e,n,t)})},trigger:function(e,t){return this.each(function(){pe.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return pe.event.trigger(e,t,n,!0)}});var Ze=/ jQuery\\d+=\"(?:null|\\d+)\"/g,et=new RegExp(\"<(?:\"+ze+\")[\\\\s/>]\",\"i\"),tt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:-]+)[^>]*)\\/>/gi,nt=/<script|<style|<link/i,rt=/checked\\s*(?:[^=]|=\\s*.checked.)/i,it=/^true\\/(.*)/,ot=/^\\s*<!(?:\\[CDATA\\[|--)|(?:\\]\\]|--)>\\s*$/g,at=p(re),st=at.appendChild(re.createElement(\"div\"));pe.extend({htmlPrefilter:function(e){return e.replace(tt,\"<$1></$2>\")},clone:function(e,t,n){var r,i,o,a,s,u=pe.contains(e.ownerDocument,e);if(fe.html5Clone||pe.isXMLDoc(e)||!et.test(\"<\"+e.nodeName+\">\")?o=e.cloneNode(!0):(st.innerHTML=e.outerHTML,st.removeChild(o=st.firstChild)),!(fe.noCloneEvent&&fe.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||pe.isXMLDoc(e)))for(r=h(o),s=h(e),a=0;null!=(i=s[a]);++a)r[a]&&k(i,r[a]);if(t)if(n)for(s=s||h(e),r=r||h(o),a=0;null!=(i=s[a]);a++)N(i,r[a]);else N(e,o);return r=h(o,\"script\"),r.length>0&&g(r,!u&&h(e,\"script\")),r=s=i=null,o},cleanData:function(e,t){for(var n,r,i,o,a=0,s=pe.expando,u=pe.cache,l=fe.attributes,c=pe.event.special;null!=(n=e[a]);a++)if((t||He(n))&&(i=n[s],o=i&&u[i])){if(o.events)for(r in o.events)c[r]?pe.event.remove(n,r):pe.removeEvent(n,r,o.handle);u[i]&&(delete u[i],l||\"undefined\"==typeof n.removeAttribute?n[s]=void 0:n.removeAttribute(s),ne.push(i))}}}),pe.fn.extend({domManip:S,detach:function(e){return A(this,e,!0)},remove:function(e){return A(this,e)},text:function(e){return Pe(this,function(e){return void 0===e?pe.text(this):this.empty().append((this[0]&&this[0].ownerDocument||re).createTextNode(e))},null,e,arguments.length)},append:function(){return S(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=T(this,e);t.appendChild(e)}})},prepend:function(){return S(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=T(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return S(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return S(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++){for(1===e.nodeType&&pe.cleanData(h(e,!1));e.firstChild;)e.removeChild(e.firstChild);e.options&&pe.nodeName(e,\"select\")&&(e.options.length=0)}return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return pe.clone(this,e,t)})},html:function(e){return Pe(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e)return 1===t.nodeType?t.innerHTML.replace(Ze,\"\"):void 0;if(\"string\"==typeof e&&!nt.test(e)&&(fe.htmlSerialize||!et.test(e))&&(fe.leadingWhitespace||!$e.test(e))&&!Xe[(We.exec(e)||[\"\",\"\"])[1].toLowerCase()]){e=pe.htmlPrefilter(e);try{for(;n<r;n++)t=this[n]||{},1===t.nodeType&&(pe.cleanData(h(t,!1)),t.innerHTML=e);t=0}catch(i){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=[];return S(this,arguments,function(t){var n=this.parentNode;pe.inArray(this,e)<0&&(pe.cleanData(h(this)),\nn&&n.replaceChild(t,this))},e)}}),pe.each({appendTo:\"append\",prependTo:\"prepend\",insertBefore:\"before\",insertAfter:\"after\",replaceAll:\"replaceWith\"},function(e,t){pe.fn[e]=function(e){for(var n,r=0,i=[],o=pe(e),a=o.length-1;r<=a;r++)n=r===a?this:this.clone(!0),pe(o[r])[t](n),ae.apply(i,n.get());return this.pushStack(i)}});var ut,lt={HTML:\"block\",BODY:\"block\"},ct=/^margin/,ft=new RegExp(\"^(\"+Fe+\")(?!px)[a-z%]+$\",\"i\"),dt=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},pt=re.documentElement;!function(){function t(){var t,c,f=re.documentElement;f.appendChild(u),l.style.cssText=\"-webkit-box-sizing:border-box;box-sizing:border-box;position:relative;display:block;margin:auto;border:1px;padding:1px;top:1%;width:50%\",n=i=s=!1,r=a=!0,e.getComputedStyle&&(c=e.getComputedStyle(l),n=\"1%\"!==(c||{}).top,s=\"2px\"===(c||{}).marginLeft,i=\"4px\"===(c||{width:\"4px\"}).width,l.style.marginRight=\"50%\",r=\"4px\"===(c||{marginRight:\"4px\"}).marginRight,t=l.appendChild(re.createElement(\"div\")),t.style.cssText=l.style.cssText=\"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0\",t.style.marginRight=t.style.width=\"0\",l.style.width=\"1px\",a=!parseFloat((e.getComputedStyle(t)||{}).marginRight),l.removeChild(t)),l.style.display=\"none\",o=0===l.getClientRects().length,o&&(l.style.display=\"\",l.innerHTML=\"<table><tr><td></td><td>t</td></tr></table>\",t=l.getElementsByTagName(\"td\"),t[0].style.cssText=\"margin:0;border:0;padding:0;display:none\",o=0===t[0].offsetHeight,o&&(t[0].style.display=\"\",t[1].style.display=\"none\",o=0===t[0].offsetHeight)),f.removeChild(u)}var n,r,i,o,a,s,u=re.createElement(\"div\"),l=re.createElement(\"div\");l.style&&(l.style.cssText=\"float:left;opacity:.5\",fe.opacity=\"0.5\"===l.style.opacity,fe.cssFloat=!!l.style.cssFloat,l.style.backgroundClip=\"content-box\",l.cloneNode(!0).style.backgroundClip=\"\",fe.clearCloneStyle=\"content-box\"===l.style.backgroundClip,u=re.createElement(\"div\"),u.style.cssText=\"border:0;width:8px;height:0;top:0;left:-9999px;padding:0;margin-top:1px;position:absolute\",l.innerHTML=\"\",u.appendChild(l),fe.boxSizing=\"\"===l.style.boxSizing||\"\"===l.style.MozBoxSizing||\"\"===l.style.WebkitBoxSizing,pe.extend(fe,{reliableHiddenOffsets:function(){return null==n&&t(),o},boxSizingReliable:function(){return null==n&&t(),i},pixelMarginRight:function(){return null==n&&t(),r},pixelPosition:function(){return null==n&&t(),n},reliableMarginRight:function(){return null==n&&t(),a},reliableMarginLeft:function(){return null==n&&t(),s}}))}();var ht,gt,mt=/^(top|right|bottom|left)$/;e.getComputedStyle?(ht=function(t){var n=t.ownerDocument.defaultView;return n&&n.opener||(n=e),n.getComputedStyle(t)},gt=function(e,t,n){var r,i,o,a,s=e.style;return n=n||ht(e),a=n?n.getPropertyValue(t)||n[t]:void 0,\"\"!==a&&void 0!==a||pe.contains(e.ownerDocument,e)||(a=pe.style(e,t)),n&&!fe.pixelMarginRight()&&ft.test(a)&&ct.test(t)&&(r=s.width,i=s.minWidth,o=s.maxWidth,s.minWidth=s.maxWidth=s.width=a,a=n.width,s.width=r,s.minWidth=i,s.maxWidth=o),void 0===a?a:a+\"\"}):pt.currentStyle&&(ht=function(e){return e.currentStyle},gt=function(e,t,n){var r,i,o,a,s=e.style;return n=n||ht(e),a=n?n[t]:void 0,null==a&&s&&s[t]&&(a=s[t]),ft.test(a)&&!mt.test(t)&&(r=s.left,i=e.runtimeStyle,o=i&&i.left,o&&(i.left=e.currentStyle.left),s.left=\"fontSize\"===t?\"1em\":a,a=s.pixelLeft+\"px\",s.left=r,o&&(i.left=o)),void 0===a?a:a+\"\"||\"auto\"});var yt=/alpha\\([^)]*\\)/i,vt=/opacity\\s*=\\s*([^)]*)/i,xt=/^(none|table(?!-c[ea]).+)/,bt=new RegExp(\"^(\"+Fe+\")(.*)$\",\"i\"),wt={position:\"absolute\",visibility:\"hidden\",display:\"block\"},Tt={letterSpacing:\"0\",fontWeight:\"400\"},Ct=[\"Webkit\",\"O\",\"Moz\",\"ms\"],Et=re.createElement(\"div\").style;pe.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=gt(e,\"opacity\");return\"\"===n?\"1\":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{\"float\":fe.cssFloat?\"cssFloat\":\"styleFloat\"},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=pe.camelCase(t),u=e.style;if(t=pe.cssProps[s]||(pe.cssProps[s]=H(s)||s),a=pe.cssHooks[t]||pe.cssHooks[s],void 0===n)return a&&\"get\"in a&&void 0!==(i=a.get(e,!1,r))?i:u[t];if(o=typeof n,\"string\"===o&&(i=Me.exec(n))&&i[1]&&(n=d(e,t,i),o=\"number\"),null!=n&&n===n&&(\"number\"===o&&(n+=i&&i[3]||(pe.cssNumber[s]?\"\":\"px\")),fe.clearCloneStyle||\"\"!==n||0!==t.indexOf(\"background\")||(u[t]=\"inherit\"),!(a&&\"set\"in a&&void 0===(n=a.set(e,n,r)))))try{u[t]=n}catch(l){}}},css:function(e,t,n,r){var i,o,a,s=pe.camelCase(t);return t=pe.cssProps[s]||(pe.cssProps[s]=H(s)||s),a=pe.cssHooks[t]||pe.cssHooks[s],a&&\"get\"in a&&(o=a.get(e,!0,n)),void 0===o&&(o=gt(e,t,r)),\"normal\"===o&&t in Tt&&(o=Tt[t]),\"\"===n||n?(i=parseFloat(o),n===!0||isFinite(i)?i||0:o):o}}),pe.each([\"height\",\"width\"],function(e,t){pe.cssHooks[t]={get:function(e,n,r){if(n)return xt.test(pe.css(e,\"display\"))&&0===e.offsetWidth?dt(e,wt,function(){return M(e,t,r)}):M(e,t,r)},set:function(e,n,r){var i=r&&ht(e);return _(e,n,r?F(e,t,r,fe.boxSizing&&\"border-box\"===pe.css(e,\"boxSizing\",!1,i),i):0)}}}),fe.opacity||(pe.cssHooks.opacity={get:function(e,t){return vt.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=pe.isNumeric(t)?\"alpha(opacity=\"+100*t+\")\":\"\",o=r&&r.filter||n.filter||\"\";n.zoom=1,(t>=1||\"\"===t)&&\"\"===pe.trim(o.replace(yt,\"\"))&&n.removeAttribute&&(n.removeAttribute(\"filter\"),\"\"===t||r&&!r.filter)||(n.filter=yt.test(o)?o.replace(yt,i):o+\" \"+i)}}),pe.cssHooks.marginRight=L(fe.reliableMarginRight,function(e,t){if(t)return dt(e,{display:\"inline-block\"},gt,[e,\"marginRight\"])}),pe.cssHooks.marginLeft=L(fe.reliableMarginLeft,function(e,t){if(t)return(parseFloat(gt(e,\"marginLeft\"))||(pe.contains(e.ownerDocument,e)?e.getBoundingClientRect().left-dt(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}):0))+\"px\"}),pe.each({margin:\"\",padding:\"\",border:\"Width\"},function(e,t){pe.cssHooks[e+t]={expand:function(n){for(var r=0,i={},o=\"string\"==typeof n?n.split(\" \"):[n];r<4;r++)i[e+Oe[r]+t]=o[r]||o[r-2]||o[0];return i}},ct.test(e)||(pe.cssHooks[e+t].set=_)}),pe.fn.extend({css:function(e,t){return Pe(this,function(e,t,n){var r,i,o={},a=0;if(pe.isArray(t)){for(r=ht(e),i=t.length;a<i;a++)o[t[a]]=pe.css(e,t[a],!1,r);return o}return void 0!==n?pe.style(e,t,n):pe.css(e,t)},e,t,arguments.length>1)},show:function(){return q(this,!0)},hide:function(){return q(this)},toggle:function(e){return\"boolean\"==typeof e?e?this.show():this.hide():this.each(function(){Re(this)?pe(this).show():pe(this).hide()})}}),pe.Tween=O,O.prototype={constructor:O,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||pe.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(pe.cssNumber[n]?\"\":\"px\")},cur:function(){var e=O.propHooks[this.prop];return e&&e.get?e.get(this):O.propHooks._default.get(this)},run:function(e){var t,n=O.propHooks[this.prop];return this.options.duration?this.pos=t=pe.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=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):O.propHooks._default.set(this),this}},O.prototype.init.prototype=O.prototype,O.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=pe.css(e.elem,e.prop,\"\"),t&&\"auto\"!==t?t:0)},set:function(e){pe.fx.step[e.prop]?pe.fx.step[e.prop](e):1!==e.elem.nodeType||null==e.elem.style[pe.cssProps[e.prop]]&&!pe.cssHooks[e.prop]?e.elem[e.prop]=e.now:pe.style(e.elem,e.prop,e.now+e.unit)}}},O.propHooks.scrollTop=O.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},pe.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:\"swing\"},pe.fx=O.prototype.init,pe.fx.step={};var Nt,kt,St=/^(?:toggle|show|hide)$/,At=/queueHooks$/;pe.Animation=pe.extend($,{tweeners:{\"*\":[function(e,t){var n=this.createTween(e,t);return d(n.elem,e,Me.exec(t),n),n}]},tweener:function(e,t){pe.isFunction(e)?(t=e,e=[\"*\"]):e=e.match(De);for(var n,r=0,i=e.length;r<i;r++)n=e[r],$.tweeners[n]=$.tweeners[n]||[],$.tweeners[n].unshift(t)},prefilters:[W],prefilter:function(e,t){t?$.prefilters.unshift(e):$.prefilters.push(e)}}),pe.speed=function(e,t,n){var r=e&&\"object\"==typeof e?pe.extend({},e):{complete:n||!n&&t||pe.isFunction(e)&&e,duration:e,easing:n&&t||t&&!pe.isFunction(t)&&t};return r.duration=pe.fx.off?0:\"number\"==typeof r.duration?r.duration:r.duration in pe.fx.speeds?pe.fx.speeds[r.duration]:pe.fx.speeds._default,null!=r.queue&&r.queue!==!0||(r.queue=\"fx\"),r.old=r.complete,r.complete=function(){pe.isFunction(r.old)&&r.old.call(this),r.queue&&pe.dequeue(this,r.queue)},r},pe.fn.extend({fadeTo:function(e,t,n,r){return this.filter(Re).css(\"opacity\",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=pe.isEmptyObject(e),o=pe.speed(t,n,r),a=function(){var t=$(this,pe.extend({},e),o);(i||pe._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,t,n){var r=function(e){var t=e.stop;delete e.stop,t(n)};return\"string\"!=typeof e&&(n=t,t=e,e=void 0),t&&e!==!1&&this.queue(e||\"fx\",[]),this.each(function(){var t=!0,i=null!=e&&e+\"queueHooks\",o=pe.timers,a=pe._data(this);if(i)a[i]&&a[i].stop&&r(a[i]);else for(i in a)a[i]&&a[i].stop&&At.test(i)&&r(a[i]);for(i=o.length;i--;)o[i].elem!==this||null!=e&&o[i].queue!==e||(o[i].anim.stop(n),t=!1,o.splice(i,1));!t&&n||pe.dequeue(this,e)})},finish:function(e){return e!==!1&&(e=e||\"fx\"),this.each(function(){var t,n=pe._data(this),r=n[e+\"queue\"],i=n[e+\"queueHooks\"],o=pe.timers,a=r?r.length:0;for(n.finish=!0,pe.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;t<a;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}}),pe.each([\"toggle\",\"show\",\"hide\"],function(e,t){var n=pe.fn[t];pe.fn[t]=function(e,r,i){return null==e||\"boolean\"==typeof e?n.apply(this,arguments):this.animate(P(t,!0),e,r,i)}}),pe.each({slideDown:P(\"show\"),slideUp:P(\"hide\"),slideToggle:P(\"toggle\"),fadeIn:{opacity:\"show\"},fadeOut:{opacity:\"hide\"},fadeToggle:{opacity:\"toggle\"}},function(e,t){pe.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),pe.timers=[],pe.fx.tick=function(){var e,t=pe.timers,n=0;for(Nt=pe.now();n<t.length;n++)e=t[n],e()||t[n]!==e||t.splice(n--,1);t.length||pe.fx.stop(),Nt=void 0},pe.fx.timer=function(e){pe.timers.push(e),e()?pe.fx.start():pe.timers.pop()},pe.fx.interval=13,pe.fx.start=function(){kt||(kt=e.setInterval(pe.fx.tick,pe.fx.interval))},pe.fx.stop=function(){e.clearInterval(kt),kt=null},pe.fx.speeds={slow:600,fast:200,_default:400},pe.fn.delay=function(t,n){return t=pe.fx?pe.fx.speeds[t]||t:t,n=n||\"fx\",this.queue(n,function(n,r){var i=e.setTimeout(n,t);r.stop=function(){e.clearTimeout(i)}})},function(){var e,t=re.createElement(\"input\"),n=re.createElement(\"div\"),r=re.createElement(\"select\"),i=r.appendChild(re.createElement(\"option\"));n=re.createElement(\"div\"),n.setAttribute(\"className\",\"t\"),n.innerHTML=\"  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>\",e=n.getElementsByTagName(\"a\")[0],t.setAttribute(\"type\",\"checkbox\"),n.appendChild(t),e=n.getElementsByTagName(\"a\")[0],e.style.cssText=\"top:1px\",fe.getSetAttribute=\"t\"!==n.className,fe.style=/top/.test(e.getAttribute(\"style\")),fe.hrefNormalized=\"/a\"===e.getAttribute(\"href\"),fe.checkOn=!!t.value,fe.optSelected=i.selected,fe.enctype=!!re.createElement(\"form\").enctype,r.disabled=!0,fe.optDisabled=!i.disabled,t=re.createElement(\"input\"),t.setAttribute(\"value\",\"\"),fe.input=\"\"===t.getAttribute(\"value\"),t.value=\"t\",t.setAttribute(\"type\",\"radio\"),fe.radioValue=\"t\"===t.value}();var Dt=/\\r/g,jt=/[\\x20\\t\\r\\n\\f]+/g;pe.fn.extend({val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=pe.isFunction(e),this.each(function(n){var i;1===this.nodeType&&(i=r?e.call(this,n,pe(this).val()):e,null==i?i=\"\":\"number\"==typeof i?i+=\"\":pe.isArray(i)&&(i=pe.map(i,function(e){return null==e?\"\":e+\"\"})),t=pe.valHooks[this.type]||pe.valHooks[this.nodeName.toLowerCase()],t&&\"set\"in t&&void 0!==t.set(this,i,\"value\")||(this.value=i))});if(i)return t=pe.valHooks[i.type]||pe.valHooks[i.nodeName.toLowerCase()],t&&\"get\"in t&&void 0!==(n=t.get(i,\"value\"))?n:(n=i.value,\"string\"==typeof n?n.replace(Dt,\"\"):null==n?\"\":n)}}}),pe.extend({valHooks:{option:{get:function(e){var t=pe.find.attr(e,\"value\");return null!=t?t:pe.trim(pe.text(e)).replace(jt,\" \")}},select:{get:function(e){for(var t,n,r=e.options,i=e.selectedIndex,o=\"select-one\"===e.type||i<0,a=o?null:[],s=o?i+1:r.length,u=i<0?s:o?i:0;u<s;u++)if(n=r[u],(n.selected||u===i)&&(fe.optDisabled?!n.disabled:null===n.getAttribute(\"disabled\"))&&(!n.parentNode.disabled||!pe.nodeName(n.parentNode,\"optgroup\"))){if(t=pe(n).val(),o)return t;a.push(t)}return a},set:function(e,t){for(var n,r,i=e.options,o=pe.makeArray(t),a=i.length;a--;)if(r=i[a],pe.inArray(pe.valHooks.option.get(r),o)>-1)try{r.selected=n=!0}catch(s){r.scrollHeight}else r.selected=!1;return n||(e.selectedIndex=-1),i}}}}),pe.each([\"radio\",\"checkbox\"],function(){pe.valHooks[this]={set:function(e,t){if(pe.isArray(t))return e.checked=pe.inArray(pe(e).val(),t)>-1}},fe.checkOn||(pe.valHooks[this].get=function(e){return null===e.getAttribute(\"value\")?\"on\":e.value})});var Lt,Ht,qt=pe.expr.attrHandle,_t=/^(?:checked|selected)$/i,Ft=fe.getSetAttribute,Mt=fe.input;pe.fn.extend({attr:function(e,t){return Pe(this,pe.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){pe.removeAttr(this,e)})}}),pe.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return\"undefined\"==typeof e.getAttribute?pe.prop(e,t,n):(1===o&&pe.isXMLDoc(e)||(t=t.toLowerCase(),i=pe.attrHooks[t]||(pe.expr.match.bool.test(t)?Ht:Lt)),void 0!==n?null===n?void pe.removeAttr(e,t):i&&\"set\"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+\"\"),n):i&&\"get\"in i&&null!==(r=i.get(e,t))?r:(r=pe.find.attr(e,t),null==r?void 0:r))},attrHooks:{type:{set:function(e,t){if(!fe.radioValue&&\"radio\"===t&&pe.nodeName(e,\"input\")){var n=e.value;return e.setAttribute(\"type\",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(De);if(o&&1===e.nodeType)for(;n=o[i++];)r=pe.propFix[n]||n,pe.expr.match.bool.test(n)?Mt&&Ft||!_t.test(n)?e[r]=!1:e[pe.camelCase(\"default-\"+n)]=e[r]=!1:pe.attr(e,n,\"\"),e.removeAttribute(Ft?n:r)}}),Ht={set:function(e,t,n){return t===!1?pe.removeAttr(e,n):Mt&&Ft||!_t.test(n)?e.setAttribute(!Ft&&pe.propFix[n]||n,n):e[pe.camelCase(\"default-\"+n)]=e[n]=!0,n}},pe.each(pe.expr.match.bool.source.match(/\\w+/g),function(e,t){var n=qt[t]||pe.find.attr;Mt&&Ft||!_t.test(t)?qt[t]=function(e,t,r){var i,o;return r||(o=qt[t],qt[t]=i,i=null!=n(e,t,r)?t.toLowerCase():null,qt[t]=o),i}:qt[t]=function(e,t,n){if(!n)return e[pe.camelCase(\"default-\"+t)]?t.toLowerCase():null}}),Mt&&Ft||(pe.attrHooks.value={set:function(e,t,n){return pe.nodeName(e,\"input\")?void(e.defaultValue=t):Lt&&Lt.set(e,t,n)}}),Ft||(Lt={set:function(e,t,n){var r=e.getAttributeNode(n);if(r||e.setAttributeNode(r=e.ownerDocument.createAttribute(n)),r.value=t+=\"\",\"value\"===n||t===e.getAttribute(n))return t}},qt.id=qt.name=qt.coords=function(e,t,n){var r;if(!n)return(r=e.getAttributeNode(t))&&\"\"!==r.value?r.value:null},pe.valHooks.button={get:function(e,t){var n=e.getAttributeNode(t);if(n&&n.specified)return n.value},set:Lt.set},pe.attrHooks.contenteditable={set:function(e,t,n){Lt.set(e,\"\"!==t&&t,n)}},pe.each([\"width\",\"height\"],function(e,t){pe.attrHooks[t]={set:function(e,n){if(\"\"===n)return e.setAttribute(t,\"auto\"),n}}})),fe.style||(pe.attrHooks.style={get:function(e){return e.style.cssText||void 0},set:function(e,t){return e.style.cssText=t+\"\"}});var Ot=/^(?:input|select|textarea|button|object)$/i,Rt=/^(?:a|area)$/i;pe.fn.extend({prop:function(e,t){return Pe(this,pe.prop,e,t,arguments.length>1)},removeProp:function(e){return e=pe.propFix[e]||e,this.each(function(){try{this[e]=void 0,delete this[e]}catch(t){}})}}),pe.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&pe.isXMLDoc(e)||(t=pe.propFix[t]||t,i=pe.propHooks[t]),void 0!==n?i&&\"set\"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&\"get\"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=pe.find.attr(e,\"tabindex\");return t?parseInt(t,10):Ot.test(e.nodeName)||Rt.test(e.nodeName)&&e.href?0:-1}}},propFix:{\"for\":\"htmlFor\",\"class\":\"className\"}}),fe.hrefNormalized||pe.each([\"href\",\"src\"],function(e,t){pe.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}}),fe.optSelected||(pe.propHooks.selected={get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),pe.each([\"tabIndex\",\"readOnly\",\"maxLength\",\"cellSpacing\",\"cellPadding\",\"rowSpan\",\"colSpan\",\"useMap\",\"frameBorder\",\"contentEditable\"],function(){pe.propFix[this.toLowerCase()]=this}),fe.enctype||(pe.propFix.enctype=\"encoding\");var Pt=/[\\t\\r\\n\\f]/g;pe.fn.extend({addClass:function(e){var t,n,r,i,o,a,s,u=0;if(pe.isFunction(e))return this.each(function(t){pe(this).addClass(e.call(this,t,z(this)))});if(\"string\"==typeof e&&e)for(t=e.match(De)||[];n=this[u++];)if(i=z(n),r=1===n.nodeType&&(\" \"+i+\" \").replace(Pt,\" \")){for(a=0;o=t[a++];)r.indexOf(\" \"+o+\" \")<0&&(r+=o+\" \");s=pe.trim(r),i!==s&&pe.attr(n,\"class\",s)}return this},removeClass:function(e){var t,n,r,i,o,a,s,u=0;if(pe.isFunction(e))return this.each(function(t){pe(this).removeClass(e.call(this,t,z(this)))});if(!arguments.length)return this.attr(\"class\",\"\");if(\"string\"==typeof e&&e)for(t=e.match(De)||[];n=this[u++];)if(i=z(n),r=1===n.nodeType&&(\" \"+i+\" \").replace(Pt,\" \")){for(a=0;o=t[a++];)for(;r.indexOf(\" \"+o+\" \")>-1;)r=r.replace(\" \"+o+\" \",\" \");s=pe.trim(r),i!==s&&pe.attr(n,\"class\",s)}return this},toggleClass:function(e,t){var n=typeof e;return\"boolean\"==typeof t&&\"string\"===n?t?this.addClass(e):this.removeClass(e):pe.isFunction(e)?this.each(function(n){pe(this).toggleClass(e.call(this,n,z(this),t),t)}):this.each(function(){var t,r,i,o;if(\"string\"===n)for(r=0,i=pe(this),o=e.match(De)||[];t=o[r++];)i.hasClass(t)?i.removeClass(t):i.addClass(t);else void 0!==e&&\"boolean\"!==n||(t=z(this),t&&pe._data(this,\"__className__\",t),pe.attr(this,\"class\",t||e===!1?\"\":pe._data(this,\"__className__\")||\"\"))})},hasClass:function(e){var t,n,r=0;for(t=\" \"+e+\" \";n=this[r++];)if(1===n.nodeType&&(\" \"+z(n)+\" \").replace(Pt,\" \").indexOf(t)>-1)return!0;return!1}}),pe.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){pe.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),pe.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}});var Bt=e.location,Wt=pe.now(),It=/\\?/,$t=/(,)|(\\[|{)|(}|])|\"(?:[^\"\\\\\\r\\n]|\\\\[\"\\\\\\/bfnrt]|\\\\u[\\da-fA-F]{4})*\"\\s*:?|true|false|null|-?(?!0\\d)\\d+(?:\\.\\d+|)(?:[eE][+-]?\\d+|)/g;pe.parseJSON=function(t){if(e.JSON&&e.JSON.parse)return e.JSON.parse(t+\"\");var n,r=null,i=pe.trim(t+\"\");return i&&!pe.trim(i.replace($t,function(e,t,i,o){return n&&t&&(r=0),0===r?e:(n=i||t,r+=!o-!i,\"\")}))?Function(\"return \"+i)():pe.error(\"Invalid JSON: \"+t)},pe.parseXML=function(t){var n,r;if(!t||\"string\"!=typeof t)return null;try{e.DOMParser?(r=new e.DOMParser,n=r.parseFromString(t,\"text/xml\")):(n=new e.ActiveXObject(\"Microsoft.XMLDOM\"),n.async=\"false\",n.loadXML(t))}catch(i){n=void 0}return n&&n.documentElement&&!n.getElementsByTagName(\"parsererror\").length||pe.error(\"Invalid XML: \"+t),n};var zt=/#.*$/,Xt=/([?&])_=[^&]*/,Ut=/^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/gm,Vt=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Yt=/^(?:GET|HEAD)$/,Jt=/^\\/\\//,Gt=/^([\\w.+-]+:)(?:\\/\\/(?:[^\\/?#]*@|)([^\\/?#:]*)(?::(\\d+)|)|)/,Kt={},Qt={},Zt=\"*/\".concat(\"*\"),en=Bt.href,tn=Gt.exec(en.toLowerCase())||[];pe.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:en,type:\"GET\",isLocal:Vt.test(tn[1]),global:!0,processData:!0,async:!0,contentType:\"application/x-www-form-urlencoded; charset=UTF-8\",accepts:{\"*\":Zt,text:\"text/plain\",html:\"text/html\",xml:\"application/xml, text/xml\",json:\"application/json, text/javascript\"},contents:{xml:/\\bxml\\b/,html:/\\bhtml/,json:/\\bjson\\b/},responseFields:{xml:\"responseXML\",text:\"responseText\",json:\"responseJSON\"},converters:{\"* text\":String,\"text html\":!0,\"text json\":pe.parseJSON,\"text xml\":pe.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?V(V(e,pe.ajaxSettings),t):V(pe.ajaxSettings,e)},ajaxPrefilter:X(Kt),ajaxTransport:X(Qt),ajax:function(t,n){function r(t,n,r,i){var o,f,v,x,w,C=n;2!==b&&(b=2,u&&e.clearTimeout(u),c=void 0,s=i||\"\",T.readyState=t>0?4:0,o=t>=200&&t<300||304===t,r&&(x=Y(d,T,r)),x=J(d,x,T,o),o?(d.ifModified&&(w=T.getResponseHeader(\"Last-Modified\"),w&&(pe.lastModified[a]=w),w=T.getResponseHeader(\"etag\"),w&&(pe.etag[a]=w)),204===t||\"HEAD\"===d.type?C=\"nocontent\":304===t?C=\"notmodified\":(C=x.state,f=x.data,v=x.error,o=!v)):(v=C,!t&&C||(C=\"error\",t<0&&(t=0))),T.status=t,T.statusText=(n||C)+\"\",o?g.resolveWith(p,[f,C,T]):g.rejectWith(p,[T,C,v]),T.statusCode(y),y=void 0,l&&h.trigger(o?\"ajaxSuccess\":\"ajaxError\",[T,d,o?f:v]),m.fireWith(p,[T,C]),l&&(h.trigger(\"ajaxComplete\",[T,d]),--pe.active||pe.event.trigger(\"ajaxStop\")))}\"object\"==typeof t&&(n=t,t=void 0),n=n||{};var i,o,a,s,u,l,c,f,d=pe.ajaxSetup({},n),p=d.context||d,h=d.context&&(p.nodeType||p.jquery)?pe(p):pe.event,g=pe.Deferred(),m=pe.Callbacks(\"once memory\"),y=d.statusCode||{},v={},x={},b=0,w=\"canceled\",T={readyState:0,getResponseHeader:function(e){var t;if(2===b){if(!f)for(f={};t=Ut.exec(s);)f[t[1].toLowerCase()]=t[2];t=f[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===b?s:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return b||(e=x[n]=x[n]||e,v[e]=t),this},overrideMimeType:function(e){return b||(d.mimeType=e),this},statusCode:function(e){var t;if(e)if(b<2)for(t in e)y[t]=[y[t],e[t]];else T.always(e[T.status]);return this},abort:function(e){var t=e||w;return c&&c.abort(t),r(0,t),this}};if(g.promise(T).complete=m.add,T.success=T.done,T.error=T.fail,d.url=((t||d.url||en)+\"\").replace(zt,\"\").replace(Jt,tn[1]+\"//\"),d.type=n.method||n.type||d.method||d.type,d.dataTypes=pe.trim(d.dataType||\"*\").toLowerCase().match(De)||[\"\"],null==d.crossDomain&&(i=Gt.exec(d.url.toLowerCase()),d.crossDomain=!(!i||i[1]===tn[1]&&i[2]===tn[2]&&(i[3]||(\"http:\"===i[1]?\"80\":\"443\"))===(tn[3]||(\"http:\"===tn[1]?\"80\":\"443\")))),d.data&&d.processData&&\"string\"!=typeof d.data&&(d.data=pe.param(d.data,d.traditional)),U(Kt,d,n,T),2===b)return T;l=pe.event&&d.global,l&&0===pe.active++&&pe.event.trigger(\"ajaxStart\"),d.type=d.type.toUpperCase(),d.hasContent=!Yt.test(d.type),a=d.url,d.hasContent||(d.data&&(a=d.url+=(It.test(a)?\"&\":\"?\")+d.data,delete d.data),d.cache===!1&&(d.url=Xt.test(a)?a.replace(Xt,\"$1_=\"+Wt++):a+(It.test(a)?\"&\":\"?\")+\"_=\"+Wt++)),d.ifModified&&(pe.lastModified[a]&&T.setRequestHeader(\"If-Modified-Since\",pe.lastModified[a]),pe.etag[a]&&T.setRequestHeader(\"If-None-Match\",pe.etag[a])),(d.data&&d.hasContent&&d.contentType!==!1||n.contentType)&&T.setRequestHeader(\"Content-Type\",d.contentType),T.setRequestHeader(\"Accept\",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(\"*\"!==d.dataTypes[0]?\", \"+Zt+\"; q=0.01\":\"\"):d.accepts[\"*\"]);for(o in d.headers)T.setRequestHeader(o,d.headers[o]);if(d.beforeSend&&(d.beforeSend.call(p,T,d)===!1||2===b))return T.abort();w=\"abort\";for(o in{success:1,error:1,complete:1})T[o](d[o]);if(c=U(Qt,d,n,T)){if(T.readyState=1,l&&h.trigger(\"ajaxSend\",[T,d]),2===b)return T;d.async&&d.timeout>0&&(u=e.setTimeout(function(){T.abort(\"timeout\")},d.timeout));try{b=1,c.send(v,r)}catch(C){if(!(b<2))throw C;r(-1,C)}}else r(-1,\"No Transport\");return T},getJSON:function(e,t,n){return pe.get(e,t,n,\"json\")},getScript:function(e,t){return pe.get(e,void 0,t,\"script\")}}),pe.each([\"get\",\"post\"],function(e,t){pe[t]=function(e,n,r,i){return pe.isFunction(n)&&(i=i||r,r=n,n=void 0),pe.ajax(pe.extend({url:e,type:t,dataType:i,data:n,success:r},pe.isPlainObject(e)&&e))}}),pe._evalUrl=function(e){return pe.ajax({url:e,type:\"GET\",dataType:\"script\",cache:!0,async:!1,global:!1,\"throws\":!0})},pe.fn.extend({wrapAll:function(e){if(pe.isFunction(e))return this.each(function(t){pe(this).wrapAll(e.call(this,t))});if(this[0]){var t=pe(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){for(var e=this;e.firstChild&&1===e.firstChild.nodeType;)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return pe.isFunction(e)?this.each(function(t){pe(this).wrapInner(e.call(this,t))}):this.each(function(){var t=pe(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=pe.isFunction(e);return this.each(function(n){pe(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){pe.nodeName(this,\"body\")||pe(this).replaceWith(this.childNodes)}).end()}}),pe.expr.filters.hidden=function(e){return fe.reliableHiddenOffsets()?e.offsetWidth<=0&&e.offsetHeight<=0&&!e.getClientRects().length:K(e)},pe.expr.filters.visible=function(e){return!pe.expr.filters.hidden(e)};var nn=/%20/g,rn=/\\[\\]$/,on=/\\r?\\n/g,an=/^(?:submit|button|image|reset|file)$/i,sn=/^(?:input|select|textarea|keygen)/i;pe.param=function(e,t){var n,r=[],i=function(e,t){t=pe.isFunction(t)?t():null==t?\"\":t,r[r.length]=encodeURIComponent(e)+\"=\"+encodeURIComponent(t)};if(void 0===t&&(t=pe.ajaxSettings&&pe.ajaxSettings.traditional),pe.isArray(e)||e.jquery&&!pe.isPlainObject(e))pe.each(e,function(){i(this.name,this.value)});else for(n in e)Q(n,e[n],t,i);return r.join(\"&\").replace(nn,\"+\")},pe.fn.extend({serialize:function(){return pe.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=pe.prop(this,\"elements\");return e?pe.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!pe(this).is(\":disabled\")&&sn.test(this.nodeName)&&!an.test(e)&&(this.checked||!Be.test(e))}).map(function(e,t){var n=pe(this).val();return null==n?null:pe.isArray(n)?pe.map(n,function(e){return{name:t.name,value:e.replace(on,\"\\r\\n\")}}):{name:t.name,value:n.replace(on,\"\\r\\n\")}}).get()}}),pe.ajaxSettings.xhr=void 0!==e.ActiveXObject?function(){return this.isLocal?ee():re.documentMode>8?Z():/^(get|post|head|put|delete|options)$/i.test(this.type)&&Z()||ee()}:Z;var un=0,ln={},cn=pe.ajaxSettings.xhr();e.attachEvent&&e.attachEvent(\"onunload\",function(){for(var e in ln)ln[e](void 0,!0)}),fe.cors=!!cn&&\"withCredentials\"in cn,cn=fe.ajax=!!cn,cn&&pe.ajaxTransport(function(t){if(!t.crossDomain||fe.cors){var n;return{send:function(r,i){var o,a=t.xhr(),s=++un;if(a.open(t.type,t.url,t.async,t.username,t.password),t.xhrFields)for(o in t.xhrFields)a[o]=t.xhrFields[o];t.mimeType&&a.overrideMimeType&&a.overrideMimeType(t.mimeType),t.crossDomain||r[\"X-Requested-With\"]||(r[\"X-Requested-With\"]=\"XMLHttpRequest\");for(o in r)void 0!==r[o]&&a.setRequestHeader(o,r[o]+\"\");a.send(t.hasContent&&t.data||null),n=function(e,r){var o,u,l;if(n&&(r||4===a.readyState))if(delete ln[s],n=void 0,a.onreadystatechange=pe.noop,r)4!==a.readyState&&a.abort();else{l={},o=a.status,\"string\"==typeof a.responseText&&(l.text=a.responseText);try{u=a.statusText}catch(c){u=\"\"}o||!t.isLocal||t.crossDomain?1223===o&&(o=204):o=l.text?200:404}l&&i(o,u,l,a.getAllResponseHeaders())},t.async?4===a.readyState?e.setTimeout(n):a.onreadystatechange=ln[s]=n:n()},abort:function(){n&&n(void 0,!0)}}}}),pe.ajaxSetup({accepts:{script:\"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"},contents:{script:/\\b(?:java|ecma)script\\b/},converters:{\"text script\":function(e){return pe.globalEval(e),e}}}),pe.ajaxPrefilter(\"script\",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type=\"GET\",e.global=!1)}),pe.ajaxTransport(\"script\",function(e){if(e.crossDomain){var t,n=re.head||pe(\"head\")[0]||re.documentElement;return{send:function(r,i){t=re.createElement(\"script\"),t.async=!0,e.scriptCharset&&(t.charset=e.scriptCharset),t.src=e.url,t.onload=t.onreadystatechange=function(e,n){(n||!t.readyState||/loaded|complete/.test(t.readyState))&&(t.onload=t.onreadystatechange=null,t.parentNode&&t.parentNode.removeChild(t),t=null,n||i(200,\"success\"))},n.insertBefore(t,n.firstChild)},abort:function(){t&&t.onload(void 0,!0)}}}});var fn=[],dn=/(=)\\?(?=&|$)|\\?\\?/;pe.ajaxSetup({jsonp:\"callback\",jsonpCallback:function(){var e=fn.pop()||pe.expando+\"_\"+Wt++;return this[e]=!0,e}}),pe.ajaxPrefilter(\"json jsonp\",function(t,n,r){var i,o,a,s=t.jsonp!==!1&&(dn.test(t.url)?\"url\":\"string\"==typeof t.data&&0===(t.contentType||\"\").indexOf(\"application/x-www-form-urlencoded\")&&dn.test(t.data)&&\"data\");if(s||\"jsonp\"===t.dataTypes[0])return i=t.jsonpCallback=pe.isFunction(t.jsonpCallback)?t.jsonpCallback():t.jsonpCallback,s?t[s]=t[s].replace(dn,\"$1\"+i):t.jsonp!==!1&&(t.url+=(It.test(t.url)?\"&\":\"?\")+t.jsonp+\"=\"+i),t.converters[\"script json\"]=function(){return a||pe.error(i+\" was not called\"),a[0]},t.dataTypes[0]=\"json\",o=e[i],e[i]=function(){a=arguments},r.always(function(){void 0===o?pe(e).removeProp(i):e[i]=o,t[i]&&(t.jsonpCallback=n.jsonpCallback,fn.push(i)),a&&pe.isFunction(o)&&o(a[0]),a=o=void 0}),\"script\"}),pe.parseHTML=function(e,t,n){if(!e||\"string\"!=typeof e)return null;\"boolean\"==typeof t&&(n=t,t=!1),t=t||re;var r=Te.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=y([e],t,i),i&&i.length&&pe(i).remove(),pe.merge([],r.childNodes))};var pn=pe.fn.load;return pe.fn.load=function(e,t,n){if(\"string\"!=typeof e&&pn)return pn.apply(this,arguments);var r,i,o,a=this,s=e.indexOf(\" \");return s>-1&&(r=pe.trim(e.slice(s,e.length)),e=e.slice(0,s)),pe.isFunction(t)?(n=t,t=void 0):t&&\"object\"==typeof t&&(i=\"POST\"),a.length>0&&pe.ajax({url:e,type:i||\"GET\",dataType:\"html\",data:t}).done(function(e){o=arguments,a.html(r?pe(\"<div>\").append(pe.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},pe.each([\"ajaxStart\",\"ajaxStop\",\"ajaxComplete\",\"ajaxError\",\"ajaxSuccess\",\"ajaxSend\"],function(e,t){pe.fn[t]=function(e){return this.on(t,e)}}),pe.expr.filters.animated=function(e){return pe.grep(pe.timers,function(t){return e===t.elem}).length},pe.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l,c=pe.css(e,\"position\"),f=pe(e),d={};\"static\"===c&&(e.style.position=\"relative\"),s=f.offset(),o=pe.css(e,\"top\"),u=pe.css(e,\"left\"),l=(\"absolute\"===c||\"fixed\"===c)&&pe.inArray(\"auto\",[o,u])>-1,l?(r=f.position(),a=r.top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),pe.isFunction(t)&&(t=t.call(e,n,pe.extend({},s))),null!=t.top&&(d.top=t.top-s.top+a),null!=t.left&&(d.left=t.left-s.left+i),\"using\"in t?t.using.call(e,d):f.css(d)}},pe.fn.extend({offset:function(e){if(arguments.length)return void 0===e?this:this.each(function(t){pe.offset.setOffset(this,e,t)});var t,n,r={top:0,left:0},i=this[0],o=i&&i.ownerDocument;if(o)return t=o.documentElement,pe.contains(t,i)?(\"undefined\"!=typeof i.getBoundingClientRect&&(r=i.getBoundingClientRect()),n=te(o),{top:r.top+(n.pageYOffset||t.scrollTop)-(t.clientTop||0),left:r.left+(n.pageXOffset||t.scrollLeft)-(t.clientLeft||0)}):r},position:function(){if(this[0]){var e,t,n={top:0,left:0},r=this[0];return\"fixed\"===pe.css(r,\"position\")?t=r.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),pe.nodeName(e[0],\"html\")||(n=e.offset()),n.top+=pe.css(e[0],\"borderTopWidth\",!0),n.left+=pe.css(e[0],\"borderLeftWidth\",!0)),{top:t.top-n.top-pe.css(r,\"marginTop\",!0),left:t.left-n.left-pe.css(r,\"marginLeft\",!0)}}},offsetParent:function(){return this.map(function(){\nfor(var e=this.offsetParent;e&&!pe.nodeName(e,\"html\")&&\"static\"===pe.css(e,\"position\");)e=e.offsetParent;return e||pt})}}),pe.each({scrollLeft:\"pageXOffset\",scrollTop:\"pageYOffset\"},function(e,t){var n=/Y/.test(t);pe.fn[e]=function(r){return Pe(this,function(e,r,i){var o=te(e);return void 0===i?o?t in o?o[t]:o.document.documentElement[r]:e[r]:void(o?o.scrollTo(n?pe(o).scrollLeft():i,n?i:pe(o).scrollTop()):e[r]=i)},e,r,arguments.length,null)}}),pe.each([\"top\",\"left\"],function(e,t){pe.cssHooks[t]=L(fe.pixelPosition,function(e,n){if(n)return n=gt(e,t),ft.test(n)?pe(e).position()[t]+\"px\":n})}),pe.each({Height:\"height\",Width:\"width\"},function(e,t){pe.each({padding:\"inner\"+e,content:t,\"\":\"outer\"+e},function(n,r){pe.fn[r]=function(r,i){var o=arguments.length&&(n||\"boolean\"!=typeof r),a=n||(r===!0||i===!0?\"margin\":\"border\");return Pe(this,function(t,n,r){var i;return pe.isWindow(t)?t.document.documentElement[\"client\"+e]:9===t.nodeType?(i=t.documentElement,Math.max(t.body[\"scroll\"+e],i[\"scroll\"+e],t.body[\"offset\"+e],i[\"offset\"+e],i[\"client\"+e])):void 0===r?pe.css(t,n,a):pe.style(t,n,r,a)},t,o?r:void 0,o,null)}})}),pe.fn.extend({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)}}),pe.fn.size=function(){return this.length},pe.fn.andSelf=pe.fn.addBack,layui.define(function(e){layui.$=pe,e(\"jquery\",pe)}),pe});"
  },
  {
    "path": "open-layui-web/src/main/view/static/layui/lay/modules/laydate.js",
    "content": "/** layui-v2.3.0-rc1 MIT License By https://www.layui.com */\n ;!function(){\"use strict\";var e=window.layui&&layui.define,t={getPath:function(){var e=document.currentScript?document.currentScript.src:function(){for(var e,t=document.scripts,n=t.length-1,a=n;a>0;a--)if(\"interactive\"===t[a].readyState){e=t[a].src;break}return e||t[n].src}();return e.substring(0,e.lastIndexOf(\"/\")+1)}(),getStyle:function(e,t){var n=e.currentStyle?e.currentStyle:window.getComputedStyle(e,null);return n[n.getPropertyValue?\"getPropertyValue\":\"getAttribute\"](t)},link:function(e,a,i){if(n.path){var r=document.getElementsByTagName(\"head\")[0],o=document.createElement(\"link\");\"string\"==typeof a&&(i=a);var s=(i||e).replace(/\\.|\\//g,\"\"),l=\"layuicss-\"+s,d=0;o.rel=\"stylesheet\",o.href=n.path+e,o.id=l,document.getElementById(l)||r.appendChild(o),\"function\"==typeof a&&!function c(){return++d>80?window.console&&console.error(\"laydate.css: Invalid\"):void(1989===parseInt(t.getStyle(document.getElementById(l),\"width\"))?a():setTimeout(c,100))}()}}},n={v:\"5.0.9\",config:{},index:window.laydate&&window.laydate.v?1e5:0,path:t.getPath,set:function(e){var t=this;return t.config=w.extend({},t.config,e),t},ready:function(a){var i=\"laydate\",r=\"\",o=(e?\"modules/laydate/\":\"theme/\")+\"default/laydate.css?v=\"+n.v+r;return e?layui.addcss(o,a,i):t.link(o,a,i),this}},a=function(){var e=this;return{hint:function(t){e.hint.call(e,t)},config:e.config}},i=\"laydate\",r=\".layui-laydate\",o=\"layui-this\",s=\"laydate-disabled\",l=\"开始日期超出了结束日期<br>建议重新选择\",d=[100,2e5],c=\"layui-laydate-static\",m=\"layui-laydate-list\",u=\"laydate-selected\",h=\"layui-laydate-hint\",y=\"laydate-day-prev\",f=\"laydate-day-next\",p=\"layui-laydate-footer\",g=\".laydate-btns-confirm\",v=\"laydate-time-text\",D=\".laydate-btns-time\",T=function(e){var t=this;t.index=++n.index,t.config=w.extend({},t.config,n.config,e),n.ready(function(){t.init()})},w=function(e){return new C(e)},C=function(e){for(var t=0,n=\"object\"==typeof e?[e]:(this.selector=e,document.querySelectorAll(e||null));t<n.length;t++)this.push(n[t])};C.prototype=[],C.prototype.constructor=C,w.extend=function(){var e=1,t=arguments,n=function(e,t){e=e||(t.constructor===Array?[]:{});for(var a in t)e[a]=t[a]&&t[a].constructor===Object?n(e[a],t[a]):t[a];return e};for(t[0]=\"object\"==typeof t[0]?t[0]:{};e<t.length;e++)\"object\"==typeof t[e]&&n(t[0],t[e]);return t[0]},w.ie=function(){var e=navigator.userAgent.toLowerCase();return!!(window.ActiveXObject||\"ActiveXObject\"in window)&&((e.match(/msie\\s(\\d+)/)||[])[1]||\"11\")}(),w.stope=function(e){e=e||window.event,e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},w.each=function(e,t){var n,a=this;if(\"function\"!=typeof t)return a;if(e=e||[],e.constructor===Object){for(n in e)if(t.call(e[n],n,e[n]))break}else for(n=0;n<e.length&&!t.call(e[n],n,e[n]);n++);return a},w.digit=function(e,t,n){var a=\"\";e=String(e),t=t||2;for(var i=e.length;i<t;i++)a+=\"0\";return e<Math.pow(10,t)?a+(0|e):e},w.elem=function(e,t){var n=document.createElement(e);return w.each(t||{},function(e,t){n.setAttribute(e,t)}),n},C.addStr=function(e,t){return e=e.replace(/\\s+/,\" \"),t=t.replace(/\\s+/,\" \").split(\" \"),w.each(t,function(t,n){new RegExp(\"\\\\b\"+n+\"\\\\b\").test(e)||(e=e+\" \"+n)}),e.replace(/^\\s|\\s$/,\"\")},C.removeStr=function(e,t){return e=e.replace(/\\s+/,\" \"),t=t.replace(/\\s+/,\" \").split(\" \"),w.each(t,function(t,n){var a=new RegExp(\"\\\\b\"+n+\"\\\\b\");a.test(e)&&(e=e.replace(a,\"\"))}),e.replace(/\\s+/,\" \").replace(/^\\s|\\s$/,\"\")},C.prototype.find=function(e){var t=this,n=0,a=[],i=\"object\"==typeof e;return this.each(function(r,o){for(var s=i?[e]:o.querySelectorAll(e||null);n<s.length;n++)a.push(s[n]);t.shift()}),i||(t.selector=(t.selector?t.selector+\" \":\"\")+e),w.each(a,function(e,n){t.push(n)}),t},C.prototype.each=function(e){return w.each.call(this,this,e)},C.prototype.addClass=function(e,t){return this.each(function(n,a){a.className=C[t?\"removeStr\":\"addStr\"](a.className,e)})},C.prototype.removeClass=function(e){return this.addClass(e,!0)},C.prototype.hasClass=function(e){var t=!1;return this.each(function(n,a){new RegExp(\"\\\\b\"+e+\"\\\\b\").test(a.className)&&(t=!0)}),t},C.prototype.attr=function(e,t){var n=this;return void 0===t?function(){if(n.length>0)return n[0].getAttribute(e)}():n.each(function(n,a){a.setAttribute(e,t)})},C.prototype.removeAttr=function(e){return this.each(function(t,n){n.removeAttribute(e)})},C.prototype.html=function(e){return this.each(function(t,n){n.innerHTML=e})},C.prototype.val=function(e){return this.each(function(t,n){n.value=e})},C.prototype.append=function(e){return this.each(function(t,n){\"object\"==typeof e?n.appendChild(e):n.innerHTML=n.innerHTML+e})},C.prototype.remove=function(e){return this.each(function(t,n){e?n.removeChild(e):n.parentNode.removeChild(n)})},C.prototype.on=function(e,t){return this.each(function(n,a){a.attachEvent?a.attachEvent(\"on\"+e,function(e){e.target=e.srcElement,t.call(a,e)}):a.addEventListener(e,t,!1)})},C.prototype.off=function(e,t){return this.each(function(n,a){a.detachEvent?a.detachEvent(\"on\"+e,t):a.removeEventListener(e,t,!1)})},T.isLeapYear=function(e){return e%4===0&&e%100!==0||e%400===0},T.prototype.config={type:\"date\",range:!1,format:\"yyyy-MM-dd\",value:null,isInitValue:!1,min:\"1900-1-1\",max:\"2099-12-31\",trigger:\"focus\",show:!1,showBottom:!0,btns:[\"clear\",\"now\",\"confirm\"],lang:\"cn\",theme:\"default\",position:null,calendar:!1,mark:{},zIndex:null,done:null,change:null},T.prototype.lang=function(){var e=this,t=e.config,n={cn:{weeks:[\"日\",\"一\",\"二\",\"三\",\"四\",\"五\",\"六\"],time:[\"时\",\"分\",\"秒\"],timeTips:\"选择时间\",startTime:\"开始时间\",endTime:\"结束时间\",dateTips:\"返回日期\",month:[\"一\",\"二\",\"三\",\"四\",\"五\",\"六\",\"七\",\"八\",\"九\",\"十\",\"十一\",\"十二\"],tools:{confirm:\"确定\",clear:\"清空\",now:\"现在\"}},en:{weeks:[\"Su\",\"Mo\",\"Tu\",\"We\",\"Th\",\"Fr\",\"Sa\"],time:[\"Hours\",\"Minutes\",\"Seconds\"],timeTips:\"Select Time\",startTime:\"Start Time\",endTime:\"End Time\",dateTips:\"Select Date\",month:[\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\"],tools:{confirm:\"Confirm\",clear:\"Clear\",now:\"Now\"}}};return n[t.lang]||n.cn},T.prototype.init=function(){var e=this,t=e.config,n=\"yyyy|y|MM|M|dd|d|HH|H|mm|m|ss|s\",a=\"static\"===t.position,i={year:\"yyyy\",month:\"yyyy-MM\",date:\"yyyy-MM-dd\",time:\"HH:mm:ss\",datetime:\"yyyy-MM-dd HH:mm:ss\"};t.elem=w(t.elem),t.eventElem=w(t.eventElem),t.elem[0]&&(t.range===!0&&(t.range=\"-\"),t.format===i.date&&(t.format=i[t.type]),e.format=t.format.match(new RegExp(n+\"|.\",\"g\"))||[],e.EXP_IF=\"\",e.EXP_SPLIT=\"\",w.each(e.format,function(t,a){var i=new RegExp(n).test(a)?\"\\\\d{\"+function(){return new RegExp(n).test(e.format[0===t?t+1:t-1]||\"\")?/^yyyy|y$/.test(a)?4:a.length:/^yyyy$/.test(a)?\"1,4\":/^y$/.test(a)?\"1,308\":\"1,2\"}()+\"}\":\"\\\\\"+a;e.EXP_IF=e.EXP_IF+i,e.EXP_SPLIT=e.EXP_SPLIT+\"(\"+i+\")\"}),e.EXP_IF=new RegExp(\"^\"+(t.range?e.EXP_IF+\"\\\\s\\\\\"+t.range+\"\\\\s\"+e.EXP_IF:e.EXP_IF)+\"$\"),e.EXP_SPLIT=new RegExp(\"^\"+e.EXP_SPLIT+\"$\",\"\"),e.isInput(t.elem[0])||\"focus\"===t.trigger&&(t.trigger=\"click\"),t.elem.attr(\"lay-key\")||(t.elem.attr(\"lay-key\",e.index),t.eventElem.attr(\"lay-key\",e.index)),t.mark=w.extend({},t.calendar&&\"cn\"===t.lang?{\"0-1-1\":\"元旦\",\"0-2-14\":\"情人\",\"0-3-8\":\"妇女\",\"0-3-12\":\"植树\",\"0-4-1\":\"愚人\",\"0-5-1\":\"劳动\",\"0-5-4\":\"青年\",\"0-6-1\":\"儿童\",\"0-9-10\":\"教师\",\"0-9-18\":\"国耻\",\"0-10-1\":\"国庆\",\"0-12-25\":\"圣诞\"}:{},t.mark),w.each([\"min\",\"max\"],function(e,n){var a=[],i=[];if(\"number\"==typeof t[n]){var r=t[n],o=(new Date).getTime(),s=864e5,l=new Date(r?r<s?o+r*s:r:o);a=[l.getFullYear(),l.getMonth()+1,l.getDate()],r<s||(i=[l.getHours(),l.getMinutes(),l.getSeconds()])}else a=(t[n].match(/\\d+-\\d+-\\d+/)||[\"\"])[0].split(\"-\"),i=(t[n].match(/\\d+:\\d+:\\d+/)||[\"\"])[0].split(\":\");t[n]={year:0|a[0]||(new Date).getFullYear(),month:a[1]?(0|a[1])-1:(new Date).getMonth(),date:0|a[2]||(new Date).getDate(),hours:0|i[0],minutes:0|i[1],seconds:0|i[2]}}),e.elemID=\"layui-laydate\"+t.elem.attr(\"lay-key\"),(t.show||a)&&e.render(),a||e.events(),t.value&&t.isInitValue&&(t.value.constructor===Date?e.setValue(e.parse(0,e.systemDate(t.value))):e.setValue(t.value)))},T.prototype.render=function(){var e=this,t=e.config,n=e.lang(),a=\"static\"===t.position,i=e.elem=w.elem(\"div\",{id:e.elemID,\"class\":[\"layui-laydate\",t.range?\" layui-laydate-range\":\"\",a?\" \"+c:\"\",t.theme&&\"default\"!==t.theme&&!/^#/.test(t.theme)?\" laydate-theme-\"+t.theme:\"\"].join(\"\")}),r=e.elemMain=[],o=e.elemHeader=[],s=e.elemCont=[],l=e.table=[],d=e.footer=w.elem(\"div\",{\"class\":p});if(t.zIndex&&(i.style.zIndex=t.zIndex),w.each(new Array(2),function(e){if(!t.range&&e>0)return!0;var a=w.elem(\"div\",{\"class\":\"layui-laydate-header\"}),i=[function(){var e=w.elem(\"i\",{\"class\":\"layui-icon laydate-icon laydate-prev-y\"});return e.innerHTML=\"&#xe65a;\",e}(),function(){var e=w.elem(\"i\",{\"class\":\"layui-icon laydate-icon laydate-prev-m\"});return e.innerHTML=\"&#xe603;\",e}(),function(){var e=w.elem(\"div\",{\"class\":\"laydate-set-ym\"}),t=w.elem(\"span\"),n=w.elem(\"span\");return e.appendChild(t),e.appendChild(n),e}(),function(){var e=w.elem(\"i\",{\"class\":\"layui-icon laydate-icon laydate-next-m\"});return e.innerHTML=\"&#xe602;\",e}(),function(){var e=w.elem(\"i\",{\"class\":\"layui-icon laydate-icon laydate-next-y\"});return e.innerHTML=\"&#xe65b;\",e}()],d=w.elem(\"div\",{\"class\":\"layui-laydate-content\"}),c=w.elem(\"table\"),m=w.elem(\"thead\"),u=w.elem(\"tr\");w.each(i,function(e,t){a.appendChild(t)}),m.appendChild(u),w.each(new Array(6),function(e){var t=c.insertRow(0);w.each(new Array(7),function(a){if(0===e){var i=w.elem(\"th\");i.innerHTML=n.weeks[a],u.appendChild(i)}t.insertCell(a)})}),c.insertBefore(m,c.children[0]),d.appendChild(c),r[e]=w.elem(\"div\",{\"class\":\"layui-laydate-main laydate-main-list-\"+e}),r[e].appendChild(a),r[e].appendChild(d),o.push(i),s.push(d),l.push(c)}),w(d).html(function(){var e=[],i=[];return\"datetime\"===t.type&&e.push('<span lay-type=\"datetime\" class=\"laydate-btns-time\">'+n.timeTips+\"</span>\"),w.each(t.btns,function(e,r){var o=n.tools[r]||\"btn\";t.range&&\"now\"===r||(a&&\"clear\"===r&&(o=\"cn\"===t.lang?\"重置\":\"Reset\"),i.push('<span lay-type=\"'+r+'\" class=\"laydate-btns-'+r+'\">'+o+\"</span>\"))}),e.push('<div class=\"laydate-footer-btns\">'+i.join(\"\")+\"</div>\"),e.join(\"\")}()),w.each(r,function(e,t){i.appendChild(t)}),t.showBottom&&i.appendChild(d),/^#/.test(t.theme)){var m=w.elem(\"style\"),u=[\"#{{id}} .layui-laydate-header{background-color:{{theme}};}\",\"#{{id}} .layui-this{background-color:{{theme}} !important;}\"].join(\"\").replace(/{{id}}/g,e.elemID).replace(/{{theme}}/g,t.theme);\"styleSheet\"in m?(m.setAttribute(\"type\",\"text/css\"),m.styleSheet.cssText=u):m.innerHTML=u,w(i).addClass(\"laydate-theme-molv\"),i.appendChild(m)}e.remove(T.thisElemDate),a?t.elem.append(i):(document.body.appendChild(i),e.position()),e.checkDate().calendar(),e.changeEvent(),T.thisElemDate=e.elemID,\"function\"==typeof t.ready&&t.ready(w.extend({},t.dateTime,{month:t.dateTime.month+1}))},T.prototype.remove=function(e){var t=this,n=(t.config,w(\"#\"+(e||t.elemID)));return n.hasClass(c)||t.checkDate(function(){n.remove()}),t},T.prototype.position=function(){var e=this,t=e.config,n=e.bindElem||t.elem[0],a=n.getBoundingClientRect(),i=e.elem.offsetWidth,r=e.elem.offsetHeight,o=function(e){return e=e?\"scrollLeft\":\"scrollTop\",document.body[e]|document.documentElement[e]},s=function(e){return document.documentElement[e?\"clientWidth\":\"clientHeight\"]},l=5,d=a.left,c=a.bottom;d+i+l>s(\"width\")&&(d=s(\"width\")-i-l),c+r+l>s()&&(c=a.top>r?a.top-r:s()-r,c-=2*l),t.position&&(e.elem.style.position=t.position),e.elem.style.left=d+(\"fixed\"===t.position?0:o(1))+\"px\",e.elem.style.top=c+(\"fixed\"===t.position?0:o())+\"px\"},T.prototype.hint=function(e){var t=this,n=(t.config,w.elem(\"div\",{\"class\":h}));n.innerHTML=e||\"\",w(t.elem).find(\".\"+h).remove(),t.elem.appendChild(n),clearTimeout(t.hinTimer),t.hinTimer=setTimeout(function(){w(t.elem).find(\".\"+h).remove()},3e3)},T.prototype.getAsYM=function(e,t,n){return n?t--:t++,t<0&&(t=11,e--),t>11&&(t=0,e++),[e,t]},T.prototype.systemDate=function(e){var t=e||new Date;return{year:t.getFullYear(),month:t.getMonth(),date:t.getDate(),hours:e?e.getHours():0,minutes:e?e.getMinutes():0,seconds:e?e.getSeconds():0}},T.prototype.checkDate=function(e){var t,a,i=this,r=(new Date,i.config),o=r.dateTime=r.dateTime||i.systemDate(),s=i.bindElem||r.elem[0],l=(i.isInput(s)?\"val\":\"html\",i.isInput(s)?s.value:\"static\"===r.position?\"\":s.innerHTML),c=function(e){e.year>d[1]&&(e.year=d[1],a=!0),e.month>11&&(e.month=11,a=!0),e.hours>23&&(e.hours=0,a=!0),e.minutes>59&&(e.minutes=0,e.hours++,a=!0),e.seconds>59&&(e.seconds=0,e.minutes++,a=!0),t=n.getEndDate(e.month+1,e.year),e.date>t&&(e.date=t,a=!0)},m=function(e,t,n){var o=[\"startTime\",\"endTime\"];t=(t.match(i.EXP_SPLIT)||[]).slice(1),n=n||0,r.range&&(i[o[n]]=i[o[n]]||{}),w.each(i.format,function(s,l){var c=parseFloat(t[s]);t[s].length<l.length&&(a=!0),/yyyy|y/.test(l)?(c<d[0]&&(c=d[0],a=!0),e.year=c):/MM|M/.test(l)?(c<1&&(c=1,a=!0),e.month=c-1):/dd|d/.test(l)?(c<1&&(c=1,a=!0),e.date=c):/HH|H/.test(l)?(c<1&&(c=0,a=!0),e.hours=c,r.range&&(i[o[n]].hours=c)):/mm|m/.test(l)?(c<1&&(c=0,a=!0),e.minutes=c,r.range&&(i[o[n]].minutes=c)):/ss|s/.test(l)&&(c<1&&(c=0,a=!0),e.seconds=c,r.range&&(i[o[n]].seconds=c))}),c(e)};return\"limit\"===e?(c(o),i):(l=l||r.value,\"string\"==typeof l&&(l=l.replace(/\\s+/g,\" \").replace(/^\\s|\\s$/g,\"\")),i.startState&&!i.endState&&(delete i.startState,i.endState=!0),\"string\"==typeof l&&l?i.EXP_IF.test(l)?r.range?(l=l.split(\" \"+r.range+\" \"),i.startDate=i.startDate||i.systemDate(),i.endDate=i.endDate||i.systemDate(),r.dateTime=w.extend({},i.startDate),w.each([i.startDate,i.endDate],function(e,t){m(t,l[e],e)})):m(o,l):(i.hint(\"日期格式不合法<br>必须遵循下述格式：<br>\"+(r.range?r.format+\" \"+r.range+\" \"+r.format:r.format)+\"<br>已为你重置\"),a=!0):l&&l.constructor===Date?r.dateTime=i.systemDate(l):(r.dateTime=i.systemDate(),delete i.startState,delete i.endState,delete i.startDate,delete i.endDate,delete i.startTime,delete i.endTime),c(o),a&&l&&i.setValue(r.range?i.endDate?i.parse():\"\":i.parse()),e&&e(),i)},T.prototype.mark=function(e,t){var n,a=this,i=a.config;return w.each(i.mark,function(e,a){var i=e.split(\"-\");i[0]!=t[0]&&0!=i[0]||i[1]!=t[1]&&0!=i[1]||i[2]!=t[2]||(n=a||t[2])}),n&&e.html('<span class=\"laydate-day-mark\">'+n+\"</span>\"),a},T.prototype.limit=function(e,t,n,a){var i,r=this,o=r.config,l={},d=o[n>41?\"endDate\":\"dateTime\"],c=w.extend({},d,t||{});return w.each({now:c,min:o.min,max:o.max},function(e,t){l[e]=r.newDate(w.extend({year:t.year,month:t.month,date:t.date},function(){var e={};return w.each(a,function(n,a){e[a]=t[a]}),e}())).getTime()}),i=l.now<l.min||l.now>l.max,e&&e[i?\"addClass\":\"removeClass\"](s),i},T.prototype.calendar=function(e){var t,a,i,r=this,s=r.config,l=e||s.dateTime,c=new Date,m=r.lang(),u=\"date\"!==s.type&&\"datetime\"!==s.type,h=e?1:0,y=w(r.table[h]).find(\"td\"),f=w(r.elemHeader[h][2]).find(\"span\");if(l.year<d[0]&&(l.year=d[0],r.hint(\"最低只能支持到公元\"+d[0]+\"年\")),l.year>d[1]&&(l.year=d[1],r.hint(\"最高只能支持到公元\"+d[1]+\"年\")),r.firstDate||(r.firstDate=w.extend({},l)),c.setFullYear(l.year,l.month,1),t=c.getDay(),a=n.getEndDate(l.month||12,l.year),i=n.getEndDate(l.month+1,l.year),w.each(y,function(e,n){var d=[l.year,l.month],c=0;n=w(n),n.removeAttr(\"class\"),e<t?(c=a-t+e,n.addClass(\"laydate-day-prev\"),d=r.getAsYM(l.year,l.month,\"sub\")):e>=t&&e<i+t?(c=e-t,s.range||c+1===l.date&&n.addClass(o)):(c=e-i-t,n.addClass(\"laydate-day-next\"),d=r.getAsYM(l.year,l.month)),d[1]++,d[2]=c+1,n.attr(\"lay-ymd\",d.join(\"-\")).html(d[2]),r.mark(n,d).limit(n,{year:d[0],month:d[1]-1,date:d[2]},e)}),w(f[0]).attr(\"lay-ym\",l.year+\"-\"+(l.month+1)),w(f[1]).attr(\"lay-ym\",l.year+\"-\"+(l.month+1)),\"cn\"===s.lang?(w(f[0]).attr(\"lay-type\",\"year\").html(l.year+\"年\"),w(f[1]).attr(\"lay-type\",\"month\").html(l.month+1+\"月\")):(w(f[0]).attr(\"lay-type\",\"month\").html(m.month[l.month]),w(f[1]).attr(\"lay-type\",\"year\").html(l.year)),u&&(s.range&&(e?r.endDate=r.endDate||{year:l.year+(\"year\"===s.type?1:0),month:l.month+(\"month\"===s.type?0:-1)}:r.startDate=r.startDate||{year:l.year,month:l.month},e&&(r.listYM=[[r.startDate.year,r.startDate.month+1],[r.endDate.year,r.endDate.month+1]],r.list(s.type,0).list(s.type,1),\"time\"===s.type?r.setBtnStatus(\"时间\",w.extend({},r.systemDate(),r.startTime),w.extend({},r.systemDate(),r.endTime)):r.setBtnStatus(!0))),s.range||(r.listYM=[[l.year,l.month+1]],r.list(s.type,0))),s.range&&!e){var p=r.getAsYM(l.year,l.month);r.calendar(w.extend({},l,{year:p[0],month:p[1]}))}return s.range||r.limit(w(r.footer).find(g),null,0,[\"hours\",\"minutes\",\"seconds\"]),s.range&&e&&!u&&r.stampRange(),r},T.prototype.list=function(e,t){var n=this,a=n.config,i=a.dateTime,r=n.lang(),l=a.range&&\"date\"!==a.type&&\"datetime\"!==a.type,d=w.elem(\"ul\",{\"class\":m+\" \"+{year:\"laydate-year-list\",month:\"laydate-month-list\",time:\"laydate-time-list\"}[e]}),c=n.elemHeader[t],u=w(c[2]).find(\"span\"),h=n.elemCont[t||0],y=w(h).find(\".\"+m)[0],f=\"cn\"===a.lang,p=f?\"年\":\"\",T=n.listYM[t]||{},C=[\"hours\",\"minutes\",\"seconds\"],x=[\"startTime\",\"endTime\"][t];if(T[0]<1&&(T[0]=1),\"year\"===e){var M,b=M=T[0]-7;b<1&&(b=M=1),w.each(new Array(15),function(e){var i=w.elem(\"li\",{\"lay-ym\":M}),r={year:M};M==T[0]&&w(i).addClass(o),i.innerHTML=M+p,d.appendChild(i),M<n.firstDate.year?(r.month=a.min.month,r.date=a.min.date):M>=n.firstDate.year&&(r.month=a.max.month,r.date=a.max.date),n.limit(w(i),r,t),M++}),w(u[f?0:1]).attr(\"lay-ym\",M-8+\"-\"+T[1]).html(b+p+\" - \"+(M-1+p))}else if(\"month\"===e)w.each(new Array(12),function(e){var i=w.elem(\"li\",{\"lay-ym\":e}),s={year:T[0],month:e};e+1==T[1]&&w(i).addClass(o),i.innerHTML=r.month[e]+(f?\"月\":\"\"),d.appendChild(i),T[0]<n.firstDate.year?s.date=a.min.date:T[0]>=n.firstDate.year&&(s.date=a.max.date),n.limit(w(i),s,t)}),w(u[f?0:1]).attr(\"lay-ym\",T[0]+\"-\"+T[1]).html(T[0]+p);else if(\"time\"===e){var E=function(){w(d).find(\"ol\").each(function(e,a){w(a).find(\"li\").each(function(a,i){n.limit(w(i),[{hours:a},{hours:n[x].hours,minutes:a},{hours:n[x].hours,minutes:n[x].minutes,seconds:a}][e],t,[[\"hours\"],[\"hours\",\"minutes\"],[\"hours\",\"minutes\",\"seconds\"]][e])})}),a.range||n.limit(w(n.footer).find(g),n[x],0,[\"hours\",\"minutes\",\"seconds\"])};a.range?n[x]||(n[x]={hours:0,minutes:0,seconds:0}):n[x]=i,w.each([24,60,60],function(e,t){var a=w.elem(\"li\"),i=[\"<p>\"+r.time[e]+\"</p><ol>\"];w.each(new Array(t),function(t){i.push(\"<li\"+(n[x][C[e]]===t?' class=\"'+o+'\"':\"\")+\">\"+w.digit(t,2)+\"</li>\")}),a.innerHTML=i.join(\"\")+\"</ol>\",d.appendChild(a)}),E()}if(y&&h.removeChild(y),h.appendChild(d),\"year\"===e||\"month\"===e)w(n.elemMain[t]).addClass(\"laydate-ym-show\"),w(d).find(\"li\").on(\"click\",function(){var r=0|w(this).attr(\"lay-ym\");if(!w(this).hasClass(s)){if(0===t)i[e]=r,l&&(n.startDate[e]=r),n.limit(w(n.footer).find(g),null,0);else if(l)n.endDate[e]=r;else{var c=\"year\"===e?n.getAsYM(r,T[1]-1,\"sub\"):n.getAsYM(T[0],r,\"sub\");w.extend(i,{year:c[0],month:c[1]})}\"year\"===a.type||\"month\"===a.type?(w(d).find(\".\"+o).removeClass(o),w(this).addClass(o),\"month\"===a.type&&\"year\"===e&&(n.listYM[t][0]=r,l&&(n[[\"startDate\",\"endDate\"][t]].year=r),n.list(\"month\",t))):(n.checkDate(\"limit\").calendar(),n.closeList()),n.setBtnStatus(),a.range||n.done(null,\"change\"),w(n.footer).find(D).removeClass(s)}});else{var S=w.elem(\"span\",{\"class\":v}),k=function(){w(d).find(\"ol\").each(function(e){var t=this,a=w(t).find(\"li\");t.scrollTop=30*(n[x][C[e]]-2),t.scrollTop<=0&&a.each(function(e,n){if(!w(this).hasClass(s))return t.scrollTop=30*(e-2),!0})})},H=w(c[2]).find(\".\"+v);k(),S.innerHTML=a.range?[r.startTime,r.endTime][t]:r.timeTips,w(n.elemMain[t]).addClass(\"laydate-time-show\"),H[0]&&H.remove(),c[2].appendChild(S),w(d).find(\"ol\").each(function(e){var t=this;w(t).find(\"li\").on(\"click\",function(){var r=0|this.innerHTML;w(this).hasClass(s)||(a.range?n[x][C[e]]=r:i[C[e]]=r,w(t).find(\".\"+o).removeClass(o),w(this).addClass(o),E(),k(),(n.endDate||\"time\"===a.type)&&n.done(null,\"change\"),n.setBtnStatus())})})}return n},T.prototype.listYM=[],T.prototype.closeList=function(){var e=this;e.config;w.each(e.elemCont,function(t,n){w(this).find(\".\"+m).remove(),w(e.elemMain[t]).removeClass(\"laydate-ym-show laydate-time-show\")}),w(e.elem).find(\".\"+v).remove()},T.prototype.setBtnStatus=function(e,t,n){var a,i=this,r=i.config,o=w(i.footer).find(g),d=r.range&&\"date\"!==r.type&&\"time\"!==r.type;d&&(t=t||i.startDate,n=n||i.endDate,a=i.newDate(t).getTime()>i.newDate(n).getTime(),i.limit(null,t)||i.limit(null,n)?o.addClass(s):o[a?\"addClass\":\"removeClass\"](s),e&&a&&i.hint(\"string\"==typeof e?l.replace(/日期/g,e):l))},T.prototype.parse=function(e,t){var n=this,a=n.config,i=t||(e?w.extend({},n.endDate,n.endTime):a.range?w.extend({},n.startDate,n.startTime):a.dateTime),r=n.format.concat();return w.each(r,function(e,t){/yyyy|y/.test(t)?r[e]=w.digit(i.year,t.length):/MM|M/.test(t)?r[e]=w.digit(i.month+1,t.length):/dd|d/.test(t)?r[e]=w.digit(i.date,t.length):/HH|H/.test(t)?r[e]=w.digit(i.hours,t.length):/mm|m/.test(t)?r[e]=w.digit(i.minutes,t.length):/ss|s/.test(t)&&(r[e]=w.digit(i.seconds,t.length))}),a.range&&!e?r.join(\"\")+\" \"+a.range+\" \"+n.parse(1):r.join(\"\")},T.prototype.newDate=function(e){return e=e||{},new Date(e.year||1,e.month||0,e.date||1,e.hours||0,e.minutes||0,e.seconds||0)},T.prototype.setValue=function(e){var t=this,n=t.config,a=t.bindElem||n.elem[0],i=t.isInput(a)?\"val\":\"html\";return\"static\"===n.position||w(a)[i](e||\"\"),this},T.prototype.stampRange=function(){var e,t,n=this,a=n.config,i=w(n.elem).find(\"td\");if(a.range&&!n.endDate&&w(n.footer).find(g).addClass(s),n.endDate)return e=n.newDate({year:n.startDate.year,month:n.startDate.month,date:n.startDate.date}).getTime(),t=n.newDate({year:n.endDate.year,month:n.endDate.month,date:n.endDate.date}).getTime(),e>t?n.hint(l):void w.each(i,function(a,i){var r=w(i).attr(\"lay-ymd\").split(\"-\"),s=n.newDate({year:r[0],month:r[1]-1,date:r[2]}).getTime();w(i).removeClass(u+\" \"+o),s!==e&&s!==t||w(i).addClass(w(i).hasClass(y)||w(i).hasClass(f)?u:o),s>e&&s<t&&w(i).addClass(u)})},T.prototype.done=function(e,t){var n=this,a=n.config,i=w.extend({},n.startDate?w.extend(n.startDate,n.startTime):a.dateTime),r=w.extend({},w.extend(n.endDate,n.endTime));return w.each([i,r],function(e,t){\"month\"in t&&w.extend(t,{month:t.month+1})}),e=e||[n.parse(),i,r],\"function\"==typeof a[t||\"done\"]&&a[t||\"done\"].apply(a,e),n},T.prototype.choose=function(e){var t=this,n=t.config,a=n.dateTime,i=w(t.elem).find(\"td\"),r=e.attr(\"lay-ymd\").split(\"-\"),l=function(e){new Date;e&&w.extend(a,r),n.range&&(t.startDate?w.extend(t.startDate,r):t.startDate=w.extend({},r,t.startTime),t.startYMD=r)};if(r={year:0|r[0],month:(0|r[1])-1,date:0|r[2]},!e.hasClass(s))if(n.range){if(w.each([\"startTime\",\"endTime\"],function(e,n){t[n]=t[n]||{hours:0,minutes:0,seconds:0}}),t.endState)l(),delete t.endState,delete t.endDate,t.startState=!0,i.removeClass(o+\" \"+u),e.addClass(o);else if(t.startState){if(e.addClass(o),t.endDate?w.extend(t.endDate,r):t.endDate=w.extend({},r,t.endTime),t.newDate(r).getTime()<t.newDate(t.startYMD).getTime()){var d=w.extend({},t.endDate,{hours:t.startDate.hours,minutes:t.startDate.minutes,seconds:t.startDate.seconds});w.extend(t.endDate,t.startDate,{hours:t.endDate.hours,minutes:t.endDate.minutes,seconds:t.endDate.seconds}),t.startDate=d}n.showBottom||t.done(),t.stampRange(),t.endState=!0,t.done(null,\"change\")}else e.addClass(o),l(),t.startState=!0;w(t.footer).find(g)[t.endDate?\"removeClass\":\"addClass\"](s)}else\"static\"===n.position?(l(!0),t.calendar().done().done(null,\"change\")):\"date\"===n.type?(l(!0),t.setValue(t.parse()).remove().done()):\"datetime\"===n.type&&(l(!0),t.calendar().done(null,\"change\"))},T.prototype.tool=function(e,t){var n=this,a=n.config,i=a.dateTime,r=\"static\"===a.position,o={datetime:function(){w(e).hasClass(s)||(n.list(\"time\",0),a.range&&n.list(\"time\",1),w(e).attr(\"lay-type\",\"date\").html(n.lang().dateTips))},date:function(){n.closeList(),w(e).attr(\"lay-type\",\"datetime\").html(n.lang().timeTips)},clear:function(){n.setValue(\"\").remove(),r&&(w.extend(i,n.firstDate),n.calendar()),a.range&&(delete n.startState,delete n.endState,delete n.endDate,delete n.startTime,delete n.endTime),n.done([\"\",{},{}])},now:function(){var e=new Date;w.extend(i,n.systemDate(),{hours:e.getHours(),minutes:e.getMinutes(),seconds:e.getSeconds()}),n.setValue(n.parse()).remove(),r&&n.calendar(),n.done()},confirm:function(){if(a.range){if(!n.endDate)return n.hint(\"请先选择日期范围\");if(w(e).hasClass(s))return n.hint(\"time\"===a.type?l.replace(/日期/g,\"时间\"):l)}else if(w(e).hasClass(s))return n.hint(\"不在有效日期或时间范围内\");n.done(),n.setValue(n.parse()).remove()}};o[t]&&o[t]()},T.prototype.change=function(e){var t=this,n=t.config,a=n.dateTime,i=n.range&&(\"year\"===n.type||\"month\"===n.type),r=t.elemCont[e||0],o=t.listYM[e],s=function(s){var l=[\"startDate\",\"endDate\"][e],d=w(r).find(\".laydate-year-list\")[0],c=w(r).find(\".laydate-month-list\")[0];return d&&(o[0]=s?o[0]-15:o[0]+15,t.list(\"year\",e)),c&&(s?o[0]--:o[0]++,t.list(\"month\",e)),(d||c)&&(w.extend(a,{year:o[0]}),i&&(t[l].year=o[0]),n.range||t.done(null,\"change\"),t.setBtnStatus(),n.range||t.limit(w(t.footer).find(g),{year:o[0]})),d||c};return{prevYear:function(){s(\"sub\")||(a.year--,t.checkDate(\"limit\").calendar(),n.range||t.done(null,\"change\"))},prevMonth:function(){var e=t.getAsYM(a.year,a.month,\"sub\");w.extend(a,{year:e[0],month:e[1]}),t.checkDate(\"limit\").calendar(),n.range||t.done(null,\"change\")},nextMonth:function(){var e=t.getAsYM(a.year,a.month);w.extend(a,{year:e[0],month:e[1]}),t.checkDate(\"limit\").calendar(),n.range||t.done(null,\"change\")},nextYear:function(){s()||(a.year++,t.checkDate(\"limit\").calendar(),n.range||t.done(null,\"change\"))}}},T.prototype.changeEvent=function(){var e=this;e.config;w(e.elem).on(\"click\",function(e){w.stope(e)}),w.each(e.elemHeader,function(t,n){w(n[0]).on(\"click\",function(n){e.change(t).prevYear()}),w(n[1]).on(\"click\",function(n){e.change(t).prevMonth()}),w(n[2]).find(\"span\").on(\"click\",function(n){var a=w(this),i=a.attr(\"lay-ym\"),r=a.attr(\"lay-type\");i&&(i=i.split(\"-\"),e.listYM[t]=[0|i[0],0|i[1]],e.list(r,t),w(e.footer).find(D).addClass(s))}),w(n[3]).on(\"click\",function(n){e.change(t).nextMonth()}),w(n[4]).on(\"click\",function(n){e.change(t).nextYear()})}),w.each(e.table,function(t,n){var a=w(n).find(\"td\");a.on(\"click\",function(){e.choose(w(this))})}),w(e.footer).find(\"span\").on(\"click\",function(){var t=w(this).attr(\"lay-type\");e.tool(this,t)})},T.prototype.isInput=function(e){return/input|textarea/.test(e.tagName.toLocaleLowerCase())},T.prototype.events=function(){var e=this,t=e.config,n=function(n,a){n.on(t.trigger,function(){a&&(e.bindElem=this),e.render()})};t.elem[0]&&!t.elem[0].eventHandler&&(n(t.elem,\"bind\"),n(t.eventElem),w(document).on(\"click\",function(n){n.target!==t.elem[0]&&n.target!==t.eventElem[0]&&n.target!==w(t.closeStop)[0]&&e.remove()}).on(\"keydown\",function(t){13===t.keyCode&&w(\"#\"+e.elemID)[0]&&e.elemID===T.thisElem&&(t.preventDefault(),w(e.footer).find(g)[0].click())}),w(window).on(\"resize\",function(){return!(!e.elem||!w(r)[0])&&void e.position()}),t.elem[0].eventHandler=!0)},n.render=function(e){var t=new T(e);return a.call(t)},n.getEndDate=function(e,t){var n=new Date;return n.setFullYear(t||n.getFullYear(),e||n.getMonth()+1,1),new Date(n.getTime()-864e5).getDate()},window.lay=window.lay||w,e?(n.ready(),layui.define(function(e){n.path=layui.cache.dir,e(i,n)})):\"function\"==typeof define&&define.amd?define(function(){return n}):function(){n.ready(),window.laydate=n}()}();"
  },
  {
    "path": "open-layui-web/src/main/view/static/layui/lay/modules/layedit.js",
    "content": "/** layui-v2.3.0-rc1 MIT License By https://www.layui.com */\n ;layui.define([\"layer\",\"form\"],function(t){\"use strict\";var e=layui.$,i=layui.layer,a=layui.form,l=(layui.hint(),layui.device()),n=\"layedit\",o=\"layui-show\",r=\"layui-disabled\",c=function(){var t=this;t.index=0,t.config={tool:[\"strong\",\"italic\",\"underline\",\"del\",\"|\",\"left\",\"center\",\"right\",\"|\",\"link\",\"unlink\",\"face\",\"image\"],hideTool:[],height:280}};c.prototype.set=function(t){var i=this;return e.extend(!0,i.config,t),i},c.prototype.on=function(t,e){return layui.onevent(n,t,e)},c.prototype.build=function(t,i){i=i||{};var a=this,n=a.config,r=\"layui-layedit\",c=e(\"string\"==typeof t?\"#\"+t:t),u=\"LAY_layedit_\"+ ++a.index,d=c.next(\".\"+r),y=e.extend({},n,i),f=function(){var t=[],e={};return layui.each(y.hideTool,function(t,i){e[i]=!0}),layui.each(y.tool,function(i,a){C[a]&&!e[a]&&t.push(C[a])}),t.join(\"\")}(),m=e(['<div class=\"'+r+'\">','<div class=\"layui-unselect layui-layedit-tool\">'+f+\"</div>\",'<div class=\"layui-layedit-iframe\">','<iframe id=\"'+u+'\" name=\"'+u+'\" textarea=\"'+t+'\" frameborder=\"0\"></iframe>',\"</div>\",\"</div>\"].join(\"\"));return l.ie&&l.ie<8?c.removeClass(\"layui-hide\").addClass(o):(d[0]&&d.remove(),s.call(a,m,c[0],y),c.addClass(\"layui-hide\").after(m),a.index)},c.prototype.getContent=function(t){var e=u(t);if(e[0])return d(e[0].document.body.innerHTML)},c.prototype.getText=function(t){var i=u(t);if(i[0])return e(i[0].document.body).text()},c.prototype.setContent=function(t,i,a){var l=u(t);l[0]&&(a?e(l[0].document.body).append(i):e(l[0].document.body).html(i),layedit.sync(t))},c.prototype.sync=function(t){var i=u(t);if(i[0]){var a=e(\"#\"+i[1].attr(\"textarea\"));a.val(d(i[0].document.body.innerHTML))}},c.prototype.getSelection=function(t){var e=u(t);if(e[0]){var i=m(e[0].document);return document.selection?i.text:i.toString()}};var s=function(t,i,a){var l=this,n=t.find(\"iframe\");n.css({height:a.height}).on(\"load\",function(){var o=n.contents(),r=n.prop(\"contentWindow\"),c=o.find(\"head\"),s=e([\"<style>\",\"*{margin: 0; padding: 0;}\",\"body{padding: 10px; line-height: 20px; overflow-x: hidden; word-wrap: break-word; font: 14px Helvetica Neue,Helvetica,PingFang SC,Microsoft YaHei,Tahoma,Arial,sans-serif; -webkit-box-sizing: border-box !important; -moz-box-sizing: border-box !important; box-sizing: border-box !important;}\",\"a{color:#01AAED; text-decoration:none;}a:hover{color:#c00}\",\"p{margin-bottom: 10px;}\",\"img{display: inline-block; border: none; vertical-align: middle;}\",\"pre{margin: 10px 0; padding: 10px; line-height: 20px; border: 1px solid #ddd; border-left-width: 6px; background-color: #F2F2F2; color: #333; font-family: Courier New; font-size: 12px;}\",\"</style>\"].join(\"\")),u=o.find(\"body\");c.append(s),u.attr(\"contenteditable\",\"true\").css({\"min-height\":a.height}).html(i.value||\"\"),y.apply(l,[r,n,i,a]),g.call(l,r,t,a)})},u=function(t){var i=e(\"#LAY_layedit_\"+t),a=i.prop(\"contentWindow\");return[a,i]},d=function(t){return 8==l.ie&&(t=t.replace(/<.+>/g,function(t){return t.toLowerCase()})),t},y=function(t,a,n,o){var r=t.document,c=e(r.body);c.on(\"keydown\",function(t){var e=t.keyCode;if(13===e){var a=m(r),l=p(a),n=l.parentNode;if(\"pre\"===n.tagName.toLowerCase()){if(t.shiftKey)return;return i.msg(\"请暂时用shift+enter\"),!1}r.execCommand(\"formatBlock\",!1,\"<p>\")}}),e(n).parents(\"form\").on(\"submit\",function(){var t=c.html();8==l.ie&&(t=t.replace(/<.+>/g,function(t){return t.toLowerCase()})),n.value=t}),c.on(\"paste\",function(e){r.execCommand(\"formatBlock\",!1,\"<p>\"),setTimeout(function(){f.call(t,c),n.value=c.html()},100)})},f=function(t){var i=this;i.document;t.find(\"*[style]\").each(function(){var t=this.style.textAlign;this.removeAttribute(\"style\"),e(this).css({\"text-align\":t||\"\"})}),t.find(\"table\").addClass(\"layui-table\"),t.find(\"script,link\").remove()},m=function(t){return t.selection?t.selection.createRange():t.getSelection().getRangeAt(0)},p=function(t){return t.endContainer||t.parentElement().childNodes[0]},v=function(t,i,a){var l=this.document,n=document.createElement(t);for(var o in i)n.setAttribute(o,i[o]);if(n.removeAttribute(\"text\"),l.selection){var r=a.text||i.text;if(\"a\"===t&&!r)return;r&&(n.innerHTML=r),a.pasteHTML(e(n).prop(\"outerHTML\")),a.select()}else{var r=a.toString()||i.text;if(\"a\"===t&&!r)return;r&&(n.innerHTML=r),a.deleteContents(),a.insertNode(n)}},h=function(t,i){var a=this.document,l=\"layedit-tool-active\",n=p(m(a)),o=function(e){return t.find(\".layedit-tool-\"+e)};i&&i[i.hasClass(l)?\"removeClass\":\"addClass\"](l),t.find(\">i\").removeClass(l),o(\"unlink\").addClass(r),e(n).parents().each(function(){var t=this.tagName.toLowerCase(),e=this.style.textAlign;\"b\"!==t&&\"strong\"!==t||o(\"b\").addClass(l),\"i\"!==t&&\"em\"!==t||o(\"i\").addClass(l),\"u\"===t&&o(\"u\").addClass(l),\"strike\"===t&&o(\"d\").addClass(l),\"p\"===t&&(\"center\"===e?o(\"center\").addClass(l):\"right\"===e?o(\"right\").addClass(l):o(\"left\").addClass(l)),\"a\"===t&&(o(\"link\").addClass(l),o(\"unlink\").removeClass(r))})},g=function(t,a,l){var n=t.document,o=e(n.body),c={link:function(i){var a=p(i),l=e(a).parent();b.call(o,{href:l.attr(\"href\"),target:l.attr(\"target\")},function(e){var a=l[0];\"A\"===a.tagName?a.href=e.url:v.call(t,\"a\",{target:e.target,href:e.url,text:e.url},i)})},unlink:function(t){n.execCommand(\"unlink\")},face:function(e){x.call(this,function(i){v.call(t,\"img\",{src:i.src,alt:i.alt},e)})},image:function(a){var n=this;layui.use(\"upload\",function(o){var r=l.uploadImage||{};o.render({url:r.url,method:r.type,elem:e(n).find(\"input\")[0],done:function(e){0==e.code?(e.data=e.data||{},v.call(t,\"img\",{src:e.data.src,alt:e.data.title},a)):i.msg(e.msg||\"上传失败\")}})})},code:function(e){k.call(o,function(i){v.call(t,\"pre\",{text:i.code,\"lay-lang\":i.lang},e)})},help:function(){i.open({type:2,title:\"帮助\",area:[\"600px\",\"380px\"],shadeClose:!0,shade:.1,skin:\"layui-layer-msg\",content:[\"http://www.layui.com/about/layedit/help.html\",\"no\"]})}},s=a.find(\".layui-layedit-tool\"),u=function(){var i=e(this),a=i.attr(\"layedit-event\"),l=i.attr(\"lay-command\");if(!i.hasClass(r)){o.focus();var u=m(n);u.commonAncestorContainer;l?(n.execCommand(l),/justifyLeft|justifyCenter|justifyRight/.test(l)&&n.execCommand(\"formatBlock\",!1,\"<p>\"),setTimeout(function(){o.focus()},10)):c[a]&&c[a].call(this,u),h.call(t,s,i)}},d=/image/;s.find(\">i\").on(\"mousedown\",function(){var t=e(this),i=t.attr(\"layedit-event\");d.test(i)||u.call(this)}).on(\"click\",function(){var t=e(this),i=t.attr(\"layedit-event\");d.test(i)&&u.call(this)}),o.on(\"click\",function(){h.call(t,s),i.close(x.index)})},b=function(t,e){var l=this,n=i.open({type:1,id:\"LAY_layedit_link\",area:\"350px\",shade:.05,shadeClose:!0,moveType:1,title:\"超链接\",skin:\"layui-layer-msg\",content:['<ul class=\"layui-form\" style=\"margin: 15px;\">','<li class=\"layui-form-item\">','<label class=\"layui-form-label\" style=\"width: 60px;\">URL</label>','<div class=\"layui-input-block\" style=\"margin-left: 90px\">','<input name=\"url\" lay-verify=\"url\" value=\"'+(t.href||\"\")+'\" autofocus=\"true\" autocomplete=\"off\" class=\"layui-input\">',\"</div>\",\"</li>\",'<li class=\"layui-form-item\">','<label class=\"layui-form-label\" style=\"width: 60px;\">打开方式</label>','<div class=\"layui-input-block\" style=\"margin-left: 90px\">','<input type=\"radio\" name=\"target\" value=\"_self\" class=\"layui-input\" title=\"当前窗口\"'+(\"_self\"!==t.target&&t.target?\"\":\"checked\")+\">\",'<input type=\"radio\" name=\"target\" value=\"_blank\" class=\"layui-input\" title=\"新窗口\" '+(\"_blank\"===t.target?\"checked\":\"\")+\">\",\"</div>\",\"</li>\",'<li class=\"layui-form-item\" style=\"text-align: center;\">','<button type=\"button\" lay-submit lay-filter=\"layedit-link-yes\" class=\"layui-btn\"> 确定 </button>','<button style=\"margin-left: 20px;\" type=\"button\" class=\"layui-btn layui-btn-primary\"> 取消 </button>',\"</li>\",\"</ul>\"].join(\"\"),success:function(t,n){var o=\"submit(layedit-link-yes)\";a.render(\"radio\"),t.find(\".layui-btn-primary\").on(\"click\",function(){i.close(n),l.focus()}),a.on(o,function(t){i.close(b.index),e&&e(t.field)})}});b.index=n},x=function(t){var a=function(){var t=[\"[微笑]\",\"[嘻嘻]\",\"[哈哈]\",\"[可爱]\",\"[可怜]\",\"[挖鼻]\",\"[吃惊]\",\"[害羞]\",\"[挤眼]\",\"[闭嘴]\",\"[鄙视]\",\"[爱你]\",\"[泪]\",\"[偷笑]\",\"[亲亲]\",\"[生病]\",\"[太开心]\",\"[白眼]\",\"[右哼哼]\",\"[左哼哼]\",\"[嘘]\",\"[衰]\",\"[委屈]\",\"[吐]\",\"[哈欠]\",\"[抱抱]\",\"[怒]\",\"[疑问]\",\"[馋嘴]\",\"[拜拜]\",\"[思考]\",\"[汗]\",\"[困]\",\"[睡]\",\"[钱]\",\"[失望]\",\"[酷]\",\"[色]\",\"[哼]\",\"[鼓掌]\",\"[晕]\",\"[悲伤]\",\"[抓狂]\",\"[黑线]\",\"[阴险]\",\"[怒骂]\",\"[互粉]\",\"[心]\",\"[伤心]\",\"[猪头]\",\"[熊猫]\",\"[兔子]\",\"[ok]\",\"[耶]\",\"[good]\",\"[NO]\",\"[赞]\",\"[来]\",\"[弱]\",\"[草泥马]\",\"[神马]\",\"[囧]\",\"[浮云]\",\"[给力]\",\"[围观]\",\"[威武]\",\"[奥特曼]\",\"[礼物]\",\"[钟]\",\"[话筒]\",\"[蜡烛]\",\"[蛋糕]\"],e={};return layui.each(t,function(t,i){e[i]=layui.cache.dir+\"images/face/\"+t+\".gif\"}),e}();return x.hide=x.hide||function(t){\"face\"!==e(t.target).attr(\"layedit-event\")&&i.close(x.index)},x.index=i.tips(function(){var t=[];return layui.each(a,function(e,i){t.push('<li title=\"'+e+'\"><img src=\"'+i+'\" alt=\"'+e+'\"></li>')}),'<ul class=\"layui-clear\">'+t.join(\"\")+\"</ul>\"}(),this,{tips:1,time:0,skin:\"layui-box layui-util-face\",maxWidth:500,success:function(l,n){l.css({marginTop:-4,marginLeft:-10}).find(\".layui-clear>li\").on(\"click\",function(){t&&t({src:a[this.title],alt:this.title}),i.close(n)}),e(document).off(\"click\",x.hide).on(\"click\",x.hide)}})},k=function(t){var e=this,l=i.open({type:1,id:\"LAY_layedit_code\",area:\"550px\",shade:.05,shadeClose:!0,moveType:1,title:\"插入代码\",skin:\"layui-layer-msg\",content:['<ul class=\"layui-form layui-form-pane\" style=\"margin: 15px;\">','<li class=\"layui-form-item\">','<label class=\"layui-form-label\">请选择语言</label>','<div class=\"layui-input-block\">','<select name=\"lang\">','<option value=\"JavaScript\">JavaScript</option>','<option value=\"HTML\">HTML</option>','<option value=\"CSS\">CSS</option>','<option value=\"Java\">Java</option>','<option value=\"PHP\">PHP</option>','<option value=\"C#\">C#</option>','<option value=\"Python\">Python</option>','<option value=\"Ruby\">Ruby</option>','<option value=\"Go\">Go</option>',\"</select>\",\"</div>\",\"</li>\",'<li class=\"layui-form-item layui-form-text\">','<label class=\"layui-form-label\">代码</label>','<div class=\"layui-input-block\">','<textarea name=\"code\" lay-verify=\"required\" autofocus=\"true\" class=\"layui-textarea\" style=\"height: 200px;\"></textarea>',\"</div>\",\"</li>\",'<li class=\"layui-form-item\" style=\"text-align: center;\">','<button type=\"button\" lay-submit lay-filter=\"layedit-code-yes\" class=\"layui-btn\"> 确定 </button>','<button style=\"margin-left: 20px;\" type=\"button\" class=\"layui-btn layui-btn-primary\"> 取消 </button>',\"</li>\",\"</ul>\"].join(\"\"),success:function(l,n){var o=\"submit(layedit-code-yes)\";a.render(\"select\"),l.find(\".layui-btn-primary\").on(\"click\",function(){i.close(n),e.focus()}),a.on(o,function(e){i.close(k.index),t&&t(e.field)})}});k.index=l},C={html:'<i class=\"layui-icon layedit-tool-html\" title=\"HTML源代码\" lay-command=\"html\" layedit-event=\"html\"\">&#xe64b;</i><span class=\"layedit-tool-mid\"></span>',strong:'<i class=\"layui-icon layedit-tool-b\" title=\"加粗\" lay-command=\"Bold\" layedit-event=\"b\"\">&#xe62b;</i>',italic:'<i class=\"layui-icon layedit-tool-i\" title=\"斜体\" lay-command=\"italic\" layedit-event=\"i\"\">&#xe644;</i>',underline:'<i class=\"layui-icon layedit-tool-u\" title=\"下划线\" lay-command=\"underline\" layedit-event=\"u\"\">&#xe646;</i>',del:'<i class=\"layui-icon layedit-tool-d\" title=\"删除线\" lay-command=\"strikeThrough\" layedit-event=\"d\"\">&#xe64f;</i>',\"|\":'<span class=\"layedit-tool-mid\"></span>',left:'<i class=\"layui-icon layedit-tool-left\" title=\"左对齐\" lay-command=\"justifyLeft\" layedit-event=\"left\"\">&#xe649;</i>',center:'<i class=\"layui-icon layedit-tool-center\" title=\"居中对齐\" lay-command=\"justifyCenter\" layedit-event=\"center\"\">&#xe647;</i>',right:'<i class=\"layui-icon layedit-tool-right\" title=\"右对齐\" lay-command=\"justifyRight\" layedit-event=\"right\"\">&#xe648;</i>',link:'<i class=\"layui-icon layedit-tool-link\" title=\"插入链接\" layedit-event=\"link\"\">&#xe64c;</i>',unlink:'<i class=\"layui-icon layedit-tool-unlink layui-disabled\" title=\"清除链接\" lay-command=\"unlink\" layedit-event=\"unlink\"\">&#xe64d;</i>',face:'<i class=\"layui-icon layedit-tool-face\" title=\"表情\" layedit-event=\"face\"\">&#xe650;</i>',image:'<i class=\"layui-icon layedit-tool-image\" title=\"图片\" layedit-event=\"image\">&#xe64a;<input type=\"file\" name=\"file\"></i>',code:'<i class=\"layui-icon layedit-tool-code\" title=\"插入代码\" layedit-event=\"code\">&#xe64e;</i>',help:'<i class=\"layui-icon layedit-tool-help\" title=\"帮助\" layedit-event=\"help\">&#xe607;</i>'},w=new c;t(n,w)});"
  },
  {
    "path": "open-layui-web/src/main/view/static/layui/lay/modules/layer.js",
    "content": "/** layui-v2.3.0-rc1 MIT License By https://www.layui.com */\n ;!function(e,t){\"use strict\";var i,n,a=e.layui&&layui.define,o={getPath:function(){var e=document.currentScript?document.currentScript.src:function(){for(var e,t=document.scripts,i=t.length-1,n=i;n>0;n--)if(\"interactive\"===t[n].readyState){e=t[n].src;break}return e||t[i].src}();return e.substring(0,e.lastIndexOf(\"/\")+1)}(),config:{},end:{},minIndex:0,minLeft:[],btn:[\"&#x786E;&#x5B9A;\",\"&#x53D6;&#x6D88;\"],type:[\"dialog\",\"page\",\"iframe\",\"loading\",\"tips\"],getStyle:function(t,i){var n=t.currentStyle?t.currentStyle:e.getComputedStyle(t,null);return n[n.getPropertyValue?\"getPropertyValue\":\"getAttribute\"](i)},link:function(t,i,n){if(r.path){var a=document.getElementsByTagName(\"head\")[0],s=document.createElement(\"link\");\"string\"==typeof i&&(n=i);var l=(n||t).replace(/\\.|\\//g,\"\"),f=\"layuicss-\"+l,c=0;s.rel=\"stylesheet\",s.href=r.path+t,s.id=f,document.getElementById(f)||a.appendChild(s),\"function\"==typeof i&&!function u(){return++c>80?e.console&&console.error(\"layer.css: Invalid\"):void(1989===parseInt(o.getStyle(document.getElementById(f),\"width\"))?i():setTimeout(u,100))}()}}},r={v:\"3.1.1\",ie:function(){var t=navigator.userAgent.toLowerCase();return!!(e.ActiveXObject||\"ActiveXObject\"in e)&&((t.match(/msie\\s(\\d+)/)||[])[1]||\"11\")}(),index:e.layer&&e.layer.v?1e5:0,path:o.getPath,config:function(e,t){return e=e||{},r.cache=o.config=i.extend({},o.config,e),r.path=o.config.path||r.path,\"string\"==typeof e.extend&&(e.extend=[e.extend]),o.config.path&&r.ready(),e.extend?(a?layui.addcss(\"modules/layer/\"+e.extend):o.link(\"theme/\"+e.extend),this):this},ready:function(e){var t=\"layer\",i=\"\",n=(a?\"modules/layer/\":\"theme/\")+\"default/layer.css?v=\"+r.v+i;return a?layui.addcss(n,e,t):o.link(n,e,t),this},alert:function(e,t,n){var a=\"function\"==typeof t;return a&&(n=t),r.open(i.extend({content:e,yes:n},a?{}:t))},confirm:function(e,t,n,a){var s=\"function\"==typeof t;return s&&(a=n,n=t),r.open(i.extend({content:e,btn:o.btn,yes:n,btn2:a},s?{}:t))},msg:function(e,n,a){var s=\"function\"==typeof n,f=o.config.skin,c=(f?f+\" \"+f+\"-msg\":\"\")||\"layui-layer-msg\",u=l.anim.length-1;return s&&(a=n),r.open(i.extend({content:e,time:3e3,shade:!1,skin:c,title:!1,closeBtn:!1,btn:!1,resize:!1,end:a},s&&!o.config.skin?{skin:c+\" layui-layer-hui\",anim:u}:function(){return n=n||{},(n.icon===-1||n.icon===t&&!o.config.skin)&&(n.skin=c+\" \"+(n.skin||\"layui-layer-hui\")),n}()))},load:function(e,t){return r.open(i.extend({type:3,icon:e||0,resize:!1,shade:.01},t))},tips:function(e,t,n){return r.open(i.extend({type:4,content:[e,t],closeBtn:!1,time:3e3,shade:!1,resize:!1,fixed:!1,maxWidth:210},n))}},s=function(e){var t=this;t.index=++r.index,t.config=i.extend({},t.config,o.config,e),document.body?t.creat():setTimeout(function(){t.creat()},30)};s.pt=s.prototype;var l=[\"layui-layer\",\".layui-layer-title\",\".layui-layer-main\",\".layui-layer-dialog\",\"layui-layer-iframe\",\"layui-layer-content\",\"layui-layer-btn\",\"layui-layer-close\"];l.anim=[\"layer-anim-00\",\"layer-anim-01\",\"layer-anim-02\",\"layer-anim-03\",\"layer-anim-04\",\"layer-anim-05\",\"layer-anim-06\"],s.pt.config={type:0,shade:.3,fixed:!0,move:l[1],title:\"&#x4FE1;&#x606F;\",offset:\"auto\",area:\"auto\",closeBtn:1,time:0,zIndex:19891014,maxWidth:360,anim:0,isOutAnim:!0,icon:-1,moveType:1,resize:!0,scrollbar:!0,tips:2},s.pt.vessel=function(e,t){var n=this,a=n.index,r=n.config,s=r.zIndex+a,f=\"object\"==typeof r.title,c=r.maxmin&&(1===r.type||2===r.type),u=r.title?'<div class=\"layui-layer-title\" style=\"'+(f?r.title[1]:\"\")+'\">'+(f?r.title[0]:r.title)+\"</div>\":\"\";return r.zIndex=s,t([r.shade?'<div class=\"layui-layer-shade\" id=\"layui-layer-shade'+a+'\" times=\"'+a+'\" style=\"'+(\"z-index:\"+(s-1)+\"; \")+'\"></div>':\"\",'<div class=\"'+l[0]+(\" layui-layer-\"+o.type[r.type])+(0!=r.type&&2!=r.type||r.shade?\"\":\" layui-layer-border\")+\" \"+(r.skin||\"\")+'\" id=\"'+l[0]+a+'\" type=\"'+o.type[r.type]+'\" times=\"'+a+'\" showtime=\"'+r.time+'\" conType=\"'+(e?\"object\":\"string\")+'\" style=\"z-index: '+s+\"; width:\"+r.area[0]+\";height:\"+r.area[1]+(r.fixed?\"\":\";position:absolute;\")+'\">'+(e&&2!=r.type?\"\":u)+'<div id=\"'+(r.id||\"\")+'\" class=\"layui-layer-content'+(0==r.type&&r.icon!==-1?\" layui-layer-padding\":\"\")+(3==r.type?\" layui-layer-loading\"+r.icon:\"\")+'\">'+(0==r.type&&r.icon!==-1?'<i class=\"layui-layer-ico layui-layer-ico'+r.icon+'\"></i>':\"\")+(1==r.type&&e?\"\":r.content||\"\")+'</div><span class=\"layui-layer-setwin\">'+function(){var e=c?'<a class=\"layui-layer-min\" href=\"javascript:;\"><cite></cite></a><a class=\"layui-layer-ico layui-layer-max\" href=\"javascript:;\"></a>':\"\";return r.closeBtn&&(e+='<a class=\"layui-layer-ico '+l[7]+\" \"+l[7]+(r.title?r.closeBtn:4==r.type?\"1\":\"2\")+'\" href=\"javascript:;\"></a>'),e}()+\"</span>\"+(r.btn?function(){var e=\"\";\"string\"==typeof r.btn&&(r.btn=[r.btn]);for(var t=0,i=r.btn.length;t<i;t++)e+='<a class=\"'+l[6]+t+'\">'+r.btn[t]+\"</a>\";return'<div class=\"'+l[6]+\" layui-layer-btn-\"+(r.btnAlign||\"\")+'\">'+e+\"</div>\"}():\"\")+(r.resize?'<span class=\"layui-layer-resize\"></span>':\"\")+\"</div>\"],u,i('<div class=\"layui-layer-move\"></div>')),n},s.pt.creat=function(){var e=this,t=e.config,a=e.index,s=t.content,f=\"object\"==typeof s,c=i(\"body\");if(!t.id||!i(\"#\"+t.id)[0]){switch(\"string\"==typeof t.area&&(t.area=\"auto\"===t.area?[\"\",\"\"]:[t.area,\"\"]),t.shift&&(t.anim=t.shift),6==r.ie&&(t.fixed=!1),t.type){case 0:t.btn=\"btn\"in t?t.btn:o.btn[0],r.closeAll(\"dialog\");break;case 2:var s=t.content=f?t.content:[t.content||\"http://layer.layui.com\",\"auto\"];t.content='<iframe scrolling=\"'+(t.content[1]||\"auto\")+'\" allowtransparency=\"true\" id=\"'+l[4]+a+'\" name=\"'+l[4]+a+'\" onload=\"this.className=\\'\\';\" class=\"layui-layer-load\" frameborder=\"0\" src=\"'+t.content[0]+'\"></iframe>';break;case 3:delete t.title,delete t.closeBtn,t.icon===-1&&0===t.icon,r.closeAll(\"loading\");break;case 4:f||(t.content=[t.content,\"body\"]),t.follow=t.content[1],t.content=t.content[0]+'<i class=\"layui-layer-TipsG\"></i>',delete t.title,t.tips=\"object\"==typeof t.tips?t.tips:[t.tips,!0],t.tipsMore||r.closeAll(\"tips\")}if(e.vessel(f,function(n,r,u){c.append(n[0]),f?function(){2==t.type||4==t.type?function(){i(\"body\").append(n[1])}():function(){s.parents(\".\"+l[0])[0]||(s.data(\"display\",s.css(\"display\")).show().addClass(\"layui-layer-wrap\").wrap(n[1]),i(\"#\"+l[0]+a).find(\".\"+l[5]).before(r))}()}():c.append(n[1]),i(\".layui-layer-move\")[0]||c.append(o.moveElem=u),e.layero=i(\"#\"+l[0]+a),t.scrollbar||l.html.css(\"overflow\",\"hidden\").attr(\"layer-full\",a)}).auto(a),i(\"#layui-layer-shade\"+e.index).css({\"background-color\":t.shade[1]||\"#000\",opacity:t.shade[0]||t.shade}),2==t.type&&6==r.ie&&e.layero.find(\"iframe\").attr(\"src\",s[0]),4==t.type?e.tips():e.offset(),t.fixed&&n.on(\"resize\",function(){e.offset(),(/^\\d+%$/.test(t.area[0])||/^\\d+%$/.test(t.area[1]))&&e.auto(a),4==t.type&&e.tips()}),t.time<=0||setTimeout(function(){r.close(e.index)},t.time),e.move().callback(),l.anim[t.anim]){var u=\"layer-anim \"+l.anim[t.anim];e.layero.addClass(u).one(\"webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend\",function(){i(this).removeClass(u)})}t.isOutAnim&&e.layero.data(\"isOutAnim\",!0)}},s.pt.auto=function(e){var t=this,a=t.config,o=i(\"#\"+l[0]+e);\"\"===a.area[0]&&a.maxWidth>0&&(r.ie&&r.ie<8&&a.btn&&o.width(o.innerWidth()),o.outerWidth()>a.maxWidth&&o.width(a.maxWidth));var s=[o.innerWidth(),o.innerHeight()],f=o.find(l[1]).outerHeight()||0,c=o.find(\".\"+l[6]).outerHeight()||0,u=function(e){e=o.find(e),e.height(s[1]-f-c-2*(0|parseFloat(e.css(\"padding-top\"))))};switch(a.type){case 2:u(\"iframe\");break;default:\"\"===a.area[1]?a.maxHeight>0&&o.outerHeight()>a.maxHeight?(s[1]=a.maxHeight,u(\".\"+l[5])):a.fixed&&s[1]>=n.height()&&(s[1]=n.height(),u(\".\"+l[5])):u(\".\"+l[5])}return t},s.pt.offset=function(){var e=this,t=e.config,i=e.layero,a=[i.outerWidth(),i.outerHeight()],o=\"object\"==typeof t.offset;e.offsetTop=(n.height()-a[1])/2,e.offsetLeft=(n.width()-a[0])/2,o?(e.offsetTop=t.offset[0],e.offsetLeft=t.offset[1]||e.offsetLeft):\"auto\"!==t.offset&&(\"t\"===t.offset?e.offsetTop=0:\"r\"===t.offset?e.offsetLeft=n.width()-a[0]:\"b\"===t.offset?e.offsetTop=n.height()-a[1]:\"l\"===t.offset?e.offsetLeft=0:\"lt\"===t.offset?(e.offsetTop=0,e.offsetLeft=0):\"lb\"===t.offset?(e.offsetTop=n.height()-a[1],e.offsetLeft=0):\"rt\"===t.offset?(e.offsetTop=0,e.offsetLeft=n.width()-a[0]):\"rb\"===t.offset?(e.offsetTop=n.height()-a[1],e.offsetLeft=n.width()-a[0]):e.offsetTop=t.offset),t.fixed||(e.offsetTop=/%$/.test(e.offsetTop)?n.height()*parseFloat(e.offsetTop)/100:parseFloat(e.offsetTop),e.offsetLeft=/%$/.test(e.offsetLeft)?n.width()*parseFloat(e.offsetLeft)/100:parseFloat(e.offsetLeft),e.offsetTop+=n.scrollTop(),e.offsetLeft+=n.scrollLeft()),i.attr(\"minLeft\")&&(e.offsetTop=n.height()-(i.find(l[1]).outerHeight()||0),e.offsetLeft=i.css(\"left\")),i.css({top:e.offsetTop,left:e.offsetLeft})},s.pt.tips=function(){var e=this,t=e.config,a=e.layero,o=[a.outerWidth(),a.outerHeight()],r=i(t.follow);r[0]||(r=i(\"body\"));var s={width:r.outerWidth(),height:r.outerHeight(),top:r.offset().top,left:r.offset().left},f=a.find(\".layui-layer-TipsG\"),c=t.tips[0];t.tips[1]||f.remove(),s.autoLeft=function(){s.left+o[0]-n.width()>0?(s.tipLeft=s.left+s.width-o[0],f.css({right:12,left:\"auto\"})):s.tipLeft=s.left},s.where=[function(){s.autoLeft(),s.tipTop=s.top-o[1]-10,f.removeClass(\"layui-layer-TipsB\").addClass(\"layui-layer-TipsT\").css(\"border-right-color\",t.tips[1])},function(){s.tipLeft=s.left+s.width+10,s.tipTop=s.top,f.removeClass(\"layui-layer-TipsL\").addClass(\"layui-layer-TipsR\").css(\"border-bottom-color\",t.tips[1])},function(){s.autoLeft(),s.tipTop=s.top+s.height+10,f.removeClass(\"layui-layer-TipsT\").addClass(\"layui-layer-TipsB\").css(\"border-right-color\",t.tips[1])},function(){s.tipLeft=s.left-o[0]-10,s.tipTop=s.top,f.removeClass(\"layui-layer-TipsR\").addClass(\"layui-layer-TipsL\").css(\"border-bottom-color\",t.tips[1])}],s.where[c-1](),1===c?s.top-(n.scrollTop()+o[1]+16)<0&&s.where[2]():2===c?n.width()-(s.left+s.width+o[0]+16)>0||s.where[3]():3===c?s.top-n.scrollTop()+s.height+o[1]+16-n.height()>0&&s.where[0]():4===c&&o[0]+16-s.left>0&&s.where[1](),a.find(\".\"+l[5]).css({\"background-color\":t.tips[1],\"padding-right\":t.closeBtn?\"30px\":\"\"}),a.css({left:s.tipLeft-(t.fixed?n.scrollLeft():0),top:s.tipTop-(t.fixed?n.scrollTop():0)})},s.pt.move=function(){var e=this,t=e.config,a=i(document),s=e.layero,l=s.find(t.move),f=s.find(\".layui-layer-resize\"),c={};return t.move&&l.css(\"cursor\",\"move\"),l.on(\"mousedown\",function(e){e.preventDefault(),t.move&&(c.moveStart=!0,c.offset=[e.clientX-parseFloat(s.css(\"left\")),e.clientY-parseFloat(s.css(\"top\"))],o.moveElem.css(\"cursor\",\"move\").show())}),f.on(\"mousedown\",function(e){e.preventDefault(),c.resizeStart=!0,c.offset=[e.clientX,e.clientY],c.area=[s.outerWidth(),s.outerHeight()],o.moveElem.css(\"cursor\",\"se-resize\").show()}),a.on(\"mousemove\",function(i){if(c.moveStart){var a=i.clientX-c.offset[0],o=i.clientY-c.offset[1],l=\"fixed\"===s.css(\"position\");if(i.preventDefault(),c.stX=l?0:n.scrollLeft(),c.stY=l?0:n.scrollTop(),!t.moveOut){var f=n.width()-s.outerWidth()+c.stX,u=n.height()-s.outerHeight()+c.stY;a<c.stX&&(a=c.stX),a>f&&(a=f),o<c.stY&&(o=c.stY),o>u&&(o=u)}s.css({left:a,top:o})}if(t.resize&&c.resizeStart){var a=i.clientX-c.offset[0],o=i.clientY-c.offset[1];i.preventDefault(),r.style(e.index,{width:c.area[0]+a,height:c.area[1]+o}),c.isResize=!0,t.resizing&&t.resizing(s)}}).on(\"mouseup\",function(e){c.moveStart&&(delete c.moveStart,o.moveElem.hide(),t.moveEnd&&t.moveEnd(s)),c.resizeStart&&(delete c.resizeStart,o.moveElem.hide())}),e},s.pt.callback=function(){function e(){var e=a.cancel&&a.cancel(t.index,n);e===!1||r.close(t.index)}var t=this,n=t.layero,a=t.config;t.openLayer(),a.success&&(2==a.type?n.find(\"iframe\").on(\"load\",function(){a.success(n,t.index)}):a.success(n,t.index)),6==r.ie&&t.IE6(n),n.find(\".\"+l[6]).children(\"a\").on(\"click\",function(){var e=i(this).index();if(0===e)a.yes?a.yes(t.index,n):a.btn1?a.btn1(t.index,n):r.close(t.index);else{var o=a[\"btn\"+(e+1)]&&a[\"btn\"+(e+1)](t.index,n);o===!1||r.close(t.index)}}),n.find(\".\"+l[7]).on(\"click\",e),a.shadeClose&&i(\"#layui-layer-shade\"+t.index).on(\"click\",function(){r.close(t.index)}),n.find(\".layui-layer-min\").on(\"click\",function(){var e=a.min&&a.min(n);e===!1||r.min(t.index,a)}),n.find(\".layui-layer-max\").on(\"click\",function(){i(this).hasClass(\"layui-layer-maxmin\")?(r.restore(t.index),a.restore&&a.restore(n)):(r.full(t.index,a),setTimeout(function(){a.full&&a.full(n)},100))}),a.end&&(o.end[t.index]=a.end)},o.reselect=function(){i.each(i(\"select\"),function(e,t){var n=i(this);n.parents(\".\"+l[0])[0]||1==n.attr(\"layer\")&&i(\".\"+l[0]).length<1&&n.removeAttr(\"layer\").show(),n=null})},s.pt.IE6=function(e){i(\"select\").each(function(e,t){var n=i(this);n.parents(\".\"+l[0])[0]||\"none\"===n.css(\"display\")||n.attr({layer:\"1\"}).hide(),n=null})},s.pt.openLayer=function(){var e=this;r.zIndex=e.config.zIndex,r.setTop=function(e){var t=function(){r.zIndex++,e.css(\"z-index\",r.zIndex+1)};return r.zIndex=parseInt(e[0].style.zIndex),e.on(\"mousedown\",t),r.zIndex}},o.record=function(e){var t=[e.width(),e.height(),e.position().top,e.position().left+parseFloat(e.css(\"margin-left\"))];e.find(\".layui-layer-max\").addClass(\"layui-layer-maxmin\"),e.attr({area:t})},o.rescollbar=function(e){l.html.attr(\"layer-full\")==e&&(l.html[0].style.removeProperty?l.html[0].style.removeProperty(\"overflow\"):l.html[0].style.removeAttribute(\"overflow\"),l.html.removeAttr(\"layer-full\"))},e.layer=r,r.getChildFrame=function(e,t){return t=t||i(\".\"+l[4]).attr(\"times\"),i(\"#\"+l[0]+t).find(\"iframe\").contents().find(e)},r.getFrameIndex=function(e){return i(\"#\"+e).parents(\".\"+l[4]).attr(\"times\")},r.iframeAuto=function(e){if(e){var t=r.getChildFrame(\"html\",e).outerHeight(),n=i(\"#\"+l[0]+e),a=n.find(l[1]).outerHeight()||0,o=n.find(\".\"+l[6]).outerHeight()||0;n.css({height:t+a+o}),n.find(\"iframe\").css({height:t})}},r.iframeSrc=function(e,t){i(\"#\"+l[0]+e).find(\"iframe\").attr(\"src\",t)},r.style=function(e,t,n){var a=i(\"#\"+l[0]+e),r=a.find(\".layui-layer-content\"),s=a.attr(\"type\"),f=a.find(l[1]).outerHeight()||0,c=a.find(\".\"+l[6]).outerHeight()||0;a.attr(\"minLeft\");s!==o.type[3]&&s!==o.type[4]&&(n||(parseFloat(t.width)<=260&&(t.width=260),parseFloat(t.height)-f-c<=64&&(t.height=64+f+c)),a.css(t),c=a.find(\".\"+l[6]).outerHeight(),s===o.type[2]?a.find(\"iframe\").css({height:parseFloat(t.height)-f-c}):r.css({height:parseFloat(t.height)-f-c-parseFloat(r.css(\"padding-top\"))-parseFloat(r.css(\"padding-bottom\"))}))},r.min=function(e,t){var a=i(\"#\"+l[0]+e),s=a.find(l[1]).outerHeight()||0,f=a.attr(\"minLeft\")||181*o.minIndex+\"px\",c=a.css(\"position\");o.record(a),o.minLeft[0]&&(f=o.minLeft[0],o.minLeft.shift()),a.attr(\"position\",c),r.style(e,{width:180,height:s,left:f,top:n.height()-s,position:\"fixed\",overflow:\"hidden\"},!0),a.find(\".layui-layer-min\").hide(),\"page\"===a.attr(\"type\")&&a.find(l[4]).hide(),o.rescollbar(e),a.attr(\"minLeft\")||o.minIndex++,a.attr(\"minLeft\",f)},r.restore=function(e){var t=i(\"#\"+l[0]+e),n=t.attr(\"area\").split(\",\");t.attr(\"type\");r.style(e,{width:parseFloat(n[0]),height:parseFloat(n[1]),top:parseFloat(n[2]),left:parseFloat(n[3]),position:t.attr(\"position\"),overflow:\"visible\"},!0),t.find(\".layui-layer-max\").removeClass(\"layui-layer-maxmin\"),t.find(\".layui-layer-min\").show(),\"page\"===t.attr(\"type\")&&t.find(l[4]).show(),o.rescollbar(e)},r.full=function(e){var t,a=i(\"#\"+l[0]+e);o.record(a),l.html.attr(\"layer-full\")||l.html.css(\"overflow\",\"hidden\").attr(\"layer-full\",e),clearTimeout(t),t=setTimeout(function(){var t=\"fixed\"===a.css(\"position\");r.style(e,{top:t?0:n.scrollTop(),left:t?0:n.scrollLeft(),width:n.width(),height:n.height()},!0),a.find(\".layui-layer-min\").hide()},100)},r.title=function(e,t){var n=i(\"#\"+l[0]+(t||r.index)).find(l[1]);n.html(e)},r.close=function(e){var t=i(\"#\"+l[0]+e),n=t.attr(\"type\"),a=\"layer-anim-close\";if(t[0]){var s=\"layui-layer-wrap\",f=function(){if(n===o.type[1]&&\"object\"===t.attr(\"conType\")){t.children(\":not(.\"+l[5]+\")\").remove();for(var a=t.find(\".\"+s),r=0;r<2;r++)a.unwrap();a.css(\"display\",a.data(\"display\")).removeClass(s)}else{if(n===o.type[2])try{var f=i(\"#\"+l[4]+e)[0];f.contentWindow.document.write(\"\"),f.contentWindow.close(),t.find(\".\"+l[5])[0].removeChild(f)}catch(c){}t[0].innerHTML=\"\",t.remove()}\"function\"==typeof o.end[e]&&o.end[e](),delete o.end[e]};t.data(\"isOutAnim\")&&t.addClass(\"layer-anim \"+a),i(\"#layui-layer-moves, #layui-layer-shade\"+e).remove(),6==r.ie&&o.reselect(),o.rescollbar(e),t.attr(\"minLeft\")&&(o.minIndex--,o.minLeft.push(t.attr(\"minLeft\"))),r.ie&&r.ie<10||!t.data(\"isOutAnim\")?f():setTimeout(function(){f()},200)}},r.closeAll=function(e){i.each(i(\".\"+l[0]),function(){var t=i(this),n=e?t.attr(\"type\")===e:1;n&&r.close(t.attr(\"times\")),n=null})};var f=r.cache||{},c=function(e){return f.skin?\" \"+f.skin+\" \"+f.skin+\"-\"+e:\"\"};r.prompt=function(e,t){var a=\"\";if(e=e||{},\"function\"==typeof e&&(t=e),e.area){var o=e.area;a='style=\"width: '+o[0]+\"; height: \"+o[1]+';\"',delete e.area}var s,l=2==e.formType?'<textarea class=\"layui-layer-input\"'+a+\"></textarea>\":function(){return'<input type=\"'+(1==e.formType?\"password\":\"text\")+'\" class=\"layui-layer-input\">'}(),f=e.success;return delete e.success,r.open(i.extend({type:1,btn:[\"&#x786E;&#x5B9A;\",\"&#x53D6;&#x6D88;\"],content:l,skin:\"layui-layer-prompt\"+c(\"prompt\"),maxWidth:n.width(),success:function(t){s=t.find(\".layui-layer-input\"),s.val(e.value||\"\").focus(),\"function\"==typeof f&&f(t)},resize:!1,yes:function(i){var n=s.val();\"\"===n?s.focus():n.length>(e.maxlength||500)?r.tips(\"&#x6700;&#x591A;&#x8F93;&#x5165;\"+(e.maxlength||500)+\"&#x4E2A;&#x5B57;&#x6570;\",s,{tips:1}):t&&t(n,i,s)}},e))},r.tab=function(e){e=e||{};var t=e.tab||{},n=\"layui-this\",a=e.success;return delete e.success,r.open(i.extend({type:1,skin:\"layui-layer-tab\"+c(\"tab\"),resize:!1,title:function(){var e=t.length,i=1,a=\"\";if(e>0)for(a='<span class=\"'+n+'\">'+t[0].title+\"</span>\";i<e;i++)a+=\"<span>\"+t[i].title+\"</span>\";return a}(),content:'<ul class=\"layui-layer-tabmain\">'+function(){var e=t.length,i=1,a=\"\";if(e>0)for(a='<li class=\"layui-layer-tabli '+n+'\">'+(t[0].content||\"no content\")+\"</li>\";i<e;i++)a+='<li class=\"layui-layer-tabli\">'+(t[i].content||\"no  content\")+\"</li>\";return a}()+\"</ul>\",success:function(t){var o=t.find(\".layui-layer-title\").children(),r=t.find(\".layui-layer-tabmain\").children();o.on(\"mousedown\",function(t){t.stopPropagation?t.stopPropagation():t.cancelBubble=!0;var a=i(this),o=a.index();a.addClass(n).siblings().removeClass(n),r.eq(o).show().siblings().hide(),\"function\"==typeof e.change&&e.change(o)}),\"function\"==typeof a&&a(t)}},e))},r.photos=function(t,n,a){function o(e,t,i){var n=new Image;return n.src=e,n.complete?t(n):(n.onload=function(){n.onload=null,t(n)},void(n.onerror=function(e){n.onerror=null,i(e)}))}var s={};if(t=t||{},t.photos){var l=t.photos.constructor===Object,f=l?t.photos:{},u=f.data||[],d=f.start||0;s.imgIndex=(0|d)+1,t.img=t.img||\"img\";var y=t.success;if(delete t.success,l){if(0===u.length)return r.msg(\"&#x6CA1;&#x6709;&#x56FE;&#x7247;\")}else{var p=i(t.photos),h=function(){u=[],p.find(t.img).each(function(e){var t=i(this);t.attr(\"layer-index\",e),u.push({alt:t.attr(\"alt\"),pid:t.attr(\"layer-pid\"),src:t.attr(\"layer-src\")||t.attr(\"src\"),thumb:t.attr(\"src\")})})};if(h(),0===u.length)return;if(n||p.on(\"click\",t.img,function(){var e=i(this),n=e.attr(\"layer-index\");r.photos(i.extend(t,{photos:{start:n,data:u,tab:t.tab},full:t.full}),!0),h()}),!n)return}s.imgprev=function(e){s.imgIndex--,s.imgIndex<1&&(s.imgIndex=u.length),s.tabimg(e)},s.imgnext=function(e,t){s.imgIndex++,s.imgIndex>u.length&&(s.imgIndex=1,t)||s.tabimg(e)},s.keyup=function(e){if(!s.end){var t=e.keyCode;e.preventDefault(),37===t?s.imgprev(!0):39===t?s.imgnext(!0):27===t&&r.close(s.index)}},s.tabimg=function(e){if(!(u.length<=1))return f.start=s.imgIndex-1,r.close(s.index),r.photos(t,!0,e)},s.event=function(){s.bigimg.hover(function(){s.imgsee.show()},function(){s.imgsee.hide()}),s.bigimg.find(\".layui-layer-imgprev\").on(\"click\",function(e){e.preventDefault(),s.imgprev()}),s.bigimg.find(\".layui-layer-imgnext\").on(\"click\",function(e){e.preventDefault(),s.imgnext()}),i(document).on(\"keyup\",s.keyup)},s.loadi=r.load(1,{shade:!(\"shade\"in t)&&.9,scrollbar:!1}),o(u[d].src,function(n){r.close(s.loadi),s.index=r.open(i.extend({type:1,id:\"layui-layer-photos\",area:function(){var a=[n.width,n.height],o=[i(e).width()-100,i(e).height()-100];if(!t.full&&(a[0]>o[0]||a[1]>o[1])){var r=[a[0]/o[0],a[1]/o[1]];r[0]>r[1]?(a[0]=a[0]/r[0],a[1]=a[1]/r[0]):r[0]<r[1]&&(a[0]=a[0]/r[1],a[1]=a[1]/r[1])}return[a[0]+\"px\",a[1]+\"px\"]}(),title:!1,shade:.9,shadeClose:!0,closeBtn:!1,move:\".layui-layer-phimg img\",moveType:1,scrollbar:!1,moveOut:!0,isOutAnim:!1,skin:\"layui-layer-photos\"+c(\"photos\"),content:'<div class=\"layui-layer-phimg\"><img src=\"'+u[d].src+'\" alt=\"'+(u[d].alt||\"\")+'\" layer-pid=\"'+u[d].pid+'\"><div class=\"layui-layer-imgsee\">'+(u.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:'+(a?\"block\":\"\")+'\"><span class=\"layui-layer-imgtit\"><a href=\"javascript:;\">'+(u[d].alt||\"\")+\"</a><em>\"+s.imgIndex+\"/\"+u.length+\"</em></span></div></div></div>\",success:function(e,i){s.bigimg=e.find(\".layui-layer-phimg\"),s.imgsee=e.find(\".layui-layer-imguide,.layui-layer-imgbar\"),s.event(e),t.tab&&t.tab(u[d],e),\"function\"==typeof y&&y(e)},end:function(){s.end=!0,i(document).off(\"keyup\",s.keyup)}},t))},function(){r.close(s.loadi),r.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(){u.length>1&&s.imgnext(!0,!0)}})})}},o.run=function(t){i=t,n=i(e),l.html=i(\"html\"),r.open=function(e){var t=new s(e);return t.index}},e.layui&&layui.define?(r.ready(),layui.define(\"jquery\",function(t){r.path=layui.cache.dir,o.run(layui.$),e.layer=r,t(\"layer\",r)})):\"function\"==typeof define&&define.amd?define([\"jquery\"],function(){return o.run(e.jQuery),r}):function(){o.run(e.jQuery),r.ready()}()}(window);"
  },
  {
    "path": "open-layui-web/src/main/view/static/layui/lay/modules/laypage.js",
    "content": "/** layui-v2.3.0-rc1 MIT License By https://www.layui.com */\n ;layui.define(function(e){\"use strict\";var a=document,t=\"getElementById\",n=\"getElementsByTagName\",i=\"laypage\",r=\"layui-disabled\",u=function(e){var a=this;a.config=e||{},a.config.index=++s.index,a.render(!0)};u.prototype.type=function(){var e=this.config;if(\"object\"==typeof e.elem)return void 0===e.elem.length?2:3},u.prototype.view=function(){var e=this,a=e.config,t=a.groups=\"groups\"in a?0|a.groups:5;a.layout=\"object\"==typeof a.layout?a.layout:[\"prev\",\"page\",\"next\"],a.count=0|a.count,a.curr=0|a.curr||1,a.limits=\"object\"==typeof a.limits?a.limits:[10,20,30,40,50],a.limit=0|a.limit||10,a.pages=Math.ceil(a.count/a.limit)||1,a.curr>a.pages&&(a.curr=a.pages),t<0?t=1:t>a.pages&&(t=a.pages),a.prev=\"prev\"in a?a.prev:\"&#x4E0A;&#x4E00;&#x9875;\",a.next=\"next\"in a?a.next:\"&#x4E0B;&#x4E00;&#x9875;\";var n=a.pages>t?Math.ceil((a.curr+(t>1?1:0))/(t>0?t:1)):1,i={prev:function(){return a.prev?'<a href=\"javascript:;\" class=\"layui-laypage-prev'+(1==a.curr?\" \"+r:\"\")+'\" data-page=\"'+(a.curr-1)+'\">'+a.prev+\"</a>\":\"\"}(),page:function(){var e=[];if(a.count<1)return\"\";n>1&&a.first!==!1&&0!==t&&e.push('<a href=\"javascript:;\" class=\"layui-laypage-first\" data-page=\"1\"  title=\"&#x9996;&#x9875;\">'+(a.first||1)+\"</a>\");var i=Math.floor((t-1)/2),r=n>1?a.curr-i:1,u=n>1?function(){var e=a.curr+(t-i-1);return e>a.pages?a.pages:e}():t;for(u-r<t-1&&(r=u-t+1),a.first!==!1&&r>2&&e.push('<span class=\"layui-laypage-spr\">&#x2026;</span>');r<=u;r++)r===a.curr?e.push('<span class=\"layui-laypage-curr\"><em class=\"layui-laypage-em\" '+(/^#/.test(a.theme)?'style=\"background-color:'+a.theme+';\"':\"\")+\"></em><em>\"+r+\"</em></span>\"):e.push('<a href=\"javascript:;\" data-page=\"'+r+'\">'+r+\"</a>\");return a.pages>t&&a.pages>u&&a.last!==!1&&(u+1<a.pages&&e.push('<span class=\"layui-laypage-spr\">&#x2026;</span>'),0!==t&&e.push('<a href=\"javascript:;\" class=\"layui-laypage-last\" title=\"&#x5C3E;&#x9875;\"  data-page=\"'+a.pages+'\">'+(a.last||a.pages)+\"</a>\")),e.join(\"\")}(),next:function(){return a.next?'<a href=\"javascript:;\" class=\"layui-laypage-next'+(a.curr==a.pages?\" \"+r:\"\")+'\" data-page=\"'+(a.curr+1)+'\">'+a.next+\"</a>\":\"\"}(),count:'<span class=\"layui-laypage-count\">共 '+a.count+\" 条</span>\",limit:function(){var e=['<span class=\"layui-laypage-limits\"><select lay-ignore>'];return layui.each(a.limits,function(t,n){e.push('<option value=\"'+n+'\"'+(n===a.limit?\"selected\":\"\")+\">\"+n+\" 条/页</option>\")}),e.join(\"\")+\"</select></span>\"}(),refresh:['<a href=\"javascript:;\" data-page=\"'+a.curr+'\" class=\"layui-laypage-refresh\">','<i class=\"layui-icon layui-icon-refresh\"></i>',\"</a>\"].join(\"\"),skip:function(){return['<span class=\"layui-laypage-skip\">&#x5230;&#x7B2C;','<input type=\"text\" min=\"1\" value=\"'+a.curr+'\" class=\"layui-input\">','&#x9875;<button type=\"button\" class=\"layui-laypage-btn\">&#x786e;&#x5b9a;</button>',\"</span>\"].join(\"\")}()};return['<div class=\"layui-box layui-laypage layui-laypage-'+(a.theme?/^#/.test(a.theme)?\"molv\":a.theme:\"default\")+'\" id=\"layui-laypage-'+a.index+'\">',function(){var e=[];return layui.each(a.layout,function(a,t){i[t]&&e.push(i[t])}),e.join(\"\")}(),\"</div>\"].join(\"\")},u.prototype.jump=function(e,a){if(e){var t=this,i=t.config,r=e.children,u=e[n](\"button\")[0],l=e[n](\"input\")[0],p=e[n](\"select\")[0],c=function(){var e=0|l.value.replace(/\\s|\\D/g,\"\");e&&(i.curr=e,t.render())};if(a)return c();for(var o=0,y=r.length;o<y;o++)\"a\"===r[o].nodeName.toLowerCase()&&s.on(r[o],\"click\",function(){var e=0|this.getAttribute(\"data-page\");e<1||e>i.pages||(i.curr=e,t.render())});p&&s.on(p,\"change\",function(){var e=this.value;i.curr*e>i.count&&(i.curr=Math.ceil(i.count/e)),i.limit=e,t.render()}),u&&s.on(u,\"click\",function(){c()})}},u.prototype.skip=function(e){if(e){var a=this,t=e[n](\"input\")[0];t&&s.on(t,\"keyup\",function(t){var n=this.value,i=t.keyCode;/^(37|38|39|40)$/.test(i)||(/\\D/.test(n)&&(this.value=n.replace(/\\D/,\"\")),13===i&&a.jump(e,!0))})}},u.prototype.render=function(e){var n=this,i=n.config,r=n.type(),u=n.view();2===r?i.elem&&(i.elem.innerHTML=u):3===r?i.elem.html(u):a[t](i.elem)&&(a[t](i.elem).innerHTML=u),i.jump&&i.jump(i,e);var s=a[t](\"layui-laypage-\"+i.index);n.jump(s),i.hash&&!e&&(location.hash=\"!\"+i.hash+\"=\"+i.curr),n.skip(s)};var s={render:function(e){var a=new u(e);return a.index},index:layui.laypage?layui.laypage.index+1e4:0,on:function(e,a,t){return e.attachEvent?e.attachEvent(\"on\"+a,function(a){a.target=a.srcElement,t.call(e,a)}):e.addEventListener(a,t,!1),this}};e(i,s)});"
  },
  {
    "path": "open-layui-web/src/main/view/static/layui/lay/modules/laytpl.js",
    "content": "/** layui-v2.3.0-rc1 MIT License By https://www.layui.com */\n ;layui.define(function(e){\"use strict\";var r={open:\"{{\",close:\"}}\"},c={exp:function(e){return new RegExp(e,\"g\")},query:function(e,c,t){var o=[\"#([\\\\s\\\\S])+?\",\"([^{#}])*?\"][e||0];return n((c||\"\")+r.open+o+r.close+(t||\"\"))},escape:function(e){return String(e||\"\").replace(/&(?!#?[a-zA-Z0-9]+;)/g,\"&amp;\").replace(/</g,\"&lt;\").replace(/>/g,\"&gt;\").replace(/'/g,\"&#39;\").replace(/\"/g,\"&quot;\")},error:function(e,r){var c=\"Laytpl Error：\";return\"object\"==typeof console&&console.error(c+e+\"\\n\"+(r||\"\")),c+e}},n=c.exp,t=function(e){this.tpl=e};t.pt=t.prototype,window.errors=0,t.pt.parse=function(e,t){var o=this,p=e,a=n(\"^\"+r.open+\"#\",\"\"),l=n(r.close+\"$\",\"\");e=e.replace(/\\s+|\\r|\\t|\\n/g,\" \").replace(n(r.open+\"#\"),r.open+\"# \").replace(n(r.close+\"}\"),\"} \"+r.close).replace(/\\\\/g,\"\\\\\\\\\").replace(n(r.open+\"!(.+?)!\"+r.close),function(e){return e=e.replace(n(\"^\"+r.open+\"!\"),\"\").replace(n(\"!\"+r.close),\"\").replace(n(r.open+\"|\"+r.close),function(e){return e.replace(/(.)/g,\"\\\\$1\")})}).replace(/(?=\"|')/g,\"\\\\\").replace(c.query(),function(e){return e=e.replace(a,\"\").replace(l,\"\"),'\";'+e.replace(/\\\\/g,\"\")+';view+=\"'}).replace(c.query(1),function(e){var c='\"+(';return e.replace(/\\s/g,\"\")===r.open+r.close?\"\":(e=e.replace(n(r.open+\"|\"+r.close),\"\"),/^=/.test(e)&&(e=e.replace(/^=/,\"\"),c='\"+_escape_('),c+e.replace(/\\\\/g,\"\")+')+\"')}),e='\"use strict\";var view = \"'+e+'\";return view;';try{return o.cache=e=new Function(\"d, _escape_\",e),e(t,c.escape)}catch(u){return delete o.cache,c.error(u,p)}},t.pt.render=function(e,r){var n,t=this;return e?(n=t.cache?t.cache(e,c.escape):t.parse(t.tpl,e),r?void r(n):n):c.error(\"no data\")};var o=function(e){return\"string\"!=typeof e?c.error(\"Template not found\"):new t(e)};o.config=function(e){e=e||{};for(var c in e)r[c]=e[c]},o.v=\"1.2.0\",e(\"laytpl\",o)});"
  },
  {
    "path": "open-layui-web/src/main/view/static/layui/lay/modules/mobile.js",
    "content": "/** layui-v2.3.0-rc1 MIT License By https://www.layui.com */\n ;layui.define(function(i){i(\"layui.mobile\",layui.v)});layui.define(function(e){\"use strict\";var r={open:\"{{\",close:\"}}\"},c={exp:function(e){return new RegExp(e,\"g\")},query:function(e,c,t){var o=[\"#([\\\\s\\\\S])+?\",\"([^{#}])*?\"][e||0];return n((c||\"\")+r.open+o+r.close+(t||\"\"))},escape:function(e){return String(e||\"\").replace(/&(?!#?[a-zA-Z0-9]+;)/g,\"&amp;\").replace(/</g,\"&lt;\").replace(/>/g,\"&gt;\").replace(/'/g,\"&#39;\").replace(/\"/g,\"&quot;\")},error:function(e,r){var c=\"Laytpl Error：\";return\"object\"==typeof console&&console.error(c+e+\"\\n\"+(r||\"\")),c+e}},n=c.exp,t=function(e){this.tpl=e};t.pt=t.prototype,window.errors=0,t.pt.parse=function(e,t){var o=this,p=e,a=n(\"^\"+r.open+\"#\",\"\"),l=n(r.close+\"$\",\"\");e=e.replace(/\\s+|\\r|\\t|\\n/g,\" \").replace(n(r.open+\"#\"),r.open+\"# \").replace(n(r.close+\"}\"),\"} \"+r.close).replace(/\\\\/g,\"\\\\\\\\\").replace(n(r.open+\"!(.+?)!\"+r.close),function(e){return e=e.replace(n(\"^\"+r.open+\"!\"),\"\").replace(n(\"!\"+r.close),\"\").replace(n(r.open+\"|\"+r.close),function(e){return e.replace(/(.)/g,\"\\\\$1\")})}).replace(/(?=\"|')/g,\"\\\\\").replace(c.query(),function(e){return e=e.replace(a,\"\").replace(l,\"\"),'\";'+e.replace(/\\\\/g,\"\")+';view+=\"'}).replace(c.query(1),function(e){var c='\"+(';return e.replace(/\\s/g,\"\")===r.open+r.close?\"\":(e=e.replace(n(r.open+\"|\"+r.close),\"\"),/^=/.test(e)&&(e=e.replace(/^=/,\"\"),c='\"+_escape_('),c+e.replace(/\\\\/g,\"\")+')+\"')}),e='\"use strict\";var view = \"'+e+'\";return view;';try{return o.cache=e=new Function(\"d, _escape_\",e),e(t,c.escape)}catch(u){return delete o.cache,c.error(u,p)}},t.pt.render=function(e,r){var n,t=this;return e?(n=t.cache?t.cache(e,c.escape):t.parse(t.tpl,e),r?void r(n):n):c.error(\"no data\")};var o=function(e){return\"string\"!=typeof e?c.error(\"Template not found\"):new t(e)};o.config=function(e){e=e||{};for(var c in e)r[c]=e[c]},o.v=\"1.2.0\",e(\"laytpl\",o)});layui.define(function(e){\"use strict\";var t=(window,document),i=\"querySelectorAll\",n=\"getElementsByClassName\",a=function(e){return t[i](e)},s={type:0,shade:!0,shadeClose:!0,fixed:!0,anim:\"scale\"},l={extend:function(e){var t=JSON.parse(JSON.stringify(s));for(var i in e)t[i]=e[i];return t},timer:{},end:{}};l.touch=function(e,t){e.addEventListener(\"click\",function(e){t.call(this,e)},!1)};var o=0,r=[\"layui-m-layer\"],d=function(e){var t=this;t.config=l.extend(e),t.view()};d.prototype.view=function(){var e=this,i=e.config,s=t.createElement(\"div\");e.id=s.id=r[0]+o,s.setAttribute(\"class\",r[0]+\" \"+r[0]+(i.type||0)),s.setAttribute(\"index\",o);var l=function(){var e=\"object\"==typeof i.title;return i.title?'<h3 style=\"'+(e?i.title[1]:\"\")+'\">'+(e?i.title[0]:i.title)+\"</h3>\":\"\"}(),d=function(){\"string\"==typeof i.btn&&(i.btn=[i.btn]);var e,t=(i.btn||[]).length;return 0!==t&&i.btn?(e='<span yes type=\"1\">'+i.btn[0]+\"</span>\",2===t&&(e='<span no type=\"0\">'+i.btn[1]+\"</span>\"+e),'<div class=\"layui-m-layerbtn\">'+e+\"</div>\"):\"\"}();if(i.fixed||(i.top=i.hasOwnProperty(\"top\")?i.top:100,i.style=i.style||\"\",i.style+=\" top:\"+(t.body.scrollTop+i.top)+\"px\"),2===i.type&&(i.content='<i></i><i class=\"layui-m-layerload\"></i><i></i><p>'+(i.content||\"\")+\"</p>\"),i.skin&&(i.anim=\"up\"),\"msg\"===i.skin&&(i.shade=!1),s.innerHTML=(i.shade?\"<div \"+(\"string\"==typeof i.shade?'style=\"'+i.shade+'\"':\"\")+' class=\"layui-m-layershade\"></div>':\"\")+'<div class=\"layui-m-layermain\" '+(i.fixed?\"\":'style=\"position:static;\"')+'><div class=\"layui-m-layersection\"><div class=\"layui-m-layerchild '+(i.skin?\"layui-m-layer-\"+i.skin+\" \":\"\")+(i.className?i.className:\"\")+\" \"+(i.anim?\"layui-m-anim-\"+i.anim:\"\")+'\" '+(i.style?'style=\"'+i.style+'\"':\"\")+\">\"+l+'<div class=\"layui-m-layercont\">'+i.content+\"</div>\"+d+\"</div></div></div>\",!i.type||2===i.type){var y=t[n](r[0]+i.type),u=y.length;u>=1&&c.close(y[0].getAttribute(\"index\"))}document.body.appendChild(s);var m=e.elem=a(\"#\"+e.id)[0];i.success&&i.success(m),e.index=o++,e.action(i,m)},d.prototype.action=function(e,t){var i=this;e.time&&(l.timer[i.index]=setTimeout(function(){c.close(i.index)},1e3*e.time));var a=function(){var t=this.getAttribute(\"type\");0==t?(e.no&&e.no(),c.close(i.index)):e.yes?e.yes(i.index):c.close(i.index)};if(e.btn)for(var s=t[n](\"layui-m-layerbtn\")[0].children,o=s.length,r=0;r<o;r++)l.touch(s[r],a);if(e.shade&&e.shadeClose){var d=t[n](\"layui-m-layershade\")[0];l.touch(d,function(){c.close(i.index,e.end)})}e.end&&(l.end[i.index]=e.end)};var c={v:\"2.0 m\",index:o,open:function(e){var t=new d(e||{});return t.index},close:function(e){var i=a(\"#\"+r[0]+e)[0];i&&(i.innerHTML=\"\",t.body.removeChild(i),clearTimeout(l.timer[e]),delete l.timer[e],\"function\"==typeof l.end[e]&&l.end[e](),delete l.end[e])},closeAll:function(){for(var e=t[n](r[0]),i=0,a=e.length;i<a;i++)c.close(0|e[0].getAttribute(\"index\"))}};e(\"layer-mobile\",c)});layui.define(function(t){var e=function(){function t(t){return null==t?String(t):J[W.call(t)]||\"object\"}function e(e){return\"function\"==t(e)}function n(t){return null!=t&&t==t.window}function r(t){return null!=t&&t.nodeType==t.DOCUMENT_NODE}function i(e){return\"object\"==t(e)}function o(t){return i(t)&&!n(t)&&Object.getPrototypeOf(t)==Object.prototype}function a(t){var e=!!t&&\"length\"in t&&t.length,r=T.type(t);return\"function\"!=r&&!n(t)&&(\"array\"==r||0===e||\"number\"==typeof e&&e>0&&e-1 in t)}function s(t){return A.call(t,function(t){return null!=t})}function u(t){return t.length>0?T.fn.concat.apply([],t):t}function c(t){return t.replace(/::/g,\"/\").replace(/([A-Z]+)([A-Z][a-z])/g,\"$1_$2\").replace(/([a-z\\d])([A-Z])/g,\"$1_$2\").replace(/_/g,\"-\").toLowerCase()}function l(t){return t in F?F[t]:F[t]=new RegExp(\"(^|\\\\s)\"+t+\"(\\\\s|$)\")}function f(t,e){return\"number\"!=typeof e||k[c(t)]?e:e+\"px\"}function h(t){var e,n;return $[t]||(e=L.createElement(t),L.body.appendChild(e),n=getComputedStyle(e,\"\").getPropertyValue(\"display\"),e.parentNode.removeChild(e),\"none\"==n&&(n=\"block\"),$[t]=n),$[t]}function p(t){return\"children\"in t?D.call(t.children):T.map(t.childNodes,function(t){if(1==t.nodeType)return t})}function d(t,e){var n,r=t?t.length:0;for(n=0;n<r;n++)this[n]=t[n];this.length=r,this.selector=e||\"\"}function m(t,e,n){for(j in e)n&&(o(e[j])||Q(e[j]))?(o(e[j])&&!o(t[j])&&(t[j]={}),Q(e[j])&&!Q(t[j])&&(t[j]=[]),m(t[j],e[j],n)):e[j]!==E&&(t[j]=e[j])}function v(t,e){return null==e?T(t):T(t).filter(e)}function g(t,n,r,i){return e(n)?n.call(t,r,i):n}function y(t,e,n){null==n?t.removeAttribute(e):t.setAttribute(e,n)}function x(t,e){var n=t.className||\"\",r=n&&n.baseVal!==E;return e===E?r?n.baseVal:n:void(r?n.baseVal=e:t.className=e)}function b(t){try{return t?\"true\"==t||\"false\"!=t&&(\"null\"==t?null:+t+\"\"==t?+t:/^[\\[\\{]/.test(t)?T.parseJSON(t):t):t}catch(e){return t}}function w(t,e){e(t);for(var n=0,r=t.childNodes.length;n<r;n++)w(t.childNodes[n],e)}var E,j,T,S,C,N,O=[],P=O.concat,A=O.filter,D=O.slice,L=window.document,$={},F={},k={\"column-count\":1,columns:1,\"font-weight\":1,\"line-height\":1,opacity:1,\"z-index\":1,zoom:1},M=/^\\s*<(\\w+|!)[^>]*>/,R=/^<(\\w+)\\s*\\/?>(?:<\\/\\1>|)$/,z=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/gi,Z=/^(?:body|html)$/i,q=/([A-Z])/g,H=[\"val\",\"css\",\"html\",\"text\",\"data\",\"width\",\"height\",\"offset\"],I=[\"after\",\"prepend\",\"before\",\"append\"],V=L.createElement(\"table\"),_=L.createElement(\"tr\"),B={tr:L.createElement(\"tbody\"),tbody:V,thead:V,tfoot:V,td:_,th:_,\"*\":L.createElement(\"div\")},U=/complete|loaded|interactive/,X=/^[\\w-]*$/,J={},W=J.toString,Y={},G=L.createElement(\"div\"),K={tabindex:\"tabIndex\",readonly:\"readOnly\",\"for\":\"htmlFor\",\"class\":\"className\",maxlength:\"maxLength\",cellspacing:\"cellSpacing\",cellpadding:\"cellPadding\",rowspan:\"rowSpan\",colspan:\"colSpan\",usemap:\"useMap\",frameborder:\"frameBorder\",contenteditable:\"contentEditable\"},Q=Array.isArray||function(t){return t instanceof Array};return Y.matches=function(t,e){if(!e||!t||1!==t.nodeType)return!1;var n=t.matches||t.webkitMatchesSelector||t.mozMatchesSelector||t.oMatchesSelector||t.matchesSelector;if(n)return n.call(t,e);var r,i=t.parentNode,o=!i;return o&&(i=G).appendChild(t),r=~Y.qsa(i,e).indexOf(t),o&&G.removeChild(t),r},C=function(t){return t.replace(/-+(.)?/g,function(t,e){return e?e.toUpperCase():\"\"})},N=function(t){return A.call(t,function(e,n){return t.indexOf(e)==n})},Y.fragment=function(t,e,n){var r,i,a;return R.test(t)&&(r=T(L.createElement(RegExp.$1))),r||(t.replace&&(t=t.replace(z,\"<$1></$2>\")),e===E&&(e=M.test(t)&&RegExp.$1),e in B||(e=\"*\"),a=B[e],a.innerHTML=\"\"+t,r=T.each(D.call(a.childNodes),function(){a.removeChild(this)})),o(n)&&(i=T(r),T.each(n,function(t,e){H.indexOf(t)>-1?i[t](e):i.attr(t,e)})),r},Y.Z=function(t,e){return new d(t,e)},Y.isZ=function(t){return t instanceof Y.Z},Y.init=function(t,n){var r;if(!t)return Y.Z();if(\"string\"==typeof t)if(t=t.trim(),\"<\"==t[0]&&M.test(t))r=Y.fragment(t,RegExp.$1,n),t=null;else{if(n!==E)return T(n).find(t);r=Y.qsa(L,t)}else{if(e(t))return T(L).ready(t);if(Y.isZ(t))return t;if(Q(t))r=s(t);else if(i(t))r=[t],t=null;else if(M.test(t))r=Y.fragment(t.trim(),RegExp.$1,n),t=null;else{if(n!==E)return T(n).find(t);r=Y.qsa(L,t)}}return Y.Z(r,t)},T=function(t,e){return Y.init(t,e)},T.extend=function(t){var e,n=D.call(arguments,1);return\"boolean\"==typeof t&&(e=t,t=n.shift()),n.forEach(function(n){m(t,n,e)}),t},Y.qsa=function(t,e){var n,r=\"#\"==e[0],i=!r&&\".\"==e[0],o=r||i?e.slice(1):e,a=X.test(o);return t.getElementById&&a&&r?(n=t.getElementById(o))?[n]:[]:1!==t.nodeType&&9!==t.nodeType&&11!==t.nodeType?[]:D.call(a&&!r&&t.getElementsByClassName?i?t.getElementsByClassName(o):t.getElementsByTagName(e):t.querySelectorAll(e))},T.contains=L.documentElement.contains?function(t,e){return t!==e&&t.contains(e)}:function(t,e){for(;e&&(e=e.parentNode);)if(e===t)return!0;return!1},T.type=t,T.isFunction=e,T.isWindow=n,T.isArray=Q,T.isPlainObject=o,T.isEmptyObject=function(t){var e;for(e in t)return!1;return!0},T.isNumeric=function(t){var e=Number(t),n=typeof t;return null!=t&&\"boolean\"!=n&&(\"string\"!=n||t.length)&&!isNaN(e)&&isFinite(e)||!1},T.inArray=function(t,e,n){return O.indexOf.call(e,t,n)},T.camelCase=C,T.trim=function(t){return null==t?\"\":String.prototype.trim.call(t)},T.uuid=0,T.support={},T.expr={},T.noop=function(){},T.map=function(t,e){var n,r,i,o=[];if(a(t))for(r=0;r<t.length;r++)n=e(t[r],r),null!=n&&o.push(n);else for(i in t)n=e(t[i],i),null!=n&&o.push(n);return u(o)},T.each=function(t,e){var n,r;if(a(t)){for(n=0;n<t.length;n++)if(e.call(t[n],n,t[n])===!1)return t}else for(r in t)if(e.call(t[r],r,t[r])===!1)return t;return t},T.grep=function(t,e){return A.call(t,e)},window.JSON&&(T.parseJSON=JSON.parse),T.each(\"Boolean Number String Function Array Date RegExp Object Error\".split(\" \"),function(t,e){J[\"[object \"+e+\"]\"]=e.toLowerCase()}),T.fn={constructor:Y.Z,length:0,forEach:O.forEach,reduce:O.reduce,push:O.push,sort:O.sort,splice:O.splice,indexOf:O.indexOf,concat:function(){var t,e,n=[];for(t=0;t<arguments.length;t++)e=arguments[t],n[t]=Y.isZ(e)?e.toArray():e;return P.apply(Y.isZ(this)?this.toArray():this,n)},map:function(t){return T(T.map(this,function(e,n){return t.call(e,n,e)}))},slice:function(){return T(D.apply(this,arguments))},ready:function(t){return U.test(L.readyState)&&L.body?t(T):L.addEventListener(\"DOMContentLoaded\",function(){t(T)},!1),this},get:function(t){return t===E?D.call(this):this[t>=0?t:t+this.length]},toArray:function(){return this.get()},size:function(){return this.length},remove:function(){return this.each(function(){null!=this.parentNode&&this.parentNode.removeChild(this)})},each:function(t){return O.every.call(this,function(e,n){return t.call(e,n,e)!==!1}),this},filter:function(t){return e(t)?this.not(this.not(t)):T(A.call(this,function(e){return Y.matches(e,t)}))},add:function(t,e){return T(N(this.concat(T(t,e))))},is:function(t){return this.length>0&&Y.matches(this[0],t)},not:function(t){var n=[];if(e(t)&&t.call!==E)this.each(function(e){t.call(this,e)||n.push(this)});else{var r=\"string\"==typeof t?this.filter(t):a(t)&&e(t.item)?D.call(t):T(t);this.forEach(function(t){r.indexOf(t)<0&&n.push(t)})}return T(n)},has:function(t){return this.filter(function(){return i(t)?T.contains(this,t):T(this).find(t).size()})},eq:function(t){return t===-1?this.slice(t):this.slice(t,+t+1)},first:function(){var t=this[0];return t&&!i(t)?t:T(t)},last:function(){var t=this[this.length-1];return t&&!i(t)?t:T(t)},find:function(t){var e,n=this;return e=t?\"object\"==typeof t?T(t).filter(function(){var t=this;return O.some.call(n,function(e){return T.contains(e,t)})}):1==this.length?T(Y.qsa(this[0],t)):this.map(function(){return Y.qsa(this,t)}):T()},closest:function(t,e){var n=[],i=\"object\"==typeof t&&T(t);return this.each(function(o,a){for(;a&&!(i?i.indexOf(a)>=0:Y.matches(a,t));)a=a!==e&&!r(a)&&a.parentNode;a&&n.indexOf(a)<0&&n.push(a)}),T(n)},parents:function(t){for(var e=[],n=this;n.length>0;)n=T.map(n,function(t){if((t=t.parentNode)&&!r(t)&&e.indexOf(t)<0)return e.push(t),t});return v(e,t)},parent:function(t){return v(N(this.pluck(\"parentNode\")),t)},children:function(t){return v(this.map(function(){return p(this)}),t)},contents:function(){return this.map(function(){return this.contentDocument||D.call(this.childNodes)})},siblings:function(t){return v(this.map(function(t,e){return A.call(p(e.parentNode),function(t){return t!==e})}),t)},empty:function(){return this.each(function(){this.innerHTML=\"\"})},pluck:function(t){return T.map(this,function(e){return e[t]})},show:function(){return this.each(function(){\"none\"==this.style.display&&(this.style.display=\"\"),\"none\"==getComputedStyle(this,\"\").getPropertyValue(\"display\")&&(this.style.display=h(this.nodeName))})},replaceWith:function(t){return this.before(t).remove()},wrap:function(t){var n=e(t);if(this[0]&&!n)var r=T(t).get(0),i=r.parentNode||this.length>1;return this.each(function(e){T(this).wrapAll(n?t.call(this,e):i?r.cloneNode(!0):r)})},wrapAll:function(t){if(this[0]){T(this[0]).before(t=T(t));for(var e;(e=t.children()).length;)t=e.first();T(t).append(this)}return this},wrapInner:function(t){var n=e(t);return this.each(function(e){var r=T(this),i=r.contents(),o=n?t.call(this,e):t;i.length?i.wrapAll(o):r.append(o)})},unwrap:function(){return this.parent().each(function(){T(this).replaceWith(T(this).children())}),this},clone:function(){return this.map(function(){return this.cloneNode(!0)})},hide:function(){return this.css(\"display\",\"none\")},toggle:function(t){return this.each(function(){var e=T(this);(t===E?\"none\"==e.css(\"display\"):t)?e.show():e.hide()})},prev:function(t){return T(this.pluck(\"previousElementSibling\")).filter(t||\"*\")},next:function(t){return T(this.pluck(\"nextElementSibling\")).filter(t||\"*\")},html:function(t){return 0 in arguments?this.each(function(e){var n=this.innerHTML;T(this).empty().append(g(this,t,e,n))}):0 in this?this[0].innerHTML:null},text:function(t){return 0 in arguments?this.each(function(e){var n=g(this,t,e,this.textContent);this.textContent=null==n?\"\":\"\"+n}):0 in this?this.pluck(\"textContent\").join(\"\"):null},attr:function(t,e){var n;return\"string\"!=typeof t||1 in arguments?this.each(function(n){if(1===this.nodeType)if(i(t))for(j in t)y(this,j,t[j]);else y(this,t,g(this,e,n,this.getAttribute(t)))}):0 in this&&1==this[0].nodeType&&null!=(n=this[0].getAttribute(t))?n:E},removeAttr:function(t){return this.each(function(){1===this.nodeType&&t.split(\" \").forEach(function(t){y(this,t)},this)})},prop:function(t,e){return t=K[t]||t,1 in arguments?this.each(function(n){this[t]=g(this,e,n,this[t])}):this[0]&&this[0][t]},removeProp:function(t){return t=K[t]||t,this.each(function(){delete this[t]})},data:function(t,e){var n=\"data-\"+t.replace(q,\"-$1\").toLowerCase(),r=1 in arguments?this.attr(n,e):this.attr(n);return null!==r?b(r):E},val:function(t){return 0 in arguments?(null==t&&(t=\"\"),this.each(function(e){this.value=g(this,t,e,this.value)})):this[0]&&(this[0].multiple?T(this[0]).find(\"option\").filter(function(){return this.selected}).pluck(\"value\"):this[0].value)},offset:function(t){if(t)return this.each(function(e){var n=T(this),r=g(this,t,e,n.offset()),i=n.offsetParent().offset(),o={top:r.top-i.top,left:r.left-i.left};\"static\"==n.css(\"position\")&&(o.position=\"relative\"),n.css(o)});if(!this.length)return null;if(L.documentElement!==this[0]&&!T.contains(L.documentElement,this[0]))return{top:0,left:0};var e=this[0].getBoundingClientRect();return{left:e.left+window.pageXOffset,top:e.top+window.pageYOffset,width:Math.round(e.width),height:Math.round(e.height)}},css:function(e,n){if(arguments.length<2){var r=this[0];if(\"string\"==typeof e){if(!r)return;return r.style[C(e)]||getComputedStyle(r,\"\").getPropertyValue(e)}if(Q(e)){if(!r)return;var i={},o=getComputedStyle(r,\"\");return T.each(e,function(t,e){i[e]=r.style[C(e)]||o.getPropertyValue(e)}),i}}var a=\"\";if(\"string\"==t(e))n||0===n?a=c(e)+\":\"+f(e,n):this.each(function(){this.style.removeProperty(c(e))});else for(j in e)e[j]||0===e[j]?a+=c(j)+\":\"+f(j,e[j])+\";\":this.each(function(){this.style.removeProperty(c(j))});return this.each(function(){this.style.cssText+=\";\"+a})},index:function(t){return t?this.indexOf(T(t)[0]):this.parent().children().indexOf(this[0])},hasClass:function(t){return!!t&&O.some.call(this,function(t){return this.test(x(t))},l(t))},addClass:function(t){return t?this.each(function(e){if(\"className\"in this){S=[];var n=x(this),r=g(this,t,e,n);r.split(/\\s+/g).forEach(function(t){T(this).hasClass(t)||S.push(t)},this),S.length&&x(this,n+(n?\" \":\"\")+S.join(\" \"))}}):this},removeClass:function(t){return this.each(function(e){if(\"className\"in this){if(t===E)return x(this,\"\");S=x(this),g(this,t,e,S).split(/\\s+/g).forEach(function(t){S=S.replace(l(t),\" \")}),x(this,S.trim())}})},toggleClass:function(t,e){return t?this.each(function(n){var r=T(this),i=g(this,t,n,x(this));i.split(/\\s+/g).forEach(function(t){(e===E?!r.hasClass(t):e)?r.addClass(t):r.removeClass(t)})}):this},scrollTop:function(t){if(this.length){var e=\"scrollTop\"in this[0];return t===E?e?this[0].scrollTop:this[0].pageYOffset:this.each(e?function(){this.scrollTop=t}:function(){this.scrollTo(this.scrollX,t)})}},scrollLeft:function(t){if(this.length){var e=\"scrollLeft\"in this[0];return t===E?e?this[0].scrollLeft:this[0].pageXOffset:this.each(e?function(){this.scrollLeft=t}:function(){this.scrollTo(t,this.scrollY)})}},position:function(){if(this.length){var t=this[0],e=this.offsetParent(),n=this.offset(),r=Z.test(e[0].nodeName)?{top:0,left:0}:e.offset();return n.top-=parseFloat(T(t).css(\"margin-top\"))||0,n.left-=parseFloat(T(t).css(\"margin-left\"))||0,r.top+=parseFloat(T(e[0]).css(\"border-top-width\"))||0,r.left+=parseFloat(T(e[0]).css(\"border-left-width\"))||0,{top:n.top-r.top,left:n.left-r.left}}},offsetParent:function(){return this.map(function(){for(var t=this.offsetParent||L.body;t&&!Z.test(t.nodeName)&&\"static\"==T(t).css(\"position\");)t=t.offsetParent;return t})}},T.fn.detach=T.fn.remove,[\"width\",\"height\"].forEach(function(t){var e=t.replace(/./,function(t){return t[0].toUpperCase()});T.fn[t]=function(i){var o,a=this[0];return i===E?n(a)?a[\"inner\"+e]:r(a)?a.documentElement[\"scroll\"+e]:(o=this.offset())&&o[t]:this.each(function(e){a=T(this),a.css(t,g(this,i,e,a[t]()))})}}),I.forEach(function(e,n){var r=n%2;T.fn[e]=function(){var e,i,o=T.map(arguments,function(n){var r=[];return e=t(n),\"array\"==e?(n.forEach(function(t){return t.nodeType!==E?r.push(t):T.zepto.isZ(t)?r=r.concat(t.get()):void(r=r.concat(Y.fragment(t)))}),r):\"object\"==e||null==n?n:Y.fragment(n)}),a=this.length>1;return o.length<1?this:this.each(function(t,e){i=r?e:e.parentNode,e=0==n?e.nextSibling:1==n?e.firstChild:2==n?e:null;var s=T.contains(L.documentElement,i);o.forEach(function(t){if(a)t=t.cloneNode(!0);else if(!i)return T(t).remove();i.insertBefore(t,e),s&&w(t,function(t){if(!(null==t.nodeName||\"SCRIPT\"!==t.nodeName.toUpperCase()||t.type&&\"text/javascript\"!==t.type||t.src)){var e=t.ownerDocument?t.ownerDocument.defaultView:window;e.eval.call(e,t.innerHTML)}})})})},T.fn[r?e+\"To\":\"insert\"+(n?\"Before\":\"After\")]=function(t){return T(t)[e](this),this}}),Y.Z.prototype=d.prototype=T.fn,Y.uniq=N,Y.deserializeValue=b,T.zepto=Y,T}();!function(t){function e(t){return t._zid||(t._zid=h++)}function n(t,n,o,a){if(n=r(n),n.ns)var s=i(n.ns);return(v[e(t)]||[]).filter(function(t){return t&&(!n.e||t.e==n.e)&&(!n.ns||s.test(t.ns))&&(!o||e(t.fn)===e(o))&&(!a||t.sel==a)})}function r(t){var e=(\"\"+t).split(\".\");return{e:e[0],ns:e.slice(1).sort().join(\" \")}}function i(t){return new RegExp(\"(?:^| )\"+t.replace(\" \",\" .* ?\")+\"(?: |$)\")}function o(t,e){return t.del&&!y&&t.e in x||!!e}function a(t){return b[t]||y&&x[t]||t}function s(n,i,s,u,l,h,p){var d=e(n),m=v[d]||(v[d]=[]);i.split(/\\s/).forEach(function(e){if(\"ready\"==e)return t(document).ready(s);var i=r(e);i.fn=s,i.sel=l,i.e in b&&(s=function(e){var n=e.relatedTarget;if(!n||n!==this&&!t.contains(this,n))return i.fn.apply(this,arguments)}),i.del=h;var d=h||s;i.proxy=function(t){if(t=c(t),!t.isImmediatePropagationStopped()){t.data=u;var e=d.apply(n,t._args==f?[t]:[t].concat(t._args));return e===!1&&(t.preventDefault(),t.stopPropagation()),e}},i.i=m.length,m.push(i),\"addEventListener\"in n&&n.addEventListener(a(i.e),i.proxy,o(i,p))})}function u(t,r,i,s,u){var c=e(t);(r||\"\").split(/\\s/).forEach(function(e){n(t,e,i,s).forEach(function(e){delete v[c][e.i],\"removeEventListener\"in t&&t.removeEventListener(a(e.e),e.proxy,o(e,u))})})}function c(e,n){return!n&&e.isDefaultPrevented||(n||(n=e),t.each(T,function(t,r){var i=n[t];e[t]=function(){return this[r]=w,i&&i.apply(n,arguments)},e[r]=E}),e.timeStamp||(e.timeStamp=Date.now()),(n.defaultPrevented!==f?n.defaultPrevented:\"returnValue\"in n?n.returnValue===!1:n.getPreventDefault&&n.getPreventDefault())&&(e.isDefaultPrevented=w)),e}function l(t){var e,n={originalEvent:t};for(e in t)j.test(e)||t[e]===f||(n[e]=t[e]);return c(n,t)}var f,h=1,p=Array.prototype.slice,d=t.isFunction,m=function(t){return\"string\"==typeof t},v={},g={},y=\"onfocusin\"in window,x={focus:\"focusin\",blur:\"focusout\"},b={mouseenter:\"mouseover\",mouseleave:\"mouseout\"};g.click=g.mousedown=g.mouseup=g.mousemove=\"MouseEvents\",t.event={add:s,remove:u},t.proxy=function(n,r){var i=2 in arguments&&p.call(arguments,2);if(d(n)){var o=function(){return n.apply(r,i?i.concat(p.call(arguments)):arguments)};return o._zid=e(n),o}if(m(r))return i?(i.unshift(n[r],n),t.proxy.apply(null,i)):t.proxy(n[r],n);throw new TypeError(\"expected function\")},t.fn.bind=function(t,e,n){return this.on(t,e,n)},t.fn.unbind=function(t,e){return this.off(t,e)},t.fn.one=function(t,e,n,r){return this.on(t,e,n,r,1)};var w=function(){return!0},E=function(){return!1},j=/^([A-Z]|returnValue$|layer[XY]$|webkitMovement[XY]$)/,T={preventDefault:\"isDefaultPrevented\",stopImmediatePropagation:\"isImmediatePropagationStopped\",stopPropagation:\"isPropagationStopped\"};t.fn.delegate=function(t,e,n){return this.on(e,t,n)},t.fn.undelegate=function(t,e,n){return this.off(e,t,n)},t.fn.live=function(e,n){return t(document.body).delegate(this.selector,e,n),this},t.fn.die=function(e,n){return t(document.body).undelegate(this.selector,e,n),this},t.fn.on=function(e,n,r,i,o){var a,c,h=this;return e&&!m(e)?(t.each(e,function(t,e){h.on(t,n,r,e,o)}),h):(m(n)||d(i)||i===!1||(i=r,r=n,n=f),i!==f&&r!==!1||(i=r,r=f),i===!1&&(i=E),h.each(function(f,h){o&&(a=function(t){return u(h,t.type,i),i.apply(this,arguments)}),n&&(c=function(e){var r,o=t(e.target).closest(n,h).get(0);if(o&&o!==h)return r=t.extend(l(e),{currentTarget:o,liveFired:h}),(a||i).apply(o,[r].concat(p.call(arguments,1)))}),s(h,e,i,r,n,c||a)}))},t.fn.off=function(e,n,r){var i=this;return e&&!m(e)?(t.each(e,function(t,e){i.off(t,n,e)}),i):(m(n)||d(r)||r===!1||(r=n,n=f),r===!1&&(r=E),i.each(function(){u(this,e,r,n)}))},t.fn.trigger=function(e,n){return e=m(e)||t.isPlainObject(e)?t.Event(e):c(e),e._args=n,this.each(function(){e.type in x&&\"function\"==typeof this[e.type]?this[e.type]():\"dispatchEvent\"in this?this.dispatchEvent(e):t(this).triggerHandler(e,n)})},t.fn.triggerHandler=function(e,r){var i,o;return this.each(function(a,s){i=l(m(e)?t.Event(e):e),i._args=r,i.target=s,t.each(n(s,e.type||e),function(t,e){if(o=e.proxy(i),i.isImmediatePropagationStopped())return!1})}),o},\"focusin focusout focus blur load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select keydown keypress keyup error\".split(\" \").forEach(function(e){t.fn[e]=function(t){return 0 in arguments?this.bind(e,t):this.trigger(e)}}),t.Event=function(t,e){m(t)||(e=t,t=e.type);var n=document.createEvent(g[t]||\"Events\"),r=!0;if(e)for(var i in e)\"bubbles\"==i?r=!!e[i]:n[i]=e[i];return n.initEvent(t,r,!0),c(n)}}(e),function(t){function e(e,n,r){var i=t.Event(n);return t(e).trigger(i,r),!i.isDefaultPrevented()}function n(t,n,r,i){if(t.global)return e(n||x,r,i)}function r(e){e.global&&0===t.active++&&n(e,null,\"ajaxStart\")}function i(e){e.global&&!--t.active&&n(e,null,\"ajaxStop\")}function o(t,e){var r=e.context;return e.beforeSend.call(r,t,e)!==!1&&n(e,r,\"ajaxBeforeSend\",[t,e])!==!1&&void n(e,r,\"ajaxSend\",[t,e])}function a(t,e,r,i){var o=r.context,a=\"success\";r.success.call(o,t,a,e),i&&i.resolveWith(o,[t,a,e]),n(r,o,\"ajaxSuccess\",[e,r,t]),u(a,e,r)}function s(t,e,r,i,o){var a=i.context;i.error.call(a,r,e,t),o&&o.rejectWith(a,[r,e,t]),n(i,a,\"ajaxError\",[r,i,t||e]),u(e,r,i)}function u(t,e,r){var o=r.context;r.complete.call(o,e,t),n(r,o,\"ajaxComplete\",[e,r]),i(r)}function c(t,e,n){if(n.dataFilter==l)return t;var r=n.context;return n.dataFilter.call(r,t,e)}function l(){}function f(t){return t&&(t=t.split(\";\",2)[0]),t&&(t==T?\"html\":t==j?\"json\":w.test(t)?\"script\":E.test(t)&&\"xml\")||\"text\"}function h(t,e){return\"\"==e?t:(t+\"&\"+e).replace(/[&?]{1,2}/,\"?\")}function p(e){e.processData&&e.data&&\"string\"!=t.type(e.data)&&(e.data=t.param(e.data,e.traditional)),!e.data||e.type&&\"GET\"!=e.type.toUpperCase()&&\"jsonp\"!=e.dataType||(e.url=h(e.url,e.data),e.data=void 0)}function d(e,n,r,i){return t.isFunction(n)&&(i=r,r=n,n=void 0),t.isFunction(r)||(i=r,r=void 0),{url:e,data:n,success:r,dataType:i}}function m(e,n,r,i){var o,a=t.isArray(n),s=t.isPlainObject(n);t.each(n,function(n,u){o=t.type(u),i&&(n=r?i:i+\"[\"+(s||\"object\"==o||\"array\"==o?n:\"\")+\"]\"),!i&&a?e.add(u.name,u.value):\"array\"==o||!r&&\"object\"==o?m(e,u,r,n):e.add(n,u)})}var v,g,y=+new Date,x=window.document,b=/<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi,w=/^(?:text|application)\\/javascript/i,E=/^(?:text|application)\\/xml/i,j=\"application/json\",T=\"text/html\",S=/^\\s*$/,C=x.createElement(\"a\");C.href=window.location.href,t.active=0,t.ajaxJSONP=function(e,n){if(!(\"type\"in e))return t.ajax(e);var r,i,u=e.jsonpCallback,c=(t.isFunction(u)?u():u)||\"Zepto\"+y++,l=x.createElement(\"script\"),f=window[c],h=function(e){t(l).triggerHandler(\"error\",e||\"abort\")},p={abort:h};return n&&n.promise(p),t(l).on(\"load error\",function(o,u){clearTimeout(i),t(l).off().remove(),\"error\"!=o.type&&r?a(r[0],p,e,n):s(null,u||\"error\",p,e,n),window[c]=f,r&&t.isFunction(f)&&f(r[0]),f=r=void 0}),o(p,e)===!1?(h(\"abort\"),p):(window[c]=function(){r=arguments},l.src=e.url.replace(/\\?(.+)=\\?/,\"?$1=\"+c),x.head.appendChild(l),e.timeout>0&&(i=setTimeout(function(){h(\"timeout\")},e.timeout)),p)},t.ajaxSettings={type:\"GET\",beforeSend:l,success:l,error:l,complete:l,context:null,global:!0,xhr:function(){return new window.XMLHttpRequest},accepts:{script:\"text/javascript, application/javascript, application/x-javascript\",json:j,xml:\"application/xml, text/xml\",html:T,text:\"text/plain\"},crossDomain:!1,timeout:0,processData:!0,cache:!0,dataFilter:l},t.ajax=function(e){var n,i,u=t.extend({},e||{}),d=t.Deferred&&t.Deferred();for(v in t.ajaxSettings)void 0===u[v]&&(u[v]=t.ajaxSettings[v]);r(u),u.crossDomain||(n=x.createElement(\"a\"),n.href=u.url,n.href=n.href,u.crossDomain=C.protocol+\"//\"+C.host!=n.protocol+\"//\"+n.host),u.url||(u.url=window.location.toString()),(i=u.url.indexOf(\"#\"))>-1&&(u.url=u.url.slice(0,i)),p(u);var m=u.dataType,y=/\\?.+=\\?/.test(u.url);if(y&&(m=\"jsonp\"),u.cache!==!1&&(e&&e.cache===!0||\"script\"!=m&&\"jsonp\"!=m)||(u.url=h(u.url,\"_=\"+Date.now())),\"jsonp\"==m)return y||(u.url=h(u.url,u.jsonp?u.jsonp+\"=?\":u.jsonp===!1?\"\":\"callback=?\")),t.ajaxJSONP(u,d);var b,w=u.accepts[m],E={},j=function(t,e){E[t.toLowerCase()]=[t,e]},T=/^([\\w-]+:)\\/\\//.test(u.url)?RegExp.$1:window.location.protocol,N=u.xhr(),O=N.setRequestHeader;if(d&&d.promise(N),u.crossDomain||j(\"X-Requested-With\",\"XMLHttpRequest\"),j(\"Accept\",w||\"*/*\"),(w=u.mimeType||w)&&(w.indexOf(\",\")>-1&&(w=w.split(\",\",2)[0]),N.overrideMimeType&&N.overrideMimeType(w)),(u.contentType||u.contentType!==!1&&u.data&&\"GET\"!=u.type.toUpperCase())&&j(\"Content-Type\",u.contentType||\"application/x-www-form-urlencoded\"),u.headers)for(g in u.headers)j(g,u.headers[g]);if(N.setRequestHeader=j,N.onreadystatechange=function(){if(4==N.readyState){N.onreadystatechange=l,clearTimeout(b);var e,n=!1;if(N.status>=200&&N.status<300||304==N.status||0==N.status&&\"file:\"==T){if(m=m||f(u.mimeType||N.getResponseHeader(\"content-type\")),\"arraybuffer\"==N.responseType||\"blob\"==N.responseType)e=N.response;else{e=N.responseText;try{e=c(e,m,u),\"script\"==m?(0,eval)(e):\"xml\"==m?e=N.responseXML:\"json\"==m&&(e=S.test(e)?null:t.parseJSON(e))}catch(r){n=r}if(n)return s(n,\"parsererror\",N,u,d)}a(e,N,u,d)}else s(N.statusText||null,N.status?\"error\":\"abort\",N,u,d)}},o(N,u)===!1)return N.abort(),s(null,\"abort\",N,u,d),N;var P=!(\"async\"in u)||u.async;if(N.open(u.type,u.url,P,u.username,u.password),u.xhrFields)for(g in u.xhrFields)N[g]=u.xhrFields[g];for(g in E)O.apply(N,E[g]);return u.timeout>0&&(b=setTimeout(function(){N.onreadystatechange=l,N.abort(),s(null,\"timeout\",N,u,d)},u.timeout)),N.send(u.data?u.data:null),N},t.get=function(){return t.ajax(d.apply(null,arguments))},t.post=function(){var e=d.apply(null,arguments);return e.type=\"POST\",t.ajax(e)},t.getJSON=function(){var e=d.apply(null,arguments);return e.dataType=\"json\",t.ajax(e)},t.fn.load=function(e,n,r){if(!this.length)return this;var i,o=this,a=e.split(/\\s/),s=d(e,n,r),u=s.success;return a.length>1&&(s.url=a[0],i=a[1]),s.success=function(e){o.html(i?t(\"<div>\").html(e.replace(b,\"\")).find(i):e),u&&u.apply(o,arguments)},t.ajax(s),this};var N=encodeURIComponent;t.param=function(e,n){var r=[];return r.add=function(e,n){t.isFunction(n)&&(n=n()),null==n&&(n=\"\"),this.push(N(e)+\"=\"+N(n))},m(r,e,n),r.join(\"&\").replace(/%20/g,\"+\")}}(e),function(t){t.fn.serializeArray=function(){var e,n,r=[],i=function(t){return t.forEach?t.forEach(i):void r.push({name:e,value:t})};return this[0]&&t.each(this[0].elements,function(r,o){n=o.type,e=o.name,e&&\"fieldset\"!=o.nodeName.toLowerCase()&&!o.disabled&&\"submit\"!=n&&\"reset\"!=n&&\"button\"!=n&&\"file\"!=n&&(\"radio\"!=n&&\"checkbox\"!=n||o.checked)&&i(t(o).val())}),r},t.fn.serialize=function(){var t=[];return this.serializeArray().forEach(function(e){t.push(encodeURIComponent(e.name)+\"=\"+encodeURIComponent(e.value))}),t.join(\"&\")},t.fn.submit=function(e){if(0 in arguments)this.bind(\"submit\",e);else if(this.length){var n=t.Event(\"submit\");this.eq(0).trigger(n),n.isDefaultPrevented()||this.get(0).submit()}return this}}(e),function(){try{getComputedStyle(void 0)}catch(t){var e=getComputedStyle;window.getComputedStyle=function(t,n){try{return e(t,n)}catch(r){return null}}}}(),t(\"zepto\",e)});layui.define([\"layer-mobile\",\"zepto\"],function(e){\"use strict\";var t=layui.zepto,a=layui[\"layer-mobile\"],i=(layui.device(),\"layui-upload-enter\"),n=\"layui-upload-iframe\",r={icon:2,shift:6},o={file:\"文件\",video:\"视频\",audio:\"音频\"};a.msg=function(e){return a.open({content:e||\"\",skin:\"msg\",time:2})};var s=function(e){this.options=e};s.prototype.init=function(){var e=this,a=e.options,r=t(\"body\"),s=t(a.elem||\".layui-upload-file\"),u=t('<iframe id=\"'+n+'\" class=\"'+n+'\" name=\"'+n+'\"></iframe>');return t(\"#\"+n)[0]||r.append(u),s.each(function(r,s){s=t(s);var u='<form target=\"'+n+'\" method=\"'+(a.method||\"post\")+'\" key=\"set-mine\" enctype=\"multipart/form-data\" action=\"'+(a.url||\"\")+'\"></form>',l=s.attr(\"lay-type\")||a.type;a.unwrap||(u='<div class=\"layui-box layui-upload-button\">'+u+'<span class=\"layui-upload-icon\"><i class=\"layui-icon\">&#xe608;</i>'+(s.attr(\"lay-title\")||a.title||\"上传\"+(o[l]||\"图片\"))+\"</span></div>\"),u=t(u),a.unwrap||u.on(\"dragover\",function(e){e.preventDefault(),t(this).addClass(i)}).on(\"dragleave\",function(){t(this).removeClass(i)}).on(\"drop\",function(){t(this).removeClass(i)}),s.parent(\"form\").attr(\"target\")===n&&(a.unwrap?s.unwrap():(s.parent().next().remove(),s.unwrap().unwrap())),s.wrap(u),s.off(\"change\").on(\"change\",function(){e.action(this,l)})})},s.prototype.action=function(e,i){var o=this,s=o.options,u=e.value,l=t(e),p=l.attr(\"lay-ext\")||s.ext||\"\";if(u){switch(i){case\"file\":if(p&&!RegExp(\"\\\\w\\\\.(\"+p+\")$\",\"i\").test(escape(u)))return a.msg(\"不支持该文件格式\",r),e.value=\"\";break;case\"video\":if(!RegExp(\"\\\\w\\\\.(\"+(p||\"avi|mp4|wma|rmvb|rm|flash|3gp|flv\")+\")$\",\"i\").test(escape(u)))return a.msg(\"不支持该视频格式\",r),e.value=\"\";break;case\"audio\":if(!RegExp(\"\\\\w\\\\.(\"+(p||\"mp3|wav|mid\")+\")$\",\"i\").test(escape(u)))return a.msg(\"不支持该音频格式\",r),e.value=\"\";break;default:if(!RegExp(\"\\\\w\\\\.(\"+(p||\"jpg|png|gif|bmp|jpeg\")+\")$\",\"i\").test(escape(u)))return a.msg(\"不支持该图片格式\",r),e.value=\"\"}s.before&&s.before(e),l.parent().submit();var c=t(\"#\"+n),f=setInterval(function(){var t;try{t=c.contents().find(\"body\").text()}catch(i){a.msg(\"上传接口存在跨域\",r),clearInterval(f)}if(t){clearInterval(f),c.contents().find(\"body\").html(\"\");try{t=JSON.parse(t)}catch(i){return t={},a.msg(\"请对上传接口返回JSON字符\",r)}\"function\"==typeof s.success&&s.success(t,e)}},30);e.value=\"\"}},e(\"upload-mobile\",function(e){var t=new s(e=e||{});t.init()})});layui.define(function(i){i(\"layim-mobile\",layui.v)});layui[\"layui.mobile\"]||layui.config({base:layui.cache.dir+\"lay/modules/mobile/\"}).extend({\"layer-mobile\":\"layer-mobile\",zepto:\"zepto\",\"upload-mobile\":\"upload-mobile\",\"layim-mobile\":\"layim-mobile\"}),layui.define([\"layer-mobile\",\"zepto\",\"layim-mobile\"],function(l){l(\"mobile\",{layer:layui[\"layer-mobile\"],layim:layui[\"layim-mobile\"]})});"
  },
  {
    "path": "open-layui-web/src/main/view/static/layui/lay/modules/rate.js",
    "content": "/** layui-v2.3.0-rc1 MIT License By https://www.layui.com */\n ;layui.define(\"jquery\",function(e){\"use strict\";var a=layui.jquery,i={config:{},index:layui.rate?layui.rate.index+1e4:0,set:function(e){var i=this;return i.config=a.extend({},i.config,e),i},on:function(e,a){return layui.onevent.call(this,n,e,a)}},l=function(){var e=this,a=e.config;return{setvalue:function(a){e.setvalue.call(e,a)},config:a}},n=\"rate\",t=\"layui-rate\",o=\"layui-icon-rate\",s=\"layui-icon-rate-solid\",u=\"layui-icon-rate-half\",r=\"layui-icon-rate-solid layui-icon-rate-half\",c=\"layui-icon-rate-solid layui-icon-rate\",f=\"layui-icon-rate layui-icon-rate-half\",v=function(e){var l=this;l.index=++i.index,l.config=a.extend({},l.config,i.config,e),l.render()};v.prototype.config={length:5,text:!1,readonly:!1,half:!1,value:0,theme:\"\"},v.prototype.render=function(){var e=this,i=e.config,l=i.theme?'style=\"color: '+i.theme+';\"':\"\";i.elem=a(i.elem),parseInt(i.value)!==i.value&&(i.half||(i.value=Math.ceil(i.value)-i.value<.5?Math.ceil(i.value):Math.floor(i.value)));for(var n='<ul class=\"layui-rate\" '+(i.readonly?\"readonly\":\"\")+\">\",u=1;u<=i.length;u++){var r='<li class=\"layui-inline\"><i class=\"layui-icon '+(u>Math.floor(i.value)?o:s)+'\" '+l+\"></i></li>\";i.half&&parseInt(i.value)!==i.value&&u==Math.ceil(i.value)?n=n+'<li><i class=\"layui-icon layui-icon-rate-half\" '+l+\"></i></li>\":n+=r}n+=\"</ul>\"+(i.text?'<span class=\"layui-inline\">'+i.value+\"星\":\"\")+\"</span>\";var c=i.elem,f=c.next(\".\"+t);f[0]&&f.remove(),e.elemTemp=a(n),i.span=e.elemTemp.next(\"span\"),i.setText&&i.setText(i.value),c.html(e.elemTemp),c.addClass(\"layui-inline\"),i.readonly||e.action()},v.prototype.setvalue=function(e){var a=this,i=a.config;i.value=e,a.render()},v.prototype.action=function(){var e=this,i=e.config,l=e.elemTemp,n=l.find(\"i\").width();l.children(\"li\").each(function(e){var t=e+1,v=a(this);v.on(\"click\",function(e){if(i.value=t,i.half){var o=e.pageX-a(this).offset().left;o<=n/2&&(i.value=i.value-.5)}i.text&&l.next(\"span\").text(i.value+\"星\"),i.choose&&i.choose(i.value),i.setText&&i.setText(i.value)}),v.on(\"mousemove\",function(e){if(l.find(\"i\").each(function(){a(this).addClass(o).removeClass(r)}),l.find(\"i:lt(\"+t+\")\").each(function(){a(this).addClass(s).removeClass(f)}),i.half){var c=e.pageX-a(this).offset().left;c<=n/2&&v.children(\"i\").addClass(u).removeClass(s)}}),v.on(\"mouseleave\",function(){l.find(\"i\").each(function(){a(this).addClass(o).removeClass(r)}),l.find(\"i:lt(\"+Math.floor(i.value)+\")\").each(function(){a(this).addClass(s).removeClass(f)}),i.half&&parseInt(i.value)!==i.value&&l.children(\"li:eq(\"+Math.floor(i.value)+\")\").children(\"i\").addClass(u).removeClass(c)})})},v.prototype.events=function(){var e=this;e.config},i.render=function(e){var a=new v(e);return l.call(a)},e(n,i)});"
  },
  {
    "path": "open-layui-web/src/main/view/static/layui/lay/modules/table.js",
    "content": "/** layui-v2.3.0-rc1 MIT License By https://www.layui.com */\n ;layui.define([\"laytpl\",\"laypage\",\"layer\",\"form\"],function(e){\"use strict\";var t=layui.$,i=layui.laytpl,a=layui.laypage,l=layui.layer,n=layui.form,o=layui.hint(),r=layui.device(),d={config:{checkName:\"LAY_CHECKED\",indexName:\"LAY_TABLE_INDEX\"},cache:{},index:layui.table?layui.table.index+1e4:0,set:function(e){var i=this;return i.config=t.extend({},i.config,e),i},on:function(e,t){return layui.onevent.call(this,s,e,t)}},c=function(){var e=this,t=e.config,i=t.id;return i&&(c.config[i]=t),{reload:function(t){e.reload.call(e,t)},config:t}},s=\"table\",u=\".layui-table\",h=\"layui-hide\",f=\"layui-none\",y=\"layui-table-view\",p=\".layui-table-header\",m=\".layui-table-body\",v=\".layui-table-main\",g=\".layui-table-fixed\",x=\".layui-table-fixed-l\",b=\".layui-table-fixed-r\",k=\".layui-table-tool\",C=\".layui-table-page\",w=\".layui-table-sort\",N=\"layui-table-edit\",T=\"layui-table-hover\",F=function(e){var t='{{#if(item2.colspan){}} colspan=\"{{item2.colspan}}\"{{#} if(item2.rowspan){}} rowspan=\"{{item2.rowspan}}\"{{#}}}';return e=e||{},['<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\" class=\"layui-table\" ','{{# if(d.data.skin){ }}lay-skin=\"{{d.data.skin}}\"{{# } }} {{# if(d.data.size){ }}lay-size=\"{{d.data.size}}\"{{# } }} {{# if(d.data.even){ }}lay-even{{# } }}>',\"<thead>\",\"{{# layui.each(d.data.cols, function(i1, item1){ }}\",\"<tr>\",\"{{# layui.each(item1, function(i2, item2){ }}\",'{{# if(item2.fixed && item2.fixed !== \"right\"){ left = true; } }}','{{# if(item2.fixed === \"right\"){ right = true; } }}',function(){return e.fixed&&\"right\"!==e.fixed?'{{# if(item2.fixed && item2.fixed !== \"right\"){ }}':\"right\"===e.fixed?'{{# if(item2.fixed === \"right\"){ }}':\"\"}(),'<th data-field=\"{{ item2.field||i2 }}\" {{# if(item2.minWidth){ }}data-minwidth=\"{{item2.minWidth}}\"{{# } }} '+t+' {{# if(item2.unresize){ }}data-unresize=\"true\"{{# } }}>','<div class=\"layui-table-cell laytable-cell-',\"{{# if(item2.colspan > 1){ }}\",\"group\",\"{{# } else { }}\",\"{{d.index}}-{{item2.field || i2}}\",'{{# if(item2.type !== \"normal\"){ }}',\" laytable-cell-{{ item2.type }}\",\"{{# } }}\",\"{{# } }}\",'\" {{#if(item2.align){}}align=\"{{item2.align}}\"{{#}}}>','{{# if(item2.type === \"checkbox\"){ }}','<input type=\"checkbox\" name=\"layTableCheckbox\" lay-skin=\"primary\" lay-filter=\"layTableAllChoose\" {{# if(item2[d.data.checkName]){ }}checked{{# }; }}>',\"{{# } else { }}\",'<span>{{item2.title||\"\"}}</span>',\"{{# if(!(item2.colspan > 1) && item2.sort){ }}\",'<span class=\"layui-table-sort layui-inline\"><i class=\"layui-edge layui-table-sort-asc\"></i><i class=\"layui-edge layui-table-sort-desc\"></i></span>',\"{{# } }}\",\"{{# } }}\",\"</div>\",\"</th>\",e.fixed?\"{{# }; }}\":\"\",\"{{# }); }}\",\"</tr>\",\"{{# }); }}\",\"</thead>\",\"</table>\"].join(\"\")},W=['<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\" class=\"layui-table\" ','{{# if(d.data.skin){ }}lay-skin=\"{{d.data.skin}}\"{{# } }} {{# if(d.data.size){ }}lay-size=\"{{d.data.size}}\"{{# } }} {{# if(d.data.even){ }}lay-even{{# } }}>',\"<tbody></tbody>\",\"</table>\"].join(\"\"),z=['<div class=\"layui-form layui-border-box {{d.VIEW_CLASS}}\" lay-filter=\"LAY-table-{{d.index}}\" style=\"{{# if(d.data.width){ }}width:{{d.data.width}}px;{{# } }} {{# if(d.data.height){ }}height:{{d.data.height}}px;{{# } }}\">',\"{{# if(d.data.toolbar){ }}\",'<div class=\"layui-table-tool\"></div>',\"{{# } }}\",'<div class=\"layui-table-box\">',\"{{# var left, right; }}\",'<div class=\"layui-table-header\">',F(),\"</div>\",'<div class=\"layui-table-body layui-table-main\">',W,\"</div>\",\"{{# if(left){ }}\",'<div class=\"layui-table-fixed layui-table-fixed-l\">','<div class=\"layui-table-header\">',F({fixed:!0}),\"</div>\",'<div class=\"layui-table-body\">',W,\"</div>\",\"</div>\",\"{{# }; }}\",\"{{# if(right){ }}\",'<div class=\"layui-table-fixed layui-table-fixed-r\">','<div class=\"layui-table-header\">',F({fixed:\"right\"}),'<div class=\"layui-table-mend\"></div>',\"</div>\",'<div class=\"layui-table-body\">',W,\"</div>\",\"</div>\",\"{{# }; }}\",\"</div>\",\"{{# if(d.data.page){ }}\",'<div class=\"layui-table-page\">','<div id=\"layui-table-page{{d.index}}\"></div>',\"</div>\",\"{{# } }}\",\"<style>\",\"{{# layui.each(d.data.cols, function(i1, item1){\",\"layui.each(item1, function(i2, item2){ }}\",\".laytable-cell-{{d.index}}-{{item2.field||i2}}{ \",\"{{# if(item2.width){ }}\",\"width: {{item2.width}}px;\",\"{{# } }}\",\" }\",\"{{# });\",\"}); }}\",\"</style>\",\"</div>\"].join(\"\"),A=t(window),S=t(document),M=function(e){var i=this;i.index=++d.index,i.config=t.extend({},i.config,d.config,e),i.render()};M.prototype.config={limit:10,loading:!0,cellMinWidth:60,text:{none:\"无数据\"}},M.prototype.render=function(){var e=this,a=e.config;if(a.elem=t(a.elem),a.where=a.where||{},a.id=a.id||a.elem.attr(\"id\"),a.request=t.extend({pageName:\"page\",limitName:\"limit\"},a.request),a.response=t.extend({statusName:\"code\",statusCode:0,msgName:\"msg\",dataName:\"data\",countName:\"count\"},a.response),\"object\"==typeof a.page&&(a.limit=a.page.limit||a.limit,a.limits=a.page.limits||a.limits,e.page=a.page.curr=a.page.curr||1,delete a.page.elem,delete a.page.jump),!a.elem[0])return e;e.setArea();var l=a.elem,n=l.next(\".\"+y),o=e.elem=t(i(z).render({VIEW_CLASS:y,data:a,index:e.index}));if(a.index=e.index,n[0]&&n.remove(),l.after(o),e.layHeader=o.find(p),e.layMain=o.find(v),e.layBody=o.find(m),e.layFixed=o.find(g),e.layFixLeft=o.find(x),e.layFixRight=o.find(b),e.layTool=o.find(k),e.layPage=o.find(C),e.layTool.html(i(t(a.toolbar).html()||\"\").render(a)),a.height&&e.fullSize(),a.cols.length>1){var r=e.layFixed.find(p).find(\"th\");r.height(e.layHeader.height()-1-parseFloat(r.css(\"padding-top\"))-parseFloat(r.css(\"padding-bottom\")))}e.pullData(e.page),e.events()},M.prototype.initOpts=function(e){var t=this,i=(t.config,{checkbox:48,space:15,numbers:40});e.checkbox&&(e.type=\"checkbox\"),e.space&&(e.type=\"space\"),e.type||(e.type=\"normal\"),\"normal\"!==e.type&&(e.unresize=!0,e.width=e.width||i[e.type])},M.prototype.setArea=function(){var e=this,t=e.config,i=0,a=0,l=0,n=0,o=t.width||function(){var e=function(i){var a,l;i=i||t.elem.parent(),a=i.width();try{l=\"none\"===i.css(\"display\")}catch(n){}return!i[0]||a&&!l?a:e(i.parent())};return e()}();e.eachCols(function(){i++}),o-=function(){return\"line\"===t.skin||\"nob\"===t.skin?2:i+1}(),layui.each(t.cols,function(t,i){layui.each(i,function(t,l){var r;return l?(e.initOpts(l),r=l.width||0,void(l.colspan>1||(/\\d+%$/.test(r)?l.width=r=Math.floor(parseFloat(r)/100*o):r||(l.width=r=0,a++),n+=r))):void i.splice(t,1)})}),e.autoColNums=a,o>n&&a&&(l=(o-n)/a),layui.each(t.cols,function(e,i){layui.each(i,function(e,i){var a=i.minWidth||t.cellMinWidth;i.colspan>1||0===i.width&&(i.width=Math.floor(l>=a?l:a))})}),t.height&&/^full-\\d+$/.test(t.height)&&(e.fullHeightGap=t.height.split(\"-\")[1],t.height=A.height()-e.fullHeightGap)},M.prototype.reload=function(e){var i=this;i.config.data&&i.config.data.constructor===Array&&delete i.config.data,i.config=t.extend({},i.config,e),i.render()},M.prototype.page=1,M.prototype.pullData=function(e,i){var a=this,n=a.config,o=n.request,r=n.response,d=function(){\"object\"==typeof n.initSort&&a.sort(n.initSort.field,n.initSort.type)};if(a.startTime=(new Date).getTime(),n.url){var c={};c[o.pageName]=e,c[o.limitName]=n.limit;var s=t.extend(c,n.where);n.contentType&&0==n.contentType.indexOf(\"application/json\")&&(s=JSON.stringify(s)),t.ajax({type:n.method||\"get\",url:n.url,contentType:n.contentType,data:s,dataType:\"json\",headers:n.headers||{},success:function(t){t[r.statusName]!=r.statusCode?(a.renderForm(),a.layMain.html('<div class=\"'+f+'\">'+(t[r.msgName]||\"返回的数据状态异常\")+\"</div>\")):(a.renderData(t,e,t[r.countName]),d(),n.time=(new Date).getTime()-a.startTime+\" ms\"),i&&l.close(i),\"function\"==typeof n.done&&n.done(t,e,t[r.countName])},error:function(e,t){a.layMain.html('<div class=\"'+f+'\">数据接口请求异常</div>'),a.renderForm(),i&&l.close(i)}})}else if(n.data&&n.data.constructor===Array){var u={},h=e*n.limit-n.limit;u[r.dataName]=n.data.concat().splice(h,n.limit),u[r.countName]=n.data.length,a.renderData(u,e,n.data.length),d(),\"function\"==typeof n.done&&n.done(u,e,u[r.countName])}},M.prototype.eachCols=function(e){var i=t.extend(!0,[],this.config.cols),a=[],l=0;layui.each(i,function(e,t){layui.each(t,function(t,n){if(n.colspan>1){var o=0;l++,n.CHILD_COLS=[],layui.each(i[e+1],function(e,t){t.PARENT_COL||o==n.colspan||(t.PARENT_COL=l,n.CHILD_COLS.push(t),o+=t.colspan>1?t.colspan:1)})}n.PARENT_COL||a.push(n)})});var n=function(t){layui.each(t||a,function(t,i){return i.CHILD_COLS?n(i.CHILD_COLS):void e(t,i)})};n()},M.prototype.renderData=function(e,n,o,r){var c=this,s=c.config,u=e[s.response.dataName]||[],y=[],p=[],m=[],v=function(){return!r&&c.sortKey?c.sort(c.sortKey.field,c.sortKey.sort,!0):(layui.each(u,function(e,a){var l=[],o=[],u=[],h=e+s.limit*(n-1)+1;0!==a.length&&(r||(a[d.config.indexName]=e),c.eachCols(function(e,n){var r=n.field||e,f=a[r];c.getColElem(c.layHeader,r);if(void 0!==f&&null!==f||(f=\"\"),!(n.colspan>1)){var y=['<td data-field=\"'+r+'\" '+function(){var e=[];return n.edit&&e.push('data-edit=\"'+n.edit+'\"'),n.align&&e.push('align=\"'+n.align+'\"'),n.templet&&e.push('data-content=\"'+f+'\"'),n.toolbar&&e.push('data-off=\"true\"'),n.event&&e.push('lay-event=\"'+n.event+'\"'),n.style&&e.push('style=\"'+n.style+'\"'),n.minWidth&&e.push('data-minwidth=\"'+n.minWidth+'\"'),e.join(\" \")}()+\">\",'<div class=\"layui-table-cell laytable-cell-'+function(){var e=s.index+\"-\"+r;return\"normal\"===n.type?e:e+\" laytable-cell-\"+n.type}()+'\">'+function(){var e=t.extend(!0,{LAY_INDEX:h},a);return\"checkbox\"===n.type?'<input type=\"checkbox\" name=\"layTableCheckbox\" lay-skin=\"primary\" '+function(){var t=d.config.checkName;return n[t]?(a[t]=n[t],n[t]?\"checked\":\"\"):e[t]?\"checked\":\"\"}()+\">\":\"numbers\"===n.type?h:n.toolbar?i(t(n.toolbar).html()||\"\").render(e):n.templet?function(){return\"function\"==typeof n.templet?n.templet(e):i(t(n.templet).html()||String(f)).render(e)}():f}(),\"</div></td>\"].join(\"\");l.push(y),n.fixed&&\"right\"!==n.fixed&&o.push(y),\"right\"===n.fixed&&u.push(y)}}),y.push('<tr data-index=\"'+e+'\">'+l.join(\"\")+\"</tr>\"),p.push('<tr data-index=\"'+e+'\">'+o.join(\"\")+\"</tr>\"),m.push('<tr data-index=\"'+e+'\">'+u.join(\"\")+\"</tr>\"))}),c.layBody.scrollTop(0),c.layMain.find(\".\"+f).remove(),c.layMain.find(\"tbody\").html(y.join(\"\")),c.layFixLeft.find(\"tbody\").html(p.join(\"\")),c.layFixRight.find(\"tbody\").html(m.join(\"\")),c.renderForm(),c.syncCheckAll(),c.haveInit?c.scrollPatch():setTimeout(function(){c.scrollPatch()},50),c.haveInit=!0,void l.close(c.tipsIndex))};return c.key=s.id||s.index,d.cache[c.key]=u,c.layPage[0===u.length&&1==n?\"addClass\":\"removeClass\"](h),r?v():0===u.length?(c.renderForm(),c.layFixed.remove(),c.layMain.find(\"tbody\").html(\"\"),c.layMain.find(\".\"+f).remove(),c.layMain.append('<div class=\"'+f+'\">'+s.text.none+\"</div>\")):(v(),void(s.page&&(s.page=t.extend({elem:\"layui-table-page\"+s.index,count:o,limit:s.limit,limits:s.limits||[10,20,30,40,50,60,70,80,90],groups:3,layout:[\"prev\",\"page\",\"next\",\"skip\",\"count\",\"limit\"],prev:'<i class=\"layui-icon\">&#xe603;</i>',next:'<i class=\"layui-icon\">&#xe602;</i>',jump:function(e,t){t||(c.page=e.curr,s.limit=e.limit,c.pullData(e.curr,c.loading()))}},s.page),s.page.count=o,a.render(s.page))))},M.prototype.getColElem=function(e,t){var i=this,a=i.config;return e.eq(0).find(\".laytable-cell-\"+(a.index+\"-\"+t)+\":eq(0)\")},M.prototype.renderForm=function(e){n.render(e,\"LAY-table-\"+this.index)},M.prototype.sort=function(e,i,a,l){var n,r,c=this,u={},h=c.config,f=h.elem.attr(\"lay-filter\"),y=d.cache[c.key];\"string\"==typeof e&&c.layHeader.find(\"th\").each(function(i,a){var l=t(this),o=l.data(\"field\");if(o===e)return e=l,n=o,!1});try{var n=n||e.data(\"field\");if(c.sortKey&&!a&&n===c.sortKey.field&&i===c.sortKey.sort)return;var p=c.layHeader.find(\"th .laytable-cell-\"+h.index+\"-\"+n).find(w);c.layHeader.find(\"th\").find(w).removeAttr(\"lay-sort\"),p.attr(\"lay-sort\",i||null),c.layFixed.find(\"th\")}catch(m){return o.error(\"Table modules: Did not match to field\")}c.sortKey={field:n,sort:i},\"asc\"===i?r=layui.sort(y,n):\"desc\"===i?r=layui.sort(y,n,!0):(r=layui.sort(y,d.config.indexName),delete c.sortKey),u[h.response.dataName]=r,c.renderData(u,c.page,c.count,!0),l&&layui.event.call(e,s,\"sort(\"+f+\")\",{field:n,type:i})},M.prototype.loading=function(){var e=this,t=e.config;if(t.loading&&t.url)return l.msg(\"数据请求中\",{icon:16,offset:[e.elem.offset().top+e.elem.height()/2-35-A.scrollTop()+\"px\",e.elem.offset().left+e.elem.width()/2-90-A.scrollLeft()+\"px\"],time:-1,anim:-1,fixed:!1})},M.prototype.setCheckData=function(e,t){var i=this,a=i.config,l=d.cache[i.key];l[e]&&l[e].constructor!==Array&&(l[e][a.checkName]=t)},M.prototype.syncCheckAll=function(){var e=this,t=e.config,i=e.layHeader.find('input[name=\"layTableCheckbox\"]'),a=function(i){return e.eachCols(function(e,a){\"checkbox\"===a.type&&(a[t.checkName]=i)}),i};i[0]&&(d.checkStatus(e.key).isAll?(i[0].checked||(i.prop(\"checked\",!0),e.renderForm(\"checkbox\")),a(!0)):(i[0].checked&&(i.prop(\"checked\",!1),e.renderForm(\"checkbox\")),a(!1)))},M.prototype.getCssRule=function(e,t){var i=this,a=i.elem.find(\"style\")[0],l=a.sheet||a.styleSheet||{},n=l.cssRules||l.rules;layui.each(n,function(a,l){if(l.selectorText===\".laytable-cell-\"+i.index+\"-\"+e)return t(l),!0})},M.prototype.fullSize=function(){var e,t=this,i=t.config,a=i.height;t.fullHeightGap&&(a=A.height()-t.fullHeightGap,a<135&&(a=135),t.elem.css(\"height\",a)),e=parseFloat(a)-parseFloat(t.layHeader.height())-1,i.toolbar&&(e-=t.layTool.outerHeight()),i.page&&(e=e-t.layPage.outerHeight()-1),t.layMain.css(\"height\",e)},M.prototype.getScrollWidth=function(e){var t=0;return e?t=e.offsetWidth-e.clientWidth:(e=document.createElement(\"div\"),e.style.width=\"100px\",e.style.height=\"100px\",e.style.overflowY=\"scroll\",document.body.appendChild(e),t=e.offsetWidth-e.clientWidth,document.body.removeChild(e)),t},M.prototype.scrollPatch=function(){var e=this,i=e.layMain.children(\"table\"),a=e.layMain.width()-e.layMain.prop(\"clientWidth\"),l=e.layMain.height()-e.layMain.prop(\"clientHeight\"),n=e.getScrollWidth(e.layMain[0]),o=i.outerWidth()-e.layMain.width();if(e.autoColNums&&o<5&&!e.scrollPatchWStatus){var r=e.layHeader.eq(0).find(\"thead th:last-child\"),d=r.data(\"field\");e.getCssRule(d,function(t){var i=t.style.width||r.outerWidth();t.style.width=parseFloat(i)-n-o+\"px\",e.layMain.height()-e.layMain.prop(\"clientHeight\")>0&&(t.style.width=parseFloat(t.style.width)-1+\"px\"),e.scrollPatchWStatus=!0})}if(a&&l){if(!e.elem.find(\".layui-table-patch\")[0]){var c=t('<th class=\"layui-table-patch\"><div class=\"layui-table-cell\"></div></th>');c.find(\"div\").css({width:a}),e.layHeader.eq(0).find(\"thead tr\").append(c)}}else e.layHeader.eq(0).find(\".layui-table-patch\").remove();var s=e.layMain.height(),u=s-l;e.layFixed.find(m).css(\"height\",i.height()>u?u:\"auto\"),e.layFixRight[o>0?\"removeClass\":\"addClass\"](h),e.layFixRight.css(\"right\",a-1)},M.prototype.events=function(){var e,a=this,n=a.config,o=t(\"body\"),c={},u=a.layHeader.find(\"th\"),h=\".layui-table-cell\",f=n.elem.attr(\"lay-filter\");u.on(\"mousemove\",function(e){var i=t(this),a=i.offset().left,l=e.clientX-a;i.attr(\"colspan\")>1||i.data(\"unresize\")||c.resizeStart||(c.allowResize=i.width()-l<=10,o.css(\"cursor\",c.allowResize?\"col-resize\":\"\"))}).on(\"mouseleave\",function(){t(this);c.resizeStart||o.css(\"cursor\",\"\")}).on(\"mousedown\",function(e){var i=t(this);if(c.allowResize){var l=i.data(\"field\");e.preventDefault(),c.resizeStart=!0,c.offset=[e.clientX,e.clientY],a.getCssRule(l,function(e){var t=e.style.width||i.outerWidth();c.rule=e,c.ruleWidth=parseFloat(t),c.minWidth=i.data(\"minwidth\")||n.cellMinWidth})}}),S.on(\"mousemove\",function(t){if(c.resizeStart){if(t.preventDefault(),c.rule){var i=c.ruleWidth+t.clientX-c.offset[0];i<c.minWidth&&(i=c.minWidth),c.rule.style.width=i+\"px\",l.close(a.tipsIndex)}e=1}}).on(\"mouseup\",function(t){c.resizeStart&&(c={},o.css(\"cursor\",\"\"),a.scrollPatch()),2===e&&(e=null)}),u.on(\"click\",function(){var i,l=t(this),n=l.find(w),o=n.attr(\"lay-sort\");return n[0]&&1!==e?(i=\"asc\"===o?\"desc\":\"desc\"===o?null:\"asc\",void a.sort(l,i,null,!0)):e=2}).find(w+\" .layui-edge \").on(\"click\",function(e){var i=t(this),l=i.index(),n=i.parents(\"th\").eq(0).data(\"field\");layui.stope(e),0===l?a.sort(n,\"asc\",null,!0):a.sort(n,\"desc\",null,!0)}),a.elem.on(\"click\",'input[name=\"layTableCheckbox\"]+',function(){var e=t(this).prev(),i=a.layBody.find('input[name=\"layTableCheckbox\"]'),l=e.parents(\"tr\").eq(0).data(\"index\"),n=e[0].checked,o=\"layTableAllChoose\"===e.attr(\"lay-filter\");o?(i.each(function(e,t){t.checked=n,a.setCheckData(e,n)}),a.syncCheckAll(),a.renderForm(\"checkbox\")):(a.setCheckData(l,n),a.syncCheckAll()),layui.event.call(this,s,\"checkbox(\"+f+\")\",{checked:n,data:d.cache[a.key]?d.cache[a.key][l]||{}:{},type:o?\"all\":\"one\"})}),a.layBody.on(\"mouseenter\",\"tr\",function(){var e=t(this),i=e.index();a.layBody.find(\"tr:eq(\"+i+\")\").addClass(T)}).on(\"mouseleave\",\"tr\",function(){var e=t(this),i=e.index();a.layBody.find(\"tr:eq(\"+i+\")\").removeClass(T)}),a.layBody.on(\"change\",\".\"+N,function(){var e=t(this),i=this.value,l=e.parent().data(\"field\"),n=e.parents(\"tr\").eq(0).data(\"index\"),o=d.cache[a.key][n];o[l]=i,layui.event.call(this,s,\"edit(\"+f+\")\",{value:i,data:o,field:l})}).on(\"blur\",\".\"+N,function(){var e,l=t(this),n=l.parent().data(\"field\"),o=l.parents(\"tr\").eq(0).data(\"index\"),r=d.cache[a.key][o];a.eachCols(function(t,i){i.field==n&&i.templet&&(e=i.templet)}),l.siblings(h).html(e?i(t(e).html()||this.value).render(r):this.value),l.parent().data(\"content\",this.value),l.remove()}),a.layBody.on(\"click\",\"td\",function(){var e=t(this),i=(e.data(\"field\"),e.data(\"edit\")),o=e.children(h);if(l.close(a.tipsIndex),!e.data(\"off\"))if(i)if(\"select\"===i);else{var d=t('<input class=\"layui-input '+N+'\">');d[0].value=e.data(\"content\")||o.text(),e.find(\".\"+N)[0]||e.append(d),d.focus()}else o.find(\".layui-form-switch,.layui-form-checkbox\")[0]||Math.round(o.prop(\"scrollWidth\"))>Math.round(o.outerWidth())&&(a.tipsIndex=l.tips(['<div class=\"layui-table-tips-main\" style=\"margin-top: -'+(o.height()+16)+\"px;\"+function(){return\"sm\"===n.size?\"padding: 4px 15px; font-size: 12px;\":\"lg\"===n.size?\"padding: 14px 15px;\":\"\"}()+'\">',o.html(),\"</div>\",'<i class=\"layui-icon layui-table-tips-c\">&#x1006;</i>'].join(\"\"),o[0],{tips:[3,\"\"],time:-1,anim:-1,maxWidth:r.ios||r.android?300:600,isOutAnim:!1,skin:\"layui-table-tips\",success:function(e,t){e.find(\".layui-table-tips-c\").on(\"click\",function(){l.close(t)})}}))}),a.layBody.on(\"click\",\"*[lay-event]\",function(){var e=t(this),l=e.parents(\"tr\").eq(0).data(\"index\"),n=a.layBody.find('tr[data-index=\"'+l+'\"]'),o=\"layui-table-click\",r=d.cache[a.key][l];layui.event.call(this,s,\"tool(\"+f+\")\",{data:d.clearCacheKey(r),event:e.attr(\"lay-event\"),tr:n,del:function(){d.cache[a.key][l]=[],n.remove(),a.scrollPatch()},update:function(e){e=e||{},layui.each(e,function(e,l){if(e in r){var o,d=n.children('td[data-field=\"'+e+'\"]');r[e]=l,a.eachCols(function(t,i){i.field==e&&i.templet&&(o=i.templet)}),d.children(h).html(o?i(t(o).html()||l).render(r):l),d.data(\"content\",l)}})}}),n.addClass(o).siblings(\"tr\").removeClass(o)}),a.layMain.on(\"scroll\",function(){var e=t(this),i=e.scrollLeft(),n=e.scrollTop();a.layHeader.scrollLeft(i),a.layFixed.find(m).scrollTop(n),l.close(a.tipsIndex)}),A.on(\"resize\",function(){a.fullSize(),a.scrollPatch()})},d.init=function(e,i){i=i||{};var a=this,l=t(e?'table[lay-filter=\"'+e+'\"]':u+\"[lay-data]\"),n=\"Table element property lay-data configuration item has a syntax error: \";return l.each(function(){var a=t(this),l=a.attr(\"lay-data\");try{l=new Function(\"return \"+l)()}catch(r){o.error(n+l)}var c=[],s=t.extend({elem:this,cols:[],data:[],skin:a.attr(\"lay-skin\"),size:a.attr(\"lay-size\"),even:\"string\"==typeof a.attr(\"lay-even\")},d.config,i,l);e&&a.hide(),a.find(\"thead>tr\").each(function(e){s.cols[e]=[],t(this).children().each(function(i){var a=t(this),l=a.attr(\"lay-data\");try{l=new Function(\"return \"+l)()}catch(r){return o.error(n+l)}var d=t.extend({title:a.text(),colspan:a.attr(\"colspan\")||0,rowspan:a.attr(\"rowspan\")||0},l);d.colspan<2&&c.push(d),s.cols[e].push(d)})}),a.find(\"tbody>tr\").each(function(e){var i=t(this),a={};i.children(\"td\").each(function(e,i){var l=t(this),n=l.data(\"field\");if(n)return a[n]=l.html()}),layui.each(c,function(e,t){var l=i.children(\"td\").eq(e);a[t.field]=l.html()}),s.data[e]=a}),d.render(s)}),a},d.checkStatus=function(e){var t=0,i=0,a=[],l=d.cache[e]||[];return layui.each(l,function(e,l){return l.constructor===Array?void i++:void(l[d.config.checkName]&&(t++,a.push(d.clearCacheKey(l))))}),{data:a,isAll:!!l.length&&t===l.length-i}},c.config={},d.reload=function(e,i){var a=c.config[e];return i=i||{},a?(i.data&&i.data.constructor===Array&&delete a.data,d.render(t.extend(!0,{},a,i))):o.error(\"The ID option was not found in the table instance\")},d.render=function(e){var t=new M(e);return c.call(t)},d.clearCacheKey=function(e){return e=t.extend({},e),delete e[d.config.checkName],delete e[d.config.indexName],e},d.init(),e(s,d)});"
  },
  {
    "path": "open-layui-web/src/main/view/static/layui/lay/modules/tree.js",
    "content": "/** layui-v2.3.0-rc1 MIT License By https://www.layui.com */\n ;layui.define(\"jquery\",function(e){\"use strict\";var o=layui.$,a=layui.hint(),i=\"layui-tree-enter\",r=function(e){this.options=e},t={arrow:[\"&#xe623;\",\"&#xe625;\"],checkbox:[\"&#xe626;\",\"&#xe627;\"],radio:[\"&#xe62b;\",\"&#xe62a;\"],branch:[\"&#xe622;\",\"&#xe624;\"],leaf:\"&#xe621;\"};r.prototype.init=function(e){var o=this;e.addClass(\"layui-box layui-tree\"),o.options.skin&&e.addClass(\"layui-tree-skin-\"+o.options.skin),o.tree(e),o.on(e)},r.prototype.tree=function(e,a){var i=this,r=i.options,n=a||r.nodes;layui.each(n,function(a,n){var l=n.children&&n.children.length>0,c=o('<ul class=\"'+(n.spread?\"layui-show\":\"\")+'\"></ul>'),s=o([\"<li \"+(n.spread?'data-spread=\"'+n.spread+'\"':\"\")+\">\",function(){return l?'<i class=\"layui-icon layui-tree-spread\">'+(n.spread?t.arrow[1]:t.arrow[0])+\"</i>\":\"\"}(),function(){return r.check?'<i class=\"layui-icon layui-tree-check\">'+(\"checkbox\"===r.check?t.checkbox[0]:\"radio\"===r.check?t.radio[0]:\"\")+\"</i>\":\"\"}(),function(){return'<a href=\"'+(n.href||\"javascript:;\")+'\" '+(r.target&&n.href?'target=\"'+r.target+'\"':\"\")+\">\"+('<i class=\"layui-icon layui-tree-'+(l?\"branch\":\"leaf\")+'\">'+(l?n.spread?t.branch[1]:t.branch[0]:t.leaf)+\"</i>\")+(\"<cite>\"+(n.name||\"未命名\")+\"</cite></a>\")}(),\"</li>\"].join(\"\"));l&&(s.append(c),i.tree(c,n.children)),e.append(s),\"function\"==typeof r.click&&i.click(s,n),i.spread(s,n),r.drag&&i.drag(s,n)})},r.prototype.click=function(e,o){var a=this,i=a.options;e.children(\"a\").on(\"click\",function(e){layui.stope(e),i.click(o)})},r.prototype.spread=function(e,o){var a=this,i=(a.options,e.children(\".layui-tree-spread\")),r=e.children(\"ul\"),n=e.children(\"a\"),l=function(){e.data(\"spread\")?(e.data(\"spread\",null),r.removeClass(\"layui-show\"),i.html(t.arrow[0]),n.find(\".layui-icon\").html(t.branch[0])):(e.data(\"spread\",!0),r.addClass(\"layui-show\"),i.html(t.arrow[1]),n.find(\".layui-icon\").html(t.branch[1]))};r[0]&&(i.on(\"click\",l),n.on(\"dblclick\",l))},r.prototype.on=function(e){var a=this,r=a.options,t=\"layui-tree-drag\";e.find(\"i\").on(\"selectstart\",function(e){return!1}),r.drag&&o(document).on(\"mousemove\",function(e){var i=a.move;if(i.from){var r=(i.to,o('<div class=\"layui-box '+t+'\"></div>'));e.preventDefault(),o(\".\"+t)[0]||o(\"body\").append(r);var n=o(\".\"+t)[0]?o(\".\"+t):r;n.addClass(\"layui-show\").html(i.from.elem.children(\"a\").html()),n.css({left:e.pageX+10,top:e.pageY+10})}}).on(\"mouseup\",function(){var e=a.move;e.from&&(e.from.elem.children(\"a\").removeClass(i),e.to&&e.to.elem.children(\"a\").removeClass(i),a.move={},o(\".\"+t).remove())})},r.prototype.move={},r.prototype.drag=function(e,a){var r=this,t=(r.options,e.children(\"a\")),n=function(){var t=o(this),n=r.move;n.from&&(n.to={item:a,elem:e},t.addClass(i))};t.on(\"mousedown\",function(){var o=r.move;o.from={item:a,elem:e}}),t.on(\"mouseenter\",n).on(\"mousemove\",n).on(\"mouseleave\",function(){var e=o(this),a=r.move;a.from&&(delete a.to,e.removeClass(i))})},e(\"tree\",function(e){var i=new r(e=e||{}),t=o(e.elem);return t[0]?void i.init(t):a.error(\"layui.tree 没有找到\"+e.elem+\"元素\")})});"
  },
  {
    "path": "open-layui-web/src/main/view/static/layui/lay/modules/upload.js",
    "content": "/** layui-v2.3.0-rc1 MIT License By https://www.layui.com */\n ;layui.define(\"layer\",function(e){\"use strict\";var i=layui.$,t=layui.layer,n=layui.hint(),a=layui.device(),o={config:{},set:function(e){var t=this;return t.config=i.extend({},t.config,e),t},on:function(e,i){return layui.onevent.call(this,r,e,i)}},l=function(){var e=this;return{upload:function(i){e.upload.call(e,i)},config:e.config}},r=\"upload\",u=\"layui-upload-file\",c=\"layui-upload-form\",f=\"layui-upload-iframe\",s=\"layui-upload-choose\",p=function(e){var t=this;t.config=i.extend({},t.config,o.config,e),t.render()};p.prototype.config={accept:\"images\",exts:\"\",auto:!0,bindAction:\"\",url:\"\",field:\"file\",method:\"post\",data:{},drag:!0,size:0,number:0,multiple:!1},p.prototype.render=function(e){var t=this,e=t.config;e.elem=i(e.elem),e.bindAction=i(e.bindAction),t.file(),t.events()},p.prototype.file=function(){var e=this,t=e.config,n=e.elemFile=i(['<input class=\"'+u+'\" type=\"file\" accept=\"'+t.acceptMime+'\" name=\"'+t.field+'\"',t.multiple?\" multiple\":\"\",\">\"].join(\"\")),o=t.elem.next();(o.hasClass(u)||o.hasClass(c))&&o.remove(),a.ie&&a.ie<10&&t.elem.wrap('<div class=\"layui-upload-wrap\"></div>'),e.isFile()?(e.elemFile=t.elem,t.field=t.elem[0].name):t.elem.after(n),a.ie&&a.ie<10&&e.initIE()},p.prototype.initIE=function(){var e=this,t=e.config,n=i('<iframe id=\"'+f+'\" class=\"'+f+'\" name=\"'+f+'\" frameborder=\"0\"></iframe>'),a=i(['<form target=\"'+f+'\" class=\"'+c+'\" method=\"'+t.method,'\" key=\"set-mine\" enctype=\"multipart/form-data\" action=\"'+t.url+'\">',\"</form>\"].join(\"\"));i(\"#\"+f)[0]||i(\"body\").append(n),t.elem.next().hasClass(f)||(e.elemFile.wrap(a),t.elem.next(\".\"+f).append(function(){var e=[];return layui.each(t.data,function(i,t){t=\"function\"==typeof t?t():t,e.push('<input type=\"hidden\" name=\"'+i+'\" value=\"'+t+'\">')}),e.join(\"\")}()))},p.prototype.msg=function(e){return t.msg(e,{icon:2,shift:6})},p.prototype.isFile=function(){var e=this.config.elem[0];if(e)return\"input\"===e.tagName.toLocaleLowerCase()&&\"file\"===e.type},p.prototype.preview=function(e){var i=this;window.FileReader&&layui.each(i.chooseFiles,function(i,t){var n=new FileReader;n.readAsDataURL(t),n.onload=function(){e&&e(i,t,this.result)}})},p.prototype.upload=function(e,t){var n,o=this,l=o.config,r=o.elemFile[0],u=function(){var t=0,n=0,a=e||o.files||o.chooseFiles||r.files,u=function(){l.multiple&&t+n===o.fileLength&&\"function\"==typeof l.allDone&&l.allDone({total:o.fileLength,successful:t,aborted:n})};layui.each(a,function(e,a){var r=new FormData;r.append(l.field,a),layui.each(l.data,function(e,i){i=\"function\"==typeof i?i():i,r.append(e,i)}),i.ajax({url:l.url,type:l.method,data:r,contentType:!1,processData:!1,dataType:\"json\",headers:l.headers||{},success:function(i){t++,d(e,i),u()},error:function(){n++,o.msg(\"请求上传接口出现异常\"),m(e),u()}})})},c=function(){var e=i(\"#\"+f);o.elemFile.parent().submit(),clearInterval(p.timer),p.timer=setInterval(function(){var i,t=e.contents().find(\"body\");try{i=t.text()}catch(n){o.msg(\"获取上传后的响应信息出现异常\"),clearInterval(p.timer),m()}i&&(clearInterval(p.timer),t.html(\"\"),d(0,i))},30)},d=function(e,i){if(o.elemFile.next(\".\"+s).remove(),r.value=\"\",\"object\"!=typeof i)try{i=JSON.parse(i)}catch(t){return i={},o.msg(\"请对上传接口返回有效JSON\")}\"function\"==typeof l.done&&l.done(i,e||0,function(e){o.upload(e)})},m=function(e){l.auto&&(r.value=\"\"),\"function\"==typeof l.error&&l.error(e||0,function(e){o.upload(e)})},h=l.exts,v=function(){var i=[];return layui.each(e||o.chooseFiles,function(e,t){i.push(t.name)}),i}(),g={preview:function(e){o.preview(e)},upload:function(e,i){var t={};t[e]=i,o.upload(t)},pushFile:function(){return o.files=o.files||{},layui.each(o.chooseFiles,function(e,i){o.files[e]=i}),o.files}},y=function(){return\"choose\"===t?l.choose&&l.choose(g):(l.before&&l.before(g),a.ie?a.ie>9?u():c():void u())};if(v=0===v.length?r.value.match(/[^\\/\\\\]+\\..+/g)||[]||\"\":v,0!==v.length){switch(l.accept){case\"file\":if(h&&!RegExp(\"\\\\w\\\\.(\"+h+\")$\",\"i\").test(escape(v)))return o.msg(\"选择的文件中包含不支持的格式\"),r.value=\"\";break;case\"video\":if(!RegExp(\"\\\\w\\\\.(\"+(h||\"avi|mp4|wma|rmvb|rm|flash|3gp|flv\")+\")$\",\"i\").test(escape(v)))return o.msg(\"选择的视频中包含不支持的格式\"),r.value=\"\";break;case\"audio\":if(!RegExp(\"\\\\w\\\\.(\"+(h||\"mp3|wav|mid\")+\")$\",\"i\").test(escape(v)))return o.msg(\"选择的音频中包含不支持的格式\"),r.value=\"\";break;default:if(layui.each(v,function(e,i){RegExp(\"\\\\w\\\\.(\"+(h||\"jpg|png|gif|bmp|jpeg$\")+\")\",\"i\").test(escape(i))||(n=!0)}),n)return o.msg(\"选择的图片中包含不支持的格式\"),r.value=\"\"}if(o.fileLength=function(){var i=0,t=e||o.files||o.chooseFiles||r.files;return layui.each(t,function(){i++}),i}(),l.number&&o.fileLength>l.number)return o.msg(\"同时最多只能上传的数量为：\"+l.number);if(l.size>0&&!(a.ie&&a.ie<10)){var F;if(layui.each(o.chooseFiles,function(e,i){if(i.size>1024*l.size){var t=l.size/1024;t=t>=1?t.toFixed(2)+\"MB\":l.size+\"KB\",r.value=\"\",F=t}}),F)return o.msg(\"文件不能超过\"+F)}y()}},p.prototype.events=function(){var e=this,t=e.config,o=function(i){e.chooseFiles={},layui.each(i,function(i,t){var n=(new Date).getTime();e.chooseFiles[n+\"-\"+i]=t})},l=function(i,n){var a=e.elemFile,o=i.length>1?i.length+\"个文件\":(i[0]||{}).name||a[0].value.match(/[^\\/\\\\]+\\..+/g)||[]||\"\";a.next().hasClass(s)&&a.next().remove(),e.upload(null,\"choose\"),e.isFile()||t.choose||a.after('<span class=\"layui-inline '+s+'\">'+o+\"</span>\")};t.elem.off(\"upload.start\").on(\"upload.start\",function(){var a=i(this),o=a.attr(\"lay-data\");if(o)try{o=new Function(\"return \"+o)(),e.config=i.extend({},t,o)}catch(l){n.error(\"Upload element property lay-data configuration item has a syntax error: \"+o)}e.config.item=a,e.elemFile[0].click()}),a.ie&&a.ie<10||t.elem.off(\"upload.over\").on(\"upload.over\",function(){var e=i(this);e.attr(\"lay-over\",\"\")}).off(\"upload.leave\").on(\"upload.leave\",function(){var e=i(this);e.removeAttr(\"lay-over\")}).off(\"upload.drop\").on(\"upload.drop\",function(n,a){var r=i(this),u=a.originalEvent.dataTransfer.files||[];r.removeAttr(\"lay-over\"),o(u),t.auto?e.upload(u):l(u)}),e.elemFile.off(\"upload.change\").on(\"upload.change\",function(){var i=this.files||[];o(i),t.auto?e.upload():l(i)}),t.bindAction.off(\"upload.action\").on(\"upload.action\",function(){e.upload()}),t.elem.data(\"haveEvents\")||(e.elemFile.on(\"change\",function(){i(this).trigger(\"upload.change\")}),t.elem.on(\"click\",function(){e.isFile()||i(this).trigger(\"upload.start\")}),t.drag&&t.elem.on(\"dragover\",function(e){e.preventDefault(),i(this).trigger(\"upload.over\")}).on(\"dragleave\",function(e){i(this).trigger(\"upload.leave\")}).on(\"drop\",function(e){e.preventDefault(),i(this).trigger(\"upload.drop\",e)}),t.bindAction.on(\"click\",function(){i(this).trigger(\"upload.action\")}),t.elem.data(\"haveEvents\",!0))},o.render=function(e){var i=new p(e);return l.call(i)},e(r,o)});"
  },
  {
    "path": "open-layui-web/src/main/view/static/layui/lay/modules/util.js",
    "content": "/** layui-v2.3.0-rc1 MIT License By https://www.layui.com */\n ;layui.define(\"jquery\",function(e){\"use strict\";var t=layui.$,i={fixbar:function(e){var i,o,a=\"layui-fixbar\",r=\"layui-fixbar-top\",n=t(document),l=t(\"body\");e=t.extend({showHeight:200},e),e.bar1=e.bar1===!0?\"&#xe606;\":e.bar1,e.bar2=e.bar2===!0?\"&#xe607;\":e.bar2,e.bgcolor=e.bgcolor?\"background-color:\"+e.bgcolor:\"\";var c=[e.bar1,e.bar2,\"&#xe604;\"],g=t(['<ul class=\"'+a+'\">',e.bar1?'<li class=\"layui-icon\" lay-type=\"bar1\" style=\"'+e.bgcolor+'\">'+c[0]+\"</li>\":\"\",e.bar2?'<li class=\"layui-icon\" lay-type=\"bar2\" style=\"'+e.bgcolor+'\">'+c[1]+\"</li>\":\"\",'<li class=\"layui-icon '+r+'\" lay-type=\"top\" style=\"'+e.bgcolor+'\">'+c[2]+\"</li>\",\"</ul>\"].join(\"\")),s=g.find(\".\"+r),u=function(){var t=n.scrollTop();t>=e.showHeight?i||(s.show(),i=1):i&&(s.hide(),i=0)};t(\".\"+a)[0]||(\"object\"==typeof e.css&&g.css(e.css),l.append(g),u(),g.find(\"li\").on(\"click\",function(){var i=t(this),o=i.attr(\"lay-type\");\"top\"===o&&t(\"html,body\").animate({scrollTop:0},200),e.click&&e.click.call(this,o)}),n.on(\"scroll\",function(){clearTimeout(o),o=setTimeout(function(){u()},100)}))},countdown:function(e,t,i){var o=this,a=\"function\"==typeof t,r=new Date(e).getTime(),n=new Date(!t||a?(new Date).getTime():t).getTime(),l=r-n,c=[Math.floor(l/864e5),Math.floor(l/36e5)%24,Math.floor(l/6e4)%60,Math.floor(l/1e3)%60];a&&(i=t);var g=setTimeout(function(){o.countdown(e,n+1e3,i)},1e3);return i&&i(l>0?c:[0,0,0,0],t,g),l<=0&&clearTimeout(g),g},timeAgo:function(e,t){var i=this,o=[[],[]],a=(new Date).getTime()-new Date(e).getTime();return a>6912e5?(a=new Date(e),o[0][0]=i.digit(a.getFullYear(),4),o[0][1]=i.digit(a.getMonth()+1),o[0][2]=i.digit(a.getDate()),t||(o[1][0]=i.digit(a.getHours()),o[1][1]=i.digit(a.getMinutes()),o[1][2]=i.digit(a.getSeconds())),o[0].join(\"-\")+\" \"+o[1].join(\":\")):a>=864e5?(a/1e3/60/60/24|0)+\"天前\":a>=36e5?(a/1e3/60/60|0)+\"小时前\":a>=12e4?(a/1e3/60|0)+\"分钟前\":a<0?\"未来\":\"刚刚\"},digit:function(e,t){var i=\"\";e=String(e),t=t||2;for(var o=e.length;o<t;o++)i+=\"0\";return e<Math.pow(10,t)?i+(0|e):e},toDateString:function(e,t){var i=this,o=new Date(e||new Date),a=[i.digit(o.getFullYear(),4),i.digit(o.getMonth()+1),i.digit(o.getDate())],r=[i.digit(o.getHours()),i.digit(o.getMinutes()),i.digit(o.getSeconds())];return t=t||\"yyyy-MM-dd HH:mm:ss\",t.replace(/yyyy/g,a[0]).replace(/MM/g,a[1]).replace(/dd/g,a[2]).replace(/HH/g,r[0]).replace(/mm/g,r[1]).replace(/ss/g,r[2])}};e(\"util\",i)});"
  },
  {
    "path": "open-layui-web/src/main/view/static/layui/layui.all.js",
    "content": "/** layui-v2.3.0-rc1 MIT License By https://www.layui.com */\n ;!function(e){\"use strict\";var t=document,n={modules:{},status:{},timeout:10,event:{}},o=function(){this.v=\"2.3.0-rc1\"},r=function(){var e=t.currentScript?t.currentScript.src:function(){for(var e,n=t.scripts,o=n.length-1,r=o;r>0;r--)if(\"interactive\"===n[r].readyState){e=n[r].src;break}return e||n[o].src}();return e.substring(0,e.lastIndexOf(\"/\")+1)}(),a=function(t){e.console&&console.error&&console.error(\"Layui hint: \"+t)},i=\"undefined\"!=typeof opera&&\"[object Opera]\"===opera.toString(),u={layer:\"modules/layer\",laydate:\"modules/laydate\",laypage:\"modules/laypage\",laytpl:\"modules/laytpl\",layim:\"modules/layim\",layedit:\"modules/layedit\",form:\"modules/form\",upload:\"modules/upload\",tree:\"modules/tree\",table:\"modules/table\",element:\"modules/element\",rate:\"modules/rate\",carousel:\"modules/carousel\",flow:\"modules/flow\",util:\"modules/util\",code:\"modules/code\",jquery:\"modules/jquery\",mobile:\"modules/mobile\",\"layui.all\":\"../layui.all\"};o.prototype.cache=n,o.prototype.define=function(e,t){var o=this,r=\"function\"==typeof e,a=function(){var e=function(e,t){layui[e]=t,n.status[e]=!0};return\"function\"==typeof t&&t(function(o,r){e(o,r),n.callback[o]=function(){t(e)}}),this};return r&&(t=e,e=[]),layui[\"layui.all\"]||!layui[\"layui.all\"]&&layui[\"layui.mobile\"]?a.call(o):(o.use(e,a),o)},o.prototype.use=function(e,o,l){function s(e,t){var o=\"PLaySTATION 3\"===navigator.platform?/^complete$/:/^(complete|loaded)$/;(\"load\"===e.type||o.test((e.currentTarget||e.srcElement).readyState))&&(n.modules[d]=t,f.removeChild(v),function r(){return++m>1e3*n.timeout/4?a(d+\" is not a valid module\"):void(n.status[d]?c():setTimeout(r,4))}())}function c(){l.push(layui[d]),e.length>1?y.use(e.slice(1),o,l):\"function\"==typeof o&&o.apply(layui,l)}var y=this,p=n.dir=n.dir?n.dir:r,f=t.getElementsByTagName(\"head\")[0];e=\"string\"==typeof e?[e]:e,window.jQuery&&jQuery.fn.on&&(y.each(e,function(t,n){\"jquery\"===n&&e.splice(t,1)}),layui.jquery=layui.$=jQuery);var d=e[0],m=0;if(l=l||[],n.host=n.host||(p.match(/\\/\\/([\\s\\S]+?)\\//)||[\"//\"+location.host+\"/\"])[0],0===e.length||layui[\"layui.all\"]&&u[d]||!layui[\"layui.all\"]&&layui[\"layui.mobile\"]&&u[d])return c(),y;if(n.modules[d])!function g(){return++m>1e3*n.timeout/4?a(d+\" is not a valid module\"):void(\"string\"==typeof n.modules[d]&&n.status[d]?c():setTimeout(g,4))}();else{var v=t.createElement(\"script\"),h=(u[d]?p+\"lay/\":/^\\{\\/\\}/.test(y.modules[d])?\"\":n.base||\"\")+(y.modules[d]||d)+\".js\";h=h.replace(/^\\{\\/\\}/,\"\"),v.async=!0,v.charset=\"utf-8\",v.src=h+function(){var e=n.version===!0?n.v||(new Date).getTime():n.version||\"\";return e?\"?v=\"+e:\"\"}(),f.appendChild(v),!v.attachEvent||v.attachEvent.toString&&v.attachEvent.toString().indexOf(\"[native code\")<0||i?v.addEventListener(\"load\",function(e){s(e,h)},!1):v.attachEvent(\"onreadystatechange\",function(e){s(e,h)}),n.modules[d]=h}return y},o.prototype.getStyle=function(t,n){var o=t.currentStyle?t.currentStyle:e.getComputedStyle(t,null);return o[o.getPropertyValue?\"getPropertyValue\":\"getAttribute\"](n)},o.prototype.link=function(e,o,r){var i=this,u=t.createElement(\"link\"),l=t.getElementsByTagName(\"head\")[0];\"string\"==typeof o&&(r=o);var s=(r||e).replace(/\\.|\\//g,\"\"),c=u.id=\"layuicss-\"+s,y=0;return u.rel=\"stylesheet\",u.href=e+(n.debug?\"?v=\"+(new Date).getTime():\"\"),u.media=\"all\",t.getElementById(c)||l.appendChild(u),\"function\"!=typeof o?i:(function p(){return++y>1e3*n.timeout/100?a(e+\" timeout\"):void(1989===parseInt(i.getStyle(t.getElementById(c),\"width\"))?function(){o()}():setTimeout(p,100))}(),i)},n.callback={},o.prototype.factory=function(e){if(layui[e])return\"function\"==typeof n.callback[e]?n.callback[e]:null},o.prototype.addcss=function(e,t,o){return layui.link(n.dir+\"css/\"+e,t,o)},o.prototype.img=function(e,t,n){var o=new Image;return o.src=e,o.complete?t(o):(o.onload=function(){o.onload=null,\"function\"==typeof t&&t(o)},void(o.onerror=function(e){o.onerror=null,\"function\"==typeof n&&n(e)}))},o.prototype.config=function(e){e=e||{};for(var t in e)n[t]=e[t];return this},o.prototype.modules=function(){var e={};for(var t in u)e[t]=u[t];return e}(),o.prototype.extend=function(e){var t=this;e=e||{};for(var n in e)t[n]||t.modules[n]?a(\"模块名 \"+n+\" 已被占用\"):t.modules[n]=e[n];return t},o.prototype.router=function(e){var t=this,e=e||location.hash,n={path:[],search:{},hash:(e.match(/[^#](#.*$)/)||[])[1]||\"\"};return/^#\\//.test(e)?(e=e.replace(/^#\\//,\"\"),n.href=\"/\"+e,e=e.replace(/([^#])(#.*$)/,\"$1\").split(\"/\")||[],t.each(e,function(e,t){/^\\w+=/.test(t)?function(){t=t.split(\"=\"),n.search[t[0]]=t[1]}():n.path.push(t)}),n):n},o.prototype.data=function(t,n,o){if(t=t||\"layui\",o=o||localStorage,e.JSON&&e.JSON.parse){if(null===n)return delete o[t];n=\"object\"==typeof n?n:{key:n};try{var r=JSON.parse(o[t])}catch(a){var r={}}return\"value\"in n&&(r[n.key]=n.value),n.remove&&delete r[n.key],o[t]=JSON.stringify(r),n.key?r[n.key]:r}},o.prototype.sessionData=function(e,t){return this.data(e,t,sessionStorage)},o.prototype.device=function(t){var n=navigator.userAgent.toLowerCase(),o=function(e){var t=new RegExp(e+\"/([^\\\\s\\\\_\\\\-]+)\");return e=(n.match(t)||[])[1],e||!1},r={os:function(){return/windows/.test(n)?\"windows\":/linux/.test(n)?\"linux\":/iphone|ipod|ipad|ios/.test(n)?\"ios\":/mac/.test(n)?\"mac\":void 0}(),ie:function(){return!!(e.ActiveXObject||\"ActiveXObject\"in e)&&((n.match(/msie\\s(\\d+)/)||[])[1]||\"11\")}(),weixin:o(\"micromessenger\")};return t&&!r[t]&&(r[t]=o(t)),r.android=/android/.test(n),r.ios=\"ios\"===r.os,r},o.prototype.hint=function(){return{error:a}},o.prototype.each=function(e,t){var n,o=this;if(\"function\"!=typeof t)return o;if(e=e||[],e.constructor===Object){for(n in e)if(t.call(e[n],n,e[n]))break}else for(n=0;n<e.length&&!t.call(e[n],n,e[n]);n++);return o},o.prototype.sort=function(e,t,n){var o=JSON.parse(JSON.stringify(e||[]));return t?(o.sort(function(e,n){var o=/^-?\\d+$/,r=e[t],a=n[t];return o.test(r)&&(r=parseFloat(r)),o.test(a)&&(a=parseFloat(a)),r&&!a?1:!r&&a?-1:r>a?1:r<a?-1:0}),n&&o.reverse(),o):o},o.prototype.stope=function(t){t=t||e.event;try{t.stopPropagation()}catch(n){t.cancelBubble=!0}},o.prototype.onevent=function(e,t,n){return\"string\"!=typeof e||\"function\"!=typeof n?this:o.event(e,t,null,n)},o.prototype.event=o.event=function(e,t,o,r){var a=this,i=null,u=t.match(/\\((.*)\\)$/)||[],l=(e+\".\"+t).replace(u[0],\"\"),s=u[1]||\"\",c=function(e,t){var n=t&&t.call(a,o);n===!1&&null===i&&(i=!1)};return r?(n.event[l]=n.event[l]||{},n.event[l][s]=[r],this):(layui.each(n.event[l],function(e,t){return\"{*}\"===s?void layui.each(t,c):(\"\"===e&&layui.each(t,c),void(e===s&&layui.each(t,c)))}),i)},e.layui=new o}(window);layui.define(function(a){var i=layui.cache;layui.config({dir:i.dir.replace(/lay\\/dest\\/$/,\"\")}),a(\"layui.all\",layui.v)});layui.define(function(e){\"use strict\";var r={open:\"{{\",close:\"}}\"},c={exp:function(e){return new RegExp(e,\"g\")},query:function(e,c,t){var o=[\"#([\\\\s\\\\S])+?\",\"([^{#}])*?\"][e||0];return n((c||\"\")+r.open+o+r.close+(t||\"\"))},escape:function(e){return String(e||\"\").replace(/&(?!#?[a-zA-Z0-9]+;)/g,\"&amp;\").replace(/</g,\"&lt;\").replace(/>/g,\"&gt;\").replace(/'/g,\"&#39;\").replace(/\"/g,\"&quot;\")},error:function(e,r){var c=\"Laytpl Error：\";return\"object\"==typeof console&&console.error(c+e+\"\\n\"+(r||\"\")),c+e}},n=c.exp,t=function(e){this.tpl=e};t.pt=t.prototype,window.errors=0,t.pt.parse=function(e,t){var o=this,p=e,a=n(\"^\"+r.open+\"#\",\"\"),l=n(r.close+\"$\",\"\");e=e.replace(/\\s+|\\r|\\t|\\n/g,\" \").replace(n(r.open+\"#\"),r.open+\"# \").replace(n(r.close+\"}\"),\"} \"+r.close).replace(/\\\\/g,\"\\\\\\\\\").replace(n(r.open+\"!(.+?)!\"+r.close),function(e){return e=e.replace(n(\"^\"+r.open+\"!\"),\"\").replace(n(\"!\"+r.close),\"\").replace(n(r.open+\"|\"+r.close),function(e){return e.replace(/(.)/g,\"\\\\$1\")})}).replace(/(?=\"|')/g,\"\\\\\").replace(c.query(),function(e){return e=e.replace(a,\"\").replace(l,\"\"),'\";'+e.replace(/\\\\/g,\"\")+';view+=\"'}).replace(c.query(1),function(e){var c='\"+(';return e.replace(/\\s/g,\"\")===r.open+r.close?\"\":(e=e.replace(n(r.open+\"|\"+r.close),\"\"),/^=/.test(e)&&(e=e.replace(/^=/,\"\"),c='\"+_escape_('),c+e.replace(/\\\\/g,\"\")+')+\"')}),e='\"use strict\";var view = \"'+e+'\";return view;';try{return o.cache=e=new Function(\"d, _escape_\",e),e(t,c.escape)}catch(u){return delete o.cache,c.error(u,p)}},t.pt.render=function(e,r){var n,t=this;return e?(n=t.cache?t.cache(e,c.escape):t.parse(t.tpl,e),r?void r(n):n):c.error(\"no data\")};var o=function(e){return\"string\"!=typeof e?c.error(\"Template not found\"):new t(e)};o.config=function(e){e=e||{};for(var c in e)r[c]=e[c]},o.v=\"1.2.0\",e(\"laytpl\",o)});layui.define(function(e){\"use strict\";var a=document,t=\"getElementById\",n=\"getElementsByTagName\",i=\"laypage\",r=\"layui-disabled\",u=function(e){var a=this;a.config=e||{},a.config.index=++s.index,a.render(!0)};u.prototype.type=function(){var e=this.config;if(\"object\"==typeof e.elem)return void 0===e.elem.length?2:3},u.prototype.view=function(){var e=this,a=e.config,t=a.groups=\"groups\"in a?0|a.groups:5;a.layout=\"object\"==typeof a.layout?a.layout:[\"prev\",\"page\",\"next\"],a.count=0|a.count,a.curr=0|a.curr||1,a.limits=\"object\"==typeof a.limits?a.limits:[10,20,30,40,50],a.limit=0|a.limit||10,a.pages=Math.ceil(a.count/a.limit)||1,a.curr>a.pages&&(a.curr=a.pages),t<0?t=1:t>a.pages&&(t=a.pages),a.prev=\"prev\"in a?a.prev:\"&#x4E0A;&#x4E00;&#x9875;\",a.next=\"next\"in a?a.next:\"&#x4E0B;&#x4E00;&#x9875;\";var n=a.pages>t?Math.ceil((a.curr+(t>1?1:0))/(t>0?t:1)):1,i={prev:function(){return a.prev?'<a href=\"javascript:;\" class=\"layui-laypage-prev'+(1==a.curr?\" \"+r:\"\")+'\" data-page=\"'+(a.curr-1)+'\">'+a.prev+\"</a>\":\"\"}(),page:function(){var e=[];if(a.count<1)return\"\";n>1&&a.first!==!1&&0!==t&&e.push('<a href=\"javascript:;\" class=\"layui-laypage-first\" data-page=\"1\"  title=\"&#x9996;&#x9875;\">'+(a.first||1)+\"</a>\");var i=Math.floor((t-1)/2),r=n>1?a.curr-i:1,u=n>1?function(){var e=a.curr+(t-i-1);return e>a.pages?a.pages:e}():t;for(u-r<t-1&&(r=u-t+1),a.first!==!1&&r>2&&e.push('<span class=\"layui-laypage-spr\">&#x2026;</span>');r<=u;r++)r===a.curr?e.push('<span class=\"layui-laypage-curr\"><em class=\"layui-laypage-em\" '+(/^#/.test(a.theme)?'style=\"background-color:'+a.theme+';\"':\"\")+\"></em><em>\"+r+\"</em></span>\"):e.push('<a href=\"javascript:;\" data-page=\"'+r+'\">'+r+\"</a>\");return a.pages>t&&a.pages>u&&a.last!==!1&&(u+1<a.pages&&e.push('<span class=\"layui-laypage-spr\">&#x2026;</span>'),0!==t&&e.push('<a href=\"javascript:;\" class=\"layui-laypage-last\" title=\"&#x5C3E;&#x9875;\"  data-page=\"'+a.pages+'\">'+(a.last||a.pages)+\"</a>\")),e.join(\"\")}(),next:function(){return a.next?'<a href=\"javascript:;\" class=\"layui-laypage-next'+(a.curr==a.pages?\" \"+r:\"\")+'\" data-page=\"'+(a.curr+1)+'\">'+a.next+\"</a>\":\"\"}(),count:'<span class=\"layui-laypage-count\">共 '+a.count+\" 条</span>\",limit:function(){var e=['<span class=\"layui-laypage-limits\"><select lay-ignore>'];return layui.each(a.limits,function(t,n){e.push('<option value=\"'+n+'\"'+(n===a.limit?\"selected\":\"\")+\">\"+n+\" 条/页</option>\")}),e.join(\"\")+\"</select></span>\"}(),refresh:['<a href=\"javascript:;\" data-page=\"'+a.curr+'\" class=\"layui-laypage-refresh\">','<i class=\"layui-icon layui-icon-refresh\"></i>',\"</a>\"].join(\"\"),skip:function(){return['<span class=\"layui-laypage-skip\">&#x5230;&#x7B2C;','<input type=\"text\" min=\"1\" value=\"'+a.curr+'\" class=\"layui-input\">','&#x9875;<button type=\"button\" class=\"layui-laypage-btn\">&#x786e;&#x5b9a;</button>',\"</span>\"].join(\"\")}()};return['<div class=\"layui-box layui-laypage layui-laypage-'+(a.theme?/^#/.test(a.theme)?\"molv\":a.theme:\"default\")+'\" id=\"layui-laypage-'+a.index+'\">',function(){var e=[];return layui.each(a.layout,function(a,t){i[t]&&e.push(i[t])}),e.join(\"\")}(),\"</div>\"].join(\"\")},u.prototype.jump=function(e,a){if(e){var t=this,i=t.config,r=e.children,u=e[n](\"button\")[0],l=e[n](\"input\")[0],p=e[n](\"select\")[0],c=function(){var e=0|l.value.replace(/\\s|\\D/g,\"\");e&&(i.curr=e,t.render())};if(a)return c();for(var o=0,y=r.length;o<y;o++)\"a\"===r[o].nodeName.toLowerCase()&&s.on(r[o],\"click\",function(){var e=0|this.getAttribute(\"data-page\");e<1||e>i.pages||(i.curr=e,t.render())});p&&s.on(p,\"change\",function(){var e=this.value;i.curr*e>i.count&&(i.curr=Math.ceil(i.count/e)),i.limit=e,t.render()}),u&&s.on(u,\"click\",function(){c()})}},u.prototype.skip=function(e){if(e){var a=this,t=e[n](\"input\")[0];t&&s.on(t,\"keyup\",function(t){var n=this.value,i=t.keyCode;/^(37|38|39|40)$/.test(i)||(/\\D/.test(n)&&(this.value=n.replace(/\\D/,\"\")),13===i&&a.jump(e,!0))})}},u.prototype.render=function(e){var n=this,i=n.config,r=n.type(),u=n.view();2===r?i.elem&&(i.elem.innerHTML=u):3===r?i.elem.html(u):a[t](i.elem)&&(a[t](i.elem).innerHTML=u),i.jump&&i.jump(i,e);var s=a[t](\"layui-laypage-\"+i.index);n.jump(s),i.hash&&!e&&(location.hash=\"!\"+i.hash+\"=\"+i.curr),n.skip(s)};var s={render:function(e){var a=new u(e);return a.index},index:layui.laypage?layui.laypage.index+1e4:0,on:function(e,a,t){return e.attachEvent?e.attachEvent(\"on\"+a,function(a){a.target=a.srcElement,t.call(e,a)}):e.addEventListener(a,t,!1),this}};e(i,s)});!function(){\"use strict\";var e=window.layui&&layui.define,t={getPath:function(){var e=document.currentScript?document.currentScript.src:function(){for(var e,t=document.scripts,n=t.length-1,a=n;a>0;a--)if(\"interactive\"===t[a].readyState){e=t[a].src;break}return e||t[n].src}();return e.substring(0,e.lastIndexOf(\"/\")+1)}(),getStyle:function(e,t){var n=e.currentStyle?e.currentStyle:window.getComputedStyle(e,null);return n[n.getPropertyValue?\"getPropertyValue\":\"getAttribute\"](t)},link:function(e,a,i){if(n.path){var r=document.getElementsByTagName(\"head\")[0],o=document.createElement(\"link\");\"string\"==typeof a&&(i=a);var s=(i||e).replace(/\\.|\\//g,\"\"),l=\"layuicss-\"+s,d=0;o.rel=\"stylesheet\",o.href=n.path+e,o.id=l,document.getElementById(l)||r.appendChild(o),\"function\"==typeof a&&!function c(){return++d>80?window.console&&console.error(\"laydate.css: Invalid\"):void(1989===parseInt(t.getStyle(document.getElementById(l),\"width\"))?a():setTimeout(c,100))}()}}},n={v:\"5.0.9\",config:{},index:window.laydate&&window.laydate.v?1e5:0,path:t.getPath,set:function(e){var t=this;return t.config=w.extend({},t.config,e),t},ready:function(a){var i=\"laydate\",r=\"\",o=(e?\"modules/laydate/\":\"theme/\")+\"default/laydate.css?v=\"+n.v+r;return e?layui.addcss(o,a,i):t.link(o,a,i),this}},a=function(){var e=this;return{hint:function(t){e.hint.call(e,t)},config:e.config}},i=\"laydate\",r=\".layui-laydate\",o=\"layui-this\",s=\"laydate-disabled\",l=\"开始日期超出了结束日期<br>建议重新选择\",d=[100,2e5],c=\"layui-laydate-static\",m=\"layui-laydate-list\",u=\"laydate-selected\",h=\"layui-laydate-hint\",y=\"laydate-day-prev\",f=\"laydate-day-next\",p=\"layui-laydate-footer\",g=\".laydate-btns-confirm\",v=\"laydate-time-text\",D=\".laydate-btns-time\",T=function(e){var t=this;t.index=++n.index,t.config=w.extend({},t.config,n.config,e),n.ready(function(){t.init()})},w=function(e){return new C(e)},C=function(e){for(var t=0,n=\"object\"==typeof e?[e]:(this.selector=e,document.querySelectorAll(e||null));t<n.length;t++)this.push(n[t])};C.prototype=[],C.prototype.constructor=C,w.extend=function(){var e=1,t=arguments,n=function(e,t){e=e||(t.constructor===Array?[]:{});for(var a in t)e[a]=t[a]&&t[a].constructor===Object?n(e[a],t[a]):t[a];return e};for(t[0]=\"object\"==typeof t[0]?t[0]:{};e<t.length;e++)\"object\"==typeof t[e]&&n(t[0],t[e]);return t[0]},w.ie=function(){var e=navigator.userAgent.toLowerCase();return!!(window.ActiveXObject||\"ActiveXObject\"in window)&&((e.match(/msie\\s(\\d+)/)||[])[1]||\"11\")}(),w.stope=function(e){e=e||window.event,e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},w.each=function(e,t){var n,a=this;if(\"function\"!=typeof t)return a;if(e=e||[],e.constructor===Object){for(n in e)if(t.call(e[n],n,e[n]))break}else for(n=0;n<e.length&&!t.call(e[n],n,e[n]);n++);return a},w.digit=function(e,t,n){var a=\"\";e=String(e),t=t||2;for(var i=e.length;i<t;i++)a+=\"0\";return e<Math.pow(10,t)?a+(0|e):e},w.elem=function(e,t){var n=document.createElement(e);return w.each(t||{},function(e,t){n.setAttribute(e,t)}),n},C.addStr=function(e,t){return e=e.replace(/\\s+/,\" \"),t=t.replace(/\\s+/,\" \").split(\" \"),w.each(t,function(t,n){new RegExp(\"\\\\b\"+n+\"\\\\b\").test(e)||(e=e+\" \"+n)}),e.replace(/^\\s|\\s$/,\"\")},C.removeStr=function(e,t){return e=e.replace(/\\s+/,\" \"),t=t.replace(/\\s+/,\" \").split(\" \"),w.each(t,function(t,n){var a=new RegExp(\"\\\\b\"+n+\"\\\\b\");a.test(e)&&(e=e.replace(a,\"\"))}),e.replace(/\\s+/,\" \").replace(/^\\s|\\s$/,\"\")},C.prototype.find=function(e){var t=this,n=0,a=[],i=\"object\"==typeof e;return this.each(function(r,o){for(var s=i?[e]:o.querySelectorAll(e||null);n<s.length;n++)a.push(s[n]);t.shift()}),i||(t.selector=(t.selector?t.selector+\" \":\"\")+e),w.each(a,function(e,n){t.push(n)}),t},C.prototype.each=function(e){return w.each.call(this,this,e)},C.prototype.addClass=function(e,t){return this.each(function(n,a){a.className=C[t?\"removeStr\":\"addStr\"](a.className,e)})},C.prototype.removeClass=function(e){return this.addClass(e,!0)},C.prototype.hasClass=function(e){var t=!1;return this.each(function(n,a){new RegExp(\"\\\\b\"+e+\"\\\\b\").test(a.className)&&(t=!0)}),t},C.prototype.attr=function(e,t){var n=this;return void 0===t?function(){if(n.length>0)return n[0].getAttribute(e)}():n.each(function(n,a){a.setAttribute(e,t)})},C.prototype.removeAttr=function(e){return this.each(function(t,n){n.removeAttribute(e)})},C.prototype.html=function(e){return this.each(function(t,n){n.innerHTML=e})},C.prototype.val=function(e){return this.each(function(t,n){n.value=e})},C.prototype.append=function(e){return this.each(function(t,n){\"object\"==typeof e?n.appendChild(e):n.innerHTML=n.innerHTML+e})},C.prototype.remove=function(e){return this.each(function(t,n){e?n.removeChild(e):n.parentNode.removeChild(n)})},C.prototype.on=function(e,t){return this.each(function(n,a){a.attachEvent?a.attachEvent(\"on\"+e,function(e){e.target=e.srcElement,t.call(a,e)}):a.addEventListener(e,t,!1)})},C.prototype.off=function(e,t){return this.each(function(n,a){a.detachEvent?a.detachEvent(\"on\"+e,t):a.removeEventListener(e,t,!1)})},T.isLeapYear=function(e){return e%4===0&&e%100!==0||e%400===0},T.prototype.config={type:\"date\",range:!1,format:\"yyyy-MM-dd\",value:null,isInitValue:!1,min:\"1900-1-1\",max:\"2099-12-31\",trigger:\"focus\",show:!1,showBottom:!0,btns:[\"clear\",\"now\",\"confirm\"],lang:\"cn\",theme:\"default\",position:null,calendar:!1,mark:{},zIndex:null,done:null,change:null},T.prototype.lang=function(){var e=this,t=e.config,n={cn:{weeks:[\"日\",\"一\",\"二\",\"三\",\"四\",\"五\",\"六\"],time:[\"时\",\"分\",\"秒\"],timeTips:\"选择时间\",startTime:\"开始时间\",endTime:\"结束时间\",dateTips:\"返回日期\",month:[\"一\",\"二\",\"三\",\"四\",\"五\",\"六\",\"七\",\"八\",\"九\",\"十\",\"十一\",\"十二\"],tools:{confirm:\"确定\",clear:\"清空\",now:\"现在\"}},en:{weeks:[\"Su\",\"Mo\",\"Tu\",\"We\",\"Th\",\"Fr\",\"Sa\"],time:[\"Hours\",\"Minutes\",\"Seconds\"],timeTips:\"Select Time\",startTime:\"Start Time\",endTime:\"End Time\",dateTips:\"Select Date\",month:[\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\"],tools:{confirm:\"Confirm\",clear:\"Clear\",now:\"Now\"}}};return n[t.lang]||n.cn},T.prototype.init=function(){var e=this,t=e.config,n=\"yyyy|y|MM|M|dd|d|HH|H|mm|m|ss|s\",a=\"static\"===t.position,i={year:\"yyyy\",month:\"yyyy-MM\",date:\"yyyy-MM-dd\",time:\"HH:mm:ss\",datetime:\"yyyy-MM-dd HH:mm:ss\"};t.elem=w(t.elem),t.eventElem=w(t.eventElem),t.elem[0]&&(t.range===!0&&(t.range=\"-\"),t.format===i.date&&(t.format=i[t.type]),e.format=t.format.match(new RegExp(n+\"|.\",\"g\"))||[],e.EXP_IF=\"\",e.EXP_SPLIT=\"\",w.each(e.format,function(t,a){var i=new RegExp(n).test(a)?\"\\\\d{\"+function(){return new RegExp(n).test(e.format[0===t?t+1:t-1]||\"\")?/^yyyy|y$/.test(a)?4:a.length:/^yyyy$/.test(a)?\"1,4\":/^y$/.test(a)?\"1,308\":\"1,2\"}()+\"}\":\"\\\\\"+a;e.EXP_IF=e.EXP_IF+i,e.EXP_SPLIT=e.EXP_SPLIT+\"(\"+i+\")\"}),e.EXP_IF=new RegExp(\"^\"+(t.range?e.EXP_IF+\"\\\\s\\\\\"+t.range+\"\\\\s\"+e.EXP_IF:e.EXP_IF)+\"$\"),e.EXP_SPLIT=new RegExp(\"^\"+e.EXP_SPLIT+\"$\",\"\"),e.isInput(t.elem[0])||\"focus\"===t.trigger&&(t.trigger=\"click\"),t.elem.attr(\"lay-key\")||(t.elem.attr(\"lay-key\",e.index),t.eventElem.attr(\"lay-key\",e.index)),t.mark=w.extend({},t.calendar&&\"cn\"===t.lang?{\"0-1-1\":\"元旦\",\"0-2-14\":\"情人\",\"0-3-8\":\"妇女\",\"0-3-12\":\"植树\",\"0-4-1\":\"愚人\",\"0-5-1\":\"劳动\",\"0-5-4\":\"青年\",\"0-6-1\":\"儿童\",\"0-9-10\":\"教师\",\"0-9-18\":\"国耻\",\"0-10-1\":\"国庆\",\"0-12-25\":\"圣诞\"}:{},t.mark),w.each([\"min\",\"max\"],function(e,n){var a=[],i=[];if(\"number\"==typeof t[n]){var r=t[n],o=(new Date).getTime(),s=864e5,l=new Date(r?r<s?o+r*s:r:o);a=[l.getFullYear(),l.getMonth()+1,l.getDate()],r<s||(i=[l.getHours(),l.getMinutes(),l.getSeconds()])}else a=(t[n].match(/\\d+-\\d+-\\d+/)||[\"\"])[0].split(\"-\"),i=(t[n].match(/\\d+:\\d+:\\d+/)||[\"\"])[0].split(\":\");t[n]={year:0|a[0]||(new Date).getFullYear(),month:a[1]?(0|a[1])-1:(new Date).getMonth(),date:0|a[2]||(new Date).getDate(),hours:0|i[0],minutes:0|i[1],seconds:0|i[2]}}),e.elemID=\"layui-laydate\"+t.elem.attr(\"lay-key\"),(t.show||a)&&e.render(),a||e.events(),t.value&&t.isInitValue&&(t.value.constructor===Date?e.setValue(e.parse(0,e.systemDate(t.value))):e.setValue(t.value)))},T.prototype.render=function(){var e=this,t=e.config,n=e.lang(),a=\"static\"===t.position,i=e.elem=w.elem(\"div\",{id:e.elemID,\"class\":[\"layui-laydate\",t.range?\" layui-laydate-range\":\"\",a?\" \"+c:\"\",t.theme&&\"default\"!==t.theme&&!/^#/.test(t.theme)?\" laydate-theme-\"+t.theme:\"\"].join(\"\")}),r=e.elemMain=[],o=e.elemHeader=[],s=e.elemCont=[],l=e.table=[],d=e.footer=w.elem(\"div\",{\"class\":p});if(t.zIndex&&(i.style.zIndex=t.zIndex),w.each(new Array(2),function(e){if(!t.range&&e>0)return!0;var a=w.elem(\"div\",{\"class\":\"layui-laydate-header\"}),i=[function(){var e=w.elem(\"i\",{\"class\":\"layui-icon laydate-icon laydate-prev-y\"});return e.innerHTML=\"&#xe65a;\",e}(),function(){var e=w.elem(\"i\",{\"class\":\"layui-icon laydate-icon laydate-prev-m\"});return e.innerHTML=\"&#xe603;\",e}(),function(){var e=w.elem(\"div\",{\"class\":\"laydate-set-ym\"}),t=w.elem(\"span\"),n=w.elem(\"span\");return e.appendChild(t),e.appendChild(n),e}(),function(){var e=w.elem(\"i\",{\"class\":\"layui-icon laydate-icon laydate-next-m\"});return e.innerHTML=\"&#xe602;\",e}(),function(){var e=w.elem(\"i\",{\"class\":\"layui-icon laydate-icon laydate-next-y\"});return e.innerHTML=\"&#xe65b;\",e}()],d=w.elem(\"div\",{\"class\":\"layui-laydate-content\"}),c=w.elem(\"table\"),m=w.elem(\"thead\"),u=w.elem(\"tr\");w.each(i,function(e,t){a.appendChild(t)}),m.appendChild(u),w.each(new Array(6),function(e){var t=c.insertRow(0);w.each(new Array(7),function(a){if(0===e){var i=w.elem(\"th\");i.innerHTML=n.weeks[a],u.appendChild(i)}t.insertCell(a)})}),c.insertBefore(m,c.children[0]),d.appendChild(c),r[e]=w.elem(\"div\",{\"class\":\"layui-laydate-main laydate-main-list-\"+e}),r[e].appendChild(a),r[e].appendChild(d),o.push(i),s.push(d),l.push(c)}),w(d).html(function(){var e=[],i=[];return\"datetime\"===t.type&&e.push('<span lay-type=\"datetime\" class=\"laydate-btns-time\">'+n.timeTips+\"</span>\"),w.each(t.btns,function(e,r){var o=n.tools[r]||\"btn\";t.range&&\"now\"===r||(a&&\"clear\"===r&&(o=\"cn\"===t.lang?\"重置\":\"Reset\"),i.push('<span lay-type=\"'+r+'\" class=\"laydate-btns-'+r+'\">'+o+\"</span>\"))}),e.push('<div class=\"laydate-footer-btns\">'+i.join(\"\")+\"</div>\"),e.join(\"\")}()),w.each(r,function(e,t){i.appendChild(t)}),t.showBottom&&i.appendChild(d),/^#/.test(t.theme)){var m=w.elem(\"style\"),u=[\"#{{id}} .layui-laydate-header{background-color:{{theme}};}\",\"#{{id}} .layui-this{background-color:{{theme}} !important;}\"].join(\"\").replace(/{{id}}/g,e.elemID).replace(/{{theme}}/g,t.theme);\"styleSheet\"in m?(m.setAttribute(\"type\",\"text/css\"),m.styleSheet.cssText=u):m.innerHTML=u,w(i).addClass(\"laydate-theme-molv\"),i.appendChild(m)}e.remove(T.thisElemDate),a?t.elem.append(i):(document.body.appendChild(i),e.position()),e.checkDate().calendar(),e.changeEvent(),T.thisElemDate=e.elemID,\"function\"==typeof t.ready&&t.ready(w.extend({},t.dateTime,{month:t.dateTime.month+1}))},T.prototype.remove=function(e){var t=this,n=(t.config,w(\"#\"+(e||t.elemID)));return n.hasClass(c)||t.checkDate(function(){n.remove()}),t},T.prototype.position=function(){var e=this,t=e.config,n=e.bindElem||t.elem[0],a=n.getBoundingClientRect(),i=e.elem.offsetWidth,r=e.elem.offsetHeight,o=function(e){return e=e?\"scrollLeft\":\"scrollTop\",document.body[e]|document.documentElement[e]},s=function(e){return document.documentElement[e?\"clientWidth\":\"clientHeight\"]},l=5,d=a.left,c=a.bottom;d+i+l>s(\"width\")&&(d=s(\"width\")-i-l),c+r+l>s()&&(c=a.top>r?a.top-r:s()-r,c-=2*l),t.position&&(e.elem.style.position=t.position),e.elem.style.left=d+(\"fixed\"===t.position?0:o(1))+\"px\",e.elem.style.top=c+(\"fixed\"===t.position?0:o())+\"px\"},T.prototype.hint=function(e){var t=this,n=(t.config,w.elem(\"div\",{\"class\":h}));n.innerHTML=e||\"\",w(t.elem).find(\".\"+h).remove(),t.elem.appendChild(n),clearTimeout(t.hinTimer),t.hinTimer=setTimeout(function(){w(t.elem).find(\".\"+h).remove()},3e3)},T.prototype.getAsYM=function(e,t,n){return n?t--:t++,t<0&&(t=11,e--),t>11&&(t=0,e++),[e,t]},T.prototype.systemDate=function(e){var t=e||new Date;return{year:t.getFullYear(),month:t.getMonth(),date:t.getDate(),hours:e?e.getHours():0,minutes:e?e.getMinutes():0,seconds:e?e.getSeconds():0}},T.prototype.checkDate=function(e){var t,a,i=this,r=(new Date,i.config),o=r.dateTime=r.dateTime||i.systemDate(),s=i.bindElem||r.elem[0],l=(i.isInput(s)?\"val\":\"html\",i.isInput(s)?s.value:\"static\"===r.position?\"\":s.innerHTML),c=function(e){e.year>d[1]&&(e.year=d[1],a=!0),e.month>11&&(e.month=11,a=!0),e.hours>23&&(e.hours=0,a=!0),e.minutes>59&&(e.minutes=0,e.hours++,a=!0),e.seconds>59&&(e.seconds=0,e.minutes++,a=!0),t=n.getEndDate(e.month+1,e.year),e.date>t&&(e.date=t,a=!0)},m=function(e,t,n){var o=[\"startTime\",\"endTime\"];t=(t.match(i.EXP_SPLIT)||[]).slice(1),n=n||0,r.range&&(i[o[n]]=i[o[n]]||{}),w.each(i.format,function(s,l){var c=parseFloat(t[s]);t[s].length<l.length&&(a=!0),/yyyy|y/.test(l)?(c<d[0]&&(c=d[0],a=!0),e.year=c):/MM|M/.test(l)?(c<1&&(c=1,a=!0),e.month=c-1):/dd|d/.test(l)?(c<1&&(c=1,a=!0),e.date=c):/HH|H/.test(l)?(c<1&&(c=0,a=!0),e.hours=c,r.range&&(i[o[n]].hours=c)):/mm|m/.test(l)?(c<1&&(c=0,a=!0),e.minutes=c,r.range&&(i[o[n]].minutes=c)):/ss|s/.test(l)&&(c<1&&(c=0,a=!0),e.seconds=c,r.range&&(i[o[n]].seconds=c))}),c(e)};return\"limit\"===e?(c(o),i):(l=l||r.value,\"string\"==typeof l&&(l=l.replace(/\\s+/g,\" \").replace(/^\\s|\\s$/g,\"\")),i.startState&&!i.endState&&(delete i.startState,i.endState=!0),\"string\"==typeof l&&l?i.EXP_IF.test(l)?r.range?(l=l.split(\" \"+r.range+\" \"),i.startDate=i.startDate||i.systemDate(),i.endDate=i.endDate||i.systemDate(),r.dateTime=w.extend({},i.startDate),w.each([i.startDate,i.endDate],function(e,t){m(t,l[e],e)})):m(o,l):(i.hint(\"日期格式不合法<br>必须遵循下述格式：<br>\"+(r.range?r.format+\" \"+r.range+\" \"+r.format:r.format)+\"<br>已为你重置\"),a=!0):l&&l.constructor===Date?r.dateTime=i.systemDate(l):(r.dateTime=i.systemDate(),delete i.startState,delete i.endState,delete i.startDate,delete i.endDate,delete i.startTime,delete i.endTime),c(o),a&&l&&i.setValue(r.range?i.endDate?i.parse():\"\":i.parse()),e&&e(),i)},T.prototype.mark=function(e,t){var n,a=this,i=a.config;return w.each(i.mark,function(e,a){var i=e.split(\"-\");i[0]!=t[0]&&0!=i[0]||i[1]!=t[1]&&0!=i[1]||i[2]!=t[2]||(n=a||t[2])}),n&&e.html('<span class=\"laydate-day-mark\">'+n+\"</span>\"),a},T.prototype.limit=function(e,t,n,a){var i,r=this,o=r.config,l={},d=o[n>41?\"endDate\":\"dateTime\"],c=w.extend({},d,t||{});return w.each({now:c,min:o.min,max:o.max},function(e,t){l[e]=r.newDate(w.extend({year:t.year,month:t.month,date:t.date},function(){var e={};return w.each(a,function(n,a){e[a]=t[a]}),e}())).getTime()}),i=l.now<l.min||l.now>l.max,e&&e[i?\"addClass\":\"removeClass\"](s),i},T.prototype.calendar=function(e){var t,a,i,r=this,s=r.config,l=e||s.dateTime,c=new Date,m=r.lang(),u=\"date\"!==s.type&&\"datetime\"!==s.type,h=e?1:0,y=w(r.table[h]).find(\"td\"),f=w(r.elemHeader[h][2]).find(\"span\");if(l.year<d[0]&&(l.year=d[0],r.hint(\"最低只能支持到公元\"+d[0]+\"年\")),l.year>d[1]&&(l.year=d[1],r.hint(\"最高只能支持到公元\"+d[1]+\"年\")),r.firstDate||(r.firstDate=w.extend({},l)),c.setFullYear(l.year,l.month,1),t=c.getDay(),a=n.getEndDate(l.month||12,l.year),i=n.getEndDate(l.month+1,l.year),w.each(y,function(e,n){var d=[l.year,l.month],c=0;n=w(n),n.removeAttr(\"class\"),e<t?(c=a-t+e,n.addClass(\"laydate-day-prev\"),d=r.getAsYM(l.year,l.month,\"sub\")):e>=t&&e<i+t?(c=e-t,s.range||c+1===l.date&&n.addClass(o)):(c=e-i-t,n.addClass(\"laydate-day-next\"),d=r.getAsYM(l.year,l.month)),d[1]++,d[2]=c+1,n.attr(\"lay-ymd\",d.join(\"-\")).html(d[2]),r.mark(n,d).limit(n,{year:d[0],month:d[1]-1,date:d[2]},e)}),w(f[0]).attr(\"lay-ym\",l.year+\"-\"+(l.month+1)),w(f[1]).attr(\"lay-ym\",l.year+\"-\"+(l.month+1)),\"cn\"===s.lang?(w(f[0]).attr(\"lay-type\",\"year\").html(l.year+\"年\"),w(f[1]).attr(\"lay-type\",\"month\").html(l.month+1+\"月\")):(w(f[0]).attr(\"lay-type\",\"month\").html(m.month[l.month]),w(f[1]).attr(\"lay-type\",\"year\").html(l.year)),u&&(s.range&&(e?r.endDate=r.endDate||{year:l.year+(\"year\"===s.type?1:0),month:l.month+(\"month\"===s.type?0:-1)}:r.startDate=r.startDate||{year:l.year,month:l.month},e&&(r.listYM=[[r.startDate.year,r.startDate.month+1],[r.endDate.year,r.endDate.month+1]],r.list(s.type,0).list(s.type,1),\"time\"===s.type?r.setBtnStatus(\"时间\",w.extend({},r.systemDate(),r.startTime),w.extend({},r.systemDate(),r.endTime)):r.setBtnStatus(!0))),s.range||(r.listYM=[[l.year,l.month+1]],r.list(s.type,0))),s.range&&!e){var p=r.getAsYM(l.year,l.month);r.calendar(w.extend({},l,{year:p[0],month:p[1]}))}return s.range||r.limit(w(r.footer).find(g),null,0,[\"hours\",\"minutes\",\"seconds\"]),s.range&&e&&!u&&r.stampRange(),r},T.prototype.list=function(e,t){var n=this,a=n.config,i=a.dateTime,r=n.lang(),l=a.range&&\"date\"!==a.type&&\"datetime\"!==a.type,d=w.elem(\"ul\",{\"class\":m+\" \"+{year:\"laydate-year-list\",month:\"laydate-month-list\",time:\"laydate-time-list\"}[e]}),c=n.elemHeader[t],u=w(c[2]).find(\"span\"),h=n.elemCont[t||0],y=w(h).find(\".\"+m)[0],f=\"cn\"===a.lang,p=f?\"年\":\"\",T=n.listYM[t]||{},C=[\"hours\",\"minutes\",\"seconds\"],x=[\"startTime\",\"endTime\"][t];if(T[0]<1&&(T[0]=1),\"year\"===e){var M,b=M=T[0]-7;b<1&&(b=M=1),w.each(new Array(15),function(e){var i=w.elem(\"li\",{\"lay-ym\":M}),r={year:M};M==T[0]&&w(i).addClass(o),i.innerHTML=M+p,d.appendChild(i),M<n.firstDate.year?(r.month=a.min.month,r.date=a.min.date):M>=n.firstDate.year&&(r.month=a.max.month,r.date=a.max.date),n.limit(w(i),r,t),M++}),w(u[f?0:1]).attr(\"lay-ym\",M-8+\"-\"+T[1]).html(b+p+\" - \"+(M-1+p))}else if(\"month\"===e)w.each(new Array(12),function(e){var i=w.elem(\"li\",{\"lay-ym\":e}),s={year:T[0],month:e};e+1==T[1]&&w(i).addClass(o),i.innerHTML=r.month[e]+(f?\"月\":\"\"),d.appendChild(i),T[0]<n.firstDate.year?s.date=a.min.date:T[0]>=n.firstDate.year&&(s.date=a.max.date),n.limit(w(i),s,t)}),w(u[f?0:1]).attr(\"lay-ym\",T[0]+\"-\"+T[1]).html(T[0]+p);else if(\"time\"===e){var E=function(){w(d).find(\"ol\").each(function(e,a){w(a).find(\"li\").each(function(a,i){n.limit(w(i),[{hours:a},{hours:n[x].hours,minutes:a},{hours:n[x].hours,minutes:n[x].minutes,seconds:a}][e],t,[[\"hours\"],[\"hours\",\"minutes\"],[\"hours\",\"minutes\",\"seconds\"]][e])})}),a.range||n.limit(w(n.footer).find(g),n[x],0,[\"hours\",\"minutes\",\"seconds\"])};a.range?n[x]||(n[x]={hours:0,minutes:0,seconds:0}):n[x]=i,w.each([24,60,60],function(e,t){var a=w.elem(\"li\"),i=[\"<p>\"+r.time[e]+\"</p><ol>\"];w.each(new Array(t),function(t){i.push(\"<li\"+(n[x][C[e]]===t?' class=\"'+o+'\"':\"\")+\">\"+w.digit(t,2)+\"</li>\")}),a.innerHTML=i.join(\"\")+\"</ol>\",d.appendChild(a)}),E()}if(y&&h.removeChild(y),h.appendChild(d),\"year\"===e||\"month\"===e)w(n.elemMain[t]).addClass(\"laydate-ym-show\"),w(d).find(\"li\").on(\"click\",function(){var r=0|w(this).attr(\"lay-ym\");if(!w(this).hasClass(s)){if(0===t)i[e]=r,l&&(n.startDate[e]=r),n.limit(w(n.footer).find(g),null,0);else if(l)n.endDate[e]=r;else{var c=\"year\"===e?n.getAsYM(r,T[1]-1,\"sub\"):n.getAsYM(T[0],r,\"sub\");w.extend(i,{year:c[0],month:c[1]})}\"year\"===a.type||\"month\"===a.type?(w(d).find(\".\"+o).removeClass(o),w(this).addClass(o),\"month\"===a.type&&\"year\"===e&&(n.listYM[t][0]=r,l&&(n[[\"startDate\",\"endDate\"][t]].year=r),n.list(\"month\",t))):(n.checkDate(\"limit\").calendar(),n.closeList()),n.setBtnStatus(),a.range||n.done(null,\"change\"),w(n.footer).find(D).removeClass(s)}});else{var S=w.elem(\"span\",{\"class\":v}),k=function(){w(d).find(\"ol\").each(function(e){var t=this,a=w(t).find(\"li\");t.scrollTop=30*(n[x][C[e]]-2),t.scrollTop<=0&&a.each(function(e,n){if(!w(this).hasClass(s))return t.scrollTop=30*(e-2),!0})})},H=w(c[2]).find(\".\"+v);k(),S.innerHTML=a.range?[r.startTime,r.endTime][t]:r.timeTips,w(n.elemMain[t]).addClass(\"laydate-time-show\"),H[0]&&H.remove(),c[2].appendChild(S),w(d).find(\"ol\").each(function(e){var t=this;w(t).find(\"li\").on(\"click\",function(){var r=0|this.innerHTML;w(this).hasClass(s)||(a.range?n[x][C[e]]=r:i[C[e]]=r,w(t).find(\".\"+o).removeClass(o),w(this).addClass(o),E(),k(),(n.endDate||\"time\"===a.type)&&n.done(null,\"change\"),n.setBtnStatus())})})}return n},T.prototype.listYM=[],T.prototype.closeList=function(){var e=this;e.config;w.each(e.elemCont,function(t,n){w(this).find(\".\"+m).remove(),w(e.elemMain[t]).removeClass(\"laydate-ym-show laydate-time-show\")}),w(e.elem).find(\".\"+v).remove()},T.prototype.setBtnStatus=function(e,t,n){var a,i=this,r=i.config,o=w(i.footer).find(g),d=r.range&&\"date\"!==r.type&&\"time\"!==r.type;d&&(t=t||i.startDate,n=n||i.endDate,a=i.newDate(t).getTime()>i.newDate(n).getTime(),i.limit(null,t)||i.limit(null,n)?o.addClass(s):o[a?\"addClass\":\"removeClass\"](s),e&&a&&i.hint(\"string\"==typeof e?l.replace(/日期/g,e):l))},T.prototype.parse=function(e,t){var n=this,a=n.config,i=t||(e?w.extend({},n.endDate,n.endTime):a.range?w.extend({},n.startDate,n.startTime):a.dateTime),r=n.format.concat();return w.each(r,function(e,t){/yyyy|y/.test(t)?r[e]=w.digit(i.year,t.length):/MM|M/.test(t)?r[e]=w.digit(i.month+1,t.length):/dd|d/.test(t)?r[e]=w.digit(i.date,t.length):/HH|H/.test(t)?r[e]=w.digit(i.hours,t.length):/mm|m/.test(t)?r[e]=w.digit(i.minutes,t.length):/ss|s/.test(t)&&(r[e]=w.digit(i.seconds,t.length))}),a.range&&!e?r.join(\"\")+\" \"+a.range+\" \"+n.parse(1):r.join(\"\")},T.prototype.newDate=function(e){return e=e||{},new Date(e.year||1,e.month||0,e.date||1,e.hours||0,e.minutes||0,e.seconds||0)},T.prototype.setValue=function(e){var t=this,n=t.config,a=t.bindElem||n.elem[0],i=t.isInput(a)?\"val\":\"html\";return\"static\"===n.position||w(a)[i](e||\"\"),this},T.prototype.stampRange=function(){var e,t,n=this,a=n.config,i=w(n.elem).find(\"td\");if(a.range&&!n.endDate&&w(n.footer).find(g).addClass(s),n.endDate)return e=n.newDate({year:n.startDate.year,month:n.startDate.month,date:n.startDate.date}).getTime(),t=n.newDate({year:n.endDate.year,month:n.endDate.month,date:n.endDate.date}).getTime(),e>t?n.hint(l):void w.each(i,function(a,i){var r=w(i).attr(\"lay-ymd\").split(\"-\"),s=n.newDate({year:r[0],month:r[1]-1,date:r[2]}).getTime();w(i).removeClass(u+\" \"+o),s!==e&&s!==t||w(i).addClass(w(i).hasClass(y)||w(i).hasClass(f)?u:o),s>e&&s<t&&w(i).addClass(u)})},T.prototype.done=function(e,t){var n=this,a=n.config,i=w.extend({},n.startDate?w.extend(n.startDate,n.startTime):a.dateTime),r=w.extend({},w.extend(n.endDate,n.endTime));return w.each([i,r],function(e,t){\"month\"in t&&w.extend(t,{month:t.month+1})}),e=e||[n.parse(),i,r],\"function\"==typeof a[t||\"done\"]&&a[t||\"done\"].apply(a,e),n},T.prototype.choose=function(e){var t=this,n=t.config,a=n.dateTime,i=w(t.elem).find(\"td\"),r=e.attr(\"lay-ymd\").split(\"-\"),l=function(e){new Date;e&&w.extend(a,r),n.range&&(t.startDate?w.extend(t.startDate,r):t.startDate=w.extend({},r,t.startTime),t.startYMD=r)};if(r={year:0|r[0],month:(0|r[1])-1,date:0|r[2]},!e.hasClass(s))if(n.range){if(w.each([\"startTime\",\"endTime\"],function(e,n){t[n]=t[n]||{hours:0,minutes:0,seconds:0}}),t.endState)l(),delete t.endState,delete t.endDate,t.startState=!0,i.removeClass(o+\" \"+u),e.addClass(o);else if(t.startState){if(e.addClass(o),t.endDate?w.extend(t.endDate,r):t.endDate=w.extend({},r,t.endTime),t.newDate(r).getTime()<t.newDate(t.startYMD).getTime()){var d=w.extend({},t.endDate,{hours:t.startDate.hours,minutes:t.startDate.minutes,seconds:t.startDate.seconds});w.extend(t.endDate,t.startDate,{hours:t.endDate.hours,minutes:t.endDate.minutes,seconds:t.endDate.seconds}),t.startDate=d}n.showBottom||t.done(),t.stampRange(),t.endState=!0,t.done(null,\"change\")}else e.addClass(o),l(),t.startState=!0;w(t.footer).find(g)[t.endDate?\"removeClass\":\"addClass\"](s)}else\"static\"===n.position?(l(!0),t.calendar().done().done(null,\"change\")):\"date\"===n.type?(l(!0),t.setValue(t.parse()).remove().done()):\"datetime\"===n.type&&(l(!0),t.calendar().done(null,\"change\"))},T.prototype.tool=function(e,t){var n=this,a=n.config,i=a.dateTime,r=\"static\"===a.position,o={datetime:function(){w(e).hasClass(s)||(n.list(\"time\",0),a.range&&n.list(\"time\",1),w(e).attr(\"lay-type\",\"date\").html(n.lang().dateTips))},date:function(){n.closeList(),w(e).attr(\"lay-type\",\"datetime\").html(n.lang().timeTips)},clear:function(){n.setValue(\"\").remove(),r&&(w.extend(i,n.firstDate),n.calendar()),a.range&&(delete n.startState,delete n.endState,delete n.endDate,delete n.startTime,delete n.endTime),n.done([\"\",{},{}])},now:function(){var e=new Date;w.extend(i,n.systemDate(),{hours:e.getHours(),minutes:e.getMinutes(),seconds:e.getSeconds()}),n.setValue(n.parse()).remove(),r&&n.calendar(),n.done()},confirm:function(){if(a.range){if(!n.endDate)return n.hint(\"请先选择日期范围\");if(w(e).hasClass(s))return n.hint(\"time\"===a.type?l.replace(/日期/g,\"时间\"):l)}else if(w(e).hasClass(s))return n.hint(\"不在有效日期或时间范围内\");n.done(),n.setValue(n.parse()).remove()}};o[t]&&o[t]()},T.prototype.change=function(e){var t=this,n=t.config,a=n.dateTime,i=n.range&&(\"year\"===n.type||\"month\"===n.type),r=t.elemCont[e||0],o=t.listYM[e],s=function(s){var l=[\"startDate\",\"endDate\"][e],d=w(r).find(\".laydate-year-list\")[0],c=w(r).find(\".laydate-month-list\")[0];return d&&(o[0]=s?o[0]-15:o[0]+15,t.list(\"year\",e)),c&&(s?o[0]--:o[0]++,t.list(\"month\",e)),(d||c)&&(w.extend(a,{year:o[0]}),i&&(t[l].year=o[0]),n.range||t.done(null,\"change\"),t.setBtnStatus(),n.range||t.limit(w(t.footer).find(g),{year:o[0]})),d||c};return{prevYear:function(){s(\"sub\")||(a.year--,t.checkDate(\"limit\").calendar(),n.range||t.done(null,\"change\"))},prevMonth:function(){var e=t.getAsYM(a.year,a.month,\"sub\");w.extend(a,{year:e[0],month:e[1]}),t.checkDate(\"limit\").calendar(),n.range||t.done(null,\"change\")},nextMonth:function(){var e=t.getAsYM(a.year,a.month);w.extend(a,{year:e[0],month:e[1]}),t.checkDate(\"limit\").calendar(),n.range||t.done(null,\"change\")},nextYear:function(){s()||(a.year++,t.checkDate(\"limit\").calendar(),n.range||t.done(null,\"change\"))}}},T.prototype.changeEvent=function(){var e=this;e.config;w(e.elem).on(\"click\",function(e){w.stope(e)}),w.each(e.elemHeader,function(t,n){w(n[0]).on(\"click\",function(n){e.change(t).prevYear()}),w(n[1]).on(\"click\",function(n){e.change(t).prevMonth()}),w(n[2]).find(\"span\").on(\"click\",function(n){var a=w(this),i=a.attr(\"lay-ym\"),r=a.attr(\"lay-type\");i&&(i=i.split(\"-\"),e.listYM[t]=[0|i[0],0|i[1]],e.list(r,t),w(e.footer).find(D).addClass(s))}),w(n[3]).on(\"click\",function(n){e.change(t).nextMonth()}),w(n[4]).on(\"click\",function(n){e.change(t).nextYear()})}),w.each(e.table,function(t,n){var a=w(n).find(\"td\");a.on(\"click\",function(){e.choose(w(this))})}),w(e.footer).find(\"span\").on(\"click\",function(){var t=w(this).attr(\"lay-type\");e.tool(this,t)})},T.prototype.isInput=function(e){return/input|textarea/.test(e.tagName.toLocaleLowerCase())},T.prototype.events=function(){var e=this,t=e.config,n=function(n,a){n.on(t.trigger,function(){a&&(e.bindElem=this),e.render()})};t.elem[0]&&!t.elem[0].eventHandler&&(n(t.elem,\"bind\"),n(t.eventElem),w(document).on(\"click\",function(n){n.target!==t.elem[0]&&n.target!==t.eventElem[0]&&n.target!==w(t.closeStop)[0]&&e.remove()}).on(\"keydown\",function(t){13===t.keyCode&&w(\"#\"+e.elemID)[0]&&e.elemID===T.thisElem&&(t.preventDefault(),w(e.footer).find(g)[0].click())}),w(window).on(\"resize\",function(){return!(!e.elem||!w(r)[0])&&void e.position()}),t.elem[0].eventHandler=!0)},n.render=function(e){var t=new T(e);return a.call(t)},n.getEndDate=function(e,t){var n=new Date;return n.setFullYear(t||n.getFullYear(),e||n.getMonth()+1,1),new Date(n.getTime()-864e5).getDate()},window.lay=window.lay||w,e?(n.ready(),layui.define(function(e){n.path=layui.cache.dir,e(i,n)})):\"function\"==typeof define&&define.amd?define(function(){return n}):function(){n.ready(),window.laydate=n}()}();!function(e,t){\"object\"==typeof module&&\"object\"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error(\"jQuery requires a window with a document\");return t(e)}:t(e)}(\"undefined\"!=typeof window?window:this,function(e,t){function n(e){var t=!!e&&\"length\"in e&&e.length,n=pe.type(e);return\"function\"!==n&&!pe.isWindow(e)&&(\"array\"===n||0===t||\"number\"==typeof t&&t>0&&t-1 in e)}function r(e,t,n){if(pe.isFunction(t))return pe.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return pe.grep(e,function(e){return e===t!==n});if(\"string\"==typeof t){if(Ce.test(t))return pe.filter(t,e,n);t=pe.filter(t,e)}return pe.grep(e,function(e){return pe.inArray(e,t)>-1!==n})}function i(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}function o(e){var t={};return pe.each(e.match(De)||[],function(e,n){t[n]=!0}),t}function a(){re.addEventListener?(re.removeEventListener(\"DOMContentLoaded\",s),e.removeEventListener(\"load\",s)):(re.detachEvent(\"onreadystatechange\",s),e.detachEvent(\"onload\",s))}function s(){(re.addEventListener||\"load\"===e.event.type||\"complete\"===re.readyState)&&(a(),pe.ready())}function u(e,t,n){if(void 0===n&&1===e.nodeType){var r=\"data-\"+t.replace(_e,\"-$1\").toLowerCase();if(n=e.getAttribute(r),\"string\"==typeof n){try{n=\"true\"===n||\"false\"!==n&&(\"null\"===n?null:+n+\"\"===n?+n:qe.test(n)?pe.parseJSON(n):n)}catch(i){}pe.data(e,t,n)}else n=void 0}return n}function l(e){var t;for(t in e)if((\"data\"!==t||!pe.isEmptyObject(e[t]))&&\"toJSON\"!==t)return!1;return!0}function c(e,t,n,r){if(He(e)){var i,o,a=pe.expando,s=e.nodeType,u=s?pe.cache:e,l=s?e[a]:e[a]&&a;if(l&&u[l]&&(r||u[l].data)||void 0!==n||\"string\"!=typeof t)return l||(l=s?e[a]=ne.pop()||pe.guid++:a),u[l]||(u[l]=s?{}:{toJSON:pe.noop}),\"object\"!=typeof t&&\"function\"!=typeof t||(r?u[l]=pe.extend(u[l],t):u[l].data=pe.extend(u[l].data,t)),o=u[l],r||(o.data||(o.data={}),o=o.data),void 0!==n&&(o[pe.camelCase(t)]=n),\"string\"==typeof t?(i=o[t],null==i&&(i=o[pe.camelCase(t)])):i=o,i}}function f(e,t,n){if(He(e)){var r,i,o=e.nodeType,a=o?pe.cache:e,s=o?e[pe.expando]:pe.expando;if(a[s]){if(t&&(r=n?a[s]:a[s].data)){pe.isArray(t)?t=t.concat(pe.map(t,pe.camelCase)):t in r?t=[t]:(t=pe.camelCase(t),t=t in r?[t]:t.split(\" \")),i=t.length;for(;i--;)delete r[t[i]];if(n?!l(r):!pe.isEmptyObject(r))return}(n||(delete a[s].data,l(a[s])))&&(o?pe.cleanData([e],!0):fe.deleteExpando||a!=a.window?delete a[s]:a[s]=void 0)}}}function d(e,t,n,r){var i,o=1,a=20,s=r?function(){return r.cur()}:function(){return pe.css(e,t,\"\")},u=s(),l=n&&n[3]||(pe.cssNumber[t]?\"\":\"px\"),c=(pe.cssNumber[t]||\"px\"!==l&&+u)&&Me.exec(pe.css(e,t));if(c&&c[3]!==l){l=l||c[3],n=n||[],c=+u||1;do o=o||\".5\",c/=o,pe.style(e,t,c+l);while(o!==(o=s()/u)&&1!==o&&--a)}return n&&(c=+c||+u||0,i=n[1]?c+(n[1]+1)*n[2]:+n[2],r&&(r.unit=l,r.start=c,r.end=i)),i}function p(e){var t=ze.split(\"|\"),n=e.createDocumentFragment();if(n.createElement)for(;t.length;)n.createElement(t.pop());return n}function h(e,t){var n,r,i=0,o=\"undefined\"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||\"*\"):\"undefined\"!=typeof e.querySelectorAll?e.querySelectorAll(t||\"*\"):void 0;if(!o)for(o=[],n=e.childNodes||e;null!=(r=n[i]);i++)!t||pe.nodeName(r,t)?o.push(r):pe.merge(o,h(r,t));return void 0===t||t&&pe.nodeName(e,t)?pe.merge([e],o):o}function g(e,t){for(var n,r=0;null!=(n=e[r]);r++)pe._data(n,\"globalEval\",!t||pe._data(t[r],\"globalEval\"))}function m(e){Be.test(e.type)&&(e.defaultChecked=e.checked)}function y(e,t,n,r,i){for(var o,a,s,u,l,c,f,d=e.length,y=p(t),v=[],x=0;x<d;x++)if(a=e[x],a||0===a)if(\"object\"===pe.type(a))pe.merge(v,a.nodeType?[a]:a);else if(Ue.test(a)){for(u=u||y.appendChild(t.createElement(\"div\")),l=(We.exec(a)||[\"\",\"\"])[1].toLowerCase(),f=Xe[l]||Xe._default,u.innerHTML=f[1]+pe.htmlPrefilter(a)+f[2],o=f[0];o--;)u=u.lastChild;if(!fe.leadingWhitespace&&$e.test(a)&&v.push(t.createTextNode($e.exec(a)[0])),!fe.tbody)for(a=\"table\"!==l||Ve.test(a)?\"<table>\"!==f[1]||Ve.test(a)?0:u:u.firstChild,o=a&&a.childNodes.length;o--;)pe.nodeName(c=a.childNodes[o],\"tbody\")&&!c.childNodes.length&&a.removeChild(c);for(pe.merge(v,u.childNodes),u.textContent=\"\";u.firstChild;)u.removeChild(u.firstChild);u=y.lastChild}else v.push(t.createTextNode(a));for(u&&y.removeChild(u),fe.appendChecked||pe.grep(h(v,\"input\"),m),x=0;a=v[x++];)if(r&&pe.inArray(a,r)>-1)i&&i.push(a);else if(s=pe.contains(a.ownerDocument,a),u=h(y.appendChild(a),\"script\"),s&&g(u),n)for(o=0;a=u[o++];)Ie.test(a.type||\"\")&&n.push(a);return u=null,y}function v(){return!0}function x(){return!1}function b(){try{return re.activeElement}catch(e){}}function w(e,t,n,r,i,o){var a,s;if(\"object\"==typeof t){\"string\"!=typeof n&&(r=r||n,n=void 0);for(s in t)w(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&(\"string\"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),i===!1)i=x;else if(!i)return e;return 1===o&&(a=i,i=function(e){return pe().off(e),a.apply(this,arguments)},i.guid=a.guid||(a.guid=pe.guid++)),e.each(function(){pe.event.add(this,t,i,r,n)})}function T(e,t){return pe.nodeName(e,\"table\")&&pe.nodeName(11!==t.nodeType?t:t.firstChild,\"tr\")?e.getElementsByTagName(\"tbody\")[0]||e.appendChild(e.ownerDocument.createElement(\"tbody\")):e}function C(e){return e.type=(null!==pe.find.attr(e,\"type\"))+\"/\"+e.type,e}function E(e){var t=it.exec(e.type);return t?e.type=t[1]:e.removeAttribute(\"type\"),e}function N(e,t){if(1===t.nodeType&&pe.hasData(e)){var n,r,i,o=pe._data(e),a=pe._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;r<i;r++)pe.event.add(t,n,s[n][r])}a.data&&(a.data=pe.extend({},a.data))}}function k(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!fe.noCloneEvent&&t[pe.expando]){i=pe._data(t);for(r in i.events)pe.removeEvent(t,r,i.handle);t.removeAttribute(pe.expando)}\"script\"===n&&t.text!==e.text?(C(t).text=e.text,E(t)):\"object\"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),fe.html5Clone&&e.innerHTML&&!pe.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):\"input\"===n&&Be.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)}}function S(e,t,n,r){t=oe.apply([],t);var i,o,a,s,u,l,c=0,f=e.length,d=f-1,p=t[0],g=pe.isFunction(p);if(g||f>1&&\"string\"==typeof p&&!fe.checkClone&&rt.test(p))return e.each(function(i){var o=e.eq(i);g&&(t[0]=p.call(this,i,o.html())),S(o,t,n,r)});if(f&&(l=y(t,e[0].ownerDocument,!1,e,r),i=l.firstChild,1===l.childNodes.length&&(l=i),i||r)){for(s=pe.map(h(l,\"script\"),C),a=s.length;c<f;c++)o=l,c!==d&&(o=pe.clone(o,!0,!0),a&&pe.merge(s,h(o,\"script\"))),n.call(e[c],o,c);if(a)for(u=s[s.length-1].ownerDocument,pe.map(s,E),c=0;c<a;c++)o=s[c],Ie.test(o.type||\"\")&&!pe._data(o,\"globalEval\")&&pe.contains(u,o)&&(o.src?pe._evalUrl&&pe._evalUrl(o.src):pe.globalEval((o.text||o.textContent||o.innerHTML||\"\").replace(ot,\"\")));l=i=null}return e}function A(e,t,n){for(var r,i=t?pe.filter(t,e):e,o=0;null!=(r=i[o]);o++)n||1!==r.nodeType||pe.cleanData(h(r)),r.parentNode&&(n&&pe.contains(r.ownerDocument,r)&&g(h(r,\"script\")),r.parentNode.removeChild(r));return e}function D(e,t){var n=pe(t.createElement(e)).appendTo(t.body),r=pe.css(n[0],\"display\");return n.detach(),r}function j(e){var t=re,n=lt[e];return n||(n=D(e,t),\"none\"!==n&&n||(ut=(ut||pe(\"<iframe frameborder='0' width='0' height='0'/>\")).appendTo(t.documentElement),t=(ut[0].contentWindow||ut[0].contentDocument).document,t.write(),t.close(),n=D(e,t),ut.detach()),lt[e]=n),n}function L(e,t){return{get:function(){return e()?void delete this.get:(this.get=t).apply(this,arguments)}}}function H(e){if(e in Et)return e;for(var t=e.charAt(0).toUpperCase()+e.slice(1),n=Ct.length;n--;)if(e=Ct[n]+t,e in Et)return e}function q(e,t){for(var n,r,i,o=[],a=0,s=e.length;a<s;a++)r=e[a],r.style&&(o[a]=pe._data(r,\"olddisplay\"),n=r.style.display,t?(o[a]||\"none\"!==n||(r.style.display=\"\"),\"\"===r.style.display&&Re(r)&&(o[a]=pe._data(r,\"olddisplay\",j(r.nodeName)))):(i=Re(r),(n&&\"none\"!==n||!i)&&pe._data(r,\"olddisplay\",i?n:pe.css(r,\"display\"))));for(a=0;a<s;a++)r=e[a],r.style&&(t&&\"none\"!==r.style.display&&\"\"!==r.style.display||(r.style.display=t?o[a]||\"\":\"none\"));return e}function _(e,t,n){var r=bt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||\"px\"):t}function F(e,t,n,r,i){for(var o=n===(r?\"border\":\"content\")?4:\"width\"===t?1:0,a=0;o<4;o+=2)\"margin\"===n&&(a+=pe.css(e,n+Oe[o],!0,i)),r?(\"content\"===n&&(a-=pe.css(e,\"padding\"+Oe[o],!0,i)),\"margin\"!==n&&(a-=pe.css(e,\"border\"+Oe[o]+\"Width\",!0,i))):(a+=pe.css(e,\"padding\"+Oe[o],!0,i),\"padding\"!==n&&(a+=pe.css(e,\"border\"+Oe[o]+\"Width\",!0,i)));return a}function M(t,n,r){var i=!0,o=\"width\"===n?t.offsetWidth:t.offsetHeight,a=ht(t),s=fe.boxSizing&&\"border-box\"===pe.css(t,\"boxSizing\",!1,a);if(re.msFullscreenElement&&e.top!==e&&t.getClientRects().length&&(o=Math.round(100*t.getBoundingClientRect()[n])),o<=0||null==o){if(o=gt(t,n,a),(o<0||null==o)&&(o=t.style[n]),ft.test(o))return o;i=s&&(fe.boxSizingReliable()||o===t.style[n]),o=parseFloat(o)||0}return o+F(t,n,r||(s?\"border\":\"content\"),i,a)+\"px\"}function O(e,t,n,r,i){return new O.prototype.init(e,t,n,r,i)}function R(){return e.setTimeout(function(){Nt=void 0}),Nt=pe.now()}function P(e,t){var n,r={height:e},i=0;for(t=t?1:0;i<4;i+=2-t)n=Oe[i],r[\"margin\"+n]=r[\"padding\"+n]=e;return t&&(r.opacity=r.width=e),r}function B(e,t,n){for(var r,i=($.tweeners[t]||[]).concat($.tweeners[\"*\"]),o=0,a=i.length;o<a;o++)if(r=i[o].call(n,t,e))return r}function W(e,t,n){var r,i,o,a,s,u,l,c,f=this,d={},p=e.style,h=e.nodeType&&Re(e),g=pe._data(e,\"fxshow\");n.queue||(s=pe._queueHooks(e,\"fx\"),null==s.unqueued&&(s.unqueued=0,u=s.empty.fire,s.empty.fire=function(){s.unqueued||u()}),s.unqueued++,f.always(function(){f.always(function(){s.unqueued--,pe.queue(e,\"fx\").length||s.empty.fire()})})),1===e.nodeType&&(\"height\"in t||\"width\"in t)&&(n.overflow=[p.overflow,p.overflowX,p.overflowY],l=pe.css(e,\"display\"),c=\"none\"===l?pe._data(e,\"olddisplay\")||j(e.nodeName):l,\"inline\"===c&&\"none\"===pe.css(e,\"float\")&&(fe.inlineBlockNeedsLayout&&\"inline\"!==j(e.nodeName)?p.zoom=1:p.display=\"inline-block\")),n.overflow&&(p.overflow=\"hidden\",fe.shrinkWrapBlocks()||f.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],St.exec(i)){if(delete t[r],o=o||\"toggle\"===i,i===(h?\"hide\":\"show\")){if(\"show\"!==i||!g||void 0===g[r])continue;h=!0}d[r]=g&&g[r]||pe.style(e,r)}else l=void 0;if(pe.isEmptyObject(d))\"inline\"===(\"none\"===l?j(e.nodeName):l)&&(p.display=l);else{g?\"hidden\"in g&&(h=g.hidden):g=pe._data(e,\"fxshow\",{}),o&&(g.hidden=!h),h?pe(e).show():f.done(function(){pe(e).hide()}),f.done(function(){var t;pe._removeData(e,\"fxshow\");for(t in d)pe.style(e,t,d[t])});for(r in d)a=B(h?g[r]:0,r,f),r in g||(g[r]=a.start,h&&(a.end=a.start,a.start=\"width\"===r||\"height\"===r?1:0))}}function I(e,t){var n,r,i,o,a;for(n in e)if(r=pe.camelCase(n),i=t[r],o=e[n],pe.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),a=pe.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}function $(e,t,n){var r,i,o=0,a=$.prefilters.length,s=pe.Deferred().always(function(){delete u.elem}),u=function(){if(i)return!1;for(var t=Nt||R(),n=Math.max(0,l.startTime+l.duration-t),r=n/l.duration||0,o=1-r,a=0,u=l.tweens.length;a<u;a++)l.tweens[a].run(o);return s.notifyWith(e,[l,o,n]),o<1&&u?n:(s.resolveWith(e,[l]),!1)},l=s.promise({elem:e,props:pe.extend({},t),opts:pe.extend(!0,{specialEasing:{},easing:pe.easing._default},n),originalProperties:t,originalOptions:n,startTime:Nt||R(),duration:n.duration,tweens:[],createTween:function(t,n){var r=pe.Tween(e,l.opts,t,n,l.opts.specialEasing[t]||l.opts.easing);return l.tweens.push(r),r},stop:function(t){var n=0,r=t?l.tweens.length:0;if(i)return this;for(i=!0;n<r;n++)l.tweens[n].run(1);return t?(s.notifyWith(e,[l,1,0]),s.resolveWith(e,[l,t])):s.rejectWith(e,[l,t]),this}}),c=l.props;for(I(c,l.opts.specialEasing);o<a;o++)if(r=$.prefilters[o].call(l,e,c,l.opts))return pe.isFunction(r.stop)&&(pe._queueHooks(l.elem,l.opts.queue).stop=pe.proxy(r.stop,r)),r;return pe.map(c,B,l),pe.isFunction(l.opts.start)&&l.opts.start.call(e,l),pe.fx.timer(pe.extend(u,{elem:e,anim:l,queue:l.opts.queue})),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always)}function z(e){return pe.attr(e,\"class\")||\"\"}function X(e){return function(t,n){\"string\"!=typeof t&&(n=t,t=\"*\");var r,i=0,o=t.toLowerCase().match(De)||[];if(pe.isFunction(n))for(;r=o[i++];)\"+\"===r.charAt(0)?(r=r.slice(1)||\"*\",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function U(e,t,n,r){function i(s){var u;return o[s]=!0,pe.each(e[s]||[],function(e,s){var l=s(t,n,r);return\"string\"!=typeof l||a||o[l]?a?!(u=l):void 0:(t.dataTypes.unshift(l),i(l),!1)}),u}var o={},a=e===Qt;return i(t.dataTypes[0])||!o[\"*\"]&&i(\"*\")}function V(e,t){var n,r,i=pe.ajaxSettings.flatOptions||{};for(r in t)void 0!==t[r]&&((i[r]?e:n||(n={}))[r]=t[r]);return n&&pe.extend(!0,e,n),e}function Y(e,t,n){for(var r,i,o,a,s=e.contents,u=e.dataTypes;\"*\"===u[0];)u.shift(),void 0===i&&(i=e.mimeType||t.getResponseHeader(\"Content-Type\"));if(i)for(a in s)if(s[a]&&s[a].test(i)){u.unshift(a);break}if(u[0]in n)o=u[0];else{for(a in n){if(!u[0]||e.converters[a+\" \"+u[0]]){o=a;break}r||(r=a)}o=o||r}if(o)return o!==u[0]&&u.unshift(o),n[o]}function J(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];for(o=c.shift();o;)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if(\"*\"===o)o=u;else if(\"*\"!==u&&u!==o){if(a=l[u+\" \"+o]||l[\"* \"+o],!a)for(i in l)if(s=i.split(\" \"),s[1]===o&&(a=l[u+\" \"+s[0]]||l[\"* \"+s[0]])){a===!0?a=l[i]:l[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(f){return{state:\"parsererror\",error:a?f:\"No conversion from \"+u+\" to \"+o}}}return{state:\"success\",data:t}}function G(e){return e.style&&e.style.display||pe.css(e,\"display\")}function K(e){for(;e&&1===e.nodeType;){if(\"none\"===G(e)||\"hidden\"===e.type)return!0;e=e.parentNode}return!1}function Q(e,t,n,r){var i;if(pe.isArray(t))pe.each(t,function(t,i){n||rn.test(e)?r(e,i):Q(e+\"[\"+(\"object\"==typeof i&&null!=i?t:\"\")+\"]\",i,n,r)});else if(n||\"object\"!==pe.type(t))r(e,t);else for(i in t)Q(e+\"[\"+i+\"]\",t[i],n,r)}function Z(){try{return new e.XMLHttpRequest}catch(t){}}function ee(){try{return new e.ActiveXObject(\"Microsoft.XMLHTTP\")}catch(t){}}function te(e){return pe.isWindow(e)?e:9===e.nodeType&&(e.defaultView||e.parentWindow)}var ne=[],re=e.document,ie=ne.slice,oe=ne.concat,ae=ne.push,se=ne.indexOf,ue={},le=ue.toString,ce=ue.hasOwnProperty,fe={},de=\"1.12.3\",pe=function(e,t){return new pe.fn.init(e,t)},he=/^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g,ge=/^-ms-/,me=/-([\\da-z])/gi,ye=function(e,t){return t.toUpperCase()};pe.fn=pe.prototype={jquery:de,constructor:pe,selector:\"\",length:0,toArray:function(){return ie.call(this)},get:function(e){return null!=e?e<0?this[e+this.length]:this[e]:ie.call(this)},pushStack:function(e){var t=pe.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e){return pe.each(this,e)},map:function(e){return this.pushStack(pe.map(this,function(t,n){return e.call(t,n,t)}))},slice:function(){return this.pushStack(ie.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(n>=0&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:ae,sort:ne.sort,splice:ne.splice},pe.extend=pe.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for(\"boolean\"==typeof a&&(l=a,a=arguments[s]||{},s++),\"object\"==typeof a||pe.isFunction(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(i=arguments[s]))for(r in i)e=a[r],n=i[r],a!==n&&(l&&n&&(pe.isPlainObject(n)||(t=pe.isArray(n)))?(t?(t=!1,o=e&&pe.isArray(e)?e:[]):o=e&&pe.isPlainObject(e)?e:{},a[r]=pe.extend(l,o,n)):void 0!==n&&(a[r]=n));return a},pe.extend({expando:\"jQuery\"+(de+Math.random()).replace(/\\D/g,\"\"),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isFunction:function(e){return\"function\"===pe.type(e)},isArray:Array.isArray||function(e){return\"array\"===pe.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){var t=e&&e.toString();return!pe.isArray(e)&&t-parseFloat(t)+1>=0},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},isPlainObject:function(e){var t;if(!e||\"object\"!==pe.type(e)||e.nodeType||pe.isWindow(e))return!1;try{if(e.constructor&&!ce.call(e,\"constructor\")&&!ce.call(e.constructor.prototype,\"isPrototypeOf\"))return!1}catch(n){return!1}if(!fe.ownFirst)for(t in e)return ce.call(e,t);for(t in e);return void 0===t||ce.call(e,t)},type:function(e){return null==e?e+\"\":\"object\"==typeof e||\"function\"==typeof e?ue[le.call(e)]||\"object\":typeof e},globalEval:function(t){t&&pe.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(ge,\"ms-\").replace(me,ye)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t){var r,i=0;if(n(e))for(r=e.length;i<r&&t.call(e[i],i,e[i])!==!1;i++);else for(i in e)if(t.call(e[i],i,e[i])===!1)break;return e},trim:function(e){return null==e?\"\":(e+\"\").replace(he,\"\")},makeArray:function(e,t){var r=t||[];return null!=e&&(n(Object(e))?pe.merge(r,\"string\"==typeof e?[e]:e):ae.call(r,e)),r},inArray:function(e,t,n){var r;if(t){if(se)return se.call(t,e,n);for(r=t.length,n=n?n<0?Math.max(0,r+n):n:0;n<r;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;)e[i++]=t[r++];if(n!==n)for(;void 0!==t[r];)e[i++]=t[r++];return e.length=i,e},grep:function(e,t,n){for(var r,i=[],o=0,a=e.length,s=!n;o<a;o++)r=!t(e[o],o),r!==s&&i.push(e[o]);return i},map:function(e,t,r){var i,o,a=0,s=[];if(n(e))for(i=e.length;a<i;a++)o=t(e[a],a,r),null!=o&&s.push(o);else for(a in e)o=t(e[a],a,r),null!=o&&s.push(o);return oe.apply([],s)},guid:1,proxy:function(e,t){var n,r,i;if(\"string\"==typeof t&&(i=e[t],t=e,e=i),pe.isFunction(e))return n=ie.call(arguments,2),r=function(){return e.apply(t||this,n.concat(ie.call(arguments)))},r.guid=e.guid=e.guid||pe.guid++,r},now:function(){return+new Date},support:fe}),\"function\"==typeof Symbol&&(pe.fn[Symbol.iterator]=ne[Symbol.iterator]),pe.each(\"Boolean Number String Function Array Date RegExp Object Error Symbol\".split(\" \"),function(e,t){ue[\"[object \"+t+\"]\"]=t.toLowerCase()});var ve=function(e){function t(e,t,n,r){var i,o,a,s,u,l,f,p,h=t&&t.ownerDocument,g=t?t.nodeType:9;if(n=n||[],\"string\"!=typeof e||!e||1!==g&&9!==g&&11!==g)return n;if(!r&&((t?t.ownerDocument||t:B)!==H&&L(t),t=t||H,_)){if(11!==g&&(l=ye.exec(e)))if(i=l[1]){if(9===g){if(!(a=t.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(h&&(a=h.getElementById(i))&&R(t,a)&&a.id===i)return n.push(a),n}else{if(l[2])return Q.apply(n,t.getElementsByTagName(e)),n;if((i=l[3])&&w.getElementsByClassName&&t.getElementsByClassName)return Q.apply(n,t.getElementsByClassName(i)),n}if(w.qsa&&!X[e+\" \"]&&(!F||!F.test(e))){if(1!==g)h=t,p=e;else if(\"object\"!==t.nodeName.toLowerCase()){for((s=t.getAttribute(\"id\"))?s=s.replace(xe,\"\\\\$&\"):t.setAttribute(\"id\",s=P),f=N(e),o=f.length,u=de.test(s)?\"#\"+s:\"[id='\"+s+\"']\";o--;)f[o]=u+\" \"+d(f[o]);p=f.join(\",\"),h=ve.test(e)&&c(t.parentNode)||t}if(p)try{return Q.apply(n,h.querySelectorAll(p)),n}catch(m){}finally{s===P&&t.removeAttribute(\"id\")}}}return S(e.replace(se,\"$1\"),t,n,r)}function n(){function e(n,r){return t.push(n+\" \")>T.cacheLength&&delete e[t.shift()],e[n+\" \"]=r}var t=[];return e}function r(e){return e[P]=!0,e}function i(e){var t=H.createElement(\"div\");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function o(e,t){for(var n=e.split(\"|\"),r=n.length;r--;)T.attrHandle[n[r]]=t}function a(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||V)-(~e.sourceIndex||V);if(r)return r;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function s(e){return function(t){var n=t.nodeName.toLowerCase();return\"input\"===n&&t.type===e}}function u(e){return function(t){var n=t.nodeName.toLowerCase();return(\"input\"===n||\"button\"===n)&&t.type===e}}function l(e){return r(function(t){return t=+t,r(function(n,r){for(var i,o=e([],n.length,t),a=o.length;a--;)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}function c(e){return e&&\"undefined\"!=typeof e.getElementsByTagName&&e}function f(){}function d(e){for(var t=0,n=e.length,r=\"\";t<n;t++)r+=e[t].value;return r}function p(e,t,n){var r=t.dir,i=n&&\"parentNode\"===r,o=I++;return t.first?function(t,n,o){for(;t=t[r];)if(1===t.nodeType||i)return e(t,n,o)}:function(t,n,a){var s,u,l,c=[W,o];if(a){for(;t=t[r];)if((1===t.nodeType||i)&&e(t,n,a))return!0}else for(;t=t[r];)if(1===t.nodeType||i){if(l=t[P]||(t[P]={}),u=l[t.uniqueID]||(l[t.uniqueID]={}),(s=u[r])&&s[0]===W&&s[1]===o)return c[2]=s[2];if(u[r]=c,c[2]=e(t,n,a))return!0}}}function h(e){return e.length>1?function(t,n,r){for(var i=e.length;i--;)if(!e[i](t,n,r))return!1;return!0}:e[0]}function g(e,n,r){for(var i=0,o=n.length;i<o;i++)t(e,n[i],r);return r}function m(e,t,n,r,i){for(var o,a=[],s=0,u=e.length,l=null!=t;s<u;s++)(o=e[s])&&(n&&!n(o,r,i)||(a.push(o),l&&t.push(s)));return a}function y(e,t,n,i,o,a){return i&&!i[P]&&(i=y(i)),o&&!o[P]&&(o=y(o,a)),r(function(r,a,s,u){var l,c,f,d=[],p=[],h=a.length,y=r||g(t||\"*\",s.nodeType?[s]:s,[]),v=!e||!r&&t?y:m(y,d,e,s,u),x=n?o||(r?e:h||i)?[]:a:v;if(n&&n(v,x,s,u),i)for(l=m(x,p),i(l,[],s,u),c=l.length;c--;)(f=l[c])&&(x[p[c]]=!(v[p[c]]=f));if(r){if(o||e){if(o){for(l=[],c=x.length;c--;)(f=x[c])&&l.push(v[c]=f);o(null,x=[],l,u)}for(c=x.length;c--;)(f=x[c])&&(l=o?ee(r,f):d[c])>-1&&(r[l]=!(a[l]=f))}}else x=m(x===a?x.splice(h,x.length):x),o?o(null,a,x,u):Q.apply(a,x)})}function v(e){for(var t,n,r,i=e.length,o=T.relative[e[0].type],a=o||T.relative[\" \"],s=o?1:0,u=p(function(e){return e===t},a,!0),l=p(function(e){return ee(t,e)>-1},a,!0),c=[function(e,n,r){var i=!o&&(r||n!==A)||((t=n).nodeType?u(e,n,r):l(e,n,r));return t=null,i}];s<i;s++)if(n=T.relative[e[s].type])c=[p(h(c),n)];else{if(n=T.filter[e[s].type].apply(null,e[s].matches),n[P]){for(r=++s;r<i&&!T.relative[e[r].type];r++);return y(s>1&&h(c),s>1&&d(e.slice(0,s-1).concat({value:\" \"===e[s-2].type?\"*\":\"\"})).replace(se,\"$1\"),n,s<r&&v(e.slice(s,r)),r<i&&v(e=e.slice(r)),r<i&&d(e))}c.push(n)}return h(c)}function x(e,n){var i=n.length>0,o=e.length>0,a=function(r,a,s,u,l){var c,f,d,p=0,h=\"0\",g=r&&[],y=[],v=A,x=r||o&&T.find.TAG(\"*\",l),b=W+=null==v?1:Math.random()||.1,w=x.length;for(l&&(A=a===H||a||l);h!==w&&null!=(c=x[h]);h++){if(o&&c){for(f=0,a||c.ownerDocument===H||(L(c),s=!_);d=e[f++];)if(d(c,a||H,s)){u.push(c);break}l&&(W=b)}i&&((c=!d&&c)&&p--,r&&g.push(c))}if(p+=h,i&&h!==p){for(f=0;d=n[f++];)d(g,y,a,s);if(r){if(p>0)for(;h--;)g[h]||y[h]||(y[h]=G.call(u));y=m(y)}Q.apply(u,y),l&&!r&&y.length>0&&p+n.length>1&&t.uniqueSort(u)}return l&&(W=b,A=v),g};return i?r(a):a}var b,w,T,C,E,N,k,S,A,D,j,L,H,q,_,F,M,O,R,P=\"sizzle\"+1*new Date,B=e.document,W=0,I=0,$=n(),z=n(),X=n(),U=function(e,t){return e===t&&(j=!0),0},V=1<<31,Y={}.hasOwnProperty,J=[],G=J.pop,K=J.push,Q=J.push,Z=J.slice,ee=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},te=\"checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped\",ne=\"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",re=\"(?:\\\\\\\\.|[\\\\w-]|[^\\\\x00-\\\\xa0])+\",ie=\"\\\\[\"+ne+\"*(\"+re+\")(?:\"+ne+\"*([*^$|!~]?=)\"+ne+\"*(?:'((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\"|(\"+re+\"))|)\"+ne+\"*\\\\]\",oe=\":(\"+re+\")(?:\\\\((('((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\")|((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\"+ie+\")*)|.*)\\\\)|)\",ae=new RegExp(ne+\"+\",\"g\"),se=new RegExp(\"^\"+ne+\"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\"+ne+\"+$\",\"g\"),ue=new RegExp(\"^\"+ne+\"*,\"+ne+\"*\"),le=new RegExp(\"^\"+ne+\"*([>+~]|\"+ne+\")\"+ne+\"*\"),ce=new RegExp(\"=\"+ne+\"*([^\\\\]'\\\"]*?)\"+ne+\"*\\\\]\",\"g\"),fe=new RegExp(oe),de=new RegExp(\"^\"+re+\"$\"),pe={ID:new RegExp(\"^#(\"+re+\")\"),CLASS:new RegExp(\"^\\\\.(\"+re+\")\"),TAG:new RegExp(\"^(\"+re+\"|[*])\"),ATTR:new RegExp(\"^\"+ie),PSEUDO:new RegExp(\"^\"+oe),CHILD:new RegExp(\"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\"+ne+\"*(even|odd|(([+-]|)(\\\\d*)n|)\"+ne+\"*(?:([+-]|)\"+ne+\"*(\\\\d+)|))\"+ne+\"*\\\\)|)\",\"i\"),bool:new RegExp(\"^(?:\"+te+\")$\",\"i\"),needsContext:new RegExp(\"^\"+ne+\"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\"+ne+\"*((?:-\\\\d)?\\\\d*)\"+ne+\"*\\\\)|)(?=[^-]|$)\",\"i\")},he=/^(?:input|select|textarea|button)$/i,ge=/^h\\d$/i,me=/^[^{]+\\{\\s*\\[native \\w/,ye=/^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,ve=/[+~]/,xe=/'|\\\\/g,be=new RegExp(\"\\\\\\\\([\\\\da-f]{1,6}\"+ne+\"?|(\"+ne+\")|.)\",\"ig\"),we=function(e,t,n){var r=\"0x\"+t-65536;return r!==r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},Te=function(){L()};try{Q.apply(J=Z.call(B.childNodes),B.childNodes),J[B.childNodes.length].nodeType}catch(Ce){Q={apply:J.length?function(e,t){K.apply(e,Z.call(t))}:function(e,t){for(var n=e.length,r=0;e[n++]=t[r++];);e.length=n-1}}}w=t.support={},E=t.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return!!t&&\"HTML\"!==t.nodeName},L=t.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:B;return r!==H&&9===r.nodeType&&r.documentElement?(H=r,q=H.documentElement,_=!E(H),(n=H.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener(\"unload\",Te,!1):n.attachEvent&&n.attachEvent(\"onunload\",Te)),w.attributes=i(function(e){return e.className=\"i\",!e.getAttribute(\"className\")}),w.getElementsByTagName=i(function(e){return e.appendChild(H.createComment(\"\")),!e.getElementsByTagName(\"*\").length}),w.getElementsByClassName=me.test(H.getElementsByClassName),w.getById=i(function(e){return q.appendChild(e).id=P,!H.getElementsByName||!H.getElementsByName(P).length}),w.getById?(T.find.ID=function(e,t){if(\"undefined\"!=typeof t.getElementById&&_){var n=t.getElementById(e);return n?[n]:[]}},T.filter.ID=function(e){var t=e.replace(be,we);return function(e){return e.getAttribute(\"id\")===t}}):(delete T.find.ID,T.filter.ID=function(e){var t=e.replace(be,we);return function(e){var n=\"undefined\"!=typeof e.getAttributeNode&&e.getAttributeNode(\"id\");return n&&n.value===t}}),T.find.TAG=w.getElementsByTagName?function(e,t){return\"undefined\"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):w.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if(\"*\"===e){for(;n=o[i++];)1===n.nodeType&&r.push(n);return r}return o},T.find.CLASS=w.getElementsByClassName&&function(e,t){if(\"undefined\"!=typeof t.getElementsByClassName&&_)return t.getElementsByClassName(e)},M=[],F=[],(w.qsa=me.test(H.querySelectorAll))&&(i(function(e){q.appendChild(e).innerHTML=\"<a id='\"+P+\"'></a><select id='\"+P+\"-\\r\\\\' msallowcapture=''><option selected=''></option></select>\",e.querySelectorAll(\"[msallowcapture^='']\").length&&F.push(\"[*^$]=\"+ne+\"*(?:''|\\\"\\\")\"),e.querySelectorAll(\"[selected]\").length||F.push(\"\\\\[\"+ne+\"*(?:value|\"+te+\")\"),e.querySelectorAll(\"[id~=\"+P+\"-]\").length||F.push(\"~=\"),e.querySelectorAll(\":checked\").length||F.push(\":checked\"),e.querySelectorAll(\"a#\"+P+\"+*\").length||F.push(\".#.+[+~]\")}),i(function(e){var t=H.createElement(\"input\");t.setAttribute(\"type\",\"hidden\"),e.appendChild(t).setAttribute(\"name\",\"D\"),e.querySelectorAll(\"[name=d]\").length&&F.push(\"name\"+ne+\"*[*^$|!~]?=\"),e.querySelectorAll(\":enabled\").length||F.push(\":enabled\",\":disabled\"),e.querySelectorAll(\"*,:x\"),F.push(\",.*:\")})),(w.matchesSelector=me.test(O=q.matches||q.webkitMatchesSelector||q.mozMatchesSelector||q.oMatchesSelector||q.msMatchesSelector))&&i(function(e){w.disconnectedMatch=O.call(e,\"div\"),O.call(e,\"[s!='']:x\"),M.push(\"!=\",oe)}),F=F.length&&new RegExp(F.join(\"|\")),M=M.length&&new RegExp(M.join(\"|\")),t=me.test(q.compareDocumentPosition),R=t||me.test(q.contains)?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)for(;t=t.parentNode;)if(t===e)return!0;return!1},U=t?function(e,t){if(e===t)return j=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n?n:(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1,1&n||!w.sortDetached&&t.compareDocumentPosition(e)===n?e===H||e.ownerDocument===B&&R(B,e)?-1:t===H||t.ownerDocument===B&&R(B,t)?1:D?ee(D,e)-ee(D,t):0:4&n?-1:1)}:function(e,t){if(e===t)return j=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,s=[e],u=[t];if(!i||!o)return e===H?-1:t===H?1:i?-1:o?1:D?ee(D,e)-ee(D,t):0;if(i===o)return a(e,t);for(n=e;n=n.parentNode;)s.unshift(n);for(n=t;n=n.parentNode;)u.unshift(n);for(;s[r]===u[r];)r++;return r?a(s[r],u[r]):s[r]===B?-1:u[r]===B?1:0},H):H},t.matches=function(e,n){return t(e,null,null,n)},t.matchesSelector=function(e,n){if((e.ownerDocument||e)!==H&&L(e),n=n.replace(ce,\"='$1']\"),w.matchesSelector&&_&&!X[n+\" \"]&&(!M||!M.test(n))&&(!F||!F.test(n)))try{var r=O.call(e,n);if(r||w.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(i){}return t(n,H,null,[e]).length>0},t.contains=function(e,t){return(e.ownerDocument||e)!==H&&L(e),R(e,t)},t.attr=function(e,t){(e.ownerDocument||e)!==H&&L(e);var n=T.attrHandle[t.toLowerCase()],r=n&&Y.call(T.attrHandle,t.toLowerCase())?n(e,t,!_):void 0;return void 0!==r?r:w.attributes||!_?e.getAttribute(t):(r=e.getAttributeNode(t))&&r.specified?r.value:null},t.error=function(e){throw new Error(\"Syntax error, unrecognized expression: \"+e)},t.uniqueSort=function(e){var t,n=[],r=0,i=0;if(j=!w.detectDuplicates,D=!w.sortStable&&e.slice(0),e.sort(U),j){for(;t=e[i++];)t===e[i]&&(r=n.push(i));for(;r--;)e.splice(n[r],1)}return D=null,e},C=t.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+=C(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r++];)n+=C(t);return n},T=t.selectors={cacheLength:50,createPseudo:r,match:pe,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(be,we),e[3]=(e[3]||e[4]||e[5]||\"\").replace(be,we),\"~=\"===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]||t.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]&&t.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return pe.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||\"\":n&&fe.test(n)&&(t=N(n,!0))&&(t=n.indexOf(\")\",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(be,we).toLowerCase();return\"*\"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=$[e+\" \"];return t||(t=new RegExp(\"(^|\"+ne+\")\"+e+\"(\"+ne+\"|$)\"))&&$(e,function(e){return t.test(\"string\"==typeof e.className&&e.className||\"undefined\"!=typeof e.getAttribute&&e.getAttribute(\"class\")||\"\")})},ATTR:function(e,n,r){return function(i){var o=t.attr(i,e);return null==o?\"!=\"===n:!n||(o+=\"\",\"=\"===n?o===r:\"!=\"===n?o!==r:\"^=\"===n?r&&0===o.indexOf(r):\"*=\"===n?r&&o.indexOf(r)>-1:\"$=\"===n?r&&o.slice(-r.length)===r:\"~=\"===n?(\" \"+o.replace(ae,\" \")+\" \").indexOf(r)>-1:\"|=\"===n&&(o===r||o.slice(0,r.length+1)===r+\"-\"))}},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,u){var l,c,f,d,p,h,g=o!==a?\"nextSibling\":\"previousSibling\",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!u&&!s,x=!1;if(m){if(o){for(;g;){for(d=t;d=d[g];)if(s?d.nodeName.toLowerCase()===y:1===d.nodeType)return!1;h=g=\"only\"===e&&!h&&\"nextSibling\"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){for(d=m,f=d[P]||(d[P]={}),c=f[d.uniqueID]||(f[d.uniqueID]={}),\nl=c[e]||[],p=l[0]===W&&l[1],x=p&&l[2],d=p&&m.childNodes[p];d=++p&&d&&d[g]||(x=p=0)||h.pop();)if(1===d.nodeType&&++x&&d===t){c[e]=[W,p,x];break}}else if(v&&(d=t,f=d[P]||(d[P]={}),c=f[d.uniqueID]||(f[d.uniqueID]={}),l=c[e]||[],p=l[0]===W&&l[1],x=p),x===!1)for(;(d=++p&&d&&d[g]||(x=p=0)||h.pop())&&((s?d.nodeName.toLowerCase()!==y:1!==d.nodeType)||!++x||(v&&(f=d[P]||(d[P]={}),c=f[d.uniqueID]||(f[d.uniqueID]={}),c[e]=[W,x]),d!==t)););return x-=i,x===r||x%r===0&&x/r>=0}}},PSEUDO:function(e,n){var i,o=T.pseudos[e]||T.setFilters[e.toLowerCase()]||t.error(\"unsupported pseudo: \"+e);return o[P]?o(n):o.length>1?(i=[e,e,\"\",n],T.setFilters.hasOwnProperty(e.toLowerCase())?r(function(e,t){for(var r,i=o(e,n),a=i.length;a--;)r=ee(e,i[a]),e[r]=!(t[r]=i[a])}):function(e){return o(e,0,i)}):o}},pseudos:{not:r(function(e){var t=[],n=[],i=k(e.replace(se,\"$1\"));return i[P]?r(function(e,t,n,r){for(var o,a=i(e,null,r,[]),s=e.length;s--;)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,r,o){return t[0]=e,i(t,null,o,n),t[0]=null,!n.pop()}}),has:r(function(e){return function(n){return t(e,n).length>0}}),contains:r(function(e){return e=e.replace(be,we),function(t){return(t.textContent||t.innerText||C(t)).indexOf(e)>-1}}),lang:r(function(e){return de.test(e||\"\")||t.error(\"unsupported lang: \"+e),e=e.replace(be,we).toLowerCase(),function(t){var n;do if(n=_?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===q},focus:function(e){return e===H.activeElement&&(!H.hasFocus||H.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.nodeType<6)return!1;return!0},parent:function(e){return!T.pseudos.empty(e)},header:function(e){return ge.test(e.nodeName)},input:function(e){return he.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\"))||\"text\"===t.toLowerCase())},first:l(function(){return[0]}),last:l(function(e,t){return[t-1]}),eq:l(function(e,t,n){return[n<0?n+t:n]}),even:l(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:l(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:l(function(e,t,n){for(var r=n<0?n+t:n;--r>=0;)e.push(r);return e}),gt:l(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}},T.pseudos.nth=T.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})T.pseudos[b]=s(b);for(b in{submit:!0,reset:!0})T.pseudos[b]=u(b);return f.prototype=T.filters=T.pseudos,T.setFilters=new f,N=t.tokenize=function(e,n){var r,i,o,a,s,u,l,c=z[e+\" \"];if(c)return n?0:c.slice(0);for(s=e,u=[],l=T.preFilter;s;){r&&!(i=ue.exec(s))||(i&&(s=s.slice(i[0].length)||s),u.push(o=[])),r=!1,(i=le.exec(s))&&(r=i.shift(),o.push({value:r,type:i[0].replace(se,\" \")}),s=s.slice(r.length));for(a in T.filter)!(i=pe[a].exec(s))||l[a]&&!(i=l[a](i))||(r=i.shift(),o.push({value:r,type:a,matches:i}),s=s.slice(r.length));if(!r)break}return n?s.length:s?t.error(e):z(e,u).slice(0)},k=t.compile=function(e,t){var n,r=[],i=[],o=X[e+\" \"];if(!o){for(t||(t=N(e)),n=t.length;n--;)o=v(t[n]),o[P]?r.push(o):i.push(o);o=X(e,x(i,r)),o.selector=e}return o},S=t.select=function(e,t,n,r){var i,o,a,s,u,l=\"function\"==typeof e&&e,f=!r&&N(e=l.selector||e);if(n=n||[],1===f.length){if(o=f[0]=f[0].slice(0),o.length>2&&\"ID\"===(a=o[0]).type&&w.getById&&9===t.nodeType&&_&&T.relative[o[1].type]){if(t=(T.find.ID(a.matches[0].replace(be,we),t)||[])[0],!t)return n;l&&(t=t.parentNode),e=e.slice(o.shift().value.length)}for(i=pe.needsContext.test(e)?0:o.length;i--&&(a=o[i],!T.relative[s=a.type]);)if((u=T.find[s])&&(r=u(a.matches[0].replace(be,we),ve.test(o[0].type)&&c(t.parentNode)||t))){if(o.splice(i,1),e=r.length&&d(o),!e)return Q.apply(n,r),n;break}}return(l||k(e,f))(r,t,!_,n,!t||ve.test(e)&&c(t.parentNode)||t),n},w.sortStable=P.split(\"\").sort(U).join(\"\")===P,w.detectDuplicates=!!j,L(),w.sortDetached=i(function(e){return 1&e.compareDocumentPosition(H.createElement(\"div\"))}),i(function(e){return e.innerHTML=\"<a href='#'></a>\",\"#\"===e.firstChild.getAttribute(\"href\")})||o(\"type|href|height|width\",function(e,t,n){if(!n)return e.getAttribute(t,\"type\"===t.toLowerCase()?1:2)}),w.attributes&&i(function(e){return e.innerHTML=\"<input/>\",e.firstChild.setAttribute(\"value\",\"\"),\"\"===e.firstChild.getAttribute(\"value\")})||o(\"value\",function(e,t,n){if(!n&&\"input\"===e.nodeName.toLowerCase())return e.defaultValue}),i(function(e){return null==e.getAttribute(\"disabled\")})||o(te,function(e,t,n){var r;if(!n)return e[t]===!0?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),t}(e);pe.find=ve,pe.expr=ve.selectors,pe.expr[\":\"]=pe.expr.pseudos,pe.uniqueSort=pe.unique=ve.uniqueSort,pe.text=ve.getText,pe.isXMLDoc=ve.isXML,pe.contains=ve.contains;var xe=function(e,t,n){for(var r=[],i=void 0!==n;(e=e[t])&&9!==e.nodeType;)if(1===e.nodeType){if(i&&pe(e).is(n))break;r.push(e)}return r},be=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},we=pe.expr.match.needsContext,Te=/^<([\\w-]+)\\s*\\/?>(?:<\\/\\1>|)$/,Ce=/^.[^:#\\[\\.,]*$/;pe.filter=function(e,t,n){var r=t[0];return n&&(e=\":not(\"+e+\")\"),1===t.length&&1===r.nodeType?pe.find.matchesSelector(r,e)?[r]:[]:pe.find.matches(e,pe.grep(t,function(e){return 1===e.nodeType}))},pe.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if(\"string\"!=typeof e)return this.pushStack(pe(e).filter(function(){for(t=0;t<i;t++)if(pe.contains(r[t],this))return!0}));for(t=0;t<i;t++)pe.find(e,r[t],n);return n=this.pushStack(i>1?pe.unique(n):n),n.selector=this.selector?this.selector+\" \"+e:e,n},filter:function(e){return this.pushStack(r(this,e||[],!1))},not:function(e){return this.pushStack(r(this,e||[],!0))},is:function(e){return!!r(this,\"string\"==typeof e&&we.test(e)?pe(e):e||[],!1).length}});var Ee,Ne=/^(?:\\s*(<[\\w\\W]+>)[^>]*|#([\\w-]*))$/,ke=pe.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||Ee,\"string\"==typeof e){if(r=\"<\"===e.charAt(0)&&\">\"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:Ne.exec(e),!r||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof pe?t[0]:t,pe.merge(this,pe.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:re,!0)),Te.test(r[1])&&pe.isPlainObject(t))for(r in t)pe.isFunction(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}if(i=re.getElementById(r[2]),i&&i.parentNode){if(i.id!==r[2])return Ee.find(e);this.length=1,this[0]=i}return this.context=re,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):pe.isFunction(e)?\"undefined\"!=typeof n.ready?n.ready(e):e(pe):(void 0!==e.selector&&(this.selector=e.selector,this.context=e.context),pe.makeArray(e,this))};ke.prototype=pe.fn,Ee=pe(re);var Se=/^(?:parents|prev(?:Until|All))/,Ae={children:!0,contents:!0,next:!0,prev:!0};pe.fn.extend({has:function(e){var t,n=pe(e,this),r=n.length;return this.filter(function(){for(t=0;t<r;t++)if(pe.contains(this,n[t]))return!0})},closest:function(e,t){for(var n,r=0,i=this.length,o=[],a=we.test(e)||\"string\"!=typeof e?pe(e,t||this.context):0;r<i;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(n.nodeType<11&&(a?a.index(n)>-1:1===n.nodeType&&pe.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(o.length>1?pe.uniqueSort(o):o)},index:function(e){return e?\"string\"==typeof e?pe.inArray(this[0],pe(e)):pe.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(pe.uniqueSort(pe.merge(this.get(),pe(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),pe.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return xe(e,\"parentNode\")},parentsUntil:function(e,t,n){return xe(e,\"parentNode\",n)},next:function(e){return i(e,\"nextSibling\")},prev:function(e){return i(e,\"previousSibling\")},nextAll:function(e){return xe(e,\"nextSibling\")},prevAll:function(e){return xe(e,\"previousSibling\")},nextUntil:function(e,t,n){return xe(e,\"nextSibling\",n)},prevUntil:function(e,t,n){return xe(e,\"previousSibling\",n)},siblings:function(e){return be((e.parentNode||{}).firstChild,e)},children:function(e){return be(e.firstChild)},contents:function(e){return pe.nodeName(e,\"iframe\")?e.contentDocument||e.contentWindow.document:pe.merge([],e.childNodes)}},function(e,t){pe.fn[e]=function(n,r){var i=pe.map(this,t,n);return\"Until\"!==e.slice(-5)&&(r=n),r&&\"string\"==typeof r&&(i=pe.filter(r,i)),this.length>1&&(Ae[e]||(i=pe.uniqueSort(i)),Se.test(e)&&(i=i.reverse())),this.pushStack(i)}});var De=/\\S+/g;pe.Callbacks=function(e){e=\"string\"==typeof e?o(e):pe.extend({},e);var t,n,r,i,a=[],s=[],u=-1,l=function(){for(i=e.once,r=t=!0;s.length;u=-1)for(n=s.shift();++u<a.length;)a[u].apply(n[0],n[1])===!1&&e.stopOnFalse&&(u=a.length,n=!1);e.memory||(n=!1),t=!1,i&&(a=n?[]:\"\")},c={add:function(){return a&&(n&&!t&&(u=a.length-1,s.push(n)),function r(t){pe.each(t,function(t,n){pe.isFunction(n)?e.unique&&c.has(n)||a.push(n):n&&n.length&&\"string\"!==pe.type(n)&&r(n)})}(arguments),n&&!t&&l()),this},remove:function(){return pe.each(arguments,function(e,t){for(var n;(n=pe.inArray(t,a,n))>-1;)a.splice(n,1),n<=u&&u--}),this},has:function(e){return e?pe.inArray(e,a)>-1:a.length>0},empty:function(){return a&&(a=[]),this},disable:function(){return i=s=[],a=n=\"\",this},disabled:function(){return!a},lock:function(){return i=!0,n||c.disable(),this},locked:function(){return!!i},fireWith:function(e,n){return i||(n=n||[],n=[e,n.slice?n.slice():n],s.push(n),t||l()),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!r}};return c},pe.extend({Deferred:function(e){var t=[[\"resolve\",\"done\",pe.Callbacks(\"once memory\"),\"resolved\"],[\"reject\",\"fail\",pe.Callbacks(\"once memory\"),\"rejected\"],[\"notify\",\"progress\",pe.Callbacks(\"memory\")]],n=\"pending\",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return pe.Deferred(function(n){pe.each(t,function(t,o){var a=pe.isFunction(e[t])&&e[t];i[o[1]](function(){var e=a&&a.apply(this,arguments);e&&pe.isFunction(e.promise)?e.promise().progress(n.notify).done(n.resolve).fail(n.reject):n[o[0]+\"With\"](this===r?n.promise():this,a?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?pe.extend(e,r):r}},i={};return r.pipe=r.then,pe.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,n,r,i=0,o=ie.call(arguments),a=o.length,s=1!==a||e&&pe.isFunction(e.promise)?a:0,u=1===s?e:pe.Deferred(),l=function(e,n,r){return function(i){n[e]=this,r[e]=arguments.length>1?ie.call(arguments):i,r===t?u.notifyWith(n,r):--s||u.resolveWith(n,r)}};if(a>1)for(t=new Array(a),n=new Array(a),r=new Array(a);i<a;i++)o[i]&&pe.isFunction(o[i].promise)?o[i].promise().progress(l(i,n,t)).done(l(i,r,o)).fail(u.reject):--s;return s||u.resolveWith(r,o),u.promise()}});var je;pe.fn.ready=function(e){return pe.ready.promise().done(e),this},pe.extend({isReady:!1,readyWait:1,holdReady:function(e){e?pe.readyWait++:pe.ready(!0)},ready:function(e){(e===!0?--pe.readyWait:pe.isReady)||(pe.isReady=!0,e!==!0&&--pe.readyWait>0||(je.resolveWith(re,[pe]),pe.fn.triggerHandler&&(pe(re).triggerHandler(\"ready\"),pe(re).off(\"ready\"))))}}),pe.ready.promise=function(t){if(!je)if(je=pe.Deferred(),\"complete\"===re.readyState||\"loading\"!==re.readyState&&!re.documentElement.doScroll)e.setTimeout(pe.ready);else if(re.addEventListener)re.addEventListener(\"DOMContentLoaded\",s),e.addEventListener(\"load\",s);else{re.attachEvent(\"onreadystatechange\",s),e.attachEvent(\"onload\",s);var n=!1;try{n=null==e.frameElement&&re.documentElement}catch(r){}n&&n.doScroll&&!function i(){if(!pe.isReady){try{n.doScroll(\"left\")}catch(t){return e.setTimeout(i,50)}a(),pe.ready()}}()}return je.promise(t)},pe.ready.promise();var Le;for(Le in pe(fe))break;fe.ownFirst=\"0\"===Le,fe.inlineBlockNeedsLayout=!1,pe(function(){var e,t,n,r;n=re.getElementsByTagName(\"body\")[0],n&&n.style&&(t=re.createElement(\"div\"),r=re.createElement(\"div\"),r.style.cssText=\"position:absolute;border:0;width:0;height:0;top:0;left:-9999px\",n.appendChild(r).appendChild(t),\"undefined\"!=typeof t.style.zoom&&(t.style.cssText=\"display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1\",fe.inlineBlockNeedsLayout=e=3===t.offsetWidth,e&&(n.style.zoom=1)),n.removeChild(r))}),function(){var e=re.createElement(\"div\");fe.deleteExpando=!0;try{delete e.test}catch(t){fe.deleteExpando=!1}e=null}();var He=function(e){var t=pe.noData[(e.nodeName+\" \").toLowerCase()],n=+e.nodeType||1;return(1===n||9===n)&&(!t||t!==!0&&e.getAttribute(\"classid\")===t)},qe=/^(?:\\{[\\w\\W]*\\}|\\[[\\w\\W]*\\])$/,_e=/([A-Z])/g;pe.extend({cache:{},noData:{\"applet \":!0,\"embed \":!0,\"object \":\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"},hasData:function(e){return e=e.nodeType?pe.cache[e[pe.expando]]:e[pe.expando],!!e&&!l(e)},data:function(e,t,n){return c(e,t,n)},removeData:function(e,t){return f(e,t)},_data:function(e,t,n){return c(e,t,n,!0)},_removeData:function(e,t){return f(e,t,!0)}}),pe.fn.extend({data:function(e,t){var n,r,i,o=this[0],a=o&&o.attributes;if(void 0===e){if(this.length&&(i=pe.data(o),1===o.nodeType&&!pe._data(o,\"parsedAttrs\"))){for(n=a.length;n--;)a[n]&&(r=a[n].name,0===r.indexOf(\"data-\")&&(r=pe.camelCase(r.slice(5)),u(o,r,i[r])));pe._data(o,\"parsedAttrs\",!0)}return i}return\"object\"==typeof e?this.each(function(){pe.data(this,e)}):arguments.length>1?this.each(function(){pe.data(this,e,t)}):o?u(o,e,pe.data(o,e)):void 0},removeData:function(e){return this.each(function(){pe.removeData(this,e)})}}),pe.extend({queue:function(e,t,n){var r;if(e)return t=(t||\"fx\")+\"queue\",r=pe._data(e,t),n&&(!r||pe.isArray(n)?r=pe._data(e,t,pe.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||\"fx\";var n=pe.queue(e,t),r=n.length,i=n.shift(),o=pe._queueHooks(e,t),a=function(){pe.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 pe._data(e,n)||pe._data(e,n,{empty:pe.Callbacks(\"once memory\").add(function(){pe._removeData(e,t+\"queue\"),pe._removeData(e,n)})})}}),pe.fn.extend({queue:function(e,t){var n=2;return\"string\"!=typeof e&&(t=e,e=\"fx\",n--),arguments.length<n?pe.queue(this[0],e):void 0===t?this:this.each(function(){var n=pe.queue(this,e,t);pe._queueHooks(this,e),\"fx\"===e&&\"inprogress\"!==n[0]&&pe.dequeue(this,e)})},dequeue:function(e){return this.each(function(){pe.dequeue(this,e)})},clearQueue:function(e){return this.queue(e||\"fx\",[])},promise:function(e,t){var n,r=1,i=pe.Deferred(),o=this,a=this.length,s=function(){--r||i.resolveWith(o,[o])};for(\"string\"!=typeof e&&(t=e,e=void 0),e=e||\"fx\";a--;)n=pe._data(o[a],e+\"queueHooks\"),n&&n.empty&&(r++,n.empty.add(s));return s(),i.promise(t)}}),function(){var e;fe.shrinkWrapBlocks=function(){if(null!=e)return e;e=!1;var t,n,r;return n=re.getElementsByTagName(\"body\")[0],n&&n.style?(t=re.createElement(\"div\"),r=re.createElement(\"div\"),r.style.cssText=\"position:absolute;border:0;width:0;height:0;top:0;left:-9999px\",n.appendChild(r).appendChild(t),\"undefined\"!=typeof t.style.zoom&&(t.style.cssText=\"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:1px;width:1px;zoom:1\",t.appendChild(re.createElement(\"div\")).style.width=\"5px\",e=3!==t.offsetWidth),n.removeChild(r),e):void 0}}();var Fe=/[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/.source,Me=new RegExp(\"^(?:([+-])=|)(\"+Fe+\")([a-z%]*)$\",\"i\"),Oe=[\"Top\",\"Right\",\"Bottom\",\"Left\"],Re=function(e,t){return e=t||e,\"none\"===pe.css(e,\"display\")||!pe.contains(e.ownerDocument,e)},Pe=function(e,t,n,r,i,o,a){var s=0,u=e.length,l=null==n;if(\"object\"===pe.type(n)){i=!0;for(s in n)Pe(e,t,s,n[s],!0,o,a)}else if(void 0!==r&&(i=!0,pe.isFunction(r)||(a=!0),l&&(a?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(pe(e),n)})),t))for(;s<u;s++)t(e[s],n,a?r:r.call(e[s],s,t(e[s],n)));return i?e:l?t.call(e):u?t(e[0],n):o},Be=/^(?:checkbox|radio)$/i,We=/<([\\w:-]+)/,Ie=/^$|\\/(?:java|ecma)script/i,$e=/^\\s+/,ze=\"abbr|article|aside|audio|bdi|canvas|data|datalist|details|dialog|figcaption|figure|footer|header|hgroup|main|mark|meter|nav|output|picture|progress|section|summary|template|time|video\";!function(){var e=re.createElement(\"div\"),t=re.createDocumentFragment(),n=re.createElement(\"input\");e.innerHTML=\"  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>\",fe.leadingWhitespace=3===e.firstChild.nodeType,fe.tbody=!e.getElementsByTagName(\"tbody\").length,fe.htmlSerialize=!!e.getElementsByTagName(\"link\").length,fe.html5Clone=\"<:nav></:nav>\"!==re.createElement(\"nav\").cloneNode(!0).outerHTML,n.type=\"checkbox\",n.checked=!0,t.appendChild(n),fe.appendChecked=n.checked,e.innerHTML=\"<textarea>x</textarea>\",fe.noCloneChecked=!!e.cloneNode(!0).lastChild.defaultValue,t.appendChild(e),n=re.createElement(\"input\"),n.setAttribute(\"type\",\"radio\"),n.setAttribute(\"checked\",\"checked\"),n.setAttribute(\"name\",\"t\"),e.appendChild(n),fe.checkClone=e.cloneNode(!0).cloneNode(!0).lastChild.checked,fe.noCloneEvent=!!e.addEventListener,e[pe.expando]=1,fe.attributes=!e.getAttribute(pe.expando)}();var Xe={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:fe.htmlSerialize?[0,\"\",\"\"]:[1,\"X<div>\",\"</div>\"]};Xe.optgroup=Xe.option,Xe.tbody=Xe.tfoot=Xe.colgroup=Xe.caption=Xe.thead,Xe.th=Xe.td;var Ue=/<|&#?\\w+;/,Ve=/<tbody/i;!function(){var t,n,r=re.createElement(\"div\");for(t in{submit:!0,change:!0,focusin:!0})n=\"on\"+t,(fe[t]=n in e)||(r.setAttribute(n,\"t\"),fe[t]=r.attributes[n].expando===!1);r=null}();var Ye=/^(?:input|select|textarea)$/i,Je=/^key/,Ge=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ke=/^(?:focusinfocus|focusoutblur)$/,Qe=/^([^.]*)(?:\\.(.+)|)/;pe.event={global:{},add:function(e,t,n,r,i){var o,a,s,u,l,c,f,d,p,h,g,m=pe._data(e);if(m){for(n.handler&&(u=n,n=u.handler,i=u.selector),n.guid||(n.guid=pe.guid++),(a=m.events)||(a=m.events={}),(c=m.handle)||(c=m.handle=function(e){return\"undefined\"==typeof pe||e&&pe.event.triggered===e.type?void 0:pe.event.dispatch.apply(c.elem,arguments)},c.elem=e),t=(t||\"\").match(De)||[\"\"],s=t.length;s--;)o=Qe.exec(t[s])||[],p=g=o[1],h=(o[2]||\"\").split(\".\").sort(),p&&(l=pe.event.special[p]||{},p=(i?l.delegateType:l.bindType)||p,l=pe.event.special[p]||{},f=pe.extend({type:p,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&pe.expr.match.needsContext.test(i),namespace:h.join(\".\")},u),(d=a[p])||(d=a[p]=[],d.delegateCount=0,l.setup&&l.setup.call(e,r,h,c)!==!1||(e.addEventListener?e.addEventListener(p,c,!1):e.attachEvent&&e.attachEvent(\"on\"+p,c))),l.add&&(l.add.call(e,f),f.handler.guid||(f.handler.guid=n.guid)),i?d.splice(d.delegateCount++,0,f):d.push(f),pe.event.global[p]=!0);e=null}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,d,p,h,g,m=pe.hasData(e)&&pe._data(e);if(m&&(c=m.events)){for(t=(t||\"\").match(De)||[\"\"],l=t.length;l--;)if(s=Qe.exec(t[l])||[],p=g=s[1],h=(s[2]||\"\").split(\".\").sort(),p){for(f=pe.event.special[p]||{},p=(r?f.delegateType:f.bindType)||p,d=c[p]||[],s=s[2]&&new RegExp(\"(^|\\\\.)\"+h.join(\"\\\\.(?:.*\\\\.|)\")+\"(\\\\.|$)\"),u=o=d.length;o--;)a=d[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&(\"**\"!==r||!a.selector)||(d.splice(o,1),a.selector&&d.delegateCount--,f.remove&&f.remove.call(e,a));u&&!d.length&&(f.teardown&&f.teardown.call(e,h,m.handle)!==!1||pe.removeEvent(e,p,m.handle),delete c[p])}else for(p in c)pe.event.remove(e,p+t[l],n,r,!0);pe.isEmptyObject(c)&&(delete m.handle,pe._removeData(e,\"events\"))}},trigger:function(t,n,r,i){var o,a,s,u,l,c,f,d=[r||re],p=ce.call(t,\"type\")?t.type:t,h=ce.call(t,\"namespace\")?t.namespace.split(\".\"):[];if(s=c=r=r||re,3!==r.nodeType&&8!==r.nodeType&&!Ke.test(p+pe.event.triggered)&&(p.indexOf(\".\")>-1&&(h=p.split(\".\"),p=h.shift(),h.sort()),a=p.indexOf(\":\")<0&&\"on\"+p,t=t[pe.expando]?t:new pe.Event(p,\"object\"==typeof t&&t),t.isTrigger=i?2:3,t.namespace=h.join(\".\"),t.rnamespace=t.namespace?new RegExp(\"(^|\\\\.)\"+h.join(\"\\\\.(?:.*\\\\.|)\")+\"(\\\\.|$)\"):null,t.result=void 0,t.target||(t.target=r),n=null==n?[t]:pe.makeArray(n,[t]),l=pe.event.special[p]||{},i||!l.trigger||l.trigger.apply(r,n)!==!1)){if(!i&&!l.noBubble&&!pe.isWindow(r)){for(u=l.delegateType||p,Ke.test(u+p)||(s=s.parentNode);s;s=s.parentNode)d.push(s),c=s;c===(r.ownerDocument||re)&&d.push(c.defaultView||c.parentWindow||e)}for(f=0;(s=d[f++])&&!t.isPropagationStopped();)t.type=f>1?u:l.bindType||p,o=(pe._data(s,\"events\")||{})[t.type]&&pe._data(s,\"handle\"),o&&o.apply(s,n),o=a&&s[a],o&&o.apply&&He(s)&&(t.result=o.apply(s,n),t.result===!1&&t.preventDefault());if(t.type=p,!i&&!t.isDefaultPrevented()&&(!l._default||l._default.apply(d.pop(),n)===!1)&&He(r)&&a&&r[p]&&!pe.isWindow(r)){c=r[a],c&&(r[a]=null),pe.event.triggered=p;try{r[p]()}catch(g){}pe.event.triggered=void 0,c&&(r[a]=c)}return t.result}},dispatch:function(e){e=pe.event.fix(e);var t,n,r,i,o,a=[],s=ie.call(arguments),u=(pe._data(this,\"events\")||{})[e.type]||[],l=pe.event.special[e.type]||{};if(s[0]=e,e.delegateTarget=this,!l.preDispatch||l.preDispatch.call(this,e)!==!1){for(a=pe.event.handlers.call(this,e,u),t=0;(i=a[t++])&&!e.isPropagationStopped();)for(e.currentTarget=i.elem,n=0;(o=i.handlers[n++])&&!e.isImmediatePropagationStopped();)e.rnamespace&&!e.rnamespace.test(o.namespace)||(e.handleObj=o,e.data=o.data,r=((pe.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,s),void 0!==r&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()));return l.postDispatch&&l.postDispatch.call(this,e),e.result}},handlers:function(e,t){var n,r,i,o,a=[],s=t.delegateCount,u=e.target;if(s&&u.nodeType&&(\"click\"!==e.type||isNaN(e.button)||e.button<1))for(;u!=this;u=u.parentNode||this)if(1===u.nodeType&&(u.disabled!==!0||\"click\"!==e.type)){for(r=[],n=0;n<s;n++)o=t[n],i=o.selector+\" \",void 0===r[i]&&(r[i]=o.needsContext?pe(i,this).index(u)>-1:pe.find(i,this,null,[u]).length),r[i]&&r.push(o);r.length&&a.push({elem:u,handlers:r})}return s<t.length&&a.push({elem:this,handlers:t.slice(s)}),a},fix:function(e){if(e[pe.expando])return e;var t,n,r,i=e.type,o=e,a=this.fixHooks[i];for(a||(this.fixHooks[i]=a=Ge.test(i)?this.mouseHooks:Je.test(i)?this.keyHooks:{}),r=a.props?this.props.concat(a.props):this.props,e=new pe.Event(o),t=r.length;t--;)n=r[t],e[n]=o[n];return e.target||(e.target=o.srcElement||re),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,a.filter?a.filter(e,o):e},props:\"altKey bubbles cancelable ctrlKey currentTarget detail 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,t){var n,r,i,o=t.button,a=t.fromElement;return null==e.pageX&&null!=t.clientX&&(r=e.target.ownerDocument||re,i=r.documentElement,n=r.body,e.pageX=t.clientX+(i&&i.scrollLeft||n&&n.scrollLeft||0)-(i&&i.clientLeft||n&&n.clientLeft||0),e.pageY=t.clientY+(i&&i.scrollTop||n&&n.scrollTop||0)-(i&&i.clientTop||n&&n.clientTop||0)),!e.relatedTarget&&a&&(e.relatedTarget=a===e.target?t.toElement:a),e.which||void 0===o||(e.which=1&o?1:2&o?3:4&o?2:0),e}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==b()&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:\"focusin\"},blur:{trigger:function(){if(this===b()&&this.blur)return this.blur(),!1},delegateType:\"focusout\"},click:{trigger:function(){if(pe.nodeName(this,\"input\")&&\"checkbox\"===this.type&&this.click)return this.click(),!1},_default:function(e){return pe.nodeName(e.target,\"a\")}},beforeunload:{postDispatch:function(e){void 0!==e.result&&e.originalEvent&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n){var r=pe.extend(new pe.Event,n,{type:e,isSimulated:!0});pe.event.trigger(r,null,t),r.isDefaultPrevented()&&n.preventDefault()}},pe.removeEvent=re.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n)}:function(e,t,n){var r=\"on\"+t;e.detachEvent&&(\"undefined\"==typeof e[r]&&(e[r]=null),e.detachEvent(r,n))},pe.Event=function(e,t){return this instanceof pe.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||void 0===e.defaultPrevented&&e.returnValue===!1?v:x):this.type=e,t&&pe.extend(this,t),this.timeStamp=e&&e.timeStamp||pe.now(),void(this[pe.expando]=!0)):new pe.Event(e,t)},pe.Event.prototype={constructor:pe.Event,isDefaultPrevented:x,isPropagationStopped:x,isImmediatePropagationStopped:x,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=v,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=v,e&&!this.isSimulated&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){var e=this.originalEvent;this.isImmediatePropagationStopped=v,e&&e.stopImmediatePropagation&&e.stopImmediatePropagation(),this.stopPropagation()}},pe.each({mouseenter:\"mouseover\",mouseleave:\"mouseout\",pointerenter:\"pointerover\",pointerleave:\"pointerout\"},function(e,t){pe.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return i&&(i===r||pe.contains(r,i))||(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),fe.submit||(pe.event.special.submit={setup:function(){return!pe.nodeName(this,\"form\")&&void pe.event.add(this,\"click._submit keypress._submit\",function(e){var t=e.target,n=pe.nodeName(t,\"input\")||pe.nodeName(t,\"button\")?pe.prop(t,\"form\"):void 0;n&&!pe._data(n,\"submit\")&&(pe.event.add(n,\"submit._submit\",function(e){e._submitBubble=!0}),pe._data(n,\"submit\",!0))})},postDispatch:function(e){e._submitBubble&&(delete e._submitBubble,this.parentNode&&!e.isTrigger&&pe.event.simulate(\"submit\",this.parentNode,e))},teardown:function(){return!pe.nodeName(this,\"form\")&&void pe.event.remove(this,\"._submit\")}}),fe.change||(pe.event.special.change={setup:function(){return Ye.test(this.nodeName)?(\"checkbox\"!==this.type&&\"radio\"!==this.type||(pe.event.add(this,\"propertychange._change\",function(e){\"checked\"===e.originalEvent.propertyName&&(this._justChanged=!0)}),pe.event.add(this,\"click._change\",function(e){this._justChanged&&!e.isTrigger&&(this._justChanged=!1),pe.event.simulate(\"change\",this,e)})),!1):void pe.event.add(this,\"beforeactivate._change\",function(e){var t=e.target;Ye.test(t.nodeName)&&!pe._data(t,\"change\")&&(pe.event.add(t,\"change._change\",function(e){!this.parentNode||e.isSimulated||e.isTrigger||pe.event.simulate(\"change\",this.parentNode,e)}),pe._data(t,\"change\",!0))})},handle:function(e){var t=e.target;if(this!==t||e.isSimulated||e.isTrigger||\"radio\"!==t.type&&\"checkbox\"!==t.type)return e.handleObj.handler.apply(this,arguments)},teardown:function(){return pe.event.remove(this,\"._change\"),!Ye.test(this.nodeName)}}),fe.focusin||pe.each({focus:\"focusin\",blur:\"focusout\"},function(e,t){var n=function(e){pe.event.simulate(t,e.target,pe.event.fix(e))};pe.event.special[t]={setup:function(){var r=this.ownerDocument||this,i=pe._data(r,t);i||r.addEventListener(e,n,!0),pe._data(r,t,(i||0)+1)},teardown:function(){var r=this.ownerDocument||this,i=pe._data(r,t)-1;i?pe._data(r,t,i):(r.removeEventListener(e,n,!0),pe._removeData(r,t))}}}),pe.fn.extend({on:function(e,t,n,r){return w(this,e,t,n,r)},one:function(e,t,n,r){return w(this,e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,pe(e.delegateTarget).off(r.namespace?r.origType+\".\"+r.namespace:r.origType,r.selector,r.handler),this;if(\"object\"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return t!==!1&&\"function\"!=typeof t||(n=t,t=void 0),n===!1&&(n=x),this.each(function(){pe.event.remove(this,e,n,t)})},trigger:function(e,t){return this.each(function(){pe.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return pe.event.trigger(e,t,n,!0)}});var Ze=/ jQuery\\d+=\"(?:null|\\d+)\"/g,et=new RegExp(\"<(?:\"+ze+\")[\\\\s/>]\",\"i\"),tt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:-]+)[^>]*)\\/>/gi,nt=/<script|<style|<link/i,rt=/checked\\s*(?:[^=]|=\\s*.checked.)/i,it=/^true\\/(.*)/,ot=/^\\s*<!(?:\\[CDATA\\[|--)|(?:\\]\\]|--)>\\s*$/g,at=p(re),st=at.appendChild(re.createElement(\"div\"));pe.extend({htmlPrefilter:function(e){return e.replace(tt,\"<$1></$2>\")},clone:function(e,t,n){var r,i,o,a,s,u=pe.contains(e.ownerDocument,e);if(fe.html5Clone||pe.isXMLDoc(e)||!et.test(\"<\"+e.nodeName+\">\")?o=e.cloneNode(!0):(st.innerHTML=e.outerHTML,st.removeChild(o=st.firstChild)),!(fe.noCloneEvent&&fe.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||pe.isXMLDoc(e)))for(r=h(o),s=h(e),a=0;null!=(i=s[a]);++a)r[a]&&k(i,r[a]);if(t)if(n)for(s=s||h(e),r=r||h(o),a=0;null!=(i=s[a]);a++)N(i,r[a]);else N(e,o);return r=h(o,\"script\"),r.length>0&&g(r,!u&&h(e,\"script\")),r=s=i=null,o},cleanData:function(e,t){for(var n,r,i,o,a=0,s=pe.expando,u=pe.cache,l=fe.attributes,c=pe.event.special;null!=(n=e[a]);a++)if((t||He(n))&&(i=n[s],o=i&&u[i])){if(o.events)for(r in o.events)c[r]?pe.event.remove(n,r):pe.removeEvent(n,r,o.handle);u[i]&&(delete u[i],l||\"undefined\"==typeof n.removeAttribute?n[s]=void 0:n.removeAttribute(s),ne.push(i))}}}),pe.fn.extend({domManip:S,detach:function(e){return A(this,e,!0)},remove:function(e){return A(this,e)},text:function(e){return Pe(this,function(e){return void 0===e?pe.text(this):this.empty().append((this[0]&&this[0].ownerDocument||re).createTextNode(e))},null,e,arguments.length)},append:function(){return S(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=T(this,e);t.appendChild(e)}})},prepend:function(){return S(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=T(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return S(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return S(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++){for(1===e.nodeType&&pe.cleanData(h(e,!1));e.firstChild;)e.removeChild(e.firstChild);e.options&&pe.nodeName(e,\"select\")&&(e.options.length=0)}return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return pe.clone(this,e,t)})},html:function(e){return Pe(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e)return 1===t.nodeType?t.innerHTML.replace(Ze,\"\"):void 0;if(\"string\"==typeof e&&!nt.test(e)&&(fe.htmlSerialize||!et.test(e))&&(fe.leadingWhitespace||!$e.test(e))&&!Xe[(We.exec(e)||[\"\",\"\"])[1].toLowerCase()]){e=pe.htmlPrefilter(e);try{for(;n<r;n++)t=this[n]||{},1===t.nodeType&&(pe.cleanData(h(t,!1)),t.innerHTML=e);t=0}catch(i){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=[];return S(this,arguments,function(t){var n=this.parentNode;pe.inArray(this,e)<0&&(pe.cleanData(h(this)),\nn&&n.replaceChild(t,this))},e)}}),pe.each({appendTo:\"append\",prependTo:\"prepend\",insertBefore:\"before\",insertAfter:\"after\",replaceAll:\"replaceWith\"},function(e,t){pe.fn[e]=function(e){for(var n,r=0,i=[],o=pe(e),a=o.length-1;r<=a;r++)n=r===a?this:this.clone(!0),pe(o[r])[t](n),ae.apply(i,n.get());return this.pushStack(i)}});var ut,lt={HTML:\"block\",BODY:\"block\"},ct=/^margin/,ft=new RegExp(\"^(\"+Fe+\")(?!px)[a-z%]+$\",\"i\"),dt=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},pt=re.documentElement;!function(){function t(){var t,c,f=re.documentElement;f.appendChild(u),l.style.cssText=\"-webkit-box-sizing:border-box;box-sizing:border-box;position:relative;display:block;margin:auto;border:1px;padding:1px;top:1%;width:50%\",n=i=s=!1,r=a=!0,e.getComputedStyle&&(c=e.getComputedStyle(l),n=\"1%\"!==(c||{}).top,s=\"2px\"===(c||{}).marginLeft,i=\"4px\"===(c||{width:\"4px\"}).width,l.style.marginRight=\"50%\",r=\"4px\"===(c||{marginRight:\"4px\"}).marginRight,t=l.appendChild(re.createElement(\"div\")),t.style.cssText=l.style.cssText=\"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0\",t.style.marginRight=t.style.width=\"0\",l.style.width=\"1px\",a=!parseFloat((e.getComputedStyle(t)||{}).marginRight),l.removeChild(t)),l.style.display=\"none\",o=0===l.getClientRects().length,o&&(l.style.display=\"\",l.innerHTML=\"<table><tr><td></td><td>t</td></tr></table>\",t=l.getElementsByTagName(\"td\"),t[0].style.cssText=\"margin:0;border:0;padding:0;display:none\",o=0===t[0].offsetHeight,o&&(t[0].style.display=\"\",t[1].style.display=\"none\",o=0===t[0].offsetHeight)),f.removeChild(u)}var n,r,i,o,a,s,u=re.createElement(\"div\"),l=re.createElement(\"div\");l.style&&(l.style.cssText=\"float:left;opacity:.5\",fe.opacity=\"0.5\"===l.style.opacity,fe.cssFloat=!!l.style.cssFloat,l.style.backgroundClip=\"content-box\",l.cloneNode(!0).style.backgroundClip=\"\",fe.clearCloneStyle=\"content-box\"===l.style.backgroundClip,u=re.createElement(\"div\"),u.style.cssText=\"border:0;width:8px;height:0;top:0;left:-9999px;padding:0;margin-top:1px;position:absolute\",l.innerHTML=\"\",u.appendChild(l),fe.boxSizing=\"\"===l.style.boxSizing||\"\"===l.style.MozBoxSizing||\"\"===l.style.WebkitBoxSizing,pe.extend(fe,{reliableHiddenOffsets:function(){return null==n&&t(),o},boxSizingReliable:function(){return null==n&&t(),i},pixelMarginRight:function(){return null==n&&t(),r},pixelPosition:function(){return null==n&&t(),n},reliableMarginRight:function(){return null==n&&t(),a},reliableMarginLeft:function(){return null==n&&t(),s}}))}();var ht,gt,mt=/^(top|right|bottom|left)$/;e.getComputedStyle?(ht=function(t){var n=t.ownerDocument.defaultView;return n&&n.opener||(n=e),n.getComputedStyle(t)},gt=function(e,t,n){var r,i,o,a,s=e.style;return n=n||ht(e),a=n?n.getPropertyValue(t)||n[t]:void 0,\"\"!==a&&void 0!==a||pe.contains(e.ownerDocument,e)||(a=pe.style(e,t)),n&&!fe.pixelMarginRight()&&ft.test(a)&&ct.test(t)&&(r=s.width,i=s.minWidth,o=s.maxWidth,s.minWidth=s.maxWidth=s.width=a,a=n.width,s.width=r,s.minWidth=i,s.maxWidth=o),void 0===a?a:a+\"\"}):pt.currentStyle&&(ht=function(e){return e.currentStyle},gt=function(e,t,n){var r,i,o,a,s=e.style;return n=n||ht(e),a=n?n[t]:void 0,null==a&&s&&s[t]&&(a=s[t]),ft.test(a)&&!mt.test(t)&&(r=s.left,i=e.runtimeStyle,o=i&&i.left,o&&(i.left=e.currentStyle.left),s.left=\"fontSize\"===t?\"1em\":a,a=s.pixelLeft+\"px\",s.left=r,o&&(i.left=o)),void 0===a?a:a+\"\"||\"auto\"});var yt=/alpha\\([^)]*\\)/i,vt=/opacity\\s*=\\s*([^)]*)/i,xt=/^(none|table(?!-c[ea]).+)/,bt=new RegExp(\"^(\"+Fe+\")(.*)$\",\"i\"),wt={position:\"absolute\",visibility:\"hidden\",display:\"block\"},Tt={letterSpacing:\"0\",fontWeight:\"400\"},Ct=[\"Webkit\",\"O\",\"Moz\",\"ms\"],Et=re.createElement(\"div\").style;pe.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=gt(e,\"opacity\");return\"\"===n?\"1\":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{\"float\":fe.cssFloat?\"cssFloat\":\"styleFloat\"},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=pe.camelCase(t),u=e.style;if(t=pe.cssProps[s]||(pe.cssProps[s]=H(s)||s),a=pe.cssHooks[t]||pe.cssHooks[s],void 0===n)return a&&\"get\"in a&&void 0!==(i=a.get(e,!1,r))?i:u[t];if(o=typeof n,\"string\"===o&&(i=Me.exec(n))&&i[1]&&(n=d(e,t,i),o=\"number\"),null!=n&&n===n&&(\"number\"===o&&(n+=i&&i[3]||(pe.cssNumber[s]?\"\":\"px\")),fe.clearCloneStyle||\"\"!==n||0!==t.indexOf(\"background\")||(u[t]=\"inherit\"),!(a&&\"set\"in a&&void 0===(n=a.set(e,n,r)))))try{u[t]=n}catch(l){}}},css:function(e,t,n,r){var i,o,a,s=pe.camelCase(t);return t=pe.cssProps[s]||(pe.cssProps[s]=H(s)||s),a=pe.cssHooks[t]||pe.cssHooks[s],a&&\"get\"in a&&(o=a.get(e,!0,n)),void 0===o&&(o=gt(e,t,r)),\"normal\"===o&&t in Tt&&(o=Tt[t]),\"\"===n||n?(i=parseFloat(o),n===!0||isFinite(i)?i||0:o):o}}),pe.each([\"height\",\"width\"],function(e,t){pe.cssHooks[t]={get:function(e,n,r){if(n)return xt.test(pe.css(e,\"display\"))&&0===e.offsetWidth?dt(e,wt,function(){return M(e,t,r)}):M(e,t,r)},set:function(e,n,r){var i=r&&ht(e);return _(e,n,r?F(e,t,r,fe.boxSizing&&\"border-box\"===pe.css(e,\"boxSizing\",!1,i),i):0)}}}),fe.opacity||(pe.cssHooks.opacity={get:function(e,t){return vt.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=pe.isNumeric(t)?\"alpha(opacity=\"+100*t+\")\":\"\",o=r&&r.filter||n.filter||\"\";n.zoom=1,(t>=1||\"\"===t)&&\"\"===pe.trim(o.replace(yt,\"\"))&&n.removeAttribute&&(n.removeAttribute(\"filter\"),\"\"===t||r&&!r.filter)||(n.filter=yt.test(o)?o.replace(yt,i):o+\" \"+i)}}),pe.cssHooks.marginRight=L(fe.reliableMarginRight,function(e,t){if(t)return dt(e,{display:\"inline-block\"},gt,[e,\"marginRight\"])}),pe.cssHooks.marginLeft=L(fe.reliableMarginLeft,function(e,t){if(t)return(parseFloat(gt(e,\"marginLeft\"))||(pe.contains(e.ownerDocument,e)?e.getBoundingClientRect().left-dt(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}):0))+\"px\"}),pe.each({margin:\"\",padding:\"\",border:\"Width\"},function(e,t){pe.cssHooks[e+t]={expand:function(n){for(var r=0,i={},o=\"string\"==typeof n?n.split(\" \"):[n];r<4;r++)i[e+Oe[r]+t]=o[r]||o[r-2]||o[0];return i}},ct.test(e)||(pe.cssHooks[e+t].set=_)}),pe.fn.extend({css:function(e,t){return Pe(this,function(e,t,n){var r,i,o={},a=0;if(pe.isArray(t)){for(r=ht(e),i=t.length;a<i;a++)o[t[a]]=pe.css(e,t[a],!1,r);return o}return void 0!==n?pe.style(e,t,n):pe.css(e,t)},e,t,arguments.length>1)},show:function(){return q(this,!0)},hide:function(){return q(this)},toggle:function(e){return\"boolean\"==typeof e?e?this.show():this.hide():this.each(function(){Re(this)?pe(this).show():pe(this).hide()})}}),pe.Tween=O,O.prototype={constructor:O,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||pe.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(pe.cssNumber[n]?\"\":\"px\")},cur:function(){var e=O.propHooks[this.prop];return e&&e.get?e.get(this):O.propHooks._default.get(this)},run:function(e){var t,n=O.propHooks[this.prop];return this.options.duration?this.pos=t=pe.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=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):O.propHooks._default.set(this),this}},O.prototype.init.prototype=O.prototype,O.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=pe.css(e.elem,e.prop,\"\"),t&&\"auto\"!==t?t:0)},set:function(e){pe.fx.step[e.prop]?pe.fx.step[e.prop](e):1!==e.elem.nodeType||null==e.elem.style[pe.cssProps[e.prop]]&&!pe.cssHooks[e.prop]?e.elem[e.prop]=e.now:pe.style(e.elem,e.prop,e.now+e.unit)}}},O.propHooks.scrollTop=O.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},pe.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:\"swing\"},pe.fx=O.prototype.init,pe.fx.step={};var Nt,kt,St=/^(?:toggle|show|hide)$/,At=/queueHooks$/;pe.Animation=pe.extend($,{tweeners:{\"*\":[function(e,t){var n=this.createTween(e,t);return d(n.elem,e,Me.exec(t),n),n}]},tweener:function(e,t){pe.isFunction(e)?(t=e,e=[\"*\"]):e=e.match(De);for(var n,r=0,i=e.length;r<i;r++)n=e[r],$.tweeners[n]=$.tweeners[n]||[],$.tweeners[n].unshift(t)},prefilters:[W],prefilter:function(e,t){t?$.prefilters.unshift(e):$.prefilters.push(e)}}),pe.speed=function(e,t,n){var r=e&&\"object\"==typeof e?pe.extend({},e):{complete:n||!n&&t||pe.isFunction(e)&&e,duration:e,easing:n&&t||t&&!pe.isFunction(t)&&t};return r.duration=pe.fx.off?0:\"number\"==typeof r.duration?r.duration:r.duration in pe.fx.speeds?pe.fx.speeds[r.duration]:pe.fx.speeds._default,null!=r.queue&&r.queue!==!0||(r.queue=\"fx\"),r.old=r.complete,r.complete=function(){pe.isFunction(r.old)&&r.old.call(this),r.queue&&pe.dequeue(this,r.queue)},r},pe.fn.extend({fadeTo:function(e,t,n,r){return this.filter(Re).css(\"opacity\",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=pe.isEmptyObject(e),o=pe.speed(t,n,r),a=function(){var t=$(this,pe.extend({},e),o);(i||pe._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,t,n){var r=function(e){var t=e.stop;delete e.stop,t(n)};return\"string\"!=typeof e&&(n=t,t=e,e=void 0),t&&e!==!1&&this.queue(e||\"fx\",[]),this.each(function(){var t=!0,i=null!=e&&e+\"queueHooks\",o=pe.timers,a=pe._data(this);if(i)a[i]&&a[i].stop&&r(a[i]);else for(i in a)a[i]&&a[i].stop&&At.test(i)&&r(a[i]);for(i=o.length;i--;)o[i].elem!==this||null!=e&&o[i].queue!==e||(o[i].anim.stop(n),t=!1,o.splice(i,1));!t&&n||pe.dequeue(this,e)})},finish:function(e){return e!==!1&&(e=e||\"fx\"),this.each(function(){var t,n=pe._data(this),r=n[e+\"queue\"],i=n[e+\"queueHooks\"],o=pe.timers,a=r?r.length:0;for(n.finish=!0,pe.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;t<a;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}}),pe.each([\"toggle\",\"show\",\"hide\"],function(e,t){var n=pe.fn[t];pe.fn[t]=function(e,r,i){return null==e||\"boolean\"==typeof e?n.apply(this,arguments):this.animate(P(t,!0),e,r,i)}}),pe.each({slideDown:P(\"show\"),slideUp:P(\"hide\"),slideToggle:P(\"toggle\"),fadeIn:{opacity:\"show\"},fadeOut:{opacity:\"hide\"},fadeToggle:{opacity:\"toggle\"}},function(e,t){pe.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),pe.timers=[],pe.fx.tick=function(){var e,t=pe.timers,n=0;for(Nt=pe.now();n<t.length;n++)e=t[n],e()||t[n]!==e||t.splice(n--,1);t.length||pe.fx.stop(),Nt=void 0},pe.fx.timer=function(e){pe.timers.push(e),e()?pe.fx.start():pe.timers.pop()},pe.fx.interval=13,pe.fx.start=function(){kt||(kt=e.setInterval(pe.fx.tick,pe.fx.interval))},pe.fx.stop=function(){e.clearInterval(kt),kt=null},pe.fx.speeds={slow:600,fast:200,_default:400},pe.fn.delay=function(t,n){return t=pe.fx?pe.fx.speeds[t]||t:t,n=n||\"fx\",this.queue(n,function(n,r){var i=e.setTimeout(n,t);r.stop=function(){e.clearTimeout(i)}})},function(){var e,t=re.createElement(\"input\"),n=re.createElement(\"div\"),r=re.createElement(\"select\"),i=r.appendChild(re.createElement(\"option\"));n=re.createElement(\"div\"),n.setAttribute(\"className\",\"t\"),n.innerHTML=\"  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>\",e=n.getElementsByTagName(\"a\")[0],t.setAttribute(\"type\",\"checkbox\"),n.appendChild(t),e=n.getElementsByTagName(\"a\")[0],e.style.cssText=\"top:1px\",fe.getSetAttribute=\"t\"!==n.className,fe.style=/top/.test(e.getAttribute(\"style\")),fe.hrefNormalized=\"/a\"===e.getAttribute(\"href\"),fe.checkOn=!!t.value,fe.optSelected=i.selected,fe.enctype=!!re.createElement(\"form\").enctype,r.disabled=!0,fe.optDisabled=!i.disabled,t=re.createElement(\"input\"),t.setAttribute(\"value\",\"\"),fe.input=\"\"===t.getAttribute(\"value\"),t.value=\"t\",t.setAttribute(\"type\",\"radio\"),fe.radioValue=\"t\"===t.value}();var Dt=/\\r/g,jt=/[\\x20\\t\\r\\n\\f]+/g;pe.fn.extend({val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=pe.isFunction(e),this.each(function(n){var i;1===this.nodeType&&(i=r?e.call(this,n,pe(this).val()):e,null==i?i=\"\":\"number\"==typeof i?i+=\"\":pe.isArray(i)&&(i=pe.map(i,function(e){return null==e?\"\":e+\"\"})),t=pe.valHooks[this.type]||pe.valHooks[this.nodeName.toLowerCase()],t&&\"set\"in t&&void 0!==t.set(this,i,\"value\")||(this.value=i))});if(i)return t=pe.valHooks[i.type]||pe.valHooks[i.nodeName.toLowerCase()],t&&\"get\"in t&&void 0!==(n=t.get(i,\"value\"))?n:(n=i.value,\"string\"==typeof n?n.replace(Dt,\"\"):null==n?\"\":n)}}}),pe.extend({valHooks:{option:{get:function(e){var t=pe.find.attr(e,\"value\");return null!=t?t:pe.trim(pe.text(e)).replace(jt,\" \")}},select:{get:function(e){for(var t,n,r=e.options,i=e.selectedIndex,o=\"select-one\"===e.type||i<0,a=o?null:[],s=o?i+1:r.length,u=i<0?s:o?i:0;u<s;u++)if(n=r[u],(n.selected||u===i)&&(fe.optDisabled?!n.disabled:null===n.getAttribute(\"disabled\"))&&(!n.parentNode.disabled||!pe.nodeName(n.parentNode,\"optgroup\"))){if(t=pe(n).val(),o)return t;a.push(t)}return a},set:function(e,t){for(var n,r,i=e.options,o=pe.makeArray(t),a=i.length;a--;)if(r=i[a],pe.inArray(pe.valHooks.option.get(r),o)>-1)try{r.selected=n=!0}catch(s){r.scrollHeight}else r.selected=!1;return n||(e.selectedIndex=-1),i}}}}),pe.each([\"radio\",\"checkbox\"],function(){pe.valHooks[this]={set:function(e,t){if(pe.isArray(t))return e.checked=pe.inArray(pe(e).val(),t)>-1}},fe.checkOn||(pe.valHooks[this].get=function(e){return null===e.getAttribute(\"value\")?\"on\":e.value})});var Lt,Ht,qt=pe.expr.attrHandle,_t=/^(?:checked|selected)$/i,Ft=fe.getSetAttribute,Mt=fe.input;pe.fn.extend({attr:function(e,t){return Pe(this,pe.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){pe.removeAttr(this,e)})}}),pe.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return\"undefined\"==typeof e.getAttribute?pe.prop(e,t,n):(1===o&&pe.isXMLDoc(e)||(t=t.toLowerCase(),i=pe.attrHooks[t]||(pe.expr.match.bool.test(t)?Ht:Lt)),void 0!==n?null===n?void pe.removeAttr(e,t):i&&\"set\"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+\"\"),n):i&&\"get\"in i&&null!==(r=i.get(e,t))?r:(r=pe.find.attr(e,t),null==r?void 0:r))},attrHooks:{type:{set:function(e,t){if(!fe.radioValue&&\"radio\"===t&&pe.nodeName(e,\"input\")){var n=e.value;return e.setAttribute(\"type\",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(De);if(o&&1===e.nodeType)for(;n=o[i++];)r=pe.propFix[n]||n,pe.expr.match.bool.test(n)?Mt&&Ft||!_t.test(n)?e[r]=!1:e[pe.camelCase(\"default-\"+n)]=e[r]=!1:pe.attr(e,n,\"\"),e.removeAttribute(Ft?n:r)}}),Ht={set:function(e,t,n){return t===!1?pe.removeAttr(e,n):Mt&&Ft||!_t.test(n)?e.setAttribute(!Ft&&pe.propFix[n]||n,n):e[pe.camelCase(\"default-\"+n)]=e[n]=!0,n}},pe.each(pe.expr.match.bool.source.match(/\\w+/g),function(e,t){var n=qt[t]||pe.find.attr;Mt&&Ft||!_t.test(t)?qt[t]=function(e,t,r){var i,o;return r||(o=qt[t],qt[t]=i,i=null!=n(e,t,r)?t.toLowerCase():null,qt[t]=o),i}:qt[t]=function(e,t,n){if(!n)return e[pe.camelCase(\"default-\"+t)]?t.toLowerCase():null}}),Mt&&Ft||(pe.attrHooks.value={set:function(e,t,n){return pe.nodeName(e,\"input\")?void(e.defaultValue=t):Lt&&Lt.set(e,t,n)}}),Ft||(Lt={set:function(e,t,n){var r=e.getAttributeNode(n);if(r||e.setAttributeNode(r=e.ownerDocument.createAttribute(n)),r.value=t+=\"\",\"value\"===n||t===e.getAttribute(n))return t}},qt.id=qt.name=qt.coords=function(e,t,n){var r;if(!n)return(r=e.getAttributeNode(t))&&\"\"!==r.value?r.value:null},pe.valHooks.button={get:function(e,t){var n=e.getAttributeNode(t);if(n&&n.specified)return n.value},set:Lt.set},pe.attrHooks.contenteditable={set:function(e,t,n){Lt.set(e,\"\"!==t&&t,n)}},pe.each([\"width\",\"height\"],function(e,t){pe.attrHooks[t]={set:function(e,n){if(\"\"===n)return e.setAttribute(t,\"auto\"),n}}})),fe.style||(pe.attrHooks.style={get:function(e){return e.style.cssText||void 0},set:function(e,t){return e.style.cssText=t+\"\"}});var Ot=/^(?:input|select|textarea|button|object)$/i,Rt=/^(?:a|area)$/i;pe.fn.extend({prop:function(e,t){return Pe(this,pe.prop,e,t,arguments.length>1)},removeProp:function(e){return e=pe.propFix[e]||e,this.each(function(){try{this[e]=void 0,delete this[e]}catch(t){}})}}),pe.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&pe.isXMLDoc(e)||(t=pe.propFix[t]||t,i=pe.propHooks[t]),void 0!==n?i&&\"set\"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&\"get\"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=pe.find.attr(e,\"tabindex\");return t?parseInt(t,10):Ot.test(e.nodeName)||Rt.test(e.nodeName)&&e.href?0:-1}}},propFix:{\"for\":\"htmlFor\",\"class\":\"className\"}}),fe.hrefNormalized||pe.each([\"href\",\"src\"],function(e,t){pe.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}}),fe.optSelected||(pe.propHooks.selected={get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),pe.each([\"tabIndex\",\"readOnly\",\"maxLength\",\"cellSpacing\",\"cellPadding\",\"rowSpan\",\"colSpan\",\"useMap\",\"frameBorder\",\"contentEditable\"],function(){pe.propFix[this.toLowerCase()]=this}),fe.enctype||(pe.propFix.enctype=\"encoding\");var Pt=/[\\t\\r\\n\\f]/g;pe.fn.extend({addClass:function(e){var t,n,r,i,o,a,s,u=0;if(pe.isFunction(e))return this.each(function(t){pe(this).addClass(e.call(this,t,z(this)))});if(\"string\"==typeof e&&e)for(t=e.match(De)||[];n=this[u++];)if(i=z(n),r=1===n.nodeType&&(\" \"+i+\" \").replace(Pt,\" \")){for(a=0;o=t[a++];)r.indexOf(\" \"+o+\" \")<0&&(r+=o+\" \");s=pe.trim(r),i!==s&&pe.attr(n,\"class\",s)}return this},removeClass:function(e){var t,n,r,i,o,a,s,u=0;if(pe.isFunction(e))return this.each(function(t){pe(this).removeClass(e.call(this,t,z(this)))});if(!arguments.length)return this.attr(\"class\",\"\");if(\"string\"==typeof e&&e)for(t=e.match(De)||[];n=this[u++];)if(i=z(n),r=1===n.nodeType&&(\" \"+i+\" \").replace(Pt,\" \")){for(a=0;o=t[a++];)for(;r.indexOf(\" \"+o+\" \")>-1;)r=r.replace(\" \"+o+\" \",\" \");s=pe.trim(r),i!==s&&pe.attr(n,\"class\",s)}return this},toggleClass:function(e,t){var n=typeof e;return\"boolean\"==typeof t&&\"string\"===n?t?this.addClass(e):this.removeClass(e):pe.isFunction(e)?this.each(function(n){pe(this).toggleClass(e.call(this,n,z(this),t),t)}):this.each(function(){var t,r,i,o;if(\"string\"===n)for(r=0,i=pe(this),o=e.match(De)||[];t=o[r++];)i.hasClass(t)?i.removeClass(t):i.addClass(t);else void 0!==e&&\"boolean\"!==n||(t=z(this),t&&pe._data(this,\"__className__\",t),pe.attr(this,\"class\",t||e===!1?\"\":pe._data(this,\"__className__\")||\"\"))})},hasClass:function(e){var t,n,r=0;for(t=\" \"+e+\" \";n=this[r++];)if(1===n.nodeType&&(\" \"+z(n)+\" \").replace(Pt,\" \").indexOf(t)>-1)return!0;return!1}}),pe.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){pe.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),pe.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}});var Bt=e.location,Wt=pe.now(),It=/\\?/,$t=/(,)|(\\[|{)|(}|])|\"(?:[^\"\\\\\\r\\n]|\\\\[\"\\\\\\/bfnrt]|\\\\u[\\da-fA-F]{4})*\"\\s*:?|true|false|null|-?(?!0\\d)\\d+(?:\\.\\d+|)(?:[eE][+-]?\\d+|)/g;pe.parseJSON=function(t){if(e.JSON&&e.JSON.parse)return e.JSON.parse(t+\"\");var n,r=null,i=pe.trim(t+\"\");return i&&!pe.trim(i.replace($t,function(e,t,i,o){return n&&t&&(r=0),0===r?e:(n=i||t,r+=!o-!i,\"\")}))?Function(\"return \"+i)():pe.error(\"Invalid JSON: \"+t)},pe.parseXML=function(t){var n,r;if(!t||\"string\"!=typeof t)return null;try{e.DOMParser?(r=new e.DOMParser,n=r.parseFromString(t,\"text/xml\")):(n=new e.ActiveXObject(\"Microsoft.XMLDOM\"),n.async=\"false\",n.loadXML(t))}catch(i){n=void 0}return n&&n.documentElement&&!n.getElementsByTagName(\"parsererror\").length||pe.error(\"Invalid XML: \"+t),n};var zt=/#.*$/,Xt=/([?&])_=[^&]*/,Ut=/^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/gm,Vt=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Yt=/^(?:GET|HEAD)$/,Jt=/^\\/\\//,Gt=/^([\\w.+-]+:)(?:\\/\\/(?:[^\\/?#]*@|)([^\\/?#:]*)(?::(\\d+)|)|)/,Kt={},Qt={},Zt=\"*/\".concat(\"*\"),en=Bt.href,tn=Gt.exec(en.toLowerCase())||[];pe.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:en,type:\"GET\",isLocal:Vt.test(tn[1]),global:!0,processData:!0,async:!0,contentType:\"application/x-www-form-urlencoded; charset=UTF-8\",accepts:{\"*\":Zt,text:\"text/plain\",html:\"text/html\",xml:\"application/xml, text/xml\",json:\"application/json, text/javascript\"},contents:{xml:/\\bxml\\b/,html:/\\bhtml/,json:/\\bjson\\b/},responseFields:{xml:\"responseXML\",text:\"responseText\",json:\"responseJSON\"},converters:{\"* text\":String,\"text html\":!0,\"text json\":pe.parseJSON,\"text xml\":pe.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?V(V(e,pe.ajaxSettings),t):V(pe.ajaxSettings,e)},ajaxPrefilter:X(Kt),ajaxTransport:X(Qt),ajax:function(t,n){function r(t,n,r,i){var o,f,v,x,w,C=n;2!==b&&(b=2,u&&e.clearTimeout(u),c=void 0,s=i||\"\",T.readyState=t>0?4:0,o=t>=200&&t<300||304===t,r&&(x=Y(d,T,r)),x=J(d,x,T,o),o?(d.ifModified&&(w=T.getResponseHeader(\"Last-Modified\"),w&&(pe.lastModified[a]=w),w=T.getResponseHeader(\"etag\"),w&&(pe.etag[a]=w)),204===t||\"HEAD\"===d.type?C=\"nocontent\":304===t?C=\"notmodified\":(C=x.state,f=x.data,v=x.error,o=!v)):(v=C,!t&&C||(C=\"error\",t<0&&(t=0))),T.status=t,T.statusText=(n||C)+\"\",o?g.resolveWith(p,[f,C,T]):g.rejectWith(p,[T,C,v]),T.statusCode(y),y=void 0,l&&h.trigger(o?\"ajaxSuccess\":\"ajaxError\",[T,d,o?f:v]),m.fireWith(p,[T,C]),l&&(h.trigger(\"ajaxComplete\",[T,d]),--pe.active||pe.event.trigger(\"ajaxStop\")))}\"object\"==typeof t&&(n=t,t=void 0),n=n||{};var i,o,a,s,u,l,c,f,d=pe.ajaxSetup({},n),p=d.context||d,h=d.context&&(p.nodeType||p.jquery)?pe(p):pe.event,g=pe.Deferred(),m=pe.Callbacks(\"once memory\"),y=d.statusCode||{},v={},x={},b=0,w=\"canceled\",T={readyState:0,getResponseHeader:function(e){var t;if(2===b){if(!f)for(f={};t=Ut.exec(s);)f[t[1].toLowerCase()]=t[2];t=f[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===b?s:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return b||(e=x[n]=x[n]||e,v[e]=t),this},overrideMimeType:function(e){return b||(d.mimeType=e),this},statusCode:function(e){var t;if(e)if(b<2)for(t in e)y[t]=[y[t],e[t]];else T.always(e[T.status]);return this},abort:function(e){var t=e||w;return c&&c.abort(t),r(0,t),this}};if(g.promise(T).complete=m.add,T.success=T.done,T.error=T.fail,d.url=((t||d.url||en)+\"\").replace(zt,\"\").replace(Jt,tn[1]+\"//\"),d.type=n.method||n.type||d.method||d.type,d.dataTypes=pe.trim(d.dataType||\"*\").toLowerCase().match(De)||[\"\"],null==d.crossDomain&&(i=Gt.exec(d.url.toLowerCase()),d.crossDomain=!(!i||i[1]===tn[1]&&i[2]===tn[2]&&(i[3]||(\"http:\"===i[1]?\"80\":\"443\"))===(tn[3]||(\"http:\"===tn[1]?\"80\":\"443\")))),d.data&&d.processData&&\"string\"!=typeof d.data&&(d.data=pe.param(d.data,d.traditional)),U(Kt,d,n,T),2===b)return T;l=pe.event&&d.global,l&&0===pe.active++&&pe.event.trigger(\"ajaxStart\"),d.type=d.type.toUpperCase(),d.hasContent=!Yt.test(d.type),a=d.url,d.hasContent||(d.data&&(a=d.url+=(It.test(a)?\"&\":\"?\")+d.data,delete d.data),d.cache===!1&&(d.url=Xt.test(a)?a.replace(Xt,\"$1_=\"+Wt++):a+(It.test(a)?\"&\":\"?\")+\"_=\"+Wt++)),d.ifModified&&(pe.lastModified[a]&&T.setRequestHeader(\"If-Modified-Since\",pe.lastModified[a]),pe.etag[a]&&T.setRequestHeader(\"If-None-Match\",pe.etag[a])),(d.data&&d.hasContent&&d.contentType!==!1||n.contentType)&&T.setRequestHeader(\"Content-Type\",d.contentType),T.setRequestHeader(\"Accept\",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(\"*\"!==d.dataTypes[0]?\", \"+Zt+\"; q=0.01\":\"\"):d.accepts[\"*\"]);for(o in d.headers)T.setRequestHeader(o,d.headers[o]);if(d.beforeSend&&(d.beforeSend.call(p,T,d)===!1||2===b))return T.abort();w=\"abort\";for(o in{success:1,error:1,complete:1})T[o](d[o]);if(c=U(Qt,d,n,T)){if(T.readyState=1,l&&h.trigger(\"ajaxSend\",[T,d]),2===b)return T;d.async&&d.timeout>0&&(u=e.setTimeout(function(){T.abort(\"timeout\")},d.timeout));try{b=1,c.send(v,r)}catch(C){if(!(b<2))throw C;r(-1,C)}}else r(-1,\"No Transport\");return T},getJSON:function(e,t,n){return pe.get(e,t,n,\"json\")},getScript:function(e,t){return pe.get(e,void 0,t,\"script\")}}),pe.each([\"get\",\"post\"],function(e,t){pe[t]=function(e,n,r,i){return pe.isFunction(n)&&(i=i||r,r=n,n=void 0),pe.ajax(pe.extend({url:e,type:t,dataType:i,data:n,success:r},pe.isPlainObject(e)&&e))}}),pe._evalUrl=function(e){return pe.ajax({url:e,type:\"GET\",dataType:\"script\",cache:!0,async:!1,global:!1,\"throws\":!0})},pe.fn.extend({wrapAll:function(e){if(pe.isFunction(e))return this.each(function(t){pe(this).wrapAll(e.call(this,t))});if(this[0]){var t=pe(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){for(var e=this;e.firstChild&&1===e.firstChild.nodeType;)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return pe.isFunction(e)?this.each(function(t){pe(this).wrapInner(e.call(this,t))}):this.each(function(){var t=pe(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=pe.isFunction(e);return this.each(function(n){pe(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){pe.nodeName(this,\"body\")||pe(this).replaceWith(this.childNodes)}).end()}}),pe.expr.filters.hidden=function(e){return fe.reliableHiddenOffsets()?e.offsetWidth<=0&&e.offsetHeight<=0&&!e.getClientRects().length:K(e)},pe.expr.filters.visible=function(e){return!pe.expr.filters.hidden(e)};var nn=/%20/g,rn=/\\[\\]$/,on=/\\r?\\n/g,an=/^(?:submit|button|image|reset|file)$/i,sn=/^(?:input|select|textarea|keygen)/i;pe.param=function(e,t){var n,r=[],i=function(e,t){t=pe.isFunction(t)?t():null==t?\"\":t,r[r.length]=encodeURIComponent(e)+\"=\"+encodeURIComponent(t)};if(void 0===t&&(t=pe.ajaxSettings&&pe.ajaxSettings.traditional),pe.isArray(e)||e.jquery&&!pe.isPlainObject(e))pe.each(e,function(){i(this.name,this.value)});else for(n in e)Q(n,e[n],t,i);return r.join(\"&\").replace(nn,\"+\")},pe.fn.extend({serialize:function(){return pe.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=pe.prop(this,\"elements\");return e?pe.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!pe(this).is(\":disabled\")&&sn.test(this.nodeName)&&!an.test(e)&&(this.checked||!Be.test(e))}).map(function(e,t){var n=pe(this).val();return null==n?null:pe.isArray(n)?pe.map(n,function(e){return{name:t.name,value:e.replace(on,\"\\r\\n\")}}):{name:t.name,value:n.replace(on,\"\\r\\n\")}}).get()}}),pe.ajaxSettings.xhr=void 0!==e.ActiveXObject?function(){return this.isLocal?ee():re.documentMode>8?Z():/^(get|post|head|put|delete|options)$/i.test(this.type)&&Z()||ee()}:Z;var un=0,ln={},cn=pe.ajaxSettings.xhr();e.attachEvent&&e.attachEvent(\"onunload\",function(){for(var e in ln)ln[e](void 0,!0)}),fe.cors=!!cn&&\"withCredentials\"in cn,cn=fe.ajax=!!cn,cn&&pe.ajaxTransport(function(t){if(!t.crossDomain||fe.cors){var n;return{send:function(r,i){var o,a=t.xhr(),s=++un;if(a.open(t.type,t.url,t.async,t.username,t.password),t.xhrFields)for(o in t.xhrFields)a[o]=t.xhrFields[o];t.mimeType&&a.overrideMimeType&&a.overrideMimeType(t.mimeType),t.crossDomain||r[\"X-Requested-With\"]||(r[\"X-Requested-With\"]=\"XMLHttpRequest\");for(o in r)void 0!==r[o]&&a.setRequestHeader(o,r[o]+\"\");a.send(t.hasContent&&t.data||null),n=function(e,r){var o,u,l;if(n&&(r||4===a.readyState))if(delete ln[s],n=void 0,a.onreadystatechange=pe.noop,r)4!==a.readyState&&a.abort();else{l={},o=a.status,\"string\"==typeof a.responseText&&(l.text=a.responseText);try{u=a.statusText}catch(c){u=\"\"}o||!t.isLocal||t.crossDomain?1223===o&&(o=204):o=l.text?200:404}l&&i(o,u,l,a.getAllResponseHeaders())},t.async?4===a.readyState?e.setTimeout(n):a.onreadystatechange=ln[s]=n:n()},abort:function(){n&&n(void 0,!0)}}}}),pe.ajaxSetup({accepts:{script:\"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"},contents:{script:/\\b(?:java|ecma)script\\b/},converters:{\"text script\":function(e){return pe.globalEval(e),e}}}),pe.ajaxPrefilter(\"script\",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type=\"GET\",e.global=!1)}),pe.ajaxTransport(\"script\",function(e){if(e.crossDomain){var t,n=re.head||pe(\"head\")[0]||re.documentElement;return{send:function(r,i){t=re.createElement(\"script\"),t.async=!0,e.scriptCharset&&(t.charset=e.scriptCharset),t.src=e.url,t.onload=t.onreadystatechange=function(e,n){(n||!t.readyState||/loaded|complete/.test(t.readyState))&&(t.onload=t.onreadystatechange=null,t.parentNode&&t.parentNode.removeChild(t),t=null,n||i(200,\"success\"))},n.insertBefore(t,n.firstChild)},abort:function(){t&&t.onload(void 0,!0)}}}});var fn=[],dn=/(=)\\?(?=&|$)|\\?\\?/;pe.ajaxSetup({jsonp:\"callback\",jsonpCallback:function(){var e=fn.pop()||pe.expando+\"_\"+Wt++;return this[e]=!0,e}}),pe.ajaxPrefilter(\"json jsonp\",function(t,n,r){var i,o,a,s=t.jsonp!==!1&&(dn.test(t.url)?\"url\":\"string\"==typeof t.data&&0===(t.contentType||\"\").indexOf(\"application/x-www-form-urlencoded\")&&dn.test(t.data)&&\"data\");if(s||\"jsonp\"===t.dataTypes[0])return i=t.jsonpCallback=pe.isFunction(t.jsonpCallback)?t.jsonpCallback():t.jsonpCallback,s?t[s]=t[s].replace(dn,\"$1\"+i):t.jsonp!==!1&&(t.url+=(It.test(t.url)?\"&\":\"?\")+t.jsonp+\"=\"+i),t.converters[\"script json\"]=function(){return a||pe.error(i+\" was not called\"),a[0]},t.dataTypes[0]=\"json\",o=e[i],e[i]=function(){a=arguments},r.always(function(){void 0===o?pe(e).removeProp(i):e[i]=o,t[i]&&(t.jsonpCallback=n.jsonpCallback,fn.push(i)),a&&pe.isFunction(o)&&o(a[0]),a=o=void 0}),\"script\"}),pe.parseHTML=function(e,t,n){if(!e||\"string\"!=typeof e)return null;\"boolean\"==typeof t&&(n=t,t=!1),t=t||re;var r=Te.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=y([e],t,i),i&&i.length&&pe(i).remove(),pe.merge([],r.childNodes))};var pn=pe.fn.load;return pe.fn.load=function(e,t,n){if(\"string\"!=typeof e&&pn)return pn.apply(this,arguments);var r,i,o,a=this,s=e.indexOf(\" \");return s>-1&&(r=pe.trim(e.slice(s,e.length)),e=e.slice(0,s)),pe.isFunction(t)?(n=t,t=void 0):t&&\"object\"==typeof t&&(i=\"POST\"),a.length>0&&pe.ajax({url:e,type:i||\"GET\",dataType:\"html\",data:t}).done(function(e){o=arguments,a.html(r?pe(\"<div>\").append(pe.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},pe.each([\"ajaxStart\",\"ajaxStop\",\"ajaxComplete\",\"ajaxError\",\"ajaxSuccess\",\"ajaxSend\"],function(e,t){pe.fn[t]=function(e){return this.on(t,e)}}),pe.expr.filters.animated=function(e){return pe.grep(pe.timers,function(t){return e===t.elem}).length},pe.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l,c=pe.css(e,\"position\"),f=pe(e),d={};\"static\"===c&&(e.style.position=\"relative\"),s=f.offset(),o=pe.css(e,\"top\"),u=pe.css(e,\"left\"),l=(\"absolute\"===c||\"fixed\"===c)&&pe.inArray(\"auto\",[o,u])>-1,l?(r=f.position(),a=r.top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),pe.isFunction(t)&&(t=t.call(e,n,pe.extend({},s))),null!=t.top&&(d.top=t.top-s.top+a),null!=t.left&&(d.left=t.left-s.left+i),\"using\"in t?t.using.call(e,d):f.css(d)}},pe.fn.extend({offset:function(e){if(arguments.length)return void 0===e?this:this.each(function(t){pe.offset.setOffset(this,e,t)});var t,n,r={top:0,left:0},i=this[0],o=i&&i.ownerDocument;if(o)return t=o.documentElement,pe.contains(t,i)?(\"undefined\"!=typeof i.getBoundingClientRect&&(r=i.getBoundingClientRect()),n=te(o),{top:r.top+(n.pageYOffset||t.scrollTop)-(t.clientTop||0),left:r.left+(n.pageXOffset||t.scrollLeft)-(t.clientLeft||0)}):r},position:function(){if(this[0]){var e,t,n={top:0,left:0},r=this[0];return\"fixed\"===pe.css(r,\"position\")?t=r.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),pe.nodeName(e[0],\"html\")||(n=e.offset()),n.top+=pe.css(e[0],\"borderTopWidth\",!0),n.left+=pe.css(e[0],\"borderLeftWidth\",!0)),{top:t.top-n.top-pe.css(r,\"marginTop\",!0),left:t.left-n.left-pe.css(r,\"marginLeft\",!0)}}},offsetParent:function(){return this.map(function(){\nfor(var e=this.offsetParent;e&&!pe.nodeName(e,\"html\")&&\"static\"===pe.css(e,\"position\");)e=e.offsetParent;return e||pt})}}),pe.each({scrollLeft:\"pageXOffset\",scrollTop:\"pageYOffset\"},function(e,t){var n=/Y/.test(t);pe.fn[e]=function(r){return Pe(this,function(e,r,i){var o=te(e);return void 0===i?o?t in o?o[t]:o.document.documentElement[r]:e[r]:void(o?o.scrollTo(n?pe(o).scrollLeft():i,n?i:pe(o).scrollTop()):e[r]=i)},e,r,arguments.length,null)}}),pe.each([\"top\",\"left\"],function(e,t){pe.cssHooks[t]=L(fe.pixelPosition,function(e,n){if(n)return n=gt(e,t),ft.test(n)?pe(e).position()[t]+\"px\":n})}),pe.each({Height:\"height\",Width:\"width\"},function(e,t){pe.each({padding:\"inner\"+e,content:t,\"\":\"outer\"+e},function(n,r){pe.fn[r]=function(r,i){var o=arguments.length&&(n||\"boolean\"!=typeof r),a=n||(r===!0||i===!0?\"margin\":\"border\");return Pe(this,function(t,n,r){var i;return pe.isWindow(t)?t.document.documentElement[\"client\"+e]:9===t.nodeType?(i=t.documentElement,Math.max(t.body[\"scroll\"+e],i[\"scroll\"+e],t.body[\"offset\"+e],i[\"offset\"+e],i[\"client\"+e])):void 0===r?pe.css(t,n,a):pe.style(t,n,r,a)},t,o?r:void 0,o,null)}})}),pe.fn.extend({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)}}),pe.fn.size=function(){return this.length},pe.fn.andSelf=pe.fn.addBack,layui.define(function(e){layui.$=pe,e(\"jquery\",pe)}),pe});!function(e,t){\"use strict\";var i,n,a=e.layui&&layui.define,o={getPath:function(){var e=document.currentScript?document.currentScript.src:function(){for(var e,t=document.scripts,i=t.length-1,n=i;n>0;n--)if(\"interactive\"===t[n].readyState){e=t[n].src;break}return e||t[i].src}();return e.substring(0,e.lastIndexOf(\"/\")+1)}(),config:{},end:{},minIndex:0,minLeft:[],btn:[\"&#x786E;&#x5B9A;\",\"&#x53D6;&#x6D88;\"],type:[\"dialog\",\"page\",\"iframe\",\"loading\",\"tips\"],getStyle:function(t,i){var n=t.currentStyle?t.currentStyle:e.getComputedStyle(t,null);return n[n.getPropertyValue?\"getPropertyValue\":\"getAttribute\"](i)},link:function(t,i,n){if(r.path){var a=document.getElementsByTagName(\"head\")[0],s=document.createElement(\"link\");\"string\"==typeof i&&(n=i);var l=(n||t).replace(/\\.|\\//g,\"\"),f=\"layuicss-\"+l,c=0;s.rel=\"stylesheet\",s.href=r.path+t,s.id=f,document.getElementById(f)||a.appendChild(s),\"function\"==typeof i&&!function u(){return++c>80?e.console&&console.error(\"layer.css: Invalid\"):void(1989===parseInt(o.getStyle(document.getElementById(f),\"width\"))?i():setTimeout(u,100))}()}}},r={v:\"3.1.1\",ie:function(){var t=navigator.userAgent.toLowerCase();return!!(e.ActiveXObject||\"ActiveXObject\"in e)&&((t.match(/msie\\s(\\d+)/)||[])[1]||\"11\")}(),index:e.layer&&e.layer.v?1e5:0,path:o.getPath,config:function(e,t){return e=e||{},r.cache=o.config=i.extend({},o.config,e),r.path=o.config.path||r.path,\"string\"==typeof e.extend&&(e.extend=[e.extend]),o.config.path&&r.ready(),e.extend?(a?layui.addcss(\"modules/layer/\"+e.extend):o.link(\"theme/\"+e.extend),this):this},ready:function(e){var t=\"layer\",i=\"\",n=(a?\"modules/layer/\":\"theme/\")+\"default/layer.css?v=\"+r.v+i;return a?layui.addcss(n,e,t):o.link(n,e,t),this},alert:function(e,t,n){var a=\"function\"==typeof t;return a&&(n=t),r.open(i.extend({content:e,yes:n},a?{}:t))},confirm:function(e,t,n,a){var s=\"function\"==typeof t;return s&&(a=n,n=t),r.open(i.extend({content:e,btn:o.btn,yes:n,btn2:a},s?{}:t))},msg:function(e,n,a){var s=\"function\"==typeof n,f=o.config.skin,c=(f?f+\" \"+f+\"-msg\":\"\")||\"layui-layer-msg\",u=l.anim.length-1;return s&&(a=n),r.open(i.extend({content:e,time:3e3,shade:!1,skin:c,title:!1,closeBtn:!1,btn:!1,resize:!1,end:a},s&&!o.config.skin?{skin:c+\" layui-layer-hui\",anim:u}:function(){return n=n||{},(n.icon===-1||n.icon===t&&!o.config.skin)&&(n.skin=c+\" \"+(n.skin||\"layui-layer-hui\")),n}()))},load:function(e,t){return r.open(i.extend({type:3,icon:e||0,resize:!1,shade:.01},t))},tips:function(e,t,n){return r.open(i.extend({type:4,content:[e,t],closeBtn:!1,time:3e3,shade:!1,resize:!1,fixed:!1,maxWidth:210},n))}},s=function(e){var t=this;t.index=++r.index,t.config=i.extend({},t.config,o.config,e),document.body?t.creat():setTimeout(function(){t.creat()},30)};s.pt=s.prototype;var l=[\"layui-layer\",\".layui-layer-title\",\".layui-layer-main\",\".layui-layer-dialog\",\"layui-layer-iframe\",\"layui-layer-content\",\"layui-layer-btn\",\"layui-layer-close\"];l.anim=[\"layer-anim-00\",\"layer-anim-01\",\"layer-anim-02\",\"layer-anim-03\",\"layer-anim-04\",\"layer-anim-05\",\"layer-anim-06\"],s.pt.config={type:0,shade:.3,fixed:!0,move:l[1],title:\"&#x4FE1;&#x606F;\",offset:\"auto\",area:\"auto\",closeBtn:1,time:0,zIndex:19891014,maxWidth:360,anim:0,isOutAnim:!0,icon:-1,moveType:1,resize:!0,scrollbar:!0,tips:2},s.pt.vessel=function(e,t){var n=this,a=n.index,r=n.config,s=r.zIndex+a,f=\"object\"==typeof r.title,c=r.maxmin&&(1===r.type||2===r.type),u=r.title?'<div class=\"layui-layer-title\" style=\"'+(f?r.title[1]:\"\")+'\">'+(f?r.title[0]:r.title)+\"</div>\":\"\";return r.zIndex=s,t([r.shade?'<div class=\"layui-layer-shade\" id=\"layui-layer-shade'+a+'\" times=\"'+a+'\" style=\"'+(\"z-index:\"+(s-1)+\"; \")+'\"></div>':\"\",'<div class=\"'+l[0]+(\" layui-layer-\"+o.type[r.type])+(0!=r.type&&2!=r.type||r.shade?\"\":\" layui-layer-border\")+\" \"+(r.skin||\"\")+'\" id=\"'+l[0]+a+'\" type=\"'+o.type[r.type]+'\" times=\"'+a+'\" showtime=\"'+r.time+'\" conType=\"'+(e?\"object\":\"string\")+'\" style=\"z-index: '+s+\"; width:\"+r.area[0]+\";height:\"+r.area[1]+(r.fixed?\"\":\";position:absolute;\")+'\">'+(e&&2!=r.type?\"\":u)+'<div id=\"'+(r.id||\"\")+'\" class=\"layui-layer-content'+(0==r.type&&r.icon!==-1?\" layui-layer-padding\":\"\")+(3==r.type?\" layui-layer-loading\"+r.icon:\"\")+'\">'+(0==r.type&&r.icon!==-1?'<i class=\"layui-layer-ico layui-layer-ico'+r.icon+'\"></i>':\"\")+(1==r.type&&e?\"\":r.content||\"\")+'</div><span class=\"layui-layer-setwin\">'+function(){var e=c?'<a class=\"layui-layer-min\" href=\"javascript:;\"><cite></cite></a><a class=\"layui-layer-ico layui-layer-max\" href=\"javascript:;\"></a>':\"\";return r.closeBtn&&(e+='<a class=\"layui-layer-ico '+l[7]+\" \"+l[7]+(r.title?r.closeBtn:4==r.type?\"1\":\"2\")+'\" href=\"javascript:;\"></a>'),e}()+\"</span>\"+(r.btn?function(){var e=\"\";\"string\"==typeof r.btn&&(r.btn=[r.btn]);for(var t=0,i=r.btn.length;t<i;t++)e+='<a class=\"'+l[6]+t+'\">'+r.btn[t]+\"</a>\";return'<div class=\"'+l[6]+\" layui-layer-btn-\"+(r.btnAlign||\"\")+'\">'+e+\"</div>\"}():\"\")+(r.resize?'<span class=\"layui-layer-resize\"></span>':\"\")+\"</div>\"],u,i('<div class=\"layui-layer-move\"></div>')),n},s.pt.creat=function(){var e=this,t=e.config,a=e.index,s=t.content,f=\"object\"==typeof s,c=i(\"body\");if(!t.id||!i(\"#\"+t.id)[0]){switch(\"string\"==typeof t.area&&(t.area=\"auto\"===t.area?[\"\",\"\"]:[t.area,\"\"]),t.shift&&(t.anim=t.shift),6==r.ie&&(t.fixed=!1),t.type){case 0:t.btn=\"btn\"in t?t.btn:o.btn[0],r.closeAll(\"dialog\");break;case 2:var s=t.content=f?t.content:[t.content||\"http://layer.layui.com\",\"auto\"];t.content='<iframe scrolling=\"'+(t.content[1]||\"auto\")+'\" allowtransparency=\"true\" id=\"'+l[4]+a+'\" name=\"'+l[4]+a+'\" onload=\"this.className=\\'\\';\" class=\"layui-layer-load\" frameborder=\"0\" src=\"'+t.content[0]+'\"></iframe>';break;case 3:delete t.title,delete t.closeBtn,t.icon===-1&&0===t.icon,r.closeAll(\"loading\");break;case 4:f||(t.content=[t.content,\"body\"]),t.follow=t.content[1],t.content=t.content[0]+'<i class=\"layui-layer-TipsG\"></i>',delete t.title,t.tips=\"object\"==typeof t.tips?t.tips:[t.tips,!0],t.tipsMore||r.closeAll(\"tips\")}if(e.vessel(f,function(n,r,u){c.append(n[0]),f?function(){2==t.type||4==t.type?function(){i(\"body\").append(n[1])}():function(){s.parents(\".\"+l[0])[0]||(s.data(\"display\",s.css(\"display\")).show().addClass(\"layui-layer-wrap\").wrap(n[1]),i(\"#\"+l[0]+a).find(\".\"+l[5]).before(r))}()}():c.append(n[1]),i(\".layui-layer-move\")[0]||c.append(o.moveElem=u),e.layero=i(\"#\"+l[0]+a),t.scrollbar||l.html.css(\"overflow\",\"hidden\").attr(\"layer-full\",a)}).auto(a),i(\"#layui-layer-shade\"+e.index).css({\"background-color\":t.shade[1]||\"#000\",opacity:t.shade[0]||t.shade}),2==t.type&&6==r.ie&&e.layero.find(\"iframe\").attr(\"src\",s[0]),4==t.type?e.tips():e.offset(),t.fixed&&n.on(\"resize\",function(){e.offset(),(/^\\d+%$/.test(t.area[0])||/^\\d+%$/.test(t.area[1]))&&e.auto(a),4==t.type&&e.tips()}),t.time<=0||setTimeout(function(){r.close(e.index)},t.time),e.move().callback(),l.anim[t.anim]){var u=\"layer-anim \"+l.anim[t.anim];e.layero.addClass(u).one(\"webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend\",function(){i(this).removeClass(u)})}t.isOutAnim&&e.layero.data(\"isOutAnim\",!0)}},s.pt.auto=function(e){var t=this,a=t.config,o=i(\"#\"+l[0]+e);\"\"===a.area[0]&&a.maxWidth>0&&(r.ie&&r.ie<8&&a.btn&&o.width(o.innerWidth()),o.outerWidth()>a.maxWidth&&o.width(a.maxWidth));var s=[o.innerWidth(),o.innerHeight()],f=o.find(l[1]).outerHeight()||0,c=o.find(\".\"+l[6]).outerHeight()||0,u=function(e){e=o.find(e),e.height(s[1]-f-c-2*(0|parseFloat(e.css(\"padding-top\"))))};switch(a.type){case 2:u(\"iframe\");break;default:\"\"===a.area[1]?a.maxHeight>0&&o.outerHeight()>a.maxHeight?(s[1]=a.maxHeight,u(\".\"+l[5])):a.fixed&&s[1]>=n.height()&&(s[1]=n.height(),u(\".\"+l[5])):u(\".\"+l[5])}return t},s.pt.offset=function(){var e=this,t=e.config,i=e.layero,a=[i.outerWidth(),i.outerHeight()],o=\"object\"==typeof t.offset;e.offsetTop=(n.height()-a[1])/2,e.offsetLeft=(n.width()-a[0])/2,o?(e.offsetTop=t.offset[0],e.offsetLeft=t.offset[1]||e.offsetLeft):\"auto\"!==t.offset&&(\"t\"===t.offset?e.offsetTop=0:\"r\"===t.offset?e.offsetLeft=n.width()-a[0]:\"b\"===t.offset?e.offsetTop=n.height()-a[1]:\"l\"===t.offset?e.offsetLeft=0:\"lt\"===t.offset?(e.offsetTop=0,e.offsetLeft=0):\"lb\"===t.offset?(e.offsetTop=n.height()-a[1],e.offsetLeft=0):\"rt\"===t.offset?(e.offsetTop=0,e.offsetLeft=n.width()-a[0]):\"rb\"===t.offset?(e.offsetTop=n.height()-a[1],e.offsetLeft=n.width()-a[0]):e.offsetTop=t.offset),t.fixed||(e.offsetTop=/%$/.test(e.offsetTop)?n.height()*parseFloat(e.offsetTop)/100:parseFloat(e.offsetTop),e.offsetLeft=/%$/.test(e.offsetLeft)?n.width()*parseFloat(e.offsetLeft)/100:parseFloat(e.offsetLeft),e.offsetTop+=n.scrollTop(),e.offsetLeft+=n.scrollLeft()),i.attr(\"minLeft\")&&(e.offsetTop=n.height()-(i.find(l[1]).outerHeight()||0),e.offsetLeft=i.css(\"left\")),i.css({top:e.offsetTop,left:e.offsetLeft})},s.pt.tips=function(){var e=this,t=e.config,a=e.layero,o=[a.outerWidth(),a.outerHeight()],r=i(t.follow);r[0]||(r=i(\"body\"));var s={width:r.outerWidth(),height:r.outerHeight(),top:r.offset().top,left:r.offset().left},f=a.find(\".layui-layer-TipsG\"),c=t.tips[0];t.tips[1]||f.remove(),s.autoLeft=function(){s.left+o[0]-n.width()>0?(s.tipLeft=s.left+s.width-o[0],f.css({right:12,left:\"auto\"})):s.tipLeft=s.left},s.where=[function(){s.autoLeft(),s.tipTop=s.top-o[1]-10,f.removeClass(\"layui-layer-TipsB\").addClass(\"layui-layer-TipsT\").css(\"border-right-color\",t.tips[1])},function(){s.tipLeft=s.left+s.width+10,s.tipTop=s.top,f.removeClass(\"layui-layer-TipsL\").addClass(\"layui-layer-TipsR\").css(\"border-bottom-color\",t.tips[1])},function(){s.autoLeft(),s.tipTop=s.top+s.height+10,f.removeClass(\"layui-layer-TipsT\").addClass(\"layui-layer-TipsB\").css(\"border-right-color\",t.tips[1])},function(){s.tipLeft=s.left-o[0]-10,s.tipTop=s.top,f.removeClass(\"layui-layer-TipsR\").addClass(\"layui-layer-TipsL\").css(\"border-bottom-color\",t.tips[1])}],s.where[c-1](),1===c?s.top-(n.scrollTop()+o[1]+16)<0&&s.where[2]():2===c?n.width()-(s.left+s.width+o[0]+16)>0||s.where[3]():3===c?s.top-n.scrollTop()+s.height+o[1]+16-n.height()>0&&s.where[0]():4===c&&o[0]+16-s.left>0&&s.where[1](),a.find(\".\"+l[5]).css({\"background-color\":t.tips[1],\"padding-right\":t.closeBtn?\"30px\":\"\"}),a.css({left:s.tipLeft-(t.fixed?n.scrollLeft():0),top:s.tipTop-(t.fixed?n.scrollTop():0)})},s.pt.move=function(){var e=this,t=e.config,a=i(document),s=e.layero,l=s.find(t.move),f=s.find(\".layui-layer-resize\"),c={};return t.move&&l.css(\"cursor\",\"move\"),l.on(\"mousedown\",function(e){e.preventDefault(),t.move&&(c.moveStart=!0,c.offset=[e.clientX-parseFloat(s.css(\"left\")),e.clientY-parseFloat(s.css(\"top\"))],o.moveElem.css(\"cursor\",\"move\").show())}),f.on(\"mousedown\",function(e){e.preventDefault(),c.resizeStart=!0,c.offset=[e.clientX,e.clientY],c.area=[s.outerWidth(),s.outerHeight()],o.moveElem.css(\"cursor\",\"se-resize\").show()}),a.on(\"mousemove\",function(i){if(c.moveStart){var a=i.clientX-c.offset[0],o=i.clientY-c.offset[1],l=\"fixed\"===s.css(\"position\");if(i.preventDefault(),c.stX=l?0:n.scrollLeft(),c.stY=l?0:n.scrollTop(),!t.moveOut){var f=n.width()-s.outerWidth()+c.stX,u=n.height()-s.outerHeight()+c.stY;a<c.stX&&(a=c.stX),a>f&&(a=f),o<c.stY&&(o=c.stY),o>u&&(o=u)}s.css({left:a,top:o})}if(t.resize&&c.resizeStart){var a=i.clientX-c.offset[0],o=i.clientY-c.offset[1];i.preventDefault(),r.style(e.index,{width:c.area[0]+a,height:c.area[1]+o}),c.isResize=!0,t.resizing&&t.resizing(s)}}).on(\"mouseup\",function(e){c.moveStart&&(delete c.moveStart,o.moveElem.hide(),t.moveEnd&&t.moveEnd(s)),c.resizeStart&&(delete c.resizeStart,o.moveElem.hide())}),e},s.pt.callback=function(){function e(){var e=a.cancel&&a.cancel(t.index,n);e===!1||r.close(t.index)}var t=this,n=t.layero,a=t.config;t.openLayer(),a.success&&(2==a.type?n.find(\"iframe\").on(\"load\",function(){a.success(n,t.index)}):a.success(n,t.index)),6==r.ie&&t.IE6(n),n.find(\".\"+l[6]).children(\"a\").on(\"click\",function(){var e=i(this).index();if(0===e)a.yes?a.yes(t.index,n):a.btn1?a.btn1(t.index,n):r.close(t.index);else{var o=a[\"btn\"+(e+1)]&&a[\"btn\"+(e+1)](t.index,n);o===!1||r.close(t.index)}}),n.find(\".\"+l[7]).on(\"click\",e),a.shadeClose&&i(\"#layui-layer-shade\"+t.index).on(\"click\",function(){r.close(t.index)}),n.find(\".layui-layer-min\").on(\"click\",function(){var e=a.min&&a.min(n);e===!1||r.min(t.index,a)}),n.find(\".layui-layer-max\").on(\"click\",function(){i(this).hasClass(\"layui-layer-maxmin\")?(r.restore(t.index),a.restore&&a.restore(n)):(r.full(t.index,a),setTimeout(function(){a.full&&a.full(n)},100))}),a.end&&(o.end[t.index]=a.end)},o.reselect=function(){i.each(i(\"select\"),function(e,t){var n=i(this);n.parents(\".\"+l[0])[0]||1==n.attr(\"layer\")&&i(\".\"+l[0]).length<1&&n.removeAttr(\"layer\").show(),n=null})},s.pt.IE6=function(e){i(\"select\").each(function(e,t){var n=i(this);n.parents(\".\"+l[0])[0]||\"none\"===n.css(\"display\")||n.attr({layer:\"1\"}).hide(),n=null})},s.pt.openLayer=function(){var e=this;r.zIndex=e.config.zIndex,r.setTop=function(e){var t=function(){r.zIndex++,e.css(\"z-index\",r.zIndex+1)};return r.zIndex=parseInt(e[0].style.zIndex),e.on(\"mousedown\",t),r.zIndex}},o.record=function(e){var t=[e.width(),e.height(),e.position().top,e.position().left+parseFloat(e.css(\"margin-left\"))];e.find(\".layui-layer-max\").addClass(\"layui-layer-maxmin\"),e.attr({area:t})},o.rescollbar=function(e){l.html.attr(\"layer-full\")==e&&(l.html[0].style.removeProperty?l.html[0].style.removeProperty(\"overflow\"):l.html[0].style.removeAttribute(\"overflow\"),l.html.removeAttr(\"layer-full\"))},e.layer=r,r.getChildFrame=function(e,t){return t=t||i(\".\"+l[4]).attr(\"times\"),i(\"#\"+l[0]+t).find(\"iframe\").contents().find(e)},r.getFrameIndex=function(e){return i(\"#\"+e).parents(\".\"+l[4]).attr(\"times\")},r.iframeAuto=function(e){if(e){var t=r.getChildFrame(\"html\",e).outerHeight(),n=i(\"#\"+l[0]+e),a=n.find(l[1]).outerHeight()||0,o=n.find(\".\"+l[6]).outerHeight()||0;n.css({height:t+a+o}),n.find(\"iframe\").css({height:t})}},r.iframeSrc=function(e,t){i(\"#\"+l[0]+e).find(\"iframe\").attr(\"src\",t)},r.style=function(e,t,n){var a=i(\"#\"+l[0]+e),r=a.find(\".layui-layer-content\"),s=a.attr(\"type\"),f=a.find(l[1]).outerHeight()||0,c=a.find(\".\"+l[6]).outerHeight()||0;a.attr(\"minLeft\");s!==o.type[3]&&s!==o.type[4]&&(n||(parseFloat(t.width)<=260&&(t.width=260),parseFloat(t.height)-f-c<=64&&(t.height=64+f+c)),a.css(t),c=a.find(\".\"+l[6]).outerHeight(),s===o.type[2]?a.find(\"iframe\").css({height:parseFloat(t.height)-f-c}):r.css({height:parseFloat(t.height)-f-c-parseFloat(r.css(\"padding-top\"))-parseFloat(r.css(\"padding-bottom\"))}))},r.min=function(e,t){var a=i(\"#\"+l[0]+e),s=a.find(l[1]).outerHeight()||0,f=a.attr(\"minLeft\")||181*o.minIndex+\"px\",c=a.css(\"position\");o.record(a),o.minLeft[0]&&(f=o.minLeft[0],o.minLeft.shift()),a.attr(\"position\",c),r.style(e,{width:180,height:s,left:f,top:n.height()-s,position:\"fixed\",overflow:\"hidden\"},!0),a.find(\".layui-layer-min\").hide(),\"page\"===a.attr(\"type\")&&a.find(l[4]).hide(),o.rescollbar(e),a.attr(\"minLeft\")||o.minIndex++,a.attr(\"minLeft\",f)},r.restore=function(e){var t=i(\"#\"+l[0]+e),n=t.attr(\"area\").split(\",\");t.attr(\"type\");r.style(e,{width:parseFloat(n[0]),height:parseFloat(n[1]),top:parseFloat(n[2]),left:parseFloat(n[3]),position:t.attr(\"position\"),overflow:\"visible\"},!0),t.find(\".layui-layer-max\").removeClass(\"layui-layer-maxmin\"),t.find(\".layui-layer-min\").show(),\"page\"===t.attr(\"type\")&&t.find(l[4]).show(),o.rescollbar(e)},r.full=function(e){var t,a=i(\"#\"+l[0]+e);o.record(a),l.html.attr(\"layer-full\")||l.html.css(\"overflow\",\"hidden\").attr(\"layer-full\",e),clearTimeout(t),t=setTimeout(function(){var t=\"fixed\"===a.css(\"position\");r.style(e,{top:t?0:n.scrollTop(),left:t?0:n.scrollLeft(),width:n.width(),height:n.height()},!0),a.find(\".layui-layer-min\").hide()},100)},r.title=function(e,t){var n=i(\"#\"+l[0]+(t||r.index)).find(l[1]);n.html(e)},r.close=function(e){var t=i(\"#\"+l[0]+e),n=t.attr(\"type\"),a=\"layer-anim-close\";if(t[0]){var s=\"layui-layer-wrap\",f=function(){if(n===o.type[1]&&\"object\"===t.attr(\"conType\")){t.children(\":not(.\"+l[5]+\")\").remove();for(var a=t.find(\".\"+s),r=0;r<2;r++)a.unwrap();a.css(\"display\",a.data(\"display\")).removeClass(s)}else{if(n===o.type[2])try{var f=i(\"#\"+l[4]+e)[0];f.contentWindow.document.write(\"\"),f.contentWindow.close(),t.find(\".\"+l[5])[0].removeChild(f)}catch(c){}t[0].innerHTML=\"\",t.remove()}\"function\"==typeof o.end[e]&&o.end[e](),delete o.end[e]};t.data(\"isOutAnim\")&&t.addClass(\"layer-anim \"+a),i(\"#layui-layer-moves, #layui-layer-shade\"+e).remove(),6==r.ie&&o.reselect(),o.rescollbar(e),t.attr(\"minLeft\")&&(o.minIndex--,o.minLeft.push(t.attr(\"minLeft\"))),r.ie&&r.ie<10||!t.data(\"isOutAnim\")?f():setTimeout(function(){f()},200)}},r.closeAll=function(e){i.each(i(\".\"+l[0]),function(){var t=i(this),n=e?t.attr(\"type\")===e:1;n&&r.close(t.attr(\"times\")),n=null})};var f=r.cache||{},c=function(e){return f.skin?\" \"+f.skin+\" \"+f.skin+\"-\"+e:\"\"};r.prompt=function(e,t){var a=\"\";if(e=e||{},\"function\"==typeof e&&(t=e),e.area){var o=e.area;a='style=\"width: '+o[0]+\"; height: \"+o[1]+';\"',delete e.area}var s,l=2==e.formType?'<textarea class=\"layui-layer-input\"'+a+\"></textarea>\":function(){return'<input type=\"'+(1==e.formType?\"password\":\"text\")+'\" class=\"layui-layer-input\">'}(),f=e.success;return delete e.success,r.open(i.extend({type:1,btn:[\"&#x786E;&#x5B9A;\",\"&#x53D6;&#x6D88;\"],content:l,skin:\"layui-layer-prompt\"+c(\"prompt\"),maxWidth:n.width(),success:function(t){s=t.find(\".layui-layer-input\"),s.val(e.value||\"\").focus(),\"function\"==typeof f&&f(t)},resize:!1,yes:function(i){var n=s.val();\"\"===n?s.focus():n.length>(e.maxlength||500)?r.tips(\"&#x6700;&#x591A;&#x8F93;&#x5165;\"+(e.maxlength||500)+\"&#x4E2A;&#x5B57;&#x6570;\",s,{tips:1}):t&&t(n,i,s)}},e))},r.tab=function(e){e=e||{};var t=e.tab||{},n=\"layui-this\",a=e.success;return delete e.success,r.open(i.extend({type:1,skin:\"layui-layer-tab\"+c(\"tab\"),resize:!1,title:function(){var e=t.length,i=1,a=\"\";if(e>0)for(a='<span class=\"'+n+'\">'+t[0].title+\"</span>\";i<e;i++)a+=\"<span>\"+t[i].title+\"</span>\";return a}(),content:'<ul class=\"layui-layer-tabmain\">'+function(){var e=t.length,i=1,a=\"\";if(e>0)for(a='<li class=\"layui-layer-tabli '+n+'\">'+(t[0].content||\"no content\")+\"</li>\";i<e;i++)a+='<li class=\"layui-layer-tabli\">'+(t[i].content||\"no  content\")+\"</li>\";return a}()+\"</ul>\",success:function(t){var o=t.find(\".layui-layer-title\").children(),r=t.find(\".layui-layer-tabmain\").children();o.on(\"mousedown\",function(t){t.stopPropagation?t.stopPropagation():t.cancelBubble=!0;var a=i(this),o=a.index();a.addClass(n).siblings().removeClass(n),r.eq(o).show().siblings().hide(),\"function\"==typeof e.change&&e.change(o)}),\"function\"==typeof a&&a(t)}},e))},r.photos=function(t,n,a){function o(e,t,i){var n=new Image;return n.src=e,n.complete?t(n):(n.onload=function(){n.onload=null,t(n)},void(n.onerror=function(e){n.onerror=null,i(e)}))}var s={};if(t=t||{},t.photos){var l=t.photos.constructor===Object,f=l?t.photos:{},u=f.data||[],d=f.start||0;s.imgIndex=(0|d)+1,t.img=t.img||\"img\";var y=t.success;if(delete t.success,l){if(0===u.length)return r.msg(\"&#x6CA1;&#x6709;&#x56FE;&#x7247;\")}else{var p=i(t.photos),h=function(){u=[],p.find(t.img).each(function(e){var t=i(this);t.attr(\"layer-index\",e),u.push({alt:t.attr(\"alt\"),pid:t.attr(\"layer-pid\"),src:t.attr(\"layer-src\")||t.attr(\"src\"),thumb:t.attr(\"src\")})})};if(h(),0===u.length)return;if(n||p.on(\"click\",t.img,function(){var e=i(this),n=e.attr(\"layer-index\");r.photos(i.extend(t,{photos:{start:n,data:u,tab:t.tab},full:t.full}),!0),h()}),!n)return}s.imgprev=function(e){s.imgIndex--,s.imgIndex<1&&(s.imgIndex=u.length),s.tabimg(e)},s.imgnext=function(e,t){s.imgIndex++,s.imgIndex>u.length&&(s.imgIndex=1,t)||s.tabimg(e)},s.keyup=function(e){if(!s.end){var t=e.keyCode;e.preventDefault(),37===t?s.imgprev(!0):39===t?s.imgnext(!0):27===t&&r.close(s.index)}},s.tabimg=function(e){if(!(u.length<=1))return f.start=s.imgIndex-1,r.close(s.index),r.photos(t,!0,e)},s.event=function(){s.bigimg.hover(function(){s.imgsee.show()},function(){s.imgsee.hide()}),s.bigimg.find(\".layui-layer-imgprev\").on(\"click\",function(e){e.preventDefault(),s.imgprev()}),s.bigimg.find(\".layui-layer-imgnext\").on(\"click\",function(e){e.preventDefault(),s.imgnext()}),i(document).on(\"keyup\",s.keyup)},s.loadi=r.load(1,{shade:!(\"shade\"in t)&&.9,scrollbar:!1}),o(u[d].src,function(n){r.close(s.loadi),s.index=r.open(i.extend({type:1,id:\"layui-layer-photos\",area:function(){var a=[n.width,n.height],o=[i(e).width()-100,i(e).height()-100];if(!t.full&&(a[0]>o[0]||a[1]>o[1])){var r=[a[0]/o[0],a[1]/o[1]];r[0]>r[1]?(a[0]=a[0]/r[0],a[1]=a[1]/r[0]):r[0]<r[1]&&(a[0]=a[0]/r[1],a[1]=a[1]/r[1])}return[a[0]+\"px\",a[1]+\"px\"]}(),title:!1,shade:.9,shadeClose:!0,closeBtn:!1,move:\".layui-layer-phimg img\",moveType:1,scrollbar:!1,moveOut:!0,isOutAnim:!1,skin:\"layui-layer-photos\"+c(\"photos\"),content:'<div class=\"layui-layer-phimg\"><img src=\"'+u[d].src+'\" alt=\"'+(u[d].alt||\"\")+'\" layer-pid=\"'+u[d].pid+'\"><div class=\"layui-layer-imgsee\">'+(u.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:'+(a?\"block\":\"\")+'\"><span class=\"layui-layer-imgtit\"><a href=\"javascript:;\">'+(u[d].alt||\"\")+\"</a><em>\"+s.imgIndex+\"/\"+u.length+\"</em></span></div></div></div>\",success:function(e,i){s.bigimg=e.find(\".layui-layer-phimg\"),s.imgsee=e.find(\".layui-layer-imguide,.layui-layer-imgbar\"),s.event(e),t.tab&&t.tab(u[d],e),\"function\"==typeof y&&y(e)},end:function(){s.end=!0,i(document).off(\"keyup\",s.keyup)}},t))},function(){r.close(s.loadi),r.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(){u.length>1&&s.imgnext(!0,!0)}})})}},o.run=function(t){i=t,n=i(e),l.html=i(\"html\"),r.open=function(e){var t=new s(e);return t.index}},e.layui&&layui.define?(r.ready(),layui.define(\"jquery\",function(t){r.path=layui.cache.dir,o.run(layui.$),e.layer=r,t(\"layer\",r)})):\"function\"==typeof define&&define.amd?define([\"jquery\"],function(){return o.run(e.jQuery),r}):function(){o.run(e.jQuery),r.ready()}()}(window);layui.define(\"jquery\",function(t){\"use strict\";var a=layui.$,i=(layui.hint(),layui.device()),e=\"element\",l=\"layui-this\",n=\"layui-show\",s=function(){this.config={}};s.prototype.set=function(t){var i=this;return a.extend(!0,i.config,t),i},s.prototype.on=function(t,a){return layui.onevent.call(this,e,t,a)},s.prototype.tabAdd=function(t,i){var e=\".layui-tab-title\",l=a(\".layui-tab[lay-filter=\"+t+\"]\"),n=l.children(e),s=n.children(\".layui-tab-bar\"),o=l.children(\".layui-tab-content\"),r='<li lay-id=\"'+(i.id||\"\")+'\"'+(i.attr?' lay-attr=\"'+i.attr+'\"':\"\")+\">\"+(i.title||\"unnaming\")+\"</li>\";return s[0]?s.before(r):n.append(r),o.append('<div class=\"layui-tab-item\">'+(i.content||\"\")+\"</div>\"),f.hideTabMore(!0),f.tabAuto(),this},s.prototype.tabDelete=function(t,i){var e=\".layui-tab-title\",l=a(\".layui-tab[lay-filter=\"+t+\"]\"),n=l.children(e),s=n.find('>li[lay-id=\"'+i+'\"]');return f.tabDelete(null,s),this},s.prototype.tabChange=function(t,i){var e=\".layui-tab-title\",l=a(\".layui-tab[lay-filter=\"+t+\"]\"),n=l.children(e),s=n.find('>li[lay-id=\"'+i+'\"]');return f.tabClick.call(s[0],null,null,s),this},s.prototype.tab=function(t){t=t||{},b.on(\"click\",t.headerElem,function(i){var e=a(this).index();f.tabClick.call(this,i,e,null,t)})},s.prototype.progress=function(t,i){var e=\"layui-progress\",l=a(\".\"+e+\"[lay-filter=\"+t+\"]\"),n=l.find(\".\"+e+\"-bar\"),s=n.find(\".\"+e+\"-text\");return n.css(\"width\",i),s.text(i),this};var o=\".layui-nav\",r=\"layui-nav-item\",c=\"layui-nav-bar\",u=\"layui-nav-tree\",d=\"layui-nav-child\",y=\"layui-nav-more\",h=\"layui-anim layui-anim-upbit\",f={tabClick:function(t,i,s,o){o=o||{};var r=s||a(this),i=i||r.parent().children(\"li\").index(r),c=o.headerElem?r.parent():r.parents(\".layui-tab\").eq(0),u=o.bodyElem?a(o.bodyElem):c.children(\".layui-tab-content\").children(\".layui-tab-item\"),d=r.find(\"a\"),y=c.attr(\"lay-filter\");\"javascript:;\"!==d.attr(\"href\")&&\"_blank\"===d.attr(\"target\")||(r.addClass(l).siblings().removeClass(l),u.eq(i).addClass(n).siblings().removeClass(n)),layui.event.call(this,e,\"tab(\"+y+\")\",{elem:c,index:i})},tabDelete:function(t,i){var n=i||a(this).parent(),s=n.index(),o=n.parents(\".layui-tab\").eq(0),r=o.children(\".layui-tab-content\").children(\".layui-tab-item\"),c=o.attr(\"lay-filter\");n.hasClass(l)&&(n.next()[0]?f.tabClick.call(n.next()[0],null,s+1):n.prev()[0]&&f.tabClick.call(n.prev()[0],null,s-1)),n.remove(),r.eq(s).remove(),setTimeout(function(){f.tabAuto()},50),layui.event.call(this,e,\"tabDelete(\"+c+\")\",{elem:o,index:s})},tabAuto:function(){var t=\"layui-tab-more\",e=\"layui-tab-bar\",l=\"layui-tab-close\",n=this;a(\".layui-tab\").each(function(){var s=a(this),o=s.children(\".layui-tab-title\"),r=(s.children(\".layui-tab-content\").children(\".layui-tab-item\"),'lay-stope=\"tabmore\"'),c=a('<span class=\"layui-unselect layui-tab-bar\" '+r+\"><i \"+r+' class=\"layui-icon\">&#xe61a;</i></span>');if(n===window&&8!=i.ie&&f.hideTabMore(!0),s.attr(\"lay-allowClose\")&&o.find(\"li\").each(function(){var t=a(this);if(!t.find(\".\"+l)[0]){var i=a('<i class=\"layui-icon layui-unselect '+l+'\">&#x1006;</i>');i.on(\"click\",f.tabDelete),t.append(i)}}),\"string\"!=typeof s.attr(\"lay-unauto\"))if(o.prop(\"scrollWidth\")>o.outerWidth()+1){if(o.find(\".\"+e)[0])return;o.append(c),s.attr(\"overflow\",\"\"),c.on(\"click\",function(a){o[this.title?\"removeClass\":\"addClass\"](t),this.title=this.title?\"\":\"收缩\"})}else o.find(\".\"+e).remove(),s.removeAttr(\"overflow\")})},hideTabMore:function(t){var i=a(\".layui-tab-title\");t!==!0&&\"tabmore\"===a(t.target).attr(\"lay-stope\")||(i.removeClass(\"layui-tab-more\"),i.find(\".layui-tab-bar\").attr(\"title\",\"\"))},clickThis:function(){var t=a(this),i=t.parents(o),n=i.attr(\"lay-filter\"),s=t.parent(),c=t.siblings(\".\"+d),y=\"string\"==typeof s.attr(\"lay-unselect\");\"javascript:;\"!==t.attr(\"href\")&&\"_blank\"===t.attr(\"target\")||y||c[0]||(i.find(\".\"+l).removeClass(l),s.addClass(l)),i.hasClass(u)&&(c.removeClass(h),c[0]&&(s[\"none\"===c.css(\"display\")?\"addClass\":\"removeClass\"](r+\"ed\"),\"all\"===i.attr(\"lay-shrink\")&&s.siblings().removeClass(r+\"ed\"))),layui.event.call(this,e,\"nav(\"+n+\")\",t)},collapse:function(){var t=a(this),i=t.find(\".layui-colla-icon\"),l=t.siblings(\".layui-colla-content\"),s=t.parents(\".layui-collapse\").eq(0),o=s.attr(\"lay-filter\"),r=\"none\"===l.css(\"display\");if(\"string\"==typeof s.attr(\"lay-accordion\")){var c=s.children(\".layui-colla-item\").children(\".\"+n);c.siblings(\".layui-colla-title\").children(\".layui-colla-icon\").html(\"&#xe602;\"),c.removeClass(n)}l[r?\"addClass\":\"removeClass\"](n),i.html(r?\"&#xe61a;\":\"&#xe602;\"),layui.event.call(this,e,\"collapse(\"+o+\")\",{title:t,content:l,show:r})}};s.prototype.init=function(t,e){var l=function(){return e?'[lay-filter=\"'+e+'\"]':\"\"}(),s={tab:function(){f.tabAuto.call({})},nav:function(){var t=200,e={},s={},p={},b=function(l,o,r){var c=a(this),f=c.find(\".\"+d);o.hasClass(u)?l.css({top:c.position().top,height:c.children(\"a\").outerHeight(),opacity:1}):(f.addClass(h),l.css({left:c.position().left+parseFloat(c.css(\"marginLeft\")),top:c.position().top+c.height()-l.height()}),e[r]=setTimeout(function(){l.css({width:c.width(),opacity:1})},i.ie&&i.ie<10?0:t),clearTimeout(p[r]),\"block\"===f.css(\"display\")&&clearTimeout(s[r]),s[r]=setTimeout(function(){f.addClass(n),c.find(\".\"+y).addClass(y+\"d\")},300))};a(o+l).each(function(i){var l=a(this),o=a('<span class=\"'+c+'\"></span>'),h=l.find(\".\"+r);l.find(\".\"+c)[0]||(l.append(o),h.on(\"mouseenter\",function(){b.call(this,o,l,i)}).on(\"mouseleave\",function(){l.hasClass(u)||(clearTimeout(s[i]),s[i]=setTimeout(function(){l.find(\".\"+d).removeClass(n),l.find(\".\"+y).removeClass(y+\"d\")},300))}),l.on(\"mouseleave\",function(){clearTimeout(e[i]),p[i]=setTimeout(function(){l.hasClass(u)?o.css({height:0,top:o.position().top+o.height()/2,opacity:0}):o.css({width:0,left:o.position().left+o.width()/2,opacity:0})},t)})),h.find(\"a\").each(function(){var t=a(this),i=(t.parent(),t.siblings(\".\"+d));i[0]&&!t.children(\".\"+y)[0]&&t.append('<span class=\"'+y+'\"></span>'),t.off(\"click\",f.clickThis).on(\"click\",f.clickThis)})})},breadcrumb:function(){var t=\".layui-breadcrumb\";a(t+l).each(function(){var t=a(this),i=\"lay-separator\",e=t.attr(i)||\"/\",l=t.find(\"a\");l.next(\"span[\"+i+\"]\")[0]||(l.each(function(t){t!==l.length-1&&a(this).after(\"<span \"+i+\">\"+e+\"</span>\")}),t.css(\"visibility\",\"visible\"))})},progress:function(){var t=\"layui-progress\";a(\".\"+t+l).each(function(){var i=a(this),e=i.find(\".layui-progress-bar\"),l=e.attr(\"lay-percent\");e.css(\"width\",function(){return/^.+\\/.+$/.test(l)?100*new Function(\"return \"+l)()+\"%\":l}()),i.attr(\"lay-showPercent\")&&setTimeout(function(){e.html('<span class=\"'+t+'-text\">'+l+\"</span>\")},350)})},collapse:function(){var t=\"layui-collapse\";a(\".\"+t+l).each(function(){var t=a(this).find(\".layui-colla-item\");t.each(function(){var t=a(this),i=t.find(\".layui-colla-title\"),e=t.find(\".layui-colla-content\"),l=\"none\"===e.css(\"display\");i.find(\".layui-colla-icon\").remove(),i.append('<i class=\"layui-icon layui-colla-icon\">'+(l?\"&#xe602;\":\"&#xe61a;\")+\"</i>\"),i.off(\"click\",f.collapse).on(\"click\",f.collapse)})})}};return s[t]?s[t]():layui.each(s,function(t,a){a()})},s.prototype.render=s.prototype.init;var p=new s,b=a(document);p.render();var v=\".layui-tab-title li\";b.on(\"click\",v,f.tabClick),b.on(\"click\",f.hideTabMore),a(window).on(\"resize\",f.tabAuto),t(e,p)});layui.define(\"layer\",function(e){\"use strict\";var i=layui.$,t=layui.layer,n=layui.hint(),a=layui.device(),o={config:{},set:function(e){var t=this;return t.config=i.extend({},t.config,e),t},on:function(e,i){return layui.onevent.call(this,r,e,i)}},l=function(){var e=this;return{upload:function(i){e.upload.call(e,i)},config:e.config}},r=\"upload\",u=\"layui-upload-file\",c=\"layui-upload-form\",f=\"layui-upload-iframe\",s=\"layui-upload-choose\",p=function(e){var t=this;t.config=i.extend({},t.config,o.config,e),t.render()};p.prototype.config={accept:\"images\",exts:\"\",auto:!0,bindAction:\"\",url:\"\",field:\"file\",method:\"post\",data:{},drag:!0,size:0,number:0,multiple:!1},p.prototype.render=function(e){var t=this,e=t.config;e.elem=i(e.elem),e.bindAction=i(e.bindAction),t.file(),t.events()},p.prototype.file=function(){var e=this,t=e.config,n=e.elemFile=i(['<input class=\"'+u+'\" type=\"file\" accept=\"'+t.acceptMime+'\" name=\"'+t.field+'\"',t.multiple?\" multiple\":\"\",\">\"].join(\"\")),o=t.elem.next();(o.hasClass(u)||o.hasClass(c))&&o.remove(),a.ie&&a.ie<10&&t.elem.wrap('<div class=\"layui-upload-wrap\"></div>'),e.isFile()?(e.elemFile=t.elem,t.field=t.elem[0].name):t.elem.after(n),a.ie&&a.ie<10&&e.initIE()},p.prototype.initIE=function(){var e=this,t=e.config,n=i('<iframe id=\"'+f+'\" class=\"'+f+'\" name=\"'+f+'\" frameborder=\"0\"></iframe>'),a=i(['<form target=\"'+f+'\" class=\"'+c+'\" method=\"'+t.method,'\" key=\"set-mine\" enctype=\"multipart/form-data\" action=\"'+t.url+'\">',\"</form>\"].join(\"\"));i(\"#\"+f)[0]||i(\"body\").append(n),t.elem.next().hasClass(f)||(e.elemFile.wrap(a),t.elem.next(\".\"+f).append(function(){var e=[];return layui.each(t.data,function(i,t){t=\"function\"==typeof t?t():t,e.push('<input type=\"hidden\" name=\"'+i+'\" value=\"'+t+'\">')}),e.join(\"\")}()))},p.prototype.msg=function(e){return t.msg(e,{icon:2,shift:6})},p.prototype.isFile=function(){var e=this.config.elem[0];if(e)return\"input\"===e.tagName.toLocaleLowerCase()&&\"file\"===e.type},p.prototype.preview=function(e){var i=this;window.FileReader&&layui.each(i.chooseFiles,function(i,t){var n=new FileReader;n.readAsDataURL(t),n.onload=function(){e&&e(i,t,this.result)}})},p.prototype.upload=function(e,t){var n,o=this,l=o.config,r=o.elemFile[0],u=function(){var t=0,n=0,a=e||o.files||o.chooseFiles||r.files,u=function(){l.multiple&&t+n===o.fileLength&&\"function\"==typeof l.allDone&&l.allDone({total:o.fileLength,successful:t,aborted:n})};layui.each(a,function(e,a){var r=new FormData;r.append(l.field,a),layui.each(l.data,function(e,i){i=\"function\"==typeof i?i():i,r.append(e,i)}),i.ajax({url:l.url,type:l.method,data:r,contentType:!1,processData:!1,dataType:\"json\",headers:l.headers||{},success:function(i){t++,d(e,i),u()},error:function(){n++,o.msg(\"请求上传接口出现异常\"),m(e),u()}})})},c=function(){var e=i(\"#\"+f);o.elemFile.parent().submit(),clearInterval(p.timer),p.timer=setInterval(function(){var i,t=e.contents().find(\"body\");try{i=t.text()}catch(n){o.msg(\"获取上传后的响应信息出现异常\"),clearInterval(p.timer),m()}i&&(clearInterval(p.timer),t.html(\"\"),d(0,i))},30)},d=function(e,i){if(o.elemFile.next(\".\"+s).remove(),r.value=\"\",\"object\"!=typeof i)try{i=JSON.parse(i)}catch(t){return i={},o.msg(\"请对上传接口返回有效JSON\")}\"function\"==typeof l.done&&l.done(i,e||0,function(e){o.upload(e)})},m=function(e){l.auto&&(r.value=\"\"),\"function\"==typeof l.error&&l.error(e||0,function(e){o.upload(e)})},h=l.exts,v=function(){var i=[];return layui.each(e||o.chooseFiles,function(e,t){i.push(t.name)}),i}(),g={preview:function(e){o.preview(e)},upload:function(e,i){var t={};t[e]=i,o.upload(t)},pushFile:function(){return o.files=o.files||{},layui.each(o.chooseFiles,function(e,i){o.files[e]=i}),o.files}},y=function(){return\"choose\"===t?l.choose&&l.choose(g):(l.before&&l.before(g),a.ie?a.ie>9?u():c():void u())};if(v=0===v.length?r.value.match(/[^\\/\\\\]+\\..+/g)||[]||\"\":v,0!==v.length){switch(l.accept){case\"file\":if(h&&!RegExp(\"\\\\w\\\\.(\"+h+\")$\",\"i\").test(escape(v)))return o.msg(\"选择的文件中包含不支持的格式\"),r.value=\"\";break;case\"video\":if(!RegExp(\"\\\\w\\\\.(\"+(h||\"avi|mp4|wma|rmvb|rm|flash|3gp|flv\")+\")$\",\"i\").test(escape(v)))return o.msg(\"选择的视频中包含不支持的格式\"),r.value=\"\";break;case\"audio\":if(!RegExp(\"\\\\w\\\\.(\"+(h||\"mp3|wav|mid\")+\")$\",\"i\").test(escape(v)))return o.msg(\"选择的音频中包含不支持的格式\"),r.value=\"\";break;default:if(layui.each(v,function(e,i){RegExp(\"\\\\w\\\\.(\"+(h||\"jpg|png|gif|bmp|jpeg$\")+\")\",\"i\").test(escape(i))||(n=!0)}),n)return o.msg(\"选择的图片中包含不支持的格式\"),r.value=\"\"}if(o.fileLength=function(){var i=0,t=e||o.files||o.chooseFiles||r.files;return layui.each(t,function(){i++}),i}(),l.number&&o.fileLength>l.number)return o.msg(\"同时最多只能上传的数量为：\"+l.number);if(l.size>0&&!(a.ie&&a.ie<10)){var F;if(layui.each(o.chooseFiles,function(e,i){if(i.size>1024*l.size){var t=l.size/1024;t=t>=1?t.toFixed(2)+\"MB\":l.size+\"KB\",r.value=\"\",F=t}}),F)return o.msg(\"文件不能超过\"+F)}y()}},p.prototype.events=function(){var e=this,t=e.config,o=function(i){e.chooseFiles={},layui.each(i,function(i,t){var n=(new Date).getTime();e.chooseFiles[n+\"-\"+i]=t})},l=function(i,n){var a=e.elemFile,o=i.length>1?i.length+\"个文件\":(i[0]||{}).name||a[0].value.match(/[^\\/\\\\]+\\..+/g)||[]||\"\";a.next().hasClass(s)&&a.next().remove(),e.upload(null,\"choose\"),e.isFile()||t.choose||a.after('<span class=\"layui-inline '+s+'\">'+o+\"</span>\")};t.elem.off(\"upload.start\").on(\"upload.start\",function(){var a=i(this),o=a.attr(\"lay-data\");if(o)try{o=new Function(\"return \"+o)(),e.config=i.extend({},t,o)}catch(l){n.error(\"Upload element property lay-data configuration item has a syntax error: \"+o)}e.config.item=a,e.elemFile[0].click()}),a.ie&&a.ie<10||t.elem.off(\"upload.over\").on(\"upload.over\",function(){var e=i(this);e.attr(\"lay-over\",\"\")}).off(\"upload.leave\").on(\"upload.leave\",function(){var e=i(this);e.removeAttr(\"lay-over\")}).off(\"upload.drop\").on(\"upload.drop\",function(n,a){var r=i(this),u=a.originalEvent.dataTransfer.files||[];r.removeAttr(\"lay-over\"),o(u),t.auto?e.upload(u):l(u)}),e.elemFile.off(\"upload.change\").on(\"upload.change\",function(){var i=this.files||[];o(i),t.auto?e.upload():l(i)}),t.bindAction.off(\"upload.action\").on(\"upload.action\",function(){e.upload()}),t.elem.data(\"haveEvents\")||(e.elemFile.on(\"change\",function(){i(this).trigger(\"upload.change\")}),t.elem.on(\"click\",function(){e.isFile()||i(this).trigger(\"upload.start\")}),t.drag&&t.elem.on(\"dragover\",function(e){e.preventDefault(),i(this).trigger(\"upload.over\")}).on(\"dragleave\",function(e){i(this).trigger(\"upload.leave\")}).on(\"drop\",function(e){e.preventDefault(),i(this).trigger(\"upload.drop\",e)}),t.bindAction.on(\"click\",function(){i(this).trigger(\"upload.action\")}),t.elem.data(\"haveEvents\",!0))},o.render=function(e){var i=new p(e);return l.call(i)},e(r,o)});layui.define(\"layer\",function(e){\"use strict\";var i=layui.$,t=layui.layer,a=layui.hint(),n=layui.device(),l=\"form\",r=\".layui-form\",s=\"layui-this\",c=\"layui-hide\",o=\"layui-disabled\",u=function(){this.config={verify:{required:[/[\\S]+/,\"必填项不能为空\"],phone:[/^1\\d{10}$/,\"请输入正确的手机号\"],email:[/^([a-zA-Z0-9_\\.\\-])+\\@(([a-zA-Z0-9\\-])+\\.)+([a-zA-Z0-9]{2,4})+$/,\"邮箱格式不正确\"],url:[/(^#)|(^http(s*):\\/\\/[^\\s]+\\.[^\\s]+)/,\"链接格式不正确\"],number:function(e){if(!e||isNaN(e))return\"只能填写数字\"},date:[/^(\\d{4})[-\\/](\\d{1}|0\\d{1}|1[0-2])([-\\/](\\d{1}|0\\d{1}|[1-2][0-9]|3[0-1]))*$/,\"日期格式不正确\"],identity:[/(^\\d{15}$)|(^\\d{17}(x|X|\\d)$)/,\"请输入正确的身份证号\"]}}};u.prototype.set=function(e){var t=this;return i.extend(!0,t.config,e),t},u.prototype.verify=function(e){var t=this;return i.extend(!0,t.config.verify,e),t},u.prototype.on=function(e,i){return layui.onevent.call(this,l,e,i)},u.prototype.val=function(e,t){var a=i(r+'[lay-filter=\"'+e+'\"]');a.each(function(e,a){var n=i(this);layui.each(t,function(e,i){var t,a=n.find('[name=\"'+e+'\"]');a[0]&&(t=a[0].type,\"checkbox\"===t?a[0].checked=i:\"radio\"===t?a.each(function(){this.value===i&&(this.checked=!0)}):a.val(i))})}),f.render(null,e)},u.prototype.render=function(e,t){var n=this,u=i(r+function(){return t?'[lay-filter=\"'+t+'\"]':\"\"}()),d={select:function(){var e,t=\"请选择\",a=\"layui-form-select\",n=\"layui-select-title\",r=\"layui-select-none\",d=\"\",f=u.find(\"select\"),v=function(t,l){i(t.target).parent().hasClass(n)&&!l||(i(\".\"+a).removeClass(a+\"ed \"+a+\"up\"),e&&d&&e.val(d)),e=null},h=function(t,u,f){var h,p=i(this),m=t.find(\".\"+n),k=m.find(\"input\"),g=t.find(\"dl\"),x=g.children(\"dd\"),b=this.selectedIndex;if(!u){var C=function(){var e=t.offset().top+t.outerHeight()+5-y.scrollTop(),i=g.outerHeight();b=p[0].selectedIndex,t.addClass(a+\"ed\"),x.removeClass(c),x.eq(b).addClass(s).siblings().removeClass(s),e+i>y.height()&&e>=i&&t.addClass(a+\"up\")},w=function(e){t.removeClass(a+\"ed \"+a+\"up\"),k.blur(),h=null,e||$(k.val(),function(e){e&&(d=g.find(\".\"+s).html(),k&&k.val(d))})};m.on(\"click\",function(e){t.hasClass(a+\"ed\")?w():(v(e,!0),C()),g.find(\".\"+r).remove()}),m.find(\".layui-edge\").on(\"click\",function(){k.focus()}),k.on(\"keyup\",function(e){var i=e.keyCode;9===i&&C()}).on(\"keydown\",function(e){var i=e.keyCode;9===i&&w();var t=function(i,a){var n,l;if(e.preventDefault(),a=function(){return a&&a[0]?a:h&&h[0]?h:x.eq(b)}(),l=a[i](),n=a[i](\"dd\"),l[0])return h=a[i](),!n[0]||n.hasClass(o)?t(i,h):void n.addClass(s).siblings().removeClass(s)};38===i&&t(\"prev\"),40===i&&t(\"next\"),13===i&&(e.preventDefault(),g.children(\"dd.\"+s).trigger(\"click\"))});var $=function(e,t,a){var n=0;layui.each(x,function(){var t=i(this),l=t.text(),r=l.indexOf(e)===-1;(\"\"===e||\"blur\"===a?e!==l:r)&&n++,\"keyup\"===a&&t[r?\"addClass\":\"removeClass\"](c)});var l=n===x.length;return t(l),l},T=function(e){var i=this.value,t=e.keyCode;return 9!==t&&13!==t&&37!==t&&38!==t&&39!==t&&40!==t&&($(i,function(e){e?g.find(\".\"+r)[0]||g.append('<p class=\"'+r+'\">无匹配项</p>'):g.find(\".\"+r).remove()},\"keyup\"),void(\"\"===i&&g.find(\".\"+r).remove()))};f&&k.on(\"keyup\",T).on(\"blur\",function(t){var a=p[0].selectedIndex;e=k,d=i(p[0].options[a]).html(),setTimeout(function(){$(k.val(),function(e){d||k.val(\"\")},\"blur\")},200)}),x.on(\"click\",function(){var e=i(this),a=e.attr(\"lay-value\"),n=p.attr(\"lay-filter\");return!e.hasClass(o)&&(e.hasClass(\"layui-select-tips\")?k.val(\"\"):(k.val(e.text()),e.addClass(s)),e.siblings().removeClass(s),p.val(a).removeClass(\"layui-form-danger\"),layui.event.call(this,l,\"select(\"+n+\")\",{elem:p[0],value:a,othis:t}),w(!0),!1)}),t.find(\"dl>dt\").on(\"click\",function(e){return!1}),i(document).off(\"click\",v).on(\"click\",v)}};f.each(function(e,l){var r=i(this),c=r.next(\".\"+a),u=this.disabled,d=l.value,f=i(l.options[l.selectedIndex]),v=l.options[0];if(\"string\"==typeof r.attr(\"lay-ignore\"))return r.show();var y=\"string\"==typeof r.attr(\"lay-search\"),p=v?v.value?t:v.innerHTML||t:t,m=i(['<div class=\"'+(y?\"\":\"layui-unselect \")+a,(u?\" layui-select-disabled\":\"\")+'\">','<div class=\"'+n+'\">','<input type=\"text\" placeholder=\"'+p+'\" '+('value=\"'+(d?f.html():\"\")+'\"')+(y?\"\":\" readonly\")+' class=\"layui-input'+(y?\"\":\" layui-unselect\")+(u?\" \"+o:\"\")+'\">','<i class=\"layui-edge\"></i></div>','<dl class=\"layui-anim layui-anim-upbit'+(r.find(\"optgroup\")[0]?\" layui-select-group\":\"\")+'\">',function(e){var i=[];return layui.each(e,function(e,a){0!==e||a.value?\"optgroup\"===a.tagName.toLowerCase()?i.push(\"<dt>\"+a.label+\"</dt>\"):i.push('<dd lay-value=\"'+a.value+'\" class=\"'+(d===a.value?s:\"\")+(a.disabled?\" \"+o:\"\")+'\">'+a.innerHTML+\"</dd>\"):i.push('<dd lay-value=\"\" class=\"layui-select-tips\">'+(a.innerHTML||t)+\"</dd>\")}),0===i.length&&i.push('<dd lay-value=\"\" class=\"'+o+'\">没有选项</dd>'),i.join(\"\")}(r.find(\"*\"))+\"</dl>\",\"</div>\"].join(\"\"));c[0]&&c.remove(),r.after(m),h.call(this,m,u,y)})},checkbox:function(){var e={checkbox:[\"layui-form-checkbox\",\"layui-form-checked\",\"checkbox\"],_switch:[\"layui-form-switch\",\"layui-form-onswitch\",\"switch\"]},t=u.find(\"input[type=checkbox]\"),a=function(e,t){var a=i(this);e.on(\"click\",function(){var i=a.attr(\"lay-filter\"),n=(a.attr(\"lay-text\")||\"\").split(\"|\");a[0].disabled||(a[0].checked?(a[0].checked=!1,e.removeClass(t[1]).find(\"em\").text(n[1])):(a[0].checked=!0,e.addClass(t[1]).find(\"em\").text(n[0])),layui.event.call(a[0],l,t[2]+\"(\"+i+\")\",{elem:a[0],value:a[0].value,othis:e}))})};t.each(function(t,n){var l=i(this),r=l.attr(\"lay-skin\"),s=(l.attr(\"lay-text\")||\"\").split(\"|\"),c=this.disabled;\"switch\"===r&&(r=\"_\"+r);var u=e[r]||e.checkbox;if(\"string\"==typeof l.attr(\"lay-ignore\"))return l.show();var d=l.next(\".\"+u[0]),f=i(['<div class=\"layui-unselect '+u[0],n.checked?\" \"+u[1]:\"\",c?\" layui-checkbox-disbaled \"+o:\"\",'\"',r?' lay-skin=\"'+r+'\"':\"\",\">\",function(){var e=n.title.replace(/\\s/g,\"\"),i={checkbox:[e?\"<span>\"+n.title+\"</span>\":\"\",'<i class=\"layui-icon layui-icon-ok\"></i>'].join(\"\"),_switch:\"<em>\"+((n.checked?s[0]:s[1])||\"\")+\"</em><i></i>\"};return i[r]||i.checkbox}(),\"</div>\"].join(\"\"));d[0]&&d.remove(),l.after(f),a.call(this,f,u)})},radio:function(){var e=\"layui-form-radio\",t=[\"&#xe643;\",\"&#xe63f;\"],a=u.find(\"input[type=radio]\"),n=function(a){var n=i(this),s=\"layui-anim-scaleSpring\";a.on(\"click\",function(){var c=n[0].name,o=n.parents(r),u=n.attr(\"lay-filter\"),d=o.find(\"input[name=\"+c.replace(/(\\.|#|\\[|\\])/g,\"\\\\$1\")+\"]\");n[0].disabled||(layui.each(d,function(){var a=i(this).next(\".\"+e);this.checked=!1,a.removeClass(e+\"ed\"),a.find(\".layui-icon\").removeClass(s).html(t[1])}),n[0].checked=!0,a.addClass(e+\"ed\"),a.find(\".layui-icon\").addClass(s).html(t[0]),layui.event.call(n[0],l,\"radio(\"+u+\")\",{elem:n[0],value:n[0].value,othis:a}))})};a.each(function(a,l){var r=i(this),s=r.next(\".\"+e),c=this.disabled;if(\"string\"==typeof r.attr(\"lay-ignore\"))return r.show();s[0]&&s.remove();var u=i(['<div class=\"layui-unselect '+e,l.checked?\" \"+e+\"ed\":\"\",(c?\" layui-radio-disbaled \"+o:\"\")+'\">','<i class=\"layui-anim layui-icon\">'+t[l.checked?0:1]+\"</i>\",\"<div>\"+function(){var e=l.title||\"\";return\"string\"==typeof r.next().attr(\"lay-radio\")&&(e=r.next().html(),r.next().remove()),e}()+\"</div>\",\"</div>\"].join(\"\"));r.after(u),n.call(this,u)})}};return e?d[e]?d[e]():a.error(\"不支持的\"+e+\"表单渲染\"):layui.each(d,function(e,i){i()}),n};var d=function(){var e=i(this),a=f.config.verify,s=null,c=\"layui-form-danger\",o={},u=e.parents(r),d=u.find(\"*[lay-verify]\"),v=e.parents(\"form\")[0],y=u.find(\"input,select,textarea\"),h=e.attr(\"lay-filter\");if(layui.each(d,function(e,l){var r=i(this),o=r.attr(\"lay-verify\").split(\"|\"),u=r.attr(\"lay-verType\"),d=r.val();if(r.removeClass(c),layui.each(o,function(e,i){var o,f=\"\",v=\"function\"==typeof a[i];if(a[i]){var o=v?f=a[i](d,l):!a[i][0].test(d);if(f=f||a[i][1],o)return\"tips\"===u?t.tips(f,function(){return\"string\"==typeof r.attr(\"lay-ignore\")||\"select\"!==l.tagName.toLowerCase()&&!/^checkbox|radio$/.test(l.type)?r:r.next()}(),{tips:1}):\"alert\"===u?t.alert(f,{title:\"提示\",shadeClose:!0}):t.msg(f,{icon:5,shift:6}),n.android||n.ios||l.focus(),r.addClass(c),s=!0}}),s)return s}),s)return!1;var p={};return layui.each(y,function(e,i){if(i.name=(i.name||\"\").replace(/^\\s*|\\s*&/,\"\"),i.name){if(/^.*\\[\\]$/.test(i.name)){var t=i.name.match(/^(.*)\\[\\]$/g)[0];p[t]=0|p[t],i.name=i.name.replace(/^(.*)\\[\\]$/,\"$1[\"+p[t]++ +\"]\")}/^checkbox|radio$/.test(i.type)&&!i.checked||(o[i.name]=i.value)}}),layui.event.call(this,l,\"submit(\"+h+\")\",{elem:this,form:v,field:o})},f=new u,v=i(document),y=i(window);f.render(),v.on(\"reset\",r,function(){var e=i(this).attr(\"lay-filter\");setTimeout(function(){f.render(null,e)},50)}),v.on(\"submit\",r,d).on(\"click\",\"*[lay-submit]\",d),e(l,f)});layui.define(\"jquery\",function(e){\"use strict\";var o=layui.$,a=layui.hint(),i=\"layui-tree-enter\",r=function(e){this.options=e},t={arrow:[\"&#xe623;\",\"&#xe625;\"],checkbox:[\"&#xe626;\",\"&#xe627;\"],radio:[\"&#xe62b;\",\"&#xe62a;\"],branch:[\"&#xe622;\",\"&#xe624;\"],leaf:\"&#xe621;\"};r.prototype.init=function(e){var o=this;e.addClass(\"layui-box layui-tree\"),o.options.skin&&e.addClass(\"layui-tree-skin-\"+o.options.skin),o.tree(e),o.on(e)},r.prototype.tree=function(e,a){var i=this,r=i.options,n=a||r.nodes;layui.each(n,function(a,n){var l=n.children&&n.children.length>0,c=o('<ul class=\"'+(n.spread?\"layui-show\":\"\")+'\"></ul>'),s=o([\"<li \"+(n.spread?'data-spread=\"'+n.spread+'\"':\"\")+\">\",function(){return l?'<i class=\"layui-icon layui-tree-spread\">'+(n.spread?t.arrow[1]:t.arrow[0])+\"</i>\":\"\"}(),function(){return r.check?'<i class=\"layui-icon layui-tree-check\">'+(\"checkbox\"===r.check?t.checkbox[0]:\"radio\"===r.check?t.radio[0]:\"\")+\"</i>\":\"\"}(),function(){return'<a href=\"'+(n.href||\"javascript:;\")+'\" '+(r.target&&n.href?'target=\"'+r.target+'\"':\"\")+\">\"+('<i class=\"layui-icon layui-tree-'+(l?\"branch\":\"leaf\")+'\">'+(l?n.spread?t.branch[1]:t.branch[0]:t.leaf)+\"</i>\")+(\"<cite>\"+(n.name||\"未命名\")+\"</cite></a>\")}(),\"</li>\"].join(\"\"));l&&(s.append(c),i.tree(c,n.children)),e.append(s),\"function\"==typeof r.click&&i.click(s,n),i.spread(s,n),r.drag&&i.drag(s,n)})},r.prototype.click=function(e,o){var a=this,i=a.options;e.children(\"a\").on(\"click\",function(e){layui.stope(e),i.click(o)})},r.prototype.spread=function(e,o){var a=this,i=(a.options,e.children(\".layui-tree-spread\")),r=e.children(\"ul\"),n=e.children(\"a\"),l=function(){e.data(\"spread\")?(e.data(\"spread\",null),r.removeClass(\"layui-show\"),i.html(t.arrow[0]),n.find(\".layui-icon\").html(t.branch[0])):(e.data(\"spread\",!0),r.addClass(\"layui-show\"),i.html(t.arrow[1]),n.find(\".layui-icon\").html(t.branch[1]))};r[0]&&(i.on(\"click\",l),n.on(\"dblclick\",l))},r.prototype.on=function(e){var a=this,r=a.options,t=\"layui-tree-drag\";e.find(\"i\").on(\"selectstart\",function(e){return!1}),r.drag&&o(document).on(\"mousemove\",function(e){var i=a.move;if(i.from){var r=(i.to,o('<div class=\"layui-box '+t+'\"></div>'));e.preventDefault(),o(\".\"+t)[0]||o(\"body\").append(r);var n=o(\".\"+t)[0]?o(\".\"+t):r;n.addClass(\"layui-show\").html(i.from.elem.children(\"a\").html()),n.css({left:e.pageX+10,top:e.pageY+10})}}).on(\"mouseup\",function(){var e=a.move;e.from&&(e.from.elem.children(\"a\").removeClass(i),e.to&&e.to.elem.children(\"a\").removeClass(i),a.move={},o(\".\"+t).remove())})},r.prototype.move={},r.prototype.drag=function(e,a){var r=this,t=(r.options,e.children(\"a\")),n=function(){var t=o(this),n=r.move;n.from&&(n.to={item:a,elem:e},t.addClass(i))};t.on(\"mousedown\",function(){var o=r.move;o.from={item:a,elem:e}}),t.on(\"mouseenter\",n).on(\"mousemove\",n).on(\"mouseleave\",function(){var e=o(this),a=r.move;a.from&&(delete a.to,e.removeClass(i))})},e(\"tree\",function(e){var i=new r(e=e||{}),t=o(e.elem);return t[0]?void i.init(t):a.error(\"layui.tree 没有找到\"+e.elem+\"元素\")})});layui.define([\"laytpl\",\"laypage\",\"layer\",\"form\"],function(e){\"use strict\";var t=layui.$,i=layui.laytpl,a=layui.laypage,l=layui.layer,n=layui.form,o=layui.hint(),r=layui.device(),d={config:{checkName:\"LAY_CHECKED\",indexName:\"LAY_TABLE_INDEX\"},cache:{},index:layui.table?layui.table.index+1e4:0,set:function(e){var i=this;return i.config=t.extend({},i.config,e),i},on:function(e,t){return layui.onevent.call(this,s,e,t)}},c=function(){var e=this,t=e.config,i=t.id;return i&&(c.config[i]=t),{reload:function(t){e.reload.call(e,t)},config:t}},s=\"table\",u=\".layui-table\",h=\"layui-hide\",f=\"layui-none\",y=\"layui-table-view\",p=\".layui-table-header\",m=\".layui-table-body\",v=\".layui-table-main\",g=\".layui-table-fixed\",x=\".layui-table-fixed-l\",b=\".layui-table-fixed-r\",k=\".layui-table-tool\",C=\".layui-table-page\",w=\".layui-table-sort\",N=\"layui-table-edit\",T=\"layui-table-hover\",F=function(e){var t='{{#if(item2.colspan){}} colspan=\"{{item2.colspan}}\"{{#} if(item2.rowspan){}} rowspan=\"{{item2.rowspan}}\"{{#}}}';return e=e||{},['<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\" class=\"layui-table\" ','{{# if(d.data.skin){ }}lay-skin=\"{{d.data.skin}}\"{{# } }} {{# if(d.data.size){ }}lay-size=\"{{d.data.size}}\"{{# } }} {{# if(d.data.even){ }}lay-even{{# } }}>',\"<thead>\",\"{{# layui.each(d.data.cols, function(i1, item1){ }}\",\"<tr>\",\"{{# layui.each(item1, function(i2, item2){ }}\",'{{# if(item2.fixed && item2.fixed !== \"right\"){ left = true; } }}','{{# if(item2.fixed === \"right\"){ right = true; } }}',function(){return e.fixed&&\"right\"!==e.fixed?'{{# if(item2.fixed && item2.fixed !== \"right\"){ }}':\"right\"===e.fixed?'{{# if(item2.fixed === \"right\"){ }}':\"\"}(),'<th data-field=\"{{ item2.field||i2 }}\" {{# if(item2.minWidth){ }}data-minwidth=\"{{item2.minWidth}}\"{{# } }} '+t+' {{# if(item2.unresize){ }}data-unresize=\"true\"{{# } }}>','<div class=\"layui-table-cell laytable-cell-',\"{{# if(item2.colspan > 1){ }}\",\"group\",\"{{# } else { }}\",\"{{d.index}}-{{item2.field || i2}}\",'{{# if(item2.type !== \"normal\"){ }}',\" laytable-cell-{{ item2.type }}\",\"{{# } }}\",\"{{# } }}\",'\" {{#if(item2.align){}}align=\"{{item2.align}}\"{{#}}}>','{{# if(item2.type === \"checkbox\"){ }}','<input type=\"checkbox\" name=\"layTableCheckbox\" lay-skin=\"primary\" lay-filter=\"layTableAllChoose\" {{# if(item2[d.data.checkName]){ }}checked{{# }; }}>',\"{{# } else { }}\",'<span>{{item2.title||\"\"}}</span>',\"{{# if(!(item2.colspan > 1) && item2.sort){ }}\",'<span class=\"layui-table-sort layui-inline\"><i class=\"layui-edge layui-table-sort-asc\"></i><i class=\"layui-edge layui-table-sort-desc\"></i></span>',\"{{# } }}\",\"{{# } }}\",\"</div>\",\"</th>\",e.fixed?\"{{# }; }}\":\"\",\"{{# }); }}\",\"</tr>\",\"{{# }); }}\",\"</thead>\",\"</table>\"].join(\"\")},W=['<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\" class=\"layui-table\" ','{{# if(d.data.skin){ }}lay-skin=\"{{d.data.skin}}\"{{# } }} {{# if(d.data.size){ }}lay-size=\"{{d.data.size}}\"{{# } }} {{# if(d.data.even){ }}lay-even{{# } }}>',\"<tbody></tbody>\",\"</table>\"].join(\"\"),z=['<div class=\"layui-form layui-border-box {{d.VIEW_CLASS}}\" lay-filter=\"LAY-table-{{d.index}}\" style=\"{{# if(d.data.width){ }}width:{{d.data.width}}px;{{# } }} {{# if(d.data.height){ }}height:{{d.data.height}}px;{{# } }}\">',\"{{# if(d.data.toolbar){ }}\",'<div class=\"layui-table-tool\"></div>',\"{{# } }}\",'<div class=\"layui-table-box\">',\"{{# var left, right; }}\",'<div class=\"layui-table-header\">',F(),\"</div>\",'<div class=\"layui-table-body layui-table-main\">',W,\"</div>\",\"{{# if(left){ }}\",'<div class=\"layui-table-fixed layui-table-fixed-l\">','<div class=\"layui-table-header\">',F({fixed:!0}),\"</div>\",'<div class=\"layui-table-body\">',W,\"</div>\",\"</div>\",\"{{# }; }}\",\"{{# if(right){ }}\",'<div class=\"layui-table-fixed layui-table-fixed-r\">','<div class=\"layui-table-header\">',F({fixed:\"right\"}),'<div class=\"layui-table-mend\"></div>',\"</div>\",'<div class=\"layui-table-body\">',W,\"</div>\",\"</div>\",\"{{# }; }}\",\"</div>\",\"{{# if(d.data.page){ }}\",'<div class=\"layui-table-page\">','<div id=\"layui-table-page{{d.index}}\"></div>',\"</div>\",\"{{# } }}\",\"<style>\",\"{{# layui.each(d.data.cols, function(i1, item1){\",\"layui.each(item1, function(i2, item2){ }}\",\".laytable-cell-{{d.index}}-{{item2.field||i2}}{ \",\"{{# if(item2.width){ }}\",\"width: {{item2.width}}px;\",\"{{# } }}\",\" }\",\"{{# });\",\"}); }}\",\"</style>\",\"</div>\"].join(\"\"),A=t(window),S=t(document),M=function(e){var i=this;i.index=++d.index,i.config=t.extend({},i.config,d.config,e),i.render()};M.prototype.config={limit:10,loading:!0,cellMinWidth:60,text:{none:\"无数据\"}},M.prototype.render=function(){var e=this,a=e.config;if(a.elem=t(a.elem),a.where=a.where||{},a.id=a.id||a.elem.attr(\"id\"),a.request=t.extend({pageName:\"page\",limitName:\"limit\"},a.request),a.response=t.extend({statusName:\"code\",statusCode:0,msgName:\"msg\",dataName:\"data\",countName:\"count\"},a.response),\"object\"==typeof a.page&&(a.limit=a.page.limit||a.limit,a.limits=a.page.limits||a.limits,e.page=a.page.curr=a.page.curr||1,delete a.page.elem,delete a.page.jump),!a.elem[0])return e;e.setArea();var l=a.elem,n=l.next(\".\"+y),o=e.elem=t(i(z).render({VIEW_CLASS:y,data:a,index:e.index}));if(a.index=e.index,n[0]&&n.remove(),l.after(o),e.layHeader=o.find(p),e.layMain=o.find(v),e.layBody=o.find(m),e.layFixed=o.find(g),e.layFixLeft=o.find(x),e.layFixRight=o.find(b),e.layTool=o.find(k),e.layPage=o.find(C),e.layTool.html(i(t(a.toolbar).html()||\"\").render(a)),a.height&&e.fullSize(),a.cols.length>1){var r=e.layFixed.find(p).find(\"th\");r.height(e.layHeader.height()-1-parseFloat(r.css(\"padding-top\"))-parseFloat(r.css(\"padding-bottom\")))}e.pullData(e.page),e.events()},M.prototype.initOpts=function(e){var t=this,i=(t.config,{checkbox:48,space:15,numbers:40});e.checkbox&&(e.type=\"checkbox\"),e.space&&(e.type=\"space\"),e.type||(e.type=\"normal\"),\"normal\"!==e.type&&(e.unresize=!0,e.width=e.width||i[e.type])},M.prototype.setArea=function(){var e=this,t=e.config,i=0,a=0,l=0,n=0,o=t.width||function(){var e=function(i){var a,l;i=i||t.elem.parent(),a=i.width();try{l=\"none\"===i.css(\"display\")}catch(n){}return!i[0]||a&&!l?a:e(i.parent())};return e()}();e.eachCols(function(){i++}),o-=function(){return\"line\"===t.skin||\"nob\"===t.skin?2:i+1}(),layui.each(t.cols,function(t,i){layui.each(i,function(t,l){var r;return l?(e.initOpts(l),r=l.width||0,void(l.colspan>1||(/\\d+%$/.test(r)?l.width=r=Math.floor(parseFloat(r)/100*o):r||(l.width=r=0,a++),n+=r))):void i.splice(t,1)})}),e.autoColNums=a,o>n&&a&&(l=(o-n)/a),layui.each(t.cols,function(e,i){layui.each(i,function(e,i){var a=i.minWidth||t.cellMinWidth;i.colspan>1||0===i.width&&(i.width=Math.floor(l>=a?l:a))})}),t.height&&/^full-\\d+$/.test(t.height)&&(e.fullHeightGap=t.height.split(\"-\")[1],t.height=A.height()-e.fullHeightGap)},M.prototype.reload=function(e){var i=this;i.config.data&&i.config.data.constructor===Array&&delete i.config.data,i.config=t.extend({},i.config,e),i.render()},M.prototype.page=1,M.prototype.pullData=function(e,i){var a=this,n=a.config,o=n.request,r=n.response,d=function(){\"object\"==typeof n.initSort&&a.sort(n.initSort.field,n.initSort.type)};if(a.startTime=(new Date).getTime(),n.url){var c={};c[o.pageName]=e,c[o.limitName]=n.limit;var s=t.extend(c,n.where);n.contentType&&0==n.contentType.indexOf(\"application/json\")&&(s=JSON.stringify(s)),t.ajax({type:n.method||\"get\",url:n.url,contentType:n.contentType,data:s,dataType:\"json\",headers:n.headers||{},success:function(t){t[r.statusName]!=r.statusCode?(a.renderForm(),a.layMain.html('<div class=\"'+f+'\">'+(t[r.msgName]||\"返回的数据状态异常\")+\"</div>\")):(a.renderData(t,e,t[r.countName]),d(),n.time=(new Date).getTime()-a.startTime+\" ms\"),i&&l.close(i),\"function\"==typeof n.done&&n.done(t,e,t[r.countName])},error:function(e,t){a.layMain.html('<div class=\"'+f+'\">数据接口请求异常</div>'),a.renderForm(),i&&l.close(i)}})}else if(n.data&&n.data.constructor===Array){var u={},h=e*n.limit-n.limit;u[r.dataName]=n.data.concat().splice(h,n.limit),u[r.countName]=n.data.length,a.renderData(u,e,n.data.length),d(),\"function\"==typeof n.done&&n.done(u,e,u[r.countName])}},M.prototype.eachCols=function(e){var i=t.extend(!0,[],this.config.cols),a=[],l=0;layui.each(i,function(e,t){layui.each(t,function(t,n){if(n.colspan>1){var o=0;l++,n.CHILD_COLS=[],layui.each(i[e+1],function(e,t){t.PARENT_COL||o==n.colspan||(t.PARENT_COL=l,n.CHILD_COLS.push(t),o+=t.colspan>1?t.colspan:1)})}n.PARENT_COL||a.push(n)})});var n=function(t){layui.each(t||a,function(t,i){return i.CHILD_COLS?n(i.CHILD_COLS):void e(t,i)})};n()},M.prototype.renderData=function(e,n,o,r){var c=this,s=c.config,u=e[s.response.dataName]||[],y=[],p=[],m=[],v=function(){return!r&&c.sortKey?c.sort(c.sortKey.field,c.sortKey.sort,!0):(layui.each(u,function(e,a){var l=[],o=[],u=[],h=e+s.limit*(n-1)+1;0!==a.length&&(r||(a[d.config.indexName]=e),c.eachCols(function(e,n){var r=n.field||e,f=a[r];c.getColElem(c.layHeader,r);if(void 0!==f&&null!==f||(f=\"\"),!(n.colspan>1)){var y=['<td data-field=\"'+r+'\" '+function(){var e=[];return n.edit&&e.push('data-edit=\"'+n.edit+'\"'),n.align&&e.push('align=\"'+n.align+'\"'),n.templet&&e.push('data-content=\"'+f+'\"'),n.toolbar&&e.push('data-off=\"true\"'),n.event&&e.push('lay-event=\"'+n.event+'\"'),n.style&&e.push('style=\"'+n.style+'\"'),n.minWidth&&e.push('data-minwidth=\"'+n.minWidth+'\"'),e.join(\" \")}()+\">\",'<div class=\"layui-table-cell laytable-cell-'+function(){var e=s.index+\"-\"+r;return\"normal\"===n.type?e:e+\" laytable-cell-\"+n.type}()+'\">'+function(){var e=t.extend(!0,{LAY_INDEX:h},a);return\"checkbox\"===n.type?'<input type=\"checkbox\" name=\"layTableCheckbox\" lay-skin=\"primary\" '+function(){var t=d.config.checkName;return n[t]?(a[t]=n[t],n[t]?\"checked\":\"\"):e[t]?\"checked\":\"\"}()+\">\":\"numbers\"===n.type?h:n.toolbar?i(t(n.toolbar).html()||\"\").render(e):n.templet?function(){return\"function\"==typeof n.templet?n.templet(e):i(t(n.templet).html()||String(f)).render(e)}():f}(),\"</div></td>\"].join(\"\");l.push(y),n.fixed&&\"right\"!==n.fixed&&o.push(y),\"right\"===n.fixed&&u.push(y)}}),y.push('<tr data-index=\"'+e+'\">'+l.join(\"\")+\"</tr>\"),p.push('<tr data-index=\"'+e+'\">'+o.join(\"\")+\"</tr>\"),m.push('<tr data-index=\"'+e+'\">'+u.join(\"\")+\"</tr>\"))}),c.layBody.scrollTop(0),c.layMain.find(\".\"+f).remove(),c.layMain.find(\"tbody\").html(y.join(\"\")),c.layFixLeft.find(\"tbody\").html(p.join(\"\")),c.layFixRight.find(\"tbody\").html(m.join(\"\")),c.renderForm(),c.syncCheckAll(),c.haveInit?c.scrollPatch():setTimeout(function(){c.scrollPatch()},50),c.haveInit=!0,void l.close(c.tipsIndex))};return c.key=s.id||s.index,d.cache[c.key]=u,c.layPage[0===u.length&&1==n?\"addClass\":\"removeClass\"](h),r?v():0===u.length?(c.renderForm(),c.layFixed.remove(),c.layMain.find(\"tbody\").html(\"\"),c.layMain.find(\".\"+f).remove(),c.layMain.append('<div class=\"'+f+'\">'+s.text.none+\"</div>\")):(v(),void(s.page&&(s.page=t.extend({elem:\"layui-table-page\"+s.index,count:o,limit:s.limit,limits:s.limits||[10,20,30,40,50,60,70,80,90],groups:3,layout:[\"prev\",\"page\",\"next\",\"skip\",\"count\",\"limit\"],prev:'<i class=\"layui-icon\">&#xe603;</i>',next:'<i class=\"layui-icon\">&#xe602;</i>',jump:function(e,t){t||(c.page=e.curr,s.limit=e.limit,c.pullData(e.curr,c.loading()))}},s.page),s.page.count=o,a.render(s.page))))},M.prototype.getColElem=function(e,t){var i=this,a=i.config;return e.eq(0).find(\".laytable-cell-\"+(a.index+\"-\"+t)+\":eq(0)\")},M.prototype.renderForm=function(e){n.render(e,\"LAY-table-\"+this.index)},M.prototype.sort=function(e,i,a,l){var n,r,c=this,u={},h=c.config,f=h.elem.attr(\"lay-filter\"),y=d.cache[c.key];\"string\"==typeof e&&c.layHeader.find(\"th\").each(function(i,a){var l=t(this),o=l.data(\"field\");if(o===e)return e=l,n=o,!1});try{var n=n||e.data(\"field\");if(c.sortKey&&!a&&n===c.sortKey.field&&i===c.sortKey.sort)return;var p=c.layHeader.find(\"th .laytable-cell-\"+h.index+\"-\"+n).find(w);c.layHeader.find(\"th\").find(w).removeAttr(\"lay-sort\"),p.attr(\"lay-sort\",i||null),c.layFixed.find(\"th\")}catch(m){return o.error(\"Table modules: Did not match to field\")}c.sortKey={field:n,sort:i},\"asc\"===i?r=layui.sort(y,n):\"desc\"===i?r=layui.sort(y,n,!0):(r=layui.sort(y,d.config.indexName),delete c.sortKey),u[h.response.dataName]=r,c.renderData(u,c.page,c.count,!0),l&&layui.event.call(e,s,\"sort(\"+f+\")\",{field:n,type:i})},M.prototype.loading=function(){var e=this,t=e.config;if(t.loading&&t.url)return l.msg(\"数据请求中\",{icon:16,offset:[e.elem.offset().top+e.elem.height()/2-35-A.scrollTop()+\"px\",e.elem.offset().left+e.elem.width()/2-90-A.scrollLeft()+\"px\"],time:-1,anim:-1,fixed:!1})},M.prototype.setCheckData=function(e,t){var i=this,a=i.config,l=d.cache[i.key];l[e]&&l[e].constructor!==Array&&(l[e][a.checkName]=t)},M.prototype.syncCheckAll=function(){var e=this,t=e.config,i=e.layHeader.find('input[name=\"layTableCheckbox\"]'),a=function(i){return e.eachCols(function(e,a){\"checkbox\"===a.type&&(a[t.checkName]=i)}),i};i[0]&&(d.checkStatus(e.key).isAll?(i[0].checked||(i.prop(\"checked\",!0),e.renderForm(\"checkbox\")),a(!0)):(i[0].checked&&(i.prop(\"checked\",!1),e.renderForm(\"checkbox\")),a(!1)))},M.prototype.getCssRule=function(e,t){var i=this,a=i.elem.find(\"style\")[0],l=a.sheet||a.styleSheet||{},n=l.cssRules||l.rules;layui.each(n,function(a,l){if(l.selectorText===\".laytable-cell-\"+i.index+\"-\"+e)return t(l),!0})},M.prototype.fullSize=function(){var e,t=this,i=t.config,a=i.height;t.fullHeightGap&&(a=A.height()-t.fullHeightGap,a<135&&(a=135),t.elem.css(\"height\",a)),e=parseFloat(a)-parseFloat(t.layHeader.height())-1,i.toolbar&&(e-=t.layTool.outerHeight()),i.page&&(e=e-t.layPage.outerHeight()-1),t.layMain.css(\"height\",e)},M.prototype.getScrollWidth=function(e){var t=0;return e?t=e.offsetWidth-e.clientWidth:(e=document.createElement(\"div\"),e.style.width=\"100px\",e.style.height=\"100px\",e.style.overflowY=\"scroll\",document.body.appendChild(e),t=e.offsetWidth-e.clientWidth,document.body.removeChild(e)),t},M.prototype.scrollPatch=function(){var e=this,i=e.layMain.children(\"table\"),a=e.layMain.width()-e.layMain.prop(\"clientWidth\"),l=e.layMain.height()-e.layMain.prop(\"clientHeight\"),n=e.getScrollWidth(e.layMain[0]),o=i.outerWidth()-e.layMain.width();if(e.autoColNums&&o<5&&!e.scrollPatchWStatus){var r=e.layHeader.eq(0).find(\"thead th:last-child\"),d=r.data(\"field\");e.getCssRule(d,function(t){var i=t.style.width||r.outerWidth();t.style.width=parseFloat(i)-n-o+\"px\",e.layMain.height()-e.layMain.prop(\"clientHeight\")>0&&(t.style.width=parseFloat(t.style.width)-1+\"px\"),e.scrollPatchWStatus=!0})}if(a&&l){if(!e.elem.find(\".layui-table-patch\")[0]){var c=t('<th class=\"layui-table-patch\"><div class=\"layui-table-cell\"></div></th>');c.find(\"div\").css({width:a}),e.layHeader.eq(0).find(\"thead tr\").append(c)}}else e.layHeader.eq(0).find(\".layui-table-patch\").remove();var s=e.layMain.height(),u=s-l;e.layFixed.find(m).css(\"height\",i.height()>u?u:\"auto\"),e.layFixRight[o>0?\"removeClass\":\"addClass\"](h),e.layFixRight.css(\"right\",a-1)},M.prototype.events=function(){var e,a=this,n=a.config,o=t(\"body\"),c={},u=a.layHeader.find(\"th\"),h=\".layui-table-cell\",f=n.elem.attr(\"lay-filter\");u.on(\"mousemove\",function(e){var i=t(this),a=i.offset().left,l=e.clientX-a;i.attr(\"colspan\")>1||i.data(\"unresize\")||c.resizeStart||(c.allowResize=i.width()-l<=10,o.css(\"cursor\",c.allowResize?\"col-resize\":\"\"))}).on(\"mouseleave\",function(){t(this);c.resizeStart||o.css(\"cursor\",\"\")}).on(\"mousedown\",function(e){var i=t(this);if(c.allowResize){var l=i.data(\"field\");e.preventDefault(),c.resizeStart=!0,c.offset=[e.clientX,e.clientY],a.getCssRule(l,function(e){var t=e.style.width||i.outerWidth();c.rule=e,c.ruleWidth=parseFloat(t),c.minWidth=i.data(\"minwidth\")||n.cellMinWidth})}}),S.on(\"mousemove\",function(t){if(c.resizeStart){if(t.preventDefault(),c.rule){var i=c.ruleWidth+t.clientX-c.offset[0];i<c.minWidth&&(i=c.minWidth),c.rule.style.width=i+\"px\",l.close(a.tipsIndex)}e=1}}).on(\"mouseup\",function(t){c.resizeStart&&(c={},o.css(\"cursor\",\"\"),a.scrollPatch()),2===e&&(e=null)}),u.on(\"click\",function(){var i,l=t(this),n=l.find(w),o=n.attr(\"lay-sort\");return n[0]&&1!==e?(i=\"asc\"===o?\"desc\":\"desc\"===o?null:\"asc\",void a.sort(l,i,null,!0)):e=2}).find(w+\" .layui-edge \").on(\"click\",function(e){var i=t(this),l=i.index(),n=i.parents(\"th\").eq(0).data(\"field\");layui.stope(e),0===l?a.sort(n,\"asc\",null,!0):a.sort(n,\"desc\",null,!0)}),a.elem.on(\"click\",'input[name=\"layTableCheckbox\"]+',function(){var e=t(this).prev(),i=a.layBody.find('input[name=\"layTableCheckbox\"]'),l=e.parents(\"tr\").eq(0).data(\"index\"),n=e[0].checked,o=\"layTableAllChoose\"===e.attr(\"lay-filter\");o?(i.each(function(e,t){t.checked=n,a.setCheckData(e,n)}),a.syncCheckAll(),a.renderForm(\"checkbox\")):(a.setCheckData(l,n),a.syncCheckAll()),layui.event.call(this,s,\"checkbox(\"+f+\")\",{checked:n,data:d.cache[a.key]?d.cache[a.key][l]||{}:{},type:o?\"all\":\"one\"})}),a.layBody.on(\"mouseenter\",\"tr\",function(){var e=t(this),i=e.index();a.layBody.find(\"tr:eq(\"+i+\")\").addClass(T)}).on(\"mouseleave\",\"tr\",function(){var e=t(this),i=e.index();a.layBody.find(\"tr:eq(\"+i+\")\").removeClass(T)}),a.layBody.on(\"change\",\".\"+N,function(){var e=t(this),i=this.value,l=e.parent().data(\"field\"),n=e.parents(\"tr\").eq(0).data(\"index\"),o=d.cache[a.key][n];o[l]=i,layui.event.call(this,s,\"edit(\"+f+\")\",{value:i,data:o,field:l})}).on(\"blur\",\".\"+N,function(){var e,l=t(this),n=l.parent().data(\"field\"),o=l.parents(\"tr\").eq(0).data(\"index\"),r=d.cache[a.key][o];a.eachCols(function(t,i){i.field==n&&i.templet&&(e=i.templet)}),l.siblings(h).html(e?i(t(e).html()||this.value).render(r):this.value),l.parent().data(\"content\",this.value),l.remove()}),a.layBody.on(\"click\",\"td\",function(){var e=t(this),i=(e.data(\"field\"),e.data(\"edit\")),o=e.children(h);if(l.close(a.tipsIndex),!e.data(\"off\"))if(i)if(\"select\"===i);else{var d=t('<input class=\"layui-input '+N+'\">');d[0].value=e.data(\"content\")||o.text(),e.find(\".\"+N)[0]||e.append(d),d.focus()}else o.find(\".layui-form-switch,.layui-form-checkbox\")[0]||Math.round(o.prop(\"scrollWidth\"))>Math.round(o.outerWidth())&&(a.tipsIndex=l.tips(['<div class=\"layui-table-tips-main\" style=\"margin-top: -'+(o.height()+16)+\"px;\"+function(){return\"sm\"===n.size?\"padding: 4px 15px; font-size: 12px;\":\"lg\"===n.size?\"padding: 14px 15px;\":\"\"}()+'\">',o.html(),\"</div>\",'<i class=\"layui-icon layui-table-tips-c\">&#x1006;</i>'].join(\"\"),o[0],{tips:[3,\"\"],time:-1,anim:-1,maxWidth:r.ios||r.android?300:600,isOutAnim:!1,skin:\"layui-table-tips\",success:function(e,t){e.find(\".layui-table-tips-c\").on(\"click\",function(){l.close(t)})}}))}),a.layBody.on(\"click\",\"*[lay-event]\",function(){var e=t(this),l=e.parents(\"tr\").eq(0).data(\"index\"),n=a.layBody.find('tr[data-index=\"'+l+'\"]'),o=\"layui-table-click\",r=d.cache[a.key][l];layui.event.call(this,s,\"tool(\"+f+\")\",{data:d.clearCacheKey(r),event:e.attr(\"lay-event\"),tr:n,del:function(){d.cache[a.key][l]=[],n.remove(),a.scrollPatch()},update:function(e){e=e||{},layui.each(e,function(e,l){if(e in r){var o,d=n.children('td[data-field=\"'+e+'\"]');r[e]=l,a.eachCols(function(t,i){i.field==e&&i.templet&&(o=i.templet)}),d.children(h).html(o?i(t(o).html()||l).render(r):l),d.data(\"content\",l)}})}}),n.addClass(o).siblings(\"tr\").removeClass(o)}),a.layMain.on(\"scroll\",function(){var e=t(this),i=e.scrollLeft(),n=e.scrollTop();a.layHeader.scrollLeft(i),a.layFixed.find(m).scrollTop(n),l.close(a.tipsIndex)}),A.on(\"resize\",function(){a.fullSize(),a.scrollPatch()})},d.init=function(e,i){i=i||{};var a=this,l=t(e?'table[lay-filter=\"'+e+'\"]':u+\"[lay-data]\"),n=\"Table element property lay-data configuration item has a syntax error: \";return l.each(function(){var a=t(this),l=a.attr(\"lay-data\");try{l=new Function(\"return \"+l)()}catch(r){o.error(n+l)}var c=[],s=t.extend({elem:this,cols:[],data:[],skin:a.attr(\"lay-skin\"),size:a.attr(\"lay-size\"),even:\"string\"==typeof a.attr(\"lay-even\")},d.config,i,l);e&&a.hide(),a.find(\"thead>tr\").each(function(e){s.cols[e]=[],t(this).children().each(function(i){var a=t(this),l=a.attr(\"lay-data\");try{l=new Function(\"return \"+l)()}catch(r){return o.error(n+l)}var d=t.extend({title:a.text(),colspan:a.attr(\"colspan\")||0,rowspan:a.attr(\"rowspan\")||0},l);d.colspan<2&&c.push(d),s.cols[e].push(d)})}),a.find(\"tbody>tr\").each(function(e){var i=t(this),a={};i.children(\"td\").each(function(e,i){var l=t(this),n=l.data(\"field\");if(n)return a[n]=l.html()}),layui.each(c,function(e,t){var l=i.children(\"td\").eq(e);a[t.field]=l.html()}),s.data[e]=a}),d.render(s)}),a},d.checkStatus=function(e){var t=0,i=0,a=[],l=d.cache[e]||[];return layui.each(l,function(e,l){return l.constructor===Array?void i++:void(l[d.config.checkName]&&(t++,a.push(d.clearCacheKey(l))))}),{data:a,isAll:!!l.length&&t===l.length-i}},c.config={},d.reload=function(e,i){var a=c.config[e];return i=i||{},a?(i.data&&i.data.constructor===Array&&delete a.data,d.render(t.extend(!0,{},a,i))):o.error(\"The ID option was not found in the table instance\")},d.render=function(e){var t=new M(e);return c.call(t)},d.clearCacheKey=function(e){return e=t.extend({},e),delete e[d.config.checkName],delete e[d.config.indexName],e},d.init(),e(s,d)});layui.define(\"jquery\",function(e){\"use strict\";var i=layui.$,n=(layui.hint(),layui.device(),{config:{},set:function(e){var n=this;return n.config=i.extend({},n.config,e),n},on:function(e,i){return layui.onevent.call(this,t,e,i)}}),t=\"carousel\",a=\"layui-this\",l=\">*[carousel-item]>*\",o=\"layui-carousel-left\",r=\"layui-carousel-right\",d=\"layui-carousel-prev\",s=\"layui-carousel-next\",u=\"layui-carousel-arrow\",c=\"layui-carousel-ind\",m=function(e){var t=this;t.config=i.extend({},t.config,n.config,e),t.render()};m.prototype.config={width:\"600px\",height:\"280px\",full:!1,arrow:\"hover\",indicator:\"inside\",autoplay:!0,interval:3e3,anim:\"\",trigger:\"click\",index:0},m.prototype.render=function(){var e=this,n=e.config;n.elem=i(n.elem),n.elem[0]&&(e.elemItem=n.elem.find(l),n.index<0&&(n.index=0),n.index>=e.elemItem.length&&(n.index=e.elemItem.length-1),n.interval<800&&(n.interval=800),n.full?n.elem.css({position:\"fixed\",width:\"100%\",height:\"100%\",zIndex:9999}):n.elem.css({width:n.width,height:n.height}),n.elem.attr(\"lay-anim\",n.anim),e.elemItem.eq(n.index).addClass(a),e.elemItem.length<=1||(e.indicator(),e.arrow(),e.autoplay(),e.events()))},m.prototype.reload=function(e){var n=this;clearInterval(n.timer),n.config=i.extend({},n.config,e),n.render()},m.prototype.prevIndex=function(){var e=this,i=e.config,n=i.index-1;return n<0&&(n=e.elemItem.length-1),n},m.prototype.nextIndex=function(){var e=this,i=e.config,n=i.index+1;return n>=e.elemItem.length&&(n=0),n},m.prototype.addIndex=function(e){var i=this,n=i.config;e=e||1,n.index=n.index+e,n.index>=i.elemItem.length&&(n.index=0)},m.prototype.subIndex=function(e){var i=this,n=i.config;e=e||1,n.index=n.index-e,n.index<0&&(n.index=i.elemItem.length-1)},m.prototype.autoplay=function(){var e=this,i=e.config;i.autoplay&&(e.timer=setInterval(function(){e.slide()},i.interval))},m.prototype.arrow=function(){var e=this,n=e.config,t=i(['<button class=\"layui-icon '+u+'\" lay-type=\"sub\">'+(\"updown\"===n.anim?\"&#xe619;\":\"&#xe603;\")+\"</button>\",'<button class=\"layui-icon '+u+'\" lay-type=\"add\">'+(\"updown\"===n.anim?\"&#xe61a;\":\"&#xe602;\")+\"</button>\"].join(\"\"));n.elem.attr(\"lay-arrow\",n.arrow),n.elem.find(\".\"+u)[0]&&n.elem.find(\".\"+u).remove(),n.elem.append(t),t.on(\"click\",function(){var n=i(this),t=n.attr(\"lay-type\");e.slide(t)})},m.prototype.indicator=function(){var e=this,n=e.config,t=e.elemInd=i(['<div class=\"'+c+'\"><ul>',function(){var i=[];return layui.each(e.elemItem,function(e){i.push(\"<li\"+(n.index===e?' class=\"layui-this\"':\"\")+\"></li>\")}),i.join(\"\")}(),\"</ul></div>\"].join(\"\"));n.elem.attr(\"lay-indicator\",n.indicator),n.elem.find(\".\"+c)[0]&&n.elem.find(\".\"+c).remove(),n.elem.append(t),\"updown\"===n.anim&&t.css(\"margin-top\",-(t.height()/2)),t.find(\"li\").on(\"hover\"===n.trigger?\"mouseover\":n.trigger,function(){var t=i(this),a=t.index();a>n.index?e.slide(\"add\",a-n.index):a<n.index&&e.slide(\"sub\",n.index-a)})},m.prototype.slide=function(e,i){var n=this,l=n.elemItem,u=n.config,c=u.index,m=u.elem.attr(\"lay-filter\");n.haveSlide||(\"sub\"===e?(n.subIndex(i),l.eq(u.index).addClass(d),setTimeout(function(){l.eq(c).addClass(r),l.eq(u.index).addClass(r)},50)):(n.addIndex(i),l.eq(u.index).addClass(s),setTimeout(function(){l.eq(c).addClass(o),l.eq(u.index).addClass(o)},50)),setTimeout(function(){l.removeClass(a+\" \"+d+\" \"+s+\" \"+o+\" \"+r),l.eq(u.index).addClass(a),n.haveSlide=!1},300),n.elemInd.find(\"li\").eq(u.index).addClass(a).siblings().removeClass(a),n.haveSlide=!0,layui.event.call(this,t,\"change(\"+m+\")\",{index:u.index,prevIndex:c,item:l.eq(u.index)}))},m.prototype.events=function(){var e=this,i=e.config;i.elem.data(\"haveEvents\")||(i.elem.on(\"mouseenter\",function(){clearInterval(e.timer)}).on(\"mouseleave\",function(){e.autoplay()}),i.elem.data(\"haveEvents\",!0))},n.render=function(e){var i=new m(e);return i},e(t,n)});layui.define(\"jquery\",function(e){\"use strict\";var t=layui.$,i={fixbar:function(e){var i,o,a=\"layui-fixbar\",r=\"layui-fixbar-top\",n=t(document),l=t(\"body\");e=t.extend({showHeight:200},e),e.bar1=e.bar1===!0?\"&#xe606;\":e.bar1,e.bar2=e.bar2===!0?\"&#xe607;\":e.bar2,e.bgcolor=e.bgcolor?\"background-color:\"+e.bgcolor:\"\";var c=[e.bar1,e.bar2,\"&#xe604;\"],g=t(['<ul class=\"'+a+'\">',e.bar1?'<li class=\"layui-icon\" lay-type=\"bar1\" style=\"'+e.bgcolor+'\">'+c[0]+\"</li>\":\"\",e.bar2?'<li class=\"layui-icon\" lay-type=\"bar2\" style=\"'+e.bgcolor+'\">'+c[1]+\"</li>\":\"\",'<li class=\"layui-icon '+r+'\" lay-type=\"top\" style=\"'+e.bgcolor+'\">'+c[2]+\"</li>\",\"</ul>\"].join(\"\")),s=g.find(\".\"+r),u=function(){var t=n.scrollTop();t>=e.showHeight?i||(s.show(),i=1):i&&(s.hide(),i=0)};t(\".\"+a)[0]||(\"object\"==typeof e.css&&g.css(e.css),l.append(g),u(),g.find(\"li\").on(\"click\",function(){var i=t(this),o=i.attr(\"lay-type\");\"top\"===o&&t(\"html,body\").animate({scrollTop:0},200),e.click&&e.click.call(this,o)}),n.on(\"scroll\",function(){clearTimeout(o),o=setTimeout(function(){u()},100)}))},countdown:function(e,t,i){var o=this,a=\"function\"==typeof t,r=new Date(e).getTime(),n=new Date(!t||a?(new Date).getTime():t).getTime(),l=r-n,c=[Math.floor(l/864e5),Math.floor(l/36e5)%24,Math.floor(l/6e4)%60,Math.floor(l/1e3)%60];a&&(i=t);var g=setTimeout(function(){o.countdown(e,n+1e3,i)},1e3);return i&&i(l>0?c:[0,0,0,0],t,g),l<=0&&clearTimeout(g),g},timeAgo:function(e,t){var i=this,o=[[],[]],a=(new Date).getTime()-new Date(e).getTime();return a>6912e5?(a=new Date(e),o[0][0]=i.digit(a.getFullYear(),4),o[0][1]=i.digit(a.getMonth()+1),o[0][2]=i.digit(a.getDate()),t||(o[1][0]=i.digit(a.getHours()),o[1][1]=i.digit(a.getMinutes()),o[1][2]=i.digit(a.getSeconds())),o[0].join(\"-\")+\" \"+o[1].join(\":\")):a>=864e5?(a/1e3/60/60/24|0)+\"天前\":a>=36e5?(a/1e3/60/60|0)+\"小时前\":a>=12e4?(a/1e3/60|0)+\"分钟前\":a<0?\"未来\":\"刚刚\"},digit:function(e,t){var i=\"\";e=String(e),t=t||2;for(var o=e.length;o<t;o++)i+=\"0\";return e<Math.pow(10,t)?i+(0|e):e},toDateString:function(e,t){var i=this,o=new Date(e||new Date),a=[i.digit(o.getFullYear(),4),i.digit(o.getMonth()+1),i.digit(o.getDate())],r=[i.digit(o.getHours()),i.digit(o.getMinutes()),i.digit(o.getSeconds())];return t=t||\"yyyy-MM-dd HH:mm:ss\",t.replace(/yyyy/g,a[0]).replace(/MM/g,a[1]).replace(/dd/g,a[2]).replace(/HH/g,r[0]).replace(/mm/g,r[1]).replace(/ss/g,r[2])}};e(\"util\",i)});layui.define(\"jquery\",function(e){\"use strict\";var l=layui.$,o=function(e){},t='<i class=\"layui-anim layui-anim-rotate layui-anim-loop layui-icon \">&#xe63e;</i>';o.prototype.load=function(e){var o,i,n,r,a=this,c=0;e=e||{};var f=l(e.elem);if(f[0]){var m=l(e.scrollElem||document),u=e.mb||50,s=!(\"isAuto\"in e)||e.isAuto,v=e.end||\"没有更多了\",y=e.scrollElem&&e.scrollElem!==document,d=\"<cite>加载更多</cite>\",h=l('<div class=\"layui-flow-more\"><a href=\"javascript:;\">'+d+\"</a></div>\");f.find(\".layui-flow-more\")[0]||f.append(h);var p=function(e,t){e=l(e),h.before(e),t=0==t||null,t?h.html(v):h.find(\"a\").html(d),i=t,o=null,n&&n()},g=function(){o=!0,h.find(\"a\").html(t),\"function\"==typeof e.done&&e.done(++c,p)};if(g(),h.find(\"a\").on(\"click\",function(){l(this);i||o||g()}),e.isLazyimg)var n=a.lazyimg({elem:e.elem+\" img\",scrollElem:e.scrollElem});return s?(m.on(\"scroll\",function(){var e=l(this),t=e.scrollTop();r&&clearTimeout(r),i||(r=setTimeout(function(){var i=y?e.height():l(window).height(),n=y?e.prop(\"scrollHeight\"):document.documentElement.scrollHeight;n-t-i<=u&&(o||g())},100))}),a):a}},o.prototype.lazyimg=function(e){var o,t=this,i=0;e=e||{};var n=l(e.scrollElem||document),r=e.elem||\"img\",a=e.scrollElem&&e.scrollElem!==document,c=function(e,l){var o=n.scrollTop(),r=o+l,c=a?function(){return e.offset().top-n.offset().top+o}():e.offset().top;if(c>=o&&c<=r&&!e.attr(\"src\")){var m=e.attr(\"lay-src\");layui.img(m,function(){var l=t.lazyimg.elem.eq(i);e.attr(\"src\",m).removeAttr(\"lay-src\"),l[0]&&f(l),i++})}},f=function(e,o){var f=a?(o||n).height():l(window).height(),m=n.scrollTop(),u=m+f;if(t.lazyimg.elem=l(r),e)c(e,f);else for(var s=0;s<t.lazyimg.elem.length;s++){var v=t.lazyimg.elem.eq(s),y=a?function(){return v.offset().top-n.offset().top+m}():v.offset().top;if(c(v,f),i=s,y>u)break}};if(f(),!o){var m;n.on(\"scroll\",function(){var e=l(this);m&&clearTimeout(m),m=setTimeout(function(){f(null,e)},50)}),o=!0}return f},e(\"flow\",new o)});layui.define([\"layer\",\"form\"],function(t){\"use strict\";var e=layui.$,i=layui.layer,a=layui.form,l=(layui.hint(),layui.device()),n=\"layedit\",o=\"layui-show\",r=\"layui-disabled\",c=function(){var t=this;t.index=0,t.config={tool:[\"strong\",\"italic\",\"underline\",\"del\",\"|\",\"left\",\"center\",\"right\",\"|\",\"link\",\"unlink\",\"face\",\"image\"],hideTool:[],height:280}};c.prototype.set=function(t){var i=this;return e.extend(!0,i.config,t),i},c.prototype.on=function(t,e){return layui.onevent(n,t,e)},c.prototype.build=function(t,i){i=i||{};var a=this,n=a.config,r=\"layui-layedit\",c=e(\"string\"==typeof t?\"#\"+t:t),u=\"LAY_layedit_\"+ ++a.index,d=c.next(\".\"+r),y=e.extend({},n,i),f=function(){var t=[],e={};return layui.each(y.hideTool,function(t,i){e[i]=!0}),layui.each(y.tool,function(i,a){C[a]&&!e[a]&&t.push(C[a])}),t.join(\"\")}(),m=e(['<div class=\"'+r+'\">','<div class=\"layui-unselect layui-layedit-tool\">'+f+\"</div>\",'<div class=\"layui-layedit-iframe\">','<iframe id=\"'+u+'\" name=\"'+u+'\" textarea=\"'+t+'\" frameborder=\"0\"></iframe>',\"</div>\",\"</div>\"].join(\"\"));return l.ie&&l.ie<8?c.removeClass(\"layui-hide\").addClass(o):(d[0]&&d.remove(),s.call(a,m,c[0],y),c.addClass(\"layui-hide\").after(m),a.index)},c.prototype.getContent=function(t){var e=u(t);if(e[0])return d(e[0].document.body.innerHTML)},c.prototype.getText=function(t){var i=u(t);if(i[0])return e(i[0].document.body).text()},c.prototype.setContent=function(t,i,a){var l=u(t);l[0]&&(a?e(l[0].document.body).append(i):e(l[0].document.body).html(i),layedit.sync(t))},c.prototype.sync=function(t){var i=u(t);if(i[0]){var a=e(\"#\"+i[1].attr(\"textarea\"));a.val(d(i[0].document.body.innerHTML))}},c.prototype.getSelection=function(t){var e=u(t);if(e[0]){var i=m(e[0].document);return document.selection?i.text:i.toString()}};var s=function(t,i,a){var l=this,n=t.find(\"iframe\");n.css({height:a.height}).on(\"load\",function(){var o=n.contents(),r=n.prop(\"contentWindow\"),c=o.find(\"head\"),s=e([\"<style>\",\"*{margin: 0; padding: 0;}\",\"body{padding: 10px; line-height: 20px; overflow-x: hidden; word-wrap: break-word; font: 14px Helvetica Neue,Helvetica,PingFang SC,Microsoft YaHei,Tahoma,Arial,sans-serif; -webkit-box-sizing: border-box !important; -moz-box-sizing: border-box !important; box-sizing: border-box !important;}\",\"a{color:#01AAED; text-decoration:none;}a:hover{color:#c00}\",\"p{margin-bottom: 10px;}\",\"img{display: inline-block; border: none; vertical-align: middle;}\",\"pre{margin: 10px 0; padding: 10px; line-height: 20px; border: 1px solid #ddd; border-left-width: 6px; background-color: #F2F2F2; color: #333; font-family: Courier New; font-size: 12px;}\",\"</style>\"].join(\"\")),u=o.find(\"body\");c.append(s),u.attr(\"contenteditable\",\"true\").css({\"min-height\":a.height}).html(i.value||\"\"),y.apply(l,[r,n,i,a]),g.call(l,r,t,a)})},u=function(t){var i=e(\"#LAY_layedit_\"+t),a=i.prop(\"contentWindow\");return[a,i]},d=function(t){return 8==l.ie&&(t=t.replace(/<.+>/g,function(t){return t.toLowerCase()})),t},y=function(t,a,n,o){var r=t.document,c=e(r.body);c.on(\"keydown\",function(t){var e=t.keyCode;if(13===e){var a=m(r),l=p(a),n=l.parentNode;if(\"pre\"===n.tagName.toLowerCase()){if(t.shiftKey)return;return i.msg(\"请暂时用shift+enter\"),!1}r.execCommand(\"formatBlock\",!1,\"<p>\")}}),e(n).parents(\"form\").on(\"submit\",function(){var t=c.html();8==l.ie&&(t=t.replace(/<.+>/g,function(t){return t.toLowerCase()})),n.value=t}),c.on(\"paste\",function(e){r.execCommand(\"formatBlock\",!1,\"<p>\"),setTimeout(function(){f.call(t,c),n.value=c.html()},100)})},f=function(t){var i=this;i.document;t.find(\"*[style]\").each(function(){var t=this.style.textAlign;this.removeAttribute(\"style\"),e(this).css({\"text-align\":t||\"\"})}),t.find(\"table\").addClass(\"layui-table\"),t.find(\"script,link\").remove()},m=function(t){return t.selection?t.selection.createRange():t.getSelection().getRangeAt(0)},p=function(t){return t.endContainer||t.parentElement().childNodes[0]},v=function(t,i,a){var l=this.document,n=document.createElement(t);for(var o in i)n.setAttribute(o,i[o]);if(n.removeAttribute(\"text\"),l.selection){var r=a.text||i.text;if(\"a\"===t&&!r)return;r&&(n.innerHTML=r),a.pasteHTML(e(n).prop(\"outerHTML\")),a.select()}else{var r=a.toString()||i.text;if(\"a\"===t&&!r)return;r&&(n.innerHTML=r),a.deleteContents(),a.insertNode(n)}},h=function(t,i){var a=this.document,l=\"layedit-tool-active\",n=p(m(a)),o=function(e){return t.find(\".layedit-tool-\"+e)};i&&i[i.hasClass(l)?\"removeClass\":\"addClass\"](l),t.find(\">i\").removeClass(l),o(\"unlink\").addClass(r),e(n).parents().each(function(){var t=this.tagName.toLowerCase(),e=this.style.textAlign;\"b\"!==t&&\"strong\"!==t||o(\"b\").addClass(l),\"i\"!==t&&\"em\"!==t||o(\"i\").addClass(l),\"u\"===t&&o(\"u\").addClass(l),\"strike\"===t&&o(\"d\").addClass(l),\"p\"===t&&(\"center\"===e?o(\"center\").addClass(l):\"right\"===e?o(\"right\").addClass(l):o(\"left\").addClass(l)),\"a\"===t&&(o(\"link\").addClass(l),o(\"unlink\").removeClass(r))})},g=function(t,a,l){var n=t.document,o=e(n.body),c={link:function(i){var a=p(i),l=e(a).parent();b.call(o,{href:l.attr(\"href\"),target:l.attr(\"target\")},function(e){var a=l[0];\"A\"===a.tagName?a.href=e.url:v.call(t,\"a\",{target:e.target,href:e.url,text:e.url},i)})},unlink:function(t){n.execCommand(\"unlink\")},face:function(e){x.call(this,function(i){v.call(t,\"img\",{src:i.src,alt:i.alt},e)})},image:function(a){var n=this;layui.use(\"upload\",function(o){var r=l.uploadImage||{};o.render({url:r.url,method:r.type,elem:e(n).find(\"input\")[0],done:function(e){0==e.code?(e.data=e.data||{},v.call(t,\"img\",{src:e.data.src,alt:e.data.title},a)):i.msg(e.msg||\"上传失败\")}})})},code:function(e){k.call(o,function(i){v.call(t,\"pre\",{text:i.code,\"lay-lang\":i.lang},e)})},help:function(){i.open({type:2,title:\"帮助\",area:[\"600px\",\"380px\"],shadeClose:!0,shade:.1,skin:\"layui-layer-msg\",content:[\"http://www.layui.com/about/layedit/help.html\",\"no\"]})}},s=a.find(\".layui-layedit-tool\"),u=function(){var i=e(this),a=i.attr(\"layedit-event\"),l=i.attr(\"lay-command\");if(!i.hasClass(r)){o.focus();var u=m(n);u.commonAncestorContainer;l?(n.execCommand(l),/justifyLeft|justifyCenter|justifyRight/.test(l)&&n.execCommand(\"formatBlock\",!1,\"<p>\"),setTimeout(function(){o.focus()},10)):c[a]&&c[a].call(this,u),h.call(t,s,i)}},d=/image/;s.find(\">i\").on(\"mousedown\",function(){var t=e(this),i=t.attr(\"layedit-event\");d.test(i)||u.call(this)}).on(\"click\",function(){var t=e(this),i=t.attr(\"layedit-event\");d.test(i)&&u.call(this)}),o.on(\"click\",function(){h.call(t,s),i.close(x.index)})},b=function(t,e){var l=this,n=i.open({type:1,id:\"LAY_layedit_link\",area:\"350px\",shade:.05,shadeClose:!0,moveType:1,title:\"超链接\",skin:\"layui-layer-msg\",content:['<ul class=\"layui-form\" style=\"margin: 15px;\">','<li class=\"layui-form-item\">','<label class=\"layui-form-label\" style=\"width: 60px;\">URL</label>','<div class=\"layui-input-block\" style=\"margin-left: 90px\">','<input name=\"url\" lay-verify=\"url\" value=\"'+(t.href||\"\")+'\" autofocus=\"true\" autocomplete=\"off\" class=\"layui-input\">',\"</div>\",\"</li>\",'<li class=\"layui-form-item\">','<label class=\"layui-form-label\" style=\"width: 60px;\">打开方式</label>','<div class=\"layui-input-block\" style=\"margin-left: 90px\">','<input type=\"radio\" name=\"target\" value=\"_self\" class=\"layui-input\" title=\"当前窗口\"'+(\"_self\"!==t.target&&t.target?\"\":\"checked\")+\">\",'<input type=\"radio\" name=\"target\" value=\"_blank\" class=\"layui-input\" title=\"新窗口\" '+(\"_blank\"===t.target?\"checked\":\"\")+\">\",\"</div>\",\"</li>\",'<li class=\"layui-form-item\" style=\"text-align: center;\">','<button type=\"button\" lay-submit lay-filter=\"layedit-link-yes\" class=\"layui-btn\"> 确定 </button>','<button style=\"margin-left: 20px;\" type=\"button\" class=\"layui-btn layui-btn-primary\"> 取消 </button>',\"</li>\",\"</ul>\"].join(\"\"),success:function(t,n){var o=\"submit(layedit-link-yes)\";a.render(\"radio\"),t.find(\".layui-btn-primary\").on(\"click\",function(){i.close(n),l.focus()}),a.on(o,function(t){i.close(b.index),e&&e(t.field)})}});b.index=n},x=function(t){var a=function(){var t=[\"[微笑]\",\"[嘻嘻]\",\"[哈哈]\",\"[可爱]\",\"[可怜]\",\"[挖鼻]\",\"[吃惊]\",\"[害羞]\",\"[挤眼]\",\"[闭嘴]\",\"[鄙视]\",\"[爱你]\",\"[泪]\",\"[偷笑]\",\"[亲亲]\",\"[生病]\",\"[太开心]\",\"[白眼]\",\"[右哼哼]\",\"[左哼哼]\",\"[嘘]\",\"[衰]\",\"[委屈]\",\"[吐]\",\"[哈欠]\",\"[抱抱]\",\"[怒]\",\"[疑问]\",\"[馋嘴]\",\"[拜拜]\",\"[思考]\",\"[汗]\",\"[困]\",\"[睡]\",\"[钱]\",\"[失望]\",\"[酷]\",\"[色]\",\"[哼]\",\"[鼓掌]\",\"[晕]\",\"[悲伤]\",\"[抓狂]\",\"[黑线]\",\"[阴险]\",\"[怒骂]\",\"[互粉]\",\"[心]\",\"[伤心]\",\"[猪头]\",\"[熊猫]\",\"[兔子]\",\"[ok]\",\"[耶]\",\"[good]\",\"[NO]\",\"[赞]\",\"[来]\",\"[弱]\",\"[草泥马]\",\"[神马]\",\"[囧]\",\"[浮云]\",\"[给力]\",\"[围观]\",\"[威武]\",\"[奥特曼]\",\"[礼物]\",\"[钟]\",\"[话筒]\",\"[蜡烛]\",\"[蛋糕]\"],e={};return layui.each(t,function(t,i){e[i]=layui.cache.dir+\"images/face/\"+t+\".gif\"}),e}();return x.hide=x.hide||function(t){\"face\"!==e(t.target).attr(\"layedit-event\")&&i.close(x.index)},x.index=i.tips(function(){var t=[];return layui.each(a,function(e,i){t.push('<li title=\"'+e+'\"><img src=\"'+i+'\" alt=\"'+e+'\"></li>')}),'<ul class=\"layui-clear\">'+t.join(\"\")+\"</ul>\"}(),this,{tips:1,time:0,skin:\"layui-box layui-util-face\",maxWidth:500,success:function(l,n){l.css({marginTop:-4,marginLeft:-10}).find(\".layui-clear>li\").on(\"click\",function(){t&&t({src:a[this.title],alt:this.title}),i.close(n)}),e(document).off(\"click\",x.hide).on(\"click\",x.hide)}})},k=function(t){var e=this,l=i.open({type:1,id:\"LAY_layedit_code\",area:\"550px\",shade:.05,shadeClose:!0,moveType:1,title:\"插入代码\",skin:\"layui-layer-msg\",content:['<ul class=\"layui-form layui-form-pane\" style=\"margin: 15px;\">','<li class=\"layui-form-item\">','<label class=\"layui-form-label\">请选择语言</label>','<div class=\"layui-input-block\">','<select name=\"lang\">','<option value=\"JavaScript\">JavaScript</option>','<option value=\"HTML\">HTML</option>','<option value=\"CSS\">CSS</option>','<option value=\"Java\">Java</option>','<option value=\"PHP\">PHP</option>','<option value=\"C#\">C#</option>','<option value=\"Python\">Python</option>','<option value=\"Ruby\">Ruby</option>','<option value=\"Go\">Go</option>',\"</select>\",\"</div>\",\"</li>\",'<li class=\"layui-form-item layui-form-text\">','<label class=\"layui-form-label\">代码</label>','<div class=\"layui-input-block\">','<textarea name=\"code\" lay-verify=\"required\" autofocus=\"true\" class=\"layui-textarea\" style=\"height: 200px;\"></textarea>',\"</div>\",\"</li>\",'<li class=\"layui-form-item\" style=\"text-align: center;\">','<button type=\"button\" lay-submit lay-filter=\"layedit-code-yes\" class=\"layui-btn\"> 确定 </button>','<button style=\"margin-left: 20px;\" type=\"button\" class=\"layui-btn layui-btn-primary\"> 取消 </button>',\"</li>\",\"</ul>\"].join(\"\"),success:function(l,n){var o=\"submit(layedit-code-yes)\";a.render(\"select\"),l.find(\".layui-btn-primary\").on(\"click\",function(){i.close(n),e.focus()}),a.on(o,function(e){i.close(k.index),t&&t(e.field)})}});k.index=l},C={html:'<i class=\"layui-icon layedit-tool-html\" title=\"HTML源代码\" lay-command=\"html\" layedit-event=\"html\"\">&#xe64b;</i><span class=\"layedit-tool-mid\"></span>',strong:'<i class=\"layui-icon layedit-tool-b\" title=\"加粗\" lay-command=\"Bold\" layedit-event=\"b\"\">&#xe62b;</i>',italic:'<i class=\"layui-icon layedit-tool-i\" title=\"斜体\" lay-command=\"italic\" layedit-event=\"i\"\">&#xe644;</i>',underline:'<i class=\"layui-icon layedit-tool-u\" title=\"下划线\" lay-command=\"underline\" layedit-event=\"u\"\">&#xe646;</i>',del:'<i class=\"layui-icon layedit-tool-d\" title=\"删除线\" lay-command=\"strikeThrough\" layedit-event=\"d\"\">&#xe64f;</i>',\"|\":'<span class=\"layedit-tool-mid\"></span>',left:'<i class=\"layui-icon layedit-tool-left\" title=\"左对齐\" lay-command=\"justifyLeft\" layedit-event=\"left\"\">&#xe649;</i>',center:'<i class=\"layui-icon layedit-tool-center\" title=\"居中对齐\" lay-command=\"justifyCenter\" layedit-event=\"center\"\">&#xe647;</i>',right:'<i class=\"layui-icon layedit-tool-right\" title=\"右对齐\" lay-command=\"justifyRight\" layedit-event=\"right\"\">&#xe648;</i>',link:'<i class=\"layui-icon layedit-tool-link\" title=\"插入链接\" layedit-event=\"link\"\">&#xe64c;</i>',unlink:'<i class=\"layui-icon layedit-tool-unlink layui-disabled\" title=\"清除链接\" lay-command=\"unlink\" layedit-event=\"unlink\"\">&#xe64d;</i>',face:'<i class=\"layui-icon layedit-tool-face\" title=\"表情\" layedit-event=\"face\"\">&#xe650;</i>',image:'<i class=\"layui-icon layedit-tool-image\" title=\"图片\" layedit-event=\"image\">&#xe64a;<input type=\"file\" name=\"file\"></i>',code:'<i class=\"layui-icon layedit-tool-code\" title=\"插入代码\" layedit-event=\"code\">&#xe64e;</i>',help:'<i class=\"layui-icon layedit-tool-help\" title=\"帮助\" layedit-event=\"help\">&#xe607;</i>'},w=new c;t(n,w)});layui.define(\"jquery\",function(e){\"use strict\";var a=layui.$,l=\"http://www.layui.com/doc/modules/code.html\";e(\"code\",function(e){var t=[];e=e||{},e.elem=a(e.elem||\".layui-code\"),e.about=!(\"about\"in e)||e.about,e.elem.each(function(){t.push(this)}),layui.each(t.reverse(),function(t,i){var c=a(i),o=c.html();(c.attr(\"lay-encode\")||e.encode)&&(o=o.replace(/&(?!#?[a-zA-Z0-9]+;)/g,\"&amp;\").replace(/</g,\"&lt;\").replace(/>/g,\"&gt;\").replace(/'/g,\"&#39;\").replace(/\"/g,\"&quot;\")),c.html('<ol class=\"layui-code-ol\"><li>'+o.replace(/[\\r\\t\\n]+/g,\"</li><li>\")+\"</li></ol>\"),c.find(\">.layui-code-h3\")[0]||c.prepend('<h3 class=\"layui-code-h3\">'+(c.attr(\"lay-title\")||e.title||\"code\")+(e.about?'<a href=\"'+l+'\" target=\"_blank\">layui.code</a>':\"\")+\"</h3>\");var d=c.find(\">.layui-code-ol\");c.addClass(\"layui-box layui-code-view\"),(c.attr(\"lay-skin\")||e.skin)&&c.addClass(\"layui-code-\"+(c.attr(\"lay-skin\")||e.skin)),(d.find(\"li\").length/100|0)>0&&d.css(\"margin-left\",(d.find(\"li\").length/100|0)+\"px\"),(c.attr(\"lay-height\")||e.height)&&d.css(\"max-height\",c.attr(\"lay-height\")||e.height)})})}).addcss(\"modules/code.css\",\"skincodecss\");"
  },
  {
    "path": "open-layui-web/src/main/view/static/layui/layui.js",
    "content": "/** layui-v2.3.0-rc1 MIT License By https://www.layui.com */\n ;!function(e){\"use strict\";var t=document,n={modules:{},status:{},timeout:10,event:{}},o=function(){this.v=\"2.3.0-rc1\"},r=function(){var e=t.currentScript?t.currentScript.src:function(){for(var e,n=t.scripts,o=n.length-1,r=o;r>0;r--)if(\"interactive\"===n[r].readyState){e=n[r].src;break}return e||n[o].src}();return e.substring(0,e.lastIndexOf(\"/\")+1)}(),a=function(t){e.console&&console.error&&console.error(\"Layui hint: \"+t)},i=\"undefined\"!=typeof opera&&\"[object Opera]\"===opera.toString(),u={layer:\"modules/layer\",laydate:\"modules/laydate\",laypage:\"modules/laypage\",laytpl:\"modules/laytpl\",layim:\"modules/layim\",layedit:\"modules/layedit\",form:\"modules/form\",upload:\"modules/upload\",tree:\"modules/tree\",table:\"modules/table\",element:\"modules/element\",rate:\"modules/rate\",carousel:\"modules/carousel\",flow:\"modules/flow\",util:\"modules/util\",code:\"modules/code\",jquery:\"modules/jquery\",mobile:\"modules/mobile\",\"layui.all\":\"../layui.all\"};o.prototype.cache=n,o.prototype.define=function(e,t){var o=this,r=\"function\"==typeof e,a=function(){var e=function(e,t){layui[e]=t,n.status[e]=!0};return\"function\"==typeof t&&t(function(o,r){e(o,r),n.callback[o]=function(){t(e)}}),this};return r&&(t=e,e=[]),layui[\"layui.all\"]||!layui[\"layui.all\"]&&layui[\"layui.mobile\"]?a.call(o):(o.use(e,a),o)},o.prototype.use=function(e,o,l){function s(e,t){var o=\"PLaySTATION 3\"===navigator.platform?/^complete$/:/^(complete|loaded)$/;(\"load\"===e.type||o.test((e.currentTarget||e.srcElement).readyState))&&(n.modules[d]=t,f.removeChild(v),function r(){return++m>1e3*n.timeout/4?a(d+\" is not a valid module\"):void(n.status[d]?c():setTimeout(r,4))}())}function c(){l.push(layui[d]),e.length>1?y.use(e.slice(1),o,l):\"function\"==typeof o&&o.apply(layui,l)}var y=this,p=n.dir=n.dir?n.dir:r,f=t.getElementsByTagName(\"head\")[0];e=\"string\"==typeof e?[e]:e,window.jQuery&&jQuery.fn.on&&(y.each(e,function(t,n){\"jquery\"===n&&e.splice(t,1)}),layui.jquery=layui.$=jQuery);var d=e[0],m=0;if(l=l||[],n.host=n.host||(p.match(/\\/\\/([\\s\\S]+?)\\//)||[\"//\"+location.host+\"/\"])[0],0===e.length||layui[\"layui.all\"]&&u[d]||!layui[\"layui.all\"]&&layui[\"layui.mobile\"]&&u[d])return c(),y;if(n.modules[d])!function g(){return++m>1e3*n.timeout/4?a(d+\" is not a valid module\"):void(\"string\"==typeof n.modules[d]&&n.status[d]?c():setTimeout(g,4))}();else{var v=t.createElement(\"script\"),h=(u[d]?p+\"lay/\":/^\\{\\/\\}/.test(y.modules[d])?\"\":n.base||\"\")+(y.modules[d]||d)+\".js\";h=h.replace(/^\\{\\/\\}/,\"\"),v.async=!0,v.charset=\"utf-8\",v.src=h+function(){var e=n.version===!0?n.v||(new Date).getTime():n.version||\"\";return e?\"?v=\"+e:\"\"}(),f.appendChild(v),!v.attachEvent||v.attachEvent.toString&&v.attachEvent.toString().indexOf(\"[native code\")<0||i?v.addEventListener(\"load\",function(e){s(e,h)},!1):v.attachEvent(\"onreadystatechange\",function(e){s(e,h)}),n.modules[d]=h}return y},o.prototype.getStyle=function(t,n){var o=t.currentStyle?t.currentStyle:e.getComputedStyle(t,null);return o[o.getPropertyValue?\"getPropertyValue\":\"getAttribute\"](n)},o.prototype.link=function(e,o,r){var i=this,u=t.createElement(\"link\"),l=t.getElementsByTagName(\"head\")[0];\"string\"==typeof o&&(r=o);var s=(r||e).replace(/\\.|\\//g,\"\"),c=u.id=\"layuicss-\"+s,y=0;return u.rel=\"stylesheet\",u.href=e+(n.debug?\"?v=\"+(new Date).getTime():\"\"),u.media=\"all\",t.getElementById(c)||l.appendChild(u),\"function\"!=typeof o?i:(function p(){return++y>1e3*n.timeout/100?a(e+\" timeout\"):void(1989===parseInt(i.getStyle(t.getElementById(c),\"width\"))?function(){o()}():setTimeout(p,100))}(),i)},n.callback={},o.prototype.factory=function(e){if(layui[e])return\"function\"==typeof n.callback[e]?n.callback[e]:null},o.prototype.addcss=function(e,t,o){return layui.link(n.dir+\"css/\"+e,t,o)},o.prototype.img=function(e,t,n){var o=new Image;return o.src=e,o.complete?t(o):(o.onload=function(){o.onload=null,\"function\"==typeof t&&t(o)},void(o.onerror=function(e){o.onerror=null,\"function\"==typeof n&&n(e)}))},o.prototype.config=function(e){e=e||{};for(var t in e)n[t]=e[t];return this},o.prototype.modules=function(){var e={};for(var t in u)e[t]=u[t];return e}(),o.prototype.extend=function(e){var t=this;e=e||{};for(var n in e)t[n]||t.modules[n]?a(\"模块名 \"+n+\" 已被占用\"):t.modules[n]=e[n];return t},o.prototype.router=function(e){var t=this,e=e||location.hash,n={path:[],search:{},hash:(e.match(/[^#](#.*$)/)||[])[1]||\"\"};return/^#\\//.test(e)?(e=e.replace(/^#\\//,\"\"),n.href=\"/\"+e,e=e.replace(/([^#])(#.*$)/,\"$1\").split(\"/\")||[],t.each(e,function(e,t){/^\\w+=/.test(t)?function(){t=t.split(\"=\"),n.search[t[0]]=t[1]}():n.path.push(t)}),n):n},o.prototype.data=function(t,n,o){if(t=t||\"layui\",o=o||localStorage,e.JSON&&e.JSON.parse){if(null===n)return delete o[t];n=\"object\"==typeof n?n:{key:n};try{var r=JSON.parse(o[t])}catch(a){var r={}}return\"value\"in n&&(r[n.key]=n.value),n.remove&&delete r[n.key],o[t]=JSON.stringify(r),n.key?r[n.key]:r}},o.prototype.sessionData=function(e,t){return this.data(e,t,sessionStorage)},o.prototype.device=function(t){var n=navigator.userAgent.toLowerCase(),o=function(e){var t=new RegExp(e+\"/([^\\\\s\\\\_\\\\-]+)\");return e=(n.match(t)||[])[1],e||!1},r={os:function(){return/windows/.test(n)?\"windows\":/linux/.test(n)?\"linux\":/iphone|ipod|ipad|ios/.test(n)?\"ios\":/mac/.test(n)?\"mac\":void 0}(),ie:function(){return!!(e.ActiveXObject||\"ActiveXObject\"in e)&&((n.match(/msie\\s(\\d+)/)||[])[1]||\"11\")}(),weixin:o(\"micromessenger\")};return t&&!r[t]&&(r[t]=o(t)),r.android=/android/.test(n),r.ios=\"ios\"===r.os,r},o.prototype.hint=function(){return{error:a}},o.prototype.each=function(e,t){var n,o=this;if(\"function\"!=typeof t)return o;if(e=e||[],e.constructor===Object){for(n in e)if(t.call(e[n],n,e[n]))break}else for(n=0;n<e.length&&!t.call(e[n],n,e[n]);n++);return o},o.prototype.sort=function(e,t,n){var o=JSON.parse(JSON.stringify(e||[]));return t?(o.sort(function(e,n){var o=/^-?\\d+$/,r=e[t],a=n[t];return o.test(r)&&(r=parseFloat(r)),o.test(a)&&(a=parseFloat(a)),r&&!a?1:!r&&a?-1:r>a?1:r<a?-1:0}),n&&o.reverse(),o):o},o.prototype.stope=function(t){t=t||e.event;try{t.stopPropagation()}catch(n){t.cancelBubble=!0}},o.prototype.onevent=function(e,t,n){return\"string\"!=typeof e||\"function\"!=typeof n?this:o.event(e,t,null,n)},o.prototype.event=o.event=function(e,t,o,r){var a=this,i=null,u=t.match(/\\((.*)\\)$/)||[],l=(e+\".\"+t).replace(u[0],\"\"),s=u[1]||\"\",c=function(e,t){var n=t&&t.call(a,o);n===!1&&null===i&&(i=!1)};return r?(n.event[l]=n.event[l]||{},n.event[l][s]=[r],this):(layui.each(n.event[l],function(e,t){return\"{*}\"===s?void layui.each(t,c):(\"\"===e&&layui.each(t,c),void(e===s&&layui.each(t,c)))}),i)},e.layui=new o}(window);"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/bootstrap/css/bootstrap-grid.css",
    "content": "/*!\n * Bootstrap Grid v4.0.0-beta.2 (https://getbootstrap.com)\n * Copyright 2011-2017 The Bootstrap Authors\n * Copyright 2011-2017 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n@-ms-viewport {\n  width: device-width;\n}\n\nhtml {\n  box-sizing: border-box;\n  -ms-overflow-style: scrollbar;\n}\n\n*,\n*::before,\n*::after {\n  box-sizing: inherit;\n}\n\n.container {\n  width: 100%;\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n@media (min-width: 576px) {\n  .container {\n    max-width: 540px;\n  }\n}\n\n@media (min-width: 768px) {\n  .container {\n    max-width: 720px;\n  }\n}\n\n@media (min-width: 992px) {\n  .container {\n    max-width: 960px;\n  }\n}\n\n@media (min-width: 1200px) {\n  .container {\n    max-width: 1140px;\n  }\n}\n\n.container-fluid {\n  width: 100%;\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.row {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-wrap: wrap;\n      flex-wrap: wrap;\n  margin-right: -15px;\n  margin-left: -15px;\n}\n\n.no-gutters {\n  margin-right: 0;\n  margin-left: 0;\n}\n\n.no-gutters > .col,\n.no-gutters > [class*=\"col-\"] {\n  padding-right: 0;\n  padding-left: 0;\n}\n\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,\n.col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm,\n.col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md,\n.col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg,\n.col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl,\n.col-xl-auto {\n  position: relative;\n  width: 100%;\n  min-height: 1px;\n  padding-right: 15px;\n  padding-left: 15px;\n}\n\n.col {\n  -ms-flex-preferred-size: 0;\n      flex-basis: 0;\n  -ms-flex-positive: 1;\n      flex-grow: 1;\n  max-width: 100%;\n}\n\n.col-auto {\n  -ms-flex: 0 0 auto;\n      flex: 0 0 auto;\n  width: auto;\n  max-width: none;\n}\n\n.col-1 {\n  -ms-flex: 0 0 8.333333%;\n      flex: 0 0 8.333333%;\n  max-width: 8.333333%;\n}\n\n.col-2 {\n  -ms-flex: 0 0 16.666667%;\n      flex: 0 0 16.666667%;\n  max-width: 16.666667%;\n}\n\n.col-3 {\n  -ms-flex: 0 0 25%;\n      flex: 0 0 25%;\n  max-width: 25%;\n}\n\n.col-4 {\n  -ms-flex: 0 0 33.333333%;\n      flex: 0 0 33.333333%;\n  max-width: 33.333333%;\n}\n\n.col-5 {\n  -ms-flex: 0 0 41.666667%;\n      flex: 0 0 41.666667%;\n  max-width: 41.666667%;\n}\n\n.col-6 {\n  -ms-flex: 0 0 50%;\n      flex: 0 0 50%;\n  max-width: 50%;\n}\n\n.col-7 {\n  -ms-flex: 0 0 58.333333%;\n      flex: 0 0 58.333333%;\n  max-width: 58.333333%;\n}\n\n.col-8 {\n  -ms-flex: 0 0 66.666667%;\n      flex: 0 0 66.666667%;\n  max-width: 66.666667%;\n}\n\n.col-9 {\n  -ms-flex: 0 0 75%;\n      flex: 0 0 75%;\n  max-width: 75%;\n}\n\n.col-10 {\n  -ms-flex: 0 0 83.333333%;\n      flex: 0 0 83.333333%;\n  max-width: 83.333333%;\n}\n\n.col-11 {\n  -ms-flex: 0 0 91.666667%;\n      flex: 0 0 91.666667%;\n  max-width: 91.666667%;\n}\n\n.col-12 {\n  -ms-flex: 0 0 100%;\n      flex: 0 0 100%;\n  max-width: 100%;\n}\n\n.order-first {\n  -ms-flex-order: -1;\n      order: -1;\n}\n\n.order-1 {\n  -ms-flex-order: 1;\n      order: 1;\n}\n\n.order-2 {\n  -ms-flex-order: 2;\n      order: 2;\n}\n\n.order-3 {\n  -ms-flex-order: 3;\n      order: 3;\n}\n\n.order-4 {\n  -ms-flex-order: 4;\n      order: 4;\n}\n\n.order-5 {\n  -ms-flex-order: 5;\n      order: 5;\n}\n\n.order-6 {\n  -ms-flex-order: 6;\n      order: 6;\n}\n\n.order-7 {\n  -ms-flex-order: 7;\n      order: 7;\n}\n\n.order-8 {\n  -ms-flex-order: 8;\n      order: 8;\n}\n\n.order-9 {\n  -ms-flex-order: 9;\n      order: 9;\n}\n\n.order-10 {\n  -ms-flex-order: 10;\n      order: 10;\n}\n\n.order-11 {\n  -ms-flex-order: 11;\n      order: 11;\n}\n\n.order-12 {\n  -ms-flex-order: 12;\n      order: 12;\n}\n\n.offset-1 {\n  margin-left: 8.333333%;\n}\n\n.offset-2 {\n  margin-left: 16.666667%;\n}\n\n.offset-3 {\n  margin-left: 25%;\n}\n\n.offset-4 {\n  margin-left: 33.333333%;\n}\n\n.offset-5 {\n  margin-left: 41.666667%;\n}\n\n.offset-6 {\n  margin-left: 50%;\n}\n\n.offset-7 {\n  margin-left: 58.333333%;\n}\n\n.offset-8 {\n  margin-left: 66.666667%;\n}\n\n.offset-9 {\n  margin-left: 75%;\n}\n\n.offset-10 {\n  margin-left: 83.333333%;\n}\n\n.offset-11 {\n  margin-left: 91.666667%;\n}\n\n@media (min-width: 576px) {\n  .col-sm {\n    -ms-flex-preferred-size: 0;\n        flex-basis: 0;\n    -ms-flex-positive: 1;\n        flex-grow: 1;\n    max-width: 100%;\n  }\n  .col-sm-auto {\n    -ms-flex: 0 0 auto;\n        flex: 0 0 auto;\n    width: auto;\n    max-width: none;\n  }\n  .col-sm-1 {\n    -ms-flex: 0 0 8.333333%;\n        flex: 0 0 8.333333%;\n    max-width: 8.333333%;\n  }\n  .col-sm-2 {\n    -ms-flex: 0 0 16.666667%;\n        flex: 0 0 16.666667%;\n    max-width: 16.666667%;\n  }\n  .col-sm-3 {\n    -ms-flex: 0 0 25%;\n        flex: 0 0 25%;\n    max-width: 25%;\n  }\n  .col-sm-4 {\n    -ms-flex: 0 0 33.333333%;\n        flex: 0 0 33.333333%;\n    max-width: 33.333333%;\n  }\n  .col-sm-5 {\n    -ms-flex: 0 0 41.666667%;\n        flex: 0 0 41.666667%;\n    max-width: 41.666667%;\n  }\n  .col-sm-6 {\n    -ms-flex: 0 0 50%;\n        flex: 0 0 50%;\n    max-width: 50%;\n  }\n  .col-sm-7 {\n    -ms-flex: 0 0 58.333333%;\n        flex: 0 0 58.333333%;\n    max-width: 58.333333%;\n  }\n  .col-sm-8 {\n    -ms-flex: 0 0 66.666667%;\n        flex: 0 0 66.666667%;\n    max-width: 66.666667%;\n  }\n  .col-sm-9 {\n    -ms-flex: 0 0 75%;\n        flex: 0 0 75%;\n    max-width: 75%;\n  }\n  .col-sm-10 {\n    -ms-flex: 0 0 83.333333%;\n        flex: 0 0 83.333333%;\n    max-width: 83.333333%;\n  }\n  .col-sm-11 {\n    -ms-flex: 0 0 91.666667%;\n        flex: 0 0 91.666667%;\n    max-width: 91.666667%;\n  }\n  .col-sm-12 {\n    -ms-flex: 0 0 100%;\n        flex: 0 0 100%;\n    max-width: 100%;\n  }\n  .order-sm-first {\n    -ms-flex-order: -1;\n        order: -1;\n  }\n  .order-sm-1 {\n    -ms-flex-order: 1;\n        order: 1;\n  }\n  .order-sm-2 {\n    -ms-flex-order: 2;\n        order: 2;\n  }\n  .order-sm-3 {\n    -ms-flex-order: 3;\n        order: 3;\n  }\n  .order-sm-4 {\n    -ms-flex-order: 4;\n        order: 4;\n  }\n  .order-sm-5 {\n    -ms-flex-order: 5;\n        order: 5;\n  }\n  .order-sm-6 {\n    -ms-flex-order: 6;\n        order: 6;\n  }\n  .order-sm-7 {\n    -ms-flex-order: 7;\n        order: 7;\n  }\n  .order-sm-8 {\n    -ms-flex-order: 8;\n        order: 8;\n  }\n  .order-sm-9 {\n    -ms-flex-order: 9;\n        order: 9;\n  }\n  .order-sm-10 {\n    -ms-flex-order: 10;\n        order: 10;\n  }\n  .order-sm-11 {\n    -ms-flex-order: 11;\n        order: 11;\n  }\n  .order-sm-12 {\n    -ms-flex-order: 12;\n        order: 12;\n  }\n  .offset-sm-0 {\n    margin-left: 0;\n  }\n  .offset-sm-1 {\n    margin-left: 8.333333%;\n  }\n  .offset-sm-2 {\n    margin-left: 16.666667%;\n  }\n  .offset-sm-3 {\n    margin-left: 25%;\n  }\n  .offset-sm-4 {\n    margin-left: 33.333333%;\n  }\n  .offset-sm-5 {\n    margin-left: 41.666667%;\n  }\n  .offset-sm-6 {\n    margin-left: 50%;\n  }\n  .offset-sm-7 {\n    margin-left: 58.333333%;\n  }\n  .offset-sm-8 {\n    margin-left: 66.666667%;\n  }\n  .offset-sm-9 {\n    margin-left: 75%;\n  }\n  .offset-sm-10 {\n    margin-left: 83.333333%;\n  }\n  .offset-sm-11 {\n    margin-left: 91.666667%;\n  }\n}\n\n@media (min-width: 768px) {\n  .col-md {\n    -ms-flex-preferred-size: 0;\n        flex-basis: 0;\n    -ms-flex-positive: 1;\n        flex-grow: 1;\n    max-width: 100%;\n  }\n  .col-md-auto {\n    -ms-flex: 0 0 auto;\n        flex: 0 0 auto;\n    width: auto;\n    max-width: none;\n  }\n  .col-md-1 {\n    -ms-flex: 0 0 8.333333%;\n        flex: 0 0 8.333333%;\n    max-width: 8.333333%;\n  }\n  .col-md-2 {\n    -ms-flex: 0 0 16.666667%;\n        flex: 0 0 16.666667%;\n    max-width: 16.666667%;\n  }\n  .col-md-3 {\n    -ms-flex: 0 0 25%;\n        flex: 0 0 25%;\n    max-width: 25%;\n  }\n  .col-md-4 {\n    -ms-flex: 0 0 33.333333%;\n        flex: 0 0 33.333333%;\n    max-width: 33.333333%;\n  }\n  .col-md-5 {\n    -ms-flex: 0 0 41.666667%;\n        flex: 0 0 41.666667%;\n    max-width: 41.666667%;\n  }\n  .col-md-6 {\n    -ms-flex: 0 0 50%;\n        flex: 0 0 50%;\n    max-width: 50%;\n  }\n  .col-md-7 {\n    -ms-flex: 0 0 58.333333%;\n        flex: 0 0 58.333333%;\n    max-width: 58.333333%;\n  }\n  .col-md-8 {\n    -ms-flex: 0 0 66.666667%;\n        flex: 0 0 66.666667%;\n    max-width: 66.666667%;\n  }\n  .col-md-9 {\n    -ms-flex: 0 0 75%;\n        flex: 0 0 75%;\n    max-width: 75%;\n  }\n  .col-md-10 {\n    -ms-flex: 0 0 83.333333%;\n        flex: 0 0 83.333333%;\n    max-width: 83.333333%;\n  }\n  .col-md-11 {\n    -ms-flex: 0 0 91.666667%;\n        flex: 0 0 91.666667%;\n    max-width: 91.666667%;\n  }\n  .col-md-12 {\n    -ms-flex: 0 0 100%;\n        flex: 0 0 100%;\n    max-width: 100%;\n  }\n  .order-md-first {\n    -ms-flex-order: -1;\n        order: -1;\n  }\n  .order-md-1 {\n    -ms-flex-order: 1;\n        order: 1;\n  }\n  .order-md-2 {\n    -ms-flex-order: 2;\n        order: 2;\n  }\n  .order-md-3 {\n    -ms-flex-order: 3;\n        order: 3;\n  }\n  .order-md-4 {\n    -ms-flex-order: 4;\n        order: 4;\n  }\n  .order-md-5 {\n    -ms-flex-order: 5;\n        order: 5;\n  }\n  .order-md-6 {\n    -ms-flex-order: 6;\n        order: 6;\n  }\n  .order-md-7 {\n    -ms-flex-order: 7;\n        order: 7;\n  }\n  .order-md-8 {\n    -ms-flex-order: 8;\n        order: 8;\n  }\n  .order-md-9 {\n    -ms-flex-order: 9;\n        order: 9;\n  }\n  .order-md-10 {\n    -ms-flex-order: 10;\n        order: 10;\n  }\n  .order-md-11 {\n    -ms-flex-order: 11;\n        order: 11;\n  }\n  .order-md-12 {\n    -ms-flex-order: 12;\n        order: 12;\n  }\n  .offset-md-0 {\n    margin-left: 0;\n  }\n  .offset-md-1 {\n    margin-left: 8.333333%;\n  }\n  .offset-md-2 {\n    margin-left: 16.666667%;\n  }\n  .offset-md-3 {\n    margin-left: 25%;\n  }\n  .offset-md-4 {\n    margin-left: 33.333333%;\n  }\n  .offset-md-5 {\n    margin-left: 41.666667%;\n  }\n  .offset-md-6 {\n    margin-left: 50%;\n  }\n  .offset-md-7 {\n    margin-left: 58.333333%;\n  }\n  .offset-md-8 {\n    margin-left: 66.666667%;\n  }\n  .offset-md-9 {\n    margin-left: 75%;\n  }\n  .offset-md-10 {\n    margin-left: 83.333333%;\n  }\n  .offset-md-11 {\n    margin-left: 91.666667%;\n  }\n}\n\n@media (min-width: 992px) {\n  .col-lg {\n    -ms-flex-preferred-size: 0;\n        flex-basis: 0;\n    -ms-flex-positive: 1;\n        flex-grow: 1;\n    max-width: 100%;\n  }\n  .col-lg-auto {\n    -ms-flex: 0 0 auto;\n        flex: 0 0 auto;\n    width: auto;\n    max-width: none;\n  }\n  .col-lg-1 {\n    -ms-flex: 0 0 8.333333%;\n        flex: 0 0 8.333333%;\n    max-width: 8.333333%;\n  }\n  .col-lg-2 {\n    -ms-flex: 0 0 16.666667%;\n        flex: 0 0 16.666667%;\n    max-width: 16.666667%;\n  }\n  .col-lg-3 {\n    -ms-flex: 0 0 25%;\n        flex: 0 0 25%;\n    max-width: 25%;\n  }\n  .col-lg-4 {\n    -ms-flex: 0 0 33.333333%;\n        flex: 0 0 33.333333%;\n    max-width: 33.333333%;\n  }\n  .col-lg-5 {\n    -ms-flex: 0 0 41.666667%;\n        flex: 0 0 41.666667%;\n    max-width: 41.666667%;\n  }\n  .col-lg-6 {\n    -ms-flex: 0 0 50%;\n        flex: 0 0 50%;\n    max-width: 50%;\n  }\n  .col-lg-7 {\n    -ms-flex: 0 0 58.333333%;\n        flex: 0 0 58.333333%;\n    max-width: 58.333333%;\n  }\n  .col-lg-8 {\n    -ms-flex: 0 0 66.666667%;\n        flex: 0 0 66.666667%;\n    max-width: 66.666667%;\n  }\n  .col-lg-9 {\n    -ms-flex: 0 0 75%;\n        flex: 0 0 75%;\n    max-width: 75%;\n  }\n  .col-lg-10 {\n    -ms-flex: 0 0 83.333333%;\n        flex: 0 0 83.333333%;\n    max-width: 83.333333%;\n  }\n  .col-lg-11 {\n    -ms-flex: 0 0 91.666667%;\n        flex: 0 0 91.666667%;\n    max-width: 91.666667%;\n  }\n  .col-lg-12 {\n    -ms-flex: 0 0 100%;\n        flex: 0 0 100%;\n    max-width: 100%;\n  }\n  .order-lg-first {\n    -ms-flex-order: -1;\n        order: -1;\n  }\n  .order-lg-1 {\n    -ms-flex-order: 1;\n        order: 1;\n  }\n  .order-lg-2 {\n    -ms-flex-order: 2;\n        order: 2;\n  }\n  .order-lg-3 {\n    -ms-flex-order: 3;\n        order: 3;\n  }\n  .order-lg-4 {\n    -ms-flex-order: 4;\n        order: 4;\n  }\n  .order-lg-5 {\n    -ms-flex-order: 5;\n        order: 5;\n  }\n  .order-lg-6 {\n    -ms-flex-order: 6;\n        order: 6;\n  }\n  .order-lg-7 {\n    -ms-flex-order: 7;\n        order: 7;\n  }\n  .order-lg-8 {\n    -ms-flex-order: 8;\n        order: 8;\n  }\n  .order-lg-9 {\n    -ms-flex-order: 9;\n        order: 9;\n  }\n  .order-lg-10 {\n    -ms-flex-order: 10;\n        order: 10;\n  }\n  .order-lg-11 {\n    -ms-flex-order: 11;\n        order: 11;\n  }\n  .order-lg-12 {\n    -ms-flex-order: 12;\n        order: 12;\n  }\n  .offset-lg-0 {\n    margin-left: 0;\n  }\n  .offset-lg-1 {\n    margin-left: 8.333333%;\n  }\n  .offset-lg-2 {\n    margin-left: 16.666667%;\n  }\n  .offset-lg-3 {\n    margin-left: 25%;\n  }\n  .offset-lg-4 {\n    margin-left: 33.333333%;\n  }\n  .offset-lg-5 {\n    margin-left: 41.666667%;\n  }\n  .offset-lg-6 {\n    margin-left: 50%;\n  }\n  .offset-lg-7 {\n    margin-left: 58.333333%;\n  }\n  .offset-lg-8 {\n    margin-left: 66.666667%;\n  }\n  .offset-lg-9 {\n    margin-left: 75%;\n  }\n  .offset-lg-10 {\n    margin-left: 83.333333%;\n  }\n  .offset-lg-11 {\n    margin-left: 91.666667%;\n  }\n}\n\n@media (min-width: 1200px) {\n  .col-xl {\n    -ms-flex-preferred-size: 0;\n        flex-basis: 0;\n    -ms-flex-positive: 1;\n        flex-grow: 1;\n    max-width: 100%;\n  }\n  .col-xl-auto {\n    -ms-flex: 0 0 auto;\n        flex: 0 0 auto;\n    width: auto;\n    max-width: none;\n  }\n  .col-xl-1 {\n    -ms-flex: 0 0 8.333333%;\n        flex: 0 0 8.333333%;\n    max-width: 8.333333%;\n  }\n  .col-xl-2 {\n    -ms-flex: 0 0 16.666667%;\n        flex: 0 0 16.666667%;\n    max-width: 16.666667%;\n  }\n  .col-xl-3 {\n    -ms-flex: 0 0 25%;\n        flex: 0 0 25%;\n    max-width: 25%;\n  }\n  .col-xl-4 {\n    -ms-flex: 0 0 33.333333%;\n        flex: 0 0 33.333333%;\n    max-width: 33.333333%;\n  }\n  .col-xl-5 {\n    -ms-flex: 0 0 41.666667%;\n        flex: 0 0 41.666667%;\n    max-width: 41.666667%;\n  }\n  .col-xl-6 {\n    -ms-flex: 0 0 50%;\n        flex: 0 0 50%;\n    max-width: 50%;\n  }\n  .col-xl-7 {\n    -ms-flex: 0 0 58.333333%;\n        flex: 0 0 58.333333%;\n    max-width: 58.333333%;\n  }\n  .col-xl-8 {\n    -ms-flex: 0 0 66.666667%;\n        flex: 0 0 66.666667%;\n    max-width: 66.666667%;\n  }\n  .col-xl-9 {\n    -ms-flex: 0 0 75%;\n        flex: 0 0 75%;\n    max-width: 75%;\n  }\n  .col-xl-10 {\n    -ms-flex: 0 0 83.333333%;\n        flex: 0 0 83.333333%;\n    max-width: 83.333333%;\n  }\n  .col-xl-11 {\n    -ms-flex: 0 0 91.666667%;\n        flex: 0 0 91.666667%;\n    max-width: 91.666667%;\n  }\n  .col-xl-12 {\n    -ms-flex: 0 0 100%;\n        flex: 0 0 100%;\n    max-width: 100%;\n  }\n  .order-xl-first {\n    -ms-flex-order: -1;\n        order: -1;\n  }\n  .order-xl-1 {\n    -ms-flex-order: 1;\n        order: 1;\n  }\n  .order-xl-2 {\n    -ms-flex-order: 2;\n        order: 2;\n  }\n  .order-xl-3 {\n    -ms-flex-order: 3;\n        order: 3;\n  }\n  .order-xl-4 {\n    -ms-flex-order: 4;\n        order: 4;\n  }\n  .order-xl-5 {\n    -ms-flex-order: 5;\n        order: 5;\n  }\n  .order-xl-6 {\n    -ms-flex-order: 6;\n        order: 6;\n  }\n  .order-xl-7 {\n    -ms-flex-order: 7;\n        order: 7;\n  }\n  .order-xl-8 {\n    -ms-flex-order: 8;\n        order: 8;\n  }\n  .order-xl-9 {\n    -ms-flex-order: 9;\n        order: 9;\n  }\n  .order-xl-10 {\n    -ms-flex-order: 10;\n        order: 10;\n  }\n  .order-xl-11 {\n    -ms-flex-order: 11;\n        order: 11;\n  }\n  .order-xl-12 {\n    -ms-flex-order: 12;\n        order: 12;\n  }\n  .offset-xl-0 {\n    margin-left: 0;\n  }\n  .offset-xl-1 {\n    margin-left: 8.333333%;\n  }\n  .offset-xl-2 {\n    margin-left: 16.666667%;\n  }\n  .offset-xl-3 {\n    margin-left: 25%;\n  }\n  .offset-xl-4 {\n    margin-left: 33.333333%;\n  }\n  .offset-xl-5 {\n    margin-left: 41.666667%;\n  }\n  .offset-xl-6 {\n    margin-left: 50%;\n  }\n  .offset-xl-7 {\n    margin-left: 58.333333%;\n  }\n  .offset-xl-8 {\n    margin-left: 66.666667%;\n  }\n  .offset-xl-9 {\n    margin-left: 75%;\n  }\n  .offset-xl-10 {\n    margin-left: 83.333333%;\n  }\n  .offset-xl-11 {\n    margin-left: 91.666667%;\n  }\n}\n\n.flex-row {\n  -ms-flex-direction: row !important;\n      flex-direction: row !important;\n}\n\n.flex-column {\n  -ms-flex-direction: column !important;\n      flex-direction: column !important;\n}\n\n.flex-row-reverse {\n  -ms-flex-direction: row-reverse !important;\n      flex-direction: row-reverse !important;\n}\n\n.flex-column-reverse {\n  -ms-flex-direction: column-reverse !important;\n      flex-direction: column-reverse !important;\n}\n\n.flex-wrap {\n  -ms-flex-wrap: wrap !important;\n      flex-wrap: wrap !important;\n}\n\n.flex-nowrap {\n  -ms-flex-wrap: nowrap !important;\n      flex-wrap: nowrap !important;\n}\n\n.flex-wrap-reverse {\n  -ms-flex-wrap: wrap-reverse !important;\n      flex-wrap: wrap-reverse !important;\n}\n\n.justify-content-start {\n  -ms-flex-pack: start !important;\n      justify-content: flex-start !important;\n}\n\n.justify-content-end {\n  -ms-flex-pack: end !important;\n      justify-content: flex-end !important;\n}\n\n.justify-content-center {\n  -ms-flex-pack: center !important;\n      justify-content: center !important;\n}\n\n.justify-content-between {\n  -ms-flex-pack: justify !important;\n      justify-content: space-between !important;\n}\n\n.justify-content-around {\n  -ms-flex-pack: distribute !important;\n      justify-content: space-around !important;\n}\n\n.align-items-start {\n  -ms-flex-align: start !important;\n      align-items: flex-start !important;\n}\n\n.align-items-end {\n  -ms-flex-align: end !important;\n      align-items: flex-end !important;\n}\n\n.align-items-center {\n  -ms-flex-align: center !important;\n      align-items: center !important;\n}\n\n.align-items-baseline {\n  -ms-flex-align: baseline !important;\n      align-items: baseline !important;\n}\n\n.align-items-stretch {\n  -ms-flex-align: stretch !important;\n      align-items: stretch !important;\n}\n\n.align-content-start {\n  -ms-flex-line-pack: start !important;\n      align-content: flex-start !important;\n}\n\n.align-content-end {\n  -ms-flex-line-pack: end !important;\n      align-content: flex-end !important;\n}\n\n.align-content-center {\n  -ms-flex-line-pack: center !important;\n      align-content: center !important;\n}\n\n.align-content-between {\n  -ms-flex-line-pack: justify !important;\n      align-content: space-between !important;\n}\n\n.align-content-around {\n  -ms-flex-line-pack: distribute !important;\n      align-content: space-around !important;\n}\n\n.align-content-stretch {\n  -ms-flex-line-pack: stretch !important;\n      align-content: stretch !important;\n}\n\n.align-self-auto {\n  -ms-flex-item-align: auto !important;\n      align-self: auto !important;\n}\n\n.align-self-start {\n  -ms-flex-item-align: start !important;\n      align-self: flex-start !important;\n}\n\n.align-self-end {\n  -ms-flex-item-align: end !important;\n      align-self: flex-end !important;\n}\n\n.align-self-center {\n  -ms-flex-item-align: center !important;\n      align-self: center !important;\n}\n\n.align-self-baseline {\n  -ms-flex-item-align: baseline !important;\n      align-self: baseline !important;\n}\n\n.align-self-stretch {\n  -ms-flex-item-align: stretch !important;\n      align-self: stretch !important;\n}\n\n@media (min-width: 576px) {\n  .flex-sm-row {\n    -ms-flex-direction: row !important;\n        flex-direction: row !important;\n  }\n  .flex-sm-column {\n    -ms-flex-direction: column !important;\n        flex-direction: column !important;\n  }\n  .flex-sm-row-reverse {\n    -ms-flex-direction: row-reverse !important;\n        flex-direction: row-reverse !important;\n  }\n  .flex-sm-column-reverse {\n    -ms-flex-direction: column-reverse !important;\n        flex-direction: column-reverse !important;\n  }\n  .flex-sm-wrap {\n    -ms-flex-wrap: wrap !important;\n        flex-wrap: wrap !important;\n  }\n  .flex-sm-nowrap {\n    -ms-flex-wrap: nowrap !important;\n        flex-wrap: nowrap !important;\n  }\n  .flex-sm-wrap-reverse {\n    -ms-flex-wrap: wrap-reverse !important;\n        flex-wrap: wrap-reverse !important;\n  }\n  .justify-content-sm-start {\n    -ms-flex-pack: start !important;\n        justify-content: flex-start !important;\n  }\n  .justify-content-sm-end {\n    -ms-flex-pack: end !important;\n        justify-content: flex-end !important;\n  }\n  .justify-content-sm-center {\n    -ms-flex-pack: center !important;\n        justify-content: center !important;\n  }\n  .justify-content-sm-between {\n    -ms-flex-pack: justify !important;\n        justify-content: space-between !important;\n  }\n  .justify-content-sm-around {\n    -ms-flex-pack: distribute !important;\n        justify-content: space-around !important;\n  }\n  .align-items-sm-start {\n    -ms-flex-align: start !important;\n        align-items: flex-start !important;\n  }\n  .align-items-sm-end {\n    -ms-flex-align: end !important;\n        align-items: flex-end !important;\n  }\n  .align-items-sm-center {\n    -ms-flex-align: center !important;\n        align-items: center !important;\n  }\n  .align-items-sm-baseline {\n    -ms-flex-align: baseline !important;\n        align-items: baseline !important;\n  }\n  .align-items-sm-stretch {\n    -ms-flex-align: stretch !important;\n        align-items: stretch !important;\n  }\n  .align-content-sm-start {\n    -ms-flex-line-pack: start !important;\n        align-content: flex-start !important;\n  }\n  .align-content-sm-end {\n    -ms-flex-line-pack: end !important;\n        align-content: flex-end !important;\n  }\n  .align-content-sm-center {\n    -ms-flex-line-pack: center !important;\n        align-content: center !important;\n  }\n  .align-content-sm-between {\n    -ms-flex-line-pack: justify !important;\n        align-content: space-between !important;\n  }\n  .align-content-sm-around {\n    -ms-flex-line-pack: distribute !important;\n        align-content: space-around !important;\n  }\n  .align-content-sm-stretch {\n    -ms-flex-line-pack: stretch !important;\n        align-content: stretch !important;\n  }\n  .align-self-sm-auto {\n    -ms-flex-item-align: auto !important;\n        align-self: auto !important;\n  }\n  .align-self-sm-start {\n    -ms-flex-item-align: start !important;\n        align-self: flex-start !important;\n  }\n  .align-self-sm-end {\n    -ms-flex-item-align: end !important;\n        align-self: flex-end !important;\n  }\n  .align-self-sm-center {\n    -ms-flex-item-align: center !important;\n        align-self: center !important;\n  }\n  .align-self-sm-baseline {\n    -ms-flex-item-align: baseline !important;\n        align-self: baseline !important;\n  }\n  .align-self-sm-stretch {\n    -ms-flex-item-align: stretch !important;\n        align-self: stretch !important;\n  }\n}\n\n@media (min-width: 768px) {\n  .flex-md-row {\n    -ms-flex-direction: row !important;\n        flex-direction: row !important;\n  }\n  .flex-md-column {\n    -ms-flex-direction: column !important;\n        flex-direction: column !important;\n  }\n  .flex-md-row-reverse {\n    -ms-flex-direction: row-reverse !important;\n        flex-direction: row-reverse !important;\n  }\n  .flex-md-column-reverse {\n    -ms-flex-direction: column-reverse !important;\n        flex-direction: column-reverse !important;\n  }\n  .flex-md-wrap {\n    -ms-flex-wrap: wrap !important;\n        flex-wrap: wrap !important;\n  }\n  .flex-md-nowrap {\n    -ms-flex-wrap: nowrap !important;\n        flex-wrap: nowrap !important;\n  }\n  .flex-md-wrap-reverse {\n    -ms-flex-wrap: wrap-reverse !important;\n        flex-wrap: wrap-reverse !important;\n  }\n  .justify-content-md-start {\n    -ms-flex-pack: start !important;\n        justify-content: flex-start !important;\n  }\n  .justify-content-md-end {\n    -ms-flex-pack: end !important;\n        justify-content: flex-end !important;\n  }\n  .justify-content-md-center {\n    -ms-flex-pack: center !important;\n        justify-content: center !important;\n  }\n  .justify-content-md-between {\n    -ms-flex-pack: justify !important;\n        justify-content: space-between !important;\n  }\n  .justify-content-md-around {\n    -ms-flex-pack: distribute !important;\n        justify-content: space-around !important;\n  }\n  .align-items-md-start {\n    -ms-flex-align: start !important;\n        align-items: flex-start !important;\n  }\n  .align-items-md-end {\n    -ms-flex-align: end !important;\n        align-items: flex-end !important;\n  }\n  .align-items-md-center {\n    -ms-flex-align: center !important;\n        align-items: center !important;\n  }\n  .align-items-md-baseline {\n    -ms-flex-align: baseline !important;\n        align-items: baseline !important;\n  }\n  .align-items-md-stretch {\n    -ms-flex-align: stretch !important;\n        align-items: stretch !important;\n  }\n  .align-content-md-start {\n    -ms-flex-line-pack: start !important;\n        align-content: flex-start !important;\n  }\n  .align-content-md-end {\n    -ms-flex-line-pack: end !important;\n        align-content: flex-end !important;\n  }\n  .align-content-md-center {\n    -ms-flex-line-pack: center !important;\n        align-content: center !important;\n  }\n  .align-content-md-between {\n    -ms-flex-line-pack: justify !important;\n        align-content: space-between !important;\n  }\n  .align-content-md-around {\n    -ms-flex-line-pack: distribute !important;\n        align-content: space-around !important;\n  }\n  .align-content-md-stretch {\n    -ms-flex-line-pack: stretch !important;\n        align-content: stretch !important;\n  }\n  .align-self-md-auto {\n    -ms-flex-item-align: auto !important;\n        align-self: auto !important;\n  }\n  .align-self-md-start {\n    -ms-flex-item-align: start !important;\n        align-self: flex-start !important;\n  }\n  .align-self-md-end {\n    -ms-flex-item-align: end !important;\n        align-self: flex-end !important;\n  }\n  .align-self-md-center {\n    -ms-flex-item-align: center !important;\n        align-self: center !important;\n  }\n  .align-self-md-baseline {\n    -ms-flex-item-align: baseline !important;\n        align-self: baseline !important;\n  }\n  .align-self-md-stretch {\n    -ms-flex-item-align: stretch !important;\n        align-self: stretch !important;\n  }\n}\n\n@media (min-width: 992px) {\n  .flex-lg-row {\n    -ms-flex-direction: row !important;\n        flex-direction: row !important;\n  }\n  .flex-lg-column {\n    -ms-flex-direction: column !important;\n        flex-direction: column !important;\n  }\n  .flex-lg-row-reverse {\n    -ms-flex-direction: row-reverse !important;\n        flex-direction: row-reverse !important;\n  }\n  .flex-lg-column-reverse {\n    -ms-flex-direction: column-reverse !important;\n        flex-direction: column-reverse !important;\n  }\n  .flex-lg-wrap {\n    -ms-flex-wrap: wrap !important;\n        flex-wrap: wrap !important;\n  }\n  .flex-lg-nowrap {\n    -ms-flex-wrap: nowrap !important;\n        flex-wrap: nowrap !important;\n  }\n  .flex-lg-wrap-reverse {\n    -ms-flex-wrap: wrap-reverse !important;\n        flex-wrap: wrap-reverse !important;\n  }\n  .justify-content-lg-start {\n    -ms-flex-pack: start !important;\n        justify-content: flex-start !important;\n  }\n  .justify-content-lg-end {\n    -ms-flex-pack: end !important;\n        justify-content: flex-end !important;\n  }\n  .justify-content-lg-center {\n    -ms-flex-pack: center !important;\n        justify-content: center !important;\n  }\n  .justify-content-lg-between {\n    -ms-flex-pack: justify !important;\n        justify-content: space-between !important;\n  }\n  .justify-content-lg-around {\n    -ms-flex-pack: distribute !important;\n        justify-content: space-around !important;\n  }\n  .align-items-lg-start {\n    -ms-flex-align: start !important;\n        align-items: flex-start !important;\n  }\n  .align-items-lg-end {\n    -ms-flex-align: end !important;\n        align-items: flex-end !important;\n  }\n  .align-items-lg-center {\n    -ms-flex-align: center !important;\n        align-items: center !important;\n  }\n  .align-items-lg-baseline {\n    -ms-flex-align: baseline !important;\n        align-items: baseline !important;\n  }\n  .align-items-lg-stretch {\n    -ms-flex-align: stretch !important;\n        align-items: stretch !important;\n  }\n  .align-content-lg-start {\n    -ms-flex-line-pack: start !important;\n        align-content: flex-start !important;\n  }\n  .align-content-lg-end {\n    -ms-flex-line-pack: end !important;\n        align-content: flex-end !important;\n  }\n  .align-content-lg-center {\n    -ms-flex-line-pack: center !important;\n        align-content: center !important;\n  }\n  .align-content-lg-between {\n    -ms-flex-line-pack: justify !important;\n        align-content: space-between !important;\n  }\n  .align-content-lg-around {\n    -ms-flex-line-pack: distribute !important;\n        align-content: space-around !important;\n  }\n  .align-content-lg-stretch {\n    -ms-flex-line-pack: stretch !important;\n        align-content: stretch !important;\n  }\n  .align-self-lg-auto {\n    -ms-flex-item-align: auto !important;\n        align-self: auto !important;\n  }\n  .align-self-lg-start {\n    -ms-flex-item-align: start !important;\n        align-self: flex-start !important;\n  }\n  .align-self-lg-end {\n    -ms-flex-item-align: end !important;\n        align-self: flex-end !important;\n  }\n  .align-self-lg-center {\n    -ms-flex-item-align: center !important;\n        align-self: center !important;\n  }\n  .align-self-lg-baseline {\n    -ms-flex-item-align: baseline !important;\n        align-self: baseline !important;\n  }\n  .align-self-lg-stretch {\n    -ms-flex-item-align: stretch !important;\n        align-self: stretch !important;\n  }\n}\n\n@media (min-width: 1200px) {\n  .flex-xl-row {\n    -ms-flex-direction: row !important;\n        flex-direction: row !important;\n  }\n  .flex-xl-column {\n    -ms-flex-direction: column !important;\n        flex-direction: column !important;\n  }\n  .flex-xl-row-reverse {\n    -ms-flex-direction: row-reverse !important;\n        flex-direction: row-reverse !important;\n  }\n  .flex-xl-column-reverse {\n    -ms-flex-direction: column-reverse !important;\n        flex-direction: column-reverse !important;\n  }\n  .flex-xl-wrap {\n    -ms-flex-wrap: wrap !important;\n        flex-wrap: wrap !important;\n  }\n  .flex-xl-nowrap {\n    -ms-flex-wrap: nowrap !important;\n        flex-wrap: nowrap !important;\n  }\n  .flex-xl-wrap-reverse {\n    -ms-flex-wrap: wrap-reverse !important;\n        flex-wrap: wrap-reverse !important;\n  }\n  .justify-content-xl-start {\n    -ms-flex-pack: start !important;\n        justify-content: flex-start !important;\n  }\n  .justify-content-xl-end {\n    -ms-flex-pack: end !important;\n        justify-content: flex-end !important;\n  }\n  .justify-content-xl-center {\n    -ms-flex-pack: center !important;\n        justify-content: center !important;\n  }\n  .justify-content-xl-between {\n    -ms-flex-pack: justify !important;\n        justify-content: space-between !important;\n  }\n  .justify-content-xl-around {\n    -ms-flex-pack: distribute !important;\n        justify-content: space-around !important;\n  }\n  .align-items-xl-start {\n    -ms-flex-align: start !important;\n        align-items: flex-start !important;\n  }\n  .align-items-xl-end {\n    -ms-flex-align: end !important;\n        align-items: flex-end !important;\n  }\n  .align-items-xl-center {\n    -ms-flex-align: center !important;\n        align-items: center !important;\n  }\n  .align-items-xl-baseline {\n    -ms-flex-align: baseline !important;\n        align-items: baseline !important;\n  }\n  .align-items-xl-stretch {\n    -ms-flex-align: stretch !important;\n        align-items: stretch !important;\n  }\n  .align-content-xl-start {\n    -ms-flex-line-pack: start !important;\n        align-content: flex-start !important;\n  }\n  .align-content-xl-end {\n    -ms-flex-line-pack: end !important;\n        align-content: flex-end !important;\n  }\n  .align-content-xl-center {\n    -ms-flex-line-pack: center !important;\n        align-content: center !important;\n  }\n  .align-content-xl-between {\n    -ms-flex-line-pack: justify !important;\n        align-content: space-between !important;\n  }\n  .align-content-xl-around {\n    -ms-flex-line-pack: distribute !important;\n        align-content: space-around !important;\n  }\n  .align-content-xl-stretch {\n    -ms-flex-line-pack: stretch !important;\n        align-content: stretch !important;\n  }\n  .align-self-xl-auto {\n    -ms-flex-item-align: auto !important;\n        align-self: auto !important;\n  }\n  .align-self-xl-start {\n    -ms-flex-item-align: start !important;\n        align-self: flex-start !important;\n  }\n  .align-self-xl-end {\n    -ms-flex-item-align: end !important;\n        align-self: flex-end !important;\n  }\n  .align-self-xl-center {\n    -ms-flex-item-align: center !important;\n        align-self: center !important;\n  }\n  .align-self-xl-baseline {\n    -ms-flex-item-align: baseline !important;\n        align-self: baseline !important;\n  }\n  .align-self-xl-stretch {\n    -ms-flex-item-align: stretch !important;\n        align-self: stretch !important;\n  }\n}\n/*# sourceMappingURL=bootstrap-grid.css.map */"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/bootstrap/css/bootstrap-reboot.css",
    "content": "/*!\n * Bootstrap Reboot v4.0.0-beta.2 (https://getbootstrap.com)\n * Copyright 2011-2017 The Bootstrap Authors\n * Copyright 2011-2017 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)\n */\n*,\n*::before,\n*::after {\n  box-sizing: border-box;\n}\n\nhtml {\n  font-family: sans-serif;\n  line-height: 1.15;\n  -webkit-text-size-adjust: 100%;\n  -ms-text-size-adjust: 100%;\n  -ms-overflow-style: scrollbar;\n  -webkit-tap-highlight-color: transparent;\n}\n\n@-ms-viewport {\n  width: device-width;\n}\n\narticle, aside, dialog, figcaption, figure, footer, header, hgroup, main, nav, section {\n  display: block;\n}\n\nbody {\n  margin: 0;\n  font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";\n  font-size: 1rem;\n  font-weight: 400;\n  line-height: 1.5;\n  color: #212529;\n  text-align: left;\n  background-color: #fff;\n}\n\n[tabindex=\"-1\"]:focus {\n  outline: none !important;\n}\n\nhr {\n  box-sizing: content-box;\n  height: 0;\n  overflow: visible;\n}\n\nh1, h2, h3, h4, h5, h6 {\n  margin-top: 0;\n  margin-bottom: 0.5rem;\n}\n\np {\n  margin-top: 0;\n  margin-bottom: 1rem;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  text-decoration: underline;\n  -webkit-text-decoration: underline dotted;\n          text-decoration: underline dotted;\n  cursor: help;\n  border-bottom: 0;\n}\n\naddress {\n  margin-bottom: 1rem;\n  font-style: normal;\n  line-height: inherit;\n}\n\nol,\nul,\ndl {\n  margin-top: 0;\n  margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n  margin-bottom: 0;\n}\n\ndt {\n  font-weight: 700;\n}\n\ndd {\n  margin-bottom: .5rem;\n  margin-left: 0;\n}\n\nblockquote {\n  margin: 0 0 1rem;\n}\n\ndfn {\n  font-style: italic;\n}\n\nb,\nstrong {\n  font-weight: bolder;\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\nsub {\n  bottom: -.25em;\n}\n\nsup {\n  top: -.5em;\n}\n\na {\n  color: #007bff;\n  text-decoration: none;\n  background-color: transparent;\n  -webkit-text-decoration-skip: objects;\n}\n\na:hover {\n  color: #0056b3;\n  text-decoration: underline;\n}\n\na:not([href]):not([tabindex]) {\n  color: inherit;\n  text-decoration: none;\n}\n\na:not([href]):not([tabindex]):focus, a:not([href]):not([tabindex]):hover {\n  color: inherit;\n  text-decoration: none;\n}\n\na:not([href]):not([tabindex]):focus {\n  outline: 0;\n}\n\npre,\ncode,\nkbd,\nsamp {\n  font-family: monospace, monospace;\n  font-size: 1em;\n}\n\npre {\n  margin-top: 0;\n  margin-bottom: 1rem;\n  overflow: auto;\n  -ms-overflow-style: scrollbar;\n}\n\nfigure {\n  margin: 0 0 1rem;\n}\n\nimg {\n  vertical-align: middle;\n  border-style: none;\n}\n\nsvg:not(:root) {\n  overflow: hidden;\n}\n\na,\narea,\nbutton,\n[role=\"button\"],\ninput:not([type=\"range\"]),\nlabel,\nselect,\nsummary,\ntextarea {\n  -ms-touch-action: manipulation;\n      touch-action: manipulation;\n}\n\ntable {\n  border-collapse: collapse;\n}\n\ncaption {\n  padding-top: 0.75rem;\n  padding-bottom: 0.75rem;\n  color: #868e96;\n  text-align: left;\n  caption-side: bottom;\n}\n\nth {\n  text-align: inherit;\n}\n\nlabel {\n  display: inline-block;\n  margin-bottom: .5rem;\n}\n\nbutton {\n  border-radius: 0;\n}\n\nbutton:focus {\n  outline: 1px dotted;\n  outline: 5px auto -webkit-focus-ring-color;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n  margin: 0;\n  font-family: inherit;\n  font-size: inherit;\n  line-height: inherit;\n}\n\nbutton,\ninput {\n  overflow: visible;\n}\n\nbutton,\nselect {\n  text-transform: none;\n}\n\nbutton,\nhtml [type=\"button\"],\n[type=\"reset\"],\n[type=\"submit\"] {\n  -webkit-appearance: button;\n}\n\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n  padding: 0;\n  border-style: none;\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  box-sizing: border-box;\n  padding: 0;\n}\n\ninput[type=\"date\"],\ninput[type=\"time\"],\ninput[type=\"datetime-local\"],\ninput[type=\"month\"] {\n  -webkit-appearance: listbox;\n}\n\ntextarea {\n  overflow: auto;\n  resize: vertical;\n}\n\nfieldset {\n  min-width: 0;\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  max-width: 100%;\n  padding: 0;\n  margin-bottom: .5rem;\n  font-size: 1.5rem;\n  line-height: inherit;\n  color: inherit;\n  white-space: normal;\n}\n\nprogress {\n  vertical-align: baseline;\n}\n\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n  height: auto;\n}\n\n[type=\"search\"] {\n  outline-offset: -2px;\n  -webkit-appearance: none;\n}\n\n[type=\"search\"]::-webkit-search-cancel-button,\n[type=\"search\"]::-webkit-search-decoration {\n  -webkit-appearance: none;\n}\n\n::-webkit-file-upload-button {\n  font: inherit;\n  -webkit-appearance: button;\n}\n\noutput {\n  display: inline-block;\n}\n\nsummary {\n  display: list-item;\n}\n\ntemplate {\n  display: none;\n}\n\n[hidden] {\n  display: none !important;\n}\n/*# sourceMappingURL=bootstrap-reboot.css.map */"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/bootstrap/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v4.0.0-beta.2 (https://getbootstrap.com)\n * Copyright 2011-2017 The Bootstrap Authors\n * Copyright 2011-2017 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n:root {\n  --blue: #007bff;\n  --indigo: #6610f2;\n  --purple: #6f42c1;\n  --pink: #e83e8c;\n  --red: #dc3545;\n  --orange: #fd7e14;\n  --yellow: #ffc107;\n  --green: #28a745;\n  --teal: #20c997;\n  --cyan: #17a2b8;\n  --white: #fff;\n  --gray: #868e96;\n  --gray-dark: #343a40;\n  --primary: #007bff;\n  --secondary: #868e96;\n  --success: #28a745;\n  --info: #17a2b8;\n  --warning: #ffc107;\n  --danger: #dc3545;\n  --light: #f8f9fa;\n  --dark: #343a40;\n  --breakpoint-xs: 0;\n  --breakpoint-sm: 576px;\n  --breakpoint-md: 768px;\n  --breakpoint-lg: 992px;\n  --breakpoint-xl: 1200px;\n  --font-family-sans-serif: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";\n  --font-family-monospace: \"SFMono-Regular\", Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n}\n\n@media print {\n  *,\n  *::before,\n  *::after {\n    text-shadow: none !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  abbr[title]::after {\n    content: \" (\" attr(title) \")\";\n  }\n  pre {\n    white-space: pre-wrap !important;\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  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n  .navbar {\n    display: none;\n  }\n  .badge {\n    border: 1px solid #000;\n  }\n  .table {\n    border-collapse: collapse !important;\n  }\n  .table td,\n  .table th {\n    background-color: #fff !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  box-sizing: border-box;\n}\n\nhtml {\n  font-family: sans-serif;\n  line-height: 1.15;\n  -webkit-text-size-adjust: 100%;\n  -ms-text-size-adjust: 100%;\n  -ms-overflow-style: scrollbar;\n  -webkit-tap-highlight-color: transparent;\n}\n\n@-ms-viewport {\n  width: device-width;\n}\n\narticle, aside, dialog, figcaption, figure, footer, header, hgroup, main, nav, section {\n  display: block;\n}\n\nbody {\n  margin: 0;\n  font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";\n  font-size: 1rem;\n  font-weight: 400;\n  line-height: 1.5;\n  color: #212529;\n  text-align: left;\n  background-color: #fff;\n}\n\n[tabindex=\"-1\"]:focus {\n  outline: none !important;\n}\n\nhr {\n  box-sizing: content-box;\n  height: 0;\n  overflow: visible;\n}\n\nh1, h2, h3, h4, h5, h6 {\n  margin-top: 0;\n  margin-bottom: 0.5rem;\n}\n\np {\n  margin-top: 0;\n  margin-bottom: 1rem;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  text-decoration: underline;\n  -webkit-text-decoration: underline dotted;\n          text-decoration: underline dotted;\n  cursor: help;\n  border-bottom: 0;\n}\n\naddress {\n  margin-bottom: 1rem;\n  font-style: normal;\n  line-height: inherit;\n}\n\nol,\nul,\ndl {\n  margin-top: 0;\n  margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n  margin-bottom: 0;\n}\n\ndt {\n  font-weight: 700;\n}\n\ndd {\n  margin-bottom: .5rem;\n  margin-left: 0;\n}\n\nblockquote {\n  margin: 0 0 1rem;\n}\n\ndfn {\n  font-style: italic;\n}\n\nb,\nstrong {\n  font-weight: bolder;\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\nsub {\n  bottom: -.25em;\n}\n\nsup {\n  top: -.5em;\n}\n\na {\n  color: #007bff;\n  text-decoration: none;\n  background-color: transparent;\n  -webkit-text-decoration-skip: objects;\n}\n\na:hover {\n  color: #0056b3;\n  text-decoration: underline;\n}\n\na:not([href]):not([tabindex]) {\n  color: inherit;\n  text-decoration: none;\n}\n\na:not([href]):not([tabindex]):focus, a:not([href]):not([tabindex]):hover {\n  color: inherit;\n  text-decoration: none;\n}\n\na:not([href]):not([tabindex]):focus {\n  outline: 0;\n}\n\npre,\ncode,\nkbd,\nsamp {\n  font-family: monospace, monospace;\n  font-size: 1em;\n}\n\npre {\n  margin-top: 0;\n  margin-bottom: 1rem;\n  overflow: auto;\n  -ms-overflow-style: scrollbar;\n}\n\nfigure {\n  margin: 0 0 1rem;\n}\n\nimg {\n  vertical-align: middle;\n  border-style: none;\n}\n\nsvg:not(:root) {\n  overflow: hidden;\n}\n\na,\narea,\nbutton,\n[role=\"button\"],\ninput:not([type=\"range\"]),\nlabel,\nselect,\nsummary,\ntextarea {\n  -ms-touch-action: manipulation;\n      touch-action: manipulation;\n}\n\ntable {\n  border-collapse: collapse;\n}\n\ncaption {\n  padding-top: 0.75rem;\n  padding-bottom: 0.75rem;\n  color: #868e96;\n  text-align: left;\n  caption-side: bottom;\n}\n\nth {\n  text-align: inherit;\n}\n\nlabel {\n  display: inline-block;\n  margin-bottom: .5rem;\n}\n\nbutton {\n  border-radius: 0;\n}\n\nbutton:focus {\n  outline: 1px dotted;\n  outline: 5px auto -webkit-focus-ring-color;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n  margin: 0;\n  font-family: inherit;\n  font-size: inherit;\n  line-height: inherit;\n}\n\nbutton,\ninput {\n  overflow: visible;\n}\n\nbutton,\nselect {\n  text-transform: none;\n}\n\nbutton,\nhtml [type=\"button\"],\n[type=\"reset\"],\n[type=\"submit\"] {\n  -webkit-appearance: button;\n}\n\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n  padding: 0;\n  border-style: none;\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  box-sizing: border-box;\n  padding: 0;\n}\n\ninput[type=\"date\"],\ninput[type=\"time\"],\ninput[type=\"datetime-local\"],\ninput[type=\"month\"] {\n  -webkit-appearance: listbox;\n}\n\ntextarea {\n  overflow: auto;\n  resize: vertical;\n}\n\nfieldset {\n  min-width: 0;\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  max-width: 100%;\n  padding: 0;\n  margin-bottom: .5rem;\n  font-size: 1.5rem;\n  line-height: inherit;\n  color: inherit;\n  white-space: normal;\n}\n\nprogress {\n  vertical-align: baseline;\n}\n\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n  height: auto;\n}\n\n[type=\"search\"] {\n  outline-offset: -2px;\n  -webkit-appearance: none;\n}\n\n[type=\"search\"]::-webkit-search-cancel-button,\n[type=\"search\"]::-webkit-search-decoration {\n  -webkit-appearance: none;\n}\n\n::-webkit-file-upload-button {\n  font: inherit;\n  -webkit-appearance: button;\n}\n\noutput {\n  display: inline-block;\n}\n\nsummary {\n  display: list-item;\n}\n\ntemplate {\n  display: none;\n}\n\n[hidden] {\n  display: none !important;\n}\n\nh1, h2, h3, h4, h5, h6,\n.h1, .h2, .h3, .h4, .h5, .h6 {\n  margin-bottom: 0.5rem;\n  font-family: inherit;\n  font-weight: 500;\n  line-height: 1.2;\n  color: inherit;\n}\n\nh1, .h1 {\n  font-size: 2.5rem;\n}\n\nh2, .h2 {\n  font-size: 2rem;\n}\n\nh3, .h3 {\n  font-size: 1.75rem;\n}\n\nh4, .h4 {\n  font-size: 1.5rem;\n}\n\nh5, .h5 {\n  font-size: 1.25rem;\n}\n\nh6, .h6 {\n  font-size: 1rem;\n}\n\n.lead {\n  font-size: 1.25rem;\n  font-weight: 300;\n}\n\n.display-1 {\n  font-size: 6rem;\n  font-weight: 300;\n  line-height: 1.2;\n}\n\n.display-2 {\n  font-size: 5.5rem;\n  font-weight: 300;\n  line-height: 1.2;\n}\n\n.display-3 {\n  font-size: 4.5rem;\n  font-weight: 300;\n  line-height: 1.2;\n}\n\n.display-4 {\n  font-size: 3.5rem;\n  font-weight: 300;\n  line-height: 1.2;\n}\n\nhr {\n  margin-top: 1rem;\n  margin-bottom: 1rem;\n  border: 0;\n  border-top: 1px solid rgba(0, 0, 0, 0.1);\n}\n\nsmall,\n.small {\n  font-size: 80%;\n  font-weight: 400;\n}\n\nmark,\n.mark {\n  padding: 0.2em;\n  background-color: #fcf8e3;\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-item {\n  display: inline-block;\n}\n\n.list-inline-item:not(:last-child) {\n  margin-right: 5px;\n}\n\n.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\n.blockquote {\n  margin-bottom: 1rem;\n  font-size: 1.25rem;\n}\n\n.blockquote-footer {\n  display: block;\n  font-size: 80%;\n  color: #868e96;\n}\n\n.blockquote-footer::before {\n  content: \"\\2014 \\00A0\";\n}\n\n.img-fluid {\n  max-width: 100%;\n  height: auto;\n}\n\n.img-thumbnail {\n  padding: 0.25rem;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  border-radius: 0.25rem;\n  transition: all 0.2s ease-in-out;\n  max-width: 100%;\n  height: auto;\n}\n\n.figure {\n  display: inline-block;\n}\n\n.figure-img {\n  margin-bottom: 0.5rem;\n  line-height: 1;\n}\n\n.figure-caption {\n  font-size: 90%;\n  color: #868e96;\n}\n\ncode,\nkbd,\npre,\nsamp {\n  font-family: \"SFMono-Regular\", Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n}\n\ncode {\n  padding: 0.2rem 0.4rem;\n  font-size: 90%;\n  color: #bd4147;\n  background-color: #f8f9fa;\n  border-radius: 0.25rem;\n}\n\na > code {\n  padding: 0;\n  color: inherit;\n  background-color: inherit;\n}\n\nkbd {\n  padding: 0.2rem 0.4rem;\n  font-size: 90%;\n  color: #fff;\n  background-color: #212529;\n  border-radius: 0.2rem;\n}\n\nkbd kbd {\n  padding: 0;\n  font-size: 100%;\n  font-weight: 700;\n}\n\npre {\n  display: block;\n  margin-top: 0;\n  margin-bottom: 1rem;\n  font-size: 90%;\n  color: #212529;\n}\n\npre code {\n  padding: 0;\n  font-size: inherit;\n  color: inherit;\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  width: 100%;\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n@media (min-width: 576px) {\n  .container {\n    max-width: 540px;\n  }\n}\n\n@media (min-width: 768px) {\n  .container {\n    max-width: 720px;\n  }\n}\n\n@media (min-width: 992px) {\n  .container {\n    max-width: 960px;\n  }\n}\n\n@media (min-width: 1200px) {\n  .container {\n    max-width: 1140px;\n  }\n}\n\n.container-fluid {\n  width: 100%;\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.row {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-wrap: wrap;\n      flex-wrap: wrap;\n  margin-right: -15px;\n  margin-left: -15px;\n}\n\n.no-gutters {\n  margin-right: 0;\n  margin-left: 0;\n}\n\n.no-gutters > .col,\n.no-gutters > [class*=\"col-\"] {\n  padding-right: 0;\n  padding-left: 0;\n}\n\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,\n.col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm,\n.col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md,\n.col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg,\n.col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl,\n.col-xl-auto {\n  position: relative;\n  width: 100%;\n  min-height: 1px;\n  padding-right: 15px;\n  padding-left: 15px;\n}\n\n.col {\n  -ms-flex-preferred-size: 0;\n      flex-basis: 0;\n  -ms-flex-positive: 1;\n      flex-grow: 1;\n  max-width: 100%;\n}\n\n.col-auto {\n  -ms-flex: 0 0 auto;\n      flex: 0 0 auto;\n  width: auto;\n  max-width: none;\n}\n\n.col-1 {\n  -ms-flex: 0 0 8.333333%;\n      flex: 0 0 8.333333%;\n  max-width: 8.333333%;\n}\n\n.col-2 {\n  -ms-flex: 0 0 16.666667%;\n      flex: 0 0 16.666667%;\n  max-width: 16.666667%;\n}\n\n.col-3 {\n  -ms-flex: 0 0 25%;\n      flex: 0 0 25%;\n  max-width: 25%;\n}\n\n.col-4 {\n  -ms-flex: 0 0 33.333333%;\n      flex: 0 0 33.333333%;\n  max-width: 33.333333%;\n}\n\n.col-5 {\n  -ms-flex: 0 0 41.666667%;\n      flex: 0 0 41.666667%;\n  max-width: 41.666667%;\n}\n\n.col-6 {\n  -ms-flex: 0 0 50%;\n      flex: 0 0 50%;\n  max-width: 50%;\n}\n\n.col-7 {\n  -ms-flex: 0 0 58.333333%;\n      flex: 0 0 58.333333%;\n  max-width: 58.333333%;\n}\n\n.col-8 {\n  -ms-flex: 0 0 66.666667%;\n      flex: 0 0 66.666667%;\n  max-width: 66.666667%;\n}\n\n.col-9 {\n  -ms-flex: 0 0 75%;\n      flex: 0 0 75%;\n  max-width: 75%;\n}\n\n.col-10 {\n  -ms-flex: 0 0 83.333333%;\n      flex: 0 0 83.333333%;\n  max-width: 83.333333%;\n}\n\n.col-11 {\n  -ms-flex: 0 0 91.666667%;\n      flex: 0 0 91.666667%;\n  max-width: 91.666667%;\n}\n\n.col-12 {\n  -ms-flex: 0 0 100%;\n      flex: 0 0 100%;\n  max-width: 100%;\n}\n\n.order-first {\n  -ms-flex-order: -1;\n      order: -1;\n}\n\n.order-1 {\n  -ms-flex-order: 1;\n      order: 1;\n}\n\n.order-2 {\n  -ms-flex-order: 2;\n      order: 2;\n}\n\n.order-3 {\n  -ms-flex-order: 3;\n      order: 3;\n}\n\n.order-4 {\n  -ms-flex-order: 4;\n      order: 4;\n}\n\n.order-5 {\n  -ms-flex-order: 5;\n      order: 5;\n}\n\n.order-6 {\n  -ms-flex-order: 6;\n      order: 6;\n}\n\n.order-7 {\n  -ms-flex-order: 7;\n      order: 7;\n}\n\n.order-8 {\n  -ms-flex-order: 8;\n      order: 8;\n}\n\n.order-9 {\n  -ms-flex-order: 9;\n      order: 9;\n}\n\n.order-10 {\n  -ms-flex-order: 10;\n      order: 10;\n}\n\n.order-11 {\n  -ms-flex-order: 11;\n      order: 11;\n}\n\n.order-12 {\n  -ms-flex-order: 12;\n      order: 12;\n}\n\n.offset-1 {\n  margin-left: 8.333333%;\n}\n\n.offset-2 {\n  margin-left: 16.666667%;\n}\n\n.offset-3 {\n  margin-left: 25%;\n}\n\n.offset-4 {\n  margin-left: 33.333333%;\n}\n\n.offset-5 {\n  margin-left: 41.666667%;\n}\n\n.offset-6 {\n  margin-left: 50%;\n}\n\n.offset-7 {\n  margin-left: 58.333333%;\n}\n\n.offset-8 {\n  margin-left: 66.666667%;\n}\n\n.offset-9 {\n  margin-left: 75%;\n}\n\n.offset-10 {\n  margin-left: 83.333333%;\n}\n\n.offset-11 {\n  margin-left: 91.666667%;\n}\n\n@media (min-width: 576px) {\n  .col-sm {\n    -ms-flex-preferred-size: 0;\n        flex-basis: 0;\n    -ms-flex-positive: 1;\n        flex-grow: 1;\n    max-width: 100%;\n  }\n  .col-sm-auto {\n    -ms-flex: 0 0 auto;\n        flex: 0 0 auto;\n    width: auto;\n    max-width: none;\n  }\n  .col-sm-1 {\n    -ms-flex: 0 0 8.333333%;\n        flex: 0 0 8.333333%;\n    max-width: 8.333333%;\n  }\n  .col-sm-2 {\n    -ms-flex: 0 0 16.666667%;\n        flex: 0 0 16.666667%;\n    max-width: 16.666667%;\n  }\n  .col-sm-3 {\n    -ms-flex: 0 0 25%;\n        flex: 0 0 25%;\n    max-width: 25%;\n  }\n  .col-sm-4 {\n    -ms-flex: 0 0 33.333333%;\n        flex: 0 0 33.333333%;\n    max-width: 33.333333%;\n  }\n  .col-sm-5 {\n    -ms-flex: 0 0 41.666667%;\n        flex: 0 0 41.666667%;\n    max-width: 41.666667%;\n  }\n  .col-sm-6 {\n    -ms-flex: 0 0 50%;\n        flex: 0 0 50%;\n    max-width: 50%;\n  }\n  .col-sm-7 {\n    -ms-flex: 0 0 58.333333%;\n        flex: 0 0 58.333333%;\n    max-width: 58.333333%;\n  }\n  .col-sm-8 {\n    -ms-flex: 0 0 66.666667%;\n        flex: 0 0 66.666667%;\n    max-width: 66.666667%;\n  }\n  .col-sm-9 {\n    -ms-flex: 0 0 75%;\n        flex: 0 0 75%;\n    max-width: 75%;\n  }\n  .col-sm-10 {\n    -ms-flex: 0 0 83.333333%;\n        flex: 0 0 83.333333%;\n    max-width: 83.333333%;\n  }\n  .col-sm-11 {\n    -ms-flex: 0 0 91.666667%;\n        flex: 0 0 91.666667%;\n    max-width: 91.666667%;\n  }\n  .col-sm-12 {\n    -ms-flex: 0 0 100%;\n        flex: 0 0 100%;\n    max-width: 100%;\n  }\n  .order-sm-first {\n    -ms-flex-order: -1;\n        order: -1;\n  }\n  .order-sm-1 {\n    -ms-flex-order: 1;\n        order: 1;\n  }\n  .order-sm-2 {\n    -ms-flex-order: 2;\n        order: 2;\n  }\n  .order-sm-3 {\n    -ms-flex-order: 3;\n        order: 3;\n  }\n  .order-sm-4 {\n    -ms-flex-order: 4;\n        order: 4;\n  }\n  .order-sm-5 {\n    -ms-flex-order: 5;\n        order: 5;\n  }\n  .order-sm-6 {\n    -ms-flex-order: 6;\n        order: 6;\n  }\n  .order-sm-7 {\n    -ms-flex-order: 7;\n        order: 7;\n  }\n  .order-sm-8 {\n    -ms-flex-order: 8;\n        order: 8;\n  }\n  .order-sm-9 {\n    -ms-flex-order: 9;\n        order: 9;\n  }\n  .order-sm-10 {\n    -ms-flex-order: 10;\n        order: 10;\n  }\n  .order-sm-11 {\n    -ms-flex-order: 11;\n        order: 11;\n  }\n  .order-sm-12 {\n    -ms-flex-order: 12;\n        order: 12;\n  }\n  .offset-sm-0 {\n    margin-left: 0;\n  }\n  .offset-sm-1 {\n    margin-left: 8.333333%;\n  }\n  .offset-sm-2 {\n    margin-left: 16.666667%;\n  }\n  .offset-sm-3 {\n    margin-left: 25%;\n  }\n  .offset-sm-4 {\n    margin-left: 33.333333%;\n  }\n  .offset-sm-5 {\n    margin-left: 41.666667%;\n  }\n  .offset-sm-6 {\n    margin-left: 50%;\n  }\n  .offset-sm-7 {\n    margin-left: 58.333333%;\n  }\n  .offset-sm-8 {\n    margin-left: 66.666667%;\n  }\n  .offset-sm-9 {\n    margin-left: 75%;\n  }\n  .offset-sm-10 {\n    margin-left: 83.333333%;\n  }\n  .offset-sm-11 {\n    margin-left: 91.666667%;\n  }\n}\n\n@media (min-width: 768px) {\n  .col-md {\n    -ms-flex-preferred-size: 0;\n        flex-basis: 0;\n    -ms-flex-positive: 1;\n        flex-grow: 1;\n    max-width: 100%;\n  }\n  .col-md-auto {\n    -ms-flex: 0 0 auto;\n        flex: 0 0 auto;\n    width: auto;\n    max-width: none;\n  }\n  .col-md-1 {\n    -ms-flex: 0 0 8.333333%;\n        flex: 0 0 8.333333%;\n    max-width: 8.333333%;\n  }\n  .col-md-2 {\n    -ms-flex: 0 0 16.666667%;\n        flex: 0 0 16.666667%;\n    max-width: 16.666667%;\n  }\n  .col-md-3 {\n    -ms-flex: 0 0 25%;\n        flex: 0 0 25%;\n    max-width: 25%;\n  }\n  .col-md-4 {\n    -ms-flex: 0 0 33.333333%;\n        flex: 0 0 33.333333%;\n    max-width: 33.333333%;\n  }\n  .col-md-5 {\n    -ms-flex: 0 0 41.666667%;\n        flex: 0 0 41.666667%;\n    max-width: 41.666667%;\n  }\n  .col-md-6 {\n    -ms-flex: 0 0 50%;\n        flex: 0 0 50%;\n    max-width: 50%;\n  }\n  .col-md-7 {\n    -ms-flex: 0 0 58.333333%;\n        flex: 0 0 58.333333%;\n    max-width: 58.333333%;\n  }\n  .col-md-8 {\n    -ms-flex: 0 0 66.666667%;\n        flex: 0 0 66.666667%;\n    max-width: 66.666667%;\n  }\n  .col-md-9 {\n    -ms-flex: 0 0 75%;\n        flex: 0 0 75%;\n    max-width: 75%;\n  }\n  .col-md-10 {\n    -ms-flex: 0 0 83.333333%;\n        flex: 0 0 83.333333%;\n    max-width: 83.333333%;\n  }\n  .col-md-11 {\n    -ms-flex: 0 0 91.666667%;\n        flex: 0 0 91.666667%;\n    max-width: 91.666667%;\n  }\n  .col-md-12 {\n    -ms-flex: 0 0 100%;\n        flex: 0 0 100%;\n    max-width: 100%;\n  }\n  .order-md-first {\n    -ms-flex-order: -1;\n        order: -1;\n  }\n  .order-md-1 {\n    -ms-flex-order: 1;\n        order: 1;\n  }\n  .order-md-2 {\n    -ms-flex-order: 2;\n        order: 2;\n  }\n  .order-md-3 {\n    -ms-flex-order: 3;\n        order: 3;\n  }\n  .order-md-4 {\n    -ms-flex-order: 4;\n        order: 4;\n  }\n  .order-md-5 {\n    -ms-flex-order: 5;\n        order: 5;\n  }\n  .order-md-6 {\n    -ms-flex-order: 6;\n        order: 6;\n  }\n  .order-md-7 {\n    -ms-flex-order: 7;\n        order: 7;\n  }\n  .order-md-8 {\n    -ms-flex-order: 8;\n        order: 8;\n  }\n  .order-md-9 {\n    -ms-flex-order: 9;\n        order: 9;\n  }\n  .order-md-10 {\n    -ms-flex-order: 10;\n        order: 10;\n  }\n  .order-md-11 {\n    -ms-flex-order: 11;\n        order: 11;\n  }\n  .order-md-12 {\n    -ms-flex-order: 12;\n        order: 12;\n  }\n  .offset-md-0 {\n    margin-left: 0;\n  }\n  .offset-md-1 {\n    margin-left: 8.333333%;\n  }\n  .offset-md-2 {\n    margin-left: 16.666667%;\n  }\n  .offset-md-3 {\n    margin-left: 25%;\n  }\n  .offset-md-4 {\n    margin-left: 33.333333%;\n  }\n  .offset-md-5 {\n    margin-left: 41.666667%;\n  }\n  .offset-md-6 {\n    margin-left: 50%;\n  }\n  .offset-md-7 {\n    margin-left: 58.333333%;\n  }\n  .offset-md-8 {\n    margin-left: 66.666667%;\n  }\n  .offset-md-9 {\n    margin-left: 75%;\n  }\n  .offset-md-10 {\n    margin-left: 83.333333%;\n  }\n  .offset-md-11 {\n    margin-left: 91.666667%;\n  }\n}\n\n@media (min-width: 992px) {\n  .col-lg {\n    -ms-flex-preferred-size: 0;\n        flex-basis: 0;\n    -ms-flex-positive: 1;\n        flex-grow: 1;\n    max-width: 100%;\n  }\n  .col-lg-auto {\n    -ms-flex: 0 0 auto;\n        flex: 0 0 auto;\n    width: auto;\n    max-width: none;\n  }\n  .col-lg-1 {\n    -ms-flex: 0 0 8.333333%;\n        flex: 0 0 8.333333%;\n    max-width: 8.333333%;\n  }\n  .col-lg-2 {\n    -ms-flex: 0 0 16.666667%;\n        flex: 0 0 16.666667%;\n    max-width: 16.666667%;\n  }\n  .col-lg-3 {\n    -ms-flex: 0 0 25%;\n        flex: 0 0 25%;\n    max-width: 25%;\n  }\n  .col-lg-4 {\n    -ms-flex: 0 0 33.333333%;\n        flex: 0 0 33.333333%;\n    max-width: 33.333333%;\n  }\n  .col-lg-5 {\n    -ms-flex: 0 0 41.666667%;\n        flex: 0 0 41.666667%;\n    max-width: 41.666667%;\n  }\n  .col-lg-6 {\n    -ms-flex: 0 0 50%;\n        flex: 0 0 50%;\n    max-width: 50%;\n  }\n  .col-lg-7 {\n    -ms-flex: 0 0 58.333333%;\n        flex: 0 0 58.333333%;\n    max-width: 58.333333%;\n  }\n  .col-lg-8 {\n    -ms-flex: 0 0 66.666667%;\n        flex: 0 0 66.666667%;\n    max-width: 66.666667%;\n  }\n  .col-lg-9 {\n    -ms-flex: 0 0 75%;\n        flex: 0 0 75%;\n    max-width: 75%;\n  }\n  .col-lg-10 {\n    -ms-flex: 0 0 83.333333%;\n        flex: 0 0 83.333333%;\n    max-width: 83.333333%;\n  }\n  .col-lg-11 {\n    -ms-flex: 0 0 91.666667%;\n        flex: 0 0 91.666667%;\n    max-width: 91.666667%;\n  }\n  .col-lg-12 {\n    -ms-flex: 0 0 100%;\n        flex: 0 0 100%;\n    max-width: 100%;\n  }\n  .order-lg-first {\n    -ms-flex-order: -1;\n        order: -1;\n  }\n  .order-lg-1 {\n    -ms-flex-order: 1;\n        order: 1;\n  }\n  .order-lg-2 {\n    -ms-flex-order: 2;\n        order: 2;\n  }\n  .order-lg-3 {\n    -ms-flex-order: 3;\n        order: 3;\n  }\n  .order-lg-4 {\n    -ms-flex-order: 4;\n        order: 4;\n  }\n  .order-lg-5 {\n    -ms-flex-order: 5;\n        order: 5;\n  }\n  .order-lg-6 {\n    -ms-flex-order: 6;\n        order: 6;\n  }\n  .order-lg-7 {\n    -ms-flex-order: 7;\n        order: 7;\n  }\n  .order-lg-8 {\n    -ms-flex-order: 8;\n        order: 8;\n  }\n  .order-lg-9 {\n    -ms-flex-order: 9;\n        order: 9;\n  }\n  .order-lg-10 {\n    -ms-flex-order: 10;\n        order: 10;\n  }\n  .order-lg-11 {\n    -ms-flex-order: 11;\n        order: 11;\n  }\n  .order-lg-12 {\n    -ms-flex-order: 12;\n        order: 12;\n  }\n  .offset-lg-0 {\n    margin-left: 0;\n  }\n  .offset-lg-1 {\n    margin-left: 8.333333%;\n  }\n  .offset-lg-2 {\n    margin-left: 16.666667%;\n  }\n  .offset-lg-3 {\n    margin-left: 25%;\n  }\n  .offset-lg-4 {\n    margin-left: 33.333333%;\n  }\n  .offset-lg-5 {\n    margin-left: 41.666667%;\n  }\n  .offset-lg-6 {\n    margin-left: 50%;\n  }\n  .offset-lg-7 {\n    margin-left: 58.333333%;\n  }\n  .offset-lg-8 {\n    margin-left: 66.666667%;\n  }\n  .offset-lg-9 {\n    margin-left: 75%;\n  }\n  .offset-lg-10 {\n    margin-left: 83.333333%;\n  }\n  .offset-lg-11 {\n    margin-left: 91.666667%;\n  }\n}\n\n@media (min-width: 1200px) {\n  .col-xl {\n    -ms-flex-preferred-size: 0;\n        flex-basis: 0;\n    -ms-flex-positive: 1;\n        flex-grow: 1;\n    max-width: 100%;\n  }\n  .col-xl-auto {\n    -ms-flex: 0 0 auto;\n        flex: 0 0 auto;\n    width: auto;\n    max-width: none;\n  }\n  .col-xl-1 {\n    -ms-flex: 0 0 8.333333%;\n        flex: 0 0 8.333333%;\n    max-width: 8.333333%;\n  }\n  .col-xl-2 {\n    -ms-flex: 0 0 16.666667%;\n        flex: 0 0 16.666667%;\n    max-width: 16.666667%;\n  }\n  .col-xl-3 {\n    -ms-flex: 0 0 25%;\n        flex: 0 0 25%;\n    max-width: 25%;\n  }\n  .col-xl-4 {\n    -ms-flex: 0 0 33.333333%;\n        flex: 0 0 33.333333%;\n    max-width: 33.333333%;\n  }\n  .col-xl-5 {\n    -ms-flex: 0 0 41.666667%;\n        flex: 0 0 41.666667%;\n    max-width: 41.666667%;\n  }\n  .col-xl-6 {\n    -ms-flex: 0 0 50%;\n        flex: 0 0 50%;\n    max-width: 50%;\n  }\n  .col-xl-7 {\n    -ms-flex: 0 0 58.333333%;\n        flex: 0 0 58.333333%;\n    max-width: 58.333333%;\n  }\n  .col-xl-8 {\n    -ms-flex: 0 0 66.666667%;\n        flex: 0 0 66.666667%;\n    max-width: 66.666667%;\n  }\n  .col-xl-9 {\n    -ms-flex: 0 0 75%;\n        flex: 0 0 75%;\n    max-width: 75%;\n  }\n  .col-xl-10 {\n    -ms-flex: 0 0 83.333333%;\n        flex: 0 0 83.333333%;\n    max-width: 83.333333%;\n  }\n  .col-xl-11 {\n    -ms-flex: 0 0 91.666667%;\n        flex: 0 0 91.666667%;\n    max-width: 91.666667%;\n  }\n  .col-xl-12 {\n    -ms-flex: 0 0 100%;\n        flex: 0 0 100%;\n    max-width: 100%;\n  }\n  .order-xl-first {\n    -ms-flex-order: -1;\n        order: -1;\n  }\n  .order-xl-1 {\n    -ms-flex-order: 1;\n        order: 1;\n  }\n  .order-xl-2 {\n    -ms-flex-order: 2;\n        order: 2;\n  }\n  .order-xl-3 {\n    -ms-flex-order: 3;\n        order: 3;\n  }\n  .order-xl-4 {\n    -ms-flex-order: 4;\n        order: 4;\n  }\n  .order-xl-5 {\n    -ms-flex-order: 5;\n        order: 5;\n  }\n  .order-xl-6 {\n    -ms-flex-order: 6;\n        order: 6;\n  }\n  .order-xl-7 {\n    -ms-flex-order: 7;\n        order: 7;\n  }\n  .order-xl-8 {\n    -ms-flex-order: 8;\n        order: 8;\n  }\n  .order-xl-9 {\n    -ms-flex-order: 9;\n        order: 9;\n  }\n  .order-xl-10 {\n    -ms-flex-order: 10;\n        order: 10;\n  }\n  .order-xl-11 {\n    -ms-flex-order: 11;\n        order: 11;\n  }\n  .order-xl-12 {\n    -ms-flex-order: 12;\n        order: 12;\n  }\n  .offset-xl-0 {\n    margin-left: 0;\n  }\n  .offset-xl-1 {\n    margin-left: 8.333333%;\n  }\n  .offset-xl-2 {\n    margin-left: 16.666667%;\n  }\n  .offset-xl-3 {\n    margin-left: 25%;\n  }\n  .offset-xl-4 {\n    margin-left: 33.333333%;\n  }\n  .offset-xl-5 {\n    margin-left: 41.666667%;\n  }\n  .offset-xl-6 {\n    margin-left: 50%;\n  }\n  .offset-xl-7 {\n    margin-left: 58.333333%;\n  }\n  .offset-xl-8 {\n    margin-left: 66.666667%;\n  }\n  .offset-xl-9 {\n    margin-left: 75%;\n  }\n  .offset-xl-10 {\n    margin-left: 83.333333%;\n  }\n  .offset-xl-11 {\n    margin-left: 91.666667%;\n  }\n}\n\n.table {\n  width: 100%;\n  max-width: 100%;\n  margin-bottom: 1rem;\n  background-color: transparent;\n}\n\n.table th,\n.table td {\n  padding: 0.75rem;\n  vertical-align: top;\n  border-top: 1px solid #e9ecef;\n}\n\n.table thead th {\n  vertical-align: bottom;\n  border-bottom: 2px solid #e9ecef;\n}\n\n.table tbody + tbody {\n  border-top: 2px solid #e9ecef;\n}\n\n.table .table {\n  background-color: #fff;\n}\n\n.table-sm th,\n.table-sm td {\n  padding: 0.3rem;\n}\n\n.table-bordered {\n  border: 1px solid #e9ecef;\n}\n\n.table-bordered th,\n.table-bordered td {\n  border: 1px solid #e9ecef;\n}\n\n.table-bordered thead th,\n.table-bordered thead td {\n  border-bottom-width: 2px;\n}\n\n.table-striped tbody tr:nth-of-type(odd) {\n  background-color: rgba(0, 0, 0, 0.05);\n}\n\n.table-hover tbody tr:hover {\n  background-color: rgba(0, 0, 0, 0.075);\n}\n\n.table-primary,\n.table-primary > th,\n.table-primary > td {\n  background-color: #b8daff;\n}\n\n.table-hover .table-primary:hover {\n  background-color: #9fcdff;\n}\n\n.table-hover .table-primary:hover > td,\n.table-hover .table-primary:hover > th {\n  background-color: #9fcdff;\n}\n\n.table-secondary,\n.table-secondary > th,\n.table-secondary > td {\n  background-color: #dddfe2;\n}\n\n.table-hover .table-secondary:hover {\n  background-color: #cfd2d6;\n}\n\n.table-hover .table-secondary:hover > td,\n.table-hover .table-secondary:hover > th {\n  background-color: #cfd2d6;\n}\n\n.table-success,\n.table-success > th,\n.table-success > td {\n  background-color: #c3e6cb;\n}\n\n.table-hover .table-success:hover {\n  background-color: #b1dfbb;\n}\n\n.table-hover .table-success:hover > td,\n.table-hover .table-success:hover > th {\n  background-color: #b1dfbb;\n}\n\n.table-info,\n.table-info > th,\n.table-info > td {\n  background-color: #bee5eb;\n}\n\n.table-hover .table-info:hover {\n  background-color: #abdde5;\n}\n\n.table-hover .table-info:hover > td,\n.table-hover .table-info:hover > th {\n  background-color: #abdde5;\n}\n\n.table-warning,\n.table-warning > th,\n.table-warning > td {\n  background-color: #ffeeba;\n}\n\n.table-hover .table-warning:hover {\n  background-color: #ffe8a1;\n}\n\n.table-hover .table-warning:hover > td,\n.table-hover .table-warning:hover > th {\n  background-color: #ffe8a1;\n}\n\n.table-danger,\n.table-danger > th,\n.table-danger > td {\n  background-color: #f5c6cb;\n}\n\n.table-hover .table-danger:hover {\n  background-color: #f1b0b7;\n}\n\n.table-hover .table-danger:hover > td,\n.table-hover .table-danger:hover > th {\n  background-color: #f1b0b7;\n}\n\n.table-light,\n.table-light > th,\n.table-light > td {\n  background-color: #fdfdfe;\n}\n\n.table-hover .table-light:hover {\n  background-color: #ececf6;\n}\n\n.table-hover .table-light:hover > td,\n.table-hover .table-light:hover > th {\n  background-color: #ececf6;\n}\n\n.table-dark,\n.table-dark > th,\n.table-dark > td {\n  background-color: #c6c8ca;\n}\n\n.table-hover .table-dark:hover {\n  background-color: #b9bbbe;\n}\n\n.table-hover .table-dark:hover > td,\n.table-hover .table-dark:hover > th {\n  background-color: #b9bbbe;\n}\n\n.table-active,\n.table-active > th,\n.table-active > td {\n  background-color: rgba(0, 0, 0, 0.075);\n}\n\n.table-hover .table-active:hover {\n  background-color: rgba(0, 0, 0, 0.075);\n}\n\n.table-hover .table-active:hover > td,\n.table-hover .table-active:hover > th {\n  background-color: rgba(0, 0, 0, 0.075);\n}\n\n.table .thead-dark th {\n  color: #fff;\n  background-color: #212529;\n  border-color: #32383e;\n}\n\n.table .thead-light th {\n  color: #495057;\n  background-color: #e9ecef;\n  border-color: #e9ecef;\n}\n\n.table-dark {\n  color: #fff;\n  background-color: #212529;\n}\n\n.table-dark th,\n.table-dark td,\n.table-dark thead th {\n  border-color: #32383e;\n}\n\n.table-dark.table-bordered {\n  border: 0;\n}\n\n.table-dark.table-striped tbody tr:nth-of-type(odd) {\n  background-color: rgba(255, 255, 255, 0.05);\n}\n\n.table-dark.table-hover tbody tr:hover {\n  background-color: rgba(255, 255, 255, 0.075);\n}\n\n@media (max-width: 575px) {\n  .table-responsive-sm {\n    display: block;\n    width: 100%;\n    overflow-x: auto;\n    -webkit-overflow-scrolling: touch;\n    -ms-overflow-style: -ms-autohiding-scrollbar;\n  }\n  .table-responsive-sm.table-bordered {\n    border: 0;\n  }\n}\n\n@media (max-width: 767px) {\n  .table-responsive-md {\n    display: block;\n    width: 100%;\n    overflow-x: auto;\n    -webkit-overflow-scrolling: touch;\n    -ms-overflow-style: -ms-autohiding-scrollbar;\n  }\n  .table-responsive-md.table-bordered {\n    border: 0;\n  }\n}\n\n@media (max-width: 991px) {\n  .table-responsive-lg {\n    display: block;\n    width: 100%;\n    overflow-x: auto;\n    -webkit-overflow-scrolling: touch;\n    -ms-overflow-style: -ms-autohiding-scrollbar;\n  }\n  .table-responsive-lg.table-bordered {\n    border: 0;\n  }\n}\n\n@media (max-width: 1199px) {\n  .table-responsive-xl {\n    display: block;\n    width: 100%;\n    overflow-x: auto;\n    -webkit-overflow-scrolling: touch;\n    -ms-overflow-style: -ms-autohiding-scrollbar;\n  }\n  .table-responsive-xl.table-bordered {\n    border: 0;\n  }\n}\n\n.table-responsive {\n  display: block;\n  width: 100%;\n  overflow-x: auto;\n  -webkit-overflow-scrolling: touch;\n  -ms-overflow-style: -ms-autohiding-scrollbar;\n}\n\n.table-responsive.table-bordered {\n  border: 0;\n}\n\n.form-control {\n  display: block;\n  width: 100%;\n  padding: 0.375rem 0.75rem;\n  font-size: 1rem;\n  line-height: 1.5;\n  color: #495057;\n  background-color: #fff;\n  background-image: none;\n  background-clip: padding-box;\n  border: 1px solid #ced4da;\n  border-radius: 0.25rem;\n  transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;\n}\n\n.form-control::-ms-expand {\n  background-color: transparent;\n  border: 0;\n}\n\n.form-control:focus {\n  color: #495057;\n  background-color: #fff;\n  border-color: #80bdff;\n  outline: none;\n  box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.form-control::-webkit-input-placeholder {\n  color: #868e96;\n  opacity: 1;\n}\n\n.form-control:-ms-input-placeholder {\n  color: #868e96;\n  opacity: 1;\n}\n\n.form-control::-ms-input-placeholder {\n  color: #868e96;\n  opacity: 1;\n}\n\n.form-control::placeholder {\n  color: #868e96;\n  opacity: 1;\n}\n\n.form-control:disabled, .form-control[readonly] {\n  background-color: #e9ecef;\n  opacity: 1;\n}\n\nselect.form-control:not([size]):not([multiple]) {\n  height: calc(2.25rem + 2px);\n}\n\nselect.form-control:focus::-ms-value {\n  color: #495057;\n  background-color: #fff;\n}\n\n.form-control-file,\n.form-control-range {\n  display: block;\n}\n\n.col-form-label {\n  padding-top: calc(0.375rem + 1px);\n  padding-bottom: calc(0.375rem + 1px);\n  margin-bottom: 0;\n  line-height: 1.5;\n}\n\n.col-form-label-lg {\n  padding-top: calc(0.5rem + 1px);\n  padding-bottom: calc(0.5rem + 1px);\n  font-size: 1.25rem;\n  line-height: 1.5;\n}\n\n.col-form-label-sm {\n  padding-top: calc(0.25rem + 1px);\n  padding-bottom: calc(0.25rem + 1px);\n  font-size: 0.875rem;\n  line-height: 1.5;\n}\n\n.col-form-legend {\n  padding-top: 0.375rem;\n  padding-bottom: 0.375rem;\n  margin-bottom: 0;\n  font-size: 1rem;\n}\n\n.form-control-plaintext {\n  padding-top: 0.375rem;\n  padding-bottom: 0.375rem;\n  margin-bottom: 0;\n  line-height: 1.5;\n  background-color: transparent;\n  border: solid transparent;\n  border-width: 1px 0;\n}\n\n.form-control-plaintext.form-control-sm, .input-group-sm > .form-control-plaintext.form-control,\n.input-group-sm > .form-control-plaintext.input-group-addon,\n.input-group-sm > .input-group-btn > .form-control-plaintext.btn, .form-control-plaintext.form-control-lg, .input-group-lg > .form-control-plaintext.form-control,\n.input-group-lg > .form-control-plaintext.input-group-addon,\n.input-group-lg > .input-group-btn > .form-control-plaintext.btn {\n  padding-right: 0;\n  padding-left: 0;\n}\n\n.form-control-sm, .input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n  padding: 0.25rem 0.5rem;\n  font-size: 0.875rem;\n  line-height: 1.5;\n  border-radius: 0.2rem;\n}\n\nselect.form-control-sm:not([size]):not([multiple]), .input-group-sm > select.form-control:not([size]):not([multiple]),\n.input-group-sm > select.input-group-addon:not([size]):not([multiple]),\n.input-group-sm > .input-group-btn > select.btn:not([size]):not([multiple]) {\n  height: calc(1.8125rem + 2px);\n}\n\n.form-control-lg, .input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n  padding: 0.5rem 1rem;\n  font-size: 1.25rem;\n  line-height: 1.5;\n  border-radius: 0.3rem;\n}\n\nselect.form-control-lg:not([size]):not([multiple]), .input-group-lg > select.form-control:not([size]):not([multiple]),\n.input-group-lg > select.input-group-addon:not([size]):not([multiple]),\n.input-group-lg > .input-group-btn > select.btn:not([size]):not([multiple]) {\n  height: calc(2.875rem + 2px);\n}\n\n.form-group {\n  margin-bottom: 1rem;\n}\n\n.form-text {\n  display: block;\n  margin-top: 0.25rem;\n}\n\n.form-row {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-wrap: wrap;\n      flex-wrap: wrap;\n  margin-right: -5px;\n  margin-left: -5px;\n}\n\n.form-row > .col,\n.form-row > [class*=\"col-\"] {\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\n.form-check {\n  position: relative;\n  display: block;\n  margin-bottom: 0.5rem;\n}\n\n.form-check.disabled .form-check-label {\n  color: #868e96;\n}\n\n.form-check-label {\n  padding-left: 1.25rem;\n  margin-bottom: 0;\n}\n\n.form-check-input {\n  position: absolute;\n  margin-top: 0.25rem;\n  margin-left: -1.25rem;\n}\n\n.form-check-inline {\n  display: inline-block;\n  margin-right: 0.75rem;\n}\n\n.form-check-inline .form-check-label {\n  vertical-align: middle;\n}\n\n.valid-feedback {\n  display: none;\n  margin-top: .25rem;\n  font-size: .875rem;\n  color: #28a745;\n}\n\n.valid-tooltip {\n  position: absolute;\n  top: 100%;\n  z-index: 5;\n  display: none;\n  width: 250px;\n  padding: .5rem;\n  margin-top: .1rem;\n  font-size: .875rem;\n  line-height: 1;\n  color: #fff;\n  background-color: rgba(40, 167, 69, 0.8);\n  border-radius: .2rem;\n}\n\n.was-validated .form-control:valid, .form-control.is-valid, .was-validated\n.custom-select:valid,\n.custom-select.is-valid {\n  border-color: #28a745;\n}\n\n.was-validated .form-control:valid:focus, .form-control.is-valid:focus, .was-validated\n.custom-select:valid:focus,\n.custom-select.is-valid:focus {\n  box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25);\n}\n\n.was-validated .form-control:valid ~ .valid-feedback,\n.was-validated .form-control:valid ~ .valid-tooltip, .form-control.is-valid ~ .valid-feedback,\n.form-control.is-valid ~ .valid-tooltip, .was-validated\n.custom-select:valid ~ .valid-feedback,\n.was-validated\n.custom-select:valid ~ .valid-tooltip,\n.custom-select.is-valid ~ .valid-feedback,\n.custom-select.is-valid ~ .valid-tooltip {\n  display: block;\n}\n\n.was-validated .form-check-input:valid + .form-check-label, .form-check-input.is-valid + .form-check-label {\n  color: #28a745;\n}\n\n.was-validated .custom-control-input:valid ~ .custom-control-indicator, .custom-control-input.is-valid ~ .custom-control-indicator {\n  background-color: rgba(40, 167, 69, 0.25);\n}\n\n.was-validated .custom-control-input:valid ~ .custom-control-description, .custom-control-input.is-valid ~ .custom-control-description {\n  color: #28a745;\n}\n\n.was-validated .custom-file-input:valid ~ .custom-file-control, .custom-file-input.is-valid ~ .custom-file-control {\n  border-color: #28a745;\n}\n\n.was-validated .custom-file-input:valid ~ .custom-file-control::before, .custom-file-input.is-valid ~ .custom-file-control::before {\n  border-color: inherit;\n}\n\n.was-validated .custom-file-input:valid:focus, .custom-file-input.is-valid:focus {\n  box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25);\n}\n\n.invalid-feedback {\n  display: none;\n  margin-top: .25rem;\n  font-size: .875rem;\n  color: #dc3545;\n}\n\n.invalid-tooltip {\n  position: absolute;\n  top: 100%;\n  z-index: 5;\n  display: none;\n  width: 250px;\n  padding: .5rem;\n  margin-top: .1rem;\n  font-size: .875rem;\n  line-height: 1;\n  color: #fff;\n  background-color: rgba(220, 53, 69, 0.8);\n  border-radius: .2rem;\n}\n\n.was-validated .form-control:invalid, .form-control.is-invalid, .was-validated\n.custom-select:invalid,\n.custom-select.is-invalid {\n  border-color: #dc3545;\n}\n\n.was-validated .form-control:invalid:focus, .form-control.is-invalid:focus, .was-validated\n.custom-select:invalid:focus,\n.custom-select.is-invalid:focus {\n  box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);\n}\n\n.was-validated .form-control:invalid ~ .invalid-feedback,\n.was-validated .form-control:invalid ~ .invalid-tooltip, .form-control.is-invalid ~ .invalid-feedback,\n.form-control.is-invalid ~ .invalid-tooltip, .was-validated\n.custom-select:invalid ~ .invalid-feedback,\n.was-validated\n.custom-select:invalid ~ .invalid-tooltip,\n.custom-select.is-invalid ~ .invalid-feedback,\n.custom-select.is-invalid ~ .invalid-tooltip {\n  display: block;\n}\n\n.was-validated .form-check-input:invalid + .form-check-label, .form-check-input.is-invalid + .form-check-label {\n  color: #dc3545;\n}\n\n.was-validated .custom-control-input:invalid ~ .custom-control-indicator, .custom-control-input.is-invalid ~ .custom-control-indicator {\n  background-color: rgba(220, 53, 69, 0.25);\n}\n\n.was-validated .custom-control-input:invalid ~ .custom-control-description, .custom-control-input.is-invalid ~ .custom-control-description {\n  color: #dc3545;\n}\n\n.was-validated .custom-file-input:invalid ~ .custom-file-control, .custom-file-input.is-invalid ~ .custom-file-control {\n  border-color: #dc3545;\n}\n\n.was-validated .custom-file-input:invalid ~ .custom-file-control::before, .custom-file-input.is-invalid ~ .custom-file-control::before {\n  border-color: inherit;\n}\n\n.was-validated .custom-file-input:invalid:focus, .custom-file-input.is-invalid:focus {\n  box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);\n}\n\n.form-inline {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-flow: row wrap;\n      flex-flow: row wrap;\n  -ms-flex-align: center;\n      align-items: center;\n}\n\n.form-inline .form-check {\n  width: 100%;\n}\n\n@media (min-width: 576px) {\n  .form-inline label {\n    display: -ms-flexbox;\n    display: flex;\n    -ms-flex-align: center;\n        align-items: center;\n    -ms-flex-pack: center;\n        justify-content: center;\n    margin-bottom: 0;\n  }\n  .form-inline .form-group {\n    display: -ms-flexbox;\n    display: flex;\n    -ms-flex: 0 0 auto;\n        flex: 0 0 auto;\n    -ms-flex-flow: row wrap;\n        flex-flow: row wrap;\n    -ms-flex-align: center;\n        align-items: center;\n    margin-bottom: 0;\n  }\n  .form-inline .form-control {\n    display: inline-block;\n    width: auto;\n    vertical-align: middle;\n  }\n  .form-inline .form-control-plaintext {\n    display: inline-block;\n  }\n  .form-inline .input-group {\n    width: auto;\n  }\n  .form-inline .form-check {\n    display: -ms-flexbox;\n    display: flex;\n    -ms-flex-align: center;\n        align-items: center;\n    -ms-flex-pack: center;\n        justify-content: center;\n    width: auto;\n    margin-top: 0;\n    margin-bottom: 0;\n  }\n  .form-inline .form-check-label {\n    padding-left: 0;\n  }\n  .form-inline .form-check-input {\n    position: relative;\n    margin-top: 0;\n    margin-right: 0.25rem;\n    margin-left: 0;\n  }\n  .form-inline .custom-control {\n    display: -ms-flexbox;\n    display: flex;\n    -ms-flex-align: center;\n        align-items: center;\n    -ms-flex-pack: center;\n        justify-content: center;\n    padding-left: 0;\n  }\n  .form-inline .custom-control-indicator {\n    position: static;\n    display: inline-block;\n    margin-right: 0.25rem;\n    vertical-align: text-bottom;\n  }\n  .form-inline .has-feedback .form-control-feedback {\n    top: 0;\n  }\n}\n\n.btn {\n  display: inline-block;\n  font-weight: 400;\n  text-align: center;\n  white-space: nowrap;\n  vertical-align: middle;\n  -webkit-user-select: none;\n     -moz-user-select: none;\n      -ms-user-select: none;\n          user-select: none;\n  border: 1px solid transparent;\n  padding: 0.375rem 0.75rem;\n  font-size: 1rem;\n  line-height: 1.5;\n  border-radius: 0.25rem;\n  transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n}\n\n.btn:focus, .btn:hover {\n  text-decoration: none;\n}\n\n.btn:focus, .btn.focus {\n  outline: 0;\n  box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.btn.disabled, .btn:disabled {\n  opacity: .65;\n}\n\n.btn:not([disabled]):not(.disabled):active, .btn:not([disabled]):not(.disabled).active {\n  background-image: none;\n}\n\na.btn.disabled,\nfieldset[disabled] a.btn {\n  pointer-events: none;\n}\n\n.btn-primary {\n  color: #fff;\n  background-color: #007bff;\n  border-color: #007bff;\n}\n\n.btn-primary:hover {\n  color: #fff;\n  background-color: #0069d9;\n  border-color: #0062cc;\n}\n\n.btn-primary:focus, .btn-primary.focus {\n  box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5);\n}\n\n.btn-primary.disabled, .btn-primary:disabled {\n  background-color: #007bff;\n  border-color: #007bff;\n}\n\n.btn-primary:not([disabled]):not(.disabled):active, .btn-primary:not([disabled]):not(.disabled).active,\n.show > .btn-primary.dropdown-toggle {\n  color: #fff;\n  background-color: #0062cc;\n  border-color: #005cbf;\n  box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5);\n}\n\n.btn-secondary {\n  color: #fff;\n  background-color: #868e96;\n  border-color: #868e96;\n}\n\n.btn-secondary:hover {\n  color: #fff;\n  background-color: #727b84;\n  border-color: #6c757d;\n}\n\n.btn-secondary:focus, .btn-secondary.focus {\n  box-shadow: 0 0 0 0.2rem rgba(134, 142, 150, 0.5);\n}\n\n.btn-secondary.disabled, .btn-secondary:disabled {\n  background-color: #868e96;\n  border-color: #868e96;\n}\n\n.btn-secondary:not([disabled]):not(.disabled):active, .btn-secondary:not([disabled]):not(.disabled).active,\n.show > .btn-secondary.dropdown-toggle {\n  color: #fff;\n  background-color: #6c757d;\n  border-color: #666e76;\n  box-shadow: 0 0 0 0.2rem rgba(134, 142, 150, 0.5);\n}\n\n.btn-success {\n  color: #fff;\n  background-color: #28a745;\n  border-color: #28a745;\n}\n\n.btn-success:hover {\n  color: #fff;\n  background-color: #218838;\n  border-color: #1e7e34;\n}\n\n.btn-success:focus, .btn-success.focus {\n  box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5);\n}\n\n.btn-success.disabled, .btn-success:disabled {\n  background-color: #28a745;\n  border-color: #28a745;\n}\n\n.btn-success:not([disabled]):not(.disabled):active, .btn-success:not([disabled]):not(.disabled).active,\n.show > .btn-success.dropdown-toggle {\n  color: #fff;\n  background-color: #1e7e34;\n  border-color: #1c7430;\n  box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5);\n}\n\n.btn-info {\n  color: #fff;\n  background-color: #17a2b8;\n  border-color: #17a2b8;\n}\n\n.btn-info:hover {\n  color: #fff;\n  background-color: #138496;\n  border-color: #117a8b;\n}\n\n.btn-info:focus, .btn-info.focus {\n  box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5);\n}\n\n.btn-info.disabled, .btn-info:disabled {\n  background-color: #17a2b8;\n  border-color: #17a2b8;\n}\n\n.btn-info:not([disabled]):not(.disabled):active, .btn-info:not([disabled]):not(.disabled).active,\n.show > .btn-info.dropdown-toggle {\n  color: #fff;\n  background-color: #117a8b;\n  border-color: #10707f;\n  box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5);\n}\n\n.btn-warning {\n  color: #111;\n  background-color: #ffc107;\n  border-color: #ffc107;\n}\n\n.btn-warning:hover {\n  color: #111;\n  background-color: #e0a800;\n  border-color: #d39e00;\n}\n\n.btn-warning:focus, .btn-warning.focus {\n  box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5);\n}\n\n.btn-warning.disabled, .btn-warning:disabled {\n  background-color: #ffc107;\n  border-color: #ffc107;\n}\n\n.btn-warning:not([disabled]):not(.disabled):active, .btn-warning:not([disabled]):not(.disabled).active,\n.show > .btn-warning.dropdown-toggle {\n  color: #111;\n  background-color: #d39e00;\n  border-color: #c69500;\n  box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5);\n}\n\n.btn-danger {\n  color: #fff;\n  background-color: #dc3545;\n  border-color: #dc3545;\n}\n\n.btn-danger:hover {\n  color: #fff;\n  background-color: #c82333;\n  border-color: #bd2130;\n}\n\n.btn-danger:focus, .btn-danger.focus {\n  box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5);\n}\n\n.btn-danger.disabled, .btn-danger:disabled {\n  background-color: #dc3545;\n  border-color: #dc3545;\n}\n\n.btn-danger:not([disabled]):not(.disabled):active, .btn-danger:not([disabled]):not(.disabled).active,\n.show > .btn-danger.dropdown-toggle {\n  color: #fff;\n  background-color: #bd2130;\n  border-color: #b21f2d;\n  box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5);\n}\n\n.btn-light {\n  color: #111;\n  background-color: #f8f9fa;\n  border-color: #f8f9fa;\n}\n\n.btn-light:hover {\n  color: #111;\n  background-color: #e2e6ea;\n  border-color: #dae0e5;\n}\n\n.btn-light:focus, .btn-light.focus {\n  box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5);\n}\n\n.btn-light.disabled, .btn-light:disabled {\n  background-color: #f8f9fa;\n  border-color: #f8f9fa;\n}\n\n.btn-light:not([disabled]):not(.disabled):active, .btn-light:not([disabled]):not(.disabled).active,\n.show > .btn-light.dropdown-toggle {\n  color: #111;\n  background-color: #dae0e5;\n  border-color: #d3d9df;\n  box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5);\n}\n\n.btn-dark {\n  color: #fff;\n  background-color: #343a40;\n  border-color: #343a40;\n}\n\n.btn-dark:hover {\n  color: #fff;\n  background-color: #23272b;\n  border-color: #1d2124;\n}\n\n.btn-dark:focus, .btn-dark.focus {\n  box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5);\n}\n\n.btn-dark.disabled, .btn-dark:disabled {\n  background-color: #343a40;\n  border-color: #343a40;\n}\n\n.btn-dark:not([disabled]):not(.disabled):active, .btn-dark:not([disabled]):not(.disabled).active,\n.show > .btn-dark.dropdown-toggle {\n  color: #fff;\n  background-color: #1d2124;\n  border-color: #171a1d;\n  box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5);\n}\n\n.btn-outline-primary {\n  color: #007bff;\n  background-color: transparent;\n  background-image: none;\n  border-color: #007bff;\n}\n\n.btn-outline-primary:hover {\n  color: #fff;\n  background-color: #007bff;\n  border-color: #007bff;\n}\n\n.btn-outline-primary:focus, .btn-outline-primary.focus {\n  box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5);\n}\n\n.btn-outline-primary.disabled, .btn-outline-primary:disabled {\n  color: #007bff;\n  background-color: transparent;\n}\n\n.btn-outline-primary:not([disabled]):not(.disabled):active, .btn-outline-primary:not([disabled]):not(.disabled).active,\n.show > .btn-outline-primary.dropdown-toggle {\n  color: #fff;\n  background-color: #007bff;\n  border-color: #007bff;\n  box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5);\n}\n\n.btn-outline-secondary {\n  color: #868e96;\n  background-color: transparent;\n  background-image: none;\n  border-color: #868e96;\n}\n\n.btn-outline-secondary:hover {\n  color: #fff;\n  background-color: #868e96;\n  border-color: #868e96;\n}\n\n.btn-outline-secondary:focus, .btn-outline-secondary.focus {\n  box-shadow: 0 0 0 0.2rem rgba(134, 142, 150, 0.5);\n}\n\n.btn-outline-secondary.disabled, .btn-outline-secondary:disabled {\n  color: #868e96;\n  background-color: transparent;\n}\n\n.btn-outline-secondary:not([disabled]):not(.disabled):active, .btn-outline-secondary:not([disabled]):not(.disabled).active,\n.show > .btn-outline-secondary.dropdown-toggle {\n  color: #fff;\n  background-color: #868e96;\n  border-color: #868e96;\n  box-shadow: 0 0 0 0.2rem rgba(134, 142, 150, 0.5);\n}\n\n.btn-outline-success {\n  color: #28a745;\n  background-color: transparent;\n  background-image: none;\n  border-color: #28a745;\n}\n\n.btn-outline-success:hover {\n  color: #fff;\n  background-color: #28a745;\n  border-color: #28a745;\n}\n\n.btn-outline-success:focus, .btn-outline-success.focus {\n  box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5);\n}\n\n.btn-outline-success.disabled, .btn-outline-success:disabled {\n  color: #28a745;\n  background-color: transparent;\n}\n\n.btn-outline-success:not([disabled]):not(.disabled):active, .btn-outline-success:not([disabled]):not(.disabled).active,\n.show > .btn-outline-success.dropdown-toggle {\n  color: #fff;\n  background-color: #28a745;\n  border-color: #28a745;\n  box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5);\n}\n\n.btn-outline-info {\n  color: #17a2b8;\n  background-color: transparent;\n  background-image: none;\n  border-color: #17a2b8;\n}\n\n.btn-outline-info:hover {\n  color: #fff;\n  background-color: #17a2b8;\n  border-color: #17a2b8;\n}\n\n.btn-outline-info:focus, .btn-outline-info.focus {\n  box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5);\n}\n\n.btn-outline-info.disabled, .btn-outline-info:disabled {\n  color: #17a2b8;\n  background-color: transparent;\n}\n\n.btn-outline-info:not([disabled]):not(.disabled):active, .btn-outline-info:not([disabled]):not(.disabled).active,\n.show > .btn-outline-info.dropdown-toggle {\n  color: #fff;\n  background-color: #17a2b8;\n  border-color: #17a2b8;\n  box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5);\n}\n\n.btn-outline-warning {\n  color: #ffc107;\n  background-color: transparent;\n  background-image: none;\n  border-color: #ffc107;\n}\n\n.btn-outline-warning:hover {\n  color: #fff;\n  background-color: #ffc107;\n  border-color: #ffc107;\n}\n\n.btn-outline-warning:focus, .btn-outline-warning.focus {\n  box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5);\n}\n\n.btn-outline-warning.disabled, .btn-outline-warning:disabled {\n  color: #ffc107;\n  background-color: transparent;\n}\n\n.btn-outline-warning:not([disabled]):not(.disabled):active, .btn-outline-warning:not([disabled]):not(.disabled).active,\n.show > .btn-outline-warning.dropdown-toggle {\n  color: #fff;\n  background-color: #ffc107;\n  border-color: #ffc107;\n  box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5);\n}\n\n.btn-outline-danger {\n  color: #dc3545;\n  background-color: transparent;\n  background-image: none;\n  border-color: #dc3545;\n}\n\n.btn-outline-danger:hover {\n  color: #fff;\n  background-color: #dc3545;\n  border-color: #dc3545;\n}\n\n.btn-outline-danger:focus, .btn-outline-danger.focus {\n  box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5);\n}\n\n.btn-outline-danger.disabled, .btn-outline-danger:disabled {\n  color: #dc3545;\n  background-color: transparent;\n}\n\n.btn-outline-danger:not([disabled]):not(.disabled):active, .btn-outline-danger:not([disabled]):not(.disabled).active,\n.show > .btn-outline-danger.dropdown-toggle {\n  color: #fff;\n  background-color: #dc3545;\n  border-color: #dc3545;\n  box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5);\n}\n\n.btn-outline-light {\n  color: #f8f9fa;\n  background-color: transparent;\n  background-image: none;\n  border-color: #f8f9fa;\n}\n\n.btn-outline-light:hover {\n  color: #212529;\n  background-color: #f8f9fa;\n  border-color: #f8f9fa;\n}\n\n.btn-outline-light:focus, .btn-outline-light.focus {\n  box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5);\n}\n\n.btn-outline-light.disabled, .btn-outline-light:disabled {\n  color: #f8f9fa;\n  background-color: transparent;\n}\n\n.btn-outline-light:not([disabled]):not(.disabled):active, .btn-outline-light:not([disabled]):not(.disabled).active,\n.show > .btn-outline-light.dropdown-toggle {\n  color: #212529;\n  background-color: #f8f9fa;\n  border-color: #f8f9fa;\n  box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5);\n}\n\n.btn-outline-dark {\n  color: #343a40;\n  background-color: transparent;\n  background-image: none;\n  border-color: #343a40;\n}\n\n.btn-outline-dark:hover {\n  color: #fff;\n  background-color: #343a40;\n  border-color: #343a40;\n}\n\n.btn-outline-dark:focus, .btn-outline-dark.focus {\n  box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5);\n}\n\n.btn-outline-dark.disabled, .btn-outline-dark:disabled {\n  color: #343a40;\n  background-color: transparent;\n}\n\n.btn-outline-dark:not([disabled]):not(.disabled):active, .btn-outline-dark:not([disabled]):not(.disabled).active,\n.show > .btn-outline-dark.dropdown-toggle {\n  color: #fff;\n  background-color: #343a40;\n  border-color: #343a40;\n  box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5);\n}\n\n.btn-link {\n  font-weight: 400;\n  color: #007bff;\n  background-color: transparent;\n}\n\n.btn-link:hover {\n  color: #0056b3;\n  text-decoration: underline;\n  background-color: transparent;\n  border-color: transparent;\n}\n\n.btn-link:focus, .btn-link.focus {\n  border-color: transparent;\n  box-shadow: none;\n}\n\n.btn-link:disabled, .btn-link.disabled {\n  color: #868e96;\n}\n\n.btn-lg, .btn-group-lg > .btn {\n  padding: 0.5rem 1rem;\n  font-size: 1.25rem;\n  line-height: 1.5;\n  border-radius: 0.3rem;\n}\n\n.btn-sm, .btn-group-sm > .btn {\n  padding: 0.25rem 0.5rem;\n  font-size: 0.875rem;\n  line-height: 1.5;\n  border-radius: 0.2rem;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n}\n\n.btn-block + .btn-block {\n  margin-top: 0.5rem;\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  transition: opacity 0.15s linear;\n}\n\n.fade.show {\n  opacity: 1;\n}\n\n.collapse {\n  display: none;\n}\n\n.collapse.show {\n  display: block;\n}\n\ntr.collapse.show {\n  display: table-row;\n}\n\ntbody.collapse.show {\n  display: table-row-group;\n}\n\n.collapsing {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  transition: height 0.35s ease;\n}\n\n.dropup,\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle::after {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  margin-left: 0.255em;\n  vertical-align: 0.255em;\n  content: \"\";\n  border-top: 0.3em solid;\n  border-right: 0.3em solid transparent;\n  border-bottom: 0;\n  border-left: 0.3em solid transparent;\n}\n\n.dropdown-toggle:empty::after {\n  margin-left: 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: 10rem;\n  padding: 0.5rem 0;\n  margin: 0.125rem 0 0;\n  font-size: 1rem;\n  color: #212529;\n  text-align: left;\n  list-style: none;\n  background-color: #fff;\n  background-clip: padding-box;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  border-radius: 0.25rem;\n}\n\n.dropup .dropdown-menu {\n  margin-top: 0;\n  margin-bottom: 0.125rem;\n}\n\n.dropup .dropdown-toggle::after {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  margin-left: 0.255em;\n  vertical-align: 0.255em;\n  content: \"\";\n  border-top: 0;\n  border-right: 0.3em solid transparent;\n  border-bottom: 0.3em solid;\n  border-left: 0.3em solid transparent;\n}\n\n.dropup .dropdown-toggle:empty::after {\n  margin-left: 0;\n}\n\n.dropdown-divider {\n  height: 0;\n  margin: 0.5rem 0;\n  overflow: hidden;\n  border-top: 1px solid #e9ecef;\n}\n\n.dropdown-item {\n  display: block;\n  width: 100%;\n  padding: 0.25rem 1.5rem;\n  clear: both;\n  font-weight: 400;\n  color: #212529;\n  text-align: inherit;\n  white-space: nowrap;\n  background: none;\n  border: 0;\n}\n\n.dropdown-item:focus, .dropdown-item:hover {\n  color: #16181b;\n  text-decoration: none;\n  background-color: #f8f9fa;\n}\n\n.dropdown-item.active, .dropdown-item:active {\n  color: #fff;\n  text-decoration: none;\n  background-color: #007bff;\n}\n\n.dropdown-item.disabled, .dropdown-item:disabled {\n  color: #868e96;\n  background-color: transparent;\n}\n\n.dropdown-menu.show {\n  display: block;\n}\n\n.dropdown-header {\n  display: block;\n  padding: 0.5rem 1.5rem;\n  margin-bottom: 0;\n  font-size: 0.875rem;\n  color: #868e96;\n  white-space: nowrap;\n}\n\n.btn-group,\n.btn-group-vertical {\n  position: relative;\n  display: -ms-inline-flexbox;\n  display: inline-flex;\n  vertical-align: middle;\n}\n\n.btn-group > .btn,\n.btn-group-vertical > .btn {\n  position: relative;\n  -ms-flex: 0 1 auto;\n      flex: 0 1 auto;\n}\n\n.btn-group > .btn:hover,\n.btn-group-vertical > .btn:hover {\n  z-index: 2;\n}\n\n.btn-group > .btn:focus, .btn-group > .btn:active, .btn-group > .btn.active,\n.btn-group-vertical > .btn:focus,\n.btn-group-vertical > .btn:active,\n.btn-group-vertical > .btn.active {\n  z-index: 2;\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.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-left: -1px;\n}\n\n.btn-toolbar {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-wrap: wrap;\n      flex-wrap: wrap;\n  -ms-flex-pack: start;\n      justify-content: flex-start;\n}\n\n.btn-toolbar .input-group {\n  width: auto;\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-top-left-radius: 0;\n  border-bottom-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:not(:last-child) > .btn:last-child,\n.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n  border-top-right-radius: 0;\n  border-bottom-right-radius: 0;\n}\n\n.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {\n  border-top-left-radius: 0;\n  border-bottom-left-radius: 0;\n}\n\n.btn + .dropdown-toggle-split {\n  padding-right: 0.5625rem;\n  padding-left: 0.5625rem;\n}\n\n.btn + .dropdown-toggle-split::after {\n  margin-left: 0;\n}\n\n.btn-sm + .dropdown-toggle-split, .btn-group-sm > .btn + .dropdown-toggle-split {\n  padding-right: 0.375rem;\n  padding-left: 0.375rem;\n}\n\n.btn-lg + .dropdown-toggle-split, .btn-group-lg > .btn + .dropdown-toggle-split {\n  padding-right: 0.75rem;\n  padding-left: 0.75rem;\n}\n\n.btn-group-vertical {\n  -ms-flex-direction: column;\n      flex-direction: column;\n  -ms-flex-align: start;\n      align-items: flex-start;\n  -ms-flex-pack: center;\n      justify-content: center;\n}\n\n.btn-group-vertical .btn,\n.btn-group-vertical .btn-group {\n  width: 100%;\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-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-left-radius: 0;\n  border-top-right-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:not(:last-child) > .btn:last-child,\n.btn-group-vertical > .btn-group:first-child:not(:last-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:not(:first-child) > .btn:first-child {\n  border-top-left-radius: 0;\n  border-top-right-radius: 0;\n}\n\n[data-toggle=\"buttons\"] > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn input[type=\"checkbox\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"checkbox\"] {\n  position: absolute;\n  clip: rect(0, 0, 0, 0);\n  pointer-events: none;\n}\n\n.input-group {\n  position: relative;\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-align: stretch;\n      align-items: stretch;\n  width: 100%;\n}\n\n.input-group .form-control {\n  position: relative;\n  z-index: 2;\n  -ms-flex: 1 1 auto;\n      flex: 1 1 auto;\n  width: 1%;\n  margin-bottom: 0;\n}\n\n.input-group .form-control:focus, .input-group .form-control:active, .input-group .form-control:hover {\n  z-index: 3;\n}\n\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-align: center;\n      align-items: center;\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  white-space: nowrap;\n}\n\n.input-group-addon {\n  padding: 0.375rem 0.75rem;\n  margin-bottom: 0;\n  font-size: 1rem;\n  font-weight: 400;\n  line-height: 1.5;\n  color: #495057;\n  text-align: center;\n  background-color: #e9ecef;\n  border: 1px solid #ced4da;\n  border-radius: 0.25rem;\n}\n\n.input-group-addon.form-control-sm,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .input-group-addon.btn {\n  padding: 0.25rem 0.5rem;\n  font-size: 0.875rem;\n  border-radius: 0.2rem;\n}\n\n.input-group-addon.form-control-lg,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .input-group-addon.btn {\n  padding: 0.5rem 1rem;\n  font-size: 1.25rem;\n  border-radius: 0.3rem;\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:not(:last-child),\n.input-group-addon:not(:last-child),\n.input-group-btn:not(:last-child) > .btn,\n.input-group-btn:not(:last-child) > .btn-group > .btn,\n.input-group-btn:not(:last-child) > .dropdown-toggle,\n.input-group-btn:not(:first-child) > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:not(:first-child) > .btn-group:not(:last-child) > .btn {\n  border-top-right-radius: 0;\n  border-bottom-right-radius: 0;\n}\n\n.input-group-addon:not(:last-child) {\n  border-right: 0;\n}\n\n.input-group .form-control:not(:first-child),\n.input-group-addon:not(:first-child),\n.input-group-btn:not(:first-child) > .btn,\n.input-group-btn:not(:first-child) > .btn-group > .btn,\n.input-group-btn:not(:first-child) > .dropdown-toggle,\n.input-group-btn:not(:last-child) > .btn:not(:first-child),\n.input-group-btn:not(:last-child) > .btn-group:not(:first-child) > .btn {\n  border-top-left-radius: 0;\n  border-bottom-left-radius: 0;\n}\n\n.form-control + .input-group-addon:not(:first-child) {\n  border-left: 0;\n}\n\n.input-group-btn {\n  position: relative;\n  -ms-flex-align: stretch;\n      align-items: stretch;\n  font-size: 0;\n  white-space: nowrap;\n}\n\n.input-group-btn > .btn {\n  position: relative;\n}\n\n.input-group-btn > .btn + .btn {\n  margin-left: -1px;\n}\n\n.input-group-btn > .btn:focus, .input-group-btn > .btn:active, .input-group-btn > .btn:hover {\n  z-index: 3;\n}\n\n.input-group-btn:first-child > .btn + .btn {\n  margin-left: 0;\n}\n\n.input-group-btn:not(:last-child) > .btn,\n.input-group-btn:not(:last-child) > .btn-group {\n  margin-right: -1px;\n}\n\n.input-group-btn:not(:first-child) > .btn,\n.input-group-btn:not(:first-child) > .btn-group {\n  z-index: 2;\n  margin-left: 0;\n}\n\n.input-group-btn:not(:first-child) > .btn:first-child,\n.input-group-btn:not(:first-child) > .btn-group:first-child {\n  margin-left: -1px;\n}\n\n.input-group-btn:not(:first-child) > .btn:focus, .input-group-btn:not(:first-child) > .btn:active, .input-group-btn:not(:first-child) > .btn:hover,\n.input-group-btn:not(:first-child) > .btn-group:focus,\n.input-group-btn:not(:first-child) > .btn-group:active,\n.input-group-btn:not(:first-child) > .btn-group:hover {\n  z-index: 3;\n}\n\n.custom-control {\n  position: relative;\n  display: -ms-inline-flexbox;\n  display: inline-flex;\n  min-height: 1.5rem;\n  padding-left: 1.5rem;\n  margin-right: 1rem;\n}\n\n.custom-control-input {\n  position: absolute;\n  z-index: -1;\n  opacity: 0;\n}\n\n.custom-control-input:checked ~ .custom-control-indicator {\n  color: #fff;\n  background-color: #007bff;\n}\n\n.custom-control-input:focus ~ .custom-control-indicator {\n  box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.custom-control-input:active ~ .custom-control-indicator {\n  color: #fff;\n  background-color: #b3d7ff;\n}\n\n.custom-control-input:disabled ~ .custom-control-indicator {\n  background-color: #e9ecef;\n}\n\n.custom-control-input:disabled ~ .custom-control-description {\n  color: #868e96;\n}\n\n.custom-control-indicator {\n  position: absolute;\n  top: 0.25rem;\n  left: 0;\n  display: block;\n  width: 1rem;\n  height: 1rem;\n  pointer-events: none;\n  -webkit-user-select: none;\n     -moz-user-select: none;\n      -ms-user-select: none;\n          user-select: none;\n  background-color: #ddd;\n  background-repeat: no-repeat;\n  background-position: center center;\n  background-size: 50% 50%;\n}\n\n.custom-checkbox .custom-control-indicator {\n  border-radius: 0.25rem;\n}\n\n.custom-checkbox .custom-control-input:checked ~ .custom-control-indicator {\n  background-image: url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E\");\n}\n\n.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-indicator {\n  background-color: #007bff;\n  background-image: url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='%23fff' d='M0 2h4'/%3E%3C/svg%3E\");\n}\n\n.custom-radio .custom-control-indicator {\n  border-radius: 50%;\n}\n\n.custom-radio .custom-control-input:checked ~ .custom-control-indicator {\n  background-image: url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E\");\n}\n\n.custom-controls-stacked {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-direction: column;\n      flex-direction: column;\n}\n\n.custom-controls-stacked .custom-control {\n  margin-bottom: 0.25rem;\n}\n\n.custom-controls-stacked .custom-control + .custom-control {\n  margin-left: 0;\n}\n\n.custom-select {\n  display: inline-block;\n  max-width: 100%;\n  height: calc(2.25rem + 2px);\n  padding: 0.375rem 1.75rem 0.375rem 0.75rem;\n  line-height: 1.5;\n  color: #495057;\n  vertical-align: middle;\n  background: #fff url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='%23333' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E\") no-repeat right 0.75rem center;\n  background-size: 8px 10px;\n  border: 1px solid #ced4da;\n  border-radius: 0.25rem;\n  -webkit-appearance: none;\n     -moz-appearance: none;\n          appearance: none;\n}\n\n.custom-select:focus {\n  border-color: #80bdff;\n  outline: none;\n}\n\n.custom-select:focus::-ms-value {\n  color: #495057;\n  background-color: #fff;\n}\n\n.custom-select[multiple] {\n  height: auto;\n  background-image: none;\n}\n\n.custom-select:disabled {\n  color: #868e96;\n  background-color: #e9ecef;\n}\n\n.custom-select::-ms-expand {\n  opacity: 0;\n}\n\n.custom-select-sm {\n  height: calc(1.8125rem + 2px);\n  padding-top: 0.375rem;\n  padding-bottom: 0.375rem;\n  font-size: 75%;\n}\n\n.custom-file {\n  position: relative;\n  display: inline-block;\n  max-width: 100%;\n  height: calc(2.25rem + 2px);\n  margin-bottom: 0;\n}\n\n.custom-file-input {\n  min-width: 14rem;\n  max-width: 100%;\n  height: calc(2.25rem + 2px);\n  margin: 0;\n  opacity: 0;\n}\n\n.custom-file-input:focus ~ .custom-file-control {\n  box-shadow: 0 0 0 0.075rem #fff, 0 0 0 0.2rem #007bff;\n}\n\n.custom-file-control {\n  position: absolute;\n  top: 0;\n  right: 0;\n  left: 0;\n  z-index: 5;\n  height: calc(2.25rem + 2px);\n  padding: 0.375rem 0.75rem;\n  line-height: 1.5;\n  color: #495057;\n  pointer-events: none;\n  -webkit-user-select: none;\n     -moz-user-select: none;\n      -ms-user-select: none;\n          user-select: none;\n  background-color: #fff;\n  border: 1px solid #ced4da;\n  border-radius: 0.25rem;\n}\n\n.custom-file-control:lang(en):empty::after {\n  content: \"Choose file...\";\n}\n\n.custom-file-control::before {\n  position: absolute;\n  top: -1px;\n  right: -1px;\n  bottom: -1px;\n  z-index: 6;\n  display: block;\n  height: calc(2.25rem + 2px);\n  padding: 0.375rem 0.75rem;\n  line-height: 1.5;\n  color: #495057;\n  background-color: #e9ecef;\n  border: 1px solid #ced4da;\n  border-radius: 0 0.25rem 0.25rem 0;\n}\n\n.custom-file-control:lang(en)::before {\n  content: \"Browse\";\n}\n\n.nav {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-wrap: wrap;\n      flex-wrap: wrap;\n  padding-left: 0;\n  margin-bottom: 0;\n  list-style: none;\n}\n\n.nav-link {\n  display: block;\n  padding: 0.5rem 1rem;\n}\n\n.nav-link:focus, .nav-link:hover {\n  text-decoration: none;\n}\n\n.nav-link.disabled {\n  color: #868e96;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n\n.nav-tabs .nav-item {\n  margin-bottom: -1px;\n}\n\n.nav-tabs .nav-link {\n  border: 1px solid transparent;\n  border-top-left-radius: 0.25rem;\n  border-top-right-radius: 0.25rem;\n}\n\n.nav-tabs .nav-link:focus, .nav-tabs .nav-link:hover {\n  border-color: #e9ecef #e9ecef #ddd;\n}\n\n.nav-tabs .nav-link.disabled {\n  color: #868e96;\n  background-color: transparent;\n  border-color: transparent;\n}\n\n.nav-tabs .nav-link.active,\n.nav-tabs .nav-item.show .nav-link {\n  color: #495057;\n  background-color: #fff;\n  border-color: #ddd #ddd #fff;\n}\n\n.nav-tabs .dropdown-menu {\n  margin-top: -1px;\n  border-top-left-radius: 0;\n  border-top-right-radius: 0;\n}\n\n.nav-pills .nav-link {\n  border-radius: 0.25rem;\n}\n\n.nav-pills .nav-link.active,\n.nav-pills .show > .nav-link {\n  color: #fff;\n  background-color: #007bff;\n}\n\n.nav-fill .nav-item {\n  -ms-flex: 1 1 auto;\n      flex: 1 1 auto;\n  text-align: center;\n}\n\n.nav-justified .nav-item {\n  -ms-flex-preferred-size: 0;\n      flex-basis: 0;\n  -ms-flex-positive: 1;\n      flex-grow: 1;\n  text-align: center;\n}\n\n.tab-content > .tab-pane {\n  display: none;\n}\n\n.tab-content > .active {\n  display: block;\n}\n\n.navbar {\n  position: relative;\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-wrap: wrap;\n      flex-wrap: wrap;\n  -ms-flex-align: center;\n      align-items: center;\n  -ms-flex-pack: justify;\n      justify-content: space-between;\n  padding: 0.5rem 1rem;\n}\n\n.navbar > .container,\n.navbar > .container-fluid {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-wrap: wrap;\n      flex-wrap: wrap;\n  -ms-flex-align: center;\n      align-items: center;\n  -ms-flex-pack: justify;\n      justify-content: space-between;\n}\n\n.navbar-brand {\n  display: inline-block;\n  padding-top: 0.3125rem;\n  padding-bottom: 0.3125rem;\n  margin-right: 1rem;\n  font-size: 1.25rem;\n  line-height: inherit;\n  white-space: nowrap;\n}\n\n.navbar-brand:focus, .navbar-brand:hover {\n  text-decoration: none;\n}\n\n.navbar-nav {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-direction: column;\n      flex-direction: column;\n  padding-left: 0;\n  margin-bottom: 0;\n  list-style: none;\n}\n\n.navbar-nav .nav-link {\n  padding-right: 0;\n  padding-left: 0;\n}\n\n.navbar-nav .dropdown-menu {\n  position: static;\n  float: none;\n}\n\n.navbar-text {\n  display: inline-block;\n  padding-top: 0.5rem;\n  padding-bottom: 0.5rem;\n}\n\n.navbar-collapse {\n  -ms-flex-preferred-size: 100%;\n      flex-basis: 100%;\n  -ms-flex-positive: 1;\n      flex-grow: 1;\n  -ms-flex-align: center;\n      align-items: center;\n}\n\n.navbar-toggler {\n  padding: 0.25rem 0.75rem;\n  font-size: 1.25rem;\n  line-height: 1;\n  background: transparent;\n  border: 1px solid transparent;\n  border-radius: 0.25rem;\n}\n\n.navbar-toggler:focus, .navbar-toggler:hover {\n  text-decoration: none;\n}\n\n.navbar-toggler-icon {\n  display: inline-block;\n  width: 1.5em;\n  height: 1.5em;\n  vertical-align: middle;\n  content: \"\";\n  background: no-repeat center center;\n  background-size: 100% 100%;\n}\n\n@media (max-width: 575px) {\n  .navbar-expand-sm > .container,\n  .navbar-expand-sm > .container-fluid {\n    padding-right: 0;\n    padding-left: 0;\n  }\n}\n\n@media (min-width: 576px) {\n  .navbar-expand-sm {\n    -ms-flex-flow: row nowrap;\n        flex-flow: row nowrap;\n    -ms-flex-pack: start;\n        justify-content: flex-start;\n  }\n  .navbar-expand-sm .navbar-nav {\n    -ms-flex-direction: row;\n        flex-direction: row;\n  }\n  .navbar-expand-sm .navbar-nav .dropdown-menu {\n    position: absolute;\n  }\n  .navbar-expand-sm .navbar-nav .dropdown-menu-right {\n    right: 0;\n    left: auto;\n  }\n  .navbar-expand-sm .navbar-nav .nav-link {\n    padding-right: .5rem;\n    padding-left: .5rem;\n  }\n  .navbar-expand-sm > .container,\n  .navbar-expand-sm > .container-fluid {\n    -ms-flex-wrap: nowrap;\n        flex-wrap: nowrap;\n  }\n  .navbar-expand-sm .navbar-collapse {\n    display: -ms-flexbox !important;\n    display: flex !important;\n    -ms-flex-preferred-size: auto;\n        flex-basis: auto;\n  }\n  .navbar-expand-sm .navbar-toggler {\n    display: none;\n  }\n  .navbar-expand-sm .dropup .dropdown-menu {\n    top: auto;\n    bottom: 100%;\n  }\n}\n\n@media (max-width: 767px) {\n  .navbar-expand-md > .container,\n  .navbar-expand-md > .container-fluid {\n    padding-right: 0;\n    padding-left: 0;\n  }\n}\n\n@media (min-width: 768px) {\n  .navbar-expand-md {\n    -ms-flex-flow: row nowrap;\n        flex-flow: row nowrap;\n    -ms-flex-pack: start;\n        justify-content: flex-start;\n  }\n  .navbar-expand-md .navbar-nav {\n    -ms-flex-direction: row;\n        flex-direction: row;\n  }\n  .navbar-expand-md .navbar-nav .dropdown-menu {\n    position: absolute;\n  }\n  .navbar-expand-md .navbar-nav .dropdown-menu-right {\n    right: 0;\n    left: auto;\n  }\n  .navbar-expand-md .navbar-nav .nav-link {\n    padding-right: .5rem;\n    padding-left: .5rem;\n  }\n  .navbar-expand-md > .container,\n  .navbar-expand-md > .container-fluid {\n    -ms-flex-wrap: nowrap;\n        flex-wrap: nowrap;\n  }\n  .navbar-expand-md .navbar-collapse {\n    display: -ms-flexbox !important;\n    display: flex !important;\n    -ms-flex-preferred-size: auto;\n        flex-basis: auto;\n  }\n  .navbar-expand-md .navbar-toggler {\n    display: none;\n  }\n  .navbar-expand-md .dropup .dropdown-menu {\n    top: auto;\n    bottom: 100%;\n  }\n}\n\n@media (max-width: 991px) {\n  .navbar-expand-lg > .container,\n  .navbar-expand-lg > .container-fluid {\n    padding-right: 0;\n    padding-left: 0;\n  }\n}\n\n@media (min-width: 992px) {\n  .navbar-expand-lg {\n    -ms-flex-flow: row nowrap;\n        flex-flow: row nowrap;\n    -ms-flex-pack: start;\n        justify-content: flex-start;\n  }\n  .navbar-expand-lg .navbar-nav {\n    -ms-flex-direction: row;\n        flex-direction: row;\n  }\n  .navbar-expand-lg .navbar-nav .dropdown-menu {\n    position: absolute;\n  }\n  .navbar-expand-lg .navbar-nav .dropdown-menu-right {\n    right: 0;\n    left: auto;\n  }\n  .navbar-expand-lg .navbar-nav .nav-link {\n    padding-right: .5rem;\n    padding-left: .5rem;\n  }\n  .navbar-expand-lg > .container,\n  .navbar-expand-lg > .container-fluid {\n    -ms-flex-wrap: nowrap;\n        flex-wrap: nowrap;\n  }\n  .navbar-expand-lg .navbar-collapse {\n    display: -ms-flexbox !important;\n    display: flex !important;\n    -ms-flex-preferred-size: auto;\n        flex-basis: auto;\n  }\n  .navbar-expand-lg .navbar-toggler {\n    display: none;\n  }\n  .navbar-expand-lg .dropup .dropdown-menu {\n    top: auto;\n    bottom: 100%;\n  }\n}\n\n@media (max-width: 1199px) {\n  .navbar-expand-xl > .container,\n  .navbar-expand-xl > .container-fluid {\n    padding-right: 0;\n    padding-left: 0;\n  }\n}\n\n@media (min-width: 1200px) {\n  .navbar-expand-xl {\n    -ms-flex-flow: row nowrap;\n        flex-flow: row nowrap;\n    -ms-flex-pack: start;\n        justify-content: flex-start;\n  }\n  .navbar-expand-xl .navbar-nav {\n    -ms-flex-direction: row;\n        flex-direction: row;\n  }\n  .navbar-expand-xl .navbar-nav .dropdown-menu {\n    position: absolute;\n  }\n  .navbar-expand-xl .navbar-nav .dropdown-menu-right {\n    right: 0;\n    left: auto;\n  }\n  .navbar-expand-xl .navbar-nav .nav-link {\n    padding-right: .5rem;\n    padding-left: .5rem;\n  }\n  .navbar-expand-xl > .container,\n  .navbar-expand-xl > .container-fluid {\n    -ms-flex-wrap: nowrap;\n        flex-wrap: nowrap;\n  }\n  .navbar-expand-xl .navbar-collapse {\n    display: -ms-flexbox !important;\n    display: flex !important;\n    -ms-flex-preferred-size: auto;\n        flex-basis: auto;\n  }\n  .navbar-expand-xl .navbar-toggler {\n    display: none;\n  }\n  .navbar-expand-xl .dropup .dropdown-menu {\n    top: auto;\n    bottom: 100%;\n  }\n}\n\n.navbar-expand {\n  -ms-flex-flow: row nowrap;\n      flex-flow: row nowrap;\n  -ms-flex-pack: start;\n      justify-content: flex-start;\n}\n\n.navbar-expand > .container,\n.navbar-expand > .container-fluid {\n  padding-right: 0;\n  padding-left: 0;\n}\n\n.navbar-expand .navbar-nav {\n  -ms-flex-direction: row;\n      flex-direction: row;\n}\n\n.navbar-expand .navbar-nav .dropdown-menu {\n  position: absolute;\n}\n\n.navbar-expand .navbar-nav .dropdown-menu-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar-expand .navbar-nav .nav-link {\n  padding-right: .5rem;\n  padding-left: .5rem;\n}\n\n.navbar-expand > .container,\n.navbar-expand > .container-fluid {\n  -ms-flex-wrap: nowrap;\n      flex-wrap: nowrap;\n}\n\n.navbar-expand .navbar-collapse {\n  display: -ms-flexbox !important;\n  display: flex !important;\n  -ms-flex-preferred-size: auto;\n      flex-basis: auto;\n}\n\n.navbar-expand .navbar-toggler {\n  display: none;\n}\n\n.navbar-expand .dropup .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n}\n\n.navbar-light .navbar-brand {\n  color: rgba(0, 0, 0, 0.9);\n}\n\n.navbar-light .navbar-brand:focus, .navbar-light .navbar-brand:hover {\n  color: rgba(0, 0, 0, 0.9);\n}\n\n.navbar-light .navbar-nav .nav-link {\n  color: rgba(0, 0, 0, 0.5);\n}\n\n.navbar-light .navbar-nav .nav-link:focus, .navbar-light .navbar-nav .nav-link:hover {\n  color: rgba(0, 0, 0, 0.7);\n}\n\n.navbar-light .navbar-nav .nav-link.disabled {\n  color: rgba(0, 0, 0, 0.3);\n}\n\n.navbar-light .navbar-nav .show > .nav-link,\n.navbar-light .navbar-nav .active > .nav-link,\n.navbar-light .navbar-nav .nav-link.show,\n.navbar-light .navbar-nav .nav-link.active {\n  color: rgba(0, 0, 0, 0.9);\n}\n\n.navbar-light .navbar-toggler {\n  color: rgba(0, 0, 0, 0.5);\n  border-color: rgba(0, 0, 0, 0.1);\n}\n\n.navbar-light .navbar-toggler-icon {\n  background-image: url(\"data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(0, 0, 0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E\");\n}\n\n.navbar-light .navbar-text {\n  color: rgba(0, 0, 0, 0.5);\n}\n\n.navbar-light .navbar-text a {\n  color: rgba(0, 0, 0, 0.9);\n}\n\n.navbar-light .navbar-text a:focus, .navbar-light .navbar-text a:hover {\n  color: rgba(0, 0, 0, 0.9);\n}\n\n.navbar-dark .navbar-brand {\n  color: #fff;\n}\n\n.navbar-dark .navbar-brand:focus, .navbar-dark .navbar-brand:hover {\n  color: #fff;\n}\n\n.navbar-dark .navbar-nav .nav-link {\n  color: rgba(255, 255, 255, 0.5);\n}\n\n.navbar-dark .navbar-nav .nav-link:focus, .navbar-dark .navbar-nav .nav-link:hover {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.navbar-dark .navbar-nav .nav-link.disabled {\n  color: rgba(255, 255, 255, 0.25);\n}\n\n.navbar-dark .navbar-nav .show > .nav-link,\n.navbar-dark .navbar-nav .active > .nav-link,\n.navbar-dark .navbar-nav .nav-link.show,\n.navbar-dark .navbar-nav .nav-link.active {\n  color: #fff;\n}\n\n.navbar-dark .navbar-toggler {\n  color: rgba(255, 255, 255, 0.5);\n  border-color: rgba(255, 255, 255, 0.1);\n}\n\n.navbar-dark .navbar-toggler-icon {\n  background-image: url(\"data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E\");\n}\n\n.navbar-dark .navbar-text {\n  color: rgba(255, 255, 255, 0.5);\n}\n\n.navbar-dark .navbar-text a {\n  color: #fff;\n}\n\n.navbar-dark .navbar-text a:focus, .navbar-dark .navbar-text a:hover {\n  color: #fff;\n}\n\n.card {\n  position: relative;\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-direction: column;\n      flex-direction: column;\n  min-width: 0;\n  word-wrap: break-word;\n  background-color: #fff;\n  background-clip: border-box;\n  border: 1px solid rgba(0, 0, 0, 0.125);\n  border-radius: 0.25rem;\n}\n\n.card > hr {\n  margin-right: 0;\n  margin-left: 0;\n}\n\n.card > .list-group:first-child .list-group-item:first-child {\n  border-top-left-radius: 0.25rem;\n  border-top-right-radius: 0.25rem;\n}\n\n.card > .list-group:last-child .list-group-item:last-child {\n  border-bottom-right-radius: 0.25rem;\n  border-bottom-left-radius: 0.25rem;\n}\n\n.card-body {\n  -ms-flex: 1 1 auto;\n      flex: 1 1 auto;\n  padding: 1.25rem;\n}\n\n.card-title {\n  margin-bottom: 0.75rem;\n}\n\n.card-subtitle {\n  margin-top: -0.375rem;\n  margin-bottom: 0;\n}\n\n.card-text:last-child {\n  margin-bottom: 0;\n}\n\n.card-link:hover {\n  text-decoration: none;\n}\n\n.card-link + .card-link {\n  margin-left: 1.25rem;\n}\n\n.card-header {\n  padding: 0.75rem 1.25rem;\n  margin-bottom: 0;\n  background-color: rgba(0, 0, 0, 0.03);\n  border-bottom: 1px solid rgba(0, 0, 0, 0.125);\n}\n\n.card-header:first-child {\n  border-radius: calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0;\n}\n\n.card-header + .list-group .list-group-item:first-child {\n  border-top: 0;\n}\n\n.card-footer {\n  padding: 0.75rem 1.25rem;\n  background-color: rgba(0, 0, 0, 0.03);\n  border-top: 1px solid rgba(0, 0, 0, 0.125);\n}\n\n.card-footer:last-child {\n  border-radius: 0 0 calc(0.25rem - 1px) calc(0.25rem - 1px);\n}\n\n.card-header-tabs {\n  margin-right: -0.625rem;\n  margin-bottom: -0.75rem;\n  margin-left: -0.625rem;\n  border-bottom: 0;\n}\n\n.card-header-pills {\n  margin-right: -0.625rem;\n  margin-left: -0.625rem;\n}\n\n.card-img-overlay {\n  position: absolute;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 1.25rem;\n}\n\n.card-img {\n  width: 100%;\n  border-radius: calc(0.25rem - 1px);\n}\n\n.card-img-top {\n  width: 100%;\n  border-top-left-radius: calc(0.25rem - 1px);\n  border-top-right-radius: calc(0.25rem - 1px);\n}\n\n.card-img-bottom {\n  width: 100%;\n  border-bottom-right-radius: calc(0.25rem - 1px);\n  border-bottom-left-radius: calc(0.25rem - 1px);\n}\n\n.card-deck {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-direction: column;\n      flex-direction: column;\n}\n\n.card-deck .card {\n  margin-bottom: 15px;\n}\n\n@media (min-width: 576px) {\n  .card-deck {\n    -ms-flex-flow: row wrap;\n        flex-flow: row wrap;\n    margin-right: -15px;\n    margin-left: -15px;\n  }\n  .card-deck .card {\n    display: -ms-flexbox;\n    display: flex;\n    -ms-flex: 1 0 0%;\n        flex: 1 0 0%;\n    -ms-flex-direction: column;\n        flex-direction: column;\n    margin-right: 15px;\n    margin-bottom: 0;\n    margin-left: 15px;\n  }\n}\n\n.card-group {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-direction: column;\n      flex-direction: column;\n}\n\n.card-group .card {\n  margin-bottom: 15px;\n}\n\n@media (min-width: 576px) {\n  .card-group {\n    -ms-flex-flow: row wrap;\n        flex-flow: row wrap;\n  }\n  .card-group .card {\n    -ms-flex: 1 0 0%;\n        flex: 1 0 0%;\n    margin-bottom: 0;\n  }\n  .card-group .card + .card {\n    margin-left: 0;\n    border-left: 0;\n  }\n  .card-group .card:first-child {\n    border-top-right-radius: 0;\n    border-bottom-right-radius: 0;\n  }\n  .card-group .card:first-child .card-img-top {\n    border-top-right-radius: 0;\n  }\n  .card-group .card:first-child .card-img-bottom {\n    border-bottom-right-radius: 0;\n  }\n  .card-group .card:last-child {\n    border-top-left-radius: 0;\n    border-bottom-left-radius: 0;\n  }\n  .card-group .card:last-child .card-img-top {\n    border-top-left-radius: 0;\n  }\n  .card-group .card:last-child .card-img-bottom {\n    border-bottom-left-radius: 0;\n  }\n  .card-group .card:only-child {\n    border-radius: 0.25rem;\n  }\n  .card-group .card:only-child .card-img-top {\n    border-top-left-radius: 0.25rem;\n    border-top-right-radius: 0.25rem;\n  }\n  .card-group .card:only-child .card-img-bottom {\n    border-bottom-right-radius: 0.25rem;\n    border-bottom-left-radius: 0.25rem;\n  }\n  .card-group .card:not(:first-child):not(:last-child):not(:only-child) {\n    border-radius: 0;\n  }\n  .card-group .card:not(:first-child):not(:last-child):not(:only-child) .card-img-top,\n  .card-group .card:not(:first-child):not(:last-child):not(:only-child) .card-img-bottom {\n    border-radius: 0;\n  }\n}\n\n.card-columns .card {\n  margin-bottom: 0.75rem;\n}\n\n@media (min-width: 576px) {\n  .card-columns {\n    -webkit-column-count: 3;\n            column-count: 3;\n    -webkit-column-gap: 1.25rem;\n            column-gap: 1.25rem;\n  }\n  .card-columns .card {\n    display: inline-block;\n    width: 100%;\n  }\n}\n\n.breadcrumb {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-wrap: wrap;\n      flex-wrap: wrap;\n  padding: 0.75rem 1rem;\n  margin-bottom: 1rem;\n  list-style: none;\n  background-color: #e9ecef;\n  border-radius: 0.25rem;\n}\n\n.breadcrumb-item + .breadcrumb-item::before {\n  display: inline-block;\n  padding-right: 0.5rem;\n  padding-left: 0.5rem;\n  color: #868e96;\n  content: \"/\";\n}\n\n.breadcrumb-item + .breadcrumb-item:hover::before {\n  text-decoration: underline;\n}\n\n.breadcrumb-item + .breadcrumb-item:hover::before {\n  text-decoration: none;\n}\n\n.breadcrumb-item.active {\n  color: #868e96;\n}\n\n.pagination {\n  display: -ms-flexbox;\n  display: flex;\n  padding-left: 0;\n  list-style: none;\n  border-radius: 0.25rem;\n}\n\n.page-item:first-child .page-link {\n  margin-left: 0;\n  border-top-left-radius: 0.25rem;\n  border-bottom-left-radius: 0.25rem;\n}\n\n.page-item:last-child .page-link {\n  border-top-right-radius: 0.25rem;\n  border-bottom-right-radius: 0.25rem;\n}\n\n.page-item.active .page-link {\n  z-index: 2;\n  color: #fff;\n  background-color: #007bff;\n  border-color: #007bff;\n}\n\n.page-item.disabled .page-link {\n  color: #868e96;\n  pointer-events: none;\n  background-color: #fff;\n  border-color: #ddd;\n}\n\n.page-link {\n  position: relative;\n  display: block;\n  padding: 0.5rem 0.75rem;\n  margin-left: -1px;\n  line-height: 1.25;\n  color: #007bff;\n  background-color: #fff;\n  border: 1px solid #ddd;\n}\n\n.page-link:focus, .page-link:hover {\n  color: #0056b3;\n  text-decoration: none;\n  background-color: #e9ecef;\n  border-color: #ddd;\n}\n\n.pagination-lg .page-link {\n  padding: 0.75rem 1.5rem;\n  font-size: 1.25rem;\n  line-height: 1.5;\n}\n\n.pagination-lg .page-item:first-child .page-link {\n  border-top-left-radius: 0.3rem;\n  border-bottom-left-radius: 0.3rem;\n}\n\n.pagination-lg .page-item:last-child .page-link {\n  border-top-right-radius: 0.3rem;\n  border-bottom-right-radius: 0.3rem;\n}\n\n.pagination-sm .page-link {\n  padding: 0.25rem 0.5rem;\n  font-size: 0.875rem;\n  line-height: 1.5;\n}\n\n.pagination-sm .page-item:first-child .page-link {\n  border-top-left-radius: 0.2rem;\n  border-bottom-left-radius: 0.2rem;\n}\n\n.pagination-sm .page-item:last-child .page-link {\n  border-top-right-radius: 0.2rem;\n  border-bottom-right-radius: 0.2rem;\n}\n\n.badge {\n  display: inline-block;\n  padding: 0.25em 0.4em;\n  font-size: 75%;\n  font-weight: 700;\n  line-height: 1;\n  text-align: center;\n  white-space: nowrap;\n  vertical-align: baseline;\n  border-radius: 0.25rem;\n}\n\n.badge:empty {\n  display: none;\n}\n\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.badge-pill {\n  padding-right: 0.6em;\n  padding-left: 0.6em;\n  border-radius: 10rem;\n}\n\n.badge-primary {\n  color: #fff;\n  background-color: #007bff;\n}\n\n.badge-primary[href]:focus, .badge-primary[href]:hover {\n  color: #fff;\n  text-decoration: none;\n  background-color: #0062cc;\n}\n\n.badge-secondary {\n  color: #fff;\n  background-color: #868e96;\n}\n\n.badge-secondary[href]:focus, .badge-secondary[href]:hover {\n  color: #fff;\n  text-decoration: none;\n  background-color: #6c757d;\n}\n\n.badge-success {\n  color: #fff;\n  background-color: #28a745;\n}\n\n.badge-success[href]:focus, .badge-success[href]:hover {\n  color: #fff;\n  text-decoration: none;\n  background-color: #1e7e34;\n}\n\n.badge-info {\n  color: #fff;\n  background-color: #17a2b8;\n}\n\n.badge-info[href]:focus, .badge-info[href]:hover {\n  color: #fff;\n  text-decoration: none;\n  background-color: #117a8b;\n}\n\n.badge-warning {\n  color: #111;\n  background-color: #ffc107;\n}\n\n.badge-warning[href]:focus, .badge-warning[href]:hover {\n  color: #111;\n  text-decoration: none;\n  background-color: #d39e00;\n}\n\n.badge-danger {\n  color: #fff;\n  background-color: #dc3545;\n}\n\n.badge-danger[href]:focus, .badge-danger[href]:hover {\n  color: #fff;\n  text-decoration: none;\n  background-color: #bd2130;\n}\n\n.badge-light {\n  color: #111;\n  background-color: #f8f9fa;\n}\n\n.badge-light[href]:focus, .badge-light[href]:hover {\n  color: #111;\n  text-decoration: none;\n  background-color: #dae0e5;\n}\n\n.badge-dark {\n  color: #fff;\n  background-color: #343a40;\n}\n\n.badge-dark[href]:focus, .badge-dark[href]:hover {\n  color: #fff;\n  text-decoration: none;\n  background-color: #1d2124;\n}\n\n.jumbotron {\n  padding: 2rem 1rem;\n  margin-bottom: 2rem;\n  background-color: #e9ecef;\n  border-radius: 0.3rem;\n}\n\n@media (min-width: 576px) {\n  .jumbotron {\n    padding: 4rem 2rem;\n  }\n}\n\n.jumbotron-fluid {\n  padding-right: 0;\n  padding-left: 0;\n  border-radius: 0;\n}\n\n.alert {\n  position: relative;\n  padding: 0.75rem 1.25rem;\n  margin-bottom: 1rem;\n  border: 1px solid transparent;\n  border-radius: 0.25rem;\n}\n\n.alert-heading {\n  color: inherit;\n}\n\n.alert-link {\n  font-weight: 700;\n}\n\n.alert-dismissible .close {\n  position: absolute;\n  top: 0;\n  right: 0;\n  padding: 0.75rem 1.25rem;\n  color: inherit;\n}\n\n.alert-primary {\n  color: #004085;\n  background-color: #cce5ff;\n  border-color: #b8daff;\n}\n\n.alert-primary hr {\n  border-top-color: #9fcdff;\n}\n\n.alert-primary .alert-link {\n  color: #002752;\n}\n\n.alert-secondary {\n  color: #464a4e;\n  background-color: #e7e8ea;\n  border-color: #dddfe2;\n}\n\n.alert-secondary hr {\n  border-top-color: #cfd2d6;\n}\n\n.alert-secondary .alert-link {\n  color: #2e3133;\n}\n\n.alert-success {\n  color: #155724;\n  background-color: #d4edda;\n  border-color: #c3e6cb;\n}\n\n.alert-success hr {\n  border-top-color: #b1dfbb;\n}\n\n.alert-success .alert-link {\n  color: #0b2e13;\n}\n\n.alert-info {\n  color: #0c5460;\n  background-color: #d1ecf1;\n  border-color: #bee5eb;\n}\n\n.alert-info hr {\n  border-top-color: #abdde5;\n}\n\n.alert-info .alert-link {\n  color: #062c33;\n}\n\n.alert-warning {\n  color: #856404;\n  background-color: #fff3cd;\n  border-color: #ffeeba;\n}\n\n.alert-warning hr {\n  border-top-color: #ffe8a1;\n}\n\n.alert-warning .alert-link {\n  color: #533f03;\n}\n\n.alert-danger {\n  color: #721c24;\n  background-color: #f8d7da;\n  border-color: #f5c6cb;\n}\n\n.alert-danger hr {\n  border-top-color: #f1b0b7;\n}\n\n.alert-danger .alert-link {\n  color: #491217;\n}\n\n.alert-light {\n  color: #818182;\n  background-color: #fefefe;\n  border-color: #fdfdfe;\n}\n\n.alert-light hr {\n  border-top-color: #ececf6;\n}\n\n.alert-light .alert-link {\n  color: #686868;\n}\n\n.alert-dark {\n  color: #1b1e21;\n  background-color: #d6d8d9;\n  border-color: #c6c8ca;\n}\n\n.alert-dark hr {\n  border-top-color: #b9bbbe;\n}\n\n.alert-dark .alert-link {\n  color: #040505;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 1rem 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 1rem 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  display: -ms-flexbox;\n  display: flex;\n  height: 1rem;\n  overflow: hidden;\n  font-size: 0.75rem;\n  background-color: #e9ecef;\n  border-radius: 0.25rem;\n}\n\n.progress-bar {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-align: center;\n      align-items: center;\n  -ms-flex-pack: center;\n      justify-content: center;\n  color: #fff;\n  background-color: #007bff;\n}\n\n.progress-bar-striped {\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: 1rem 1rem;\n}\n\n.progress-bar-animated {\n  -webkit-animation: progress-bar-stripes 1s linear infinite;\n          animation: progress-bar-stripes 1s linear infinite;\n}\n\n.media {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-align: start;\n      align-items: flex-start;\n}\n\n.media-body {\n  -ms-flex: 1;\n      flex: 1;\n}\n\n.list-group {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-direction: column;\n      flex-direction: column;\n  padding-left: 0;\n  margin-bottom: 0;\n}\n\n.list-group-item-action {\n  width: 100%;\n  color: #495057;\n  text-align: inherit;\n}\n\n.list-group-item-action:focus, .list-group-item-action:hover {\n  color: #495057;\n  text-decoration: none;\n  background-color: #f8f9fa;\n}\n\n.list-group-item-action:active {\n  color: #212529;\n  background-color: #e9ecef;\n}\n\n.list-group-item {\n  position: relative;\n  display: block;\n  padding: 0.75rem 1.25rem;\n  margin-bottom: -1px;\n  background-color: #fff;\n  border: 1px solid rgba(0, 0, 0, 0.125);\n}\n\n.list-group-item:first-child {\n  border-top-left-radius: 0.25rem;\n  border-top-right-radius: 0.25rem;\n}\n\n.list-group-item:last-child {\n  margin-bottom: 0;\n  border-bottom-right-radius: 0.25rem;\n  border-bottom-left-radius: 0.25rem;\n}\n\n.list-group-item:focus, .list-group-item:hover {\n  text-decoration: none;\n}\n\n.list-group-item.disabled, .list-group-item:disabled {\n  color: #868e96;\n  background-color: #fff;\n}\n\n.list-group-item.active {\n  z-index: 2;\n  color: #fff;\n  background-color: #007bff;\n  border-color: #007bff;\n}\n\n.list-group-flush .list-group-item {\n  border-right: 0;\n  border-left: 0;\n  border-radius: 0;\n}\n\n.list-group-flush:first-child .list-group-item:first-child {\n  border-top: 0;\n}\n\n.list-group-flush:last-child .list-group-item:last-child {\n  border-bottom: 0;\n}\n\n.list-group-item-primary {\n  color: #004085;\n  background-color: #b8daff;\n}\n\na.list-group-item-primary,\nbutton.list-group-item-primary {\n  color: #004085;\n}\n\na.list-group-item-primary:focus, a.list-group-item-primary:hover,\nbutton.list-group-item-primary:focus,\nbutton.list-group-item-primary:hover {\n  color: #004085;\n  background-color: #9fcdff;\n}\n\na.list-group-item-primary.active,\nbutton.list-group-item-primary.active {\n  color: #fff;\n  background-color: #004085;\n  border-color: #004085;\n}\n\n.list-group-item-secondary {\n  color: #464a4e;\n  background-color: #dddfe2;\n}\n\na.list-group-item-secondary,\nbutton.list-group-item-secondary {\n  color: #464a4e;\n}\n\na.list-group-item-secondary:focus, a.list-group-item-secondary:hover,\nbutton.list-group-item-secondary:focus,\nbutton.list-group-item-secondary:hover {\n  color: #464a4e;\n  background-color: #cfd2d6;\n}\n\na.list-group-item-secondary.active,\nbutton.list-group-item-secondary.active {\n  color: #fff;\n  background-color: #464a4e;\n  border-color: #464a4e;\n}\n\n.list-group-item-success {\n  color: #155724;\n  background-color: #c3e6cb;\n}\n\na.list-group-item-success,\nbutton.list-group-item-success {\n  color: #155724;\n}\n\na.list-group-item-success:focus, a.list-group-item-success:hover,\nbutton.list-group-item-success:focus,\nbutton.list-group-item-success:hover {\n  color: #155724;\n  background-color: #b1dfbb;\n}\n\na.list-group-item-success.active,\nbutton.list-group-item-success.active {\n  color: #fff;\n  background-color: #155724;\n  border-color: #155724;\n}\n\n.list-group-item-info {\n  color: #0c5460;\n  background-color: #bee5eb;\n}\n\na.list-group-item-info,\nbutton.list-group-item-info {\n  color: #0c5460;\n}\n\na.list-group-item-info:focus, a.list-group-item-info:hover,\nbutton.list-group-item-info:focus,\nbutton.list-group-item-info:hover {\n  color: #0c5460;\n  background-color: #abdde5;\n}\n\na.list-group-item-info.active,\nbutton.list-group-item-info.active {\n  color: #fff;\n  background-color: #0c5460;\n  border-color: #0c5460;\n}\n\n.list-group-item-warning {\n  color: #856404;\n  background-color: #ffeeba;\n}\n\na.list-group-item-warning,\nbutton.list-group-item-warning {\n  color: #856404;\n}\n\na.list-group-item-warning:focus, a.list-group-item-warning:hover,\nbutton.list-group-item-warning:focus,\nbutton.list-group-item-warning:hover {\n  color: #856404;\n  background-color: #ffe8a1;\n}\n\na.list-group-item-warning.active,\nbutton.list-group-item-warning.active {\n  color: #fff;\n  background-color: #856404;\n  border-color: #856404;\n}\n\n.list-group-item-danger {\n  color: #721c24;\n  background-color: #f5c6cb;\n}\n\na.list-group-item-danger,\nbutton.list-group-item-danger {\n  color: #721c24;\n}\n\na.list-group-item-danger:focus, a.list-group-item-danger:hover,\nbutton.list-group-item-danger:focus,\nbutton.list-group-item-danger:hover {\n  color: #721c24;\n  background-color: #f1b0b7;\n}\n\na.list-group-item-danger.active,\nbutton.list-group-item-danger.active {\n  color: #fff;\n  background-color: #721c24;\n  border-color: #721c24;\n}\n\n.list-group-item-light {\n  color: #818182;\n  background-color: #fdfdfe;\n}\n\na.list-group-item-light,\nbutton.list-group-item-light {\n  color: #818182;\n}\n\na.list-group-item-light:focus, a.list-group-item-light:hover,\nbutton.list-group-item-light:focus,\nbutton.list-group-item-light:hover {\n  color: #818182;\n  background-color: #ececf6;\n}\n\na.list-group-item-light.active,\nbutton.list-group-item-light.active {\n  color: #fff;\n  background-color: #818182;\n  border-color: #818182;\n}\n\n.list-group-item-dark {\n  color: #1b1e21;\n  background-color: #c6c8ca;\n}\n\na.list-group-item-dark,\nbutton.list-group-item-dark {\n  color: #1b1e21;\n}\n\na.list-group-item-dark:focus, a.list-group-item-dark:hover,\nbutton.list-group-item-dark:focus,\nbutton.list-group-item-dark:hover {\n  color: #1b1e21;\n  background-color: #b9bbbe;\n}\n\na.list-group-item-dark.active,\nbutton.list-group-item-dark.active {\n  color: #fff;\n  background-color: #1b1e21;\n  border-color: #1b1e21;\n}\n\n.close {\n  float: right;\n  font-size: 1.5rem;\n  font-weight: 700;\n  line-height: 1;\n  color: #000;\n  text-shadow: 0 1px 0 #fff;\n  opacity: .5;\n}\n\n.close:focus, .close:hover {\n  color: #000;\n  text-decoration: none;\n  opacity: .75;\n}\n\nbutton.close {\n  padding: 0;\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: 1050;\n  display: none;\n  overflow: hidden;\n  outline: 0;\n}\n\n.modal.fade .modal-dialog {\n  transition: -webkit-transform 0.3s ease-out;\n  transition: transform 0.3s ease-out;\n  transition: transform 0.3s ease-out, -webkit-transform 0.3s ease-out;\n  -webkit-transform: translate(0, -25%);\n          transform: translate(0, -25%);\n}\n\n.modal.show .modal-dialog {\n  -webkit-transform: translate(0, 0);\n          transform: translate(0, 0);\n}\n\n.modal-open .modal {\n  overflow-x: hidden;\n  overflow-y: auto;\n}\n\n.modal-dialog {\n  position: relative;\n  width: auto;\n  margin: 10px;\n  pointer-events: none;\n}\n\n.modal-content {\n  position: relative;\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-direction: column;\n      flex-direction: column;\n  pointer-events: auto;\n  background-color: #fff;\n  background-clip: padding-box;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  border-radius: 0.3rem;\n  outline: 0;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n}\n\n.modal-backdrop.show {\n  opacity: 0.5;\n}\n\n.modal-header {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-align: start;\n      align-items: flex-start;\n  -ms-flex-pack: justify;\n      justify-content: space-between;\n  padding: 15px;\n  border-bottom: 1px solid #e9ecef;\n  border-top-left-radius: 0.3rem;\n  border-top-right-radius: 0.3rem;\n}\n\n.modal-header .close {\n  padding: 15px;\n  margin: -15px -15px -15px auto;\n}\n\n.modal-title {\n  margin-bottom: 0;\n  line-height: 1.5;\n}\n\n.modal-body {\n  position: relative;\n  -ms-flex: 1 1 auto;\n      flex: 1 1 auto;\n  padding: 15px;\n}\n\n.modal-footer {\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-align: center;\n      align-items: center;\n  -ms-flex-pack: end;\n      justify-content: flex-end;\n  padding: 15px;\n  border-top: 1px solid #e9ecef;\n}\n\n.modal-footer > :not(:first-child) {\n  margin-left: .25rem;\n}\n\n.modal-footer > :not(:last-child) {\n  margin-right: .25rem;\n}\n\n.modal-scrollbar-measure {\n  position: absolute;\n  top: -9999px;\n  width: 50px;\n  height: 50px;\n  overflow: scroll;\n}\n\n@media (min-width: 576px) {\n  .modal-dialog {\n    max-width: 500px;\n    margin: 30px auto;\n  }\n  .modal-sm {\n    max-width: 300px;\n  }\n}\n\n@media (min-width: 992px) {\n  .modal-lg {\n    max-width: 800px;\n  }\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1070;\n  display: block;\n  margin: 0;\n  font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";\n  font-style: normal;\n  font-weight: 400;\n  line-height: 1.5;\n  text-align: left;\n  text-align: start;\n  text-decoration: none;\n  text-shadow: none;\n  text-transform: none;\n  letter-spacing: normal;\n  word-break: normal;\n  word-spacing: normal;\n  white-space: normal;\n  line-break: auto;\n  font-size: 0.875rem;\n  word-wrap: break-word;\n  opacity: 0;\n}\n\n.tooltip.show {\n  opacity: 0.9;\n}\n\n.tooltip .arrow {\n  position: absolute;\n  display: block;\n  width: 5px;\n  height: 5px;\n}\n\n.tooltip .arrow::before {\n  position: absolute;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.bs-tooltip-top, .tooltip.bs-tooltip-auto[x-placement^=\"top\"] {\n  padding: 5px 0;\n}\n\n.tooltip.bs-tooltip-top .arrow, .tooltip.bs-tooltip-auto[x-placement^=\"top\"] .arrow {\n  bottom: 0;\n}\n\n.tooltip.bs-tooltip-top .arrow::before, .tooltip.bs-tooltip-auto[x-placement^=\"top\"] .arrow::before {\n  margin-left: -3px;\n  content: \"\";\n  border-width: 5px 5px 0;\n  border-top-color: #000;\n}\n\n.tooltip.bs-tooltip-right, .tooltip.bs-tooltip-auto[x-placement^=\"right\"] {\n  padding: 0 5px;\n}\n\n.tooltip.bs-tooltip-right .arrow, .tooltip.bs-tooltip-auto[x-placement^=\"right\"] .arrow {\n  left: 0;\n}\n\n.tooltip.bs-tooltip-right .arrow::before, .tooltip.bs-tooltip-auto[x-placement^=\"right\"] .arrow::before {\n  margin-top: -3px;\n  content: \"\";\n  border-width: 5px 5px 5px 0;\n  border-right-color: #000;\n}\n\n.tooltip.bs-tooltip-bottom, .tooltip.bs-tooltip-auto[x-placement^=\"bottom\"] {\n  padding: 5px 0;\n}\n\n.tooltip.bs-tooltip-bottom .arrow, .tooltip.bs-tooltip-auto[x-placement^=\"bottom\"] .arrow {\n  top: 0;\n}\n\n.tooltip.bs-tooltip-bottom .arrow::before, .tooltip.bs-tooltip-auto[x-placement^=\"bottom\"] .arrow::before {\n  margin-left: -3px;\n  content: \"\";\n  border-width: 0 5px 5px;\n  border-bottom-color: #000;\n}\n\n.tooltip.bs-tooltip-left, .tooltip.bs-tooltip-auto[x-placement^=\"left\"] {\n  padding: 0 5px;\n}\n\n.tooltip.bs-tooltip-left .arrow, .tooltip.bs-tooltip-auto[x-placement^=\"left\"] .arrow {\n  right: 0;\n}\n\n.tooltip.bs-tooltip-left .arrow::before, .tooltip.bs-tooltip-auto[x-placement^=\"left\"] .arrow::before {\n  right: 0;\n  margin-top: -3px;\n  content: \"\";\n  border-width: 5px 0 5px 5px;\n  border-left-color: #000;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #fff;\n  text-align: center;\n  background-color: #000;\n  border-radius: 0.25rem;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1060;\n  display: block;\n  max-width: 276px;\n  font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";\n  font-style: normal;\n  font-weight: 400;\n  line-height: 1.5;\n  text-align: left;\n  text-align: start;\n  text-decoration: none;\n  text-shadow: none;\n  text-transform: none;\n  letter-spacing: normal;\n  word-break: normal;\n  word-spacing: normal;\n  white-space: normal;\n  line-break: auto;\n  font-size: 0.875rem;\n  word-wrap: break-word;\n  background-color: #fff;\n  background-clip: padding-box;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  border-radius: 0.3rem;\n}\n\n.popover .arrow {\n  position: absolute;\n  display: block;\n  width: 0.8rem;\n  height: 0.4rem;\n}\n\n.popover .arrow::before,\n.popover .arrow::after {\n  position: absolute;\n  display: block;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow::before {\n  content: \"\";\n  border-width: 0.8rem;\n}\n\n.popover .arrow::after {\n  content: \"\";\n  border-width: 0.8rem;\n}\n\n.popover.bs-popover-top, .popover.bs-popover-auto[x-placement^=\"top\"] {\n  margin-bottom: 0.8rem;\n}\n\n.popover.bs-popover-top .arrow, .popover.bs-popover-auto[x-placement^=\"top\"] .arrow {\n  bottom: 0;\n}\n\n.popover.bs-popover-top .arrow::before, .popover.bs-popover-auto[x-placement^=\"top\"] .arrow::before,\n.popover.bs-popover-top .arrow::after, .popover.bs-popover-auto[x-placement^=\"top\"] .arrow::after {\n  border-bottom-width: 0;\n}\n\n.popover.bs-popover-top .arrow::before, .popover.bs-popover-auto[x-placement^=\"top\"] .arrow::before {\n  bottom: -0.8rem;\n  margin-left: -0.8rem;\n  border-top-color: rgba(0, 0, 0, 0.25);\n}\n\n.popover.bs-popover-top .arrow::after, .popover.bs-popover-auto[x-placement^=\"top\"] .arrow::after {\n  bottom: calc((0.8rem - 1px) * -1);\n  margin-left: -0.8rem;\n  border-top-color: #fff;\n}\n\n.popover.bs-popover-right, .popover.bs-popover-auto[x-placement^=\"right\"] {\n  margin-left: 0.8rem;\n}\n\n.popover.bs-popover-right .arrow, .popover.bs-popover-auto[x-placement^=\"right\"] .arrow {\n  left: 0;\n}\n\n.popover.bs-popover-right .arrow::before, .popover.bs-popover-auto[x-placement^=\"right\"] .arrow::before,\n.popover.bs-popover-right .arrow::after, .popover.bs-popover-auto[x-placement^=\"right\"] .arrow::after {\n  margin-top: -0.8rem;\n  border-left-width: 0;\n}\n\n.popover.bs-popover-right .arrow::before, .popover.bs-popover-auto[x-placement^=\"right\"] .arrow::before {\n  left: -0.8rem;\n  border-right-color: rgba(0, 0, 0, 0.25);\n}\n\n.popover.bs-popover-right .arrow::after, .popover.bs-popover-auto[x-placement^=\"right\"] .arrow::after {\n  left: calc((0.8rem - 1px) * -1);\n  border-right-color: #fff;\n}\n\n.popover.bs-popover-bottom, .popover.bs-popover-auto[x-placement^=\"bottom\"] {\n  margin-top: 0.8rem;\n}\n\n.popover.bs-popover-bottom .arrow, .popover.bs-popover-auto[x-placement^=\"bottom\"] .arrow {\n  top: 0;\n}\n\n.popover.bs-popover-bottom .arrow::before, .popover.bs-popover-auto[x-placement^=\"bottom\"] .arrow::before,\n.popover.bs-popover-bottom .arrow::after, .popover.bs-popover-auto[x-placement^=\"bottom\"] .arrow::after {\n  margin-left: -0.8rem;\n  border-top-width: 0;\n}\n\n.popover.bs-popover-bottom .arrow::before, .popover.bs-popover-auto[x-placement^=\"bottom\"] .arrow::before {\n  top: -0.8rem;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n}\n\n.popover.bs-popover-bottom .arrow::after, .popover.bs-popover-auto[x-placement^=\"bottom\"] .arrow::after {\n  top: calc((0.8rem - 1px) * -1);\n  border-bottom-color: #fff;\n}\n\n.popover.bs-popover-bottom .popover-header::before, .popover.bs-popover-auto[x-placement^=\"bottom\"] .popover-header::before {\n  position: absolute;\n  top: 0;\n  left: 50%;\n  display: block;\n  width: 20px;\n  margin-left: -10px;\n  content: \"\";\n  border-bottom: 1px solid #f7f7f7;\n}\n\n.popover.bs-popover-left, .popover.bs-popover-auto[x-placement^=\"left\"] {\n  margin-right: 0.8rem;\n}\n\n.popover.bs-popover-left .arrow, .popover.bs-popover-auto[x-placement^=\"left\"] .arrow {\n  right: 0;\n}\n\n.popover.bs-popover-left .arrow::before, .popover.bs-popover-auto[x-placement^=\"left\"] .arrow::before,\n.popover.bs-popover-left .arrow::after, .popover.bs-popover-auto[x-placement^=\"left\"] .arrow::after {\n  margin-top: -0.8rem;\n  border-right-width: 0;\n}\n\n.popover.bs-popover-left .arrow::before, .popover.bs-popover-auto[x-placement^=\"left\"] .arrow::before {\n  right: -0.8rem;\n  border-left-color: rgba(0, 0, 0, 0.25);\n}\n\n.popover.bs-popover-left .arrow::after, .popover.bs-popover-auto[x-placement^=\"left\"] .arrow::after {\n  right: calc((0.8rem - 1px) * -1);\n  border-left-color: #fff;\n}\n\n.popover-header {\n  padding: 0.5rem 0.75rem;\n  margin-bottom: 0;\n  font-size: 1rem;\n  color: inherit;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  border-top-left-radius: calc(0.3rem - 1px);\n  border-top-right-radius: calc(0.3rem - 1px);\n}\n\n.popover-header:empty {\n  display: none;\n}\n\n.popover-body {\n  padding: 0.5rem 0.75rem;\n  color: #212529;\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-item {\n  position: relative;\n  display: none;\n  -ms-flex-align: center;\n      align-items: center;\n  width: 100%;\n  transition: -webkit-transform 0.6s ease;\n  transition: transform 0.6s ease;\n  transition: transform 0.6s ease, -webkit-transform 0.6s ease;\n  -webkit-backface-visibility: hidden;\n          backface-visibility: hidden;\n  -webkit-perspective: 1000px;\n          perspective: 1000px;\n}\n\n.carousel-item.active,\n.carousel-item-next,\n.carousel-item-prev {\n  display: block;\n}\n\n.carousel-item-next,\n.carousel-item-prev {\n  position: absolute;\n  top: 0;\n}\n\n.carousel-item-next.carousel-item-left,\n.carousel-item-prev.carousel-item-right {\n  -webkit-transform: translateX(0);\n          transform: translateX(0);\n}\n\n@supports ((-webkit-transform-style: preserve-3d) or (transform-style: preserve-3d)) {\n  .carousel-item-next.carousel-item-left,\n  .carousel-item-prev.carousel-item-right {\n    -webkit-transform: translate3d(0, 0, 0);\n            transform: translate3d(0, 0, 0);\n  }\n}\n\n.carousel-item-next,\n.active.carousel-item-right {\n  -webkit-transform: translateX(100%);\n          transform: translateX(100%);\n}\n\n@supports ((-webkit-transform-style: preserve-3d) or (transform-style: preserve-3d)) {\n  .carousel-item-next,\n  .active.carousel-item-right {\n    -webkit-transform: translate3d(100%, 0, 0);\n            transform: translate3d(100%, 0, 0);\n  }\n}\n\n.carousel-item-prev,\n.active.carousel-item-left {\n  -webkit-transform: translateX(-100%);\n          transform: translateX(-100%);\n}\n\n@supports ((-webkit-transform-style: preserve-3d) or (transform-style: preserve-3d)) {\n  .carousel-item-prev,\n  .active.carousel-item-left {\n    -webkit-transform: translate3d(-100%, 0, 0);\n            transform: translate3d(-100%, 0, 0);\n  }\n}\n\n.carousel-control-prev,\n.carousel-control-next {\n  position: absolute;\n  top: 0;\n  bottom: 0;\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-align: center;\n      align-items: center;\n  -ms-flex-pack: center;\n      justify-content: center;\n  width: 15%;\n  color: #fff;\n  text-align: center;\n  opacity: 0.5;\n}\n\n.carousel-control-prev:focus, .carousel-control-prev:hover,\n.carousel-control-next:focus,\n.carousel-control-next:hover {\n  color: #fff;\n  text-decoration: none;\n  outline: 0;\n  opacity: .9;\n}\n\n.carousel-control-prev {\n  left: 0;\n}\n\n.carousel-control-next {\n  right: 0;\n}\n\n.carousel-control-prev-icon,\n.carousel-control-next-icon {\n  display: inline-block;\n  width: 20px;\n  height: 20px;\n  background: transparent no-repeat center center;\n  background-size: 100% 100%;\n}\n\n.carousel-control-prev-icon {\n  background-image: url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E\");\n}\n\n.carousel-control-next-icon {\n  background-image: url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3E%3C/svg%3E\");\n}\n\n.carousel-indicators {\n  position: absolute;\n  right: 0;\n  bottom: 10px;\n  left: 0;\n  z-index: 15;\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-pack: center;\n      justify-content: center;\n  padding-left: 0;\n  margin-right: 15%;\n  margin-left: 15%;\n  list-style: none;\n}\n\n.carousel-indicators li {\n  position: relative;\n  -ms-flex: 0 1 auto;\n      flex: 0 1 auto;\n  width: 30px;\n  height: 3px;\n  margin-right: 3px;\n  margin-left: 3px;\n  text-indent: -999px;\n  background-color: rgba(255, 255, 255, 0.5);\n}\n\n.carousel-indicators li::before {\n  position: absolute;\n  top: -10px;\n  left: 0;\n  display: inline-block;\n  width: 100%;\n  height: 10px;\n  content: \"\";\n}\n\n.carousel-indicators li::after {\n  position: absolute;\n  bottom: -10px;\n  left: 0;\n  display: inline-block;\n  width: 100%;\n  height: 10px;\n  content: \"\";\n}\n\n.carousel-indicators .active {\n  background-color: #fff;\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: #fff;\n  text-align: center;\n}\n\n.align-baseline {\n  vertical-align: baseline !important;\n}\n\n.align-top {\n  vertical-align: top !important;\n}\n\n.align-middle {\n  vertical-align: middle !important;\n}\n\n.align-bottom {\n  vertical-align: bottom !important;\n}\n\n.align-text-bottom {\n  vertical-align: text-bottom !important;\n}\n\n.align-text-top {\n  vertical-align: text-top !important;\n}\n\n.bg-primary {\n  background-color: #007bff !important;\n}\n\na.bg-primary:focus, a.bg-primary:hover {\n  background-color: #0062cc !important;\n}\n\n.bg-secondary {\n  background-color: #868e96 !important;\n}\n\na.bg-secondary:focus, a.bg-secondary:hover {\n  background-color: #6c757d !important;\n}\n\n.bg-success {\n  background-color: #28a745 !important;\n}\n\na.bg-success:focus, a.bg-success:hover {\n  background-color: #1e7e34 !important;\n}\n\n.bg-info {\n  background-color: #17a2b8 !important;\n}\n\na.bg-info:focus, a.bg-info:hover {\n  background-color: #117a8b !important;\n}\n\n.bg-warning {\n  background-color: #ffc107 !important;\n}\n\na.bg-warning:focus, a.bg-warning:hover {\n  background-color: #d39e00 !important;\n}\n\n.bg-danger {\n  background-color: #dc3545 !important;\n}\n\na.bg-danger:focus, a.bg-danger:hover {\n  background-color: #bd2130 !important;\n}\n\n.bg-light {\n  background-color: #f8f9fa !important;\n}\n\na.bg-light:focus, a.bg-light:hover {\n  background-color: #dae0e5 !important;\n}\n\n.bg-dark {\n  background-color: #343a40 !important;\n}\n\na.bg-dark:focus, a.bg-dark:hover {\n  background-color: #1d2124 !important;\n}\n\n.bg-white {\n  background-color: #fff !important;\n}\n\n.bg-transparent {\n  background-color: transparent !important;\n}\n\n.border {\n  border: 1px solid #e9ecef !important;\n}\n\n.border-0 {\n  border: 0 !important;\n}\n\n.border-top-0 {\n  border-top: 0 !important;\n}\n\n.border-right-0 {\n  border-right: 0 !important;\n}\n\n.border-bottom-0 {\n  border-bottom: 0 !important;\n}\n\n.border-left-0 {\n  border-left: 0 !important;\n}\n\n.border-primary {\n  border-color: #007bff !important;\n}\n\n.border-secondary {\n  border-color: #868e96 !important;\n}\n\n.border-success {\n  border-color: #28a745 !important;\n}\n\n.border-info {\n  border-color: #17a2b8 !important;\n}\n\n.border-warning {\n  border-color: #ffc107 !important;\n}\n\n.border-danger {\n  border-color: #dc3545 !important;\n}\n\n.border-light {\n  border-color: #f8f9fa !important;\n}\n\n.border-dark {\n  border-color: #343a40 !important;\n}\n\n.border-white {\n  border-color: #fff !important;\n}\n\n.rounded {\n  border-radius: 0.25rem !important;\n}\n\n.rounded-top {\n  border-top-left-radius: 0.25rem !important;\n  border-top-right-radius: 0.25rem !important;\n}\n\n.rounded-right {\n  border-top-right-radius: 0.25rem !important;\n  border-bottom-right-radius: 0.25rem !important;\n}\n\n.rounded-bottom {\n  border-bottom-right-radius: 0.25rem !important;\n  border-bottom-left-radius: 0.25rem !important;\n}\n\n.rounded-left {\n  border-top-left-radius: 0.25rem !important;\n  border-bottom-left-radius: 0.25rem !important;\n}\n\n.rounded-circle {\n  border-radius: 50% !important;\n}\n\n.rounded-0 {\n  border-radius: 0 !important;\n}\n\n.clearfix::after {\n  display: block;\n  clear: both;\n  content: \"\";\n}\n\n.d-none {\n  display: none !important;\n}\n\n.d-inline {\n  display: inline !important;\n}\n\n.d-inline-block {\n  display: inline-block !important;\n}\n\n.d-block {\n  display: block !important;\n}\n\n.d-table {\n  display: table !important;\n}\n\n.d-table-row {\n  display: table-row !important;\n}\n\n.d-table-cell {\n  display: table-cell !important;\n}\n\n.d-flex {\n  display: -ms-flexbox !important;\n  display: flex !important;\n}\n\n.d-inline-flex {\n  display: -ms-inline-flexbox !important;\n  display: inline-flex !important;\n}\n\n@media (min-width: 576px) {\n  .d-sm-none {\n    display: none !important;\n  }\n  .d-sm-inline {\n    display: inline !important;\n  }\n  .d-sm-inline-block {\n    display: inline-block !important;\n  }\n  .d-sm-block {\n    display: block !important;\n  }\n  .d-sm-table {\n    display: table !important;\n  }\n  .d-sm-table-row {\n    display: table-row !important;\n  }\n  .d-sm-table-cell {\n    display: table-cell !important;\n  }\n  .d-sm-flex {\n    display: -ms-flexbox !important;\n    display: flex !important;\n  }\n  .d-sm-inline-flex {\n    display: -ms-inline-flexbox !important;\n    display: inline-flex !important;\n  }\n}\n\n@media (min-width: 768px) {\n  .d-md-none {\n    display: none !important;\n  }\n  .d-md-inline {\n    display: inline !important;\n  }\n  .d-md-inline-block {\n    display: inline-block !important;\n  }\n  .d-md-block {\n    display: block !important;\n  }\n  .d-md-table {\n    display: table !important;\n  }\n  .d-md-table-row {\n    display: table-row !important;\n  }\n  .d-md-table-cell {\n    display: table-cell !important;\n  }\n  .d-md-flex {\n    display: -ms-flexbox !important;\n    display: flex !important;\n  }\n  .d-md-inline-flex {\n    display: -ms-inline-flexbox !important;\n    display: inline-flex !important;\n  }\n}\n\n@media (min-width: 992px) {\n  .d-lg-none {\n    display: none !important;\n  }\n  .d-lg-inline {\n    display: inline !important;\n  }\n  .d-lg-inline-block {\n    display: inline-block !important;\n  }\n  .d-lg-block {\n    display: block !important;\n  }\n  .d-lg-table {\n    display: table !important;\n  }\n  .d-lg-table-row {\n    display: table-row !important;\n  }\n  .d-lg-table-cell {\n    display: table-cell !important;\n  }\n  .d-lg-flex {\n    display: -ms-flexbox !important;\n    display: flex !important;\n  }\n  .d-lg-inline-flex {\n    display: -ms-inline-flexbox !important;\n    display: inline-flex !important;\n  }\n}\n\n@media (min-width: 1200px) {\n  .d-xl-none {\n    display: none !important;\n  }\n  .d-xl-inline {\n    display: inline !important;\n  }\n  .d-xl-inline-block {\n    display: inline-block !important;\n  }\n  .d-xl-block {\n    display: block !important;\n  }\n  .d-xl-table {\n    display: table !important;\n  }\n  .d-xl-table-row {\n    display: table-row !important;\n  }\n  .d-xl-table-cell {\n    display: table-cell !important;\n  }\n  .d-xl-flex {\n    display: -ms-flexbox !important;\n    display: flex !important;\n  }\n  .d-xl-inline-flex {\n    display: -ms-inline-flexbox !important;\n    display: inline-flex !important;\n  }\n}\n\n.d-print-block {\n  display: none !important;\n}\n\n@media print {\n  .d-print-block {\n    display: block !important;\n  }\n}\n\n.d-print-inline {\n  display: none !important;\n}\n\n@media print {\n  .d-print-inline {\n    display: inline !important;\n  }\n}\n\n.d-print-inline-block {\n  display: none !important;\n}\n\n@media print {\n  .d-print-inline-block {\n    display: inline-block !important;\n  }\n}\n\n@media print {\n  .d-print-none {\n    display: none !important;\n  }\n}\n\n.embed-responsive {\n  position: relative;\n  display: block;\n  width: 100%;\n  padding: 0;\n  overflow: hidden;\n}\n\n.embed-responsive::before {\n  display: block;\n  content: \"\";\n}\n\n.embed-responsive .embed-responsive-item,\n.embed-responsive iframe,\n.embed-responsive embed,\n.embed-responsive object,\n.embed-responsive video {\n  position: absolute;\n  top: 0;\n  bottom: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n  border: 0;\n}\n\n.embed-responsive-21by9::before {\n  padding-top: 42.857143%;\n}\n\n.embed-responsive-16by9::before {\n  padding-top: 56.25%;\n}\n\n.embed-responsive-4by3::before {\n  padding-top: 75%;\n}\n\n.embed-responsive-1by1::before {\n  padding-top: 100%;\n}\n\n.flex-row {\n  -ms-flex-direction: row !important;\n      flex-direction: row !important;\n}\n\n.flex-column {\n  -ms-flex-direction: column !important;\n      flex-direction: column !important;\n}\n\n.flex-row-reverse {\n  -ms-flex-direction: row-reverse !important;\n      flex-direction: row-reverse !important;\n}\n\n.flex-column-reverse {\n  -ms-flex-direction: column-reverse !important;\n      flex-direction: column-reverse !important;\n}\n\n.flex-wrap {\n  -ms-flex-wrap: wrap !important;\n      flex-wrap: wrap !important;\n}\n\n.flex-nowrap {\n  -ms-flex-wrap: nowrap !important;\n      flex-wrap: nowrap !important;\n}\n\n.flex-wrap-reverse {\n  -ms-flex-wrap: wrap-reverse !important;\n      flex-wrap: wrap-reverse !important;\n}\n\n.justify-content-start {\n  -ms-flex-pack: start !important;\n      justify-content: flex-start !important;\n}\n\n.justify-content-end {\n  -ms-flex-pack: end !important;\n      justify-content: flex-end !important;\n}\n\n.justify-content-center {\n  -ms-flex-pack: center !important;\n      justify-content: center !important;\n}\n\n.justify-content-between {\n  -ms-flex-pack: justify !important;\n      justify-content: space-between !important;\n}\n\n.justify-content-around {\n  -ms-flex-pack: distribute !important;\n      justify-content: space-around !important;\n}\n\n.align-items-start {\n  -ms-flex-align: start !important;\n      align-items: flex-start !important;\n}\n\n.align-items-end {\n  -ms-flex-align: end !important;\n      align-items: flex-end !important;\n}\n\n.align-items-center {\n  -ms-flex-align: center !important;\n      align-items: center !important;\n}\n\n.align-items-baseline {\n  -ms-flex-align: baseline !important;\n      align-items: baseline !important;\n}\n\n.align-items-stretch {\n  -ms-flex-align: stretch !important;\n      align-items: stretch !important;\n}\n\n.align-content-start {\n  -ms-flex-line-pack: start !important;\n      align-content: flex-start !important;\n}\n\n.align-content-end {\n  -ms-flex-line-pack: end !important;\n      align-content: flex-end !important;\n}\n\n.align-content-center {\n  -ms-flex-line-pack: center !important;\n      align-content: center !important;\n}\n\n.align-content-between {\n  -ms-flex-line-pack: justify !important;\n      align-content: space-between !important;\n}\n\n.align-content-around {\n  -ms-flex-line-pack: distribute !important;\n      align-content: space-around !important;\n}\n\n.align-content-stretch {\n  -ms-flex-line-pack: stretch !important;\n      align-content: stretch !important;\n}\n\n.align-self-auto {\n  -ms-flex-item-align: auto !important;\n      align-self: auto !important;\n}\n\n.align-self-start {\n  -ms-flex-item-align: start !important;\n      align-self: flex-start !important;\n}\n\n.align-self-end {\n  -ms-flex-item-align: end !important;\n      align-self: flex-end !important;\n}\n\n.align-self-center {\n  -ms-flex-item-align: center !important;\n      align-self: center !important;\n}\n\n.align-self-baseline {\n  -ms-flex-item-align: baseline !important;\n      align-self: baseline !important;\n}\n\n.align-self-stretch {\n  -ms-flex-item-align: stretch !important;\n      align-self: stretch !important;\n}\n\n@media (min-width: 576px) {\n  .flex-sm-row {\n    -ms-flex-direction: row !important;\n        flex-direction: row !important;\n  }\n  .flex-sm-column {\n    -ms-flex-direction: column !important;\n        flex-direction: column !important;\n  }\n  .flex-sm-row-reverse {\n    -ms-flex-direction: row-reverse !important;\n        flex-direction: row-reverse !important;\n  }\n  .flex-sm-column-reverse {\n    -ms-flex-direction: column-reverse !important;\n        flex-direction: column-reverse !important;\n  }\n  .flex-sm-wrap {\n    -ms-flex-wrap: wrap !important;\n        flex-wrap: wrap !important;\n  }\n  .flex-sm-nowrap {\n    -ms-flex-wrap: nowrap !important;\n        flex-wrap: nowrap !important;\n  }\n  .flex-sm-wrap-reverse {\n    -ms-flex-wrap: wrap-reverse !important;\n        flex-wrap: wrap-reverse !important;\n  }\n  .justify-content-sm-start {\n    -ms-flex-pack: start !important;\n        justify-content: flex-start !important;\n  }\n  .justify-content-sm-end {\n    -ms-flex-pack: end !important;\n        justify-content: flex-end !important;\n  }\n  .justify-content-sm-center {\n    -ms-flex-pack: center !important;\n        justify-content: center !important;\n  }\n  .justify-content-sm-between {\n    -ms-flex-pack: justify !important;\n        justify-content: space-between !important;\n  }\n  .justify-content-sm-around {\n    -ms-flex-pack: distribute !important;\n        justify-content: space-around !important;\n  }\n  .align-items-sm-start {\n    -ms-flex-align: start !important;\n        align-items: flex-start !important;\n  }\n  .align-items-sm-end {\n    -ms-flex-align: end !important;\n        align-items: flex-end !important;\n  }\n  .align-items-sm-center {\n    -ms-flex-align: center !important;\n        align-items: center !important;\n  }\n  .align-items-sm-baseline {\n    -ms-flex-align: baseline !important;\n        align-items: baseline !important;\n  }\n  .align-items-sm-stretch {\n    -ms-flex-align: stretch !important;\n        align-items: stretch !important;\n  }\n  .align-content-sm-start {\n    -ms-flex-line-pack: start !important;\n        align-content: flex-start !important;\n  }\n  .align-content-sm-end {\n    -ms-flex-line-pack: end !important;\n        align-content: flex-end !important;\n  }\n  .align-content-sm-center {\n    -ms-flex-line-pack: center !important;\n        align-content: center !important;\n  }\n  .align-content-sm-between {\n    -ms-flex-line-pack: justify !important;\n        align-content: space-between !important;\n  }\n  .align-content-sm-around {\n    -ms-flex-line-pack: distribute !important;\n        align-content: space-around !important;\n  }\n  .align-content-sm-stretch {\n    -ms-flex-line-pack: stretch !important;\n        align-content: stretch !important;\n  }\n  .align-self-sm-auto {\n    -ms-flex-item-align: auto !important;\n        align-self: auto !important;\n  }\n  .align-self-sm-start {\n    -ms-flex-item-align: start !important;\n        align-self: flex-start !important;\n  }\n  .align-self-sm-end {\n    -ms-flex-item-align: end !important;\n        align-self: flex-end !important;\n  }\n  .align-self-sm-center {\n    -ms-flex-item-align: center !important;\n        align-self: center !important;\n  }\n  .align-self-sm-baseline {\n    -ms-flex-item-align: baseline !important;\n        align-self: baseline !important;\n  }\n  .align-self-sm-stretch {\n    -ms-flex-item-align: stretch !important;\n        align-self: stretch !important;\n  }\n}\n\n@media (min-width: 768px) {\n  .flex-md-row {\n    -ms-flex-direction: row !important;\n        flex-direction: row !important;\n  }\n  .flex-md-column {\n    -ms-flex-direction: column !important;\n        flex-direction: column !important;\n  }\n  .flex-md-row-reverse {\n    -ms-flex-direction: row-reverse !important;\n        flex-direction: row-reverse !important;\n  }\n  .flex-md-column-reverse {\n    -ms-flex-direction: column-reverse !important;\n        flex-direction: column-reverse !important;\n  }\n  .flex-md-wrap {\n    -ms-flex-wrap: wrap !important;\n        flex-wrap: wrap !important;\n  }\n  .flex-md-nowrap {\n    -ms-flex-wrap: nowrap !important;\n        flex-wrap: nowrap !important;\n  }\n  .flex-md-wrap-reverse {\n    -ms-flex-wrap: wrap-reverse !important;\n        flex-wrap: wrap-reverse !important;\n  }\n  .justify-content-md-start {\n    -ms-flex-pack: start !important;\n        justify-content: flex-start !important;\n  }\n  .justify-content-md-end {\n    -ms-flex-pack: end !important;\n        justify-content: flex-end !important;\n  }\n  .justify-content-md-center {\n    -ms-flex-pack: center !important;\n        justify-content: center !important;\n  }\n  .justify-content-md-between {\n    -ms-flex-pack: justify !important;\n        justify-content: space-between !important;\n  }\n  .justify-content-md-around {\n    -ms-flex-pack: distribute !important;\n        justify-content: space-around !important;\n  }\n  .align-items-md-start {\n    -ms-flex-align: start !important;\n        align-items: flex-start !important;\n  }\n  .align-items-md-end {\n    -ms-flex-align: end !important;\n        align-items: flex-end !important;\n  }\n  .align-items-md-center {\n    -ms-flex-align: center !important;\n        align-items: center !important;\n  }\n  .align-items-md-baseline {\n    -ms-flex-align: baseline !important;\n        align-items: baseline !important;\n  }\n  .align-items-md-stretch {\n    -ms-flex-align: stretch !important;\n        align-items: stretch !important;\n  }\n  .align-content-md-start {\n    -ms-flex-line-pack: start !important;\n        align-content: flex-start !important;\n  }\n  .align-content-md-end {\n    -ms-flex-line-pack: end !important;\n        align-content: flex-end !important;\n  }\n  .align-content-md-center {\n    -ms-flex-line-pack: center !important;\n        align-content: center !important;\n  }\n  .align-content-md-between {\n    -ms-flex-line-pack: justify !important;\n        align-content: space-between !important;\n  }\n  .align-content-md-around {\n    -ms-flex-line-pack: distribute !important;\n        align-content: space-around !important;\n  }\n  .align-content-md-stretch {\n    -ms-flex-line-pack: stretch !important;\n        align-content: stretch !important;\n  }\n  .align-self-md-auto {\n    -ms-flex-item-align: auto !important;\n        align-self: auto !important;\n  }\n  .align-self-md-start {\n    -ms-flex-item-align: start !important;\n        align-self: flex-start !important;\n  }\n  .align-self-md-end {\n    -ms-flex-item-align: end !important;\n        align-self: flex-end !important;\n  }\n  .align-self-md-center {\n    -ms-flex-item-align: center !important;\n        align-self: center !important;\n  }\n  .align-self-md-baseline {\n    -ms-flex-item-align: baseline !important;\n        align-self: baseline !important;\n  }\n  .align-self-md-stretch {\n    -ms-flex-item-align: stretch !important;\n        align-self: stretch !important;\n  }\n}\n\n@media (min-width: 992px) {\n  .flex-lg-row {\n    -ms-flex-direction: row !important;\n        flex-direction: row !important;\n  }\n  .flex-lg-column {\n    -ms-flex-direction: column !important;\n        flex-direction: column !important;\n  }\n  .flex-lg-row-reverse {\n    -ms-flex-direction: row-reverse !important;\n        flex-direction: row-reverse !important;\n  }\n  .flex-lg-column-reverse {\n    -ms-flex-direction: column-reverse !important;\n        flex-direction: column-reverse !important;\n  }\n  .flex-lg-wrap {\n    -ms-flex-wrap: wrap !important;\n        flex-wrap: wrap !important;\n  }\n  .flex-lg-nowrap {\n    -ms-flex-wrap: nowrap !important;\n        flex-wrap: nowrap !important;\n  }\n  .flex-lg-wrap-reverse {\n    -ms-flex-wrap: wrap-reverse !important;\n        flex-wrap: wrap-reverse !important;\n  }\n  .justify-content-lg-start {\n    -ms-flex-pack: start !important;\n        justify-content: flex-start !important;\n  }\n  .justify-content-lg-end {\n    -ms-flex-pack: end !important;\n        justify-content: flex-end !important;\n  }\n  .justify-content-lg-center {\n    -ms-flex-pack: center !important;\n        justify-content: center !important;\n  }\n  .justify-content-lg-between {\n    -ms-flex-pack: justify !important;\n        justify-content: space-between !important;\n  }\n  .justify-content-lg-around {\n    -ms-flex-pack: distribute !important;\n        justify-content: space-around !important;\n  }\n  .align-items-lg-start {\n    -ms-flex-align: start !important;\n        align-items: flex-start !important;\n  }\n  .align-items-lg-end {\n    -ms-flex-align: end !important;\n        align-items: flex-end !important;\n  }\n  .align-items-lg-center {\n    -ms-flex-align: center !important;\n        align-items: center !important;\n  }\n  .align-items-lg-baseline {\n    -ms-flex-align: baseline !important;\n        align-items: baseline !important;\n  }\n  .align-items-lg-stretch {\n    -ms-flex-align: stretch !important;\n        align-items: stretch !important;\n  }\n  .align-content-lg-start {\n    -ms-flex-line-pack: start !important;\n        align-content: flex-start !important;\n  }\n  .align-content-lg-end {\n    -ms-flex-line-pack: end !important;\n        align-content: flex-end !important;\n  }\n  .align-content-lg-center {\n    -ms-flex-line-pack: center !important;\n        align-content: center !important;\n  }\n  .align-content-lg-between {\n    -ms-flex-line-pack: justify !important;\n        align-content: space-between !important;\n  }\n  .align-content-lg-around {\n    -ms-flex-line-pack: distribute !important;\n        align-content: space-around !important;\n  }\n  .align-content-lg-stretch {\n    -ms-flex-line-pack: stretch !important;\n        align-content: stretch !important;\n  }\n  .align-self-lg-auto {\n    -ms-flex-item-align: auto !important;\n        align-self: auto !important;\n  }\n  .align-self-lg-start {\n    -ms-flex-item-align: start !important;\n        align-self: flex-start !important;\n  }\n  .align-self-lg-end {\n    -ms-flex-item-align: end !important;\n        align-self: flex-end !important;\n  }\n  .align-self-lg-center {\n    -ms-flex-item-align: center !important;\n        align-self: center !important;\n  }\n  .align-self-lg-baseline {\n    -ms-flex-item-align: baseline !important;\n        align-self: baseline !important;\n  }\n  .align-self-lg-stretch {\n    -ms-flex-item-align: stretch !important;\n        align-self: stretch !important;\n  }\n}\n\n@media (min-width: 1200px) {\n  .flex-xl-row {\n    -ms-flex-direction: row !important;\n        flex-direction: row !important;\n  }\n  .flex-xl-column {\n    -ms-flex-direction: column !important;\n        flex-direction: column !important;\n  }\n  .flex-xl-row-reverse {\n    -ms-flex-direction: row-reverse !important;\n        flex-direction: row-reverse !important;\n  }\n  .flex-xl-column-reverse {\n    -ms-flex-direction: column-reverse !important;\n        flex-direction: column-reverse !important;\n  }\n  .flex-xl-wrap {\n    -ms-flex-wrap: wrap !important;\n        flex-wrap: wrap !important;\n  }\n  .flex-xl-nowrap {\n    -ms-flex-wrap: nowrap !important;\n        flex-wrap: nowrap !important;\n  }\n  .flex-xl-wrap-reverse {\n    -ms-flex-wrap: wrap-reverse !important;\n        flex-wrap: wrap-reverse !important;\n  }\n  .justify-content-xl-start {\n    -ms-flex-pack: start !important;\n        justify-content: flex-start !important;\n  }\n  .justify-content-xl-end {\n    -ms-flex-pack: end !important;\n        justify-content: flex-end !important;\n  }\n  .justify-content-xl-center {\n    -ms-flex-pack: center !important;\n        justify-content: center !important;\n  }\n  .justify-content-xl-between {\n    -ms-flex-pack: justify !important;\n        justify-content: space-between !important;\n  }\n  .justify-content-xl-around {\n    -ms-flex-pack: distribute !important;\n        justify-content: space-around !important;\n  }\n  .align-items-xl-start {\n    -ms-flex-align: start !important;\n        align-items: flex-start !important;\n  }\n  .align-items-xl-end {\n    -ms-flex-align: end !important;\n        align-items: flex-end !important;\n  }\n  .align-items-xl-center {\n    -ms-flex-align: center !important;\n        align-items: center !important;\n  }\n  .align-items-xl-baseline {\n    -ms-flex-align: baseline !important;\n        align-items: baseline !important;\n  }\n  .align-items-xl-stretch {\n    -ms-flex-align: stretch !important;\n        align-items: stretch !important;\n  }\n  .align-content-xl-start {\n    -ms-flex-line-pack: start !important;\n        align-content: flex-start !important;\n  }\n  .align-content-xl-end {\n    -ms-flex-line-pack: end !important;\n        align-content: flex-end !important;\n  }\n  .align-content-xl-center {\n    -ms-flex-line-pack: center !important;\n        align-content: center !important;\n  }\n  .align-content-xl-between {\n    -ms-flex-line-pack: justify !important;\n        align-content: space-between !important;\n  }\n  .align-content-xl-around {\n    -ms-flex-line-pack: distribute !important;\n        align-content: space-around !important;\n  }\n  .align-content-xl-stretch {\n    -ms-flex-line-pack: stretch !important;\n        align-content: stretch !important;\n  }\n  .align-self-xl-auto {\n    -ms-flex-item-align: auto !important;\n        align-self: auto !important;\n  }\n  .align-self-xl-start {\n    -ms-flex-item-align: start !important;\n        align-self: flex-start !important;\n  }\n  .align-self-xl-end {\n    -ms-flex-item-align: end !important;\n        align-self: flex-end !important;\n  }\n  .align-self-xl-center {\n    -ms-flex-item-align: center !important;\n        align-self: center !important;\n  }\n  .align-self-xl-baseline {\n    -ms-flex-item-align: baseline !important;\n        align-self: baseline !important;\n  }\n  .align-self-xl-stretch {\n    -ms-flex-item-align: stretch !important;\n        align-self: stretch !important;\n  }\n}\n\n.float-left {\n  float: left !important;\n}\n\n.float-right {\n  float: right !important;\n}\n\n.float-none {\n  float: none !important;\n}\n\n@media (min-width: 576px) {\n  .float-sm-left {\n    float: left !important;\n  }\n  .float-sm-right {\n    float: right !important;\n  }\n  .float-sm-none {\n    float: none !important;\n  }\n}\n\n@media (min-width: 768px) {\n  .float-md-left {\n    float: left !important;\n  }\n  .float-md-right {\n    float: right !important;\n  }\n  .float-md-none {\n    float: none !important;\n  }\n}\n\n@media (min-width: 992px) {\n  .float-lg-left {\n    float: left !important;\n  }\n  .float-lg-right {\n    float: right !important;\n  }\n  .float-lg-none {\n    float: none !important;\n  }\n}\n\n@media (min-width: 1200px) {\n  .float-xl-left {\n    float: left !important;\n  }\n  .float-xl-right {\n    float: right !important;\n  }\n  .float-xl-none {\n    float: none !important;\n  }\n}\n\n.position-static {\n  position: static !important;\n}\n\n.position-relative {\n  position: relative !important;\n}\n\n.position-absolute {\n  position: absolute !important;\n}\n\n.position-fixed {\n  position: fixed !important;\n}\n\n.position-sticky {\n  position: -webkit-sticky !important;\n  position: sticky !important;\n}\n\n.fixed-top {\n  position: fixed;\n  top: 0;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n}\n\n.fixed-bottom {\n  position: fixed;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1030;\n}\n\n@supports ((position: -webkit-sticky) or (position: sticky)) {\n  .sticky-top {\n    position: -webkit-sticky;\n    position: sticky;\n    top: 0;\n    z-index: 1020;\n  }\n}\n\n.sr-only {\n  position: absolute;\n  width: 1px;\n  height: 1px;\n  padding: 0;\n  overflow: hidden;\n  clip: rect(0, 0, 0, 0);\n  white-space: nowrap;\n  -webkit-clip-path: inset(50%);\n          clip-path: inset(50%);\n  border: 0;\n}\n\n.sr-only-focusable:active, .sr-only-focusable:focus {\n  position: static;\n  width: auto;\n  height: auto;\n  overflow: visible;\n  clip: auto;\n  white-space: normal;\n  -webkit-clip-path: none;\n          clip-path: none;\n}\n\n.w-25 {\n  width: 25% !important;\n}\n\n.w-50 {\n  width: 50% !important;\n}\n\n.w-75 {\n  width: 75% !important;\n}\n\n.w-100 {\n  width: 100% !important;\n}\n\n.h-25 {\n  height: 25% !important;\n}\n\n.h-50 {\n  height: 50% !important;\n}\n\n.h-75 {\n  height: 75% !important;\n}\n\n.h-100 {\n  height: 100% !important;\n}\n\n.mw-100 {\n  max-width: 100% !important;\n}\n\n.mh-100 {\n  max-height: 100% !important;\n}\n\n.m-0 {\n  margin: 0 !important;\n}\n\n.mt-0,\n.my-0 {\n  margin-top: 0 !important;\n}\n\n.mr-0,\n.mx-0 {\n  margin-right: 0 !important;\n}\n\n.mb-0,\n.my-0 {\n  margin-bottom: 0 !important;\n}\n\n.ml-0,\n.mx-0 {\n  margin-left: 0 !important;\n}\n\n.m-1 {\n  margin: 0.25rem !important;\n}\n\n.mt-1,\n.my-1 {\n  margin-top: 0.25rem !important;\n}\n\n.mr-1,\n.mx-1 {\n  margin-right: 0.25rem !important;\n}\n\n.mb-1,\n.my-1 {\n  margin-bottom: 0.25rem !important;\n}\n\n.ml-1,\n.mx-1 {\n  margin-left: 0.25rem !important;\n}\n\n.m-2 {\n  margin: 0.5rem !important;\n}\n\n.mt-2,\n.my-2 {\n  margin-top: 0.5rem !important;\n}\n\n.mr-2,\n.mx-2 {\n  margin-right: 0.5rem !important;\n}\n\n.mb-2,\n.my-2 {\n  margin-bottom: 0.5rem !important;\n}\n\n.ml-2,\n.mx-2 {\n  margin-left: 0.5rem !important;\n}\n\n.m-3 {\n  margin: 1rem !important;\n}\n\n.mt-3,\n.my-3 {\n  margin-top: 1rem !important;\n}\n\n.mr-3,\n.mx-3 {\n  margin-right: 1rem !important;\n}\n\n.mb-3,\n.my-3 {\n  margin-bottom: 1rem !important;\n}\n\n.ml-3,\n.mx-3 {\n  margin-left: 1rem !important;\n}\n\n.m-4 {\n  margin: 1.5rem !important;\n}\n\n.mt-4,\n.my-4 {\n  margin-top: 1.5rem !important;\n}\n\n.mr-4,\n.mx-4 {\n  margin-right: 1.5rem !important;\n}\n\n.mb-4,\n.my-4 {\n  margin-bottom: 1.5rem !important;\n}\n\n.ml-4,\n.mx-4 {\n  margin-left: 1.5rem !important;\n}\n\n.m-5 {\n  margin: 3rem !important;\n}\n\n.mt-5,\n.my-5 {\n  margin-top: 3rem !important;\n}\n\n.mr-5,\n.mx-5 {\n  margin-right: 3rem !important;\n}\n\n.mb-5,\n.my-5 {\n  margin-bottom: 3rem !important;\n}\n\n.ml-5,\n.mx-5 {\n  margin-left: 3rem !important;\n}\n\n.p-0 {\n  padding: 0 !important;\n}\n\n.pt-0,\n.py-0 {\n  padding-top: 0 !important;\n}\n\n.pr-0,\n.px-0 {\n  padding-right: 0 !important;\n}\n\n.pb-0,\n.py-0 {\n  padding-bottom: 0 !important;\n}\n\n.pl-0,\n.px-0 {\n  padding-left: 0 !important;\n}\n\n.p-1 {\n  padding: 0.25rem !important;\n}\n\n.pt-1,\n.py-1 {\n  padding-top: 0.25rem !important;\n}\n\n.pr-1,\n.px-1 {\n  padding-right: 0.25rem !important;\n}\n\n.pb-1,\n.py-1 {\n  padding-bottom: 0.25rem !important;\n}\n\n.pl-1,\n.px-1 {\n  padding-left: 0.25rem !important;\n}\n\n.p-2 {\n  padding: 0.5rem !important;\n}\n\n.pt-2,\n.py-2 {\n  padding-top: 0.5rem !important;\n}\n\n.pr-2,\n.px-2 {\n  padding-right: 0.5rem !important;\n}\n\n.pb-2,\n.py-2 {\n  padding-bottom: 0.5rem !important;\n}\n\n.pl-2,\n.px-2 {\n  padding-left: 0.5rem !important;\n}\n\n.p-3 {\n  padding: 1rem !important;\n}\n\n.pt-3,\n.py-3 {\n  padding-top: 1rem !important;\n}\n\n.pr-3,\n.px-3 {\n  padding-right: 1rem !important;\n}\n\n.pb-3,\n.py-3 {\n  padding-bottom: 1rem !important;\n}\n\n.pl-3,\n.px-3 {\n  padding-left: 1rem !important;\n}\n\n.p-4 {\n  padding: 1.5rem !important;\n}\n\n.pt-4,\n.py-4 {\n  padding-top: 1.5rem !important;\n}\n\n.pr-4,\n.px-4 {\n  padding-right: 1.5rem !important;\n}\n\n.pb-4,\n.py-4 {\n  padding-bottom: 1.5rem !important;\n}\n\n.pl-4,\n.px-4 {\n  padding-left: 1.5rem !important;\n}\n\n.p-5 {\n  padding: 3rem !important;\n}\n\n.pt-5,\n.py-5 {\n  padding-top: 3rem !important;\n}\n\n.pr-5,\n.px-5 {\n  padding-right: 3rem !important;\n}\n\n.pb-5,\n.py-5 {\n  padding-bottom: 3rem !important;\n}\n\n.pl-5,\n.px-5 {\n  padding-left: 3rem !important;\n}\n\n.m-auto {\n  margin: auto !important;\n}\n\n.mt-auto,\n.my-auto {\n  margin-top: auto !important;\n}\n\n.mr-auto,\n.mx-auto {\n  margin-right: auto !important;\n}\n\n.mb-auto,\n.my-auto {\n  margin-bottom: auto !important;\n}\n\n.ml-auto,\n.mx-auto {\n  margin-left: auto !important;\n}\n\n@media (min-width: 576px) {\n  .m-sm-0 {\n    margin: 0 !important;\n  }\n  .mt-sm-0,\n  .my-sm-0 {\n    margin-top: 0 !important;\n  }\n  .mr-sm-0,\n  .mx-sm-0 {\n    margin-right: 0 !important;\n  }\n  .mb-sm-0,\n  .my-sm-0 {\n    margin-bottom: 0 !important;\n  }\n  .ml-sm-0,\n  .mx-sm-0 {\n    margin-left: 0 !important;\n  }\n  .m-sm-1 {\n    margin: 0.25rem !important;\n  }\n  .mt-sm-1,\n  .my-sm-1 {\n    margin-top: 0.25rem !important;\n  }\n  .mr-sm-1,\n  .mx-sm-1 {\n    margin-right: 0.25rem !important;\n  }\n  .mb-sm-1,\n  .my-sm-1 {\n    margin-bottom: 0.25rem !important;\n  }\n  .ml-sm-1,\n  .mx-sm-1 {\n    margin-left: 0.25rem !important;\n  }\n  .m-sm-2 {\n    margin: 0.5rem !important;\n  }\n  .mt-sm-2,\n  .my-sm-2 {\n    margin-top: 0.5rem !important;\n  }\n  .mr-sm-2,\n  .mx-sm-2 {\n    margin-right: 0.5rem !important;\n  }\n  .mb-sm-2,\n  .my-sm-2 {\n    margin-bottom: 0.5rem !important;\n  }\n  .ml-sm-2,\n  .mx-sm-2 {\n    margin-left: 0.5rem !important;\n  }\n  .m-sm-3 {\n    margin: 1rem !important;\n  }\n  .mt-sm-3,\n  .my-sm-3 {\n    margin-top: 1rem !important;\n  }\n  .mr-sm-3,\n  .mx-sm-3 {\n    margin-right: 1rem !important;\n  }\n  .mb-sm-3,\n  .my-sm-3 {\n    margin-bottom: 1rem !important;\n  }\n  .ml-sm-3,\n  .mx-sm-3 {\n    margin-left: 1rem !important;\n  }\n  .m-sm-4 {\n    margin: 1.5rem !important;\n  }\n  .mt-sm-4,\n  .my-sm-4 {\n    margin-top: 1.5rem !important;\n  }\n  .mr-sm-4,\n  .mx-sm-4 {\n    margin-right: 1.5rem !important;\n  }\n  .mb-sm-4,\n  .my-sm-4 {\n    margin-bottom: 1.5rem !important;\n  }\n  .ml-sm-4,\n  .mx-sm-4 {\n    margin-left: 1.5rem !important;\n  }\n  .m-sm-5 {\n    margin: 3rem !important;\n  }\n  .mt-sm-5,\n  .my-sm-5 {\n    margin-top: 3rem !important;\n  }\n  .mr-sm-5,\n  .mx-sm-5 {\n    margin-right: 3rem !important;\n  }\n  .mb-sm-5,\n  .my-sm-5 {\n    margin-bottom: 3rem !important;\n  }\n  .ml-sm-5,\n  .mx-sm-5 {\n    margin-left: 3rem !important;\n  }\n  .p-sm-0 {\n    padding: 0 !important;\n  }\n  .pt-sm-0,\n  .py-sm-0 {\n    padding-top: 0 !important;\n  }\n  .pr-sm-0,\n  .px-sm-0 {\n    padding-right: 0 !important;\n  }\n  .pb-sm-0,\n  .py-sm-0 {\n    padding-bottom: 0 !important;\n  }\n  .pl-sm-0,\n  .px-sm-0 {\n    padding-left: 0 !important;\n  }\n  .p-sm-1 {\n    padding: 0.25rem !important;\n  }\n  .pt-sm-1,\n  .py-sm-1 {\n    padding-top: 0.25rem !important;\n  }\n  .pr-sm-1,\n  .px-sm-1 {\n    padding-right: 0.25rem !important;\n  }\n  .pb-sm-1,\n  .py-sm-1 {\n    padding-bottom: 0.25rem !important;\n  }\n  .pl-sm-1,\n  .px-sm-1 {\n    padding-left: 0.25rem !important;\n  }\n  .p-sm-2 {\n    padding: 0.5rem !important;\n  }\n  .pt-sm-2,\n  .py-sm-2 {\n    padding-top: 0.5rem !important;\n  }\n  .pr-sm-2,\n  .px-sm-2 {\n    padding-right: 0.5rem !important;\n  }\n  .pb-sm-2,\n  .py-sm-2 {\n    padding-bottom: 0.5rem !important;\n  }\n  .pl-sm-2,\n  .px-sm-2 {\n    padding-left: 0.5rem !important;\n  }\n  .p-sm-3 {\n    padding: 1rem !important;\n  }\n  .pt-sm-3,\n  .py-sm-3 {\n    padding-top: 1rem !important;\n  }\n  .pr-sm-3,\n  .px-sm-3 {\n    padding-right: 1rem !important;\n  }\n  .pb-sm-3,\n  .py-sm-3 {\n    padding-bottom: 1rem !important;\n  }\n  .pl-sm-3,\n  .px-sm-3 {\n    padding-left: 1rem !important;\n  }\n  .p-sm-4 {\n    padding: 1.5rem !important;\n  }\n  .pt-sm-4,\n  .py-sm-4 {\n    padding-top: 1.5rem !important;\n  }\n  .pr-sm-4,\n  .px-sm-4 {\n    padding-right: 1.5rem !important;\n  }\n  .pb-sm-4,\n  .py-sm-4 {\n    padding-bottom: 1.5rem !important;\n  }\n  .pl-sm-4,\n  .px-sm-4 {\n    padding-left: 1.5rem !important;\n  }\n  .p-sm-5 {\n    padding: 3rem !important;\n  }\n  .pt-sm-5,\n  .py-sm-5 {\n    padding-top: 3rem !important;\n  }\n  .pr-sm-5,\n  .px-sm-5 {\n    padding-right: 3rem !important;\n  }\n  .pb-sm-5,\n  .py-sm-5 {\n    padding-bottom: 3rem !important;\n  }\n  .pl-sm-5,\n  .px-sm-5 {\n    padding-left: 3rem !important;\n  }\n  .m-sm-auto {\n    margin: auto !important;\n  }\n  .mt-sm-auto,\n  .my-sm-auto {\n    margin-top: auto !important;\n  }\n  .mr-sm-auto,\n  .mx-sm-auto {\n    margin-right: auto !important;\n  }\n  .mb-sm-auto,\n  .my-sm-auto {\n    margin-bottom: auto !important;\n  }\n  .ml-sm-auto,\n  .mx-sm-auto {\n    margin-left: auto !important;\n  }\n}\n\n@media (min-width: 768px) {\n  .m-md-0 {\n    margin: 0 !important;\n  }\n  .mt-md-0,\n  .my-md-0 {\n    margin-top: 0 !important;\n  }\n  .mr-md-0,\n  .mx-md-0 {\n    margin-right: 0 !important;\n  }\n  .mb-md-0,\n  .my-md-0 {\n    margin-bottom: 0 !important;\n  }\n  .ml-md-0,\n  .mx-md-0 {\n    margin-left: 0 !important;\n  }\n  .m-md-1 {\n    margin: 0.25rem !important;\n  }\n  .mt-md-1,\n  .my-md-1 {\n    margin-top: 0.25rem !important;\n  }\n  .mr-md-1,\n  .mx-md-1 {\n    margin-right: 0.25rem !important;\n  }\n  .mb-md-1,\n  .my-md-1 {\n    margin-bottom: 0.25rem !important;\n  }\n  .ml-md-1,\n  .mx-md-1 {\n    margin-left: 0.25rem !important;\n  }\n  .m-md-2 {\n    margin: 0.5rem !important;\n  }\n  .mt-md-2,\n  .my-md-2 {\n    margin-top: 0.5rem !important;\n  }\n  .mr-md-2,\n  .mx-md-2 {\n    margin-right: 0.5rem !important;\n  }\n  .mb-md-2,\n  .my-md-2 {\n    margin-bottom: 0.5rem !important;\n  }\n  .ml-md-2,\n  .mx-md-2 {\n    margin-left: 0.5rem !important;\n  }\n  .m-md-3 {\n    margin: 1rem !important;\n  }\n  .mt-md-3,\n  .my-md-3 {\n    margin-top: 1rem !important;\n  }\n  .mr-md-3,\n  .mx-md-3 {\n    margin-right: 1rem !important;\n  }\n  .mb-md-3,\n  .my-md-3 {\n    margin-bottom: 1rem !important;\n  }\n  .ml-md-3,\n  .mx-md-3 {\n    margin-left: 1rem !important;\n  }\n  .m-md-4 {\n    margin: 1.5rem !important;\n  }\n  .mt-md-4,\n  .my-md-4 {\n    margin-top: 1.5rem !important;\n  }\n  .mr-md-4,\n  .mx-md-4 {\n    margin-right: 1.5rem !important;\n  }\n  .mb-md-4,\n  .my-md-4 {\n    margin-bottom: 1.5rem !important;\n  }\n  .ml-md-4,\n  .mx-md-4 {\n    margin-left: 1.5rem !important;\n  }\n  .m-md-5 {\n    margin: 3rem !important;\n  }\n  .mt-md-5,\n  .my-md-5 {\n    margin-top: 3rem !important;\n  }\n  .mr-md-5,\n  .mx-md-5 {\n    margin-right: 3rem !important;\n  }\n  .mb-md-5,\n  .my-md-5 {\n    margin-bottom: 3rem !important;\n  }\n  .ml-md-5,\n  .mx-md-5 {\n    margin-left: 3rem !important;\n  }\n  .p-md-0 {\n    padding: 0 !important;\n  }\n  .pt-md-0,\n  .py-md-0 {\n    padding-top: 0 !important;\n  }\n  .pr-md-0,\n  .px-md-0 {\n    padding-right: 0 !important;\n  }\n  .pb-md-0,\n  .py-md-0 {\n    padding-bottom: 0 !important;\n  }\n  .pl-md-0,\n  .px-md-0 {\n    padding-left: 0 !important;\n  }\n  .p-md-1 {\n    padding: 0.25rem !important;\n  }\n  .pt-md-1,\n  .py-md-1 {\n    padding-top: 0.25rem !important;\n  }\n  .pr-md-1,\n  .px-md-1 {\n    padding-right: 0.25rem !important;\n  }\n  .pb-md-1,\n  .py-md-1 {\n    padding-bottom: 0.25rem !important;\n  }\n  .pl-md-1,\n  .px-md-1 {\n    padding-left: 0.25rem !important;\n  }\n  .p-md-2 {\n    padding: 0.5rem !important;\n  }\n  .pt-md-2,\n  .py-md-2 {\n    padding-top: 0.5rem !important;\n  }\n  .pr-md-2,\n  .px-md-2 {\n    padding-right: 0.5rem !important;\n  }\n  .pb-md-2,\n  .py-md-2 {\n    padding-bottom: 0.5rem !important;\n  }\n  .pl-md-2,\n  .px-md-2 {\n    padding-left: 0.5rem !important;\n  }\n  .p-md-3 {\n    padding: 1rem !important;\n  }\n  .pt-md-3,\n  .py-md-3 {\n    padding-top: 1rem !important;\n  }\n  .pr-md-3,\n  .px-md-3 {\n    padding-right: 1rem !important;\n  }\n  .pb-md-3,\n  .py-md-3 {\n    padding-bottom: 1rem !important;\n  }\n  .pl-md-3,\n  .px-md-3 {\n    padding-left: 1rem !important;\n  }\n  .p-md-4 {\n    padding: 1.5rem !important;\n  }\n  .pt-md-4,\n  .py-md-4 {\n    padding-top: 1.5rem !important;\n  }\n  .pr-md-4,\n  .px-md-4 {\n    padding-right: 1.5rem !important;\n  }\n  .pb-md-4,\n  .py-md-4 {\n    padding-bottom: 1.5rem !important;\n  }\n  .pl-md-4,\n  .px-md-4 {\n    padding-left: 1.5rem !important;\n  }\n  .p-md-5 {\n    padding: 3rem !important;\n  }\n  .pt-md-5,\n  .py-md-5 {\n    padding-top: 3rem !important;\n  }\n  .pr-md-5,\n  .px-md-5 {\n    padding-right: 3rem !important;\n  }\n  .pb-md-5,\n  .py-md-5 {\n    padding-bottom: 3rem !important;\n  }\n  .pl-md-5,\n  .px-md-5 {\n    padding-left: 3rem !important;\n  }\n  .m-md-auto {\n    margin: auto !important;\n  }\n  .mt-md-auto,\n  .my-md-auto {\n    margin-top: auto !important;\n  }\n  .mr-md-auto,\n  .mx-md-auto {\n    margin-right: auto !important;\n  }\n  .mb-md-auto,\n  .my-md-auto {\n    margin-bottom: auto !important;\n  }\n  .ml-md-auto,\n  .mx-md-auto {\n    margin-left: auto !important;\n  }\n}\n\n@media (min-width: 992px) {\n  .m-lg-0 {\n    margin: 0 !important;\n  }\n  .mt-lg-0,\n  .my-lg-0 {\n    margin-top: 0 !important;\n  }\n  .mr-lg-0,\n  .mx-lg-0 {\n    margin-right: 0 !important;\n  }\n  .mb-lg-0,\n  .my-lg-0 {\n    margin-bottom: 0 !important;\n  }\n  .ml-lg-0,\n  .mx-lg-0 {\n    margin-left: 0 !important;\n  }\n  .m-lg-1 {\n    margin: 0.25rem !important;\n  }\n  .mt-lg-1,\n  .my-lg-1 {\n    margin-top: 0.25rem !important;\n  }\n  .mr-lg-1,\n  .mx-lg-1 {\n    margin-right: 0.25rem !important;\n  }\n  .mb-lg-1,\n  .my-lg-1 {\n    margin-bottom: 0.25rem !important;\n  }\n  .ml-lg-1,\n  .mx-lg-1 {\n    margin-left: 0.25rem !important;\n  }\n  .m-lg-2 {\n    margin: 0.5rem !important;\n  }\n  .mt-lg-2,\n  .my-lg-2 {\n    margin-top: 0.5rem !important;\n  }\n  .mr-lg-2,\n  .mx-lg-2 {\n    margin-right: 0.5rem !important;\n  }\n  .mb-lg-2,\n  .my-lg-2 {\n    margin-bottom: 0.5rem !important;\n  }\n  .ml-lg-2,\n  .mx-lg-2 {\n    margin-left: 0.5rem !important;\n  }\n  .m-lg-3 {\n    margin: 1rem !important;\n  }\n  .mt-lg-3,\n  .my-lg-3 {\n    margin-top: 1rem !important;\n  }\n  .mr-lg-3,\n  .mx-lg-3 {\n    margin-right: 1rem !important;\n  }\n  .mb-lg-3,\n  .my-lg-3 {\n    margin-bottom: 1rem !important;\n  }\n  .ml-lg-3,\n  .mx-lg-3 {\n    margin-left: 1rem !important;\n  }\n  .m-lg-4 {\n    margin: 1.5rem !important;\n  }\n  .mt-lg-4,\n  .my-lg-4 {\n    margin-top: 1.5rem !important;\n  }\n  .mr-lg-4,\n  .mx-lg-4 {\n    margin-right: 1.5rem !important;\n  }\n  .mb-lg-4,\n  .my-lg-4 {\n    margin-bottom: 1.5rem !important;\n  }\n  .ml-lg-4,\n  .mx-lg-4 {\n    margin-left: 1.5rem !important;\n  }\n  .m-lg-5 {\n    margin: 3rem !important;\n  }\n  .mt-lg-5,\n  .my-lg-5 {\n    margin-top: 3rem !important;\n  }\n  .mr-lg-5,\n  .mx-lg-5 {\n    margin-right: 3rem !important;\n  }\n  .mb-lg-5,\n  .my-lg-5 {\n    margin-bottom: 3rem !important;\n  }\n  .ml-lg-5,\n  .mx-lg-5 {\n    margin-left: 3rem !important;\n  }\n  .p-lg-0 {\n    padding: 0 !important;\n  }\n  .pt-lg-0,\n  .py-lg-0 {\n    padding-top: 0 !important;\n  }\n  .pr-lg-0,\n  .px-lg-0 {\n    padding-right: 0 !important;\n  }\n  .pb-lg-0,\n  .py-lg-0 {\n    padding-bottom: 0 !important;\n  }\n  .pl-lg-0,\n  .px-lg-0 {\n    padding-left: 0 !important;\n  }\n  .p-lg-1 {\n    padding: 0.25rem !important;\n  }\n  .pt-lg-1,\n  .py-lg-1 {\n    padding-top: 0.25rem !important;\n  }\n  .pr-lg-1,\n  .px-lg-1 {\n    padding-right: 0.25rem !important;\n  }\n  .pb-lg-1,\n  .py-lg-1 {\n    padding-bottom: 0.25rem !important;\n  }\n  .pl-lg-1,\n  .px-lg-1 {\n    padding-left: 0.25rem !important;\n  }\n  .p-lg-2 {\n    padding: 0.5rem !important;\n  }\n  .pt-lg-2,\n  .py-lg-2 {\n    padding-top: 0.5rem !important;\n  }\n  .pr-lg-2,\n  .px-lg-2 {\n    padding-right: 0.5rem !important;\n  }\n  .pb-lg-2,\n  .py-lg-2 {\n    padding-bottom: 0.5rem !important;\n  }\n  .pl-lg-2,\n  .px-lg-2 {\n    padding-left: 0.5rem !important;\n  }\n  .p-lg-3 {\n    padding: 1rem !important;\n  }\n  .pt-lg-3,\n  .py-lg-3 {\n    padding-top: 1rem !important;\n  }\n  .pr-lg-3,\n  .px-lg-3 {\n    padding-right: 1rem !important;\n  }\n  .pb-lg-3,\n  .py-lg-3 {\n    padding-bottom: 1rem !important;\n  }\n  .pl-lg-3,\n  .px-lg-3 {\n    padding-left: 1rem !important;\n  }\n  .p-lg-4 {\n    padding: 1.5rem !important;\n  }\n  .pt-lg-4,\n  .py-lg-4 {\n    padding-top: 1.5rem !important;\n  }\n  .pr-lg-4,\n  .px-lg-4 {\n    padding-right: 1.5rem !important;\n  }\n  .pb-lg-4,\n  .py-lg-4 {\n    padding-bottom: 1.5rem !important;\n  }\n  .pl-lg-4,\n  .px-lg-4 {\n    padding-left: 1.5rem !important;\n  }\n  .p-lg-5 {\n    padding: 3rem !important;\n  }\n  .pt-lg-5,\n  .py-lg-5 {\n    padding-top: 3rem !important;\n  }\n  .pr-lg-5,\n  .px-lg-5 {\n    padding-right: 3rem !important;\n  }\n  .pb-lg-5,\n  .py-lg-5 {\n    padding-bottom: 3rem !important;\n  }\n  .pl-lg-5,\n  .px-lg-5 {\n    padding-left: 3rem !important;\n  }\n  .m-lg-auto {\n    margin: auto !important;\n  }\n  .mt-lg-auto,\n  .my-lg-auto {\n    margin-top: auto !important;\n  }\n  .mr-lg-auto,\n  .mx-lg-auto {\n    margin-right: auto !important;\n  }\n  .mb-lg-auto,\n  .my-lg-auto {\n    margin-bottom: auto !important;\n  }\n  .ml-lg-auto,\n  .mx-lg-auto {\n    margin-left: auto !important;\n  }\n}\n\n@media (min-width: 1200px) {\n  .m-xl-0 {\n    margin: 0 !important;\n  }\n  .mt-xl-0,\n  .my-xl-0 {\n    margin-top: 0 !important;\n  }\n  .mr-xl-0,\n  .mx-xl-0 {\n    margin-right: 0 !important;\n  }\n  .mb-xl-0,\n  .my-xl-0 {\n    margin-bottom: 0 !important;\n  }\n  .ml-xl-0,\n  .mx-xl-0 {\n    margin-left: 0 !important;\n  }\n  .m-xl-1 {\n    margin: 0.25rem !important;\n  }\n  .mt-xl-1,\n  .my-xl-1 {\n    margin-top: 0.25rem !important;\n  }\n  .mr-xl-1,\n  .mx-xl-1 {\n    margin-right: 0.25rem !important;\n  }\n  .mb-xl-1,\n  .my-xl-1 {\n    margin-bottom: 0.25rem !important;\n  }\n  .ml-xl-1,\n  .mx-xl-1 {\n    margin-left: 0.25rem !important;\n  }\n  .m-xl-2 {\n    margin: 0.5rem !important;\n  }\n  .mt-xl-2,\n  .my-xl-2 {\n    margin-top: 0.5rem !important;\n  }\n  .mr-xl-2,\n  .mx-xl-2 {\n    margin-right: 0.5rem !important;\n  }\n  .mb-xl-2,\n  .my-xl-2 {\n    margin-bottom: 0.5rem !important;\n  }\n  .ml-xl-2,\n  .mx-xl-2 {\n    margin-left: 0.5rem !important;\n  }\n  .m-xl-3 {\n    margin: 1rem !important;\n  }\n  .mt-xl-3,\n  .my-xl-3 {\n    margin-top: 1rem !important;\n  }\n  .mr-xl-3,\n  .mx-xl-3 {\n    margin-right: 1rem !important;\n  }\n  .mb-xl-3,\n  .my-xl-3 {\n    margin-bottom: 1rem !important;\n  }\n  .ml-xl-3,\n  .mx-xl-3 {\n    margin-left: 1rem !important;\n  }\n  .m-xl-4 {\n    margin: 1.5rem !important;\n  }\n  .mt-xl-4,\n  .my-xl-4 {\n    margin-top: 1.5rem !important;\n  }\n  .mr-xl-4,\n  .mx-xl-4 {\n    margin-right: 1.5rem !important;\n  }\n  .mb-xl-4,\n  .my-xl-4 {\n    margin-bottom: 1.5rem !important;\n  }\n  .ml-xl-4,\n  .mx-xl-4 {\n    margin-left: 1.5rem !important;\n  }\n  .m-xl-5 {\n    margin: 3rem !important;\n  }\n  .mt-xl-5,\n  .my-xl-5 {\n    margin-top: 3rem !important;\n  }\n  .mr-xl-5,\n  .mx-xl-5 {\n    margin-right: 3rem !important;\n  }\n  .mb-xl-5,\n  .my-xl-5 {\n    margin-bottom: 3rem !important;\n  }\n  .ml-xl-5,\n  .mx-xl-5 {\n    margin-left: 3rem !important;\n  }\n  .p-xl-0 {\n    padding: 0 !important;\n  }\n  .pt-xl-0,\n  .py-xl-0 {\n    padding-top: 0 !important;\n  }\n  .pr-xl-0,\n  .px-xl-0 {\n    padding-right: 0 !important;\n  }\n  .pb-xl-0,\n  .py-xl-0 {\n    padding-bottom: 0 !important;\n  }\n  .pl-xl-0,\n  .px-xl-0 {\n    padding-left: 0 !important;\n  }\n  .p-xl-1 {\n    padding: 0.25rem !important;\n  }\n  .pt-xl-1,\n  .py-xl-1 {\n    padding-top: 0.25rem !important;\n  }\n  .pr-xl-1,\n  .px-xl-1 {\n    padding-right: 0.25rem !important;\n  }\n  .pb-xl-1,\n  .py-xl-1 {\n    padding-bottom: 0.25rem !important;\n  }\n  .pl-xl-1,\n  .px-xl-1 {\n    padding-left: 0.25rem !important;\n  }\n  .p-xl-2 {\n    padding: 0.5rem !important;\n  }\n  .pt-xl-2,\n  .py-xl-2 {\n    padding-top: 0.5rem !important;\n  }\n  .pr-xl-2,\n  .px-xl-2 {\n    padding-right: 0.5rem !important;\n  }\n  .pb-xl-2,\n  .py-xl-2 {\n    padding-bottom: 0.5rem !important;\n  }\n  .pl-xl-2,\n  .px-xl-2 {\n    padding-left: 0.5rem !important;\n  }\n  .p-xl-3 {\n    padding: 1rem !important;\n  }\n  .pt-xl-3,\n  .py-xl-3 {\n    padding-top: 1rem !important;\n  }\n  .pr-xl-3,\n  .px-xl-3 {\n    padding-right: 1rem !important;\n  }\n  .pb-xl-3,\n  .py-xl-3 {\n    padding-bottom: 1rem !important;\n  }\n  .pl-xl-3,\n  .px-xl-3 {\n    padding-left: 1rem !important;\n  }\n  .p-xl-4 {\n    padding: 1.5rem !important;\n  }\n  .pt-xl-4,\n  .py-xl-4 {\n    padding-top: 1.5rem !important;\n  }\n  .pr-xl-4,\n  .px-xl-4 {\n    padding-right: 1.5rem !important;\n  }\n  .pb-xl-4,\n  .py-xl-4 {\n    padding-bottom: 1.5rem !important;\n  }\n  .pl-xl-4,\n  .px-xl-4 {\n    padding-left: 1.5rem !important;\n  }\n  .p-xl-5 {\n    padding: 3rem !important;\n  }\n  .pt-xl-5,\n  .py-xl-5 {\n    padding-top: 3rem !important;\n  }\n  .pr-xl-5,\n  .px-xl-5 {\n    padding-right: 3rem !important;\n  }\n  .pb-xl-5,\n  .py-xl-5 {\n    padding-bottom: 3rem !important;\n  }\n  .pl-xl-5,\n  .px-xl-5 {\n    padding-left: 3rem !important;\n  }\n  .m-xl-auto {\n    margin: auto !important;\n  }\n  .mt-xl-auto,\n  .my-xl-auto {\n    margin-top: auto !important;\n  }\n  .mr-xl-auto,\n  .mx-xl-auto {\n    margin-right: auto !important;\n  }\n  .mb-xl-auto,\n  .my-xl-auto {\n    margin-bottom: auto !important;\n  }\n  .ml-xl-auto,\n  .mx-xl-auto {\n    margin-left: auto !important;\n  }\n}\n\n.text-justify {\n  text-align: justify !important;\n}\n\n.text-nowrap {\n  white-space: nowrap !important;\n}\n\n.text-truncate {\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.text-left {\n  text-align: left !important;\n}\n\n.text-right {\n  text-align: right !important;\n}\n\n.text-center {\n  text-align: center !important;\n}\n\n@media (min-width: 576px) {\n  .text-sm-left {\n    text-align: left !important;\n  }\n  .text-sm-right {\n    text-align: right !important;\n  }\n  .text-sm-center {\n    text-align: center !important;\n  }\n}\n\n@media (min-width: 768px) {\n  .text-md-left {\n    text-align: left !important;\n  }\n  .text-md-right {\n    text-align: right !important;\n  }\n  .text-md-center {\n    text-align: center !important;\n  }\n}\n\n@media (min-width: 992px) {\n  .text-lg-left {\n    text-align: left !important;\n  }\n  .text-lg-right {\n    text-align: right !important;\n  }\n  .text-lg-center {\n    text-align: center !important;\n  }\n}\n\n@media (min-width: 1200px) {\n  .text-xl-left {\n    text-align: left !important;\n  }\n  .text-xl-right {\n    text-align: right !important;\n  }\n  .text-xl-center {\n    text-align: center !important;\n  }\n}\n\n.text-lowercase {\n  text-transform: lowercase !important;\n}\n\n.text-uppercase {\n  text-transform: uppercase !important;\n}\n\n.text-capitalize {\n  text-transform: capitalize !important;\n}\n\n.font-weight-light {\n  font-weight: 300 !important;\n}\n\n.font-weight-normal {\n  font-weight: 400 !important;\n}\n\n.font-weight-bold {\n  font-weight: 700 !important;\n}\n\n.font-italic {\n  font-style: italic !important;\n}\n\n.text-white {\n  color: #fff !important;\n}\n\n.text-primary {\n  color: #007bff !important;\n}\n\na.text-primary:focus, a.text-primary:hover {\n  color: #0062cc !important;\n}\n\n.text-secondary {\n  color: #868e96 !important;\n}\n\na.text-secondary:focus, a.text-secondary:hover {\n  color: #6c757d !important;\n}\n\n.text-success {\n  color: #28a745 !important;\n}\n\na.text-success:focus, a.text-success:hover {\n  color: #1e7e34 !important;\n}\n\n.text-info {\n  color: #17a2b8 !important;\n}\n\na.text-info:focus, a.text-info:hover {\n  color: #117a8b !important;\n}\n\n.text-warning {\n  color: #ffc107 !important;\n}\n\na.text-warning:focus, a.text-warning:hover {\n  color: #d39e00 !important;\n}\n\n.text-danger {\n  color: #dc3545 !important;\n}\n\na.text-danger:focus, a.text-danger:hover {\n  color: #bd2130 !important;\n}\n\n.text-light {\n  color: #f8f9fa !important;\n}\n\na.text-light:focus, a.text-light:hover {\n  color: #dae0e5 !important;\n}\n\n.text-dark {\n  color: #343a40 !important;\n}\n\na.text-dark:focus, a.text-dark:hover {\n  color: #1d2124 !important;\n}\n\n.text-muted {\n  color: #868e96 !important;\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.visible {\n  visibility: visible !important;\n}\n\n.invisible {\n  visibility: hidden !important;\n}\n/*# sourceMappingURL=bootstrap.css.map */"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/bootstrap/js/bootstrap.bundle.js",
    "content": "/*!\n  * Bootstrap v4.0.0-beta.2 (https://getbootstrap.com)\n  * Copyright 2011-2017 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)\n  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n  */\nvar bootstrap = (function (exports,$) {\n'use strict';\n\n$ = $ && $.hasOwnProperty('default') ? $['default'] : $;\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.0.0-beta.2): util.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nvar Util = function () {\n  /**\n   * ------------------------------------------------------------------------\n   * Private TransitionEnd Helpers\n   * ------------------------------------------------------------------------\n   */\n  var transition = false;\n  var MAX_UID = 1000000;\n  var TransitionEndEvent = {\n    WebkitTransition: 'webkitTransitionEnd',\n    MozTransition: 'transitionend',\n    OTransition: 'oTransitionEnd otransitionend',\n    transition: 'transitionend' // shoutout AngusCroll (https://goo.gl/pxwQGp)\n\n  };\n\n  function toType(obj) {\n    return {}.toString.call(obj).match(/\\s([a-zA-Z]+)/)[1].toLowerCase();\n  }\n\n  function getSpecialTransitionEndEvent() {\n    return {\n      bindType: transition.end,\n      delegateType: transition.end,\n      handle: function handle(event) {\n        if ($(event.target).is(this)) {\n          return event.handleObj.handler.apply(this, arguments); // eslint-disable-line prefer-rest-params\n        }\n\n        return undefined; // eslint-disable-line no-undefined\n      }\n    };\n  }\n\n  function transitionEndTest() {\n    if (window.QUnit) {\n      return false;\n    }\n\n    var el = document.createElement('bootstrap');\n\n    for (var name in TransitionEndEvent) {\n      if (typeof el.style[name] !== 'undefined') {\n        return {\n          end: TransitionEndEvent[name]\n        };\n      }\n    }\n\n    return false;\n  }\n\n  function transitionEndEmulator(duration) {\n    var _this = this;\n\n    var called = false;\n    $(this).one(Util.TRANSITION_END, function () {\n      called = true;\n    });\n    setTimeout(function () {\n      if (!called) {\n        Util.triggerTransitionEnd(_this);\n      }\n    }, duration);\n    return this;\n  }\n\n  function setTransitionEndSupport() {\n    transition = transitionEndTest();\n    $.fn.emulateTransitionEnd = transitionEndEmulator;\n\n    if (Util.supportsTransitionEnd()) {\n      $.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent();\n    }\n  }\n  /**\n   * --------------------------------------------------------------------------\n   * Public Util Api\n   * --------------------------------------------------------------------------\n   */\n\n\n  var Util = {\n    TRANSITION_END: 'bsTransitionEnd',\n    getUID: function getUID(prefix) {\n      do {\n        // eslint-disable-next-line no-bitwise\n        prefix += ~~(Math.random() * MAX_UID); // \"~~\" acts like a faster Math.floor() here\n      } while (document.getElementById(prefix));\n\n      return prefix;\n    },\n    getSelectorFromElement: function getSelectorFromElement(element) {\n      var selector = element.getAttribute('data-target');\n\n      if (!selector || selector === '#') {\n        selector = element.getAttribute('href') || '';\n      }\n\n      try {\n        var $selector = $(document).find(selector);\n        return $selector.length > 0 ? selector : null;\n      } catch (error) {\n        return null;\n      }\n    },\n    reflow: function reflow(element) {\n      return element.offsetHeight;\n    },\n    triggerTransitionEnd: function triggerTransitionEnd(element) {\n      $(element).trigger(transition.end);\n    },\n    supportsTransitionEnd: function supportsTransitionEnd() {\n      return Boolean(transition);\n    },\n    isElement: function isElement(obj) {\n      return (obj[0] || obj).nodeType;\n    },\n    typeCheckConfig: function typeCheckConfig(componentName, config, configTypes) {\n      for (var property in configTypes) {\n        if (Object.prototype.hasOwnProperty.call(configTypes, property)) {\n          var expectedTypes = configTypes[property];\n          var value = config[property];\n          var valueType = value && Util.isElement(value) ? 'element' : toType(value);\n\n          if (!new RegExp(expectedTypes).test(valueType)) {\n            throw new Error(componentName.toUpperCase() + \": \" + (\"Option \\\"\" + property + \"\\\" provided type \\\"\" + valueType + \"\\\" \") + (\"but expected type \\\"\" + expectedTypes + \"\\\".\"));\n          }\n        }\n      }\n    }\n  };\n  setTransitionEndSupport();\n  return Util;\n}($);\n\nfunction _defineProperties(target, props) {\n  for (var i = 0; i < props.length; i++) {\n    var descriptor = props[i];\n    descriptor.enumerable = descriptor.enumerable || false;\n    descriptor.configurable = true;\n    if (\"value\" in descriptor) descriptor.writable = true;\n    Object.defineProperty(target, descriptor.key, descriptor);\n  }\n}\n\nfunction _createClass(Constructor, protoProps, staticProps) {\n  if (protoProps) _defineProperties(Constructor.prototype, protoProps);\n  if (staticProps) _defineProperties(Constructor, staticProps);\n  return Constructor;\n}\n\nvar createClass = _createClass;\n\nfunction _inheritsLoose(subClass, superClass) {\n  subClass.prototype = Object.create(superClass.prototype);\n  subClass.prototype.constructor = subClass;\n  subClass.__proto__ = superClass;\n}\n\nvar inheritsLoose = _inheritsLoose;\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.0.0-beta.2): alert.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nvar Alert = function () {\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n  var NAME = 'alert';\n  var VERSION = '4.0.0-beta.2';\n  var DATA_KEY = 'bs.alert';\n  var EVENT_KEY = \".\" + DATA_KEY;\n  var DATA_API_KEY = '.data-api';\n  var JQUERY_NO_CONFLICT = $.fn[NAME];\n  var TRANSITION_DURATION = 150;\n  var Selector = {\n    DISMISS: '[data-dismiss=\"alert\"]'\n  };\n  var Event = {\n    CLOSE: \"close\" + EVENT_KEY,\n    CLOSED: \"closed\" + EVENT_KEY,\n    CLICK_DATA_API: \"click\" + EVENT_KEY + DATA_API_KEY\n  };\n  var ClassName = {\n    ALERT: 'alert',\n    FADE: 'fade',\n    SHOW: 'show'\n    /**\n     * ------------------------------------------------------------------------\n     * Class Definition\n     * ------------------------------------------------------------------------\n     */\n\n  };\n\n  var Alert =\n  /*#__PURE__*/\n  function () {\n    function Alert(element) {\n      this._element = element;\n    } // getters\n\n\n    var _proto = Alert.prototype;\n\n    // public\n    _proto.close = function close(element) {\n      element = element || this._element;\n\n      var rootElement = this._getRootElement(element);\n\n      var customEvent = this._triggerCloseEvent(rootElement);\n\n      if (customEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      this._removeElement(rootElement);\n    };\n\n    _proto.dispose = function dispose() {\n      $.removeData(this._element, DATA_KEY);\n      this._element = null;\n    }; // private\n\n\n    _proto._getRootElement = function _getRootElement(element) {\n      var selector = Util.getSelectorFromElement(element);\n      var parent = false;\n\n      if (selector) {\n        parent = $(selector)[0];\n      }\n\n      if (!parent) {\n        parent = $(element).closest(\".\" + ClassName.ALERT)[0];\n      }\n\n      return parent;\n    };\n\n    _proto._triggerCloseEvent = function _triggerCloseEvent(element) {\n      var closeEvent = $.Event(Event.CLOSE);\n      $(element).trigger(closeEvent);\n      return closeEvent;\n    };\n\n    _proto._removeElement = function _removeElement(element) {\n      var _this = this;\n\n      $(element).removeClass(ClassName.SHOW);\n\n      if (!Util.supportsTransitionEnd() || !$(element).hasClass(ClassName.FADE)) {\n        this._destroyElement(element);\n\n        return;\n      }\n\n      $(element).one(Util.TRANSITION_END, function (event) {\n        return _this._destroyElement(element, event);\n      }).emulateTransitionEnd(TRANSITION_DURATION);\n    };\n\n    _proto._destroyElement = function _destroyElement(element) {\n      $(element).detach().trigger(Event.CLOSED).remove();\n    }; // static\n\n\n    Alert._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var $element = $(this);\n        var data = $element.data(DATA_KEY);\n\n        if (!data) {\n          data = new Alert(this);\n          $element.data(DATA_KEY, data);\n        }\n\n        if (config === 'close') {\n          data[config](this);\n        }\n      });\n    };\n\n    Alert._handleDismiss = function _handleDismiss(alertInstance) {\n      return function (event) {\n        if (event) {\n          event.preventDefault();\n        }\n\n        alertInstance.close(this);\n      };\n    };\n\n    createClass(Alert, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION;\n      }\n    }]);\n    return Alert;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  $(document).on(Event.CLICK_DATA_API, Selector.DISMISS, Alert._handleDismiss(new Alert()));\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n  $.fn[NAME] = Alert._jQueryInterface;\n  $.fn[NAME].Constructor = Alert;\n\n  $.fn[NAME].noConflict = function () {\n    $.fn[NAME] = JQUERY_NO_CONFLICT;\n    return Alert._jQueryInterface;\n  };\n\n  return Alert;\n}($);\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.0.0-beta.2): button.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nvar Button = function () {\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n  var NAME = 'button';\n  var VERSION = '4.0.0-beta.2';\n  var DATA_KEY = 'bs.button';\n  var EVENT_KEY = \".\" + DATA_KEY;\n  var DATA_API_KEY = '.data-api';\n  var JQUERY_NO_CONFLICT = $.fn[NAME];\n  var ClassName = {\n    ACTIVE: 'active',\n    BUTTON: 'btn',\n    FOCUS: 'focus'\n  };\n  var Selector = {\n    DATA_TOGGLE_CARROT: '[data-toggle^=\"button\"]',\n    DATA_TOGGLE: '[data-toggle=\"buttons\"]',\n    INPUT: 'input',\n    ACTIVE: '.active',\n    BUTTON: '.btn'\n  };\n  var Event = {\n    CLICK_DATA_API: \"click\" + EVENT_KEY + DATA_API_KEY,\n    FOCUS_BLUR_DATA_API: \"focus\" + EVENT_KEY + DATA_API_KEY + \" \" + (\"blur\" + EVENT_KEY + DATA_API_KEY)\n    /**\n     * ------------------------------------------------------------------------\n     * Class Definition\n     * ------------------------------------------------------------------------\n     */\n\n  };\n\n  var Button =\n  /*#__PURE__*/\n  function () {\n    function Button(element) {\n      this._element = element;\n    } // getters\n\n\n    var _proto = Button.prototype;\n\n    // public\n    _proto.toggle = function toggle() {\n      var triggerChangeEvent = true;\n      var addAriaPressed = true;\n      var rootElement = $(this._element).closest(Selector.DATA_TOGGLE)[0];\n\n      if (rootElement) {\n        var input = $(this._element).find(Selector.INPUT)[0];\n\n        if (input) {\n          if (input.type === 'radio') {\n            if (input.checked && $(this._element).hasClass(ClassName.ACTIVE)) {\n              triggerChangeEvent = false;\n            } else {\n              var activeElement = $(rootElement).find(Selector.ACTIVE)[0];\n\n              if (activeElement) {\n                $(activeElement).removeClass(ClassName.ACTIVE);\n              }\n            }\n          }\n\n          if (triggerChangeEvent) {\n            if (input.hasAttribute('disabled') || rootElement.hasAttribute('disabled') || input.classList.contains('disabled') || rootElement.classList.contains('disabled')) {\n              return;\n            }\n\n            input.checked = !$(this._element).hasClass(ClassName.ACTIVE);\n            $(input).trigger('change');\n          }\n\n          input.focus();\n          addAriaPressed = false;\n        }\n      }\n\n      if (addAriaPressed) {\n        this._element.setAttribute('aria-pressed', !$(this._element).hasClass(ClassName.ACTIVE));\n      }\n\n      if (triggerChangeEvent) {\n        $(this._element).toggleClass(ClassName.ACTIVE);\n      }\n    };\n\n    _proto.dispose = function dispose() {\n      $.removeData(this._element, DATA_KEY);\n      this._element = null;\n    }; // static\n\n\n    Button._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var data = $(this).data(DATA_KEY);\n\n        if (!data) {\n          data = new Button(this);\n          $(this).data(DATA_KEY, data);\n        }\n\n        if (config === 'toggle') {\n          data[config]();\n        }\n      });\n    };\n\n    createClass(Button, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION;\n      }\n    }]);\n    return Button;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE_CARROT, function (event) {\n    event.preventDefault();\n    var button = event.target;\n\n    if (!$(button).hasClass(ClassName.BUTTON)) {\n      button = $(button).closest(Selector.BUTTON);\n    }\n\n    Button._jQueryInterface.call($(button), 'toggle');\n  }).on(Event.FOCUS_BLUR_DATA_API, Selector.DATA_TOGGLE_CARROT, function (event) {\n    var button = $(event.target).closest(Selector.BUTTON)[0];\n    $(button).toggleClass(ClassName.FOCUS, /^focus(in)?$/.test(event.type));\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n  $.fn[NAME] = Button._jQueryInterface;\n  $.fn[NAME].Constructor = Button;\n\n  $.fn[NAME].noConflict = function () {\n    $.fn[NAME] = JQUERY_NO_CONFLICT;\n    return Button._jQueryInterface;\n  };\n\n  return Button;\n}($);\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.0.0-beta.2): carousel.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nvar Carousel = function () {\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n  var NAME = 'carousel';\n  var VERSION = '4.0.0-beta.2';\n  var DATA_KEY = 'bs.carousel';\n  var EVENT_KEY = \".\" + DATA_KEY;\n  var DATA_API_KEY = '.data-api';\n  var JQUERY_NO_CONFLICT = $.fn[NAME];\n  var TRANSITION_DURATION = 600;\n  var ARROW_LEFT_KEYCODE = 37; // KeyboardEvent.which value for left arrow key\n\n  var ARROW_RIGHT_KEYCODE = 39; // KeyboardEvent.which value for right arrow key\n\n  var TOUCHEVENT_COMPAT_WAIT = 500; // Time for mouse compat events to fire after touch\n\n  var Default = {\n    interval: 5000,\n    keyboard: true,\n    slide: false,\n    pause: 'hover',\n    wrap: true\n  };\n  var DefaultType = {\n    interval: '(number|boolean)',\n    keyboard: 'boolean',\n    slide: '(boolean|string)',\n    pause: '(string|boolean)',\n    wrap: 'boolean'\n  };\n  var Direction = {\n    NEXT: 'next',\n    PREV: 'prev',\n    LEFT: 'left',\n    RIGHT: 'right'\n  };\n  var Event = {\n    SLIDE: \"slide\" + EVENT_KEY,\n    SLID: \"slid\" + EVENT_KEY,\n    KEYDOWN: \"keydown\" + EVENT_KEY,\n    MOUSEENTER: \"mouseenter\" + EVENT_KEY,\n    MOUSELEAVE: \"mouseleave\" + EVENT_KEY,\n    TOUCHEND: \"touchend\" + EVENT_KEY,\n    LOAD_DATA_API: \"load\" + EVENT_KEY + DATA_API_KEY,\n    CLICK_DATA_API: \"click\" + EVENT_KEY + DATA_API_KEY\n  };\n  var ClassName = {\n    CAROUSEL: 'carousel',\n    ACTIVE: 'active',\n    SLIDE: 'slide',\n    RIGHT: 'carousel-item-right',\n    LEFT: 'carousel-item-left',\n    NEXT: 'carousel-item-next',\n    PREV: 'carousel-item-prev',\n    ITEM: 'carousel-item'\n  };\n  var Selector = {\n    ACTIVE: '.active',\n    ACTIVE_ITEM: '.active.carousel-item',\n    ITEM: '.carousel-item',\n    NEXT_PREV: '.carousel-item-next, .carousel-item-prev',\n    INDICATORS: '.carousel-indicators',\n    DATA_SLIDE: '[data-slide], [data-slide-to]',\n    DATA_RIDE: '[data-ride=\"carousel\"]'\n    /**\n     * ------------------------------------------------------------------------\n     * Class Definition\n     * ------------------------------------------------------------------------\n     */\n\n  };\n\n  var Carousel =\n  /*#__PURE__*/\n  function () {\n    function Carousel(element, config) {\n      this._items = null;\n      this._interval = null;\n      this._activeElement = null;\n      this._isPaused = false;\n      this._isSliding = false;\n      this.touchTimeout = null;\n      this._config = this._getConfig(config);\n      this._element = $(element)[0];\n      this._indicatorsElement = $(this._element).find(Selector.INDICATORS)[0];\n\n      this._addEventListeners();\n    } // getters\n\n\n    var _proto = Carousel.prototype;\n\n    // public\n    _proto.next = function next() {\n      if (!this._isSliding) {\n        this._slide(Direction.NEXT);\n      }\n    };\n\n    _proto.nextWhenVisible = function nextWhenVisible() {\n      // Don't call next when the page isn't visible\n      // or the carousel or its parent isn't visible\n      if (!document.hidden && $(this._element).is(':visible') && $(this._element).css('visibility') !== 'hidden') {\n        this.next();\n      }\n    };\n\n    _proto.prev = function prev() {\n      if (!this._isSliding) {\n        this._slide(Direction.PREV);\n      }\n    };\n\n    _proto.pause = function pause(event) {\n      if (!event) {\n        this._isPaused = true;\n      }\n\n      if ($(this._element).find(Selector.NEXT_PREV)[0] && Util.supportsTransitionEnd()) {\n        Util.triggerTransitionEnd(this._element);\n        this.cycle(true);\n      }\n\n      clearInterval(this._interval);\n      this._interval = null;\n    };\n\n    _proto.cycle = function cycle(event) {\n      if (!event) {\n        this._isPaused = false;\n      }\n\n      if (this._interval) {\n        clearInterval(this._interval);\n        this._interval = null;\n      }\n\n      if (this._config.interval && !this._isPaused) {\n        this._interval = setInterval((document.visibilityState ? this.nextWhenVisible : this.next).bind(this), this._config.interval);\n      }\n    };\n\n    _proto.to = function to(index) {\n      var _this = this;\n\n      this._activeElement = $(this._element).find(Selector.ACTIVE_ITEM)[0];\n\n      var activeIndex = this._getItemIndex(this._activeElement);\n\n      if (index > this._items.length - 1 || index < 0) {\n        return;\n      }\n\n      if (this._isSliding) {\n        $(this._element).one(Event.SLID, function () {\n          return _this.to(index);\n        });\n        return;\n      }\n\n      if (activeIndex === index) {\n        this.pause();\n        this.cycle();\n        return;\n      }\n\n      var direction = index > activeIndex ? Direction.NEXT : Direction.PREV;\n\n      this._slide(direction, this._items[index]);\n    };\n\n    _proto.dispose = function dispose() {\n      $(this._element).off(EVENT_KEY);\n      $.removeData(this._element, DATA_KEY);\n      this._items = null;\n      this._config = null;\n      this._element = null;\n      this._interval = null;\n      this._isPaused = null;\n      this._isSliding = null;\n      this._activeElement = null;\n      this._indicatorsElement = null;\n    }; // private\n\n\n    _proto._getConfig = function _getConfig(config) {\n      config = $.extend({}, Default, config);\n      Util.typeCheckConfig(NAME, config, DefaultType);\n      return config;\n    };\n\n    _proto._addEventListeners = function _addEventListeners() {\n      var _this2 = this;\n\n      if (this._config.keyboard) {\n        $(this._element).on(Event.KEYDOWN, function (event) {\n          return _this2._keydown(event);\n        });\n      }\n\n      if (this._config.pause === 'hover') {\n        $(this._element).on(Event.MOUSEENTER, function (event) {\n          return _this2.pause(event);\n        }).on(Event.MOUSELEAVE, function (event) {\n          return _this2.cycle(event);\n        });\n\n        if ('ontouchstart' in document.documentElement) {\n          // if it's a touch-enabled device, mouseenter/leave are fired as\n          // part of the mouse compatibility events on first tap - the carousel\n          // would stop cycling until user tapped out of it;\n          // here, we listen for touchend, explicitly pause the carousel\n          // (as if it's the second time we tap on it, mouseenter compat event\n          // is NOT fired) and after a timeout (to allow for mouse compatibility\n          // events to fire) we explicitly restart cycling\n          $(this._element).on(Event.TOUCHEND, function () {\n            _this2.pause();\n\n            if (_this2.touchTimeout) {\n              clearTimeout(_this2.touchTimeout);\n            }\n\n            _this2.touchTimeout = setTimeout(function (event) {\n              return _this2.cycle(event);\n            }, TOUCHEVENT_COMPAT_WAIT + _this2._config.interval);\n          });\n        }\n      }\n    };\n\n    _proto._keydown = function _keydown(event) {\n      if (/input|textarea/i.test(event.target.tagName)) {\n        return;\n      }\n\n      switch (event.which) {\n        case ARROW_LEFT_KEYCODE:\n          event.preventDefault();\n          this.prev();\n          break;\n\n        case ARROW_RIGHT_KEYCODE:\n          event.preventDefault();\n          this.next();\n          break;\n\n        default:\n          return;\n      }\n    };\n\n    _proto._getItemIndex = function _getItemIndex(element) {\n      this._items = $.makeArray($(element).parent().find(Selector.ITEM));\n      return this._items.indexOf(element);\n    };\n\n    _proto._getItemByDirection = function _getItemByDirection(direction, activeElement) {\n      var isNextDirection = direction === Direction.NEXT;\n      var isPrevDirection = direction === Direction.PREV;\n\n      var activeIndex = this._getItemIndex(activeElement);\n\n      var lastItemIndex = this._items.length - 1;\n      var isGoingToWrap = isPrevDirection && activeIndex === 0 || isNextDirection && activeIndex === lastItemIndex;\n\n      if (isGoingToWrap && !this._config.wrap) {\n        return activeElement;\n      }\n\n      var delta = direction === Direction.PREV ? -1 : 1;\n      var itemIndex = (activeIndex + delta) % this._items.length;\n      return itemIndex === -1 ? this._items[this._items.length - 1] : this._items[itemIndex];\n    };\n\n    _proto._triggerSlideEvent = function _triggerSlideEvent(relatedTarget, eventDirectionName) {\n      var targetIndex = this._getItemIndex(relatedTarget);\n\n      var fromIndex = this._getItemIndex($(this._element).find(Selector.ACTIVE_ITEM)[0]);\n\n      var slideEvent = $.Event(Event.SLIDE, {\n        relatedTarget: relatedTarget,\n        direction: eventDirectionName,\n        from: fromIndex,\n        to: targetIndex\n      });\n      $(this._element).trigger(slideEvent);\n      return slideEvent;\n    };\n\n    _proto._setActiveIndicatorElement = function _setActiveIndicatorElement(element) {\n      if (this._indicatorsElement) {\n        $(this._indicatorsElement).find(Selector.ACTIVE).removeClass(ClassName.ACTIVE);\n\n        var nextIndicator = this._indicatorsElement.children[this._getItemIndex(element)];\n\n        if (nextIndicator) {\n          $(nextIndicator).addClass(ClassName.ACTIVE);\n        }\n      }\n    };\n\n    _proto._slide = function _slide(direction, element) {\n      var _this3 = this;\n\n      var activeElement = $(this._element).find(Selector.ACTIVE_ITEM)[0];\n\n      var activeElementIndex = this._getItemIndex(activeElement);\n\n      var nextElement = element || activeElement && this._getItemByDirection(direction, activeElement);\n\n      var nextElementIndex = this._getItemIndex(nextElement);\n\n      var isCycling = Boolean(this._interval);\n      var directionalClassName;\n      var orderClassName;\n      var eventDirectionName;\n\n      if (direction === Direction.NEXT) {\n        directionalClassName = ClassName.LEFT;\n        orderClassName = ClassName.NEXT;\n        eventDirectionName = Direction.LEFT;\n      } else {\n        directionalClassName = ClassName.RIGHT;\n        orderClassName = ClassName.PREV;\n        eventDirectionName = Direction.RIGHT;\n      }\n\n      if (nextElement && $(nextElement).hasClass(ClassName.ACTIVE)) {\n        this._isSliding = false;\n        return;\n      }\n\n      var slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName);\n\n      if (slideEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      if (!activeElement || !nextElement) {\n        // some weirdness is happening, so we bail\n        return;\n      }\n\n      this._isSliding = true;\n\n      if (isCycling) {\n        this.pause();\n      }\n\n      this._setActiveIndicatorElement(nextElement);\n\n      var slidEvent = $.Event(Event.SLID, {\n        relatedTarget: nextElement,\n        direction: eventDirectionName,\n        from: activeElementIndex,\n        to: nextElementIndex\n      });\n\n      if (Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.SLIDE)) {\n        $(nextElement).addClass(orderClassName);\n        Util.reflow(nextElement);\n        $(activeElement).addClass(directionalClassName);\n        $(nextElement).addClass(directionalClassName);\n        $(activeElement).one(Util.TRANSITION_END, function () {\n          $(nextElement).removeClass(directionalClassName + \" \" + orderClassName).addClass(ClassName.ACTIVE);\n          $(activeElement).removeClass(ClassName.ACTIVE + \" \" + orderClassName + \" \" + directionalClassName);\n          _this3._isSliding = false;\n          setTimeout(function () {\n            return $(_this3._element).trigger(slidEvent);\n          }, 0);\n        }).emulateTransitionEnd(TRANSITION_DURATION);\n      } else {\n        $(activeElement).removeClass(ClassName.ACTIVE);\n        $(nextElement).addClass(ClassName.ACTIVE);\n        this._isSliding = false;\n        $(this._element).trigger(slidEvent);\n      }\n\n      if (isCycling) {\n        this.cycle();\n      }\n    }; // static\n\n\n    Carousel._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var data = $(this).data(DATA_KEY);\n\n        var _config = $.extend({}, Default, $(this).data());\n\n        if (typeof config === 'object') {\n          $.extend(_config, config);\n        }\n\n        var action = typeof config === 'string' ? config : _config.slide;\n\n        if (!data) {\n          data = new Carousel(this, _config);\n          $(this).data(DATA_KEY, data);\n        }\n\n        if (typeof config === 'number') {\n          data.to(config);\n        } else if (typeof action === 'string') {\n          if (typeof data[action] === 'undefined') {\n            throw new Error(\"No method named \\\"\" + action + \"\\\"\");\n          }\n\n          data[action]();\n        } else if (_config.interval) {\n          data.pause();\n          data.cycle();\n        }\n      });\n    };\n\n    Carousel._dataApiClickHandler = function _dataApiClickHandler(event) {\n      var selector = Util.getSelectorFromElement(this);\n\n      if (!selector) {\n        return;\n      }\n\n      var target = $(selector)[0];\n\n      if (!target || !$(target).hasClass(ClassName.CAROUSEL)) {\n        return;\n      }\n\n      var config = $.extend({}, $(target).data(), $(this).data());\n      var slideIndex = this.getAttribute('data-slide-to');\n\n      if (slideIndex) {\n        config.interval = false;\n      }\n\n      Carousel._jQueryInterface.call($(target), config);\n\n      if (slideIndex) {\n        $(target).data(DATA_KEY).to(slideIndex);\n      }\n\n      event.preventDefault();\n    };\n\n    createClass(Carousel, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION;\n      }\n    }, {\n      key: \"Default\",\n      get: function get() {\n        return Default;\n      }\n    }]);\n    return Carousel;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  $(document).on(Event.CLICK_DATA_API, Selector.DATA_SLIDE, Carousel._dataApiClickHandler);\n  $(window).on(Event.LOAD_DATA_API, function () {\n    $(Selector.DATA_RIDE).each(function () {\n      var $carousel = $(this);\n\n      Carousel._jQueryInterface.call($carousel, $carousel.data());\n    });\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n  $.fn[NAME] = Carousel._jQueryInterface;\n  $.fn[NAME].Constructor = Carousel;\n\n  $.fn[NAME].noConflict = function () {\n    $.fn[NAME] = JQUERY_NO_CONFLICT;\n    return Carousel._jQueryInterface;\n  };\n\n  return Carousel;\n}($);\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.0.0-beta.2): collapse.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nvar Collapse = function () {\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n  var NAME = 'collapse';\n  var VERSION = '4.0.0-beta.2';\n  var DATA_KEY = 'bs.collapse';\n  var EVENT_KEY = \".\" + DATA_KEY;\n  var DATA_API_KEY = '.data-api';\n  var JQUERY_NO_CONFLICT = $.fn[NAME];\n  var TRANSITION_DURATION = 600;\n  var Default = {\n    toggle: true,\n    parent: ''\n  };\n  var DefaultType = {\n    toggle: 'boolean',\n    parent: '(string|element)'\n  };\n  var Event = {\n    SHOW: \"show\" + EVENT_KEY,\n    SHOWN: \"shown\" + EVENT_KEY,\n    HIDE: \"hide\" + EVENT_KEY,\n    HIDDEN: \"hidden\" + EVENT_KEY,\n    CLICK_DATA_API: \"click\" + EVENT_KEY + DATA_API_KEY\n  };\n  var ClassName = {\n    SHOW: 'show',\n    COLLAPSE: 'collapse',\n    COLLAPSING: 'collapsing',\n    COLLAPSED: 'collapsed'\n  };\n  var Dimension = {\n    WIDTH: 'width',\n    HEIGHT: 'height'\n  };\n  var Selector = {\n    ACTIVES: '.show, .collapsing',\n    DATA_TOGGLE: '[data-toggle=\"collapse\"]'\n    /**\n     * ------------------------------------------------------------------------\n     * Class Definition\n     * ------------------------------------------------------------------------\n     */\n\n  };\n\n  var Collapse =\n  /*#__PURE__*/\n  function () {\n    function Collapse(element, config) {\n      this._isTransitioning = false;\n      this._element = element;\n      this._config = this._getConfig(config);\n      this._triggerArray = $.makeArray($(\"[data-toggle=\\\"collapse\\\"][href=\\\"#\" + element.id + \"\\\"],\" + (\"[data-toggle=\\\"collapse\\\"][data-target=\\\"#\" + element.id + \"\\\"]\")));\n      var tabToggles = $(Selector.DATA_TOGGLE);\n\n      for (var i = 0; i < tabToggles.length; i++) {\n        var elem = tabToggles[i];\n        var selector = Util.getSelectorFromElement(elem);\n\n        if (selector !== null && $(selector).filter(element).length > 0) {\n          this._triggerArray.push(elem);\n        }\n      }\n\n      this._parent = this._config.parent ? this._getParent() : null;\n\n      if (!this._config.parent) {\n        this._addAriaAndCollapsedClass(this._element, this._triggerArray);\n      }\n\n      if (this._config.toggle) {\n        this.toggle();\n      }\n    } // getters\n\n\n    var _proto = Collapse.prototype;\n\n    // public\n    _proto.toggle = function toggle() {\n      if ($(this._element).hasClass(ClassName.SHOW)) {\n        this.hide();\n      } else {\n        this.show();\n      }\n    };\n\n    _proto.show = function show() {\n      var _this = this;\n\n      if (this._isTransitioning || $(this._element).hasClass(ClassName.SHOW)) {\n        return;\n      }\n\n      var actives;\n      var activesData;\n\n      if (this._parent) {\n        actives = $.makeArray($(this._parent).children().children(Selector.ACTIVES));\n\n        if (!actives.length) {\n          actives = null;\n        }\n      }\n\n      if (actives) {\n        activesData = $(actives).data(DATA_KEY);\n\n        if (activesData && activesData._isTransitioning) {\n          return;\n        }\n      }\n\n      var startEvent = $.Event(Event.SHOW);\n      $(this._element).trigger(startEvent);\n\n      if (startEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      if (actives) {\n        Collapse._jQueryInterface.call($(actives), 'hide');\n\n        if (!activesData) {\n          $(actives).data(DATA_KEY, null);\n        }\n      }\n\n      var dimension = this._getDimension();\n\n      $(this._element).removeClass(ClassName.COLLAPSE).addClass(ClassName.COLLAPSING);\n      this._element.style[dimension] = 0;\n\n      if (this._triggerArray.length) {\n        $(this._triggerArray).removeClass(ClassName.COLLAPSED).attr('aria-expanded', true);\n      }\n\n      this.setTransitioning(true);\n\n      var complete = function complete() {\n        $(_this._element).removeClass(ClassName.COLLAPSING).addClass(ClassName.COLLAPSE).addClass(ClassName.SHOW);\n        _this._element.style[dimension] = '';\n\n        _this.setTransitioning(false);\n\n        $(_this._element).trigger(Event.SHOWN);\n      };\n\n      if (!Util.supportsTransitionEnd()) {\n        complete();\n        return;\n      }\n\n      var capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1);\n      var scrollSize = \"scroll\" + capitalizedDimension;\n      $(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION);\n      this._element.style[dimension] = this._element[scrollSize] + \"px\";\n    };\n\n    _proto.hide = function hide() {\n      var _this2 = this;\n\n      if (this._isTransitioning || !$(this._element).hasClass(ClassName.SHOW)) {\n        return;\n      }\n\n      var startEvent = $.Event(Event.HIDE);\n      $(this._element).trigger(startEvent);\n\n      if (startEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      var dimension = this._getDimension();\n\n      this._element.style[dimension] = this._element.getBoundingClientRect()[dimension] + \"px\";\n      Util.reflow(this._element);\n      $(this._element).addClass(ClassName.COLLAPSING).removeClass(ClassName.COLLAPSE).removeClass(ClassName.SHOW);\n\n      if (this._triggerArray.length) {\n        for (var i = 0; i < this._triggerArray.length; i++) {\n          var trigger = this._triggerArray[i];\n          var selector = Util.getSelectorFromElement(trigger);\n\n          if (selector !== null) {\n            var $elem = $(selector);\n\n            if (!$elem.hasClass(ClassName.SHOW)) {\n              $(trigger).addClass(ClassName.COLLAPSED).attr('aria-expanded', false);\n            }\n          }\n        }\n      }\n\n      this.setTransitioning(true);\n\n      var complete = function complete() {\n        _this2.setTransitioning(false);\n\n        $(_this2._element).removeClass(ClassName.COLLAPSING).addClass(ClassName.COLLAPSE).trigger(Event.HIDDEN);\n      };\n\n      this._element.style[dimension] = '';\n\n      if (!Util.supportsTransitionEnd()) {\n        complete();\n        return;\n      }\n\n      $(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION);\n    };\n\n    _proto.setTransitioning = function setTransitioning(isTransitioning) {\n      this._isTransitioning = isTransitioning;\n    };\n\n    _proto.dispose = function dispose() {\n      $.removeData(this._element, DATA_KEY);\n      this._config = null;\n      this._parent = null;\n      this._element = null;\n      this._triggerArray = null;\n      this._isTransitioning = null;\n    }; // private\n\n\n    _proto._getConfig = function _getConfig(config) {\n      config = $.extend({}, Default, config);\n      config.toggle = Boolean(config.toggle); // coerce string values\n\n      Util.typeCheckConfig(NAME, config, DefaultType);\n      return config;\n    };\n\n    _proto._getDimension = function _getDimension() {\n      var hasWidth = $(this._element).hasClass(Dimension.WIDTH);\n      return hasWidth ? Dimension.WIDTH : Dimension.HEIGHT;\n    };\n\n    _proto._getParent = function _getParent() {\n      var _this3 = this;\n\n      var parent = null;\n\n      if (Util.isElement(this._config.parent)) {\n        parent = this._config.parent; // it's a jQuery object\n\n        if (typeof this._config.parent.jquery !== 'undefined') {\n          parent = this._config.parent[0];\n        }\n      } else {\n        parent = $(this._config.parent)[0];\n      }\n\n      var selector = \"[data-toggle=\\\"collapse\\\"][data-parent=\\\"\" + this._config.parent + \"\\\"]\";\n      $(parent).find(selector).each(function (i, element) {\n        _this3._addAriaAndCollapsedClass(Collapse._getTargetFromElement(element), [element]);\n      });\n      return parent;\n    };\n\n    _proto._addAriaAndCollapsedClass = function _addAriaAndCollapsedClass(element, triggerArray) {\n      if (element) {\n        var isOpen = $(element).hasClass(ClassName.SHOW);\n\n        if (triggerArray.length) {\n          $(triggerArray).toggleClass(ClassName.COLLAPSED, !isOpen).attr('aria-expanded', isOpen);\n        }\n      }\n    }; // static\n\n\n    Collapse._getTargetFromElement = function _getTargetFromElement(element) {\n      var selector = Util.getSelectorFromElement(element);\n      return selector ? $(selector)[0] : null;\n    };\n\n    Collapse._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var $this = $(this);\n        var data = $this.data(DATA_KEY);\n\n        var _config = $.extend({}, Default, $this.data(), typeof config === 'object' && config);\n\n        if (!data && _config.toggle && /show|hide/.test(config)) {\n          _config.toggle = false;\n        }\n\n        if (!data) {\n          data = new Collapse(this, _config);\n          $this.data(DATA_KEY, data);\n        }\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new Error(\"No method named \\\"\" + config + \"\\\"\");\n          }\n\n          data[config]();\n        }\n      });\n    };\n\n    createClass(Collapse, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION;\n      }\n    }, {\n      key: \"Default\",\n      get: function get() {\n        return Default;\n      }\n    }]);\n    return Collapse;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {\n    // preventDefault only for <a> elements (which change the URL) not inside the collapsible element\n    if (event.currentTarget.tagName === 'A') {\n      event.preventDefault();\n    }\n\n    var $trigger = $(this);\n    var selector = Util.getSelectorFromElement(this);\n    $(selector).each(function () {\n      var $target = $(this);\n      var data = $target.data(DATA_KEY);\n      var config = data ? 'toggle' : $trigger.data();\n\n      Collapse._jQueryInterface.call($target, config);\n    });\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n  $.fn[NAME] = Collapse._jQueryInterface;\n  $.fn[NAME].Constructor = Collapse;\n\n  $.fn[NAME].noConflict = function () {\n    $.fn[NAME] = JQUERY_NO_CONFLICT;\n    return Collapse._jQueryInterface;\n  };\n\n  return Collapse;\n}($);\n\n/**!\n * @fileOverview Kickass library to create and place poppers near their reference elements.\n * @version 1.12.5\n * @license\n * Copyright (c) 2016 Federico Zivolo and contributors\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 all\n * 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 THE\n * SOFTWARE.\n */\nvar nativeHints = ['native code', '[object MutationObserverConstructor]'];\n\n/**\n * Determine if a function is implemented natively (as opposed to a polyfill).\n * @method\n * @memberof Popper.Utils\n * @argument {Function | undefined} fn the function to check\n * @returns {Boolean}\n */\nvar isNative = (function (fn) {\n  return nativeHints.some(function (hint) {\n    return (fn || '').toString().indexOf(hint) > -1;\n  });\n});\n\nvar isBrowser = typeof window !== 'undefined';\nvar longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox'];\nvar timeoutDuration = 0;\nfor (var i = 0; i < longerTimeoutBrowsers.length; i += 1) {\n  if (isBrowser && navigator.userAgent.indexOf(longerTimeoutBrowsers[i]) >= 0) {\n    timeoutDuration = 1;\n    break;\n  }\n}\n\nfunction microtaskDebounce(fn) {\n  var scheduled = false;\n  var i = 0;\n  var elem = document.createElement('span');\n\n  // MutationObserver provides a mechanism for scheduling microtasks, which\n  // are scheduled *before* the next task. This gives us a way to debounce\n  // a function but ensure it's called *before* the next paint.\n  var observer = new MutationObserver(function () {\n    fn();\n    scheduled = false;\n  });\n\n  observer.observe(elem, { attributes: true });\n\n  return function () {\n    if (!scheduled) {\n      scheduled = true;\n      elem.setAttribute('x-index', i);\n      i = i + 1; // don't use compund (+=) because it doesn't get optimized in V8\n    }\n  };\n}\n\nfunction taskDebounce(fn) {\n  var scheduled = false;\n  return function () {\n    if (!scheduled) {\n      scheduled = true;\n      setTimeout(function () {\n        scheduled = false;\n        fn();\n      }, timeoutDuration);\n    }\n  };\n}\n\n// It's common for MutationObserver polyfills to be seen in the wild, however\n// these rely on Mutation Events which only occur when an element is connected\n// to the DOM. The algorithm used in this module does not use a connected element,\n// and so we must ensure that a *native* MutationObserver is available.\nvar supportsNativeMutationObserver = isBrowser && isNative(window.MutationObserver);\n\n/**\n* Create a debounced version of a method, that's asynchronously deferred\n* but called in the minimum time possible.\n*\n* @method\n* @memberof Popper.Utils\n* @argument {Function} fn\n* @returns {Function}\n*/\nvar debounce = supportsNativeMutationObserver ? microtaskDebounce : taskDebounce;\n\n/**\n * Check if the given variable is a function\n * @method\n * @memberof Popper.Utils\n * @argument {Any} functionToCheck - variable to check\n * @returns {Boolean} answer to: is a function?\n */\nfunction isFunction(functionToCheck) {\n  var getType = {};\n  return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';\n}\n\n/**\n * Get CSS computed property of the given element\n * @method\n * @memberof Popper.Utils\n * @argument {Eement} element\n * @argument {String} property\n */\nfunction getStyleComputedProperty(element, property) {\n  if (element.nodeType !== 1) {\n    return [];\n  }\n  // NOTE: 1 DOM access here\n  var css = window.getComputedStyle(element, null);\n  return property ? css[property] : css;\n}\n\n/**\n * Returns the parentNode or the host of the element\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @returns {Element} parent\n */\nfunction getParentNode(element) {\n  if (element.nodeName === 'HTML') {\n    return element;\n  }\n  return element.parentNode || element.host;\n}\n\n/**\n * Returns the scrolling parent of the given element\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @returns {Element} scroll parent\n */\nfunction getScrollParent(element) {\n  // Return body, `getScroll` will take care to get the correct `scrollTop` from it\n  if (!element || ['HTML', 'BODY', '#document'].indexOf(element.nodeName) !== -1) {\n    return window.document.body;\n  }\n\n  // Firefox want us to check `-x` and `-y` variations as well\n\n  var _getStyleComputedProp = getStyleComputedProperty(element),\n      overflow = _getStyleComputedProp.overflow,\n      overflowX = _getStyleComputedProp.overflowX,\n      overflowY = _getStyleComputedProp.overflowY;\n\n  if (/(auto|scroll)/.test(overflow + overflowY + overflowX)) {\n    return element;\n  }\n\n  return getScrollParent(getParentNode(element));\n}\n\n/**\n * Returns the offset parent of the given element\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @returns {Element} offset parent\n */\nfunction getOffsetParent(element) {\n  // NOTE: 1 DOM access here\n  var offsetParent = element && element.offsetParent;\n  var nodeName = offsetParent && offsetParent.nodeName;\n\n  if (!nodeName || nodeName === 'BODY' || nodeName === 'HTML') {\n    return window.document.documentElement;\n  }\n\n  // .offsetParent will return the closest TD or TABLE in case\n  // no offsetParent is present, I hate this job...\n  if (['TD', 'TABLE'].indexOf(offsetParent.nodeName) !== -1 && getStyleComputedProperty(offsetParent, 'position') === 'static') {\n    return getOffsetParent(offsetParent);\n  }\n\n  return offsetParent;\n}\n\nfunction isOffsetContainer(element) {\n  var nodeName = element.nodeName;\n\n  if (nodeName === 'BODY') {\n    return false;\n  }\n  return nodeName === 'HTML' || getOffsetParent(element.firstElementChild) === element;\n}\n\n/**\n * Finds the root node (document, shadowDOM root) of the given element\n * @method\n * @memberof Popper.Utils\n * @argument {Element} node\n * @returns {Element} root node\n */\nfunction getRoot(node) {\n  if (node.parentNode !== null) {\n    return getRoot(node.parentNode);\n  }\n\n  return node;\n}\n\n/**\n * Finds the offset parent common to the two provided nodes\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element1\n * @argument {Element} element2\n * @returns {Element} common offset parent\n */\nfunction findCommonOffsetParent(element1, element2) {\n  // This check is needed to avoid errors in case one of the elements isn't defined for any reason\n  if (!element1 || !element1.nodeType || !element2 || !element2.nodeType) {\n    return window.document.documentElement;\n  }\n\n  // Here we make sure to give as \"start\" the element that comes first in the DOM\n  var order = element1.compareDocumentPosition(element2) & Node.DOCUMENT_POSITION_FOLLOWING;\n  var start = order ? element1 : element2;\n  var end = order ? element2 : element1;\n\n  // Get common ancestor container\n  var range = document.createRange();\n  range.setStart(start, 0);\n  range.setEnd(end, 0);\n  var commonAncestorContainer = range.commonAncestorContainer;\n\n  // Both nodes are inside #document\n\n  if (element1 !== commonAncestorContainer && element2 !== commonAncestorContainer || start.contains(end)) {\n    if (isOffsetContainer(commonAncestorContainer)) {\n      return commonAncestorContainer;\n    }\n\n    return getOffsetParent(commonAncestorContainer);\n  }\n\n  // one of the nodes is inside shadowDOM, find which one\n  var element1root = getRoot(element1);\n  if (element1root.host) {\n    return findCommonOffsetParent(element1root.host, element2);\n  } else {\n    return findCommonOffsetParent(element1, getRoot(element2).host);\n  }\n}\n\n/**\n * Gets the scroll value of the given element in the given side (top and left)\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @argument {String} side `top` or `left`\n * @returns {number} amount of scrolled pixels\n */\nfunction getScroll(element) {\n  var side = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'top';\n\n  var upperSide = side === 'top' ? 'scrollTop' : 'scrollLeft';\n  var nodeName = element.nodeName;\n\n  if (nodeName === 'BODY' || nodeName === 'HTML') {\n    var html = window.document.documentElement;\n    var scrollingElement = window.document.scrollingElement || html;\n    return scrollingElement[upperSide];\n  }\n\n  return element[upperSide];\n}\n\n/*\n * Sum or subtract the element scroll values (left and top) from a given rect object\n * @method\n * @memberof Popper.Utils\n * @param {Object} rect - Rect object you want to change\n * @param {HTMLElement} element - The element from the function reads the scroll values\n * @param {Boolean} subtract - set to true if you want to subtract the scroll values\n * @return {Object} rect - The modifier rect object\n */\nfunction includeScroll(rect, element) {\n  var subtract = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;\n\n  var scrollTop = getScroll(element, 'top');\n  var scrollLeft = getScroll(element, 'left');\n  var modifier = subtract ? -1 : 1;\n  rect.top += scrollTop * modifier;\n  rect.bottom += scrollTop * modifier;\n  rect.left += scrollLeft * modifier;\n  rect.right += scrollLeft * modifier;\n  return rect;\n}\n\n/*\n * Helper to detect borders of a given element\n * @method\n * @memberof Popper.Utils\n * @param {CSSStyleDeclaration} styles\n * Result of `getStyleComputedProperty` on the given element\n * @param {String} axis - `x` or `y`\n * @return {number} borders - The borders size of the given axis\n */\n\nfunction getBordersSize(styles, axis) {\n  var sideA = axis === 'x' ? 'Left' : 'Top';\n  var sideB = sideA === 'Left' ? 'Right' : 'Bottom';\n\n  return +styles['border' + sideA + 'Width'].split('px')[0] + +styles['border' + sideB + 'Width'].split('px')[0];\n}\n\n/**\n * Tells if you are running Internet Explorer 10\n * @method\n * @memberof Popper.Utils\n * @returns {Boolean} isIE10\n */\nvar isIE10 = undefined;\n\nvar isIE10$1 = function () {\n  if (isIE10 === undefined) {\n    isIE10 = navigator.appVersion.indexOf('MSIE 10') !== -1;\n  }\n  return isIE10;\n};\n\nfunction getSize(axis, body, html, computedStyle) {\n  return Math.max(body['offset' + axis], body['scroll' + axis], html['client' + axis], html['offset' + axis], html['scroll' + axis], isIE10$1() ? html['offset' + axis] + computedStyle['margin' + (axis === 'Height' ? 'Top' : 'Left')] + computedStyle['margin' + (axis === 'Height' ? 'Bottom' : 'Right')] : 0);\n}\n\nfunction getWindowSizes() {\n  var body = window.document.body;\n  var html = window.document.documentElement;\n  var computedStyle = isIE10$1() && window.getComputedStyle(html);\n\n  return {\n    height: getSize('Height', body, html, computedStyle),\n    width: getSize('Width', body, html, computedStyle)\n  };\n}\n\nvar classCallCheck = function (instance, Constructor) {\n  if (!(instance instanceof Constructor)) {\n    throw new TypeError(\"Cannot call a class as a function\");\n  }\n};\n\nvar createClass$1 = function () {\n  function defineProperties(target, props) {\n    for (var i = 0; i < props.length; i++) {\n      var descriptor = props[i];\n      descriptor.enumerable = descriptor.enumerable || false;\n      descriptor.configurable = true;\n      if (\"value\" in descriptor) descriptor.writable = true;\n      Object.defineProperty(target, descriptor.key, descriptor);\n    }\n  }\n\n  return function (Constructor, protoProps, staticProps) {\n    if (protoProps) defineProperties(Constructor.prototype, protoProps);\n    if (staticProps) defineProperties(Constructor, staticProps);\n    return Constructor;\n  };\n}();\n\n\n\n\n\nvar defineProperty = function (obj, key, value) {\n  if (key in obj) {\n    Object.defineProperty(obj, key, {\n      value: value,\n      enumerable: true,\n      configurable: true,\n      writable: true\n    });\n  } else {\n    obj[key] = value;\n  }\n\n  return obj;\n};\n\nvar _extends$1 = Object.assign || function (target) {\n  for (var i = 1; i < arguments.length; i++) {\n    var source = arguments[i];\n\n    for (var key in source) {\n      if (Object.prototype.hasOwnProperty.call(source, key)) {\n        target[key] = source[key];\n      }\n    }\n  }\n\n  return target;\n};\n\n/**\n * Given element offsets, generate an output similar to getBoundingClientRect\n * @method\n * @memberof Popper.Utils\n * @argument {Object} offsets\n * @returns {Object} ClientRect like output\n */\nfunction getClientRect(offsets) {\n  return _extends$1({}, offsets, {\n    right: offsets.left + offsets.width,\n    bottom: offsets.top + offsets.height\n  });\n}\n\n/**\n * Get bounding client rect of given element\n * @method\n * @memberof Popper.Utils\n * @param {HTMLElement} element\n * @return {Object} client rect\n */\nfunction getBoundingClientRect(element) {\n  var rect = {};\n\n  // IE10 10 FIX: Please, don't ask, the element isn't\n  // considered in DOM in some circumstances...\n  // This isn't reproducible in IE10 compatibility mode of IE11\n  if (isIE10$1()) {\n    try {\n      rect = element.getBoundingClientRect();\n      var scrollTop = getScroll(element, 'top');\n      var scrollLeft = getScroll(element, 'left');\n      rect.top += scrollTop;\n      rect.left += scrollLeft;\n      rect.bottom += scrollTop;\n      rect.right += scrollLeft;\n    } catch (err) {}\n  } else {\n    rect = element.getBoundingClientRect();\n  }\n\n  var result = {\n    left: rect.left,\n    top: rect.top,\n    width: rect.right - rect.left,\n    height: rect.bottom - rect.top\n  };\n\n  // subtract scrollbar size from sizes\n  var sizes = element.nodeName === 'HTML' ? getWindowSizes() : {};\n  var width = sizes.width || element.clientWidth || result.right - result.left;\n  var height = sizes.height || element.clientHeight || result.bottom - result.top;\n\n  var horizScrollbar = element.offsetWidth - width;\n  var vertScrollbar = element.offsetHeight - height;\n\n  // if an hypothetical scrollbar is detected, we must be sure it's not a `border`\n  // we make this check conditional for performance reasons\n  if (horizScrollbar || vertScrollbar) {\n    var styles = getStyleComputedProperty(element);\n    horizScrollbar -= getBordersSize(styles, 'x');\n    vertScrollbar -= getBordersSize(styles, 'y');\n\n    result.width -= horizScrollbar;\n    result.height -= vertScrollbar;\n  }\n\n  return getClientRect(result);\n}\n\nfunction getOffsetRectRelativeToArbitraryNode(children, parent) {\n  var isIE10 = isIE10$1();\n  var isHTML = parent.nodeName === 'HTML';\n  var childrenRect = getBoundingClientRect(children);\n  var parentRect = getBoundingClientRect(parent);\n  var scrollParent = getScrollParent(children);\n\n  var styles = getStyleComputedProperty(parent);\n  var borderTopWidth = +styles.borderTopWidth.split('px')[0];\n  var borderLeftWidth = +styles.borderLeftWidth.split('px')[0];\n\n  var offsets = getClientRect({\n    top: childrenRect.top - parentRect.top - borderTopWidth,\n    left: childrenRect.left - parentRect.left - borderLeftWidth,\n    width: childrenRect.width,\n    height: childrenRect.height\n  });\n  offsets.marginTop = 0;\n  offsets.marginLeft = 0;\n\n  // Subtract margins of documentElement in case it's being used as parent\n  // we do this only on HTML because it's the only element that behaves\n  // differently when margins are applied to it. The margins are included in\n  // the box of the documentElement, in the other cases not.\n  if (!isIE10 && isHTML) {\n    var marginTop = +styles.marginTop.split('px')[0];\n    var marginLeft = +styles.marginLeft.split('px')[0];\n\n    offsets.top -= borderTopWidth - marginTop;\n    offsets.bottom -= borderTopWidth - marginTop;\n    offsets.left -= borderLeftWidth - marginLeft;\n    offsets.right -= borderLeftWidth - marginLeft;\n\n    // Attach marginTop and marginLeft because in some circumstances we may need them\n    offsets.marginTop = marginTop;\n    offsets.marginLeft = marginLeft;\n  }\n\n  if (isIE10 ? parent.contains(scrollParent) : parent === scrollParent && scrollParent.nodeName !== 'BODY') {\n    offsets = includeScroll(offsets, parent);\n  }\n\n  return offsets;\n}\n\nfunction getViewportOffsetRectRelativeToArtbitraryNode(element) {\n  var html = window.document.documentElement;\n  var relativeOffset = getOffsetRectRelativeToArbitraryNode(element, html);\n  var width = Math.max(html.clientWidth, window.innerWidth || 0);\n  var height = Math.max(html.clientHeight, window.innerHeight || 0);\n\n  var scrollTop = getScroll(html);\n  var scrollLeft = getScroll(html, 'left');\n\n  var offset = {\n    top: scrollTop - relativeOffset.top + relativeOffset.marginTop,\n    left: scrollLeft - relativeOffset.left + relativeOffset.marginLeft,\n    width: width,\n    height: height\n  };\n\n  return getClientRect(offset);\n}\n\n/**\n * Check if the given element is fixed or is inside a fixed parent\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @argument {Element} customContainer\n * @returns {Boolean} answer to \"isFixed?\"\n */\nfunction isFixed(element) {\n  var nodeName = element.nodeName;\n  if (nodeName === 'BODY' || nodeName === 'HTML') {\n    return false;\n  }\n  if (getStyleComputedProperty(element, 'position') === 'fixed') {\n    return true;\n  }\n  return isFixed(getParentNode(element));\n}\n\n/**\n * Computed the boundaries limits and return them\n * @method\n * @memberof Popper.Utils\n * @param {HTMLElement} popper\n * @param {HTMLElement} reference\n * @param {number} padding\n * @param {HTMLElement} boundariesElement - Element used to define the boundaries\n * @returns {Object} Coordinates of the boundaries\n */\nfunction getBoundaries(popper, reference, padding, boundariesElement) {\n  // NOTE: 1 DOM access here\n  var boundaries = { top: 0, left: 0 };\n  var offsetParent = findCommonOffsetParent(popper, reference);\n\n  // Handle viewport case\n  if (boundariesElement === 'viewport') {\n    boundaries = getViewportOffsetRectRelativeToArtbitraryNode(offsetParent);\n  } else {\n    // Handle other cases based on DOM element used as boundaries\n    var boundariesNode = void 0;\n    if (boundariesElement === 'scrollParent') {\n      boundariesNode = getScrollParent(getParentNode(popper));\n      if (boundariesNode.nodeName === 'BODY') {\n        boundariesNode = window.document.documentElement;\n      }\n    } else if (boundariesElement === 'window') {\n      boundariesNode = window.document.documentElement;\n    } else {\n      boundariesNode = boundariesElement;\n    }\n\n    var offsets = getOffsetRectRelativeToArbitraryNode(boundariesNode, offsetParent);\n\n    // In case of HTML, we need a different computation\n    if (boundariesNode.nodeName === 'HTML' && !isFixed(offsetParent)) {\n      var _getWindowSizes = getWindowSizes(),\n          height = _getWindowSizes.height,\n          width = _getWindowSizes.width;\n\n      boundaries.top += offsets.top - offsets.marginTop;\n      boundaries.bottom = height + offsets.top;\n      boundaries.left += offsets.left - offsets.marginLeft;\n      boundaries.right = width + offsets.left;\n    } else {\n      // for all the other DOM elements, this one is good\n      boundaries = offsets;\n    }\n  }\n\n  // Add paddings\n  boundaries.left += padding;\n  boundaries.top += padding;\n  boundaries.right -= padding;\n  boundaries.bottom -= padding;\n\n  return boundaries;\n}\n\nfunction getArea(_ref) {\n  var width = _ref.width,\n      height = _ref.height;\n\n  return width * height;\n}\n\n/**\n * Utility used to transform the `auto` placement to the placement with more\n * available space.\n * @method\n * @memberof Popper.Utils\n * @argument {Object} data - The data object generated by update method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction computeAutoPlacement(placement, refRect, popper, reference, boundariesElement) {\n  var padding = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0;\n\n  if (placement.indexOf('auto') === -1) {\n    return placement;\n  }\n\n  var boundaries = getBoundaries(popper, reference, padding, boundariesElement);\n\n  var rects = {\n    top: {\n      width: boundaries.width,\n      height: refRect.top - boundaries.top\n    },\n    right: {\n      width: boundaries.right - refRect.right,\n      height: boundaries.height\n    },\n    bottom: {\n      width: boundaries.width,\n      height: boundaries.bottom - refRect.bottom\n    },\n    left: {\n      width: refRect.left - boundaries.left,\n      height: boundaries.height\n    }\n  };\n\n  var sortedAreas = Object.keys(rects).map(function (key) {\n    return _extends$1({\n      key: key\n    }, rects[key], {\n      area: getArea(rects[key])\n    });\n  }).sort(function (a, b) {\n    return b.area - a.area;\n  });\n\n  var filteredAreas = sortedAreas.filter(function (_ref2) {\n    var width = _ref2.width,\n        height = _ref2.height;\n    return width >= popper.clientWidth && height >= popper.clientHeight;\n  });\n\n  var computedPlacement = filteredAreas.length > 0 ? filteredAreas[0].key : sortedAreas[0].key;\n\n  var variation = placement.split('-')[1];\n\n  return computedPlacement + (variation ? '-' + variation : '');\n}\n\n/**\n * Get offsets to the reference element\n * @method\n * @memberof Popper.Utils\n * @param {Object} state\n * @param {Element} popper - the popper element\n * @param {Element} reference - the reference element (the popper will be relative to this)\n * @returns {Object} An object containing the offsets which will be applied to the popper\n */\nfunction getReferenceOffsets(state, popper, reference) {\n  var commonOffsetParent = findCommonOffsetParent(popper, reference);\n  return getOffsetRectRelativeToArbitraryNode(reference, commonOffsetParent);\n}\n\n/**\n * Get the outer sizes of the given element (offset size + margins)\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @returns {Object} object containing width and height properties\n */\nfunction getOuterSizes(element) {\n  var styles = window.getComputedStyle(element);\n  var x = parseFloat(styles.marginTop) + parseFloat(styles.marginBottom);\n  var y = parseFloat(styles.marginLeft) + parseFloat(styles.marginRight);\n  var result = {\n    width: element.offsetWidth + y,\n    height: element.offsetHeight + x\n  };\n  return result;\n}\n\n/**\n * Get the opposite placement of the given one\n * @method\n * @memberof Popper.Utils\n * @argument {String} placement\n * @returns {String} flipped placement\n */\nfunction getOppositePlacement(placement) {\n  var hash = { left: 'right', right: 'left', bottom: 'top', top: 'bottom' };\n  return placement.replace(/left|right|bottom|top/g, function (matched) {\n    return hash[matched];\n  });\n}\n\n/**\n * Get offsets to the popper\n * @method\n * @memberof Popper.Utils\n * @param {Object} position - CSS position the Popper will get applied\n * @param {HTMLElement} popper - the popper element\n * @param {Object} referenceOffsets - the reference offsets (the popper will be relative to this)\n * @param {String} placement - one of the valid placement options\n * @returns {Object} popperOffsets - An object containing the offsets which will be applied to the popper\n */\nfunction getPopperOffsets(popper, referenceOffsets, placement) {\n  placement = placement.split('-')[0];\n\n  // Get popper node sizes\n  var popperRect = getOuterSizes(popper);\n\n  // Add position, width and height to our offsets object\n  var popperOffsets = {\n    width: popperRect.width,\n    height: popperRect.height\n  };\n\n  // depending by the popper placement we have to compute its offsets slightly differently\n  var isHoriz = ['right', 'left'].indexOf(placement) !== -1;\n  var mainSide = isHoriz ? 'top' : 'left';\n  var secondarySide = isHoriz ? 'left' : 'top';\n  var measurement = isHoriz ? 'height' : 'width';\n  var secondaryMeasurement = !isHoriz ? 'height' : 'width';\n\n  popperOffsets[mainSide] = referenceOffsets[mainSide] + referenceOffsets[measurement] / 2 - popperRect[measurement] / 2;\n  if (placement === secondarySide) {\n    popperOffsets[secondarySide] = referenceOffsets[secondarySide] - popperRect[secondaryMeasurement];\n  } else {\n    popperOffsets[secondarySide] = referenceOffsets[getOppositePlacement(secondarySide)];\n  }\n\n  return popperOffsets;\n}\n\n/**\n * Mimics the `find` method of Array\n * @method\n * @memberof Popper.Utils\n * @argument {Array} arr\n * @argument prop\n * @argument value\n * @returns index or -1\n */\nfunction find(arr, check) {\n  // use native find if supported\n  if (Array.prototype.find) {\n    return arr.find(check);\n  }\n\n  // use `filter` to obtain the same behavior of `find`\n  return arr.filter(check)[0];\n}\n\n/**\n * Return the index of the matching object\n * @method\n * @memberof Popper.Utils\n * @argument {Array} arr\n * @argument prop\n * @argument value\n * @returns index or -1\n */\nfunction findIndex(arr, prop, value) {\n  // use native findIndex if supported\n  if (Array.prototype.findIndex) {\n    return arr.findIndex(function (cur) {\n      return cur[prop] === value;\n    });\n  }\n\n  // use `find` + `indexOf` if `findIndex` isn't supported\n  var match = find(arr, function (obj) {\n    return obj[prop] === value;\n  });\n  return arr.indexOf(match);\n}\n\n/**\n * Loop trough the list of modifiers and run them in order,\n * each of them will then edit the data object.\n * @method\n * @memberof Popper.Utils\n * @param {dataObject} data\n * @param {Array} modifiers\n * @param {String} ends - Optional modifier name used as stopper\n * @returns {dataObject}\n */\nfunction runModifiers(modifiers, data, ends) {\n  var modifiersToRun = ends === undefined ? modifiers : modifiers.slice(0, findIndex(modifiers, 'name', ends));\n\n  modifiersToRun.forEach(function (modifier) {\n    if (modifier.function) {\n      console.warn('`modifier.function` is deprecated, use `modifier.fn`!');\n    }\n    var fn = modifier.function || modifier.fn;\n    if (modifier.enabled && isFunction(fn)) {\n      // Add properties to offsets to make them a complete clientRect object\n      // we do this before each modifier to make sure the previous one doesn't\n      // mess with these values\n      data.offsets.popper = getClientRect(data.offsets.popper);\n      data.offsets.reference = getClientRect(data.offsets.reference);\n\n      data = fn(data, modifier);\n    }\n  });\n\n  return data;\n}\n\n/**\n * Updates the position of the popper, computing the new offsets and applying\n * the new style.<br />\n * Prefer `scheduleUpdate` over `update` because of performance reasons.\n * @method\n * @memberof Popper\n */\nfunction update() {\n  // if popper is destroyed, don't perform any further update\n  if (this.state.isDestroyed) {\n    return;\n  }\n\n  var data = {\n    instance: this,\n    styles: {},\n    arrowStyles: {},\n    attributes: {},\n    flipped: false,\n    offsets: {}\n  };\n\n  // compute reference element offsets\n  data.offsets.reference = getReferenceOffsets(this.state, this.popper, this.reference);\n\n  // compute auto placement, store placement inside the data object,\n  // modifiers will be able to edit `placement` if needed\n  // and refer to originalPlacement to know the original value\n  data.placement = computeAutoPlacement(this.options.placement, data.offsets.reference, this.popper, this.reference, this.options.modifiers.flip.boundariesElement, this.options.modifiers.flip.padding);\n\n  // store the computed placement inside `originalPlacement`\n  data.originalPlacement = data.placement;\n\n  // compute the popper offsets\n  data.offsets.popper = getPopperOffsets(this.popper, data.offsets.reference, data.placement);\n  data.offsets.popper.position = 'absolute';\n\n  // run the modifiers\n  data = runModifiers(this.modifiers, data);\n\n  // the first `update` will call `onCreate` callback\n  // the other ones will call `onUpdate` callback\n  if (!this.state.isCreated) {\n    this.state.isCreated = true;\n    this.options.onCreate(data);\n  } else {\n    this.options.onUpdate(data);\n  }\n}\n\n/**\n * Helper used to know if the given modifier is enabled.\n * @method\n * @memberof Popper.Utils\n * @returns {Boolean}\n */\nfunction isModifierEnabled(modifiers, modifierName) {\n  return modifiers.some(function (_ref) {\n    var name = _ref.name,\n        enabled = _ref.enabled;\n    return enabled && name === modifierName;\n  });\n}\n\n/**\n * Get the prefixed supported property name\n * @method\n * @memberof Popper.Utils\n * @argument {String} property (camelCase)\n * @returns {String} prefixed property (camelCase or PascalCase, depending on the vendor prefix)\n */\nfunction getSupportedPropertyName(property) {\n  var prefixes = [false, 'ms', 'Webkit', 'Moz', 'O'];\n  var upperProp = property.charAt(0).toUpperCase() + property.slice(1);\n\n  for (var i = 0; i < prefixes.length - 1; i++) {\n    var prefix = prefixes[i];\n    var toCheck = prefix ? '' + prefix + upperProp : property;\n    if (typeof window.document.body.style[toCheck] !== 'undefined') {\n      return toCheck;\n    }\n  }\n  return null;\n}\n\n/**\n * Destroy the popper\n * @method\n * @memberof Popper\n */\nfunction destroy() {\n  this.state.isDestroyed = true;\n\n  // touch DOM only if `applyStyle` modifier is enabled\n  if (isModifierEnabled(this.modifiers, 'applyStyle')) {\n    this.popper.removeAttribute('x-placement');\n    this.popper.style.left = '';\n    this.popper.style.position = '';\n    this.popper.style.top = '';\n    this.popper.style[getSupportedPropertyName('transform')] = '';\n  }\n\n  this.disableEventListeners();\n\n  // remove the popper if user explicity asked for the deletion on destroy\n  // do not use `remove` because IE11 doesn't support it\n  if (this.options.removeOnDestroy) {\n    this.popper.parentNode.removeChild(this.popper);\n  }\n  return this;\n}\n\nfunction attachToScrollParents(scrollParent, event, callback, scrollParents) {\n  var isBody = scrollParent.nodeName === 'BODY';\n  var target = isBody ? window : scrollParent;\n  target.addEventListener(event, callback, { passive: true });\n\n  if (!isBody) {\n    attachToScrollParents(getScrollParent(target.parentNode), event, callback, scrollParents);\n  }\n  scrollParents.push(target);\n}\n\n/**\n * Setup needed event listeners used to update the popper position\n * @method\n * @memberof Popper.Utils\n * @private\n */\nfunction setupEventListeners(reference, options, state, updateBound) {\n  // Resize event listener on window\n  state.updateBound = updateBound;\n  window.addEventListener('resize', state.updateBound, { passive: true });\n\n  // Scroll event listener on scroll parents\n  var scrollElement = getScrollParent(reference);\n  attachToScrollParents(scrollElement, 'scroll', state.updateBound, state.scrollParents);\n  state.scrollElement = scrollElement;\n  state.eventsEnabled = true;\n\n  return state;\n}\n\n/**\n * It will add resize/scroll events and start recalculating\n * position of the popper element when they are triggered.\n * @method\n * @memberof Popper\n */\nfunction enableEventListeners() {\n  if (!this.state.eventsEnabled) {\n    this.state = setupEventListeners(this.reference, this.options, this.state, this.scheduleUpdate);\n  }\n}\n\n/**\n * Remove event listeners used to update the popper position\n * @method\n * @memberof Popper.Utils\n * @private\n */\nfunction removeEventListeners(reference, state) {\n  // Remove resize event listener on window\n  window.removeEventListener('resize', state.updateBound);\n\n  // Remove scroll event listener on scroll parents\n  state.scrollParents.forEach(function (target) {\n    target.removeEventListener('scroll', state.updateBound);\n  });\n\n  // Reset state\n  state.updateBound = null;\n  state.scrollParents = [];\n  state.scrollElement = null;\n  state.eventsEnabled = false;\n  return state;\n}\n\n/**\n * It will remove resize/scroll events and won't recalculate popper position\n * when they are triggered. It also won't trigger onUpdate callback anymore,\n * unless you call `update` method manually.\n * @method\n * @memberof Popper\n */\nfunction disableEventListeners() {\n  if (this.state.eventsEnabled) {\n    window.cancelAnimationFrame(this.scheduleUpdate);\n    this.state = removeEventListeners(this.reference, this.state);\n  }\n}\n\n/**\n * Tells if a given input is a number\n * @method\n * @memberof Popper.Utils\n * @param {*} input to check\n * @return {Boolean}\n */\nfunction isNumeric(n) {\n  return n !== '' && !isNaN(parseFloat(n)) && isFinite(n);\n}\n\n/**\n * Set the style to the given popper\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element - Element to apply the style to\n * @argument {Object} styles\n * Object with a list of properties and values which will be applied to the element\n */\nfunction setStyles(element, styles) {\n  Object.keys(styles).forEach(function (prop) {\n    var unit = '';\n    // add unit if the value is numeric and is one of the following\n    if (['width', 'height', 'top', 'right', 'bottom', 'left'].indexOf(prop) !== -1 && isNumeric(styles[prop])) {\n      unit = 'px';\n    }\n    element.style[prop] = styles[prop] + unit;\n  });\n}\n\n/**\n * Set the attributes to the given popper\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element - Element to apply the attributes to\n * @argument {Object} styles\n * Object with a list of properties and values which will be applied to the element\n */\nfunction setAttributes(element, attributes) {\n  Object.keys(attributes).forEach(function (prop) {\n    var value = attributes[prop];\n    if (value !== false) {\n      element.setAttribute(prop, attributes[prop]);\n    } else {\n      element.removeAttribute(prop);\n    }\n  });\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by `update` method\n * @argument {Object} data.styles - List of style properties - values to apply to popper element\n * @argument {Object} data.attributes - List of attribute properties - values to apply to popper element\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The same data object\n */\nfunction applyStyle(data) {\n  // any property present in `data.styles` will be applied to the popper,\n  // in this way we can make the 3rd party modifiers add custom styles to it\n  // Be aware, modifiers could override the properties defined in the previous\n  // lines of this modifier!\n  setStyles(data.instance.popper, data.styles);\n\n  // any property present in `data.attributes` will be applied to the popper,\n  // they will be set as HTML attributes of the element\n  setAttributes(data.instance.popper, data.attributes);\n\n  // if arrowElement is defined and arrowStyles has some properties\n  if (data.arrowElement && Object.keys(data.arrowStyles).length) {\n    setStyles(data.arrowElement, data.arrowStyles);\n  }\n\n  return data;\n}\n\n/**\n * Set the x-placement attribute before everything else because it could be used\n * to add margins to the popper margins needs to be calculated to get the\n * correct popper offsets.\n * @method\n * @memberof Popper.modifiers\n * @param {HTMLElement} reference - The reference element used to position the popper\n * @param {HTMLElement} popper - The HTML element used as popper.\n * @param {Object} options - Popper.js options\n */\nfunction applyStyleOnLoad(reference, popper, options, modifierOptions, state) {\n  // compute reference element offsets\n  var referenceOffsets = getReferenceOffsets(state, popper, reference);\n\n  // compute auto placement, store placement inside the data object,\n  // modifiers will be able to edit `placement` if needed\n  // and refer to originalPlacement to know the original value\n  var placement = computeAutoPlacement(options.placement, referenceOffsets, popper, reference, options.modifiers.flip.boundariesElement, options.modifiers.flip.padding);\n\n  popper.setAttribute('x-placement', placement);\n\n  // Apply `position` to popper before anything else because\n  // without the position applied we can't guarantee correct computations\n  setStyles(popper, { position: 'absolute' });\n\n  return options;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by `update` method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction computeStyle(data, options) {\n  var x = options.x,\n      y = options.y;\n  var popper = data.offsets.popper;\n\n  // Remove this legacy support in Popper.js v2\n\n  var legacyGpuAccelerationOption = find(data.instance.modifiers, function (modifier) {\n    return modifier.name === 'applyStyle';\n  }).gpuAcceleration;\n  if (legacyGpuAccelerationOption !== undefined) {\n    console.warn('WARNING: `gpuAcceleration` option moved to `computeStyle` modifier and will not be supported in future versions of Popper.js!');\n  }\n  var gpuAcceleration = legacyGpuAccelerationOption !== undefined ? legacyGpuAccelerationOption : options.gpuAcceleration;\n\n  var offsetParent = getOffsetParent(data.instance.popper);\n  var offsetParentRect = getBoundingClientRect(offsetParent);\n\n  // Styles\n  var styles = {\n    position: popper.position\n  };\n\n  // floor sides to avoid blurry text\n  var offsets = {\n    left: Math.floor(popper.left),\n    top: Math.floor(popper.top),\n    bottom: Math.floor(popper.bottom),\n    right: Math.floor(popper.right)\n  };\n\n  var sideA = x === 'bottom' ? 'top' : 'bottom';\n  var sideB = y === 'right' ? 'left' : 'right';\n\n  // if gpuAcceleration is set to `true` and transform is supported,\n  //  we use `translate3d` to apply the position to the popper we\n  // automatically use the supported prefixed version if needed\n  var prefixedProperty = getSupportedPropertyName('transform');\n\n  // now, let's make a step back and look at this code closely (wtf?)\n  // If the content of the popper grows once it's been positioned, it\n  // may happen that the popper gets misplaced because of the new content\n  // overflowing its reference element\n  // To avoid this problem, we provide two options (x and y), which allow\n  // the consumer to define the offset origin.\n  // If we position a popper on top of a reference element, we can set\n  // `x` to `top` to make the popper grow towards its top instead of\n  // its bottom.\n  var left = void 0,\n      top = void 0;\n  if (sideA === 'bottom') {\n    top = -offsetParentRect.height + offsets.bottom;\n  } else {\n    top = offsets.top;\n  }\n  if (sideB === 'right') {\n    left = -offsetParentRect.width + offsets.right;\n  } else {\n    left = offsets.left;\n  }\n  if (gpuAcceleration && prefixedProperty) {\n    styles[prefixedProperty] = 'translate3d(' + left + 'px, ' + top + 'px, 0)';\n    styles[sideA] = 0;\n    styles[sideB] = 0;\n    styles.willChange = 'transform';\n  } else {\n    // othwerise, we use the standard `top`, `left`, `bottom` and `right` properties\n    var invertTop = sideA === 'bottom' ? -1 : 1;\n    var invertLeft = sideB === 'right' ? -1 : 1;\n    styles[sideA] = top * invertTop;\n    styles[sideB] = left * invertLeft;\n    styles.willChange = sideA + ', ' + sideB;\n  }\n\n  // Attributes\n  var attributes = {\n    'x-placement': data.placement\n  };\n\n  // Update `data` attributes, styles and arrowStyles\n  data.attributes = _extends$1({}, attributes, data.attributes);\n  data.styles = _extends$1({}, styles, data.styles);\n  data.arrowStyles = _extends$1({}, data.offsets.arrow, data.arrowStyles);\n\n  return data;\n}\n\n/**\n * Helper used to know if the given modifier depends from another one.<br />\n * It checks if the needed modifier is listed and enabled.\n * @method\n * @memberof Popper.Utils\n * @param {Array} modifiers - list of modifiers\n * @param {String} requestingName - name of requesting modifier\n * @param {String} requestedName - name of requested modifier\n * @returns {Boolean}\n */\nfunction isModifierRequired(modifiers, requestingName, requestedName) {\n  var requesting = find(modifiers, function (_ref) {\n    var name = _ref.name;\n    return name === requestingName;\n  });\n\n  var isRequired = !!requesting && modifiers.some(function (modifier) {\n    return modifier.name === requestedName && modifier.enabled && modifier.order < requesting.order;\n  });\n\n  if (!isRequired) {\n    var _requesting = '`' + requestingName + '`';\n    var requested = '`' + requestedName + '`';\n    console.warn(requested + ' modifier is required by ' + _requesting + ' modifier in order to work, be sure to include it before ' + _requesting + '!');\n  }\n  return isRequired;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by update method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction arrow(data, options) {\n  // arrow depends on keepTogether in order to work\n  if (!isModifierRequired(data.instance.modifiers, 'arrow', 'keepTogether')) {\n    return data;\n  }\n\n  var arrowElement = options.element;\n\n  // if arrowElement is a string, suppose it's a CSS selector\n  if (typeof arrowElement === 'string') {\n    arrowElement = data.instance.popper.querySelector(arrowElement);\n\n    // if arrowElement is not found, don't run the modifier\n    if (!arrowElement) {\n      return data;\n    }\n  } else {\n    // if the arrowElement isn't a query selector we must check that the\n    // provided DOM node is child of its popper node\n    if (!data.instance.popper.contains(arrowElement)) {\n      console.warn('WARNING: `arrow.element` must be child of its popper element!');\n      return data;\n    }\n  }\n\n  var placement = data.placement.split('-')[0];\n  var _data$offsets = data.offsets,\n      popper = _data$offsets.popper,\n      reference = _data$offsets.reference;\n\n  var isVertical = ['left', 'right'].indexOf(placement) !== -1;\n\n  var len = isVertical ? 'height' : 'width';\n  var sideCapitalized = isVertical ? 'Top' : 'Left';\n  var side = sideCapitalized.toLowerCase();\n  var altSide = isVertical ? 'left' : 'top';\n  var opSide = isVertical ? 'bottom' : 'right';\n  var arrowElementSize = getOuterSizes(arrowElement)[len];\n\n  //\n  // extends keepTogether behavior making sure the popper and its\n  // reference have enough pixels in conjuction\n  //\n\n  // top/left side\n  if (reference[opSide] - arrowElementSize < popper[side]) {\n    data.offsets.popper[side] -= popper[side] - (reference[opSide] - arrowElementSize);\n  }\n  // bottom/right side\n  if (reference[side] + arrowElementSize > popper[opSide]) {\n    data.offsets.popper[side] += reference[side] + arrowElementSize - popper[opSide];\n  }\n\n  // compute center of the popper\n  var center = reference[side] + reference[len] / 2 - arrowElementSize / 2;\n\n  // Compute the sideValue using the updated popper offsets\n  // take popper margin in account because we don't have this info available\n  var popperMarginSide = getStyleComputedProperty(data.instance.popper, 'margin' + sideCapitalized).replace('px', '');\n  var sideValue = center - getClientRect(data.offsets.popper)[side] - popperMarginSide;\n\n  // prevent arrowElement from being placed not contiguously to its popper\n  sideValue = Math.max(Math.min(popper[len] - arrowElementSize, sideValue), 0);\n\n  data.arrowElement = arrowElement;\n  data.offsets.arrow = {};\n  data.offsets.arrow[side] = Math.round(sideValue);\n  data.offsets.arrow[altSide] = ''; // make sure to unset any eventual altSide value from the DOM node\n\n  return data;\n}\n\n/**\n * Get the opposite placement variation of the given one\n * @method\n * @memberof Popper.Utils\n * @argument {String} placement variation\n * @returns {String} flipped placement variation\n */\nfunction getOppositeVariation(variation) {\n  if (variation === 'end') {\n    return 'start';\n  } else if (variation === 'start') {\n    return 'end';\n  }\n  return variation;\n}\n\n/**\n * List of accepted placements to use as values of the `placement` option.<br />\n * Valid placements are:\n * - `auto`\n * - `top`\n * - `right`\n * - `bottom`\n * - `left`\n *\n * Each placement can have a variation from this list:\n * - `-start`\n * - `-end`\n *\n * Variations are interpreted easily if you think of them as the left to right\n * written languages. Horizontally (`top` and `bottom`), `start` is left and `end`\n * is right.<br />\n * Vertically (`left` and `right`), `start` is top and `end` is bottom.\n *\n * Some valid examples are:\n * - `top-end` (on top of reference, right aligned)\n * - `right-start` (on right of reference, top aligned)\n * - `bottom` (on bottom, centered)\n * - `auto-right` (on the side with more space available, alignment depends by placement)\n *\n * @static\n * @type {Array}\n * @enum {String}\n * @readonly\n * @method placements\n * @memberof Popper\n */\nvar placements = ['auto-start', 'auto', 'auto-end', 'top-start', 'top', 'top-end', 'right-start', 'right', 'right-end', 'bottom-end', 'bottom', 'bottom-start', 'left-end', 'left', 'left-start'];\n\n// Get rid of `auto` `auto-start` and `auto-end`\nvar validPlacements = placements.slice(3);\n\n/**\n * Given an initial placement, returns all the subsequent placements\n * clockwise (or counter-clockwise).\n *\n * @method\n * @memberof Popper.Utils\n * @argument {String} placement - A valid placement (it accepts variations)\n * @argument {Boolean} counter - Set to true to walk the placements counterclockwise\n * @returns {Array} placements including their variations\n */\nfunction clockwise(placement) {\n  var counter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;\n\n  var index = validPlacements.indexOf(placement);\n  var arr = validPlacements.slice(index + 1).concat(validPlacements.slice(0, index));\n  return counter ? arr.reverse() : arr;\n}\n\nvar BEHAVIORS = {\n  FLIP: 'flip',\n  CLOCKWISE: 'clockwise',\n  COUNTERCLOCKWISE: 'counterclockwise'\n};\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by update method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction flip(data, options) {\n  // if `inner` modifier is enabled, we can't use the `flip` modifier\n  if (isModifierEnabled(data.instance.modifiers, 'inner')) {\n    return data;\n  }\n\n  if (data.flipped && data.placement === data.originalPlacement) {\n    // seems like flip is trying to loop, probably there's not enough space on any of the flippable sides\n    return data;\n  }\n\n  var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, options.boundariesElement);\n\n  var placement = data.placement.split('-')[0];\n  var placementOpposite = getOppositePlacement(placement);\n  var variation = data.placement.split('-')[1] || '';\n\n  var flipOrder = [];\n\n  switch (options.behavior) {\n    case BEHAVIORS.FLIP:\n      flipOrder = [placement, placementOpposite];\n      break;\n    case BEHAVIORS.CLOCKWISE:\n      flipOrder = clockwise(placement);\n      break;\n    case BEHAVIORS.COUNTERCLOCKWISE:\n      flipOrder = clockwise(placement, true);\n      break;\n    default:\n      flipOrder = options.behavior;\n  }\n\n  flipOrder.forEach(function (step, index) {\n    if (placement !== step || flipOrder.length === index + 1) {\n      return data;\n    }\n\n    placement = data.placement.split('-')[0];\n    placementOpposite = getOppositePlacement(placement);\n\n    var popperOffsets = data.offsets.popper;\n    var refOffsets = data.offsets.reference;\n\n    // using floor because the reference offsets may contain decimals we are not going to consider here\n    var floor = Math.floor;\n    var overlapsRef = placement === 'left' && floor(popperOffsets.right) > floor(refOffsets.left) || placement === 'right' && floor(popperOffsets.left) < floor(refOffsets.right) || placement === 'top' && floor(popperOffsets.bottom) > floor(refOffsets.top) || placement === 'bottom' && floor(popperOffsets.top) < floor(refOffsets.bottom);\n\n    var overflowsLeft = floor(popperOffsets.left) < floor(boundaries.left);\n    var overflowsRight = floor(popperOffsets.right) > floor(boundaries.right);\n    var overflowsTop = floor(popperOffsets.top) < floor(boundaries.top);\n    var overflowsBottom = floor(popperOffsets.bottom) > floor(boundaries.bottom);\n\n    var overflowsBoundaries = placement === 'left' && overflowsLeft || placement === 'right' && overflowsRight || placement === 'top' && overflowsTop || placement === 'bottom' && overflowsBottom;\n\n    // flip the variation if required\n    var isVertical = ['top', 'bottom'].indexOf(placement) !== -1;\n    var flippedVariation = !!options.flipVariations && (isVertical && variation === 'start' && overflowsLeft || isVertical && variation === 'end' && overflowsRight || !isVertical && variation === 'start' && overflowsTop || !isVertical && variation === 'end' && overflowsBottom);\n\n    if (overlapsRef || overflowsBoundaries || flippedVariation) {\n      // this boolean to detect any flip loop\n      data.flipped = true;\n\n      if (overlapsRef || overflowsBoundaries) {\n        placement = flipOrder[index + 1];\n      }\n\n      if (flippedVariation) {\n        variation = getOppositeVariation(variation);\n      }\n\n      data.placement = placement + (variation ? '-' + variation : '');\n\n      // this object contains `position`, we want to preserve it along with\n      // any additional property we may add in the future\n      data.offsets.popper = _extends$1({}, data.offsets.popper, getPopperOffsets(data.instance.popper, data.offsets.reference, data.placement));\n\n      data = runModifiers(data.instance.modifiers, data, 'flip');\n    }\n  });\n  return data;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by update method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction keepTogether(data) {\n  var _data$offsets = data.offsets,\n      popper = _data$offsets.popper,\n      reference = _data$offsets.reference;\n\n  var placement = data.placement.split('-')[0];\n  var floor = Math.floor;\n  var isVertical = ['top', 'bottom'].indexOf(placement) !== -1;\n  var side = isVertical ? 'right' : 'bottom';\n  var opSide = isVertical ? 'left' : 'top';\n  var measurement = isVertical ? 'width' : 'height';\n\n  if (popper[side] < floor(reference[opSide])) {\n    data.offsets.popper[opSide] = floor(reference[opSide]) - popper[measurement];\n  }\n  if (popper[opSide] > floor(reference[side])) {\n    data.offsets.popper[opSide] = floor(reference[side]);\n  }\n\n  return data;\n}\n\n/**\n * Converts a string containing value + unit into a px value number\n * @function\n * @memberof {modifiers~offset}\n * @private\n * @argument {String} str - Value + unit string\n * @argument {String} measurement - `height` or `width`\n * @argument {Object} popperOffsets\n * @argument {Object} referenceOffsets\n * @returns {Number|String}\n * Value in pixels, or original string if no values were extracted\n */\nfunction toValue(str, measurement, popperOffsets, referenceOffsets) {\n  // separate value from unit\n  var split = str.match(/((?:\\-|\\+)?\\d*\\.?\\d*)(.*)/);\n  var value = +split[1];\n  var unit = split[2];\n\n  // If it's not a number it's an operator, I guess\n  if (!value) {\n    return str;\n  }\n\n  if (unit.indexOf('%') === 0) {\n    var element = void 0;\n    switch (unit) {\n      case '%p':\n        element = popperOffsets;\n        break;\n      case '%':\n      case '%r':\n      default:\n        element = referenceOffsets;\n    }\n\n    var rect = getClientRect(element);\n    return rect[measurement] / 100 * value;\n  } else if (unit === 'vh' || unit === 'vw') {\n    // if is a vh or vw, we calculate the size based on the viewport\n    var size = void 0;\n    if (unit === 'vh') {\n      size = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);\n    } else {\n      size = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);\n    }\n    return size / 100 * value;\n  } else {\n    // if is an explicit pixel unit, we get rid of the unit and keep the value\n    // if is an implicit unit, it's px, and we return just the value\n    return value;\n  }\n}\n\n/**\n * Parse an `offset` string to extrapolate `x` and `y` numeric offsets.\n * @function\n * @memberof {modifiers~offset}\n * @private\n * @argument {String} offset\n * @argument {Object} popperOffsets\n * @argument {Object} referenceOffsets\n * @argument {String} basePlacement\n * @returns {Array} a two cells array with x and y offsets in numbers\n */\nfunction parseOffset(offset, popperOffsets, referenceOffsets, basePlacement) {\n  var offsets = [0, 0];\n\n  // Use height if placement is left or right and index is 0 otherwise use width\n  // in this way the first offset will use an axis and the second one\n  // will use the other one\n  var useHeight = ['right', 'left'].indexOf(basePlacement) !== -1;\n\n  // Split the offset string to obtain a list of values and operands\n  // The regex addresses values with the plus or minus sign in front (+10, -20, etc)\n  var fragments = offset.split(/(\\+|\\-)/).map(function (frag) {\n    return frag.trim();\n  });\n\n  // Detect if the offset string contains a pair of values or a single one\n  // they could be separated by comma or space\n  var divider = fragments.indexOf(find(fragments, function (frag) {\n    return frag.search(/,|\\s/) !== -1;\n  }));\n\n  if (fragments[divider] && fragments[divider].indexOf(',') === -1) {\n    console.warn('Offsets separated by white space(s) are deprecated, use a comma (,) instead.');\n  }\n\n  // If divider is found, we divide the list of values and operands to divide\n  // them by ofset X and Y.\n  var splitRegex = /\\s*,\\s*|\\s+/;\n  var ops = divider !== -1 ? [fragments.slice(0, divider).concat([fragments[divider].split(splitRegex)[0]]), [fragments[divider].split(splitRegex)[1]].concat(fragments.slice(divider + 1))] : [fragments];\n\n  // Convert the values with units to absolute pixels to allow our computations\n  ops = ops.map(function (op, index) {\n    // Most of the units rely on the orientation of the popper\n    var measurement = (index === 1 ? !useHeight : useHeight) ? 'height' : 'width';\n    var mergeWithPrevious = false;\n    return op\n    // This aggregates any `+` or `-` sign that aren't considered operators\n    // e.g.: 10 + +5 => [10, +, +5]\n    .reduce(function (a, b) {\n      if (a[a.length - 1] === '' && ['+', '-'].indexOf(b) !== -1) {\n        a[a.length - 1] = b;\n        mergeWithPrevious = true;\n        return a;\n      } else if (mergeWithPrevious) {\n        a[a.length - 1] += b;\n        mergeWithPrevious = false;\n        return a;\n      } else {\n        return a.concat(b);\n      }\n    }, [])\n    // Here we convert the string values into number values (in px)\n    .map(function (str) {\n      return toValue(str, measurement, popperOffsets, referenceOffsets);\n    });\n  });\n\n  // Loop trough the offsets arrays and execute the operations\n  ops.forEach(function (op, index) {\n    op.forEach(function (frag, index2) {\n      if (isNumeric(frag)) {\n        offsets[index] += frag * (op[index2 - 1] === '-' ? -1 : 1);\n      }\n    });\n  });\n  return offsets;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by update method\n * @argument {Object} options - Modifiers configuration and options\n * @argument {Number|String} options.offset=0\n * The offset value as described in the modifier description\n * @returns {Object} The data object, properly modified\n */\nfunction offset(data, _ref) {\n  var offset = _ref.offset;\n  var placement = data.placement,\n      _data$offsets = data.offsets,\n      popper = _data$offsets.popper,\n      reference = _data$offsets.reference;\n\n  var basePlacement = placement.split('-')[0];\n\n  var offsets = void 0;\n  if (isNumeric(+offset)) {\n    offsets = [+offset, 0];\n  } else {\n    offsets = parseOffset(offset, popper, reference, basePlacement);\n  }\n\n  if (basePlacement === 'left') {\n    popper.top += offsets[0];\n    popper.left -= offsets[1];\n  } else if (basePlacement === 'right') {\n    popper.top += offsets[0];\n    popper.left += offsets[1];\n  } else if (basePlacement === 'top') {\n    popper.left += offsets[0];\n    popper.top -= offsets[1];\n  } else if (basePlacement === 'bottom') {\n    popper.left += offsets[0];\n    popper.top += offsets[1];\n  }\n\n  data.popper = popper;\n  return data;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by `update` method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction preventOverflow(data, options) {\n  var boundariesElement = options.boundariesElement || getOffsetParent(data.instance.popper);\n\n  // If offsetParent is the reference element, we really want to\n  // go one step up and use the next offsetParent as reference to\n  // avoid to make this modifier completely useless and look like broken\n  if (data.instance.reference === boundariesElement) {\n    boundariesElement = getOffsetParent(boundariesElement);\n  }\n\n  var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, boundariesElement);\n  options.boundaries = boundaries;\n\n  var order = options.priority;\n  var popper = data.offsets.popper;\n\n  var check = {\n    primary: function primary(placement) {\n      var value = popper[placement];\n      if (popper[placement] < boundaries[placement] && !options.escapeWithReference) {\n        value = Math.max(popper[placement], boundaries[placement]);\n      }\n      return defineProperty({}, placement, value);\n    },\n    secondary: function secondary(placement) {\n      var mainSide = placement === 'right' ? 'left' : 'top';\n      var value = popper[mainSide];\n      if (popper[placement] > boundaries[placement] && !options.escapeWithReference) {\n        value = Math.min(popper[mainSide], boundaries[placement] - (placement === 'right' ? popper.width : popper.height));\n      }\n      return defineProperty({}, mainSide, value);\n    }\n  };\n\n  order.forEach(function (placement) {\n    var side = ['left', 'top'].indexOf(placement) !== -1 ? 'primary' : 'secondary';\n    popper = _extends$1({}, popper, check[side](placement));\n  });\n\n  data.offsets.popper = popper;\n\n  return data;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by `update` method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction shift(data) {\n  var placement = data.placement;\n  var basePlacement = placement.split('-')[0];\n  var shiftvariation = placement.split('-')[1];\n\n  // if shift shiftvariation is specified, run the modifier\n  if (shiftvariation) {\n    var _data$offsets = data.offsets,\n        reference = _data$offsets.reference,\n        popper = _data$offsets.popper;\n\n    var isVertical = ['bottom', 'top'].indexOf(basePlacement) !== -1;\n    var side = isVertical ? 'left' : 'top';\n    var measurement = isVertical ? 'width' : 'height';\n\n    var shiftOffsets = {\n      start: defineProperty({}, side, reference[side]),\n      end: defineProperty({}, side, reference[side] + reference[measurement] - popper[measurement])\n    };\n\n    data.offsets.popper = _extends$1({}, popper, shiftOffsets[shiftvariation]);\n  }\n\n  return data;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by update method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction hide(data) {\n  if (!isModifierRequired(data.instance.modifiers, 'hide', 'preventOverflow')) {\n    return data;\n  }\n\n  var refRect = data.offsets.reference;\n  var bound = find(data.instance.modifiers, function (modifier) {\n    return modifier.name === 'preventOverflow';\n  }).boundaries;\n\n  if (refRect.bottom < bound.top || refRect.left > bound.right || refRect.top > bound.bottom || refRect.right < bound.left) {\n    // Avoid unnecessary DOM access if visibility hasn't changed\n    if (data.hide === true) {\n      return data;\n    }\n\n    data.hide = true;\n    data.attributes['x-out-of-boundaries'] = '';\n  } else {\n    // Avoid unnecessary DOM access if visibility hasn't changed\n    if (data.hide === false) {\n      return data;\n    }\n\n    data.hide = false;\n    data.attributes['x-out-of-boundaries'] = false;\n  }\n\n  return data;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by `update` method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction inner(data) {\n  var placement = data.placement;\n  var basePlacement = placement.split('-')[0];\n  var _data$offsets = data.offsets,\n      popper = _data$offsets.popper,\n      reference = _data$offsets.reference;\n\n  var isHoriz = ['left', 'right'].indexOf(basePlacement) !== -1;\n\n  var subtractLength = ['top', 'left'].indexOf(basePlacement) === -1;\n\n  popper[isHoriz ? 'left' : 'top'] = reference[basePlacement] - (subtractLength ? popper[isHoriz ? 'width' : 'height'] : 0);\n\n  data.placement = getOppositePlacement(placement);\n  data.offsets.popper = getClientRect(popper);\n\n  return data;\n}\n\n/**\n * Modifier function, each modifier can have a function of this type assigned\n * to its `fn` property.<br />\n * These functions will be called on each update, this means that you must\n * make sure they are performant enough to avoid performance bottlenecks.\n *\n * @function ModifierFn\n * @argument {dataObject} data - The data object generated by `update` method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {dataObject} The data object, properly modified\n */\n\n/**\n * Modifiers are plugins used to alter the behavior of your poppers.<br />\n * Popper.js uses a set of 9 modifiers to provide all the basic functionalities\n * needed by the library.\n *\n * Usually you don't want to override the `order`, `fn` and `onLoad` props.\n * All the other properties are configurations that could be tweaked.\n * @namespace modifiers\n */\nvar modifiers = {\n  /**\n   * Modifier used to shift the popper on the start or end of its reference\n   * element.<br />\n   * It will read the variation of the `placement` property.<br />\n   * It can be one either `-end` or `-start`.\n   * @memberof modifiers\n   * @inner\n   */\n  shift: {\n    /** @prop {number} order=100 - Index used to define the order of execution */\n    order: 100,\n    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n    enabled: true,\n    /** @prop {ModifierFn} */\n    fn: shift\n  },\n\n  /**\n   * The `offset` modifier can shift your popper on both its axis.\n   *\n   * It accepts the following units:\n   * - `px` or unitless, interpreted as pixels\n   * - `%` or `%r`, percentage relative to the length of the reference element\n   * - `%p`, percentage relative to the length of the popper element\n   * - `vw`, CSS viewport width unit\n   * - `vh`, CSS viewport height unit\n   *\n   * For length is intended the main axis relative to the placement of the popper.<br />\n   * This means that if the placement is `top` or `bottom`, the length will be the\n   * `width`. In case of `left` or `right`, it will be the height.\n   *\n   * You can provide a single value (as `Number` or `String`), or a pair of values\n   * as `String` divided by a comma or one (or more) white spaces.<br />\n   * The latter is a deprecated method because it leads to confusion and will be\n   * removed in v2.<br />\n   * Additionally, it accepts additions and subtractions between different units.\n   * Note that multiplications and divisions aren't supported.\n   *\n   * Valid examples are:\n   * ```\n   * 10\n   * '10%'\n   * '10, 10'\n   * '10%, 10'\n   * '10 + 10%'\n   * '10 - 5vh + 3%'\n   * '-10px + 5vh, 5px - 6%'\n   * ```\n   * > **NB**: If you desire to apply offsets to your poppers in a way that may make them overlap\n   * > with their reference element, unfortunately, you will have to disable the `flip` modifier.\n   * > More on this [reading this issue](https://github.com/FezVrasta/popper.js/issues/373)\n   *\n   * @memberof modifiers\n   * @inner\n   */\n  offset: {\n    /** @prop {number} order=200 - Index used to define the order of execution */\n    order: 200,\n    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n    enabled: true,\n    /** @prop {ModifierFn} */\n    fn: offset,\n    /** @prop {Number|String} offset=0\n     * The offset value as described in the modifier description\n     */\n    offset: 0\n  },\n\n  /**\n   * Modifier used to prevent the popper from being positioned outside the boundary.\n   *\n   * An scenario exists where the reference itself is not within the boundaries.<br />\n   * We can say it has \"escaped the boundaries\" — or just \"escaped\".<br />\n   * In this case we need to decide whether the popper should either:\n   *\n   * - detach from the reference and remain \"trapped\" in the boundaries, or\n   * - if it should ignore the boundary and \"escape with its reference\"\n   *\n   * When `escapeWithReference` is set to`true` and reference is completely\n   * outside its boundaries, the popper will overflow (or completely leave)\n   * the boundaries in order to remain attached to the edge of the reference.\n   *\n   * @memberof modifiers\n   * @inner\n   */\n  preventOverflow: {\n    /** @prop {number} order=300 - Index used to define the order of execution */\n    order: 300,\n    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n    enabled: true,\n    /** @prop {ModifierFn} */\n    fn: preventOverflow,\n    /**\n     * @prop {Array} [priority=['left','right','top','bottom']]\n     * Popper will try to prevent overflow following these priorities by default,\n     * then, it could overflow on the left and on top of the `boundariesElement`\n     */\n    priority: ['left', 'right', 'top', 'bottom'],\n    /**\n     * @prop {number} padding=5\n     * Amount of pixel used to define a minimum distance between the boundaries\n     * and the popper this makes sure the popper has always a little padding\n     * between the edges of its container\n     */\n    padding: 5,\n    /**\n     * @prop {String|HTMLElement} boundariesElement='scrollParent'\n     * Boundaries used by the modifier, can be `scrollParent`, `window`,\n     * `viewport` or any DOM element.\n     */\n    boundariesElement: 'scrollParent'\n  },\n\n  /**\n   * Modifier used to make sure the reference and its popper stay near eachothers\n   * without leaving any gap between the two. Expecially useful when the arrow is\n   * enabled and you want to assure it to point to its reference element.\n   * It cares only about the first axis, you can still have poppers with margin\n   * between the popper and its reference element.\n   * @memberof modifiers\n   * @inner\n   */\n  keepTogether: {\n    /** @prop {number} order=400 - Index used to define the order of execution */\n    order: 400,\n    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n    enabled: true,\n    /** @prop {ModifierFn} */\n    fn: keepTogether\n  },\n\n  /**\n   * This modifier is used to move the `arrowElement` of the popper to make\n   * sure it is positioned between the reference element and its popper element.\n   * It will read the outer size of the `arrowElement` node to detect how many\n   * pixels of conjuction are needed.\n   *\n   * It has no effect if no `arrowElement` is provided.\n   * @memberof modifiers\n   * @inner\n   */\n  arrow: {\n    /** @prop {number} order=500 - Index used to define the order of execution */\n    order: 500,\n    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n    enabled: true,\n    /** @prop {ModifierFn} */\n    fn: arrow,\n    /** @prop {String|HTMLElement} element='[x-arrow]' - Selector or node used as arrow */\n    element: '[x-arrow]'\n  },\n\n  /**\n   * Modifier used to flip the popper's placement when it starts to overlap its\n   * reference element.\n   *\n   * Requires the `preventOverflow` modifier before it in order to work.\n   *\n   * **NOTE:** this modifier will interrupt the current update cycle and will\n   * restart it if it detects the need to flip the placement.\n   * @memberof modifiers\n   * @inner\n   */\n  flip: {\n    /** @prop {number} order=600 - Index used to define the order of execution */\n    order: 600,\n    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n    enabled: true,\n    /** @prop {ModifierFn} */\n    fn: flip,\n    /**\n     * @prop {String|Array} behavior='flip'\n     * The behavior used to change the popper's placement. It can be one of\n     * `flip`, `clockwise`, `counterclockwise` or an array with a list of valid\n     * placements (with optional variations).\n     */\n    behavior: 'flip',\n    /**\n     * @prop {number} padding=5\n     * The popper will flip if it hits the edges of the `boundariesElement`\n     */\n    padding: 5,\n    /**\n     * @prop {String|HTMLElement} boundariesElement='viewport'\n     * The element which will define the boundaries of the popper position,\n     * the popper will never be placed outside of the defined boundaries\n     * (except if keepTogether is enabled)\n     */\n    boundariesElement: 'viewport'\n  },\n\n  /**\n   * Modifier used to make the popper flow toward the inner of the reference element.\n   * By default, when this modifier is disabled, the popper will be placed outside\n   * the reference element.\n   * @memberof modifiers\n   * @inner\n   */\n  inner: {\n    /** @prop {number} order=700 - Index used to define the order of execution */\n    order: 700,\n    /** @prop {Boolean} enabled=false - Whether the modifier is enabled or not */\n    enabled: false,\n    /** @prop {ModifierFn} */\n    fn: inner\n  },\n\n  /**\n   * Modifier used to hide the popper when its reference element is outside of the\n   * popper boundaries. It will set a `x-out-of-boundaries` attribute which can\n   * be used to hide with a CSS selector the popper when its reference is\n   * out of boundaries.\n   *\n   * Requires the `preventOverflow` modifier before it in order to work.\n   * @memberof modifiers\n   * @inner\n   */\n  hide: {\n    /** @prop {number} order=800 - Index used to define the order of execution */\n    order: 800,\n    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n    enabled: true,\n    /** @prop {ModifierFn} */\n    fn: hide\n  },\n\n  /**\n   * Computes the style that will be applied to the popper element to gets\n   * properly positioned.\n   *\n   * Note that this modifier will not touch the DOM, it just prepares the styles\n   * so that `applyStyle` modifier can apply it. This separation is useful\n   * in case you need to replace `applyStyle` with a custom implementation.\n   *\n   * This modifier has `850` as `order` value to maintain backward compatibility\n   * with previous versions of Popper.js. Expect the modifiers ordering method\n   * to change in future major versions of the library.\n   *\n   * @memberof modifiers\n   * @inner\n   */\n  computeStyle: {\n    /** @prop {number} order=850 - Index used to define the order of execution */\n    order: 850,\n    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n    enabled: true,\n    /** @prop {ModifierFn} */\n    fn: computeStyle,\n    /**\n     * @prop {Boolean} gpuAcceleration=true\n     * If true, it uses the CSS 3d transformation to position the popper.\n     * Otherwise, it will use the `top` and `left` properties.\n     */\n    gpuAcceleration: true,\n    /**\n     * @prop {string} [x='bottom']\n     * Where to anchor the X axis (`bottom` or `top`). AKA X offset origin.\n     * Change this if your popper should grow in a direction different from `bottom`\n     */\n    x: 'bottom',\n    /**\n     * @prop {string} [x='left']\n     * Where to anchor the Y axis (`left` or `right`). AKA Y offset origin.\n     * Change this if your popper should grow in a direction different from `right`\n     */\n    y: 'right'\n  },\n\n  /**\n   * Applies the computed styles to the popper element.\n   *\n   * All the DOM manipulations are limited to this modifier. This is useful in case\n   * you want to integrate Popper.js inside a framework or view library and you\n   * want to delegate all the DOM manipulations to it.\n   *\n   * Note that if you disable this modifier, you must make sure the popper element\n   * has its position set to `absolute` before Popper.js can do its work!\n   *\n   * Just disable this modifier and define you own to achieve the desired effect.\n   *\n   * @memberof modifiers\n   * @inner\n   */\n  applyStyle: {\n    /** @prop {number} order=900 - Index used to define the order of execution */\n    order: 900,\n    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n    enabled: true,\n    /** @prop {ModifierFn} */\n    fn: applyStyle,\n    /** @prop {Function} */\n    onLoad: applyStyleOnLoad,\n    /**\n     * @deprecated since version 1.10.0, the property moved to `computeStyle` modifier\n     * @prop {Boolean} gpuAcceleration=true\n     * If true, it uses the CSS 3d transformation to position the popper.\n     * Otherwise, it will use the `top` and `left` properties.\n     */\n    gpuAcceleration: undefined\n  }\n};\n\n/**\n * The `dataObject` is an object containing all the informations used by Popper.js\n * this object get passed to modifiers and to the `onCreate` and `onUpdate` callbacks.\n * @name dataObject\n * @property {Object} data.instance The Popper.js instance\n * @property {String} data.placement Placement applied to popper\n * @property {String} data.originalPlacement Placement originally defined on init\n * @property {Boolean} data.flipped True if popper has been flipped by flip modifier\n * @property {Boolean} data.hide True if the reference element is out of boundaries, useful to know when to hide the popper.\n * @property {HTMLElement} data.arrowElement Node used as arrow by arrow modifier\n * @property {Object} data.styles Any CSS property defined here will be applied to the popper, it expects the JavaScript nomenclature (eg. `marginBottom`)\n * @property {Object} data.arrowStyles Any CSS property defined here will be applied to the popper arrow, it expects the JavaScript nomenclature (eg. `marginBottom`)\n * @property {Object} data.boundaries Offsets of the popper boundaries\n * @property {Object} data.offsets The measurements of popper, reference and arrow elements.\n * @property {Object} data.offsets.popper `top`, `left`, `width`, `height` values\n * @property {Object} data.offsets.reference `top`, `left`, `width`, `height` values\n * @property {Object} data.offsets.arrow] `top` and `left` offsets, only one of them will be different from 0\n */\n\n/**\n * Default options provided to Popper.js constructor.<br />\n * These can be overriden using the `options` argument of Popper.js.<br />\n * To override an option, simply pass as 3rd argument an object with the same\n * structure of this object, example:\n * ```\n * new Popper(ref, pop, {\n *   modifiers: {\n *     preventOverflow: { enabled: false }\n *   }\n * })\n * ```\n * @type {Object}\n * @static\n * @memberof Popper\n */\nvar Defaults = {\n  /**\n   * Popper's placement\n   * @prop {Popper.placements} placement='bottom'\n   */\n  placement: 'bottom',\n\n  /**\n   * Whether events (resize, scroll) are initially enabled\n   * @prop {Boolean} eventsEnabled=true\n   */\n  eventsEnabled: true,\n\n  /**\n   * Set to true if you want to automatically remove the popper when\n   * you call the `destroy` method.\n   * @prop {Boolean} removeOnDestroy=false\n   */\n  removeOnDestroy: false,\n\n  /**\n   * Callback called when the popper is created.<br />\n   * By default, is set to no-op.<br />\n   * Access Popper.js instance with `data.instance`.\n   * @prop {onCreate}\n   */\n  onCreate: function onCreate() {},\n\n  /**\n   * Callback called when the popper is updated, this callback is not called\n   * on the initialization/creation of the popper, but only on subsequent\n   * updates.<br />\n   * By default, is set to no-op.<br />\n   * Access Popper.js instance with `data.instance`.\n   * @prop {onUpdate}\n   */\n  onUpdate: function onUpdate() {},\n\n  /**\n   * List of modifiers used to modify the offsets before they are applied to the popper.\n   * They provide most of the functionalities of Popper.js\n   * @prop {modifiers}\n   */\n  modifiers: modifiers\n};\n\n/**\n * @callback onCreate\n * @param {dataObject} data\n */\n\n/**\n * @callback onUpdate\n * @param {dataObject} data\n */\n\n// Utils\n// Methods\nvar Popper = function () {\n  /**\n   * Create a new Popper.js instance\n   * @class Popper\n   * @param {HTMLElement|referenceObject} reference - The reference element used to position the popper\n   * @param {HTMLElement} popper - The HTML element used as popper.\n   * @param {Object} options - Your custom options to override the ones defined in [Defaults](#defaults)\n   * @return {Object} instance - The generated Popper.js instance\n   */\n  function Popper(reference, popper) {\n    var _this = this;\n\n    var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};\n    classCallCheck(this, Popper);\n\n    this.scheduleUpdate = function () {\n      return requestAnimationFrame(_this.update);\n    };\n\n    // make update() debounced, so that it only runs at most once-per-tick\n    this.update = debounce(this.update.bind(this));\n\n    // with {} we create a new object with the options inside it\n    this.options = _extends$1({}, Popper.Defaults, options);\n\n    // init state\n    this.state = {\n      isDestroyed: false,\n      isCreated: false,\n      scrollParents: []\n    };\n\n    // get reference and popper elements (allow jQuery wrappers)\n    this.reference = reference.jquery ? reference[0] : reference;\n    this.popper = popper.jquery ? popper[0] : popper;\n\n    // Deep merge modifiers options\n    this.options.modifiers = {};\n    Object.keys(_extends$1({}, Popper.Defaults.modifiers, options.modifiers)).forEach(function (name) {\n      _this.options.modifiers[name] = _extends$1({}, Popper.Defaults.modifiers[name] || {}, options.modifiers ? options.modifiers[name] : {});\n    });\n\n    // Refactoring modifiers' list (Object => Array)\n    this.modifiers = Object.keys(this.options.modifiers).map(function (name) {\n      return _extends$1({\n        name: name\n      }, _this.options.modifiers[name]);\n    })\n    // sort the modifiers by order\n    .sort(function (a, b) {\n      return a.order - b.order;\n    });\n\n    // modifiers have the ability to execute arbitrary code when Popper.js get inited\n    // such code is executed in the same order of its modifier\n    // they could add new properties to their options configuration\n    // BE AWARE: don't add options to `options.modifiers.name` but to `modifierOptions`!\n    this.modifiers.forEach(function (modifierOptions) {\n      if (modifierOptions.enabled && isFunction(modifierOptions.onLoad)) {\n        modifierOptions.onLoad(_this.reference, _this.popper, _this.options, modifierOptions, _this.state);\n      }\n    });\n\n    // fire the first update to position the popper in the right place\n    this.update();\n\n    var eventsEnabled = this.options.eventsEnabled;\n    if (eventsEnabled) {\n      // setup event listeners, they will take care of update the position in specific situations\n      this.enableEventListeners();\n    }\n\n    this.state.eventsEnabled = eventsEnabled;\n  }\n\n  // We can't use class properties because they don't get listed in the\n  // class prototype and break stuff like Sinon stubs\n\n\n  createClass$1(Popper, [{\n    key: 'update',\n    value: function update$$1() {\n      return update.call(this);\n    }\n  }, {\n    key: 'destroy',\n    value: function destroy$$1() {\n      return destroy.call(this);\n    }\n  }, {\n    key: 'enableEventListeners',\n    value: function enableEventListeners$$1() {\n      return enableEventListeners.call(this);\n    }\n  }, {\n    key: 'disableEventListeners',\n    value: function disableEventListeners$$1() {\n      return disableEventListeners.call(this);\n    }\n\n    /**\n     * Schedule an update, it will run on the next UI update available\n     * @method scheduleUpdate\n     * @memberof Popper\n     */\n\n\n    /**\n     * Collection of utilities useful when writing custom modifiers.\n     * Starting from version 1.7, this method is available only if you\n     * include `popper-utils.js` before `popper.js`.\n     *\n     * **DEPRECATION**: This way to access PopperUtils is deprecated\n     * and will be removed in v2! Use the PopperUtils module directly instead.\n     * Due to the high instability of the methods contained in Utils, we can't\n     * guarantee them to follow semver. Use them at your own risk!\n     * @static\n     * @private\n     * @type {Object}\n     * @deprecated since version 1.8\n     * @member Utils\n     * @memberof Popper\n     */\n\n  }]);\n  return Popper;\n}();\n\n/**\n * The `referenceObject` is an object that provides an interface compatible with Popper.js\n * and lets you use it as replacement of a real DOM node.<br />\n * You can use this method to position a popper relatively to a set of coordinates\n * in case you don't have a DOM node to use as reference.\n *\n * ```\n * new Popper(referenceObject, popperNode);\n * ```\n *\n * NB: This feature isn't supported in Internet Explorer 10\n * @name referenceObject\n * @property {Function} data.getBoundingClientRect\n * A function that returns a set of coordinates compatible with the native `getBoundingClientRect` method.\n * @property {number} data.clientWidth\n * An ES6 getter that will return the width of the virtual reference element.\n * @property {number} data.clientHeight\n * An ES6 getter that will return the height of the virtual reference element.\n */\n\n\nPopper.Utils = (typeof window !== 'undefined' ? window : global).PopperUtils;\nPopper.placements = placements;\nPopper.Defaults = Defaults;\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.0.0-beta.2): dropdown.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nvar Dropdown = function () {\n  /**\n   * Check for Popper dependency\n   * Popper - https://popper.js.org\n   */\n  if (typeof Popper === 'undefined') {\n    throw new Error('Bootstrap dropdown require Popper.js (https://popper.js.org)');\n  }\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n\n  var NAME = 'dropdown';\n  var VERSION = '4.0.0-beta.2';\n  var DATA_KEY = 'bs.dropdown';\n  var EVENT_KEY = \".\" + DATA_KEY;\n  var DATA_API_KEY = '.data-api';\n  var JQUERY_NO_CONFLICT = $.fn[NAME];\n  var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key\n\n  var SPACE_KEYCODE = 32; // KeyboardEvent.which value for space key\n\n  var TAB_KEYCODE = 9; // KeyboardEvent.which value for tab key\n\n  var ARROW_UP_KEYCODE = 38; // KeyboardEvent.which value for up arrow key\n\n  var ARROW_DOWN_KEYCODE = 40; // KeyboardEvent.which value for down arrow key\n\n  var RIGHT_MOUSE_BUTTON_WHICH = 3; // MouseEvent.which value for the right button (assuming a right-handed mouse)\n\n  var REGEXP_KEYDOWN = new RegExp(ARROW_UP_KEYCODE + \"|\" + ARROW_DOWN_KEYCODE + \"|\" + ESCAPE_KEYCODE);\n  var Event = {\n    HIDE: \"hide\" + EVENT_KEY,\n    HIDDEN: \"hidden\" + EVENT_KEY,\n    SHOW: \"show\" + EVENT_KEY,\n    SHOWN: \"shown\" + EVENT_KEY,\n    CLICK: \"click\" + EVENT_KEY,\n    CLICK_DATA_API: \"click\" + EVENT_KEY + DATA_API_KEY,\n    KEYDOWN_DATA_API: \"keydown\" + EVENT_KEY + DATA_API_KEY,\n    KEYUP_DATA_API: \"keyup\" + EVENT_KEY + DATA_API_KEY\n  };\n  var ClassName = {\n    DISABLED: 'disabled',\n    SHOW: 'show',\n    DROPUP: 'dropup',\n    MENURIGHT: 'dropdown-menu-right',\n    MENULEFT: 'dropdown-menu-left'\n  };\n  var Selector = {\n    DATA_TOGGLE: '[data-toggle=\"dropdown\"]',\n    FORM_CHILD: '.dropdown form',\n    MENU: '.dropdown-menu',\n    NAVBAR_NAV: '.navbar-nav',\n    VISIBLE_ITEMS: '.dropdown-menu .dropdown-item:not(.disabled)'\n  };\n  var AttachmentMap = {\n    TOP: 'top-start',\n    TOPEND: 'top-end',\n    BOTTOM: 'bottom-start',\n    BOTTOMEND: 'bottom-end'\n  };\n  var Default = {\n    offset: 0,\n    flip: true\n  };\n  var DefaultType = {\n    offset: '(number|string|function)',\n    flip: 'boolean'\n    /**\n     * ------------------------------------------------------------------------\n     * Class Definition\n     * ------------------------------------------------------------------------\n     */\n\n  };\n\n  var Dropdown =\n  /*#__PURE__*/\n  function () {\n    function Dropdown(element, config) {\n      this._element = element;\n      this._popper = null;\n      this._config = this._getConfig(config);\n      this._menu = this._getMenuElement();\n      this._inNavbar = this._detectNavbar();\n\n      this._addEventListeners();\n    } // getters\n\n\n    var _proto = Dropdown.prototype;\n\n    // public\n    _proto.toggle = function toggle() {\n      if (this._element.disabled || $(this._element).hasClass(ClassName.DISABLED)) {\n        return;\n      }\n\n      var parent = Dropdown._getParentFromElement(this._element);\n\n      var isActive = $(this._menu).hasClass(ClassName.SHOW);\n\n      Dropdown._clearMenus();\n\n      if (isActive) {\n        return;\n      }\n\n      var relatedTarget = {\n        relatedTarget: this._element\n      };\n      var showEvent = $.Event(Event.SHOW, relatedTarget);\n      $(parent).trigger(showEvent);\n\n      if (showEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      var element = this._element; // for dropup with alignment we use the parent as popper container\n\n      if ($(parent).hasClass(ClassName.DROPUP)) {\n        if ($(this._menu).hasClass(ClassName.MENULEFT) || $(this._menu).hasClass(ClassName.MENURIGHT)) {\n          element = parent;\n        }\n      }\n\n      this._popper = new Popper(element, this._menu, this._getPopperConfig()); // if this is a touch-enabled device we add extra\n      // empty mouseover listeners to the body's immediate children;\n      // only needed because of broken event delegation on iOS\n      // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html\n\n      if ('ontouchstart' in document.documentElement && !$(parent).closest(Selector.NAVBAR_NAV).length) {\n        $('body').children().on('mouseover', null, $.noop);\n      }\n\n      this._element.focus();\n\n      this._element.setAttribute('aria-expanded', true);\n\n      $(this._menu).toggleClass(ClassName.SHOW);\n      $(parent).toggleClass(ClassName.SHOW).trigger($.Event(Event.SHOWN, relatedTarget));\n    };\n\n    _proto.dispose = function dispose() {\n      $.removeData(this._element, DATA_KEY);\n      $(this._element).off(EVENT_KEY);\n      this._element = null;\n      this._menu = null;\n\n      if (this._popper !== null) {\n        this._popper.destroy();\n      }\n\n      this._popper = null;\n    };\n\n    _proto.update = function update() {\n      this._inNavbar = this._detectNavbar();\n\n      if (this._popper !== null) {\n        this._popper.scheduleUpdate();\n      }\n    }; // private\n\n\n    _proto._addEventListeners = function _addEventListeners() {\n      var _this = this;\n\n      $(this._element).on(Event.CLICK, function (event) {\n        event.preventDefault();\n        event.stopPropagation();\n\n        _this.toggle();\n      });\n    };\n\n    _proto._getConfig = function _getConfig(config) {\n      config = $.extend({}, this.constructor.Default, $(this._element).data(), config);\n      Util.typeCheckConfig(NAME, config, this.constructor.DefaultType);\n      return config;\n    };\n\n    _proto._getMenuElement = function _getMenuElement() {\n      if (!this._menu) {\n        var parent = Dropdown._getParentFromElement(this._element);\n\n        this._menu = $(parent).find(Selector.MENU)[0];\n      }\n\n      return this._menu;\n    };\n\n    _proto._getPlacement = function _getPlacement() {\n      var $parentDropdown = $(this._element).parent();\n      var placement = AttachmentMap.BOTTOM; // Handle dropup\n\n      if ($parentDropdown.hasClass(ClassName.DROPUP)) {\n        placement = AttachmentMap.TOP;\n\n        if ($(this._menu).hasClass(ClassName.MENURIGHT)) {\n          placement = AttachmentMap.TOPEND;\n        }\n      } else if ($(this._menu).hasClass(ClassName.MENURIGHT)) {\n        placement = AttachmentMap.BOTTOMEND;\n      }\n\n      return placement;\n    };\n\n    _proto._detectNavbar = function _detectNavbar() {\n      return $(this._element).closest('.navbar').length > 0;\n    };\n\n    _proto._getPopperConfig = function _getPopperConfig() {\n      var _this2 = this;\n\n      var offsetConf = {};\n\n      if (typeof this._config.offset === 'function') {\n        offsetConf.fn = function (data) {\n          data.offsets = $.extend({}, data.offsets, _this2._config.offset(data.offsets) || {});\n          return data;\n        };\n      } else {\n        offsetConf.offset = this._config.offset;\n      }\n\n      var popperConfig = {\n        placement: this._getPlacement(),\n        modifiers: {\n          offset: offsetConf,\n          flip: {\n            enabled: this._config.flip\n          }\n        } // Disable Popper.js for Dropdown in Navbar\n\n      };\n\n      if (this._inNavbar) {\n        popperConfig.modifiers.applyStyle = {\n          enabled: !this._inNavbar\n        };\n      }\n\n      return popperConfig;\n    }; // static\n\n\n    Dropdown._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var data = $(this).data(DATA_KEY);\n\n        var _config = typeof config === 'object' ? config : null;\n\n        if (!data) {\n          data = new Dropdown(this, _config);\n          $(this).data(DATA_KEY, data);\n        }\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new Error(\"No method named \\\"\" + config + \"\\\"\");\n          }\n\n          data[config]();\n        }\n      });\n    };\n\n    Dropdown._clearMenus = function _clearMenus(event) {\n      if (event && (event.which === RIGHT_MOUSE_BUTTON_WHICH || event.type === 'keyup' && event.which !== TAB_KEYCODE)) {\n        return;\n      }\n\n      var toggles = $.makeArray($(Selector.DATA_TOGGLE));\n\n      for (var i = 0; i < toggles.length; i++) {\n        var parent = Dropdown._getParentFromElement(toggles[i]);\n\n        var context = $(toggles[i]).data(DATA_KEY);\n        var relatedTarget = {\n          relatedTarget: toggles[i]\n        };\n\n        if (!context) {\n          continue;\n        }\n\n        var dropdownMenu = context._menu;\n\n        if (!$(parent).hasClass(ClassName.SHOW)) {\n          continue;\n        }\n\n        if (event && (event.type === 'click' && /input|textarea/i.test(event.target.tagName) || event.type === 'keyup' && event.which === TAB_KEYCODE) && $.contains(parent, event.target)) {\n          continue;\n        }\n\n        var hideEvent = $.Event(Event.HIDE, relatedTarget);\n        $(parent).trigger(hideEvent);\n\n        if (hideEvent.isDefaultPrevented()) {\n          continue;\n        } // if this is a touch-enabled device we remove the extra\n        // empty mouseover listeners we added for iOS support\n\n\n        if ('ontouchstart' in document.documentElement) {\n          $('body').children().off('mouseover', null, $.noop);\n        }\n\n        toggles[i].setAttribute('aria-expanded', 'false');\n        $(dropdownMenu).removeClass(ClassName.SHOW);\n        $(parent).removeClass(ClassName.SHOW).trigger($.Event(Event.HIDDEN, relatedTarget));\n      }\n    };\n\n    Dropdown._getParentFromElement = function _getParentFromElement(element) {\n      var parent;\n      var selector = Util.getSelectorFromElement(element);\n\n      if (selector) {\n        parent = $(selector)[0];\n      }\n\n      return parent || element.parentNode;\n    };\n\n    Dropdown._dataApiKeydownHandler = function _dataApiKeydownHandler(event) {\n      if (!REGEXP_KEYDOWN.test(event.which) || /button/i.test(event.target.tagName) && event.which === SPACE_KEYCODE || /input|textarea/i.test(event.target.tagName)) {\n        return;\n      }\n\n      event.preventDefault();\n      event.stopPropagation();\n\n      if (this.disabled || $(this).hasClass(ClassName.DISABLED)) {\n        return;\n      }\n\n      var parent = Dropdown._getParentFromElement(this);\n\n      var isActive = $(parent).hasClass(ClassName.SHOW);\n\n      if (!isActive && (event.which !== ESCAPE_KEYCODE || event.which !== SPACE_KEYCODE) || isActive && (event.which === ESCAPE_KEYCODE || event.which === SPACE_KEYCODE)) {\n        if (event.which === ESCAPE_KEYCODE) {\n          var toggle = $(parent).find(Selector.DATA_TOGGLE)[0];\n          $(toggle).trigger('focus');\n        }\n\n        $(this).trigger('click');\n        return;\n      }\n\n      var items = $(parent).find(Selector.VISIBLE_ITEMS).get();\n\n      if (!items.length) {\n        return;\n      }\n\n      var index = items.indexOf(event.target);\n\n      if (event.which === ARROW_UP_KEYCODE && index > 0) {\n        // up\n        index--;\n      }\n\n      if (event.which === ARROW_DOWN_KEYCODE && index < items.length - 1) {\n        // down\n        index++;\n      }\n\n      if (index < 0) {\n        index = 0;\n      }\n\n      items[index].focus();\n    };\n\n    createClass(Dropdown, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION;\n      }\n    }, {\n      key: \"Default\",\n      get: function get() {\n        return Default;\n      }\n    }, {\n      key: \"DefaultType\",\n      get: function get() {\n        return DefaultType;\n      }\n    }]);\n    return Dropdown;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  $(document).on(Event.KEYDOWN_DATA_API, Selector.DATA_TOGGLE, Dropdown._dataApiKeydownHandler).on(Event.KEYDOWN_DATA_API, Selector.MENU, Dropdown._dataApiKeydownHandler).on(Event.CLICK_DATA_API + \" \" + Event.KEYUP_DATA_API, Dropdown._clearMenus).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {\n    event.preventDefault();\n    event.stopPropagation();\n\n    Dropdown._jQueryInterface.call($(this), 'toggle');\n  }).on(Event.CLICK_DATA_API, Selector.FORM_CHILD, function (e) {\n    e.stopPropagation();\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n  $.fn[NAME] = Dropdown._jQueryInterface;\n  $.fn[NAME].Constructor = Dropdown;\n\n  $.fn[NAME].noConflict = function () {\n    $.fn[NAME] = JQUERY_NO_CONFLICT;\n    return Dropdown._jQueryInterface;\n  };\n\n  return Dropdown;\n}($, Popper);\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.0.0-beta.2): modal.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nvar Modal = function () {\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n  var NAME = 'modal';\n  var VERSION = '4.0.0-beta.2';\n  var DATA_KEY = 'bs.modal';\n  var EVENT_KEY = \".\" + DATA_KEY;\n  var DATA_API_KEY = '.data-api';\n  var JQUERY_NO_CONFLICT = $.fn[NAME];\n  var TRANSITION_DURATION = 300;\n  var BACKDROP_TRANSITION_DURATION = 150;\n  var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key\n\n  var Default = {\n    backdrop: true,\n    keyboard: true,\n    focus: true,\n    show: true\n  };\n  var DefaultType = {\n    backdrop: '(boolean|string)',\n    keyboard: 'boolean',\n    focus: 'boolean',\n    show: 'boolean'\n  };\n  var Event = {\n    HIDE: \"hide\" + EVENT_KEY,\n    HIDDEN: \"hidden\" + EVENT_KEY,\n    SHOW: \"show\" + EVENT_KEY,\n    SHOWN: \"shown\" + EVENT_KEY,\n    FOCUSIN: \"focusin\" + EVENT_KEY,\n    RESIZE: \"resize\" + EVENT_KEY,\n    CLICK_DISMISS: \"click.dismiss\" + EVENT_KEY,\n    KEYDOWN_DISMISS: \"keydown.dismiss\" + EVENT_KEY,\n    MOUSEUP_DISMISS: \"mouseup.dismiss\" + EVENT_KEY,\n    MOUSEDOWN_DISMISS: \"mousedown.dismiss\" + EVENT_KEY,\n    CLICK_DATA_API: \"click\" + EVENT_KEY + DATA_API_KEY\n  };\n  var ClassName = {\n    SCROLLBAR_MEASURER: 'modal-scrollbar-measure',\n    BACKDROP: 'modal-backdrop',\n    OPEN: 'modal-open',\n    FADE: 'fade',\n    SHOW: 'show'\n  };\n  var Selector = {\n    DIALOG: '.modal-dialog',\n    DATA_TOGGLE: '[data-toggle=\"modal\"]',\n    DATA_DISMISS: '[data-dismiss=\"modal\"]',\n    FIXED_CONTENT: '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top',\n    STICKY_CONTENT: '.sticky-top',\n    NAVBAR_TOGGLER: '.navbar-toggler'\n    /**\n     * ------------------------------------------------------------------------\n     * Class Definition\n     * ------------------------------------------------------------------------\n     */\n\n  };\n\n  var Modal =\n  /*#__PURE__*/\n  function () {\n    function Modal(element, config) {\n      this._config = this._getConfig(config);\n      this._element = element;\n      this._dialog = $(element).find(Selector.DIALOG)[0];\n      this._backdrop = null;\n      this._isShown = false;\n      this._isBodyOverflowing = false;\n      this._ignoreBackdropClick = false;\n      this._originalBodyPadding = 0;\n      this._scrollbarWidth = 0;\n    } // getters\n\n\n    var _proto = Modal.prototype;\n\n    // public\n    _proto.toggle = function toggle(relatedTarget) {\n      return this._isShown ? this.hide() : this.show(relatedTarget);\n    };\n\n    _proto.show = function show(relatedTarget) {\n      var _this = this;\n\n      if (this._isTransitioning || this._isShown) {\n        return;\n      }\n\n      if (Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.FADE)) {\n        this._isTransitioning = true;\n      }\n\n      var showEvent = $.Event(Event.SHOW, {\n        relatedTarget: relatedTarget\n      });\n      $(this._element).trigger(showEvent);\n\n      if (this._isShown || showEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      this._isShown = true;\n\n      this._checkScrollbar();\n\n      this._setScrollbar();\n\n      this._adjustDialog();\n\n      $(document.body).addClass(ClassName.OPEN);\n\n      this._setEscapeEvent();\n\n      this._setResizeEvent();\n\n      $(this._element).on(Event.CLICK_DISMISS, Selector.DATA_DISMISS, function (event) {\n        return _this.hide(event);\n      });\n      $(this._dialog).on(Event.MOUSEDOWN_DISMISS, function () {\n        $(_this._element).one(Event.MOUSEUP_DISMISS, function (event) {\n          if ($(event.target).is(_this._element)) {\n            _this._ignoreBackdropClick = true;\n          }\n        });\n      });\n\n      this._showBackdrop(function () {\n        return _this._showElement(relatedTarget);\n      });\n    };\n\n    _proto.hide = function hide(event) {\n      var _this2 = this;\n\n      if (event) {\n        event.preventDefault();\n      }\n\n      if (this._isTransitioning || !this._isShown) {\n        return;\n      }\n\n      var hideEvent = $.Event(Event.HIDE);\n      $(this._element).trigger(hideEvent);\n\n      if (!this._isShown || hideEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      this._isShown = false;\n      var transition = Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.FADE);\n\n      if (transition) {\n        this._isTransitioning = true;\n      }\n\n      this._setEscapeEvent();\n\n      this._setResizeEvent();\n\n      $(document).off(Event.FOCUSIN);\n      $(this._element).removeClass(ClassName.SHOW);\n      $(this._element).off(Event.CLICK_DISMISS);\n      $(this._dialog).off(Event.MOUSEDOWN_DISMISS);\n\n      if (transition) {\n        $(this._element).one(Util.TRANSITION_END, function (event) {\n          return _this2._hideModal(event);\n        }).emulateTransitionEnd(TRANSITION_DURATION);\n      } else {\n        this._hideModal();\n      }\n    };\n\n    _proto.dispose = function dispose() {\n      $.removeData(this._element, DATA_KEY);\n      $(window, document, this._element, this._backdrop).off(EVENT_KEY);\n      this._config = null;\n      this._element = null;\n      this._dialog = null;\n      this._backdrop = null;\n      this._isShown = null;\n      this._isBodyOverflowing = null;\n      this._ignoreBackdropClick = null;\n      this._scrollbarWidth = null;\n    };\n\n    _proto.handleUpdate = function handleUpdate() {\n      this._adjustDialog();\n    }; // private\n\n\n    _proto._getConfig = function _getConfig(config) {\n      config = $.extend({}, Default, config);\n      Util.typeCheckConfig(NAME, config, DefaultType);\n      return config;\n    };\n\n    _proto._showElement = function _showElement(relatedTarget) {\n      var _this3 = this;\n\n      var transition = Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.FADE);\n\n      if (!this._element.parentNode || this._element.parentNode.nodeType !== Node.ELEMENT_NODE) {\n        // don't move modals dom position\n        document.body.appendChild(this._element);\n      }\n\n      this._element.style.display = 'block';\n\n      this._element.removeAttribute('aria-hidden');\n\n      this._element.scrollTop = 0;\n\n      if (transition) {\n        Util.reflow(this._element);\n      }\n\n      $(this._element).addClass(ClassName.SHOW);\n\n      if (this._config.focus) {\n        this._enforceFocus();\n      }\n\n      var shownEvent = $.Event(Event.SHOWN, {\n        relatedTarget: relatedTarget\n      });\n\n      var transitionComplete = function transitionComplete() {\n        if (_this3._config.focus) {\n          _this3._element.focus();\n        }\n\n        _this3._isTransitioning = false;\n        $(_this3._element).trigger(shownEvent);\n      };\n\n      if (transition) {\n        $(this._dialog).one(Util.TRANSITION_END, transitionComplete).emulateTransitionEnd(TRANSITION_DURATION);\n      } else {\n        transitionComplete();\n      }\n    };\n\n    _proto._enforceFocus = function _enforceFocus() {\n      var _this4 = this;\n\n      $(document).off(Event.FOCUSIN) // guard against infinite focus loop\n      .on(Event.FOCUSIN, function (event) {\n        if (document !== event.target && _this4._element !== event.target && !$(_this4._element).has(event.target).length) {\n          _this4._element.focus();\n        }\n      });\n    };\n\n    _proto._setEscapeEvent = function _setEscapeEvent() {\n      var _this5 = this;\n\n      if (this._isShown && this._config.keyboard) {\n        $(this._element).on(Event.KEYDOWN_DISMISS, function (event) {\n          if (event.which === ESCAPE_KEYCODE) {\n            event.preventDefault();\n\n            _this5.hide();\n          }\n        });\n      } else if (!this._isShown) {\n        $(this._element).off(Event.KEYDOWN_DISMISS);\n      }\n    };\n\n    _proto._setResizeEvent = function _setResizeEvent() {\n      var _this6 = this;\n\n      if (this._isShown) {\n        $(window).on(Event.RESIZE, function (event) {\n          return _this6.handleUpdate(event);\n        });\n      } else {\n        $(window).off(Event.RESIZE);\n      }\n    };\n\n    _proto._hideModal = function _hideModal() {\n      var _this7 = this;\n\n      this._element.style.display = 'none';\n\n      this._element.setAttribute('aria-hidden', true);\n\n      this._isTransitioning = false;\n\n      this._showBackdrop(function () {\n        $(document.body).removeClass(ClassName.OPEN);\n\n        _this7._resetAdjustments();\n\n        _this7._resetScrollbar();\n\n        $(_this7._element).trigger(Event.HIDDEN);\n      });\n    };\n\n    _proto._removeBackdrop = function _removeBackdrop() {\n      if (this._backdrop) {\n        $(this._backdrop).remove();\n        this._backdrop = null;\n      }\n    };\n\n    _proto._showBackdrop = function _showBackdrop(callback) {\n      var _this8 = this;\n\n      var animate = $(this._element).hasClass(ClassName.FADE) ? ClassName.FADE : '';\n\n      if (this._isShown && this._config.backdrop) {\n        var doAnimate = Util.supportsTransitionEnd() && animate;\n        this._backdrop = document.createElement('div');\n        this._backdrop.className = ClassName.BACKDROP;\n\n        if (animate) {\n          $(this._backdrop).addClass(animate);\n        }\n\n        $(this._backdrop).appendTo(document.body);\n        $(this._element).on(Event.CLICK_DISMISS, function (event) {\n          if (_this8._ignoreBackdropClick) {\n            _this8._ignoreBackdropClick = false;\n            return;\n          }\n\n          if (event.target !== event.currentTarget) {\n            return;\n          }\n\n          if (_this8._config.backdrop === 'static') {\n            _this8._element.focus();\n          } else {\n            _this8.hide();\n          }\n        });\n\n        if (doAnimate) {\n          Util.reflow(this._backdrop);\n        }\n\n        $(this._backdrop).addClass(ClassName.SHOW);\n\n        if (!callback) {\n          return;\n        }\n\n        if (!doAnimate) {\n          callback();\n          return;\n        }\n\n        $(this._backdrop).one(Util.TRANSITION_END, callback).emulateTransitionEnd(BACKDROP_TRANSITION_DURATION);\n      } else if (!this._isShown && this._backdrop) {\n        $(this._backdrop).removeClass(ClassName.SHOW);\n\n        var callbackRemove = function callbackRemove() {\n          _this8._removeBackdrop();\n\n          if (callback) {\n            callback();\n          }\n        };\n\n        if (Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.FADE)) {\n          $(this._backdrop).one(Util.TRANSITION_END, callbackRemove).emulateTransitionEnd(BACKDROP_TRANSITION_DURATION);\n        } else {\n          callbackRemove();\n        }\n      } else if (callback) {\n        callback();\n      }\n    }; // ----------------------------------------------------------------------\n    // the following methods are used to handle overflowing modals\n    // todo (fat): these should probably be refactored out of modal.js\n    // ----------------------------------------------------------------------\n\n\n    _proto._adjustDialog = function _adjustDialog() {\n      var isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight;\n\n      if (!this._isBodyOverflowing && isModalOverflowing) {\n        this._element.style.paddingLeft = this._scrollbarWidth + \"px\";\n      }\n\n      if (this._isBodyOverflowing && !isModalOverflowing) {\n        this._element.style.paddingRight = this._scrollbarWidth + \"px\";\n      }\n    };\n\n    _proto._resetAdjustments = function _resetAdjustments() {\n      this._element.style.paddingLeft = '';\n      this._element.style.paddingRight = '';\n    };\n\n    _proto._checkScrollbar = function _checkScrollbar() {\n      var rect = document.body.getBoundingClientRect();\n      this._isBodyOverflowing = rect.left + rect.right < window.innerWidth;\n      this._scrollbarWidth = this._getScrollbarWidth();\n    };\n\n    _proto._setScrollbar = function _setScrollbar() {\n      var _this9 = this;\n\n      if (this._isBodyOverflowing) {\n        // Note: DOMNode.style.paddingRight returns the actual value or '' if not set\n        //   while $(DOMNode).css('padding-right') returns the calculated value or 0 if not set\n        // Adjust fixed content padding\n        $(Selector.FIXED_CONTENT).each(function (index, element) {\n          var actualPadding = $(element)[0].style.paddingRight;\n          var calculatedPadding = $(element).css('padding-right');\n          $(element).data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + _this9._scrollbarWidth + \"px\");\n        }); // Adjust sticky content margin\n\n        $(Selector.STICKY_CONTENT).each(function (index, element) {\n          var actualMargin = $(element)[0].style.marginRight;\n          var calculatedMargin = $(element).css('margin-right');\n          $(element).data('margin-right', actualMargin).css('margin-right', parseFloat(calculatedMargin) - _this9._scrollbarWidth + \"px\");\n        }); // Adjust navbar-toggler margin\n\n        $(Selector.NAVBAR_TOGGLER).each(function (index, element) {\n          var actualMargin = $(element)[0].style.marginRight;\n          var calculatedMargin = $(element).css('margin-right');\n          $(element).data('margin-right', actualMargin).css('margin-right', parseFloat(calculatedMargin) + _this9._scrollbarWidth + \"px\");\n        }); // Adjust body padding\n\n        var actualPadding = document.body.style.paddingRight;\n        var calculatedPadding = $('body').css('padding-right');\n        $('body').data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + this._scrollbarWidth + \"px\");\n      }\n    };\n\n    _proto._resetScrollbar = function _resetScrollbar() {\n      // Restore fixed content padding\n      $(Selector.FIXED_CONTENT).each(function (index, element) {\n        var padding = $(element).data('padding-right');\n\n        if (typeof padding !== 'undefined') {\n          $(element).css('padding-right', padding).removeData('padding-right');\n        }\n      }); // Restore sticky content and navbar-toggler margin\n\n      $(Selector.STICKY_CONTENT + \", \" + Selector.NAVBAR_TOGGLER).each(function (index, element) {\n        var margin = $(element).data('margin-right');\n\n        if (typeof margin !== 'undefined') {\n          $(element).css('margin-right', margin).removeData('margin-right');\n        }\n      }); // Restore body padding\n\n      var padding = $('body').data('padding-right');\n\n      if (typeof padding !== 'undefined') {\n        $('body').css('padding-right', padding).removeData('padding-right');\n      }\n    };\n\n    _proto._getScrollbarWidth = function _getScrollbarWidth() {\n      // thx d.walsh\n      var scrollDiv = document.createElement('div');\n      scrollDiv.className = ClassName.SCROLLBAR_MEASURER;\n      document.body.appendChild(scrollDiv);\n      var scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth;\n      document.body.removeChild(scrollDiv);\n      return scrollbarWidth;\n    }; // static\n\n\n    Modal._jQueryInterface = function _jQueryInterface(config, relatedTarget) {\n      return this.each(function () {\n        var data = $(this).data(DATA_KEY);\n\n        var _config = $.extend({}, Modal.Default, $(this).data(), typeof config === 'object' && config);\n\n        if (!data) {\n          data = new Modal(this, _config);\n          $(this).data(DATA_KEY, data);\n        }\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new Error(\"No method named \\\"\" + config + \"\\\"\");\n          }\n\n          data[config](relatedTarget);\n        } else if (_config.show) {\n          data.show(relatedTarget);\n        }\n      });\n    };\n\n    createClass(Modal, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION;\n      }\n    }, {\n      key: \"Default\",\n      get: function get() {\n        return Default;\n      }\n    }]);\n    return Modal;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {\n    var _this10 = this;\n\n    var target;\n    var selector = Util.getSelectorFromElement(this);\n\n    if (selector) {\n      target = $(selector)[0];\n    }\n\n    var config = $(target).data(DATA_KEY) ? 'toggle' : $.extend({}, $(target).data(), $(this).data());\n\n    if (this.tagName === 'A' || this.tagName === 'AREA') {\n      event.preventDefault();\n    }\n\n    var $target = $(target).one(Event.SHOW, function (showEvent) {\n      if (showEvent.isDefaultPrevented()) {\n        // only register focus restorer if modal will actually get shown\n        return;\n      }\n\n      $target.one(Event.HIDDEN, function () {\n        if ($(_this10).is(':visible')) {\n          _this10.focus();\n        }\n      });\n    });\n\n    Modal._jQueryInterface.call($(target), config, this);\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n  $.fn[NAME] = Modal._jQueryInterface;\n  $.fn[NAME].Constructor = Modal;\n\n  $.fn[NAME].noConflict = function () {\n    $.fn[NAME] = JQUERY_NO_CONFLICT;\n    return Modal._jQueryInterface;\n  };\n\n  return Modal;\n}($);\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.0.0-beta.2): tooltip.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nvar Tooltip = function () {\n  /**\n   * Check for Popper dependency\n   * Popper - https://popper.js.org\n   */\n  if (typeof Popper === 'undefined') {\n    throw new Error('Bootstrap tooltips require Popper.js (https://popper.js.org)');\n  }\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n\n  var NAME = 'tooltip';\n  var VERSION = '4.0.0-beta.2';\n  var DATA_KEY = 'bs.tooltip';\n  var EVENT_KEY = \".\" + DATA_KEY;\n  var JQUERY_NO_CONFLICT = $.fn[NAME];\n  var TRANSITION_DURATION = 150;\n  var CLASS_PREFIX = 'bs-tooltip';\n  var BSCLS_PREFIX_REGEX = new RegExp(\"(^|\\\\s)\" + CLASS_PREFIX + \"\\\\S+\", 'g');\n  var DefaultType = {\n    animation: 'boolean',\n    template: 'string',\n    title: '(string|element|function)',\n    trigger: 'string',\n    delay: '(number|object)',\n    html: 'boolean',\n    selector: '(string|boolean)',\n    placement: '(string|function)',\n    offset: '(number|string)',\n    container: '(string|element|boolean)',\n    fallbackPlacement: '(string|array)'\n  };\n  var AttachmentMap = {\n    AUTO: 'auto',\n    TOP: 'top',\n    RIGHT: 'right',\n    BOTTOM: 'bottom',\n    LEFT: 'left'\n  };\n  var Default = {\n    animation: true,\n    template: '<div class=\"tooltip\" role=\"tooltip\">' + '<div class=\"arrow\"></div>' + '<div class=\"tooltip-inner\"></div></div>',\n    trigger: 'hover focus',\n    title: '',\n    delay: 0,\n    html: false,\n    selector: false,\n    placement: 'top',\n    offset: 0,\n    container: false,\n    fallbackPlacement: 'flip'\n  };\n  var HoverState = {\n    SHOW: 'show',\n    OUT: 'out'\n  };\n  var Event = {\n    HIDE: \"hide\" + EVENT_KEY,\n    HIDDEN: \"hidden\" + EVENT_KEY,\n    SHOW: \"show\" + EVENT_KEY,\n    SHOWN: \"shown\" + EVENT_KEY,\n    INSERTED: \"inserted\" + EVENT_KEY,\n    CLICK: \"click\" + EVENT_KEY,\n    FOCUSIN: \"focusin\" + EVENT_KEY,\n    FOCUSOUT: \"focusout\" + EVENT_KEY,\n    MOUSEENTER: \"mouseenter\" + EVENT_KEY,\n    MOUSELEAVE: \"mouseleave\" + EVENT_KEY\n  };\n  var ClassName = {\n    FADE: 'fade',\n    SHOW: 'show'\n  };\n  var Selector = {\n    TOOLTIP: '.tooltip',\n    TOOLTIP_INNER: '.tooltip-inner',\n    ARROW: '.arrow'\n  };\n  var Trigger = {\n    HOVER: 'hover',\n    FOCUS: 'focus',\n    CLICK: 'click',\n    MANUAL: 'manual'\n    /**\n     * ------------------------------------------------------------------------\n     * Class Definition\n     * ------------------------------------------------------------------------\n     */\n\n  };\n\n  var Tooltip =\n  /*#__PURE__*/\n  function () {\n    function Tooltip(element, config) {\n      // private\n      this._isEnabled = true;\n      this._timeout = 0;\n      this._hoverState = '';\n      this._activeTrigger = {};\n      this._popper = null; // protected\n\n      this.element = element;\n      this.config = this._getConfig(config);\n      this.tip = null;\n\n      this._setListeners();\n    } // getters\n\n\n    var _proto = Tooltip.prototype;\n\n    // public\n    _proto.enable = function enable() {\n      this._isEnabled = true;\n    };\n\n    _proto.disable = function disable() {\n      this._isEnabled = false;\n    };\n\n    _proto.toggleEnabled = function toggleEnabled() {\n      this._isEnabled = !this._isEnabled;\n    };\n\n    _proto.toggle = function toggle(event) {\n      if (!this._isEnabled) {\n        return;\n      }\n\n      if (event) {\n        var dataKey = this.constructor.DATA_KEY;\n        var context = $(event.currentTarget).data(dataKey);\n\n        if (!context) {\n          context = new this.constructor(event.currentTarget, this._getDelegateConfig());\n          $(event.currentTarget).data(dataKey, context);\n        }\n\n        context._activeTrigger.click = !context._activeTrigger.click;\n\n        if (context._isWithActiveTrigger()) {\n          context._enter(null, context);\n        } else {\n          context._leave(null, context);\n        }\n      } else {\n        if ($(this.getTipElement()).hasClass(ClassName.SHOW)) {\n          this._leave(null, this);\n\n          return;\n        }\n\n        this._enter(null, this);\n      }\n    };\n\n    _proto.dispose = function dispose() {\n      clearTimeout(this._timeout);\n      $.removeData(this.element, this.constructor.DATA_KEY);\n      $(this.element).off(this.constructor.EVENT_KEY);\n      $(this.element).closest('.modal').off('hide.bs.modal');\n\n      if (this.tip) {\n        $(this.tip).remove();\n      }\n\n      this._isEnabled = null;\n      this._timeout = null;\n      this._hoverState = null;\n      this._activeTrigger = null;\n\n      if (this._popper !== null) {\n        this._popper.destroy();\n      }\n\n      this._popper = null;\n      this.element = null;\n      this.config = null;\n      this.tip = null;\n    };\n\n    _proto.show = function show() {\n      var _this = this;\n\n      if ($(this.element).css('display') === 'none') {\n        throw new Error('Please use show on visible elements');\n      }\n\n      var showEvent = $.Event(this.constructor.Event.SHOW);\n\n      if (this.isWithContent() && this._isEnabled) {\n        $(this.element).trigger(showEvent);\n        var isInTheDom = $.contains(this.element.ownerDocument.documentElement, this.element);\n\n        if (showEvent.isDefaultPrevented() || !isInTheDom) {\n          return;\n        }\n\n        var tip = this.getTipElement();\n        var tipId = Util.getUID(this.constructor.NAME);\n        tip.setAttribute('id', tipId);\n        this.element.setAttribute('aria-describedby', tipId);\n        this.setContent();\n\n        if (this.config.animation) {\n          $(tip).addClass(ClassName.FADE);\n        }\n\n        var placement = typeof this.config.placement === 'function' ? this.config.placement.call(this, tip, this.element) : this.config.placement;\n\n        var attachment = this._getAttachment(placement);\n\n        this.addAttachmentClass(attachment);\n        var container = this.config.container === false ? document.body : $(this.config.container);\n        $(tip).data(this.constructor.DATA_KEY, this);\n\n        if (!$.contains(this.element.ownerDocument.documentElement, this.tip)) {\n          $(tip).appendTo(container);\n        }\n\n        $(this.element).trigger(this.constructor.Event.INSERTED);\n        this._popper = new Popper(this.element, tip, {\n          placement: attachment,\n          modifiers: {\n            offset: {\n              offset: this.config.offset\n            },\n            flip: {\n              behavior: this.config.fallbackPlacement\n            },\n            arrow: {\n              element: Selector.ARROW\n            }\n          },\n          onCreate: function onCreate(data) {\n            if (data.originalPlacement !== data.placement) {\n              _this._handlePopperPlacementChange(data);\n            }\n          },\n          onUpdate: function onUpdate(data) {\n            _this._handlePopperPlacementChange(data);\n          }\n        });\n        $(tip).addClass(ClassName.SHOW); // if this is a touch-enabled device we add extra\n        // empty mouseover listeners to the body's immediate children;\n        // only needed because of broken event delegation on iOS\n        // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html\n\n        if ('ontouchstart' in document.documentElement) {\n          $('body').children().on('mouseover', null, $.noop);\n        }\n\n        var complete = function complete() {\n          if (_this.config.animation) {\n            _this._fixTransition();\n          }\n\n          var prevHoverState = _this._hoverState;\n          _this._hoverState = null;\n          $(_this.element).trigger(_this.constructor.Event.SHOWN);\n\n          if (prevHoverState === HoverState.OUT) {\n            _this._leave(null, _this);\n          }\n        };\n\n        if (Util.supportsTransitionEnd() && $(this.tip).hasClass(ClassName.FADE)) {\n          $(this.tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(Tooltip._TRANSITION_DURATION);\n        } else {\n          complete();\n        }\n      }\n    };\n\n    _proto.hide = function hide(callback) {\n      var _this2 = this;\n\n      var tip = this.getTipElement();\n      var hideEvent = $.Event(this.constructor.Event.HIDE);\n\n      var complete = function complete() {\n        if (_this2._hoverState !== HoverState.SHOW && tip.parentNode) {\n          tip.parentNode.removeChild(tip);\n        }\n\n        _this2._cleanTipClass();\n\n        _this2.element.removeAttribute('aria-describedby');\n\n        $(_this2.element).trigger(_this2.constructor.Event.HIDDEN);\n\n        if (_this2._popper !== null) {\n          _this2._popper.destroy();\n        }\n\n        if (callback) {\n          callback();\n        }\n      };\n\n      $(this.element).trigger(hideEvent);\n\n      if (hideEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      $(tip).removeClass(ClassName.SHOW); // if this is a touch-enabled device we remove the extra\n      // empty mouseover listeners we added for iOS support\n\n      if ('ontouchstart' in document.documentElement) {\n        $('body').children().off('mouseover', null, $.noop);\n      }\n\n      this._activeTrigger[Trigger.CLICK] = false;\n      this._activeTrigger[Trigger.FOCUS] = false;\n      this._activeTrigger[Trigger.HOVER] = false;\n\n      if (Util.supportsTransitionEnd() && $(this.tip).hasClass(ClassName.FADE)) {\n        $(tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION);\n      } else {\n        complete();\n      }\n\n      this._hoverState = '';\n    };\n\n    _proto.update = function update() {\n      if (this._popper !== null) {\n        this._popper.scheduleUpdate();\n      }\n    }; // protected\n\n\n    _proto.isWithContent = function isWithContent() {\n      return Boolean(this.getTitle());\n    };\n\n    _proto.addAttachmentClass = function addAttachmentClass(attachment) {\n      $(this.getTipElement()).addClass(CLASS_PREFIX + \"-\" + attachment);\n    };\n\n    _proto.getTipElement = function getTipElement() {\n      this.tip = this.tip || $(this.config.template)[0];\n      return this.tip;\n    };\n\n    _proto.setContent = function setContent() {\n      var $tip = $(this.getTipElement());\n      this.setElementContent($tip.find(Selector.TOOLTIP_INNER), this.getTitle());\n      $tip.removeClass(ClassName.FADE + \" \" + ClassName.SHOW);\n    };\n\n    _proto.setElementContent = function setElementContent($element, content) {\n      var html = this.config.html;\n\n      if (typeof content === 'object' && (content.nodeType || content.jquery)) {\n        // content is a DOM node or a jQuery\n        if (html) {\n          if (!$(content).parent().is($element)) {\n            $element.empty().append(content);\n          }\n        } else {\n          $element.text($(content).text());\n        }\n      } else {\n        $element[html ? 'html' : 'text'](content);\n      }\n    };\n\n    _proto.getTitle = function getTitle() {\n      var title = this.element.getAttribute('data-original-title');\n\n      if (!title) {\n        title = typeof this.config.title === 'function' ? this.config.title.call(this.element) : this.config.title;\n      }\n\n      return title;\n    }; // private\n\n\n    _proto._getAttachment = function _getAttachment(placement) {\n      return AttachmentMap[placement.toUpperCase()];\n    };\n\n    _proto._setListeners = function _setListeners() {\n      var _this3 = this;\n\n      var triggers = this.config.trigger.split(' ');\n      triggers.forEach(function (trigger) {\n        if (trigger === 'click') {\n          $(_this3.element).on(_this3.constructor.Event.CLICK, _this3.config.selector, function (event) {\n            return _this3.toggle(event);\n          });\n        } else if (trigger !== Trigger.MANUAL) {\n          var eventIn = trigger === Trigger.HOVER ? _this3.constructor.Event.MOUSEENTER : _this3.constructor.Event.FOCUSIN;\n          var eventOut = trigger === Trigger.HOVER ? _this3.constructor.Event.MOUSELEAVE : _this3.constructor.Event.FOCUSOUT;\n          $(_this3.element).on(eventIn, _this3.config.selector, function (event) {\n            return _this3._enter(event);\n          }).on(eventOut, _this3.config.selector, function (event) {\n            return _this3._leave(event);\n          });\n        }\n\n        $(_this3.element).closest('.modal').on('hide.bs.modal', function () {\n          return _this3.hide();\n        });\n      });\n\n      if (this.config.selector) {\n        this.config = $.extend({}, this.config, {\n          trigger: 'manual',\n          selector: ''\n        });\n      } else {\n        this._fixTitle();\n      }\n    };\n\n    _proto._fixTitle = function _fixTitle() {\n      var titleType = typeof this.element.getAttribute('data-original-title');\n\n      if (this.element.getAttribute('title') || titleType !== 'string') {\n        this.element.setAttribute('data-original-title', this.element.getAttribute('title') || '');\n        this.element.setAttribute('title', '');\n      }\n    };\n\n    _proto._enter = function _enter(event, context) {\n      var dataKey = this.constructor.DATA_KEY;\n      context = context || $(event.currentTarget).data(dataKey);\n\n      if (!context) {\n        context = new this.constructor(event.currentTarget, this._getDelegateConfig());\n        $(event.currentTarget).data(dataKey, context);\n      }\n\n      if (event) {\n        context._activeTrigger[event.type === 'focusin' ? Trigger.FOCUS : Trigger.HOVER] = true;\n      }\n\n      if ($(context.getTipElement()).hasClass(ClassName.SHOW) || context._hoverState === HoverState.SHOW) {\n        context._hoverState = HoverState.SHOW;\n        return;\n      }\n\n      clearTimeout(context._timeout);\n      context._hoverState = HoverState.SHOW;\n\n      if (!context.config.delay || !context.config.delay.show) {\n        context.show();\n        return;\n      }\n\n      context._timeout = setTimeout(function () {\n        if (context._hoverState === HoverState.SHOW) {\n          context.show();\n        }\n      }, context.config.delay.show);\n    };\n\n    _proto._leave = function _leave(event, context) {\n      var dataKey = this.constructor.DATA_KEY;\n      context = context || $(event.currentTarget).data(dataKey);\n\n      if (!context) {\n        context = new this.constructor(event.currentTarget, this._getDelegateConfig());\n        $(event.currentTarget).data(dataKey, context);\n      }\n\n      if (event) {\n        context._activeTrigger[event.type === 'focusout' ? Trigger.FOCUS : Trigger.HOVER] = false;\n      }\n\n      if (context._isWithActiveTrigger()) {\n        return;\n      }\n\n      clearTimeout(context._timeout);\n      context._hoverState = HoverState.OUT;\n\n      if (!context.config.delay || !context.config.delay.hide) {\n        context.hide();\n        return;\n      }\n\n      context._timeout = setTimeout(function () {\n        if (context._hoverState === HoverState.OUT) {\n          context.hide();\n        }\n      }, context.config.delay.hide);\n    };\n\n    _proto._isWithActiveTrigger = function _isWithActiveTrigger() {\n      for (var trigger in this._activeTrigger) {\n        if (this._activeTrigger[trigger]) {\n          return true;\n        }\n      }\n\n      return false;\n    };\n\n    _proto._getConfig = function _getConfig(config) {\n      config = $.extend({}, this.constructor.Default, $(this.element).data(), config);\n\n      if (typeof config.delay === 'number') {\n        config.delay = {\n          show: config.delay,\n          hide: config.delay\n        };\n      }\n\n      if (typeof config.title === 'number') {\n        config.title = config.title.toString();\n      }\n\n      if (typeof config.content === 'number') {\n        config.content = config.content.toString();\n      }\n\n      Util.typeCheckConfig(NAME, config, this.constructor.DefaultType);\n      return config;\n    };\n\n    _proto._getDelegateConfig = function _getDelegateConfig() {\n      var config = {};\n\n      if (this.config) {\n        for (var key in this.config) {\n          if (this.constructor.Default[key] !== this.config[key]) {\n            config[key] = this.config[key];\n          }\n        }\n      }\n\n      return config;\n    };\n\n    _proto._cleanTipClass = function _cleanTipClass() {\n      var $tip = $(this.getTipElement());\n      var tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX);\n\n      if (tabClass !== null && tabClass.length > 0) {\n        $tip.removeClass(tabClass.join(''));\n      }\n    };\n\n    _proto._handlePopperPlacementChange = function _handlePopperPlacementChange(data) {\n      this._cleanTipClass();\n\n      this.addAttachmentClass(this._getAttachment(data.placement));\n    };\n\n    _proto._fixTransition = function _fixTransition() {\n      var tip = this.getTipElement();\n      var initConfigAnimation = this.config.animation;\n\n      if (tip.getAttribute('x-placement') !== null) {\n        return;\n      }\n\n      $(tip).removeClass(ClassName.FADE);\n      this.config.animation = false;\n      this.hide();\n      this.show();\n      this.config.animation = initConfigAnimation;\n    }; // static\n\n\n    Tooltip._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var data = $(this).data(DATA_KEY);\n\n        var _config = typeof config === 'object' && config;\n\n        if (!data && /dispose|hide/.test(config)) {\n          return;\n        }\n\n        if (!data) {\n          data = new Tooltip(this, _config);\n          $(this).data(DATA_KEY, data);\n        }\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new Error(\"No method named \\\"\" + config + \"\\\"\");\n          }\n\n          data[config]();\n        }\n      });\n    };\n\n    createClass(Tooltip, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION;\n      }\n    }, {\n      key: \"Default\",\n      get: function get() {\n        return Default;\n      }\n    }, {\n      key: \"NAME\",\n      get: function get() {\n        return NAME;\n      }\n    }, {\n      key: \"DATA_KEY\",\n      get: function get() {\n        return DATA_KEY;\n      }\n    }, {\n      key: \"Event\",\n      get: function get() {\n        return Event;\n      }\n    }, {\n      key: \"EVENT_KEY\",\n      get: function get() {\n        return EVENT_KEY;\n      }\n    }, {\n      key: \"DefaultType\",\n      get: function get() {\n        return DefaultType;\n      }\n    }]);\n    return Tooltip;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n\n  $.fn[NAME] = Tooltip._jQueryInterface;\n  $.fn[NAME].Constructor = Tooltip;\n\n  $.fn[NAME].noConflict = function () {\n    $.fn[NAME] = JQUERY_NO_CONFLICT;\n    return Tooltip._jQueryInterface;\n  };\n\n  return Tooltip;\n}($, Popper);\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.0.0-beta.2): popover.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nvar Popover = function () {\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n  var NAME = 'popover';\n  var VERSION = '4.0.0-beta.2';\n  var DATA_KEY = 'bs.popover';\n  var EVENT_KEY = \".\" + DATA_KEY;\n  var JQUERY_NO_CONFLICT = $.fn[NAME];\n  var CLASS_PREFIX = 'bs-popover';\n  var BSCLS_PREFIX_REGEX = new RegExp(\"(^|\\\\s)\" + CLASS_PREFIX + \"\\\\S+\", 'g');\n  var Default = $.extend({}, Tooltip.Default, {\n    placement: 'right',\n    trigger: 'click',\n    content: '',\n    template: '<div class=\"popover\" role=\"tooltip\">' + '<div class=\"arrow\"></div>' + '<h3 class=\"popover-header\"></h3>' + '<div class=\"popover-body\"></div></div>'\n  });\n  var DefaultType = $.extend({}, Tooltip.DefaultType, {\n    content: '(string|element|function)'\n  });\n  var ClassName = {\n    FADE: 'fade',\n    SHOW: 'show'\n  };\n  var Selector = {\n    TITLE: '.popover-header',\n    CONTENT: '.popover-body'\n  };\n  var Event = {\n    HIDE: \"hide\" + EVENT_KEY,\n    HIDDEN: \"hidden\" + EVENT_KEY,\n    SHOW: \"show\" + EVENT_KEY,\n    SHOWN: \"shown\" + EVENT_KEY,\n    INSERTED: \"inserted\" + EVENT_KEY,\n    CLICK: \"click\" + EVENT_KEY,\n    FOCUSIN: \"focusin\" + EVENT_KEY,\n    FOCUSOUT: \"focusout\" + EVENT_KEY,\n    MOUSEENTER: \"mouseenter\" + EVENT_KEY,\n    MOUSELEAVE: \"mouseleave\" + EVENT_KEY\n    /**\n     * ------------------------------------------------------------------------\n     * Class Definition\n     * ------------------------------------------------------------------------\n     */\n\n  };\n\n  var Popover =\n  /*#__PURE__*/\n  function (_Tooltip) {\n    inheritsLoose(Popover, _Tooltip);\n\n    function Popover() {\n      return _Tooltip.apply(this, arguments) || this;\n    }\n\n    var _proto = Popover.prototype;\n\n    // overrides\n    _proto.isWithContent = function isWithContent() {\n      return this.getTitle() || this._getContent();\n    };\n\n    _proto.addAttachmentClass = function addAttachmentClass(attachment) {\n      $(this.getTipElement()).addClass(CLASS_PREFIX + \"-\" + attachment);\n    };\n\n    _proto.getTipElement = function getTipElement() {\n      this.tip = this.tip || $(this.config.template)[0];\n      return this.tip;\n    };\n\n    _proto.setContent = function setContent() {\n      var $tip = $(this.getTipElement()); // we use append for html objects to maintain js events\n\n      this.setElementContent($tip.find(Selector.TITLE), this.getTitle());\n      this.setElementContent($tip.find(Selector.CONTENT), this._getContent());\n      $tip.removeClass(ClassName.FADE + \" \" + ClassName.SHOW);\n    }; // private\n\n\n    _proto._getContent = function _getContent() {\n      return this.element.getAttribute('data-content') || (typeof this.config.content === 'function' ? this.config.content.call(this.element) : this.config.content);\n    };\n\n    _proto._cleanTipClass = function _cleanTipClass() {\n      var $tip = $(this.getTipElement());\n      var tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX);\n\n      if (tabClass !== null && tabClass.length > 0) {\n        $tip.removeClass(tabClass.join(''));\n      }\n    }; // static\n\n\n    Popover._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var data = $(this).data(DATA_KEY);\n\n        var _config = typeof config === 'object' ? config : null;\n\n        if (!data && /destroy|hide/.test(config)) {\n          return;\n        }\n\n        if (!data) {\n          data = new Popover(this, _config);\n          $(this).data(DATA_KEY, data);\n        }\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new Error(\"No method named \\\"\" + config + \"\\\"\");\n          }\n\n          data[config]();\n        }\n      });\n    };\n\n    createClass(Popover, null, [{\n      key: \"VERSION\",\n      // getters\n      get: function get() {\n        return VERSION;\n      }\n    }, {\n      key: \"Default\",\n      get: function get() {\n        return Default;\n      }\n    }, {\n      key: \"NAME\",\n      get: function get() {\n        return NAME;\n      }\n    }, {\n      key: \"DATA_KEY\",\n      get: function get() {\n        return DATA_KEY;\n      }\n    }, {\n      key: \"Event\",\n      get: function get() {\n        return Event;\n      }\n    }, {\n      key: \"EVENT_KEY\",\n      get: function get() {\n        return EVENT_KEY;\n      }\n    }, {\n      key: \"DefaultType\",\n      get: function get() {\n        return DefaultType;\n      }\n    }]);\n    return Popover;\n  }(Tooltip);\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n\n  $.fn[NAME] = Popover._jQueryInterface;\n  $.fn[NAME].Constructor = Popover;\n\n  $.fn[NAME].noConflict = function () {\n    $.fn[NAME] = JQUERY_NO_CONFLICT;\n    return Popover._jQueryInterface;\n  };\n\n  return Popover;\n}($);\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.0.0-beta.2): scrollspy.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nvar ScrollSpy = function () {\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n  var NAME = 'scrollspy';\n  var VERSION = '4.0.0-beta.2';\n  var DATA_KEY = 'bs.scrollspy';\n  var EVENT_KEY = \".\" + DATA_KEY;\n  var DATA_API_KEY = '.data-api';\n  var JQUERY_NO_CONFLICT = $.fn[NAME];\n  var Default = {\n    offset: 10,\n    method: 'auto',\n    target: ''\n  };\n  var DefaultType = {\n    offset: 'number',\n    method: 'string',\n    target: '(string|element)'\n  };\n  var Event = {\n    ACTIVATE: \"activate\" + EVENT_KEY,\n    SCROLL: \"scroll\" + EVENT_KEY,\n    LOAD_DATA_API: \"load\" + EVENT_KEY + DATA_API_KEY\n  };\n  var ClassName = {\n    DROPDOWN_ITEM: 'dropdown-item',\n    DROPDOWN_MENU: 'dropdown-menu',\n    ACTIVE: 'active'\n  };\n  var Selector = {\n    DATA_SPY: '[data-spy=\"scroll\"]',\n    ACTIVE: '.active',\n    NAV_LIST_GROUP: '.nav, .list-group',\n    NAV_LINKS: '.nav-link',\n    NAV_ITEMS: '.nav-item',\n    LIST_ITEMS: '.list-group-item',\n    DROPDOWN: '.dropdown',\n    DROPDOWN_ITEMS: '.dropdown-item',\n    DROPDOWN_TOGGLE: '.dropdown-toggle'\n  };\n  var OffsetMethod = {\n    OFFSET: 'offset',\n    POSITION: 'position'\n    /**\n     * ------------------------------------------------------------------------\n     * Class Definition\n     * ------------------------------------------------------------------------\n     */\n\n  };\n\n  var ScrollSpy =\n  /*#__PURE__*/\n  function () {\n    function ScrollSpy(element, config) {\n      var _this = this;\n\n      this._element = element;\n      this._scrollElement = element.tagName === 'BODY' ? window : element;\n      this._config = this._getConfig(config);\n      this._selector = this._config.target + \" \" + Selector.NAV_LINKS + \",\" + (this._config.target + \" \" + Selector.LIST_ITEMS + \",\") + (this._config.target + \" \" + Selector.DROPDOWN_ITEMS);\n      this._offsets = [];\n      this._targets = [];\n      this._activeTarget = null;\n      this._scrollHeight = 0;\n      $(this._scrollElement).on(Event.SCROLL, function (event) {\n        return _this._process(event);\n      });\n      this.refresh();\n\n      this._process();\n    } // getters\n\n\n    var _proto = ScrollSpy.prototype;\n\n    // public\n    _proto.refresh = function refresh() {\n      var _this2 = this;\n\n      var autoMethod = this._scrollElement !== this._scrollElement.window ? OffsetMethod.POSITION : OffsetMethod.OFFSET;\n      var offsetMethod = this._config.method === 'auto' ? autoMethod : this._config.method;\n      var offsetBase = offsetMethod === OffsetMethod.POSITION ? this._getScrollTop() : 0;\n      this._offsets = [];\n      this._targets = [];\n      this._scrollHeight = this._getScrollHeight();\n      var targets = $.makeArray($(this._selector));\n      targets.map(function (element) {\n        var target;\n        var targetSelector = Util.getSelectorFromElement(element);\n\n        if (targetSelector) {\n          target = $(targetSelector)[0];\n        }\n\n        if (target) {\n          var targetBCR = target.getBoundingClientRect();\n\n          if (targetBCR.width || targetBCR.height) {\n            // todo (fat): remove sketch reliance on jQuery position/offset\n            return [$(target)[offsetMethod]().top + offsetBase, targetSelector];\n          }\n        }\n\n        return null;\n      }).filter(function (item) {\n        return item;\n      }).sort(function (a, b) {\n        return a[0] - b[0];\n      }).forEach(function (item) {\n        _this2._offsets.push(item[0]);\n\n        _this2._targets.push(item[1]);\n      });\n    };\n\n    _proto.dispose = function dispose() {\n      $.removeData(this._element, DATA_KEY);\n      $(this._scrollElement).off(EVENT_KEY);\n      this._element = null;\n      this._scrollElement = null;\n      this._config = null;\n      this._selector = null;\n      this._offsets = null;\n      this._targets = null;\n      this._activeTarget = null;\n      this._scrollHeight = null;\n    }; // private\n\n\n    _proto._getConfig = function _getConfig(config) {\n      config = $.extend({}, Default, config);\n\n      if (typeof config.target !== 'string') {\n        var id = $(config.target).attr('id');\n\n        if (!id) {\n          id = Util.getUID(NAME);\n          $(config.target).attr('id', id);\n        }\n\n        config.target = \"#\" + id;\n      }\n\n      Util.typeCheckConfig(NAME, config, DefaultType);\n      return config;\n    };\n\n    _proto._getScrollTop = function _getScrollTop() {\n      return this._scrollElement === window ? this._scrollElement.pageYOffset : this._scrollElement.scrollTop;\n    };\n\n    _proto._getScrollHeight = function _getScrollHeight() {\n      return this._scrollElement.scrollHeight || Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);\n    };\n\n    _proto._getOffsetHeight = function _getOffsetHeight() {\n      return this._scrollElement === window ? window.innerHeight : this._scrollElement.getBoundingClientRect().height;\n    };\n\n    _proto._process = function _process() {\n      var scrollTop = this._getScrollTop() + this._config.offset;\n\n      var scrollHeight = this._getScrollHeight();\n\n      var maxScroll = this._config.offset + scrollHeight - this._getOffsetHeight();\n\n      if (this._scrollHeight !== scrollHeight) {\n        this.refresh();\n      }\n\n      if (scrollTop >= maxScroll) {\n        var target = this._targets[this._targets.length - 1];\n\n        if (this._activeTarget !== target) {\n          this._activate(target);\n        }\n\n        return;\n      }\n\n      if (this._activeTarget && scrollTop < this._offsets[0] && this._offsets[0] > 0) {\n        this._activeTarget = null;\n\n        this._clear();\n\n        return;\n      }\n\n      for (var i = this._offsets.length; i--;) {\n        var isActiveTarget = this._activeTarget !== this._targets[i] && scrollTop >= this._offsets[i] && (typeof this._offsets[i + 1] === 'undefined' || scrollTop < this._offsets[i + 1]);\n\n        if (isActiveTarget) {\n          this._activate(this._targets[i]);\n        }\n      }\n    };\n\n    _proto._activate = function _activate(target) {\n      this._activeTarget = target;\n\n      this._clear();\n\n      var queries = this._selector.split(','); // eslint-disable-next-line arrow-body-style\n\n\n      queries = queries.map(function (selector) {\n        return selector + \"[data-target=\\\"\" + target + \"\\\"],\" + (selector + \"[href=\\\"\" + target + \"\\\"]\");\n      });\n      var $link = $(queries.join(','));\n\n      if ($link.hasClass(ClassName.DROPDOWN_ITEM)) {\n        $link.closest(Selector.DROPDOWN).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE);\n        $link.addClass(ClassName.ACTIVE);\n      } else {\n        // Set triggered link as active\n        $link.addClass(ClassName.ACTIVE); // Set triggered links parents as active\n        // With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor\n\n        $link.parents(Selector.NAV_LIST_GROUP).prev(Selector.NAV_LINKS + \", \" + Selector.LIST_ITEMS).addClass(ClassName.ACTIVE); // Handle special case when .nav-link is inside .nav-item\n\n        $link.parents(Selector.NAV_LIST_GROUP).prev(Selector.NAV_ITEMS).children(Selector.NAV_LINKS).addClass(ClassName.ACTIVE);\n      }\n\n      $(this._scrollElement).trigger(Event.ACTIVATE, {\n        relatedTarget: target\n      });\n    };\n\n    _proto._clear = function _clear() {\n      $(this._selector).filter(Selector.ACTIVE).removeClass(ClassName.ACTIVE);\n    }; // static\n\n\n    ScrollSpy._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var data = $(this).data(DATA_KEY);\n\n        var _config = typeof config === 'object' && config;\n\n        if (!data) {\n          data = new ScrollSpy(this, _config);\n          $(this).data(DATA_KEY, data);\n        }\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new Error(\"No method named \\\"\" + config + \"\\\"\");\n          }\n\n          data[config]();\n        }\n      });\n    };\n\n    createClass(ScrollSpy, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION;\n      }\n    }, {\n      key: \"Default\",\n      get: function get() {\n        return Default;\n      }\n    }]);\n    return ScrollSpy;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  $(window).on(Event.LOAD_DATA_API, function () {\n    var scrollSpys = $.makeArray($(Selector.DATA_SPY));\n\n    for (var i = scrollSpys.length; i--;) {\n      var $spy = $(scrollSpys[i]);\n\n      ScrollSpy._jQueryInterface.call($spy, $spy.data());\n    }\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n  $.fn[NAME] = ScrollSpy._jQueryInterface;\n  $.fn[NAME].Constructor = ScrollSpy;\n\n  $.fn[NAME].noConflict = function () {\n    $.fn[NAME] = JQUERY_NO_CONFLICT;\n    return ScrollSpy._jQueryInterface;\n  };\n\n  return ScrollSpy;\n}($);\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.0.0-beta.2): tab.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nvar Tab = function () {\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n  var NAME = 'tab';\n  var VERSION = '4.0.0-beta.2';\n  var DATA_KEY = 'bs.tab';\n  var EVENT_KEY = \".\" + DATA_KEY;\n  var DATA_API_KEY = '.data-api';\n  var JQUERY_NO_CONFLICT = $.fn[NAME];\n  var TRANSITION_DURATION = 150;\n  var Event = {\n    HIDE: \"hide\" + EVENT_KEY,\n    HIDDEN: \"hidden\" + EVENT_KEY,\n    SHOW: \"show\" + EVENT_KEY,\n    SHOWN: \"shown\" + EVENT_KEY,\n    CLICK_DATA_API: \"click\" + EVENT_KEY + DATA_API_KEY\n  };\n  var ClassName = {\n    DROPDOWN_MENU: 'dropdown-menu',\n    ACTIVE: 'active',\n    DISABLED: 'disabled',\n    FADE: 'fade',\n    SHOW: 'show'\n  };\n  var Selector = {\n    DROPDOWN: '.dropdown',\n    NAV_LIST_GROUP: '.nav, .list-group',\n    ACTIVE: '.active',\n    ACTIVE_UL: '> li > .active',\n    DATA_TOGGLE: '[data-toggle=\"tab\"], [data-toggle=\"pill\"], [data-toggle=\"list\"]',\n    DROPDOWN_TOGGLE: '.dropdown-toggle',\n    DROPDOWN_ACTIVE_CHILD: '> .dropdown-menu .active'\n    /**\n     * ------------------------------------------------------------------------\n     * Class Definition\n     * ------------------------------------------------------------------------\n     */\n\n  };\n\n  var Tab =\n  /*#__PURE__*/\n  function () {\n    function Tab(element) {\n      this._element = element;\n    } // getters\n\n\n    var _proto = Tab.prototype;\n\n    // public\n    _proto.show = function show() {\n      var _this = this;\n\n      if (this._element.parentNode && this._element.parentNode.nodeType === Node.ELEMENT_NODE && $(this._element).hasClass(ClassName.ACTIVE) || $(this._element).hasClass(ClassName.DISABLED)) {\n        return;\n      }\n\n      var target;\n      var previous;\n      var listElement = $(this._element).closest(Selector.NAV_LIST_GROUP)[0];\n      var selector = Util.getSelectorFromElement(this._element);\n\n      if (listElement) {\n        var itemSelector = listElement.nodeName === 'UL' ? Selector.ACTIVE_UL : Selector.ACTIVE;\n        previous = $.makeArray($(listElement).find(itemSelector));\n        previous = previous[previous.length - 1];\n      }\n\n      var hideEvent = $.Event(Event.HIDE, {\n        relatedTarget: this._element\n      });\n      var showEvent = $.Event(Event.SHOW, {\n        relatedTarget: previous\n      });\n\n      if (previous) {\n        $(previous).trigger(hideEvent);\n      }\n\n      $(this._element).trigger(showEvent);\n\n      if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      if (selector) {\n        target = $(selector)[0];\n      }\n\n      this._activate(this._element, listElement);\n\n      var complete = function complete() {\n        var hiddenEvent = $.Event(Event.HIDDEN, {\n          relatedTarget: _this._element\n        });\n        var shownEvent = $.Event(Event.SHOWN, {\n          relatedTarget: previous\n        });\n        $(previous).trigger(hiddenEvent);\n        $(_this._element).trigger(shownEvent);\n      };\n\n      if (target) {\n        this._activate(target, target.parentNode, complete);\n      } else {\n        complete();\n      }\n    };\n\n    _proto.dispose = function dispose() {\n      $.removeData(this._element, DATA_KEY);\n      this._element = null;\n    }; // private\n\n\n    _proto._activate = function _activate(element, container, callback) {\n      var _this2 = this;\n\n      var activeElements;\n\n      if (container.nodeName === 'UL') {\n        activeElements = $(container).find(Selector.ACTIVE_UL);\n      } else {\n        activeElements = $(container).children(Selector.ACTIVE);\n      }\n\n      var active = activeElements[0];\n      var isTransitioning = callback && Util.supportsTransitionEnd() && active && $(active).hasClass(ClassName.FADE);\n\n      var complete = function complete() {\n        return _this2._transitionComplete(element, active, isTransitioning, callback);\n      };\n\n      if (active && isTransitioning) {\n        $(active).one(Util.TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION);\n      } else {\n        complete();\n      }\n\n      if (active) {\n        $(active).removeClass(ClassName.SHOW);\n      }\n    };\n\n    _proto._transitionComplete = function _transitionComplete(element, active, isTransitioning, callback) {\n      if (active) {\n        $(active).removeClass(ClassName.ACTIVE);\n        var dropdownChild = $(active.parentNode).find(Selector.DROPDOWN_ACTIVE_CHILD)[0];\n\n        if (dropdownChild) {\n          $(dropdownChild).removeClass(ClassName.ACTIVE);\n        }\n\n        if (active.getAttribute('role') === 'tab') {\n          active.setAttribute('aria-selected', false);\n        }\n      }\n\n      $(element).addClass(ClassName.ACTIVE);\n\n      if (element.getAttribute('role') === 'tab') {\n        element.setAttribute('aria-selected', true);\n      }\n\n      if (isTransitioning) {\n        Util.reflow(element);\n        $(element).addClass(ClassName.SHOW);\n      } else {\n        $(element).removeClass(ClassName.FADE);\n      }\n\n      if (element.parentNode && $(element.parentNode).hasClass(ClassName.DROPDOWN_MENU)) {\n        var dropdownElement = $(element).closest(Selector.DROPDOWN)[0];\n\n        if (dropdownElement) {\n          $(dropdownElement).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE);\n        }\n\n        element.setAttribute('aria-expanded', true);\n      }\n\n      if (callback) {\n        callback();\n      }\n    }; // static\n\n\n    Tab._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var $this = $(this);\n        var data = $this.data(DATA_KEY);\n\n        if (!data) {\n          data = new Tab(this);\n          $this.data(DATA_KEY, data);\n        }\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new Error(\"No method named \\\"\" + config + \"\\\"\");\n          }\n\n          data[config]();\n        }\n      });\n    };\n\n    createClass(Tab, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION;\n      }\n    }]);\n    return Tab;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {\n    event.preventDefault();\n\n    Tab._jQueryInterface.call($(this), 'show');\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n  $.fn[NAME] = Tab._jQueryInterface;\n  $.fn[NAME].Constructor = Tab;\n\n  $.fn[NAME].noConflict = function () {\n    $.fn[NAME] = JQUERY_NO_CONFLICT;\n    return Tab._jQueryInterface;\n  };\n\n  return Tab;\n}($);\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.0.0-alpha.6): index.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n(function () {\n  if (typeof $ === 'undefined') {\n    throw new Error('Bootstrap\\'s JavaScript requires jQuery. jQuery must be included before Bootstrap\\'s JavaScript.');\n  }\n\n  var version = $.fn.jquery.split(' ')[0].split('.');\n  var minMajor = 1;\n  var ltMajor = 2;\n  var minMinor = 9;\n  var minPatch = 1;\n  var maxMajor = 4;\n\n  if (version[0] < ltMajor && version[1] < minMinor || version[0] === minMajor && version[1] === minMinor && version[2] < minPatch || version[0] >= maxMajor) {\n    throw new Error('Bootstrap\\'s JavaScript requires at least jQuery v1.9.1 but less than v4.0.0');\n  }\n})($);\n\nexports.Util = Util;\nexports.Alert = Alert;\nexports.Button = Button;\nexports.Carousel = Carousel;\nexports.Collapse = Collapse;\nexports.Dropdown = Dropdown;\nexports.Modal = Modal;\nexports.Popover = Popover;\nexports.Scrollspy = ScrollSpy;\nexports.Tab = Tab;\nexports.Tooltip = Tooltip;\n\nreturn exports;\n\n}({},$));\n//# sourceMappingURL=bootstrap.bundle.js.map\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/bootstrap/js/bootstrap.js",
    "content": "/*!\n  * Bootstrap v4.0.0-beta.2 (https://getbootstrap.com)\n  * Copyright 2011-2017 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)\n  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n  */\nvar bootstrap = (function (exports,$,Popper) {\n'use strict';\n\n$ = $ && $.hasOwnProperty('default') ? $['default'] : $;\nPopper = Popper && Popper.hasOwnProperty('default') ? Popper['default'] : Popper;\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.0.0-beta.2): util.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nvar Util = function () {\n  /**\n   * ------------------------------------------------------------------------\n   * Private TransitionEnd Helpers\n   * ------------------------------------------------------------------------\n   */\n  var transition = false;\n  var MAX_UID = 1000000;\n  var TransitionEndEvent = {\n    WebkitTransition: 'webkitTransitionEnd',\n    MozTransition: 'transitionend',\n    OTransition: 'oTransitionEnd otransitionend',\n    transition: 'transitionend' // shoutout AngusCroll (https://goo.gl/pxwQGp)\n\n  };\n\n  function toType(obj) {\n    return {}.toString.call(obj).match(/\\s([a-zA-Z]+)/)[1].toLowerCase();\n  }\n\n  function getSpecialTransitionEndEvent() {\n    return {\n      bindType: transition.end,\n      delegateType: transition.end,\n      handle: function handle(event) {\n        if ($(event.target).is(this)) {\n          return event.handleObj.handler.apply(this, arguments); // eslint-disable-line prefer-rest-params\n        }\n\n        return undefined; // eslint-disable-line no-undefined\n      }\n    };\n  }\n\n  function transitionEndTest() {\n    if (window.QUnit) {\n      return false;\n    }\n\n    var el = document.createElement('bootstrap');\n\n    for (var name in TransitionEndEvent) {\n      if (typeof el.style[name] !== 'undefined') {\n        return {\n          end: TransitionEndEvent[name]\n        };\n      }\n    }\n\n    return false;\n  }\n\n  function transitionEndEmulator(duration) {\n    var _this = this;\n\n    var called = false;\n    $(this).one(Util.TRANSITION_END, function () {\n      called = true;\n    });\n    setTimeout(function () {\n      if (!called) {\n        Util.triggerTransitionEnd(_this);\n      }\n    }, duration);\n    return this;\n  }\n\n  function setTransitionEndSupport() {\n    transition = transitionEndTest();\n    $.fn.emulateTransitionEnd = transitionEndEmulator;\n\n    if (Util.supportsTransitionEnd()) {\n      $.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent();\n    }\n  }\n  /**\n   * --------------------------------------------------------------------------\n   * Public Util Api\n   * --------------------------------------------------------------------------\n   */\n\n\n  var Util = {\n    TRANSITION_END: 'bsTransitionEnd',\n    getUID: function getUID(prefix) {\n      do {\n        // eslint-disable-next-line no-bitwise\n        prefix += ~~(Math.random() * MAX_UID); // \"~~\" acts like a faster Math.floor() here\n      } while (document.getElementById(prefix));\n\n      return prefix;\n    },\n    getSelectorFromElement: function getSelectorFromElement(element) {\n      var selector = element.getAttribute('data-target');\n\n      if (!selector || selector === '#') {\n        selector = element.getAttribute('href') || '';\n      }\n\n      try {\n        var $selector = $(document).find(selector);\n        return $selector.length > 0 ? selector : null;\n      } catch (error) {\n        return null;\n      }\n    },\n    reflow: function reflow(element) {\n      return element.offsetHeight;\n    },\n    triggerTransitionEnd: function triggerTransitionEnd(element) {\n      $(element).trigger(transition.end);\n    },\n    supportsTransitionEnd: function supportsTransitionEnd() {\n      return Boolean(transition);\n    },\n    isElement: function isElement(obj) {\n      return (obj[0] || obj).nodeType;\n    },\n    typeCheckConfig: function typeCheckConfig(componentName, config, configTypes) {\n      for (var property in configTypes) {\n        if (Object.prototype.hasOwnProperty.call(configTypes, property)) {\n          var expectedTypes = configTypes[property];\n          var value = config[property];\n          var valueType = value && Util.isElement(value) ? 'element' : toType(value);\n\n          if (!new RegExp(expectedTypes).test(valueType)) {\n            throw new Error(componentName.toUpperCase() + \": \" + (\"Option \\\"\" + property + \"\\\" provided type \\\"\" + valueType + \"\\\" \") + (\"but expected type \\\"\" + expectedTypes + \"\\\".\"));\n          }\n        }\n      }\n    }\n  };\n  setTransitionEndSupport();\n  return Util;\n}($);\n\nfunction _defineProperties(target, props) {\n  for (var i = 0; i < props.length; i++) {\n    var descriptor = props[i];\n    descriptor.enumerable = descriptor.enumerable || false;\n    descriptor.configurable = true;\n    if (\"value\" in descriptor) descriptor.writable = true;\n    Object.defineProperty(target, descriptor.key, descriptor);\n  }\n}\n\nfunction _createClass(Constructor, protoProps, staticProps) {\n  if (protoProps) _defineProperties(Constructor.prototype, protoProps);\n  if (staticProps) _defineProperties(Constructor, staticProps);\n  return Constructor;\n}\n\nvar createClass = _createClass;\n\nfunction _inheritsLoose(subClass, superClass) {\n  subClass.prototype = Object.create(superClass.prototype);\n  subClass.prototype.constructor = subClass;\n  subClass.__proto__ = superClass;\n}\n\nvar inheritsLoose = _inheritsLoose;\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.0.0-beta.2): alert.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nvar Alert = function () {\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n  var NAME = 'alert';\n  var VERSION = '4.0.0-beta.2';\n  var DATA_KEY = 'bs.alert';\n  var EVENT_KEY = \".\" + DATA_KEY;\n  var DATA_API_KEY = '.data-api';\n  var JQUERY_NO_CONFLICT = $.fn[NAME];\n  var TRANSITION_DURATION = 150;\n  var Selector = {\n    DISMISS: '[data-dismiss=\"alert\"]'\n  };\n  var Event = {\n    CLOSE: \"close\" + EVENT_KEY,\n    CLOSED: \"closed\" + EVENT_KEY,\n    CLICK_DATA_API: \"click\" + EVENT_KEY + DATA_API_KEY\n  };\n  var ClassName = {\n    ALERT: 'alert',\n    FADE: 'fade',\n    SHOW: 'show'\n    /**\n     * ------------------------------------------------------------------------\n     * Class Definition\n     * ------------------------------------------------------------------------\n     */\n\n  };\n\n  var Alert =\n  /*#__PURE__*/\n  function () {\n    function Alert(element) {\n      this._element = element;\n    } // getters\n\n\n    var _proto = Alert.prototype;\n\n    // public\n    _proto.close = function close(element) {\n      element = element || this._element;\n\n      var rootElement = this._getRootElement(element);\n\n      var customEvent = this._triggerCloseEvent(rootElement);\n\n      if (customEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      this._removeElement(rootElement);\n    };\n\n    _proto.dispose = function dispose() {\n      $.removeData(this._element, DATA_KEY);\n      this._element = null;\n    }; // private\n\n\n    _proto._getRootElement = function _getRootElement(element) {\n      var selector = Util.getSelectorFromElement(element);\n      var parent = false;\n\n      if (selector) {\n        parent = $(selector)[0];\n      }\n\n      if (!parent) {\n        parent = $(element).closest(\".\" + ClassName.ALERT)[0];\n      }\n\n      return parent;\n    };\n\n    _proto._triggerCloseEvent = function _triggerCloseEvent(element) {\n      var closeEvent = $.Event(Event.CLOSE);\n      $(element).trigger(closeEvent);\n      return closeEvent;\n    };\n\n    _proto._removeElement = function _removeElement(element) {\n      var _this = this;\n\n      $(element).removeClass(ClassName.SHOW);\n\n      if (!Util.supportsTransitionEnd() || !$(element).hasClass(ClassName.FADE)) {\n        this._destroyElement(element);\n\n        return;\n      }\n\n      $(element).one(Util.TRANSITION_END, function (event) {\n        return _this._destroyElement(element, event);\n      }).emulateTransitionEnd(TRANSITION_DURATION);\n    };\n\n    _proto._destroyElement = function _destroyElement(element) {\n      $(element).detach().trigger(Event.CLOSED).remove();\n    }; // static\n\n\n    Alert._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var $element = $(this);\n        var data = $element.data(DATA_KEY);\n\n        if (!data) {\n          data = new Alert(this);\n          $element.data(DATA_KEY, data);\n        }\n\n        if (config === 'close') {\n          data[config](this);\n        }\n      });\n    };\n\n    Alert._handleDismiss = function _handleDismiss(alertInstance) {\n      return function (event) {\n        if (event) {\n          event.preventDefault();\n        }\n\n        alertInstance.close(this);\n      };\n    };\n\n    createClass(Alert, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION;\n      }\n    }]);\n    return Alert;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  $(document).on(Event.CLICK_DATA_API, Selector.DISMISS, Alert._handleDismiss(new Alert()));\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n  $.fn[NAME] = Alert._jQueryInterface;\n  $.fn[NAME].Constructor = Alert;\n\n  $.fn[NAME].noConflict = function () {\n    $.fn[NAME] = JQUERY_NO_CONFLICT;\n    return Alert._jQueryInterface;\n  };\n\n  return Alert;\n}($);\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.0.0-beta.2): button.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nvar Button = function () {\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n  var NAME = 'button';\n  var VERSION = '4.0.0-beta.2';\n  var DATA_KEY = 'bs.button';\n  var EVENT_KEY = \".\" + DATA_KEY;\n  var DATA_API_KEY = '.data-api';\n  var JQUERY_NO_CONFLICT = $.fn[NAME];\n  var ClassName = {\n    ACTIVE: 'active',\n    BUTTON: 'btn',\n    FOCUS: 'focus'\n  };\n  var Selector = {\n    DATA_TOGGLE_CARROT: '[data-toggle^=\"button\"]',\n    DATA_TOGGLE: '[data-toggle=\"buttons\"]',\n    INPUT: 'input',\n    ACTIVE: '.active',\n    BUTTON: '.btn'\n  };\n  var Event = {\n    CLICK_DATA_API: \"click\" + EVENT_KEY + DATA_API_KEY,\n    FOCUS_BLUR_DATA_API: \"focus\" + EVENT_KEY + DATA_API_KEY + \" \" + (\"blur\" + EVENT_KEY + DATA_API_KEY)\n    /**\n     * ------------------------------------------------------------------------\n     * Class Definition\n     * ------------------------------------------------------------------------\n     */\n\n  };\n\n  var Button =\n  /*#__PURE__*/\n  function () {\n    function Button(element) {\n      this._element = element;\n    } // getters\n\n\n    var _proto = Button.prototype;\n\n    // public\n    _proto.toggle = function toggle() {\n      var triggerChangeEvent = true;\n      var addAriaPressed = true;\n      var rootElement = $(this._element).closest(Selector.DATA_TOGGLE)[0];\n\n      if (rootElement) {\n        var input = $(this._element).find(Selector.INPUT)[0];\n\n        if (input) {\n          if (input.type === 'radio') {\n            if (input.checked && $(this._element).hasClass(ClassName.ACTIVE)) {\n              triggerChangeEvent = false;\n            } else {\n              var activeElement = $(rootElement).find(Selector.ACTIVE)[0];\n\n              if (activeElement) {\n                $(activeElement).removeClass(ClassName.ACTIVE);\n              }\n            }\n          }\n\n          if (triggerChangeEvent) {\n            if (input.hasAttribute('disabled') || rootElement.hasAttribute('disabled') || input.classList.contains('disabled') || rootElement.classList.contains('disabled')) {\n              return;\n            }\n\n            input.checked = !$(this._element).hasClass(ClassName.ACTIVE);\n            $(input).trigger('change');\n          }\n\n          input.focus();\n          addAriaPressed = false;\n        }\n      }\n\n      if (addAriaPressed) {\n        this._element.setAttribute('aria-pressed', !$(this._element).hasClass(ClassName.ACTIVE));\n      }\n\n      if (triggerChangeEvent) {\n        $(this._element).toggleClass(ClassName.ACTIVE);\n      }\n    };\n\n    _proto.dispose = function dispose() {\n      $.removeData(this._element, DATA_KEY);\n      this._element = null;\n    }; // static\n\n\n    Button._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var data = $(this).data(DATA_KEY);\n\n        if (!data) {\n          data = new Button(this);\n          $(this).data(DATA_KEY, data);\n        }\n\n        if (config === 'toggle') {\n          data[config]();\n        }\n      });\n    };\n\n    createClass(Button, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION;\n      }\n    }]);\n    return Button;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE_CARROT, function (event) {\n    event.preventDefault();\n    var button = event.target;\n\n    if (!$(button).hasClass(ClassName.BUTTON)) {\n      button = $(button).closest(Selector.BUTTON);\n    }\n\n    Button._jQueryInterface.call($(button), 'toggle');\n  }).on(Event.FOCUS_BLUR_DATA_API, Selector.DATA_TOGGLE_CARROT, function (event) {\n    var button = $(event.target).closest(Selector.BUTTON)[0];\n    $(button).toggleClass(ClassName.FOCUS, /^focus(in)?$/.test(event.type));\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n  $.fn[NAME] = Button._jQueryInterface;\n  $.fn[NAME].Constructor = Button;\n\n  $.fn[NAME].noConflict = function () {\n    $.fn[NAME] = JQUERY_NO_CONFLICT;\n    return Button._jQueryInterface;\n  };\n\n  return Button;\n}($);\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.0.0-beta.2): carousel.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nvar Carousel = function () {\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n  var NAME = 'carousel';\n  var VERSION = '4.0.0-beta.2';\n  var DATA_KEY = 'bs.carousel';\n  var EVENT_KEY = \".\" + DATA_KEY;\n  var DATA_API_KEY = '.data-api';\n  var JQUERY_NO_CONFLICT = $.fn[NAME];\n  var TRANSITION_DURATION = 600;\n  var ARROW_LEFT_KEYCODE = 37; // KeyboardEvent.which value for left arrow key\n\n  var ARROW_RIGHT_KEYCODE = 39; // KeyboardEvent.which value for right arrow key\n\n  var TOUCHEVENT_COMPAT_WAIT = 500; // Time for mouse compat events to fire after touch\n\n  var Default = {\n    interval: 5000,\n    keyboard: true,\n    slide: false,\n    pause: 'hover',\n    wrap: true\n  };\n  var DefaultType = {\n    interval: '(number|boolean)',\n    keyboard: 'boolean',\n    slide: '(boolean|string)',\n    pause: '(string|boolean)',\n    wrap: 'boolean'\n  };\n  var Direction = {\n    NEXT: 'next',\n    PREV: 'prev',\n    LEFT: 'left',\n    RIGHT: 'right'\n  };\n  var Event = {\n    SLIDE: \"slide\" + EVENT_KEY,\n    SLID: \"slid\" + EVENT_KEY,\n    KEYDOWN: \"keydown\" + EVENT_KEY,\n    MOUSEENTER: \"mouseenter\" + EVENT_KEY,\n    MOUSELEAVE: \"mouseleave\" + EVENT_KEY,\n    TOUCHEND: \"touchend\" + EVENT_KEY,\n    LOAD_DATA_API: \"load\" + EVENT_KEY + DATA_API_KEY,\n    CLICK_DATA_API: \"click\" + EVENT_KEY + DATA_API_KEY\n  };\n  var ClassName = {\n    CAROUSEL: 'carousel',\n    ACTIVE: 'active',\n    SLIDE: 'slide',\n    RIGHT: 'carousel-item-right',\n    LEFT: 'carousel-item-left',\n    NEXT: 'carousel-item-next',\n    PREV: 'carousel-item-prev',\n    ITEM: 'carousel-item'\n  };\n  var Selector = {\n    ACTIVE: '.active',\n    ACTIVE_ITEM: '.active.carousel-item',\n    ITEM: '.carousel-item',\n    NEXT_PREV: '.carousel-item-next, .carousel-item-prev',\n    INDICATORS: '.carousel-indicators',\n    DATA_SLIDE: '[data-slide], [data-slide-to]',\n    DATA_RIDE: '[data-ride=\"carousel\"]'\n    /**\n     * ------------------------------------------------------------------------\n     * Class Definition\n     * ------------------------------------------------------------------------\n     */\n\n  };\n\n  var Carousel =\n  /*#__PURE__*/\n  function () {\n    function Carousel(element, config) {\n      this._items = null;\n      this._interval = null;\n      this._activeElement = null;\n      this._isPaused = false;\n      this._isSliding = false;\n      this.touchTimeout = null;\n      this._config = this._getConfig(config);\n      this._element = $(element)[0];\n      this._indicatorsElement = $(this._element).find(Selector.INDICATORS)[0];\n\n      this._addEventListeners();\n    } // getters\n\n\n    var _proto = Carousel.prototype;\n\n    // public\n    _proto.next = function next() {\n      if (!this._isSliding) {\n        this._slide(Direction.NEXT);\n      }\n    };\n\n    _proto.nextWhenVisible = function nextWhenVisible() {\n      // Don't call next when the page isn't visible\n      // or the carousel or its parent isn't visible\n      if (!document.hidden && $(this._element).is(':visible') && $(this._element).css('visibility') !== 'hidden') {\n        this.next();\n      }\n    };\n\n    _proto.prev = function prev() {\n      if (!this._isSliding) {\n        this._slide(Direction.PREV);\n      }\n    };\n\n    _proto.pause = function pause(event) {\n      if (!event) {\n        this._isPaused = true;\n      }\n\n      if ($(this._element).find(Selector.NEXT_PREV)[0] && Util.supportsTransitionEnd()) {\n        Util.triggerTransitionEnd(this._element);\n        this.cycle(true);\n      }\n\n      clearInterval(this._interval);\n      this._interval = null;\n    };\n\n    _proto.cycle = function cycle(event) {\n      if (!event) {\n        this._isPaused = false;\n      }\n\n      if (this._interval) {\n        clearInterval(this._interval);\n        this._interval = null;\n      }\n\n      if (this._config.interval && !this._isPaused) {\n        this._interval = setInterval((document.visibilityState ? this.nextWhenVisible : this.next).bind(this), this._config.interval);\n      }\n    };\n\n    _proto.to = function to(index) {\n      var _this = this;\n\n      this._activeElement = $(this._element).find(Selector.ACTIVE_ITEM)[0];\n\n      var activeIndex = this._getItemIndex(this._activeElement);\n\n      if (index > this._items.length - 1 || index < 0) {\n        return;\n      }\n\n      if (this._isSliding) {\n        $(this._element).one(Event.SLID, function () {\n          return _this.to(index);\n        });\n        return;\n      }\n\n      if (activeIndex === index) {\n        this.pause();\n        this.cycle();\n        return;\n      }\n\n      var direction = index > activeIndex ? Direction.NEXT : Direction.PREV;\n\n      this._slide(direction, this._items[index]);\n    };\n\n    _proto.dispose = function dispose() {\n      $(this._element).off(EVENT_KEY);\n      $.removeData(this._element, DATA_KEY);\n      this._items = null;\n      this._config = null;\n      this._element = null;\n      this._interval = null;\n      this._isPaused = null;\n      this._isSliding = null;\n      this._activeElement = null;\n      this._indicatorsElement = null;\n    }; // private\n\n\n    _proto._getConfig = function _getConfig(config) {\n      config = $.extend({}, Default, config);\n      Util.typeCheckConfig(NAME, config, DefaultType);\n      return config;\n    };\n\n    _proto._addEventListeners = function _addEventListeners() {\n      var _this2 = this;\n\n      if (this._config.keyboard) {\n        $(this._element).on(Event.KEYDOWN, function (event) {\n          return _this2._keydown(event);\n        });\n      }\n\n      if (this._config.pause === 'hover') {\n        $(this._element).on(Event.MOUSEENTER, function (event) {\n          return _this2.pause(event);\n        }).on(Event.MOUSELEAVE, function (event) {\n          return _this2.cycle(event);\n        });\n\n        if ('ontouchstart' in document.documentElement) {\n          // if it's a touch-enabled device, mouseenter/leave are fired as\n          // part of the mouse compatibility events on first tap - the carousel\n          // would stop cycling until user tapped out of it;\n          // here, we listen for touchend, explicitly pause the carousel\n          // (as if it's the second time we tap on it, mouseenter compat event\n          // is NOT fired) and after a timeout (to allow for mouse compatibility\n          // events to fire) we explicitly restart cycling\n          $(this._element).on(Event.TOUCHEND, function () {\n            _this2.pause();\n\n            if (_this2.touchTimeout) {\n              clearTimeout(_this2.touchTimeout);\n            }\n\n            _this2.touchTimeout = setTimeout(function (event) {\n              return _this2.cycle(event);\n            }, TOUCHEVENT_COMPAT_WAIT + _this2._config.interval);\n          });\n        }\n      }\n    };\n\n    _proto._keydown = function _keydown(event) {\n      if (/input|textarea/i.test(event.target.tagName)) {\n        return;\n      }\n\n      switch (event.which) {\n        case ARROW_LEFT_KEYCODE:\n          event.preventDefault();\n          this.prev();\n          break;\n\n        case ARROW_RIGHT_KEYCODE:\n          event.preventDefault();\n          this.next();\n          break;\n\n        default:\n          return;\n      }\n    };\n\n    _proto._getItemIndex = function _getItemIndex(element) {\n      this._items = $.makeArray($(element).parent().find(Selector.ITEM));\n      return this._items.indexOf(element);\n    };\n\n    _proto._getItemByDirection = function _getItemByDirection(direction, activeElement) {\n      var isNextDirection = direction === Direction.NEXT;\n      var isPrevDirection = direction === Direction.PREV;\n\n      var activeIndex = this._getItemIndex(activeElement);\n\n      var lastItemIndex = this._items.length - 1;\n      var isGoingToWrap = isPrevDirection && activeIndex === 0 || isNextDirection && activeIndex === lastItemIndex;\n\n      if (isGoingToWrap && !this._config.wrap) {\n        return activeElement;\n      }\n\n      var delta = direction === Direction.PREV ? -1 : 1;\n      var itemIndex = (activeIndex + delta) % this._items.length;\n      return itemIndex === -1 ? this._items[this._items.length - 1] : this._items[itemIndex];\n    };\n\n    _proto._triggerSlideEvent = function _triggerSlideEvent(relatedTarget, eventDirectionName) {\n      var targetIndex = this._getItemIndex(relatedTarget);\n\n      var fromIndex = this._getItemIndex($(this._element).find(Selector.ACTIVE_ITEM)[0]);\n\n      var slideEvent = $.Event(Event.SLIDE, {\n        relatedTarget: relatedTarget,\n        direction: eventDirectionName,\n        from: fromIndex,\n        to: targetIndex\n      });\n      $(this._element).trigger(slideEvent);\n      return slideEvent;\n    };\n\n    _proto._setActiveIndicatorElement = function _setActiveIndicatorElement(element) {\n      if (this._indicatorsElement) {\n        $(this._indicatorsElement).find(Selector.ACTIVE).removeClass(ClassName.ACTIVE);\n\n        var nextIndicator = this._indicatorsElement.children[this._getItemIndex(element)];\n\n        if (nextIndicator) {\n          $(nextIndicator).addClass(ClassName.ACTIVE);\n        }\n      }\n    };\n\n    _proto._slide = function _slide(direction, element) {\n      var _this3 = this;\n\n      var activeElement = $(this._element).find(Selector.ACTIVE_ITEM)[0];\n\n      var activeElementIndex = this._getItemIndex(activeElement);\n\n      var nextElement = element || activeElement && this._getItemByDirection(direction, activeElement);\n\n      var nextElementIndex = this._getItemIndex(nextElement);\n\n      var isCycling = Boolean(this._interval);\n      var directionalClassName;\n      var orderClassName;\n      var eventDirectionName;\n\n      if (direction === Direction.NEXT) {\n        directionalClassName = ClassName.LEFT;\n        orderClassName = ClassName.NEXT;\n        eventDirectionName = Direction.LEFT;\n      } else {\n        directionalClassName = ClassName.RIGHT;\n        orderClassName = ClassName.PREV;\n        eventDirectionName = Direction.RIGHT;\n      }\n\n      if (nextElement && $(nextElement).hasClass(ClassName.ACTIVE)) {\n        this._isSliding = false;\n        return;\n      }\n\n      var slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName);\n\n      if (slideEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      if (!activeElement || !nextElement) {\n        // some weirdness is happening, so we bail\n        return;\n      }\n\n      this._isSliding = true;\n\n      if (isCycling) {\n        this.pause();\n      }\n\n      this._setActiveIndicatorElement(nextElement);\n\n      var slidEvent = $.Event(Event.SLID, {\n        relatedTarget: nextElement,\n        direction: eventDirectionName,\n        from: activeElementIndex,\n        to: nextElementIndex\n      });\n\n      if (Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.SLIDE)) {\n        $(nextElement).addClass(orderClassName);\n        Util.reflow(nextElement);\n        $(activeElement).addClass(directionalClassName);\n        $(nextElement).addClass(directionalClassName);\n        $(activeElement).one(Util.TRANSITION_END, function () {\n          $(nextElement).removeClass(directionalClassName + \" \" + orderClassName).addClass(ClassName.ACTIVE);\n          $(activeElement).removeClass(ClassName.ACTIVE + \" \" + orderClassName + \" \" + directionalClassName);\n          _this3._isSliding = false;\n          setTimeout(function () {\n            return $(_this3._element).trigger(slidEvent);\n          }, 0);\n        }).emulateTransitionEnd(TRANSITION_DURATION);\n      } else {\n        $(activeElement).removeClass(ClassName.ACTIVE);\n        $(nextElement).addClass(ClassName.ACTIVE);\n        this._isSliding = false;\n        $(this._element).trigger(slidEvent);\n      }\n\n      if (isCycling) {\n        this.cycle();\n      }\n    }; // static\n\n\n    Carousel._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var data = $(this).data(DATA_KEY);\n\n        var _config = $.extend({}, Default, $(this).data());\n\n        if (typeof config === 'object') {\n          $.extend(_config, config);\n        }\n\n        var action = typeof config === 'string' ? config : _config.slide;\n\n        if (!data) {\n          data = new Carousel(this, _config);\n          $(this).data(DATA_KEY, data);\n        }\n\n        if (typeof config === 'number') {\n          data.to(config);\n        } else if (typeof action === 'string') {\n          if (typeof data[action] === 'undefined') {\n            throw new Error(\"No method named \\\"\" + action + \"\\\"\");\n          }\n\n          data[action]();\n        } else if (_config.interval) {\n          data.pause();\n          data.cycle();\n        }\n      });\n    };\n\n    Carousel._dataApiClickHandler = function _dataApiClickHandler(event) {\n      var selector = Util.getSelectorFromElement(this);\n\n      if (!selector) {\n        return;\n      }\n\n      var target = $(selector)[0];\n\n      if (!target || !$(target).hasClass(ClassName.CAROUSEL)) {\n        return;\n      }\n\n      var config = $.extend({}, $(target).data(), $(this).data());\n      var slideIndex = this.getAttribute('data-slide-to');\n\n      if (slideIndex) {\n        config.interval = false;\n      }\n\n      Carousel._jQueryInterface.call($(target), config);\n\n      if (slideIndex) {\n        $(target).data(DATA_KEY).to(slideIndex);\n      }\n\n      event.preventDefault();\n    };\n\n    createClass(Carousel, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION;\n      }\n    }, {\n      key: \"Default\",\n      get: function get() {\n        return Default;\n      }\n    }]);\n    return Carousel;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  $(document).on(Event.CLICK_DATA_API, Selector.DATA_SLIDE, Carousel._dataApiClickHandler);\n  $(window).on(Event.LOAD_DATA_API, function () {\n    $(Selector.DATA_RIDE).each(function () {\n      var $carousel = $(this);\n\n      Carousel._jQueryInterface.call($carousel, $carousel.data());\n    });\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n  $.fn[NAME] = Carousel._jQueryInterface;\n  $.fn[NAME].Constructor = Carousel;\n\n  $.fn[NAME].noConflict = function () {\n    $.fn[NAME] = JQUERY_NO_CONFLICT;\n    return Carousel._jQueryInterface;\n  };\n\n  return Carousel;\n}($);\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.0.0-beta.2): collapse.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nvar Collapse = function () {\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n  var NAME = 'collapse';\n  var VERSION = '4.0.0-beta.2';\n  var DATA_KEY = 'bs.collapse';\n  var EVENT_KEY = \".\" + DATA_KEY;\n  var DATA_API_KEY = '.data-api';\n  var JQUERY_NO_CONFLICT = $.fn[NAME];\n  var TRANSITION_DURATION = 600;\n  var Default = {\n    toggle: true,\n    parent: ''\n  };\n  var DefaultType = {\n    toggle: 'boolean',\n    parent: '(string|element)'\n  };\n  var Event = {\n    SHOW: \"show\" + EVENT_KEY,\n    SHOWN: \"shown\" + EVENT_KEY,\n    HIDE: \"hide\" + EVENT_KEY,\n    HIDDEN: \"hidden\" + EVENT_KEY,\n    CLICK_DATA_API: \"click\" + EVENT_KEY + DATA_API_KEY\n  };\n  var ClassName = {\n    SHOW: 'show',\n    COLLAPSE: 'collapse',\n    COLLAPSING: 'collapsing',\n    COLLAPSED: 'collapsed'\n  };\n  var Dimension = {\n    WIDTH: 'width',\n    HEIGHT: 'height'\n  };\n  var Selector = {\n    ACTIVES: '.show, .collapsing',\n    DATA_TOGGLE: '[data-toggle=\"collapse\"]'\n    /**\n     * ------------------------------------------------------------------------\n     * Class Definition\n     * ------------------------------------------------------------------------\n     */\n\n  };\n\n  var Collapse =\n  /*#__PURE__*/\n  function () {\n    function Collapse(element, config) {\n      this._isTransitioning = false;\n      this._element = element;\n      this._config = this._getConfig(config);\n      this._triggerArray = $.makeArray($(\"[data-toggle=\\\"collapse\\\"][href=\\\"#\" + element.id + \"\\\"],\" + (\"[data-toggle=\\\"collapse\\\"][data-target=\\\"#\" + element.id + \"\\\"]\")));\n      var tabToggles = $(Selector.DATA_TOGGLE);\n\n      for (var i = 0; i < tabToggles.length; i++) {\n        var elem = tabToggles[i];\n        var selector = Util.getSelectorFromElement(elem);\n\n        if (selector !== null && $(selector).filter(element).length > 0) {\n          this._triggerArray.push(elem);\n        }\n      }\n\n      this._parent = this._config.parent ? this._getParent() : null;\n\n      if (!this._config.parent) {\n        this._addAriaAndCollapsedClass(this._element, this._triggerArray);\n      }\n\n      if (this._config.toggle) {\n        this.toggle();\n      }\n    } // getters\n\n\n    var _proto = Collapse.prototype;\n\n    // public\n    _proto.toggle = function toggle() {\n      if ($(this._element).hasClass(ClassName.SHOW)) {\n        this.hide();\n      } else {\n        this.show();\n      }\n    };\n\n    _proto.show = function show() {\n      var _this = this;\n\n      if (this._isTransitioning || $(this._element).hasClass(ClassName.SHOW)) {\n        return;\n      }\n\n      var actives;\n      var activesData;\n\n      if (this._parent) {\n        actives = $.makeArray($(this._parent).children().children(Selector.ACTIVES));\n\n        if (!actives.length) {\n          actives = null;\n        }\n      }\n\n      if (actives) {\n        activesData = $(actives).data(DATA_KEY);\n\n        if (activesData && activesData._isTransitioning) {\n          return;\n        }\n      }\n\n      var startEvent = $.Event(Event.SHOW);\n      $(this._element).trigger(startEvent);\n\n      if (startEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      if (actives) {\n        Collapse._jQueryInterface.call($(actives), 'hide');\n\n        if (!activesData) {\n          $(actives).data(DATA_KEY, null);\n        }\n      }\n\n      var dimension = this._getDimension();\n\n      $(this._element).removeClass(ClassName.COLLAPSE).addClass(ClassName.COLLAPSING);\n      this._element.style[dimension] = 0;\n\n      if (this._triggerArray.length) {\n        $(this._triggerArray).removeClass(ClassName.COLLAPSED).attr('aria-expanded', true);\n      }\n\n      this.setTransitioning(true);\n\n      var complete = function complete() {\n        $(_this._element).removeClass(ClassName.COLLAPSING).addClass(ClassName.COLLAPSE).addClass(ClassName.SHOW);\n        _this._element.style[dimension] = '';\n\n        _this.setTransitioning(false);\n\n        $(_this._element).trigger(Event.SHOWN);\n      };\n\n      if (!Util.supportsTransitionEnd()) {\n        complete();\n        return;\n      }\n\n      var capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1);\n      var scrollSize = \"scroll\" + capitalizedDimension;\n      $(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION);\n      this._element.style[dimension] = this._element[scrollSize] + \"px\";\n    };\n\n    _proto.hide = function hide() {\n      var _this2 = this;\n\n      if (this._isTransitioning || !$(this._element).hasClass(ClassName.SHOW)) {\n        return;\n      }\n\n      var startEvent = $.Event(Event.HIDE);\n      $(this._element).trigger(startEvent);\n\n      if (startEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      var dimension = this._getDimension();\n\n      this._element.style[dimension] = this._element.getBoundingClientRect()[dimension] + \"px\";\n      Util.reflow(this._element);\n      $(this._element).addClass(ClassName.COLLAPSING).removeClass(ClassName.COLLAPSE).removeClass(ClassName.SHOW);\n\n      if (this._triggerArray.length) {\n        for (var i = 0; i < this._triggerArray.length; i++) {\n          var trigger = this._triggerArray[i];\n          var selector = Util.getSelectorFromElement(trigger);\n\n          if (selector !== null) {\n            var $elem = $(selector);\n\n            if (!$elem.hasClass(ClassName.SHOW)) {\n              $(trigger).addClass(ClassName.COLLAPSED).attr('aria-expanded', false);\n            }\n          }\n        }\n      }\n\n      this.setTransitioning(true);\n\n      var complete = function complete() {\n        _this2.setTransitioning(false);\n\n        $(_this2._element).removeClass(ClassName.COLLAPSING).addClass(ClassName.COLLAPSE).trigger(Event.HIDDEN);\n      };\n\n      this._element.style[dimension] = '';\n\n      if (!Util.supportsTransitionEnd()) {\n        complete();\n        return;\n      }\n\n      $(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION);\n    };\n\n    _proto.setTransitioning = function setTransitioning(isTransitioning) {\n      this._isTransitioning = isTransitioning;\n    };\n\n    _proto.dispose = function dispose() {\n      $.removeData(this._element, DATA_KEY);\n      this._config = null;\n      this._parent = null;\n      this._element = null;\n      this._triggerArray = null;\n      this._isTransitioning = null;\n    }; // private\n\n\n    _proto._getConfig = function _getConfig(config) {\n      config = $.extend({}, Default, config);\n      config.toggle = Boolean(config.toggle); // coerce string values\n\n      Util.typeCheckConfig(NAME, config, DefaultType);\n      return config;\n    };\n\n    _proto._getDimension = function _getDimension() {\n      var hasWidth = $(this._element).hasClass(Dimension.WIDTH);\n      return hasWidth ? Dimension.WIDTH : Dimension.HEIGHT;\n    };\n\n    _proto._getParent = function _getParent() {\n      var _this3 = this;\n\n      var parent = null;\n\n      if (Util.isElement(this._config.parent)) {\n        parent = this._config.parent; // it's a jQuery object\n\n        if (typeof this._config.parent.jquery !== 'undefined') {\n          parent = this._config.parent[0];\n        }\n      } else {\n        parent = $(this._config.parent)[0];\n      }\n\n      var selector = \"[data-toggle=\\\"collapse\\\"][data-parent=\\\"\" + this._config.parent + \"\\\"]\";\n      $(parent).find(selector).each(function (i, element) {\n        _this3._addAriaAndCollapsedClass(Collapse._getTargetFromElement(element), [element]);\n      });\n      return parent;\n    };\n\n    _proto._addAriaAndCollapsedClass = function _addAriaAndCollapsedClass(element, triggerArray) {\n      if (element) {\n        var isOpen = $(element).hasClass(ClassName.SHOW);\n\n        if (triggerArray.length) {\n          $(triggerArray).toggleClass(ClassName.COLLAPSED, !isOpen).attr('aria-expanded', isOpen);\n        }\n      }\n    }; // static\n\n\n    Collapse._getTargetFromElement = function _getTargetFromElement(element) {\n      var selector = Util.getSelectorFromElement(element);\n      return selector ? $(selector)[0] : null;\n    };\n\n    Collapse._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var $this = $(this);\n        var data = $this.data(DATA_KEY);\n\n        var _config = $.extend({}, Default, $this.data(), typeof config === 'object' && config);\n\n        if (!data && _config.toggle && /show|hide/.test(config)) {\n          _config.toggle = false;\n        }\n\n        if (!data) {\n          data = new Collapse(this, _config);\n          $this.data(DATA_KEY, data);\n        }\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new Error(\"No method named \\\"\" + config + \"\\\"\");\n          }\n\n          data[config]();\n        }\n      });\n    };\n\n    createClass(Collapse, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION;\n      }\n    }, {\n      key: \"Default\",\n      get: function get() {\n        return Default;\n      }\n    }]);\n    return Collapse;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {\n    // preventDefault only for <a> elements (which change the URL) not inside the collapsible element\n    if (event.currentTarget.tagName === 'A') {\n      event.preventDefault();\n    }\n\n    var $trigger = $(this);\n    var selector = Util.getSelectorFromElement(this);\n    $(selector).each(function () {\n      var $target = $(this);\n      var data = $target.data(DATA_KEY);\n      var config = data ? 'toggle' : $trigger.data();\n\n      Collapse._jQueryInterface.call($target, config);\n    });\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n  $.fn[NAME] = Collapse._jQueryInterface;\n  $.fn[NAME].Constructor = Collapse;\n\n  $.fn[NAME].noConflict = function () {\n    $.fn[NAME] = JQUERY_NO_CONFLICT;\n    return Collapse._jQueryInterface;\n  };\n\n  return Collapse;\n}($);\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.0.0-beta.2): dropdown.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nvar Dropdown = function () {\n  /**\n   * Check for Popper dependency\n   * Popper - https://popper.js.org\n   */\n  if (typeof Popper === 'undefined') {\n    throw new Error('Bootstrap dropdown require Popper.js (https://popper.js.org)');\n  }\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n\n  var NAME = 'dropdown';\n  var VERSION = '4.0.0-beta.2';\n  var DATA_KEY = 'bs.dropdown';\n  var EVENT_KEY = \".\" + DATA_KEY;\n  var DATA_API_KEY = '.data-api';\n  var JQUERY_NO_CONFLICT = $.fn[NAME];\n  var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key\n\n  var SPACE_KEYCODE = 32; // KeyboardEvent.which value for space key\n\n  var TAB_KEYCODE = 9; // KeyboardEvent.which value for tab key\n\n  var ARROW_UP_KEYCODE = 38; // KeyboardEvent.which value for up arrow key\n\n  var ARROW_DOWN_KEYCODE = 40; // KeyboardEvent.which value for down arrow key\n\n  var RIGHT_MOUSE_BUTTON_WHICH = 3; // MouseEvent.which value for the right button (assuming a right-handed mouse)\n\n  var REGEXP_KEYDOWN = new RegExp(ARROW_UP_KEYCODE + \"|\" + ARROW_DOWN_KEYCODE + \"|\" + ESCAPE_KEYCODE);\n  var Event = {\n    HIDE: \"hide\" + EVENT_KEY,\n    HIDDEN: \"hidden\" + EVENT_KEY,\n    SHOW: \"show\" + EVENT_KEY,\n    SHOWN: \"shown\" + EVENT_KEY,\n    CLICK: \"click\" + EVENT_KEY,\n    CLICK_DATA_API: \"click\" + EVENT_KEY + DATA_API_KEY,\n    KEYDOWN_DATA_API: \"keydown\" + EVENT_KEY + DATA_API_KEY,\n    KEYUP_DATA_API: \"keyup\" + EVENT_KEY + DATA_API_KEY\n  };\n  var ClassName = {\n    DISABLED: 'disabled',\n    SHOW: 'show',\n    DROPUP: 'dropup',\n    MENURIGHT: 'dropdown-menu-right',\n    MENULEFT: 'dropdown-menu-left'\n  };\n  var Selector = {\n    DATA_TOGGLE: '[data-toggle=\"dropdown\"]',\n    FORM_CHILD: '.dropdown form',\n    MENU: '.dropdown-menu',\n    NAVBAR_NAV: '.navbar-nav',\n    VISIBLE_ITEMS: '.dropdown-menu .dropdown-item:not(.disabled)'\n  };\n  var AttachmentMap = {\n    TOP: 'top-start',\n    TOPEND: 'top-end',\n    BOTTOM: 'bottom-start',\n    BOTTOMEND: 'bottom-end'\n  };\n  var Default = {\n    offset: 0,\n    flip: true\n  };\n  var DefaultType = {\n    offset: '(number|string|function)',\n    flip: 'boolean'\n    /**\n     * ------------------------------------------------------------------------\n     * Class Definition\n     * ------------------------------------------------------------------------\n     */\n\n  };\n\n  var Dropdown =\n  /*#__PURE__*/\n  function () {\n    function Dropdown(element, config) {\n      this._element = element;\n      this._popper = null;\n      this._config = this._getConfig(config);\n      this._menu = this._getMenuElement();\n      this._inNavbar = this._detectNavbar();\n\n      this._addEventListeners();\n    } // getters\n\n\n    var _proto = Dropdown.prototype;\n\n    // public\n    _proto.toggle = function toggle() {\n      if (this._element.disabled || $(this._element).hasClass(ClassName.DISABLED)) {\n        return;\n      }\n\n      var parent = Dropdown._getParentFromElement(this._element);\n\n      var isActive = $(this._menu).hasClass(ClassName.SHOW);\n\n      Dropdown._clearMenus();\n\n      if (isActive) {\n        return;\n      }\n\n      var relatedTarget = {\n        relatedTarget: this._element\n      };\n      var showEvent = $.Event(Event.SHOW, relatedTarget);\n      $(parent).trigger(showEvent);\n\n      if (showEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      var element = this._element; // for dropup with alignment we use the parent as popper container\n\n      if ($(parent).hasClass(ClassName.DROPUP)) {\n        if ($(this._menu).hasClass(ClassName.MENULEFT) || $(this._menu).hasClass(ClassName.MENURIGHT)) {\n          element = parent;\n        }\n      }\n\n      this._popper = new Popper(element, this._menu, this._getPopperConfig()); // if this is a touch-enabled device we add extra\n      // empty mouseover listeners to the body's immediate children;\n      // only needed because of broken event delegation on iOS\n      // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html\n\n      if ('ontouchstart' in document.documentElement && !$(parent).closest(Selector.NAVBAR_NAV).length) {\n        $('body').children().on('mouseover', null, $.noop);\n      }\n\n      this._element.focus();\n\n      this._element.setAttribute('aria-expanded', true);\n\n      $(this._menu).toggleClass(ClassName.SHOW);\n      $(parent).toggleClass(ClassName.SHOW).trigger($.Event(Event.SHOWN, relatedTarget));\n    };\n\n    _proto.dispose = function dispose() {\n      $.removeData(this._element, DATA_KEY);\n      $(this._element).off(EVENT_KEY);\n      this._element = null;\n      this._menu = null;\n\n      if (this._popper !== null) {\n        this._popper.destroy();\n      }\n\n      this._popper = null;\n    };\n\n    _proto.update = function update() {\n      this._inNavbar = this._detectNavbar();\n\n      if (this._popper !== null) {\n        this._popper.scheduleUpdate();\n      }\n    }; // private\n\n\n    _proto._addEventListeners = function _addEventListeners() {\n      var _this = this;\n\n      $(this._element).on(Event.CLICK, function (event) {\n        event.preventDefault();\n        event.stopPropagation();\n\n        _this.toggle();\n      });\n    };\n\n    _proto._getConfig = function _getConfig(config) {\n      config = $.extend({}, this.constructor.Default, $(this._element).data(), config);\n      Util.typeCheckConfig(NAME, config, this.constructor.DefaultType);\n      return config;\n    };\n\n    _proto._getMenuElement = function _getMenuElement() {\n      if (!this._menu) {\n        var parent = Dropdown._getParentFromElement(this._element);\n\n        this._menu = $(parent).find(Selector.MENU)[0];\n      }\n\n      return this._menu;\n    };\n\n    _proto._getPlacement = function _getPlacement() {\n      var $parentDropdown = $(this._element).parent();\n      var placement = AttachmentMap.BOTTOM; // Handle dropup\n\n      if ($parentDropdown.hasClass(ClassName.DROPUP)) {\n        placement = AttachmentMap.TOP;\n\n        if ($(this._menu).hasClass(ClassName.MENURIGHT)) {\n          placement = AttachmentMap.TOPEND;\n        }\n      } else if ($(this._menu).hasClass(ClassName.MENURIGHT)) {\n        placement = AttachmentMap.BOTTOMEND;\n      }\n\n      return placement;\n    };\n\n    _proto._detectNavbar = function _detectNavbar() {\n      return $(this._element).closest('.navbar').length > 0;\n    };\n\n    _proto._getPopperConfig = function _getPopperConfig() {\n      var _this2 = this;\n\n      var offsetConf = {};\n\n      if (typeof this._config.offset === 'function') {\n        offsetConf.fn = function (data) {\n          data.offsets = $.extend({}, data.offsets, _this2._config.offset(data.offsets) || {});\n          return data;\n        };\n      } else {\n        offsetConf.offset = this._config.offset;\n      }\n\n      var popperConfig = {\n        placement: this._getPlacement(),\n        modifiers: {\n          offset: offsetConf,\n          flip: {\n            enabled: this._config.flip\n          }\n        } // Disable Popper.js for Dropdown in Navbar\n\n      };\n\n      if (this._inNavbar) {\n        popperConfig.modifiers.applyStyle = {\n          enabled: !this._inNavbar\n        };\n      }\n\n      return popperConfig;\n    }; // static\n\n\n    Dropdown._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var data = $(this).data(DATA_KEY);\n\n        var _config = typeof config === 'object' ? config : null;\n\n        if (!data) {\n          data = new Dropdown(this, _config);\n          $(this).data(DATA_KEY, data);\n        }\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new Error(\"No method named \\\"\" + config + \"\\\"\");\n          }\n\n          data[config]();\n        }\n      });\n    };\n\n    Dropdown._clearMenus = function _clearMenus(event) {\n      if (event && (event.which === RIGHT_MOUSE_BUTTON_WHICH || event.type === 'keyup' && event.which !== TAB_KEYCODE)) {\n        return;\n      }\n\n      var toggles = $.makeArray($(Selector.DATA_TOGGLE));\n\n      for (var i = 0; i < toggles.length; i++) {\n        var parent = Dropdown._getParentFromElement(toggles[i]);\n\n        var context = $(toggles[i]).data(DATA_KEY);\n        var relatedTarget = {\n          relatedTarget: toggles[i]\n        };\n\n        if (!context) {\n          continue;\n        }\n\n        var dropdownMenu = context._menu;\n\n        if (!$(parent).hasClass(ClassName.SHOW)) {\n          continue;\n        }\n\n        if (event && (event.type === 'click' && /input|textarea/i.test(event.target.tagName) || event.type === 'keyup' && event.which === TAB_KEYCODE) && $.contains(parent, event.target)) {\n          continue;\n        }\n\n        var hideEvent = $.Event(Event.HIDE, relatedTarget);\n        $(parent).trigger(hideEvent);\n\n        if (hideEvent.isDefaultPrevented()) {\n          continue;\n        } // if this is a touch-enabled device we remove the extra\n        // empty mouseover listeners we added for iOS support\n\n\n        if ('ontouchstart' in document.documentElement) {\n          $('body').children().off('mouseover', null, $.noop);\n        }\n\n        toggles[i].setAttribute('aria-expanded', 'false');\n        $(dropdownMenu).removeClass(ClassName.SHOW);\n        $(parent).removeClass(ClassName.SHOW).trigger($.Event(Event.HIDDEN, relatedTarget));\n      }\n    };\n\n    Dropdown._getParentFromElement = function _getParentFromElement(element) {\n      var parent;\n      var selector = Util.getSelectorFromElement(element);\n\n      if (selector) {\n        parent = $(selector)[0];\n      }\n\n      return parent || element.parentNode;\n    };\n\n    Dropdown._dataApiKeydownHandler = function _dataApiKeydownHandler(event) {\n      if (!REGEXP_KEYDOWN.test(event.which) || /button/i.test(event.target.tagName) && event.which === SPACE_KEYCODE || /input|textarea/i.test(event.target.tagName)) {\n        return;\n      }\n\n      event.preventDefault();\n      event.stopPropagation();\n\n      if (this.disabled || $(this).hasClass(ClassName.DISABLED)) {\n        return;\n      }\n\n      var parent = Dropdown._getParentFromElement(this);\n\n      var isActive = $(parent).hasClass(ClassName.SHOW);\n\n      if (!isActive && (event.which !== ESCAPE_KEYCODE || event.which !== SPACE_KEYCODE) || isActive && (event.which === ESCAPE_KEYCODE || event.which === SPACE_KEYCODE)) {\n        if (event.which === ESCAPE_KEYCODE) {\n          var toggle = $(parent).find(Selector.DATA_TOGGLE)[0];\n          $(toggle).trigger('focus');\n        }\n\n        $(this).trigger('click');\n        return;\n      }\n\n      var items = $(parent).find(Selector.VISIBLE_ITEMS).get();\n\n      if (!items.length) {\n        return;\n      }\n\n      var index = items.indexOf(event.target);\n\n      if (event.which === ARROW_UP_KEYCODE && index > 0) {\n        // up\n        index--;\n      }\n\n      if (event.which === ARROW_DOWN_KEYCODE && index < items.length - 1) {\n        // down\n        index++;\n      }\n\n      if (index < 0) {\n        index = 0;\n      }\n\n      items[index].focus();\n    };\n\n    createClass(Dropdown, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION;\n      }\n    }, {\n      key: \"Default\",\n      get: function get() {\n        return Default;\n      }\n    }, {\n      key: \"DefaultType\",\n      get: function get() {\n        return DefaultType;\n      }\n    }]);\n    return Dropdown;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  $(document).on(Event.KEYDOWN_DATA_API, Selector.DATA_TOGGLE, Dropdown._dataApiKeydownHandler).on(Event.KEYDOWN_DATA_API, Selector.MENU, Dropdown._dataApiKeydownHandler).on(Event.CLICK_DATA_API + \" \" + Event.KEYUP_DATA_API, Dropdown._clearMenus).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {\n    event.preventDefault();\n    event.stopPropagation();\n\n    Dropdown._jQueryInterface.call($(this), 'toggle');\n  }).on(Event.CLICK_DATA_API, Selector.FORM_CHILD, function (e) {\n    e.stopPropagation();\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n  $.fn[NAME] = Dropdown._jQueryInterface;\n  $.fn[NAME].Constructor = Dropdown;\n\n  $.fn[NAME].noConflict = function () {\n    $.fn[NAME] = JQUERY_NO_CONFLICT;\n    return Dropdown._jQueryInterface;\n  };\n\n  return Dropdown;\n}($, Popper);\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.0.0-beta.2): modal.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nvar Modal = function () {\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n  var NAME = 'modal';\n  var VERSION = '4.0.0-beta.2';\n  var DATA_KEY = 'bs.modal';\n  var EVENT_KEY = \".\" + DATA_KEY;\n  var DATA_API_KEY = '.data-api';\n  var JQUERY_NO_CONFLICT = $.fn[NAME];\n  var TRANSITION_DURATION = 300;\n  var BACKDROP_TRANSITION_DURATION = 150;\n  var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key\n\n  var Default = {\n    backdrop: true,\n    keyboard: true,\n    focus: true,\n    show: true\n  };\n  var DefaultType = {\n    backdrop: '(boolean|string)',\n    keyboard: 'boolean',\n    focus: 'boolean',\n    show: 'boolean'\n  };\n  var Event = {\n    HIDE: \"hide\" + EVENT_KEY,\n    HIDDEN: \"hidden\" + EVENT_KEY,\n    SHOW: \"show\" + EVENT_KEY,\n    SHOWN: \"shown\" + EVENT_KEY,\n    FOCUSIN: \"focusin\" + EVENT_KEY,\n    RESIZE: \"resize\" + EVENT_KEY,\n    CLICK_DISMISS: \"click.dismiss\" + EVENT_KEY,\n    KEYDOWN_DISMISS: \"keydown.dismiss\" + EVENT_KEY,\n    MOUSEUP_DISMISS: \"mouseup.dismiss\" + EVENT_KEY,\n    MOUSEDOWN_DISMISS: \"mousedown.dismiss\" + EVENT_KEY,\n    CLICK_DATA_API: \"click\" + EVENT_KEY + DATA_API_KEY\n  };\n  var ClassName = {\n    SCROLLBAR_MEASURER: 'modal-scrollbar-measure',\n    BACKDROP: 'modal-backdrop',\n    OPEN: 'modal-open',\n    FADE: 'fade',\n    SHOW: 'show'\n  };\n  var Selector = {\n    DIALOG: '.modal-dialog',\n    DATA_TOGGLE: '[data-toggle=\"modal\"]',\n    DATA_DISMISS: '[data-dismiss=\"modal\"]',\n    FIXED_CONTENT: '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top',\n    STICKY_CONTENT: '.sticky-top',\n    NAVBAR_TOGGLER: '.navbar-toggler'\n    /**\n     * ------------------------------------------------------------------------\n     * Class Definition\n     * ------------------------------------------------------------------------\n     */\n\n  };\n\n  var Modal =\n  /*#__PURE__*/\n  function () {\n    function Modal(element, config) {\n      this._config = this._getConfig(config);\n      this._element = element;\n      this._dialog = $(element).find(Selector.DIALOG)[0];\n      this._backdrop = null;\n      this._isShown = false;\n      this._isBodyOverflowing = false;\n      this._ignoreBackdropClick = false;\n      this._originalBodyPadding = 0;\n      this._scrollbarWidth = 0;\n    } // getters\n\n\n    var _proto = Modal.prototype;\n\n    // public\n    _proto.toggle = function toggle(relatedTarget) {\n      return this._isShown ? this.hide() : this.show(relatedTarget);\n    };\n\n    _proto.show = function show(relatedTarget) {\n      var _this = this;\n\n      if (this._isTransitioning || this._isShown) {\n        return;\n      }\n\n      if (Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.FADE)) {\n        this._isTransitioning = true;\n      }\n\n      var showEvent = $.Event(Event.SHOW, {\n        relatedTarget: relatedTarget\n      });\n      $(this._element).trigger(showEvent);\n\n      if (this._isShown || showEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      this._isShown = true;\n\n      this._checkScrollbar();\n\n      this._setScrollbar();\n\n      this._adjustDialog();\n\n      $(document.body).addClass(ClassName.OPEN);\n\n      this._setEscapeEvent();\n\n      this._setResizeEvent();\n\n      $(this._element).on(Event.CLICK_DISMISS, Selector.DATA_DISMISS, function (event) {\n        return _this.hide(event);\n      });\n      $(this._dialog).on(Event.MOUSEDOWN_DISMISS, function () {\n        $(_this._element).one(Event.MOUSEUP_DISMISS, function (event) {\n          if ($(event.target).is(_this._element)) {\n            _this._ignoreBackdropClick = true;\n          }\n        });\n      });\n\n      this._showBackdrop(function () {\n        return _this._showElement(relatedTarget);\n      });\n    };\n\n    _proto.hide = function hide(event) {\n      var _this2 = this;\n\n      if (event) {\n        event.preventDefault();\n      }\n\n      if (this._isTransitioning || !this._isShown) {\n        return;\n      }\n\n      var hideEvent = $.Event(Event.HIDE);\n      $(this._element).trigger(hideEvent);\n\n      if (!this._isShown || hideEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      this._isShown = false;\n      var transition = Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.FADE);\n\n      if (transition) {\n        this._isTransitioning = true;\n      }\n\n      this._setEscapeEvent();\n\n      this._setResizeEvent();\n\n      $(document).off(Event.FOCUSIN);\n      $(this._element).removeClass(ClassName.SHOW);\n      $(this._element).off(Event.CLICK_DISMISS);\n      $(this._dialog).off(Event.MOUSEDOWN_DISMISS);\n\n      if (transition) {\n        $(this._element).one(Util.TRANSITION_END, function (event) {\n          return _this2._hideModal(event);\n        }).emulateTransitionEnd(TRANSITION_DURATION);\n      } else {\n        this._hideModal();\n      }\n    };\n\n    _proto.dispose = function dispose() {\n      $.removeData(this._element, DATA_KEY);\n      $(window, document, this._element, this._backdrop).off(EVENT_KEY);\n      this._config = null;\n      this._element = null;\n      this._dialog = null;\n      this._backdrop = null;\n      this._isShown = null;\n      this._isBodyOverflowing = null;\n      this._ignoreBackdropClick = null;\n      this._scrollbarWidth = null;\n    };\n\n    _proto.handleUpdate = function handleUpdate() {\n      this._adjustDialog();\n    }; // private\n\n\n    _proto._getConfig = function _getConfig(config) {\n      config = $.extend({}, Default, config);\n      Util.typeCheckConfig(NAME, config, DefaultType);\n      return config;\n    };\n\n    _proto._showElement = function _showElement(relatedTarget) {\n      var _this3 = this;\n\n      var transition = Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.FADE);\n\n      if (!this._element.parentNode || this._element.parentNode.nodeType !== Node.ELEMENT_NODE) {\n        // don't move modals dom position\n        document.body.appendChild(this._element);\n      }\n\n      this._element.style.display = 'block';\n\n      this._element.removeAttribute('aria-hidden');\n\n      this._element.scrollTop = 0;\n\n      if (transition) {\n        Util.reflow(this._element);\n      }\n\n      $(this._element).addClass(ClassName.SHOW);\n\n      if (this._config.focus) {\n        this._enforceFocus();\n      }\n\n      var shownEvent = $.Event(Event.SHOWN, {\n        relatedTarget: relatedTarget\n      });\n\n      var transitionComplete = function transitionComplete() {\n        if (_this3._config.focus) {\n          _this3._element.focus();\n        }\n\n        _this3._isTransitioning = false;\n        $(_this3._element).trigger(shownEvent);\n      };\n\n      if (transition) {\n        $(this._dialog).one(Util.TRANSITION_END, transitionComplete).emulateTransitionEnd(TRANSITION_DURATION);\n      } else {\n        transitionComplete();\n      }\n    };\n\n    _proto._enforceFocus = function _enforceFocus() {\n      var _this4 = this;\n\n      $(document).off(Event.FOCUSIN) // guard against infinite focus loop\n      .on(Event.FOCUSIN, function (event) {\n        if (document !== event.target && _this4._element !== event.target && !$(_this4._element).has(event.target).length) {\n          _this4._element.focus();\n        }\n      });\n    };\n\n    _proto._setEscapeEvent = function _setEscapeEvent() {\n      var _this5 = this;\n\n      if (this._isShown && this._config.keyboard) {\n        $(this._element).on(Event.KEYDOWN_DISMISS, function (event) {\n          if (event.which === ESCAPE_KEYCODE) {\n            event.preventDefault();\n\n            _this5.hide();\n          }\n        });\n      } else if (!this._isShown) {\n        $(this._element).off(Event.KEYDOWN_DISMISS);\n      }\n    };\n\n    _proto._setResizeEvent = function _setResizeEvent() {\n      var _this6 = this;\n\n      if (this._isShown) {\n        $(window).on(Event.RESIZE, function (event) {\n          return _this6.handleUpdate(event);\n        });\n      } else {\n        $(window).off(Event.RESIZE);\n      }\n    };\n\n    _proto._hideModal = function _hideModal() {\n      var _this7 = this;\n\n      this._element.style.display = 'none';\n\n      this._element.setAttribute('aria-hidden', true);\n\n      this._isTransitioning = false;\n\n      this._showBackdrop(function () {\n        $(document.body).removeClass(ClassName.OPEN);\n\n        _this7._resetAdjustments();\n\n        _this7._resetScrollbar();\n\n        $(_this7._element).trigger(Event.HIDDEN);\n      });\n    };\n\n    _proto._removeBackdrop = function _removeBackdrop() {\n      if (this._backdrop) {\n        $(this._backdrop).remove();\n        this._backdrop = null;\n      }\n    };\n\n    _proto._showBackdrop = function _showBackdrop(callback) {\n      var _this8 = this;\n\n      var animate = $(this._element).hasClass(ClassName.FADE) ? ClassName.FADE : '';\n\n      if (this._isShown && this._config.backdrop) {\n        var doAnimate = Util.supportsTransitionEnd() && animate;\n        this._backdrop = document.createElement('div');\n        this._backdrop.className = ClassName.BACKDROP;\n\n        if (animate) {\n          $(this._backdrop).addClass(animate);\n        }\n\n        $(this._backdrop).appendTo(document.body);\n        $(this._element).on(Event.CLICK_DISMISS, function (event) {\n          if (_this8._ignoreBackdropClick) {\n            _this8._ignoreBackdropClick = false;\n            return;\n          }\n\n          if (event.target !== event.currentTarget) {\n            return;\n          }\n\n          if (_this8._config.backdrop === 'static') {\n            _this8._element.focus();\n          } else {\n            _this8.hide();\n          }\n        });\n\n        if (doAnimate) {\n          Util.reflow(this._backdrop);\n        }\n\n        $(this._backdrop).addClass(ClassName.SHOW);\n\n        if (!callback) {\n          return;\n        }\n\n        if (!doAnimate) {\n          callback();\n          return;\n        }\n\n        $(this._backdrop).one(Util.TRANSITION_END, callback).emulateTransitionEnd(BACKDROP_TRANSITION_DURATION);\n      } else if (!this._isShown && this._backdrop) {\n        $(this._backdrop).removeClass(ClassName.SHOW);\n\n        var callbackRemove = function callbackRemove() {\n          _this8._removeBackdrop();\n\n          if (callback) {\n            callback();\n          }\n        };\n\n        if (Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.FADE)) {\n          $(this._backdrop).one(Util.TRANSITION_END, callbackRemove).emulateTransitionEnd(BACKDROP_TRANSITION_DURATION);\n        } else {\n          callbackRemove();\n        }\n      } else if (callback) {\n        callback();\n      }\n    }; // ----------------------------------------------------------------------\n    // the following methods are used to handle overflowing modals\n    // todo (fat): these should probably be refactored out of modal.js\n    // ----------------------------------------------------------------------\n\n\n    _proto._adjustDialog = function _adjustDialog() {\n      var isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight;\n\n      if (!this._isBodyOverflowing && isModalOverflowing) {\n        this._element.style.paddingLeft = this._scrollbarWidth + \"px\";\n      }\n\n      if (this._isBodyOverflowing && !isModalOverflowing) {\n        this._element.style.paddingRight = this._scrollbarWidth + \"px\";\n      }\n    };\n\n    _proto._resetAdjustments = function _resetAdjustments() {\n      this._element.style.paddingLeft = '';\n      this._element.style.paddingRight = '';\n    };\n\n    _proto._checkScrollbar = function _checkScrollbar() {\n      var rect = document.body.getBoundingClientRect();\n      this._isBodyOverflowing = rect.left + rect.right < window.innerWidth;\n      this._scrollbarWidth = this._getScrollbarWidth();\n    };\n\n    _proto._setScrollbar = function _setScrollbar() {\n      var _this9 = this;\n\n      if (this._isBodyOverflowing) {\n        // Note: DOMNode.style.paddingRight returns the actual value or '' if not set\n        //   while $(DOMNode).css('padding-right') returns the calculated value or 0 if not set\n        // Adjust fixed content padding\n        $(Selector.FIXED_CONTENT).each(function (index, element) {\n          var actualPadding = $(element)[0].style.paddingRight;\n          var calculatedPadding = $(element).css('padding-right');\n          $(element).data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + _this9._scrollbarWidth + \"px\");\n        }); // Adjust sticky content margin\n\n        $(Selector.STICKY_CONTENT).each(function (index, element) {\n          var actualMargin = $(element)[0].style.marginRight;\n          var calculatedMargin = $(element).css('margin-right');\n          $(element).data('margin-right', actualMargin).css('margin-right', parseFloat(calculatedMargin) - _this9._scrollbarWidth + \"px\");\n        }); // Adjust navbar-toggler margin\n\n        $(Selector.NAVBAR_TOGGLER).each(function (index, element) {\n          var actualMargin = $(element)[0].style.marginRight;\n          var calculatedMargin = $(element).css('margin-right');\n          $(element).data('margin-right', actualMargin).css('margin-right', parseFloat(calculatedMargin) + _this9._scrollbarWidth + \"px\");\n        }); // Adjust body padding\n\n        var actualPadding = document.body.style.paddingRight;\n        var calculatedPadding = $('body').css('padding-right');\n        $('body').data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + this._scrollbarWidth + \"px\");\n      }\n    };\n\n    _proto._resetScrollbar = function _resetScrollbar() {\n      // Restore fixed content padding\n      $(Selector.FIXED_CONTENT).each(function (index, element) {\n        var padding = $(element).data('padding-right');\n\n        if (typeof padding !== 'undefined') {\n          $(element).css('padding-right', padding).removeData('padding-right');\n        }\n      }); // Restore sticky content and navbar-toggler margin\n\n      $(Selector.STICKY_CONTENT + \", \" + Selector.NAVBAR_TOGGLER).each(function (index, element) {\n        var margin = $(element).data('margin-right');\n\n        if (typeof margin !== 'undefined') {\n          $(element).css('margin-right', margin).removeData('margin-right');\n        }\n      }); // Restore body padding\n\n      var padding = $('body').data('padding-right');\n\n      if (typeof padding !== 'undefined') {\n        $('body').css('padding-right', padding).removeData('padding-right');\n      }\n    };\n\n    _proto._getScrollbarWidth = function _getScrollbarWidth() {\n      // thx d.walsh\n      var scrollDiv = document.createElement('div');\n      scrollDiv.className = ClassName.SCROLLBAR_MEASURER;\n      document.body.appendChild(scrollDiv);\n      var scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth;\n      document.body.removeChild(scrollDiv);\n      return scrollbarWidth;\n    }; // static\n\n\n    Modal._jQueryInterface = function _jQueryInterface(config, relatedTarget) {\n      return this.each(function () {\n        var data = $(this).data(DATA_KEY);\n\n        var _config = $.extend({}, Modal.Default, $(this).data(), typeof config === 'object' && config);\n\n        if (!data) {\n          data = new Modal(this, _config);\n          $(this).data(DATA_KEY, data);\n        }\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new Error(\"No method named \\\"\" + config + \"\\\"\");\n          }\n\n          data[config](relatedTarget);\n        } else if (_config.show) {\n          data.show(relatedTarget);\n        }\n      });\n    };\n\n    createClass(Modal, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION;\n      }\n    }, {\n      key: \"Default\",\n      get: function get() {\n        return Default;\n      }\n    }]);\n    return Modal;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {\n    var _this10 = this;\n\n    var target;\n    var selector = Util.getSelectorFromElement(this);\n\n    if (selector) {\n      target = $(selector)[0];\n    }\n\n    var config = $(target).data(DATA_KEY) ? 'toggle' : $.extend({}, $(target).data(), $(this).data());\n\n    if (this.tagName === 'A' || this.tagName === 'AREA') {\n      event.preventDefault();\n    }\n\n    var $target = $(target).one(Event.SHOW, function (showEvent) {\n      if (showEvent.isDefaultPrevented()) {\n        // only register focus restorer if modal will actually get shown\n        return;\n      }\n\n      $target.one(Event.HIDDEN, function () {\n        if ($(_this10).is(':visible')) {\n          _this10.focus();\n        }\n      });\n    });\n\n    Modal._jQueryInterface.call($(target), config, this);\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n  $.fn[NAME] = Modal._jQueryInterface;\n  $.fn[NAME].Constructor = Modal;\n\n  $.fn[NAME].noConflict = function () {\n    $.fn[NAME] = JQUERY_NO_CONFLICT;\n    return Modal._jQueryInterface;\n  };\n\n  return Modal;\n}($);\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.0.0-beta.2): tooltip.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nvar Tooltip = function () {\n  /**\n   * Check for Popper dependency\n   * Popper - https://popper.js.org\n   */\n  if (typeof Popper === 'undefined') {\n    throw new Error('Bootstrap tooltips require Popper.js (https://popper.js.org)');\n  }\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n\n  var NAME = 'tooltip';\n  var VERSION = '4.0.0-beta.2';\n  var DATA_KEY = 'bs.tooltip';\n  var EVENT_KEY = \".\" + DATA_KEY;\n  var JQUERY_NO_CONFLICT = $.fn[NAME];\n  var TRANSITION_DURATION = 150;\n  var CLASS_PREFIX = 'bs-tooltip';\n  var BSCLS_PREFIX_REGEX = new RegExp(\"(^|\\\\s)\" + CLASS_PREFIX + \"\\\\S+\", 'g');\n  var DefaultType = {\n    animation: 'boolean',\n    template: 'string',\n    title: '(string|element|function)',\n    trigger: 'string',\n    delay: '(number|object)',\n    html: 'boolean',\n    selector: '(string|boolean)',\n    placement: '(string|function)',\n    offset: '(number|string)',\n    container: '(string|element|boolean)',\n    fallbackPlacement: '(string|array)'\n  };\n  var AttachmentMap = {\n    AUTO: 'auto',\n    TOP: 'top',\n    RIGHT: 'right',\n    BOTTOM: 'bottom',\n    LEFT: 'left'\n  };\n  var Default = {\n    animation: true,\n    template: '<div class=\"tooltip\" role=\"tooltip\">' + '<div class=\"arrow\"></div>' + '<div class=\"tooltip-inner\"></div></div>',\n    trigger: 'hover focus',\n    title: '',\n    delay: 0,\n    html: false,\n    selector: false,\n    placement: 'top',\n    offset: 0,\n    container: false,\n    fallbackPlacement: 'flip'\n  };\n  var HoverState = {\n    SHOW: 'show',\n    OUT: 'out'\n  };\n  var Event = {\n    HIDE: \"hide\" + EVENT_KEY,\n    HIDDEN: \"hidden\" + EVENT_KEY,\n    SHOW: \"show\" + EVENT_KEY,\n    SHOWN: \"shown\" + EVENT_KEY,\n    INSERTED: \"inserted\" + EVENT_KEY,\n    CLICK: \"click\" + EVENT_KEY,\n    FOCUSIN: \"focusin\" + EVENT_KEY,\n    FOCUSOUT: \"focusout\" + EVENT_KEY,\n    MOUSEENTER: \"mouseenter\" + EVENT_KEY,\n    MOUSELEAVE: \"mouseleave\" + EVENT_KEY\n  };\n  var ClassName = {\n    FADE: 'fade',\n    SHOW: 'show'\n  };\n  var Selector = {\n    TOOLTIP: '.tooltip',\n    TOOLTIP_INNER: '.tooltip-inner',\n    ARROW: '.arrow'\n  };\n  var Trigger = {\n    HOVER: 'hover',\n    FOCUS: 'focus',\n    CLICK: 'click',\n    MANUAL: 'manual'\n    /**\n     * ------------------------------------------------------------------------\n     * Class Definition\n     * ------------------------------------------------------------------------\n     */\n\n  };\n\n  var Tooltip =\n  /*#__PURE__*/\n  function () {\n    function Tooltip(element, config) {\n      // private\n      this._isEnabled = true;\n      this._timeout = 0;\n      this._hoverState = '';\n      this._activeTrigger = {};\n      this._popper = null; // protected\n\n      this.element = element;\n      this.config = this._getConfig(config);\n      this.tip = null;\n\n      this._setListeners();\n    } // getters\n\n\n    var _proto = Tooltip.prototype;\n\n    // public\n    _proto.enable = function enable() {\n      this._isEnabled = true;\n    };\n\n    _proto.disable = function disable() {\n      this._isEnabled = false;\n    };\n\n    _proto.toggleEnabled = function toggleEnabled() {\n      this._isEnabled = !this._isEnabled;\n    };\n\n    _proto.toggle = function toggle(event) {\n      if (!this._isEnabled) {\n        return;\n      }\n\n      if (event) {\n        var dataKey = this.constructor.DATA_KEY;\n        var context = $(event.currentTarget).data(dataKey);\n\n        if (!context) {\n          context = new this.constructor(event.currentTarget, this._getDelegateConfig());\n          $(event.currentTarget).data(dataKey, context);\n        }\n\n        context._activeTrigger.click = !context._activeTrigger.click;\n\n        if (context._isWithActiveTrigger()) {\n          context._enter(null, context);\n        } else {\n          context._leave(null, context);\n        }\n      } else {\n        if ($(this.getTipElement()).hasClass(ClassName.SHOW)) {\n          this._leave(null, this);\n\n          return;\n        }\n\n        this._enter(null, this);\n      }\n    };\n\n    _proto.dispose = function dispose() {\n      clearTimeout(this._timeout);\n      $.removeData(this.element, this.constructor.DATA_KEY);\n      $(this.element).off(this.constructor.EVENT_KEY);\n      $(this.element).closest('.modal').off('hide.bs.modal');\n\n      if (this.tip) {\n        $(this.tip).remove();\n      }\n\n      this._isEnabled = null;\n      this._timeout = null;\n      this._hoverState = null;\n      this._activeTrigger = null;\n\n      if (this._popper !== null) {\n        this._popper.destroy();\n      }\n\n      this._popper = null;\n      this.element = null;\n      this.config = null;\n      this.tip = null;\n    };\n\n    _proto.show = function show() {\n      var _this = this;\n\n      if ($(this.element).css('display') === 'none') {\n        throw new Error('Please use show on visible elements');\n      }\n\n      var showEvent = $.Event(this.constructor.Event.SHOW);\n\n      if (this.isWithContent() && this._isEnabled) {\n        $(this.element).trigger(showEvent);\n        var isInTheDom = $.contains(this.element.ownerDocument.documentElement, this.element);\n\n        if (showEvent.isDefaultPrevented() || !isInTheDom) {\n          return;\n        }\n\n        var tip = this.getTipElement();\n        var tipId = Util.getUID(this.constructor.NAME);\n        tip.setAttribute('id', tipId);\n        this.element.setAttribute('aria-describedby', tipId);\n        this.setContent();\n\n        if (this.config.animation) {\n          $(tip).addClass(ClassName.FADE);\n        }\n\n        var placement = typeof this.config.placement === 'function' ? this.config.placement.call(this, tip, this.element) : this.config.placement;\n\n        var attachment = this._getAttachment(placement);\n\n        this.addAttachmentClass(attachment);\n        var container = this.config.container === false ? document.body : $(this.config.container);\n        $(tip).data(this.constructor.DATA_KEY, this);\n\n        if (!$.contains(this.element.ownerDocument.documentElement, this.tip)) {\n          $(tip).appendTo(container);\n        }\n\n        $(this.element).trigger(this.constructor.Event.INSERTED);\n        this._popper = new Popper(this.element, tip, {\n          placement: attachment,\n          modifiers: {\n            offset: {\n              offset: this.config.offset\n            },\n            flip: {\n              behavior: this.config.fallbackPlacement\n            },\n            arrow: {\n              element: Selector.ARROW\n            }\n          },\n          onCreate: function onCreate(data) {\n            if (data.originalPlacement !== data.placement) {\n              _this._handlePopperPlacementChange(data);\n            }\n          },\n          onUpdate: function onUpdate(data) {\n            _this._handlePopperPlacementChange(data);\n          }\n        });\n        $(tip).addClass(ClassName.SHOW); // if this is a touch-enabled device we add extra\n        // empty mouseover listeners to the body's immediate children;\n        // only needed because of broken event delegation on iOS\n        // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html\n\n        if ('ontouchstart' in document.documentElement) {\n          $('body').children().on('mouseover', null, $.noop);\n        }\n\n        var complete = function complete() {\n          if (_this.config.animation) {\n            _this._fixTransition();\n          }\n\n          var prevHoverState = _this._hoverState;\n          _this._hoverState = null;\n          $(_this.element).trigger(_this.constructor.Event.SHOWN);\n\n          if (prevHoverState === HoverState.OUT) {\n            _this._leave(null, _this);\n          }\n        };\n\n        if (Util.supportsTransitionEnd() && $(this.tip).hasClass(ClassName.FADE)) {\n          $(this.tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(Tooltip._TRANSITION_DURATION);\n        } else {\n          complete();\n        }\n      }\n    };\n\n    _proto.hide = function hide(callback) {\n      var _this2 = this;\n\n      var tip = this.getTipElement();\n      var hideEvent = $.Event(this.constructor.Event.HIDE);\n\n      var complete = function complete() {\n        if (_this2._hoverState !== HoverState.SHOW && tip.parentNode) {\n          tip.parentNode.removeChild(tip);\n        }\n\n        _this2._cleanTipClass();\n\n        _this2.element.removeAttribute('aria-describedby');\n\n        $(_this2.element).trigger(_this2.constructor.Event.HIDDEN);\n\n        if (_this2._popper !== null) {\n          _this2._popper.destroy();\n        }\n\n        if (callback) {\n          callback();\n        }\n      };\n\n      $(this.element).trigger(hideEvent);\n\n      if (hideEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      $(tip).removeClass(ClassName.SHOW); // if this is a touch-enabled device we remove the extra\n      // empty mouseover listeners we added for iOS support\n\n      if ('ontouchstart' in document.documentElement) {\n        $('body').children().off('mouseover', null, $.noop);\n      }\n\n      this._activeTrigger[Trigger.CLICK] = false;\n      this._activeTrigger[Trigger.FOCUS] = false;\n      this._activeTrigger[Trigger.HOVER] = false;\n\n      if (Util.supportsTransitionEnd() && $(this.tip).hasClass(ClassName.FADE)) {\n        $(tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION);\n      } else {\n        complete();\n      }\n\n      this._hoverState = '';\n    };\n\n    _proto.update = function update() {\n      if (this._popper !== null) {\n        this._popper.scheduleUpdate();\n      }\n    }; // protected\n\n\n    _proto.isWithContent = function isWithContent() {\n      return Boolean(this.getTitle());\n    };\n\n    _proto.addAttachmentClass = function addAttachmentClass(attachment) {\n      $(this.getTipElement()).addClass(CLASS_PREFIX + \"-\" + attachment);\n    };\n\n    _proto.getTipElement = function getTipElement() {\n      this.tip = this.tip || $(this.config.template)[0];\n      return this.tip;\n    };\n\n    _proto.setContent = function setContent() {\n      var $tip = $(this.getTipElement());\n      this.setElementContent($tip.find(Selector.TOOLTIP_INNER), this.getTitle());\n      $tip.removeClass(ClassName.FADE + \" \" + ClassName.SHOW);\n    };\n\n    _proto.setElementContent = function setElementContent($element, content) {\n      var html = this.config.html;\n\n      if (typeof content === 'object' && (content.nodeType || content.jquery)) {\n        // content is a DOM node or a jQuery\n        if (html) {\n          if (!$(content).parent().is($element)) {\n            $element.empty().append(content);\n          }\n        } else {\n          $element.text($(content).text());\n        }\n      } else {\n        $element[html ? 'html' : 'text'](content);\n      }\n    };\n\n    _proto.getTitle = function getTitle() {\n      var title = this.element.getAttribute('data-original-title');\n\n      if (!title) {\n        title = typeof this.config.title === 'function' ? this.config.title.call(this.element) : this.config.title;\n      }\n\n      return title;\n    }; // private\n\n\n    _proto._getAttachment = function _getAttachment(placement) {\n      return AttachmentMap[placement.toUpperCase()];\n    };\n\n    _proto._setListeners = function _setListeners() {\n      var _this3 = this;\n\n      var triggers = this.config.trigger.split(' ');\n      triggers.forEach(function (trigger) {\n        if (trigger === 'click') {\n          $(_this3.element).on(_this3.constructor.Event.CLICK, _this3.config.selector, function (event) {\n            return _this3.toggle(event);\n          });\n        } else if (trigger !== Trigger.MANUAL) {\n          var eventIn = trigger === Trigger.HOVER ? _this3.constructor.Event.MOUSEENTER : _this3.constructor.Event.FOCUSIN;\n          var eventOut = trigger === Trigger.HOVER ? _this3.constructor.Event.MOUSELEAVE : _this3.constructor.Event.FOCUSOUT;\n          $(_this3.element).on(eventIn, _this3.config.selector, function (event) {\n            return _this3._enter(event);\n          }).on(eventOut, _this3.config.selector, function (event) {\n            return _this3._leave(event);\n          });\n        }\n\n        $(_this3.element).closest('.modal').on('hide.bs.modal', function () {\n          return _this3.hide();\n        });\n      });\n\n      if (this.config.selector) {\n        this.config = $.extend({}, this.config, {\n          trigger: 'manual',\n          selector: ''\n        });\n      } else {\n        this._fixTitle();\n      }\n    };\n\n    _proto._fixTitle = function _fixTitle() {\n      var titleType = typeof this.element.getAttribute('data-original-title');\n\n      if (this.element.getAttribute('title') || titleType !== 'string') {\n        this.element.setAttribute('data-original-title', this.element.getAttribute('title') || '');\n        this.element.setAttribute('title', '');\n      }\n    };\n\n    _proto._enter = function _enter(event, context) {\n      var dataKey = this.constructor.DATA_KEY;\n      context = context || $(event.currentTarget).data(dataKey);\n\n      if (!context) {\n        context = new this.constructor(event.currentTarget, this._getDelegateConfig());\n        $(event.currentTarget).data(dataKey, context);\n      }\n\n      if (event) {\n        context._activeTrigger[event.type === 'focusin' ? Trigger.FOCUS : Trigger.HOVER] = true;\n      }\n\n      if ($(context.getTipElement()).hasClass(ClassName.SHOW) || context._hoverState === HoverState.SHOW) {\n        context._hoverState = HoverState.SHOW;\n        return;\n      }\n\n      clearTimeout(context._timeout);\n      context._hoverState = HoverState.SHOW;\n\n      if (!context.config.delay || !context.config.delay.show) {\n        context.show();\n        return;\n      }\n\n      context._timeout = setTimeout(function () {\n        if (context._hoverState === HoverState.SHOW) {\n          context.show();\n        }\n      }, context.config.delay.show);\n    };\n\n    _proto._leave = function _leave(event, context) {\n      var dataKey = this.constructor.DATA_KEY;\n      context = context || $(event.currentTarget).data(dataKey);\n\n      if (!context) {\n        context = new this.constructor(event.currentTarget, this._getDelegateConfig());\n        $(event.currentTarget).data(dataKey, context);\n      }\n\n      if (event) {\n        context._activeTrigger[event.type === 'focusout' ? Trigger.FOCUS : Trigger.HOVER] = false;\n      }\n\n      if (context._isWithActiveTrigger()) {\n        return;\n      }\n\n      clearTimeout(context._timeout);\n      context._hoverState = HoverState.OUT;\n\n      if (!context.config.delay || !context.config.delay.hide) {\n        context.hide();\n        return;\n      }\n\n      context._timeout = setTimeout(function () {\n        if (context._hoverState === HoverState.OUT) {\n          context.hide();\n        }\n      }, context.config.delay.hide);\n    };\n\n    _proto._isWithActiveTrigger = function _isWithActiveTrigger() {\n      for (var trigger in this._activeTrigger) {\n        if (this._activeTrigger[trigger]) {\n          return true;\n        }\n      }\n\n      return false;\n    };\n\n    _proto._getConfig = function _getConfig(config) {\n      config = $.extend({}, this.constructor.Default, $(this.element).data(), config);\n\n      if (typeof config.delay === 'number') {\n        config.delay = {\n          show: config.delay,\n          hide: config.delay\n        };\n      }\n\n      if (typeof config.title === 'number') {\n        config.title = config.title.toString();\n      }\n\n      if (typeof config.content === 'number') {\n        config.content = config.content.toString();\n      }\n\n      Util.typeCheckConfig(NAME, config, this.constructor.DefaultType);\n      return config;\n    };\n\n    _proto._getDelegateConfig = function _getDelegateConfig() {\n      var config = {};\n\n      if (this.config) {\n        for (var key in this.config) {\n          if (this.constructor.Default[key] !== this.config[key]) {\n            config[key] = this.config[key];\n          }\n        }\n      }\n\n      return config;\n    };\n\n    _proto._cleanTipClass = function _cleanTipClass() {\n      var $tip = $(this.getTipElement());\n      var tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX);\n\n      if (tabClass !== null && tabClass.length > 0) {\n        $tip.removeClass(tabClass.join(''));\n      }\n    };\n\n    _proto._handlePopperPlacementChange = function _handlePopperPlacementChange(data) {\n      this._cleanTipClass();\n\n      this.addAttachmentClass(this._getAttachment(data.placement));\n    };\n\n    _proto._fixTransition = function _fixTransition() {\n      var tip = this.getTipElement();\n      var initConfigAnimation = this.config.animation;\n\n      if (tip.getAttribute('x-placement') !== null) {\n        return;\n      }\n\n      $(tip).removeClass(ClassName.FADE);\n      this.config.animation = false;\n      this.hide();\n      this.show();\n      this.config.animation = initConfigAnimation;\n    }; // static\n\n\n    Tooltip._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var data = $(this).data(DATA_KEY);\n\n        var _config = typeof config === 'object' && config;\n\n        if (!data && /dispose|hide/.test(config)) {\n          return;\n        }\n\n        if (!data) {\n          data = new Tooltip(this, _config);\n          $(this).data(DATA_KEY, data);\n        }\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new Error(\"No method named \\\"\" + config + \"\\\"\");\n          }\n\n          data[config]();\n        }\n      });\n    };\n\n    createClass(Tooltip, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION;\n      }\n    }, {\n      key: \"Default\",\n      get: function get() {\n        return Default;\n      }\n    }, {\n      key: \"NAME\",\n      get: function get() {\n        return NAME;\n      }\n    }, {\n      key: \"DATA_KEY\",\n      get: function get() {\n        return DATA_KEY;\n      }\n    }, {\n      key: \"Event\",\n      get: function get() {\n        return Event;\n      }\n    }, {\n      key: \"EVENT_KEY\",\n      get: function get() {\n        return EVENT_KEY;\n      }\n    }, {\n      key: \"DefaultType\",\n      get: function get() {\n        return DefaultType;\n      }\n    }]);\n    return Tooltip;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n\n  $.fn[NAME] = Tooltip._jQueryInterface;\n  $.fn[NAME].Constructor = Tooltip;\n\n  $.fn[NAME].noConflict = function () {\n    $.fn[NAME] = JQUERY_NO_CONFLICT;\n    return Tooltip._jQueryInterface;\n  };\n\n  return Tooltip;\n}($, Popper);\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.0.0-beta.2): popover.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nvar Popover = function () {\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n  var NAME = 'popover';\n  var VERSION = '4.0.0-beta.2';\n  var DATA_KEY = 'bs.popover';\n  var EVENT_KEY = \".\" + DATA_KEY;\n  var JQUERY_NO_CONFLICT = $.fn[NAME];\n  var CLASS_PREFIX = 'bs-popover';\n  var BSCLS_PREFIX_REGEX = new RegExp(\"(^|\\\\s)\" + CLASS_PREFIX + \"\\\\S+\", 'g');\n  var Default = $.extend({}, Tooltip.Default, {\n    placement: 'right',\n    trigger: 'click',\n    content: '',\n    template: '<div class=\"popover\" role=\"tooltip\">' + '<div class=\"arrow\"></div>' + '<h3 class=\"popover-header\"></h3>' + '<div class=\"popover-body\"></div></div>'\n  });\n  var DefaultType = $.extend({}, Tooltip.DefaultType, {\n    content: '(string|element|function)'\n  });\n  var ClassName = {\n    FADE: 'fade',\n    SHOW: 'show'\n  };\n  var Selector = {\n    TITLE: '.popover-header',\n    CONTENT: '.popover-body'\n  };\n  var Event = {\n    HIDE: \"hide\" + EVENT_KEY,\n    HIDDEN: \"hidden\" + EVENT_KEY,\n    SHOW: \"show\" + EVENT_KEY,\n    SHOWN: \"shown\" + EVENT_KEY,\n    INSERTED: \"inserted\" + EVENT_KEY,\n    CLICK: \"click\" + EVENT_KEY,\n    FOCUSIN: \"focusin\" + EVENT_KEY,\n    FOCUSOUT: \"focusout\" + EVENT_KEY,\n    MOUSEENTER: \"mouseenter\" + EVENT_KEY,\n    MOUSELEAVE: \"mouseleave\" + EVENT_KEY\n    /**\n     * ------------------------------------------------------------------------\n     * Class Definition\n     * ------------------------------------------------------------------------\n     */\n\n  };\n\n  var Popover =\n  /*#__PURE__*/\n  function (_Tooltip) {\n    inheritsLoose(Popover, _Tooltip);\n\n    function Popover() {\n      return _Tooltip.apply(this, arguments) || this;\n    }\n\n    var _proto = Popover.prototype;\n\n    // overrides\n    _proto.isWithContent = function isWithContent() {\n      return this.getTitle() || this._getContent();\n    };\n\n    _proto.addAttachmentClass = function addAttachmentClass(attachment) {\n      $(this.getTipElement()).addClass(CLASS_PREFIX + \"-\" + attachment);\n    };\n\n    _proto.getTipElement = function getTipElement() {\n      this.tip = this.tip || $(this.config.template)[0];\n      return this.tip;\n    };\n\n    _proto.setContent = function setContent() {\n      var $tip = $(this.getTipElement()); // we use append for html objects to maintain js events\n\n      this.setElementContent($tip.find(Selector.TITLE), this.getTitle());\n      this.setElementContent($tip.find(Selector.CONTENT), this._getContent());\n      $tip.removeClass(ClassName.FADE + \" \" + ClassName.SHOW);\n    }; // private\n\n\n    _proto._getContent = function _getContent() {\n      return this.element.getAttribute('data-content') || (typeof this.config.content === 'function' ? this.config.content.call(this.element) : this.config.content);\n    };\n\n    _proto._cleanTipClass = function _cleanTipClass() {\n      var $tip = $(this.getTipElement());\n      var tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX);\n\n      if (tabClass !== null && tabClass.length > 0) {\n        $tip.removeClass(tabClass.join(''));\n      }\n    }; // static\n\n\n    Popover._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var data = $(this).data(DATA_KEY);\n\n        var _config = typeof config === 'object' ? config : null;\n\n        if (!data && /destroy|hide/.test(config)) {\n          return;\n        }\n\n        if (!data) {\n          data = new Popover(this, _config);\n          $(this).data(DATA_KEY, data);\n        }\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new Error(\"No method named \\\"\" + config + \"\\\"\");\n          }\n\n          data[config]();\n        }\n      });\n    };\n\n    createClass(Popover, null, [{\n      key: \"VERSION\",\n      // getters\n      get: function get() {\n        return VERSION;\n      }\n    }, {\n      key: \"Default\",\n      get: function get() {\n        return Default;\n      }\n    }, {\n      key: \"NAME\",\n      get: function get() {\n        return NAME;\n      }\n    }, {\n      key: \"DATA_KEY\",\n      get: function get() {\n        return DATA_KEY;\n      }\n    }, {\n      key: \"Event\",\n      get: function get() {\n        return Event;\n      }\n    }, {\n      key: \"EVENT_KEY\",\n      get: function get() {\n        return EVENT_KEY;\n      }\n    }, {\n      key: \"DefaultType\",\n      get: function get() {\n        return DefaultType;\n      }\n    }]);\n    return Popover;\n  }(Tooltip);\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n\n  $.fn[NAME] = Popover._jQueryInterface;\n  $.fn[NAME].Constructor = Popover;\n\n  $.fn[NAME].noConflict = function () {\n    $.fn[NAME] = JQUERY_NO_CONFLICT;\n    return Popover._jQueryInterface;\n  };\n\n  return Popover;\n}($);\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.0.0-beta.2): scrollspy.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nvar ScrollSpy = function () {\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n  var NAME = 'scrollspy';\n  var VERSION = '4.0.0-beta.2';\n  var DATA_KEY = 'bs.scrollspy';\n  var EVENT_KEY = \".\" + DATA_KEY;\n  var DATA_API_KEY = '.data-api';\n  var JQUERY_NO_CONFLICT = $.fn[NAME];\n  var Default = {\n    offset: 10,\n    method: 'auto',\n    target: ''\n  };\n  var DefaultType = {\n    offset: 'number',\n    method: 'string',\n    target: '(string|element)'\n  };\n  var Event = {\n    ACTIVATE: \"activate\" + EVENT_KEY,\n    SCROLL: \"scroll\" + EVENT_KEY,\n    LOAD_DATA_API: \"load\" + EVENT_KEY + DATA_API_KEY\n  };\n  var ClassName = {\n    DROPDOWN_ITEM: 'dropdown-item',\n    DROPDOWN_MENU: 'dropdown-menu',\n    ACTIVE: 'active'\n  };\n  var Selector = {\n    DATA_SPY: '[data-spy=\"scroll\"]',\n    ACTIVE: '.active',\n    NAV_LIST_GROUP: '.nav, .list-group',\n    NAV_LINKS: '.nav-link',\n    NAV_ITEMS: '.nav-item',\n    LIST_ITEMS: '.list-group-item',\n    DROPDOWN: '.dropdown',\n    DROPDOWN_ITEMS: '.dropdown-item',\n    DROPDOWN_TOGGLE: '.dropdown-toggle'\n  };\n  var OffsetMethod = {\n    OFFSET: 'offset',\n    POSITION: 'position'\n    /**\n     * ------------------------------------------------------------------------\n     * Class Definition\n     * ------------------------------------------------------------------------\n     */\n\n  };\n\n  var ScrollSpy =\n  /*#__PURE__*/\n  function () {\n    function ScrollSpy(element, config) {\n      var _this = this;\n\n      this._element = element;\n      this._scrollElement = element.tagName === 'BODY' ? window : element;\n      this._config = this._getConfig(config);\n      this._selector = this._config.target + \" \" + Selector.NAV_LINKS + \",\" + (this._config.target + \" \" + Selector.LIST_ITEMS + \",\") + (this._config.target + \" \" + Selector.DROPDOWN_ITEMS);\n      this._offsets = [];\n      this._targets = [];\n      this._activeTarget = null;\n      this._scrollHeight = 0;\n      $(this._scrollElement).on(Event.SCROLL, function (event) {\n        return _this._process(event);\n      });\n      this.refresh();\n\n      this._process();\n    } // getters\n\n\n    var _proto = ScrollSpy.prototype;\n\n    // public\n    _proto.refresh = function refresh() {\n      var _this2 = this;\n\n      var autoMethod = this._scrollElement !== this._scrollElement.window ? OffsetMethod.POSITION : OffsetMethod.OFFSET;\n      var offsetMethod = this._config.method === 'auto' ? autoMethod : this._config.method;\n      var offsetBase = offsetMethod === OffsetMethod.POSITION ? this._getScrollTop() : 0;\n      this._offsets = [];\n      this._targets = [];\n      this._scrollHeight = this._getScrollHeight();\n      var targets = $.makeArray($(this._selector));\n      targets.map(function (element) {\n        var target;\n        var targetSelector = Util.getSelectorFromElement(element);\n\n        if (targetSelector) {\n          target = $(targetSelector)[0];\n        }\n\n        if (target) {\n          var targetBCR = target.getBoundingClientRect();\n\n          if (targetBCR.width || targetBCR.height) {\n            // todo (fat): remove sketch reliance on jQuery position/offset\n            return [$(target)[offsetMethod]().top + offsetBase, targetSelector];\n          }\n        }\n\n        return null;\n      }).filter(function (item) {\n        return item;\n      }).sort(function (a, b) {\n        return a[0] - b[0];\n      }).forEach(function (item) {\n        _this2._offsets.push(item[0]);\n\n        _this2._targets.push(item[1]);\n      });\n    };\n\n    _proto.dispose = function dispose() {\n      $.removeData(this._element, DATA_KEY);\n      $(this._scrollElement).off(EVENT_KEY);\n      this._element = null;\n      this._scrollElement = null;\n      this._config = null;\n      this._selector = null;\n      this._offsets = null;\n      this._targets = null;\n      this._activeTarget = null;\n      this._scrollHeight = null;\n    }; // private\n\n\n    _proto._getConfig = function _getConfig(config) {\n      config = $.extend({}, Default, config);\n\n      if (typeof config.target !== 'string') {\n        var id = $(config.target).attr('id');\n\n        if (!id) {\n          id = Util.getUID(NAME);\n          $(config.target).attr('id', id);\n        }\n\n        config.target = \"#\" + id;\n      }\n\n      Util.typeCheckConfig(NAME, config, DefaultType);\n      return config;\n    };\n\n    _proto._getScrollTop = function _getScrollTop() {\n      return this._scrollElement === window ? this._scrollElement.pageYOffset : this._scrollElement.scrollTop;\n    };\n\n    _proto._getScrollHeight = function _getScrollHeight() {\n      return this._scrollElement.scrollHeight || Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);\n    };\n\n    _proto._getOffsetHeight = function _getOffsetHeight() {\n      return this._scrollElement === window ? window.innerHeight : this._scrollElement.getBoundingClientRect().height;\n    };\n\n    _proto._process = function _process() {\n      var scrollTop = this._getScrollTop() + this._config.offset;\n\n      var scrollHeight = this._getScrollHeight();\n\n      var maxScroll = this._config.offset + scrollHeight - this._getOffsetHeight();\n\n      if (this._scrollHeight !== scrollHeight) {\n        this.refresh();\n      }\n\n      if (scrollTop >= maxScroll) {\n        var target = this._targets[this._targets.length - 1];\n\n        if (this._activeTarget !== target) {\n          this._activate(target);\n        }\n\n        return;\n      }\n\n      if (this._activeTarget && scrollTop < this._offsets[0] && this._offsets[0] > 0) {\n        this._activeTarget = null;\n\n        this._clear();\n\n        return;\n      }\n\n      for (var i = this._offsets.length; i--;) {\n        var isActiveTarget = this._activeTarget !== this._targets[i] && scrollTop >= this._offsets[i] && (typeof this._offsets[i + 1] === 'undefined' || scrollTop < this._offsets[i + 1]);\n\n        if (isActiveTarget) {\n          this._activate(this._targets[i]);\n        }\n      }\n    };\n\n    _proto._activate = function _activate(target) {\n      this._activeTarget = target;\n\n      this._clear();\n\n      var queries = this._selector.split(','); // eslint-disable-next-line arrow-body-style\n\n\n      queries = queries.map(function (selector) {\n        return selector + \"[data-target=\\\"\" + target + \"\\\"],\" + (selector + \"[href=\\\"\" + target + \"\\\"]\");\n      });\n      var $link = $(queries.join(','));\n\n      if ($link.hasClass(ClassName.DROPDOWN_ITEM)) {\n        $link.closest(Selector.DROPDOWN).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE);\n        $link.addClass(ClassName.ACTIVE);\n      } else {\n        // Set triggered link as active\n        $link.addClass(ClassName.ACTIVE); // Set triggered links parents as active\n        // With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor\n\n        $link.parents(Selector.NAV_LIST_GROUP).prev(Selector.NAV_LINKS + \", \" + Selector.LIST_ITEMS).addClass(ClassName.ACTIVE); // Handle special case when .nav-link is inside .nav-item\n\n        $link.parents(Selector.NAV_LIST_GROUP).prev(Selector.NAV_ITEMS).children(Selector.NAV_LINKS).addClass(ClassName.ACTIVE);\n      }\n\n      $(this._scrollElement).trigger(Event.ACTIVATE, {\n        relatedTarget: target\n      });\n    };\n\n    _proto._clear = function _clear() {\n      $(this._selector).filter(Selector.ACTIVE).removeClass(ClassName.ACTIVE);\n    }; // static\n\n\n    ScrollSpy._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var data = $(this).data(DATA_KEY);\n\n        var _config = typeof config === 'object' && config;\n\n        if (!data) {\n          data = new ScrollSpy(this, _config);\n          $(this).data(DATA_KEY, data);\n        }\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new Error(\"No method named \\\"\" + config + \"\\\"\");\n          }\n\n          data[config]();\n        }\n      });\n    };\n\n    createClass(ScrollSpy, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION;\n      }\n    }, {\n      key: \"Default\",\n      get: function get() {\n        return Default;\n      }\n    }]);\n    return ScrollSpy;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  $(window).on(Event.LOAD_DATA_API, function () {\n    var scrollSpys = $.makeArray($(Selector.DATA_SPY));\n\n    for (var i = scrollSpys.length; i--;) {\n      var $spy = $(scrollSpys[i]);\n\n      ScrollSpy._jQueryInterface.call($spy, $spy.data());\n    }\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n  $.fn[NAME] = ScrollSpy._jQueryInterface;\n  $.fn[NAME].Constructor = ScrollSpy;\n\n  $.fn[NAME].noConflict = function () {\n    $.fn[NAME] = JQUERY_NO_CONFLICT;\n    return ScrollSpy._jQueryInterface;\n  };\n\n  return ScrollSpy;\n}($);\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.0.0-beta.2): tab.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nvar Tab = function () {\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n  var NAME = 'tab';\n  var VERSION = '4.0.0-beta.2';\n  var DATA_KEY = 'bs.tab';\n  var EVENT_KEY = \".\" + DATA_KEY;\n  var DATA_API_KEY = '.data-api';\n  var JQUERY_NO_CONFLICT = $.fn[NAME];\n  var TRANSITION_DURATION = 150;\n  var Event = {\n    HIDE: \"hide\" + EVENT_KEY,\n    HIDDEN: \"hidden\" + EVENT_KEY,\n    SHOW: \"show\" + EVENT_KEY,\n    SHOWN: \"shown\" + EVENT_KEY,\n    CLICK_DATA_API: \"click\" + EVENT_KEY + DATA_API_KEY\n  };\n  var ClassName = {\n    DROPDOWN_MENU: 'dropdown-menu',\n    ACTIVE: 'active',\n    DISABLED: 'disabled',\n    FADE: 'fade',\n    SHOW: 'show'\n  };\n  var Selector = {\n    DROPDOWN: '.dropdown',\n    NAV_LIST_GROUP: '.nav, .list-group',\n    ACTIVE: '.active',\n    ACTIVE_UL: '> li > .active',\n    DATA_TOGGLE: '[data-toggle=\"tab\"], [data-toggle=\"pill\"], [data-toggle=\"list\"]',\n    DROPDOWN_TOGGLE: '.dropdown-toggle',\n    DROPDOWN_ACTIVE_CHILD: '> .dropdown-menu .active'\n    /**\n     * ------------------------------------------------------------------------\n     * Class Definition\n     * ------------------------------------------------------------------------\n     */\n\n  };\n\n  var Tab =\n  /*#__PURE__*/\n  function () {\n    function Tab(element) {\n      this._element = element;\n    } // getters\n\n\n    var _proto = Tab.prototype;\n\n    // public\n    _proto.show = function show() {\n      var _this = this;\n\n      if (this._element.parentNode && this._element.parentNode.nodeType === Node.ELEMENT_NODE && $(this._element).hasClass(ClassName.ACTIVE) || $(this._element).hasClass(ClassName.DISABLED)) {\n        return;\n      }\n\n      var target;\n      var previous;\n      var listElement = $(this._element).closest(Selector.NAV_LIST_GROUP)[0];\n      var selector = Util.getSelectorFromElement(this._element);\n\n      if (listElement) {\n        var itemSelector = listElement.nodeName === 'UL' ? Selector.ACTIVE_UL : Selector.ACTIVE;\n        previous = $.makeArray($(listElement).find(itemSelector));\n        previous = previous[previous.length - 1];\n      }\n\n      var hideEvent = $.Event(Event.HIDE, {\n        relatedTarget: this._element\n      });\n      var showEvent = $.Event(Event.SHOW, {\n        relatedTarget: previous\n      });\n\n      if (previous) {\n        $(previous).trigger(hideEvent);\n      }\n\n      $(this._element).trigger(showEvent);\n\n      if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      if (selector) {\n        target = $(selector)[0];\n      }\n\n      this._activate(this._element, listElement);\n\n      var complete = function complete() {\n        var hiddenEvent = $.Event(Event.HIDDEN, {\n          relatedTarget: _this._element\n        });\n        var shownEvent = $.Event(Event.SHOWN, {\n          relatedTarget: previous\n        });\n        $(previous).trigger(hiddenEvent);\n        $(_this._element).trigger(shownEvent);\n      };\n\n      if (target) {\n        this._activate(target, target.parentNode, complete);\n      } else {\n        complete();\n      }\n    };\n\n    _proto.dispose = function dispose() {\n      $.removeData(this._element, DATA_KEY);\n      this._element = null;\n    }; // private\n\n\n    _proto._activate = function _activate(element, container, callback) {\n      var _this2 = this;\n\n      var activeElements;\n\n      if (container.nodeName === 'UL') {\n        activeElements = $(container).find(Selector.ACTIVE_UL);\n      } else {\n        activeElements = $(container).children(Selector.ACTIVE);\n      }\n\n      var active = activeElements[0];\n      var isTransitioning = callback && Util.supportsTransitionEnd() && active && $(active).hasClass(ClassName.FADE);\n\n      var complete = function complete() {\n        return _this2._transitionComplete(element, active, isTransitioning, callback);\n      };\n\n      if (active && isTransitioning) {\n        $(active).one(Util.TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION);\n      } else {\n        complete();\n      }\n\n      if (active) {\n        $(active).removeClass(ClassName.SHOW);\n      }\n    };\n\n    _proto._transitionComplete = function _transitionComplete(element, active, isTransitioning, callback) {\n      if (active) {\n        $(active).removeClass(ClassName.ACTIVE);\n        var dropdownChild = $(active.parentNode).find(Selector.DROPDOWN_ACTIVE_CHILD)[0];\n\n        if (dropdownChild) {\n          $(dropdownChild).removeClass(ClassName.ACTIVE);\n        }\n\n        if (active.getAttribute('role') === 'tab') {\n          active.setAttribute('aria-selected', false);\n        }\n      }\n\n      $(element).addClass(ClassName.ACTIVE);\n\n      if (element.getAttribute('role') === 'tab') {\n        element.setAttribute('aria-selected', true);\n      }\n\n      if (isTransitioning) {\n        Util.reflow(element);\n        $(element).addClass(ClassName.SHOW);\n      } else {\n        $(element).removeClass(ClassName.FADE);\n      }\n\n      if (element.parentNode && $(element.parentNode).hasClass(ClassName.DROPDOWN_MENU)) {\n        var dropdownElement = $(element).closest(Selector.DROPDOWN)[0];\n\n        if (dropdownElement) {\n          $(dropdownElement).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE);\n        }\n\n        element.setAttribute('aria-expanded', true);\n      }\n\n      if (callback) {\n        callback();\n      }\n    }; // static\n\n\n    Tab._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var $this = $(this);\n        var data = $this.data(DATA_KEY);\n\n        if (!data) {\n          data = new Tab(this);\n          $this.data(DATA_KEY, data);\n        }\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new Error(\"No method named \\\"\" + config + \"\\\"\");\n          }\n\n          data[config]();\n        }\n      });\n    };\n\n    createClass(Tab, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION;\n      }\n    }]);\n    return Tab;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {\n    event.preventDefault();\n\n    Tab._jQueryInterface.call($(this), 'show');\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n  $.fn[NAME] = Tab._jQueryInterface;\n  $.fn[NAME].Constructor = Tab;\n\n  $.fn[NAME].noConflict = function () {\n    $.fn[NAME] = JQUERY_NO_CONFLICT;\n    return Tab._jQueryInterface;\n  };\n\n  return Tab;\n}($);\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.0.0-alpha.6): index.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n(function () {\n  if (typeof $ === 'undefined') {\n    throw new Error('Bootstrap\\'s JavaScript requires jQuery. jQuery must be included before Bootstrap\\'s JavaScript.');\n  }\n\n  var version = $.fn.jquery.split(' ')[0].split('.');\n  var minMajor = 1;\n  var ltMajor = 2;\n  var minMinor = 9;\n  var minPatch = 1;\n  var maxMajor = 4;\n\n  if (version[0] < ltMajor && version[1] < minMinor || version[0] === minMajor && version[1] === minMinor && version[2] < minPatch || version[0] >= maxMajor) {\n    throw new Error('Bootstrap\\'s JavaScript requires at least jQuery v1.9.1 but less than v4.0.0');\n  }\n})($);\n\nexports.Util = Util;\nexports.Alert = Alert;\nexports.Button = Button;\nexports.Carousel = Carousel;\nexports.Collapse = Collapse;\nexports.Dropdown = Dropdown;\nexports.Modal = Modal;\nexports.Popover = Popover;\nexports.Scrollspy = ScrollSpy;\nexports.Tab = Tab;\nexports.Tooltip = Tooltip;\n\nreturn exports;\n\n}({},$,Popper));\n//# sourceMappingURL=bootstrap.js.map\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/font-awesome/css/font-awesome.css",
    "content": "/*!\n *  Font Awesome 4.7.0 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.7.0');\n  src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'), url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg');\n  font-weight: normal;\n  font-style: normal;\n}\n.fa {\n  display: inline-block;\n  font: normal normal normal 14px/1 FontAwesome;\n  font-size: inherit;\n  text-rendering: auto;\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.33333333em;\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.28571429em;\n  text-align: center;\n}\n.fa-ul {\n  padding-left: 0;\n  margin-left: 2.14285714em;\n  list-style-type: none;\n}\n.fa-ul > li {\n  position: relative;\n}\n.fa-li {\n  position: absolute;\n  left: -2.14285714em;\n  width: 2.14285714em;\n  top: 0.14285714em;\n  text-align: center;\n}\n.fa-li.fa-lg {\n  left: -1.85714286em;\n}\n.fa-border {\n  padding: .2em .25em .15em;\n  border: solid 0.08em #eeeeee;\n  border-radius: .1em;\n}\n.fa-pull-left {\n  float: left;\n}\n.fa-pull-right {\n  float: right;\n}\n.fa.fa-pull-left {\n  margin-right: .3em;\n}\n.fa.fa-pull-right {\n  margin-left: .3em;\n}\n/* Deprecated as of 4.4.0 */\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: fa-spin 2s infinite linear;\n  animation: fa-spin 2s infinite linear;\n}\n.fa-pulse {\n  -webkit-animation: fa-spin 1s infinite steps(8);\n  animation: fa-spin 1s infinite steps(8);\n}\n@-webkit-keyframes fa-spin {\n  0% {\n    -webkit-transform: rotate(0deg);\n    transform: rotate(0deg);\n  }\n  100% {\n    -webkit-transform: rotate(359deg);\n    transform: rotate(359deg);\n  }\n}\n@keyframes fa-spin {\n  0% {\n    -webkit-transform: rotate(0deg);\n    transform: rotate(0deg);\n  }\n  100% {\n    -webkit-transform: rotate(359deg);\n    transform: rotate(359deg);\n  }\n}\n.fa-rotate-90 {\n  -ms-filter: \"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)\";\n  -webkit-transform: rotate(90deg);\n  -ms-transform: rotate(90deg);\n  transform: rotate(90deg);\n}\n.fa-rotate-180 {\n  -ms-filter: \"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)\";\n  -webkit-transform: rotate(180deg);\n  -ms-transform: rotate(180deg);\n  transform: rotate(180deg);\n}\n.fa-rotate-270 {\n  -ms-filter: \"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)\";\n  -webkit-transform: rotate(270deg);\n  -ms-transform: rotate(270deg);\n  transform: rotate(270deg);\n}\n.fa-flip-horizontal {\n  -ms-filter: \"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)\";\n  -webkit-transform: scale(-1, 1);\n  -ms-transform: scale(-1, 1);\n  transform: scale(-1, 1);\n}\n.fa-flip-vertical {\n  -ms-filter: \"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)\";\n  -webkit-transform: scale(1, -1);\n  -ms-transform: scale(1, -1);\n  transform: scale(1, -1);\n}\n:root .fa-rotate-90,\n:root .fa-rotate-180,\n:root .fa-rotate-270,\n:root .fa-flip-horizontal,\n:root .fa-flip-vertical {\n  filter: none;\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-remove:before,\n.fa-close:before,\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\";\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-photo:before,\n.fa-image:before,\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-bar-chart-o:before,\n.fa-bar-chart:before {\n  content: \"\\f080\";\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-f:before,\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-feed:before,\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-navicon:before,\n.fa-reorder:before,\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: \"\\f0d6\";\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-desc:before {\n  content: \"\\f0dd\";\n}\n.fa-sort-up:before,\n.fa-sort-asc: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-mail-reply-all:before,\n.fa-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: \"\\f145\";\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.fa-gratipay: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-space-shuttle:before {\n  content: \"\\f197\";\n}\n.fa-slack:before {\n  content: \"\\f198\";\n}\n.fa-envelope-square:before {\n  content: \"\\f199\";\n}\n.fa-wordpress:before {\n  content: \"\\f19a\";\n}\n.fa-openid:before {\n  content: \"\\f19b\";\n}\n.fa-institution:before,\n.fa-bank:before,\n.fa-university:before {\n  content: \"\\f19c\";\n}\n.fa-mortar-board:before,\n.fa-graduation-cap:before {\n  content: \"\\f19d\";\n}\n.fa-yahoo:before {\n  content: \"\\f19e\";\n}\n.fa-google:before {\n  content: \"\\f1a0\";\n}\n.fa-reddit:before {\n  content: \"\\f1a1\";\n}\n.fa-reddit-square:before {\n  content: \"\\f1a2\";\n}\n.fa-stumbleupon-circle:before {\n  content: \"\\f1a3\";\n}\n.fa-stumbleupon:before {\n  content: \"\\f1a4\";\n}\n.fa-delicious:before {\n  content: \"\\f1a5\";\n}\n.fa-digg:before {\n  content: \"\\f1a6\";\n}\n.fa-pied-piper-pp:before {\n  content: \"\\f1a7\";\n}\n.fa-pied-piper-alt:before {\n  content: \"\\f1a8\";\n}\n.fa-drupal:before {\n  content: \"\\f1a9\";\n}\n.fa-joomla:before {\n  content: \"\\f1aa\";\n}\n.fa-language:before {\n  content: \"\\f1ab\";\n}\n.fa-fax:before {\n  content: \"\\f1ac\";\n}\n.fa-building:before {\n  content: \"\\f1ad\";\n}\n.fa-child:before {\n  content: \"\\f1ae\";\n}\n.fa-paw:before {\n  content: \"\\f1b0\";\n}\n.fa-spoon:before {\n  content: \"\\f1b1\";\n}\n.fa-cube:before {\n  content: \"\\f1b2\";\n}\n.fa-cubes:before {\n  content: \"\\f1b3\";\n}\n.fa-behance:before {\n  content: \"\\f1b4\";\n}\n.fa-behance-square:before {\n  content: \"\\f1b5\";\n}\n.fa-steam:before {\n  content: \"\\f1b6\";\n}\n.fa-steam-square:before {\n  content: \"\\f1b7\";\n}\n.fa-recycle:before {\n  content: \"\\f1b8\";\n}\n.fa-automobile:before,\n.fa-car:before {\n  content: \"\\f1b9\";\n}\n.fa-cab:before,\n.fa-taxi:before {\n  content: \"\\f1ba\";\n}\n.fa-tree:before {\n  content: \"\\f1bb\";\n}\n.fa-spotify:before {\n  content: \"\\f1bc\";\n}\n.fa-deviantart:before {\n  content: \"\\f1bd\";\n}\n.fa-soundcloud:before {\n  content: \"\\f1be\";\n}\n.fa-database:before {\n  content: \"\\f1c0\";\n}\n.fa-file-pdf-o:before {\n  content: \"\\f1c1\";\n}\n.fa-file-word-o:before {\n  content: \"\\f1c2\";\n}\n.fa-file-excel-o:before {\n  content: \"\\f1c3\";\n}\n.fa-file-powerpoint-o:before {\n  content: \"\\f1c4\";\n}\n.fa-file-photo-o:before,\n.fa-file-picture-o:before,\n.fa-file-image-o:before {\n  content: \"\\f1c5\";\n}\n.fa-file-zip-o:before,\n.fa-file-archive-o:before {\n  content: \"\\f1c6\";\n}\n.fa-file-sound-o:before,\n.fa-file-audio-o:before {\n  content: \"\\f1c7\";\n}\n.fa-file-movie-o:before,\n.fa-file-video-o:before {\n  content: \"\\f1c8\";\n}\n.fa-file-code-o:before {\n  content: \"\\f1c9\";\n}\n.fa-vine:before {\n  content: \"\\f1ca\";\n}\n.fa-codepen:before {\n  content: \"\\f1cb\";\n}\n.fa-jsfiddle:before {\n  content: \"\\f1cc\";\n}\n.fa-life-bouy:before,\n.fa-life-buoy:before,\n.fa-life-saver:before,\n.fa-support:before,\n.fa-life-ring:before {\n  content: \"\\f1cd\";\n}\n.fa-circle-o-notch:before {\n  content: \"\\f1ce\";\n}\n.fa-ra:before,\n.fa-resistance:before,\n.fa-rebel:before {\n  content: \"\\f1d0\";\n}\n.fa-ge:before,\n.fa-empire:before {\n  content: \"\\f1d1\";\n}\n.fa-git-square:before {\n  content: \"\\f1d2\";\n}\n.fa-git:before {\n  content: \"\\f1d3\";\n}\n.fa-y-combinator-square:before,\n.fa-yc-square:before,\n.fa-hacker-news:before {\n  content: \"\\f1d4\";\n}\n.fa-tencent-weibo:before {\n  content: \"\\f1d5\";\n}\n.fa-qq:before {\n  content: \"\\f1d6\";\n}\n.fa-wechat:before,\n.fa-weixin:before {\n  content: \"\\f1d7\";\n}\n.fa-send:before,\n.fa-paper-plane:before {\n  content: \"\\f1d8\";\n}\n.fa-send-o:before,\n.fa-paper-plane-o:before {\n  content: \"\\f1d9\";\n}\n.fa-history:before {\n  content: \"\\f1da\";\n}\n.fa-circle-thin:before {\n  content: \"\\f1db\";\n}\n.fa-header:before {\n  content: \"\\f1dc\";\n}\n.fa-paragraph:before {\n  content: \"\\f1dd\";\n}\n.fa-sliders:before {\n  content: \"\\f1de\";\n}\n.fa-share-alt:before {\n  content: \"\\f1e0\";\n}\n.fa-share-alt-square:before {\n  content: \"\\f1e1\";\n}\n.fa-bomb:before {\n  content: \"\\f1e2\";\n}\n.fa-soccer-ball-o:before,\n.fa-futbol-o:before {\n  content: \"\\f1e3\";\n}\n.fa-tty:before {\n  content: \"\\f1e4\";\n}\n.fa-binoculars:before {\n  content: \"\\f1e5\";\n}\n.fa-plug:before {\n  content: \"\\f1e6\";\n}\n.fa-slideshare:before {\n  content: \"\\f1e7\";\n}\n.fa-twitch:before {\n  content: \"\\f1e8\";\n}\n.fa-yelp:before {\n  content: \"\\f1e9\";\n}\n.fa-newspaper-o:before {\n  content: \"\\f1ea\";\n}\n.fa-wifi:before {\n  content: \"\\f1eb\";\n}\n.fa-calculator:before {\n  content: \"\\f1ec\";\n}\n.fa-paypal:before {\n  content: \"\\f1ed\";\n}\n.fa-google-wallet:before {\n  content: \"\\f1ee\";\n}\n.fa-cc-visa:before {\n  content: \"\\f1f0\";\n}\n.fa-cc-mastercard:before {\n  content: \"\\f1f1\";\n}\n.fa-cc-discover:before {\n  content: \"\\f1f2\";\n}\n.fa-cc-amex:before {\n  content: \"\\f1f3\";\n}\n.fa-cc-paypal:before {\n  content: \"\\f1f4\";\n}\n.fa-cc-stripe:before {\n  content: \"\\f1f5\";\n}\n.fa-bell-slash:before {\n  content: \"\\f1f6\";\n}\n.fa-bell-slash-o:before {\n  content: \"\\f1f7\";\n}\n.fa-trash:before {\n  content: \"\\f1f8\";\n}\n.fa-copyright:before {\n  content: \"\\f1f9\";\n}\n.fa-at:before {\n  content: \"\\f1fa\";\n}\n.fa-eyedropper:before {\n  content: \"\\f1fb\";\n}\n.fa-paint-brush:before {\n  content: \"\\f1fc\";\n}\n.fa-birthday-cake:before {\n  content: \"\\f1fd\";\n}\n.fa-area-chart:before {\n  content: \"\\f1fe\";\n}\n.fa-pie-chart:before {\n  content: \"\\f200\";\n}\n.fa-line-chart:before {\n  content: \"\\f201\";\n}\n.fa-lastfm:before {\n  content: \"\\f202\";\n}\n.fa-lastfm-square:before {\n  content: \"\\f203\";\n}\n.fa-toggle-off:before {\n  content: \"\\f204\";\n}\n.fa-toggle-on:before {\n  content: \"\\f205\";\n}\n.fa-bicycle:before {\n  content: \"\\f206\";\n}\n.fa-bus:before {\n  content: \"\\f207\";\n}\n.fa-ioxhost:before {\n  content: \"\\f208\";\n}\n.fa-angellist:before {\n  content: \"\\f209\";\n}\n.fa-cc:before {\n  content: \"\\f20a\";\n}\n.fa-shekel:before,\n.fa-sheqel:before,\n.fa-ils:before {\n  content: \"\\f20b\";\n}\n.fa-meanpath:before {\n  content: \"\\f20c\";\n}\n.fa-buysellads:before {\n  content: \"\\f20d\";\n}\n.fa-connectdevelop:before {\n  content: \"\\f20e\";\n}\n.fa-dashcube:before {\n  content: \"\\f210\";\n}\n.fa-forumbee:before {\n  content: \"\\f211\";\n}\n.fa-leanpub:before {\n  content: \"\\f212\";\n}\n.fa-sellsy:before {\n  content: \"\\f213\";\n}\n.fa-shirtsinbulk:before {\n  content: \"\\f214\";\n}\n.fa-simplybuilt:before {\n  content: \"\\f215\";\n}\n.fa-skyatlas:before {\n  content: \"\\f216\";\n}\n.fa-cart-plus:before {\n  content: \"\\f217\";\n}\n.fa-cart-arrow-down:before {\n  content: \"\\f218\";\n}\n.fa-diamond:before {\n  content: \"\\f219\";\n}\n.fa-ship:before {\n  content: \"\\f21a\";\n}\n.fa-user-secret:before {\n  content: \"\\f21b\";\n}\n.fa-motorcycle:before {\n  content: \"\\f21c\";\n}\n.fa-street-view:before {\n  content: \"\\f21d\";\n}\n.fa-heartbeat:before {\n  content: \"\\f21e\";\n}\n.fa-venus:before {\n  content: \"\\f221\";\n}\n.fa-mars:before {\n  content: \"\\f222\";\n}\n.fa-mercury:before {\n  content: \"\\f223\";\n}\n.fa-intersex:before,\n.fa-transgender:before {\n  content: \"\\f224\";\n}\n.fa-transgender-alt:before {\n  content: \"\\f225\";\n}\n.fa-venus-double:before {\n  content: \"\\f226\";\n}\n.fa-mars-double:before {\n  content: \"\\f227\";\n}\n.fa-venus-mars:before {\n  content: \"\\f228\";\n}\n.fa-mars-stroke:before {\n  content: \"\\f229\";\n}\n.fa-mars-stroke-v:before {\n  content: \"\\f22a\";\n}\n.fa-mars-stroke-h:before {\n  content: \"\\f22b\";\n}\n.fa-neuter:before {\n  content: \"\\f22c\";\n}\n.fa-genderless:before {\n  content: \"\\f22d\";\n}\n.fa-facebook-official:before {\n  content: \"\\f230\";\n}\n.fa-pinterest-p:before {\n  content: \"\\f231\";\n}\n.fa-whatsapp:before {\n  content: \"\\f232\";\n}\n.fa-server:before {\n  content: \"\\f233\";\n}\n.fa-user-plus:before {\n  content: \"\\f234\";\n}\n.fa-user-times:before {\n  content: \"\\f235\";\n}\n.fa-hotel:before,\n.fa-bed:before {\n  content: \"\\f236\";\n}\n.fa-viacoin:before {\n  content: \"\\f237\";\n}\n.fa-train:before {\n  content: \"\\f238\";\n}\n.fa-subway:before {\n  content: \"\\f239\";\n}\n.fa-medium:before {\n  content: \"\\f23a\";\n}\n.fa-yc:before,\n.fa-y-combinator:before {\n  content: \"\\f23b\";\n}\n.fa-optin-monster:before {\n  content: \"\\f23c\";\n}\n.fa-opencart:before {\n  content: \"\\f23d\";\n}\n.fa-expeditedssl:before {\n  content: \"\\f23e\";\n}\n.fa-battery-4:before,\n.fa-battery:before,\n.fa-battery-full:before {\n  content: \"\\f240\";\n}\n.fa-battery-3:before,\n.fa-battery-three-quarters:before {\n  content: \"\\f241\";\n}\n.fa-battery-2:before,\n.fa-battery-half:before {\n  content: \"\\f242\";\n}\n.fa-battery-1:before,\n.fa-battery-quarter:before {\n  content: \"\\f243\";\n}\n.fa-battery-0:before,\n.fa-battery-empty:before {\n  content: \"\\f244\";\n}\n.fa-mouse-pointer:before {\n  content: \"\\f245\";\n}\n.fa-i-cursor:before {\n  content: \"\\f246\";\n}\n.fa-object-group:before {\n  content: \"\\f247\";\n}\n.fa-object-ungroup:before {\n  content: \"\\f248\";\n}\n.fa-sticky-note:before {\n  content: \"\\f249\";\n}\n.fa-sticky-note-o:before {\n  content: \"\\f24a\";\n}\n.fa-cc-jcb:before {\n  content: \"\\f24b\";\n}\n.fa-cc-diners-club:before {\n  content: \"\\f24c\";\n}\n.fa-clone:before {\n  content: \"\\f24d\";\n}\n.fa-balance-scale:before {\n  content: \"\\f24e\";\n}\n.fa-hourglass-o:before {\n  content: \"\\f250\";\n}\n.fa-hourglass-1:before,\n.fa-hourglass-start:before {\n  content: \"\\f251\";\n}\n.fa-hourglass-2:before,\n.fa-hourglass-half:before {\n  content: \"\\f252\";\n}\n.fa-hourglass-3:before,\n.fa-hourglass-end:before {\n  content: \"\\f253\";\n}\n.fa-hourglass:before {\n  content: \"\\f254\";\n}\n.fa-hand-grab-o:before,\n.fa-hand-rock-o:before {\n  content: \"\\f255\";\n}\n.fa-hand-stop-o:before,\n.fa-hand-paper-o:before {\n  content: \"\\f256\";\n}\n.fa-hand-scissors-o:before {\n  content: \"\\f257\";\n}\n.fa-hand-lizard-o:before {\n  content: \"\\f258\";\n}\n.fa-hand-spock-o:before {\n  content: \"\\f259\";\n}\n.fa-hand-pointer-o:before {\n  content: \"\\f25a\";\n}\n.fa-hand-peace-o:before {\n  content: \"\\f25b\";\n}\n.fa-trademark:before {\n  content: \"\\f25c\";\n}\n.fa-registered:before {\n  content: \"\\f25d\";\n}\n.fa-creative-commons:before {\n  content: \"\\f25e\";\n}\n.fa-gg:before {\n  content: \"\\f260\";\n}\n.fa-gg-circle:before {\n  content: \"\\f261\";\n}\n.fa-tripadvisor:before {\n  content: \"\\f262\";\n}\n.fa-odnoklassniki:before {\n  content: \"\\f263\";\n}\n.fa-odnoklassniki-square:before {\n  content: \"\\f264\";\n}\n.fa-get-pocket:before {\n  content: \"\\f265\";\n}\n.fa-wikipedia-w:before {\n  content: \"\\f266\";\n}\n.fa-safari:before {\n  content: \"\\f267\";\n}\n.fa-chrome:before {\n  content: \"\\f268\";\n}\n.fa-firefox:before {\n  content: \"\\f269\";\n}\n.fa-opera:before {\n  content: \"\\f26a\";\n}\n.fa-internet-explorer:before {\n  content: \"\\f26b\";\n}\n.fa-tv:before,\n.fa-television:before {\n  content: \"\\f26c\";\n}\n.fa-contao:before {\n  content: \"\\f26d\";\n}\n.fa-500px:before {\n  content: \"\\f26e\";\n}\n.fa-amazon:before {\n  content: \"\\f270\";\n}\n.fa-calendar-plus-o:before {\n  content: \"\\f271\";\n}\n.fa-calendar-minus-o:before {\n  content: \"\\f272\";\n}\n.fa-calendar-times-o:before {\n  content: \"\\f273\";\n}\n.fa-calendar-check-o:before {\n  content: \"\\f274\";\n}\n.fa-industry:before {\n  content: \"\\f275\";\n}\n.fa-map-pin:before {\n  content: \"\\f276\";\n}\n.fa-map-signs:before {\n  content: \"\\f277\";\n}\n.fa-map-o:before {\n  content: \"\\f278\";\n}\n.fa-map:before {\n  content: \"\\f279\";\n}\n.fa-commenting:before {\n  content: \"\\f27a\";\n}\n.fa-commenting-o:before {\n  content: \"\\f27b\";\n}\n.fa-houzz:before {\n  content: \"\\f27c\";\n}\n.fa-vimeo:before {\n  content: \"\\f27d\";\n}\n.fa-black-tie:before {\n  content: \"\\f27e\";\n}\n.fa-fonticons:before {\n  content: \"\\f280\";\n}\n.fa-reddit-alien:before {\n  content: \"\\f281\";\n}\n.fa-edge:before {\n  content: \"\\f282\";\n}\n.fa-credit-card-alt:before {\n  content: \"\\f283\";\n}\n.fa-codiepie:before {\n  content: \"\\f284\";\n}\n.fa-modx:before {\n  content: \"\\f285\";\n}\n.fa-fort-awesome:before {\n  content: \"\\f286\";\n}\n.fa-usb:before {\n  content: \"\\f287\";\n}\n.fa-product-hunt:before {\n  content: \"\\f288\";\n}\n.fa-mixcloud:before {\n  content: \"\\f289\";\n}\n.fa-scribd:before {\n  content: \"\\f28a\";\n}\n.fa-pause-circle:before {\n  content: \"\\f28b\";\n}\n.fa-pause-circle-o:before {\n  content: \"\\f28c\";\n}\n.fa-stop-circle:before {\n  content: \"\\f28d\";\n}\n.fa-stop-circle-o:before {\n  content: \"\\f28e\";\n}\n.fa-shopping-bag:before {\n  content: \"\\f290\";\n}\n.fa-shopping-basket:before {\n  content: \"\\f291\";\n}\n.fa-hashtag:before {\n  content: \"\\f292\";\n}\n.fa-bluetooth:before {\n  content: \"\\f293\";\n}\n.fa-bluetooth-b:before {\n  content: \"\\f294\";\n}\n.fa-percent:before {\n  content: \"\\f295\";\n}\n.fa-gitlab:before {\n  content: \"\\f296\";\n}\n.fa-wpbeginner:before {\n  content: \"\\f297\";\n}\n.fa-wpforms:before {\n  content: \"\\f298\";\n}\n.fa-envira:before {\n  content: \"\\f299\";\n}\n.fa-universal-access:before {\n  content: \"\\f29a\";\n}\n.fa-wheelchair-alt:before {\n  content: \"\\f29b\";\n}\n.fa-question-circle-o:before {\n  content: \"\\f29c\";\n}\n.fa-blind:before {\n  content: \"\\f29d\";\n}\n.fa-audio-description:before {\n  content: \"\\f29e\";\n}\n.fa-volume-control-phone:before {\n  content: \"\\f2a0\";\n}\n.fa-braille:before {\n  content: \"\\f2a1\";\n}\n.fa-assistive-listening-systems:before {\n  content: \"\\f2a2\";\n}\n.fa-asl-interpreting:before,\n.fa-american-sign-language-interpreting:before {\n  content: \"\\f2a3\";\n}\n.fa-deafness:before,\n.fa-hard-of-hearing:before,\n.fa-deaf:before {\n  content: \"\\f2a4\";\n}\n.fa-glide:before {\n  content: \"\\f2a5\";\n}\n.fa-glide-g:before {\n  content: \"\\f2a6\";\n}\n.fa-signing:before,\n.fa-sign-language:before {\n  content: \"\\f2a7\";\n}\n.fa-low-vision:before {\n  content: \"\\f2a8\";\n}\n.fa-viadeo:before {\n  content: \"\\f2a9\";\n}\n.fa-viadeo-square:before {\n  content: \"\\f2aa\";\n}\n.fa-snapchat:before {\n  content: \"\\f2ab\";\n}\n.fa-snapchat-ghost:before {\n  content: \"\\f2ac\";\n}\n.fa-snapchat-square:before {\n  content: \"\\f2ad\";\n}\n.fa-pied-piper:before {\n  content: \"\\f2ae\";\n}\n.fa-first-order:before {\n  content: \"\\f2b0\";\n}\n.fa-yoast:before {\n  content: \"\\f2b1\";\n}\n.fa-themeisle:before {\n  content: \"\\f2b2\";\n}\n.fa-google-plus-circle:before,\n.fa-google-plus-official:before {\n  content: \"\\f2b3\";\n}\n.fa-fa:before,\n.fa-font-awesome:before {\n  content: \"\\f2b4\";\n}\n.fa-handshake-o:before {\n  content: \"\\f2b5\";\n}\n.fa-envelope-open:before {\n  content: \"\\f2b6\";\n}\n.fa-envelope-open-o:before {\n  content: \"\\f2b7\";\n}\n.fa-linode:before {\n  content: \"\\f2b8\";\n}\n.fa-address-book:before {\n  content: \"\\f2b9\";\n}\n.fa-address-book-o:before {\n  content: \"\\f2ba\";\n}\n.fa-vcard:before,\n.fa-address-card:before {\n  content: \"\\f2bb\";\n}\n.fa-vcard-o:before,\n.fa-address-card-o:before {\n  content: \"\\f2bc\";\n}\n.fa-user-circle:before {\n  content: \"\\f2bd\";\n}\n.fa-user-circle-o:before {\n  content: \"\\f2be\";\n}\n.fa-user-o:before {\n  content: \"\\f2c0\";\n}\n.fa-id-badge:before {\n  content: \"\\f2c1\";\n}\n.fa-drivers-license:before,\n.fa-id-card:before {\n  content: \"\\f2c2\";\n}\n.fa-drivers-license-o:before,\n.fa-id-card-o:before {\n  content: \"\\f2c3\";\n}\n.fa-quora:before {\n  content: \"\\f2c4\";\n}\n.fa-free-code-camp:before {\n  content: \"\\f2c5\";\n}\n.fa-telegram:before {\n  content: \"\\f2c6\";\n}\n.fa-thermometer-4:before,\n.fa-thermometer:before,\n.fa-thermometer-full:before {\n  content: \"\\f2c7\";\n}\n.fa-thermometer-3:before,\n.fa-thermometer-three-quarters:before {\n  content: \"\\f2c8\";\n}\n.fa-thermometer-2:before,\n.fa-thermometer-half:before {\n  content: \"\\f2c9\";\n}\n.fa-thermometer-1:before,\n.fa-thermometer-quarter:before {\n  content: \"\\f2ca\";\n}\n.fa-thermometer-0:before,\n.fa-thermometer-empty:before {\n  content: \"\\f2cb\";\n}\n.fa-shower:before {\n  content: \"\\f2cc\";\n}\n.fa-bathtub:before,\n.fa-s15:before,\n.fa-bath:before {\n  content: \"\\f2cd\";\n}\n.fa-podcast:before {\n  content: \"\\f2ce\";\n}\n.fa-window-maximize:before {\n  content: \"\\f2d0\";\n}\n.fa-window-minimize:before {\n  content: \"\\f2d1\";\n}\n.fa-window-restore:before {\n  content: \"\\f2d2\";\n}\n.fa-times-rectangle:before,\n.fa-window-close:before {\n  content: \"\\f2d3\";\n}\n.fa-times-rectangle-o:before,\n.fa-window-close-o:before {\n  content: \"\\f2d4\";\n}\n.fa-bandcamp:before {\n  content: \"\\f2d5\";\n}\n.fa-grav:before {\n  content: \"\\f2d6\";\n}\n.fa-etsy:before {\n  content: \"\\f2d7\";\n}\n.fa-imdb:before {\n  content: \"\\f2d8\";\n}\n.fa-ravelry:before {\n  content: \"\\f2d9\";\n}\n.fa-eercast:before {\n  content: \"\\f2da\";\n}\n.fa-microchip:before {\n  content: \"\\f2db\";\n}\n.fa-snowflake-o:before {\n  content: \"\\f2dc\";\n}\n.fa-superpowers:before {\n  content: \"\\f2dd\";\n}\n.fa-wpexplorer:before {\n  content: \"\\f2de\";\n}\n.fa-meetup:before {\n  content: \"\\f2e0\";\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.sr-only-focusable:active,\n.sr-only-focusable:focus {\n  position: static;\n  width: auto;\n  height: auto;\n  margin: 0;\n  overflow: visible;\n  clip: auto;\n}\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/jquery/core.js",
    "content": "/* global Symbol */\n// Defining this global in .eslintrc.json would create a danger of using the global\n// unguarded in another place, it seems safer to define global only for this module\n\ndefine( [\n\t\"./var/arr\",\n\t\"./var/document\",\n\t\"./var/getProto\",\n\t\"./var/slice\",\n\t\"./var/concat\",\n\t\"./var/push\",\n\t\"./var/indexOf\",\n\t\"./var/class2type\",\n\t\"./var/toString\",\n\t\"./var/hasOwn\",\n\t\"./var/fnToString\",\n\t\"./var/ObjectFunctionString\",\n\t\"./var/support\",\n\t\"./core/DOMEval\"\n], function( arr, document, getProto, slice, concat, push, indexOf,\n\tclass2type, toString, hasOwn, fnToString, ObjectFunctionString,\n\tsupport, DOMEval ) {\n\n\"use strict\";\n\nvar\n\tversion = \"3.2.1\",\n\n\t// Define a local copy of jQuery\n\tjQuery = function( selector, context ) {\n\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.0 only\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 = /-([a-z])/g,\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\n\t// The current version of jQuery being used\n\tjquery: version,\n\n\tconstructor: jQuery,\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\n\t\t// Return all the elements in a clean array\n\t\tif ( num == null ) {\n\t\t\treturn slice.call( this );\n\t\t}\n\n\t\t// Return just the one element from the set\n\t\treturn num < 0 ? this[ num + this.length ] : 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\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\teach: function( callback ) {\n\t\treturn jQuery.each( this, callback );\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();\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\n\t\t// Only deal with non-null/undefined values\n\t\tif ( ( options = arguments[ i ] ) != null ) {\n\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 ) ||\n\t\t\t\t\t( copyIsArray = Array.isArray( copy ) ) ) ) {\n\n\t\t\t\t\tif ( copyIsArray ) {\n\t\t\t\t\t\tcopyIsArray = false;\n\t\t\t\t\t\tclone = src && Array.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\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\tisWindow: function( obj ) {\n\t\treturn obj != null && obj === obj.window;\n\t},\n\n\tisNumeric: function( obj ) {\n\n\t\t// As of jQuery 3.0, isNumeric is limited to\n\t\t// strings and numbers (primitives or objects)\n\t\t// that can be coerced to finite numbers (gh-2662)\n\t\tvar type = jQuery.type( obj );\n\t\treturn ( type === \"number\" || type === \"string\" ) &&\n\n\t\t\t// parseFloat NaNs numeric-cast false positives (\"\")\n\t\t\t// ...but misinterprets leading-number strings, particularly hex literals (\"0x...\")\n\t\t\t// subtraction forces infinities to NaN\n\t\t\t!isNaN( obj - parseFloat( obj ) );\n\t},\n\n\tisPlainObject: function( obj ) {\n\t\tvar proto, Ctor;\n\n\t\t// Detect obvious negatives\n\t\t// Use toString instead of jQuery.type to catch host objects\n\t\tif ( !obj || toString.call( obj ) !== \"[object Object]\" ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tproto = getProto( obj );\n\n\t\t// Objects with no prototype (e.g., `Object.create( null )`) are plain\n\t\tif ( !proto ) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Objects with prototype are plain iff they were constructed by a global Object function\n\t\tCtor = hasOwn.call( proto, \"constructor\" ) && proto.constructor;\n\t\treturn typeof Ctor === \"function\" && fnToString.call( Ctor ) === ObjectFunctionString;\n\t},\n\n\tisEmptyObject: function( obj ) {\n\n\t\t/* eslint-disable no-unused-vars */\n\t\t// See https://github.com/eslint/eslint/issues/6125\n\t\tvar name;\n\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\n\t\t// Support: Android <=2.3 only (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\tDOMEval( code );\n\t},\n\n\t// Convert dashed to camelCase; used by the css and data modules\n\t// Support: IE <=9 - 11, Edge 12 - 13\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\teach: function( obj, callback ) {\n\t\tvar length, i = 0;\n\n\t\tif ( isArrayLike( obj ) ) {\n\t\t\tlength = obj.length;\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tfor ( i in obj ) {\n\t\t\t\tif ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {\n\t\t\t\t\tbreak;\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.0 only\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\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t// push.apply(_, arraylike) throws on ancient WebKit\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 length, value,\n\t\t\ti = 0,\n\t\t\tret = [];\n\n\t\t// Go through the array, translating each of the items to their new values\n\t\tif ( isArrayLike( elems ) ) {\n\t\t\tlength = elems.length;\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\nif ( typeof Symbol === \"function\" ) {\n\tjQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ];\n}\n\n// Populate the class2type map\njQuery.each( \"Boolean Number String Function Array Date RegExp Object Error Symbol\".split( \" \" ),\nfunction( i, name ) {\n\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n} );\n\nfunction isArrayLike( obj ) {\n\n\t// Support: real iOS 8.2 only (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 = !!obj && \"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\treturn type === \"array\" || length === 0 ||\n\t\ttypeof length === \"number\" && length > 0 && ( length - 1 ) in obj;\n}\n\nreturn jQuery;\n} );\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/jquery/jquery.js",
    "content": "/*!\n * jQuery JavaScript Library v3.2.1\n * https://jquery.com/\n *\n * Includes Sizzle.js\n * https://sizzlejs.com/\n *\n * Copyright JS Foundation and other contributors\n * Released under the MIT license\n * https://jquery.org/license\n *\n * Date: 2017-03-20T18:59Z\n */\n( function( global, factory ) {\n\n\t\"use strict\";\n\n\tif ( typeof module === \"object\" && typeof module.exports === \"object\" ) {\n\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// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1\n// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode\n// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common\n// enough that all such attempts are guarded in a try block.\n\t\"use strict\";\n\n\tvar arr = [];\n\n\tvar document = window.document;\n\n\tvar getProto = Object.getPrototypeOf;\n\n\tvar slice = arr.slice;\n\n\tvar concat = arr.concat;\n\n\tvar push = arr.push;\n\n\tvar indexOf = arr.indexOf;\n\n\tvar class2type = {};\n\n\tvar toString = class2type.toString;\n\n\tvar hasOwn = class2type.hasOwnProperty;\n\n\tvar fnToString = hasOwn.toString;\n\n\tvar ObjectFunctionString = fnToString.call( Object );\n\n\tvar support = {};\n\n\n\n\tfunction DOMEval( code, doc ) {\n\t\tdoc = doc || document;\n\n\t\tvar script = doc.createElement( \"script\" );\n\n\t\tscript.text = code;\n\t\tdoc.head.appendChild( script ).parentNode.removeChild( script );\n\t}\n\t/* global Symbol */\n// Defining this global in .eslintrc.json would create a danger of using the global\n// unguarded in another place, it seems safer to define global only for this module\n\n\n\n\tvar\n\t\tversion = \"3.2.1\",\n\n\t\t// Define a local copy of jQuery\n\t\tjQuery = function( selector, context ) {\n\n\t\t\t// The jQuery object is actually just the init constructor 'enhanced'\n\t\t\t// Need init if jQuery is called (just allow error to be thrown if not included)\n\t\t\treturn new jQuery.fn.init( selector, context );\n\t\t},\n\n\t\t// Support: Android <=4.0 only\n\t\t// Make sure we trim BOM and NBSP\n\t\trtrim = /^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g,\n\n\t\t// Matches dashed string for camelizing\n\t\trmsPrefix = /^-ms-/,\n\t\trdashAlpha = /-([a-z])/g,\n\n\t\t// Used by jQuery.camelCase as callback to replace()\n\t\tfcamelCase = function( all, letter ) {\n\t\t\treturn letter.toUpperCase();\n\t\t};\n\n\tjQuery.fn = jQuery.prototype = {\n\n\t\t// The current version of jQuery being used\n\t\tjquery: version,\n\n\t\tconstructor: jQuery,\n\n\t\t// The default length of a jQuery object is 0\n\t\tlength: 0,\n\n\t\ttoArray: function() {\n\t\t\treturn slice.call( this );\n\t\t},\n\n\t\t// Get the Nth element in the matched element set OR\n\t\t// Get the whole matched element set as a clean array\n\t\tget: function( num ) {\n\n\t\t\t// Return all the elements in a clean array\n\t\t\tif ( num == null ) {\n\t\t\t\treturn slice.call( this );\n\t\t\t}\n\n\t\t\t// Return just the one element from the set\n\t\t\treturn num < 0 ? this[ num + this.length ] : this[ num ];\n\t\t},\n\n\t\t// Take an array of elements and push it onto the stack\n\t\t// (returning the new matched element set)\n\t\tpushStack: function( elems ) {\n\n\t\t\t// Build a new jQuery matched element set\n\t\t\tvar ret = jQuery.merge( this.constructor(), elems );\n\n\t\t\t// Add the old object onto the stack (as a reference)\n\t\t\tret.prevObject = this;\n\n\t\t\t// Return the newly-formed element set\n\t\t\treturn ret;\n\t\t},\n\n\t\t// Execute a callback for every element in the matched set.\n\t\teach: function( callback ) {\n\t\t\treturn jQuery.each( this, callback );\n\t\t},\n\n\t\tmap: function( callback ) {\n\t\t\treturn this.pushStack( jQuery.map( this, function( elem, i ) {\n\t\t\t\treturn callback.call( elem, i, elem );\n\t\t\t} ) );\n\t\t},\n\n\t\tslice: function() {\n\t\t\treturn this.pushStack( slice.apply( this, arguments ) );\n\t\t},\n\n\t\tfirst: function() {\n\t\t\treturn this.eq( 0 );\n\t\t},\n\n\t\tlast: function() {\n\t\t\treturn this.eq( -1 );\n\t\t},\n\n\t\teq: function( i ) {\n\t\t\tvar len = this.length,\n\t\t\t\tj = +i + ( i < 0 ? len : 0 );\n\t\t\treturn this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] );\n\t\t},\n\n\t\tend: function() {\n\t\t\treturn this.prevObject || this.constructor();\n\t\t},\n\n\t\t// For internal use only.\n\t\t// Behaves like an Array's method, not like a jQuery method.\n\t\tpush: push,\n\t\tsort: arr.sort,\n\t\tsplice: arr.splice\n\t};\n\n\tjQuery.extend = jQuery.fn.extend = function() {\n\t\tvar options, name, src, copy, copyIsArray, clone,\n\t\t\ttarget = arguments[ 0 ] || {},\n\t\t\ti = 1,\n\t\t\tlength = arguments.length,\n\t\t\tdeep = false;\n\n\t\t// Handle a deep copy situation\n\t\tif ( typeof target === \"boolean\" ) {\n\t\t\tdeep = target;\n\n\t\t\t// Skip the boolean and the target\n\t\t\ttarget = arguments[ i ] || {};\n\t\t\ti++;\n\t\t}\n\n\t\t// Handle case when target is a string or something (possible in deep copy)\n\t\tif ( typeof target !== \"object\" && !jQuery.isFunction( target ) ) {\n\t\t\ttarget = {};\n\t\t}\n\n\t\t// Extend jQuery itself if only one argument is passed\n\t\tif ( i === length ) {\n\t\t\ttarget = this;\n\t\t\ti--;\n\t\t}\n\n\t\tfor ( ; i < length; i++ ) {\n\n\t\t\t// Only deal with non-null/undefined values\n\t\t\tif ( ( options = arguments[ i ] ) != null ) {\n\n\t\t\t\t// Extend the base object\n\t\t\t\tfor ( name in options ) {\n\t\t\t\t\tsrc = target[ name ];\n\t\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t\t// Prevent never-ending loop\n\t\t\t\t\tif ( target === copy ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject( copy ) ||\n\t\t\t\t\t\t( copyIsArray = Array.isArray( copy ) ) ) ) {\n\n\t\t\t\t\t\tif ( copyIsArray ) {\n\t\t\t\t\t\t\tcopyIsArray = false;\n\t\t\t\t\t\t\tclone = src && Array.isArray( src ) ? src : [];\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tclone = src && jQuery.isPlainObject( src ) ? src : {};\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n\n\t\t\t\t\t\t// Don't bring in undefined values\n\t\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Return the modified object\n\t\treturn target;\n\t};\n\n\tjQuery.extend( {\n\n\t\t// Unique for each copy of jQuery on the page\n\t\texpando: \"jQuery\" + ( version + Math.random() ).replace( /\\D/g, \"\" ),\n\n\t\t// Assume jQuery is ready without the ready module\n\t\tisReady: true,\n\n\t\terror: function( msg ) {\n\t\t\tthrow new Error( msg );\n\t\t},\n\n\t\tnoop: function() {},\n\n\t\tisFunction: function( obj ) {\n\t\t\treturn jQuery.type( obj ) === \"function\";\n\t\t},\n\n\t\tisWindow: function( obj ) {\n\t\t\treturn obj != null && obj === obj.window;\n\t\t},\n\n\t\tisNumeric: function( obj ) {\n\n\t\t\t// As of jQuery 3.0, isNumeric is limited to\n\t\t\t// strings and numbers (primitives or objects)\n\t\t\t// that can be coerced to finite numbers (gh-2662)\n\t\t\tvar type = jQuery.type( obj );\n\t\t\treturn ( type === \"number\" || type === \"string\" ) &&\n\n\t\t\t\t// parseFloat NaNs numeric-cast false positives (\"\")\n\t\t\t\t// ...but misinterprets leading-number strings, particularly hex literals (\"0x...\")\n\t\t\t\t// subtraction forces infinities to NaN\n\t\t\t\t!isNaN( obj - parseFloat( obj ) );\n\t\t},\n\n\t\tisPlainObject: function( obj ) {\n\t\t\tvar proto, Ctor;\n\n\t\t\t// Detect obvious negatives\n\t\t\t// Use toString instead of jQuery.type to catch host objects\n\t\t\tif ( !obj || toString.call( obj ) !== \"[object Object]\" ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tproto = getProto( obj );\n\n\t\t\t// Objects with no prototype (e.g., `Object.create( null )`) are plain\n\t\t\tif ( !proto ) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t// Objects with prototype are plain iff they were constructed by a global Object function\n\t\t\tCtor = hasOwn.call( proto, \"constructor\" ) && proto.constructor;\n\t\t\treturn typeof Ctor === \"function\" && fnToString.call( Ctor ) === ObjectFunctionString;\n\t\t},\n\n\t\tisEmptyObject: function( obj ) {\n\n\t\t\t/* eslint-disable no-unused-vars */\n\t\t\t// See https://github.com/eslint/eslint/issues/6125\n\t\t\tvar name;\n\n\t\t\tfor ( name in obj ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\n\t\ttype: function( obj ) {\n\t\t\tif ( obj == null ) {\n\t\t\t\treturn obj + \"\";\n\t\t\t}\n\n\t\t\t// Support: Android <=2.3 only (functionish RegExp)\n\t\t\treturn typeof obj === \"object\" || typeof obj === \"function\" ?\n\t\t\tclass2type[ toString.call( obj ) ] || \"object\" :\n\t\t\t\ttypeof obj;\n\t\t},\n\n\t\t// Evaluates a script in a global context\n\t\tglobalEval: function( code ) {\n\t\t\tDOMEval( code );\n\t\t},\n\n\t\t// Convert dashed to camelCase; used by the css and data modules\n\t\t// Support: IE <=9 - 11, Edge 12 - 13\n\t\t// Microsoft forgot to hump their vendor prefix (#9572)\n\t\tcamelCase: function( string ) {\n\t\t\treturn string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n\t\t},\n\n\t\teach: function( obj, callback ) {\n\t\t\tvar length, i = 0;\n\n\t\t\tif ( isArrayLike( obj ) ) {\n\t\t\t\tlength = obj.length;\n\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\tif ( callback.call( obj[ i ], i, obj[ i ] ) === 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\tif ( callback.call( obj[ i ], i, obj[ i ] ) === 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\treturn obj;\n\t\t},\n\n\t\t// Support: Android <=4.0 only\n\t\ttrim: function( 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\t// results is for internal usage only\n\t\tmakeArray: function( arr, results ) {\n\t\t\tvar ret = results || [];\n\n\t\t\tif ( arr != null ) {\n\t\t\t\tif ( isArrayLike( Object( arr ) ) ) {\n\t\t\t\t\tjQuery.merge( ret,\n\t\t\t\t\t\ttypeof arr === \"string\" ?\n\t\t\t\t\t\t\t[ arr ] : arr\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tpush.call( ret, arr );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn ret;\n\t\t},\n\n\t\tinArray: function( elem, arr, i ) {\n\t\t\treturn arr == null ? -1 : indexOf.call( arr, elem, i );\n\t\t},\n\n\t\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t\t// push.apply(_, arraylike) throws on ancient WebKit\n\t\tmerge: function( first, second ) {\n\t\t\tvar len = +second.length,\n\t\t\t\tj = 0,\n\t\t\t\ti = first.length;\n\n\t\t\tfor ( ; j < len; j++ ) {\n\t\t\t\tfirst[ i++ ] = second[ j ];\n\t\t\t}\n\n\t\t\tfirst.length = i;\n\n\t\t\treturn first;\n\t\t},\n\n\t\tgrep: function( elems, callback, invert ) {\n\t\t\tvar callbackInverse,\n\t\t\t\tmatches = [],\n\t\t\t\ti = 0,\n\t\t\t\tlength = elems.length,\n\t\t\t\tcallbackExpect = !invert;\n\n\t\t\t// Go through the array, only saving the items\n\t\t\t// that pass the validator function\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tcallbackInverse = !callback( elems[ i ], i );\n\t\t\t\tif ( callbackInverse !== callbackExpect ) {\n\t\t\t\t\tmatches.push( elems[ i ] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn matches;\n\t\t},\n\n\t\t// arg is for internal usage only\n\t\tmap: function( elems, callback, arg ) {\n\t\t\tvar length, value,\n\t\t\t\ti = 0,\n\t\t\t\tret = [];\n\n\t\t\t// Go through the array, translating each of the items to their new values\n\t\t\tif ( isArrayLike( elems ) ) {\n\t\t\t\tlength = elems.length;\n\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\t\tif ( value != null ) {\n\t\t\t\t\t\tret.push( value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Go through every key on the object,\n\t\t\t} else {\n\t\t\t\tfor ( i in elems ) {\n\t\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\t\tif ( value != null ) {\n\t\t\t\t\t\tret.push( value );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Flatten any nested arrays\n\t\t\treturn concat.apply( [], ret );\n\t\t},\n\n\t\t// A global GUID counter for objects\n\t\tguid: 1,\n\n\t\t// Bind a function to a context, optionally partially applying any\n\t\t// arguments.\n\t\tproxy: function( fn, context ) {\n\t\t\tvar tmp, args, proxy;\n\n\t\t\tif ( typeof context === \"string\" ) {\n\t\t\t\ttmp = fn[ context ];\n\t\t\t\tcontext = fn;\n\t\t\t\tfn = tmp;\n\t\t\t}\n\n\t\t\t// Quick check to determine if target is callable, in the spec\n\t\t\t// this throws a TypeError, but we will just return undefined.\n\t\t\tif ( !jQuery.isFunction( fn ) ) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\n\t\t\t// Simulated bind\n\t\t\targs = slice.call( arguments, 2 );\n\t\t\tproxy = function() {\n\t\t\t\treturn fn.apply( context || this, args.concat( slice.call( arguments ) ) );\n\t\t\t};\n\n\t\t\t// Set the guid of unique handler to the same of original handler, so it can be removed\n\t\t\tproxy.guid = fn.guid = fn.guid || jQuery.guid++;\n\n\t\t\treturn proxy;\n\t\t},\n\n\t\tnow: Date.now,\n\n\t\t// jQuery.support is not used in Core but other projects attach their\n\t\t// properties to it so it needs to exist.\n\t\tsupport: support\n\t} );\n\n\tif ( typeof Symbol === \"function\" ) {\n\t\tjQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ];\n\t}\n\n// Populate the class2type map\n\tjQuery.each( \"Boolean Number String Function Array Date RegExp Object Error Symbol\".split( \" \" ),\n\t\tfunction( i, name ) {\n\t\t\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n\t\t} );\n\n\tfunction isArrayLike( obj ) {\n\n\t\t// Support: real iOS 8.2 only (not reproducible in simulator)\n\t\t// `in` check used to prevent JIT error (gh-2145)\n\t\t// hasOwn isn't used here due to false negatives\n\t\t// regarding Nodelist length in IE\n\t\tvar length = !!obj && \"length\" in obj && obj.length,\n\t\t\ttype = jQuery.type( obj );\n\n\t\tif ( type === \"function\" || jQuery.isWindow( obj ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn type === \"array\" || length === 0 ||\n\t\t\ttypeof length === \"number\" && length > 0 && ( length - 1 ) in obj;\n\t}\n\tvar Sizzle =\n\t\t/*!\n\t\t * Sizzle CSS Selector Engine v2.3.3\n\t\t * https://sizzlejs.com/\n\t\t *\n\t\t * Copyright jQuery Foundation and other contributors\n\t\t * Released under the MIT license\n\t\t * http://jquery.org/license\n\t\t *\n\t\t * Date: 2016-08-08\n\t\t */\n\t\t(function( window ) {\n\n\t\t\tvar i,\n\t\t\t\tsupport,\n\t\t\t\tExpr,\n\t\t\t\tgetText,\n\t\t\t\tisXML,\n\t\t\t\ttokenize,\n\t\t\t\tcompile,\n\t\t\t\tselect,\n\t\t\t\toutermostContext,\n\t\t\t\tsortInput,\n\t\t\t\thasDuplicate,\n\n\t\t\t\t// Local document vars\n\t\t\t\tsetDocument,\n\t\t\t\tdocument,\n\t\t\t\tdocElem,\n\t\t\t\tdocumentIsHTML,\n\t\t\t\trbuggyQSA,\n\t\t\t\trbuggyMatches,\n\t\t\t\tmatches,\n\t\t\t\tcontains,\n\n\t\t\t\t// Instance-specific data\n\t\t\t\texpando = \"sizzle\" + 1 * new Date(),\n\t\t\t\tpreferredDoc = window.document,\n\t\t\t\tdirruns = 0,\n\t\t\t\tdone = 0,\n\t\t\t\tclassCache = createCache(),\n\t\t\t\ttokenCache = createCache(),\n\t\t\t\tcompilerCache = createCache(),\n\t\t\t\tsortOrder = function( a, b ) {\n\t\t\t\t\tif ( a === b ) {\n\t\t\t\t\t\thasDuplicate = true;\n\t\t\t\t\t}\n\t\t\t\t\treturn 0;\n\t\t\t\t},\n\n\t\t\t\t// Instance methods\n\t\t\t\thasOwn = ({}).hasOwnProperty,\n\t\t\t\tarr = [],\n\t\t\t\tpop = arr.pop,\n\t\t\t\tpush_native = arr.push,\n\t\t\t\tpush = arr.push,\n\t\t\t\tslice = arr.slice,\n\t\t\t\t// Use a stripped-down indexOf as it's faster than native\n\t\t\t\t// https://jsperf.com/thor-indexof-vs-for/5\n\t\t\t\tindexOf = function( list, elem ) {\n\t\t\t\t\tvar i = 0,\n\t\t\t\t\t\tlen = list.length;\n\t\t\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t\t\tif ( list[i] === elem ) {\n\t\t\t\t\t\t\treturn i;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn -1;\n\t\t\t\t},\n\n\t\t\t\tbooleans = \"checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped\",\n\n\t\t\t\t// Regular expressions\n\n\t\t\t\t// http://www.w3.org/TR/css3-selectors/#whitespace\n\t\t\t\twhitespace = \"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",\n\n\t\t\t\t// http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier\n\t\t\t\tidentifier = \"(?:\\\\\\\\.|[\\\\w-]|[^\\0-\\\\xa0])+\",\n\n\t\t\t\t// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors\n\t\t\t\tattributes = \"\\\\[\" + whitespace + \"*(\" + identifier + \")(?:\" + whitespace +\n\t\t\t\t\t// Operator (capture 2)\n\t\t\t\t\t\"*([*^$|!~]?=)\" + whitespace +\n\t\t\t\t\t// \"Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]\"\n\t\t\t\t\t\"*(?:'((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\"|(\" + identifier + \"))|)\" + whitespace +\n\t\t\t\t\t\"*\\\\]\",\n\n\t\t\t\tpseudos = \":(\" + identifier + \")(?:\\\\((\" +\n\t\t\t\t\t// To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:\n\t\t\t\t\t// 1. quoted (capture 3; capture 4 or capture 5)\n\t\t\t\t\t\"('((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\")|\" +\n\t\t\t\t\t// 2. simple (capture 6)\n\t\t\t\t\t\"((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\" + attributes + \")*)|\" +\n\t\t\t\t\t// 3. anything else (capture 2)\n\t\t\t\t\t\".*\" +\n\t\t\t\t\t\")\\\\)|)\",\n\n\t\t\t\t// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter\n\t\t\t\trwhitespace = new RegExp( whitespace + \"+\", \"g\" ),\n\t\t\t\trtrim = new RegExp( \"^\" + whitespace + \"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\" + whitespace + \"+$\", \"g\" ),\n\n\t\t\t\trcomma = new RegExp( \"^\" + whitespace + \"*,\" + whitespace + \"*\" ),\n\t\t\t\trcombinators = new RegExp( \"^\" + whitespace + \"*([>+~]|\" + whitespace + \")\" + whitespace + \"*\" ),\n\n\t\t\t\trattributeQuotes = new RegExp( \"=\" + whitespace + \"*([^\\\\]'\\\"]*?)\" + whitespace + \"*\\\\]\", \"g\" ),\n\n\t\t\t\trpseudo = new RegExp( pseudos ),\n\t\t\t\tridentifier = new RegExp( \"^\" + identifier + \"$\" ),\n\n\t\t\t\tmatchExpr = {\n\t\t\t\t\t\"ID\": new RegExp( \"^#(\" + identifier + \")\" ),\n\t\t\t\t\t\"CLASS\": new RegExp( \"^\\\\.(\" + identifier + \")\" ),\n\t\t\t\t\t\"TAG\": new RegExp( \"^(\" + identifier + \"|[*])\" ),\n\t\t\t\t\t\"ATTR\": new RegExp( \"^\" + attributes ),\n\t\t\t\t\t\"PSEUDO\": new RegExp( \"^\" + pseudos ),\n\t\t\t\t\t\"CHILD\": new RegExp( \"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\" + whitespace +\n\t\t\t\t\t\t\"*(even|odd|(([+-]|)(\\\\d*)n|)\" + whitespace + \"*(?:([+-]|)\" + whitespace +\n\t\t\t\t\t\t\"*(\\\\d+)|))\" + whitespace + \"*\\\\)|)\", \"i\" ),\n\t\t\t\t\t\"bool\": new RegExp( \"^(?:\" + booleans + \")$\", \"i\" ),\n\t\t\t\t\t// For use in libraries implementing .is()\n\t\t\t\t\t// We use this for POS matching in `select`\n\t\t\t\t\t\"needsContext\": new RegExp( \"^\" + whitespace + \"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\" +\n\t\t\t\t\t\twhitespace + \"*((?:-\\\\d)?\\\\d*)\" + whitespace + \"*\\\\)|)(?=[^-]|$)\", \"i\" )\n\t\t\t\t},\n\n\t\t\t\trinputs = /^(?:input|select|textarea|button)$/i,\n\t\t\t\trheader = /^h\\d$/i,\n\n\t\t\t\trnative = /^[^{]+\\{\\s*\\[native \\w/,\n\n\t\t\t\t// Easily-parseable/retrievable ID or TAG or CLASS selectors\n\t\t\t\trquickExpr = /^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,\n\n\t\t\t\trsibling = /[+~]/,\n\n\t\t\t\t// CSS escapes\n\t\t\t\t// http://www.w3.org/TR/CSS21/syndata.html#escaped-characters\n\t\t\t\trunescape = new RegExp( \"\\\\\\\\([\\\\da-f]{1,6}\" + whitespace + \"?|(\" + whitespace + \")|.)\", \"ig\" ),\n\t\t\t\tfunescape = function( _, escaped, escapedWhitespace ) {\n\t\t\t\t\tvar high = \"0x\" + escaped - 0x10000;\n\t\t\t\t\t// NaN means non-codepoint\n\t\t\t\t\t// Support: Firefox<24\n\t\t\t\t\t// Workaround erroneous numeric interpretation of +\"0x\"\n\t\t\t\t\treturn high !== high || escapedWhitespace ?\n\t\t\t\t\t\tescaped :\n\t\t\t\t\t\thigh < 0 ?\n\t\t\t\t\t\t\t// BMP codepoint\n\t\t\t\t\t\t\tString.fromCharCode( high + 0x10000 ) :\n\t\t\t\t\t\t\t// Supplemental Plane codepoint (surrogate pair)\n\t\t\t\t\t\t\tString.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );\n\t\t\t\t},\n\n\t\t\t\t// CSS string/identifier serialization\n\t\t\t\t// https://drafts.csswg.org/cssom/#common-serializing-idioms\n\t\t\t\trcssescape = /([\\0-\\x1f\\x7f]|^-?\\d)|^-$|[^\\0-\\x1f\\x7f-\\uFFFF\\w-]/g,\n\t\t\t\tfcssescape = function( ch, asCodePoint ) {\n\t\t\t\t\tif ( asCodePoint ) {\n\n\t\t\t\t\t\t// U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER\n\t\t\t\t\t\tif ( ch === \"\\0\" ) {\n\t\t\t\t\t\t\treturn \"\\uFFFD\";\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Control characters and (dependent upon position) numbers get escaped as code points\n\t\t\t\t\t\treturn ch.slice( 0, -1 ) + \"\\\\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + \" \";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Other potentially-special ASCII characters get backslash-escaped\n\t\t\t\t\treturn \"\\\\\" + ch;\n\t\t\t\t},\n\n\t\t\t\t// Used for iframes\n\t\t\t\t// See setDocument()\n\t\t\t\t// Removing the function wrapper causes a \"Permission Denied\"\n\t\t\t\t// error in IE\n\t\t\t\tunloadHandler = function() {\n\t\t\t\t\tsetDocument();\n\t\t\t\t},\n\n\t\t\t\tdisabledAncestor = addCombinator(\n\t\t\t\t\tfunction( elem ) {\n\t\t\t\t\t\treturn elem.disabled === true && (\"form\" in elem || \"label\" in elem);\n\t\t\t\t\t},\n\t\t\t\t\t{ dir: \"parentNode\", next: \"legend\" }\n\t\t\t\t);\n\n// Optimize for push.apply( _, NodeList )\n\t\t\ttry {\n\t\t\t\tpush.apply(\n\t\t\t\t\t(arr = slice.call( preferredDoc.childNodes )),\n\t\t\t\t\tpreferredDoc.childNodes\n\t\t\t\t);\n\t\t\t\t// Support: Android<4.0\n\t\t\t\t// Detect silently failing push.apply\n\t\t\t\tarr[ preferredDoc.childNodes.length ].nodeType;\n\t\t\t} catch ( e ) {\n\t\t\t\tpush = { apply: arr.length ?\n\n\t\t\t\t\t// Leverage slice if possible\n\t\t\t\t\tfunction( target, els ) {\n\t\t\t\t\t\tpush_native.apply( target, slice.call(els) );\n\t\t\t\t\t} :\n\n\t\t\t\t\t// Support: IE<9\n\t\t\t\t\t// Otherwise append directly\n\t\t\t\t\tfunction( target, els ) {\n\t\t\t\t\t\tvar j = target.length,\n\t\t\t\t\t\t\ti = 0;\n\t\t\t\t\t\t// Can't trust NodeList.length\n\t\t\t\t\t\twhile ( (target[j++] = els[i++]) ) {}\n\t\t\t\t\t\ttarget.length = j - 1;\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tfunction Sizzle( selector, context, results, seed ) {\n\t\t\t\tvar m, i, elem, nid, match, groups, newSelector,\n\t\t\t\t\tnewContext = context && context.ownerDocument,\n\n\t\t\t\t\t// nodeType defaults to 9, since context defaults to document\n\t\t\t\t\tnodeType = context ? context.nodeType : 9;\n\n\t\t\t\tresults = results || [];\n\n\t\t\t\t// Return early from calls with invalid selector or context\n\t\t\t\tif ( typeof selector !== \"string\" || !selector ||\n\t\t\t\t\tnodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {\n\n\t\t\t\t\treturn results;\n\t\t\t\t}\n\n\t\t\t\t// Try to shortcut find operations (as opposed to filters) in HTML documents\n\t\t\t\tif ( !seed ) {\n\n\t\t\t\t\tif ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {\n\t\t\t\t\t\tsetDocument( context );\n\t\t\t\t\t}\n\t\t\t\t\tcontext = context || document;\n\n\t\t\t\t\tif ( documentIsHTML ) {\n\n\t\t\t\t\t\t// If the selector is sufficiently simple, try using a \"get*By*\" DOM method\n\t\t\t\t\t\t// (excepting DocumentFragment context, where the methods don't exist)\n\t\t\t\t\t\tif ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {\n\n\t\t\t\t\t\t\t// ID selector\n\t\t\t\t\t\t\tif ( (m = match[1]) ) {\n\n\t\t\t\t\t\t\t\t// Document context\n\t\t\t\t\t\t\t\tif ( nodeType === 9 ) {\n\t\t\t\t\t\t\t\t\tif ( (elem = context.getElementById( m )) ) {\n\n\t\t\t\t\t\t\t\t\t\t// Support: IE, Opera, Webkit\n\t\t\t\t\t\t\t\t\t\t// TODO: identify versions\n\t\t\t\t\t\t\t\t\t\t// getElementById can match elements by name instead of ID\n\t\t\t\t\t\t\t\t\t\tif ( elem.id === m ) {\n\t\t\t\t\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Element context\n\t\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t\t// Support: IE, Opera, Webkit\n\t\t\t\t\t\t\t\t\t// TODO: identify versions\n\t\t\t\t\t\t\t\t\t// getElementById can match elements by name instead of ID\n\t\t\t\t\t\t\t\t\tif ( newContext && (elem = newContext.getElementById( m )) &&\n\t\t\t\t\t\t\t\t\t\tcontains( context, elem ) &&\n\t\t\t\t\t\t\t\t\t\telem.id === m ) {\n\n\t\t\t\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\t\t\t\treturn results;\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// Type selector\n\t\t\t\t\t\t\t} else if ( match[2] ) {\n\t\t\t\t\t\t\t\tpush.apply( results, context.getElementsByTagName( selector ) );\n\t\t\t\t\t\t\t\treturn results;\n\n\t\t\t\t\t\t\t\t// Class selector\n\t\t\t\t\t\t\t} else if ( (m = match[3]) && support.getElementsByClassName &&\n\t\t\t\t\t\t\t\tcontext.getElementsByClassName ) {\n\n\t\t\t\t\t\t\t\tpush.apply( results, context.getElementsByClassName( m ) );\n\t\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Take advantage of querySelectorAll\n\t\t\t\t\t\tif ( support.qsa &&\n\t\t\t\t\t\t\t!compilerCache[ selector + \" \" ] &&\n\t\t\t\t\t\t\t(!rbuggyQSA || !rbuggyQSA.test( selector )) ) {\n\n\t\t\t\t\t\t\tif ( nodeType !== 1 ) {\n\t\t\t\t\t\t\t\tnewContext = context;\n\t\t\t\t\t\t\t\tnewSelector = selector;\n\n\t\t\t\t\t\t\t\t// qSA looks outside Element context, which is not what we want\n\t\t\t\t\t\t\t\t// Thanks to Andrew Dupont for this workaround technique\n\t\t\t\t\t\t\t\t// Support: IE <=8\n\t\t\t\t\t\t\t\t// Exclude object elements\n\t\t\t\t\t\t\t} else if ( context.nodeName.toLowerCase() !== \"object\" ) {\n\n\t\t\t\t\t\t\t\t// Capture the context ID, setting it first if necessary\n\t\t\t\t\t\t\t\tif ( (nid = context.getAttribute( \"id\" )) ) {\n\t\t\t\t\t\t\t\t\tnid = nid.replace( rcssescape, fcssescape );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tcontext.setAttribute( \"id\", (nid = expando) );\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// Prefix every selector in the list\n\t\t\t\t\t\t\t\tgroups = tokenize( selector );\n\t\t\t\t\t\t\t\ti = groups.length;\n\t\t\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\t\t\tgroups[i] = \"#\" + nid + \" \" + toSelector( groups[i] );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tnewSelector = groups.join( \",\" );\n\n\t\t\t\t\t\t\t\t// Expand context for sibling selectors\n\t\t\t\t\t\t\t\tnewContext = rsibling.test( selector ) && testContext( context.parentNode ) ||\n\t\t\t\t\t\t\t\t\tcontext;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif ( newSelector ) {\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tpush.apply( results,\n\t\t\t\t\t\t\t\t\t\tnewContext.querySelectorAll( newSelector )\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t\t\t} catch ( qsaError ) {\n\t\t\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\t\t\tif ( nid === expando ) {\n\t\t\t\t\t\t\t\t\t\tcontext.removeAttribute( \"id\" );\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}\n\t\t\t\t}\n\n\t\t\t\t// All others\n\t\t\t\treturn select( selector.replace( rtrim, \"$1\" ), context, results, seed );\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Create key-value caches of limited size\n\t\t\t * @returns {function(string, object)} Returns the Object data after storing it on itself with\n\t\t\t *\tproperty name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)\n\t\t\t *\tdeleting the oldest entry\n\t\t\t */\n\t\t\tfunction createCache() {\n\t\t\t\tvar keys = [];\n\n\t\t\t\tfunction cache( key, value ) {\n\t\t\t\t\t// Use (key + \" \") to avoid collision with native prototype properties (see Issue #157)\n\t\t\t\t\tif ( keys.push( key + \" \" ) > Expr.cacheLength ) {\n\t\t\t\t\t\t// Only keep the most recent entries\n\t\t\t\t\t\tdelete cache[ keys.shift() ];\n\t\t\t\t\t}\n\t\t\t\t\treturn (cache[ key + \" \" ] = value);\n\t\t\t\t}\n\t\t\t\treturn cache;\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Mark a function for special use by Sizzle\n\t\t\t * @param {Function} fn The function to mark\n\t\t\t */\n\t\t\tfunction markFunction( fn ) {\n\t\t\t\tfn[ expando ] = true;\n\t\t\t\treturn fn;\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Support testing using an element\n\t\t\t * @param {Function} fn Passed the created element and returns a boolean result\n\t\t\t */\n\t\t\tfunction assert( fn ) {\n\t\t\t\tvar el = document.createElement(\"fieldset\");\n\n\t\t\t\ttry {\n\t\t\t\t\treturn !!fn( el );\n\t\t\t\t} catch (e) {\n\t\t\t\t\treturn false;\n\t\t\t\t} finally {\n\t\t\t\t\t// Remove from its parent by default\n\t\t\t\t\tif ( el.parentNode ) {\n\t\t\t\t\t\tel.parentNode.removeChild( el );\n\t\t\t\t\t}\n\t\t\t\t\t// release memory in IE\n\t\t\t\t\tel = null;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Adds the same handler for all of the specified attrs\n\t\t\t * @param {String} attrs Pipe-separated list of attributes\n\t\t\t * @param {Function} handler The method that will be applied\n\t\t\t */\n\t\t\tfunction addHandle( attrs, handler ) {\n\t\t\t\tvar arr = attrs.split(\"|\"),\n\t\t\t\t\ti = arr.length;\n\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\tExpr.attrHandle[ arr[i] ] = handler;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Checks document order of two siblings\n\t\t\t * @param {Element} a\n\t\t\t * @param {Element} b\n\t\t\t * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b\n\t\t\t */\n\t\t\tfunction siblingCheck( a, b ) {\n\t\t\t\tvar cur = b && a,\n\t\t\t\t\tdiff = cur && a.nodeType === 1 && b.nodeType === 1 &&\n\t\t\t\t\t\ta.sourceIndex - b.sourceIndex;\n\n\t\t\t\t// Use IE sourceIndex if available on both nodes\n\t\t\t\tif ( diff ) {\n\t\t\t\t\treturn diff;\n\t\t\t\t}\n\n\t\t\t\t// Check if b follows a\n\t\t\t\tif ( cur ) {\n\t\t\t\t\twhile ( (cur = cur.nextSibling) ) {\n\t\t\t\t\t\tif ( cur === b ) {\n\t\t\t\t\t\t\treturn -1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn a ? 1 : -1;\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Returns a function to use in pseudos for input types\n\t\t\t * @param {String} type\n\t\t\t */\n\t\t\tfunction createInputPseudo( type ) {\n\t\t\t\treturn function( elem ) {\n\t\t\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\t\t\treturn name === \"input\" && elem.type === type;\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Returns a function to use in pseudos for buttons\n\t\t\t * @param {String} type\n\t\t\t */\n\t\t\tfunction createButtonPseudo( type ) {\n\t\t\t\treturn function( elem ) {\n\t\t\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\t\t\treturn (name === \"input\" || name === \"button\") && elem.type === type;\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Returns a function to use in pseudos for :enabled/:disabled\n\t\t\t * @param {Boolean} disabled true for :disabled; false for :enabled\n\t\t\t */\n\t\t\tfunction createDisabledPseudo( disabled ) {\n\n\t\t\t\t// Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable\n\t\t\t\treturn function( elem ) {\n\n\t\t\t\t\t// Only certain elements can match :enabled or :disabled\n\t\t\t\t\t// https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled\n\t\t\t\t\t// https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled\n\t\t\t\t\tif ( \"form\" in elem ) {\n\n\t\t\t\t\t\t// Check for inherited disabledness on relevant non-disabled elements:\n\t\t\t\t\t\t// * listed form-associated elements in a disabled fieldset\n\t\t\t\t\t\t//   https://html.spec.whatwg.org/multipage/forms.html#category-listed\n\t\t\t\t\t\t//   https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled\n\t\t\t\t\t\t// * option elements in a disabled optgroup\n\t\t\t\t\t\t//   https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled\n\t\t\t\t\t\t// All such elements have a \"form\" property.\n\t\t\t\t\t\tif ( elem.parentNode && elem.disabled === false ) {\n\n\t\t\t\t\t\t\t// Option elements defer to a parent optgroup if present\n\t\t\t\t\t\t\tif ( \"label\" in elem ) {\n\t\t\t\t\t\t\t\tif ( \"label\" in elem.parentNode ) {\n\t\t\t\t\t\t\t\t\treturn elem.parentNode.disabled === disabled;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\treturn elem.disabled === disabled;\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\t// Support: IE 6 - 11\n\t\t\t\t\t\t\t// Use the isDisabled shortcut property to check for disabled fieldset ancestors\n\t\t\t\t\t\t\treturn elem.isDisabled === disabled ||\n\n\t\t\t\t\t\t\t\t// Where there is no isDisabled, check manually\n\t\t\t\t\t\t\t\t/* jshint -W018 */\n\t\t\t\t\t\t\t\telem.isDisabled !== !disabled &&\n\t\t\t\t\t\t\t\tdisabledAncestor( elem ) === disabled;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn elem.disabled === disabled;\n\n\t\t\t\t\t\t// Try to winnow out elements that can't be disabled before trusting the disabled property.\n\t\t\t\t\t\t// Some victims get caught in our net (label, legend, menu, track), but it shouldn't\n\t\t\t\t\t\t// even exist on them, let alone have a boolean value.\n\t\t\t\t\t} else if ( \"label\" in elem ) {\n\t\t\t\t\t\treturn elem.disabled === disabled;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remaining elements are neither :enabled nor :disabled\n\t\t\t\t\treturn false;\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Returns a function to use in pseudos for positionals\n\t\t\t * @param {Function} fn\n\t\t\t */\n\t\t\tfunction createPositionalPseudo( fn ) {\n\t\t\t\treturn markFunction(function( argument ) {\n\t\t\t\t\targument = +argument;\n\t\t\t\t\treturn markFunction(function( seed, matches ) {\n\t\t\t\t\t\tvar j,\n\t\t\t\t\t\t\tmatchIndexes = fn( [], seed.length, argument ),\n\t\t\t\t\t\t\ti = matchIndexes.length;\n\n\t\t\t\t\t\t// Match elements found at the specified indexes\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tif ( seed[ (j = matchIndexes[i]) ] ) {\n\t\t\t\t\t\t\t\tseed[j] = !(matches[j] = seed[j]);\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\n\t\t\t/**\n\t\t\t * Checks a node for validity as a Sizzle context\n\t\t\t * @param {Element|Object=} context\n\t\t\t * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value\n\t\t\t */\n\t\t\tfunction testContext( context ) {\n\t\t\t\treturn context && typeof context.getElementsByTagName !== \"undefined\" && context;\n\t\t\t}\n\n// Expose support vars for convenience\n\t\t\tsupport = Sizzle.support = {};\n\n\t\t\t/**\n\t\t\t * Detects XML nodes\n\t\t\t * @param {Element|Object} elem An element or a document\n\t\t\t * @returns {Boolean} True iff elem is a non-HTML XML node\n\t\t\t */\n\t\t\tisXML = Sizzle.isXML = function( elem ) {\n\t\t\t\t// documentElement is verified for cases where it doesn't yet exist\n\t\t\t\t// (such as loading iframes in IE - #4833)\n\t\t\t\tvar documentElement = elem && (elem.ownerDocument || elem).documentElement;\n\t\t\t\treturn documentElement ? documentElement.nodeName !== \"HTML\" : false;\n\t\t\t};\n\n\t\t\t/**\n\t\t\t * Sets document-related variables once based on the current document\n\t\t\t * @param {Element|Object} [doc] An element or document object to use to set the document\n\t\t\t * @returns {Object} Returns the current document\n\t\t\t */\n\t\t\tsetDocument = Sizzle.setDocument = function( node ) {\n\t\t\t\tvar hasCompare, subWindow,\n\t\t\t\t\tdoc = node ? node.ownerDocument || node : preferredDoc;\n\n\t\t\t\t// Return early if doc is invalid or already selected\n\t\t\t\tif ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {\n\t\t\t\t\treturn document;\n\t\t\t\t}\n\n\t\t\t\t// Update global variables\n\t\t\t\tdocument = doc;\n\t\t\t\tdocElem = document.documentElement;\n\t\t\t\tdocumentIsHTML = !isXML( document );\n\n\t\t\t\t// Support: IE 9-11, Edge\n\t\t\t\t// Accessing iframe documents after unload throws \"permission denied\" errors (jQuery #13936)\n\t\t\t\tif ( preferredDoc !== document &&\n\t\t\t\t\t(subWindow = document.defaultView) && subWindow.top !== subWindow ) {\n\n\t\t\t\t\t// Support: IE 11, Edge\n\t\t\t\t\tif ( subWindow.addEventListener ) {\n\t\t\t\t\t\tsubWindow.addEventListener( \"unload\", unloadHandler, false );\n\n\t\t\t\t\t\t// Support: IE 9 - 10 only\n\t\t\t\t\t} else if ( subWindow.attachEvent ) {\n\t\t\t\t\t\tsubWindow.attachEvent( \"onunload\", unloadHandler );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/* Attributes\n\t\t\t\t ---------------------------------------------------------------------- */\n\n\t\t\t\t// Support: IE<8\n\t\t\t\t// Verify that getAttribute really returns attributes and not properties\n\t\t\t\t// (excepting IE8 booleans)\n\t\t\t\tsupport.attributes = assert(function( el ) {\n\t\t\t\t\tel.className = \"i\";\n\t\t\t\t\treturn !el.getAttribute(\"className\");\n\t\t\t\t});\n\n\t\t\t\t/* getElement(s)By*\n\t\t\t\t ---------------------------------------------------------------------- */\n\n\t\t\t\t// Check if getElementsByTagName(\"*\") returns only elements\n\t\t\t\tsupport.getElementsByTagName = assert(function( el ) {\n\t\t\t\t\tel.appendChild( document.createComment(\"\") );\n\t\t\t\t\treturn !el.getElementsByTagName(\"*\").length;\n\t\t\t\t});\n\n\t\t\t\t// Support: IE<9\n\t\t\t\tsupport.getElementsByClassName = rnative.test( document.getElementsByClassName );\n\n\t\t\t\t// Support: IE<10\n\t\t\t\t// Check if getElementById returns elements by name\n\t\t\t\t// The broken getElementById methods don't pick up programmatically-set names,\n\t\t\t\t// so use a roundabout getElementsByName test\n\t\t\t\tsupport.getById = assert(function( el ) {\n\t\t\t\t\tdocElem.appendChild( el ).id = expando;\n\t\t\t\t\treturn !document.getElementsByName || !document.getElementsByName( expando ).length;\n\t\t\t\t});\n\n\t\t\t\t// ID filter and find\n\t\t\t\tif ( support.getById ) {\n\t\t\t\t\tExpr.filter[\"ID\"] = function( id ) {\n\t\t\t\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\t\t\t\treturn function( elem ) {\n\t\t\t\t\t\t\treturn elem.getAttribute(\"id\") === attrId;\n\t\t\t\t\t\t};\n\t\t\t\t\t};\n\t\t\t\t\tExpr.find[\"ID\"] = function( id, context ) {\n\t\t\t\t\t\tif ( typeof context.getElementById !== \"undefined\" && documentIsHTML ) {\n\t\t\t\t\t\t\tvar elem = context.getElementById( id );\n\t\t\t\t\t\t\treturn elem ? [ elem ] : [];\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\tExpr.filter[\"ID\"] =  function( id ) {\n\t\t\t\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\t\t\t\treturn function( elem ) {\n\t\t\t\t\t\t\tvar node = typeof elem.getAttributeNode !== \"undefined\" &&\n\t\t\t\t\t\t\t\telem.getAttributeNode(\"id\");\n\t\t\t\t\t\t\treturn node && node.value === attrId;\n\t\t\t\t\t\t};\n\t\t\t\t\t};\n\n\t\t\t\t\t// Support: IE 6 - 7 only\n\t\t\t\t\t// getElementById is not reliable as a find shortcut\n\t\t\t\t\tExpr.find[\"ID\"] = function( id, context ) {\n\t\t\t\t\t\tif ( typeof context.getElementById !== \"undefined\" && documentIsHTML ) {\n\t\t\t\t\t\t\tvar node, i, elems,\n\t\t\t\t\t\t\t\telem = context.getElementById( id );\n\n\t\t\t\t\t\t\tif ( elem ) {\n\n\t\t\t\t\t\t\t\t// Verify the id attribute\n\t\t\t\t\t\t\t\tnode = elem.getAttributeNode(\"id\");\n\t\t\t\t\t\t\t\tif ( node && node.value === id ) {\n\t\t\t\t\t\t\t\t\treturn [ elem ];\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// Fall back on getElementsByName\n\t\t\t\t\t\t\t\telems = context.getElementsByName( id );\n\t\t\t\t\t\t\t\ti = 0;\n\t\t\t\t\t\t\t\twhile ( (elem = elems[i++]) ) {\n\t\t\t\t\t\t\t\t\tnode = elem.getAttributeNode(\"id\");\n\t\t\t\t\t\t\t\t\tif ( node && node.value === id ) {\n\t\t\t\t\t\t\t\t\t\treturn [ elem ];\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\n\t\t\t\t\t\t\treturn [];\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\t// Tag\n\t\t\t\tExpr.find[\"TAG\"] = support.getElementsByTagName ?\n\t\t\t\t\tfunction( tag, context ) {\n\t\t\t\t\t\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\t\t\t\t\t\treturn context.getElementsByTagName( tag );\n\n\t\t\t\t\t\t\t// DocumentFragment nodes don't have gEBTN\n\t\t\t\t\t\t} else if ( support.qsa ) {\n\t\t\t\t\t\t\treturn context.querySelectorAll( tag );\n\t\t\t\t\t\t}\n\t\t\t\t\t} :\n\n\t\t\t\t\tfunction( tag, context ) {\n\t\t\t\t\t\tvar elem,\n\t\t\t\t\t\t\ttmp = [],\n\t\t\t\t\t\t\ti = 0,\n\t\t\t\t\t\t\t// By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too\n\t\t\t\t\t\t\tresults = context.getElementsByTagName( tag );\n\n\t\t\t\t\t\t// Filter out possible comments\n\t\t\t\t\t\tif ( tag === \"*\" ) {\n\t\t\t\t\t\t\twhile ( (elem = results[i++]) ) {\n\t\t\t\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\t\t\t\ttmp.push( elem );\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\treturn tmp;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t};\n\n\t\t\t\t// Class\n\t\t\t\tExpr.find[\"CLASS\"] = support.getElementsByClassName && function( className, context ) {\n\t\t\t\t\t\tif ( typeof context.getElementsByClassName !== \"undefined\" && documentIsHTML ) {\n\t\t\t\t\t\t\treturn context.getElementsByClassName( className );\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t/* QSA/matchesSelector\n\t\t\t\t ---------------------------------------------------------------------- */\n\n\t\t\t\t// QSA and matchesSelector support\n\n\t\t\t\t// matchesSelector(:active) reports false when true (IE9/Opera 11.5)\n\t\t\t\trbuggyMatches = [];\n\n\t\t\t\t// qSa(:focus) reports false when true (Chrome 21)\n\t\t\t\t// We allow this because of a bug in IE8/9 that throws an error\n\t\t\t\t// whenever `document.activeElement` is accessed on an iframe\n\t\t\t\t// So, we allow :focus to pass through QSA all the time to avoid the IE error\n\t\t\t\t// See https://bugs.jquery.com/ticket/13378\n\t\t\t\trbuggyQSA = [];\n\n\t\t\t\tif ( (support.qsa = rnative.test( document.querySelectorAll )) ) {\n\t\t\t\t\t// Build QSA regex\n\t\t\t\t\t// Regex strategy adopted from Diego Perini\n\t\t\t\t\tassert(function( el ) {\n\t\t\t\t\t\t// Select is set to empty string on purpose\n\t\t\t\t\t\t// This is to test IE's treatment of not explicitly\n\t\t\t\t\t\t// setting a boolean content attribute,\n\t\t\t\t\t\t// since its presence should be enough\n\t\t\t\t\t\t// https://bugs.jquery.com/ticket/12359\n\t\t\t\t\t\tdocElem.appendChild( el ).innerHTML = \"<a id='\" + expando + \"'></a>\" +\n\t\t\t\t\t\t\t\"<select id='\" + expando + \"-\\r\\\\' msallowcapture=''>\" +\n\t\t\t\t\t\t\t\"<option selected=''></option></select>\";\n\n\t\t\t\t\t\t// Support: IE8, Opera 11-12.16\n\t\t\t\t\t\t// Nothing should be selected when empty strings follow ^= or $= or *=\n\t\t\t\t\t\t// The test attribute must be unknown in Opera but \"safe\" for WinRT\n\t\t\t\t\t\t// https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section\n\t\t\t\t\t\tif ( el.querySelectorAll(\"[msallowcapture^='']\").length ) {\n\t\t\t\t\t\t\trbuggyQSA.push( \"[*^$]=\" + whitespace + \"*(?:''|\\\"\\\")\" );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Support: IE8\n\t\t\t\t\t\t// Boolean attributes and \"value\" are not treated correctly\n\t\t\t\t\t\tif ( !el.querySelectorAll(\"[selected]\").length ) {\n\t\t\t\t\t\t\trbuggyQSA.push( \"\\\\[\" + whitespace + \"*(?:value|\" + booleans + \")\" );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+\n\t\t\t\t\t\tif ( !el.querySelectorAll( \"[id~=\" + expando + \"-]\" ).length ) {\n\t\t\t\t\t\t\trbuggyQSA.push(\"~=\");\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Webkit/Opera - :checked should return selected option elements\n\t\t\t\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\t\t\t\t// IE8 throws error here and will not see later tests\n\t\t\t\t\t\tif ( !el.querySelectorAll(\":checked\").length ) {\n\t\t\t\t\t\t\trbuggyQSA.push(\":checked\");\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Support: Safari 8+, iOS 8+\n\t\t\t\t\t\t// https://bugs.webkit.org/show_bug.cgi?id=136851\n\t\t\t\t\t\t// In-page `selector#id sibling-combinator selector` fails\n\t\t\t\t\t\tif ( !el.querySelectorAll( \"a#\" + expando + \"+*\" ).length ) {\n\t\t\t\t\t\t\trbuggyQSA.push(\".#.+[+~]\");\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\tassert(function( el ) {\n\t\t\t\t\t\tel.innerHTML = \"<a href='' disabled='disabled'></a>\" +\n\t\t\t\t\t\t\t\"<select disabled='disabled'><option/></select>\";\n\n\t\t\t\t\t\t// Support: Windows 8 Native Apps\n\t\t\t\t\t\t// The type and name attributes are restricted during .innerHTML assignment\n\t\t\t\t\t\tvar input = document.createElement(\"input\");\n\t\t\t\t\t\tinput.setAttribute( \"type\", \"hidden\" );\n\t\t\t\t\t\tel.appendChild( input ).setAttribute( \"name\", \"D\" );\n\n\t\t\t\t\t\t// Support: IE8\n\t\t\t\t\t\t// Enforce case-sensitivity of name attribute\n\t\t\t\t\t\tif ( el.querySelectorAll(\"[name=d]\").length ) {\n\t\t\t\t\t\t\trbuggyQSA.push( \"name\" + whitespace + \"*[*^$|!~]?=\" );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)\n\t\t\t\t\t\t// IE8 throws error here and will not see later tests\n\t\t\t\t\t\tif ( el.querySelectorAll(\":enabled\").length !== 2 ) {\n\t\t\t\t\t\t\trbuggyQSA.push( \":enabled\", \":disabled\" );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Support: IE9-11+\n\t\t\t\t\t\t// IE's :disabled selector does not pick up the children of disabled fieldsets\n\t\t\t\t\t\tdocElem.appendChild( el ).disabled = true;\n\t\t\t\t\t\tif ( el.querySelectorAll(\":disabled\").length !== 2 ) {\n\t\t\t\t\t\t\trbuggyQSA.push( \":enabled\", \":disabled\" );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Opera 10-11 does not throw on post-comma invalid pseudos\n\t\t\t\t\t\tel.querySelectorAll(\"*,:x\");\n\t\t\t\t\t\trbuggyQSA.push(\",.*:\");\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tif ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||\n\t\t\t\t\t\tdocElem.webkitMatchesSelector ||\n\t\t\t\t\t\tdocElem.mozMatchesSelector ||\n\t\t\t\t\t\tdocElem.oMatchesSelector ||\n\t\t\t\t\t\tdocElem.msMatchesSelector) )) ) {\n\n\t\t\t\t\tassert(function( el ) {\n\t\t\t\t\t\t// Check to see if it's possible to do matchesSelector\n\t\t\t\t\t\t// on a disconnected node (IE 9)\n\t\t\t\t\t\tsupport.disconnectedMatch = matches.call( el, \"*\" );\n\n\t\t\t\t\t\t// This should fail with an exception\n\t\t\t\t\t\t// Gecko does not error, returns false instead\n\t\t\t\t\t\tmatches.call( el, \"[s!='']:x\" );\n\t\t\t\t\t\trbuggyMatches.push( \"!=\", pseudos );\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\trbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join(\"|\") );\n\t\t\t\trbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join(\"|\") );\n\n\t\t\t\t/* Contains\n\t\t\t\t ---------------------------------------------------------------------- */\n\t\t\t\thasCompare = rnative.test( docElem.compareDocumentPosition );\n\n\t\t\t\t// Element contains another\n\t\t\t\t// Purposefully self-exclusive\n\t\t\t\t// As in, an element does not contain itself\n\t\t\t\tcontains = hasCompare || rnative.test( docElem.contains ) ?\n\t\t\t\t\tfunction( a, b ) {\n\t\t\t\t\t\tvar adown = a.nodeType === 9 ? a.documentElement : a,\n\t\t\t\t\t\t\tbup = b && b.parentNode;\n\t\t\t\t\t\treturn a === bup || !!( bup && bup.nodeType === 1 && (\n\t\t\t\t\t\t\t\tadown.contains ?\n\t\t\t\t\t\t\t\t\tadown.contains( bup ) :\n\t\t\t\t\t\t\t\ta.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16\n\t\t\t\t\t\t\t));\n\t\t\t\t\t} :\n\t\t\t\t\tfunction( a, b ) {\n\t\t\t\t\t\tif ( b ) {\n\t\t\t\t\t\t\twhile ( (b = b.parentNode) ) {\n\t\t\t\t\t\t\t\tif ( b === a ) {\n\t\t\t\t\t\t\t\t\treturn true;\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\treturn false;\n\t\t\t\t\t};\n\n\t\t\t\t/* Sorting\n\t\t\t\t ---------------------------------------------------------------------- */\n\n\t\t\t\t// Document order sorting\n\t\t\t\tsortOrder = hasCompare ?\n\t\t\t\t\tfunction( a, b ) {\n\n\t\t\t\t\t\t// Flag for duplicate removal\n\t\t\t\t\t\tif ( a === b ) {\n\t\t\t\t\t\t\thasDuplicate = true;\n\t\t\t\t\t\t\treturn 0;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Sort on method existence if only one input has compareDocumentPosition\n\t\t\t\t\t\tvar compare = !a.compareDocumentPosition - !b.compareDocumentPosition;\n\t\t\t\t\t\tif ( compare ) {\n\t\t\t\t\t\t\treturn compare;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Calculate position if both inputs belong to the same document\n\t\t\t\t\t\tcompare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?\n\t\t\t\t\t\t\ta.compareDocumentPosition( b ) :\n\n\t\t\t\t\t\t\t// Otherwise we know they are disconnected\n\t\t\t\t\t\t\t1;\n\n\t\t\t\t\t\t// Disconnected nodes\n\t\t\t\t\t\tif ( compare & 1 ||\n\t\t\t\t\t\t\t(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {\n\n\t\t\t\t\t\t\t// Choose the first element that is related to our preferred document\n\t\t\t\t\t\t\tif ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {\n\t\t\t\t\t\t\t\treturn -1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {\n\t\t\t\t\t\t\t\treturn 1;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Maintain original order\n\t\t\t\t\t\t\treturn sortInput ?\n\t\t\t\t\t\t\t\t( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :\n\t\t\t\t\t\t\t\t0;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn compare & 4 ? -1 : 1;\n\t\t\t\t\t} :\n\t\t\t\t\tfunction( a, b ) {\n\t\t\t\t\t\t// Exit early if the nodes are identical\n\t\t\t\t\t\tif ( a === b ) {\n\t\t\t\t\t\t\thasDuplicate = true;\n\t\t\t\t\t\t\treturn 0;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tvar cur,\n\t\t\t\t\t\t\ti = 0,\n\t\t\t\t\t\t\taup = a.parentNode,\n\t\t\t\t\t\t\tbup = b.parentNode,\n\t\t\t\t\t\t\tap = [ a ],\n\t\t\t\t\t\t\tbp = [ b ];\n\n\t\t\t\t\t\t// Parentless nodes are either documents or disconnected\n\t\t\t\t\t\tif ( !aup || !bup ) {\n\t\t\t\t\t\t\treturn a === document ? -1 :\n\t\t\t\t\t\t\t\tb === document ? 1 :\n\t\t\t\t\t\t\t\t\taup ? -1 :\n\t\t\t\t\t\t\t\t\t\tbup ? 1 :\n\t\t\t\t\t\t\t\t\t\t\tsortInput ?\n\t\t\t\t\t\t\t\t\t\t\t\t( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :\n\t\t\t\t\t\t\t\t\t\t\t\t0;\n\n\t\t\t\t\t\t\t// If the nodes are siblings, we can do a quick check\n\t\t\t\t\t\t} else if ( aup === bup ) {\n\t\t\t\t\t\t\treturn siblingCheck( a, b );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Otherwise we need full lists of their ancestors for comparison\n\t\t\t\t\t\tcur = a;\n\t\t\t\t\t\twhile ( (cur = cur.parentNode) ) {\n\t\t\t\t\t\t\tap.unshift( cur );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcur = b;\n\t\t\t\t\t\twhile ( (cur = cur.parentNode) ) {\n\t\t\t\t\t\t\tbp.unshift( cur );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Walk down the tree looking for a discrepancy\n\t\t\t\t\t\twhile ( ap[i] === bp[i] ) {\n\t\t\t\t\t\t\ti++;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn i ?\n\t\t\t\t\t\t\t// Do a sibling check if the nodes have a common ancestor\n\t\t\t\t\t\t\tsiblingCheck( ap[i], bp[i] ) :\n\n\t\t\t\t\t\t\t// Otherwise nodes in our document sort first\n\t\t\t\t\t\t\tap[i] === preferredDoc ? -1 :\n\t\t\t\t\t\t\t\tbp[i] === preferredDoc ? 1 :\n\t\t\t\t\t\t\t\t\t0;\n\t\t\t\t\t};\n\n\t\t\t\treturn document;\n\t\t\t};\n\n\t\t\tSizzle.matches = function( expr, elements ) {\n\t\t\t\treturn Sizzle( expr, null, null, elements );\n\t\t\t};\n\n\t\t\tSizzle.matchesSelector = function( elem, expr ) {\n\t\t\t\t// Set document vars if needed\n\t\t\t\tif ( ( elem.ownerDocument || elem ) !== document ) {\n\t\t\t\t\tsetDocument( elem );\n\t\t\t\t}\n\n\t\t\t\t// Make sure that attribute selectors are quoted\n\t\t\t\texpr = expr.replace( rattributeQuotes, \"='$1']\" );\n\n\t\t\t\tif ( support.matchesSelector && documentIsHTML &&\n\t\t\t\t\t!compilerCache[ expr + \" \" ] &&\n\t\t\t\t\t( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&\n\t\t\t\t\t( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tvar ret = matches.call( elem, expr );\n\n\t\t\t\t\t\t// IE 9's matchesSelector returns false on disconnected nodes\n\t\t\t\t\t\tif ( ret || support.disconnectedMatch ||\n\t\t\t\t\t\t\t// As well, disconnected nodes are said to be in a document\n\t\t\t\t\t\t\t// fragment in IE 9\n\t\t\t\t\t\t\telem.document && elem.document.nodeType !== 11 ) {\n\t\t\t\t\t\t\treturn ret;\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (e) {}\n\t\t\t\t}\n\n\t\t\t\treturn Sizzle( expr, document, null, [ elem ] ).length > 0;\n\t\t\t};\n\n\t\t\tSizzle.contains = function( context, elem ) {\n\t\t\t\t// Set document vars if needed\n\t\t\t\tif ( ( context.ownerDocument || context ) !== document ) {\n\t\t\t\t\tsetDocument( context );\n\t\t\t\t}\n\t\t\t\treturn contains( context, elem );\n\t\t\t};\n\n\t\t\tSizzle.attr = function( elem, name ) {\n\t\t\t\t// Set document vars if needed\n\t\t\t\tif ( ( elem.ownerDocument || elem ) !== document ) {\n\t\t\t\t\tsetDocument( elem );\n\t\t\t\t}\n\n\t\t\t\tvar fn = Expr.attrHandle[ name.toLowerCase() ],\n\t\t\t\t\t// Don't get fooled by Object.prototype properties (jQuery #13807)\n\t\t\t\t\tval = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?\n\t\t\t\t\t\tfn( elem, name, !documentIsHTML ) :\n\t\t\t\t\t\tundefined;\n\n\t\t\t\treturn val !== undefined ?\n\t\t\t\t\tval :\n\t\t\t\t\tsupport.attributes || !documentIsHTML ?\n\t\t\t\t\t\telem.getAttribute( name ) :\n\t\t\t\t\t\t(val = elem.getAttributeNode(name)) && val.specified ?\n\t\t\t\t\t\t\tval.value :\n\t\t\t\t\t\t\tnull;\n\t\t\t};\n\n\t\t\tSizzle.escape = function( sel ) {\n\t\t\t\treturn (sel + \"\").replace( rcssescape, fcssescape );\n\t\t\t};\n\n\t\t\tSizzle.error = function( msg ) {\n\t\t\t\tthrow new Error( \"Syntax error, unrecognized expression: \" + msg );\n\t\t\t};\n\n\t\t\t/**\n\t\t\t * Document sorting and removing duplicates\n\t\t\t * @param {ArrayLike} results\n\t\t\t */\n\t\t\tSizzle.uniqueSort = function( results ) {\n\t\t\t\tvar elem,\n\t\t\t\t\tduplicates = [],\n\t\t\t\t\tj = 0,\n\t\t\t\t\ti = 0;\n\n\t\t\t\t// Unless we *know* we can detect duplicates, assume their presence\n\t\t\t\thasDuplicate = !support.detectDuplicates;\n\t\t\t\tsortInput = !support.sortStable && results.slice( 0 );\n\t\t\t\tresults.sort( sortOrder );\n\n\t\t\t\tif ( hasDuplicate ) {\n\t\t\t\t\twhile ( (elem = results[i++]) ) {\n\t\t\t\t\t\tif ( elem === results[ i ] ) {\n\t\t\t\t\t\t\tj = duplicates.push( i );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\twhile ( j-- ) {\n\t\t\t\t\t\tresults.splice( duplicates[ j ], 1 );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Clear input after sorting to release objects\n\t\t\t\t// See https://github.com/jquery/sizzle/pull/225\n\t\t\t\tsortInput = null;\n\n\t\t\t\treturn results;\n\t\t\t};\n\n\t\t\t/**\n\t\t\t * Utility function for retrieving the text value of an array of DOM nodes\n\t\t\t * @param {Array|Element} elem\n\t\t\t */\n\t\t\tgetText = Sizzle.getText = function( elem ) {\n\t\t\t\tvar node,\n\t\t\t\t\tret = \"\",\n\t\t\t\t\ti = 0,\n\t\t\t\t\tnodeType = elem.nodeType;\n\n\t\t\t\tif ( !nodeType ) {\n\t\t\t\t\t// If no nodeType, this is expected to be an array\n\t\t\t\t\twhile ( (node = elem[i++]) ) {\n\t\t\t\t\t\t// Do not traverse comment nodes\n\t\t\t\t\t\tret += getText( node );\n\t\t\t\t\t}\n\t\t\t\t} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\n\t\t\t\t\t// Use textContent for elements\n\t\t\t\t\t// innerText usage removed for consistency of new lines (jQuery #11153)\n\t\t\t\t\tif ( typeof elem.textContent === \"string\" ) {\n\t\t\t\t\t\treturn elem.textContent;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Traverse its children\n\t\t\t\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\t\t\t\tret += getText( elem );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if ( nodeType === 3 || nodeType === 4 ) {\n\t\t\t\t\treturn elem.nodeValue;\n\t\t\t\t}\n\t\t\t\t// Do not include comment or processing instruction nodes\n\n\t\t\t\treturn ret;\n\t\t\t};\n\n\t\t\tExpr = Sizzle.selectors = {\n\n\t\t\t\t// Can be adjusted by the user\n\t\t\t\tcacheLength: 50,\n\n\t\t\t\tcreatePseudo: markFunction,\n\n\t\t\t\tmatch: matchExpr,\n\n\t\t\t\tattrHandle: {},\n\n\t\t\t\tfind: {},\n\n\t\t\t\trelative: {\n\t\t\t\t\t\">\": { dir: \"parentNode\", first: true },\n\t\t\t\t\t\" \": { dir: \"parentNode\" },\n\t\t\t\t\t\"+\": { dir: \"previousSibling\", first: true },\n\t\t\t\t\t\"~\": { dir: \"previousSibling\" }\n\t\t\t\t},\n\n\t\t\t\tpreFilter: {\n\t\t\t\t\t\"ATTR\": function( match ) {\n\t\t\t\t\t\tmatch[1] = match[1].replace( runescape, funescape );\n\n\t\t\t\t\t\t// Move the given value to match[3] whether quoted or unquoted\n\t\t\t\t\t\tmatch[3] = ( match[3] || match[4] || match[5] || \"\" ).replace( runescape, funescape );\n\n\t\t\t\t\t\tif ( match[2] === \"~=\" ) {\n\t\t\t\t\t\t\tmatch[3] = \" \" + match[3] + \" \";\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn match.slice( 0, 4 );\n\t\t\t\t\t},\n\n\t\t\t\t\t\"CHILD\": function( match ) {\n\t\t\t\t\t\t/* matches from matchExpr[\"CHILD\"]\n\t\t\t\t\t\t 1 type (only|nth|...)\n\t\t\t\t\t\t 2 what (child|of-type)\n\t\t\t\t\t\t 3 argument (even|odd|\\d*|\\d*n([+-]\\d+)?|...)\n\t\t\t\t\t\t 4 xn-component of xn+y argument ([+-]?\\d*n|)\n\t\t\t\t\t\t 5 sign of xn-component\n\t\t\t\t\t\t 6 x of xn-component\n\t\t\t\t\t\t 7 sign of y-component\n\t\t\t\t\t\t 8 y of y-component\n\t\t\t\t\t\t */\n\t\t\t\t\t\tmatch[1] = match[1].toLowerCase();\n\n\t\t\t\t\t\tif ( match[1].slice( 0, 3 ) === \"nth\" ) {\n\t\t\t\t\t\t\t// nth-* requires argument\n\t\t\t\t\t\t\tif ( !match[3] ) {\n\t\t\t\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// numeric x and y parameters for Expr.filter.CHILD\n\t\t\t\t\t\t\t// remember that false/true cast respectively to 0/1\n\t\t\t\t\t\t\tmatch[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === \"even\" || match[3] === \"odd\" ) );\n\t\t\t\t\t\t\tmatch[5] = +( ( match[7] + match[8] ) || match[3] === \"odd\" );\n\n\t\t\t\t\t\t\t// other types prohibit arguments\n\t\t\t\t\t\t} else if ( match[3] ) {\n\t\t\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn match;\n\t\t\t\t\t},\n\n\t\t\t\t\t\"PSEUDO\": function( match ) {\n\t\t\t\t\t\tvar excess,\n\t\t\t\t\t\t\tunquoted = !match[6] && match[2];\n\n\t\t\t\t\t\tif ( matchExpr[\"CHILD\"].test( match[0] ) ) {\n\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Accept quoted arguments as-is\n\t\t\t\t\t\tif ( match[3] ) {\n\t\t\t\t\t\t\tmatch[2] = match[4] || match[5] || \"\";\n\n\t\t\t\t\t\t\t// Strip excess characters from unquoted arguments\n\t\t\t\t\t\t} else if ( unquoted && rpseudo.test( unquoted ) &&\n\t\t\t\t\t\t\t// Get excess from tokenize (recursively)\n\t\t\t\t\t\t\t(excess = tokenize( unquoted, true )) &&\n\t\t\t\t\t\t\t// advance to the next closing parenthesis\n\t\t\t\t\t\t\t(excess = unquoted.indexOf( \")\", unquoted.length - excess ) - unquoted.length) ) {\n\n\t\t\t\t\t\t\t// excess is a negative index\n\t\t\t\t\t\t\tmatch[0] = match[0].slice( 0, excess );\n\t\t\t\t\t\t\tmatch[2] = unquoted.slice( 0, excess );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Return only captures needed by the pseudo filter method (type and argument)\n\t\t\t\t\t\treturn match.slice( 0, 3 );\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\tfilter: {\n\n\t\t\t\t\t\"TAG\": function( nodeNameSelector ) {\n\t\t\t\t\t\tvar nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();\n\t\t\t\t\t\treturn nodeNameSelector === \"*\" ?\n\t\t\t\t\t\t\tfunction() { return true; } :\n\t\t\t\t\t\t\tfunction( elem ) {\n\t\t\t\t\t\t\t\treturn elem.nodeName && elem.nodeName.toLowerCase() === nodeName;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t},\n\n\t\t\t\t\t\"CLASS\": function( className ) {\n\t\t\t\t\t\tvar pattern = classCache[ className + \" \" ];\n\n\t\t\t\t\t\treturn pattern ||\n\t\t\t\t\t\t\t(pattern = new RegExp( \"(^|\" + whitespace + \")\" + className + \"(\" + whitespace + \"|$)\" )) &&\n\t\t\t\t\t\t\tclassCache( className, function( elem ) {\n\t\t\t\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\t\t\t});\n\t\t\t\t\t},\n\n\t\t\t\t\t\"ATTR\": function( name, operator, check ) {\n\t\t\t\t\t\treturn function( elem ) {\n\t\t\t\t\t\t\tvar result = Sizzle.attr( elem, name );\n\n\t\t\t\t\t\t\tif ( result == null ) {\n\t\t\t\t\t\t\t\treturn operator === \"!=\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif ( !operator ) {\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tresult += \"\";\n\n\t\t\t\t\t\t\treturn operator === \"=\" ? result === check :\n\t\t\t\t\t\t\t\toperator === \"!=\" ? result !== check :\n\t\t\t\t\t\t\t\t\toperator === \"^=\" ? check && result.indexOf( check ) === 0 :\n\t\t\t\t\t\t\t\t\t\toperator === \"*=\" ? check && result.indexOf( check ) > -1 :\n\t\t\t\t\t\t\t\t\t\t\toperator === \"$=\" ? check && result.slice( -check.length ) === check :\n\t\t\t\t\t\t\t\t\t\t\t\toperator === \"~=\" ? ( \" \" + result.replace( rwhitespace, \" \" ) + \" \" ).indexOf( check ) > -1 :\n\t\t\t\t\t\t\t\t\t\t\t\t\toperator === \"|=\" ? result === check || result.slice( 0, check.length + 1 ) === check + \"-\" :\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfalse;\n\t\t\t\t\t\t};\n\t\t\t\t\t},\n\n\t\t\t\t\t\"CHILD\": function( type, what, argument, first, last ) {\n\t\t\t\t\t\tvar simple = type.slice( 0, 3 ) !== \"nth\",\n\t\t\t\t\t\t\tforward = type.slice( -4 ) !== \"last\",\n\t\t\t\t\t\t\tofType = what === \"of-type\";\n\n\t\t\t\t\t\treturn first === 1 && last === 0 ?\n\n\t\t\t\t\t\t\t// Shortcut for :nth-*(n)\n\t\t\t\t\t\t\tfunction( elem ) {\n\t\t\t\t\t\t\t\treturn !!elem.parentNode;\n\t\t\t\t\t\t\t} :\n\n\t\t\t\t\t\t\tfunction( elem, context, xml ) {\n\t\t\t\t\t\t\t\tvar cache, uniqueCache, outerCache, node, nodeIndex, start,\n\t\t\t\t\t\t\t\t\tdir = simple !== forward ? \"nextSibling\" : \"previousSibling\",\n\t\t\t\t\t\t\t\t\tparent = elem.parentNode,\n\t\t\t\t\t\t\t\t\tname = ofType && elem.nodeName.toLowerCase(),\n\t\t\t\t\t\t\t\t\tuseCache = !xml && !ofType,\n\t\t\t\t\t\t\t\t\tdiff = false;\n\n\t\t\t\t\t\t\t\tif ( parent ) {\n\n\t\t\t\t\t\t\t\t\t// :(first|last|only)-(child|of-type)\n\t\t\t\t\t\t\t\t\tif ( simple ) {\n\t\t\t\t\t\t\t\t\t\twhile ( dir ) {\n\t\t\t\t\t\t\t\t\t\t\tnode = elem;\n\t\t\t\t\t\t\t\t\t\t\twhile ( (node = node[ dir ]) ) {\n\t\t\t\t\t\t\t\t\t\t\t\tif ( ofType ?\n\t\t\t\t\t\t\t\t\t\t\t\t\tnode.nodeName.toLowerCase() === name :\n\t\t\t\t\t\t\t\t\t\t\t\t\tnode.nodeType === 1 ) {\n\n\t\t\t\t\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\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\t\t\t\tstart = dir = type === \"only\" && !start && \"nextSibling\";\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tstart = [ forward ? parent.firstChild : parent.lastChild ];\n\n\t\t\t\t\t\t\t\t\t// non-xml :nth-child(...) stores cache data on `parent`\n\t\t\t\t\t\t\t\t\tif ( forward && useCache ) {\n\n\t\t\t\t\t\t\t\t\t\t// Seek `elem` from a previously-cached index\n\n\t\t\t\t\t\t\t\t\t\t// ...in a gzip-friendly way\n\t\t\t\t\t\t\t\t\t\tnode = parent;\n\t\t\t\t\t\t\t\t\t\touterCache = node[ expando ] || (node[ expando ] = {});\n\n\t\t\t\t\t\t\t\t\t\t// Support: IE <9 only\n\t\t\t\t\t\t\t\t\t\t// Defend against cloned attroperties (jQuery gh-1709)\n\t\t\t\t\t\t\t\t\t\tuniqueCache = outerCache[ node.uniqueID ] ||\n\t\t\t\t\t\t\t\t\t\t\t(outerCache[ node.uniqueID ] = {});\n\n\t\t\t\t\t\t\t\t\t\tcache = uniqueCache[ type ] || [];\n\t\t\t\t\t\t\t\t\t\tnodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];\n\t\t\t\t\t\t\t\t\t\tdiff = nodeIndex && cache[ 2 ];\n\t\t\t\t\t\t\t\t\t\tnode = nodeIndex && parent.childNodes[ nodeIndex ];\n\n\t\t\t\t\t\t\t\t\t\twhile ( (node = ++nodeIndex && node && node[ dir ] ||\n\n\t\t\t\t\t\t\t\t\t\t\t// Fallback to seeking `elem` from the start\n\t\t\t\t\t\t\t\t\t\t\t(diff = nodeIndex = 0) || start.pop()) ) {\n\n\t\t\t\t\t\t\t\t\t\t\t// When found, cache indexes on `parent` and break\n\t\t\t\t\t\t\t\t\t\t\tif ( node.nodeType === 1 && ++diff && node === elem ) {\n\t\t\t\t\t\t\t\t\t\t\t\tuniqueCache[ type ] = [ dirruns, nodeIndex, diff ];\n\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t// Use previously-cached element index if available\n\t\t\t\t\t\t\t\t\t\tif ( useCache ) {\n\t\t\t\t\t\t\t\t\t\t\t// ...in a gzip-friendly way\n\t\t\t\t\t\t\t\t\t\t\tnode = elem;\n\t\t\t\t\t\t\t\t\t\t\touterCache = node[ expando ] || (node[ expando ] = {});\n\n\t\t\t\t\t\t\t\t\t\t\t// Support: IE <9 only\n\t\t\t\t\t\t\t\t\t\t\t// Defend against cloned attroperties (jQuery gh-1709)\n\t\t\t\t\t\t\t\t\t\t\tuniqueCache = outerCache[ node.uniqueID ] ||\n\t\t\t\t\t\t\t\t\t\t\t\t(outerCache[ node.uniqueID ] = {});\n\n\t\t\t\t\t\t\t\t\t\t\tcache = uniqueCache[ type ] || [];\n\t\t\t\t\t\t\t\t\t\t\tnodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];\n\t\t\t\t\t\t\t\t\t\t\tdiff = nodeIndex;\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t// xml :nth-child(...)\n\t\t\t\t\t\t\t\t\t\t// or :nth-last-child(...) or :nth(-last)?-of-type(...)\n\t\t\t\t\t\t\t\t\t\tif ( diff === false ) {\n\t\t\t\t\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\t\t\t\t\twhile ( (node = ++nodeIndex && node && node[ dir ] ||\n\t\t\t\t\t\t\t\t\t\t\t\t(diff = nodeIndex = 0) || start.pop()) ) {\n\n\t\t\t\t\t\t\t\t\t\t\t\tif ( ( ofType ?\n\t\t\t\t\t\t\t\t\t\t\t\t\tnode.nodeName.toLowerCase() === name :\n\t\t\t\t\t\t\t\t\t\t\t\t\tnode.nodeType === 1 ) &&\n\t\t\t\t\t\t\t\t\t\t\t\t\t++diff ) {\n\n\t\t\t\t\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\t\t\t\t\tif ( useCache ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\touterCache = node[ expando ] || (node[ expando ] = {});\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Support: IE <9 only\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Defend against cloned attroperties (jQuery gh-1709)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tuniqueCache = outerCache[ node.uniqueID ] ||\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t(outerCache[ node.uniqueID ] = {});\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tuniqueCache[ type ] = [ dirruns, diff ];\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\tif ( node === elem ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t}\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}\n\n\t\t\t\t\t\t\t\t\t// Incorporate the offset, then check against cycle size\n\t\t\t\t\t\t\t\t\tdiff -= last;\n\t\t\t\t\t\t\t\t\treturn diff === first || ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t};\n\t\t\t\t\t},\n\n\t\t\t\t\t\"PSEUDO\": function( pseudo, argument ) {\n\t\t\t\t\t\t// pseudo-class names are case-insensitive\n\t\t\t\t\t\t// http://www.w3.org/TR/selectors/#pseudo-classes\n\t\t\t\t\t\t// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters\n\t\t\t\t\t\t// Remember that setFilters inherits from pseudos\n\t\t\t\t\t\tvar args,\n\t\t\t\t\t\t\tfn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||\n\t\t\t\t\t\t\t\tSizzle.error( \"unsupported pseudo: \" + pseudo );\n\n\t\t\t\t\t\t// The user may use createPseudo to indicate that\n\t\t\t\t\t\t// arguments are needed to create the filter function\n\t\t\t\t\t\t// just as Sizzle does\n\t\t\t\t\t\tif ( fn[ expando ] ) {\n\t\t\t\t\t\t\treturn fn( argument );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// But maintain support for old signatures\n\t\t\t\t\t\tif ( fn.length > 1 ) {\n\t\t\t\t\t\t\targs = [ pseudo, pseudo, \"\", argument ];\n\t\t\t\t\t\t\treturn Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?\n\t\t\t\t\t\t\t\tmarkFunction(function( seed, matches ) {\n\t\t\t\t\t\t\t\t\tvar idx,\n\t\t\t\t\t\t\t\t\t\tmatched = fn( seed, argument ),\n\t\t\t\t\t\t\t\t\t\ti = matched.length;\n\t\t\t\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\t\t\t\tidx = indexOf( seed, matched[i] );\n\t\t\t\t\t\t\t\t\t\tseed[ idx ] = !( matches[ idx ] = matched[i] );\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\tfunction( elem ) {\n\t\t\t\t\t\t\t\t\treturn fn( elem, 0, args );\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn fn;\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\tpseudos: {\n\t\t\t\t\t// Potentially complex pseudos\n\t\t\t\t\t\"not\": markFunction(function( selector ) {\n\t\t\t\t\t\t// Trim the selector passed to compile\n\t\t\t\t\t\t// to avoid treating leading and trailing\n\t\t\t\t\t\t// spaces as combinators\n\t\t\t\t\t\tvar input = [],\n\t\t\t\t\t\t\tresults = [],\n\t\t\t\t\t\t\tmatcher = compile( selector.replace( rtrim, \"$1\" ) );\n\n\t\t\t\t\t\treturn matcher[ expando ] ?\n\t\t\t\t\t\t\tmarkFunction(function( seed, matches, context, xml ) {\n\t\t\t\t\t\t\t\tvar elem,\n\t\t\t\t\t\t\t\t\tunmatched = matcher( seed, null, xml, [] ),\n\t\t\t\t\t\t\t\t\ti = seed.length;\n\n\t\t\t\t\t\t\t\t// Match elements unmatched by `matcher`\n\t\t\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\t\t\tif ( (elem = unmatched[i]) ) {\n\t\t\t\t\t\t\t\t\t\tseed[i] = !(matches[i] = elem);\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\tfunction( elem, context, xml ) {\n\t\t\t\t\t\t\t\tinput[0] = elem;\n\t\t\t\t\t\t\t\tmatcher( input, null, xml, results );\n\t\t\t\t\t\t\t\t// Don't keep the element (issue #299)\n\t\t\t\t\t\t\t\tinput[0] = null;\n\t\t\t\t\t\t\t\treturn !results.pop();\n\t\t\t\t\t\t\t};\n\t\t\t\t\t}),\n\n\t\t\t\t\t\"has\": markFunction(function( selector ) {\n\t\t\t\t\t\treturn function( elem ) {\n\t\t\t\t\t\t\treturn Sizzle( selector, elem ).length > 0;\n\t\t\t\t\t\t};\n\t\t\t\t\t}),\n\n\t\t\t\t\t\"contains\": markFunction(function( text ) {\n\t\t\t\t\t\ttext = text.replace( runescape, funescape );\n\t\t\t\t\t\treturn function( elem ) {\n\t\t\t\t\t\t\treturn ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;\n\t\t\t\t\t\t};\n\t\t\t\t\t}),\n\n\t\t\t\t\t// \"Whether an element is represented by a :lang() selector\n\t\t\t\t\t// is based solely on the element's language value\n\t\t\t\t\t// being equal to the identifier C,\n\t\t\t\t\t// or beginning with the identifier C immediately followed by \"-\".\n\t\t\t\t\t// The matching of C against the element's language value is performed case-insensitively.\n\t\t\t\t\t// The identifier C does not have to be a valid language name.\"\n\t\t\t\t\t// http://www.w3.org/TR/selectors/#lang-pseudo\n\t\t\t\t\t\"lang\": markFunction( function( lang ) {\n\t\t\t\t\t\t// lang value must be a valid identifier\n\t\t\t\t\t\tif ( !ridentifier.test(lang || \"\") ) {\n\t\t\t\t\t\t\tSizzle.error( \"unsupported lang: \" + lang );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tlang = lang.replace( runescape, funescape ).toLowerCase();\n\t\t\t\t\t\treturn function( elem ) {\n\t\t\t\t\t\t\tvar elemLang;\n\t\t\t\t\t\t\tdo {\n\t\t\t\t\t\t\t\tif ( (elemLang = documentIsHTML ?\n\t\t\t\t\t\t\t\t\t\telem.lang :\n\t\t\t\t\t\t\t\t\telem.getAttribute(\"xml:lang\") || elem.getAttribute(\"lang\")) ) {\n\n\t\t\t\t\t\t\t\t\telemLang = elemLang.toLowerCase();\n\t\t\t\t\t\t\t\t\treturn elemLang === lang || elemLang.indexOf( lang + \"-\" ) === 0;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} while ( (elem = elem.parentNode) && elem.nodeType === 1 );\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t};\n\t\t\t\t\t}),\n\n\t\t\t\t\t// Miscellaneous\n\t\t\t\t\t\"target\": function( elem ) {\n\t\t\t\t\t\tvar hash = window.location && window.location.hash;\n\t\t\t\t\t\treturn hash && hash.slice( 1 ) === elem.id;\n\t\t\t\t\t},\n\n\t\t\t\t\t\"root\": function( elem ) {\n\t\t\t\t\t\treturn elem === docElem;\n\t\t\t\t\t},\n\n\t\t\t\t\t\"focus\": function( elem ) {\n\t\t\t\t\t\treturn elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);\n\t\t\t\t\t},\n\n\t\t\t\t\t// Boolean properties\n\t\t\t\t\t\"enabled\": createDisabledPseudo( false ),\n\t\t\t\t\t\"disabled\": createDisabledPseudo( true ),\n\n\t\t\t\t\t\"checked\": function( elem ) {\n\t\t\t\t\t\t// In CSS3, :checked should return both checked and selected elements\n\t\t\t\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\t\t\t\tvar nodeName = elem.nodeName.toLowerCase();\n\t\t\t\t\t\treturn (nodeName === \"input\" && !!elem.checked) || (nodeName === \"option\" && !!elem.selected);\n\t\t\t\t\t},\n\n\t\t\t\t\t\"selected\": function( elem ) {\n\t\t\t\t\t\t// Accessing this property makes selected-by-default\n\t\t\t\t\t\t// options in Safari work properly\n\t\t\t\t\t\tif ( elem.parentNode ) {\n\t\t\t\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn elem.selected === true;\n\t\t\t\t\t},\n\n\t\t\t\t\t// Contents\n\t\t\t\t\t\"empty\": function( elem ) {\n\t\t\t\t\t\t// http://www.w3.org/TR/selectors/#empty-pseudo\n\t\t\t\t\t\t// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),\n\t\t\t\t\t\t//   but not by others (comment: 8; processing instruction: 7; etc.)\n\t\t\t\t\t\t// nodeType < 6 works because attributes (2) do not appear as children\n\t\t\t\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\t\t\t\tif ( elem.nodeType < 6 ) {\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\treturn true;\n\t\t\t\t\t},\n\n\t\t\t\t\t\"parent\": function( elem ) {\n\t\t\t\t\t\treturn !Expr.pseudos[\"empty\"]( elem );\n\t\t\t\t\t},\n\n\t\t\t\t\t// Element/input types\n\t\t\t\t\t\"header\": function( elem ) {\n\t\t\t\t\t\treturn rheader.test( elem.nodeName );\n\t\t\t\t\t},\n\n\t\t\t\t\t\"input\": function( elem ) {\n\t\t\t\t\t\treturn rinputs.test( elem.nodeName );\n\t\t\t\t\t},\n\n\t\t\t\t\t\"button\": function( elem ) {\n\t\t\t\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\t\t\t\treturn name === \"input\" && elem.type === \"button\" || name === \"button\";\n\t\t\t\t\t},\n\n\t\t\t\t\t\"text\": function( elem ) {\n\t\t\t\t\t\tvar attr;\n\t\t\t\t\t\treturn elem.nodeName.toLowerCase() === \"input\" &&\n\t\t\t\t\t\t\telem.type === \"text\" &&\n\n\t\t\t\t\t\t\t// Support: IE<8\n\t\t\t\t\t\t\t// New HTML5 attribute values (e.g., \"search\") appear with elem.type === \"text\"\n\t\t\t\t\t\t\t( (attr = elem.getAttribute(\"type\")) == null || attr.toLowerCase() === \"text\" );\n\t\t\t\t\t},\n\n\t\t\t\t\t// Position-in-collection\n\t\t\t\t\t\"first\": createPositionalPseudo(function() {\n\t\t\t\t\t\treturn [ 0 ];\n\t\t\t\t\t}),\n\n\t\t\t\t\t\"last\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\t\t\t\treturn [ length - 1 ];\n\t\t\t\t\t}),\n\n\t\t\t\t\t\"eq\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\t\t\t\treturn [ argument < 0 ? argument + length : argument ];\n\t\t\t\t\t}),\n\n\t\t\t\t\t\"even\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\t\t\t\tvar i = 0;\n\t\t\t\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\t\t\t\tmatchIndexes.push( i );\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn matchIndexes;\n\t\t\t\t\t}),\n\n\t\t\t\t\t\"odd\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\t\t\t\tvar i = 1;\n\t\t\t\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\t\t\t\tmatchIndexes.push( i );\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn matchIndexes;\n\t\t\t\t\t}),\n\n\t\t\t\t\t\"lt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\t\t\t\tvar i = argument < 0 ? argument + length : argument;\n\t\t\t\t\t\tfor ( ; --i >= 0; ) {\n\t\t\t\t\t\t\tmatchIndexes.push( i );\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn matchIndexes;\n\t\t\t\t\t}),\n\n\t\t\t\t\t\"gt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\t\t\t\tvar i = argument < 0 ? argument + length : argument;\n\t\t\t\t\t\tfor ( ; ++i < length; ) {\n\t\t\t\t\t\t\tmatchIndexes.push( i );\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn matchIndexes;\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tExpr.pseudos[\"nth\"] = Expr.pseudos[\"eq\"];\n\n// Add button/input type pseudos\n\t\t\tfor ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {\n\t\t\t\tExpr.pseudos[ i ] = createInputPseudo( i );\n\t\t\t}\n\t\t\tfor ( i in { submit: true, reset: true } ) {\n\t\t\t\tExpr.pseudos[ i ] = createButtonPseudo( i );\n\t\t\t}\n\n// Easy API for creating new setFilters\n\t\t\tfunction setFilters() {}\n\t\t\tsetFilters.prototype = Expr.filters = Expr.pseudos;\n\t\t\tExpr.setFilters = new setFilters();\n\n\t\t\ttokenize = Sizzle.tokenize = function( selector, parseOnly ) {\n\t\t\t\tvar matched, match, tokens, type,\n\t\t\t\t\tsoFar, groups, preFilters,\n\t\t\t\t\tcached = tokenCache[ selector + \" \" ];\n\n\t\t\t\tif ( cached ) {\n\t\t\t\t\treturn parseOnly ? 0 : cached.slice( 0 );\n\t\t\t\t}\n\n\t\t\t\tsoFar = selector;\n\t\t\t\tgroups = [];\n\t\t\t\tpreFilters = Expr.preFilter;\n\n\t\t\t\twhile ( soFar ) {\n\n\t\t\t\t\t// Comma and first run\n\t\t\t\t\tif ( !matched || (match = rcomma.exec( soFar )) ) {\n\t\t\t\t\t\tif ( match ) {\n\t\t\t\t\t\t\t// Don't consume trailing commas as valid\n\t\t\t\t\t\t\tsoFar = soFar.slice( match[0].length ) || soFar;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tgroups.push( (tokens = []) );\n\t\t\t\t\t}\n\n\t\t\t\t\tmatched = false;\n\n\t\t\t\t\t// Combinators\n\t\t\t\t\tif ( (match = rcombinators.exec( soFar )) ) {\n\t\t\t\t\t\tmatched = match.shift();\n\t\t\t\t\t\ttokens.push({\n\t\t\t\t\t\t\tvalue: matched,\n\t\t\t\t\t\t\t// Cast descendant combinators to space\n\t\t\t\t\t\t\ttype: match[0].replace( rtrim, \" \" )\n\t\t\t\t\t\t});\n\t\t\t\t\t\tsoFar = soFar.slice( matched.length );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Filters\n\t\t\t\t\tfor ( type in Expr.filter ) {\n\t\t\t\t\t\tif ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||\n\t\t\t\t\t\t\t(match = preFilters[ type ]( match ))) ) {\n\t\t\t\t\t\t\tmatched = match.shift();\n\t\t\t\t\t\t\ttokens.push({\n\t\t\t\t\t\t\t\tvalue: matched,\n\t\t\t\t\t\t\t\ttype: type,\n\t\t\t\t\t\t\t\tmatches: match\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tsoFar = soFar.slice( matched.length );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( !matched ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Return the length of the invalid excess\n\t\t\t\t// if we're just parsing\n\t\t\t\t// Otherwise, throw an error or return tokens\n\t\t\t\treturn parseOnly ?\n\t\t\t\t\tsoFar.length :\n\t\t\t\t\tsoFar ?\n\t\t\t\t\t\tSizzle.error( selector ) :\n\t\t\t\t\t\t// Cache the tokens\n\t\t\t\t\t\ttokenCache( selector, groups ).slice( 0 );\n\t\t\t};\n\n\t\t\tfunction toSelector( tokens ) {\n\t\t\t\tvar i = 0,\n\t\t\t\t\tlen = tokens.length,\n\t\t\t\t\tselector = \"\";\n\t\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t\tselector += tokens[i].value;\n\t\t\t\t}\n\t\t\t\treturn selector;\n\t\t\t}\n\n\t\t\tfunction addCombinator( matcher, combinator, base ) {\n\t\t\t\tvar dir = combinator.dir,\n\t\t\t\t\tskip = combinator.next,\n\t\t\t\t\tkey = skip || dir,\n\t\t\t\t\tcheckNonElements = base && key === \"parentNode\",\n\t\t\t\t\tdoneName = done++;\n\n\t\t\t\treturn combinator.first ?\n\t\t\t\t\t// Check against closest ancestor/preceding element\n\t\t\t\t\tfunction( elem, context, xml ) {\n\t\t\t\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\t\t\treturn matcher( elem, context, xml );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t} :\n\n\t\t\t\t\t// Check against all ancestor/preceding elements\n\t\t\t\t\tfunction( elem, context, xml ) {\n\t\t\t\t\t\tvar oldCache, uniqueCache, outerCache,\n\t\t\t\t\t\t\tnewCache = [ dirruns, doneName ];\n\n\t\t\t\t\t\t// We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching\n\t\t\t\t\t\tif ( xml ) {\n\t\t\t\t\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\t\t\t\tif ( matcher( elem, context, xml ) ) {\n\t\t\t\t\t\t\t\t\t\treturn true;\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\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\t\t\t\touterCache = elem[ expando ] || (elem[ expando ] = {});\n\n\t\t\t\t\t\t\t\t\t// Support: IE <9 only\n\t\t\t\t\t\t\t\t\t// Defend against cloned attroperties (jQuery gh-1709)\n\t\t\t\t\t\t\t\t\tuniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {});\n\n\t\t\t\t\t\t\t\t\tif ( skip && skip === elem.nodeName.toLowerCase() ) {\n\t\t\t\t\t\t\t\t\t\telem = elem[ dir ] || elem;\n\t\t\t\t\t\t\t\t\t} else if ( (oldCache = uniqueCache[ key ]) &&\n\t\t\t\t\t\t\t\t\t\toldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {\n\n\t\t\t\t\t\t\t\t\t\t// Assign to newCache so results back-propagate to previous elements\n\t\t\t\t\t\t\t\t\t\treturn (newCache[ 2 ] = oldCache[ 2 ]);\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t// Reuse newcache so results back-propagate to previous elements\n\t\t\t\t\t\t\t\t\t\tuniqueCache[ key ] = newCache;\n\n\t\t\t\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\t\t\t\tif ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {\n\t\t\t\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t\t\t\t}\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\treturn false;\n\t\t\t\t\t};\n\t\t\t}\n\n\t\t\tfunction elementMatcher( matchers ) {\n\t\t\t\treturn matchers.length > 1 ?\n\t\t\t\t\tfunction( elem, context, xml ) {\n\t\t\t\t\t\tvar i = matchers.length;\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tif ( !matchers[i]( elem, context, xml ) ) {\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\treturn true;\n\t\t\t\t\t} :\n\t\t\t\t\tmatchers[0];\n\t\t\t}\n\n\t\t\tfunction multipleContexts( selector, contexts, results ) {\n\t\t\t\tvar i = 0,\n\t\t\t\t\tlen = contexts.length;\n\t\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t\tSizzle( selector, contexts[i], results );\n\t\t\t\t}\n\t\t\t\treturn results;\n\t\t\t}\n\n\t\t\tfunction condense( unmatched, map, filter, context, xml ) {\n\t\t\t\tvar elem,\n\t\t\t\t\tnewUnmatched = [],\n\t\t\t\t\ti = 0,\n\t\t\t\t\tlen = unmatched.length,\n\t\t\t\t\tmapped = map != null;\n\n\t\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t\tif ( (elem = unmatched[i]) ) {\n\t\t\t\t\t\tif ( !filter || filter( elem, context, xml ) ) {\n\t\t\t\t\t\t\tnewUnmatched.push( elem );\n\t\t\t\t\t\t\tif ( mapped ) {\n\t\t\t\t\t\t\t\tmap.push( i );\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\treturn newUnmatched;\n\t\t\t}\n\n\t\t\tfunction setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {\n\t\t\t\tif ( postFilter && !postFilter[ expando ] ) {\n\t\t\t\t\tpostFilter = setMatcher( postFilter );\n\t\t\t\t}\n\t\t\t\tif ( postFinder && !postFinder[ expando ] ) {\n\t\t\t\t\tpostFinder = setMatcher( postFinder, postSelector );\n\t\t\t\t}\n\t\t\t\treturn markFunction(function( seed, results, context, xml ) {\n\t\t\t\t\tvar temp, i, elem,\n\t\t\t\t\t\tpreMap = [],\n\t\t\t\t\t\tpostMap = [],\n\t\t\t\t\t\tpreexisting = results.length,\n\n\t\t\t\t\t\t// Get initial elements from seed or context\n\t\t\t\t\t\telems = seed || multipleContexts( selector || \"*\", context.nodeType ? [ context ] : context, [] ),\n\n\t\t\t\t\t\t// Prefilter to get matcher input, preserving a map for seed-results synchronization\n\t\t\t\t\t\tmatcherIn = preFilter && ( seed || !selector ) ?\n\t\t\t\t\t\t\tcondense( elems, preMap, preFilter, context, xml ) :\n\t\t\t\t\t\t\telems,\n\n\t\t\t\t\t\tmatcherOut = matcher ?\n\t\t\t\t\t\t\t// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,\n\t\t\t\t\t\t\tpostFinder || ( seed ? preFilter : preexisting || postFilter ) ?\n\n\t\t\t\t\t\t\t\t// ...intermediate processing is necessary\n\t\t\t\t\t\t\t\t[] :\n\n\t\t\t\t\t\t\t\t// ...otherwise use results directly\n\t\t\t\t\t\t\t\tresults :\n\t\t\t\t\t\t\tmatcherIn;\n\n\t\t\t\t\t// Find primary matches\n\t\t\t\t\tif ( matcher ) {\n\t\t\t\t\t\tmatcher( matcherIn, matcherOut, context, xml );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Apply postFilter\n\t\t\t\t\tif ( postFilter ) {\n\t\t\t\t\t\ttemp = condense( matcherOut, postMap );\n\t\t\t\t\t\tpostFilter( temp, [], context, xml );\n\n\t\t\t\t\t\t// Un-match failing elements by moving them back to matcherIn\n\t\t\t\t\t\ti = temp.length;\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tif ( (elem = temp[i]) ) {\n\t\t\t\t\t\t\t\tmatcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);\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 ( seed ) {\n\t\t\t\t\t\tif ( postFinder || preFilter ) {\n\t\t\t\t\t\t\tif ( postFinder ) {\n\t\t\t\t\t\t\t\t// Get the final matcherOut by condensing this intermediate into postFinder contexts\n\t\t\t\t\t\t\t\ttemp = [];\n\t\t\t\t\t\t\t\ti = matcherOut.length;\n\t\t\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\t\t\tif ( (elem = matcherOut[i]) ) {\n\t\t\t\t\t\t\t\t\t\t// Restore matcherIn since elem is not yet a final match\n\t\t\t\t\t\t\t\t\t\ttemp.push( (matcherIn[i] = elem) );\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\tpostFinder( null, (matcherOut = []), temp, xml );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Move matched elements from seed to results to keep them synchronized\n\t\t\t\t\t\t\ti = matcherOut.length;\n\t\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\t\tif ( (elem = matcherOut[i]) &&\n\t\t\t\t\t\t\t\t\t(temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {\n\n\t\t\t\t\t\t\t\t\tseed[temp] = !(results[temp] = elem);\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// Add elements to results, through postFinder if defined\n\t\t\t\t\t} else {\n\t\t\t\t\t\tmatcherOut = condense(\n\t\t\t\t\t\t\tmatcherOut === results ?\n\t\t\t\t\t\t\t\tmatcherOut.splice( preexisting, matcherOut.length ) :\n\t\t\t\t\t\t\t\tmatcherOut\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif ( postFinder ) {\n\t\t\t\t\t\t\tpostFinder( null, results, matcherOut, xml );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tpush.apply( results, matcherOut );\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 matcherFromTokens( tokens ) {\n\t\t\t\tvar checkContext, matcher, j,\n\t\t\t\t\tlen = tokens.length,\n\t\t\t\t\tleadingRelative = Expr.relative[ tokens[0].type ],\n\t\t\t\t\timplicitRelative = leadingRelative || Expr.relative[\" \"],\n\t\t\t\t\ti = leadingRelative ? 1 : 0,\n\n\t\t\t\t\t// The foundational matcher ensures that elements are reachable from top-level context(s)\n\t\t\t\t\tmatchContext = addCombinator( function( elem ) {\n\t\t\t\t\t\treturn elem === checkContext;\n\t\t\t\t\t}, implicitRelative, true ),\n\t\t\t\t\tmatchAnyContext = addCombinator( function( elem ) {\n\t\t\t\t\t\treturn indexOf( checkContext, elem ) > -1;\n\t\t\t\t\t}, implicitRelative, true ),\n\t\t\t\t\tmatchers = [ function( elem, context, xml ) {\n\t\t\t\t\t\tvar ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (\n\t\t\t\t\t\t\t\t(checkContext = context).nodeType ?\n\t\t\t\t\t\t\t\t\tmatchContext( elem, context, xml ) :\n\t\t\t\t\t\t\t\t\tmatchAnyContext( elem, context, xml ) );\n\t\t\t\t\t\t// Avoid hanging onto element (issue #299)\n\t\t\t\t\t\tcheckContext = null;\n\t\t\t\t\t\treturn ret;\n\t\t\t\t\t} ];\n\n\t\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t\tif ( (matcher = Expr.relative[ tokens[i].type ]) ) {\n\t\t\t\t\t\tmatchers = [ addCombinator(elementMatcher( matchers ), matcher) ];\n\t\t\t\t\t} else {\n\t\t\t\t\t\tmatcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );\n\n\t\t\t\t\t\t// Return special upon seeing a positional matcher\n\t\t\t\t\t\tif ( matcher[ expando ] ) {\n\t\t\t\t\t\t\t// Find the next relative operator (if any) for proper handling\n\t\t\t\t\t\t\tj = ++i;\n\t\t\t\t\t\t\tfor ( ; j < len; j++ ) {\n\t\t\t\t\t\t\t\tif ( Expr.relative[ tokens[j].type ] ) {\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\t\t\t\t\t\t\treturn setMatcher(\n\t\t\t\t\t\t\t\ti > 1 && elementMatcher( matchers ),\n\t\t\t\t\t\t\t\ti > 1 && toSelector(\n\t\t\t\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\t\t\t\ttokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === \" \" ? \"*\" : \"\" })\n\t\t\t\t\t\t\t\t).replace( rtrim, \"$1\" ),\n\t\t\t\t\t\t\t\tmatcher,\n\t\t\t\t\t\t\t\ti < j && matcherFromTokens( tokens.slice( i, j ) ),\n\t\t\t\t\t\t\t\tj < len && matcherFromTokens( (tokens = tokens.slice( j )) ),\n\t\t\t\t\t\t\t\tj < len && toSelector( tokens )\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmatchers.push( matcher );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn elementMatcher( matchers );\n\t\t\t}\n\n\t\t\tfunction matcherFromGroupMatchers( elementMatchers, setMatchers ) {\n\t\t\t\tvar bySet = setMatchers.length > 0,\n\t\t\t\t\tbyElement = elementMatchers.length > 0,\n\t\t\t\t\tsuperMatcher = function( seed, context, xml, results, outermost ) {\n\t\t\t\t\t\tvar elem, j, matcher,\n\t\t\t\t\t\t\tmatchedCount = 0,\n\t\t\t\t\t\t\ti = \"0\",\n\t\t\t\t\t\t\tunmatched = seed && [],\n\t\t\t\t\t\t\tsetMatched = [],\n\t\t\t\t\t\t\tcontextBackup = outermostContext,\n\t\t\t\t\t\t\t// We must always have either seed elements or outermost context\n\t\t\t\t\t\t\telems = seed || byElement && Expr.find[\"TAG\"]( \"*\", outermost ),\n\t\t\t\t\t\t\t// Use integer dirruns iff this is the outermost matcher\n\t\t\t\t\t\t\tdirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),\n\t\t\t\t\t\t\tlen = elems.length;\n\n\t\t\t\t\t\tif ( outermost ) {\n\t\t\t\t\t\t\toutermostContext = context === document || context || outermost;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Add elements passing elementMatchers directly to results\n\t\t\t\t\t\t// Support: IE<9, Safari\n\t\t\t\t\t\t// Tolerate NodeList properties (IE: \"length\"; Safari: <number>) matching elements by id\n\t\t\t\t\t\tfor ( ; i !== len && (elem = elems[i]) != null; i++ ) {\n\t\t\t\t\t\t\tif ( byElement && elem ) {\n\t\t\t\t\t\t\t\tj = 0;\n\t\t\t\t\t\t\t\tif ( !context && elem.ownerDocument !== document ) {\n\t\t\t\t\t\t\t\t\tsetDocument( elem );\n\t\t\t\t\t\t\t\t\txml = !documentIsHTML;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\twhile ( (matcher = elementMatchers[j++]) ) {\n\t\t\t\t\t\t\t\t\tif ( matcher( elem, context || document, xml) ) {\n\t\t\t\t\t\t\t\t\t\tresults.push( 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\tif ( outermost ) {\n\t\t\t\t\t\t\t\t\tdirruns = dirrunsUnique;\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\t// Track unmatched elements for set filters\n\t\t\t\t\t\t\tif ( bySet ) {\n\t\t\t\t\t\t\t\t// They will have gone through all possible matchers\n\t\t\t\t\t\t\t\tif ( (elem = !matcher && elem) ) {\n\t\t\t\t\t\t\t\t\tmatchedCount--;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// Lengthen the array for every element, matched or not\n\t\t\t\t\t\t\t\tif ( seed ) {\n\t\t\t\t\t\t\t\t\tunmatched.push( elem );\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// `i` is now the count of elements visited above, and adding it to `matchedCount`\n\t\t\t\t\t\t// makes the latter nonnegative.\n\t\t\t\t\t\tmatchedCount += i;\n\n\t\t\t\t\t\t// Apply set filters to unmatched elements\n\t\t\t\t\t\t// NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`\n\t\t\t\t\t\t// equals `i`), unless we didn't visit _any_ elements in the above loop because we have\n\t\t\t\t\t\t// no element matchers and no seed.\n\t\t\t\t\t\t// Incrementing an initially-string \"0\" `i` allows `i` to remain a string only in that\n\t\t\t\t\t\t// case, which will result in a \"00\" `matchedCount` that differs from `i` but is also\n\t\t\t\t\t\t// numerically zero.\n\t\t\t\t\t\tif ( bySet && i !== matchedCount ) {\n\t\t\t\t\t\t\tj = 0;\n\t\t\t\t\t\t\twhile ( (matcher = setMatchers[j++]) ) {\n\t\t\t\t\t\t\t\tmatcher( unmatched, setMatched, context, xml );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif ( seed ) {\n\t\t\t\t\t\t\t\t// Reintegrate element matches to eliminate the need for sorting\n\t\t\t\t\t\t\t\tif ( matchedCount > 0 ) {\n\t\t\t\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\t\t\t\tif ( !(unmatched[i] || setMatched[i]) ) {\n\t\t\t\t\t\t\t\t\t\t\tsetMatched[i] = pop.call( results );\n\t\t\t\t\t\t\t\t\t\t}\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// Discard index placeholder values to get only actual matches\n\t\t\t\t\t\t\t\tsetMatched = condense( setMatched );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Add matches to results\n\t\t\t\t\t\t\tpush.apply( results, setMatched );\n\n\t\t\t\t\t\t\t// Seedless set matches succeeding multiple successful matchers stipulate sorting\n\t\t\t\t\t\t\tif ( outermost && !seed && setMatched.length > 0 &&\n\t\t\t\t\t\t\t\t( matchedCount + setMatchers.length ) > 1 ) {\n\n\t\t\t\t\t\t\t\tSizzle.uniqueSort( results );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Override manipulation of globals by nested matchers\n\t\t\t\t\t\tif ( outermost ) {\n\t\t\t\t\t\t\tdirruns = dirrunsUnique;\n\t\t\t\t\t\t\toutermostContext = contextBackup;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn unmatched;\n\t\t\t\t\t};\n\n\t\t\t\treturn bySet ?\n\t\t\t\t\tmarkFunction( superMatcher ) :\n\t\t\t\t\tsuperMatcher;\n\t\t\t}\n\n\t\t\tcompile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {\n\t\t\t\tvar i,\n\t\t\t\t\tsetMatchers = [],\n\t\t\t\t\telementMatchers = [],\n\t\t\t\t\tcached = compilerCache[ selector + \" \" ];\n\n\t\t\t\tif ( !cached ) {\n\t\t\t\t\t// Generate a function of recursive functions that can be used to check each element\n\t\t\t\t\tif ( !match ) {\n\t\t\t\t\t\tmatch = tokenize( selector );\n\t\t\t\t\t}\n\t\t\t\t\ti = match.length;\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tcached = matcherFromTokens( match[i] );\n\t\t\t\t\t\tif ( cached[ expando ] ) {\n\t\t\t\t\t\t\tsetMatchers.push( cached );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\telementMatchers.push( cached );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Cache the compiled function\n\t\t\t\t\tcached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );\n\n\t\t\t\t\t// Save selector and tokenization\n\t\t\t\t\tcached.selector = selector;\n\t\t\t\t}\n\t\t\t\treturn cached;\n\t\t\t};\n\n\t\t\t/**\n\t\t\t * A low-level selection function that works with Sizzle's compiled\n\t\t\t *  selector functions\n\t\t\t * @param {String|Function} selector A selector or a pre-compiled\n\t\t\t *  selector function built with Sizzle.compile\n\t\t\t * @param {Element} context\n\t\t\t * @param {Array} [results]\n\t\t\t * @param {Array} [seed] A set of elements to match against\n\t\t\t */\n\t\t\tselect = Sizzle.select = function( selector, context, results, seed ) {\n\t\t\t\tvar i, tokens, token, type, find,\n\t\t\t\t\tcompiled = typeof selector === \"function\" && selector,\n\t\t\t\t\tmatch = !seed && tokenize( (selector = compiled.selector || selector) );\n\n\t\t\t\tresults = results || [];\n\n\t\t\t\t// Try to minimize operations if there is only one selector in the list and no seed\n\t\t\t\t// (the latter of which guarantees us context)\n\t\t\t\tif ( match.length === 1 ) {\n\n\t\t\t\t\t// Reduce context if the leading compound selector is an ID\n\t\t\t\t\ttokens = match[0] = match[0].slice( 0 );\n\t\t\t\t\tif ( tokens.length > 2 && (token = tokens[0]).type === \"ID\" &&\n\t\t\t\t\t\tcontext.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[1].type ] ) {\n\n\t\t\t\t\t\tcontext = ( Expr.find[\"ID\"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];\n\t\t\t\t\t\tif ( !context ) {\n\t\t\t\t\t\t\treturn results;\n\n\t\t\t\t\t\t\t// Precompiled matchers will still verify ancestry, so step up a level\n\t\t\t\t\t\t} else if ( compiled ) {\n\t\t\t\t\t\t\tcontext = context.parentNode;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tselector = selector.slice( tokens.shift().value.length );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Fetch a seed set for right-to-left matching\n\t\t\t\t\ti = matchExpr[\"needsContext\"].test( selector ) ? 0 : tokens.length;\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\ttoken = tokens[i];\n\n\t\t\t\t\t\t// Abort if we hit a combinator\n\t\t\t\t\t\tif ( Expr.relative[ (type = token.type) ] ) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( (find = Expr.find[ type ]) ) {\n\t\t\t\t\t\t\t// Search, expanding context for leading sibling combinators\n\t\t\t\t\t\t\tif ( (seed = find(\n\t\t\t\t\t\t\t\t\ttoken.matches[0].replace( runescape, funescape ),\n\t\t\t\t\t\t\t\t\trsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context\n\t\t\t\t\t\t\t\t)) ) {\n\n\t\t\t\t\t\t\t\t// If seed is empty or no tokens remain, we can return early\n\t\t\t\t\t\t\t\ttokens.splice( i, 1 );\n\t\t\t\t\t\t\t\tselector = seed.length && toSelector( tokens );\n\t\t\t\t\t\t\t\tif ( !selector ) {\n\t\t\t\t\t\t\t\t\tpush.apply( results, seed );\n\t\t\t\t\t\t\t\t\treturn results;\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// Compile and execute a filtering function if one is not provided\n\t\t\t\t// Provide `match` to avoid retokenization if we modified the selector above\n\t\t\t\t( compiled || compile( selector, match ) )(\n\t\t\t\t\tseed,\n\t\t\t\t\tcontext,\n\t\t\t\t\t!documentIsHTML,\n\t\t\t\t\tresults,\n\t\t\t\t\t!context || rsibling.test( selector ) && testContext( context.parentNode ) || context\n\t\t\t\t);\n\t\t\t\treturn results;\n\t\t\t};\n\n// One-time assignments\n\n// Sort stability\n\t\t\tsupport.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\n\t\t\tsupport.detectDuplicates = !!hasDuplicate;\n\n// Initialize against the default document\n\t\t\tsetDocument();\n\n// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)\n// Detached nodes confoundingly follow *each other*\n\t\t\tsupport.sortDetached = assert(function( el ) {\n\t\t\t\t// Should return 1, but returns 4 (following)\n\t\t\t\treturn el.compareDocumentPosition( document.createElement(\"fieldset\") ) & 1;\n\t\t\t});\n\n// Support: IE<8\n// Prevent attribute/property \"interpolation\"\n// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx\n\t\t\tif ( !assert(function( el ) {\n\t\t\t\t\tel.innerHTML = \"<a href='#'></a>\";\n\t\t\t\t\treturn el.firstChild.getAttribute(\"href\") === \"#\" ;\n\t\t\t\t}) ) {\n\t\t\t\taddHandle( \"type|href|height|width\", function( elem, name, isXML ) {\n\t\t\t\t\tif ( !isXML ) {\n\t\t\t\t\t\treturn elem.getAttribute( name, name.toLowerCase() === \"type\" ? 1 : 2 );\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n// Support: IE<9\n// Use defaultValue in place of getAttribute(\"value\")\n\t\t\tif ( !support.attributes || !assert(function( el ) {\n\t\t\t\t\tel.innerHTML = \"<input/>\";\n\t\t\t\t\tel.firstChild.setAttribute( \"value\", \"\" );\n\t\t\t\t\treturn el.firstChild.getAttribute( \"value\" ) === \"\";\n\t\t\t\t}) ) {\n\t\t\t\taddHandle( \"value\", function( elem, name, isXML ) {\n\t\t\t\t\tif ( !isXML && elem.nodeName.toLowerCase() === \"input\" ) {\n\t\t\t\t\t\treturn elem.defaultValue;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n// Support: IE<9\n// Use getAttributeNode to fetch booleans when getAttribute lies\n\t\t\tif ( !assert(function( el ) {\n\t\t\t\t\treturn el.getAttribute(\"disabled\") == null;\n\t\t\t\t}) ) {\n\t\t\t\taddHandle( booleans, function( elem, name, isXML ) {\n\t\t\t\t\tvar val;\n\t\t\t\t\tif ( !isXML ) {\n\t\t\t\t\t\treturn elem[ name ] === true ? name.toLowerCase() :\n\t\t\t\t\t\t\t(val = elem.getAttributeNode( name )) && val.specified ?\n\t\t\t\t\t\t\t\tval.value :\n\t\t\t\t\t\t\t\tnull;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn Sizzle;\n\n\t\t})( window );\n\n\n\n\tjQuery.find = Sizzle;\n\tjQuery.expr = Sizzle.selectors;\n\n// Deprecated\n\tjQuery.expr[ \":\" ] = jQuery.expr.pseudos;\n\tjQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort;\n\tjQuery.text = Sizzle.getText;\n\tjQuery.isXMLDoc = Sizzle.isXML;\n\tjQuery.contains = Sizzle.contains;\n\tjQuery.escapeSelector = Sizzle.escape;\n\n\n\n\n\tvar dir = 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\n\tvar siblings = 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\n\tvar rneedsContext = jQuery.expr.match.needsContext;\n\n\n\n\tfunction nodeName( elem, name ) {\n\n\t\treturn elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();\n\n\t};\n\tvar rsingleTag = ( /^<([a-z][^\\/\\0>:\\x20\\t\\r\\n\\f]*)[\\x20\\t\\r\\n\\f]*\\/?>(?:<\\/\\1>|)$/i );\n\n\n\n\tvar risSimple = /^.[^:#\\[\\.,]*$/;\n\n// Implement the identical functionality for filter and not\n\tfunction winnow( elements, qualifier, not ) {\n\t\tif ( jQuery.isFunction( qualifier ) ) {\n\t\t\treturn jQuery.grep( elements, function( elem, i ) {\n\t\t\t\treturn !!qualifier.call( elem, i, elem ) !== not;\n\t\t\t} );\n\t\t}\n\n\t\t// Single element\n\t\tif ( qualifier.nodeType ) {\n\t\t\treturn jQuery.grep( elements, function( elem ) {\n\t\t\t\treturn ( elem === qualifier ) !== not;\n\t\t\t} );\n\t\t}\n\n\t\t// Arraylike of elements (jQuery, arguments, Array)\n\t\tif ( typeof qualifier !== \"string\" ) {\n\t\t\treturn jQuery.grep( elements, function( elem ) {\n\t\t\t\treturn ( indexOf.call( qualifier, elem ) > -1 ) !== not;\n\t\t\t} );\n\t\t}\n\n\t\t// Simple selector that can be filtered directly, removing non-Elements\n\t\tif ( risSimple.test( qualifier ) ) {\n\t\t\treturn jQuery.filter( qualifier, elements, not );\n\t\t}\n\n\t\t// Complex selector, compare the two sets, removing non-Elements\n\t\tqualifier = jQuery.filter( qualifier, elements );\n\t\treturn jQuery.grep( elements, function( elem ) {\n\t\t\treturn ( indexOf.call( qualifier, elem ) > -1 ) !== not && elem.nodeType === 1;\n\t\t} );\n\t}\n\n\tjQuery.filter = function( expr, elems, not ) {\n\t\tvar elem = elems[ 0 ];\n\n\t\tif ( not ) {\n\t\t\texpr = \":not(\" + expr + \")\";\n\t\t}\n\n\t\tif ( elems.length === 1 && elem.nodeType === 1 ) {\n\t\t\treturn jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [];\n\t\t}\n\n\t\treturn jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {\n\t\t\treturn elem.nodeType === 1;\n\t\t} ) );\n\t};\n\n\tjQuery.fn.extend( {\n\t\tfind: function( selector ) {\n\t\t\tvar i, ret,\n\t\t\t\tlen = this.length,\n\t\t\t\tself = this;\n\n\t\t\tif ( typeof selector !== \"string\" ) {\n\t\t\t\treturn this.pushStack( jQuery( selector ).filter( function() {\n\t\t\t\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\t\t\t\tif ( jQuery.contains( self[ i ], this ) ) {\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}\n\n\t\t\tret = this.pushStack( [] );\n\n\t\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\t\tjQuery.find( selector, self[ i ], ret );\n\t\t\t}\n\n\t\t\treturn len > 1 ? jQuery.uniqueSort( ret ) : ret;\n\t\t},\n\t\tfilter: function( selector ) {\n\t\t\treturn this.pushStack( winnow( this, selector || [], false ) );\n\t\t},\n\t\tnot: function( selector ) {\n\t\t\treturn this.pushStack( winnow( this, selector || [], true ) );\n\t\t},\n\t\tis: function( selector ) {\n\t\t\treturn !!winnow(\n\t\t\t\tthis,\n\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\ttypeof selector === \"string\" && rneedsContext.test( selector ) ?\n\t\t\t\t\tjQuery( selector ) :\n\t\t\t\tselector || [],\n\t\t\t\tfalse\n\t\t\t).length;\n\t\t}\n\t} );\n\n\n// Initialize a jQuery object\n\n\n// A central reference to the root jQuery(document)\n\tvar rootjQuery,\n\n\t\t// A simple way to check for HTML strings\n\t\t// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n\t\t// Strict HTML recognition (#11290: must start with <)\n\t\t// Shortcut simple #id case for speed\n\t\trquickExpr = /^(?:\\s*(<[\\w\\W]+>)[^>]*|#([\\w-]+))$/,\n\n\t\tinit = jQuery.fn.init = function( selector, context, root ) {\n\t\t\tvar match, elem;\n\n\t\t\t// HANDLE: $(\"\"), $(null), $(undefined), $(false)\n\t\t\tif ( !selector ) {\n\t\t\t\treturn this;\n\t\t\t}\n\n\t\t\t// Method init() accepts an alternate rootjQuery\n\t\t\t// so migrate can support jQuery.sub (gh-2101)\n\t\t\troot = root || rootjQuery;\n\n\t\t\t// Handle HTML strings\n\t\t\tif ( typeof selector === \"string\" ) {\n\t\t\t\tif ( selector[ 0 ] === \"<\" &&\n\t\t\t\t\tselector[ selector.length - 1 ] === \">\" &&\n\t\t\t\t\tselector.length >= 3 ) {\n\n\t\t\t\t\t// Assume that strings that start and end with <> are HTML and skip the regex check\n\t\t\t\t\tmatch = [ null, selector, null ];\n\n\t\t\t\t} else {\n\t\t\t\t\tmatch = rquickExpr.exec( selector );\n\t\t\t\t}\n\n\t\t\t\t// Match html or make sure no context is specified for #id\n\t\t\t\tif ( match && ( match[ 1 ] || !context ) ) {\n\n\t\t\t\t\t// HANDLE: $(html) -> $(array)\n\t\t\t\t\tif ( match[ 1 ] ) {\n\t\t\t\t\t\tcontext = context instanceof jQuery ? context[ 0 ] : context;\n\n\t\t\t\t\t\t// Option to run scripts is true for back-compat\n\t\t\t\t\t\t// Intentionally let the error be thrown if parseHTML is not present\n\t\t\t\t\t\tjQuery.merge( this, jQuery.parseHTML(\n\t\t\t\t\t\t\tmatch[ 1 ],\n\t\t\t\t\t\t\tcontext && context.nodeType ? context.ownerDocument || context : document,\n\t\t\t\t\t\t\ttrue\n\t\t\t\t\t\t) );\n\n\t\t\t\t\t\t// HANDLE: $(html, props)\n\t\t\t\t\t\tif ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) {\n\t\t\t\t\t\t\tfor ( match in context ) {\n\n\t\t\t\t\t\t\t\t// Properties of context are called as methods if possible\n\t\t\t\t\t\t\t\tif ( jQuery.isFunction( this[ match ] ) ) {\n\t\t\t\t\t\t\t\t\tthis[ match ]( context[ match ] );\n\n\t\t\t\t\t\t\t\t\t// ...and otherwise set as attributes\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tthis.attr( match, context[ match ] );\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\treturn this;\n\n\t\t\t\t\t\t// HANDLE: $(#id)\n\t\t\t\t\t} else {\n\t\t\t\t\t\telem = document.getElementById( match[ 2 ] );\n\n\t\t\t\t\t\tif ( elem ) {\n\n\t\t\t\t\t\t\t// Inject the element directly into the jQuery object\n\t\t\t\t\t\t\tthis[ 0 ] = elem;\n\t\t\t\t\t\t\tthis.length = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn this;\n\t\t\t\t\t}\n\n\t\t\t\t\t// HANDLE: $(expr, $(...))\n\t\t\t\t} else if ( !context || context.jquery ) {\n\t\t\t\t\treturn ( context || root ).find( selector );\n\n\t\t\t\t\t// HANDLE: $(expr, context)\n\t\t\t\t\t// (which is just equivalent to: $(context).find(expr)\n\t\t\t\t} else {\n\t\t\t\t\treturn this.constructor( context ).find( selector );\n\t\t\t\t}\n\n\t\t\t\t// HANDLE: $(DOMElement)\n\t\t\t} else if ( selector.nodeType ) {\n\t\t\t\tthis[ 0 ] = selector;\n\t\t\t\tthis.length = 1;\n\t\t\t\treturn this;\n\n\t\t\t\t// HANDLE: $(function)\n\t\t\t\t// Shortcut for document ready\n\t\t\t} else if ( jQuery.isFunction( selector ) ) {\n\t\t\t\treturn root.ready !== undefined ?\n\t\t\t\t\troot.ready( selector ) :\n\n\t\t\t\t\t// Execute immediately if ready is not present\n\t\t\t\t\tselector( jQuery );\n\t\t\t}\n\n\t\t\treturn jQuery.makeArray( selector, this );\n\t\t};\n\n// Give the init function the jQuery prototype for later instantiation\n\tinit.prototype = jQuery.fn;\n\n// Initialize central reference\n\trootjQuery = jQuery( document );\n\n\n\tvar rparentsprev = /^(?:parents|prev(?:Until|All))/,\n\n\t\t// Methods guaranteed to produce a unique set when starting from a unique set\n\t\tguaranteedUnique = {\n\t\t\tchildren: true,\n\t\t\tcontents: true,\n\t\t\tnext: true,\n\t\t\tprev: true\n\t\t};\n\n\tjQuery.fn.extend( {\n\t\thas: function( target ) {\n\t\t\tvar targets = jQuery( target, this ),\n\t\t\t\tl = targets.length;\n\n\t\t\treturn this.filter( function() {\n\t\t\t\tvar i = 0;\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\tif ( jQuery.contains( this, targets[ i ] ) ) {\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\tclosest: function( selectors, context ) {\n\t\t\tvar cur,\n\t\t\t\ti = 0,\n\t\t\t\tl = this.length,\n\t\t\t\tmatched = [],\n\t\t\t\ttargets = typeof selectors !== \"string\" && jQuery( selectors );\n\n\t\t\t// Positional selectors never match, since there's no _selection_ context\n\t\t\tif ( !rneedsContext.test( selectors ) ) {\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\tfor ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) {\n\n\t\t\t\t\t\t// Always skip document fragments\n\t\t\t\t\t\tif ( cur.nodeType < 11 && ( targets ?\n\t\t\t\t\t\t\ttargets.index( cur ) > -1 :\n\n\t\t\t\t\t\t\t\t// Don't pass non-elements to Sizzle\n\t\t\t\t\t\t\tcur.nodeType === 1 &&\n\t\t\t\t\t\t\tjQuery.find.matchesSelector( cur, selectors ) ) ) {\n\n\t\t\t\t\t\t\tmatched.push( cur );\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}\n\n\t\t\treturn this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched );\n\t\t},\n\n\t\t// Determine the position of an element within the set\n\t\tindex: function( elem ) {\n\n\t\t\t// No argument, return index in parent\n\t\t\tif ( !elem ) {\n\t\t\t\treturn ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;\n\t\t\t}\n\n\t\t\t// Index in selector\n\t\t\tif ( typeof elem === \"string\" ) {\n\t\t\t\treturn indexOf.call( jQuery( elem ), this[ 0 ] );\n\t\t\t}\n\n\t\t\t// Locate the position of the desired element\n\t\t\treturn indexOf.call( this,\n\n\t\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\t\telem.jquery ? elem[ 0 ] : elem\n\t\t\t);\n\t\t},\n\n\t\tadd: function( selector, context ) {\n\t\t\treturn this.pushStack(\n\t\t\t\tjQuery.uniqueSort(\n\t\t\t\t\tjQuery.merge( this.get(), jQuery( selector, context ) )\n\t\t\t\t)\n\t\t\t);\n\t\t},\n\n\t\taddBack: function( selector ) {\n\t\t\treturn this.add( selector == null ?\n\t\t\t\tthis.prevObject : this.prevObject.filter( selector )\n\t\t\t);\n\t\t}\n\t} );\n\n\tfunction sibling( cur, dir ) {\n\t\twhile ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {}\n\t\treturn cur;\n\t}\n\n\tjQuery.each( {\n\t\tparent: function( elem ) {\n\t\t\tvar parent = elem.parentNode;\n\t\t\treturn parent && parent.nodeType !== 11 ? parent : null;\n\t\t},\n\t\tparents: function( elem ) {\n\t\t\treturn dir( elem, \"parentNode\" );\n\t\t},\n\t\tparentsUntil: function( elem, i, until ) {\n\t\t\treturn dir( elem, \"parentNode\", until );\n\t\t},\n\t\tnext: function( elem ) {\n\t\t\treturn sibling( elem, \"nextSibling\" );\n\t\t},\n\t\tprev: function( elem ) {\n\t\t\treturn sibling( elem, \"previousSibling\" );\n\t\t},\n\t\tnextAll: function( elem ) {\n\t\t\treturn dir( elem, \"nextSibling\" );\n\t\t},\n\t\tprevAll: function( elem ) {\n\t\t\treturn dir( elem, \"previousSibling\" );\n\t\t},\n\t\tnextUntil: function( elem, i, until ) {\n\t\t\treturn dir( elem, \"nextSibling\", until );\n\t\t},\n\t\tprevUntil: function( elem, i, until ) {\n\t\t\treturn dir( elem, \"previousSibling\", until );\n\t\t},\n\t\tsiblings: function( elem ) {\n\t\t\treturn siblings( ( elem.parentNode || {} ).firstChild, elem );\n\t\t},\n\t\tchildren: function( elem ) {\n\t\t\treturn siblings( elem.firstChild );\n\t\t},\n\t\tcontents: function( elem ) {\n\t\t\tif ( nodeName( elem, \"iframe\" ) ) {\n\t\t\t\treturn elem.contentDocument;\n\t\t\t}\n\n\t\t\t// Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only\n\t\t\t// Treat the template element as a regular one in browsers that\n\t\t\t// don't support it.\n\t\t\tif ( nodeName( elem, \"template\" ) ) {\n\t\t\t\telem = elem.content || elem;\n\t\t\t}\n\n\t\t\treturn jQuery.merge( [], elem.childNodes );\n\t\t}\n\t}, function( name, fn ) {\n\t\tjQuery.fn[ name ] = function( until, selector ) {\n\t\t\tvar matched = jQuery.map( this, fn, until );\n\n\t\t\tif ( name.slice( -5 ) !== \"Until\" ) {\n\t\t\t\tselector = until;\n\t\t\t}\n\n\t\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\t\tmatched = jQuery.filter( selector, matched );\n\t\t\t}\n\n\t\t\tif ( this.length > 1 ) {\n\n\t\t\t\t// Remove duplicates\n\t\t\t\tif ( !guaranteedUnique[ name ] ) {\n\t\t\t\t\tjQuery.uniqueSort( matched );\n\t\t\t\t}\n\n\t\t\t\t// Reverse order for parents* and prev-derivatives\n\t\t\t\tif ( rparentsprev.test( name ) ) {\n\t\t\t\t\tmatched.reverse();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this.pushStack( matched );\n\t\t};\n\t} );\n\tvar rnothtmlwhite = ( /[^\\x20\\t\\r\\n\\f]+/g );\n\n\n\n// Convert String-formatted options into Object-formatted ones\n\tfunction createOptions( options ) {\n\t\tvar object = {};\n\t\tjQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) {\n\t\t\tobject[ flag ] = true;\n\t\t} );\n\t\treturn object;\n\t}\n\n\t/*\n\t * Create a callback list using the following parameters:\n\t *\n\t *\toptions: an optional list of space-separated options that will change how\n\t *\t\t\tthe callback list behaves or a more traditional option object\n\t *\n\t * By default a callback list will act like an event callback list and can be\n\t * \"fired\" multiple times.\n\t *\n\t * Possible options:\n\t *\n\t *\tonce:\t\t\twill ensure the callback list can only be fired once (like a Deferred)\n\t *\n\t *\tmemory:\t\t\twill keep track of previous values and will call any callback added\n\t *\t\t\t\t\tafter the list has been fired right away with the latest \"memorized\"\n\t *\t\t\t\t\tvalues (like a Deferred)\n\t *\n\t *\tunique:\t\t\twill ensure a callback can only be added once (no duplicate in the list)\n\t *\n\t *\tstopOnFalse:\tinterrupt callings when a callback returns false\n\t *\n\t */\n\tjQuery.Callbacks = function( options ) {\n\n\t\t// Convert options from String-formatted to Object-formatted if needed\n\t\t// (we check in cache first)\n\t\toptions = typeof options === \"string\" ?\n\t\t\tcreateOptions( options ) :\n\t\t\tjQuery.extend( {}, options );\n\n\t\tvar // Flag to know if list is currently firing\n\t\t\tfiring,\n\n\t\t\t// Last fire value for non-forgettable lists\n\t\t\tmemory,\n\n\t\t\t// Flag to know if list was already fired\n\t\t\tfired,\n\n\t\t\t// Flag to prevent firing\n\t\t\tlocked,\n\n\t\t\t// Actual callback list\n\t\t\tlist = [],\n\n\t\t\t// Queue of execution data for repeatable lists\n\t\t\tqueue = [],\n\n\t\t\t// Index of currently firing callback (modified by add/remove as needed)\n\t\t\tfiringIndex = -1,\n\n\t\t\t// Fire callbacks\n\t\t\tfire = function() {\n\n\t\t\t\t// Enforce single-firing\n\t\t\t\tlocked = locked || options.once;\n\n\t\t\t\t// Execute callbacks for all pending executions,\n\t\t\t\t// respecting firingIndex overrides and runtime changes\n\t\t\t\tfired = firing = true;\n\t\t\t\tfor ( ; queue.length; firingIndex = -1 ) {\n\t\t\t\t\tmemory = queue.shift();\n\t\t\t\t\twhile ( ++firingIndex < list.length ) {\n\n\t\t\t\t\t\t// Run callback and check for early termination\n\t\t\t\t\t\tif ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false &&\n\t\t\t\t\t\t\toptions.stopOnFalse ) {\n\n\t\t\t\t\t\t\t// Jump to end and forget the data so .add doesn't re-fire\n\t\t\t\t\t\t\tfiringIndex = list.length;\n\t\t\t\t\t\t\tmemory = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Forget the data if we're done with it\n\t\t\t\tif ( !options.memory ) {\n\t\t\t\t\tmemory = false;\n\t\t\t\t}\n\n\t\t\t\tfiring = false;\n\n\t\t\t\t// Clean up if we're done firing for good\n\t\t\t\tif ( locked ) {\n\n\t\t\t\t\t// Keep an empty list if we have data for future add calls\n\t\t\t\t\tif ( memory ) {\n\t\t\t\t\t\tlist = [];\n\n\t\t\t\t\t\t// Otherwise, this object is spent\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlist = \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t// Actual Callbacks object\n\t\t\tself = {\n\n\t\t\t\t// Add a callback or a collection of callbacks to the list\n\t\t\t\tadd: function() {\n\t\t\t\t\tif ( list ) {\n\n\t\t\t\t\t\t// If we have memory from a past run, we should fire after adding\n\t\t\t\t\t\tif ( memory && !firing ) {\n\t\t\t\t\t\t\tfiringIndex = list.length - 1;\n\t\t\t\t\t\t\tqueue.push( memory );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t( function add( args ) {\n\t\t\t\t\t\t\tjQuery.each( args, function( _, arg ) {\n\t\t\t\t\t\t\t\tif ( jQuery.isFunction( arg ) ) {\n\t\t\t\t\t\t\t\t\tif ( !options.unique || !self.has( arg ) ) {\n\t\t\t\t\t\t\t\t\t\tlist.push( arg );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else if ( arg && arg.length && jQuery.type( arg ) !== \"string\" ) {\n\n\t\t\t\t\t\t\t\t\t// Inspect recursively\n\t\t\t\t\t\t\t\t\tadd( arg );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t} )( arguments );\n\n\t\t\t\t\t\tif ( memory && !firing ) {\n\t\t\t\t\t\t\tfire();\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// Remove a callback from the list\n\t\t\t\tremove: function() {\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\n\t\t\t\t\t\t\t// Handle firing indexes\n\t\t\t\t\t\t\tif ( index <= firingIndex ) {\n\t\t\t\t\t\t\t\tfiringIndex--;\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\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Check if a given callback is in the list.\n\t\t\t\t// If no argument is given, return whether or not list has callbacks attached.\n\t\t\t\thas: function( fn ) {\n\t\t\t\t\treturn fn ?\n\t\t\t\t\tjQuery.inArray( fn, list ) > -1 :\n\t\t\t\t\tlist.length > 0;\n\t\t\t\t},\n\n\t\t\t\t// Remove all callbacks from the list\n\t\t\t\tempty: function() {\n\t\t\t\t\tif ( list ) {\n\t\t\t\t\t\tlist = [];\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Disable .fire and .add\n\t\t\t\t// Abort any current/pending executions\n\t\t\t\t// Clear all callbacks and values\n\t\t\t\tdisable: function() {\n\t\t\t\t\tlocked = queue = [];\n\t\t\t\t\tlist = memory = \"\";\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\tdisabled: function() {\n\t\t\t\t\treturn !list;\n\t\t\t\t},\n\n\t\t\t\t// Disable .fire\n\t\t\t\t// Also disable .add unless we have memory (since it would have no effect)\n\t\t\t\t// Abort any pending executions\n\t\t\t\tlock: function() {\n\t\t\t\t\tlocked = queue = [];\n\t\t\t\t\tif ( !memory && !firing ) {\n\t\t\t\t\t\tlist = memory = \"\";\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\tlocked: function() {\n\t\t\t\t\treturn !!locked;\n\t\t\t\t},\n\n\t\t\t\t// Call all callbacks with the given context and arguments\n\t\t\t\tfireWith: function( context, args ) {\n\t\t\t\t\tif ( !locked ) {\n\t\t\t\t\t\targs = args || [];\n\t\t\t\t\t\targs = [ context, args.slice ? args.slice() : args ];\n\t\t\t\t\t\tqueue.push( args );\n\t\t\t\t\t\tif ( !firing ) {\n\t\t\t\t\t\t\tfire();\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// Call all the callbacks with the given arguments\n\t\t\t\tfire: function() {\n\t\t\t\t\tself.fireWith( this, arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// To know if the callbacks have already been called at least once\n\t\t\t\tfired: function() {\n\t\t\t\t\treturn !!fired;\n\t\t\t\t}\n\t\t\t};\n\n\t\treturn self;\n\t};\n\n\n\tfunction Identity( v ) {\n\t\treturn v;\n\t}\n\tfunction Thrower( ex ) {\n\t\tthrow ex;\n\t}\n\n\tfunction adoptValue( value, resolve, reject, noValue ) {\n\t\tvar method;\n\n\t\ttry {\n\n\t\t\t// Check for promise aspect first to privilege synchronous behavior\n\t\t\tif ( value && jQuery.isFunction( ( method = value.promise ) ) ) {\n\t\t\t\tmethod.call( value ).done( resolve ).fail( reject );\n\n\t\t\t\t// Other thenables\n\t\t\t} else if ( value && jQuery.isFunction( ( method = value.then ) ) ) {\n\t\t\t\tmethod.call( value, resolve, reject );\n\n\t\t\t\t// Other non-thenables\n\t\t\t} else {\n\n\t\t\t\t// Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer:\n\t\t\t\t// * false: [ value ].slice( 0 ) => resolve( value )\n\t\t\t\t// * true: [ value ].slice( 1 ) => resolve()\n\t\t\t\tresolve.apply( undefined, [ value ].slice( noValue ) );\n\t\t\t}\n\n\t\t\t// For Promises/A+, convert exceptions into rejections\n\t\t\t// Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in\n\t\t\t// Deferred#then to conditionally suppress rejection.\n\t\t} catch ( value ) {\n\n\t\t\t// Support: Android 4.0 only\n\t\t\t// Strict mode functions invoked without .call/.apply get global-object context\n\t\t\treject.apply( undefined, [ value ] );\n\t\t}\n\t}\n\n\tjQuery.extend( {\n\n\t\tDeferred: function( func ) {\n\t\t\tvar tuples = [\n\n\t\t\t\t\t// action, add listener, callbacks,\n\t\t\t\t\t// ... .then handlers, argument index, [final state]\n\t\t\t\t\t[ \"notify\", \"progress\", jQuery.Callbacks( \"memory\" ),\n\t\t\t\t\t\tjQuery.Callbacks( \"memory\" ), 2 ],\n\t\t\t\t\t[ \"resolve\", \"done\", jQuery.Callbacks( \"once memory\" ),\n\t\t\t\t\t\tjQuery.Callbacks( \"once memory\" ), 0, \"resolved\" ],\n\t\t\t\t\t[ \"reject\", \"fail\", jQuery.Callbacks( \"once memory\" ),\n\t\t\t\t\t\tjQuery.Callbacks( \"once memory\" ), 1, \"rejected\" ]\n\t\t\t\t],\n\t\t\t\tstate = \"pending\",\n\t\t\t\tpromise = {\n\t\t\t\t\tstate: function() {\n\t\t\t\t\t\treturn state;\n\t\t\t\t\t},\n\t\t\t\t\talways: function() {\n\t\t\t\t\t\tdeferred.done( arguments ).fail( arguments );\n\t\t\t\t\t\treturn this;\n\t\t\t\t\t},\n\t\t\t\t\t\"catch\": function( fn ) {\n\t\t\t\t\t\treturn promise.then( null, fn );\n\t\t\t\t\t},\n\n\t\t\t\t\t// Keep pipe for back-compat\n\t\t\t\t\tpipe: function( /* fnDone, fnFail, fnProgress */ ) {\n\t\t\t\t\t\tvar fns = arguments;\n\n\t\t\t\t\t\treturn jQuery.Deferred( function( newDefer ) {\n\t\t\t\t\t\t\tjQuery.each( tuples, function( i, tuple ) {\n\n\t\t\t\t\t\t\t\t// Map tuples (progress, done, fail) to arguments (done, fail, progress)\n\t\t\t\t\t\t\t\tvar fn = jQuery.isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ];\n\n\t\t\t\t\t\t\t\t// deferred.progress(function() { bind to newDefer or newDefer.notify })\n\t\t\t\t\t\t\t\t// deferred.done(function() { bind to newDefer or newDefer.resolve })\n\t\t\t\t\t\t\t\t// deferred.fail(function() { bind to newDefer or newDefer.reject })\n\t\t\t\t\t\t\t\tdeferred[ tuple[ 1 ] ]( function() {\n\t\t\t\t\t\t\t\t\tvar returned = fn && fn.apply( this, arguments );\n\t\t\t\t\t\t\t\t\tif ( returned && jQuery.isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\t\t\t\treturned.promise()\n\t\t\t\t\t\t\t\t\t\t\t.progress( newDefer.notify )\n\t\t\t\t\t\t\t\t\t\t\t.done( newDefer.resolve )\n\t\t\t\t\t\t\t\t\t\t\t.fail( newDefer.reject );\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tnewDefer[ tuple[ 0 ] + \"With\" ](\n\t\t\t\t\t\t\t\t\t\t\tthis,\n\t\t\t\t\t\t\t\t\t\t\tfn ? [ returned ] : arguments\n\t\t\t\t\t\t\t\t\t\t);\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\tfns = null;\n\t\t\t\t\t\t} ).promise();\n\t\t\t\t\t},\n\t\t\t\t\tthen: function( onFulfilled, onRejected, onProgress ) {\n\t\t\t\t\t\tvar maxDepth = 0;\n\t\t\t\t\t\tfunction resolve( depth, deferred, handler, special ) {\n\t\t\t\t\t\t\treturn function() {\n\t\t\t\t\t\t\t\tvar that = this,\n\t\t\t\t\t\t\t\t\targs = arguments,\n\t\t\t\t\t\t\t\t\tmightThrow = function() {\n\t\t\t\t\t\t\t\t\t\tvar returned, then;\n\n\t\t\t\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.3.3.3\n\t\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-59\n\t\t\t\t\t\t\t\t\t\t// Ignore double-resolution attempts\n\t\t\t\t\t\t\t\t\t\tif ( depth < maxDepth ) {\n\t\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\treturned = handler.apply( that, args );\n\n\t\t\t\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.1\n\t\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-48\n\t\t\t\t\t\t\t\t\t\tif ( returned === deferred.promise() ) {\n\t\t\t\t\t\t\t\t\t\t\tthrow new TypeError( \"Thenable self-resolution\" );\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t// Support: Promises/A+ sections 2.3.3.1, 3.5\n\t\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-54\n\t\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-75\n\t\t\t\t\t\t\t\t\t\t// Retrieve `then` only once\n\t\t\t\t\t\t\t\t\t\tthen = returned &&\n\n\t\t\t\t\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.4\n\t\t\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-64\n\t\t\t\t\t\t\t\t\t\t\t// Only check objects and functions for thenability\n\t\t\t\t\t\t\t\t\t\t\t( typeof returned === \"object\" ||\n\t\t\t\t\t\t\t\t\t\t\ttypeof returned === \"function\" ) &&\n\t\t\t\t\t\t\t\t\t\t\treturned.then;\n\n\t\t\t\t\t\t\t\t\t\t// Handle a returned thenable\n\t\t\t\t\t\t\t\t\t\tif ( jQuery.isFunction( then ) ) {\n\n\t\t\t\t\t\t\t\t\t\t\t// Special processors (notify) just wait for resolution\n\t\t\t\t\t\t\t\t\t\t\tif ( special ) {\n\t\t\t\t\t\t\t\t\t\t\t\tthen.call(\n\t\t\t\t\t\t\t\t\t\t\t\t\treturned,\n\t\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Identity, special ),\n\t\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Thrower, special )\n\t\t\t\t\t\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t\t\t\t\t\t// Normal processors (resolve) also hook into progress\n\t\t\t\t\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t\t\t\t\t// ...and disregard older resolution values\n\t\t\t\t\t\t\t\t\t\t\t\tmaxDepth++;\n\n\t\t\t\t\t\t\t\t\t\t\t\tthen.call(\n\t\t\t\t\t\t\t\t\t\t\t\t\treturned,\n\t\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Identity, special ),\n\t\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Thrower, special ),\n\t\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Identity,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdeferred.notifyWith )\n\t\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t// Handle all other returned values\n\t\t\t\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t\t\t\t// Only substitute handlers pass on context\n\t\t\t\t\t\t\t\t\t\t\t// and multiple values (non-spec behavior)\n\t\t\t\t\t\t\t\t\t\t\tif ( handler !== Identity ) {\n\t\t\t\t\t\t\t\t\t\t\t\tthat = undefined;\n\t\t\t\t\t\t\t\t\t\t\t\targs = [ returned ];\n\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t// Process the value(s)\n\t\t\t\t\t\t\t\t\t\t\t// Default process is resolve\n\t\t\t\t\t\t\t\t\t\t\t( special || deferred.resolveWith )( that, args );\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t},\n\n\t\t\t\t\t\t\t\t\t// Only normal processors (resolve) catch and reject exceptions\n\t\t\t\t\t\t\t\t\tprocess = special ?\n\t\t\t\t\t\t\t\t\t\tmightThrow :\n\t\t\t\t\t\t\t\t\t\tfunction() {\n\t\t\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\t\t\tmightThrow();\n\t\t\t\t\t\t\t\t\t\t\t} catch ( e ) {\n\n\t\t\t\t\t\t\t\t\t\t\t\tif ( jQuery.Deferred.exceptionHook ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tjQuery.Deferred.exceptionHook( e,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tprocess.stackTrace );\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.3.3.4.1\n\t\t\t\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-61\n\t\t\t\t\t\t\t\t\t\t\t\t// Ignore post-resolution exceptions\n\t\t\t\t\t\t\t\t\t\t\t\tif ( depth + 1 >= maxDepth ) {\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t// Only substitute handlers pass on context\n\t\t\t\t\t\t\t\t\t\t\t\t\t// and multiple values (non-spec behavior)\n\t\t\t\t\t\t\t\t\t\t\t\t\tif ( handler !== Thrower ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tthat = undefined;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\targs = [ e ];\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\tdeferred.rejectWith( that, args );\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.3.3.1\n\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-57\n\t\t\t\t\t\t\t\t// Re-resolve promises immediately to dodge false rejection from\n\t\t\t\t\t\t\t\t// subsequent errors\n\t\t\t\t\t\t\t\tif ( depth ) {\n\t\t\t\t\t\t\t\t\tprocess();\n\t\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t\t// Call an optional hook to record the stack, in case of exception\n\t\t\t\t\t\t\t\t\t// since it's otherwise lost when execution goes async\n\t\t\t\t\t\t\t\t\tif ( jQuery.Deferred.getStackHook ) {\n\t\t\t\t\t\t\t\t\t\tprocess.stackTrace = jQuery.Deferred.getStackHook();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\twindow.setTimeout( process );\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\treturn jQuery.Deferred( function( newDefer ) {\n\n\t\t\t\t\t\t\t// progress_handlers.add( ... )\n\t\t\t\t\t\t\ttuples[ 0 ][ 3 ].add(\n\t\t\t\t\t\t\t\tresolve(\n\t\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\t\tnewDefer,\n\t\t\t\t\t\t\t\t\tjQuery.isFunction( onProgress ) ?\n\t\t\t\t\t\t\t\t\t\tonProgress :\n\t\t\t\t\t\t\t\t\t\tIdentity,\n\t\t\t\t\t\t\t\t\tnewDefer.notifyWith\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\t// fulfilled_handlers.add( ... )\n\t\t\t\t\t\t\ttuples[ 1 ][ 3 ].add(\n\t\t\t\t\t\t\t\tresolve(\n\t\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\t\tnewDefer,\n\t\t\t\t\t\t\t\t\tjQuery.isFunction( onFulfilled ) ?\n\t\t\t\t\t\t\t\t\t\tonFulfilled :\n\t\t\t\t\t\t\t\t\t\tIdentity\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\t// rejected_handlers.add( ... )\n\t\t\t\t\t\t\ttuples[ 2 ][ 3 ].add(\n\t\t\t\t\t\t\t\tresolve(\n\t\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\t\tnewDefer,\n\t\t\t\t\t\t\t\t\tjQuery.isFunction( onRejected ) ?\n\t\t\t\t\t\t\t\t\t\tonRejected :\n\t\t\t\t\t\t\t\t\t\tThrower\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t} ).promise();\n\t\t\t\t\t},\n\n\t\t\t\t\t// Get a promise for this deferred\n\t\t\t\t\t// If obj is provided, the promise aspect is added to the object\n\t\t\t\t\tpromise: function( obj ) {\n\t\t\t\t\t\treturn obj != null ? jQuery.extend( obj, promise ) : promise;\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tdeferred = {};\n\n\t\t\t// Add list-specific methods\n\t\t\tjQuery.each( tuples, function( i, tuple ) {\n\t\t\t\tvar list = tuple[ 2 ],\n\t\t\t\t\tstateString = tuple[ 5 ];\n\n\t\t\t\t// promise.progress = list.add\n\t\t\t\t// promise.done = list.add\n\t\t\t\t// promise.fail = list.add\n\t\t\t\tpromise[ tuple[ 1 ] ] = list.add;\n\n\t\t\t\t// Handle state\n\t\t\t\tif ( stateString ) {\n\t\t\t\t\tlist.add(\n\t\t\t\t\t\tfunction() {\n\n\t\t\t\t\t\t\t// state = \"resolved\" (i.e., fulfilled)\n\t\t\t\t\t\t\t// state = \"rejected\"\n\t\t\t\t\t\t\tstate = stateString;\n\t\t\t\t\t\t},\n\n\t\t\t\t\t\t// rejected_callbacks.disable\n\t\t\t\t\t\t// fulfilled_callbacks.disable\n\t\t\t\t\t\ttuples[ 3 - i ][ 2 ].disable,\n\n\t\t\t\t\t\t// progress_callbacks.lock\n\t\t\t\t\t\ttuples[ 0 ][ 2 ].lock\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\t// progress_handlers.fire\n\t\t\t\t// fulfilled_handlers.fire\n\t\t\t\t// rejected_handlers.fire\n\t\t\t\tlist.add( tuple[ 3 ].fire );\n\n\t\t\t\t// deferred.notify = function() { deferred.notifyWith(...) }\n\t\t\t\t// deferred.resolve = function() { deferred.resolveWith(...) }\n\t\t\t\t// deferred.reject = function() { deferred.rejectWith(...) }\n\t\t\t\tdeferred[ tuple[ 0 ] ] = function() {\n\t\t\t\t\tdeferred[ tuple[ 0 ] + \"With\" ]( this === deferred ? undefined : this, arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t};\n\n\t\t\t\t// deferred.notifyWith = list.fireWith\n\t\t\t\t// deferred.resolveWith = list.fireWith\n\t\t\t\t// deferred.rejectWith = list.fireWith\n\t\t\t\tdeferred[ tuple[ 0 ] + \"With\" ] = list.fireWith;\n\t\t\t} );\n\n\t\t\t// Make the deferred a promise\n\t\t\tpromise.promise( deferred );\n\n\t\t\t// Call given func if any\n\t\t\tif ( func ) {\n\t\t\t\tfunc.call( deferred, deferred );\n\t\t\t}\n\n\t\t\t// All done!\n\t\t\treturn deferred;\n\t\t},\n\n\t\t// Deferred helper\n\t\twhen: function( singleValue ) {\n\t\t\tvar\n\n\t\t\t\t// count of uncompleted subordinates\n\t\t\t\tremaining = arguments.length,\n\n\t\t\t\t// count of unprocessed arguments\n\t\t\t\ti = remaining,\n\n\t\t\t\t// subordinate fulfillment data\n\t\t\t\tresolveContexts = Array( i ),\n\t\t\t\tresolveValues = slice.call( arguments ),\n\n\t\t\t\t// the master Deferred\n\t\t\t\tmaster = jQuery.Deferred(),\n\n\t\t\t\t// subordinate callback factory\n\t\t\t\tupdateFunc = function( i ) {\n\t\t\t\t\treturn function( value ) {\n\t\t\t\t\t\tresolveContexts[ i ] = this;\n\t\t\t\t\t\tresolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;\n\t\t\t\t\t\tif ( !( --remaining ) ) {\n\t\t\t\t\t\t\tmaster.resolveWith( resolveContexts, resolveValues );\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t};\n\n\t\t\t// Single- and empty arguments are adopted like Promise.resolve\n\t\t\tif ( remaining <= 1 ) {\n\t\t\t\tadoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject,\n\t\t\t\t\t!remaining );\n\n\t\t\t\t// Use .then() to unwrap secondary thenables (cf. gh-3000)\n\t\t\t\tif ( master.state() === \"pending\" ||\n\t\t\t\t\tjQuery.isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) {\n\n\t\t\t\t\treturn master.then();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Multiple arguments are aggregated like Promise.all array elements\n\t\t\twhile ( i-- ) {\n\t\t\t\tadoptValue( resolveValues[ i ], updateFunc( i ), master.reject );\n\t\t\t}\n\n\t\t\treturn master.promise();\n\t\t}\n\t} );\n\n\n// These usually indicate a programmer mistake during development,\n// warn about them ASAP rather than swallowing them by default.\n\tvar rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;\n\n\tjQuery.Deferred.exceptionHook = function( error, stack ) {\n\n\t\t// Support: IE 8 - 9 only\n\t\t// Console exists when dev tools are open, which can happen at any time\n\t\tif ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) {\n\t\t\twindow.console.warn( \"jQuery.Deferred exception: \" + error.message, error.stack, stack );\n\t\t}\n\t};\n\n\n\n\n\tjQuery.readyException = function( error ) {\n\t\twindow.setTimeout( function() {\n\t\t\tthrow error;\n\t\t} );\n\t};\n\n\n\n\n// The deferred used on DOM ready\n\tvar readyList = jQuery.Deferred();\n\n\tjQuery.fn.ready = function( fn ) {\n\n\t\treadyList\n\t\t\t.then( fn )\n\n\t\t\t// Wrap jQuery.readyException in a function so that the lookup\n\t\t\t// happens at the time of error handling instead of callback\n\t\t\t// registration.\n\t\t\t.catch( function( error ) {\n\t\t\t\tjQuery.readyException( error );\n\t\t\t} );\n\n\t\treturn this;\n\t};\n\n\tjQuery.extend( {\n\n\t\t// Is the DOM ready to be used? Set to true once it occurs.\n\t\tisReady: false,\n\n\t\t// A counter to track how many items to wait for before\n\t\t// the ready event fires. See #6781\n\t\treadyWait: 1,\n\n\t\t// Handle when the DOM is ready\n\t\tready: function( wait ) {\n\n\t\t\t// Abort if there are pending holds or we're already ready\n\t\t\tif ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Remember that the DOM is ready\n\t\t\tjQuery.isReady = true;\n\n\t\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If there are functions bound, to execute\n\t\t\treadyList.resolveWith( document, [ jQuery ] );\n\t\t}\n\t} );\n\n\tjQuery.ready.then = readyList.then;\n\n// The ready event handler and self cleanup method\n\tfunction completed() {\n\t\tdocument.removeEventListener( \"DOMContentLoaded\", completed );\n\t\twindow.removeEventListener( \"load\", completed );\n\t\tjQuery.ready();\n\t}\n\n// Catch cases where $(document).ready() is called\n// after the browser event has already occurred.\n// Support: IE <=9 - 10 only\n// Older IE sometimes signals \"interactive\" too soon\n\tif ( document.readyState === \"complete\" ||\n\t\t( document.readyState !== \"loading\" && !document.documentElement.doScroll ) ) {\n\n\t\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\t\twindow.setTimeout( jQuery.ready );\n\n\t} else {\n\n\t\t// Use the handy event callback\n\t\tdocument.addEventListener( \"DOMContentLoaded\", completed );\n\n\t\t// A fallback to window.onload, that will always work\n\t\twindow.addEventListener( \"load\", completed );\n\t}\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\n\tvar access = function( elems, fn, key, value, chainable, emptyGet, raw ) {\n\t\tvar i = 0,\n\t\t\tlen = 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\taccess( elems, fn, i, key[ i ], true, emptyGet, raw );\n\t\t\t}\n\n\t\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\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\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 < len; i++ ) {\n\t\t\t\t\tfn(\n\t\t\t\t\t\telems[ i ], key, raw ?\n\t\t\t\t\t\t\tvalue :\n\t\t\t\t\t\t\tvalue.call( elems[ i ], i, fn( elems[ i ], key ) )\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( chainable ) {\n\t\t\treturn elems;\n\t\t}\n\n\t\t// Gets\n\t\tif ( bulk ) {\n\t\t\treturn fn.call( elems );\n\t\t}\n\n\t\treturn len ? fn( elems[ 0 ], key ) : emptyGet;\n\t};\n\tvar acceptData = function( owner ) {\n\n\t\t// Accepts only:\n\t\t//  - Node\n\t\t//    - Node.ELEMENT_NODE\n\t\t//    - Node.DOCUMENT_NODE\n\t\t//  - Object\n\t\t//    - Any\n\t\treturn owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );\n\t};\n\n\n\n\n\tfunction Data() {\n\t\tthis.expando = jQuery.expando + Data.uid++;\n\t}\n\n\tData.uid = 1;\n\n\tData.prototype = {\n\n\t\tcache: function( owner ) {\n\n\t\t\t// Check if the owner object already has a cache\n\t\t\tvar value = owner[ this.expando ];\n\n\t\t\t// If not, create one\n\t\t\tif ( !value ) {\n\t\t\t\tvalue = {};\n\n\t\t\t\t// We can accept data for non-element nodes in modern browsers,\n\t\t\t\t// but we should not, see #8335.\n\t\t\t\t// Always return an empty object.\n\t\t\t\tif ( acceptData( owner ) ) {\n\n\t\t\t\t\t// If it is a node unlikely to be stringify-ed or looped over\n\t\t\t\t\t// use plain assignment\n\t\t\t\t\tif ( owner.nodeType ) {\n\t\t\t\t\t\towner[ this.expando ] = value;\n\n\t\t\t\t\t\t// Otherwise secure it in a non-enumerable property\n\t\t\t\t\t\t// configurable must be true to allow the property to be\n\t\t\t\t\t\t// deleted when data is removed\n\t\t\t\t\t} else {\n\t\t\t\t\t\tObject.defineProperty( owner, this.expando, {\n\t\t\t\t\t\t\tvalue: value,\n\t\t\t\t\t\t\tconfigurable: true\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\treturn value;\n\t\t},\n\t\tset: function( owner, data, value ) {\n\t\t\tvar prop,\n\t\t\t\tcache = this.cache( owner );\n\n\t\t\t// Handle: [ owner, key, value ] args\n\t\t\t// Always use camelCase key (gh-2257)\n\t\t\tif ( typeof data === \"string\" ) {\n\t\t\t\tcache[ jQuery.camelCase( data ) ] = value;\n\n\t\t\t\t// Handle: [ owner, { properties } ] args\n\t\t\t} else {\n\n\t\t\t\t// Copy the properties one-by-one to the cache object\n\t\t\t\tfor ( prop in data ) {\n\t\t\t\t\tcache[ jQuery.camelCase( prop ) ] = data[ prop ];\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn cache;\n\t\t},\n\t\tget: function( owner, key ) {\n\t\t\treturn key === undefined ?\n\t\t\t\tthis.cache( owner ) :\n\n\t\t\t\t// Always use camelCase key (gh-2257)\n\t\t\towner[ this.expando ] && owner[ this.expando ][ jQuery.camelCase( key ) ];\n\t\t},\n\t\taccess: function( owner, key, value ) {\n\n\t\t\t// In cases where either:\n\t\t\t//\n\t\t\t//   1. No key was specified\n\t\t\t//   2. A string key was specified, but no value provided\n\t\t\t//\n\t\t\t// Take the \"read\" path and allow the get method to determine\n\t\t\t// which value to return, respectively either:\n\t\t\t//\n\t\t\t//   1. The entire cache object\n\t\t\t//   2. The data stored at the key\n\t\t\t//\n\t\t\tif ( key === undefined ||\n\t\t\t\t( ( key && typeof key === \"string\" ) && value === undefined ) ) {\n\n\t\t\t\treturn this.get( owner, key );\n\t\t\t}\n\n\t\t\t// When the key is not a string, or both a key and value\n\t\t\t// are specified, set or extend (existing objects) with either:\n\t\t\t//\n\t\t\t//   1. An object of properties\n\t\t\t//   2. A key and value\n\t\t\t//\n\t\t\tthis.set( owner, key, value );\n\n\t\t\t// Since the \"set\" path can have two possible entry points\n\t\t\t// return the expected data based on which path was taken[*]\n\t\t\treturn value !== undefined ? value : key;\n\t\t},\n\t\tremove: function( owner, key ) {\n\t\t\tvar i,\n\t\t\t\tcache = owner[ this.expando ];\n\n\t\t\tif ( cache === undefined ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( key !== undefined ) {\n\n\t\t\t\t// Support array or space separated string of keys\n\t\t\t\tif ( Array.isArray( key ) ) {\n\n\t\t\t\t\t// If key is an array of keys...\n\t\t\t\t\t// We always set camelCase keys, so remove that.\n\t\t\t\t\tkey = key.map( jQuery.camelCase );\n\t\t\t\t} else {\n\t\t\t\t\tkey = jQuery.camelCase( key );\n\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\tkey = key in cache ?\n\t\t\t\t\t\t[ key ] :\n\t\t\t\t\t\t( key.match( rnothtmlwhite ) || [] );\n\t\t\t\t}\n\n\t\t\t\ti = key.length;\n\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\tdelete cache[ key[ i ] ];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove the expando if there's no more data\n\t\t\tif ( key === undefined || jQuery.isEmptyObject( cache ) ) {\n\n\t\t\t\t// Support: Chrome <=35 - 45\n\t\t\t\t// Webkit & Blink performance suffers when deleting properties\n\t\t\t\t// from DOM nodes, so set to undefined instead\n\t\t\t\t// https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted)\n\t\t\t\tif ( owner.nodeType ) {\n\t\t\t\t\towner[ this.expando ] = undefined;\n\t\t\t\t} else {\n\t\t\t\t\tdelete owner[ this.expando ];\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\thasData: function( owner ) {\n\t\t\tvar cache = owner[ this.expando ];\n\t\t\treturn cache !== undefined && !jQuery.isEmptyObject( cache );\n\t\t}\n\t};\n\tvar dataPriv = new Data();\n\n\tvar dataUser = 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\n\tvar rbrace = /^(?:\\{[\\w\\W]*\\}|\\[[\\w\\W]*\\])$/,\n\t\trmultiDash = /[A-Z]/g;\n\n\tfunction getData( data ) {\n\t\tif ( data === \"true\" ) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif ( data === \"false\" ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( data === \"null\" ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Only convert to a number if it doesn't change the string\n\t\tif ( data === +data + \"\" ) {\n\t\t\treturn +data;\n\t\t}\n\n\t\tif ( rbrace.test( data ) ) {\n\t\t\treturn JSON.parse( data );\n\t\t}\n\n\t\treturn data;\n\t}\n\n\tfunction dataAttr( elem, key, data ) {\n\t\tvar name;\n\n\t\t// If nothing was found internally, try to fetch any\n\t\t// data from the HTML5 data-* attribute\n\t\tif ( data === undefined && elem.nodeType === 1 ) {\n\t\t\tname = \"data-\" + key.replace( rmultiDash, \"-$&\" ).toLowerCase();\n\t\t\tdata = elem.getAttribute( name );\n\n\t\t\tif ( typeof data === \"string\" ) {\n\t\t\t\ttry {\n\t\t\t\t\tdata = getData( data );\n\t\t\t\t} catch ( e ) {}\n\n\t\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\t\tdataUser.set( elem, key, data );\n\t\t\t} else {\n\t\t\t\tdata = undefined;\n\t\t\t}\n\t\t}\n\t\treturn data;\n\t}\n\n\tjQuery.extend( {\n\t\thasData: function( elem ) {\n\t\t\treturn dataUser.hasData( elem ) || dataPriv.hasData( elem );\n\t\t},\n\n\t\tdata: function( elem, name, data ) {\n\t\t\treturn dataUser.access( elem, name, data );\n\t\t},\n\n\t\tremoveData: function( elem, name ) {\n\t\t\tdataUser.remove( elem, name );\n\t\t},\n\n\t\t// TODO: Now that all calls to _data and _removeData have been replaced\n\t\t// with direct calls to dataPriv methods, these can be deprecated.\n\t\t_data: function( elem, name, data ) {\n\t\t\treturn dataPriv.access( elem, name, data );\n\t\t},\n\n\t\t_removeData: function( elem, name ) {\n\t\t\tdataPriv.remove( elem, name );\n\t\t}\n\t} );\n\n\tjQuery.fn.extend( {\n\t\tdata: function( key, value ) {\n\t\t\tvar i, name, data,\n\t\t\t\telem = this[ 0 ],\n\t\t\t\tattrs = elem && elem.attributes;\n\n\t\t\t// Gets all values\n\t\t\tif ( key === undefined ) {\n\t\t\t\tif ( this.length ) {\n\t\t\t\t\tdata = dataUser.get( elem );\n\n\t\t\t\t\tif ( elem.nodeType === 1 && !dataPriv.get( elem, \"hasDataAttrs\" ) ) {\n\t\t\t\t\t\ti = attrs.length;\n\t\t\t\t\t\twhile ( i-- ) {\n\n\t\t\t\t\t\t\t// Support: IE 11 only\n\t\t\t\t\t\t\t// The attrs elements can be null (#14894)\n\t\t\t\t\t\t\tif ( attrs[ i ] ) {\n\t\t\t\t\t\t\t\tname = attrs[ i ].name;\n\t\t\t\t\t\t\t\tif ( name.indexOf( \"data-\" ) === 0 ) {\n\t\t\t\t\t\t\t\t\tname = jQuery.camelCase( name.slice( 5 ) );\n\t\t\t\t\t\t\t\t\tdataAttr( elem, name, data[ name ] );\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\tdataPriv.set( elem, \"hasDataAttrs\", true );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn data;\n\t\t\t}\n\n\t\t\t// Sets multiple values\n\t\t\tif ( typeof key === \"object\" ) {\n\t\t\t\treturn this.each( function() {\n\t\t\t\t\tdataUser.set( this, key );\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\treturn access( this, function( value ) {\n\t\t\t\tvar data;\n\n\t\t\t\t// The calling jQuery object (element matches) is not empty\n\t\t\t\t// (and therefore has an element appears at this[ 0 ]) and the\n\t\t\t\t// `value` parameter was not undefined. An empty jQuery object\n\t\t\t\t// will result in `undefined` for elem = this[ 0 ] which will\n\t\t\t\t// throw an exception if an attempt to read a data cache is made.\n\t\t\t\tif ( elem && value === undefined ) {\n\n\t\t\t\t\t// Attempt to get data from the cache\n\t\t\t\t\t// The key will always be camelCased in Data\n\t\t\t\t\tdata = dataUser.get( elem, key );\n\t\t\t\t\tif ( data !== undefined ) {\n\t\t\t\t\t\treturn data;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Attempt to \"discover\" the data in\n\t\t\t\t\t// HTML5 custom data-* attrs\n\t\t\t\t\tdata = dataAttr( elem, key );\n\t\t\t\t\tif ( data !== undefined ) {\n\t\t\t\t\t\treturn data;\n\t\t\t\t\t}\n\n\t\t\t\t\t// We tried really hard, but the data doesn't exist.\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Set the data...\n\t\t\t\tthis.each( function() {\n\n\t\t\t\t\t// We always store the camelCased key\n\t\t\t\t\tdataUser.set( this, key, value );\n\t\t\t\t} );\n\t\t\t}, null, value, arguments.length > 1, null, true );\n\t\t},\n\n\t\tremoveData: function( key ) {\n\t\t\treturn this.each( function() {\n\t\t\t\tdataUser.remove( this, key );\n\t\t\t} );\n\t\t}\n\t} );\n\n\n\tjQuery.extend( {\n\t\tqueue: function( elem, type, data ) {\n\t\t\tvar queue;\n\n\t\t\tif ( elem ) {\n\t\t\t\ttype = ( type || \"fx\" ) + \"queue\";\n\t\t\t\tqueue = dataPriv.get( elem, type );\n\n\t\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\t\tif ( data ) {\n\t\t\t\t\tif ( !queue || Array.isArray( data ) ) {\n\t\t\t\t\t\tqueue = dataPriv.access( elem, type, jQuery.makeArray( data ) );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tqueue.push( data );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn queue || [];\n\t\t\t}\n\t\t},\n\n\t\tdequeue: function( elem, type ) {\n\t\t\ttype = type || \"fx\";\n\n\t\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\t\tstartLength = queue.length,\n\t\t\t\tfn = queue.shift(),\n\t\t\t\thooks = jQuery._queueHooks( elem, type ),\n\t\t\t\tnext = function() {\n\t\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t\t};\n\n\t\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\t\tif ( fn === \"inprogress\" ) {\n\t\t\t\tfn = queue.shift();\n\t\t\t\tstartLength--;\n\t\t\t}\n\n\t\t\tif ( fn ) {\n\n\t\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t\t// automatically dequeued\n\t\t\t\tif ( type === \"fx\" ) {\n\t\t\t\t\tqueue.unshift( \"inprogress\" );\n\t\t\t\t}\n\n\t\t\t\t// Clear up the last queue stop function\n\t\t\t\tdelete hooks.stop;\n\t\t\t\tfn.call( elem, next, hooks );\n\t\t\t}\n\n\t\t\tif ( !startLength && hooks ) {\n\t\t\t\thooks.empty.fire();\n\t\t\t}\n\t\t},\n\n\t\t// Not public - generate a queueHooks object, or return the current one\n\t\t_queueHooks: function( elem, type ) {\n\t\t\tvar key = type + \"queueHooks\";\n\t\t\treturn dataPriv.get( elem, key ) || dataPriv.access( elem, key, {\n\t\t\t\t\tempty: jQuery.Callbacks( \"once memory\" ).add( function() {\n\t\t\t\t\t\tdataPriv.remove( elem, [ type + \"queue\", key ] );\n\t\t\t\t\t} )\n\t\t\t\t} );\n\t\t}\n\t} );\n\n\tjQuery.fn.extend( {\n\t\tqueue: function( type, data ) {\n\t\t\tvar setter = 2;\n\n\t\t\tif ( typeof type !== \"string\" ) {\n\t\t\t\tdata = type;\n\t\t\t\ttype = \"fx\";\n\t\t\t\tsetter--;\n\t\t\t}\n\n\t\t\tif ( arguments.length < setter ) {\n\t\t\t\treturn jQuery.queue( this[ 0 ], type );\n\t\t\t}\n\n\t\t\treturn data === undefined ?\n\t\t\t\tthis :\n\t\t\t\tthis.each( function() {\n\t\t\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\t\t\t// Ensure a hooks for this queue\n\t\t\t\t\tjQuery._queueHooks( this, type );\n\n\t\t\t\t\tif ( type === \"fx\" && queue[ 0 ] !== \"inprogress\" ) {\n\t\t\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t},\n\t\tdequeue: function( type ) {\n\t\t\treturn this.each( function() {\n\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t} );\n\t\t},\n\t\tclearQueue: function( type ) {\n\t\t\treturn this.queue( type || \"fx\", [] );\n\t\t},\n\n\t\t// Get a promise resolved when queues of a certain type\n\t\t// are emptied (fx is the type by default)\n\t\tpromise: function( type, obj ) {\n\t\t\tvar tmp,\n\t\t\t\tcount = 1,\n\t\t\t\tdefer = jQuery.Deferred(),\n\t\t\t\telements = this,\n\t\t\t\ti = this.length,\n\t\t\t\tresolve = function() {\n\t\t\t\t\tif ( !( --count ) ) {\n\t\t\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\tif ( typeof type !== \"string\" ) {\n\t\t\t\tobj = type;\n\t\t\t\ttype = undefined;\n\t\t\t}\n\t\t\ttype = type || \"fx\";\n\n\t\t\twhile ( i-- ) {\n\t\t\t\ttmp = dataPriv.get( elements[ i ], type + \"queueHooks\" );\n\t\t\t\tif ( tmp && tmp.empty ) {\n\t\t\t\t\tcount++;\n\t\t\t\t\ttmp.empty.add( resolve );\n\t\t\t\t}\n\t\t\t}\n\t\t\tresolve();\n\t\t\treturn defer.promise( obj );\n\t\t}\n\t} );\n\tvar pnum = ( /[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/ ).source;\n\n\tvar rcssNum = new RegExp( \"^(?:([+-])=|)(\" + pnum + \")([a-z%]*)$\", \"i\" );\n\n\n\tvar cssExpand = [ \"Top\", \"Right\", \"Bottom\", \"Left\" ];\n\n\tvar isHiddenWithinTree = function( elem, el ) {\n\n\t\t// isHiddenWithinTree might be called from jQuery#filter function;\n\t\t// in that case, element will be second argument\n\t\telem = el || elem;\n\n\t\t// Inline style trumps all\n\t\treturn elem.style.display === \"none\" ||\n\t\t\telem.style.display === \"\" &&\n\n\t\t\t// Otherwise, check computed style\n\t\t\t// Support: Firefox <=43 - 45\n\t\t\t// Disconnected elements can have computed display: none, so first confirm that elem is\n\t\t\t// in the document.\n\t\t\tjQuery.contains( elem.ownerDocument, elem ) &&\n\n\t\t\tjQuery.css( elem, \"display\" ) === \"none\";\n\t};\n\n\tvar swap = 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\n\n\tfunction adjustCSS( elem, prop, valueParts, tween ) {\n\t\tvar adjusted,\n\t\t\tscale = 1,\n\t\t\tmaxIterations = 20,\n\t\t\tcurrentValue = tween ?\n\t\t\t\tfunction() {\n\t\t\t\t\treturn tween.cur();\n\t\t\t\t} :\n\t\t\t\tfunction() {\n\t\t\t\t\treturn jQuery.css( elem, prop, \"\" );\n\t\t\t\t},\n\t\t\tinitial = currentValue(),\n\t\t\tunit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" ),\n\n\t\t\t// Starting value computation is required for potential unit mismatches\n\t\t\tinitialInUnit = ( jQuery.cssNumber[ prop ] || unit !== \"px\" && +initial ) &&\n\t\t\t\trcssNum.exec( jQuery.css( elem, prop ) );\n\n\t\tif ( initialInUnit && initialInUnit[ 3 ] !== unit ) {\n\n\t\t\t// Trust units reported by jQuery.css\n\t\t\tunit = unit || initialInUnit[ 3 ];\n\n\t\t\t// Make sure we update the tween properties later on\n\t\t\tvalueParts = valueParts || [];\n\n\t\t\t// Iteratively approximate from a nonzero starting point\n\t\t\tinitialInUnit = +initial || 1;\n\n\t\t\tdo {\n\n\t\t\t\t// If previous iteration zeroed out, double until we get *something*.\n\t\t\t\t// Use string for doubling so we don't accidentally see scale as unchanged below\n\t\t\t\tscale = scale || \".5\";\n\n\t\t\t\t// Adjust and apply\n\t\t\t\tinitialInUnit = initialInUnit / scale;\n\t\t\t\tjQuery.style( elem, prop, initialInUnit + 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} while (\n\t\t\tscale !== ( scale = currentValue() / initial ) && scale !== 1 && --maxIterations\n\t\t\t\t);\n\t\t}\n\n\t\tif ( valueParts ) {\n\t\t\tinitialInUnit = +initialInUnit || +initial || 0;\n\n\t\t\t// Apply relative offset (+=/-=) if specified\n\t\t\tadjusted = valueParts[ 1 ] ?\n\t\t\tinitialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] :\n\t\t\t\t+valueParts[ 2 ];\n\t\t\tif ( tween ) {\n\t\t\t\ttween.unit = unit;\n\t\t\t\ttween.start = initialInUnit;\n\t\t\t\ttween.end = adjusted;\n\t\t\t}\n\t\t}\n\t\treturn adjusted;\n\t}\n\n\n\tvar defaultDisplayMap = {};\n\n\tfunction getDefaultDisplay( elem ) {\n\t\tvar temp,\n\t\t\tdoc = elem.ownerDocument,\n\t\t\tnodeName = elem.nodeName,\n\t\t\tdisplay = defaultDisplayMap[ nodeName ];\n\n\t\tif ( display ) {\n\t\t\treturn display;\n\t\t}\n\n\t\ttemp = doc.body.appendChild( doc.createElement( nodeName ) );\n\t\tdisplay = jQuery.css( temp, \"display\" );\n\n\t\ttemp.parentNode.removeChild( temp );\n\n\t\tif ( display === \"none\" ) {\n\t\t\tdisplay = \"block\";\n\t\t}\n\t\tdefaultDisplayMap[ nodeName ] = display;\n\n\t\treturn display;\n\t}\n\n\tfunction showHide( elements, show ) {\n\t\tvar display, elem,\n\t\t\tvalues = [],\n\t\t\tindex = 0,\n\t\t\tlength = elements.length;\n\n\t\t// Determine new display value for elements that need to change\n\t\tfor ( ; index < length; index++ ) {\n\t\t\telem = elements[ index ];\n\t\t\tif ( !elem.style ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tdisplay = elem.style.display;\n\t\t\tif ( show ) {\n\n\t\t\t\t// Since we force visibility upon cascade-hidden elements, an immediate (and slow)\n\t\t\t\t// check is required in this first loop unless we have a nonempty display value (either\n\t\t\t\t// inline or about-to-be-restored)\n\t\t\t\tif ( display === \"none\" ) {\n\t\t\t\t\tvalues[ index ] = dataPriv.get( elem, \"display\" ) || null;\n\t\t\t\t\tif ( !values[ index ] ) {\n\t\t\t\t\t\telem.style.display = \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif ( elem.style.display === \"\" && isHiddenWithinTree( elem ) ) {\n\t\t\t\t\tvalues[ index ] = getDefaultDisplay( elem );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif ( display !== \"none\" ) {\n\t\t\t\t\tvalues[ index ] = \"none\";\n\n\t\t\t\t\t// Remember what we're overwriting\n\t\t\t\t\tdataPriv.set( elem, \"display\", display );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Set the display of the elements in a second loop to avoid constant reflow\n\t\tfor ( index = 0; index < length; index++ ) {\n\t\t\tif ( values[ index ] != null ) {\n\t\t\t\telements[ index ].style.display = values[ index ];\n\t\t\t}\n\t\t}\n\n\t\treturn elements;\n\t}\n\n\tjQuery.fn.extend( {\n\t\tshow: function() {\n\t\t\treturn showHide( this, true );\n\t\t},\n\t\thide: function() {\n\t\t\treturn showHide( this );\n\t\t},\n\t\ttoggle: function( state ) {\n\t\t\tif ( typeof state === \"boolean\" ) {\n\t\t\t\treturn state ? this.show() : this.hide();\n\t\t\t}\n\n\t\t\treturn this.each( function() {\n\t\t\t\tif ( isHiddenWithinTree( this ) ) {\n\t\t\t\t\tjQuery( this ).show();\n\t\t\t\t} else {\n\t\t\t\t\tjQuery( this ).hide();\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t} );\n\tvar rcheckableType = ( /^(?:checkbox|radio)$/i );\n\n\tvar rtagName = ( /<([a-z][^\\/\\0>\\x20\\t\\r\\n\\f]+)/i );\n\n\tvar rscriptType = ( /^$|\\/(?:java|ecma)script/i );\n\n\n\n// We have to close these tags to support XHTML (#13200)\n\tvar wrapMap = {\n\n\t\t// Support: IE <=9 only\n\t\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\n\t\t// XHTML parsers do not magically insert elements in the\n\t\t// same way that tag soup parsers do. So we cannot shorten\n\t\t// this by omitting <tbody> or other required elements.\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: IE <=9 only\n\twrapMap.optgroup = wrapMap.option;\n\n\twrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\n\twrapMap.th = wrapMap.td;\n\n\n\tfunction getAll( context, tag ) {\n\n\t\t// Support: IE <=9 - 11 only\n\t\t// Use typeof to avoid zero-argument method invocation on host objects (#15151)\n\t\tvar ret;\n\n\t\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\t\tret = context.getElementsByTagName( tag || \"*\" );\n\n\t\t} else if ( typeof context.querySelectorAll !== \"undefined\" ) {\n\t\t\tret = context.querySelectorAll( tag || \"*\" );\n\n\t\t} else {\n\t\t\tret = [];\n\t\t}\n\n\t\tif ( tag === undefined || tag && nodeName( context, tag ) ) {\n\t\t\treturn jQuery.merge( [ context ], ret );\n\t\t}\n\n\t\treturn ret;\n\t}\n\n\n// Mark scripts as having already been evaluated\n\tfunction setGlobalEval( elems, refElements ) {\n\t\tvar i = 0,\n\t\t\tl = elems.length;\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tdataPriv.set(\n\t\t\t\telems[ i ],\n\t\t\t\t\"globalEval\",\n\t\t\t\t!refElements || dataPriv.get( refElements[ i ], \"globalEval\" )\n\t\t\t);\n\t\t}\n\t}\n\n\n\tvar rhtml = /<|&#?\\w+;/;\n\n\tfunction buildFragment( elems, context, scripts, selection, ignored ) {\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\n\t\t\t\t\t// Support: Android <=4.0 only, PhantomJS 1 only\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\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\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 ] + jQuery.htmlPrefilter( elem ) + 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: Android <=4.0 only, PhantomJS 1 only\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// Skip elements already in the context collection (trac-4087)\n\t\t\tif ( selection && jQuery.inArray( elem, selection ) > -1 ) {\n\t\t\t\tif ( ignored ) {\n\t\t\t\t\tignored.push( elem );\n\t\t\t\t}\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\n\t( function() {\n\t\tvar fragment = document.createDocumentFragment(),\n\t\t\tdiv = fragment.appendChild( document.createElement( \"div\" ) ),\n\t\t\tinput = document.createElement( \"input\" );\n\n\t\t// Support: Android 4.0 - 4.3 only\n\t\t// Check state lost if the name is set (#11217)\n\t\t// Support: Windows Web Apps (WWA)\n\t\t// `name` and `type` must use .setAttribute for WWA (#14901)\n\t\tinput.setAttribute( \"type\", \"radio\" );\n\t\tinput.setAttribute( \"checked\", \"checked\" );\n\t\tinput.setAttribute( \"name\", \"t\" );\n\n\t\tdiv.appendChild( input );\n\n\t\t// Support: Android <=4.1 only\n\t\t// Older WebKit doesn't clone checked state correctly in fragments\n\t\tsupport.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\t\t// Support: IE <=11 only\n\t\t// Make sure textarea (and checkbox) defaultValue is properly cloned\n\t\tdiv.innerHTML = \"<textarea>x</textarea>\";\n\t\tsupport.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;\n\t} )();\n\tvar documentElement = document.documentElement;\n\n\n\n\tvar\n\t\trkeyEvent = /^key/,\n\t\trmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/,\n\t\trtypenamespace = /^([^.]*)(?:\\.(.+)|)/;\n\n\tfunction returnTrue() {\n\t\treturn true;\n\t}\n\n\tfunction returnFalse() {\n\t\treturn false;\n\t}\n\n// Support: IE <=9 only\n// See #13393 for more info\n\tfunction safeActiveElement() {\n\t\ttry {\n\t\t\treturn document.activeElement;\n\t\t} catch ( err ) { }\n\t}\n\n\tfunction on( elem, types, selector, data, fn, 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\n\t\t\t// ( types-Object, selector, data )\n\t\t\tif ( typeof selector !== \"string\" ) {\n\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\ton( elem, type, selector, data, types[ type ], one );\n\t\t\t}\n\t\t\treturn elem;\n\t\t}\n\n\t\tif ( data == null && fn == null ) {\n\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\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\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 elem;\n\t\t}\n\n\t\tif ( one === 1 ) {\n\t\t\torigFn = fn;\n\t\t\tfn = function( event ) {\n\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\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 elem.each( function() {\n\t\t\tjQuery.event.add( this, types, fn, data, selector );\n\t\t} );\n\t}\n\n\t/*\n\t * Helper functions for managing events -- not part of the public interface.\n\t * Props to Dean Edwards' addEvent library for many of the ideas.\n\t */\n\tjQuery.event = {\n\n\t\tglobal: {},\n\n\t\tadd: function( elem, types, handler, data, selector ) {\n\n\t\t\tvar handleObjIn, eventHandle, tmp,\n\t\t\t\tevents, t, handleObj,\n\t\t\t\tspecial, handlers, type, namespaces, origType,\n\t\t\t\telemData = dataPriv.get( elem );\n\n\t\t\t// Don't attach events to noData or text/comment nodes (but allow plain objects)\n\t\t\tif ( !elemData ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Caller can pass in an object of custom data in lieu of the handler\n\t\t\tif ( handler.handler ) {\n\t\t\t\thandleObjIn = handler;\n\t\t\t\thandler = handleObjIn.handler;\n\t\t\t\tselector = handleObjIn.selector;\n\t\t\t}\n\n\t\t\t// Ensure that invalid selectors throw exceptions at attach time\n\t\t\t// Evaluate against documentElement in case elem is a non-element node (e.g., document)\n\t\t\tif ( selector ) {\n\t\t\t\tjQuery.find.matchesSelector( documentElement, selector );\n\t\t\t}\n\n\t\t\t// Make sure that the handler has a unique ID, used to find/remove it later\n\t\t\tif ( !handler.guid ) {\n\t\t\t\thandler.guid = jQuery.guid++;\n\t\t\t}\n\n\t\t\t// Init the element's event structure and main handler, if this is the first\n\t\t\tif ( !( events = elemData.events ) ) {\n\t\t\t\tevents = elemData.events = {};\n\t\t\t}\n\t\t\tif ( !( eventHandle = elemData.handle ) ) {\n\t\t\t\teventHandle = elemData.handle = function( e ) {\n\n\t\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\t\treturn typeof jQuery !== \"undefined\" && jQuery.event.triggered !== e.type ?\n\t\t\t\t\t\tjQuery.event.dispatch.apply( elem, arguments ) : undefined;\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Handle multiple events separated by a space\n\t\t\ttypes = ( types || \"\" ).match( rnothtmlwhite ) || [ \"\" ];\n\t\t\tt = types.length;\n\t\t\twhile ( t-- ) {\n\t\t\t\ttmp = rtypenamespace.exec( types[ t ] ) || [];\n\t\t\t\ttype = origType = tmp[ 1 ];\n\t\t\t\tnamespaces = ( tmp[ 2 ] || \"\" ).split( \".\" ).sort();\n\n\t\t\t\t// There *must* be a type, no attaching namespace-only handlers\n\t\t\t\tif ( !type ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// If event changes its type, use the special event handlers for the changed type\n\t\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t\t// If selector defined, determine special event api type, otherwise given type\n\t\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\n\t\t\t\t// Update special based on newly reset type\n\t\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t\t// handleObj is passed to all event handlers\n\t\t\t\thandleObj = jQuery.extend( {\n\t\t\t\t\ttype: type,\n\t\t\t\t\torigType: origType,\n\t\t\t\t\tdata: data,\n\t\t\t\t\thandler: handler,\n\t\t\t\t\tguid: handler.guid,\n\t\t\t\t\tselector: selector,\n\t\t\t\t\tneedsContext: selector && jQuery.expr.match.needsContext.test( selector ),\n\t\t\t\t\tnamespace: namespaces.join( \".\" )\n\t\t\t\t}, handleObjIn );\n\n\t\t\t\t// Init the event handler queue if we're the first\n\t\t\t\tif ( !( handlers = events[ type ] ) ) {\n\t\t\t\t\thandlers = events[ type ] = [];\n\t\t\t\t\thandlers.delegateCount = 0;\n\n\t\t\t\t\t// Only use addEventListener if the special events handler returns false\n\t\t\t\t\tif ( !special.setup ||\n\t\t\t\t\t\tspecial.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\n\t\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\t\telem.addEventListener( type, eventHandle );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( special.add ) {\n\t\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Add to the element's handler list, delegates in front\n\t\t\t\tif ( selector ) {\n\t\t\t\t\thandlers.splice( handlers.delegateCount++, 0, handleObj );\n\t\t\t\t} else {\n\t\t\t\t\thandlers.push( handleObj );\n\t\t\t\t}\n\n\t\t\t\t// Keep track of which events have ever been used, for event optimization\n\t\t\t\tjQuery.event.global[ type ] = true;\n\t\t\t}\n\n\t\t},\n\n\t\t// Detach an event or set of events from an element\n\t\tremove: function( elem, types, handler, selector, mappedTypes ) {\n\n\t\t\tvar j, origCount, tmp,\n\t\t\t\tevents, t, handleObj,\n\t\t\t\tspecial, handlers, type, namespaces, origType,\n\t\t\t\telemData = dataPriv.hasData( elem ) && dataPriv.get( elem );\n\n\t\t\tif ( !elemData || !( events = elemData.events ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Once for each type.namespace in types; type may be omitted\n\t\t\ttypes = ( types || \"\" ).match( rnothtmlwhite ) || [ \"\" ];\n\t\t\tt = types.length;\n\t\t\twhile ( t-- ) {\n\t\t\t\ttmp = rtypenamespace.exec( types[ t ] ) || [];\n\t\t\t\ttype = origType = tmp[ 1 ];\n\t\t\t\tnamespaces = ( tmp[ 2 ] || \"\" ).split( \".\" ).sort();\n\n\t\t\t\t// Unbind all events (on this namespace, if provided) for the element\n\t\t\t\tif ( !type ) {\n\t\t\t\t\tfor ( type in events ) {\n\t\t\t\t\t\tjQuery.event.remove( elem, type + types[ t ], handler, selector, true );\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tspecial = jQuery.event.special[ type ] || {};\n\t\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\t\t\t\thandlers = events[ type ] || [];\n\t\t\t\ttmp = tmp[ 2 ] &&\n\t\t\t\t\tnew RegExp( \"(^|\\\\.)\" + namespaces.join( \"\\\\.(?:.*\\\\.|)\" ) + \"(\\\\.|$)\" );\n\n\t\t\t\t// Remove matching events\n\t\t\t\torigCount = j = handlers.length;\n\t\t\t\twhile ( j-- ) {\n\t\t\t\t\thandleObj = handlers[ j ];\n\n\t\t\t\t\tif ( ( mappedTypes || origType === handleObj.origType ) &&\n\t\t\t\t\t\t( !handler || handler.guid === handleObj.guid ) &&\n\t\t\t\t\t\t( !tmp || tmp.test( handleObj.namespace ) ) &&\n\t\t\t\t\t\t( !selector || selector === handleObj.selector ||\n\t\t\t\t\t\tselector === \"**\" && handleObj.selector ) ) {\n\t\t\t\t\t\thandlers.splice( j, 1 );\n\n\t\t\t\t\t\tif ( handleObj.selector ) {\n\t\t\t\t\t\t\thandlers.delegateCount--;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( special.remove ) {\n\t\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Remove generic event handler if we removed something and no more handlers exist\n\t\t\t\t// (avoids potential for endless recursion during removal of special event handlers)\n\t\t\t\tif ( origCount && !handlers.length ) {\n\t\t\t\t\tif ( !special.teardown ||\n\t\t\t\t\t\tspecial.teardown.call( elem, namespaces, elemData.handle ) === false ) {\n\n\t\t\t\t\t\tjQuery.removeEvent( elem, type, elemData.handle );\n\t\t\t\t\t}\n\n\t\t\t\t\tdelete events[ type ];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove data and the expando if it's no longer used\n\t\t\tif ( jQuery.isEmptyObject( events ) ) {\n\t\t\t\tdataPriv.remove( elem, \"handle events\" );\n\t\t\t}\n\t\t},\n\n\t\tdispatch: function( nativeEvent ) {\n\n\t\t\t// Make a writable jQuery.Event from the native event object\n\t\t\tvar event = jQuery.event.fix( nativeEvent );\n\n\t\t\tvar i, j, ret, matched, handleObj, handlerQueue,\n\t\t\t\targs = new Array( arguments.length ),\n\t\t\t\thandlers = ( dataPriv.get( this, \"events\" ) || {} )[ event.type ] || [],\n\t\t\t\tspecial = jQuery.event.special[ event.type ] || {};\n\n\t\t\t// Use the fix-ed jQuery.Event rather than the (read-only) native event\n\t\t\targs[ 0 ] = event;\n\n\t\t\tfor ( i = 1; i < arguments.length; i++ ) {\n\t\t\t\targs[ i ] = arguments[ i ];\n\t\t\t}\n\n\t\t\tevent.delegateTarget = this;\n\n\t\t\t// Call the preDispatch hook for the mapped type, and let it bail if desired\n\t\t\tif ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Determine handlers\n\t\t\thandlerQueue = jQuery.event.handlers.call( this, event, handlers );\n\n\t\t\t// Run delegates first; they may want to stop propagation beneath us\n\t\t\ti = 0;\n\t\t\twhile ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) {\n\t\t\t\tevent.currentTarget = matched.elem;\n\n\t\t\t\tj = 0;\n\t\t\t\twhile ( ( handleObj = matched.handlers[ j++ ] ) &&\n\t\t\t\t!event.isImmediatePropagationStopped() ) {\n\n\t\t\t\t\t// Triggered event must either 1) have no namespace, or 2) have namespace(s)\n\t\t\t\t\t// a subset or equal to those in the bound event (both can have no namespace).\n\t\t\t\t\tif ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) {\n\n\t\t\t\t\t\tevent.handleObj = handleObj;\n\t\t\t\t\t\tevent.data = handleObj.data;\n\n\t\t\t\t\t\tret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle ||\n\t\t\t\t\t\thandleObj.handler ).apply( matched.elem, args );\n\n\t\t\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\t\t\tif ( ( event.result = ret ) === false ) {\n\t\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\t\tevent.stopPropagation();\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\n\t\t\t// Call the postDispatch hook for the mapped type\n\t\t\tif ( special.postDispatch ) {\n\t\t\t\tspecial.postDispatch.call( this, event );\n\t\t\t}\n\n\t\t\treturn event.result;\n\t\t},\n\n\t\thandlers: function( event, handlers ) {\n\t\t\tvar i, handleObj, sel, matchedHandlers, matchedSelectors,\n\t\t\t\thandlerQueue = [],\n\t\t\t\tdelegateCount = handlers.delegateCount,\n\t\t\t\tcur = event.target;\n\n\t\t\t// Find delegate handlers\n\t\t\tif ( delegateCount &&\n\n\t\t\t\t// Support: IE <=9\n\t\t\t\t// Black-hole SVG <use> instance trees (trac-13180)\n\t\t\t\tcur.nodeType &&\n\n\t\t\t\t// Support: Firefox <=42\n\t\t\t\t// Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861)\n\t\t\t\t// https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click\n\t\t\t\t// Support: IE 11 only\n\t\t\t\t// ...but not arrow key \"clicks\" of radio inputs, which can have `button` -1 (gh-2343)\n\t\t\t\t!( event.type === \"click\" && event.button >= 1 ) ) {\n\n\t\t\t\tfor ( ; cur !== this; cur = cur.parentNode || this ) {\n\n\t\t\t\t\t// Don't check non-elements (#13208)\n\t\t\t\t\t// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)\n\t\t\t\t\tif ( cur.nodeType === 1 && !( event.type === \"click\" && cur.disabled === true ) ) {\n\t\t\t\t\t\tmatchedHandlers = [];\n\t\t\t\t\t\tmatchedSelectors = {};\n\t\t\t\t\t\tfor ( i = 0; i < delegateCount; i++ ) {\n\t\t\t\t\t\t\thandleObj = handlers[ i ];\n\n\t\t\t\t\t\t\t// Don't conflict with Object.prototype properties (#13203)\n\t\t\t\t\t\t\tsel = handleObj.selector + \" \";\n\n\t\t\t\t\t\t\tif ( matchedSelectors[ sel ] === undefined ) {\n\t\t\t\t\t\t\t\tmatchedSelectors[ sel ] = handleObj.needsContext ?\n\t\t\t\t\t\t\t\tjQuery( sel, this ).index( cur ) > -1 :\n\t\t\t\t\t\t\t\t\tjQuery.find( sel, this, null, [ cur ] ).length;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif ( matchedSelectors[ sel ] ) {\n\t\t\t\t\t\t\t\tmatchedHandlers.push( handleObj );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( matchedHandlers.length ) {\n\t\t\t\t\t\t\thandlerQueue.push( { elem: cur, handlers: matchedHandlers } );\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// Add the remaining (directly-bound) handlers\n\t\t\tcur = this;\n\t\t\tif ( delegateCount < handlers.length ) {\n\t\t\t\thandlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } );\n\t\t\t}\n\n\t\t\treturn handlerQueue;\n\t\t},\n\n\t\taddProp: function( name, hook ) {\n\t\t\tObject.defineProperty( jQuery.Event.prototype, name, {\n\t\t\t\tenumerable: true,\n\t\t\t\tconfigurable: true,\n\n\t\t\t\tget: jQuery.isFunction( hook ) ?\n\t\t\t\t\tfunction() {\n\t\t\t\t\t\tif ( this.originalEvent ) {\n\t\t\t\t\t\t\treturn hook( this.originalEvent );\n\t\t\t\t\t\t}\n\t\t\t\t\t} :\n\t\t\t\t\tfunction() {\n\t\t\t\t\t\tif ( this.originalEvent ) {\n\t\t\t\t\t\t\treturn this.originalEvent[ name ];\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\n\t\t\t\tset: function( value ) {\n\t\t\t\t\tObject.defineProperty( this, name, {\n\t\t\t\t\t\tenumerable: true,\n\t\t\t\t\t\tconfigurable: true,\n\t\t\t\t\t\twritable: true,\n\t\t\t\t\t\tvalue: value\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t} );\n\t\t},\n\n\t\tfix: function( originalEvent ) {\n\t\t\treturn originalEvent[ jQuery.expando ] ?\n\t\t\t\toriginalEvent :\n\t\t\t\tnew jQuery.Event( originalEvent );\n\t\t},\n\n\t\tspecial: {\n\t\t\tload: {\n\n\t\t\t\t// Prevent triggered image.load events from bubbling to window.load\n\t\t\t\tnoBubble: true\n\t\t\t},\n\t\t\tfocus: {\n\n\t\t\t\t// Fire native event if possible so blur/focus sequence is correct\n\t\t\t\ttrigger: function() {\n\t\t\t\t\tif ( this !== safeActiveElement() && this.focus ) {\n\t\t\t\t\t\tthis.focus();\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tdelegateType: \"focusin\"\n\t\t\t},\n\t\t\tblur: {\n\t\t\t\ttrigger: function() {\n\t\t\t\t\tif ( this === safeActiveElement() && this.blur ) {\n\t\t\t\t\t\tthis.blur();\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tdelegateType: \"focusout\"\n\t\t\t},\n\t\t\tclick: {\n\n\t\t\t\t// For checkbox, fire native event so checked state will be right\n\t\t\t\ttrigger: function() {\n\t\t\t\t\tif ( this.type === \"checkbox\" && this.click && nodeName( this, \"input\" ) ) {\n\t\t\t\t\t\tthis.click();\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\t// For cross-browser consistency, don't fire native .click() on links\n\t\t\t\t_default: function( event ) {\n\t\t\t\t\treturn nodeName( event.target, \"a\" );\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tbeforeunload: {\n\t\t\t\tpostDispatch: function( event ) {\n\n\t\t\t\t\t// Support: Firefox 20+\n\t\t\t\t\t// Firefox doesn't alert if the returnValue field is not set.\n\t\t\t\t\tif ( event.result !== undefined && event.originalEvent ) {\n\t\t\t\t\t\tevent.originalEvent.returnValue = event.result;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\tjQuery.removeEvent = function( elem, type, handle ) {\n\n\t\t// This \"if\" is needed for plain objects\n\t\tif ( elem.removeEventListener ) {\n\t\t\telem.removeEventListener( type, handle );\n\t\t}\n\t};\n\n\tjQuery.Event = function( src, props ) {\n\n\t\t// Allow instantiation without the 'new' keyword\n\t\tif ( !( this instanceof jQuery.Event ) ) {\n\t\t\treturn new jQuery.Event( src, props );\n\t\t}\n\n\t\t// Event object\n\t\tif ( src && src.type ) {\n\t\t\tthis.originalEvent = src;\n\t\t\tthis.type = src.type;\n\n\t\t\t// Events bubbling up the document may have been marked as prevented\n\t\t\t// by a handler lower down the tree; reflect the correct value.\n\t\t\tthis.isDefaultPrevented = src.defaultPrevented ||\n\t\t\tsrc.defaultPrevented === undefined &&\n\n\t\t\t// Support: Android <=2.3 only\n\t\t\tsrc.returnValue === false ?\n\t\t\t\treturnTrue :\n\t\t\t\treturnFalse;\n\n\t\t\t// Create target properties\n\t\t\t// Support: Safari <=6 - 7 only\n\t\t\t// Target should not be a text node (#504, #13143)\n\t\t\tthis.target = ( src.target && src.target.nodeType === 3 ) ?\n\t\t\t\tsrc.target.parentNode :\n\t\t\t\tsrc.target;\n\n\t\t\tthis.currentTarget = src.currentTarget;\n\t\t\tthis.relatedTarget = src.relatedTarget;\n\n\t\t\t// Event type\n\t\t} else {\n\t\t\tthis.type = src;\n\t\t}\n\n\t\t// Put explicitly provided properties onto the event object\n\t\tif ( props ) {\n\t\t\tjQuery.extend( this, props );\n\t\t}\n\n\t\t// Create a timestamp if incoming event doesn't have one\n\t\tthis.timeStamp = src && src.timeStamp || jQuery.now();\n\n\t\t// Mark it as fixed\n\t\tthis[ jQuery.expando ] = true;\n\t};\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\n\tjQuery.Event.prototype = {\n\t\tconstructor: jQuery.Event,\n\t\tisDefaultPrevented: returnFalse,\n\t\tisPropagationStopped: returnFalse,\n\t\tisImmediatePropagationStopped: returnFalse,\n\t\tisSimulated: false,\n\n\t\tpreventDefault: function() {\n\t\t\tvar e = this.originalEvent;\n\n\t\t\tthis.isDefaultPrevented = returnTrue;\n\n\t\t\tif ( e && !this.isSimulated ) {\n\t\t\t\te.preventDefault();\n\t\t\t}\n\t\t},\n\t\tstopPropagation: function() {\n\t\t\tvar e = this.originalEvent;\n\n\t\t\tthis.isPropagationStopped = returnTrue;\n\n\t\t\tif ( e && !this.isSimulated ) {\n\t\t\t\te.stopPropagation();\n\t\t\t}\n\t\t},\n\t\tstopImmediatePropagation: function() {\n\t\t\tvar e = this.originalEvent;\n\n\t\t\tthis.isImmediatePropagationStopped = returnTrue;\n\n\t\t\tif ( e && !this.isSimulated ) {\n\t\t\t\te.stopImmediatePropagation();\n\t\t\t}\n\n\t\t\tthis.stopPropagation();\n\t\t}\n\t};\n\n// Includes all common event props including KeyEvent and MouseEvent specific props\n\tjQuery.each( {\n\t\taltKey: true,\n\t\tbubbles: true,\n\t\tcancelable: true,\n\t\tchangedTouches: true,\n\t\tctrlKey: true,\n\t\tdetail: true,\n\t\teventPhase: true,\n\t\tmetaKey: true,\n\t\tpageX: true,\n\t\tpageY: true,\n\t\tshiftKey: true,\n\t\tview: true,\n\t\t\"char\": true,\n\t\tcharCode: true,\n\t\tkey: true,\n\t\tkeyCode: true,\n\t\tbutton: true,\n\t\tbuttons: true,\n\t\tclientX: true,\n\t\tclientY: true,\n\t\toffsetX: true,\n\t\toffsetY: true,\n\t\tpointerId: true,\n\t\tpointerType: true,\n\t\tscreenX: true,\n\t\tscreenY: true,\n\t\ttargetTouches: true,\n\t\ttoElement: true,\n\t\ttouches: true,\n\n\t\twhich: function( event ) {\n\t\t\tvar button = event.button;\n\n\t\t\t// Add which for key events\n\t\t\tif ( event.which == null && rkeyEvent.test( event.type ) ) {\n\t\t\t\treturn event.charCode != null ? event.charCode : event.keyCode;\n\t\t\t}\n\n\t\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\t\tif ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) {\n\t\t\t\tif ( button & 1 ) {\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\n\t\t\t\tif ( button & 2 ) {\n\t\t\t\t\treturn 3;\n\t\t\t\t}\n\n\t\t\t\tif ( button & 4 ) {\n\t\t\t\t\treturn 2;\n\t\t\t\t}\n\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\treturn event.which;\n\t\t}\n\t}, jQuery.event.addProp );\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\n// so that event delegation works in jQuery.\n// Do the same for pointerenter/pointerleave and pointerover/pointerout\n//\n// Support: Safari 7 only\n// Safari sends mouseenter too often; see:\n// https://bugs.chromium.org/p/chromium/issues/detail?id=470258\n// for the description of the bug (it existed in older Chrome versions as well).\n\tjQuery.each( {\n\t\tmouseenter: \"mouseover\",\n\t\tmouseleave: \"mouseout\",\n\t\tpointerenter: \"pointerover\",\n\t\tpointerleave: \"pointerout\"\n\t}, function( orig, fix ) {\n\t\tjQuery.event.special[ orig ] = {\n\t\t\tdelegateType: fix,\n\t\t\tbindType: fix,\n\n\t\t\thandle: function( event ) {\n\t\t\t\tvar ret,\n\t\t\t\t\ttarget = this,\n\t\t\t\t\trelated = event.relatedTarget,\n\t\t\t\t\thandleObj = event.handleObj;\n\n\t\t\t\t// For mouseenter/leave call the handler if related is outside the target.\n\t\t\t\t// NB: No relatedTarget if the mouse left/entered the browser window\n\t\t\t\tif ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) {\n\t\t\t\t\tevent.type = handleObj.origType;\n\t\t\t\t\tret = handleObj.handler.apply( this, arguments );\n\t\t\t\t\tevent.type = fix;\n\t\t\t\t}\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t};\n\t} );\n\n\tjQuery.fn.extend( {\n\n\t\ton: function( types, selector, data, fn ) {\n\t\t\treturn on( this, types, selector, data, fn );\n\t\t},\n\t\tone: function( types, selector, data, fn ) {\n\t\t\treturn on( this, types, selector, data, fn, 1 );\n\t\t},\n\t\toff: function( types, selector, fn ) {\n\t\t\tvar handleObj, type;\n\t\t\tif ( types && types.preventDefault && types.handleObj ) {\n\n\t\t\t\t// ( event )  dispatched jQuery.Event\n\t\t\t\thandleObj = types.handleObj;\n\t\t\t\tjQuery( types.delegateTarget ).off(\n\t\t\t\t\thandleObj.namespace ?\n\t\t\t\t\thandleObj.origType + \".\" + handleObj.namespace :\n\t\t\t\t\t\thandleObj.origType,\n\t\t\t\t\thandleObj.selector,\n\t\t\t\t\thandleObj.handler\n\t\t\t\t);\n\t\t\t\treturn this;\n\t\t\t}\n\t\t\tif ( typeof types === \"object\" ) {\n\n\t\t\t\t// ( types-object [, selector] )\n\t\t\t\tfor ( type in types ) {\n\t\t\t\t\tthis.off( type, selector, types[ type ] );\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t}\n\t\t\tif ( selector === false || typeof selector === \"function\" ) {\n\n\t\t\t\t// ( types [, fn] )\n\t\t\t\tfn = selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t\tif ( fn === false ) {\n\t\t\t\tfn = returnFalse;\n\t\t\t}\n\t\t\treturn this.each( function() {\n\t\t\t\tjQuery.event.remove( this, types, fn, selector );\n\t\t\t} );\n\t\t}\n\t} );\n\n\n\tvar\n\n\t\t/* eslint-disable max-len */\n\n\t\t// See https://github.com/eslint/eslint/issues/3229\n\t\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\\/\\0>\\x20\\t\\r\\n\\f]*)[^>]*)\\/>/gi,\n\n\t\t/* eslint-enable */\n\n\t\t// Support: IE <=10 - 11, Edge 12 - 13\n\t\t// In IE/Edge using regex groups here causes severe slowdowns.\n\t\t// See https://connect.microsoft.com/IE/feedback/details/1736512/\n\t\trnoInnerhtml = /<script|<style|<link/i,\n\n\t\t// checked=\"checked\" or checked\n\t\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\t\trscriptTypeMasked = /^true\\/(.*)/,\n\t\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|--)|(?:\\]\\]|--)>\\s*$/g;\n\n// Prefer a tbody over its parent table for containing new rows\n\tfunction manipulationTarget( elem, content ) {\n\t\tif ( nodeName( elem, \"table\" ) &&\n\t\t\tnodeName( content.nodeType !== 11 ? content : content.firstChild, \"tr\" ) ) {\n\n\t\t\treturn jQuery( \">tbody\", elem )[ 0 ] || elem;\n\t\t}\n\n\t\treturn elem;\n\t}\n\n// Replace/restore the type attribute of script elements for safe DOM manipulation\n\tfunction disableScript( elem ) {\n\t\telem.type = ( elem.getAttribute( \"type\" ) !== null ) + \"/\" + elem.type;\n\t\treturn elem;\n\t}\n\tfunction restoreScript( elem ) {\n\t\tvar match = rscriptTypeMasked.exec( elem.type );\n\n\t\tif ( match ) {\n\t\t\telem.type = match[ 1 ];\n\t\t} else {\n\t\t\telem.removeAttribute( \"type\" );\n\t\t}\n\n\t\treturn elem;\n\t}\n\n\tfunction cloneCopyEvent( src, dest ) {\n\t\tvar i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;\n\n\t\tif ( dest.nodeType !== 1 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// 1. Copy private data: events, handlers, etc.\n\t\tif ( dataPriv.hasData( src ) ) {\n\t\t\tpdataOld = dataPriv.access( src );\n\t\t\tpdataCur = dataPriv.set( dest, pdataOld );\n\t\t\tevents = pdataOld.events;\n\n\t\t\tif ( events ) {\n\t\t\t\tdelete pdataCur.handle;\n\t\t\t\tpdataCur.events = {};\n\n\t\t\t\tfor ( type in events ) {\n\t\t\t\t\tfor ( i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\t\t\tjQuery.event.add( dest, type, events[ type ][ i ] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// 2. Copy user data\n\t\tif ( dataUser.hasData( src ) ) {\n\t\t\tudataOld = dataUser.access( src );\n\t\t\tudataCur = jQuery.extend( {}, udataOld );\n\n\t\t\tdataUser.set( dest, udataCur );\n\t\t}\n\t}\n\n// Fix IE bugs, see support tests\n\tfunction fixInput( src, dest ) {\n\t\tvar nodeName = dest.nodeName.toLowerCase();\n\n\t\t// Fails to persist the checked state of a cloned checkbox or radio button.\n\t\tif ( nodeName === \"input\" && rcheckableType.test( src.type ) ) {\n\t\t\tdest.checked = src.checked;\n\n\t\t\t// Fails to return the selected option to the default selected state when cloning options\n\t\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\t\tdest.defaultValue = src.defaultValue;\n\t\t}\n\t}\n\n\tfunction domManip( collection, args, callback, ignored ) {\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 = collection.length,\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( l > 1 && typeof value === \"string\" &&\n\t\t\t!support.checkClone && rchecked.test( value ) ) ) {\n\t\t\treturn collection.each( function( index ) {\n\t\t\t\tvar self = collection.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\tdomManip( self, args, callback, ignored );\n\t\t\t} );\n\t\t}\n\n\t\tif ( l ) {\n\t\t\tfragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored );\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\t// Require either new content or an interest in ignored elements to invoke the callback\n\t\t\tif ( first || ignored ) {\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\n\t\t\t\t// 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\n\t\t\t\t\t\t\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t\t\t\t\t\t\t// push.apply(_, arraylike) throws on ancient WebKit\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( collection[ 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!dataPriv.access( node, \"globalEval\" ) &&\n\t\t\t\t\t\t\tjQuery.contains( doc, node ) ) {\n\n\t\t\t\t\t\t\tif ( node.src ) {\n\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\tDOMEval( node.textContent.replace( rcleanScript, \"\" ), doc );\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 collection;\n\t}\n\n\tfunction remove( elem, selector, keepData ) {\n\t\tvar node,\n\t\t\tnodes = selector ? jQuery.filter( selector, elem ) : elem,\n\t\t\ti = 0;\n\n\t\tfor ( ; ( node = nodes[ i ] ) != null; i++ ) {\n\t\t\tif ( !keepData && node.nodeType === 1 ) {\n\t\t\t\tjQuery.cleanData( getAll( node ) );\n\t\t\t}\n\n\t\t\tif ( node.parentNode ) {\n\t\t\t\tif ( keepData && jQuery.contains( node.ownerDocument, node ) ) {\n\t\t\t\t\tsetGlobalEval( getAll( node, \"script\" ) );\n\t\t\t\t}\n\t\t\t\tnode.parentNode.removeChild( node );\n\t\t\t}\n\t\t}\n\n\t\treturn elem;\n\t}\n\n\tjQuery.extend( {\n\t\thtmlPrefilter: function( html ) {\n\t\t\treturn html.replace( rxhtmlTag, \"<$1></$2>\" );\n\t\t},\n\n\t\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\t\tvar i, l, srcElements, destElements,\n\t\t\t\tclone = elem.cloneNode( true ),\n\t\t\t\tinPage = jQuery.contains( elem.ownerDocument, elem );\n\n\t\t\t// Fix IE cloning issues\n\t\t\tif ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&\n\t\t\t\t!jQuery.isXMLDoc( elem ) ) {\n\n\t\t\t\t// We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2\n\t\t\t\tdestElements = getAll( clone );\n\t\t\t\tsrcElements = getAll( elem );\n\n\t\t\t\tfor ( i = 0, l = srcElements.length; i < l; i++ ) {\n\t\t\t\t\tfixInput( srcElements[ i ], destElements[ i ] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Copy the events from the original to the clone\n\t\t\tif ( dataAndEvents ) {\n\t\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\t\tsrcElements = srcElements || getAll( elem );\n\t\t\t\t\tdestElements = destElements || getAll( clone );\n\n\t\t\t\t\tfor ( i = 0, l = srcElements.length; i < l; i++ ) {\n\t\t\t\t\t\tcloneCopyEvent( srcElements[ i ], destElements[ i ] );\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tcloneCopyEvent( elem, clone );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Preserve script evaluation history\n\t\t\tdestElements = getAll( clone, \"script\" );\n\t\t\tif ( destElements.length > 0 ) {\n\t\t\t\tsetGlobalEval( destElements, !inPage && getAll( elem, \"script\" ) );\n\t\t\t}\n\n\t\t\t// Return the cloned set\n\t\t\treturn clone;\n\t\t},\n\n\t\tcleanData: function( elems ) {\n\t\t\tvar data, elem, type,\n\t\t\t\tspecial = jQuery.event.special,\n\t\t\t\ti = 0;\n\n\t\t\tfor ( ; ( elem = elems[ i ] ) !== undefined; i++ ) {\n\t\t\t\tif ( acceptData( elem ) ) {\n\t\t\t\t\tif ( ( data = elem[ dataPriv.expando ] ) ) {\n\t\t\t\t\t\tif ( data.events ) {\n\t\t\t\t\t\t\tfor ( type in data.events ) {\n\t\t\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\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\t} else {\n\t\t\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\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// Support: Chrome <=35 - 45+\n\t\t\t\t\t\t// Assign undefined instead of using delete, see Data#remove\n\t\t\t\t\t\telem[ dataPriv.expando ] = undefined;\n\t\t\t\t\t}\n\t\t\t\t\tif ( elem[ dataUser.expando ] ) {\n\n\t\t\t\t\t\t// Support: Chrome <=35 - 45+\n\t\t\t\t\t\t// Assign undefined instead of using delete, see Data#remove\n\t\t\t\t\t\telem[ dataUser.expando ] = undefined;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} );\n\n\tjQuery.fn.extend( {\n\t\tdetach: function( selector ) {\n\t\t\treturn remove( this, selector, true );\n\t\t},\n\n\t\tremove: function( selector ) {\n\t\t\treturn remove( this, selector );\n\t\t},\n\n\t\ttext: function( value ) {\n\t\t\treturn access( this, function( value ) {\n\t\t\t\treturn value === undefined ?\n\t\t\t\t\tjQuery.text( this ) :\n\t\t\t\t\tthis.empty().each( function() {\n\t\t\t\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\t\t\t\tthis.textContent = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\t\t\t}, null, value, arguments.length );\n\t\t},\n\n\t\tappend: function() {\n\t\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\t\tvar target = manipulationTarget( this, elem );\n\t\t\t\t\ttarget.appendChild( elem );\n\t\t\t\t}\n\t\t\t} );\n\t\t},\n\n\t\tprepend: function() {\n\t\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\t\tvar target = manipulationTarget( this, elem );\n\t\t\t\t\ttarget.insertBefore( elem, target.firstChild );\n\t\t\t\t}\n\t\t\t} );\n\t\t},\n\n\t\tbefore: function() {\n\t\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\t\tif ( this.parentNode ) {\n\t\t\t\t\tthis.parentNode.insertBefore( elem, this );\n\t\t\t\t}\n\t\t\t} );\n\t\t},\n\n\t\tafter: function() {\n\t\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\t\tif ( this.parentNode ) {\n\t\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n\t\t\t\t}\n\t\t\t} );\n\t\t},\n\n\t\tempty: function() {\n\t\t\tvar elem,\n\t\t\t\ti = 0;\n\n\t\t\tfor ( ; ( elem = this[ i ] ) != null; i++ ) {\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\n\t\t\t\t\t// Prevent memory leaks\n\t\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\n\t\t\t\t\t// Remove any remaining nodes\n\t\t\t\t\telem.textContent = \"\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t},\n\n\t\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\t\treturn this.map( function() {\n\t\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t\t} );\n\t\t},\n\n\t\thtml: function( value ) {\n\t\t\treturn access( this, function( value ) {\n\t\t\t\tvar elem = this[ 0 ] || {},\n\t\t\t\t\ti = 0,\n\t\t\t\t\tl = this.length;\n\n\t\t\t\tif ( value === undefined && elem.nodeType === 1 ) {\n\t\t\t\t\treturn elem.innerHTML;\n\t\t\t\t}\n\n\t\t\t\t// See if we can take a shortcut and just use innerHTML\n\t\t\t\tif ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n\t\t\t\t\t!wrapMap[ ( rtagName.exec( value ) || [ \"\", \"\" ] )[ 1 ].toLowerCase() ] ) {\n\n\t\t\t\t\tvalue = jQuery.htmlPrefilter( value );\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\t\t\telem = this[ i ] || {};\n\n\t\t\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\t\t\t\t\t\t\t\telem.innerHTML = value;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\telem = 0;\n\n\t\t\t\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t\t\t} catch ( e ) {}\n\t\t\t\t}\n\n\t\t\t\tif ( elem ) {\n\t\t\t\t\tthis.empty().append( value );\n\t\t\t\t}\n\t\t\t}, null, value, arguments.length );\n\t\t},\n\n\t\treplaceWith: function() {\n\t\t\tvar ignored = [];\n\n\t\t\t// Make the changes, replacing each non-ignored context element with the new content\n\t\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\t\tvar parent = this.parentNode;\n\n\t\t\t\tif ( jQuery.inArray( this, ignored ) < 0 ) {\n\t\t\t\t\tjQuery.cleanData( getAll( this ) );\n\t\t\t\t\tif ( parent ) {\n\t\t\t\t\t\tparent.replaceChild( elem, this );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Force callback invocation\n\t\t\t}, ignored );\n\t\t}\n\t} );\n\n\tjQuery.each( {\n\t\tappendTo: \"append\",\n\t\tprependTo: \"prepend\",\n\t\tinsertBefore: \"before\",\n\t\tinsertAfter: \"after\",\n\t\treplaceAll: \"replaceWith\"\n\t}, function( name, original ) {\n\t\tjQuery.fn[ name ] = function( selector ) {\n\t\t\tvar elems,\n\t\t\t\tret = [],\n\t\t\t\tinsert = jQuery( selector ),\n\t\t\t\tlast = insert.length - 1,\n\t\t\t\ti = 0;\n\n\t\t\tfor ( ; i <= last; i++ ) {\n\t\t\t\telems = i === last ? this : this.clone( true );\n\t\t\t\tjQuery( insert[ i ] )[ original ]( elems );\n\n\t\t\t\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t\t\t\t// .get() because push.apply(_, arraylike) throws on ancient WebKit\n\t\t\t\tpush.apply( ret, elems.get() );\n\t\t\t}\n\n\t\t\treturn this.pushStack( ret );\n\t\t};\n\t} );\n\tvar rmargin = ( /^margin/ );\n\n\tvar rnumnonpx = new RegExp( \"^(\" + pnum + \")(?!px)[a-z%]+$\", \"i\" );\n\n\tvar getStyles = function( elem ) {\n\n\t\t// Support: IE <=11 only, 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\tvar view = elem.ownerDocument.defaultView;\n\n\t\tif ( !view || !view.opener ) {\n\t\t\tview = window;\n\t\t}\n\n\t\treturn view.getComputedStyle( elem );\n\t};\n\n\n\n\t( function() {\n\n\t\t// Executing both pixelPosition & boxSizingReliable tests require only one layout\n\t\t// so they're executed at the same time to save the second computation.\n\t\tfunction computeStyleTests() {\n\n\t\t\t// This is a singleton, we need to execute it only once\n\t\t\tif ( !div ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tdiv.style.cssText =\n\t\t\t\t\"box-sizing:border-box;\" +\n\t\t\t\t\"position:relative;display:block;\" +\n\t\t\t\t\"margin:auto;border:1px;padding:1px;\" +\n\t\t\t\t\"top:1%;width:50%\";\n\t\t\tdiv.innerHTML = \"\";\n\t\t\tdocumentElement.appendChild( container );\n\n\t\t\tvar divStyle = window.getComputedStyle( div );\n\t\t\tpixelPositionVal = divStyle.top !== \"1%\";\n\n\t\t\t// Support: Android 4.0 - 4.3 only, Firefox <=3 - 44\n\t\t\treliableMarginLeftVal = divStyle.marginLeft === \"2px\";\n\t\t\tboxSizingReliableVal = divStyle.width === \"4px\";\n\n\t\t\t// Support: Android 4.0 - 4.3 only\n\t\t\t// Some styles come back with percentage values, even though they shouldn't\n\t\t\tdiv.style.marginRight = \"50%\";\n\t\t\tpixelMarginRightVal = divStyle.marginRight === \"4px\";\n\n\t\t\tdocumentElement.removeChild( container );\n\n\t\t\t// Nullify the div so it wouldn't be stored in the memory and\n\t\t\t// it will also be a sign that checks already performed\n\t\t\tdiv = null;\n\t\t}\n\n\t\tvar pixelPositionVal, boxSizingReliableVal, pixelMarginRightVal, reliableMarginLeftVal,\n\t\t\tcontainer = document.createElement( \"div\" ),\n\t\t\tdiv = document.createElement( \"div\" );\n\n\t\t// Finish early in limited (non-browser) environments\n\t\tif ( !div.style ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Support: IE <=9 - 11 only\n\t\t// Style of cloned element affects source element cloned (#8908)\n\t\tdiv.style.backgroundClip = \"content-box\";\n\t\tdiv.cloneNode( true ).style.backgroundClip = \"\";\n\t\tsupport.clearCloneStyle = div.style.backgroundClip === \"content-box\";\n\n\t\tcontainer.style.cssText = \"border:0;width:8px;height:0;top:0;left:-9999px;\" +\n\t\t\t\"padding:0;margin-top:1px;position:absolute\";\n\t\tcontainer.appendChild( div );\n\n\t\tjQuery.extend( support, {\n\t\t\tpixelPosition: function() {\n\t\t\t\tcomputeStyleTests();\n\t\t\t\treturn pixelPositionVal;\n\t\t\t},\n\t\t\tboxSizingReliable: function() {\n\t\t\t\tcomputeStyleTests();\n\t\t\t\treturn boxSizingReliableVal;\n\t\t\t},\n\t\t\tpixelMarginRight: function() {\n\t\t\t\tcomputeStyleTests();\n\t\t\t\treturn pixelMarginRightVal;\n\t\t\t},\n\t\t\treliableMarginLeft: function() {\n\t\t\t\tcomputeStyleTests();\n\t\t\t\treturn reliableMarginLeftVal;\n\t\t\t}\n\t\t} );\n\t} )();\n\n\n\tfunction curCSS( elem, name, computed ) {\n\t\tvar width, minWidth, maxWidth, ret,\n\n\t\t\t// Support: Firefox 51+\n\t\t\t// Retrieving style before computed somehow\n\t\t\t// fixes an issue with getting wrong values\n\t\t\t// on detached elements\n\t\t\tstyle = elem.style;\n\n\t\tcomputed = computed || getStyles( elem );\n\n\t\t// getPropertyValue is needed for:\n\t\t//   .css('filter') (IE 9 only, #12537)\n\t\t//   .css('--customProperty) (#3144)\n\t\tif ( computed ) {\n\t\t\tret = computed.getPropertyValue( name ) || computed[ name ];\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// Android Browser returns percentage for some values,\n\t\t\t// but width seems to be reliably pixels.\n\t\t\t// This is against the CSSOM draft spec:\n\t\t\t// https://drafts.csswg.org/cssom/#resolved-values\n\t\t\tif ( !support.pixelMarginRight() && 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 !== undefined ?\n\n\t\t\t// Support: IE <=9 - 11 only\n\t\t\t// IE returns zIndex value as an integer.\n\t\tret + \"\" :\n\t\t\tret;\n\t}\n\n\n\tfunction addGetHookIf( conditionFn, hookFn ) {\n\n\t\t// Define the hook, we'll check on the first run if it's really needed.\n\t\treturn {\n\t\t\tget: function() {\n\t\t\t\tif ( conditionFn() ) {\n\n\t\t\t\t\t// Hook not needed (or it's not possible to use it due\n\t\t\t\t\t// to missing dependency), remove it.\n\t\t\t\t\tdelete this.get;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Hook needed; redefine it so that the support test is not executed again.\n\t\t\t\treturn ( this.get = hookFn ).apply( this, arguments );\n\t\t\t}\n\t\t};\n\t}\n\n\n\tvar\n\n\t\t// Swappable if display is none or starts with table\n\t\t// except \"table\", \"table-cell\", or \"table-caption\"\n\t\t// See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display\n\t\trdisplayswap = /^(none|table(?!-c[ea]).+)/,\n\t\trcustomProp = /^--/,\n\t\tcssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\t\tcssNormalTransform = {\n\t\t\tletterSpacing: \"0\",\n\t\t\tfontWeight: \"400\"\n\t\t},\n\n\t\tcssPrefixes = [ \"Webkit\", \"Moz\", \"ms\" ],\n\t\temptyStyle = document.createElement( \"div\" ).style;\n\n// Return a css property mapped to a potentially vendor prefixed property\n\tfunction vendorPropName( name ) {\n\n\t\t// Shortcut for names that are not vendor prefixed\n\t\tif ( name in emptyStyle ) {\n\t\t\treturn name;\n\t\t}\n\n\t\t// Check for vendor prefixed names\n\t\tvar capName = name[ 0 ].toUpperCase() + name.slice( 1 ),\n\t\t\ti = cssPrefixes.length;\n\n\t\twhile ( i-- ) {\n\t\t\tname = cssPrefixes[ i ] + capName;\n\t\t\tif ( name in emptyStyle ) {\n\t\t\t\treturn name;\n\t\t\t}\n\t\t}\n\t}\n\n// Return a property mapped along what jQuery.cssProps suggests or to\n// a vendor prefixed property.\n\tfunction finalPropName( name ) {\n\t\tvar ret = jQuery.cssProps[ name ];\n\t\tif ( !ret ) {\n\t\t\tret = jQuery.cssProps[ name ] = vendorPropName( name ) || name;\n\t\t}\n\t\treturn ret;\n\t}\n\n\tfunction setPositiveNumber( elem, value, subtract ) {\n\n\t\t// Any relative (+/-) values have already been\n\t\t// normalized at this point\n\t\tvar matches = rcssNum.exec( value );\n\t\treturn matches ?\n\n\t\t\t// Guard against undefined \"subtract\", e.g., when used as in cssHooks\n\t\tMath.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || \"px\" ) :\n\t\t\tvalue;\n\t}\n\n\tfunction augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {\n\t\tvar i,\n\t\t\tval = 0;\n\n\t\t// If we already have the right measurement, avoid augmentation\n\t\tif ( extra === ( isBorderBox ? \"border\" : \"content\" ) ) {\n\t\t\ti = 4;\n\n\t\t\t// Otherwise initialize for horizontal or vertical properties\n\t\t} else {\n\t\t\ti = name === \"width\" ? 1 : 0;\n\t\t}\n\n\t\tfor ( ; i < 4; i += 2 ) {\n\n\t\t\t// Both box models exclude margin, so add it if we want it\n\t\t\tif ( extra === \"margin\" ) {\n\t\t\t\tval += jQuery.css( elem, extra + cssExpand[ i ], true, styles );\n\t\t\t}\n\n\t\t\tif ( isBorderBox ) {\n\n\t\t\t\t// border-box includes padding, so remove it if we want content\n\t\t\t\tif ( extra === \"content\" ) {\n\t\t\t\t\tval -= jQuery.css( elem, \"padding\" + cssExpand[ i ], true, styles );\n\t\t\t\t}\n\n\t\t\t\t// At this point, extra isn't border nor margin, so remove border\n\t\t\t\tif ( extra !== \"margin\" ) {\n\t\t\t\t\tval -= jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t// At this point, extra isn't content, so add padding\n\t\t\t\tval += jQuery.css( elem, \"padding\" + cssExpand[ i ], true, styles );\n\n\t\t\t\t// At this point, extra isn't content nor padding, so add border\n\t\t\t\tif ( extra !== \"padding\" ) {\n\t\t\t\t\tval += jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn val;\n\t}\n\n\tfunction getWidthOrHeight( elem, name, extra ) {\n\n\t\t// Start with computed style\n\t\tvar valueIsBorderBox,\n\t\t\tstyles = getStyles( elem ),\n\t\t\tval = curCSS( elem, name, styles ),\n\t\t\tisBorderBox = jQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\";\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// Fall back to offsetWidth/Height when value is \"auto\"\n\t\t// This happens for inline elements with no explicit setting (gh-3571)\n\t\tif ( val === \"auto\" ) {\n\t\t\tval = elem[ \"offset\" + name[ 0 ].toUpperCase() + name.slice( 1 ) ];\n\t\t}\n\n\t\t// Normalize \"\", auto, and prepare for extra\n\t\tval = parseFloat( val ) || 0;\n\n\t\t// Use the active box-sizing model to add/subtract irrelevant styles\n\t\treturn ( val +\n\t\t\t\taugmentWidthOrHeight(\n\t\t\t\t\telem,\n\t\t\t\t\tname,\n\t\t\t\t\textra || ( isBorderBox ? \"border\" : \"content\" ),\n\t\t\t\t\tvalueIsBorderBox,\n\t\t\t\t\tstyles\n\t\t\t\t)\n\t\t\t) + \"px\";\n\t}\n\n\tjQuery.extend( {\n\n\t\t// Add in style property hooks for overriding the default\n\t\t// behavior of getting and setting a style property\n\t\tcssHooks: {\n\t\t\topacity: {\n\t\t\t\tget: function( elem, computed ) {\n\t\t\t\t\tif ( computed ) {\n\n\t\t\t\t\t\t// We should always get a number back from opacity\n\t\t\t\t\t\tvar ret = curCSS( elem, \"opacity\" );\n\t\t\t\t\t\treturn ret === \"\" ? \"1\" : ret;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t// Don't automatically add \"px\" to these possibly-unitless properties\n\t\tcssNumber: {\n\t\t\t\"animationIterationCount\": true,\n\t\t\t\"columnCount\": true,\n\t\t\t\"fillOpacity\": true,\n\t\t\t\"flexGrow\": true,\n\t\t\t\"flexShrink\": true,\n\t\t\t\"fontWeight\": true,\n\t\t\t\"lineHeight\": true,\n\t\t\t\"opacity\": true,\n\t\t\t\"order\": true,\n\t\t\t\"orphans\": true,\n\t\t\t\"widows\": true,\n\t\t\t\"zIndex\": true,\n\t\t\t\"zoom\": true\n\t\t},\n\n\t\t// Add in properties whose names you wish to fix before\n\t\t// setting or getting the value\n\t\tcssProps: {\n\t\t\t\"float\": \"cssFloat\"\n\t\t},\n\n\t\t// Get and set the style property on a DOM Node\n\t\tstyle: function( elem, name, value, extra ) {\n\n\t\t\t// Don't set styles on text and comment nodes\n\t\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Make sure that we're working with the right name\n\t\t\tvar ret, type, hooks,\n\t\t\t\torigName = jQuery.camelCase( name ),\n\t\t\t\tisCustomProp = rcustomProp.test( name ),\n\t\t\t\tstyle = elem.style;\n\n\t\t\t// Make sure that we're working with the right name. We don't\n\t\t\t// want to query the value if it is a CSS custom property\n\t\t\t// since they are user-defined.\n\t\t\tif ( !isCustomProp ) {\n\t\t\t\tname = finalPropName( origName );\n\t\t\t}\n\n\t\t\t// Gets hook for the prefixed version, then unprefixed version\n\t\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n\t\t\t// Check if we're setting a value\n\t\t\tif ( value !== undefined ) {\n\t\t\t\ttype = typeof value;\n\n\t\t\t\t// Convert \"+=\" or \"-=\" to relative numbers (#7345)\n\t\t\t\tif ( type === \"string\" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) {\n\t\t\t\t\tvalue = adjustCSS( elem, name, ret );\n\n\t\t\t\t\t// Fixes bug #9237\n\t\t\t\t\ttype = \"number\";\n\t\t\t\t}\n\n\t\t\t\t// Make sure that null and NaN values aren't set (#7116)\n\t\t\t\tif ( value == null || value !== value ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// If a number was passed in, add the unit (except for certain CSS properties)\n\t\t\t\tif ( type === \"number\" ) {\n\t\t\t\t\tvalue += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? \"\" : \"px\" );\n\t\t\t\t}\n\n\t\t\t\t// background-* props affect original clone's values\n\t\t\t\tif ( !support.clearCloneStyle && value === \"\" && name.indexOf( \"background\" ) === 0 ) {\n\t\t\t\t\tstyle[ name ] = \"inherit\";\n\t\t\t\t}\n\n\t\t\t\t// If a hook was provided, use that value, otherwise just set the specified value\n\t\t\t\tif ( !hooks || !( \"set\" in hooks ) ||\n\t\t\t\t\t( value = hooks.set( elem, value, extra ) ) !== undefined ) {\n\n\t\t\t\t\tif ( isCustomProp ) {\n\t\t\t\t\t\tstyle.setProperty( name, value );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tstyle[ name ] = value;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\t\tif ( hooks && \"get\" in hooks &&\n\t\t\t\t\t( ret = hooks.get( elem, false, extra ) ) !== undefined ) {\n\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\t// Otherwise just get the value from the style object\n\t\t\t\treturn style[ name ];\n\t\t\t}\n\t\t},\n\n\t\tcss: function( elem, name, extra, styles ) {\n\t\t\tvar val, num, hooks,\n\t\t\t\torigName = jQuery.camelCase( name ),\n\t\t\t\tisCustomProp = rcustomProp.test( name );\n\n\t\t\t// Make sure that we're working with the right name. We don't\n\t\t\t// want to modify the value if it is a CSS custom property\n\t\t\t// since they are user-defined.\n\t\t\tif ( !isCustomProp ) {\n\t\t\t\tname = finalPropName( origName );\n\t\t\t}\n\n\t\t\t// Try prefixed name followed by the unprefixed name\n\t\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n\t\t\t// If a hook was provided get the computed value from there\n\t\t\tif ( hooks && \"get\" in hooks ) {\n\t\t\t\tval = hooks.get( elem, true, extra );\n\t\t\t}\n\n\t\t\t// Otherwise, if a way to get the computed value exists, use that\n\t\t\tif ( val === undefined ) {\n\t\t\t\tval = curCSS( elem, name, styles );\n\t\t\t}\n\n\t\t\t// Convert \"normal\" to computed value\n\t\t\tif ( val === \"normal\" && name in cssNormalTransform ) {\n\t\t\t\tval = cssNormalTransform[ name ];\n\t\t\t}\n\n\t\t\t// Make numeric if forced or a qualifier was provided and val looks numeric\n\t\t\tif ( extra === \"\" || extra ) {\n\t\t\t\tnum = parseFloat( val );\n\t\t\t\treturn extra === true || isFinite( num ) ? num || 0 : val;\n\t\t\t}\n\n\t\t\treturn val;\n\t\t}\n\t} );\n\n\tjQuery.each( [ \"height\", \"width\" ], function( i, name ) {\n\t\tjQuery.cssHooks[ name ] = {\n\t\t\tget: function( elem, computed, extra ) {\n\t\t\t\tif ( computed ) {\n\n\t\t\t\t\t// Certain elements can have dimension info if we invisibly show them\n\t\t\t\t\t// but it must have a current display style that would benefit\n\t\t\t\t\treturn rdisplayswap.test( jQuery.css( elem, \"display\" ) ) &&\n\n\t\t\t\t\t// Support: Safari 8+\n\t\t\t\t\t// Table columns in Safari have non-zero offsetWidth & zero\n\t\t\t\t\t// getBoundingClientRect().width unless display is changed.\n\t\t\t\t\t// Support: IE <=11 only\n\t\t\t\t\t// Running getBoundingClientRect on a disconnected node\n\t\t\t\t\t// in IE throws an error.\n\t\t\t\t\t( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ?\n\t\t\t\t\t\tswap( elem, cssShow, function() {\n\t\t\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t\t\t} ) :\n\t\t\t\t\t\tgetWidthOrHeight( elem, name, extra );\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tset: function( elem, value, extra ) {\n\t\t\t\tvar matches,\n\t\t\t\t\tstyles = extra && getStyles( elem ),\n\t\t\t\t\tsubtract = extra && augmentWidthOrHeight(\n\t\t\t\t\t\t\telem,\n\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\textra,\n\t\t\t\t\t\t\tjQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\",\n\t\t\t\t\t\t\tstyles\n\t\t\t\t\t\t);\n\n\t\t\t\t// Convert to pixels if value adjustment is needed\n\t\t\t\tif ( subtract && ( matches = rcssNum.exec( value ) ) &&\n\t\t\t\t\t( matches[ 3 ] || \"px\" ) !== \"px\" ) {\n\n\t\t\t\t\telem.style[ name ] = value;\n\t\t\t\t\tvalue = jQuery.css( elem, name );\n\t\t\t\t}\n\n\t\t\t\treturn setPositiveNumber( elem, value, subtract );\n\t\t\t}\n\t\t};\n\t} );\n\n\tjQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft,\n\t\tfunction( elem, computed ) {\n\t\t\tif ( computed ) {\n\t\t\t\treturn ( parseFloat( curCSS( elem, \"marginLeft\" ) ) ||\n\t\t\t\t\t\telem.getBoundingClientRect().left -\n\t\t\t\t\t\tswap( elem, { marginLeft: 0 }, function() {\n\t\t\t\t\t\t\treturn elem.getBoundingClientRect().left;\n\t\t\t\t\t\t} )\n\t\t\t\t\t) + \"px\";\n\t\t\t}\n\t\t}\n\t);\n\n// These hooks are used by animate to expand properties\n\tjQuery.each( {\n\t\tmargin: \"\",\n\t\tpadding: \"\",\n\t\tborder: \"Width\"\n\t}, function( prefix, suffix ) {\n\t\tjQuery.cssHooks[ prefix + suffix ] = {\n\t\t\texpand: function( value ) {\n\t\t\t\tvar i = 0,\n\t\t\t\t\texpanded = {},\n\n\t\t\t\t\t// Assumes a single number if not a string\n\t\t\t\t\tparts = typeof value === \"string\" ? value.split( \" \" ) : [ value ];\n\n\t\t\t\tfor ( ; i < 4; i++ ) {\n\t\t\t\t\texpanded[ prefix + cssExpand[ i ] + suffix ] =\n\t\t\t\t\t\tparts[ i ] || parts[ i - 2 ] || parts[ 0 ];\n\t\t\t\t}\n\n\t\t\t\treturn expanded;\n\t\t\t}\n\t\t};\n\n\t\tif ( !rmargin.test( prefix ) ) {\n\t\t\tjQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;\n\t\t}\n\t} );\n\n\tjQuery.fn.extend( {\n\t\tcss: function( name, value ) {\n\t\t\treturn access( this, function( elem, name, value ) {\n\t\t\t\tvar styles, len,\n\t\t\t\t\tmap = {},\n\t\t\t\t\ti = 0;\n\n\t\t\t\tif ( Array.isArray( name ) ) {\n\t\t\t\t\tstyles = getStyles( elem );\n\t\t\t\t\tlen = name.length;\n\n\t\t\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t\t\tmap[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );\n\t\t\t\t\t}\n\n\t\t\t\t\treturn map;\n\t\t\t\t}\n\n\t\t\t\treturn value !== undefined ?\n\t\t\t\t\tjQuery.style( elem, name, value ) :\n\t\t\t\t\tjQuery.css( elem, name );\n\t\t\t}, name, value, arguments.length > 1 );\n\t\t}\n\t} );\n\n\n\tfunction Tween( elem, options, prop, end, easing ) {\n\t\treturn new Tween.prototype.init( elem, options, prop, end, easing );\n\t}\n\tjQuery.Tween = Tween;\n\n\tTween.prototype = {\n\t\tconstructor: Tween,\n\t\tinit: function( elem, options, prop, end, easing, unit ) {\n\t\t\tthis.elem = elem;\n\t\t\tthis.prop = prop;\n\t\t\tthis.easing = easing || jQuery.easing._default;\n\t\t\tthis.options = options;\n\t\t\tthis.start = this.now = this.cur();\n\t\t\tthis.end = end;\n\t\t\tthis.unit = unit || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" );\n\t\t},\n\t\tcur: function() {\n\t\t\tvar hooks = Tween.propHooks[ this.prop ];\n\n\t\t\treturn hooks && hooks.get ?\n\t\t\t\thooks.get( this ) :\n\t\t\t\tTween.propHooks._default.get( this );\n\t\t},\n\t\trun: function( percent ) {\n\t\t\tvar eased,\n\t\t\t\thooks = Tween.propHooks[ this.prop ];\n\n\t\t\tif ( this.options.duration ) {\n\t\t\t\tthis.pos = eased = jQuery.easing[ this.easing ](\n\t\t\t\t\tpercent, this.options.duration * percent, 0, 1, this.options.duration\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tthis.pos = eased = percent;\n\t\t\t}\n\t\t\tthis.now = ( this.end - this.start ) * eased + this.start;\n\n\t\t\tif ( this.options.step ) {\n\t\t\t\tthis.options.step.call( this.elem, this.now, this );\n\t\t\t}\n\n\t\t\tif ( hooks && hooks.set ) {\n\t\t\t\thooks.set( this );\n\t\t\t} else {\n\t\t\t\tTween.propHooks._default.set( this );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t};\n\n\tTween.prototype.init.prototype = Tween.prototype;\n\n\tTween.propHooks = {\n\t\t_default: {\n\t\t\tget: function( tween ) {\n\t\t\t\tvar result;\n\n\t\t\t\t// Use a property on the element directly when it is not a DOM element,\n\t\t\t\t// or when there is no matching style property that exists.\n\t\t\t\tif ( tween.elem.nodeType !== 1 ||\n\t\t\t\t\ttween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) {\n\t\t\t\t\treturn tween.elem[ tween.prop ];\n\t\t\t\t}\n\n\t\t\t\t// Passing an empty string as a 3rd parameter to .css will automatically\n\t\t\t\t// attempt a parseFloat and fallback to a string if the parse fails.\n\t\t\t\t// Simple values such as \"10px\" are parsed to Float;\n\t\t\t\t// complex values such as \"rotate(1rad)\" are returned as-is.\n\t\t\t\tresult = jQuery.css( tween.elem, tween.prop, \"\" );\n\n\t\t\t\t// Empty strings, null, undefined and \"auto\" are converted to 0.\n\t\t\t\treturn !result || result === \"auto\" ? 0 : result;\n\t\t\t},\n\t\t\tset: function( tween ) {\n\n\t\t\t\t// Use step hook for back compat.\n\t\t\t\t// Use cssHook if its there.\n\t\t\t\t// Use .style if available and use plain properties where available.\n\t\t\t\tif ( jQuery.fx.step[ tween.prop ] ) {\n\t\t\t\t\tjQuery.fx.step[ tween.prop ]( tween );\n\t\t\t\t} else if ( tween.elem.nodeType === 1 &&\n\t\t\t\t\t( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null ||\n\t\t\t\t\tjQuery.cssHooks[ tween.prop ] ) ) {\n\t\t\t\t\tjQuery.style( tween.elem, tween.prop, tween.now + tween.unit );\n\t\t\t\t} else {\n\t\t\t\t\ttween.elem[ tween.prop ] = tween.now;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n// Support: IE <=9 only\n// Panic based approach to setting things on disconnected nodes\n\tTween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {\n\t\tset: function( tween ) {\n\t\t\tif ( tween.elem.nodeType && tween.elem.parentNode ) {\n\t\t\t\ttween.elem[ tween.prop ] = tween.now;\n\t\t\t}\n\t\t}\n\t};\n\n\tjQuery.easing = {\n\t\tlinear: function( p ) {\n\t\t\treturn p;\n\t\t},\n\t\tswing: function( p ) {\n\t\t\treturn 0.5 - Math.cos( p * Math.PI ) / 2;\n\t\t},\n\t\t_default: \"swing\"\n\t};\n\n\tjQuery.fx = Tween.prototype.init;\n\n// Back compat <1.8 extension point\n\tjQuery.fx.step = {};\n\n\n\n\n\tvar\n\t\tfxNow, inProgress,\n\t\trfxtypes = /^(?:toggle|show|hide)$/,\n\t\trrun = /queueHooks$/;\n\n\tfunction schedule() {\n\t\tif ( inProgress ) {\n\t\t\tif ( document.hidden === false && window.requestAnimationFrame ) {\n\t\t\t\twindow.requestAnimationFrame( schedule );\n\t\t\t} else {\n\t\t\t\twindow.setTimeout( schedule, jQuery.fx.interval );\n\t\t\t}\n\n\t\t\tjQuery.fx.tick();\n\t\t}\n\t}\n\n// Animations created synchronously will run synchronously\n\tfunction createFxNow() {\n\t\twindow.setTimeout( function() {\n\t\t\tfxNow = undefined;\n\t\t} );\n\t\treturn ( fxNow = jQuery.now() );\n\t}\n\n// Generate parameters to create a standard animation\n\tfunction genFx( type, includeWidth ) {\n\t\tvar which,\n\t\t\ti = 0,\n\t\t\tattrs = { height: type };\n\n\t\t// If we include width, step value is 1 to do all cssExpand values,\n\t\t// otherwise step value is 2 to skip over Left and Right\n\t\tincludeWidth = includeWidth ? 1 : 0;\n\t\tfor ( ; i < 4; i += 2 - includeWidth ) {\n\t\t\twhich = cssExpand[ i ];\n\t\t\tattrs[ \"margin\" + which ] = attrs[ \"padding\" + which ] = type;\n\t\t}\n\n\t\tif ( includeWidth ) {\n\t\t\tattrs.opacity = attrs.width = type;\n\t\t}\n\n\t\treturn attrs;\n\t}\n\n\tfunction createTween( value, prop, animation ) {\n\t\tvar tween,\n\t\t\tcollection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ \"*\" ] ),\n\t\t\tindex = 0,\n\t\t\tlength = collection.length;\n\t\tfor ( ; index < length; index++ ) {\n\t\t\tif ( ( tween = collection[ index ].call( animation, prop, value ) ) ) {\n\n\t\t\t\t// We're done with this property\n\t\t\t\treturn tween;\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction defaultPrefilter( elem, props, opts ) {\n\t\tvar prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display,\n\t\t\tisBox = \"width\" in props || \"height\" in props,\n\t\t\tanim = this,\n\t\t\torig = {},\n\t\t\tstyle = elem.style,\n\t\t\thidden = elem.nodeType && isHiddenWithinTree( elem ),\n\t\t\tdataShow = dataPriv.get( elem, \"fxshow\" );\n\n\t\t// Queue-skipping animations hijack the fx hooks\n\t\tif ( !opts.queue ) {\n\t\t\thooks = jQuery._queueHooks( elem, \"fx\" );\n\t\t\tif ( hooks.unqueued == null ) {\n\t\t\t\thooks.unqueued = 0;\n\t\t\t\toldfire = hooks.empty.fire;\n\t\t\t\thooks.empty.fire = function() {\n\t\t\t\t\tif ( !hooks.unqueued ) {\n\t\t\t\t\t\toldfire();\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t}\n\t\t\thooks.unqueued++;\n\n\t\t\tanim.always( function() {\n\n\t\t\t\t// Ensure the complete handler is called before this completes\n\t\t\t\tanim.always( function() {\n\t\t\t\t\thooks.unqueued--;\n\t\t\t\t\tif ( !jQuery.queue( elem, \"fx\" ).length ) {\n\t\t\t\t\t\thooks.empty.fire();\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t} );\n\t\t}\n\n\t\t// Detect show/hide animations\n\t\tfor ( prop in props ) {\n\t\t\tvalue = props[ prop ];\n\t\t\tif ( rfxtypes.test( value ) ) {\n\t\t\t\tdelete props[ prop ];\n\t\t\t\ttoggle = toggle || value === \"toggle\";\n\t\t\t\tif ( value === ( hidden ? \"hide\" : \"show\" ) ) {\n\n\t\t\t\t\t// Pretend to be hidden if this is a \"show\" and\n\t\t\t\t\t// there is still data from a stopped show/hide\n\t\t\t\t\tif ( value === \"show\" && dataShow && dataShow[ prop ] !== undefined ) {\n\t\t\t\t\t\thidden = true;\n\n\t\t\t\t\t\t// Ignore all other no-op show/hide data\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\torig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );\n\t\t\t}\n\t\t}\n\n\t\t// Bail out if this is a no-op like .hide().hide()\n\t\tpropTween = !jQuery.isEmptyObject( props );\n\t\tif ( !propTween && jQuery.isEmptyObject( orig ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Restrict \"overflow\" and \"display\" styles during box animations\n\t\tif ( isBox && elem.nodeType === 1 ) {\n\n\t\t\t// Support: IE <=9 - 11, Edge 12 - 13\n\t\t\t// Record all 3 overflow attributes because IE does not infer the shorthand\n\t\t\t// from identically-valued overflowX and overflowY\n\t\t\topts.overflow = [ style.overflow, style.overflowX, style.overflowY ];\n\n\t\t\t// Identify a display type, preferring old show/hide data over the CSS cascade\n\t\t\trestoreDisplay = dataShow && dataShow.display;\n\t\t\tif ( restoreDisplay == null ) {\n\t\t\t\trestoreDisplay = dataPriv.get( elem, \"display\" );\n\t\t\t}\n\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\t\t\tif ( display === \"none\" ) {\n\t\t\t\tif ( restoreDisplay ) {\n\t\t\t\t\tdisplay = restoreDisplay;\n\t\t\t\t} else {\n\n\t\t\t\t\t// Get nonempty value(s) by temporarily forcing visibility\n\t\t\t\t\tshowHide( [ elem ], true );\n\t\t\t\t\trestoreDisplay = elem.style.display || restoreDisplay;\n\t\t\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\t\t\t\t\tshowHide( [ elem ] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Animate inline elements as inline-block\n\t\t\tif ( display === \"inline\" || display === \"inline-block\" && restoreDisplay != null ) {\n\t\t\t\tif ( jQuery.css( elem, \"float\" ) === \"none\" ) {\n\n\t\t\t\t\t// Restore the original display value at the end of pure show/hide animations\n\t\t\t\t\tif ( !propTween ) {\n\t\t\t\t\t\tanim.done( function() {\n\t\t\t\t\t\t\tstyle.display = restoreDisplay;\n\t\t\t\t\t\t} );\n\t\t\t\t\t\tif ( restoreDisplay == null ) {\n\t\t\t\t\t\t\tdisplay = style.display;\n\t\t\t\t\t\t\trestoreDisplay = display === \"none\" ? \"\" : display;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tstyle.display = \"inline-block\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( opts.overflow ) {\n\t\t\tstyle.overflow = \"hidden\";\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\n\t\t// Implement show/hide animations\n\t\tpropTween = false;\n\t\tfor ( prop in orig ) {\n\n\t\t\t// General show/hide setup for this element animation\n\t\t\tif ( !propTween ) {\n\t\t\t\tif ( dataShow ) {\n\t\t\t\t\tif ( \"hidden\" in dataShow ) {\n\t\t\t\t\t\thidden = dataShow.hidden;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tdataShow = dataPriv.access( elem, \"fxshow\", { display: restoreDisplay } );\n\t\t\t\t}\n\n\t\t\t\t// Store hidden/visible for toggle so `.stop().toggle()` \"reverses\"\n\t\t\t\tif ( toggle ) {\n\t\t\t\t\tdataShow.hidden = !hidden;\n\t\t\t\t}\n\n\t\t\t\t// Show elements before animating them\n\t\t\t\tif ( hidden ) {\n\t\t\t\t\tshowHide( [ elem ], true );\n\t\t\t\t}\n\n\t\t\t\t/* eslint-disable no-loop-func */\n\n\t\t\t\tanim.done( function() {\n\n\t\t\t\t\t/* eslint-enable no-loop-func */\n\n\t\t\t\t\t// The final step of a \"hide\" animation is actually hiding the element\n\t\t\t\t\tif ( !hidden ) {\n\t\t\t\t\t\tshowHide( [ elem ] );\n\t\t\t\t\t}\n\t\t\t\t\tdataPriv.remove( elem, \"fxshow\" );\n\t\t\t\t\tfor ( prop in orig ) {\n\t\t\t\t\t\tjQuery.style( elem, prop, orig[ prop ] );\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\t// Per-property setup\n\t\t\tpropTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );\n\t\t\tif ( !( prop in dataShow ) ) {\n\t\t\t\tdataShow[ prop ] = propTween.start;\n\t\t\t\tif ( hidden ) {\n\t\t\t\t\tpropTween.end = propTween.start;\n\t\t\t\t\tpropTween.start = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction propFilter( props, specialEasing ) {\n\t\tvar index, name, easing, value, hooks;\n\n\t\t// camelCase, specialEasing and expand cssHook pass\n\t\tfor ( index in props ) {\n\t\t\tname = jQuery.camelCase( index );\n\t\t\teasing = specialEasing[ name ];\n\t\t\tvalue = props[ index ];\n\t\t\tif ( Array.isArray( value ) ) {\n\t\t\t\teasing = value[ 1 ];\n\t\t\t\tvalue = props[ index ] = value[ 0 ];\n\t\t\t}\n\n\t\t\tif ( index !== name ) {\n\t\t\t\tprops[ name ] = value;\n\t\t\t\tdelete props[ index ];\n\t\t\t}\n\n\t\t\thooks = jQuery.cssHooks[ name ];\n\t\t\tif ( hooks && \"expand\" in hooks ) {\n\t\t\t\tvalue = hooks.expand( value );\n\t\t\t\tdelete props[ name ];\n\n\t\t\t\t// Not quite $.extend, this won't overwrite existing keys.\n\t\t\t\t// Reusing 'index' because we have the correct \"name\"\n\t\t\t\tfor ( index in value ) {\n\t\t\t\t\tif ( !( index in props ) ) {\n\t\t\t\t\t\tprops[ index ] = value[ index ];\n\t\t\t\t\t\tspecialEasing[ index ] = easing;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tspecialEasing[ name ] = easing;\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction Animation( elem, properties, options ) {\n\t\tvar result,\n\t\t\tstopped,\n\t\t\tindex = 0,\n\t\t\tlength = Animation.prefilters.length,\n\t\t\tdeferred = jQuery.Deferred().always( function() {\n\n\t\t\t\t// Don't match elem in the :animated selector\n\t\t\t\tdelete tick.elem;\n\t\t\t} ),\n\t\t\ttick = function() {\n\t\t\t\tif ( stopped ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tvar currentTime = fxNow || createFxNow(),\n\t\t\t\t\tremaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),\n\n\t\t\t\t\t// Support: Android 2.3 only\n\t\t\t\t\t// Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497)\n\t\t\t\t\ttemp = remaining / animation.duration || 0,\n\t\t\t\t\tpercent = 1 - temp,\n\t\t\t\t\tindex = 0,\n\t\t\t\t\tlength = animation.tweens.length;\n\n\t\t\t\tfor ( ; index < length; index++ ) {\n\t\t\t\t\tanimation.tweens[ index ].run( percent );\n\t\t\t\t}\n\n\t\t\t\tdeferred.notifyWith( elem, [ animation, percent, remaining ] );\n\n\t\t\t\t// If there's more to do, yield\n\t\t\t\tif ( percent < 1 && length ) {\n\t\t\t\t\treturn remaining;\n\t\t\t\t}\n\n\t\t\t\t// If this was an empty animation, synthesize a final progress notification\n\t\t\t\tif ( !length ) {\n\t\t\t\t\tdeferred.notifyWith( elem, [ animation, 1, 0 ] );\n\t\t\t\t}\n\n\t\t\t\t// Resolve the animation and report its conclusion\n\t\t\t\tdeferred.resolveWith( elem, [ animation ] );\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\tanimation = deferred.promise( {\n\t\t\t\telem: elem,\n\t\t\t\tprops: jQuery.extend( {}, properties ),\n\t\t\t\topts: jQuery.extend( true, {\n\t\t\t\t\tspecialEasing: {},\n\t\t\t\t\teasing: jQuery.easing._default\n\t\t\t\t}, options ),\n\t\t\t\toriginalProperties: properties,\n\t\t\t\toriginalOptions: options,\n\t\t\t\tstartTime: fxNow || createFxNow(),\n\t\t\t\tduration: options.duration,\n\t\t\t\ttweens: [],\n\t\t\t\tcreateTween: function( prop, end ) {\n\t\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\t\tanimation.tweens.push( tween );\n\t\t\t\t\treturn tween;\n\t\t\t\t},\n\t\t\t\tstop: function( gotoEnd ) {\n\t\t\t\t\tvar index = 0,\n\n\t\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\t// otherwise we skip this part\n\t\t\t\t\t\tlength = gotoEnd ? animation.tweens.length : 0;\n\t\t\t\t\tif ( stopped ) {\n\t\t\t\t\t\treturn this;\n\t\t\t\t\t}\n\t\t\t\t\tstopped = true;\n\t\t\t\t\tfor ( ; index < length; index++ ) {\n\t\t\t\t\t\tanimation.tweens[ index ].run( 1 );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Resolve when we played the last frame; otherwise, reject\n\t\t\t\t\tif ( gotoEnd ) {\n\t\t\t\t\t\tdeferred.notifyWith( elem, [ animation, 1, 0 ] );\n\t\t\t\t\t\tdeferred.resolveWith( elem, [ animation, gotoEnd ] );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdeferred.rejectWith( elem, [ animation, gotoEnd ] );\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t} ),\n\t\t\tprops = animation.props;\n\n\t\tpropFilter( props, animation.opts.specialEasing );\n\n\t\tfor ( ; index < length; index++ ) {\n\t\t\tresult = Animation.prefilters[ index ].call( animation, elem, props, animation.opts );\n\t\t\tif ( result ) {\n\t\t\t\tif ( jQuery.isFunction( result.stop ) ) {\n\t\t\t\t\tjQuery._queueHooks( animation.elem, animation.opts.queue ).stop =\n\t\t\t\t\t\tjQuery.proxy( result.stop, result );\n\t\t\t\t}\n\t\t\t\treturn result;\n\t\t\t}\n\t\t}\n\n\t\tjQuery.map( props, createTween, animation );\n\n\t\tif ( jQuery.isFunction( animation.opts.start ) ) {\n\t\t\tanimation.opts.start.call( elem, animation );\n\t\t}\n\n\t\t// Attach callbacks from options\n\t\tanimation\n\t\t\t.progress( animation.opts.progress )\n\t\t\t.done( animation.opts.done, animation.opts.complete )\n\t\t\t.fail( animation.opts.fail )\n\t\t\t.always( animation.opts.always );\n\n\t\tjQuery.fx.timer(\n\t\t\tjQuery.extend( tick, {\n\t\t\t\telem: elem,\n\t\t\t\tanim: animation,\n\t\t\t\tqueue: animation.opts.queue\n\t\t\t} )\n\t\t);\n\n\t\treturn animation;\n\t}\n\n\tjQuery.Animation = jQuery.extend( Animation, {\n\n\t\ttweeners: {\n\t\t\t\"*\": [ function( prop, value ) {\n\t\t\t\tvar tween = this.createTween( prop, value );\n\t\t\t\tadjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );\n\t\t\t\treturn tween;\n\t\t\t} ]\n\t\t},\n\n\t\ttweener: function( props, callback ) {\n\t\t\tif ( jQuery.isFunction( props ) ) {\n\t\t\t\tcallback = props;\n\t\t\t\tprops = [ \"*\" ];\n\t\t\t} else {\n\t\t\t\tprops = props.match( rnothtmlwhite );\n\t\t\t}\n\n\t\t\tvar prop,\n\t\t\t\tindex = 0,\n\t\t\t\tlength = props.length;\n\n\t\t\tfor ( ; index < length; index++ ) {\n\t\t\t\tprop = props[ index ];\n\t\t\t\tAnimation.tweeners[ prop ] = Animation.tweeners[ prop ] || [];\n\t\t\t\tAnimation.tweeners[ prop ].unshift( callback );\n\t\t\t}\n\t\t},\n\n\t\tprefilters: [ defaultPrefilter ],\n\n\t\tprefilter: function( callback, prepend ) {\n\t\t\tif ( prepend ) {\n\t\t\t\tAnimation.prefilters.unshift( callback );\n\t\t\t} else {\n\t\t\t\tAnimation.prefilters.push( callback );\n\t\t\t}\n\t\t}\n\t} );\n\n\tjQuery.speed = function( speed, easing, fn ) {\n\t\tvar opt = speed && typeof speed === \"object\" ? jQuery.extend( {}, speed ) : {\n\t\t\tcomplete: fn || !fn && easing ||\n\t\t\tjQuery.isFunction( speed ) && speed,\n\t\t\tduration: speed,\n\t\t\teasing: fn && easing || easing && !jQuery.isFunction( easing ) && easing\n\t\t};\n\n\t\t// Go to the end state if fx are off\n\t\tif ( jQuery.fx.off ) {\n\t\t\topt.duration = 0;\n\n\t\t} else {\n\t\t\tif ( typeof opt.duration !== \"number\" ) {\n\t\t\t\tif ( opt.duration in jQuery.fx.speeds ) {\n\t\t\t\t\topt.duration = jQuery.fx.speeds[ opt.duration ];\n\n\t\t\t\t} else {\n\t\t\t\t\topt.duration = jQuery.fx.speeds._default;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Normalize opt.queue - true/undefined/null -> \"fx\"\n\t\tif ( opt.queue == null || opt.queue === true ) {\n\t\t\topt.queue = \"fx\";\n\t\t}\n\n\t\t// Queueing\n\t\topt.old = opt.complete;\n\n\t\topt.complete = function() {\n\t\t\tif ( jQuery.isFunction( opt.old ) ) {\n\t\t\t\topt.old.call( this );\n\t\t\t}\n\n\t\t\tif ( opt.queue ) {\n\t\t\t\tjQuery.dequeue( this, opt.queue );\n\t\t\t}\n\t\t};\n\n\t\treturn opt;\n\t};\n\n\tjQuery.fn.extend( {\n\t\tfadeTo: function( speed, to, easing, callback ) {\n\n\t\t\t// Show any hidden elements after setting opacity to 0\n\t\t\treturn this.filter( isHiddenWithinTree ).css( \"opacity\", 0 ).show()\n\n\t\t\t// Animate to the value specified\n\t\t\t\t.end().animate( { opacity: to }, speed, easing, callback );\n\t\t},\n\t\tanimate: function( prop, speed, easing, callback ) {\n\t\t\tvar empty = jQuery.isEmptyObject( prop ),\n\t\t\t\toptall = jQuery.speed( speed, easing, callback ),\n\t\t\t\tdoAnimation = function() {\n\n\t\t\t\t\t// Operate on a copy of prop so per-property easing won't be lost\n\t\t\t\t\tvar anim = Animation( this, jQuery.extend( {}, prop ), optall );\n\n\t\t\t\t\t// Empty animations, or finishing resolves immediately\n\t\t\t\t\tif ( empty || dataPriv.get( this, \"finish\" ) ) {\n\t\t\t\t\t\tanim.stop( true );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\tdoAnimation.finish = doAnimation;\n\n\t\t\treturn empty || optall.queue === false ?\n\t\t\t\tthis.each( doAnimation ) :\n\t\t\t\tthis.queue( optall.queue, doAnimation );\n\t\t},\n\t\tstop: function( type, clearQueue, gotoEnd ) {\n\t\t\tvar stopQueue = function( hooks ) {\n\t\t\t\tvar stop = hooks.stop;\n\t\t\t\tdelete hooks.stop;\n\t\t\t\tstop( gotoEnd );\n\t\t\t};\n\n\t\t\tif ( typeof type !== \"string\" ) {\n\t\t\t\tgotoEnd = clearQueue;\n\t\t\t\tclearQueue = type;\n\t\t\t\ttype = undefined;\n\t\t\t}\n\t\t\tif ( clearQueue && type !== false ) {\n\t\t\t\tthis.queue( type || \"fx\", [] );\n\t\t\t}\n\n\t\t\treturn this.each( function() {\n\t\t\t\tvar dequeue = true,\n\t\t\t\t\tindex = type != null && type + \"queueHooks\",\n\t\t\t\t\ttimers = jQuery.timers,\n\t\t\t\t\tdata = dataPriv.get( this );\n\n\t\t\t\tif ( index ) {\n\t\t\t\t\tif ( data[ index ] && data[ index ].stop ) {\n\t\t\t\t\t\tstopQueue( data[ index ] );\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tfor ( index in data ) {\n\t\t\t\t\t\tif ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {\n\t\t\t\t\t\t\tstopQueue( data[ index ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\t\tif ( timers[ index ].elem === this &&\n\t\t\t\t\t\t( type == null || timers[ index ].queue === type ) ) {\n\n\t\t\t\t\t\ttimers[ index ].anim.stop( gotoEnd );\n\t\t\t\t\t\tdequeue = false;\n\t\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Start the next in the queue if the last step wasn't forced.\n\t\t\t\t// Timers currently will call their complete callbacks, which\n\t\t\t\t// will dequeue but only if they were gotoEnd.\n\t\t\t\tif ( dequeue || !gotoEnd ) {\n\t\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t\t}\n\t\t\t} );\n\t\t},\n\t\tfinish: function( type ) {\n\t\t\tif ( type !== false ) {\n\t\t\t\ttype = type || \"fx\";\n\t\t\t}\n\t\t\treturn this.each( function() {\n\t\t\t\tvar index,\n\t\t\t\t\tdata = dataPriv.get( this ),\n\t\t\t\t\tqueue = data[ type + \"queue\" ],\n\t\t\t\t\thooks = data[ type + \"queueHooks\" ],\n\t\t\t\t\ttimers = jQuery.timers,\n\t\t\t\t\tlength = queue ? queue.length : 0;\n\n\t\t\t\t// Enable finishing flag on private data\n\t\t\t\tdata.finish = true;\n\n\t\t\t\t// Empty the queue first\n\t\t\t\tjQuery.queue( this, type, [] );\n\n\t\t\t\tif ( hooks && hooks.stop ) {\n\t\t\t\t\thooks.stop.call( this, true );\n\t\t\t\t}\n\n\t\t\t\t// Look for any active animations, and finish them\n\t\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\t\tif ( timers[ index ].elem === this && timers[ index ].queue === type ) {\n\t\t\t\t\t\ttimers[ index ].anim.stop( true );\n\t\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Look for any animations in the old queue and finish them\n\t\t\t\tfor ( index = 0; index < length; index++ ) {\n\t\t\t\t\tif ( queue[ index ] && queue[ index ].finish ) {\n\t\t\t\t\t\tqueue[ index ].finish.call( this );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Turn off finishing flag\n\t\t\t\tdelete data.finish;\n\t\t\t} );\n\t\t}\n\t} );\n\n\tjQuery.each( [ \"toggle\", \"show\", \"hide\" ], function( i, name ) {\n\t\tvar cssFn = jQuery.fn[ name ];\n\t\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\t\treturn speed == null || typeof speed === \"boolean\" ?\n\t\t\t\tcssFn.apply( this, arguments ) :\n\t\t\t\tthis.animate( genFx( name, true ), speed, easing, callback );\n\t\t};\n\t} );\n\n// Generate shortcuts for custom animations\n\tjQuery.each( {\n\t\tslideDown: genFx( \"show\" ),\n\t\tslideUp: genFx( \"hide\" ),\n\t\tslideToggle: genFx( \"toggle\" ),\n\t\tfadeIn: { opacity: \"show\" },\n\t\tfadeOut: { opacity: \"hide\" },\n\t\tfadeToggle: { opacity: \"toggle\" }\n\t}, function( name, props ) {\n\t\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\t\treturn this.animate( props, speed, easing, callback );\n\t\t};\n\t} );\n\n\tjQuery.timers = [];\n\tjQuery.fx.tick = function() {\n\t\tvar timer,\n\t\t\ti = 0,\n\t\t\ttimers = jQuery.timers;\n\n\t\tfxNow = jQuery.now();\n\n\t\tfor ( ; i < timers.length; i++ ) {\n\t\t\ttimer = timers[ i ];\n\n\t\t\t// Run the timer and safely remove it when done (allowing for external removal)\n\t\t\tif ( !timer() && timers[ i ] === timer ) {\n\t\t\t\ttimers.splice( i--, 1 );\n\t\t\t}\n\t\t}\n\n\t\tif ( !timers.length ) {\n\t\t\tjQuery.fx.stop();\n\t\t}\n\t\tfxNow = undefined;\n\t};\n\n\tjQuery.fx.timer = function( timer ) {\n\t\tjQuery.timers.push( timer );\n\t\tjQuery.fx.start();\n\t};\n\n\tjQuery.fx.interval = 13;\n\tjQuery.fx.start = function() {\n\t\tif ( inProgress ) {\n\t\t\treturn;\n\t\t}\n\n\t\tinProgress = true;\n\t\tschedule();\n\t};\n\n\tjQuery.fx.stop = function() {\n\t\tinProgress = null;\n\t};\n\n\tjQuery.fx.speeds = {\n\t\tslow: 600,\n\t\tfast: 200,\n\n\t\t// Default speed\n\t\t_default: 400\n\t};\n\n\n// Based off of the plugin by Clint Helfers, with permission.\n// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/\n\tjQuery.fn.delay = 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 = window.setTimeout( next, time );\n\t\t\thooks.stop = function() {\n\t\t\t\twindow.clearTimeout( timeout );\n\t\t\t};\n\t\t} );\n\t};\n\n\n\t( function() {\n\t\tvar input = document.createElement( \"input\" ),\n\t\t\tselect = document.createElement( \"select\" ),\n\t\t\topt = select.appendChild( document.createElement( \"option\" ) );\n\n\t\tinput.type = \"checkbox\";\n\n\t\t// Support: Android <=4.3 only\n\t\t// Default value for a checkbox should be \"on\"\n\t\tsupport.checkOn = input.value !== \"\";\n\n\t\t// Support: IE <=11 only\n\t\t// Must access selectedIndex to make default options select\n\t\tsupport.optSelected = opt.selected;\n\n\t\t// Support: IE <=11 only\n\t\t// An input loses its value after becoming a radio\n\t\tinput = document.createElement( \"input\" );\n\t\tinput.value = \"t\";\n\t\tinput.type = \"radio\";\n\t\tsupport.radioValue = input.value === \"t\";\n\t} )();\n\n\n\tvar boolHook,\n\t\tattrHandle = jQuery.expr.attrHandle;\n\n\tjQuery.fn.extend( {\n\t\tattr: function( name, value ) {\n\t\t\treturn access( this, jQuery.attr, name, value, arguments.length > 1 );\n\t\t},\n\n\t\tremoveAttr: function( name ) {\n\t\t\treturn this.each( function() {\n\t\t\t\tjQuery.removeAttr( this, name );\n\t\t\t} );\n\t\t}\n\t} );\n\n\tjQuery.extend( {\n\t\tattr: function( elem, name, value ) {\n\t\t\tvar ret, hooks,\n\t\t\t\tnType = elem.nodeType;\n\n\t\t\t// Don't get/set attributes on text, comment and attribute nodes\n\t\t\tif ( nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Fallback to prop when attributes are not supported\n\t\t\tif ( typeof elem.getAttribute === \"undefined\" ) {\n\t\t\t\treturn jQuery.prop( elem, name, value );\n\t\t\t}\n\n\t\t\t// Attribute hooks are determined by the lowercase version\n\t\t\t// Grab necessary hook if one is defined\n\t\t\tif ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {\n\t\t\t\thooks = jQuery.attrHooks[ name.toLowerCase() ] ||\n\t\t\t\t\t( jQuery.expr.match.bool.test( name ) ? boolHook : undefined );\n\t\t\t}\n\n\t\t\tif ( value !== undefined ) {\n\t\t\t\tif ( value === null ) {\n\t\t\t\t\tjQuery.removeAttr( elem, name );\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif ( hooks && \"set\" in hooks &&\n\t\t\t\t\t( ret = hooks.set( elem, value, name ) ) !== undefined ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\telem.setAttribute( name, value + \"\" );\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t\tif ( hooks && \"get\" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\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 ? undefined : ret;\n\t\t},\n\n\t\tattrHooks: {\n\t\t\ttype: {\n\t\t\t\tset: function( elem, value ) {\n\t\t\t\t\tif ( !support.radioValue && value === \"radio\" &&\n\t\t\t\t\t\tnodeName( elem, \"input\" ) ) {\n\t\t\t\t\t\tvar val = elem.value;\n\t\t\t\t\t\telem.setAttribute( \"type\", value );\n\t\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\t\telem.value = val;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn value;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tremoveAttr: function( elem, value ) {\n\t\t\tvar name,\n\t\t\t\ti = 0,\n\n\t\t\t\t// Attribute names can contain non-HTML whitespace characters\n\t\t\t\t// https://html.spec.whatwg.org/multipage/syntax.html#attributes-2\n\t\t\t\tattrNames = value && value.match( rnothtmlwhite );\n\n\t\t\tif ( attrNames && elem.nodeType === 1 ) {\n\t\t\t\twhile ( ( name = attrNames[ i++ ] ) ) {\n\t\t\t\t\telem.removeAttribute( name );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} );\n\n// Hooks for boolean attributes\n\tboolHook = {\n\t\tset: function( elem, value, name ) {\n\t\t\tif ( value === false ) {\n\n\t\t\t\t// Remove boolean attributes when set to false\n\t\t\t\tjQuery.removeAttr( elem, name );\n\t\t\t} else {\n\t\t\t\telem.setAttribute( name, name );\n\t\t\t}\n\t\t\treturn name;\n\t\t}\n\t};\n\n\tjQuery.each( jQuery.expr.match.bool.source.match( /\\w+/g ), function( i, name ) {\n\t\tvar getter = attrHandle[ name ] || jQuery.find.attr;\n\n\t\tattrHandle[ name ] = function( elem, name, isXML ) {\n\t\t\tvar ret, handle,\n\t\t\t\tlowercaseName = name.toLowerCase();\n\n\t\t\tif ( !isXML ) {\n\n\t\t\t\t// Avoid an infinite loop by temporarily removing this function from the getter\n\t\t\t\thandle = attrHandle[ lowercaseName ];\n\t\t\t\tattrHandle[ lowercaseName ] = ret;\n\t\t\t\tret = getter( elem, name, isXML ) != null ?\n\t\t\t\t\tlowercaseName :\n\t\t\t\t\tnull;\n\t\t\t\tattrHandle[ lowercaseName ] = handle;\n\t\t\t}\n\t\t\treturn ret;\n\t\t};\n\t} );\n\n\n\n\n\tvar rfocusable = /^(?:input|select|textarea|button)$/i,\n\t\trclickable = /^(?:a|area)$/i;\n\n\tjQuery.fn.extend( {\n\t\tprop: function( name, value ) {\n\t\t\treturn access( this, jQuery.prop, name, value, arguments.length > 1 );\n\t\t},\n\n\t\tremoveProp: function( name ) {\n\t\t\treturn this.each( function() {\n\t\t\t\tdelete this[ jQuery.propFix[ name ] || name ];\n\t\t\t} );\n\t\t}\n\t} );\n\n\tjQuery.extend( {\n\t\tprop: function( elem, name, value ) {\n\t\t\tvar ret, hooks,\n\t\t\t\tnType = elem.nodeType;\n\n\t\t\t// Don't get/set properties on text, comment and attribute nodes\n\t\t\tif ( nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {\n\n\t\t\t\t// Fix name and attach hooks\n\t\t\t\tname = jQuery.propFix[ name ] || name;\n\t\t\t\thooks = jQuery.propHooks[ name ];\n\t\t\t}\n\n\t\t\tif ( value !== undefined ) {\n\t\t\t\tif ( hooks && \"set\" in hooks &&\n\t\t\t\t\t( ret = hooks.set( elem, value, name ) ) !== undefined ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\treturn ( elem[ name ] = value );\n\t\t\t}\n\n\t\t\tif ( hooks && \"get\" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\treturn elem[ name ];\n\t\t},\n\n\t\tpropHooks: {\n\t\t\ttabIndex: {\n\t\t\t\tget: function( elem ) {\n\n\t\t\t\t\t// Support: IE <=9 - 11 only\n\t\t\t\t\t// elem.tabIndex doesn't always return the\n\t\t\t\t\t// correct value when it hasn't been explicitly set\n\t\t\t\t\t// https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/\n\t\t\t\t\t// Use proper attribute retrieval(#12072)\n\t\t\t\t\tvar tabindex = jQuery.find.attr( elem, \"tabindex\" );\n\n\t\t\t\t\tif ( tabindex ) {\n\t\t\t\t\t\treturn parseInt( tabindex, 10 );\n\t\t\t\t\t}\n\n\t\t\t\t\tif (\n\t\t\t\t\t\trfocusable.test( elem.nodeName ) ||\n\t\t\t\t\t\trclickable.test( elem.nodeName ) &&\n\t\t\t\t\t\telem.href\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn 0;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn -1;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tpropFix: {\n\t\t\t\"for\": \"htmlFor\",\n\t\t\t\"class\": \"className\"\n\t\t}\n\t} );\n\n// Support: IE <=11 only\n// Accessing the selectedIndex property\n// forces the browser to respect setting selected\n// on the option\n// The getter ensures a default option is selected\n// when in an optgroup\n// eslint rule \"no-unused-expressions\" is disabled for this code\n// since it considers such accessions noop\n\tif ( !support.optSelected ) {\n\t\tjQuery.propHooks.selected = {\n\t\t\tget: function( elem ) {\n\n\t\t\t\t/* eslint no-unused-expressions: \"off\" */\n\n\t\t\t\tvar parent = elem.parentNode;\n\t\t\t\tif ( parent && parent.parentNode ) {\n\t\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t\t}\n\t\t\t\treturn null;\n\t\t\t},\n\t\t\tset: function( elem ) {\n\n\t\t\t\t/* eslint no-unused-expressions: \"off\" */\n\n\t\t\t\tvar parent = elem.parentNode;\n\t\t\t\tif ( parent ) {\n\t\t\t\t\tparent.selectedIndex;\n\n\t\t\t\t\tif ( parent.parentNode ) {\n\t\t\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\n\tjQuery.each( [\n\t\t\"tabIndex\",\n\t\t\"readOnly\",\n\t\t\"maxLength\",\n\t\t\"cellSpacing\",\n\t\t\"cellPadding\",\n\t\t\"rowSpan\",\n\t\t\"colSpan\",\n\t\t\"useMap\",\n\t\t\"frameBorder\",\n\t\t\"contentEditable\"\n\t], function() {\n\t\tjQuery.propFix[ this.toLowerCase() ] = this;\n\t} );\n\n\n\n\n\t// Strip and collapse whitespace according to HTML spec\n\t// https://html.spec.whatwg.org/multipage/infrastructure.html#strip-and-collapse-whitespace\n\tfunction stripAndCollapse( value ) {\n\t\tvar tokens = value.match( rnothtmlwhite ) || [];\n\t\treturn tokens.join( \" \" );\n\t}\n\n\n\tfunction getClass( elem ) {\n\t\treturn elem.getAttribute && elem.getAttribute( \"class\" ) || \"\";\n\t}\n\n\tjQuery.fn.extend( {\n\t\taddClass: function( value ) {\n\t\t\tvar classes, elem, cur, curValue, clazz, j, finalValue,\n\t\t\t\ti = 0;\n\n\t\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\t\treturn this.each( function( j ) {\n\t\t\t\t\tjQuery( this ).addClass( value.call( this, j, getClass( this ) ) );\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\tif ( typeof value === \"string\" && value ) {\n\t\t\t\tclasses = value.match( rnothtmlwhite ) || [];\n\n\t\t\t\twhile ( ( elem = this[ i++ ] ) ) {\n\t\t\t\t\tcurValue = getClass( elem );\n\t\t\t\t\tcur = elem.nodeType === 1 && ( \" \" + stripAndCollapse( curValue ) + \" \" );\n\n\t\t\t\t\tif ( cur ) {\n\t\t\t\t\t\tj = 0;\n\t\t\t\t\t\twhile ( ( clazz = classes[ j++ ] ) ) {\n\t\t\t\t\t\t\tif ( cur.indexOf( \" \" + clazz + \" \" ) < 0 ) {\n\t\t\t\t\t\t\t\tcur += clazz + \" \";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Only assign if different to avoid unneeded rendering.\n\t\t\t\t\t\tfinalValue = stripAndCollapse( cur );\n\t\t\t\t\t\tif ( curValue !== finalValue ) {\n\t\t\t\t\t\t\telem.setAttribute( \"class\", finalValue );\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\treturn this;\n\t\t},\n\n\t\tremoveClass: function( value ) {\n\t\t\tvar classes, elem, cur, curValue, clazz, j, finalValue,\n\t\t\t\ti = 0;\n\n\t\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\t\treturn this.each( function( j ) {\n\t\t\t\t\tjQuery( this ).removeClass( value.call( this, j, getClass( this ) ) );\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\tif ( !arguments.length ) {\n\t\t\t\treturn this.attr( \"class\", \"\" );\n\t\t\t}\n\n\t\t\tif ( typeof value === \"string\" && value ) {\n\t\t\t\tclasses = value.match( rnothtmlwhite ) || [];\n\n\t\t\t\twhile ( ( elem = this[ i++ ] ) ) {\n\t\t\t\t\tcurValue = getClass( elem );\n\n\t\t\t\t\t// This expression is here for better compressibility (see addClass)\n\t\t\t\t\tcur = elem.nodeType === 1 && ( \" \" + stripAndCollapse( curValue ) + \" \" );\n\n\t\t\t\t\tif ( cur ) {\n\t\t\t\t\t\tj = 0;\n\t\t\t\t\t\twhile ( ( clazz = classes[ j++ ] ) ) {\n\n\t\t\t\t\t\t\t// Remove *all* instances\n\t\t\t\t\t\t\twhile ( cur.indexOf( \" \" + clazz + \" \" ) > -1 ) {\n\t\t\t\t\t\t\t\tcur = cur.replace( \" \" + clazz + \" \", \" \" );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Only assign if different to avoid unneeded rendering.\n\t\t\t\t\t\tfinalValue = stripAndCollapse( cur );\n\t\t\t\t\t\tif ( curValue !== finalValue ) {\n\t\t\t\t\t\t\telem.setAttribute( \"class\", finalValue );\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\treturn this;\n\t\t},\n\n\t\ttoggleClass: function( value, stateVal ) {\n\t\t\tvar type = typeof value;\n\n\t\t\tif ( typeof stateVal === \"boolean\" && type === \"string\" ) {\n\t\t\t\treturn stateVal ? this.addClass( value ) : this.removeClass( value );\n\t\t\t}\n\n\t\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\t\treturn this.each( function( i ) {\n\t\t\t\t\tjQuery( this ).toggleClass(\n\t\t\t\t\t\tvalue.call( this, i, getClass( this ), stateVal ),\n\t\t\t\t\t\tstateVal\n\t\t\t\t\t);\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\treturn this.each( function() {\n\t\t\t\tvar className, i, self, classNames;\n\n\t\t\t\tif ( type === \"string\" ) {\n\n\t\t\t\t\t// Toggle individual class names\n\t\t\t\t\ti = 0;\n\t\t\t\t\tself = jQuery( this );\n\t\t\t\t\tclassNames = value.match( rnothtmlwhite ) || [];\n\n\t\t\t\t\twhile ( ( className = classNames[ i++ ] ) ) {\n\n\t\t\t\t\t\t// Check each className given, space separated list\n\t\t\t\t\t\tif ( self.hasClass( className ) ) {\n\t\t\t\t\t\t\tself.removeClass( className );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tself.addClass( className );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Toggle whole class name\n\t\t\t\t} else if ( value === undefined || type === \"boolean\" ) {\n\t\t\t\t\tclassName = getClass( this );\n\t\t\t\t\tif ( className ) {\n\n\t\t\t\t\t\t// Store className if set\n\t\t\t\t\t\tdataPriv.set( this, \"__className__\", className );\n\t\t\t\t\t}\n\n\t\t\t\t\t// If the element has a class name or if we're passed `false`,\n\t\t\t\t\t// then remove the whole classname (if there was one, the above saved it).\n\t\t\t\t\t// Otherwise bring back whatever was previously saved (if anything),\n\t\t\t\t\t// falling back to the empty string if nothing was stored.\n\t\t\t\t\tif ( this.setAttribute ) {\n\t\t\t\t\t\tthis.setAttribute( \"class\",\n\t\t\t\t\t\t\tclassName || value === false ?\n\t\t\t\t\t\t\t\t\"\" :\n\t\t\t\t\t\t\tdataPriv.get( this, \"__className__\" ) || \"\"\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\thasClass: function( selector ) {\n\t\t\tvar className, elem,\n\t\t\t\ti = 0;\n\n\t\t\tclassName = \" \" + selector + \" \";\n\t\t\twhile ( ( elem = this[ i++ ] ) ) {\n\t\t\t\tif ( elem.nodeType === 1 &&\n\t\t\t\t\t( \" \" + stripAndCollapse( getClass( elem ) ) + \" \" ).indexOf( className ) > -1 ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\t\t}\n\t} );\n\n\n\n\n\tvar rreturn = /\\r/g;\n\n\tjQuery.fn.extend( {\n\t\tval: function( value ) {\n\t\t\tvar hooks, ret, isFunction,\n\t\t\t\telem = this[ 0 ];\n\n\t\t\tif ( !arguments.length ) {\n\t\t\t\tif ( elem ) {\n\t\t\t\t\thooks = jQuery.valHooks[ elem.type ] ||\n\t\t\t\t\t\tjQuery.valHooks[ elem.nodeName.toLowerCase() ];\n\n\t\t\t\t\tif ( hooks &&\n\t\t\t\t\t\t\"get\" in hooks &&\n\t\t\t\t\t\t( ret = hooks.get( elem, \"value\" ) ) !== undefined\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn ret;\n\t\t\t\t\t}\n\n\t\t\t\t\tret = elem.value;\n\n\t\t\t\t\t// Handle most common string cases\n\t\t\t\t\tif ( typeof ret === \"string\" ) {\n\t\t\t\t\t\treturn ret.replace( rreturn, \"\" );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Handle cases where value is null/undef or number\n\t\t\t\t\treturn ret == null ? \"\" : ret;\n\t\t\t\t}\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tisFunction = jQuery.isFunction( value );\n\n\t\t\treturn this.each( function( i ) {\n\t\t\t\tvar val;\n\n\t\t\t\tif ( this.nodeType !== 1 ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif ( isFunction ) {\n\t\t\t\t\tval = value.call( this, i, jQuery( this ).val() );\n\t\t\t\t} else {\n\t\t\t\t\tval = value;\n\t\t\t\t}\n\n\t\t\t\t// Treat null/undefined as \"\"; convert numbers to string\n\t\t\t\tif ( val == null ) {\n\t\t\t\t\tval = \"\";\n\n\t\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\t\tval += \"\";\n\n\t\t\t\t} else if ( Array.isArray( val ) ) {\n\t\t\t\t\tval = jQuery.map( val, function( value ) {\n\t\t\t\t\t\treturn value == null ? \"\" : value + \"\";\n\t\t\t\t\t} );\n\t\t\t\t}\n\n\t\t\t\thooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];\n\n\t\t\t\t// If set returns undefined, fall back to normal setting\n\t\t\t\tif ( !hooks || !( \"set\" in hooks ) || hooks.set( this, val, \"value\" ) === undefined ) {\n\t\t\t\t\tthis.value = val;\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t} );\n\n\tjQuery.extend( {\n\t\tvalHooks: {\n\t\t\toption: {\n\t\t\t\tget: function( elem ) {\n\n\t\t\t\t\tvar val = jQuery.find.attr( elem, \"value\" );\n\t\t\t\t\treturn val != null ?\n\t\t\t\t\t\tval :\n\n\t\t\t\t\t\t// Support: IE <=10 - 11 only\n\t\t\t\t\t\t// option.text throws exceptions (#14686, #14858)\n\t\t\t\t\t\t// Strip and collapse whitespace\n\t\t\t\t\t\t// https://html.spec.whatwg.org/#strip-and-collapse-whitespace\n\t\t\t\t\t\tstripAndCollapse( jQuery.text( elem ) );\n\t\t\t\t}\n\t\t\t},\n\t\t\tselect: {\n\t\t\t\tget: function( elem ) {\n\t\t\t\t\tvar value, option, i,\n\t\t\t\t\t\toptions = elem.options,\n\t\t\t\t\t\tindex = elem.selectedIndex,\n\t\t\t\t\t\tone = elem.type === \"select-one\",\n\t\t\t\t\t\tvalues = one ? null : [],\n\t\t\t\t\t\tmax = one ? index + 1 : options.length;\n\n\t\t\t\t\tif ( index < 0 ) {\n\t\t\t\t\t\ti = max;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\ti = one ? index : 0;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Loop through all the selected options\n\t\t\t\t\tfor ( ; i < max; i++ ) {\n\t\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t\t// Support: IE <=9 only\n\t\t\t\t\t\t// IE8-9 doesn't update selected after form reset (#2551)\n\t\t\t\t\t\tif ( ( option.selected || i === index ) &&\n\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!option.disabled &&\n\t\t\t\t\t\t\t( !option.parentNode.disabled ||\n\t\t\t\t\t\t\t!nodeName( option.parentNode, \"optgroup\" ) ) ) {\n\n\t\t\t\t\t\t\t// Get the specific value for the option\n\t\t\t\t\t\t\tvalue = jQuery( option ).val();\n\n\t\t\t\t\t\t\t// We don't need an array for one selects\n\t\t\t\t\t\t\tif ( one ) {\n\t\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Multi-Selects return an array\n\t\t\t\t\t\t\tvalues.push( value );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn values;\n\t\t\t\t},\n\n\t\t\t\tset: function( elem, value ) {\n\t\t\t\t\tvar optionSet, option,\n\t\t\t\t\t\toptions = elem.options,\n\t\t\t\t\t\tvalues = jQuery.makeArray( value ),\n\t\t\t\t\t\ti = options.length;\n\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t\t/* eslint-disable no-cond-assign */\n\n\t\t\t\t\t\tif ( option.selected =\n\t\t\t\t\t\t\t\tjQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\toptionSet = true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/* eslint-enable no-cond-assign */\n\t\t\t\t\t}\n\n\t\t\t\t\t// Force browsers to behave consistently when non-matching value is set\n\t\t\t\t\tif ( !optionSet ) {\n\t\t\t\t\t\telem.selectedIndex = -1;\n\t\t\t\t\t}\n\t\t\t\t\treturn values;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} );\n\n// Radios and checkboxes getter/setter\n\tjQuery.each( [ \"radio\", \"checkbox\" ], function() {\n\t\tjQuery.valHooks[ this ] = {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( Array.isArray( value ) ) {\n\t\t\t\t\treturn ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\tif ( !support.checkOn ) {\n\t\t\tjQuery.valHooks[ this ].get = function( elem ) {\n\t\t\t\treturn elem.getAttribute( \"value\" ) === null ? \"on\" : elem.value;\n\t\t\t};\n\t\t}\n\t} );\n\n\n\n\n// Return jQuery for attributes-only inclusion\n\n\n\tvar rfocusMorph = /^(?:focusinfocus|focusoutblur)$/;\n\n\tjQuery.extend( jQuery.event, {\n\n\t\ttrigger: function( event, data, elem, onlyHandlers ) {\n\n\t\t\tvar i, cur, tmp, bubbleType, ontype, handle, special,\n\t\t\t\teventPath = [ elem || document ],\n\t\t\t\ttype = hasOwn.call( event, \"type\" ) ? event.type : event,\n\t\t\t\tnamespaces = hasOwn.call( event, \"namespace\" ) ? event.namespace.split( \".\" ) : [];\n\n\t\t\tcur = tmp = elem = elem || document;\n\n\t\t\t// Don't do events on text and comment nodes\n\t\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// focus/blur morphs to focusin/out; ensure we're not firing them right now\n\t\t\tif ( rfocusMorph.test( type + jQuery.event.triggered ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( type.indexOf( \".\" ) > -1 ) {\n\n\t\t\t\t// Namespaced trigger; create a regexp to match event type in handle()\n\t\t\t\tnamespaces = type.split( \".\" );\n\t\t\t\ttype = namespaces.shift();\n\t\t\t\tnamespaces.sort();\n\t\t\t}\n\t\t\tontype = type.indexOf( \":\" ) < 0 && \"on\" + type;\n\n\t\t\t// Caller can pass in a jQuery.Event object, Object, or just an event type string\n\t\t\tevent = event[ jQuery.expando ] ?\n\t\t\t\tevent :\n\t\t\t\tnew jQuery.Event( type, typeof event === \"object\" && event );\n\n\t\t\t// Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)\n\t\t\tevent.isTrigger = onlyHandlers ? 2 : 3;\n\t\t\tevent.namespace = namespaces.join( \".\" );\n\t\t\tevent.rnamespace = event.namespace ?\n\t\t\t\tnew RegExp( \"(^|\\\\.)\" + namespaces.join( \"\\\\.(?:.*\\\\.|)\" ) + \"(\\\\.|$)\" ) :\n\t\t\t\tnull;\n\n\t\t\t// Clean up the event in case it is being reused\n\t\t\tevent.result = undefined;\n\t\t\tif ( !event.target ) {\n\t\t\t\tevent.target = elem;\n\t\t\t}\n\n\t\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n\t\t\tdata = data == null ?\n\t\t\t\t[ event ] :\n\t\t\t\tjQuery.makeArray( data, [ event ] );\n\n\t\t\t// Allow special events to draw outside the lines\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\t\t\tif ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Determine event propagation path in advance, per W3C events spec (#9951)\n\t\t\t// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)\n\t\t\tif ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {\n\n\t\t\t\tbubbleType = special.delegateType || type;\n\t\t\t\tif ( !rfocusMorph.test( bubbleType + type ) ) {\n\t\t\t\t\tcur = cur.parentNode;\n\t\t\t\t}\n\t\t\t\tfor ( ; cur; cur = cur.parentNode ) {\n\t\t\t\t\teventPath.push( cur );\n\t\t\t\t\ttmp = cur;\n\t\t\t\t}\n\n\t\t\t\t// Only add window if we got to document (e.g., not plain obj or detached DOM)\n\t\t\t\tif ( tmp === ( elem.ownerDocument || document ) ) {\n\t\t\t\t\teventPath.push( tmp.defaultView || tmp.parentWindow || window );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Fire handlers on the event path\n\t\t\ti = 0;\n\t\t\twhile ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) {\n\n\t\t\t\tevent.type = i > 1 ?\n\t\t\t\t\tbubbleType :\n\t\t\t\tspecial.bindType || type;\n\n\t\t\t\t// jQuery handler\n\t\t\t\thandle = ( dataPriv.get( cur, \"events\" ) || {} )[ event.type ] &&\n\t\t\t\t\tdataPriv.get( cur, \"handle\" );\n\t\t\t\tif ( handle ) {\n\t\t\t\t\thandle.apply( cur, data );\n\t\t\t\t}\n\n\t\t\t\t// Native handler\n\t\t\t\thandle = ontype && cur[ ontype ];\n\t\t\t\tif ( handle && handle.apply && acceptData( cur ) ) {\n\t\t\t\t\tevent.result = handle.apply( cur, data );\n\t\t\t\t\tif ( event.result === false ) {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tevent.type = type;\n\n\t\t\t// If nobody prevented the default action, do it now\n\t\t\tif ( !onlyHandlers && !event.isDefaultPrevented() ) {\n\n\t\t\t\tif ( ( !special._default ||\n\t\t\t\t\tspecial._default.apply( eventPath.pop(), data ) === false ) &&\n\t\t\t\t\tacceptData( elem ) ) {\n\n\t\t\t\t\t// Call a native DOM method on the target with the same name as the event.\n\t\t\t\t\t// Don't do default actions on window, that's where global variables be (#6170)\n\t\t\t\t\tif ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {\n\n\t\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\t\ttmp = elem[ ontype ];\n\n\t\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Prevent re-triggering of the same event, since we already bubbled it above\n\t\t\t\t\t\tjQuery.event.triggered = type;\n\t\t\t\t\t\telem[ type ]();\n\t\t\t\t\t\tjQuery.event.triggered = undefined;\n\n\t\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\t\telem[ ontype ] = tmp;\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\treturn event.result;\n\t\t},\n\n\t\t// Piggyback on a donor event to simulate a different one\n\t\t// Used only for `focus(in | out)` events\n\t\tsimulate: function( type, elem, event ) {\n\t\t\tvar e = jQuery.extend(\n\t\t\t\tnew jQuery.Event(),\n\t\t\t\tevent,\n\t\t\t\t{\n\t\t\t\t\ttype: type,\n\t\t\t\t\tisSimulated: true\n\t\t\t\t}\n\t\t\t);\n\n\t\t\tjQuery.event.trigger( e, null, elem );\n\t\t}\n\n\t} );\n\n\tjQuery.fn.extend( {\n\n\t\ttrigger: function( type, data ) {\n\t\t\treturn this.each( function() {\n\t\t\t\tjQuery.event.trigger( type, data, this );\n\t\t\t} );\n\t\t},\n\t\ttriggerHandler: function( type, data ) {\n\t\t\tvar elem = this[ 0 ];\n\t\t\tif ( elem ) {\n\t\t\t\treturn jQuery.event.trigger( type, data, elem, true );\n\t\t\t}\n\t\t}\n\t} );\n\n\n\tjQuery.each( ( \"blur focus focusin focusout resize scroll click dblclick \" +\n\t\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\t\"change select submit keydown keypress keyup contextmenu\" ).split( \" \" ),\n\t\tfunction( i, name ) {\n\n\t\t\t// Handle event binding\n\t\t\tjQuery.fn[ name ] = function( data, fn ) {\n\t\t\t\treturn arguments.length > 0 ?\n\t\t\t\t\tthis.on( name, null, data, fn ) :\n\t\t\t\t\tthis.trigger( name );\n\t\t\t};\n\t\t} );\n\n\tjQuery.fn.extend( {\n\t\thover: function( fnOver, fnOut ) {\n\t\t\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n\t\t}\n\t} );\n\n\n\n\n\tsupport.focusin = \"onfocusin\" in window;\n\n\n// Support: Firefox <=44\n// Firefox doesn't have focus(in | out) events\n// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787\n//\n// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1\n// focus(in | out) events fire after focus & blur events,\n// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order\n// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857\n\tif ( !support.focusin ) {\n\t\tjQuery.each( { focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n\t\t\t// Attach a single capturing handler on the document while someone wants focusin/focusout\n\t\t\tvar handler = function( event ) {\n\t\t\t\tjQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) );\n\t\t\t};\n\n\t\t\tjQuery.event.special[ fix ] = {\n\t\t\t\tsetup: function() {\n\t\t\t\t\tvar doc = this.ownerDocument || this,\n\t\t\t\t\t\tattaches = dataPriv.access( doc, fix );\n\n\t\t\t\t\tif ( !attaches ) {\n\t\t\t\t\t\tdoc.addEventListener( orig, handler, true );\n\t\t\t\t\t}\n\t\t\t\t\tdataPriv.access( doc, fix, ( attaches || 0 ) + 1 );\n\t\t\t\t},\n\t\t\t\tteardown: function() {\n\t\t\t\t\tvar doc = this.ownerDocument || this,\n\t\t\t\t\t\tattaches = dataPriv.access( doc, fix ) - 1;\n\n\t\t\t\t\tif ( !attaches ) {\n\t\t\t\t\t\tdoc.removeEventListener( orig, handler, true );\n\t\t\t\t\t\tdataPriv.remove( doc, fix );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdataPriv.access( doc, fix, attaches );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t} );\n\t}\n\tvar location = window.location;\n\n\tvar nonce = jQuery.now();\n\n\tvar rquery = ( /\\?/ );\n\n\n\n// Cross-browser xml parsing\n\tjQuery.parseXML = function( data ) {\n\t\tvar xml;\n\t\tif ( !data || typeof data !== \"string\" ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Support: IE 9 - 11 only\n\t\t// IE throws on parseFromString with invalid input.\n\t\ttry {\n\t\t\txml = ( new window.DOMParser() ).parseFromString( data, \"text/xml\" );\n\t\t} catch ( e ) {\n\t\t\txml = undefined;\n\t\t}\n\n\t\tif ( !xml || xml.getElementsByTagName( \"parsererror\" ).length ) {\n\t\t\tjQuery.error( \"Invalid XML: \" + data );\n\t\t}\n\t\treturn xml;\n\t};\n\n\n\tvar\n\t\trbracket = /\\[\\]$/,\n\t\trCRLF = /\\r?\\n/g,\n\t\trsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,\n\t\trsubmittable = /^(?:input|select|textarea|keygen)/i;\n\n\tfunction buildParams( prefix, obj, traditional, add ) {\n\t\tvar name;\n\n\t\tif ( Array.isArray( obj ) ) {\n\n\t\t\t// Serialize array item.\n\t\t\tjQuery.each( obj, function( i, v ) {\n\t\t\t\tif ( traditional || rbracket.test( prefix ) ) {\n\n\t\t\t\t\t// Treat each array item as a scalar.\n\t\t\t\t\tadd( prefix, v );\n\n\t\t\t\t} else {\n\n\t\t\t\t\t// Item is non-scalar (array or object), encode its numeric index.\n\t\t\t\t\tbuildParams(\n\t\t\t\t\t\tprefix + \"[\" + ( typeof v === \"object\" && v != null ? i : \"\" ) + \"]\",\n\t\t\t\t\t\tv,\n\t\t\t\t\t\ttraditional,\n\t\t\t\t\t\tadd\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} );\n\n\t\t} else if ( !traditional && jQuery.type( obj ) === \"object\" ) {\n\n\t\t\t// Serialize object item.\n\t\t\tfor ( name in obj ) {\n\t\t\t\tbuildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t// Serialize scalar item.\n\t\t\tadd( prefix, obj );\n\t\t}\n\t}\n\n// Serialize an array of form elements or a set of\n// key/values into a query string\n\tjQuery.param = function( a, traditional ) {\n\t\tvar prefix,\n\t\t\ts = [],\n\t\t\tadd = function( key, valueOrFunction ) {\n\n\t\t\t\t// If value is a function, invoke it and use its return value\n\t\t\t\tvar value = jQuery.isFunction( valueOrFunction ) ?\n\t\t\t\t\tvalueOrFunction() :\n\t\t\t\t\tvalueOrFunction;\n\n\t\t\t\ts[ s.length ] = encodeURIComponent( key ) + \"=\" +\n\t\t\t\t\tencodeURIComponent( value == null ? \"\" : value );\n\t\t\t};\n\n\t\t// If an array was passed in, assume that it is an array of form elements.\n\t\tif ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n\n\t\t\t// Serialize the form elements\n\t\t\tjQuery.each( a, function() {\n\t\t\t\tadd( this.name, this.value );\n\t\t\t} );\n\n\t\t} else {\n\n\t\t\t// If traditional, encode the \"old\" way (the way 1.3.2 or older\n\t\t\t// did it), otherwise encode params recursively.\n\t\t\tfor ( prefix in a ) {\n\t\t\t\tbuildParams( prefix, a[ prefix ], traditional, add );\n\t\t\t}\n\t\t}\n\n\t\t// Return the resulting serialization\n\t\treturn s.join( \"&\" );\n\t};\n\n\tjQuery.fn.extend( {\n\t\tserialize: function() {\n\t\t\treturn jQuery.param( this.serializeArray() );\n\t\t},\n\t\tserializeArray: function() {\n\t\t\treturn this.map( function() {\n\n\t\t\t\t// Can add propHook for \"elements\" to filter or add form elements\n\t\t\t\tvar elements = jQuery.prop( this, \"elements\" );\n\t\t\t\treturn elements ? jQuery.makeArray( elements ) : this;\n\t\t\t} )\n\t\t\t\t.filter( function() {\n\t\t\t\t\tvar type = this.type;\n\n\t\t\t\t\t// Use .is( \":disabled\" ) so that fieldset[disabled] works\n\t\t\t\t\treturn this.name && !jQuery( this ).is( \":disabled\" ) &&\n\t\t\t\t\t\trsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&\n\t\t\t\t\t\t( this.checked || !rcheckableType.test( type ) );\n\t\t\t\t} )\n\t\t\t\t.map( function( i, elem ) {\n\t\t\t\t\tvar val = jQuery( this ).val();\n\n\t\t\t\t\tif ( val == null ) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( Array.isArray( val ) ) {\n\t\t\t\t\t\treturn jQuery.map( val, function( val ) {\n\t\t\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t\t\t} );\n\t\t\t\t\t}\n\n\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t} ).get();\n\t\t}\n\t} );\n\n\n\tvar\n\t\tr20 = /%20/g,\n\t\trhash = /#.*$/,\n\t\trantiCache = /([?&])_=[^&]*/,\n\t\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)$/mg,\n\n\t\t// #7653, #8125, #8152: local protocol detection\n\t\trlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,\n\t\trnoContent = /^(?:GET|HEAD)$/,\n\t\trprotocol = /^\\/\\//,\n\n\t\t/* Prefilters\n\t\t * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n\t\t * 2) These are called:\n\t\t *    - BEFORE asking for a transport\n\t\t *    - AFTER param serialization (s.data is a string if s.processData is true)\n\t\t * 3) key is the dataType\n\t\t * 4) the catchall symbol \"*\" can be used\n\t\t * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n\t\t */\n\t\tprefilters = {},\n\n\t\t/* Transports bindings\n\t\t * 1) key is the dataType\n\t\t * 2) the catchall symbol \"*\" can be used\n\t\t * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n\t\t */\n\t\ttransports = {},\n\n\t\t// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression\n\t\tallTypes = \"*/\".concat( \"*\" ),\n\n\t\t// Anchor tag for parsing the document origin\n\t\toriginAnchor = document.createElement( \"a\" );\n\toriginAnchor.href = location.href;\n\n// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\n\tfunction addToPrefiltersOrTransports( structure ) {\n\n\t\t// dataTypeExpression is optional and defaults to \"*\"\n\t\treturn function( dataTypeExpression, func ) {\n\n\t\t\tif ( typeof dataTypeExpression !== \"string\" ) {\n\t\t\t\tfunc = dataTypeExpression;\n\t\t\t\tdataTypeExpression = \"*\";\n\t\t\t}\n\n\t\t\tvar dataType,\n\t\t\t\ti = 0,\n\t\t\t\tdataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || [];\n\n\t\t\tif ( jQuery.isFunction( func ) ) {\n\n\t\t\t\t// For each dataType in the dataTypeExpression\n\t\t\t\twhile ( ( dataType = dataTypes[ i++ ] ) ) {\n\n\t\t\t\t\t// Prepend if requested\n\t\t\t\t\tif ( dataType[ 0 ] === \"+\" ) {\n\t\t\t\t\t\tdataType = dataType.slice( 1 ) || \"*\";\n\t\t\t\t\t\t( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func );\n\n\t\t\t\t\t\t// Otherwise append\n\t\t\t\t\t} else {\n\t\t\t\t\t\t( structure[ dataType ] = structure[ dataType ] || [] ).push( func );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\n// Base inspection function for prefilters and transports\n\tfunction inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {\n\n\t\tvar inspected = {},\n\t\t\tseekingTransport = ( structure === transports );\n\n\t\tfunction inspect( dataType ) {\n\t\t\tvar selected;\n\t\t\tinspected[ dataType ] = true;\n\t\t\tjQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {\n\t\t\t\tvar dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );\n\t\t\t\tif ( typeof dataTypeOrTransport === \"string\" &&\n\t\t\t\t\t!seekingTransport && !inspected[ dataTypeOrTransport ] ) {\n\n\t\t\t\t\toptions.dataTypes.unshift( dataTypeOrTransport );\n\t\t\t\t\tinspect( dataTypeOrTransport );\n\t\t\t\t\treturn false;\n\t\t\t\t} else if ( seekingTransport ) {\n\t\t\t\t\treturn !( selected = dataTypeOrTransport );\n\t\t\t\t}\n\t\t\t} );\n\t\t\treturn selected;\n\t\t}\n\n\t\treturn inspect( options.dataTypes[ 0 ] ) || !inspected[ \"*\" ] && inspect( \"*\" );\n\t}\n\n// A special extend for ajax options\n// that takes \"flat\" options (not to be deep extended)\n// Fixes #9887\n\tfunction ajaxExtend( target, src ) {\n\t\tvar key, deep,\n\t\t\tflatOptions = jQuery.ajaxSettings.flatOptions || {};\n\n\t\tfor ( key in src ) {\n\t\t\tif ( src[ key ] !== undefined ) {\n\t\t\t\t( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];\n\t\t\t}\n\t\t}\n\t\tif ( deep ) {\n\t\t\tjQuery.extend( true, target, deep );\n\t\t}\n\n\t\treturn target;\n\t}\n\n\t/* Handles responses to an ajax request:\n\t * - finds the right dataType (mediates between content-type and expected dataType)\n\t * - returns the corresponding response\n\t */\n\tfunction ajaxHandleResponses( s, jqXHR, responses ) {\n\n\t\tvar ct, type, finalDataType, firstDataType,\n\t\t\tcontents = s.contents,\n\t\t\tdataTypes = s.dataTypes;\n\n\t\t// Remove auto dataType and get content-type in the process\n\t\twhile ( dataTypes[ 0 ] === \"*\" ) {\n\t\t\tdataTypes.shift();\n\t\t\tif ( ct === undefined ) {\n\t\t\t\tct = s.mimeType || jqXHR.getResponseHeader( \"Content-Type\" );\n\t\t\t}\n\t\t}\n\n\t\t// Check if we're dealing with a known content-type\n\t\tif ( ct ) {\n\t\t\tfor ( type in contents ) {\n\t\t\t\tif ( contents[ type ] && contents[ type ].test( ct ) ) {\n\t\t\t\t\tdataTypes.unshift( type );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Check to see if we have a response for the expected dataType\n\t\tif ( dataTypes[ 0 ] in responses ) {\n\t\t\tfinalDataType = dataTypes[ 0 ];\n\t\t} else {\n\n\t\t\t// Try convertible dataTypes\n\t\t\tfor ( type in responses ) {\n\t\t\t\tif ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[ 0 ] ] ) {\n\t\t\t\t\tfinalDataType = type;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif ( !firstDataType ) {\n\t\t\t\t\tfirstDataType = type;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Or just use first one\n\t\t\tfinalDataType = finalDataType || firstDataType;\n\t\t}\n\n\t\t// If we found a dataType\n\t\t// We add the dataType to the list if needed\n\t\t// and return the corresponding response\n\t\tif ( finalDataType ) {\n\t\t\tif ( finalDataType !== dataTypes[ 0 ] ) {\n\t\t\t\tdataTypes.unshift( finalDataType );\n\t\t\t}\n\t\t\treturn responses[ finalDataType ];\n\t\t}\n\t}\n\n\t/* Chain conversions given the request and the original response\n\t * Also sets the responseXXX fields on the jqXHR instance\n\t */\n\tfunction ajaxConvert( s, response, jqXHR, isSuccess ) {\n\t\tvar conv2, current, conv, tmp, prev,\n\t\t\tconverters = {},\n\n\t\t\t// Work with a copy of dataTypes in case we need to modify it for conversion\n\t\t\tdataTypes = s.dataTypes.slice();\n\n\t\t// Create converters map with lowercased keys\n\t\tif ( dataTypes[ 1 ] ) {\n\t\t\tfor ( conv in s.converters ) {\n\t\t\t\tconverters[ conv.toLowerCase() ] = s.converters[ conv ];\n\t\t\t}\n\t\t}\n\n\t\tcurrent = dataTypes.shift();\n\n\t\t// Convert to each sequential dataType\n\t\twhile ( current ) {\n\n\t\t\tif ( s.responseFields[ current ] ) {\n\t\t\t\tjqXHR[ s.responseFields[ current ] ] = response;\n\t\t\t}\n\n\t\t\t// Apply the dataFilter if provided\n\t\t\tif ( !prev && isSuccess && s.dataFilter ) {\n\t\t\t\tresponse = s.dataFilter( response, s.dataType );\n\t\t\t}\n\n\t\t\tprev = current;\n\t\t\tcurrent = dataTypes.shift();\n\n\t\t\tif ( current ) {\n\n\t\t\t\t// There's only work to do if current dataType is non-auto\n\t\t\t\tif ( current === \"*\" ) {\n\n\t\t\t\t\tcurrent = prev;\n\n\t\t\t\t\t// Convert response if prev dataType is non-auto and differs from current\n\t\t\t\t} else if ( prev !== \"*\" && prev !== current ) {\n\n\t\t\t\t\t// Seek a direct converter\n\t\t\t\t\tconv = converters[ prev + \" \" + current ] || converters[ \"* \" + current ];\n\n\t\t\t\t\t// If none found, seek a pair\n\t\t\t\t\tif ( !conv ) {\n\t\t\t\t\t\tfor ( conv2 in converters ) {\n\n\t\t\t\t\t\t\t// If conv2 outputs current\n\t\t\t\t\t\t\ttmp = conv2.split( \" \" );\n\t\t\t\t\t\t\tif ( tmp[ 1 ] === current ) {\n\n\t\t\t\t\t\t\t\t// If prev can be converted to accepted input\n\t\t\t\t\t\t\t\tconv = converters[ prev + \" \" + tmp[ 0 ] ] ||\n\t\t\t\t\t\t\t\t\tconverters[ \"* \" + tmp[ 0 ] ];\n\t\t\t\t\t\t\t\tif ( conv ) {\n\n\t\t\t\t\t\t\t\t\t// Condense equivalence converters\n\t\t\t\t\t\t\t\t\tif ( conv === true ) {\n\t\t\t\t\t\t\t\t\t\tconv = converters[ conv2 ];\n\n\t\t\t\t\t\t\t\t\t\t// Otherwise, insert the intermediate dataType\n\t\t\t\t\t\t\t\t\t} else if ( converters[ conv2 ] !== true ) {\n\t\t\t\t\t\t\t\t\t\tcurrent = tmp[ 0 ];\n\t\t\t\t\t\t\t\t\t\tdataTypes.unshift( tmp[ 1 ] );\n\t\t\t\t\t\t\t\t\t}\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\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Apply converter (if not an equivalence)\n\t\t\t\t\tif ( conv !== true ) {\n\n\t\t\t\t\t\t// Unless errors are allowed to bubble, catch and return them\n\t\t\t\t\t\tif ( conv && s.throws ) {\n\t\t\t\t\t\t\tresponse = conv( response );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tresponse = conv( response );\n\t\t\t\t\t\t\t} catch ( e ) {\n\t\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t\tstate: \"parsererror\",\n\t\t\t\t\t\t\t\t\terror: conv ? e : \"No conversion from \" + prev + \" to \" + current\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}\n\t\t}\n\n\t\treturn { state: \"success\", data: response };\n\t}\n\n\tjQuery.extend( {\n\n\t\t// Counter for holding the number of active queries\n\t\tactive: 0,\n\n\t\t// Last-Modified header cache for next request\n\t\tlastModified: {},\n\t\tetag: {},\n\n\t\tajaxSettings: {\n\t\t\turl: location.href,\n\t\t\ttype: \"GET\",\n\t\t\tisLocal: rlocalProtocol.test( location.protocol ),\n\t\t\tglobal: true,\n\t\t\tprocessData: true,\n\t\t\tasync: true,\n\t\t\tcontentType: \"application/x-www-form-urlencoded; charset=UTF-8\",\n\n\t\t\t/*\n\t\t\t timeout: 0,\n\t\t\t data: null,\n\t\t\t dataType: null,\n\t\t\t username: null,\n\t\t\t password: null,\n\t\t\t cache: null,\n\t\t\t throws: false,\n\t\t\t traditional: false,\n\t\t\t headers: {},\n\t\t\t */\n\n\t\t\taccepts: {\n\t\t\t\t\"*\": allTypes,\n\t\t\t\ttext: \"text/plain\",\n\t\t\t\thtml: \"text/html\",\n\t\t\t\txml: \"application/xml, text/xml\",\n\t\t\t\tjson: \"application/json, text/javascript\"\n\t\t\t},\n\n\t\t\tcontents: {\n\t\t\t\txml: /\\bxml\\b/,\n\t\t\t\thtml: /\\bhtml/,\n\t\t\t\tjson: /\\bjson\\b/\n\t\t\t},\n\n\t\t\tresponseFields: {\n\t\t\t\txml: \"responseXML\",\n\t\t\t\ttext: \"responseText\",\n\t\t\t\tjson: \"responseJSON\"\n\t\t\t},\n\n\t\t\t// Data converters\n\t\t\t// Keys separate source (or catchall \"*\") and destination types with a single space\n\t\t\tconverters: {\n\n\t\t\t\t// Convert anything to text\n\t\t\t\t\"* text\": String,\n\n\t\t\t\t// Text to html (true = no transformation)\n\t\t\t\t\"text html\": true,\n\n\t\t\t\t// Evaluate text as a json expression\n\t\t\t\t\"text json\": JSON.parse,\n\n\t\t\t\t// Parse text as xml\n\t\t\t\t\"text xml\": jQuery.parseXML\n\t\t\t},\n\n\t\t\t// For options that shouldn't be deep extended:\n\t\t\t// you can add your own custom options here if\n\t\t\t// and when you create one that shouldn't be\n\t\t\t// deep extended (see ajaxExtend)\n\t\t\tflatOptions: {\n\t\t\t\turl: true,\n\t\t\t\tcontext: true\n\t\t\t}\n\t\t},\n\n\t\t// Creates a full fledged settings object into target\n\t\t// with both ajaxSettings and settings fields.\n\t\t// If target is omitted, writes into ajaxSettings.\n\t\tajaxSetup: function( target, settings ) {\n\t\t\treturn settings ?\n\n\t\t\t\t// Building a settings object\n\t\t\t\tajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :\n\n\t\t\t\t// Extending ajaxSettings\n\t\t\t\tajaxExtend( jQuery.ajaxSettings, target );\n\t\t},\n\n\t\tajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n\t\tajaxTransport: addToPrefiltersOrTransports( transports ),\n\n\t\t// Main method\n\t\tajax: function( url, options ) {\n\n\t\t\t// If url is an object, simulate pre-1.5 signature\n\t\t\tif ( typeof url === \"object\" ) {\n\t\t\t\toptions = url;\n\t\t\t\turl = undefined;\n\t\t\t}\n\n\t\t\t// Force options to be an object\n\t\t\toptions = options || {};\n\n\t\t\tvar transport,\n\n\t\t\t\t// URL without anti-cache param\n\t\t\t\tcacheURL,\n\n\t\t\t\t// Response headers\n\t\t\t\tresponseHeadersString,\n\t\t\t\tresponseHeaders,\n\n\t\t\t\t// timeout handle\n\t\t\t\ttimeoutTimer,\n\n\t\t\t\t// Url cleanup var\n\t\t\t\turlAnchor,\n\n\t\t\t\t// Request state (becomes false upon send and true upon completion)\n\t\t\t\tcompleted,\n\n\t\t\t\t// To know if global events are to be dispatched\n\t\t\t\tfireGlobals,\n\n\t\t\t\t// Loop variable\n\t\t\t\ti,\n\n\t\t\t\t// uncached part of the url\n\t\t\t\tuncached,\n\n\t\t\t\t// Create the final options object\n\t\t\t\ts = jQuery.ajaxSetup( {}, options ),\n\n\t\t\t\t// Callbacks context\n\t\t\t\tcallbackContext = s.context || s,\n\n\t\t\t\t// Context for global events is callbackContext if it is a DOM node or jQuery collection\n\t\t\t\tglobalEventContext = s.context &&\n\t\t\t\t( callbackContext.nodeType || callbackContext.jquery ) ?\n\t\t\t\t\tjQuery( callbackContext ) :\n\t\t\t\t\tjQuery.event,\n\n\t\t\t\t// Deferreds\n\t\t\t\tdeferred = jQuery.Deferred(),\n\t\t\t\tcompleteDeferred = jQuery.Callbacks( \"once memory\" ),\n\n\t\t\t\t// Status-dependent callbacks\n\t\t\t\tstatusCode = s.statusCode || {},\n\n\t\t\t\t// Headers (they are sent all at once)\n\t\t\t\trequestHeaders = {},\n\t\t\t\trequestHeadersNames = {},\n\n\t\t\t\t// Default abort message\n\t\t\t\tstrAbort = \"canceled\",\n\n\t\t\t\t// Fake xhr\n\t\t\t\tjqXHR = {\n\t\t\t\t\treadyState: 0,\n\n\t\t\t\t\t// Builds headers hashtable if needed\n\t\t\t\t\tgetResponseHeader: function( key ) {\n\t\t\t\t\t\tvar match;\n\t\t\t\t\t\tif ( completed ) {\n\t\t\t\t\t\t\tif ( !responseHeaders ) {\n\t\t\t\t\t\t\t\tresponseHeaders = {};\n\t\t\t\t\t\t\t\twhile ( ( match = rheaders.exec( responseHeadersString ) ) ) {\n\t\t\t\t\t\t\t\t\tresponseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ];\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tmatch = responseHeaders[ key.toLowerCase() ];\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn match == null ? null : match;\n\t\t\t\t\t},\n\n\t\t\t\t\t// Raw string\n\t\t\t\t\tgetAllResponseHeaders: function() {\n\t\t\t\t\t\treturn completed ? responseHeadersString : null;\n\t\t\t\t\t},\n\n\t\t\t\t\t// Caches the header\n\t\t\t\t\tsetRequestHeader: function( name, value ) {\n\t\t\t\t\t\tif ( completed == null ) {\n\t\t\t\t\t\t\tname = requestHeadersNames[ name.toLowerCase() ] =\n\t\t\t\t\t\t\t\trequestHeadersNames[ name.toLowerCase() ] || name;\n\t\t\t\t\t\t\trequestHeaders[ name ] = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn this;\n\t\t\t\t\t},\n\n\t\t\t\t\t// Overrides response content-type header\n\t\t\t\t\toverrideMimeType: function( type ) {\n\t\t\t\t\t\tif ( completed == null ) {\n\t\t\t\t\t\t\ts.mimeType = type;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn this;\n\t\t\t\t\t},\n\n\t\t\t\t\t// Status-dependent callbacks\n\t\t\t\t\tstatusCode: function( map ) {\n\t\t\t\t\t\tvar code;\n\t\t\t\t\t\tif ( map ) {\n\t\t\t\t\t\t\tif ( completed ) {\n\n\t\t\t\t\t\t\t\t// Execute the appropriate callbacks\n\t\t\t\t\t\t\t\tjqXHR.always( map[ jqXHR.status ] );\n\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t// Lazy-add the new callbacks in a way that preserves old ones\n\t\t\t\t\t\t\t\tfor ( code in map ) {\n\t\t\t\t\t\t\t\t\tstatusCode[ code ] = [ statusCode[ code ], map[ code ] ];\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\treturn this;\n\t\t\t\t\t},\n\n\t\t\t\t\t// Cancel the request\n\t\t\t\t\tabort: function( statusText ) {\n\t\t\t\t\t\tvar finalText = statusText || strAbort;\n\t\t\t\t\t\tif ( transport ) {\n\t\t\t\t\t\t\ttransport.abort( finalText );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdone( 0, finalText );\n\t\t\t\t\t\treturn this;\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t// Attach deferreds\n\t\t\tdeferred.promise( jqXHR );\n\n\t\t\t// Add protocol if not provided (prefilters might expect it)\n\t\t\t// Handle falsy url in the settings object (#10093: consistency with old signature)\n\t\t\t// We also use the url parameter if available\n\t\t\ts.url = ( ( url || s.url || location.href ) + \"\" )\n\t\t\t\t.replace( rprotocol, location.protocol + \"//\" );\n\n\t\t\t// Alias method option to type as per ticket #12004\n\t\t\ts.type = options.method || options.type || s.method || s.type;\n\n\t\t\t// Extract dataTypes list\n\t\t\ts.dataTypes = ( s.dataType || \"*\" ).toLowerCase().match( rnothtmlwhite ) || [ \"\" ];\n\n\t\t\t// A cross-domain request is in order when the origin doesn't match the current origin.\n\t\t\tif ( s.crossDomain == null ) {\n\t\t\t\turlAnchor = document.createElement( \"a\" );\n\n\t\t\t\t// Support: IE <=8 - 11, Edge 12 - 13\n\t\t\t\t// IE throws exception on accessing the href property if url is malformed,\n\t\t\t\t// e.g. http://example.com:80x/\n\t\t\t\ttry {\n\t\t\t\t\turlAnchor.href = s.url;\n\n\t\t\t\t\t// Support: IE <=8 - 11 only\n\t\t\t\t\t// Anchor's host property isn't correctly set when s.url is relative\n\t\t\t\t\turlAnchor.href = urlAnchor.href;\n\t\t\t\t\ts.crossDomain = originAnchor.protocol + \"//\" + originAnchor.host !==\n\t\t\t\t\t\turlAnchor.protocol + \"//\" + urlAnchor.host;\n\t\t\t\t} catch ( e ) {\n\n\t\t\t\t\t// If there is an error parsing the URL, assume it is crossDomain,\n\t\t\t\t\t// it can be rejected by the transport if it is invalid\n\t\t\t\t\ts.crossDomain = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Convert data if not already a string\n\t\t\tif ( s.data && s.processData && typeof s.data !== \"string\" ) {\n\t\t\t\ts.data = jQuery.param( s.data, s.traditional );\n\t\t\t}\n\n\t\t\t// Apply prefilters\n\t\t\tinspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n\t\t\t// If request was aborted inside a prefilter, stop there\n\t\t\tif ( completed ) {\n\n\t\t\t\treturn jqXHR;\n\t\t\t}\n\n\t\t\t// We can fire global events as of now if asked to\n\t\t\t// Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)\n\t\t\tfireGlobals = jQuery.event && s.global;\n\n\t\t\t// Watch for a new set of requests\n\t\t\tif ( fireGlobals && jQuery.active++ === 0 ) {\n\t\t\t\tjQuery.event.trigger( \"ajaxStart\" );\n\t\t\t}\n\n\t\t\t// Uppercase the type\n\t\t\ts.type = s.type.toUpperCase();\n\n\t\t\t// Determine if request has content\n\t\t\ts.hasContent = !rnoContent.test( s.type );\n\n\t\t\t// Save the URL in case we're toying with the If-Modified-Since\n\t\t\t// and/or If-None-Match header later on\n\t\t\t// Remove hash to simplify url manipulation\n\t\t\tcacheURL = s.url.replace( rhash, \"\" );\n\n\t\t\t// More options handling for requests with no content\n\t\t\tif ( !s.hasContent ) {\n\n\t\t\t\t// Remember the hash so we can put it back\n\t\t\t\tuncached = s.url.slice( cacheURL.length );\n\n\t\t\t\t// If data is available, append data to url\n\t\t\t\tif ( s.data ) {\n\t\t\t\t\tcacheURL += ( rquery.test( cacheURL ) ? \"&\" : \"?\" ) + s.data;\n\n\t\t\t\t\t// #9682: remove data so that it's not used in an eventual retry\n\t\t\t\t\tdelete s.data;\n\t\t\t\t}\n\n\t\t\t\t// Add or update anti-cache param if needed\n\t\t\t\tif ( s.cache === false ) {\n\t\t\t\t\tcacheURL = cacheURL.replace( rantiCache, \"$1\" );\n\t\t\t\t\tuncached = ( rquery.test( cacheURL ) ? \"&\" : \"?\" ) + \"_=\" + ( nonce++ ) + uncached;\n\t\t\t\t}\n\n\t\t\t\t// Put hash and anti-cache on the URL that will be requested (gh-1732)\n\t\t\t\ts.url = cacheURL + uncached;\n\n\t\t\t\t// Change '%20' to '+' if this is encoded form body content (gh-2658)\n\t\t\t} else if ( s.data && s.processData &&\n\t\t\t\t( s.contentType || \"\" ).indexOf( \"application/x-www-form-urlencoded\" ) === 0 ) {\n\t\t\t\ts.data = s.data.replace( r20, \"+\" );\n\t\t\t}\n\n\t\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\t\tif ( s.ifModified ) {\n\t\t\t\tif ( jQuery.lastModified[ cacheURL ] ) {\n\t\t\t\t\tjqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ cacheURL ] );\n\t\t\t\t}\n\t\t\t\tif ( jQuery.etag[ cacheURL ] ) {\n\t\t\t\t\tjqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ cacheURL ] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the correct header, if data is being sent\n\t\t\tif ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n\t\t\t\tjqXHR.setRequestHeader( \"Content-Type\", s.contentType );\n\t\t\t}\n\n\t\t\t// Set the Accepts header for the server, depending on the dataType\n\t\t\tjqXHR.setRequestHeader(\n\t\t\t\t\"Accept\",\n\t\t\t\ts.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ?\n\t\t\t\ts.accepts[ s.dataTypes[ 0 ] ] +\n\t\t\t\t( s.dataTypes[ 0 ] !== \"*\" ? \", \" + allTypes + \"; q=0.01\" : \"\" ) :\n\t\t\t\t\ts.accepts[ \"*\" ]\n\t\t\t);\n\n\t\t\t// Check for headers option\n\t\t\tfor ( i in s.headers ) {\n\t\t\t\tjqXHR.setRequestHeader( i, s.headers[ i ] );\n\t\t\t}\n\n\t\t\t// Allow custom headers/mimetypes and early abort\n\t\t\tif ( s.beforeSend &&\n\t\t\t\t( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) {\n\n\t\t\t\t// Abort if not done already and return\n\t\t\t\treturn jqXHR.abort();\n\t\t\t}\n\n\t\t\t// Aborting is no longer a cancellation\n\t\t\tstrAbort = \"abort\";\n\n\t\t\t// Install callbacks on deferreds\n\t\t\tcompleteDeferred.add( s.complete );\n\t\t\tjqXHR.done( s.success );\n\t\t\tjqXHR.fail( s.error );\n\n\t\t\t// Get transport\n\t\t\ttransport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n\n\t\t\t// If no transport, we auto-abort\n\t\t\tif ( !transport ) {\n\t\t\t\tdone( -1, \"No Transport\" );\n\t\t\t} else {\n\t\t\t\tjqXHR.readyState = 1;\n\n\t\t\t\t// Send global event\n\t\t\t\tif ( fireGlobals ) {\n\t\t\t\t\tglobalEventContext.trigger( \"ajaxSend\", [ jqXHR, s ] );\n\t\t\t\t}\n\n\t\t\t\t// If request was aborted inside ajaxSend, stop there\n\t\t\t\tif ( completed ) {\n\t\t\t\t\treturn jqXHR;\n\t\t\t\t}\n\n\t\t\t\t// Timeout\n\t\t\t\tif ( s.async && s.timeout > 0 ) {\n\t\t\t\t\ttimeoutTimer = window.setTimeout( function() {\n\t\t\t\t\t\tjqXHR.abort( \"timeout\" );\n\t\t\t\t\t}, s.timeout );\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tcompleted = false;\n\t\t\t\t\ttransport.send( requestHeaders, done );\n\t\t\t\t} catch ( e ) {\n\n\t\t\t\t\t// Rethrow post-completion exceptions\n\t\t\t\t\tif ( completed ) {\n\t\t\t\t\t\tthrow e;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Propagate others as results\n\t\t\t\t\tdone( -1, e );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Callback for when everything is done\n\t\t\tfunction done( status, nativeStatusText, responses, headers ) {\n\t\t\t\tvar isSuccess, success, error, response, modified,\n\t\t\t\t\tstatusText = nativeStatusText;\n\n\t\t\t\t// Ignore repeat invocations\n\t\t\t\tif ( completed ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tcompleted = true;\n\n\t\t\t\t// Clear timeout if it exists\n\t\t\t\tif ( timeoutTimer ) {\n\t\t\t\t\twindow.clearTimeout( timeoutTimer );\n\t\t\t\t}\n\n\t\t\t\t// Dereference transport for early garbage collection\n\t\t\t\t// (no matter how long the jqXHR object will be used)\n\t\t\t\ttransport = undefined;\n\n\t\t\t\t// Cache response headers\n\t\t\t\tresponseHeadersString = headers || \"\";\n\n\t\t\t\t// Set readyState\n\t\t\t\tjqXHR.readyState = status > 0 ? 4 : 0;\n\n\t\t\t\t// Determine if successful\n\t\t\t\tisSuccess = status >= 200 && status < 300 || status === 304;\n\n\t\t\t\t// Get response data\n\t\t\t\tif ( responses ) {\n\t\t\t\t\tresponse = ajaxHandleResponses( s, jqXHR, responses );\n\t\t\t\t}\n\n\t\t\t\t// Convert no matter what (that way responseXXX fields are always set)\n\t\t\t\tresponse = ajaxConvert( s, response, jqXHR, isSuccess );\n\n\t\t\t\t// If successful, handle type chaining\n\t\t\t\tif ( isSuccess ) {\n\t\t\t\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\t\t\t\tif ( s.ifModified ) {\n\t\t\t\t\t\tmodified = jqXHR.getResponseHeader( \"Last-Modified\" );\n\t\t\t\t\t\tif ( modified ) {\n\t\t\t\t\t\t\tjQuery.lastModified[ cacheURL ] = modified;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmodified = jqXHR.getResponseHeader( \"etag\" );\n\t\t\t\t\t\tif ( modified ) {\n\t\t\t\t\t\t\tjQuery.etag[ cacheURL ] = modified;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// if no content\n\t\t\t\t\tif ( status === 204 || s.type === \"HEAD\" ) {\n\t\t\t\t\t\tstatusText = \"nocontent\";\n\n\t\t\t\t\t\t// if not modified\n\t\t\t\t\t} else if ( status === 304 ) {\n\t\t\t\t\t\tstatusText = \"notmodified\";\n\n\t\t\t\t\t\t// If we have data, let's convert it\n\t\t\t\t\t} else {\n\t\t\t\t\t\tstatusText = response.state;\n\t\t\t\t\t\tsuccess = response.data;\n\t\t\t\t\t\terror = response.error;\n\t\t\t\t\t\tisSuccess = !error;\n\t\t\t\t\t\tdebugger;\n\t\t\t\t\t\tif(success==\"401\"){\n\t\t\t\t\t\t\twindow.location.href=\"/login\";\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\n\t\t\t\t\t// Extract error from statusText and normalize for non-aborts\n\t\t\t\t\terror = statusText;\n\t\t\t\t\tif ( status || !statusText ) {\n\t\t\t\t\t\tstatusText = \"error\";\n\t\t\t\t\t\tif ( status < 0 ) {\n\t\t\t\t\t\t\tstatus = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Set data for the fake xhr object\n\t\t\t\tjqXHR.status = status;\n\t\t\t\tjqXHR.statusText = ( nativeStatusText || statusText ) + \"\";\n\n\t\t\t\t// Success/Error\n\t\t\t\tif ( isSuccess ) {\n\t\t\t\t\tdeferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n\t\t\t\t} else {\n\t\t\t\t\tdeferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n\t\t\t\t}\n\n\t\t\t\t// Status-dependent callbacks\n\t\t\t\tjqXHR.statusCode( statusCode );\n\t\t\t\tstatusCode = undefined;\n\n\t\t\t\tif ( fireGlobals ) {\n\t\t\t\t\tglobalEventContext.trigger( isSuccess ? \"ajaxSuccess\" : \"ajaxError\",\n\t\t\t\t\t\t[ jqXHR, s, isSuccess ? success : error ] );\n\t\t\t\t}\n\n\t\t\t\t// Complete\n\t\t\t\tcompleteDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );\n\n\t\t\t\tif ( fireGlobals ) {\n\t\t\t\t\tglobalEventContext.trigger( \"ajaxComplete\", [ jqXHR, s ] );\n\n\t\t\t\t\t// Handle the global AJAX counter\n\t\t\t\t\tif ( !( --jQuery.active ) ) {\n\t\t\t\t\t\tjQuery.event.trigger( \"ajaxStop\" );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn jqXHR;\n\t\t},\n\n\t\tgetJSON: function( url, data, callback ) {\n\t\t\treturn jQuery.get( url, data, callback, \"json\" );\n\t\t},\n\n\t\tgetScript: function( url, callback ) {\n\t\t\treturn jQuery.get( url, undefined, callback, \"script\" );\n\t\t}\n\t} );\n\n\tjQuery.each( [ \"get\", \"post\" ], function( i, method ) {\n\t\tjQuery[ method ] = function( url, data, callback, type ) {\n\n\t\t\t// Shift arguments if data argument was omitted\n\t\t\tif ( jQuery.isFunction( data ) ) {\n\t\t\t\ttype = type || callback;\n\t\t\t\tcallback = data;\n\t\t\t\tdata = undefined;\n\t\t\t}\n\n\t\t\t// The url can be an options object (which then must have .url)\n\t\t\treturn jQuery.ajax( jQuery.extend( {\n\t\t\t\turl: url,\n\t\t\t\ttype: method,\n\t\t\t\tdataType: type,\n\t\t\t\tdata: data,\n\t\t\t\tsuccess: callback\n\t\t\t}, jQuery.isPlainObject( url ) && url ) );\n\t\t};\n\t} );\n\n\n\tjQuery._evalUrl = function( url ) {\n\t\treturn jQuery.ajax( {\n\t\t\turl: url,\n\n\t\t\t// Make this explicit, since user can override this through ajaxSetup (#11264)\n\t\t\ttype: \"GET\",\n\t\t\tdataType: \"script\",\n\t\t\tcache: true,\n\t\t\tasync: false,\n\t\t\tglobal: false,\n\t\t\t\"throws\": true\n\t\t} );\n\t};\n\n\n\tjQuery.fn.extend( {\n\t\twrapAll: function( html ) {\n\t\t\tvar wrap;\n\n\t\t\tif ( this[ 0 ] ) {\n\t\t\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\t\t\thtml = html.call( this[ 0 ] );\n\t\t\t\t}\n\n\t\t\t\t// The elements to wrap the target around\n\t\t\t\twrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );\n\n\t\t\t\tif ( this[ 0 ].parentNode ) {\n\t\t\t\t\twrap.insertBefore( this[ 0 ] );\n\t\t\t\t}\n\n\t\t\t\twrap.map( function() {\n\t\t\t\t\tvar elem = this;\n\n\t\t\t\t\twhile ( elem.firstElementChild ) {\n\t\t\t\t\t\telem = elem.firstElementChild;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn elem;\n\t\t\t\t} ).append( this );\n\t\t\t}\n\n\t\t\treturn this;\n\t\t},\n\n\t\twrapInner: function( html ) {\n\t\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\t\treturn this.each( function( i ) {\n\t\t\t\t\tjQuery( this ).wrapInner( html.call( this, i ) );\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\treturn this.each( function() {\n\t\t\t\tvar self = jQuery( this ),\n\t\t\t\t\tcontents = self.contents();\n\n\t\t\t\tif ( contents.length ) {\n\t\t\t\t\tcontents.wrapAll( html );\n\n\t\t\t\t} else {\n\t\t\t\t\tself.append( html );\n\t\t\t\t}\n\t\t\t} );\n\t\t},\n\n\t\twrap: function( html ) {\n\t\t\tvar isFunction = jQuery.isFunction( html );\n\n\t\t\treturn this.each( function( i ) {\n\t\t\t\tjQuery( this ).wrapAll( isFunction ? html.call( this, i ) : html );\n\t\t\t} );\n\t\t},\n\n\t\tunwrap: function( selector ) {\n\t\t\tthis.parent( selector ).not( \"body\" ).each( function() {\n\t\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t\t} );\n\t\t\treturn this;\n\t\t}\n\t} );\n\n\n\tjQuery.expr.pseudos.hidden = function( elem ) {\n\t\treturn !jQuery.expr.pseudos.visible( elem );\n\t};\n\tjQuery.expr.pseudos.visible = function( elem ) {\n\t\treturn !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length );\n\t};\n\n\n\n\n\tjQuery.ajaxSettings.xhr = function() {\n\t\ttry {\n\t\t\treturn new window.XMLHttpRequest();\n\t\t} catch ( e ) {}\n\t};\n\n\tvar xhrSuccessStatus = {\n\n\t\t\t// File protocol always yields status code 0, assume 200\n\t\t\t0: 200,\n\n\t\t\t// Support: IE <=9 only\n\t\t\t// #1450: sometimes IE returns 1223 when it should be 204\n\t\t\t1223: 204\n\t\t},\n\t\txhrSupported = jQuery.ajaxSettings.xhr();\n\n\tsupport.cors = !!xhrSupported && ( \"withCredentials\" in xhrSupported );\n\tsupport.ajax = xhrSupported = !!xhrSupported;\n\n\tjQuery.ajaxTransport( function( options ) {\n\t\tvar callback, errorCallback;\n\n\t\t// Cross domain only allowed if supported through XMLHttpRequest\n\t\tif ( support.cors || xhrSupported && !options.crossDomain ) {\n\t\t\treturn {\n\t\t\t\tsend: function( headers, complete ) {\n\t\t\t\t\tvar i,\n\t\t\t\t\t\txhr = options.xhr();\n\n\t\t\t\t\txhr.open(\n\t\t\t\t\t\toptions.type,\n\t\t\t\t\t\toptions.url,\n\t\t\t\t\t\toptions.async,\n\t\t\t\t\t\toptions.username,\n\t\t\t\t\t\toptions.password\n\t\t\t\t\t);\n\n\t\t\t\t\t// Apply custom fields if provided\n\t\t\t\t\tif ( options.xhrFields ) {\n\t\t\t\t\t\tfor ( i in options.xhrFields ) {\n\t\t\t\t\t\t\txhr[ i ] = options.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 ( options.mimeType && xhr.overrideMimeType ) {\n\t\t\t\t\t\txhr.overrideMimeType( options.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 ( !options.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// Set headers\n\t\t\t\t\tfor ( i in headers ) {\n\t\t\t\t\t\txhr.setRequestHeader( i, headers[ i ] );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Callback\n\t\t\t\t\tcallback = function( type ) {\n\t\t\t\t\t\treturn function() {\n\t\t\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\t\t\tcallback = errorCallback = xhr.onload =\n\t\t\t\t\t\t\t\t\txhr.onerror = xhr.onabort = xhr.onreadystatechange = null;\n\n\t\t\t\t\t\t\t\tif ( type === \"abort\" ) {\n\t\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t\t} else if ( type === \"error\" ) {\n\n\t\t\t\t\t\t\t\t\t// Support: IE <=9 only\n\t\t\t\t\t\t\t\t\t// On a manual native abort, IE9 throws\n\t\t\t\t\t\t\t\t\t// errors on any property access that is not readyState\n\t\t\t\t\t\t\t\t\tif ( typeof xhr.status !== \"number\" ) {\n\t\t\t\t\t\t\t\t\t\tcomplete( 0, \"error\" );\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tcomplete(\n\n\t\t\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\t\t\txhr.status,\n\t\t\t\t\t\t\t\t\t\t\txhr.statusText\n\t\t\t\t\t\t\t\t\t\t);\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\tcomplete(\n\t\t\t\t\t\t\t\t\t\txhrSuccessStatus[ xhr.status ] || xhr.status,\n\t\t\t\t\t\t\t\t\t\txhr.statusText,\n\n\t\t\t\t\t\t\t\t\t\t// Support: IE <=9 only\n\t\t\t\t\t\t\t\t\t\t// IE9 has no XHR2 but throws on binary (trac-11426)\n\t\t\t\t\t\t\t\t\t\t// For XHR2 non-text, let the caller handle it (gh-2498)\n\t\t\t\t\t\t\t\t\t\t( xhr.responseType || \"text\" ) !== \"text\"  ||\n\t\t\t\t\t\t\t\t\t\ttypeof xhr.responseText !== \"string\" ?\n\t\t\t\t\t\t\t\t\t\t{ binary: xhr.response } :\n\t\t\t\t\t\t\t\t\t\t{ text: xhr.responseText },\n\t\t\t\t\t\t\t\t\t\txhr.getAllResponseHeaders()\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};\n\n\t\t\t\t\t// Listen to events\n\t\t\t\t\txhr.onload = callback();\n\t\t\t\t\terrorCallback = xhr.onerror = callback( \"error\" );\n\n\t\t\t\t\t// Support: IE 9 only\n\t\t\t\t\t// Use onreadystatechange to replace onabort\n\t\t\t\t\t// to handle uncaught aborts\n\t\t\t\t\tif ( xhr.onabort !== undefined ) {\n\t\t\t\t\t\txhr.onabort = errorCallback;\n\t\t\t\t\t} else {\n\t\t\t\t\t\txhr.onreadystatechange = function() {\n\n\t\t\t\t\t\t\t// Check readyState before timeout as it changes\n\t\t\t\t\t\t\tif ( xhr.readyState === 4 ) {\n\n\t\t\t\t\t\t\t\t// Allow onerror to be called first,\n\t\t\t\t\t\t\t\t// but that will not handle a native abort\n\t\t\t\t\t\t\t\t// Also, save errorCallback to a variable\n\t\t\t\t\t\t\t\t// as xhr.onerror cannot be accessed\n\t\t\t\t\t\t\t\twindow.setTimeout( function() {\n\t\t\t\t\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\t\t\t\t\terrorCallback();\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}\n\n\t\t\t\t\t// Create the abort callback\n\t\t\t\t\tcallback = callback( \"abort\" );\n\n\t\t\t\t\ttry {\n\n\t\t\t\t\t\t// Do send the request (this may raise an exception)\n\t\t\t\t\t\txhr.send( options.hasContent && options.data || null );\n\t\t\t\t\t} catch ( e ) {\n\n\t\t\t\t\t\t// #14683: Only rethrow if this hasn't been notified as an error yet\n\t\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\t\tthrow e;\n\t\t\t\t\t\t}\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();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t} );\n\n\n\n\n// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432)\n\tjQuery.ajaxPrefilter( function( s ) {\n\t\tif ( s.crossDomain ) {\n\t\t\ts.contents.script = false;\n\t\t}\n\t} );\n\n// Install script dataType\n\tjQuery.ajaxSetup( {\n\t\taccepts: {\n\t\t\tscript: \"text/javascript, application/javascript, \" +\n\t\t\t\"application/ecmascript, application/x-ecmascript\"\n\t\t},\n\t\tcontents: {\n\t\t\tscript: /\\b(?:java|ecma)script\\b/\n\t\t},\n\t\tconverters: {\n\t\t\t\"text script\": function( text ) {\n\t\t\t\tjQuery.globalEval( text );\n\t\t\t\treturn text;\n\t\t\t}\n\t\t}\n\t} );\n\n// Handle cache's special case and crossDomain\n\tjQuery.ajaxPrefilter( \"script\", function( s ) {\n\t\tif ( s.cache === undefined ) {\n\t\t\ts.cache = false;\n\t\t}\n\t\tif ( s.crossDomain ) {\n\t\t\ts.type = \"GET\";\n\t\t}\n\t} );\n\n// Bind script tag hack transport\n\tjQuery.ajaxTransport( \"script\", function( s ) {\n\n\t\t// This transport only deals with cross domain requests\n\t\tif ( s.crossDomain ) {\n\t\t\tvar script, callback;\n\t\t\treturn {\n\t\t\t\tsend: function( _, complete ) {\n\t\t\t\t\tscript = jQuery( \"<script>\" ).prop( {\n\t\t\t\t\t\tcharset: s.scriptCharset,\n\t\t\t\t\t\tsrc: s.url\n\t\t\t\t\t} ).on(\n\t\t\t\t\t\t\"load error\",\n\t\t\t\t\t\tcallback = function( evt ) {\n\t\t\t\t\t\t\tscript.remove();\n\t\t\t\t\t\t\tcallback = null;\n\t\t\t\t\t\t\tif ( evt ) {\n\t\t\t\t\t\t\t\tcomplete( evt.type === \"error\" ? 404 : 200, evt.type );\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// Use native DOM manipulation to avoid our domManip AJAX trickery\n\t\t\t\t\tdocument.head.appendChild( script[ 0 ] );\n\t\t\t\t},\n\t\t\t\tabort: function() {\n\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\tcallback();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t} );\n\n\n\n\n\tvar oldCallbacks = [],\n\t\trjsonp = /(=)\\?(?=&|$)|\\?\\?/;\n\n// Default jsonp settings\n\tjQuery.ajaxSetup( {\n\t\tjsonp: \"callback\",\n\t\tjsonpCallback: function() {\n\t\t\tvar callback = oldCallbacks.pop() || ( jQuery.expando + \"_\" + ( nonce++ ) );\n\t\t\tthis[ callback ] = true;\n\t\t\treturn callback;\n\t\t}\n\t} );\n\n// Detect, normalize options and install callbacks for jsonp requests\n\tjQuery.ajaxPrefilter( \"json jsonp\", function( s, originalSettings, jqXHR ) {\n\n\t\tvar callbackName, overwritten, responseContainer,\n\t\t\tjsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?\n\t\t\t\t\t\t\"url\" :\n\t\t\t\t\ttypeof s.data === \"string\" &&\n\t\t\t\t\t( s.contentType || \"\" )\n\t\t\t\t\t\t.indexOf( \"application/x-www-form-urlencoded\" ) === 0 &&\n\t\t\t\t\trjsonp.test( s.data ) && \"data\"\n\t\t\t\t);\n\n\t\t// Handle iff the expected data type is \"jsonp\" or we have a parameter to set\n\t\tif ( jsonProp || s.dataTypes[ 0 ] === \"jsonp\" ) {\n\n\t\t\t// Get callback name, remembering preexisting value associated with it\n\t\t\tcallbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?\n\t\t\t\ts.jsonpCallback() :\n\t\t\t\ts.jsonpCallback;\n\n\t\t\t// Insert callback into url or form data\n\t\t\tif ( jsonProp ) {\n\t\t\t\ts[ jsonProp ] = s[ jsonProp ].replace( rjsonp, \"$1\" + callbackName );\n\t\t\t} else if ( s.jsonp !== false ) {\n\t\t\t\ts.url += ( rquery.test( s.url ) ? \"&\" : \"?\" ) + s.jsonp + \"=\" + callbackName;\n\t\t\t}\n\n\t\t\t// Use data converter to retrieve json after script execution\n\t\t\ts.converters[ \"script json\" ] = function() {\n\t\t\t\tif ( !responseContainer ) {\n\t\t\t\t\tjQuery.error( callbackName + \" was not called\" );\n\t\t\t\t}\n\t\t\t\treturn responseContainer[ 0 ];\n\t\t\t};\n\n\t\t\t// Force json dataType\n\t\t\ts.dataTypes[ 0 ] = \"json\";\n\n\t\t\t// Install callback\n\t\t\toverwritten = window[ callbackName ];\n\t\t\twindow[ callbackName ] = function() {\n\t\t\t\tresponseContainer = arguments;\n\t\t\t};\n\n\t\t\t// Clean-up function (fires after converters)\n\t\t\tjqXHR.always( function() {\n\n\t\t\t\t// If previous value didn't exist - remove it\n\t\t\t\tif ( overwritten === undefined ) {\n\t\t\t\t\tjQuery( window ).removeProp( callbackName );\n\n\t\t\t\t\t// Otherwise restore preexisting value\n\t\t\t\t} else {\n\t\t\t\t\twindow[ callbackName ] = overwritten;\n\t\t\t\t}\n\n\t\t\t\t// Save back as free\n\t\t\t\tif ( s[ callbackName ] ) {\n\n\t\t\t\t\t// Make sure that re-using the options doesn't screw things around\n\t\t\t\t\ts.jsonpCallback = originalSettings.jsonpCallback;\n\n\t\t\t\t\t// Save the callback name for future use\n\t\t\t\t\toldCallbacks.push( callbackName );\n\t\t\t\t}\n\n\t\t\t\t// Call if it was a function and we have a response\n\t\t\t\tif ( responseContainer && jQuery.isFunction( overwritten ) ) {\n\t\t\t\t\toverwritten( responseContainer[ 0 ] );\n\t\t\t\t}\n\n\t\t\t\tresponseContainer = overwritten = undefined;\n\t\t\t} );\n\n\t\t\t// Delegate to script\n\t\t\treturn \"script\";\n\t\t}\n\t} );\n\n\n\n\n// Support: Safari 8 only\n// In Safari 8 documents created via document.implementation.createHTMLDocument\n// collapse sibling forms: the second one becomes a child of the first one.\n// Because of that, this security measure has to be disabled in Safari 8.\n// https://bugs.webkit.org/show_bug.cgi?id=137337\n\tsupport.createHTMLDocument = ( function() {\n\t\tvar body = document.implementation.createHTMLDocument( \"\" ).body;\n\t\tbody.innerHTML = \"<form></form><form></form>\";\n\t\treturn body.childNodes.length === 2;\n\t} )();\n\n\n// Argument \"data\" should be string of html\n// context (optional): If specified, the fragment will be created in this context,\n// defaults to document\n// keepScripts (optional): If true, will include scripts passed in the html string\n\tjQuery.parseHTML = function( data, context, keepScripts ) {\n\t\tif ( typeof data !== \"string\" ) {\n\t\t\treturn [];\n\t\t}\n\t\tif ( typeof context === \"boolean\" ) {\n\t\t\tkeepScripts = context;\n\t\t\tcontext = false;\n\t\t}\n\n\t\tvar base, parsed, scripts;\n\n\t\tif ( !context ) {\n\n\t\t\t// Stop scripts or inline event handlers from being executed immediately\n\t\t\t// by using document.implementation\n\t\t\tif ( support.createHTMLDocument ) {\n\t\t\t\tcontext = document.implementation.createHTMLDocument( \"\" );\n\n\t\t\t\t// Set the base href for the created document\n\t\t\t\t// so any parsed elements with URLs\n\t\t\t\t// are based on the document's URL (gh-2965)\n\t\t\t\tbase = context.createElement( \"base\" );\n\t\t\t\tbase.href = document.location.href;\n\t\t\t\tcontext.head.appendChild( base );\n\t\t\t} else {\n\t\t\t\tcontext = document;\n\t\t\t}\n\t\t}\n\n\t\tparsed = rsingleTag.exec( data );\n\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 = buildFragment( [ data ], context, scripts );\n\n\t\tif ( scripts && scripts.length ) {\n\t\t\tjQuery( scripts ).remove();\n\t\t}\n\n\t\treturn jQuery.merge( [], parsed.childNodes );\n\t};\n\n\n\t/**\n\t * Load a url into a page\n\t */\n\tjQuery.fn.load = function( url, params, callback ) {\n\t\tvar selector, type, response,\n\t\t\tself = this,\n\t\t\toff = url.indexOf( \" \" );\n\n\t\tif ( off > -1 ) {\n\t\t\tselector = stripAndCollapse( url.slice( off ) );\n\t\t\turl = url.slice( 0, off );\n\t\t}\n\n\t\t// If it's a function\n\t\tif ( jQuery.isFunction( params ) ) {\n\n\t\t\t// We assume that it's the callback\n\t\t\tcallback = params;\n\t\t\tparams = undefined;\n\n\t\t\t// Otherwise, build a param string\n\t\t} else if ( params && typeof params === \"object\" ) {\n\t\t\ttype = \"POST\";\n\t\t}\n\n\t\t// If we have elements to modify, make the request\n\t\tif ( self.length > 0 ) {\n\t\t\tjQuery.ajax( {\n\t\t\t\turl: url,\n\n\t\t\t\t// If \"type\" variable is undefined, then \"GET\" method will be used.\n\t\t\t\t// Make value of this field explicit since\n\t\t\t\t// user can override it through ajaxSetup method\n\t\t\t\ttype: type || \"GET\",\n\t\t\t\tdataType: \"html\",\n\t\t\t\tdata: params\n\t\t\t} ).done( function( responseText ) {\n\n\t\t\t\t// Save response for use in complete callback\n\t\t\t\tresponse = arguments;\n\n\t\t\t\tself.html( selector ?\n\n\t\t\t\t\t// If a selector was specified, locate the right elements in a dummy div\n\t\t\t\t\t// Exclude scripts to avoid IE 'Permission Denied' errors\n\t\t\t\t\tjQuery( \"<div>\" ).append( jQuery.parseHTML( responseText ) ).find( selector ) :\n\n\t\t\t\t\t// Otherwise use the full result\n\t\t\t\t\tresponseText );\n\n\t\t\t\t// If the request succeeds, this function gets \"data\", \"status\", \"jqXHR\"\n\t\t\t\t// but they are ignored because response was set above.\n\t\t\t\t// If it fails, this function gets \"jqXHR\", \"status\", \"error\"\n\t\t\t} ).always( callback && function( jqXHR, status ) {\n\t\t\t\t\tself.each( function() {\n\t\t\t\t\t\tcallback.apply( this, response || [ jqXHR.responseText, status, jqXHR ] );\n\t\t\t\t\t} );\n\t\t\t\t} );\n\t\t}\n\n\t\treturn this;\n\t};\n\n\n\n\n// Attach a bunch of functions for handling common AJAX events\n\tjQuery.each( [\n\t\t\"ajaxStart\",\n\t\t\"ajaxStop\",\n\t\t\"ajaxComplete\",\n\t\t\"ajaxError\",\n\t\t\"ajaxSuccess\",\n\t\t\"ajaxSend\"\n\t], function( i, type ) {\n\t\tjQuery.fn[ type ] = function( fn ) {\n\t\t\treturn this.on( type, fn );\n\t\t};\n\t} );\n\n\n\n\n\tjQuery.expr.pseudos.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\n\n\n\n\tjQuery.offset = {\n\t\tsetOffset: function( elem, options, i ) {\n\t\t\tvar curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,\n\t\t\t\tposition = jQuery.css( elem, \"position\" ),\n\t\t\t\tcurElem = jQuery( elem ),\n\t\t\t\tprops = {};\n\n\t\t\t// Set position first, in-case top/left are set even on static elem\n\t\t\tif ( position === \"static\" ) {\n\t\t\t\telem.style.position = \"relative\";\n\t\t\t}\n\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\" ) &&\n\t\t\t\t( curCSSTop + curCSSLeft ).indexOf( \"auto\" ) > -1;\n\n\t\t\t// Need to be able to calculate position if either\n\t\t\t// top or left is auto and position is either absolute or fixed\n\t\t\tif ( calculatePosition ) {\n\t\t\t\tcurPosition = curElem.position();\n\t\t\t\tcurTop = curPosition.top;\n\t\t\t\tcurLeft = curPosition.left;\n\n\t\t\t} else {\n\t\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n\t\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n\t\t\t}\n\n\t\t\tif ( jQuery.isFunction( options ) ) {\n\n\t\t\t\t// Use jQuery.extend here to allow modification of coordinates argument (gh-1848)\n\t\t\t\toptions = options.call( elem, i, jQuery.extend( {}, curOffset ) );\n\t\t\t}\n\n\t\t\tif ( options.top != null ) {\n\t\t\t\tprops.top = ( options.top - curOffset.top ) + curTop;\n\t\t\t}\n\t\t\tif ( options.left != null ) {\n\t\t\t\tprops.left = ( options.left - curOffset.left ) + curLeft;\n\t\t\t}\n\n\t\t\tif ( \"using\" in options ) {\n\t\t\t\toptions.using.call( elem, props );\n\n\t\t\t} else {\n\t\t\t\tcurElem.css( props );\n\t\t\t}\n\t\t}\n\t};\n\n\tjQuery.fn.extend( {\n\t\toffset: function( options ) {\n\n\t\t\t// Preserve chaining for setter\n\t\t\tif ( arguments.length ) {\n\t\t\t\treturn options === undefined ?\n\t\t\t\t\tthis :\n\t\t\t\t\tthis.each( function( i ) {\n\t\t\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t\t\t} );\n\t\t\t}\n\n\t\t\tvar doc, docElem, rect, win,\n\t\t\t\telem = this[ 0 ];\n\n\t\t\tif ( !elem ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Return zeros for disconnected and hidden (display: none) elements (gh-2310)\n\t\t\t// Support: IE <=11 only\n\t\t\t// Running getBoundingClientRect on a\n\t\t\t// disconnected node in IE throws an error\n\t\t\tif ( !elem.getClientRects().length ) {\n\t\t\t\treturn { top: 0, left: 0 };\n\t\t\t}\n\n\t\t\trect = elem.getBoundingClientRect();\n\n\t\t\tdoc = elem.ownerDocument;\n\t\t\tdocElem = doc.documentElement;\n\t\t\twin = doc.defaultView;\n\n\t\t\treturn {\n\t\t\t\ttop: rect.top + win.pageYOffset - docElem.clientTop,\n\t\t\t\tleft: rect.left + win.pageXOffset - docElem.clientLeft\n\t\t\t};\n\t\t},\n\n\t\tposition: function() {\n\t\t\tif ( !this[ 0 ] ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar offsetParent, offset,\n\t\t\t\telem = this[ 0 ],\n\t\t\t\tparentOffset = { top: 0, left: 0 };\n\n\t\t\t// Fixed elements are offset from window (parentOffset = {top:0, left: 0},\n\t\t\t// because it is its only offset parent\n\t\t\tif ( jQuery.css( elem, \"position\" ) === \"fixed\" ) {\n\n\t\t\t\t// Assume getBoundingClientRect is there when computed position is fixed\n\t\t\t\toffset = elem.getBoundingClientRect();\n\n\t\t\t} else {\n\n\t\t\t\t// Get *real* offsetParent\n\t\t\t\toffsetParent = this.offsetParent();\n\n\t\t\t\t// Get correct offsets\n\t\t\t\toffset = this.offset();\n\t\t\t\tif ( !nodeName( offsetParent[ 0 ], \"html\" ) ) {\n\t\t\t\t\tparentOffset = offsetParent.offset();\n\t\t\t\t}\n\n\t\t\t\t// Add offsetParent borders\n\t\t\t\tparentOffset = {\n\t\t\t\t\ttop: parentOffset.top + jQuery.css( offsetParent[ 0 ], \"borderTopWidth\", true ),\n\t\t\t\t\tleft: parentOffset.left + jQuery.css( offsetParent[ 0 ], \"borderLeftWidth\", true )\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Subtract parent offsets and element margins\n\t\t\treturn {\n\t\t\t\ttop: offset.top - parentOffset.top - jQuery.css( elem, \"marginTop\", true ),\n\t\t\t\tleft: offset.left - parentOffset.left - jQuery.css( elem, \"marginLeft\", true )\n\t\t\t};\n\t\t},\n\n\t\t// This method will return documentElement in the following cases:\n\t\t// 1) For the element inside the iframe without offsetParent, this method will return\n\t\t//    documentElement of the parent window\n\t\t// 2) For the hidden or detached element\n\t\t// 3) For body or html element, i.e. in case of the html node - it will return itself\n\t\t//\n\t\t// but those exceptions were never presented as a real life use-cases\n\t\t// and might be considered as more preferable results.\n\t\t//\n\t\t// This logic, however, is not guaranteed and can change at any point in the future\n\t\toffsetParent: function() {\n\t\t\treturn this.map( function() {\n\t\t\t\tvar offsetParent = this.offsetParent;\n\n\t\t\t\twhile ( offsetParent && jQuery.css( offsetParent, \"position\" ) === \"static\" ) {\n\t\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t\t}\n\n\t\t\t\treturn offsetParent || documentElement;\n\t\t\t} );\n\t\t}\n\t} );\n\n// Create scrollLeft and scrollTop methods\n\tjQuery.each( { scrollLeft: \"pageXOffset\", scrollTop: \"pageYOffset\" }, function( method, prop ) {\n\t\tvar top = \"pageYOffset\" === prop;\n\n\t\tjQuery.fn[ method ] = function( val ) {\n\t\t\treturn access( this, function( elem, method, val ) {\n\n\t\t\t\t// Coalesce documents and windows\n\t\t\t\tvar win;\n\t\t\t\tif ( jQuery.isWindow( elem ) ) {\n\t\t\t\t\twin = elem;\n\t\t\t\t} else if ( elem.nodeType === 9 ) {\n\t\t\t\t\twin = elem.defaultView;\n\t\t\t\t}\n\n\t\t\t\tif ( val === undefined ) {\n\t\t\t\t\treturn win ? win[ prop ] : elem[ method ];\n\t\t\t\t}\n\n\t\t\t\tif ( win ) {\n\t\t\t\t\twin.scrollTo(\n\t\t\t\t\t\t!top ? val : win.pageXOffset,\n\t\t\t\t\t\ttop ? val : win.pageYOffset\n\t\t\t\t\t);\n\n\t\t\t\t} else {\n\t\t\t\t\telem[ method ] = val;\n\t\t\t\t}\n\t\t\t}, method, val, arguments.length );\n\t\t};\n\t} );\n\n// Support: Safari <=7 - 9.1, Chrome <=37 - 49\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://bugs.chromium.org/p/chromium/issues/detail?id=589347\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\n\tjQuery.each( [ \"top\", \"left\" ], function( i, prop ) {\n\t\tjQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,\n\t\t\tfunction( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\t\t\t\t\tcomputed = curCSS( elem, prop );\n\n\t\t\t\t\t// If curCSS returns percentage, fallback to offset\n\t\t\t\t\treturn rnumnonpx.test( computed ) ?\n\t\t\t\t\tjQuery( elem ).position()[ prop ] + \"px\" :\n\t\t\t\t\t\tcomputed;\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t} );\n\n\n// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods\n\tjQuery.each( { Height: \"height\", Width: \"width\" }, function( name, type ) {\n\t\tjQuery.each( { padding: \"inner\" + name, content: type, \"\": \"outer\" + name },\n\t\t\tfunction( defaultExtra, funcName ) {\n\n\t\t\t\t// Margin is only for outerHeight, outerWidth\n\t\t\t\tjQuery.fn[ funcName ] = function( margin, value ) {\n\t\t\t\t\tvar chainable = arguments.length && ( defaultExtra || typeof margin !== \"boolean\" ),\n\t\t\t\t\t\textra = defaultExtra || ( margin === true || value === true ? \"margin\" : \"border\" );\n\n\t\t\t\t\treturn access( this, function( elem, type, value ) {\n\t\t\t\t\t\tvar doc;\n\n\t\t\t\t\t\tif ( jQuery.isWindow( elem ) ) {\n\n\t\t\t\t\t\t\t// $( window ).outerWidth/Height return w/h including scrollbars (gh-1729)\n\t\t\t\t\t\t\treturn funcName.indexOf( \"outer\" ) === 0 ?\n\t\t\t\t\t\t\t\telem[ \"inner\" + name ] :\n\t\t\t\t\t\t\t\telem.document.documentElement[ \"client\" + name ];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Get document width or height\n\t\t\t\t\t\tif ( elem.nodeType === 9 ) {\n\t\t\t\t\t\t\tdoc = elem.documentElement;\n\n\t\t\t\t\t\t\t// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],\n\t\t\t\t\t\t\t// whichever is greatest\n\t\t\t\t\t\t\treturn Math.max(\n\t\t\t\t\t\t\t\telem.body[ \"scroll\" + name ], doc[ \"scroll\" + name ],\n\t\t\t\t\t\t\t\telem.body[ \"offset\" + name ], doc[ \"offset\" + name ],\n\t\t\t\t\t\t\t\tdoc[ \"client\" + name ]\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn value === undefined ?\n\n\t\t\t\t\t\t\t// Get width or height on the element, requesting but not forcing parseFloat\n\t\t\t\t\t\t\tjQuery.css( elem, type, extra ) :\n\n\t\t\t\t\t\t\t// Set width or height on the element\n\t\t\t\t\t\t\tjQuery.style( elem, type, value, extra );\n\t\t\t\t\t}, type, chainable ? margin : undefined, chainable );\n\t\t\t\t};\n\t\t\t} );\n\t} );\n\n\n\tjQuery.fn.extend( {\n\n\t\tbind: function( types, data, fn ) {\n\t\t\treturn this.on( types, null, data, fn );\n\t\t},\n\t\tunbind: function( types, fn ) {\n\t\t\treturn this.off( types, null, fn );\n\t\t},\n\n\t\tdelegate: function( selector, types, data, fn ) {\n\t\t\treturn this.on( types, selector, data, fn );\n\t\t},\n\t\tundelegate: function( selector, types, fn ) {\n\n\t\t\t// ( namespace ) or ( selector, types [, fn] )\n\t\t\treturn arguments.length === 1 ?\n\t\t\t\tthis.off( selector, \"**\" ) :\n\t\t\t\tthis.off( types, selector || \"**\", fn );\n\t\t}\n\t} );\n\n\tjQuery.holdReady = 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\tjQuery.isArray = Array.isArray;\n\tjQuery.parseJSON = JSON.parse;\n\tjQuery.nodeName = nodeName;\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\n\tif ( typeof define === \"function\" && define.amd ) {\n\t\tdefine( \"jquery\", [], function() {\n\t\t\treturn jQuery;\n\t\t} );\n\t}\n\n\n\n\n\tvar\n\n\t\t// Map over jQuery in case of overwrite\n\t\t_jQuery = window.jQuery,\n\n\t\t// Map over the $ in case of overwrite\n\t\t_$ = window.$;\n\n\tjQuery.noConflict = 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// 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)\n\tif ( !noGlobal ) {\n\t\twindow.jQuery = window.$ = jQuery;\n\t}\n\n\n\n\n\treturn jQuery;\n} );\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/jquery/jquery.slim.js",
    "content": "/*!\n * jQuery JavaScript Library v3.2.1 -ajax,-ajax/jsonp,-ajax/load,-ajax/parseXML,-ajax/script,-ajax/var/location,-ajax/var/nonce,-ajax/var/rquery,-ajax/xhr,-manipulation/_evalUrl,-event/ajax,-effects,-effects/Tween,-effects/animatedSelector\n * https://jquery.com/\n *\n * Includes Sizzle.js\n * https://sizzlejs.com/\n *\n * Copyright JS Foundation and other contributors\n * Released under the MIT license\n * https://jquery.org/license\n *\n * Date: 2017-03-20T19:00Z\n */\n( function( global, factory ) {\n\n\t\"use strict\";\n\n\tif ( typeof module === \"object\" && typeof module.exports === \"object\" ) {\n\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// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1\n// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode\n// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common\n// enough that all such attempts are guarded in a try block.\n\"use strict\";\n\nvar arr = [];\n\nvar document = window.document;\n\nvar getProto = Object.getPrototypeOf;\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 fnToString = hasOwn.toString;\n\nvar ObjectFunctionString = fnToString.call( Object );\n\nvar support = {};\n\n\n\n\tfunction DOMEval( code, doc ) {\n\t\tdoc = doc || document;\n\n\t\tvar script = doc.createElement( \"script\" );\n\n\t\tscript.text = code;\n\t\tdoc.head.appendChild( script ).parentNode.removeChild( script );\n\t}\n/* global Symbol */\n// Defining this global in .eslintrc.json would create a danger of using the global\n// unguarded in another place, it seems safer to define global only for this module\n\n\n\nvar\n\tversion = \"3.2.1 -ajax,-ajax/jsonp,-ajax/load,-ajax/parseXML,-ajax/script,-ajax/var/location,-ajax/var/nonce,-ajax/var/rquery,-ajax/xhr,-manipulation/_evalUrl,-event/ajax,-effects,-effects/Tween,-effects/animatedSelector\",\n\n\t// Define a local copy of jQuery\n\tjQuery = function( selector, context ) {\n\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.0 only\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 = /-([a-z])/g,\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\n\t// The current version of jQuery being used\n\tjquery: version,\n\n\tconstructor: jQuery,\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\n\t\t// Return all the elements in a clean array\n\t\tif ( num == null ) {\n\t\t\treturn slice.call( this );\n\t\t}\n\n\t\t// Return just the one element from the set\n\t\treturn num < 0 ? this[ num + this.length ] : 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\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\teach: function( callback ) {\n\t\treturn jQuery.each( this, callback );\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();\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\n\t\t// Only deal with non-null/undefined values\n\t\tif ( ( options = arguments[ i ] ) != null ) {\n\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 ) ||\n\t\t\t\t\t( copyIsArray = Array.isArray( copy ) ) ) ) {\n\n\t\t\t\t\tif ( copyIsArray ) {\n\t\t\t\t\t\tcopyIsArray = false;\n\t\t\t\t\t\tclone = src && Array.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\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\tisWindow: function( obj ) {\n\t\treturn obj != null && obj === obj.window;\n\t},\n\n\tisNumeric: function( obj ) {\n\n\t\t// As of jQuery 3.0, isNumeric is limited to\n\t\t// strings and numbers (primitives or objects)\n\t\t// that can be coerced to finite numbers (gh-2662)\n\t\tvar type = jQuery.type( obj );\n\t\treturn ( type === \"number\" || type === \"string\" ) &&\n\n\t\t\t// parseFloat NaNs numeric-cast false positives (\"\")\n\t\t\t// ...but misinterprets leading-number strings, particularly hex literals (\"0x...\")\n\t\t\t// subtraction forces infinities to NaN\n\t\t\t!isNaN( obj - parseFloat( obj ) );\n\t},\n\n\tisPlainObject: function( obj ) {\n\t\tvar proto, Ctor;\n\n\t\t// Detect obvious negatives\n\t\t// Use toString instead of jQuery.type to catch host objects\n\t\tif ( !obj || toString.call( obj ) !== \"[object Object]\" ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tproto = getProto( obj );\n\n\t\t// Objects with no prototype (e.g., `Object.create( null )`) are plain\n\t\tif ( !proto ) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Objects with prototype are plain iff they were constructed by a global Object function\n\t\tCtor = hasOwn.call( proto, \"constructor\" ) && proto.constructor;\n\t\treturn typeof Ctor === \"function\" && fnToString.call( Ctor ) === ObjectFunctionString;\n\t},\n\n\tisEmptyObject: function( obj ) {\n\n\t\t/* eslint-disable no-unused-vars */\n\t\t// See https://github.com/eslint/eslint/issues/6125\n\t\tvar name;\n\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\n\t\t// Support: Android <=2.3 only (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\tDOMEval( code );\n\t},\n\n\t// Convert dashed to camelCase; used by the css and data modules\n\t// Support: IE <=9 - 11, Edge 12 - 13\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\teach: function( obj, callback ) {\n\t\tvar length, i = 0;\n\n\t\tif ( isArrayLike( obj ) ) {\n\t\t\tlength = obj.length;\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tfor ( i in obj ) {\n\t\t\t\tif ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {\n\t\t\t\t\tbreak;\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.0 only\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\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t// push.apply(_, arraylike) throws on ancient WebKit\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 length, value,\n\t\t\ti = 0,\n\t\t\tret = [];\n\n\t\t// Go through the array, translating each of the items to their new values\n\t\tif ( isArrayLike( elems ) ) {\n\t\t\tlength = elems.length;\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\nif ( typeof Symbol === \"function\" ) {\n\tjQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ];\n}\n\n// Populate the class2type map\njQuery.each( \"Boolean Number String Function Array Date RegExp Object Error Symbol\".split( \" \" ),\nfunction( i, name ) {\n\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n} );\n\nfunction isArrayLike( obj ) {\n\n\t// Support: real iOS 8.2 only (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 = !!obj && \"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\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.3.3\n * https://sizzlejs.com/\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license\n * http://jquery.org/license\n *\n * Date: 2016-08-08\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// 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// https://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// http://www.w3.org/TR/css3-selectors/#whitespace\n\twhitespace = \"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",\n\n\t// http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier\n\tidentifier = \"(?:\\\\\\\\.|[\\\\w-]|[^\\0-\\\\xa0])+\",\n\n\t// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors\n\tattributes = \"\\\\[\" + whitespace + \"*(\" + identifier + \")(?:\" + 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 = \":(\" + identifier + \")(?:\\\\((\" +\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( \"^#(\" + identifier + \")\" ),\n\t\t\"CLASS\": new RegExp( \"^\\\\.(\" + identifier + \")\" ),\n\t\t\"TAG\": new RegExp( \"^(\" + identifier + \"|[*])\" ),\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\n\t// CSS escapes\n\t// 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// CSS string/identifier serialization\n\t// https://drafts.csswg.org/cssom/#common-serializing-idioms\n\trcssescape = /([\\0-\\x1f\\x7f]|^-?\\d)|^-$|[^\\0-\\x1f\\x7f-\\uFFFF\\w-]/g,\n\tfcssescape = function( ch, asCodePoint ) {\n\t\tif ( asCodePoint ) {\n\n\t\t\t// U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER\n\t\t\tif ( ch === \"\\0\" ) {\n\t\t\t\treturn \"\\uFFFD\";\n\t\t\t}\n\n\t\t\t// Control characters and (dependent upon position) numbers get escaped as code points\n\t\t\treturn ch.slice( 0, -1 ) + \"\\\\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + \" \";\n\t\t}\n\n\t\t// Other potentially-special ASCII characters get backslash-escaped\n\t\treturn \"\\\\\" + ch;\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\tdisabledAncestor = addCombinator(\n\t\tfunction( elem ) {\n\t\t\treturn elem.disabled === true && (\"form\" in elem || \"label\" in elem);\n\t\t},\n\t\t{ dir: \"parentNode\", next: \"legend\" }\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 m, i, elem, nid, match, groups, newSelector,\n\t\tnewContext = context && context.ownerDocument,\n\n\t\t// nodeType defaults to 9, since context defaults to document\n\t\tnodeType = context ? context.nodeType : 9;\n\n\tresults = results || [];\n\n\t// Return early from calls with invalid selector or context\n\tif ( typeof selector !== \"string\" || !selector ||\n\t\tnodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {\n\n\t\treturn results;\n\t}\n\n\t// Try to shortcut find operations (as opposed to filters) in HTML documents\n\tif ( !seed ) {\n\n\t\tif ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {\n\t\t\tsetDocument( context );\n\t\t}\n\t\tcontext = context || document;\n\n\t\tif ( documentIsHTML ) {\n\n\t\t\t// If the selector is sufficiently simple, try using a \"get*By*\" DOM method\n\t\t\t// (excepting DocumentFragment context, where the methods don't exist)\n\t\t\tif ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {\n\n\t\t\t\t// ID selector\n\t\t\t\tif ( (m = match[1]) ) {\n\n\t\t\t\t\t// Document context\n\t\t\t\t\tif ( nodeType === 9 ) {\n\t\t\t\t\t\tif ( (elem = context.getElementById( m )) ) {\n\n\t\t\t\t\t\t\t// Support: IE, Opera, Webkit\n\t\t\t\t\t\t\t// TODO: identify versions\n\t\t\t\t\t\t\t// getElementById can match elements by name instead of ID\n\t\t\t\t\t\t\tif ( elem.id === m ) {\n\t\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t// Element context\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t// Support: IE, Opera, Webkit\n\t\t\t\t\t\t// TODO: identify versions\n\t\t\t\t\t\t// getElementById can match elements by name instead of ID\n\t\t\t\t\t\tif ( newContext && (elem = newContext.getElementById( m )) &&\n\t\t\t\t\t\t\tcontains( context, elem ) &&\n\t\t\t\t\t\t\telem.id === m ) {\n\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}\n\n\t\t\t\t// Type selector\n\t\t\t\t} else if ( match[2] ) {\n\t\t\t\t\tpush.apply( results, context.getElementsByTagName( selector ) );\n\t\t\t\t\treturn results;\n\n\t\t\t\t// Class selector\n\t\t\t\t} else if ( (m = match[3]) && support.getElementsByClassName &&\n\t\t\t\t\tcontext.getElementsByClassName ) {\n\n\t\t\t\t\tpush.apply( results, context.getElementsByClassName( m ) );\n\t\t\t\t\treturn results;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Take advantage of querySelectorAll\n\t\t\tif ( support.qsa &&\n\t\t\t\t!compilerCache[ selector + \" \" ] &&\n\t\t\t\t(!rbuggyQSA || !rbuggyQSA.test( selector )) ) {\n\n\t\t\t\tif ( nodeType !== 1 ) {\n\t\t\t\t\tnewContext = context;\n\t\t\t\t\tnewSelector = selector;\n\n\t\t\t\t// qSA looks outside Element context, which is not what we want\n\t\t\t\t// Thanks to Andrew Dupont for this workaround technique\n\t\t\t\t// Support: IE <=8\n\t\t\t\t// Exclude object elements\n\t\t\t\t} else if ( context.nodeName.toLowerCase() !== \"object\" ) {\n\n\t\t\t\t\t// Capture the context ID, setting it first if necessary\n\t\t\t\t\tif ( (nid = context.getAttribute( \"id\" )) ) {\n\t\t\t\t\t\tnid = nid.replace( rcssescape, fcssescape );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcontext.setAttribute( \"id\", (nid = expando) );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prefix every selector in the list\n\t\t\t\t\tgroups = tokenize( selector );\n\t\t\t\t\ti = groups.length;\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tgroups[i] = \"#\" + nid + \" \" + toSelector( groups[i] );\n\t\t\t\t\t}\n\t\t\t\t\tnewSelector = groups.join( \",\" );\n\n\t\t\t\t\t// Expand context for sibling selectors\n\t\t\t\t\tnewContext = rsibling.test( selector ) && testContext( context.parentNode ) ||\n\t\t\t\t\t\tcontext;\n\t\t\t\t}\n\n\t\t\t\tif ( newSelector ) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tpush.apply( results,\n\t\t\t\t\t\t\tnewContext.querySelectorAll( newSelector )\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t} catch ( qsaError ) {\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tif ( nid === expando ) {\n\t\t\t\t\t\t\tcontext.removeAttribute( \"id\" );\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\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 element and returns a boolean result\n */\nfunction assert( fn ) {\n\tvar el = document.createElement(\"fieldset\");\n\n\ttry {\n\t\treturn !!fn( el );\n\t} catch (e) {\n\t\treturn false;\n\t} finally {\n\t\t// Remove from its parent by default\n\t\tif ( el.parentNode ) {\n\t\t\tel.parentNode.removeChild( el );\n\t\t}\n\t\t// release memory in IE\n\t\tel = 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 = arr.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\ta.sourceIndex - b.sourceIndex;\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 :enabled/:disabled\n * @param {Boolean} disabled true for :disabled; false for :enabled\n */\nfunction createDisabledPseudo( disabled ) {\n\n\t// Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable\n\treturn function( elem ) {\n\n\t\t// Only certain elements can match :enabled or :disabled\n\t\t// https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled\n\t\t// https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled\n\t\tif ( \"form\" in elem ) {\n\n\t\t\t// Check for inherited disabledness on relevant non-disabled elements:\n\t\t\t// * listed form-associated elements in a disabled fieldset\n\t\t\t//   https://html.spec.whatwg.org/multipage/forms.html#category-listed\n\t\t\t//   https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled\n\t\t\t// * option elements in a disabled optgroup\n\t\t\t//   https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled\n\t\t\t// All such elements have a \"form\" property.\n\t\t\tif ( elem.parentNode && elem.disabled === false ) {\n\n\t\t\t\t// Option elements defer to a parent optgroup if present\n\t\t\t\tif ( \"label\" in elem ) {\n\t\t\t\t\tif ( \"label\" in elem.parentNode ) {\n\t\t\t\t\t\treturn elem.parentNode.disabled === disabled;\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn elem.disabled === disabled;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Support: IE 6 - 11\n\t\t\t\t// Use the isDisabled shortcut property to check for disabled fieldset ancestors\n\t\t\t\treturn elem.isDisabled === disabled ||\n\n\t\t\t\t\t// Where there is no isDisabled, check manually\n\t\t\t\t\t/* jshint -W018 */\n\t\t\t\t\telem.isDisabled !== !disabled &&\n\t\t\t\t\t\tdisabledAncestor( elem ) === disabled;\n\t\t\t}\n\n\t\t\treturn elem.disabled === disabled;\n\n\t\t// Try to winnow out elements that can't be disabled before trusting the disabled property.\n\t\t// Some victims get caught in our net (label, legend, menu, track), but it shouldn't\n\t\t// even exist on them, let alone have a boolean value.\n\t\t} else if ( \"label\" in elem ) {\n\t\t\treturn elem.disabled === disabled;\n\t\t}\n\n\t\t// Remaining elements are neither :enabled nor :disabled\n\t\treturn false;\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, subWindow,\n\t\tdoc = node ? node.ownerDocument || node : preferredDoc;\n\n\t// Return early if doc is invalid or already selected\n\tif ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {\n\t\treturn document;\n\t}\n\n\t// Update global variables\n\tdocument = doc;\n\tdocElem = document.documentElement;\n\tdocumentIsHTML = !isXML( document );\n\n\t// Support: IE 9-11, Edge\n\t// Accessing iframe documents after unload throws \"permission denied\" errors (jQuery #13936)\n\tif ( preferredDoc !== document &&\n\t\t(subWindow = document.defaultView) && subWindow.top !== subWindow ) {\n\n\t\t// Support: IE 11, Edge\n\t\tif ( subWindow.addEventListener ) {\n\t\t\tsubWindow.addEventListener( \"unload\", unloadHandler, false );\n\n\t\t// Support: IE 9 - 10 only\n\t\t} else if ( subWindow.attachEvent ) {\n\t\t\tsubWindow.attachEvent( \"onunload\", unloadHandler );\n\t\t}\n\t}\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( el ) {\n\t\tel.className = \"i\";\n\t\treturn !el.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( el ) {\n\t\tel.appendChild( document.createComment(\"\") );\n\t\treturn !el.getElementsByTagName(\"*\").length;\n\t});\n\n\t// Support: IE<9\n\tsupport.getElementsByClassName = rnative.test( document.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 programmatically-set names,\n\t// so use a roundabout getElementsByName test\n\tsupport.getById = assert(function( el ) {\n\t\tdocElem.appendChild( el ).id = expando;\n\t\treturn !document.getElementsByName || !document.getElementsByName( expando ).length;\n\t});\n\n\t// ID filter and find\n\tif ( support.getById ) {\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\tExpr.find[\"ID\"] = function( id, context ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && documentIsHTML ) {\n\t\t\t\tvar elem = context.getElementById( id );\n\t\t\t\treturn elem ? [ elem ] : [];\n\t\t\t}\n\t\t};\n\t} else {\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\" &&\n\t\t\t\t\telem.getAttributeNode(\"id\");\n\t\t\t\treturn node && node.value === attrId;\n\t\t\t};\n\t\t};\n\n\t\t// Support: IE 6 - 7 only\n\t\t// getElementById is not reliable as a find shortcut\n\t\tExpr.find[\"ID\"] = function( id, context ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && documentIsHTML ) {\n\t\t\t\tvar node, i, elems,\n\t\t\t\t\telem = context.getElementById( id );\n\n\t\t\t\tif ( elem ) {\n\n\t\t\t\t\t// Verify the id attribute\n\t\t\t\t\tnode = elem.getAttributeNode(\"id\");\n\t\t\t\t\tif ( node && node.value === id ) {\n\t\t\t\t\t\treturn [ elem ];\n\t\t\t\t\t}\n\n\t\t\t\t\t// Fall back on getElementsByName\n\t\t\t\t\telems = context.getElementsByName( id );\n\t\t\t\t\ti = 0;\n\t\t\t\t\twhile ( (elem = elems[i++]) ) {\n\t\t\t\t\t\tnode = elem.getAttributeNode(\"id\");\n\t\t\t\t\t\tif ( node && node.value === id ) {\n\t\t\t\t\t\t\treturn [ elem ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn [];\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 ( typeof context.getElementsByClassName !== \"undefined\" && 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 https://bugs.jquery.com/ticket/13378\n\trbuggyQSA = [];\n\n\tif ( (support.qsa = rnative.test( document.querySelectorAll )) ) {\n\t\t// Build QSA regex\n\t\t// Regex strategy adopted from Diego Perini\n\t\tassert(function( el ) {\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// https://bugs.jquery.com/ticket/12359\n\t\t\tdocElem.appendChild( el ).innerHTML = \"<a id='\" + expando + \"'></a>\" +\n\t\t\t\t\"<select id='\" + expando + \"-\\r\\\\' 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// https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section\n\t\t\tif ( el.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 ( !el.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.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+\n\t\t\tif ( !el.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 ( !el.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 sibling-combinator selector` fails\n\t\t\tif ( !el.querySelectorAll( \"a#\" + expando + \"+*\" ).length ) {\n\t\t\t\trbuggyQSA.push(\".#.+[+~]\");\n\t\t\t}\n\t\t});\n\n\t\tassert(function( el ) {\n\t\t\tel.innerHTML = \"<a href='' disabled='disabled'></a>\" +\n\t\t\t\t\"<select disabled='disabled'><option/></select>\";\n\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 = document.createElement(\"input\");\n\t\t\tinput.setAttribute( \"type\", \"hidden\" );\n\t\t\tel.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 ( el.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 ( el.querySelectorAll(\":enabled\").length !== 2 ) {\n\t\t\t\trbuggyQSA.push( \":enabled\", \":disabled\" );\n\t\t\t}\n\n\t\t\t// Support: IE9-11+\n\t\t\t// IE's :disabled selector does not pick up the children of disabled fieldsets\n\t\t\tdocElem.appendChild( el ).disabled = true;\n\t\t\tif ( el.querySelectorAll(\":disabled\").length !== 2 ) {\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\tel.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( el ) {\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( el, \"*\" );\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( el, \"[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 self-exclusive\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 === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t\tif ( b === document || 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 === document ? -1 :\n\t\t\t\tb === document ? 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 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\tif ( support.matchesSelector && documentIsHTML &&\n\t\t!compilerCache[ expr + \" \" ] &&\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.escape = function( sel ) {\n\treturn (sel + \"\").replace( rcssescape, fcssescape );\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, uniqueCache, outerCache, node, 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\t\t\t\t\t\tdiff = false;\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 ?\n\t\t\t\t\t\t\t\t\t\tnode.nodeName.toLowerCase() === name :\n\t\t\t\t\t\t\t\t\t\tnode.nodeType === 1 ) {\n\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\n\t\t\t\t\t\t\t// Seek `elem` from a previously-cached index\n\n\t\t\t\t\t\t\t// ...in a gzip-friendly way\n\t\t\t\t\t\t\tnode = parent;\n\t\t\t\t\t\t\touterCache = node[ expando ] || (node[ expando ] = {});\n\n\t\t\t\t\t\t\t// Support: IE <9 only\n\t\t\t\t\t\t\t// Defend against cloned attroperties (jQuery gh-1709)\n\t\t\t\t\t\t\tuniqueCache = outerCache[ node.uniqueID ] ||\n\t\t\t\t\t\t\t\t(outerCache[ node.uniqueID ] = {});\n\n\t\t\t\t\t\t\tcache = uniqueCache[ type ] || [];\n\t\t\t\t\t\t\tnodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];\n\t\t\t\t\t\t\tdiff = nodeIndex && 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\tuniqueCache[ 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} else {\n\t\t\t\t\t\t\t// Use previously-cached element index if available\n\t\t\t\t\t\t\tif ( useCache ) {\n\t\t\t\t\t\t\t\t// ...in a gzip-friendly way\n\t\t\t\t\t\t\t\tnode = elem;\n\t\t\t\t\t\t\t\touterCache = node[ expando ] || (node[ expando ] = {});\n\n\t\t\t\t\t\t\t\t// Support: IE <9 only\n\t\t\t\t\t\t\t\t// Defend against cloned attroperties (jQuery gh-1709)\n\t\t\t\t\t\t\t\tuniqueCache = outerCache[ node.uniqueID ] ||\n\t\t\t\t\t\t\t\t\t(outerCache[ node.uniqueID ] = {});\n\n\t\t\t\t\t\t\t\tcache = uniqueCache[ type ] || [];\n\t\t\t\t\t\t\t\tnodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];\n\t\t\t\t\t\t\t\tdiff = nodeIndex;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// xml :nth-child(...)\n\t\t\t\t\t\t\t// or :nth-last-child(...) or :nth(-last)?-of-type(...)\n\t\t\t\t\t\t\tif ( diff === false ) {\n\t\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\t\twhile ( (node = ++nodeIndex && node && node[ dir ] ||\n\t\t\t\t\t\t\t\t\t(diff = nodeIndex = 0) || start.pop()) ) {\n\n\t\t\t\t\t\t\t\t\tif ( ( ofType ?\n\t\t\t\t\t\t\t\t\t\tnode.nodeName.toLowerCase() === name :\n\t\t\t\t\t\t\t\t\t\tnode.nodeType === 1 ) &&\n\t\t\t\t\t\t\t\t\t\t++diff ) {\n\n\t\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\t\tif ( useCache ) {\n\t\t\t\t\t\t\t\t\t\t\touterCache = node[ expando ] || (node[ expando ] = {});\n\n\t\t\t\t\t\t\t\t\t\t\t// Support: IE <9 only\n\t\t\t\t\t\t\t\t\t\t\t// Defend against cloned attroperties (jQuery gh-1709)\n\t\t\t\t\t\t\t\t\t\t\tuniqueCache = outerCache[ node.uniqueID ] ||\n\t\t\t\t\t\t\t\t\t\t\t\t(outerCache[ node.uniqueID ] = {});\n\n\t\t\t\t\t\t\t\t\t\t\tuniqueCache[ type ] = [ dirruns, diff ];\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tif ( node === elem ) {\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t}\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\": createDisabledPseudo( false ),\n\t\t\"disabled\": createDisabledPseudo( true ),\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\tskip = combinator.next,\n\t\tkey = skip || dir,\n\t\tcheckNonElements = base && key === \"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\treturn false;\n\t\t} :\n\n\t\t// Check against all ancestor/preceding elements\n\t\tfunction( elem, context, xml ) {\n\t\t\tvar oldCache, uniqueCache, 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 combinator 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\n\t\t\t\t\t\t// Support: IE <9 only\n\t\t\t\t\t\t// Defend against cloned attroperties (jQuery gh-1709)\n\t\t\t\t\t\tuniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {});\n\n\t\t\t\t\t\tif ( skip && skip === elem.nodeName.toLowerCase() ) {\n\t\t\t\t\t\t\telem = elem[ dir ] || elem;\n\t\t\t\t\t\t} else if ( (oldCache = uniqueCache[ key ]) &&\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\tuniqueCache[ key ] = 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\treturn false;\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 || outermost;\n\t\t\t}\n\n\t\t\t// Add elements passing elementMatchers directly to results\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\tif ( !context && elem.ownerDocument !== document ) {\n\t\t\t\t\t\tsetDocument( elem );\n\t\t\t\t\t\txml = !documentIsHTML;\n\t\t\t\t\t}\n\t\t\t\t\twhile ( (matcher = elementMatchers[j++]) ) {\n\t\t\t\t\t\tif ( matcher( elem, context || document, 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// `i` is now the count of elements visited above, and adding it to `matchedCount`\n\t\t\t// makes the latter nonnegative.\n\t\t\tmatchedCount += i;\n\n\t\t\t// Apply set filters to unmatched elements\n\t\t\t// NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`\n\t\t\t// equals `i`), unless we didn't visit _any_ elements in the above loop because we have\n\t\t\t// no element matchers and no seed.\n\t\t\t// Incrementing an initially-string \"0\" `i` allows `i` to remain a string only in that\n\t\t\t// case, which will result in a \"00\" `matchedCount` that differs from `i` but is also\n\t\t\t// numerically zero.\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 only one selector in the list and no seed\n\t// (the latter of which guarantees us context)\n\tif ( match.length === 1 ) {\n\n\t\t// Reduce context if the leading compound 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\tcontext.nodeType === 9 && documentIsHTML && Expr.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\t!context || rsibling.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( el ) {\n\t// Should return 1, but returns 4 (following)\n\treturn el.compareDocumentPosition( document.createElement(\"fieldset\") ) & 1;\n});\n\n// Support: IE<8\n// Prevent attribute/property \"interpolation\"\n// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx\nif ( !assert(function( el ) {\n\tel.innerHTML = \"<a href='#'></a>\";\n\treturn el.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( el ) {\n\tel.innerHTML = \"<input/>\";\n\tel.firstChild.setAttribute( \"value\", \"\" );\n\treturn el.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( el ) {\n\treturn el.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;\n\n// Deprecated\njQuery.expr[ \":\" ] = jQuery.expr.pseudos;\njQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\njQuery.escapeSelector = Sizzle.escape;\n\n\n\n\nvar dir = function( elem, dir, until ) {\n\tvar matched = [],\n\t\ttruncate = until !== undefined;\n\n\twhile ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) {\n\t\tif ( elem.nodeType === 1 ) {\n\t\t\tif ( truncate && jQuery( elem ).is( until ) ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tmatched.push( elem );\n\t\t}\n\t}\n\treturn matched;\n};\n\n\nvar siblings = function( n, elem ) {\n\tvar matched = [];\n\n\tfor ( ; n; n = n.nextSibling ) {\n\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\tmatched.push( n );\n\t\t}\n\t}\n\n\treturn matched;\n};\n\n\nvar rneedsContext = jQuery.expr.match.needsContext;\n\n\n\nfunction nodeName( elem, name ) {\n\n  return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();\n\n};\nvar rsingleTag = ( /^<([a-z][^\\/\\0>:\\x20\\t\\r\\n\\f]*)[\\x20\\t\\r\\n\\f]*\\/?>(?:<\\/\\1>|)$/i );\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\treturn !!qualifier.call( elem, i, elem ) !== not;\n\t\t} );\n\t}\n\n\t// Single element\n\tif ( qualifier.nodeType ) {\n\t\treturn jQuery.grep( elements, function( elem ) {\n\t\t\treturn ( elem === qualifier ) !== not;\n\t\t} );\n\t}\n\n\t// Arraylike of elements (jQuery, arguments, Array)\n\tif ( typeof qualifier !== \"string\" ) {\n\t\treturn jQuery.grep( elements, function( elem ) {\n\t\t\treturn ( indexOf.call( qualifier, elem ) > -1 ) !== not;\n\t\t} );\n\t}\n\n\t// Simple selector that can be filtered directly, removing non-Elements\n\tif ( risSimple.test( qualifier ) ) {\n\t\treturn jQuery.filter( qualifier, elements, not );\n\t}\n\n\t// Complex selector, compare the two sets, removing non-Elements\n\tqualifier = jQuery.filter( qualifier, elements );\n\treturn jQuery.grep( elements, function( elem ) {\n\t\treturn ( indexOf.call( qualifier, elem ) > -1 ) !== not && elem.nodeType === 1;\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\tif ( elems.length === 1 && elem.nodeType === 1 ) {\n\t\treturn jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [];\n\t}\n\n\treturn jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {\n\t\treturn elem.nodeType === 1;\n\t} ) );\n};\n\njQuery.fn.extend( {\n\tfind: function( selector ) {\n\t\tvar i, ret,\n\t\t\tlen = this.length,\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\tret = this.pushStack( [] );\n\n\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\tjQuery.find( selector, self[ i ], ret );\n\t\t}\n\n\t\treturn len > 1 ? jQuery.uniqueSort( ret ) : 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\t// Shortcut simple #id case for speed\n\trquickExpr = /^(?:\\s*(<[\\w\\W]+>)[^>]*|#([\\w-]+))$/,\n\n\tinit = jQuery.fn.init = function( selector, context, root ) {\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// Method init() accepts an alternate rootjQuery\n\t\t// so migrate can support jQuery.sub (gh-2101)\n\t\troot = root || rootjQuery;\n\n\t\t// Handle HTML strings\n\t\tif ( typeof selector === \"string\" ) {\n\t\t\tif ( selector[ 0 ] === \"<\" &&\n\t\t\t\tselector[ selector.length - 1 ] === \">\" &&\n\t\t\t\tselector.length >= 3 ) {\n\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\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\tif ( elem ) {\n\n\t\t\t\t\t\t// Inject the element directly into the jQuery object\n\t\t\t\t\t\tthis[ 0 ] = elem;\n\t\t\t\t\t\tthis.length = 1;\n\t\t\t\t\t}\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 || root ).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[ 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 root.ready !== undefined ?\n\t\t\t\troot.ready( selector ) :\n\n\t\t\t\t// Execute immediately if ready is not present\n\t\t\t\tselector( jQuery );\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\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\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\ttargets = typeof selectors !== \"string\" && jQuery( selectors );\n\n\t\t// Positional selectors never match, since there's no _selection_ context\n\t\tif ( !rneedsContext.test( selectors ) ) {\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tfor ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) {\n\n\t\t\t\t\t// Always skip document fragments\n\t\t\t\t\tif ( cur.nodeType < 11 && ( targets ?\n\t\t\t\t\t\ttargets.index( cur ) > -1 :\n\n\t\t\t\t\t\t// Don't pass non-elements to Sizzle\n\t\t\t\t\t\tcur.nodeType === 1 &&\n\t\t\t\t\t\t\tjQuery.find.matchesSelector( cur, selectors ) ) ) {\n\n\t\t\t\t\t\tmatched.push( cur );\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 this.pushStack( matched.length > 1 ? jQuery.uniqueSort( 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.uniqueSort(\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 dir( elem, \"parentNode\" );\n\t},\n\tparentsUntil: function( elem, i, until ) {\n\t\treturn 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 dir( elem, \"nextSibling\" );\n\t},\n\tprevAll: function( elem ) {\n\t\treturn dir( elem, \"previousSibling\" );\n\t},\n\tnextUntil: function( elem, i, until ) {\n\t\treturn dir( elem, \"nextSibling\", until );\n\t},\n\tprevUntil: function( elem, i, until ) {\n\t\treturn dir( elem, \"previousSibling\", until );\n\t},\n\tsiblings: function( elem ) {\n\t\treturn siblings( ( elem.parentNode || {} ).firstChild, elem );\n\t},\n\tchildren: function( elem ) {\n\t\treturn siblings( elem.firstChild );\n\t},\n\tcontents: function( elem ) {\n        if ( nodeName( elem, \"iframe\" ) ) {\n            return elem.contentDocument;\n        }\n\n        // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only\n        // Treat the template element as a regular one in browsers that\n        // don't support it.\n        if ( nodeName( elem, \"template\" ) ) {\n            elem = elem.content || elem;\n        }\n\n        return 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\n\t\t\t// Remove duplicates\n\t\t\tif ( !guaranteedUnique[ name ] ) {\n\t\t\t\tjQuery.uniqueSort( 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 rnothtmlwhite = ( /[^\\x20\\t\\r\\n\\f]+/g );\n\n\n\n// Convert String-formatted options into Object-formatted ones\nfunction createOptions( options ) {\n\tvar object = {};\n\tjQuery.each( options.match( rnothtmlwhite ) || [], 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\tcreateOptions( options ) :\n\t\tjQuery.extend( {}, options );\n\n\tvar // Flag to know if list is currently firing\n\t\tfiring,\n\n\t\t// Last fire value for non-forgettable lists\n\t\tmemory,\n\n\t\t// Flag to know if list was already fired\n\t\tfired,\n\n\t\t// Flag to prevent firing\n\t\tlocked,\n\n\t\t// Actual callback list\n\t\tlist = [],\n\n\t\t// Queue of execution data for repeatable lists\n\t\tqueue = [],\n\n\t\t// Index of currently firing callback (modified by add/remove as needed)\n\t\tfiringIndex = -1,\n\n\t\t// Fire callbacks\n\t\tfire = function() {\n\n\t\t\t// Enforce single-firing\n\t\t\tlocked = locked || options.once;\n\n\t\t\t// Execute callbacks for all pending executions,\n\t\t\t// respecting firingIndex overrides and runtime changes\n\t\t\tfired = firing = true;\n\t\t\tfor ( ; queue.length; firingIndex = -1 ) {\n\t\t\t\tmemory = queue.shift();\n\t\t\t\twhile ( ++firingIndex < list.length ) {\n\n\t\t\t\t\t// Run callback and check for early termination\n\t\t\t\t\tif ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false &&\n\t\t\t\t\t\toptions.stopOnFalse ) {\n\n\t\t\t\t\t\t// Jump to end and forget the data so .add doesn't re-fire\n\t\t\t\t\t\tfiringIndex = list.length;\n\t\t\t\t\t\tmemory = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Forget the data if we're done with it\n\t\t\tif ( !options.memory ) {\n\t\t\t\tmemory = false;\n\t\t\t}\n\n\t\t\tfiring = false;\n\n\t\t\t// Clean up if we're done firing for good\n\t\t\tif ( locked ) {\n\n\t\t\t\t// Keep an empty list if we have data for future add calls\n\t\t\t\tif ( memory ) {\n\t\t\t\t\tlist = [];\n\n\t\t\t\t// Otherwise, this object is spent\n\t\t\t\t} else {\n\t\t\t\t\tlist = \"\";\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t// Actual Callbacks object\n\t\tself = {\n\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\n\t\t\t\t\t// If we have memory from a past run, we should fire after adding\n\t\t\t\t\tif ( memory && !firing ) {\n\t\t\t\t\t\tfiringIndex = list.length - 1;\n\t\t\t\t\t\tqueue.push( memory );\n\t\t\t\t\t}\n\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\tif ( jQuery.isFunction( arg ) ) {\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 && jQuery.type( arg ) !== \"string\" ) {\n\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\n\t\t\t\t\tif ( memory && !firing ) {\n\t\t\t\t\t\tfire();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\t// Remove a callback from the list\n\t\t\tremove: function() {\n\t\t\t\tjQuery.each( arguments, function( _, arg ) {\n\t\t\t\t\tvar index;\n\t\t\t\t\twhile ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {\n\t\t\t\t\t\tlist.splice( index, 1 );\n\n\t\t\t\t\t\t// Handle firing indexes\n\t\t\t\t\t\tif ( index <= firingIndex ) {\n\t\t\t\t\t\t\tfiringIndex--;\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\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 ?\n\t\t\t\t\tjQuery.inArray( fn, list ) > -1 :\n\t\t\t\t\tlist.length > 0;\n\t\t\t},\n\n\t\t\t// Remove all callbacks from the list\n\t\t\tempty: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tlist = [];\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\t// Disable .fire and .add\n\t\t\t// Abort any current/pending executions\n\t\t\t// Clear all callbacks and values\n\t\t\tdisable: function() {\n\t\t\t\tlocked = queue = [];\n\t\t\t\tlist = memory = \"\";\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\tdisabled: function() {\n\t\t\t\treturn !list;\n\t\t\t},\n\n\t\t\t// Disable .fire\n\t\t\t// Also disable .add unless we have memory (since it would have no effect)\n\t\t\t// Abort any pending executions\n\t\t\tlock: function() {\n\t\t\t\tlocked = queue = [];\n\t\t\t\tif ( !memory && !firing ) {\n\t\t\t\t\tlist = memory = \"\";\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\tlocked: function() {\n\t\t\t\treturn !!locked;\n\t\t\t},\n\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 ( !locked ) {\n\t\t\t\t\targs = args || [];\n\t\t\t\t\targs = [ context, args.slice ? args.slice() : args ];\n\t\t\t\t\tqueue.push( args );\n\t\t\t\t\tif ( !firing ) {\n\t\t\t\t\t\tfire();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\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\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\nfunction Identity( v ) {\n\treturn v;\n}\nfunction Thrower( ex ) {\n\tthrow ex;\n}\n\nfunction adoptValue( value, resolve, reject, noValue ) {\n\tvar method;\n\n\ttry {\n\n\t\t// Check for promise aspect first to privilege synchronous behavior\n\t\tif ( value && jQuery.isFunction( ( method = value.promise ) ) ) {\n\t\t\tmethod.call( value ).done( resolve ).fail( reject );\n\n\t\t// Other thenables\n\t\t} else if ( value && jQuery.isFunction( ( method = value.then ) ) ) {\n\t\t\tmethod.call( value, resolve, reject );\n\n\t\t// Other non-thenables\n\t\t} else {\n\n\t\t\t// Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer:\n\t\t\t// * false: [ value ].slice( 0 ) => resolve( value )\n\t\t\t// * true: [ value ].slice( 1 ) => resolve()\n\t\t\tresolve.apply( undefined, [ value ].slice( noValue ) );\n\t\t}\n\n\t// For Promises/A+, convert exceptions into rejections\n\t// Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in\n\t// Deferred#then to conditionally suppress rejection.\n\t} catch ( value ) {\n\n\t\t// Support: Android 4.0 only\n\t\t// Strict mode functions invoked without .call/.apply get global-object context\n\t\treject.apply( undefined, [ value ] );\n\t}\n}\n\njQuery.extend( {\n\n\tDeferred: function( func ) {\n\t\tvar tuples = [\n\n\t\t\t\t// action, add listener, callbacks,\n\t\t\t\t// ... .then handlers, argument index, [final state]\n\t\t\t\t[ \"notify\", \"progress\", jQuery.Callbacks( \"memory\" ),\n\t\t\t\t\tjQuery.Callbacks( \"memory\" ), 2 ],\n\t\t\t\t[ \"resolve\", \"done\", jQuery.Callbacks( \"once memory\" ),\n\t\t\t\t\tjQuery.Callbacks( \"once memory\" ), 0, \"resolved\" ],\n\t\t\t\t[ \"reject\", \"fail\", jQuery.Callbacks( \"once memory\" ),\n\t\t\t\t\tjQuery.Callbacks( \"once memory\" ), 1, \"rejected\" ]\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\t\"catch\": function( fn ) {\n\t\t\t\t\treturn promise.then( null, fn );\n\t\t\t\t},\n\n\t\t\t\t// Keep pipe for back-compat\n\t\t\t\tpipe: function( /* fnDone, fnFail, fnProgress */ ) {\n\t\t\t\t\tvar fns = arguments;\n\n\t\t\t\t\treturn jQuery.Deferred( function( newDefer ) {\n\t\t\t\t\t\tjQuery.each( tuples, function( i, tuple ) {\n\n\t\t\t\t\t\t\t// Map tuples (progress, done, fail) to arguments (done, fail, progress)\n\t\t\t\t\t\t\tvar fn = jQuery.isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ];\n\n\t\t\t\t\t\t\t// deferred.progress(function() { bind to newDefer or newDefer.notify })\n\t\t\t\t\t\t\t// deferred.done(function() { bind to newDefer or newDefer.resolve })\n\t\t\t\t\t\t\t// deferred.fail(function() { bind to newDefer or newDefer.reject })\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.progress( newDefer.notify )\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} else {\n\t\t\t\t\t\t\t\t\tnewDefer[ tuple[ 0 ] + \"With\" ](\n\t\t\t\t\t\t\t\t\t\tthis,\n\t\t\t\t\t\t\t\t\t\tfn ? [ returned ] : arguments\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\tfns = null;\n\t\t\t\t\t} ).promise();\n\t\t\t\t},\n\t\t\t\tthen: function( onFulfilled, onRejected, onProgress ) {\n\t\t\t\t\tvar maxDepth = 0;\n\t\t\t\t\tfunction resolve( depth, deferred, handler, special ) {\n\t\t\t\t\t\treturn function() {\n\t\t\t\t\t\t\tvar that = this,\n\t\t\t\t\t\t\t\targs = arguments,\n\t\t\t\t\t\t\t\tmightThrow = function() {\n\t\t\t\t\t\t\t\t\tvar returned, then;\n\n\t\t\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.3.3.3\n\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-59\n\t\t\t\t\t\t\t\t\t// Ignore double-resolution attempts\n\t\t\t\t\t\t\t\t\tif ( depth < maxDepth ) {\n\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\treturned = handler.apply( that, args );\n\n\t\t\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.1\n\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-48\n\t\t\t\t\t\t\t\t\tif ( returned === deferred.promise() ) {\n\t\t\t\t\t\t\t\t\t\tthrow new TypeError( \"Thenable self-resolution\" );\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Support: Promises/A+ sections 2.3.3.1, 3.5\n\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-54\n\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-75\n\t\t\t\t\t\t\t\t\t// Retrieve `then` only once\n\t\t\t\t\t\t\t\t\tthen = returned &&\n\n\t\t\t\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.4\n\t\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-64\n\t\t\t\t\t\t\t\t\t\t// Only check objects and functions for thenability\n\t\t\t\t\t\t\t\t\t\t( typeof returned === \"object\" ||\n\t\t\t\t\t\t\t\t\t\t\ttypeof returned === \"function\" ) &&\n\t\t\t\t\t\t\t\t\t\treturned.then;\n\n\t\t\t\t\t\t\t\t\t// Handle a returned thenable\n\t\t\t\t\t\t\t\t\tif ( jQuery.isFunction( then ) ) {\n\n\t\t\t\t\t\t\t\t\t\t// Special processors (notify) just wait for resolution\n\t\t\t\t\t\t\t\t\t\tif ( special ) {\n\t\t\t\t\t\t\t\t\t\t\tthen.call(\n\t\t\t\t\t\t\t\t\t\t\t\treturned,\n\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Identity, special ),\n\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Thrower, special )\n\t\t\t\t\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t\t\t\t// Normal processors (resolve) also hook into progress\n\t\t\t\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t\t\t\t// ...and disregard older resolution values\n\t\t\t\t\t\t\t\t\t\t\tmaxDepth++;\n\n\t\t\t\t\t\t\t\t\t\t\tthen.call(\n\t\t\t\t\t\t\t\t\t\t\t\treturned,\n\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Identity, special ),\n\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Thrower, special ),\n\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Identity,\n\t\t\t\t\t\t\t\t\t\t\t\t\tdeferred.notifyWith )\n\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Handle all other returned values\n\t\t\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t\t\t// Only substitute handlers pass on context\n\t\t\t\t\t\t\t\t\t\t// and multiple values (non-spec behavior)\n\t\t\t\t\t\t\t\t\t\tif ( handler !== Identity ) {\n\t\t\t\t\t\t\t\t\t\t\tthat = undefined;\n\t\t\t\t\t\t\t\t\t\t\targs = [ returned ];\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t// Process the value(s)\n\t\t\t\t\t\t\t\t\t\t// Default process is resolve\n\t\t\t\t\t\t\t\t\t\t( special || deferred.resolveWith )( that, args );\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// Only normal processors (resolve) catch and reject exceptions\n\t\t\t\t\t\t\t\tprocess = special ?\n\t\t\t\t\t\t\t\t\tmightThrow :\n\t\t\t\t\t\t\t\t\tfunction() {\n\t\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\t\tmightThrow();\n\t\t\t\t\t\t\t\t\t\t} catch ( e ) {\n\n\t\t\t\t\t\t\t\t\t\t\tif ( jQuery.Deferred.exceptionHook ) {\n\t\t\t\t\t\t\t\t\t\t\t\tjQuery.Deferred.exceptionHook( e,\n\t\t\t\t\t\t\t\t\t\t\t\t\tprocess.stackTrace );\n\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.3.3.4.1\n\t\t\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-61\n\t\t\t\t\t\t\t\t\t\t\t// Ignore post-resolution exceptions\n\t\t\t\t\t\t\t\t\t\t\tif ( depth + 1 >= maxDepth ) {\n\n\t\t\t\t\t\t\t\t\t\t\t\t// Only substitute handlers pass on context\n\t\t\t\t\t\t\t\t\t\t\t\t// and multiple values (non-spec behavior)\n\t\t\t\t\t\t\t\t\t\t\t\tif ( handler !== Thrower ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tthat = undefined;\n\t\t\t\t\t\t\t\t\t\t\t\t\targs = [ e ];\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\tdeferred.rejectWith( that, args );\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};\n\n\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.3.3.1\n\t\t\t\t\t\t\t// https://promisesaplus.com/#point-57\n\t\t\t\t\t\t\t// Re-resolve promises immediately to dodge false rejection from\n\t\t\t\t\t\t\t// subsequent errors\n\t\t\t\t\t\t\tif ( depth ) {\n\t\t\t\t\t\t\t\tprocess();\n\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t// Call an optional hook to record the stack, in case of exception\n\t\t\t\t\t\t\t\t// since it's otherwise lost when execution goes async\n\t\t\t\t\t\t\t\tif ( jQuery.Deferred.getStackHook ) {\n\t\t\t\t\t\t\t\t\tprocess.stackTrace = jQuery.Deferred.getStackHook();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\twindow.setTimeout( process );\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 jQuery.Deferred( function( newDefer ) {\n\n\t\t\t\t\t\t// progress_handlers.add( ... )\n\t\t\t\t\t\ttuples[ 0 ][ 3 ].add(\n\t\t\t\t\t\t\tresolve(\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\tnewDefer,\n\t\t\t\t\t\t\t\tjQuery.isFunction( onProgress ) ?\n\t\t\t\t\t\t\t\t\tonProgress :\n\t\t\t\t\t\t\t\t\tIdentity,\n\t\t\t\t\t\t\t\tnewDefer.notifyWith\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\t// fulfilled_handlers.add( ... )\n\t\t\t\t\t\ttuples[ 1 ][ 3 ].add(\n\t\t\t\t\t\t\tresolve(\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\tnewDefer,\n\t\t\t\t\t\t\t\tjQuery.isFunction( onFulfilled ) ?\n\t\t\t\t\t\t\t\t\tonFulfilled :\n\t\t\t\t\t\t\t\t\tIdentity\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\t// rejected_handlers.add( ... )\n\t\t\t\t\t\ttuples[ 2 ][ 3 ].add(\n\t\t\t\t\t\t\tresolve(\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\tnewDefer,\n\t\t\t\t\t\t\t\tjQuery.isFunction( onRejected ) ?\n\t\t\t\t\t\t\t\t\tonRejected :\n\t\t\t\t\t\t\t\t\tThrower\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t);\n\t\t\t\t\t} ).promise();\n\t\t\t\t},\n\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// 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[ 5 ];\n\n\t\t\t// promise.progress = list.add\n\t\t\t// promise.done = list.add\n\t\t\t// promise.fail = 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(\n\t\t\t\t\tfunction() {\n\n\t\t\t\t\t\t// state = \"resolved\" (i.e., fulfilled)\n\t\t\t\t\t\t// state = \"rejected\"\n\t\t\t\t\t\tstate = stateString;\n\t\t\t\t\t},\n\n\t\t\t\t\t// rejected_callbacks.disable\n\t\t\t\t\t// fulfilled_callbacks.disable\n\t\t\t\t\ttuples[ 3 - i ][ 2 ].disable,\n\n\t\t\t\t\t// progress_callbacks.lock\n\t\t\t\t\ttuples[ 0 ][ 2 ].lock\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// progress_handlers.fire\n\t\t\t// fulfilled_handlers.fire\n\t\t\t// rejected_handlers.fire\n\t\t\tlist.add( tuple[ 3 ].fire );\n\n\t\t\t// deferred.notify = function() { deferred.notifyWith(...) }\n\t\t\t// deferred.resolve = function() { deferred.resolveWith(...) }\n\t\t\t// deferred.reject = function() { deferred.rejectWith(...) }\n\t\t\tdeferred[ tuple[ 0 ] ] = function() {\n\t\t\t\tdeferred[ tuple[ 0 ] + \"With\" ]( this === deferred ? undefined : this, arguments );\n\t\t\t\treturn this;\n\t\t\t};\n\n\t\t\t// deferred.notifyWith = list.fireWith\n\t\t\t// deferred.resolveWith = list.fireWith\n\t\t\t// deferred.rejectWith = list.fireWith\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( singleValue ) {\n\t\tvar\n\n\t\t\t// count of uncompleted subordinates\n\t\t\tremaining = arguments.length,\n\n\t\t\t// count of unprocessed arguments\n\t\t\ti = remaining,\n\n\t\t\t// subordinate fulfillment data\n\t\t\tresolveContexts = Array( i ),\n\t\t\tresolveValues = slice.call( arguments ),\n\n\t\t\t// the master Deferred\n\t\t\tmaster = jQuery.Deferred(),\n\n\t\t\t// subordinate callback factory\n\t\t\tupdateFunc = function( i ) {\n\t\t\t\treturn function( value ) {\n\t\t\t\t\tresolveContexts[ i ] = this;\n\t\t\t\t\tresolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;\n\t\t\t\t\tif ( !( --remaining ) ) {\n\t\t\t\t\t\tmaster.resolveWith( resolveContexts, resolveValues );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t};\n\n\t\t// Single- and empty arguments are adopted like Promise.resolve\n\t\tif ( remaining <= 1 ) {\n\t\t\tadoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject,\n\t\t\t\t!remaining );\n\n\t\t\t// Use .then() to unwrap secondary thenables (cf. gh-3000)\n\t\t\tif ( master.state() === \"pending\" ||\n\t\t\t\tjQuery.isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) {\n\n\t\t\t\treturn master.then();\n\t\t\t}\n\t\t}\n\n\t\t// Multiple arguments are aggregated like Promise.all array elements\n\t\twhile ( i-- ) {\n\t\t\tadoptValue( resolveValues[ i ], updateFunc( i ), master.reject );\n\t\t}\n\n\t\treturn master.promise();\n\t}\n} );\n\n\n// These usually indicate a programmer mistake during development,\n// warn about them ASAP rather than swallowing them by default.\nvar rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;\n\njQuery.Deferred.exceptionHook = function( error, stack ) {\n\n\t// Support: IE 8 - 9 only\n\t// Console exists when dev tools are open, which can happen at any time\n\tif ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) {\n\t\twindow.console.warn( \"jQuery.Deferred exception: \" + error.message, error.stack, stack );\n\t}\n};\n\n\n\n\njQuery.readyException = function( error ) {\n\twindow.setTimeout( function() {\n\t\tthrow error;\n\t} );\n};\n\n\n\n\n// The deferred used on DOM ready\nvar readyList = jQuery.Deferred();\n\njQuery.fn.ready = function( fn ) {\n\n\treadyList\n\t\t.then( fn )\n\n\t\t// Wrap jQuery.readyException in a function so that the lookup\n\t\t// happens at the time of error handling instead of callback\n\t\t// registration.\n\t\t.catch( function( error ) {\n\t\t\tjQuery.readyException( error );\n\t\t} );\n\n\treturn this;\n};\n\njQuery.extend( {\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// 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\t}\n} );\n\njQuery.ready.then = readyList.then;\n\n// The ready event handler and self cleanup method\nfunction completed() {\n\tdocument.removeEventListener( \"DOMContentLoaded\", completed );\n\twindow.removeEventListener( \"load\", completed );\n\tjQuery.ready();\n}\n\n// Catch cases where $(document).ready() is called\n// after the browser event has already occurred.\n// Support: IE <=9 - 10 only\n// Older IE sometimes signals \"interactive\" too soon\nif ( document.readyState === \"complete\" ||\n\t( document.readyState !== \"loading\" && !document.documentElement.doScroll ) ) {\n\n\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\twindow.setTimeout( jQuery.ready );\n\n} else {\n\n\t// Use the handy event callback\n\tdocument.addEventListener( \"DOMContentLoaded\", completed );\n\n\t// A fallback to window.onload, that will always work\n\twindow.addEventListener( \"load\", completed );\n}\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 = 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\taccess( 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\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(\n\t\t\t\t\telems[ i ], key, raw ?\n\t\t\t\t\tvalue :\n\t\t\t\t\tvalue.call( elems[ i ], i, fn( elems[ i ], key ) )\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( chainable ) {\n\t\treturn elems;\n\t}\n\n\t// Gets\n\tif ( bulk ) {\n\t\treturn fn.call( elems );\n\t}\n\n\treturn len ? fn( elems[ 0 ], key ) : emptyGet;\n};\nvar acceptData = function( owner ) {\n\n\t// Accepts only:\n\t//  - Node\n\t//    - Node.ELEMENT_NODE\n\t//    - Node.DOCUMENT_NODE\n\t//  - Object\n\t//    - Any\n\treturn owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );\n};\n\n\n\n\nfunction Data() {\n\tthis.expando = jQuery.expando + Data.uid++;\n}\n\nData.uid = 1;\n\nData.prototype = {\n\n\tcache: function( owner ) {\n\n\t\t// Check if the owner object already has a cache\n\t\tvar value = owner[ this.expando ];\n\n\t\t// If not, create one\n\t\tif ( !value ) {\n\t\t\tvalue = {};\n\n\t\t\t// We can accept data for non-element nodes in modern browsers,\n\t\t\t// but we should not, see #8335.\n\t\t\t// Always return an empty object.\n\t\t\tif ( acceptData( owner ) ) {\n\n\t\t\t\t// If it is a node unlikely to be stringify-ed or looped over\n\t\t\t\t// use plain assignment\n\t\t\t\tif ( owner.nodeType ) {\n\t\t\t\t\towner[ this.expando ] = value;\n\n\t\t\t\t// Otherwise secure it in a non-enumerable property\n\t\t\t\t// configurable must be true to allow the property to be\n\t\t\t\t// deleted when data is removed\n\t\t\t\t} else {\n\t\t\t\t\tObject.defineProperty( owner, this.expando, {\n\t\t\t\t\t\tvalue: value,\n\t\t\t\t\t\tconfigurable: true\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn value;\n\t},\n\tset: function( owner, data, value ) {\n\t\tvar prop,\n\t\t\tcache = this.cache( owner );\n\n\t\t// Handle: [ owner, key, value ] args\n\t\t// Always use camelCase key (gh-2257)\n\t\tif ( typeof data === \"string\" ) {\n\t\t\tcache[ jQuery.camelCase( data ) ] = value;\n\n\t\t// Handle: [ owner, { properties } ] args\n\t\t} else {\n\n\t\t\t// Copy the properties one-by-one to the cache object\n\t\t\tfor ( prop in data ) {\n\t\t\t\tcache[ jQuery.camelCase( prop ) ] = data[ prop ];\n\t\t\t}\n\t\t}\n\t\treturn cache;\n\t},\n\tget: function( owner, key ) {\n\t\treturn key === undefined ?\n\t\t\tthis.cache( owner ) :\n\n\t\t\t// Always use camelCase key (gh-2257)\n\t\t\towner[ this.expando ] && owner[ this.expando ][ jQuery.camelCase( key ) ];\n\t},\n\taccess: function( owner, key, value ) {\n\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\treturn this.get( owner, 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,\n\t\t\tcache = owner[ this.expando ];\n\n\t\tif ( cache === undefined ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( key !== undefined ) {\n\n\t\t\t// Support array or space separated string of keys\n\t\t\tif ( Array.isArray( key ) ) {\n\n\t\t\t\t// If key is an array of keys...\n\t\t\t\t// We always set camelCase keys, so remove that.\n\t\t\t\tkey = key.map( jQuery.camelCase );\n\t\t\t} else {\n\t\t\t\tkey = jQuery.camelCase( key );\n\n\t\t\t\t// If a key with the spaces exists, use it.\n\t\t\t\t// Otherwise, create an array by matching non-whitespace\n\t\t\t\tkey = key in cache ?\n\t\t\t\t\t[ key ] :\n\t\t\t\t\t( key.match( rnothtmlwhite ) || [] );\n\t\t\t}\n\n\t\t\ti = key.length;\n\n\t\t\twhile ( i-- ) {\n\t\t\t\tdelete cache[ key[ i ] ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove the expando if there's no more data\n\t\tif ( key === undefined || jQuery.isEmptyObject( cache ) ) {\n\n\t\t\t// Support: Chrome <=35 - 45\n\t\t\t// Webkit & Blink performance suffers when deleting properties\n\t\t\t// from DOM nodes, so set to undefined instead\n\t\t\t// https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted)\n\t\t\tif ( owner.nodeType ) {\n\t\t\t\towner[ this.expando ] = undefined;\n\t\t\t} else {\n\t\t\t\tdelete owner[ this.expando ];\n\t\t\t}\n\t\t}\n\t},\n\thasData: function( owner ) {\n\t\tvar cache = owner[ this.expando ];\n\t\treturn cache !== undefined && !jQuery.isEmptyObject( cache );\n\t}\n};\nvar dataPriv = new Data();\n\nvar dataUser = 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 getData( data ) {\n\tif ( data === \"true\" ) {\n\t\treturn true;\n\t}\n\n\tif ( data === \"false\" ) {\n\t\treturn false;\n\t}\n\n\tif ( data === \"null\" ) {\n\t\treturn null;\n\t}\n\n\t// Only convert to a number if it doesn't change the string\n\tif ( data === +data + \"\" ) {\n\t\treturn +data;\n\t}\n\n\tif ( rbrace.test( data ) ) {\n\t\treturn JSON.parse( data );\n\t}\n\n\treturn data;\n}\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, \"-$&\" ).toLowerCase();\n\t\tdata = elem.getAttribute( name );\n\n\t\tif ( typeof data === \"string\" ) {\n\t\t\ttry {\n\t\t\t\tdata = getData( data );\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\tdataUser.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 dataUser.hasData( elem ) || dataPriv.hasData( elem );\n\t},\n\n\tdata: function( elem, name, data ) {\n\t\treturn dataUser.access( elem, name, data );\n\t},\n\n\tremoveData: function( elem, name ) {\n\t\tdataUser.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 dataPriv methods, these can be deprecated.\n\t_data: function( elem, name, data ) {\n\t\treturn dataPriv.access( elem, name, data );\n\t},\n\n\t_removeData: function( elem, name ) {\n\t\tdataPriv.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 = dataUser.get( elem );\n\n\t\t\t\tif ( elem.nodeType === 1 && !dataPriv.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: IE 11 only\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\tdataPriv.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\tdataUser.set( this, key );\n\t\t\t} );\n\t\t}\n\n\t\treturn access( this, function( value ) {\n\t\t\tvar data;\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\n\t\t\t\t// Attempt to get data from the cache\n\t\t\t\t// The key will always be camelCased in Data\n\t\t\t\tdata = dataUser.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 \"discover\" the data in\n\t\t\t\t// HTML5 custom data-* attrs\n\t\t\t\tdata = dataAttr( 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// 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\n\t\t\t\t// We always store the camelCased key\n\t\t\t\tdataUser.set( 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\tdataUser.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 = dataPriv.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 || Array.isArray( data ) ) {\n\t\t\t\t\tqueue = dataPriv.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 dataPriv.get( elem, key ) || dataPriv.access( elem, key, {\n\t\t\tempty: jQuery.Callbacks( \"once memory\" ).add( function() {\n\t\t\t\tdataPriv.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\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 = dataPriv.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 rcssNum = new RegExp( \"^(?:([+-])=|)(\" + pnum + \")([a-z%]*)$\", \"i\" );\n\n\nvar cssExpand = [ \"Top\", \"Right\", \"Bottom\", \"Left\" ];\n\nvar isHiddenWithinTree = function( elem, el ) {\n\n\t\t// isHiddenWithinTree might be called from jQuery#filter function;\n\t\t// in that case, element will be second argument\n\t\telem = el || elem;\n\n\t\t// Inline style trumps all\n\t\treturn elem.style.display === \"none\" ||\n\t\t\telem.style.display === \"\" &&\n\n\t\t\t// Otherwise, check computed style\n\t\t\t// Support: Firefox <=43 - 45\n\t\t\t// Disconnected elements can have computed display: none, so first confirm that elem is\n\t\t\t// in the document.\n\t\t\tjQuery.contains( elem.ownerDocument, elem ) &&\n\n\t\t\tjQuery.css( elem, \"display\" ) === \"none\";\n\t};\n\nvar 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\n\n\nfunction adjustCSS( elem, prop, valueParts, tween ) {\n\tvar adjusted,\n\t\tscale = 1,\n\t\tmaxIterations = 20,\n\t\tcurrentValue = tween ?\n\t\t\tfunction() {\n\t\t\t\treturn tween.cur();\n\t\t\t} :\n\t\t\tfunction() {\n\t\t\t\treturn jQuery.css( elem, prop, \"\" );\n\t\t\t},\n\t\tinitial = currentValue(),\n\t\tunit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" ),\n\n\t\t// Starting value computation is required for potential unit mismatches\n\t\tinitialInUnit = ( jQuery.cssNumber[ prop ] || unit !== \"px\" && +initial ) &&\n\t\t\trcssNum.exec( jQuery.css( elem, prop ) );\n\n\tif ( initialInUnit && initialInUnit[ 3 ] !== unit ) {\n\n\t\t// Trust units reported by jQuery.css\n\t\tunit = unit || initialInUnit[ 3 ];\n\n\t\t// Make sure we update the tween properties later on\n\t\tvalueParts = valueParts || [];\n\n\t\t// Iteratively approximate from a nonzero starting point\n\t\tinitialInUnit = +initial || 1;\n\n\t\tdo {\n\n\t\t\t// If previous iteration zeroed out, double until we get *something*.\n\t\t\t// Use string for doubling so we don't accidentally see scale as unchanged below\n\t\t\tscale = scale || \".5\";\n\n\t\t\t// Adjust and apply\n\t\t\tinitialInUnit = initialInUnit / scale;\n\t\t\tjQuery.style( elem, prop, initialInUnit + unit );\n\n\t\t// Update scale, tolerating zero or NaN from tween.cur()\n\t\t// Break the loop if scale is unchanged or perfect, or if we've just had enough.\n\t\t} while (\n\t\t\tscale !== ( scale = currentValue() / initial ) && scale !== 1 && --maxIterations\n\t\t);\n\t}\n\n\tif ( valueParts ) {\n\t\tinitialInUnit = +initialInUnit || +initial || 0;\n\n\t\t// Apply relative offset (+=/-=) if specified\n\t\tadjusted = valueParts[ 1 ] ?\n\t\t\tinitialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] :\n\t\t\t+valueParts[ 2 ];\n\t\tif ( tween ) {\n\t\t\ttween.unit = unit;\n\t\t\ttween.start = initialInUnit;\n\t\t\ttween.end = adjusted;\n\t\t}\n\t}\n\treturn adjusted;\n}\n\n\nvar defaultDisplayMap = {};\n\nfunction getDefaultDisplay( elem ) {\n\tvar temp,\n\t\tdoc = elem.ownerDocument,\n\t\tnodeName = elem.nodeName,\n\t\tdisplay = defaultDisplayMap[ nodeName ];\n\n\tif ( display ) {\n\t\treturn display;\n\t}\n\n\ttemp = doc.body.appendChild( doc.createElement( nodeName ) );\n\tdisplay = jQuery.css( temp, \"display\" );\n\n\ttemp.parentNode.removeChild( temp );\n\n\tif ( display === \"none\" ) {\n\t\tdisplay = \"block\";\n\t}\n\tdefaultDisplayMap[ nodeName ] = display;\n\n\treturn display;\n}\n\nfunction showHide( elements, show ) {\n\tvar display, elem,\n\t\tvalues = [],\n\t\tindex = 0,\n\t\tlength = elements.length;\n\n\t// Determine new display value for elements that need to change\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\tdisplay = elem.style.display;\n\t\tif ( show ) {\n\n\t\t\t// Since we force visibility upon cascade-hidden elements, an immediate (and slow)\n\t\t\t// check is required in this first loop unless we have a nonempty display value (either\n\t\t\t// inline or about-to-be-restored)\n\t\t\tif ( display === \"none\" ) {\n\t\t\t\tvalues[ index ] = dataPriv.get( elem, \"display\" ) || null;\n\t\t\t\tif ( !values[ index ] ) {\n\t\t\t\t\telem.style.display = \"\";\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( elem.style.display === \"\" && isHiddenWithinTree( elem ) ) {\n\t\t\t\tvalues[ index ] = getDefaultDisplay( elem );\n\t\t\t}\n\t\t} else {\n\t\t\tif ( display !== \"none\" ) {\n\t\t\t\tvalues[ index ] = \"none\";\n\n\t\t\t\t// Remember what we're overwriting\n\t\t\t\tdataPriv.set( elem, \"display\", display );\n\t\t\t}\n\t\t}\n\t}\n\n\t// Set the display of the elements in a second loop to avoid constant reflow\n\tfor ( index = 0; index < length; index++ ) {\n\t\tif ( values[ index ] != null ) {\n\t\t\telements[ index ].style.display = values[ index ];\n\t\t}\n\t}\n\n\treturn elements;\n}\n\njQuery.fn.extend( {\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 ( isHiddenWithinTree( 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} );\nvar rcheckableType = ( /^(?:checkbox|radio)$/i );\n\nvar rtagName = ( /<([a-z][^\\/\\0>\\x20\\t\\r\\n\\f]+)/i );\n\nvar rscriptType = ( /^$|\\/(?:java|ecma)script/i );\n\n\n\n// We have to close these tags to support XHTML (#13200)\nvar wrapMap = {\n\n\t// Support: IE <=9 only\n\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\n\t// XHTML parsers do not magically insert elements in the\n\t// same way that tag soup parsers do. So we cannot shorten\n\t// this by omitting <tbody> or other required elements.\n\tthead: [ 1, \"<table>\", \"</table>\" ],\n\tcol: [ 2, \"<table><colgroup>\", \"</colgroup></table>\" ],\n\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\n\t_default: [ 0, \"\", \"\" ]\n};\n\n// Support: IE <=9 only\nwrapMap.optgroup = wrapMap.option;\n\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n\nfunction getAll( context, tag ) {\n\n\t// Support: IE <=9 - 11 only\n\t// Use typeof to avoid zero-argument method invocation on host objects (#15151)\n\tvar ret;\n\n\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\tret = context.getElementsByTagName( tag || \"*\" );\n\n\t} else if ( typeof context.querySelectorAll !== \"undefined\" ) {\n\t\tret = context.querySelectorAll( tag || \"*\" );\n\n\t} else {\n\t\tret = [];\n\t}\n\n\tif ( tag === undefined || tag && nodeName( context, tag ) ) {\n\t\treturn jQuery.merge( [ context ], ret );\n\t}\n\n\treturn ret;\n}\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\tdataPriv.set(\n\t\t\telems[ i ],\n\t\t\t\"globalEval\",\n\t\t\t!refElements || dataPriv.get( refElements[ i ], \"globalEval\" )\n\t\t);\n\t}\n}\n\n\nvar rhtml = /<|&#?\\w+;/;\n\nfunction buildFragment( elems, context, scripts, selection, ignored ) {\n\tvar elem, tmp, tag, wrap, contains, j,\n\t\tfragment = context.createDocumentFragment(),\n\t\tnodes = [],\n\t\ti = 0,\n\t\tl = elems.length;\n\n\tfor ( ; i < l; i++ ) {\n\t\telem = elems[ i ];\n\n\t\tif ( elem || elem === 0 ) {\n\n\t\t\t// Add nodes directly\n\t\t\tif ( jQuery.type( elem ) === \"object\" ) {\n\n\t\t\t\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t\t\t\t// push.apply(_, arraylike) throws on ancient WebKit\n\t\t\t\tjQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );\n\n\t\t\t// Convert non-html into a text node\n\t\t\t} else if ( !rhtml.test( elem ) ) {\n\t\t\t\tnodes.push( context.createTextNode( elem ) );\n\n\t\t\t// Convert html into DOM nodes\n\t\t\t} else {\n\t\t\t\ttmp = tmp || fragment.appendChild( context.createElement( \"div\" ) );\n\n\t\t\t\t// Deserialize a standard representation\n\t\t\t\ttag = ( rtagName.exec( elem ) || [ \"\", \"\" ] )[ 1 ].toLowerCase();\n\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default;\n\t\t\t\ttmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];\n\n\t\t\t\t// Descend through wrappers to the right content\n\t\t\t\tj = wrap[ 0 ];\n\t\t\t\twhile ( j-- ) {\n\t\t\t\t\ttmp = tmp.lastChild;\n\t\t\t\t}\n\n\t\t\t\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t\t\t\t// push.apply(_, arraylike) throws on ancient WebKit\n\t\t\t\tjQuery.merge( nodes, tmp.childNodes );\n\n\t\t\t\t// Remember the top-level container\n\t\t\t\ttmp = fragment.firstChild;\n\n\t\t\t\t// Ensure the created nodes are orphaned (#12392)\n\t\t\t\ttmp.textContent = \"\";\n\t\t\t}\n\t\t}\n\t}\n\n\t// Remove wrapper from fragment\n\tfragment.textContent = \"\";\n\n\ti = 0;\n\twhile ( ( elem = nodes[ i++ ] ) ) {\n\n\t\t// Skip elements already in the context collection (trac-4087)\n\t\tif ( selection && jQuery.inArray( elem, selection ) > -1 ) {\n\t\t\tif ( ignored ) {\n\t\t\t\tignored.push( elem );\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tcontains = jQuery.contains( elem.ownerDocument, elem );\n\n\t\t// Append to fragment\n\t\ttmp = getAll( fragment.appendChild( elem ), \"script\" );\n\n\t\t// Preserve script evaluation history\n\t\tif ( contains ) {\n\t\t\tsetGlobalEval( tmp );\n\t\t}\n\n\t\t// Capture executables\n\t\tif ( scripts ) {\n\t\t\tj = 0;\n\t\t\twhile ( ( elem = tmp[ j++ ] ) ) {\n\t\t\t\tif ( rscriptType.test( elem.type || \"\" ) ) {\n\t\t\t\t\tscripts.push( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn fragment;\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: Android 4.0 - 4.3 only\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: Android <=4.1 only\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 only\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 documentElement = document.documentElement;\n\n\n\nvar\n\trkeyEvent = /^key/,\n\trmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/,\n\trtypenamespace = /^([^.]*)(?:\\.(.+)|)/;\n\nfunction returnTrue() {\n\treturn true;\n}\n\nfunction returnFalse() {\n\treturn false;\n}\n\n// Support: IE <=9 only\n// See #13393 for more info\nfunction safeActiveElement() {\n\ttry {\n\t\treturn document.activeElement;\n\t} catch ( err ) { }\n}\n\nfunction on( elem, types, selector, data, fn, one ) {\n\tvar origFn, type;\n\n\t// Types can be a map of types/handlers\n\tif ( typeof types === \"object\" ) {\n\n\t\t// ( types-Object, selector, data )\n\t\tif ( typeof selector !== \"string\" ) {\n\n\t\t\t// ( types-Object, data )\n\t\t\tdata = data || selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tfor ( type in types ) {\n\t\t\ton( elem, type, selector, data, types[ type ], one );\n\t\t}\n\t\treturn elem;\n\t}\n\n\tif ( data == null && fn == null ) {\n\n\t\t// ( types, fn )\n\t\tfn = selector;\n\t\tdata = selector = undefined;\n\t} else if ( fn == null ) {\n\t\tif ( typeof selector === \"string\" ) {\n\n\t\t\t// ( types, selector, fn )\n\t\t\tfn = data;\n\t\t\tdata = undefined;\n\t\t} else {\n\n\t\t\t// ( types, data, fn )\n\t\t\tfn = data;\n\t\t\tdata = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t}\n\tif ( fn === false ) {\n\t\tfn = returnFalse;\n\t} else if ( !fn ) {\n\t\treturn elem;\n\t}\n\n\tif ( one === 1 ) {\n\t\torigFn = fn;\n\t\tfn = function( event ) {\n\n\t\t\t// Can use an empty set, since event contains the info\n\t\t\tjQuery().off( event );\n\t\t\treturn origFn.apply( this, arguments );\n\t\t};\n\n\t\t// Use same guid so caller can remove using origFn\n\t\tfn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n\t}\n\treturn elem.each( function() {\n\t\tjQuery.event.add( this, types, fn, data, selector );\n\t} );\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 = dataPriv.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// Ensure that invalid selectors throw exceptions at attach time\n\t\t// Evaluate against documentElement in case elem is a non-element node (e.g., document)\n\t\tif ( selector ) {\n\t\t\tjQuery.find.matchesSelector( documentElement, 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\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 !== \"undefined\" && 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( rnothtmlwhite ) || [ \"\" ];\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 ||\n\t\t\t\t\tspecial.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( 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},\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 = dataPriv.hasData( elem ) && dataPriv.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( rnothtmlwhite ) || [ \"\" ];\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 ] &&\n\t\t\t\tnew 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 ||\n\t\t\t\t\t\tselector === \"**\" && 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 ||\n\t\t\t\t\tspecial.teardown.call( elem, namespaces, elemData.handle ) === false ) {\n\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 data and the expando if it's no longer used\n\t\tif ( jQuery.isEmptyObject( events ) ) {\n\t\t\tdataPriv.remove( elem, \"handle events\" );\n\t\t}\n\t},\n\n\tdispatch: function( nativeEvent ) {\n\n\t\t// Make a writable jQuery.Event from the native event object\n\t\tvar event = jQuery.event.fix( nativeEvent );\n\n\t\tvar i, j, ret, matched, handleObj, handlerQueue,\n\t\t\targs = new Array( arguments.length ),\n\t\t\thandlers = ( dataPriv.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\n\t\tfor ( i = 1; i < arguments.length; i++ ) {\n\t\t\targs[ i ] = arguments[ i ];\n\t\t}\n\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++ ] ) &&\n\t\t\t\t!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.rnamespace || event.rnamespace.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 ||\n\t\t\t\t\t\thandleObj.handler ).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, handleObj, sel, matchedHandlers, matchedSelectors,\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\tif ( delegateCount &&\n\n\t\t\t// Support: IE <=9\n\t\t\t// Black-hole SVG <use> instance trees (trac-13180)\n\t\t\tcur.nodeType &&\n\n\t\t\t// Support: Firefox <=42\n\t\t\t// Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861)\n\t\t\t// https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click\n\t\t\t// Support: IE 11 only\n\t\t\t// ...but not arrow key \"clicks\" of radio inputs, which can have `button` -1 (gh-2343)\n\t\t\t!( event.type === \"click\" && event.button >= 1 ) ) {\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 && !( event.type === \"click\" && cur.disabled === true ) ) {\n\t\t\t\t\tmatchedHandlers = [];\n\t\t\t\t\tmatchedSelectors = {};\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 ( matchedSelectors[ sel ] === undefined ) {\n\t\t\t\t\t\t\tmatchedSelectors[ sel ] = handleObj.needsContext ?\n\t\t\t\t\t\t\t\tjQuery( sel, this ).index( cur ) > -1 :\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 ( matchedSelectors[ sel ] ) {\n\t\t\t\t\t\t\tmatchedHandlers.push( handleObj );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( matchedHandlers.length ) {\n\t\t\t\t\t\thandlerQueue.push( { elem: cur, handlers: matchedHandlers } );\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\tcur = this;\n\t\tif ( delegateCount < handlers.length ) {\n\t\t\thandlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } );\n\t\t}\n\n\t\treturn handlerQueue;\n\t},\n\n\taddProp: function( name, hook ) {\n\t\tObject.defineProperty( jQuery.Event.prototype, name, {\n\t\t\tenumerable: true,\n\t\t\tconfigurable: true,\n\n\t\t\tget: jQuery.isFunction( hook ) ?\n\t\t\t\tfunction() {\n\t\t\t\t\tif ( this.originalEvent ) {\n\t\t\t\t\t\t\treturn hook( this.originalEvent );\n\t\t\t\t\t}\n\t\t\t\t} :\n\t\t\t\tfunction() {\n\t\t\t\t\tif ( this.originalEvent ) {\n\t\t\t\t\t\t\treturn this.originalEvent[ name ];\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\tset: function( value ) {\n\t\t\t\tObject.defineProperty( this, name, {\n\t\t\t\t\tenumerable: true,\n\t\t\t\t\tconfigurable: true,\n\t\t\t\t\twritable: true,\n\t\t\t\t\tvalue: value\n\t\t\t\t} );\n\t\t\t}\n\t\t} );\n\t},\n\n\tfix: function( originalEvent ) {\n\t\treturn originalEvent[ jQuery.expando ] ?\n\t\t\toriginalEvent :\n\t\t\tnew jQuery.Event( originalEvent );\n\t},\n\n\tspecial: {\n\t\tload: {\n\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\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\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 && 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 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\njQuery.removeEvent = function( elem, type, handle ) {\n\n\t// This \"if\" is needed for plain objects\n\tif ( elem.removeEventListener ) {\n\t\telem.removeEventListener( type, handle );\n\t}\n};\n\njQuery.Event = function( src, props ) {\n\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\n\t\t\t\t// Support: Android <=2.3 only\n\t\t\t\tsrc.returnValue === false ?\n\t\t\treturnTrue :\n\t\t\treturnFalse;\n\n\t\t// Create target properties\n\t\t// Support: Safari <=6 - 7 only\n\t\t// Target should not be a text node (#504, #13143)\n\t\tthis.target = ( src.target && src.target.nodeType === 3 ) ?\n\t\t\tsrc.target.parentNode :\n\t\t\tsrc.target;\n\n\t\tthis.currentTarget = src.currentTarget;\n\t\tthis.relatedTarget = src.relatedTarget;\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// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n\tconstructor: jQuery.Event,\n\tisDefaultPrevented: returnFalse,\n\tisPropagationStopped: returnFalse,\n\tisImmediatePropagationStopped: returnFalse,\n\tisSimulated: false,\n\n\tpreventDefault: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isDefaultPrevented = returnTrue;\n\n\t\tif ( e && !this.isSimulated ) {\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 && !this.isSimulated ) {\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 && !this.isSimulated ) {\n\t\t\te.stopImmediatePropagation();\n\t\t}\n\n\t\tthis.stopPropagation();\n\t}\n};\n\n// Includes all common event props including KeyEvent and MouseEvent specific props\njQuery.each( {\n\taltKey: true,\n\tbubbles: true,\n\tcancelable: true,\n\tchangedTouches: true,\n\tctrlKey: true,\n\tdetail: true,\n\teventPhase: true,\n\tmetaKey: true,\n\tpageX: true,\n\tpageY: true,\n\tshiftKey: true,\n\tview: true,\n\t\"char\": true,\n\tcharCode: true,\n\tkey: true,\n\tkeyCode: true,\n\tbutton: true,\n\tbuttons: true,\n\tclientX: true,\n\tclientY: true,\n\toffsetX: true,\n\toffsetY: true,\n\tpointerId: true,\n\tpointerType: true,\n\tscreenX: true,\n\tscreenY: true,\n\ttargetTouches: true,\n\ttoElement: true,\n\ttouches: true,\n\n\twhich: function( event ) {\n\t\tvar button = event.button;\n\n\t\t// Add which for key events\n\t\tif ( event.which == null && rkeyEvent.test( event.type ) ) {\n\t\t\treturn event.charCode != null ? event.charCode : event.keyCode;\n\t\t}\n\n\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\tif ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) {\n\t\t\tif ( button & 1 ) {\n\t\t\t\treturn 1;\n\t\t\t}\n\n\t\t\tif ( button & 2 ) {\n\t\t\t\treturn 3;\n\t\t\t}\n\n\t\t\tif ( button & 4 ) {\n\t\t\t\treturn 2;\n\t\t\t}\n\n\t\t\treturn 0;\n\t\t}\n\n\t\treturn event.which;\n\t}\n}, jQuery.event.addProp );\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\n// so that event delegation works in jQuery.\n// Do the same for pointerenter/pointerleave and pointerover/pointerout\n//\n// Support: Safari 7 only\n// Safari sends mouseenter too often; see:\n// https://bugs.chromium.org/p/chromium/issues/detail?id=470258\n// for the description of the bug (it existed in older Chrome versions as well).\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 mouseenter/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\njQuery.fn.extend( {\n\n\ton: function( types, selector, data, fn ) {\n\t\treturn on( this, types, selector, data, fn );\n\t},\n\tone: function( types, selector, data, fn ) {\n\t\treturn on( this, 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\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 ?\n\t\t\t\t\thandleObj.origType + \".\" + handleObj.namespace :\n\t\t\t\t\thandleObj.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\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\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\n\nvar\n\n\t/* eslint-disable max-len */\n\n\t// See https://github.com/eslint/eslint/issues/3229\n\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\\/\\0>\\x20\\t\\r\\n\\f]*)[^>]*)\\/>/gi,\n\n\t/* eslint-enable */\n\n\t// Support: IE <=10 - 11, Edge 12 - 13\n\t// In IE/Edge using regex groups here causes severe slowdowns.\n\t// See https://connect.microsoft.com/IE/feedback/details/1736512/\n\trnoInnerhtml = /<script|<style|<link/i,\n\n\t// checked=\"checked\" or checked\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\trscriptTypeMasked = /^true\\/(.*)/,\n\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|--)|(?:\\]\\]|--)>\\s*$/g;\n\n// Prefer a tbody over its parent table for containing new rows\nfunction manipulationTarget( elem, content ) {\n\tif ( nodeName( elem, \"table\" ) &&\n\t\tnodeName( content.nodeType !== 11 ? content : content.firstChild, \"tr\" ) ) {\n\n\t\treturn jQuery( \">tbody\", elem )[ 0 ] || elem;\n\t}\n\n\treturn elem;\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\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 ( dataPriv.hasData( src ) ) {\n\t\tpdataOld = dataPriv.access( src );\n\t\tpdataCur = dataPriv.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 ( dataUser.hasData( src ) ) {\n\t\tudataOld = dataUser.access( src );\n\t\tudataCur = jQuery.extend( {}, udataOld );\n\n\t\tdataUser.set( dest, udataCur );\n\t}\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\nfunction domManip( collection, args, callback, ignored ) {\n\n\t// Flatten any nested arrays\n\targs = concat.apply( [], args );\n\n\tvar fragment, first, scripts, hasScripts, node, doc,\n\t\ti = 0,\n\t\tl = collection.length,\n\t\tiNoClone = l - 1,\n\t\tvalue = args[ 0 ],\n\t\tisFunction = jQuery.isFunction( value );\n\n\t// We can't cloneNode fragments that contain checked, in WebKit\n\tif ( isFunction ||\n\t\t\t( l > 1 && typeof value === \"string\" &&\n\t\t\t\t!support.checkClone && rchecked.test( value ) ) ) {\n\t\treturn collection.each( function( index ) {\n\t\t\tvar self = collection.eq( index );\n\t\t\tif ( isFunction ) {\n\t\t\t\targs[ 0 ] = value.call( this, index, self.html() );\n\t\t\t}\n\t\t\tdomManip( self, args, callback, ignored );\n\t\t} );\n\t}\n\n\tif ( l ) {\n\t\tfragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored );\n\t\tfirst = fragment.firstChild;\n\n\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\tfragment = first;\n\t\t}\n\n\t\t// Require either new content or an interest in ignored elements to invoke the callback\n\t\tif ( first || ignored ) {\n\t\t\tscripts = jQuery.map( getAll( fragment, \"script\" ), disableScript );\n\t\t\thasScripts = scripts.length;\n\n\t\t\t// Use the original fragment for the last item\n\t\t\t// instead of the first because it can end up\n\t\t\t// being emptied incorrectly in certain situations (#8070).\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tnode = fragment;\n\n\t\t\t\tif ( i !== iNoClone ) {\n\t\t\t\t\tnode = jQuery.clone( node, true, true );\n\n\t\t\t\t\t// Keep references to cloned scripts for later restoration\n\t\t\t\t\tif ( hasScripts ) {\n\n\t\t\t\t\t\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t\t\t\t\t\t// push.apply(_, arraylike) throws on ancient WebKit\n\t\t\t\t\t\tjQuery.merge( scripts, getAll( node, \"script\" ) );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcallback.call( collection[ i ], node, i );\n\t\t\t}\n\n\t\t\tif ( hasScripts ) {\n\t\t\t\tdoc = scripts[ scripts.length - 1 ].ownerDocument;\n\n\t\t\t\t// Reenable scripts\n\t\t\t\tjQuery.map( scripts, restoreScript );\n\n\t\t\t\t// Evaluate executable scripts on first document insertion\n\t\t\t\tfor ( i = 0; i < hasScripts; i++ ) {\n\t\t\t\t\tnode = scripts[ i ];\n\t\t\t\t\tif ( rscriptType.test( node.type || \"\" ) &&\n\t\t\t\t\t\t!dataPriv.access( node, \"globalEval\" ) &&\n\t\t\t\t\t\tjQuery.contains( doc, node ) ) {\n\n\t\t\t\t\t\tif ( node.src ) {\n\n\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\tif ( jQuery._evalUrl ) {\n\t\t\t\t\t\t\t\tjQuery._evalUrl( node.src );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tDOMEval( node.textContent.replace( rcleanScript, \"\" ), doc );\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 collection;\n}\n\nfunction remove( elem, selector, keepData ) {\n\tvar node,\n\t\tnodes = selector ? jQuery.filter( selector, elem ) : elem,\n\t\ti = 0;\n\n\tfor ( ; ( node = nodes[ i ] ) != null; i++ ) {\n\t\tif ( !keepData && node.nodeType === 1 ) {\n\t\t\tjQuery.cleanData( getAll( node ) );\n\t\t}\n\n\t\tif ( node.parentNode ) {\n\t\t\tif ( keepData && jQuery.contains( node.ownerDocument, node ) ) {\n\t\t\t\tsetGlobalEval( getAll( node, \"script\" ) );\n\t\t\t}\n\t\t\tnode.parentNode.removeChild( node );\n\t\t}\n\t}\n\n\treturn elem;\n}\n\njQuery.extend( {\n\thtmlPrefilter: function( html ) {\n\t\treturn html.replace( rxhtmlTag, \"<$1></$2>\" );\n\t},\n\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: https://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\tcleanData: function( elems ) {\n\t\tvar data, elem, type,\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 ( acceptData( elem ) ) {\n\t\t\t\tif ( ( data = elem[ dataPriv.expando ] ) ) {\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// Support: Chrome <=35 - 45+\n\t\t\t\t\t// Assign undefined instead of using delete, see Data#remove\n\t\t\t\t\telem[ dataPriv.expando ] = undefined;\n\t\t\t\t}\n\t\t\t\tif ( elem[ dataUser.expando ] ) {\n\n\t\t\t\t\t// Support: Chrome <=35 - 45+\n\t\t\t\t\t// Assign undefined instead of using delete, see Data#remove\n\t\t\t\t\telem[ dataUser.expando ] = undefined;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n} );\n\njQuery.fn.extend( {\n\tdetach: function( selector ) {\n\t\treturn remove( this, selector, true );\n\t},\n\n\tremove: function( selector ) {\n\t\treturn remove( this, selector );\n\t},\n\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 domManip( this, 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 domManip( this, 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 domManip( this, 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 domManip( this, 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\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 = jQuery.htmlPrefilter( value );\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 ignored = [];\n\n\t\t// Make the changes, replacing each non-ignored context element with the new content\n\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\tvar parent = this.parentNode;\n\n\t\t\tif ( jQuery.inArray( this, ignored ) < 0 ) {\n\t\t\t\tjQuery.cleanData( getAll( this ) );\n\t\t\t\tif ( parent ) {\n\t\t\t\t\tparent.replaceChild( elem, this );\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Force callback invocation\n\t\t}, ignored );\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: Android <=4.0 only, PhantomJS 1 only\n\t\t\t// .get() because push.apply(_, arraylike) throws on ancient WebKit\n\t\t\tpush.apply( ret, elems.get() );\n\t\t}\n\n\t\treturn this.pushStack( ret );\n\t};\n} );\nvar rmargin = ( /^margin/ );\n\nvar rnumnonpx = new RegExp( \"^(\" + pnum + \")(?!px)[a-z%]+$\", \"i\" );\n\nvar getStyles = function( elem ) {\n\n\t\t// Support: IE <=11 only, 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\tvar view = elem.ownerDocument.defaultView;\n\n\t\tif ( !view || !view.opener ) {\n\t\t\tview = window;\n\t\t}\n\n\t\treturn view.getComputedStyle( elem );\n\t};\n\n\n\n( function() {\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 computeStyleTests() {\n\n\t\t// This is a singleton, we need to execute it only once\n\t\tif ( !div ) {\n\t\t\treturn;\n\t\t}\n\n\t\tdiv.style.cssText =\n\t\t\t\"box-sizing:border-box;\" +\n\t\t\t\"position:relative;display:block;\" +\n\t\t\t\"margin:auto;border:1px;padding:1px;\" +\n\t\t\t\"top:1%;width:50%\";\n\t\tdiv.innerHTML = \"\";\n\t\tdocumentElement.appendChild( container );\n\n\t\tvar divStyle = window.getComputedStyle( div );\n\t\tpixelPositionVal = divStyle.top !== \"1%\";\n\n\t\t// Support: Android 4.0 - 4.3 only, Firefox <=3 - 44\n\t\treliableMarginLeftVal = divStyle.marginLeft === \"2px\";\n\t\tboxSizingReliableVal = divStyle.width === \"4px\";\n\n\t\t// Support: Android 4.0 - 4.3 only\n\t\t// Some styles come back with percentage values, even though they shouldn't\n\t\tdiv.style.marginRight = \"50%\";\n\t\tpixelMarginRightVal = divStyle.marginRight === \"4px\";\n\n\t\tdocumentElement.removeChild( container );\n\n\t\t// Nullify the div so it wouldn't be stored in the memory and\n\t\t// it will also be a sign that checks already performed\n\t\tdiv = null;\n\t}\n\n\tvar pixelPositionVal, boxSizingReliableVal, pixelMarginRightVal, reliableMarginLeftVal,\n\t\tcontainer = document.createElement( \"div\" ),\n\t\tdiv = document.createElement( \"div\" );\n\n\t// Finish early in limited (non-browser) environments\n\tif ( !div.style ) {\n\t\treturn;\n\t}\n\n\t// Support: IE <=9 - 11 only\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:8px;height:0;top:0;left:-9999px;\" +\n\t\t\"padding:0;margin-top:1px;position:absolute\";\n\tcontainer.appendChild( div );\n\n\tjQuery.extend( support, {\n\t\tpixelPosition: function() {\n\t\t\tcomputeStyleTests();\n\t\t\treturn pixelPositionVal;\n\t\t},\n\t\tboxSizingReliable: function() {\n\t\t\tcomputeStyleTests();\n\t\t\treturn boxSizingReliableVal;\n\t\t},\n\t\tpixelMarginRight: function() {\n\t\t\tcomputeStyleTests();\n\t\t\treturn pixelMarginRightVal;\n\t\t},\n\t\treliableMarginLeft: function() {\n\t\t\tcomputeStyleTests();\n\t\t\treturn reliableMarginLeftVal;\n\t\t}\n\t} );\n} )();\n\n\nfunction curCSS( elem, name, computed ) {\n\tvar width, minWidth, maxWidth, ret,\n\n\t\t// Support: Firefox 51+\n\t\t// Retrieving style before computed somehow\n\t\t// fixes an issue with getting wrong values\n\t\t// on detached elements\n\t\tstyle = elem.style;\n\n\tcomputed = computed || getStyles( elem );\n\n\t// getPropertyValue is needed for:\n\t//   .css('filter') (IE 9 only, #12537)\n\t//   .css('--customProperty) (#3144)\n\tif ( computed ) {\n\t\tret = computed.getPropertyValue( name ) || computed[ name ];\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// A tribute to the \"awesome hack by Dean Edwards\"\n\t\t// Android Browser returns percentage for some values,\n\t\t// but width seems to be reliably pixels.\n\t\t// This is against the CSSOM draft spec:\n\t\t// https://drafts.csswg.org/cssom/#resolved-values\n\t\tif ( !support.pixelMarginRight() && 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\n\t\t// Support: IE <=9 - 11 only\n\t\t// IE returns zIndex value as an integer.\n\t\tret + \"\" :\n\t\tret;\n}\n\n\nfunction addGetHookIf( conditionFn, hookFn ) {\n\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\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\nvar\n\n\t// Swappable if display is none or starts with table\n\t// 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\trcustomProp = /^--/,\n\tcssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\tcssNormalTransform = {\n\t\tletterSpacing: \"0\",\n\t\tfontWeight: \"400\"\n\t},\n\n\tcssPrefixes = [ \"Webkit\", \"Moz\", \"ms\" ],\n\temptyStyle = document.createElement( \"div\" ).style;\n\n// Return a css property mapped to a potentially vendor prefixed property\nfunction vendorPropName( name ) {\n\n\t// Shortcut for names that are not vendor prefixed\n\tif ( name in emptyStyle ) {\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\ti = cssPrefixes.length;\n\n\twhile ( i-- ) {\n\t\tname = cssPrefixes[ i ] + capName;\n\t\tif ( name in emptyStyle ) {\n\t\t\treturn name;\n\t\t}\n\t}\n}\n\n// Return a property mapped along what jQuery.cssProps suggests or to\n// a vendor prefixed property.\nfunction finalPropName( name ) {\n\tvar ret = jQuery.cssProps[ name ];\n\tif ( !ret ) {\n\t\tret = jQuery.cssProps[ name ] = vendorPropName( name ) || name;\n\t}\n\treturn ret;\n}\n\nfunction setPositiveNumber( elem, value, subtract ) {\n\n\t// Any relative (+/-) values have already been\n\t// normalized at this point\n\tvar matches = rcssNum.exec( value );\n\treturn matches ?\n\n\t\t// Guard against undefined \"subtract\", e.g., when used as in cssHooks\n\t\tMath.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || \"px\" ) :\n\t\tvalue;\n}\n\nfunction augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {\n\tvar i,\n\t\tval = 0;\n\n\t// If we already have the right measurement, avoid augmentation\n\tif ( extra === ( isBorderBox ? \"border\" : \"content\" ) ) {\n\t\ti = 4;\n\n\t// Otherwise initialize for horizontal or vertical properties\n\t} else {\n\t\ti = name === \"width\" ? 1 : 0;\n\t}\n\n\tfor ( ; i < 4; i += 2 ) {\n\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\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\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 computed style\n\tvar valueIsBorderBox,\n\t\tstyles = getStyles( elem ),\n\t\tval = curCSS( elem, name, styles ),\n\t\tisBorderBox = jQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\";\n\n\t// Computed unit is not pixels. Stop here and return.\n\tif ( rnumnonpx.test( val ) ) {\n\t\treturn val;\n\t}\n\n\t// Check for style in case a browser which returns unreliable values\n\t// for getComputedStyle silently falls back to the reliable elem.style\n\tvalueIsBorderBox = isBorderBox &&\n\t\t( support.boxSizingReliable() || val === elem.style[ name ] );\n\n\t// Fall back to offsetWidth/Height when value is \"auto\"\n\t// This happens for inline elements with no explicit setting (gh-3571)\n\tif ( val === \"auto\" ) {\n\t\tval = elem[ \"offset\" + name[ 0 ].toUpperCase() + name.slice( 1 ) ];\n\t}\n\n\t// Normalize \"\", auto, and prepare for extra\n\tval = parseFloat( val ) || 0;\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\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\"animationIterationCount\": true,\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\tisCustomProp = rcustomProp.test( name ),\n\t\t\tstyle = elem.style;\n\n\t\t// Make sure that we're working with the right name. We don't\n\t\t// want to query the value if it is a CSS custom property\n\t\t// since they are user-defined.\n\t\tif ( !isCustomProp ) {\n\t\t\tname = finalPropName( origName );\n\t\t}\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 = rcssNum.exec( value ) ) && ret[ 1 ] ) {\n\t\t\t\tvalue = adjustCSS( elem, name, ret );\n\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 was passed in, add the unit (except for certain CSS properties)\n\t\t\tif ( type === \"number\" ) {\n\t\t\t\tvalue += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? \"\" : \"px\" );\n\t\t\t}\n\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 ) ||\n\t\t\t\t( value = hooks.set( elem, value, extra ) ) !== undefined ) {\n\n\t\t\t\tif ( isCustomProp ) {\n\t\t\t\t\tstyle.setProperty( name, value );\n\t\t\t\t} else {\n\t\t\t\t\tstyle[ name ] = value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\tif ( hooks && \"get\" in hooks &&\n\t\t\t\t( ret = hooks.get( elem, false, extra ) ) !== undefined ) {\n\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\t\t\tisCustomProp = rcustomProp.test( name );\n\n\t\t// Make sure that we're working with the right name. We don't\n\t\t// want to modify the value if it is a CSS custom property\n\t\t// since they are user-defined.\n\t\tif ( !isCustomProp ) {\n\t\t\tname = finalPropName( origName );\n\t\t}\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 || isFinite( num ) ? num || 0 : val;\n\t\t}\n\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\" ) ) &&\n\n\t\t\t\t\t// Support: Safari 8+\n\t\t\t\t\t// Table columns in Safari have non-zero offsetWidth & zero\n\t\t\t\t\t// getBoundingClientRect().width unless display is changed.\n\t\t\t\t\t// Support: IE <=11 only\n\t\t\t\t\t// Running getBoundingClientRect on a disconnected node\n\t\t\t\t\t// in IE throws an error.\n\t\t\t\t\t( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ?\n\t\t\t\t\t\tswap( elem, cssShow, function() {\n\t\t\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t\t\t} ) :\n\t\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 matches,\n\t\t\t\tstyles = extra && getStyles( elem ),\n\t\t\t\tsubtract = extra && augmentWidthOrHeight(\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);\n\n\t\t\t// Convert to pixels if value adjustment is needed\n\t\t\tif ( subtract && ( matches = rcssNum.exec( value ) ) &&\n\t\t\t\t( matches[ 3 ] || \"px\" ) !== \"px\" ) {\n\n\t\t\t\telem.style[ name ] = value;\n\t\t\t\tvalue = jQuery.css( elem, name );\n\t\t\t}\n\n\t\t\treturn setPositiveNumber( elem, value, subtract );\n\t\t}\n\t};\n} );\n\njQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft,\n\tfunction( elem, computed ) {\n\t\tif ( computed ) {\n\t\t\treturn ( parseFloat( curCSS( elem, \"marginLeft\" ) ) ||\n\t\t\t\telem.getBoundingClientRect().left -\n\t\t\t\t\tswap( elem, { marginLeft: 0 }, function() {\n\t\t\t\t\t\treturn elem.getBoundingClientRect().left;\n\t\t\t\t\t} )\n\t\t\t\t) + \"px\";\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 ( Array.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} );\n\n\n// Based off of the plugin by Clint Helfers, with permission.\n// https://web.archive.org/web/20100324014747/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 = window.setTimeout( next, time );\n\t\thooks.stop = function() {\n\t\t\twindow.clearTimeout( 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: Android <=4.3 only\n\t// Default value for a checkbox should be \"on\"\n\tsupport.checkOn = input.value !== \"\";\n\n\t// Support: IE <=11 only\n\t// Must access selectedIndex to make default options select\n\tsupport.optSelected = opt.selected;\n\n\t// Support: IE <=11 only\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 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 ret, hooks,\n\t\t\tnType = elem.nodeType;\n\n\t\t// Don't get/set attributes on text, comment and attribute nodes\n\t\tif ( 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 === \"undefined\" ) {\n\t\t\treturn jQuery.prop( elem, name, value );\n\t\t}\n\n\t\t// Attribute hooks are determined by the lowercase version\n\t\t// Grab necessary hook if one is defined\n\t\tif ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {\n\t\t\thooks = jQuery.attrHooks[ name.toLowerCase() ] ||\n\t\t\t\t( jQuery.expr.match.bool.test( name ) ? boolHook : undefined );\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\tif ( value === null ) {\n\t\t\t\tjQuery.removeAttr( elem, name );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( hooks && \"set\" in hooks &&\n\t\t\t\t( ret = hooks.set( elem, value, name ) ) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\telem.setAttribute( name, value + \"\" );\n\t\t\treturn value;\n\t\t}\n\n\t\tif ( hooks && \"get\" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {\n\t\t\treturn ret;\n\t\t}\n\n\t\tret = jQuery.find.attr( elem, name );\n\n\t\t// Non-existent attributes return null, we normalize to undefined\n\t\treturn ret == null ? undefined : ret;\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\tnodeName( 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\tremoveAttr: function( elem, value ) {\n\t\tvar name,\n\t\t\ti = 0,\n\n\t\t\t// Attribute names can contain non-HTML whitespace characters\n\t\t\t// https://html.spec.whatwg.org/multipage/syntax.html#attributes-2\n\t\t\tattrNames = value && value.match( rnothtmlwhite );\n\n\t\tif ( attrNames && elem.nodeType === 1 ) {\n\t\t\twhile ( ( name = attrNames[ i++ ] ) ) {\n\t\t\t\telem.removeAttribute( name );\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\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};\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\t\tlowercaseName = name.toLowerCase();\n\n\t\tif ( !isXML ) {\n\n\t\t\t// Avoid an infinite loop by temporarily removing this function from the getter\n\t\t\thandle = attrHandle[ lowercaseName ];\n\t\t\tattrHandle[ lowercaseName ] = ret;\n\t\t\tret = getter( elem, name, isXML ) != null ?\n\t\t\t\tlowercaseName :\n\t\t\t\tnull;\n\t\t\tattrHandle[ lowercaseName ] = handle;\n\t\t}\n\t\treturn ret;\n\t};\n} );\n\n\n\n\nvar rfocusable = /^(?:input|select|textarea|button)$/i,\n\trclickable = /^(?:a|area)$/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\tprop: function( elem, name, value ) {\n\t\tvar ret, hooks,\n\t\t\tnType = elem.nodeType;\n\n\t\t// Don't get/set properties on text, comment and attribute nodes\n\t\tif ( nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {\n\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 &&\n\t\t\t\t( ret = hooks.set( elem, value, name ) ) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\treturn ( elem[ name ] = value );\n\t\t}\n\n\t\tif ( hooks && \"get\" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {\n\t\t\treturn ret;\n\t\t}\n\n\t\treturn elem[ name ];\n\t},\n\n\tpropHooks: {\n\t\ttabIndex: {\n\t\t\tget: function( elem ) {\n\n\t\t\t\t// Support: IE <=9 - 11 only\n\t\t\t\t// elem.tabIndex doesn't always return the\n\t\t\t\t// correct value when it hasn't been explicitly set\n\t\t\t\t// https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/\n\t\t\t\t// Use proper attribute retrieval(#12072)\n\t\t\t\tvar tabindex = jQuery.find.attr( elem, \"tabindex\" );\n\n\t\t\t\tif ( tabindex ) {\n\t\t\t\t\treturn parseInt( tabindex, 10 );\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\trfocusable.test( elem.nodeName ) ||\n\t\t\t\t\trclickable.test( elem.nodeName ) &&\n\t\t\t\t\telem.href\n\t\t\t\t) {\n\t\t\t\t\treturn 0;\n\t\t\t\t}\n\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t}\n\t},\n\n\tpropFix: {\n\t\t\"for\": \"htmlFor\",\n\t\t\"class\": \"className\"\n\t}\n} );\n\n// Support: IE <=11 only\n// Accessing the selectedIndex property\n// forces the browser to respect setting selected\n// on the option\n// The getter ensures a default option is selected\n// when in an optgroup\n// eslint rule \"no-unused-expressions\" is disabled for this code\n// since it considers such accessions noop\nif ( !support.optSelected ) {\n\tjQuery.propHooks.selected = {\n\t\tget: function( elem ) {\n\n\t\t\t/* eslint no-unused-expressions: \"off\" */\n\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\tset: function( elem ) {\n\n\t\t\t/* eslint no-unused-expressions: \"off\" */\n\n\t\t\tvar parent = elem.parentNode;\n\t\t\tif ( parent ) {\n\t\t\t\tparent.selectedIndex;\n\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}\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\n\t// Strip and collapse whitespace according to HTML spec\n\t// https://html.spec.whatwg.org/multipage/infrastructure.html#strip-and-collapse-whitespace\n\tfunction stripAndCollapse( value ) {\n\t\tvar tokens = value.match( rnothtmlwhite ) || [];\n\t\treturn tokens.join( \" \" );\n\t}\n\n\nfunction getClass( elem ) {\n\treturn elem.getAttribute && elem.getAttribute( \"class\" ) || \"\";\n}\n\njQuery.fn.extend( {\n\taddClass: function( value ) {\n\t\tvar classes, elem, cur, curValue, clazz, j, finalValue,\n\t\t\ti = 0;\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, getClass( this ) ) );\n\t\t\t} );\n\t\t}\n\n\t\tif ( typeof value === \"string\" && value ) {\n\t\t\tclasses = value.match( rnothtmlwhite ) || [];\n\n\t\t\twhile ( ( elem = this[ i++ ] ) ) {\n\t\t\t\tcurValue = getClass( elem );\n\t\t\t\tcur = elem.nodeType === 1 && ( \" \" + stripAndCollapse( curValue ) + \" \" );\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 = stripAndCollapse( cur );\n\t\t\t\t\tif ( curValue !== finalValue ) {\n\t\t\t\t\t\telem.setAttribute( \"class\", 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, curValue, clazz, j, finalValue,\n\t\t\ti = 0;\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, getClass( this ) ) );\n\t\t\t} );\n\t\t}\n\n\t\tif ( !arguments.length ) {\n\t\t\treturn this.attr( \"class\", \"\" );\n\t\t}\n\n\t\tif ( typeof value === \"string\" && value ) {\n\t\t\tclasses = value.match( rnothtmlwhite ) || [];\n\n\t\t\twhile ( ( elem = this[ i++ ] ) ) {\n\t\t\t\tcurValue = getClass( elem );\n\n\t\t\t\t// This expression is here for better compressibility (see addClass)\n\t\t\t\tcur = elem.nodeType === 1 && ( \" \" + stripAndCollapse( curValue ) + \" \" );\n\n\t\t\t\tif ( cur ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( ( clazz = classes[ j++ ] ) ) {\n\n\t\t\t\t\t\t// Remove *all* instances\n\t\t\t\t\t\twhile ( cur.indexOf( \" \" + clazz + \" \" ) > -1 ) {\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 = stripAndCollapse( cur );\n\t\t\t\t\tif ( curValue !== finalValue ) {\n\t\t\t\t\t\telem.setAttribute( \"class\", 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(\n\t\t\t\t\tvalue.call( this, i, getClass( this ), stateVal ),\n\t\t\t\t\tstateVal\n\t\t\t\t);\n\t\t\t} );\n\t\t}\n\n\t\treturn this.each( function() {\n\t\t\tvar className, i, self, classNames;\n\n\t\t\tif ( type === \"string\" ) {\n\n\t\t\t\t// Toggle individual class names\n\t\t\t\ti = 0;\n\t\t\t\tself = jQuery( this );\n\t\t\t\tclassNames = value.match( rnothtmlwhite ) || [];\n\n\t\t\t\twhile ( ( className = classNames[ i++ ] ) ) {\n\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 ( value === undefined || type === \"boolean\" ) {\n\t\t\t\tclassName = getClass( this );\n\t\t\t\tif ( className ) {\n\n\t\t\t\t\t// Store className if set\n\t\t\t\t\tdataPriv.set( this, \"__className__\", 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\tif ( this.setAttribute ) {\n\t\t\t\t\tthis.setAttribute( \"class\",\n\t\t\t\t\t\tclassName || value === false ?\n\t\t\t\t\t\t\"\" :\n\t\t\t\t\t\tdataPriv.get( this, \"__className__\" ) || \"\"\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t},\n\n\thasClass: function( selector ) {\n\t\tvar className, elem,\n\t\t\ti = 0;\n\n\t\tclassName = \" \" + selector + \" \";\n\t\twhile ( ( elem = this[ i++ ] ) ) {\n\t\t\tif ( elem.nodeType === 1 &&\n\t\t\t\t( \" \" + stripAndCollapse( getClass( elem ) ) + \" \" ).indexOf( className ) > -1 ) {\n\t\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 ] ||\n\t\t\t\t\tjQuery.valHooks[ elem.nodeName.toLowerCase() ];\n\n\t\t\t\tif ( hooks &&\n\t\t\t\t\t\"get\" in hooks &&\n\t\t\t\t\t( ret = hooks.get( elem, \"value\" ) ) !== undefined\n\t\t\t\t) {\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\t// Handle most common string cases\n\t\t\t\tif ( typeof ret === \"string\" ) {\n\t\t\t\t\treturn ret.replace( rreturn, \"\" );\n\t\t\t\t}\n\n\t\t\t\t// Handle cases where value is null/undef or number\n\t\t\t\treturn ret == 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 ( Array.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\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\n\t\t\t\t\t// Support: IE <=10 - 11 only\n\t\t\t\t\t// option.text throws exceptions (#14686, #14858)\n\t\t\t\t\t// Strip and collapse whitespace\n\t\t\t\t\t// https://html.spec.whatwg.org/#strip-and-collapse-whitespace\n\t\t\t\t\tstripAndCollapse( 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, i,\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\",\n\t\t\t\t\tvalues = one ? null : [],\n\t\t\t\t\tmax = one ? index + 1 : options.length;\n\n\t\t\t\tif ( index < 0 ) {\n\t\t\t\t\ti = max;\n\n\t\t\t\t} else {\n\t\t\t\t\ti = one ? index : 0;\n\t\t\t\t}\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// Support: IE <=9 only\n\t\t\t\t\t// IE8-9 doesn't update selected after form reset (#2551)\n\t\t\t\t\tif ( ( option.selected || i === index ) &&\n\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!option.disabled &&\n\t\t\t\t\t\t\t( !option.parentNode.disabled ||\n\t\t\t\t\t\t\t\t!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\n\t\t\t\t\t/* eslint-disable no-cond-assign */\n\n\t\t\t\t\tif ( option.selected =\n\t\t\t\t\t\tjQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1\n\t\t\t\t\t) {\n\t\t\t\t\t\toptionSet = true;\n\t\t\t\t\t}\n\n\t\t\t\t\t/* eslint-enable no-cond-assign */\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 ( Array.isArray( value ) ) {\n\t\t\t\treturn ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 );\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\nvar rfocusMorph = /^(?:focusinfocus|focusoutblur)$/;\n\njQuery.extend( jQuery.event, {\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( \".\" ) > -1 ) {\n\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.rnamespace = 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 = ( dataPriv.get( cur, \"events\" ) || {} )[ event.type ] &&\n\t\t\t\tdataPriv.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 && 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 ||\n\t\t\t\tspecial._default.apply( eventPath.pop(), data ) === false ) &&\n\t\t\t\tacceptData( elem ) ) {\n\n\t\t\t\t// Call a native DOM method on the target with the same 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\t// Piggyback on a donor event to simulate a different one\n\t// Used only for `focus(in | out)` events\n\tsimulate: function( type, elem, event ) {\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}\n\t\t);\n\n\t\tjQuery.event.trigger( e, null, elem );\n\t}\n\n} );\n\njQuery.fn.extend( {\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\njQuery.each( ( \"blur focus focusin focusout resize scroll click dblclick \" +\n\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\"change select submit keydown keypress keyup contextmenu\" ).split( \" \" ),\n\tfunction( 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\n\n\n\nsupport.focusin = \"onfocusin\" in window;\n\n\n// Support: Firefox <=44\n// Firefox doesn't have focus(in | out) events\n// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787\n//\n// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1\n// focus(in | out) events fire after focus & blur events,\n// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order\n// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857\nif ( !support.focusin ) {\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\tjQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) );\n\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 = dataPriv.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\tdataPriv.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 = dataPriv.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\tdataPriv.remove( doc, fix );\n\n\t\t\t\t} else {\n\t\t\t\t\tdataPriv.access( doc, fix, attaches );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t} );\n}\n\n\nvar\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 ( Array.isArray( obj ) ) {\n\n\t\t// Serialize array item.\n\t\tjQuery.each( obj, function( i, v ) {\n\t\t\tif ( traditional || rbracket.test( prefix ) ) {\n\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\n\t\t\t\t// Item is non-scalar (array or object), encode its numeric index.\n\t\t\t\tbuildParams(\n\t\t\t\t\tprefix + \"[\" + ( typeof v === \"object\" && v != null ? i : \"\" ) + \"]\",\n\t\t\t\t\tv,\n\t\t\t\t\ttraditional,\n\t\t\t\t\tadd\n\t\t\t\t);\n\t\t\t}\n\t\t} );\n\n\t} else if ( !traditional && jQuery.type( obj ) === \"object\" ) {\n\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\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, valueOrFunction ) {\n\n\t\t\t// If value is a function, invoke it and use its return value\n\t\t\tvar value = jQuery.isFunction( valueOrFunction ) ?\n\t\t\t\tvalueOrFunction() :\n\t\t\t\tvalueOrFunction;\n\n\t\t\ts[ s.length ] = encodeURIComponent( key ) + \"=\" +\n\t\t\t\tencodeURIComponent( value == null ? \"\" : value );\n\t\t};\n\n\t// If an array was passed in, assume that it is an array of form elements.\n\tif ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n\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\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( \"&\" );\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\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\tif ( val == null ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tif ( Array.isArray( val ) ) {\n\t\t\t\treturn jQuery.map( val, function( val ) {\n\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t} ).get();\n\t}\n} );\n\n\njQuery.fn.extend( {\n\twrapAll: function( html ) {\n\t\tvar wrap;\n\n\t\tif ( this[ 0 ] ) {\n\t\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\t\thtml = html.call( this[ 0 ] );\n\t\t\t}\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( selector ) {\n\t\tthis.parent( selector ).not( \"body\" ).each( function() {\n\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t} );\n\t\treturn this;\n\t}\n} );\n\n\njQuery.expr.pseudos.hidden = function( elem ) {\n\treturn !jQuery.expr.pseudos.visible( elem );\n};\njQuery.expr.pseudos.visible = function( elem ) {\n\treturn !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length );\n};\n\n\n\n\n// Support: Safari 8 only\n// In Safari 8 documents created via document.implementation.createHTMLDocument\n// collapse sibling forms: the second one becomes a child of the first one.\n// Because of that, this security measure has to be disabled in Safari 8.\n// https://bugs.webkit.org/show_bug.cgi?id=137337\nsupport.createHTMLDocument = ( function() {\n\tvar body = document.implementation.createHTMLDocument( \"\" ).body;\n\tbody.innerHTML = \"<form></form><form></form>\";\n\treturn body.childNodes.length === 2;\n} )();\n\n\n// Argument \"data\" should be string of html\n// context (optional): If specified, the fragment will be created in this context,\n// defaults to document\n// keepScripts (optional): If true, will include scripts passed in the html string\njQuery.parseHTML = function( data, context, keepScripts ) {\n\tif ( typeof data !== \"string\" ) {\n\t\treturn [];\n\t}\n\tif ( typeof context === \"boolean\" ) {\n\t\tkeepScripts = context;\n\t\tcontext = false;\n\t}\n\n\tvar base, parsed, scripts;\n\n\tif ( !context ) {\n\n\t\t// Stop scripts or inline event handlers from being executed immediately\n\t\t// by using document.implementation\n\t\tif ( support.createHTMLDocument ) {\n\t\t\tcontext = document.implementation.createHTMLDocument( \"\" );\n\n\t\t\t// Set the base href for the created document\n\t\t\t// so any parsed elements with URLs\n\t\t\t// are based on the document's URL (gh-2965)\n\t\t\tbase = context.createElement( \"base\" );\n\t\t\tbase.href = document.location.href;\n\t\t\tcontext.head.appendChild( base );\n\t\t} else {\n\t\t\tcontext = document;\n\t\t}\n\t}\n\n\tparsed = rsingleTag.exec( data );\n\tscripts = !keepScripts && [];\n\n\t// Single tag\n\tif ( parsed ) {\n\t\treturn [ context.createElement( parsed[ 1 ] ) ];\n\t}\n\n\tparsed = 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\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\n\t\t\t// Use jQuery.extend here to allow modification of coordinates argument (gh-1848)\n\t\t\toptions = options.call( elem, i, jQuery.extend( {}, 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\n\t\t// Preserve chaining for setter\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 doc, docElem, rect, win,\n\t\t\telem = this[ 0 ];\n\n\t\tif ( !elem ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Return zeros for disconnected and hidden (display: none) elements (gh-2310)\n\t\t// Support: IE <=11 only\n\t\t// Running getBoundingClientRect on a\n\t\t// disconnected node in IE throws an error\n\t\tif ( !elem.getClientRects().length ) {\n\t\t\treturn { top: 0, left: 0 };\n\t\t}\n\n\t\trect = elem.getBoundingClientRect();\n\n\t\tdoc = elem.ownerDocument;\n\t\tdocElem = doc.documentElement;\n\t\twin = doc.defaultView;\n\n\t\treturn {\n\t\t\ttop: rect.top + win.pageYOffset - docElem.clientTop,\n\t\t\tleft: rect.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},\n\t\t// because it is its only offset parent\n\t\tif ( jQuery.css( elem, \"position\" ) === \"fixed\" ) {\n\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\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 ( !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 = {\n\t\t\t\ttop: parentOffset.top + jQuery.css( offsetParent[ 0 ], \"borderTopWidth\", true ),\n\t\t\t\tleft: parentOffset.left + jQuery.css( offsetParent[ 0 ], \"borderLeftWidth\", true )\n\t\t\t};\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\t// This method will return documentElement in the following cases:\n\t// 1) For the element inside the iframe without offsetParent, this method will return\n\t//    documentElement of the parent window\n\t// 2) For the hidden or detached element\n\t// 3) For body or html element, i.e. in case of the html node - it will return itself\n\t//\n\t// but those exceptions were never presented as a real life use-cases\n\t// and might be considered as more preferable results.\n\t//\n\t// This logic, however, is not guaranteed and can change at any point in the future\n\toffsetParent: function() {\n\t\treturn this.map( function() {\n\t\t\tvar offsetParent = this.offsetParent;\n\n\t\t\twhile ( offsetParent && jQuery.css( offsetParent, \"position\" ) === \"static\" ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\n\t\t\treturn offsetParent || documentElement;\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\n\t\t\t// Coalesce documents and windows\n\t\t\tvar win;\n\t\t\tif ( jQuery.isWindow( elem ) ) {\n\t\t\t\twin = elem;\n\t\t\t} else if ( elem.nodeType === 9 ) {\n\t\t\t\twin = elem.defaultView;\n\t\t\t}\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 : win.pageXOffset,\n\t\t\t\t\ttop ? val : win.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 );\n\t};\n} );\n\n// Support: Safari <=7 - 9.1, Chrome <=37 - 49\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://bugs.chromium.org/p/chromium/issues/detail?id=589347\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\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 },\n\t\tfunction( defaultExtra, funcName ) {\n\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\n\t\t\t\t\t// $( window ).outerWidth/Height return w/h including scrollbars (gh-1729)\n\t\t\t\t\treturn funcName.indexOf( \"outer\" ) === 0 ?\n\t\t\t\t\t\telem[ \"inner\" + name ] :\n\t\t\t\t\t\telem.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\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 );\n\t\t};\n\t} );\n} );\n\n\njQuery.fn.extend( {\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\n\t\t// ( namespace ) or ( selector, types [, fn] )\n\t\treturn arguments.length === 1 ?\n\t\t\tthis.off( selector, \"**\" ) :\n\t\t\tthis.off( types, selector || \"**\", fn );\n\t}\n} );\n\njQuery.holdReady = function( hold ) {\n\tif ( hold ) {\n\t\tjQuery.readyWait++;\n\t} else {\n\t\tjQuery.ready( true );\n\t}\n};\njQuery.isArray = Array.isArray;\njQuery.parseJSON = JSON.parse;\njQuery.nodeName = nodeName;\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\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 ( !noGlobal ) {\n\twindow.jQuery = window.$ = jQuery;\n}\n\n\n\n\nreturn jQuery;\n} );\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/layer/layer.js",
    "content": "/*! layer-v3.1.1 Web弹层组件 MIT License  http://layer.layui.com/  By 贤心 */\n ;!function(e,t){\"use strict\";var i,n,a=e.layui&&layui.define,o={getPath:function(){var e=document.currentScript?document.currentScript.src:function(){for(var e,t=document.scripts,i=t.length-1,n=i;n>0;n--)if(\"interactive\"===t[n].readyState){e=t[n].src;break}return e||t[i].src}();return e.substring(0,e.lastIndexOf(\"/\")+1)}(),config:{},end:{},minIndex:0,minLeft:[],btn:[\"&#x786E;&#x5B9A;\",\"&#x53D6;&#x6D88;\"],type:[\"dialog\",\"page\",\"iframe\",\"loading\",\"tips\"],getStyle:function(t,i){var n=t.currentStyle?t.currentStyle:e.getComputedStyle(t,null);return n[n.getPropertyValue?\"getPropertyValue\":\"getAttribute\"](i)},link:function(t,i,n){if(r.path){var a=document.getElementsByTagName(\"head\")[0],s=document.createElement(\"link\");\"string\"==typeof i&&(n=i);var l=(n||t).replace(/\\.|\\//g,\"\"),f=\"layuicss-\"+l,c=0;s.rel=\"stylesheet\",s.href=r.path+t,s.id=f,document.getElementById(f)||a.appendChild(s),\"function\"==typeof i&&!function u(){return++c>80?e.console&&console.error(\"layer.css: Invalid\"):void(1989===parseInt(o.getStyle(document.getElementById(f),\"width\"))?i():setTimeout(u,100))}()}}},r={v:\"3.1.1\",ie:function(){var t=navigator.userAgent.toLowerCase();return!!(e.ActiveXObject||\"ActiveXObject\"in e)&&((t.match(/msie\\s(\\d+)/)||[])[1]||\"11\")}(),index:e.layer&&e.layer.v?1e5:0,path:o.getPath,config:function(e,t){return e=e||{},r.cache=o.config=i.extend({},o.config,e),r.path=o.config.path||r.path,\"string\"==typeof e.extend&&(e.extend=[e.extend]),o.config.path&&r.ready(),e.extend?(a?layui.addcss(\"modules/layer/\"+e.extend):o.link(\"theme/\"+e.extend),this):this},ready:function(e){var t=\"layer\",i=\"\",n=(a?\"modules/layer/\":\"theme/\")+\"default/layer.css?v=\"+r.v+i;return a?layui.addcss(n,e,t):o.link(n,e,t),this},alert:function(e,t,n){var a=\"function\"==typeof t;return a&&(n=t),r.open(i.extend({content:e,yes:n},a?{}:t))},confirm:function(e,t,n,a){var s=\"function\"==typeof t;return s&&(a=n,n=t),r.open(i.extend({content:e,btn:o.btn,yes:n,btn2:a},s?{}:t))},msg:function(e,n,a){var s=\"function\"==typeof n,f=o.config.skin,c=(f?f+\" \"+f+\"-msg\":\"\")||\"layui-layer-msg\",u=l.anim.length-1;return s&&(a=n),r.open(i.extend({content:e,time:3e3,shade:!1,skin:c,title:!1,closeBtn:!1,btn:!1,resize:!1,end:a},s&&!o.config.skin?{skin:c+\" layui-layer-hui\",anim:u}:function(){return n=n||{},(n.icon===-1||n.icon===t&&!o.config.skin)&&(n.skin=c+\" \"+(n.skin||\"layui-layer-hui\")),n}()))},load:function(e,t){return r.open(i.extend({type:3,icon:e||0,resize:!1,shade:.01},t))},tips:function(e,t,n){return r.open(i.extend({type:4,content:[e,t],closeBtn:!1,time:3e3,shade:!1,resize:!1,fixed:!1,maxWidth:210},n))}},s=function(e){var t=this;t.index=++r.index,t.config=i.extend({},t.config,o.config,e),document.body?t.creat():setTimeout(function(){t.creat()},30)};s.pt=s.prototype;var l=[\"layui-layer\",\".layui-layer-title\",\".layui-layer-main\",\".layui-layer-dialog\",\"layui-layer-iframe\",\"layui-layer-content\",\"layui-layer-btn\",\"layui-layer-close\"];l.anim=[\"layer-anim-00\",\"layer-anim-01\",\"layer-anim-02\",\"layer-anim-03\",\"layer-anim-04\",\"layer-anim-05\",\"layer-anim-06\"],s.pt.config={type:0,shade:.3,fixed:!0,move:l[1],title:\"&#x4FE1;&#x606F;\",offset:\"auto\",area:\"auto\",closeBtn:1,time:0,zIndex:19891014,maxWidth:360,anim:0,isOutAnim:!0,icon:-1,moveType:1,resize:!0,scrollbar:!0,tips:2},s.pt.vessel=function(e,t){var n=this,a=n.index,r=n.config,s=r.zIndex+a,f=\"object\"==typeof r.title,c=r.maxmin&&(1===r.type||2===r.type),u=r.title?'<div class=\"layui-layer-title\" style=\"'+(f?r.title[1]:\"\")+'\">'+(f?r.title[0]:r.title)+\"</div>\":\"\";return r.zIndex=s,t([r.shade?'<div class=\"layui-layer-shade\" id=\"layui-layer-shade'+a+'\" times=\"'+a+'\" style=\"'+(\"z-index:\"+(s-1)+\"; \")+'\"></div>':\"\",'<div class=\"'+l[0]+(\" layui-layer-\"+o.type[r.type])+(0!=r.type&&2!=r.type||r.shade?\"\":\" layui-layer-border\")+\" \"+(r.skin||\"\")+'\" id=\"'+l[0]+a+'\" type=\"'+o.type[r.type]+'\" times=\"'+a+'\" showtime=\"'+r.time+'\" conType=\"'+(e?\"object\":\"string\")+'\" style=\"z-index: '+s+\"; width:\"+r.area[0]+\";height:\"+r.area[1]+(r.fixed?\"\":\";position:absolute;\")+'\">'+(e&&2!=r.type?\"\":u)+'<div id=\"'+(r.id||\"\")+'\" class=\"layui-layer-content'+(0==r.type&&r.icon!==-1?\" layui-layer-padding\":\"\")+(3==r.type?\" layui-layer-loading\"+r.icon:\"\")+'\">'+(0==r.type&&r.icon!==-1?'<i class=\"layui-layer-ico layui-layer-ico'+r.icon+'\"></i>':\"\")+(1==r.type&&e?\"\":r.content||\"\")+'</div><span class=\"layui-layer-setwin\">'+function(){var e=c?'<a class=\"layui-layer-min\" href=\"javascript:;\"><cite></cite></a><a class=\"layui-layer-ico layui-layer-max\" href=\"javascript:;\"></a>':\"\";return r.closeBtn&&(e+='<a class=\"layui-layer-ico '+l[7]+\" \"+l[7]+(r.title?r.closeBtn:4==r.type?\"1\":\"2\")+'\" href=\"javascript:;\"></a>'),e}()+\"</span>\"+(r.btn?function(){var e=\"\";\"string\"==typeof r.btn&&(r.btn=[r.btn]);for(var t=0,i=r.btn.length;t<i;t++)e+='<a class=\"'+l[6]+t+'\">'+r.btn[t]+\"</a>\";return'<div class=\"'+l[6]+\" layui-layer-btn-\"+(r.btnAlign||\"\")+'\">'+e+\"</div>\"}():\"\")+(r.resize?'<span class=\"layui-layer-resize\"></span>':\"\")+\"</div>\"],u,i('<div class=\"layui-layer-move\"></div>')),n},s.pt.creat=function(){var e=this,t=e.config,a=e.index,s=t.content,f=\"object\"==typeof s,c=i(\"body\");if(!t.id||!i(\"#\"+t.id)[0]){switch(\"string\"==typeof t.area&&(t.area=\"auto\"===t.area?[\"\",\"\"]:[t.area,\"\"]),t.shift&&(t.anim=t.shift),6==r.ie&&(t.fixed=!1),t.type){case 0:t.btn=\"btn\"in t?t.btn:o.btn[0],r.closeAll(\"dialog\");break;case 2:var s=t.content=f?t.content:[t.content||\"http://layer.layui.com\",\"auto\"];t.content='<iframe scrolling=\"'+(t.content[1]||\"auto\")+'\" allowtransparency=\"true\" id=\"'+l[4]+a+'\" name=\"'+l[4]+a+'\" onload=\"this.className=\\'\\';\" class=\"layui-layer-load\" frameborder=\"0\" src=\"'+t.content[0]+'\"></iframe>';break;case 3:delete t.title,delete t.closeBtn,t.icon===-1&&0===t.icon,r.closeAll(\"loading\");break;case 4:f||(t.content=[t.content,\"body\"]),t.follow=t.content[1],t.content=t.content[0]+'<i class=\"layui-layer-TipsG\"></i>',delete t.title,t.tips=\"object\"==typeof t.tips?t.tips:[t.tips,!0],t.tipsMore||r.closeAll(\"tips\")}if(e.vessel(f,function(n,r,u){c.append(n[0]),f?function(){2==t.type||4==t.type?function(){i(\"body\").append(n[1])}():function(){s.parents(\".\"+l[0])[0]||(s.data(\"display\",s.css(\"display\")).show().addClass(\"layui-layer-wrap\").wrap(n[1]),i(\"#\"+l[0]+a).find(\".\"+l[5]).before(r))}()}():c.append(n[1]),i(\".layui-layer-move\")[0]||c.append(o.moveElem=u),e.layero=i(\"#\"+l[0]+a),t.scrollbar||l.html.css(\"overflow\",\"hidden\").attr(\"layer-full\",a)}).auto(a),i(\"#layui-layer-shade\"+e.index).css({\"background-color\":t.shade[1]||\"#000\",opacity:t.shade[0]||t.shade}),2==t.type&&6==r.ie&&e.layero.find(\"iframe\").attr(\"src\",s[0]),4==t.type?e.tips():e.offset(),t.fixed&&n.on(\"resize\",function(){e.offset(),(/^\\d+%$/.test(t.area[0])||/^\\d+%$/.test(t.area[1]))&&e.auto(a),4==t.type&&e.tips()}),t.time<=0||setTimeout(function(){r.close(e.index)},t.time),e.move().callback(),l.anim[t.anim]){var u=\"layer-anim \"+l.anim[t.anim];e.layero.addClass(u).one(\"webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend\",function(){i(this).removeClass(u)})}t.isOutAnim&&e.layero.data(\"isOutAnim\",!0)}},s.pt.auto=function(e){var t=this,a=t.config,o=i(\"#\"+l[0]+e);\"\"===a.area[0]&&a.maxWidth>0&&(r.ie&&r.ie<8&&a.btn&&o.width(o.innerWidth()),o.outerWidth()>a.maxWidth&&o.width(a.maxWidth));var s=[o.innerWidth(),o.innerHeight()],f=o.find(l[1]).outerHeight()||0,c=o.find(\".\"+l[6]).outerHeight()||0,u=function(e){e=o.find(e),e.height(s[1]-f-c-2*(0|parseFloat(e.css(\"padding-top\"))))};switch(a.type){case 2:u(\"iframe\");break;default:\"\"===a.area[1]?a.maxHeight>0&&o.outerHeight()>a.maxHeight?(s[1]=a.maxHeight,u(\".\"+l[5])):a.fixed&&s[1]>=n.height()&&(s[1]=n.height(),u(\".\"+l[5])):u(\".\"+l[5])}return t},s.pt.offset=function(){var e=this,t=e.config,i=e.layero,a=[i.outerWidth(),i.outerHeight()],o=\"object\"==typeof t.offset;e.offsetTop=(n.height()-a[1])/2,e.offsetLeft=(n.width()-a[0])/2,o?(e.offsetTop=t.offset[0],e.offsetLeft=t.offset[1]||e.offsetLeft):\"auto\"!==t.offset&&(\"t\"===t.offset?e.offsetTop=0:\"r\"===t.offset?e.offsetLeft=n.width()-a[0]:\"b\"===t.offset?e.offsetTop=n.height()-a[1]:\"l\"===t.offset?e.offsetLeft=0:\"lt\"===t.offset?(e.offsetTop=0,e.offsetLeft=0):\"lb\"===t.offset?(e.offsetTop=n.height()-a[1],e.offsetLeft=0):\"rt\"===t.offset?(e.offsetTop=0,e.offsetLeft=n.width()-a[0]):\"rb\"===t.offset?(e.offsetTop=n.height()-a[1],e.offsetLeft=n.width()-a[0]):e.offsetTop=t.offset),t.fixed||(e.offsetTop=/%$/.test(e.offsetTop)?n.height()*parseFloat(e.offsetTop)/100:parseFloat(e.offsetTop),e.offsetLeft=/%$/.test(e.offsetLeft)?n.width()*parseFloat(e.offsetLeft)/100:parseFloat(e.offsetLeft),e.offsetTop+=n.scrollTop(),e.offsetLeft+=n.scrollLeft()),i.attr(\"minLeft\")&&(e.offsetTop=n.height()-(i.find(l[1]).outerHeight()||0),e.offsetLeft=i.css(\"left\")),i.css({top:e.offsetTop,left:e.offsetLeft})},s.pt.tips=function(){var e=this,t=e.config,a=e.layero,o=[a.outerWidth(),a.outerHeight()],r=i(t.follow);r[0]||(r=i(\"body\"));var s={width:r.outerWidth(),height:r.outerHeight(),top:r.offset().top,left:r.offset().left},f=a.find(\".layui-layer-TipsG\"),c=t.tips[0];t.tips[1]||f.remove(),s.autoLeft=function(){s.left+o[0]-n.width()>0?(s.tipLeft=s.left+s.width-o[0],f.css({right:12,left:\"auto\"})):s.tipLeft=s.left},s.where=[function(){s.autoLeft(),s.tipTop=s.top-o[1]-10,f.removeClass(\"layui-layer-TipsB\").addClass(\"layui-layer-TipsT\").css(\"border-right-color\",t.tips[1])},function(){s.tipLeft=s.left+s.width+10,s.tipTop=s.top,f.removeClass(\"layui-layer-TipsL\").addClass(\"layui-layer-TipsR\").css(\"border-bottom-color\",t.tips[1])},function(){s.autoLeft(),s.tipTop=s.top+s.height+10,f.removeClass(\"layui-layer-TipsT\").addClass(\"layui-layer-TipsB\").css(\"border-right-color\",t.tips[1])},function(){s.tipLeft=s.left-o[0]-10,s.tipTop=s.top,f.removeClass(\"layui-layer-TipsR\").addClass(\"layui-layer-TipsL\").css(\"border-bottom-color\",t.tips[1])}],s.where[c-1](),1===c?s.top-(n.scrollTop()+o[1]+16)<0&&s.where[2]():2===c?n.width()-(s.left+s.width+o[0]+16)>0||s.where[3]():3===c?s.top-n.scrollTop()+s.height+o[1]+16-n.height()>0&&s.where[0]():4===c&&o[0]+16-s.left>0&&s.where[1](),a.find(\".\"+l[5]).css({\"background-color\":t.tips[1],\"padding-right\":t.closeBtn?\"30px\":\"\"}),a.css({left:s.tipLeft-(t.fixed?n.scrollLeft():0),top:s.tipTop-(t.fixed?n.scrollTop():0)})},s.pt.move=function(){var e=this,t=e.config,a=i(document),s=e.layero,l=s.find(t.move),f=s.find(\".layui-layer-resize\"),c={};return t.move&&l.css(\"cursor\",\"move\"),l.on(\"mousedown\",function(e){e.preventDefault(),t.move&&(c.moveStart=!0,c.offset=[e.clientX-parseFloat(s.css(\"left\")),e.clientY-parseFloat(s.css(\"top\"))],o.moveElem.css(\"cursor\",\"move\").show())}),f.on(\"mousedown\",function(e){e.preventDefault(),c.resizeStart=!0,c.offset=[e.clientX,e.clientY],c.area=[s.outerWidth(),s.outerHeight()],o.moveElem.css(\"cursor\",\"se-resize\").show()}),a.on(\"mousemove\",function(i){if(c.moveStart){var a=i.clientX-c.offset[0],o=i.clientY-c.offset[1],l=\"fixed\"===s.css(\"position\");if(i.preventDefault(),c.stX=l?0:n.scrollLeft(),c.stY=l?0:n.scrollTop(),!t.moveOut){var f=n.width()-s.outerWidth()+c.stX,u=n.height()-s.outerHeight()+c.stY;a<c.stX&&(a=c.stX),a>f&&(a=f),o<c.stY&&(o=c.stY),o>u&&(o=u)}s.css({left:a,top:o})}if(t.resize&&c.resizeStart){var a=i.clientX-c.offset[0],o=i.clientY-c.offset[1];i.preventDefault(),r.style(e.index,{width:c.area[0]+a,height:c.area[1]+o}),c.isResize=!0,t.resizing&&t.resizing(s)}}).on(\"mouseup\",function(e){c.moveStart&&(delete c.moveStart,o.moveElem.hide(),t.moveEnd&&t.moveEnd(s)),c.resizeStart&&(delete c.resizeStart,o.moveElem.hide())}),e},s.pt.callback=function(){function e(){var e=a.cancel&&a.cancel(t.index,n);e===!1||r.close(t.index)}var t=this,n=t.layero,a=t.config;t.openLayer(),a.success&&(2==a.type?n.find(\"iframe\").on(\"load\",function(){a.success(n,t.index)}):a.success(n,t.index)),6==r.ie&&t.IE6(n),n.find(\".\"+l[6]).children(\"a\").on(\"click\",function(){var e=i(this).index();if(0===e)a.yes?a.yes(t.index,n):a.btn1?a.btn1(t.index,n):r.close(t.index);else{var o=a[\"btn\"+(e+1)]&&a[\"btn\"+(e+1)](t.index,n);o===!1||r.close(t.index)}}),n.find(\".\"+l[7]).on(\"click\",e),a.shadeClose&&i(\"#layui-layer-shade\"+t.index).on(\"click\",function(){r.close(t.index)}),n.find(\".layui-layer-min\").on(\"click\",function(){var e=a.min&&a.min(n);e===!1||r.min(t.index,a)}),n.find(\".layui-layer-max\").on(\"click\",function(){i(this).hasClass(\"layui-layer-maxmin\")?(r.restore(t.index),a.restore&&a.restore(n)):(r.full(t.index,a),setTimeout(function(){a.full&&a.full(n)},100))}),a.end&&(o.end[t.index]=a.end)},o.reselect=function(){i.each(i(\"select\"),function(e,t){var n=i(this);n.parents(\".\"+l[0])[0]||1==n.attr(\"layer\")&&i(\".\"+l[0]).length<1&&n.removeAttr(\"layer\").show(),n=null})},s.pt.IE6=function(e){i(\"select\").each(function(e,t){var n=i(this);n.parents(\".\"+l[0])[0]||\"none\"===n.css(\"display\")||n.attr({layer:\"1\"}).hide(),n=null})},s.pt.openLayer=function(){var e=this;r.zIndex=e.config.zIndex,r.setTop=function(e){var t=function(){r.zIndex++,e.css(\"z-index\",r.zIndex+1)};return r.zIndex=parseInt(e[0].style.zIndex),e.on(\"mousedown\",t),r.zIndex}},o.record=function(e){var t=[e.width(),e.height(),e.position().top,e.position().left+parseFloat(e.css(\"margin-left\"))];e.find(\".layui-layer-max\").addClass(\"layui-layer-maxmin\"),e.attr({area:t})},o.rescollbar=function(e){l.html.attr(\"layer-full\")==e&&(l.html[0].style.removeProperty?l.html[0].style.removeProperty(\"overflow\"):l.html[0].style.removeAttribute(\"overflow\"),l.html.removeAttr(\"layer-full\"))},e.layer=r,r.getChildFrame=function(e,t){return t=t||i(\".\"+l[4]).attr(\"times\"),i(\"#\"+l[0]+t).find(\"iframe\").contents().find(e)},r.getFrameIndex=function(e){return i(\"#\"+e).parents(\".\"+l[4]).attr(\"times\")},r.iframeAuto=function(e){if(e){var t=r.getChildFrame(\"html\",e).outerHeight(),n=i(\"#\"+l[0]+e),a=n.find(l[1]).outerHeight()||0,o=n.find(\".\"+l[6]).outerHeight()||0;n.css({height:t+a+o}),n.find(\"iframe\").css({height:t})}},r.iframeSrc=function(e,t){i(\"#\"+l[0]+e).find(\"iframe\").attr(\"src\",t)},r.style=function(e,t,n){var a=i(\"#\"+l[0]+e),r=a.find(\".layui-layer-content\"),s=a.attr(\"type\"),f=a.find(l[1]).outerHeight()||0,c=a.find(\".\"+l[6]).outerHeight()||0;a.attr(\"minLeft\");s!==o.type[3]&&s!==o.type[4]&&(n||(parseFloat(t.width)<=260&&(t.width=260),parseFloat(t.height)-f-c<=64&&(t.height=64+f+c)),a.css(t),c=a.find(\".\"+l[6]).outerHeight(),s===o.type[2]?a.find(\"iframe\").css({height:parseFloat(t.height)-f-c}):r.css({height:parseFloat(t.height)-f-c-parseFloat(r.css(\"padding-top\"))-parseFloat(r.css(\"padding-bottom\"))}))},r.min=function(e,t){var a=i(\"#\"+l[0]+e),s=a.find(l[1]).outerHeight()||0,f=a.attr(\"minLeft\")||181*o.minIndex+\"px\",c=a.css(\"position\");o.record(a),o.minLeft[0]&&(f=o.minLeft[0],o.minLeft.shift()),a.attr(\"position\",c),r.style(e,{width:180,height:s,left:f,top:n.height()-s,position:\"fixed\",overflow:\"hidden\"},!0),a.find(\".layui-layer-min\").hide(),\"page\"===a.attr(\"type\")&&a.find(l[4]).hide(),o.rescollbar(e),a.attr(\"minLeft\")||o.minIndex++,a.attr(\"minLeft\",f)},r.restore=function(e){var t=i(\"#\"+l[0]+e),n=t.attr(\"area\").split(\",\");t.attr(\"type\");r.style(e,{width:parseFloat(n[0]),height:parseFloat(n[1]),top:parseFloat(n[2]),left:parseFloat(n[3]),position:t.attr(\"position\"),overflow:\"visible\"},!0),t.find(\".layui-layer-max\").removeClass(\"layui-layer-maxmin\"),t.find(\".layui-layer-min\").show(),\"page\"===t.attr(\"type\")&&t.find(l[4]).show(),o.rescollbar(e)},r.full=function(e){var t,a=i(\"#\"+l[0]+e);o.record(a),l.html.attr(\"layer-full\")||l.html.css(\"overflow\",\"hidden\").attr(\"layer-full\",e),clearTimeout(t),t=setTimeout(function(){var t=\"fixed\"===a.css(\"position\");r.style(e,{top:t?0:n.scrollTop(),left:t?0:n.scrollLeft(),width:n.width(),height:n.height()},!0),a.find(\".layui-layer-min\").hide()},100)},r.title=function(e,t){var n=i(\"#\"+l[0]+(t||r.index)).find(l[1]);n.html(e)},r.close=function(e){var t=i(\"#\"+l[0]+e),n=t.attr(\"type\"),a=\"layer-anim-close\";if(t[0]){var s=\"layui-layer-wrap\",f=function(){if(n===o.type[1]&&\"object\"===t.attr(\"conType\")){t.children(\":not(.\"+l[5]+\")\").remove();for(var a=t.find(\".\"+s),r=0;r<2;r++)a.unwrap();a.css(\"display\",a.data(\"display\")).removeClass(s)}else{if(n===o.type[2])try{var f=i(\"#\"+l[4]+e)[0];f.contentWindow.document.write(\"\"),f.contentWindow.close(),t.find(\".\"+l[5])[0].removeChild(f)}catch(c){}t[0].innerHTML=\"\",t.remove()}\"function\"==typeof o.end[e]&&o.end[e](),delete o.end[e]};t.data(\"isOutAnim\")&&t.addClass(\"layer-anim \"+a),i(\"#layui-layer-moves, #layui-layer-shade\"+e).remove(),6==r.ie&&o.reselect(),o.rescollbar(e),t.attr(\"minLeft\")&&(o.minIndex--,o.minLeft.push(t.attr(\"minLeft\"))),r.ie&&r.ie<10||!t.data(\"isOutAnim\")?f():setTimeout(function(){f()},200)}},r.closeAll=function(e){i.each(i(\".\"+l[0]),function(){var t=i(this),n=e?t.attr(\"type\")===e:1;n&&r.close(t.attr(\"times\")),n=null})};var f=r.cache||{},c=function(e){return f.skin?\" \"+f.skin+\" \"+f.skin+\"-\"+e:\"\"};r.prompt=function(e,t){var a=\"\";if(e=e||{},\"function\"==typeof e&&(t=e),e.area){var o=e.area;a='style=\"width: '+o[0]+\"; height: \"+o[1]+';\"',delete e.area}var s,l=2==e.formType?'<textarea class=\"layui-layer-input\"'+a+\">\"+(e.value||\"\")+\"</textarea>\":function(){return'<input type=\"'+(1==e.formType?\"password\":\"text\")+'\" class=\"layui-layer-input\" value=\"'+(e.value||\"\")+'\">'}(),f=e.success;return delete e.success,r.open(i.extend({type:1,btn:[\"&#x786E;&#x5B9A;\",\"&#x53D6;&#x6D88;\"],content:l,skin:\"layui-layer-prompt\"+c(\"prompt\"),maxWidth:n.width(),success:function(e){s=e.find(\".layui-layer-input\"),s.focus(),\"function\"==typeof f&&f(e)},resize:!1,yes:function(i){var n=s.val();\"\"===n?s.focus():n.length>(e.maxlength||500)?r.tips(\"&#x6700;&#x591A;&#x8F93;&#x5165;\"+(e.maxlength||500)+\"&#x4E2A;&#x5B57;&#x6570;\",s,{tips:1}):t&&t(n,i,s)}},e))},r.tab=function(e){e=e||{};var t=e.tab||{},n=\"layui-this\",a=e.success;return delete e.success,r.open(i.extend({type:1,skin:\"layui-layer-tab\"+c(\"tab\"),resize:!1,title:function(){var e=t.length,i=1,a=\"\";if(e>0)for(a='<span class=\"'+n+'\">'+t[0].title+\"</span>\";i<e;i++)a+=\"<span>\"+t[i].title+\"</span>\";return a}(),content:'<ul class=\"layui-layer-tabmain\">'+function(){var e=t.length,i=1,a=\"\";if(e>0)for(a='<li class=\"layui-layer-tabli '+n+'\">'+(t[0].content||\"no content\")+\"</li>\";i<e;i++)a+='<li class=\"layui-layer-tabli\">'+(t[i].content||\"no  content\")+\"</li>\";return a}()+\"</ul>\",success:function(t){var o=t.find(\".layui-layer-title\").children(),r=t.find(\".layui-layer-tabmain\").children();o.on(\"mousedown\",function(t){t.stopPropagation?t.stopPropagation():t.cancelBubble=!0;var a=i(this),o=a.index();a.addClass(n).siblings().removeClass(n),r.eq(o).show().siblings().hide(),\"function\"==typeof e.change&&e.change(o)}),\"function\"==typeof a&&a(t)}},e))},r.photos=function(t,n,a){function o(e,t,i){var n=new Image;return n.src=e,n.complete?t(n):(n.onload=function(){n.onload=null,t(n)},void(n.onerror=function(e){n.onerror=null,i(e)}))}var s={};if(t=t||{},t.photos){var l=t.photos.constructor===Object,f=l?t.photos:{},u=f.data||[],d=f.start||0;s.imgIndex=(0|d)+1,t.img=t.img||\"img\";var y=t.success;if(delete t.success,l){if(0===u.length)return r.msg(\"&#x6CA1;&#x6709;&#x56FE;&#x7247;\")}else{var p=i(t.photos),h=function(){u=[],p.find(t.img).each(function(e){var t=i(this);t.attr(\"layer-index\",e),u.push({alt:t.attr(\"alt\"),pid:t.attr(\"layer-pid\"),src:t.attr(\"layer-src\")||t.attr(\"src\"),thumb:t.attr(\"src\")})})};if(h(),0===u.length)return;if(n||p.on(\"click\",t.img,function(){var e=i(this),n=e.attr(\"layer-index\");r.photos(i.extend(t,{photos:{start:n,data:u,tab:t.tab},full:t.full}),!0),h()}),!n)return}s.imgprev=function(e){s.imgIndex--,s.imgIndex<1&&(s.imgIndex=u.length),s.tabimg(e)},s.imgnext=function(e,t){s.imgIndex++,s.imgIndex>u.length&&(s.imgIndex=1,t)||s.tabimg(e)},s.keyup=function(e){if(!s.end){var t=e.keyCode;e.preventDefault(),37===t?s.imgprev(!0):39===t?s.imgnext(!0):27===t&&r.close(s.index)}},s.tabimg=function(e){if(!(u.length<=1))return f.start=s.imgIndex-1,r.close(s.index),r.photos(t,!0,e)},s.event=function(){s.bigimg.hover(function(){s.imgsee.show()},function(){s.imgsee.hide()}),s.bigimg.find(\".layui-layer-imgprev\").on(\"click\",function(e){e.preventDefault(),s.imgprev()}),s.bigimg.find(\".layui-layer-imgnext\").on(\"click\",function(e){e.preventDefault(),s.imgnext()}),i(document).on(\"keyup\",s.keyup)},s.loadi=r.load(1,{shade:!(\"shade\"in t)&&.9,scrollbar:!1}),o(u[d].src,function(n){r.close(s.loadi),s.index=r.open(i.extend({type:1,id:\"layui-layer-photos\",area:function(){var a=[n.width,n.height],o=[i(e).width()-100,i(e).height()-100];if(!t.full&&(a[0]>o[0]||a[1]>o[1])){var r=[a[0]/o[0],a[1]/o[1]];r[0]>r[1]?(a[0]=a[0]/r[0],a[1]=a[1]/r[0]):r[0]<r[1]&&(a[0]=a[0]/r[1],a[1]=a[1]/r[1])}return[a[0]+\"px\",a[1]+\"px\"]}(),title:!1,shade:.9,shadeClose:!0,closeBtn:!1,move:\".layui-layer-phimg img\",moveType:1,scrollbar:!1,moveOut:!0,isOutAnim:!1,skin:\"layui-layer-photos\"+c(\"photos\"),content:'<div class=\"layui-layer-phimg\"><img src=\"'+u[d].src+'\" alt=\"'+(u[d].alt||\"\")+'\" layer-pid=\"'+u[d].pid+'\"><div class=\"layui-layer-imgsee\">'+(u.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:'+(a?\"block\":\"\")+'\"><span class=\"layui-layer-imgtit\"><a href=\"javascript:;\">'+(u[d].alt||\"\")+\"</a><em>\"+s.imgIndex+\"/\"+u.length+\"</em></span></div></div></div>\",success:function(e,i){s.bigimg=e.find(\".layui-layer-phimg\"),s.imgsee=e.find(\".layui-layer-imguide,.layui-layer-imgbar\"),s.event(e),t.tab&&t.tab(u[d],e),\"function\"==typeof y&&y(e)},end:function(){s.end=!0,i(document).off(\"keyup\",s.keyup)}},t))},function(){r.close(s.loadi),r.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(){u.length>1&&s.imgnext(!0,!0)}})})}},o.run=function(t){i=t,n=i(e),l.html=i(\"html\"),r.open=function(e){var t=new s(e);return t.index}},e.layui&&layui.define?(r.ready(),layui.define(\"jquery\",function(t){r.path=layui.cache.dir,o.run(layui.$),e.layer=r,t(\"layer\",r)})):\"function\"==typeof define&&define.amd?define([\"jquery\"],function(){return o.run(e.jQuery),r}):function(){o.run(e.jQuery),r.ready()}()}(window);"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/layer/mobile/layer.js",
    "content": "/*! layer mobile-v2.0.0 Web弹层组件 MIT License  http://layer.layui.com/mobile  By 贤心 */\n ;!function(e){\"use strict\";var t=document,n=\"querySelectorAll\",i=\"getElementsByClassName\",a=function(e){return t[n](e)},s={type:0,shade:!0,shadeClose:!0,fixed:!0,anim:\"scale\"},l={extend:function(e){var t=JSON.parse(JSON.stringify(s));for(var n in e)t[n]=e[n];return t},timer:{},end:{}};l.touch=function(e,t){e.addEventListener(\"click\",function(e){t.call(this,e)},!1)};var r=0,o=[\"layui-m-layer\"],c=function(e){var t=this;t.config=l.extend(e),t.view()};c.prototype.view=function(){var e=this,n=e.config,s=t.createElement(\"div\");e.id=s.id=o[0]+r,s.setAttribute(\"class\",o[0]+\" \"+o[0]+(n.type||0)),s.setAttribute(\"index\",r);var l=function(){var e=\"object\"==typeof n.title;return n.title?'<h3 style=\"'+(e?n.title[1]:\"\")+'\">'+(e?n.title[0]:n.title)+\"</h3>\":\"\"}(),c=function(){\"string\"==typeof n.btn&&(n.btn=[n.btn]);var e,t=(n.btn||[]).length;return 0!==t&&n.btn?(e='<span yes type=\"1\">'+n.btn[0]+\"</span>\",2===t&&(e='<span no type=\"0\">'+n.btn[1]+\"</span>\"+e),'<div class=\"layui-m-layerbtn\">'+e+\"</div>\"):\"\"}();if(n.fixed||(n.top=n.hasOwnProperty(\"top\")?n.top:100,n.style=n.style||\"\",n.style+=\" top:\"+(t.body.scrollTop+n.top)+\"px\"),2===n.type&&(n.content='<i></i><i class=\"layui-m-layerload\"></i><i></i><p>'+(n.content||\"\")+\"</p>\"),n.skin&&(n.anim=\"up\"),\"msg\"===n.skin&&(n.shade=!1),s.innerHTML=(n.shade?\"<div \"+(\"string\"==typeof n.shade?'style=\"'+n.shade+'\"':\"\")+' class=\"layui-m-layershade\"></div>':\"\")+'<div class=\"layui-m-layermain\" '+(n.fixed?\"\":'style=\"position:static;\"')+'><div class=\"layui-m-layersection\"><div class=\"layui-m-layerchild '+(n.skin?\"layui-m-layer-\"+n.skin+\" \":\"\")+(n.className?n.className:\"\")+\" \"+(n.anim?\"layui-m-anim-\"+n.anim:\"\")+'\" '+(n.style?'style=\"'+n.style+'\"':\"\")+\">\"+l+'<div class=\"layui-m-layercont\">'+n.content+\"</div>\"+c+\"</div></div></div>\",!n.type||2===n.type){var d=t[i](o[0]+n.type),y=d.length;y>=1&&layer.close(d[0].getAttribute(\"index\"))}document.body.appendChild(s);var u=e.elem=a(\"#\"+e.id)[0];n.success&&n.success(u),e.index=r++,e.action(n,u)},c.prototype.action=function(e,t){var n=this;e.time&&(l.timer[n.index]=setTimeout(function(){layer.close(n.index)},1e3*e.time));var a=function(){var t=this.getAttribute(\"type\");0==t?(e.no&&e.no(),layer.close(n.index)):e.yes?e.yes(n.index):layer.close(n.index)};if(e.btn)for(var s=t[i](\"layui-m-layerbtn\")[0].children,r=s.length,o=0;o<r;o++)l.touch(s[o],a);if(e.shade&&e.shadeClose){var c=t[i](\"layui-m-layershade\")[0];l.touch(c,function(){layer.close(n.index,e.end)})}e.end&&(l.end[n.index]=e.end)},e.layer={v:\"2.0\",index:r,open:function(e){var t=new c(e||{});return t.index},close:function(e){var n=a(\"#\"+o[0]+e)[0];n&&(n.innerHTML=\"\",t.body.removeChild(n),clearTimeout(l.timer[e]),delete l.timer[e],\"function\"==typeof l.end[e]&&l.end[e](),delete l.end[e])},closeAll:function(){for(var e=t[i](o[0]),n=0,a=e.length;n<a;n++)layer.close(0|e[0].getAttribute(\"index\"))}},\"function\"==typeof define?define(function(){return layer}):function(){var e=document.scripts,n=e[e.length-1],i=n.src,a=i.substring(0,i.lastIndexOf(\"/\")+1);n.getAttribute(\"merge\")||document.head.appendChild(function(){var e=t.createElement(\"link\");return e.href=a+\"need/layer.css?2.0\",e.type=\"text/css\",e.rel=\"styleSheet\",e.id=\"layermcss\",e}())}()}(window);"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/layer/mobile/need/layer.css",
    "content": ".layui-m-layer{position:relative;z-index:19891014}.layui-m-layer *{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.layui-m-layermain,.layui-m-layershade{position:fixed;left:0;top:0;width:100%;height:100%}.layui-m-layershade{background-color:rgba(0,0,0,.7);pointer-events:auto}.layui-m-layermain{display:table;font-family:Helvetica,arial,sans-serif;pointer-events:none}.layui-m-layermain .layui-m-layersection{display:table-cell;vertical-align:middle;text-align:center}.layui-m-layerchild{position:relative;display:inline-block;text-align:left;background-color:#fff;font-size:14px;border-radius:5px;box-shadow:0 0 8px rgba(0,0,0,.1);pointer-events:auto;-webkit-overflow-scrolling:touch;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:.2s;animation-duration:.2s}@-webkit-keyframes layui-m-anim-scale{0%{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}@keyframes layui-m-anim-scale{0%{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}.layui-m-anim-scale{animation-name:layui-m-anim-scale;-webkit-animation-name:layui-m-anim-scale}@-webkit-keyframes layui-m-anim-up{0%{opacity:0;-webkit-transform:translateY(800px);transform:translateY(800px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes layui-m-anim-up{0%{opacity:0;-webkit-transform:translateY(800px);transform:translateY(800px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}.layui-m-anim-up{-webkit-animation-name:layui-m-anim-up;animation-name:layui-m-anim-up}.layui-m-layer0 .layui-m-layerchild{width:90%;max-width:640px}.layui-m-layer1 .layui-m-layerchild{border:none;border-radius:0}.layui-m-layer2 .layui-m-layerchild{width:auto;max-width:260px;min-width:40px;border:none;background:0 0;box-shadow:none;color:#fff}.layui-m-layerchild h3{padding:0 10px;height:60px;line-height:60px;font-size:16px;font-weight:400;border-radius:5px 5px 0 0;text-align:center}.layui-m-layerbtn span,.layui-m-layerchild h3{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-m-layercont{padding:50px 30px;line-height:22px;text-align:center}.layui-m-layer1 .layui-m-layercont{padding:0;text-align:left}.layui-m-layer2 .layui-m-layercont{text-align:center;padding:0;line-height:0}.layui-m-layer2 .layui-m-layercont i{width:25px;height:25px;margin-left:8px;display:inline-block;background-color:#fff;border-radius:100%;-webkit-animation:layui-m-anim-loading 1.4s infinite ease-in-out;animation:layui-m-anim-loading 1.4s infinite ease-in-out;-webkit-animation-fill-mode:both;animation-fill-mode:both}.layui-m-layerbtn,.layui-m-layerbtn span{position:relative;text-align:center;border-radius:0 0 5px 5px}.layui-m-layer2 .layui-m-layercont p{margin-top:20px}@-webkit-keyframes layui-m-anim-loading{0%,100%,80%{transform:scale(0);-webkit-transform:scale(0)}40%{transform:scale(1);-webkit-transform:scale(1)}}@keyframes layui-m-anim-loading{0%,100%,80%{transform:scale(0);-webkit-transform:scale(0)}40%{transform:scale(1);-webkit-transform:scale(1)}}.layui-m-layer2 .layui-m-layercont i:first-child{margin-left:0;-webkit-animation-delay:-.32s;animation-delay:-.32s}.layui-m-layer2 .layui-m-layercont i.layui-m-layerload{-webkit-animation-delay:-.16s;animation-delay:-.16s}.layui-m-layer2 .layui-m-layercont>div{line-height:22px;padding-top:7px;margin-bottom:20px;font-size:14px}.layui-m-layerbtn{display:box;display:-moz-box;display:-webkit-box;width:100%;height:50px;line-height:50px;font-size:0;border-top:1px solid #D0D0D0;background-color:#F2F2F2}.layui-m-layerbtn span{display:block;-moz-box-flex:1;box-flex:1;-webkit-box-flex:1;font-size:14px;cursor:pointer}.layui-m-layerbtn span[yes]{color:#40AFFE}.layui-m-layerbtn span[no]{border-right:1px solid #D0D0D0;border-radius:0 0 0 5px}.layui-m-layerbtn span:active{background-color:#F6F6F6}.layui-m-layerend{position:absolute;right:7px;top:10px;width:30px;height:30px;border:0;font-weight:400;background:0 0;cursor:pointer;-webkit-appearance:none;font-size:30px}.layui-m-layerend::after,.layui-m-layerend::before{position:absolute;left:5px;top:15px;content:'';width:18px;height:1px;background-color:#999;transform:rotate(45deg);-webkit-transform:rotate(45deg);border-radius:3px}.layui-m-layerend::after{transform:rotate(-45deg);-webkit-transform:rotate(-45deg)}body .layui-m-layer .layui-m-layer-footer{position:fixed;width:95%;max-width:100%;margin:0 auto;left:0;right:0;bottom:10px;background:0 0}.layui-m-layer-footer .layui-m-layercont{padding:20px;border-radius:5px 5px 0 0;background-color:rgba(255,255,255,.8)}.layui-m-layer-footer .layui-m-layerbtn{display:block;height:auto;background:0 0;border-top:none}.layui-m-layer-footer .layui-m-layerbtn span{background-color:rgba(255,255,255,.8)}.layui-m-layer-footer .layui-m-layerbtn span[no]{color:#FD482C;border-top:1px solid #c2c2c2;border-radius:0 0 5px 5px}.layui-m-layer-footer .layui-m-layerbtn span[yes]{margin-top:10px;border-radius:5px}body .layui-m-layer .layui-m-layer-msg{width:auto;max-width:90%;margin:0 auto;bottom:-150px;background-color:rgba(0,0,0,.7);color:#fff}.layui-m-layer-msg .layui-m-layercont{padding:10px 20px}"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/layer/theme/default/layer.css",
    "content": ".layui-layer-imgbar,.layui-layer-imgtit a,.layui-layer-tab .layui-layer-title span,.layui-layer-title{text-overflow:ellipsis;white-space:nowrap}html #layuicss-layer{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;border-radius:2px;box-shadow:1px 1px 50px rgba(0,0,0,.3)}.layui-layer-close{position:absolute}.layui-layer-content{position:relative}.layui-layer-border{border:1px solid #B2B2B2;border:1px solid rgba(0,0,0,.1);box-shadow:1px 1px 5px rgba(0,0,0,.2)}.layui-layer-load{background:url(loading-1.gif) center center no-repeat #eee}.layui-layer-ico{background:url(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}.layui-layer-move{display:none;position:fixed;*position:absolute;left:0;top:0;width:100%;height:100%;cursor:move;opacity:0;filter:alpha(opacity=0);background-color:#fff;z-index:2147483647}.layui-layer-resize{position:absolute;width:15px;height:15px;right:0;bottom:0;cursor:se-resize}.layer-anim{-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:.3s;animation-duration:.3s}@-webkit-keyframes layer-bounceIn{0%{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}@keyframes layer-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-00{-webkit-animation-name:layer-bounceIn;animation-name:layer-bounceIn}@-webkit-keyframes layer-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 layer-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:layer-zoomInDown;animation-name:layer-zoomInDown}@-webkit-keyframes layer-fadeInUpBig{0%{opacity:0;-webkit-transform:translateY(2000px);transform:translateY(2000px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes layer-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:layer-fadeInUpBig;animation-name:layer-fadeInUpBig}@-webkit-keyframes layer-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 layer-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:layer-zoomInLeft;animation-name:layer-zoomInLeft}@-webkit-keyframes layer-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 layer-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:layer-rollIn;animation-name:layer-rollIn}@keyframes layer-fadeIn{0%{opacity:0}100%{opacity:1}}.layer-anim-05{-webkit-animation-name:layer-fadeIn;animation-name:layer-fadeIn}@-webkit-keyframes layer-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 layer-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:layer-shake;animation-name:layer-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:1px -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 15px 12px;pointer-events:auto;user-select:none;-webkit-user-select:none}.layui-layer-btn a{height:28px;line-height:28px;margin:5px 5px 0;padding:0 15px;border:1px solid #dedede;background-color:#fff;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:.8}.layui-layer-btn .layui-layer-btn0{border-color:#1E9FFF;background-color:#1E9FFF;color:#fff}.layui-layer-btn-l{text-align:left}.layui-layer-btn-c{text-align:center}.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 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(loading-0.gif) no-repeat}.layui-layer-loading .layui-layer-loading1{width:37px;height:37px;background:url(loading-1.gif) no-repeat}.layui-layer-ico16,.layui-layer-loading .layui-layer-loading2{width:32px;height:32px;background:url(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:8px 15px;font-size:12px;_float:left;border-radius:2px;box-shadow:1px 1px 3px rgba(0,0,0,.2);background-color:#000;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:#000}.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:5px;border-bottom-style:solid;border-bottom-color:#000}.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:5px 10px 10px;text-align:right;border-top:1px solid #E9E7E7}.layui-layer-lan .layui-layer-btn a{background:#fff;border-color:#E9E7E7;color:#333}.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;border-color:#009f95}.layui-layer-molv .layui-layer-btn .layui-layer-btn1{background:#92B8B1}.layui-layer-iconext{background:url(icon-ext.png) no-repeat}.layui-layer-prompt .layui-layer-input{display:block;width:230px;height:36px;margin:0 auto;line-height:30px;padding-left:10px;border:1px solid #e6e6e6;color:#333}.layui-layer-prompt textarea.layui-layer-input{width:300px;height:100px;line-height:20px;padding:6px 10px}.layui-layer-prompt .layui-layer-content{padding:20px}.layui-layer-prompt .layui-layer-btn{padding-top:0}.layui-layer-tab{box-shadow:1px 1px 50px rgba(0,0,0,.4)}.layui-layer-tab .layui-layer-title{padding-left:0;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;overflow:hidden;cursor:pointer}.layui-layer-tab .layui-layer-title span.layui-this{height:43px;border-left:1px solid #eee;border-right:1px solid #eee;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.layui-this{display:block}.layui-layer-photos{-webkit-animation-duration:.8s;animation-duration:.8s}.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}@-webkit-keyframes layer-bounceOut{100%{opacity:0;-webkit-transform:scale(.7);transform:scale(.7)}30%{-webkit-transform:scale(1.05);transform:scale(1.05)}0%{-webkit-transform:scale(1);transform:scale(1)}}@keyframes layer-bounceOut{100%{opacity:0;-webkit-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}30%{-webkit-transform:scale(1.05);-ms-transform:scale(1.05);transform:scale(1.05)}0%{-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}.layer-anim-close{-webkit-animation-name:layer-bounceOut;animation-name:layer-bounceOut;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:.2s;animation-duration:.2s}@media screen and (max-width:1100px){.layui-layer-iframe{overflow-y:auto;-webkit-overflow-scrolling:touch}}"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/layui/css/global.css",
    "content": "/* 布局 */\n.site-inline{font-size: 0;}\n.site-tree, .site-content{display: inline-block;  *display:inline; *zoom:1; vertical-align: top; font-size: 14px;}\n.site-tree{width: 220px; min-height: 900px; padding: 5px 0 20px;}\n.site-content{width: 899px; min-height: 900px; padding: 20px 0 10px 20px;}\n\n/* 头部 */admin-side-toggle\n.header{height: 65px; border-bottom: 1px solid #404553;  background-color: #393D49; color: #fff;}\n.logo{position: absolute; left: 0; top: 18px;}\n.logo img{width: 82px; height: 31px;}\n\n.header .layui-nav{position: absolute; right: 0; top: 0; padding: 0; background: none;}\n.header .layui-nav .layui-nav-item{margin: 0 20px; line-height: 66px;}\n\n.menu{position: absolute; right: 0; top: 0; line-height: 65px;}\n.menu a{display:inline-block; *display:inline; *zoom:1; vertical-align:top;}\n.menu a{position: relative; padding: 0 20px; margin: 0 20px; color: #c2c2c2; font-size: 14px;}\n.menu a:hover{color: #fff; transition: all .5s; -webkit-transition: all .5s}\n.menu a.this{color: #fff}\n.menu a.this::after{content: ''; position: absolute; left: 0; bottom: -1px; width: 100%; height: 5px; background-color: #5FB878;}\n\n.header-index{background-color: #080018; border: none;}\n\n.layui-layout-admin .header-demo{border-bottom-color: #1AA094; background-color: #fff;}\n.header-demo .logo{left: 40px;}\n.header-demo .layui-nav{top: 0;}\n.header-demo .layui-nav .layui-nav-item{margin: 0 10px; line-height: 65px;}\n.header-demo .layui-nav .layui-nav-item a{color: #999;}\n.header-demo .layui-nav .layui-this{    background-color: #333;  }\n.header-demo .layui-nav .layui-nav-item a:hover, \n.header-demo .layui-nav .layui-this a{color: #000;}\n.header-demo .layui-nav .layui-this:after, \n.header-demo .layui-nav-bar{background-color: #393D49;}\n.header-demo .layui-nav .layui-this a{padding: 0 20px;}\n\n/* 底部 */\n.footer{padding: 30px 0; line-height: 30px; text-align: center; background-color: #eee; color: #666; font-weight: 300;}\nbody .layui-layout-admin .footer-demo{height: auto; padding: 5px 0; line-height: 26px;}\n.footer a{padding: 0 5px;}\n\n/* 首页banner部分 */\n.site-banner{position: relative; height: 600px; text-align: center; overflow: hidden; background-color: #393D49;}\n.site-banner-bg\n,.site-banner-main{position: absolute; left: 0; top: 0; width: 100%; height: 100%;}\n.site-banner-bg{background-position: center 0;}\n\n\n.site-zfj{padding-top: 25px; height: 220px;}\n.site-zfj i{position: absolute; left: 50%; top: 25px; width: 200px; height: 200px; margin-left: -100px; font-size: 200px; color: #c2c2c2;}\n\n@-webkit-keyframes site-zfj {\n  0% {opacity: 1;  -webkit-transform: translate3d(0, 0, 0) rotate(0deg) scale(1);}\n  10% {opacity: 0.8; -webkit-transform: translate3d(-100px, 0px, 0) rotate(10deg) scale(0.7);}\n  35% {opacity: 0.6; -webkit-transform: translate3d(100px, 0px, 0) rotate(30deg) scale(0.4);}\n  50% {opacity: 0.4; -webkit-transform: translate3d(0, 0, 0) rotate(360deg) scale(0);}\n  80% {opacity: 0.2; -webkit-transform: translate3d(0, 0, 0) rotate(720deg) scale(1);}\n  90% {opacity: 0.1; -webkit-transform: translate3d(0, 0, 0) rotate(3600deg) scale(6);}\n  100% {opacity: 1; -webkit-transform: translate3d(0, 0, 0) rotate(3600deg) scale(1);}\n}\n@keyframes site-zfj {\n  0% {opacity: 1;  transform: translate3d(0, 0, 0) rotate(0deg) scale(1);}\n  10% {opacity: 0.8; transform: translate3d(-100px, 0px, 0) rotate(10deg) scale(0.7);}\n  35% {opacity: 0.6; transform: translate3d(100px, 0px, 0) rotate(30deg) scale(0.4);}\n  50% {opacity: 0.4; transform: translate3d(0, 0, 0) rotate(360deg) scale(0);}\n  80% {opacity: 0.2; transform: translate3d(0, 0, 0) rotate(720deg) scale(1);}\n  90% {opacity: 0.1; transform: translate3d(0, 0, 0) rotate(3600deg) scale(6);}\n  100% {opacity: 1; transform: translate3d(0, 0, 0) rotate(3600deg) scale(1);}\n}\n\n@-webkit-keyframes site-desc {\n  0% { -webkit-transform: scale(1.1);}\n  100% {opacity: 1; -webkit-transform: scale(1);}\n}\n@keyframes site-desc {\n  0% { transform: scale(1.1);}\n  100% {transform: scale(1);}\n}\n\n.layui-anim-scaleSpring{-webkit-animation-name: layui-scale-spring; animation-name: layui-scale-spring}\n.site-zfj-anim i{-webkit-animation-name: site-zfj; animation-name: site-zfj; -webkit-animation-duration: 5s; animation-duration: 5s;  -webkit-animation-timing-function: linear; animation-timing-function: linear;}\n\n\n.site-desc{position: relative; height: 70px; margin-top: 25px;  background: url(../images/layui/desc.png) center no-repeat;}\n.site-desc-anim{-webkit-animation-name: site-desc; animation-name: site-desc;}\n\n.site-desc cite{position: absolute; bottom: -40px; left: 0; width: 100%; color: #c2c2c2; font-style: normal;}\n.site-download{margin-top: 80px; font-size: 0;}\n.site-download a{position: relative; padding: 0 45px 0 90px; height: 60px; line-height: 60px; border: 1px solid #464B5B; font-size: 24px; color: #ccc; transition: all .5s; -webkit-transition: all .5s;}\n.site-download a:hover{border: 1px solid #778097; color: #fff; border-radius: 30px; }\n.site-download a cite{position: absolute; left: 45px; font-size: 30px;}\n.site-version{position: relative; margin-top: 15px; color: #ccc; font-size: 12px;}\n.site-version span{padding: 0 3px;}\n.site-version *{font-style: normal;}\n.site-version a{color: #e2e2e2; text-decoration: underline;}\n\n.site-banner-other{position: absolute; left: 0; bottom: 32px; width: 100%; text-align: center;}\n.site-banner-other iframe{border: none;}\n\n.site-idea{margin: 50px 0; font-size: 0; text-align: center; font-weight: 300;}\n.site-idea li{display: inline-block; vertical-align: top; *display: inline; *zoom:1; font-size: 14px; }\n.site-idea li{width: 298px; height: 150px; padding: 30px; line-height: 24px; margin-left: 30px; border: 1px solid #d2d2d2; text-align: left;}\n.site-idea li:first-child{margin-left: 0}\n.site-idea .layui-field-title{border-color: #d2d2d2}\n.site-idea .layui-field-title legend{margin: 0 20px 20px 0; padding: 0 20px; text-align: center;}\n\n\n/* 辅助 */\n.site-tips{margin-bottom: 10px; padding: 15px; border-left: 5px solid #0078AD; background-color: #f2f2f2;}\nbody .site-tips p{margin: 0;}\n\n/* 目录 */\n.site-dir{display: none;}\n.site-dir li{line-height: 26px; margin-left: 20px; overflow: visible; list-style-type: disc;}\n.site-dir li a{display: block;}\n.site-dir li a:active{color: #01AAED;}\n.site-dir li a.layui-this{color: #01AAED;}\nbody .layui-layer-dir{box-shadow: none; border: 1px solid #d2d2d2;}\nbody .layui-layer-dir .layui-layer-content{padding: 10px; max-height: 280px; overflow: auto;}\n.site-dir a em{padding-left: 5px; font-size: 12px; color: #c2c2c2; font-style: normal;}\n\n/* 文档 */\n.site-tree{border-right: 1px solid #eee; }\n.site-tree .layui-tree{line-height: 32px;}\n.site-tree .layui-tree li i{position: relative; font-size: 22px; color: #000}\n.site-tree .layui-tree li a cite{padding: 0 8px;}\n.site-tree .layui-tree .site-tree-noicon a cite{padding-left: 15px;}\n.site-tree .layui-tree li a em{font-size: 12px; color: #bbb; padding-right: 5px; font-style: normal;}\n.site-tree .layui-tree li h2{line-height: 36px; border-left: 5px solid #009E94; margin: 15px 0 5px; padding: 0 10px; background-color: #f2f2f2;}\n.site-tree .layui-tree li ul{margin-left: 27px; line-height: 28px;}\n.site-tree .layui-tree li ul a,\n.site-tree .layui-tree li ul a i{color: #777;}\n.site-tree .layui-tree li ul a:hover{color: #333;}\n.site-tree .layui-tree li ul li{margin-left: 25px; overflow: visible; list-style-type: disc; /*list-style-position: inside;*/}\n.site-tree .layui-tree li ul li cite,\n.site-tree .layui-tree .site-tree-noicon ul li cite{padding-left: 0;}\n\n.site-tree .layui-tree .layui-this a{color: #01AAED;}\n.site-tree .layui-tree .layui-this .layui-icon{color: #01AAED;}\n\n.site-fix .site-tree{position: fixed; top: 0; bottom: 0; z-index: 666; min-height: 0; overflow: auto;  background-color: #fff;}\n.site-fix .site-content{margin-left: 220px;}\n.site-fix-footer .site-tree{margin-bottom: 120px;}\n\n\n.site-title{ margin: 30px 0 20px;}\n.site-title fieldset{border: none; padding: 0; border-top: 1px solid #eee;}\n.site-title fieldset legend{margin-left: 20px;  padding: 0 10px; font-size: 22px; font-weight: 300;}\n\n.site-text a{color: #01AAED;}\n.site-h1{margin-bottom: 20px; line-height: 60px; padding-bottom: 10px; color: #393D49; border-bottom: 1px solid #eee;  font-size: 28px; font-weight: 300;}\n.site-h1 .layui-icon{position: relative; top: 5px; font-size: 50px; margin-right: 10px;}\n.site-text{position:relative;}\n.site-text p{margin-bottom: 10px;  line-height:22px;}\n.site-text em{padding: 0 3px; font-weight: 500; font-style: italic; color: #666;}\n.site-text code{margin:0 5px; padding: 3px 10px; border: 1px solid #e2e2e2; background-color: #fbfbfb; color: #666; border-radius: 2px;}\n\n.site-table{width: 100%; margin: 10px 0;}\n.site-table thead{background-color:#f2f2f2; }\n.site-table th, \n.site-table td{padding: 6px 15px; min-height: 20px; line-height: 20px; border:1px solid #ddd; font-size: 14px; font-weight: 400;}\n.site-table tr:nth-child(even){background: #fbfbfb;}\n\n.site-block{padding: 20px; border: 1px solid #eee;}\n.site-block .layui-form{margin-right: 200px;}\n\n\n/* 演示 */\nbody .layui-layout-admin .site-demo{bottom: 82px; padding: 0;z-index:-1;}\nbody .site-demo-nav .layui-nav-item{line-height: 40px}\n.layui-nav-item .layui-icon{position: relative; /*font-size: 20px;*/}\n.layui-nav-item a cite{padding: 0 10px;}\n.site-demo .layui-main{margin: 15px; line-height: 22px;}\n.site-demo-editor{position: absolute; top: 0; bottom: 0; left: 0; width: 50%; }\n.site-demo-area{position: absolute; top: 0; bottom: 90px; width: 100%;}\n.site-demo-editor textarea{position: absolute; width: 100%; height: 100%; padding: 15px; border: none; resize: none; /*background-color: #F7FBFF;*/ background-color: #272822; color: #CFBFAF; font-family: Courier New; font-size: 12px; -webkit-box-sizing: border-box !important; -moz-box-sizing: border-box !important; box-sizing: border-box !important;}\n.site-demo-btn{position: absolute; bottom: 100px; right: 20px;}\n.site-demo-zanzhu{position: absolute; bottom: 0; left: 0; width: 100%; height: 90px; text-align: center; background-color: #e2e2e2; overflow: hidden;}\n.site-demo-zanzhu>*{position: relative; z-index: 1;}\n.site-demo-zanzhu:before{content: \"\"; position: absolute; z-index: 0; top: 50%; left: 50%; width: 120px; margin: -10px 0px 0px -60px; text-align: center; color: rgb(170, 170, 170); font-size: 18px; font-weight: 300; }\n\n.site-demo-result{position: absolute; right: 0; top: 0; bottom: 0; width: 50%;}\n.site-demo-result iframe{position: absolute; width: 100%; height: 100%;}\n\n.site-demo-button{margin-bottom: 30px;}\n.site-demo-button div{margin: 20px 30px 10px;}\n.site-demo-button .layui-btn{margin-bottom: 10px;}\n\n\n.site-demo-laytpl{text-align: center;}\n.site-demo-laytpl textarea,\n.site-demo-laytpl div span{width: 40%;  padding: 15px; margin: 0 15px;}\n.site-demo-laytpl textarea{height: 300px; border: none; background-color: #3F3F3F; color: #E3CEAB; font-family: Courier New; resize: none;}\n.site-demo-laytpl div span{display: inline-block; text-align: center; background: #101010; color: #fff;}\n.site-demo-tplres{margin: 10px 0; text-align: center}\n.site-demo-tplres .site-demo-tplh2,\n.site-demo-tplres .site-demo-tplview{display: inline-block; width: 50%;}\n.site-demo-tplres h2{padding: 15px; background: #e2e2e2;}\n.site-demo-tplres h3{font-weight: 700;}\n.site-demo-tplres div{padding: 14px; border: 1px solid #e2e2e2; text-align: left;}\n\n.site-demo-upload,\n.site-demo-upload img{width: 200px; height: 200px; border-radius: 100%;}\n.site-demo-upload{position: relative; background: #e2e2e2;}\n.site-demo-upload .site-demo-upbar{position: absolute; top: 50%; left: 50%; margin: -18px 0 0 -56px;}\n.site-demo-upload .layui-upload-button{background-color: rgba(0,0,0,.2); color: rgba(255,255,255,1);}\n\n.site-demo-util{position: relative; width: 300px;}\n.site-demo-util img{width: 300px; border-radius: 100%;}\n.site-demo-util span{position: absolute; left: 0; top: 0; width: 100%; height: 100%; background: #333; cursor: pointer;}\n@-webkit-keyframes demo-fengjie {\n  0% {-webkit-filter: blur(0); opacity: 1; background: #fff; height: 300px; border-radius: 100%;}\n  80% {-webkit-filter: blur(50px);  opacity: 0.95;}\n  100% {-webkit-filter: blur(20px); opacity: 0; background: #fff;}\n}\n@keyframes demo-fengjie {\n  0% {filter: blur(0); opacity: 1; background: #fff; height: 300px; border-radius: 100%;}\n  80% {filter: blur(50px);  opacity: 0.95;}\n  100% {filter: blur(20px); opacity: 0; background: #fff;}\n}\n.site-demo-fengjie{-webkit-animation-name: demo-fengjie; animation-name: demo-fengjie; -webkit-animation-duration: 5s; animation-duration: 5s;}\n\n\n.layui-layout-admin .site-demo-body{top: 117px;}\n.site-demo-title{position: fixed; left: 200px; right: 0; top: 76px;}\n.site-demo-code{position: absolute; left: 0; top: 0; width: 100%; height: 100%; border: none; padding: 10px; resize: none; font-size: 12px; background-color: #F7FBFF; color: #881280; font-family: Courier New;}\n\n.site-demo-body .layui-elem-quote a{color: #01AAED;}\n.site-demo-body .layui-elem-quote a:hover{color: #FF5722;}\n\n\n/* 其它 */\n#trans-tooltip,\n#tip-arrow-bottom,\n#tip-arrow-top{display: none !important;}\n\n\n/* 独立组件 */\n.alone{width:730px; margin:200px auto;}\n.alone ul{margin-left:1px; font-size:0;}\n.alone li{display:inline-block; width:181px; font-size: 16px; text-align:center; line-height:80px; margin:0 1px 1px 0; background-color:#393D49; color:#fff;}\n.alone li:hover{opacity:0.8;}\n.alone li a{display:block; color:#fff;}\n\n\n/* 自定义css */\n.admin-header-item-mobile{\n\tposition: absolute; right: 0px; height: 70px;line-height: 70px; \n\tpadding: 0 20px; text-align: center; top:0;\n\tdisplay: none;\n}\n\n.admin-nav-tree .layui-nav-child a {\n\tpadding-left: 30px;\n}\n\n.admin{\n\tborder: 0;\n\tmargin: 0;\n\tbox-shadow:none;\n}\n.admin-nav-card{\n\tmargin-top: 5px;\n}\n.admin-nav-card .layui-icon{\n\tposition: relative;\n}\n.admin-nav-card .layui-tab-item iframe{\n\twidth: 100%;\n\tborder: 0;\n\theight: 100%;\n}\n.admin-nav-card>.layui-tab-title{\n\tborder-bottom: 1px solid #1AA094;\n}\n.admin-nav-card .layui-tab-title cite{\n\tfont-style: normal;\n\tpadding-left: 5px;\n}\n.admin-nav-card>.layui-tab-title .layui-this{\n\tcolor: white;\n    background-color: #1AA094;\n}\n.admin-nav-card>.layui-tab-title .layui-this:after{\n\tborder-bottom: 0;\n}\n.admin-header-user img{\n\twidth: 40px; height: 40px; border-radius: 100%;    \n\t/*position: relative;\n    top: 15px;*/\n}\n.admin-header-user .layui-nav-more{\n\t/*top:26px;*/\n}\n.admin-header-user .layui-nav-mored{\n\ttop: 26px;\n}\n\n/*lock*/\n.admin-header-lock{\n\twidth: 320px; height: 150px; padding: 20px; position: relative; text-align: center;\n}\n.admin-header-lock-img{\n\twidth: 60px; height: 60px; margin: 0 auto;\n}\n.admin-header-lock-img img{\n\twidth: 60px; height: 60px; border-radius: 100%;\n}\n.admin-header-lock-name{\n\tcolor: #009688;margin: 8px 0 15px 0;\n}\n.admin-header-lock-input{\n\twidth: 150px; color: #FFFFFF; height: 30px; border: 0;background-color: #009688; padding: 0 7px; border-radius: 2px;\n}\n/*table*/\n.site-table tbody tr td {text-align: center;}\n.site-table tbody tr td .layui-btn+.layui-btn{margin-left: 0px;}\n.admin-table-page {position: fixed;z-index: 19940201;bottom: 0;width: 100%;background-color: #eee;border-bottom: 1px solid #ddd;left: 0px;}\n.admin-table-page .page{padding-left:20px;}\n.admin-table-page .page .layui-laypage {margin: 6px 0 0 0;}\n\n/**/\n.admin-main {margin: 15px;}\n\n.admin-side-toggle,.admin-side-full{\n\tposition: absolute; cursor: pointer;\n    z-index: 19940201;\n    left: 200px;\n    color: white;\n    text-align: center;\n    width: 30px;\n    height: 30px;\n    background-color: #1AA094;\n    line-height: 30px;\n    top: 25%;\n}\n.admin-side-toggle:hover{\n\tbackground-color: #5FB878;\n}\n.admin-side-full{\n\tleft: 240px;\n}\n.admin-login-box{\n\twidth: 185px; height: 70px; position: relative;\n}\n\n.beg-navbar .layui-nav-child dd a{\n\tpadding-left: 30px;\n}\n\n\n.admin-contextmenu{\n\tposition: absolute;line-height: 36px;padding: 5px 0;\n\tborder: 1px solid #d2d2d2;background-color: white;z-index: 19940201;border-radius: 2px;white-space: nowrap;top:30px;\n\t/*width: 100px;height: 200px; */\n}\n.admin-contextmenu ul li{\n\tpadding: 0 15px;\n}\n.admin-contextmenu ul li:hover{\n\tbackground-color: #eee;\n\tcursor: pointer;\n}\n\n\n/* 适配多设备 */\n@media screen and (max-width: 750px) {\n  .layui-main{width: auto; margin: 0 10px;}\n  .logo,\n  .header-demo .logo{left: 10px;}\n\n  .site-nav-layim{display: none !important;}\n  .header .layui-nav .layui-nav-item{margin: 0;}\n  .header .layui-nav .layui-nav-item a{padding: 0 15px;}\n  .site-banner{height: 300px;}\n  .site-banner-bg{background-size: cover;}\n  .site-zfj{height: 100px; padding-top: 5px;}\n  .site-zfj i{top: 10px; width: 100px; height: 100px; margin-left: -50px; font-size: 100px;}\n  .site-desc{background-size: 70%; margin: 0;}\n  .site-desc cite{display: none;}\n  .site-download{margin-top: 0; }\n  .site-download a{height: 40px; line-height: 40px; padding: 0 25px 0 60px; border: 1px solid #778097; border-radius: 30px; color: #fff; font-size: 16px;}\n  .site-download a cite{left: 20px;}\n  .site-banner-other{bottom: 15px;}\n\n  .site-idea{margin: 20px 0;}\n  .site-idea li{margin: 0 0 20px 0; width: 100%; height: auto; -webkit-box-sizing: border-box !important; -moz-box-sizing: border-box !important; box-sizing: border-box !important;}\n  .site-hengfu img{max-width: 100%}\n\n  .layui-layer-dir{display: none;}\n  .site-tree{position: fixed; top: 0; bottom: 0; min-height: 0; overflow: auto; z-index: 1000; left: -260px; background-color: #fff;  transition: all .3s; -webkit-transition: all .3s;}\n  .site-content{width: 100%; padding: 0; overflow: auto;}\n  .site-content img{max-width: 100%;}\n  .site-tree-mobile{display: block!important; position: fixed; z-index: 100000; bottom: 15px; left: 15px; width: 50px; height: 50px; line-height: 50px; border-radius: 2px; text-align: center; background-color: rgba(0,0,0,.7); color: #fff;}\n  .site-home .site-tree-mobile{display: none!important;}\n  .site-mobile .site-tree-mobile{display: none !important;}\n  .site-mobile .site-tree{left: 0;}\n  .site-mobile .site-mobile-shade{content: ''; position: fixed; top: 0; bottom: 0; left: 0; right: 0; background-color: rgba(0,0,0,.8); z-index: 9999;}\n  .site-tree-mobile i{font-size: 20px;}\n  .layui-code-view{-webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box;}\n\n  .layui-layout-admin .layui-side{position: fixed; top: 0; left: -260px; transition: all .3s; -webkit-transition: all .3s; z-index: 10000;}\n  .layui-body{position: static; bottom: 0; left: 0;}\n  .site-mobile .layui-side{left: 0;}\n  body .layui-layout-admin .footer-demo{position: static;}\n\n  .site-demo-area,\n  .site-demo-editor,\n  .site-demo-result,\n  .site-demo-editor textarea,\n  .site-demo-result iframe{position: static; width: 100%;}\n  .site-demo-editor textarea{height: 350px;}\n  .site-demo-zanzhu{display: none;}\n  .site-demo-btn{bottom: auto; top: 370px;}\n  .site-demo-result iframe{height: 500px;}\n\n  .site-demo-laytpl textarea, .site-demo-laytpl div span{margin: 0;}\n  .site-demo-tplres .site-demo-tplh2, .site-demo-tplres .site-demo-tplview{width: 100%; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box;}\n\n  .site-demo-title{position: static; left: 0;}\n  body .layui-layout-admin .site-demo{}\n  .site-demo-code{position: static; height: 350px;}\n  \n  .admin-side-toggle ,.admin-header-item{display: none;}\n  .admin-header-item-mobile{ display: block; }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/layui/css/layui.css",
    "content": "/** layui-v2.2.5 MIT License By https://www.layui.com */\n.layui-inline,img{display:inline-block;vertical-align:middle}h1,h2,h3,h4,h5,h6{font-weight:400}.layui-edge,.layui-header,.layui-inline,.layui-main{position:relative}.layui-btn,.layui-edge,.layui-inline,img{vertical-align:middle}.layui-btn,.layui-disabled,.layui-icon,.layui-unselect{-webkit-user-select:none;-ms-user-select:none;-moz-user-select:none}blockquote,body,button,dd,div,dl,dt,form,h1,h2,h3,h4,h5,h6,input,li,ol,p,pre,td,textarea,th,ul{margin:0;padding:0;-webkit-tap-highlight-color:rgba(0,0,0,0)}a:active,a:hover{outline:0}img{border:none}li{list-style:none}table{border-collapse:collapse;border-spacing:0}h4,h5,h6{font-size:100%}button,input,optgroup,option,select,textarea{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;outline:0}pre{white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word}body{line-height:24px;font:14px Helvetica Neue,Helvetica,PingFang SC,\\5FAE\\8F6F\\96C5\\9ED1,Tahoma,Arial,sans-serif}hr{height:1px;margin:10px 0;border:0;clear:both}a{color:#333;text-decoration:none}a:hover{color:#777}a cite{font-style:normal;*cursor:pointer}.layui-border-box,.layui-border-box *{box-sizing:border-box}.layui-box,.layui-box *{box-sizing:content-box}.layui-clear{clear:both;*zoom:1}.layui-clear:after{content:'\\20';clear:both;*zoom:1;display:block;height:0}.layui-inline{*display:inline;*zoom:1}.layui-edge{display:inline-block;width:0;height:0;border-width:6px;border-style:dashed;border-color:transparent;overflow:hidden}.layui-edge-top{top:-4px;border-bottom-color:#999;border-bottom-style:solid}.layui-edge-right{border-left-color:#999;border-left-style:solid}.layui-edge-bottom{top:2px;border-top-color:#999;border-top-style:solid}.layui-edge-left{border-right-color:#999;border-right-style:solid}.layui-elip{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-disabled,.layui-disabled:hover{color:#d2d2d2!important;cursor:not-allowed!important}.layui-circle{border-radius:100%}.layui-show{display:block!important}.layui-hide{display:none!important}@font-face{font-family:layui-icon;src:url(../font/iconfont.eot?v=220);src:url(../font/iconfont.eot?v=220#iefix) format('embedded-opentype'),url(../font/iconfont.svg?v=220#iconfont) format('svg'),url(../font/iconfont.woff?v=220) format('woff'),url(../font/iconfont.ttf?v=220) format('truetype')}.layui-icon{font-family:layui-icon!important;font-size:16px;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.layui-icon-duihua:before{content:\"\\e611\"}.layui-icon-shezhi:before{content:\"\\e614\"}.layui-icon-yinshenim:before{content:\"\\e60f\"}.layui-icon-search:before{content:\"\\e615\"}.layui-icon-fenxiang1:before{content:\"\\e641\"}.layui-icon-shezhi1:before{content:\"\\e620\"}.layui-icon-yinqing:before{content:\"\\e628\"}.layui-icon-yuejuancuohao:before{content:\"\\1006\"}.layui-icon-cuo:before{content:\"\\1007\"}.layui-icon-baobiao:before{content:\"\\e629\"}.layui-icon-star:before{content:\"\\e600\"}.layui-icon-yuandian:before{content:\"\\e617\"}.layui-icon-chat:before{content:\"\\e606\"}.layui-icon-logo:before{content:\"\\e609\"}.layui-icon-list:before{content:\"\\e60a\"}.layui-icon-tubiao:before{content:\"\\e62c\"}.layui-icon-right:before{content:\"\\1005\"}.layui-icon-huanfu2:before{content:\"\\e61b\"}.layui-icon-On-line:before{content:\"\\e610\"}.layui-icon-biaoge:before{content:\"\\e62d\"}.layui-icon-youyou:before{content:\"\\e602\"}.layui-icon-zuozuo:before{content:\"\\e603\"}.layui-icon-cart-simple:before{content:\"\\e698\"}.layui-icon-cry:before{content:\"\\e69c\"}.layui-icon-smile:before{content:\"\\e6af\"}.layui-icon-survey:before{content:\"\\e6b2\"}.layui-icon-tree:before{content:\"\\e62e\"}.layui-icon-iconfont17:before{content:\"\\e62f\"}.layui-icon-tianjia:before{content:\"\\e61f\"}.layui-icon-xiazai:before{content:\"\\e601\"}.layui-icon-xuanzemoban48:before{content:\"\\e630\"}.layui-icon-gongju:before{content:\"\\e631\"}.layui-icon-face-surprised:before{content:\"\\e664\"}.layui-icon-bianji:before{content:\"\\e642\"}.layui-icon-speaker:before{content:\"\\e645\"}.layui-icon-xiangxia:before{content:\"\\e61a\"}.layui-icon-wenjian:before{content:\"\\e621\"}.layui-icon-layouts:before{content:\"\\e632\"}.layui-icon-duigou:before{content:\"\\e618\"}.layui-icon-tianjia1:before{content:\"\\e608\"}.layui-icon-yaoyaozhibofanye:before{content:\"\\e633\"}.layui-icon-read:before{content:\"\\e705\"}.layui-icon-404:before{content:\"\\e61c\"}.layui-icon-lunbozutu:before{content:\"\\e634\"}.layui-icon-help:before{content:\"\\e607\"}.layui-icon-daima1:before{content:\"\\e635\"}.layui-icon-jinshui:before{content:\"\\e636\"}.layui-icon-find-fill:before{content:\"\\e670\"}.layui-icon-about:before{content:\"\\e60b\"}.layui-icon-location:before{content:\"\\e715\"}.layui-icon-xiangshang:before{content:\"\\e619\"}.layui-icon-pause:before{content:\"\\e651\"}.layui-icon-riqi:before{content:\"\\e637\"}.layui-icon-uploadfile:before{content:\"\\e61d\"}.layui-icon-delete:before{content:\"\\e640\"}.layui-icon-play:before{content:\"\\e652\"}.layui-icon-top:before{content:\"\\e604\"}.layui-icon-haoyouqingqiu:before{content:\"\\e612\"}.layui-icon-weibiaoti1:before{content:\"\\e605\"}.layui-icon-chuangkou:before{content:\"\\e638\"}.layui-icon-comiisbiaoqing:before{content:\"\\e60c\"}.layui-icon-zhengque:before{content:\"\\e616\"}.layui-icon-dollar:before{content:\"\\e659\"}.layui-icon-iconfontwodehaoyou:before{content:\"\\e613\"}.layui-icon-wenjianxiazai:before{content:\"\\e61e\"}.layui-icon-tupian:before{content:\"\\e60d\"}.layui-icon-lianjie:before{content:\"\\e64c\"}.layui-icon-diamond:before{content:\"\\e735\"}.layui-icon-jilu:before{content:\"\\e60e\"}.layui-icon-liucheng:before{content:\"\\e622\"}.layui-icon-fontstrikethrough:before{content:\"\\e64f\"}.layui-icon-unlink:before{content:\"\\e64d\"}.layui-icon-bianjiwenzi:before{content:\"\\e639\"}.layui-icon-sanjiao:before{content:\"\\e623\"}.layui-icon-danxuankuanghouxuan:before{content:\"\\e63f\"}.layui-icon-danxuankuangxuanzhong:before{content:\"\\e643\"}.layui-icon-juzhongduiqi:before{content:\"\\e647\"}.layui-icon-youduiqi:before{content:\"\\e648\"}.layui-icon-zuoduiqi:before{content:\"\\e649\"}.layui-icon-gongsisvgtubiaozongji22:before{content:\"\\e626\"}.layui-icon-gongsisvgtubiaozongji23:before{content:\"\\e627\"}.layui-icon-refresh-2:before{content:\"\\1002\"}.layui-icon-loading-1:before{content:\"\\e63e\"}.layui-icon-return:before{content:\"\\e65c\"}.layui-icon-jiacu:before{content:\"\\e62b\"}.layui-icon-uploading:before{content:\"\\e67c\"}.layui-icon-liaotianduihuaimgoutong:before{content:\"\\e63a\"}.layui-icon-video:before{content:\"\\e6ed\"}.layui-icon-headset:before{content:\"\\e6fc\"}.layui-icon-wenjianjiafan:before{content:\"\\e624\"}.layui-icon-shouji:before{content:\"\\e63b\"}.layui-icon-tianjia2:before{content:\"\\e654\"}.layui-icon-wenjianjia:before{content:\"\\e7a0\"}.layui-icon-biaoqing:before{content:\"\\e650\"}.layui-icon-html:before{content:\"\\e64b\"}.layui-icon-biaodan:before{content:\"\\e63c\"}.layui-icon-cart:before{content:\"\\e657\"}.layui-icon-camera-fill:before{content:\"\\e65d\"}.layui-icon-25:before{content:\"\\e62a\"}.layui-icon-emwdaima:before{content:\"\\e64e\"}.layui-icon-fire:before{content:\"\\e756\"}.layui-icon-set:before{content:\"\\e716\"}.layui-icon-zitixiahuaxian:before{content:\"\\e646\"}.layui-icon-sanjiao1:before{content:\"\\e625\"}.layui-icon-tips:before{content:\"\\e702\"}.layui-icon-tupian-copy-copy:before{content:\"\\e64a\"}.layui-icon-more-vertical:before{content:\"\\e671\"}.layui-icon-zhuti2:before{content:\"\\e66c\"}.layui-icon-loading:before{content:\"\\e63d\"}.layui-icon-xieti:before{content:\"\\e644\"}.layui-icon-refresh-1:before{content:\"\\e666\"}.layui-icon-rmb:before{content:\"\\e65e\"}.layui-icon-home:before{content:\"\\e68e\"}.layui-icon-user:before{content:\"\\e770\"}.layui-icon-notice:before{content:\"\\e667\"}.layui-icon-voice:before{content:\"\\e688\"}.layui-icon-download:before{content:\"\\e681\"}.layui-icon-snowflake:before{content:\"\\e6b1\"}.layui-icon-yemian1:before{content:\"\\e655\"}.layui-icon-template:before{content:\"\\e663\"}.layui-icon-auz:before{content:\"\\e672\"}.layui-icon-console:before{content:\"\\e665\"}.layui-icon-app:before{content:\"\\e653\"}.layui-icon-xiayiye:before{content:\"\\e65a\"}.layui-icon-website:before{content:\"\\e7ae\"}.layui-icon-xiayiye1:before{content:\"\\e65b\"}.layui-icon-component:before{content:\"\\e857\"}.layui-icon-more:before{content:\"\\e65f\"}.layui-icon-shrink-right:before{content:\"\\e668\"}.layui-icon-spread-left:before{content:\"\\e66b\"}.layui-icon-camera:before{content:\"\\e660\"}.layui-icon-note:before{content:\"\\e66e\"}.layui-icon-refresh:before{content:\"\\e669\"}.layui-icon-nv:before{content:\"\\e661\"}.layui-icon-nan:before{content:\"\\e662\"}.layui-icon-senior:before{content:\"\\e674\"}.layui-icon-theme:before{content:\"\\e66a\"}.layui-icon-tread:before{content:\"\\e6c5\"}.layui-icon-praise:before{content:\"\\e6c6\"}.layui-icon-star-fill:before{content:\"\\e658\"}.layui-icon-template-1:before{content:\"\\e656\"}.layui-icon-loading-2:before{content:\"\\e66d\"}.layui-main{width:1140px;margin:0 auto}.layui-header{z-index:1000;height:60px}.layui-header a:hover{transition:all .5s;-webkit-transition:all .5s}.layui-side{position:fixed;top:0;bottom:0;z-index:999;width:200px;overflow-x:hidden}.layui-side-scroll{width:220px;height:100%;overflow-x:hidden}.layui-body{position:absolute;left:200px;right:0;top:0;bottom:0;z-index:998;width:auto;overflow:hidden;overflow-y:auto;box-sizing:border-box}.layui-layout-body{overflow:hidden}.layui-layout-admin .layui-header{background-color:#23262E}.layui-layout-admin .layui-side{top:60px;width:200px;overflow-x:hidden}.layui-layout-admin .layui-body{top:60px;bottom:44px}.layui-layout-admin .layui-main{width:auto;margin:0 15px}.layui-layout-admin .layui-footer{position:fixed;left:200px;right:0;bottom:0;height:44px;line-height:44px;padding:0 15px;background-color:#eee}.layui-layout-admin .layui-logo{position:absolute;left:0;top:0;width:200px;height:100%;line-height:60px;text-align:center;color:#009688;font-size:16px}.layui-layout-admin .layui-header .layui-nav{background:0 0}.layui-layout-left{position:absolute!important;left:200px;top:0}.layui-layout-right{position:absolute!important;right:0;top:0}.layui-container{position:relative;margin:0 auto;padding:0 15px;box-sizing:border-box}.layui-fluid{position:relative;margin:0 auto;padding:0 15px}.layui-row:after,.layui-row:before{content:'';display:block;clear:both}.layui-col-lg1,.layui-col-lg10,.layui-col-lg11,.layui-col-lg12,.layui-col-lg2,.layui-col-lg3,.layui-col-lg4,.layui-col-lg5,.layui-col-lg6,.layui-col-lg7,.layui-col-lg8,.layui-col-lg9,.layui-col-md1,.layui-col-md10,.layui-col-md11,.layui-col-md12,.layui-col-md2,.layui-col-md3,.layui-col-md4,.layui-col-md5,.layui-col-md6,.layui-col-md7,.layui-col-md8,.layui-col-md9,.layui-col-sm1,.layui-col-sm10,.layui-col-sm11,.layui-col-sm12,.layui-col-sm2,.layui-col-sm3,.layui-col-sm4,.layui-col-sm5,.layui-col-sm6,.layui-col-sm7,.layui-col-sm8,.layui-col-sm9,.layui-col-xs1,.layui-col-xs10,.layui-col-xs11,.layui-col-xs12,.layui-col-xs2,.layui-col-xs3,.layui-col-xs4,.layui-col-xs5,.layui-col-xs6,.layui-col-xs7,.layui-col-xs8,.layui-col-xs9{position:relative;display:block;box-sizing:border-box}.layui-col-xs1,.layui-col-xs10,.layui-col-xs11,.layui-col-xs12,.layui-col-xs2,.layui-col-xs3,.layui-col-xs4,.layui-col-xs5,.layui-col-xs6,.layui-col-xs7,.layui-col-xs8,.layui-col-xs9{float:left}.layui-col-xs1{width:8.33333333%}.layui-col-xs2{width:16.66666667%}.layui-col-xs3{width:25%}.layui-col-xs4{width:33.33333333%}.layui-col-xs5{width:41.66666667%}.layui-col-xs6{width:50%}.layui-col-xs7{width:58.33333333%}.layui-col-xs8{width:66.66666667%}.layui-col-xs9{width:75%}.layui-col-xs10{width:83.33333333%}.layui-col-xs11{width:91.66666667%}.layui-col-xs12{width:100%}.layui-col-xs-offset1{margin-left:8.33333333%}.layui-col-xs-offset2{margin-left:16.66666667%}.layui-col-xs-offset3{margin-left:25%}.layui-col-xs-offset4{margin-left:33.33333333%}.layui-col-xs-offset5{margin-left:41.66666667%}.layui-col-xs-offset6{margin-left:50%}.layui-col-xs-offset7{margin-left:58.33333333%}.layui-col-xs-offset8{margin-left:66.66666667%}.layui-col-xs-offset9{margin-left:75%}.layui-col-xs-offset10{margin-left:83.33333333%}.layui-col-xs-offset11{margin-left:91.66666667%}.layui-col-xs-offset12{margin-left:100%}@media screen and (max-width:768px){.layui-hide-xs{display:none!important}.layui-show-xs-block{display:block!important}.layui-show-xs-inline{display:inline!important}.layui-show-xs-inline-block{display:inline-block!important}}@media screen and (min-width:768px){.layui-container{width:750px}.layui-hide-sm{display:none!important}.layui-show-sm-block{display:block!important}.layui-show-sm-inline{display:inline!important}.layui-show-sm-inline-block{display:inline-block!important}.layui-col-sm1,.layui-col-sm10,.layui-col-sm11,.layui-col-sm12,.layui-col-sm2,.layui-col-sm3,.layui-col-sm4,.layui-col-sm5,.layui-col-sm6,.layui-col-sm7,.layui-col-sm8,.layui-col-sm9{float:left}.layui-col-sm1{width:8.33333333%}.layui-col-sm2{width:16.66666667%}.layui-col-sm3{width:25%}.layui-col-sm4{width:33.33333333%}.layui-col-sm5{width:41.66666667%}.layui-col-sm6{width:50%}.layui-col-sm7{width:58.33333333%}.layui-col-sm8{width:66.66666667%}.layui-col-sm9{width:75%}.layui-col-sm10{width:83.33333333%}.layui-col-sm11{width:91.66666667%}.layui-col-sm12{width:100%}.layui-col-sm-offset1{margin-left:8.33333333%}.layui-col-sm-offset2{margin-left:16.66666667%}.layui-col-sm-offset3{margin-left:25%}.layui-col-sm-offset4{margin-left:33.33333333%}.layui-col-sm-offset5{margin-left:41.66666667%}.layui-col-sm-offset6{margin-left:50%}.layui-col-sm-offset7{margin-left:58.33333333%}.layui-col-sm-offset8{margin-left:66.66666667%}.layui-col-sm-offset9{margin-left:75%}.layui-col-sm-offset10{margin-left:83.33333333%}.layui-col-sm-offset11{margin-left:91.66666667%}.layui-col-sm-offset12{margin-left:100%}}@media screen and (min-width:992px){.layui-container{width:970px}.layui-hide-md{display:none!important}.layui-show-md-block{display:block!important}.layui-show-md-inline{display:inline!important}.layui-show-md-inline-block{display:inline-block!important}.layui-col-md1,.layui-col-md10,.layui-col-md11,.layui-col-md12,.layui-col-md2,.layui-col-md3,.layui-col-md4,.layui-col-md5,.layui-col-md6,.layui-col-md7,.layui-col-md8,.layui-col-md9{float:left}.layui-col-md1{width:8.33333333%}.layui-col-md2{width:16.66666667%}.layui-col-md3{width:25%}.layui-col-md4{width:33.33333333%}.layui-col-md5{width:41.66666667%}.layui-col-md6{width:50%}.layui-col-md7{width:58.33333333%}.layui-col-md8{width:66.66666667%}.layui-col-md9{width:75%}.layui-col-md10{width:83.33333333%}.layui-col-md11{width:91.66666667%}.layui-col-md12{width:100%}.layui-col-md-offset1{margin-left:8.33333333%}.layui-col-md-offset2{margin-left:16.66666667%}.layui-col-md-offset3{margin-left:25%}.layui-col-md-offset4{margin-left:33.33333333%}.layui-col-md-offset5{margin-left:41.66666667%}.layui-col-md-offset6{margin-left:50%}.layui-col-md-offset7{margin-left:58.33333333%}.layui-col-md-offset8{margin-left:66.66666667%}.layui-col-md-offset9{margin-left:75%}.layui-col-md-offset10{margin-left:83.33333333%}.layui-col-md-offset11{margin-left:91.66666667%}.layui-col-md-offset12{margin-left:100%}}@media screen and (min-width:1200px){.layui-container{width:1170px}.layui-hide-lg{display:none!important}.layui-show-lg-block{display:block!important}.layui-show-lg-inline{display:inline!important}.layui-show-lg-inline-block{display:inline-block!important}.layui-col-lg1,.layui-col-lg10,.layui-col-lg11,.layui-col-lg12,.layui-col-lg2,.layui-col-lg3,.layui-col-lg4,.layui-col-lg5,.layui-col-lg6,.layui-col-lg7,.layui-col-lg8,.layui-col-lg9{float:left}.layui-col-lg1{width:8.33333333%}.layui-col-lg2{width:16.66666667%}.layui-col-lg3{width:25%}.layui-col-lg4{width:33.33333333%}.layui-col-lg5{width:41.66666667%}.layui-col-lg6{width:50%}.layui-col-lg7{width:58.33333333%}.layui-col-lg8{width:66.66666667%}.layui-col-lg9{width:75%}.layui-col-lg10{width:83.33333333%}.layui-col-lg11{width:91.66666667%}.layui-col-lg12{width:100%}.layui-col-lg-offset1{margin-left:8.33333333%}.layui-col-lg-offset2{margin-left:16.66666667%}.layui-col-lg-offset3{margin-left:25%}.layui-col-lg-offset4{margin-left:33.33333333%}.layui-col-lg-offset5{margin-left:41.66666667%}.layui-col-lg-offset6{margin-left:50%}.layui-col-lg-offset7{margin-left:58.33333333%}.layui-col-lg-offset8{margin-left:66.66666667%}.layui-col-lg-offset9{margin-left:75%}.layui-col-lg-offset10{margin-left:83.33333333%}.layui-col-lg-offset11{margin-left:91.66666667%}.layui-col-lg-offset12{margin-left:100%}}.layui-col-space1{margin:-.5px}.layui-col-space1>*{padding:.5px}.layui-col-space3{margin:-1.5px}.layui-col-space3>*{padding:1.5px}.layui-col-space5{margin:-2.5px}.layui-col-space5>*{padding:2.5px}.layui-col-space8{margin:-3.5px}.layui-col-space8>*{padding:3.5px}.layui-col-space10{margin:-5px}.layui-col-space10>*{padding:5px}.layui-col-space12{margin:-6px}.layui-col-space12>*{padding:6px}.layui-col-space15{margin:-7.5px}.layui-col-space15>*{padding:7.5px}.layui-col-space18{margin:-9px}.layui-col-space18>*{padding:9px}.layui-col-space20{margin:-10px}.layui-col-space20>*{padding:10px}.layui-col-space22{margin:-11px}.layui-col-space22>*{padding:11px}.layui-col-space25{margin:-12.5px}.layui-col-space25>*{padding:12.5px}.layui-col-space30{margin:-15px}.layui-col-space30>*{padding:15px}.layui-btn,.layui-input,.layui-select,.layui-textarea,.layui-upload-button{outline:0;-webkit-appearance:none;transition:all .3s;-webkit-transition:all .3s;box-sizing:border-box}.layui-elem-quote{margin-bottom:10px;padding:15px;line-height:22px;border-radius:0 2px 2px 0;background-color:#f2f2f2}.layui-quote-nm{border-style:solid;border-width:1px 1px 1px 5px;background:0 0}.layui-elem-field{margin-bottom:10px;padding:0;border-width:1px;border-style:solid}.layui-elem-field legend{margin-left:20px;padding:0 10px;font-size:20px;font-weight:300}.layui-field-title{margin:10px 0 20px;border-width:1px 0 0}.layui-field-box{padding:10px 15px}.layui-field-title .layui-field-box{padding:10px 0}.layui-progress{position:relative;height:6px;border-radius:20px;background-color:#e2e2e2}.layui-progress-bar{position:absolute;left:0;top:0;width:0;max-width:100%;height:6px;border-radius:20px;text-align:right;background-color:#5FB878;transition:all .3s;-webkit-transition:all .3s}.layui-progress-big,.layui-progress-big .layui-progress-bar{height:18px;line-height:18px}.layui-progress-text{position:relative;top:-20px;line-height:18px;font-size:12px;color:#666}.layui-progress-big .layui-progress-text{position:static;padding:0 10px;color:#fff}.layui-collapse{border-width:1px;border-style:solid;border-radius:2px}.layui-colla-content,.layui-colla-item{border-top-width:1px;border-top-style:solid}.layui-colla-item:first-child{border-top:none}.layui-colla-title{position:relative;height:42px;line-height:42px;padding:0 15px 0 35px;color:#333;background-color:#f2f2f2;cursor:pointer;font-size:14px}.layui-colla-content{display:none;padding:10px 15px;line-height:22px;color:#666}.layui-colla-icon{position:absolute;left:15px;top:0;font-size:14px}.layui-card-body,.layui-card-header,.layui-form-label,.layui-form-mid,.layui-form-select,.layui-input-block,.layui-input-inline,.layui-textarea{position:relative}.layui-card{margin-bottom:15px;border-radius:2px;background-color:#fff;box-shadow:0 1px 2px 0 rgba(0,0,0,.05)}.layui-card:last-child{margin-bottom:0}.layui-card-header{height:42px;line-height:42px;padding:0 15px;border-bottom:1px solid #f6f6f6;color:#333;border-radius:2px 2px 0 0;font-size:14px}.layui-bg-black,.layui-bg-blue,.layui-bg-cyan,.layui-bg-green,.layui-bg-orange,.layui-bg-red{color:#fff!important}.layui-card-body{padding:10px 15px;line-height:24px}.layui-card-body .layui-table{margin:5px 0}.layui-card .layui-tab{margin:0}.layui-panel-window{position:relative;padding:15px;border-radius:0;border-top:5px solid #E6E6E6;background-color:#fff}.layui-bg-red{background-color:#FF5722!important}.layui-bg-orange{background-color:#FFB800!important}.layui-bg-green{background-color:#009688!important}.layui-bg-cyan{background-color:#2F4056!important}.layui-bg-blue{background-color:#1E9FFF!important}.layui-bg-black{background-color:#393D49!important}.layui-bg-gray{background-color:#eee!important;color:#666!important}.layui-badge-rim,.layui-colla-content,.layui-colla-item,.layui-collapse,.layui-elem-field,.layui-form-pane .layui-form-item[pane],.layui-form-pane .layui-form-label,.layui-input,.layui-layedit,.layui-layedit-tool,.layui-quote-nm,.layui-select,.layui-tab-bar,.layui-tab-card,.layui-tab-title,.layui-tab-title .layui-this:after,.layui-textarea{border-color:#e6e6e6}.layui-timeline-item:before,hr{background-color:#e6e6e6}.layui-text{line-height:22px;font-size:14px;color:#666}.layui-text h1,.layui-text h2,.layui-text h3{font-weight:500;color:#333}.layui-text h1{font-size:30px}.layui-text h2{font-size:24px}.layui-text h3{font-size:18px}.layui-text a:not(.layui-btn){color:#01AAED}.layui-text a:not(.layui-btn):hover{text-decoration:underline}.layui-text ul{padding:5px 0 5px 15px}.layui-text ul li{margin-top:5px;list-style-type:disc}.layui-text em,.layui-word-aux{color:#999!important;padding:0 5px!important}.layui-btn{display:inline-block;height:38px;line-height:38px;padding:0 18px;background-color:#009688;color:#fff;white-space:nowrap;text-align:center;font-size:14px;border:none;border-radius:2px;cursor:pointer}.layui-btn:hover{opacity:.8;filter:alpha(opacity=80);color:#fff}.layui-btn:active{opacity:1;filter:alpha(opacity=100)}.layui-btn+.layui-btn{margin-left:10px}.layui-btn-container{font-size:0}.layui-btn-container .layui-btn{margin-right:10px;margin-bottom:10px}.layui-btn-container .layui-btn+.layui-btn{margin-left:0}.layui-table .layui-btn-container .layui-btn{margin-bottom:9px}.layui-btn-radius{border-radius:100px}.layui-btn .layui-icon{margin-right:3px;font-size:18px;vertical-align:bottom;vertical-align:middle\\9}.layui-btn-primary{border:1px solid #C9C9C9;background-color:#fff;color:#555}.layui-btn-primary:hover{border-color:#009688;color:#333}.layui-btn-normal{background-color:#1E9FFF}.layui-btn-warm{background-color:#FFB800}.layui-btn-danger{background-color:#FF5722}.layui-btn-disabled,.layui-btn-disabled:active,.layui-btn-disabled:hover{border:1px solid #e6e6e6;background-color:#FBFBFB;color:#C9C9C9;cursor:not-allowed;opacity:1}.layui-btn-lg{height:44px;line-height:44px;padding:0 25px;font-size:16px}.layui-btn-sm{height:30px;line-height:30px;padding:0 10px;font-size:12px}.layui-btn-sm i{font-size:16px!important}.layui-btn-xs{height:22px;line-height:22px;padding:0 5px;font-size:12px}.layui-btn-xs i{font-size:14px!important}.layui-btn-group{display:inline-block;vertical-align:middle;font-size:0}.layui-btn-group .layui-btn{margin-left:0!important;margin-right:0!important;border-left:1px solid rgba(255,255,255,.5);border-radius:0}.layui-btn-group .layui-btn-primary{border-left:none}.layui-btn-group .layui-btn-primary:hover{border-color:#C9C9C9;color:#009688}.layui-btn-group .layui-btn:first-child{border-left:none;border-radius:2px 0 0 2px}.layui-btn-group .layui-btn-primary:first-child{border-left:1px solid #c9c9c9}.layui-btn-group .layui-btn:last-child{border-radius:0 2px 2px 0}.layui-btn-group .layui-btn+.layui-btn{margin-left:0}.layui-btn-group+.layui-btn-group{margin-left:10px}.layui-btn-fluid{width:100%}.layui-input,.layui-select,.layui-textarea{height:38px;line-height:1.3;line-height:38px\\9;border-width:1px;border-style:solid;background-color:#fff;border-radius:2px}.layui-input::-webkit-input-placeholder,.layui-select::-webkit-input-placeholder,.layui-textarea::-webkit-input-placeholder{line-height:1.3}.layui-input,.layui-textarea{display:block;width:100%;padding-left:10px}.layui-input:hover,.layui-textarea:hover{border-color:#D2D2D2!important}.layui-input:focus,.layui-textarea:focus{border-color:#C9C9C9!important}.layui-textarea{min-height:100px;height:auto;line-height:20px;padding:6px 10px;resize:vertical}.layui-select{padding:0 10px}.layui-form input[type=checkbox],.layui-form input[type=radio],.layui-form select{display:none}.layui-form [lay-ignore]{display:initial}.layui-form-item{margin-bottom:15px;clear:both;*zoom:1}.layui-form-item:after{content:'\\20';clear:both;*zoom:1;display:block;height:0}.layui-form-label{float:right;display:block;padding:9px 15px;width:100px;font-weight:400;line-height:20px;text-align:right;margin-left:40px}.layui-form-label-col{display:block;float:none;padding:9px 0;line-height:20px;text-align:left}.layui-form-item .layui-inline{margin-bottom:5px;margin-right:10px}.layui-input-block{margin-left:10px;min-height:36px}.layui-input-inline{display:inline-block;vertical-align:middle}.layui-form-item .layui-input-inline{float:left;width:190px;margin-right:10px}.layui-form-text .layui-input-inline{width:auto}.layui-form-mid{float:left;display:block;padding:9px 0!important;line-height:20px;margin-right:10px}.layui-form-danger+.layui-form-select .layui-input,.layui-form-danger:focus{border-color:#FF5722!important}.layui-form-select .layui-input{padding-right:30px;cursor:pointer}.layui-form-select .layui-edge{position:absolute;right:10px;top:50%;margin-top:-3px;cursor:pointer;border-width:6px;border-top-color:#c2c2c2;border-top-style:solid;transition:all .3s;-webkit-transition:all .3s}.layui-form-select dl{display:none;position:absolute;left:0;top:42px;padding:5px 0;z-index:999;min-width:100%;border:1px solid #d2d2d2;max-height:300px;overflow-y:auto;background-color:#fff;border-radius:2px;box-shadow:0 2px 4px rgba(0,0,0,.12);box-sizing:border-box}.layui-form-select dl dd,.layui-form-select dl dt{padding:0 10px;line-height:36px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.layui-form-select dl dt{font-size:12px;color:#999}.layui-form-select dl dd{cursor:pointer}.layui-form-select dl dd:hover{background-color:#f2f2f2}.layui-form-select .layui-select-group dd{padding-left:20px}.layui-form-select dl dd.layui-select-tips{padding-left:10px!important;color:#999}.layui-form-select dl dd.layui-this{background-color:#5FB878;color:#fff}.layui-form-checkbox,.layui-form-select dl dd.layui-disabled{background-color:#fff}.layui-form-selected dl{display:block}.layui-form-checkbox,.layui-form-checkbox *,.layui-form-switch{display:inline-block;vertical-align:middle}.layui-form-selected .layui-edge{margin-top:-9px;-webkit-transform:rotate(180deg);transform:rotate(180deg);margin-top:-3px\\9}:root .layui-form-selected .layui-edge{margin-top:-9px\\0/IE9}.layui-form-selectup dl{top:auto;bottom:42px}.layui-select-none{margin:5px 0;text-align:center;color:#999}.layui-select-disabled .layui-disabled{border-color:#eee!important}.layui-select-disabled .layui-edge{border-top-color:#d2d2d2}.layui-form-checkbox{position:relative;height:30px;line-height:28px;margin-right:10px;padding-right:30px;border:1px solid #d2d2d2;cursor:pointer;font-size:0;border-radius:2px;-webkit-transition:.1s linear;transition:.1s linear;box-sizing:border-box}.layui-form-checkbox:hover{border:1px solid #c2c2c2}.layui-form-checkbox span{padding:0 10px;height:100%;font-size:14px;background-color:#d2d2d2;color:#fff;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.layui-form-checkbox:hover span{background-color:#c2c2c2}.layui-form-checkbox i{position:absolute;right:0;width:30px;color:#fff;font-size:20px;text-align:center}.layui-form-checkbox:hover i{color:#c2c2c2}.layui-form-checked,.layui-form-checked:hover{border-color:#5FB878}.layui-form-checked span,.layui-form-checked:hover span{background-color:#5FB878}.layui-form-checked i,.layui-form-checked:hover i{color:#5FB878}.layui-form-item .layui-form-checkbox{margin-top:4px}.layui-form-checkbox[lay-skin=primary]{height:auto!important;line-height:normal!important;border:none!important;margin-right:0;padding-right:0;background:0 0}.layui-form-checkbox[lay-skin=primary] span{float:right;padding-right:15px;line-height:18px;background:0 0;color:#666}.layui-form-checkbox[lay-skin=primary] i{position:relative;top:0;width:16px;height:16px;line-height:16px;border:1px solid #d2d2d2;font-size:12px;border-radius:2px;background-color:#fff;-webkit-transition:.1s linear;transition:.1s linear}.layui-form-checkbox[lay-skin=primary]:hover i{border-color:#5FB878;color:#fff}.layui-form-checked[lay-skin=primary] i{border-color:#5FB878;background-color:#5FB878;color:#fff}.layui-checkbox-disbaled[lay-skin=primary] span{background:0 0!important;color:#c2c2c2}.layui-checkbox-disbaled[lay-skin=primary]:hover i{border-color:#d2d2d2}.layui-form-item .layui-form-checkbox[lay-skin=primary]{margin-top:10px}.layui-form-switch{position:relative;height:22px;line-height:22px;width:42px;padding:0 5px;margin-top:8px;border:1px solid #d2d2d2;border-radius:20px;cursor:pointer;background-color:#fff;-webkit-transition:.1s linear;transition:.1s linear}.layui-form-switch i{position:absolute;left:5px;top:3px;width:16px;height:16px;border-radius:20px;background-color:#d2d2d2;-webkit-transition:.1s linear;transition:.1s linear}.layui-form-switch em{position:absolute;right:5px;top:0;width:25px;padding:0!important;text-align:center!important;color:#999!important;font-style:normal!important;font-size:12px}.layui-form-onswitch{border-color:#5FB878;background-color:#5FB878}.layui-form-onswitch i{left:32px;background-color:#fff}.layui-form-onswitch em{left:5px;right:auto;color:#fff!important}.layui-checkbox-disbaled{border-color:#e2e2e2!important}.layui-checkbox-disbaled span{background-color:#e2e2e2!important}.layui-checkbox-disbaled:hover i{color:#fff!important}[lay-radio]{display:none}.layui-form-radio,.layui-form-radio *{display:inline-block;vertical-align:middle}.layui-form-radio{line-height:28px;margin:6px 10px 0 0;padding-right:10px;cursor:pointer;font-size:0}.layui-form-radio *{font-size:14px}.layui-form-radio>i{margin-right:8px;font-size:22px;color:#c2c2c2}.layui-form-radio>i:hover,.layui-form-radioed>i{color:#5FB878}.layui-radio-disbaled>i{color:#e2e2e2!important}.layui-form-pane .layui-form-label{width:110px;padding:8px 15px;height:38px;line-height:20px;border-width:1px;border-style:solid;border-radius:2px 0 0 2px;text-align:center;background-color:#FBFBFB;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;box-sizing:border-box}.layui-form-pane .layui-input-inline{margin-left:-1px}.layui-form-pane .layui-input-block{margin-left:110px;left:-1px}.layui-form-pane .layui-input{border-radius:0 2px 2px 0}.layui-form-pane .layui-form-text .layui-form-label{float:none;width:100%;border-radius:2px;box-sizing:border-box;text-align:left}.layui-form-pane .layui-form-text .layui-input-inline{display:block;margin:0;top:-1px;clear:both}.layui-form-pane .layui-form-text .layui-input-block{margin:0;left:0;top:-1px}.layui-form-pane .layui-form-text .layui-textarea{min-height:100px;border-radius:0 0 2px 2px}.layui-form-pane .layui-form-checkbox{margin:4px 0 4px 10px}.layui-form-pane .layui-form-radio,.layui-form-pane .layui-form-switch{margin-top:6px;margin-left:10px}.layui-form-pane .layui-form-item[pane]{position:relative;border-width:1px;border-style:solid}.layui-form-pane .layui-form-item[pane] .layui-form-label{position:absolute;left:0;top:0;height:100%;border-width:0 1px 0 0}.layui-form-pane .layui-form-item[pane] .layui-input-inline{margin-left:110px}@media screen and (max-width:450px){.layui-form-item .layui-form-label{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-form-item .layui-inline{display:block;margin-right:0;margin-bottom:20px;clear:both}.layui-form-item .layui-inline:after{content:'\\20';clear:both;display:block;height:0}.layui-form-item .layui-input-inline{display:block;float:none;left:-3px;width:auto;margin:0 0 10px 112px}.layui-form-item .layui-input-inline+.layui-form-mid{margin-left:110px;top:-5px;padding:0}.layui-form-item .layui-form-checkbox{margin-right:5px;margin-bottom:5px}}.layui-layedit{border-width:1px;border-style:solid;border-radius:2px}.layui-layedit-tool{padding:3px 5px;border-bottom-width:1px;border-bottom-style:solid;font-size:0}.layedit-tool-fixed{position:fixed;top:0;border-top:1px solid #e2e2e2}.layui-layedit-tool .layedit-tool-mid,.layui-layedit-tool .layui-icon{display:inline-block;vertical-align:middle;text-align:center;font-size:14px}.layui-layedit-tool .layui-icon{position:relative;width:32px;height:30px;line-height:30px;margin:3px 5px;color:#777;cursor:pointer;border-radius:2px}.layui-layedit-tool .layui-icon:hover{color:#393D49}.layui-layedit-tool .layui-icon:active{color:#000}.layui-layedit-tool .layedit-tool-active{background-color:#e2e2e2;color:#000}.layui-layedit-tool .layui-disabled,.layui-layedit-tool .layui-disabled:hover{color:#d2d2d2;cursor:not-allowed}.layui-layedit-tool .layedit-tool-mid{width:1px;height:18px;margin:0 10px;background-color:#d2d2d2}.layedit-tool-html{width:50px!important;font-size:30px!important}.layedit-tool-b,.layedit-tool-code,.layedit-tool-help{font-size:16px!important}.layedit-tool-d,.layedit-tool-face,.layedit-tool-image,.layedit-tool-unlink{font-size:18px!important}.layedit-tool-image input{position:absolute;font-size:0;left:0;top:0;width:100%;height:100%;opacity:.01;filter:Alpha(opacity=1);cursor:pointer}.layui-layedit-iframe iframe{display:block;width:100%}#LAY_layedit_code{overflow:hidden}.layui-laypage{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;margin:10px 0;font-size:0}.layui-laypage>a:first-child,.layui-laypage>a:first-child em{border-radius:2px 0 0 2px}.layui-laypage>a:last-child,.layui-laypage>a:last-child em{border-radius:0 2px 2px 0}.layui-laypage>:first-child{margin-left:0!important}.layui-laypage>:last-child{margin-right:0!important}.layui-laypage a,.layui-laypage button,.layui-laypage input,.layui-laypage select,.layui-laypage span{border:1px solid #e2e2e2}.layui-laypage a,.layui-laypage span{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;padding:0 15px;height:28px;line-height:28px;margin:0 -1px 5px 0;background-color:#fff;color:#333;font-size:12px}.layui-laypage a:hover{color:#009688}.layui-laypage em{font-style:normal}.layui-laypage .layui-laypage-spr{color:#999;font-weight:700}.layui-laypage a{text-decoration:none}.layui-laypage .layui-laypage-curr{position:relative}.layui-laypage .layui-laypage-curr em{position:relative;color:#fff}.layui-laypage .layui-laypage-curr .layui-laypage-em{position:absolute;left:-1px;top:-1px;padding:1px;width:100%;height:100%;background-color:#009688}.layui-laypage-em{border-radius:2px}.layui-laypage-next em,.layui-laypage-prev em{font-family:Sim sun;font-size:16px}.layui-laypage .layui-laypage-count,.layui-laypage .layui-laypage-limits,.layui-laypage .layui-laypage-skip{margin-left:10px;margin-right:10px;padding:0;border:none}.layui-laypage .layui-laypage-limits{vertical-align:top}.layui-laypage select{height:22px;padding:3px;border-radius:2px;cursor:pointer}.layui-laypage .layui-laypage-skip{height:30px;line-height:30px;color:#999}.layui-laypage button,.layui-laypage input{height:30px;line-height:30px;border-radius:2px;vertical-align:top;background-color:#fff;box-sizing:border-box}.layui-laypage input{display:inline-block;width:40px;margin:0 10px;padding:0 3px;text-align:center}.layui-laypage input:focus,.layui-laypage select:focus{border-color:#009688!important}.layui-laypage button{margin-left:10px;padding:0 10px;cursor:pointer}.layui-table,.layui-table-view{margin:10px 0}.layui-flow-more{margin:10px 0;text-align:center;color:#999;font-size:14px}.layui-flow-more a{height:32px;line-height:32px}.layui-flow-more a *{display:inline-block;vertical-align:top}.layui-flow-more a cite{padding:0 20px;border-radius:3px;background-color:#eee;color:#333;font-style:normal}.layui-flow-more a cite:hover{opacity:.8}.layui-flow-more a i{font-size:30px;color:#737383}.layui-table{width:100%;background-color:#fff;color:#666}.layui-table tr{transition:all .3s;-webkit-transition:all .3s}.layui-table th{text-align:left;font-weight:400}.layui-table tbody tr:hover,.layui-table thead tr,.layui-table-click,.layui-table-header,.layui-table-hover,.layui-table-mend,.layui-table-patch,.layui-table-tool,.layui-table[lay-even] tr:nth-child(even){background-color:#f2f2f2}.layui-table td,.layui-table th,.layui-table-fixed-r,.layui-table-header,.layui-table-page,.layui-table-tips-main,.layui-table-tool,.layui-table-view,.layui-table[lay-skin=line],.layui-table[lay-skin=row]{border-width:1px;border-style:solid;border-color:#e6e6e6}.layui-table td,.layui-table th{position:relative;padding:9px 15px;min-height:20px;line-height:20px;font-size:14px}.layui-table[lay-skin=line] td,.layui-table[lay-skin=line] th{border-width:0 0 1px}.layui-table[lay-skin=row] td,.layui-table[lay-skin=row] th{border-width:0 1px 0 0}.layui-table[lay-skin=nob] td,.layui-table[lay-skin=nob] th{border:none}.layui-table img{max-width:100px}.layui-table[lay-size=lg] td,.layui-table[lay-size=lg] th{padding:15px 30px}.layui-table-view .layui-table[lay-size=lg] .layui-table-cell{height:40px;line-height:40px}.layui-table[lay-size=sm] td,.layui-table[lay-size=sm] th{font-size:12px;padding:5px 10px}.layui-table-view .layui-table[lay-size=sm] .layui-table-cell{height:20px;line-height:20px}.layui-table[lay-data]{display:none}.layui-table-box,.layui-table-view{position:relative;overflow:hidden}.layui-table-view .layui-table{position:relative;width:auto;margin:0}.layui-table-body,.layui-table-header .layui-table,.layui-table-page{margin-bottom:-1px}.layui-table-view .layui-table[lay-skin=line]{border-width:0 1px 0 0}.layui-table-view .layui-table[lay-skin=row]{border-width:0 0 1px}.layui-table-view .layui-table td,.layui-table-view .layui-table th{padding:5px 0;border-top:none;border-left:none}.layui-table-view .layui-table td{cursor:default}.layui-table-view .layui-form-checkbox[lay-skin=primary] i{width:18px;height:18px}.layui-table-header{border-width:0 0 1px;overflow:hidden}.layui-table-sort{width:10px;height:20px;margin-left:5px;cursor:pointer!important}.layui-table-sort .layui-edge{position:absolute;left:5px;border-width:5px}.layui-table-sort .layui-table-sort-asc{top:4px;border-top:none;border-bottom-style:solid;border-bottom-color:#b2b2b2}.layui-table-sort .layui-table-sort-asc:hover{border-bottom-color:#666}.layui-table-sort .layui-table-sort-desc{bottom:4px;border-bottom:none;border-top-style:solid;border-top-color:#b2b2b2}.layui-table-sort .layui-table-sort-desc:hover{border-top-color:#666}.layui-table-sort[lay-sort=asc] .layui-table-sort-asc{border-bottom-color:#000}.layui-table-sort[lay-sort=desc] .layui-table-sort-desc{border-top-color:#000}.layui-table-cell{height:28px;line-height:28px;padding:0 15px;position:relative;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;box-sizing:border-box}.layui-table-cell .layui-form-checkbox[lay-skin=primary]{top:-1px;vertical-align:middle}.layui-table-cell .layui-table-link{color:#01AAED}.laytable-cell-checkbox,.laytable-cell-numbers,.laytable-cell-space{padding:0;text-align:center}.layui-table-body{position:relative;overflow:auto;margin-right:-1px}.layui-table-body .layui-none{line-height:40px;text-align:center;color:#999}.layui-table-fixed{position:absolute;left:0;top:0}.layui-table-fixed .layui-table-body{overflow:hidden}.layui-table-fixed-l{box-shadow:0 -1px 8px rgba(0,0,0,.08)}.layui-table-fixed-r{left:auto;right:-1px;border-width:0 0 0 1px;box-shadow:-1px 0 8px rgba(0,0,0,.08)}.layui-table-fixed-r .layui-table-header{position:relative;overflow:visible}.layui-table-mend{position:absolute;right:-49px;top:0;height:100%;width:50px}.layui-table-tool{position:relative;width:100%;height:50px;line-height:30px;padding:10px 15px;border-width:0 0 1px}.layui-table-page{position:relative;width:100%;padding:7px 7px 0;border-width:1px 0 0;height:41px;font-size:12px}.layui-table-page>div{height:26px}.layui-table-page .layui-laypage{margin:0}.layui-table-page .layui-laypage a,.layui-table-page .layui-laypage span{height:26px;line-height:26px;margin-bottom:10px;border:none;background:0 0}.layui-table-page .layui-laypage a,.layui-table-page .layui-laypage span.layui-laypage-curr{padding:0 12px}.layui-table-page .layui-laypage span{margin-left:0;padding:0}.layui-table-page .layui-laypage .layui-laypage-prev{margin-left:-7px!important}.layui-table-page .layui-laypage .layui-laypage-curr .layui-laypage-em{left:0;top:0;padding:0}.layui-table-page .layui-laypage button,.layui-table-page .layui-laypage input{height:26px;line-height:26px}.layui-table-page .layui-laypage input{width:40px}.layui-table-page .layui-laypage button{padding:0 10px}.layui-table-page select{height:18px}.layui-table-view select[lay-ignore]{display:inline-block}.layui-table-patch .layui-table-cell{padding:0;width:30px}.layui-table-edit{position:absolute;left:0;top:0;width:100%;height:100%;padding:0 14px 1px;border-radius:0;box-shadow:1px 1px 20px rgba(0,0,0,.15)}.layui-table-edit:focus{border-color:#5FB878!important}select.layui-table-edit{padding:0 0 0 10px;border-color:#C9C9C9}.layui-table-view .layui-form-checkbox,.layui-table-view .layui-form-radio,.layui-table-view .layui-form-switch{top:0;margin:0;box-sizing:content-box}.layui-table-view .layui-form-checkbox{top:-1px;height:26px;line-height:26px}body .layui-table-tips .layui-layer-content{background:0 0;padding:0;box-shadow:0 1px 6px rgba(0,0,0,.1)}.layui-table-tips-main{margin:-44px 0 0 -1px;max-height:150px;padding:8px 15px;font-size:14px;overflow-y:scroll;background-color:#fff;color:#333}.layui-code,.layui-upload-list{margin:10px 0}.layui-table-tips-c{position:absolute;right:-3px;top:-12px;width:18px;height:18px;padding:3px;text-align:center;font-weight:700;border-radius:100%;font-size:14px;cursor:pointer;background-color:#666}.layui-table-tips-c:hover{background-color:#999}.layui-upload-file{display:none!important;opacity:.01;filter:Alpha(opacity=1)}.layui-upload-drag,.layui-upload-form,.layui-upload-wrap{display:inline-block}.layui-upload-choose{padding:0 10px;color:#999}.layui-upload-drag{position:relative;padding:30px;border:1px dashed #e2e2e2;background-color:#fff;text-align:center;cursor:pointer;color:#999}.layui-upload-drag .layui-icon{font-size:50px;color:#009688}.layui-upload-drag[lay-over]{border-color:#009688}.layui-upload-iframe{position:absolute;width:0;height:0;border:0;visibility:hidden}.layui-upload-wrap{position:relative;vertical-align:middle}.layui-upload-wrap .layui-upload-file{display:block!important;position:absolute;left:0;top:0;z-index:10;font-size:100px;width:100%;height:100%;opacity:.01;filter:Alpha(opacity=1);cursor:pointer}.layui-code{position:relative;padding:15px;line-height:20px;border:1px solid #ddd;border-left-width:6px;background-color:#F2F2F2;color:#333;font-family:Courier New;font-size:12px}.layui-tree{line-height:26px}.layui-tree li{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-tree li .layui-tree-spread,.layui-tree li a{display:inline-block;vertical-align:top;height:26px;*display:inline;*zoom:1;cursor:pointer}.layui-tree li a{font-size:0}.layui-tree li a i{font-size:16px}.layui-tree li a cite{padding:0 6px;font-size:14px;font-style:normal}.layui-tree li i{padding-left:6px;color:#333;-moz-user-select:none}.layui-tree li .layui-tree-check{font-size:13px}.layui-tree li .layui-tree-check:hover{color:#009E94}.layui-tree li ul{display:none;margin-left:20px}.layui-tree li .layui-tree-enter{line-height:24px;border:1px dotted #000}.layui-tree-drag{display:none;position:absolute;left:-666px;top:-666px;background-color:#f2f2f2;padding:5px 10px;border:1px dotted #000;white-space:nowrap}.layui-tree-drag i{padding-right:5px}.layui-nav{position:relative;padding:0 20px;background-color:#393D49;color:#fff;border-radius:2px;font-size:0;box-sizing:border-box}.layui-nav *{font-size:14px}.layui-nav .layui-nav-item{position:relative;display:inline-block;*display:inline;*zoom:1;vertical-align:middle;line-height:60px}.layui-nav .layui-nav-item a{display:block;padding:0 20px;color:#fff;color:rgba(255,255,255,.7);transition:all .3s;-webkit-transition:all .3s}.layui-nav .layui-this:after,.layui-nav-bar,.layui-nav-tree .layui-nav-itemed:after{position:absolute;left:0;top:0;width:0;height:5px;background-color:#5FB878;transition:all .2s;-webkit-transition:all .2s}.layui-nav-bar{z-index:1000}.layui-nav .layui-nav-item a:hover,.layui-nav .layui-this a{color:#fff}.layui-nav .layui-this:after{content:'';top:auto;bottom:0;width:100%}.layui-nav-img{width:30px;height:30px;margin-right:10px;border-radius:50%}.layui-nav .layui-nav-more{content:'';width:0;height:0;border-style:solid dashed dashed;border-color:#fff transparent transparent;overflow:hidden;cursor:pointer;transition:all .2s;-webkit-transition:all .2s;position:absolute;top:50%;right:3px;margin-top:-3px;border-width:6px;border-top-color:rgba(255,255,255,.7)}.layui-nav .layui-nav-mored,.layui-nav-itemed .layui-nav-more{margin-top:-9px;border-style:dashed dashed solid;border-color:transparent transparent #fff}.layui-nav-child{display:none;position:absolute;left:0;top:65px;min-width:100%;line-height:36px;padding:5px 0;box-shadow:0 2px 4px rgba(0,0,0,.12);border:1px solid #d2d2d2;background-color:#fff;z-index:100;border-radius:2px;white-space:nowrap}.layui-nav .layui-nav-child a{color:#333}.layui-nav .layui-nav-child a:hover{background-color:#f2f2f2;color:#000}.layui-nav-child dd{position:relative}.layui-nav .layui-nav-child dd.layui-this a,.layui-nav-child dd.layui-this{background-color:#5FB878;color:#fff}.layui-nav-child dd.layui-this:after{display:none}.layui-nav-tree{width:200px;padding:0}.layui-nav-tree .layui-nav-item{display:block;width:100%;line-height:45px}.layui-nav-tree .layui-nav-item a{height:45px;line-height:45px;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-nav-tree .layui-nav-item a:hover{background-color:#4E5465}.layui-nav-tree .layui-nav-bar{width:5px;height:0;background-color:#009688}.layui-nav-tree .layui-nav-child dd.layui-this,.layui-nav-tree .layui-nav-child dd.layui-this a,.layui-nav-tree .layui-this,.layui-nav-tree .layui-this>a,.layui-nav-tree .layui-this>a:hover{background-color:#009688;color:#fff}.layui-nav-tree .layui-this:after{display:none}.layui-nav-itemed>a,.layui-nav-tree .layui-nav-title a,.layui-nav-tree .layui-nav-title a:hover{color:#fff!important}.layui-nav-tree .layui-nav-child{position:relative;z-index:0;top:0;border:none;box-shadow:none}.layui-nav-tree .layui-nav-child a{height:40px;line-height:40px;color:#fff;color:rgba(255,255,255,.7)}.layui-nav-tree .layui-nav-child,.layui-nav-tree .layui-nav-child a:hover{background:0 0;color:#fff}.layui-nav-tree .layui-nav-more{top:20px;right:10px;margin:0}.layui-nav-itemed .layui-nav-more{top:14px}.layui-nav-itemed .layui-nav-child{display:block;padding:0;background-color:rgba(0,0,0,.3)!important}.layui-nav-side{position:fixed;top:0;bottom:0;left:0;overflow-x:hidden;z-index:999}.layui-bg-blue .layui-nav-bar,.layui-bg-blue .layui-nav-itemed:after,.layui-bg-blue .layui-this:after{background-color:#93D1FF}.layui-bg-blue .layui-nav-child dd.layui-this{background-color:#1E9FFF}.layui-bg-blue .layui-nav-itemed>a,.layui-nav-tree.layui-bg-blue .layui-nav-title a,.layui-nav-tree.layui-bg-blue .layui-nav-title a:hover{background-color:#007DDB!important}.layui-breadcrumb{visibility:hidden;font-size:0}.layui-breadcrumb>*{font-size:14px}.layui-breadcrumb a{color:#999!important}.layui-breadcrumb a:hover{color:#5FB878!important}.layui-breadcrumb a cite{color:#666;font-style:normal}.layui-breadcrumb span[lay-separator]{margin:0 10px;color:#999}.layui-tab{margin:10px 0;text-align:left!important}.layui-tab[overflow]>.layui-tab-title{overflow:hidden}.layui-tab-title{position:relative;left:0;height:40px;white-space:nowrap;font-size:0;border-bottom-width:1px;border-bottom-style:solid;transition:all .2s;-webkit-transition:all .2s}.layui-tab-title li{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;font-size:14px;transition:all .2s;-webkit-transition:all .2s;position:relative;line-height:40px;min-width:65px;padding:0 15px;text-align:center;cursor:pointer}.layui-tab-title li a{display:block}.layui-tab-title .layui-this{color:#000}.layui-tab-title .layui-this:after{position:absolute;left:0;top:0;content:'';width:100%;height:41px;border-width:1px;border-style:solid;border-bottom-color:#fff;border-radius:2px 2px 0 0;box-sizing:border-box;pointer-events:none}.layui-tab-bar{position:absolute;right:0;top:0;z-index:10;width:30px;height:39px;line-height:39px;border-width:1px;border-style:solid;border-radius:2px;text-align:center;background-color:#fff;cursor:pointer}.layui-tab-bar .layui-icon{position:relative;display:inline-block;top:3px;transition:all .3s;-webkit-transition:all .3s}.layui-tab-item{display:none}.layui-tab-more{padding-right:30px;height:auto!important;white-space:normal!important}.layui-tab-more li.layui-this:after{border-bottom-color:#e2e2e2;border-radius:2px}.layui-tab-more .layui-tab-bar .layui-icon{top:-2px;top:3px\\9;-webkit-transform:rotate(180deg);transform:rotate(180deg)}:root .layui-tab-more .layui-tab-bar .layui-icon{top:-2px\\0/IE9}.layui-tab-content{padding:10px}.layui-tab-title li .layui-tab-close{position:relative;display:inline-block;width:18px;height:18px;line-height:20px;margin-left:8px;top:1px;text-align:center;font-size:14px;color:#c2c2c2;transition:all .2s;-webkit-transition:all .2s}.layui-tab-title li .layui-tab-close:hover{border-radius:2px;background-color:#FF5722;color:#fff}.layui-tab-brief>.layui-tab-title .layui-this{color:#009688}.layui-tab-brief>.layui-tab-more li.layui-this:after,.layui-tab-brief>.layui-tab-title .layui-this:after{border:none;border-radius:0;border-bottom:2px solid #5FB878}.layui-tab-brief[overflow]>.layui-tab-title .layui-this:after{top:-1px}.layui-tab-card{border-width:1px;border-style:solid;border-radius:2px;box-shadow:0 2px 5px 0 rgba(0,0,0,.1)}.layui-tab-card>.layui-tab-title{background-color:#f2f2f2}.layui-tab-card>.layui-tab-title li{margin-right:-1px;margin-left:-1px}.layui-tab-card>.layui-tab-title .layui-this{background-color:#fff}.layui-tab-card>.layui-tab-title .layui-this:after{border-top:none;border-width:1px;border-bottom-color:#fff}.layui-tab-card>.layui-tab-title .layui-tab-bar{height:40px;line-height:40px;border-radius:0;border-top:none;border-right:none}.layui-tab-card>.layui-tab-more .layui-this{background:0 0;color:#5FB878}.layui-tab-card>.layui-tab-more .layui-this:after{border:none}.layui-timeline{padding-left:5px}.layui-timeline-item{position:relative;padding-bottom:20px}.layui-timeline-axis{position:absolute;left:-5px;top:0;z-index:10;width:20px;height:20px;line-height:20px;background-color:#fff;color:#5FB878;border-radius:50%;text-align:center;cursor:pointer}.layui-timeline-axis:hover{color:#FF5722}.layui-timeline-item:before{content:'';position:absolute;left:5px;top:0;z-index:0;width:1px;height:100%}.layui-timeline-item:last-child:before{display:none}.layui-timeline-item:first-child:before{display:block}.layui-timeline-content{padding-left:25px}.layui-timeline-title{position:relative;margin-bottom:10px}.layui-badge,.layui-badge-dot,.layui-badge-rim{position:relative;display:inline-block;padding:0 6px;font-size:12px;text-align:center;background-color:#FF5722;color:#fff;border-radius:2px}.layui-badge{height:18px;line-height:18px}.layui-badge-dot{width:8px;height:8px;padding:0;border-radius:50%}.layui-badge-rim{height:18px;line-height:18px;border-width:1px;border-style:solid;background-color:#fff;color:#666}.layui-btn .layui-badge,.layui-btn .layui-badge-dot{margin-left:5px}.layui-nav .layui-badge,.layui-nav .layui-badge-dot{position:absolute;top:50%;margin:-8px 6px 0}.layui-tab-title .layui-badge,.layui-tab-title .layui-badge-dot{left:5px;top:-2px}.layui-carousel{position:relative;left:0;top:0;background-color:#f8f8f8}.layui-carousel>[carousel-item]{position:relative;width:100%;height:100%;overflow:hidden}.layui-carousel>[carousel-item]:before{position:absolute;content:'\\e63d';left:50%;top:50%;width:100px;line-height:20px;margin:-10px 0 0 -50px;text-align:center;color:#c2c2c2;font-family:layui-icon!important;font-size:30px;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.layui-carousel>[carousel-item]>*{display:none;position:absolute;left:0;top:0;width:100%;height:100%;background-color:#f8f8f8;transition-duration:.3s;-webkit-transition-duration:.3s}.layui-carousel-updown>*{-webkit-transition:.3s ease-in-out up;transition:.3s ease-in-out up}.layui-carousel-arrow{display:none\\9;opacity:0;position:absolute;left:10px;top:50%;margin-top:-18px;width:36px;height:36px;line-height:36px;text-align:center;font-size:20px;border:0;border-radius:50%;background-color:rgba(0,0,0,.2);color:#fff;-webkit-transition-duration:.3s;transition-duration:.3s;cursor:pointer}.layui-carousel-arrow[lay-type=add]{left:auto!important;right:10px}.layui-carousel:hover .layui-carousel-arrow[lay-type=add],.layui-carousel[lay-arrow=always] .layui-carousel-arrow[lay-type=add]{right:20px}.layui-carousel[lay-arrow=always] .layui-carousel-arrow{opacity:1;left:20px}.layui-carousel[lay-arrow=none] .layui-carousel-arrow{display:none}.layui-carousel-arrow:hover,.layui-carousel-ind ul:hover{background-color:rgba(0,0,0,.35)}.layui-carousel:hover .layui-carousel-arrow{display:block\\9;opacity:1;left:20px}.layui-carousel-ind{position:relative;top:-35px;width:100%;line-height:0!important;text-align:center;font-size:0}.layui-carousel[lay-indicator=outside]{margin-bottom:30px}.layui-carousel[lay-indicator=outside] .layui-carousel-ind{top:10px}.layui-carousel[lay-indicator=outside] .layui-carousel-ind ul{background-color:rgba(0,0,0,.5)}.layui-carousel[lay-indicator=none] .layui-carousel-ind{display:none}.layui-carousel-ind ul{display:inline-block;padding:5px;background-color:rgba(0,0,0,.2);border-radius:10px;-webkit-transition-duration:.3s;transition-duration:.3s}.layui-carousel-ind li{display:inline-block;width:10px;height:10px;margin:0 3px;font-size:14px;background-color:#e2e2e2;background-color:rgba(255,255,255,.5);border-radius:50%;cursor:pointer;-webkit-transition-duration:.3s;transition-duration:.3s}.layui-carousel-ind li:hover{background-color:rgba(255,255,255,.7)}.layui-carousel-ind li.layui-this{background-color:#fff}.layui-carousel>[carousel-item]>.layui-carousel-next,.layui-carousel>[carousel-item]>.layui-carousel-prev,.layui-carousel>[carousel-item]>.layui-this{display:block}.layui-carousel>[carousel-item]>.layui-this{left:0}.layui-carousel>[carousel-item]>.layui-carousel-prev{left:-100%}.layui-carousel>[carousel-item]>.layui-carousel-next{left:100%}.layui-carousel>[carousel-item]>.layui-carousel-next.layui-carousel-left,.layui-carousel>[carousel-item]>.layui-carousel-prev.layui-carousel-right{left:0}.layui-carousel>[carousel-item]>.layui-this.layui-carousel-left{left:-100%}.layui-carousel>[carousel-item]>.layui-this.layui-carousel-right{left:100%}.layui-carousel[lay-anim=updown] .layui-carousel-arrow{left:50%!important;top:20px;margin:0 0 0 -18px}.layui-carousel[lay-anim=updown]>[carousel-item]>*,.layui-carousel[lay-anim=fade]>[carousel-item]>*{left:0!important}.layui-carousel[lay-anim=updown] .layui-carousel-arrow[lay-type=add]{top:auto!important;bottom:20px}.layui-carousel[lay-anim=updown] .layui-carousel-ind{position:absolute;top:50%;right:20px;width:auto;height:auto}.layui-carousel[lay-anim=updown] .layui-carousel-ind ul{padding:3px 5px}.layui-carousel[lay-anim=updown] .layui-carousel-ind li{display:block;margin:6px 0}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-this{top:0}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-carousel-prev{top:-100%}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-carousel-next{top:100%}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-carousel-next.layui-carousel-left,.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-carousel-prev.layui-carousel-right{top:0}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-this.layui-carousel-left{top:-100%}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-this.layui-carousel-right{top:100%}.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-carousel-next,.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-carousel-prev{opacity:0}.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-carousel-next.layui-carousel-left,.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-carousel-prev.layui-carousel-right{opacity:1}.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-this.layui-carousel-left,.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-this.layui-carousel-right{opacity:0}.layui-fixbar{position:fixed;right:15px;bottom:15px;z-index:9999}.layui-fixbar li{width:50px;height:50px;line-height:50px;margin-bottom:1px;text-align:center;cursor:pointer;font-size:30px;background-color:#9F9F9F;color:#fff;border-radius:2px;opacity:.95}.layui-fixbar li:hover{opacity:.85}.layui-fixbar li:active{opacity:1}.layui-fixbar .layui-fixbar-top{display:none;font-size:40px}body .layui-util-face{border:none;background:0 0}body .layui-util-face .layui-layer-content{padding:0;background-color:#fff;color:#666;box-shadow:none}.layui-util-face .layui-layer-TipsG{display:none}.layui-util-face ul{position:relative;width:372px;padding:10px;border:1px solid #D9D9D9;background-color:#fff;box-shadow:0 0 20px rgba(0,0,0,.2)}.layui-util-face ul li{cursor:pointer;float:left;border:1px solid #e8e8e8;height:22px;width:26px;overflow:hidden;margin:-1px 0 0 -1px;padding:4px 2px;text-align:center}.layui-util-face ul li:hover{position:relative;z-index:2;border:1px solid #eb7350;background:#fff9ec}.layui-anim{-webkit-animation-duration:.3s;animation-duration:.3s;-webkit-animation-fill-mode:both;animation-fill-mode:both}.layui-anim.layui-icon{display:inline-block}.layui-anim-loop{-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}@-webkit-keyframes layui-rotate{from{-webkit-transform:rotate(0)}to{-webkit-transform:rotate(360deg)}}@keyframes layui-rotate{from{transform:rotate(0)}to{transform:rotate(360deg)}}.layui-anim-rotate{-webkit-animation-name:layui-rotate;animation-name:layui-rotate;-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-timing-function:linear;animation-timing-function:linear}@-webkit-keyframes layui-up{from{-webkit-transform:translate3d(0,100%,0);opacity:.3}to{-webkit-transform:translate3d(0,0,0);opacity:1}}@keyframes layui-up{from{transform:translate3d(0,100%,0);opacity:.3}to{transform:translate3d(0,0,0);opacity:1}}.layui-anim-up{-webkit-animation-name:layui-up;animation-name:layui-up}@-webkit-keyframes layui-upbit{from{-webkit-transform:translate3d(0,30px,0);opacity:.3}to{-webkit-transform:translate3d(0,0,0);opacity:1}}@keyframes layui-upbit{from{transform:translate3d(0,30px,0);opacity:.3}to{transform:translate3d(0,0,0);opacity:1}}.layui-anim-upbit{-webkit-animation-name:layui-upbit;animation-name:layui-upbit}@-webkit-keyframes layui-scale{0%{opacity:.3;-webkit-transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1)}}@keyframes layui-scale{0%{opacity:.3;-ms-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-ms-transform:scale(1);transform:scale(1)}}.layui-anim-scale{-webkit-animation-name:layui-scale;animation-name:layui-scale}@-webkit-keyframes layui-scale-spring{0%{opacity:.5;-webkit-transform:scale(.5)}80%{opacity:.8;-webkit-transform:scale(1.1)}100%{opacity:1;-webkit-transform:scale(1)}}@keyframes layui-scale-spring{0%{opacity:.5;transform:scale(.5)}80%{opacity:.8;transform:scale(1.1)}100%{opacity:1;transform:scale(1)}}.layui-anim-scaleSpring{-webkit-animation-name:layui-scale-spring;animation-name:layui-scale-spring}@-webkit-keyframes layui-fadein{0%{opacity:0}100%{opacity:1}}@keyframes layui-fadein{0%{opacity:0}100%{opacity:1}}.layui-anim-fadein{-webkit-animation-name:layui-fadein;animation-name:layui-fadein}@-webkit-keyframes layui-fadeout{0%{opacity:1}100%{opacity:0}}@keyframes layui-fadeout{0%{opacity:1}100%{opacity:0}}.layui-anim-fadeout{-webkit-animation-name:layui-fadeout;animation-name:layui-fadeout}"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/layui/css/layui.mobile.css",
    "content": "/** layui-v2.2.5 MIT License By https://www.layui.com */\n blockquote,body,button,dd,div,dl,dt,form,h1,h2,h3,h4,h5,h6,input,legend,li,ol,p,td,textarea,th,ul{margin:0;padding:0;-webkit-tap-highlight-color:rgba(0,0,0,0)}html{font:12px 'Helvetica Neue','PingFang SC',STHeitiSC-Light,Helvetica,Arial,sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}a,button,input{-webkit-tap-highlight-color:rgba(255,0,0,0)}a{text-decoration:none;background:0 0}a:active,a:hover{outline:0}table{border-collapse:collapse;border-spacing:0}li{list-style:none}b,strong{font-weight:700}h1,h2,h3,h4,h5,h6{font-weight:500}address,cite,dfn,em,var{font-style:normal}dfn{font-style:italic}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}img{border:0;vertical-align:bottom}.layui-inline,input,label{vertical-align:middle}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0;outline:0}button,select{text-transform:none}select{-webkit-appearance:none;border:none}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}@font-face{font-family:layui-icon;src:url(../font/iconfont.eot?v=1.0.7);src:url(../font/iconfont.eot?v=1.0.7#iefix) format('embedded-opentype'),url(../font/iconfont.woff?v=1.0.7) format('woff'),url(../font/iconfont.ttf?v=1.0.7) format('truetype'),url(../font/iconfont.svg?v=1.0.7#iconfont) format('svg')}.layui-icon{font-family:layui-icon!important;font-size:16px;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.layui-box,.layui-box *{-webkit-box-sizing:content-box!important;-moz-box-sizing:content-box!important;box-sizing:content-box!important}.layui-border-box,.layui-border-box *{-webkit-box-sizing:border-box!important;-moz-box-sizing:border-box!important;box-sizing:border-box!important}.layui-inline{position:relative;display:inline-block;*display:inline;*zoom:1}.layui-edge,.layui-upload-iframe{position:absolute;width:0;height:0}.layui-edge{border-style:dashed;border-color:transparent;overflow:hidden}.layui-elip{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-unselect{-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.layui-disabled,.layui-disabled:active{background-color:#d2d2d2!important;color:#fff!important;cursor:not-allowed!important}.layui-circle{border-radius:100%}.layui-show{display:block!important}.layui-hide{display:none!important}.layui-upload-iframe{border:0;visibility:hidden}.layui-upload-enter{border:1px solid #009E94;background-color:#009E94;color:#fff;-webkit-transform:scale(1.1);transform:scale(1.1)}@-webkit-keyframes layui-m-anim-scale{0%{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}@keyframes layui-m-anim-scale{0%{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}.layui-m-anim-scale{animation-name:layui-m-anim-scale;-webkit-animation-name:layui-m-anim-scale}@-webkit-keyframes layui-m-anim-up{0%{opacity:0;-webkit-transform:translateY(800px);transform:translateY(800px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes layui-m-anim-up{0%{opacity:0;-webkit-transform:translateY(800px);transform:translateY(800px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}.layui-m-anim-up{-webkit-animation-name:layui-m-anim-up;animation-name:layui-m-anim-up}@-webkit-keyframes layui-m-anim-left{0%{-webkit-transform:translateX(100%);transform:translateX(100%)}100%{-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes layui-m-anim-left{0%{-webkit-transform:translateX(100%);transform:translateX(100%)}100%{-webkit-transform:translateX(0);transform:translateX(0)}}.layui-m-anim-left{-webkit-animation-name:layui-m-anim-left;animation-name:layui-m-anim-left}@-webkit-keyframes layui-m-anim-right{0%{-webkit-transform:translateX(-100%);transform:translateX(-100%)}100%{-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes layui-m-anim-right{0%{-webkit-transform:translateX(-100%);transform:translateX(-100%)}100%{-webkit-transform:translateX(0);transform:translateX(0)}}.layui-m-anim-right{-webkit-animation-name:layui-m-anim-right;animation-name:layui-m-anim-right}@-webkit-keyframes layui-m-anim-lout{0%{-webkit-transform:translateX(0);transform:translateX(0)}100%{-webkit-transform:translateX(-100%);transform:translateX(-100%)}}@keyframes layui-m-anim-lout{0%{-webkit-transform:translateX(0);transform:translateX(0)}100%{-webkit-transform:translateX(-100%);transform:translateX(-100%)}}.layui-m-anim-lout{-webkit-animation-name:layui-m-anim-lout;animation-name:layui-m-anim-lout}@-webkit-keyframes layui-m-anim-rout{0%{-webkit-transform:translateX(0);transform:translateX(0)}100%{-webkit-transform:translateX(100%);transform:translateX(100%)}}@keyframes layui-m-anim-rout{0%{-webkit-transform:translateX(0);transform:translateX(0)}100%{-webkit-transform:translateX(100%);transform:translateX(100%)}}.layui-m-anim-rout{-webkit-animation-name:layui-m-anim-rout;animation-name:layui-m-anim-rout}.layui-m-layer{position:relative;z-index:19891014}.layui-m-layer *{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.layui-m-layermain,.layui-m-layershade{position:fixed;left:0;top:0;width:100%;height:100%}.layui-m-layershade{background-color:rgba(0,0,0,.7);pointer-events:auto}.layui-m-layermain{display:table;font-family:Helvetica,arial,sans-serif;pointer-events:none}.layui-m-layermain .layui-m-layersection{display:table-cell;vertical-align:middle;text-align:center}.layui-m-layerchild{position:relative;display:inline-block;text-align:left;background-color:#fff;font-size:14px;border-radius:5px;box-shadow:0 0 8px rgba(0,0,0,.1);pointer-events:auto;-webkit-overflow-scrolling:touch;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:.2s;animation-duration:.2s}.layui-m-layer0 .layui-m-layerchild{width:90%;max-width:640px}.layui-m-layer1 .layui-m-layerchild{border:none;border-radius:0}.layui-m-layer2 .layui-m-layerchild{width:auto;max-width:260px;min-width:40px;border:none;background:0 0;box-shadow:none;color:#fff}.layui-m-layerchild h3{padding:0 10px;height:60px;line-height:60px;font-size:16px;font-weight:400;border-radius:5px 5px 0 0;text-align:center}.layui-m-layerbtn span,.layui-m-layerchild h3{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-m-layercont{padding:50px 30px;line-height:22px;text-align:center}.layui-m-layer1 .layui-m-layercont{padding:0;text-align:left}.layui-m-layer2 .layui-m-layercont{text-align:center;padding:0;line-height:0}.layui-m-layer2 .layui-m-layercont i{width:25px;height:25px;margin-left:8px;display:inline-block;background-color:#fff;border-radius:100%;-webkit-animation:layui-m-anim-loading 1.4s infinite ease-in-out;animation:layui-m-anim-loading 1.4s infinite ease-in-out;-webkit-animation-fill-mode:both;animation-fill-mode:both}.layui-m-layerbtn,.layui-m-layerbtn span{position:relative;text-align:center;border-radius:0 0 5px 5px}.layui-m-layer2 .layui-m-layercont p{margin-top:20px}@-webkit-keyframes layui-m-anim-loading{0%,100%,80%{transform:scale(0);-webkit-transform:scale(0)}40%{transform:scale(1);-webkit-transform:scale(1)}}@keyframes layui-m-anim-loading{0%,100%,80%{transform:scale(0);-webkit-transform:scale(0)}40%{transform:scale(1);-webkit-transform:scale(1)}}.layui-m-layer2 .layui-m-layercont i:first-child{margin-left:0;-webkit-animation-delay:-.32s;animation-delay:-.32s}.layui-m-layer2 .layui-m-layercont i.layui-m-layerload{-webkit-animation-delay:-.16s;animation-delay:-.16s}.layui-m-layer2 .layui-m-layercont>div{line-height:22px;padding-top:7px;margin-bottom:20px;font-size:14px}.layui-m-layerbtn{display:box;display:-moz-box;display:-webkit-box;width:100%;height:50px;line-height:50px;font-size:0;border-top:1px solid #D0D0D0;background-color:#F2F2F2}.layui-m-layerbtn span{display:block;-moz-box-flex:1;box-flex:1;-webkit-box-flex:1;font-size:14px;cursor:pointer}.layui-m-layerbtn span[yes]{color:#40AFFE}.layui-m-layerbtn span[no]{border-right:1px solid #D0D0D0;border-radius:0 0 0 5px}.layui-m-layerbtn span:active{background-color:#F6F6F6}.layui-m-layerend{position:absolute;right:7px;top:10px;width:30px;height:30px;border:0;font-weight:400;background:0 0;cursor:pointer;-webkit-appearance:none;font-size:30px}.layui-m-layerend::after,.layui-m-layerend::before{position:absolute;left:5px;top:15px;content:'';width:18px;height:1px;background-color:#999;transform:rotate(45deg);-webkit-transform:rotate(45deg);border-radius:3px}.layui-m-layerend::after{transform:rotate(-45deg);-webkit-transform:rotate(-45deg)}body .layui-m-layer .layui-m-layer-footer{position:fixed;width:95%;max-width:100%;margin:0 auto;left:0;right:0;bottom:10px;background:0 0}.layui-m-layer-footer .layui-m-layercont{padding:20px;border-radius:5px 5px 0 0;background-color:rgba(255,255,255,.8)}.layui-m-layer-footer .layui-m-layerbtn{display:block;height:auto;background:0 0;border-top:none}.layui-m-layer-footer .layui-m-layerbtn span{background-color:rgba(255,255,255,.8)}.layui-m-layer-footer .layui-m-layerbtn span[no]{color:#FD482C;border-top:1px solid #c2c2c2;border-radius:0 0 5px 5px}.layui-m-layer-footer .layui-m-layerbtn span[yes]{margin-top:10px;border-radius:5px}body .layui-m-layer .layui-m-layer-msg{width:auto;max-width:90%;margin:0 auto;bottom:-150px;background-color:rgba(0,0,0,.7);color:#fff}.layui-m-layer-msg .layui-m-layercont{padding:10px 20px}"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/layui/css/modules/code.css",
    "content": "/** layui-v2.2.5 MIT License By https://www.layui.com */\n html #layuicss-skincodecss{display:none;position:absolute;width:1989px}.layui-code-h3,.layui-code-view{position:relative;font-size:12px}.layui-code-view{display:block;margin:10px 0;padding:0;border:1px solid #e2e2e2;border-left-width:6px;background-color:#F2F2F2;color:#333;font-family:Courier New}.layui-code-h3{padding:0 10px;height:32px;line-height:32px;border-bottom:1px solid #e2e2e2}.layui-code-h3 a{position:absolute;right:10px;top:0;color:#999}.layui-code-view .layui-code-ol{position:relative;overflow:auto}.layui-code-view .layui-code-ol li{position:relative;margin-left:45px;line-height:20px;padding:0 5px;border-left:1px solid #e2e2e2;list-style-type:decimal-leading-zero;*list-style-type:decimal;background-color:#fff}.layui-code-view pre{margin:0}.layui-code-notepad{border:1px solid #0C0C0C;border-left-color:#3F3F3F;background-color:#0C0C0C;color:#C2BE9E}.layui-code-notepad .layui-code-h3{border-bottom:none}.layui-code-notepad .layui-code-ol li{background-color:#3F3F3F;border-left:none}"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/layui/css/modules/laydate/default/laydate.css",
    "content": "/** layui-v2.2.5 MIT License By https://www.layui.com */\n .laydate-set-ym,.layui-laydate,.layui-laydate *,.layui-laydate-list{box-sizing:border-box}html #layuicss-laydate{display:none;position:absolute;width:1989px}.layui-laydate *{margin:0;padding:0}.layui-laydate{position:absolute;z-index:66666666;margin:5px 0;border-radius:2px;font-size:14px;-webkit-animation-duration:.3s;animation-duration:.3s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-name:laydate-upbit;animation-name:laydate-upbit}.layui-laydate-main{width:272px}.layui-laydate-content td,.layui-laydate-header *,.layui-laydate-list li{transition-duration:.3s;-webkit-transition-duration:.3s}@-webkit-keyframes laydate-upbit{from{-webkit-transform:translate3d(0,20px,0);opacity:.3}to{-webkit-transform:translate3d(0,0,0);opacity:1}}@keyframes laydate-upbit{from{transform:translate3d(0,20px,0);opacity:.3}to{transform:translate3d(0,0,0);opacity:1}}.layui-laydate-static{position:relative;z-index:0;display:inline-block;margin:0;-webkit-animation:none;animation:none}.laydate-ym-show .laydate-next-m,.laydate-ym-show .laydate-prev-m{display:none!important}.laydate-ym-show .laydate-next-y,.laydate-ym-show .laydate-prev-y{display:inline-block!important}.laydate-time-show .laydate-set-ym span[lay-type=month],.laydate-time-show .laydate-set-ym span[lay-type=year],.laydate-time-show .layui-laydate-header .layui-icon,.laydate-ym-show .laydate-set-ym span[lay-type=month]{display:none!important}.layui-laydate-header{position:relative;line-height:30px;padding:10px 70px 5px}.laydate-set-ym span,.layui-laydate-header i{padding:0 5px;cursor:pointer}.layui-laydate-header *{display:inline-block;vertical-align:bottom}.layui-laydate-header i{position:absolute;top:10px;color:#999;font-size:18px}.layui-laydate-header i.laydate-prev-y{left:15px}.layui-laydate-header i.laydate-prev-m{left:45px}.layui-laydate-header i.laydate-next-y{right:15px}.layui-laydate-header i.laydate-next-m{right:45px}.laydate-set-ym{width:100%;text-align:center;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.laydate-time-text{cursor:default!important}.layui-laydate-content{position:relative;padding:10px;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.layui-laydate-content table{border-collapse:collapse;border-spacing:0}.layui-laydate-content td,.layui-laydate-content th{width:36px;height:30px;padding:5px;text-align:center}.layui-laydate-content td{position:relative;cursor:pointer}.laydate-day-mark{position:absolute;left:0;top:0;width:100%;height:100%;line-height:30px;font-size:12px;overflow:hidden}.laydate-day-mark::after{position:absolute;content:'';right:2px;top:2px;width:5px;height:5px;border-radius:50%}.layui-laydate-footer{position:relative;height:46px;line-height:26px;padding:10px 20px}.layui-laydate-footer span{margin-right:15px;display:inline-block;cursor:pointer;font-size:12px}.layui-laydate-footer span:hover{color:#5FB878}.laydate-footer-btns{position:absolute;right:10px;top:10px}.laydate-footer-btns span{height:26px;line-height:26px;margin:0 0 0 -1px;padding:0 10px;border:1px solid #C9C9C9;background-color:#fff;white-space:nowrap;vertical-align:top;border-radius:2px}.layui-laydate-list>li,.layui-laydate-range .layui-laydate-main{display:inline-block;vertical-align:middle}.layui-laydate-list{position:absolute;left:0;top:0;width:100%;height:100%;padding:10px;background-color:#fff}.layui-laydate-list>li{position:relative;width:33.3%;height:36px;line-height:36px;margin:3px 0;text-align:center;cursor:pointer}.laydate-month-list>li{width:25%;margin:17px 0}.laydate-time-list>li{height:100%;margin:0;line-height:normal;cursor:default}.laydate-time-list p{position:relative;top:-4px;line-height:29px}.laydate-time-list ol{height:181px;overflow:hidden}.laydate-time-list>li:hover ol{overflow-y:auto}.laydate-time-list ol li{width:130%;padding-left:33px;line-height:30px;text-align:left;cursor:pointer}.layui-laydate-hint{position:absolute;top:115px;left:50%;width:250px;margin-left:-125px;line-height:20px;padding:15px;text-align:center;font-size:12px}.layui-laydate-range{width:546px}.layui-laydate-range .laydate-main-list-0 .laydate-next-m,.layui-laydate-range .laydate-main-list-0 .laydate-next-y,.layui-laydate-range .laydate-main-list-1 .laydate-prev-m,.layui-laydate-range .laydate-main-list-1 .laydate-prev-y{display:none}.layui-laydate-range .laydate-main-list-1 .layui-laydate-content{border-left:1px solid #e2e2e2}.layui-laydate,.layui-laydate-hint{border:1px solid #d2d2d2;box-shadow:0 2px 4px rgba(0,0,0,.12);background-color:#fff;color:#666}.layui-laydate-header{border-bottom:1px solid #e2e2e2}.layui-laydate-header i:hover,.layui-laydate-header span:hover{color:#5FB878}.layui-laydate-content{border-top:none 0;border-bottom:none 0}.layui-laydate-content th{font-weight:400;color:#333}.layui-laydate-content td{color:#666}.layui-laydate-content td.laydate-selected{background-color:#00F7DE}.laydate-selected:hover{background-color:#00F7DE!important}.layui-laydate-content td:hover,.layui-laydate-list li:hover{background-color:#eaeaea;color:#333}.laydate-time-list li ol{margin:0;padding:0;border:1px solid #e2e2e2;border-left-width:0}.laydate-time-list li:first-child ol{border-left-width:1px}.laydate-time-list>li:hover{background:0 0}.layui-laydate-content .laydate-day-next,.layui-laydate-content .laydate-day-prev{color:#d2d2d2}.laydate-selected.laydate-day-next,.laydate-selected.laydate-day-prev{background-color:#f8f8f8!important}.layui-laydate-footer{border-top:1px solid #e2e2e2}.layui-laydate-hint{color:#FF5722}.laydate-day-mark::after{background-color:#5FB878}.layui-laydate-content td.layui-this .laydate-day-mark::after{display:none}.layui-laydate-footer span[lay-type=date]{color:#5FB878}.layui-laydate .layui-this{background-color:#009688!important;color:#fff!important}.layui-laydate .laydate-disabled,.layui-laydate .laydate-disabled:hover{background:0 0!important;color:#d2d2d2!important;cursor:not-allowed!important;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.laydate-theme-molv{border:none}.laydate-theme-molv.layui-laydate-range{width:548px}.laydate-theme-molv .layui-laydate-main{width:274px}.laydate-theme-molv .layui-laydate-header{border:none;background-color:#009688}.laydate-theme-molv .layui-laydate-header i,.laydate-theme-molv .layui-laydate-header span{color:#f6f6f6}.laydate-theme-molv .layui-laydate-header i:hover,.laydate-theme-molv .layui-laydate-header span:hover{color:#fff}.laydate-theme-molv .layui-laydate-content{border:1px solid #e2e2e2;border-top:none;border-bottom:none}.laydate-theme-molv .laydate-main-list-1 .layui-laydate-content{border-left:none}.laydate-theme-grid .laydate-month-list>li,.laydate-theme-grid .laydate-year-list>li,.laydate-theme-grid .layui-laydate-content td,.laydate-theme-grid .layui-laydate-content thead,.laydate-theme-molv .layui-laydate-footer{border:1px solid #e2e2e2}.laydate-theme-grid .laydate-selected,.laydate-theme-grid .laydate-selected:hover{background-color:#f2f2f2!important;color:#009688!important}.laydate-theme-grid .laydate-selected.laydate-day-next,.laydate-theme-grid .laydate-selected.laydate-day-prev{color:#d2d2d2!important}.laydate-theme-grid .laydate-month-list,.laydate-theme-grid .laydate-year-list{margin:1px 0 0 1px}.laydate-theme-grid .laydate-month-list>li,.laydate-theme-grid .laydate-year-list>li{margin:0 -1px -1px 0}.laydate-theme-grid .laydate-year-list>li{height:43px;line-height:43px}.laydate-theme-grid .laydate-month-list>li{height:71px;line-height:71px}"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/layui/css/modules/layer/default/layer.css",
    "content": "/** layui-v2.2.5 MIT License By https://www.layui.com */\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 #layuicss-layer{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;border-radius:2px;box-shadow:1px 1px 50px rgba(0,0,0,.3)}.layui-layer-close{position:absolute}.layui-layer-content{position:relative}.layui-layer-border{border:1px solid #B2B2B2;border:1px solid rgba(0,0,0,.1);box-shadow:1px 1px 5px rgba(0,0,0,.2)}.layui-layer-load{background:url(loading-1.gif) center center no-repeat #eee}.layui-layer-ico{background:url(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}.layui-layer-move{display:none;position:fixed;*position:absolute;left:0;top:0;width:100%;height:100%;cursor:move;opacity:0;filter:alpha(opacity=0);background-color:#fff;z-index:2147483647}.layui-layer-resize{position:absolute;width:15px;height:15px;right:0;bottom:0;cursor:se-resize}.layer-anim{-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:.3s;animation-duration:.3s}@-webkit-keyframes layer-bounceIn{0%{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}@keyframes layer-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-00{-webkit-animation-name:layer-bounceIn;animation-name:layer-bounceIn}@-webkit-keyframes layer-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 layer-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:layer-zoomInDown;animation-name:layer-zoomInDown}@-webkit-keyframes layer-fadeInUpBig{0%{opacity:0;-webkit-transform:translateY(2000px);transform:translateY(2000px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes layer-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:layer-fadeInUpBig;animation-name:layer-fadeInUpBig}@-webkit-keyframes layer-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 layer-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:layer-zoomInLeft;animation-name:layer-zoomInLeft}@-webkit-keyframes layer-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 layer-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:layer-rollIn;animation-name:layer-rollIn}@keyframes layer-fadeIn{0%{opacity:0}100%{opacity:1}}.layer-anim-05{-webkit-animation-name:layer-fadeIn;animation-name:layer-fadeIn}@-webkit-keyframes layer-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 layer-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:layer-shake;animation-name:layer-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:1px -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 15px 12px;pointer-events:auto;user-select:none;-webkit-user-select:none}.layui-layer-btn a{height:28px;line-height:28px;margin:5px 5px 0;padding:0 15px;border:1px solid #dedede;background-color:#fff;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:.8}.layui-layer-btn .layui-layer-btn0{border-color:#1E9FFF;background-color:#1E9FFF;color:#fff}.layui-layer-btn-l{text-align:left}.layui-layer-btn-c{text-align:center}.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 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(loading-0.gif) no-repeat}.layui-layer-loading .layui-layer-loading1{width:37px;height:37px;background:url(loading-1.gif) no-repeat}.layui-layer-ico16,.layui-layer-loading .layui-layer-loading2{width:32px;height:32px;background:url(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:8px 15px;font-size:12px;_float:left;border-radius:2px;box-shadow:1px 1px 3px rgba(0,0,0,.2);background-color:#000;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:#000}.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:5px;border-bottom-style:solid;border-bottom-color:#000}.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:5px 10px 10px;text-align:right;border-top:1px solid #E9E7E7}.layui-layer-lan .layui-layer-btn a{background:#fff;border-color:#E9E7E7;color:#333}.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;border-color:#009f95}.layui-layer-molv .layui-layer-btn .layui-layer-btn1{background:#92B8B1}.layui-layer-iconext{background:url(icon-ext.png) no-repeat}.layui-layer-prompt .layui-layer-input{display:block;width:230px;height:36px;margin:0 auto;line-height:30px;padding-left:10px;border:1px solid #e6e6e6;color:#333}.layui-layer-prompt textarea.layui-layer-input{width:300px;height:100px;line-height:20px;padding:6px 10px}.layui-layer-prompt .layui-layer-content{padding:20px}.layui-layer-prompt .layui-layer-btn{padding-top:0}.layui-layer-tab{box-shadow:1px 1px 50px rgba(0,0,0,.4)}.layui-layer-tab .layui-layer-title{padding-left:0;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;overflow:hidden;cursor:pointer}.layui-layer-tab .layui-layer-title span.layui-this{height:43px;border-left:1px solid #eee;border-right:1px solid #eee;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.layui-this{display:block}.layui-layer-photos{-webkit-animation-duration:.8s;animation-duration:.8s}.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}@-webkit-keyframes layer-bounceOut{100%{opacity:0;-webkit-transform:scale(.7);transform:scale(.7)}30%{-webkit-transform:scale(1.05);transform:scale(1.05)}0%{-webkit-transform:scale(1);transform:scale(1)}}@keyframes layer-bounceOut{100%{opacity:0;-webkit-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}30%{-webkit-transform:scale(1.05);-ms-transform:scale(1.05);transform:scale(1.05)}0%{-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}.layer-anim-close{-webkit-animation-name:layer-bounceOut;animation-name:layer-bounceOut;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:.2s;animation-duration:.2s}@media screen and (max-width:1100px){.layui-layer-iframe{overflow-y:auto;-webkit-overflow-scrolling:touch}}"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/layui/lay/modules/carousel.js",
    "content": "/** layui-v2.2.5 MIT License By https://www.layui.com */\n ;layui.define(\"jquery\",function(e){\"use strict\";var i=layui.$,n=(layui.hint(),layui.device(),{config:{},set:function(e){var n=this;return n.config=i.extend({},n.config,e),n},on:function(e,i){return layui.onevent.call(this,t,e,i)}}),t=\"carousel\",a=\"layui-this\",l=\">*[carousel-item]>*\",o=\"layui-carousel-left\",r=\"layui-carousel-right\",d=\"layui-carousel-prev\",s=\"layui-carousel-next\",u=\"layui-carousel-arrow\",c=\"layui-carousel-ind\",m=function(e){var t=this;t.config=i.extend({},t.config,n.config,e),t.render()};m.prototype.config={width:\"600px\",height:\"280px\",full:!1,arrow:\"hover\",indicator:\"inside\",autoplay:!0,interval:3e3,anim:\"\",trigger:\"click\",index:0},m.prototype.render=function(){var e=this,n=e.config;n.elem=i(n.elem),n.elem[0]&&(e.elemItem=n.elem.find(l),n.index<0&&(n.index=0),n.index>=e.elemItem.length&&(n.index=e.elemItem.length-1),n.interval<800&&(n.interval=800),n.full?n.elem.css({position:\"fixed\",width:\"100%\",height:\"100%\",zIndex:9999}):n.elem.css({width:n.width,height:n.height}),n.elem.attr(\"lay-anim\",n.anim),e.elemItem.eq(n.index).addClass(a),e.elemItem.length<=1||(e.indicator(),e.arrow(),e.autoplay(),e.events()))},m.prototype.reload=function(e){var n=this;clearInterval(n.timer),n.config=i.extend({},n.config,e),n.render()},m.prototype.prevIndex=function(){var e=this,i=e.config,n=i.index-1;return n<0&&(n=e.elemItem.length-1),n},m.prototype.nextIndex=function(){var e=this,i=e.config,n=i.index+1;return n>=e.elemItem.length&&(n=0),n},m.prototype.addIndex=function(e){var i=this,n=i.config;e=e||1,n.index=n.index+e,n.index>=i.elemItem.length&&(n.index=0)},m.prototype.subIndex=function(e){var i=this,n=i.config;e=e||1,n.index=n.index-e,n.index<0&&(n.index=i.elemItem.length-1)},m.prototype.autoplay=function(){var e=this,i=e.config;i.autoplay&&(e.timer=setInterval(function(){e.slide()},i.interval))},m.prototype.arrow=function(){var e=this,n=e.config,t=i(['<button class=\"layui-icon '+u+'\" lay-type=\"sub\">'+(\"updown\"===n.anim?\"&#xe619;\":\"&#xe603;\")+\"</button>\",'<button class=\"layui-icon '+u+'\" lay-type=\"add\">'+(\"updown\"===n.anim?\"&#xe61a;\":\"&#xe602;\")+\"</button>\"].join(\"\"));n.elem.attr(\"lay-arrow\",n.arrow),n.elem.find(\".\"+u)[0]&&n.elem.find(\".\"+u).remove(),n.elem.append(t),t.on(\"click\",function(){var n=i(this),t=n.attr(\"lay-type\");e.slide(t)})},m.prototype.indicator=function(){var e=this,n=e.config,t=e.elemInd=i(['<div class=\"'+c+'\"><ul>',function(){var i=[];return layui.each(e.elemItem,function(e){i.push(\"<li\"+(n.index===e?' class=\"layui-this\"':\"\")+\"></li>\")}),i.join(\"\")}(),\"</ul></div>\"].join(\"\"));n.elem.attr(\"lay-indicator\",n.indicator),n.elem.find(\".\"+c)[0]&&n.elem.find(\".\"+c).remove(),n.elem.append(t),\"updown\"===n.anim&&t.css(\"margin-top\",-(t.height()/2)),t.find(\"li\").on(\"hover\"===n.trigger?\"mouseover\":n.trigger,function(){var t=i(this),a=t.index();a>n.index?e.slide(\"add\",a-n.index):a<n.index&&e.slide(\"sub\",n.index-a)})},m.prototype.slide=function(e,i){var n=this,l=n.elemItem,u=n.config,c=u.index,m=u.elem.attr(\"lay-filter\");n.haveSlide||(\"sub\"===e?(n.subIndex(i),l.eq(u.index).addClass(d),setTimeout(function(){l.eq(c).addClass(r),l.eq(u.index).addClass(r)},50)):(n.addIndex(i),l.eq(u.index).addClass(s),setTimeout(function(){l.eq(c).addClass(o),l.eq(u.index).addClass(o)},50)),setTimeout(function(){l.removeClass(a+\" \"+d+\" \"+s+\" \"+o+\" \"+r),l.eq(u.index).addClass(a),n.haveSlide=!1},300),n.elemInd.find(\"li\").eq(u.index).addClass(a).siblings().removeClass(a),n.haveSlide=!0,layui.event.call(this,t,\"change(\"+m+\")\",{index:u.index,prevIndex:c,item:l.eq(u.index)}))},m.prototype.events=function(){var e=this,i=e.config;i.elem.data(\"haveEvents\")||(i.elem.on(\"mouseenter\",function(){clearInterval(e.timer)}).on(\"mouseleave\",function(){e.autoplay()}),i.elem.data(\"haveEvents\",!0))},n.render=function(e){var i=new m(e);return i},e(t,n)});"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/layui/lay/modules/code.js",
    "content": "/** layui-v2.2.5 MIT License By https://www.layui.com */\n ;layui.define(\"jquery\",function(e){\"use strict\";var a=layui.$,l=\"http://www.layui.com/doc/modules/code.html\";e(\"code\",function(e){var t=[];e=e||{},e.elem=a(e.elem||\".layui-code\"),e.about=!(\"about\"in e)||e.about,e.elem.each(function(){t.push(this)}),layui.each(t.reverse(),function(t,i){var c=a(i),o=c.html();(c.attr(\"lay-encode\")||e.encode)&&(o=o.replace(/&(?!#?[a-zA-Z0-9]+;)/g,\"&amp;\").replace(/</g,\"&lt;\").replace(/>/g,\"&gt;\").replace(/'/g,\"&#39;\").replace(/\"/g,\"&quot;\")),c.html('<ol class=\"layui-code-ol\"><li>'+o.replace(/[\\r\\t\\n]+/g,\"</li><li>\")+\"</li></ol>\"),c.find(\">.layui-code-h3\")[0]||c.prepend('<h3 class=\"layui-code-h3\">'+(c.attr(\"lay-title\")||e.title||\"code\")+(e.about?'<a href=\"'+l+'\" target=\"_blank\">layui.code</a>':\"\")+\"</h3>\");var d=c.find(\">.layui-code-ol\");c.addClass(\"layui-box layui-code-view\"),(c.attr(\"lay-skin\")||e.skin)&&c.addClass(\"layui-code-\"+(c.attr(\"lay-skin\")||e.skin)),(d.find(\"li\").length/100|0)>0&&d.css(\"margin-left\",(d.find(\"li\").length/100|0)+\"px\"),(c.attr(\"lay-height\")||e.height)&&d.css(\"max-height\",c.attr(\"lay-height\")||e.height)})})}).addcss(\"modules/code.css\",\"skincodecss\");"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/layui/lay/modules/element.js",
    "content": "/** layui-v2.2.5 MIT License By https://www.layui.com */\n ;layui.define(\"jquery\",function(i){\"use strict\";var t=layui.$,a=(layui.hint(),layui.device()),e=\"element\",l=\"layui-this\",n=\"layui-show\",s=function(){this.config={}};s.prototype.set=function(i){var a=this;return t.extend(!0,a.config,i),a},s.prototype.on=function(i,t){return layui.onevent.call(this,e,i,t)},s.prototype.tabAdd=function(i,a){var e=\".layui-tab-title\",l=t(\".layui-tab[lay-filter=\"+i+\"]\"),n=l.children(e),s=n.children(\".layui-tab-bar\"),o=l.children(\".layui-tab-content\"),c='<li lay-id=\"'+(a.id||\"\")+'\">'+(a.title||\"unnaming\")+\"</li>\";return s[0]?s.before(c):n.append(c),o.append('<div class=\"layui-tab-item\">'+(a.content||\"\")+\"</div>\"),y.hideTabMore(!0),y.tabAuto(),this},s.prototype.tabDelete=function(i,a){var e=\".layui-tab-title\",l=t(\".layui-tab[lay-filter=\"+i+\"]\"),n=l.children(e),s=n.find('>li[lay-id=\"'+a+'\"]');return y.tabDelete(null,s),this},s.prototype.tabChange=function(i,a){var e=\".layui-tab-title\",l=t(\".layui-tab[lay-filter=\"+i+\"]\"),n=l.children(e),s=n.find('>li[lay-id=\"'+a+'\"]');return y.tabClick.call(s[0],null,null,s),this},s.prototype.tab=function(i){i=i||{},v.on(\"click\",i.headerElem,function(a){var e=t(this).index();y.tabClick.call(this,a,e,null,i)})},s.prototype.progress=function(i,a){var e=\"layui-progress\",l=t(\".\"+e+\"[lay-filter=\"+i+\"]\"),n=l.find(\".\"+e+\"-bar\"),s=n.find(\".\"+e+\"-text\");return n.css(\"width\",a),s.text(a),this};var o=\".layui-nav\",c=\"layui-nav-item\",r=\"layui-nav-bar\",u=\"layui-nav-tree\",d=\"layui-nav-child\",h=\"layui-nav-more\",f=\"layui-anim layui-anim-upbit\",y={tabClick:function(i,a,s,o){o=o||{};var c=s||t(this),a=a||c.parent().children(\"li\").index(c),r=o.headerElem?c.parent():c.parents(\".layui-tab\").eq(0),u=o.bodyElem?t(o.bodyElem):r.children(\".layui-tab-content\").children(\".layui-tab-item\"),d=c.find(\"a\"),h=r.attr(\"lay-filter\");\"javascript:;\"!==d.attr(\"href\")&&\"_blank\"===d.attr(\"target\")||(c.addClass(l).siblings().removeClass(l),u.eq(a).addClass(n).siblings().removeClass(n)),layui.event.call(this,e,\"tab(\"+h+\")\",{elem:r,index:a})},tabDelete:function(i,a){var n=a||t(this).parent(),s=n.index(),o=n.parents(\".layui-tab\").eq(0),c=o.children(\".layui-tab-content\").children(\".layui-tab-item\"),r=o.attr(\"lay-filter\");n.hasClass(l)&&(n.next()[0]?y.tabClick.call(n.next()[0],null,s+1):n.prev()[0]&&y.tabClick.call(n.prev()[0],null,s-1)),n.remove(),c.eq(s).remove(),setTimeout(function(){y.tabAuto()},50),layui.event.call(this,e,\"tabDelete(\"+r+\")\",{elem:o,index:s})},tabAuto:function(){var i=\"layui-tab-more\",e=\"layui-tab-bar\",l=\"layui-tab-close\",n=this;t(\".layui-tab\").each(function(){var s=t(this),o=s.children(\".layui-tab-title\"),c=(s.children(\".layui-tab-content\").children(\".layui-tab-item\"),'lay-stope=\"tabmore\"'),r=t('<span class=\"layui-unselect layui-tab-bar\" '+c+\"><i \"+c+' class=\"layui-icon\">&#xe61a;</i></span>');if(n===window&&8!=a.ie&&y.hideTabMore(!0),s.attr(\"lay-allowClose\")&&o.find(\"li\").each(function(){var i=t(this);if(!i.find(\".\"+l)[0]){var a=t('<i class=\"layui-icon layui-unselect '+l+'\">&#x1006;</i>');a.on(\"click\",y.tabDelete),i.append(a)}}),o.prop(\"scrollWidth\")>o.outerWidth()+1){if(o.find(\".\"+e)[0])return;o.append(r),s.attr(\"overflow\",\"\"),r.on(\"click\",function(t){o[this.title?\"removeClass\":\"addClass\"](i),this.title=this.title?\"\":\"收缩\"})}else o.find(\".\"+e).remove(),s.removeAttr(\"overflow\")})},hideTabMore:function(i){var a=t(\".layui-tab-title\");i!==!0&&\"tabmore\"===t(i.target).attr(\"lay-stope\")||(a.removeClass(\"layui-tab-more\"),a.find(\".layui-tab-bar\").attr(\"title\",\"\"))},clickThis:function(){var i=t(this),a=i.parents(o),n=a.attr(\"lay-filter\"),s=i.find(\"a\"),c=\"string\"==typeof i.attr(\"lay-unselect\");i.find(\".\"+d)[0]||(\"javascript:;\"!==s.attr(\"href\")&&\"_blank\"===s.attr(\"target\")||c||(a.find(\".\"+l).removeClass(l),i.addClass(l)),layui.event.call(this,e,\"nav(\"+n+\")\",i))},clickChild:function(){var i=t(this),a=i.parents(o),n=a.attr(\"lay-filter\");a.find(\".\"+l).removeClass(l),i.addClass(l),layui.event.call(this,e,\"nav(\"+n+\")\",i)},showChild:function(){var i=t(this),a=i.parents(o),e=i.parent(),l=i.siblings(\".\"+d);a.hasClass(u)&&(l.removeClass(f),e[\"none\"===l.css(\"display\")?\"addClass\":\"removeClass\"](c+\"ed\"))},collapse:function(){var i=t(this),a=i.find(\".layui-colla-icon\"),l=i.siblings(\".layui-colla-content\"),s=i.parents(\".layui-collapse\").eq(0),o=s.attr(\"lay-filter\"),c=\"none\"===l.css(\"display\");if(\"string\"==typeof s.attr(\"lay-accordion\")){var r=s.children(\".layui-colla-item\").children(\".\"+n);r.siblings(\".layui-colla-title\").children(\".layui-colla-icon\").html(\"&#xe602;\"),r.removeClass(n)}l[c?\"addClass\":\"removeClass\"](n),a.html(c?\"&#xe61a;\":\"&#xe602;\"),layui.event.call(this,e,\"collapse(\"+o+\")\",{title:i,content:l,show:c})}};s.prototype.init=function(i,e){var l=function(){return e?'[lay-filter=\"'+e+'\"]':\"\"}(),s={tab:function(){y.tabAuto.call({})},nav:function(){var i=200,e={},s={},p={},v=function(l,o,c){var r=t(this),y=r.find(\".\"+d);o.hasClass(u)?l.css({top:r.position().top,height:r.children(\"a\").height(),opacity:1}):(y.addClass(f),l.css({left:r.position().left+parseFloat(r.css(\"marginLeft\")),top:r.position().top+r.height()-l.height()}),e[c]=setTimeout(function(){l.css({width:r.width(),opacity:1})},a.ie&&a.ie<10?0:i),clearTimeout(p[c]),\"block\"===y.css(\"display\")&&clearTimeout(s[c]),s[c]=setTimeout(function(){y.addClass(n),r.find(\".\"+h).addClass(h+\"d\")},300))};t(o+l).each(function(a){var l=t(this),o=t('<span class=\"'+r+'\"></span>'),f=l.find(\".\"+c);l.find(\".\"+r)[0]||(l.append(o),f.on(\"mouseenter\",function(){v.call(this,o,l,a)}).on(\"mouseleave\",function(){l.hasClass(u)||(clearTimeout(s[a]),s[a]=setTimeout(function(){l.find(\".\"+d).removeClass(n),l.find(\".\"+h).removeClass(h+\"d\")},300))}),l.on(\"mouseleave\",function(){clearTimeout(e[a]),p[a]=setTimeout(function(){l.hasClass(u)?o.css({height:0,top:o.position().top+o.height()/2,opacity:0}):o.css({width:0,left:o.position().left+o.width()/2,opacity:0})},i)})),f.each(function(){var i=t(this),a=i.find(\".\"+d);if(a[0]&&!i.find(\".\"+h)[0]){var e=i.children(\"a\");e.append('<span class=\"'+h+'\"></span>')}i.off(\"click\",y.clickThis).on(\"click\",y.clickThis),i.children(\"a\").off(\"click\",y.showChild).on(\"click\",y.showChild),a.children(\"dd\").off(\"click\",y.clickChild).on(\"click\",y.clickChild)})})},breadcrumb:function(){var i=\".layui-breadcrumb\";t(i+l).each(function(){var i=t(this),a=\"lay-separator\",e=i.attr(a)||\"/\",l=i.find(\"a\");l.next(\"span[\"+a+\"]\")[0]||(l.each(function(i){i!==l.length-1&&t(this).after(\"<span \"+a+\">\"+e+\"</span>\")}),i.css(\"visibility\",\"visible\"))})},progress:function(){var i=\"layui-progress\";t(\".\"+i+l).each(function(){var a=t(this),e=a.find(\".layui-progress-bar\"),l=e.attr(\"lay-percent\");e.css(\"width\",function(){return/^.+\\/.+$/.test(l)?100*new Function(\"return \"+l)()+\"%\":l}()),a.attr(\"lay-showPercent\")&&setTimeout(function(){e.html('<span class=\"'+i+'-text\">'+l+\"</span>\")},350)})},collapse:function(){var i=\"layui-collapse\";t(\".\"+i+l).each(function(){var i=t(this).find(\".layui-colla-item\");i.each(function(){var i=t(this),a=i.find(\".layui-colla-title\"),e=i.find(\".layui-colla-content\"),l=\"none\"===e.css(\"display\");a.find(\".layui-colla-icon\").remove(),a.append('<i class=\"layui-icon layui-colla-icon\">'+(l?\"&#xe602;\":\"&#xe61a;\")+\"</i>\"),a.off(\"click\",y.collapse).on(\"click\",y.collapse)})})}};return s[i]?s[i]():layui.each(s,function(i,t){t()})},s.prototype.render=s.prototype.init;var p=new s,v=t(document);p.render();var b=\".layui-tab-title li\";v.on(\"click\",b,y.tabClick),v.on(\"click\",y.hideTabMore),t(window).on(\"resize\",y.tabAuto),i(e,p)});"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/layui/lay/modules/flow.js",
    "content": "/** layui-v2.2.5 MIT License By https://www.layui.com */\n ;layui.define(\"jquery\",function(e){\"use strict\";var l=layui.$,o=function(e){},t='<i class=\"layui-anim layui-anim-rotate layui-anim-loop layui-icon \">&#xe63e;</i>';o.prototype.load=function(e){var o,i,n,r,a=this,c=0;e=e||{};var f=l(e.elem);if(f[0]){var m=l(e.scrollElem||document),u=e.mb||50,s=!(\"isAuto\"in e)||e.isAuto,v=e.end||\"没有更多了\",y=e.scrollElem&&e.scrollElem!==document,d=\"<cite>加载更多</cite>\",h=l('<div class=\"layui-flow-more\"><a href=\"javascript:;\">'+d+\"</a></div>\");f.find(\".layui-flow-more\")[0]||f.append(h);var p=function(e,t){e=l(e),h.before(e),t=0==t||null,t?h.html(v):h.find(\"a\").html(d),i=t,o=null,n&&n()},g=function(){o=!0,h.find(\"a\").html(t),\"function\"==typeof e.done&&e.done(++c,p)};if(g(),h.find(\"a\").on(\"click\",function(){l(this);i||o||g()}),e.isLazyimg)var n=a.lazyimg({elem:e.elem+\" img\",scrollElem:e.scrollElem});return s?(m.on(\"scroll\",function(){var e=l(this),t=e.scrollTop();r&&clearTimeout(r),i||(r=setTimeout(function(){var i=y?e.height():l(window).height(),n=y?e.prop(\"scrollHeight\"):document.documentElement.scrollHeight;n-t-i<=u&&(o||g())},100))}),a):a}},o.prototype.lazyimg=function(e){var o,t=this,i=0;e=e||{};var n=l(e.scrollElem||document),r=e.elem||\"img\",a=e.scrollElem&&e.scrollElem!==document,c=function(e,l){var o=n.scrollTop(),r=o+l,c=a?function(){return e.offset().top-n.offset().top+o}():e.offset().top;if(c>=o&&c<=r&&!e.attr(\"src\")){var m=e.attr(\"lay-src\");layui.img(m,function(){var l=t.lazyimg.elem.eq(i);e.attr(\"src\",m).removeAttr(\"lay-src\"),l[0]&&f(l),i++})}},f=function(e,o){var f=a?(o||n).height():l(window).height(),m=n.scrollTop(),u=m+f;if(t.lazyimg.elem=l(r),e)c(e,f);else for(var s=0;s<t.lazyimg.elem.length;s++){var v=t.lazyimg.elem.eq(s),y=a?function(){return v.offset().top-n.offset().top+m}():v.offset().top;if(c(v,f),i=s,y>u)break}};if(f(),!o){var m;n.on(\"scroll\",function(){var e=l(this);m&&clearTimeout(m),m=setTimeout(function(){f(null,e)},50)}),o=!0}return f},e(\"flow\",new o)});"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/layui/lay/modules/form.js",
    "content": "/** layui-v2.2.5 MIT License By https://www.layui.com */\n ;layui.define(\"layer\",function(e){\"use strict\";var t=layui.$,i=layui.layer,a=layui.hint(),n=layui.device(),l=\"form\",r=\".layui-form\",s=\"layui-this\",o=\"layui-hide\",u=\"layui-disabled\",c=function(){this.config={verify:{required:[/[\\S]+/,\"必填项不能为空\"],phone:[/^1\\d{10}$/,\"请输入正确的手机号\"],email:[/^([a-zA-Z0-9_\\.\\-])+\\@(([a-zA-Z0-9\\-])+\\.)+([a-zA-Z0-9]{2,4})+$/,\"邮箱格式不正确\"],url:[/(^#)|(^http(s*):\\/\\/[^\\s]+\\.[^\\s]+)/,\"链接格式不正确\"],number:function(e){if(!e||isNaN(e))return\"只能填写数字\"},date:[/^(\\d{4})[-\\/](\\d{1}|0\\d{1}|1[0-2])([-\\/](\\d{1}|0\\d{1}|[1-2][0-9]|3[0-1]))*$/,\"日期格式不正确\"],identity:[/(^\\d{15}$)|(^\\d{17}(x|X|\\d)$)/,\"请输入正确的身份证号\"]}}};c.prototype.set=function(e){var i=this;return t.extend(!0,i.config,e),i},c.prototype.verify=function(e){var i=this;return t.extend(!0,i.config.verify,e),i},c.prototype.on=function(e,t){return layui.onevent.call(this,l,e,t)},c.prototype.render=function(e,i){var n=this,c=t(r+function(){return i?'[lay-filter=\"'+i+'\"]':\"\"}()),d={select:function(){var e,i=\"请选择\",a=\"layui-form-select\",n=\"layui-select-title\",r=\"layui-select-none\",d=\"\",f=c.find(\"select\"),y=function(i,l){t(i.target).parent().hasClass(n)&&!l||(t(\".\"+a).removeClass(a+\"ed \"+a+\"up\"),e&&d&&e.val(d)),e=null},h=function(i,c,f){var h=t(this),p=i.find(\".\"+n),m=p.find(\"input\"),k=i.find(\"dl\"),g=k.children(\"dd\");if(!c){var x=function(){var e=i.offset().top+i.outerHeight()+5-v.scrollTop(),t=k.outerHeight();i.addClass(a+\"ed\"),g.removeClass(o),e+t>v.height()&&e>=t&&i.addClass(a+\"up\")},b=function(e){i.removeClass(a+\"ed \"+a+\"up\"),m.blur(),e||C(m.val(),function(e){e&&(d=k.find(\".\"+s).html(),m&&m.val(d))})};p.on(\"click\",function(e){i.hasClass(a+\"ed\")?b():(y(e,!0),x()),k.find(\".\"+r).remove()}),p.find(\".layui-edge\").on(\"click\",function(){m.focus()}),m.on(\"keyup\",function(e){var t=e.keyCode;9===t&&x()}).on(\"keydown\",function(e){var t=e.keyCode;9===t?b():13===t&&e.preventDefault()});var C=function(e,i,a){var n=0;layui.each(g,function(){var i=t(this),l=i.text(),r=l.indexOf(e)===-1;(\"\"===e||\"blur\"===a?e!==l:r)&&n++,\"keyup\"===a&&i[r?\"addClass\":\"removeClass\"](o)});var l=n===g.length;return i(l),l},w=function(e){var t=this.value,i=e.keyCode;return 9!==i&&13!==i&&37!==i&&38!==i&&39!==i&&40!==i&&(C(t,function(e){e?k.find(\".\"+r)[0]||k.append('<p class=\"'+r+'\">无匹配项</p>'):k.find(\".\"+r).remove()},\"keyup\"),void(\"\"===t&&k.find(\".\"+r).remove()))};f&&m.on(\"keyup\",w).on(\"blur\",function(t){e=m,d=k.find(\".\"+s).html(),setTimeout(function(){C(m.val(),function(e){d||m.val(\"\")},\"blur\")},200)}),g.on(\"click\",function(){var e=t(this),a=e.attr(\"lay-value\"),n=h.attr(\"lay-filter\");return!e.hasClass(u)&&(e.hasClass(\"layui-select-tips\")?m.val(\"\"):(m.val(e.text()),e.addClass(s)),e.siblings().removeClass(s),h.val(a).removeClass(\"layui-form-danger\"),layui.event.call(this,l,\"select(\"+n+\")\",{elem:h[0],value:a,othis:i}),b(!0),!1)}),i.find(\"dl>dt\").on(\"click\",function(e){return!1}),t(document).off(\"click\",y).on(\"click\",y)}};f.each(function(e,l){var r=t(this),o=r.next(\".\"+a),c=this.disabled,d=l.value,f=t(l.options[l.selectedIndex]),y=l.options[0];if(\"string\"==typeof r.attr(\"lay-ignore\"))return r.show();var v=\"string\"==typeof r.attr(\"lay-search\"),p=y?y.value?i:y.innerHTML||i:i,m=t(['<div class=\"'+(v?\"\":\"layui-unselect \")+a+(c?\" layui-select-disabled\":\"\")+'\">','<div class=\"'+n+'\"><input type=\"text\" placeholder=\"'+p+'\" value=\"'+(d?f.html():\"\")+'\" '+(v?\"\":\"readonly\")+' class=\"layui-input'+(v?\"\":\" layui-unselect\")+(c?\" \"+u:\"\")+'\">','<i class=\"layui-edge\"></i></div>','<dl class=\"layui-anim layui-anim-upbit'+(r.find(\"optgroup\")[0]?\" layui-select-group\":\"\")+'\">'+function(e){var t=[];return layui.each(e,function(e,a){0!==e||a.value?\"optgroup\"===a.tagName.toLowerCase()?t.push(\"<dt>\"+a.label+\"</dt>\"):t.push('<dd lay-value=\"'+a.value+'\" class=\"'+(d===a.value?s:\"\")+(a.disabled?\" \"+u:\"\")+'\">'+a.innerHTML+\"</dd>\"):t.push('<dd lay-value=\"\" class=\"layui-select-tips\">'+(a.innerHTML||i)+\"</dd>\")}),0===t.length&&t.push('<dd lay-value=\"\" class=\"'+u+'\">没有选项</dd>'),t.join(\"\")}(r.find(\"*\"))+\"</dl>\",\"</div>\"].join(\"\"));o[0]&&o.remove(),r.after(m),h.call(this,m,c,v)})},checkbox:function(){var e={checkbox:[\"layui-form-checkbox\",\"layui-form-checked\",\"checkbox\"],_switch:[\"layui-form-switch\",\"layui-form-onswitch\",\"switch\"]},i=c.find(\"input[type=checkbox]\"),a=function(e,i){var a=t(this);e.on(\"click\",function(){var t=a.attr(\"lay-filter\"),n=(a.attr(\"lay-text\")||\"\").split(\"|\");a[0].disabled||(a[0].checked?(a[0].checked=!1,e.removeClass(i[1]).find(\"em\").text(n[1])):(a[0].checked=!0,e.addClass(i[1]).find(\"em\").text(n[0])),layui.event.call(a[0],l,i[2]+\"(\"+t+\")\",{elem:a[0],value:a[0].value,othis:e}))})};i.each(function(i,n){var l=t(this),r=l.attr(\"lay-skin\"),s=(l.attr(\"lay-text\")||\"\").split(\"|\"),o=this.disabled;\"switch\"===r&&(r=\"_\"+r);var c=e[r]||e.checkbox;if(\"string\"==typeof l.attr(\"lay-ignore\"))return l.show();var d=l.next(\".\"+c[0]),f=t(['<div class=\"layui-unselect '+c[0]+(n.checked?\" \"+c[1]:\"\")+(o?\" layui-checkbox-disbaled \"+u:\"\")+'\" lay-skin=\"'+(r||\"\")+'\">',{_switch:\"<em>\"+((n.checked?s[0]:s[1])||\"\")+\"</em><i></i>\"}[r]||(n.title.replace(/\\s/g,\"\")?\"<span>\"+n.title+\"</span>\":\"\")+'<i class=\"layui-icon\">'+(r?\"&#xe605;\":\"&#xe618;\")+\"</i>\",\"</div>\"].join(\"\"));d[0]&&d.remove(),l.after(f),a.call(this,f,c)})},radio:function(){var e=\"layui-form-radio\",i=[\"&#xe643;\",\"&#xe63f;\"],a=c.find(\"input[type=radio]\"),n=function(a){var n=t(this),s=\"layui-anim-scaleSpring\";a.on(\"click\",function(){var o=n[0].name,u=n.parents(r),c=n.attr(\"lay-filter\"),d=u.find(\"input[name=\"+o.replace(/(\\.|#|\\[|\\])/g,\"\\\\$1\")+\"]\");n[0].disabled||(layui.each(d,function(){var a=t(this).next(\".\"+e);this.checked=!1,a.removeClass(e+\"ed\"),a.find(\".layui-icon\").removeClass(s).html(i[1])}),n[0].checked=!0,a.addClass(e+\"ed\"),a.find(\".layui-icon\").addClass(s).html(i[0]),layui.event.call(n[0],l,\"radio(\"+c+\")\",{elem:n[0],value:n[0].value,othis:a}))})};a.each(function(a,l){var r=t(this),s=r.next(\".\"+e),o=this.disabled;if(\"string\"==typeof r.attr(\"lay-ignore\"))return r.show();s[0]&&s.remove();var c=t(['<div class=\"layui-unselect '+e+(l.checked?\" \"+e+\"ed\":\"\")+(o?\" layui-radio-disbaled \"+u:\"\")+'\">','<i class=\"layui-anim layui-icon\">'+i[l.checked?0:1]+\"</i>\",\"<div>\"+function(){var e=l.title||\"\";return\"string\"==typeof r.next().attr(\"lay-radio\")&&(e=r.next().html(),r.next().remove()),e}()+\"</div>\",\"</div>\"].join(\"\"));r.after(c),n.call(this,c)})}};return e?d[e]?d[e]():a.error(\"不支持的\"+e+\"表单渲染\"):layui.each(d,function(e,t){t()}),n};var d=function(){var e=t(this),a=f.config.verify,s=null,o=\"layui-form-danger\",u={},c=e.parents(r),d=c.find(\"*[lay-verify]\"),y=e.parents(\"form\")[0],v=c.find(\"input,select,textarea\"),h=e.attr(\"lay-filter\");if(layui.each(d,function(e,l){var r=t(this),u=r.attr(\"lay-verify\").split(\"|\"),c=r.attr(\"lay-verType\"),d=r.val();if(r.removeClass(o),layui.each(u,function(e,t){var u,f=\"\",y=\"function\"==typeof a[t];if(a[t]){var u=y?f=a[t](d,l):!a[t][0].test(d);if(f=f||a[t][1],u)return\"tips\"===c?i.tips(f,function(){return\"string\"==typeof r.attr(\"lay-ignore\")||\"select\"!==l.tagName.toLowerCase()&&!/^checkbox|radio$/.test(l.type)?r:r.next()}(),{tips:1}):\"alert\"===c?i.alert(f,{title:\"提示\",shadeClose:!0}):i.msg(f,{icon:5,shift:6}),n.android||n.ios||l.focus(),r.addClass(o),s=!0}}),s)return s}),s)return!1;var p={};return layui.each(v,function(e,t){if(t.name=(t.name||\"\").replace(/^\\s*|\\s*&/,\"\"),t.name){if(/^.*\\[\\]$/.test(t.name)){var i=t.name.match(/^(.*)\\[\\]$/g)[0];p[i]=0|p[i],t.name=t.name.replace(/^(.*)\\[\\]$/,\"$1[\"+p[i]++ +\"]\")}/^checkbox|radio$/.test(t.type)&&!t.checked||(u[t.name]=t.value)}}),layui.event.call(this,l,\"submit(\"+h+\")\",{elem:this,form:y,field:u})},f=new c,y=t(document),v=t(window);f.render(),y.on(\"reset\",r,function(){var e=t(this).attr(\"lay-filter\");setTimeout(function(){f.render(null,e)},50)}),y.on(\"submit\",r,d).on(\"click\",\"*[lay-submit]\",d),e(l,f)});"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/layui/lay/modules/jquery.js",
    "content": "/** layui-v2.2.5 MIT License By https://www.layui.com */\n ;!function(e,t){\"object\"==typeof module&&\"object\"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error(\"jQuery requires a window with a document\");return t(e)}:t(e)}(\"undefined\"!=typeof window?window:this,function(e,t){function n(e){var t=!!e&&\"length\"in e&&e.length,n=pe.type(e);return\"function\"!==n&&!pe.isWindow(e)&&(\"array\"===n||0===t||\"number\"==typeof t&&t>0&&t-1 in e)}function r(e,t,n){if(pe.isFunction(t))return pe.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return pe.grep(e,function(e){return e===t!==n});if(\"string\"==typeof t){if(Ce.test(t))return pe.filter(t,e,n);t=pe.filter(t,e)}return pe.grep(e,function(e){return pe.inArray(e,t)>-1!==n})}function i(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}function o(e){var t={};return pe.each(e.match(De)||[],function(e,n){t[n]=!0}),t}function a(){re.addEventListener?(re.removeEventListener(\"DOMContentLoaded\",s),e.removeEventListener(\"load\",s)):(re.detachEvent(\"onreadystatechange\",s),e.detachEvent(\"onload\",s))}function s(){(re.addEventListener||\"load\"===e.event.type||\"complete\"===re.readyState)&&(a(),pe.ready())}function u(e,t,n){if(void 0===n&&1===e.nodeType){var r=\"data-\"+t.replace(_e,\"-$1\").toLowerCase();if(n=e.getAttribute(r),\"string\"==typeof n){try{n=\"true\"===n||\"false\"!==n&&(\"null\"===n?null:+n+\"\"===n?+n:qe.test(n)?pe.parseJSON(n):n)}catch(i){}pe.data(e,t,n)}else n=void 0}return n}function l(e){var t;for(t in e)if((\"data\"!==t||!pe.isEmptyObject(e[t]))&&\"toJSON\"!==t)return!1;return!0}function c(e,t,n,r){if(He(e)){var i,o,a=pe.expando,s=e.nodeType,u=s?pe.cache:e,l=s?e[a]:e[a]&&a;if(l&&u[l]&&(r||u[l].data)||void 0!==n||\"string\"!=typeof t)return l||(l=s?e[a]=ne.pop()||pe.guid++:a),u[l]||(u[l]=s?{}:{toJSON:pe.noop}),\"object\"!=typeof t&&\"function\"!=typeof t||(r?u[l]=pe.extend(u[l],t):u[l].data=pe.extend(u[l].data,t)),o=u[l],r||(o.data||(o.data={}),o=o.data),void 0!==n&&(o[pe.camelCase(t)]=n),\"string\"==typeof t?(i=o[t],null==i&&(i=o[pe.camelCase(t)])):i=o,i}}function f(e,t,n){if(He(e)){var r,i,o=e.nodeType,a=o?pe.cache:e,s=o?e[pe.expando]:pe.expando;if(a[s]){if(t&&(r=n?a[s]:a[s].data)){pe.isArray(t)?t=t.concat(pe.map(t,pe.camelCase)):t in r?t=[t]:(t=pe.camelCase(t),t=t in r?[t]:t.split(\" \")),i=t.length;for(;i--;)delete r[t[i]];if(n?!l(r):!pe.isEmptyObject(r))return}(n||(delete a[s].data,l(a[s])))&&(o?pe.cleanData([e],!0):fe.deleteExpando||a!=a.window?delete a[s]:a[s]=void 0)}}}function d(e,t,n,r){var i,o=1,a=20,s=r?function(){return r.cur()}:function(){return pe.css(e,t,\"\")},u=s(),l=n&&n[3]||(pe.cssNumber[t]?\"\":\"px\"),c=(pe.cssNumber[t]||\"px\"!==l&&+u)&&Me.exec(pe.css(e,t));if(c&&c[3]!==l){l=l||c[3],n=n||[],c=+u||1;do o=o||\".5\",c/=o,pe.style(e,t,c+l);while(o!==(o=s()/u)&&1!==o&&--a)}return n&&(c=+c||+u||0,i=n[1]?c+(n[1]+1)*n[2]:+n[2],r&&(r.unit=l,r.start=c,r.end=i)),i}function p(e){var t=ze.split(\"|\"),n=e.createDocumentFragment();if(n.createElement)for(;t.length;)n.createElement(t.pop());return n}function h(e,t){var n,r,i=0,o=\"undefined\"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||\"*\"):\"undefined\"!=typeof e.querySelectorAll?e.querySelectorAll(t||\"*\"):void 0;if(!o)for(o=[],n=e.childNodes||e;null!=(r=n[i]);i++)!t||pe.nodeName(r,t)?o.push(r):pe.merge(o,h(r,t));return void 0===t||t&&pe.nodeName(e,t)?pe.merge([e],o):o}function g(e,t){for(var n,r=0;null!=(n=e[r]);r++)pe._data(n,\"globalEval\",!t||pe._data(t[r],\"globalEval\"))}function m(e){Be.test(e.type)&&(e.defaultChecked=e.checked)}function y(e,t,n,r,i){for(var o,a,s,u,l,c,f,d=e.length,y=p(t),v=[],x=0;x<d;x++)if(a=e[x],a||0===a)if(\"object\"===pe.type(a))pe.merge(v,a.nodeType?[a]:a);else if(Ue.test(a)){for(u=u||y.appendChild(t.createElement(\"div\")),l=(We.exec(a)||[\"\",\"\"])[1].toLowerCase(),f=Xe[l]||Xe._default,u.innerHTML=f[1]+pe.htmlPrefilter(a)+f[2],o=f[0];o--;)u=u.lastChild;if(!fe.leadingWhitespace&&$e.test(a)&&v.push(t.createTextNode($e.exec(a)[0])),!fe.tbody)for(a=\"table\"!==l||Ve.test(a)?\"<table>\"!==f[1]||Ve.test(a)?0:u:u.firstChild,o=a&&a.childNodes.length;o--;)pe.nodeName(c=a.childNodes[o],\"tbody\")&&!c.childNodes.length&&a.removeChild(c);for(pe.merge(v,u.childNodes),u.textContent=\"\";u.firstChild;)u.removeChild(u.firstChild);u=y.lastChild}else v.push(t.createTextNode(a));for(u&&y.removeChild(u),fe.appendChecked||pe.grep(h(v,\"input\"),m),x=0;a=v[x++];)if(r&&pe.inArray(a,r)>-1)i&&i.push(a);else if(s=pe.contains(a.ownerDocument,a),u=h(y.appendChild(a),\"script\"),s&&g(u),n)for(o=0;a=u[o++];)Ie.test(a.type||\"\")&&n.push(a);return u=null,y}function v(){return!0}function x(){return!1}function b(){try{return re.activeElement}catch(e){}}function w(e,t,n,r,i,o){var a,s;if(\"object\"==typeof t){\"string\"!=typeof n&&(r=r||n,n=void 0);for(s in t)w(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&(\"string\"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),i===!1)i=x;else if(!i)return e;return 1===o&&(a=i,i=function(e){return pe().off(e),a.apply(this,arguments)},i.guid=a.guid||(a.guid=pe.guid++)),e.each(function(){pe.event.add(this,t,i,r,n)})}function T(e,t){return pe.nodeName(e,\"table\")&&pe.nodeName(11!==t.nodeType?t:t.firstChild,\"tr\")?e.getElementsByTagName(\"tbody\")[0]||e.appendChild(e.ownerDocument.createElement(\"tbody\")):e}function C(e){return e.type=(null!==pe.find.attr(e,\"type\"))+\"/\"+e.type,e}function E(e){var t=it.exec(e.type);return t?e.type=t[1]:e.removeAttribute(\"type\"),e}function N(e,t){if(1===t.nodeType&&pe.hasData(e)){var n,r,i,o=pe._data(e),a=pe._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;r<i;r++)pe.event.add(t,n,s[n][r])}a.data&&(a.data=pe.extend({},a.data))}}function k(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!fe.noCloneEvent&&t[pe.expando]){i=pe._data(t);for(r in i.events)pe.removeEvent(t,r,i.handle);t.removeAttribute(pe.expando)}\"script\"===n&&t.text!==e.text?(C(t).text=e.text,E(t)):\"object\"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),fe.html5Clone&&e.innerHTML&&!pe.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):\"input\"===n&&Be.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)}}function S(e,t,n,r){t=oe.apply([],t);var i,o,a,s,u,l,c=0,f=e.length,d=f-1,p=t[0],g=pe.isFunction(p);if(g||f>1&&\"string\"==typeof p&&!fe.checkClone&&rt.test(p))return e.each(function(i){var o=e.eq(i);g&&(t[0]=p.call(this,i,o.html())),S(o,t,n,r)});if(f&&(l=y(t,e[0].ownerDocument,!1,e,r),i=l.firstChild,1===l.childNodes.length&&(l=i),i||r)){for(s=pe.map(h(l,\"script\"),C),a=s.length;c<f;c++)o=l,c!==d&&(o=pe.clone(o,!0,!0),a&&pe.merge(s,h(o,\"script\"))),n.call(e[c],o,c);if(a)for(u=s[s.length-1].ownerDocument,pe.map(s,E),c=0;c<a;c++)o=s[c],Ie.test(o.type||\"\")&&!pe._data(o,\"globalEval\")&&pe.contains(u,o)&&(o.src?pe._evalUrl&&pe._evalUrl(o.src):pe.globalEval((o.text||o.textContent||o.innerHTML||\"\").replace(ot,\"\")));l=i=null}return e}function A(e,t,n){for(var r,i=t?pe.filter(t,e):e,o=0;null!=(r=i[o]);o++)n||1!==r.nodeType||pe.cleanData(h(r)),r.parentNode&&(n&&pe.contains(r.ownerDocument,r)&&g(h(r,\"script\")),r.parentNode.removeChild(r));return e}function D(e,t){var n=pe(t.createElement(e)).appendTo(t.body),r=pe.css(n[0],\"display\");return n.detach(),r}function j(e){var t=re,n=lt[e];return n||(n=D(e,t),\"none\"!==n&&n||(ut=(ut||pe(\"<iframe frameborder='0' width='0' height='0'/>\")).appendTo(t.documentElement),t=(ut[0].contentWindow||ut[0].contentDocument).document,t.write(),t.close(),n=D(e,t),ut.detach()),lt[e]=n),n}function L(e,t){return{get:function(){return e()?void delete this.get:(this.get=t).apply(this,arguments)}}}function H(e){if(e in Et)return e;for(var t=e.charAt(0).toUpperCase()+e.slice(1),n=Ct.length;n--;)if(e=Ct[n]+t,e in Et)return e}function q(e,t){for(var n,r,i,o=[],a=0,s=e.length;a<s;a++)r=e[a],r.style&&(o[a]=pe._data(r,\"olddisplay\"),n=r.style.display,t?(o[a]||\"none\"!==n||(r.style.display=\"\"),\"\"===r.style.display&&Re(r)&&(o[a]=pe._data(r,\"olddisplay\",j(r.nodeName)))):(i=Re(r),(n&&\"none\"!==n||!i)&&pe._data(r,\"olddisplay\",i?n:pe.css(r,\"display\"))));for(a=0;a<s;a++)r=e[a],r.style&&(t&&\"none\"!==r.style.display&&\"\"!==r.style.display||(r.style.display=t?o[a]||\"\":\"none\"));return e}function _(e,t,n){var r=bt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||\"px\"):t}function F(e,t,n,r,i){for(var o=n===(r?\"border\":\"content\")?4:\"width\"===t?1:0,a=0;o<4;o+=2)\"margin\"===n&&(a+=pe.css(e,n+Oe[o],!0,i)),r?(\"content\"===n&&(a-=pe.css(e,\"padding\"+Oe[o],!0,i)),\"margin\"!==n&&(a-=pe.css(e,\"border\"+Oe[o]+\"Width\",!0,i))):(a+=pe.css(e,\"padding\"+Oe[o],!0,i),\"padding\"!==n&&(a+=pe.css(e,\"border\"+Oe[o]+\"Width\",!0,i)));return a}function M(t,n,r){var i=!0,o=\"width\"===n?t.offsetWidth:t.offsetHeight,a=ht(t),s=fe.boxSizing&&\"border-box\"===pe.css(t,\"boxSizing\",!1,a);if(re.msFullscreenElement&&e.top!==e&&t.getClientRects().length&&(o=Math.round(100*t.getBoundingClientRect()[n])),o<=0||null==o){if(o=gt(t,n,a),(o<0||null==o)&&(o=t.style[n]),ft.test(o))return o;i=s&&(fe.boxSizingReliable()||o===t.style[n]),o=parseFloat(o)||0}return o+F(t,n,r||(s?\"border\":\"content\"),i,a)+\"px\"}function O(e,t,n,r,i){return new O.prototype.init(e,t,n,r,i)}function R(){return e.setTimeout(function(){Nt=void 0}),Nt=pe.now()}function P(e,t){var n,r={height:e},i=0;for(t=t?1:0;i<4;i+=2-t)n=Oe[i],r[\"margin\"+n]=r[\"padding\"+n]=e;return t&&(r.opacity=r.width=e),r}function B(e,t,n){for(var r,i=($.tweeners[t]||[]).concat($.tweeners[\"*\"]),o=0,a=i.length;o<a;o++)if(r=i[o].call(n,t,e))return r}function W(e,t,n){var r,i,o,a,s,u,l,c,f=this,d={},p=e.style,h=e.nodeType&&Re(e),g=pe._data(e,\"fxshow\");n.queue||(s=pe._queueHooks(e,\"fx\"),null==s.unqueued&&(s.unqueued=0,u=s.empty.fire,s.empty.fire=function(){s.unqueued||u()}),s.unqueued++,f.always(function(){f.always(function(){s.unqueued--,pe.queue(e,\"fx\").length||s.empty.fire()})})),1===e.nodeType&&(\"height\"in t||\"width\"in t)&&(n.overflow=[p.overflow,p.overflowX,p.overflowY],l=pe.css(e,\"display\"),c=\"none\"===l?pe._data(e,\"olddisplay\")||j(e.nodeName):l,\"inline\"===c&&\"none\"===pe.css(e,\"float\")&&(fe.inlineBlockNeedsLayout&&\"inline\"!==j(e.nodeName)?p.zoom=1:p.display=\"inline-block\")),n.overflow&&(p.overflow=\"hidden\",fe.shrinkWrapBlocks()||f.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],St.exec(i)){if(delete t[r],o=o||\"toggle\"===i,i===(h?\"hide\":\"show\")){if(\"show\"!==i||!g||void 0===g[r])continue;h=!0}d[r]=g&&g[r]||pe.style(e,r)}else l=void 0;if(pe.isEmptyObject(d))\"inline\"===(\"none\"===l?j(e.nodeName):l)&&(p.display=l);else{g?\"hidden\"in g&&(h=g.hidden):g=pe._data(e,\"fxshow\",{}),o&&(g.hidden=!h),h?pe(e).show():f.done(function(){pe(e).hide()}),f.done(function(){var t;pe._removeData(e,\"fxshow\");for(t in d)pe.style(e,t,d[t])});for(r in d)a=B(h?g[r]:0,r,f),r in g||(g[r]=a.start,h&&(a.end=a.start,a.start=\"width\"===r||\"height\"===r?1:0))}}function I(e,t){var n,r,i,o,a;for(n in e)if(r=pe.camelCase(n),i=t[r],o=e[n],pe.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),a=pe.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}function $(e,t,n){var r,i,o=0,a=$.prefilters.length,s=pe.Deferred().always(function(){delete u.elem}),u=function(){if(i)return!1;for(var t=Nt||R(),n=Math.max(0,l.startTime+l.duration-t),r=n/l.duration||0,o=1-r,a=0,u=l.tweens.length;a<u;a++)l.tweens[a].run(o);return s.notifyWith(e,[l,o,n]),o<1&&u?n:(s.resolveWith(e,[l]),!1)},l=s.promise({elem:e,props:pe.extend({},t),opts:pe.extend(!0,{specialEasing:{},easing:pe.easing._default},n),originalProperties:t,originalOptions:n,startTime:Nt||R(),duration:n.duration,tweens:[],createTween:function(t,n){var r=pe.Tween(e,l.opts,t,n,l.opts.specialEasing[t]||l.opts.easing);return l.tweens.push(r),r},stop:function(t){var n=0,r=t?l.tweens.length:0;if(i)return this;for(i=!0;n<r;n++)l.tweens[n].run(1);return t?(s.notifyWith(e,[l,1,0]),s.resolveWith(e,[l,t])):s.rejectWith(e,[l,t]),this}}),c=l.props;for(I(c,l.opts.specialEasing);o<a;o++)if(r=$.prefilters[o].call(l,e,c,l.opts))return pe.isFunction(r.stop)&&(pe._queueHooks(l.elem,l.opts.queue).stop=pe.proxy(r.stop,r)),r;return pe.map(c,B,l),pe.isFunction(l.opts.start)&&l.opts.start.call(e,l),pe.fx.timer(pe.extend(u,{elem:e,anim:l,queue:l.opts.queue})),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always)}function z(e){return pe.attr(e,\"class\")||\"\"}function X(e){return function(t,n){\"string\"!=typeof t&&(n=t,t=\"*\");var r,i=0,o=t.toLowerCase().match(De)||[];if(pe.isFunction(n))for(;r=o[i++];)\"+\"===r.charAt(0)?(r=r.slice(1)||\"*\",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function U(e,t,n,r){function i(s){var u;return o[s]=!0,pe.each(e[s]||[],function(e,s){var l=s(t,n,r);return\"string\"!=typeof l||a||o[l]?a?!(u=l):void 0:(t.dataTypes.unshift(l),i(l),!1)}),u}var o={},a=e===Qt;return i(t.dataTypes[0])||!o[\"*\"]&&i(\"*\")}function V(e,t){var n,r,i=pe.ajaxSettings.flatOptions||{};for(r in t)void 0!==t[r]&&((i[r]?e:n||(n={}))[r]=t[r]);return n&&pe.extend(!0,e,n),e}function Y(e,t,n){for(var r,i,o,a,s=e.contents,u=e.dataTypes;\"*\"===u[0];)u.shift(),void 0===i&&(i=e.mimeType||t.getResponseHeader(\"Content-Type\"));if(i)for(a in s)if(s[a]&&s[a].test(i)){u.unshift(a);break}if(u[0]in n)o=u[0];else{for(a in n){if(!u[0]||e.converters[a+\" \"+u[0]]){o=a;break}r||(r=a)}o=o||r}if(o)return o!==u[0]&&u.unshift(o),n[o]}function J(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];for(o=c.shift();o;)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if(\"*\"===o)o=u;else if(\"*\"!==u&&u!==o){if(a=l[u+\" \"+o]||l[\"* \"+o],!a)for(i in l)if(s=i.split(\" \"),s[1]===o&&(a=l[u+\" \"+s[0]]||l[\"* \"+s[0]])){a===!0?a=l[i]:l[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(f){return{state:\"parsererror\",error:a?f:\"No conversion from \"+u+\" to \"+o}}}return{state:\"success\",data:t}}function G(e){return e.style&&e.style.display||pe.css(e,\"display\")}function K(e){for(;e&&1===e.nodeType;){if(\"none\"===G(e)||\"hidden\"===e.type)return!0;e=e.parentNode}return!1}function Q(e,t,n,r){var i;if(pe.isArray(t))pe.each(t,function(t,i){n||rn.test(e)?r(e,i):Q(e+\"[\"+(\"object\"==typeof i&&null!=i?t:\"\")+\"]\",i,n,r)});else if(n||\"object\"!==pe.type(t))r(e,t);else for(i in t)Q(e+\"[\"+i+\"]\",t[i],n,r)}function Z(){try{return new e.XMLHttpRequest}catch(t){}}function ee(){try{return new e.ActiveXObject(\"Microsoft.XMLHTTP\")}catch(t){}}function te(e){return pe.isWindow(e)?e:9===e.nodeType&&(e.defaultView||e.parentWindow)}var ne=[],re=e.document,ie=ne.slice,oe=ne.concat,ae=ne.push,se=ne.indexOf,ue={},le=ue.toString,ce=ue.hasOwnProperty,fe={},de=\"1.12.3\",pe=function(e,t){return new pe.fn.init(e,t)},he=/^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g,ge=/^-ms-/,me=/-([\\da-z])/gi,ye=function(e,t){return t.toUpperCase()};pe.fn=pe.prototype={jquery:de,constructor:pe,selector:\"\",length:0,toArray:function(){return ie.call(this)},get:function(e){return null!=e?e<0?this[e+this.length]:this[e]:ie.call(this)},pushStack:function(e){var t=pe.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e){return pe.each(this,e)},map:function(e){return this.pushStack(pe.map(this,function(t,n){return e.call(t,n,t)}))},slice:function(){return this.pushStack(ie.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(n>=0&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:ae,sort:ne.sort,splice:ne.splice},pe.extend=pe.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for(\"boolean\"==typeof a&&(l=a,a=arguments[s]||{},s++),\"object\"==typeof a||pe.isFunction(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(i=arguments[s]))for(r in i)e=a[r],n=i[r],a!==n&&(l&&n&&(pe.isPlainObject(n)||(t=pe.isArray(n)))?(t?(t=!1,o=e&&pe.isArray(e)?e:[]):o=e&&pe.isPlainObject(e)?e:{},a[r]=pe.extend(l,o,n)):void 0!==n&&(a[r]=n));return a},pe.extend({expando:\"jQuery\"+(de+Math.random()).replace(/\\D/g,\"\"),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isFunction:function(e){return\"function\"===pe.type(e)},isArray:Array.isArray||function(e){return\"array\"===pe.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){var t=e&&e.toString();return!pe.isArray(e)&&t-parseFloat(t)+1>=0},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},isPlainObject:function(e){var t;if(!e||\"object\"!==pe.type(e)||e.nodeType||pe.isWindow(e))return!1;try{if(e.constructor&&!ce.call(e,\"constructor\")&&!ce.call(e.constructor.prototype,\"isPrototypeOf\"))return!1}catch(n){return!1}if(!fe.ownFirst)for(t in e)return ce.call(e,t);for(t in e);return void 0===t||ce.call(e,t)},type:function(e){return null==e?e+\"\":\"object\"==typeof e||\"function\"==typeof e?ue[le.call(e)]||\"object\":typeof e},globalEval:function(t){t&&pe.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(ge,\"ms-\").replace(me,ye)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t){var r,i=0;if(n(e))for(r=e.length;i<r&&t.call(e[i],i,e[i])!==!1;i++);else for(i in e)if(t.call(e[i],i,e[i])===!1)break;return e},trim:function(e){return null==e?\"\":(e+\"\").replace(he,\"\")},makeArray:function(e,t){var r=t||[];return null!=e&&(n(Object(e))?pe.merge(r,\"string\"==typeof e?[e]:e):ae.call(r,e)),r},inArray:function(e,t,n){var r;if(t){if(se)return se.call(t,e,n);for(r=t.length,n=n?n<0?Math.max(0,r+n):n:0;n<r;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;)e[i++]=t[r++];if(n!==n)for(;void 0!==t[r];)e[i++]=t[r++];return e.length=i,e},grep:function(e,t,n){for(var r,i=[],o=0,a=e.length,s=!n;o<a;o++)r=!t(e[o],o),r!==s&&i.push(e[o]);return i},map:function(e,t,r){var i,o,a=0,s=[];if(n(e))for(i=e.length;a<i;a++)o=t(e[a],a,r),null!=o&&s.push(o);else for(a in e)o=t(e[a],a,r),null!=o&&s.push(o);return oe.apply([],s)},guid:1,proxy:function(e,t){var n,r,i;if(\"string\"==typeof t&&(i=e[t],t=e,e=i),pe.isFunction(e))return n=ie.call(arguments,2),r=function(){return e.apply(t||this,n.concat(ie.call(arguments)))},r.guid=e.guid=e.guid||pe.guid++,r},now:function(){return+new Date},support:fe}),\"function\"==typeof Symbol&&(pe.fn[Symbol.iterator]=ne[Symbol.iterator]),pe.each(\"Boolean Number String Function Array Date RegExp Object Error Symbol\".split(\" \"),function(e,t){ue[\"[object \"+t+\"]\"]=t.toLowerCase()});var ve=function(e){function t(e,t,n,r){var i,o,a,s,u,l,f,p,h=t&&t.ownerDocument,g=t?t.nodeType:9;if(n=n||[],\"string\"!=typeof e||!e||1!==g&&9!==g&&11!==g)return n;if(!r&&((t?t.ownerDocument||t:B)!==H&&L(t),t=t||H,_)){if(11!==g&&(l=ye.exec(e)))if(i=l[1]){if(9===g){if(!(a=t.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(h&&(a=h.getElementById(i))&&R(t,a)&&a.id===i)return n.push(a),n}else{if(l[2])return Q.apply(n,t.getElementsByTagName(e)),n;if((i=l[3])&&w.getElementsByClassName&&t.getElementsByClassName)return Q.apply(n,t.getElementsByClassName(i)),n}if(w.qsa&&!X[e+\" \"]&&(!F||!F.test(e))){if(1!==g)h=t,p=e;else if(\"object\"!==t.nodeName.toLowerCase()){for((s=t.getAttribute(\"id\"))?s=s.replace(xe,\"\\\\$&\"):t.setAttribute(\"id\",s=P),f=N(e),o=f.length,u=de.test(s)?\"#\"+s:\"[id='\"+s+\"']\";o--;)f[o]=u+\" \"+d(f[o]);p=f.join(\",\"),h=ve.test(e)&&c(t.parentNode)||t}if(p)try{return Q.apply(n,h.querySelectorAll(p)),n}catch(m){}finally{s===P&&t.removeAttribute(\"id\")}}}return S(e.replace(se,\"$1\"),t,n,r)}function n(){function e(n,r){return t.push(n+\" \")>T.cacheLength&&delete e[t.shift()],e[n+\" \"]=r}var t=[];return e}function r(e){return e[P]=!0,e}function i(e){var t=H.createElement(\"div\");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function o(e,t){for(var n=e.split(\"|\"),r=n.length;r--;)T.attrHandle[n[r]]=t}function a(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||V)-(~e.sourceIndex||V);if(r)return r;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function s(e){return function(t){var n=t.nodeName.toLowerCase();return\"input\"===n&&t.type===e}}function u(e){return function(t){var n=t.nodeName.toLowerCase();return(\"input\"===n||\"button\"===n)&&t.type===e}}function l(e){return r(function(t){return t=+t,r(function(n,r){for(var i,o=e([],n.length,t),a=o.length;a--;)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}function c(e){return e&&\"undefined\"!=typeof e.getElementsByTagName&&e}function f(){}function d(e){for(var t=0,n=e.length,r=\"\";t<n;t++)r+=e[t].value;return r}function p(e,t,n){var r=t.dir,i=n&&\"parentNode\"===r,o=I++;return t.first?function(t,n,o){for(;t=t[r];)if(1===t.nodeType||i)return e(t,n,o)}:function(t,n,a){var s,u,l,c=[W,o];if(a){for(;t=t[r];)if((1===t.nodeType||i)&&e(t,n,a))return!0}else for(;t=t[r];)if(1===t.nodeType||i){if(l=t[P]||(t[P]={}),u=l[t.uniqueID]||(l[t.uniqueID]={}),(s=u[r])&&s[0]===W&&s[1]===o)return c[2]=s[2];if(u[r]=c,c[2]=e(t,n,a))return!0}}}function h(e){return e.length>1?function(t,n,r){for(var i=e.length;i--;)if(!e[i](t,n,r))return!1;return!0}:e[0]}function g(e,n,r){for(var i=0,o=n.length;i<o;i++)t(e,n[i],r);return r}function m(e,t,n,r,i){for(var o,a=[],s=0,u=e.length,l=null!=t;s<u;s++)(o=e[s])&&(n&&!n(o,r,i)||(a.push(o),l&&t.push(s)));return a}function y(e,t,n,i,o,a){return i&&!i[P]&&(i=y(i)),o&&!o[P]&&(o=y(o,a)),r(function(r,a,s,u){var l,c,f,d=[],p=[],h=a.length,y=r||g(t||\"*\",s.nodeType?[s]:s,[]),v=!e||!r&&t?y:m(y,d,e,s,u),x=n?o||(r?e:h||i)?[]:a:v;if(n&&n(v,x,s,u),i)for(l=m(x,p),i(l,[],s,u),c=l.length;c--;)(f=l[c])&&(x[p[c]]=!(v[p[c]]=f));if(r){if(o||e){if(o){for(l=[],c=x.length;c--;)(f=x[c])&&l.push(v[c]=f);o(null,x=[],l,u)}for(c=x.length;c--;)(f=x[c])&&(l=o?ee(r,f):d[c])>-1&&(r[l]=!(a[l]=f))}}else x=m(x===a?x.splice(h,x.length):x),o?o(null,a,x,u):Q.apply(a,x)})}function v(e){for(var t,n,r,i=e.length,o=T.relative[e[0].type],a=o||T.relative[\" \"],s=o?1:0,u=p(function(e){return e===t},a,!0),l=p(function(e){return ee(t,e)>-1},a,!0),c=[function(e,n,r){var i=!o&&(r||n!==A)||((t=n).nodeType?u(e,n,r):l(e,n,r));return t=null,i}];s<i;s++)if(n=T.relative[e[s].type])c=[p(h(c),n)];else{if(n=T.filter[e[s].type].apply(null,e[s].matches),n[P]){for(r=++s;r<i&&!T.relative[e[r].type];r++);return y(s>1&&h(c),s>1&&d(e.slice(0,s-1).concat({value:\" \"===e[s-2].type?\"*\":\"\"})).replace(se,\"$1\"),n,s<r&&v(e.slice(s,r)),r<i&&v(e=e.slice(r)),r<i&&d(e))}c.push(n)}return h(c)}function x(e,n){var i=n.length>0,o=e.length>0,a=function(r,a,s,u,l){var c,f,d,p=0,h=\"0\",g=r&&[],y=[],v=A,x=r||o&&T.find.TAG(\"*\",l),b=W+=null==v?1:Math.random()||.1,w=x.length;for(l&&(A=a===H||a||l);h!==w&&null!=(c=x[h]);h++){if(o&&c){for(f=0,a||c.ownerDocument===H||(L(c),s=!_);d=e[f++];)if(d(c,a||H,s)){u.push(c);break}l&&(W=b)}i&&((c=!d&&c)&&p--,r&&g.push(c))}if(p+=h,i&&h!==p){for(f=0;d=n[f++];)d(g,y,a,s);if(r){if(p>0)for(;h--;)g[h]||y[h]||(y[h]=G.call(u));y=m(y)}Q.apply(u,y),l&&!r&&y.length>0&&p+n.length>1&&t.uniqueSort(u)}return l&&(W=b,A=v),g};return i?r(a):a}var b,w,T,C,E,N,k,S,A,D,j,L,H,q,_,F,M,O,R,P=\"sizzle\"+1*new Date,B=e.document,W=0,I=0,$=n(),z=n(),X=n(),U=function(e,t){return e===t&&(j=!0),0},V=1<<31,Y={}.hasOwnProperty,J=[],G=J.pop,K=J.push,Q=J.push,Z=J.slice,ee=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},te=\"checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped\",ne=\"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",re=\"(?:\\\\\\\\.|[\\\\w-]|[^\\\\x00-\\\\xa0])+\",ie=\"\\\\[\"+ne+\"*(\"+re+\")(?:\"+ne+\"*([*^$|!~]?=)\"+ne+\"*(?:'((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\"|(\"+re+\"))|)\"+ne+\"*\\\\]\",oe=\":(\"+re+\")(?:\\\\((('((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\")|((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\"+ie+\")*)|.*)\\\\)|)\",ae=new RegExp(ne+\"+\",\"g\"),se=new RegExp(\"^\"+ne+\"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\"+ne+\"+$\",\"g\"),ue=new RegExp(\"^\"+ne+\"*,\"+ne+\"*\"),le=new RegExp(\"^\"+ne+\"*([>+~]|\"+ne+\")\"+ne+\"*\"),ce=new RegExp(\"=\"+ne+\"*([^\\\\]'\\\"]*?)\"+ne+\"*\\\\]\",\"g\"),fe=new RegExp(oe),de=new RegExp(\"^\"+re+\"$\"),pe={ID:new RegExp(\"^#(\"+re+\")\"),CLASS:new RegExp(\"^\\\\.(\"+re+\")\"),TAG:new RegExp(\"^(\"+re+\"|[*])\"),ATTR:new RegExp(\"^\"+ie),PSEUDO:new RegExp(\"^\"+oe),CHILD:new RegExp(\"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\"+ne+\"*(even|odd|(([+-]|)(\\\\d*)n|)\"+ne+\"*(?:([+-]|)\"+ne+\"*(\\\\d+)|))\"+ne+\"*\\\\)|)\",\"i\"),bool:new RegExp(\"^(?:\"+te+\")$\",\"i\"),needsContext:new RegExp(\"^\"+ne+\"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\"+ne+\"*((?:-\\\\d)?\\\\d*)\"+ne+\"*\\\\)|)(?=[^-]|$)\",\"i\")},he=/^(?:input|select|textarea|button)$/i,ge=/^h\\d$/i,me=/^[^{]+\\{\\s*\\[native \\w/,ye=/^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,ve=/[+~]/,xe=/'|\\\\/g,be=new RegExp(\"\\\\\\\\([\\\\da-f]{1,6}\"+ne+\"?|(\"+ne+\")|.)\",\"ig\"),we=function(e,t,n){var r=\"0x\"+t-65536;return r!==r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},Te=function(){L()};try{Q.apply(J=Z.call(B.childNodes),B.childNodes),J[B.childNodes.length].nodeType}catch(Ce){Q={apply:J.length?function(e,t){K.apply(e,Z.call(t))}:function(e,t){for(var n=e.length,r=0;e[n++]=t[r++];);e.length=n-1}}}w=t.support={},E=t.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return!!t&&\"HTML\"!==t.nodeName},L=t.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:B;return r!==H&&9===r.nodeType&&r.documentElement?(H=r,q=H.documentElement,_=!E(H),(n=H.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener(\"unload\",Te,!1):n.attachEvent&&n.attachEvent(\"onunload\",Te)),w.attributes=i(function(e){return e.className=\"i\",!e.getAttribute(\"className\")}),w.getElementsByTagName=i(function(e){return e.appendChild(H.createComment(\"\")),!e.getElementsByTagName(\"*\").length}),w.getElementsByClassName=me.test(H.getElementsByClassName),w.getById=i(function(e){return q.appendChild(e).id=P,!H.getElementsByName||!H.getElementsByName(P).length}),w.getById?(T.find.ID=function(e,t){if(\"undefined\"!=typeof t.getElementById&&_){var n=t.getElementById(e);return n?[n]:[]}},T.filter.ID=function(e){var t=e.replace(be,we);return function(e){return e.getAttribute(\"id\")===t}}):(delete T.find.ID,T.filter.ID=function(e){var t=e.replace(be,we);return function(e){var n=\"undefined\"!=typeof e.getAttributeNode&&e.getAttributeNode(\"id\");return n&&n.value===t}}),T.find.TAG=w.getElementsByTagName?function(e,t){return\"undefined\"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):w.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if(\"*\"===e){for(;n=o[i++];)1===n.nodeType&&r.push(n);return r}return o},T.find.CLASS=w.getElementsByClassName&&function(e,t){if(\"undefined\"!=typeof t.getElementsByClassName&&_)return t.getElementsByClassName(e)},M=[],F=[],(w.qsa=me.test(H.querySelectorAll))&&(i(function(e){q.appendChild(e).innerHTML=\"<a id='\"+P+\"'></a><select id='\"+P+\"-\\r\\\\' msallowcapture=''><option selected=''></option></select>\",e.querySelectorAll(\"[msallowcapture^='']\").length&&F.push(\"[*^$]=\"+ne+\"*(?:''|\\\"\\\")\"),e.querySelectorAll(\"[selected]\").length||F.push(\"\\\\[\"+ne+\"*(?:value|\"+te+\")\"),e.querySelectorAll(\"[id~=\"+P+\"-]\").length||F.push(\"~=\"),e.querySelectorAll(\":checked\").length||F.push(\":checked\"),e.querySelectorAll(\"a#\"+P+\"+*\").length||F.push(\".#.+[+~]\")}),i(function(e){var t=H.createElement(\"input\");t.setAttribute(\"type\",\"hidden\"),e.appendChild(t).setAttribute(\"name\",\"D\"),e.querySelectorAll(\"[name=d]\").length&&F.push(\"name\"+ne+\"*[*^$|!~]?=\"),e.querySelectorAll(\":enabled\").length||F.push(\":enabled\",\":disabled\"),e.querySelectorAll(\"*,:x\"),F.push(\",.*:\")})),(w.matchesSelector=me.test(O=q.matches||q.webkitMatchesSelector||q.mozMatchesSelector||q.oMatchesSelector||q.msMatchesSelector))&&i(function(e){w.disconnectedMatch=O.call(e,\"div\"),O.call(e,\"[s!='']:x\"),M.push(\"!=\",oe)}),F=F.length&&new RegExp(F.join(\"|\")),M=M.length&&new RegExp(M.join(\"|\")),t=me.test(q.compareDocumentPosition),R=t||me.test(q.contains)?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)for(;t=t.parentNode;)if(t===e)return!0;return!1},U=t?function(e,t){if(e===t)return j=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n?n:(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1,1&n||!w.sortDetached&&t.compareDocumentPosition(e)===n?e===H||e.ownerDocument===B&&R(B,e)?-1:t===H||t.ownerDocument===B&&R(B,t)?1:D?ee(D,e)-ee(D,t):0:4&n?-1:1)}:function(e,t){if(e===t)return j=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,s=[e],u=[t];if(!i||!o)return e===H?-1:t===H?1:i?-1:o?1:D?ee(D,e)-ee(D,t):0;if(i===o)return a(e,t);for(n=e;n=n.parentNode;)s.unshift(n);for(n=t;n=n.parentNode;)u.unshift(n);for(;s[r]===u[r];)r++;return r?a(s[r],u[r]):s[r]===B?-1:u[r]===B?1:0},H):H},t.matches=function(e,n){return t(e,null,null,n)},t.matchesSelector=function(e,n){if((e.ownerDocument||e)!==H&&L(e),n=n.replace(ce,\"='$1']\"),w.matchesSelector&&_&&!X[n+\" \"]&&(!M||!M.test(n))&&(!F||!F.test(n)))try{var r=O.call(e,n);if(r||w.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(i){}return t(n,H,null,[e]).length>0},t.contains=function(e,t){return(e.ownerDocument||e)!==H&&L(e),R(e,t)},t.attr=function(e,t){(e.ownerDocument||e)!==H&&L(e);var n=T.attrHandle[t.toLowerCase()],r=n&&Y.call(T.attrHandle,t.toLowerCase())?n(e,t,!_):void 0;return void 0!==r?r:w.attributes||!_?e.getAttribute(t):(r=e.getAttributeNode(t))&&r.specified?r.value:null},t.error=function(e){throw new Error(\"Syntax error, unrecognized expression: \"+e)},t.uniqueSort=function(e){var t,n=[],r=0,i=0;if(j=!w.detectDuplicates,D=!w.sortStable&&e.slice(0),e.sort(U),j){for(;t=e[i++];)t===e[i]&&(r=n.push(i));for(;r--;)e.splice(n[r],1)}return D=null,e},C=t.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+=C(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r++];)n+=C(t);return n},T=t.selectors={cacheLength:50,createPseudo:r,match:pe,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(be,we),e[3]=(e[3]||e[4]||e[5]||\"\").replace(be,we),\"~=\"===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]||t.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]&&t.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return pe.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||\"\":n&&fe.test(n)&&(t=N(n,!0))&&(t=n.indexOf(\")\",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(be,we).toLowerCase();return\"*\"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=$[e+\" \"];return t||(t=new RegExp(\"(^|\"+ne+\")\"+e+\"(\"+ne+\"|$)\"))&&$(e,function(e){return t.test(\"string\"==typeof e.className&&e.className||\"undefined\"!=typeof e.getAttribute&&e.getAttribute(\"class\")||\"\")})},ATTR:function(e,n,r){return function(i){var o=t.attr(i,e);return null==o?\"!=\"===n:!n||(o+=\"\",\"=\"===n?o===r:\"!=\"===n?o!==r:\"^=\"===n?r&&0===o.indexOf(r):\"*=\"===n?r&&o.indexOf(r)>-1:\"$=\"===n?r&&o.slice(-r.length)===r:\"~=\"===n?(\" \"+o.replace(ae,\" \")+\" \").indexOf(r)>-1:\"|=\"===n&&(o===r||o.slice(0,r.length+1)===r+\"-\"))}},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,u){var l,c,f,d,p,h,g=o!==a?\"nextSibling\":\"previousSibling\",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!u&&!s,x=!1;if(m){if(o){for(;g;){for(d=t;d=d[g];)if(s?d.nodeName.toLowerCase()===y:1===d.nodeType)return!1;h=g=\"only\"===e&&!h&&\"nextSibling\"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){for(d=m,f=d[P]||(d[P]={}),c=f[d.uniqueID]||(f[d.uniqueID]={}),\nl=c[e]||[],p=l[0]===W&&l[1],x=p&&l[2],d=p&&m.childNodes[p];d=++p&&d&&d[g]||(x=p=0)||h.pop();)if(1===d.nodeType&&++x&&d===t){c[e]=[W,p,x];break}}else if(v&&(d=t,f=d[P]||(d[P]={}),c=f[d.uniqueID]||(f[d.uniqueID]={}),l=c[e]||[],p=l[0]===W&&l[1],x=p),x===!1)for(;(d=++p&&d&&d[g]||(x=p=0)||h.pop())&&((s?d.nodeName.toLowerCase()!==y:1!==d.nodeType)||!++x||(v&&(f=d[P]||(d[P]={}),c=f[d.uniqueID]||(f[d.uniqueID]={}),c[e]=[W,x]),d!==t)););return x-=i,x===r||x%r===0&&x/r>=0}}},PSEUDO:function(e,n){var i,o=T.pseudos[e]||T.setFilters[e.toLowerCase()]||t.error(\"unsupported pseudo: \"+e);return o[P]?o(n):o.length>1?(i=[e,e,\"\",n],T.setFilters.hasOwnProperty(e.toLowerCase())?r(function(e,t){for(var r,i=o(e,n),a=i.length;a--;)r=ee(e,i[a]),e[r]=!(t[r]=i[a])}):function(e){return o(e,0,i)}):o}},pseudos:{not:r(function(e){var t=[],n=[],i=k(e.replace(se,\"$1\"));return i[P]?r(function(e,t,n,r){for(var o,a=i(e,null,r,[]),s=e.length;s--;)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,r,o){return t[0]=e,i(t,null,o,n),t[0]=null,!n.pop()}}),has:r(function(e){return function(n){return t(e,n).length>0}}),contains:r(function(e){return e=e.replace(be,we),function(t){return(t.textContent||t.innerText||C(t)).indexOf(e)>-1}}),lang:r(function(e){return de.test(e||\"\")||t.error(\"unsupported lang: \"+e),e=e.replace(be,we).toLowerCase(),function(t){var n;do if(n=_?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===q},focus:function(e){return e===H.activeElement&&(!H.hasFocus||H.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.nodeType<6)return!1;return!0},parent:function(e){return!T.pseudos.empty(e)},header:function(e){return ge.test(e.nodeName)},input:function(e){return he.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\"))||\"text\"===t.toLowerCase())},first:l(function(){return[0]}),last:l(function(e,t){return[t-1]}),eq:l(function(e,t,n){return[n<0?n+t:n]}),even:l(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:l(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:l(function(e,t,n){for(var r=n<0?n+t:n;--r>=0;)e.push(r);return e}),gt:l(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}},T.pseudos.nth=T.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})T.pseudos[b]=s(b);for(b in{submit:!0,reset:!0})T.pseudos[b]=u(b);return f.prototype=T.filters=T.pseudos,T.setFilters=new f,N=t.tokenize=function(e,n){var r,i,o,a,s,u,l,c=z[e+\" \"];if(c)return n?0:c.slice(0);for(s=e,u=[],l=T.preFilter;s;){r&&!(i=ue.exec(s))||(i&&(s=s.slice(i[0].length)||s),u.push(o=[])),r=!1,(i=le.exec(s))&&(r=i.shift(),o.push({value:r,type:i[0].replace(se,\" \")}),s=s.slice(r.length));for(a in T.filter)!(i=pe[a].exec(s))||l[a]&&!(i=l[a](i))||(r=i.shift(),o.push({value:r,type:a,matches:i}),s=s.slice(r.length));if(!r)break}return n?s.length:s?t.error(e):z(e,u).slice(0)},k=t.compile=function(e,t){var n,r=[],i=[],o=X[e+\" \"];if(!o){for(t||(t=N(e)),n=t.length;n--;)o=v(t[n]),o[P]?r.push(o):i.push(o);o=X(e,x(i,r)),o.selector=e}return o},S=t.select=function(e,t,n,r){var i,o,a,s,u,l=\"function\"==typeof e&&e,f=!r&&N(e=l.selector||e);if(n=n||[],1===f.length){if(o=f[0]=f[0].slice(0),o.length>2&&\"ID\"===(a=o[0]).type&&w.getById&&9===t.nodeType&&_&&T.relative[o[1].type]){if(t=(T.find.ID(a.matches[0].replace(be,we),t)||[])[0],!t)return n;l&&(t=t.parentNode),e=e.slice(o.shift().value.length)}for(i=pe.needsContext.test(e)?0:o.length;i--&&(a=o[i],!T.relative[s=a.type]);)if((u=T.find[s])&&(r=u(a.matches[0].replace(be,we),ve.test(o[0].type)&&c(t.parentNode)||t))){if(o.splice(i,1),e=r.length&&d(o),!e)return Q.apply(n,r),n;break}}return(l||k(e,f))(r,t,!_,n,!t||ve.test(e)&&c(t.parentNode)||t),n},w.sortStable=P.split(\"\").sort(U).join(\"\")===P,w.detectDuplicates=!!j,L(),w.sortDetached=i(function(e){return 1&e.compareDocumentPosition(H.createElement(\"div\"))}),i(function(e){return e.innerHTML=\"<a href='#'></a>\",\"#\"===e.firstChild.getAttribute(\"href\")})||o(\"type|href|height|width\",function(e,t,n){if(!n)return e.getAttribute(t,\"type\"===t.toLowerCase()?1:2)}),w.attributes&&i(function(e){return e.innerHTML=\"<input/>\",e.firstChild.setAttribute(\"value\",\"\"),\"\"===e.firstChild.getAttribute(\"value\")})||o(\"value\",function(e,t,n){if(!n&&\"input\"===e.nodeName.toLowerCase())return e.defaultValue}),i(function(e){return null==e.getAttribute(\"disabled\")})||o(te,function(e,t,n){var r;if(!n)return e[t]===!0?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),t}(e);pe.find=ve,pe.expr=ve.selectors,pe.expr[\":\"]=pe.expr.pseudos,pe.uniqueSort=pe.unique=ve.uniqueSort,pe.text=ve.getText,pe.isXMLDoc=ve.isXML,pe.contains=ve.contains;var xe=function(e,t,n){for(var r=[],i=void 0!==n;(e=e[t])&&9!==e.nodeType;)if(1===e.nodeType){if(i&&pe(e).is(n))break;r.push(e)}return r},be=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},we=pe.expr.match.needsContext,Te=/^<([\\w-]+)\\s*\\/?>(?:<\\/\\1>|)$/,Ce=/^.[^:#\\[\\.,]*$/;pe.filter=function(e,t,n){var r=t[0];return n&&(e=\":not(\"+e+\")\"),1===t.length&&1===r.nodeType?pe.find.matchesSelector(r,e)?[r]:[]:pe.find.matches(e,pe.grep(t,function(e){return 1===e.nodeType}))},pe.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if(\"string\"!=typeof e)return this.pushStack(pe(e).filter(function(){for(t=0;t<i;t++)if(pe.contains(r[t],this))return!0}));for(t=0;t<i;t++)pe.find(e,r[t],n);return n=this.pushStack(i>1?pe.unique(n):n),n.selector=this.selector?this.selector+\" \"+e:e,n},filter:function(e){return this.pushStack(r(this,e||[],!1))},not:function(e){return this.pushStack(r(this,e||[],!0))},is:function(e){return!!r(this,\"string\"==typeof e&&we.test(e)?pe(e):e||[],!1).length}});var Ee,Ne=/^(?:\\s*(<[\\w\\W]+>)[^>]*|#([\\w-]*))$/,ke=pe.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||Ee,\"string\"==typeof e){if(r=\"<\"===e.charAt(0)&&\">\"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:Ne.exec(e),!r||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof pe?t[0]:t,pe.merge(this,pe.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:re,!0)),Te.test(r[1])&&pe.isPlainObject(t))for(r in t)pe.isFunction(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}if(i=re.getElementById(r[2]),i&&i.parentNode){if(i.id!==r[2])return Ee.find(e);this.length=1,this[0]=i}return this.context=re,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):pe.isFunction(e)?\"undefined\"!=typeof n.ready?n.ready(e):e(pe):(void 0!==e.selector&&(this.selector=e.selector,this.context=e.context),pe.makeArray(e,this))};ke.prototype=pe.fn,Ee=pe(re);var Se=/^(?:parents|prev(?:Until|All))/,Ae={children:!0,contents:!0,next:!0,prev:!0};pe.fn.extend({has:function(e){var t,n=pe(e,this),r=n.length;return this.filter(function(){for(t=0;t<r;t++)if(pe.contains(this,n[t]))return!0})},closest:function(e,t){for(var n,r=0,i=this.length,o=[],a=we.test(e)||\"string\"!=typeof e?pe(e,t||this.context):0;r<i;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(n.nodeType<11&&(a?a.index(n)>-1:1===n.nodeType&&pe.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(o.length>1?pe.uniqueSort(o):o)},index:function(e){return e?\"string\"==typeof e?pe.inArray(this[0],pe(e)):pe.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(pe.uniqueSort(pe.merge(this.get(),pe(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),pe.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return xe(e,\"parentNode\")},parentsUntil:function(e,t,n){return xe(e,\"parentNode\",n)},next:function(e){return i(e,\"nextSibling\")},prev:function(e){return i(e,\"previousSibling\")},nextAll:function(e){return xe(e,\"nextSibling\")},prevAll:function(e){return xe(e,\"previousSibling\")},nextUntil:function(e,t,n){return xe(e,\"nextSibling\",n)},prevUntil:function(e,t,n){return xe(e,\"previousSibling\",n)},siblings:function(e){return be((e.parentNode||{}).firstChild,e)},children:function(e){return be(e.firstChild)},contents:function(e){return pe.nodeName(e,\"iframe\")?e.contentDocument||e.contentWindow.document:pe.merge([],e.childNodes)}},function(e,t){pe.fn[e]=function(n,r){var i=pe.map(this,t,n);return\"Until\"!==e.slice(-5)&&(r=n),r&&\"string\"==typeof r&&(i=pe.filter(r,i)),this.length>1&&(Ae[e]||(i=pe.uniqueSort(i)),Se.test(e)&&(i=i.reverse())),this.pushStack(i)}});var De=/\\S+/g;pe.Callbacks=function(e){e=\"string\"==typeof e?o(e):pe.extend({},e);var t,n,r,i,a=[],s=[],u=-1,l=function(){for(i=e.once,r=t=!0;s.length;u=-1)for(n=s.shift();++u<a.length;)a[u].apply(n[0],n[1])===!1&&e.stopOnFalse&&(u=a.length,n=!1);e.memory||(n=!1),t=!1,i&&(a=n?[]:\"\")},c={add:function(){return a&&(n&&!t&&(u=a.length-1,s.push(n)),function r(t){pe.each(t,function(t,n){pe.isFunction(n)?e.unique&&c.has(n)||a.push(n):n&&n.length&&\"string\"!==pe.type(n)&&r(n)})}(arguments),n&&!t&&l()),this},remove:function(){return pe.each(arguments,function(e,t){for(var n;(n=pe.inArray(t,a,n))>-1;)a.splice(n,1),n<=u&&u--}),this},has:function(e){return e?pe.inArray(e,a)>-1:a.length>0},empty:function(){return a&&(a=[]),this},disable:function(){return i=s=[],a=n=\"\",this},disabled:function(){return!a},lock:function(){return i=!0,n||c.disable(),this},locked:function(){return!!i},fireWith:function(e,n){return i||(n=n||[],n=[e,n.slice?n.slice():n],s.push(n),t||l()),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!r}};return c},pe.extend({Deferred:function(e){var t=[[\"resolve\",\"done\",pe.Callbacks(\"once memory\"),\"resolved\"],[\"reject\",\"fail\",pe.Callbacks(\"once memory\"),\"rejected\"],[\"notify\",\"progress\",pe.Callbacks(\"memory\")]],n=\"pending\",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return pe.Deferred(function(n){pe.each(t,function(t,o){var a=pe.isFunction(e[t])&&e[t];i[o[1]](function(){var e=a&&a.apply(this,arguments);e&&pe.isFunction(e.promise)?e.promise().progress(n.notify).done(n.resolve).fail(n.reject):n[o[0]+\"With\"](this===r?n.promise():this,a?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?pe.extend(e,r):r}},i={};return r.pipe=r.then,pe.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,n,r,i=0,o=ie.call(arguments),a=o.length,s=1!==a||e&&pe.isFunction(e.promise)?a:0,u=1===s?e:pe.Deferred(),l=function(e,n,r){return function(i){n[e]=this,r[e]=arguments.length>1?ie.call(arguments):i,r===t?u.notifyWith(n,r):--s||u.resolveWith(n,r)}};if(a>1)for(t=new Array(a),n=new Array(a),r=new Array(a);i<a;i++)o[i]&&pe.isFunction(o[i].promise)?o[i].promise().progress(l(i,n,t)).done(l(i,r,o)).fail(u.reject):--s;return s||u.resolveWith(r,o),u.promise()}});var je;pe.fn.ready=function(e){return pe.ready.promise().done(e),this},pe.extend({isReady:!1,readyWait:1,holdReady:function(e){e?pe.readyWait++:pe.ready(!0)},ready:function(e){(e===!0?--pe.readyWait:pe.isReady)||(pe.isReady=!0,e!==!0&&--pe.readyWait>0||(je.resolveWith(re,[pe]),pe.fn.triggerHandler&&(pe(re).triggerHandler(\"ready\"),pe(re).off(\"ready\"))))}}),pe.ready.promise=function(t){if(!je)if(je=pe.Deferred(),\"complete\"===re.readyState||\"loading\"!==re.readyState&&!re.documentElement.doScroll)e.setTimeout(pe.ready);else if(re.addEventListener)re.addEventListener(\"DOMContentLoaded\",s),e.addEventListener(\"load\",s);else{re.attachEvent(\"onreadystatechange\",s),e.attachEvent(\"onload\",s);var n=!1;try{n=null==e.frameElement&&re.documentElement}catch(r){}n&&n.doScroll&&!function i(){if(!pe.isReady){try{n.doScroll(\"left\")}catch(t){return e.setTimeout(i,50)}a(),pe.ready()}}()}return je.promise(t)},pe.ready.promise();var Le;for(Le in pe(fe))break;fe.ownFirst=\"0\"===Le,fe.inlineBlockNeedsLayout=!1,pe(function(){var e,t,n,r;n=re.getElementsByTagName(\"body\")[0],n&&n.style&&(t=re.createElement(\"div\"),r=re.createElement(\"div\"),r.style.cssText=\"position:absolute;border:0;width:0;height:0;top:0;left:-9999px\",n.appendChild(r).appendChild(t),\"undefined\"!=typeof t.style.zoom&&(t.style.cssText=\"display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1\",fe.inlineBlockNeedsLayout=e=3===t.offsetWidth,e&&(n.style.zoom=1)),n.removeChild(r))}),function(){var e=re.createElement(\"div\");fe.deleteExpando=!0;try{delete e.test}catch(t){fe.deleteExpando=!1}e=null}();var He=function(e){var t=pe.noData[(e.nodeName+\" \").toLowerCase()],n=+e.nodeType||1;return(1===n||9===n)&&(!t||t!==!0&&e.getAttribute(\"classid\")===t)},qe=/^(?:\\{[\\w\\W]*\\}|\\[[\\w\\W]*\\])$/,_e=/([A-Z])/g;pe.extend({cache:{},noData:{\"applet \":!0,\"embed \":!0,\"object \":\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"},hasData:function(e){return e=e.nodeType?pe.cache[e[pe.expando]]:e[pe.expando],!!e&&!l(e)},data:function(e,t,n){return c(e,t,n)},removeData:function(e,t){return f(e,t)},_data:function(e,t,n){return c(e,t,n,!0)},_removeData:function(e,t){return f(e,t,!0)}}),pe.fn.extend({data:function(e,t){var n,r,i,o=this[0],a=o&&o.attributes;if(void 0===e){if(this.length&&(i=pe.data(o),1===o.nodeType&&!pe._data(o,\"parsedAttrs\"))){for(n=a.length;n--;)a[n]&&(r=a[n].name,0===r.indexOf(\"data-\")&&(r=pe.camelCase(r.slice(5)),u(o,r,i[r])));pe._data(o,\"parsedAttrs\",!0)}return i}return\"object\"==typeof e?this.each(function(){pe.data(this,e)}):arguments.length>1?this.each(function(){pe.data(this,e,t)}):o?u(o,e,pe.data(o,e)):void 0},removeData:function(e){return this.each(function(){pe.removeData(this,e)})}}),pe.extend({queue:function(e,t,n){var r;if(e)return t=(t||\"fx\")+\"queue\",r=pe._data(e,t),n&&(!r||pe.isArray(n)?r=pe._data(e,t,pe.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||\"fx\";var n=pe.queue(e,t),r=n.length,i=n.shift(),o=pe._queueHooks(e,t),a=function(){pe.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 pe._data(e,n)||pe._data(e,n,{empty:pe.Callbacks(\"once memory\").add(function(){pe._removeData(e,t+\"queue\"),pe._removeData(e,n)})})}}),pe.fn.extend({queue:function(e,t){var n=2;return\"string\"!=typeof e&&(t=e,e=\"fx\",n--),arguments.length<n?pe.queue(this[0],e):void 0===t?this:this.each(function(){var n=pe.queue(this,e,t);pe._queueHooks(this,e),\"fx\"===e&&\"inprogress\"!==n[0]&&pe.dequeue(this,e)})},dequeue:function(e){return this.each(function(){pe.dequeue(this,e)})},clearQueue:function(e){return this.queue(e||\"fx\",[])},promise:function(e,t){var n,r=1,i=pe.Deferred(),o=this,a=this.length,s=function(){--r||i.resolveWith(o,[o])};for(\"string\"!=typeof e&&(t=e,e=void 0),e=e||\"fx\";a--;)n=pe._data(o[a],e+\"queueHooks\"),n&&n.empty&&(r++,n.empty.add(s));return s(),i.promise(t)}}),function(){var e;fe.shrinkWrapBlocks=function(){if(null!=e)return e;e=!1;var t,n,r;return n=re.getElementsByTagName(\"body\")[0],n&&n.style?(t=re.createElement(\"div\"),r=re.createElement(\"div\"),r.style.cssText=\"position:absolute;border:0;width:0;height:0;top:0;left:-9999px\",n.appendChild(r).appendChild(t),\"undefined\"!=typeof t.style.zoom&&(t.style.cssText=\"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:1px;width:1px;zoom:1\",t.appendChild(re.createElement(\"div\")).style.width=\"5px\",e=3!==t.offsetWidth),n.removeChild(r),e):void 0}}();var Fe=/[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/.source,Me=new RegExp(\"^(?:([+-])=|)(\"+Fe+\")([a-z%]*)$\",\"i\"),Oe=[\"Top\",\"Right\",\"Bottom\",\"Left\"],Re=function(e,t){return e=t||e,\"none\"===pe.css(e,\"display\")||!pe.contains(e.ownerDocument,e)},Pe=function(e,t,n,r,i,o,a){var s=0,u=e.length,l=null==n;if(\"object\"===pe.type(n)){i=!0;for(s in n)Pe(e,t,s,n[s],!0,o,a)}else if(void 0!==r&&(i=!0,pe.isFunction(r)||(a=!0),l&&(a?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(pe(e),n)})),t))for(;s<u;s++)t(e[s],n,a?r:r.call(e[s],s,t(e[s],n)));return i?e:l?t.call(e):u?t(e[0],n):o},Be=/^(?:checkbox|radio)$/i,We=/<([\\w:-]+)/,Ie=/^$|\\/(?:java|ecma)script/i,$e=/^\\s+/,ze=\"abbr|article|aside|audio|bdi|canvas|data|datalist|details|dialog|figcaption|figure|footer|header|hgroup|main|mark|meter|nav|output|picture|progress|section|summary|template|time|video\";!function(){var e=re.createElement(\"div\"),t=re.createDocumentFragment(),n=re.createElement(\"input\");e.innerHTML=\"  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>\",fe.leadingWhitespace=3===e.firstChild.nodeType,fe.tbody=!e.getElementsByTagName(\"tbody\").length,fe.htmlSerialize=!!e.getElementsByTagName(\"link\").length,fe.html5Clone=\"<:nav></:nav>\"!==re.createElement(\"nav\").cloneNode(!0).outerHTML,n.type=\"checkbox\",n.checked=!0,t.appendChild(n),fe.appendChecked=n.checked,e.innerHTML=\"<textarea>x</textarea>\",fe.noCloneChecked=!!e.cloneNode(!0).lastChild.defaultValue,t.appendChild(e),n=re.createElement(\"input\"),n.setAttribute(\"type\",\"radio\"),n.setAttribute(\"checked\",\"checked\"),n.setAttribute(\"name\",\"t\"),e.appendChild(n),fe.checkClone=e.cloneNode(!0).cloneNode(!0).lastChild.checked,fe.noCloneEvent=!!e.addEventListener,e[pe.expando]=1,fe.attributes=!e.getAttribute(pe.expando)}();var Xe={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:fe.htmlSerialize?[0,\"\",\"\"]:[1,\"X<div>\",\"</div>\"]};Xe.optgroup=Xe.option,Xe.tbody=Xe.tfoot=Xe.colgroup=Xe.caption=Xe.thead,Xe.th=Xe.td;var Ue=/<|&#?\\w+;/,Ve=/<tbody/i;!function(){var t,n,r=re.createElement(\"div\");for(t in{submit:!0,change:!0,focusin:!0})n=\"on\"+t,(fe[t]=n in e)||(r.setAttribute(n,\"t\"),fe[t]=r.attributes[n].expando===!1);r=null}();var Ye=/^(?:input|select|textarea)$/i,Je=/^key/,Ge=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ke=/^(?:focusinfocus|focusoutblur)$/,Qe=/^([^.]*)(?:\\.(.+)|)/;pe.event={global:{},add:function(e,t,n,r,i){var o,a,s,u,l,c,f,d,p,h,g,m=pe._data(e);if(m){for(n.handler&&(u=n,n=u.handler,i=u.selector),n.guid||(n.guid=pe.guid++),(a=m.events)||(a=m.events={}),(c=m.handle)||(c=m.handle=function(e){return\"undefined\"==typeof pe||e&&pe.event.triggered===e.type?void 0:pe.event.dispatch.apply(c.elem,arguments)},c.elem=e),t=(t||\"\").match(De)||[\"\"],s=t.length;s--;)o=Qe.exec(t[s])||[],p=g=o[1],h=(o[2]||\"\").split(\".\").sort(),p&&(l=pe.event.special[p]||{},p=(i?l.delegateType:l.bindType)||p,l=pe.event.special[p]||{},f=pe.extend({type:p,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&pe.expr.match.needsContext.test(i),namespace:h.join(\".\")},u),(d=a[p])||(d=a[p]=[],d.delegateCount=0,l.setup&&l.setup.call(e,r,h,c)!==!1||(e.addEventListener?e.addEventListener(p,c,!1):e.attachEvent&&e.attachEvent(\"on\"+p,c))),l.add&&(l.add.call(e,f),f.handler.guid||(f.handler.guid=n.guid)),i?d.splice(d.delegateCount++,0,f):d.push(f),pe.event.global[p]=!0);e=null}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,d,p,h,g,m=pe.hasData(e)&&pe._data(e);if(m&&(c=m.events)){for(t=(t||\"\").match(De)||[\"\"],l=t.length;l--;)if(s=Qe.exec(t[l])||[],p=g=s[1],h=(s[2]||\"\").split(\".\").sort(),p){for(f=pe.event.special[p]||{},p=(r?f.delegateType:f.bindType)||p,d=c[p]||[],s=s[2]&&new RegExp(\"(^|\\\\.)\"+h.join(\"\\\\.(?:.*\\\\.|)\")+\"(\\\\.|$)\"),u=o=d.length;o--;)a=d[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&(\"**\"!==r||!a.selector)||(d.splice(o,1),a.selector&&d.delegateCount--,f.remove&&f.remove.call(e,a));u&&!d.length&&(f.teardown&&f.teardown.call(e,h,m.handle)!==!1||pe.removeEvent(e,p,m.handle),delete c[p])}else for(p in c)pe.event.remove(e,p+t[l],n,r,!0);pe.isEmptyObject(c)&&(delete m.handle,pe._removeData(e,\"events\"))}},trigger:function(t,n,r,i){var o,a,s,u,l,c,f,d=[r||re],p=ce.call(t,\"type\")?t.type:t,h=ce.call(t,\"namespace\")?t.namespace.split(\".\"):[];if(s=c=r=r||re,3!==r.nodeType&&8!==r.nodeType&&!Ke.test(p+pe.event.triggered)&&(p.indexOf(\".\")>-1&&(h=p.split(\".\"),p=h.shift(),h.sort()),a=p.indexOf(\":\")<0&&\"on\"+p,t=t[pe.expando]?t:new pe.Event(p,\"object\"==typeof t&&t),t.isTrigger=i?2:3,t.namespace=h.join(\".\"),t.rnamespace=t.namespace?new RegExp(\"(^|\\\\.)\"+h.join(\"\\\\.(?:.*\\\\.|)\")+\"(\\\\.|$)\"):null,t.result=void 0,t.target||(t.target=r),n=null==n?[t]:pe.makeArray(n,[t]),l=pe.event.special[p]||{},i||!l.trigger||l.trigger.apply(r,n)!==!1)){if(!i&&!l.noBubble&&!pe.isWindow(r)){for(u=l.delegateType||p,Ke.test(u+p)||(s=s.parentNode);s;s=s.parentNode)d.push(s),c=s;c===(r.ownerDocument||re)&&d.push(c.defaultView||c.parentWindow||e)}for(f=0;(s=d[f++])&&!t.isPropagationStopped();)t.type=f>1?u:l.bindType||p,o=(pe._data(s,\"events\")||{})[t.type]&&pe._data(s,\"handle\"),o&&o.apply(s,n),o=a&&s[a],o&&o.apply&&He(s)&&(t.result=o.apply(s,n),t.result===!1&&t.preventDefault());if(t.type=p,!i&&!t.isDefaultPrevented()&&(!l._default||l._default.apply(d.pop(),n)===!1)&&He(r)&&a&&r[p]&&!pe.isWindow(r)){c=r[a],c&&(r[a]=null),pe.event.triggered=p;try{r[p]()}catch(g){}pe.event.triggered=void 0,c&&(r[a]=c)}return t.result}},dispatch:function(e){e=pe.event.fix(e);var t,n,r,i,o,a=[],s=ie.call(arguments),u=(pe._data(this,\"events\")||{})[e.type]||[],l=pe.event.special[e.type]||{};if(s[0]=e,e.delegateTarget=this,!l.preDispatch||l.preDispatch.call(this,e)!==!1){for(a=pe.event.handlers.call(this,e,u),t=0;(i=a[t++])&&!e.isPropagationStopped();)for(e.currentTarget=i.elem,n=0;(o=i.handlers[n++])&&!e.isImmediatePropagationStopped();)e.rnamespace&&!e.rnamespace.test(o.namespace)||(e.handleObj=o,e.data=o.data,r=((pe.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,s),void 0!==r&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()));return l.postDispatch&&l.postDispatch.call(this,e),e.result}},handlers:function(e,t){var n,r,i,o,a=[],s=t.delegateCount,u=e.target;if(s&&u.nodeType&&(\"click\"!==e.type||isNaN(e.button)||e.button<1))for(;u!=this;u=u.parentNode||this)if(1===u.nodeType&&(u.disabled!==!0||\"click\"!==e.type)){for(r=[],n=0;n<s;n++)o=t[n],i=o.selector+\" \",void 0===r[i]&&(r[i]=o.needsContext?pe(i,this).index(u)>-1:pe.find(i,this,null,[u]).length),r[i]&&r.push(o);r.length&&a.push({elem:u,handlers:r})}return s<t.length&&a.push({elem:this,handlers:t.slice(s)}),a},fix:function(e){if(e[pe.expando])return e;var t,n,r,i=e.type,o=e,a=this.fixHooks[i];for(a||(this.fixHooks[i]=a=Ge.test(i)?this.mouseHooks:Je.test(i)?this.keyHooks:{}),r=a.props?this.props.concat(a.props):this.props,e=new pe.Event(o),t=r.length;t--;)n=r[t],e[n]=o[n];return e.target||(e.target=o.srcElement||re),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,a.filter?a.filter(e,o):e},props:\"altKey bubbles cancelable ctrlKey currentTarget detail 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,t){var n,r,i,o=t.button,a=t.fromElement;return null==e.pageX&&null!=t.clientX&&(r=e.target.ownerDocument||re,i=r.documentElement,n=r.body,e.pageX=t.clientX+(i&&i.scrollLeft||n&&n.scrollLeft||0)-(i&&i.clientLeft||n&&n.clientLeft||0),e.pageY=t.clientY+(i&&i.scrollTop||n&&n.scrollTop||0)-(i&&i.clientTop||n&&n.clientTop||0)),!e.relatedTarget&&a&&(e.relatedTarget=a===e.target?t.toElement:a),e.which||void 0===o||(e.which=1&o?1:2&o?3:4&o?2:0),e}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==b()&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:\"focusin\"},blur:{trigger:function(){if(this===b()&&this.blur)return this.blur(),!1},delegateType:\"focusout\"},click:{trigger:function(){if(pe.nodeName(this,\"input\")&&\"checkbox\"===this.type&&this.click)return this.click(),!1},_default:function(e){return pe.nodeName(e.target,\"a\")}},beforeunload:{postDispatch:function(e){void 0!==e.result&&e.originalEvent&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n){var r=pe.extend(new pe.Event,n,{type:e,isSimulated:!0});pe.event.trigger(r,null,t),r.isDefaultPrevented()&&n.preventDefault()}},pe.removeEvent=re.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n)}:function(e,t,n){var r=\"on\"+t;e.detachEvent&&(\"undefined\"==typeof e[r]&&(e[r]=null),e.detachEvent(r,n))},pe.Event=function(e,t){return this instanceof pe.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||void 0===e.defaultPrevented&&e.returnValue===!1?v:x):this.type=e,t&&pe.extend(this,t),this.timeStamp=e&&e.timeStamp||pe.now(),void(this[pe.expando]=!0)):new pe.Event(e,t)},pe.Event.prototype={constructor:pe.Event,isDefaultPrevented:x,isPropagationStopped:x,isImmediatePropagationStopped:x,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=v,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=v,e&&!this.isSimulated&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){var e=this.originalEvent;this.isImmediatePropagationStopped=v,e&&e.stopImmediatePropagation&&e.stopImmediatePropagation(),this.stopPropagation()}},pe.each({mouseenter:\"mouseover\",mouseleave:\"mouseout\",pointerenter:\"pointerover\",pointerleave:\"pointerout\"},function(e,t){pe.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return i&&(i===r||pe.contains(r,i))||(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),fe.submit||(pe.event.special.submit={setup:function(){return!pe.nodeName(this,\"form\")&&void pe.event.add(this,\"click._submit keypress._submit\",function(e){var t=e.target,n=pe.nodeName(t,\"input\")||pe.nodeName(t,\"button\")?pe.prop(t,\"form\"):void 0;n&&!pe._data(n,\"submit\")&&(pe.event.add(n,\"submit._submit\",function(e){e._submitBubble=!0}),pe._data(n,\"submit\",!0))})},postDispatch:function(e){e._submitBubble&&(delete e._submitBubble,this.parentNode&&!e.isTrigger&&pe.event.simulate(\"submit\",this.parentNode,e))},teardown:function(){return!pe.nodeName(this,\"form\")&&void pe.event.remove(this,\"._submit\")}}),fe.change||(pe.event.special.change={setup:function(){return Ye.test(this.nodeName)?(\"checkbox\"!==this.type&&\"radio\"!==this.type||(pe.event.add(this,\"propertychange._change\",function(e){\"checked\"===e.originalEvent.propertyName&&(this._justChanged=!0)}),pe.event.add(this,\"click._change\",function(e){this._justChanged&&!e.isTrigger&&(this._justChanged=!1),pe.event.simulate(\"change\",this,e)})),!1):void pe.event.add(this,\"beforeactivate._change\",function(e){var t=e.target;Ye.test(t.nodeName)&&!pe._data(t,\"change\")&&(pe.event.add(t,\"change._change\",function(e){!this.parentNode||e.isSimulated||e.isTrigger||pe.event.simulate(\"change\",this.parentNode,e)}),pe._data(t,\"change\",!0))})},handle:function(e){var t=e.target;if(this!==t||e.isSimulated||e.isTrigger||\"radio\"!==t.type&&\"checkbox\"!==t.type)return e.handleObj.handler.apply(this,arguments)},teardown:function(){return pe.event.remove(this,\"._change\"),!Ye.test(this.nodeName)}}),fe.focusin||pe.each({focus:\"focusin\",blur:\"focusout\"},function(e,t){var n=function(e){pe.event.simulate(t,e.target,pe.event.fix(e))};pe.event.special[t]={setup:function(){var r=this.ownerDocument||this,i=pe._data(r,t);i||r.addEventListener(e,n,!0),pe._data(r,t,(i||0)+1)},teardown:function(){var r=this.ownerDocument||this,i=pe._data(r,t)-1;i?pe._data(r,t,i):(r.removeEventListener(e,n,!0),pe._removeData(r,t))}}}),pe.fn.extend({on:function(e,t,n,r){return w(this,e,t,n,r)},one:function(e,t,n,r){return w(this,e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,pe(e.delegateTarget).off(r.namespace?r.origType+\".\"+r.namespace:r.origType,r.selector,r.handler),this;if(\"object\"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return t!==!1&&\"function\"!=typeof t||(n=t,t=void 0),n===!1&&(n=x),this.each(function(){pe.event.remove(this,e,n,t)})},trigger:function(e,t){return this.each(function(){pe.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return pe.event.trigger(e,t,n,!0)}});var Ze=/ jQuery\\d+=\"(?:null|\\d+)\"/g,et=new RegExp(\"<(?:\"+ze+\")[\\\\s/>]\",\"i\"),tt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:-]+)[^>]*)\\/>/gi,nt=/<script|<style|<link/i,rt=/checked\\s*(?:[^=]|=\\s*.checked.)/i,it=/^true\\/(.*)/,ot=/^\\s*<!(?:\\[CDATA\\[|--)|(?:\\]\\]|--)>\\s*$/g,at=p(re),st=at.appendChild(re.createElement(\"div\"));pe.extend({htmlPrefilter:function(e){return e.replace(tt,\"<$1></$2>\")},clone:function(e,t,n){var r,i,o,a,s,u=pe.contains(e.ownerDocument,e);if(fe.html5Clone||pe.isXMLDoc(e)||!et.test(\"<\"+e.nodeName+\">\")?o=e.cloneNode(!0):(st.innerHTML=e.outerHTML,st.removeChild(o=st.firstChild)),!(fe.noCloneEvent&&fe.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||pe.isXMLDoc(e)))for(r=h(o),s=h(e),a=0;null!=(i=s[a]);++a)r[a]&&k(i,r[a]);if(t)if(n)for(s=s||h(e),r=r||h(o),a=0;null!=(i=s[a]);a++)N(i,r[a]);else N(e,o);return r=h(o,\"script\"),r.length>0&&g(r,!u&&h(e,\"script\")),r=s=i=null,o},cleanData:function(e,t){for(var n,r,i,o,a=0,s=pe.expando,u=pe.cache,l=fe.attributes,c=pe.event.special;null!=(n=e[a]);a++)if((t||He(n))&&(i=n[s],o=i&&u[i])){if(o.events)for(r in o.events)c[r]?pe.event.remove(n,r):pe.removeEvent(n,r,o.handle);u[i]&&(delete u[i],l||\"undefined\"==typeof n.removeAttribute?n[s]=void 0:n.removeAttribute(s),ne.push(i))}}}),pe.fn.extend({domManip:S,detach:function(e){return A(this,e,!0)},remove:function(e){return A(this,e)},text:function(e){return Pe(this,function(e){return void 0===e?pe.text(this):this.empty().append((this[0]&&this[0].ownerDocument||re).createTextNode(e))},null,e,arguments.length)},append:function(){return S(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=T(this,e);t.appendChild(e)}})},prepend:function(){return S(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=T(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return S(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return S(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++){for(1===e.nodeType&&pe.cleanData(h(e,!1));e.firstChild;)e.removeChild(e.firstChild);e.options&&pe.nodeName(e,\"select\")&&(e.options.length=0)}return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return pe.clone(this,e,t)})},html:function(e){return Pe(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e)return 1===t.nodeType?t.innerHTML.replace(Ze,\"\"):void 0;if(\"string\"==typeof e&&!nt.test(e)&&(fe.htmlSerialize||!et.test(e))&&(fe.leadingWhitespace||!$e.test(e))&&!Xe[(We.exec(e)||[\"\",\"\"])[1].toLowerCase()]){e=pe.htmlPrefilter(e);try{for(;n<r;n++)t=this[n]||{},1===t.nodeType&&(pe.cleanData(h(t,!1)),t.innerHTML=e);t=0}catch(i){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=[];return S(this,arguments,function(t){var n=this.parentNode;pe.inArray(this,e)<0&&(pe.cleanData(h(this)),\nn&&n.replaceChild(t,this))},e)}}),pe.each({appendTo:\"append\",prependTo:\"prepend\",insertBefore:\"before\",insertAfter:\"after\",replaceAll:\"replaceWith\"},function(e,t){pe.fn[e]=function(e){for(var n,r=0,i=[],o=pe(e),a=o.length-1;r<=a;r++)n=r===a?this:this.clone(!0),pe(o[r])[t](n),ae.apply(i,n.get());return this.pushStack(i)}});var ut,lt={HTML:\"block\",BODY:\"block\"},ct=/^margin/,ft=new RegExp(\"^(\"+Fe+\")(?!px)[a-z%]+$\",\"i\"),dt=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},pt=re.documentElement;!function(){function t(){var t,c,f=re.documentElement;f.appendChild(u),l.style.cssText=\"-webkit-box-sizing:border-box;box-sizing:border-box;position:relative;display:block;margin:auto;border:1px;padding:1px;top:1%;width:50%\",n=i=s=!1,r=a=!0,e.getComputedStyle&&(c=e.getComputedStyle(l),n=\"1%\"!==(c||{}).top,s=\"2px\"===(c||{}).marginLeft,i=\"4px\"===(c||{width:\"4px\"}).width,l.style.marginRight=\"50%\",r=\"4px\"===(c||{marginRight:\"4px\"}).marginRight,t=l.appendChild(re.createElement(\"div\")),t.style.cssText=l.style.cssText=\"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0\",t.style.marginRight=t.style.width=\"0\",l.style.width=\"1px\",a=!parseFloat((e.getComputedStyle(t)||{}).marginRight),l.removeChild(t)),l.style.display=\"none\",o=0===l.getClientRects().length,o&&(l.style.display=\"\",l.innerHTML=\"<table><tr><td></td><td>t</td></tr></table>\",t=l.getElementsByTagName(\"td\"),t[0].style.cssText=\"margin:0;border:0;padding:0;display:none\",o=0===t[0].offsetHeight,o&&(t[0].style.display=\"\",t[1].style.display=\"none\",o=0===t[0].offsetHeight)),f.removeChild(u)}var n,r,i,o,a,s,u=re.createElement(\"div\"),l=re.createElement(\"div\");l.style&&(l.style.cssText=\"float:left;opacity:.5\",fe.opacity=\"0.5\"===l.style.opacity,fe.cssFloat=!!l.style.cssFloat,l.style.backgroundClip=\"content-box\",l.cloneNode(!0).style.backgroundClip=\"\",fe.clearCloneStyle=\"content-box\"===l.style.backgroundClip,u=re.createElement(\"div\"),u.style.cssText=\"border:0;width:8px;height:0;top:0;left:-9999px;padding:0;margin-top:1px;position:absolute\",l.innerHTML=\"\",u.appendChild(l),fe.boxSizing=\"\"===l.style.boxSizing||\"\"===l.style.MozBoxSizing||\"\"===l.style.WebkitBoxSizing,pe.extend(fe,{reliableHiddenOffsets:function(){return null==n&&t(),o},boxSizingReliable:function(){return null==n&&t(),i},pixelMarginRight:function(){return null==n&&t(),r},pixelPosition:function(){return null==n&&t(),n},reliableMarginRight:function(){return null==n&&t(),a},reliableMarginLeft:function(){return null==n&&t(),s}}))}();var ht,gt,mt=/^(top|right|bottom|left)$/;e.getComputedStyle?(ht=function(t){var n=t.ownerDocument.defaultView;return n&&n.opener||(n=e),n.getComputedStyle(t)},gt=function(e,t,n){var r,i,o,a,s=e.style;return n=n||ht(e),a=n?n.getPropertyValue(t)||n[t]:void 0,\"\"!==a&&void 0!==a||pe.contains(e.ownerDocument,e)||(a=pe.style(e,t)),n&&!fe.pixelMarginRight()&&ft.test(a)&&ct.test(t)&&(r=s.width,i=s.minWidth,o=s.maxWidth,s.minWidth=s.maxWidth=s.width=a,a=n.width,s.width=r,s.minWidth=i,s.maxWidth=o),void 0===a?a:a+\"\"}):pt.currentStyle&&(ht=function(e){return e.currentStyle},gt=function(e,t,n){var r,i,o,a,s=e.style;return n=n||ht(e),a=n?n[t]:void 0,null==a&&s&&s[t]&&(a=s[t]),ft.test(a)&&!mt.test(t)&&(r=s.left,i=e.runtimeStyle,o=i&&i.left,o&&(i.left=e.currentStyle.left),s.left=\"fontSize\"===t?\"1em\":a,a=s.pixelLeft+\"px\",s.left=r,o&&(i.left=o)),void 0===a?a:a+\"\"||\"auto\"});var yt=/alpha\\([^)]*\\)/i,vt=/opacity\\s*=\\s*([^)]*)/i,xt=/^(none|table(?!-c[ea]).+)/,bt=new RegExp(\"^(\"+Fe+\")(.*)$\",\"i\"),wt={position:\"absolute\",visibility:\"hidden\",display:\"block\"},Tt={letterSpacing:\"0\",fontWeight:\"400\"},Ct=[\"Webkit\",\"O\",\"Moz\",\"ms\"],Et=re.createElement(\"div\").style;pe.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=gt(e,\"opacity\");return\"\"===n?\"1\":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{\"float\":fe.cssFloat?\"cssFloat\":\"styleFloat\"},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=pe.camelCase(t),u=e.style;if(t=pe.cssProps[s]||(pe.cssProps[s]=H(s)||s),a=pe.cssHooks[t]||pe.cssHooks[s],void 0===n)return a&&\"get\"in a&&void 0!==(i=a.get(e,!1,r))?i:u[t];if(o=typeof n,\"string\"===o&&(i=Me.exec(n))&&i[1]&&(n=d(e,t,i),o=\"number\"),null!=n&&n===n&&(\"number\"===o&&(n+=i&&i[3]||(pe.cssNumber[s]?\"\":\"px\")),fe.clearCloneStyle||\"\"!==n||0!==t.indexOf(\"background\")||(u[t]=\"inherit\"),!(a&&\"set\"in a&&void 0===(n=a.set(e,n,r)))))try{u[t]=n}catch(l){}}},css:function(e,t,n,r){var i,o,a,s=pe.camelCase(t);return t=pe.cssProps[s]||(pe.cssProps[s]=H(s)||s),a=pe.cssHooks[t]||pe.cssHooks[s],a&&\"get\"in a&&(o=a.get(e,!0,n)),void 0===o&&(o=gt(e,t,r)),\"normal\"===o&&t in Tt&&(o=Tt[t]),\"\"===n||n?(i=parseFloat(o),n===!0||isFinite(i)?i||0:o):o}}),pe.each([\"height\",\"width\"],function(e,t){pe.cssHooks[t]={get:function(e,n,r){if(n)return xt.test(pe.css(e,\"display\"))&&0===e.offsetWidth?dt(e,wt,function(){return M(e,t,r)}):M(e,t,r)},set:function(e,n,r){var i=r&&ht(e);return _(e,n,r?F(e,t,r,fe.boxSizing&&\"border-box\"===pe.css(e,\"boxSizing\",!1,i),i):0)}}}),fe.opacity||(pe.cssHooks.opacity={get:function(e,t){return vt.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=pe.isNumeric(t)?\"alpha(opacity=\"+100*t+\")\":\"\",o=r&&r.filter||n.filter||\"\";n.zoom=1,(t>=1||\"\"===t)&&\"\"===pe.trim(o.replace(yt,\"\"))&&n.removeAttribute&&(n.removeAttribute(\"filter\"),\"\"===t||r&&!r.filter)||(n.filter=yt.test(o)?o.replace(yt,i):o+\" \"+i)}}),pe.cssHooks.marginRight=L(fe.reliableMarginRight,function(e,t){if(t)return dt(e,{display:\"inline-block\"},gt,[e,\"marginRight\"])}),pe.cssHooks.marginLeft=L(fe.reliableMarginLeft,function(e,t){if(t)return(parseFloat(gt(e,\"marginLeft\"))||(pe.contains(e.ownerDocument,e)?e.getBoundingClientRect().left-dt(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}):0))+\"px\"}),pe.each({margin:\"\",padding:\"\",border:\"Width\"},function(e,t){pe.cssHooks[e+t]={expand:function(n){for(var r=0,i={},o=\"string\"==typeof n?n.split(\" \"):[n];r<4;r++)i[e+Oe[r]+t]=o[r]||o[r-2]||o[0];return i}},ct.test(e)||(pe.cssHooks[e+t].set=_)}),pe.fn.extend({css:function(e,t){return Pe(this,function(e,t,n){var r,i,o={},a=0;if(pe.isArray(t)){for(r=ht(e),i=t.length;a<i;a++)o[t[a]]=pe.css(e,t[a],!1,r);return o}return void 0!==n?pe.style(e,t,n):pe.css(e,t)},e,t,arguments.length>1)},show:function(){return q(this,!0)},hide:function(){return q(this)},toggle:function(e){return\"boolean\"==typeof e?e?this.show():this.hide():this.each(function(){Re(this)?pe(this).show():pe(this).hide()})}}),pe.Tween=O,O.prototype={constructor:O,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||pe.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(pe.cssNumber[n]?\"\":\"px\")},cur:function(){var e=O.propHooks[this.prop];return e&&e.get?e.get(this):O.propHooks._default.get(this)},run:function(e){var t,n=O.propHooks[this.prop];return this.options.duration?this.pos=t=pe.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=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):O.propHooks._default.set(this),this}},O.prototype.init.prototype=O.prototype,O.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=pe.css(e.elem,e.prop,\"\"),t&&\"auto\"!==t?t:0)},set:function(e){pe.fx.step[e.prop]?pe.fx.step[e.prop](e):1!==e.elem.nodeType||null==e.elem.style[pe.cssProps[e.prop]]&&!pe.cssHooks[e.prop]?e.elem[e.prop]=e.now:pe.style(e.elem,e.prop,e.now+e.unit)}}},O.propHooks.scrollTop=O.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},pe.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:\"swing\"},pe.fx=O.prototype.init,pe.fx.step={};var Nt,kt,St=/^(?:toggle|show|hide)$/,At=/queueHooks$/;pe.Animation=pe.extend($,{tweeners:{\"*\":[function(e,t){var n=this.createTween(e,t);return d(n.elem,e,Me.exec(t),n),n}]},tweener:function(e,t){pe.isFunction(e)?(t=e,e=[\"*\"]):e=e.match(De);for(var n,r=0,i=e.length;r<i;r++)n=e[r],$.tweeners[n]=$.tweeners[n]||[],$.tweeners[n].unshift(t)},prefilters:[W],prefilter:function(e,t){t?$.prefilters.unshift(e):$.prefilters.push(e)}}),pe.speed=function(e,t,n){var r=e&&\"object\"==typeof e?pe.extend({},e):{complete:n||!n&&t||pe.isFunction(e)&&e,duration:e,easing:n&&t||t&&!pe.isFunction(t)&&t};return r.duration=pe.fx.off?0:\"number\"==typeof r.duration?r.duration:r.duration in pe.fx.speeds?pe.fx.speeds[r.duration]:pe.fx.speeds._default,null!=r.queue&&r.queue!==!0||(r.queue=\"fx\"),r.old=r.complete,r.complete=function(){pe.isFunction(r.old)&&r.old.call(this),r.queue&&pe.dequeue(this,r.queue)},r},pe.fn.extend({fadeTo:function(e,t,n,r){return this.filter(Re).css(\"opacity\",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=pe.isEmptyObject(e),o=pe.speed(t,n,r),a=function(){var t=$(this,pe.extend({},e),o);(i||pe._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,t,n){var r=function(e){var t=e.stop;delete e.stop,t(n)};return\"string\"!=typeof e&&(n=t,t=e,e=void 0),t&&e!==!1&&this.queue(e||\"fx\",[]),this.each(function(){var t=!0,i=null!=e&&e+\"queueHooks\",o=pe.timers,a=pe._data(this);if(i)a[i]&&a[i].stop&&r(a[i]);else for(i in a)a[i]&&a[i].stop&&At.test(i)&&r(a[i]);for(i=o.length;i--;)o[i].elem!==this||null!=e&&o[i].queue!==e||(o[i].anim.stop(n),t=!1,o.splice(i,1));!t&&n||pe.dequeue(this,e)})},finish:function(e){return e!==!1&&(e=e||\"fx\"),this.each(function(){var t,n=pe._data(this),r=n[e+\"queue\"],i=n[e+\"queueHooks\"],o=pe.timers,a=r?r.length:0;for(n.finish=!0,pe.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;t<a;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}}),pe.each([\"toggle\",\"show\",\"hide\"],function(e,t){var n=pe.fn[t];pe.fn[t]=function(e,r,i){return null==e||\"boolean\"==typeof e?n.apply(this,arguments):this.animate(P(t,!0),e,r,i)}}),pe.each({slideDown:P(\"show\"),slideUp:P(\"hide\"),slideToggle:P(\"toggle\"),fadeIn:{opacity:\"show\"},fadeOut:{opacity:\"hide\"},fadeToggle:{opacity:\"toggle\"}},function(e,t){pe.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),pe.timers=[],pe.fx.tick=function(){var e,t=pe.timers,n=0;for(Nt=pe.now();n<t.length;n++)e=t[n],e()||t[n]!==e||t.splice(n--,1);t.length||pe.fx.stop(),Nt=void 0},pe.fx.timer=function(e){pe.timers.push(e),e()?pe.fx.start():pe.timers.pop()},pe.fx.interval=13,pe.fx.start=function(){kt||(kt=e.setInterval(pe.fx.tick,pe.fx.interval))},pe.fx.stop=function(){e.clearInterval(kt),kt=null},pe.fx.speeds={slow:600,fast:200,_default:400},pe.fn.delay=function(t,n){return t=pe.fx?pe.fx.speeds[t]||t:t,n=n||\"fx\",this.queue(n,function(n,r){var i=e.setTimeout(n,t);r.stop=function(){e.clearTimeout(i)}})},function(){var e,t=re.createElement(\"input\"),n=re.createElement(\"div\"),r=re.createElement(\"select\"),i=r.appendChild(re.createElement(\"option\"));n=re.createElement(\"div\"),n.setAttribute(\"className\",\"t\"),n.innerHTML=\"  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>\",e=n.getElementsByTagName(\"a\")[0],t.setAttribute(\"type\",\"checkbox\"),n.appendChild(t),e=n.getElementsByTagName(\"a\")[0],e.style.cssText=\"top:1px\",fe.getSetAttribute=\"t\"!==n.className,fe.style=/top/.test(e.getAttribute(\"style\")),fe.hrefNormalized=\"/a\"===e.getAttribute(\"href\"),fe.checkOn=!!t.value,fe.optSelected=i.selected,fe.enctype=!!re.createElement(\"form\").enctype,r.disabled=!0,fe.optDisabled=!i.disabled,t=re.createElement(\"input\"),t.setAttribute(\"value\",\"\"),fe.input=\"\"===t.getAttribute(\"value\"),t.value=\"t\",t.setAttribute(\"type\",\"radio\"),fe.radioValue=\"t\"===t.value}();var Dt=/\\r/g,jt=/[\\x20\\t\\r\\n\\f]+/g;pe.fn.extend({val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=pe.isFunction(e),this.each(function(n){var i;1===this.nodeType&&(i=r?e.call(this,n,pe(this).val()):e,null==i?i=\"\":\"number\"==typeof i?i+=\"\":pe.isArray(i)&&(i=pe.map(i,function(e){return null==e?\"\":e+\"\"})),t=pe.valHooks[this.type]||pe.valHooks[this.nodeName.toLowerCase()],t&&\"set\"in t&&void 0!==t.set(this,i,\"value\")||(this.value=i))});if(i)return t=pe.valHooks[i.type]||pe.valHooks[i.nodeName.toLowerCase()],t&&\"get\"in t&&void 0!==(n=t.get(i,\"value\"))?n:(n=i.value,\"string\"==typeof n?n.replace(Dt,\"\"):null==n?\"\":n)}}}),pe.extend({valHooks:{option:{get:function(e){var t=pe.find.attr(e,\"value\");return null!=t?t:pe.trim(pe.text(e)).replace(jt,\" \")}},select:{get:function(e){for(var t,n,r=e.options,i=e.selectedIndex,o=\"select-one\"===e.type||i<0,a=o?null:[],s=o?i+1:r.length,u=i<0?s:o?i:0;u<s;u++)if(n=r[u],(n.selected||u===i)&&(fe.optDisabled?!n.disabled:null===n.getAttribute(\"disabled\"))&&(!n.parentNode.disabled||!pe.nodeName(n.parentNode,\"optgroup\"))){if(t=pe(n).val(),o)return t;a.push(t)}return a},set:function(e,t){for(var n,r,i=e.options,o=pe.makeArray(t),a=i.length;a--;)if(r=i[a],pe.inArray(pe.valHooks.option.get(r),o)>-1)try{r.selected=n=!0}catch(s){r.scrollHeight}else r.selected=!1;return n||(e.selectedIndex=-1),i}}}}),pe.each([\"radio\",\"checkbox\"],function(){pe.valHooks[this]={set:function(e,t){if(pe.isArray(t))return e.checked=pe.inArray(pe(e).val(),t)>-1}},fe.checkOn||(pe.valHooks[this].get=function(e){return null===e.getAttribute(\"value\")?\"on\":e.value})});var Lt,Ht,qt=pe.expr.attrHandle,_t=/^(?:checked|selected)$/i,Ft=fe.getSetAttribute,Mt=fe.input;pe.fn.extend({attr:function(e,t){return Pe(this,pe.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){pe.removeAttr(this,e)})}}),pe.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return\"undefined\"==typeof e.getAttribute?pe.prop(e,t,n):(1===o&&pe.isXMLDoc(e)||(t=t.toLowerCase(),i=pe.attrHooks[t]||(pe.expr.match.bool.test(t)?Ht:Lt)),void 0!==n?null===n?void pe.removeAttr(e,t):i&&\"set\"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+\"\"),n):i&&\"get\"in i&&null!==(r=i.get(e,t))?r:(r=pe.find.attr(e,t),null==r?void 0:r))},attrHooks:{type:{set:function(e,t){if(!fe.radioValue&&\"radio\"===t&&pe.nodeName(e,\"input\")){var n=e.value;return e.setAttribute(\"type\",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(De);if(o&&1===e.nodeType)for(;n=o[i++];)r=pe.propFix[n]||n,pe.expr.match.bool.test(n)?Mt&&Ft||!_t.test(n)?e[r]=!1:e[pe.camelCase(\"default-\"+n)]=e[r]=!1:pe.attr(e,n,\"\"),e.removeAttribute(Ft?n:r)}}),Ht={set:function(e,t,n){return t===!1?pe.removeAttr(e,n):Mt&&Ft||!_t.test(n)?e.setAttribute(!Ft&&pe.propFix[n]||n,n):e[pe.camelCase(\"default-\"+n)]=e[n]=!0,n}},pe.each(pe.expr.match.bool.source.match(/\\w+/g),function(e,t){var n=qt[t]||pe.find.attr;Mt&&Ft||!_t.test(t)?qt[t]=function(e,t,r){var i,o;return r||(o=qt[t],qt[t]=i,i=null!=n(e,t,r)?t.toLowerCase():null,qt[t]=o),i}:qt[t]=function(e,t,n){if(!n)return e[pe.camelCase(\"default-\"+t)]?t.toLowerCase():null}}),Mt&&Ft||(pe.attrHooks.value={set:function(e,t,n){return pe.nodeName(e,\"input\")?void(e.defaultValue=t):Lt&&Lt.set(e,t,n)}}),Ft||(Lt={set:function(e,t,n){var r=e.getAttributeNode(n);if(r||e.setAttributeNode(r=e.ownerDocument.createAttribute(n)),r.value=t+=\"\",\"value\"===n||t===e.getAttribute(n))return t}},qt.id=qt.name=qt.coords=function(e,t,n){var r;if(!n)return(r=e.getAttributeNode(t))&&\"\"!==r.value?r.value:null},pe.valHooks.button={get:function(e,t){var n=e.getAttributeNode(t);if(n&&n.specified)return n.value},set:Lt.set},pe.attrHooks.contenteditable={set:function(e,t,n){Lt.set(e,\"\"!==t&&t,n)}},pe.each([\"width\",\"height\"],function(e,t){pe.attrHooks[t]={set:function(e,n){if(\"\"===n)return e.setAttribute(t,\"auto\"),n}}})),fe.style||(pe.attrHooks.style={get:function(e){return e.style.cssText||void 0},set:function(e,t){return e.style.cssText=t+\"\"}});var Ot=/^(?:input|select|textarea|button|object)$/i,Rt=/^(?:a|area)$/i;pe.fn.extend({prop:function(e,t){return Pe(this,pe.prop,e,t,arguments.length>1)},removeProp:function(e){return e=pe.propFix[e]||e,this.each(function(){try{this[e]=void 0,delete this[e]}catch(t){}})}}),pe.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&pe.isXMLDoc(e)||(t=pe.propFix[t]||t,i=pe.propHooks[t]),void 0!==n?i&&\"set\"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&\"get\"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=pe.find.attr(e,\"tabindex\");return t?parseInt(t,10):Ot.test(e.nodeName)||Rt.test(e.nodeName)&&e.href?0:-1}}},propFix:{\"for\":\"htmlFor\",\"class\":\"className\"}}),fe.hrefNormalized||pe.each([\"href\",\"src\"],function(e,t){pe.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}}),fe.optSelected||(pe.propHooks.selected={get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),pe.each([\"tabIndex\",\"readOnly\",\"maxLength\",\"cellSpacing\",\"cellPadding\",\"rowSpan\",\"colSpan\",\"useMap\",\"frameBorder\",\"contentEditable\"],function(){pe.propFix[this.toLowerCase()]=this}),fe.enctype||(pe.propFix.enctype=\"encoding\");var Pt=/[\\t\\r\\n\\f]/g;pe.fn.extend({addClass:function(e){var t,n,r,i,o,a,s,u=0;if(pe.isFunction(e))return this.each(function(t){pe(this).addClass(e.call(this,t,z(this)))});if(\"string\"==typeof e&&e)for(t=e.match(De)||[];n=this[u++];)if(i=z(n),r=1===n.nodeType&&(\" \"+i+\" \").replace(Pt,\" \")){for(a=0;o=t[a++];)r.indexOf(\" \"+o+\" \")<0&&(r+=o+\" \");s=pe.trim(r),i!==s&&pe.attr(n,\"class\",s)}return this},removeClass:function(e){var t,n,r,i,o,a,s,u=0;if(pe.isFunction(e))return this.each(function(t){pe(this).removeClass(e.call(this,t,z(this)))});if(!arguments.length)return this.attr(\"class\",\"\");if(\"string\"==typeof e&&e)for(t=e.match(De)||[];n=this[u++];)if(i=z(n),r=1===n.nodeType&&(\" \"+i+\" \").replace(Pt,\" \")){for(a=0;o=t[a++];)for(;r.indexOf(\" \"+o+\" \")>-1;)r=r.replace(\" \"+o+\" \",\" \");s=pe.trim(r),i!==s&&pe.attr(n,\"class\",s)}return this},toggleClass:function(e,t){var n=typeof e;return\"boolean\"==typeof t&&\"string\"===n?t?this.addClass(e):this.removeClass(e):pe.isFunction(e)?this.each(function(n){pe(this).toggleClass(e.call(this,n,z(this),t),t)}):this.each(function(){var t,r,i,o;if(\"string\"===n)for(r=0,i=pe(this),o=e.match(De)||[];t=o[r++];)i.hasClass(t)?i.removeClass(t):i.addClass(t);else void 0!==e&&\"boolean\"!==n||(t=z(this),t&&pe._data(this,\"__className__\",t),pe.attr(this,\"class\",t||e===!1?\"\":pe._data(this,\"__className__\")||\"\"))})},hasClass:function(e){var t,n,r=0;for(t=\" \"+e+\" \";n=this[r++];)if(1===n.nodeType&&(\" \"+z(n)+\" \").replace(Pt,\" \").indexOf(t)>-1)return!0;return!1}}),pe.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){pe.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),pe.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}});var Bt=e.location,Wt=pe.now(),It=/\\?/,$t=/(,)|(\\[|{)|(}|])|\"(?:[^\"\\\\\\r\\n]|\\\\[\"\\\\\\/bfnrt]|\\\\u[\\da-fA-F]{4})*\"\\s*:?|true|false|null|-?(?!0\\d)\\d+(?:\\.\\d+|)(?:[eE][+-]?\\d+|)/g;pe.parseJSON=function(t){if(e.JSON&&e.JSON.parse)return e.JSON.parse(t+\"\");var n,r=null,i=pe.trim(t+\"\");return i&&!pe.trim(i.replace($t,function(e,t,i,o){return n&&t&&(r=0),0===r?e:(n=i||t,r+=!o-!i,\"\")}))?Function(\"return \"+i)():pe.error(\"Invalid JSON: \"+t)},pe.parseXML=function(t){var n,r;if(!t||\"string\"!=typeof t)return null;try{e.DOMParser?(r=new e.DOMParser,n=r.parseFromString(t,\"text/xml\")):(n=new e.ActiveXObject(\"Microsoft.XMLDOM\"),n.async=\"false\",n.loadXML(t))}catch(i){n=void 0}return n&&n.documentElement&&!n.getElementsByTagName(\"parsererror\").length||pe.error(\"Invalid XML: \"+t),n};var zt=/#.*$/,Xt=/([?&])_=[^&]*/,Ut=/^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/gm,Vt=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Yt=/^(?:GET|HEAD)$/,Jt=/^\\/\\//,Gt=/^([\\w.+-]+:)(?:\\/\\/(?:[^\\/?#]*@|)([^\\/?#:]*)(?::(\\d+)|)|)/,Kt={},Qt={},Zt=\"*/\".concat(\"*\"),en=Bt.href,tn=Gt.exec(en.toLowerCase())||[];pe.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:en,type:\"GET\",isLocal:Vt.test(tn[1]),global:!0,processData:!0,async:!0,contentType:\"application/x-www-form-urlencoded; charset=UTF-8\",accepts:{\"*\":Zt,text:\"text/plain\",html:\"text/html\",xml:\"application/xml, text/xml\",json:\"application/json, text/javascript\"},contents:{xml:/\\bxml\\b/,html:/\\bhtml/,json:/\\bjson\\b/},responseFields:{xml:\"responseXML\",text:\"responseText\",json:\"responseJSON\"},converters:{\"* text\":String,\"text html\":!0,\"text json\":pe.parseJSON,\"text xml\":pe.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?V(V(e,pe.ajaxSettings),t):V(pe.ajaxSettings,e)},ajaxPrefilter:X(Kt),ajaxTransport:X(Qt),ajax:function(t,n){function r(t,n,r,i){var o,f,v,x,w,C=n;2!==b&&(b=2,u&&e.clearTimeout(u),c=void 0,s=i||\"\",T.readyState=t>0?4:0,o=t>=200&&t<300||304===t,r&&(x=Y(d,T,r)),x=J(d,x,T,o),o?(d.ifModified&&(w=T.getResponseHeader(\"Last-Modified\"),w&&(pe.lastModified[a]=w),w=T.getResponseHeader(\"etag\"),w&&(pe.etag[a]=w)),204===t||\"HEAD\"===d.type?C=\"nocontent\":304===t?C=\"notmodified\":(C=x.state,f=x.data,v=x.error,o=!v)):(v=C,!t&&C||(C=\"error\",t<0&&(t=0))),T.status=t,T.statusText=(n||C)+\"\",o?g.resolveWith(p,[f,C,T]):g.rejectWith(p,[T,C,v]),T.statusCode(y),y=void 0,l&&h.trigger(o?\"ajaxSuccess\":\"ajaxError\",[T,d,o?f:v]),m.fireWith(p,[T,C]),l&&(h.trigger(\"ajaxComplete\",[T,d]),--pe.active||pe.event.trigger(\"ajaxStop\")))}\"object\"==typeof t&&(n=t,t=void 0),n=n||{};var i,o,a,s,u,l,c,f,d=pe.ajaxSetup({},n),p=d.context||d,h=d.context&&(p.nodeType||p.jquery)?pe(p):pe.event,g=pe.Deferred(),m=pe.Callbacks(\"once memory\"),y=d.statusCode||{},v={},x={},b=0,w=\"canceled\",T={readyState:0,getResponseHeader:function(e){var t;if(2===b){if(!f)for(f={};t=Ut.exec(s);)f[t[1].toLowerCase()]=t[2];t=f[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===b?s:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return b||(e=x[n]=x[n]||e,v[e]=t),this},overrideMimeType:function(e){return b||(d.mimeType=e),this},statusCode:function(e){var t;if(e)if(b<2)for(t in e)y[t]=[y[t],e[t]];else T.always(e[T.status]);return this},abort:function(e){var t=e||w;return c&&c.abort(t),r(0,t),this}};if(g.promise(T).complete=m.add,T.success=T.done,T.error=T.fail,d.url=((t||d.url||en)+\"\").replace(zt,\"\").replace(Jt,tn[1]+\"//\"),d.type=n.method||n.type||d.method||d.type,d.dataTypes=pe.trim(d.dataType||\"*\").toLowerCase().match(De)||[\"\"],null==d.crossDomain&&(i=Gt.exec(d.url.toLowerCase()),d.crossDomain=!(!i||i[1]===tn[1]&&i[2]===tn[2]&&(i[3]||(\"http:\"===i[1]?\"80\":\"443\"))===(tn[3]||(\"http:\"===tn[1]?\"80\":\"443\")))),d.data&&d.processData&&\"string\"!=typeof d.data&&(d.data=pe.param(d.data,d.traditional)),U(Kt,d,n,T),2===b)return T;l=pe.event&&d.global,l&&0===pe.active++&&pe.event.trigger(\"ajaxStart\"),d.type=d.type.toUpperCase(),d.hasContent=!Yt.test(d.type),a=d.url,d.hasContent||(d.data&&(a=d.url+=(It.test(a)?\"&\":\"?\")+d.data,delete d.data),d.cache===!1&&(d.url=Xt.test(a)?a.replace(Xt,\"$1_=\"+Wt++):a+(It.test(a)?\"&\":\"?\")+\"_=\"+Wt++)),d.ifModified&&(pe.lastModified[a]&&T.setRequestHeader(\"If-Modified-Since\",pe.lastModified[a]),pe.etag[a]&&T.setRequestHeader(\"If-None-Match\",pe.etag[a])),(d.data&&d.hasContent&&d.contentType!==!1||n.contentType)&&T.setRequestHeader(\"Content-Type\",d.contentType),T.setRequestHeader(\"Accept\",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(\"*\"!==d.dataTypes[0]?\", \"+Zt+\"; q=0.01\":\"\"):d.accepts[\"*\"]);for(o in d.headers)T.setRequestHeader(o,d.headers[o]);if(d.beforeSend&&(d.beforeSend.call(p,T,d)===!1||2===b))return T.abort();w=\"abort\";for(o in{success:1,error:1,complete:1})T[o](d[o]);if(c=U(Qt,d,n,T)){if(T.readyState=1,l&&h.trigger(\"ajaxSend\",[T,d]),2===b)return T;d.async&&d.timeout>0&&(u=e.setTimeout(function(){T.abort(\"timeout\")},d.timeout));try{b=1,c.send(v,r)}catch(C){if(!(b<2))throw C;r(-1,C)}}else r(-1,\"No Transport\");return T},getJSON:function(e,t,n){return pe.get(e,t,n,\"json\")},getScript:function(e,t){return pe.get(e,void 0,t,\"script\")}}),pe.each([\"get\",\"post\"],function(e,t){pe[t]=function(e,n,r,i){return pe.isFunction(n)&&(i=i||r,r=n,n=void 0),pe.ajax(pe.extend({url:e,type:t,dataType:i,data:n,success:r},pe.isPlainObject(e)&&e))}}),pe._evalUrl=function(e){return pe.ajax({url:e,type:\"GET\",dataType:\"script\",cache:!0,async:!1,global:!1,\"throws\":!0})},pe.fn.extend({wrapAll:function(e){if(pe.isFunction(e))return this.each(function(t){pe(this).wrapAll(e.call(this,t))});if(this[0]){var t=pe(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){for(var e=this;e.firstChild&&1===e.firstChild.nodeType;)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return pe.isFunction(e)?this.each(function(t){pe(this).wrapInner(e.call(this,t))}):this.each(function(){var t=pe(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=pe.isFunction(e);return this.each(function(n){pe(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){pe.nodeName(this,\"body\")||pe(this).replaceWith(this.childNodes)}).end()}}),pe.expr.filters.hidden=function(e){return fe.reliableHiddenOffsets()?e.offsetWidth<=0&&e.offsetHeight<=0&&!e.getClientRects().length:K(e)},pe.expr.filters.visible=function(e){return!pe.expr.filters.hidden(e)};var nn=/%20/g,rn=/\\[\\]$/,on=/\\r?\\n/g,an=/^(?:submit|button|image|reset|file)$/i,sn=/^(?:input|select|textarea|keygen)/i;pe.param=function(e,t){var n,r=[],i=function(e,t){t=pe.isFunction(t)?t():null==t?\"\":t,r[r.length]=encodeURIComponent(e)+\"=\"+encodeURIComponent(t)};if(void 0===t&&(t=pe.ajaxSettings&&pe.ajaxSettings.traditional),pe.isArray(e)||e.jquery&&!pe.isPlainObject(e))pe.each(e,function(){i(this.name,this.value)});else for(n in e)Q(n,e[n],t,i);return r.join(\"&\").replace(nn,\"+\")},pe.fn.extend({serialize:function(){return pe.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=pe.prop(this,\"elements\");return e?pe.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!pe(this).is(\":disabled\")&&sn.test(this.nodeName)&&!an.test(e)&&(this.checked||!Be.test(e))}).map(function(e,t){var n=pe(this).val();return null==n?null:pe.isArray(n)?pe.map(n,function(e){return{name:t.name,value:e.replace(on,\"\\r\\n\")}}):{name:t.name,value:n.replace(on,\"\\r\\n\")}}).get()}}),pe.ajaxSettings.xhr=void 0!==e.ActiveXObject?function(){return this.isLocal?ee():re.documentMode>8?Z():/^(get|post|head|put|delete|options)$/i.test(this.type)&&Z()||ee()}:Z;var un=0,ln={},cn=pe.ajaxSettings.xhr();e.attachEvent&&e.attachEvent(\"onunload\",function(){for(var e in ln)ln[e](void 0,!0)}),fe.cors=!!cn&&\"withCredentials\"in cn,cn=fe.ajax=!!cn,cn&&pe.ajaxTransport(function(t){if(!t.crossDomain||fe.cors){var n;return{send:function(r,i){var o,a=t.xhr(),s=++un;if(a.open(t.type,t.url,t.async,t.username,t.password),t.xhrFields)for(o in t.xhrFields)a[o]=t.xhrFields[o];t.mimeType&&a.overrideMimeType&&a.overrideMimeType(t.mimeType),t.crossDomain||r[\"X-Requested-With\"]||(r[\"X-Requested-With\"]=\"XMLHttpRequest\");for(o in r)void 0!==r[o]&&a.setRequestHeader(o,r[o]+\"\");a.send(t.hasContent&&t.data||null),n=function(e,r){var o,u,l;if(n&&(r||4===a.readyState))if(delete ln[s],n=void 0,a.onreadystatechange=pe.noop,r)4!==a.readyState&&a.abort();else{l={},o=a.status,\"string\"==typeof a.responseText&&(l.text=a.responseText);try{u=a.statusText}catch(c){u=\"\"}o||!t.isLocal||t.crossDomain?1223===o&&(o=204):o=l.text?200:404}l&&i(o,u,l,a.getAllResponseHeaders())},t.async?4===a.readyState?e.setTimeout(n):a.onreadystatechange=ln[s]=n:n()},abort:function(){n&&n(void 0,!0)}}}}),pe.ajaxSetup({accepts:{script:\"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"},contents:{script:/\\b(?:java|ecma)script\\b/},converters:{\"text script\":function(e){return pe.globalEval(e),e}}}),pe.ajaxPrefilter(\"script\",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type=\"GET\",e.global=!1)}),pe.ajaxTransport(\"script\",function(e){if(e.crossDomain){var t,n=re.head||pe(\"head\")[0]||re.documentElement;return{send:function(r,i){t=re.createElement(\"script\"),t.async=!0,e.scriptCharset&&(t.charset=e.scriptCharset),t.src=e.url,t.onload=t.onreadystatechange=function(e,n){(n||!t.readyState||/loaded|complete/.test(t.readyState))&&(t.onload=t.onreadystatechange=null,t.parentNode&&t.parentNode.removeChild(t),t=null,n||i(200,\"success\"))},n.insertBefore(t,n.firstChild)},abort:function(){t&&t.onload(void 0,!0)}}}});var fn=[],dn=/(=)\\?(?=&|$)|\\?\\?/;pe.ajaxSetup({jsonp:\"callback\",jsonpCallback:function(){var e=fn.pop()||pe.expando+\"_\"+Wt++;return this[e]=!0,e}}),pe.ajaxPrefilter(\"json jsonp\",function(t,n,r){var i,o,a,s=t.jsonp!==!1&&(dn.test(t.url)?\"url\":\"string\"==typeof t.data&&0===(t.contentType||\"\").indexOf(\"application/x-www-form-urlencoded\")&&dn.test(t.data)&&\"data\");if(s||\"jsonp\"===t.dataTypes[0])return i=t.jsonpCallback=pe.isFunction(t.jsonpCallback)?t.jsonpCallback():t.jsonpCallback,s?t[s]=t[s].replace(dn,\"$1\"+i):t.jsonp!==!1&&(t.url+=(It.test(t.url)?\"&\":\"?\")+t.jsonp+\"=\"+i),t.converters[\"script json\"]=function(){return a||pe.error(i+\" was not called\"),a[0]},t.dataTypes[0]=\"json\",o=e[i],e[i]=function(){a=arguments},r.always(function(){void 0===o?pe(e).removeProp(i):e[i]=o,t[i]&&(t.jsonpCallback=n.jsonpCallback,fn.push(i)),a&&pe.isFunction(o)&&o(a[0]),a=o=void 0}),\"script\"}),pe.parseHTML=function(e,t,n){if(!e||\"string\"!=typeof e)return null;\"boolean\"==typeof t&&(n=t,t=!1),t=t||re;var r=Te.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=y([e],t,i),i&&i.length&&pe(i).remove(),pe.merge([],r.childNodes))};var pn=pe.fn.load;return pe.fn.load=function(e,t,n){if(\"string\"!=typeof e&&pn)return pn.apply(this,arguments);var r,i,o,a=this,s=e.indexOf(\" \");return s>-1&&(r=pe.trim(e.slice(s,e.length)),e=e.slice(0,s)),pe.isFunction(t)?(n=t,t=void 0):t&&\"object\"==typeof t&&(i=\"POST\"),a.length>0&&pe.ajax({url:e,type:i||\"GET\",dataType:\"html\",data:t}).done(function(e){o=arguments,a.html(r?pe(\"<div>\").append(pe.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},pe.each([\"ajaxStart\",\"ajaxStop\",\"ajaxComplete\",\"ajaxError\",\"ajaxSuccess\",\"ajaxSend\"],function(e,t){pe.fn[t]=function(e){return this.on(t,e)}}),pe.expr.filters.animated=function(e){return pe.grep(pe.timers,function(t){return e===t.elem}).length},pe.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l,c=pe.css(e,\"position\"),f=pe(e),d={};\"static\"===c&&(e.style.position=\"relative\"),s=f.offset(),o=pe.css(e,\"top\"),u=pe.css(e,\"left\"),l=(\"absolute\"===c||\"fixed\"===c)&&pe.inArray(\"auto\",[o,u])>-1,l?(r=f.position(),a=r.top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),pe.isFunction(t)&&(t=t.call(e,n,pe.extend({},s))),null!=t.top&&(d.top=t.top-s.top+a),null!=t.left&&(d.left=t.left-s.left+i),\"using\"in t?t.using.call(e,d):f.css(d)}},pe.fn.extend({offset:function(e){if(arguments.length)return void 0===e?this:this.each(function(t){pe.offset.setOffset(this,e,t)});var t,n,r={top:0,left:0},i=this[0],o=i&&i.ownerDocument;if(o)return t=o.documentElement,pe.contains(t,i)?(\"undefined\"!=typeof i.getBoundingClientRect&&(r=i.getBoundingClientRect()),n=te(o),{top:r.top+(n.pageYOffset||t.scrollTop)-(t.clientTop||0),left:r.left+(n.pageXOffset||t.scrollLeft)-(t.clientLeft||0)}):r},position:function(){if(this[0]){var e,t,n={top:0,left:0},r=this[0];return\"fixed\"===pe.css(r,\"position\")?t=r.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),pe.nodeName(e[0],\"html\")||(n=e.offset()),n.top+=pe.css(e[0],\"borderTopWidth\",!0),n.left+=pe.css(e[0],\"borderLeftWidth\",!0)),{top:t.top-n.top-pe.css(r,\"marginTop\",!0),left:t.left-n.left-pe.css(r,\"marginLeft\",!0)}}},offsetParent:function(){return this.map(function(){\nfor(var e=this.offsetParent;e&&!pe.nodeName(e,\"html\")&&\"static\"===pe.css(e,\"position\");)e=e.offsetParent;return e||pt})}}),pe.each({scrollLeft:\"pageXOffset\",scrollTop:\"pageYOffset\"},function(e,t){var n=/Y/.test(t);pe.fn[e]=function(r){return Pe(this,function(e,r,i){var o=te(e);return void 0===i?o?t in o?o[t]:o.document.documentElement[r]:e[r]:void(o?o.scrollTo(n?pe(o).scrollLeft():i,n?i:pe(o).scrollTop()):e[r]=i)},e,r,arguments.length,null)}}),pe.each([\"top\",\"left\"],function(e,t){pe.cssHooks[t]=L(fe.pixelPosition,function(e,n){if(n)return n=gt(e,t),ft.test(n)?pe(e).position()[t]+\"px\":n})}),pe.each({Height:\"height\",Width:\"width\"},function(e,t){pe.each({padding:\"inner\"+e,content:t,\"\":\"outer\"+e},function(n,r){pe.fn[r]=function(r,i){var o=arguments.length&&(n||\"boolean\"!=typeof r),a=n||(r===!0||i===!0?\"margin\":\"border\");return Pe(this,function(t,n,r){var i;return pe.isWindow(t)?t.document.documentElement[\"client\"+e]:9===t.nodeType?(i=t.documentElement,Math.max(t.body[\"scroll\"+e],i[\"scroll\"+e],t.body[\"offset\"+e],i[\"offset\"+e],i[\"client\"+e])):void 0===r?pe.css(t,n,a):pe.style(t,n,r,a)},t,o?r:void 0,o,null)}})}),pe.fn.extend({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)}}),pe.fn.size=function(){return this.length},pe.fn.andSelf=pe.fn.addBack,layui.define(function(e){layui.$=pe,e(\"jquery\",pe)}),pe});"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/layui/lay/modules/laydate.js",
    "content": "/** layui-v2.2.5 MIT License By https://www.layui.com */\n ;!function(){\"use strict\";var e=window.layui&&layui.define,t={getPath:function(){var e=document.currentScript?document.currentScript.src:function(){for(var e,t=document.scripts,n=t.length-1,a=n;a>0;a--)if(\"interactive\"===t[a].readyState){e=t[a].src;break}return e||t[n].src}();return e.substring(0,e.lastIndexOf(\"/\")+1)}(),getStyle:function(e,t){var n=e.currentStyle?e.currentStyle:window.getComputedStyle(e,null);return n[n.getPropertyValue?\"getPropertyValue\":\"getAttribute\"](t)},link:function(e,a,i){if(n.path){var r=document.getElementsByTagName(\"head\")[0],o=document.createElement(\"link\");\"string\"==typeof a&&(i=a);var s=(i||e).replace(/\\.|\\//g,\"\"),l=\"layuicss-\"+s,d=0;o.rel=\"stylesheet\",o.href=n.path+e,o.id=l,document.getElementById(l)||r.appendChild(o),\"function\"==typeof a&&!function c(){return++d>80?window.console&&console.error(\"laydate.css: Invalid\"):void(1989===parseInt(t.getStyle(document.getElementById(l),\"width\"))?a():setTimeout(c,100))}()}}},n={v:\"5.0.9\",config:{},index:window.laydate&&window.laydate.v?1e5:0,path:t.getPath,set:function(e){var t=this;return t.config=w.extend({},t.config,e),t},ready:function(a){var i=\"laydate\",r=\"\",o=(e?\"modules/laydate/\":\"theme/\")+\"default/laydate.css?v=\"+n.v+r;return e?layui.addcss(o,a,i):t.link(o,a,i),this}},a=function(){var e=this;return{hint:function(t){e.hint.call(e,t)},config:e.config}},i=\"laydate\",r=\".layui-laydate\",o=\"layui-this\",s=\"laydate-disabled\",l=\"开始日期超出了结束日期<br>建议重新选择\",d=[100,2e5],c=\"layui-laydate-static\",m=\"layui-laydate-list\",u=\"laydate-selected\",h=\"layui-laydate-hint\",y=\"laydate-day-prev\",f=\"laydate-day-next\",p=\"layui-laydate-footer\",g=\".laydate-btns-confirm\",v=\"laydate-time-text\",D=\".laydate-btns-time\",T=function(e){var t=this;t.index=++n.index,t.config=w.extend({},t.config,n.config,e),n.ready(function(){t.init()})},w=function(e){return new C(e)},C=function(e){for(var t=0,n=\"object\"==typeof e?[e]:(this.selector=e,document.querySelectorAll(e||null));t<n.length;t++)this.push(n[t])};C.prototype=[],C.prototype.constructor=C,w.extend=function(){var e=1,t=arguments,n=function(e,t){e=e||(t.constructor===Array?[]:{});for(var a in t)e[a]=t[a]&&t[a].constructor===Object?n(e[a],t[a]):t[a];return e};for(t[0]=\"object\"==typeof t[0]?t[0]:{};e<t.length;e++)\"object\"==typeof t[e]&&n(t[0],t[e]);return t[0]},w.ie=function(){var e=navigator.userAgent.toLowerCase();return!!(window.ActiveXObject||\"ActiveXObject\"in window)&&((e.match(/msie\\s(\\d+)/)||[])[1]||\"11\")}(),w.stope=function(e){e=e||window.event,e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},w.each=function(e,t){var n,a=this;if(\"function\"!=typeof t)return a;if(e=e||[],e.constructor===Object){for(n in e)if(t.call(e[n],n,e[n]))break}else for(n=0;n<e.length&&!t.call(e[n],n,e[n]);n++);return a},w.digit=function(e,t,n){var a=\"\";e=String(e),t=t||2;for(var i=e.length;i<t;i++)a+=\"0\";return e<Math.pow(10,t)?a+(0|e):e},w.elem=function(e,t){var n=document.createElement(e);return w.each(t||{},function(e,t){n.setAttribute(e,t)}),n},C.addStr=function(e,t){return e=e.replace(/\\s+/,\" \"),t=t.replace(/\\s+/,\" \").split(\" \"),w.each(t,function(t,n){new RegExp(\"\\\\b\"+n+\"\\\\b\").test(e)||(e=e+\" \"+n)}),e.replace(/^\\s|\\s$/,\"\")},C.removeStr=function(e,t){return e=e.replace(/\\s+/,\" \"),t=t.replace(/\\s+/,\" \").split(\" \"),w.each(t,function(t,n){var a=new RegExp(\"\\\\b\"+n+\"\\\\b\");a.test(e)&&(e=e.replace(a,\"\"))}),e.replace(/\\s+/,\" \").replace(/^\\s|\\s$/,\"\")},C.prototype.find=function(e){var t=this,n=0,a=[],i=\"object\"==typeof e;return this.each(function(r,o){for(var s=i?[e]:o.querySelectorAll(e||null);n<s.length;n++)a.push(s[n]);t.shift()}),i||(t.selector=(t.selector?t.selector+\" \":\"\")+e),w.each(a,function(e,n){t.push(n)}),t},C.prototype.each=function(e){return w.each.call(this,this,e)},C.prototype.addClass=function(e,t){return this.each(function(n,a){a.className=C[t?\"removeStr\":\"addStr\"](a.className,e)})},C.prototype.removeClass=function(e){return this.addClass(e,!0)},C.prototype.hasClass=function(e){var t=!1;return this.each(function(n,a){new RegExp(\"\\\\b\"+e+\"\\\\b\").test(a.className)&&(t=!0)}),t},C.prototype.attr=function(e,t){var n=this;return void 0===t?function(){if(n.length>0)return n[0].getAttribute(e)}():n.each(function(n,a){a.setAttribute(e,t)})},C.prototype.removeAttr=function(e){return this.each(function(t,n){n.removeAttribute(e)})},C.prototype.html=function(e){return this.each(function(t,n){n.innerHTML=e})},C.prototype.val=function(e){return this.each(function(t,n){n.value=e})},C.prototype.append=function(e){return this.each(function(t,n){\"object\"==typeof e?n.appendChild(e):n.innerHTML=n.innerHTML+e})},C.prototype.remove=function(e){return this.each(function(t,n){e?n.removeChild(e):n.parentNode.removeChild(n)})},C.prototype.on=function(e,t){return this.each(function(n,a){a.attachEvent?a.attachEvent(\"on\"+e,function(e){e.target=e.srcElement,t.call(a,e)}):a.addEventListener(e,t,!1)})},C.prototype.off=function(e,t){return this.each(function(n,a){a.detachEvent?a.detachEvent(\"on\"+e,t):a.removeEventListener(e,t,!1)})},T.isLeapYear=function(e){return e%4===0&&e%100!==0||e%400===0},T.prototype.config={type:\"date\",range:!1,format:\"yyyy-MM-dd\",value:null,min:\"1900-1-1\",max:\"2099-12-31\",trigger:\"focus\",show:!1,showBottom:!0,btns:[\"clear\",\"now\",\"confirm\"],lang:\"cn\",theme:\"default\",position:null,calendar:!1,mark:{},zIndex:null,done:null,change:null},T.prototype.lang=function(){var e=this,t=e.config,n={cn:{weeks:[\"日\",\"一\",\"二\",\"三\",\"四\",\"五\",\"六\"],time:[\"时\",\"分\",\"秒\"],timeTips:\"选择时间\",startTime:\"开始时间\",endTime:\"结束时间\",dateTips:\"返回日期\",month:[\"一\",\"二\",\"三\",\"四\",\"五\",\"六\",\"七\",\"八\",\"九\",\"十\",\"十一\",\"十二\"],tools:{confirm:\"确定\",clear:\"清空\",now:\"现在\"}},en:{weeks:[\"Su\",\"Mo\",\"Tu\",\"We\",\"Th\",\"Fr\",\"Sa\"],time:[\"Hours\",\"Minutes\",\"Seconds\"],timeTips:\"Select Time\",startTime:\"Start Time\",endTime:\"End Time\",dateTips:\"Select Date\",month:[\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\"],tools:{confirm:\"Confirm\",clear:\"Clear\",now:\"Now\"}}};return n[t.lang]||n.cn},T.prototype.init=function(){var e=this,t=e.config,n=\"yyyy|y|MM|M|dd|d|HH|H|mm|m|ss|s\",a=\"static\"===t.position,i={year:\"yyyy\",month:\"yyyy-MM\",date:\"yyyy-MM-dd\",time:\"HH:mm:ss\",datetime:\"yyyy-MM-dd HH:mm:ss\"};t.elem=w(t.elem),t.eventElem=w(t.eventElem),t.elem[0]&&(t.range===!0&&(t.range=\"-\"),t.format===i.date&&(t.format=i[t.type]),e.format=t.format.match(new RegExp(n+\"|.\",\"g\"))||[],e.EXP_IF=\"\",e.EXP_SPLIT=\"\",w.each(e.format,function(t,a){var i=new RegExp(n).test(a)?\"\\\\d{\"+function(){return new RegExp(n).test(e.format[0===t?t+1:t-1]||\"\")?/^yyyy|y$/.test(a)?4:a.length:/^yyyy$/.test(a)?\"1,4\":/^y$/.test(a)?\"1,308\":\"1,2\"}()+\"}\":\"\\\\\"+a;e.EXP_IF=e.EXP_IF+i,e.EXP_SPLIT=e.EXP_SPLIT+\"(\"+i+\")\"}),e.EXP_IF=new RegExp(\"^\"+(t.range?e.EXP_IF+\"\\\\s\\\\\"+t.range+\"\\\\s\"+e.EXP_IF:e.EXP_IF)+\"$\"),e.EXP_SPLIT=new RegExp(\"^\"+e.EXP_SPLIT+\"$\",\"\"),e.isInput(t.elem[0])||\"focus\"===t.trigger&&(t.trigger=\"click\"),t.elem.attr(\"lay-key\")||(t.elem.attr(\"lay-key\",e.index),t.eventElem.attr(\"lay-key\",e.index)),t.mark=w.extend({},t.calendar&&\"cn\"===t.lang?{\"0-1-1\":\"元旦\",\"0-2-14\":\"情人\",\"0-3-8\":\"妇女\",\"0-3-12\":\"植树\",\"0-4-1\":\"愚人\",\"0-5-1\":\"劳动\",\"0-5-4\":\"青年\",\"0-6-1\":\"儿童\",\"0-9-10\":\"教师\",\"0-9-18\":\"国耻\",\"0-10-1\":\"国庆\",\"0-12-25\":\"圣诞\"}:{},t.mark),w.each([\"min\",\"max\"],function(e,n){var a=[],i=[];if(\"number\"==typeof t[n]){var r=t[n],o=(new Date).getTime(),s=864e5,l=new Date(r?r<s?o+r*s:r:o);a=[l.getFullYear(),l.getMonth()+1,l.getDate()],r<s||(i=[l.getHours(),l.getMinutes(),l.getSeconds()])}else a=(t[n].match(/\\d+-\\d+-\\d+/)||[\"\"])[0].split(\"-\"),i=(t[n].match(/\\d+:\\d+:\\d+/)||[\"\"])[0].split(\":\");t[n]={year:0|a[0]||(new Date).getFullYear(),month:a[1]?(0|a[1])-1:(new Date).getMonth(),date:0|a[2]||(new Date).getDate(),hours:0|i[0],minutes:0|i[1],seconds:0|i[2]}}),e.elemID=\"layui-laydate\"+t.elem.attr(\"lay-key\"),(t.show||a)&&e.render(),a||e.events(),t.value&&(t.value.constructor===Date?e.setValue(e.parse(0,e.systemDate(t.value))):e.setValue(t.value)))},T.prototype.render=function(){var e=this,t=e.config,n=e.lang(),a=\"static\"===t.position,i=e.elem=w.elem(\"div\",{id:e.elemID,\"class\":[\"layui-laydate\",t.range?\" layui-laydate-range\":\"\",a?\" \"+c:\"\",t.theme&&\"default\"!==t.theme&&!/^#/.test(t.theme)?\" laydate-theme-\"+t.theme:\"\"].join(\"\")}),r=e.elemMain=[],o=e.elemHeader=[],s=e.elemCont=[],l=e.table=[],d=e.footer=w.elem(\"div\",{\"class\":p});if(t.zIndex&&(i.style.zIndex=t.zIndex),w.each(new Array(2),function(e){if(!t.range&&e>0)return!0;var a=w.elem(\"div\",{\"class\":\"layui-laydate-header\"}),i=[function(){var e=w.elem(\"i\",{\"class\":\"layui-icon laydate-icon laydate-prev-y\"});return e.innerHTML=\"&#xe65a;\",e}(),function(){var e=w.elem(\"i\",{\"class\":\"layui-icon laydate-icon laydate-prev-m\"});return e.innerHTML=\"&#xe603;\",e}(),function(){var e=w.elem(\"div\",{\"class\":\"laydate-set-ym\"}),t=w.elem(\"span\"),n=w.elem(\"span\");return e.appendChild(t),e.appendChild(n),e}(),function(){var e=w.elem(\"i\",{\"class\":\"layui-icon laydate-icon laydate-next-m\"});return e.innerHTML=\"&#xe602;\",e}(),function(){var e=w.elem(\"i\",{\"class\":\"layui-icon laydate-icon laydate-next-y\"});return e.innerHTML=\"&#xe65b;\",e}()],d=w.elem(\"div\",{\"class\":\"layui-laydate-content\"}),c=w.elem(\"table\"),m=w.elem(\"thead\"),u=w.elem(\"tr\");w.each(i,function(e,t){a.appendChild(t)}),m.appendChild(u),w.each(new Array(6),function(e){var t=c.insertRow(0);w.each(new Array(7),function(a){if(0===e){var i=w.elem(\"th\");i.innerHTML=n.weeks[a],u.appendChild(i)}t.insertCell(a)})}),c.insertBefore(m,c.children[0]),d.appendChild(c),r[e]=w.elem(\"div\",{\"class\":\"layui-laydate-main laydate-main-list-\"+e}),r[e].appendChild(a),r[e].appendChild(d),o.push(i),s.push(d),l.push(c)}),w(d).html(function(){var e=[],i=[];return\"datetime\"===t.type&&e.push('<span lay-type=\"datetime\" class=\"laydate-btns-time\">'+n.timeTips+\"</span>\"),w.each(t.btns,function(e,r){var o=n.tools[r]||\"btn\";t.range&&\"now\"===r||(a&&\"clear\"===r&&(o=\"cn\"===t.lang?\"重置\":\"Reset\"),i.push('<span lay-type=\"'+r+'\" class=\"laydate-btns-'+r+'\">'+o+\"</span>\"))}),e.push('<div class=\"laydate-footer-btns\">'+i.join(\"\")+\"</div>\"),e.join(\"\")}()),w.each(r,function(e,t){i.appendChild(t)}),t.showBottom&&i.appendChild(d),/^#/.test(t.theme)){var m=w.elem(\"style\"),u=[\"#{{id}} .layui-laydate-header{background-color:{{theme}};}\",\"#{{id}} .layui-this{background-color:{{theme}} !important;}\"].join(\"\").replace(/{{id}}/g,e.elemID).replace(/{{theme}}/g,t.theme);\"styleSheet\"in m?(m.setAttribute(\"type\",\"text/css\"),m.styleSheet.cssText=u):m.innerHTML=u,w(i).addClass(\"laydate-theme-molv\"),i.appendChild(m)}e.remove(T.thisElemDate),a?t.elem.append(i):(document.body.appendChild(i),e.position()),e.checkDate().calendar(),e.changeEvent(),T.thisElemDate=e.elemID,\"function\"==typeof t.ready&&t.ready(w.extend({},t.dateTime,{month:t.dateTime.month+1}))},T.prototype.remove=function(e){var t=this,n=(t.config,w(\"#\"+(e||t.elemID)));return n.hasClass(c)||t.checkDate(function(){n.remove()}),t},T.prototype.position=function(){var e=this,t=e.config,n=e.bindElem||t.elem[0],a=n.getBoundingClientRect(),i=e.elem.offsetWidth,r=e.elem.offsetHeight,o=function(e){return e=e?\"scrollLeft\":\"scrollTop\",document.body[e]|document.documentElement[e]},s=function(e){return document.documentElement[e?\"clientWidth\":\"clientHeight\"]},l=5,d=a.left,c=a.bottom;d+i+l>s(\"width\")&&(d=s(\"width\")-i-l),c+r+l>s()&&(c=a.top>r?a.top-r:s()-r,c-=2*l),t.position&&(e.elem.style.position=t.position),e.elem.style.left=d+(\"fixed\"===t.position?0:o(1))+\"px\",e.elem.style.top=c+(\"fixed\"===t.position?0:o())+\"px\"},T.prototype.hint=function(e){var t=this,n=(t.config,w.elem(\"div\",{\"class\":h}));n.innerHTML=e||\"\",w(t.elem).find(\".\"+h).remove(),t.elem.appendChild(n),clearTimeout(t.hinTimer),t.hinTimer=setTimeout(function(){w(t.elem).find(\".\"+h).remove()},3e3)},T.prototype.getAsYM=function(e,t,n){return n?t--:t++,t<0&&(t=11,e--),t>11&&(t=0,e++),[e,t]},T.prototype.systemDate=function(e){var t=e||new Date;return{year:t.getFullYear(),month:t.getMonth(),date:t.getDate(),hours:e?e.getHours():0,minutes:e?e.getMinutes():0,seconds:e?e.getSeconds():0}},T.prototype.checkDate=function(e){var t,a,i=this,r=(new Date,i.config),o=r.dateTime=r.dateTime||i.systemDate(),s=i.bindElem||r.elem[0],l=(i.isInput(s)?\"val\":\"html\",i.isInput(s)?s.value:\"static\"===r.position?\"\":s.innerHTML),c=function(e){e.year>d[1]&&(e.year=d[1],a=!0),e.month>11&&(e.month=11,a=!0),e.hours>23&&(e.hours=0,a=!0),e.minutes>59&&(e.minutes=0,e.hours++,a=!0),e.seconds>59&&(e.seconds=0,e.minutes++,a=!0),t=n.getEndDate(e.month+1,e.year),e.date>t&&(e.date=t,a=!0)},m=function(e,t,n){var o=[\"startTime\",\"endTime\"];t=(t.match(i.EXP_SPLIT)||[]).slice(1),n=n||0,r.range&&(i[o[n]]=i[o[n]]||{}),w.each(i.format,function(s,l){var c=parseFloat(t[s]);t[s].length<l.length&&(a=!0),/yyyy|y/.test(l)?(c<d[0]&&(c=d[0],a=!0),e.year=c):/MM|M/.test(l)?(c<1&&(c=1,a=!0),e.month=c-1):/dd|d/.test(l)?(c<1&&(c=1,a=!0),e.date=c):/HH|H/.test(l)?(c<1&&(c=0,a=!0),e.hours=c,r.range&&(i[o[n]].hours=c)):/mm|m/.test(l)?(c<1&&(c=0,a=!0),e.minutes=c,r.range&&(i[o[n]].minutes=c)):/ss|s/.test(l)&&(c<1&&(c=0,a=!0),e.seconds=c,r.range&&(i[o[n]].seconds=c))}),c(e)};return\"limit\"===e?(c(o),i):(l=l||r.value,\"string\"==typeof l&&(l=l.replace(/\\s+/g,\" \").replace(/^\\s|\\s$/g,\"\")),i.startState&&!i.endState&&(delete i.startState,i.endState=!0),\"string\"==typeof l&&l?i.EXP_IF.test(l)?r.range?(l=l.split(\" \"+r.range+\" \"),i.startDate=i.startDate||i.systemDate(),i.endDate=i.endDate||i.systemDate(),r.dateTime=w.extend({},i.startDate),w.each([i.startDate,i.endDate],function(e,t){m(t,l[e],e)})):m(o,l):(i.hint(\"日期格式不合法<br>必须遵循下述格式：<br>\"+(r.range?r.format+\" \"+r.range+\" \"+r.format:r.format)+\"<br>已为你重置\"),a=!0):l&&l.constructor===Date?r.dateTime=i.systemDate(l):(r.dateTime=i.systemDate(),delete i.startState,delete i.endState,delete i.startDate,delete i.endDate,delete i.startTime,delete i.endTime),c(o),a&&l&&i.setValue(r.range?i.endDate?i.parse():\"\":i.parse()),e&&e(),i)},T.prototype.mark=function(e,t){var n,a=this,i=a.config;return w.each(i.mark,function(e,a){var i=e.split(\"-\");i[0]!=t[0]&&0!=i[0]||i[1]!=t[1]&&0!=i[1]||i[2]!=t[2]||(n=a||t[2])}),n&&e.html('<span class=\"laydate-day-mark\">'+n+\"</span>\"),a},T.prototype.limit=function(e,t,n,a){var i,r=this,o=r.config,l={},d=o[n>41?\"endDate\":\"dateTime\"],c=w.extend({},d,t||{});return w.each({now:c,min:o.min,max:o.max},function(e,t){l[e]=r.newDate(w.extend({year:t.year,month:t.month,date:t.date},function(){var e={};return w.each(a,function(n,a){e[a]=t[a]}),e}())).getTime()}),i=l.now<l.min||l.now>l.max,e&&e[i?\"addClass\":\"removeClass\"](s),i},T.prototype.calendar=function(e){var t,a,i,r=this,s=r.config,l=e||s.dateTime,c=new Date,m=r.lang(),u=\"date\"!==s.type&&\"datetime\"!==s.type,h=e?1:0,y=w(r.table[h]).find(\"td\"),f=w(r.elemHeader[h][2]).find(\"span\");if(l.year<d[0]&&(l.year=d[0],r.hint(\"最低只能支持到公元\"+d[0]+\"年\")),l.year>d[1]&&(l.year=d[1],r.hint(\"最高只能支持到公元\"+d[1]+\"年\")),r.firstDate||(r.firstDate=w.extend({},l)),c.setFullYear(l.year,l.month,1),t=c.getDay(),a=n.getEndDate(l.month||12,l.year),i=n.getEndDate(l.month+1,l.year),w.each(y,function(e,n){var d=[l.year,l.month],c=0;n=w(n),n.removeAttr(\"class\"),e<t?(c=a-t+e,n.addClass(\"laydate-day-prev\"),d=r.getAsYM(l.year,l.month,\"sub\")):e>=t&&e<i+t?(c=e-t,s.range||c+1===l.date&&n.addClass(o)):(c=e-i-t,n.addClass(\"laydate-day-next\"),d=r.getAsYM(l.year,l.month)),d[1]++,d[2]=c+1,n.attr(\"lay-ymd\",d.join(\"-\")).html(d[2]),r.mark(n,d).limit(n,{year:d[0],month:d[1]-1,date:d[2]},e)}),w(f[0]).attr(\"lay-ym\",l.year+\"-\"+(l.month+1)),w(f[1]).attr(\"lay-ym\",l.year+\"-\"+(l.month+1)),\"cn\"===s.lang?(w(f[0]).attr(\"lay-type\",\"year\").html(l.year+\"年\"),w(f[1]).attr(\"lay-type\",\"month\").html(l.month+1+\"月\")):(w(f[0]).attr(\"lay-type\",\"month\").html(m.month[l.month]),w(f[1]).attr(\"lay-type\",\"year\").html(l.year)),u&&(s.range&&(e?r.endDate=r.endDate||{year:l.year+(\"year\"===s.type?1:0),month:l.month+(\"month\"===s.type?0:-1)}:r.startDate=r.startDate||{year:l.year,month:l.month},e&&(r.listYM=[[r.startDate.year,r.startDate.month+1],[r.endDate.year,r.endDate.month+1]],r.list(s.type,0).list(s.type,1),\"time\"===s.type?r.setBtnStatus(\"时间\",w.extend({},r.systemDate(),r.startTime),w.extend({},r.systemDate(),r.endTime)):r.setBtnStatus(!0))),s.range||(r.listYM=[[l.year,l.month+1]],r.list(s.type,0))),s.range&&!e){var p=r.getAsYM(l.year,l.month);r.calendar(w.extend({},l,{year:p[0],month:p[1]}))}return s.range||r.limit(w(r.footer).find(g),null,0,[\"hours\",\"minutes\",\"seconds\"]),s.range&&e&&!u&&r.stampRange(),r},T.prototype.list=function(e,t){var n=this,a=n.config,i=a.dateTime,r=n.lang(),l=a.range&&\"date\"!==a.type&&\"datetime\"!==a.type,d=w.elem(\"ul\",{\"class\":m+\" \"+{year:\"laydate-year-list\",month:\"laydate-month-list\",time:\"laydate-time-list\"}[e]}),c=n.elemHeader[t],u=w(c[2]).find(\"span\"),h=n.elemCont[t||0],y=w(h).find(\".\"+m)[0],f=\"cn\"===a.lang,p=f?\"年\":\"\",T=n.listYM[t]||{},C=[\"hours\",\"minutes\",\"seconds\"],x=[\"startTime\",\"endTime\"][t];if(T[0]<1&&(T[0]=1),\"year\"===e){var M,b=M=T[0]-7;b<1&&(b=M=1),w.each(new Array(15),function(e){var i=w.elem(\"li\",{\"lay-ym\":M}),r={year:M};M==T[0]&&w(i).addClass(o),i.innerHTML=M+p,d.appendChild(i),M<n.firstDate.year?(r.month=a.min.month,r.date=a.min.date):M>=n.firstDate.year&&(r.month=a.max.month,r.date=a.max.date),n.limit(w(i),r,t),M++}),w(u[f?0:1]).attr(\"lay-ym\",M-8+\"-\"+T[1]).html(b+p+\" - \"+(M-1+p))}else if(\"month\"===e)w.each(new Array(12),function(e){var i=w.elem(\"li\",{\"lay-ym\":e}),s={year:T[0],month:e};e+1==T[1]&&w(i).addClass(o),i.innerHTML=r.month[e]+(f?\"月\":\"\"),d.appendChild(i),T[0]<n.firstDate.year?s.date=a.min.date:T[0]>=n.firstDate.year&&(s.date=a.max.date),n.limit(w(i),s,t)}),w(u[f?0:1]).attr(\"lay-ym\",T[0]+\"-\"+T[1]).html(T[0]+p);else if(\"time\"===e){var E=function(){w(d).find(\"ol\").each(function(e,a){w(a).find(\"li\").each(function(a,i){n.limit(w(i),[{hours:a},{hours:n[x].hours,minutes:a},{hours:n[x].hours,minutes:n[x].minutes,seconds:a}][e],t,[[\"hours\"],[\"hours\",\"minutes\"],[\"hours\",\"minutes\",\"seconds\"]][e])})}),a.range||n.limit(w(n.footer).find(g),n[x],0,[\"hours\",\"minutes\",\"seconds\"])};a.range?n[x]||(n[x]={hours:0,minutes:0,seconds:0}):n[x]=i,w.each([24,60,60],function(e,t){var a=w.elem(\"li\"),i=[\"<p>\"+r.time[e]+\"</p><ol>\"];w.each(new Array(t),function(t){i.push(\"<li\"+(n[x][C[e]]===t?' class=\"'+o+'\"':\"\")+\">\"+w.digit(t,2)+\"</li>\")}),a.innerHTML=i.join(\"\")+\"</ol>\",d.appendChild(a)}),E()}if(y&&h.removeChild(y),h.appendChild(d),\"year\"===e||\"month\"===e)w(n.elemMain[t]).addClass(\"laydate-ym-show\"),w(d).find(\"li\").on(\"click\",function(){var r=0|w(this).attr(\"lay-ym\");if(!w(this).hasClass(s)){if(0===t)i[e]=r,l&&(n.startDate[e]=r),n.limit(w(n.footer).find(g),null,0);else if(l)n.endDate[e]=r;else{var c=\"year\"===e?n.getAsYM(r,T[1]-1,\"sub\"):n.getAsYM(T[0],r,\"sub\");w.extend(i,{year:c[0],month:c[1]})}\"year\"===a.type||\"month\"===a.type?(w(d).find(\".\"+o).removeClass(o),w(this).addClass(o),\"month\"===a.type&&\"year\"===e&&(n.listYM[t][0]=r,l&&(n[[\"startDate\",\"endDate\"][t]].year=r),n.list(\"month\",t))):(n.checkDate(\"limit\").calendar(),n.closeList()),n.setBtnStatus(),a.range||n.done(null,\"change\"),w(n.footer).find(D).removeClass(s)}});else{var S=w.elem(\"span\",{\"class\":v}),k=function(){w(d).find(\"ol\").each(function(e){var t=this,a=w(t).find(\"li\");t.scrollTop=30*(n[x][C[e]]-2),t.scrollTop<=0&&a.each(function(e,n){if(!w(this).hasClass(s))return t.scrollTop=30*(e-2),!0})})},H=w(c[2]).find(\".\"+v);k(),S.innerHTML=a.range?[r.startTime,r.endTime][t]:r.timeTips,w(n.elemMain[t]).addClass(\"laydate-time-show\"),H[0]&&H.remove(),c[2].appendChild(S),w(d).find(\"ol\").each(function(e){var t=this;w(t).find(\"li\").on(\"click\",function(){var r=0|this.innerHTML;w(this).hasClass(s)||(a.range?n[x][C[e]]=r:i[C[e]]=r,w(t).find(\".\"+o).removeClass(o),w(this).addClass(o),E(),k(),(n.endDate||\"time\"===a.type)&&n.done(null,\"change\"),n.setBtnStatus())})})}return n},T.prototype.listYM=[],T.prototype.closeList=function(){var e=this;e.config;w.each(e.elemCont,function(t,n){w(this).find(\".\"+m).remove(),w(e.elemMain[t]).removeClass(\"laydate-ym-show laydate-time-show\")}),w(e.elem).find(\".\"+v).remove()},T.prototype.setBtnStatus=function(e,t,n){var a,i=this,r=i.config,o=w(i.footer).find(g),d=r.range&&\"date\"!==r.type&&\"time\"!==r.type;d&&(t=t||i.startDate,n=n||i.endDate,a=i.newDate(t).getTime()>i.newDate(n).getTime(),i.limit(null,t)||i.limit(null,n)?o.addClass(s):o[a?\"addClass\":\"removeClass\"](s),e&&a&&i.hint(\"string\"==typeof e?l.replace(/日期/g,e):l))},T.prototype.parse=function(e,t){var n=this,a=n.config,i=t||(e?w.extend({},n.endDate,n.endTime):a.range?w.extend({},n.startDate,n.startTime):a.dateTime),r=n.format.concat();return w.each(r,function(e,t){/yyyy|y/.test(t)?r[e]=w.digit(i.year,t.length):/MM|M/.test(t)?r[e]=w.digit(i.month+1,t.length):/dd|d/.test(t)?r[e]=w.digit(i.date,t.length):/HH|H/.test(t)?r[e]=w.digit(i.hours,t.length):/mm|m/.test(t)?r[e]=w.digit(i.minutes,t.length):/ss|s/.test(t)&&(r[e]=w.digit(i.seconds,t.length))}),a.range&&!e?r.join(\"\")+\" \"+a.range+\" \"+n.parse(1):r.join(\"\")},T.prototype.newDate=function(e){return e=e||{},new Date(e.year||1,e.month||0,e.date||1,e.hours||0,e.minutes||0,e.seconds||0)},T.prototype.setValue=function(e){var t=this,n=t.config,a=t.bindElem||n.elem[0],i=t.isInput(a)?\"val\":\"html\";return\"static\"===n.position||w(a)[i](e||\"\"),this},T.prototype.stampRange=function(){var e,t,n=this,a=n.config,i=w(n.elem).find(\"td\");if(a.range&&!n.endDate&&w(n.footer).find(g).addClass(s),n.endDate)return e=n.newDate({year:n.startDate.year,month:n.startDate.month,date:n.startDate.date}).getTime(),t=n.newDate({year:n.endDate.year,month:n.endDate.month,date:n.endDate.date}).getTime(),e>t?n.hint(l):void w.each(i,function(a,i){var r=w(i).attr(\"lay-ymd\").split(\"-\"),s=n.newDate({year:r[0],month:r[1]-1,date:r[2]}).getTime();w(i).removeClass(u+\" \"+o),s!==e&&s!==t||w(i).addClass(w(i).hasClass(y)||w(i).hasClass(f)?u:o),s>e&&s<t&&w(i).addClass(u)})},T.prototype.done=function(e,t){var n=this,a=n.config,i=w.extend({},n.startDate?w.extend(n.startDate,n.startTime):a.dateTime),r=w.extend({},w.extend(n.endDate,n.endTime));return w.each([i,r],function(e,t){\"month\"in t&&w.extend(t,{month:t.month+1})}),e=e||[n.parse(),i,r],\"function\"==typeof a[t||\"done\"]&&a[t||\"done\"].apply(a,e),n},T.prototype.choose=function(e){var t=this,n=t.config,a=n.dateTime,i=w(t.elem).find(\"td\"),r=e.attr(\"lay-ymd\").split(\"-\"),l=function(e){new Date;e&&w.extend(a,r),n.range&&(t.startDate?w.extend(t.startDate,r):t.startDate=w.extend({},r,t.startTime),t.startYMD=r)};if(r={year:0|r[0],month:(0|r[1])-1,date:0|r[2]},!e.hasClass(s))if(n.range){if(w.each([\"startTime\",\"endTime\"],function(e,n){t[n]=t[n]||{hours:0,minutes:0,seconds:0}}),t.endState)l(),delete t.endState,delete t.endDate,t.startState=!0,i.removeClass(o+\" \"+u),e.addClass(o);else if(t.startState){if(e.addClass(o),t.endDate?w.extend(t.endDate,r):t.endDate=w.extend({},r,t.endTime),t.newDate(r).getTime()<t.newDate(t.startYMD).getTime()){var d=w.extend({},t.endDate,{hours:t.startDate.hours,minutes:t.startDate.minutes,seconds:t.startDate.seconds});w.extend(t.endDate,t.startDate,{hours:t.endDate.hours,minutes:t.endDate.minutes,seconds:t.endDate.seconds}),t.startDate=d}n.showBottom||t.done(),t.stampRange(),t.endState=!0,t.done(null,\"change\")}else e.addClass(o),l(),t.startState=!0;w(t.footer).find(g)[t.endDate?\"removeClass\":\"addClass\"](s)}else\"static\"===n.position?(l(!0),t.calendar().done().done(null,\"change\")):\"date\"===n.type?(l(!0),t.setValue(t.parse()).remove().done()):\"datetime\"===n.type&&(l(!0),t.calendar().done(null,\"change\"))},T.prototype.tool=function(e,t){var n=this,a=n.config,i=a.dateTime,r=\"static\"===a.position,o={datetime:function(){w(e).hasClass(s)||(n.list(\"time\",0),a.range&&n.list(\"time\",1),w(e).attr(\"lay-type\",\"date\").html(n.lang().dateTips))},date:function(){n.closeList(),w(e).attr(\"lay-type\",\"datetime\").html(n.lang().timeTips)},clear:function(){n.setValue(\"\").remove(),r&&(w.extend(i,n.firstDate),n.calendar()),a.range&&(delete n.startState,delete n.endState,delete n.endDate,delete n.startTime,delete n.endTime),n.done([\"\",{},{}])},now:function(){var e=new Date;w.extend(i,n.systemDate(),{hours:e.getHours(),minutes:e.getMinutes(),seconds:e.getSeconds()}),n.setValue(n.parse()).remove(),r&&n.calendar(),n.done()},confirm:function(){if(a.range){if(!n.endDate)return n.hint(\"请先选择日期范围\");if(w(e).hasClass(s))return n.hint(\"time\"===a.type?l.replace(/日期/g,\"时间\"):l)}else if(w(e).hasClass(s))return n.hint(\"不在有效日期或时间范围内\");n.done(),n.setValue(n.parse()).remove()}};o[t]&&o[t]()},T.prototype.change=function(e){var t=this,n=t.config,a=n.dateTime,i=n.range&&(\"year\"===n.type||\"month\"===n.type),r=t.elemCont[e||0],o=t.listYM[e],s=function(s){var l=[\"startDate\",\"endDate\"][e],d=w(r).find(\".laydate-year-list\")[0],c=w(r).find(\".laydate-month-list\")[0];return d&&(o[0]=s?o[0]-15:o[0]+15,t.list(\"year\",e)),c&&(s?o[0]--:o[0]++,t.list(\"month\",e)),(d||c)&&(w.extend(a,{year:o[0]}),i&&(t[l].year=o[0]),n.range||t.done(null,\"change\"),t.setBtnStatus(),n.range||t.limit(w(t.footer).find(g),{year:o[0]})),d||c};return{prevYear:function(){s(\"sub\")||(a.year--,t.checkDate(\"limit\").calendar(),n.range||t.done(null,\"change\"))},prevMonth:function(){var e=t.getAsYM(a.year,a.month,\"sub\");w.extend(a,{year:e[0],month:e[1]}),t.checkDate(\"limit\").calendar(),n.range||t.done(null,\"change\")},nextMonth:function(){var e=t.getAsYM(a.year,a.month);w.extend(a,{year:e[0],month:e[1]}),t.checkDate(\"limit\").calendar(),n.range||t.done(null,\"change\")},nextYear:function(){s()||(a.year++,t.checkDate(\"limit\").calendar(),n.range||t.done(null,\"change\"))}}},T.prototype.changeEvent=function(){var e=this;e.config;w(e.elem).on(\"click\",function(e){w.stope(e)}),w.each(e.elemHeader,function(t,n){w(n[0]).on(\"click\",function(n){e.change(t).prevYear()}),w(n[1]).on(\"click\",function(n){e.change(t).prevMonth()}),w(n[2]).find(\"span\").on(\"click\",function(n){var a=w(this),i=a.attr(\"lay-ym\"),r=a.attr(\"lay-type\");i&&(i=i.split(\"-\"),e.listYM[t]=[0|i[0],0|i[1]],e.list(r,t),w(e.footer).find(D).addClass(s))}),w(n[3]).on(\"click\",function(n){e.change(t).nextMonth()}),w(n[4]).on(\"click\",function(n){e.change(t).nextYear()})}),w.each(e.table,function(t,n){var a=w(n).find(\"td\");a.on(\"click\",function(){e.choose(w(this))})}),w(e.footer).find(\"span\").on(\"click\",function(){var t=w(this).attr(\"lay-type\");e.tool(this,t)})},T.prototype.isInput=function(e){return/input|textarea/.test(e.tagName.toLocaleLowerCase())},T.prototype.events=function(){var e=this,t=e.config,n=function(n,a){n.on(t.trigger,function(){a&&(e.bindElem=this),e.render()})};t.elem[0]&&!t.elem[0].eventHandler&&(n(t.elem,\"bind\"),n(t.eventElem),w(document).on(\"click\",function(n){n.target!==t.elem[0]&&n.target!==t.eventElem[0]&&n.target!==w(t.closeStop)[0]&&e.remove()}).on(\"keydown\",function(t){13===t.keyCode&&w(\"#\"+e.elemID)[0]&&e.elemID===T.thisElem&&(t.preventDefault(),w(e.footer).find(g)[0].click())}),w(window).on(\"resize\",function(){return!(!e.elem||!w(r)[0])&&void e.position()}),t.elem[0].eventHandler=!0)},n.render=function(e){var t=new T(e);return a.call(t)},n.getEndDate=function(e,t){var n=new Date;return n.setFullYear(t||n.getFullYear(),e||n.getMonth()+1,1),new Date(n.getTime()-864e5).getDate()},window.lay=window.lay||w,e?(n.ready(),layui.define(function(e){n.path=layui.cache.dir,e(i,n)})):\"function\"==typeof define&&define.amd?define(function(){return n}):function(){n.ready(),window.laydate=n}()}();"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/layui/lay/modules/layedit.js",
    "content": "/** layui-v2.2.5 MIT License By https://www.layui.com */\n ;layui.define([\"layer\",\"form\"],function(t){\"use strict\";var e=layui.$,i=layui.layer,a=layui.form,l=(layui.hint(),layui.device()),n=\"layedit\",o=\"layui-show\",r=\"layui-disabled\",c=function(){var t=this;t.index=0,t.config={tool:[\"strong\",\"italic\",\"underline\",\"del\",\"|\",\"left\",\"center\",\"right\",\"|\",\"link\",\"unlink\",\"face\",\"image\"],hideTool:[],height:280}};c.prototype.set=function(t){var i=this;return e.extend(!0,i.config,t),i},c.prototype.on=function(t,e){return layui.onevent(n,t,e)},c.prototype.build=function(t,i){i=i||{};var a=this,n=a.config,r=\"layui-layedit\",c=e(\"#\"+t),u=\"LAY_layedit_\"+ ++a.index,d=c.next(\".\"+r),y=e.extend({},n,i),f=function(){var t=[],e={};return layui.each(y.hideTool,function(t,i){e[i]=!0}),layui.each(y.tool,function(i,a){C[a]&&!e[a]&&t.push(C[a])}),t.join(\"\")}(),m=e(['<div class=\"'+r+'\">','<div class=\"layui-unselect layui-layedit-tool\">'+f+\"</div>\",'<div class=\"layui-layedit-iframe\">','<iframe id=\"'+u+'\" name=\"'+u+'\" textarea=\"'+t+'\" frameborder=\"0\"></iframe>',\"</div>\",\"</div>\"].join(\"\"));return l.ie&&l.ie<8?c.removeClass(\"layui-hide\").addClass(o):(d[0]&&d.remove(),s.call(a,m,c[0],y),c.addClass(\"layui-hide\").after(m),a.index)},c.prototype.getContent=function(t){var e=u(t);if(e[0])return d(e[0].document.body.innerHTML)},c.prototype.getText=function(t){var i=u(t);if(i[0])return e(i[0].document.body).text()},c.prototype.setContent=function(t,i,a){var l=u(t);l[0]&&(a?e(l[0].document.body).append(i):e(l[0].document.body).html(i),layedit.sync(t))},c.prototype.sync=function(t){var i=u(t);if(i[0]){var a=e(\"#\"+i[1].attr(\"textarea\"));a.val(d(i[0].document.body.innerHTML))}},c.prototype.getSelection=function(t){var e=u(t);if(e[0]){var i=m(e[0].document);return document.selection?i.text:i.toString()}};var s=function(t,i,a){var l=this,n=t.find(\"iframe\");n.css({height:a.height}).on(\"load\",function(){var o=n.contents(),r=n.prop(\"contentWindow\"),c=o.find(\"head\"),s=e([\"<style>\",\"*{margin: 0; padding: 0;}\",\"body{padding: 10px; line-height: 20px; overflow-x: hidden; word-wrap: break-word; font: 14px Helvetica Neue,Helvetica,PingFang SC,Microsoft YaHei,Tahoma,Arial,sans-serif; -webkit-box-sizing: border-box !important; -moz-box-sizing: border-box !important; box-sizing: border-box !important;}\",\"a{color:#01AAED; text-decoration:none;}a:hover{color:#c00}\",\"p{margin-bottom: 10px;}\",\"img{display: inline-block; border: none; vertical-align: middle;}\",\"pre{margin: 10px 0; padding: 10px; line-height: 20px; border: 1px solid #ddd; border-left-width: 6px; background-color: #F2F2F2; color: #333; font-family: Courier New; font-size: 12px;}\",\"</style>\"].join(\"\")),u=o.find(\"body\");c.append(s),u.attr(\"contenteditable\",\"true\").css({\"min-height\":a.height}).html(i.value||\"\"),y.apply(l,[r,n,i,a]),g.call(l,r,t,a)})},u=function(t){var i=e(\"#LAY_layedit_\"+t),a=i.prop(\"contentWindow\");return[a,i]},d=function(t){return 8==l.ie&&(t=t.replace(/<.+>/g,function(t){return t.toLowerCase()})),t},y=function(t,a,n,o){var r=t.document,c=e(r.body);c.on(\"keydown\",function(t){var e=t.keyCode;if(13===e){var a=m(r),l=p(a),n=l.parentNode;if(\"pre\"===n.tagName.toLowerCase()){if(t.shiftKey)return;return i.msg(\"请暂时用shift+enter\"),!1}r.execCommand(\"formatBlock\",!1,\"<p>\")}}),e(n).parents(\"form\").on(\"submit\",function(){var t=c.html();8==l.ie&&(t=t.replace(/<.+>/g,function(t){return t.toLowerCase()})),n.value=t}),c.on(\"paste\",function(e){r.execCommand(\"formatBlock\",!1,\"<p>\"),setTimeout(function(){f.call(t,c),n.value=c.html()},100)})},f=function(t){var i=this;i.document;t.find(\"*[style]\").each(function(){var t=this.style.textAlign;this.removeAttribute(\"style\"),e(this).css({\"text-align\":t||\"\"})}),t.find(\"table\").addClass(\"layui-table\"),t.find(\"script,link\").remove()},m=function(t){return t.selection?t.selection.createRange():t.getSelection().getRangeAt(0)},p=function(t){return t.endContainer||t.parentElement().childNodes[0]},v=function(t,i,a){var l=this.document,n=document.createElement(t);for(var o in i)n.setAttribute(o,i[o]);if(n.removeAttribute(\"text\"),l.selection){var r=a.text||i.text;if(\"a\"===t&&!r)return;r&&(n.innerHTML=r),a.pasteHTML(e(n).prop(\"outerHTML\")),a.select()}else{var r=a.toString()||i.text;if(\"a\"===t&&!r)return;r&&(n.innerHTML=r),a.deleteContents(),a.insertNode(n)}},h=function(t,i){var a=this.document,l=\"layedit-tool-active\",n=p(m(a)),o=function(e){return t.find(\".layedit-tool-\"+e)};i&&i[i.hasClass(l)?\"removeClass\":\"addClass\"](l),t.find(\">i\").removeClass(l),o(\"unlink\").addClass(r),e(n).parents().each(function(){var t=this.tagName.toLowerCase(),e=this.style.textAlign;\"b\"!==t&&\"strong\"!==t||o(\"b\").addClass(l),\"i\"!==t&&\"em\"!==t||o(\"i\").addClass(l),\"u\"===t&&o(\"u\").addClass(l),\"strike\"===t&&o(\"d\").addClass(l),\"p\"===t&&(\"center\"===e?o(\"center\").addClass(l):\"right\"===e?o(\"right\").addClass(l):o(\"left\").addClass(l)),\"a\"===t&&(o(\"link\").addClass(l),o(\"unlink\").removeClass(r))})},g=function(t,a,l){var n=t.document,o=e(n.body),c={link:function(i){var a=p(i),l=e(a).parent();b.call(o,{href:l.attr(\"href\"),target:l.attr(\"target\")},function(e){var a=l[0];\"A\"===a.tagName?a.href=e.url:v.call(t,\"a\",{target:e.target,href:e.url,text:e.url},i)})},unlink:function(t){n.execCommand(\"unlink\")},face:function(e){x.call(this,function(i){v.call(t,\"img\",{src:i.src,alt:i.alt},e)})},image:function(a){var n=this;layui.use(\"upload\",function(o){var r=l.uploadImage||{};o.render({url:r.url,method:r.type,elem:e(n).find(\"input\")[0],done:function(e){0==e.code?(e.data=e.data||{},v.call(t,\"img\",{src:e.data.src,alt:e.data.title},a)):i.msg(e.msg||\"上传失败\")}})})},code:function(e){k.call(o,function(i){v.call(t,\"pre\",{text:i.code,\"lay-lang\":i.lang},e)})},help:function(){i.open({type:2,title:\"帮助\",area:[\"600px\",\"380px\"],shadeClose:!0,shade:.1,skin:\"layui-layer-msg\",content:[\"http://www.layui.com/about/layedit/help.html\",\"no\"]})}},s=a.find(\".layui-layedit-tool\"),u=function(){var i=e(this),a=i.attr(\"layedit-event\"),l=i.attr(\"lay-command\");if(!i.hasClass(r)){o.focus();var u=m(n);u.commonAncestorContainer;l?(n.execCommand(l),/justifyLeft|justifyCenter|justifyRight/.test(l)&&n.execCommand(\"formatBlock\",!1,\"<p>\"),setTimeout(function(){o.focus()},10)):c[a]&&c[a].call(this,u),h.call(t,s,i)}},d=/image/;s.find(\">i\").on(\"mousedown\",function(){var t=e(this),i=t.attr(\"layedit-event\");d.test(i)||u.call(this)}).on(\"click\",function(){var t=e(this),i=t.attr(\"layedit-event\");d.test(i)&&u.call(this)}),o.on(\"click\",function(){h.call(t,s),i.close(x.index)})},b=function(t,e){var l=this,n=i.open({type:1,id:\"LAY_layedit_link\",area:\"350px\",shade:.05,shadeClose:!0,moveType:1,title:\"超链接\",skin:\"layui-layer-msg\",content:['<ul class=\"layui-form\" style=\"margin: 15px;\">','<li class=\"layui-form-item\">','<label class=\"layui-form-label\" style=\"width: 60px;\">URL</label>','<div class=\"layui-input-block\" style=\"margin-left: 90px\">','<input name=\"url\" lay-verify=\"url\" value=\"'+(t.href||\"\")+'\" autofocus=\"true\" autocomplete=\"off\" class=\"layui-input\">',\"</div>\",\"</li>\",'<li class=\"layui-form-item\">','<label class=\"layui-form-label\" style=\"width: 60px;\">打开方式</label>','<div class=\"layui-input-block\" style=\"margin-left: 90px\">','<input type=\"radio\" name=\"target\" value=\"_self\" class=\"layui-input\" title=\"当前窗口\"'+(\"_self\"!==t.target&&t.target?\"\":\"checked\")+\">\",'<input type=\"radio\" name=\"target\" value=\"_blank\" class=\"layui-input\" title=\"新窗口\" '+(\"_blank\"===t.target?\"checked\":\"\")+\">\",\"</div>\",\"</li>\",'<li class=\"layui-form-item\" style=\"text-align: center;\">','<button type=\"button\" lay-submit lay-filter=\"layedit-link-yes\" class=\"layui-btn\"> 确定 </button>','<button style=\"margin-left: 20px;\" type=\"button\" class=\"layui-btn layui-btn-primary\"> 取消 </button>',\"</li>\",\"</ul>\"].join(\"\"),success:function(t,n){var o=\"submit(layedit-link-yes)\";a.render(\"radio\"),t.find(\".layui-btn-primary\").on(\"click\",function(){i.close(n),l.focus()}),a.on(o,function(t){i.close(b.index),e&&e(t.field)})}});b.index=n},x=function(t){var a=function(){var t=[\"[微笑]\",\"[嘻嘻]\",\"[哈哈]\",\"[可爱]\",\"[可怜]\",\"[挖鼻]\",\"[吃惊]\",\"[害羞]\",\"[挤眼]\",\"[闭嘴]\",\"[鄙视]\",\"[爱你]\",\"[泪]\",\"[偷笑]\",\"[亲亲]\",\"[生病]\",\"[太开心]\",\"[白眼]\",\"[右哼哼]\",\"[左哼哼]\",\"[嘘]\",\"[衰]\",\"[委屈]\",\"[吐]\",\"[哈欠]\",\"[抱抱]\",\"[怒]\",\"[疑问]\",\"[馋嘴]\",\"[拜拜]\",\"[思考]\",\"[汗]\",\"[困]\",\"[睡]\",\"[钱]\",\"[失望]\",\"[酷]\",\"[色]\",\"[哼]\",\"[鼓掌]\",\"[晕]\",\"[悲伤]\",\"[抓狂]\",\"[黑线]\",\"[阴险]\",\"[怒骂]\",\"[互粉]\",\"[心]\",\"[伤心]\",\"[猪头]\",\"[熊猫]\",\"[兔子]\",\"[ok]\",\"[耶]\",\"[good]\",\"[NO]\",\"[赞]\",\"[来]\",\"[弱]\",\"[草泥马]\",\"[神马]\",\"[囧]\",\"[浮云]\",\"[给力]\",\"[围观]\",\"[威武]\",\"[奥特曼]\",\"[礼物]\",\"[钟]\",\"[话筒]\",\"[蜡烛]\",\"[蛋糕]\"],e={};return layui.each(t,function(t,i){e[i]=layui.cache.dir+\"images/face/\"+t+\".gif\"}),e}();return x.hide=x.hide||function(t){\"face\"!==e(t.target).attr(\"layedit-event\")&&i.close(x.index)},x.index=i.tips(function(){var t=[];return layui.each(a,function(e,i){t.push('<li title=\"'+e+'\"><img src=\"'+i+'\" alt=\"'+e+'\"></li>')}),'<ul class=\"layui-clear\">'+t.join(\"\")+\"</ul>\"}(),this,{tips:1,time:0,skin:\"layui-box layui-util-face\",maxWidth:500,success:function(l,n){l.css({marginTop:-4,marginLeft:-10}).find(\".layui-clear>li\").on(\"click\",function(){t&&t({src:a[this.title],alt:this.title}),i.close(n)}),e(document).off(\"click\",x.hide).on(\"click\",x.hide)}})},k=function(t){var e=this,l=i.open({type:1,id:\"LAY_layedit_code\",area:\"550px\",shade:.05,shadeClose:!0,moveType:1,title:\"插入代码\",skin:\"layui-layer-msg\",content:['<ul class=\"layui-form layui-form-pane\" style=\"margin: 15px;\">','<li class=\"layui-form-item\">','<label class=\"layui-form-label\">请选择语言</label>','<div class=\"layui-input-block\">','<select name=\"lang\">','<option value=\"JavaScript\">JavaScript</option>','<option value=\"HTML\">HTML</option>','<option value=\"CSS\">CSS</option>','<option value=\"Java\">Java</option>','<option value=\"PHP\">PHP</option>','<option value=\"C#\">C#</option>','<option value=\"Python\">Python</option>','<option value=\"Ruby\">Ruby</option>','<option value=\"Go\">Go</option>',\"</select>\",\"</div>\",\"</li>\",'<li class=\"layui-form-item layui-form-text\">','<label class=\"layui-form-label\">代码</label>','<div class=\"layui-input-block\">','<textarea name=\"code\" lay-verify=\"required\" autofocus=\"true\" class=\"layui-textarea\" style=\"height: 200px;\"></textarea>',\"</div>\",\"</li>\",'<li class=\"layui-form-item\" style=\"text-align: center;\">','<button type=\"button\" lay-submit lay-filter=\"layedit-code-yes\" class=\"layui-btn\"> 确定 </button>','<button style=\"margin-left: 20px;\" type=\"button\" class=\"layui-btn layui-btn-primary\"> 取消 </button>',\"</li>\",\"</ul>\"].join(\"\"),success:function(l,n){var o=\"submit(layedit-code-yes)\";a.render(\"select\"),l.find(\".layui-btn-primary\").on(\"click\",function(){i.close(n),e.focus()}),a.on(o,function(e){i.close(k.index),t&&t(e.field)})}});k.index=l},C={html:'<i class=\"layui-icon layedit-tool-html\" title=\"HTML源代码\" lay-command=\"html\" layedit-event=\"html\"\">&#xe64b;</i><span class=\"layedit-tool-mid\"></span>',strong:'<i class=\"layui-icon layedit-tool-b\" title=\"加粗\" lay-command=\"Bold\" layedit-event=\"b\"\">&#xe62b;</i>',italic:'<i class=\"layui-icon layedit-tool-i\" title=\"斜体\" lay-command=\"italic\" layedit-event=\"i\"\">&#xe644;</i>',underline:'<i class=\"layui-icon layedit-tool-u\" title=\"下划线\" lay-command=\"underline\" layedit-event=\"u\"\">&#xe646;</i>',del:'<i class=\"layui-icon layedit-tool-d\" title=\"删除线\" lay-command=\"strikeThrough\" layedit-event=\"d\"\">&#xe64f;</i>',\"|\":'<span class=\"layedit-tool-mid\"></span>',left:'<i class=\"layui-icon layedit-tool-left\" title=\"左对齐\" lay-command=\"justifyLeft\" layedit-event=\"left\"\">&#xe649;</i>',center:'<i class=\"layui-icon layedit-tool-center\" title=\"居中对齐\" lay-command=\"justifyCenter\" layedit-event=\"center\"\">&#xe647;</i>',right:'<i class=\"layui-icon layedit-tool-right\" title=\"右对齐\" lay-command=\"justifyRight\" layedit-event=\"right\"\">&#xe648;</i>',link:'<i class=\"layui-icon layedit-tool-link\" title=\"插入链接\" layedit-event=\"link\"\">&#xe64c;</i>',unlink:'<i class=\"layui-icon layedit-tool-unlink layui-disabled\" title=\"清除链接\" lay-command=\"unlink\" layedit-event=\"unlink\"\">&#xe64d;</i>',face:'<i class=\"layui-icon layedit-tool-face\" title=\"表情\" layedit-event=\"face\"\">&#xe650;</i>',image:'<i class=\"layui-icon layedit-tool-image\" title=\"图片\" layedit-event=\"image\">&#xe64a;<input type=\"file\" name=\"file\"></i>',code:'<i class=\"layui-icon layedit-tool-code\" title=\"插入代码\" layedit-event=\"code\">&#xe64e;</i>',help:'<i class=\"layui-icon layedit-tool-help\" title=\"帮助\" layedit-event=\"help\">&#xe607;</i>'},w=new c;t(n,w)});"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/layui/lay/modules/layer.js",
    "content": "/** layui-v2.2.5 MIT License By https://www.layui.com */\n ;!function(e,t){\"use strict\";var i,n,a=e.layui&&layui.define,o={getPath:function(){var e=document.currentScript?document.currentScript.src:function(){for(var e,t=document.scripts,i=t.length-1,n=i;n>0;n--)if(\"interactive\"===t[n].readyState){e=t[n].src;break}return e||t[i].src}();return e.substring(0,e.lastIndexOf(\"/\")+1)}(),config:{},end:{},minIndex:0,minLeft:[],btn:[\"&#x786E;&#x5B9A;\",\"&#x53D6;&#x6D88;\"],type:[\"dialog\",\"page\",\"iframe\",\"loading\",\"tips\"],getStyle:function(t,i){var n=t.currentStyle?t.currentStyle:e.getComputedStyle(t,null);return n[n.getPropertyValue?\"getPropertyValue\":\"getAttribute\"](i)},link:function(t,i,n){if(r.path){var a=document.getElementsByTagName(\"head\")[0],s=document.createElement(\"link\");\"string\"==typeof i&&(n=i);var l=(n||t).replace(/\\.|\\//g,\"\"),f=\"layuicss-\"+l,c=0;s.rel=\"stylesheet\",s.href=r.path+t,s.id=f,document.getElementById(f)||a.appendChild(s),\"function\"==typeof i&&!function u(){return++c>80?e.console&&console.error(\"layer.css: Invalid\"):void(1989===parseInt(o.getStyle(document.getElementById(f),\"width\"))?i():setTimeout(u,100))}()}}},r={v:\"3.1.1\",ie:function(){var t=navigator.userAgent.toLowerCase();return!!(e.ActiveXObject||\"ActiveXObject\"in e)&&((t.match(/msie\\s(\\d+)/)||[])[1]||\"11\")}(),index:e.layer&&e.layer.v?1e5:0,path:o.getPath,config:function(e,t){return e=e||{},r.cache=o.config=i.extend({},o.config,e),r.path=o.config.path||r.path,\"string\"==typeof e.extend&&(e.extend=[e.extend]),o.config.path&&r.ready(),e.extend?(a?layui.addcss(\"modules/layer/\"+e.extend):o.link(\"theme/\"+e.extend),this):this},ready:function(e){var t=\"layer\",i=\"\",n=(a?\"modules/layer/\":\"theme/\")+\"default/layer.css?v=\"+r.v+i;return a?layui.addcss(n,e,t):o.link(n,e,t),this},alert:function(e,t,n){var a=\"function\"==typeof t;return a&&(n=t),r.open(i.extend({content:e,yes:n},a?{}:t))},confirm:function(e,t,n,a){var s=\"function\"==typeof t;return s&&(a=n,n=t),r.open(i.extend({content:e,btn:o.btn,yes:n,btn2:a},s?{}:t))},msg:function(e,n,a){var s=\"function\"==typeof n,f=o.config.skin,c=(f?f+\" \"+f+\"-msg\":\"\")||\"layui-layer-msg\",u=l.anim.length-1;return s&&(a=n),r.open(i.extend({content:e,time:3e3,shade:!1,skin:c,title:!1,closeBtn:!1,btn:!1,resize:!1,end:a},s&&!o.config.skin?{skin:c+\" layui-layer-hui\",anim:u}:function(){return n=n||{},(n.icon===-1||n.icon===t&&!o.config.skin)&&(n.skin=c+\" \"+(n.skin||\"layui-layer-hui\")),n}()))},load:function(e,t){return r.open(i.extend({type:3,icon:e||0,resize:!1,shade:.01},t))},tips:function(e,t,n){return r.open(i.extend({type:4,content:[e,t],closeBtn:!1,time:3e3,shade:!1,resize:!1,fixed:!1,maxWidth:210},n))}},s=function(e){var t=this;t.index=++r.index,t.config=i.extend({},t.config,o.config,e),document.body?t.creat():setTimeout(function(){t.creat()},30)};s.pt=s.prototype;var l=[\"layui-layer\",\".layui-layer-title\",\".layui-layer-main\",\".layui-layer-dialog\",\"layui-layer-iframe\",\"layui-layer-content\",\"layui-layer-btn\",\"layui-layer-close\"];l.anim=[\"layer-anim-00\",\"layer-anim-01\",\"layer-anim-02\",\"layer-anim-03\",\"layer-anim-04\",\"layer-anim-05\",\"layer-anim-06\"],s.pt.config={type:0,shade:.3,fixed:!0,move:l[1],title:\"&#x4FE1;&#x606F;\",offset:\"auto\",area:\"auto\",closeBtn:1,time:0,zIndex:19891014,maxWidth:360,anim:0,isOutAnim:!0,icon:-1,moveType:1,resize:!0,scrollbar:!0,tips:2},s.pt.vessel=function(e,t){var n=this,a=n.index,r=n.config,s=r.zIndex+a,f=\"object\"==typeof r.title,c=r.maxmin&&(1===r.type||2===r.type),u=r.title?'<div class=\"layui-layer-title\" style=\"'+(f?r.title[1]:\"\")+'\">'+(f?r.title[0]:r.title)+\"</div>\":\"\";return r.zIndex=s,t([r.shade?'<div class=\"layui-layer-shade\" id=\"layui-layer-shade'+a+'\" times=\"'+a+'\" style=\"'+(\"z-index:\"+(s-1)+\"; \")+'\"></div>':\"\",'<div class=\"'+l[0]+(\" layui-layer-\"+o.type[r.type])+(0!=r.type&&2!=r.type||r.shade?\"\":\" layui-layer-border\")+\" \"+(r.skin||\"\")+'\" id=\"'+l[0]+a+'\" type=\"'+o.type[r.type]+'\" times=\"'+a+'\" showtime=\"'+r.time+'\" conType=\"'+(e?\"object\":\"string\")+'\" style=\"z-index: '+s+\"; width:\"+r.area[0]+\";height:\"+r.area[1]+(r.fixed?\"\":\";position:absolute;\")+'\">'+(e&&2!=r.type?\"\":u)+'<div id=\"'+(r.id||\"\")+'\" class=\"layui-layer-content'+(0==r.type&&r.icon!==-1?\" layui-layer-padding\":\"\")+(3==r.type?\" layui-layer-loading\"+r.icon:\"\")+'\">'+(0==r.type&&r.icon!==-1?'<i class=\"layui-layer-ico layui-layer-ico'+r.icon+'\"></i>':\"\")+(1==r.type&&e?\"\":r.content||\"\")+'</div><span class=\"layui-layer-setwin\">'+function(){var e=c?'<a class=\"layui-layer-min\" href=\"javascript:;\"><cite></cite></a><a class=\"layui-layer-ico layui-layer-max\" href=\"javascript:;\"></a>':\"\";return r.closeBtn&&(e+='<a class=\"layui-layer-ico '+l[7]+\" \"+l[7]+(r.title?r.closeBtn:4==r.type?\"1\":\"2\")+'\" href=\"javascript:;\"></a>'),e}()+\"</span>\"+(r.btn?function(){var e=\"\";\"string\"==typeof r.btn&&(r.btn=[r.btn]);for(var t=0,i=r.btn.length;t<i;t++)e+='<a class=\"'+l[6]+t+'\">'+r.btn[t]+\"</a>\";return'<div class=\"'+l[6]+\" layui-layer-btn-\"+(r.btnAlign||\"\")+'\">'+e+\"</div>\"}():\"\")+(r.resize?'<span class=\"layui-layer-resize\"></span>':\"\")+\"</div>\"],u,i('<div class=\"layui-layer-move\"></div>')),n},s.pt.creat=function(){var e=this,t=e.config,a=e.index,s=t.content,f=\"object\"==typeof s,c=i(\"body\");if(!t.id||!i(\"#\"+t.id)[0]){switch(\"string\"==typeof t.area&&(t.area=\"auto\"===t.area?[\"\",\"\"]:[t.area,\"\"]),t.shift&&(t.anim=t.shift),6==r.ie&&(t.fixed=!1),t.type){case 0:t.btn=\"btn\"in t?t.btn:o.btn[0],r.closeAll(\"dialog\");break;case 2:var s=t.content=f?t.content:[t.content||\"http://layer.layui.com\",\"auto\"];t.content='<iframe scrolling=\"'+(t.content[1]||\"auto\")+'\" allowtransparency=\"true\" id=\"'+l[4]+a+'\" name=\"'+l[4]+a+'\" onload=\"this.className=\\'\\';\" class=\"layui-layer-load\" frameborder=\"0\" src=\"'+t.content[0]+'\"></iframe>';break;case 3:delete t.title,delete t.closeBtn,t.icon===-1&&0===t.icon,r.closeAll(\"loading\");break;case 4:f||(t.content=[t.content,\"body\"]),t.follow=t.content[1],t.content=t.content[0]+'<i class=\"layui-layer-TipsG\"></i>',delete t.title,t.tips=\"object\"==typeof t.tips?t.tips:[t.tips,!0],t.tipsMore||r.closeAll(\"tips\")}if(e.vessel(f,function(n,r,u){c.append(n[0]),f?function(){2==t.type||4==t.type?function(){i(\"body\").append(n[1])}():function(){s.parents(\".\"+l[0])[0]||(s.data(\"display\",s.css(\"display\")).show().addClass(\"layui-layer-wrap\").wrap(n[1]),i(\"#\"+l[0]+a).find(\".\"+l[5]).before(r))}()}():c.append(n[1]),i(\".layui-layer-move\")[0]||c.append(o.moveElem=u),e.layero=i(\"#\"+l[0]+a),t.scrollbar||l.html.css(\"overflow\",\"hidden\").attr(\"layer-full\",a)}).auto(a),i(\"#layui-layer-shade\"+e.index).css({\"background-color\":t.shade[1]||\"#000\",opacity:t.shade[0]||t.shade}),2==t.type&&6==r.ie&&e.layero.find(\"iframe\").attr(\"src\",s[0]),4==t.type?e.tips():e.offset(),t.fixed&&n.on(\"resize\",function(){e.offset(),(/^\\d+%$/.test(t.area[0])||/^\\d+%$/.test(t.area[1]))&&e.auto(a),4==t.type&&e.tips()}),t.time<=0||setTimeout(function(){r.close(e.index)},t.time),e.move().callback(),l.anim[t.anim]){var u=\"layer-anim \"+l.anim[t.anim];e.layero.addClass(u).one(\"webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend\",function(){i(this).removeClass(u)})}t.isOutAnim&&e.layero.data(\"isOutAnim\",!0)}},s.pt.auto=function(e){var t=this,a=t.config,o=i(\"#\"+l[0]+e);\"\"===a.area[0]&&a.maxWidth>0&&(r.ie&&r.ie<8&&a.btn&&o.width(o.innerWidth()),o.outerWidth()>a.maxWidth&&o.width(a.maxWidth));var s=[o.innerWidth(),o.innerHeight()],f=o.find(l[1]).outerHeight()||0,c=o.find(\".\"+l[6]).outerHeight()||0,u=function(e){e=o.find(e),e.height(s[1]-f-c-2*(0|parseFloat(e.css(\"padding-top\"))))};switch(a.type){case 2:u(\"iframe\");break;default:\"\"===a.area[1]?a.maxHeight>0&&o.outerHeight()>a.maxHeight?(s[1]=a.maxHeight,u(\".\"+l[5])):a.fixed&&s[1]>=n.height()&&(s[1]=n.height(),u(\".\"+l[5])):u(\".\"+l[5])}return t},s.pt.offset=function(){var e=this,t=e.config,i=e.layero,a=[i.outerWidth(),i.outerHeight()],o=\"object\"==typeof t.offset;e.offsetTop=(n.height()-a[1])/2,e.offsetLeft=(n.width()-a[0])/2,o?(e.offsetTop=t.offset[0],e.offsetLeft=t.offset[1]||e.offsetLeft):\"auto\"!==t.offset&&(\"t\"===t.offset?e.offsetTop=0:\"r\"===t.offset?e.offsetLeft=n.width()-a[0]:\"b\"===t.offset?e.offsetTop=n.height()-a[1]:\"l\"===t.offset?e.offsetLeft=0:\"lt\"===t.offset?(e.offsetTop=0,e.offsetLeft=0):\"lb\"===t.offset?(e.offsetTop=n.height()-a[1],e.offsetLeft=0):\"rt\"===t.offset?(e.offsetTop=0,e.offsetLeft=n.width()-a[0]):\"rb\"===t.offset?(e.offsetTop=n.height()-a[1],e.offsetLeft=n.width()-a[0]):e.offsetTop=t.offset),t.fixed||(e.offsetTop=/%$/.test(e.offsetTop)?n.height()*parseFloat(e.offsetTop)/100:parseFloat(e.offsetTop),e.offsetLeft=/%$/.test(e.offsetLeft)?n.width()*parseFloat(e.offsetLeft)/100:parseFloat(e.offsetLeft),e.offsetTop+=n.scrollTop(),e.offsetLeft+=n.scrollLeft()),i.attr(\"minLeft\")&&(e.offsetTop=n.height()-(i.find(l[1]).outerHeight()||0),e.offsetLeft=i.css(\"left\")),i.css({top:e.offsetTop,left:e.offsetLeft})},s.pt.tips=function(){var e=this,t=e.config,a=e.layero,o=[a.outerWidth(),a.outerHeight()],r=i(t.follow);r[0]||(r=i(\"body\"));var s={width:r.outerWidth(),height:r.outerHeight(),top:r.offset().top,left:r.offset().left},f=a.find(\".layui-layer-TipsG\"),c=t.tips[0];t.tips[1]||f.remove(),s.autoLeft=function(){s.left+o[0]-n.width()>0?(s.tipLeft=s.left+s.width-o[0],f.css({right:12,left:\"auto\"})):s.tipLeft=s.left},s.where=[function(){s.autoLeft(),s.tipTop=s.top-o[1]-10,f.removeClass(\"layui-layer-TipsB\").addClass(\"layui-layer-TipsT\").css(\"border-right-color\",t.tips[1])},function(){s.tipLeft=s.left+s.width+10,s.tipTop=s.top,f.removeClass(\"layui-layer-TipsL\").addClass(\"layui-layer-TipsR\").css(\"border-bottom-color\",t.tips[1])},function(){s.autoLeft(),s.tipTop=s.top+s.height+10,f.removeClass(\"layui-layer-TipsT\").addClass(\"layui-layer-TipsB\").css(\"border-right-color\",t.tips[1])},function(){s.tipLeft=s.left-o[0]-10,s.tipTop=s.top,f.removeClass(\"layui-layer-TipsR\").addClass(\"layui-layer-TipsL\").css(\"border-bottom-color\",t.tips[1])}],s.where[c-1](),1===c?s.top-(n.scrollTop()+o[1]+16)<0&&s.where[2]():2===c?n.width()-(s.left+s.width+o[0]+16)>0||s.where[3]():3===c?s.top-n.scrollTop()+s.height+o[1]+16-n.height()>0&&s.where[0]():4===c&&o[0]+16-s.left>0&&s.where[1](),a.find(\".\"+l[5]).css({\"background-color\":t.tips[1],\"padding-right\":t.closeBtn?\"30px\":\"\"}),a.css({left:s.tipLeft-(t.fixed?n.scrollLeft():0),top:s.tipTop-(t.fixed?n.scrollTop():0)})},s.pt.move=function(){var e=this,t=e.config,a=i(document),s=e.layero,l=s.find(t.move),f=s.find(\".layui-layer-resize\"),c={};return t.move&&l.css(\"cursor\",\"move\"),l.on(\"mousedown\",function(e){e.preventDefault(),t.move&&(c.moveStart=!0,c.offset=[e.clientX-parseFloat(s.css(\"left\")),e.clientY-parseFloat(s.css(\"top\"))],o.moveElem.css(\"cursor\",\"move\").show())}),f.on(\"mousedown\",function(e){e.preventDefault(),c.resizeStart=!0,c.offset=[e.clientX,e.clientY],c.area=[s.outerWidth(),s.outerHeight()],o.moveElem.css(\"cursor\",\"se-resize\").show()}),a.on(\"mousemove\",function(i){if(c.moveStart){var a=i.clientX-c.offset[0],o=i.clientY-c.offset[1],l=\"fixed\"===s.css(\"position\");if(i.preventDefault(),c.stX=l?0:n.scrollLeft(),c.stY=l?0:n.scrollTop(),!t.moveOut){var f=n.width()-s.outerWidth()+c.stX,u=n.height()-s.outerHeight()+c.stY;a<c.stX&&(a=c.stX),a>f&&(a=f),o<c.stY&&(o=c.stY),o>u&&(o=u)}s.css({left:a,top:o})}if(t.resize&&c.resizeStart){var a=i.clientX-c.offset[0],o=i.clientY-c.offset[1];i.preventDefault(),r.style(e.index,{width:c.area[0]+a,height:c.area[1]+o}),c.isResize=!0,t.resizing&&t.resizing(s)}}).on(\"mouseup\",function(e){c.moveStart&&(delete c.moveStart,o.moveElem.hide(),t.moveEnd&&t.moveEnd(s)),c.resizeStart&&(delete c.resizeStart,o.moveElem.hide())}),e},s.pt.callback=function(){function e(){var e=a.cancel&&a.cancel(t.index,n);e===!1||r.close(t.index)}var t=this,n=t.layero,a=t.config;t.openLayer(),a.success&&(2==a.type?n.find(\"iframe\").on(\"load\",function(){a.success(n,t.index)}):a.success(n,t.index)),6==r.ie&&t.IE6(n),n.find(\".\"+l[6]).children(\"a\").on(\"click\",function(){var e=i(this).index();if(0===e)a.yes?a.yes(t.index,n):a.btn1?a.btn1(t.index,n):r.close(t.index);else{var o=a[\"btn\"+(e+1)]&&a[\"btn\"+(e+1)](t.index,n);o===!1||r.close(t.index)}}),n.find(\".\"+l[7]).on(\"click\",e),a.shadeClose&&i(\"#layui-layer-shade\"+t.index).on(\"click\",function(){r.close(t.index)}),n.find(\".layui-layer-min\").on(\"click\",function(){var e=a.min&&a.min(n);e===!1||r.min(t.index,a)}),n.find(\".layui-layer-max\").on(\"click\",function(){i(this).hasClass(\"layui-layer-maxmin\")?(r.restore(t.index),a.restore&&a.restore(n)):(r.full(t.index,a),setTimeout(function(){a.full&&a.full(n)},100))}),a.end&&(o.end[t.index]=a.end)},o.reselect=function(){i.each(i(\"select\"),function(e,t){var n=i(this);n.parents(\".\"+l[0])[0]||1==n.attr(\"layer\")&&i(\".\"+l[0]).length<1&&n.removeAttr(\"layer\").show(),n=null})},s.pt.IE6=function(e){i(\"select\").each(function(e,t){var n=i(this);n.parents(\".\"+l[0])[0]||\"none\"===n.css(\"display\")||n.attr({layer:\"1\"}).hide(),n=null})},s.pt.openLayer=function(){var e=this;r.zIndex=e.config.zIndex,r.setTop=function(e){var t=function(){r.zIndex++,e.css(\"z-index\",r.zIndex+1)};return r.zIndex=parseInt(e[0].style.zIndex),e.on(\"mousedown\",t),r.zIndex}},o.record=function(e){var t=[e.width(),e.height(),e.position().top,e.position().left+parseFloat(e.css(\"margin-left\"))];e.find(\".layui-layer-max\").addClass(\"layui-layer-maxmin\"),e.attr({area:t})},o.rescollbar=function(e){l.html.attr(\"layer-full\")==e&&(l.html[0].style.removeProperty?l.html[0].style.removeProperty(\"overflow\"):l.html[0].style.removeAttribute(\"overflow\"),l.html.removeAttr(\"layer-full\"))},e.layer=r,r.getChildFrame=function(e,t){return t=t||i(\".\"+l[4]).attr(\"times\"),i(\"#\"+l[0]+t).find(\"iframe\").contents().find(e)},r.getFrameIndex=function(e){return i(\"#\"+e).parents(\".\"+l[4]).attr(\"times\")},r.iframeAuto=function(e){if(e){var t=r.getChildFrame(\"html\",e).outerHeight(),n=i(\"#\"+l[0]+e),a=n.find(l[1]).outerHeight()||0,o=n.find(\".\"+l[6]).outerHeight()||0;n.css({height:t+a+o}),n.find(\"iframe\").css({height:t})}},r.iframeSrc=function(e,t){i(\"#\"+l[0]+e).find(\"iframe\").attr(\"src\",t)},r.style=function(e,t,n){var a=i(\"#\"+l[0]+e),r=a.find(\".layui-layer-content\"),s=a.attr(\"type\"),f=a.find(l[1]).outerHeight()||0,c=a.find(\".\"+l[6]).outerHeight()||0;a.attr(\"minLeft\");s!==o.type[3]&&s!==o.type[4]&&(n||(parseFloat(t.width)<=260&&(t.width=260),parseFloat(t.height)-f-c<=64&&(t.height=64+f+c)),a.css(t),c=a.find(\".\"+l[6]).outerHeight(),s===o.type[2]?a.find(\"iframe\").css({height:parseFloat(t.height)-f-c}):r.css({height:parseFloat(t.height)-f-c-parseFloat(r.css(\"padding-top\"))-parseFloat(r.css(\"padding-bottom\"))}))},r.min=function(e,t){var a=i(\"#\"+l[0]+e),s=a.find(l[1]).outerHeight()||0,f=a.attr(\"minLeft\")||181*o.minIndex+\"px\",c=a.css(\"position\");o.record(a),o.minLeft[0]&&(f=o.minLeft[0],o.minLeft.shift()),a.attr(\"position\",c),r.style(e,{width:180,height:s,left:f,top:n.height()-s,position:\"fixed\",overflow:\"hidden\"},!0),a.find(\".layui-layer-min\").hide(),\"page\"===a.attr(\"type\")&&a.find(l[4]).hide(),o.rescollbar(e),a.attr(\"minLeft\")||o.minIndex++,a.attr(\"minLeft\",f)},r.restore=function(e){var t=i(\"#\"+l[0]+e),n=t.attr(\"area\").split(\",\");t.attr(\"type\");r.style(e,{width:parseFloat(n[0]),height:parseFloat(n[1]),top:parseFloat(n[2]),left:parseFloat(n[3]),position:t.attr(\"position\"),overflow:\"visible\"},!0),t.find(\".layui-layer-max\").removeClass(\"layui-layer-maxmin\"),t.find(\".layui-layer-min\").show(),\"page\"===t.attr(\"type\")&&t.find(l[4]).show(),o.rescollbar(e)},r.full=function(e){var t,a=i(\"#\"+l[0]+e);o.record(a),l.html.attr(\"layer-full\")||l.html.css(\"overflow\",\"hidden\").attr(\"layer-full\",e),clearTimeout(t),t=setTimeout(function(){var t=\"fixed\"===a.css(\"position\");r.style(e,{top:t?0:n.scrollTop(),left:t?0:n.scrollLeft(),width:n.width(),height:n.height()},!0),a.find(\".layui-layer-min\").hide()},100)},r.title=function(e,t){var n=i(\"#\"+l[0]+(t||r.index)).find(l[1]);n.html(e)},r.close=function(e){var t=i(\"#\"+l[0]+e),n=t.attr(\"type\"),a=\"layer-anim-close\";if(t[0]){var s=\"layui-layer-wrap\",f=function(){if(n===o.type[1]&&\"object\"===t.attr(\"conType\")){t.children(\":not(.\"+l[5]+\")\").remove();for(var a=t.find(\".\"+s),r=0;r<2;r++)a.unwrap();a.css(\"display\",a.data(\"display\")).removeClass(s)}else{if(n===o.type[2])try{var f=i(\"#\"+l[4]+e)[0];f.contentWindow.document.write(\"\"),f.contentWindow.close(),t.find(\".\"+l[5])[0].removeChild(f)}catch(c){}t[0].innerHTML=\"\",t.remove()}\"function\"==typeof o.end[e]&&o.end[e](),delete o.end[e]};t.data(\"isOutAnim\")&&t.addClass(\"layer-anim \"+a),i(\"#layui-layer-moves, #layui-layer-shade\"+e).remove(),6==r.ie&&o.reselect(),o.rescollbar(e),t.attr(\"minLeft\")&&(o.minIndex--,o.minLeft.push(t.attr(\"minLeft\"))),r.ie&&r.ie<10||!t.data(\"isOutAnim\")?f():setTimeout(function(){f()},200)}},r.closeAll=function(e){i.each(i(\".\"+l[0]),function(){var t=i(this),n=e?t.attr(\"type\")===e:1;n&&r.close(t.attr(\"times\")),n=null})};var f=r.cache||{},c=function(e){return f.skin?\" \"+f.skin+\" \"+f.skin+\"-\"+e:\"\"};r.prompt=function(e,t){var a=\"\";if(e=e||{},\"function\"==typeof e&&(t=e),e.area){var o=e.area;a='style=\"width: '+o[0]+\"; height: \"+o[1]+';\"',delete e.area}var s,l=2==e.formType?'<textarea class=\"layui-layer-input\"'+a+\"></textarea>\":function(){return'<input type=\"'+(1==e.formType?\"password\":\"text\")+'\" class=\"layui-layer-input\">'}(),f=e.success;return delete e.success,r.open(i.extend({type:1,btn:[\"&#x786E;&#x5B9A;\",\"&#x53D6;&#x6D88;\"],content:l,skin:\"layui-layer-prompt\"+c(\"prompt\"),maxWidth:n.width(),success:function(t){s=t.find(\".layui-layer-input\"),s.val(e.value||\"\").focus(),\"function\"==typeof f&&f(t)},resize:!1,yes:function(i){var n=s.val();\"\"===n?s.focus():n.length>(e.maxlength||500)?r.tips(\"&#x6700;&#x591A;&#x8F93;&#x5165;\"+(e.maxlength||500)+\"&#x4E2A;&#x5B57;&#x6570;\",s,{tips:1}):t&&t(n,i,s)}},e))},r.tab=function(e){e=e||{};var t=e.tab||{},n=\"layui-this\",a=e.success;return delete e.success,r.open(i.extend({type:1,skin:\"layui-layer-tab\"+c(\"tab\"),resize:!1,title:function(){var e=t.length,i=1,a=\"\";if(e>0)for(a='<span class=\"'+n+'\">'+t[0].title+\"</span>\";i<e;i++)a+=\"<span>\"+t[i].title+\"</span>\";return a}(),content:'<ul class=\"layui-layer-tabmain\">'+function(){var e=t.length,i=1,a=\"\";if(e>0)for(a='<li class=\"layui-layer-tabli '+n+'\">'+(t[0].content||\"no content\")+\"</li>\";i<e;i++)a+='<li class=\"layui-layer-tabli\">'+(t[i].content||\"no  content\")+\"</li>\";return a}()+\"</ul>\",success:function(t){var o=t.find(\".layui-layer-title\").children(),r=t.find(\".layui-layer-tabmain\").children();o.on(\"mousedown\",function(t){t.stopPropagation?t.stopPropagation():t.cancelBubble=!0;var a=i(this),o=a.index();a.addClass(n).siblings().removeClass(n),r.eq(o).show().siblings().hide(),\"function\"==typeof e.change&&e.change(o)}),\"function\"==typeof a&&a(t)}},e))},r.photos=function(t,n,a){function o(e,t,i){var n=new Image;return n.src=e,n.complete?t(n):(n.onload=function(){n.onload=null,t(n)},void(n.onerror=function(e){n.onerror=null,i(e)}))}var s={};if(t=t||{},t.photos){var l=t.photos.constructor===Object,f=l?t.photos:{},u=f.data||[],d=f.start||0;s.imgIndex=(0|d)+1,t.img=t.img||\"img\";var y=t.success;if(delete t.success,l){if(0===u.length)return r.msg(\"&#x6CA1;&#x6709;&#x56FE;&#x7247;\")}else{var p=i(t.photos),h=function(){u=[],p.find(t.img).each(function(e){var t=i(this);t.attr(\"layer-index\",e),u.push({alt:t.attr(\"alt\"),pid:t.attr(\"layer-pid\"),src:t.attr(\"layer-src\")||t.attr(\"src\"),thumb:t.attr(\"src\")})})};if(h(),0===u.length)return;if(n||p.on(\"click\",t.img,function(){var e=i(this),n=e.attr(\"layer-index\");r.photos(i.extend(t,{photos:{start:n,data:u,tab:t.tab},full:t.full}),!0),h()}),!n)return}s.imgprev=function(e){s.imgIndex--,s.imgIndex<1&&(s.imgIndex=u.length),s.tabimg(e)},s.imgnext=function(e,t){s.imgIndex++,s.imgIndex>u.length&&(s.imgIndex=1,t)||s.tabimg(e)},s.keyup=function(e){if(!s.end){var t=e.keyCode;e.preventDefault(),37===t?s.imgprev(!0):39===t?s.imgnext(!0):27===t&&r.close(s.index)}},s.tabimg=function(e){if(!(u.length<=1))return f.start=s.imgIndex-1,r.close(s.index),r.photos(t,!0,e)},s.event=function(){s.bigimg.hover(function(){s.imgsee.show()},function(){s.imgsee.hide()}),s.bigimg.find(\".layui-layer-imgprev\").on(\"click\",function(e){e.preventDefault(),s.imgprev()}),s.bigimg.find(\".layui-layer-imgnext\").on(\"click\",function(e){e.preventDefault(),s.imgnext()}),i(document).on(\"keyup\",s.keyup)},s.loadi=r.load(1,{shade:!(\"shade\"in t)&&.9,scrollbar:!1}),o(u[d].src,function(n){r.close(s.loadi),s.index=r.open(i.extend({type:1,id:\"layui-layer-photos\",area:function(){var a=[n.width,n.height],o=[i(e).width()-100,i(e).height()-100];if(!t.full&&(a[0]>o[0]||a[1]>o[1])){var r=[a[0]/o[0],a[1]/o[1]];r[0]>r[1]?(a[0]=a[0]/r[0],a[1]=a[1]/r[0]):r[0]<r[1]&&(a[0]=a[0]/r[1],a[1]=a[1]/r[1])}return[a[0]+\"px\",a[1]+\"px\"]}(),title:!1,shade:.9,shadeClose:!0,closeBtn:!1,move:\".layui-layer-phimg img\",moveType:1,scrollbar:!1,moveOut:!0,isOutAnim:!1,skin:\"layui-layer-photos\"+c(\"photos\"),content:'<div class=\"layui-layer-phimg\"><img src=\"'+u[d].src+'\" alt=\"'+(u[d].alt||\"\")+'\" layer-pid=\"'+u[d].pid+'\"><div class=\"layui-layer-imgsee\">'+(u.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:'+(a?\"block\":\"\")+'\"><span class=\"layui-layer-imgtit\"><a href=\"javascript:;\">'+(u[d].alt||\"\")+\"</a><em>\"+s.imgIndex+\"/\"+u.length+\"</em></span></div></div></div>\",success:function(e,i){s.bigimg=e.find(\".layui-layer-phimg\"),s.imgsee=e.find(\".layui-layer-imguide,.layui-layer-imgbar\"),s.event(e),t.tab&&t.tab(u[d],e),\"function\"==typeof y&&y(e)},end:function(){s.end=!0,i(document).off(\"keyup\",s.keyup)}},t))},function(){r.close(s.loadi),r.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(){u.length>1&&s.imgnext(!0,!0)}})})}},o.run=function(t){i=t,n=i(e),l.html=i(\"html\"),r.open=function(e){var t=new s(e);return t.index}},e.layui&&layui.define?(r.ready(),layui.define(\"jquery\",function(t){r.path=layui.cache.dir,o.run(layui.$),e.layer=r,t(\"layer\",r)})):\"function\"==typeof define&&define.amd?define([\"jquery\"],function(){return o.run(e.jQuery),r}):function(){o.run(e.jQuery),r.ready()}()}(window);"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/layui/lay/modules/laypage.js",
    "content": "/** layui-v2.2.5 MIT License By https://www.layui.com */\n ;layui.define(function(e){\"use strict\";var a=document,t=\"getElementById\",n=\"getElementsByTagName\",i=\"laypage\",r=\"layui-disabled\",u=function(e){var a=this;a.config=e||{},a.config.index=++s.index,a.render(!0)};u.prototype.type=function(){var e=this.config;if(\"object\"==typeof e.elem)return void 0===e.elem.length?2:3},u.prototype.view=function(){var e=this,a=e.config,t=a.groups=\"groups\"in a?0|a.groups:5;a.layout=\"object\"==typeof a.layout?a.layout:[\"prev\",\"page\",\"next\"],a.count=0|a.count,a.curr=0|a.curr||1,a.limits=\"object\"==typeof a.limits?a.limits:[10,20,30,40,50],a.limit=0|a.limit||10,a.pages=Math.ceil(a.count/a.limit)||1,a.curr>a.pages&&(a.curr=a.pages),t<0?t=1:t>a.pages&&(t=a.pages),a.prev=\"prev\"in a?a.prev:\"&#x4E0A;&#x4E00;&#x9875;\",a.next=\"next\"in a?a.next:\"&#x4E0B;&#x4E00;&#x9875;\";var n=a.pages>t?Math.ceil((a.curr+(t>1?1:0))/(t>0?t:1)):1,i={prev:function(){return a.prev?'<a href=\"javascript:;\" class=\"layui-laypage-prev'+(1==a.curr?\" \"+r:\"\")+'\" data-page=\"'+(a.curr-1)+'\">'+a.prev+\"</a>\":\"\"}(),page:function(){var e=[];if(a.count<1)return\"\";n>1&&a.first!==!1&&0!==t&&e.push('<a href=\"javascript:;\" class=\"layui-laypage-first\" data-page=\"1\"  title=\"&#x9996;&#x9875;\">'+(a.first||1)+\"</a>\");var i=Math.floor((t-1)/2),r=n>1?a.curr-i:1,u=n>1?function(){var e=a.curr+(t-i-1);return e>a.pages?a.pages:e}():t;for(u-r<t-1&&(r=u-t+1),a.first!==!1&&r>2&&e.push('<span class=\"layui-laypage-spr\">&#x2026;</span>');r<=u;r++)r===a.curr?e.push('<span class=\"layui-laypage-curr\"><em class=\"layui-laypage-em\" '+(/^#/.test(a.theme)?'style=\"background-color:'+a.theme+';\"':\"\")+\"></em><em>\"+r+\"</em></span>\"):e.push('<a href=\"javascript:;\" data-page=\"'+r+'\">'+r+\"</a>\");return a.pages>t&&a.pages>u&&a.last!==!1&&(u+1<a.pages&&e.push('<span class=\"layui-laypage-spr\">&#x2026;</span>'),0!==t&&e.push('<a href=\"javascript:;\" class=\"layui-laypage-last\" title=\"&#x5C3E;&#x9875;\"  data-page=\"'+a.pages+'\">'+(a.last||a.pages)+\"</a>\")),e.join(\"\")}(),next:function(){return a.next?'<a href=\"javascript:;\" class=\"layui-laypage-next'+(a.curr==a.pages?\" \"+r:\"\")+'\" data-page=\"'+(a.curr+1)+'\">'+a.next+\"</a>\":\"\"}(),count:'<span class=\"layui-laypage-count\">共 '+a.count+\" 条</span>\",limit:function(){var e=['<span class=\"layui-laypage-limits\"><select lay-ignore>'];return layui.each(a.limits,function(t,n){e.push('<option value=\"'+n+'\"'+(n===a.limit?\"selected\":\"\")+\">\"+n+\" 条/页</option>\")}),e.join(\"\")+\"</select></span>\"}(),skip:function(){return['<span class=\"layui-laypage-skip\">&#x5230;&#x7B2C;','<input type=\"text\" min=\"1\" value=\"'+a.curr+'\" class=\"layui-input\">','&#x9875;<button type=\"button\" class=\"layui-laypage-btn\">&#x786e;&#x5b9a;</button>',\"</span>\"].join(\"\")}()};return['<div class=\"layui-box layui-laypage layui-laypage-'+(a.theme?/^#/.test(a.theme)?\"molv\":a.theme:\"default\")+'\" id=\"layui-laypage-'+a.index+'\">',function(){var e=[];return layui.each(a.layout,function(a,t){i[t]&&e.push(i[t])}),e.join(\"\")}(),\"</div>\"].join(\"\")},u.prototype.jump=function(e,a){if(e){var t=this,i=t.config,r=e.children,u=e[n](\"button\")[0],l=e[n](\"input\")[0],p=e[n](\"select\")[0],c=function(){var e=0|l.value.replace(/\\s|\\D/g,\"\");e&&(i.curr=e,t.render())};if(a)return c();for(var o=0,y=r.length;o<y;o++)\"a\"===r[o].nodeName.toLowerCase()&&s.on(r[o],\"click\",function(){var e=0|this.getAttribute(\"data-page\");e<1||e>i.pages||(i.curr=e,t.render())});p&&s.on(p,\"change\",function(){var e=this.value;i.curr*e>i.count&&(i.curr=Math.ceil(i.count/e)),i.limit=e,t.render()}),u&&s.on(u,\"click\",function(){c()})}},u.prototype.skip=function(e){if(e){var a=this,t=e[n](\"input\")[0];t&&s.on(t,\"keyup\",function(t){var n=this.value,i=t.keyCode;/^(37|38|39|40)$/.test(i)||(/\\D/.test(n)&&(this.value=n.replace(/\\D/,\"\")),13===i&&a.jump(e,!0))})}},u.prototype.render=function(e){var n=this,i=n.config,r=n.type(),u=n.view();2===r?i.elem&&(i.elem.innerHTML=u):3===r?i.elem.html(u):a[t](i.elem)&&(a[t](i.elem).innerHTML=u),i.jump&&i.jump(i,e);var s=a[t](\"layui-laypage-\"+i.index);n.jump(s),i.hash&&!e&&(location.hash=\"!\"+i.hash+\"=\"+i.curr),n.skip(s)};var s={render:function(e){var a=new u(e);return a.index},index:layui.laypage?layui.laypage.index+1e4:0,on:function(e,a,t){return e.attachEvent?e.attachEvent(\"on\"+a,function(a){a.target=a.srcElement,t.call(e,a)}):e.addEventListener(a,t,!1),this}};e(i,s)});"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/layui/lay/modules/laytpl.js",
    "content": "/** layui-v2.2.5 MIT License By https://www.layui.com */\n ;layui.define(function(e){\"use strict\";var r={open:\"{{\",close:\"}}\"},c={exp:function(e){return new RegExp(e,\"g\")},query:function(e,c,t){var o=[\"#([\\\\s\\\\S])+?\",\"([^{#}])*?\"][e||0];return n((c||\"\")+r.open+o+r.close+(t||\"\"))},escape:function(e){return String(e||\"\").replace(/&(?!#?[a-zA-Z0-9]+;)/g,\"&amp;\").replace(/</g,\"&lt;\").replace(/>/g,\"&gt;\").replace(/'/g,\"&#39;\").replace(/\"/g,\"&quot;\")},error:function(e,r){var c=\"Laytpl Error：\";return\"object\"==typeof console&&console.error(c+e+\"\\n\"+(r||\"\")),c+e}},n=c.exp,t=function(e){this.tpl=e};t.pt=t.prototype,window.errors=0,t.pt.parse=function(e,t){var o=this,p=e,a=n(\"^\"+r.open+\"#\",\"\"),l=n(r.close+\"$\",\"\");e=e.replace(/\\s+|\\r|\\t|\\n/g,\" \").replace(n(r.open+\"#\"),r.open+\"# \").replace(n(r.close+\"}\"),\"} \"+r.close).replace(/\\\\/g,\"\\\\\\\\\").replace(n(r.open+\"!(.+?)!\"+r.close),function(e){return e=e.replace(n(\"^\"+r.open+\"!\"),\"\").replace(n(\"!\"+r.close),\"\").replace(n(r.open+\"|\"+r.close),function(e){return e.replace(/(.)/g,\"\\\\$1\")})}).replace(/(?=\"|')/g,\"\\\\\").replace(c.query(),function(e){return e=e.replace(a,\"\").replace(l,\"\"),'\";'+e.replace(/\\\\/g,\"\")+';view+=\"'}).replace(c.query(1),function(e){var c='\"+(';return e.replace(/\\s/g,\"\")===r.open+r.close?\"\":(e=e.replace(n(r.open+\"|\"+r.close),\"\"),/^=/.test(e)&&(e=e.replace(/^=/,\"\"),c='\"+_escape_('),c+e.replace(/\\\\/g,\"\")+')+\"')}),e='\"use strict\";var view = \"'+e+'\";return view;';try{return o.cache=e=new Function(\"d, _escape_\",e),e(t,c.escape)}catch(u){return delete o.cache,c.error(u,p)}},t.pt.render=function(e,r){var n,t=this;return e?(n=t.cache?t.cache(e,c.escape):t.parse(t.tpl,e),r?void r(n):n):c.error(\"no data\")};var o=function(e){return\"string\"!=typeof e?c.error(\"Template not found\"):new t(e)};o.config=function(e){e=e||{};for(var c in e)r[c]=e[c]},o.v=\"1.2.0\",e(\"laytpl\",o)});"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/layui/lay/modules/mobile.js",
    "content": "/** layui-v2.2.5 MIT License By https://www.layui.com */\n ;layui.define(function(i){i(\"layui.mobile\",layui.v)});layui.define(function(e){\"use strict\";var r={open:\"{{\",close:\"}}\"},c={exp:function(e){return new RegExp(e,\"g\")},query:function(e,c,t){var o=[\"#([\\\\s\\\\S])+?\",\"([^{#}])*?\"][e||0];return n((c||\"\")+r.open+o+r.close+(t||\"\"))},escape:function(e){return String(e||\"\").replace(/&(?!#?[a-zA-Z0-9]+;)/g,\"&amp;\").replace(/</g,\"&lt;\").replace(/>/g,\"&gt;\").replace(/'/g,\"&#39;\").replace(/\"/g,\"&quot;\")},error:function(e,r){var c=\"Laytpl Error：\";return\"object\"==typeof console&&console.error(c+e+\"\\n\"+(r||\"\")),c+e}},n=c.exp,t=function(e){this.tpl=e};t.pt=t.prototype,window.errors=0,t.pt.parse=function(e,t){var o=this,p=e,a=n(\"^\"+r.open+\"#\",\"\"),l=n(r.close+\"$\",\"\");e=e.replace(/\\s+|\\r|\\t|\\n/g,\" \").replace(n(r.open+\"#\"),r.open+\"# \").replace(n(r.close+\"}\"),\"} \"+r.close).replace(/\\\\/g,\"\\\\\\\\\").replace(n(r.open+\"!(.+?)!\"+r.close),function(e){return e=e.replace(n(\"^\"+r.open+\"!\"),\"\").replace(n(\"!\"+r.close),\"\").replace(n(r.open+\"|\"+r.close),function(e){return e.replace(/(.)/g,\"\\\\$1\")})}).replace(/(?=\"|')/g,\"\\\\\").replace(c.query(),function(e){return e=e.replace(a,\"\").replace(l,\"\"),'\";'+e.replace(/\\\\/g,\"\")+';view+=\"'}).replace(c.query(1),function(e){var c='\"+(';return e.replace(/\\s/g,\"\")===r.open+r.close?\"\":(e=e.replace(n(r.open+\"|\"+r.close),\"\"),/^=/.test(e)&&(e=e.replace(/^=/,\"\"),c='\"+_escape_('),c+e.replace(/\\\\/g,\"\")+')+\"')}),e='\"use strict\";var view = \"'+e+'\";return view;';try{return o.cache=e=new Function(\"d, _escape_\",e),e(t,c.escape)}catch(u){return delete o.cache,c.error(u,p)}},t.pt.render=function(e,r){var n,t=this;return e?(n=t.cache?t.cache(e,c.escape):t.parse(t.tpl,e),r?void r(n):n):c.error(\"no data\")};var o=function(e){return\"string\"!=typeof e?c.error(\"Template not found\"):new t(e)};o.config=function(e){e=e||{};for(var c in e)r[c]=e[c]},o.v=\"1.2.0\",e(\"laytpl\",o)});layui.define(function(e){\"use strict\";var t=(window,document),i=\"querySelectorAll\",n=\"getElementsByClassName\",a=function(e){return t[i](e)},s={type:0,shade:!0,shadeClose:!0,fixed:!0,anim:\"scale\"},l={extend:function(e){var t=JSON.parse(JSON.stringify(s));for(var i in e)t[i]=e[i];return t},timer:{},end:{}};l.touch=function(e,t){e.addEventListener(\"click\",function(e){t.call(this,e)},!1)};var o=0,r=[\"layui-m-layer\"],d=function(e){var t=this;t.config=l.extend(e),t.view()};d.prototype.view=function(){var e=this,i=e.config,s=t.createElement(\"div\");e.id=s.id=r[0]+o,s.setAttribute(\"class\",r[0]+\" \"+r[0]+(i.type||0)),s.setAttribute(\"index\",o);var l=function(){var e=\"object\"==typeof i.title;return i.title?'<h3 style=\"'+(e?i.title[1]:\"\")+'\">'+(e?i.title[0]:i.title)+\"</h3>\":\"\"}(),d=function(){\"string\"==typeof i.btn&&(i.btn=[i.btn]);var e,t=(i.btn||[]).length;return 0!==t&&i.btn?(e='<span yes type=\"1\">'+i.btn[0]+\"</span>\",2===t&&(e='<span no type=\"0\">'+i.btn[1]+\"</span>\"+e),'<div class=\"layui-m-layerbtn\">'+e+\"</div>\"):\"\"}();if(i.fixed||(i.top=i.hasOwnProperty(\"top\")?i.top:100,i.style=i.style||\"\",i.style+=\" top:\"+(t.body.scrollTop+i.top)+\"px\"),2===i.type&&(i.content='<i></i><i class=\"layui-m-layerload\"></i><i></i><p>'+(i.content||\"\")+\"</p>\"),i.skin&&(i.anim=\"up\"),\"msg\"===i.skin&&(i.shade=!1),s.innerHTML=(i.shade?\"<div \"+(\"string\"==typeof i.shade?'style=\"'+i.shade+'\"':\"\")+' class=\"layui-m-layershade\"></div>':\"\")+'<div class=\"layui-m-layermain\" '+(i.fixed?\"\":'style=\"position:static;\"')+'><div class=\"layui-m-layersection\"><div class=\"layui-m-layerchild '+(i.skin?\"layui-m-layer-\"+i.skin+\" \":\"\")+(i.className?i.className:\"\")+\" \"+(i.anim?\"layui-m-anim-\"+i.anim:\"\")+'\" '+(i.style?'style=\"'+i.style+'\"':\"\")+\">\"+l+'<div class=\"layui-m-layercont\">'+i.content+\"</div>\"+d+\"</div></div></div>\",!i.type||2===i.type){var y=t[n](r[0]+i.type),u=y.length;u>=1&&c.close(y[0].getAttribute(\"index\"))}document.body.appendChild(s);var m=e.elem=a(\"#\"+e.id)[0];i.success&&i.success(m),e.index=o++,e.action(i,m)},d.prototype.action=function(e,t){var i=this;e.time&&(l.timer[i.index]=setTimeout(function(){c.close(i.index)},1e3*e.time));var a=function(){var t=this.getAttribute(\"type\");0==t?(e.no&&e.no(),c.close(i.index)):e.yes?e.yes(i.index):c.close(i.index)};if(e.btn)for(var s=t[n](\"layui-m-layerbtn\")[0].children,o=s.length,r=0;r<o;r++)l.touch(s[r],a);if(e.shade&&e.shadeClose){var d=t[n](\"layui-m-layershade\")[0];l.touch(d,function(){c.close(i.index,e.end)})}e.end&&(l.end[i.index]=e.end)};var c={v:\"2.0 m\",index:o,open:function(e){var t=new d(e||{});return t.index},close:function(e){var i=a(\"#\"+r[0]+e)[0];i&&(i.innerHTML=\"\",t.body.removeChild(i),clearTimeout(l.timer[e]),delete l.timer[e],\"function\"==typeof l.end[e]&&l.end[e](),delete l.end[e])},closeAll:function(){for(var e=t[n](r[0]),i=0,a=e.length;i<a;i++)c.close(0|e[0].getAttribute(\"index\"))}};e(\"layer-mobile\",c)});layui.define(function(t){var e=function(){function t(t){return null==t?String(t):J[W.call(t)]||\"object\"}function e(e){return\"function\"==t(e)}function n(t){return null!=t&&t==t.window}function r(t){return null!=t&&t.nodeType==t.DOCUMENT_NODE}function i(e){return\"object\"==t(e)}function o(t){return i(t)&&!n(t)&&Object.getPrototypeOf(t)==Object.prototype}function a(t){var e=!!t&&\"length\"in t&&t.length,r=T.type(t);return\"function\"!=r&&!n(t)&&(\"array\"==r||0===e||\"number\"==typeof e&&e>0&&e-1 in t)}function s(t){return A.call(t,function(t){return null!=t})}function u(t){return t.length>0?T.fn.concat.apply([],t):t}function c(t){return t.replace(/::/g,\"/\").replace(/([A-Z]+)([A-Z][a-z])/g,\"$1_$2\").replace(/([a-z\\d])([A-Z])/g,\"$1_$2\").replace(/_/g,\"-\").toLowerCase()}function l(t){return t in F?F[t]:F[t]=new RegExp(\"(^|\\\\s)\"+t+\"(\\\\s|$)\")}function f(t,e){return\"number\"!=typeof e||k[c(t)]?e:e+\"px\"}function h(t){var e,n;return $[t]||(e=L.createElement(t),L.body.appendChild(e),n=getComputedStyle(e,\"\").getPropertyValue(\"display\"),e.parentNode.removeChild(e),\"none\"==n&&(n=\"block\"),$[t]=n),$[t]}function p(t){return\"children\"in t?D.call(t.children):T.map(t.childNodes,function(t){if(1==t.nodeType)return t})}function d(t,e){var n,r=t?t.length:0;for(n=0;n<r;n++)this[n]=t[n];this.length=r,this.selector=e||\"\"}function m(t,e,n){for(j in e)n&&(o(e[j])||Q(e[j]))?(o(e[j])&&!o(t[j])&&(t[j]={}),Q(e[j])&&!Q(t[j])&&(t[j]=[]),m(t[j],e[j],n)):e[j]!==E&&(t[j]=e[j])}function v(t,e){return null==e?T(t):T(t).filter(e)}function g(t,n,r,i){return e(n)?n.call(t,r,i):n}function y(t,e,n){null==n?t.removeAttribute(e):t.setAttribute(e,n)}function x(t,e){var n=t.className||\"\",r=n&&n.baseVal!==E;return e===E?r?n.baseVal:n:void(r?n.baseVal=e:t.className=e)}function b(t){try{return t?\"true\"==t||\"false\"!=t&&(\"null\"==t?null:+t+\"\"==t?+t:/^[\\[\\{]/.test(t)?T.parseJSON(t):t):t}catch(e){return t}}function w(t,e){e(t);for(var n=0,r=t.childNodes.length;n<r;n++)w(t.childNodes[n],e)}var E,j,T,S,C,N,O=[],P=O.concat,A=O.filter,D=O.slice,L=window.document,$={},F={},k={\"column-count\":1,columns:1,\"font-weight\":1,\"line-height\":1,opacity:1,\"z-index\":1,zoom:1},M=/^\\s*<(\\w+|!)[^>]*>/,R=/^<(\\w+)\\s*\\/?>(?:<\\/\\1>|)$/,z=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/gi,Z=/^(?:body|html)$/i,q=/([A-Z])/g,H=[\"val\",\"css\",\"html\",\"text\",\"data\",\"width\",\"height\",\"offset\"],I=[\"after\",\"prepend\",\"before\",\"append\"],V=L.createElement(\"table\"),_=L.createElement(\"tr\"),B={tr:L.createElement(\"tbody\"),tbody:V,thead:V,tfoot:V,td:_,th:_,\"*\":L.createElement(\"div\")},U=/complete|loaded|interactive/,X=/^[\\w-]*$/,J={},W=J.toString,Y={},G=L.createElement(\"div\"),K={tabindex:\"tabIndex\",readonly:\"readOnly\",\"for\":\"htmlFor\",\"class\":\"className\",maxlength:\"maxLength\",cellspacing:\"cellSpacing\",cellpadding:\"cellPadding\",rowspan:\"rowSpan\",colspan:\"colSpan\",usemap:\"useMap\",frameborder:\"frameBorder\",contenteditable:\"contentEditable\"},Q=Array.isArray||function(t){return t instanceof Array};return Y.matches=function(t,e){if(!e||!t||1!==t.nodeType)return!1;var n=t.matches||t.webkitMatchesSelector||t.mozMatchesSelector||t.oMatchesSelector||t.matchesSelector;if(n)return n.call(t,e);var r,i=t.parentNode,o=!i;return o&&(i=G).appendChild(t),r=~Y.qsa(i,e).indexOf(t),o&&G.removeChild(t),r},C=function(t){return t.replace(/-+(.)?/g,function(t,e){return e?e.toUpperCase():\"\"})},N=function(t){return A.call(t,function(e,n){return t.indexOf(e)==n})},Y.fragment=function(t,e,n){var r,i,a;return R.test(t)&&(r=T(L.createElement(RegExp.$1))),r||(t.replace&&(t=t.replace(z,\"<$1></$2>\")),e===E&&(e=M.test(t)&&RegExp.$1),e in B||(e=\"*\"),a=B[e],a.innerHTML=\"\"+t,r=T.each(D.call(a.childNodes),function(){a.removeChild(this)})),o(n)&&(i=T(r),T.each(n,function(t,e){H.indexOf(t)>-1?i[t](e):i.attr(t,e)})),r},Y.Z=function(t,e){return new d(t,e)},Y.isZ=function(t){return t instanceof Y.Z},Y.init=function(t,n){var r;if(!t)return Y.Z();if(\"string\"==typeof t)if(t=t.trim(),\"<\"==t[0]&&M.test(t))r=Y.fragment(t,RegExp.$1,n),t=null;else{if(n!==E)return T(n).find(t);r=Y.qsa(L,t)}else{if(e(t))return T(L).ready(t);if(Y.isZ(t))return t;if(Q(t))r=s(t);else if(i(t))r=[t],t=null;else if(M.test(t))r=Y.fragment(t.trim(),RegExp.$1,n),t=null;else{if(n!==E)return T(n).find(t);r=Y.qsa(L,t)}}return Y.Z(r,t)},T=function(t,e){return Y.init(t,e)},T.extend=function(t){var e,n=D.call(arguments,1);return\"boolean\"==typeof t&&(e=t,t=n.shift()),n.forEach(function(n){m(t,n,e)}),t},Y.qsa=function(t,e){var n,r=\"#\"==e[0],i=!r&&\".\"==e[0],o=r||i?e.slice(1):e,a=X.test(o);return t.getElementById&&a&&r?(n=t.getElementById(o))?[n]:[]:1!==t.nodeType&&9!==t.nodeType&&11!==t.nodeType?[]:D.call(a&&!r&&t.getElementsByClassName?i?t.getElementsByClassName(o):t.getElementsByTagName(e):t.querySelectorAll(e))},T.contains=L.documentElement.contains?function(t,e){return t!==e&&t.contains(e)}:function(t,e){for(;e&&(e=e.parentNode);)if(e===t)return!0;return!1},T.type=t,T.isFunction=e,T.isWindow=n,T.isArray=Q,T.isPlainObject=o,T.isEmptyObject=function(t){var e;for(e in t)return!1;return!0},T.isNumeric=function(t){var e=Number(t),n=typeof t;return null!=t&&\"boolean\"!=n&&(\"string\"!=n||t.length)&&!isNaN(e)&&isFinite(e)||!1},T.inArray=function(t,e,n){return O.indexOf.call(e,t,n)},T.camelCase=C,T.trim=function(t){return null==t?\"\":String.prototype.trim.call(t)},T.uuid=0,T.support={},T.expr={},T.noop=function(){},T.map=function(t,e){var n,r,i,o=[];if(a(t))for(r=0;r<t.length;r++)n=e(t[r],r),null!=n&&o.push(n);else for(i in t)n=e(t[i],i),null!=n&&o.push(n);return u(o)},T.each=function(t,e){var n,r;if(a(t)){for(n=0;n<t.length;n++)if(e.call(t[n],n,t[n])===!1)return t}else for(r in t)if(e.call(t[r],r,t[r])===!1)return t;return t},T.grep=function(t,e){return A.call(t,e)},window.JSON&&(T.parseJSON=JSON.parse),T.each(\"Boolean Number String Function Array Date RegExp Object Error\".split(\" \"),function(t,e){J[\"[object \"+e+\"]\"]=e.toLowerCase()}),T.fn={constructor:Y.Z,length:0,forEach:O.forEach,reduce:O.reduce,push:O.push,sort:O.sort,splice:O.splice,indexOf:O.indexOf,concat:function(){var t,e,n=[];for(t=0;t<arguments.length;t++)e=arguments[t],n[t]=Y.isZ(e)?e.toArray():e;return P.apply(Y.isZ(this)?this.toArray():this,n)},map:function(t){return T(T.map(this,function(e,n){return t.call(e,n,e)}))},slice:function(){return T(D.apply(this,arguments))},ready:function(t){return U.test(L.readyState)&&L.body?t(T):L.addEventListener(\"DOMContentLoaded\",function(){t(T)},!1),this},get:function(t){return t===E?D.call(this):this[t>=0?t:t+this.length]},toArray:function(){return this.get()},size:function(){return this.length},remove:function(){return this.each(function(){null!=this.parentNode&&this.parentNode.removeChild(this)})},each:function(t){return O.every.call(this,function(e,n){return t.call(e,n,e)!==!1}),this},filter:function(t){return e(t)?this.not(this.not(t)):T(A.call(this,function(e){return Y.matches(e,t)}))},add:function(t,e){return T(N(this.concat(T(t,e))))},is:function(t){return this.length>0&&Y.matches(this[0],t)},not:function(t){var n=[];if(e(t)&&t.call!==E)this.each(function(e){t.call(this,e)||n.push(this)});else{var r=\"string\"==typeof t?this.filter(t):a(t)&&e(t.item)?D.call(t):T(t);this.forEach(function(t){r.indexOf(t)<0&&n.push(t)})}return T(n)},has:function(t){return this.filter(function(){return i(t)?T.contains(this,t):T(this).find(t).size()})},eq:function(t){return t===-1?this.slice(t):this.slice(t,+t+1)},first:function(){var t=this[0];return t&&!i(t)?t:T(t)},last:function(){var t=this[this.length-1];return t&&!i(t)?t:T(t)},find:function(t){var e,n=this;return e=t?\"object\"==typeof t?T(t).filter(function(){var t=this;return O.some.call(n,function(e){return T.contains(e,t)})}):1==this.length?T(Y.qsa(this[0],t)):this.map(function(){return Y.qsa(this,t)}):T()},closest:function(t,e){var n=[],i=\"object\"==typeof t&&T(t);return this.each(function(o,a){for(;a&&!(i?i.indexOf(a)>=0:Y.matches(a,t));)a=a!==e&&!r(a)&&a.parentNode;a&&n.indexOf(a)<0&&n.push(a)}),T(n)},parents:function(t){for(var e=[],n=this;n.length>0;)n=T.map(n,function(t){if((t=t.parentNode)&&!r(t)&&e.indexOf(t)<0)return e.push(t),t});return v(e,t)},parent:function(t){return v(N(this.pluck(\"parentNode\")),t)},children:function(t){return v(this.map(function(){return p(this)}),t)},contents:function(){return this.map(function(){return this.contentDocument||D.call(this.childNodes)})},siblings:function(t){return v(this.map(function(t,e){return A.call(p(e.parentNode),function(t){return t!==e})}),t)},empty:function(){return this.each(function(){this.innerHTML=\"\"})},pluck:function(t){return T.map(this,function(e){return e[t]})},show:function(){return this.each(function(){\"none\"==this.style.display&&(this.style.display=\"\"),\"none\"==getComputedStyle(this,\"\").getPropertyValue(\"display\")&&(this.style.display=h(this.nodeName))})},replaceWith:function(t){return this.before(t).remove()},wrap:function(t){var n=e(t);if(this[0]&&!n)var r=T(t).get(0),i=r.parentNode||this.length>1;return this.each(function(e){T(this).wrapAll(n?t.call(this,e):i?r.cloneNode(!0):r)})},wrapAll:function(t){if(this[0]){T(this[0]).before(t=T(t));for(var e;(e=t.children()).length;)t=e.first();T(t).append(this)}return this},wrapInner:function(t){var n=e(t);return this.each(function(e){var r=T(this),i=r.contents(),o=n?t.call(this,e):t;i.length?i.wrapAll(o):r.append(o)})},unwrap:function(){return this.parent().each(function(){T(this).replaceWith(T(this).children())}),this},clone:function(){return this.map(function(){return this.cloneNode(!0)})},hide:function(){return this.css(\"display\",\"none\")},toggle:function(t){return this.each(function(){var e=T(this);(t===E?\"none\"==e.css(\"display\"):t)?e.show():e.hide()})},prev:function(t){return T(this.pluck(\"previousElementSibling\")).filter(t||\"*\")},next:function(t){return T(this.pluck(\"nextElementSibling\")).filter(t||\"*\")},html:function(t){return 0 in arguments?this.each(function(e){var n=this.innerHTML;T(this).empty().append(g(this,t,e,n))}):0 in this?this[0].innerHTML:null},text:function(t){return 0 in arguments?this.each(function(e){var n=g(this,t,e,this.textContent);this.textContent=null==n?\"\":\"\"+n}):0 in this?this.pluck(\"textContent\").join(\"\"):null},attr:function(t,e){var n;return\"string\"!=typeof t||1 in arguments?this.each(function(n){if(1===this.nodeType)if(i(t))for(j in t)y(this,j,t[j]);else y(this,t,g(this,e,n,this.getAttribute(t)))}):0 in this&&1==this[0].nodeType&&null!=(n=this[0].getAttribute(t))?n:E},removeAttr:function(t){return this.each(function(){1===this.nodeType&&t.split(\" \").forEach(function(t){y(this,t)},this)})},prop:function(t,e){return t=K[t]||t,1 in arguments?this.each(function(n){this[t]=g(this,e,n,this[t])}):this[0]&&this[0][t]},removeProp:function(t){return t=K[t]||t,this.each(function(){delete this[t]})},data:function(t,e){var n=\"data-\"+t.replace(q,\"-$1\").toLowerCase(),r=1 in arguments?this.attr(n,e):this.attr(n);return null!==r?b(r):E},val:function(t){return 0 in arguments?(null==t&&(t=\"\"),this.each(function(e){this.value=g(this,t,e,this.value)})):this[0]&&(this[0].multiple?T(this[0]).find(\"option\").filter(function(){return this.selected}).pluck(\"value\"):this[0].value)},offset:function(t){if(t)return this.each(function(e){var n=T(this),r=g(this,t,e,n.offset()),i=n.offsetParent().offset(),o={top:r.top-i.top,left:r.left-i.left};\"static\"==n.css(\"position\")&&(o.position=\"relative\"),n.css(o)});if(!this.length)return null;if(L.documentElement!==this[0]&&!T.contains(L.documentElement,this[0]))return{top:0,left:0};var e=this[0].getBoundingClientRect();return{left:e.left+window.pageXOffset,top:e.top+window.pageYOffset,width:Math.round(e.width),height:Math.round(e.height)}},css:function(e,n){if(arguments.length<2){var r=this[0];if(\"string\"==typeof e){if(!r)return;return r.style[C(e)]||getComputedStyle(r,\"\").getPropertyValue(e)}if(Q(e)){if(!r)return;var i={},o=getComputedStyle(r,\"\");return T.each(e,function(t,e){i[e]=r.style[C(e)]||o.getPropertyValue(e)}),i}}var a=\"\";if(\"string\"==t(e))n||0===n?a=c(e)+\":\"+f(e,n):this.each(function(){this.style.removeProperty(c(e))});else for(j in e)e[j]||0===e[j]?a+=c(j)+\":\"+f(j,e[j])+\";\":this.each(function(){this.style.removeProperty(c(j))});return this.each(function(){this.style.cssText+=\";\"+a})},index:function(t){return t?this.indexOf(T(t)[0]):this.parent().children().indexOf(this[0])},hasClass:function(t){return!!t&&O.some.call(this,function(t){return this.test(x(t))},l(t))},addClass:function(t){return t?this.each(function(e){if(\"className\"in this){S=[];var n=x(this),r=g(this,t,e,n);r.split(/\\s+/g).forEach(function(t){T(this).hasClass(t)||S.push(t)},this),S.length&&x(this,n+(n?\" \":\"\")+S.join(\" \"))}}):this},removeClass:function(t){return this.each(function(e){if(\"className\"in this){if(t===E)return x(this,\"\");S=x(this),g(this,t,e,S).split(/\\s+/g).forEach(function(t){S=S.replace(l(t),\" \")}),x(this,S.trim())}})},toggleClass:function(t,e){return t?this.each(function(n){var r=T(this),i=g(this,t,n,x(this));i.split(/\\s+/g).forEach(function(t){(e===E?!r.hasClass(t):e)?r.addClass(t):r.removeClass(t)})}):this},scrollTop:function(t){if(this.length){var e=\"scrollTop\"in this[0];return t===E?e?this[0].scrollTop:this[0].pageYOffset:this.each(e?function(){this.scrollTop=t}:function(){this.scrollTo(this.scrollX,t)})}},scrollLeft:function(t){if(this.length){var e=\"scrollLeft\"in this[0];return t===E?e?this[0].scrollLeft:this[0].pageXOffset:this.each(e?function(){this.scrollLeft=t}:function(){this.scrollTo(t,this.scrollY)})}},position:function(){if(this.length){var t=this[0],e=this.offsetParent(),n=this.offset(),r=Z.test(e[0].nodeName)?{top:0,left:0}:e.offset();return n.top-=parseFloat(T(t).css(\"margin-top\"))||0,n.left-=parseFloat(T(t).css(\"margin-left\"))||0,r.top+=parseFloat(T(e[0]).css(\"border-top-width\"))||0,r.left+=parseFloat(T(e[0]).css(\"border-left-width\"))||0,{top:n.top-r.top,left:n.left-r.left}}},offsetParent:function(){return this.map(function(){for(var t=this.offsetParent||L.body;t&&!Z.test(t.nodeName)&&\"static\"==T(t).css(\"position\");)t=t.offsetParent;return t})}},T.fn.detach=T.fn.remove,[\"width\",\"height\"].forEach(function(t){var e=t.replace(/./,function(t){return t[0].toUpperCase()});T.fn[t]=function(i){var o,a=this[0];return i===E?n(a)?a[\"inner\"+e]:r(a)?a.documentElement[\"scroll\"+e]:(o=this.offset())&&o[t]:this.each(function(e){a=T(this),a.css(t,g(this,i,e,a[t]()))})}}),I.forEach(function(e,n){var r=n%2;T.fn[e]=function(){var e,i,o=T.map(arguments,function(n){var r=[];return e=t(n),\"array\"==e?(n.forEach(function(t){return t.nodeType!==E?r.push(t):T.zepto.isZ(t)?r=r.concat(t.get()):void(r=r.concat(Y.fragment(t)))}),r):\"object\"==e||null==n?n:Y.fragment(n)}),a=this.length>1;return o.length<1?this:this.each(function(t,e){i=r?e:e.parentNode,e=0==n?e.nextSibling:1==n?e.firstChild:2==n?e:null;var s=T.contains(L.documentElement,i);o.forEach(function(t){if(a)t=t.cloneNode(!0);else if(!i)return T(t).remove();i.insertBefore(t,e),s&&w(t,function(t){if(!(null==t.nodeName||\"SCRIPT\"!==t.nodeName.toUpperCase()||t.type&&\"text/javascript\"!==t.type||t.src)){var e=t.ownerDocument?t.ownerDocument.defaultView:window;e.eval.call(e,t.innerHTML)}})})})},T.fn[r?e+\"To\":\"insert\"+(n?\"Before\":\"After\")]=function(t){return T(t)[e](this),this}}),Y.Z.prototype=d.prototype=T.fn,Y.uniq=N,Y.deserializeValue=b,T.zepto=Y,T}();!function(t){function e(t){return t._zid||(t._zid=h++)}function n(t,n,o,a){if(n=r(n),n.ns)var s=i(n.ns);return(v[e(t)]||[]).filter(function(t){return t&&(!n.e||t.e==n.e)&&(!n.ns||s.test(t.ns))&&(!o||e(t.fn)===e(o))&&(!a||t.sel==a)})}function r(t){var e=(\"\"+t).split(\".\");return{e:e[0],ns:e.slice(1).sort().join(\" \")}}function i(t){return new RegExp(\"(?:^| )\"+t.replace(\" \",\" .* ?\")+\"(?: |$)\")}function o(t,e){return t.del&&!y&&t.e in x||!!e}function a(t){return b[t]||y&&x[t]||t}function s(n,i,s,u,l,h,p){var d=e(n),m=v[d]||(v[d]=[]);i.split(/\\s/).forEach(function(e){if(\"ready\"==e)return t(document).ready(s);var i=r(e);i.fn=s,i.sel=l,i.e in b&&(s=function(e){var n=e.relatedTarget;if(!n||n!==this&&!t.contains(this,n))return i.fn.apply(this,arguments)}),i.del=h;var d=h||s;i.proxy=function(t){if(t=c(t),!t.isImmediatePropagationStopped()){t.data=u;var e=d.apply(n,t._args==f?[t]:[t].concat(t._args));return e===!1&&(t.preventDefault(),t.stopPropagation()),e}},i.i=m.length,m.push(i),\"addEventListener\"in n&&n.addEventListener(a(i.e),i.proxy,o(i,p))})}function u(t,r,i,s,u){var c=e(t);(r||\"\").split(/\\s/).forEach(function(e){n(t,e,i,s).forEach(function(e){delete v[c][e.i],\"removeEventListener\"in t&&t.removeEventListener(a(e.e),e.proxy,o(e,u))})})}function c(e,n){return!n&&e.isDefaultPrevented||(n||(n=e),t.each(T,function(t,r){var i=n[t];e[t]=function(){return this[r]=w,i&&i.apply(n,arguments)},e[r]=E}),e.timeStamp||(e.timeStamp=Date.now()),(n.defaultPrevented!==f?n.defaultPrevented:\"returnValue\"in n?n.returnValue===!1:n.getPreventDefault&&n.getPreventDefault())&&(e.isDefaultPrevented=w)),e}function l(t){var e,n={originalEvent:t};for(e in t)j.test(e)||t[e]===f||(n[e]=t[e]);return c(n,t)}var f,h=1,p=Array.prototype.slice,d=t.isFunction,m=function(t){return\"string\"==typeof t},v={},g={},y=\"onfocusin\"in window,x={focus:\"focusin\",blur:\"focusout\"},b={mouseenter:\"mouseover\",mouseleave:\"mouseout\"};g.click=g.mousedown=g.mouseup=g.mousemove=\"MouseEvents\",t.event={add:s,remove:u},t.proxy=function(n,r){var i=2 in arguments&&p.call(arguments,2);if(d(n)){var o=function(){return n.apply(r,i?i.concat(p.call(arguments)):arguments)};return o._zid=e(n),o}if(m(r))return i?(i.unshift(n[r],n),t.proxy.apply(null,i)):t.proxy(n[r],n);throw new TypeError(\"expected function\")},t.fn.bind=function(t,e,n){return this.on(t,e,n)},t.fn.unbind=function(t,e){return this.off(t,e)},t.fn.one=function(t,e,n,r){return this.on(t,e,n,r,1)};var w=function(){return!0},E=function(){return!1},j=/^([A-Z]|returnValue$|layer[XY]$|webkitMovement[XY]$)/,T={preventDefault:\"isDefaultPrevented\",stopImmediatePropagation:\"isImmediatePropagationStopped\",stopPropagation:\"isPropagationStopped\"};t.fn.delegate=function(t,e,n){return this.on(e,t,n)},t.fn.undelegate=function(t,e,n){return this.off(e,t,n)},t.fn.live=function(e,n){return t(document.body).delegate(this.selector,e,n),this},t.fn.die=function(e,n){return t(document.body).undelegate(this.selector,e,n),this},t.fn.on=function(e,n,r,i,o){var a,c,h=this;return e&&!m(e)?(t.each(e,function(t,e){h.on(t,n,r,e,o)}),h):(m(n)||d(i)||i===!1||(i=r,r=n,n=f),i!==f&&r!==!1||(i=r,r=f),i===!1&&(i=E),h.each(function(f,h){o&&(a=function(t){return u(h,t.type,i),i.apply(this,arguments)}),n&&(c=function(e){var r,o=t(e.target).closest(n,h).get(0);if(o&&o!==h)return r=t.extend(l(e),{currentTarget:o,liveFired:h}),(a||i).apply(o,[r].concat(p.call(arguments,1)))}),s(h,e,i,r,n,c||a)}))},t.fn.off=function(e,n,r){var i=this;return e&&!m(e)?(t.each(e,function(t,e){i.off(t,n,e)}),i):(m(n)||d(r)||r===!1||(r=n,n=f),r===!1&&(r=E),i.each(function(){u(this,e,r,n)}))},t.fn.trigger=function(e,n){return e=m(e)||t.isPlainObject(e)?t.Event(e):c(e),e._args=n,this.each(function(){e.type in x&&\"function\"==typeof this[e.type]?this[e.type]():\"dispatchEvent\"in this?this.dispatchEvent(e):t(this).triggerHandler(e,n)})},t.fn.triggerHandler=function(e,r){var i,o;return this.each(function(a,s){i=l(m(e)?t.Event(e):e),i._args=r,i.target=s,t.each(n(s,e.type||e),function(t,e){if(o=e.proxy(i),i.isImmediatePropagationStopped())return!1})}),o},\"focusin focusout focus blur load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select keydown keypress keyup error\".split(\" \").forEach(function(e){t.fn[e]=function(t){return 0 in arguments?this.bind(e,t):this.trigger(e)}}),t.Event=function(t,e){m(t)||(e=t,t=e.type);var n=document.createEvent(g[t]||\"Events\"),r=!0;if(e)for(var i in e)\"bubbles\"==i?r=!!e[i]:n[i]=e[i];return n.initEvent(t,r,!0),c(n)}}(e),function(t){function e(e,n,r){var i=t.Event(n);return t(e).trigger(i,r),!i.isDefaultPrevented()}function n(t,n,r,i){if(t.global)return e(n||x,r,i)}function r(e){e.global&&0===t.active++&&n(e,null,\"ajaxStart\")}function i(e){e.global&&!--t.active&&n(e,null,\"ajaxStop\")}function o(t,e){var r=e.context;return e.beforeSend.call(r,t,e)!==!1&&n(e,r,\"ajaxBeforeSend\",[t,e])!==!1&&void n(e,r,\"ajaxSend\",[t,e])}function a(t,e,r,i){var o=r.context,a=\"success\";r.success.call(o,t,a,e),i&&i.resolveWith(o,[t,a,e]),n(r,o,\"ajaxSuccess\",[e,r,t]),u(a,e,r)}function s(t,e,r,i,o){var a=i.context;i.error.call(a,r,e,t),o&&o.rejectWith(a,[r,e,t]),n(i,a,\"ajaxError\",[r,i,t||e]),u(e,r,i)}function u(t,e,r){var o=r.context;r.complete.call(o,e,t),n(r,o,\"ajaxComplete\",[e,r]),i(r)}function c(t,e,n){if(n.dataFilter==l)return t;var r=n.context;return n.dataFilter.call(r,t,e)}function l(){}function f(t){return t&&(t=t.split(\";\",2)[0]),t&&(t==T?\"html\":t==j?\"json\":w.test(t)?\"script\":E.test(t)&&\"xml\")||\"text\"}function h(t,e){return\"\"==e?t:(t+\"&\"+e).replace(/[&?]{1,2}/,\"?\")}function p(e){e.processData&&e.data&&\"string\"!=t.type(e.data)&&(e.data=t.param(e.data,e.traditional)),!e.data||e.type&&\"GET\"!=e.type.toUpperCase()&&\"jsonp\"!=e.dataType||(e.url=h(e.url,e.data),e.data=void 0)}function d(e,n,r,i){return t.isFunction(n)&&(i=r,r=n,n=void 0),t.isFunction(r)||(i=r,r=void 0),{url:e,data:n,success:r,dataType:i}}function m(e,n,r,i){var o,a=t.isArray(n),s=t.isPlainObject(n);t.each(n,function(n,u){o=t.type(u),i&&(n=r?i:i+\"[\"+(s||\"object\"==o||\"array\"==o?n:\"\")+\"]\"),!i&&a?e.add(u.name,u.value):\"array\"==o||!r&&\"object\"==o?m(e,u,r,n):e.add(n,u)})}var v,g,y=+new Date,x=window.document,b=/<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi,w=/^(?:text|application)\\/javascript/i,E=/^(?:text|application)\\/xml/i,j=\"application/json\",T=\"text/html\",S=/^\\s*$/,C=x.createElement(\"a\");C.href=window.location.href,t.active=0,t.ajaxJSONP=function(e,n){if(!(\"type\"in e))return t.ajax(e);var r,i,u=e.jsonpCallback,c=(t.isFunction(u)?u():u)||\"Zepto\"+y++,l=x.createElement(\"script\"),f=window[c],h=function(e){t(l).triggerHandler(\"error\",e||\"abort\")},p={abort:h};return n&&n.promise(p),t(l).on(\"load error\",function(o,u){clearTimeout(i),t(l).off().remove(),\"error\"!=o.type&&r?a(r[0],p,e,n):s(null,u||\"error\",p,e,n),window[c]=f,r&&t.isFunction(f)&&f(r[0]),f=r=void 0}),o(p,e)===!1?(h(\"abort\"),p):(window[c]=function(){r=arguments},l.src=e.url.replace(/\\?(.+)=\\?/,\"?$1=\"+c),x.head.appendChild(l),e.timeout>0&&(i=setTimeout(function(){h(\"timeout\")},e.timeout)),p)},t.ajaxSettings={type:\"GET\",beforeSend:l,success:l,error:l,complete:l,context:null,global:!0,xhr:function(){return new window.XMLHttpRequest},accepts:{script:\"text/javascript, application/javascript, application/x-javascript\",json:j,xml:\"application/xml, text/xml\",html:T,text:\"text/plain\"},crossDomain:!1,timeout:0,processData:!0,cache:!0,dataFilter:l},t.ajax=function(e){var n,i,u=t.extend({},e||{}),d=t.Deferred&&t.Deferred();for(v in t.ajaxSettings)void 0===u[v]&&(u[v]=t.ajaxSettings[v]);r(u),u.crossDomain||(n=x.createElement(\"a\"),n.href=u.url,n.href=n.href,u.crossDomain=C.protocol+\"//\"+C.host!=n.protocol+\"//\"+n.host),u.url||(u.url=window.location.toString()),(i=u.url.indexOf(\"#\"))>-1&&(u.url=u.url.slice(0,i)),p(u);var m=u.dataType,y=/\\?.+=\\?/.test(u.url);if(y&&(m=\"jsonp\"),u.cache!==!1&&(e&&e.cache===!0||\"script\"!=m&&\"jsonp\"!=m)||(u.url=h(u.url,\"_=\"+Date.now())),\"jsonp\"==m)return y||(u.url=h(u.url,u.jsonp?u.jsonp+\"=?\":u.jsonp===!1?\"\":\"callback=?\")),t.ajaxJSONP(u,d);var b,w=u.accepts[m],E={},j=function(t,e){E[t.toLowerCase()]=[t,e]},T=/^([\\w-]+:)\\/\\//.test(u.url)?RegExp.$1:window.location.protocol,N=u.xhr(),O=N.setRequestHeader;if(d&&d.promise(N),u.crossDomain||j(\"X-Requested-With\",\"XMLHttpRequest\"),j(\"Accept\",w||\"*/*\"),(w=u.mimeType||w)&&(w.indexOf(\",\")>-1&&(w=w.split(\",\",2)[0]),N.overrideMimeType&&N.overrideMimeType(w)),(u.contentType||u.contentType!==!1&&u.data&&\"GET\"!=u.type.toUpperCase())&&j(\"Content-Type\",u.contentType||\"application/x-www-form-urlencoded\"),u.headers)for(g in u.headers)j(g,u.headers[g]);if(N.setRequestHeader=j,N.onreadystatechange=function(){if(4==N.readyState){N.onreadystatechange=l,clearTimeout(b);var e,n=!1;if(N.status>=200&&N.status<300||304==N.status||0==N.status&&\"file:\"==T){if(m=m||f(u.mimeType||N.getResponseHeader(\"content-type\")),\"arraybuffer\"==N.responseType||\"blob\"==N.responseType)e=N.response;else{e=N.responseText;try{e=c(e,m,u),\"script\"==m?(0,eval)(e):\"xml\"==m?e=N.responseXML:\"json\"==m&&(e=S.test(e)?null:t.parseJSON(e))}catch(r){n=r}if(n)return s(n,\"parsererror\",N,u,d)}a(e,N,u,d)}else s(N.statusText||null,N.status?\"error\":\"abort\",N,u,d)}},o(N,u)===!1)return N.abort(),s(null,\"abort\",N,u,d),N;var P=!(\"async\"in u)||u.async;if(N.open(u.type,u.url,P,u.username,u.password),u.xhrFields)for(g in u.xhrFields)N[g]=u.xhrFields[g];for(g in E)O.apply(N,E[g]);return u.timeout>0&&(b=setTimeout(function(){N.onreadystatechange=l,N.abort(),s(null,\"timeout\",N,u,d)},u.timeout)),N.send(u.data?u.data:null),N},t.get=function(){return t.ajax(d.apply(null,arguments))},t.post=function(){var e=d.apply(null,arguments);return e.type=\"POST\",t.ajax(e)},t.getJSON=function(){var e=d.apply(null,arguments);return e.dataType=\"json\",t.ajax(e)},t.fn.load=function(e,n,r){if(!this.length)return this;var i,o=this,a=e.split(/\\s/),s=d(e,n,r),u=s.success;return a.length>1&&(s.url=a[0],i=a[1]),s.success=function(e){o.html(i?t(\"<div>\").html(e.replace(b,\"\")).find(i):e),u&&u.apply(o,arguments)},t.ajax(s),this};var N=encodeURIComponent;t.param=function(e,n){var r=[];return r.add=function(e,n){t.isFunction(n)&&(n=n()),null==n&&(n=\"\"),this.push(N(e)+\"=\"+N(n))},m(r,e,n),r.join(\"&\").replace(/%20/g,\"+\")}}(e),function(t){t.fn.serializeArray=function(){var e,n,r=[],i=function(t){return t.forEach?t.forEach(i):void r.push({name:e,value:t})};return this[0]&&t.each(this[0].elements,function(r,o){n=o.type,e=o.name,e&&\"fieldset\"!=o.nodeName.toLowerCase()&&!o.disabled&&\"submit\"!=n&&\"reset\"!=n&&\"button\"!=n&&\"file\"!=n&&(\"radio\"!=n&&\"checkbox\"!=n||o.checked)&&i(t(o).val())}),r},t.fn.serialize=function(){var t=[];return this.serializeArray().forEach(function(e){t.push(encodeURIComponent(e.name)+\"=\"+encodeURIComponent(e.value))}),t.join(\"&\")},t.fn.submit=function(e){if(0 in arguments)this.bind(\"submit\",e);else if(this.length){var n=t.Event(\"submit\");this.eq(0).trigger(n),n.isDefaultPrevented()||this.get(0).submit()}return this}}(e),function(){try{getComputedStyle(void 0)}catch(t){var e=getComputedStyle;window.getComputedStyle=function(t,n){try{return e(t,n)}catch(r){return null}}}}(),t(\"zepto\",e)});layui.define([\"layer-mobile\",\"zepto\"],function(e){\"use strict\";var t=layui.zepto,a=layui[\"layer-mobile\"],i=(layui.device(),\"layui-upload-enter\"),n=\"layui-upload-iframe\",r={icon:2,shift:6},o={file:\"文件\",video:\"视频\",audio:\"音频\"};a.msg=function(e){return a.open({content:e||\"\",skin:\"msg\",time:2})};var s=function(e){this.options=e};s.prototype.init=function(){var e=this,a=e.options,r=t(\"body\"),s=t(a.elem||\".layui-upload-file\"),u=t('<iframe id=\"'+n+'\" class=\"'+n+'\" name=\"'+n+'\"></iframe>');return t(\"#\"+n)[0]||r.append(u),s.each(function(r,s){s=t(s);var u='<form target=\"'+n+'\" method=\"'+(a.method||\"post\")+'\" key=\"set-mine\" enctype=\"multipart/form-data\" action=\"'+(a.url||\"\")+'\"></form>',l=s.attr(\"lay-type\")||a.type;a.unwrap||(u='<div class=\"layui-box layui-upload-button\">'+u+'<span class=\"layui-upload-icon\"><i class=\"layui-icon\">&#xe608;</i>'+(s.attr(\"lay-title\")||a.title||\"上传\"+(o[l]||\"图片\"))+\"</span></div>\"),u=t(u),a.unwrap||u.on(\"dragover\",function(e){e.preventDefault(),t(this).addClass(i)}).on(\"dragleave\",function(){t(this).removeClass(i)}).on(\"drop\",function(){t(this).removeClass(i)}),s.parent(\"form\").attr(\"target\")===n&&(a.unwrap?s.unwrap():(s.parent().next().remove(),s.unwrap().unwrap())),s.wrap(u),s.off(\"change\").on(\"change\",function(){e.action(this,l)})})},s.prototype.action=function(e,i){var o=this,s=o.options,u=e.value,l=t(e),p=l.attr(\"lay-ext\")||s.ext||\"\";if(u){switch(i){case\"file\":if(p&&!RegExp(\"\\\\w\\\\.(\"+p+\")$\",\"i\").test(escape(u)))return a.msg(\"不支持该文件格式\",r),e.value=\"\";break;case\"video\":if(!RegExp(\"\\\\w\\\\.(\"+(p||\"avi|mp4|wma|rmvb|rm|flash|3gp|flv\")+\")$\",\"i\").test(escape(u)))return a.msg(\"不支持该视频格式\",r),e.value=\"\";break;case\"audio\":if(!RegExp(\"\\\\w\\\\.(\"+(p||\"mp3|wav|mid\")+\")$\",\"i\").test(escape(u)))return a.msg(\"不支持该音频格式\",r),e.value=\"\";break;default:if(!RegExp(\"\\\\w\\\\.(\"+(p||\"jpg|png|gif|bmp|jpeg\")+\")$\",\"i\").test(escape(u)))return a.msg(\"不支持该图片格式\",r),e.value=\"\"}s.before&&s.before(e),l.parent().submit();var c=t(\"#\"+n),f=setInterval(function(){var t;try{t=c.contents().find(\"body\").text()}catch(i){a.msg(\"上传接口存在跨域\",r),clearInterval(f)}if(t){clearInterval(f),c.contents().find(\"body\").html(\"\");try{t=JSON.parse(t)}catch(i){return t={},a.msg(\"请对上传接口返回JSON字符\",r)}\"function\"==typeof s.success&&s.success(t,e)}},30);e.value=\"\"}},e(\"upload-mobile\",function(e){var t=new s(e=e||{});t.init()})});layui.define(function(i){i(\"layim-mobile\",layui.v)});layui[\"layui.mobile\"]||layui.config({base:layui.cache.dir+\"lay/modules/mobile/\"}).extend({\"layer-mobile\":\"layer-mobile\",zepto:\"zepto\",\"upload-mobile\":\"upload-mobile\",\"layim-mobile\":\"layim-mobile\"}),layui.define([\"layer-mobile\",\"zepto\",\"layim-mobile\"],function(l){l(\"mobile\",{layer:layui[\"layer-mobile\"],layim:layui[\"layim-mobile\"]})});"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/layui/lay/modules/table.js",
    "content": "/** layui-v2.2.5 MIT License By https://www.layui.com */\n ;layui.define([\"laytpl\",\"laypage\",\"layer\",\"form\"],function(e){\"use strict\";var t=layui.$,i=layui.laytpl,a=layui.laypage,l=layui.layer,n=layui.form,o=layui.hint(),r=layui.device(),d={config:{checkName:\"LAY_CHECKED\",indexName:\"LAY_TABLE_INDEX\"},cache:{},index:layui.table?layui.table.index+1e4:0,set:function(e){var i=this;return i.config=t.extend({},i.config,e),i},on:function(e,t){return layui.onevent.call(this,s,e,t)}},c=function(){var e=this,t=e.config,i=t.id;return i&&(c.config[i]=t),{reload:function(t){e.reload.call(e,t)},config:t}},s=\"table\",u=\".layui-table\",h=\"layui-hide\",f=\"layui-none\",y=\"layui-table-view\",p=\".layui-table-header\",m=\".layui-table-body\",v=\".layui-table-main\",g=\".layui-table-fixed\",x=\".layui-table-fixed-l\",b=\".layui-table-fixed-r\",k=\".layui-table-tool\",C=\".layui-table-page\",w=\".layui-table-sort\",N=\"layui-table-edit\",F=\"layui-table-hover\",W=function(e){var t='{{#if(item2.colspan){}} colspan=\"{{item2.colspan}}\"{{#} if(item2.rowspan){}} rowspan=\"{{item2.rowspan}}\"{{#}}}';return e=e||{},['<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\" class=\"layui-table\" ','{{# if(d.data.skin){ }}lay-skin=\"{{d.data.skin}}\"{{# } }} {{# if(d.data.size){ }}lay-size=\"{{d.data.size}}\"{{# } }} {{# if(d.data.even){ }}lay-even{{# } }}>',\"<thead>\",\"{{# layui.each(d.data.cols, function(i1, item1){ }}\",\"<tr>\",\"{{# layui.each(item1, function(i2, item2){ }}\",'{{# if(item2.fixed && item2.fixed !== \"right\"){ left = true; } }}','{{# if(item2.fixed === \"right\"){ right = true; } }}',function(){return e.fixed&&\"right\"!==e.fixed?'{{# if(item2.fixed && item2.fixed !== \"right\"){ }}':\"right\"===e.fixed?'{{# if(item2.fixed === \"right\"){ }}':\"\"}(),'<th data-field=\"{{ item2.field||i2 }}\" {{# if(item2.minWidth){ }}data-minwidth=\"{{item2.minWidth}}\"{{# } }} '+t+' {{# if(item2.unresize){ }}data-unresize=\"true\"{{# } }}>','<div class=\"layui-table-cell laytable-cell-',\"{{# if(item2.colspan > 1){ }}\",\"group\",\"{{# } else { }}\",\"{{d.index}}-{{item2.field || i2}}\",'{{# if(item2.type !== \"normal\"){ }}',\" laytable-cell-{{ item2.type }}\",\"{{# } }}\",\"{{# } }}\",'\" {{#if(item2.align){}}align=\"{{item2.align}}\"{{#}}}>','{{# if(item2.type === \"checkbox\"){ }}','<input type=\"checkbox\" name=\"layTableCheckbox\" lay-skin=\"primary\" lay-filter=\"layTableAllChoose\" {{# if(item2[d.data.checkName]){ }}checked{{# }; }}>',\"{{# } else { }}\",'<span>{{item2.title||\"\"}}</span>',\"{{# if(!(item2.colspan > 1) && item2.sort){ }}\",'<span class=\"layui-table-sort layui-inline\"><i class=\"layui-edge layui-table-sort-asc\"></i><i class=\"layui-edge layui-table-sort-desc\"></i></span>',\"{{# } }}\",\"{{# } }}\",\"</div>\",\"</th>\",e.fixed?\"{{# }; }}\":\"\",\"{{# }); }}\",\"</tr>\",\"{{# }); }}\",\"</thead>\",\"</table>\"].join(\"\")},z=['<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\" class=\"layui-table\" ','{{# if(d.data.skin){ }}lay-skin=\"{{d.data.skin}}\"{{# } }} {{# if(d.data.size){ }}lay-size=\"{{d.data.size}}\"{{# } }} {{# if(d.data.even){ }}lay-even{{# } }}>',\"<tbody></tbody>\",\"</table>\"].join(\"\"),A=['<div class=\"layui-form layui-border-box {{d.VIEW_CLASS}}\" lay-filter=\"LAY-table-{{d.index}}\" style=\"{{# if(d.data.width){ }}width:{{d.data.width}}px;{{# } }} {{# if(d.data.height){ }}height:{{d.data.height}}px;{{# } }}\">',\"{{# if(d.data.toolbar){ }}\",'<div class=\"layui-table-tool\"></div>',\"{{# } }}\",'<div class=\"layui-table-box\">',\"{{# var left, right; }}\",'<div class=\"layui-table-header\">',W(),\"</div>\",'<div class=\"layui-table-body layui-table-main\">',z,\"</div>\",\"{{# if(left){ }}\",'<div class=\"layui-table-fixed layui-table-fixed-l\">','<div class=\"layui-table-header\">',W({fixed:!0}),\"</div>\",'<div class=\"layui-table-body\">',z,\"</div>\",\"</div>\",\"{{# }; }}\",\"{{# if(right){ }}\",'<div class=\"layui-table-fixed layui-table-fixed-r\">','<div class=\"layui-table-header\">',W({fixed:\"right\"}),'<div class=\"layui-table-mend\"></div>',\"</div>\",'<div class=\"layui-table-body\">',z,\"</div>\",\"</div>\",\"{{# }; }}\",\"</div>\",\"{{# if(d.data.page){ }}\",'<div class=\"layui-table-page\">','<div id=\"layui-table-page{{d.index}}\"></div>',\"</div>\",\"{{# } }}\",\"<style>\",\"{{# layui.each(d.data.cols, function(i1, item1){\",\"layui.each(item1, function(i2, item2){ }}\",\".laytable-cell-{{d.index}}-{{item2.field||i2}}{ \",\"{{# if(item2.width){ }}\",\"width: {{item2.width}}px;\",\"{{# } }}\",\" }\",\"{{# });\",\"}); }}\",\"</style>\",\"</div>\"].join(\"\"),T=t(window),M=t(document),S=function(e){var i=this;i.index=++d.index,i.config=t.extend({},i.config,d.config,e),i.render()};S.prototype.config={limit:10,loading:!0,cellMinWidth:60,text:{none:\"无数据\"}},S.prototype.render=function(){var e=this,a=e.config;if(a.elem=t(a.elem),a.where=a.where||{},a.id=a.id||a.elem.attr(\"id\"),a.request=t.extend({pageName:\"page\",limitName:\"limit\"},a.request),a.response=t.extend({statusName:\"code\",statusCode:0,msgName:\"msg\",dataName:\"data\",countName:\"count\"},a.response),\"object\"==typeof a.page&&(a.limit=a.page.limit||a.limit,a.limits=a.page.limits||a.limits,e.page=a.page.curr=a.page.curr||1,delete a.page.elem,delete a.page.jump),!a.elem[0])return e;e.setArea();var l=a.elem,n=l.next(\".\"+y),o=e.elem=t(i(A).render({VIEW_CLASS:y,data:a,index:e.index}));if(a.index=e.index,n[0]&&n.remove(),l.after(o),e.layHeader=o.find(p),e.layMain=o.find(v),e.layBody=o.find(m),e.layFixed=o.find(g),e.layFixLeft=o.find(x),e.layFixRight=o.find(b),e.layTool=o.find(k),e.layPage=o.find(C),e.layTool.html(i(t(a.toolbar).html()||\"\").render(a)),a.height&&e.fullSize(),a.cols.length>1){var r=e.layFixed.find(p).find(\"th\");r.height(e.layHeader.height()-1-parseFloat(r.css(\"padding-top\"))-parseFloat(r.css(\"padding-bottom\")))}e.pullData(e.page),e.events()},S.prototype.initOpts=function(e){var t=this,i=(t.config,{checkbox:48,space:15,numbers:40});e.checkbox&&(e.type=\"checkbox\"),e.space&&(e.type=\"space\"),e.type||(e.type=\"normal\"),\"normal\"!==e.type&&(e.unresize=!0,e.width=e.width||i[e.type])},S.prototype.setArea=function(){var e=this,t=e.config,i=0,a=0,l=0,n=0,o=t.width||function(){var e=function(i){var a,l;i=i||t.elem.parent(),a=i.width();try{l=\"none\"===i.css(\"display\")}catch(n){}return!i[0]||a&&!l?a:e(i.parent())};return e()}();e.eachCols(function(){i++}),o-=function(){return\"line\"===t.skin||\"nob\"===t.skin?2:i+1}(),layui.each(t.cols,function(t,i){layui.each(i,function(t,l){var r;return l?(e.initOpts(l),r=l.width||0,void(l.colspan>1||(/\\d+%$/.test(r)?l.width=r=Math.floor(parseFloat(r)/100*o):r||(l.width=r=0,a++),n+=r))):void i.splice(t,1)})}),e.autoColNums=a,o>n&&a&&(l=(o-n)/a),layui.each(t.cols,function(e,i){layui.each(i,function(e,i){var a=i.minWidth||t.cellMinWidth;i.colspan>1||0===i.width&&(i.width=Math.floor(l>=a?l:a))})}),t.height&&/^full-\\d+$/.test(t.height)&&(e.fullHeightGap=t.height.split(\"-\")[1],t.height=T.height()-e.fullHeightGap)},S.prototype.reload=function(e){var i=this;i.config.data&&i.config.data.constructor===Array&&delete i.config.data,i.config=t.extend({},i.config,e),i.render()},S.prototype.page=1,S.prototype.pullData=function(e,i){var a=this,n=a.config,o=n.request,r=n.response,d=function(){\"object\"==typeof n.initSort&&a.sort(n.initSort.field,n.initSort.type)};if(a.startTime=(new Date).getTime(),n.url){var c={};c[o.pageName]=e,c[o.limitName]=n.limit,t.ajax({type:n.method||\"get\",url:n.url,data:t.extend(c,n.where),dataType:\"json\",success:function(t){t[r.statusName]!=r.statusCode?(a.renderForm(),a.layMain.html('<div class=\"'+f+'\">'+(t[r.msgName]||\"返回的数据状态异常\")+\"</div>\")):(a.renderData(t,e,t[r.countName]),d(),n.time=(new Date).getTime()-a.startTime+\" ms\"),i&&l.close(i),\"function\"==typeof n.done&&n.done(t,e,t[r.countName])},error:function(e,t){a.layMain.html('<div class=\"'+f+'\">数据接口请求异常</div>'),a.renderForm(),i&&l.close(i)}})}else if(n.data&&n.data.constructor===Array){var s={},u=e*n.limit-n.limit;s[r.dataName]=n.data.concat().splice(u,n.limit),s[r.countName]=n.data.length,a.renderData(s,e,n.data.length),d(),\"function\"==typeof n.done&&n.done(s,e,s[r.countName])}},S.prototype.eachCols=function(e){var i=t.extend(!0,[],this.config.cols),a=[],l=0;layui.each(i,function(e,t){layui.each(t,function(t,n){if(n.colspan>1){var o=0;l++,n.CHILD_COLS=[],layui.each(i[e+1],function(e,t){t.PARENT_COL||o==n.colspan||(t.PARENT_COL=l,n.CHILD_COLS.push(t),o+=t.colspan>1?t.colspan:1)})}n.PARENT_COL||a.push(n)})});var n=function(t){layui.each(t||a,function(t,i){return i.CHILD_COLS?n(i.CHILD_COLS):void e(t,i)})};n()},S.prototype.renderData=function(e,n,o,r){var c=this,s=c.config,u=e[s.response.dataName]||[],y=[],p=[],m=[],v=function(){return!r&&c.sortKey?c.sort(c.sortKey.field,c.sortKey.sort,!0):(layui.each(u,function(e,a){var l=[],o=[],u=[],h=e+s.limit*(n-1)+1;0!==a.length&&(r||(a[d.config.indexName]=e),c.eachCols(function(e,n){var r=n.field||e,f=a[r];c.getColElem(c.layHeader,r);if(void 0!==f&&null!==f||(f=\"\"),!(n.colspan>1)){var y=['<td data-field=\"'+r+'\" '+function(){var e=[];return n.edit&&e.push('data-edit=\"'+n.edit+'\"'),n.align&&e.push('align=\"'+n.align+'\"'),n.templet&&e.push('data-content=\"'+f+'\"'),n.toolbar&&e.push('data-off=\"true\"'),n.event&&e.push('lay-event=\"'+n.event+'\"'),n.style&&e.push('style=\"'+n.style+'\"'),n.minWidth&&e.push('data-minwidth=\"'+n.minWidth+'\"'),e.join(\" \")}()+\">\",'<div class=\"layui-table-cell laytable-cell-'+function(){var e=s.index+\"-\"+r;return\"normal\"===n.type?e:e+\" laytable-cell-\"+n.type}()+'\">'+function(){var e=t.extend(!0,{LAY_INDEX:h},a);return\"checkbox\"===n.type?'<input type=\"checkbox\" name=\"layTableCheckbox\" lay-skin=\"primary\" '+function(){var t=d.config.checkName;return n[t]?(a[t]=n[t],n[t]?\"checked\":\"\"):e[t]?\"checked\":\"\"}()+\">\":\"numbers\"===n.type?h:n.toolbar?i(t(n.toolbar).html()||\"\").render(e):n.templet?function(){return\"function\"==typeof n.templet?n.templet(e):i(t(n.templet).html()||String(f)).render(e)}():f}(),\"</div></td>\"].join(\"\");l.push(y),n.fixed&&\"right\"!==n.fixed&&o.push(y),\"right\"===n.fixed&&u.push(y)}}),y.push('<tr data-index=\"'+e+'\">'+l.join(\"\")+\"</tr>\"),p.push('<tr data-index=\"'+e+'\">'+o.join(\"\")+\"</tr>\"),m.push('<tr data-index=\"'+e+'\">'+u.join(\"\")+\"</tr>\"))}),c.layBody.scrollTop(0),c.layMain.find(\".\"+f).remove(),c.layMain.find(\"tbody\").html(y.join(\"\")),c.layFixLeft.find(\"tbody\").html(p.join(\"\")),c.layFixRight.find(\"tbody\").html(m.join(\"\")),c.renderForm(),c.syncCheckAll(),c.haveInit?c.scrollPatch():setTimeout(function(){c.scrollPatch()},50),c.haveInit=!0,void l.close(c.tipsIndex))};return c.key=s.id||s.index,d.cache[c.key]=u,c.layPage[0===u.length&&1==n?\"addClass\":\"removeClass\"](h),r?v():0===u.length?(c.renderForm(),c.layFixed.remove(),c.layMain.find(\"tbody\").html(\"\"),c.layMain.find(\".\"+f).remove(),c.layMain.append('<div class=\"'+f+'\">'+s.text.none+\"</div>\")):(v(),void(s.page&&(s.page=t.extend({elem:\"layui-table-page\"+s.index,count:o,limit:s.limit,limits:s.limits||[10,20,30,40,50,60,70,80,90],groups:3,layout:[\"prev\",\"page\",\"next\",\"skip\",\"count\",\"limit\"],prev:'<i class=\"layui-icon\">&#xe603;</i>',next:'<i class=\"layui-icon\">&#xe602;</i>',jump:function(e,t){t||(c.page=e.curr,s.limit=e.limit,c.pullData(e.curr,c.loading()))}},s.page),s.page.count=o,a.render(s.page))))},S.prototype.getColElem=function(e,t){var i=this,a=i.config;return e.eq(0).find(\".laytable-cell-\"+(a.index+\"-\"+t)+\":eq(0)\")},S.prototype.renderForm=function(e){n.render(e,\"LAY-table-\"+this.index)},S.prototype.sort=function(e,i,a,l){var n,r,c=this,u={},h=c.config,f=h.elem.attr(\"lay-filter\"),y=d.cache[c.key];\"string\"==typeof e&&c.layHeader.find(\"th\").each(function(i,a){var l=t(this),o=l.data(\"field\");if(o===e)return e=l,n=o,!1});try{var n=n||e.data(\"field\");if(c.sortKey&&!a&&n===c.sortKey.field&&i===c.sortKey.sort)return;var p=c.layHeader.find(\"th .laytable-cell-\"+h.index+\"-\"+n).find(w);c.layHeader.find(\"th\").find(w).removeAttr(\"lay-sort\"),p.attr(\"lay-sort\",i||null),c.layFixed.find(\"th\")}catch(m){return o.error(\"Table modules: Did not match to field\")}c.sortKey={field:n,sort:i},\"asc\"===i?r=layui.sort(y,n):\"desc\"===i?r=layui.sort(y,n,!0):(r=layui.sort(y,d.config.indexName),delete c.sortKey),u[h.response.dataName]=r,c.renderData(u,c.page,c.count,!0),l&&layui.event.call(e,s,\"sort(\"+f+\")\",{field:n,type:i})},S.prototype.loading=function(){var e=this,t=e.config;if(t.loading&&t.url)return l.msg(\"数据请求中\",{icon:16,offset:[e.elem.offset().top+e.elem.height()/2-35-T.scrollTop()+\"px\",e.elem.offset().left+e.elem.width()/2-90-T.scrollLeft()+\"px\"],time:-1,anim:-1,fixed:!1})},S.prototype.setCheckData=function(e,t){var i=this,a=i.config,l=d.cache[i.key];l[e]&&l[e].constructor!==Array&&(l[e][a.checkName]=t)},S.prototype.syncCheckAll=function(){var e=this,t=e.config,i=e.layHeader.find('input[name=\"layTableCheckbox\"]'),a=function(i){return e.eachCols(function(e,a){\"checkbox\"===a.type&&(a[t.checkName]=i)}),i};i[0]&&(d.checkStatus(e.key).isAll?(i[0].checked||(i.prop(\"checked\",!0),e.renderForm(\"checkbox\")),a(!0)):(i[0].checked&&(i.prop(\"checked\",!1),e.renderForm(\"checkbox\")),a(!1)))},S.prototype.getCssRule=function(e,t){var i=this,a=i.elem.find(\"style\")[0],l=a.sheet||a.styleSheet||{},n=l.cssRules||l.rules;layui.each(n,function(a,l){if(l.selectorText===\".laytable-cell-\"+i.index+\"-\"+e)return t(l),!0})},S.prototype.fullSize=function(){var e,t=this,i=t.config,a=i.height;t.fullHeightGap&&(a=T.height()-t.fullHeightGap,a<135&&(a=135),t.elem.css(\"height\",a)),e=parseFloat(a)-parseFloat(t.layHeader.height())-1,i.toolbar&&(e-=t.layTool.outerHeight()),i.page&&(e=e-t.layPage.outerHeight()-1),t.layMain.css(\"height\",e)},S.prototype.getScrollWidth=function(e){var t=0;return e?t=e.offsetWidth-e.clientWidth:(e=document.createElement(\"div\"),e.style.width=\"100px\",e.style.height=\"100px\",e.style.overflowY=\"scroll\",document.body.appendChild(e),t=e.offsetWidth-e.clientWidth,document.body.removeChild(e)),t},S.prototype.scrollPatch=function(){var e=this,i=e.layMain.children(\"table\"),a=e.layMain.width()-e.layMain.prop(\"clientWidth\"),l=e.layMain.height()-e.layMain.prop(\"clientHeight\"),n=e.getScrollWidth(e.layMain[0]),o=i.outerWidth()-e.layMain.width();if(e.autoColNums&&o<5&&!e.scrollPatchWStatus){var r=e.layHeader.eq(0).find(\"thead th:last-child\"),d=r.data(\"field\");e.getCssRule(d,function(t){var i=t.style.width||r.outerWidth();t.style.width=parseFloat(i)-n-o+\"px\",e.layMain.height()-e.layMain.prop(\"clientHeight\")>0&&(t.style.width=parseFloat(t.style.width)-1+\"px\"),e.scrollPatchWStatus=!0})}if(a&&l){if(!e.elem.find(\".layui-table-patch\")[0]){var c=t('<th class=\"layui-table-patch\"><div class=\"layui-table-cell\"></div></th>');c.find(\"div\").css({width:a}),e.layHeader.eq(0).find(\"thead tr\").append(c)}}else e.layHeader.eq(0).find(\".layui-table-patch\").remove();var s=e.layMain.height(),u=s-l;e.layFixed.find(m).css(\"height\",i.height()>u?u:\"auto\"),e.layFixRight[o>0?\"removeClass\":\"addClass\"](h),e.layFixRight.css(\"right\",a-1)},S.prototype.events=function(){var e,a=this,n=a.config,o=t(\"body\"),c={},u=a.layHeader.find(\"th\"),h=\".layui-table-cell\",f=n.elem.attr(\"lay-filter\");u.on(\"mousemove\",function(e){var i=t(this),a=i.offset().left,l=e.clientX-a;i.attr(\"colspan\")>1||i.data(\"unresize\")||c.resizeStart||(c.allowResize=i.width()-l<=10,o.css(\"cursor\",c.allowResize?\"col-resize\":\"\"))}).on(\"mouseleave\",function(){t(this);c.resizeStart||o.css(\"cursor\",\"\")}).on(\"mousedown\",function(e){var i=t(this);if(c.allowResize){var l=i.data(\"field\");e.preventDefault(),c.resizeStart=!0,c.offset=[e.clientX,e.clientY],a.getCssRule(l,function(e){var t=e.style.width||i.outerWidth();c.rule=e,c.ruleWidth=parseFloat(t),c.minWidth=i.data(\"minwidth\")||n.cellMinWidth})}}),M.on(\"mousemove\",function(t){if(c.resizeStart){if(t.preventDefault(),c.rule){var i=c.ruleWidth+t.clientX-c.offset[0];i<c.minWidth&&(i=c.minWidth),c.rule.style.width=i+\"px\",l.close(a.tipsIndex)}e=1}}).on(\"mouseup\",function(t){c.resizeStart&&(c={},o.css(\"cursor\",\"\"),a.scrollPatch()),2===e&&(e=null)}),u.on(\"click\",function(){var i,l=t(this),n=l.find(w),o=n.attr(\"lay-sort\");return n[0]&&1!==e?(i=\"asc\"===o?\"desc\":\"desc\"===o?null:\"asc\",void a.sort(l,i,null,!0)):e=2}).find(w+\" .layui-edge \").on(\"click\",function(e){var i=t(this),l=i.index(),n=i.parents(\"th\").eq(0).data(\"field\");layui.stope(e),0===l?a.sort(n,\"asc\",null,!0):a.sort(n,\"desc\",null,!0)}),a.elem.on(\"click\",'input[name=\"layTableCheckbox\"]+',function(){var e=t(this).prev(),i=a.layBody.find('input[name=\"layTableCheckbox\"]'),l=e.parents(\"tr\").eq(0).data(\"index\"),n=e[0].checked,o=\"layTableAllChoose\"===e.attr(\"lay-filter\");o?(i.each(function(e,t){t.checked=n,a.setCheckData(e,n)}),a.syncCheckAll(),a.renderForm(\"checkbox\")):(a.setCheckData(l,n),a.syncCheckAll()),layui.event.call(this,s,\"checkbox(\"+f+\")\",{checked:n,data:d.cache[a.key]?d.cache[a.key][l]||{}:{},type:o?\"all\":\"one\"})}),a.layBody.on(\"mouseenter\",\"tr\",function(){var e=t(this),i=e.index();a.layBody.find(\"tr:eq(\"+i+\")\").addClass(F)}).on(\"mouseleave\",\"tr\",function(){var e=t(this),i=e.index();a.layBody.find(\"tr:eq(\"+i+\")\").removeClass(F)}),a.layBody.on(\"change\",\".\"+N,function(){var e=t(this),i=this.value,l=e.parent().data(\"field\"),n=e.parents(\"tr\").eq(0).data(\"index\"),o=d.cache[a.key][n];o[l]=i,layui.event.call(this,s,\"edit(\"+f+\")\",{value:i,data:o,field:l})}).on(\"blur\",\".\"+N,function(){var e,l=t(this),n=l.parent().data(\"field\"),o=l.parents(\"tr\").eq(0).data(\"index\"),r=d.cache[a.key][o];a.eachCols(function(t,i){i.field==n&&i.templet&&(e=i.templet)}),l.siblings(h).html(e?i(t(e).html()||this.value).render(r):this.value),l.parent().data(\"content\",this.value),l.remove()}),a.layBody.on(\"click\",\"td\",function(){var e=t(this),i=(e.data(\"field\"),e.data(\"edit\")),o=e.children(h);if(l.close(a.tipsIndex),!e.data(\"off\"))if(i)if(\"select\"===i);else{var d=t('<input class=\"layui-input '+N+'\">');d[0].value=e.data(\"content\")||o.text(),e.find(\".\"+N)[0]||e.append(d),d.focus()}else o.find(\".layui-form-switch,.layui-form-checkbox\")[0]||Math.round(o.prop(\"scrollWidth\"))>Math.round(o.outerWidth())&&(a.tipsIndex=l.tips(['<div class=\"layui-table-tips-main\" style=\"margin-top: -'+(o.height()+16)+\"px;\"+function(){return\"sm\"===n.size?\"padding: 4px 15px; font-size: 12px;\":\"lg\"===n.size?\"padding: 14px 15px;\":\"\"}()+'\">',o.html(),\"</div>\",'<i class=\"layui-icon layui-table-tips-c\">&#x1006;</i>'].join(\"\"),o[0],{tips:[3,\"\"],time:-1,anim:-1,maxWidth:r.ios||r.android?300:600,isOutAnim:!1,skin:\"layui-table-tips\",success:function(e,t){e.find(\".layui-table-tips-c\").on(\"click\",function(){l.close(t)})}}))}),a.layBody.on(\"click\",\"*[lay-event]\",function(){var e=t(this),l=e.parents(\"tr\").eq(0).data(\"index\"),n=a.layBody.find('tr[data-index=\"'+l+'\"]'),o=\"layui-table-click\",r=d.cache[a.key][l];layui.event.call(this,s,\"tool(\"+f+\")\",{data:d.clearCacheKey(r),event:e.attr(\"lay-event\"),tr:n,del:function(){d.cache[a.key][l]=[],n.remove(),a.scrollPatch()},update:function(e){e=e||{},layui.each(e,function(e,l){if(e in r){var o,d=n.children('td[data-field=\"'+e+'\"]');r[e]=l,a.eachCols(function(t,i){i.field==e&&i.templet&&(o=i.templet)}),d.children(h).html(o?i(t(o).html()||l).render(r):l),d.data(\"content\",l)}})}}),n.addClass(o).siblings(\"tr\").removeClass(o)}),a.layMain.on(\"scroll\",function(){var e=t(this),i=e.scrollLeft(),n=e.scrollTop();a.layHeader.scrollLeft(i),a.layFixed.find(m).scrollTop(n),l.close(a.tipsIndex)}),T.on(\"resize\",function(){a.fullSize(),a.scrollPatch()})},d.init=function(e,i){i=i||{};var a=this,l=t(e?'table[lay-filter=\"'+e+'\"]':u+\"[lay-data]\"),n=\"Table element property lay-data configuration item has a syntax error: \";return l.each(function(){var a=t(this),l=a.attr(\"lay-data\");try{l=new Function(\"return \"+l)()}catch(r){o.error(n+l)}var c=[],s=t.extend({elem:this,cols:[],data:[],skin:a.attr(\"lay-skin\"),size:a.attr(\"lay-size\"),even:\"string\"==typeof a.attr(\"lay-even\")},d.config,i,l);e&&a.hide(),a.find(\"thead>tr\").each(function(e){s.cols[e]=[],t(this).children().each(function(i){var a=t(this),l=a.attr(\"lay-data\");try{l=new Function(\"return \"+l)()}catch(r){return o.error(n+l)}var d=t.extend({title:a.text(),colspan:a.attr(\"colspan\")||0,rowspan:a.attr(\"rowspan\")||0},l);d.colspan<2&&c.push(d),s.cols[e].push(d)})}),a.find(\"tbody>tr\").each(function(e){var i=t(this),a={};i.children(\"td\").each(function(e,i){var l=t(this),n=l.data(\"field\");if(n)return a[n]=l.html()}),layui.each(c,function(e,t){var l=i.children(\"td\").eq(e);a[t.field]=l.html()}),s.data[e]=a}),d.render(s)}),a},d.checkStatus=function(e){var t=0,i=0,a=[],l=d.cache[e]||[];return layui.each(l,function(e,l){return l.constructor===Array?void i++:void(l[d.config.checkName]&&(t++,a.push(d.clearCacheKey(l))))}),{data:a,isAll:!!l.length&&t===l.length-i}},c.config={},d.reload=function(e,i){var a=c.config[e];return i=i||{},a?(i.data&&i.data.constructor===Array&&delete a.data,d.render(t.extend(!0,{},a,i))):o.error(\"The ID option was not found in the table instance\")},d.render=function(e){var t=new S(e);return c.call(t)},d.clearCacheKey=function(e){return e=t.extend({},e),delete e[d.config.checkName],delete e[d.config.indexName],e},d.init(),e(s,d)});"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/layui/lay/modules/tree.js",
    "content": "/** layui-v2.2.5 MIT License By https://www.layui.com */\n ;layui.define(\"jquery\",function(e){\"use strict\";var o=layui.$,a=layui.hint(),i=\"layui-tree-enter\",r=function(e){this.options=e},t={arrow:[\"&#xe623;\",\"&#xe625;\"],checkbox:[\"&#xe626;\",\"&#xe627;\"],radio:[\"&#xe62b;\",\"&#xe62a;\"],branch:[\"&#xe622;\",\"&#xe624;\"],leaf:\"&#xe621;\"};r.prototype.init=function(e){var o=this;e.addClass(\"layui-box layui-tree\"),o.options.skin&&e.addClass(\"layui-tree-skin-\"+o.options.skin),o.tree(e),o.on(e)},r.prototype.tree=function(e,a){var i=this,r=i.options,n=a||r.nodes;layui.each(n,function(a,n){var l=n.children&&n.children.length>0,c=o('<ul class=\"'+(n.spread?\"layui-show\":\"\")+'\"></ul>'),s=o([\"<li \"+(n.spread?'data-spread=\"'+n.spread+'\"':\"\")+\">\",function(){return l?'<i class=\"layui-icon layui-tree-spread\">'+(n.spread?t.arrow[1]:t.arrow[0])+\"</i>\":\"\"}(),function(){return r.check?'<i class=\"layui-icon layui-tree-check\">'+(\"checkbox\"===r.check?t.checkbox[0]:\"radio\"===r.check?t.radio[0]:\"\")+\"</i>\":\"\"}(),function(){return'<a href=\"'+(n.href||\"javascript:;\")+'\" '+(r.target&&n.href?'target=\"'+r.target+'\"':\"\")+\">\"+('<i class=\"layui-icon layui-tree-'+(l?\"branch\":\"leaf\")+'\">'+(l?n.spread?t.branch[1]:t.branch[0]:t.leaf)+\"</i>\")+(\"<cite>\"+(n.name||\"未命名\")+\"</cite></a>\")}(),\"</li>\"].join(\"\"));l&&(s.append(c),i.tree(c,n.children)),e.append(s),\"function\"==typeof r.click&&i.click(s,n),i.spread(s,n),r.drag&&i.drag(s,n)})},r.prototype.click=function(e,o){var a=this,i=a.options;e.children(\"a\").on(\"click\",function(e){layui.stope(e),i.click(o)})},r.prototype.spread=function(e,o){var a=this,i=(a.options,e.children(\".layui-tree-spread\")),r=e.children(\"ul\"),n=e.children(\"a\"),l=function(){e.data(\"spread\")?(e.data(\"spread\",null),r.removeClass(\"layui-show\"),i.html(t.arrow[0]),n.find(\".layui-icon\").html(t.branch[0])):(e.data(\"spread\",!0),r.addClass(\"layui-show\"),i.html(t.arrow[1]),n.find(\".layui-icon\").html(t.branch[1]))};r[0]&&(i.on(\"click\",l),n.on(\"dblclick\",l))},r.prototype.on=function(e){var a=this,r=a.options,t=\"layui-tree-drag\";e.find(\"i\").on(\"selectstart\",function(e){return!1}),r.drag&&o(document).on(\"mousemove\",function(e){var i=a.move;if(i.from){var r=(i.to,o('<div class=\"layui-box '+t+'\"></div>'));e.preventDefault(),o(\".\"+t)[0]||o(\"body\").append(r);var n=o(\".\"+t)[0]?o(\".\"+t):r;n.addClass(\"layui-show\").html(i.from.elem.children(\"a\").html()),n.css({left:e.pageX+10,top:e.pageY+10})}}).on(\"mouseup\",function(){var e=a.move;e.from&&(e.from.elem.children(\"a\").removeClass(i),e.to&&e.to.elem.children(\"a\").removeClass(i),a.move={},o(\".\"+t).remove())})},r.prototype.move={},r.prototype.drag=function(e,a){var r=this,t=(r.options,e.children(\"a\")),n=function(){var t=o(this),n=r.move;n.from&&(n.to={item:a,elem:e},t.addClass(i))};t.on(\"mousedown\",function(){var o=r.move;o.from={item:a,elem:e}}),t.on(\"mouseenter\",n).on(\"mousemove\",n).on(\"mouseleave\",function(){var e=o(this),a=r.move;a.from&&(delete a.to,e.removeClass(i))})},e(\"tree\",function(e){var i=new r(e=e||{}),t=o(e.elem);return t[0]?void i.init(t):a.error(\"layui.tree 没有找到\"+e.elem+\"元素\")})});"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/layui/lay/modules/upload.js",
    "content": "/** layui-v2.2.5 MIT License By https://www.layui.com */\n ;layui.define(\"layer\",function(e){\"use strict\";var i=layui.$,t=layui.layer,n=layui.hint(),a=layui.device(),o={config:{},set:function(e){var t=this;return t.config=i.extend({},t.config,e),t},on:function(e,i){return layui.onevent.call(this,r,e,i)}},l=function(){var e=this;return{upload:function(i){e.upload.call(e,i)},config:e.config}},r=\"upload\",u=\"layui-upload-file\",c=\"layui-upload-form\",f=\"layui-upload-iframe\",s=\"layui-upload-choose\",p=function(e){var t=this;t.config=i.extend({},t.config,o.config,e),t.render()};p.prototype.config={accept:\"images\",exts:\"\",auto:!0,bindAction:\"\",url:\"\",field:\"file\",method:\"post\",data:{},drag:!0,size:0,number:0,multiple:!1},p.prototype.render=function(e){var t=this,e=t.config;e.elem=i(e.elem),e.bindAction=i(e.bindAction),t.file(),t.events()},p.prototype.file=function(){var e=this,t=e.config,n=e.elemFile=i(['<input class=\"'+u+'\" type=\"file\" name=\"'+t.field+'\"',t.multiple?\" multiple\":\"\",\">\"].join(\"\")),o=t.elem.next();(o.hasClass(u)||o.hasClass(c))&&o.remove(),a.ie&&a.ie<10&&t.elem.wrap('<div class=\"layui-upload-wrap\"></div>'),e.isFile()?(e.elemFile=t.elem,t.field=t.elem[0].name):t.elem.after(n),a.ie&&a.ie<10&&e.initIE()},p.prototype.initIE=function(){var e=this,t=e.config,n=i('<iframe id=\"'+f+'\" class=\"'+f+'\" name=\"'+f+'\" frameborder=\"0\"></iframe>'),a=i(['<form target=\"'+f+'\" class=\"'+c+'\" method=\"'+t.method,'\" key=\"set-mine\" enctype=\"multipart/form-data\" action=\"'+t.url+'\">',\"</form>\"].join(\"\"));i(\"#\"+f)[0]||i(\"body\").append(n),t.elem.next().hasClass(f)||(e.elemFile.wrap(a),t.elem.next(\".\"+f).append(function(){var e=[];return layui.each(t.data,function(i,t){e.push('<input type=\"hidden\" name=\"'+i+'\" value=\"'+t+'\">')}),e.join(\"\")}()))},p.prototype.msg=function(e){return t.msg(e,{icon:2,shift:6})},p.prototype.isFile=function(){var e=this.config.elem[0];if(e)return\"input\"===e.tagName.toLocaleLowerCase()&&\"file\"===e.type},p.prototype.preview=function(e){var i=this;window.FileReader&&layui.each(i.chooseFiles,function(i,t){var n=new FileReader;n.readAsDataURL(t),n.onload=function(){e&&e(i,t,this.result)}})},p.prototype.upload=function(e,t){var n,o=this,l=o.config,r=o.elemFile[0],u=function(){var t=0,n=0,a=e||o.files||o.chooseFiles||r.files,u=function(){l.multiple&&t+n===o.fileLength&&\"function\"==typeof l.allDone&&l.allDone({total:o.fileLength,successful:t,aborted:n})};layui.each(a,function(e,a){var r=new FormData;r.append(l.field,a),layui.each(l.data,function(e,i){r.append(e,i)}),i.ajax({url:l.url,type:l.method,data:r,contentType:!1,processData:!1,dataType:\"json\",success:function(i){t++,d(e,i),u()},error:function(){n++,o.msg(\"请求上传接口出现异常\"),m(e),u()}})})},c=function(){var e=i(\"#\"+f);o.elemFile.parent().submit(),clearInterval(p.timer),p.timer=setInterval(function(){var i,t=e.contents().find(\"body\");try{i=t.text()}catch(n){o.msg(\"获取上传后的响应信息出现异常\"),clearInterval(p.timer),m()}i&&(clearInterval(p.timer),t.html(\"\"),d(0,i))},30)},d=function(e,i){if(o.elemFile.next(\".\"+s).remove(),r.value=\"\",\"object\"!=typeof i)try{i=JSON.parse(i)}catch(t){return i={},o.msg(\"请对上传接口返回有效JSON\")}\"function\"==typeof l.done&&l.done(i,e||0,function(e){o.upload(e)})},m=function(e){l.auto&&(r.value=\"\"),\"function\"==typeof l.error&&l.error(e||0,function(e){o.upload(e)})},h=l.exts,v=function(){var i=[];return layui.each(e||o.chooseFiles,function(e,t){i.push(t.name)}),i}(),g={preview:function(e){o.preview(e)},upload:function(e,i){var t={};t[e]=i,o.upload(t)},pushFile:function(){return o.files=o.files||{},layui.each(o.chooseFiles,function(e,i){o.files[e]=i}),o.files}},y=function(){return\"choose\"===t?l.choose&&l.choose(g):(l.before&&l.before(g),a.ie?a.ie>9?u():c():void u())};if(v=0===v.length?r.value.match(/[^\\/\\\\]+\\..+/g)||[]||\"\":v,0!==v.length){switch(l.accept){case\"file\":if(h&&!RegExp(\"\\\\w\\\\.(\"+h+\")$\",\"i\").test(escape(v)))return o.msg(\"选择的文件中包含不支持的格式\"),r.value=\"\";break;case\"video\":if(!RegExp(\"\\\\w\\\\.(\"+(h||\"avi|mp4|wma|rmvb|rm|flash|3gp|flv\")+\")$\",\"i\").test(escape(v)))return o.msg(\"选择的视频中包含不支持的格式\"),r.value=\"\";break;case\"audio\":if(!RegExp(\"\\\\w\\\\.(\"+(h||\"mp3|wav|mid\")+\")$\",\"i\").test(escape(v)))return o.msg(\"选择的音频中包含不支持的格式\"),r.value=\"\";break;default:if(layui.each(v,function(e,i){RegExp(\"\\\\w\\\\.(\"+(h||\"jpg|png|gif|bmp|jpeg$\")+\")\",\"i\").test(escape(i))||(n=!0)}),n)return o.msg(\"选择的图片中包含不支持的格式\"),r.value=\"\"}if(o.fileLength=function(){var i=0,t=e||o.files||o.chooseFiles||r.files;return layui.each(t,function(){i++}),i}(),l.number&&o.fileLength>l.number)return o.msg(\"同时最多只能上传的数量为：\"+l.number);if(l.size>0&&!(a.ie&&a.ie<10)){var F;if(layui.each(o.chooseFiles,function(e,i){if(i.size>1024*l.size){var t=l.size/1024;t=t>=1?Math.floor(t)+(t%1>0?t.toFixed(1):0)+\"MB\":l.size+\"KB\",r.value=\"\",F=t}}),F)return o.msg(\"文件不能超过\"+F)}y()}},p.prototype.events=function(){var e=this,t=e.config,o=function(i){e.chooseFiles={},layui.each(i,function(i,t){var n=(new Date).getTime();e.chooseFiles[n+\"-\"+i]=t})},l=function(i,n){var a=e.elemFile,o=i.length>1?i.length+\"个文件\":(i[0]||{}).name||a[0].value.match(/[^\\/\\\\]+\\..+/g)||[]||\"\";a.next().hasClass(s)&&a.next().remove(),e.upload(null,\"choose\"),e.isFile()||t.choose||a.after('<span class=\"layui-inline '+s+'\">'+o+\"</span>\")};t.elem.off(\"upload.start\").on(\"upload.start\",function(){var a=i(this),o=a.attr(\"lay-data\");if(o)try{o=new Function(\"return \"+o)(),e.config=i.extend({},t,o)}catch(l){n.error(\"Upload element property lay-data configuration item has a syntax error: \"+o)}e.config.item=a,e.elemFile[0].click()}),a.ie&&a.ie<10||t.elem.off(\"upload.over\").on(\"upload.over\",function(){var e=i(this);e.attr(\"lay-over\",\"\")}).off(\"upload.leave\").on(\"upload.leave\",function(){var e=i(this);e.removeAttr(\"lay-over\")}).off(\"upload.drop\").on(\"upload.drop\",function(n,a){var r=i(this),u=a.originalEvent.dataTransfer.files||[];r.removeAttr(\"lay-over\"),o(u),t.auto?e.upload(u):l(u)}),e.elemFile.off(\"upload.change\").on(\"upload.change\",function(){var i=this.files||[];o(i),t.auto?e.upload():l(i)}),t.bindAction.off(\"upload.action\").on(\"upload.action\",function(){e.upload()}),t.elem.data(\"haveEvents\")||(e.elemFile.on(\"change\",function(){i(this).trigger(\"upload.change\")}),t.elem.on(\"click\",function(){e.isFile()||i(this).trigger(\"upload.start\")}),t.drag&&t.elem.on(\"dragover\",function(e){e.preventDefault(),i(this).trigger(\"upload.over\")}).on(\"dragleave\",function(e){i(this).trigger(\"upload.leave\")}).on(\"drop\",function(e){e.preventDefault(),i(this).trigger(\"upload.drop\",e)}),t.bindAction.on(\"click\",function(){i(this).trigger(\"upload.action\")}),t.elem.data(\"haveEvents\",!0))},o.render=function(e){var i=new p(e);return l.call(i)},e(r,o)});"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/layui/lay/modules/util.js",
    "content": "/** layui-v2.2.5 MIT License By https://www.layui.com */\n ;layui.define(\"jquery\",function(e){\"use strict\";var t=layui.$,i={fixbar:function(e){var i,o,a=\"layui-fixbar\",r=\"layui-fixbar-top\",n=t(document),l=t(\"body\");e=t.extend({showHeight:200},e),e.bar1=e.bar1===!0?\"&#xe606;\":e.bar1,e.bar2=e.bar2===!0?\"&#xe607;\":e.bar2,e.bgcolor=e.bgcolor?\"background-color:\"+e.bgcolor:\"\";var c=[e.bar1,e.bar2,\"&#xe604;\"],g=t(['<ul class=\"'+a+'\">',e.bar1?'<li class=\"layui-icon\" lay-type=\"bar1\" style=\"'+e.bgcolor+'\">'+c[0]+\"</li>\":\"\",e.bar2?'<li class=\"layui-icon\" lay-type=\"bar2\" style=\"'+e.bgcolor+'\">'+c[1]+\"</li>\":\"\",'<li class=\"layui-icon '+r+'\" lay-type=\"top\" style=\"'+e.bgcolor+'\">'+c[2]+\"</li>\",\"</ul>\"].join(\"\")),s=g.find(\".\"+r),u=function(){var t=n.scrollTop();t>=e.showHeight?i||(s.show(),i=1):i&&(s.hide(),i=0)};t(\".\"+a)[0]||(\"object\"==typeof e.css&&g.css(e.css),l.append(g),u(),g.find(\"li\").on(\"click\",function(){var i=t(this),o=i.attr(\"lay-type\");\"top\"===o&&t(\"html,body\").animate({scrollTop:0},200),e.click&&e.click.call(this,o)}),n.on(\"scroll\",function(){clearTimeout(o),o=setTimeout(function(){u()},100)}))},countdown:function(e,t,i){var o=this,a=\"function\"==typeof t,r=new Date(e).getTime(),n=new Date(!t||a?(new Date).getTime():t).getTime(),l=r-n,c=[Math.floor(l/864e5),Math.floor(l/36e5)%24,Math.floor(l/6e4)%60,Math.floor(l/1e3)%60];a&&(i=t);var g=setTimeout(function(){o.countdown(e,n+1e3,i)},1e3);return i&&i(l>0?c:[0,0,0,0],t,g),l<=0&&clearTimeout(g),g},timeAgo:function(e,t){var i=this,o=[[],[]],a=(new Date).getTime()-new Date(e).getTime();return a>6912e5?(a=new Date(e),o[0][0]=i.digit(a.getFullYear(),4),o[0][1]=i.digit(a.getMonth()+1),o[0][2]=i.digit(a.getDate()),t||(o[1][0]=i.digit(a.getHours()),o[1][1]=i.digit(a.getMinutes()),o[1][2]=i.digit(a.getSeconds())),o[0].join(\"-\")+\" \"+o[1].join(\":\")):a>=864e5?(a/1e3/60/60/24|0)+\"天前\":a>=36e5?(a/1e3/60/60|0)+\"小时前\":a>=12e4?(a/1e3/60|0)+\"分钟前\":a<0?\"未来\":\"刚刚\"},digit:function(e,t){var i=\"\";e=String(e),t=t||2;for(var o=e.length;o<t;o++)i+=\"0\";return e<Math.pow(10,t)?i+(0|e):e},toDateString:function(e,t){var i=this,o=new Date(e||new Date),a=[i.digit(o.getFullYear(),4),i.digit(o.getMonth()+1),i.digit(o.getDate())],r=[i.digit(o.getHours()),i.digit(o.getMinutes()),i.digit(o.getSeconds())];return t=t||\"yyyy-MM-dd HH:mm:ss\",t.replace(/yyyy/g,a[0]).replace(/MM/g,a[1]).replace(/dd/g,a[2]).replace(/HH/g,r[0]).replace(/mm/g,r[1]).replace(/ss/g,r[2])}};e(\"util\",i)});"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/layui/layui.all.js",
    "content": "/** layui-v2.2.5 MIT License By https://www.layui.com */\n ;!function(e){\"use strict\";var t=document,n={modules:{},status:{},timeout:10,event:{}},o=function(){this.v=\"2.2.5\"},r=function(){var e=t.currentScript?t.currentScript.src:function(){for(var e,n=t.scripts,o=n.length-1,r=o;r>0;r--)if(\"interactive\"===n[r].readyState){e=n[r].src;break}return e||n[o].src}();return e.substring(0,e.lastIndexOf(\"/\")+1)}(),a=function(t){e.console&&console.error&&console.error(\"Layui hint: \"+t)},i=\"undefined\"!=typeof opera&&\"[object Opera]\"===opera.toString(),u={layer:\"modules/layer\",laydate:\"modules/laydate\",laypage:\"modules/laypage\",laytpl:\"modules/laytpl\",layim:\"modules/layim\",layedit:\"modules/layedit\",form:\"modules/form\",upload:\"modules/upload\",tree:\"modules/tree\",table:\"modules/table\",element:\"modules/element\",util:\"modules/util\",flow:\"modules/flow\",carousel:\"modules/carousel\",code:\"modules/code\",jquery:\"modules/jquery\",mobile:\"modules/mobile\",\"layui.all\":\"../layui.all\"};o.prototype.cache=n,o.prototype.define=function(e,t){var o=this,r=\"function\"==typeof e,a=function(){var e=function(e,t){layui[e]=t,n.status[e]=!0};return\"function\"==typeof t&&t(function(o,r){e(o,r),n.callback[o]=function(){t(e)}}),this};return r&&(t=e,e=[]),layui[\"layui.all\"]||!layui[\"layui.all\"]&&layui[\"layui.mobile\"]?a.call(o):(o.use(e,a),o)},o.prototype.use=function(e,o,l){function s(e,t){var o=\"PLaySTATION 3\"===navigator.platform?/^complete$/:/^(complete|loaded)$/;(\"load\"===e.type||o.test((e.currentTarget||e.srcElement).readyState))&&(n.modules[f]=t,d.removeChild(v),function r(){return++m>1e3*n.timeout/4?a(f+\" is not a valid module\"):void(n.status[f]?c():setTimeout(r,4))}())}function c(){l.push(layui[f]),e.length>1?y.use(e.slice(1),o,l):\"function\"==typeof o&&o.apply(layui,l)}var y=this,p=n.dir=n.dir?n.dir:r,d=t.getElementsByTagName(\"head\")[0];e=\"string\"==typeof e?[e]:e,window.jQuery&&jQuery.fn.on&&(y.each(e,function(t,n){\"jquery\"===n&&e.splice(t,1)}),layui.jquery=layui.$=jQuery);var f=e[0],m=0;if(l=l||[],n.host=n.host||(p.match(/\\/\\/([\\s\\S]+?)\\//)||[\"//\"+location.host+\"/\"])[0],0===e.length||layui[\"layui.all\"]&&u[f]||!layui[\"layui.all\"]&&layui[\"layui.mobile\"]&&u[f])return c(),y;if(n.modules[f])!function g(){return++m>1e3*n.timeout/4?a(f+\" is not a valid module\"):void(\"string\"==typeof n.modules[f]&&n.status[f]?c():setTimeout(g,4))}();else{var v=t.createElement(\"script\"),h=(u[f]?p+\"lay/\":/^\\{\\/\\}/.test(y.modules[f])?\"\":n.base||\"\")+(y.modules[f]||f)+\".js\";h=h.replace(/^\\{\\/\\}/,\"\"),v.async=!0,v.charset=\"utf-8\",v.src=h+function(){var e=n.version===!0?n.v||(new Date).getTime():n.version||\"\";return e?\"?v=\"+e:\"\"}(),d.appendChild(v),!v.attachEvent||v.attachEvent.toString&&v.attachEvent.toString().indexOf(\"[native code\")<0||i?v.addEventListener(\"load\",function(e){s(e,h)},!1):v.attachEvent(\"onreadystatechange\",function(e){s(e,h)}),n.modules[f]=h}return y},o.prototype.getStyle=function(t,n){var o=t.currentStyle?t.currentStyle:e.getComputedStyle(t,null);return o[o.getPropertyValue?\"getPropertyValue\":\"getAttribute\"](n)},o.prototype.link=function(e,o,r){var i=this,u=t.createElement(\"link\"),l=t.getElementsByTagName(\"head\")[0];\"string\"==typeof o&&(r=o);var s=(r||e).replace(/\\.|\\//g,\"\"),c=u.id=\"layuicss-\"+s,y=0;return u.rel=\"stylesheet\",u.href=e+(n.debug?\"?v=\"+(new Date).getTime():\"\"),u.media=\"all\",t.getElementById(c)||l.appendChild(u),\"function\"!=typeof o?i:(function p(){return++y>1e3*n.timeout/100?a(e+\" timeout\"):void(1989===parseInt(i.getStyle(t.getElementById(c),\"width\"))?function(){o()}():setTimeout(p,100))}(),i)},n.callback={},o.prototype.factory=function(e){if(layui[e])return\"function\"==typeof n.callback[e]?n.callback[e]:null},o.prototype.addcss=function(e,t,o){return layui.link(n.dir+\"css/\"+e,t,o)},o.prototype.img=function(e,t,n){var o=new Image;return o.src=e,o.complete?t(o):(o.onload=function(){o.onload=null,t(o)},void(o.onerror=function(e){o.onerror=null,n(e)}))},o.prototype.config=function(e){e=e||{};for(var t in e)n[t]=e[t];return this},o.prototype.modules=function(){var e={};for(var t in u)e[t]=u[t];return e}(),o.prototype.extend=function(e){var t=this;e=e||{};for(var n in e)t[n]||t.modules[n]?a(\"模块名 \"+n+\" 已被占用\"):t.modules[n]=e[n];return t},o.prototype.router=function(e){var t=this,e=e||location.hash,n={path:[],search:{},hash:(e.match(/[^#](#.*$)/)||[])[1]||\"\"};return/^#\\//.test(e)?(n.href=e=e.replace(/^#\\//,\"\"),e=e.replace(/([^#])(#.*$)/,\"$1\").split(\"/\")||[],t.each(e,function(e,t){/^\\w+=/.test(t)?function(){t=t.split(\"=\"),n.search[t[0]]=t[1]}():n.path.push(t)}),n):n},o.prototype.data=function(t,n,o){if(t=t||\"layui\",o=o||localStorage,e.JSON&&e.JSON.parse){if(null===n)return delete o[t];n=\"object\"==typeof n?n:{key:n};try{var r=JSON.parse(o[t])}catch(a){var r={}}return\"value\"in n&&(r[n.key]=n.value),n.remove&&delete r[n.key],o[t]=JSON.stringify(r),n.key?r[n.key]:r}},o.prototype.sessionData=function(e,t){return this.data(e,t,sessionStorage)},o.prototype.device=function(t){var n=navigator.userAgent.toLowerCase(),o=function(e){var t=new RegExp(e+\"/([^\\\\s\\\\_\\\\-]+)\");return e=(n.match(t)||[])[1],e||!1},r={os:function(){return/windows/.test(n)?\"windows\":/linux/.test(n)?\"linux\":/iphone|ipod|ipad|ios/.test(n)?\"ios\":/mac/.test(n)?\"mac\":void 0}(),ie:function(){return!!(e.ActiveXObject||\"ActiveXObject\"in e)&&((n.match(/msie\\s(\\d+)/)||[])[1]||\"11\")}(),weixin:o(\"micromessenger\")};return t&&!r[t]&&(r[t]=o(t)),r.android=/android/.test(n),r.ios=\"ios\"===r.os,r},o.prototype.hint=function(){return{error:a}},o.prototype.each=function(e,t){var n,o=this;if(\"function\"!=typeof t)return o;if(e=e||[],e.constructor===Object){for(n in e)if(t.call(e[n],n,e[n]))break}else for(n=0;n<e.length&&!t.call(e[n],n,e[n]);n++);return o},o.prototype.sort=function(e,t,n){var o=JSON.parse(JSON.stringify(e||[]));return t?(o.sort(function(e,n){var o=/^-?\\d+$/,r=e[t],a=n[t];return o.test(r)&&(r=parseFloat(r)),o.test(a)&&(a=parseFloat(a)),r&&!a?1:!r&&a?-1:r>a?1:r<a?-1:0}),n&&o.reverse(),o):o},o.prototype.stope=function(t){t=t||e.event;try{t.stopPropagation()}catch(n){t.cancelBubble=!0}},o.prototype.onevent=function(e,t,n){return\"string\"!=typeof e||\"function\"!=typeof n?this:o.event(e,t,null,n)},o.prototype.event=o.event=function(e,t,o,r){var a=this,i=null,u=t.match(/\\((.*)\\)$/)||[],l=(e+\".\"+t).replace(u[0],\"\"),s=u[1]||\"\",c=function(e,t){var n=t&&t.call(a,o);n===!1&&null===i&&(i=!1)};return r?(n.event[l]=n.event[l]||{},n.event[l][s]=[r],this):(layui.each(n.event[l],function(e,t){return\"{*}\"===s?void layui.each(t,c):(\"\"===e&&layui.each(t,c),void(e===s&&layui.each(t,c)))}),i)},e.layui=new o}(window);layui.define(function(a){var i=layui.cache;layui.config({dir:i.dir.replace(/lay\\/dest\\/$/,\"\")}),a(\"layui.all\",layui.v)});layui.define(function(e){\"use strict\";var r={open:\"{{\",close:\"}}\"},c={exp:function(e){return new RegExp(e,\"g\")},query:function(e,c,t){var o=[\"#([\\\\s\\\\S])+?\",\"([^{#}])*?\"][e||0];return n((c||\"\")+r.open+o+r.close+(t||\"\"))},escape:function(e){return String(e||\"\").replace(/&(?!#?[a-zA-Z0-9]+;)/g,\"&amp;\").replace(/</g,\"&lt;\").replace(/>/g,\"&gt;\").replace(/'/g,\"&#39;\").replace(/\"/g,\"&quot;\")},error:function(e,r){var c=\"Laytpl Error：\";return\"object\"==typeof console&&console.error(c+e+\"\\n\"+(r||\"\")),c+e}},n=c.exp,t=function(e){this.tpl=e};t.pt=t.prototype,window.errors=0,t.pt.parse=function(e,t){var o=this,p=e,a=n(\"^\"+r.open+\"#\",\"\"),l=n(r.close+\"$\",\"\");e=e.replace(/\\s+|\\r|\\t|\\n/g,\" \").replace(n(r.open+\"#\"),r.open+\"# \").replace(n(r.close+\"}\"),\"} \"+r.close).replace(/\\\\/g,\"\\\\\\\\\").replace(n(r.open+\"!(.+?)!\"+r.close),function(e){return e=e.replace(n(\"^\"+r.open+\"!\"),\"\").replace(n(\"!\"+r.close),\"\").replace(n(r.open+\"|\"+r.close),function(e){return e.replace(/(.)/g,\"\\\\$1\")})}).replace(/(?=\"|')/g,\"\\\\\").replace(c.query(),function(e){return e=e.replace(a,\"\").replace(l,\"\"),'\";'+e.replace(/\\\\/g,\"\")+';view+=\"'}).replace(c.query(1),function(e){var c='\"+(';return e.replace(/\\s/g,\"\")===r.open+r.close?\"\":(e=e.replace(n(r.open+\"|\"+r.close),\"\"),/^=/.test(e)&&(e=e.replace(/^=/,\"\"),c='\"+_escape_('),c+e.replace(/\\\\/g,\"\")+')+\"')}),e='\"use strict\";var view = \"'+e+'\";return view;';try{return o.cache=e=new Function(\"d, _escape_\",e),e(t,c.escape)}catch(u){return delete o.cache,c.error(u,p)}},t.pt.render=function(e,r){var n,t=this;return e?(n=t.cache?t.cache(e,c.escape):t.parse(t.tpl,e),r?void r(n):n):c.error(\"no data\")};var o=function(e){return\"string\"!=typeof e?c.error(\"Template not found\"):new t(e)};o.config=function(e){e=e||{};for(var c in e)r[c]=e[c]},o.v=\"1.2.0\",e(\"laytpl\",o)});layui.define(function(e){\"use strict\";var a=document,t=\"getElementById\",n=\"getElementsByTagName\",i=\"laypage\",r=\"layui-disabled\",u=function(e){var a=this;a.config=e||{},a.config.index=++s.index,a.render(!0)};u.prototype.type=function(){var e=this.config;if(\"object\"==typeof e.elem)return void 0===e.elem.length?2:3},u.prototype.view=function(){var e=this,a=e.config,t=a.groups=\"groups\"in a?0|a.groups:5;a.layout=\"object\"==typeof a.layout?a.layout:[\"prev\",\"page\",\"next\"],a.count=0|a.count,a.curr=0|a.curr||1,a.limits=\"object\"==typeof a.limits?a.limits:[10,20,30,40,50],a.limit=0|a.limit||10,a.pages=Math.ceil(a.count/a.limit)||1,a.curr>a.pages&&(a.curr=a.pages),t<0?t=1:t>a.pages&&(t=a.pages),a.prev=\"prev\"in a?a.prev:\"&#x4E0A;&#x4E00;&#x9875;\",a.next=\"next\"in a?a.next:\"&#x4E0B;&#x4E00;&#x9875;\";var n=a.pages>t?Math.ceil((a.curr+(t>1?1:0))/(t>0?t:1)):1,i={prev:function(){return a.prev?'<a href=\"javascript:;\" class=\"layui-laypage-prev'+(1==a.curr?\" \"+r:\"\")+'\" data-page=\"'+(a.curr-1)+'\">'+a.prev+\"</a>\":\"\"}(),page:function(){var e=[];if(a.count<1)return\"\";n>1&&a.first!==!1&&0!==t&&e.push('<a href=\"javascript:;\" class=\"layui-laypage-first\" data-page=\"1\"  title=\"&#x9996;&#x9875;\">'+(a.first||1)+\"</a>\");var i=Math.floor((t-1)/2),r=n>1?a.curr-i:1,u=n>1?function(){var e=a.curr+(t-i-1);return e>a.pages?a.pages:e}():t;for(u-r<t-1&&(r=u-t+1),a.first!==!1&&r>2&&e.push('<span class=\"layui-laypage-spr\">&#x2026;</span>');r<=u;r++)r===a.curr?e.push('<span class=\"layui-laypage-curr\"><em class=\"layui-laypage-em\" '+(/^#/.test(a.theme)?'style=\"background-color:'+a.theme+';\"':\"\")+\"></em><em>\"+r+\"</em></span>\"):e.push('<a href=\"javascript:;\" data-page=\"'+r+'\">'+r+\"</a>\");return a.pages>t&&a.pages>u&&a.last!==!1&&(u+1<a.pages&&e.push('<span class=\"layui-laypage-spr\">&#x2026;</span>'),0!==t&&e.push('<a href=\"javascript:;\" class=\"layui-laypage-last\" title=\"&#x5C3E;&#x9875;\"  data-page=\"'+a.pages+'\">'+(a.last||a.pages)+\"</a>\")),e.join(\"\")}(),next:function(){return a.next?'<a href=\"javascript:;\" class=\"layui-laypage-next'+(a.curr==a.pages?\" \"+r:\"\")+'\" data-page=\"'+(a.curr+1)+'\">'+a.next+\"</a>\":\"\"}(),count:'<span class=\"layui-laypage-count\">共 '+a.count+\" 条</span>\",limit:function(){var e=['<span class=\"layui-laypage-limits\"><select lay-ignore>'];return layui.each(a.limits,function(t,n){e.push('<option value=\"'+n+'\"'+(n===a.limit?\"selected\":\"\")+\">\"+n+\" 条/页</option>\")}),e.join(\"\")+\"</select></span>\"}(),skip:function(){return['<span class=\"layui-laypage-skip\">&#x5230;&#x7B2C;','<input type=\"text\" min=\"1\" value=\"'+a.curr+'\" class=\"layui-input\">','&#x9875;<button type=\"button\" class=\"layui-laypage-btn\">&#x786e;&#x5b9a;</button>',\"</span>\"].join(\"\")}()};return['<div class=\"layui-box layui-laypage layui-laypage-'+(a.theme?/^#/.test(a.theme)?\"molv\":a.theme:\"default\")+'\" id=\"layui-laypage-'+a.index+'\">',function(){var e=[];return layui.each(a.layout,function(a,t){i[t]&&e.push(i[t])}),e.join(\"\")}(),\"</div>\"].join(\"\")},u.prototype.jump=function(e,a){if(e){var t=this,i=t.config,r=e.children,u=e[n](\"button\")[0],l=e[n](\"input\")[0],p=e[n](\"select\")[0],c=function(){var e=0|l.value.replace(/\\s|\\D/g,\"\");e&&(i.curr=e,t.render())};if(a)return c();for(var o=0,y=r.length;o<y;o++)\"a\"===r[o].nodeName.toLowerCase()&&s.on(r[o],\"click\",function(){var e=0|this.getAttribute(\"data-page\");e<1||e>i.pages||(i.curr=e,t.render())});p&&s.on(p,\"change\",function(){var e=this.value;i.curr*e>i.count&&(i.curr=Math.ceil(i.count/e)),i.limit=e,t.render()}),u&&s.on(u,\"click\",function(){c()})}},u.prototype.skip=function(e){if(e){var a=this,t=e[n](\"input\")[0];t&&s.on(t,\"keyup\",function(t){var n=this.value,i=t.keyCode;/^(37|38|39|40)$/.test(i)||(/\\D/.test(n)&&(this.value=n.replace(/\\D/,\"\")),13===i&&a.jump(e,!0))})}},u.prototype.render=function(e){var n=this,i=n.config,r=n.type(),u=n.view();2===r?i.elem&&(i.elem.innerHTML=u):3===r?i.elem.html(u):a[t](i.elem)&&(a[t](i.elem).innerHTML=u),i.jump&&i.jump(i,e);var s=a[t](\"layui-laypage-\"+i.index);n.jump(s),i.hash&&!e&&(location.hash=\"!\"+i.hash+\"=\"+i.curr),n.skip(s)};var s={render:function(e){var a=new u(e);return a.index},index:layui.laypage?layui.laypage.index+1e4:0,on:function(e,a,t){return e.attachEvent?e.attachEvent(\"on\"+a,function(a){a.target=a.srcElement,t.call(e,a)}):e.addEventListener(a,t,!1),this}};e(i,s)});!function(){\"use strict\";var e=window.layui&&layui.define,t={getPath:function(){var e=document.currentScript?document.currentScript.src:function(){for(var e,t=document.scripts,n=t.length-1,a=n;a>0;a--)if(\"interactive\"===t[a].readyState){e=t[a].src;break}return e||t[n].src}();return e.substring(0,e.lastIndexOf(\"/\")+1)}(),getStyle:function(e,t){var n=e.currentStyle?e.currentStyle:window.getComputedStyle(e,null);return n[n.getPropertyValue?\"getPropertyValue\":\"getAttribute\"](t)},link:function(e,a,i){if(n.path){var r=document.getElementsByTagName(\"head\")[0],o=document.createElement(\"link\");\"string\"==typeof a&&(i=a);var s=(i||e).replace(/\\.|\\//g,\"\"),l=\"layuicss-\"+s,d=0;o.rel=\"stylesheet\",o.href=n.path+e,o.id=l,document.getElementById(l)||r.appendChild(o),\"function\"==typeof a&&!function c(){return++d>80?window.console&&console.error(\"laydate.css: Invalid\"):void(1989===parseInt(t.getStyle(document.getElementById(l),\"width\"))?a():setTimeout(c,100))}()}}},n={v:\"5.0.9\",config:{},index:window.laydate&&window.laydate.v?1e5:0,path:t.getPath,set:function(e){var t=this;return t.config=w.extend({},t.config,e),t},ready:function(a){var i=\"laydate\",r=\"\",o=(e?\"modules/laydate/\":\"theme/\")+\"default/laydate.css?v=\"+n.v+r;return e?layui.addcss(o,a,i):t.link(o,a,i),this}},a=function(){var e=this;return{hint:function(t){e.hint.call(e,t)},config:e.config}},i=\"laydate\",r=\".layui-laydate\",o=\"layui-this\",s=\"laydate-disabled\",l=\"开始日期超出了结束日期<br>建议重新选择\",d=[100,2e5],c=\"layui-laydate-static\",m=\"layui-laydate-list\",u=\"laydate-selected\",h=\"layui-laydate-hint\",y=\"laydate-day-prev\",f=\"laydate-day-next\",p=\"layui-laydate-footer\",g=\".laydate-btns-confirm\",v=\"laydate-time-text\",D=\".laydate-btns-time\",T=function(e){var t=this;t.index=++n.index,t.config=w.extend({},t.config,n.config,e),n.ready(function(){t.init()})},w=function(e){return new C(e)},C=function(e){for(var t=0,n=\"object\"==typeof e?[e]:(this.selector=e,document.querySelectorAll(e||null));t<n.length;t++)this.push(n[t])};C.prototype=[],C.prototype.constructor=C,w.extend=function(){var e=1,t=arguments,n=function(e,t){e=e||(t.constructor===Array?[]:{});for(var a in t)e[a]=t[a]&&t[a].constructor===Object?n(e[a],t[a]):t[a];return e};for(t[0]=\"object\"==typeof t[0]?t[0]:{};e<t.length;e++)\"object\"==typeof t[e]&&n(t[0],t[e]);return t[0]},w.ie=function(){var e=navigator.userAgent.toLowerCase();return!!(window.ActiveXObject||\"ActiveXObject\"in window)&&((e.match(/msie\\s(\\d+)/)||[])[1]||\"11\")}(),w.stope=function(e){e=e||window.event,e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},w.each=function(e,t){var n,a=this;if(\"function\"!=typeof t)return a;if(e=e||[],e.constructor===Object){for(n in e)if(t.call(e[n],n,e[n]))break}else for(n=0;n<e.length&&!t.call(e[n],n,e[n]);n++);return a},w.digit=function(e,t,n){var a=\"\";e=String(e),t=t||2;for(var i=e.length;i<t;i++)a+=\"0\";return e<Math.pow(10,t)?a+(0|e):e},w.elem=function(e,t){var n=document.createElement(e);return w.each(t||{},function(e,t){n.setAttribute(e,t)}),n},C.addStr=function(e,t){return e=e.replace(/\\s+/,\" \"),t=t.replace(/\\s+/,\" \").split(\" \"),w.each(t,function(t,n){new RegExp(\"\\\\b\"+n+\"\\\\b\").test(e)||(e=e+\" \"+n)}),e.replace(/^\\s|\\s$/,\"\")},C.removeStr=function(e,t){return e=e.replace(/\\s+/,\" \"),t=t.replace(/\\s+/,\" \").split(\" \"),w.each(t,function(t,n){var a=new RegExp(\"\\\\b\"+n+\"\\\\b\");a.test(e)&&(e=e.replace(a,\"\"))}),e.replace(/\\s+/,\" \").replace(/^\\s|\\s$/,\"\")},C.prototype.find=function(e){var t=this,n=0,a=[],i=\"object\"==typeof e;return this.each(function(r,o){for(var s=i?[e]:o.querySelectorAll(e||null);n<s.length;n++)a.push(s[n]);t.shift()}),i||(t.selector=(t.selector?t.selector+\" \":\"\")+e),w.each(a,function(e,n){t.push(n)}),t},C.prototype.each=function(e){return w.each.call(this,this,e)},C.prototype.addClass=function(e,t){return this.each(function(n,a){a.className=C[t?\"removeStr\":\"addStr\"](a.className,e)})},C.prototype.removeClass=function(e){return this.addClass(e,!0)},C.prototype.hasClass=function(e){var t=!1;return this.each(function(n,a){new RegExp(\"\\\\b\"+e+\"\\\\b\").test(a.className)&&(t=!0)}),t},C.prototype.attr=function(e,t){var n=this;return void 0===t?function(){if(n.length>0)return n[0].getAttribute(e)}():n.each(function(n,a){a.setAttribute(e,t)})},C.prototype.removeAttr=function(e){return this.each(function(t,n){n.removeAttribute(e)})},C.prototype.html=function(e){return this.each(function(t,n){n.innerHTML=e})},C.prototype.val=function(e){return this.each(function(t,n){n.value=e})},C.prototype.append=function(e){return this.each(function(t,n){\"object\"==typeof e?n.appendChild(e):n.innerHTML=n.innerHTML+e})},C.prototype.remove=function(e){return this.each(function(t,n){e?n.removeChild(e):n.parentNode.removeChild(n)})},C.prototype.on=function(e,t){return this.each(function(n,a){a.attachEvent?a.attachEvent(\"on\"+e,function(e){e.target=e.srcElement,t.call(a,e)}):a.addEventListener(e,t,!1)})},C.prototype.off=function(e,t){return this.each(function(n,a){a.detachEvent?a.detachEvent(\"on\"+e,t):a.removeEventListener(e,t,!1)})},T.isLeapYear=function(e){return e%4===0&&e%100!==0||e%400===0},T.prototype.config={type:\"date\",range:!1,format:\"yyyy-MM-dd\",value:null,min:\"1900-1-1\",max:\"2099-12-31\",trigger:\"focus\",show:!1,showBottom:!0,btns:[\"clear\",\"now\",\"confirm\"],lang:\"cn\",theme:\"default\",position:null,calendar:!1,mark:{},zIndex:null,done:null,change:null},T.prototype.lang=function(){var e=this,t=e.config,n={cn:{weeks:[\"日\",\"一\",\"二\",\"三\",\"四\",\"五\",\"六\"],time:[\"时\",\"分\",\"秒\"],timeTips:\"选择时间\",startTime:\"开始时间\",endTime:\"结束时间\",dateTips:\"返回日期\",month:[\"一\",\"二\",\"三\",\"四\",\"五\",\"六\",\"七\",\"八\",\"九\",\"十\",\"十一\",\"十二\"],tools:{confirm:\"确定\",clear:\"清空\",now:\"现在\"}},en:{weeks:[\"Su\",\"Mo\",\"Tu\",\"We\",\"Th\",\"Fr\",\"Sa\"],time:[\"Hours\",\"Minutes\",\"Seconds\"],timeTips:\"Select Time\",startTime:\"Start Time\",endTime:\"End Time\",dateTips:\"Select Date\",month:[\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\"],tools:{confirm:\"Confirm\",clear:\"Clear\",now:\"Now\"}}};return n[t.lang]||n.cn},T.prototype.init=function(){var e=this,t=e.config,n=\"yyyy|y|MM|M|dd|d|HH|H|mm|m|ss|s\",a=\"static\"===t.position,i={year:\"yyyy\",month:\"yyyy-MM\",date:\"yyyy-MM-dd\",time:\"HH:mm:ss\",datetime:\"yyyy-MM-dd HH:mm:ss\"};t.elem=w(t.elem),t.eventElem=w(t.eventElem),t.elem[0]&&(t.range===!0&&(t.range=\"-\"),t.format===i.date&&(t.format=i[t.type]),e.format=t.format.match(new RegExp(n+\"|.\",\"g\"))||[],e.EXP_IF=\"\",e.EXP_SPLIT=\"\",w.each(e.format,function(t,a){var i=new RegExp(n).test(a)?\"\\\\d{\"+function(){return new RegExp(n).test(e.format[0===t?t+1:t-1]||\"\")?/^yyyy|y$/.test(a)?4:a.length:/^yyyy$/.test(a)?\"1,4\":/^y$/.test(a)?\"1,308\":\"1,2\"}()+\"}\":\"\\\\\"+a;e.EXP_IF=e.EXP_IF+i,e.EXP_SPLIT=e.EXP_SPLIT+\"(\"+i+\")\"}),e.EXP_IF=new RegExp(\"^\"+(t.range?e.EXP_IF+\"\\\\s\\\\\"+t.range+\"\\\\s\"+e.EXP_IF:e.EXP_IF)+\"$\"),e.EXP_SPLIT=new RegExp(\"^\"+e.EXP_SPLIT+\"$\",\"\"),e.isInput(t.elem[0])||\"focus\"===t.trigger&&(t.trigger=\"click\"),t.elem.attr(\"lay-key\")||(t.elem.attr(\"lay-key\",e.index),t.eventElem.attr(\"lay-key\",e.index)),t.mark=w.extend({},t.calendar&&\"cn\"===t.lang?{\"0-1-1\":\"元旦\",\"0-2-14\":\"情人\",\"0-3-8\":\"妇女\",\"0-3-12\":\"植树\",\"0-4-1\":\"愚人\",\"0-5-1\":\"劳动\",\"0-5-4\":\"青年\",\"0-6-1\":\"儿童\",\"0-9-10\":\"教师\",\"0-9-18\":\"国耻\",\"0-10-1\":\"国庆\",\"0-12-25\":\"圣诞\"}:{},t.mark),w.each([\"min\",\"max\"],function(e,n){var a=[],i=[];if(\"number\"==typeof t[n]){var r=t[n],o=(new Date).getTime(),s=864e5,l=new Date(r?r<s?o+r*s:r:o);a=[l.getFullYear(),l.getMonth()+1,l.getDate()],r<s||(i=[l.getHours(),l.getMinutes(),l.getSeconds()])}else a=(t[n].match(/\\d+-\\d+-\\d+/)||[\"\"])[0].split(\"-\"),i=(t[n].match(/\\d+:\\d+:\\d+/)||[\"\"])[0].split(\":\");t[n]={year:0|a[0]||(new Date).getFullYear(),month:a[1]?(0|a[1])-1:(new Date).getMonth(),date:0|a[2]||(new Date).getDate(),hours:0|i[0],minutes:0|i[1],seconds:0|i[2]}}),e.elemID=\"layui-laydate\"+t.elem.attr(\"lay-key\"),(t.show||a)&&e.render(),a||e.events(),t.value&&(t.value.constructor===Date?e.setValue(e.parse(0,e.systemDate(t.value))):e.setValue(t.value)))},T.prototype.render=function(){var e=this,t=e.config,n=e.lang(),a=\"static\"===t.position,i=e.elem=w.elem(\"div\",{id:e.elemID,\"class\":[\"layui-laydate\",t.range?\" layui-laydate-range\":\"\",a?\" \"+c:\"\",t.theme&&\"default\"!==t.theme&&!/^#/.test(t.theme)?\" laydate-theme-\"+t.theme:\"\"].join(\"\")}),r=e.elemMain=[],o=e.elemHeader=[],s=e.elemCont=[],l=e.table=[],d=e.footer=w.elem(\"div\",{\"class\":p});if(t.zIndex&&(i.style.zIndex=t.zIndex),w.each(new Array(2),function(e){if(!t.range&&e>0)return!0;var a=w.elem(\"div\",{\"class\":\"layui-laydate-header\"}),i=[function(){var e=w.elem(\"i\",{\"class\":\"layui-icon laydate-icon laydate-prev-y\"});return e.innerHTML=\"&#xe65a;\",e}(),function(){var e=w.elem(\"i\",{\"class\":\"layui-icon laydate-icon laydate-prev-m\"});return e.innerHTML=\"&#xe603;\",e}(),function(){var e=w.elem(\"div\",{\"class\":\"laydate-set-ym\"}),t=w.elem(\"span\"),n=w.elem(\"span\");return e.appendChild(t),e.appendChild(n),e}(),function(){var e=w.elem(\"i\",{\"class\":\"layui-icon laydate-icon laydate-next-m\"});return e.innerHTML=\"&#xe602;\",e}(),function(){var e=w.elem(\"i\",{\"class\":\"layui-icon laydate-icon laydate-next-y\"});return e.innerHTML=\"&#xe65b;\",e}()],d=w.elem(\"div\",{\"class\":\"layui-laydate-content\"}),c=w.elem(\"table\"),m=w.elem(\"thead\"),u=w.elem(\"tr\");w.each(i,function(e,t){a.appendChild(t)}),m.appendChild(u),w.each(new Array(6),function(e){var t=c.insertRow(0);w.each(new Array(7),function(a){if(0===e){var i=w.elem(\"th\");i.innerHTML=n.weeks[a],u.appendChild(i)}t.insertCell(a)})}),c.insertBefore(m,c.children[0]),d.appendChild(c),r[e]=w.elem(\"div\",{\"class\":\"layui-laydate-main laydate-main-list-\"+e}),r[e].appendChild(a),r[e].appendChild(d),o.push(i),s.push(d),l.push(c)}),w(d).html(function(){var e=[],i=[];return\"datetime\"===t.type&&e.push('<span lay-type=\"datetime\" class=\"laydate-btns-time\">'+n.timeTips+\"</span>\"),w.each(t.btns,function(e,r){var o=n.tools[r]||\"btn\";t.range&&\"now\"===r||(a&&\"clear\"===r&&(o=\"cn\"===t.lang?\"重置\":\"Reset\"),i.push('<span lay-type=\"'+r+'\" class=\"laydate-btns-'+r+'\">'+o+\"</span>\"))}),e.push('<div class=\"laydate-footer-btns\">'+i.join(\"\")+\"</div>\"),e.join(\"\")}()),w.each(r,function(e,t){i.appendChild(t)}),t.showBottom&&i.appendChild(d),/^#/.test(t.theme)){var m=w.elem(\"style\"),u=[\"#{{id}} .layui-laydate-header{background-color:{{theme}};}\",\"#{{id}} .layui-this{background-color:{{theme}} !important;}\"].join(\"\").replace(/{{id}}/g,e.elemID).replace(/{{theme}}/g,t.theme);\"styleSheet\"in m?(m.setAttribute(\"type\",\"text/css\"),m.styleSheet.cssText=u):m.innerHTML=u,w(i).addClass(\"laydate-theme-molv\"),i.appendChild(m)}e.remove(T.thisElemDate),a?t.elem.append(i):(document.body.appendChild(i),e.position()),e.checkDate().calendar(),e.changeEvent(),T.thisElemDate=e.elemID,\"function\"==typeof t.ready&&t.ready(w.extend({},t.dateTime,{month:t.dateTime.month+1}))},T.prototype.remove=function(e){var t=this,n=(t.config,w(\"#\"+(e||t.elemID)));return n.hasClass(c)||t.checkDate(function(){n.remove()}),t},T.prototype.position=function(){var e=this,t=e.config,n=e.bindElem||t.elem[0],a=n.getBoundingClientRect(),i=e.elem.offsetWidth,r=e.elem.offsetHeight,o=function(e){return e=e?\"scrollLeft\":\"scrollTop\",document.body[e]|document.documentElement[e]},s=function(e){return document.documentElement[e?\"clientWidth\":\"clientHeight\"]},l=5,d=a.left,c=a.bottom;d+i+l>s(\"width\")&&(d=s(\"width\")-i-l),c+r+l>s()&&(c=a.top>r?a.top-r:s()-r,c-=2*l),t.position&&(e.elem.style.position=t.position),e.elem.style.left=d+(\"fixed\"===t.position?0:o(1))+\"px\",e.elem.style.top=c+(\"fixed\"===t.position?0:o())+\"px\"},T.prototype.hint=function(e){var t=this,n=(t.config,w.elem(\"div\",{\"class\":h}));n.innerHTML=e||\"\",w(t.elem).find(\".\"+h).remove(),t.elem.appendChild(n),clearTimeout(t.hinTimer),t.hinTimer=setTimeout(function(){w(t.elem).find(\".\"+h).remove()},3e3)},T.prototype.getAsYM=function(e,t,n){return n?t--:t++,t<0&&(t=11,e--),t>11&&(t=0,e++),[e,t]},T.prototype.systemDate=function(e){var t=e||new Date;return{year:t.getFullYear(),month:t.getMonth(),date:t.getDate(),hours:e?e.getHours():0,minutes:e?e.getMinutes():0,seconds:e?e.getSeconds():0}},T.prototype.checkDate=function(e){var t,a,i=this,r=(new Date,i.config),o=r.dateTime=r.dateTime||i.systemDate(),s=i.bindElem||r.elem[0],l=(i.isInput(s)?\"val\":\"html\",i.isInput(s)?s.value:\"static\"===r.position?\"\":s.innerHTML),c=function(e){e.year>d[1]&&(e.year=d[1],a=!0),e.month>11&&(e.month=11,a=!0),e.hours>23&&(e.hours=0,a=!0),e.minutes>59&&(e.minutes=0,e.hours++,a=!0),e.seconds>59&&(e.seconds=0,e.minutes++,a=!0),t=n.getEndDate(e.month+1,e.year),e.date>t&&(e.date=t,a=!0)},m=function(e,t,n){var o=[\"startTime\",\"endTime\"];t=(t.match(i.EXP_SPLIT)||[]).slice(1),n=n||0,r.range&&(i[o[n]]=i[o[n]]||{}),w.each(i.format,function(s,l){var c=parseFloat(t[s]);t[s].length<l.length&&(a=!0),/yyyy|y/.test(l)?(c<d[0]&&(c=d[0],a=!0),e.year=c):/MM|M/.test(l)?(c<1&&(c=1,a=!0),e.month=c-1):/dd|d/.test(l)?(c<1&&(c=1,a=!0),e.date=c):/HH|H/.test(l)?(c<1&&(c=0,a=!0),e.hours=c,r.range&&(i[o[n]].hours=c)):/mm|m/.test(l)?(c<1&&(c=0,a=!0),e.minutes=c,r.range&&(i[o[n]].minutes=c)):/ss|s/.test(l)&&(c<1&&(c=0,a=!0),e.seconds=c,r.range&&(i[o[n]].seconds=c))}),c(e)};return\"limit\"===e?(c(o),i):(l=l||r.value,\"string\"==typeof l&&(l=l.replace(/\\s+/g,\" \").replace(/^\\s|\\s$/g,\"\")),i.startState&&!i.endState&&(delete i.startState,i.endState=!0),\"string\"==typeof l&&l?i.EXP_IF.test(l)?r.range?(l=l.split(\" \"+r.range+\" \"),i.startDate=i.startDate||i.systemDate(),i.endDate=i.endDate||i.systemDate(),r.dateTime=w.extend({},i.startDate),w.each([i.startDate,i.endDate],function(e,t){m(t,l[e],e)})):m(o,l):(i.hint(\"日期格式不合法<br>必须遵循下述格式：<br>\"+(r.range?r.format+\" \"+r.range+\" \"+r.format:r.format)+\"<br>已为你重置\"),a=!0):l&&l.constructor===Date?r.dateTime=i.systemDate(l):(r.dateTime=i.systemDate(),delete i.startState,delete i.endState,delete i.startDate,delete i.endDate,delete i.startTime,delete i.endTime),c(o),a&&l&&i.setValue(r.range?i.endDate?i.parse():\"\":i.parse()),e&&e(),i)},T.prototype.mark=function(e,t){var n,a=this,i=a.config;return w.each(i.mark,function(e,a){var i=e.split(\"-\");i[0]!=t[0]&&0!=i[0]||i[1]!=t[1]&&0!=i[1]||i[2]!=t[2]||(n=a||t[2])}),n&&e.html('<span class=\"laydate-day-mark\">'+n+\"</span>\"),a},T.prototype.limit=function(e,t,n,a){var i,r=this,o=r.config,l={},d=o[n>41?\"endDate\":\"dateTime\"],c=w.extend({},d,t||{});return w.each({now:c,min:o.min,max:o.max},function(e,t){l[e]=r.newDate(w.extend({year:t.year,month:t.month,date:t.date},function(){var e={};return w.each(a,function(n,a){e[a]=t[a]}),e}())).getTime()}),i=l.now<l.min||l.now>l.max,e&&e[i?\"addClass\":\"removeClass\"](s),i},T.prototype.calendar=function(e){var t,a,i,r=this,s=r.config,l=e||s.dateTime,c=new Date,m=r.lang(),u=\"date\"!==s.type&&\"datetime\"!==s.type,h=e?1:0,y=w(r.table[h]).find(\"td\"),f=w(r.elemHeader[h][2]).find(\"span\");if(l.year<d[0]&&(l.year=d[0],r.hint(\"最低只能支持到公元\"+d[0]+\"年\")),l.year>d[1]&&(l.year=d[1],r.hint(\"最高只能支持到公元\"+d[1]+\"年\")),r.firstDate||(r.firstDate=w.extend({},l)),c.setFullYear(l.year,l.month,1),t=c.getDay(),a=n.getEndDate(l.month||12,l.year),i=n.getEndDate(l.month+1,l.year),w.each(y,function(e,n){var d=[l.year,l.month],c=0;n=w(n),n.removeAttr(\"class\"),e<t?(c=a-t+e,n.addClass(\"laydate-day-prev\"),d=r.getAsYM(l.year,l.month,\"sub\")):e>=t&&e<i+t?(c=e-t,s.range||c+1===l.date&&n.addClass(o)):(c=e-i-t,n.addClass(\"laydate-day-next\"),d=r.getAsYM(l.year,l.month)),d[1]++,d[2]=c+1,n.attr(\"lay-ymd\",d.join(\"-\")).html(d[2]),r.mark(n,d).limit(n,{year:d[0],month:d[1]-1,date:d[2]},e)}),w(f[0]).attr(\"lay-ym\",l.year+\"-\"+(l.month+1)),w(f[1]).attr(\"lay-ym\",l.year+\"-\"+(l.month+1)),\"cn\"===s.lang?(w(f[0]).attr(\"lay-type\",\"year\").html(l.year+\"年\"),w(f[1]).attr(\"lay-type\",\"month\").html(l.month+1+\"月\")):(w(f[0]).attr(\"lay-type\",\"month\").html(m.month[l.month]),w(f[1]).attr(\"lay-type\",\"year\").html(l.year)),u&&(s.range&&(e?r.endDate=r.endDate||{year:l.year+(\"year\"===s.type?1:0),month:l.month+(\"month\"===s.type?0:-1)}:r.startDate=r.startDate||{year:l.year,month:l.month},e&&(r.listYM=[[r.startDate.year,r.startDate.month+1],[r.endDate.year,r.endDate.month+1]],r.list(s.type,0).list(s.type,1),\"time\"===s.type?r.setBtnStatus(\"时间\",w.extend({},r.systemDate(),r.startTime),w.extend({},r.systemDate(),r.endTime)):r.setBtnStatus(!0))),s.range||(r.listYM=[[l.year,l.month+1]],r.list(s.type,0))),s.range&&!e){var p=r.getAsYM(l.year,l.month);r.calendar(w.extend({},l,{year:p[0],month:p[1]}))}return s.range||r.limit(w(r.footer).find(g),null,0,[\"hours\",\"minutes\",\"seconds\"]),s.range&&e&&!u&&r.stampRange(),r},T.prototype.list=function(e,t){var n=this,a=n.config,i=a.dateTime,r=n.lang(),l=a.range&&\"date\"!==a.type&&\"datetime\"!==a.type,d=w.elem(\"ul\",{\"class\":m+\" \"+{year:\"laydate-year-list\",month:\"laydate-month-list\",time:\"laydate-time-list\"}[e]}),c=n.elemHeader[t],u=w(c[2]).find(\"span\"),h=n.elemCont[t||0],y=w(h).find(\".\"+m)[0],f=\"cn\"===a.lang,p=f?\"年\":\"\",T=n.listYM[t]||{},C=[\"hours\",\"minutes\",\"seconds\"],x=[\"startTime\",\"endTime\"][t];if(T[0]<1&&(T[0]=1),\"year\"===e){var M,b=M=T[0]-7;b<1&&(b=M=1),w.each(new Array(15),function(e){var i=w.elem(\"li\",{\"lay-ym\":M}),r={year:M};M==T[0]&&w(i).addClass(o),i.innerHTML=M+p,d.appendChild(i),M<n.firstDate.year?(r.month=a.min.month,r.date=a.min.date):M>=n.firstDate.year&&(r.month=a.max.month,r.date=a.max.date),n.limit(w(i),r,t),M++}),w(u[f?0:1]).attr(\"lay-ym\",M-8+\"-\"+T[1]).html(b+p+\" - \"+(M-1+p))}else if(\"month\"===e)w.each(new Array(12),function(e){var i=w.elem(\"li\",{\"lay-ym\":e}),s={year:T[0],month:e};e+1==T[1]&&w(i).addClass(o),i.innerHTML=r.month[e]+(f?\"月\":\"\"),d.appendChild(i),T[0]<n.firstDate.year?s.date=a.min.date:T[0]>=n.firstDate.year&&(s.date=a.max.date),n.limit(w(i),s,t)}),w(u[f?0:1]).attr(\"lay-ym\",T[0]+\"-\"+T[1]).html(T[0]+p);else if(\"time\"===e){var E=function(){w(d).find(\"ol\").each(function(e,a){w(a).find(\"li\").each(function(a,i){n.limit(w(i),[{hours:a},{hours:n[x].hours,minutes:a},{hours:n[x].hours,minutes:n[x].minutes,seconds:a}][e],t,[[\"hours\"],[\"hours\",\"minutes\"],[\"hours\",\"minutes\",\"seconds\"]][e])})}),a.range||n.limit(w(n.footer).find(g),n[x],0,[\"hours\",\"minutes\",\"seconds\"])};a.range?n[x]||(n[x]={hours:0,minutes:0,seconds:0}):n[x]=i,w.each([24,60,60],function(e,t){var a=w.elem(\"li\"),i=[\"<p>\"+r.time[e]+\"</p><ol>\"];w.each(new Array(t),function(t){i.push(\"<li\"+(n[x][C[e]]===t?' class=\"'+o+'\"':\"\")+\">\"+w.digit(t,2)+\"</li>\")}),a.innerHTML=i.join(\"\")+\"</ol>\",d.appendChild(a)}),E()}if(y&&h.removeChild(y),h.appendChild(d),\"year\"===e||\"month\"===e)w(n.elemMain[t]).addClass(\"laydate-ym-show\"),w(d).find(\"li\").on(\"click\",function(){var r=0|w(this).attr(\"lay-ym\");if(!w(this).hasClass(s)){if(0===t)i[e]=r,l&&(n.startDate[e]=r),n.limit(w(n.footer).find(g),null,0);else if(l)n.endDate[e]=r;else{var c=\"year\"===e?n.getAsYM(r,T[1]-1,\"sub\"):n.getAsYM(T[0],r,\"sub\");w.extend(i,{year:c[0],month:c[1]})}\"year\"===a.type||\"month\"===a.type?(w(d).find(\".\"+o).removeClass(o),w(this).addClass(o),\"month\"===a.type&&\"year\"===e&&(n.listYM[t][0]=r,l&&(n[[\"startDate\",\"endDate\"][t]].year=r),n.list(\"month\",t))):(n.checkDate(\"limit\").calendar(),n.closeList()),n.setBtnStatus(),a.range||n.done(null,\"change\"),w(n.footer).find(D).removeClass(s)}});else{var S=w.elem(\"span\",{\"class\":v}),k=function(){w(d).find(\"ol\").each(function(e){var t=this,a=w(t).find(\"li\");t.scrollTop=30*(n[x][C[e]]-2),t.scrollTop<=0&&a.each(function(e,n){if(!w(this).hasClass(s))return t.scrollTop=30*(e-2),!0})})},H=w(c[2]).find(\".\"+v);k(),S.innerHTML=a.range?[r.startTime,r.endTime][t]:r.timeTips,w(n.elemMain[t]).addClass(\"laydate-time-show\"),H[0]&&H.remove(),c[2].appendChild(S),w(d).find(\"ol\").each(function(e){var t=this;w(t).find(\"li\").on(\"click\",function(){var r=0|this.innerHTML;w(this).hasClass(s)||(a.range?n[x][C[e]]=r:i[C[e]]=r,w(t).find(\".\"+o).removeClass(o),w(this).addClass(o),E(),k(),(n.endDate||\"time\"===a.type)&&n.done(null,\"change\"),n.setBtnStatus())})})}return n},T.prototype.listYM=[],T.prototype.closeList=function(){var e=this;e.config;w.each(e.elemCont,function(t,n){w(this).find(\".\"+m).remove(),w(e.elemMain[t]).removeClass(\"laydate-ym-show laydate-time-show\")}),w(e.elem).find(\".\"+v).remove()},T.prototype.setBtnStatus=function(e,t,n){var a,i=this,r=i.config,o=w(i.footer).find(g),d=r.range&&\"date\"!==r.type&&\"time\"!==r.type;d&&(t=t||i.startDate,n=n||i.endDate,a=i.newDate(t).getTime()>i.newDate(n).getTime(),i.limit(null,t)||i.limit(null,n)?o.addClass(s):o[a?\"addClass\":\"removeClass\"](s),e&&a&&i.hint(\"string\"==typeof e?l.replace(/日期/g,e):l))},T.prototype.parse=function(e,t){var n=this,a=n.config,i=t||(e?w.extend({},n.endDate,n.endTime):a.range?w.extend({},n.startDate,n.startTime):a.dateTime),r=n.format.concat();return w.each(r,function(e,t){/yyyy|y/.test(t)?r[e]=w.digit(i.year,t.length):/MM|M/.test(t)?r[e]=w.digit(i.month+1,t.length):/dd|d/.test(t)?r[e]=w.digit(i.date,t.length):/HH|H/.test(t)?r[e]=w.digit(i.hours,t.length):/mm|m/.test(t)?r[e]=w.digit(i.minutes,t.length):/ss|s/.test(t)&&(r[e]=w.digit(i.seconds,t.length))}),a.range&&!e?r.join(\"\")+\" \"+a.range+\" \"+n.parse(1):r.join(\"\")},T.prototype.newDate=function(e){return e=e||{},new Date(e.year||1,e.month||0,e.date||1,e.hours||0,e.minutes||0,e.seconds||0)},T.prototype.setValue=function(e){var t=this,n=t.config,a=t.bindElem||n.elem[0],i=t.isInput(a)?\"val\":\"html\";return\"static\"===n.position||w(a)[i](e||\"\"),this},T.prototype.stampRange=function(){var e,t,n=this,a=n.config,i=w(n.elem).find(\"td\");if(a.range&&!n.endDate&&w(n.footer).find(g).addClass(s),n.endDate)return e=n.newDate({year:n.startDate.year,month:n.startDate.month,date:n.startDate.date}).getTime(),t=n.newDate({year:n.endDate.year,month:n.endDate.month,date:n.endDate.date}).getTime(),e>t?n.hint(l):void w.each(i,function(a,i){var r=w(i).attr(\"lay-ymd\").split(\"-\"),s=n.newDate({year:r[0],month:r[1]-1,date:r[2]}).getTime();w(i).removeClass(u+\" \"+o),s!==e&&s!==t||w(i).addClass(w(i).hasClass(y)||w(i).hasClass(f)?u:o),s>e&&s<t&&w(i).addClass(u)})},T.prototype.done=function(e,t){var n=this,a=n.config,i=w.extend({},n.startDate?w.extend(n.startDate,n.startTime):a.dateTime),r=w.extend({},w.extend(n.endDate,n.endTime));return w.each([i,r],function(e,t){\"month\"in t&&w.extend(t,{month:t.month+1})}),e=e||[n.parse(),i,r],\"function\"==typeof a[t||\"done\"]&&a[t||\"done\"].apply(a,e),n},T.prototype.choose=function(e){var t=this,n=t.config,a=n.dateTime,i=w(t.elem).find(\"td\"),r=e.attr(\"lay-ymd\").split(\"-\"),l=function(e){new Date;e&&w.extend(a,r),n.range&&(t.startDate?w.extend(t.startDate,r):t.startDate=w.extend({},r,t.startTime),t.startYMD=r)};if(r={year:0|r[0],month:(0|r[1])-1,date:0|r[2]},!e.hasClass(s))if(n.range){if(w.each([\"startTime\",\"endTime\"],function(e,n){t[n]=t[n]||{hours:0,minutes:0,seconds:0}}),t.endState)l(),delete t.endState,delete t.endDate,t.startState=!0,i.removeClass(o+\" \"+u),e.addClass(o);else if(t.startState){if(e.addClass(o),t.endDate?w.extend(t.endDate,r):t.endDate=w.extend({},r,t.endTime),t.newDate(r).getTime()<t.newDate(t.startYMD).getTime()){var d=w.extend({},t.endDate,{hours:t.startDate.hours,minutes:t.startDate.minutes,seconds:t.startDate.seconds});w.extend(t.endDate,t.startDate,{hours:t.endDate.hours,minutes:t.endDate.minutes,seconds:t.endDate.seconds}),t.startDate=d}n.showBottom||t.done(),t.stampRange(),t.endState=!0,t.done(null,\"change\")}else e.addClass(o),l(),t.startState=!0;w(t.footer).find(g)[t.endDate?\"removeClass\":\"addClass\"](s)}else\"static\"===n.position?(l(!0),t.calendar().done().done(null,\"change\")):\"date\"===n.type?(l(!0),t.setValue(t.parse()).remove().done()):\"datetime\"===n.type&&(l(!0),t.calendar().done(null,\"change\"))},T.prototype.tool=function(e,t){var n=this,a=n.config,i=a.dateTime,r=\"static\"===a.position,o={datetime:function(){w(e).hasClass(s)||(n.list(\"time\",0),a.range&&n.list(\"time\",1),w(e).attr(\"lay-type\",\"date\").html(n.lang().dateTips))},date:function(){n.closeList(),w(e).attr(\"lay-type\",\"datetime\").html(n.lang().timeTips)},clear:function(){n.setValue(\"\").remove(),r&&(w.extend(i,n.firstDate),n.calendar()),a.range&&(delete n.startState,delete n.endState,delete n.endDate,delete n.startTime,delete n.endTime),n.done([\"\",{},{}])},now:function(){var e=new Date;w.extend(i,n.systemDate(),{hours:e.getHours(),minutes:e.getMinutes(),seconds:e.getSeconds()}),n.setValue(n.parse()).remove(),r&&n.calendar(),n.done()},confirm:function(){if(a.range){if(!n.endDate)return n.hint(\"请先选择日期范围\");if(w(e).hasClass(s))return n.hint(\"time\"===a.type?l.replace(/日期/g,\"时间\"):l)}else if(w(e).hasClass(s))return n.hint(\"不在有效日期或时间范围内\");n.done(),n.setValue(n.parse()).remove()}};o[t]&&o[t]()},T.prototype.change=function(e){var t=this,n=t.config,a=n.dateTime,i=n.range&&(\"year\"===n.type||\"month\"===n.type),r=t.elemCont[e||0],o=t.listYM[e],s=function(s){var l=[\"startDate\",\"endDate\"][e],d=w(r).find(\".laydate-year-list\")[0],c=w(r).find(\".laydate-month-list\")[0];return d&&(o[0]=s?o[0]-15:o[0]+15,t.list(\"year\",e)),c&&(s?o[0]--:o[0]++,t.list(\"month\",e)),(d||c)&&(w.extend(a,{year:o[0]}),i&&(t[l].year=o[0]),n.range||t.done(null,\"change\"),t.setBtnStatus(),n.range||t.limit(w(t.footer).find(g),{year:o[0]})),d||c};return{prevYear:function(){s(\"sub\")||(a.year--,t.checkDate(\"limit\").calendar(),n.range||t.done(null,\"change\"))},prevMonth:function(){var e=t.getAsYM(a.year,a.month,\"sub\");w.extend(a,{year:e[0],month:e[1]}),t.checkDate(\"limit\").calendar(),n.range||t.done(null,\"change\")},nextMonth:function(){var e=t.getAsYM(a.year,a.month);w.extend(a,{year:e[0],month:e[1]}),t.checkDate(\"limit\").calendar(),n.range||t.done(null,\"change\")},nextYear:function(){s()||(a.year++,t.checkDate(\"limit\").calendar(),n.range||t.done(null,\"change\"))}}},T.prototype.changeEvent=function(){var e=this;e.config;w(e.elem).on(\"click\",function(e){w.stope(e)}),w.each(e.elemHeader,function(t,n){w(n[0]).on(\"click\",function(n){e.change(t).prevYear()}),w(n[1]).on(\"click\",function(n){e.change(t).prevMonth()}),w(n[2]).find(\"span\").on(\"click\",function(n){var a=w(this),i=a.attr(\"lay-ym\"),r=a.attr(\"lay-type\");i&&(i=i.split(\"-\"),e.listYM[t]=[0|i[0],0|i[1]],e.list(r,t),w(e.footer).find(D).addClass(s))}),w(n[3]).on(\"click\",function(n){e.change(t).nextMonth()}),w(n[4]).on(\"click\",function(n){e.change(t).nextYear()})}),w.each(e.table,function(t,n){var a=w(n).find(\"td\");a.on(\"click\",function(){e.choose(w(this))})}),w(e.footer).find(\"span\").on(\"click\",function(){var t=w(this).attr(\"lay-type\");e.tool(this,t)})},T.prototype.isInput=function(e){return/input|textarea/.test(e.tagName.toLocaleLowerCase())},T.prototype.events=function(){var e=this,t=e.config,n=function(n,a){n.on(t.trigger,function(){a&&(e.bindElem=this),e.render()})};t.elem[0]&&!t.elem[0].eventHandler&&(n(t.elem,\"bind\"),n(t.eventElem),w(document).on(\"click\",function(n){n.target!==t.elem[0]&&n.target!==t.eventElem[0]&&n.target!==w(t.closeStop)[0]&&e.remove()}).on(\"keydown\",function(t){13===t.keyCode&&w(\"#\"+e.elemID)[0]&&e.elemID===T.thisElem&&(t.preventDefault(),w(e.footer).find(g)[0].click())}),w(window).on(\"resize\",function(){return!(!e.elem||!w(r)[0])&&void e.position()}),t.elem[0].eventHandler=!0)},n.render=function(e){var t=new T(e);return a.call(t)},n.getEndDate=function(e,t){var n=new Date;return n.setFullYear(t||n.getFullYear(),e||n.getMonth()+1,1),new Date(n.getTime()-864e5).getDate()},window.lay=window.lay||w,e?(n.ready(),layui.define(function(e){n.path=layui.cache.dir,e(i,n)})):\"function\"==typeof define&&define.amd?define(function(){return n}):function(){n.ready(),window.laydate=n}()}();!function(e,t){\"object\"==typeof module&&\"object\"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error(\"jQuery requires a window with a document\");return t(e)}:t(e)}(\"undefined\"!=typeof window?window:this,function(e,t){function n(e){var t=!!e&&\"length\"in e&&e.length,n=pe.type(e);return\"function\"!==n&&!pe.isWindow(e)&&(\"array\"===n||0===t||\"number\"==typeof t&&t>0&&t-1 in e)}function r(e,t,n){if(pe.isFunction(t))return pe.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return pe.grep(e,function(e){return e===t!==n});if(\"string\"==typeof t){if(Ce.test(t))return pe.filter(t,e,n);t=pe.filter(t,e)}return pe.grep(e,function(e){return pe.inArray(e,t)>-1!==n})}function i(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}function o(e){var t={};return pe.each(e.match(De)||[],function(e,n){t[n]=!0}),t}function a(){re.addEventListener?(re.removeEventListener(\"DOMContentLoaded\",s),e.removeEventListener(\"load\",s)):(re.detachEvent(\"onreadystatechange\",s),e.detachEvent(\"onload\",s))}function s(){(re.addEventListener||\"load\"===e.event.type||\"complete\"===re.readyState)&&(a(),pe.ready())}function u(e,t,n){if(void 0===n&&1===e.nodeType){var r=\"data-\"+t.replace(_e,\"-$1\").toLowerCase();if(n=e.getAttribute(r),\"string\"==typeof n){try{n=\"true\"===n||\"false\"!==n&&(\"null\"===n?null:+n+\"\"===n?+n:qe.test(n)?pe.parseJSON(n):n)}catch(i){}pe.data(e,t,n)}else n=void 0}return n}function l(e){var t;for(t in e)if((\"data\"!==t||!pe.isEmptyObject(e[t]))&&\"toJSON\"!==t)return!1;return!0}function c(e,t,n,r){if(He(e)){var i,o,a=pe.expando,s=e.nodeType,u=s?pe.cache:e,l=s?e[a]:e[a]&&a;if(l&&u[l]&&(r||u[l].data)||void 0!==n||\"string\"!=typeof t)return l||(l=s?e[a]=ne.pop()||pe.guid++:a),u[l]||(u[l]=s?{}:{toJSON:pe.noop}),\"object\"!=typeof t&&\"function\"!=typeof t||(r?u[l]=pe.extend(u[l],t):u[l].data=pe.extend(u[l].data,t)),o=u[l],r||(o.data||(o.data={}),o=o.data),void 0!==n&&(o[pe.camelCase(t)]=n),\"string\"==typeof t?(i=o[t],null==i&&(i=o[pe.camelCase(t)])):i=o,i}}function f(e,t,n){if(He(e)){var r,i,o=e.nodeType,a=o?pe.cache:e,s=o?e[pe.expando]:pe.expando;if(a[s]){if(t&&(r=n?a[s]:a[s].data)){pe.isArray(t)?t=t.concat(pe.map(t,pe.camelCase)):t in r?t=[t]:(t=pe.camelCase(t),t=t in r?[t]:t.split(\" \")),i=t.length;for(;i--;)delete r[t[i]];if(n?!l(r):!pe.isEmptyObject(r))return}(n||(delete a[s].data,l(a[s])))&&(o?pe.cleanData([e],!0):fe.deleteExpando||a!=a.window?delete a[s]:a[s]=void 0)}}}function d(e,t,n,r){var i,o=1,a=20,s=r?function(){return r.cur()}:function(){return pe.css(e,t,\"\")},u=s(),l=n&&n[3]||(pe.cssNumber[t]?\"\":\"px\"),c=(pe.cssNumber[t]||\"px\"!==l&&+u)&&Me.exec(pe.css(e,t));if(c&&c[3]!==l){l=l||c[3],n=n||[],c=+u||1;do o=o||\".5\",c/=o,pe.style(e,t,c+l);while(o!==(o=s()/u)&&1!==o&&--a)}return n&&(c=+c||+u||0,i=n[1]?c+(n[1]+1)*n[2]:+n[2],r&&(r.unit=l,r.start=c,r.end=i)),i}function p(e){var t=ze.split(\"|\"),n=e.createDocumentFragment();if(n.createElement)for(;t.length;)n.createElement(t.pop());return n}function h(e,t){var n,r,i=0,o=\"undefined\"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||\"*\"):\"undefined\"!=typeof e.querySelectorAll?e.querySelectorAll(t||\"*\"):void 0;if(!o)for(o=[],n=e.childNodes||e;null!=(r=n[i]);i++)!t||pe.nodeName(r,t)?o.push(r):pe.merge(o,h(r,t));return void 0===t||t&&pe.nodeName(e,t)?pe.merge([e],o):o}function g(e,t){for(var n,r=0;null!=(n=e[r]);r++)pe._data(n,\"globalEval\",!t||pe._data(t[r],\"globalEval\"))}function m(e){Be.test(e.type)&&(e.defaultChecked=e.checked)}function y(e,t,n,r,i){for(var o,a,s,u,l,c,f,d=e.length,y=p(t),v=[],x=0;x<d;x++)if(a=e[x],a||0===a)if(\"object\"===pe.type(a))pe.merge(v,a.nodeType?[a]:a);else if(Ue.test(a)){for(u=u||y.appendChild(t.createElement(\"div\")),l=(We.exec(a)||[\"\",\"\"])[1].toLowerCase(),f=Xe[l]||Xe._default,u.innerHTML=f[1]+pe.htmlPrefilter(a)+f[2],o=f[0];o--;)u=u.lastChild;if(!fe.leadingWhitespace&&$e.test(a)&&v.push(t.createTextNode($e.exec(a)[0])),!fe.tbody)for(a=\"table\"!==l||Ve.test(a)?\"<table>\"!==f[1]||Ve.test(a)?0:u:u.firstChild,o=a&&a.childNodes.length;o--;)pe.nodeName(c=a.childNodes[o],\"tbody\")&&!c.childNodes.length&&a.removeChild(c);for(pe.merge(v,u.childNodes),u.textContent=\"\";u.firstChild;)u.removeChild(u.firstChild);u=y.lastChild}else v.push(t.createTextNode(a));for(u&&y.removeChild(u),fe.appendChecked||pe.grep(h(v,\"input\"),m),x=0;a=v[x++];)if(r&&pe.inArray(a,r)>-1)i&&i.push(a);else if(s=pe.contains(a.ownerDocument,a),u=h(y.appendChild(a),\"script\"),s&&g(u),n)for(o=0;a=u[o++];)Ie.test(a.type||\"\")&&n.push(a);return u=null,y}function v(){return!0}function x(){return!1}function b(){try{return re.activeElement}catch(e){}}function w(e,t,n,r,i,o){var a,s;if(\"object\"==typeof t){\"string\"!=typeof n&&(r=r||n,n=void 0);for(s in t)w(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&(\"string\"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),i===!1)i=x;else if(!i)return e;return 1===o&&(a=i,i=function(e){return pe().off(e),a.apply(this,arguments)},i.guid=a.guid||(a.guid=pe.guid++)),e.each(function(){pe.event.add(this,t,i,r,n)})}function T(e,t){return pe.nodeName(e,\"table\")&&pe.nodeName(11!==t.nodeType?t:t.firstChild,\"tr\")?e.getElementsByTagName(\"tbody\")[0]||e.appendChild(e.ownerDocument.createElement(\"tbody\")):e}function C(e){return e.type=(null!==pe.find.attr(e,\"type\"))+\"/\"+e.type,e}function E(e){var t=it.exec(e.type);return t?e.type=t[1]:e.removeAttribute(\"type\"),e}function N(e,t){if(1===t.nodeType&&pe.hasData(e)){var n,r,i,o=pe._data(e),a=pe._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;r<i;r++)pe.event.add(t,n,s[n][r])}a.data&&(a.data=pe.extend({},a.data))}}function k(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!fe.noCloneEvent&&t[pe.expando]){i=pe._data(t);for(r in i.events)pe.removeEvent(t,r,i.handle);t.removeAttribute(pe.expando)}\"script\"===n&&t.text!==e.text?(C(t).text=e.text,E(t)):\"object\"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),fe.html5Clone&&e.innerHTML&&!pe.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):\"input\"===n&&Be.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)}}function S(e,t,n,r){t=oe.apply([],t);var i,o,a,s,u,l,c=0,f=e.length,d=f-1,p=t[0],g=pe.isFunction(p);if(g||f>1&&\"string\"==typeof p&&!fe.checkClone&&rt.test(p))return e.each(function(i){var o=e.eq(i);g&&(t[0]=p.call(this,i,o.html())),S(o,t,n,r)});if(f&&(l=y(t,e[0].ownerDocument,!1,e,r),i=l.firstChild,1===l.childNodes.length&&(l=i),i||r)){for(s=pe.map(h(l,\"script\"),C),a=s.length;c<f;c++)o=l,c!==d&&(o=pe.clone(o,!0,!0),a&&pe.merge(s,h(o,\"script\"))),n.call(e[c],o,c);if(a)for(u=s[s.length-1].ownerDocument,pe.map(s,E),c=0;c<a;c++)o=s[c],Ie.test(o.type||\"\")&&!pe._data(o,\"globalEval\")&&pe.contains(u,o)&&(o.src?pe._evalUrl&&pe._evalUrl(o.src):pe.globalEval((o.text||o.textContent||o.innerHTML||\"\").replace(ot,\"\")));l=i=null}return e}function A(e,t,n){for(var r,i=t?pe.filter(t,e):e,o=0;null!=(r=i[o]);o++)n||1!==r.nodeType||pe.cleanData(h(r)),r.parentNode&&(n&&pe.contains(r.ownerDocument,r)&&g(h(r,\"script\")),r.parentNode.removeChild(r));return e}function D(e,t){var n=pe(t.createElement(e)).appendTo(t.body),r=pe.css(n[0],\"display\");return n.detach(),r}function j(e){var t=re,n=lt[e];return n||(n=D(e,t),\"none\"!==n&&n||(ut=(ut||pe(\"<iframe frameborder='0' width='0' height='0'/>\")).appendTo(t.documentElement),t=(ut[0].contentWindow||ut[0].contentDocument).document,t.write(),t.close(),n=D(e,t),ut.detach()),lt[e]=n),n}function L(e,t){return{get:function(){return e()?void delete this.get:(this.get=t).apply(this,arguments)}}}function H(e){if(e in Et)return e;for(var t=e.charAt(0).toUpperCase()+e.slice(1),n=Ct.length;n--;)if(e=Ct[n]+t,e in Et)return e}function q(e,t){for(var n,r,i,o=[],a=0,s=e.length;a<s;a++)r=e[a],r.style&&(o[a]=pe._data(r,\"olddisplay\"),n=r.style.display,t?(o[a]||\"none\"!==n||(r.style.display=\"\"),\"\"===r.style.display&&Re(r)&&(o[a]=pe._data(r,\"olddisplay\",j(r.nodeName)))):(i=Re(r),(n&&\"none\"!==n||!i)&&pe._data(r,\"olddisplay\",i?n:pe.css(r,\"display\"))));for(a=0;a<s;a++)r=e[a],r.style&&(t&&\"none\"!==r.style.display&&\"\"!==r.style.display||(r.style.display=t?o[a]||\"\":\"none\"));return e}function _(e,t,n){var r=bt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||\"px\"):t}function F(e,t,n,r,i){for(var o=n===(r?\"border\":\"content\")?4:\"width\"===t?1:0,a=0;o<4;o+=2)\"margin\"===n&&(a+=pe.css(e,n+Oe[o],!0,i)),r?(\"content\"===n&&(a-=pe.css(e,\"padding\"+Oe[o],!0,i)),\"margin\"!==n&&(a-=pe.css(e,\"border\"+Oe[o]+\"Width\",!0,i))):(a+=pe.css(e,\"padding\"+Oe[o],!0,i),\"padding\"!==n&&(a+=pe.css(e,\"border\"+Oe[o]+\"Width\",!0,i)));return a}function M(t,n,r){var i=!0,o=\"width\"===n?t.offsetWidth:t.offsetHeight,a=ht(t),s=fe.boxSizing&&\"border-box\"===pe.css(t,\"boxSizing\",!1,a);if(re.msFullscreenElement&&e.top!==e&&t.getClientRects().length&&(o=Math.round(100*t.getBoundingClientRect()[n])),o<=0||null==o){if(o=gt(t,n,a),(o<0||null==o)&&(o=t.style[n]),ft.test(o))return o;i=s&&(fe.boxSizingReliable()||o===t.style[n]),o=parseFloat(o)||0}return o+F(t,n,r||(s?\"border\":\"content\"),i,a)+\"px\"}function O(e,t,n,r,i){return new O.prototype.init(e,t,n,r,i)}function R(){return e.setTimeout(function(){Nt=void 0}),Nt=pe.now()}function P(e,t){var n,r={height:e},i=0;for(t=t?1:0;i<4;i+=2-t)n=Oe[i],r[\"margin\"+n]=r[\"padding\"+n]=e;return t&&(r.opacity=r.width=e),r}function B(e,t,n){for(var r,i=($.tweeners[t]||[]).concat($.tweeners[\"*\"]),o=0,a=i.length;o<a;o++)if(r=i[o].call(n,t,e))return r}function W(e,t,n){var r,i,o,a,s,u,l,c,f=this,d={},p=e.style,h=e.nodeType&&Re(e),g=pe._data(e,\"fxshow\");n.queue||(s=pe._queueHooks(e,\"fx\"),null==s.unqueued&&(s.unqueued=0,u=s.empty.fire,s.empty.fire=function(){s.unqueued||u()}),s.unqueued++,f.always(function(){f.always(function(){s.unqueued--,pe.queue(e,\"fx\").length||s.empty.fire()})})),1===e.nodeType&&(\"height\"in t||\"width\"in t)&&(n.overflow=[p.overflow,p.overflowX,p.overflowY],l=pe.css(e,\"display\"),c=\"none\"===l?pe._data(e,\"olddisplay\")||j(e.nodeName):l,\"inline\"===c&&\"none\"===pe.css(e,\"float\")&&(fe.inlineBlockNeedsLayout&&\"inline\"!==j(e.nodeName)?p.zoom=1:p.display=\"inline-block\")),n.overflow&&(p.overflow=\"hidden\",fe.shrinkWrapBlocks()||f.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],St.exec(i)){if(delete t[r],o=o||\"toggle\"===i,i===(h?\"hide\":\"show\")){if(\"show\"!==i||!g||void 0===g[r])continue;h=!0}d[r]=g&&g[r]||pe.style(e,r)}else l=void 0;if(pe.isEmptyObject(d))\"inline\"===(\"none\"===l?j(e.nodeName):l)&&(p.display=l);else{g?\"hidden\"in g&&(h=g.hidden):g=pe._data(e,\"fxshow\",{}),o&&(g.hidden=!h),h?pe(e).show():f.done(function(){pe(e).hide()}),f.done(function(){var t;pe._removeData(e,\"fxshow\");for(t in d)pe.style(e,t,d[t])});for(r in d)a=B(h?g[r]:0,r,f),r in g||(g[r]=a.start,h&&(a.end=a.start,a.start=\"width\"===r||\"height\"===r?1:0))}}function I(e,t){var n,r,i,o,a;for(n in e)if(r=pe.camelCase(n),i=t[r],o=e[n],pe.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),a=pe.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}function $(e,t,n){var r,i,o=0,a=$.prefilters.length,s=pe.Deferred().always(function(){delete u.elem}),u=function(){if(i)return!1;for(var t=Nt||R(),n=Math.max(0,l.startTime+l.duration-t),r=n/l.duration||0,o=1-r,a=0,u=l.tweens.length;a<u;a++)l.tweens[a].run(o);return s.notifyWith(e,[l,o,n]),o<1&&u?n:(s.resolveWith(e,[l]),!1)},l=s.promise({elem:e,props:pe.extend({},t),opts:pe.extend(!0,{specialEasing:{},easing:pe.easing._default},n),originalProperties:t,originalOptions:n,startTime:Nt||R(),duration:n.duration,tweens:[],createTween:function(t,n){var r=pe.Tween(e,l.opts,t,n,l.opts.specialEasing[t]||l.opts.easing);return l.tweens.push(r),r},stop:function(t){var n=0,r=t?l.tweens.length:0;if(i)return this;for(i=!0;n<r;n++)l.tweens[n].run(1);return t?(s.notifyWith(e,[l,1,0]),s.resolveWith(e,[l,t])):s.rejectWith(e,[l,t]),this}}),c=l.props;for(I(c,l.opts.specialEasing);o<a;o++)if(r=$.prefilters[o].call(l,e,c,l.opts))return pe.isFunction(r.stop)&&(pe._queueHooks(l.elem,l.opts.queue).stop=pe.proxy(r.stop,r)),r;return pe.map(c,B,l),pe.isFunction(l.opts.start)&&l.opts.start.call(e,l),pe.fx.timer(pe.extend(u,{elem:e,anim:l,queue:l.opts.queue})),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always)}function z(e){return pe.attr(e,\"class\")||\"\"}function X(e){return function(t,n){\"string\"!=typeof t&&(n=t,t=\"*\");var r,i=0,o=t.toLowerCase().match(De)||[];if(pe.isFunction(n))for(;r=o[i++];)\"+\"===r.charAt(0)?(r=r.slice(1)||\"*\",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function U(e,t,n,r){function i(s){var u;return o[s]=!0,pe.each(e[s]||[],function(e,s){var l=s(t,n,r);return\"string\"!=typeof l||a||o[l]?a?!(u=l):void 0:(t.dataTypes.unshift(l),i(l),!1)}),u}var o={},a=e===Qt;return i(t.dataTypes[0])||!o[\"*\"]&&i(\"*\")}function V(e,t){var n,r,i=pe.ajaxSettings.flatOptions||{};for(r in t)void 0!==t[r]&&((i[r]?e:n||(n={}))[r]=t[r]);return n&&pe.extend(!0,e,n),e}function Y(e,t,n){for(var r,i,o,a,s=e.contents,u=e.dataTypes;\"*\"===u[0];)u.shift(),void 0===i&&(i=e.mimeType||t.getResponseHeader(\"Content-Type\"));if(i)for(a in s)if(s[a]&&s[a].test(i)){u.unshift(a);break}if(u[0]in n)o=u[0];else{for(a in n){if(!u[0]||e.converters[a+\" \"+u[0]]){o=a;break}r||(r=a)}o=o||r}if(o)return o!==u[0]&&u.unshift(o),n[o]}function J(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];for(o=c.shift();o;)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if(\"*\"===o)o=u;else if(\"*\"!==u&&u!==o){if(a=l[u+\" \"+o]||l[\"* \"+o],!a)for(i in l)if(s=i.split(\" \"),s[1]===o&&(a=l[u+\" \"+s[0]]||l[\"* \"+s[0]])){a===!0?a=l[i]:l[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(f){return{state:\"parsererror\",error:a?f:\"No conversion from \"+u+\" to \"+o}}}return{state:\"success\",data:t}}function G(e){return e.style&&e.style.display||pe.css(e,\"display\")}function K(e){for(;e&&1===e.nodeType;){if(\"none\"===G(e)||\"hidden\"===e.type)return!0;e=e.parentNode}return!1}function Q(e,t,n,r){var i;if(pe.isArray(t))pe.each(t,function(t,i){n||rn.test(e)?r(e,i):Q(e+\"[\"+(\"object\"==typeof i&&null!=i?t:\"\")+\"]\",i,n,r)});else if(n||\"object\"!==pe.type(t))r(e,t);else for(i in t)Q(e+\"[\"+i+\"]\",t[i],n,r)}function Z(){try{return new e.XMLHttpRequest}catch(t){}}function ee(){try{return new e.ActiveXObject(\"Microsoft.XMLHTTP\")}catch(t){}}function te(e){return pe.isWindow(e)?e:9===e.nodeType&&(e.defaultView||e.parentWindow)}var ne=[],re=e.document,ie=ne.slice,oe=ne.concat,ae=ne.push,se=ne.indexOf,ue={},le=ue.toString,ce=ue.hasOwnProperty,fe={},de=\"1.12.3\",pe=function(e,t){return new pe.fn.init(e,t)},he=/^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g,ge=/^-ms-/,me=/-([\\da-z])/gi,ye=function(e,t){return t.toUpperCase()};pe.fn=pe.prototype={jquery:de,constructor:pe,selector:\"\",length:0,toArray:function(){return ie.call(this)},get:function(e){return null!=e?e<0?this[e+this.length]:this[e]:ie.call(this)},pushStack:function(e){var t=pe.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e){return pe.each(this,e)},map:function(e){return this.pushStack(pe.map(this,function(t,n){return e.call(t,n,t)}))},slice:function(){return this.pushStack(ie.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(n>=0&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:ae,sort:ne.sort,splice:ne.splice},pe.extend=pe.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for(\"boolean\"==typeof a&&(l=a,a=arguments[s]||{},s++),\"object\"==typeof a||pe.isFunction(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(i=arguments[s]))for(r in i)e=a[r],n=i[r],a!==n&&(l&&n&&(pe.isPlainObject(n)||(t=pe.isArray(n)))?(t?(t=!1,o=e&&pe.isArray(e)?e:[]):o=e&&pe.isPlainObject(e)?e:{},a[r]=pe.extend(l,o,n)):void 0!==n&&(a[r]=n));return a},pe.extend({expando:\"jQuery\"+(de+Math.random()).replace(/\\D/g,\"\"),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isFunction:function(e){return\"function\"===pe.type(e)},isArray:Array.isArray||function(e){return\"array\"===pe.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){var t=e&&e.toString();return!pe.isArray(e)&&t-parseFloat(t)+1>=0},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},isPlainObject:function(e){var t;if(!e||\"object\"!==pe.type(e)||e.nodeType||pe.isWindow(e))return!1;try{if(e.constructor&&!ce.call(e,\"constructor\")&&!ce.call(e.constructor.prototype,\"isPrototypeOf\"))return!1}catch(n){return!1}if(!fe.ownFirst)for(t in e)return ce.call(e,t);for(t in e);return void 0===t||ce.call(e,t)},type:function(e){return null==e?e+\"\":\"object\"==typeof e||\"function\"==typeof e?ue[le.call(e)]||\"object\":typeof e},globalEval:function(t){t&&pe.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(ge,\"ms-\").replace(me,ye)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t){var r,i=0;if(n(e))for(r=e.length;i<r&&t.call(e[i],i,e[i])!==!1;i++);else for(i in e)if(t.call(e[i],i,e[i])===!1)break;return e},trim:function(e){return null==e?\"\":(e+\"\").replace(he,\"\")},makeArray:function(e,t){var r=t||[];return null!=e&&(n(Object(e))?pe.merge(r,\"string\"==typeof e?[e]:e):ae.call(r,e)),r},inArray:function(e,t,n){var r;if(t){if(se)return se.call(t,e,n);for(r=t.length,n=n?n<0?Math.max(0,r+n):n:0;n<r;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;)e[i++]=t[r++];if(n!==n)for(;void 0!==t[r];)e[i++]=t[r++];return e.length=i,e},grep:function(e,t,n){for(var r,i=[],o=0,a=e.length,s=!n;o<a;o++)r=!t(e[o],o),r!==s&&i.push(e[o]);return i},map:function(e,t,r){var i,o,a=0,s=[];if(n(e))for(i=e.length;a<i;a++)o=t(e[a],a,r),null!=o&&s.push(o);else for(a in e)o=t(e[a],a,r),null!=o&&s.push(o);return oe.apply([],s)},guid:1,proxy:function(e,t){var n,r,i;if(\"string\"==typeof t&&(i=e[t],t=e,e=i),pe.isFunction(e))return n=ie.call(arguments,2),r=function(){return e.apply(t||this,n.concat(ie.call(arguments)))},r.guid=e.guid=e.guid||pe.guid++,r},now:function(){return+new Date},support:fe}),\"function\"==typeof Symbol&&(pe.fn[Symbol.iterator]=ne[Symbol.iterator]),pe.each(\"Boolean Number String Function Array Date RegExp Object Error Symbol\".split(\" \"),function(e,t){ue[\"[object \"+t+\"]\"]=t.toLowerCase()});var ve=function(e){function t(e,t,n,r){var i,o,a,s,u,l,f,p,h=t&&t.ownerDocument,g=t?t.nodeType:9;if(n=n||[],\"string\"!=typeof e||!e||1!==g&&9!==g&&11!==g)return n;if(!r&&((t?t.ownerDocument||t:B)!==H&&L(t),t=t||H,_)){if(11!==g&&(l=ye.exec(e)))if(i=l[1]){if(9===g){if(!(a=t.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(h&&(a=h.getElementById(i))&&R(t,a)&&a.id===i)return n.push(a),n}else{if(l[2])return Q.apply(n,t.getElementsByTagName(e)),n;if((i=l[3])&&w.getElementsByClassName&&t.getElementsByClassName)return Q.apply(n,t.getElementsByClassName(i)),n}if(w.qsa&&!X[e+\" \"]&&(!F||!F.test(e))){if(1!==g)h=t,p=e;else if(\"object\"!==t.nodeName.toLowerCase()){for((s=t.getAttribute(\"id\"))?s=s.replace(xe,\"\\\\$&\"):t.setAttribute(\"id\",s=P),f=N(e),o=f.length,u=de.test(s)?\"#\"+s:\"[id='\"+s+\"']\";o--;)f[o]=u+\" \"+d(f[o]);p=f.join(\",\"),h=ve.test(e)&&c(t.parentNode)||t}if(p)try{return Q.apply(n,h.querySelectorAll(p)),n}catch(m){}finally{s===P&&t.removeAttribute(\"id\")}}}return S(e.replace(se,\"$1\"),t,n,r)}function n(){function e(n,r){return t.push(n+\" \")>T.cacheLength&&delete e[t.shift()],e[n+\" \"]=r}var t=[];return e}function r(e){return e[P]=!0,e}function i(e){var t=H.createElement(\"div\");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function o(e,t){for(var n=e.split(\"|\"),r=n.length;r--;)T.attrHandle[n[r]]=t}function a(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||V)-(~e.sourceIndex||V);if(r)return r;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function s(e){return function(t){var n=t.nodeName.toLowerCase();return\"input\"===n&&t.type===e}}function u(e){return function(t){var n=t.nodeName.toLowerCase();return(\"input\"===n||\"button\"===n)&&t.type===e}}function l(e){return r(function(t){return t=+t,r(function(n,r){for(var i,o=e([],n.length,t),a=o.length;a--;)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}function c(e){return e&&\"undefined\"!=typeof e.getElementsByTagName&&e}function f(){}function d(e){for(var t=0,n=e.length,r=\"\";t<n;t++)r+=e[t].value;return r}function p(e,t,n){var r=t.dir,i=n&&\"parentNode\"===r,o=I++;return t.first?function(t,n,o){for(;t=t[r];)if(1===t.nodeType||i)return e(t,n,o)}:function(t,n,a){var s,u,l,c=[W,o];if(a){for(;t=t[r];)if((1===t.nodeType||i)&&e(t,n,a))return!0}else for(;t=t[r];)if(1===t.nodeType||i){if(l=t[P]||(t[P]={}),u=l[t.uniqueID]||(l[t.uniqueID]={}),(s=u[r])&&s[0]===W&&s[1]===o)return c[2]=s[2];if(u[r]=c,c[2]=e(t,n,a))return!0}}}function h(e){return e.length>1?function(t,n,r){for(var i=e.length;i--;)if(!e[i](t,n,r))return!1;return!0}:e[0]}function g(e,n,r){for(var i=0,o=n.length;i<o;i++)t(e,n[i],r);return r}function m(e,t,n,r,i){for(var o,a=[],s=0,u=e.length,l=null!=t;s<u;s++)(o=e[s])&&(n&&!n(o,r,i)||(a.push(o),l&&t.push(s)));return a}function y(e,t,n,i,o,a){return i&&!i[P]&&(i=y(i)),o&&!o[P]&&(o=y(o,a)),r(function(r,a,s,u){var l,c,f,d=[],p=[],h=a.length,y=r||g(t||\"*\",s.nodeType?[s]:s,[]),v=!e||!r&&t?y:m(y,d,e,s,u),x=n?o||(r?e:h||i)?[]:a:v;if(n&&n(v,x,s,u),i)for(l=m(x,p),i(l,[],s,u),c=l.length;c--;)(f=l[c])&&(x[p[c]]=!(v[p[c]]=f));if(r){if(o||e){if(o){for(l=[],c=x.length;c--;)(f=x[c])&&l.push(v[c]=f);o(null,x=[],l,u)}for(c=x.length;c--;)(f=x[c])&&(l=o?ee(r,f):d[c])>-1&&(r[l]=!(a[l]=f))}}else x=m(x===a?x.splice(h,x.length):x),o?o(null,a,x,u):Q.apply(a,x)})}function v(e){for(var t,n,r,i=e.length,o=T.relative[e[0].type],a=o||T.relative[\" \"],s=o?1:0,u=p(function(e){return e===t},a,!0),l=p(function(e){return ee(t,e)>-1},a,!0),c=[function(e,n,r){var i=!o&&(r||n!==A)||((t=n).nodeType?u(e,n,r):l(e,n,r));return t=null,i}];s<i;s++)if(n=T.relative[e[s].type])c=[p(h(c),n)];else{if(n=T.filter[e[s].type].apply(null,e[s].matches),n[P]){for(r=++s;r<i&&!T.relative[e[r].type];r++);return y(s>1&&h(c),s>1&&d(e.slice(0,s-1).concat({value:\" \"===e[s-2].type?\"*\":\"\"})).replace(se,\"$1\"),n,s<r&&v(e.slice(s,r)),r<i&&v(e=e.slice(r)),r<i&&d(e))}c.push(n)}return h(c)}function x(e,n){var i=n.length>0,o=e.length>0,a=function(r,a,s,u,l){var c,f,d,p=0,h=\"0\",g=r&&[],y=[],v=A,x=r||o&&T.find.TAG(\"*\",l),b=W+=null==v?1:Math.random()||.1,w=x.length;for(l&&(A=a===H||a||l);h!==w&&null!=(c=x[h]);h++){if(o&&c){for(f=0,a||c.ownerDocument===H||(L(c),s=!_);d=e[f++];)if(d(c,a||H,s)){u.push(c);break}l&&(W=b)}i&&((c=!d&&c)&&p--,r&&g.push(c))}if(p+=h,i&&h!==p){for(f=0;d=n[f++];)d(g,y,a,s);if(r){if(p>0)for(;h--;)g[h]||y[h]||(y[h]=G.call(u));y=m(y)}Q.apply(u,y),l&&!r&&y.length>0&&p+n.length>1&&t.uniqueSort(u)}return l&&(W=b,A=v),g};return i?r(a):a}var b,w,T,C,E,N,k,S,A,D,j,L,H,q,_,F,M,O,R,P=\"sizzle\"+1*new Date,B=e.document,W=0,I=0,$=n(),z=n(),X=n(),U=function(e,t){return e===t&&(j=!0),0},V=1<<31,Y={}.hasOwnProperty,J=[],G=J.pop,K=J.push,Q=J.push,Z=J.slice,ee=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},te=\"checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped\",ne=\"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",re=\"(?:\\\\\\\\.|[\\\\w-]|[^\\\\x00-\\\\xa0])+\",ie=\"\\\\[\"+ne+\"*(\"+re+\")(?:\"+ne+\"*([*^$|!~]?=)\"+ne+\"*(?:'((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\"|(\"+re+\"))|)\"+ne+\"*\\\\]\",oe=\":(\"+re+\")(?:\\\\((('((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\")|((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\"+ie+\")*)|.*)\\\\)|)\",ae=new RegExp(ne+\"+\",\"g\"),se=new RegExp(\"^\"+ne+\"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\"+ne+\"+$\",\"g\"),ue=new RegExp(\"^\"+ne+\"*,\"+ne+\"*\"),le=new RegExp(\"^\"+ne+\"*([>+~]|\"+ne+\")\"+ne+\"*\"),ce=new RegExp(\"=\"+ne+\"*([^\\\\]'\\\"]*?)\"+ne+\"*\\\\]\",\"g\"),fe=new RegExp(oe),de=new RegExp(\"^\"+re+\"$\"),pe={ID:new RegExp(\"^#(\"+re+\")\"),CLASS:new RegExp(\"^\\\\.(\"+re+\")\"),TAG:new RegExp(\"^(\"+re+\"|[*])\"),ATTR:new RegExp(\"^\"+ie),PSEUDO:new RegExp(\"^\"+oe),CHILD:new RegExp(\"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\"+ne+\"*(even|odd|(([+-]|)(\\\\d*)n|)\"+ne+\"*(?:([+-]|)\"+ne+\"*(\\\\d+)|))\"+ne+\"*\\\\)|)\",\"i\"),bool:new RegExp(\"^(?:\"+te+\")$\",\"i\"),needsContext:new RegExp(\"^\"+ne+\"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\"+ne+\"*((?:-\\\\d)?\\\\d*)\"+ne+\"*\\\\)|)(?=[^-]|$)\",\"i\")},he=/^(?:input|select|textarea|button)$/i,ge=/^h\\d$/i,me=/^[^{]+\\{\\s*\\[native \\w/,ye=/^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,ve=/[+~]/,xe=/'|\\\\/g,be=new RegExp(\"\\\\\\\\([\\\\da-f]{1,6}\"+ne+\"?|(\"+ne+\")|.)\",\"ig\"),we=function(e,t,n){var r=\"0x\"+t-65536;return r!==r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},Te=function(){L()};try{Q.apply(J=Z.call(B.childNodes),B.childNodes),J[B.childNodes.length].nodeType}catch(Ce){Q={apply:J.length?function(e,t){K.apply(e,Z.call(t))}:function(e,t){for(var n=e.length,r=0;e[n++]=t[r++];);e.length=n-1}}}w=t.support={},E=t.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return!!t&&\"HTML\"!==t.nodeName},L=t.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:B;return r!==H&&9===r.nodeType&&r.documentElement?(H=r,q=H.documentElement,_=!E(H),(n=H.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener(\"unload\",Te,!1):n.attachEvent&&n.attachEvent(\"onunload\",Te)),w.attributes=i(function(e){return e.className=\"i\",!e.getAttribute(\"className\")}),w.getElementsByTagName=i(function(e){return e.appendChild(H.createComment(\"\")),!e.getElementsByTagName(\"*\").length}),w.getElementsByClassName=me.test(H.getElementsByClassName),w.getById=i(function(e){return q.appendChild(e).id=P,!H.getElementsByName||!H.getElementsByName(P).length}),w.getById?(T.find.ID=function(e,t){if(\"undefined\"!=typeof t.getElementById&&_){var n=t.getElementById(e);return n?[n]:[]}},T.filter.ID=function(e){var t=e.replace(be,we);return function(e){return e.getAttribute(\"id\")===t}}):(delete T.find.ID,T.filter.ID=function(e){var t=e.replace(be,we);return function(e){var n=\"undefined\"!=typeof e.getAttributeNode&&e.getAttributeNode(\"id\");return n&&n.value===t}}),T.find.TAG=w.getElementsByTagName?function(e,t){return\"undefined\"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):w.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if(\"*\"===e){for(;n=o[i++];)1===n.nodeType&&r.push(n);return r}return o},T.find.CLASS=w.getElementsByClassName&&function(e,t){if(\"undefined\"!=typeof t.getElementsByClassName&&_)return t.getElementsByClassName(e)},M=[],F=[],(w.qsa=me.test(H.querySelectorAll))&&(i(function(e){q.appendChild(e).innerHTML=\"<a id='\"+P+\"'></a><select id='\"+P+\"-\\r\\\\' msallowcapture=''><option selected=''></option></select>\",e.querySelectorAll(\"[msallowcapture^='']\").length&&F.push(\"[*^$]=\"+ne+\"*(?:''|\\\"\\\")\"),e.querySelectorAll(\"[selected]\").length||F.push(\"\\\\[\"+ne+\"*(?:value|\"+te+\")\"),e.querySelectorAll(\"[id~=\"+P+\"-]\").length||F.push(\"~=\"),e.querySelectorAll(\":checked\").length||F.push(\":checked\"),e.querySelectorAll(\"a#\"+P+\"+*\").length||F.push(\".#.+[+~]\")}),i(function(e){var t=H.createElement(\"input\");t.setAttribute(\"type\",\"hidden\"),e.appendChild(t).setAttribute(\"name\",\"D\"),e.querySelectorAll(\"[name=d]\").length&&F.push(\"name\"+ne+\"*[*^$|!~]?=\"),e.querySelectorAll(\":enabled\").length||F.push(\":enabled\",\":disabled\"),e.querySelectorAll(\"*,:x\"),F.push(\",.*:\")})),(w.matchesSelector=me.test(O=q.matches||q.webkitMatchesSelector||q.mozMatchesSelector||q.oMatchesSelector||q.msMatchesSelector))&&i(function(e){w.disconnectedMatch=O.call(e,\"div\"),O.call(e,\"[s!='']:x\"),M.push(\"!=\",oe)}),F=F.length&&new RegExp(F.join(\"|\")),M=M.length&&new RegExp(M.join(\"|\")),t=me.test(q.compareDocumentPosition),R=t||me.test(q.contains)?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)for(;t=t.parentNode;)if(t===e)return!0;return!1},U=t?function(e,t){if(e===t)return j=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n?n:(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1,1&n||!w.sortDetached&&t.compareDocumentPosition(e)===n?e===H||e.ownerDocument===B&&R(B,e)?-1:t===H||t.ownerDocument===B&&R(B,t)?1:D?ee(D,e)-ee(D,t):0:4&n?-1:1)}:function(e,t){if(e===t)return j=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,s=[e],u=[t];if(!i||!o)return e===H?-1:t===H?1:i?-1:o?1:D?ee(D,e)-ee(D,t):0;if(i===o)return a(e,t);for(n=e;n=n.parentNode;)s.unshift(n);for(n=t;n=n.parentNode;)u.unshift(n);for(;s[r]===u[r];)r++;return r?a(s[r],u[r]):s[r]===B?-1:u[r]===B?1:0},H):H},t.matches=function(e,n){return t(e,null,null,n)},t.matchesSelector=function(e,n){if((e.ownerDocument||e)!==H&&L(e),n=n.replace(ce,\"='$1']\"),w.matchesSelector&&_&&!X[n+\" \"]&&(!M||!M.test(n))&&(!F||!F.test(n)))try{var r=O.call(e,n);if(r||w.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(i){}return t(n,H,null,[e]).length>0},t.contains=function(e,t){return(e.ownerDocument||e)!==H&&L(e),R(e,t)},t.attr=function(e,t){(e.ownerDocument||e)!==H&&L(e);var n=T.attrHandle[t.toLowerCase()],r=n&&Y.call(T.attrHandle,t.toLowerCase())?n(e,t,!_):void 0;return void 0!==r?r:w.attributes||!_?e.getAttribute(t):(r=e.getAttributeNode(t))&&r.specified?r.value:null},t.error=function(e){throw new Error(\"Syntax error, unrecognized expression: \"+e)},t.uniqueSort=function(e){var t,n=[],r=0,i=0;if(j=!w.detectDuplicates,D=!w.sortStable&&e.slice(0),e.sort(U),j){for(;t=e[i++];)t===e[i]&&(r=n.push(i));for(;r--;)e.splice(n[r],1)}return D=null,e},C=t.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+=C(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r++];)n+=C(t);return n},T=t.selectors={cacheLength:50,createPseudo:r,match:pe,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(be,we),e[3]=(e[3]||e[4]||e[5]||\"\").replace(be,we),\"~=\"===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]||t.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]&&t.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return pe.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||\"\":n&&fe.test(n)&&(t=N(n,!0))&&(t=n.indexOf(\")\",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(be,we).toLowerCase();return\"*\"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=$[e+\" \"];return t||(t=new RegExp(\"(^|\"+ne+\")\"+e+\"(\"+ne+\"|$)\"))&&$(e,function(e){return t.test(\"string\"==typeof e.className&&e.className||\"undefined\"!=typeof e.getAttribute&&e.getAttribute(\"class\")||\"\")})},ATTR:function(e,n,r){return function(i){var o=t.attr(i,e);return null==o?\"!=\"===n:!n||(o+=\"\",\"=\"===n?o===r:\"!=\"===n?o!==r:\"^=\"===n?r&&0===o.indexOf(r):\"*=\"===n?r&&o.indexOf(r)>-1:\"$=\"===n?r&&o.slice(-r.length)===r:\"~=\"===n?(\" \"+o.replace(ae,\" \")+\" \").indexOf(r)>-1:\"|=\"===n&&(o===r||o.slice(0,r.length+1)===r+\"-\"))}},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,u){var l,c,f,d,p,h,g=o!==a?\"nextSibling\":\"previousSibling\",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!u&&!s,x=!1;if(m){if(o){for(;g;){for(d=t;d=d[g];)if(s?d.nodeName.toLowerCase()===y:1===d.nodeType)return!1;h=g=\"only\"===e&&!h&&\"nextSibling\"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){for(d=m,f=d[P]||(d[P]={}),c=f[d.uniqueID]||(f[d.uniqueID]={}),\nl=c[e]||[],p=l[0]===W&&l[1],x=p&&l[2],d=p&&m.childNodes[p];d=++p&&d&&d[g]||(x=p=0)||h.pop();)if(1===d.nodeType&&++x&&d===t){c[e]=[W,p,x];break}}else if(v&&(d=t,f=d[P]||(d[P]={}),c=f[d.uniqueID]||(f[d.uniqueID]={}),l=c[e]||[],p=l[0]===W&&l[1],x=p),x===!1)for(;(d=++p&&d&&d[g]||(x=p=0)||h.pop())&&((s?d.nodeName.toLowerCase()!==y:1!==d.nodeType)||!++x||(v&&(f=d[P]||(d[P]={}),c=f[d.uniqueID]||(f[d.uniqueID]={}),c[e]=[W,x]),d!==t)););return x-=i,x===r||x%r===0&&x/r>=0}}},PSEUDO:function(e,n){var i,o=T.pseudos[e]||T.setFilters[e.toLowerCase()]||t.error(\"unsupported pseudo: \"+e);return o[P]?o(n):o.length>1?(i=[e,e,\"\",n],T.setFilters.hasOwnProperty(e.toLowerCase())?r(function(e,t){for(var r,i=o(e,n),a=i.length;a--;)r=ee(e,i[a]),e[r]=!(t[r]=i[a])}):function(e){return o(e,0,i)}):o}},pseudos:{not:r(function(e){var t=[],n=[],i=k(e.replace(se,\"$1\"));return i[P]?r(function(e,t,n,r){for(var o,a=i(e,null,r,[]),s=e.length;s--;)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,r,o){return t[0]=e,i(t,null,o,n),t[0]=null,!n.pop()}}),has:r(function(e){return function(n){return t(e,n).length>0}}),contains:r(function(e){return e=e.replace(be,we),function(t){return(t.textContent||t.innerText||C(t)).indexOf(e)>-1}}),lang:r(function(e){return de.test(e||\"\")||t.error(\"unsupported lang: \"+e),e=e.replace(be,we).toLowerCase(),function(t){var n;do if(n=_?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===q},focus:function(e){return e===H.activeElement&&(!H.hasFocus||H.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.nodeType<6)return!1;return!0},parent:function(e){return!T.pseudos.empty(e)},header:function(e){return ge.test(e.nodeName)},input:function(e){return he.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\"))||\"text\"===t.toLowerCase())},first:l(function(){return[0]}),last:l(function(e,t){return[t-1]}),eq:l(function(e,t,n){return[n<0?n+t:n]}),even:l(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:l(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:l(function(e,t,n){for(var r=n<0?n+t:n;--r>=0;)e.push(r);return e}),gt:l(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}},T.pseudos.nth=T.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})T.pseudos[b]=s(b);for(b in{submit:!0,reset:!0})T.pseudos[b]=u(b);return f.prototype=T.filters=T.pseudos,T.setFilters=new f,N=t.tokenize=function(e,n){var r,i,o,a,s,u,l,c=z[e+\" \"];if(c)return n?0:c.slice(0);for(s=e,u=[],l=T.preFilter;s;){r&&!(i=ue.exec(s))||(i&&(s=s.slice(i[0].length)||s),u.push(o=[])),r=!1,(i=le.exec(s))&&(r=i.shift(),o.push({value:r,type:i[0].replace(se,\" \")}),s=s.slice(r.length));for(a in T.filter)!(i=pe[a].exec(s))||l[a]&&!(i=l[a](i))||(r=i.shift(),o.push({value:r,type:a,matches:i}),s=s.slice(r.length));if(!r)break}return n?s.length:s?t.error(e):z(e,u).slice(0)},k=t.compile=function(e,t){var n,r=[],i=[],o=X[e+\" \"];if(!o){for(t||(t=N(e)),n=t.length;n--;)o=v(t[n]),o[P]?r.push(o):i.push(o);o=X(e,x(i,r)),o.selector=e}return o},S=t.select=function(e,t,n,r){var i,o,a,s,u,l=\"function\"==typeof e&&e,f=!r&&N(e=l.selector||e);if(n=n||[],1===f.length){if(o=f[0]=f[0].slice(0),o.length>2&&\"ID\"===(a=o[0]).type&&w.getById&&9===t.nodeType&&_&&T.relative[o[1].type]){if(t=(T.find.ID(a.matches[0].replace(be,we),t)||[])[0],!t)return n;l&&(t=t.parentNode),e=e.slice(o.shift().value.length)}for(i=pe.needsContext.test(e)?0:o.length;i--&&(a=o[i],!T.relative[s=a.type]);)if((u=T.find[s])&&(r=u(a.matches[0].replace(be,we),ve.test(o[0].type)&&c(t.parentNode)||t))){if(o.splice(i,1),e=r.length&&d(o),!e)return Q.apply(n,r),n;break}}return(l||k(e,f))(r,t,!_,n,!t||ve.test(e)&&c(t.parentNode)||t),n},w.sortStable=P.split(\"\").sort(U).join(\"\")===P,w.detectDuplicates=!!j,L(),w.sortDetached=i(function(e){return 1&e.compareDocumentPosition(H.createElement(\"div\"))}),i(function(e){return e.innerHTML=\"<a href='#'></a>\",\"#\"===e.firstChild.getAttribute(\"href\")})||o(\"type|href|height|width\",function(e,t,n){if(!n)return e.getAttribute(t,\"type\"===t.toLowerCase()?1:2)}),w.attributes&&i(function(e){return e.innerHTML=\"<input/>\",e.firstChild.setAttribute(\"value\",\"\"),\"\"===e.firstChild.getAttribute(\"value\")})||o(\"value\",function(e,t,n){if(!n&&\"input\"===e.nodeName.toLowerCase())return e.defaultValue}),i(function(e){return null==e.getAttribute(\"disabled\")})||o(te,function(e,t,n){var r;if(!n)return e[t]===!0?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),t}(e);pe.find=ve,pe.expr=ve.selectors,pe.expr[\":\"]=pe.expr.pseudos,pe.uniqueSort=pe.unique=ve.uniqueSort,pe.text=ve.getText,pe.isXMLDoc=ve.isXML,pe.contains=ve.contains;var xe=function(e,t,n){for(var r=[],i=void 0!==n;(e=e[t])&&9!==e.nodeType;)if(1===e.nodeType){if(i&&pe(e).is(n))break;r.push(e)}return r},be=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},we=pe.expr.match.needsContext,Te=/^<([\\w-]+)\\s*\\/?>(?:<\\/\\1>|)$/,Ce=/^.[^:#\\[\\.,]*$/;pe.filter=function(e,t,n){var r=t[0];return n&&(e=\":not(\"+e+\")\"),1===t.length&&1===r.nodeType?pe.find.matchesSelector(r,e)?[r]:[]:pe.find.matches(e,pe.grep(t,function(e){return 1===e.nodeType}))},pe.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if(\"string\"!=typeof e)return this.pushStack(pe(e).filter(function(){for(t=0;t<i;t++)if(pe.contains(r[t],this))return!0}));for(t=0;t<i;t++)pe.find(e,r[t],n);return n=this.pushStack(i>1?pe.unique(n):n),n.selector=this.selector?this.selector+\" \"+e:e,n},filter:function(e){return this.pushStack(r(this,e||[],!1))},not:function(e){return this.pushStack(r(this,e||[],!0))},is:function(e){return!!r(this,\"string\"==typeof e&&we.test(e)?pe(e):e||[],!1).length}});var Ee,Ne=/^(?:\\s*(<[\\w\\W]+>)[^>]*|#([\\w-]*))$/,ke=pe.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||Ee,\"string\"==typeof e){if(r=\"<\"===e.charAt(0)&&\">\"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:Ne.exec(e),!r||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof pe?t[0]:t,pe.merge(this,pe.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:re,!0)),Te.test(r[1])&&pe.isPlainObject(t))for(r in t)pe.isFunction(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}if(i=re.getElementById(r[2]),i&&i.parentNode){if(i.id!==r[2])return Ee.find(e);this.length=1,this[0]=i}return this.context=re,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):pe.isFunction(e)?\"undefined\"!=typeof n.ready?n.ready(e):e(pe):(void 0!==e.selector&&(this.selector=e.selector,this.context=e.context),pe.makeArray(e,this))};ke.prototype=pe.fn,Ee=pe(re);var Se=/^(?:parents|prev(?:Until|All))/,Ae={children:!0,contents:!0,next:!0,prev:!0};pe.fn.extend({has:function(e){var t,n=pe(e,this),r=n.length;return this.filter(function(){for(t=0;t<r;t++)if(pe.contains(this,n[t]))return!0})},closest:function(e,t){for(var n,r=0,i=this.length,o=[],a=we.test(e)||\"string\"!=typeof e?pe(e,t||this.context):0;r<i;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(n.nodeType<11&&(a?a.index(n)>-1:1===n.nodeType&&pe.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(o.length>1?pe.uniqueSort(o):o)},index:function(e){return e?\"string\"==typeof e?pe.inArray(this[0],pe(e)):pe.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(pe.uniqueSort(pe.merge(this.get(),pe(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),pe.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return xe(e,\"parentNode\")},parentsUntil:function(e,t,n){return xe(e,\"parentNode\",n)},next:function(e){return i(e,\"nextSibling\")},prev:function(e){return i(e,\"previousSibling\")},nextAll:function(e){return xe(e,\"nextSibling\")},prevAll:function(e){return xe(e,\"previousSibling\")},nextUntil:function(e,t,n){return xe(e,\"nextSibling\",n)},prevUntil:function(e,t,n){return xe(e,\"previousSibling\",n)},siblings:function(e){return be((e.parentNode||{}).firstChild,e)},children:function(e){return be(e.firstChild)},contents:function(e){return pe.nodeName(e,\"iframe\")?e.contentDocument||e.contentWindow.document:pe.merge([],e.childNodes)}},function(e,t){pe.fn[e]=function(n,r){var i=pe.map(this,t,n);return\"Until\"!==e.slice(-5)&&(r=n),r&&\"string\"==typeof r&&(i=pe.filter(r,i)),this.length>1&&(Ae[e]||(i=pe.uniqueSort(i)),Se.test(e)&&(i=i.reverse())),this.pushStack(i)}});var De=/\\S+/g;pe.Callbacks=function(e){e=\"string\"==typeof e?o(e):pe.extend({},e);var t,n,r,i,a=[],s=[],u=-1,l=function(){for(i=e.once,r=t=!0;s.length;u=-1)for(n=s.shift();++u<a.length;)a[u].apply(n[0],n[1])===!1&&e.stopOnFalse&&(u=a.length,n=!1);e.memory||(n=!1),t=!1,i&&(a=n?[]:\"\")},c={add:function(){return a&&(n&&!t&&(u=a.length-1,s.push(n)),function r(t){pe.each(t,function(t,n){pe.isFunction(n)?e.unique&&c.has(n)||a.push(n):n&&n.length&&\"string\"!==pe.type(n)&&r(n)})}(arguments),n&&!t&&l()),this},remove:function(){return pe.each(arguments,function(e,t){for(var n;(n=pe.inArray(t,a,n))>-1;)a.splice(n,1),n<=u&&u--}),this},has:function(e){return e?pe.inArray(e,a)>-1:a.length>0},empty:function(){return a&&(a=[]),this},disable:function(){return i=s=[],a=n=\"\",this},disabled:function(){return!a},lock:function(){return i=!0,n||c.disable(),this},locked:function(){return!!i},fireWith:function(e,n){return i||(n=n||[],n=[e,n.slice?n.slice():n],s.push(n),t||l()),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!r}};return c},pe.extend({Deferred:function(e){var t=[[\"resolve\",\"done\",pe.Callbacks(\"once memory\"),\"resolved\"],[\"reject\",\"fail\",pe.Callbacks(\"once memory\"),\"rejected\"],[\"notify\",\"progress\",pe.Callbacks(\"memory\")]],n=\"pending\",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return pe.Deferred(function(n){pe.each(t,function(t,o){var a=pe.isFunction(e[t])&&e[t];i[o[1]](function(){var e=a&&a.apply(this,arguments);e&&pe.isFunction(e.promise)?e.promise().progress(n.notify).done(n.resolve).fail(n.reject):n[o[0]+\"With\"](this===r?n.promise():this,a?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?pe.extend(e,r):r}},i={};return r.pipe=r.then,pe.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,n,r,i=0,o=ie.call(arguments),a=o.length,s=1!==a||e&&pe.isFunction(e.promise)?a:0,u=1===s?e:pe.Deferred(),l=function(e,n,r){return function(i){n[e]=this,r[e]=arguments.length>1?ie.call(arguments):i,r===t?u.notifyWith(n,r):--s||u.resolveWith(n,r)}};if(a>1)for(t=new Array(a),n=new Array(a),r=new Array(a);i<a;i++)o[i]&&pe.isFunction(o[i].promise)?o[i].promise().progress(l(i,n,t)).done(l(i,r,o)).fail(u.reject):--s;return s||u.resolveWith(r,o),u.promise()}});var je;pe.fn.ready=function(e){return pe.ready.promise().done(e),this},pe.extend({isReady:!1,readyWait:1,holdReady:function(e){e?pe.readyWait++:pe.ready(!0)},ready:function(e){(e===!0?--pe.readyWait:pe.isReady)||(pe.isReady=!0,e!==!0&&--pe.readyWait>0||(je.resolveWith(re,[pe]),pe.fn.triggerHandler&&(pe(re).triggerHandler(\"ready\"),pe(re).off(\"ready\"))))}}),pe.ready.promise=function(t){if(!je)if(je=pe.Deferred(),\"complete\"===re.readyState||\"loading\"!==re.readyState&&!re.documentElement.doScroll)e.setTimeout(pe.ready);else if(re.addEventListener)re.addEventListener(\"DOMContentLoaded\",s),e.addEventListener(\"load\",s);else{re.attachEvent(\"onreadystatechange\",s),e.attachEvent(\"onload\",s);var n=!1;try{n=null==e.frameElement&&re.documentElement}catch(r){}n&&n.doScroll&&!function i(){if(!pe.isReady){try{n.doScroll(\"left\")}catch(t){return e.setTimeout(i,50)}a(),pe.ready()}}()}return je.promise(t)},pe.ready.promise();var Le;for(Le in pe(fe))break;fe.ownFirst=\"0\"===Le,fe.inlineBlockNeedsLayout=!1,pe(function(){var e,t,n,r;n=re.getElementsByTagName(\"body\")[0],n&&n.style&&(t=re.createElement(\"div\"),r=re.createElement(\"div\"),r.style.cssText=\"position:absolute;border:0;width:0;height:0;top:0;left:-9999px\",n.appendChild(r).appendChild(t),\"undefined\"!=typeof t.style.zoom&&(t.style.cssText=\"display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1\",fe.inlineBlockNeedsLayout=e=3===t.offsetWidth,e&&(n.style.zoom=1)),n.removeChild(r))}),function(){var e=re.createElement(\"div\");fe.deleteExpando=!0;try{delete e.test}catch(t){fe.deleteExpando=!1}e=null}();var He=function(e){var t=pe.noData[(e.nodeName+\" \").toLowerCase()],n=+e.nodeType||1;return(1===n||9===n)&&(!t||t!==!0&&e.getAttribute(\"classid\")===t)},qe=/^(?:\\{[\\w\\W]*\\}|\\[[\\w\\W]*\\])$/,_e=/([A-Z])/g;pe.extend({cache:{},noData:{\"applet \":!0,\"embed \":!0,\"object \":\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"},hasData:function(e){return e=e.nodeType?pe.cache[e[pe.expando]]:e[pe.expando],!!e&&!l(e)},data:function(e,t,n){return c(e,t,n)},removeData:function(e,t){return f(e,t)},_data:function(e,t,n){return c(e,t,n,!0)},_removeData:function(e,t){return f(e,t,!0)}}),pe.fn.extend({data:function(e,t){var n,r,i,o=this[0],a=o&&o.attributes;if(void 0===e){if(this.length&&(i=pe.data(o),1===o.nodeType&&!pe._data(o,\"parsedAttrs\"))){for(n=a.length;n--;)a[n]&&(r=a[n].name,0===r.indexOf(\"data-\")&&(r=pe.camelCase(r.slice(5)),u(o,r,i[r])));pe._data(o,\"parsedAttrs\",!0)}return i}return\"object\"==typeof e?this.each(function(){pe.data(this,e)}):arguments.length>1?this.each(function(){pe.data(this,e,t)}):o?u(o,e,pe.data(o,e)):void 0},removeData:function(e){return this.each(function(){pe.removeData(this,e)})}}),pe.extend({queue:function(e,t,n){var r;if(e)return t=(t||\"fx\")+\"queue\",r=pe._data(e,t),n&&(!r||pe.isArray(n)?r=pe._data(e,t,pe.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||\"fx\";var n=pe.queue(e,t),r=n.length,i=n.shift(),o=pe._queueHooks(e,t),a=function(){pe.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 pe._data(e,n)||pe._data(e,n,{empty:pe.Callbacks(\"once memory\").add(function(){pe._removeData(e,t+\"queue\"),pe._removeData(e,n)})})}}),pe.fn.extend({queue:function(e,t){var n=2;return\"string\"!=typeof e&&(t=e,e=\"fx\",n--),arguments.length<n?pe.queue(this[0],e):void 0===t?this:this.each(function(){var n=pe.queue(this,e,t);pe._queueHooks(this,e),\"fx\"===e&&\"inprogress\"!==n[0]&&pe.dequeue(this,e)})},dequeue:function(e){return this.each(function(){pe.dequeue(this,e)})},clearQueue:function(e){return this.queue(e||\"fx\",[])},promise:function(e,t){var n,r=1,i=pe.Deferred(),o=this,a=this.length,s=function(){--r||i.resolveWith(o,[o])};for(\"string\"!=typeof e&&(t=e,e=void 0),e=e||\"fx\";a--;)n=pe._data(o[a],e+\"queueHooks\"),n&&n.empty&&(r++,n.empty.add(s));return s(),i.promise(t)}}),function(){var e;fe.shrinkWrapBlocks=function(){if(null!=e)return e;e=!1;var t,n,r;return n=re.getElementsByTagName(\"body\")[0],n&&n.style?(t=re.createElement(\"div\"),r=re.createElement(\"div\"),r.style.cssText=\"position:absolute;border:0;width:0;height:0;top:0;left:-9999px\",n.appendChild(r).appendChild(t),\"undefined\"!=typeof t.style.zoom&&(t.style.cssText=\"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:1px;width:1px;zoom:1\",t.appendChild(re.createElement(\"div\")).style.width=\"5px\",e=3!==t.offsetWidth),n.removeChild(r),e):void 0}}();var Fe=/[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/.source,Me=new RegExp(\"^(?:([+-])=|)(\"+Fe+\")([a-z%]*)$\",\"i\"),Oe=[\"Top\",\"Right\",\"Bottom\",\"Left\"],Re=function(e,t){return e=t||e,\"none\"===pe.css(e,\"display\")||!pe.contains(e.ownerDocument,e)},Pe=function(e,t,n,r,i,o,a){var s=0,u=e.length,l=null==n;if(\"object\"===pe.type(n)){i=!0;for(s in n)Pe(e,t,s,n[s],!0,o,a)}else if(void 0!==r&&(i=!0,pe.isFunction(r)||(a=!0),l&&(a?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(pe(e),n)})),t))for(;s<u;s++)t(e[s],n,a?r:r.call(e[s],s,t(e[s],n)));return i?e:l?t.call(e):u?t(e[0],n):o},Be=/^(?:checkbox|radio)$/i,We=/<([\\w:-]+)/,Ie=/^$|\\/(?:java|ecma)script/i,$e=/^\\s+/,ze=\"abbr|article|aside|audio|bdi|canvas|data|datalist|details|dialog|figcaption|figure|footer|header|hgroup|main|mark|meter|nav|output|picture|progress|section|summary|template|time|video\";!function(){var e=re.createElement(\"div\"),t=re.createDocumentFragment(),n=re.createElement(\"input\");e.innerHTML=\"  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>\",fe.leadingWhitespace=3===e.firstChild.nodeType,fe.tbody=!e.getElementsByTagName(\"tbody\").length,fe.htmlSerialize=!!e.getElementsByTagName(\"link\").length,fe.html5Clone=\"<:nav></:nav>\"!==re.createElement(\"nav\").cloneNode(!0).outerHTML,n.type=\"checkbox\",n.checked=!0,t.appendChild(n),fe.appendChecked=n.checked,e.innerHTML=\"<textarea>x</textarea>\",fe.noCloneChecked=!!e.cloneNode(!0).lastChild.defaultValue,t.appendChild(e),n=re.createElement(\"input\"),n.setAttribute(\"type\",\"radio\"),n.setAttribute(\"checked\",\"checked\"),n.setAttribute(\"name\",\"t\"),e.appendChild(n),fe.checkClone=e.cloneNode(!0).cloneNode(!0).lastChild.checked,fe.noCloneEvent=!!e.addEventListener,e[pe.expando]=1,fe.attributes=!e.getAttribute(pe.expando)}();var Xe={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:fe.htmlSerialize?[0,\"\",\"\"]:[1,\"X<div>\",\"</div>\"]};Xe.optgroup=Xe.option,Xe.tbody=Xe.tfoot=Xe.colgroup=Xe.caption=Xe.thead,Xe.th=Xe.td;var Ue=/<|&#?\\w+;/,Ve=/<tbody/i;!function(){var t,n,r=re.createElement(\"div\");for(t in{submit:!0,change:!0,focusin:!0})n=\"on\"+t,(fe[t]=n in e)||(r.setAttribute(n,\"t\"),fe[t]=r.attributes[n].expando===!1);r=null}();var Ye=/^(?:input|select|textarea)$/i,Je=/^key/,Ge=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ke=/^(?:focusinfocus|focusoutblur)$/,Qe=/^([^.]*)(?:\\.(.+)|)/;pe.event={global:{},add:function(e,t,n,r,i){var o,a,s,u,l,c,f,d,p,h,g,m=pe._data(e);if(m){for(n.handler&&(u=n,n=u.handler,i=u.selector),n.guid||(n.guid=pe.guid++),(a=m.events)||(a=m.events={}),(c=m.handle)||(c=m.handle=function(e){return\"undefined\"==typeof pe||e&&pe.event.triggered===e.type?void 0:pe.event.dispatch.apply(c.elem,arguments)},c.elem=e),t=(t||\"\").match(De)||[\"\"],s=t.length;s--;)o=Qe.exec(t[s])||[],p=g=o[1],h=(o[2]||\"\").split(\".\").sort(),p&&(l=pe.event.special[p]||{},p=(i?l.delegateType:l.bindType)||p,l=pe.event.special[p]||{},f=pe.extend({type:p,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&pe.expr.match.needsContext.test(i),namespace:h.join(\".\")},u),(d=a[p])||(d=a[p]=[],d.delegateCount=0,l.setup&&l.setup.call(e,r,h,c)!==!1||(e.addEventListener?e.addEventListener(p,c,!1):e.attachEvent&&e.attachEvent(\"on\"+p,c))),l.add&&(l.add.call(e,f),f.handler.guid||(f.handler.guid=n.guid)),i?d.splice(d.delegateCount++,0,f):d.push(f),pe.event.global[p]=!0);e=null}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,d,p,h,g,m=pe.hasData(e)&&pe._data(e);if(m&&(c=m.events)){for(t=(t||\"\").match(De)||[\"\"],l=t.length;l--;)if(s=Qe.exec(t[l])||[],p=g=s[1],h=(s[2]||\"\").split(\".\").sort(),p){for(f=pe.event.special[p]||{},p=(r?f.delegateType:f.bindType)||p,d=c[p]||[],s=s[2]&&new RegExp(\"(^|\\\\.)\"+h.join(\"\\\\.(?:.*\\\\.|)\")+\"(\\\\.|$)\"),u=o=d.length;o--;)a=d[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&(\"**\"!==r||!a.selector)||(d.splice(o,1),a.selector&&d.delegateCount--,f.remove&&f.remove.call(e,a));u&&!d.length&&(f.teardown&&f.teardown.call(e,h,m.handle)!==!1||pe.removeEvent(e,p,m.handle),delete c[p])}else for(p in c)pe.event.remove(e,p+t[l],n,r,!0);pe.isEmptyObject(c)&&(delete m.handle,pe._removeData(e,\"events\"))}},trigger:function(t,n,r,i){var o,a,s,u,l,c,f,d=[r||re],p=ce.call(t,\"type\")?t.type:t,h=ce.call(t,\"namespace\")?t.namespace.split(\".\"):[];if(s=c=r=r||re,3!==r.nodeType&&8!==r.nodeType&&!Ke.test(p+pe.event.triggered)&&(p.indexOf(\".\")>-1&&(h=p.split(\".\"),p=h.shift(),h.sort()),a=p.indexOf(\":\")<0&&\"on\"+p,t=t[pe.expando]?t:new pe.Event(p,\"object\"==typeof t&&t),t.isTrigger=i?2:3,t.namespace=h.join(\".\"),t.rnamespace=t.namespace?new RegExp(\"(^|\\\\.)\"+h.join(\"\\\\.(?:.*\\\\.|)\")+\"(\\\\.|$)\"):null,t.result=void 0,t.target||(t.target=r),n=null==n?[t]:pe.makeArray(n,[t]),l=pe.event.special[p]||{},i||!l.trigger||l.trigger.apply(r,n)!==!1)){if(!i&&!l.noBubble&&!pe.isWindow(r)){for(u=l.delegateType||p,Ke.test(u+p)||(s=s.parentNode);s;s=s.parentNode)d.push(s),c=s;c===(r.ownerDocument||re)&&d.push(c.defaultView||c.parentWindow||e)}for(f=0;(s=d[f++])&&!t.isPropagationStopped();)t.type=f>1?u:l.bindType||p,o=(pe._data(s,\"events\")||{})[t.type]&&pe._data(s,\"handle\"),o&&o.apply(s,n),o=a&&s[a],o&&o.apply&&He(s)&&(t.result=o.apply(s,n),t.result===!1&&t.preventDefault());if(t.type=p,!i&&!t.isDefaultPrevented()&&(!l._default||l._default.apply(d.pop(),n)===!1)&&He(r)&&a&&r[p]&&!pe.isWindow(r)){c=r[a],c&&(r[a]=null),pe.event.triggered=p;try{r[p]()}catch(g){}pe.event.triggered=void 0,c&&(r[a]=c)}return t.result}},dispatch:function(e){e=pe.event.fix(e);var t,n,r,i,o,a=[],s=ie.call(arguments),u=(pe._data(this,\"events\")||{})[e.type]||[],l=pe.event.special[e.type]||{};if(s[0]=e,e.delegateTarget=this,!l.preDispatch||l.preDispatch.call(this,e)!==!1){for(a=pe.event.handlers.call(this,e,u),t=0;(i=a[t++])&&!e.isPropagationStopped();)for(e.currentTarget=i.elem,n=0;(o=i.handlers[n++])&&!e.isImmediatePropagationStopped();)e.rnamespace&&!e.rnamespace.test(o.namespace)||(e.handleObj=o,e.data=o.data,r=((pe.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,s),void 0!==r&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()));return l.postDispatch&&l.postDispatch.call(this,e),e.result}},handlers:function(e,t){var n,r,i,o,a=[],s=t.delegateCount,u=e.target;if(s&&u.nodeType&&(\"click\"!==e.type||isNaN(e.button)||e.button<1))for(;u!=this;u=u.parentNode||this)if(1===u.nodeType&&(u.disabled!==!0||\"click\"!==e.type)){for(r=[],n=0;n<s;n++)o=t[n],i=o.selector+\" \",void 0===r[i]&&(r[i]=o.needsContext?pe(i,this).index(u)>-1:pe.find(i,this,null,[u]).length),r[i]&&r.push(o);r.length&&a.push({elem:u,handlers:r})}return s<t.length&&a.push({elem:this,handlers:t.slice(s)}),a},fix:function(e){if(e[pe.expando])return e;var t,n,r,i=e.type,o=e,a=this.fixHooks[i];for(a||(this.fixHooks[i]=a=Ge.test(i)?this.mouseHooks:Je.test(i)?this.keyHooks:{}),r=a.props?this.props.concat(a.props):this.props,e=new pe.Event(o),t=r.length;t--;)n=r[t],e[n]=o[n];return e.target||(e.target=o.srcElement||re),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,a.filter?a.filter(e,o):e},props:\"altKey bubbles cancelable ctrlKey currentTarget detail 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,t){var n,r,i,o=t.button,a=t.fromElement;return null==e.pageX&&null!=t.clientX&&(r=e.target.ownerDocument||re,i=r.documentElement,n=r.body,e.pageX=t.clientX+(i&&i.scrollLeft||n&&n.scrollLeft||0)-(i&&i.clientLeft||n&&n.clientLeft||0),e.pageY=t.clientY+(i&&i.scrollTop||n&&n.scrollTop||0)-(i&&i.clientTop||n&&n.clientTop||0)),!e.relatedTarget&&a&&(e.relatedTarget=a===e.target?t.toElement:a),e.which||void 0===o||(e.which=1&o?1:2&o?3:4&o?2:0),e}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==b()&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:\"focusin\"},blur:{trigger:function(){if(this===b()&&this.blur)return this.blur(),!1},delegateType:\"focusout\"},click:{trigger:function(){if(pe.nodeName(this,\"input\")&&\"checkbox\"===this.type&&this.click)return this.click(),!1},_default:function(e){return pe.nodeName(e.target,\"a\")}},beforeunload:{postDispatch:function(e){void 0!==e.result&&e.originalEvent&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n){var r=pe.extend(new pe.Event,n,{type:e,isSimulated:!0});pe.event.trigger(r,null,t),r.isDefaultPrevented()&&n.preventDefault()}},pe.removeEvent=re.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n)}:function(e,t,n){var r=\"on\"+t;e.detachEvent&&(\"undefined\"==typeof e[r]&&(e[r]=null),e.detachEvent(r,n))},pe.Event=function(e,t){return this instanceof pe.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||void 0===e.defaultPrevented&&e.returnValue===!1?v:x):this.type=e,t&&pe.extend(this,t),this.timeStamp=e&&e.timeStamp||pe.now(),void(this[pe.expando]=!0)):new pe.Event(e,t)},pe.Event.prototype={constructor:pe.Event,isDefaultPrevented:x,isPropagationStopped:x,isImmediatePropagationStopped:x,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=v,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=v,e&&!this.isSimulated&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){var e=this.originalEvent;this.isImmediatePropagationStopped=v,e&&e.stopImmediatePropagation&&e.stopImmediatePropagation(),this.stopPropagation()}},pe.each({mouseenter:\"mouseover\",mouseleave:\"mouseout\",pointerenter:\"pointerover\",pointerleave:\"pointerout\"},function(e,t){pe.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return i&&(i===r||pe.contains(r,i))||(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),fe.submit||(pe.event.special.submit={setup:function(){return!pe.nodeName(this,\"form\")&&void pe.event.add(this,\"click._submit keypress._submit\",function(e){var t=e.target,n=pe.nodeName(t,\"input\")||pe.nodeName(t,\"button\")?pe.prop(t,\"form\"):void 0;n&&!pe._data(n,\"submit\")&&(pe.event.add(n,\"submit._submit\",function(e){e._submitBubble=!0}),pe._data(n,\"submit\",!0))})},postDispatch:function(e){e._submitBubble&&(delete e._submitBubble,this.parentNode&&!e.isTrigger&&pe.event.simulate(\"submit\",this.parentNode,e))},teardown:function(){return!pe.nodeName(this,\"form\")&&void pe.event.remove(this,\"._submit\")}}),fe.change||(pe.event.special.change={setup:function(){return Ye.test(this.nodeName)?(\"checkbox\"!==this.type&&\"radio\"!==this.type||(pe.event.add(this,\"propertychange._change\",function(e){\"checked\"===e.originalEvent.propertyName&&(this._justChanged=!0)}),pe.event.add(this,\"click._change\",function(e){this._justChanged&&!e.isTrigger&&(this._justChanged=!1),pe.event.simulate(\"change\",this,e)})),!1):void pe.event.add(this,\"beforeactivate._change\",function(e){var t=e.target;Ye.test(t.nodeName)&&!pe._data(t,\"change\")&&(pe.event.add(t,\"change._change\",function(e){!this.parentNode||e.isSimulated||e.isTrigger||pe.event.simulate(\"change\",this.parentNode,e)}),pe._data(t,\"change\",!0))})},handle:function(e){var t=e.target;if(this!==t||e.isSimulated||e.isTrigger||\"radio\"!==t.type&&\"checkbox\"!==t.type)return e.handleObj.handler.apply(this,arguments)},teardown:function(){return pe.event.remove(this,\"._change\"),!Ye.test(this.nodeName)}}),fe.focusin||pe.each({focus:\"focusin\",blur:\"focusout\"},function(e,t){var n=function(e){pe.event.simulate(t,e.target,pe.event.fix(e))};pe.event.special[t]={setup:function(){var r=this.ownerDocument||this,i=pe._data(r,t);i||r.addEventListener(e,n,!0),pe._data(r,t,(i||0)+1)},teardown:function(){var r=this.ownerDocument||this,i=pe._data(r,t)-1;i?pe._data(r,t,i):(r.removeEventListener(e,n,!0),pe._removeData(r,t))}}}),pe.fn.extend({on:function(e,t,n,r){return w(this,e,t,n,r)},one:function(e,t,n,r){return w(this,e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,pe(e.delegateTarget).off(r.namespace?r.origType+\".\"+r.namespace:r.origType,r.selector,r.handler),this;if(\"object\"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return t!==!1&&\"function\"!=typeof t||(n=t,t=void 0),n===!1&&(n=x),this.each(function(){pe.event.remove(this,e,n,t)})},trigger:function(e,t){return this.each(function(){pe.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return pe.event.trigger(e,t,n,!0)}});var Ze=/ jQuery\\d+=\"(?:null|\\d+)\"/g,et=new RegExp(\"<(?:\"+ze+\")[\\\\s/>]\",\"i\"),tt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:-]+)[^>]*)\\/>/gi,nt=/<script|<style|<link/i,rt=/checked\\s*(?:[^=]|=\\s*.checked.)/i,it=/^true\\/(.*)/,ot=/^\\s*<!(?:\\[CDATA\\[|--)|(?:\\]\\]|--)>\\s*$/g,at=p(re),st=at.appendChild(re.createElement(\"div\"));pe.extend({htmlPrefilter:function(e){return e.replace(tt,\"<$1></$2>\")},clone:function(e,t,n){var r,i,o,a,s,u=pe.contains(e.ownerDocument,e);if(fe.html5Clone||pe.isXMLDoc(e)||!et.test(\"<\"+e.nodeName+\">\")?o=e.cloneNode(!0):(st.innerHTML=e.outerHTML,st.removeChild(o=st.firstChild)),!(fe.noCloneEvent&&fe.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||pe.isXMLDoc(e)))for(r=h(o),s=h(e),a=0;null!=(i=s[a]);++a)r[a]&&k(i,r[a]);if(t)if(n)for(s=s||h(e),r=r||h(o),a=0;null!=(i=s[a]);a++)N(i,r[a]);else N(e,o);return r=h(o,\"script\"),r.length>0&&g(r,!u&&h(e,\"script\")),r=s=i=null,o},cleanData:function(e,t){for(var n,r,i,o,a=0,s=pe.expando,u=pe.cache,l=fe.attributes,c=pe.event.special;null!=(n=e[a]);a++)if((t||He(n))&&(i=n[s],o=i&&u[i])){if(o.events)for(r in o.events)c[r]?pe.event.remove(n,r):pe.removeEvent(n,r,o.handle);u[i]&&(delete u[i],l||\"undefined\"==typeof n.removeAttribute?n[s]=void 0:n.removeAttribute(s),ne.push(i))}}}),pe.fn.extend({domManip:S,detach:function(e){return A(this,e,!0)},remove:function(e){return A(this,e)},text:function(e){return Pe(this,function(e){return void 0===e?pe.text(this):this.empty().append((this[0]&&this[0].ownerDocument||re).createTextNode(e))},null,e,arguments.length)},append:function(){return S(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=T(this,e);t.appendChild(e)}})},prepend:function(){return S(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=T(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return S(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return S(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++){for(1===e.nodeType&&pe.cleanData(h(e,!1));e.firstChild;)e.removeChild(e.firstChild);e.options&&pe.nodeName(e,\"select\")&&(e.options.length=0)}return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return pe.clone(this,e,t)})},html:function(e){return Pe(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e)return 1===t.nodeType?t.innerHTML.replace(Ze,\"\"):void 0;if(\"string\"==typeof e&&!nt.test(e)&&(fe.htmlSerialize||!et.test(e))&&(fe.leadingWhitespace||!$e.test(e))&&!Xe[(We.exec(e)||[\"\",\"\"])[1].toLowerCase()]){e=pe.htmlPrefilter(e);try{for(;n<r;n++)t=this[n]||{},1===t.nodeType&&(pe.cleanData(h(t,!1)),t.innerHTML=e);t=0}catch(i){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=[];return S(this,arguments,function(t){var n=this.parentNode;pe.inArray(this,e)<0&&(pe.cleanData(h(this)),\nn&&n.replaceChild(t,this))},e)}}),pe.each({appendTo:\"append\",prependTo:\"prepend\",insertBefore:\"before\",insertAfter:\"after\",replaceAll:\"replaceWith\"},function(e,t){pe.fn[e]=function(e){for(var n,r=0,i=[],o=pe(e),a=o.length-1;r<=a;r++)n=r===a?this:this.clone(!0),pe(o[r])[t](n),ae.apply(i,n.get());return this.pushStack(i)}});var ut,lt={HTML:\"block\",BODY:\"block\"},ct=/^margin/,ft=new RegExp(\"^(\"+Fe+\")(?!px)[a-z%]+$\",\"i\"),dt=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},pt=re.documentElement;!function(){function t(){var t,c,f=re.documentElement;f.appendChild(u),l.style.cssText=\"-webkit-box-sizing:border-box;box-sizing:border-box;position:relative;display:block;margin:auto;border:1px;padding:1px;top:1%;width:50%\",n=i=s=!1,r=a=!0,e.getComputedStyle&&(c=e.getComputedStyle(l),n=\"1%\"!==(c||{}).top,s=\"2px\"===(c||{}).marginLeft,i=\"4px\"===(c||{width:\"4px\"}).width,l.style.marginRight=\"50%\",r=\"4px\"===(c||{marginRight:\"4px\"}).marginRight,t=l.appendChild(re.createElement(\"div\")),t.style.cssText=l.style.cssText=\"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0\",t.style.marginRight=t.style.width=\"0\",l.style.width=\"1px\",a=!parseFloat((e.getComputedStyle(t)||{}).marginRight),l.removeChild(t)),l.style.display=\"none\",o=0===l.getClientRects().length,o&&(l.style.display=\"\",l.innerHTML=\"<table><tr><td></td><td>t</td></tr></table>\",t=l.getElementsByTagName(\"td\"),t[0].style.cssText=\"margin:0;border:0;padding:0;display:none\",o=0===t[0].offsetHeight,o&&(t[0].style.display=\"\",t[1].style.display=\"none\",o=0===t[0].offsetHeight)),f.removeChild(u)}var n,r,i,o,a,s,u=re.createElement(\"div\"),l=re.createElement(\"div\");l.style&&(l.style.cssText=\"float:left;opacity:.5\",fe.opacity=\"0.5\"===l.style.opacity,fe.cssFloat=!!l.style.cssFloat,l.style.backgroundClip=\"content-box\",l.cloneNode(!0).style.backgroundClip=\"\",fe.clearCloneStyle=\"content-box\"===l.style.backgroundClip,u=re.createElement(\"div\"),u.style.cssText=\"border:0;width:8px;height:0;top:0;left:-9999px;padding:0;margin-top:1px;position:absolute\",l.innerHTML=\"\",u.appendChild(l),fe.boxSizing=\"\"===l.style.boxSizing||\"\"===l.style.MozBoxSizing||\"\"===l.style.WebkitBoxSizing,pe.extend(fe,{reliableHiddenOffsets:function(){return null==n&&t(),o},boxSizingReliable:function(){return null==n&&t(),i},pixelMarginRight:function(){return null==n&&t(),r},pixelPosition:function(){return null==n&&t(),n},reliableMarginRight:function(){return null==n&&t(),a},reliableMarginLeft:function(){return null==n&&t(),s}}))}();var ht,gt,mt=/^(top|right|bottom|left)$/;e.getComputedStyle?(ht=function(t){var n=t.ownerDocument.defaultView;return n&&n.opener||(n=e),n.getComputedStyle(t)},gt=function(e,t,n){var r,i,o,a,s=e.style;return n=n||ht(e),a=n?n.getPropertyValue(t)||n[t]:void 0,\"\"!==a&&void 0!==a||pe.contains(e.ownerDocument,e)||(a=pe.style(e,t)),n&&!fe.pixelMarginRight()&&ft.test(a)&&ct.test(t)&&(r=s.width,i=s.minWidth,o=s.maxWidth,s.minWidth=s.maxWidth=s.width=a,a=n.width,s.width=r,s.minWidth=i,s.maxWidth=o),void 0===a?a:a+\"\"}):pt.currentStyle&&(ht=function(e){return e.currentStyle},gt=function(e,t,n){var r,i,o,a,s=e.style;return n=n||ht(e),a=n?n[t]:void 0,null==a&&s&&s[t]&&(a=s[t]),ft.test(a)&&!mt.test(t)&&(r=s.left,i=e.runtimeStyle,o=i&&i.left,o&&(i.left=e.currentStyle.left),s.left=\"fontSize\"===t?\"1em\":a,a=s.pixelLeft+\"px\",s.left=r,o&&(i.left=o)),void 0===a?a:a+\"\"||\"auto\"});var yt=/alpha\\([^)]*\\)/i,vt=/opacity\\s*=\\s*([^)]*)/i,xt=/^(none|table(?!-c[ea]).+)/,bt=new RegExp(\"^(\"+Fe+\")(.*)$\",\"i\"),wt={position:\"absolute\",visibility:\"hidden\",display:\"block\"},Tt={letterSpacing:\"0\",fontWeight:\"400\"},Ct=[\"Webkit\",\"O\",\"Moz\",\"ms\"],Et=re.createElement(\"div\").style;pe.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=gt(e,\"opacity\");return\"\"===n?\"1\":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{\"float\":fe.cssFloat?\"cssFloat\":\"styleFloat\"},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=pe.camelCase(t),u=e.style;if(t=pe.cssProps[s]||(pe.cssProps[s]=H(s)||s),a=pe.cssHooks[t]||pe.cssHooks[s],void 0===n)return a&&\"get\"in a&&void 0!==(i=a.get(e,!1,r))?i:u[t];if(o=typeof n,\"string\"===o&&(i=Me.exec(n))&&i[1]&&(n=d(e,t,i),o=\"number\"),null!=n&&n===n&&(\"number\"===o&&(n+=i&&i[3]||(pe.cssNumber[s]?\"\":\"px\")),fe.clearCloneStyle||\"\"!==n||0!==t.indexOf(\"background\")||(u[t]=\"inherit\"),!(a&&\"set\"in a&&void 0===(n=a.set(e,n,r)))))try{u[t]=n}catch(l){}}},css:function(e,t,n,r){var i,o,a,s=pe.camelCase(t);return t=pe.cssProps[s]||(pe.cssProps[s]=H(s)||s),a=pe.cssHooks[t]||pe.cssHooks[s],a&&\"get\"in a&&(o=a.get(e,!0,n)),void 0===o&&(o=gt(e,t,r)),\"normal\"===o&&t in Tt&&(o=Tt[t]),\"\"===n||n?(i=parseFloat(o),n===!0||isFinite(i)?i||0:o):o}}),pe.each([\"height\",\"width\"],function(e,t){pe.cssHooks[t]={get:function(e,n,r){if(n)return xt.test(pe.css(e,\"display\"))&&0===e.offsetWidth?dt(e,wt,function(){return M(e,t,r)}):M(e,t,r)},set:function(e,n,r){var i=r&&ht(e);return _(e,n,r?F(e,t,r,fe.boxSizing&&\"border-box\"===pe.css(e,\"boxSizing\",!1,i),i):0)}}}),fe.opacity||(pe.cssHooks.opacity={get:function(e,t){return vt.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=pe.isNumeric(t)?\"alpha(opacity=\"+100*t+\")\":\"\",o=r&&r.filter||n.filter||\"\";n.zoom=1,(t>=1||\"\"===t)&&\"\"===pe.trim(o.replace(yt,\"\"))&&n.removeAttribute&&(n.removeAttribute(\"filter\"),\"\"===t||r&&!r.filter)||(n.filter=yt.test(o)?o.replace(yt,i):o+\" \"+i)}}),pe.cssHooks.marginRight=L(fe.reliableMarginRight,function(e,t){if(t)return dt(e,{display:\"inline-block\"},gt,[e,\"marginRight\"])}),pe.cssHooks.marginLeft=L(fe.reliableMarginLeft,function(e,t){if(t)return(parseFloat(gt(e,\"marginLeft\"))||(pe.contains(e.ownerDocument,e)?e.getBoundingClientRect().left-dt(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}):0))+\"px\"}),pe.each({margin:\"\",padding:\"\",border:\"Width\"},function(e,t){pe.cssHooks[e+t]={expand:function(n){for(var r=0,i={},o=\"string\"==typeof n?n.split(\" \"):[n];r<4;r++)i[e+Oe[r]+t]=o[r]||o[r-2]||o[0];return i}},ct.test(e)||(pe.cssHooks[e+t].set=_)}),pe.fn.extend({css:function(e,t){return Pe(this,function(e,t,n){var r,i,o={},a=0;if(pe.isArray(t)){for(r=ht(e),i=t.length;a<i;a++)o[t[a]]=pe.css(e,t[a],!1,r);return o}return void 0!==n?pe.style(e,t,n):pe.css(e,t)},e,t,arguments.length>1)},show:function(){return q(this,!0)},hide:function(){return q(this)},toggle:function(e){return\"boolean\"==typeof e?e?this.show():this.hide():this.each(function(){Re(this)?pe(this).show():pe(this).hide()})}}),pe.Tween=O,O.prototype={constructor:O,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||pe.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(pe.cssNumber[n]?\"\":\"px\")},cur:function(){var e=O.propHooks[this.prop];return e&&e.get?e.get(this):O.propHooks._default.get(this)},run:function(e){var t,n=O.propHooks[this.prop];return this.options.duration?this.pos=t=pe.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=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):O.propHooks._default.set(this),this}},O.prototype.init.prototype=O.prototype,O.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=pe.css(e.elem,e.prop,\"\"),t&&\"auto\"!==t?t:0)},set:function(e){pe.fx.step[e.prop]?pe.fx.step[e.prop](e):1!==e.elem.nodeType||null==e.elem.style[pe.cssProps[e.prop]]&&!pe.cssHooks[e.prop]?e.elem[e.prop]=e.now:pe.style(e.elem,e.prop,e.now+e.unit)}}},O.propHooks.scrollTop=O.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},pe.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:\"swing\"},pe.fx=O.prototype.init,pe.fx.step={};var Nt,kt,St=/^(?:toggle|show|hide)$/,At=/queueHooks$/;pe.Animation=pe.extend($,{tweeners:{\"*\":[function(e,t){var n=this.createTween(e,t);return d(n.elem,e,Me.exec(t),n),n}]},tweener:function(e,t){pe.isFunction(e)?(t=e,e=[\"*\"]):e=e.match(De);for(var n,r=0,i=e.length;r<i;r++)n=e[r],$.tweeners[n]=$.tweeners[n]||[],$.tweeners[n].unshift(t)},prefilters:[W],prefilter:function(e,t){t?$.prefilters.unshift(e):$.prefilters.push(e)}}),pe.speed=function(e,t,n){var r=e&&\"object\"==typeof e?pe.extend({},e):{complete:n||!n&&t||pe.isFunction(e)&&e,duration:e,easing:n&&t||t&&!pe.isFunction(t)&&t};return r.duration=pe.fx.off?0:\"number\"==typeof r.duration?r.duration:r.duration in pe.fx.speeds?pe.fx.speeds[r.duration]:pe.fx.speeds._default,null!=r.queue&&r.queue!==!0||(r.queue=\"fx\"),r.old=r.complete,r.complete=function(){pe.isFunction(r.old)&&r.old.call(this),r.queue&&pe.dequeue(this,r.queue)},r},pe.fn.extend({fadeTo:function(e,t,n,r){return this.filter(Re).css(\"opacity\",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=pe.isEmptyObject(e),o=pe.speed(t,n,r),a=function(){var t=$(this,pe.extend({},e),o);(i||pe._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,t,n){var r=function(e){var t=e.stop;delete e.stop,t(n)};return\"string\"!=typeof e&&(n=t,t=e,e=void 0),t&&e!==!1&&this.queue(e||\"fx\",[]),this.each(function(){var t=!0,i=null!=e&&e+\"queueHooks\",o=pe.timers,a=pe._data(this);if(i)a[i]&&a[i].stop&&r(a[i]);else for(i in a)a[i]&&a[i].stop&&At.test(i)&&r(a[i]);for(i=o.length;i--;)o[i].elem!==this||null!=e&&o[i].queue!==e||(o[i].anim.stop(n),t=!1,o.splice(i,1));!t&&n||pe.dequeue(this,e)})},finish:function(e){return e!==!1&&(e=e||\"fx\"),this.each(function(){var t,n=pe._data(this),r=n[e+\"queue\"],i=n[e+\"queueHooks\"],o=pe.timers,a=r?r.length:0;for(n.finish=!0,pe.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;t<a;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}}),pe.each([\"toggle\",\"show\",\"hide\"],function(e,t){var n=pe.fn[t];pe.fn[t]=function(e,r,i){return null==e||\"boolean\"==typeof e?n.apply(this,arguments):this.animate(P(t,!0),e,r,i)}}),pe.each({slideDown:P(\"show\"),slideUp:P(\"hide\"),slideToggle:P(\"toggle\"),fadeIn:{opacity:\"show\"},fadeOut:{opacity:\"hide\"},fadeToggle:{opacity:\"toggle\"}},function(e,t){pe.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),pe.timers=[],pe.fx.tick=function(){var e,t=pe.timers,n=0;for(Nt=pe.now();n<t.length;n++)e=t[n],e()||t[n]!==e||t.splice(n--,1);t.length||pe.fx.stop(),Nt=void 0},pe.fx.timer=function(e){pe.timers.push(e),e()?pe.fx.start():pe.timers.pop()},pe.fx.interval=13,pe.fx.start=function(){kt||(kt=e.setInterval(pe.fx.tick,pe.fx.interval))},pe.fx.stop=function(){e.clearInterval(kt),kt=null},pe.fx.speeds={slow:600,fast:200,_default:400},pe.fn.delay=function(t,n){return t=pe.fx?pe.fx.speeds[t]||t:t,n=n||\"fx\",this.queue(n,function(n,r){var i=e.setTimeout(n,t);r.stop=function(){e.clearTimeout(i)}})},function(){var e,t=re.createElement(\"input\"),n=re.createElement(\"div\"),r=re.createElement(\"select\"),i=r.appendChild(re.createElement(\"option\"));n=re.createElement(\"div\"),n.setAttribute(\"className\",\"t\"),n.innerHTML=\"  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>\",e=n.getElementsByTagName(\"a\")[0],t.setAttribute(\"type\",\"checkbox\"),n.appendChild(t),e=n.getElementsByTagName(\"a\")[0],e.style.cssText=\"top:1px\",fe.getSetAttribute=\"t\"!==n.className,fe.style=/top/.test(e.getAttribute(\"style\")),fe.hrefNormalized=\"/a\"===e.getAttribute(\"href\"),fe.checkOn=!!t.value,fe.optSelected=i.selected,fe.enctype=!!re.createElement(\"form\").enctype,r.disabled=!0,fe.optDisabled=!i.disabled,t=re.createElement(\"input\"),t.setAttribute(\"value\",\"\"),fe.input=\"\"===t.getAttribute(\"value\"),t.value=\"t\",t.setAttribute(\"type\",\"radio\"),fe.radioValue=\"t\"===t.value}();var Dt=/\\r/g,jt=/[\\x20\\t\\r\\n\\f]+/g;pe.fn.extend({val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=pe.isFunction(e),this.each(function(n){var i;1===this.nodeType&&(i=r?e.call(this,n,pe(this).val()):e,null==i?i=\"\":\"number\"==typeof i?i+=\"\":pe.isArray(i)&&(i=pe.map(i,function(e){return null==e?\"\":e+\"\"})),t=pe.valHooks[this.type]||pe.valHooks[this.nodeName.toLowerCase()],t&&\"set\"in t&&void 0!==t.set(this,i,\"value\")||(this.value=i))});if(i)return t=pe.valHooks[i.type]||pe.valHooks[i.nodeName.toLowerCase()],t&&\"get\"in t&&void 0!==(n=t.get(i,\"value\"))?n:(n=i.value,\"string\"==typeof n?n.replace(Dt,\"\"):null==n?\"\":n)}}}),pe.extend({valHooks:{option:{get:function(e){var t=pe.find.attr(e,\"value\");return null!=t?t:pe.trim(pe.text(e)).replace(jt,\" \")}},select:{get:function(e){for(var t,n,r=e.options,i=e.selectedIndex,o=\"select-one\"===e.type||i<0,a=o?null:[],s=o?i+1:r.length,u=i<0?s:o?i:0;u<s;u++)if(n=r[u],(n.selected||u===i)&&(fe.optDisabled?!n.disabled:null===n.getAttribute(\"disabled\"))&&(!n.parentNode.disabled||!pe.nodeName(n.parentNode,\"optgroup\"))){if(t=pe(n).val(),o)return t;a.push(t)}return a},set:function(e,t){for(var n,r,i=e.options,o=pe.makeArray(t),a=i.length;a--;)if(r=i[a],pe.inArray(pe.valHooks.option.get(r),o)>-1)try{r.selected=n=!0}catch(s){r.scrollHeight}else r.selected=!1;return n||(e.selectedIndex=-1),i}}}}),pe.each([\"radio\",\"checkbox\"],function(){pe.valHooks[this]={set:function(e,t){if(pe.isArray(t))return e.checked=pe.inArray(pe(e).val(),t)>-1}},fe.checkOn||(pe.valHooks[this].get=function(e){return null===e.getAttribute(\"value\")?\"on\":e.value})});var Lt,Ht,qt=pe.expr.attrHandle,_t=/^(?:checked|selected)$/i,Ft=fe.getSetAttribute,Mt=fe.input;pe.fn.extend({attr:function(e,t){return Pe(this,pe.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){pe.removeAttr(this,e)})}}),pe.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return\"undefined\"==typeof e.getAttribute?pe.prop(e,t,n):(1===o&&pe.isXMLDoc(e)||(t=t.toLowerCase(),i=pe.attrHooks[t]||(pe.expr.match.bool.test(t)?Ht:Lt)),void 0!==n?null===n?void pe.removeAttr(e,t):i&&\"set\"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+\"\"),n):i&&\"get\"in i&&null!==(r=i.get(e,t))?r:(r=pe.find.attr(e,t),null==r?void 0:r))},attrHooks:{type:{set:function(e,t){if(!fe.radioValue&&\"radio\"===t&&pe.nodeName(e,\"input\")){var n=e.value;return e.setAttribute(\"type\",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(De);if(o&&1===e.nodeType)for(;n=o[i++];)r=pe.propFix[n]||n,pe.expr.match.bool.test(n)?Mt&&Ft||!_t.test(n)?e[r]=!1:e[pe.camelCase(\"default-\"+n)]=e[r]=!1:pe.attr(e,n,\"\"),e.removeAttribute(Ft?n:r)}}),Ht={set:function(e,t,n){return t===!1?pe.removeAttr(e,n):Mt&&Ft||!_t.test(n)?e.setAttribute(!Ft&&pe.propFix[n]||n,n):e[pe.camelCase(\"default-\"+n)]=e[n]=!0,n}},pe.each(pe.expr.match.bool.source.match(/\\w+/g),function(e,t){var n=qt[t]||pe.find.attr;Mt&&Ft||!_t.test(t)?qt[t]=function(e,t,r){var i,o;return r||(o=qt[t],qt[t]=i,i=null!=n(e,t,r)?t.toLowerCase():null,qt[t]=o),i}:qt[t]=function(e,t,n){if(!n)return e[pe.camelCase(\"default-\"+t)]?t.toLowerCase():null}}),Mt&&Ft||(pe.attrHooks.value={set:function(e,t,n){return pe.nodeName(e,\"input\")?void(e.defaultValue=t):Lt&&Lt.set(e,t,n)}}),Ft||(Lt={set:function(e,t,n){var r=e.getAttributeNode(n);if(r||e.setAttributeNode(r=e.ownerDocument.createAttribute(n)),r.value=t+=\"\",\"value\"===n||t===e.getAttribute(n))return t}},qt.id=qt.name=qt.coords=function(e,t,n){var r;if(!n)return(r=e.getAttributeNode(t))&&\"\"!==r.value?r.value:null},pe.valHooks.button={get:function(e,t){var n=e.getAttributeNode(t);if(n&&n.specified)return n.value},set:Lt.set},pe.attrHooks.contenteditable={set:function(e,t,n){Lt.set(e,\"\"!==t&&t,n)}},pe.each([\"width\",\"height\"],function(e,t){pe.attrHooks[t]={set:function(e,n){if(\"\"===n)return e.setAttribute(t,\"auto\"),n}}})),fe.style||(pe.attrHooks.style={get:function(e){return e.style.cssText||void 0},set:function(e,t){return e.style.cssText=t+\"\"}});var Ot=/^(?:input|select|textarea|button|object)$/i,Rt=/^(?:a|area)$/i;pe.fn.extend({prop:function(e,t){return Pe(this,pe.prop,e,t,arguments.length>1)},removeProp:function(e){return e=pe.propFix[e]||e,this.each(function(){try{this[e]=void 0,delete this[e]}catch(t){}})}}),pe.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&pe.isXMLDoc(e)||(t=pe.propFix[t]||t,i=pe.propHooks[t]),void 0!==n?i&&\"set\"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&\"get\"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=pe.find.attr(e,\"tabindex\");return t?parseInt(t,10):Ot.test(e.nodeName)||Rt.test(e.nodeName)&&e.href?0:-1}}},propFix:{\"for\":\"htmlFor\",\"class\":\"className\"}}),fe.hrefNormalized||pe.each([\"href\",\"src\"],function(e,t){pe.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}}),fe.optSelected||(pe.propHooks.selected={get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),pe.each([\"tabIndex\",\"readOnly\",\"maxLength\",\"cellSpacing\",\"cellPadding\",\"rowSpan\",\"colSpan\",\"useMap\",\"frameBorder\",\"contentEditable\"],function(){pe.propFix[this.toLowerCase()]=this}),fe.enctype||(pe.propFix.enctype=\"encoding\");var Pt=/[\\t\\r\\n\\f]/g;pe.fn.extend({addClass:function(e){var t,n,r,i,o,a,s,u=0;if(pe.isFunction(e))return this.each(function(t){pe(this).addClass(e.call(this,t,z(this)))});if(\"string\"==typeof e&&e)for(t=e.match(De)||[];n=this[u++];)if(i=z(n),r=1===n.nodeType&&(\" \"+i+\" \").replace(Pt,\" \")){for(a=0;o=t[a++];)r.indexOf(\" \"+o+\" \")<0&&(r+=o+\" \");s=pe.trim(r),i!==s&&pe.attr(n,\"class\",s)}return this},removeClass:function(e){var t,n,r,i,o,a,s,u=0;if(pe.isFunction(e))return this.each(function(t){pe(this).removeClass(e.call(this,t,z(this)))});if(!arguments.length)return this.attr(\"class\",\"\");if(\"string\"==typeof e&&e)for(t=e.match(De)||[];n=this[u++];)if(i=z(n),r=1===n.nodeType&&(\" \"+i+\" \").replace(Pt,\" \")){for(a=0;o=t[a++];)for(;r.indexOf(\" \"+o+\" \")>-1;)r=r.replace(\" \"+o+\" \",\" \");s=pe.trim(r),i!==s&&pe.attr(n,\"class\",s)}return this},toggleClass:function(e,t){var n=typeof e;return\"boolean\"==typeof t&&\"string\"===n?t?this.addClass(e):this.removeClass(e):pe.isFunction(e)?this.each(function(n){pe(this).toggleClass(e.call(this,n,z(this),t),t)}):this.each(function(){var t,r,i,o;if(\"string\"===n)for(r=0,i=pe(this),o=e.match(De)||[];t=o[r++];)i.hasClass(t)?i.removeClass(t):i.addClass(t);else void 0!==e&&\"boolean\"!==n||(t=z(this),t&&pe._data(this,\"__className__\",t),pe.attr(this,\"class\",t||e===!1?\"\":pe._data(this,\"__className__\")||\"\"))})},hasClass:function(e){var t,n,r=0;for(t=\" \"+e+\" \";n=this[r++];)if(1===n.nodeType&&(\" \"+z(n)+\" \").replace(Pt,\" \").indexOf(t)>-1)return!0;return!1}}),pe.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){pe.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),pe.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}});var Bt=e.location,Wt=pe.now(),It=/\\?/,$t=/(,)|(\\[|{)|(}|])|\"(?:[^\"\\\\\\r\\n]|\\\\[\"\\\\\\/bfnrt]|\\\\u[\\da-fA-F]{4})*\"\\s*:?|true|false|null|-?(?!0\\d)\\d+(?:\\.\\d+|)(?:[eE][+-]?\\d+|)/g;pe.parseJSON=function(t){if(e.JSON&&e.JSON.parse)return e.JSON.parse(t+\"\");var n,r=null,i=pe.trim(t+\"\");return i&&!pe.trim(i.replace($t,function(e,t,i,o){return n&&t&&(r=0),0===r?e:(n=i||t,r+=!o-!i,\"\")}))?Function(\"return \"+i)():pe.error(\"Invalid JSON: \"+t)},pe.parseXML=function(t){var n,r;if(!t||\"string\"!=typeof t)return null;try{e.DOMParser?(r=new e.DOMParser,n=r.parseFromString(t,\"text/xml\")):(n=new e.ActiveXObject(\"Microsoft.XMLDOM\"),n.async=\"false\",n.loadXML(t))}catch(i){n=void 0}return n&&n.documentElement&&!n.getElementsByTagName(\"parsererror\").length||pe.error(\"Invalid XML: \"+t),n};var zt=/#.*$/,Xt=/([?&])_=[^&]*/,Ut=/^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/gm,Vt=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Yt=/^(?:GET|HEAD)$/,Jt=/^\\/\\//,Gt=/^([\\w.+-]+:)(?:\\/\\/(?:[^\\/?#]*@|)([^\\/?#:]*)(?::(\\d+)|)|)/,Kt={},Qt={},Zt=\"*/\".concat(\"*\"),en=Bt.href,tn=Gt.exec(en.toLowerCase())||[];pe.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:en,type:\"GET\",isLocal:Vt.test(tn[1]),global:!0,processData:!0,async:!0,contentType:\"application/x-www-form-urlencoded; charset=UTF-8\",accepts:{\"*\":Zt,text:\"text/plain\",html:\"text/html\",xml:\"application/xml, text/xml\",json:\"application/json, text/javascript\"},contents:{xml:/\\bxml\\b/,html:/\\bhtml/,json:/\\bjson\\b/},responseFields:{xml:\"responseXML\",text:\"responseText\",json:\"responseJSON\"},converters:{\"* text\":String,\"text html\":!0,\"text json\":pe.parseJSON,\"text xml\":pe.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?V(V(e,pe.ajaxSettings),t):V(pe.ajaxSettings,e)},ajaxPrefilter:X(Kt),ajaxTransport:X(Qt),ajax:function(t,n){function r(t,n,r,i){var o,f,v,x,w,C=n;2!==b&&(b=2,u&&e.clearTimeout(u),c=void 0,s=i||\"\",T.readyState=t>0?4:0,o=t>=200&&t<300||304===t,r&&(x=Y(d,T,r)),x=J(d,x,T,o),o?(d.ifModified&&(w=T.getResponseHeader(\"Last-Modified\"),w&&(pe.lastModified[a]=w),w=T.getResponseHeader(\"etag\"),w&&(pe.etag[a]=w)),204===t||\"HEAD\"===d.type?C=\"nocontent\":304===t?C=\"notmodified\":(C=x.state,f=x.data,v=x.error,o=!v)):(v=C,!t&&C||(C=\"error\",t<0&&(t=0))),T.status=t,T.statusText=(n||C)+\"\",o?g.resolveWith(p,[f,C,T]):g.rejectWith(p,[T,C,v]),T.statusCode(y),y=void 0,l&&h.trigger(o?\"ajaxSuccess\":\"ajaxError\",[T,d,o?f:v]),m.fireWith(p,[T,C]),l&&(h.trigger(\"ajaxComplete\",[T,d]),--pe.active||pe.event.trigger(\"ajaxStop\")))}\"object\"==typeof t&&(n=t,t=void 0),n=n||{};var i,o,a,s,u,l,c,f,d=pe.ajaxSetup({},n),p=d.context||d,h=d.context&&(p.nodeType||p.jquery)?pe(p):pe.event,g=pe.Deferred(),m=pe.Callbacks(\"once memory\"),y=d.statusCode||{},v={},x={},b=0,w=\"canceled\",T={readyState:0,getResponseHeader:function(e){var t;if(2===b){if(!f)for(f={};t=Ut.exec(s);)f[t[1].toLowerCase()]=t[2];t=f[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===b?s:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return b||(e=x[n]=x[n]||e,v[e]=t),this},overrideMimeType:function(e){return b||(d.mimeType=e),this},statusCode:function(e){var t;if(e)if(b<2)for(t in e)y[t]=[y[t],e[t]];else T.always(e[T.status]);return this},abort:function(e){var t=e||w;return c&&c.abort(t),r(0,t),this}};if(g.promise(T).complete=m.add,T.success=T.done,T.error=T.fail,d.url=((t||d.url||en)+\"\").replace(zt,\"\").replace(Jt,tn[1]+\"//\"),d.type=n.method||n.type||d.method||d.type,d.dataTypes=pe.trim(d.dataType||\"*\").toLowerCase().match(De)||[\"\"],null==d.crossDomain&&(i=Gt.exec(d.url.toLowerCase()),d.crossDomain=!(!i||i[1]===tn[1]&&i[2]===tn[2]&&(i[3]||(\"http:\"===i[1]?\"80\":\"443\"))===(tn[3]||(\"http:\"===tn[1]?\"80\":\"443\")))),d.data&&d.processData&&\"string\"!=typeof d.data&&(d.data=pe.param(d.data,d.traditional)),U(Kt,d,n,T),2===b)return T;l=pe.event&&d.global,l&&0===pe.active++&&pe.event.trigger(\"ajaxStart\"),d.type=d.type.toUpperCase(),d.hasContent=!Yt.test(d.type),a=d.url,d.hasContent||(d.data&&(a=d.url+=(It.test(a)?\"&\":\"?\")+d.data,delete d.data),d.cache===!1&&(d.url=Xt.test(a)?a.replace(Xt,\"$1_=\"+Wt++):a+(It.test(a)?\"&\":\"?\")+\"_=\"+Wt++)),d.ifModified&&(pe.lastModified[a]&&T.setRequestHeader(\"If-Modified-Since\",pe.lastModified[a]),pe.etag[a]&&T.setRequestHeader(\"If-None-Match\",pe.etag[a])),(d.data&&d.hasContent&&d.contentType!==!1||n.contentType)&&T.setRequestHeader(\"Content-Type\",d.contentType),T.setRequestHeader(\"Accept\",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(\"*\"!==d.dataTypes[0]?\", \"+Zt+\"; q=0.01\":\"\"):d.accepts[\"*\"]);for(o in d.headers)T.setRequestHeader(o,d.headers[o]);if(d.beforeSend&&(d.beforeSend.call(p,T,d)===!1||2===b))return T.abort();w=\"abort\";for(o in{success:1,error:1,complete:1})T[o](d[o]);if(c=U(Qt,d,n,T)){if(T.readyState=1,l&&h.trigger(\"ajaxSend\",[T,d]),2===b)return T;d.async&&d.timeout>0&&(u=e.setTimeout(function(){T.abort(\"timeout\")},d.timeout));try{b=1,c.send(v,r)}catch(C){if(!(b<2))throw C;r(-1,C)}}else r(-1,\"No Transport\");return T},getJSON:function(e,t,n){return pe.get(e,t,n,\"json\")},getScript:function(e,t){return pe.get(e,void 0,t,\"script\")}}),pe.each([\"get\",\"post\"],function(e,t){pe[t]=function(e,n,r,i){return pe.isFunction(n)&&(i=i||r,r=n,n=void 0),pe.ajax(pe.extend({url:e,type:t,dataType:i,data:n,success:r},pe.isPlainObject(e)&&e))}}),pe._evalUrl=function(e){return pe.ajax({url:e,type:\"GET\",dataType:\"script\",cache:!0,async:!1,global:!1,\"throws\":!0})},pe.fn.extend({wrapAll:function(e){if(pe.isFunction(e))return this.each(function(t){pe(this).wrapAll(e.call(this,t))});if(this[0]){var t=pe(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){for(var e=this;e.firstChild&&1===e.firstChild.nodeType;)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return pe.isFunction(e)?this.each(function(t){pe(this).wrapInner(e.call(this,t))}):this.each(function(){var t=pe(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=pe.isFunction(e);return this.each(function(n){pe(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){pe.nodeName(this,\"body\")||pe(this).replaceWith(this.childNodes)}).end()}}),pe.expr.filters.hidden=function(e){return fe.reliableHiddenOffsets()?e.offsetWidth<=0&&e.offsetHeight<=0&&!e.getClientRects().length:K(e)},pe.expr.filters.visible=function(e){return!pe.expr.filters.hidden(e)};var nn=/%20/g,rn=/\\[\\]$/,on=/\\r?\\n/g,an=/^(?:submit|button|image|reset|file)$/i,sn=/^(?:input|select|textarea|keygen)/i;pe.param=function(e,t){var n,r=[],i=function(e,t){t=pe.isFunction(t)?t():null==t?\"\":t,r[r.length]=encodeURIComponent(e)+\"=\"+encodeURIComponent(t)};if(void 0===t&&(t=pe.ajaxSettings&&pe.ajaxSettings.traditional),pe.isArray(e)||e.jquery&&!pe.isPlainObject(e))pe.each(e,function(){i(this.name,this.value)});else for(n in e)Q(n,e[n],t,i);return r.join(\"&\").replace(nn,\"+\")},pe.fn.extend({serialize:function(){return pe.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=pe.prop(this,\"elements\");return e?pe.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!pe(this).is(\":disabled\")&&sn.test(this.nodeName)&&!an.test(e)&&(this.checked||!Be.test(e))}).map(function(e,t){var n=pe(this).val();return null==n?null:pe.isArray(n)?pe.map(n,function(e){return{name:t.name,value:e.replace(on,\"\\r\\n\")}}):{name:t.name,value:n.replace(on,\"\\r\\n\")}}).get()}}),pe.ajaxSettings.xhr=void 0!==e.ActiveXObject?function(){return this.isLocal?ee():re.documentMode>8?Z():/^(get|post|head|put|delete|options)$/i.test(this.type)&&Z()||ee()}:Z;var un=0,ln={},cn=pe.ajaxSettings.xhr();e.attachEvent&&e.attachEvent(\"onunload\",function(){for(var e in ln)ln[e](void 0,!0)}),fe.cors=!!cn&&\"withCredentials\"in cn,cn=fe.ajax=!!cn,cn&&pe.ajaxTransport(function(t){if(!t.crossDomain||fe.cors){var n;return{send:function(r,i){var o,a=t.xhr(),s=++un;if(a.open(t.type,t.url,t.async,t.username,t.password),t.xhrFields)for(o in t.xhrFields)a[o]=t.xhrFields[o];t.mimeType&&a.overrideMimeType&&a.overrideMimeType(t.mimeType),t.crossDomain||r[\"X-Requested-With\"]||(r[\"X-Requested-With\"]=\"XMLHttpRequest\");for(o in r)void 0!==r[o]&&a.setRequestHeader(o,r[o]+\"\");a.send(t.hasContent&&t.data||null),n=function(e,r){var o,u,l;if(n&&(r||4===a.readyState))if(delete ln[s],n=void 0,a.onreadystatechange=pe.noop,r)4!==a.readyState&&a.abort();else{l={},o=a.status,\"string\"==typeof a.responseText&&(l.text=a.responseText);try{u=a.statusText}catch(c){u=\"\"}o||!t.isLocal||t.crossDomain?1223===o&&(o=204):o=l.text?200:404}l&&i(o,u,l,a.getAllResponseHeaders())},t.async?4===a.readyState?e.setTimeout(n):a.onreadystatechange=ln[s]=n:n()},abort:function(){n&&n(void 0,!0)}}}}),pe.ajaxSetup({accepts:{script:\"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"},contents:{script:/\\b(?:java|ecma)script\\b/},converters:{\"text script\":function(e){return pe.globalEval(e),e}}}),pe.ajaxPrefilter(\"script\",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type=\"GET\",e.global=!1)}),pe.ajaxTransport(\"script\",function(e){if(e.crossDomain){var t,n=re.head||pe(\"head\")[0]||re.documentElement;return{send:function(r,i){t=re.createElement(\"script\"),t.async=!0,e.scriptCharset&&(t.charset=e.scriptCharset),t.src=e.url,t.onload=t.onreadystatechange=function(e,n){(n||!t.readyState||/loaded|complete/.test(t.readyState))&&(t.onload=t.onreadystatechange=null,t.parentNode&&t.parentNode.removeChild(t),t=null,n||i(200,\"success\"))},n.insertBefore(t,n.firstChild)},abort:function(){t&&t.onload(void 0,!0)}}}});var fn=[],dn=/(=)\\?(?=&|$)|\\?\\?/;pe.ajaxSetup({jsonp:\"callback\",jsonpCallback:function(){var e=fn.pop()||pe.expando+\"_\"+Wt++;return this[e]=!0,e}}),pe.ajaxPrefilter(\"json jsonp\",function(t,n,r){var i,o,a,s=t.jsonp!==!1&&(dn.test(t.url)?\"url\":\"string\"==typeof t.data&&0===(t.contentType||\"\").indexOf(\"application/x-www-form-urlencoded\")&&dn.test(t.data)&&\"data\");if(s||\"jsonp\"===t.dataTypes[0])return i=t.jsonpCallback=pe.isFunction(t.jsonpCallback)?t.jsonpCallback():t.jsonpCallback,s?t[s]=t[s].replace(dn,\"$1\"+i):t.jsonp!==!1&&(t.url+=(It.test(t.url)?\"&\":\"?\")+t.jsonp+\"=\"+i),t.converters[\"script json\"]=function(){return a||pe.error(i+\" was not called\"),a[0]},t.dataTypes[0]=\"json\",o=e[i],e[i]=function(){a=arguments},r.always(function(){void 0===o?pe(e).removeProp(i):e[i]=o,t[i]&&(t.jsonpCallback=n.jsonpCallback,fn.push(i)),a&&pe.isFunction(o)&&o(a[0]),a=o=void 0}),\"script\"}),pe.parseHTML=function(e,t,n){if(!e||\"string\"!=typeof e)return null;\"boolean\"==typeof t&&(n=t,t=!1),t=t||re;var r=Te.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=y([e],t,i),i&&i.length&&pe(i).remove(),pe.merge([],r.childNodes))};var pn=pe.fn.load;return pe.fn.load=function(e,t,n){if(\"string\"!=typeof e&&pn)return pn.apply(this,arguments);var r,i,o,a=this,s=e.indexOf(\" \");return s>-1&&(r=pe.trim(e.slice(s,e.length)),e=e.slice(0,s)),pe.isFunction(t)?(n=t,t=void 0):t&&\"object\"==typeof t&&(i=\"POST\"),a.length>0&&pe.ajax({url:e,type:i||\"GET\",dataType:\"html\",data:t}).done(function(e){o=arguments,a.html(r?pe(\"<div>\").append(pe.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},pe.each([\"ajaxStart\",\"ajaxStop\",\"ajaxComplete\",\"ajaxError\",\"ajaxSuccess\",\"ajaxSend\"],function(e,t){pe.fn[t]=function(e){return this.on(t,e)}}),pe.expr.filters.animated=function(e){return pe.grep(pe.timers,function(t){return e===t.elem}).length},pe.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l,c=pe.css(e,\"position\"),f=pe(e),d={};\"static\"===c&&(e.style.position=\"relative\"),s=f.offset(),o=pe.css(e,\"top\"),u=pe.css(e,\"left\"),l=(\"absolute\"===c||\"fixed\"===c)&&pe.inArray(\"auto\",[o,u])>-1,l?(r=f.position(),a=r.top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),pe.isFunction(t)&&(t=t.call(e,n,pe.extend({},s))),null!=t.top&&(d.top=t.top-s.top+a),null!=t.left&&(d.left=t.left-s.left+i),\"using\"in t?t.using.call(e,d):f.css(d)}},pe.fn.extend({offset:function(e){if(arguments.length)return void 0===e?this:this.each(function(t){pe.offset.setOffset(this,e,t)});var t,n,r={top:0,left:0},i=this[0],o=i&&i.ownerDocument;if(o)return t=o.documentElement,pe.contains(t,i)?(\"undefined\"!=typeof i.getBoundingClientRect&&(r=i.getBoundingClientRect()),n=te(o),{top:r.top+(n.pageYOffset||t.scrollTop)-(t.clientTop||0),left:r.left+(n.pageXOffset||t.scrollLeft)-(t.clientLeft||0)}):r},position:function(){if(this[0]){var e,t,n={top:0,left:0},r=this[0];return\"fixed\"===pe.css(r,\"position\")?t=r.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),pe.nodeName(e[0],\"html\")||(n=e.offset()),n.top+=pe.css(e[0],\"borderTopWidth\",!0),n.left+=pe.css(e[0],\"borderLeftWidth\",!0)),{top:t.top-n.top-pe.css(r,\"marginTop\",!0),left:t.left-n.left-pe.css(r,\"marginLeft\",!0)}}},offsetParent:function(){return this.map(function(){\nfor(var e=this.offsetParent;e&&!pe.nodeName(e,\"html\")&&\"static\"===pe.css(e,\"position\");)e=e.offsetParent;return e||pt})}}),pe.each({scrollLeft:\"pageXOffset\",scrollTop:\"pageYOffset\"},function(e,t){var n=/Y/.test(t);pe.fn[e]=function(r){return Pe(this,function(e,r,i){var o=te(e);return void 0===i?o?t in o?o[t]:o.document.documentElement[r]:e[r]:void(o?o.scrollTo(n?pe(o).scrollLeft():i,n?i:pe(o).scrollTop()):e[r]=i)},e,r,arguments.length,null)}}),pe.each([\"top\",\"left\"],function(e,t){pe.cssHooks[t]=L(fe.pixelPosition,function(e,n){if(n)return n=gt(e,t),ft.test(n)?pe(e).position()[t]+\"px\":n})}),pe.each({Height:\"height\",Width:\"width\"},function(e,t){pe.each({padding:\"inner\"+e,content:t,\"\":\"outer\"+e},function(n,r){pe.fn[r]=function(r,i){var o=arguments.length&&(n||\"boolean\"!=typeof r),a=n||(r===!0||i===!0?\"margin\":\"border\");return Pe(this,function(t,n,r){var i;return pe.isWindow(t)?t.document.documentElement[\"client\"+e]:9===t.nodeType?(i=t.documentElement,Math.max(t.body[\"scroll\"+e],i[\"scroll\"+e],t.body[\"offset\"+e],i[\"offset\"+e],i[\"client\"+e])):void 0===r?pe.css(t,n,a):pe.style(t,n,r,a)},t,o?r:void 0,o,null)}})}),pe.fn.extend({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)}}),pe.fn.size=function(){return this.length},pe.fn.andSelf=pe.fn.addBack,layui.define(function(e){layui.$=pe,e(\"jquery\",pe)}),pe});!function(e,t){\"use strict\";var i,n,a=e.layui&&layui.define,o={getPath:function(){var e=document.currentScript?document.currentScript.src:function(){for(var e,t=document.scripts,i=t.length-1,n=i;n>0;n--)if(\"interactive\"===t[n].readyState){e=t[n].src;break}return e||t[i].src}();return e.substring(0,e.lastIndexOf(\"/\")+1)}(),config:{},end:{},minIndex:0,minLeft:[],btn:[\"&#x786E;&#x5B9A;\",\"&#x53D6;&#x6D88;\"],type:[\"dialog\",\"page\",\"iframe\",\"loading\",\"tips\"],getStyle:function(t,i){var n=t.currentStyle?t.currentStyle:e.getComputedStyle(t,null);return n[n.getPropertyValue?\"getPropertyValue\":\"getAttribute\"](i)},link:function(t,i,n){if(r.path){var a=document.getElementsByTagName(\"head\")[0],s=document.createElement(\"link\");\"string\"==typeof i&&(n=i);var l=(n||t).replace(/\\.|\\//g,\"\"),f=\"layuicss-\"+l,c=0;s.rel=\"stylesheet\",s.href=r.path+t,s.id=f,document.getElementById(f)||a.appendChild(s),\"function\"==typeof i&&!function u(){return++c>80?e.console&&console.error(\"layer.css: Invalid\"):void(1989===parseInt(o.getStyle(document.getElementById(f),\"width\"))?i():setTimeout(u,100))}()}}},r={v:\"3.1.1\",ie:function(){var t=navigator.userAgent.toLowerCase();return!!(e.ActiveXObject||\"ActiveXObject\"in e)&&((t.match(/msie\\s(\\d+)/)||[])[1]||\"11\")}(),index:e.layer&&e.layer.v?1e5:0,path:o.getPath,config:function(e,t){return e=e||{},r.cache=o.config=i.extend({},o.config,e),r.path=o.config.path||r.path,\"string\"==typeof e.extend&&(e.extend=[e.extend]),o.config.path&&r.ready(),e.extend?(a?layui.addcss(\"modules/layer/\"+e.extend):o.link(\"theme/\"+e.extend),this):this},ready:function(e){var t=\"layer\",i=\"\",n=(a?\"modules/layer/\":\"theme/\")+\"default/layer.css?v=\"+r.v+i;return a?layui.addcss(n,e,t):o.link(n,e,t),this},alert:function(e,t,n){var a=\"function\"==typeof t;return a&&(n=t),r.open(i.extend({content:e,yes:n},a?{}:t))},confirm:function(e,t,n,a){var s=\"function\"==typeof t;return s&&(a=n,n=t),r.open(i.extend({content:e,btn:o.btn,yes:n,btn2:a},s?{}:t))},msg:function(e,n,a){var s=\"function\"==typeof n,f=o.config.skin,c=(f?f+\" \"+f+\"-msg\":\"\")||\"layui-layer-msg\",u=l.anim.length-1;return s&&(a=n),r.open(i.extend({content:e,time:3e3,shade:!1,skin:c,title:!1,closeBtn:!1,btn:!1,resize:!1,end:a},s&&!o.config.skin?{skin:c+\" layui-layer-hui\",anim:u}:function(){return n=n||{},(n.icon===-1||n.icon===t&&!o.config.skin)&&(n.skin=c+\" \"+(n.skin||\"layui-layer-hui\")),n}()))},load:function(e,t){return r.open(i.extend({type:3,icon:e||0,resize:!1,shade:.01},t))},tips:function(e,t,n){return r.open(i.extend({type:4,content:[e,t],closeBtn:!1,time:3e3,shade:!1,resize:!1,fixed:!1,maxWidth:210},n))}},s=function(e){var t=this;t.index=++r.index,t.config=i.extend({},t.config,o.config,e),document.body?t.creat():setTimeout(function(){t.creat()},30)};s.pt=s.prototype;var l=[\"layui-layer\",\".layui-layer-title\",\".layui-layer-main\",\".layui-layer-dialog\",\"layui-layer-iframe\",\"layui-layer-content\",\"layui-layer-btn\",\"layui-layer-close\"];l.anim=[\"layer-anim-00\",\"layer-anim-01\",\"layer-anim-02\",\"layer-anim-03\",\"layer-anim-04\",\"layer-anim-05\",\"layer-anim-06\"],s.pt.config={type:0,shade:.3,fixed:!0,move:l[1],title:\"&#x4FE1;&#x606F;\",offset:\"auto\",area:\"auto\",closeBtn:1,time:0,zIndex:19891014,maxWidth:360,anim:0,isOutAnim:!0,icon:-1,moveType:1,resize:!0,scrollbar:!0,tips:2},s.pt.vessel=function(e,t){var n=this,a=n.index,r=n.config,s=r.zIndex+a,f=\"object\"==typeof r.title,c=r.maxmin&&(1===r.type||2===r.type),u=r.title?'<div class=\"layui-layer-title\" style=\"'+(f?r.title[1]:\"\")+'\">'+(f?r.title[0]:r.title)+\"</div>\":\"\";return r.zIndex=s,t([r.shade?'<div class=\"layui-layer-shade\" id=\"layui-layer-shade'+a+'\" times=\"'+a+'\" style=\"'+(\"z-index:\"+(s-1)+\"; \")+'\"></div>':\"\",'<div class=\"'+l[0]+(\" layui-layer-\"+o.type[r.type])+(0!=r.type&&2!=r.type||r.shade?\"\":\" layui-layer-border\")+\" \"+(r.skin||\"\")+'\" id=\"'+l[0]+a+'\" type=\"'+o.type[r.type]+'\" times=\"'+a+'\" showtime=\"'+r.time+'\" conType=\"'+(e?\"object\":\"string\")+'\" style=\"z-index: '+s+\"; width:\"+r.area[0]+\";height:\"+r.area[1]+(r.fixed?\"\":\";position:absolute;\")+'\">'+(e&&2!=r.type?\"\":u)+'<div id=\"'+(r.id||\"\")+'\" class=\"layui-layer-content'+(0==r.type&&r.icon!==-1?\" layui-layer-padding\":\"\")+(3==r.type?\" layui-layer-loading\"+r.icon:\"\")+'\">'+(0==r.type&&r.icon!==-1?'<i class=\"layui-layer-ico layui-layer-ico'+r.icon+'\"></i>':\"\")+(1==r.type&&e?\"\":r.content||\"\")+'</div><span class=\"layui-layer-setwin\">'+function(){var e=c?'<a class=\"layui-layer-min\" href=\"javascript:;\"><cite></cite></a><a class=\"layui-layer-ico layui-layer-max\" href=\"javascript:;\"></a>':\"\";return r.closeBtn&&(e+='<a class=\"layui-layer-ico '+l[7]+\" \"+l[7]+(r.title?r.closeBtn:4==r.type?\"1\":\"2\")+'\" href=\"javascript:;\"></a>'),e}()+\"</span>\"+(r.btn?function(){var e=\"\";\"string\"==typeof r.btn&&(r.btn=[r.btn]);for(var t=0,i=r.btn.length;t<i;t++)e+='<a class=\"'+l[6]+t+'\">'+r.btn[t]+\"</a>\";return'<div class=\"'+l[6]+\" layui-layer-btn-\"+(r.btnAlign||\"\")+'\">'+e+\"</div>\"}():\"\")+(r.resize?'<span class=\"layui-layer-resize\"></span>':\"\")+\"</div>\"],u,i('<div class=\"layui-layer-move\"></div>')),n},s.pt.creat=function(){var e=this,t=e.config,a=e.index,s=t.content,f=\"object\"==typeof s,c=i(\"body\");if(!t.id||!i(\"#\"+t.id)[0]){switch(\"string\"==typeof t.area&&(t.area=\"auto\"===t.area?[\"\",\"\"]:[t.area,\"\"]),t.shift&&(t.anim=t.shift),6==r.ie&&(t.fixed=!1),t.type){case 0:t.btn=\"btn\"in t?t.btn:o.btn[0],r.closeAll(\"dialog\");break;case 2:var s=t.content=f?t.content:[t.content||\"http://layer.layui.com\",\"auto\"];t.content='<iframe scrolling=\"'+(t.content[1]||\"auto\")+'\" allowtransparency=\"true\" id=\"'+l[4]+a+'\" name=\"'+l[4]+a+'\" onload=\"this.className=\\'\\';\" class=\"layui-layer-load\" frameborder=\"0\" src=\"'+t.content[0]+'\"></iframe>';break;case 3:delete t.title,delete t.closeBtn,t.icon===-1&&0===t.icon,r.closeAll(\"loading\");break;case 4:f||(t.content=[t.content,\"body\"]),t.follow=t.content[1],t.content=t.content[0]+'<i class=\"layui-layer-TipsG\"></i>',delete t.title,t.tips=\"object\"==typeof t.tips?t.tips:[t.tips,!0],t.tipsMore||r.closeAll(\"tips\")}if(e.vessel(f,function(n,r,u){c.append(n[0]),f?function(){2==t.type||4==t.type?function(){i(\"body\").append(n[1])}():function(){s.parents(\".\"+l[0])[0]||(s.data(\"display\",s.css(\"display\")).show().addClass(\"layui-layer-wrap\").wrap(n[1]),i(\"#\"+l[0]+a).find(\".\"+l[5]).before(r))}()}():c.append(n[1]),i(\".layui-layer-move\")[0]||c.append(o.moveElem=u),e.layero=i(\"#\"+l[0]+a),t.scrollbar||l.html.css(\"overflow\",\"hidden\").attr(\"layer-full\",a)}).auto(a),i(\"#layui-layer-shade\"+e.index).css({\"background-color\":t.shade[1]||\"#000\",opacity:t.shade[0]||t.shade}),2==t.type&&6==r.ie&&e.layero.find(\"iframe\").attr(\"src\",s[0]),4==t.type?e.tips():e.offset(),t.fixed&&n.on(\"resize\",function(){e.offset(),(/^\\d+%$/.test(t.area[0])||/^\\d+%$/.test(t.area[1]))&&e.auto(a),4==t.type&&e.tips()}),t.time<=0||setTimeout(function(){r.close(e.index)},t.time),e.move().callback(),l.anim[t.anim]){var u=\"layer-anim \"+l.anim[t.anim];e.layero.addClass(u).one(\"webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend\",function(){i(this).removeClass(u)})}t.isOutAnim&&e.layero.data(\"isOutAnim\",!0)}},s.pt.auto=function(e){var t=this,a=t.config,o=i(\"#\"+l[0]+e);\"\"===a.area[0]&&a.maxWidth>0&&(r.ie&&r.ie<8&&a.btn&&o.width(o.innerWidth()),o.outerWidth()>a.maxWidth&&o.width(a.maxWidth));var s=[o.innerWidth(),o.innerHeight()],f=o.find(l[1]).outerHeight()||0,c=o.find(\".\"+l[6]).outerHeight()||0,u=function(e){e=o.find(e),e.height(s[1]-f-c-2*(0|parseFloat(e.css(\"padding-top\"))))};switch(a.type){case 2:u(\"iframe\");break;default:\"\"===a.area[1]?a.maxHeight>0&&o.outerHeight()>a.maxHeight?(s[1]=a.maxHeight,u(\".\"+l[5])):a.fixed&&s[1]>=n.height()&&(s[1]=n.height(),u(\".\"+l[5])):u(\".\"+l[5])}return t},s.pt.offset=function(){var e=this,t=e.config,i=e.layero,a=[i.outerWidth(),i.outerHeight()],o=\"object\"==typeof t.offset;e.offsetTop=(n.height()-a[1])/2,e.offsetLeft=(n.width()-a[0])/2,o?(e.offsetTop=t.offset[0],e.offsetLeft=t.offset[1]||e.offsetLeft):\"auto\"!==t.offset&&(\"t\"===t.offset?e.offsetTop=0:\"r\"===t.offset?e.offsetLeft=n.width()-a[0]:\"b\"===t.offset?e.offsetTop=n.height()-a[1]:\"l\"===t.offset?e.offsetLeft=0:\"lt\"===t.offset?(e.offsetTop=0,e.offsetLeft=0):\"lb\"===t.offset?(e.offsetTop=n.height()-a[1],e.offsetLeft=0):\"rt\"===t.offset?(e.offsetTop=0,e.offsetLeft=n.width()-a[0]):\"rb\"===t.offset?(e.offsetTop=n.height()-a[1],e.offsetLeft=n.width()-a[0]):e.offsetTop=t.offset),t.fixed||(e.offsetTop=/%$/.test(e.offsetTop)?n.height()*parseFloat(e.offsetTop)/100:parseFloat(e.offsetTop),e.offsetLeft=/%$/.test(e.offsetLeft)?n.width()*parseFloat(e.offsetLeft)/100:parseFloat(e.offsetLeft),e.offsetTop+=n.scrollTop(),e.offsetLeft+=n.scrollLeft()),i.attr(\"minLeft\")&&(e.offsetTop=n.height()-(i.find(l[1]).outerHeight()||0),e.offsetLeft=i.css(\"left\")),i.css({top:e.offsetTop,left:e.offsetLeft})},s.pt.tips=function(){var e=this,t=e.config,a=e.layero,o=[a.outerWidth(),a.outerHeight()],r=i(t.follow);r[0]||(r=i(\"body\"));var s={width:r.outerWidth(),height:r.outerHeight(),top:r.offset().top,left:r.offset().left},f=a.find(\".layui-layer-TipsG\"),c=t.tips[0];t.tips[1]||f.remove(),s.autoLeft=function(){s.left+o[0]-n.width()>0?(s.tipLeft=s.left+s.width-o[0],f.css({right:12,left:\"auto\"})):s.tipLeft=s.left},s.where=[function(){s.autoLeft(),s.tipTop=s.top-o[1]-10,f.removeClass(\"layui-layer-TipsB\").addClass(\"layui-layer-TipsT\").css(\"border-right-color\",t.tips[1])},function(){s.tipLeft=s.left+s.width+10,s.tipTop=s.top,f.removeClass(\"layui-layer-TipsL\").addClass(\"layui-layer-TipsR\").css(\"border-bottom-color\",t.tips[1])},function(){s.autoLeft(),s.tipTop=s.top+s.height+10,f.removeClass(\"layui-layer-TipsT\").addClass(\"layui-layer-TipsB\").css(\"border-right-color\",t.tips[1])},function(){s.tipLeft=s.left-o[0]-10,s.tipTop=s.top,f.removeClass(\"layui-layer-TipsR\").addClass(\"layui-layer-TipsL\").css(\"border-bottom-color\",t.tips[1])}],s.where[c-1](),1===c?s.top-(n.scrollTop()+o[1]+16)<0&&s.where[2]():2===c?n.width()-(s.left+s.width+o[0]+16)>0||s.where[3]():3===c?s.top-n.scrollTop()+s.height+o[1]+16-n.height()>0&&s.where[0]():4===c&&o[0]+16-s.left>0&&s.where[1](),a.find(\".\"+l[5]).css({\"background-color\":t.tips[1],\"padding-right\":t.closeBtn?\"30px\":\"\"}),a.css({left:s.tipLeft-(t.fixed?n.scrollLeft():0),top:s.tipTop-(t.fixed?n.scrollTop():0)})},s.pt.move=function(){var e=this,t=e.config,a=i(document),s=e.layero,l=s.find(t.move),f=s.find(\".layui-layer-resize\"),c={};return t.move&&l.css(\"cursor\",\"move\"),l.on(\"mousedown\",function(e){e.preventDefault(),t.move&&(c.moveStart=!0,c.offset=[e.clientX-parseFloat(s.css(\"left\")),e.clientY-parseFloat(s.css(\"top\"))],o.moveElem.css(\"cursor\",\"move\").show())}),f.on(\"mousedown\",function(e){e.preventDefault(),c.resizeStart=!0,c.offset=[e.clientX,e.clientY],c.area=[s.outerWidth(),s.outerHeight()],o.moveElem.css(\"cursor\",\"se-resize\").show()}),a.on(\"mousemove\",function(i){if(c.moveStart){var a=i.clientX-c.offset[0],o=i.clientY-c.offset[1],l=\"fixed\"===s.css(\"position\");if(i.preventDefault(),c.stX=l?0:n.scrollLeft(),c.stY=l?0:n.scrollTop(),!t.moveOut){var f=n.width()-s.outerWidth()+c.stX,u=n.height()-s.outerHeight()+c.stY;a<c.stX&&(a=c.stX),a>f&&(a=f),o<c.stY&&(o=c.stY),o>u&&(o=u)}s.css({left:a,top:o})}if(t.resize&&c.resizeStart){var a=i.clientX-c.offset[0],o=i.clientY-c.offset[1];i.preventDefault(),r.style(e.index,{width:c.area[0]+a,height:c.area[1]+o}),c.isResize=!0,t.resizing&&t.resizing(s)}}).on(\"mouseup\",function(e){c.moveStart&&(delete c.moveStart,o.moveElem.hide(),t.moveEnd&&t.moveEnd(s)),c.resizeStart&&(delete c.resizeStart,o.moveElem.hide())}),e},s.pt.callback=function(){function e(){var e=a.cancel&&a.cancel(t.index,n);e===!1||r.close(t.index)}var t=this,n=t.layero,a=t.config;t.openLayer(),a.success&&(2==a.type?n.find(\"iframe\").on(\"load\",function(){a.success(n,t.index)}):a.success(n,t.index)),6==r.ie&&t.IE6(n),n.find(\".\"+l[6]).children(\"a\").on(\"click\",function(){var e=i(this).index();if(0===e)a.yes?a.yes(t.index,n):a.btn1?a.btn1(t.index,n):r.close(t.index);else{var o=a[\"btn\"+(e+1)]&&a[\"btn\"+(e+1)](t.index,n);o===!1||r.close(t.index)}}),n.find(\".\"+l[7]).on(\"click\",e),a.shadeClose&&i(\"#layui-layer-shade\"+t.index).on(\"click\",function(){r.close(t.index)}),n.find(\".layui-layer-min\").on(\"click\",function(){var e=a.min&&a.min(n);e===!1||r.min(t.index,a)}),n.find(\".layui-layer-max\").on(\"click\",function(){i(this).hasClass(\"layui-layer-maxmin\")?(r.restore(t.index),a.restore&&a.restore(n)):(r.full(t.index,a),setTimeout(function(){a.full&&a.full(n)},100))}),a.end&&(o.end[t.index]=a.end)},o.reselect=function(){i.each(i(\"select\"),function(e,t){var n=i(this);n.parents(\".\"+l[0])[0]||1==n.attr(\"layer\")&&i(\".\"+l[0]).length<1&&n.removeAttr(\"layer\").show(),n=null})},s.pt.IE6=function(e){i(\"select\").each(function(e,t){var n=i(this);n.parents(\".\"+l[0])[0]||\"none\"===n.css(\"display\")||n.attr({layer:\"1\"}).hide(),n=null})},s.pt.openLayer=function(){var e=this;r.zIndex=e.config.zIndex,r.setTop=function(e){var t=function(){r.zIndex++,e.css(\"z-index\",r.zIndex+1)};return r.zIndex=parseInt(e[0].style.zIndex),e.on(\"mousedown\",t),r.zIndex}},o.record=function(e){var t=[e.width(),e.height(),e.position().top,e.position().left+parseFloat(e.css(\"margin-left\"))];e.find(\".layui-layer-max\").addClass(\"layui-layer-maxmin\"),e.attr({area:t})},o.rescollbar=function(e){l.html.attr(\"layer-full\")==e&&(l.html[0].style.removeProperty?l.html[0].style.removeProperty(\"overflow\"):l.html[0].style.removeAttribute(\"overflow\"),l.html.removeAttr(\"layer-full\"))},e.layer=r,r.getChildFrame=function(e,t){return t=t||i(\".\"+l[4]).attr(\"times\"),i(\"#\"+l[0]+t).find(\"iframe\").contents().find(e)},r.getFrameIndex=function(e){return i(\"#\"+e).parents(\".\"+l[4]).attr(\"times\")},r.iframeAuto=function(e){if(e){var t=r.getChildFrame(\"html\",e).outerHeight(),n=i(\"#\"+l[0]+e),a=n.find(l[1]).outerHeight()||0,o=n.find(\".\"+l[6]).outerHeight()||0;n.css({height:t+a+o}),n.find(\"iframe\").css({height:t})}},r.iframeSrc=function(e,t){i(\"#\"+l[0]+e).find(\"iframe\").attr(\"src\",t)},r.style=function(e,t,n){var a=i(\"#\"+l[0]+e),r=a.find(\".layui-layer-content\"),s=a.attr(\"type\"),f=a.find(l[1]).outerHeight()||0,c=a.find(\".\"+l[6]).outerHeight()||0;a.attr(\"minLeft\");s!==o.type[3]&&s!==o.type[4]&&(n||(parseFloat(t.width)<=260&&(t.width=260),parseFloat(t.height)-f-c<=64&&(t.height=64+f+c)),a.css(t),c=a.find(\".\"+l[6]).outerHeight(),s===o.type[2]?a.find(\"iframe\").css({height:parseFloat(t.height)-f-c}):r.css({height:parseFloat(t.height)-f-c-parseFloat(r.css(\"padding-top\"))-parseFloat(r.css(\"padding-bottom\"))}))},r.min=function(e,t){var a=i(\"#\"+l[0]+e),s=a.find(l[1]).outerHeight()||0,f=a.attr(\"minLeft\")||181*o.minIndex+\"px\",c=a.css(\"position\");o.record(a),o.minLeft[0]&&(f=o.minLeft[0],o.minLeft.shift()),a.attr(\"position\",c),r.style(e,{width:180,height:s,left:f,top:n.height()-s,position:\"fixed\",overflow:\"hidden\"},!0),a.find(\".layui-layer-min\").hide(),\"page\"===a.attr(\"type\")&&a.find(l[4]).hide(),o.rescollbar(e),a.attr(\"minLeft\")||o.minIndex++,a.attr(\"minLeft\",f)},r.restore=function(e){var t=i(\"#\"+l[0]+e),n=t.attr(\"area\").split(\",\");t.attr(\"type\");r.style(e,{width:parseFloat(n[0]),height:parseFloat(n[1]),top:parseFloat(n[2]),left:parseFloat(n[3]),position:t.attr(\"position\"),overflow:\"visible\"},!0),t.find(\".layui-layer-max\").removeClass(\"layui-layer-maxmin\"),t.find(\".layui-layer-min\").show(),\"page\"===t.attr(\"type\")&&t.find(l[4]).show(),o.rescollbar(e)},r.full=function(e){var t,a=i(\"#\"+l[0]+e);o.record(a),l.html.attr(\"layer-full\")||l.html.css(\"overflow\",\"hidden\").attr(\"layer-full\",e),clearTimeout(t),t=setTimeout(function(){var t=\"fixed\"===a.css(\"position\");r.style(e,{top:t?0:n.scrollTop(),left:t?0:n.scrollLeft(),width:n.width(),height:n.height()},!0),a.find(\".layui-layer-min\").hide()},100)},r.title=function(e,t){var n=i(\"#\"+l[0]+(t||r.index)).find(l[1]);n.html(e)},r.close=function(e){var t=i(\"#\"+l[0]+e),n=t.attr(\"type\"),a=\"layer-anim-close\";if(t[0]){var s=\"layui-layer-wrap\",f=function(){if(n===o.type[1]&&\"object\"===t.attr(\"conType\")){t.children(\":not(.\"+l[5]+\")\").remove();for(var a=t.find(\".\"+s),r=0;r<2;r++)a.unwrap();a.css(\"display\",a.data(\"display\")).removeClass(s)}else{if(n===o.type[2])try{var f=i(\"#\"+l[4]+e)[0];f.contentWindow.document.write(\"\"),f.contentWindow.close(),t.find(\".\"+l[5])[0].removeChild(f)}catch(c){}t[0].innerHTML=\"\",t.remove()}\"function\"==typeof o.end[e]&&o.end[e](),delete o.end[e]};t.data(\"isOutAnim\")&&t.addClass(\"layer-anim \"+a),i(\"#layui-layer-moves, #layui-layer-shade\"+e).remove(),6==r.ie&&o.reselect(),o.rescollbar(e),t.attr(\"minLeft\")&&(o.minIndex--,o.minLeft.push(t.attr(\"minLeft\"))),r.ie&&r.ie<10||!t.data(\"isOutAnim\")?f():setTimeout(function(){f()},200)}},r.closeAll=function(e){i.each(i(\".\"+l[0]),function(){var t=i(this),n=e?t.attr(\"type\")===e:1;n&&r.close(t.attr(\"times\")),n=null})};var f=r.cache||{},c=function(e){return f.skin?\" \"+f.skin+\" \"+f.skin+\"-\"+e:\"\"};r.prompt=function(e,t){var a=\"\";if(e=e||{},\"function\"==typeof e&&(t=e),e.area){var o=e.area;a='style=\"width: '+o[0]+\"; height: \"+o[1]+';\"',delete e.area}var s,l=2==e.formType?'<textarea class=\"layui-layer-input\"'+a+\"></textarea>\":function(){return'<input type=\"'+(1==e.formType?\"password\":\"text\")+'\" class=\"layui-layer-input\">'}(),f=e.success;return delete e.success,r.open(i.extend({type:1,btn:[\"&#x786E;&#x5B9A;\",\"&#x53D6;&#x6D88;\"],content:l,skin:\"layui-layer-prompt\"+c(\"prompt\"),maxWidth:n.width(),success:function(t){s=t.find(\".layui-layer-input\"),s.val(e.value||\"\").focus(),\"function\"==typeof f&&f(t)},resize:!1,yes:function(i){var n=s.val();\"\"===n?s.focus():n.length>(e.maxlength||500)?r.tips(\"&#x6700;&#x591A;&#x8F93;&#x5165;\"+(e.maxlength||500)+\"&#x4E2A;&#x5B57;&#x6570;\",s,{tips:1}):t&&t(n,i,s)}},e))},r.tab=function(e){e=e||{};var t=e.tab||{},n=\"layui-this\",a=e.success;return delete e.success,r.open(i.extend({type:1,skin:\"layui-layer-tab\"+c(\"tab\"),resize:!1,title:function(){var e=t.length,i=1,a=\"\";if(e>0)for(a='<span class=\"'+n+'\">'+t[0].title+\"</span>\";i<e;i++)a+=\"<span>\"+t[i].title+\"</span>\";return a}(),content:'<ul class=\"layui-layer-tabmain\">'+function(){var e=t.length,i=1,a=\"\";if(e>0)for(a='<li class=\"layui-layer-tabli '+n+'\">'+(t[0].content||\"no content\")+\"</li>\";i<e;i++)a+='<li class=\"layui-layer-tabli\">'+(t[i].content||\"no  content\")+\"</li>\";return a}()+\"</ul>\",success:function(t){var o=t.find(\".layui-layer-title\").children(),r=t.find(\".layui-layer-tabmain\").children();o.on(\"mousedown\",function(t){t.stopPropagation?t.stopPropagation():t.cancelBubble=!0;var a=i(this),o=a.index();a.addClass(n).siblings().removeClass(n),r.eq(o).show().siblings().hide(),\"function\"==typeof e.change&&e.change(o)}),\"function\"==typeof a&&a(t)}},e))},r.photos=function(t,n,a){function o(e,t,i){var n=new Image;return n.src=e,n.complete?t(n):(n.onload=function(){n.onload=null,t(n)},void(n.onerror=function(e){n.onerror=null,i(e)}))}var s={};if(t=t||{},t.photos){var l=t.photos.constructor===Object,f=l?t.photos:{},u=f.data||[],d=f.start||0;s.imgIndex=(0|d)+1,t.img=t.img||\"img\";var y=t.success;if(delete t.success,l){if(0===u.length)return r.msg(\"&#x6CA1;&#x6709;&#x56FE;&#x7247;\")}else{var p=i(t.photos),h=function(){u=[],p.find(t.img).each(function(e){var t=i(this);t.attr(\"layer-index\",e),u.push({alt:t.attr(\"alt\"),pid:t.attr(\"layer-pid\"),src:t.attr(\"layer-src\")||t.attr(\"src\"),thumb:t.attr(\"src\")})})};if(h(),0===u.length)return;if(n||p.on(\"click\",t.img,function(){var e=i(this),n=e.attr(\"layer-index\");r.photos(i.extend(t,{photos:{start:n,data:u,tab:t.tab},full:t.full}),!0),h()}),!n)return}s.imgprev=function(e){s.imgIndex--,s.imgIndex<1&&(s.imgIndex=u.length),s.tabimg(e)},s.imgnext=function(e,t){s.imgIndex++,s.imgIndex>u.length&&(s.imgIndex=1,t)||s.tabimg(e)},s.keyup=function(e){if(!s.end){var t=e.keyCode;e.preventDefault(),37===t?s.imgprev(!0):39===t?s.imgnext(!0):27===t&&r.close(s.index)}},s.tabimg=function(e){if(!(u.length<=1))return f.start=s.imgIndex-1,r.close(s.index),r.photos(t,!0,e)},s.event=function(){s.bigimg.hover(function(){s.imgsee.show()},function(){s.imgsee.hide()}),s.bigimg.find(\".layui-layer-imgprev\").on(\"click\",function(e){e.preventDefault(),s.imgprev()}),s.bigimg.find(\".layui-layer-imgnext\").on(\"click\",function(e){e.preventDefault(),s.imgnext()}),i(document).on(\"keyup\",s.keyup)},s.loadi=r.load(1,{shade:!(\"shade\"in t)&&.9,scrollbar:!1}),o(u[d].src,function(n){r.close(s.loadi),s.index=r.open(i.extend({type:1,id:\"layui-layer-photos\",area:function(){var a=[n.width,n.height],o=[i(e).width()-100,i(e).height()-100];if(!t.full&&(a[0]>o[0]||a[1]>o[1])){var r=[a[0]/o[0],a[1]/o[1]];r[0]>r[1]?(a[0]=a[0]/r[0],a[1]=a[1]/r[0]):r[0]<r[1]&&(a[0]=a[0]/r[1],a[1]=a[1]/r[1])}return[a[0]+\"px\",a[1]+\"px\"]}(),title:!1,shade:.9,shadeClose:!0,closeBtn:!1,move:\".layui-layer-phimg img\",moveType:1,scrollbar:!1,moveOut:!0,isOutAnim:!1,skin:\"layui-layer-photos\"+c(\"photos\"),content:'<div class=\"layui-layer-phimg\"><img src=\"'+u[d].src+'\" alt=\"'+(u[d].alt||\"\")+'\" layer-pid=\"'+u[d].pid+'\"><div class=\"layui-layer-imgsee\">'+(u.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:'+(a?\"block\":\"\")+'\"><span class=\"layui-layer-imgtit\"><a href=\"javascript:;\">'+(u[d].alt||\"\")+\"</a><em>\"+s.imgIndex+\"/\"+u.length+\"</em></span></div></div></div>\",success:function(e,i){s.bigimg=e.find(\".layui-layer-phimg\"),s.imgsee=e.find(\".layui-layer-imguide,.layui-layer-imgbar\"),s.event(e),t.tab&&t.tab(u[d],e),\"function\"==typeof y&&y(e)},end:function(){s.end=!0,i(document).off(\"keyup\",s.keyup)}},t))},function(){r.close(s.loadi),r.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(){u.length>1&&s.imgnext(!0,!0)}})})}},o.run=function(t){i=t,n=i(e),l.html=i(\"html\"),r.open=function(e){var t=new s(e);return t.index}},e.layui&&layui.define?(r.ready(),layui.define(\"jquery\",function(t){r.path=layui.cache.dir,o.run(layui.$),e.layer=r,t(\"layer\",r)})):\"function\"==typeof define&&define.amd?define([\"jquery\"],function(){return o.run(e.jQuery),r}):function(){o.run(e.jQuery),r.ready()}()}(window);layui.define(\"jquery\",function(i){\"use strict\";var t=layui.$,a=(layui.hint(),layui.device()),e=\"element\",l=\"layui-this\",n=\"layui-show\",s=function(){this.config={}};s.prototype.set=function(i){var a=this;return t.extend(!0,a.config,i),a},s.prototype.on=function(i,t){return layui.onevent.call(this,e,i,t)},s.prototype.tabAdd=function(i,a){var e=\".layui-tab-title\",l=t(\".layui-tab[lay-filter=\"+i+\"]\"),n=l.children(e),s=n.children(\".layui-tab-bar\"),o=l.children(\".layui-tab-content\"),c='<li lay-id=\"'+(a.id||\"\")+'\">'+(a.title||\"unnaming\")+\"</li>\";return s[0]?s.before(c):n.append(c),o.append('<div class=\"layui-tab-item\">'+(a.content||\"\")+\"</div>\"),y.hideTabMore(!0),y.tabAuto(),this},s.prototype.tabDelete=function(i,a){var e=\".layui-tab-title\",l=t(\".layui-tab[lay-filter=\"+i+\"]\"),n=l.children(e),s=n.find('>li[lay-id=\"'+a+'\"]');return y.tabDelete(null,s),this},s.prototype.tabChange=function(i,a){var e=\".layui-tab-title\",l=t(\".layui-tab[lay-filter=\"+i+\"]\"),n=l.children(e),s=n.find('>li[lay-id=\"'+a+'\"]');return y.tabClick.call(s[0],null,null,s),this},s.prototype.tab=function(i){i=i||{},v.on(\"click\",i.headerElem,function(a){var e=t(this).index();y.tabClick.call(this,a,e,null,i)})},s.prototype.progress=function(i,a){var e=\"layui-progress\",l=t(\".\"+e+\"[lay-filter=\"+i+\"]\"),n=l.find(\".\"+e+\"-bar\"),s=n.find(\".\"+e+\"-text\");return n.css(\"width\",a),s.text(a),this};var o=\".layui-nav\",c=\"layui-nav-item\",r=\"layui-nav-bar\",u=\"layui-nav-tree\",d=\"layui-nav-child\",h=\"layui-nav-more\",f=\"layui-anim layui-anim-upbit\",y={tabClick:function(i,a,s,o){o=o||{};var c=s||t(this),a=a||c.parent().children(\"li\").index(c),r=o.headerElem?c.parent():c.parents(\".layui-tab\").eq(0),u=o.bodyElem?t(o.bodyElem):r.children(\".layui-tab-content\").children(\".layui-tab-item\"),d=c.find(\"a\"),h=r.attr(\"lay-filter\");\"javascript:;\"!==d.attr(\"href\")&&\"_blank\"===d.attr(\"target\")||(c.addClass(l).siblings().removeClass(l),u.eq(a).addClass(n).siblings().removeClass(n)),layui.event.call(this,e,\"tab(\"+h+\")\",{elem:r,index:a})},tabDelete:function(i,a){var n=a||t(this).parent(),s=n.index(),o=n.parents(\".layui-tab\").eq(0),c=o.children(\".layui-tab-content\").children(\".layui-tab-item\"),r=o.attr(\"lay-filter\");n.hasClass(l)&&(n.next()[0]?y.tabClick.call(n.next()[0],null,s+1):n.prev()[0]&&y.tabClick.call(n.prev()[0],null,s-1)),n.remove(),c.eq(s).remove(),setTimeout(function(){y.tabAuto()},50),layui.event.call(this,e,\"tabDelete(\"+r+\")\",{elem:o,index:s})},tabAuto:function(){var i=\"layui-tab-more\",e=\"layui-tab-bar\",l=\"layui-tab-close\",n=this;t(\".layui-tab\").each(function(){var s=t(this),o=s.children(\".layui-tab-title\"),c=(s.children(\".layui-tab-content\").children(\".layui-tab-item\"),'lay-stope=\"tabmore\"'),r=t('<span class=\"layui-unselect layui-tab-bar\" '+c+\"><i \"+c+' class=\"layui-icon\">&#xe61a;</i></span>');if(n===window&&8!=a.ie&&y.hideTabMore(!0),s.attr(\"lay-allowClose\")&&o.find(\"li\").each(function(){var i=t(this);if(!i.find(\".\"+l)[0]){var a=t('<i class=\"layui-icon layui-unselect '+l+'\">&#x1006;</i>');a.on(\"click\",y.tabDelete),i.append(a)}}),o.prop(\"scrollWidth\")>o.outerWidth()+1){if(o.find(\".\"+e)[0])return;o.append(r),s.attr(\"overflow\",\"\"),r.on(\"click\",function(t){o[this.title?\"removeClass\":\"addClass\"](i),this.title=this.title?\"\":\"收缩\"})}else o.find(\".\"+e).remove(),s.removeAttr(\"overflow\")})},hideTabMore:function(i){var a=t(\".layui-tab-title\");i!==!0&&\"tabmore\"===t(i.target).attr(\"lay-stope\")||(a.removeClass(\"layui-tab-more\"),a.find(\".layui-tab-bar\").attr(\"title\",\"\"))},clickThis:function(){var i=t(this),a=i.parents(o),n=a.attr(\"lay-filter\"),s=i.find(\"a\"),c=\"string\"==typeof i.attr(\"lay-unselect\");i.find(\".\"+d)[0]||(\"javascript:;\"!==s.attr(\"href\")&&\"_blank\"===s.attr(\"target\")||c||(a.find(\".\"+l).removeClass(l),i.addClass(l)),layui.event.call(this,e,\"nav(\"+n+\")\",i))},clickChild:function(){var i=t(this),a=i.parents(o),n=a.attr(\"lay-filter\");a.find(\".\"+l).removeClass(l),i.addClass(l),layui.event.call(this,e,\"nav(\"+n+\")\",i)},showChild:function(){var i=t(this),a=i.parents(o),e=i.parent(),l=i.siblings(\".\"+d);a.hasClass(u)&&(l.removeClass(f),e[\"none\"===l.css(\"display\")?\"addClass\":\"removeClass\"](c+\"ed\"))},collapse:function(){var i=t(this),a=i.find(\".layui-colla-icon\"),l=i.siblings(\".layui-colla-content\"),s=i.parents(\".layui-collapse\").eq(0),o=s.attr(\"lay-filter\"),c=\"none\"===l.css(\"display\");if(\"string\"==typeof s.attr(\"lay-accordion\")){var r=s.children(\".layui-colla-item\").children(\".\"+n);r.siblings(\".layui-colla-title\").children(\".layui-colla-icon\").html(\"&#xe602;\"),r.removeClass(n)}l[c?\"addClass\":\"removeClass\"](n),a.html(c?\"&#xe61a;\":\"&#xe602;\"),layui.event.call(this,e,\"collapse(\"+o+\")\",{title:i,content:l,show:c})}};s.prototype.init=function(i,e){var l=function(){return e?'[lay-filter=\"'+e+'\"]':\"\"}(),s={tab:function(){y.tabAuto.call({})},nav:function(){var i=200,e={},s={},p={},v=function(l,o,c){var r=t(this),y=r.find(\".\"+d);o.hasClass(u)?l.css({top:r.position().top,height:r.children(\"a\").height(),opacity:1}):(y.addClass(f),l.css({left:r.position().left+parseFloat(r.css(\"marginLeft\")),top:r.position().top+r.height()-l.height()}),e[c]=setTimeout(function(){l.css({width:r.width(),opacity:1})},a.ie&&a.ie<10?0:i),clearTimeout(p[c]),\"block\"===y.css(\"display\")&&clearTimeout(s[c]),s[c]=setTimeout(function(){y.addClass(n),r.find(\".\"+h).addClass(h+\"d\")},300))};t(o+l).each(function(a){var l=t(this),o=t('<span class=\"'+r+'\"></span>'),f=l.find(\".\"+c);l.find(\".\"+r)[0]||(l.append(o),f.on(\"mouseenter\",function(){v.call(this,o,l,a)}).on(\"mouseleave\",function(){l.hasClass(u)||(clearTimeout(s[a]),s[a]=setTimeout(function(){l.find(\".\"+d).removeClass(n),l.find(\".\"+h).removeClass(h+\"d\")},300))}),l.on(\"mouseleave\",function(){clearTimeout(e[a]),p[a]=setTimeout(function(){l.hasClass(u)?o.css({height:0,top:o.position().top+o.height()/2,opacity:0}):o.css({width:0,left:o.position().left+o.width()/2,opacity:0})},i)})),f.each(function(){var i=t(this),a=i.find(\".\"+d);if(a[0]&&!i.find(\".\"+h)[0]){var e=i.children(\"a\");e.append('<span class=\"'+h+'\"></span>')}i.off(\"click\",y.clickThis).on(\"click\",y.clickThis),i.children(\"a\").off(\"click\",y.showChild).on(\"click\",y.showChild),a.children(\"dd\").off(\"click\",y.clickChild).on(\"click\",y.clickChild)})})},breadcrumb:function(){var i=\".layui-breadcrumb\";t(i+l).each(function(){var i=t(this),a=\"lay-separator\",e=i.attr(a)||\"/\",l=i.find(\"a\");l.next(\"span[\"+a+\"]\")[0]||(l.each(function(i){i!==l.length-1&&t(this).after(\"<span \"+a+\">\"+e+\"</span>\")}),i.css(\"visibility\",\"visible\"))})},progress:function(){var i=\"layui-progress\";t(\".\"+i+l).each(function(){var a=t(this),e=a.find(\".layui-progress-bar\"),l=e.attr(\"lay-percent\");e.css(\"width\",function(){return/^.+\\/.+$/.test(l)?100*new Function(\"return \"+l)()+\"%\":l}()),a.attr(\"lay-showPercent\")&&setTimeout(function(){e.html('<span class=\"'+i+'-text\">'+l+\"</span>\")},350)})},collapse:function(){var i=\"layui-collapse\";t(\".\"+i+l).each(function(){var i=t(this).find(\".layui-colla-item\");i.each(function(){var i=t(this),a=i.find(\".layui-colla-title\"),e=i.find(\".layui-colla-content\"),l=\"none\"===e.css(\"display\");a.find(\".layui-colla-icon\").remove(),a.append('<i class=\"layui-icon layui-colla-icon\">'+(l?\"&#xe602;\":\"&#xe61a;\")+\"</i>\"),a.off(\"click\",y.collapse).on(\"click\",y.collapse)})})}};return s[i]?s[i]():layui.each(s,function(i,t){t()})},s.prototype.render=s.prototype.init;var p=new s,v=t(document);p.render();var b=\".layui-tab-title li\";v.on(\"click\",b,y.tabClick),v.on(\"click\",y.hideTabMore),t(window).on(\"resize\",y.tabAuto),i(e,p)});layui.define(\"layer\",function(e){\"use strict\";var i=layui.$,t=layui.layer,n=layui.hint(),a=layui.device(),o={config:{},set:function(e){var t=this;return t.config=i.extend({},t.config,e),t},on:function(e,i){return layui.onevent.call(this,r,e,i)}},l=function(){var e=this;return{upload:function(i){e.upload.call(e,i)},config:e.config}},r=\"upload\",u=\"layui-upload-file\",c=\"layui-upload-form\",f=\"layui-upload-iframe\",s=\"layui-upload-choose\",p=function(e){var t=this;t.config=i.extend({},t.config,o.config,e),t.render()};p.prototype.config={accept:\"images\",exts:\"\",auto:!0,bindAction:\"\",url:\"\",field:\"file\",method:\"post\",data:{},drag:!0,size:0,number:0,multiple:!1},p.prototype.render=function(e){var t=this,e=t.config;e.elem=i(e.elem),e.bindAction=i(e.bindAction),t.file(),t.events()},p.prototype.file=function(){var e=this,t=e.config,n=e.elemFile=i(['<input class=\"'+u+'\" type=\"file\" name=\"'+t.field+'\"',t.multiple?\" multiple\":\"\",\">\"].join(\"\")),o=t.elem.next();(o.hasClass(u)||o.hasClass(c))&&o.remove(),a.ie&&a.ie<10&&t.elem.wrap('<div class=\"layui-upload-wrap\"></div>'),e.isFile()?(e.elemFile=t.elem,t.field=t.elem[0].name):t.elem.after(n),a.ie&&a.ie<10&&e.initIE()},p.prototype.initIE=function(){var e=this,t=e.config,n=i('<iframe id=\"'+f+'\" class=\"'+f+'\" name=\"'+f+'\" frameborder=\"0\"></iframe>'),a=i(['<form target=\"'+f+'\" class=\"'+c+'\" method=\"'+t.method,'\" key=\"set-mine\" enctype=\"multipart/form-data\" action=\"'+t.url+'\">',\"</form>\"].join(\"\"));i(\"#\"+f)[0]||i(\"body\").append(n),t.elem.next().hasClass(f)||(e.elemFile.wrap(a),t.elem.next(\".\"+f).append(function(){var e=[];return layui.each(t.data,function(i,t){e.push('<input type=\"hidden\" name=\"'+i+'\" value=\"'+t+'\">')}),e.join(\"\")}()))},p.prototype.msg=function(e){return t.msg(e,{icon:2,shift:6})},p.prototype.isFile=function(){var e=this.config.elem[0];if(e)return\"input\"===e.tagName.toLocaleLowerCase()&&\"file\"===e.type},p.prototype.preview=function(e){var i=this;window.FileReader&&layui.each(i.chooseFiles,function(i,t){var n=new FileReader;n.readAsDataURL(t),n.onload=function(){e&&e(i,t,this.result)}})},p.prototype.upload=function(e,t){var n,o=this,l=o.config,r=o.elemFile[0],u=function(){var t=0,n=0,a=e||o.files||o.chooseFiles||r.files,u=function(){l.multiple&&t+n===o.fileLength&&\"function\"==typeof l.allDone&&l.allDone({total:o.fileLength,successful:t,aborted:n})};layui.each(a,function(e,a){var r=new FormData;r.append(l.field,a),layui.each(l.data,function(e,i){r.append(e,i)}),i.ajax({url:l.url,type:l.method,data:r,contentType:!1,processData:!1,dataType:\"json\",success:function(i){t++,d(e,i),u()},error:function(){n++,o.msg(\"请求上传接口出现异常\"),m(e),u()}})})},c=function(){var e=i(\"#\"+f);o.elemFile.parent().submit(),clearInterval(p.timer),p.timer=setInterval(function(){var i,t=e.contents().find(\"body\");try{i=t.text()}catch(n){o.msg(\"获取上传后的响应信息出现异常\"),clearInterval(p.timer),m()}i&&(clearInterval(p.timer),t.html(\"\"),d(0,i))},30)},d=function(e,i){if(o.elemFile.next(\".\"+s).remove(),r.value=\"\",\"object\"!=typeof i)try{i=JSON.parse(i)}catch(t){return i={},o.msg(\"请对上传接口返回有效JSON\")}\"function\"==typeof l.done&&l.done(i,e||0,function(e){o.upload(e)})},m=function(e){l.auto&&(r.value=\"\"),\"function\"==typeof l.error&&l.error(e||0,function(e){o.upload(e)})},h=l.exts,v=function(){var i=[];return layui.each(e||o.chooseFiles,function(e,t){i.push(t.name)}),i}(),g={preview:function(e){o.preview(e)},upload:function(e,i){var t={};t[e]=i,o.upload(t)},pushFile:function(){return o.files=o.files||{},layui.each(o.chooseFiles,function(e,i){o.files[e]=i}),o.files}},y=function(){return\"choose\"===t?l.choose&&l.choose(g):(l.before&&l.before(g),a.ie?a.ie>9?u():c():void u())};if(v=0===v.length?r.value.match(/[^\\/\\\\]+\\..+/g)||[]||\"\":v,0!==v.length){switch(l.accept){case\"file\":if(h&&!RegExp(\"\\\\w\\\\.(\"+h+\")$\",\"i\").test(escape(v)))return o.msg(\"选择的文件中包含不支持的格式\"),r.value=\"\";break;case\"video\":if(!RegExp(\"\\\\w\\\\.(\"+(h||\"avi|mp4|wma|rmvb|rm|flash|3gp|flv\")+\")$\",\"i\").test(escape(v)))return o.msg(\"选择的视频中包含不支持的格式\"),r.value=\"\";break;case\"audio\":if(!RegExp(\"\\\\w\\\\.(\"+(h||\"mp3|wav|mid\")+\")$\",\"i\").test(escape(v)))return o.msg(\"选择的音频中包含不支持的格式\"),r.value=\"\";break;default:if(layui.each(v,function(e,i){RegExp(\"\\\\w\\\\.(\"+(h||\"jpg|png|gif|bmp|jpeg$\")+\")\",\"i\").test(escape(i))||(n=!0)}),n)return o.msg(\"选择的图片中包含不支持的格式\"),r.value=\"\"}if(o.fileLength=function(){var i=0,t=e||o.files||o.chooseFiles||r.files;return layui.each(t,function(){i++}),i}(),l.number&&o.fileLength>l.number)return o.msg(\"同时最多只能上传的数量为：\"+l.number);if(l.size>0&&!(a.ie&&a.ie<10)){var F;if(layui.each(o.chooseFiles,function(e,i){if(i.size>1024*l.size){var t=l.size/1024;t=t>=1?Math.floor(t)+(t%1>0?t.toFixed(1):0)+\"MB\":l.size+\"KB\",r.value=\"\",F=t}}),F)return o.msg(\"文件不能超过\"+F)}y()}},p.prototype.events=function(){var e=this,t=e.config,o=function(i){e.chooseFiles={},layui.each(i,function(i,t){var n=(new Date).getTime();e.chooseFiles[n+\"-\"+i]=t})},l=function(i,n){var a=e.elemFile,o=i.length>1?i.length+\"个文件\":(i[0]||{}).name||a[0].value.match(/[^\\/\\\\]+\\..+/g)||[]||\"\";a.next().hasClass(s)&&a.next().remove(),e.upload(null,\"choose\"),e.isFile()||t.choose||a.after('<span class=\"layui-inline '+s+'\">'+o+\"</span>\")};t.elem.off(\"upload.start\").on(\"upload.start\",function(){var a=i(this),o=a.attr(\"lay-data\");if(o)try{o=new Function(\"return \"+o)(),e.config=i.extend({},t,o)}catch(l){n.error(\"Upload element property lay-data configuration item has a syntax error: \"+o)}e.config.item=a,e.elemFile[0].click()}),a.ie&&a.ie<10||t.elem.off(\"upload.over\").on(\"upload.over\",function(){var e=i(this);e.attr(\"lay-over\",\"\")}).off(\"upload.leave\").on(\"upload.leave\",function(){var e=i(this);e.removeAttr(\"lay-over\")}).off(\"upload.drop\").on(\"upload.drop\",function(n,a){var r=i(this),u=a.originalEvent.dataTransfer.files||[];r.removeAttr(\"lay-over\"),o(u),t.auto?e.upload(u):l(u)}),e.elemFile.off(\"upload.change\").on(\"upload.change\",function(){var i=this.files||[];o(i),t.auto?e.upload():l(i)}),t.bindAction.off(\"upload.action\").on(\"upload.action\",function(){e.upload()}),t.elem.data(\"haveEvents\")||(e.elemFile.on(\"change\",function(){i(this).trigger(\"upload.change\")}),t.elem.on(\"click\",function(){e.isFile()||i(this).trigger(\"upload.start\")}),t.drag&&t.elem.on(\"dragover\",function(e){e.preventDefault(),i(this).trigger(\"upload.over\")}).on(\"dragleave\",function(e){i(this).trigger(\"upload.leave\")}).on(\"drop\",function(e){e.preventDefault(),i(this).trigger(\"upload.drop\",e)}),t.bindAction.on(\"click\",function(){i(this).trigger(\"upload.action\")}),t.elem.data(\"haveEvents\",!0))},o.render=function(e){var i=new p(e);return l.call(i)},e(r,o)});layui.define(\"layer\",function(e){\"use strict\";var t=layui.$,i=layui.layer,a=layui.hint(),n=layui.device(),l=\"form\",r=\".layui-form\",s=\"layui-this\",o=\"layui-hide\",u=\"layui-disabled\",c=function(){this.config={verify:{required:[/[\\S]+/,\"必填项不能为空\"],phone:[/^1\\d{10}$/,\"请输入正确的手机号\"],email:[/^([a-zA-Z0-9_\\.\\-])+\\@(([a-zA-Z0-9\\-])+\\.)+([a-zA-Z0-9]{2,4})+$/,\"邮箱格式不正确\"],url:[/(^#)|(^http(s*):\\/\\/[^\\s]+\\.[^\\s]+)/,\"链接格式不正确\"],number:function(e){if(!e||isNaN(e))return\"只能填写数字\"},date:[/^(\\d{4})[-\\/](\\d{1}|0\\d{1}|1[0-2])([-\\/](\\d{1}|0\\d{1}|[1-2][0-9]|3[0-1]))*$/,\"日期格式不正确\"],identity:[/(^\\d{15}$)|(^\\d{17}(x|X|\\d)$)/,\"请输入正确的身份证号\"]}}};c.prototype.set=function(e){var i=this;return t.extend(!0,i.config,e),i},c.prototype.verify=function(e){var i=this;return t.extend(!0,i.config.verify,e),i},c.prototype.on=function(e,t){return layui.onevent.call(this,l,e,t)},c.prototype.render=function(e,i){var n=this,c=t(r+function(){return i?'[lay-filter=\"'+i+'\"]':\"\"}()),d={select:function(){var e,i=\"请选择\",a=\"layui-form-select\",n=\"layui-select-title\",r=\"layui-select-none\",d=\"\",f=c.find(\"select\"),y=function(i,l){t(i.target).parent().hasClass(n)&&!l||(t(\".\"+a).removeClass(a+\"ed \"+a+\"up\"),e&&d&&e.val(d)),e=null},h=function(i,c,f){var h=t(this),p=i.find(\".\"+n),m=p.find(\"input\"),k=i.find(\"dl\"),g=k.children(\"dd\");if(!c){var x=function(){var e=i.offset().top+i.outerHeight()+5-v.scrollTop(),t=k.outerHeight();i.addClass(a+\"ed\"),g.removeClass(o),e+t>v.height()&&e>=t&&i.addClass(a+\"up\")},b=function(e){i.removeClass(a+\"ed \"+a+\"up\"),m.blur(),e||C(m.val(),function(e){e&&(d=k.find(\".\"+s).html(),m&&m.val(d))})};p.on(\"click\",function(e){i.hasClass(a+\"ed\")?b():(y(e,!0),x()),k.find(\".\"+r).remove()}),p.find(\".layui-edge\").on(\"click\",function(){m.focus()}),m.on(\"keyup\",function(e){var t=e.keyCode;9===t&&x()}).on(\"keydown\",function(e){var t=e.keyCode;9===t?b():13===t&&e.preventDefault()});var C=function(e,i,a){var n=0;layui.each(g,function(){var i=t(this),l=i.text(),r=l.indexOf(e)===-1;(\"\"===e||\"blur\"===a?e!==l:r)&&n++,\"keyup\"===a&&i[r?\"addClass\":\"removeClass\"](o)});var l=n===g.length;return i(l),l},w=function(e){var t=this.value,i=e.keyCode;return 9!==i&&13!==i&&37!==i&&38!==i&&39!==i&&40!==i&&(C(t,function(e){e?k.find(\".\"+r)[0]||k.append('<p class=\"'+r+'\">无匹配项</p>'):k.find(\".\"+r).remove()},\"keyup\"),void(\"\"===t&&k.find(\".\"+r).remove()))};f&&m.on(\"keyup\",w).on(\"blur\",function(t){e=m,d=k.find(\".\"+s).html(),setTimeout(function(){C(m.val(),function(e){d||m.val(\"\")},\"blur\")},200)}),g.on(\"click\",function(){var e=t(this),a=e.attr(\"lay-value\"),n=h.attr(\"lay-filter\");return!e.hasClass(u)&&(e.hasClass(\"layui-select-tips\")?m.val(\"\"):(m.val(e.text()),e.addClass(s)),e.siblings().removeClass(s),h.val(a).removeClass(\"layui-form-danger\"),layui.event.call(this,l,\"select(\"+n+\")\",{elem:h[0],value:a,othis:i}),b(!0),!1)}),i.find(\"dl>dt\").on(\"click\",function(e){return!1}),t(document).off(\"click\",y).on(\"click\",y)}};f.each(function(e,l){var r=t(this),o=r.next(\".\"+a),c=this.disabled,d=l.value,f=t(l.options[l.selectedIndex]),y=l.options[0];if(\"string\"==typeof r.attr(\"lay-ignore\"))return r.show();var v=\"string\"==typeof r.attr(\"lay-search\"),p=y?y.value?i:y.innerHTML||i:i,m=t(['<div class=\"'+(v?\"\":\"layui-unselect \")+a+(c?\" layui-select-disabled\":\"\")+'\">','<div class=\"'+n+'\"><input type=\"text\" placeholder=\"'+p+'\" value=\"'+(d?f.html():\"\")+'\" '+(v?\"\":\"readonly\")+' class=\"layui-input'+(v?\"\":\" layui-unselect\")+(c?\" \"+u:\"\")+'\">','<i class=\"layui-edge\"></i></div>','<dl class=\"layui-anim layui-anim-upbit'+(r.find(\"optgroup\")[0]?\" layui-select-group\":\"\")+'\">'+function(e){var t=[];return layui.each(e,function(e,a){0!==e||a.value?\"optgroup\"===a.tagName.toLowerCase()?t.push(\"<dt>\"+a.label+\"</dt>\"):t.push('<dd lay-value=\"'+a.value+'\" class=\"'+(d===a.value?s:\"\")+(a.disabled?\" \"+u:\"\")+'\">'+a.innerHTML+\"</dd>\"):t.push('<dd lay-value=\"\" class=\"layui-select-tips\">'+(a.innerHTML||i)+\"</dd>\")}),0===t.length&&t.push('<dd lay-value=\"\" class=\"'+u+'\">没有选项</dd>'),t.join(\"\")}(r.find(\"*\"))+\"</dl>\",\"</div>\"].join(\"\"));o[0]&&o.remove(),r.after(m),h.call(this,m,c,v)})},checkbox:function(){var e={checkbox:[\"layui-form-checkbox\",\"layui-form-checked\",\"checkbox\"],_switch:[\"layui-form-switch\",\"layui-form-onswitch\",\"switch\"]},i=c.find(\"input[type=checkbox]\"),a=function(e,i){var a=t(this);e.on(\"click\",function(){var t=a.attr(\"lay-filter\"),n=(a.attr(\"lay-text\")||\"\").split(\"|\");a[0].disabled||(a[0].checked?(a[0].checked=!1,e.removeClass(i[1]).find(\"em\").text(n[1])):(a[0].checked=!0,e.addClass(i[1]).find(\"em\").text(n[0])),layui.event.call(a[0],l,i[2]+\"(\"+t+\")\",{elem:a[0],value:a[0].value,othis:e}))})};i.each(function(i,n){var l=t(this),r=l.attr(\"lay-skin\"),s=(l.attr(\"lay-text\")||\"\").split(\"|\"),o=this.disabled;\"switch\"===r&&(r=\"_\"+r);var c=e[r]||e.checkbox;if(\"string\"==typeof l.attr(\"lay-ignore\"))return l.show();var d=l.next(\".\"+c[0]),f=t(['<div class=\"layui-unselect '+c[0]+(n.checked?\" \"+c[1]:\"\")+(o?\" layui-checkbox-disbaled \"+u:\"\")+'\" lay-skin=\"'+(r||\"\")+'\">',{_switch:\"<em>\"+((n.checked?s[0]:s[1])||\"\")+\"</em><i></i>\"}[r]||(n.title.replace(/\\s/g,\"\")?\"<span>\"+n.title+\"</span>\":\"\")+'<i class=\"layui-icon\">'+(r?\"&#xe605;\":\"&#xe618;\")+\"</i>\",\"</div>\"].join(\"\"));d[0]&&d.remove(),l.after(f),a.call(this,f,c)})},radio:function(){var e=\"layui-form-radio\",i=[\"&#xe643;\",\"&#xe63f;\"],a=c.find(\"input[type=radio]\"),n=function(a){var n=t(this),s=\"layui-anim-scaleSpring\";a.on(\"click\",function(){var o=n[0].name,u=n.parents(r),c=n.attr(\"lay-filter\"),d=u.find(\"input[name=\"+o.replace(/(\\.|#|\\[|\\])/g,\"\\\\$1\")+\"]\");n[0].disabled||(layui.each(d,function(){var a=t(this).next(\".\"+e);this.checked=!1,a.removeClass(e+\"ed\"),a.find(\".layui-icon\").removeClass(s).html(i[1])}),n[0].checked=!0,a.addClass(e+\"ed\"),a.find(\".layui-icon\").addClass(s).html(i[0]),layui.event.call(n[0],l,\"radio(\"+c+\")\",{elem:n[0],value:n[0].value,othis:a}))})};a.each(function(a,l){var r=t(this),s=r.next(\".\"+e),o=this.disabled;if(\"string\"==typeof r.attr(\"lay-ignore\"))return r.show();s[0]&&s.remove();var c=t(['<div class=\"layui-unselect '+e+(l.checked?\" \"+e+\"ed\":\"\")+(o?\" layui-radio-disbaled \"+u:\"\")+'\">','<i class=\"layui-anim layui-icon\">'+i[l.checked?0:1]+\"</i>\",\"<div>\"+function(){var e=l.title||\"\";return\"string\"==typeof r.next().attr(\"lay-radio\")&&(e=r.next().html(),r.next().remove()),e}()+\"</div>\",\"</div>\"].join(\"\"));r.after(c),n.call(this,c)})}};return e?d[e]?d[e]():a.error(\"不支持的\"+e+\"表单渲染\"):layui.each(d,function(e,t){t()}),n};var d=function(){var e=t(this),a=f.config.verify,s=null,o=\"layui-form-danger\",u={},c=e.parents(r),d=c.find(\"*[lay-verify]\"),y=e.parents(\"form\")[0],v=c.find(\"input,select,textarea\"),h=e.attr(\"lay-filter\");if(layui.each(d,function(e,l){var r=t(this),u=r.attr(\"lay-verify\").split(\"|\"),c=r.attr(\"lay-verType\"),d=r.val();if(r.removeClass(o),layui.each(u,function(e,t){var u,f=\"\",y=\"function\"==typeof a[t];if(a[t]){var u=y?f=a[t](d,l):!a[t][0].test(d);if(f=f||a[t][1],u)return\"tips\"===c?i.tips(f,function(){return\"string\"==typeof r.attr(\"lay-ignore\")||\"select\"!==l.tagName.toLowerCase()&&!/^checkbox|radio$/.test(l.type)?r:r.next()}(),{tips:1}):\"alert\"===c?i.alert(f,{title:\"提示\",shadeClose:!0}):i.msg(f,{icon:5,shift:6}),n.android||n.ios||l.focus(),r.addClass(o),s=!0}}),s)return s}),s)return!1;var p={};return layui.each(v,function(e,t){if(t.name=(t.name||\"\").replace(/^\\s*|\\s*&/,\"\"),t.name){if(/^.*\\[\\]$/.test(t.name)){var i=t.name.match(/^(.*)\\[\\]$/g)[0];p[i]=0|p[i],t.name=t.name.replace(/^(.*)\\[\\]$/,\"$1[\"+p[i]++ +\"]\")}/^checkbox|radio$/.test(t.type)&&!t.checked||(u[t.name]=t.value)}}),layui.event.call(this,l,\"submit(\"+h+\")\",{elem:this,form:y,field:u})},f=new c,y=t(document),v=t(window);f.render(),y.on(\"reset\",r,function(){var e=t(this).attr(\"lay-filter\");setTimeout(function(){f.render(null,e)},50)}),y.on(\"submit\",r,d).on(\"click\",\"*[lay-submit]\",d),e(l,f)});layui.define(\"jquery\",function(e){\"use strict\";var o=layui.$,a=layui.hint(),i=\"layui-tree-enter\",r=function(e){this.options=e},t={arrow:[\"&#xe623;\",\"&#xe625;\"],checkbox:[\"&#xe626;\",\"&#xe627;\"],radio:[\"&#xe62b;\",\"&#xe62a;\"],branch:[\"&#xe622;\",\"&#xe624;\"],leaf:\"&#xe621;\"};r.prototype.init=function(e){var o=this;e.addClass(\"layui-box layui-tree\"),o.options.skin&&e.addClass(\"layui-tree-skin-\"+o.options.skin),o.tree(e),o.on(e)},r.prototype.tree=function(e,a){var i=this,r=i.options,n=a||r.nodes;layui.each(n,function(a,n){var l=n.children&&n.children.length>0,c=o('<ul class=\"'+(n.spread?\"layui-show\":\"\")+'\"></ul>'),s=o([\"<li \"+(n.spread?'data-spread=\"'+n.spread+'\"':\"\")+\">\",function(){return l?'<i class=\"layui-icon layui-tree-spread\">'+(n.spread?t.arrow[1]:t.arrow[0])+\"</i>\":\"\"}(),function(){return r.check?'<i class=\"layui-icon layui-tree-check\">'+(\"checkbox\"===r.check?t.checkbox[0]:\"radio\"===r.check?t.radio[0]:\"\")+\"</i>\":\"\"}(),function(){return'<a href=\"'+(n.href||\"javascript:;\")+'\" '+(r.target&&n.href?'target=\"'+r.target+'\"':\"\")+\">\"+('<i class=\"layui-icon layui-tree-'+(l?\"branch\":\"leaf\")+'\">'+(l?n.spread?t.branch[1]:t.branch[0]:t.leaf)+\"</i>\")+(\"<cite>\"+(n.name||\"未命名\")+\"</cite></a>\")}(),\"</li>\"].join(\"\"));l&&(s.append(c),i.tree(c,n.children)),e.append(s),\"function\"==typeof r.click&&i.click(s,n),i.spread(s,n),r.drag&&i.drag(s,n)})},r.prototype.click=function(e,o){var a=this,i=a.options;e.children(\"a\").on(\"click\",function(e){layui.stope(e),i.click(o)})},r.prototype.spread=function(e,o){var a=this,i=(a.options,e.children(\".layui-tree-spread\")),r=e.children(\"ul\"),n=e.children(\"a\"),l=function(){e.data(\"spread\")?(e.data(\"spread\",null),r.removeClass(\"layui-show\"),i.html(t.arrow[0]),n.find(\".layui-icon\").html(t.branch[0])):(e.data(\"spread\",!0),r.addClass(\"layui-show\"),i.html(t.arrow[1]),n.find(\".layui-icon\").html(t.branch[1]))};r[0]&&(i.on(\"click\",l),n.on(\"dblclick\",l))},r.prototype.on=function(e){var a=this,r=a.options,t=\"layui-tree-drag\";e.find(\"i\").on(\"selectstart\",function(e){return!1}),r.drag&&o(document).on(\"mousemove\",function(e){var i=a.move;if(i.from){var r=(i.to,o('<div class=\"layui-box '+t+'\"></div>'));e.preventDefault(),o(\".\"+t)[0]||o(\"body\").append(r);var n=o(\".\"+t)[0]?o(\".\"+t):r;n.addClass(\"layui-show\").html(i.from.elem.children(\"a\").html()),n.css({left:e.pageX+10,top:e.pageY+10})}}).on(\"mouseup\",function(){var e=a.move;e.from&&(e.from.elem.children(\"a\").removeClass(i),e.to&&e.to.elem.children(\"a\").removeClass(i),a.move={},o(\".\"+t).remove())})},r.prototype.move={},r.prototype.drag=function(e,a){var r=this,t=(r.options,e.children(\"a\")),n=function(){var t=o(this),n=r.move;n.from&&(n.to={item:a,elem:e},t.addClass(i))};t.on(\"mousedown\",function(){var o=r.move;o.from={item:a,elem:e}}),t.on(\"mouseenter\",n).on(\"mousemove\",n).on(\"mouseleave\",function(){var e=o(this),a=r.move;a.from&&(delete a.to,e.removeClass(i))})},e(\"tree\",function(e){var i=new r(e=e||{}),t=o(e.elem);return t[0]?void i.init(t):a.error(\"layui.tree 没有找到\"+e.elem+\"元素\")})});layui.define([\"laytpl\",\"laypage\",\"layer\",\"form\"],function(e){\"use strict\";var t=layui.$,i=layui.laytpl,a=layui.laypage,l=layui.layer,n=layui.form,o=layui.hint(),r=layui.device(),d={config:{checkName:\"LAY_CHECKED\",indexName:\"LAY_TABLE_INDEX\"},cache:{},index:layui.table?layui.table.index+1e4:0,set:function(e){var i=this;return i.config=t.extend({},i.config,e),i},on:function(e,t){return layui.onevent.call(this,s,e,t)}},c=function(){var e=this,t=e.config,i=t.id;return i&&(c.config[i]=t),{reload:function(t){e.reload.call(e,t)},config:t}},s=\"table\",u=\".layui-table\",h=\"layui-hide\",f=\"layui-none\",y=\"layui-table-view\",p=\".layui-table-header\",m=\".layui-table-body\",v=\".layui-table-main\",g=\".layui-table-fixed\",x=\".layui-table-fixed-l\",b=\".layui-table-fixed-r\",k=\".layui-table-tool\",C=\".layui-table-page\",w=\".layui-table-sort\",N=\"layui-table-edit\",F=\"layui-table-hover\",W=function(e){var t='{{#if(item2.colspan){}} colspan=\"{{item2.colspan}}\"{{#} if(item2.rowspan){}} rowspan=\"{{item2.rowspan}}\"{{#}}}';return e=e||{},['<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\" class=\"layui-table\" ','{{# if(d.data.skin){ }}lay-skin=\"{{d.data.skin}}\"{{# } }} {{# if(d.data.size){ }}lay-size=\"{{d.data.size}}\"{{# } }} {{# if(d.data.even){ }}lay-even{{# } }}>',\"<thead>\",\"{{# layui.each(d.data.cols, function(i1, item1){ }}\",\"<tr>\",\"{{# layui.each(item1, function(i2, item2){ }}\",'{{# if(item2.fixed && item2.fixed !== \"right\"){ left = true; } }}','{{# if(item2.fixed === \"right\"){ right = true; } }}',function(){return e.fixed&&\"right\"!==e.fixed?'{{# if(item2.fixed && item2.fixed !== \"right\"){ }}':\"right\"===e.fixed?'{{# if(item2.fixed === \"right\"){ }}':\"\"}(),'<th data-field=\"{{ item2.field||i2 }}\" {{# if(item2.minWidth){ }}data-minwidth=\"{{item2.minWidth}}\"{{# } }} '+t+' {{# if(item2.unresize){ }}data-unresize=\"true\"{{# } }}>','<div class=\"layui-table-cell laytable-cell-',\"{{# if(item2.colspan > 1){ }}\",\"group\",\"{{# } else { }}\",\"{{d.index}}-{{item2.field || i2}}\",'{{# if(item2.type !== \"normal\"){ }}',\" laytable-cell-{{ item2.type }}\",\"{{# } }}\",\"{{# } }}\",'\" {{#if(item2.align){}}align=\"{{item2.align}}\"{{#}}}>','{{# if(item2.type === \"checkbox\"){ }}','<input type=\"checkbox\" name=\"layTableCheckbox\" lay-skin=\"primary\" lay-filter=\"layTableAllChoose\" {{# if(item2[d.data.checkName]){ }}checked{{# }; }}>',\"{{# } else { }}\",'<span>{{item2.title||\"\"}}</span>',\"{{# if(!(item2.colspan > 1) && item2.sort){ }}\",'<span class=\"layui-table-sort layui-inline\"><i class=\"layui-edge layui-table-sort-asc\"></i><i class=\"layui-edge layui-table-sort-desc\"></i></span>',\"{{# } }}\",\"{{# } }}\",\"</div>\",\"</th>\",e.fixed?\"{{# }; }}\":\"\",\"{{# }); }}\",\"</tr>\",\"{{# }); }}\",\"</thead>\",\"</table>\"].join(\"\")},z=['<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\" class=\"layui-table\" ','{{# if(d.data.skin){ }}lay-skin=\"{{d.data.skin}}\"{{# } }} {{# if(d.data.size){ }}lay-size=\"{{d.data.size}}\"{{# } }} {{# if(d.data.even){ }}lay-even{{# } }}>',\"<tbody></tbody>\",\"</table>\"].join(\"\"),A=['<div class=\"layui-form layui-border-box {{d.VIEW_CLASS}}\" lay-filter=\"LAY-table-{{d.index}}\" style=\"{{# if(d.data.width){ }}width:{{d.data.width}}px;{{# } }} {{# if(d.data.height){ }}height:{{d.data.height}}px;{{# } }}\">',\"{{# if(d.data.toolbar){ }}\",'<div class=\"layui-table-tool\"></div>',\"{{# } }}\",'<div class=\"layui-table-box\">',\"{{# var left, right; }}\",'<div class=\"layui-table-header\">',W(),\"</div>\",'<div class=\"layui-table-body layui-table-main\">',z,\"</div>\",\"{{# if(left){ }}\",'<div class=\"layui-table-fixed layui-table-fixed-l\">','<div class=\"layui-table-header\">',W({fixed:!0}),\"</div>\",'<div class=\"layui-table-body\">',z,\"</div>\",\"</div>\",\"{{# }; }}\",\"{{# if(right){ }}\",'<div class=\"layui-table-fixed layui-table-fixed-r\">','<div class=\"layui-table-header\">',W({fixed:\"right\"}),'<div class=\"layui-table-mend\"></div>',\"</div>\",'<div class=\"layui-table-body\">',z,\"</div>\",\"</div>\",\"{{# }; }}\",\"</div>\",\"{{# if(d.data.page){ }}\",'<div class=\"layui-table-page\">','<div id=\"layui-table-page{{d.index}}\"></div>',\"</div>\",\"{{# } }}\",\"<style>\",\"{{# layui.each(d.data.cols, function(i1, item1){\",\"layui.each(item1, function(i2, item2){ }}\",\".laytable-cell-{{d.index}}-{{item2.field||i2}}{ \",\"{{# if(item2.width){ }}\",\"width: {{item2.width}}px;\",\"{{# } }}\",\" }\",\"{{# });\",\"}); }}\",\"</style>\",\"</div>\"].join(\"\"),T=t(window),M=t(document),S=function(e){var i=this;i.index=++d.index,i.config=t.extend({},i.config,d.config,e),i.render()};S.prototype.config={limit:10,loading:!0,cellMinWidth:60,text:{none:\"无数据\"}},S.prototype.render=function(){var e=this,a=e.config;if(a.elem=t(a.elem),a.where=a.where||{},a.id=a.id||a.elem.attr(\"id\"),a.request=t.extend({pageName:\"page\",limitName:\"limit\"},a.request),a.response=t.extend({statusName:\"code\",statusCode:0,msgName:\"msg\",dataName:\"data\",countName:\"count\"},a.response),\"object\"==typeof a.page&&(a.limit=a.page.limit||a.limit,a.limits=a.page.limits||a.limits,e.page=a.page.curr=a.page.curr||1,delete a.page.elem,delete a.page.jump),!a.elem[0])return e;e.setArea();var l=a.elem,n=l.next(\".\"+y),o=e.elem=t(i(A).render({VIEW_CLASS:y,data:a,index:e.index}));if(a.index=e.index,n[0]&&n.remove(),l.after(o),e.layHeader=o.find(p),e.layMain=o.find(v),e.layBody=o.find(m),e.layFixed=o.find(g),e.layFixLeft=o.find(x),e.layFixRight=o.find(b),e.layTool=o.find(k),e.layPage=o.find(C),e.layTool.html(i(t(a.toolbar).html()||\"\").render(a)),a.height&&e.fullSize(),a.cols.length>1){var r=e.layFixed.find(p).find(\"th\");r.height(e.layHeader.height()-1-parseFloat(r.css(\"padding-top\"))-parseFloat(r.css(\"padding-bottom\")))}e.pullData(e.page),e.events()},S.prototype.initOpts=function(e){var t=this,i=(t.config,{checkbox:48,space:15,numbers:40});e.checkbox&&(e.type=\"checkbox\"),e.space&&(e.type=\"space\"),e.type||(e.type=\"normal\"),\"normal\"!==e.type&&(e.unresize=!0,e.width=e.width||i[e.type])},S.prototype.setArea=function(){var e=this,t=e.config,i=0,a=0,l=0,n=0,o=t.width||function(){var e=function(i){var a,l;i=i||t.elem.parent(),a=i.width();try{l=\"none\"===i.css(\"display\")}catch(n){}return!i[0]||a&&!l?a:e(i.parent())};return e()}();e.eachCols(function(){i++}),o-=function(){return\"line\"===t.skin||\"nob\"===t.skin?2:i+1}(),layui.each(t.cols,function(t,i){layui.each(i,function(t,l){var r;return l?(e.initOpts(l),r=l.width||0,void(l.colspan>1||(/\\d+%$/.test(r)?l.width=r=Math.floor(parseFloat(r)/100*o):r||(l.width=r=0,a++),n+=r))):void i.splice(t,1)})}),e.autoColNums=a,o>n&&a&&(l=(o-n)/a),layui.each(t.cols,function(e,i){layui.each(i,function(e,i){var a=i.minWidth||t.cellMinWidth;i.colspan>1||0===i.width&&(i.width=Math.floor(l>=a?l:a))})}),t.height&&/^full-\\d+$/.test(t.height)&&(e.fullHeightGap=t.height.split(\"-\")[1],t.height=T.height()-e.fullHeightGap)},S.prototype.reload=function(e){var i=this;i.config.data&&i.config.data.constructor===Array&&delete i.config.data,i.config=t.extend({},i.config,e),i.render()},S.prototype.page=1,S.prototype.pullData=function(e,i){var a=this,n=a.config,o=n.request,r=n.response,d=function(){\"object\"==typeof n.initSort&&a.sort(n.initSort.field,n.initSort.type)};if(a.startTime=(new Date).getTime(),n.url){var c={};c[o.pageName]=e,c[o.limitName]=n.limit,t.ajax({type:n.method||\"get\",url:n.url,data:t.extend(c,n.where),dataType:\"json\",success:function(t){t[r.statusName]!=r.statusCode?(a.renderForm(),a.layMain.html('<div class=\"'+f+'\">'+(t[r.msgName]||\"返回的数据状态异常\")+\"</div>\")):(a.renderData(t,e,t[r.countName]),d(),n.time=(new Date).getTime()-a.startTime+\" ms\"),i&&l.close(i),\"function\"==typeof n.done&&n.done(t,e,t[r.countName])},error:function(e,t){a.layMain.html('<div class=\"'+f+'\">数据接口请求异常</div>'),a.renderForm(),i&&l.close(i)}})}else if(n.data&&n.data.constructor===Array){var s={},u=e*n.limit-n.limit;s[r.dataName]=n.data.concat().splice(u,n.limit),s[r.countName]=n.data.length,a.renderData(s,e,n.data.length),d(),\"function\"==typeof n.done&&n.done(s,e,s[r.countName])}},S.prototype.eachCols=function(e){var i=t.extend(!0,[],this.config.cols),a=[],l=0;layui.each(i,function(e,t){layui.each(t,function(t,n){if(n.colspan>1){var o=0;l++,n.CHILD_COLS=[],layui.each(i[e+1],function(e,t){t.PARENT_COL||o==n.colspan||(t.PARENT_COL=l,n.CHILD_COLS.push(t),o+=t.colspan>1?t.colspan:1)})}n.PARENT_COL||a.push(n)})});var n=function(t){layui.each(t||a,function(t,i){return i.CHILD_COLS?n(i.CHILD_COLS):void e(t,i)})};n()},S.prototype.renderData=function(e,n,o,r){var c=this,s=c.config,u=e[s.response.dataName]||[],y=[],p=[],m=[],v=function(){return!r&&c.sortKey?c.sort(c.sortKey.field,c.sortKey.sort,!0):(layui.each(u,function(e,a){var l=[],o=[],u=[],h=e+s.limit*(n-1)+1;0!==a.length&&(r||(a[d.config.indexName]=e),c.eachCols(function(e,n){var r=n.field||e,f=a[r];c.getColElem(c.layHeader,r);if(void 0!==f&&null!==f||(f=\"\"),!(n.colspan>1)){var y=['<td data-field=\"'+r+'\" '+function(){var e=[];return n.edit&&e.push('data-edit=\"'+n.edit+'\"'),n.align&&e.push('align=\"'+n.align+'\"'),n.templet&&e.push('data-content=\"'+f+'\"'),n.toolbar&&e.push('data-off=\"true\"'),n.event&&e.push('lay-event=\"'+n.event+'\"'),n.style&&e.push('style=\"'+n.style+'\"'),n.minWidth&&e.push('data-minwidth=\"'+n.minWidth+'\"'),e.join(\" \")}()+\">\",'<div class=\"layui-table-cell laytable-cell-'+function(){var e=s.index+\"-\"+r;return\"normal\"===n.type?e:e+\" laytable-cell-\"+n.type}()+'\">'+function(){var e=t.extend(!0,{LAY_INDEX:h},a);return\"checkbox\"===n.type?'<input type=\"checkbox\" name=\"layTableCheckbox\" lay-skin=\"primary\" '+function(){var t=d.config.checkName;return n[t]?(a[t]=n[t],n[t]?\"checked\":\"\"):e[t]?\"checked\":\"\"}()+\">\":\"numbers\"===n.type?h:n.toolbar?i(t(n.toolbar).html()||\"\").render(e):n.templet?function(){return\"function\"==typeof n.templet?n.templet(e):i(t(n.templet).html()||String(f)).render(e)}():f}(),\"</div></td>\"].join(\"\");l.push(y),n.fixed&&\"right\"!==n.fixed&&o.push(y),\"right\"===n.fixed&&u.push(y)}}),y.push('<tr data-index=\"'+e+'\">'+l.join(\"\")+\"</tr>\"),p.push('<tr data-index=\"'+e+'\">'+o.join(\"\")+\"</tr>\"),m.push('<tr data-index=\"'+e+'\">'+u.join(\"\")+\"</tr>\"))}),c.layBody.scrollTop(0),c.layMain.find(\".\"+f).remove(),c.layMain.find(\"tbody\").html(y.join(\"\")),c.layFixLeft.find(\"tbody\").html(p.join(\"\")),c.layFixRight.find(\"tbody\").html(m.join(\"\")),c.renderForm(),c.syncCheckAll(),c.haveInit?c.scrollPatch():setTimeout(function(){c.scrollPatch()},50),c.haveInit=!0,void l.close(c.tipsIndex))};return c.key=s.id||s.index,d.cache[c.key]=u,c.layPage[0===u.length&&1==n?\"addClass\":\"removeClass\"](h),r?v():0===u.length?(c.renderForm(),c.layFixed.remove(),c.layMain.find(\"tbody\").html(\"\"),c.layMain.find(\".\"+f).remove(),c.layMain.append('<div class=\"'+f+'\">'+s.text.none+\"</div>\")):(v(),void(s.page&&(s.page=t.extend({elem:\"layui-table-page\"+s.index,count:o,limit:s.limit,limits:s.limits||[10,20,30,40,50,60,70,80,90],groups:3,layout:[\"prev\",\"page\",\"next\",\"skip\",\"count\",\"limit\"],prev:'<i class=\"layui-icon\">&#xe603;</i>',next:'<i class=\"layui-icon\">&#xe602;</i>',jump:function(e,t){t||(c.page=e.curr,s.limit=e.limit,c.pullData(e.curr,c.loading()))}},s.page),s.page.count=o,a.render(s.page))))},S.prototype.getColElem=function(e,t){var i=this,a=i.config;return e.eq(0).find(\".laytable-cell-\"+(a.index+\"-\"+t)+\":eq(0)\")},S.prototype.renderForm=function(e){n.render(e,\"LAY-table-\"+this.index)},S.prototype.sort=function(e,i,a,l){var n,r,c=this,u={},h=c.config,f=h.elem.attr(\"lay-filter\"),y=d.cache[c.key];\"string\"==typeof e&&c.layHeader.find(\"th\").each(function(i,a){var l=t(this),o=l.data(\"field\");if(o===e)return e=l,n=o,!1});try{var n=n||e.data(\"field\");if(c.sortKey&&!a&&n===c.sortKey.field&&i===c.sortKey.sort)return;var p=c.layHeader.find(\"th .laytable-cell-\"+h.index+\"-\"+n).find(w);c.layHeader.find(\"th\").find(w).removeAttr(\"lay-sort\"),p.attr(\"lay-sort\",i||null),c.layFixed.find(\"th\")}catch(m){return o.error(\"Table modules: Did not match to field\")}c.sortKey={field:n,sort:i},\"asc\"===i?r=layui.sort(y,n):\"desc\"===i?r=layui.sort(y,n,!0):(r=layui.sort(y,d.config.indexName),delete c.sortKey),u[h.response.dataName]=r,c.renderData(u,c.page,c.count,!0),l&&layui.event.call(e,s,\"sort(\"+f+\")\",{field:n,type:i})},S.prototype.loading=function(){var e=this,t=e.config;if(t.loading&&t.url)return l.msg(\"数据请求中\",{icon:16,offset:[e.elem.offset().top+e.elem.height()/2-35-T.scrollTop()+\"px\",e.elem.offset().left+e.elem.width()/2-90-T.scrollLeft()+\"px\"],time:-1,anim:-1,fixed:!1})},S.prototype.setCheckData=function(e,t){var i=this,a=i.config,l=d.cache[i.key];l[e]&&l[e].constructor!==Array&&(l[e][a.checkName]=t)},S.prototype.syncCheckAll=function(){var e=this,t=e.config,i=e.layHeader.find('input[name=\"layTableCheckbox\"]'),a=function(i){return e.eachCols(function(e,a){\"checkbox\"===a.type&&(a[t.checkName]=i)}),i};i[0]&&(d.checkStatus(e.key).isAll?(i[0].checked||(i.prop(\"checked\",!0),e.renderForm(\"checkbox\")),a(!0)):(i[0].checked&&(i.prop(\"checked\",!1),e.renderForm(\"checkbox\")),a(!1)))},S.prototype.getCssRule=function(e,t){var i=this,a=i.elem.find(\"style\")[0],l=a.sheet||a.styleSheet||{},n=l.cssRules||l.rules;layui.each(n,function(a,l){if(l.selectorText===\".laytable-cell-\"+i.index+\"-\"+e)return t(l),!0})},S.prototype.fullSize=function(){var e,t=this,i=t.config,a=i.height;t.fullHeightGap&&(a=T.height()-t.fullHeightGap,a<135&&(a=135),t.elem.css(\"height\",a)),e=parseFloat(a)-parseFloat(t.layHeader.height())-1,i.toolbar&&(e-=t.layTool.outerHeight()),i.page&&(e=e-t.layPage.outerHeight()-1),t.layMain.css(\"height\",e)},S.prototype.getScrollWidth=function(e){var t=0;return e?t=e.offsetWidth-e.clientWidth:(e=document.createElement(\"div\"),e.style.width=\"100px\",e.style.height=\"100px\",e.style.overflowY=\"scroll\",document.body.appendChild(e),t=e.offsetWidth-e.clientWidth,document.body.removeChild(e)),t},S.prototype.scrollPatch=function(){var e=this,i=e.layMain.children(\"table\"),a=e.layMain.width()-e.layMain.prop(\"clientWidth\"),l=e.layMain.height()-e.layMain.prop(\"clientHeight\"),n=e.getScrollWidth(e.layMain[0]),o=i.outerWidth()-e.layMain.width();if(e.autoColNums&&o<5&&!e.scrollPatchWStatus){var r=e.layHeader.eq(0).find(\"thead th:last-child\"),d=r.data(\"field\");e.getCssRule(d,function(t){var i=t.style.width||r.outerWidth();t.style.width=parseFloat(i)-n-o+\"px\",e.layMain.height()-e.layMain.prop(\"clientHeight\")>0&&(t.style.width=parseFloat(t.style.width)-1+\"px\"),e.scrollPatchWStatus=!0})}if(a&&l){if(!e.elem.find(\".layui-table-patch\")[0]){var c=t('<th class=\"layui-table-patch\"><div class=\"layui-table-cell\"></div></th>');c.find(\"div\").css({width:a}),e.layHeader.eq(0).find(\"thead tr\").append(c)}}else e.layHeader.eq(0).find(\".layui-table-patch\").remove();var s=e.layMain.height(),u=s-l;e.layFixed.find(m).css(\"height\",i.height()>u?u:\"auto\"),e.layFixRight[o>0?\"removeClass\":\"addClass\"](h),e.layFixRight.css(\"right\",a-1)},S.prototype.events=function(){var e,a=this,n=a.config,o=t(\"body\"),c={},u=a.layHeader.find(\"th\"),h=\".layui-table-cell\",f=n.elem.attr(\"lay-filter\");u.on(\"mousemove\",function(e){var i=t(this),a=i.offset().left,l=e.clientX-a;i.attr(\"colspan\")>1||i.data(\"unresize\")||c.resizeStart||(c.allowResize=i.width()-l<=10,o.css(\"cursor\",c.allowResize?\"col-resize\":\"\"))}).on(\"mouseleave\",function(){t(this);c.resizeStart||o.css(\"cursor\",\"\")}).on(\"mousedown\",function(e){var i=t(this);if(c.allowResize){var l=i.data(\"field\");e.preventDefault(),c.resizeStart=!0,c.offset=[e.clientX,e.clientY],a.getCssRule(l,function(e){var t=e.style.width||i.outerWidth();c.rule=e,c.ruleWidth=parseFloat(t),c.minWidth=i.data(\"minwidth\")||n.cellMinWidth})}}),M.on(\"mousemove\",function(t){if(c.resizeStart){if(t.preventDefault(),c.rule){var i=c.ruleWidth+t.clientX-c.offset[0];i<c.minWidth&&(i=c.minWidth),c.rule.style.width=i+\"px\",l.close(a.tipsIndex)}e=1}}).on(\"mouseup\",function(t){c.resizeStart&&(c={},o.css(\"cursor\",\"\"),a.scrollPatch()),2===e&&(e=null)}),u.on(\"click\",function(){var i,l=t(this),n=l.find(w),o=n.attr(\"lay-sort\");return n[0]&&1!==e?(i=\"asc\"===o?\"desc\":\"desc\"===o?null:\"asc\",void a.sort(l,i,null,!0)):e=2}).find(w+\" .layui-edge \").on(\"click\",function(e){var i=t(this),l=i.index(),n=i.parents(\"th\").eq(0).data(\"field\");layui.stope(e),0===l?a.sort(n,\"asc\",null,!0):a.sort(n,\"desc\",null,!0)}),a.elem.on(\"click\",'input[name=\"layTableCheckbox\"]+',function(){var e=t(this).prev(),i=a.layBody.find('input[name=\"layTableCheckbox\"]'),l=e.parents(\"tr\").eq(0).data(\"index\"),n=e[0].checked,o=\"layTableAllChoose\"===e.attr(\"lay-filter\");o?(i.each(function(e,t){t.checked=n,a.setCheckData(e,n)}),a.syncCheckAll(),a.renderForm(\"checkbox\")):(a.setCheckData(l,n),a.syncCheckAll()),layui.event.call(this,s,\"checkbox(\"+f+\")\",{checked:n,data:d.cache[a.key]?d.cache[a.key][l]||{}:{},type:o?\"all\":\"one\"})}),a.layBody.on(\"mouseenter\",\"tr\",function(){var e=t(this),i=e.index();a.layBody.find(\"tr:eq(\"+i+\")\").addClass(F)}).on(\"mouseleave\",\"tr\",function(){var e=t(this),i=e.index();a.layBody.find(\"tr:eq(\"+i+\")\").removeClass(F)}),a.layBody.on(\"change\",\".\"+N,function(){var e=t(this),i=this.value,l=e.parent().data(\"field\"),n=e.parents(\"tr\").eq(0).data(\"index\"),o=d.cache[a.key][n];o[l]=i,layui.event.call(this,s,\"edit(\"+f+\")\",{value:i,data:o,field:l})}).on(\"blur\",\".\"+N,function(){var e,l=t(this),n=l.parent().data(\"field\"),o=l.parents(\"tr\").eq(0).data(\"index\"),r=d.cache[a.key][o];a.eachCols(function(t,i){i.field==n&&i.templet&&(e=i.templet)}),l.siblings(h).html(e?i(t(e).html()||this.value).render(r):this.value),l.parent().data(\"content\",this.value),l.remove()}),a.layBody.on(\"click\",\"td\",function(){var e=t(this),i=(e.data(\"field\"),e.data(\"edit\")),o=e.children(h);if(l.close(a.tipsIndex),!e.data(\"off\"))if(i)if(\"select\"===i);else{var d=t('<input class=\"layui-input '+N+'\">');d[0].value=e.data(\"content\")||o.text(),e.find(\".\"+N)[0]||e.append(d),d.focus()}else o.find(\".layui-form-switch,.layui-form-checkbox\")[0]||Math.round(o.prop(\"scrollWidth\"))>Math.round(o.outerWidth())&&(a.tipsIndex=l.tips(['<div class=\"layui-table-tips-main\" style=\"margin-top: -'+(o.height()+16)+\"px;\"+function(){return\"sm\"===n.size?\"padding: 4px 15px; font-size: 12px;\":\"lg\"===n.size?\"padding: 14px 15px;\":\"\"}()+'\">',o.html(),\"</div>\",'<i class=\"layui-icon layui-table-tips-c\">&#x1006;</i>'].join(\"\"),o[0],{tips:[3,\"\"],time:-1,anim:-1,maxWidth:r.ios||r.android?300:600,isOutAnim:!1,skin:\"layui-table-tips\",success:function(e,t){e.find(\".layui-table-tips-c\").on(\"click\",function(){l.close(t)})}}))}),a.layBody.on(\"click\",\"*[lay-event]\",function(){var e=t(this),l=e.parents(\"tr\").eq(0).data(\"index\"),n=a.layBody.find('tr[data-index=\"'+l+'\"]'),o=\"layui-table-click\",r=d.cache[a.key][l];layui.event.call(this,s,\"tool(\"+f+\")\",{data:d.clearCacheKey(r),event:e.attr(\"lay-event\"),tr:n,del:function(){d.cache[a.key][l]=[],n.remove(),a.scrollPatch()},update:function(e){e=e||{},layui.each(e,function(e,l){if(e in r){var o,d=n.children('td[data-field=\"'+e+'\"]');r[e]=l,a.eachCols(function(t,i){i.field==e&&i.templet&&(o=i.templet)}),d.children(h).html(o?i(t(o).html()||l).render(r):l),d.data(\"content\",l)}})}}),n.addClass(o).siblings(\"tr\").removeClass(o)}),a.layMain.on(\"scroll\",function(){var e=t(this),i=e.scrollLeft(),n=e.scrollTop();a.layHeader.scrollLeft(i),a.layFixed.find(m).scrollTop(n),l.close(a.tipsIndex)}),T.on(\"resize\",function(){a.fullSize(),a.scrollPatch()})},d.init=function(e,i){i=i||{};var a=this,l=t(e?'table[lay-filter=\"'+e+'\"]':u+\"[lay-data]\"),n=\"Table element property lay-data configuration item has a syntax error: \";return l.each(function(){var a=t(this),l=a.attr(\"lay-data\");try{l=new Function(\"return \"+l)()}catch(r){o.error(n+l)}var c=[],s=t.extend({elem:this,cols:[],data:[],skin:a.attr(\"lay-skin\"),size:a.attr(\"lay-size\"),even:\"string\"==typeof a.attr(\"lay-even\")},d.config,i,l);e&&a.hide(),a.find(\"thead>tr\").each(function(e){s.cols[e]=[],t(this).children().each(function(i){var a=t(this),l=a.attr(\"lay-data\");try{l=new Function(\"return \"+l)()}catch(r){return o.error(n+l)}var d=t.extend({title:a.text(),colspan:a.attr(\"colspan\")||0,rowspan:a.attr(\"rowspan\")||0},l);d.colspan<2&&c.push(d),s.cols[e].push(d)})}),a.find(\"tbody>tr\").each(function(e){var i=t(this),a={};i.children(\"td\").each(function(e,i){var l=t(this),n=l.data(\"field\");if(n)return a[n]=l.html()}),layui.each(c,function(e,t){var l=i.children(\"td\").eq(e);a[t.field]=l.html()}),s.data[e]=a}),d.render(s)}),a},d.checkStatus=function(e){var t=0,i=0,a=[],l=d.cache[e]||[];return layui.each(l,function(e,l){return l.constructor===Array?void i++:void(l[d.config.checkName]&&(t++,a.push(d.clearCacheKey(l))))}),{data:a,isAll:!!l.length&&t===l.length-i}},c.config={},d.reload=function(e,i){var a=c.config[e];return i=i||{},a?(i.data&&i.data.constructor===Array&&delete a.data,d.render(t.extend(!0,{},a,i))):o.error(\"The ID option was not found in the table instance\")},d.render=function(e){var t=new S(e);return c.call(t)},d.clearCacheKey=function(e){return e=t.extend({},e),delete e[d.config.checkName],delete e[d.config.indexName],e},d.init(),e(s,d)});layui.define(\"jquery\",function(e){\"use strict\";var i=layui.$,n=(layui.hint(),layui.device(),{config:{},set:function(e){var n=this;return n.config=i.extend({},n.config,e),n},on:function(e,i){return layui.onevent.call(this,t,e,i)}}),t=\"carousel\",a=\"layui-this\",l=\">*[carousel-item]>*\",o=\"layui-carousel-left\",r=\"layui-carousel-right\",d=\"layui-carousel-prev\",s=\"layui-carousel-next\",u=\"layui-carousel-arrow\",c=\"layui-carousel-ind\",m=function(e){var t=this;t.config=i.extend({},t.config,n.config,e),t.render()};m.prototype.config={width:\"600px\",height:\"280px\",full:!1,arrow:\"hover\",indicator:\"inside\",autoplay:!0,interval:3e3,anim:\"\",trigger:\"click\",index:0},m.prototype.render=function(){var e=this,n=e.config;n.elem=i(n.elem),n.elem[0]&&(e.elemItem=n.elem.find(l),n.index<0&&(n.index=0),n.index>=e.elemItem.length&&(n.index=e.elemItem.length-1),n.interval<800&&(n.interval=800),n.full?n.elem.css({position:\"fixed\",width:\"100%\",height:\"100%\",zIndex:9999}):n.elem.css({width:n.width,height:n.height}),n.elem.attr(\"lay-anim\",n.anim),e.elemItem.eq(n.index).addClass(a),e.elemItem.length<=1||(e.indicator(),e.arrow(),e.autoplay(),e.events()))},m.prototype.reload=function(e){var n=this;clearInterval(n.timer),n.config=i.extend({},n.config,e),n.render()},m.prototype.prevIndex=function(){var e=this,i=e.config,n=i.index-1;return n<0&&(n=e.elemItem.length-1),n},m.prototype.nextIndex=function(){var e=this,i=e.config,n=i.index+1;return n>=e.elemItem.length&&(n=0),n},m.prototype.addIndex=function(e){var i=this,n=i.config;e=e||1,n.index=n.index+e,n.index>=i.elemItem.length&&(n.index=0)},m.prototype.subIndex=function(e){var i=this,n=i.config;e=e||1,n.index=n.index-e,n.index<0&&(n.index=i.elemItem.length-1)},m.prototype.autoplay=function(){var e=this,i=e.config;i.autoplay&&(e.timer=setInterval(function(){e.slide()},i.interval))},m.prototype.arrow=function(){var e=this,n=e.config,t=i(['<button class=\"layui-icon '+u+'\" lay-type=\"sub\">'+(\"updown\"===n.anim?\"&#xe619;\":\"&#xe603;\")+\"</button>\",'<button class=\"layui-icon '+u+'\" lay-type=\"add\">'+(\"updown\"===n.anim?\"&#xe61a;\":\"&#xe602;\")+\"</button>\"].join(\"\"));n.elem.attr(\"lay-arrow\",n.arrow),n.elem.find(\".\"+u)[0]&&n.elem.find(\".\"+u).remove(),n.elem.append(t),t.on(\"click\",function(){var n=i(this),t=n.attr(\"lay-type\");e.slide(t)})},m.prototype.indicator=function(){var e=this,n=e.config,t=e.elemInd=i(['<div class=\"'+c+'\"><ul>',function(){var i=[];return layui.each(e.elemItem,function(e){i.push(\"<li\"+(n.index===e?' class=\"layui-this\"':\"\")+\"></li>\")}),i.join(\"\")}(),\"</ul></div>\"].join(\"\"));n.elem.attr(\"lay-indicator\",n.indicator),n.elem.find(\".\"+c)[0]&&n.elem.find(\".\"+c).remove(),n.elem.append(t),\"updown\"===n.anim&&t.css(\"margin-top\",-(t.height()/2)),t.find(\"li\").on(\"hover\"===n.trigger?\"mouseover\":n.trigger,function(){var t=i(this),a=t.index();a>n.index?e.slide(\"add\",a-n.index):a<n.index&&e.slide(\"sub\",n.index-a)})},m.prototype.slide=function(e,i){var n=this,l=n.elemItem,u=n.config,c=u.index,m=u.elem.attr(\"lay-filter\");n.haveSlide||(\"sub\"===e?(n.subIndex(i),l.eq(u.index).addClass(d),setTimeout(function(){l.eq(c).addClass(r),l.eq(u.index).addClass(r)},50)):(n.addIndex(i),l.eq(u.index).addClass(s),setTimeout(function(){l.eq(c).addClass(o),l.eq(u.index).addClass(o)},50)),setTimeout(function(){l.removeClass(a+\" \"+d+\" \"+s+\" \"+o+\" \"+r),l.eq(u.index).addClass(a),n.haveSlide=!1},300),n.elemInd.find(\"li\").eq(u.index).addClass(a).siblings().removeClass(a),n.haveSlide=!0,layui.event.call(this,t,\"change(\"+m+\")\",{index:u.index,prevIndex:c,item:l.eq(u.index)}))},m.prototype.events=function(){var e=this,i=e.config;i.elem.data(\"haveEvents\")||(i.elem.on(\"mouseenter\",function(){clearInterval(e.timer)}).on(\"mouseleave\",function(){e.autoplay()}),i.elem.data(\"haveEvents\",!0))},n.render=function(e){var i=new m(e);return i},e(t,n)});layui.define(\"jquery\",function(e){\"use strict\";var t=layui.$,i={fixbar:function(e){var i,o,a=\"layui-fixbar\",r=\"layui-fixbar-top\",n=t(document),l=t(\"body\");e=t.extend({showHeight:200},e),e.bar1=e.bar1===!0?\"&#xe606;\":e.bar1,e.bar2=e.bar2===!0?\"&#xe607;\":e.bar2,e.bgcolor=e.bgcolor?\"background-color:\"+e.bgcolor:\"\";var c=[e.bar1,e.bar2,\"&#xe604;\"],g=t(['<ul class=\"'+a+'\">',e.bar1?'<li class=\"layui-icon\" lay-type=\"bar1\" style=\"'+e.bgcolor+'\">'+c[0]+\"</li>\":\"\",e.bar2?'<li class=\"layui-icon\" lay-type=\"bar2\" style=\"'+e.bgcolor+'\">'+c[1]+\"</li>\":\"\",'<li class=\"layui-icon '+r+'\" lay-type=\"top\" style=\"'+e.bgcolor+'\">'+c[2]+\"</li>\",\"</ul>\"].join(\"\")),s=g.find(\".\"+r),u=function(){var t=n.scrollTop();t>=e.showHeight?i||(s.show(),i=1):i&&(s.hide(),i=0)};t(\".\"+a)[0]||(\"object\"==typeof e.css&&g.css(e.css),l.append(g),u(),g.find(\"li\").on(\"click\",function(){var i=t(this),o=i.attr(\"lay-type\");\"top\"===o&&t(\"html,body\").animate({scrollTop:0},200),e.click&&e.click.call(this,o)}),n.on(\"scroll\",function(){clearTimeout(o),o=setTimeout(function(){u()},100)}))},countdown:function(e,t,i){var o=this,a=\"function\"==typeof t,r=new Date(e).getTime(),n=new Date(!t||a?(new Date).getTime():t).getTime(),l=r-n,c=[Math.floor(l/864e5),Math.floor(l/36e5)%24,Math.floor(l/6e4)%60,Math.floor(l/1e3)%60];a&&(i=t);var g=setTimeout(function(){o.countdown(e,n+1e3,i)},1e3);return i&&i(l>0?c:[0,0,0,0],t,g),l<=0&&clearTimeout(g),g},timeAgo:function(e,t){var i=this,o=[[],[]],a=(new Date).getTime()-new Date(e).getTime();return a>6912e5?(a=new Date(e),o[0][0]=i.digit(a.getFullYear(),4),o[0][1]=i.digit(a.getMonth()+1),o[0][2]=i.digit(a.getDate()),t||(o[1][0]=i.digit(a.getHours()),o[1][1]=i.digit(a.getMinutes()),o[1][2]=i.digit(a.getSeconds())),o[0].join(\"-\")+\" \"+o[1].join(\":\")):a>=864e5?(a/1e3/60/60/24|0)+\"天前\":a>=36e5?(a/1e3/60/60|0)+\"小时前\":a>=12e4?(a/1e3/60|0)+\"分钟前\":a<0?\"未来\":\"刚刚\"},digit:function(e,t){var i=\"\";e=String(e),t=t||2;for(var o=e.length;o<t;o++)i+=\"0\";return e<Math.pow(10,t)?i+(0|e):e},toDateString:function(e,t){var i=this,o=new Date(e||new Date),a=[i.digit(o.getFullYear(),4),i.digit(o.getMonth()+1),i.digit(o.getDate())],r=[i.digit(o.getHours()),i.digit(o.getMinutes()),i.digit(o.getSeconds())];return t=t||\"yyyy-MM-dd HH:mm:ss\",t.replace(/yyyy/g,a[0]).replace(/MM/g,a[1]).replace(/dd/g,a[2]).replace(/HH/g,r[0]).replace(/mm/g,r[1]).replace(/ss/g,r[2])}};e(\"util\",i)});layui.define(\"jquery\",function(e){\"use strict\";var l=layui.$,o=function(e){},t='<i class=\"layui-anim layui-anim-rotate layui-anim-loop layui-icon \">&#xe63e;</i>';o.prototype.load=function(e){var o,i,n,r,a=this,c=0;e=e||{};var f=l(e.elem);if(f[0]){var m=l(e.scrollElem||document),u=e.mb||50,s=!(\"isAuto\"in e)||e.isAuto,v=e.end||\"没有更多了\",y=e.scrollElem&&e.scrollElem!==document,d=\"<cite>加载更多</cite>\",h=l('<div class=\"layui-flow-more\"><a href=\"javascript:;\">'+d+\"</a></div>\");f.find(\".layui-flow-more\")[0]||f.append(h);var p=function(e,t){e=l(e),h.before(e),t=0==t||null,t?h.html(v):h.find(\"a\").html(d),i=t,o=null,n&&n()},g=function(){o=!0,h.find(\"a\").html(t),\"function\"==typeof e.done&&e.done(++c,p)};if(g(),h.find(\"a\").on(\"click\",function(){l(this);i||o||g()}),e.isLazyimg)var n=a.lazyimg({elem:e.elem+\" img\",scrollElem:e.scrollElem});return s?(m.on(\"scroll\",function(){var e=l(this),t=e.scrollTop();r&&clearTimeout(r),i||(r=setTimeout(function(){var i=y?e.height():l(window).height(),n=y?e.prop(\"scrollHeight\"):document.documentElement.scrollHeight;n-t-i<=u&&(o||g())},100))}),a):a}},o.prototype.lazyimg=function(e){var o,t=this,i=0;e=e||{};var n=l(e.scrollElem||document),r=e.elem||\"img\",a=e.scrollElem&&e.scrollElem!==document,c=function(e,l){var o=n.scrollTop(),r=o+l,c=a?function(){return e.offset().top-n.offset().top+o}():e.offset().top;if(c>=o&&c<=r&&!e.attr(\"src\")){var m=e.attr(\"lay-src\");layui.img(m,function(){var l=t.lazyimg.elem.eq(i);e.attr(\"src\",m).removeAttr(\"lay-src\"),l[0]&&f(l),i++})}},f=function(e,o){var f=a?(o||n).height():l(window).height(),m=n.scrollTop(),u=m+f;if(t.lazyimg.elem=l(r),e)c(e,f);else for(var s=0;s<t.lazyimg.elem.length;s++){var v=t.lazyimg.elem.eq(s),y=a?function(){return v.offset().top-n.offset().top+m}():v.offset().top;if(c(v,f),i=s,y>u)break}};if(f(),!o){var m;n.on(\"scroll\",function(){var e=l(this);m&&clearTimeout(m),m=setTimeout(function(){f(null,e)},50)}),o=!0}return f},e(\"flow\",new o)});layui.define([\"layer\",\"form\"],function(t){\"use strict\";var e=layui.$,i=layui.layer,a=layui.form,l=(layui.hint(),layui.device()),n=\"layedit\",o=\"layui-show\",r=\"layui-disabled\",c=function(){var t=this;t.index=0,t.config={tool:[\"strong\",\"italic\",\"underline\",\"del\",\"|\",\"left\",\"center\",\"right\",\"|\",\"link\",\"unlink\",\"face\",\"image\"],hideTool:[],height:280}};c.prototype.set=function(t){var i=this;return e.extend(!0,i.config,t),i},c.prototype.on=function(t,e){return layui.onevent(n,t,e)},c.prototype.build=function(t,i){i=i||{};var a=this,n=a.config,r=\"layui-layedit\",c=e(\"#\"+t),u=\"LAY_layedit_\"+ ++a.index,d=c.next(\".\"+r),y=e.extend({},n,i),f=function(){var t=[],e={};return layui.each(y.hideTool,function(t,i){e[i]=!0}),layui.each(y.tool,function(i,a){C[a]&&!e[a]&&t.push(C[a])}),t.join(\"\")}(),m=e(['<div class=\"'+r+'\">','<div class=\"layui-unselect layui-layedit-tool\">'+f+\"</div>\",'<div class=\"layui-layedit-iframe\">','<iframe id=\"'+u+'\" name=\"'+u+'\" textarea=\"'+t+'\" frameborder=\"0\"></iframe>',\"</div>\",\"</div>\"].join(\"\"));return l.ie&&l.ie<8?c.removeClass(\"layui-hide\").addClass(o):(d[0]&&d.remove(),s.call(a,m,c[0],y),c.addClass(\"layui-hide\").after(m),a.index)},c.prototype.getContent=function(t){var e=u(t);if(e[0])return d(e[0].document.body.innerHTML)},c.prototype.getText=function(t){var i=u(t);if(i[0])return e(i[0].document.body).text()},c.prototype.setContent=function(t,i,a){var l=u(t);l[0]&&(a?e(l[0].document.body).append(i):e(l[0].document.body).html(i),layedit.sync(t))},c.prototype.sync=function(t){var i=u(t);if(i[0]){var a=e(\"#\"+i[1].attr(\"textarea\"));a.val(d(i[0].document.body.innerHTML))}},c.prototype.getSelection=function(t){var e=u(t);if(e[0]){var i=m(e[0].document);return document.selection?i.text:i.toString()}};var s=function(t,i,a){var l=this,n=t.find(\"iframe\");n.css({height:a.height}).on(\"load\",function(){var o=n.contents(),r=n.prop(\"contentWindow\"),c=o.find(\"head\"),s=e([\"<style>\",\"*{margin: 0; padding: 0;}\",\"body{padding: 10px; line-height: 20px; overflow-x: hidden; word-wrap: break-word; font: 14px Helvetica Neue,Helvetica,PingFang SC,Microsoft YaHei,Tahoma,Arial,sans-serif; -webkit-box-sizing: border-box !important; -moz-box-sizing: border-box !important; box-sizing: border-box !important;}\",\"a{color:#01AAED; text-decoration:none;}a:hover{color:#c00}\",\"p{margin-bottom: 10px;}\",\"img{display: inline-block; border: none; vertical-align: middle;}\",\"pre{margin: 10px 0; padding: 10px; line-height: 20px; border: 1px solid #ddd; border-left-width: 6px; background-color: #F2F2F2; color: #333; font-family: Courier New; font-size: 12px;}\",\"</style>\"].join(\"\")),u=o.find(\"body\");c.append(s),u.attr(\"contenteditable\",\"true\").css({\"min-height\":a.height}).html(i.value||\"\"),y.apply(l,[r,n,i,a]),g.call(l,r,t,a)})},u=function(t){var i=e(\"#LAY_layedit_\"+t),a=i.prop(\"contentWindow\");return[a,i]},d=function(t){return 8==l.ie&&(t=t.replace(/<.+>/g,function(t){return t.toLowerCase()})),t},y=function(t,a,n,o){var r=t.document,c=e(r.body);c.on(\"keydown\",function(t){var e=t.keyCode;if(13===e){var a=m(r),l=p(a),n=l.parentNode;if(\"pre\"===n.tagName.toLowerCase()){if(t.shiftKey)return;return i.msg(\"请暂时用shift+enter\"),!1}r.execCommand(\"formatBlock\",!1,\"<p>\")}}),e(n).parents(\"form\").on(\"submit\",function(){var t=c.html();8==l.ie&&(t=t.replace(/<.+>/g,function(t){return t.toLowerCase()})),n.value=t}),c.on(\"paste\",function(e){r.execCommand(\"formatBlock\",!1,\"<p>\"),setTimeout(function(){f.call(t,c),n.value=c.html()},100)})},f=function(t){var i=this;i.document;t.find(\"*[style]\").each(function(){var t=this.style.textAlign;this.removeAttribute(\"style\"),e(this).css({\"text-align\":t||\"\"})}),t.find(\"table\").addClass(\"layui-table\"),t.find(\"script,link\").remove()},m=function(t){return t.selection?t.selection.createRange():t.getSelection().getRangeAt(0)},p=function(t){return t.endContainer||t.parentElement().childNodes[0]},v=function(t,i,a){var l=this.document,n=document.createElement(t);for(var o in i)n.setAttribute(o,i[o]);if(n.removeAttribute(\"text\"),l.selection){var r=a.text||i.text;if(\"a\"===t&&!r)return;r&&(n.innerHTML=r),a.pasteHTML(e(n).prop(\"outerHTML\")),a.select()}else{var r=a.toString()||i.text;if(\"a\"===t&&!r)return;r&&(n.innerHTML=r),a.deleteContents(),a.insertNode(n)}},h=function(t,i){var a=this.document,l=\"layedit-tool-active\",n=p(m(a)),o=function(e){return t.find(\".layedit-tool-\"+e)};i&&i[i.hasClass(l)?\"removeClass\":\"addClass\"](l),t.find(\">i\").removeClass(l),o(\"unlink\").addClass(r),e(n).parents().each(function(){var t=this.tagName.toLowerCase(),e=this.style.textAlign;\"b\"!==t&&\"strong\"!==t||o(\"b\").addClass(l),\"i\"!==t&&\"em\"!==t||o(\"i\").addClass(l),\"u\"===t&&o(\"u\").addClass(l),\"strike\"===t&&o(\"d\").addClass(l),\"p\"===t&&(\"center\"===e?o(\"center\").addClass(l):\"right\"===e?o(\"right\").addClass(l):o(\"left\").addClass(l)),\"a\"===t&&(o(\"link\").addClass(l),o(\"unlink\").removeClass(r))})},g=function(t,a,l){var n=t.document,o=e(n.body),c={link:function(i){var a=p(i),l=e(a).parent();b.call(o,{href:l.attr(\"href\"),target:l.attr(\"target\")},function(e){var a=l[0];\"A\"===a.tagName?a.href=e.url:v.call(t,\"a\",{target:e.target,href:e.url,text:e.url},i)})},unlink:function(t){n.execCommand(\"unlink\")},face:function(e){x.call(this,function(i){v.call(t,\"img\",{src:i.src,alt:i.alt},e)})},image:function(a){var n=this;layui.use(\"upload\",function(o){var r=l.uploadImage||{};o.render({url:r.url,method:r.type,elem:e(n).find(\"input\")[0],done:function(e){0==e.code?(e.data=e.data||{},v.call(t,\"img\",{src:e.data.src,alt:e.data.title},a)):i.msg(e.msg||\"上传失败\")}})})},code:function(e){k.call(o,function(i){v.call(t,\"pre\",{text:i.code,\"lay-lang\":i.lang},e)})},help:function(){i.open({type:2,title:\"帮助\",area:[\"600px\",\"380px\"],shadeClose:!0,shade:.1,skin:\"layui-layer-msg\",content:[\"http://www.layui.com/about/layedit/help.html\",\"no\"]})}},s=a.find(\".layui-layedit-tool\"),u=function(){var i=e(this),a=i.attr(\"layedit-event\"),l=i.attr(\"lay-command\");if(!i.hasClass(r)){o.focus();var u=m(n);u.commonAncestorContainer;l?(n.execCommand(l),/justifyLeft|justifyCenter|justifyRight/.test(l)&&n.execCommand(\"formatBlock\",!1,\"<p>\"),setTimeout(function(){o.focus()},10)):c[a]&&c[a].call(this,u),h.call(t,s,i)}},d=/image/;s.find(\">i\").on(\"mousedown\",function(){var t=e(this),i=t.attr(\"layedit-event\");d.test(i)||u.call(this)}).on(\"click\",function(){var t=e(this),i=t.attr(\"layedit-event\");d.test(i)&&u.call(this)}),o.on(\"click\",function(){h.call(t,s),i.close(x.index)})},b=function(t,e){var l=this,n=i.open({type:1,id:\"LAY_layedit_link\",area:\"350px\",shade:.05,shadeClose:!0,moveType:1,title:\"超链接\",skin:\"layui-layer-msg\",content:['<ul class=\"layui-form\" style=\"margin: 15px;\">','<li class=\"layui-form-item\">','<label class=\"layui-form-label\" style=\"width: 60px;\">URL</label>','<div class=\"layui-input-block\" style=\"margin-left: 90px\">','<input name=\"url\" lay-verify=\"url\" value=\"'+(t.href||\"\")+'\" autofocus=\"true\" autocomplete=\"off\" class=\"layui-input\">',\"</div>\",\"</li>\",'<li class=\"layui-form-item\">','<label class=\"layui-form-label\" style=\"width: 60px;\">打开方式</label>','<div class=\"layui-input-block\" style=\"margin-left: 90px\">','<input type=\"radio\" name=\"target\" value=\"_self\" class=\"layui-input\" title=\"当前窗口\"'+(\"_self\"!==t.target&&t.target?\"\":\"checked\")+\">\",'<input type=\"radio\" name=\"target\" value=\"_blank\" class=\"layui-input\" title=\"新窗口\" '+(\"_blank\"===t.target?\"checked\":\"\")+\">\",\"</div>\",\"</li>\",'<li class=\"layui-form-item\" style=\"text-align: center;\">','<button type=\"button\" lay-submit lay-filter=\"layedit-link-yes\" class=\"layui-btn\"> 确定 </button>','<button style=\"margin-left: 20px;\" type=\"button\" class=\"layui-btn layui-btn-primary\"> 取消 </button>',\"</li>\",\"</ul>\"].join(\"\"),success:function(t,n){var o=\"submit(layedit-link-yes)\";a.render(\"radio\"),t.find(\".layui-btn-primary\").on(\"click\",function(){i.close(n),l.focus()}),a.on(o,function(t){i.close(b.index),e&&e(t.field)})}});b.index=n},x=function(t){var a=function(){var t=[\"[微笑]\",\"[嘻嘻]\",\"[哈哈]\",\"[可爱]\",\"[可怜]\",\"[挖鼻]\",\"[吃惊]\",\"[害羞]\",\"[挤眼]\",\"[闭嘴]\",\"[鄙视]\",\"[爱你]\",\"[泪]\",\"[偷笑]\",\"[亲亲]\",\"[生病]\",\"[太开心]\",\"[白眼]\",\"[右哼哼]\",\"[左哼哼]\",\"[嘘]\",\"[衰]\",\"[委屈]\",\"[吐]\",\"[哈欠]\",\"[抱抱]\",\"[怒]\",\"[疑问]\",\"[馋嘴]\",\"[拜拜]\",\"[思考]\",\"[汗]\",\"[困]\",\"[睡]\",\"[钱]\",\"[失望]\",\"[酷]\",\"[色]\",\"[哼]\",\"[鼓掌]\",\"[晕]\",\"[悲伤]\",\"[抓狂]\",\"[黑线]\",\"[阴险]\",\"[怒骂]\",\"[互粉]\",\"[心]\",\"[伤心]\",\"[猪头]\",\"[熊猫]\",\"[兔子]\",\"[ok]\",\"[耶]\",\"[good]\",\"[NO]\",\"[赞]\",\"[来]\",\"[弱]\",\"[草泥马]\",\"[神马]\",\"[囧]\",\"[浮云]\",\"[给力]\",\"[围观]\",\"[威武]\",\"[奥特曼]\",\"[礼物]\",\"[钟]\",\"[话筒]\",\"[蜡烛]\",\"[蛋糕]\"],e={};return layui.each(t,function(t,i){e[i]=layui.cache.dir+\"images/face/\"+t+\".gif\"}),e}();return x.hide=x.hide||function(t){\"face\"!==e(t.target).attr(\"layedit-event\")&&i.close(x.index)},x.index=i.tips(function(){var t=[];return layui.each(a,function(e,i){t.push('<li title=\"'+e+'\"><img src=\"'+i+'\" alt=\"'+e+'\"></li>')}),'<ul class=\"layui-clear\">'+t.join(\"\")+\"</ul>\"}(),this,{tips:1,time:0,skin:\"layui-box layui-util-face\",maxWidth:500,success:function(l,n){l.css({marginTop:-4,marginLeft:-10}).find(\".layui-clear>li\").on(\"click\",function(){t&&t({src:a[this.title],alt:this.title}),i.close(n)}),e(document).off(\"click\",x.hide).on(\"click\",x.hide)}})},k=function(t){var e=this,l=i.open({type:1,id:\"LAY_layedit_code\",area:\"550px\",shade:.05,shadeClose:!0,moveType:1,title:\"插入代码\",skin:\"layui-layer-msg\",content:['<ul class=\"layui-form layui-form-pane\" style=\"margin: 15px;\">','<li class=\"layui-form-item\">','<label class=\"layui-form-label\">请选择语言</label>','<div class=\"layui-input-block\">','<select name=\"lang\">','<option value=\"JavaScript\">JavaScript</option>','<option value=\"HTML\">HTML</option>','<option value=\"CSS\">CSS</option>','<option value=\"Java\">Java</option>','<option value=\"PHP\">PHP</option>','<option value=\"C#\">C#</option>','<option value=\"Python\">Python</option>','<option value=\"Ruby\">Ruby</option>','<option value=\"Go\">Go</option>',\"</select>\",\"</div>\",\"</li>\",'<li class=\"layui-form-item layui-form-text\">','<label class=\"layui-form-label\">代码</label>','<div class=\"layui-input-block\">','<textarea name=\"code\" lay-verify=\"required\" autofocus=\"true\" class=\"layui-textarea\" style=\"height: 200px;\"></textarea>',\"</div>\",\"</li>\",'<li class=\"layui-form-item\" style=\"text-align: center;\">','<button type=\"button\" lay-submit lay-filter=\"layedit-code-yes\" class=\"layui-btn\"> 确定 </button>','<button style=\"margin-left: 20px;\" type=\"button\" class=\"layui-btn layui-btn-primary\"> 取消 </button>',\"</li>\",\"</ul>\"].join(\"\"),success:function(l,n){var o=\"submit(layedit-code-yes)\";a.render(\"select\"),l.find(\".layui-btn-primary\").on(\"click\",function(){i.close(n),e.focus()}),a.on(o,function(e){i.close(k.index),t&&t(e.field)})}});k.index=l},C={html:'<i class=\"layui-icon layedit-tool-html\" title=\"HTML源代码\" lay-command=\"html\" layedit-event=\"html\"\">&#xe64b;</i><span class=\"layedit-tool-mid\"></span>',strong:'<i class=\"layui-icon layedit-tool-b\" title=\"加粗\" lay-command=\"Bold\" layedit-event=\"b\"\">&#xe62b;</i>',italic:'<i class=\"layui-icon layedit-tool-i\" title=\"斜体\" lay-command=\"italic\" layedit-event=\"i\"\">&#xe644;</i>',underline:'<i class=\"layui-icon layedit-tool-u\" title=\"下划线\" lay-command=\"underline\" layedit-event=\"u\"\">&#xe646;</i>',del:'<i class=\"layui-icon layedit-tool-d\" title=\"删除线\" lay-command=\"strikeThrough\" layedit-event=\"d\"\">&#xe64f;</i>',\"|\":'<span class=\"layedit-tool-mid\"></span>',left:'<i class=\"layui-icon layedit-tool-left\" title=\"左对齐\" lay-command=\"justifyLeft\" layedit-event=\"left\"\">&#xe649;</i>',center:'<i class=\"layui-icon layedit-tool-center\" title=\"居中对齐\" lay-command=\"justifyCenter\" layedit-event=\"center\"\">&#xe647;</i>',right:'<i class=\"layui-icon layedit-tool-right\" title=\"右对齐\" lay-command=\"justifyRight\" layedit-event=\"right\"\">&#xe648;</i>',link:'<i class=\"layui-icon layedit-tool-link\" title=\"插入链接\" layedit-event=\"link\"\">&#xe64c;</i>',unlink:'<i class=\"layui-icon layedit-tool-unlink layui-disabled\" title=\"清除链接\" lay-command=\"unlink\" layedit-event=\"unlink\"\">&#xe64d;</i>',face:'<i class=\"layui-icon layedit-tool-face\" title=\"表情\" layedit-event=\"face\"\">&#xe650;</i>',image:'<i class=\"layui-icon layedit-tool-image\" title=\"图片\" layedit-event=\"image\">&#xe64a;<input type=\"file\" name=\"file\"></i>',code:'<i class=\"layui-icon layedit-tool-code\" title=\"插入代码\" layedit-event=\"code\">&#xe64e;</i>',help:'<i class=\"layui-icon layedit-tool-help\" title=\"帮助\" layedit-event=\"help\">&#xe607;</i>'},w=new c;t(n,w)});layui.define(\"jquery\",function(e){\"use strict\";var a=layui.$,l=\"http://www.layui.com/doc/modules/code.html\";e(\"code\",function(e){var t=[];e=e||{},e.elem=a(e.elem||\".layui-code\"),e.about=!(\"about\"in e)||e.about,e.elem.each(function(){t.push(this)}),layui.each(t.reverse(),function(t,i){var c=a(i),o=c.html();(c.attr(\"lay-encode\")||e.encode)&&(o=o.replace(/&(?!#?[a-zA-Z0-9]+;)/g,\"&amp;\").replace(/</g,\"&lt;\").replace(/>/g,\"&gt;\").replace(/'/g,\"&#39;\").replace(/\"/g,\"&quot;\")),c.html('<ol class=\"layui-code-ol\"><li>'+o.replace(/[\\r\\t\\n]+/g,\"</li><li>\")+\"</li></ol>\"),c.find(\">.layui-code-h3\")[0]||c.prepend('<h3 class=\"layui-code-h3\">'+(c.attr(\"lay-title\")||e.title||\"code\")+(e.about?'<a href=\"'+l+'\" target=\"_blank\">layui.code</a>':\"\")+\"</h3>\");var d=c.find(\">.layui-code-ol\");c.addClass(\"layui-box layui-code-view\"),(c.attr(\"lay-skin\")||e.skin)&&c.addClass(\"layui-code-\"+(c.attr(\"lay-skin\")||e.skin)),(d.find(\"li\").length/100|0)>0&&d.css(\"margin-left\",(d.find(\"li\").length/100|0)+\"px\"),(c.attr(\"lay-height\")||e.height)&&d.css(\"max-height\",c.attr(\"lay-height\")||e.height)})})}).addcss(\"modules/code.css\",\"skincodecss\");"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/layui/layui.js",
    "content": "/** layui-v2.2.5 MIT License By https://www.layui.com */\n ;!function(e){\"use strict\";var t=document,n={modules:{},status:{},timeout:10,event:{}},o=function(){this.v=\"2.2.5\"},r=function(){var e=t.currentScript?t.currentScript.src:function(){for(var e,n=t.scripts,o=n.length-1,r=o;r>0;r--)if(\"interactive\"===n[r].readyState){e=n[r].src;break}return e||n[o].src}();return e.substring(0,e.lastIndexOf(\"/\")+1)}(),a=function(t){e.console&&console.error&&console.error(\"Layui hint: \"+t)},i=\"undefined\"!=typeof opera&&\"[object Opera]\"===opera.toString(),u={layer:\"modules/layer\",laydate:\"modules/laydate\",laypage:\"modules/laypage\",laytpl:\"modules/laytpl\",layim:\"modules/layim\",layedit:\"modules/layedit\",form:\"modules/form\",upload:\"modules/upload\",tree:\"modules/tree\",table:\"modules/table\",element:\"modules/element\",util:\"modules/util\",flow:\"modules/flow\",carousel:\"modules/carousel\",code:\"modules/code\",jquery:\"modules/jquery\",mobile:\"modules/mobile\",\"layui.all\":\"../layui.all\"};o.prototype.cache=n,o.prototype.define=function(e,t){var o=this,r=\"function\"==typeof e,a=function(){var e=function(e,t){layui[e]=t,n.status[e]=!0};return\"function\"==typeof t&&t(function(o,r){e(o,r),n.callback[o]=function(){t(e)}}),this};return r&&(t=e,e=[]),layui[\"layui.all\"]||!layui[\"layui.all\"]&&layui[\"layui.mobile\"]?a.call(o):(o.use(e,a),o)},o.prototype.use=function(e,o,l){function s(e,t){var o=\"PLaySTATION 3\"===navigator.platform?/^complete$/:/^(complete|loaded)$/;(\"load\"===e.type||o.test((e.currentTarget||e.srcElement).readyState))&&(n.modules[f]=t,d.removeChild(v),function r(){return++m>1e3*n.timeout/4?a(f+\" is not a valid module\"):void(n.status[f]?c():setTimeout(r,4))}())}function c(){l.push(layui[f]),e.length>1?y.use(e.slice(1),o,l):\"function\"==typeof o&&o.apply(layui,l)}var y=this,p=n.dir=n.dir?n.dir:r,d=t.getElementsByTagName(\"head\")[0];e=\"string\"==typeof e?[e]:e,window.jQuery&&jQuery.fn.on&&(y.each(e,function(t,n){\"jquery\"===n&&e.splice(t,1)}),layui.jquery=layui.$=jQuery);var f=e[0],m=0;if(l=l||[],n.host=n.host||(p.match(/\\/\\/([\\s\\S]+?)\\//)||[\"//\"+location.host+\"/\"])[0],0===e.length||layui[\"layui.all\"]&&u[f]||!layui[\"layui.all\"]&&layui[\"layui.mobile\"]&&u[f])return c(),y;if(n.modules[f])!function g(){return++m>1e3*n.timeout/4?a(f+\" is not a valid module\"):void(\"string\"==typeof n.modules[f]&&n.status[f]?c():setTimeout(g,4))}();else{var v=t.createElement(\"script\"),h=(u[f]?p+\"lay/\":/^\\{\\/\\}/.test(y.modules[f])?\"\":n.base||\"\")+(y.modules[f]||f)+\".js\";h=h.replace(/^\\{\\/\\}/,\"\"),v.async=!0,v.charset=\"utf-8\",v.src=h+function(){var e=n.version===!0?n.v||(new Date).getTime():n.version||\"\";return e?\"?v=\"+e:\"\"}(),d.appendChild(v),!v.attachEvent||v.attachEvent.toString&&v.attachEvent.toString().indexOf(\"[native code\")<0||i?v.addEventListener(\"load\",function(e){s(e,h)},!1):v.attachEvent(\"onreadystatechange\",function(e){s(e,h)}),n.modules[f]=h}return y},o.prototype.getStyle=function(t,n){var o=t.currentStyle?t.currentStyle:e.getComputedStyle(t,null);return o[o.getPropertyValue?\"getPropertyValue\":\"getAttribute\"](n)},o.prototype.link=function(e,o,r){var i=this,u=t.createElement(\"link\"),l=t.getElementsByTagName(\"head\")[0];\"string\"==typeof o&&(r=o);var s=(r||e).replace(/\\.|\\//g,\"\"),c=u.id=\"layuicss-\"+s,y=0;return u.rel=\"stylesheet\",u.href=e+(n.debug?\"?v=\"+(new Date).getTime():\"\"),u.media=\"all\",t.getElementById(c)||l.appendChild(u),\"function\"!=typeof o?i:(function p(){return++y>1e3*n.timeout/100?a(e+\" timeout\"):void(1989===parseInt(i.getStyle(t.getElementById(c),\"width\"))?function(){o()}():setTimeout(p,100))}(),i)},n.callback={},o.prototype.factory=function(e){if(layui[e])return\"function\"==typeof n.callback[e]?n.callback[e]:null},o.prototype.addcss=function(e,t,o){return layui.link(n.dir+\"css/\"+e,t,o)},o.prototype.img=function(e,t,n){var o=new Image;return o.src=e,o.complete?t(o):(o.onload=function(){o.onload=null,t(o)},void(o.onerror=function(e){o.onerror=null,n(e)}))},o.prototype.config=function(e){e=e||{};for(var t in e)n[t]=e[t];return this},o.prototype.modules=function(){var e={};for(var t in u)e[t]=u[t];return e}(),o.prototype.extend=function(e){var t=this;e=e||{};for(var n in e)t[n]||t.modules[n]?a(\"模块名 \"+n+\" 已被占用\"):t.modules[n]=e[n];return t},o.prototype.router=function(e){var t=this,e=e||location.hash,n={path:[],search:{},hash:(e.match(/[^#](#.*$)/)||[])[1]||\"\"};return/^#\\//.test(e)?(n.href=e=e.replace(/^#\\//,\"\"),e=e.replace(/([^#])(#.*$)/,\"$1\").split(\"/\")||[],t.each(e,function(e,t){/^\\w+=/.test(t)?function(){t=t.split(\"=\"),n.search[t[0]]=t[1]}():n.path.push(t)}),n):n},o.prototype.data=function(t,n,o){if(t=t||\"layui\",o=o||localStorage,e.JSON&&e.JSON.parse){if(null===n)return delete o[t];n=\"object\"==typeof n?n:{key:n};try{var r=JSON.parse(o[t])}catch(a){var r={}}return\"value\"in n&&(r[n.key]=n.value),n.remove&&delete r[n.key],o[t]=JSON.stringify(r),n.key?r[n.key]:r}},o.prototype.sessionData=function(e,t){return this.data(e,t,sessionStorage)},o.prototype.device=function(t){var n=navigator.userAgent.toLowerCase(),o=function(e){var t=new RegExp(e+\"/([^\\\\s\\\\_\\\\-]+)\");return e=(n.match(t)||[])[1],e||!1},r={os:function(){return/windows/.test(n)?\"windows\":/linux/.test(n)?\"linux\":/iphone|ipod|ipad|ios/.test(n)?\"ios\":/mac/.test(n)?\"mac\":void 0}(),ie:function(){return!!(e.ActiveXObject||\"ActiveXObject\"in e)&&((n.match(/msie\\s(\\d+)/)||[])[1]||\"11\")}(),weixin:o(\"micromessenger\")};return t&&!r[t]&&(r[t]=o(t)),r.android=/android/.test(n),r.ios=\"ios\"===r.os,r},o.prototype.hint=function(){return{error:a}},o.prototype.each=function(e,t){var n,o=this;if(\"function\"!=typeof t)return o;if(e=e||[],e.constructor===Object){for(n in e)if(t.call(e[n],n,e[n]))break}else for(n=0;n<e.length&&!t.call(e[n],n,e[n]);n++);return o},o.prototype.sort=function(e,t,n){var o=JSON.parse(JSON.stringify(e||[]));return t?(o.sort(function(e,n){var o=/^-?\\d+$/,r=e[t],a=n[t];return o.test(r)&&(r=parseFloat(r)),o.test(a)&&(a=parseFloat(a)),r&&!a?1:!r&&a?-1:r>a?1:r<a?-1:0}),n&&o.reverse(),o):o},o.prototype.stope=function(t){t=t||e.event;try{t.stopPropagation()}catch(n){t.cancelBubble=!0}},o.prototype.onevent=function(e,t,n){return\"string\"!=typeof e||\"function\"!=typeof n?this:o.event(e,t,null,n)},o.prototype.event=o.event=function(e,t,o,r){var a=this,i=null,u=t.match(/\\((.*)\\)$/)||[],l=(e+\".\"+t).replace(u[0],\"\"),s=u[1]||\"\",c=function(e,t){var n=t&&t.call(a,o);n===!1&&null===i&&(i=!1)};return r?(n.event[l]=n.event[l]||{},n.event[l][s]=[r],this):(layui.each(n.event[l],function(e,t){return\"{*}\"===s?void layui.each(t,c):(\"\"===e&&layui.each(t,c),void(e===s&&layui.each(t,c)))}),i)},e.layui=new o}(window);"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/layui/layuiextend/treeSelect/css/treeSelect.css",
    "content": "/**treeselect*/\n.layui-form-select .layui-tree {\n    display: none;\n    position: absolute;\n    left: 0;\n    top: 42px;\n    padding: 5px 0;\n    z-index: 999;\n    min-width: 100%;\n    border: 1px solid #d2d2d2;\n    max-height: 300px;\n    overflow-y: auto;\n    background-color: #fff;\n    border-radius: 2px;\n    box-shadow: 0 2px 4px rgba(0,0,0,.12);\n    box-sizing: border-box;\n}\n.layui-form-selected .layui-tree {\n    display: block;\n}"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/layui/layuiextend/treeSelect/treeselect.js",
    "content": "//treeSelect组件\nlayui.define('tree', function (exports) {\n    \"use strict\";\n\n    var _MOD = 'treeselect',\n        treeData = {}, //全局树形数据缓存\n        $ = layui.jquery,\n        hint = layui.hint(),\n        DISABLED = 'layui-disabled',\n        win = $(window),\n        TreeSelect = function() {\n            this.v = '1.0.0';\n        };\n    /**\n    * 初始化下拉树选择框\n    */\n    TreeSelect.prototype.render = function (options) {\n        var that = this,\n            othis =options? $(options.elem):null,\n            tips = '请选择',\n            CLASS = 'layui-form-select',\n            TITLE = 'layui-select-title',\n            NONE = 'layui-select-none',\n            initValue = '',\n            thatInput,\n            isString = function(obj) {\n                return Object.prototype.toString.call(obj) === \"[object String]\";\n            },\n            settext = function (data, val, input) {\n                $.each(data,\n                    function (_, o) {\n                        if (o.id === val) {\n                            input.val(o.name);\n                            return false;\n                        }\n                        if (o.children)\n                            settext.call(this, o.children, val, input);\n                    });\n            },\n            hide = function(e, clear) {\n                if (!$(e.target).parent().hasClass(TITLE) || clear) {\n                    $('.' + CLASS).removeClass(CLASS + 'ed ' + CLASS + 'up');\n                    thatInput && initValue && thatInput.val(initValue);\n                }\n                thatInput = null;\n            },\n            events = function(reElem,treeid, disabled) {\n                var title = reElem.find('.' + TITLE),\n                    input = title.find('input'),\n                    tree = reElem.find('.layui-tree'),\n                    o = treeData,\n                    defaultVal = othis.val();\n\n                //如果控件有默认值，设置默认值\n                if (defaultVal)\n                    settext.call(this, o.data, defaultVal, input);\n\n                if (disabled) return;\n\n                //展开下拉\n                var showDown = function () {\n                        \n                    var top = reElem.offset().top + reElem.outerHeight() + 5 - win.scrollTop(),\n                        downHeight = win.height() - top - 13,\n                        dlHeight = tree.outerHeight();\n                        if (downHeight < 300)\n                            tree.css(\"max-height\", downHeight + \"px\");\n\n                        reElem.addClass(CLASS + 'ed');\n\n                        //上下定位识别\n                        if (top + dlHeight > win.height() && top >= dlHeight) {\n                            reElem.addClass(CLASS + 'up');\n                        }\n                    },\n                    hideDown = function() {\n                        reElem.removeClass(CLASS + 'ed ' + CLASS + 'up');\n                        input.blur();\n                    };\n\n                //点击标题区域\n                title.on('click',\n                    function(e) {\n                        reElem.hasClass(CLASS + 'ed')\n                            ? (\n                                hideDown()\n                            )\n                            : (\n                                hide(e, true),\n                                showDown()\n                            );\n                        tree.find('.' + NONE).remove();\n                    });\n\n                //点击箭头获取焦点\n                title.find('.layui-edge').on('click',\n                    function() {\n                        input.focus();\n                    });\n\n                //键盘事件\n                input.on('keyup',\n                        function(e) {\n                            var keyCode = e.keyCode;\n                            //Tab键\n                            if (keyCode === 9) {\n                                showDown();\n                            }\n                        })\n                    .on('keydown',\n                        function(e) {\n                            var keyCode = e.keyCode;\n                            //Tab键\n                            if (keyCode === 9) {\n                                hideDown();\n                            } else if (keyCode === 13) { //回车键\n                                e.preventDefault();\n                            }\n                        });\n                //渲染tree\n                layui.tree({\n                    elem: \"#\" + treeid,\n                    click: function(obj) {\n                        othis.val(obj.id).removeClass('layui-form-danger');\n                        input.val(obj.name);\n                        tree.find(\".youyao-this\").removeClass(\"youyao-this\");\n                        hideDown(true);\n                        if (o.selectcall)\n                            o.selectcall(obj);\n                        return false;\n                    },\n                    nodes: o.data\n                });\n                //点击树箭头不隐藏\n                tree.find(\".layui-tree-spread\").on('click',\n                    function() {\n                        return false;\n                    });\n                //关闭下拉\n                $(document).off('click', hide).on('click', hide);\n            },\n            init = function(treeid) {\n                var hasRender = othis.next('.' + CLASS),\n                    disabled = othis[0].disabled,\n                    value = othis.value,\n                    placeholder = othis.attr(\"placeholder\") ? othis.attr(\"placeholder\") : tips;\n                if (typeof othis.attr('lay-ignore') === 'string') return othis.show();\n                //隐藏原控件\n                othis.hide();\n                othis.addClass(\"layui-input-treeselect\");\n                othis.attr(\"data-treeid\", treeid);\n                //替代元素\n                var reElem = $([\n                    '<div class=\"layui-unselect ' + CLASS + (disabled ? ' layui-select-disabled' : '') + '\">',\n                    '<div class=\"' +\n                    TITLE +\n                    '\"><input type=\"text\" placeholder=\"' +\n                    placeholder +\n                    '\" id=\"' +\n                    treeid +\n                    \"_text\" +\n                    '\" value=\"' +\n                    (value ? selected.html() : '') +\n                    '\" readonly class=\"layui-input layui-unselect' +\n                    (disabled ? (' ' + DISABLED) : '') +\n                    '\">', '<i class=\"layui-edge\"></i></div>',\n                    '<ul id=\"' + treeid + '\" class=\"layui-anim layui-anim-upbit layui-tree\"></ul>', '</div>'\n                ].join(''));\n                hasRender[0] && hasRender.remove(); //如果已经渲染，则Rerender\n                othis.after(reElem);\n                events.call(this, reElem, treeid, disabled);\n            },\n            reset = function(filter) {\n                var trees = filter ? $('*[lay-filter=\"' + filter + '\"]') : $(\".layui-input-treeselect\");\n                layui.each(trees,\n                    function (_, one) {\n                        othis = $(one);\n                        var treeid = othis.attr(\"data-treeid\");\n                        init.call(this, treeid);\n                    });\n            };\n        if (!options)\n            return reset.call(this,null);\n        if (options.filter)\n            return reset.call(this,options.filter);\n        if (!othis[0])\n            return hint.error('layui.treeSelect 没有找到' + options.elem + '元素');\n        if (!options.data)\n            return hint.error(\n                'layui.treeSelect 缺少参数 data ,data 可直接指定treedata，也可以是treedata数据url，treedata参见layui tree模块');\n        var treeid = \"selecttree_\" + options.elem.replace(\"#\", \"\");\n        if (!isString.call(this, options.data)) {\n            //缓存tree data\n            treeData = options;\n            init.call(this, treeid);\n        } else {\n            $.ajax({\n                url: options.data,\n                dataType: \"json\",\n                type: !options.method ? \"POST\" : options.method,\n                success: function(d) {\n                    options.data = d;\n                    treeData = options;\n                    init.call(this, treeid);\n                }\n            });\n        }\n    };\n    var treeSelect = new TreeSelect();\n    //暴露接口\n    exports(_MOD, treeSelect);\n\tlayui.link(layui.cache.base + 'css/treeSelect.css', null, 'treeSelectcss');\n});\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/layui/layuiextend/treegrid/css/grid.css",
    "content": "﻿.text-left {\n    text-align:left;\n}\n.text-center {\n    text-align:center;\n}\n.text-right {\n    text-align:right;\n}\n\n.layui-table th {\n    /*text-align:inherit;*/\n}\ntr.selected td {\n    background-color:#f2f2f2;\n}\ntr.focus td {\n    background-color:#eee;\n}\n\n.layui-table.table-edit td {\n    padding:2px;\n}\n\n.grid {\n    position: absolute;\n    top: 5px;\n    left: 5px;\n    right: 5px;\n    bottom: 5px;\n    border: solid 1px #e2e2e2;\n}\n.grid-content {\n    position:relative;\n    height:100%;\n}\n    .grid-content table {\n        margin: 0;\n        width: auto;\n        min-width: 100%;\n    }\n.grid-content table td,\n.grid-content table th {\n    white-space:nowrap;\n}\n    .grid-content td.edit,.grid-content th.edit {\n        background-color:floralwhite;\n    }\n    .grid-content .edit input[type=\"text\"],\n    .grid-content .edit input[type=\"number\"],\n    .grid-content .edit select,\n    .grid-content .edit textarea {\n        width:100%;\n        height:100%;\n        border:none;\n        background-color:floralwhite;\n        outline: 0;\n        -webkit-transition: border-color .3s cubic-bezier(.65,.05,.35,.5);\n        transition: border-color .3s cubic-bezier(.65,.05,.35,.5);\n        -webkit-box-sizing: border-box !important;\n        -moz-box-sizing: border-box !important;\n        box-sizing: border-box !important;\n    }\n    \n.grid-content td.grid-danger,\n.grid-content th.grid-danger,\n.grid-content td.grid-danger *,\n.grid-content th.grid-danger * {\n    background-color:#f2dede !important;\n    color:red;\n}\n.grid-head {\n    overflow:hidden;\n    background-color:#f2f2f2;\n}\n    .grid-head table {\n        table-layout:fixed;\n        background-color:#f2f2f2;\n    }\n    .grid-head table thead,.grid-body table thead {\n        background-color:#f2f2f2;\n        text-align:center;\n    }\n    .grid-head thead {\n        float:left !important;\n    }\n.grid-body {\n    overflow:hidden;\n}\n.grid .grid-body {\n    position:absolute;\n    top:40px;\n    left:0;\n    right:0;\n    overflow:auto;\n}\n.grid-body thead th,\n.grid-body thead td {\n    border-top: none;\n}\n    .grid-body thead th *,\n    .grid-body thead td * {\n    }\n.grid-title {\n    border:solid 1px #e2e2e2;\n    border-bottom:none;\n    line-height:20px;\n    padding:5px 10px;\n}\n.grid .grid-page {\n    position:absolute;\n    bottom:0;\n    left:0;\n    right:0;\n    background-color:#eee;\n}\n    .grid-page > div {\n        float:right;\n    }\n.grid .layui-laypage a, .grid .layui-laypage span {\n    background-color: #eee;\n}\n\n.grid-page .grid-tool {\n    float: left;\n    line-height: 40px;\n    margin-left: 5px;\n}\n\n\n.layui-laypage {\n    margin:7px 0 2px 0;\n}\n\n.loading_bg {\n    position:absolute;\n    top:0;\n    right:0;\n    bottom:0;\n    left:0;    \n    background-color:#fff;\n    opacity: 0.3;\n    filter: alpha(opacity=30);\n}\n.loading {\n    position:absolute;\n    top:50%;\n    left:0;\n    right:0;\n    margin-top:-20px;\n    text-align:center;\n}\n    .loading .layui-icon {\n        display:inline-block;\n        font-size:40px; \n        font-weight:400;\n    }\n\n\n.grid-order {\n    display:inline-block;\n    width:10px;\n    height:20px;\n    margin-left:5px;\n    vertical-align:middle\n}\n    .grid-order:before {\n        display:block;\n        content:'';\n        width:0;\n        height:0;\n        border-style:dashed dashed solid;\n        border-width:4px;\n        border-color:transparent transparent #aaa;\n    }\n    .grid-order:after {\n        display:block;\n        content:'';\n        width:0;\n        height:0;\n        margin-top:3px;\n        border-style:solid dashed dashed;\n        border-width:4px;\n        border-color:#aaa transparent transparent;\n    }\n    .grid-order.grid-order-asc:before {\n        border-color:transparent transparent #222;\n    }\n    .grid-order.grid-order-desc:after {\n        border-color:#222 transparent transparent;\n    }\n\n/*treegrid*/\n.treegrid-indent {width:16px; height: 16px; display: block;float:left; }\n.treegrid-expander {width:16px; height: 16px; display: block;float:left; cursor: pointer;}\nspan.treegrid-expander { background-repeat:no-repeat;background-size:100%;}\n.treegrid-expanded .treegrid-expander{background-image: url(../img/collapse.png); }\n.treegrid-collapse .treegrid-expander{background-image: url(../img/expand.png);}\n.treegrid-loading .treegrid-expander{background-image:url(../img/loading.gif);}\n.treegrid-wrong .treegrid-expander {background-image:url('../img/wrong.png');}\ntable.tree tbody tr td:nth-child(1),table.tree tbody tr th:nth-child(1) {text-align:left !important;}"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/layui/layuiextend/treegrid/grid.js",
    "content": "﻿layui.define(['form', 'laypage'], function (exports) {\n    var form = layui.form,\n        Grid = {\n            config: {\n                render: function (view, data) { return '未配置渲染函数'; }, //渲染函数\n                token: ''\n            },\n            createNew: function (option) {\n                var GRIDORDER = [], RESIZE = { left: 0, top: 0 }, CONFIG = this.config;\n\n                //样式\n                var CSS = {\n                    danger:'grid-danger'\n                }\n\n                var grid = {\n                    elem: typeof (option.elem) === 'string' ? $('#' + option.elem) : option.elem, //GridID 或 Jquery对象\n                    view: option.view,  //模板名称\n                    //originData: option.data,\n                    data: option.data,  //模板数据（json）\n                    pageData: null,  //页面数据，分页后当前页数据\n                    url: option.url,    //获取数据的url(返回Json，优先使用data数据)\n                    page: option.page || 1, //页码\n                    pageSize: option.pageSize, //每页显示条数\n                    pageGroup: option.pageGroup == undefined ? 5 : option.pageGroup,\n                    search: option.search, //搜索按钮(submit)的lay-filter\n                    searchData: option.searchData || [],\n                    html: '',   //渲染后的html\n                    flag: true,  //获取数据是否成功\n                    message: '', //错误消息\n                    total: 0,  //数据总条数\n                    record: option.record || false,  //是否显示总记录数\n                    freeze: option.freeze,\n                    singleSelect: option.singleSelect || false, //是否单选\n                    success: option.success,  //渲染结束后执行\n                    rowClick: option.rowClick,\n                    rowid: option.rowid,\n                    dataSuccess: option.dataSuccess  //获取数据成功后触发的事件\n                };\n                grid.build = function () {\n                    fnData(fnSuccess);\n                }\n\n                function fnFreeze() {\n                }\n\n                //获取数据\n                function fnData(fn) {\n                    grid.loading();\n                    if (grid.data) {\n                        var DATA = $.extend(true, {}, grid.data);\n\n                        //排序\n                        if (GRIDORDER.length > 0) {\n                            DATA.rows.sort(function (a, b) {\n                                var r = 0;\n                                for (var i = GRIDORDER.length; i > 0; i--) {\n                                    var x = a[GRIDORDER[i - 1].code],\n                                        y = b[GRIDORDER[i - 1].code];\n                                    if (x == y) r = 0;\n                                    else {\n                                        r = (x > y ? 1 : -1) * (GRIDORDER[i - 1].asc == 'asc' ? 1 : -1);\n                                        break;\n                                    }\n                                }\n                                return r;\n                            });\n                        }\n\n                        if (grid.pageSize) {\n                            grid.total = grid.data.rows.length;\n                            var pageData = $.extend(true, {}, DATA);\n                            pageData.rows = pageData.rows.slice(grid.pageSize * (grid.page - 1), grid.pageSize * grid.page);\n                            grid.pageData = pageData;\n                        } else\n                            grid.pageData = DATA;\n                        grid.flag = true;\n                        if (grid.dataSuccess) grid.dataSuccess(grid.pageData);\n                        fn();\n                    }\n                    else if (grid.url) {\n                        var url = grid.url;\n                        if (grid.pageSize) {\n                            grid.searchData.page = grid.page;\n                            grid.searchData.pageSize = grid.pageSize;\n                        }\n                        //生成排序字符串\n                        if (GRIDORDER.length > 0) {\n                            var orderStr = '';\n                            $.each(GRIDORDER, function (_, order) {\n                                orderStr += order.code + ' ' + order.asc + ',';\n                            });\n                            orderStr = orderStr.substr(0, orderStr.length - 1);\n                            grid.searchData.orderString = orderStr;\n                        }\n                        $.ajax({\n                            url: url,\n                            data: grid.searchData,\n                            type: 'get',\n                            dataType: 'json',\n                            beforeSend: function (xhr) {\n                                if (CONFIG.token) {\n                                    xhr.setRequestHeader('Authorization', 'Basic ' + CONFIG.token);\n                                }\n                            },\n                            success: function (data) {\n                                grid.pageData = data;\n                                grid.flag = data.flag;\n                                grid.total = data.total;\n                                if (grid.dataSuccess) grid.dataSuccess(data);\n                                fn();\n                            },\n                            error: function (error) {\n                                grid.flag = false;\n                                fn();\n                            }\n                        });\n                    }\n                    else {\n                        grid.pageData = { rows: [] };\n                        fn();\n                    }\n                }\n\n                //事件\n                var events = {\n                    //行点击事件\n                    rowClick: function () {\n                        var that = $(this);\n                        if (that.hasClass('selected')) {\n                            if (!grid.singleSelect) {\n                                that.removeClass('selected');\n                                if (that.find('td:first :checkbox').length > 0)\n                                    that.find('td:first :checkbox')[0].checked = false;\n                            }\n                            if (grid.elem.find('.grid-head').find('th,td').first().find(':checkbox').length > 0)\n                                grid.elem.find('.grid-head').find('th,td').first().find(':checkbox')[0].checked = false;\n                        } else {\n                            that.addClass('selected');\n                            if (that.find('td:first :checkbox').length > 0) {\n                                that.find('td:first :checkbox')[0].checked = true;\n                                that.find('td:first :checkbox').on('click', function () {\n                                    that[0].checked = true;\n                                });\n                            }\n                            if (grid.singleSelect)\n                                that.siblings().removeClass('selected').each(function () {\n                                    if ($(this).find('td:first :checkbox').length > 0)\n                                        $(this).find('td:first :checkbox')[0].checked = false;\n                                });\n                        }\n                        if (grid.rowClick)\n                            grid.rowClick(grid.pageData.rows[that.index()]);\n                        that.addClass('focus');\n                        that.siblings().removeClass('focus');\n                    }\n                    //排序\n                    , order: function () {\n                        var that = $(this);\n                        var ord = that.find('.grid-order');\n                        var ordCode = that.attr('order');\n                        if (ord.hasClass('grid-order-asc')) {\n                            ord.removeClass('grid-order-asc').addClass('grid-order-desc');\n                            $.each(GRIDORDER, function (i, item) {\n                                if (item.code == ordCode) {\n                                    GRIDORDER.splice(i, 1);\n                                    return false;\n                                }\n                            });\n                            GRIDORDER.push({ code: ordCode, asc: 'desc' });\n                        } else if (ord.hasClass('grid-order-desc')) {\n                            ord.removeClass('grid-order-desc');\n                            $.each(GRIDORDER, function (i, item) {\n                                if (item.code == ordCode) {\n                                    GRIDORDER.splice(i, 1);\n                                    return false;\n                                }\n                            });\n                        } else {\n                            ord.addClass('grid-order-asc');\n                            $.each(GRIDORDER, function (i, item) {\n                                if (item.code == ordCode) {\n                                    GRIDORDER.splice(i, 1);\n                                    return false;\n                                }\n                            });\n                            GRIDORDER.push({ code: ordCode, asc: 'asc' });\n                        }\n                        fnData(function () {\n                            fnBody(CONFIG.render(grid.view, grid.pageData), grid.elem.find('.grid-content'));\n                        });\n                    }\n                    //全选\n                    , selectAll: function () {\n                        var that = $(this);\n                        var checked = that[0].checked,\n                            trs = grid.elem.find('.grid-body tbody tr');\n                        checked ? trs.addClass('selected') : trs.removeClass('selected');\n                        trs.each(function () {\n                            if ($(this).find('td:first :checkbox').length > 0)\n                                $(this).find('td:first :checkbox')[0].checked = checked;\n                        });\n                    }\n                }\n\n\n                //渲染Grid视图\n                function fnSuccess() {\n                    grid.elem.html('');\n                    var content = $('<div class=\"grid-content\"></div>').appendTo(grid.elem),\n                        html = CONFIG.render(grid.view, grid.pageData);\n                    fnHeader(html, content);\n                    fnBody(html, content);\n\n                    if (grid.success)\n                        grid.success(grid.pageData, grid.elem);\n\n                    setTimeout(function () {\n                        grid.resize();\n                    }, 100);\n                    setTimeout(function () {\n                        grid.resize();\n                    },200)\n                    $(window).resize(function () {\n                        if (grid.elem.parents('div.layui-tab-item').length > 0) {\n                            if (grid.elem.parents('div.layui-tab-item').hasClass('layui-show')) {\n                                grid.resize();\n                            }\n                        }\n                        else\n                            grid.resize();\n                    });\n                }\n\n\n                //header 处理\n                function fnHeader(html, content) {\n                    var tbHead = content.find('.grid-head');\n                    if (tbHead.length == 0)\n                        tbHead = $('<div class=\"grid-head\"></div>').appendTo(content);\n                    tbHead.html(html);\n                    tbHead.find('>table').nextAll().remove();\n                    tbHead.find('thead').siblings().empty();\n\n                    tbHead.find('thead th,thead td').each(function (i) {\n                        var that = $(this);\n                        /*if (typeof (that.attr('order')) != 'undefined') {\n                         that.append('<i class=\"grid-order\"></i>').on('click', events.order);\n                         }\n\n                         if (i == 0 && $(this).find(':checkbox').length > 0 && !grid.singleSelect) {\n                         that.find(':checkbox').on('click', events.selectAll);\n                         }*/\n\n                        that.html('<div class=\"grid-coll\">' + that.html() + '</div>');\n                        if (typeof (that.attr('order')) != 'undefined') {\n                            that.on('click', events.order).find('.grid-coll').append('<i class=\"grid-order\"></i>');\n                        }\n                        if (i == 0 && that.find(':checkbox').length > 0 && !grid.singleSelect) {\n                            that.find(':checkbox').on('click', events.selectAll);\n                        }\n                    });\n                }\n\n                //body处理\n                function fnBody(html, content) {\n                    if (!grid.flag) {\n                        content.addClass('grid-err').html('获取数据失败');\n                        grid.closeLoading();\n                        return;\n                    }\n                    var tbHead = content.find('.grid-head').find('table'),\n                        tbBody = content.find('.grid-body');\n                    if (tbBody.length == 0)\n                        tbBody = $('<div class=\"grid-body\"></div>').appendTo(content);\n                    tbBody.html(html);\n                    tbBody.find('>table').prevAll().remove();\n\n                    tbBody.find('thead th,thead td').each(function () {\n                        /*if (typeof ($(this).attr('order')) != 'undefined')\n                         $(this).append('<i class=\"grid-order\"></i>');*/\n\n                        var that = $(this);\n                        that.html('<div class=\"grid-coll\">' + that.html() + '</div>');\n                        if (typeof (that.attr('order')) != 'undefined') {\n                            that.find('.grid-coll').append('<i class=\"grid-order\"></i>');\n                        }\n\n                    });\n                    if (tbBody.find('tbody tr').length == 0)\n                        tbBody.find('tbody').append('<tr><td style=\"border:none\"></td></tr>');\n\n                    var tool = tbBody.find('>.grid-tool').remove();\n                    grid.elem.find('.grid-page').remove();\n                    var pageDom = $('<div class=\"grid-page\"><div></div></div>');\n                    var pages = Math.ceil(grid.total / grid.pageSize);\n                    if (pages > 1 || tool.length > 0) {\n                        pageDom.appendTo(content);\n                        tool.prependTo(pageDom);\n                    }\n                    if (pages > 1) {\n                        layui.laypage({\n                            record: grid.record ? grid.total : 0,\n                            cont: pageDom.find('>div'),\n                            pages: pages,\n                            curr: grid.page,\n                            groups: grid.pageGroup,\n                            skip: true,\n                            first: 1,\n                            last: pages,\n                            prev: '<em><</em>',\n                            next: '<em>></em>',\n                            jump: function (obj, isFirst) {\n                                if (!isFirst) {\n                                    grid.page = obj.curr;\n                                    //grid.build();\n                                    fnData(function () {\n                                        fnBody(CONFIG.render(grid.view, grid.pageData), grid.elem.find('.grid-content'));\n                                    });\n                                }\n                            }\n                        });\n                    }\n\n                    var trs = tbBody.find('tbody tr');\n                    if (trs.length > 0) {\n                        var checkbox = tbHead.find('th').first().find(':checkbox');\n\n                        trs.on('click', events.rowClick);\n                    }\n                    tbBody.scroll(function () {\n                        RESIZE = {\n                            left: $(this).scrollLeft(),\n                            top: $(this).scrollTop()\n                        };\n                        tbHead.css('margin-left', -RESIZE.left);\n                    });\n                    grid.closeLoading();\n\n                    grid.resize();\n\n                    //verify(tbBody);\n                }\n\n                grid.loading = function () {\n                    var loading = grid.elem.find('.loading_bg,.loading');\n                    if (loading.length == 0)\n                        loading = $('<div class=\"loading_bg\"></div><div class=\"loading\"><i class=\"layui-icon layui-anim layui-anim-rotate layui-anim-loop\">&#xe63d;</i></div>')\n                            .appendTo(grid.elem);\n                    loading.show();\n                }\n\n                grid.closeLoading = function () {\n                    grid.elem.find('.loading_bg,.loading').hide();\n                }\n\n                grid.getIndex = function () {\n                    var tr = this.elem.find('.grid-body tbody tr.focus');\n                    if (tr.length > 0)\n                        return tr.index();\n                    else\n                        return -1;\n                }\n\n                grid.getRow = function () {\n                    var index = grid.getIndex();\n                    if (index >= 0)\n                        return grid.pageData.rows[index];\n                    else\n                        return null;\n                }\n\n                grid.focus = function (index) {\n                    if (index == undefined || index == -1) {\n                        grid.elem.find('.grid-body tbody tr.focus').removeClass('focus');\n                    }\n                    else {\n                        var tr = grid.elem.find('.grid-body tbody tr:eq(' + index + ')').addClass('focus');\n                        tr.siblings('.focus').removeClass('focus');\n                        if (grid.singleSelect)\n                            grid.selectIndex(index);\n                        else {\n                            tr.addClass('selected');\n                            if (tr.find('td:first :checkbox').length > 0)\n                                tr.find('td:first :checkbox')[0].checked = true;\n                        }\n                    }\n                }\n\n                grid.selectValue = function (v) {\n                    var rowid = this.id;\n                    if (v == undefined) {\n                        var rows = this.selectRow();\n                        if (rows == null)\n                            return null;\n\n                        if (this.singleSelect) {\n                            return rows[rowid];\n                        } else {\n                            values = [];\n                            $.each(rows, function (_, row) {\n                                values.push(row[rowid]);\n                            });\n                            return values;\n                        }\n                    } else {\n                        if (this.singleSelect)\n                            v = [v];\n                        this.elem.find('tbody tr.selected').each(function () {\n                            $(this).removeClass('selected');\n                            if ($(this).find('td:first :checkbox').length > 0)\n                                $(this).find('td:first :checkbox')[0].checked = false;\n                        });\n                        $.each(grid.pageData.rows, function (i, row) {\n                            if (v.indexOf(row[rowid]) != -1) {\n                                var tr = grid.elem.find('tbody tr:eq(' + i + ')');\n                                tr.addClass('selected');\n                                if (tr.find('td:first :checkbox').length > 0)\n                                    tr.find('td:first :checkbox')[0].checked = true;\n                            }\n                        });\n                    }\n                }\n\n                grid.selectRow = function () {\n                    /*if (values != undefined) {\n                     grid.elem.find('.grid-body tbody tr.selected').removeClass('selected').each(function () {\n                     if ($(this).find('td:first :checkbox').length > 0)\n                     $(this).find('td:first :checkbox')[0].checked = false;\n                     });\n                     var keys = grid.keys.split(';');\n                     if (Object.prototype.toString.call(values) == '[object Array]' && !grid.singleSelect) {\n                     $.each(values, function (a, value) {\n                     $.each(grid.pageData.rows, function (i, r) {\n                     var key = '';\n                     $.each(keys, function (j, k) {\n                     key += r[k]+';';\n                     });\n                     if (value + ';' == key) {\n                     var tr = grid.elem.find('.grid-body tbody tr:eq(' + i + ')');\n                     tr.addClass('selected');\n                     if (tr.find('td:first :checkbox').length > 0)\n                     tr.find('td:first :checkbox')[0].checked = true;\n                     return false;\n                     }\n                     });\n                     });\n                     }\n                     else {\n                     $.each(grid.pageData.rows, function (i, r) {\n                     var key = '';\n                     $.each(keys, function (j, k) {\n                     key += r[k]+';';\n                     });\n                     if (values + ';' == key) {\n                     var tr = grid.elem.find('.grid-body tbody tr:eq(' + i + ')');\n                     tr.addClass('selected');\n                     if (tr.find('td:first :checkbox').length > 0)\n                     tr.find('td:first :checkbox')[0].checked = true;\n                     return false;\n                     }\n                     });\n                     }\n                     }\n                     else {*/\n                    if (!grid.singleSelect) {\n                        rows = [];\n                        this.elem.find('.grid-body tbody tr').each(function (i) {\n                            if ($(this).hasClass('selected'))\n                                rows.push(grid.pageData.rows[i]);\n                        });\n                        return rows.length > 0 ? rows : null;\n                    }\n                    else {\n                        var tr = this.elem.find('.grid-body tbody tr.selected');\n                        if (tr.length > 0)\n                            return grid.pageData.rows[tr.index()];\n                        else\n                            return null;\n                    }\n                    //}\n                }\n\n                grid.selectIndex = function (index) {\n                    if (index != undefined && index >= 0) {\n                        grid.elem.find('.grid-body tbody tr.selected').removeClass('selected').each(function () {\n                            if ($(this).find('td:first :checkbox').length > 0)\n                                $(this).find('td:first :checkbox')[0].checked = false;\n                        });\n                        if (Object.prototype.toString.call(index) == '[object Array]' && !grid.singleSelect) {\n                            $.each(index, function (i, idx) {\n                                var tr = grid.elem.find('.grid-body tbody tr:eq(' + idx + ')');\n                                tr.addClass('selected');\n                                if (tr.find('td:first :checkbox').length > 0)\n                                    tr.find('td:first :checkbox')[0].checked = true;\n                                return false;\n                            });\n                        } else {\n                            var tr = grid.elem.find('.grid-body tbody tr:eq(' + index + ')');\n                            tr.addClass('selected');\n                            if (tr.find('td:first :checkbox').length > 0)\n                                tr.find('td:first :checkbox')[0].checked = true;\n                        }\n                    }\n                    else if (index == undefined) {\n                        if (!grid.singleSelect) {\n                            rows = [];\n                            this.elem.find('.grid-body tbody tr').each(function (i) {\n                                if ($(this).hasClass('selected'))\n                                    rows.push(i);\n                            });\n                            return rows.length > 0 ? rows : null;\n\n                        } else {\n                            var tr = this.elem.find('.grid-body tbody tr.selected');\n                            if (tr.length > 0)\n                                return tr.index();\n                            else\n                                return -1;\n                        }\n                    }\n                }\n\n                //生成表格行并绑定事件\n                function rowsDom(rows, op) {\n                    if (Object.prototype.toString.call(rows) != '[object Array]')\n                        rows = [rows];\n                    var html = CONFIG.render(grid.view, { rows: rows, op: op });\n                    //var content = grid.elem.find('.grid-content');\n                    var trs = $(html).find('tbody tr');\n                    trs.on('click', events.rowClick);\n                    //verify(trs);\n                    return trs;\n                }\n\n                function verify(elem) {\n                    var flag = true, msg = '', errOthis;\n                    var fmVer = form.config.verify;\n                    elem.find('*[lay-verify]').each(function () {\n                        var othis = $(this),\n                            td = othis.parents('td').last(),\n                            ver = othis.attr('lay-verify').split('|'),\n                            tips='',\n                            value = othis.val();\n                        //othis.removeClass(DANGER);\n                        $.each(ver, function (_, thisVer) {\n                            var isFn = typeof fmVer[thisVer] === 'function';\n                            if (fmVer[thisVer] && (isFn ? tips = fmVer[thisVer](value, othis[0]) : !fmVer[thisVer][0].test(value))) {\n                                td.addClass(CSS.danger);\n                                flag = false;\n                                if (msg == '') msg = tips || fmVer[thisVer][1];\n                                if (!errOthis) errOthis = othis;\n                            }\n                        });\n                        $(this).on('keyup', function () {\n                            td.removeClass(CSS.danger);\n                        });\n                    });\n                    if (!flag) {\n                        layer.msg(msg, { icon: 5, shift: 6 });\n                        errOthis.select();\n                    }\n                    return flag;\n                }\n\n                grid.insert = function (rows, index) {\n                    if (Object.prototype.toString.call(rows) != '[object Array]')\n                        rows = [rows];\n\n                    if (index == undefined || index < 0) {\n                        $.each(rows, function (i, row) {\n                            grid.pageData.rows.push(row);\n                        });\n\n                    } else {\n                        var str = JSON.stringify(rows);\n                        str = str.substr(1, str.length - 2);\n                        if (index == 0)\n                            eval('grid.pageData.rows.unshift(' + str + ')');\n                        else\n                            eval('grid.pageData.rows.splice(' + index + ',0,' + str + ')');\n                    }\n                    var trs = rowsDom(rows);\n                    var tbody = grid.elem.find('.grid-body tbody');\n                    if (index == undefined || index < 0)\n                        tbody.append(trs);\n                    else if (index == 0)\n                        tbody.prepend(trs);\n                    else {\n                        tbody.find('>tr:eq(' + index + ')').before(trs);\n                    }\n                    grid.resize();\n                    return trs;\n                }\n\n                grid.update = function (row, index) {\n                    if (index == undefined || index < 0) {\n                        console.log('grid error: index参数错误');\n                        return;\n                    }\n                    grid.pageData.rows[index] = row;\n\n                    var tr = rowsDom(row);\n                    grid.elem.find('.grid-body tbody').find('>tr:eq(' + index + ')').replaceWith(tr);\n                    grid.resize();\n\n                    //grid.selectIndex(index);\n                    grid.focus(index);\n                    return tr;\n                }\n\n                grid.delete = function (index) {\n                    if (index == undefined) {\n                        console.log('grid error:index参数错误');\n                        return;\n                    } else if (Object.prototype.toString.call(index) != '[object Array]') {\n                        index = [index];\n                    }\n                    for (var i = index.length; i > 0; i--) {\n                        grid.pageData.rows.splice(index[i - 1], 1);\n                        grid.elem.find('.grid-body tbody').find('>tr:eq(' + index[i - 1] + ')').remove();\n                    }\n                    grid.resize();\n                }\n\n                //更新表格页脚\n                grid.foot = function (footData) {\n                    var html = CONFIG.render(grid.view, footData);\n                    var tfoot = $(html).find('tfoot');\n                    grid.elem.find('.grid-body tfoot').replaceWith(tfoot);\n                    grid.resize();\n                }\n\n                //编辑行\n                grid.edit = function (index) {\n                    var body = grid.elem.find('.grid-body tbody');\n                    //if (index == undefined)\n                    //    index = grid.selectIndex();\n                    if (index == undefined || index < 0) {\n                        var rowhtml = rowsDom(grid.pageData.rows, 'edit');\n                        body.html(rowhtml);\n                    }\n                    else {\n                        var row = grid.pageData.rows[index];\n                        var rowhtml = rowsDom(row, 'edit');\n                        body.find('>tr:eq(' + index + ')').replaceWith(rowhtml);\n                        grid.focus(index);\n                    }\n                    grid.resize();\n                }\n                //结束编辑行\n                grid.endEdit = function (index) {\n                    var body = grid.elem.find('.grid-body tbody');\n                    //if (index == undefined)\n                    //    index = grid.selectIndex();\n                    var row = null;\n                    if (index == undefined || index < 0) {\n                        if (verify(body)) {\n                            body.find('tr').each(function (i, tr) {\n                                $(tr).find('*[name]').each(function (_, item) {\n                                    grid.pageData.rows[i][$(item).attr('name')] = item.value;\n                                });\n                            });\n                            row = grid.pageData.rows;\n                            var rowhtml = rowsDom(row);\n                            body.html(rowhtml);\n                        }\n                    }\n                    else {\n                        //erify()\n                        var tr = body.find('tr:eq(' + index + ')');\n                        if (verify(tr)) {\n                            tr.find('*[name]').each(function (_, item) {\n                                grid.pageData.rows[index][$(item).attr('name')] = item.value;\n                            });\n                            row = grid.pageData.rows[index];\n                            var rowhtml = rowsDom(row);\n                            body.find('>tr:eq(' + index + ')').replaceWith(rowhtml);\n                            grid.focus(index);\n                        }\n                    }\n                    grid.resize();\n\n                    return row;\n                }\n\n                grid.clear = function () {\n                    grid.data = { rows: [] };\n                    grid.build();\n                }\n\n                grid.setData = function (data) {\n                    grid.data = data;\n                    grid.page = 1;\n                    grid.build();\n                }\n                /*New End*/\n\n                grid.resize = function () {\n                    //grid.elem.find('.grid-body thead').show();\n                    var head = grid.elem.find('.grid-head>table'),\n                        body = grid.elem.find('.grid-body>table');\n                    var ths = grid.elem.find('.grid-head th,.grid-head td');\n                    var tbhs = grid.elem.find('.grid-body thead th,.grid-body thead td');\n                    head.css('width', body.width());\n                    tbhs.each(function (i, th) {\n                        var w = $(th).find('.grid-coll').width();\n                        $(ths[i]).find('.grid-coll').css('width', w);\n                    });\n                    if (grid.elem.hasClass('grid')) {\n                        var top = grid.elem.find('.grid-head').height() || 0,\n                            bottom = grid.elem.find('.grid-page').height() || 0;\n                        grid.elem.find('.grid-body').css({ top: top, bottom: bottom });\n                        if (grid.elem.find('.grid-body table').height() < grid.elem.find('.grid-body').height())\n                            grid.elem.find('.grid-body').css({ bottom: 'auto' });\n                        var gridTop = 0;\n                        var prev = grid.elem.prevAll('.grid-position');\n                        if (prev.length == 0) prev = grid.elem.prev();\n                        if (prev.length > 0) {\n                            gridTop = prev.height() + prev.position().top + 5;\n                            grid.elem.css('top', gridTop);\n                        }\n                    }\n                    var H = grid.elem.find('.grid-body table:first thead').height() || 0;\n                    if (H > 0)\n                        grid.elem.find('.grid-body table:first').css('margin-top', -H);\n                    if (RESIZE.top != 0)\n                        grid.elem.find('.grid-body').scrollTop(RESIZE.top);\n                    if (RESIZE.left != 0)\n                        grid.elem.find('.grid-body').scrollLeft(RESIZE.left);\n                }\n\n                if (grid.search) { //绑定搜索事件\n                    form.on('submit(' + grid.search + ')', function (data) {\n                        grid.page = 1;\n                        grid.searchData = data.field;\n                        grid.build();\n                    });\n                }\n\n                return grid;\n            }\n        };\n    exports('grid', Grid);\n    layui.link(layui.cache.base + 'css/grid.css', null, 'gridcss');\n});\n\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/layui/layuiextend/treegrid/treegrid.js",
    "content": "﻿layui.define('grid', function (exports) {\n    var Grid = layui.grid;\n    var TreeGrid = {\n        config: Grid.config,\n        createNew: function (option) {\n            var grid = Grid.createNew(option);\n            grid.pageSize = undefined;\n            grid.id = option.id || 'id';\n            grid.parentid = option.parentid || 'parentid';\n            grid.root = option.root || 0;\n            grid.order = option.order || grid.id;\n            grid.asc = option.asc || 'asc';\n            grid.loadRow = option.loadRow;  //懒加载\n\n            //grid.onCollapse = option.onCollapse;\n            //grid.onExpand = option.onExpand;\n\n            grid.dataSuccess = function (pageData) {\n                if (option.dataSuccess) option.dataSuccess(pageData);\n                var treeRows = [];\n                HELPER.treeData(pageData.rows, treeRows, grid.root);\n                grid.pageData.rows = treeRows;\n            };\n\n            var EXPANDER = '<span class=\"treegrid-expander\"></span>',\n                INDENT = '<span class=\"treegrid-indent\"></span>';\n\n            var HELPER = {\n                treeData: function (rows, tree, pid) {\n                    if (Object.prototype.toString.call(rows) != '[object Array]')\n                        rows = [rows];\n                    var items = [];\n                    $.each(rows, function (_, item) {\n                        if (item[grid.parentid] == pid)\n                            items.push(item);\n                    });\n                    items.sort(function (a, b) {\n                        var x = a[grid.order],\n                            y = b[grid.order];\n                        return x == y ? 0 : (x > y ? 1 : -1);\n                    });\n                    if (items.length > 0) {\n                        $.each(items, function (_, item) {\n                            tree.push(item);\n                            HELPER.treeData(rows, tree, item[grid.id]);\n                        });\n                    }\n                },\n                nodeId: function (node) {\n                    var template = /treegrid-([A-Za-z0-9_-]+)/;\n                    if (template.test(node.attr('class')))\n                        return template.exec(node.attr('class'))[1];\n                    else\n                        return null;\n                },\n                nodePid: function (node) {\n                    var template = /treegrid-parent-([A-Za-z0-9_-]+)/;\n                    if (template.test(node.attr('class')))\n                        return template.exec(node.attr('class'))[1];\n                    else\n                        return null;\n                },\n\n                //展开\n                expanded: function (flag, id) {\n                    var trs, tr;\n                    if (id != undefined) {\n                        tr = grid.elem.find('.grid-body tr.treegrid-' + id);\n                        tr.removeClass('treegrid-collapse').addClass('treegrid-expanded');\n                        trs = tr.nextAll();\n                    } else\n                        trs = grid.elem.find('.grid-body tbody tr');\n                    trs.each(function (_, t) {\n                        t = $(t);\n                        if (tr && t.find('span.treegrid-indent,span.treegrid-expander').length <= tr.find('span.treegrid-indent,span.treegrid-expander').length) {\n                            return false;\n                        }\n                        var pid = HELPER.nodePid(t),\n                            pNode = t.prevAll('.treegrid-' + pid);\n                        if (flag || pNode.hasClass('treegrid-expanded') || id == undefined && HELPER.nodeId(pNode) == grid.root)\n                            t.show();\n                        if (t.hasClass('treegrid-collapse') && flag || id == undefined && pid == null)\n                            t.removeClass('treegrid-collapse').addClass('treegrid-expanded');\n                    });\n                    grid.resize();\n                },\n\n                //折叠\n                cellapsed: function (flag, id) {\n                    var trs, tr;\n                    if (id != undefined) {\n                        tr = grid.elem.find('.grid-body tbody tr.treegrid-' + id);\n                        tr.removeClass('treegrid-expanded').addClass('treegrid-collapse');\n                        trs = tr.nextAll();\n                    } else\n                        trs = grid.elem.find('.grid-body tbody tr');\n                    trs.each(function (_, t) {\n                        t = $(t);\n                        if (tr && t.find('span.treegrid-indent,span.treegrid-expander').length <= tr.find('span.treegrid-indent,span.treegrid-expander').length) {\n                            return false;\n                        }\n                        var pid = HELPER.nodePid(t);\n                        if (pid != null)\n                            t.hide();\n                        if (t.hasClass('treegrid-expanded') && (flag) || id == undefined && pid == null)\n                            t.removeClass('treegrid-expanded').addClass('treegrid-collapse');\n                    });\n                    grid.resize();\n                },\n\n                //节点展开、折叠事件\n                onExpand: function () {\n                    var tr = $(this).parents('tr').last(),\n                        id = HELPER.nodeId(tr);\n                    if (tr.hasClass('treegrid-expanded')) {\n                        HELPER.cellapsed(false, id);\n                    } else {\n                        HELPER.expanded(false, id);\n                    }\n                    event.stopPropagation(); //阻止冒泡 rowClick\n                },\n\n                //懒加载事件\n                onLoadRow: function () {\n                    var that = $(this);\n                    var tr = that.parents('tr').last().removeClass('treegrid-collapse').addClass('treegrid-loading'),\n                        id = HELPER.nodeId(tr);\n                    that.unbind('click');\n                    /*grid.loadRow(id, function (rows) {\n                        console.log(123);\n                        grid.insertChild(rows, id);\n                        that.on('click', HELPER.onExpand);\n                        tr.removeClass('treegrid-loading').addClass('treegrid-expanded');\n                    });*/\n                    grid.loadRow({\n                        pid: id,\n                        children: function (rows) {\n                            tr.removeClass('treegrid-loading');\n                            if (!rows) {\n                                tr.addClass('treegrid-wrong');\n                            }\n                            else if (rows.length > 0) {\n                                grid.insertChild(rows, id);\n                                that.on('click', HELPER.onExpand);\n                                tr.addClass('treegrid-expanded');\n                            } else {\n                                that.replaceWith(INDENT);\n                            }\n                        }\n                    });\n                },\n\n                treeDom: function (trs, rows) {\n                    if (Object.prototype.toString.call(rows) != '[object Array]')\n                        rows = [rows];\n                    $.each(trs, function (i, tr) {\n                        tr = $(tr),\n                        id = rows[i][grid.id],\n                        pid = rows[i][grid.parentid];\n                        tr.addClass('treegrid-' + id);\n                        if (pid != grid.root) tr.addClass('treegrid-parent-' + pid);\n\n                        //多选事件绑定\n                        if (!grid.singleSelect) {\n                            tr.click(function () {\n                                var selected = $(this).hasClass('selected');\n                                private_childSelect($(this), selected);\n                                var _pid = HELPER.nodePid($(this));\n                                if (_pid != null)\n                                    private_parentSelect(selected, _pid);\n                            });\n                        }\n                    });\n\n                    function private_childSelect($tr, selected) {\n                        $tr.nextAll().each(function (_, tr) {\n                            if ($(tr).find('span.treegrid-indent,span.treegrid-expander').length <= $tr.find('span.treegrid-indent,span.treegrid-expander').length) {\n                                return false;\n                            }\n                            selected ? $(tr).addClass('selected') : $(tr).removeClass('selected');\n                            if ($(tr).find('td:first :checkbox').length > 0)\n                                $(tr).find('td:first :checkbox')[0].checked = selected;\n                        });\n                    }\n                    function private_parentSelect(selected, pid) {\n                        var tr = grid.elem.find('tr.treegrid-' + pid);\n                        if (tr.length > 0) {\n                            if (selected && !tr.hasClass('selected')) {\n                                tr.addClass('selected');\n                                if (tr.find('td:first :checkbox').length > 0)\n                                    tr.find('td:first :checkbox')[0].checked = true;\n                            }\n                            else if (tr.nextAll('tr.treegrid-parent-' + pid + '.selected').length == 0) {\n                                tr.removeClass('selected');\n                                if (tr.find('td:first :checkbox').length > 0)\n                                    tr.find('td:first :checkbox')[0].checked = false;\n                            }\n                            pid = HELPER.nodePid(tr);\n                            if (pid != null)\n                                private_parentSelect(selected, pid);\n                        }\n                    }\n\n\n                    $.each(trs, function (_, tr) {\n                        tr = $(tr);\n                        var id = HELPER.nodeId(tr),\n                            pid = HELPER.nodePid(tr);\n                        if (tr.next('.treegrid-parent-' + id).length > 0) {\n                            $(EXPANDER).on('click', HELPER.onExpand).prependTo(tr.addClass('treegrid-expanded').find('td:eq(0)'));\n                        } else if (grid.loadRow && grid.pageData.rows[tr.index()]._children) {\n                            $(EXPANDER).on('click', HELPER.onLoadRow).prependTo(tr.addClass('treegrid-collapse').find('td:eq(0)'));\n                        } else {\n                            tr.find('td:eq(0)').prepend(INDENT);\n                        }\n                        if (grid.elem.find('tr.treegrid-' + pid).length > 0) {\n                            var prevIndentLen = grid.elem.find('tr.treegrid-' + pid).find('.treegrid-expander').prevAll().length;\n                            var pindent = '';\n                            for (var i = 0; i < prevIndentLen; i++) {\n                                pindent += INDENT;\n                            }\n                            tr.find('td:eq(0)').prepend(pindent + INDENT);\n                        }\n                    });\n                    grid.resize();\n                }\n            }\n\n            grid.success = function () {\n                if (option.success)\n                    option.success();\n                HELPER.treeDom(grid.elem.find('.grid-body tbody tr'), grid.pageData.rows);\n\n                /*\n                if (option.onCollapse) {\n                    \n                }\n                if (option.onExpand) {\n                    \n                }*/\n            };\n\n            //折叠\n            grid.collapse = function (id) {\n                HELPER.cellapsed(false, id);\n            }\n\n            //折叠全部\n            grid.collapseAll = function (id) {\n                HELPER.cellapsed(true, id);\n            }\n\n            //展开\n            grid.expand = function (id) {\n                HELPER.expanded(false, id);\n            }\n\n            //展开全部\n            grid.expandAll = function (id) {\n                HELPER.expanded(true, id);\n            }\n\n            //获取子节数据\n            grid.getChild = function (pid) {\n                var rows = [],\n                    tr = grid.elem.find('.grid-body tr.treegrid-' + pid),\n                    index = tr.index();\n                $.each(tr.nextAll('.treegrid-parent-' + pid), function () {\n                    rows.push(grid.pageData.rows[$(this).index()]);\n                });\n                return rows;\n            }\n\n            //获取子节点数据，包含子节点的延伸\n            grid.getChildAll = function (pid) {\n                var rows = [],\n                    tr = grid.elem.find('.grid-body tr.treegrid-' + pid),\n                    index = tr.index();\n                $.each(tr.nextAll(),function(i,t){\n                    var t=$(t);\n                    if (t.find('span.treegrid-indent,span.treegrid-expander').length <= tr.find('span.treegrid-indent,span.treegrid-expander').length) {\n                        return false;\n                    }\n                    rows.push(grid.pageData[index + i]);\n                });\n                return rows;\n            }\n\n            //添加同级节点\n            grid.insertNode = function (rows, pid) {\n                pid = pid != undefined ? pid : grid.root;\n                var index = undefined;\n                if (pid != grid.root) {\n                    var tr = grid.elem.find('.grid-body tr.treegrid-' + pid);\n                    index = tr.index();\n                    pid = HELPER.nodePid(tr);\n                }\n\n                var newRow = [];\n                HELPER.treeData(rows, newRow, pid);\n                var trs = grid.insert(newRow, index);\n                HELPER.treeDom(trs, newRow);\n            }\n\n            //添加子节点\n            grid.insertChild = function (rows, pid) {\n                pid = pid != undefined ? pid : grid.root;\n                var index = undefined;\n                if (pid != grid.root) {\n                    var tr = grid.elem.find('.grid-body tr.treegrid-' + pid);\n                    index = tr.index();\n                    index++;\n                    tr.addClass('treegrid-expanded');\n                    if (tr.find('td').first().find('span.treegrid-expander').length == 0) {\n                        tr.find('td').first().find('span.treegrid-indent').last().removeClass('treegrid-indent').addClass('treegrid-expander').on('click', HELPER.onExpand);\n                    } else {\n                        $.each(tr.nextAll(), function (i, t) {\n                            var t = $(t);\n                            if (t.find('span.treegrid-indent,span.treegrid-expander').length <= tr.find('span.treegrid-indent,span.treegrid-expander').length) {\n                                return false;\n                            }\n                            index++;\n                            if (HELPER.nodePid(t) == pid) t.show();\n                        });\n                    }\n                }\n                if (index >= grid.pageData.rows.length)\n                    index = undefined;\n                var newRow = [];\n                HELPER.treeData(rows, newRow, pid);\n\n                var trs = grid.insert(newRow, index);\n                HELPER.treeDom(trs, newRow);\n            }\n\n            //修改节点\n            grid.updateNode = function (row,id) {\n                if (id == undefined) {\n                    console.log('treegrid error:参数id错误');\n                    return;\n                }\n                var tr = grid.elem.find('.grid-body tr.treegrid-' + id);\n                var index = tr.index();\n                var trs = grid.update(row, index);\n                HELPER.treeDom(trs, row);\n            }\n\n            //删除节点及其子节点\n            grid.deleteNode = function (id) {\n                if (id == undefined) {\n                    console.log('treegrid error:参数id错误');\n                    return;\n                }\n                var tr = grid.elem.find('.grid-body tr.treegrid-' + id);\n                var index = tr.index(),\n                    idx = [index];\n                $.each(tr.nextAll(), function (i, t) {\n                    var t = $(t);\n                    if (t.find('span.treegrid-indent,span.treegrid-expander').length <= tr.find('span.treegrid-indent,span.treegrid-expander').length) {\n                        return false;\n                    }\n                    index++;\n                    idx.push(index);\n                });\n                grid.delete(idx);\n            }\n\n            grid.editNode = function (id) {\n                var index, trs, rows;\n                if (id != undefined) {\n                    var tr = grid.elem.find('.grid-body tbody tr.treegrid-' + id);\n                    index = tr.index();\n                }\n                grid.edit(index);\n                if (index != undefined && index >= 0) {\n                    trs = grid.elem.find('.grid-body tbody tr:eq(' + index + ')');\n                    rows = grid.pageData.rows[index];\n                } else {\n                    trs = grid.elem.find('.grid-body tbody tr');\n                    rows = grid.pageData.rows;\n                }\n                HELPER.treeDom(trs, rows);\n            }\n            grid.endEditNode = function (id) {\n                var index, trs, rows;\n                if (id != undefined) {\n                    var tr = grid.elem.find('.grid-body tbody tr.treegrid-' + id);\n                    index = tr.index();\n                }\n                grid.endEdit(index);\n                if (index != undefined && index >= 0) {\n                    trs = grid.elem.find('.grid-body tbody tr:eq(' + index + ')');\n                    rows = grid.pageData.rows[index];\n                } else {\n                    trs = grid.elem.find('.grid-body tbody tr');\n                    rows = grid.pageData.rows;\n                }\n                HELPER.treeDom(trs, rows);\n            }\n\n            return grid;\n        }\n    };\n    exports('treegrid', TreeGrid);\n    layui.link(layui.cache.base + 'css/grid.css', null, 'gridcss');\n});\n\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/layui/layuiextend/ztree/css/treeselect.css",
    "content": ".layui-input-treeselect .ztree,\n.layui-input-treeselect .ztree * {\n  background-color: white;\n  color: black;\n  font-size: 16px;\n}\n\n.layui-input-treeselect .ztree {\n  padding: 10px 5px;\n}\n\n.layui-input-treeselect .ztree-content {\n  border: 1px solid #e6e6e6;\n  position: absolute;\n  z-index: 100;\n  top: 42px;\n  width: 100%;\n  display: none;\n  border-radius: 2px;\n}\n\n.layui-input-treeselect .ztree>li {\n  padding: 0 10px;\n}\n\n.layui-input-treeselect .ztree li span.button.roots_docu::before,\n.layui-input-treeselect .ztree li span.button::before {\n  color: black;\n}\n\n.layui-input-treeselect .ztree-input {\n  position: absolute;\n  line-height: 37px;\n  width: 100%;\n  border: 1px solid #e6e6e6;\n  overflow: hidden;\n  border-radius: 2px;\n  height: 37px;\n  overflow-y: inherit;\n}\n\n.layui-input-treeselect .ztree-input a:first-child {\n  margin-left: 10px;\n}\n\n.layui-input-treeselect .ztree-input a {\n  background-color: #5FB878;\n  margin-left: 5px;\n  padding: 2px 3px 2px 5px;\n  position: relative;\n  cursor: default;\n  color: white;\n  border-radius: 2px;\n}\n\n.layui-input-treeselect .ztree-input a i {\n  font-size: inherit;\n}\n\n.layui-input-treeselect .ztree-input a i:hover {\n  color: red;\n  cursor: pointer;\n}\n\n.layui-input-treeselect .layui-input {\n  background-color: transparent;\n  border: 0;\n  display: none;\n}"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/layui/layuiextend/ztree/css/ztree/awesome/fa.less",
    "content": "@fa-glass: \"\\f000\";\n@fa-music: \"\\f001\";\n@fa-search: \"\\f002\";\n@fa-envelope-o: \"\\f003\";\n@fa-heart: \"\\f004\";\n@fa-star: \"\\f005\";\n@fa-star-o: \"\\f006\";\n@fa-user: \"\\f007\";\n@fa-film: \"\\f008\";\n@fa-th-large: \"\\f009\";\n@fa-th: \"\\f00a\";\n@fa-th-list: \"\\f00b\";\n@fa-check: \"\\f00c\";\n@fa-times: \"\\f00d\";\n@fa-search-plus: \"\\f00e\";\n@fa-search-minus: \"\\f010\";\n@fa-power-off: \"\\f011\";\n@fa-signal: \"\\f012\";\n@fa-cog: \"\\f013\";\n@fa-trash-o: \"\\f014\";\n@fa-home: \"\\f015\";\n@fa-file-o: \"\\f016\";\n@fa-clock-o: \"\\f017\";\n@fa-road: \"\\f018\";\n@fa-download: \"\\f019\";\n@fa-arrow-circle-o-down: \"\\f01a\";\n@fa-arrow-circle-o-up: \"\\f01b\";\n@fa-inbox: \"\\f01c\";\n@fa-play-circle-o: \"\\f01d\";\n@fa-repeat: \"\\f01e\";\n@fa-refresh: \"\\f021\";\n@fa-list-alt: \"\\f022\";\n@fa-lock: \"\\f023\";\n@fa-flag: \"\\f024\";\n@fa-headphones: \"\\f025\";\n@fa-volume-off: \"\\f026\";\n@fa-volume-down: \"\\f027\";\n@fa-volume-up: \"\\f028\";\n@fa-qrcode: \"\\f029\";\n@fa-barcode: \"\\f02a\";\n@fa-tag: \"\\f02b\";\n@fa-tags: \"\\f02c\";\n@fa-book: \"\\f02d\";\n@fa-bookmark: \"\\f02e\";\n@fa-print: \"\\f02f\";\n@fa-camera: \"\\f030\";\n@fa-font: \"\\f031\";\n@fa-bold: \"\\f032\";\n@fa-italic: \"\\f033\";\n@fa-text-height: \"\\f034\";\n@fa-text-width: \"\\f035\";\n@fa-align-left: \"\\f036\";\n@fa-align-center: \"\\f037\";\n@fa-align-right: \"\\f038\";\n@fa-align-justify: \"\\f039\";\n@fa-list: \"\\f03a\";\n@fa-outdent: \"\\f03b\";\n@fa-indent: \"\\f03c\";\n@fa-video-camera: \"\\f03d\";\n@fa-picture-o: \"\\f03e\";\n@fa-pencil: \"\\f040\";\n@fa-map-marker: \"\\f041\";\n@fa-adjust: \"\\f042\";\n@fa-tint: \"\\f043\";\n@fa-pencil-square-o: \"\\f044\";\n@fa-share-square-o: \"\\f045\";\n@fa-check-square-o: \"\\f046\";\n@fa-arrows: \"\\f047\";\n@fa-step-backward: \"\\f048\";\n@fa-fast-backward: \"\\f049\";\n@fa-backward: \"\\f04a\";\n@fa-play: \"\\f04b\";\n@fa-pause: \"\\f04c\";\n@fa-stop: \"\\f04d\";\n@fa-forward: \"\\f04e\";\n@fa-fast-forward: \"\\f050\";\n@fa-step-forward: \"\\f051\";\n@fa-eject: \"\\f052\";\n@fa-chevron-left: \"\\f053\";\n@fa-chevron-right: \"\\f054\";\n@fa-plus-circle: \"\\f055\";\n@fa-minus-circle: \"\\f056\";\n@fa-times-circle: \"\\f057\";\n@fa-check-circle: \"\\f058\";\n@fa-question-circle: \"\\f059\";\n@fa-info-circle: \"\\f05a\";\n@fa-crosshairs: \"\\f05b\";\n@fa-times-circle-o: \"\\f05c\";\n@fa-check-circle-o: \"\\f05d\";\n@fa-ban: \"\\f05e\";\n@fa-arrow-left: \"\\f060\";\n@fa-arrow-right: \"\\f061\";\n@fa-arrow-up: \"\\f062\";\n@fa-arrow-down: \"\\f063\";\n@fa-share: \"\\f064\";\n@fa-expand: \"\\f065\";\n@fa-compress: \"\\f066\";\n@fa-plus: \"\\f067\";\n@fa-minus: \"\\f068\";\n@fa-asterisk: \"\\f069\";\n@fa-exclamation-circle: \"\\f06a\";\n@fa-gift: \"\\f06b\";\n@fa-leaf: \"\\f06c\";\n@fa-fire: \"\\f06d\";\n@fa-eye: \"\\f06e\";\n@fa-eye-slash: \"\\f070\";\n@fa-exclamation-triangle: \"\\f071\";\n@fa-plane: \"\\f072\";\n@fa-calendar: \"\\f073\";\n@fa-random: \"\\f074\";\n@fa-comment: \"\\f075\";\n@fa-magnet: \"\\f076\";\n@fa-chevron-up: \"\\f077\";\n@fa-chevron-down: \"\\f078\";\n@fa-retweet: \"\\f079\";\n@fa-shopping-cart: \"\\f07a\";\n@fa-folder: \"\\f07b\";\n@fa-folder-open: \"\\f07c\";\n@fa-arrows-v: \"\\f07d\";\n@fa-arrows-h: \"\\f07e\";\n@fa-bar-chart: \"\\f080\";\n@fa-twitter-square: \"\\f081\";\n@fa-facebook-square: \"\\f082\";\n@fa-camera-retro: \"\\f083\";\n@fa-key: \"\\f084\";\n@fa-cogs: \"\\f085\";\n@fa-comments: \"\\f086\";\n@fa-thumbs-o-up: \"\\f087\";\n@fa-thumbs-o-down: \"\\f088\";\n@fa-star-half: \"\\f089\";\n@fa-heart-o: \"\\f08a\";\n@fa-sign-out: \"\\f08b\";\n@fa-linkedin-square: \"\\f08c\";\n@fa-thumb-tack: \"\\f08d\";\n@fa-external-link: \"\\f08e\";\n@fa-sign-in: \"\\f090\";\n@fa-trophy: \"\\f091\";\n@fa-github-square: \"\\f092\";\n@fa-upload: \"\\f093\";\n@fa-lemon-o: \"\\f094\";\n@fa-phone: \"\\f095\";\n@fa-square-o: \"\\f096\";\n@fa-bookmark-o: \"\\f097\";\n@fa-phone-square: \"\\f098\";\n@fa-twitter: \"\\f099\";\n@fa-facebook: \"\\f09a\";\n@fa-github: \"\\f09b\";\n@fa-unlock: \"\\f09c\";\n@fa-credit-card: \"\\f09d\";\n@fa-rss: \"\\f09e\";\n@fa-hdd-o: \"\\f0a0\";\n@fa-bullhorn: \"\\f0a1\";\n@fa-bell: \"\\f0f3\";\n@fa-certificate: \"\\f0a3\";\n@fa-hand-o-right: \"\\f0a4\";\n@fa-hand-o-left: \"\\f0a5\";\n@fa-hand-o-up: \"\\f0a6\";\n@fa-hand-o-down: \"\\f0a7\";\n@fa-arrow-circle-left: \"\\f0a8\";\n@fa-arrow-circle-right: \"\\f0a9\";\n@fa-arrow-circle-up: \"\\f0aa\";\n@fa-arrow-circle-down: \"\\f0ab\";\n@fa-globe: \"\\f0ac\";\n@fa-wrench: \"\\f0ad\";\n@fa-tasks: \"\\f0ae\";\n@fa-filter: \"\\f0b0\";\n@fa-briefcase: \"\\f0b1\";\n@fa-arrows-alt: \"\\f0b2\";\n@fa-users: \"\\f0c0\";\n@fa-link: \"\\f0c1\";\n@fa-cloud: \"\\f0c2\";\n@fa-flask: \"\\f0c3\";\n@fa-scissors: \"\\f0c4\";\n@fa-files-o: \"\\f0c5\";\n@fa-paperclip: \"\\f0c6\";\n@fa-floppy-o: \"\\f0c7\";\n@fa-square: \"\\f0c8\";\n@fa-bars: \"\\f0c9\";\n@fa-list-ul: \"\\f0ca\";\n@fa-list-ol: \"\\f0cb\";\n@fa-strikethrough: \"\\f0cc\";\n@fa-underline: \"\\f0cd\";\n@fa-table: \"\\f0ce\";\n@fa-magic: \"\\f0d0\";\n@fa-truck: \"\\f0d1\";\n@fa-pinterest: \"\\f0d2\";\n@fa-pinterest-square: \"\\f0d3\";\n@fa-google-plus-square: \"\\f0d4\";\n@fa-google-plus: \"\\f0d5\";\n@fa-money: \"\\f0d6\";\n@fa-caret-down: \"\\f0d7\";\n@fa-caret-up: \"\\f0d8\";\n@fa-caret-left: \"\\f0d9\";\n@fa-caret-right: \"\\f0da\";\n@fa-columns: \"\\f0db\";\n@fa-sort: \"\\f0dc\";\n@fa-sort-desc: \"\\f0dd\";\n@fa-sort-asc: \"\\f0de\";\n@fa-envelope: \"\\f0e0\";\n@fa-linkedin: \"\\f0e1\";\n@fa-undo: \"\\f0e2\";\n@fa-gavel: \"\\f0e3\";\n@fa-tachometer: \"\\f0e4\";\n@fa-comment-o: \"\\f0e5\";\n@fa-comments-o: \"\\f0e6\";\n@fa-bolt: \"\\f0e7\";\n@fa-sitemap: \"\\f0e8\";\n@fa-umbrella: \"\\f0e9\";\n@fa-clipboard: \"\\f0ea\";\n@fa-lightbulb-o: \"\\f0eb\";\n@fa-exchange: \"\\f0ec\";\n@fa-cloud-download: \"\\f0ed\";\n@fa-cloud-upload: \"\\f0ee\";\n@fa-user-md: \"\\f0f0\";\n@fa-stethoscope: \"\\f0f1\";\n@fa-suitcase: \"\\f0f2\";\n@fa-bell-o: \"\\f0a2\";\n@fa-coffee: \"\\f0f4\";\n@fa-cutlery: \"\\f0f5\";\n@fa-file-text-o: \"\\f0f6\";\n@fa-building-o: \"\\f0f7\";\n@fa-hospital-o: \"\\f0f8\";\n@fa-ambulance: \"\\f0f9\";\n@fa-medkit: \"\\f0fa\";\n@fa-fighter-jet: \"\\f0fb\";\n@fa-beer: \"\\f0fc\";\n@fa-h-square: \"\\f0fd\";\n@fa-plus-square: \"\\f0fe\";\n@fa-angle-double-left: \"\\f100\";\n@fa-angle-double-right: \"\\f101\";\n@fa-angle-double-up: \"\\f102\";\n@fa-angle-double-down: \"\\f103\";\n@fa-angle-left: \"\\f104\";\n@fa-angle-right: \"\\f105\";\n@fa-angle-up: \"\\f106\";\n@fa-angle-down: \"\\f107\";\n@fa-desktop: \"\\f108\";\n@fa-laptop: \"\\f109\";\n@fa-tablet: \"\\f10a\";\n@fa-mobile: \"\\f10b\";\n@fa-circle-o: \"\\f10c\";\n@fa-quote-left: \"\\f10d\";\n@fa-quote-right: \"\\f10e\";\n@fa-spinner: \"\\f110\";\n@fa-circle: \"\\f111\";\n@fa-reply: \"\\f112\";\n@fa-github-alt: \"\\f113\";\n@fa-folder-o: \"\\f114\";\n@fa-folder-open-o: \"\\f115\";\n@fa-smile-o: \"\\f118\";\n@fa-frown-o: \"\\f119\";\n@fa-meh-o: \"\\f11a\";\n@fa-gamepad: \"\\f11b\";\n@fa-keyboard-o: \"\\f11c\";\n@fa-flag-o: \"\\f11d\";\n@fa-flag-checkered: \"\\f11e\";\n@fa-terminal: \"\\f120\";\n@fa-code: \"\\f121\";\n@fa-reply-all: \"\\f122\";\n@fa-star-half-o: \"\\f123\";\n@fa-location-arrow: \"\\f124\";\n@fa-crop: \"\\f125\";\n@fa-code-fork: \"\\f126\";\n@fa-chain-broken: \"\\f127\";\n@fa-question: \"\\f128\";\n@fa-info: \"\\f129\";\n@fa-exclamation: \"\\f12a\";\n@fa-superscript: \"\\f12b\";\n@fa-subscript: \"\\f12c\";\n@fa-eraser: \"\\f12d\";\n@fa-puzzle-piece: \"\\f12e\";\n@fa-microphone: \"\\f130\";\n@fa-microphone-slash: \"\\f131\";\n@fa-shield: \"\\f132\";\n@fa-calendar-o: \"\\f133\";\n@fa-fire-extinguisher: \"\\f134\";\n@fa-rocket: \"\\f135\";\n@fa-maxcdn: \"\\f136\";\n@fa-chevron-circle-left: \"\\f137\";\n@fa-chevron-circle-right: \"\\f138\";\n@fa-chevron-circle-up: \"\\f139\";\n@fa-chevron-circle-down: \"\\f13a\";\n@fa-html5: \"\\f13b\";\n@fa-css3: \"\\f13c\";\n@fa-anchor: \"\\f13d\";\n@fa-unlock-alt: \"\\f13e\";\n@fa-bullseye: \"\\f140\";\n@fa-ellipsis-h: \"\\f141\";\n@fa-ellipsis-v: \"\\f142\";\n@fa-rss-square: \"\\f143\";\n@fa-play-circle: \"\\f144\";\n@fa-ticket: \"\\f145\";\n@fa-minus-square: \"\\f146\";\n@fa-minus-square-o: \"\\f147\";\n@fa-level-up: \"\\f148\";\n@fa-level-down: \"\\f149\";\n@fa-check-square: \"\\f14a\";\n@fa-pencil-square: \"\\f14b\";\n@fa-external-link-square: \"\\f14c\";\n@fa-share-square: \"\\f14d\";\n@fa-compass: \"\\f14e\";\n@fa-caret-square-o-down: \"\\f150\";\n@fa-caret-square-o-up: \"\\f151\";\n@fa-caret-square-o-right: \"\\f152\";\n@fa-eur: \"\\f153\";\n@fa-gbp: \"\\f154\";\n@fa-usd: \"\\f155\";\n@fa-inr: \"\\f156\";\n@fa-jpy: \"\\f157\";\n@fa-rub: \"\\f158\";\n@fa-krw: \"\\f159\";\n@fa-btc: \"\\f15a\";\n@fa-file: \"\\f15b\";\n@fa-file-text: \"\\f15c\";\n@fa-sort-alpha-asc: \"\\f15d\";\n@fa-sort-alpha-desc: \"\\f15e\";\n@fa-sort-amount-asc: \"\\f160\";\n@fa-sort-amount-desc: \"\\f161\";\n@fa-sort-numeric-asc: \"\\f162\";\n@fa-sort-numeric-desc: \"\\f163\";\n@fa-thumbs-up: \"\\f164\";\n@fa-thumbs-down: \"\\f165\";\n@fa-youtube-square: \"\\f166\";\n@fa-youtube: \"\\f167\";\n@fa-xing: \"\\f168\";\n@fa-xing-square: \"\\f169\";\n@fa-youtube-play: \"\\f16a\";\n@fa-dropbox: \"\\f16b\";\n@fa-stack-overflow: \"\\f16c\";\n@fa-instagram: \"\\f16d\";\n@fa-flickr: \"\\f16e\";\n@fa-adn: \"\\f170\";\n@fa-bitbucket: \"\\f171\";\n@fa-bitbucket-square: \"\\f172\";\n@fa-tumblr: \"\\f173\";\n@fa-tumblr-square: \"\\f174\";\n@fa-long-arrow-down: \"\\f175\";\n@fa-long-arrow-up: \"\\f176\";\n@fa-long-arrow-left: \"\\f177\";\n@fa-long-arrow-right: \"\\f178\";\n@fa-apple: \"\\f179\";\n@fa-windows: \"\\f17a\";\n@fa-android: \"\\f17b\";\n@fa-linux: \"\\f17c\";\n@fa-dribbble: \"\\f17d\";\n@fa-skype: \"\\f17e\";\n@fa-foursquare: \"\\f180\";\n@fa-trello: \"\\f181\";\n@fa-female: \"\\f182\";\n@fa-male: \"\\f183\";\n@fa-gittip: \"\\f184\";\n@fa-sun-o: \"\\f185\";\n@fa-moon-o: \"\\f186\";\n@fa-archive: \"\\f187\";\n@fa-bug: \"\\f188\";\n@fa-vk: \"\\f189\";\n@fa-weibo: \"\\f18a\";\n@fa-renren: \"\\f18b\";\n@fa-pagelines: \"\\f18c\";\n@fa-stack-exchange: \"\\f18d\";\n@fa-arrow-circle-o-right: \"\\f18e\";\n@fa-arrow-circle-o-left: \"\\f190\";\n@fa-caret-square-o-left: \"\\f191\";\n@fa-dot-circle-o: \"\\f192\";\n@fa-wheelchair: \"\\f193\";\n@fa-vimeo-square: \"\\f194\";\n@fa-try: \"\\f195\";\n@fa-plus-square-o: \"\\f196\";\n@fa-space-shuttle: \"\\f197\";\n@fa-slack: \"\\f198\";\n@fa-envelope-square: \"\\f199\";\n@fa-wordpress: \"\\f19a\";\n@fa-openid: \"\\f19b\";\n@fa-university: \"\\f19c\";\n@fa-graduation-cap: \"\\f19d\";\n@fa-yahoo: \"\\f19e\";\n@fa-google: \"\\f1a0\";\n@fa-reddit: \"\\f1a1\";\n@fa-reddit-square: \"\\f1a2\";\n@fa-stumbleupon-circle: \"\\f1a3\";\n@fa-stumbleupon: \"\\f1a4\";\n@fa-delicious: \"\\f1a5\";\n@fa-digg: \"\\f1a6\";\n@fa-pied-piper: \"\\f1a7\";\n@fa-pied-piper-alt: \"\\f1a8\";\n@fa-drupal: \"\\f1a9\";\n@fa-joomla: \"\\f1aa\";\n@fa-language: \"\\f1ab\";\n@fa-fax: \"\\f1ac\";\n@fa-building: \"\\f1ad\";\n@fa-child: \"\\f1ae\";\n@fa-paw: \"\\f1b0\";\n@fa-spoon: \"\\f1b1\";\n@fa-cube: \"\\f1b2\";\n@fa-cubes: \"\\f1b3\";\n@fa-behance: \"\\f1b4\";\n@fa-behance-square: \"\\f1b5\";\n@fa-steam: \"\\f1b6\";\n@fa-steam-square: \"\\f1b7\";\n@fa-recycle: \"\\f1b8\";\n@fa-car: \"\\f1b9\";\n@fa-taxi: \"\\f1ba\";\n@fa-tree: \"\\f1bb\";\n@fa-spotify: \"\\f1bc\";\n@fa-deviantart: \"\\f1bd\";\n@fa-soundcloud: \"\\f1be\";\n@fa-database: \"\\f1c0\";\n@fa-file-pdf-o: \"\\f1c1\";\n@fa-file-word-o: \"\\f1c2\";\n@fa-file-excel-o: \"\\f1c3\";\n@fa-file-powerpoint-o: \"\\f1c4\";\n@fa-file-image-o: \"\\f1c5\";\n@fa-file-archive-o: \"\\f1c6\";\n@fa-file-audio-o: \"\\f1c7\";\n@fa-file-video-o: \"\\f1c8\";\n@fa-file-code-o: \"\\f1c9\";\n@fa-vine: \"\\f1ca\";\n@fa-codepen: \"\\f1cb\";\n@fa-jsfiddle: \"\\f1cc\";\n@fa-life-ring: \"\\f1cd\";\n@fa-circle-o-notch: \"\\f1ce\";\n@fa-rebel: \"\\f1d0\";\n@fa-empire: \"\\f1d1\";\n@fa-git-square: \"\\f1d2\";\n@fa-git: \"\\f1d3\";\n@fa-hacker-news: \"\\f1d4\";\n@fa-tencent-weibo: \"\\f1d5\";\n@fa-qq: \"\\f1d6\";\n@fa-weixin: \"\\f1d7\";\n@fa-paper-plane: \"\\f1d8\";\n@fa-paper-plane-o: \"\\f1d9\";\n@fa-history: \"\\f1da\";\n@fa-circle-thin: \"\\f1db\";\n@fa-header: \"\\f1dc\";\n@fa-paragraph: \"\\f1dd\";\n@fa-sliders: \"\\f1de\";\n@fa-share-alt: \"\\f1e0\";\n@fa-share-alt-square: \"\\f1e1\";\n@fa-bomb: \"\\f1e2\";\n@fa-futbol-o: \"\\f1e3\";\n@fa-tty: \"\\f1e4\";\n@fa-binoculars: \"\\f1e5\";\n@fa-plug: \"\\f1e6\";\n@fa-slideshare: \"\\f1e7\";\n@fa-twitch: \"\\f1e8\";\n@fa-yelp: \"\\f1e9\";\n@fa-newspaper-o: \"\\f1ea\";\n@fa-wifi: \"\\f1eb\";\n@fa-calculator: \"\\f1ec\";\n@fa-paypal: \"\\f1ed\";\n@fa-google-wallet: \"\\f1ee\";\n@fa-cc-visa: \"\\f1f0\";\n@fa-cc-mastercard: \"\\f1f1\";\n@fa-cc-discover: \"\\f1f2\";\n@fa-cc-amex: \"\\f1f3\";\n@fa-cc-paypal: \"\\f1f4\";\n@fa-cc-stripe: \"\\f1f5\";\n@fa-bell-slash: \"\\f1f6\";\n@fa-bell-slash-o: \"\\f1f7\";\n@fa-trash: \"\\f1f8\";\n@fa-copyright: \"\\f1f9\";\n@fa-at: \"\\f1fa\";\n@fa-eyedropper: \"\\f1fb\";\n@fa-paint-brush: \"\\f1fc\";\n@fa-birthday-cake: \"\\f1fd\";\n@fa-area-chart: \"\\f1fe\";\n@fa-pie-chart: \"\\f200\";\n@fa-line-chart: \"\\f201\";\n@fa-lastfm: \"\\f202\";\n@fa-lastfm-square: \"\\f203\";\n@fa-toggle-off: \"\\f204\";\n@fa-toggle-on: \"\\f205\";\n@fa-bicycle: \"\\f206\";\n@fa-bus: \"\\f207\";\n@fa-ioxhost: \"\\f208\";\n@fa-angellist: \"\\f209\";\n@fa-cc: \"\\f20a\";\n@fa-ils: \"\\f20b\";\n@fa-meanpath: \"\\f20c\";\n\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/layui/layuiextend/ztree/css/ztree/awesome/ztree.css",
    "content": "/*-------------------------------------\nzTree Style using fontawesome instead of images\n\nversion:    1.1\nauthor:     Mike King\nemail:      mikkelking @ hotmail . com\nwebsite:    http://code.google.com/p/jquerytree/\n\n-------------------------------------*/\n/* Definitions ----------------------*/\n/* End of Definitions ---------------*/\n/* Imports  -------------------------*/\n/* End of Imports  ------------------*/\n.ztree * {\n  padding: 0;\n  margin: 0;\n  font-size: 12px;\n  font-family: Verdana, Arial, Helvetica, AppleGothic, sans-serif;\n  background-color: #af0000;\n}\n.ztree {\n  margin: 0;\n  padding: 5px;\n  color: #ffffff;\n  background-color: #af0000;\n}\n.ztree li {\n  padding: 0;\n  margin: 0;\n  list-style: none;\n  line-height: 17px;\n  text-align: left;\n  white-space: nowrap;\n  outline: 0;\n}\n.ztree li ul {\n  margin: 0px;\n  padding: 0 0 0 18px;\n}\n.ztree li a {\n  padding-right: 3px;\n  margin: 0;\n  cursor: pointer;\n  height: 17px;\n  color: #ffffff;\n  background-color: transparent;\n  text-decoration: none;\n  vertical-align: top;\n  display: inline-block;\n}\n.ztree li a input.rename {\n  height: 14px;\n  width: 80px;\n  padding: 0;\n  margin: 0;\n  color: #af0000;\n  background-color: #ffffff;\n  font-size: 12px;\n  border: 1px #585956 solid;\n  *border: 0px;\n}\n.ztree li a:hover {\n  text-decoration: underline;\n}\n.ztree li a.curSelectedNode {\n  padding-top: 0px;\n  background-color: #af4040;\n  color: #ffff00;\n  height: 17px;\n  opacity: 0.8;\n}\n.ztree li a.curSelectedNode_Edit {\n  padding-top: 0px;\n  background-color: transparent;\n  color: #ffff00;\n  height: 17px;\n  border: 1px #666 solid;\n  opacity: 0.8;\n}\n.ztree li a.tmpTargetNode_inner {\n  padding-top: 0px;\n  background-color: #aaa;\n  color: #ffff00;\n  height: 17px;\n  border: 1px #666 solid;\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n.ztree li span {\n  line-height: 17px;\n  margin-right: 2px;\n  background-color: transparent;\n}\n.ztree li span.button {\n  line-height: 0;\n  margin: 0;\n  padding: 0;\n  width: 15px;\n  height: 17px;\n  display: inline-block;\n  vertical-align: top;\n  border: 0px solid;\n  cursor: pointer;\n  outline: none;\n  background-color: transparent;\n  background-repeat: no-repeat;\n  background-attachment: scroll;\n}\n.ztree li span.button::before {\n  color: #ffffff;\n  font-family: FontAwesome;\n  padding-top: 10px;\n}\n.ztree li span.button.chk {\n  margin: 0px;\n  cursor: auto;\n  width: 12px;\n  display: inline-block;\n  padding-top: 10px;\n  padding-left: 2px;\n}\n.ztree li span.button.chk.checkbox_false_full::before {\n  content: \"\\f096\";\n}\n.ztree li span.button.chk.checkbox_false_full_focus::before {\n  content: \"\\f096\";\n  color: #ffff00;\n}\n.ztree li span.button.chk.checkbox_false_part::before {\n  content: \"\\f096\";\n  color: #aaaaaa;\n}\n.ztree li span.button.chk.checkbox_false_part_focus::before {\n  content: \"\\f096\";\n  color: #cad96c;\n}\n.ztree li span.button.chk.checkbox_false_disable::before {\n  content: \"\\f096\";\n  color: #808080;\n}\n.ztree li span.button.chk.checkbox_true_full::before {\n  content: \"\\f046\";\n}\n.ztree li span.button.chk.checkbox_true_full_focus::before {\n  content: \"\\f046\";\n}\n.ztree li span.button.chk.checkbox_true_part::before {\n  content: \"\\f14a\";\n}\n.ztree li span.button.chk.checkbox_true_part_focus::before {\n  content: \"\\f14a\";\n  color: #ffff00;\n}\n.ztree li span.button.chk.checkbox_true_full_focus::before {\n  content: \"\\f046\";\n  color: #ffff00;\n}\n.ztree li span.button.chk.checkbox_true_part::before {\n  content: \"\\f046\";\n  color: #aaaaaa;\n}\n.ztree li span.button.chk.checkbox_true_part_focus::before {\n  content: \"\\f046\";\n  color: #cad96c;\n}\n.ztree li span.button.chk.checkbox_true_disable::before {\n  content: \"\\f046\";\n  color: #808080;\n}\n.ztree li span.button.chk.radio_false_full::before {\n  content: \"\\f10c\";\n}\n.ztree li span.button.chk.radio_false_full_focus::before {\n  content: \"\\f10c\";\n  color: #ffff00;\n}\n.ztree li span.button.chk.radio_false_part::before {\n  content: \"\\f10c\";\n  color: #aaaaaa;\n}\n.ztree li span.button.chk.radio_false_part_focus::before {\n  content: \"\\f10c\";\n  color: #ffff00;\n}\n.ztree li span.button.chk.radio_false_disable::before {\n  content: \"\\f1db\";\n  color: #808080;\n}\n.ztree li span.button.chk.radio_true_full::before {\n  content: \"\\f192\";\n}\n.ztree li span.button.chk.radio_true_full_focus::before {\n  content: \"\\f192\";\n  color: #ffff00;\n}\n.ztree li span.button.chk.radio_true_part::before {\n  content: \"\\f192\";\n  color: #aaaaaa;\n}\n.ztree li span.button.chk.radio_true_part_focus::before {\n  content: \"\\f192\";\n  color: #aaaaaa;\n}\n.ztree li span.button.chk.radio_true_disable::before {\n  content: \"\\f1db\";\n  color: #808080;\n}\n.ztree li span.button.switch {\n  width: 15px;\n  height: 17px;\n}\n.ztree li span.button.root_open::before {\n  content: \"\\f078\";\n  padding-top: 10px;\n  padding-left: 2px;\n  display: inline-block;\n}\n.ztree li span.button.root_close::before {\n  content: \"\\f115\";\n  padding-top: 10px;\n  padding-left: 2px;\n  display: inline-block;\n}\n.ztree li span.button.roots_open::before {\n  content: \"\\f078\";\n  padding-top: 10px;\n  padding-left: 2px;\n  display: inline-block;\n}\n.ztree li span.button.roots_close::before {\n  content: \"\\f054\";\n  padding-top: 10px;\n  padding-left: 2px;\n  display: inline-block;\n}\n.ztree li span.button.center_open::before {\n  content: \"\\f078\";\n  padding-top: 10px;\n  padding-left: 2px;\n  display: inline-block;\n}\n.ztree li span.button.center_close::before {\n  content: \"\\f054\";\n  padding-top: 10px;\n  padding-left: 2px;\n  display: inline-block;\n}\n.ztree li span.button.bottom_open::before {\n  content: \"\\f078\";\n  padding-top: 10px;\n  padding-left: 2px;\n  display: inline-block;\n}\n.ztree li span.button.bottom_close::before {\n  content: \"\\f054\";\n  padding-top: 10px;\n  padding-left: 2px;\n  display: inline-block;\n}\n.ztree li span.button.root_docu {\n  background: none;\n}\n.ztree li span.button.roots_docu::before {\n  content: \"\\f022\";\n  padding-left: 2px;\n  display: inline-block;\n  color: #ffffff;\n}\n.ztree li span.button.center_docu::before {\n  padding-top: 10px;\n  padding-left: 2px;\n  display: inline-block;\n  color: #ffffff;\n}\n.ztree li span.button.bottom_docu::before {\n  padding-top: 10px;\n  padding-left: 2px;\n  display: inline-block;\n  color: #ffffff;\n}\n.ztree li span.button.noline_docu {\n  background: none;\n}\n.ztree li span.button.ico_open::before {\n  content: \"\\f115\";\n  font-family: FontAwesome;\n  padding-top: 10px;\n  padding-left: 2px;\n  display: inline-block;\n  color: #ffffff;\n}\n.ztree li span.button.ico_close::before {\n  content: \"\\f114\";\n  font-family: FontAwesome;\n  padding-top: 10px;\n  padding-left: 2px;\n  display: inline-block;\n  color: #ffffff;\n}\n.ztree li span.button.ico_docu::before {\n  content: \"\\f022\";\n  font-family: FontAwesome;\n  padding-top: 10px;\n  padding-left: 2px;\n  display: inline-block;\n  color: #ffffff;\n}\n.ztree li span.button.edit {\n  margin-left: 4px;\n  margin-right: -1px;\n  vertical-align: top;\n  *vertical-align: middle;\n  padding-top: 10px;\n}\n.ztree li span.button.edit::before {\n  content: \"\\f044\";\n  font-family: FontAwesome;\n}\n.ztree li span.button.remove {\n  margin-left: 4px;\n  margin-right: -1px;\n  vertical-align: top;\n  *vertical-align: middle;\n  padding-top: 10px;\n}\n.ztree li span.button.remove::before {\n  content: \"\\f1f8\";\n  font-family: FontAwesome;\n}\n.ztree li span.button.add {\n  margin-left: 4px;\n  margin-right: -1px;\n  vertical-align: top;\n  *vertical-align: middle;\n  padding-top: 10px;\n}\n.ztree li span.button.add::before {\n  content: \"\\f067\";\n  font-family: FontAwesome;\n}\n.ztree li span.button.ico_loading {\n  margin-right: 2px;\n  background: url(img/loading.gif) no-repeat scroll 0 0 transparent;\n  vertical-align: top;\n  *vertical-align: middle;\n}\nul.tmpTargetzTree {\n  background-color: #FFE6B0;\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\nspan.tmpzTreeMove_arrow {\n  width: 16px;\n  height: 17px;\n  display: inline-block;\n  padding: 0;\n  margin: 2px 0 0 1px;\n  border: 0 none;\n  position: absolute;\n  background-color: transparent;\n  background-attachment: scroll;\n}\nspan.tmpzTreeMove_arrow::before {\n  content: \"\\f04b\";\n  font-family: FontAwesome;\n  color: #ffff00;\n}\nul.ztree.zTreeDragUL {\n  margin: 0;\n  padding: 0;\n  position: absolute;\n  width: auto;\n  height: auto;\n  overflow: hidden;\n  background-color: #cfcfcf;\n  border: 1px #ffff00 dotted;\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n.ztreeMask {\n  z-index: 10000;\n  background-color: #cfcfcf;\n  opacity: 0.0;\n  filter: alpha(opacity=0);\n  position: absolute;\n}\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/layui/layuiextend/ztree/css/ztree/awesome/ztree.less",
    "content": "/*-------------------------------------\nzTree Style using fontawesome instead of images\n\nversion:    1.1\nauthor:     Mike King\nemail:      mikkelking @ hotmail . com\nwebsite:    http://code.google.com/p/jquerytree/\n\n-------------------------------------*/\n\n/* Definitions ----------------------*/\n@font-size: 12px;\n// Regular icon and text color is white, which suits any medium -> dark background \n@color-normal: white;\n// Background color\n@color-bg: #af0000;\n// Highlight color\n@color-highlight: yellow;\n// Partially selected (checkboxes, radio buttons)\n@color-partial: #aaaaaa;\n// Partially selected and focused (checkboxes, radio buttons)\n@color-partfocus: #cad96c;\n// Disabled altogether\n@color-disabled: #808080;\n// Editing color\n@color-edit: yellow;\n@w: 15px;\n@h: 17px;\n@pad-left: 2px;\n@pad-top: 10px;\n/* End of Definitions ---------------*/\n\n/* Imports  -------------------------*/\n@import \"fa.less\";\n/* End of Imports  ------------------*/\n\n.ztree * {padding:0; margin:0; font-size:@font-size; font-family: Verdana, Arial, Helvetica, AppleGothic, sans-serif; background-color: @color-bg;}\n.ztree {\n    margin:0; padding:5px; color:@color-normal; background-color: @color-bg;\n    li {\n        padding:0; margin:0; list-style:none; line-height:17px; text-align:left; white-space:nowrap; outline:0;\n        ul { \n            margin: 0px; padding:0 0 0 18px;\n        }\n        ul.line { }\n        a {padding-right:3px; margin:0; cursor:pointer; height:@h; color:@color-normal; background-color: transparent; \n            text-decoration:none; vertical-align:top; display: inline-block;\n            input.rename {height:14px; width:80px; padding:0; margin:0;\n                          color: @color-bg; background-color: @color-normal;\n                        font-size:@font-size; border:1px #585956 solid; *border:0px}\n        }\n        a:hover {text-decoration:underline}\n        a.curSelectedNode {padding-top:0px; background-color:#af4040; color:@color-highlight; height:@h; opacity:0.8;}\n        a.curSelectedNode_Edit {padding-top:0px; background-color:transparent; color:@color-highlight; height:@h; border:1px #666 solid; opacity:0.8;}\n        a.tmpTargetNode_inner {padding-top:0px; background-color:#aaa; color:@color-highlight; height:@h; border:1px #666 solid;\n          opacity:0.8; filter:alpha(opacity=80)}\n        a.tmpTargetNode_prev {}\n        a.tmpTargetNode_next {}\n        span {line-height:@h; margin-right:2px; background-color:transparent;}\n        span.button {line-height:0; margin:0; padding: 0; width:@w; height:@h; display: inline-block; vertical-align:top;\n          border:0px solid; cursor: pointer;outline:none;\n          background-color:transparent; background-repeat:no-repeat; background-attachment: scroll;\n \n            &::before{color: @color-normal; font-family: FontAwesome; padding-top:@pad-top;}\n            &.chk { margin:0px; cursor: auto; width: 12px;\n                display: inline-block;padding-top:@pad-top;padding-left:@pad-left;\n                \n                &.checkbox_false_full::before {content: @fa-square-o;}\n                &.checkbox_false_full_focus::before {content: @fa-square-o; color:@color-highlight;}\n                &.checkbox_false_part::before {content: @fa-square-o;color: @color-partial;}\n                &.checkbox_false_part_focus::before {content: @fa-square-o; color:@color-partfocus;}\n                &.checkbox_false_disable::before {content: @fa-square-o; color:@color-disabled;}\n                &.checkbox_true_full::before {content: @fa-check-square-o;}\n                &.checkbox_true_full_focus::before {content: @fa-check-square-o;}\n                &.checkbox_true_part::before {content: @fa-check-square;}\n                &.checkbox_true_part_focus::before {content: @fa-check-square; color: @color-highlight}\n                &.checkbox_true_full_focus::before {content: @fa-check-square-o; color: @color-highlight}\n                &.checkbox_true_part::before {content: @fa-check-square-o;color: @color-partial}\n                &.checkbox_true_part_focus::before {content: @fa-check-square-o;color: @color-partfocus;}\n                &.checkbox_true_disable::before {content: @fa-check-square-o;color: @color-disabled}\n                 \n                &.radio_false_full::before {content: @fa-circle-o;}\n                &.radio_false_full_focus::before {content: @fa-circle-o;color: @color-highlight}\n                &.radio_false_part::before {content: @fa-circle-o;color: @color-partial}\n                &.radio_false_part_focus::before {content: @fa-circle-o;color: @color-highlight}\n                &.radio_false_disable::before {content: @fa-circle-thin;color: @color-disabled}\n                &.radio_true_full::before {content: @fa-dot-circle-o;}\n                &.radio_true_full_focus::before {content: @fa-dot-circle-o;color: @color-highlight}\n                &.radio_true_part::before {content: @fa-dot-circle-o;color: @color-partial}\n                &.radio_true_part_focus::before {content: @fa-dot-circle-o;color: @color-partial;}\n                &.radio_true_disable::before {content: @fa-circle-thin;color: @color-disabled}\n                \n            }\n            &.switch  {width:@w; height:@h}\n            &.root_open::before{content: @fa-chevron-down;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;}\n            &.root_close::before{content: @fa-folder-open-o;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;}\n            &.roots_open::before{content: @fa-chevron-down;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;}\n            &.roots_close::before{content: @fa-chevron-right;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;}\n            &.center_open::before{content: @fa-chevron-down;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;}\n            &.center_close::before{content: @fa-chevron-right;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;}\n            &.bottom_open::before{content: @fa-chevron-down;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;}\n            &.bottom_close::before{content: @fa-chevron-right;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;}  \n            &.noline_open{}\n            &.noline_close{}\n            &.root_docu{ background:none;}\n            &.roots_docu::before{content: @fa-list-alt;padding-left:@pad-left;display: inline-block;color:@color-normal;}\n            &.center_docu::before{padding-top:@pad-top;padding-left:@pad-left;display: inline-block;color:@color-normal;}\n            &.bottom_docu::before{padding-top:@pad-top;padding-left:@pad-left;display: inline-block;color:@color-normal;}\n            &.noline_docu{ background:none;}\n    \n            &.ico_open::before {content: @fa-folder-open-o;font-family: FontAwesome;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;color:@color-normal;}\n            &.ico_close::before {content: @fa-folder-o;font-family: FontAwesome;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;color:@color-normal;}\n            &.ico_docu::before{content: @fa-list-alt;font-family: FontAwesome;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;color:@color-normal;}\n            \n            &.edit {margin-left:4px; margin-right: -1px;  vertical-align:top; *vertical-align:middle;padding-top:@pad-top;}\n            &.edit::before{content: @fa-pencil-square-o;font-family: FontAwesome;}\n    \n            &.remove {margin-left:4px; margin-right: -1px;  vertical-align:top; *vertical-align:middle;padding-top:@pad-top;}\n            &.remove::before{content: @fa-trash;font-family: FontAwesome;}\n\n    \n            &.add {margin-left:4px; margin-right: -1px; vertical-align:top; *vertical-align:middle;padding-top:@pad-top;}\n            &.add::before{content: @fa-plus;font-family: FontAwesome;}\n\n            &.ico_loading{margin-right:2px; background:url(img/loading.gif) no-repeat scroll 0 0 transparent; vertical-align:top; *vertical-align:middle}\n        }\n\n    }\n}\n\n\nul.tmpTargetzTree {background-color:#FFE6B0; opacity:0.8; filter:alpha(opacity=80)}\n\n// this is the arrow that moves \nspan.tmpzTreeMove_arrow{width:16px; height:@h; display: inline-block; \n                                padding:0; margin:2px 0 0 1px; border:0 none; position:absolute;\n                                background-color:transparent;  background-attachment: scroll;\n                                 }\nspan.tmpzTreeMove_arrow::before{content: @fa-play;font-family: FontAwesome;color: @color-highlight;\n                                 }\n// outline\n\nul.ztree.zTreeDragUL {margin:0; padding:0; position:absolute; width:auto; height:auto;overflow:hidden; \n             background-color:#cfcfcf; border:1px @color-highlight 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"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/layui/layuiextend/ztree/css/ztree/default/ztree.css",
    "content": "/*-------------------------------------\nzTree Style\n\nversion:\t3.5.19\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": "open-layui-web/src/main/view/static/lib/layui/layuiextend/ztree/css/ztree/metro/ztree.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:16px; 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.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"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/layui/layuiextend/ztree/js/treeselect.js",
    "content": "//treeSelect组件\nlayui.define(['layer', 'ztree'], function(exports) {\n  var _MOD = 'treeselect',\n    layer = layui.layer,\n    $ = layui.jquery;\n  var TreeSelect = function() {\n    this.v = '1.0.0';\n  };\n  /**\n   * 渲染treeSelect\n   */\n  TreeSelect.prototype.render = function(options) {\n    var that = this;\n    // 设置可参考ztree.js配置 URL:http://www.treejs.cn/v3/api.php\n    var setting = {\n      check: {\n        enable: true,\n        chkboxType: {\n          \"Y\": \"\",\n          \"N\": \"\"\n        }\n      },\n      view: {\n        dblClickExpand: false\n      },\n      data: {\n        simpleData: {\n          enable: true\n        }\n      },\n      callback: {\n        // ztree 点击前发生\n        beforeClick: function(treeId, treeNode) {\n          var zTree = $.fn.zTree.getZTreeObj(treeId);\n          zTree.checkNode(treeNode, !treeNode.checked, null, true);\n        },\n        // ztree 点击时发生\n        onClick: onClick,\n        onCheck: onClick\n      }\n    };\n    // 获取当前时间戳\n    var times = new Date().getTime();\n    var eId = 'content' + times;\n    var treeDOMId = 'treeDemo' + times;\n    // 创建DOM\n    $(options.elem)\n      .parent()\n      .append('<div class=\"ztree-input\" id=\"' + options.elem.substr(1) + '\"></div>')\n      .append(['<div id=\"' + eId + '\" class=\"ztree-content layui-anim layui-anim-upbit\">',\n        '<ul id=\"treeDemo' + times + '\" class=\"ztree\"></ul>',\n        '</div>'\n      ].join(''))\n      .children('input.layui-input').removeAttr('id');\n    // 初始化zTree\n    var zTree = $.fn.zTree.init($('#' + treeDOMId), setting, options.data);\n    // 获取所有节点\n    var nodes = zTree.getNodes();\n    // 获取初始值\n    var vals = $(options.elem).parent().children('input.layui-input').val();\n    if ($.trim(vals).length > 0) {\n      initNode(nodes);\n    }\n    // 初始化数据\n    function initNode(nodes) {\n      for (var i = 0, l = nodes.length; i < l; i++) {\n        var node = nodes[i];\n        if (findArray(vals.split(','), node.id) !== -1) {\n          zTree.checkNode(node, true, false);\n          $(options.elem).append([\n            '<a href=\"javascript:;\">',\n            node.name,\n            ' <i class=\"layui-icon\" data-action=\"close\" data-tid=\"' + node.tId + '\" data-id=\"' + node.id + '\">&#x1006;</i>',\n            '</a>'\n          ].join(''));\n          _bindCloseEvent();\n        }\n        if (node.children !== null && node.children !== undefined && node.children.length > 0) {\n          // 递归调用\n          initNode(node.children);\n        }\n      }\n    };\n    //点击事件的处理\n    function onClick(e, treeId, treeNode) {\n      var zTree = $.fn.zTree.getZTreeObj(treeId),\n        nodes = zTree.getCheckedNodes(true), //获取选中的节点\n        valIds = [],\n        arr = [];\n      for (var i = 0, l = nodes.length; i < l; i++) {\n        valIds.push(nodes[i].id);\n        arr.push({\n          name: nodes[i].name,\n          id: nodes[i].id,\n          tid: nodes[i].tId\n        });\n      }\n      _div = $(options.elem);\n      var _htm = [];\n      layui.each(arr, function(index, item) {\n        _htm.push([\n          '<a href=\"javascript:;\">',\n          item.name,\n          ' <i class=\"layui-icon\" data-action=\"close\" data-tid=\"' + item.tid + '\" data-id=\"' + item.id + '\">&#x1006;</i>',\n          '</a>'\n        ].join(''));\n      });\n      _div.html(_htm.join(''));\n      //给input 赋值\n      var _input = _div.siblings('input.layui-input');\n      _input.attr(\"value\", valIds.join(','));\n      _bindCloseEvent();\n    }\n    // input 框点击事件\n    $(options.elem).off('click').on('click', function() {\n      $(\"#\" + eId).show();\n      $(document).off('mousedown').on(\"mousedown\", function(event) {\n        if (!('#' + event.target.id == options.elem || event.target.id == eId || $(event.target).parents('#' + eId).length > 0)) {\n          // 隐藏ztree\n          $(\"#\" + eId).fadeOut('fast');\n        }\n      });\n    });\n    /**\n     * 绑定删除按钮事件\n     */\n    function _bindCloseEvent() {\n      var _div = $(options.elem),\n        _input = _div.siblings('input.layui-input');\n      _div.find('i[data-action=close]').off('click').on('click', function(e) {\n        layui.stope(e);\n        // 获取id\n        var id = $(this).data('id');\n        // 获取tid\n        var tid = $(this).data('tid');\n        // 处理节点显示\n        var node = zTree.getNodeByTId(tid);\n        // 将对应的ztree节点的check取消选中\n        zTree.checkNode(node, false, false);\n        // 处理input 值\n        var inputs = _input.val().split(',');\n        // 移除当前所选值Id\n        inputs.remove(id);\n        // 重新辅助\n        _input.attr('value', inputs.join(','));\n        // 移除截元素\n        $(this).parent().remove();\n      });\n    }\n    return that;\n  };\n\n\n  // Array 扩展\n  Array.prototype.indexOf = function(val) {\n    for (var i = 0; i < this.length; i++) {\n      if (this[i] == val) return i;\n    }\n    return -1;\n  };\n  // 移除指定值\n  Array.prototype.remove = function(val) {\n    var index = this.indexOf(val);\n    if (index > -1) {\n      this.splice(index, 1);\n    }\n  };\n  /**\n   * \n   * 查找数组，返回匹配到的第一个index\n   * \n   * @param array 被查找的数组\n   * @param feature 查找特征 或者为一个具体值，用于匹配数组遍历的值，或者为一个对象，表明所有希望被匹配的key-value\n   * @param or boolean 希望命中feature全部特征或者只需命中一个特征，默认true\n   * \n   * @return 数组下标  查找不到返回-1\n   */\n  function findArray(array, feature, all) {\n    all = all || true;\n    for (var index in array) {\n      var cur = array[index];\n      if (feature instanceof Object) {\n        var allRight = true;\n        for (var key in feature) {\n          var value = feature[key];\n          if (cur[key] == value && !all) return index;\n          if (all && cur[key] != value) {\n            allRight = false;\n            break;\n          }\n        }\n        if (allRight) return index;\n      } else {\n        if (cur == feature) {\n          return index;\n        }\n      }\n    }\n    return -1;\n  };\n  // 导出组件\n  exports(_MOD, new TreeSelect());\n});"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/layui/layuiextend/ztree/js/ztree.js",
    "content": "layui.define(['jquery'], function(exports) {\n    var jQuery = layui.jquery;\n\n\n    /*\n     * JQuery zTree core v3.5.29\n     * http://treejs.cn/\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: 2017-06-19\n     */\n    (function($) {\n        var settings = {},\n            roots = {},\n            caches = {},\n            //default consts of core\n            _consts = {\n                className: {\n                    BUTTON: \"button\",\n                    LEVEL: \"level\",\n                    ICO_LOADING: \"ico_loading\",\n                    SWITCH: \"switch\",\n                    NAME: 'node_name'\n                },\n                event: {\n                    NODECREATED: \"ztree_nodeCreated\",\n                    CLICK: \"ztree_click\",\n                    EXPAND: \"ztree_expand\",\n                    COLLAPSE: \"ztree_collapse\",\n                    ASYNC_SUCCESS: \"ztree_async_success\",\n                    ASYNC_ERROR: \"ztree_async_error\",\n                    REMOVE: \"ztree_remove\",\n                    SELECTED: \"ztree_selected\",\n                    UNSELECTED: \"ztree_unselected\"\n                },\n                id: {\n                    A: \"_a\",\n                    ICON: \"_ico\",\n                    SPAN: \"_span\",\n                    SWITCH: \"_switch\",\n                    UL: \"_ul\"\n                },\n                line: {\n                    ROOT: \"root\",\n                    ROOTS: \"roots\",\n                    CENTER: \"center\",\n                    BOTTOM: \"bottom\",\n                    NOLINE: \"noline\",\n                    LINE: \"line\"\n                },\n                folder: {\n                    OPEN: \"open\",\n                    CLOSE: \"close\",\n                    DOCU: \"docu\"\n                },\n                node: {\n                    CURSELECTED: \"curSelectedNode\"\n                }\n            },\n            //default setting of core\n            _setting = {\n                treeId: \"\",\n                treeObj: null,\n                view: {\n                    addDiyDom: null,\n                    autoCancelSelected: true,\n                    dblClickExpand: true,\n                    expandSpeed: \"fast\",\n                    fontCss: {},\n                    nameIsHTML: false,\n                    selectedMulti: true,\n                    showIcon: true,\n                    showLine: true,\n                    showTitle: true,\n                    txtSelectedEnable: false\n                },\n                data: {\n                    key: {\n                        children: \"children\",\n                        name: \"name\",\n                        title: \"\",\n                        url: \"url\",\n                        icon: \"icon\"\n                    },\n                    simpleData: {\n                        enable: false,\n                        idKey: \"id\",\n                        pIdKey: \"pId\",\n                        rootPId: null\n                    },\n                    keep: {\n                        parent: false,\n                        leaf: false\n                    }\n                },\n                async: {\n                    enable: false,\n                    contentType: \"application/x-www-form-urlencoded\",\n                    type: \"post\",\n                    dataType: \"text\",\n                    url: \"\",\n                    autoParam: [],\n                    otherParam: [],\n                    dataFilter: null\n                },\n                callback: {\n                    beforeAsync: null,\n                    beforeClick: null,\n                    beforeDblClick: null,\n                    beforeRightClick: null,\n                    beforeMouseDown: null,\n                    beforeMouseUp: null,\n                    beforeExpand: null,\n                    beforeCollapse: null,\n                    beforeRemove: null,\n\n                    onAsyncError: null,\n                    onAsyncSuccess: null,\n                    onNodeCreated: null,\n                    onClick: null,\n                    onDblClick: null,\n                    onRightClick: null,\n                    onMouseDown: null,\n                    onMouseUp: null,\n                    onExpand: null,\n                    onCollapse: null,\n                    onRemove: null\n                }\n            },\n            //default root of core\n            //zTree use root to save full data\n            _initRoot = function(setting) {\n                var r = data.getRoot(setting);\n                if (!r) {\n                    r = {};\n                    data.setRoot(setting, r);\n                }\n                r[setting.data.key.children] = [];\n                r.expandTriggerFlag = false;\n                r.curSelectedList = [];\n                r.noSelection = true;\n                r.createdNodes = [];\n                r.zId = 0;\n                r._ver = (new Date()).getTime();\n            },\n            //default cache of core\n            _initCache = function(setting) {\n                var c = data.getCache(setting);\n                if (!c) {\n                    c = {};\n                    data.setCache(setting, c);\n                }\n                c.nodes = [];\n                c.doms = [];\n            },\n            //default bindEvent of core\n            _bindEvent = function(setting) {\n                var o = setting.treeObj,\n                    c = consts.event;\n                o.bind(c.NODECREATED, function(event, treeId, node) {\n                    tools.apply(setting.callback.onNodeCreated, [event, treeId, node]);\n                });\n\n                o.bind(c.CLICK, function(event, srcEvent, treeId, node, clickFlag) {\n                    tools.apply(setting.callback.onClick, [srcEvent, treeId, node, clickFlag]);\n                });\n\n                o.bind(c.EXPAND, function(event, treeId, node) {\n                    tools.apply(setting.callback.onExpand, [event, treeId, node]);\n                });\n\n                o.bind(c.COLLAPSE, function(event, treeId, node) {\n                    tools.apply(setting.callback.onCollapse, [event, treeId, node]);\n                });\n\n                o.bind(c.ASYNC_SUCCESS, function(event, treeId, node, msg) {\n                    tools.apply(setting.callback.onAsyncSuccess, [event, treeId, node, msg]);\n                });\n\n                o.bind(c.ASYNC_ERROR, function(event, treeId, node, XMLHttpRequest, textStatus, errorThrown) {\n                    tools.apply(setting.callback.onAsyncError, [event, treeId, node, XMLHttpRequest, textStatus, errorThrown]);\n                });\n\n                o.bind(c.REMOVE, function(event, treeId, treeNode) {\n                    tools.apply(setting.callback.onRemove, [event, treeId, treeNode]);\n                });\n\n                o.bind(c.SELECTED, function(event, treeId, node) {\n                    tools.apply(setting.callback.onSelected, [treeId, node]);\n                });\n                o.bind(c.UNSELECTED, function(event, treeId, node) {\n                    tools.apply(setting.callback.onUnSelected, [treeId, node]);\n                });\n            },\n            _unbindEvent = function(setting) {\n                var o = setting.treeObj,\n                    c = consts.event;\n                o.unbind(c.NODECREATED)\n                    .unbind(c.CLICK)\n                    .unbind(c.EXPAND)\n                    .unbind(c.COLLAPSE)\n                    .unbind(c.ASYNC_SUCCESS)\n                    .unbind(c.ASYNC_ERROR)\n                    .unbind(c.REMOVE)\n                    .unbind(c.SELECTED)\n                    .unbind(c.UNSELECTED);\n            },\n            //default event proxy of core\n            _eventProxy = function(event) {\n                var target = event.target,\n                    setting = data.getSetting(event.data.treeId),\n                    tId = \"\",\n                    node = null,\n                    nodeEventType = \"\",\n                    treeEventType = \"\",\n                    nodeEventCallback = null,\n                    treeEventCallback = null,\n                    tmp = null;\n\n                if (tools.eqs(event.type, \"mousedown\")) {\n                    treeEventType = \"mousedown\";\n                } else if (tools.eqs(event.type, \"mouseup\")) {\n                    treeEventType = \"mouseup\";\n                } else if (tools.eqs(event.type, \"contextmenu\")) {\n                    treeEventType = \"contextmenu\";\n                } else if (tools.eqs(event.type, \"click\")) {\n                    if (tools.eqs(target.tagName, \"span\") && target.getAttribute(\"treeNode\" + consts.id.SWITCH) !== null) {\n                        tId = tools.getNodeMainDom(target).id;\n                        nodeEventType = \"switchNode\";\n                    } else {\n                        tmp = tools.getMDom(setting, target, [{ tagName: \"a\", attrName: \"treeNode\" + consts.id.A }]);\n                        if (tmp) {\n                            tId = tools.getNodeMainDom(tmp).id;\n                            nodeEventType = \"clickNode\";\n                        }\n                    }\n                } else if (tools.eqs(event.type, \"dblclick\")) {\n                    treeEventType = \"dblclick\";\n                    tmp = tools.getMDom(setting, target, [{ tagName: \"a\", attrName: \"treeNode\" + consts.id.A }]);\n                    if (tmp) {\n                        tId = tools.getNodeMainDom(tmp).id;\n                        nodeEventType = \"switchNode\";\n                    }\n                }\n                if (treeEventType.length > 0 && tId.length == 0) {\n                    tmp = tools.getMDom(setting, target, [{ tagName: \"a\", attrName: \"treeNode\" + consts.id.A }]);\n                    if (tmp) {\n                        tId = tools.getNodeMainDom(tmp).id;\n                    }\n                }\n                // event to node\n                if (tId.length > 0) {\n                    node = data.getNodeCache(setting, tId);\n                    switch (nodeEventType) {\n                        case \"switchNode\":\n                            if (!node.isParent) {\n                                nodeEventType = \"\";\n                            } else if (tools.eqs(event.type, \"click\") ||\n                                (tools.eqs(event.type, \"dblclick\") && tools.apply(setting.view.dblClickExpand, [setting.treeId, node], setting.view.dblClickExpand))) {\n                                nodeEventCallback = handler.onSwitchNode;\n                            } else {\n                                nodeEventType = \"\";\n                            }\n                            break;\n                        case \"clickNode\":\n                            nodeEventCallback = handler.onClickNode;\n                            break;\n                    }\n                }\n                // event to zTree\n                switch (treeEventType) {\n                    case \"mousedown\":\n                        treeEventCallback = handler.onZTreeMousedown;\n                        break;\n                    case \"mouseup\":\n                        treeEventCallback = handler.onZTreeMouseup;\n                        break;\n                    case \"dblclick\":\n                        treeEventCallback = handler.onZTreeDblclick;\n                        break;\n                    case \"contextmenu\":\n                        treeEventCallback = handler.onZTreeContextmenu;\n                        break;\n                }\n                var proxyResult = {\n                    stop: false,\n                    node: node,\n                    nodeEventType: nodeEventType,\n                    nodeEventCallback: nodeEventCallback,\n                    treeEventType: treeEventType,\n                    treeEventCallback: treeEventCallback\n                };\n                return proxyResult\n            },\n            //default init node of core\n            _initNode = function(setting, level, n, parentNode, isFirstNode, isLastNode, openFlag) {\n                if (!n) return;\n                var r = data.getRoot(setting),\n                    childKey = setting.data.key.children;\n                n.level = level;\n                n.tId = setting.treeId + \"_\" + (++r.zId);\n                n.parentTId = parentNode ? parentNode.tId : null;\n                n.open = (typeof n.open == \"string\") ? tools.eqs(n.open, \"true\") : !!n.open;\n                if (n[childKey] && n[childKey].length > 0) {\n                    n.isParent = true;\n                    n.zAsync = true;\n                } else {\n                    n.isParent = (typeof n.isParent == \"string\") ? tools.eqs(n.isParent, \"true\") : !!n.isParent;\n                    n.open = (n.isParent && !setting.async.enable) ? n.open : false;\n                    n.zAsync = !n.isParent;\n                }\n                n.isFirstNode = isFirstNode;\n                n.isLastNode = isLastNode;\n                n.getParentNode = function() {\n                    return data.getNodeCache(setting, n.parentTId);\n                };\n                n.getPreNode = function() {\n                    return data.getPreNode(setting, n);\n                };\n                n.getNextNode = function() {\n                    return data.getNextNode(setting, n);\n                };\n                n.getIndex = function() {\n                    return data.getNodeIndex(setting, n);\n                };\n                n.getPath = function() {\n                    return data.getNodePath(setting, n);\n                };\n                n.isAjaxing = false;\n                data.fixPIdKeyValue(setting, n);\n            },\n            _init = {\n                bind: [_bindEvent],\n                unbind: [_unbindEvent],\n                caches: [_initCache],\n                nodes: [_initNode],\n                proxys: [_eventProxy],\n                roots: [_initRoot],\n                beforeA: [],\n                afterA: [],\n                innerBeforeA: [],\n                innerAfterA: [],\n                zTreeTools: []\n            },\n            //method of operate data\n            data = {\n                addNodeCache: function(setting, node) {\n                    data.getCache(setting).nodes[data.getNodeCacheId(node.tId)] = node;\n                },\n                getNodeCacheId: function(tId) {\n                    return tId.substring(tId.lastIndexOf(\"_\") + 1);\n                },\n                addAfterA: function(afterA) {\n                    _init.afterA.push(afterA);\n                },\n                addBeforeA: function(beforeA) {\n                    _init.beforeA.push(beforeA);\n                },\n                addInnerAfterA: function(innerAfterA) {\n                    _init.innerAfterA.push(innerAfterA);\n                },\n                addInnerBeforeA: function(innerBeforeA) {\n                    _init.innerBeforeA.push(innerBeforeA);\n                },\n                addInitBind: function(bindEvent) {\n                    _init.bind.push(bindEvent);\n                },\n                addInitUnBind: function(unbindEvent) {\n                    _init.unbind.push(unbindEvent);\n                },\n                addInitCache: function(initCache) {\n                    _init.caches.push(initCache);\n                },\n                addInitNode: function(initNode) {\n                    _init.nodes.push(initNode);\n                },\n                addInitProxy: function(initProxy, isFirst) {\n                    if (!!isFirst) {\n                        _init.proxys.splice(0, 0, initProxy);\n                    } else {\n                        _init.proxys.push(initProxy);\n                    }\n                },\n                addInitRoot: function(initRoot) {\n                    _init.roots.push(initRoot);\n                },\n                addNodesData: function(setting, parentNode, index, nodes) {\n                    var childKey = setting.data.key.children,\n                        params;\n                    if (!parentNode[childKey]) {\n                        parentNode[childKey] = [];\n                        index = -1;\n                    } else if (index >= parentNode[childKey].length) {\n                        index = -1;\n                    }\n\n                    if (parentNode[childKey].length > 0 && index === 0) {\n                        parentNode[childKey][0].isFirstNode = false;\n                        view.setNodeLineIcos(setting, parentNode[childKey][0]);\n                    } else if (parentNode[childKey].length > 0 && index < 0) {\n                        parentNode[childKey][parentNode[childKey].length - 1].isLastNode = false;\n                        view.setNodeLineIcos(setting, parentNode[childKey][parentNode[childKey].length - 1]);\n                    }\n                    parentNode.isParent = true;\n\n                    if (index < 0) {\n                        parentNode[childKey] = parentNode[childKey].concat(nodes);\n                    } else {\n                        params = [index, 0].concat(nodes);\n                        parentNode[childKey].splice.apply(parentNode[childKey], params);\n                    }\n                },\n                addSelectedNode: function(setting, node) {\n                    var root = data.getRoot(setting);\n                    if (!data.isSelectedNode(setting, node)) {\n                        root.curSelectedList.push(node);\n                    }\n                },\n                addCreatedNode: function(setting, node) {\n                    if (!!setting.callback.onNodeCreated || !!setting.view.addDiyDom) {\n                        var root = data.getRoot(setting);\n                        root.createdNodes.push(node);\n                    }\n                },\n                addZTreeTools: function(zTreeTools) {\n                    _init.zTreeTools.push(zTreeTools);\n                },\n                exSetting: function(s) {\n                    $.extend(true, _setting, s);\n                },\n                fixPIdKeyValue: function(setting, node) {\n                    if (setting.data.simpleData.enable) {\n                        node[setting.data.simpleData.pIdKey] = node.parentTId ? node.getParentNode()[setting.data.simpleData.idKey] : setting.data.simpleData.rootPId;\n                    }\n                },\n                getAfterA: function(setting, node, array) {\n                    for (var i = 0, j = _init.afterA.length; i < j; i++) {\n                        _init.afterA[i].apply(this, arguments);\n                    }\n                },\n                getBeforeA: function(setting, node, array) {\n                    for (var i = 0, j = _init.beforeA.length; i < j; i++) {\n                        _init.beforeA[i].apply(this, arguments);\n                    }\n                },\n                getInnerAfterA: function(setting, node, array) {\n                    for (var i = 0, j = _init.innerAfterA.length; i < j; i++) {\n                        _init.innerAfterA[i].apply(this, arguments);\n                    }\n                },\n                getInnerBeforeA: function(setting, node, array) {\n                    for (var i = 0, j = _init.innerBeforeA.length; i < j; i++) {\n                        _init.innerBeforeA[i].apply(this, arguments);\n                    }\n                },\n                getCache: function(setting) {\n                    return caches[setting.treeId];\n                },\n                getNodeIndex: function(setting, node) {\n                    if (!node) return null;\n                    var childKey = setting.data.key.children,\n                        p = node.parentTId ? node.getParentNode() : data.getRoot(setting);\n                    for (var i = 0, l = p[childKey].length - 1; i <= l; i++) {\n                        if (p[childKey][i] === node) {\n                            return i;\n                        }\n                    }\n                    return -1;\n                },\n                getNextNode: function(setting, node) {\n                    if (!node) return null;\n                    var childKey = setting.data.key.children,\n                        p = node.parentTId ? node.getParentNode() : data.getRoot(setting);\n                    for (var i = 0, l = p[childKey].length - 1; i <= l; i++) {\n                        if (p[childKey][i] === node) {\n                            return (i == l ? null : p[childKey][i + 1]);\n                        }\n                    }\n                    return null;\n                },\n                getNodeByParam: function(setting, nodes, key, value) {\n                    if (!nodes || !key) return null;\n                    var childKey = setting.data.key.children;\n                    for (var i = 0, l = nodes.length; i < l; i++) {\n                        if (nodes[i][key] == value) {\n                            return nodes[i];\n                        }\n                        var tmp = data.getNodeByParam(setting, nodes[i][childKey], key, value);\n                        if (tmp) return tmp;\n                    }\n                    return null;\n                },\n                getNodeCache: function(setting, tId) {\n                    if (!tId) return null;\n                    var n = caches[setting.treeId].nodes[data.getNodeCacheId(tId)];\n                    return n ? n : null;\n                },\n                getNodeName: function(setting, node) {\n                    var nameKey = setting.data.key.name;\n                    return \"\" + node[nameKey];\n                },\n                getNodePath: function(setting, node) {\n                    if (!node) return null;\n\n                    var path;\n                    if (node.parentTId) {\n                        path = node.getParentNode().getPath();\n                    } else {\n                        path = [];\n                    }\n\n                    if (path) {\n                        path.push(node);\n                    }\n\n                    return path;\n                },\n                getNodeTitle: function(setting, node) {\n                    var t = setting.data.key.title === \"\" ? setting.data.key.name : setting.data.key.title;\n                    return \"\" + node[t];\n                },\n                getNodes: function(setting) {\n                    return data.getRoot(setting)[setting.data.key.children];\n                },\n                getNodesByParam: function(setting, nodes, key, value) {\n                    if (!nodes || !key) return [];\n                    var childKey = setting.data.key.children,\n                        result = [];\n                    for (var i = 0, l = nodes.length; i < l; i++) {\n                        if (nodes[i][key] == value) {\n                            result.push(nodes[i]);\n                        }\n                        result = result.concat(data.getNodesByParam(setting, nodes[i][childKey], key, value));\n                    }\n                    return result;\n                },\n                getNodesByParamFuzzy: function(setting, nodes, key, value) {\n                    if (!nodes || !key) return [];\n                    var childKey = setting.data.key.children,\n                        result = [];\n                    value = value.toLowerCase();\n                    for (var i = 0, l = nodes.length; i < l; i++) {\n                        if (typeof nodes[i][key] == \"string\" && nodes[i][key].toLowerCase().indexOf(value) > -1) {\n                            result.push(nodes[i]);\n                        }\n                        result = result.concat(data.getNodesByParamFuzzy(setting, nodes[i][childKey], key, value));\n                    }\n                    return result;\n                },\n                getNodesByFilter: function(setting, nodes, filter, isSingle, invokeParam) {\n                    if (!nodes) return (isSingle ? null : []);\n                    var childKey = setting.data.key.children,\n                        result = isSingle ? null : [];\n                    for (var i = 0, l = nodes.length; i < l; i++) {\n                        if (tools.apply(filter, [nodes[i], invokeParam], false)) {\n                            if (isSingle) {\n                                return nodes[i];\n                            }\n                            result.push(nodes[i]);\n                        }\n                        var tmpResult = data.getNodesByFilter(setting, nodes[i][childKey], filter, isSingle, invokeParam);\n                        if (isSingle && !!tmpResult) {\n                            return tmpResult;\n                        }\n                        result = isSingle ? tmpResult : result.concat(tmpResult);\n                    }\n                    return result;\n                },\n                getPreNode: function(setting, node) {\n                    if (!node) return null;\n                    var childKey = setting.data.key.children,\n                        p = node.parentTId ? node.getParentNode() : data.getRoot(setting);\n                    for (var i = 0, l = p[childKey].length; i < l; i++) {\n                        if (p[childKey][i] === node) {\n                            return (i == 0 ? null : p[childKey][i - 1]);\n                        }\n                    }\n                    return null;\n                },\n                getRoot: function(setting) {\n                    return setting ? roots[setting.treeId] : null;\n                },\n                getRoots: function() {\n                    return roots;\n                },\n                getSetting: function(treeId) {\n                    return settings[treeId];\n                },\n                getSettings: function() {\n                    return settings;\n                },\n                getZTreeTools: function(treeId) {\n                    var r = this.getRoot(this.getSetting(treeId));\n                    return r ? r.treeTools : null;\n                },\n                initCache: function(setting) {\n                    for (var i = 0, j = _init.caches.length; i < j; i++) {\n                        _init.caches[i].apply(this, arguments);\n                    }\n                },\n                initNode: function(setting, level, node, parentNode, preNode, nextNode) {\n                    for (var i = 0, j = _init.nodes.length; i < j; i++) {\n                        _init.nodes[i].apply(this, arguments);\n                    }\n                },\n                initRoot: function(setting) {\n                    for (var i = 0, j = _init.roots.length; i < j; i++) {\n                        _init.roots[i].apply(this, arguments);\n                    }\n                },\n                isSelectedNode: function(setting, node) {\n                    var root = data.getRoot(setting);\n                    for (var i = 0, j = root.curSelectedList.length; i < j; i++) {\n                        if (node === root.curSelectedList[i]) return true;\n                    }\n                    return false;\n                },\n                removeNodeCache: function(setting, node) {\n                    var childKey = setting.data.key.children;\n                    if (node[childKey]) {\n                        for (var i = 0, l = node[childKey].length; i < l; i++) {\n                            data.removeNodeCache(setting, node[childKey][i]);\n                        }\n                    }\n                    data.getCache(setting).nodes[data.getNodeCacheId(node.tId)] = null;\n                },\n                removeSelectedNode: function(setting, node) {\n                    var root = data.getRoot(setting);\n                    for (var i = 0, j = root.curSelectedList.length; i < j; i++) {\n                        if (node === root.curSelectedList[i] || !data.getNodeCache(setting, root.curSelectedList[i].tId)) {\n                            root.curSelectedList.splice(i, 1);\n                            setting.treeObj.trigger(consts.event.UNSELECTED, [setting.treeId, node]);\n                            i--;\n                            j--;\n                        }\n                    }\n                },\n                setCache: function(setting, cache) {\n                    caches[setting.treeId] = cache;\n                },\n                setRoot: function(setting, root) {\n                    roots[setting.treeId] = root;\n                },\n                setZTreeTools: function(setting, zTreeTools) {\n                    for (var i = 0, j = _init.zTreeTools.length; i < j; i++) {\n                        _init.zTreeTools[i].apply(this, arguments);\n                    }\n                },\n                transformToArrayFormat: function(setting, nodes) {\n                    if (!nodes) return [];\n                    var childKey = setting.data.key.children,\n                        r = [];\n                    if (tools.isArray(nodes)) {\n                        for (var i = 0, l = nodes.length; i < l; i++) {\n                            r.push(nodes[i]);\n                            if (nodes[i][childKey])\n                                r = r.concat(data.transformToArrayFormat(setting, nodes[i][childKey]));\n                        }\n                    } else {\n                        r.push(nodes);\n                        if (nodes[childKey])\n                            r = r.concat(data.transformToArrayFormat(setting, nodes[childKey]));\n                    }\n                    return r;\n                },\n                transformTozTreeFormat: function(setting, sNodes) {\n                    var i, l,\n                        key = setting.data.simpleData.idKey,\n                        parentKey = setting.data.simpleData.pIdKey,\n                        childKey = setting.data.key.children;\n                    if (!key || key == \"\" || !sNodes) return [];\n\n                    if (tools.isArray(sNodes)) {\n                        var r = [];\n                        var tmpMap = {};\n                        for (i = 0, l = sNodes.length; i < l; i++) {\n                            tmpMap[sNodes[i][key]] = sNodes[i];\n                        }\n                        for (i = 0, l = sNodes.length; i < l; i++) {\n                            if (tmpMap[sNodes[i][parentKey]] && sNodes[i][key] != sNodes[i][parentKey]) {\n                                if (!tmpMap[sNodes[i][parentKey]][childKey])\n                                    tmpMap[sNodes[i][parentKey]][childKey] = [];\n                                tmpMap[sNodes[i][parentKey]][childKey].push(sNodes[i]);\n                            } else {\n                                r.push(sNodes[i]);\n                            }\n                        }\n                        return r;\n                    } else {\n                        return [sNodes];\n                    }\n                }\n            },\n            //method of event proxy\n            event = {\n                bindEvent: function(setting) {\n                    for (var i = 0, j = _init.bind.length; i < j; i++) {\n                        _init.bind[i].apply(this, arguments);\n                    }\n                },\n                unbindEvent: function(setting) {\n                    for (var i = 0, j = _init.unbind.length; i < j; i++) {\n                        _init.unbind[i].apply(this, arguments);\n                    }\n                },\n                bindTree: function(setting) {\n                    var eventParam = {\n                            treeId: setting.treeId\n                        },\n                        o = setting.treeObj;\n                    if (!setting.view.txtSelectedEnable) {\n                        // for can't select text\n                        o.bind('selectstart', handler.onSelectStart).css({\n                            \"-moz-user-select\": \"-moz-none\"\n                        });\n                    }\n                    o.bind('click', eventParam, event.proxy);\n                    o.bind('dblclick', eventParam, event.proxy);\n                    o.bind('mouseover', eventParam, event.proxy);\n                    o.bind('mouseout', eventParam, event.proxy);\n                    o.bind('mousedown', eventParam, event.proxy);\n                    o.bind('mouseup', eventParam, event.proxy);\n                    o.bind('contextmenu', eventParam, event.proxy);\n                },\n                unbindTree: function(setting) {\n                    var o = setting.treeObj;\n                    o.unbind('selectstart', handler.onSelectStart)\n                        .unbind('click', event.proxy)\n                        .unbind('dblclick', event.proxy)\n                        .unbind('mouseover', event.proxy)\n                        .unbind('mouseout', event.proxy)\n                        .unbind('mousedown', event.proxy)\n                        .unbind('mouseup', event.proxy)\n                        .unbind('contextmenu', event.proxy);\n                },\n                doProxy: function(e) {\n                    var results = [];\n                    for (var i = 0, j = _init.proxys.length; i < j; i++) {\n                        var proxyResult = _init.proxys[i].apply(this, arguments);\n                        results.push(proxyResult);\n                        if (proxyResult.stop) {\n                            break;\n                        }\n                    }\n                    return results;\n                },\n                proxy: function(e) {\n                    var setting = data.getSetting(e.data.treeId);\n                    if (!tools.uCanDo(setting, e)) return true;\n                    var results = event.doProxy(e),\n                        r = true,\n                        x = false;\n                    for (var i = 0, l = results.length; i < l; i++) {\n                        var proxyResult = results[i];\n                        if (proxyResult.nodeEventCallback) {\n                            x = true;\n                            r = proxyResult.nodeEventCallback.apply(proxyResult, [e, proxyResult.node]) && r;\n                        }\n                        if (proxyResult.treeEventCallback) {\n                            x = true;\n                            r = proxyResult.treeEventCallback.apply(proxyResult, [e, proxyResult.node]) && r;\n                        }\n                    }\n                    return r;\n                }\n            },\n            //method of event handler\n            handler = {\n                onSwitchNode: function(event, node) {\n                    var setting = data.getSetting(event.data.treeId);\n                    if (node.open) {\n                        if (tools.apply(setting.callback.beforeCollapse, [setting.treeId, node], true) == false) return true;\n                        data.getRoot(setting).expandTriggerFlag = true;\n                        view.switchNode(setting, node);\n                    } else {\n                        if (tools.apply(setting.callback.beforeExpand, [setting.treeId, node], true) == false) return true;\n                        data.getRoot(setting).expandTriggerFlag = true;\n                        view.switchNode(setting, node);\n                    }\n                    return true;\n                },\n                onClickNode: function(event, node) {\n                    var setting = data.getSetting(event.data.treeId),\n                        clickFlag = ((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                    if (tools.apply(setting.callback.beforeClick, [setting.treeId, node, clickFlag], true) == false) return true;\n                    if (clickFlag === 0) {\n                        view.cancelPreSelectedNode(setting, node);\n                    } else {\n                        view.selectNode(setting, node, clickFlag === 2);\n                    }\n                    setting.treeObj.trigger(consts.event.CLICK, [event, setting.treeId, node, clickFlag]);\n                    return true;\n                },\n                onZTreeMousedown: function(event, node) {\n                    var setting = data.getSetting(event.data.treeId);\n                    if (tools.apply(setting.callback.beforeMouseDown, [setting.treeId, node], true)) {\n                        tools.apply(setting.callback.onMouseDown, [event, setting.treeId, node]);\n                    }\n                    return true;\n                },\n                onZTreeMouseup: function(event, node) {\n                    var setting = data.getSetting(event.data.treeId);\n                    if (tools.apply(setting.callback.beforeMouseUp, [setting.treeId, node], true)) {\n                        tools.apply(setting.callback.onMouseUp, [event, setting.treeId, node]);\n                    }\n                    return true;\n                },\n                onZTreeDblclick: function(event, node) {\n                    var setting = data.getSetting(event.data.treeId);\n                    if (tools.apply(setting.callback.beforeDblClick, [setting.treeId, node], true)) {\n                        tools.apply(setting.callback.onDblClick, [event, setting.treeId, node]);\n                    }\n                    return true;\n                },\n                onZTreeContextmenu: function(event, node) {\n                    var setting = data.getSetting(event.data.treeId);\n                    if (tools.apply(setting.callback.beforeRightClick, [setting.treeId, node], true)) {\n                        tools.apply(setting.callback.onRightClick, [event, setting.treeId, node]);\n                    }\n                    return (typeof setting.callback.onRightClick) != \"function\";\n                },\n                onSelectStart: function(e) {\n                    var n = e.originalEvent.srcElement.nodeName.toLowerCase();\n                    return (n === \"input\" || n === \"textarea\");\n                }\n            },\n            //method of tools for zTree\n            tools = {\n                apply: function(fun, param, defaultValue) {\n                    if ((typeof fun) == \"function\") {\n                        return fun.apply(zt, param ? param : []);\n                    }\n                    return defaultValue;\n                },\n                canAsync: function(setting, node) {\n                    var childKey = setting.data.key.children;\n                    return (setting.async.enable && node && node.isParent && !(node.zAsync || (node[childKey] && node[childKey].length > 0)));\n                },\n                clone: function(obj) {\n                    if (obj === null) return null;\n                    var o = tools.isArray(obj) ? [] : {};\n                    for (var i in obj) {\n                        o[i] = (obj[i] instanceof Date) ? new Date(obj[i].getTime()) : (typeof obj[i] === \"object\" ? tools.clone(obj[i]) : obj[i]);\n                    }\n                    return o;\n                },\n                eqs: function(str1, str2) {\n                    return str1.toLowerCase() === str2.toLowerCase();\n                },\n                isArray: function(arr) {\n                    return Object.prototype.toString.apply(arr) === \"[object Array]\";\n                },\n                isElement: function(o) {\n                    return (\n                        typeof HTMLElement === \"object\" ? o instanceof HTMLElement : //DOM2\n                        o && typeof o === \"object\" && o !== null && o.nodeType === 1 && typeof o.nodeName === \"string\"\n                    );\n                },\n                $: function(node, exp, setting) {\n                    if (!!exp && typeof exp != \"string\") {\n                        setting = exp;\n                        exp = \"\";\n                    }\n                    if (typeof node == \"string\") {\n                        return $(node, setting ? setting.treeObj.get(0).ownerDocument : null);\n                    } else {\n                        return $(\"#\" + node.tId + exp, setting ? setting.treeObj : null);\n                    }\n                },\n                getMDom: function(setting, curDom, targetExpr) {\n                    if (!curDom) return null;\n                    while (curDom && curDom.id !== setting.treeId) {\n                        for (var i = 0, l = targetExpr.length; curDom.tagName && i < l; i++) {\n                            if (tools.eqs(curDom.tagName, targetExpr[i].tagName) && curDom.getAttribute(targetExpr[i].attrName) !== null) {\n                                return curDom;\n                            }\n                        }\n                        curDom = curDom.parentNode;\n                    }\n                    return null;\n                },\n                getNodeMainDom: function(target) {\n                    return ($(target).parent(\"li\").get(0) || $(target).parentsUntil(\"li\").parent().get(0));\n                },\n                isChildOrSelf: function(dom, parentId) {\n                    return ($(dom).closest(\"#\" + parentId).length > 0);\n                },\n                uCanDo: function(setting, e) {\n                    return true;\n                }\n            },\n            //method of operate ztree dom\n            view = {\n                addNodes: function(setting, parentNode, index, newNodes, isSilent) {\n                    if (setting.data.keep.leaf && parentNode && !parentNode.isParent) {\n                        return;\n                    }\n                    if (!tools.isArray(newNodes)) {\n                        newNodes = [newNodes];\n                    }\n                    if (setting.data.simpleData.enable) {\n                        newNodes = data.transformTozTreeFormat(setting, newNodes);\n                    }\n                    if (parentNode) {\n                        var target_switchObj = $$(parentNode, consts.id.SWITCH, setting),\n                            target_icoObj = $$(parentNode, consts.id.ICON, setting),\n                            target_ulObj = $$(parentNode, consts.id.UL, setting);\n\n                        if (!parentNode.open) {\n                            view.replaceSwitchClass(parentNode, target_switchObj, consts.folder.CLOSE);\n                            view.replaceIcoClass(parentNode, target_icoObj, consts.folder.CLOSE);\n                            parentNode.open = false;\n                            target_ulObj.css({\n                                \"display\": \"none\"\n                            });\n                        }\n\n                        data.addNodesData(setting, parentNode, index, newNodes);\n                        view.createNodes(setting, parentNode.level + 1, newNodes, parentNode, index);\n                        if (!isSilent) {\n                            view.expandCollapseParentNode(setting, parentNode, true);\n                        }\n                    } else {\n                        data.addNodesData(setting, data.getRoot(setting), index, newNodes);\n                        view.createNodes(setting, 0, newNodes, null, index);\n                    }\n                },\n                appendNodes: function(setting, level, nodes, parentNode, index, initFlag, openFlag) {\n                    if (!nodes) return [];\n                    var html = [],\n                        childKey = setting.data.key.children;\n\n                    var tmpPNode = (parentNode) ? parentNode : data.getRoot(setting),\n                        tmpPChild = tmpPNode[childKey],\n                        isFirstNode, isLastNode;\n\n                    if (!tmpPChild || index >= tmpPChild.length - nodes.length) {\n                        index = -1;\n                    }\n\n                    for (var i = 0, l = nodes.length; i < l; i++) {\n                        var node = nodes[i];\n                        if (initFlag) {\n                            isFirstNode = ((index === 0 || tmpPChild.length == nodes.length) && (i == 0));\n                            isLastNode = (index < 0 && i == (nodes.length - 1));\n                            data.initNode(setting, level, node, parentNode, isFirstNode, isLastNode, openFlag);\n                            data.addNodeCache(setting, node);\n                        }\n\n                        var childHtml = [];\n                        if (node[childKey] && node[childKey].length > 0) {\n                            //make child html first, because checkType\n                            childHtml = view.appendNodes(setting, level + 1, node[childKey], node, -1, initFlag, openFlag && node.open);\n                        }\n                        if (openFlag) {\n\n                            view.makeDOMNodeMainBefore(html, setting, node);\n                            view.makeDOMNodeLine(html, setting, node);\n                            data.getBeforeA(setting, node, html);\n                            view.makeDOMNodeNameBefore(html, setting, node);\n                            data.getInnerBeforeA(setting, node, html);\n                            view.makeDOMNodeIcon(html, setting, node);\n                            data.getInnerAfterA(setting, node, html);\n                            view.makeDOMNodeNameAfter(html, setting, node);\n                            data.getAfterA(setting, node, html);\n                            if (node.isParent && node.open) {\n                                view.makeUlHtml(setting, node, html, childHtml.join(''));\n                            }\n                            view.makeDOMNodeMainAfter(html, setting, node);\n                            data.addCreatedNode(setting, node);\n                        }\n                    }\n                    return html;\n                },\n                appendParentULDom: function(setting, node) {\n                    var html = [],\n                        nObj = $$(node, setting);\n                    if (!nObj.get(0) && !!node.parentTId) {\n                        view.appendParentULDom(setting, node.getParentNode());\n                        nObj = $$(node, setting);\n                    }\n                    var ulObj = $$(node, consts.id.UL, setting);\n                    if (ulObj.get(0)) {\n                        ulObj.remove();\n                    }\n                    var childKey = setting.data.key.children,\n                        childHtml = view.appendNodes(setting, node.level + 1, node[childKey], node, -1, false, true);\n                    view.makeUlHtml(setting, node, html, childHtml.join(''));\n                    nObj.append(html.join(''));\n                },\n                asyncNode: function(setting, node, isSilent, callback) {\n                    var i, l;\n                    if (node && !node.isParent) {\n                        tools.apply(callback);\n                        return false;\n                    } else if (node && node.isAjaxing) {\n                        return false;\n                    } else if (tools.apply(setting.callback.beforeAsync, [setting.treeId, node], true) == false) {\n                        tools.apply(callback);\n                        return false;\n                    }\n                    if (node) {\n                        node.isAjaxing = true;\n                        var icoObj = $$(node, consts.id.ICON, setting);\n                        icoObj.attr({ \"style\": \"\", \"class\": consts.className.BUTTON + \" \" + consts.className.ICO_LOADING });\n                    }\n\n                    var tmpParam = {};\n                    for (i = 0, l = setting.async.autoParam.length; node && i < l; i++) {\n                        var pKey = setting.async.autoParam[i].split(\"=\"),\n                            spKey = pKey;\n                        if (pKey.length > 1) {\n                            spKey = pKey[1];\n                            pKey = pKey[0];\n                        }\n                        tmpParam[spKey] = node[pKey];\n                    }\n                    if (tools.isArray(setting.async.otherParam)) {\n                        for (i = 0, l = setting.async.otherParam.length; i < l; i += 2) {\n                            tmpParam[setting.async.otherParam[i]] = setting.async.otherParam[i + 1];\n                        }\n                    } else {\n                        for (var p in setting.async.otherParam) {\n                            tmpParam[p] = setting.async.otherParam[p];\n                        }\n                    }\n\n                    var _tmpV = data.getRoot(setting)._ver;\n                    $.ajax({\n                        contentType: setting.async.contentType,\n                        cache: false,\n                        type: setting.async.type,\n                        url: tools.apply(setting.async.url, [setting.treeId, node], setting.async.url),\n                        data: setting.async.contentType.indexOf('application/json') > -1 ? JSON.stringify(tmpParam) : tmpParam,\n                        dataType: setting.async.dataType,\n                        success: function(msg) {\n                            if (_tmpV != data.getRoot(setting)._ver) {\n                                return;\n                            }\n                            var newNodes = [];\n                            try {\n                                if (!msg || msg.length == 0) {\n                                    newNodes = [];\n                                } else if (typeof msg == \"string\") {\n                                    newNodes = eval(\"(\" + msg + \")\");\n                                } else {\n                                    newNodes = msg;\n                                }\n                            } catch (err) {\n                                newNodes = msg;\n                            }\n\n                            if (node) {\n                                node.isAjaxing = null;\n                                node.zAsync = true;\n                            }\n                            view.setNodeLineIcos(setting, node);\n                            if (newNodes && newNodes !== \"\") {\n                                newNodes = tools.apply(setting.async.dataFilter, [setting.treeId, node, newNodes], newNodes);\n                                view.addNodes(setting, node, -1, !!newNodes ? tools.clone(newNodes) : [], !!isSilent);\n                            } else {\n                                view.addNodes(setting, node, -1, [], !!isSilent);\n                            }\n                            setting.treeObj.trigger(consts.event.ASYNC_SUCCESS, [setting.treeId, node, msg]);\n                            tools.apply(callback);\n                        },\n                        error: function(XMLHttpRequest, textStatus, errorThrown) {\n                            if (_tmpV != data.getRoot(setting)._ver) {\n                                return;\n                            }\n                            if (node) node.isAjaxing = null;\n                            view.setNodeLineIcos(setting, node);\n                            setting.treeObj.trigger(consts.event.ASYNC_ERROR, [setting.treeId, node, XMLHttpRequest, textStatus, errorThrown]);\n                        }\n                    });\n                    return true;\n                },\n                cancelPreSelectedNode: function(setting, node, excludeNode) {\n                    var list = data.getRoot(setting).curSelectedList,\n                        i, n;\n                    for (i = list.length - 1; i >= 0; i--) {\n                        n = list[i];\n                        if (node === n || (!node && (!excludeNode || excludeNode !== n))) {\n                            $$(n, consts.id.A, setting).removeClass(consts.node.CURSELECTED);\n                            if (node) {\n                                data.removeSelectedNode(setting, node);\n                                break;\n                            } else {\n                                list.splice(i, 1);\n                                setting.treeObj.trigger(consts.event.UNSELECTED, [setting.treeId, n]);\n                            }\n                        }\n                    }\n                },\n                createNodeCallback: function(setting) {\n                    if (!!setting.callback.onNodeCreated || !!setting.view.addDiyDom) {\n                        var root = data.getRoot(setting);\n                        while (root.createdNodes.length > 0) {\n                            var node = root.createdNodes.shift();\n                            tools.apply(setting.view.addDiyDom, [setting.treeId, node]);\n                            if (!!setting.callback.onNodeCreated) {\n                                setting.treeObj.trigger(consts.event.NODECREATED, [setting.treeId, node]);\n                            }\n                        }\n                    }\n                },\n                createNodes: function(setting, level, nodes, parentNode, index) {\n                    if (!nodes || nodes.length == 0) return;\n                    var root = data.getRoot(setting),\n                        childKey = setting.data.key.children,\n                        openFlag = !parentNode || parentNode.open || !!$$(parentNode[childKey][0], setting).get(0);\n                    root.createdNodes = [];\n                    var zTreeHtml = view.appendNodes(setting, level, nodes, parentNode, index, true, openFlag),\n                        parentObj, nextObj;\n\n                    if (!parentNode) {\n                        parentObj = setting.treeObj;\n                        //setting.treeObj.append(zTreeHtml.join(''));\n                    } else {\n                        var ulObj = $$(parentNode, consts.id.UL, setting);\n                        if (ulObj.get(0)) {\n                            parentObj = ulObj;\n                            //ulObj.append(zTreeHtml.join(''));\n                        }\n                    }\n                    if (parentObj) {\n                        if (index >= 0) {\n                            nextObj = parentObj.children()[index];\n                        }\n                        if (index >= 0 && nextObj) {\n                            $(nextObj).before(zTreeHtml.join(''));\n                        } else {\n                            parentObj.append(zTreeHtml.join(''));\n                        }\n                    }\n\n                    view.createNodeCallback(setting);\n                },\n                destroy: function(setting) {\n                    if (!setting) return;\n                    data.initCache(setting);\n                    data.initRoot(setting);\n                    event.unbindTree(setting);\n                    event.unbindEvent(setting);\n                    setting.treeObj.empty();\n                    delete settings[setting.treeId];\n                },\n                expandCollapseNode: function(setting, node, expandFlag, animateFlag, callback) {\n                    var root = data.getRoot(setting),\n                        childKey = setting.data.key.children;\n                    var tmpCb, _callback;\n                    if (!node) {\n                        tools.apply(callback, []);\n                        return;\n                    }\n                    if (root.expandTriggerFlag) {\n                        _callback = callback;\n                        tmpCb = function() {\n                            if (_callback) _callback();\n                            if (node.open) {\n                                setting.treeObj.trigger(consts.event.EXPAND, [setting.treeId, node]);\n                            } else {\n                                setting.treeObj.trigger(consts.event.COLLAPSE, [setting.treeId, node]);\n                            }\n                        };\n                        callback = tmpCb;\n                        root.expandTriggerFlag = false;\n                    }\n                    if (!node.open && node.isParent && ((!$$(node, consts.id.UL, setting).get(0)) || (node[childKey] && node[childKey].length > 0 && !$$(node[childKey][0], setting).get(0)))) {\n                        view.appendParentULDom(setting, node);\n                        view.createNodeCallback(setting);\n                    }\n                    if (node.open == expandFlag) {\n                        tools.apply(callback, []);\n                        return;\n                    }\n                    var ulObj = $$(node, consts.id.UL, setting),\n                        switchObj = $$(node, consts.id.SWITCH, setting),\n                        icoObj = $$(node, consts.id.ICON, setting);\n\n                    if (node.isParent) {\n                        node.open = !node.open;\n                        if (node.iconOpen && node.iconClose) {\n                            icoObj.attr(\"style\", view.makeNodeIcoStyle(setting, node));\n                        }\n\n                        if (node.open) {\n                            view.replaceSwitchClass(node, switchObj, consts.folder.OPEN);\n                            view.replaceIcoClass(node, icoObj, consts.folder.OPEN);\n                            if (animateFlag == false || setting.view.expandSpeed == \"\") {\n                                ulObj.show();\n                                tools.apply(callback, []);\n                            } else {\n                                if (node[childKey] && node[childKey].length > 0) {\n                                    ulObj.slideDown(setting.view.expandSpeed, callback);\n                                } else {\n                                    ulObj.show();\n                                    tools.apply(callback, []);\n                                }\n                            }\n                        } else {\n                            view.replaceSwitchClass(node, switchObj, consts.folder.CLOSE);\n                            view.replaceIcoClass(node, icoObj, consts.folder.CLOSE);\n                            if (animateFlag == false || setting.view.expandSpeed == \"\" || !(node[childKey] && node[childKey].length > 0)) {\n                                ulObj.hide();\n                                tools.apply(callback, []);\n                            } else {\n                                ulObj.slideUp(setting.view.expandSpeed, callback);\n                            }\n                        }\n                    } else {\n                        tools.apply(callback, []);\n                    }\n                },\n                expandCollapseParentNode: function(setting, node, expandFlag, animateFlag, callback) {\n                    if (!node) return;\n                    if (!node.parentTId) {\n                        view.expandCollapseNode(setting, node, expandFlag, animateFlag, callback);\n                        return;\n                    } else {\n                        view.expandCollapseNode(setting, node, expandFlag, animateFlag);\n                    }\n                    if (node.parentTId) {\n                        view.expandCollapseParentNode(setting, node.getParentNode(), expandFlag, animateFlag, callback);\n                    }\n                },\n                expandCollapseSonNode: function(setting, node, expandFlag, animateFlag, callback) {\n                    var root = data.getRoot(setting),\n                        childKey = setting.data.key.children,\n                        treeNodes = (node) ? node[childKey] : root[childKey],\n                        selfAnimateSign = (node) ? false : animateFlag,\n                        expandTriggerFlag = data.getRoot(setting).expandTriggerFlag;\n                    data.getRoot(setting).expandTriggerFlag = false;\n                    if (treeNodes) {\n                        for (var i = 0, l = treeNodes.length; i < l; i++) {\n                            if (treeNodes[i]) view.expandCollapseSonNode(setting, treeNodes[i], expandFlag, selfAnimateSign);\n                        }\n                    }\n                    data.getRoot(setting).expandTriggerFlag = expandTriggerFlag;\n                    view.expandCollapseNode(setting, node, expandFlag, animateFlag, callback);\n                },\n                isSelectedNode: function(setting, node) {\n                    if (!node) {\n                        return false;\n                    }\n                    var list = data.getRoot(setting).curSelectedList,\n                        i;\n                    for (i = list.length - 1; i >= 0; i--) {\n                        if (node === list[i]) {\n                            return true;\n                        }\n                    }\n                    return false;\n                },\n                makeDOMNodeIcon: function(html, setting, node) {\n                    var nameStr = data.getNodeName(setting, node),\n                        name = setting.view.nameIsHTML ? nameStr : nameStr.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n                    html.push(\"<span id='\", node.tId, consts.id.ICON,\n                        \"' title='' treeNode\", consts.id.ICON, \" class='\", view.makeNodeIcoClass(setting, node),\n                        \"' style='\", view.makeNodeIcoStyle(setting, node), \"'></span><span id='\", node.tId, consts.id.SPAN,\n                        \"' class='\", consts.className.NAME,\n                        \"'>\", name, \"</span>\");\n                },\n                makeDOMNodeLine: function(html, setting, node) {\n                    html.push(\"<span id='\", node.tId, consts.id.SWITCH, \"' title='' class='\", view.makeNodeLineClass(setting, node), \"' treeNode\", consts.id.SWITCH, \"></span>\");\n                },\n                makeDOMNodeMainAfter: function(html, setting, node) {\n                    html.push(\"</li>\");\n                },\n                makeDOMNodeMainBefore: function(html, setting, node) {\n                    html.push(\"<li id='\", node.tId, \"' class='\", consts.className.LEVEL, node.level, \"' tabindex='0' hidefocus='true' treenode>\");\n                },\n                makeDOMNodeNameAfter: function(html, setting, node) {\n                    html.push(\"</a>\");\n                },\n                makeDOMNodeNameBefore: function(html, setting, node) {\n                    var title = data.getNodeTitle(setting, node),\n                        url = view.makeNodeUrl(setting, node),\n                        fontcss = view.makeNodeFontCss(setting, node),\n                        fontStyle = [];\n                    for (var f in fontcss) {\n                        fontStyle.push(f, \":\", fontcss[f], \";\");\n                    }\n                    html.push(\"<a id='\", node.tId, consts.id.A, \"' class='\", consts.className.LEVEL, node.level, \"' treeNode\", consts.id.A, \" onclick=\\\"\", (node.click || ''),\n                        \"\\\" \", ((url != null && url.length > 0) ? \"href='\" + url + \"'\" : \"\"), \" target='\", view.makeNodeTarget(node), \"' style='\", fontStyle.join(''),\n                        \"'\");\n                    if (tools.apply(setting.view.showTitle, [setting.treeId, node], setting.view.showTitle) && title) {\n                        html.push(\"title='\", title.replace(/'/g, \"&#39;\").replace(/</g, '&lt;').replace(/>/g, '&gt;'), \"'\");\n                    }\n                    html.push(\">\");\n                },\n                makeNodeFontCss: function(setting, node) {\n                    var fontCss = tools.apply(setting.view.fontCss, [setting.treeId, node], setting.view.fontCss);\n                    return (fontCss && ((typeof fontCss) != \"function\")) ? fontCss : {};\n                },\n                makeNodeIcoClass: function(setting, node) {\n                    var icoCss = [\"ico\"];\n                    if (!node.isAjaxing) {\n                        icoCss[0] = (node.iconSkin ? node.iconSkin + \"_\" : \"\") + icoCss[0];\n                        if (node.isParent) {\n                            icoCss.push(node.open ? consts.folder.OPEN : consts.folder.CLOSE);\n                        } else {\n                            icoCss.push(consts.folder.DOCU);\n                        }\n                    }\n                    return consts.className.BUTTON + \" \" + icoCss.join('_');\n                },\n                makeNodeIcoStyle: function(setting, node) {\n                    var icoStyle = [];\n                    if (!node.isAjaxing) {\n                        var icon = (node.isParent && node.iconOpen && node.iconClose) ? (node.open ? node.iconOpen : node.iconClose) : node[setting.data.key.icon];\n                        if (icon) icoStyle.push(\"background:url(\", icon, \") 0 0 no-repeat;\");\n                        if (setting.view.showIcon == false || !tools.apply(setting.view.showIcon, [setting.treeId, node], true)) {\n                            icoStyle.push(\"width:0px;height:0px;\");\n                        }\n                    }\n                    return icoStyle.join('');\n                },\n                makeNodeLineClass: function(setting, node) {\n                    var lineClass = [];\n                    if (setting.view.showLine) {\n                        if (node.level == 0 && node.isFirstNode && node.isLastNode) {\n                            lineClass.push(consts.line.ROOT);\n                        } else if (node.level == 0 && node.isFirstNode) {\n                            lineClass.push(consts.line.ROOTS);\n                        } else if (node.isLastNode) {\n                            lineClass.push(consts.line.BOTTOM);\n                        } else {\n                            lineClass.push(consts.line.CENTER);\n                        }\n                    } else {\n                        lineClass.push(consts.line.NOLINE);\n                    }\n                    if (node.isParent) {\n                        lineClass.push(node.open ? consts.folder.OPEN : consts.folder.CLOSE);\n                    } else {\n                        lineClass.push(consts.folder.DOCU);\n                    }\n                    return view.makeNodeLineClassEx(node) + lineClass.join('_');\n                },\n                makeNodeLineClassEx: function(node) {\n                    return consts.className.BUTTON + \" \" + consts.className.LEVEL + node.level + \" \" + consts.className.SWITCH + \" \";\n                },\n                makeNodeTarget: function(node) {\n                    return (node.target || \"_blank\");\n                },\n                makeNodeUrl: function(setting, node) {\n                    var urlKey = setting.data.key.url;\n                    return node[urlKey] ? node[urlKey] : null;\n                },\n                makeUlHtml: function(setting, node, html, content) {\n                    html.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                    html.push(content);\n                    html.push(\"</ul>\");\n                },\n                makeUlLineClass: function(setting, node) {\n                    return ((setting.view.showLine && !node.isLastNode) ? consts.line.LINE : \"\");\n                },\n                removeChildNodes: function(setting, node) {\n                    if (!node) return;\n                    var childKey = setting.data.key.children,\n                        nodes = node[childKey];\n                    if (!nodes) return;\n\n                    for (var i = 0, l = nodes.length; i < l; i++) {\n                        data.removeNodeCache(setting, nodes[i]);\n                    }\n                    data.removeSelectedNode(setting);\n                    delete node[childKey];\n\n                    if (!setting.data.keep.parent) {\n                        node.isParent = false;\n                        node.open = false;\n                        var tmp_switchObj = $$(node, consts.id.SWITCH, setting),\n                            tmp_icoObj = $$(node, consts.id.ICON, setting);\n                        view.replaceSwitchClass(node, tmp_switchObj, consts.folder.DOCU);\n                        view.replaceIcoClass(node, tmp_icoObj, consts.folder.DOCU);\n                        $$(node, consts.id.UL, setting).remove();\n                    } else {\n                        $$(node, consts.id.UL, setting).empty();\n                    }\n                },\n                scrollIntoView: function(dom) {\n                    if (!dom) {\n                        return;\n                    }\n                    // code src: http://jsfiddle.net/08u6cxwj/\n                    if (!Element.prototype.scrollIntoViewIfNeeded) {\n                        Element.prototype.scrollIntoViewIfNeeded = function(centerIfNeeded) {\n                            function withinBounds(value, min, max, extent) {\n                                if (false === centerIfNeeded || max <= value + extent && value <= min + extent) {\n                                    return Math.min(max, Math.max(min, value));\n                                } else {\n                                    return (min + max) / 2;\n                                }\n                            }\n\n                            function makeArea(left, top, width, height) {\n                                return {\n                                    \"left\": left,\n                                    \"top\": top,\n                                    \"width\": width,\n                                    \"height\": height,\n                                    \"right\": left + width,\n                                    \"bottom\": top + height,\n                                    \"translate\": function(x, y) {\n                                        return makeArea(x + left, y + top, width, height);\n                                    },\n                                    \"relativeFromTo\": function(lhs, rhs) {\n                                        var newLeft = left,\n                                            newTop = top;\n                                        lhs = lhs.offsetParent;\n                                        rhs = rhs.offsetParent;\n                                        if (lhs === rhs) {\n                                            return area;\n                                        }\n                                        for (; lhs; lhs = lhs.offsetParent) {\n                                            newLeft += lhs.offsetLeft + lhs.clientLeft;\n                                            newTop += lhs.offsetTop + lhs.clientTop;\n                                        }\n                                        for (; rhs; rhs = rhs.offsetParent) {\n                                            newLeft -= rhs.offsetLeft + rhs.clientLeft;\n                                            newTop -= rhs.offsetTop + rhs.clientTop;\n                                        }\n                                        return makeArea(newLeft, newTop, width, height);\n                                    }\n                                };\n                            }\n\n                            var parent, elem = this,\n                                area = makeArea(\n                                    this.offsetLeft, this.offsetTop,\n                                    this.offsetWidth, this.offsetHeight);\n                            while (tools.isElement(parent = elem.parentNode)) {\n                                var clientLeft = parent.offsetLeft + parent.clientLeft;\n                                var clientTop = parent.offsetTop + parent.clientTop;\n\n                                // Make area relative to parent's client area.\n                                area = area.relativeFromTo(elem, parent).translate(-clientLeft, -clientTop);\n\n                                parent.scrollLeft = withinBounds(\n                                    parent.scrollLeft,\n                                    area.right - parent.clientWidth, area.left,\n                                    parent.clientWidth);\n\n                                parent.scrollTop = withinBounds(\n                                    parent.scrollTop,\n                                    area.bottom - parent.clientHeight, area.top,\n                                    parent.clientHeight);\n\n                                // Determine actual scroll amount by reading back scroll properties.\n                                area = area.translate(clientLeft - parent.scrollLeft,\n                                    clientTop - parent.scrollTop);\n                                elem = parent;\n                            }\n                        };\n                    }\n                    dom.scrollIntoViewIfNeeded();\n                },\n                setFirstNode: function(setting, parentNode) {\n                    var childKey = setting.data.key.children,\n                        childLength = parentNode[childKey].length;\n                    if (childLength > 0) {\n                        parentNode[childKey][0].isFirstNode = true;\n                    }\n                },\n                setLastNode: function(setting, parentNode) {\n                    var childKey = setting.data.key.children,\n                        childLength = parentNode[childKey].length;\n                    if (childLength > 0) {\n                        parentNode[childKey][childLength - 1].isLastNode = true;\n                    }\n                },\n                removeNode: function(setting, node) {\n                    var root = data.getRoot(setting),\n                        childKey = setting.data.key.children,\n                        parentNode = (node.parentTId) ? node.getParentNode() : root;\n\n                    node.isFirstNode = false;\n                    node.isLastNode = false;\n                    node.getPreNode = function() {\n                        return null;\n                    };\n                    node.getNextNode = function() {\n                        return null;\n                    };\n\n                    if (!data.getNodeCache(setting, node.tId)) {\n                        return;\n                    }\n\n                    $$(node, setting).remove();\n                    data.removeNodeCache(setting, node);\n                    data.removeSelectedNode(setting, node);\n\n                    for (var i = 0, l = parentNode[childKey].length; i < l; i++) {\n                        if (parentNode[childKey][i].tId == node.tId) {\n                            parentNode[childKey].splice(i, 1);\n                            break;\n                        }\n                    }\n                    view.setFirstNode(setting, parentNode);\n                    view.setLastNode(setting, parentNode);\n\n                    var tmp_ulObj, tmp_switchObj, tmp_icoObj,\n                        childLength = parentNode[childKey].length;\n\n                    //repair nodes old parent\n                    if (!setting.data.keep.parent && childLength == 0) {\n                        //old parentNode has no child nodes\n                        parentNode.isParent = false;\n                        parentNode.open = false;\n                        tmp_ulObj = $$(parentNode, consts.id.UL, setting);\n                        tmp_switchObj = $$(parentNode, consts.id.SWITCH, setting);\n                        tmp_icoObj = $$(parentNode, consts.id.ICON, setting);\n                        view.replaceSwitchClass(parentNode, tmp_switchObj, consts.folder.DOCU);\n                        view.replaceIcoClass(parentNode, tmp_icoObj, consts.folder.DOCU);\n                        tmp_ulObj.css(\"display\", \"none\");\n\n                    } else if (setting.view.showLine && childLength > 0) {\n                        //old parentNode has child nodes\n                        var newLast = parentNode[childKey][childLength - 1];\n                        tmp_ulObj = $$(newLast, consts.id.UL, setting);\n                        tmp_switchObj = $$(newLast, consts.id.SWITCH, setting);\n                        tmp_icoObj = $$(newLast, consts.id.ICON, setting);\n                        if (parentNode == root) {\n                            if (parentNode[childKey].length == 1) {\n                                //node was root, and ztree has only one root after move node\n                                view.replaceSwitchClass(newLast, tmp_switchObj, consts.line.ROOT);\n                            } else {\n                                var tmp_first_switchObj = $$(parentNode[childKey][0], consts.id.SWITCH, setting);\n                                view.replaceSwitchClass(parentNode[childKey][0], tmp_first_switchObj, consts.line.ROOTS);\n                                view.replaceSwitchClass(newLast, tmp_switchObj, consts.line.BOTTOM);\n                            }\n                        } else {\n                            view.replaceSwitchClass(newLast, tmp_switchObj, consts.line.BOTTOM);\n                        }\n                        tmp_ulObj.removeClass(consts.line.LINE);\n                    }\n                },\n                replaceIcoClass: function(node, obj, newName) {\n                    if (!obj || node.isAjaxing) return;\n                    var tmpName = obj.attr(\"class\");\n                    if (tmpName == undefined) return;\n                    var tmpList = tmpName.split(\"_\");\n                    switch (newName) {\n                        case consts.folder.OPEN:\n                        case consts.folder.CLOSE:\n                        case consts.folder.DOCU:\n                            tmpList[tmpList.length - 1] = newName;\n                            break;\n                    }\n                    obj.attr(\"class\", tmpList.join(\"_\"));\n                },\n                replaceSwitchClass: function(node, obj, newName) {\n                    if (!obj) return;\n                    var tmpName = obj.attr(\"class\");\n                    if (tmpName == undefined) return;\n                    var tmpList = tmpName.split(\"_\");\n                    switch (newName) {\n                        case consts.line.ROOT:\n                        case consts.line.ROOTS:\n                        case consts.line.CENTER:\n                        case consts.line.BOTTOM:\n                        case consts.line.NOLINE:\n                            tmpList[0] = view.makeNodeLineClassEx(node) + newName;\n                            break;\n                        case consts.folder.OPEN:\n                        case consts.folder.CLOSE:\n                        case consts.folder.DOCU:\n                            tmpList[1] = newName;\n                            break;\n                    }\n                    obj.attr(\"class\", tmpList.join(\"_\"));\n                    if (newName !== consts.folder.DOCU) {\n                        obj.removeAttr(\"disabled\");\n                    } else {\n                        obj.attr(\"disabled\", \"disabled\");\n                    }\n                },\n                selectNode: function(setting, node, addFlag) {\n                    if (!addFlag) {\n                        view.cancelPreSelectedNode(setting, null, node);\n                    }\n                    $$(node, consts.id.A, setting).addClass(consts.node.CURSELECTED);\n                    data.addSelectedNode(setting, node);\n                    setting.treeObj.trigger(consts.event.SELECTED, [setting.treeId, node]);\n                },\n                setNodeFontCss: function(setting, treeNode) {\n                    var aObj = $$(treeNode, consts.id.A, setting),\n                        fontCss = view.makeNodeFontCss(setting, treeNode);\n                    if (fontCss) {\n                        aObj.css(fontCss);\n                    }\n                },\n                setNodeLineIcos: function(setting, node) {\n                    if (!node) return;\n                    var switchObj = $$(node, consts.id.SWITCH, setting),\n                        ulObj = $$(node, consts.id.UL, setting),\n                        icoObj = $$(node, consts.id.ICON, setting),\n                        ulLine = view.makeUlLineClass(setting, node);\n                    if (ulLine.length == 0) {\n                        ulObj.removeClass(consts.line.LINE);\n                    } else {\n                        ulObj.addClass(ulLine);\n                    }\n                    switchObj.attr(\"class\", view.makeNodeLineClass(setting, node));\n                    if (node.isParent) {\n                        switchObj.removeAttr(\"disabled\");\n                    } else {\n                        switchObj.attr(\"disabled\", \"disabled\");\n                    }\n                    icoObj.removeAttr(\"style\");\n                    icoObj.attr(\"style\", view.makeNodeIcoStyle(setting, node));\n                    icoObj.attr(\"class\", view.makeNodeIcoClass(setting, node));\n                },\n                setNodeName: function(setting, node) {\n                    var title = data.getNodeTitle(setting, node),\n                        nObj = $$(node, consts.id.SPAN, setting);\n                    nObj.empty();\n                    if (setting.view.nameIsHTML) {\n                        nObj.html(data.getNodeName(setting, node));\n                    } else {\n                        nObj.text(data.getNodeName(setting, node));\n                    }\n                    if (tools.apply(setting.view.showTitle, [setting.treeId, node], setting.view.showTitle)) {\n                        var aObj = $$(node, consts.id.A, setting);\n                        aObj.attr(\"title\", !title ? \"\" : title);\n                    }\n                },\n                setNodeTarget: function(setting, node) {\n                    var aObj = $$(node, consts.id.A, setting);\n                    aObj.attr(\"target\", view.makeNodeTarget(node));\n                },\n                setNodeUrl: function(setting, node) {\n                    var aObj = $$(node, consts.id.A, setting),\n                        url = view.makeNodeUrl(setting, node);\n                    if (url == null || url.length == 0) {\n                        aObj.removeAttr(\"href\");\n                    } else {\n                        aObj.attr(\"href\", url);\n                    }\n                },\n                switchNode: function(setting, node) {\n                    if (node.open || !tools.canAsync(setting, node)) {\n                        view.expandCollapseNode(setting, node, !node.open);\n                    } else if (setting.async.enable) {\n                        if (!view.asyncNode(setting, node)) {\n                            view.expandCollapseNode(setting, node, !node.open);\n                            return;\n                        }\n                    } else if (node) {\n                        view.expandCollapseNode(setting, node, !node.open);\n                    }\n                }\n            };\n        // zTree defind\n        $.fn.zTree = {\n            consts: _consts,\n            _z: {\n                tools: tools,\n                view: view,\n                event: event,\n                data: data\n            },\n            getZTreeObj: function(treeId) {\n                var o = data.getZTreeTools(treeId);\n                return o ? o : null;\n            },\n            destroy: function(treeId) {\n                if (!!treeId && treeId.length > 0) {\n                    view.destroy(data.getSetting(treeId));\n                } else {\n                    for (var s in settings) {\n                        view.destroy(settings[s]);\n                    }\n                }\n            },\n            init: function(obj, zSetting, zNodes) {\n                var setting = tools.clone(_setting);\n                $.extend(true, setting, zSetting);\n                setting.treeId = obj.attr(\"id\");\n                setting.treeObj = obj;\n                setting.treeObj.empty();\n                settings[setting.treeId] = setting;\n                //For some older browser,(e.g., ie6)\n                if (typeof document.body.style.maxHeight === \"undefined\") {\n                    setting.view.expandSpeed = \"\";\n                }\n                data.initRoot(setting);\n                var root = data.getRoot(setting),\n                    childKey = setting.data.key.children;\n                zNodes = zNodes ? tools.clone(tools.isArray(zNodes) ? zNodes : [zNodes]) : [];\n                if (setting.data.simpleData.enable) {\n                    root[childKey] = data.transformTozTreeFormat(setting, zNodes);\n                } else {\n                    root[childKey] = zNodes;\n                }\n\n                data.initCache(setting);\n                event.unbindTree(setting);\n                event.bindTree(setting);\n                event.unbindEvent(setting);\n                event.bindEvent(setting);\n\n                var zTreeTools = {\n                    setting: setting,\n                    addNodes: function(parentNode, index, newNodes, isSilent) {\n                        if (!parentNode) parentNode = null;\n                        if (parentNode && !parentNode.isParent && setting.data.keep.leaf) return null;\n\n                        var i = parseInt(index, 10);\n                        if (isNaN(i)) {\n                            isSilent = !!newNodes;\n                            newNodes = index;\n                            index = -1;\n                        } else {\n                            index = i;\n                        }\n                        if (!newNodes) return null;\n\n\n                        var xNewNodes = tools.clone(tools.isArray(newNodes) ? newNodes : [newNodes]);\n\n                        function addCallback() {\n                            view.addNodes(setting, parentNode, index, xNewNodes, (isSilent == true));\n                        }\n\n                        if (tools.canAsync(setting, parentNode)) {\n                            view.asyncNode(setting, parentNode, isSilent, addCallback);\n                        } else {\n                            addCallback();\n                        }\n                        return xNewNodes;\n                    },\n                    cancelSelectedNode: function(node) {\n                        view.cancelPreSelectedNode(setting, node);\n                    },\n                    destroy: function() {\n                        view.destroy(setting);\n                    },\n                    expandAll: function(expandFlag) {\n                        expandFlag = !!expandFlag;\n                        view.expandCollapseSonNode(setting, null, expandFlag, true);\n                        return expandFlag;\n                    },\n                    expandNode: function(node, expandFlag, sonSign, focus, callbackFlag) {\n                        if (!node || !node.isParent) return null;\n                        if (expandFlag !== true && expandFlag !== false) {\n                            expandFlag = !node.open;\n                        }\n                        callbackFlag = !!callbackFlag;\n\n                        if (callbackFlag && expandFlag && (tools.apply(setting.callback.beforeExpand, [setting.treeId, node], true) == false)) {\n                            return null;\n                        } else if (callbackFlag && !expandFlag && (tools.apply(setting.callback.beforeCollapse, [setting.treeId, node], true) == false)) {\n                            return null;\n                        }\n                        if (expandFlag && node.parentTId) {\n                            view.expandCollapseParentNode(setting, node.getParentNode(), expandFlag, false);\n                        }\n                        if (expandFlag === node.open && !sonSign) {\n                            return null;\n                        }\n\n                        data.getRoot(setting).expandTriggerFlag = callbackFlag;\n                        if (!tools.canAsync(setting, node) && sonSign) {\n                            view.expandCollapseSonNode(setting, node, expandFlag, true, showNodeFocus);\n                        } else {\n                            node.open = !expandFlag;\n                            view.switchNode(this.setting, node);\n                            showNodeFocus();\n                        }\n                        return expandFlag;\n\n                        function showNodeFocus() {\n                            var a = $$(node, setting).get(0);\n                            if (a && focus !== false) {\n                                view.scrollIntoView(a);\n                            }\n                        }\n                    },\n                    getNodes: function() {\n                        return data.getNodes(setting);\n                    },\n                    getNodeByParam: function(key, value, parentNode) {\n                        if (!key) return null;\n                        return data.getNodeByParam(setting, parentNode ? parentNode[setting.data.key.children] : data.getNodes(setting), key, value);\n                    },\n                    getNodeByTId: function(tId) {\n                        return data.getNodeCache(setting, tId);\n                    },\n                    getNodesByParam: function(key, value, parentNode) {\n                        if (!key) return null;\n                        return data.getNodesByParam(setting, parentNode ? parentNode[setting.data.key.children] : data.getNodes(setting), key, value);\n                    },\n                    getNodesByParamFuzzy: function(key, value, parentNode) {\n                        if (!key) return null;\n                        return data.getNodesByParamFuzzy(setting, parentNode ? parentNode[setting.data.key.children] : data.getNodes(setting), key, value);\n                    },\n                    getNodesByFilter: function(filter, isSingle, parentNode, invokeParam) {\n                        isSingle = !!isSingle;\n                        if (!filter || (typeof filter != \"function\")) return (isSingle ? null : []);\n                        return data.getNodesByFilter(setting, parentNode ? parentNode[setting.data.key.children] : data.getNodes(setting), filter, isSingle, invokeParam);\n                    },\n                    getNodeIndex: function(node) {\n                        if (!node) return null;\n                        var childKey = setting.data.key.children,\n                            parentNode = (node.parentTId) ? node.getParentNode() : data.getRoot(setting);\n                        for (var i = 0, l = parentNode[childKey].length; i < l; i++) {\n                            if (parentNode[childKey][i] == node) return i;\n                        }\n                        return -1;\n                    },\n                    getSelectedNodes: function() {\n                        var r = [],\n                            list = data.getRoot(setting).curSelectedList;\n                        for (var i = 0, l = list.length; i < l; i++) {\n                            r.push(list[i]);\n                        }\n                        return r;\n                    },\n                    isSelectedNode: function(node) {\n                        return data.isSelectedNode(setting, node);\n                    },\n                    reAsyncChildNodesPromise: function(parentNode, reloadType, isSilent) {\n                        var promise = new Promise(function(resolve, reject) {\n                            try {\n                                zTreeTools.reAsyncChildNodes(parentNode, reloadType, isSilent, function() {\n                                    resolve(parentNode);\n                                });\n                            } catch (e) {\n                                reject(e);\n                            }\n                        });\n                        return promise;\n                    },\n                    reAsyncChildNodes: function(parentNode, reloadType, isSilent, callback) {\n                        if (!this.setting.async.enable) return;\n                        var isRoot = !parentNode;\n                        if (isRoot) {\n                            parentNode = data.getRoot(setting);\n                        }\n                        if (reloadType == \"refresh\") {\n                            var childKey = this.setting.data.key.children;\n                            for (var i = 0, l = parentNode[childKey] ? parentNode[childKey].length : 0; i < l; i++) {\n                                data.removeNodeCache(setting, parentNode[childKey][i]);\n                            }\n                            data.removeSelectedNode(setting);\n                            parentNode[childKey] = [];\n                            if (isRoot) {\n                                this.setting.treeObj.empty();\n                            } else {\n                                var ulObj = $$(parentNode, consts.id.UL, setting);\n                                ulObj.empty();\n                            }\n                        }\n                        view.asyncNode(this.setting, isRoot ? null : parentNode, !!isSilent, callback);\n                    },\n                    refresh: function() {\n                        this.setting.treeObj.empty();\n                        var root = data.getRoot(setting),\n                            nodes = root[setting.data.key.children]\n                        data.initRoot(setting);\n                        root[setting.data.key.children] = nodes\n                        data.initCache(setting);\n                        view.createNodes(setting, 0, root[setting.data.key.children], null, -1);\n                    },\n                    removeChildNodes: function(node) {\n                        if (!node) return null;\n                        var childKey = setting.data.key.children,\n                            nodes = node[childKey];\n                        view.removeChildNodes(setting, node);\n                        return nodes ? nodes : null;\n                    },\n                    removeNode: function(node, callbackFlag) {\n                        if (!node) return;\n                        callbackFlag = !!callbackFlag;\n                        if (callbackFlag && tools.apply(setting.callback.beforeRemove, [setting.treeId, node], true) == false) return;\n                        view.removeNode(setting, node);\n                        if (callbackFlag) {\n                            this.setting.treeObj.trigger(consts.event.REMOVE, [setting.treeId, node]);\n                        }\n                    },\n                    selectNode: function(node, addFlag, isSilent) {\n                        if (!node) return;\n                        if (tools.uCanDo(setting)) {\n                            addFlag = setting.view.selectedMulti && addFlag;\n                            if (node.parentTId) {\n                                view.expandCollapseParentNode(setting, node.getParentNode(), true, false, showNodeFocus);\n                            } else if (!isSilent) {\n                                try {\n                                    $$(node, setting).focus().blur();\n                                } catch (e) {}\n                            }\n                            view.selectNode(setting, node, addFlag);\n                        }\n\n                        function showNodeFocus() {\n                            if (isSilent) {\n                                return;\n                            }\n                            var a = $$(node, setting).get(0);\n                            view.scrollIntoView(a);\n                        }\n                    },\n                    transformTozTreeNodes: function(simpleNodes) {\n                        return data.transformTozTreeFormat(setting, simpleNodes);\n                    },\n                    transformToArray: function(nodes) {\n                        return data.transformToArrayFormat(setting, nodes);\n                    },\n                    updateNode: function(node, checkTypeFlag) {\n                        if (!node) return;\n                        var nObj = $$(node, setting);\n                        if (nObj.get(0) && tools.uCanDo(setting)) {\n                            view.setNodeName(setting, node);\n                            view.setNodeTarget(setting, node);\n                            view.setNodeUrl(setting, node);\n                            view.setNodeLineIcos(setting, node);\n                            view.setNodeFontCss(setting, node);\n                        }\n                    }\n                }\n                root.treeTools = zTreeTools;\n                data.setZTreeTools(setting, zTreeTools);\n\n                if (root[childKey] && root[childKey].length > 0) {\n                    view.createNodes(setting, 0, root[childKey], null, -1);\n                } else if (setting.async.enable && setting.async.url && setting.async.url !== '') {\n                    view.asyncNode(setting);\n                }\n                return zTreeTools;\n            }\n        };\n\n        var zt = $.fn.zTree,\n            $$ = tools.$,\n            consts = zt.consts;\n    })(jQuery);\n    /*\n     * JQuery zTree excheck v3.5.29\n     * http://treejs.cn/\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: 2017-06-19\n     */\n    (function($) {\n        //default consts of excheck\n        var _consts = {\n                event: {\n                    CHECK: \"ztree_check\"\n                },\n                id: {\n                    CHECK: \"_check\"\n                },\n                checkbox: {\n                    STYLE: \"checkbox\",\n                    DEFAULT: \"chk\",\n                    DISABLED: \"disable\",\n                    FALSE: \"false\",\n                    TRUE: \"true\",\n                    FULL: \"full\",\n                    PART: \"part\",\n                    FOCUS: \"focus\"\n                },\n                radio: {\n                    STYLE: \"radio\",\n                    TYPE_ALL: \"all\",\n                    TYPE_LEVEL: \"level\"\n                }\n            },\n            //default setting of excheck\n            _setting = {\n                check: {\n                    enable: false,\n                    autoCheckTrigger: false,\n                    chkStyle: _consts.checkbox.STYLE,\n                    nocheckInherit: false,\n                    chkDisabledInherit: false,\n                    radioType: _consts.radio.TYPE_LEVEL,\n                    chkboxType: {\n                        \"Y\": \"ps\",\n                        \"N\": \"ps\"\n                    }\n                },\n                data: {\n                    key: {\n                        checked: \"checked\"\n                    }\n                },\n                callback: {\n                    beforeCheck: null,\n                    onCheck: null\n                }\n            },\n            //default root of excheck\n            _initRoot = function(setting) {\n                var r = data.getRoot(setting);\n                r.radioCheckedList = [];\n            },\n            //default cache of excheck\n            _initCache = function(treeId) {},\n            //default bind event of excheck\n            _bindEvent = function(setting) {\n                var o = setting.treeObj,\n                    c = consts.event;\n                o.bind(c.CHECK, function(event, srcEvent, treeId, node) {\n                    event.srcEvent = srcEvent;\n                    tools.apply(setting.callback.onCheck, [event, treeId, node]);\n                });\n            },\n            _unbindEvent = function(setting) {\n                var o = setting.treeObj,\n                    c = consts.event;\n                o.unbind(c.CHECK);\n            },\n            //default event proxy of excheck\n            _eventProxy = function(e) {\n                var target = e.target,\n                    setting = data.getSetting(e.data.treeId),\n                    tId = \"\",\n                    node = null,\n                    nodeEventType = \"\",\n                    treeEventType = \"\",\n                    nodeEventCallback = null,\n                    treeEventCallback = null;\n\n                if (tools.eqs(e.type, \"mouseover\")) {\n                    if (setting.check.enable && tools.eqs(target.tagName, \"span\") && target.getAttribute(\"treeNode\" + consts.id.CHECK) !== null) {\n                        tId = tools.getNodeMainDom(target).id;\n                        nodeEventType = \"mouseoverCheck\";\n                    }\n                } else if (tools.eqs(e.type, \"mouseout\")) {\n                    if (setting.check.enable && tools.eqs(target.tagName, \"span\") && target.getAttribute(\"treeNode\" + consts.id.CHECK) !== null) {\n                        tId = tools.getNodeMainDom(target).id;\n                        nodeEventType = \"mouseoutCheck\";\n                    }\n                } else if (tools.eqs(e.type, \"click\")) {\n                    if (setting.check.enable && tools.eqs(target.tagName, \"span\") && target.getAttribute(\"treeNode\" + consts.id.CHECK) !== null) {\n                        tId = tools.getNodeMainDom(target).id;\n                        nodeEventType = \"checkNode\";\n                    }\n                }\n                if (tId.length > 0) {\n                    node = data.getNodeCache(setting, tId);\n                    switch (nodeEventType) {\n                        case \"checkNode\":\n                            nodeEventCallback = _handler.onCheckNode;\n                            break;\n                        case \"mouseoverCheck\":\n                            nodeEventCallback = _handler.onMouseoverCheck;\n                            break;\n                        case \"mouseoutCheck\":\n                            nodeEventCallback = _handler.onMouseoutCheck;\n                            break;\n                    }\n                }\n                var proxyResult = {\n                    stop: nodeEventType === \"checkNode\",\n                    node: node,\n                    nodeEventType: nodeEventType,\n                    nodeEventCallback: nodeEventCallback,\n                    treeEventType: treeEventType,\n                    treeEventCallback: treeEventCallback\n                };\n                return proxyResult\n            },\n            //default init node of excheck\n            _initNode = function(setting, level, n, parentNode, isFirstNode, isLastNode, openFlag) {\n                if (!n) return;\n                var checkedKey = setting.data.key.checked;\n                if (typeof n[checkedKey] == \"string\") n[checkedKey] = tools.eqs(n[checkedKey], \"true\");\n                n[checkedKey] = !!n[checkedKey];\n                n.checkedOld = n[checkedKey];\n                if (typeof n.nocheck == \"string\") n.nocheck = tools.eqs(n.nocheck, \"true\");\n                n.nocheck = !!n.nocheck || (setting.check.nocheckInherit && parentNode && !!parentNode.nocheck);\n                if (typeof n.chkDisabled == \"string\") n.chkDisabled = tools.eqs(n.chkDisabled, \"true\");\n                n.chkDisabled = !!n.chkDisabled || (setting.check.chkDisabledInherit && parentNode && !!parentNode.chkDisabled);\n                if (typeof n.halfCheck == \"string\") n.halfCheck = tools.eqs(n.halfCheck, \"true\");\n                n.halfCheck = !!n.halfCheck;\n                n.check_Child_State = -1;\n                n.check_Focus = false;\n                n.getCheckStatus = function() { return data.getCheckStatus(setting, n); };\n\n                if (setting.check.chkStyle == consts.radio.STYLE && setting.check.radioType == consts.radio.TYPE_ALL && n[checkedKey]) {\n                    var r = data.getRoot(setting);\n                    r.radioCheckedList.push(n);\n                }\n            },\n            //add dom for check\n            _beforeA = function(setting, node, html) {\n                var checkedKey = setting.data.key.checked;\n                if (setting.check.enable) {\n                    data.makeChkFlag(setting, node);\n                    html.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                }\n            },\n            //update zTreeObj, add method of check\n            _zTreeTools = function(setting, zTreeTools) {\n                zTreeTools.checkNode = function(node, checked, checkTypeFlag, callbackFlag) {\n                    var checkedKey = this.setting.data.key.checked;\n                    if (node.chkDisabled === true) return;\n                    if (checked !== true && checked !== false) {\n                        checked = !node[checkedKey];\n                    }\n                    callbackFlag = !!callbackFlag;\n\n                    if (node[checkedKey] === checked && !checkTypeFlag) {\n                        return;\n                    } else if (callbackFlag && tools.apply(this.setting.callback.beforeCheck, [this.setting.treeId, node], true) == false) {\n                        return;\n                    }\n                    if (tools.uCanDo(this.setting) && this.setting.check.enable && node.nocheck !== true) {\n                        node[checkedKey] = checked;\n                        var checkObj = $$(node, consts.id.CHECK, this.setting);\n                        if (checkTypeFlag || this.setting.check.chkStyle === consts.radio.STYLE) view.checkNodeRelation(this.setting, node);\n                        view.setChkClass(this.setting, checkObj, node);\n                        view.repairParentChkClassWithSelf(this.setting, node);\n                        if (callbackFlag) {\n                            this.setting.treeObj.trigger(consts.event.CHECK, [null, this.setting.treeId, node]);\n                        }\n                    }\n                }\n\n                zTreeTools.checkAllNodes = function(checked) {\n                    view.repairAllChk(this.setting, !!checked);\n                }\n\n                zTreeTools.getCheckedNodes = function(checked) {\n                    var childKey = this.setting.data.key.children;\n                    checked = (checked !== false);\n                    return data.getTreeCheckedNodes(this.setting, data.getRoot(this.setting)[childKey], checked);\n                }\n\n                zTreeTools.getChangeCheckedNodes = function() {\n                    var childKey = this.setting.data.key.children;\n                    return data.getTreeChangeCheckedNodes(this.setting, data.getRoot(this.setting)[childKey]);\n                }\n\n                zTreeTools.setChkDisabled = function(node, disabled, inheritParent, inheritChildren) {\n                    disabled = !!disabled;\n                    inheritParent = !!inheritParent;\n                    inheritChildren = !!inheritChildren;\n                    view.repairSonChkDisabled(this.setting, node, disabled, inheritChildren);\n                    view.repairParentChkDisabled(this.setting, node.getParentNode(), disabled, inheritParent);\n                }\n\n                var _updateNode = zTreeTools.updateNode;\n                zTreeTools.updateNode = function(node, checkTypeFlag) {\n                    if (_updateNode) _updateNode.apply(zTreeTools, arguments);\n                    if (!node || !this.setting.check.enable) return;\n                    var nObj = $$(node, this.setting);\n                    if (nObj.get(0) && tools.uCanDo(this.setting)) {\n                        var checkObj = $$(node, consts.id.CHECK, this.setting);\n                        if (checkTypeFlag == true || this.setting.check.chkStyle === consts.radio.STYLE) view.checkNodeRelation(this.setting, node);\n                        view.setChkClass(this.setting, checkObj, node);\n                        view.repairParentChkClassWithSelf(this.setting, node);\n                    }\n                }\n            },\n            //method of operate data\n            _data = {\n                getRadioCheckedList: function(setting) {\n                    var checkedList = data.getRoot(setting).radioCheckedList;\n                    for (var i = 0, j = checkedList.length; i < j; i++) {\n                        if (!data.getNodeCache(setting, checkedList[i].tId)) {\n                            checkedList.splice(i, 1);\n                            i--;\n                            j--;\n                        }\n                    }\n                    return checkedList;\n                },\n                getCheckStatus: function(setting, node) {\n                    if (!setting.check.enable || node.nocheck || node.chkDisabled) return null;\n                    var checkedKey = setting.data.key.checked,\n                        r = {\n                            checked: node[checkedKey],\n                            half: 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                        };\n                    return r;\n                },\n                getTreeCheckedNodes: function(setting, nodes, checked, results) {\n                    if (!nodes) return [];\n                    var childKey = setting.data.key.children,\n                        checkedKey = setting.data.key.checked,\n                        onlyOne = (checked && setting.check.chkStyle == consts.radio.STYLE && setting.check.radioType == consts.radio.TYPE_ALL);\n                    results = !results ? [] : results;\n                    for (var i = 0, l = nodes.length; i < l; i++) {\n                        if (nodes[i].nocheck !== true && nodes[i].chkDisabled !== true && nodes[i][checkedKey] == checked) {\n                            results.push(nodes[i]);\n                            if (onlyOne) {\n                                break;\n                            }\n                        }\n                        data.getTreeCheckedNodes(setting, nodes[i][childKey], checked, results);\n                        if (onlyOne && results.length > 0) {\n                            break;\n                        }\n                    }\n                    return results;\n                },\n                getTreeChangeCheckedNodes: function(setting, nodes, results) {\n                    if (!nodes) return [];\n                    var childKey = setting.data.key.children,\n                        checkedKey = setting.data.key.checked;\n                    results = !results ? [] : results;\n                    for (var i = 0, l = nodes.length; i < l; i++) {\n                        if (nodes[i].nocheck !== true && nodes[i].chkDisabled !== true && nodes[i][checkedKey] != nodes[i].checkedOld) {\n                            results.push(nodes[i]);\n                        }\n                        data.getTreeChangeCheckedNodes(setting, nodes[i][childKey], results);\n                    }\n                    return results;\n                },\n                makeChkFlag: function(setting, node) {\n                    if (!node) return;\n                    var childKey = setting.data.key.children,\n                        checkedKey = setting.data.key.checked,\n                        chkFlag = -1;\n                    if (node[childKey]) {\n                        for (var i = 0, l = node[childKey].length; i < l; i++) {\n                            var cNode = node[childKey][i];\n                            var tmp = -1;\n                            if (setting.check.chkStyle == consts.radio.STYLE) {\n                                if (cNode.nocheck === true || cNode.chkDisabled === true) {\n                                    tmp = cNode.check_Child_State;\n                                } else if (cNode.halfCheck === true) {\n                                    tmp = 2;\n                                } else if (cNode[checkedKey]) {\n                                    tmp = 2;\n                                } else {\n                                    tmp = cNode.check_Child_State > 0 ? 2 : 0;\n                                }\n                                if (tmp == 2) {\n                                    chkFlag = 2;\n                                    break;\n                                } else if (tmp == 0) {\n                                    chkFlag = 0;\n                                }\n                            } else if (setting.check.chkStyle == consts.checkbox.STYLE) {\n                                if (cNode.nocheck === true || cNode.chkDisabled === true) {\n                                    tmp = cNode.check_Child_State;\n                                } else if (cNode.halfCheck === true) {\n                                    tmp = 1;\n                                } else if (cNode[checkedKey]) {\n                                    tmp = (cNode.check_Child_State === -1 || cNode.check_Child_State === 2) ? 2 : 1;\n                                } else {\n                                    tmp = (cNode.check_Child_State > 0) ? 1 : 0;\n                                }\n                                if (tmp === 1) {\n                                    chkFlag = 1;\n                                    break;\n                                } else if (tmp === 2 && chkFlag > -1 && i > 0 && tmp !== chkFlag) {\n                                    chkFlag = 1;\n                                    break;\n                                } else if (chkFlag === 2 && tmp > -1 && tmp < 2) {\n                                    chkFlag = 1;\n                                    break;\n                                } else if (tmp > -1) {\n                                    chkFlag = tmp;\n                                }\n                            }\n                        }\n                    }\n                    node.check_Child_State = chkFlag;\n                }\n            },\n            //method of event proxy\n            _event = {\n\n            },\n            //method of event handler\n            _handler = {\n                onCheckNode: function(event, node) {\n                    if (node.chkDisabled === true) return false;\n                    var setting = data.getSetting(event.data.treeId),\n                        checkedKey = setting.data.key.checked;\n                    if (tools.apply(setting.callback.beforeCheck, [setting.treeId, node], true) == false) return true;\n                    node[checkedKey] = !node[checkedKey];\n                    view.checkNodeRelation(setting, node);\n                    var checkObj = $$(node, consts.id.CHECK, setting);\n                    view.setChkClass(setting, checkObj, node);\n                    view.repairParentChkClassWithSelf(setting, node);\n                    setting.treeObj.trigger(consts.event.CHECK, [event, setting.treeId, node]);\n                    return true;\n                },\n                onMouseoverCheck: function(event, node) {\n                    if (node.chkDisabled === true) return false;\n                    var setting = data.getSetting(event.data.treeId),\n                        checkObj = $$(node, consts.id.CHECK, setting);\n                    node.check_Focus = true;\n                    view.setChkClass(setting, checkObj, node);\n                    return true;\n                },\n                onMouseoutCheck: function(event, node) {\n                    if (node.chkDisabled === true) return false;\n                    var setting = data.getSetting(event.data.treeId),\n                        checkObj = $$(node, consts.id.CHECK, setting);\n                    node.check_Focus = false;\n                    view.setChkClass(setting, checkObj, node);\n                    return true;\n                }\n            },\n            //method of tools for zTree\n            _tools = {\n\n            },\n            //method of operate ztree dom\n            _view = {\n                checkNodeRelation: function(setting, node) {\n                    var pNode, i, l,\n                        childKey = setting.data.key.children,\n                        checkedKey = setting.data.key.checked,\n                        r = consts.radio;\n                    if (setting.check.chkStyle == r.STYLE) {\n                        var checkedList = data.getRadioCheckedList(setting);\n                        if (node[checkedKey]) {\n                            if (setting.check.radioType == r.TYPE_ALL) {\n                                for (i = checkedList.length - 1; i >= 0; i--) {\n                                    pNode = checkedList[i];\n                                    if (pNode[checkedKey] && pNode != node) {\n                                        pNode[checkedKey] = false;\n                                        checkedList.splice(i, 1);\n\n                                        view.setChkClass(setting, $$(pNode, consts.id.CHECK, setting), pNode);\n                                        if (pNode.parentTId != node.parentTId) {\n                                            view.repairParentChkClassWithSelf(setting, pNode);\n                                        }\n                                    }\n                                }\n                                checkedList.push(node);\n                            } else {\n                                var parentNode = (node.parentTId) ? node.getParentNode() : data.getRoot(setting);\n                                for (i = 0, l = parentNode[childKey].length; i < l; i++) {\n                                    pNode = parentNode[childKey][i];\n                                    if (pNode[checkedKey] && pNode != node) {\n                                        pNode[checkedKey] = false;\n                                        view.setChkClass(setting, $$(pNode, consts.id.CHECK, setting), pNode);\n                                    }\n                                }\n                            }\n                        } else if (setting.check.radioType == r.TYPE_ALL) {\n                            for (i = 0, l = checkedList.length; i < l; i++) {\n                                if (node == checkedList[i]) {\n                                    checkedList.splice(i, 1);\n                                    break;\n                                }\n                            }\n                        }\n\n                    } else {\n                        if (node[checkedKey] && (!node[childKey] || node[childKey].length == 0 || setting.check.chkboxType.Y.indexOf(\"s\") > -1)) {\n                            view.setSonNodeCheckBox(setting, node, true);\n                        }\n                        if (!node[checkedKey] && (!node[childKey] || node[childKey].length == 0 || setting.check.chkboxType.N.indexOf(\"s\") > -1)) {\n                            view.setSonNodeCheckBox(setting, node, false);\n                        }\n                        if (node[checkedKey] && setting.check.chkboxType.Y.indexOf(\"p\") > -1) {\n                            view.setParentNodeCheckBox(setting, node, true);\n                        }\n                        if (!node[checkedKey] && setting.check.chkboxType.N.indexOf(\"p\") > -1) {\n                            view.setParentNodeCheckBox(setting, node, false);\n                        }\n                    }\n                },\n                makeChkClass: function(setting, node) {\n                    var checkedKey = setting.data.key.checked,\n                        c = consts.checkbox,\n                        r = consts.radio,\n                        fullStyle = \"\";\n                    if (node.chkDisabled === true) {\n                        fullStyle = c.DISABLED;\n                    } else if (node.halfCheck) {\n                        fullStyle = c.PART;\n                    } else if (setting.check.chkStyle == r.STYLE) {\n                        fullStyle = (node.check_Child_State < 1) ? c.FULL : c.PART;\n                    } else {\n                        fullStyle = 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                    }\n                    var chkName = setting.check.chkStyle + \"_\" + (node[checkedKey] ? c.TRUE : c.FALSE) + \"_\" + fullStyle;\n                    chkName = (node.check_Focus && node.chkDisabled !== true) ? chkName + \"_\" + c.FOCUS : chkName;\n                    return consts.className.BUTTON + \" \" + c.DEFAULT + \" \" + chkName;\n                },\n                repairAllChk: function(setting, checked) {\n                    if (setting.check.enable && setting.check.chkStyle === consts.checkbox.STYLE) {\n                        var checkedKey = setting.data.key.checked,\n                            childKey = setting.data.key.children,\n                            root = data.getRoot(setting);\n                        for (var i = 0, l = root[childKey].length; i < l; i++) {\n                            var node = root[childKey][i];\n                            if (node.nocheck !== true && node.chkDisabled !== true) {\n                                node[checkedKey] = checked;\n                            }\n                            view.setSonNodeCheckBox(setting, node, checked);\n                        }\n                    }\n                },\n                repairChkClass: function(setting, node) {\n                    if (!node) return;\n                    data.makeChkFlag(setting, node);\n                    if (node.nocheck !== true) {\n                        var checkObj = $$(node, consts.id.CHECK, setting);\n                        view.setChkClass(setting, checkObj, node);\n                    }\n                },\n                repairParentChkClass: function(setting, node) {\n                    if (!node || !node.parentTId) return;\n                    var pNode = node.getParentNode();\n                    view.repairChkClass(setting, pNode);\n                    view.repairParentChkClass(setting, pNode);\n                },\n                repairParentChkClassWithSelf: function(setting, node) {\n                    if (!node) return;\n                    var childKey = setting.data.key.children;\n                    if (node[childKey] && node[childKey].length > 0) {\n                        view.repairParentChkClass(setting, node[childKey][0]);\n                    } else {\n                        view.repairParentChkClass(setting, node);\n                    }\n                },\n                repairSonChkDisabled: function(setting, node, chkDisabled, inherit) {\n                    if (!node) return;\n                    var childKey = setting.data.key.children;\n                    if (node.chkDisabled != chkDisabled) {\n                        node.chkDisabled = chkDisabled;\n                    }\n                    view.repairChkClass(setting, node);\n                    if (node[childKey] && inherit) {\n                        for (var i = 0, l = node[childKey].length; i < l; i++) {\n                            var sNode = node[childKey][i];\n                            view.repairSonChkDisabled(setting, sNode, chkDisabled, inherit);\n                        }\n                    }\n                },\n                repairParentChkDisabled: function(setting, node, chkDisabled, inherit) {\n                    if (!node) return;\n                    if (node.chkDisabled != chkDisabled && inherit) {\n                        node.chkDisabled = chkDisabled;\n                    }\n                    view.repairChkClass(setting, node);\n                    view.repairParentChkDisabled(setting, node.getParentNode(), chkDisabled, inherit);\n                },\n                setChkClass: function(setting, obj, node) {\n                    if (!obj) return;\n                    if (node.nocheck === true) {\n                        obj.hide();\n                    } else {\n                        obj.show();\n                    }\n                    obj.attr('class', view.makeChkClass(setting, node));\n                },\n                setParentNodeCheckBox: function(setting, node, value, srcNode) {\n                    var childKey = setting.data.key.children,\n                        checkedKey = setting.data.key.checked,\n                        checkObj = $$(node, consts.id.CHECK, setting);\n                    if (!srcNode) srcNode = node;\n                    data.makeChkFlag(setting, node);\n                    if (node.nocheck !== true && node.chkDisabled !== true) {\n                        node[checkedKey] = value;\n                        view.setChkClass(setting, checkObj, node);\n                        if (setting.check.autoCheckTrigger && node != srcNode) {\n                            setting.treeObj.trigger(consts.event.CHECK, [null, setting.treeId, node]);\n                        }\n                    }\n                    if (node.parentTId) {\n                        var pSign = true;\n                        if (!value) {\n                            var pNodes = node.getParentNode()[childKey];\n                            for (var i = 0, l = pNodes.length; i < l; i++) {\n                                if ((pNodes[i].nocheck !== true && pNodes[i].chkDisabled !== true && pNodes[i][checkedKey]) ||\n                                    ((pNodes[i].nocheck === true || pNodes[i].chkDisabled === true) && pNodes[i].check_Child_State > 0)) {\n                                    pSign = false;\n                                    break;\n                                }\n                            }\n                        }\n                        if (pSign) {\n                            view.setParentNodeCheckBox(setting, node.getParentNode(), value, srcNode);\n                        }\n                    }\n                },\n                setSonNodeCheckBox: function(setting, node, value, srcNode) {\n                    if (!node) return;\n                    var childKey = setting.data.key.children,\n                        checkedKey = setting.data.key.checked,\n                        checkObj = $$(node, consts.id.CHECK, setting);\n                    if (!srcNode) srcNode = node;\n\n                    var hasDisable = false;\n                    if (node[childKey]) {\n                        for (var i = 0, l = node[childKey].length; i < l; i++) {\n                            var sNode = node[childKey][i];\n                            view.setSonNodeCheckBox(setting, sNode, value, srcNode);\n                            if (sNode.chkDisabled === true) hasDisable = true;\n                        }\n                    }\n\n                    if (node != data.getRoot(setting) && node.chkDisabled !== true) {\n                        if (hasDisable && node.nocheck !== true) {\n                            data.makeChkFlag(setting, node);\n                        }\n                        if (node.nocheck !== true && node.chkDisabled !== true) {\n                            node[checkedKey] = value;\n                            if (!hasDisable) node.check_Child_State = (node[childKey] && node[childKey].length > 0) ? (value ? 2 : 0) : -1;\n                        } else {\n                            node.check_Child_State = -1;\n                        }\n                        view.setChkClass(setting, checkObj, node);\n                        if (setting.check.autoCheckTrigger && node != srcNode && node.nocheck !== true && node.chkDisabled !== true) {\n                            setting.treeObj.trigger(consts.event.CHECK, [null, setting.treeId, node]);\n                        }\n                    }\n\n                }\n            },\n\n            _z = {\n                tools: _tools,\n                view: _view,\n                event: _event,\n                data: _data\n            };\n        $.extend(true, $.fn.zTree.consts, _consts);\n        $.extend(true, $.fn.zTree._z, _z);\n\n        var zt = $.fn.zTree,\n            tools = zt._z.tools,\n            consts = zt.consts,\n            view = zt._z.view,\n            data = zt._z.data,\n            event = zt._z.event,\n            $$ = tools.$;\n\n        data.exSetting(_setting);\n        data.addInitBind(_bindEvent);\n        data.addInitUnBind(_unbindEvent);\n        data.addInitCache(_initCache);\n        data.addInitNode(_initNode);\n        data.addInitProxy(_eventProxy, true);\n        data.addInitRoot(_initRoot);\n        data.addBeforeA(_beforeA);\n        data.addZTreeTools(_zTreeTools);\n\n        var _createNodes = view.createNodes;\n        view.createNodes = function(setting, level, nodes, parentNode, index) {\n            if (_createNodes) _createNodes.apply(view, arguments);\n            if (!nodes) return;\n            view.repairParentChkClassWithSelf(setting, parentNode);\n        }\n        var _removeNode = view.removeNode;\n        view.removeNode = function(setting, node) {\n            var parentNode = node.getParentNode();\n            if (_removeNode) _removeNode.apply(view, arguments);\n            if (!node || !parentNode) return;\n            view.repairChkClass(setting, parentNode);\n            view.repairParentChkClass(setting, parentNode);\n        }\n\n        var _appendNodes = view.appendNodes;\n        view.appendNodes = function(setting, level, nodes, parentNode, index, initFlag, openFlag) {\n            var html = \"\";\n            if (_appendNodes) {\n                html = _appendNodes.apply(view, arguments);\n            }\n            if (parentNode) {\n                data.makeChkFlag(setting, parentNode);\n            }\n            return html;\n        }\n    })(jQuery);\n    /*\n     * JQuery zTree exedit v3.5.29\n     * http://treejs.cn/\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: 2017-06-19\n     */\n    (function($) {\n        //default consts of exedit\n        var _consts = {\n                event: {\n                    DRAG: \"ztree_drag\",\n                    DROP: \"ztree_drop\",\n                    RENAME: \"ztree_rename\",\n                    DRAGMOVE: \"ztree_dragmove\"\n                },\n                id: {\n                    EDIT: \"_edit\",\n                    INPUT: \"_input\",\n                    REMOVE: \"_remove\"\n                },\n                move: {\n                    TYPE_INNER: \"inner\",\n                    TYPE_PREV: \"prev\",\n                    TYPE_NEXT: \"next\"\n                },\n                node: {\n                    CURSELECTED_EDIT: \"curSelectedNode_Edit\",\n                    TMPTARGET_TREE: \"tmpTargetzTree\",\n                    TMPTARGET_NODE: \"tmpTargetNode\"\n                }\n            },\n            //default setting of exedit\n            _setting = {\n                edit: {\n                    enable: false,\n                    editNameSelectAll: false,\n                    showRemoveBtn: true,\n                    showRenameBtn: true,\n                    removeTitle: \"remove\",\n                    renameTitle: \"rename\",\n                    drag: {\n                        autoExpandTrigger: false,\n                        isCopy: true,\n                        isMove: true,\n                        prev: true,\n                        next: true,\n                        inner: true,\n                        minMoveSize: 5,\n                        borderMax: 10,\n                        borderMin: -5,\n                        maxShowNodeNum: 5,\n                        autoOpenTime: 500\n                    }\n                },\n                view: {\n                    addHoverDom: null,\n                    removeHoverDom: null\n                },\n                callback: {\n                    beforeDrag: null,\n                    beforeDragOpen: null,\n                    beforeDrop: null,\n                    beforeEditName: null,\n                    beforeRename: null,\n                    onDrag: null,\n                    onDragMove: null,\n                    onDrop: null,\n                    onRename: null\n                }\n            },\n            //default root of exedit\n            _initRoot = function(setting) {\n                var r = data.getRoot(setting),\n                    rs = data.getRoots();\n                r.curEditNode = null;\n                r.curEditInput = null;\n                r.curHoverNode = null;\n                r.dragFlag = 0;\n                r.dragNodeShowBefore = [];\n                r.dragMaskList = new Array();\n                rs.showHoverDom = true;\n            },\n            //default cache of exedit\n            _initCache = function(treeId) {},\n            //default bind event of exedit\n            _bindEvent = function(setting) {\n                var o = setting.treeObj;\n                var c = consts.event;\n                o.bind(c.RENAME, function(event, treeId, treeNode, isCancel) {\n                    tools.apply(setting.callback.onRename, [event, treeId, treeNode, isCancel]);\n                });\n\n                o.bind(c.DRAG, function(event, srcEvent, treeId, treeNodes) {\n                    tools.apply(setting.callback.onDrag, [srcEvent, treeId, treeNodes]);\n                });\n\n                o.bind(c.DRAGMOVE, function(event, srcEvent, treeId, treeNodes) {\n                    tools.apply(setting.callback.onDragMove, [srcEvent, treeId, treeNodes]);\n                });\n\n                o.bind(c.DROP, function(event, srcEvent, treeId, treeNodes, targetNode, moveType, isCopy) {\n                    tools.apply(setting.callback.onDrop, [srcEvent, treeId, treeNodes, targetNode, moveType, isCopy]);\n                });\n            },\n            _unbindEvent = function(setting) {\n                var o = setting.treeObj;\n                var c = consts.event;\n                o.unbind(c.RENAME);\n                o.unbind(c.DRAG);\n                o.unbind(c.DRAGMOVE);\n                o.unbind(c.DROP);\n            },\n            //default event proxy of exedit\n            _eventProxy = function(e) {\n                var target = e.target,\n                    setting = data.getSetting(e.data.treeId),\n                    relatedTarget = e.relatedTarget,\n                    tId = \"\",\n                    node = null,\n                    nodeEventType = \"\",\n                    treeEventType = \"\",\n                    nodeEventCallback = null,\n                    treeEventCallback = null,\n                    tmp = null;\n\n                if (tools.eqs(e.type, \"mouseover\")) {\n                    tmp = tools.getMDom(setting, target, [{ tagName: \"a\", attrName: \"treeNode\" + consts.id.A }]);\n                    if (tmp) {\n                        tId = tools.getNodeMainDom(tmp).id;\n                        nodeEventType = \"hoverOverNode\";\n                    }\n                } else if (tools.eqs(e.type, \"mouseout\")) {\n                    tmp = tools.getMDom(setting, relatedTarget, [{ tagName: \"a\", attrName: \"treeNode\" + consts.id.A }]);\n                    if (!tmp) {\n                        tId = \"remove\";\n                        nodeEventType = \"hoverOutNode\";\n                    }\n                } else if (tools.eqs(e.type, \"mousedown\")) {\n                    tmp = tools.getMDom(setting, target, [{ tagName: \"a\", attrName: \"treeNode\" + consts.id.A }]);\n                    if (tmp) {\n                        tId = tools.getNodeMainDom(tmp).id;\n                        nodeEventType = \"mousedownNode\";\n                    }\n                }\n                if (tId.length > 0) {\n                    node = data.getNodeCache(setting, tId);\n                    switch (nodeEventType) {\n                        case \"mousedownNode\":\n                            nodeEventCallback = _handler.onMousedownNode;\n                            break;\n                        case \"hoverOverNode\":\n                            nodeEventCallback = _handler.onHoverOverNode;\n                            break;\n                        case \"hoverOutNode\":\n                            nodeEventCallback = _handler.onHoverOutNode;\n                            break;\n                    }\n                }\n                var proxyResult = {\n                    stop: false,\n                    node: node,\n                    nodeEventType: nodeEventType,\n                    nodeEventCallback: nodeEventCallback,\n                    treeEventType: treeEventType,\n                    treeEventCallback: treeEventCallback\n                };\n                return proxyResult\n            },\n            //default init node of exedit\n            _initNode = function(setting, level, n, parentNode, isFirstNode, isLastNode, openFlag) {\n                if (!n) return;\n                n.isHover = false;\n                n.editNameFlag = false;\n            },\n            //update zTreeObj, add method of edit\n            _zTreeTools = function(setting, zTreeTools) {\n                zTreeTools.cancelEditName = function(newName) {\n                    var root = data.getRoot(this.setting);\n                    if (!root.curEditNode) return;\n                    view.cancelCurEditNode(this.setting, newName ? newName : null, true);\n                }\n                zTreeTools.copyNode = function(targetNode, node, moveType, isSilent) {\n                    if (!node) return null;\n                    if (targetNode && !targetNode.isParent && this.setting.data.keep.leaf && moveType === consts.move.TYPE_INNER) return null;\n                    var _this = this,\n                        newNode = tools.clone(node);\n                    if (!targetNode) {\n                        targetNode = null;\n                        moveType = consts.move.TYPE_INNER;\n                    }\n                    if (moveType == consts.move.TYPE_INNER) {\n                        function copyCallback() {\n                            view.addNodes(_this.setting, targetNode, -1, [newNode], isSilent);\n                        }\n\n                        if (tools.canAsync(this.setting, targetNode)) {\n                            view.asyncNode(this.setting, targetNode, isSilent, copyCallback);\n                        } else {\n                            copyCallback();\n                        }\n                    } else {\n                        view.addNodes(this.setting, targetNode.parentNode, -1, [newNode], isSilent);\n                        view.moveNode(this.setting, targetNode, newNode, moveType, false, isSilent);\n                    }\n                    return newNode;\n                }\n                zTreeTools.editName = function(node) {\n                    if (!node || !node.tId || node !== data.getNodeCache(this.setting, node.tId)) return;\n                    if (node.parentTId) view.expandCollapseParentNode(this.setting, node.getParentNode(), true);\n                    view.editNode(this.setting, node)\n                }\n                zTreeTools.moveNode = function(targetNode, node, moveType, isSilent) {\n                    if (!node) return node;\n                    if (targetNode && !targetNode.isParent && this.setting.data.keep.leaf && moveType === consts.move.TYPE_INNER) {\n                        return null;\n                    } else if (targetNode && ((node.parentTId == targetNode.tId && moveType == consts.move.TYPE_INNER) || $$(node, this.setting).find(\"#\" + targetNode.tId).length > 0)) {\n                        return null;\n                    } else if (!targetNode) {\n                        targetNode = null;\n                    }\n                    var _this = this;\n\n                    function moveCallback() {\n                        view.moveNode(_this.setting, targetNode, node, moveType, false, isSilent);\n                    }\n                    if (tools.canAsync(this.setting, targetNode) && moveType === consts.move.TYPE_INNER) {\n                        view.asyncNode(this.setting, targetNode, isSilent, moveCallback);\n                    } else {\n                        moveCallback();\n                    }\n                    return node;\n                }\n                zTreeTools.setEditable = function(editable) {\n                    this.setting.edit.enable = editable;\n                    return this.refresh();\n                }\n            },\n            //method of operate data\n            _data = {\n                setSonNodeLevel: function(setting, parentNode, node) {\n                    if (!node) return;\n                    var childKey = setting.data.key.children;\n                    node.level = (parentNode) ? parentNode.level + 1 : 0;\n                    if (!node[childKey]) return;\n                    for (var i = 0, l = node[childKey].length; i < l; i++) {\n                        if (node[childKey][i]) data.setSonNodeLevel(setting, node, node[childKey][i]);\n                    }\n                }\n            },\n            //method of event proxy\n            _event = {\n\n            },\n            //method of event handler\n            _handler = {\n                onHoverOverNode: function(event, node) {\n                    var setting = data.getSetting(event.data.treeId),\n                        root = data.getRoot(setting);\n                    if (root.curHoverNode != node) {\n                        _handler.onHoverOutNode(event);\n                    }\n                    root.curHoverNode = node;\n                    view.addHoverDom(setting, node);\n                },\n                onHoverOutNode: function(event, node) {\n                    var setting = data.getSetting(event.data.treeId),\n                        root = data.getRoot(setting);\n                    if (root.curHoverNode && !data.isSelectedNode(setting, root.curHoverNode)) {\n                        view.removeTreeDom(setting, root.curHoverNode);\n                        root.curHoverNode = null;\n                    }\n                },\n                onMousedownNode: function(eventMouseDown, _node) {\n                    var i, l,\n                        setting = data.getSetting(eventMouseDown.data.treeId),\n                        root = data.getRoot(setting),\n                        roots = data.getRoots();\n                    //right click can't drag & drop\n                    if (eventMouseDown.button == 2 || !setting.edit.enable || (!setting.edit.drag.isCopy && !setting.edit.drag.isMove)) return true;\n\n                    //input of edit node name can't drag & drop\n                    var target = eventMouseDown.target,\n                        _nodes = data.getRoot(setting).curSelectedList,\n                        nodes = [];\n                    if (!data.isSelectedNode(setting, _node)) {\n                        nodes = [_node];\n                    } else {\n                        for (i = 0, l = _nodes.length; i < l; i++) {\n                            if (_nodes[i].editNameFlag && tools.eqs(target.tagName, \"input\") && target.getAttribute(\"treeNode\" + consts.id.INPUT) !== null) {\n                                return true;\n                            }\n                            nodes.push(_nodes[i]);\n                            if (nodes[0].parentTId !== _nodes[i].parentTId) {\n                                nodes = [_node];\n                                break;\n                            }\n                        }\n                    }\n\n                    view.editNodeBlur = true;\n                    view.cancelCurEditNode(setting);\n\n                    var doc = $(setting.treeObj.get(0).ownerDocument),\n                        body = $(setting.treeObj.get(0).ownerDocument.body),\n                        curNode, tmpArrow, tmpTarget,\n                        isOtherTree = false,\n                        targetSetting = setting,\n                        sourceSetting = setting,\n                        preNode, nextNode,\n                        preTmpTargetNodeId = null,\n                        preTmpMoveType = null,\n                        tmpTargetNodeId = null,\n                        moveType = consts.move.TYPE_INNER,\n                        mouseDownX = eventMouseDown.clientX,\n                        mouseDownY = eventMouseDown.clientY,\n                        startTime = (new Date()).getTime();\n\n                    if (tools.uCanDo(setting)) {\n                        doc.bind(\"mousemove\", _docMouseMove);\n                    }\n\n                    function _docMouseMove(event) {\n                        //avoid start drag after click node\n                        if (root.dragFlag == 0 && Math.abs(mouseDownX - event.clientX) < setting.edit.drag.minMoveSize &&\n                            Math.abs(mouseDownY - event.clientY) < setting.edit.drag.minMoveSize) {\n                            return true;\n                        }\n                        var i, l, tmpNode, tmpDom, tmpNodes,\n                            childKey = setting.data.key.children;\n                        body.css(\"cursor\", \"pointer\");\n\n                        if (root.dragFlag == 0) {\n                            if (tools.apply(setting.callback.beforeDrag, [setting.treeId, nodes], true) == false) {\n                                _docMouseUp(event);\n                                return true;\n                            }\n\n                            for (i = 0, l = nodes.length; i < l; i++) {\n                                if (i == 0) {\n                                    root.dragNodeShowBefore = [];\n                                }\n                                tmpNode = nodes[i];\n                                if (tmpNode.isParent && tmpNode.open) {\n                                    view.expandCollapseNode(setting, tmpNode, !tmpNode.open);\n                                    root.dragNodeShowBefore[tmpNode.tId] = true;\n                                } else {\n                                    root.dragNodeShowBefore[tmpNode.tId] = false;\n                                }\n                            }\n\n                            root.dragFlag = 1;\n                            roots.showHoverDom = false;\n                            tools.showIfameMask(setting, true);\n\n                            //sort\n                            var isOrder = true,\n                                lastIndex = -1;\n                            if (nodes.length > 1) {\n                                var pNodes = nodes[0].parentTId ? nodes[0].getParentNode()[childKey] : data.getNodes(setting);\n                                tmpNodes = [];\n                                for (i = 0, l = pNodes.length; i < l; i++) {\n                                    if (root.dragNodeShowBefore[pNodes[i].tId] !== undefined) {\n                                        if (isOrder && lastIndex > -1 && (lastIndex + 1) !== i) {\n                                            isOrder = false;\n                                        }\n                                        tmpNodes.push(pNodes[i]);\n                                        lastIndex = i;\n                                    }\n                                    if (nodes.length === tmpNodes.length) {\n                                        nodes = tmpNodes;\n                                        break;\n                                    }\n                                }\n                            }\n                            if (isOrder) {\n                                preNode = nodes[0].getPreNode();\n                                nextNode = nodes[nodes.length - 1].getNextNode();\n                            }\n\n                            //set node in selected\n                            curNode = $$(\"<ul class='zTreeDragUL'></ul>\", setting);\n                            for (i = 0, l = nodes.length; i < l; i++) {\n                                tmpNode = nodes[i];\n                                tmpNode.editNameFlag = false;\n                                view.selectNode(setting, tmpNode, i > 0);\n                                view.removeTreeDom(setting, tmpNode);\n\n                                if (i > setting.edit.drag.maxShowNodeNum - 1) {\n                                    continue;\n                                }\n\n                                tmpDom = $$(\"<li id='\" + tmpNode.tId + \"_tmp'></li>\", setting);\n                                tmpDom.append($$(tmpNode, consts.id.A, setting).clone());\n                                tmpDom.css(\"padding\", \"0\");\n                                tmpDom.children(\"#\" + tmpNode.tId + consts.id.A).removeClass(consts.node.CURSELECTED);\n                                curNode.append(tmpDom);\n                                if (i == setting.edit.drag.maxShowNodeNum - 1) {\n                                    tmpDom = $$(\"<li id='\" + tmpNode.tId + \"_moretmp'><a>  ...  </a></li>\", setting);\n                                    curNode.append(tmpDom);\n                                }\n                            }\n                            curNode.attr(\"id\", nodes[0].tId + consts.id.UL + \"_tmp\");\n                            curNode.addClass(setting.treeObj.attr(\"class\"));\n                            curNode.appendTo(body);\n\n                            tmpArrow = $$(\"<span class='tmpzTreeMove_arrow'></span>\", setting);\n                            tmpArrow.attr(\"id\", \"zTreeMove_arrow_tmp\");\n                            tmpArrow.appendTo(body);\n\n                            setting.treeObj.trigger(consts.event.DRAG, [event, setting.treeId, nodes]);\n                        }\n\n                        if (root.dragFlag == 1) {\n                            if (tmpTarget && tmpArrow.attr(\"id\") == event.target.id && tmpTargetNodeId && (event.clientX + doc.scrollLeft() + 2) > ($(\"#\" + tmpTargetNodeId + consts.id.A, tmpTarget).offset().left)) {\n                                var xT = $(\"#\" + tmpTargetNodeId + consts.id.A, tmpTarget);\n                                event.target = (xT.length > 0) ? xT.get(0) : event.target;\n                            } else if (tmpTarget) {\n                                tmpTarget.removeClass(consts.node.TMPTARGET_TREE);\n                                if (tmpTargetNodeId) $(\"#\" + tmpTargetNodeId + consts.id.A, tmpTarget).removeClass(consts.node.TMPTARGET_NODE + \"_\" + consts.move.TYPE_PREV)\n                                    .removeClass(consts.node.TMPTARGET_NODE + \"_\" + _consts.move.TYPE_NEXT).removeClass(consts.node.TMPTARGET_NODE + \"_\" + _consts.move.TYPE_INNER);\n                            }\n                            tmpTarget = null;\n                            tmpTargetNodeId = null;\n\n                            //judge drag & drop in multi ztree\n                            isOtherTree = false;\n                            targetSetting = setting;\n                            var settings = data.getSettings();\n                            for (var s in settings) {\n                                if (settings[s].treeId && settings[s].edit.enable && settings[s].treeId != setting.treeId &&\n                                    (event.target.id == settings[s].treeId || $(event.target).parents(\"#\" + settings[s].treeId).length > 0)) {\n                                    isOtherTree = true;\n                                    targetSetting = settings[s];\n                                }\n                            }\n\n                            var docScrollTop = doc.scrollTop(),\n                                docScrollLeft = doc.scrollLeft(),\n                                treeOffset = targetSetting.treeObj.offset(),\n                                scrollHeight = targetSetting.treeObj.get(0).scrollHeight,\n                                scrollWidth = targetSetting.treeObj.get(0).scrollWidth,\n                                dTop = (event.clientY + docScrollTop - treeOffset.top),\n                                dBottom = (targetSetting.treeObj.height() + treeOffset.top - event.clientY - docScrollTop),\n                                dLeft = (event.clientX + docScrollLeft - treeOffset.left),\n                                dRight = (targetSetting.treeObj.width() + treeOffset.left - event.clientX - docScrollLeft),\n                                isTop = (dTop < setting.edit.drag.borderMax && dTop > setting.edit.drag.borderMin),\n                                isBottom = (dBottom < setting.edit.drag.borderMax && dBottom > setting.edit.drag.borderMin),\n                                isLeft = (dLeft < setting.edit.drag.borderMax && dLeft > setting.edit.drag.borderMin),\n                                isRight = (dRight < setting.edit.drag.borderMax && dRight > setting.edit.drag.borderMin),\n                                isTreeInner = dTop > setting.edit.drag.borderMin && dBottom > setting.edit.drag.borderMin && dLeft > setting.edit.drag.borderMin && dRight > setting.edit.drag.borderMin,\n                                isTreeTop = (isTop && targetSetting.treeObj.scrollTop() <= 0),\n                                isTreeBottom = (isBottom && (targetSetting.treeObj.scrollTop() + targetSetting.treeObj.height() + 10) >= scrollHeight),\n                                isTreeLeft = (isLeft && targetSetting.treeObj.scrollLeft() <= 0),\n                                isTreeRight = (isRight && (targetSetting.treeObj.scrollLeft() + targetSetting.treeObj.width() + 10) >= scrollWidth);\n\n                            if (event.target && tools.isChildOrSelf(event.target, targetSetting.treeId)) {\n                                //get node <li> dom\n                                var targetObj = event.target;\n                                while (targetObj && targetObj.tagName && !tools.eqs(targetObj.tagName, \"li\") && targetObj.id != targetSetting.treeId) {\n                                    targetObj = targetObj.parentNode;\n                                }\n\n                                var canMove = true;\n                                //don't move to self or children of self\n                                for (i = 0, l = nodes.length; i < l; i++) {\n                                    tmpNode = nodes[i];\n                                    if (targetObj.id === tmpNode.tId) {\n                                        canMove = false;\n                                        break;\n                                    } else if ($$(tmpNode, setting).find(\"#\" + targetObj.id).length > 0) {\n                                        canMove = false;\n                                        break;\n                                    }\n                                }\n                                if (canMove && event.target && tools.isChildOrSelf(event.target, targetObj.id + consts.id.A)) {\n                                    tmpTarget = $(targetObj);\n                                    tmpTargetNodeId = targetObj.id;\n                                }\n                            }\n\n                            //the mouse must be in zTree\n                            tmpNode = nodes[0];\n                            if (isTreeInner && tools.isChildOrSelf(event.target, targetSetting.treeId)) {\n                                //judge mouse move in root of ztree\n                                if (!tmpTarget && (event.target.id == targetSetting.treeId || isTreeTop || isTreeBottom || isTreeLeft || isTreeRight) && (isOtherTree || (!isOtherTree && tmpNode.parentTId))) {\n                                    tmpTarget = targetSetting.treeObj;\n                                }\n                                //auto scroll top\n                                if (isTop) {\n                                    targetSetting.treeObj.scrollTop(targetSetting.treeObj.scrollTop() - 10);\n                                } else if (isBottom) {\n                                    targetSetting.treeObj.scrollTop(targetSetting.treeObj.scrollTop() + 10);\n                                }\n                                if (isLeft) {\n                                    targetSetting.treeObj.scrollLeft(targetSetting.treeObj.scrollLeft() - 10);\n                                } else if (isRight) {\n                                    targetSetting.treeObj.scrollLeft(targetSetting.treeObj.scrollLeft() + 10);\n                                }\n                                //auto scroll left\n                                if (tmpTarget && tmpTarget != targetSetting.treeObj && tmpTarget.offset().left < targetSetting.treeObj.offset().left) {\n                                    targetSetting.treeObj.scrollLeft(targetSetting.treeObj.scrollLeft() + tmpTarget.offset().left - targetSetting.treeObj.offset().left);\n                                }\n                            }\n\n                            curNode.css({\n                                \"top\": (event.clientY + docScrollTop + 3) + \"px\",\n                                \"left\": (event.clientX + docScrollLeft + 3) + \"px\"\n                            });\n\n                            var dX = 0;\n                            var dY = 0;\n                            if (tmpTarget && tmpTarget.attr(\"id\") != targetSetting.treeId) {\n                                var tmpTargetNode = tmpTargetNodeId == null ? null : data.getNodeCache(targetSetting, tmpTargetNodeId),\n                                    isCopy = ((event.ctrlKey || event.metaKey) && setting.edit.drag.isMove && setting.edit.drag.isCopy) || (!setting.edit.drag.isMove && setting.edit.drag.isCopy),\n                                    isPrev = !!(preNode && tmpTargetNodeId === preNode.tId),\n                                    isNext = !!(nextNode && tmpTargetNodeId === nextNode.tId),\n                                    isInner = (tmpNode.parentTId && tmpNode.parentTId == tmpTargetNodeId),\n                                    canPrev = (isCopy || !isNext) && tools.apply(targetSetting.edit.drag.prev, [targetSetting.treeId, nodes, tmpTargetNode], !!targetSetting.edit.drag.prev),\n                                    canNext = (isCopy || !isPrev) && tools.apply(targetSetting.edit.drag.next, [targetSetting.treeId, nodes, tmpTargetNode], !!targetSetting.edit.drag.next),\n                                    canInner = (isCopy || !isInner) && !(targetSetting.data.keep.leaf && !tmpTargetNode.isParent) && tools.apply(targetSetting.edit.drag.inner, [targetSetting.treeId, nodes, tmpTargetNode], !!targetSetting.edit.drag.inner);\n\n                                function clearMove() {\n                                    tmpTarget = null;\n                                    tmpTargetNodeId = \"\";\n                                    moveType = consts.move.TYPE_INNER;\n                                    tmpArrow.css({\n                                        \"display\": \"none\"\n                                    });\n                                    if (window.zTreeMoveTimer) {\n                                        clearTimeout(window.zTreeMoveTimer);\n                                        window.zTreeMoveTargetNodeTId = null\n                                    }\n                                }\n                                if (!canPrev && !canNext && !canInner) {\n                                    clearMove();\n                                } else {\n                                    var tmpTargetA = $(\"#\" + tmpTargetNodeId + consts.id.A, tmpTarget),\n                                        tmpNextA = tmpTargetNode.isLastNode ? null : $(\"#\" + tmpTargetNode.getNextNode().tId + consts.id.A, tmpTarget.next()),\n                                        tmpTop = tmpTargetA.offset().top,\n                                        tmpLeft = tmpTargetA.offset().left,\n                                        prevPercent = canPrev ? (canInner ? 0.25 : (canNext ? 0.5 : 1)) : -1,\n                                        nextPercent = canNext ? (canInner ? 0.75 : (canPrev ? 0.5 : 0)) : -1,\n                                        dY_percent = (event.clientY + docScrollTop - tmpTop) / tmpTargetA.height();\n\n                                    if ((prevPercent == 1 || dY_percent <= prevPercent && dY_percent >= -.2) && canPrev) {\n                                        dX = 1 - tmpArrow.width();\n                                        dY = tmpTop - tmpArrow.height() / 2;\n                                        moveType = consts.move.TYPE_PREV;\n                                    } else if ((nextPercent == 0 || dY_percent >= nextPercent && dY_percent <= 1.2) && canNext) {\n                                        dX = 1 - tmpArrow.width();\n                                        dY = (tmpNextA == null || (tmpTargetNode.isParent && tmpTargetNode.open)) ? (tmpTop + tmpTargetA.height() - tmpArrow.height() / 2) : (tmpNextA.offset().top - tmpArrow.height() / 2);\n                                        moveType = consts.move.TYPE_NEXT;\n                                    } else if (canInner) {\n                                        dX = 5 - tmpArrow.width();\n                                        dY = tmpTop;\n                                        moveType = consts.move.TYPE_INNER;\n                                    } else {\n                                        clearMove();\n                                    }\n\n                                    if (tmpTarget) {\n                                        tmpArrow.css({\n                                            \"display\": \"block\",\n                                            \"top\": dY + \"px\",\n                                            \"left\": (tmpLeft + dX) + \"px\"\n                                        });\n                                        tmpTargetA.addClass(consts.node.TMPTARGET_NODE + \"_\" + moveType);\n\n                                        if (preTmpTargetNodeId != tmpTargetNodeId || preTmpMoveType != moveType) {\n                                            startTime = (new Date()).getTime();\n                                        }\n                                        if (tmpTargetNode && tmpTargetNode.isParent && moveType == consts.move.TYPE_INNER) {\n                                            var startTimer = true;\n                                            if (window.zTreeMoveTimer && window.zTreeMoveTargetNodeTId !== tmpTargetNode.tId) {\n                                                clearTimeout(window.zTreeMoveTimer);\n                                                window.zTreeMoveTargetNodeTId = null;\n                                            } else if (window.zTreeMoveTimer && window.zTreeMoveTargetNodeTId === tmpTargetNode.tId) {\n                                                startTimer = false;\n                                            }\n                                            if (startTimer) {\n                                                window.zTreeMoveTimer = setTimeout(function() {\n                                                    if (moveType != consts.move.TYPE_INNER) return;\n                                                    if (tmpTargetNode && tmpTargetNode.isParent && !tmpTargetNode.open && (new Date()).getTime() - startTime > targetSetting.edit.drag.autoOpenTime &&\n                                                        tools.apply(targetSetting.callback.beforeDragOpen, [targetSetting.treeId, tmpTargetNode], true)) {\n                                                        view.switchNode(targetSetting, tmpTargetNode);\n                                                        if (targetSetting.edit.drag.autoExpandTrigger) {\n                                                            targetSetting.treeObj.trigger(consts.event.EXPAND, [targetSetting.treeId, tmpTargetNode]);\n                                                        }\n                                                    }\n                                                }, targetSetting.edit.drag.autoOpenTime + 50);\n                                                window.zTreeMoveTargetNodeTId = tmpTargetNode.tId;\n                                            }\n                                        }\n                                    }\n                                }\n                            } else {\n                                moveType = consts.move.TYPE_INNER;\n                                if (tmpTarget && tools.apply(targetSetting.edit.drag.inner, [targetSetting.treeId, nodes, null], !!targetSetting.edit.drag.inner)) {\n                                    tmpTarget.addClass(consts.node.TMPTARGET_TREE);\n                                } else {\n                                    tmpTarget = null;\n                                }\n                                tmpArrow.css({\n                                    \"display\": \"none\"\n                                });\n                                if (window.zTreeMoveTimer) {\n                                    clearTimeout(window.zTreeMoveTimer);\n                                    window.zTreeMoveTargetNodeTId = null;\n                                }\n                            }\n                            preTmpTargetNodeId = tmpTargetNodeId;\n                            preTmpMoveType = moveType;\n\n                            setting.treeObj.trigger(consts.event.DRAGMOVE, [event, setting.treeId, nodes]);\n                        }\n                        return false;\n                    }\n\n                    doc.bind(\"mouseup\", _docMouseUp);\n\n                    function _docMouseUp(event) {\n                        if (window.zTreeMoveTimer) {\n                            clearTimeout(window.zTreeMoveTimer);\n                            window.zTreeMoveTargetNodeTId = null;\n                        }\n                        preTmpTargetNodeId = null;\n                        preTmpMoveType = null;\n                        doc.unbind(\"mousemove\", _docMouseMove);\n                        doc.unbind(\"mouseup\", _docMouseUp);\n                        doc.unbind(\"selectstart\", _docSelect);\n                        body.css(\"cursor\", \"\");\n                        if (tmpTarget) {\n                            tmpTarget.removeClass(consts.node.TMPTARGET_TREE);\n                            if (tmpTargetNodeId) $(\"#\" + tmpTargetNodeId + consts.id.A, tmpTarget).removeClass(consts.node.TMPTARGET_NODE + \"_\" + consts.move.TYPE_PREV)\n                                .removeClass(consts.node.TMPTARGET_NODE + \"_\" + _consts.move.TYPE_NEXT).removeClass(consts.node.TMPTARGET_NODE + \"_\" + _consts.move.TYPE_INNER);\n                        }\n                        tools.showIfameMask(setting, false);\n\n                        roots.showHoverDom = true;\n                        if (root.dragFlag == 0) return;\n                        root.dragFlag = 0;\n\n                        var i, l, tmpNode;\n                        for (i = 0, l = nodes.length; i < l; i++) {\n                            tmpNode = nodes[i];\n                            if (tmpNode.isParent && root.dragNodeShowBefore[tmpNode.tId] && !tmpNode.open) {\n                                view.expandCollapseNode(setting, tmpNode, !tmpNode.open);\n                                delete root.dragNodeShowBefore[tmpNode.tId];\n                            }\n                        }\n\n                        if (curNode) curNode.remove();\n                        if (tmpArrow) tmpArrow.remove();\n\n                        var isCopy = ((event.ctrlKey || event.metaKey) && setting.edit.drag.isMove && setting.edit.drag.isCopy) || (!setting.edit.drag.isMove && setting.edit.drag.isCopy);\n                        if (!isCopy && tmpTarget && tmpTargetNodeId && nodes[0].parentTId && tmpTargetNodeId == nodes[0].parentTId && moveType == consts.move.TYPE_INNER) {\n                            tmpTarget = null;\n                        }\n                        if (tmpTarget) {\n                            var dragTargetNode = tmpTargetNodeId == null ? null : data.getNodeCache(targetSetting, tmpTargetNodeId);\n                            if (tools.apply(setting.callback.beforeDrop, [targetSetting.treeId, nodes, dragTargetNode, moveType, isCopy], true) == false) {\n                                view.selectNodes(sourceSetting, nodes);\n                                return;\n                            }\n                            var newNodes = isCopy ? tools.clone(nodes) : nodes;\n\n                            function dropCallback() {\n                                if (isOtherTree) {\n                                    if (!isCopy) {\n                                        for (var i = 0, l = nodes.length; i < l; i++) {\n                                            view.removeNode(setting, nodes[i]);\n                                        }\n                                    }\n                                    if (moveType == consts.move.TYPE_INNER) {\n                                        view.addNodes(targetSetting, dragTargetNode, -1, newNodes);\n                                    } else {\n                                        view.addNodes(targetSetting, dragTargetNode.getParentNode(), moveType == consts.move.TYPE_PREV ? dragTargetNode.getIndex() : dragTargetNode.getIndex() + 1, newNodes);\n                                    }\n                                } else {\n                                    if (isCopy && moveType == consts.move.TYPE_INNER) {\n                                        view.addNodes(targetSetting, dragTargetNode, -1, newNodes);\n                                    } else if (isCopy) {\n                                        view.addNodes(targetSetting, dragTargetNode.getParentNode(), moveType == consts.move.TYPE_PREV ? dragTargetNode.getIndex() : dragTargetNode.getIndex() + 1, newNodes);\n                                    } else {\n                                        if (moveType != consts.move.TYPE_NEXT) {\n                                            for (i = 0, l = newNodes.length; i < l; i++) {\n                                                view.moveNode(targetSetting, dragTargetNode, newNodes[i], moveType, false);\n                                            }\n                                        } else {\n                                            for (i = -1, l = newNodes.length - 1; i < l; l--) {\n                                                view.moveNode(targetSetting, dragTargetNode, newNodes[l], moveType, false);\n                                            }\n                                        }\n                                    }\n                                }\n                                view.selectNodes(targetSetting, newNodes);\n\n                                var a = $$(newNodes[0], setting).get(0);\n                                view.scrollIntoView(a);\n\n                                setting.treeObj.trigger(consts.event.DROP, [event, targetSetting.treeId, newNodes, dragTargetNode, moveType, isCopy]);\n                            }\n\n                            if (moveType == consts.move.TYPE_INNER && tools.canAsync(targetSetting, dragTargetNode)) {\n                                view.asyncNode(targetSetting, dragTargetNode, false, dropCallback);\n                            } else {\n                                dropCallback();\n                            }\n\n                        } else {\n                            view.selectNodes(sourceSetting, nodes);\n                            setting.treeObj.trigger(consts.event.DROP, [event, setting.treeId, nodes, null, null, null]);\n                        }\n                    }\n\n                    doc.bind(\"selectstart\", _docSelect);\n\n                    function _docSelect() {\n                        return false;\n                    }\n\n                    //Avoid FireFox's Bug\n                    //If zTree Div CSS set 'overflow', so drag node outside of zTree, and event.target is error.\n                    if (eventMouseDown.preventDefault) {\n                        eventMouseDown.preventDefault();\n                    }\n                    return true;\n                }\n            },\n            //method of tools for zTree\n            _tools = {\n                getAbs: function(obj) {\n                    var oRect = obj.getBoundingClientRect(),\n                        scrollTop = document.body.scrollTop + document.documentElement.scrollTop,\n                        scrollLeft = document.body.scrollLeft + document.documentElement.scrollLeft;\n                    return [oRect.left + scrollLeft, oRect.top + scrollTop];\n                },\n                inputFocus: function(inputObj) {\n                    if (inputObj.get(0)) {\n                        inputObj.focus();\n                        tools.setCursorPosition(inputObj.get(0), inputObj.val().length);\n                    }\n                },\n                inputSelect: function(inputObj) {\n                    if (inputObj.get(0)) {\n                        inputObj.focus();\n                        inputObj.select();\n                    }\n                },\n                setCursorPosition: function(obj, pos) {\n                    if (obj.setSelectionRange) {\n                        obj.focus();\n                        obj.setSelectionRange(pos, pos);\n                    } else if (obj.createTextRange) {\n                        var range = obj.createTextRange();\n                        range.collapse(true);\n                        range.moveEnd('character', pos);\n                        range.moveStart('character', pos);\n                        range.select();\n                    }\n                },\n                showIfameMask: function(setting, showSign) {\n                    var root = data.getRoot(setting);\n                    //clear full mask\n                    while (root.dragMaskList.length > 0) {\n                        root.dragMaskList[0].remove();\n                        root.dragMaskList.shift();\n                    }\n                    if (showSign) {\n                        //show mask\n                        var iframeList = $$(\"iframe\", setting);\n                        for (var i = 0, l = iframeList.length; i < l; i++) {\n                            var obj = iframeList.get(i),\n                                r = tools.getAbs(obj),\n                                dragMask = $$(\"<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                            dragMask.appendTo($$(\"body\", setting));\n                            root.dragMaskList.push(dragMask);\n                        }\n                    }\n                }\n            },\n            //method of operate ztree dom\n            _view = {\n                addEditBtn: function(setting, node) {\n                    if (node.editNameFlag || $$(node, consts.id.EDIT, setting).length > 0) {\n                        return;\n                    }\n                    if (!tools.apply(setting.edit.showRenameBtn, [setting.treeId, node], setting.edit.showRenameBtn)) {\n                        return;\n                    }\n                    var aObj = $$(node, consts.id.A, setting),\n                        editStr = \"<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                    aObj.append(editStr);\n\n                    $$(node, consts.id.EDIT, setting).bind('click',\n                        function() {\n                            if (!tools.uCanDo(setting) || tools.apply(setting.callback.beforeEditName, [setting.treeId, node], true) == false) return false;\n                            view.editNode(setting, node);\n                            return false;\n                        }\n                    ).show();\n                },\n                addRemoveBtn: function(setting, node) {\n                    if (node.editNameFlag || $$(node, consts.id.REMOVE, setting).length > 0) {\n                        return;\n                    }\n                    if (!tools.apply(setting.edit.showRemoveBtn, [setting.treeId, node], setting.edit.showRemoveBtn)) {\n                        return;\n                    }\n                    var aObj = $$(node, consts.id.A, setting),\n                        removeStr = \"<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                    aObj.append(removeStr);\n\n                    $$(node, consts.id.REMOVE, setting).bind('click',\n                        function() {\n                            if (!tools.uCanDo(setting) || tools.apply(setting.callback.beforeRemove, [setting.treeId, node], true) == false) return false;\n                            view.removeNode(setting, node);\n                            setting.treeObj.trigger(consts.event.REMOVE, [setting.treeId, node]);\n                            return false;\n                        }\n                    ).bind('mousedown',\n                        function(eventMouseDown) {\n                            return true;\n                        }\n                    ).show();\n                },\n                addHoverDom: function(setting, node) {\n                    if (data.getRoots().showHoverDom) {\n                        node.isHover = true;\n                        if (setting.edit.enable) {\n                            view.addEditBtn(setting, node);\n                            view.addRemoveBtn(setting, node);\n                        }\n                        tools.apply(setting.view.addHoverDom, [setting.treeId, node]);\n                    }\n                },\n                cancelCurEditNode: function(setting, forceName, isCancel) {\n                    var root = data.getRoot(setting),\n                        nameKey = setting.data.key.name,\n                        node = root.curEditNode;\n\n                    if (node) {\n                        var inputObj = root.curEditInput,\n                            newName = forceName ? forceName : (isCancel ? node[nameKey] : inputObj.val());\n                        if (tools.apply(setting.callback.beforeRename, [setting.treeId, node, newName, isCancel], true) === false) {\n                            return false;\n                        }\n                        node[nameKey] = newName;\n                        var aObj = $$(node, consts.id.A, setting);\n                        aObj.removeClass(consts.node.CURSELECTED_EDIT);\n                        inputObj.unbind();\n                        view.setNodeName(setting, node);\n                        node.editNameFlag = false;\n                        root.curEditNode = null;\n                        root.curEditInput = null;\n                        view.selectNode(setting, node, false);\n                        setting.treeObj.trigger(consts.event.RENAME, [setting.treeId, node, isCancel]);\n                    }\n                    root.noSelection = true;\n                    return true;\n                },\n                editNode: function(setting, node) {\n                    var root = data.getRoot(setting);\n                    view.editNodeBlur = false;\n                    if (data.isSelectedNode(setting, node) && root.curEditNode == node && node.editNameFlag) {\n                        setTimeout(function() { tools.inputFocus(root.curEditInput); }, 0);\n                        return;\n                    }\n                    var nameKey = setting.data.key.name;\n                    node.editNameFlag = true;\n                    view.removeTreeDom(setting, node);\n                    view.cancelCurEditNode(setting);\n                    view.selectNode(setting, node, false);\n                    $$(node, consts.id.SPAN, setting).html(\"<input type=text class='rename' id='\" + node.tId + consts.id.INPUT + \"' treeNode\" + consts.id.INPUT + \" >\");\n                    var inputObj = $$(node, consts.id.INPUT, setting);\n                    inputObj.attr(\"value\", node[nameKey]);\n                    if (setting.edit.editNameSelectAll) {\n                        tools.inputSelect(inputObj);\n                    } else {\n                        tools.inputFocus(inputObj);\n                    }\n\n                    inputObj.bind('blur', function(event) {\n                        if (!view.editNodeBlur) {\n                            view.cancelCurEditNode(setting);\n                        }\n                    }).bind('keydown', function(event) {\n                        if (event.keyCode == \"13\") {\n                            view.editNodeBlur = true;\n                            view.cancelCurEditNode(setting);\n                        } else if (event.keyCode == \"27\") {\n                            view.cancelCurEditNode(setting, null, true);\n                        }\n                    }).bind('click', function(event) {\n                        return false;\n                    }).bind('dblclick', function(event) {\n                        return false;\n                    });\n\n                    $$(node, consts.id.A, setting).addClass(consts.node.CURSELECTED_EDIT);\n                    root.curEditInput = inputObj;\n                    root.noSelection = false;\n                    root.curEditNode = node;\n                },\n                moveNode: function(setting, targetNode, node, moveType, animateFlag, isSilent) {\n                    var root = data.getRoot(setting),\n                        childKey = setting.data.key.children;\n                    if (targetNode == node) return;\n                    if (setting.data.keep.leaf && targetNode && !targetNode.isParent && moveType == consts.move.TYPE_INNER) return;\n                    var oldParentNode = (node.parentTId ? node.getParentNode() : root),\n                        targetNodeIsRoot = (targetNode === null || targetNode == root);\n                    if (targetNodeIsRoot && targetNode === null) targetNode = root;\n                    if (targetNodeIsRoot) moveType = consts.move.TYPE_INNER;\n                    var targetParentNode = (targetNode.parentTId ? targetNode.getParentNode() : root);\n\n                    if (moveType != consts.move.TYPE_PREV && moveType != consts.move.TYPE_NEXT) {\n                        moveType = consts.move.TYPE_INNER;\n                    }\n\n                    if (moveType == consts.move.TYPE_INNER) {\n                        if (targetNodeIsRoot) {\n                            //parentTId of root node is null\n                            node.parentTId = null;\n                        } else {\n                            if (!targetNode.isParent) {\n                                targetNode.isParent = true;\n                                targetNode.open = !!targetNode.open;\n                                view.setNodeLineIcos(setting, targetNode);\n                            }\n                            node.parentTId = targetNode.tId;\n                        }\n                    }\n\n                    //move node Dom\n                    var targetObj, target_ulObj;\n                    if (targetNodeIsRoot) {\n                        targetObj = setting.treeObj;\n                        target_ulObj = targetObj;\n                    } else {\n                        if (!isSilent && moveType == consts.move.TYPE_INNER) {\n                            view.expandCollapseNode(setting, targetNode, true, false);\n                        } else if (!isSilent) {\n                            view.expandCollapseNode(setting, targetNode.getParentNode(), true, false);\n                        }\n                        targetObj = $$(targetNode, setting);\n                        target_ulObj = $$(targetNode, consts.id.UL, setting);\n                        if (!!targetObj.get(0) && !target_ulObj.get(0)) {\n                            var ulstr = [];\n                            view.makeUlHtml(setting, targetNode, ulstr, '');\n                            targetObj.append(ulstr.join(''));\n                        }\n                        target_ulObj = $$(targetNode, consts.id.UL, setting);\n                    }\n                    var nodeDom = $$(node, setting);\n                    if (!nodeDom.get(0)) {\n                        nodeDom = view.appendNodes(setting, node.level, [node], null, -1, false, true).join('');\n                    } else if (!targetObj.get(0)) {\n                        nodeDom.remove();\n                    }\n                    if (target_ulObj.get(0) && moveType == consts.move.TYPE_INNER) {\n                        target_ulObj.append(nodeDom);\n                    } else if (targetObj.get(0) && moveType == consts.move.TYPE_PREV) {\n                        targetObj.before(nodeDom);\n                    } else if (targetObj.get(0) && moveType == consts.move.TYPE_NEXT) {\n                        targetObj.after(nodeDom);\n                    }\n\n                    //repair the data after move\n                    var i, l,\n                        tmpSrcIndex = -1,\n                        tmpTargetIndex = 0,\n                        oldNeighbor = null,\n                        newNeighbor = null,\n                        oldLevel = node.level;\n                    if (node.isFirstNode) {\n                        tmpSrcIndex = 0;\n                        if (oldParentNode[childKey].length > 1) {\n                            oldNeighbor = oldParentNode[childKey][1];\n                            oldNeighbor.isFirstNode = true;\n                        }\n                    } else if (node.isLastNode) {\n                        tmpSrcIndex = oldParentNode[childKey].length - 1;\n                        oldNeighbor = oldParentNode[childKey][tmpSrcIndex - 1];\n                        oldNeighbor.isLastNode = true;\n                    } else {\n                        for (i = 0, l = oldParentNode[childKey].length; i < l; i++) {\n                            if (oldParentNode[childKey][i].tId == node.tId) {\n                                tmpSrcIndex = i;\n                                break;\n                            }\n                        }\n                    }\n                    if (tmpSrcIndex >= 0) {\n                        oldParentNode[childKey].splice(tmpSrcIndex, 1);\n                    }\n                    if (moveType != consts.move.TYPE_INNER) {\n                        for (i = 0, l = targetParentNode[childKey].length; i < l; i++) {\n                            if (targetParentNode[childKey][i].tId == targetNode.tId) tmpTargetIndex = i;\n                        }\n                    }\n                    if (moveType == consts.move.TYPE_INNER) {\n                        if (!targetNode[childKey]) targetNode[childKey] = new Array();\n                        if (targetNode[childKey].length > 0) {\n                            newNeighbor = targetNode[childKey][targetNode[childKey].length - 1];\n                            newNeighbor.isLastNode = false;\n                        }\n                        targetNode[childKey].splice(targetNode[childKey].length, 0, node);\n                        node.isLastNode = true;\n                        node.isFirstNode = (targetNode[childKey].length == 1);\n                    } else if (targetNode.isFirstNode && moveType == consts.move.TYPE_PREV) {\n                        targetParentNode[childKey].splice(tmpTargetIndex, 0, node);\n                        newNeighbor = targetNode;\n                        newNeighbor.isFirstNode = false;\n                        node.parentTId = targetNode.parentTId;\n                        node.isFirstNode = true;\n                        node.isLastNode = false;\n\n                    } else if (targetNode.isLastNode && moveType == consts.move.TYPE_NEXT) {\n                        targetParentNode[childKey].splice(tmpTargetIndex + 1, 0, node);\n                        newNeighbor = targetNode;\n                        newNeighbor.isLastNode = false;\n                        node.parentTId = targetNode.parentTId;\n                        node.isFirstNode = false;\n                        node.isLastNode = true;\n\n                    } else {\n                        if (moveType == consts.move.TYPE_PREV) {\n                            targetParentNode[childKey].splice(tmpTargetIndex, 0, node);\n                        } else {\n                            targetParentNode[childKey].splice(tmpTargetIndex + 1, 0, node);\n                        }\n                        node.parentTId = targetNode.parentTId;\n                        node.isFirstNode = false;\n                        node.isLastNode = false;\n                    }\n                    data.fixPIdKeyValue(setting, node);\n                    data.setSonNodeLevel(setting, node.getParentNode(), node);\n\n                    //repair node what been moved\n                    view.setNodeLineIcos(setting, node);\n                    view.repairNodeLevelClass(setting, node, oldLevel)\n\n                    //repair node's old parentNode dom\n                    if (!setting.data.keep.parent && oldParentNode[childKey].length < 1) {\n                        //old parentNode has no child nodes\n                        oldParentNode.isParent = false;\n                        oldParentNode.open = false;\n                        var tmp_ulObj = $$(oldParentNode, consts.id.UL, setting),\n                            tmp_switchObj = $$(oldParentNode, consts.id.SWITCH, setting),\n                            tmp_icoObj = $$(oldParentNode, consts.id.ICON, setting);\n                        view.replaceSwitchClass(oldParentNode, tmp_switchObj, consts.folder.DOCU);\n                        view.replaceIcoClass(oldParentNode, tmp_icoObj, consts.folder.DOCU);\n                        tmp_ulObj.css(\"display\", \"none\");\n\n                    } else if (oldNeighbor) {\n                        //old neigbor node\n                        view.setNodeLineIcos(setting, oldNeighbor);\n                    }\n\n                    //new neigbor node\n                    if (newNeighbor) {\n                        view.setNodeLineIcos(setting, newNeighbor);\n                    }\n\n                    //repair checkbox / radio\n                    if (!!setting.check && setting.check.enable && view.repairChkClass) {\n                        view.repairChkClass(setting, oldParentNode);\n                        view.repairParentChkClassWithSelf(setting, oldParentNode);\n                        if (oldParentNode != node.parent)\n                            view.repairParentChkClassWithSelf(setting, node);\n                    }\n\n                    //expand parents after move\n                    if (!isSilent) {\n                        view.expandCollapseParentNode(setting, node.getParentNode(), true, animateFlag);\n                    }\n                },\n                removeEditBtn: function(setting, node) {\n                    $$(node, consts.id.EDIT, setting).unbind().remove();\n                },\n                removeRemoveBtn: function(setting, node) {\n                    $$(node, consts.id.REMOVE, setting).unbind().remove();\n                },\n                removeTreeDom: function(setting, node) {\n                    node.isHover = false;\n                    view.removeEditBtn(setting, node);\n                    view.removeRemoveBtn(setting, node);\n                    tools.apply(setting.view.removeHoverDom, [setting.treeId, node]);\n                },\n                repairNodeLevelClass: function(setting, node, oldLevel) {\n                    if (oldLevel === node.level) return;\n                    var liObj = $$(node, setting),\n                        aObj = $$(node, consts.id.A, setting),\n                        ulObj = $$(node, consts.id.UL, setting),\n                        oldClass = consts.className.LEVEL + oldLevel,\n                        newClass = consts.className.LEVEL + node.level;\n                    liObj.removeClass(oldClass);\n                    liObj.addClass(newClass);\n                    aObj.removeClass(oldClass);\n                    aObj.addClass(newClass);\n                    ulObj.removeClass(oldClass);\n                    ulObj.addClass(newClass);\n                },\n                selectNodes: function(setting, nodes) {\n                    for (var i = 0, l = nodes.length; i < l; i++) {\n                        view.selectNode(setting, nodes[i], i > 0);\n                    }\n                }\n            },\n\n            _z = {\n                tools: _tools,\n                view: _view,\n                event: _event,\n                data: _data\n            };\n        $.extend(true, $.fn.zTree.consts, _consts);\n        $.extend(true, $.fn.zTree._z, _z);\n\n        var zt = $.fn.zTree,\n            tools = zt._z.tools,\n            consts = zt.consts,\n            view = zt._z.view,\n            data = zt._z.data,\n            event = zt._z.event,\n            $$ = tools.$;\n\n        data.exSetting(_setting);\n        data.addInitBind(_bindEvent);\n        data.addInitUnBind(_unbindEvent);\n        data.addInitCache(_initCache);\n        data.addInitNode(_initNode);\n        data.addInitProxy(_eventProxy);\n        data.addInitRoot(_initRoot);\n        data.addZTreeTools(_zTreeTools);\n\n        var _cancelPreSelectedNode = view.cancelPreSelectedNode;\n        view.cancelPreSelectedNode = function(setting, node) {\n            var list = data.getRoot(setting).curSelectedList;\n            for (var i = 0, j = list.length; i < j; i++) {\n                if (!node || node === list[i]) {\n                    view.removeTreeDom(setting, list[i]);\n                    if (node) break;\n                }\n            }\n            if (_cancelPreSelectedNode) _cancelPreSelectedNode.apply(view, arguments);\n        }\n\n        var _createNodes = view.createNodes;\n        view.createNodes = function(setting, level, nodes, parentNode, index) {\n            if (_createNodes) {\n                _createNodes.apply(view, arguments);\n            }\n            if (!nodes) return;\n            if (view.repairParentChkClassWithSelf) {\n                view.repairParentChkClassWithSelf(setting, parentNode);\n            }\n        }\n\n        var _makeNodeUrl = view.makeNodeUrl;\n        view.makeNodeUrl = function(setting, node) {\n            return setting.edit.enable ? null : (_makeNodeUrl.apply(view, arguments));\n        }\n\n        var _removeNode = view.removeNode;\n        view.removeNode = function(setting, node) {\n            var root = data.getRoot(setting);\n            if (root.curEditNode === node) root.curEditNode = null;\n            if (_removeNode) {\n                _removeNode.apply(view, arguments);\n            }\n        }\n\n        var _selectNode = view.selectNode;\n        view.selectNode = function(setting, node, addFlag) {\n            var root = data.getRoot(setting);\n            if (data.isSelectedNode(setting, node) && root.curEditNode == node && node.editNameFlag) {\n                return false;\n            }\n            if (_selectNode) _selectNode.apply(view, arguments);\n            view.addHoverDom(setting, node);\n            return true;\n        }\n\n        var _uCanDo = tools.uCanDo;\n        tools.uCanDo = function(setting, e) {\n            var root = data.getRoot(setting);\n            if (e && (tools.eqs(e.type, \"mouseover\") || tools.eqs(e.type, \"mouseout\") || tools.eqs(e.type, \"mousedown\") || tools.eqs(e.type, \"mouseup\"))) {\n                return true;\n            }\n            if (root.curEditNode) {\n                view.editNodeBlur = false;\n                root.curEditInput.focus();\n            }\n            return (!root.curEditNode) && (_uCanDo ? _uCanDo.apply(view, arguments) : true);\n        }\n    })(jQuery);\n\n    //输出接口\n    exports('ztree');\n});"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/popper.js/popper-utils.js",
    "content": "/**!\n * @fileOverview Kickass library to create and place poppers near their reference elements.\n * @version 1.12.6\n * @license\n * Copyright (c) 2016 Federico Zivolo and contributors\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 all\n * 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 THE\n * SOFTWARE.\n */\n(function (global, factory) {\n\ttypeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :\n\ttypeof define === 'function' && define.amd ? define(['exports'], factory) :\n\t(factory((global.PopperUtils = global.PopperUtils || {})));\n}(this, (function (exports) { 'use strict';\n\n/**\n * Get CSS computed property of the given element\n * @method\n * @memberof Popper.Utils\n * @argument {Eement} element\n * @argument {String} property\n */\nfunction getStyleComputedProperty(element, property) {\n  if (element.nodeType !== 1) {\n    return [];\n  }\n  // NOTE: 1 DOM access here\n  var css = window.getComputedStyle(element, null);\n  return property ? css[property] : css;\n}\n\n/**\n * Returns the parentNode or the host of the element\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @returns {Element} parent\n */\nfunction getParentNode(element) {\n  if (element.nodeName === 'HTML') {\n    return element;\n  }\n  return element.parentNode || element.host;\n}\n\n/**\n * Returns the scrolling parent of the given element\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @returns {Element} scroll parent\n */\nfunction getScrollParent(element) {\n  // Return body, `getScroll` will take care to get the correct `scrollTop` from it\n  if (!element) {\n    return window.document.body;\n  }\n\n  switch (element.nodeName) {\n    case 'HTML':\n    case 'BODY':\n      return element.ownerDocument.body;\n    case '#document':\n      return element.body;\n  }\n\n  // Firefox want us to check `-x` and `-y` variations as well\n\n  var _getStyleComputedProp = getStyleComputedProperty(element),\n      overflow = _getStyleComputedProp.overflow,\n      overflowX = _getStyleComputedProp.overflowX,\n      overflowY = _getStyleComputedProp.overflowY;\n\n  if (/(auto|scroll)/.test(overflow + overflowY + overflowX)) {\n    return element;\n  }\n\n  return getScrollParent(getParentNode(element));\n}\n\n/**\n * Returns the offset parent of the given element\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @returns {Element} offset parent\n */\nfunction getOffsetParent(element) {\n  // NOTE: 1 DOM access here\n  var offsetParent = element && element.offsetParent;\n  var nodeName = offsetParent && offsetParent.nodeName;\n\n  if (!nodeName || nodeName === 'BODY' || nodeName === 'HTML') {\n    if (element) {\n      return element.ownerDocument.documentElement;\n    }\n\n    return window.document.documentElement;\n  }\n\n  // .offsetParent will return the closest TD or TABLE in case\n  // no offsetParent is present, I hate this job...\n  if (['TD', 'TABLE'].indexOf(offsetParent.nodeName) !== -1 && getStyleComputedProperty(offsetParent, 'position') === 'static') {\n    return getOffsetParent(offsetParent);\n  }\n\n  return offsetParent;\n}\n\nfunction isOffsetContainer(element) {\n  var nodeName = element.nodeName;\n\n  if (nodeName === 'BODY') {\n    return false;\n  }\n  return nodeName === 'HTML' || getOffsetParent(element.firstElementChild) === element;\n}\n\n/**\n * Finds the root node (document, shadowDOM root) of the given element\n * @method\n * @memberof Popper.Utils\n * @argument {Element} node\n * @returns {Element} root node\n */\nfunction getRoot(node) {\n  if (node.parentNode !== null) {\n    return getRoot(node.parentNode);\n  }\n\n  return node;\n}\n\n/**\n * Finds the offset parent common to the two provided nodes\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element1\n * @argument {Element} element2\n * @returns {Element} common offset parent\n */\nfunction findCommonOffsetParent(element1, element2) {\n  // This check is needed to avoid errors in case one of the elements isn't defined for any reason\n  if (!element1 || !element1.nodeType || !element2 || !element2.nodeType) {\n    return window.document.documentElement;\n  }\n\n  // Here we make sure to give as \"start\" the element that comes first in the DOM\n  var order = element1.compareDocumentPosition(element2) & Node.DOCUMENT_POSITION_FOLLOWING;\n  var start = order ? element1 : element2;\n  var end = order ? element2 : element1;\n\n  // Get common ancestor container\n  var range = document.createRange();\n  range.setStart(start, 0);\n  range.setEnd(end, 0);\n  var commonAncestorContainer = range.commonAncestorContainer;\n\n  // Both nodes are inside #document\n\n  if (element1 !== commonAncestorContainer && element2 !== commonAncestorContainer || start.contains(end)) {\n    if (isOffsetContainer(commonAncestorContainer)) {\n      return commonAncestorContainer;\n    }\n\n    return getOffsetParent(commonAncestorContainer);\n  }\n\n  // one of the nodes is inside shadowDOM, find which one\n  var element1root = getRoot(element1);\n  if (element1root.host) {\n    return findCommonOffsetParent(element1root.host, element2);\n  } else {\n    return findCommonOffsetParent(element1, getRoot(element2).host);\n  }\n}\n\n/**\n * Gets the scroll value of the given element in the given side (top and left)\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @argument {String} side `top` or `left`\n * @returns {number} amount of scrolled pixels\n */\nfunction getScroll(element) {\n  var side = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'top';\n\n  var upperSide = side === 'top' ? 'scrollTop' : 'scrollLeft';\n  var nodeName = element.nodeName;\n\n  if (nodeName === 'BODY' || nodeName === 'HTML') {\n    var html = element.ownerDocument.documentElement;\n    var scrollingElement = element.ownerDocument.scrollingElement || html;\n    return scrollingElement[upperSide];\n  }\n\n  return element[upperSide];\n}\n\n/*\n * Sum or subtract the element scroll values (left and top) from a given rect object\n * @method\n * @memberof Popper.Utils\n * @param {Object} rect - Rect object you want to change\n * @param {HTMLElement} element - The element from the function reads the scroll values\n * @param {Boolean} subtract - set to true if you want to subtract the scroll values\n * @return {Object} rect - The modifier rect object\n */\nfunction includeScroll(rect, element) {\n  var subtract = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;\n\n  var scrollTop = getScroll(element, 'top');\n  var scrollLeft = getScroll(element, 'left');\n  var modifier = subtract ? -1 : 1;\n  rect.top += scrollTop * modifier;\n  rect.bottom += scrollTop * modifier;\n  rect.left += scrollLeft * modifier;\n  rect.right += scrollLeft * modifier;\n  return rect;\n}\n\n/*\n * Helper to detect borders of a given element\n * @method\n * @memberof Popper.Utils\n * @param {CSSStyleDeclaration} styles\n * Result of `getStyleComputedProperty` on the given element\n * @param {String} axis - `x` or `y`\n * @return {number} borders - The borders size of the given axis\n */\n\nfunction getBordersSize(styles, axis) {\n  var sideA = axis === 'x' ? 'Left' : 'Top';\n  var sideB = sideA === 'Left' ? 'Right' : 'Bottom';\n\n  return +styles['border' + sideA + 'Width'].split('px')[0] + +styles['border' + sideB + 'Width'].split('px')[0];\n}\n\n/**\n * Tells if you are running Internet Explorer 10\n * @method\n * @memberof Popper.Utils\n * @returns {Boolean} isIE10\n */\nvar isIE10 = undefined;\n\nvar isIE10$1 = function () {\n  if (isIE10 === undefined) {\n    isIE10 = navigator.appVersion.indexOf('MSIE 10') !== -1;\n  }\n  return isIE10;\n};\n\nfunction getSize(axis, body, html, computedStyle) {\n  return Math.max(body['offset' + axis], body['scroll' + axis], html['client' + axis], html['offset' + axis], html['scroll' + axis], isIE10$1() ? html['offset' + axis] + computedStyle['margin' + (axis === 'Height' ? 'Top' : 'Left')] + computedStyle['margin' + (axis === 'Height' ? 'Bottom' : 'Right')] : 0);\n}\n\nfunction getWindowSizes() {\n  var body = window.document.body;\n  var html = window.document.documentElement;\n  var computedStyle = isIE10$1() && window.getComputedStyle(html);\n\n  return {\n    height: getSize('Height', body, html, computedStyle),\n    width: getSize('Width', body, html, computedStyle)\n  };\n}\n\nvar _extends = Object.assign || function (target) {\n  for (var i = 1; i < arguments.length; i++) {\n    var source = arguments[i];\n\n    for (var key in source) {\n      if (Object.prototype.hasOwnProperty.call(source, key)) {\n        target[key] = source[key];\n      }\n    }\n  }\n\n  return target;\n};\n\n/**\n * Given element offsets, generate an output similar to getBoundingClientRect\n * @method\n * @memberof Popper.Utils\n * @argument {Object} offsets\n * @returns {Object} ClientRect like output\n */\nfunction getClientRect(offsets) {\n  return _extends({}, offsets, {\n    right: offsets.left + offsets.width,\n    bottom: offsets.top + offsets.height\n  });\n}\n\n/**\n * Get bounding client rect of given element\n * @method\n * @memberof Popper.Utils\n * @param {HTMLElement} element\n * @return {Object} client rect\n */\nfunction getBoundingClientRect(element) {\n  var rect = {};\n\n  // IE10 10 FIX: Please, don't ask, the element isn't\n  // considered in DOM in some circumstances...\n  // This isn't reproducible in IE10 compatibility mode of IE11\n  if (isIE10$1()) {\n    try {\n      rect = element.getBoundingClientRect();\n      var scrollTop = getScroll(element, 'top');\n      var scrollLeft = getScroll(element, 'left');\n      rect.top += scrollTop;\n      rect.left += scrollLeft;\n      rect.bottom += scrollTop;\n      rect.right += scrollLeft;\n    } catch (err) {}\n  } else {\n    rect = element.getBoundingClientRect();\n  }\n\n  var result = {\n    left: rect.left,\n    top: rect.top,\n    width: rect.right - rect.left,\n    height: rect.bottom - rect.top\n  };\n\n  // subtract scrollbar size from sizes\n  var sizes = element.nodeName === 'HTML' ? getWindowSizes() : {};\n  var width = sizes.width || element.clientWidth || result.right - result.left;\n  var height = sizes.height || element.clientHeight || result.bottom - result.top;\n\n  var horizScrollbar = element.offsetWidth - width;\n  var vertScrollbar = element.offsetHeight - height;\n\n  // if an hypothetical scrollbar is detected, we must be sure it's not a `border`\n  // we make this check conditional for performance reasons\n  if (horizScrollbar || vertScrollbar) {\n    var styles = getStyleComputedProperty(element);\n    horizScrollbar -= getBordersSize(styles, 'x');\n    vertScrollbar -= getBordersSize(styles, 'y');\n\n    result.width -= horizScrollbar;\n    result.height -= vertScrollbar;\n  }\n\n  return getClientRect(result);\n}\n\nfunction getOffsetRectRelativeToArbitraryNode(children, parent) {\n  var isIE10 = isIE10$1();\n  var isHTML = parent.nodeName === 'HTML';\n  var childrenRect = getBoundingClientRect(children);\n  var parentRect = getBoundingClientRect(parent);\n  var scrollParent = getScrollParent(children);\n\n  var styles = getStyleComputedProperty(parent);\n  var borderTopWidth = +styles.borderTopWidth.split('px')[0];\n  var borderLeftWidth = +styles.borderLeftWidth.split('px')[0];\n\n  var offsets = getClientRect({\n    top: childrenRect.top - parentRect.top - borderTopWidth,\n    left: childrenRect.left - parentRect.left - borderLeftWidth,\n    width: childrenRect.width,\n    height: childrenRect.height\n  });\n  offsets.marginTop = 0;\n  offsets.marginLeft = 0;\n\n  // Subtract margins of documentElement in case it's being used as parent\n  // we do this only on HTML because it's the only element that behaves\n  // differently when margins are applied to it. The margins are included in\n  // the box of the documentElement, in the other cases not.\n  if (!isIE10 && isHTML) {\n    var marginTop = +styles.marginTop.split('px')[0];\n    var marginLeft = +styles.marginLeft.split('px')[0];\n\n    offsets.top -= borderTopWidth - marginTop;\n    offsets.bottom -= borderTopWidth - marginTop;\n    offsets.left -= borderLeftWidth - marginLeft;\n    offsets.right -= borderLeftWidth - marginLeft;\n\n    // Attach marginTop and marginLeft because in some circumstances we may need them\n    offsets.marginTop = marginTop;\n    offsets.marginLeft = marginLeft;\n  }\n\n  if (isIE10 ? parent.contains(scrollParent) : parent === scrollParent && scrollParent.nodeName !== 'BODY') {\n    offsets = includeScroll(offsets, parent);\n  }\n\n  return offsets;\n}\n\nfunction getViewportOffsetRectRelativeToArtbitraryNode(element) {\n  var html = element.ownerDocument.documentElement;\n  var relativeOffset = getOffsetRectRelativeToArbitraryNode(element, html);\n  var width = Math.max(html.clientWidth, window.innerWidth || 0);\n  var height = Math.max(html.clientHeight, window.innerHeight || 0);\n\n  var scrollTop = getScroll(html);\n  var scrollLeft = getScroll(html, 'left');\n\n  var offset = {\n    top: scrollTop - relativeOffset.top + relativeOffset.marginTop,\n    left: scrollLeft - relativeOffset.left + relativeOffset.marginLeft,\n    width: width,\n    height: height\n  };\n\n  return getClientRect(offset);\n}\n\n/**\n * Check if the given element is fixed or is inside a fixed parent\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @argument {Element} customContainer\n * @returns {Boolean} answer to \"isFixed?\"\n */\nfunction isFixed(element) {\n  var nodeName = element.nodeName;\n  if (nodeName === 'BODY' || nodeName === 'HTML') {\n    return false;\n  }\n  if (getStyleComputedProperty(element, 'position') === 'fixed') {\n    return true;\n  }\n  return isFixed(getParentNode(element));\n}\n\n/**\n * Computed the boundaries limits and return them\n * @method\n * @memberof Popper.Utils\n * @param {HTMLElement} popper\n * @param {HTMLElement} reference\n * @param {number} padding\n * @param {HTMLElement} boundariesElement - Element used to define the boundaries\n * @returns {Object} Coordinates of the boundaries\n */\nfunction getBoundaries(popper, reference, padding, boundariesElement) {\n  // NOTE: 1 DOM access here\n  var boundaries = { top: 0, left: 0 };\n  var offsetParent = findCommonOffsetParent(popper, reference);\n\n  // Handle viewport case\n  if (boundariesElement === 'viewport') {\n    boundaries = getViewportOffsetRectRelativeToArtbitraryNode(offsetParent);\n  } else {\n    // Handle other cases based on DOM element used as boundaries\n    var boundariesNode = void 0;\n    if (boundariesElement === 'scrollParent') {\n      boundariesNode = getScrollParent(getParentNode(popper));\n      if (boundariesNode.nodeName === 'BODY') {\n        boundariesNode = popper.ownerDocument.documentElement;\n      }\n    } else if (boundariesElement === 'window') {\n      boundariesNode = popper.ownerDocument.documentElement;\n    } else {\n      boundariesNode = boundariesElement;\n    }\n\n    var offsets = getOffsetRectRelativeToArbitraryNode(boundariesNode, offsetParent);\n\n    // In case of HTML, we need a different computation\n    if (boundariesNode.nodeName === 'HTML' && !isFixed(offsetParent)) {\n      var _getWindowSizes = getWindowSizes(),\n          height = _getWindowSizes.height,\n          width = _getWindowSizes.width;\n\n      boundaries.top += offsets.top - offsets.marginTop;\n      boundaries.bottom = height + offsets.top;\n      boundaries.left += offsets.left - offsets.marginLeft;\n      boundaries.right = width + offsets.left;\n    } else {\n      // for all the other DOM elements, this one is good\n      boundaries = offsets;\n    }\n  }\n\n  // Add paddings\n  boundaries.left += padding;\n  boundaries.top += padding;\n  boundaries.right -= padding;\n  boundaries.bottom -= padding;\n\n  return boundaries;\n}\n\nfunction getArea(_ref) {\n  var width = _ref.width,\n      height = _ref.height;\n\n  return width * height;\n}\n\n/**\n * Utility used to transform the `auto` placement to the placement with more\n * available space.\n * @method\n * @memberof Popper.Utils\n * @argument {Object} data - The data object generated by update method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction computeAutoPlacement(placement, refRect, popper, reference, boundariesElement) {\n  var padding = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0;\n\n  if (placement.indexOf('auto') === -1) {\n    return placement;\n  }\n\n  var boundaries = getBoundaries(popper, reference, padding, boundariesElement);\n\n  var rects = {\n    top: {\n      width: boundaries.width,\n      height: refRect.top - boundaries.top\n    },\n    right: {\n      width: boundaries.right - refRect.right,\n      height: boundaries.height\n    },\n    bottom: {\n      width: boundaries.width,\n      height: boundaries.bottom - refRect.bottom\n    },\n    left: {\n      width: refRect.left - boundaries.left,\n      height: boundaries.height\n    }\n  };\n\n  var sortedAreas = Object.keys(rects).map(function (key) {\n    return _extends({\n      key: key\n    }, rects[key], {\n      area: getArea(rects[key])\n    });\n  }).sort(function (a, b) {\n    return b.area - a.area;\n  });\n\n  var filteredAreas = sortedAreas.filter(function (_ref2) {\n    var width = _ref2.width,\n        height = _ref2.height;\n    return width >= popper.clientWidth && height >= popper.clientHeight;\n  });\n\n  var computedPlacement = filteredAreas.length > 0 ? filteredAreas[0].key : sortedAreas[0].key;\n\n  var variation = placement.split('-')[1];\n\n  return computedPlacement + (variation ? '-' + variation : '');\n}\n\nvar isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined';\nvar longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox'];\nvar timeoutDuration = 0;\nfor (var i = 0; i < longerTimeoutBrowsers.length; i += 1) {\n  if (isBrowser && navigator.userAgent.indexOf(longerTimeoutBrowsers[i]) >= 0) {\n    timeoutDuration = 1;\n    break;\n  }\n}\n\nfunction microtaskDebounce(fn) {\n  var called = false;\n  return function () {\n    if (called) {\n      return;\n    }\n    called = true;\n    Promise.resolve().then(function () {\n      called = false;\n      fn();\n    });\n  };\n}\n\nfunction taskDebounce(fn) {\n  var scheduled = false;\n  return function () {\n    if (!scheduled) {\n      scheduled = true;\n      setTimeout(function () {\n        scheduled = false;\n        fn();\n      }, timeoutDuration);\n    }\n  };\n}\n\nvar supportsMicroTasks = isBrowser && window.Promise;\n\n/**\n* Create a debounced version of a method, that's asynchronously deferred\n* but called in the minimum time possible.\n*\n* @method\n* @memberof Popper.Utils\n* @argument {Function} fn\n* @returns {Function}\n*/\nvar debounce = supportsMicroTasks ? microtaskDebounce : taskDebounce;\n\n/**\n * Mimics the `find` method of Array\n * @method\n * @memberof Popper.Utils\n * @argument {Array} arr\n * @argument prop\n * @argument value\n * @returns index or -1\n */\nfunction find(arr, check) {\n  // use native find if supported\n  if (Array.prototype.find) {\n    return arr.find(check);\n  }\n\n  // use `filter` to obtain the same behavior of `find`\n  return arr.filter(check)[0];\n}\n\n/**\n * Return the index of the matching object\n * @method\n * @memberof Popper.Utils\n * @argument {Array} arr\n * @argument prop\n * @argument value\n * @returns index or -1\n */\nfunction findIndex(arr, prop, value) {\n  // use native findIndex if supported\n  if (Array.prototype.findIndex) {\n    return arr.findIndex(function (cur) {\n      return cur[prop] === value;\n    });\n  }\n\n  // use `find` + `indexOf` if `findIndex` isn't supported\n  var match = find(arr, function (obj) {\n    return obj[prop] === value;\n  });\n  return arr.indexOf(match);\n}\n\n/**\n * Get the position of the given element, relative to its offset parent\n * @method\n * @memberof Popper.Utils\n * @param {Element} element\n * @return {Object} position - Coordinates of the element and its `scrollTop`\n */\nfunction getOffsetRect(element) {\n  var elementRect = void 0;\n  if (element.nodeName === 'HTML') {\n    var _getWindowSizes = getWindowSizes(),\n        width = _getWindowSizes.width,\n        height = _getWindowSizes.height;\n\n    elementRect = {\n      width: width,\n      height: height,\n      left: 0,\n      top: 0\n    };\n  } else {\n    elementRect = {\n      width: element.offsetWidth,\n      height: element.offsetHeight,\n      left: element.offsetLeft,\n      top: element.offsetTop\n    };\n  }\n\n  // position\n  return getClientRect(elementRect);\n}\n\n/**\n * Get the outer sizes of the given element (offset size + margins)\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @returns {Object} object containing width and height properties\n */\nfunction getOuterSizes(element) {\n  var styles = window.getComputedStyle(element);\n  var x = parseFloat(styles.marginTop) + parseFloat(styles.marginBottom);\n  var y = parseFloat(styles.marginLeft) + parseFloat(styles.marginRight);\n  var result = {\n    width: element.offsetWidth + y,\n    height: element.offsetHeight + x\n  };\n  return result;\n}\n\n/**\n * Get the opposite placement of the given one\n * @method\n * @memberof Popper.Utils\n * @argument {String} placement\n * @returns {String} flipped placement\n */\nfunction getOppositePlacement(placement) {\n  var hash = { left: 'right', right: 'left', bottom: 'top', top: 'bottom' };\n  return placement.replace(/left|right|bottom|top/g, function (matched) {\n    return hash[matched];\n  });\n}\n\n/**\n * Get offsets to the popper\n * @method\n * @memberof Popper.Utils\n * @param {Object} position - CSS position the Popper will get applied\n * @param {HTMLElement} popper - the popper element\n * @param {Object} referenceOffsets - the reference offsets (the popper will be relative to this)\n * @param {String} placement - one of the valid placement options\n * @returns {Object} popperOffsets - An object containing the offsets which will be applied to the popper\n */\nfunction getPopperOffsets(popper, referenceOffsets, placement) {\n  placement = placement.split('-')[0];\n\n  // Get popper node sizes\n  var popperRect = getOuterSizes(popper);\n\n  // Add position, width and height to our offsets object\n  var popperOffsets = {\n    width: popperRect.width,\n    height: popperRect.height\n  };\n\n  // depending by the popper placement we have to compute its offsets slightly differently\n  var isHoriz = ['right', 'left'].indexOf(placement) !== -1;\n  var mainSide = isHoriz ? 'top' : 'left';\n  var secondarySide = isHoriz ? 'left' : 'top';\n  var measurement = isHoriz ? 'height' : 'width';\n  var secondaryMeasurement = !isHoriz ? 'height' : 'width';\n\n  popperOffsets[mainSide] = referenceOffsets[mainSide] + referenceOffsets[measurement] / 2 - popperRect[measurement] / 2;\n  if (placement === secondarySide) {\n    popperOffsets[secondarySide] = referenceOffsets[secondarySide] - popperRect[secondaryMeasurement];\n  } else {\n    popperOffsets[secondarySide] = referenceOffsets[getOppositePlacement(secondarySide)];\n  }\n\n  return popperOffsets;\n}\n\n/**\n * Get offsets to the reference element\n * @method\n * @memberof Popper.Utils\n * @param {Object} state\n * @param {Element} popper - the popper element\n * @param {Element} reference - the reference element (the popper will be relative to this)\n * @returns {Object} An object containing the offsets which will be applied to the popper\n */\nfunction getReferenceOffsets(state, popper, reference) {\n  var commonOffsetParent = findCommonOffsetParent(popper, reference);\n  return getOffsetRectRelativeToArbitraryNode(reference, commonOffsetParent);\n}\n\n/**\n * Get the prefixed supported property name\n * @method\n * @memberof Popper.Utils\n * @argument {String} property (camelCase)\n * @returns {String} prefixed property (camelCase or PascalCase, depending on the vendor prefix)\n */\nfunction getSupportedPropertyName(property) {\n  var prefixes = [false, 'ms', 'Webkit', 'Moz', 'O'];\n  var upperProp = property.charAt(0).toUpperCase() + property.slice(1);\n\n  for (var i = 0; i < prefixes.length - 1; i++) {\n    var prefix = prefixes[i];\n    var toCheck = prefix ? '' + prefix + upperProp : property;\n    if (typeof window.document.body.style[toCheck] !== 'undefined') {\n      return toCheck;\n    }\n  }\n  return null;\n}\n\n/**\n * Check if the given variable is a function\n * @method\n * @memberof Popper.Utils\n * @argument {Any} functionToCheck - variable to check\n * @returns {Boolean} answer to: is a function?\n */\nfunction isFunction(functionToCheck) {\n  var getType = {};\n  return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';\n}\n\n/**\n * Helper used to know if the given modifier is enabled.\n * @method\n * @memberof Popper.Utils\n * @returns {Boolean}\n */\nfunction isModifierEnabled(modifiers, modifierName) {\n  return modifiers.some(function (_ref) {\n    var name = _ref.name,\n        enabled = _ref.enabled;\n    return enabled && name === modifierName;\n  });\n}\n\n/**\n * Helper used to know if the given modifier depends from another one.<br />\n * It checks if the needed modifier is listed and enabled.\n * @method\n * @memberof Popper.Utils\n * @param {Array} modifiers - list of modifiers\n * @param {String} requestingName - name of requesting modifier\n * @param {String} requestedName - name of requested modifier\n * @returns {Boolean}\n */\nfunction isModifierRequired(modifiers, requestingName, requestedName) {\n  var requesting = find(modifiers, function (_ref) {\n    var name = _ref.name;\n    return name === requestingName;\n  });\n\n  var isRequired = !!requesting && modifiers.some(function (modifier) {\n    return modifier.name === requestedName && modifier.enabled && modifier.order < requesting.order;\n  });\n\n  if (!isRequired) {\n    var _requesting = '`' + requestingName + '`';\n    var requested = '`' + requestedName + '`';\n    console.warn(requested + ' modifier is required by ' + _requesting + ' modifier in order to work, be sure to include it before ' + _requesting + '!');\n  }\n  return isRequired;\n}\n\n/**\n * Tells if a given input is a number\n * @method\n * @memberof Popper.Utils\n * @param {*} input to check\n * @return {Boolean}\n */\nfunction isNumeric(n) {\n  return n !== '' && !isNaN(parseFloat(n)) && isFinite(n);\n}\n\n/**\n * Get the window associated with the element\n * @argument {Element} element\n * @returns {Window}\n */\nfunction getWindow(element) {\n  var ownerDocument = element.ownerDocument;\n  return ownerDocument ? ownerDocument.defaultView : window;\n}\n\n/**\n * Remove event listeners used to update the popper position\n * @method\n * @memberof Popper.Utils\n * @private\n */\nfunction removeEventListeners(reference, state) {\n  // Remove resize event listener on window\n  getWindow(reference).removeEventListener('resize', state.updateBound);\n\n  // Remove scroll event listener on scroll parents\n  state.scrollParents.forEach(function (target) {\n    target.removeEventListener('scroll', state.updateBound);\n  });\n\n  // Reset state\n  state.updateBound = null;\n  state.scrollParents = [];\n  state.scrollElement = null;\n  state.eventsEnabled = false;\n  return state;\n}\n\n/**\n * Loop trough the list of modifiers and run them in order,\n * each of them will then edit the data object.\n * @method\n * @memberof Popper.Utils\n * @param {dataObject} data\n * @param {Array} modifiers\n * @param {String} ends - Optional modifier name used as stopper\n * @returns {dataObject}\n */\nfunction runModifiers(modifiers, data, ends) {\n  var modifiersToRun = ends === undefined ? modifiers : modifiers.slice(0, findIndex(modifiers, 'name', ends));\n\n  modifiersToRun.forEach(function (modifier) {\n    if (modifier['function']) {\n      // eslint-disable-line dot-notation\n      console.warn('`modifier.function` is deprecated, use `modifier.fn`!');\n    }\n    var fn = modifier['function'] || modifier.fn; // eslint-disable-line dot-notation\n    if (modifier.enabled && isFunction(fn)) {\n      // Add properties to offsets to make them a complete clientRect object\n      // we do this before each modifier to make sure the previous one doesn't\n      // mess with these values\n      data.offsets.popper = getClientRect(data.offsets.popper);\n      data.offsets.reference = getClientRect(data.offsets.reference);\n\n      data = fn(data, modifier);\n    }\n  });\n\n  return data;\n}\n\n/**\n * Set the attributes to the given popper\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element - Element to apply the attributes to\n * @argument {Object} styles\n * Object with a list of properties and values which will be applied to the element\n */\nfunction setAttributes(element, attributes) {\n  Object.keys(attributes).forEach(function (prop) {\n    var value = attributes[prop];\n    if (value !== false) {\n      element.setAttribute(prop, attributes[prop]);\n    } else {\n      element.removeAttribute(prop);\n    }\n  });\n}\n\n/**\n * Set the style to the given popper\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element - Element to apply the style to\n * @argument {Object} styles\n * Object with a list of properties and values which will be applied to the element\n */\nfunction setStyles(element, styles) {\n  Object.keys(styles).forEach(function (prop) {\n    var unit = '';\n    // add unit if the value is numeric and is one of the following\n    if (['width', 'height', 'top', 'right', 'bottom', 'left'].indexOf(prop) !== -1 && isNumeric(styles[prop])) {\n      unit = 'px';\n    }\n    element.style[prop] = styles[prop] + unit;\n  });\n}\n\nfunction attachToScrollParents(scrollParent, event, callback, scrollParents) {\n  var isBody = scrollParent.nodeName === 'BODY';\n  var target = isBody ? scrollParent.ownerDocument.defaultView : scrollParent;\n  target.addEventListener(event, callback, { passive: true });\n\n  if (!isBody) {\n    attachToScrollParents(getScrollParent(target.parentNode), event, callback, scrollParents);\n  }\n  scrollParents.push(target);\n}\n\n/**\n * Setup needed event listeners used to update the popper position\n * @method\n * @memberof Popper.Utils\n * @private\n */\nfunction setupEventListeners(reference, options, state, updateBound) {\n  // Resize event listener on window\n  state.updateBound = updateBound;\n  getWindow(reference).addEventListener('resize', state.updateBound, { passive: true });\n\n  // Scroll event listener on scroll parents\n  var scrollElement = getScrollParent(reference);\n  attachToScrollParents(scrollElement, 'scroll', state.updateBound, state.scrollParents);\n  state.scrollElement = scrollElement;\n  state.eventsEnabled = true;\n\n  return state;\n}\n\n// This is here just for backward compatibility with versions lower than v1.10.3\n// you should import the utilities using named exports, if you want them all use:\n// ```\n// import * as PopperUtils from 'popper-utils';\n// ```\n// The default export will be removed in the next major version.\nvar index = {\n  computeAutoPlacement: computeAutoPlacement,\n  debounce: debounce,\n  findIndex: findIndex,\n  getBordersSize: getBordersSize,\n  getBoundaries: getBoundaries,\n  getBoundingClientRect: getBoundingClientRect,\n  getClientRect: getClientRect,\n  getOffsetParent: getOffsetParent,\n  getOffsetRect: getOffsetRect,\n  getOffsetRectRelativeToArbitraryNode: getOffsetRectRelativeToArbitraryNode,\n  getOuterSizes: getOuterSizes,\n  getParentNode: getParentNode,\n  getPopperOffsets: getPopperOffsets,\n  getReferenceOffsets: getReferenceOffsets,\n  getScroll: getScroll,\n  getScrollParent: getScrollParent,\n  getStyleComputedProperty: getStyleComputedProperty,\n  getSupportedPropertyName: getSupportedPropertyName,\n  getWindowSizes: getWindowSizes,\n  isFixed: isFixed,\n  isFunction: isFunction,\n  isModifierEnabled: isModifierEnabled,\n  isModifierRequired: isModifierRequired,\n  isNumeric: isNumeric,\n  removeEventListeners: removeEventListeners,\n  runModifiers: runModifiers,\n  setAttributes: setAttributes,\n  setStyles: setStyles,\n  setupEventListeners: setupEventListeners\n};\n\nexports.computeAutoPlacement = computeAutoPlacement;\nexports.debounce = debounce;\nexports.findIndex = findIndex;\nexports.getBordersSize = getBordersSize;\nexports.getBoundaries = getBoundaries;\nexports.getBoundingClientRect = getBoundingClientRect;\nexports.getClientRect = getClientRect;\nexports.getOffsetParent = getOffsetParent;\nexports.getOffsetRect = getOffsetRect;\nexports.getOffsetRectRelativeToArbitraryNode = getOffsetRectRelativeToArbitraryNode;\nexports.getOuterSizes = getOuterSizes;\nexports.getParentNode = getParentNode;\nexports.getPopperOffsets = getPopperOffsets;\nexports.getReferenceOffsets = getReferenceOffsets;\nexports.getScroll = getScroll;\nexports.getScrollParent = getScrollParent;\nexports.getStyleComputedProperty = getStyleComputedProperty;\nexports.getSupportedPropertyName = getSupportedPropertyName;\nexports.getWindowSizes = getWindowSizes;\nexports.isFixed = isFixed;\nexports.isFunction = isFunction;\nexports.isModifierEnabled = isModifierEnabled;\nexports.isModifierRequired = isModifierRequired;\nexports.isNumeric = isNumeric;\nexports.removeEventListeners = removeEventListeners;\nexports.runModifiers = runModifiers;\nexports.setAttributes = setAttributes;\nexports.setStyles = setStyles;\nexports.setupEventListeners = setupEventListeners;\nexports['default'] = index;\n\nObject.defineProperty(exports, '__esModule', { value: true });\n\n})));\n//# sourceMappingURL=popper-utils.js.map\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/popper.js/popper.js",
    "content": "/**!\n * @fileOverview Kickass library to create and place poppers near their reference elements.\n * @version 1.12.6\n * @license\n * Copyright (c) 2016 Federico Zivolo and contributors\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 all\n * 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 THE\n * SOFTWARE.\n */\n(function (global, factory) {\n\ttypeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :\n\ttypeof define === 'function' && define.amd ? define(factory) :\n\t(global.Popper = factory());\n}(this, (function () { 'use strict';\n\nvar isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined';\nvar longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox'];\nvar timeoutDuration = 0;\nfor (var i = 0; i < longerTimeoutBrowsers.length; i += 1) {\n  if (isBrowser && navigator.userAgent.indexOf(longerTimeoutBrowsers[i]) >= 0) {\n    timeoutDuration = 1;\n    break;\n  }\n}\n\nfunction microtaskDebounce(fn) {\n  var called = false;\n  return function () {\n    if (called) {\n      return;\n    }\n    called = true;\n    Promise.resolve().then(function () {\n      called = false;\n      fn();\n    });\n  };\n}\n\nfunction taskDebounce(fn) {\n  var scheduled = false;\n  return function () {\n    if (!scheduled) {\n      scheduled = true;\n      setTimeout(function () {\n        scheduled = false;\n        fn();\n      }, timeoutDuration);\n    }\n  };\n}\n\nvar supportsMicroTasks = isBrowser && window.Promise;\n\n/**\n* Create a debounced version of a method, that's asynchronously deferred\n* but called in the minimum time possible.\n*\n* @method\n* @memberof Popper.Utils\n* @argument {Function} fn\n* @returns {Function}\n*/\nvar debounce = supportsMicroTasks ? microtaskDebounce : taskDebounce;\n\n/**\n * Check if the given variable is a function\n * @method\n * @memberof Popper.Utils\n * @argument {Any} functionToCheck - variable to check\n * @returns {Boolean} answer to: is a function?\n */\nfunction isFunction(functionToCheck) {\n  var getType = {};\n  return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';\n}\n\n/**\n * Get CSS computed property of the given element\n * @method\n * @memberof Popper.Utils\n * @argument {Eement} element\n * @argument {String} property\n */\nfunction getStyleComputedProperty(element, property) {\n  if (element.nodeType !== 1) {\n    return [];\n  }\n  // NOTE: 1 DOM access here\n  var css = window.getComputedStyle(element, null);\n  return property ? css[property] : css;\n}\n\n/**\n * Returns the parentNode or the host of the element\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @returns {Element} parent\n */\nfunction getParentNode(element) {\n  if (element.nodeName === 'HTML') {\n    return element;\n  }\n  return element.parentNode || element.host;\n}\n\n/**\n * Returns the scrolling parent of the given element\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @returns {Element} scroll parent\n */\nfunction getScrollParent(element) {\n  // Return body, `getScroll` will take care to get the correct `scrollTop` from it\n  if (!element) {\n    return window.document.body;\n  }\n\n  switch (element.nodeName) {\n    case 'HTML':\n    case 'BODY':\n      return element.ownerDocument.body;\n    case '#document':\n      return element.body;\n  }\n\n  // Firefox want us to check `-x` and `-y` variations as well\n\n  var _getStyleComputedProp = getStyleComputedProperty(element),\n      overflow = _getStyleComputedProp.overflow,\n      overflowX = _getStyleComputedProp.overflowX,\n      overflowY = _getStyleComputedProp.overflowY;\n\n  if (/(auto|scroll)/.test(overflow + overflowY + overflowX)) {\n    return element;\n  }\n\n  return getScrollParent(getParentNode(element));\n}\n\n/**\n * Returns the offset parent of the given element\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @returns {Element} offset parent\n */\nfunction getOffsetParent(element) {\n  // NOTE: 1 DOM access here\n  var offsetParent = element && element.offsetParent;\n  var nodeName = offsetParent && offsetParent.nodeName;\n\n  if (!nodeName || nodeName === 'BODY' || nodeName === 'HTML') {\n    if (element) {\n      return element.ownerDocument.documentElement;\n    }\n\n    return window.document.documentElement;\n  }\n\n  // .offsetParent will return the closest TD or TABLE in case\n  // no offsetParent is present, I hate this job...\n  if (['TD', 'TABLE'].indexOf(offsetParent.nodeName) !== -1 && getStyleComputedProperty(offsetParent, 'position') === 'static') {\n    return getOffsetParent(offsetParent);\n  }\n\n  return offsetParent;\n}\n\nfunction isOffsetContainer(element) {\n  var nodeName = element.nodeName;\n\n  if (nodeName === 'BODY') {\n    return false;\n  }\n  return nodeName === 'HTML' || getOffsetParent(element.firstElementChild) === element;\n}\n\n/**\n * Finds the root node (document, shadowDOM root) of the given element\n * @method\n * @memberof Popper.Utils\n * @argument {Element} node\n * @returns {Element} root node\n */\nfunction getRoot(node) {\n  if (node.parentNode !== null) {\n    return getRoot(node.parentNode);\n  }\n\n  return node;\n}\n\n/**\n * Finds the offset parent common to the two provided nodes\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element1\n * @argument {Element} element2\n * @returns {Element} common offset parent\n */\nfunction findCommonOffsetParent(element1, element2) {\n  // This check is needed to avoid errors in case one of the elements isn't defined for any reason\n  if (!element1 || !element1.nodeType || !element2 || !element2.nodeType) {\n    return window.document.documentElement;\n  }\n\n  // Here we make sure to give as \"start\" the element that comes first in the DOM\n  var order = element1.compareDocumentPosition(element2) & Node.DOCUMENT_POSITION_FOLLOWING;\n  var start = order ? element1 : element2;\n  var end = order ? element2 : element1;\n\n  // Get common ancestor container\n  var range = document.createRange();\n  range.setStart(start, 0);\n  range.setEnd(end, 0);\n  var commonAncestorContainer = range.commonAncestorContainer;\n\n  // Both nodes are inside #document\n\n  if (element1 !== commonAncestorContainer && element2 !== commonAncestorContainer || start.contains(end)) {\n    if (isOffsetContainer(commonAncestorContainer)) {\n      return commonAncestorContainer;\n    }\n\n    return getOffsetParent(commonAncestorContainer);\n  }\n\n  // one of the nodes is inside shadowDOM, find which one\n  var element1root = getRoot(element1);\n  if (element1root.host) {\n    return findCommonOffsetParent(element1root.host, element2);\n  } else {\n    return findCommonOffsetParent(element1, getRoot(element2).host);\n  }\n}\n\n/**\n * Gets the scroll value of the given element in the given side (top and left)\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @argument {String} side `top` or `left`\n * @returns {number} amount of scrolled pixels\n */\nfunction getScroll(element) {\n  var side = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'top';\n\n  var upperSide = side === 'top' ? 'scrollTop' : 'scrollLeft';\n  var nodeName = element.nodeName;\n\n  if (nodeName === 'BODY' || nodeName === 'HTML') {\n    var html = element.ownerDocument.documentElement;\n    var scrollingElement = element.ownerDocument.scrollingElement || html;\n    return scrollingElement[upperSide];\n  }\n\n  return element[upperSide];\n}\n\n/*\n * Sum or subtract the element scroll values (left and top) from a given rect object\n * @method\n * @memberof Popper.Utils\n * @param {Object} rect - Rect object you want to change\n * @param {HTMLElement} element - The element from the function reads the scroll values\n * @param {Boolean} subtract - set to true if you want to subtract the scroll values\n * @return {Object} rect - The modifier rect object\n */\nfunction includeScroll(rect, element) {\n  var subtract = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;\n\n  var scrollTop = getScroll(element, 'top');\n  var scrollLeft = getScroll(element, 'left');\n  var modifier = subtract ? -1 : 1;\n  rect.top += scrollTop * modifier;\n  rect.bottom += scrollTop * modifier;\n  rect.left += scrollLeft * modifier;\n  rect.right += scrollLeft * modifier;\n  return rect;\n}\n\n/*\n * Helper to detect borders of a given element\n * @method\n * @memberof Popper.Utils\n * @param {CSSStyleDeclaration} styles\n * Result of `getStyleComputedProperty` on the given element\n * @param {String} axis - `x` or `y`\n * @return {number} borders - The borders size of the given axis\n */\n\nfunction getBordersSize(styles, axis) {\n  var sideA = axis === 'x' ? 'Left' : 'Top';\n  var sideB = sideA === 'Left' ? 'Right' : 'Bottom';\n\n  return +styles['border' + sideA + 'Width'].split('px')[0] + +styles['border' + sideB + 'Width'].split('px')[0];\n}\n\n/**\n * Tells if you are running Internet Explorer 10\n * @method\n * @memberof Popper.Utils\n * @returns {Boolean} isIE10\n */\nvar isIE10 = undefined;\n\nvar isIE10$1 = function () {\n  if (isIE10 === undefined) {\n    isIE10 = navigator.appVersion.indexOf('MSIE 10') !== -1;\n  }\n  return isIE10;\n};\n\nfunction getSize(axis, body, html, computedStyle) {\n  return Math.max(body['offset' + axis], body['scroll' + axis], html['client' + axis], html['offset' + axis], html['scroll' + axis], isIE10$1() ? html['offset' + axis] + computedStyle['margin' + (axis === 'Height' ? 'Top' : 'Left')] + computedStyle['margin' + (axis === 'Height' ? 'Bottom' : 'Right')] : 0);\n}\n\nfunction getWindowSizes() {\n  var body = window.document.body;\n  var html = window.document.documentElement;\n  var computedStyle = isIE10$1() && window.getComputedStyle(html);\n\n  return {\n    height: getSize('Height', body, html, computedStyle),\n    width: getSize('Width', body, html, computedStyle)\n  };\n}\n\nvar classCallCheck = function (instance, Constructor) {\n  if (!(instance instanceof Constructor)) {\n    throw new TypeError(\"Cannot call a class as a function\");\n  }\n};\n\nvar createClass = function () {\n  function defineProperties(target, props) {\n    for (var i = 0; i < props.length; i++) {\n      var descriptor = props[i];\n      descriptor.enumerable = descriptor.enumerable || false;\n      descriptor.configurable = true;\n      if (\"value\" in descriptor) descriptor.writable = true;\n      Object.defineProperty(target, descriptor.key, descriptor);\n    }\n  }\n\n  return function (Constructor, protoProps, staticProps) {\n    if (protoProps) defineProperties(Constructor.prototype, protoProps);\n    if (staticProps) defineProperties(Constructor, staticProps);\n    return Constructor;\n  };\n}();\n\n\n\n\n\nvar defineProperty = function (obj, key, value) {\n  if (key in obj) {\n    Object.defineProperty(obj, key, {\n      value: value,\n      enumerable: true,\n      configurable: true,\n      writable: true\n    });\n  } else {\n    obj[key] = value;\n  }\n\n  return obj;\n};\n\nvar _extends = Object.assign || function (target) {\n  for (var i = 1; i < arguments.length; i++) {\n    var source = arguments[i];\n\n    for (var key in source) {\n      if (Object.prototype.hasOwnProperty.call(source, key)) {\n        target[key] = source[key];\n      }\n    }\n  }\n\n  return target;\n};\n\n/**\n * Given element offsets, generate an output similar to getBoundingClientRect\n * @method\n * @memberof Popper.Utils\n * @argument {Object} offsets\n * @returns {Object} ClientRect like output\n */\nfunction getClientRect(offsets) {\n  return _extends({}, offsets, {\n    right: offsets.left + offsets.width,\n    bottom: offsets.top + offsets.height\n  });\n}\n\n/**\n * Get bounding client rect of given element\n * @method\n * @memberof Popper.Utils\n * @param {HTMLElement} element\n * @return {Object} client rect\n */\nfunction getBoundingClientRect(element) {\n  var rect = {};\n\n  // IE10 10 FIX: Please, don't ask, the element isn't\n  // considered in DOM in some circumstances...\n  // This isn't reproducible in IE10 compatibility mode of IE11\n  if (isIE10$1()) {\n    try {\n      rect = element.getBoundingClientRect();\n      var scrollTop = getScroll(element, 'top');\n      var scrollLeft = getScroll(element, 'left');\n      rect.top += scrollTop;\n      rect.left += scrollLeft;\n      rect.bottom += scrollTop;\n      rect.right += scrollLeft;\n    } catch (err) {}\n  } else {\n    rect = element.getBoundingClientRect();\n  }\n\n  var result = {\n    left: rect.left,\n    top: rect.top,\n    width: rect.right - rect.left,\n    height: rect.bottom - rect.top\n  };\n\n  // subtract scrollbar size from sizes\n  var sizes = element.nodeName === 'HTML' ? getWindowSizes() : {};\n  var width = sizes.width || element.clientWidth || result.right - result.left;\n  var height = sizes.height || element.clientHeight || result.bottom - result.top;\n\n  var horizScrollbar = element.offsetWidth - width;\n  var vertScrollbar = element.offsetHeight - height;\n\n  // if an hypothetical scrollbar is detected, we must be sure it's not a `border`\n  // we make this check conditional for performance reasons\n  if (horizScrollbar || vertScrollbar) {\n    var styles = getStyleComputedProperty(element);\n    horizScrollbar -= getBordersSize(styles, 'x');\n    vertScrollbar -= getBordersSize(styles, 'y');\n\n    result.width -= horizScrollbar;\n    result.height -= vertScrollbar;\n  }\n\n  return getClientRect(result);\n}\n\nfunction getOffsetRectRelativeToArbitraryNode(children, parent) {\n  var isIE10 = isIE10$1();\n  var isHTML = parent.nodeName === 'HTML';\n  var childrenRect = getBoundingClientRect(children);\n  var parentRect = getBoundingClientRect(parent);\n  var scrollParent = getScrollParent(children);\n\n  var styles = getStyleComputedProperty(parent);\n  var borderTopWidth = +styles.borderTopWidth.split('px')[0];\n  var borderLeftWidth = +styles.borderLeftWidth.split('px')[0];\n\n  var offsets = getClientRect({\n    top: childrenRect.top - parentRect.top - borderTopWidth,\n    left: childrenRect.left - parentRect.left - borderLeftWidth,\n    width: childrenRect.width,\n    height: childrenRect.height\n  });\n  offsets.marginTop = 0;\n  offsets.marginLeft = 0;\n\n  // Subtract margins of documentElement in case it's being used as parent\n  // we do this only on HTML because it's the only element that behaves\n  // differently when margins are applied to it. The margins are included in\n  // the box of the documentElement, in the other cases not.\n  if (!isIE10 && isHTML) {\n    var marginTop = +styles.marginTop.split('px')[0];\n    var marginLeft = +styles.marginLeft.split('px')[0];\n\n    offsets.top -= borderTopWidth - marginTop;\n    offsets.bottom -= borderTopWidth - marginTop;\n    offsets.left -= borderLeftWidth - marginLeft;\n    offsets.right -= borderLeftWidth - marginLeft;\n\n    // Attach marginTop and marginLeft because in some circumstances we may need them\n    offsets.marginTop = marginTop;\n    offsets.marginLeft = marginLeft;\n  }\n\n  if (isIE10 ? parent.contains(scrollParent) : parent === scrollParent && scrollParent.nodeName !== 'BODY') {\n    offsets = includeScroll(offsets, parent);\n  }\n\n  return offsets;\n}\n\nfunction getViewportOffsetRectRelativeToArtbitraryNode(element) {\n  var html = element.ownerDocument.documentElement;\n  var relativeOffset = getOffsetRectRelativeToArbitraryNode(element, html);\n  var width = Math.max(html.clientWidth, window.innerWidth || 0);\n  var height = Math.max(html.clientHeight, window.innerHeight || 0);\n\n  var scrollTop = getScroll(html);\n  var scrollLeft = getScroll(html, 'left');\n\n  var offset = {\n    top: scrollTop - relativeOffset.top + relativeOffset.marginTop,\n    left: scrollLeft - relativeOffset.left + relativeOffset.marginLeft,\n    width: width,\n    height: height\n  };\n\n  return getClientRect(offset);\n}\n\n/**\n * Check if the given element is fixed or is inside a fixed parent\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @argument {Element} customContainer\n * @returns {Boolean} answer to \"isFixed?\"\n */\nfunction isFixed(element) {\n  var nodeName = element.nodeName;\n  if (nodeName === 'BODY' || nodeName === 'HTML') {\n    return false;\n  }\n  if (getStyleComputedProperty(element, 'position') === 'fixed') {\n    return true;\n  }\n  return isFixed(getParentNode(element));\n}\n\n/**\n * Computed the boundaries limits and return them\n * @method\n * @memberof Popper.Utils\n * @param {HTMLElement} popper\n * @param {HTMLElement} reference\n * @param {number} padding\n * @param {HTMLElement} boundariesElement - Element used to define the boundaries\n * @returns {Object} Coordinates of the boundaries\n */\nfunction getBoundaries(popper, reference, padding, boundariesElement) {\n  // NOTE: 1 DOM access here\n  var boundaries = { top: 0, left: 0 };\n  var offsetParent = findCommonOffsetParent(popper, reference);\n\n  // Handle viewport case\n  if (boundariesElement === 'viewport') {\n    boundaries = getViewportOffsetRectRelativeToArtbitraryNode(offsetParent);\n  } else {\n    // Handle other cases based on DOM element used as boundaries\n    var boundariesNode = void 0;\n    if (boundariesElement === 'scrollParent') {\n      boundariesNode = getScrollParent(getParentNode(popper));\n      if (boundariesNode.nodeName === 'BODY') {\n        boundariesNode = popper.ownerDocument.documentElement;\n      }\n    } else if (boundariesElement === 'window') {\n      boundariesNode = popper.ownerDocument.documentElement;\n    } else {\n      boundariesNode = boundariesElement;\n    }\n\n    var offsets = getOffsetRectRelativeToArbitraryNode(boundariesNode, offsetParent);\n\n    // In case of HTML, we need a different computation\n    if (boundariesNode.nodeName === 'HTML' && !isFixed(offsetParent)) {\n      var _getWindowSizes = getWindowSizes(),\n          height = _getWindowSizes.height,\n          width = _getWindowSizes.width;\n\n      boundaries.top += offsets.top - offsets.marginTop;\n      boundaries.bottom = height + offsets.top;\n      boundaries.left += offsets.left - offsets.marginLeft;\n      boundaries.right = width + offsets.left;\n    } else {\n      // for all the other DOM elements, this one is good\n      boundaries = offsets;\n    }\n  }\n\n  // Add paddings\n  boundaries.left += padding;\n  boundaries.top += padding;\n  boundaries.right -= padding;\n  boundaries.bottom -= padding;\n\n  return boundaries;\n}\n\nfunction getArea(_ref) {\n  var width = _ref.width,\n      height = _ref.height;\n\n  return width * height;\n}\n\n/**\n * Utility used to transform the `auto` placement to the placement with more\n * available space.\n * @method\n * @memberof Popper.Utils\n * @argument {Object} data - The data object generated by update method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction computeAutoPlacement(placement, refRect, popper, reference, boundariesElement) {\n  var padding = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0;\n\n  if (placement.indexOf('auto') === -1) {\n    return placement;\n  }\n\n  var boundaries = getBoundaries(popper, reference, padding, boundariesElement);\n\n  var rects = {\n    top: {\n      width: boundaries.width,\n      height: refRect.top - boundaries.top\n    },\n    right: {\n      width: boundaries.right - refRect.right,\n      height: boundaries.height\n    },\n    bottom: {\n      width: boundaries.width,\n      height: boundaries.bottom - refRect.bottom\n    },\n    left: {\n      width: refRect.left - boundaries.left,\n      height: boundaries.height\n    }\n  };\n\n  var sortedAreas = Object.keys(rects).map(function (key) {\n    return _extends({\n      key: key\n    }, rects[key], {\n      area: getArea(rects[key])\n    });\n  }).sort(function (a, b) {\n    return b.area - a.area;\n  });\n\n  var filteredAreas = sortedAreas.filter(function (_ref2) {\n    var width = _ref2.width,\n        height = _ref2.height;\n    return width >= popper.clientWidth && height >= popper.clientHeight;\n  });\n\n  var computedPlacement = filteredAreas.length > 0 ? filteredAreas[0].key : sortedAreas[0].key;\n\n  var variation = placement.split('-')[1];\n\n  return computedPlacement + (variation ? '-' + variation : '');\n}\n\n/**\n * Get offsets to the reference element\n * @method\n * @memberof Popper.Utils\n * @param {Object} state\n * @param {Element} popper - the popper element\n * @param {Element} reference - the reference element (the popper will be relative to this)\n * @returns {Object} An object containing the offsets which will be applied to the popper\n */\nfunction getReferenceOffsets(state, popper, reference) {\n  var commonOffsetParent = findCommonOffsetParent(popper, reference);\n  return getOffsetRectRelativeToArbitraryNode(reference, commonOffsetParent);\n}\n\n/**\n * Get the outer sizes of the given element (offset size + margins)\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @returns {Object} object containing width and height properties\n */\nfunction getOuterSizes(element) {\n  var styles = window.getComputedStyle(element);\n  var x = parseFloat(styles.marginTop) + parseFloat(styles.marginBottom);\n  var y = parseFloat(styles.marginLeft) + parseFloat(styles.marginRight);\n  var result = {\n    width: element.offsetWidth + y,\n    height: element.offsetHeight + x\n  };\n  return result;\n}\n\n/**\n * Get the opposite placement of the given one\n * @method\n * @memberof Popper.Utils\n * @argument {String} placement\n * @returns {String} flipped placement\n */\nfunction getOppositePlacement(placement) {\n  var hash = { left: 'right', right: 'left', bottom: 'top', top: 'bottom' };\n  return placement.replace(/left|right|bottom|top/g, function (matched) {\n    return hash[matched];\n  });\n}\n\n/**\n * Get offsets to the popper\n * @method\n * @memberof Popper.Utils\n * @param {Object} position - CSS position the Popper will get applied\n * @param {HTMLElement} popper - the popper element\n * @param {Object} referenceOffsets - the reference offsets (the popper will be relative to this)\n * @param {String} placement - one of the valid placement options\n * @returns {Object} popperOffsets - An object containing the offsets which will be applied to the popper\n */\nfunction getPopperOffsets(popper, referenceOffsets, placement) {\n  placement = placement.split('-')[0];\n\n  // Get popper node sizes\n  var popperRect = getOuterSizes(popper);\n\n  // Add position, width and height to our offsets object\n  var popperOffsets = {\n    width: popperRect.width,\n    height: popperRect.height\n  };\n\n  // depending by the popper placement we have to compute its offsets slightly differently\n  var isHoriz = ['right', 'left'].indexOf(placement) !== -1;\n  var mainSide = isHoriz ? 'top' : 'left';\n  var secondarySide = isHoriz ? 'left' : 'top';\n  var measurement = isHoriz ? 'height' : 'width';\n  var secondaryMeasurement = !isHoriz ? 'height' : 'width';\n\n  popperOffsets[mainSide] = referenceOffsets[mainSide] + referenceOffsets[measurement] / 2 - popperRect[measurement] / 2;\n  if (placement === secondarySide) {\n    popperOffsets[secondarySide] = referenceOffsets[secondarySide] - popperRect[secondaryMeasurement];\n  } else {\n    popperOffsets[secondarySide] = referenceOffsets[getOppositePlacement(secondarySide)];\n  }\n\n  return popperOffsets;\n}\n\n/**\n * Mimics the `find` method of Array\n * @method\n * @memberof Popper.Utils\n * @argument {Array} arr\n * @argument prop\n * @argument value\n * @returns index or -1\n */\nfunction find(arr, check) {\n  // use native find if supported\n  if (Array.prototype.find) {\n    return arr.find(check);\n  }\n\n  // use `filter` to obtain the same behavior of `find`\n  return arr.filter(check)[0];\n}\n\n/**\n * Return the index of the matching object\n * @method\n * @memberof Popper.Utils\n * @argument {Array} arr\n * @argument prop\n * @argument value\n * @returns index or -1\n */\nfunction findIndex(arr, prop, value) {\n  // use native findIndex if supported\n  if (Array.prototype.findIndex) {\n    return arr.findIndex(function (cur) {\n      return cur[prop] === value;\n    });\n  }\n\n  // use `find` + `indexOf` if `findIndex` isn't supported\n  var match = find(arr, function (obj) {\n    return obj[prop] === value;\n  });\n  return arr.indexOf(match);\n}\n\n/**\n * Loop trough the list of modifiers and run them in order,\n * each of them will then edit the data object.\n * @method\n * @memberof Popper.Utils\n * @param {dataObject} data\n * @param {Array} modifiers\n * @param {String} ends - Optional modifier name used as stopper\n * @returns {dataObject}\n */\nfunction runModifiers(modifiers, data, ends) {\n  var modifiersToRun = ends === undefined ? modifiers : modifiers.slice(0, findIndex(modifiers, 'name', ends));\n\n  modifiersToRun.forEach(function (modifier) {\n    if (modifier['function']) {\n      // eslint-disable-line dot-notation\n      console.warn('`modifier.function` is deprecated, use `modifier.fn`!');\n    }\n    var fn = modifier['function'] || modifier.fn; // eslint-disable-line dot-notation\n    if (modifier.enabled && isFunction(fn)) {\n      // Add properties to offsets to make them a complete clientRect object\n      // we do this before each modifier to make sure the previous one doesn't\n      // mess with these values\n      data.offsets.popper = getClientRect(data.offsets.popper);\n      data.offsets.reference = getClientRect(data.offsets.reference);\n\n      data = fn(data, modifier);\n    }\n  });\n\n  return data;\n}\n\n/**\n * Updates the position of the popper, computing the new offsets and applying\n * the new style.<br />\n * Prefer `scheduleUpdate` over `update` because of performance reasons.\n * @method\n * @memberof Popper\n */\nfunction update() {\n  // if popper is destroyed, don't perform any further update\n  if (this.state.isDestroyed) {\n    return;\n  }\n\n  var data = {\n    instance: this,\n    styles: {},\n    arrowStyles: {},\n    attributes: {},\n    flipped: false,\n    offsets: {}\n  };\n\n  // compute reference element offsets\n  data.offsets.reference = getReferenceOffsets(this.state, this.popper, this.reference);\n\n  // compute auto placement, store placement inside the data object,\n  // modifiers will be able to edit `placement` if needed\n  // and refer to originalPlacement to know the original value\n  data.placement = computeAutoPlacement(this.options.placement, data.offsets.reference, this.popper, this.reference, this.options.modifiers.flip.boundariesElement, this.options.modifiers.flip.padding);\n\n  // store the computed placement inside `originalPlacement`\n  data.originalPlacement = data.placement;\n\n  // compute the popper offsets\n  data.offsets.popper = getPopperOffsets(this.popper, data.offsets.reference, data.placement);\n  data.offsets.popper.position = 'absolute';\n\n  // run the modifiers\n  data = runModifiers(this.modifiers, data);\n\n  // the first `update` will call `onCreate` callback\n  // the other ones will call `onUpdate` callback\n  if (!this.state.isCreated) {\n    this.state.isCreated = true;\n    this.options.onCreate(data);\n  } else {\n    this.options.onUpdate(data);\n  }\n}\n\n/**\n * Helper used to know if the given modifier is enabled.\n * @method\n * @memberof Popper.Utils\n * @returns {Boolean}\n */\nfunction isModifierEnabled(modifiers, modifierName) {\n  return modifiers.some(function (_ref) {\n    var name = _ref.name,\n        enabled = _ref.enabled;\n    return enabled && name === modifierName;\n  });\n}\n\n/**\n * Get the prefixed supported property name\n * @method\n * @memberof Popper.Utils\n * @argument {String} property (camelCase)\n * @returns {String} prefixed property (camelCase or PascalCase, depending on the vendor prefix)\n */\nfunction getSupportedPropertyName(property) {\n  var prefixes = [false, 'ms', 'Webkit', 'Moz', 'O'];\n  var upperProp = property.charAt(0).toUpperCase() + property.slice(1);\n\n  for (var i = 0; i < prefixes.length - 1; i++) {\n    var prefix = prefixes[i];\n    var toCheck = prefix ? '' + prefix + upperProp : property;\n    if (typeof window.document.body.style[toCheck] !== 'undefined') {\n      return toCheck;\n    }\n  }\n  return null;\n}\n\n/**\n * Destroy the popper\n * @method\n * @memberof Popper\n */\nfunction destroy() {\n  this.state.isDestroyed = true;\n\n  // touch DOM only if `applyStyle` modifier is enabled\n  if (isModifierEnabled(this.modifiers, 'applyStyle')) {\n    this.popper.removeAttribute('x-placement');\n    this.popper.style.left = '';\n    this.popper.style.position = '';\n    this.popper.style.top = '';\n    this.popper.style[getSupportedPropertyName('transform')] = '';\n  }\n\n  this.disableEventListeners();\n\n  // remove the popper if user explicity asked for the deletion on destroy\n  // do not use `remove` because IE11 doesn't support it\n  if (this.options.removeOnDestroy) {\n    this.popper.parentNode.removeChild(this.popper);\n  }\n  return this;\n}\n\n/**\n * Get the window associated with the element\n * @argument {Element} element\n * @returns {Window}\n */\nfunction getWindow(element) {\n  var ownerDocument = element.ownerDocument;\n  return ownerDocument ? ownerDocument.defaultView : window;\n}\n\nfunction attachToScrollParents(scrollParent, event, callback, scrollParents) {\n  var isBody = scrollParent.nodeName === 'BODY';\n  var target = isBody ? scrollParent.ownerDocument.defaultView : scrollParent;\n  target.addEventListener(event, callback, { passive: true });\n\n  if (!isBody) {\n    attachToScrollParents(getScrollParent(target.parentNode), event, callback, scrollParents);\n  }\n  scrollParents.push(target);\n}\n\n/**\n * Setup needed event listeners used to update the popper position\n * @method\n * @memberof Popper.Utils\n * @private\n */\nfunction setupEventListeners(reference, options, state, updateBound) {\n  // Resize event listener on window\n  state.updateBound = updateBound;\n  getWindow(reference).addEventListener('resize', state.updateBound, { passive: true });\n\n  // Scroll event listener on scroll parents\n  var scrollElement = getScrollParent(reference);\n  attachToScrollParents(scrollElement, 'scroll', state.updateBound, state.scrollParents);\n  state.scrollElement = scrollElement;\n  state.eventsEnabled = true;\n\n  return state;\n}\n\n/**\n * It will add resize/scroll events and start recalculating\n * position of the popper element when they are triggered.\n * @method\n * @memberof Popper\n */\nfunction enableEventListeners() {\n  if (!this.state.eventsEnabled) {\n    this.state = setupEventListeners(this.reference, this.options, this.state, this.scheduleUpdate);\n  }\n}\n\n/**\n * Remove event listeners used to update the popper position\n * @method\n * @memberof Popper.Utils\n * @private\n */\nfunction removeEventListeners(reference, state) {\n  // Remove resize event listener on window\n  getWindow(reference).removeEventListener('resize', state.updateBound);\n\n  // Remove scroll event listener on scroll parents\n  state.scrollParents.forEach(function (target) {\n    target.removeEventListener('scroll', state.updateBound);\n  });\n\n  // Reset state\n  state.updateBound = null;\n  state.scrollParents = [];\n  state.scrollElement = null;\n  state.eventsEnabled = false;\n  return state;\n}\n\n/**\n * It will remove resize/scroll events and won't recalculate popper position\n * when they are triggered. It also won't trigger onUpdate callback anymore,\n * unless you call `update` method manually.\n * @method\n * @memberof Popper\n */\nfunction disableEventListeners() {\n  if (this.state.eventsEnabled) {\n    window.cancelAnimationFrame(this.scheduleUpdate);\n    this.state = removeEventListeners(this.reference, this.state);\n  }\n}\n\n/**\n * Tells if a given input is a number\n * @method\n * @memberof Popper.Utils\n * @param {*} input to check\n * @return {Boolean}\n */\nfunction isNumeric(n) {\n  return n !== '' && !isNaN(parseFloat(n)) && isFinite(n);\n}\n\n/**\n * Set the style to the given popper\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element - Element to apply the style to\n * @argument {Object} styles\n * Object with a list of properties and values which will be applied to the element\n */\nfunction setStyles(element, styles) {\n  Object.keys(styles).forEach(function (prop) {\n    var unit = '';\n    // add unit if the value is numeric and is one of the following\n    if (['width', 'height', 'top', 'right', 'bottom', 'left'].indexOf(prop) !== -1 && isNumeric(styles[prop])) {\n      unit = 'px';\n    }\n    element.style[prop] = styles[prop] + unit;\n  });\n}\n\n/**\n * Set the attributes to the given popper\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element - Element to apply the attributes to\n * @argument {Object} styles\n * Object with a list of properties and values which will be applied to the element\n */\nfunction setAttributes(element, attributes) {\n  Object.keys(attributes).forEach(function (prop) {\n    var value = attributes[prop];\n    if (value !== false) {\n      element.setAttribute(prop, attributes[prop]);\n    } else {\n      element.removeAttribute(prop);\n    }\n  });\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by `update` method\n * @argument {Object} data.styles - List of style properties - values to apply to popper element\n * @argument {Object} data.attributes - List of attribute properties - values to apply to popper element\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The same data object\n */\nfunction applyStyle(data) {\n  // any property present in `data.styles` will be applied to the popper,\n  // in this way we can make the 3rd party modifiers add custom styles to it\n  // Be aware, modifiers could override the properties defined in the previous\n  // lines of this modifier!\n  setStyles(data.instance.popper, data.styles);\n\n  // any property present in `data.attributes` will be applied to the popper,\n  // they will be set as HTML attributes of the element\n  setAttributes(data.instance.popper, data.attributes);\n\n  // if arrowElement is defined and arrowStyles has some properties\n  if (data.arrowElement && Object.keys(data.arrowStyles).length) {\n    setStyles(data.arrowElement, data.arrowStyles);\n  }\n\n  return data;\n}\n\n/**\n * Set the x-placement attribute before everything else because it could be used\n * to add margins to the popper margins needs to be calculated to get the\n * correct popper offsets.\n * @method\n * @memberof Popper.modifiers\n * @param {HTMLElement} reference - The reference element used to position the popper\n * @param {HTMLElement} popper - The HTML element used as popper.\n * @param {Object} options - Popper.js options\n */\nfunction applyStyleOnLoad(reference, popper, options, modifierOptions, state) {\n  // compute reference element offsets\n  var referenceOffsets = getReferenceOffsets(state, popper, reference);\n\n  // compute auto placement, store placement inside the data object,\n  // modifiers will be able to edit `placement` if needed\n  // and refer to originalPlacement to know the original value\n  var placement = computeAutoPlacement(options.placement, referenceOffsets, popper, reference, options.modifiers.flip.boundariesElement, options.modifiers.flip.padding);\n\n  popper.setAttribute('x-placement', placement);\n\n  // Apply `position` to popper before anything else because\n  // without the position applied we can't guarantee correct computations\n  setStyles(popper, { position: 'absolute' });\n\n  return options;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by `update` method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction computeStyle(data, options) {\n  var x = options.x,\n      y = options.y;\n  var popper = data.offsets.popper;\n\n  // Remove this legacy support in Popper.js v2\n\n  var legacyGpuAccelerationOption = find(data.instance.modifiers, function (modifier) {\n    return modifier.name === 'applyStyle';\n  }).gpuAcceleration;\n  if (legacyGpuAccelerationOption !== undefined) {\n    console.warn('WARNING: `gpuAcceleration` option moved to `computeStyle` modifier and will not be supported in future versions of Popper.js!');\n  }\n  var gpuAcceleration = legacyGpuAccelerationOption !== undefined ? legacyGpuAccelerationOption : options.gpuAcceleration;\n\n  var offsetParent = getOffsetParent(data.instance.popper);\n  var offsetParentRect = getBoundingClientRect(offsetParent);\n\n  // Styles\n  var styles = {\n    position: popper.position\n  };\n\n  // floor sides to avoid blurry text\n  var offsets = {\n    left: Math.floor(popper.left),\n    top: Math.floor(popper.top),\n    bottom: Math.floor(popper.bottom),\n    right: Math.floor(popper.right)\n  };\n\n  var sideA = x === 'bottom' ? 'top' : 'bottom';\n  var sideB = y === 'right' ? 'left' : 'right';\n\n  // if gpuAcceleration is set to `true` and transform is supported,\n  //  we use `translate3d` to apply the position to the popper we\n  // automatically use the supported prefixed version if needed\n  var prefixedProperty = getSupportedPropertyName('transform');\n\n  // now, let's make a step back and look at this code closely (wtf?)\n  // If the content of the popper grows once it's been positioned, it\n  // may happen that the popper gets misplaced because of the new content\n  // overflowing its reference element\n  // To avoid this problem, we provide two options (x and y), which allow\n  // the consumer to define the offset origin.\n  // If we position a popper on top of a reference element, we can set\n  // `x` to `top` to make the popper grow towards its top instead of\n  // its bottom.\n  var left = void 0,\n      top = void 0;\n  if (sideA === 'bottom') {\n    top = -offsetParentRect.height + offsets.bottom;\n  } else {\n    top = offsets.top;\n  }\n  if (sideB === 'right') {\n    left = -offsetParentRect.width + offsets.right;\n  } else {\n    left = offsets.left;\n  }\n  if (gpuAcceleration && prefixedProperty) {\n    styles[prefixedProperty] = 'translate3d(' + left + 'px, ' + top + 'px, 0)';\n    styles[sideA] = 0;\n    styles[sideB] = 0;\n    styles.willChange = 'transform';\n  } else {\n    // othwerise, we use the standard `top`, `left`, `bottom` and `right` properties\n    var invertTop = sideA === 'bottom' ? -1 : 1;\n    var invertLeft = sideB === 'right' ? -1 : 1;\n    styles[sideA] = top * invertTop;\n    styles[sideB] = left * invertLeft;\n    styles.willChange = sideA + ', ' + sideB;\n  }\n\n  // Attributes\n  var attributes = {\n    'x-placement': data.placement\n  };\n\n  // Update `data` attributes, styles and arrowStyles\n  data.attributes = _extends({}, attributes, data.attributes);\n  data.styles = _extends({}, styles, data.styles);\n  data.arrowStyles = _extends({}, data.offsets.arrow, data.arrowStyles);\n\n  return data;\n}\n\n/**\n * Helper used to know if the given modifier depends from another one.<br />\n * It checks if the needed modifier is listed and enabled.\n * @method\n * @memberof Popper.Utils\n * @param {Array} modifiers - list of modifiers\n * @param {String} requestingName - name of requesting modifier\n * @param {String} requestedName - name of requested modifier\n * @returns {Boolean}\n */\nfunction isModifierRequired(modifiers, requestingName, requestedName) {\n  var requesting = find(modifiers, function (_ref) {\n    var name = _ref.name;\n    return name === requestingName;\n  });\n\n  var isRequired = !!requesting && modifiers.some(function (modifier) {\n    return modifier.name === requestedName && modifier.enabled && modifier.order < requesting.order;\n  });\n\n  if (!isRequired) {\n    var _requesting = '`' + requestingName + '`';\n    var requested = '`' + requestedName + '`';\n    console.warn(requested + ' modifier is required by ' + _requesting + ' modifier in order to work, be sure to include it before ' + _requesting + '!');\n  }\n  return isRequired;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by update method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction arrow(data, options) {\n  // arrow depends on keepTogether in order to work\n  if (!isModifierRequired(data.instance.modifiers, 'arrow', 'keepTogether')) {\n    return data;\n  }\n\n  var arrowElement = options.element;\n\n  // if arrowElement is a string, suppose it's a CSS selector\n  if (typeof arrowElement === 'string') {\n    arrowElement = data.instance.popper.querySelector(arrowElement);\n\n    // if arrowElement is not found, don't run the modifier\n    if (!arrowElement) {\n      return data;\n    }\n  } else {\n    // if the arrowElement isn't a query selector we must check that the\n    // provided DOM node is child of its popper node\n    if (!data.instance.popper.contains(arrowElement)) {\n      console.warn('WARNING: `arrow.element` must be child of its popper element!');\n      return data;\n    }\n  }\n\n  var placement = data.placement.split('-')[0];\n  var _data$offsets = data.offsets,\n      popper = _data$offsets.popper,\n      reference = _data$offsets.reference;\n\n  var isVertical = ['left', 'right'].indexOf(placement) !== -1;\n\n  var len = isVertical ? 'height' : 'width';\n  var sideCapitalized = isVertical ? 'Top' : 'Left';\n  var side = sideCapitalized.toLowerCase();\n  var altSide = isVertical ? 'left' : 'top';\n  var opSide = isVertical ? 'bottom' : 'right';\n  var arrowElementSize = getOuterSizes(arrowElement)[len];\n\n  //\n  // extends keepTogether behavior making sure the popper and its\n  // reference have enough pixels in conjuction\n  //\n\n  // top/left side\n  if (reference[opSide] - arrowElementSize < popper[side]) {\n    data.offsets.popper[side] -= popper[side] - (reference[opSide] - arrowElementSize);\n  }\n  // bottom/right side\n  if (reference[side] + arrowElementSize > popper[opSide]) {\n    data.offsets.popper[side] += reference[side] + arrowElementSize - popper[opSide];\n  }\n\n  // compute center of the popper\n  var center = reference[side] + reference[len] / 2 - arrowElementSize / 2;\n\n  // Compute the sideValue using the updated popper offsets\n  // take popper margin in account because we don't have this info available\n  var popperMarginSide = getStyleComputedProperty(data.instance.popper, 'margin' + sideCapitalized).replace('px', '');\n  var sideValue = center - getClientRect(data.offsets.popper)[side] - popperMarginSide;\n\n  // prevent arrowElement from being placed not contiguously to its popper\n  sideValue = Math.max(Math.min(popper[len] - arrowElementSize, sideValue), 0);\n\n  data.arrowElement = arrowElement;\n  data.offsets.arrow = {};\n  data.offsets.arrow[side] = Math.round(sideValue);\n  data.offsets.arrow[altSide] = ''; // make sure to unset any eventual altSide value from the DOM node\n\n  return data;\n}\n\n/**\n * Get the opposite placement variation of the given one\n * @method\n * @memberof Popper.Utils\n * @argument {String} placement variation\n * @returns {String} flipped placement variation\n */\nfunction getOppositeVariation(variation) {\n  if (variation === 'end') {\n    return 'start';\n  } else if (variation === 'start') {\n    return 'end';\n  }\n  return variation;\n}\n\n/**\n * List of accepted placements to use as values of the `placement` option.<br />\n * Valid placements are:\n * - `auto`\n * - `top`\n * - `right`\n * - `bottom`\n * - `left`\n *\n * Each placement can have a variation from this list:\n * - `-start`\n * - `-end`\n *\n * Variations are interpreted easily if you think of them as the left to right\n * written languages. Horizontally (`top` and `bottom`), `start` is left and `end`\n * is right.<br />\n * Vertically (`left` and `right`), `start` is top and `end` is bottom.\n *\n * Some valid examples are:\n * - `top-end` (on top of reference, right aligned)\n * - `right-start` (on right of reference, top aligned)\n * - `bottom` (on bottom, centered)\n * - `auto-right` (on the side with more space available, alignment depends by placement)\n *\n * @static\n * @type {Array}\n * @enum {String}\n * @readonly\n * @method placements\n * @memberof Popper\n */\nvar placements = ['auto-start', 'auto', 'auto-end', 'top-start', 'top', 'top-end', 'right-start', 'right', 'right-end', 'bottom-end', 'bottom', 'bottom-start', 'left-end', 'left', 'left-start'];\n\n// Get rid of `auto` `auto-start` and `auto-end`\nvar validPlacements = placements.slice(3);\n\n/**\n * Given an initial placement, returns all the subsequent placements\n * clockwise (or counter-clockwise).\n *\n * @method\n * @memberof Popper.Utils\n * @argument {String} placement - A valid placement (it accepts variations)\n * @argument {Boolean} counter - Set to true to walk the placements counterclockwise\n * @returns {Array} placements including their variations\n */\nfunction clockwise(placement) {\n  var counter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;\n\n  var index = validPlacements.indexOf(placement);\n  var arr = validPlacements.slice(index + 1).concat(validPlacements.slice(0, index));\n  return counter ? arr.reverse() : arr;\n}\n\nvar BEHAVIORS = {\n  FLIP: 'flip',\n  CLOCKWISE: 'clockwise',\n  COUNTERCLOCKWISE: 'counterclockwise'\n};\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by update method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction flip(data, options) {\n  // if `inner` modifier is enabled, we can't use the `flip` modifier\n  if (isModifierEnabled(data.instance.modifiers, 'inner')) {\n    return data;\n  }\n\n  if (data.flipped && data.placement === data.originalPlacement) {\n    // seems like flip is trying to loop, probably there's not enough space on any of the flippable sides\n    return data;\n  }\n\n  var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, options.boundariesElement);\n\n  var placement = data.placement.split('-')[0];\n  var placementOpposite = getOppositePlacement(placement);\n  var variation = data.placement.split('-')[1] || '';\n\n  var flipOrder = [];\n\n  switch (options.behavior) {\n    case BEHAVIORS.FLIP:\n      flipOrder = [placement, placementOpposite];\n      break;\n    case BEHAVIORS.CLOCKWISE:\n      flipOrder = clockwise(placement);\n      break;\n    case BEHAVIORS.COUNTERCLOCKWISE:\n      flipOrder = clockwise(placement, true);\n      break;\n    default:\n      flipOrder = options.behavior;\n  }\n\n  flipOrder.forEach(function (step, index) {\n    if (placement !== step || flipOrder.length === index + 1) {\n      return data;\n    }\n\n    placement = data.placement.split('-')[0];\n    placementOpposite = getOppositePlacement(placement);\n\n    var popperOffsets = data.offsets.popper;\n    var refOffsets = data.offsets.reference;\n\n    // using floor because the reference offsets may contain decimals we are not going to consider here\n    var floor = Math.floor;\n    var overlapsRef = placement === 'left' && floor(popperOffsets.right) > floor(refOffsets.left) || placement === 'right' && floor(popperOffsets.left) < floor(refOffsets.right) || placement === 'top' && floor(popperOffsets.bottom) > floor(refOffsets.top) || placement === 'bottom' && floor(popperOffsets.top) < floor(refOffsets.bottom);\n\n    var overflowsLeft = floor(popperOffsets.left) < floor(boundaries.left);\n    var overflowsRight = floor(popperOffsets.right) > floor(boundaries.right);\n    var overflowsTop = floor(popperOffsets.top) < floor(boundaries.top);\n    var overflowsBottom = floor(popperOffsets.bottom) > floor(boundaries.bottom);\n\n    var overflowsBoundaries = placement === 'left' && overflowsLeft || placement === 'right' && overflowsRight || placement === 'top' && overflowsTop || placement === 'bottom' && overflowsBottom;\n\n    // flip the variation if required\n    var isVertical = ['top', 'bottom'].indexOf(placement) !== -1;\n    var flippedVariation = !!options.flipVariations && (isVertical && variation === 'start' && overflowsLeft || isVertical && variation === 'end' && overflowsRight || !isVertical && variation === 'start' && overflowsTop || !isVertical && variation === 'end' && overflowsBottom);\n\n    if (overlapsRef || overflowsBoundaries || flippedVariation) {\n      // this boolean to detect any flip loop\n      data.flipped = true;\n\n      if (overlapsRef || overflowsBoundaries) {\n        placement = flipOrder[index + 1];\n      }\n\n      if (flippedVariation) {\n        variation = getOppositeVariation(variation);\n      }\n\n      data.placement = placement + (variation ? '-' + variation : '');\n\n      // this object contains `position`, we want to preserve it along with\n      // any additional property we may add in the future\n      data.offsets.popper = _extends({}, data.offsets.popper, getPopperOffsets(data.instance.popper, data.offsets.reference, data.placement));\n\n      data = runModifiers(data.instance.modifiers, data, 'flip');\n    }\n  });\n  return data;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by update method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction keepTogether(data) {\n  var _data$offsets = data.offsets,\n      popper = _data$offsets.popper,\n      reference = _data$offsets.reference;\n\n  var placement = data.placement.split('-')[0];\n  var floor = Math.floor;\n  var isVertical = ['top', 'bottom'].indexOf(placement) !== -1;\n  var side = isVertical ? 'right' : 'bottom';\n  var opSide = isVertical ? 'left' : 'top';\n  var measurement = isVertical ? 'width' : 'height';\n\n  if (popper[side] < floor(reference[opSide])) {\n    data.offsets.popper[opSide] = floor(reference[opSide]) - popper[measurement];\n  }\n  if (popper[opSide] > floor(reference[side])) {\n    data.offsets.popper[opSide] = floor(reference[side]);\n  }\n\n  return data;\n}\n\n/**\n * Converts a string containing value + unit into a px value number\n * @function\n * @memberof {modifiers~offset}\n * @private\n * @argument {String} str - Value + unit string\n * @argument {String} measurement - `height` or `width`\n * @argument {Object} popperOffsets\n * @argument {Object} referenceOffsets\n * @returns {Number|String}\n * Value in pixels, or original string if no values were extracted\n */\nfunction toValue(str, measurement, popperOffsets, referenceOffsets) {\n  // separate value from unit\n  var split = str.match(/((?:\\-|\\+)?\\d*\\.?\\d*)(.*)/);\n  var value = +split[1];\n  var unit = split[2];\n\n  // If it's not a number it's an operator, I guess\n  if (!value) {\n    return str;\n  }\n\n  if (unit.indexOf('%') === 0) {\n    var element = void 0;\n    switch (unit) {\n      case '%p':\n        element = popperOffsets;\n        break;\n      case '%':\n      case '%r':\n      default:\n        element = referenceOffsets;\n    }\n\n    var rect = getClientRect(element);\n    return rect[measurement] / 100 * value;\n  } else if (unit === 'vh' || unit === 'vw') {\n    // if is a vh or vw, we calculate the size based on the viewport\n    var size = void 0;\n    if (unit === 'vh') {\n      size = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);\n    } else {\n      size = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);\n    }\n    return size / 100 * value;\n  } else {\n    // if is an explicit pixel unit, we get rid of the unit and keep the value\n    // if is an implicit unit, it's px, and we return just the value\n    return value;\n  }\n}\n\n/**\n * Parse an `offset` string to extrapolate `x` and `y` numeric offsets.\n * @function\n * @memberof {modifiers~offset}\n * @private\n * @argument {String} offset\n * @argument {Object} popperOffsets\n * @argument {Object} referenceOffsets\n * @argument {String} basePlacement\n * @returns {Array} a two cells array with x and y offsets in numbers\n */\nfunction parseOffset(offset, popperOffsets, referenceOffsets, basePlacement) {\n  var offsets = [0, 0];\n\n  // Use height if placement is left or right and index is 0 otherwise use width\n  // in this way the first offset will use an axis and the second one\n  // will use the other one\n  var useHeight = ['right', 'left'].indexOf(basePlacement) !== -1;\n\n  // Split the offset string to obtain a list of values and operands\n  // The regex addresses values with the plus or minus sign in front (+10, -20, etc)\n  var fragments = offset.split(/(\\+|\\-)/).map(function (frag) {\n    return frag.trim();\n  });\n\n  // Detect if the offset string contains a pair of values or a single one\n  // they could be separated by comma or space\n  var divider = fragments.indexOf(find(fragments, function (frag) {\n    return frag.search(/,|\\s/) !== -1;\n  }));\n\n  if (fragments[divider] && fragments[divider].indexOf(',') === -1) {\n    console.warn('Offsets separated by white space(s) are deprecated, use a comma (,) instead.');\n  }\n\n  // If divider is found, we divide the list of values and operands to divide\n  // them by ofset X and Y.\n  var splitRegex = /\\s*,\\s*|\\s+/;\n  var ops = divider !== -1 ? [fragments.slice(0, divider).concat([fragments[divider].split(splitRegex)[0]]), [fragments[divider].split(splitRegex)[1]].concat(fragments.slice(divider + 1))] : [fragments];\n\n  // Convert the values with units to absolute pixels to allow our computations\n  ops = ops.map(function (op, index) {\n    // Most of the units rely on the orientation of the popper\n    var measurement = (index === 1 ? !useHeight : useHeight) ? 'height' : 'width';\n    var mergeWithPrevious = false;\n    return op\n    // This aggregates any `+` or `-` sign that aren't considered operators\n    // e.g.: 10 + +5 => [10, +, +5]\n    .reduce(function (a, b) {\n      if (a[a.length - 1] === '' && ['+', '-'].indexOf(b) !== -1) {\n        a[a.length - 1] = b;\n        mergeWithPrevious = true;\n        return a;\n      } else if (mergeWithPrevious) {\n        a[a.length - 1] += b;\n        mergeWithPrevious = false;\n        return a;\n      } else {\n        return a.concat(b);\n      }\n    }, [])\n    // Here we convert the string values into number values (in px)\n    .map(function (str) {\n      return toValue(str, measurement, popperOffsets, referenceOffsets);\n    });\n  });\n\n  // Loop trough the offsets arrays and execute the operations\n  ops.forEach(function (op, index) {\n    op.forEach(function (frag, index2) {\n      if (isNumeric(frag)) {\n        offsets[index] += frag * (op[index2 - 1] === '-' ? -1 : 1);\n      }\n    });\n  });\n  return offsets;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by update method\n * @argument {Object} options - Modifiers configuration and options\n * @argument {Number|String} options.offset=0\n * The offset value as described in the modifier description\n * @returns {Object} The data object, properly modified\n */\nfunction offset(data, _ref) {\n  var offset = _ref.offset;\n  var placement = data.placement,\n      _data$offsets = data.offsets,\n      popper = _data$offsets.popper,\n      reference = _data$offsets.reference;\n\n  var basePlacement = placement.split('-')[0];\n\n  var offsets = void 0;\n  if (isNumeric(+offset)) {\n    offsets = [+offset, 0];\n  } else {\n    offsets = parseOffset(offset, popper, reference, basePlacement);\n  }\n\n  if (basePlacement === 'left') {\n    popper.top += offsets[0];\n    popper.left -= offsets[1];\n  } else if (basePlacement === 'right') {\n    popper.top += offsets[0];\n    popper.left += offsets[1];\n  } else if (basePlacement === 'top') {\n    popper.left += offsets[0];\n    popper.top -= offsets[1];\n  } else if (basePlacement === 'bottom') {\n    popper.left += offsets[0];\n    popper.top += offsets[1];\n  }\n\n  data.popper = popper;\n  return data;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by `update` method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction preventOverflow(data, options) {\n  var boundariesElement = options.boundariesElement || getOffsetParent(data.instance.popper);\n\n  // If offsetParent is the reference element, we really want to\n  // go one step up and use the next offsetParent as reference to\n  // avoid to make this modifier completely useless and look like broken\n  if (data.instance.reference === boundariesElement) {\n    boundariesElement = getOffsetParent(boundariesElement);\n  }\n\n  var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, boundariesElement);\n  options.boundaries = boundaries;\n\n  var order = options.priority;\n  var popper = data.offsets.popper;\n\n  var check = {\n    primary: function primary(placement) {\n      var value = popper[placement];\n      if (popper[placement] < boundaries[placement] && !options.escapeWithReference) {\n        value = Math.max(popper[placement], boundaries[placement]);\n      }\n      return defineProperty({}, placement, value);\n    },\n    secondary: function secondary(placement) {\n      var mainSide = placement === 'right' ? 'left' : 'top';\n      var value = popper[mainSide];\n      if (popper[placement] > boundaries[placement] && !options.escapeWithReference) {\n        value = Math.min(popper[mainSide], boundaries[placement] - (placement === 'right' ? popper.width : popper.height));\n      }\n      return defineProperty({}, mainSide, value);\n    }\n  };\n\n  order.forEach(function (placement) {\n    var side = ['left', 'top'].indexOf(placement) !== -1 ? 'primary' : 'secondary';\n    popper = _extends({}, popper, check[side](placement));\n  });\n\n  data.offsets.popper = popper;\n\n  return data;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by `update` method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction shift(data) {\n  var placement = data.placement;\n  var basePlacement = placement.split('-')[0];\n  var shiftvariation = placement.split('-')[1];\n\n  // if shift shiftvariation is specified, run the modifier\n  if (shiftvariation) {\n    var _data$offsets = data.offsets,\n        reference = _data$offsets.reference,\n        popper = _data$offsets.popper;\n\n    var isVertical = ['bottom', 'top'].indexOf(basePlacement) !== -1;\n    var side = isVertical ? 'left' : 'top';\n    var measurement = isVertical ? 'width' : 'height';\n\n    var shiftOffsets = {\n      start: defineProperty({}, side, reference[side]),\n      end: defineProperty({}, side, reference[side] + reference[measurement] - popper[measurement])\n    };\n\n    data.offsets.popper = _extends({}, popper, shiftOffsets[shiftvariation]);\n  }\n\n  return data;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by update method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction hide(data) {\n  if (!isModifierRequired(data.instance.modifiers, 'hide', 'preventOverflow')) {\n    return data;\n  }\n\n  var refRect = data.offsets.reference;\n  var bound = find(data.instance.modifiers, function (modifier) {\n    return modifier.name === 'preventOverflow';\n  }).boundaries;\n\n  if (refRect.bottom < bound.top || refRect.left > bound.right || refRect.top > bound.bottom || refRect.right < bound.left) {\n    // Avoid unnecessary DOM access if visibility hasn't changed\n    if (data.hide === true) {\n      return data;\n    }\n\n    data.hide = true;\n    data.attributes['x-out-of-boundaries'] = '';\n  } else {\n    // Avoid unnecessary DOM access if visibility hasn't changed\n    if (data.hide === false) {\n      return data;\n    }\n\n    data.hide = false;\n    data.attributes['x-out-of-boundaries'] = false;\n  }\n\n  return data;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by `update` method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction inner(data) {\n  var placement = data.placement;\n  var basePlacement = placement.split('-')[0];\n  var _data$offsets = data.offsets,\n      popper = _data$offsets.popper,\n      reference = _data$offsets.reference;\n\n  var isHoriz = ['left', 'right'].indexOf(basePlacement) !== -1;\n\n  var subtractLength = ['top', 'left'].indexOf(basePlacement) === -1;\n\n  popper[isHoriz ? 'left' : 'top'] = reference[basePlacement] - (subtractLength ? popper[isHoriz ? 'width' : 'height'] : 0);\n\n  data.placement = getOppositePlacement(placement);\n  data.offsets.popper = getClientRect(popper);\n\n  return data;\n}\n\n/**\n * Modifier function, each modifier can have a function of this type assigned\n * to its `fn` property.<br />\n * These functions will be called on each update, this means that you must\n * make sure they are performant enough to avoid performance bottlenecks.\n *\n * @function ModifierFn\n * @argument {dataObject} data - The data object generated by `update` method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {dataObject} The data object, properly modified\n */\n\n/**\n * Modifiers are plugins used to alter the behavior of your poppers.<br />\n * Popper.js uses a set of 9 modifiers to provide all the basic functionalities\n * needed by the library.\n *\n * Usually you don't want to override the `order`, `fn` and `onLoad` props.\n * All the other properties are configurations that could be tweaked.\n * @namespace modifiers\n */\nvar modifiers = {\n  /**\n   * Modifier used to shift the popper on the start or end of its reference\n   * element.<br />\n   * It will read the variation of the `placement` property.<br />\n   * It can be one either `-end` or `-start`.\n   * @memberof modifiers\n   * @inner\n   */\n  shift: {\n    /** @prop {number} order=100 - Index used to define the order of execution */\n    order: 100,\n    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n    enabled: true,\n    /** @prop {ModifierFn} */\n    fn: shift\n  },\n\n  /**\n   * The `offset` modifier can shift your popper on both its axis.\n   *\n   * It accepts the following units:\n   * - `px` or unitless, interpreted as pixels\n   * - `%` or `%r`, percentage relative to the length of the reference element\n   * - `%p`, percentage relative to the length of the popper element\n   * - `vw`, CSS viewport width unit\n   * - `vh`, CSS viewport height unit\n   *\n   * For length is intended the main axis relative to the placement of the popper.<br />\n   * This means that if the placement is `top` or `bottom`, the length will be the\n   * `width`. In case of `left` or `right`, it will be the height.\n   *\n   * You can provide a single value (as `Number` or `String`), or a pair of values\n   * as `String` divided by a comma or one (or more) white spaces.<br />\n   * The latter is a deprecated method because it leads to confusion and will be\n   * removed in v2.<br />\n   * Additionally, it accepts additions and subtractions between different units.\n   * Note that multiplications and divisions aren't supported.\n   *\n   * Valid examples are:\n   * ```\n   * 10\n   * '10%'\n   * '10, 10'\n   * '10%, 10'\n   * '10 + 10%'\n   * '10 - 5vh + 3%'\n   * '-10px + 5vh, 5px - 6%'\n   * ```\n   * > **NB**: If you desire to apply offsets to your poppers in a way that may make them overlap\n   * > with their reference element, unfortunately, you will have to disable the `flip` modifier.\n   * > More on this [reading this issue](https://github.com/FezVrasta/popper.js/issues/373)\n   *\n   * @memberof modifiers\n   * @inner\n   */\n  offset: {\n    /** @prop {number} order=200 - Index used to define the order of execution */\n    order: 200,\n    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n    enabled: true,\n    /** @prop {ModifierFn} */\n    fn: offset,\n    /** @prop {Number|String} offset=0\n     * The offset value as described in the modifier description\n     */\n    offset: 0\n  },\n\n  /**\n   * Modifier used to prevent the popper from being positioned outside the boundary.\n   *\n   * An scenario exists where the reference itself is not within the boundaries.<br />\n   * We can say it has \"escaped the boundaries\" — or just \"escaped\".<br />\n   * In this case we need to decide whether the popper should either:\n   *\n   * - detach from the reference and remain \"trapped\" in the boundaries, or\n   * - if it should ignore the boundary and \"escape with its reference\"\n   *\n   * When `escapeWithReference` is set to`true` and reference is completely\n   * outside its boundaries, the popper will overflow (or completely leave)\n   * the boundaries in order to remain attached to the edge of the reference.\n   *\n   * @memberof modifiers\n   * @inner\n   */\n  preventOverflow: {\n    /** @prop {number} order=300 - Index used to define the order of execution */\n    order: 300,\n    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n    enabled: true,\n    /** @prop {ModifierFn} */\n    fn: preventOverflow,\n    /**\n     * @prop {Array} [priority=['left','right','top','bottom']]\n     * Popper will try to prevent overflow following these priorities by default,\n     * then, it could overflow on the left and on top of the `boundariesElement`\n     */\n    priority: ['left', 'right', 'top', 'bottom'],\n    /**\n     * @prop {number} padding=5\n     * Amount of pixel used to define a minimum distance between the boundaries\n     * and the popper this makes sure the popper has always a little padding\n     * between the edges of its container\n     */\n    padding: 5,\n    /**\n     * @prop {String|HTMLElement} boundariesElement='scrollParent'\n     * Boundaries used by the modifier, can be `scrollParent`, `window`,\n     * `viewport` or any DOM element.\n     */\n    boundariesElement: 'scrollParent'\n  },\n\n  /**\n   * Modifier used to make sure the reference and its popper stay near eachothers\n   * without leaving any gap between the two. Expecially useful when the arrow is\n   * enabled and you want to assure it to point to its reference element.\n   * It cares only about the first axis, you can still have poppers with margin\n   * between the popper and its reference element.\n   * @memberof modifiers\n   * @inner\n   */\n  keepTogether: {\n    /** @prop {number} order=400 - Index used to define the order of execution */\n    order: 400,\n    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n    enabled: true,\n    /** @prop {ModifierFn} */\n    fn: keepTogether\n  },\n\n  /**\n   * This modifier is used to move the `arrowElement` of the popper to make\n   * sure it is positioned between the reference element and its popper element.\n   * It will read the outer size of the `arrowElement` node to detect how many\n   * pixels of conjuction are needed.\n   *\n   * It has no effect if no `arrowElement` is provided.\n   * @memberof modifiers\n   * @inner\n   */\n  arrow: {\n    /** @prop {number} order=500 - Index used to define the order of execution */\n    order: 500,\n    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n    enabled: true,\n    /** @prop {ModifierFn} */\n    fn: arrow,\n    /** @prop {String|HTMLElement} element='[x-arrow]' - Selector or node used as arrow */\n    element: '[x-arrow]'\n  },\n\n  /**\n   * Modifier used to flip the popper's placement when it starts to overlap its\n   * reference element.\n   *\n   * Requires the `preventOverflow` modifier before it in order to work.\n   *\n   * **NOTE:** this modifier will interrupt the current update cycle and will\n   * restart it if it detects the need to flip the placement.\n   * @memberof modifiers\n   * @inner\n   */\n  flip: {\n    /** @prop {number} order=600 - Index used to define the order of execution */\n    order: 600,\n    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n    enabled: true,\n    /** @prop {ModifierFn} */\n    fn: flip,\n    /**\n     * @prop {String|Array} behavior='flip'\n     * The behavior used to change the popper's placement. It can be one of\n     * `flip`, `clockwise`, `counterclockwise` or an array with a list of valid\n     * placements (with optional variations).\n     */\n    behavior: 'flip',\n    /**\n     * @prop {number} padding=5\n     * The popper will flip if it hits the edges of the `boundariesElement`\n     */\n    padding: 5,\n    /**\n     * @prop {String|HTMLElement} boundariesElement='viewport'\n     * The element which will define the boundaries of the popper position,\n     * the popper will never be placed outside of the defined boundaries\n     * (except if keepTogether is enabled)\n     */\n    boundariesElement: 'viewport'\n  },\n\n  /**\n   * Modifier used to make the popper flow toward the inner of the reference element.\n   * By default, when this modifier is disabled, the popper will be placed outside\n   * the reference element.\n   * @memberof modifiers\n   * @inner\n   */\n  inner: {\n    /** @prop {number} order=700 - Index used to define the order of execution */\n    order: 700,\n    /** @prop {Boolean} enabled=false - Whether the modifier is enabled or not */\n    enabled: false,\n    /** @prop {ModifierFn} */\n    fn: inner\n  },\n\n  /**\n   * Modifier used to hide the popper when its reference element is outside of the\n   * popper boundaries. It will set a `x-out-of-boundaries` attribute which can\n   * be used to hide with a CSS selector the popper when its reference is\n   * out of boundaries.\n   *\n   * Requires the `preventOverflow` modifier before it in order to work.\n   * @memberof modifiers\n   * @inner\n   */\n  hide: {\n    /** @prop {number} order=800 - Index used to define the order of execution */\n    order: 800,\n    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n    enabled: true,\n    /** @prop {ModifierFn} */\n    fn: hide\n  },\n\n  /**\n   * Computes the style that will be applied to the popper element to gets\n   * properly positioned.\n   *\n   * Note that this modifier will not touch the DOM, it just prepares the styles\n   * so that `applyStyle` modifier can apply it. This separation is useful\n   * in case you need to replace `applyStyle` with a custom implementation.\n   *\n   * This modifier has `850` as `order` value to maintain backward compatibility\n   * with previous versions of Popper.js. Expect the modifiers ordering method\n   * to change in future major versions of the library.\n   *\n   * @memberof modifiers\n   * @inner\n   */\n  computeStyle: {\n    /** @prop {number} order=850 - Index used to define the order of execution */\n    order: 850,\n    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n    enabled: true,\n    /** @prop {ModifierFn} */\n    fn: computeStyle,\n    /**\n     * @prop {Boolean} gpuAcceleration=true\n     * If true, it uses the CSS 3d transformation to position the popper.\n     * Otherwise, it will use the `top` and `left` properties.\n     */\n    gpuAcceleration: true,\n    /**\n     * @prop {string} [x='bottom']\n     * Where to anchor the X axis (`bottom` or `top`). AKA X offset origin.\n     * Change this if your popper should grow in a direction different from `bottom`\n     */\n    x: 'bottom',\n    /**\n     * @prop {string} [x='left']\n     * Where to anchor the Y axis (`left` or `right`). AKA Y offset origin.\n     * Change this if your popper should grow in a direction different from `right`\n     */\n    y: 'right'\n  },\n\n  /**\n   * Applies the computed styles to the popper element.\n   *\n   * All the DOM manipulations are limited to this modifier. This is useful in case\n   * you want to integrate Popper.js inside a framework or view library and you\n   * want to delegate all the DOM manipulations to it.\n   *\n   * Note that if you disable this modifier, you must make sure the popper element\n   * has its position set to `absolute` before Popper.js can do its work!\n   *\n   * Just disable this modifier and define you own to achieve the desired effect.\n   *\n   * @memberof modifiers\n   * @inner\n   */\n  applyStyle: {\n    /** @prop {number} order=900 - Index used to define the order of execution */\n    order: 900,\n    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n    enabled: true,\n    /** @prop {ModifierFn} */\n    fn: applyStyle,\n    /** @prop {Function} */\n    onLoad: applyStyleOnLoad,\n    /**\n     * @deprecated since version 1.10.0, the property moved to `computeStyle` modifier\n     * @prop {Boolean} gpuAcceleration=true\n     * If true, it uses the CSS 3d transformation to position the popper.\n     * Otherwise, it will use the `top` and `left` properties.\n     */\n    gpuAcceleration: undefined\n  }\n};\n\n/**\n * The `dataObject` is an object containing all the informations used by Popper.js\n * this object get passed to modifiers and to the `onCreate` and `onUpdate` callbacks.\n * @name dataObject\n * @property {Object} data.instance The Popper.js instance\n * @property {String} data.placement Placement applied to popper\n * @property {String} data.originalPlacement Placement originally defined on init\n * @property {Boolean} data.flipped True if popper has been flipped by flip modifier\n * @property {Boolean} data.hide True if the reference element is out of boundaries, useful to know when to hide the popper.\n * @property {HTMLElement} data.arrowElement Node used as arrow by arrow modifier\n * @property {Object} data.styles Any CSS property defined here will be applied to the popper, it expects the JavaScript nomenclature (eg. `marginBottom`)\n * @property {Object} data.arrowStyles Any CSS property defined here will be applied to the popper arrow, it expects the JavaScript nomenclature (eg. `marginBottom`)\n * @property {Object} data.boundaries Offsets of the popper boundaries\n * @property {Object} data.offsets The measurements of popper, reference and arrow elements.\n * @property {Object} data.offsets.popper `top`, `left`, `width`, `height` values\n * @property {Object} data.offsets.reference `top`, `left`, `width`, `height` values\n * @property {Object} data.offsets.arrow] `top` and `left` offsets, only one of them will be different from 0\n */\n\n/**\n * Default options provided to Popper.js constructor.<br />\n * These can be overriden using the `options` argument of Popper.js.<br />\n * To override an option, simply pass as 3rd argument an object with the same\n * structure of this object, example:\n * ```\n * new Popper(ref, pop, {\n *   modifiers: {\n *     preventOverflow: { enabled: false }\n *   }\n * })\n * ```\n * @type {Object}\n * @static\n * @memberof Popper\n */\nvar Defaults = {\n  /**\n   * Popper's placement\n   * @prop {Popper.placements} placement='bottom'\n   */\n  placement: 'bottom',\n\n  /**\n   * Whether events (resize, scroll) are initially enabled\n   * @prop {Boolean} eventsEnabled=true\n   */\n  eventsEnabled: true,\n\n  /**\n   * Set to true if you want to automatically remove the popper when\n   * you call the `destroy` method.\n   * @prop {Boolean} removeOnDestroy=false\n   */\n  removeOnDestroy: false,\n\n  /**\n   * Callback called when the popper is created.<br />\n   * By default, is set to no-op.<br />\n   * Access Popper.js instance with `data.instance`.\n   * @prop {onCreate}\n   */\n  onCreate: function onCreate() {},\n\n  /**\n   * Callback called when the popper is updated, this callback is not called\n   * on the initialization/creation of the popper, but only on subsequent\n   * updates.<br />\n   * By default, is set to no-op.<br />\n   * Access Popper.js instance with `data.instance`.\n   * @prop {onUpdate}\n   */\n  onUpdate: function onUpdate() {},\n\n  /**\n   * List of modifiers used to modify the offsets before they are applied to the popper.\n   * They provide most of the functionalities of Popper.js\n   * @prop {modifiers}\n   */\n  modifiers: modifiers\n};\n\n/**\n * @callback onCreate\n * @param {dataObject} data\n */\n\n/**\n * @callback onUpdate\n * @param {dataObject} data\n */\n\n// Utils\n// Methods\nvar Popper = function () {\n  /**\n   * Create a new Popper.js instance\n   * @class Popper\n   * @param {HTMLElement|referenceObject} reference - The reference element used to position the popper\n   * @param {HTMLElement} popper - The HTML element used as popper.\n   * @param {Object} options - Your custom options to override the ones defined in [Defaults](#defaults)\n   * @return {Object} instance - The generated Popper.js instance\n   */\n  function Popper(reference, popper) {\n    var _this = this;\n\n    var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};\n    classCallCheck(this, Popper);\n\n    this.scheduleUpdate = function () {\n      return requestAnimationFrame(_this.update);\n    };\n\n    // make update() debounced, so that it only runs at most once-per-tick\n    this.update = debounce(this.update.bind(this));\n\n    // with {} we create a new object with the options inside it\n    this.options = _extends({}, Popper.Defaults, options);\n\n    // init state\n    this.state = {\n      isDestroyed: false,\n      isCreated: false,\n      scrollParents: []\n    };\n\n    // get reference and popper elements (allow jQuery wrappers)\n    this.reference = reference && reference.jquery ? reference[0] : reference;\n    this.popper = popper && popper.jquery ? popper[0] : popper;\n\n    // Deep merge modifiers options\n    this.options.modifiers = {};\n    Object.keys(_extends({}, Popper.Defaults.modifiers, options.modifiers)).forEach(function (name) {\n      _this.options.modifiers[name] = _extends({}, Popper.Defaults.modifiers[name] || {}, options.modifiers ? options.modifiers[name] : {});\n    });\n\n    // Refactoring modifiers' list (Object => Array)\n    this.modifiers = Object.keys(this.options.modifiers).map(function (name) {\n      return _extends({\n        name: name\n      }, _this.options.modifiers[name]);\n    })\n    // sort the modifiers by order\n    .sort(function (a, b) {\n      return a.order - b.order;\n    });\n\n    // modifiers have the ability to execute arbitrary code when Popper.js get inited\n    // such code is executed in the same order of its modifier\n    // they could add new properties to their options configuration\n    // BE AWARE: don't add options to `options.modifiers.name` but to `modifierOptions`!\n    this.modifiers.forEach(function (modifierOptions) {\n      if (modifierOptions.enabled && isFunction(modifierOptions.onLoad)) {\n        modifierOptions.onLoad(_this.reference, _this.popper, _this.options, modifierOptions, _this.state);\n      }\n    });\n\n    // fire the first update to position the popper in the right place\n    this.update();\n\n    var eventsEnabled = this.options.eventsEnabled;\n    if (eventsEnabled) {\n      // setup event listeners, they will take care of update the position in specific situations\n      this.enableEventListeners();\n    }\n\n    this.state.eventsEnabled = eventsEnabled;\n  }\n\n  // We can't use class properties because they don't get listed in the\n  // class prototype and break stuff like Sinon stubs\n\n\n  createClass(Popper, [{\n    key: 'update',\n    value: function update$$1() {\n      return update.call(this);\n    }\n  }, {\n    key: 'destroy',\n    value: function destroy$$1() {\n      return destroy.call(this);\n    }\n  }, {\n    key: 'enableEventListeners',\n    value: function enableEventListeners$$1() {\n      return enableEventListeners.call(this);\n    }\n  }, {\n    key: 'disableEventListeners',\n    value: function disableEventListeners$$1() {\n      return disableEventListeners.call(this);\n    }\n\n    /**\n     * Schedule an update, it will run on the next UI update available\n     * @method scheduleUpdate\n     * @memberof Popper\n     */\n\n\n    /**\n     * Collection of utilities useful when writing custom modifiers.\n     * Starting from version 1.7, this method is available only if you\n     * include `popper-utils.js` before `popper.js`.\n     *\n     * **DEPRECATION**: This way to access PopperUtils is deprecated\n     * and will be removed in v2! Use the PopperUtils module directly instead.\n     * Due to the high instability of the methods contained in Utils, we can't\n     * guarantee them to follow semver. Use them at your own risk!\n     * @static\n     * @private\n     * @type {Object}\n     * @deprecated since version 1.8\n     * @member Utils\n     * @memberof Popper\n     */\n\n  }]);\n  return Popper;\n}();\n\n/**\n * The `referenceObject` is an object that provides an interface compatible with Popper.js\n * and lets you use it as replacement of a real DOM node.<br />\n * You can use this method to position a popper relatively to a set of coordinates\n * in case you don't have a DOM node to use as reference.\n *\n * ```\n * new Popper(referenceObject, popperNode);\n * ```\n *\n * NB: This feature isn't supported in Internet Explorer 10\n * @name referenceObject\n * @property {Function} data.getBoundingClientRect\n * A function that returns a set of coordinates compatible with the native `getBoundingClientRect` method.\n * @property {number} data.clientWidth\n * An ES6 getter that will return the width of the virtual reference element.\n * @property {number} data.clientHeight\n * An ES6 getter that will return the height of the virtual reference element.\n */\n\n\nPopper.Utils = (typeof window !== 'undefined' ? window : global).PopperUtils;\nPopper.placements = placements;\nPopper.Defaults = Defaults;\n\nreturn Popper;\n\n})));\n//# sourceMappingURL=popper.js.map\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/simple-line-icons/css/simple-line-icons.css",
    "content": "@font-face {\n  font-family: 'simple-line-icons';\n  src: url('../fonts/Simple-Line-Icons.eot?v=2.4.0');\n  src: url('../fonts/Simple-Line-Icons.eot?v=2.4.0#iefix') format('embedded-opentype'), url('../fonts/Simple-Line-Icons.woff2?v=2.4.0') format('woff2'), url('../fonts/Simple-Line-Icons.ttf?v=2.4.0') format('truetype'), url('../fonts/Simple-Line-Icons.woff?v=2.4.0') format('woff'), url('../fonts/Simple-Line-Icons.svg?v=2.4.0#simple-line-icons') format('svg');\n  font-weight: normal;\n  font-style: normal;\n}\n/*\n Use the following CSS code if you want to have a class per icon.\n Instead of a list of all class selectors, you can use the generic [class*=\"icon-\"] selector, but it's slower:\n*/\n.icon-user,\n.icon-people,\n.icon-user-female,\n.icon-user-follow,\n.icon-user-following,\n.icon-user-unfollow,\n.icon-login,\n.icon-logout,\n.icon-emotsmile,\n.icon-phone,\n.icon-call-end,\n.icon-call-in,\n.icon-call-out,\n.icon-map,\n.icon-location-pin,\n.icon-direction,\n.icon-directions,\n.icon-compass,\n.icon-layers,\n.icon-menu,\n.icon-list,\n.icon-options-vertical,\n.icon-options,\n.icon-arrow-down,\n.icon-arrow-left,\n.icon-arrow-right,\n.icon-arrow-up,\n.icon-arrow-up-circle,\n.icon-arrow-left-circle,\n.icon-arrow-right-circle,\n.icon-arrow-down-circle,\n.icon-check,\n.icon-clock,\n.icon-plus,\n.icon-minus,\n.icon-close,\n.icon-event,\n.icon-exclamation,\n.icon-organization,\n.icon-trophy,\n.icon-screen-smartphone,\n.icon-screen-desktop,\n.icon-plane,\n.icon-notebook,\n.icon-mustache,\n.icon-mouse,\n.icon-magnet,\n.icon-energy,\n.icon-disc,\n.icon-cursor,\n.icon-cursor-move,\n.icon-crop,\n.icon-chemistry,\n.icon-speedometer,\n.icon-shield,\n.icon-screen-tablet,\n.icon-magic-wand,\n.icon-hourglass,\n.icon-graduation,\n.icon-ghost,\n.icon-game-controller,\n.icon-fire,\n.icon-eyeglass,\n.icon-envelope-open,\n.icon-envelope-letter,\n.icon-bell,\n.icon-badge,\n.icon-anchor,\n.icon-wallet,\n.icon-vector,\n.icon-speech,\n.icon-puzzle,\n.icon-printer,\n.icon-present,\n.icon-playlist,\n.icon-pin,\n.icon-picture,\n.icon-handbag,\n.icon-globe-alt,\n.icon-globe,\n.icon-folder-alt,\n.icon-folder,\n.icon-film,\n.icon-feed,\n.icon-drop,\n.icon-drawer,\n.icon-docs,\n.icon-doc,\n.icon-diamond,\n.icon-cup,\n.icon-calculator,\n.icon-bubbles,\n.icon-briefcase,\n.icon-book-open,\n.icon-basket-loaded,\n.icon-basket,\n.icon-bag,\n.icon-action-undo,\n.icon-action-redo,\n.icon-wrench,\n.icon-umbrella,\n.icon-trash,\n.icon-tag,\n.icon-support,\n.icon-frame,\n.icon-size-fullscreen,\n.icon-size-actual,\n.icon-shuffle,\n.icon-share-alt,\n.icon-share,\n.icon-rocket,\n.icon-question,\n.icon-pie-chart,\n.icon-pencil,\n.icon-note,\n.icon-loop,\n.icon-home,\n.icon-grid,\n.icon-graph,\n.icon-microphone,\n.icon-music-tone-alt,\n.icon-music-tone,\n.icon-earphones-alt,\n.icon-earphones,\n.icon-equalizer,\n.icon-like,\n.icon-dislike,\n.icon-control-start,\n.icon-control-rewind,\n.icon-control-play,\n.icon-control-pause,\n.icon-control-forward,\n.icon-control-end,\n.icon-volume-1,\n.icon-volume-2,\n.icon-volume-off,\n.icon-calendar,\n.icon-bulb,\n.icon-chart,\n.icon-ban,\n.icon-bubble,\n.icon-camrecorder,\n.icon-camera,\n.icon-cloud-download,\n.icon-cloud-upload,\n.icon-envelope,\n.icon-eye,\n.icon-flag,\n.icon-heart,\n.icon-info,\n.icon-key,\n.icon-link,\n.icon-lock,\n.icon-lock-open,\n.icon-magnifier,\n.icon-magnifier-add,\n.icon-magnifier-remove,\n.icon-paper-clip,\n.icon-paper-plane,\n.icon-power,\n.icon-refresh,\n.icon-reload,\n.icon-settings,\n.icon-star,\n.icon-symbol-female,\n.icon-symbol-male,\n.icon-target,\n.icon-credit-card,\n.icon-paypal,\n.icon-social-tumblr,\n.icon-social-twitter,\n.icon-social-facebook,\n.icon-social-instagram,\n.icon-social-linkedin,\n.icon-social-pinterest,\n.icon-social-github,\n.icon-social-google,\n.icon-social-reddit,\n.icon-social-skype,\n.icon-social-dribbble,\n.icon-social-behance,\n.icon-social-foursqare,\n.icon-social-soundcloud,\n.icon-social-spotify,\n.icon-social-stumbleupon,\n.icon-social-youtube,\n.icon-social-dropbox,\n.icon-social-vkontakte,\n.icon-social-steam {\n  font-family: 'simple-line-icons';\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.icon-user:before {\n  content: \"\\e005\";\n}\n.icon-people:before {\n  content: \"\\e001\";\n}\n.icon-user-female:before {\n  content: \"\\e000\";\n}\n.icon-user-follow:before {\n  content: \"\\e002\";\n}\n.icon-user-following:before {\n  content: \"\\e003\";\n}\n.icon-user-unfollow:before {\n  content: \"\\e004\";\n}\n.icon-login:before {\n  content: \"\\e066\";\n}\n.icon-logout:before {\n  content: \"\\e065\";\n}\n.icon-emotsmile:before {\n  content: \"\\e021\";\n}\n.icon-phone:before {\n  content: \"\\e600\";\n}\n.icon-call-end:before {\n  content: \"\\e048\";\n}\n.icon-call-in:before {\n  content: \"\\e047\";\n}\n.icon-call-out:before {\n  content: \"\\e046\";\n}\n.icon-map:before {\n  content: \"\\e033\";\n}\n.icon-location-pin:before {\n  content: \"\\e096\";\n}\n.icon-direction:before {\n  content: \"\\e042\";\n}\n.icon-directions:before {\n  content: \"\\e041\";\n}\n.icon-compass:before {\n  content: \"\\e045\";\n}\n.icon-layers:before {\n  content: \"\\e034\";\n}\n.icon-menu:before {\n  content: \"\\e601\";\n}\n.icon-list:before {\n  content: \"\\e067\";\n}\n.icon-options-vertical:before {\n  content: \"\\e602\";\n}\n.icon-options:before {\n  content: \"\\e603\";\n}\n.icon-arrow-down:before {\n  content: \"\\e604\";\n}\n.icon-arrow-left:before {\n  content: \"\\e605\";\n}\n.icon-arrow-right:before {\n  content: \"\\e606\";\n}\n.icon-arrow-up:before {\n  content: \"\\e607\";\n}\n.icon-arrow-up-circle:before {\n  content: \"\\e078\";\n}\n.icon-arrow-left-circle:before {\n  content: \"\\e07a\";\n}\n.icon-arrow-right-circle:before {\n  content: \"\\e079\";\n}\n.icon-arrow-down-circle:before {\n  content: \"\\e07b\";\n}\n.icon-check:before {\n  content: \"\\e080\";\n}\n.icon-clock:before {\n  content: \"\\e081\";\n}\n.icon-plus:before {\n  content: \"\\e095\";\n}\n.icon-minus:before {\n  content: \"\\e615\";\n}\n.icon-close:before {\n  content: \"\\e082\";\n}\n.icon-event:before {\n  content: \"\\e619\";\n}\n.icon-exclamation:before {\n  content: \"\\e617\";\n}\n.icon-organization:before {\n  content: \"\\e616\";\n}\n.icon-trophy:before {\n  content: \"\\e006\";\n}\n.icon-screen-smartphone:before {\n  content: \"\\e010\";\n}\n.icon-screen-desktop:before {\n  content: \"\\e011\";\n}\n.icon-plane:before {\n  content: \"\\e012\";\n}\n.icon-notebook:before {\n  content: \"\\e013\";\n}\n.icon-mustache:before {\n  content: \"\\e014\";\n}\n.icon-mouse:before {\n  content: \"\\e015\";\n}\n.icon-magnet:before {\n  content: \"\\e016\";\n}\n.icon-energy:before {\n  content: \"\\e020\";\n}\n.icon-disc:before {\n  content: \"\\e022\";\n}\n.icon-cursor:before {\n  content: \"\\e06e\";\n}\n.icon-cursor-move:before {\n  content: \"\\e023\";\n}\n.icon-crop:before {\n  content: \"\\e024\";\n}\n.icon-chemistry:before {\n  content: \"\\e026\";\n}\n.icon-speedometer:before {\n  content: \"\\e007\";\n}\n.icon-shield:before {\n  content: \"\\e00e\";\n}\n.icon-screen-tablet:before {\n  content: \"\\e00f\";\n}\n.icon-magic-wand:before {\n  content: \"\\e017\";\n}\n.icon-hourglass:before {\n  content: \"\\e018\";\n}\n.icon-graduation:before {\n  content: \"\\e019\";\n}\n.icon-ghost:before {\n  content: \"\\e01a\";\n}\n.icon-game-controller:before {\n  content: \"\\e01b\";\n}\n.icon-fire:before {\n  content: \"\\e01c\";\n}\n.icon-eyeglass:before {\n  content: \"\\e01d\";\n}\n.icon-envelope-open:before {\n  content: \"\\e01e\";\n}\n.icon-envelope-letter:before {\n  content: \"\\e01f\";\n}\n.icon-bell:before {\n  content: \"\\e027\";\n}\n.icon-badge:before {\n  content: \"\\e028\";\n}\n.icon-anchor:before {\n  content: \"\\e029\";\n}\n.icon-wallet:before {\n  content: \"\\e02a\";\n}\n.icon-vector:before {\n  content: \"\\e02b\";\n}\n.icon-speech:before {\n  content: \"\\e02c\";\n}\n.icon-puzzle:before {\n  content: \"\\e02d\";\n}\n.icon-printer:before {\n  content: \"\\e02e\";\n}\n.icon-present:before {\n  content: \"\\e02f\";\n}\n.icon-playlist:before {\n  content: \"\\e030\";\n}\n.icon-pin:before {\n  content: \"\\e031\";\n}\n.icon-picture:before {\n  content: \"\\e032\";\n}\n.icon-handbag:before {\n  content: \"\\e035\";\n}\n.icon-globe-alt:before {\n  content: \"\\e036\";\n}\n.icon-globe:before {\n  content: \"\\e037\";\n}\n.icon-folder-alt:before {\n  content: \"\\e039\";\n}\n.icon-folder:before {\n  content: \"\\e089\";\n}\n.icon-film:before {\n  content: \"\\e03a\";\n}\n.icon-feed:before {\n  content: \"\\e03b\";\n}\n.icon-drop:before {\n  content: \"\\e03e\";\n}\n.icon-drawer:before {\n  content: \"\\e03f\";\n}\n.icon-docs:before {\n  content: \"\\e040\";\n}\n.icon-doc:before {\n  content: \"\\e085\";\n}\n.icon-diamond:before {\n  content: \"\\e043\";\n}\n.icon-cup:before {\n  content: \"\\e044\";\n}\n.icon-calculator:before {\n  content: \"\\e049\";\n}\n.icon-bubbles:before {\n  content: \"\\e04a\";\n}\n.icon-briefcase:before {\n  content: \"\\e04b\";\n}\n.icon-book-open:before {\n  content: \"\\e04c\";\n}\n.icon-basket-loaded:before {\n  content: \"\\e04d\";\n}\n.icon-basket:before {\n  content: \"\\e04e\";\n}\n.icon-bag:before {\n  content: \"\\e04f\";\n}\n.icon-action-undo:before {\n  content: \"\\e050\";\n}\n.icon-action-redo:before {\n  content: \"\\e051\";\n}\n.icon-wrench:before {\n  content: \"\\e052\";\n}\n.icon-umbrella:before {\n  content: \"\\e053\";\n}\n.icon-trash:before {\n  content: \"\\e054\";\n}\n.icon-tag:before {\n  content: \"\\e055\";\n}\n.icon-support:before {\n  content: \"\\e056\";\n}\n.icon-frame:before {\n  content: \"\\e038\";\n}\n.icon-size-fullscreen:before {\n  content: \"\\e057\";\n}\n.icon-size-actual:before {\n  content: \"\\e058\";\n}\n.icon-shuffle:before {\n  content: \"\\e059\";\n}\n.icon-share-alt:before {\n  content: \"\\e05a\";\n}\n.icon-share:before {\n  content: \"\\e05b\";\n}\n.icon-rocket:before {\n  content: \"\\e05c\";\n}\n.icon-question:before {\n  content: \"\\e05d\";\n}\n.icon-pie-chart:before {\n  content: \"\\e05e\";\n}\n.icon-pencil:before {\n  content: \"\\e05f\";\n}\n.icon-note:before {\n  content: \"\\e060\";\n}\n.icon-loop:before {\n  content: \"\\e064\";\n}\n.icon-home:before {\n  content: \"\\e069\";\n}\n.icon-grid:before {\n  content: \"\\e06a\";\n}\n.icon-graph:before {\n  content: \"\\e06b\";\n}\n.icon-microphone:before {\n  content: \"\\e063\";\n}\n.icon-music-tone-alt:before {\n  content: \"\\e061\";\n}\n.icon-music-tone:before {\n  content: \"\\e062\";\n}\n.icon-earphones-alt:before {\n  content: \"\\e03c\";\n}\n.icon-earphones:before {\n  content: \"\\e03d\";\n}\n.icon-equalizer:before {\n  content: \"\\e06c\";\n}\n.icon-like:before {\n  content: \"\\e068\";\n}\n.icon-dislike:before {\n  content: \"\\e06d\";\n}\n.icon-control-start:before {\n  content: \"\\e06f\";\n}\n.icon-control-rewind:before {\n  content: \"\\e070\";\n}\n.icon-control-play:before {\n  content: \"\\e071\";\n}\n.icon-control-pause:before {\n  content: \"\\e072\";\n}\n.icon-control-forward:before {\n  content: \"\\e073\";\n}\n.icon-control-end:before {\n  content: \"\\e074\";\n}\n.icon-volume-1:before {\n  content: \"\\e09f\";\n}\n.icon-volume-2:before {\n  content: \"\\e0a0\";\n}\n.icon-volume-off:before {\n  content: \"\\e0a1\";\n}\n.icon-calendar:before {\n  content: \"\\e075\";\n}\n.icon-bulb:before {\n  content: \"\\e076\";\n}\n.icon-chart:before {\n  content: \"\\e077\";\n}\n.icon-ban:before {\n  content: \"\\e07c\";\n}\n.icon-bubble:before {\n  content: \"\\e07d\";\n}\n.icon-camrecorder:before {\n  content: \"\\e07e\";\n}\n.icon-camera:before {\n  content: \"\\e07f\";\n}\n.icon-cloud-download:before {\n  content: \"\\e083\";\n}\n.icon-cloud-upload:before {\n  content: \"\\e084\";\n}\n.icon-envelope:before {\n  content: \"\\e086\";\n}\n.icon-eye:before {\n  content: \"\\e087\";\n}\n.icon-flag:before {\n  content: \"\\e088\";\n}\n.icon-heart:before {\n  content: \"\\e08a\";\n}\n.icon-info:before {\n  content: \"\\e08b\";\n}\n.icon-key:before {\n  content: \"\\e08c\";\n}\n.icon-link:before {\n  content: \"\\e08d\";\n}\n.icon-lock:before {\n  content: \"\\e08e\";\n}\n.icon-lock-open:before {\n  content: \"\\e08f\";\n}\n.icon-magnifier:before {\n  content: \"\\e090\";\n}\n.icon-magnifier-add:before {\n  content: \"\\e091\";\n}\n.icon-magnifier-remove:before {\n  content: \"\\e092\";\n}\n.icon-paper-clip:before {\n  content: \"\\e093\";\n}\n.icon-paper-plane:before {\n  content: \"\\e094\";\n}\n.icon-power:before {\n  content: \"\\e097\";\n}\n.icon-refresh:before {\n  content: \"\\e098\";\n}\n.icon-reload:before {\n  content: \"\\e099\";\n}\n.icon-settings:before {\n  content: \"\\e09a\";\n}\n.icon-star:before {\n  content: \"\\e09b\";\n}\n.icon-symbol-female:before {\n  content: \"\\e09c\";\n}\n.icon-symbol-male:before {\n  content: \"\\e09d\";\n}\n.icon-target:before {\n  content: \"\\e09e\";\n}\n.icon-credit-card:before {\n  content: \"\\e025\";\n}\n.icon-paypal:before {\n  content: \"\\e608\";\n}\n.icon-social-tumblr:before {\n  content: \"\\e00a\";\n}\n.icon-social-twitter:before {\n  content: \"\\e009\";\n}\n.icon-social-facebook:before {\n  content: \"\\e00b\";\n}\n.icon-social-instagram:before {\n  content: \"\\e609\";\n}\n.icon-social-linkedin:before {\n  content: \"\\e60a\";\n}\n.icon-social-pinterest:before {\n  content: \"\\e60b\";\n}\n.icon-social-github:before {\n  content: \"\\e60c\";\n}\n.icon-social-google:before {\n  content: \"\\e60d\";\n}\n.icon-social-reddit:before {\n  content: \"\\e60e\";\n}\n.icon-social-skype:before {\n  content: \"\\e60f\";\n}\n.icon-social-dribbble:before {\n  content: \"\\e00d\";\n}\n.icon-social-behance:before {\n  content: \"\\e610\";\n}\n.icon-social-foursqare:before {\n  content: \"\\e611\";\n}\n.icon-social-soundcloud:before {\n  content: \"\\e612\";\n}\n.icon-social-spotify:before {\n  content: \"\\e613\";\n}\n.icon-social-stumbleupon:before {\n  content: \"\\e614\";\n}\n.icon-social-youtube:before {\n  content: \"\\e008\";\n}\n.icon-social-dropbox:before {\n  content: \"\\e00c\";\n}\n.icon-social-vkontakte:before {\n  content: \"\\e618\";\n}\n.icon-social-steam:before {\n  content: \"\\e620\";\n}\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/skin/css/admin.css",
    "content": "/** EasyWeb */\nhtml {\n    background-color: #f2f2f2;\n    color: #666;\n}\n\n/** header样式 */\n/** 导航栏下面的线条 */\n.layui-layout-admin .layui-header .layui-nav .layui-this:after, .layui-layout-admin .layui-header .layui-nav-bar {\n    height: 2px;\n    background-color: #03152A;\n    top: 0 !important;\n}\n\n.layui-layout-admin .layui-header .layui-nav .layui-nav-item {\n    line-height: 50px; /** 高度重写 */\n}\n\n.layui-layout-admin .layui-header .layui-nav .layui-nav-item .layui-nav-child {\n    top: 55px;\n}\n\n.layui-layout-admin .layui-header .layui-nav-item .layui-icon {\n    font-size: 16px; /** 图标大小 */\n}\n\n.layui-layout-admin .layui-header .layui-layout-left {\n    left: 220px;\n    padding: 0 10px;\n    transition: all .3s;\n}\n\n.layui-layout-admin .layui-header .layui-layout-right {\n    padding: 0;\n}\n\n/** 重写header的背景色和字体颜色 */\n.layui-layout-admin .layui-header {\n    background-color: #fff;\n    height: 50px;\n    box-shadow: 0 1px 4px 0 rgba(0, 21, 41, .08);\n}\n\n.layui-layout-admin .layui-header a {\n    color: #333;\n    padding: 0 15px;\n}\n\n.layui-layout-admin .layui-header a:hover {\n    color: #333;\n}\n\n.layui-layout-admin .layui-header .layui-nav-child a {\n    color: #333 !important;\n}\n\n.layui-layout-admin .layui-header .layui-nav .layui-nav-more {\n    border-color: #666 transparent transparent;\n}\n\n.layui-layout-admin .layui-header .layui-nav .layui-nav-mored {\n    border-color: transparent transparent #666;\n}\n\n/** logo部分样式 */\n.layui-layout-admin .layui-header .layui-logo {\n    width: 220px;\n    background-color: #001529;\n    box-shadow: 0 1px 2px 0 rgba(0, 0, 0, .15);\n    color: #eee;\n    font-size: 16px;\n    font-family: Myriad Pro, Helvetica Neue, Arial, Helvetica, sans-serif;\n    font-weight: 300;\n    overflow: hidden;\n    line-height: 50px;\n    transition: all .3s;\n}\n\n.layui-layout-admin .layui-header .layui-logo img {\n    height: 40px;\n}\n\n.layui-layout-admin .layui-header .layui-logo cite {\n    font-style: normal;\n}\n\n.layui-layout-admin .layui-header .layui-nav-img {\n    margin-right: 5px;\n}\n\n.layui-layout-admin .layui-header .layui-nav-img + cite {\n    margin-right: 5px;\n}\n\n.layui-layout-admin .layui-header .layui-nav-child dd {\n    text-align: center;\n}\n\n.layui-layout-admin .layui-header a {\n    cursor: pointer;\n}\n\n/** //header样式结束 */\n\n/** 侧边栏样式 */\n.layui-layout-admin .layui-side .layui-side-scroll {\n    width: 240px;\n}\n\n.layui-layout-admin .layui-side {\n    top: 50px;\n    width: 220px;\n    background-color: #001529;\n    transition: all .3s;\n    -webkit-transition: all .3s;\n}\n\n.layui-layout-admin .layui-side .layui-nav {\n    width: 220px;\n    background-color: transparent;\n}\n\n.layui-layout-admin .layui-side .layui-nav .layui-nav-item > a:hover {\n    background: transparent;\n}\n\n.layui-layout-admin .layui-side .layui-nav .layui-nav-item > .layui-nav-child {\n    padding: 5px 0;\n    background-color: rgba(0, 0, 0, .3) !important;\n}\n\n.layui-layout-admin .layui-side .layui-nav .layui-nav-more {\n    right: 15px;\n}\n\n.layui-layout-admin .layui-side .layui-nav .layui-nav-item .layui-nav-child a {\n    padding-left: 50px; /** 导航字体位置 */\n}\n\n.layui-layout-admin .layui-side .layui-nav .layui-nav-item > a {\n    padding-top: 8px;\n    padding-bottom: 8px;\n}\n\n/** 侧边栏样式结束 */\n\n/** 主体部分样式 */\n.layui-layout-admin .layui-body {\n    left: 220px;\n    top: 50px;\n    transition: left .3s;\n    /*overflow-y: scroll;*/\n    /*padding: 15px;*/\n}\n\n/** //主体部分样式结束 */\n\n/** 底部样式 */\n.layui-layout-admin .layui-footer {\n    left: 220px;\n    background: #fff;\n    transition: all .3s;\n}\n\n/** 底部样式结束 */\n\n/** 侧导航折叠样式PC */\n.layui-layout-admin.admin-nav-mini .layui-header .layui-logo {\n    width: 60px;\n}\n\n.layui-layout-admin.admin-nav-mini .layui-header .layui-logo cite {\n    display: none;\n}\n\n.layui-layout-admin.admin-nav-mini .layui-header .layui-layout-left {\n    left: 60px;\n}\n\n.layui-layout-admin.admin-nav-mini .layui-side {\n    width: 60px;\n}\n\n.layui-layout-admin.admin-nav-mini .layui-side .layui-nav {\n    width: 60px;\n}\n\n.layui-layout-admin.admin-nav-mini .layui-side-scroll {\n    width: 80px;\n}\n\n/** 侧导航隐藏文字 */\n.layui-layout-admin.admin-nav-mini .layui-side .layui-nav .layui-nav-item > a > cite {\n    display: none;\n}\n\n.layui-layout-admin.admin-nav-mini .layui-side .layui-nav .layui-nav-item > a .layui-nav-more {\n    display: none;\n}\n\n.layui-layout-admin.admin-nav-mini .layui-side .layui-nav .layui-nav-item > a {\n    overflow: visible;\n}\n\n.layui-layout-admin.admin-nav-mini .layui-side .layui-nav .layui-nav-itemed .layui-nav-child {\n    display: none;\n}\n\n.layui-layout-admin.admin-nav-mini .layui-body {\n    left: 60px;\n}\n\n.layui-layout-admin.admin-nav-mini .layui-footer {\n    left: 60px;\n}\n\n.layui-layout-admin.admin-nav-mini .layui-side .layui-nav .layui-nav-itemed > a {\n    background: rgba(0, 0, 0, .3);\n}\n\n/** 修改折叠的图标 */\n.layui-layout-admin.admin-nav-mini .layui-header .layui-icon-shrink-right:before {\n    content: \"\\e66b\";\n}\n\n/** //侧导航折叠样式结束 */\n\n/** 移动设备样式 */\n@media screen and (max-width: 750px) {\n    .layui-layout-admin .layui-side {\n        position: fixed;\n        left: -260px;\n        z-index: 10000;\n    }\n\n    .layui-layout-admin .layui-body {\n        left: 0;\n    }\n\n    .layui-layout-admin .layui-footer {\n        left: 0;\n    }\n\n    .layui-layout-admin .layui-header .layui-logo {\n        left: -260px;\n    }\n\n    .layui-layout-admin .layui-header .layui-layout-left {\n        left: 0;\n    }\n\n    .layui-layout-admin .layui-header .layui-icon-shrink-right:before {\n        content: \"\\e66b\";\n    }\n\n    /* 移动设备侧导航折叠样式 */\n    .layui-layout-admin.admin-nav-mini .layui-header .layui-logo {\n        width: 220px;\n        left: 0;\n        z-index: 10001;\n    }\n\n    .layui-layout-admin.admin-nav-mini .layui-header {\n        z-index: auto;\n    }\n\n    .layui-layout-admin.admin-nav-mini .layui-header .layui-logo cite {\n        display: inline-block;\n    }\n\n    .layui-layout-admin.admin-nav-mini .layui-header .layui-layout-left {\n        left: 0;\n    }\n\n    .layui-layout-admin.admin-nav-mini .layui-side {\n        width: 220px;\n        left: 0;\n    }\n\n    .layui-layout-admin.admin-nav-mini .layui-side .layui-nav {\n        width: 220px;\n    }\n\n    .layui-layout-admin.admin-nav-mini .layui-side-scroll {\n        width: 240px;\n    }\n\n    .layui-layout-admin.admin-nav-mini .layui-side .layui-nav .layui-nav-item > a > cite {\n        display: inline-block;\n    }\n\n    .layui-layout-admin.admin-nav-mini .layui-side .layui-nav .layui-nav-item > a .layui-nav-more {\n        display: inline-block;\n    }\n\n    .layui-layout-admin.admin-nav-mini .layui-side .layui-nav .layui-nav-item > a {\n        overflow: hidden;\n    }\n\n    .layui-layout-admin.admin-nav-mini .layui-side .layui-nav .layui-nav-itemed .layui-nav-child {\n        display: block;\n    }\n\n    .layui-layout-admin.admin-nav-mini .layui-body {\n        left: 0;\n    }\n\n    .layui-layout-admin.admin-nav-mini .layui-footer {\n        left: 0;\n    }\n\n    /** 移动设备遮罩层 */\n    .layui-layout-admin.admin-nav-mini .site-mobile-shade {\n        content: '';\n        position: fixed;\n        top: 0;\n        bottom: 0;\n        left: 0;\n        right: 0;\n        background-color: rgba(0, 0, 0, .2);\n        z-index: 9999;\n        cursor: pointer;\n    }\n\n    .layui-layout-admin.admin-nav-mini .layui-side .layui-nav .layui-nav-itemed > a {\n        background: transparent;\n    }\n\n    .layui-layout-admin.admin-nav-mini .layui-header .layui-icon-shrink-right:before {\n        content: \"\\e668\";\n    }\n}\n\n/** //移动设备样式结束 */\n\n/** 右侧弹窗样式 */\n.layui-layer.layui-layer-adminRight {\n    top: 50px !important;\n    bottom: 0;\n    box-shadow: 1px 1px 10px rgba(0, 0, 0, .1);\n    border-radius: 0;\n    overflow: auto;\n}\n\n/** 消息列表样式 */\n.message-list {\n}\n\n.message-list-item {\n    padding: 10px 24px;\n    border-bottom: 1px solid #e8e8e8;\n    -ms-flex-align: start;\n    align-items: flex-start;\n    display: flex;\n    -ms-flex: 1 1;\n    flex: 1 1;\n}\n\n.message-list-item:hover {\n    background: #F2F2F2;\n}\n\n.message-item-icon {\n    width: 40px;\n    height: 40px;\n    margin-right: 16px;\n    display: block;\n    margin-top: 4px;\n}\n\n.message-item-right {\n    display: block;\n    flex: 1 0;\n}\n\n.message-item-title {\n    font-size: 14px;\n    color: rgba(0, 0, 0, .65);\n}\n\n.message-item-text {\n    color: rgba(0, 0, 0, .45);\n    font-size: 12px;\n}\n\n/** //消息列表样式结束 */\n\n/** 主体部分标题样式 */\n.layui-card-header .header-title {\n    display: inline;\n    font-size: 16px;\n}\n\n/** 表格搜索框样式 */\n.search-input {\n    width: 150px;\n    display: inline-block;\n    height: 36px;\n    vertical-align: middle;\n    padding: 3px 6px;\n}\n\n/** 重写layui默认按钮的高度，因为按钮跟输入框不一样高特别丑 */\n.layui-btn:not(.layui-btn-lg ):not(.layui-btn-sm):not(.layui-btn-xs) {\n    height: 34px;\n    line-height: 34px;\n}\n\n/** 如果按钮加图标减少内边距 */\n.icon-btn {\n    padding: 0 8px;\n}\n\n.layui-form.toolbar .layui-btn + .layui-btn {\n    margin-left: 15px;\n}\n\n.model-form-footer .layui-btn + .layui-btn {\n    margin-left: 15px;\n}\n\n.layui-table-cell .layui-btn + .layui-btn {\n    margin-left: 5px;\n}\n\n/** 表格上方工具栏样式 */\n.layui-form.toolbar {\n    color: #333;\n}\n\n.layui-form.toolbar .layui-form-select input {\n    height: 35px;\n    line-height: 35px;\n    width: 150px;\n    overflow: hidden;\n}\n\n.layui-form.toolbar .layui-form-select {\n    display: inline-block;\n}\n\n/* 表单弹窗样式 */\n.model-form {\n    padding-top: 30px;\n    padding-right: 45px;\n}\n\n.model-form-footer {\n    text-align: right;\n}\n\n/** dialog超出显示 */\n.layui-layout-body .layui-layer-page .layui-layer-content {\n    overflow: visible;\n}\n\n/* layui文档官网右侧弹窗目录列表的样式 */\n.site-dir li {\n    line-height: 26px;\n    margin-left: 20px;\n    overflow: visible;\n    list-style-type: disc;\n}\n\n/** laydate加图标 */\n.date-icon {\n    background-image: url(../images/icon_date.png);\n    background-repeat: no-repeat;\n    background-position: right center;\n}\n\n/** 辅助样式 */\n.layui-link {\n    color: #029789 !important;\n}\n\n.layui-link:hover {\n    opacity: .8;\n}\n\n.pull-right {\n    float: right;\n}\n\n.inline-block {\n    display: inline-block;\n}\n\n/** 卡片header里面的徽章样式调整 */\n.layui-card .layui-card-header .layui-badge.pull-right {\n    top: 50%;\n    margin-top: -9px;\n}\n\n/** 特大字体 */\n.lay-big-font {\n    font-size: 36px;\n    color: #666;\n    line-height: 36px;\n    padding: 5px 0 10px;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    word-break: break-all;\n    white-space: nowrap;\n}\n\n/** 超链接样式 */\n.layui-text a:not(.layui-btn) {\n    color: #01AAED;\n}\n\n.layui-text a:not(.layui-btn):hover {\n    text-decoration: underline;\n}\n\n/** loading组件样式 */\n.admin-loading {\n    position: absolute;\n    left: 50%;\n    top: 50%;\n    margin: -16px -15px;\n    font-size: 30px;\n    color: #c2c2c2\n}\n\n/** admin选项卡样式 */\n/** 调整header阴影 */\n.layui-layout-admin.open-tab .layui-header {\n    box-shadow: 0 1px 1px 0 rgba(0, 21, 41, .05);\n}\n\n.layui-layout-admin.open-tab .layui-body {\n    padding: 0;\n    overflow: hidden;\n}\n\n.layui-layout-admin .layui-body .layui-tab {\n    margin: 0;\n    overflow: hidden;\n}\n\n/** 开启选项卡后让tab-content样式为以前的layui-body样式 */\n.layui-layout-admin .layui-body .layui-tab .layui-tab-content .layui-tab-item {\n    position: absolute;\n    bottom: 0;\n    overflow-y: scroll;\n    padding: 15px;\n    right: 0;\n    top: 40px;\n    left: 0;\n}\n\n/** 选项卡标题样式 */\n.layui-layout-admin .layui-body .layui-tab .layui-tab-title {\n    height: 40px;\n    line-height: 40px;\n    padding: 0 80px 0 40px;\n    background-color: #fff;\n    box-shadow: 0 1px 2px 0 rgba(0, 0, 0, .1);\n    position: absolute;\n    right: 0;\n    z-index: 999;\n    border: none;\n    overflow: hidden;\n}\n\n.layui-layout-admin .layui-body .layui-tab .layui-tab-title li {\n    min-width: 0;\n    line-height: 40px;\n    max-width: 160px;\n    text-overflow: ellipsis;\n    overflow: hidden;\n    border-right: 1px solid #f6f6f6;\n    vertical-align: top;\n}\n\n.layui-layout-admin .layui-body .layui-tab .layui-tab-title .layui-tab-bar {\n    display: none;\n}\n\n.layui-layout-admin .layui-body .layui-tab .layui-tab-title li.layui-this,\n.layui-layout-admin .layui-body .layui-tab .layui-tab-title li:hover {\n    background-color: #333;\n}\n\n.layui-layout-admin .layui-body .layui-tab .layui-tab-title li.layui-this:after {\n    width: 100%;\n    border: none;\n    height: 2px;\n    background-color: #292B34;\n    border-radius: 0;\n}\n\n/** tab关闭按钮样式 */\n.layui-layout-admin .layui-body .layui-tab .layui-tab-title li .layui-tab-close {\n    width: 16px;\n    height: 16px;\n    line-height: 16px;\n    border-radius: 50%;\n    font-size: 12px;\n}\n\n.layui-layout-admin .layui-body .layui-tab .layui-tab-title li:first-child .layui-tab-close {\n    display: none; /** 第一个选项卡不可关闭 */\n}\n\n/** 选项卡其他操作按钮样式 */\n.layui-layout-admin .layui-body .admin-tabs-control {\n    position: absolute;\n    top: 0;\n    width: 40px;\n    height: 40px;\n    line-height: 40px;\n    text-align: center;\n    cursor: pointer;\n    transition: all .3s;\n    box-sizing: border-box;\n    border-left: 1px solid #f6f6f6;\n    z-index: 1000;\n    visibility: hidden; /** 默认隐藏 */\n    background-color: white;\n}\n\n.layui-layout-admin.open-tab .layui-body .admin-tabs-control {\n    visibility: visible;\n}\n\n.layui-layout-admin .layui-body .admin-tabs-control:hover {\n    background-color: #f6f6f6\n}\n\n.layui-layout-admin .layui-body .layui-icon-prev {\n    left: 0;\n    border-left: none;\n    border-right: 1px solid #f6f6f6;\n}\n\n.layui-layout-admin .layui-body .layui-icon-next {\n    right: 40px;\n}\n\n.layui-layout-admin .layui-body .layui-icon-down {\n    right: 0;\n}\n\n.admin-tabs-select.layui-nav {\n    position: absolute;\n    left: 0;\n    top: 0;\n    width: 100%;\n    height: 100%;\n    padding: 0;\n    background: 0 0;\n}\n\n.admin-tabs-select.layui-nav .layui-nav-item {\n    line-height: 40px\n}\n\n.admin-tabs-select.layui-nav .layui-nav-item > a {\n    height: 40px\n}\n\n.admin-tabs-select.layui-nav .layui-nav-item a {\n    color: #666\n}\n\n.admin-tabs-select.layui-nav .layui-nav-child {\n    top: 40px;\n    left: auto;\n    right: 0\n}\n\n.admin-tabs-select.layui-nav .layui-nav-child dd.layui-this,\n.admin-tabs-select.layui-nav .layui-nav-child dd.layui-this a {\n    background-color: #f2f2f2 !important;\n    color: #333\n}\n\n.admin-tabs-select.layui-nav .layui-nav-bar, .admin-tabs-select.layui-nav .layui-nav-more {\n    display: none;\n}\n\n.layui-fluid {\n    padding: 15px;\n}\n\nbody.layui-fluid {\n    overflow-y: scroll;\n}\n\n.admin-iframe {\n    width: 100%;\n    height: 100%;\n}\n\n.layui-layout-admin .layui-body.admin-iframe-body {\n    padding: 0;\n    overflow: hidden;\n}\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/skin/css/console.css",
    "content": "/** 卡片轮播图样式 */\n.admin-carousel .layui-carousel-ind {\n    position: absolute;\n    top: -41px;\n    text-align: right;\n}\n\n.admin-carousel .layui-carousel-ind ul {\n    background: 0 0;\n}\n\n.admin-carousel .layui-carousel-ind li {\n    background-color: #e2e2e2;\n}\n\n.admin-carousel .layui-carousel-ind li.layui-this {\n    background-color: #999;\n}\n\n/** 广告位轮播图 */\n.admin-news .layui-carousel-ind {\n    height: 45px;\n}\n\n.admin-news a {\n    display: block;\n    line-height: 60px;\n    text-align: center;\n}\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/lib/skin/css/login.css",
    "content": "/** EasyWeb */\n\nbody {\n    background-image: url(\"../images/bg_login.png\");\n    background-repeat: no-repeat;\n    background-size: cover;\n}\n\n.login-wrapper, body, html {\n    height: 100%\n}\n\n.login-wrapper {\n    overflow: auto;\n    position: absolute;\n    top: 0;\n    bottom: 0;\n    left: 0;\n    right: 0;\n}\n\n.login-body {\n    padding: 10px 10px 40px 10px;\n}\n\n.login-body > .layui-card {\n    max-width: 360px;\n    margin: 0 auto;\n}\n\n.login-body .layui-card-header {\n    font-weight: 700;\n    font-size: 15px;\n}\n\n.login-body .layui-form-pane .layui-form-label {\n    width: 48px;\n}\n\n.login-body .layui-form-pane .layui-input-block {\n    margin-left: 48px;\n}\n\n.login-body .login-captcha {\n    width: 100%;\n    cursor: pointer;\n}\n\n.login-body .login-other > * {\n    display: inline-block;\n    vertical-align: middle;\n    margin-right: 10px;\n    font-size: 14px;\n}\n\n.login-body .login-other .layui-icon {\n    position: relative;\n    top: 2px;\n    font-size: 26px;\n}\n\n.login-body .login-other a:hover {\n    opacity: .8;\n}\n\n.layui-icon-login-qq {\n    color: #3492ED\n}\n\n.layui-icon-login-wechat {\n    color: #4DAF29\n}\n\n.layui-icon-login-weibo {\n    color: #CF1900\n}\n\n/** 底部样式 */\n.login-footer {\n    text-align: center;\n    line-height: 30px;\n    color: rgba(255, 255, 255, 0.7) !important;\n    padding-bottom: 20px;\n}\n\n.login-footer span {\n    padding: 0 5px\n}\n\n.login-footer a {\n    padding: 0 5px;\n    color: rgba(255, 255, 255, 0.7) !important;\n}\n\n.login-footer a:hover {\n    color: rgba(255, 255, 255, 0.4) !important;\n}\n\n/** 头部样式 */\n.login-header {\n    font-size: 20px;\n    font-weight: bold;\n    color: rgba(255, 255, 255, 0.85) !important;\n    padding: 10px;\n}\n\n.login-header img {\n    height: 40px;\n}\n\n/** 移动设备样式 */\n@media screen and (min-height: 590px) {\n    .login-footer {\n        position: absolute;\n        bottom: 0;\n        width: 100%;\n    }\n}\n\n@media screen and (min-height: 670px) {\n    .login-body {\n        padding: 110px 10px 40px 10px;\n    }\n}\n\n/** 辅助样式 */\n.layui-link {\n    color: #029789 !important;\n}\n\n.layui-link:hover {\n    opacity: .8;\n}\n\n.pull-right {\n    float: right;\n}\n\n.inline-block {\n    display: inline-block;\n}"
  },
  {
    "path": "open-layui-web/src/main/view/static/login.html",
    "content": "<!doctype html>\n<html class=\"no-js\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n\t<meta name=\"description\" content=\"\">\n\t<meta name=\"keywords\" content=\"\">\n\t<meta name=\"viewport\"\n\t\t  content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no\">\n\t<title>OCP</title>\n\t<meta name=\"renderer\" content=\"webkit\">\n\t<meta http-equiv=\"Cache-Control\" content=\"no-siteapp\"/>\n\t<link rel=\"stylesheet\" href=\"assets/css/amazeui.min.css\">\n\t<link rel=\"stylesheet\" href=\"assets/css/app.css\">\n</head>\n<body>\n<div class=\"am-g myapp-login\">\n\t<div class=\"myapp-login-logo-block\">\n\t\t<div class=\"myapp-login-logo\">\n\t\t\t<i class=\"am-icon-jsfiddle\"></i>\n\t\t</div>\n\t\t<div class=\"myapp-login-logo-text\">\n\t\t\t<div class=\"myapp-login-logo-text\">\n\t\t\t\tOCP<span>后台管理系统</span>\n\t\t\t\t<div class=\"info\">Find the best places in town.</div>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<div class=\"am-u-sm-10 login-am-center\">\n\t\t\t<form class=\"am-form\">\n\t\t\t\t<fieldset>\n\t\t\t\t\t<div class=\"am-form-group\">\n\t\t\t\t\t\t<input type=\"text\" class=\"\" id=\"username\" name=\"username\" placeholder=\"用户名\">\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div class=\"am-form-group\">\n\t\t\t\t\t\t<input type=\"password\" class=\"\"  id=\"password\" name=\"password\" placeholder=\"密码\">\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"am-form-group\">\n\t\t\t\t\t\t<span id=\"info\" style=\"color: red\"></span>\n\t\t\t\t\t</div>\n\t\t\t\t\t<p><button type=\"submit\" class=\"am-btn am-btn-default\" onclick=\"login(this)\">登录</button></p>\n\t\t\t\t</fieldset>\n\t\t\t</form>\n\t\t</div>\n\n\t\t<div class=\"login-font\">\n\t\t\t<script src='//gitee.com/owenwangwen/open-capacity-platform/widget_preview'></script>\n\t\t</div>\n\t</div>\n</div>\n\n\n\n\n<!--[if (gte IE 9)|!(IE)]><!-->\n<script src=\"assets/js/jquery.min.js\"></script>\n<!--<![endif]-->\n<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n\n<script src=\"assets/js/login.js\"></script>\n\n<script type=\"text/javascript\">\n    if (top != self) {\n        parent.location.href = '/login.html';\n    }\n\n    var token = localStorage.getItem(\"token\");\n    if (token != null && token.trim().length != 0) {\n        $.ajax({\n            type : 'get',\n            url : '/users/current?token=' + token,\n            success : function(data) {\n                location.href = '/index.html';\n            },\n            error : function(xhr, textStatus, errorThrown) {\n                var msg = xhr.responseText;\n                var response = JSON.parse(msg);\n                var code = response.code;\n                var message = response.message;\n                if (code == 401) {\n                    localStorage.removeItem(\"token\");\n                }\n            }\n        });\n    }\n\n    function login(obj) {\n        $(obj).attr(\"disabled\", true);\n\n        var username = $.trim($('#username').val());\n        var password = $.trim($('#password').val());\n        if (username == \"\" || password == \"\") {\n            $(\"#info\").html('用户名或者密码不能为空');\n            $(obj).attr(\"disabled\", false);\n        } else {\n            $.ajax({\n                type : 'post',\n                url : '/login',\n                data : \"username=\" + username +\"&password=\"+password,\n                success : function(data) {\n                    localStorage.setItem(\"token\", data.token);\n                    location.href = '/index.html';\n                },\n                error : function(xhr, textStatus, errorThrown) {\n                    var msg = xhr.responseText;\n                    var response = JSON.parse(msg);\n                    $(\"#info\").html(response.message);\n                    $(obj).attr(\"disabled\", false);\n                }\n            });\n\n        }\n    }\n</script>\n\n<script src=\"assets/js/amazeui.min.js\"></script>\n\n\n\n</body>\n</html>"
  },
  {
    "path": "open-layui-web/src/main/view/static/login.html.bak",
    "content": "<!doctype html>\n<html class=\"no-js\">\n<head>\n  <meta charset=\"utf-8\">\n  <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n  <meta name=\"description\" content=\"\">\n  <meta name=\"keywords\" content=\"\">\n  <meta name=\"viewport\"\n        content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no\">\n  <title>OCP</title>\n  <meta name=\"renderer\" content=\"webkit\">\n  <meta http-equiv=\"Cache-Control\" content=\"no-siteapp\"/>\n  <link rel=\"stylesheet\" href=\"assets/css/amazeui.min.css\">\n  <link rel=\"stylesheet\" href=\"assets/css/app.css\">\n  <style type=\"text/css\">\n  \tbody{\n\t    background:url(../img/login/bg.png) no-repeat center;\n\t    background-size: cover;\n\t}\n  \n  </style>\n</head>\n<body>\n<div class=\"am-g myapp-login\">\n\t<div class=\"myapp-login-logo-block\">\n\t\t<div class=\"myapp-login-logo\">\n\t\t\t<i class=\"am-icon-jsfiddle\"></i>\n\t\t</div>\n\t\t<div class=\"myapp-login-logo-text\">\n\t\t\t<div class=\"myapp-login-logo-text\">\n\t\t\t\tOCP<span>后台管理系统</span>\n\t\t\t\t<div class=\"info\">Find the best places in town.</div>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<div class=\"am-u-sm-10 login-am-center\">\n\t\t\t<form class=\"am-form\">\n\t\t\t\t<fieldset>\n\t\t\t\t\t<div class=\"am-form-group\">\n\t\t\t\t\t\t<input type=\"text\" class=\"\" id=\"username\" name=\"username\" placeholder=\"用户名\">\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div class=\"am-form-group\">\n\t\t\t\t\t\t<input type=\"password\" class=\"\"  id=\"password\" name=\"password\" placeholder=\"密码\">\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"am-form-group\">\n                                    <span id=\"info\" style=\"color: red\"></span>\n                    </div>\n\t\t\t\t\t<p><button type=\"submit\" class=\"am-btn am-btn-default\" onclick=\"login(this)\">登录</button></p>\n\t\t\t\t</fieldset>\n\t\t\t</form>\n\t\t</div>\n\t\t\n\t\t<div class=\"login-font\">\n\t\t\t  <script src='//gitee.com/owenwangwen/open-capacity-platform/widget_preview'></script>\n\t\t</div>\n\t</div>\n</div>\n\n<!--[if (gte IE 9)|!(IE)]><!-->\n<script src=\"assets/js/jquery.min.js\"></script>\n<!--<![endif]-->\n<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n<script type=\"text/javascript\">\n\tif (top != self) {\n\t\tparent.location.href = '/login.html';\n\t}\n\t\n\tvar token = localStorage.getItem(\"token\");\n\tif (token != null && token.trim().length != 0) {\n\t\t$.ajax({\n\t\t\ttype : 'get',\n\t\t\turl : '/users/current?token=' + token,\n\t\t\tsuccess : function(data) {\n\t\t\t\tlocation.href = '/index.html';\n\t\t\t},\n\t\t\terror : function(xhr, textStatus, errorThrown) {\n\t\t\t\tvar msg = xhr.responseText;\n\t\t\t\tvar response = JSON.parse(msg);\n\t\t\t\tvar code = response.code;\n\t\t\t\tvar message = response.message;\n\t\t\t\tif (code == 401) {\n\t\t\t\t\tlocalStorage.removeItem(\"token\");\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\tfunction login(obj) {\n\t\t$(obj).attr(\"disabled\", true);\n\n\t\tvar username = $.trim($('#username').val());\n\t\tvar password = $.trim($('#password').val());\n\t\tif (username == \"\" || password == \"\") {\n\t\t\t$(\"#info\").html('用户名或者密码不能为空');\n\t\t\t$(obj).attr(\"disabled\", false);\n\t\t} else {\n\t\t\t$.ajax({\n\t\t\t\ttype : 'post',\n\t\t\t\turl : '/login',\n\t\t\t\tdata : \"username=\" + username +\"&password=\"+password,\n\t\t\t\tsuccess : function(data) {\n\t\t\t\t\tlocalStorage.setItem(\"token\", data.token);\n\t\t\t\t\tlocation.href = '/index.html';\n\t\t\t\t},\n\t\t\t\terror : function(xhr, textStatus, errorThrown) {\n\t\t\t\t\tvar msg = xhr.responseText;\n\t\t\t\t\tvar response = JSON.parse(msg);\n\t\t\t\t\t$(\"#info\").html(response.message);\n\t\t\t\t\t$(obj).attr(\"disabled\", false);\n\t\t\t\t}\n\t\t\t});\n\n\t\t}\n\t}\n</script>\n\n<script src=\"assets/js/amazeui.min.js\"></script>\n\n\n\n</body>\n</html>"
  },
  {
    "path": "open-layui-web/src/main/view/static/login.html.bak1",
    "content": "<!doctype html>\n<html class=\"no-js\">\n<head>\n  <meta charset=\"utf-8\">\n  <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n  <meta name=\"description\" content=\"\">\n  <meta name=\"keywords\" content=\"\">\n  <meta name=\"viewport\"\n        content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no\">\n  <title>OCP</title>\n  <meta name=\"renderer\" content=\"webkit\">\n  <meta http-equiv=\"Cache-Control\" content=\"no-siteapp\"/>\n  <link rel=\"stylesheet\" href=\"assets/css/amazeui.min.css\">\n  <link rel=\"stylesheet\" href=\"assets/css/app.css\">\n  <style type=\"text/css\">\n  \tbody{\n\t    background:url(../img/login/bg.png) no-repeat center;\n\t    background-size: cover;\n\t}\n  \n  </style>\n</head>\n<body>\n<div class=\"am-g myapp-login\">\n\t<div class=\"myapp-login-logo-block\">\n\t\t<div class=\"myapp-login-logo\">\n\t\t\t<i class=\"am-icon-jsfiddle\"></i>\n\t\t</div>\n\t\t<div class=\"myapp-login-logo-text\">\n\t\t\t<div class=\"myapp-login-logo-text\">\n\t\t\t\tOCP<span>后台管理系统</span>\n\t\t\t\t<div class=\"info\">Find the best places in town.</div>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<div class=\"am-u-sm-10 login-am-center\">\n\t\t\t<form class=\"am-form\">\n\t\t\t\t<fieldset>\n\t\t\t\t\t<div class=\"am-form-group\">\n\t\t\t\t\t\t<input type=\"text\" class=\"\" id=\"username\" name=\"username\" placeholder=\"用户名\">\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div class=\"am-form-group\">\n\t\t\t\t\t\t<input type=\"password\" class=\"\"  id=\"password\" name=\"password\" placeholder=\"密码\">\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"am-form-group\">\n                                    <span id=\"info\" style=\"color: red\"></span>\n                    </div>\n\t\t\t\t\t<p><button type=\"submit\" class=\"am-btn am-btn-default\" onclick=\"login(this)\">登录</button></p>\n\t\t\t\t</fieldset>\n\t\t\t</form>\n\t\t</div>\n\t\t\n\t\t<div class=\"login-font\">\n\t\t\t  <script src='//gitee.com/owenwangwen/open-capacity-platform/widget_preview'></script>\n\t\t</div>\n\t</div>\n</div>\n\n<!--[if (gte IE 9)|!(IE)]><!-->\n<script src=\"assets/js/jquery.min.js\"></script>\n<!--<![endif]-->\n<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n<script type=\"text/javascript\">\n\tif (top != self) {\n\t\tparent.location.href = '/login.html';\n\t}\n\t\n\tvar token = localStorage.getItem(\"token\");\n\tif (token != null && token.trim().length != 0) {\n\t\t$.ajax({\n\t\t\ttype : 'get',\n\t\t\turl : '/users/current?token=' + token,\n\t\t\tsuccess : function(data) {\n\t\t\t\tlocation.href = '/index.html';\n\t\t\t},\n\t\t\terror : function(xhr, textStatus, errorThrown) {\n\t\t\t\tvar msg = xhr.responseText;\n\t\t\t\tvar response = JSON.parse(msg);\n\t\t\t\tvar code = response.code;\n\t\t\t\tvar message = response.message;\n\t\t\t\tif (code == 401) {\n\t\t\t\t\tlocalStorage.removeItem(\"token\");\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\tfunction login(obj) {\n\t\t$(obj).attr(\"disabled\", true);\n\n\t\tvar username = $.trim($('#username').val());\n\t\tvar password = $.trim($('#password').val());\n\t\tif (username == \"\" || password == \"\") {\n\t\t\t$(\"#info\").html('用户名或者密码不能为空');\n\t\t\t$(obj).attr(\"disabled\", false);\n\t\t} else {\n\t\t\t$.ajax({\n\t\t\t\ttype : 'post',\n\t\t\t\turl : '/login',\n\t\t\t\tdata : \"username=\" + username +\"&password=\"+password,\n\t\t\t\tsuccess : function(data) {\n\t\t\t\t\tlocalStorage.setItem(\"token\", data.token);\n\t\t\t\t\tlocation.href = '/index.html';\n\t\t\t\t},\n\t\t\t\terror : function(xhr, textStatus, errorThrown) {\n\t\t\t\t\tvar msg = xhr.responseText;\n\t\t\t\t\tvar response = JSON.parse(msg);\n\t\t\t\t\t$(\"#info\").html(response.message);\n\t\t\t\t\t$(obj).attr(\"disabled\", false);\n\t\t\t\t}\n\t\t\t});\n\n\t\t}\n\t}\n</script>\n\n<script src=\"assets/js/amazeui.min.js\"></script>\n\n\n\n</body>\n</html>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/actList.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"UTF-8\">\n  <title>流程部署</title>\n  <meta name=\"renderer\" content=\"webkit\">\n  <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">\n  <meta name=\"viewport\"\n        content=\"width=device-width,user-scalable=yes, minimum-scale=0.4, initial-scale=0.8,target-densitydpi=low-dpi\"/>\n  <link rel=\"stylesheet\" href=\"/lib/layui/css/layui.css\">\n\n\n\n    <script type=\"text/javascript\" src=\"/lib/layui/layui.all.js\" charset=\"utf-8\"></script>\n    <script type=\"text/javascript\" src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n    <script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n  <!--<link rel=\"stylesheet\" href=\"${re.contextPath}/plugin/lenos/main.css\">-->\n  <!--<script type=\"text/javascript\" src=\"${re.contextPath}/plugin/jquery/jquery-3.2.1.min.js\"></script>-->\n  <!--<script type=\"text/javascript\" src=\"${re.contextPath}/plugin/layui/layui.all.js\" charset=\"utf-8\"></script>-->\n  <!--<script type=\"text/javascript\" src=\"${re.contextPath}/plugin/tools/tool.js\" charset=\"utf-8\"></script>-->\n</head>\n\n<body style=\"background-color: #FFFFFF;overflow:hidden\">\n<div class=\"lenos-search\">\n  <div class=\"select\">\n    部署id：\n    <div class=\"layui-inline\">\n      <input class=\"layui-input\" height=\"20px\" id=\"deploymentId\" autocomplete=\"off\">\n    </div>\n    流程名称：\n    <div class=\"layui-inline\">\n      <input class=\"layui-input\" height=\"20px\" id=\"name\" autocomplete=\"off\">\n    </div>\n    <button class=\"select-on layui-btn layui-btn-sm\" data-type=\"select\"><i class=\"layui-icon\"></i>\n    </button>\n    <button class=\"layui-btn layui-btn-sm icon-position-button\" id=\"refresh\" style=\"float: right;\"\n            data-type=\"reload\">\n      <i class=\"layui-icon\">ဂ</i>\n    </button>\n  </div>\n</div>\n<div class=\"layui-col-md12\">\n    <div class=\"layui-btn-group\">\n      <button class=\"layui-btn layui-btn-normal\" id=\"processGroup\" data-type=\"assignee\">\n        <i class=\"layui-icon\">&#xe642;</i>节点处理人设置\n      </button>\n    </div>\n</div>\n\n<table id=\"actList\" class=\"layui-hide\" lay-filter=\"act\"></table>\n<script type=\"text/html\" id=\"toolBar\">\n  <a class=\"layui-btn layui-btn-danger layui-btn-xs\" lay-event=\"del\"><i class=\"layui-icon\">&#xe640;</i>删除</a>\n</script>\n<script>\n  layui.laytpl.toDateString = function(d, format){\n    var date = new Date(d || new Date())\n        ,ymd = [\n      this.digit(date.getFullYear(), 4)\n      ,this.digit(date.getMonth() + 1)\n      ,this.digit(date.getDate())\n    ]\n        ,hms = [\n      this.digit(date.getHours())\n      ,this.digit(date.getMinutes())\n      ,this.digit(date.getSeconds())\n    ];\n\n    format = format || 'yyyy-MM-dd HH:mm:ss';\n\n    return format.replace(/yyyy/g, ymd[0])\n    .replace(/MM/g, ymd[1])\n    .replace(/dd/g, ymd[2])\n    .replace(/HH/g, hms[0])\n    .replace(/mm/g, hms[1])\n    .replace(/ss/g, hms[2]);\n  };\n\n  //数字前置补零\n  layui.laytpl.digit = function(num, length, end){\n    var str = '';\n    num = String(num);\n    length = length || 2;\n    for(var i = num.length; i < length; i++){\n      str += '0';\n    }\n    return num < Math.pow(10, length) ? str + (num|0) : num;\n  };\n\n  document.onkeydown = function (e) { // 回车提交表单\n    var theEvent = window.event || e;\n    var code = theEvent.keyCode || theEvent.which;\n    if (code == 13) {\n      $(\".select .select-on\").click();\n    }\n  }\n\n  layui.use('table', function () {\n    var table = layui.table;\n    //方法级渲染\n    table.render({\n      id: 'actList',\n      elem: '#actList'\n      , url: '/activiti/showAct'\n      , where : { access_token : localStorage.getItem(\"token\") }\n      , cols: [[\n          {checkbox: true, fixed: true, width: '5%'}\n        , {field: 'id', title: '编号', width: '15%', sort: true}\n        , {field: 'name', title: '流程名称', width: '10%', sort: true}\n        , {field: 'key', title: 'key', width: '12%', sort: true}\n        , {field: 'deploymentId', title: '部署id', width: '5%', sort: true}\n        , {field: 'diagramResourceName', title: '流程图资源', width: '15%', sort: true}\n        , {field: 'category', title: '版本', width: '15%', sort: true}\n        , {field: 'resourceName', title: '资源名称', width: '10%', sort: true}\n        , {field: 'text', title: '操作', width: '10%', toolbar:'#toolBar'}\n      ]]\n      , page: true\n      ,  height: 'full-85'\n    });\n\n    var $ = layui.$, active = {\n      select: function () {\n        var deploymentId = $('#deploymentId').val();\n        var name = $('#name').val();\n        table.reload('actList', {\n          where: {\n            deploymentId: deploymentId,\n            name: name\n          }\n        });\n      }\n      ,assignee:function(){\n        var checkStatus = table.checkStatus('actList')\n            , data = checkStatus.data;\n        if (data.length !=1) {\n          layer.msg('请选择一个流程', {icon: 5});\n          return false;\n        }\n        assignee(data[0].deploymentId);\n      }\n      ,reload:function(){\n        $('#deploymentId').val('');\n        $('#name').val('');\n        table.reload('actList', {\n          where: {\n            deploymentId: null,\n            name: null\n          }\n        });\n      }\n    };\n    //监听工具条\n      table.on('tool(act)', function (obj) {\n      var data = obj.data;\n      if (obj.event === 'del') {\n        layer.confirm('将会删除正在执行的流程,确定删除？', {\n          btn: ['确定','取消'] //按钮\n        }, function(){\n          del(data.deploymentId);\n        }, function(){\n        });\n      }\n    });\n\n    $('.layui-col-md12 .layui-btn').on('click', function () {\n      var type = $(this).data('type');\n      active[type] ? active[type].call(this) : '';\n    });\n    $('.select .layui-btn').on('click', function () {\n      var type = $(this).data('type');\n      active[type] ? active[type].call(this) : '';\n    });\n\n  });\n  function del(id) {\n    $.ajax({\n      url: \"/activiti/delDeploy\",\n      type: \"post\",\n      data: {id: id},\n      dataType: \"json\", traditional: true,\n      success: function (d) {\n        if(d.flag){\n          layer.msg(d.msg, {icon: 6});\n          layui.table.reload('actList');\n        }else{\n          layer.msg(d.msg, {icon: 5});\n        }\n      }\n    });\n  }\n  /**\n   * 流程绑定节点\n   * @param id\n   */\n  function assignee(id){\n    var index =\n        layer.open({\n          id: 'assignee',\n          type: 2,\n          area: ['600px',  '350px'],\n          fix: false,\n          maxmin: true,\n          shadeClose: false,\n          shade: 0.4,\n          title: '设置流程节点',\n          content: '/activiti/goAssignee/'+id+\"?access_token=\"+ localStorage.getItem(\"token\")\n        });\n    layer.full(index);\n  }\n\n\n</script>\n</body>\n\n</html>\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/actModelList.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"UTF-8\">\n  <title>模型列表</title>\n  <meta name=\"renderer\" content=\"webkit\">\n  <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">\n  <meta name=\"viewport\"\n        content=\"width=device-width,user-scalable=yes, minimum-scale=0.4, initial-scale=0.8,target-densitydpi=low-dpi\"/>\n\n    <link rel=\"stylesheet\" href=\"/lib/layui/css/layui.css\">\n\n    <script type=\"text/javascript\" src=\"/lib/layui/layui.all.js\" charset=\"utf-8\"></script>\n    <script type=\"text/javascript\" src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n    <script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n\n</head>\n\n<body style=\"background-color: #FFFFFF;overflow:hidden\">\n<div class=\"lenos-search\">\n  <div class=\"select\">\n    模型名称：\n    <div class=\"layui-inline\">\n      <input class=\"layui-input\" height=\"20px\" id=\"name\" autocomplete=\"off\">\n    </div>\n    key：\n    <div class=\"layui-inline\">\n      <input class=\"layui-input\" height=\"20px\" id=\"key\" autocomplete=\"off\">\n    </div>\n    <button class=\"select-on layui-btn layui-btn-sm\" data-type=\"select\"><i class=\"layui-icon\"></i>\n    </button>\n    <button class=\"layui-btn layui-btn-sm icon-position-button\" id=\"refresh\" style=\"float: right;\"\n            data-type=\"reload\">\n      <i class=\"layui-icon\">ဂ</i>\n    </button>\n  </div>\n</div>\n<div class=\"layui-col-md12\">\n    <div class=\"layui-btn-group\">\n        <button class=\"layui-btn layui-btn-normal\" data-type=\"syncdata\">\n            <i class=\"layui-icon\">&#xe618;</i>同步数据\n        </button>\n      <button class=\"layui-btn layui-btn-normal\" id=\"processGroup\" data-type=\"add\">\n        <i class=\"layui-icon\">&#xe642;</i>新建流程\n      </button>\n    </div>\n  </button>\n</div>\n\n<table id=\"actModelList\" class=\"layui-hide\" lay-filter=\"act\"></table>\n<script type=\"text/html\" id=\"toolBar\">\n  <shiro.hasPermission name=\"control:del\">\n  <a class=\"layui-btn layui-btn-danger layui-btn-xs\" lay-event=\"update\"><i class=\"layui-icon\">&#xe640;</i>编辑</a>\n  <a class=\"layui-btn layui-btn-danger layui-btn-xs\" lay-event=\"open\"><i class=\"layui-icon\">&#xe640;</i>发布</a>\n  <a class=\"layui-btn layui-btn-danger layui-btn-xs\" lay-event=\"del\"><i class=\"layui-icon\">&#xe640;</i>删除</a>\n  </shiro.hasPermission>\n</script>\n<script>\n  layui.laytpl.toDateString = function(d, format){\n    var date = new Date(d || new Date())\n        ,ymd = [\n      this.digit(date.getFullYear(), 4)\n      ,this.digit(date.getMonth() + 1)\n      ,this.digit(date.getDate())\n    ]\n        ,hms = [\n      this.digit(date.getHours())\n      ,this.digit(date.getMinutes())\n      ,this.digit(date.getSeconds())\n    ];\n\n    format = format || 'yyyy-MM-dd HH:mm:ss';\n\n    return format.replace(/yyyy/g, ymd[0])\n    .replace(/MM/g, ymd[1])\n    .replace(/dd/g, ymd[2])\n    .replace(/HH/g, hms[0])\n    .replace(/mm/g, hms[1])\n    .replace(/ss/g, hms[2]);\n  };\n  $('#processGroup').on('mouseover',function(){\n    layer.tips('设置流程节点的代办人/候选人/候选组，目前只开发到组', this,{time:2000});\n  });\n  //数字前置补零\n  layui.laytpl.digit = function(num, length, end){\n    var str = '';\n    num = String(num);\n    length = length || 2;\n    for(var i = num.length; i < length; i++){\n      str += '0';\n    }\n    return num < Math.pow(10, length) ? str + (num|0) : num;\n  };\n\n  document.onkeydown = function (e) { // 回车提交表单\n    var theEvent = window.event || e;\n    var code = theEvent.keyCode || theEvent.which;\n    if (code == 13) {\n      $(\".select .select-on\").click();\n    }\n  }\n\n  layui.use('table', function () {\n    var table = layui.table;\n    //方法级渲染\n    table.render({\n      id: 'actModelList',\n      elem: '#actModelList'\n      , url: '/activiti/showAm'\n      , where : { access_token : localStorage.getItem(\"token\") }\n      , cols: [[\n          {checkbox: true, fixed: true, width: '5%'}\n        , {field: 'id', title: '编号', width: '10%', sort: true}\n        , {field: 'name', title: '流程名称', width: '10%', sort: true}\n        , {field: 'key', title: 'key', width: '10%', sort: true}\n        , {field: 'version', title: '版本', width: '10%', sort: true}\n        , {field: 'createTime', title: '创建时间', width: '20%',templet: '<div>{{ layui.laytpl.toDateString(d.createTime,\"yyyy-MM-dd HH:mm:ss\") }}</div>'}\n        , {field: 'text', title: '操作', width: '20%', toolbar:'#toolBar'}\n\n      ]]\n      , page: true\n      ,  height: 'full-85'\n    });\n\n    var $ = layui.$, active = {\n      select: function () {\n        var name = $('#name').val();\n        var key = $('#key').val();\n        table.reload('actModelList', {\n          where: {\n            name: name,\n            key: key\n          }\n        });\n      },\n     syncdata:function () {\n        syncdata();\n      }\n      ,reload:function(){\n       $('#name').val('');\n       $('#key').val('');\n        table.reload('actModelList', {\n          where: {\n            name: null,\n            key: null\n          }\n        });\n      },add:function(){\n        var index =layer.open({\n          id: 'act-add',\n          type: 2,\n          area: ['600px','350px'],\n          fix: false,\n          maxmin: true,\n          shadeClose: false,\n          shade: 0.4,\n          title: '添加流程',\n          content: '/activiti/goActiviti?access_token='+localStorage.getItem(\"token\")\n        });\n        layer.full(index);\n      }\n    };\n    //监听工具条\n    table.on('tool(act)', function (obj) {\n      var data = obj.data;\n      if (obj.event === 'open') {\n        open(data.id);\n      }else if(obj.event === 'update'){\n        var index =layer.open({\n              id: 'act-update',\n              type: 2,\n              area: ['600px','350px'],\n              fix: false,\n              maxmin: true,\n              shadeClose: false,\n              shade: 0.4,\n              title: '编辑流程',\n              content: '/activiti/actUpdate/'+data.id+\"?access_token=\"+localStorage.getItem(\"token\")\n            });\n        layer.full(index);\n      }else if(obj.event === 'del') {\n        layer.confirm('确定删除[' + data.name + ']？', {\n          btn: ['确定', '取消'] //按钮\n        }, function () {\n          del(data.id);\n        }, function () {\n        });\n      }\n    });\n\n    $('.layui-col-md12 .layui-btn').on('click', function () {\n      var type = $(this).data('type');\n      active[type] ? active[type].call(this) : '';\n    });\n    $('.select .layui-btn').on('click', function () {\n      var type = $(this).data('type');\n      active[type] ? active[type].call(this) : '';\n    });\n\n  });\n  function del(id) {\n    $.ajax({\n      url: \"/activiti/delModel\",\n      type: \"post\",\n      data: {id: id},\n      dataType: \"json\", traditional: true,\n      success: function (d) {\n        if(d.flag){\n          layer.msg(d.msg, {icon: 6});\n          layui.table.reload('actModelList');\n        }else{\n          layer.msg(d.msg, {icon: 5});\n        }\n      }\n    });\n  }\n  function syncdata() {\n    $.ajax({\n      url: \"/activiti/syncdata\",\n      type: \"post\",\n      dataType: \"json\", traditional: true,\n      success: function (data) {\n        layer.msg(data.msg, {icon: 6});\n        //layui.table.reload('actModeltList');\n      }\n    });\n  }\n  function open(id) {\n    $.ajax({\n      url: \"/activiti/open\",\n      type: \"post\",\n      data: {id: id},\n      dataType: \"json\", traditional: true,\n      success: function d(data) {\n        layer.msg(data.msg, {icon: 6});\n        layui.table.reload('actModelList');\n      }\n    });\n  }\n\n</script>\n</body>\n\n</html>\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/deploy/act-node.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\" xmlns:th=\"http://www.thymeleaf.org\">\n\n<head>\n  <meta charset=\"UTF-8\" />\n  <title>流程节点分配</title>\n  <meta name=\"renderer\" content=\"webkit\"/>\n  <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\"/>\n  <meta name=\"viewport\" content=\"width=device-width,user-scalable=yes, minimum-scale=0.4, initial-scale=0.8,target-densitydpi=low-dpi\" />\n  <!--<link rel=\"stylesheet\" href=\"/plugin/layui/css/layui.css\">-->\n  <!--<link rel=\"stylesheet\" href=\"/plugin/ztree/css/metroStyle/metroStyle.css\">-->\n  <!--<script type=\"text/javascript\" src=\"/plugin/jquery/jquery-3.2.1.min.js\"></script>-->\n  <!--<script type=\"text/javascript\" src=\"/plugin/layui/layui.all.js\" charset=\"utf-8\"></script>-->\n  <!--<script type=\"text/javascript\" src=\"/plugin/tools/tool.js\" charset=\"utf-8\"></script>-->\n\n  <link rel=\"stylesheet\" href=\"/lib/layui/css/layui.css\" />\n\n  <script type=\"text/javascript\" src=\"/lib/layui/layui.all.js\" charset=\"utf-8\"></script>\n  <script type=\"text/javascript\" src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n  <script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n\n\n</head>\n\n<body>\n<div class=\"x-body\">\n  <form class=\"layui-form layui-form-pane\" style=\"margin-left: 20px;\">\n    <div style=\"width:100%;height:400px;overflow: auto;\">\n\n      <div class=\"layui-tab\">\n        <ul class=\"layui-tab-title\">\n\n          <li th:each=\"act:${actList}\" th:text=\"${act.name}\" > <i class=\"layui-icon\">&#xe715;</i> </li>\n\n        <!--<#list actList as act>-->\n            <!--<li <#if act_index==0>class=\"layui-this\"</#if>><i class=\"layui-icon\">&#xe715;</i>${act.name}</li>-->\n        <!--</#list>-->\n\n        </ul>\n        <div class=\"layui-tab-content\">\n\n            <div th:each=\"act,actStat:${actList}\" class=\"layui-tab-item\">\n                <div style=\"display: none\" name=\"id\" th:text=\"${act.id}\" ></div>\n                <fieldset class=\"layui-elem-field layui-field-title\" style=\"margin-top: 10px;\">\n                <legend style=\"font-size:16px;\">分配角色</legend>\n                </fieldset>\n                <div class=\"layui-form-item\">\n                <div class=\"layui-input-block\" style=\"margin-left: 0px;\">\n                    <!--${act_index}_${json_index}_role_${act.id}_${act.name}-->\n                <input th:each=\"json,jsonStat:${act.boxJson}\"  type=\"checkbox\" name=\"${act_index}_${json_index}_role_${act.id}_${act.name}\"\n                       th:name=\" ${  '__${actStat.count}__'+'_'+'__${jsonStat.count}__'+'_role_'+ '__${act.id}__'+'_'+'__${act.name}__'}  \"\n                    th:title=\"${json.name}\" th:value=\"${json.id}\" lay-filter=\"check\" title=\"${json.name}\"  value=\"${json.id}\"  th:checked=\"${json.check}\" >\n\n                </div>\n                </div>\n                <fieldset class=\"layui-elem-field layui-field-title\" style=\"margin-top: 10px;\">\n                <legend style=\"font-size:16px;\">分配成员</legend>\n                </fieldset>\n                <div class=\"layui-form-item\">\n                    ------开发中------\n                </div>\n            </div>\n\n\n          <!--<#list actList as act>-->\n            <!--<div class=\"layui-tab-item <#if act_index==0>layui-show</#if>\">-->\n             <!--<div style=\"display: none\" name=\"id\">${act.id}</div>-->\n              <!--<fieldset class=\"layui-elem-field layui-field-title\" style=\"margin-top: 10px;\">-->\n                <!--<legend style=\"font-size:16px;\">分配角色</legend>-->\n              <!--</fieldset>-->\n                <!--<div class=\"layui-form-item\">-->\n                  <!--<div class=\"layui-input-block\" style=\"margin-left: 0px;\">-->\n                    <!--<#list act.boxJson as json>-->\n                      <!--<input type=\"checkbox\" name=\"${act_index}_${json_index}_role_${act.id}_${act.name}\"-->\n                             <!--title=\"${json.name}\" lay-filter=\"check\" value=\"${json.id}\" <#if json.check?string=='true'>checked</#if>>-->\n                    <!--</#list>-->\n                  <!--</div>-->\n                <!--</div>-->\n              <!--<fieldset class=\"layui-elem-field layui-field-title\" style=\"margin-top: 10px;\">-->\n                <!--<legend style=\"font-size:16px;\">分配成员</legend>-->\n              <!--</fieldset>-->\n              <!--<div class=\"layui-form-item\">-->\n                <!--开发中..ing-->\n              <!--</div>-->\n            <!--</div>-->\n          <!--</#list>-->\n\n        </div>\n      </div>\n  <div style=\"width: 100%;height: 55px;background-color: white;border-top:1px solid #e6e6e6;\n  position: fixed;bottom: 1px;margin-left:-20px;\">\n    <div class=\"layui-form-item\" style=\" float: right;margin-right: 30px;margin-top: 8px\">\n      <button  class=\"layui-btn layui-btn-normal\" lay-filter=\"add\" lay-submit>\n        确定\n      </button>\n      <button  class=\"layui-btn layui-btn-primary\"   data-type=\"close\">\n        取消\n      </button>\n    </div>\n  </div>\n    </div>\n  </form>\n</div>\n<script>\n  layui.use(['form','layer'], function(){\n    $ = layui.jquery;\n    var form = layui.form\n        ,layer = layui.layer;\n    var $ = layui.$, active = {\n      close: function () {\n        var index = parent.layer.getFrameIndex(window.name);\n        parent.layer.close(index);\n      }\n    };\n    $('.layui-form-item .layui-btn').on('click', function () {\n      var type = $(this).data('type');\n      active[type] ? active[type].call(this) : '';\n    });\n    //监听提交\n    form.on('submit(add)', function(data){\n      $.ajax({\n        url:'updateNode',\n        type:'post',\n        data:data.field,\n        success:function(d){\n            var index = parent.layer.getFrameIndex(window.name);\n            if(d.flag){\n              parent.layer.close(index);\n              window.parent.layui.table.reload('actList');\n              window.top.layer.msg(d.msg,{icon:6,offset: 'rb',area:['120px','80px'],anim:2});\n            }else{\n              layer.msg(d.msg,{icon:5});\n            }\n        },error:function(){\n          layer.alert(\"请求失败\", {icon: 6},function () {\n            var index = parent.layer.getFrameIndex(window.name);\n            parent.layer.close(index);\n          });\n        }\n      });\n      return false;\n    });\n    form.render();\n  });\n</script>\n</body>\n\n</html>\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/diagram-viewer/index.html",
    "content": "﻿<html>\n<head>\n  <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n  \n  <link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\" media=\"screen\">\n  <script src=\"js/jstools.js\" type=\"text/javascript\" charset=\"utf-8\"></script>\n  <script src=\"js/raphael.js\" type=\"text/javascript\" charset=\"utf-8\"></script>\n  \n  <script src=\"js/jquery/jquery.js\" type=\"text/javascript\" charset=\"utf-8\"></script>\n  <script src=\"js/jquery/jquery.progressbar.js\" type=\"text/javascript\" charset=\"utf-8\"></script>\n  <script src=\"js/jquery/jquery.asyncqueue.js\" type=\"text/javascript\" charset=\"utf-8\"></script>\n  \n  <script src=\"js/Color.js\" type=\"text/javascript\" charset=\"utf-8\"></script>\n  <script src=\"js/Polyline.js\" type=\"text/javascript\" charset=\"utf-8\"></script>\n  <script src=\"js/ActivityImpl.js\" type=\"text/javascript\" charset=\"utf-8\"></script>\n  <script src=\"js/ActivitiRest.js\" type=\"text/javascript\" charset=\"utf-8\"></script>\n  <script src=\"js/LineBreakMeasurer.js\" type=\"text/javascript\" charset=\"utf-8\"></script>\n  <script src=\"js/ProcessDiagramGenerator.js\" type=\"text/javascript\" charset=\"utf-8\"></script>\n  <script src=\"js/ProcessDiagramCanvas.js\" type=\"text/javascript\" charset=\"utf-8\"></script>\n  \n  <style type=\"text/css\" media=\"screen\">\n    \n  </style>\n</head>\n<body>\n<div class=\"wrapper\">\n  <div id=\"pb1\"></div>\n  <div id=\"overlayBox\" >\n    <div id=\"diagramBreadCrumbs\" class=\"diagramBreadCrumbs\" onmousedown=\"return false\" onselectstart=\"return false\"></div>\n    <div id=\"diagramHolder\" class=\"diagramHolder\"></div>\n    <div class=\"diagram-info\" id=\"diagramInfo\"></div>\n  </div>\n</div>\n<script language='javascript'>\nvar DiagramGenerator = {};\nvar pb1;\n$(document).ready(function(){\n  var query_string = {};\n  var query = window.location.search.substring(1);\n  var vars = query.split(\"&\");\n  for (var i=0;i<vars.length;i++) {\n    var pair = vars[i].split(\"=\");\n    query_string[pair[0]] = pair[1];\n  } \n  \n  var processDefinitionId = query_string[\"processDefinitionId\"];\n  var processInstanceId = query_string[\"processInstanceId\"];\n  \n  console.log(\"Initialize progress bar\");\n  \n  pb1 = new $.ProgressBar({\n    boundingBox: '#pb1',\n    label: 'Progressbar!',\n    on: {\n      complete: function() {\n        console.log(\"Progress Bar COMPLETE\");\n        this.set('label', 'complete!');\n        if (processInstanceId) {\n          ProcessDiagramGenerator.drawHighLights(processInstanceId);\n        }\n      },\n      valueChange: function(e) {\n        this.set('label', e.newVal + '%');\n      }\n    },\n    value: 0\n  });\n  console.log(\"Progress bar inited\");\n  \n  ProcessDiagramGenerator.options = {\n    diagramBreadCrumbsId: \"diagramBreadCrumbs\",\n    diagramHolderId: \"diagramHolder\",\n    diagramInfoId: \"diagramInfo\",\n    on: {\n      click: function(canvas, element, contextObject){\n        var mouseEvent = this;\n        console.log(\"[CLICK] mouseEvent: %o, canvas: %o, clicked element: %o, contextObject: %o\", mouseEvent, canvas, element, contextObject);\n\n        if (contextObject.getProperty(\"type\") == \"callActivity\") {\n          var processDefinitonKey = contextObject.getProperty(\"processDefinitonKey\");\n          var processDefinitons = contextObject.getProperty(\"processDefinitons\");\n          var processDefiniton = processDefinitons[0];\n          console.log(\"Load callActivity '\" + processDefiniton.processDefinitionKey + \"', contextObject: \", contextObject);\n\n          // Load processDefinition\n        ProcessDiagramGenerator.drawDiagram(processDefiniton.processDefinitionId);\n        }\n      },\n      rightClick: function(canvas, element, contextObject){\n        var mouseEvent = this;\n        console.log(\"[RIGHTCLICK] mouseEvent: %o, canvas: %o, clicked element: %o, contextObject: %o\", mouseEvent, canvas, element, contextObject);\n      },\n      over: function(canvas, element, contextObject){\n        var mouseEvent = this;\n        //console.log(\"[OVER] mouseEvent: %o, canvas: %o, clicked element: %o, contextObject: %o\", mouseEvent, canvas, element, contextObject);\n\n        // TODO: show tooltip-window with contextObject info\n        ProcessDiagramGenerator.showActivityInfo(contextObject);\n      },\n      out: function(canvas, element, contextObject){\n        var mouseEvent = this;\n        //console.log(\"[OUT] mouseEvent: %o, canvas: %o, clicked element: %o, contextObject: %o\", mouseEvent, canvas, element, contextObject);\n\n        ProcessDiagramGenerator.hideInfo();\n      }\n    }\n  };\n  \n  var baseUrl = window.document.location.protocol + \"//\" + window.document.location.host + \"/\";\n  var shortenedUrl = window.document.location.href.replace(baseUrl, \"\");\n  baseUrl = baseUrl + shortenedUrl.substring(0, shortenedUrl.indexOf(\"/\"));\n  \n  ActivitiRest.options = {\n    processInstanceHighLightsUrl: baseUrl + \"/service/process-instance/{processInstanceId}/highlights?callback=?\",\n    processDefinitionUrl: baseUrl + \"/service/process-definition/{processDefinitionId}/diagram-layout?callback=?\",\n    processDefinitionByKeyUrl: baseUrl + \"/service/process-definition/{processDefinitionKey}/diagram-layout?callback=?\"\n  };\n  \n  if (processDefinitionId) {\n    ProcessDiagramGenerator.drawDiagram(processDefinitionId);\n    \n  } else {\n    alert(\"processDefinitionId parameter is required\");\n  }\n});\n\n\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/diagram-viewer/js/ActivitiRest.js",
    "content": "var ActivitiRest = {\n\toptions: {},\n\tgetProcessDefinitionByKey: function(processDefinitionKey, callback) {\n\t\tvar url = Lang.sub(this.options.processDefinitionByKeyUrl, {processDefinitionKey: processDefinitionKey});\n\t\t\n\t\t$.ajax({\n\t\t\turl: url,\n\t\t\tdataType: 'jsonp',\n\t\t\tcache: false,\n\t\t\tasync: true,\n\t\t\tsuccess: function(data, textStatus) {\n\t\t\t\tvar processDefinition = data;\n\t\t\t\tif (!processDefinition) {\n\t\t\t\t\tconsole.error(\"Process definition '\" + processDefinitionKey + \"' not found\");\n\t\t\t\t} else {\n\t\t\t\t  callback.apply({processDefinitionId: processDefinition.id});\n\t\t\t\t}\n\t\t\t}\n\t\t}).done(function(data, textStatus) {\n\t\t\tconsole.log(\"ajax done\");\n\t\t}).fail(function(jqXHR, textStatus, error){\n\t\t\tconsole.error('Get diagram layout['+processDefinitionKey+'] failure: ', textStatus, 'error: ', error, jqXHR);\n\t\t});\n\t},\n\t\n\tgetProcessDefinition: function(processDefinitionId, callback) {\n\t\tvar url = Lang.sub(this.options.processDefinitionUrl, {processDefinitionId: processDefinitionId});\n\t\t\n\t\t$.ajax({\n\t\t\turl: url,\n\t\t\tdataType: 'jsonp',\n\t\t\tcache: false,\n\t\t\tasync: true,\n\t\t\tsuccess: function(data, textStatus) {\n\t\t\t\tvar processDefinitionDiagramLayout = data;\n\t\t\t\tif (!processDefinitionDiagramLayout) {\n\t\t\t\t\tconsole.error(\"Process definition diagram layout '\" + processDefinitionId + \"' not found\");\n\t\t\t\t\treturn;\n\t\t\t\t} else {\n\t\t\t\t\tcallback.apply({processDefinitionDiagramLayout: processDefinitionDiagramLayout});\n\t\t\t\t}\n\t\t\t}\n\t\t}).done(function(data, textStatus) {\n\t\t\tconsole.log(\"ajax done\");\n\t\t}).fail(function(jqXHR, textStatus, error){\n\t\t\tconsole.log('Get diagram layout['+processDefinitionId+'] failure: ', textStatus, jqXHR);\n\t\t});\n\t},\n\t\n\tgetHighLights: function(processInstanceId, callback) {\n\t\tvar url = Lang.sub(this.options.processInstanceHighLightsUrl, {processInstanceId: processInstanceId});\n\t\t\n\t\t$.ajax({\n\t\t\turl: url,\n\t\t\tdataType: 'jsonp',\n\t\t\tcache: false,\n\t\t\tasync: true,\n\t\t\tsuccess: function(data, textStatus) {\n\t\t\t\tconsole.log(\"ajax returned data\");\n\t\t\t\tvar highLights = data;\n\t\t\t\tif (!highLights) {\n\t\t\t\t\tconsole.log(\"highLights not found\");\n\t\t\t\t\treturn;\n\t\t\t\t} else {\n\t\t\t\t\tcallback.apply({highLights: highLights});\n\t\t\t\t}\n\t\t\t}\n\t\t}).done(function(data, textStatus) {\n\t\t\tconsole.log(\"ajax done\");\n\t\t}).fail(function(jqXHR, textStatus, error){\n\t\t  console.log('Get HighLights['+processInstanceId+'] failure: ', textStatus, jqXHR);\n\t\t});\n\t}\n};"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/diagram-viewer/js/ActivityImpl.js",
    "content": "/**\r * \r * @author Tom Baeyens\r * @author (Javascript) Dmitry Farafonov\r */\r \rvar ActivityImpl = function(activityJson){\r\tthis.outgoingTransitions = [];\r\tthis.outgoingTransitions = [];\r\tthis.incomingTransitions = [];\r\tthis.activityBehavior = null;\r\tthis.parent = null;\r\tthis.isScope = false;\r\tthis.isAsync = false;\r\tthis.isExclusive = false;\r\tthis.x = -1;\r\tthis.y = -1;\r\tthis.width = -1;\r\tthis.height = -1;\r\tthis.properties = {};\r\t\r\t//console.log(\"activityJson: \", activityJson);\r\t\r\tif (activityJson != undefined) {\r\t\tthis.setId(activityJson.activityId);\r\t\t\t\t\r\t\tfor (var propertyName in activityJson.properties) {\r\t\t\tthis.setProperty(propertyName, activityJson.properties[propertyName]);\r\t\t}\r\t\t//this.setProperty(\"name\", activityJson.activityName);\r\t\t//this.setProperty(\"type\", activityJson.activityType);\r\t\tthis.setX(activityJson.x);\r\t\tthis.setY(activityJson.y);\r\t\tthis.setWidth(activityJson.width);\r\t\tthis.setHeight(activityJson.height);\r\t\t\r\t\tif (activityJson.multiInstance)\r\t\t\tthis.setProperty(\"multiInstance\", activityJson.multiInstance);\r\t\tif (activityJson.collapsed) {\r\t\t\tthis.setProperty(\"collapsed\", activityJson.collapsed);\r\t\t}\r\t\tif (activityJson.isInterrupting != undefined)\r\t\t\tthis.setProperty(\"isInterrupting\", activityJson.isInterrupting);\r\t}\r};\r\rActivityImpl.prototype = {\r\toutgoingTransitions: [],\r\toutgoingTransitions: [],\r\tincomingTransitions: [],\r\tactivityBehavior: null,\r\tparent: null,\r\tisScope: false,\r\tisAsync: false,\r\tisExclusive: false,\r\t\r\tid: null,\r\t\r\tproperties: {},\r\t\r\t// Graphical information\r\tx: -1,\r\ty: -1,\r\twidth: -1,\r\theight: -1,\r\t\r\tsetId: function(id){\r\t\tthis.id = id;\r\t},\r\t\r\tgetId: function(){\r\t\treturn this.id;\r\t},\r\t\r\t\r\tsetProperty: function(name, value){\r\t\tthis.properties[name] = value;\r\t},\r\tgetProperty: function(name){\r\t\treturn this.properties[name];\r\t},\r\t\r\tcreateOutgoingTransition: function(transitionId){\r\t\r\t},\r\t\r\ttoString: function(id) {\r\t\treturn \"Activity(\"+id+\")\";\r\t},\r\t\r\tgetParentActivity: function(){\r\t/*\r\t\tif (parent instanceof ActivityImpl) {\r79       return (ActivityImpl) parent;\r80     }\r81     return null;\r\t*/\r\treturn this.parent;\r\t},\r\t\r\t// restricted setters ///////////////////////////////////////////////////////\r\t\r\tsetOutgoingTransitions: function(outgoingTransitions){\r\t\tthis.outgoingTransitions = outgoingTransitions;\r\t},\r\t\r\tsetParent: function(parent){\r\t\tthis.parent = parent;\r\t},\r\t\r\tsetIncomingTransitions: function(incomingTransitions){\r\t\tthis.incomingTransitions = incomingTransitions;\r\t},\r\t\r\t// getters and setters //////////////////////////////////////////////////////\r\t\r\tgetOutgoingTransitions: function(){\r\t\treturn this.outgoingTransitions;\r\t},\r\t\r\tgetActivityBehavior: function(){\r\t\treturn this.activityBehavior;\r\t},\r\t\r\tsetActivityBehavior: function(activityBehavior){\r\t\tthis.activityBehavior = activityBehavior;\r\t},\r\t\r\tgetParent: function(){\r\t\treturn this.parent;\r\t},\r\t\r\tgetIncomingTransitions: function(){\r\t\treturn this.incomingTransitions;\r\t},\r\t\r\tisScope: function(){\r\t\treturn this.isScope;\r\t},\r\t\r\tsetScope: function(isScope){\r\t\tthis.isScope = isScope;\r\t},\r\t\r\tgetX: function(){\r\t\treturn this.x;\r\t},\r\t\r\tsetX: function(x){\r\t\tthis.x = x;\r\t},\r\t\r\tgetY: function(){\r\t\treturn this.y;\r\t},\r\t\r\tsetY: function(y){\r\t\tthis.y = y;\r\t},\r\t\r\tgetWidth: function(){\r\t\treturn this.width;\r\t},\r\t\r\tsetWidth: function(width){\r\t\tthis.width = width;\r\t},\r\t\r\tgetHeight: function(){\r\t\treturn this.height;\r\t},\r\t\r\tsetHeight: function(height){\r\t\tthis.height = height;\r\t},\r\t\r  isAsync: function() {\r    return this.isAsync;\r  },\r  \r  setAsync: function(isAsync) {\r    this.isAsync = isAsync;\r  },\r  \r  isExclusive: function() {\r    return this.isExclusive;\r  },\r    \r  setExclusive: function(isExclusive) {\r    this.isExclusive = isExclusive;\r  },\r\t\r\tvvoid: function(){}\r};"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/diagram-viewer/js/Color.js",
    "content": "/**\n * Web color table\n * \n * @author Dmitry Farafonov\n */\n\nvar Color = {\n   /**\n   * The color white.  In the default sRGB space.\n   */\n  white     : Raphael.getRGB(\"rgb(255,255,255)\"),\n  \n  /**\n   * The color white.  In the default sRGB space.\n   */\n  WHITE : this.white,\n  \n  /**\n   * The color light gray.  In the default sRGB space.\n   */\n  lightGray : Raphael.getRGB(\"rgb(192, 192, 192)\"),\n  \n  /**\n   * The color light gray.  In the default sRGB space.\n   */\n  LIGHT_GRAY : this.lightGray,\n  \n  /**\n   * The color gray.  In the default sRGB space.\n   */\n  gray : Raphael.getRGB(\"rgb(128, 128, 128)\"),\n  \n  /**\n   * The color gray.  In the default sRGB space.\n   */\n  GRAY : this.gray,\n  \n  /**\n   * The color dark gray.  In the default sRGB space.\n   */\n  darkGray : Raphael.getRGB(\"rgb(64, 64, 64)\"),\n  \n  /**\n   * The color dark gray.  In the default sRGB space.\n   */\n  DARK_GRAY : this.darkGray,\n  \n  /**\n   * The color black.  In the default sRGB space.\n   */\n  black : Raphael.getRGB(\"rgb(0, 0, 0)\"),\n  \n  /**\n   * The color black.  In the default sRGB space.\n   */\n  BLACK : this.black,\n  \n  /**\n   * The color red.  In the default sRGB space.\n   */\n  red : Raphael.getRGB(\"rgb(255, 0, 0)\"),\n  \n  /**\n   * The color red.  In the default sRGB space.\n   */\n  RED : this.red,\n  \n  /**\n   * The color pink.  In the default sRGB space.\n   */\n  pink : Raphael.getRGB(\"rgb(255, 175, 175)\"),\n  \n  /**\n   * The color pink.  In the default sRGB space.\n   */\n  PINK : this.pink,\n  \n  /**\n   * The color orange.  In the default sRGB space.\n   */\n  orange : Raphael.getRGB(\"rgb(255, 200, 0)\"),\n  \n  /**\n   * The color orange.  In the default sRGB space.\n   */\n  ORANGE : this.orange,\n  \n  /**\n   * The color yellow.  In the default sRGB space.\n   */\n  yellow : Raphael.getRGB(\"rgb(255, 255, 0)\"),\n  \n  /**\n   * The color yellow.  In the default sRGB space.\n   */\n  YELLOW : this.yellow,\n  \n  /**\n   * The color green.  In the default sRGB space.\n   */\n  green : Raphael.getRGB(\"rgb(0, 255, 0)\"),\n  \n  /**\n   * The color green.  In the default sRGB space.\n   */\n  GREEN : this.green,\n  \n  /**\n   * The color magenta.  In the default sRGB space.\n   */\n  magenta : Raphael.getRGB(\"rgb(255, 0, 255)\"),\n  \n  /**\n   * The color magenta.  In the default sRGB space.\n   */\n  MAGENTA : this.magenta,\n  \n  /**\n   * The color cyan.  In the default sRGB space.\n   */\n  cyan : Raphael.getRGB(\"rgb(0, 255, 255)\"),\n  \n  /**\n   * The color cyan.  In the default sRGB space.\n   */\n  CYAN : this.cyan,\n  \n  /**\n   * The color blue.  In the default sRGB space.\n   */\n  blue : Raphael.getRGB(\"rgb(0, 0, 255)\"),\n  \n  /**\n   * The color blue.  In the default sRGB space.\n   */\n  BLUE : this.blue,\n  \n  /************************************************************************/\n\n  // http://www.stm.dp.ua/web-design/color-html.php\n  \n\tSnow\t\t\t:   Raphael.getRGB(\"#FFFAFA\t\"),  // \t255 250 250\n\tGhostWhite\t\t:   Raphael.getRGB(\"#F8F8FF\t\"),  // \t248 248 255\n\tWhiteSmoke\t\t:   Raphael.getRGB(\"#F5F5F5\t\"),  // \t245 245 245\n\tGainsboro\t\t:   Raphael.getRGB(\"#DCDCDC\t\"),  // \t220 220 220\n\tFloralWhite\t\t:   Raphael.getRGB(\"#FFFAF0\t\"),  // \t255 250 240\n\tOldLace\t\t\t:   Raphael.getRGB(\"#FDF5E6\t\"),  // \t253 245 230\n\tLinen\t\t\t:   Raphael.getRGB(\"#FAF0E6\t\"),  // \t250 240 230\n\tAntiqueWhite\t:   Raphael.getRGB(\"#FAEBD7\t\"),  // \t250 235 215\n\tPapayaWhip\t\t:   Raphael.getRGB(\"#FFEFD5\t\"),  // \t255 239 213\n\tBlanchedAlmond\t:   Raphael.getRGB(\"#FFEBCD\t\"),  // \t255 235 205\n\tBisque\t\t\t:   Raphael.getRGB(\"#FFE4C4\t\"),  // \t255 228 196\n\tPeachPuff\t\t:   Raphael.getRGB(\"#FFDAB9\t\"),  // \t255 218 185\n\tNavajoWhite\t\t:   Raphael.getRGB(\"#FFDEAD\t\"),  // \t255 222 173\n\tMoccasin\t\t:   Raphael.getRGB(\"#FFE4B5\t\"),  // \t255 228 181\n\tCornsilk\t\t:   Raphael.getRGB(\"#FFF8DC\t\"),  // \t255 248 220\n\tIvory\t\t\t:   Raphael.getRGB(\"#FFFFF0\t\"),  // \t255 255 240\n\tLemonChiffon\t:   Raphael.getRGB(\"#FFFACD\t\"),  // \t255 250 205\n\tSeashell\t\t:   Raphael.getRGB(\"#FFF5EE\t\"),  // \t255 245 238\n\tHoneydew\t\t:   Raphael.getRGB(\"#F0FFF0\t\"),  // \t240 255 240\n\tMintCream\t\t:   Raphael.getRGB(\"#F5FFFA\t\"),  // \t245 255 250\n\tAzure\t\t\t:   Raphael.getRGB(\"#F0FFFF\t\"),  // \t240 255 255\n\tAliceBlue\t\t:   Raphael.getRGB(\"#F0F8FF\t\"),  // \t240 248 255\n\tlavender\t\t:   Raphael.getRGB(\"#E6E6FA\t\"),  // \t230 230 250\n\tLavenderBlush\t:   Raphael.getRGB(\"#FFF0F5\t\"),  // \t255 240 245\n\tMistyRose\t\t:   Raphael.getRGB(\"#FFE4E1\t\"),  // \t255 228 225\n\tWhite\t\t\t:   Raphael.getRGB(\"#FFFFFF\t\"),  // \t255 255 255\n\tBlack\t\t\t:   Raphael.getRGB(\"#000000\t\"),  // \t0 0 0\n\tDarkSlateGray\t:   Raphael.getRGB(\"#2F4F4F\t\"),  // \t47 79 79\n\tDimGrey\t\t\t:   Raphael.getRGB(\"#696969\t\"),  // \t105 105 105\n\tSlateGrey\t\t:   Raphael.getRGB(\"#708090\t\"),  // \t112 128 144\n\tLightSlateGray\t:   Raphael.getRGB(\"#778899\t\"),  // \t119 136 153\n\tGrey\t\t\t:   Raphael.getRGB(\"#BEBEBE\t\"),  // \t190 190 190\n\tLightGray\t\t:   Raphael.getRGB(\"#D3D3D3\t\"),  // \t211 211 211\n\tMidnightBlue\t:   Raphael.getRGB(\"#191970\t\"),  // \t25 25 112\n\tNavyBlue\t\t:   Raphael.getRGB(\"#000080\t\"),  // \t0 0 128\n\tCornflowerBlue\t:   Raphael.getRGB(\"#6495ED\t\"),  // \t100 149 237\n\tDarkSlateBlue\t:   Raphael.getRGB(\"#483D8B\t\"),  // \t72 61 139\n\tSlateBlue\t\t:   Raphael.getRGB(\"#6A5ACD\t\"),  // \t106 90 205\n\tMediumSlateBlue\t:   Raphael.getRGB(\"#7B68EE\t\"),  // \t123 104 238\n\tLightSlateBlue\t:   Raphael.getRGB(\"#8470FF\t\"),  // \t132 112 255\n\tMediumBlue\t\t:   Raphael.getRGB(\"#0000CD\t\"),  // \t0 0 205\n\tRoyalBlue\t\t:   Raphael.getRGB(\"#4169E1\t\"),  // \t65 105 225\n\tBlue\t\t\t:   Raphael.getRGB(\"#0000FF\t\"),  // \t0 0 255\n\tDodgerBlue\t\t:   Raphael.getRGB(\"#1E90FF\t\"),  // \t30 144 255\n\tDeepSkyBlue\t\t:   Raphael.getRGB(\"#00BFFF\t\"),  // \t0 191 255\n\tSkyBlue\t\t\t:   Raphael.getRGB(\"#87CEEB\t\"),  // \t135 206 235\n\tLightSkyBlue\t:   Raphael.getRGB(\"#87CEFA\t\"),  // \t135 206 250\n\tSteelBlue\t\t:   Raphael.getRGB(\"#4682B4\t\"),  // \t70 130 180\n\tLightSteelBlue\t:   Raphael.getRGB(\"#B0C4DE\t\"),  // \t176 196 222\n\tLightBlue\t\t:   Raphael.getRGB(\"#ADD8E6\t\"),  // \t173 216 230\n\tPowderBlue\t\t:   Raphael.getRGB(\"#B0E0E6\t\"),  // \t176 224 230\n\tPaleTurquoise\t:   Raphael.getRGB(\"#AFEEEE\t\"),  // \t175 238 238\n\tDarkTurquoise\t:   Raphael.getRGB(\"#00CED1\t\"),  // \t0 206 209\n\tMediumTurquoise\t:   Raphael.getRGB(\"#48D1CC\t\"),  // \t72 209 204\n\tTurquoise\t\t:   Raphael.getRGB(\"#40E0D0\t\"),  // \t64 224 208\n\tCyan\t\t\t:   Raphael.getRGB(\"#00FFFF\t\"),  // \t0 255 255\n\tLightCyan\t\t:   Raphael.getRGB(\"#E0FFFF\t\"),  // \t224 255 255\n\tCadetBlue\t\t:   Raphael.getRGB(\"#5F9EA0\t\"),  // \t95 158 160\n\tMediumAquamarine:   Raphael.getRGB(\"#66CDAA\t\"),  // \t102 205 170\n\tAquamarine\t\t:   Raphael.getRGB(\"#7FFFD4\t\"),  // \t127 255 212\n\tDarkGreen\t\t:   Raphael.getRGB(\"#006400\t\"),  // \t0 100 0\n\tDarkOliveGreen\t:   Raphael.getRGB(\"#556B2F\t\"),  // \t85 107 47\n\tDarkSeaGreen\t:   Raphael.getRGB(\"#8FBC8F\t\"),  // \t143 188 143\n\tSeaGreen\t\t:   Raphael.getRGB(\"#2E8B57\t\"),  // \t46 139 87\n\tMediumSeaGreen\t:   Raphael.getRGB(\"#3CB371\t\"),  // \t60 179 113\n\tLightSeaGreen\t:   Raphael.getRGB(\"#20B2AA\t\"),  // \t32 178 170\n\tPaleGreen\t\t:   Raphael.getRGB(\"#98FB98\t\"),  // \t152 251 152\n\tSpringGreen\t\t:   Raphael.getRGB(\"#00FF7F\t\"),  // \t0 255 127\n\tLawnGreen\t\t:   Raphael.getRGB(\"#7CFC00\t\"),  // \t124 252 0\n\tGreen\t\t\t:   Raphael.getRGB(\"#00FF00\t\"),  // \t0 255 0\n\tChartreuse\t\t:   Raphael.getRGB(\"#7FFF00\t\"),  // \t127 255 0\n\tMedSpringGreen\t:   Raphael.getRGB(\"#00FA9A\t\"),  // \t0 250 154\n\tGreenYellow\t\t:   Raphael.getRGB(\"#ADFF2F\t\"),  // \t173 255 47\n\tLimeGreen\t\t:   Raphael.getRGB(\"#32CD32\t\"),  // \t50 205 50\n\tYellowGreen\t\t:   Raphael.getRGB(\"#9ACD32\t\"),  // \t154 205 50\n\tForestGreen\t\t:   Raphael.getRGB(\"#228B22\t\"),  // \t34 139 34\n\tOliveDrab\t\t:   Raphael.getRGB(\"#6B8E23\t\"),  // \t107 142 35\n\tDarkKhaki\t\t:   Raphael.getRGB(\"#BDB76B\t\"),  // \t189 183 107\n\tPaleGoldenrod\t:   Raphael.getRGB(\"#EEE8AA\t\"),  // \t238 232 170\n\tLtGoldenrodYello:   Raphael.getRGB(\"#FAFAD2\t\"),  // \t250 250 210\n\tLightYellow\t\t:   Raphael.getRGB(\"#FFFFE0\t\"),  // \t255 255 224\n\tYellow\t\t\t:   Raphael.getRGB(\"#FFFF00\t\"),  // \t255 255 0\n\tGold\t\t\t:   Raphael.getRGB(\"#FFD700\t\"),  // \t255 215 0\n\tLightGoldenrod\t:   Raphael.getRGB(\"#EEDD82\t\"),  // \t238 221 130\n\tgoldenrod\t\t:   Raphael.getRGB(\"#DAA520\t\"),  // \t218 165 32\n\tDarkGoldenrod\t:   Raphael.getRGB(\"#B8860B\t\"),  // \t184 134 11\n\tRosyBrown\t\t:   Raphael.getRGB(\"#BC8F8F\t\"),  // \t188 143 143\n\tIndianRed\t\t:   Raphael.getRGB(\"#CD5C5C\t\"),  // \t205 92 92\n\tSaddleBrown\t\t:   Raphael.getRGB(\"#8B4513\t\"),  // \t139 69 19\n\tSienna\t\t\t:   Raphael.getRGB(\"#A0522D\t\"),  // \t160 82 45\n\tPeru\t\t\t:   Raphael.getRGB(\"#CD853F\t\"),  // \t205 133 63\n\tBurlywood\t\t:   Raphael.getRGB(\"#DEB887\t\"),  // \t222 184 135\n\tBeige\t\t\t:   Raphael.getRGB(\"#F5F5DC\t\"),  // \t245 245 220\n\tWheat\t\t\t:   Raphael.getRGB(\"#F5DEB3\t\"),  // \t245 222 179\n\tSandyBrown\t\t:   Raphael.getRGB(\"#F4A460\t\"),  // \t244 164 96\n\tTan\t\t\t\t:   Raphael.getRGB(\"#D2B48C\t\"),  // \t210 180 140\n\tChocolate\t\t:   Raphael.getRGB(\"#D2691E\t\"),  // \t210 105 30\n\tFirebrick\t\t:   Raphael.getRGB(\"#B22222\t\"),  // \t178 34 34\n\tBrown\t\t\t:   Raphael.getRGB(\"#A52A2A\t\"),  // \t165 42 42\n\tDarkSalmon\t\t:   Raphael.getRGB(\"#E9967A\t\"),  // \t233 150 122\n\tSalmon\t\t\t:   Raphael.getRGB(\"#FA8072\t\"),  // \t250 128 114\n\tLightSalmon\t\t:   Raphael.getRGB(\"#FFA07A\t\"),  // \t255 160 122\n\tOrange\t\t\t:   Raphael.getRGB(\"#FFA500\t\"),  // \t255 165 0\n\tDarkOrange\t\t:   Raphael.getRGB(\"#FF8C00\t\"),  // \t255 140 0\n\tCoral\t\t\t:   Raphael.getRGB(\"#FF7F50\t\"),  // \t255 127 80\n\tLightCoral\t\t:   Raphael.getRGB(\"#F08080\t\"),  // \t240 128 128\n\tTomato\t\t\t:   Raphael.getRGB(\"#FF6347\t\"),  // \t255 99 71\n\tOrangeRed\t\t:   Raphael.getRGB(\"#FF4500\t\"),  // \t255 69 0\n\tRed\t\t\t\t:   Raphael.getRGB(\"#FF0000\t\"),  // \t255 0 0\n\tHotPink\t\t\t:   Raphael.getRGB(\"#FF69B4\t\"),  // \t255 105 180\n\tDeepPink\t\t:   Raphael.getRGB(\"#FF1493\t\"),  // \t255 20 147\n\tPink\t\t\t:   Raphael.getRGB(\"#FFC0CB\t\"),  // \t255 192 203\n\tLightPink\t\t:   Raphael.getRGB(\"#FFB6C1\t\"),  // \t255 182 193\n\tPaleVioletRed\t:   Raphael.getRGB(\"#DB7093\t\"),  // \t219 112 147\n\tMaroon\t\t\t:   Raphael.getRGB(\"#B03060\t\"),  // \t176 48 96\n\tMediumVioletRed\t:   Raphael.getRGB(\"#C71585\t\"),  // \t199 21 133\n\tVioletRed\t\t:   Raphael.getRGB(\"#D02090\t\"),  // \t208 32 144\n\tMagenta\t\t\t:   Raphael.getRGB(\"#FF00FF\t\"),  // \t255 0 255\n\tViolet\t\t\t:   Raphael.getRGB(\"#EE82EE\t\"),  // \t238 130 238\n\tPlum\t\t\t:   Raphael.getRGB(\"#DDA0DD\t\"),  // \t221 160 221\n\tOrchid\t\t\t:   Raphael.getRGB(\"#DA70D6\t\"),  // \t218 112 214\n\tMediumOrchid\t:   Raphael.getRGB(\"#BA55D3\t\"),  // \t186 85 211\n\tDarkOrchid\t\t:   Raphael.getRGB(\"#9932CC\t\"),  // \t153 50 204\n\tDarkViolet\t\t:   Raphael.getRGB(\"#9400D3\t\"),  // \t148 0 211\n\tBlueViolet\t\t:   Raphael.getRGB(\"#8A2BE2\t\"),  // \t138 43 226\n\tPurple\t\t\t:   Raphael.getRGB(\"#A020F0\t\"),  // \t160 32 240\n\tMediumPurple\t:   Raphael.getRGB(\"#9370DB\t\"),  // \t147 112 219\n\tThistle\t\t\t:   Raphael.getRGB(\"#D8BFD8\t\"),  // \t216 191 216\n\tSnow1\t\t\t:   Raphael.getRGB(\"#FFFAFA\t\"),  // \t255 250 250\n\tSnow2\t\t\t:   Raphael.getRGB(\"#EEE9E9\t\"),  // \t238 233 233\n\tSnow3\t\t\t:   Raphael.getRGB(\"#CDC9C9\t\"),  // \t205 201 201\n\tSnow4\t\t\t:   Raphael.getRGB(\"#8B8989\t\"),  // \t139 137 137\n\tSeashell1\t\t:   Raphael.getRGB(\"#FFF5EE\t\"),  // \t255 245 238\n\tSeashell2\t\t:   Raphael.getRGB(\"#EEE5DE\t\"),  // \t238 229 222\n\tSeashell3\t\t:   Raphael.getRGB(\"#CDC5BF\t\"),  // \t205 197 191\n\tSeashell4\t\t:   Raphael.getRGB(\"#8B8682\t\"),  // \t139 134 130\n\tAntiqueWhite1\t:   Raphael.getRGB(\"#FFEFDB\t\"),  // \t255 239 219\n\tAntiqueWhite2\t:   Raphael.getRGB(\"#EEDFCC\t\"),  // \t238 223 204\n\tAntiqueWhite3\t:   Raphael.getRGB(\"#CDC0B0\t\"),  // \t205 192 176\n\tAntiqueWhite4\t:   Raphael.getRGB(\"#8B8378\t\"),  // \t139 131 120\n\tBisque1\t\t\t:   Raphael.getRGB(\"#FFE4C4\t\"),  // \t255 228 196\n\tBisque2\t\t\t:   Raphael.getRGB(\"#EED5B7\t\"),  // \t238 213 183\n\tBisque3\t\t\t:   Raphael.getRGB(\"#CDB79E\t\"),  // \t205 183 158\n\tBisque4\t\t\t:   Raphael.getRGB(\"#8B7D6B\t\"),  // \t139 125 107\n\tPeachPuff1\t\t:   Raphael.getRGB(\"#FFDAB9\t\"),  // \t255 218 185\n\tPeachPuff2\t\t:   Raphael.getRGB(\"#EECBAD\t\"),  // \t238 203 173\n\tPeachPuff3\t\t:   Raphael.getRGB(\"#CDAF95\t\"),  // \t205 175 149\n\tPeachPuff4\t\t:   Raphael.getRGB(\"#8B7765\t\"),  // \t139 119 101\n\tNavajoWhite1\t:   Raphael.getRGB(\"#FFDEAD\t\"),  // \t255 222 173\n\tNavajoWhite2\t:   Raphael.getRGB(\"#EECFA1\t\"),  // \t238 207 161\n\tNavajoWhite3\t:   Raphael.getRGB(\"#CDB38B\t\"),  // \t205 179 139\n\tNavajoWhite4\t:   Raphael.getRGB(\"#8B795E\t\"),  // \t139 121 94\n\tLemonChiffon1\t:   Raphael.getRGB(\"#FFFACD\t\"),  // \t255 250 205\n\tLemonChiffon2\t:   Raphael.getRGB(\"#EEE9BF\t\"),  // \t238 233 191\n\tLemonChiffon3\t:   Raphael.getRGB(\"#CDC9A5\t\"),  // \t205 201 165\n\tLemonChiffon4\t:   Raphael.getRGB(\"#8B8970\t\"),  // \t139 137 112\n\tCornsilk1\t\t:   Raphael.getRGB(\"#FFF8DC\t\"),  // \t255 248 220\n\tCornsilk2\t\t:   Raphael.getRGB(\"#EEE8CD\t\"),  // \t238 232 205\n\tCornsilk3\t\t:   Raphael.getRGB(\"#CDC8B1\t\"),  // \t205 200 177\n\tCornsilk4\t\t:   Raphael.getRGB(\"#8B8878\t\"),  // \t139 136 120\n\tIvory1\t\t\t:   Raphael.getRGB(\"#FFFFF0\t\"),  // \t255 255 240\n\tIvory2\t\t\t:   Raphael.getRGB(\"#EEEEE0\t\"),  // \t238 238 224\n\tIvory3\t\t\t:   Raphael.getRGB(\"#CDCDC1\t\"),  // \t205 205 193\n\tIvory4\t\t\t:   Raphael.getRGB(\"#8B8B83\t\"),  // \t139 139 131\n\tHoneydew1\t\t:   Raphael.getRGB(\"#F0FFF0\t\"),  // \t240 255 240\n\tHoneydew2\t\t:   Raphael.getRGB(\"#E0EEE0\t\"),  // \t224 238 224\n\tHoneydew3\t\t:   Raphael.getRGB(\"#C1CDC1\t\"),  // \t193 205 193\n\tHoneydew4\t\t:   Raphael.getRGB(\"#838B83\t\"),  // \t131 139 131\n\tLavenderBlush1\t:   Raphael.getRGB(\"#FFF0F5\t\"),  // \t255 240 245\n\tLavenderBlush2\t:   Raphael.getRGB(\"#EEE0E5\t\"),  // \t238 224 229\n\tLavenderBlush3\t:   Raphael.getRGB(\"#CDC1C5\t\"),  // \t205 193 197\n\tLavenderBlush4\t:   Raphael.getRGB(\"#8B8386\t\"),  // \t139 131 134\n\tMistyRose1\t\t:   Raphael.getRGB(\"#FFE4E1\t\"),  // \t255 228 225\n\tMistyRose2\t\t:   Raphael.getRGB(\"#EED5D2\t\"),  // \t238 213 210\n\tMistyRose3\t\t:   Raphael.getRGB(\"#CDB7B5\t\"),  // \t205 183 181\n\tMistyRose4\t\t:   Raphael.getRGB(\"#8B7D7B\t\"),  // \t139 125 123\n\tAzure1\t\t\t:   Raphael.getRGB(\"#F0FFFF\t\"),  // \t240 255 255\n\tAzure2\t\t\t:   Raphael.getRGB(\"#E0EEEE\t\"),  // \t224 238 238\n\tAzure3\t\t\t:   Raphael.getRGB(\"#C1CDCD\t\"),  // \t193 205 205\n\tAzure4\t\t\t:   Raphael.getRGB(\"#838B8B\t\"),  // \t131 139 139\n\tSlateBlue1\t\t:   Raphael.getRGB(\"#836FFF\t\"),  // \t131 111 255\n\tSlateBlue2\t\t:   Raphael.getRGB(\"#7A67EE\t\"),  // \t122 103 238\n\tSlateBlue3\t\t:   Raphael.getRGB(\"#6959CD\t\"),  // \t105 89 205\n\tSlateBlue4\t\t:   Raphael.getRGB(\"#473C8B\t\"),  // \t71 60 139\n\tRoyalBlue1\t\t:   Raphael.getRGB(\"#4876FF\t\"),  // \t72 118 255\n\tRoyalBlue2\t\t:   Raphael.getRGB(\"#436EEE\t\"),  // \t67 110 238\n\tRoyalBlue3\t\t:   Raphael.getRGB(\"#3A5FCD\t\"),  // \t58 95 205\n\tRoyalBlue4\t\t:   Raphael.getRGB(\"#27408B\t\"),  // \t39 64 139\n\tBlue1\t\t\t:   Raphael.getRGB(\"#0000FF\t\"),  // \t0 0 255\n\tBlue2\t\t\t:   Raphael.getRGB(\"#0000EE\t\"),  // \t0 0 238\n\tBlue3\t\t\t:   Raphael.getRGB(\"#0000CD\t\"),  // \t0 0 205\n\tBlue4\t\t\t:   Raphael.getRGB(\"#00008B\t\"),  // \t0 0 139\n\tDodgerBlue1\t\t:   Raphael.getRGB(\"#1E90FF\t\"),  // \t30 144 255\n\tDodgerBlue2\t\t:   Raphael.getRGB(\"#1C86EE\t\"),  // \t28 134 238\n\tDodgerBlue3\t\t:   Raphael.getRGB(\"#1874CD\t\"),  // \t24 116 205\n\tDodgerBlue4\t\t:   Raphael.getRGB(\"#104E8B\t\"),  // \t16 78 139\n\tSteelBlue1\t\t:   Raphael.getRGB(\"#63B8FF\t\"),  // \t99 184 255\n\tSteelBlue2\t\t:   Raphael.getRGB(\"#5CACEE\t\"),  // \t92 172 238\n\tSteelBlue3\t\t:   Raphael.getRGB(\"#4F94CD\t\"),  // \t79 148 205\n\tSteelBlue4\t\t:   Raphael.getRGB(\"#36648B\t\"),  // \t54 100 139\n\tDeepSkyBlue1\t:   Raphael.getRGB(\"#00BFFF\t\"),  // \t0 191 255\n\tDeepSkyBlue2\t:   Raphael.getRGB(\"#00B2EE\t\"),  // \t0 178 238\n\tDeepSkyBlue3\t:   Raphael.getRGB(\"#009ACD\t\"),  // \t0 154 205\n\tDeepSkyBlue4\t:   Raphael.getRGB(\"#00688B\t\"),  // \t0 104 139\n\tSkyBlue1\t\t:   Raphael.getRGB(\"#87CEFF\t\"),  // \t135 206 255\n\tSkyBlue2\t\t:   Raphael.getRGB(\"#7EC0EE\t\"),  // \t126 192 238\n\tSkyBlue3\t\t:   Raphael.getRGB(\"#6CA6CD\t\"),  // \t108 166 205\n\tSkyBlue4\t\t:   Raphael.getRGB(\"#4A708B\t\"),  // \t74 112 139\n\tLightSkyBlue1\t:   Raphael.getRGB(\"#B0E2FF\t\"),  // \t176 226 255\n\tLightSkyBlue2\t:   Raphael.getRGB(\"#A4D3EE\t\"),  // \t164 211 238\n\tLightSkyBlue3\t:   Raphael.getRGB(\"#8DB6CD\t\"),  // \t141 182 205\n\tLightSkyBlue4\t:   Raphael.getRGB(\"#607B8B\t\"),  // \t96 123 139\n\tSlateGray1\t\t:   Raphael.getRGB(\"#C6E2FF\t\"),  // \t198 226 255\n\tSlateGray2\t\t:   Raphael.getRGB(\"#B9D3EE\t\"),  // \t185 211 238\n\tSlateGray3\t\t:   Raphael.getRGB(\"#9FB6CD\t\"),  // \t159 182 205\n\tSlateGray4\t\t:   Raphael.getRGB(\"#6C7B8B\t\"),  // \t108 123 139\n\tLightSteelBlue1\t:   Raphael.getRGB(\"#CAE1FF\t\"),  // \t202 225 255\n\tLightSteelBlue2\t:   Raphael.getRGB(\"#BCD2EE\t\"),  // \t188 210 238\n\tLightSteelBlue3\t:   Raphael.getRGB(\"#A2B5CD\t\"),  // \t162 181 205\n\tLightSteelBlue4\t:   Raphael.getRGB(\"#6E7B8B\t\"),  // \t110 123 139\n\tLightBlue1\t\t:   Raphael.getRGB(\"#BFEFFF\t\"),  // \t191 239 255\n\tLightBlue2\t\t:   Raphael.getRGB(\"#B2DFEE\t\"),  // \t178 223 238\n\tLightBlue3\t\t:   Raphael.getRGB(\"#9AC0CD\t\"),  // \t154 192 205\n\tLightBlue4\t\t:   Raphael.getRGB(\"#68838B\t\"),  // \t104 131 139\n\tLightCyan1\t\t:   Raphael.getRGB(\"#E0FFFF\t\"),  // \t224 255 255\n\tLightCyan2\t\t:   Raphael.getRGB(\"#D1EEEE\t\"),  // \t209 238 238\n\tLightCyan3\t\t:   Raphael.getRGB(\"#B4CDCD\t\"),  // \t180 205 205\n\tLightCyan4\t\t:   Raphael.getRGB(\"#7A8B8B\t\"),  // \t122 139 139\n\tPaleTurquoise1\t:   Raphael.getRGB(\"#BBFFFF\t\"),  // \t187 255 255\n\tPaleTurquoise2\t:   Raphael.getRGB(\"#AEEEEE\t\"),  // \t174 238 238\n\tPaleTurquoise3\t:   Raphael.getRGB(\"#96CDCD\t\"),  // \t150 205 205\n\tPaleTurquoise4\t:   Raphael.getRGB(\"#668B8B\t\"),  // \t102 139 139\n\tCadetBlue1\t\t:   Raphael.getRGB(\"#98F5FF\t\"),  // \t152 245 255\n\tCadetBlue2\t\t:   Raphael.getRGB(\"#8EE5EE\t\"),  // \t142 229 238\n\tCadetBlue3\t\t:   Raphael.getRGB(\"#7AC5CD\t\"),  // \t122 197 205\n\tCadetBlue4\t\t:   Raphael.getRGB(\"#53868B\t\"),  // \t83 134 139\n\tTurquoise1\t\t:   Raphael.getRGB(\"#00F5FF\t\"),  // \t0 245 255\n\tTurquoise2\t\t:   Raphael.getRGB(\"#00E5EE\t\"),  // \t0 229 238\n\tTurquoise3\t\t:   Raphael.getRGB(\"#00C5CD\t\"),  // \t0 197 205\n\tTurquoise4\t\t:   Raphael.getRGB(\"#00868B\t\"),  // \t0 134 139\n\tCyan1\t\t\t:   Raphael.getRGB(\"#00FFFF\t\"),  // \t0 255 255\n\tCyan2\t\t\t:   Raphael.getRGB(\"#00EEEE\t\"),  // \t0 238 238\n\tCyan3\t\t\t:   Raphael.getRGB(\"#00CDCD\t\"),  // \t0 205 205\n\tCyan4\t\t\t:   Raphael.getRGB(\"#008B8B\t\"),  // \t0 139 139\n\tDarkSlateGray1\t:   Raphael.getRGB(\"#97FFFF\t\"),  // \t151 255 255\n\tDarkSlateGray2\t:   Raphael.getRGB(\"#8DEEEE\t\"),  // \t141 238 238\n\tDarkSlateGray3\t:   Raphael.getRGB(\"#79CDCD\t\"),  // \t121 205 205\n\tDarkSlateGray4\t:   Raphael.getRGB(\"#528B8B\t\"),  // \t82 139 139\n\tAquamarine1\t\t:   Raphael.getRGB(\"#7FFFD4\t\"),  // \t127 255 212\n\tAquamarine2\t\t:   Raphael.getRGB(\"#76EEC6\t\"),  // \t118 238 198\n\tAquamarine3\t\t:   Raphael.getRGB(\"#66CDAA\t\"),  // \t102 205 170\n\tAquamarine4\t\t:   Raphael.getRGB(\"#458B74\t\"),  // \t69 139 116\n\tDarkSeaGreen1\t:   Raphael.getRGB(\"#C1FFC1\t\"),  // \t193 255 193\n\tDarkSeaGreen2\t:   Raphael.getRGB(\"#B4EEB4\t\"),  // \t180 238 180\n\tDarkSeaGreen3\t:   Raphael.getRGB(\"#9BCD9B\t\"),  // \t155 205 155\n\tDarkSeaGreen4\t:   Raphael.getRGB(\"#698B69\t\"),  // \t105 139 105\n\tSeaGreen1\t\t:   Raphael.getRGB(\"#54FF9F\t\"),  // \t84 255 159\n\tSeaGreen2\t\t:   Raphael.getRGB(\"#4EEE94\t\"),  // \t78 238 148\n\tSeaGreen3\t\t:   Raphael.getRGB(\"#43CD80\t\"),  // \t67 205 128\n\tSeaGreen4\t\t:   Raphael.getRGB(\"#2E8B57\t\"),  // \t46 139 87\n\tPaleGreen1\t\t:   Raphael.getRGB(\"#9AFF9A\t\"),  // \t154 255 154\n\tPaleGreen2\t\t:   Raphael.getRGB(\"#90EE90\t\"),  // \t144 238 144\n\tPaleGreen3\t\t:   Raphael.getRGB(\"#7CCD7C\t\"),  // \t124 205 124\n\tPaleGreen4\t\t:   Raphael.getRGB(\"#548B54\t\"),  // \t84 139 84\n\tSpringGreen1\t:   Raphael.getRGB(\"#00FF7F\t\"),  // \t0 255 127\n\tSpringGreen2\t:   Raphael.getRGB(\"#00EE76\t\"),  // \t0 238 118\n\tSpringGreen3\t:   Raphael.getRGB(\"#00CD66\t\"),  // \t0 205 102\n\tSpringGreen4\t:   Raphael.getRGB(\"#008B45\t\"),  // \t0 139 69\n\tGreen1\t\t\t:   Raphael.getRGB(\"#00FF00\t\"),  // \t0 255 0\n\tGreen2\t\t\t:   Raphael.getRGB(\"#00EE00\t\"),  // \t0 238 0\n\tGreen3\t\t\t:   Raphael.getRGB(\"#00CD00\t\"),  // \t0 205 0\n\tGreen4\t\t\t:   Raphael.getRGB(\"#008B00\t\"),  // \t0 139 0\n\tChartreuse1\t\t:   Raphael.getRGB(\"#7FFF00\t\"),  // \t127 255 0\n\tChartreuse2\t\t:   Raphael.getRGB(\"#76EE00\t\"),  // \t118 238 0\n\tChartreuse3\t\t:   Raphael.getRGB(\"#66CD00\t\"),  // \t102 205 0\n\tChartreuse4\t\t:   Raphael.getRGB(\"#458B00\t\"),  // \t69 139 0\n\tOliveDrab1\t\t:   Raphael.getRGB(\"#C0FF3E\t\"),  // \t192 255 62\n\tOliveDrab2\t\t:   Raphael.getRGB(\"#B3EE3A\t\"),  // \t179 238 58\n\tOliveDrab3\t\t:   Raphael.getRGB(\"#9ACD32\t\"),  // \t154 205 50\n\tOliveDrab4\t\t:   Raphael.getRGB(\"#698B22\t\"),  // \t105 139 34\n\tDarkOliveGreen1\t:   Raphael.getRGB(\"#CAFF70\t\"),  // \t202 255 112\n\tDarkOliveGreen2\t:   Raphael.getRGB(\"#BCEE68\t\"),  // \t188 238 104\n\tDarkOliveGreen3\t:   Raphael.getRGB(\"#A2CD5A\t\"),  // \t162 205 90\n\tDarkOliveGreen4\t:   Raphael.getRGB(\"#6E8B3D\t\"),  // \t110 139 61\n\tKhaki1\t\t\t:   Raphael.getRGB(\"#FFF68F\t\"),  // \t255 246 143\n\tKhaki2\t\t\t:   Raphael.getRGB(\"#EEE685\t\"),  // \t238 230 133\n\tKhaki3\t\t\t:   Raphael.getRGB(\"#CDC673\t\"),  // \t205 198 115\n\tKhaki4\t\t\t:   Raphael.getRGB(\"#8B864E\t\"),  // \t139 134 78\n\tLightGoldenrod1\t:   Raphael.getRGB(\"#FFEC8B\t\"),  // \t255 236 139\n\tLightGoldenrod2\t:   Raphael.getRGB(\"#EEDC82\t\"),  // \t238 220 130\n\tLightGoldenrod3\t:   Raphael.getRGB(\"#CDBE70\t\"),  // \t205 190 112\n\tLightGoldenrod4\t:   Raphael.getRGB(\"#8B814C\t\"),  // \t139 129 76\n\tLightYellow1\t:   Raphael.getRGB(\"#FFFFE0\t\"),  // \t255 255 224\n\tLightYellow2\t:   Raphael.getRGB(\"#EEEED1\t\"),  // \t238 238 209\n\tLightYellow3\t:   Raphael.getRGB(\"#CDCDB4\t\"),  // \t205 205 180\n\tLightYellow4\t:   Raphael.getRGB(\"#8B8B7A\t\"),  // \t139 139 122\n\tYellow1\t\t\t:   Raphael.getRGB(\"#FFFF00\t\"),  // \t255 255 0\n\tYellow2\t\t\t:   Raphael.getRGB(\"#EEEE00\t\"),  // \t238 238 0\n\tYellow3\t\t\t:   Raphael.getRGB(\"#CDCD00\t\"),  // \t205 205 0\n\tYellow4\t\t\t:   Raphael.getRGB(\"#8B8B00\t\"),  // \t139 139 0\n\tGold1\t\t\t:   Raphael.getRGB(\"#FFD700\t\"),  // \t255 215 0\n\tGold2\t\t\t:   Raphael.getRGB(\"#EEC900\t\"),  // \t238 201 0\n\tGold3\t\t\t:   Raphael.getRGB(\"#CDAD00\t\"),  // \t205 173 0\n\tGold4\t\t\t:   Raphael.getRGB(\"#8B7500\t\"),  // \t139 117 0\n\tGoldenrod1\t\t:   Raphael.getRGB(\"#FFC125\t\"),  // \t255 193 37\n\tGoldenrod2\t\t:   Raphael.getRGB(\"#EEB422\t\"),  // \t238 180 34\n\tGoldenrod3\t\t:   Raphael.getRGB(\"#CD9B1D\t\"),  // \t205 155 29\n\tGoldenrod4\t\t:   Raphael.getRGB(\"#8B6914\t\"),  // \t139 105 20\n\tDarkGoldenrod1\t:   Raphael.getRGB(\"#FFB90F\t\"),  // \t255 185 15\n\tDarkGoldenrod2\t:   Raphael.getRGB(\"#EEAD0E\t\"),  // \t238 173 14\n\tDarkGoldenrod3\t:   Raphael.getRGB(\"#CD950C\t\"),  // \t205 149 12\n\tDarkGoldenrod4\t:   Raphael.getRGB(\"#8B658B\t\"),  // \t139 101 8\n\tRosyBrown1\t\t:   Raphael.getRGB(\"#FFC1C1\t\"),  // \t255 193 193\n\tRosyBrown2\t\t:   Raphael.getRGB(\"#EEB4B4\t\"),  // \t238 180 180\n\tRosyBrown3\t\t:   Raphael.getRGB(\"#CD9B9B\t\"),  // \t205 155 155\n\tRosyBrown4\t\t:   Raphael.getRGB(\"#8B6969\t\"),  // \t139 105 105\n\tIndianRed1\t\t:   Raphael.getRGB(\"#FF6A6A\t\"),  // \t255 106 106\n\tIndianRed2\t\t:   Raphael.getRGB(\"#EE6363\t\"),  // \t238 99 99\n\tIndianRed3\t\t:   Raphael.getRGB(\"#CD5555\t\"),  // \t205 85 85\n\tIndianRed4\t\t:   Raphael.getRGB(\"#8B3A3A\t\"),  // \t139 58 58\n\tSienna1\t\t\t:   Raphael.getRGB(\"#FF8247\t\"),  // \t255 130 71\n\tSienna2\t\t\t:   Raphael.getRGB(\"#EE7942\t\"),  // \t238 121 66\n\tSienna3\t\t\t:   Raphael.getRGB(\"#CD6839\t\"),  // \t205 104 57\n\tSienna4\t\t\t:   Raphael.getRGB(\"#8B4726\t\"),  // \t139 71 38\n\tBurlywood1\t\t:   Raphael.getRGB(\"#FFD39B\t\"),  // \t255 211 155\n\tBurlywood2\t\t:   Raphael.getRGB(\"#EEC591\t\"),  // \t238 197 145\n\tBurlywood3\t\t:   Raphael.getRGB(\"#CDAA7D\t\"),  // \t205 170 125\n\tBurlywood4\t\t:   Raphael.getRGB(\"#8B7355\t\"),  // \t139 115 85\n\tWheat1\t\t\t:   Raphael.getRGB(\"#FFE7BA\t\"),  // \t255 231 186\n\tWheat2\t\t\t:   Raphael.getRGB(\"#EED8AE\t\"),  // \t238 216 174\n\tWheat3\t\t\t:   Raphael.getRGB(\"#CDBA96\t\"),  // \t205 186 150\n\tWheat4\t\t\t:   Raphael.getRGB(\"#8B7E66\t\"),  // \t139 126 102\n\tTan1\t\t\t:   Raphael.getRGB(\"#FFA54F\t\"),  // \t255 165 79\n\tTan2\t\t\t:   Raphael.getRGB(\"#EE9A49\t\"),  // \t238 154 73\n\tTan3\t\t\t:   Raphael.getRGB(\"#CD853F\t\"),  // \t205 133 63\n\tTan4\t\t\t:   Raphael.getRGB(\"#8B5A2B\t\"),  // \t139 90 43\n\tChocolate1\t\t:   Raphael.getRGB(\"#FF7F24\t\"),  // \t255 127 36\n\tChocolate2\t\t:   Raphael.getRGB(\"#EE7621\t\"),  // \t238 118 33\n\tChocolate3\t\t:   Raphael.getRGB(\"#CD661D\t\"),  // \t205 102 29\n\tChocolate4\t\t:   Raphael.getRGB(\"#8B4513\t\"),  // \t139 69 19\n\tFirebrick1\t\t:   Raphael.getRGB(\"#FF3030\t\"),  // \t255 48 48\n\tFirebrick2\t\t:   Raphael.getRGB(\"#EE2C2C\t\"),  // \t238 44 44\n\tFirebrick3\t\t:   Raphael.getRGB(\"#CD2626\t\"),  // \t205 38 38\n\tFirebrick4\t\t:   Raphael.getRGB(\"#8B1A1A\t\"),  // \t139 26 26\n\tBrown1\t\t\t:   Raphael.getRGB(\"#FF4040\t\"),  // \t255 64 64\n\tBrown2\t\t\t:   Raphael.getRGB(\"#EE3B3B\t\"),  // \t238 59 59\n\tBrown3\t\t\t:   Raphael.getRGB(\"#CD3333\t\"),  // \t205 51 51\n\tBrown4\t\t\t:   Raphael.getRGB(\"#8B2323\t\"),  // \t139 35 35\n\tSalmon1\t\t\t:   Raphael.getRGB(\"#FF8C69\t\"),  // \t255 140 105\n\tSalmon2\t\t\t:   Raphael.getRGB(\"#EE8262\t\"),  // \t238 130 98\n\tSalmon3\t\t\t:   Raphael.getRGB(\"#CD7054\t\"),  // \t205 112 84\n\tSalmon4\t\t\t:   Raphael.getRGB(\"#8B4C39\t\"),  // \t139 76 57\n\tLightSalmon1\t:   Raphael.getRGB(\"#FFA07A\t\"),  // \t255 160 122\n\tLightSalmon2\t:   Raphael.getRGB(\"#EE9572\t\"),  // \t238 149 114\n\tLightSalmon3\t:   Raphael.getRGB(\"#CD8162\t\"),  // \t205 129 98\n\tLightSalmon4\t:   Raphael.getRGB(\"#8B5742\t\"),  // \t139 87 66\n\tOrange1\t\t\t:   Raphael.getRGB(\"#FFA500\t\"),  // \t255 165 0\n\tOrange2\t\t\t:   Raphael.getRGB(\"#EE9A00\t\"),  // \t238 154 0\n\tOrange3\t\t\t:   Raphael.getRGB(\"#CD8500\t\"),  // \t205 133 0\n\tOrange4\t\t\t:   Raphael.getRGB(\"#8B5A00\t\"),  // \t139 90 0\n\tDarkOrange1\t\t:   Raphael.getRGB(\"#FF7F00\t\"),  // \t255 127 0\n\tDarkOrange2\t\t:   Raphael.getRGB(\"#EE7600\t\"),  // \t238 118 0\n\tDarkOrange3\t\t:   Raphael.getRGB(\"#CD6600\t\"),  // \t205 102 0\n\tDarkOrange4\t\t:   Raphael.getRGB(\"#8B4500\t\"),  // \t139 69 0\n\tCoral1\t\t\t:   Raphael.getRGB(\"#FF7256\t\"),  // \t255 114 86\n\tCoral2\t\t\t:   Raphael.getRGB(\"#EE6A50\t\"),  // \t238 106 80\n\tCoral3\t\t\t:   Raphael.getRGB(\"#CD5B45\t\"),  // \t205 91 69\n\tCoral4\t\t\t:   Raphael.getRGB(\"#8B3E2F\t\"),  // \t139 62 47\n\tTomato1\t\t\t:   Raphael.getRGB(\"#FF6347\t\"),  // \t255 99 71\n\tTomato2\t\t\t:   Raphael.getRGB(\"#EE5C42\t\"),  // \t238 92 66\n\tTomato3\t\t\t:   Raphael.getRGB(\"#CD4F39\t\"),  // \t205 79 57\n\tTomato4\t\t\t:   Raphael.getRGB(\"#8B3626\t\"),  // \t139 54 38\n\tOrangeRed1\t\t:   Raphael.getRGB(\"#FF4500\t\"),  // \t255 69 0\n\tOrangeRed2\t\t:   Raphael.getRGB(\"#EE4000\t\"),  // \t238 64 0\n\tOrangeRed3\t\t:   Raphael.getRGB(\"#CD3700\t\"),  // \t205 55 0\n\tOrangeRed4\t\t:   Raphael.getRGB(\"#8B2500\t\"),  // \t139 37 0\n\tRed1\t\t\t:   Raphael.getRGB(\"#FF0000\t\"),  // \t255 0 0\n\tRed2\t\t\t:   Raphael.getRGB(\"#EE0000\t\"),  // \t238 0 0\n\tRed3\t\t\t:   Raphael.getRGB(\"#CD0000\t\"),  // \t205 0 0\n\tRed4\t\t\t:   Raphael.getRGB(\"#8B0000\t\"),  // \t139 0 0\n\tDeepPink1\t\t:   Raphael.getRGB(\"#FF1493\t\"),  // \t255 20 147\n\tDeepPink2\t\t:   Raphael.getRGB(\"#EE1289\t\"),  // \t238 18 137\n\tDeepPink3\t\t:   Raphael.getRGB(\"#CD1076\t\"),  // \t205 16 118\n\tDeepPink4\t\t:   Raphael.getRGB(\"#8B0A50\t\"),  // \t139 10 80\n\tHotPink1\t\t:   Raphael.getRGB(\"#FF6EB4\t\"),  // \t255 110 180\n\tHotPink2\t\t:   Raphael.getRGB(\"#EE6AA7\t\"),  // \t238 106 167\n\tHotPink3\t\t:   Raphael.getRGB(\"#CD6090\t\"),  // \t205 96 144\n\tHotPink4\t\t:   Raphael.getRGB(\"#8B3A62\t\"),  // \t139 58 98\n\tPink1\t\t\t:   Raphael.getRGB(\"#FFB5C5\t\"),  // \t255 181 197\n\tPink2\t\t\t:   Raphael.getRGB(\"#EEA9B8\t\"),  // \t238 169 184\n\tPink3\t\t\t:   Raphael.getRGB(\"#CD919E\t\"),  // \t205 145 158\n\tPink4\t\t\t:   Raphael.getRGB(\"#8B636C\t\"),  // \t139 99 108\n\tLightPink1\t\t:   Raphael.getRGB(\"#FFAEB9\t\"),  // \t255 174 185\n\tLightPink2\t\t:   Raphael.getRGB(\"#EEA2AD\t\"),  // \t238 162 173\n\tLightPink3\t\t:   Raphael.getRGB(\"#CD8C95\t\"),  // \t205 140 149\n\tLightPink4\t\t:   Raphael.getRGB(\"#8B5F65\t\"),  // \t139 95 101\n\tPaleVioletRed1\t:   Raphael.getRGB(\"#FF82AB\t\"),  // \t255 130 171\n\tPaleVioletRed2\t:   Raphael.getRGB(\"#EE799F\t\"),  // \t238 121 159\n\tPaleVioletRed3\t:   Raphael.getRGB(\"#CD6889\t\"),  // \t205 104 137\n\tPaleVioletRed4\t:   Raphael.getRGB(\"#8B475D\t\"),  // \t139 71 93\n\tMaroon1\t\t\t:   Raphael.getRGB(\"#FF34B3\t\"),  // \t255 52 179\n\tMaroon2\t\t\t:   Raphael.getRGB(\"#EE30A7\t\"),  // \t238 48 167\n\tMaroon3\t\t\t:   Raphael.getRGB(\"#CD2990\t\"),  // \t205 41 144\n\tMaroon4\t\t\t:   Raphael.getRGB(\"#8B1C62\t\"),  // \t139 28 98\n\tVioletRed1\t\t:   Raphael.getRGB(\"#FF3E96\t\"),  // \t255 62 150\n\tVioletRed2\t\t:   Raphael.getRGB(\"#EE3A8C\t\"),  // \t238 58 140\n\tVioletRed3\t\t:   Raphael.getRGB(\"#CD3278\t\"),  // \t205 50 120\n\tVioletRed4\t\t:   Raphael.getRGB(\"#8B2252\t\"),  // \t139 34 82\n\tMagenta1\t\t:   Raphael.getRGB(\"#FF00FF\t\"),  // \t255 0 255\n\tMagenta2\t\t:   Raphael.getRGB(\"#EE00EE\t\"),  // \t238 0 238\n\tMagenta3\t\t:   Raphael.getRGB(\"#CD00CD\t\"),  // \t205 0 205\n\tMagenta4\t\t:   Raphael.getRGB(\"#8B008B\t\"),  // \t139 0 139\n\tOrchid1\t\t\t:   Raphael.getRGB(\"#FF83FA\t\"),  // \t255 131 250\n\tOrchid2\t\t\t:   Raphael.getRGB(\"#EE7AE9\t\"),  // \t238 122 233\n\tOrchid3\t\t\t:   Raphael.getRGB(\"#CD69C9\t\"),  // \t205 105 201\n\tOrchid4\t\t\t:   Raphael.getRGB(\"#8B4789\t\"),  // \t139 71 137\n\tPlum1\t\t\t:   Raphael.getRGB(\"#FFBBFF\t\"),  // \t255 187 255\n\tPlum2\t\t\t:   Raphael.getRGB(\"#EEAEEE\t\"),  // \t238 174 238\n\tPlum3\t\t\t:   Raphael.getRGB(\"#CD96CD\t\"),  // \t205 150 205\n\tPlum4\t\t\t:   Raphael.getRGB(\"#8B668B\t\"),  // \t139 102 139\n\tMediumOrchid1\t:   Raphael.getRGB(\"#E066FF\t\"),  // \t224 102 255\n\tMediumOrchid2\t:   Raphael.getRGB(\"#D15FEE\t\"),  // \t209 95 238\n\tMediumOrchid3\t:   Raphael.getRGB(\"#B452CD\t\"),  // \t180 82 205\n\tMediumOrchid4\t:   Raphael.getRGB(\"#7A378B\t\"),  // \t122 55 139\n\tDarkOrchid1\t\t:   Raphael.getRGB(\"#BF3EFF\t\"),  // \t191 62 255\n\tDarkOrchid2\t\t:   Raphael.getRGB(\"#B23AEE\t\"),  // \t178 58 238\n\tDarkOrchid3\t\t:   Raphael.getRGB(\"#9A32CD\t\"),  // \t154 50 205\n\tDarkOrchid4\t\t:   Raphael.getRGB(\"#68228B\t\"),  // \t104 34 139\n\tPurple1\t\t\t:   Raphael.getRGB(\"#9B30FF\t\"),  // \t155 48 255\n\tPurple2\t\t\t:   Raphael.getRGB(\"#912CEE\t\"),  // \t145 44 238\n\tPurple3\t\t\t:   Raphael.getRGB(\"#7D26CD\t\"),  // \t125 38 205\n\tPurple4\t\t\t:   Raphael.getRGB(\"#551A8B\t\"),  // \t85 26 139\n\tMediumPurple1\t:   Raphael.getRGB(\"#AB82FF\t\"),  // \t171 130 255\n\tMediumPurple2\t:   Raphael.getRGB(\"#9F79EE\t\"),  // \t159 121 238\n\tMediumPurple3\t:   Raphael.getRGB(\"#8968CD\t\"),  // \t137 104 205\n\tMediumPurple4\t:   Raphael.getRGB(\"#5D478B\t\"),  // \t93 71 139\n\tThistle1\t\t:   Raphael.getRGB(\"#FFE1FF\t\"),  // \t255 225 255\n\tThistle2\t\t:   Raphael.getRGB(\"#EED2EE\t\"),  // \t238 210 238\n\tThistle3\t\t:   Raphael.getRGB(\"#CDB5CD\t\"),  // \t205 181 205\n\tThistle4\t\t:   Raphael.getRGB(\"#8B7B8B\t\"),  // \t139 123 139\n\tgrey11\t\t\t:   Raphael.getRGB(\"#1C1C1C\t\"),  // \t28 28 28\n\tgrey21\t\t\t:   Raphael.getRGB(\"#363636\t\"),  // \t54 54 54\n\tgrey31\t\t\t:   Raphael.getRGB(\"#4F4F4F\t\"),  // \t79 79 79\n\tgrey41\t\t\t:   Raphael.getRGB(\"#696969\t\"),  // \t105 105 105\n\tgrey51\t\t\t:   Raphael.getRGB(\"#828282\t\"),  // \t130 130 130\n\tgrey61\t\t\t:   Raphael.getRGB(\"#9C9C9C\t\"),  // \t156 156 156\n\tgrey71\t\t\t:   Raphael.getRGB(\"#B5B5B5\t\"),  // \t181 181 181\n\tgray81\t\t\t:   Raphael.getRGB(\"#CFCFCF\t\"),  // \t207 207 207\n\tgray91\t\t\t:   Raphael.getRGB(\"#E8E8E8\t\"),  // \t232 232 232\n\tDarkGrey\t\t:   Raphael.getRGB(\"#A9A9A9\t\"),  // \t169 169 169\n\tDarkBlue\t\t:   Raphael.getRGB(\"#00008B\t\"),  // \t0 0 139\n\tDarkCyan\t\t:   Raphael.getRGB(\"#008B8B\t\"),  // \t0 139 139\n\tDarkMagenta\t\t:   Raphael.getRGB(\"#8B008B\t\"),  // \t139 0 139\n\tDarkRed\t\t\t:   Raphael.getRGB(\"#8B0000\t\"),  // \t139 0 0\n\tLightGreen\t\t:   Raphael.getRGB(\"#90EE90\t\"),  // \t144 238 144\n\n  \n  \n  get: function(R, G, B){\n\treturn Raphael.getRGB(\"rgb(\" + R + \", \" + G + \", \" + B + \")\");\n  }\n};"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/diagram-viewer/js/LineBreakMeasurer.js",
    "content": "/**\n * Word wrapping\n * \n * @author (Javascript) Dmitry Farafonov\n */\n\n\t\tvar AttributedStringIterator = function(text){\n\t\t\t\t//this.text = this.rtrim(this.ltrim(text));\n\t\t\t\ttext = text.replace(/(\\s)+/, \" \");\n\t\t\t\tthis.text = this.rtrim(text);\n\t\t\t\t/*\n\t\t\t\tif (beginIndex < 0 || beginIndex > endIndex || endIndex > length()) {\n\t\t\t\t\tthrow new IllegalArgumentException(\"Invalid substring range\");\n\t\t\t\t}\n\t\t\t\t*/\n\t\t\t\tthis.beginIndex = 0;\n\t\t\t\tthis.endIndex = this.text.length;\n\t\t\t\tthis.currentIndex = this.beginIndex;\n\t\t\t\t\n\t\t\t\t//console.group(\"[AttributedStringIterator]\");\n\t\t\t\tvar i = 0;\n\t\t\t\tvar string = this.text;\n\t\t\t\tvar fullPos = 0;\n\t\t\t\t\n\t\t\t\t//console.log(\"string: \\\"\" + string + \"\\\", length: \" + string.length);\n\t\t\t\tthis.startWordOffsets = [];\n\t\t\t\tthis.startWordOffsets.push(fullPos);\n\t\t\t\t\n\t\t\t\t// TODO: remove i 1000\n\t\t\t\twhile (i<1000) {\n\t\t\t\t\tvar pos = string.search(/[ \\t\\n\\f-\\.\\,]/);\n\t\t\t\t\tif (pos == -1)\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\n\t\t\t\t\t// whitespace start\n\t\t\t\t\tfullPos += pos;\n\t\t\t\t\tstring = string.substr(pos);\n\t\t\t\t\t////console.log(\"fullPos: \" + fullPos + \", pos: \" + pos +  \", string: \", string);\n\t\t\t\t\t\n\t\t\t\t\t// remove whitespaces\n\t\t\t\t\tvar pos = string.search(/[^ \\t\\n\\f-\\.\\,]/);\n\t\t\t\t\tif (pos == -1)\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\n\t\t\t\t\t// whitespace end\n\t\t\t\t\tfullPos += pos;\n\t\t\t\t\tstring = string.substr(pos);\n\t\t\t\t\t\n\t\t\t\t\t////console.log(\"fullPos: \" + fullPos);\n\t\t\t\t\tthis.startWordOffsets.push(fullPos);\n\t\t\t\t\t\n\t\t\t\t\ti++;\n\t\t\t\t}\n\t\t\t\t//console.log(\"startWordOffsets: \", this.startWordOffsets);\n\t\t\t\t//console.groupEnd();\n\t\t\t};\n\t\t\tAttributedStringIterator.prototype = {\n\t\t\t\tgetEndIndex: function(pos){\n\t\t\t\t\tif (typeof(pos) == \"undefined\")\n\t\t\t\t\t\treturn this.endIndex;\n\t\t\t\t\t\t\n\t\t\t\t\tvar string = this.text.substr(pos, this.endIndex - pos);\n\t\t\t\t\t\n\t\t\t\t\tvar posEndOfLine = string.search(/[\\n]/);\n\t\t\t\t\tif (posEndOfLine == -1)\n\t\t\t\t\t\treturn this.endIndex;\n\t\t\t\t\telse\n\t\t\t\t\t\treturn pos + posEndOfLine;\n\t\t\t\t},\n\t\t\t\tgetBeginIndex: function(){\n\t\t\t\t\treturn this.beginIndex;\n\t\t\t\t},\n\t\t\t\tisWhitespace: function(pos){\n\t\t\t\t\tvar str = this.text[pos];\n\t\t\t\t\tvar whitespaceChars = \" \\t\\n\\f\";\n\t\t\t\t\t\n\t\t\t\t\treturn (whitespaceChars.indexOf(str) != -1);\n\t\t\t\t},\n\t\t\t\tisNewLine: function(pos){\n\t\t\t\t\tvar str = this.text[pos];\n\t\t\t\t\tvar whitespaceChars = \"\\n\";\n\t\t\t\t\t\n\t\t\t\t\treturn (whitespaceChars.indexOf(str) != -1);\n\t\t\t\t},\n\t\t\t\tpreceding: function(pos){\n\t\t\t\t\t//console.group(\"[AttributedStringIterator.preceding]\");\n\t\t\t\t\tfor(var i in this.startWordOffsets) {\n\t\t\t\t\t\tvar startWordOffset = this.startWordOffsets[i];\n\t\t\t\t\t\tif (pos < startWordOffset && i>0) {\n\t\t\t\t\t\t\t//console.log(\"startWordOffset: \" + this.startWordOffsets[i-1]);\n\t\t\t\t\t\t\t//console.groupEnd();\n\t\t\t\t\t\t\treturn this.startWordOffsets[i-1];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t//console.log(\"pos: \" + pos);\n\t\t\t\t\t//console.groupEnd();\n\t\t\t\t\treturn this.startWordOffsets[i];\n\t\t\t\t},\n\t\t\t\tfollowing: function(pos){\n\t\t\t\t\t//console.group(\"[AttributedStringIterator.following]\");\n\t\t\t\t\tfor(var i in this.startWordOffsets) {\n\t\t\t\t\t\tvar startWordOffset = this.startWordOffsets[i];\n\t\t\t\t\t\tif (pos < startWordOffset && i>0) {\n\t\t\t\t\t\t\t//console.log(\"startWordOffset: \" + this.startWordOffsets[i]);\n\t\t\t\t\t\t\t//console.groupEnd();\n\t\t\t\t\t\t\treturn this.startWordOffsets[i];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t//console.log(\"pos: \" + pos);\n\t\t\t\t\t//console.groupEnd();\n\t\t\t\t\treturn this.startWordOffsets[i];\n\t\t\t\t},\n\t\t\t\tltrim: function(str){\n\t\t\t\t\tvar patt2=/^\\s+/g;\n\t\t\t\t\treturn str.replace(patt2, \"\");\n\t\t\t\t}, \n\t\t\t\trtrim: function(str){\n\t\t\t\t\tvar patt2=/\\s+$/g;\n\t\t\t\t\treturn str.replace(patt2, \"\");\n\t\t\t\t},\n\t\t\t\tgetLayout: function(start, limit){\n\t\t\t\t\treturn this.text.substr(start, limit - start);\n\t\t\t\t},\n\t\t\t\tgetCharAtPos: function(pos) {\n\t\t\t\t\treturn this.text[pos];\n\t\t\t\t}\n\t\t\t};\n\n\t\tvar LineBreakMeasurer = function(paper, x, y, text, fontAttrs){\n\t\t\t\tthis.paper = paper;\n\t\t\t\tthis.text = new AttributedStringIterator(text);\n\t\t\t\tthis.fontAttrs = fontAttrs;\n\t\t\t\t\n\t\t\t\tif (this.text.getEndIndex() - this.text.getBeginIndex() < 1) {\n\t\t\t\t\tthrow {message: \"Text must contain at least one character.\", code: \"IllegalArgumentException\"};\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t//this.measurer = new TextMeasurer(paper, this.text, this.fontAttrs);\n\t\t\t\tthis.limit = this.text.getEndIndex();\n\t\t\t\tthis.pos = this.start = this.text.getBeginIndex();\n\t\t\t\t\n\t\t\t\tthis.rafaelTextObject = this.paper.text(x, y, this.text.text).attr(fontAttrs).attr(\"text-anchor\", \"start\");\n\t\t\t\tthis.svgTextObject = this.rafaelTextObject[0];\n\t\t\t};\n\t\t\tLineBreakMeasurer.prototype = {\n\t\t\t\tnextOffset: function(wrappingWidth, offsetLimit, requireNextWord) {\n\t\t\t\t\t//console.group(\"[nextOffset]\");\n\t\t\t\t\tvar nextOffset = this.pos;\n\t\t\t\t\tif (this.pos < this.limit) {\n\t\t\t\t\t\tif (offsetLimit <= this.pos) {\n\t\t\t\t\t\t\tthrow {message: \"offsetLimit must be after current position\", code: \"IllegalArgumentException\"};\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tvar charAtMaxAdvance = this.getLineBreakIndex(this.pos, wrappingWidth);\n\t\t\t\t\t\t//charAtMaxAdvance --;\n\t\t\t\t\t\t//console.log(\"charAtMaxAdvance:\", charAtMaxAdvance, \", [\" + this.text.getCharAtPos(charAtMaxAdvance) + \"]\");\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (charAtMaxAdvance == this.limit) {\n\t\t\t\t\t\t\tnextOffset = this.limit;\n\t\t\t\t\t\t\t//console.log(\"charAtMaxAdvance == this.limit\");\n\t\t\t\t\t\t} else if (this.text.isNewLine(charAtMaxAdvance)) {\n\t\t\t\t\t\t\t//console.log(\"isNewLine\");\n\t\t\t\t\t\t\tnextOffset = charAtMaxAdvance+1;\n\t\t\t\t\t\t} else if (this.text.isWhitespace(charAtMaxAdvance)) {\n\t\t\t\t\t\t\t// TODO: find next noSpaceChar\n\t\t\t\t\t\t\t//return nextOffset;\n\t\t\t\t\t\t\tnextOffset = this.text.following(charAtMaxAdvance);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Break is in a word;  back up to previous break.\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\tvar testPos = charAtMaxAdvance + 1;\n\t\t\t\t\t\t\tif (testPos == this.limit) {\n\t\t\t\t\t\t\t\tconsole.error(\"hbz...\");\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tnextOffset = this.text.preceding(charAtMaxAdvance);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tnextOffset = this.text.preceding(charAtMaxAdvance);\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif (nextOffset <= this.pos) {\n\t\t\t\t\t\t\t\tnextOffset = Math.max(this.pos+1, charAtMaxAdvance);\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 (nextOffset > offsetLimit) {\n\t\t\t\t\t\tnextOffset = offsetLimit;\n\t\t\t\t\t}\n\t\t\t\t\t//console.log(\"nextOffset: \" + nextOffset);\n\t\t\t\t\t//console.groupEnd();\n\t\t\t\t\treturn nextOffset;\n\t\t\t\t},\n\t\t\t\tnextLayout: function(wrappingWidth) {\n\t\t\t\t\t//console.groupCollapsed(\"[nextLayout]\");\n\t\t\t\t\tif (this.pos < this.limit) {\n\t\t\t\t\t\tvar requireNextWord = false;\n\t\t\t\t\t\tvar layoutLimit = this.nextOffset(wrappingWidth, this.limit, requireNextWord);\n\t\t\t\t\t\t//console.log(\"layoutLimit:\", layoutLimit);\n\t\t\t\t\t\tif (layoutLimit == this.pos) {\n\t\t\t\t\t\t\t//console.groupEnd();\n\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvar result = this.text.getLayout(this.pos, layoutLimit);\n\t\t\t\t\t\t//console.log(\"layout: \\\"\" + result + \"\\\"\");\n\t\t\t\t\t\t\n\t\t\t\t\t\t// remove end of line\n\t\t\t\t\t\t\n\t\t\t\t\t\t//var posEndOfLine = this.text.getEndIndex(this.pos);\n\t\t\t\t\t\t//if (posEndOfLine < result.length)\n\t\t\t\t\t\t//\tresult = result.substr(0, posEndOfLine);\n\t\t\t\t\t\t\n\t\t\t\t\t\tthis.pos = layoutLimit;\n\t\t\t\t\t\t\n\t\t\t\t\t\t//console.groupEnd();\n\t\t\t\t\t\treturn result;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t//console.groupEnd();\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tgetLineBreakIndex: function(pos, wrappingWidth) {\n\t\t\t\t\t//console.group(\"[getLineBreakIndex]\");\n\t\t\t\t\t//console.log(\"pos:\"+pos + \", text: \\\"\"+ this.text.text.replace(/\\n/g, \"_\").substr(pos, 1) + \"\\\"\");\n\t\t\t\t\t\n\t\t\t\t\tvar bb = this.rafaelTextObject.getBBox();\n\t\t\t\t\t\n\t\t\t\t\tvar charNum = -1;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tvar svgPoint = this.svgTextObject.getStartPositionOfChar(pos);\n\t\t\t\t\t\t//var dot = this.paper.ellipse(svgPoint.x, svgPoint.y, 1, 1).attr({\"stroke-width\": 0, fill: Color.blue});\n\t\t\t\t\t\tsvgPoint.x = svgPoint.x + wrappingWidth;\n\t\t\t\t\t\t//svgPoint.y = bb.y;\n\t\t\t\t\t\t//console.log(\"svgPoint:\", svgPoint);\n\t\t\t\t\t\n\t\t\t\t\t\t//var dot = this.paper.ellipse(svgPoint.x, svgPoint.y, 1, 1).attr({\"stroke-width\": 0, fill: Color.red});\n\t\t\t\t\t\n\t\t\t\t\t\tcharNum = this.svgTextObject.getCharNumAtPosition(svgPoint);\n\t\t\t\t\t} catch (e){\n\t\t\t\t\t\tconsole.warn(\"getStartPositionOfChar error, pos:\" + pos);\n\t\t\t\t\t\t/*\n\t\t\t\t\t\tvar testPos = pos + 1;\n\t\t\t\t\t\tif (testPos < this.limit) {\n\t\t\t\t\t\t\treturn testPos\n\t\t\t\t\t\t}\n\t\t\t\t\t\t*/\n\t\t\t\t\t}\n\t\t\t\t\t//console.log(\"charNum:\", charNum);\n\t\t\t\t\tif (charNum == -1) {\n\t\t\t\t\t\t//console.groupEnd();\n\t\t\t\t\t\treturn this.text.getEndIndex(pos);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// When case there is new line between pos and charnum then use this new line\n\t\t\t\t\t\tvar newLineIndex = this.text.getEndIndex(pos);\n\t\t\t\t\t\tif (newLineIndex < charNum ) {\n\t\t\t\t\t\t\tconsole.log(\"newLineIndex <= charNum, newLineIndex:\"+newLineIndex+\", charNum:\"+charNum, \"\\\"\" + this.text.text.substr(newLineIndex+1).replace(/\\n/g, \"?\") + \"\\\"\");\n\t\t\t\t\t\t\t//console.groupEnd();\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\treturn newLineIndex;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t//var charAtMaxAdvance  = this.text.text.substring(charNum, charNum + 1);\n\t\t\t\t\t\tvar charAtMaxAdvance  = this.text.getCharAtPos(charNum);\n\t\t\t\t\t\t//console.log(\"!!charAtMaxAdvance: \" + charAtMaxAdvance);\n\t\t\t\t\t\t//console.groupEnd();\n\t\t\t\t\t\treturn charNum;\n\t\t\t\t\t}\n\t\t\t\t}, \n\t\t\t\tgetPosition: function() {\n\t\t\t\t\treturn this.pos;\n\t\t\t\t}\n\t\t\t};"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/diagram-viewer/js/Polyline.js",
    "content": "/**\n * Class to generate polyline\n *\n * @author Dmitry Farafonov\n */\n \nvar ANCHOR_TYPE= {\n\tmain: \"main\",\n\tmiddle: \"middle\",\n\tfirst: \"first\",\n\tlast: \"last\"\n};\n\nfunction Anchor(uuid, type, x, y) {\n\tthis.uuid = uuid; \n\tthis.x = x\n\tthis.y = y\n\tthis.type = (type == ANCHOR_TYPE.middle) ? ANCHOR_TYPE.middle : ANCHOR_TYPE.main;\n};\nAnchor.prototype = {\n\tuuid: null,\n\tx: 0,\n\ty: 0,\n\ttype: ANCHOR_TYPE.main,\n\tisFirst: false,\n\tisLast: false,\n\tndex: 0,\n\ttypeIndex: 0\n};\n\nfunction Polyline(uuid, points, strokeWidth) {\n\t/* Array on coordinates:\n\t * points: [{x: 410, y: 110}, 1\n\t *\t\t\t{x: 570, y: 110}, 1 2\n\t *\t\t\t{x: 620, y: 240},   2 3\n\t *\t\t\t{x: 750, y: 270},     3 4\n\t *\t\t\t{x: 650, y: 370}];      4\n\t */\n\tthis.points = points;\n\t\n\t/*\n\t * path for graph\n\t * [[\"M\", x1, y1], [\"L\", x2, y2], [\"C\", ax, ay, bx, by, x3, y3], [\"L\", x3, y3]]\n\t */\n\tthis.path = [];\n\t\n\tthis.anchors = [];\n\t\n\tif (strokeWidth) this.strokeWidth = strokeWidth;\n\t\n\tthis.closePath = false;\n\t\n\tthis.init();\n};\n\nPolyline.prototype = {\n\tid: null,\n\tpoints: [],\n\tpath: [],\n\tanchors: [],\n\tstrokeWidth: 1,\n\tradius: 15,\n\tshowDetails: false,\n\telement: null,\n\tisDefaultConditionAvailable: false,\n\tclosePath: false,\n\t\n\tinit: function(points){\n\t\tvar linesCount = this.getLinesCount();\n\t\tif (linesCount < 1)\n\t\t\treturn;\n\t\t\t\n\t\tthis.normalizeCoordinates();\n\t\t\n\t\t// create anchors\n\t\t\n\t\tthis.pushAnchor(ANCHOR_TYPE.first, this.getLine(0).x1, this.getLine(0).y1);\n\t\t\n\t\tfor(var i = 1; i < linesCount; i++){\n\t\t\tvar line1 = this.getLine(i-1),\n\t\t\t\tline2 = this.getLine(i);\n\t\t\t\n\t\t\t//this.pushAnchor(ANCHOR_TYPE.middle, line1.x1 + line1.x2-line1.x1, line1.y1 + line1.y2-line1.y1);\n\t\t\tthis.pushAnchor(ANCHOR_TYPE.main,  line1.x2, line1.y2);\n\t\t\t//this.pushAnchor(ANCHOR_TYPE.middle,  line2.x1 + line2.x2-line2.x1, line2.y1 + line2.y2-line2.y1);\n\t\t}\n\t\t\n\t\tthis.pushAnchor(ANCHOR_TYPE.last, this.getLine(linesCount-1).x2, this.getLine(linesCount-1).y2);\n\t\t\n\t\tthis.rebuildPath();\n\t},\n\t\n\tnormalizeCoordinates: function(){\n\t\tfor(var i=0; i < this.points.length; i++){\n\t\t\tthis.points[i].x = parseFloat(this.points[i].x);\n\t\t\tthis.points[i].y = parseFloat(this.points[i].y);\n\t\t}\n\t},\n\t\n\tgetLinesCount: function(){\n\t\treturn this.points.length-1;\n\t},\n\t_getLine: function(i){\n\t\treturn {x1: this.points[i].x, y1: this.points[i].y, x2: this.points[i+1].x, y2: this.points[i+1].y};\n\t},\n\tgetLine: function(i){\n\t\tvar line = this._getLine(i);\n\t\tline.angle = this.getLineAngle(i) ;\n\t\treturn line;\n\t},\n\tgetLineAngle: function(i){\n\t\tvar line = this._getLine(i);\n\t\treturn Math.atan2(line.y2 - line.y1, line.x2 - line.x1);\n\t},\n\tgetLineLengthX: function(i){\n\t\tvar line = this.getLine(i);\n\t\treturn (line.x2 - line.x1);\n\t},\n\tgetLineLengthY: function(i){\n\t\tvar line = this.getLine(i);\n\t\treturn (line.y2 - line.y1);\n\t},\n\tgetLineLength: function(i){\n\t\tvar line = this.getLine(i);\n\t\treturn Math.sqrt(Math.pow(this.getLineLengthX(i), 2) + Math.pow(this.getLineLengthY(i), 2));\n\t},\n\t\n\tgetAnchors: function(){\n\t\t//   \n\t\t// ????\n\t\treturn this.anchors;\n\t},\n\tgetAnchorsCount: function(type){\n\t\tif (!type)\n\t\t\treturn this.anchors.length;\n\t\telse {\n\t\t\tvar count = 0;\n\t\t\tfor(var i=0; i < this.getAnchorsCount(); i++){\n\t\t\t\tvar anchor = this.anchors[i];\n\t\t\t\tif (anchor.getType() == type) {\n\t\t\t\t\tcount++;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn count;\n\t\t}\n\t},\n\t\n\tpushAnchor: function(type, x, y, index){\n\t\tif (type == ANCHOR_TYPE.first) {\n\t\t\tindex = 0;\n\t\t\ttypeIndex = 0;\n\t\t} else if (type == ANCHOR_TYPE.last) {\n\t\t\tindex = this.getAnchorsCount();\n\t\t\ttypeIndex = 0;\n\t\t} else if (!index) {\n\t\t\tindex = this.anchors.length;\n\t\t} else {\n\t\t\t//  anchors,    ,   index\n\t\t\t//var anchor = this.getAnchor()\n\t\t\tfor(var i=0; i < this.getAnchorsCount(); i++){\n\t\t\t\tvar anchor = this.anchors[i];\n\t\t\t\tif (anchor.index > index) {\n\t\t\t\t\tanchor.index++;\n\t\t\t\t\tanchor.typeIndex++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\tvar anchor = new Anchor(this.id, ANCHOR_TYPE.main, x, y, index, typeIndex);\n\t\t\n\t\tthis.anchors.push(anchor);\n\t},\n\t\n\tgetAnchor: function(position){\n\t\treturn this.anchors[position];\n\t},\n\t\n\tgetAnchorByType: function(type, position){\n\t\tif (type == ANCHOR_TYPE.first)\n\t\t\treturn this.anchors[0];\n\t\tif (type == ANCHOR_TYPE.last)\n\t\t\treturn this.anchors[this.getAnchorsCount()-1];\n\t\t\n\t\tfor(var i=0; i < this.getAnchorsCount(); i++){\n\t\t\tvar anchor = this.anchors[i];\n\t\t\tif (anchor.type == type) {\n\t\t\t\tif( position == anchor.position)\n\t\t\t\t\treturn anchor;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t},\n\t\n\taddNewPoint: function(position, x, y){\n\t\t// \n\t\tfor(var i = 0; i < this.getLinesCount(); i++){\n\t\t\tvar line = this.getLine(i);\n\t\t\tif (x > line.x1 && x < line.x2 && y > line.y1 && y < line.y2) {\n\t\t\t\tthis.points.splice(i+1,0,{x: x, y: y});\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\t\n\t\tthis.rebuildPath();\n\t},\n\t\n\trebuildPath: function(){\n\t\tvar path = [];\n\t\t\n\t\tfor(var i = 0; i < this.getAnchorsCount(); i++){\n\t\t\tvar anchor = this.getAnchor(i);\n\t\t\t\n\t\t\tvar pathType = \"\"\n\t\t\tif (i==0)\n\t\t\t\tpathType = \"M\";\n\t\t\telse \n\t\t\t\tpathType = \"L\";\n\t\t\t\n// TODO: save previous points and calculate new path just if points are updated, and then save currents values as previous\n\t\t\t\n\t\t\tvar targetX = anchor.x, targetY = anchor.y;\n\t\t\tif (i>0 && i < this.getAnchorsCount()-1) {\n\t\t\t\t// get new x,y\n\t\t\t\tvar cx = anchor.x, cy = anchor.y;\n\t\t\t\t\n\t\t\t\t// pivot point of prev line\n\t\t\t\tvar AO = this.getLineLength(i-1);\n\t\t\t\tif (AO < this.radius) {\n\t\t\t\t\tAO = this.radius;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tthis.isDefaultConditionAvailable = (this.isDefaultConditionAvailable || (i == 1 && AO > 10));\n\t\t\t\t//console.log(\"isDefaultConditionAvailable\", this.isDefaultConditionAvailable);\n\t\t\t\t\n\t\t\t\tvar ED = this.getLineLengthY(i-1) * this.radius / AO;\n\t\t\t\tvar OD = this.getLineLengthX(i-1) * this.radius / AO;\n\t\t\t\t\ttargetX = anchor.x - OD;\n\t\t\t\t\ttargetY = anchor.y - ED;\n\t\t\t\t\n\t\t\t\tif (AO < 2*this.radius && i>1) {\n\t\t\t\t\ttargetX = anchor.x - this.getLineLengthX(i-1)/2;\n\t\t\t\t\ttargetY = anchor.y - this.getLineLengthY(i-1)/2;;\n\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t// pivot point of next line\n\t\t\t\tvar AO = this.getLineLength(i);\n\t\t\t\tif (AO < this.radius) {\n\t\t\t\t\tAO = this.radius;\n\t\t\t\t}\n\t\t\t\tvar ED = this.getLineLengthY(i) * this.radius / AO;\n\t\t\t\tvar OD = this.getLineLengthX(i) * this.radius / AO;\n\t\t\t\t\tvar nextSrcX = anchor.x + OD;\n\t\t\t\t\tvar nextSrcY = anchor.y + ED;\n\t\t\t\t\t\n\t\t\t\tif (AO < 2*this.radius && i<this.getAnchorsCount()-2) {\n\t\t\t\t\tnextSrcX = anchor.x + this.getLineLengthX(i)/2;\n\t\t\t\t\tnextSrcY = anchor.y + this.getLineLengthY(i)/2;;\n\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\tvar dx0 = (cx - targetX) / 3,\n\t\t\t\t\tdy0 = (cy - targetY) / 3,\n\t\t\t\t\tax = cx - dx0,\n\t\t\t\t\tay = cy - dy0,\n\t\t\t\t\t\n\t\t\t\t\tdx1 = (cx - nextSrcX) / 3,\n\t\t\t\t\tdy1 = (cy - nextSrcY) / 3,\n\t\t\t\t\tbx = cx - dx1,\n\t\t\t\t\tby = cy - dy1,\n\t\t\t\t\t\n\t\t\t\t\tzx=nextSrcX, zy=nextSrcY;\n\t\t\t\t\t\n\t\t\t\tif (this.showDetails) {\n\t\t\t\t\tvar c = ProcessDiagramCanvas.g.path(\"M\"+targetX+\",\"+targetY+\"L\"+ax+\",\"+ay).attr({stroke: Color.get(255, 153, 51), \"stroke-dasharray\": \"- \"});\n\t\t\t\t\tvar c = ProcessDiagramCanvas.g.path(\"M\"+nextSrcX+\",\"+nextSrcY+\"L\"+bx+\",\"+by).attr({stroke: Color.get(255, 153, 51), \"stroke-dasharray\": \"- \"});\n\t\t\t\t\tvar c = ProcessDiagramCanvas.g.ellipse(ax, ay, 2, 2).attr({stroke: Color.SlateGrey});\n\t\t\t\t\tvar c = ProcessDiagramCanvas.g.ellipse(bx, by, 2, 2).attr({stroke: Color.SlateGrey});\n\t\t\t\t\tvar c = ProcessDiagramCanvas.g.ellipse(cx, cy, this.radius, this.radius).attr({stroke: Color.Gainsboro});\n\t\t\t\t\tvar c = ProcessDiagramCanvas.g.ellipse(targetX, targetY, 2, 2).attr({fill: Color.red});\n\t\t\t\t\tvar c = ProcessDiagramCanvas.g.ellipse(nextSrcX, nextSrcY, 2, 2).attr({fill: Color.red});\n\t\t\t\t}\n\t\t\t} else if (i==1 && this.getAnchorsCount() == 2){\n\t\t\t\tvar AO = this.getLineLength(i-1);\n\t\t\t\tif (AO < this.radius) {\n\t\t\t\t\tAO = this.radius;\n\t\t\t\t}\n\t\t\t\tthis.isDefaultConditionAvailable = (this.isDefaultConditionAvailable || (i == 1 && AO > 10));\n\t\t\t\t//console.log(\"-- isDefaultConditionAvailable\", this.isDefaultConditionAvailable);\n\t\t\t}\n\n\t\t\t// anti smoothing\n\t\t\tif (this.strokeWidth%2 == 1) {\n\t\t\t\ttargetX += 0.5;\n\t\t\t\ttargetY += 0.5;\n\t\t\t}\n\t\t\t\n\t\t\tpath.push([pathType, targetX, targetY]);\n\t\t\t\n\t\t\tif (i>0 && i < this.getAnchorsCount()-1) {\n\t\t\t\tpath.push([\"C\", ax, ay, bx, by, zx, zy]);\n\t\t\t}\n\t\t}\n\t\t\n\t\tif (this.closePath) {\n\t\t\tconsole.log(\"closePath:\", this.closePath);\n\t\t\tpath.push([\"Z\"]);\n\t\t}\n\t\t\n\t\tthis.path = path;\n\t},\n\t\n\ttransform: function(transformation){\n\t\tthis.element.transform(transformation);\n\t},\n\tattr: function(attrs){\n\t\t//console.log(\"attrs: \" +attrs, \"\", this.element);\n\t\t// TODO: foreach and set each\n\t\tthis.element.attr(attrs);\n\t}\n};\n\nfunction Polygone(points, strokeWidth) {\n\t/* Array on coordinates:\n\t * points: [{x: 410, y: 110}, 1\n\t *\t\t\t{x: 570, y: 110}, 1 2\n\t *\t\t\t{x: 620, y: 240},   2 3\n\t *\t\t\t{x: 750, y: 270},     3 4\n\t *\t\t\t{x: 650, y: 370}];      4\n\t */\n\tthis.points = points;\n\t\n\t/*\n\t * path for graph\n\t * [[\"M\", x1, y1], [\"L\", x2, y2], [\"C\", ax, ay, bx, by, x3, y3], [\"L\", x3, y3]]\n\t */\n\tthis.path = [];\n\t\n\tthis.anchors = [];\n\t\n\tif (strokeWidth) this.strokeWidth = strokeWidth;\n\t\n\tthis.closePath = true;\n\tthis.init();\n};\n\n\n/*\n * Poligone is inherited from Poliline: draws closedPath of polyline\n */\n\nvar Foo = function () { };\nFoo.prototype = Polyline.prototype;\n\nPolygone.prototype = new Foo();\n\nPolygone.prototype.rebuildPath = function(){\n\tvar path = [];\n\t//console.log(\"Polygone rebuildPath\");\n\tfor(var i = 0; i < this.getAnchorsCount(); i++){\n\t\tvar anchor = this.getAnchor(i);\n\t\t\n\t\tvar pathType = \"\"\n\t\tif (i==0)\n\t\t\tpathType = \"M\";\n\t\telse \n\t\t\tpathType = \"L\";\n\t\t\n\t\tvar targetX = anchor.x, targetY = anchor.y;\n\t\t\n\t\t// anti smoothing\n\t\tif (this.strokeWidth%2 == 1) {\n\t\t\ttargetX += 0.5;\n\t\t\ttargetY += 0.5;\n\t\t}\n\t\t\n\t\tpath.push([pathType, targetX, targetY]);\t\n\t}\n\tif (this.closePath)\n\t\tpath.push([\"Z\"]);\n\t\n\tthis.path = path;\n};\n/*\nPolygone.prototype.transform = function(transformation){\n\tthis.element.transform(transformation);\n};\n*/"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/diagram-viewer/js/ProcessDiagramCanvas.js",
    "content": "/**\n * Represents a canvas on which BPMN 2.0 constructs can be drawn.\n * \n * Some of the icons used are licenced under a Creative Commons Attribution 2.5\n * License, see http://www.famfamfam.com/lab/icons/silk/\n * \n * @see ProcessDiagramGenerator\n * @author (Java) Joram Barrez\n * @author (Javascript) Dmitry Farafonov\n */\n \n//Color.Cornsilk\n\nvar ARROW_HEAD_SIMPLE = \"simple\";\nvar ARROW_HEAD_EMPTY = \"empty\";\nvar ARROW_HEAD_FILL = \"FILL\";\nvar MULTILINE_VERTICAL_ALIGN_TOP = \"top\";\nvar MULTILINE_VERTICAL_ALIGN_MIDDLE = \"middle\";\nvar MULTILINE_VERTICAL_ALIGN_BOTTOM = \"bottom\";\nvar MULTILINE_HORIZONTAL_ALIGN_LEFT = \"start\";\nvar MULTILINE_HORIZONTAL_ALIGN_MIDDLE = \"middle\";\nvar MULTILINE_HORIZONTAL_ALIGN_RIGHT = \"end\";\n\n// Predefined sized\nvar TEXT_PADDING = 3;\nvar ARROW_WIDTH = 4;\nvar CONDITIONAL_INDICATOR_WIDTH = 16;\nvar MARKER_WIDTH = 12;\nvar ANNOTATION_TEXT_PADDING = 7;\n\n// Colors\nvar TASK_COLOR = Color.OldLace; // original: Color.get(255, 255, 204);\nvar TASK_STROKE_COLOR = Color.black; /*Color.SlateGrey; */\n//var EXPANDED_SUBPROCESS_ATTRS = Color.black; /*Color.SlateGrey; */\nvar BOUNDARY_EVENT_COLOR = Color.white;\nvar CONDITIONAL_INDICATOR_COLOR = Color.get(255, 255, 255);\nvar HIGHLIGHT_COLOR = Color.Firebrick1;\n//var SEQUENCEFLOW_COLOR = Color.DimGrey;\nvar SEQUENCEFLOW_COLOR = Color.black;\n\nvar CATCHING_EVENT_COLOR = Color.black; /* Color.SlateGrey; */\nvar START_EVENT_COLOR = Color.get(251,251,251);\nvar START_EVENT_STROKE_COLOR = Color.black; /* Color.SlateGrey; */\nvar END_EVENT_COLOR = Color.get(251,251,251);\n//var END_EVENT_STROKE_COLOR = Color.black;\nvar NONE_END_EVENT_COLOR = Color.Firebrick4;\nvar NONE_END_EVENT_STROKE_COLOR = Color.Firebrick4;\nvar ERROR_END_EVENT_COLOR = Color.Firebrick;\nvar ERROR_END_EVENT_STROKE_COLOR = Color.Firebrick;\n//var LABEL_COLOR = Color.get(112, 146, 190);\nvar LABEL_COLOR = Color.get(72, 106, 150);\n\n// Fonts\nvar NORMAL_FONT = {font: \"10px Arial\", opacity: 1, fill: Color.black};\nvar LABEL_FONT = {font: \"11px Arial\", \"font-style\":\"italic\", opacity: 1, \"fill\": LABEL_COLOR};\nvar LABEL_FONT_SMOOTH = {font: \"10px Arial\", \"font-style\":\"italic\", opacity: 1, \"fill\": LABEL_COLOR, stroke: LABEL_COLOR, \"stroke-width\":.4};\nvar TASK_FONT = {font: \"11px Arial\", opacity: 1, fill: Color.black};\nvar TASK_FONT_SMOOTH = {font: \"11px Arial\", opacity: 1, fill: Color.black, stroke: LABEL_COLOR, \"stroke-width\":.4};\nvar POOL_LANE_FONT = {font: \"11px Arial\", opacity: 1, fill: Color.black};\nvar EXPANDED_SUBPROCESS_FONT = {font: \"11px Arial\", opacity: 1, fill: Color.black};\n\n// Strokes\nvar NORMAL_STROKE = 1;\nvar SEQUENCEFLOW_STROKE = 1.5;\nvar SEQUENCEFLOW_HIGHLIGHT_STROKE = 2;\nvar THICK_TASK_BORDER_STROKE = 2.5;\nvar GATEWAY_TYPE_STROKE = 3.2;\nvar END_EVENT_STROKE = NORMAL_STROKE+2;\nvar MULTI_INSTANCE_STROKE = 1.3;\nvar EVENT_SUBPROCESS_ATTRS = \t{\"stroke\": Color.black, \"stroke-width\": NORMAL_STROKE, \"stroke-dasharray\": \". \"};\n//var EXPANDED_SUBPROCESS_ATTRS = {\"stroke\": Color.black, \"stroke-width\": NORMAL_STROKE, \"fill\": Color.FloralWhite};\nvar EXPANDED_SUBPROCESS_ATTRS = {\"stroke\": Color.black, \"stroke-width\": NORMAL_STROKE, \"fill\": Color.WhiteSmoke};\nvar NON_INTERRUPTING_EVENT_STROKE = \"- \";\n\nvar TASK_CORNER_ROUND = 10;\nvar EXPANDED_SUBPROCESS_CORNER_ROUND = 10;\n\n// icons\nvar ICON_SIZE = 16;\nvar ICON_PADDING = 4;\nvar USERTASK_IMAGE = \t\t\"images/deployer/user.png\";\nvar SCRIPTTASK_IMAGE = \t\t\"images/deployer/script.png\";\nvar SERVICETASK_IMAGE = \t\"images/deployer/service.png\";\nvar RECEIVETASK_IMAGE = \t\"images/deployer/receive.png\";\nvar SENDTASK_IMAGE = \t\t\"images/deployer/send.png\";\nvar MANUALTASK_IMAGE = \t\t\"images/deployer/manual.png\";\nvar BUSINESS_RULE_TASK_IMAGE = \"images/deployer/business_rule.png\";\nvar TIMER_IMAGE = \t\t\t\"images/deployer/timer.png\";\nvar MESSAGE_CATCH_IMAGE = \t\"images/deployer/message_catch.png\";\nvar MESSAGE_THROW_IMAGE = \t\"images/deployer/message_throw.png\";\nvar ERROR_THROW_IMAGE = \t\"images/deployer/error_throw.png\";\nvar ERROR_CATCH_IMAGE = \t\"images/deployer/error_catch.png\";\nvar SIGNAL_CATCH_IMAGE = \t\"images/deployer/signal_catch.png\";\nvar SIGNAL_THROW_IMAGE = \t\"images/deployer/signal_throw.png\";\nvar MULTIPLE_CATCH_IMAGE = \t\"images/deployer/multiple_catch.png\";\n\n\nvar ObjectType = {\n\tELLIPSE: \"ellipse\",\n\tFLOW: \"flow\",\n\tRECT: \"rect\",\n\tRHOMBUS: \"rhombus\"\n};\n\nfunction OBJ(type){\n\tthis.c = null;\n\tthis.type = type;\n\tthis.nestedElements = [];\n};\nOBJ.prototype = {\n\t\n};\n\nvar CONNECTION_TYPE = {\n\tSEQUENCE_FLOW: \"sequence_flow\",\n\tMESSAGE_FLOW: \"message_flow\",\n\tASSOCIATION: \"association\"\n};\n\nvar ProcessDiagramCanvas = function(){\n};\nProcessDiagramCanvas.prototype = {\n// var DefaultProcessDiagramCanvas = {\n\tcanvasHolder: \"holder\",\n\tcanvasWidth: 0, \n\tcanvasHeight: 0,\n\tpaint: Color.black,\n\tstrokeWidth: 0,\n\tfont: null,\n\tfontSmoothing: null,\n\t\n\tg: null,\n\tninjaPaper: null,\n\t\n\tobjects: [],\n\t\n\tprocessDefinitionId: null,\n\tactivity: null,\n\t\n\tframe: null,\n\t\n\t\n\tdebug: false,\n\t\n\t/**\n\t* Creates an empty canvas with given width and height.\n\t*/\n\tinit: function(width, height, processDefinitionId){\n\t\tthis.canvasWidth = width;\n\t\tthis.canvasHeight = height;\n\t\t\n\t\t// TODO: name it as 'canvasName'\n\t\tif (!processDefinitionId)\n\t\t\tprocessDefinitionId = \"holder\";\n\t\t\n\t\tthis.processDefinitionId = processDefinitionId;\n\t\tthis.canvasHolder = this.processDefinitionId;\n\n\t\tvar h = document.getElementById(this.canvasHolder);\n\t\tif (!h) return;\n\t\t\n\t\th.style.width = this.canvasWidth;\n\t\th.style.height = this.canvasHeight;\n\t\t\n\t\tthis.g = Raphael(this.canvasHolder);\n\t\tthis.g.clear();\n\t\n\t\t//this.setPaint(Color.DimGrey);\n\t\tthis.setPaint(Color.black);\n\t\t//this.setPaint(Color.white);\n\t\tthis.setStroke(NORMAL_STROKE);\n\t\t\n\t\t//this.setFont(\"Arial\", 11);\n\t\tthis.setFont(NORMAL_FONT);\n\t\t//this.font = this.g.getFont(\"Arial\");\n\t\t\n\t\tthis.fontSmoothing = true;\n\t\t\n\t\t// ninja!\n\t\tvar RaphaelOriginal = Raphael;\n\t\tthis.ninjaPaper =(function (local_raphael) {\n\t\t\tvar paper = local_raphael(1, 1, 1, 1, processDefinitionId);\n\t\t\treturn paper;\n\t\t})(Raphael.ninja());\n\t\tRaphael = RaphaelOriginal;\n\t},\n\tsetPaint: function(color){\n\t\tthis.paint = color;\n\t},\n\tgetPaint: function(){\n\t\treturn this.paint;\n\t},\n\tsetStroke: function(strokeWidth){\n\t\tthis.strokeWidth = strokeWidth;\n\t},\n\tgetStroke: function(){\n\t\treturn this.strokeWidth;\n\t},\n\t/*\n\tsetFont: function(family, weight, style, stretch){\n\t\tthis.font = this.g.getFont(family, weight);\n\t},\n\t*/\n\tsetFont: function(font){\n\t\tthis.font = font;\n\t},\n\tgetFont: function(){\n\t\treturn this.font;\n\t},\n\tdrawShaddow: function(object){\n\t\tvar border = object.clone();\n\t\tborder.attr({\"stroke-width\": this.strokeWidth + 6, \n\t\t\t\t\t\"stroke\": Color.white,\n\t\t\t\t\t\"fill\": Color.white,\n\t\t\t\t\t\"opacity\": 1,\n\t\t\t\t\t\"stroke-dasharray\":null});\n\t\t//border.toBack();\n\t\tobject.toFront();\n\t\t\n\t\treturn border;\n\t},\n\t\n\tsetConextObject: function(obj){\n\t\tthis.contextObject = obj;\n\t},\n\tgetConextObject: function(){\n\t\treturn this.contextObject;\n\t},\n\tsetContextToElement: function(object){\n\t\tvar contextObject = this.getConextObject();\n\t\tobject.id = contextObject.id;\n\t\tobject.data(\"contextObject\", contextObject);\n\t},\n\tonClick: function(event, instance, element){\n\t  var overlay = element;\n\t  var set = overlay.data(\"set\");\n\t  var contextObject = overlay.data(\"contextObject\");\n\t  //console.log(\"[\"+contextObject.getProperty(\"type\")+\"], activityId: \" + contextObject.getId());\n\t  if (ProcessDiagramGenerator.options && ProcessDiagramGenerator.options.on && ProcessDiagramGenerator.options.on.click) {\n\t    var args = [instance, element, contextObject];\n\t    ProcessDiagramGenerator.options.on.click.apply(event, args);\n\t  }\n\t},\n\tonRightClick: function(event, instance, element){\n\t  var overlay = element;\n\t  var set = overlay.data(\"set\");\n\t  var contextObject = overlay.data(\"contextObject\");\n\t  //console.log(\"[%s], activityId: %s (RIGHTCLICK)\", contextObject.getProperty(\"type\"), contextObject.getId());\n\n\t  if (ProcessDiagramGenerator.options && ProcessDiagramGenerator.options.on && ProcessDiagramGenerator.options.on.rightClick) {\n\t    var args = [instance, element, contextObject];\n\t    ProcessDiagramGenerator.options.on.rightClick.apply(event, args);\n\t  }\n\t},\n\tonHoverIn: function(event, instance, element){\n\t  var overlay = element;\n\t  var set = overlay.data(\"set\");\n\t  var contextObject = overlay.data(\"contextObject\");\n\n\t  var border = instance.g.getById(contextObject.id + \"_border\");\n\t  border.attr(\"opacity\", 0.3);\n\n\t  // provide callback\n\t  if (ProcessDiagramGenerator.options && ProcessDiagramGenerator.options.on && ProcessDiagramGenerator.options.on.over) {\n\t    var args = [instance, element, contextObject];\n\t    ProcessDiagramGenerator.options.on.over.apply(event, args);\n\t  }\n\t },\n\t onHoverOut: function(event, instance, element){\n\t   var overlay = element;\n\t   var set = overlay.data(\"set\");\n\t   var contextObject = overlay.data(\"contextObject\");\n\n\t   var border = instance.g.getById(contextObject.id + \"_border\");\n\t   border.attr(\"opacity\", 0.0);\n\t   // provide callback\n\t   if (ProcessDiagramGenerator.options && ProcessDiagramGenerator.options.on && ProcessDiagramGenerator.options.on.out) {\n\t     var args = [instance, element, contextObject];\n\t     ProcessDiagramGenerator.options.on.out.apply(event, args);\n\t   }\n\t },\n\t addHandlers: function(set, x, y, width, height, type){\n\t   var contextObject = this.getConextObject();\n\n\t   var cx = x+width/2, cy = y+height/2;\n\t   if (type == \"event\") {\n\t     var border = this.g.ellipse(cx, cy, width/2+4, height/2+4);\n\t     var overlay = this.g.ellipse(cx, cy, width/2, height/2);\n\t   } else if (type == \"gateway\") {\n\t     // rhombus\n\t     var border = this.g.path( \"M\" + (x - 4) + \" \" + (y + (height / 2)) +\n\t         \"L\" + (x + (width / 2)) + \" \" + (y + height + 4) +\n\t         \"L\" + (x + width + 4) + \" \" + (y + (height / 2)) +\n\t         \"L\" + (x + (width / 2)) + \" \" + (y - 4) +\n\t         \"z\" );\n\t     var overlay = this.g.path(  \"M\" + x + \" \" + (y + (height / 2)) +\n\t         \"L\" + (x + (width / 2)) + \" \" + (y + height) +\n\t         \"L\" + (x + width) + \" \" + (y + (height / 2)) +\n\t         \"L\" + (x + (width / 2)) + \" \" + y +\n\t         \"z\" );\n\t   } else if (type == \"task\") {\n\t     var border = this.g.rect(x - 4, y - 4, width+9, height+9, TASK_CORNER_ROUND+4);\n\t     var overlay = this.g.rect(x, y, width, height, TASK_CORNER_ROUND);\n\t   }\n\n\t   border.attr({stroke: Color.get(132,112,255)/*Color.Tan1*/,\"stroke-width\": 4, opacity: 0.0});\n\t   border.id = contextObject.id + \"_border\";\n\n\t   set.push(border);\n\n\t   overlay.attr({stroke: Color.Orange,\"stroke-width\": 3, fill: Color.get(0,0,0), opacity: 0.0, cursor: \"hand\"});\n\t   overlay.data(\"set\",set);\n\t   overlay.id = contextObject.id;\n\t   overlay.data(\"contextObject\",contextObject);\n\n\t   var instance = this;\n\t   overlay.mousedown(function(event){if (event.button == 2) instance.onRightClick(event, instance, this);});\n\t   overlay.click(function(event){instance.onClick(event, instance, this);});\n\t   overlay.hover(function(event){instance.onHoverIn(event, instance, this);}, function(event){instance.onHoverOut(event, instance, this);});\n\t },\n\t\n\t/*\n\t * Start Events:\n\t * \n\t *\tdrawNoneStartEvent\n\t *\tdrawTimerStartEvent\n\t *\tdrawMessageStartEvent\n\t *\tdrawErrorStartEvent\n\t *\tdrawSignalStartEvent\n\t *\t_drawStartEventImage\n\t *\t_drawStartEvent\n\t */\n\t \n\tdrawNoneStartEvent: function(x, y, width, height) {\n\t  this.g.setStart();\n\t  \n\t\tvar isInterrupting = undefined;\n\t\tthis._drawStartEvent(x, y, width, height, isInterrupting, null);\n\t\t\n\t\tvar set = this.g.setFinish();\n\t\tthis.addHandlers(set, x, y, width, height, \"event\");\n\t},\n\t\n\tdrawTimerStartEvent: function(x, y, width, height, isInterrupting, name) {\n\t  this.g.setStart();\n\t  \n\t\tthis._drawStartEvent(x, y, width, height, isInterrupting, null);\n\t\t\n\t\tvar cx = x + width/2 - this.getStroke()/4;\n\t\tvar cy = y + height/2 - this.getStroke()/4;\n\t\t\n\t\tvar w = width*.9;// - this.getStroke()*2;\n\t\tvar h = height*.9;// - this.getStroke()*2;\n\t\t\n\t\tthis._drawClock(cx, cy, w, h);\n\t\t\n\t\tif (this.gebug)\n\t\t\tvar center = this.g.ellipse(cx, cy, 3, 3).attr({stroke:\"none\", fill: Color.green});\n\t\t\n\t\tvar set = this.g.setFinish();\n\t\tthis.addHandlers(set, x, y, width, height, \"event\");\n\t},\n\t\n\tdrawMessageStartEvent: function(x, y, width, height, isInterrupting, name) {\n\t  this.g.setStart();\n\t  \n\t\tthis._drawStartEvent(x, y, width, height, isInterrupting, null);\n\t\t\n\t\tthis._drawStartEventImage(x, y, width, height, MESSAGE_CATCH_IMAGE);\n\t\t\n\t\tvar set = this.g.setFinish();\n    this.addHandlers(set, x, y, width, height, \"event\");\n\t},\n\t\n\tdrawErrorStartEvent: function(x, y, width, height, name) {\n\t  this.g.setStart();\n\t\tvar isInterrupting = undefined;\n\t\tthis._drawStartEvent(x, y, width, height, isInterrupting);\n\n\t\tthis._drawStartEventImage(x, y, width, height, ERROR_CATCH_IMAGE);\n\t\t\n\t\tvar set = this.g.setFinish();\n    this.addHandlers(set, x, y, width, height, \"event\");\n\t},\n\t\n\tdrawSignalStartEvent: function(x, y, width, height, isInterrupting, name) {\n\t  this.g.setStart();\n\t\tthis._drawStartEvent(x, y, width, height, isInterrupting, null);\n\t\t\n\t\tthis._drawStartEventImage(x, y, width, height, SIGNAL_CATCH_IMAGE);\n\t\t\n\t\tvar set = this.g.setFinish();\n    this.addHandlers(set, x, y, width, height, \"event\");\n\t},\n\t\n\tdrawMultipleStartEvent: function(x, y, width, height, isInterrupting, name) {\n\t  this.g.setStart();\n\t\t\n\t  this._drawStartEvent(x, y, width, height, isInterrupting, null);\n\t\t\n\t\tvar cx = x + width/2 - this.getStroke()/4;\n\t\tvar cy = y + height/2 - this.getStroke()/4;\n\t\t\n\t\tvar w = width*1;\n\t\tvar h = height*1;\n\t\t\n\t\tthis._drawPentagon(cx, cy, w, h);\n\t\t\n\t\tvar set = this.g.setFinish();\n    this.addHandlers(set, x, y, width, height, \"event\");\n\t},\n\t\n\t_drawStartEventImage: function(x, y, width, height, image){\n\t\tvar cx = x + width/2 - this.getStroke()/2;\n\t\tvar cy = y + height/2 - this.getStroke()/2;\n\t\t\n\t\tvar w = width*.65;// - this.getStroke()*2;\n\t\tvar h = height*.65;// - this.getStroke()*2;\n\t\t\n\t\tvar img = this.g.image(image, cx-w/2, cy-h/2, w, h);\n\t},\n\t_drawStartEvent: function(x, y, width, height, isInterrupting){\n\t\tvar originalPaint = this.getPaint();\n\t\tif (typeof(START_EVENT_STROKE_COLOR) != \"undefined\")\n\t\t\tthis.setPaint(START_EVENT_STROKE_COLOR);\n\t\t\n\t\t\n\t\twidth -= this.strokeWidth / 2;\n\t\theight -= this.strokeWidth / 2;\n\t\t\n\t\tx = x + width/2;\n\t\ty = y + height/2;\n\t\t\n\t\tvar circle = this.g.ellipse(x, y, width/2, height/2);\n\t\t\n\t\tcircle.attr({\"stroke-width\": this.strokeWidth, \n\t\t\t\t\"stroke\": this.paint, \n\t\t\t\t//\"stroke\": START_EVENT_STROKE_COLOR,\n\t\t\t\t\"fill\": START_EVENT_COLOR});\n\t\t\t\t\n\t\t// white shaddow\n\t\tthis.drawShaddow(circle);\n\t\t\n\t\tif (isInterrupting!=null && isInterrupting!=undefined && !isInterrupting) \n\t\t\tcircle.attr({\"stroke-dasharray\": NON_INTERRUPTING_EVENT_STROKE});\n\n\t\tthis.setContextToElement(circle);\n\t\t\n\t\t\n\t\tthis.setPaint(originalPaint);\n\t},\n\t\n\t/*\n\t * End Events:\n\t * \n\t *\tdrawNoneEndEvent\n\t *\tdrawErrorEndEvent\n\t *\tdrawMessageEndEvent\n\t *\tdrawSignalEndEvent\n\t *\tdrawMultipleEndEvent\n\t *  _drawEndEventImage\n\t *\t_drawNoneEndEvent\n\t */\n\t \n\tdrawNoneEndEvent: function(x, y, width, height) {\n\t  this.g.setStart();\n\t  \n\t\tthis._drawNoneEndEvent(x, y, width, height, null, \"noneEndEvent\");\n\t\t\n\t\tvar set = this.g.setFinish();\n    this.addHandlers(set, x, y, width, height, \"event\");\n\t},\n\t\n\tdrawErrorEndEvent: function(x, y, width, height) {\n\t  this.g.setStart();\n\t\tvar type = \"errorEndEvent\";\n\t\tthis._drawNoneEndEvent(x, y, width, height, null, type);\n\t\t\n\t\tthis._drawEndEventImage(x, y, width, height, ERROR_THROW_IMAGE);\n\t\t\n\t\tvar set = this.g.setFinish();\n    this.addHandlers(set, x, y, width, height, \"event\");\n\t},\n\t\n\tdrawMessageEndEvent: function(x, y, width, height, name) {\n\t  this.g.setStart();\n\t\tvar type = \"errorEndEvent\";\n\t\tthis._drawNoneEndEvent(x, y, width, height, null, type);\n\t\t\n\t\tthis._drawEndEventImage(x, y, width, height, MESSAGE_THROW_IMAGE);\n\t\t\n\t\tvar set = this.g.setFinish();\n    this.addHandlers(set, x, y, width, height, \"event\");\n\t},\n\t\n\tdrawSignalEndEvent: function(x, y, width, height, name) {\n\t  this.g.setStart();\n\t\tvar type = \"errorEndEvent\";\n\t\tthis._drawNoneEndEvent(x, y, width, height, null, type);\n\t\t\n\t\tthis._drawEndEventImage(x, y, width, height, SIGNAL_THROW_IMAGE);\n\t\t\n\t\tvar set = this.g.setFinish();\n    this.addHandlers(set, x, y, width, height, \"event\");\n\t},\n\t\n\tdrawMultipleEndEvent: function(x, y, width, height, name) {\n\t  this.g.setStart();\n\t\tvar type = \"errorEndEvent\";\n\t\tthis._drawNoneEndEvent(x, y, width, height, null, type);\n\t\t\n\t\tvar cx = x + width/2;// - this.getStroke();\n\t\tvar cy = y + height/2;// - this.getStroke();\n\t\t\n\t\tvar w = width*1;\n\t\tvar h = height*1;\n\t\t\n\t\tvar filled = true;\n\t\tthis._drawPentagon(cx, cy, w, h, filled);\n\t\t\n\t\tvar set = this.g.setFinish();\n    this.addHandlers(set, x, y, width, height, \"event\");\n\t},\n\t\n\tdrawTerminateEndEvent: function(x, y, width, height) {\n\t  this.g.setStart();\n\t\tvar type = \"errorEndEvent\";\n\t\tthis._drawNoneEndEvent(x, y, width, height, null, type);\n\t\t\n\t\tvar cx = x + width/2;// - this.getStroke()/2;\n\t\tvar cy = y + height/2;// - this.getStroke()/2;\n\t\t\n\t\tvar w = width/2*.6;\n\t\tvar h = height/2*.6;\n\t\t\n\t\tvar circle = this.g.ellipse(cx, cy, w, h).attr({fill: Color.black});\n\t\t\n\t\tvar set = this.g.setFinish();\n    this.addHandlers(set, x, y, width, height, \"event\");\n\t},\n\t\n\t_drawEndEventImage: function(x, y, width, height, image){\n\t\tvar cx = x + width/2 - this.getStroke()/2;\n\t\tvar cy = y + height/2 - this.getStroke()/2;\n\t\t\n\t\tvar w = width*.65;\n\t\tvar h = height*.65;\n\t\t\n\t\tvar img = this.g.image(image, cx-w/2, cy-h/2, w, h);\n\t},\n\t\n\t_drawNoneEndEvent: function(x, y, width, height, image, type) {\n\t\tvar originalPaint = this.getPaint();\n\t\tif (typeof(CATCHING_EVENT_COLOR) != \"undefined\")\n\t\t\tthis.setPaint(CATCHING_EVENT_COLOR);\n\t\t\t\n\t\tvar strokeColor = this.getPaint();\n\t\tvar fillColor = this.getPaint();\n\t\t\n\t\tif (type == \"errorEndEvent\") {\n\t\t\tstrokeColor = ERROR_END_EVENT_STROKE_COLOR;\n\t\t\tfillColor = ERROR_END_EVENT_COLOR;\n\t\t} else if (type == \"noneEndEvent\") {\n\t\t\tstrokeColor = NONE_END_EVENT_STROKE_COLOR;\n\t\t\tfillColor = NONE_END_EVENT_COLOR;\n\t\t} else \n\t\t\t\n\t\t// event circles\n\t\twidth -= this.strokeWidth / 2;\n\t\theight -= this.strokeWidth / 2;\n\t\t\n\t\tx = x + width/2;// + this.strokeWidth/2;\n\t\ty = y + width/2;// + this.strokeWidth/2;\n\t\t\n\t\t// outerCircle\n\t\tvar outerCircle = this.g.ellipse(x, y, width/2, height/2);\n\t\t\n\t\t// white shaddow\n\t\tvar shaddow = this.drawShaddow(outerCircle);\n\t\t\n\t\touterCircle.attr({\"stroke-width\": this.strokeWidth,\n\t\t\t\t\t\t\"stroke\": strokeColor,\n\t\t\t\t\t\t\"fill\": fillColor});\n\t\t\n\t\tvar innerCircleX = x;\n\t\tvar innerCircleY = y;\n\t\tvar innerCircleWidth = width/2 - 2;\n\t\tvar innerCircleHeight = height/2 - 2;\n\t\tvar innerCircle = this.g.ellipse(innerCircleX, innerCircleY, innerCircleWidth, innerCircleHeight);\n\t\tinnerCircle.attr({\"stroke-width\": this.strokeWidth,\n\t\t\t\t\"stroke\": strokeColor,\n\t\t\t\t\"fill\": Color.white});\n\n\t\t// TODO: implement it\n\t\t//var originalPaint = this.getPaint();\n\t\t//this.g.setPaint(BOUNDARY_EVENT_COLOR);\n\t\t\n\t\tthis.setPaint(originalPaint);\n\t},\n\t\n\t/*\n\t * Catching Events:\n\t * \n\t *\tdrawCatchingTimerEvent\n\t *\tdrawCatchingErrorEvent\n\t *\tdrawCatchingSignalEvent\n\t *  drawCatchingMessageEvent\n\t *\tdrawCatchingMultipleEvent\n\t *\t_drawCatchingEventImage\n\t *\t_drawCatchingEvent\n\t */\n\t \n\t\n\tdrawCatchingTimerEvent: function(x, y, width, height, isInterrupting, name) {\n\t  this.g.setStart();\n\t\tthis._drawCatchingEvent(x, y, width, height, isInterrupting, null);\n\t\t\n\t\tvar innerCircleWidth = width - 4;\n\t\tvar innerCircleHeight = height - 4;\n\t\t\n\t\tvar cx = x + width/2 - this.getStroke()/4;\n\t\tvar cy = y + height/2 - this.getStroke()/4;\n\t\t\n\t\tvar w = innerCircleWidth*.9;// - this.getStroke()*2;\n\t\tvar h = innerCircleHeight*.9;// - this.getStroke()*2;\n\t\t\n\t\tthis._drawClock(cx, cy, w, h);\n\t\t\n\t\tvar set = this.g.setFinish();\n\t\tthis.addHandlers(set, x, y, width, height, \"event\");\n\t},\n\n\tdrawCatchingErrorEvent: function(x, y, width, height, isInterrupting, name) {\n\t  this.g.setStart();\n\t\tthis._drawCatchingEvent(x, y, width, height, isInterrupting, null);\n\t\t\n\t\tthis._drawCatchingEventImage(x, y, width, height, ERROR_CATCH_IMAGE);\n\t\t\n\t\tvar set = this.g.setFinish();\n    this.addHandlers(set, x, y, width, height, \"event\");\n\t},\n\t\n\tdrawCatchingSignalEvent: function(x, y, width, height, isInterrupting, name) {\n\t  this.g.setStart();\n\t\tthis._drawCatchingEvent(x, y, width, height, isInterrupting, null);\n\t\t\n\t\tthis._drawCatchingEventImage(x, y, width, height, SIGNAL_CATCH_IMAGE);\n\t\t\n\t\tvar set = this.g.setFinish();\n    this.addHandlers(set, x, y, width, height, \"event\");\n\t},\n\t\n\tdrawCatchingMessageEvent: function(x, y, width, height, isInterrupting, name) {\n\t  this.g.setStart();\n\t\tthis._drawCatchingEvent(x, y, width, height, isInterrupting, null);\n\t\t\n\t\tthis._drawCatchingEventImage(x, y, width, height, MESSAGE_CATCH_IMAGE);\n\t\t\n\t\tvar set = this.g.setFinish();\n    this.addHandlers(set, x, y, width, height, \"event\");\n\t},\n\t\n\tdrawCatchingMultipleEvent: function(x, y, width, height, isInterrupting, name) {\n\t  this.g.setStart();\n\t\tthis._drawCatchingEvent(x, y, width, height, isInterrupting, null);\n\t\t\n\t\tvar cx = x + width/2 - this.getStroke();\n\t\tvar cy = y + height/2 - this.getStroke();\n\t\t\n\t\tvar w = width*.9;\n\t\tvar h = height*.9;\n\t\t\n\t\tthis._drawPentagon(cx, cy, w, h);\n\t\t\n\t\tvar set = this.g.setFinish();\n    this.addHandlers(set, x, y, width, height, \"event\");\n\t},\n\t\n\t_drawCatchingEventImage: function(x, y, width, height, image){\n\t\tvar innerCircleWidth = width - 4;\n\t\tvar innerCircleHeight = height - 4;\n\t\t\n\t\tvar cx = x + width/2 - this.getStroke()/2;\n\t\tvar cy = y + height/2 - this.getStroke()/2;\n\t\t\n\t\tvar w = innerCircleWidth*.6;// - this.getStroke()*2;\n\t\tvar h = innerCircleHeight*.6;// - this.getStroke()*2;\n\t\t\n\t\tvar img = this.g.image(image, cx-w/2, cy-h/2, w, h);\n\t},\n\t\n\t_drawCatchingEvent: function(x, y, width, height, isInterrupting, image) {\n\t\tvar originalPaint = this.getPaint();\n\t\tif (typeof(CATCHING_EVENT_COLOR) != \"undefined\")\n\t\t\tthis.setPaint(CATCHING_EVENT_COLOR);\n\t\t\t\n\t\t// event circles\n\t\twidth -= this.strokeWidth / 2;\n\t\theight -= this.strokeWidth / 2;\n\t\t\n\t\tx = x + width/2;// + this.strokeWidth/2;\n\t\ty = y + width/2;// + this.strokeWidth/2;\n\t\t\n\t\t// outerCircle\n\t\tvar outerCircle = this.g.ellipse(x, y, width/2, height/2);\n\t\t\n\t\t// white shaddow\n\t\tvar shaddow = this.drawShaddow(outerCircle);\n\t\t\n\t\t//console.log(\"isInterrupting: \" + isInterrupting, \"x:\" , x, \"y:\",y);\n\t\tif (isInterrupting!=null && isInterrupting!=undefined && !isInterrupting) \n\t\t\touterCircle.attr({\"stroke-dasharray\": NON_INTERRUPTING_EVENT_STROKE});\n\t\t\n\t\touterCircle.attr({\"stroke-width\": this.strokeWidth,\n\t\t\t\t\t\t\"stroke\": this.getPaint(),\n\t\t\t\t\t\t\"fill\": BOUNDARY_EVENT_COLOR});\n\t\t\n\t\tvar innerCircleX = x;\n\t\tvar innerCircleY = y;\n\t\tvar innerCircleRadiusX = width/2 - 4;\n\t\tvar innerCircleRadiusY = height/2 - 4;\n\t\tvar innerCircle = this.g.ellipse(innerCircleX, innerCircleY, innerCircleRadiusX, innerCircleRadiusY);\n\t\tinnerCircle.attr({\"stroke-width\": this.strokeWidth,\n\t\t\t\t\"stroke\": this.getPaint()});\n\n\t\tif (image) {\n\t\t\tvar imageWidth = imageHeight = innerCircleRadiusX*1.2 + this.getStroke()*2;\n\t\t\tvar imageX = innerCircleX-imageWidth/2 - this.strokeWidth/2;\n\t\t\tvar imageY = innerCircleY-imageWidth/2 - this.strokeWidth/2;\n\t\t\tvar img = this.g.image(image, imageX, imageY, imageWidth, imageHeight);\n\t\t}\n\t\t\n\t\tthis.setPaint(originalPaint);\n\t\t\n\t\tvar set = this.g.set();\n\t\tset.push(outerCircle, innerCircle, shaddow);\n\t\tthis.setContextToElement(outerCircle);\n\t\t\n\t\t// TODO: add shapes to set\n\t\t\n\t\t/*\n\t\tvar st = this.g.set();\n\t\tst.push(\n\t\t\tthis.g.ellipse(innerCircleX, innerCircleY, 2, 2),\n\t\t\tthis.g.ellipse(imageX, imageY, 2, 2)\n\t\t);\n\t\tst.attr({fill: \"red\", \"stroke-width\":0});\n\t\t*/\n\t},\n\t\n\t/*\n\t * Catching Events:\n\t * \n\t *\tdrawThrowingNoneEvent\n\t *\tdrawThrowingSignalEvent\n\t *\tdrawThrowingMessageEvent\n\t *\tdrawThrowingMultipleEvent\n\t */\n\t\n\tdrawThrowingNoneEvent: function(x, y, width, height, name) {\n\t  this.g.setStart();\n\t\tthis._drawCatchingEvent(x, y, width, height, null, null);\n\t\t\n\t\tvar set = this.g.setFinish();\n    this.addHandlers(set, x, y, width, height, \"event\");\n\t},\n\t\n\tdrawThrowingSignalEvent: function(x, y, width, height, name) {\n\t  this.g.setStart();\n\t\tthis._drawCatchingEvent(x, y, width, height, null, null);\n\t\t\n\t\tthis._drawCatchingEventImage(x, y, width, height, SIGNAL_THROW_IMAGE);\n\t\t\n\t\tvar set = this.g.setFinish();\n    this.addHandlers(set, x, y, width, height, \"event\");\n\t},\n\t\n\tdrawThrowingMessageEvent: function(x, y, width, height, name) {\n\t  this.g.setStart();\n\t\tthis._drawCatchingEvent(x, y, width, height, null, null);\n\t\t\n\t\tthis._drawCatchingEventImage(x, y, width, height, MESSAGE_THROW_IMAGE);\n\t\t\n\t\tvar set = this.g.setFinish();\n    this.addHandlers(set, x, y, width, height, \"event\");\n\t},\n\t\n\tdrawThrowingMultipleEvent: function(x, y, width, height, name) {\n\t  this.g.setStart();\n\t\tthis._drawCatchingEvent(x, y, width, height, null, null);\n\t\t\n\t\tvar cx = x + width/2 - this.getStroke();\n\t\tvar cy = y + height/2 - this.getStroke();\n\t\t\n\t\tvar w = width*.9;\n\t\tvar h = height*.9;\n\t\t\n\t\tvar filled = true;\n\t\tthis._drawPentagon(cx, cy, w, h, filled);\n\t\t\n\t\tvar set = this.g.setFinish();\n    this.addHandlers(set, x, y, width, height, \"event\");\n\t},\n\t\n\t/*\n\t * Draw flows:\n\t * \n\t *  _connectFlowToActivity\n\t *\t_drawFlow\n\t *\t_drawDefaultSequenceFlowIndicator\n\t *\tdrawSequenceflow\n\t *\tdrawMessageflow\n\t *\tdrawAssociation\n\t *\t_drawCircleTail\n\t *\t_drawArrowHead\n\t *\t_drawConditionalSequenceFlowIndicator\n\t *\tdrawSequenceflowWithoutArrow\n\t */\n\t \n\t_connectFlowToActivity: function(sourceActivityId, destinationActivityId, waypoints){\n\t\tvar sourceActivity = this.g.getById(sourceActivityId);\n\t\tvar destinationActivity = this.g.getById(destinationActivityId);\n\t\tif (sourceActivity == null || destinationActivity == null) {\n\t\t\tif (sourceActivity == null)\n\t\t\t\tconsole.error(\"source activity[\"+sourceActivityId+\"] not found\");\n\t\t\telse\n\t\t\t\tconsole.error(\"destination activity[\"+destinationActivityId+\"] not found\");\n\t\t\treturn null;\n\t\t}\n\t\t\tvar bbSourceActivity = sourceActivity.getBBox()\n\t\t\tvar bbDestinationActivity = destinationActivity.getBBox()\n\t\t\t\n\t\t\tvar path = [];\n\t\t\tvar newWaypoints = [];\n\t\t\tfor(var i = 0; i < waypoints.length; i++){\n\t\t\t\tvar pathType = \"\"\n\t\t\t\tif (i==0)\n\t\t\t\t\tpathType = \"M\";\n\t\t\t\telse \n\t\t\t\t\tpathType = \"L\";\n\t\t\t\t\t\n\t\t\t\tpath.push([pathType, waypoints[i].x, waypoints[i].y]);\n\t\t\t\tnewWaypoints.push({x:waypoints[i].x, y:waypoints[i].y});\n\t\t\t}\n\n\t\t\tvar ninjaPathSourceActivity = this.ninjaPaper.path(sourceActivity.realPath);\n\t\t\tvar ninjaPathDestinationActivity = this.ninjaPaper.path(destinationActivity.realPath);\n\t\t\tvar ninjaBBSourceActivity = ninjaPathSourceActivity.getBBox();\n\t\t\tvar ninjaBBDestinationActivity = ninjaPathDestinationActivity.getBBox();\n\t\t\t\n\t\t\t// set target of the flow to the center of the taskObject\n\t\t\tvar newPath = path;\n\t\t\tvar originalSource = {x: newPath[0][1], y: newPath[0][2]};\n\t\t\tvar originalTarget = {x: newPath[newPath.length-1][1], y: newPath[newPath.length-1][2]};\n\t\t\tnewPath[0][1] = ninjaBBSourceActivity.x + (ninjaBBSourceActivity.x2 - ninjaBBSourceActivity.x ) / 2;\n\t\t\tnewPath[0][2] = ninjaBBSourceActivity.y + (ninjaBBSourceActivity.y2 - ninjaBBSourceActivity.y ) / 2;\n\t\t\tnewPath[newPath.length-1][1] = ninjaBBDestinationActivity.x + (ninjaBBDestinationActivity.x2 - ninjaBBDestinationActivity.x ) / 2;\n\t\t\tnewPath[newPath.length-1][2] = ninjaBBDestinationActivity.y + (ninjaBBDestinationActivity.y2 - ninjaBBDestinationActivity.y ) / 2;\n\t\t\t\n\t\t\tvar ninjaPathFlowObject = this.ninjaPaper.path(newPath);\n\t\t\tvar ninjaBBFlowObject = ninjaPathFlowObject.getBBox();\n\t\t\t\n\t\t\tvar intersectionsSource = Raphael.pathIntersection(ninjaPathSourceActivity.realPath, ninjaPathFlowObject.realPath);\n\t\t\tvar intersectionsDestination = Raphael.pathIntersection(ninjaPathDestinationActivity.realPath, ninjaPathFlowObject.realPath);\n\t\t\tvar intersectionSource = intersectionsSource.pop();\n\t\t\tvar intersectionDestination = intersectionsDestination.pop();\n\t\t\t\n\t\t\tif (intersectionSource != undefined) {\n\t\t\t\tif (this.gebug) {\n\t\t\t\t\tvar diameter = 5;\n\t\t\t\t\tvar dotOriginal = this.g.ellipse(originalSource.x, originalSource.y, diameter, diameter).attr({\"fill\": Color.white, \"stroke\": Color.Pink});\n\t\t\t\t\tvar dot = this.g.ellipse(intersectionSource.x, intersectionSource.y, diameter, diameter).attr({\"fill\": Color.white, \"stroke\": Color.Green});\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tnewWaypoints[0].x = intersectionSource.x;\n\t\t\t\tnewWaypoints[0].y = intersectionSource.y;\n\t\t\t}\n\t\t\tif (intersectionDestination != undefined) {\n\t\t\t\tif (this.gebug) {\n\t\t\t\t\tvar diameter = 5;\n\t\t\t\t\tvar dotOriginal = this.g.ellipse(originalTarget.x, originalTarget.y, diameter, diameter).attr({\"fill\": Color.white, \"stroke\": Color.Red});\n\t\t\t\t\tvar dot = this.g.ellipse(intersectionDestination.x, intersectionDestination.y, diameter, diameter).attr({\"fill\": Color.white, \"stroke\": Color.Blue});\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tnewWaypoints[newWaypoints.length-1].x = intersectionDestination.x;\n\t\t\t\tnewWaypoints[newWaypoints.length-1].y = intersectionDestination.y;\n\t\t\t}\n\t\t\t\n\t\t\tthis.ninjaPaper.clear();\n\t\treturn newWaypoints;\n\t},\n\t \n\t_drawFlow: function(waypoints, conditional, isDefault, highLighted, withArrowHead, connectionType){\n\t\tvar originalPaint = this.getPaint();\n\t\tvar originalStroke = this.getStroke();\n\t\t\n\t\tthis.setPaint(SEQUENCEFLOW_COLOR);\n\t\tthis.setStroke(SEQUENCEFLOW_STROKE);\n\t\t\n\t\tif (highLighted) {\n\t\t\tthis.setPaint(HIGHLIGHT_COLOR);\n\t\t\tthis.setStroke(SEQUENCEFLOW_HIGHLIGHT_STROKE);\n\t\t}\n\n// TODO: generate polylineId or do something!!\n\t\tvar uuid = Raphael.createUUID();\n\t\t\n\t\tvar contextObject = this.getConextObject();\n\t\tvar newWaypoints = waypoints;\n\t\tif (contextObject) {\n\t\t\tvar newWaypoints = this._connectFlowToActivity(contextObject.sourceActivityId, contextObject.destinationActivityId, waypoints);\n\t\t\t\n\t\t\tif (!newWaypoints) {\n\t\t\t\tconsole.error(\"Error draw flow from '\"+contextObject.sourceActivityId+\"' to '\"+contextObject.destinationActivityId+\"' \");\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tvar polyline = new Polyline(uuid, newWaypoints, this.getStroke());\n\t\t//var polyline = new Polyline(waypoints, 3);\n\t\t\n\t\tpolyline.element = this.g.path(polyline.path);\n\t\tpolyline.element.attr(\"stroke-width\", this.getStroke());\n\t\tpolyline.element.attr(\"stroke\", this.getPaint());\n\t\t\t\n\t\tif (contextObject) {\n\t\t\tpolyline.element.id = contextObject.id;\n\t\t\tpolyline.element.data(\"contextObject\", contextObject);\n\t\t} else {\n\t\t\tpolyline.element.id = uuid;\n\t\t}\n\t\t\n\t\t\n\t\t/*\n\t\tpolyline.element.mouseover(function(){\n\t\t\tthis.attr({\"stroke-width\": NORMAL_STROKE + 2});\n\t\t}).mouseout(function(){\n\t\t\tthis.attr({\"stroke-width\": NORMAL_STROKE});\n\t\t});\n\t\t*/\n\t\t\n\t\tvar last = polyline.getAnchorsCount()-1;\n\t\tvar x = polyline.getAnchor(last).x;\n\t\tvar y = polyline.getAnchor(last).y;\n\t\t//var c = this.g.ellipse(x, y, 5, 5);\n\t\t\n\t\tvar lastLineIndex = polyline.getLinesCount()-1;\n\t\tvar line = polyline.getLine(lastLineIndex);\n\t\tvar firstLine = polyline.getLine(0);\n\t\t\n\t\tvar arrowHead = null,\n\t\t\tcircleTail = null,\n\t\t\tdefaultSequenceFlowIndicator = null,\n\t\t\tconditionalSequenceFlowIndicator = null;\n\n\t\tif (connectionType == CONNECTION_TYPE.MESSAGE_FLOW) {\n\t\t\tcircleTail = this._drawCircleTail(firstLine, connectionType);\n\t\t}\n\t\tif(withArrowHead)\n\t\t\tarrowHead = this._drawArrowHead(line, connectionType);\n\t\t\n\t\t//console.log(\"isDefault: \", isDefault, \", isDefaultConditionAvailable: \", polyline.isDefaultConditionAvailable);\n\t\tif (isDefault && polyline.isDefaultConditionAvailable) {\n\t\t\t//var angle = polyline.getLineAngle(0);\n\t\t\t//console.log(\"firstLine\", firstLine);\n\t\t\tdefaultSequenceFlowIndicator = this._drawDefaultSequenceFlowIndicator(firstLine);\n\t\t}\n\t\t\n\t\tif (conditional) {\n\t\t\tconditionalSequenceFlowIndicator = this._drawConditionalSequenceFlowIndicator(firstLine);\n\t\t}\n\n        // draw flow name\n        var flowName = contextObject.name;\n        if (flowName) {\n            var xPointArray = contextObject.xPointArray;\n            var yPointArray = contextObject.yPointArray;\n            var textX = xPointArray[0] < xPointArray[1] ? xPointArray[0] : xPointArray[1];\n            var textY = yPointArray[0] < yPointArray[1] ? yPointArray[1] : yPointArray[0];\n            // fix xy\n            textX += 20;\n            textY -= 10;\n            this.g.text(textX, textY, flowName).attr(LABEL_FONT);\n        }\n\t\t\n\t\tvar st = this.g.set();\n\t\tst.push(polyline.element, arrowHead, circleTail, conditionalSequenceFlowIndicator);\n\t\tpolyline.element.data(\"set\", st);\n\t\tpolyline.element.data(\"withArrowHead\", withArrowHead);\n\t\t\n\t\tvar polyCloneAttrNormal = {\"stroke-width\": this.getStroke() + 5, stroke: Color.get(132,112,255), opacity: 0.0, cursor: \"hand\"};\n\t\tvar polyClone = st.clone().attr(polyCloneAttrNormal).hover(function () {\n\t\t\t\t//if (polyLine.data(\"isSelected\")) return;\n\t\t\t\tpolyClone.attr({opacity: 0.2});\n\t\t\t}, function () {\n\t\t\t\t//if (polyLine.data(\"isSelected\")) return;\n\t\t\t\tpolyClone.attr({opacity: 0.0});\n\t\t\t});\n\t\tpolyClone.data(\"objectId\", polyline.element.id);\n\t\tpolyClone.click(function(){\n\t\t\tvar instance = this;\n\t\t\tvar objectId = instance.data(\"objectId\");\n\t\t\tvar object = this.paper.getById(objectId);\n\t\t\tvar contextObject = object.data(\"contextObject\");\n\t\t\tif (contextObject) {\n\t\t\t\tconsole.log(\"[flow], objectId: \" + object.id +\", flow: \" + contextObject.flow);\n\t\t\t\tProcessDiagramGenerator.showFlowInfo(contextObject);\n\t\t\t}\n\t\t}).dblclick(function(){\n\t\t\tconsole.log(\"!!! DOUBLE CLICK !!!\");\n\t\t}).hover(function (mouseEvent) {\n\t\t\tvar instance = this;\n\t\t\tvar objectId = instance.data(\"objectId\");\n\t\t\tvar object = this.paper.getById(objectId);\n\t\t\tvar contextObject = object.data(\"contextObject\");\n\t\t\tif (contextObject)\n\t\t\t\tProcessDiagramGenerator.showFlowInfo(contextObject);\n\t\t});\n\t\tpolyClone.data(\"parentId\", uuid);\n\t\t\n\t\tif (!connectionType || connectionType == CONNECTION_TYPE.SEQUENCE_FLOW)\n\t\t\tpolyline.element.attr(\"stroke-width\", this.getStroke());\n\t\telse if (connectionType == CONNECTION_TYPE.MESSAGE_FLOW)\n\t\t\tpolyline.element.attr({\"stroke-dasharray\": \"--\"});\n\t\telse if (connectionType == CONNECTION_TYPE.ASSOCIATION)\n\t\t\tpolyline.element.attr({\"stroke-dasharray\": \". \"});\n\t\t\n\t\tthis.setPaint(originalPaint);\n\t\tthis.setStroke(originalStroke);\n\t},\n\t\n\t_drawDefaultSequenceFlowIndicator: function(line) {\n\t\t//console.log(\"line: \", line);\n\t\t\n\t\tvar len = 10; c = len/2, f = 8;\n\t\tvar defaultIndicator = this.g.path(\"M\" + (-c) + \" \" + 0 + \"L\" + (c) + \" \" + 0);\n\t\tdefaultIndicator.attr(\"stroke-width\", this.getStroke()+0);\n\t\tdefaultIndicator.attr(\"stroke\", this.getPaint());\n\t\t\n\t\t\n\t\tvar cosAngle = Math.cos((line.angle));\n\t\tvar sinAngle = Math.sin((line.angle));\n\t\t\n\t\tvar dx = f * cosAngle;\n\t\tvar dy = f * sinAngle;\n\t\t\n\t\tvar x1 = line.x1 + dx + 0*c*cosAngle;\n\t\tvar y1 = line.y1 + dy + 0*c*sinAngle;\n\t\t\n\t\tdefaultIndicator.transform(\"t\" + (x1) + \",\" + (y1) + \"\");\n\t\tdefaultIndicator.transform(\"...r\" + Raphael.deg(line.angle - 3*Math.PI / 4) + \" \" + 0 + \" \" + 0);\n\t\t/*\n\t\tvar c0 = this.g.ellipse(0, 0, 1, 1).attr({stroke: Color.Blue});\n\t\tc0.transform(\"t\" + (line.x1) + \",\" + (line.y1) + \"\");\n\t\tvar center = this.g.ellipse(0, 0, 1, 1).attr({stroke: Color.Red});\n\t\tcenter.transform(\"t\" + (line.x1+dx) + \",\" + (line.y1+dy) + \"\");\n\t\t*/\n\t\t\n\t\treturn defaultIndicator;\n\t},\n\t\n\tdrawSequenceflow: function(waypoints, conditional, isDefault, highLighted) {\n\t\tvar withArrowHead = true;\n\t\tthis._drawFlow(waypoints, conditional, isDefault, highLighted, withArrowHead, CONNECTION_TYPE.SEQUENCE_FLOW);\n\t},\n\t\n\tdrawMessageflow: function(waypoints, highLighted) {\n\t\tvar withArrowHead = true;\n\t\tvar conditional=isDefault=false;\n\t\tthis._drawFlow(waypoints, conditional, isDefault, highLighted, withArrowHead, CONNECTION_TYPE.MESSAGE_FLOW);\n\t},\n\t\n\tdrawAssociation: function(waypoints, withArrowHead, highLighted) {\n\t\tvar withArrowHead = withArrowHead;\n\t\tvar conditional=isDefault=false;\n\t\tthis._drawFlow(waypoints, conditional, isDefault, highLighted, withArrowHead, CONNECTION_TYPE.ASSOCIATION);\n\t},\n  \n\t_drawCircleTail: function(line, connectionType){\n\t\tvar diameter = ARROW_WIDTH/2*1.5;\n\t\t\n\t\t// anti smoothing\n\t\tif (this.strokeWidth%2 == 1)\n\t\t\tline.x1 += .5, line.y1 += .5;\n\t\t\n\t\tvar circleTail = this.g.ellipse(line.x1, line.y1, diameter, diameter);\n\t\tcircleTail.attr(\"fill\", Color.white);\n\t\tcircleTail.attr(\"stroke\", this.getPaint());\n\t\t\n\t\treturn circleTail;\n\t},\n\t\n\t_drawArrowHead: function(line, connectionType){\n\t\tvar doubleArrowWidth = 2 * ARROW_WIDTH;\n\t\t\n\t\tif (connectionType == CONNECTION_TYPE.ASSOCIATION)\n\t\t\tvar arrowHead = this.g.path(\"M-\" + (ARROW_WIDTH/2+.5) + \" -\" + doubleArrowWidth + \"L 0 0 L\" + (ARROW_WIDTH/2+.5) + \" -\" + doubleArrowWidth);\n\t\telse\n\t\t\tvar arrowHead = this.g.path(\"M0 0L-\" + (ARROW_WIDTH/2+.5) + \" -\" + doubleArrowWidth + \"L\" + (ARROW_WIDTH/2+.5) + \" -\" + doubleArrowWidth + \"z\");\n\t\t\n\t\t//arrowHead.transform(\"t\" + 0 + \",-\" + this.getStroke() + \"\");\n\t\t\n\t\t// anti smoothing\n\t\tif (this.strokeWidth%2 == 1)\n\t\t\tline.x2 += .5, line.y2 += .5;\n\t\t\n\t\tarrowHead.transform(\"t\" + line.x2 + \",\" + line.y2 + \"\");\n\t\tarrowHead.transform(\"...r\" + Raphael.deg(line.angle - Math.PI / 2) + \" \" + 0 + \" \" + 0);\n\t\t\n\t\tif (!connectionType || connectionType == CONNECTION_TYPE.SEQUENCE_FLOW)\n\t\t\tarrowHead.attr(\"fill\", this.getPaint());\n\t\telse if (connectionType == CONNECTION_TYPE.MESSAGE_FLOW)\n\t\t\tarrowHead.attr(\"fill\", Color.white);\n\t\t\t\n\t\tarrowHead.attr(\"stroke-width\", this.getStroke());\n\t\tarrowHead.attr(\"stroke\", this.getPaint());\n\t\t\n\t\treturn arrowHead;\n\t},\n\t\n\t/*\n\tdrawArrowHead2: function(srcX, srcY, targetX, targetY) {\n\t\tvar doubleArrowWidth = 2 * ARROW_WIDTH;\n\t\t\n\t\t//var arrowHead = this.g.path(\"M-\" + ARROW_WIDTH/2 + \" -\" + doubleArrowWidth + \"L0 0\" + \"L\" + ARROW_WIDTH/2 + \" -\" + doubleArrowWidth + \"z\");\n\t\t\n\t\tvar arrowHead = this.g.path(\"M0 0L-\" + ARROW_WIDTH/1.5 + \" -\" + doubleArrowWidth + \"L\" + ARROW_WIDTH/1.5 + \" -\" + doubleArrowWidth + \"z\");\n\t\t//var c = DefaultProcessDiagramCanvas.g.ellipse(0, 0, 3, 3);\n\t\t//c.transform(\"t\"+targetX+\",\"+targetY+\"\");\n\t\t\n\t\tvar angle = Math.atan2(targetY - srcY, targetX - srcX);\n\t\t\n\t\tarrowHead.transform(\"t\"+targetX+\",\"+targetY+\"\");\n\t\tarrowHead.transform(\"...r\" + Raphael.deg(angle - Math.PI / 2) + \" \"+0+\" \"+0);\n\t\t\n\t\t//console.log(arrowHead.transform());\n\t\t//console.log(\"--> \" + Raphael.deg(angle - Math.PI / 2));\n\t\t\n\t\tarrowHead.attr(\"fill\", this.getPaint());\n\t\tarrowHead.attr(\"stroke\", this.getPaint());\n\t\t\n\t\t/ *\n\t\t// shaddow\n\t\tvar c0 = arrowHead.clone();\n\t\tc0.transform(\"...t-1 1\");\n\t\tc0.attr(\"stroke-width\", this.strokeWidth);\n\t\tc0.attr(\"stroke\", Color.black);\n\t\tc0.attr(\"opacity\", 0.15);\n\t\tc0.toBack();\n\t\t* /\n\t},\n\t*/\n\t\n\t_drawConditionalSequenceFlowIndicator: function(line){\n\t\tvar horizontal = (CONDITIONAL_INDICATOR_WIDTH * 0.7);\n\t\tvar halfOfHorizontal = horizontal / 2;\n\t\tvar halfOfVertical = CONDITIONAL_INDICATOR_WIDTH / 2;\n\n\t\tvar uuid = null;\n\t\tvar waypoints = [{x: 0, y: 0},\n\t\t\t\t\t\t{x: -halfOfHorizontal, y: halfOfVertical},\n\t\t\t\t\t\t{x: 0, y: CONDITIONAL_INDICATOR_WIDTH},\n\t\t\t\t\t\t{x: halfOfHorizontal, y: halfOfVertical}];\n\t\t/*\n\t\tvar polyline = new Polyline(uuid, waypoints, this.getStroke());\n\t\tpolyline.element = this.g.path(polyline.path);\n\t\tpolyline.element.attr(\"stroke-width\", this.getStroke());\n\t\tpolyline.element.attr(\"stroke\", this.getPaint());\n\t\tpolyline.element.id = uuid;\n\t\t*/\n\t\tvar polygone = new Polygone(waypoints, this.getStroke());\n\t\tpolygone.element = this.g.path(polygone.path);\n\t\tpolygone.element.attr(\"fill\", Color.white);\n\t\t\n\t\tpolygone.transform(\"t\" + line.x1 + \",\" + line.y1 + \"\");\n\t\tpolygone.transform(\"...r\" + Raphael.deg(line.angle - Math.PI / 2) + \" \" + 0 + \" \" + 0);\n\t\t\n\t\t\n\t\tvar cosAngle = Math.cos((line.angle));\n\t\tvar sinAngle = Math.sin((line.angle));\n\t\t\n\t\t//polygone.element.attr(\"stroke-width\", this.getStroke());\n\t\t//polygone.element.attr(\"stroke\", this.getPaint());\n\t\t\n\t\tpolygone.attr({\"stroke-width\": this.getStroke(), \"stroke\": this.getPaint()});\n\t\t\n\t\treturn polygone.element;\n\t},\n  \n\tdrawSequenceflowWithoutArrow: function(waypoints, conditional, isDefault, highLighted) {\n\t\tvar withArrowHead = false;\n\t\tthis._drawFlow(waypoints, conditional, isDefault, highLighted, withArrowHead, CONNECTION_TYPE.SEQUENCE_FLOW);\n\t},\n\t\n\t/*\n\t * Draw artifacts\n\t */\n\t\n\tdrawPoolOrLane: function(x, y, width, height, name){\n\t\t// anti smoothing\n\t\tif (this.strokeWidth%2 == 1)\n\t\t\tx = Math.round(x) + .5, y = Math.round(y) + .5;\n\t\t\n\t\t// shape\n\t\tvar rect = this.g.rect(x, y, width, height);\n\t\tvar attr = {\"stroke-width\": NORMAL_STROKE, stroke: TASK_STROKE_COLOR};\n\t\trect.attr(attr);\n\t\t\n\t\t// Add the name as text, vertical\n\t\tif(name != null && name.length > 0) {\n\t\t\tvar attr = POOL_LANE_FONT;\n\t\t\t\n\t\t\t// Include some padding\n\t\t\tvar availableTextSpace = height - 6;\n\t\t\t\n\t\t\t// Create rotation for derived font\n\t\t\tvar truncated = this.fitTextToWidth(name, availableTextSpace);\n\t\t\tvar realWidth = this.getStringWidth(truncated, attr);\n\t\t\tvar realHeight = this.getStringHeight(truncated, attr);\n\t\t\t\n\t\t\t//console.log(\"truncated:\", truncated, \", height:\", height, \", realHeight:\", realHeight, \", availableTextSpace:\", availableTextSpace, \", realWidth:\", realWidth);\n\t\t\tvar newX = x + 2 + realHeight*1 - realHeight/2;\n\t\t\tvar newY = 3 + y + availableTextSpace - (availableTextSpace - realWidth) / 2 - realWidth/2;\n\t\t\tvar textElement = this.g.text(newX, newY, truncated).attr(attr);\n\t\t\t//console.log(\".getBBox(): \", t.getBBox());\n\t\t\ttextElement.transform(\"r\" + Raphael.deg(270 * Math.PI/180) + \" \" + newX + \" \" + newY);\n\t\t}\n\t\t\n\t\t// TODO: add to set\n\t},\n\t\n\t_drawTask: function(name, x, y, width, height, thickBorder) {\n\t\tvar originalPaint = this.getPaint();\n\t\tthis.setPaint(TASK_COLOR);\n\t\t\n\t\t// anti smoothing\n\t\tif (this.strokeWidth%2 == 1)\n\t\t\tx = Math.round(x) + .5, y = Math.round(y) + .5;\n\t\t\n\t\t// shape\n\t\tvar shape = this.g.rect(x, y, width, height, TASK_CORNER_ROUND);\n\t\tvar attr = {\"stroke-width\": this.strokeWidth, stroke: TASK_STROKE_COLOR, fill: this.getPaint()};\n\t\tshape.attr(attr);\n\t\t//shape.attr({fill: \"90-\"+this.getPaint()+\"-\" + Color.get(250, 250, 244)});\n\t\t\n\t\tvar contextObject = this.getConextObject();\n\t\tif (contextObject) {\n\t\t\tshape.id = contextObject.id;\n\t\t\tshape.data(\"contextObject\", contextObject);\n\t\t}\n\t\t\n\t\t//var activity = this.getConextObject();\n\t\t//console.log(\"activity: \" + activity.getId(), activity);\n\t\t//Object.clone(activity);\n\t\t\n\t\t/*\n\t\tc.mouseover(function(){\n\t\t\tthis.attr({\"stroke-width\": NORMAL_STROKE + 2});\n\t\t}).mouseout(function(){\n\t\t\tthis.attr({\"stroke-width\": NORMAL_STROKE});\n\t\t});\n\t\t*/\n\t\t\n\t\tthis.setPaint(originalPaint);\n\n\t\t// white shaddow\n\t\tthis.drawShaddow(shape);\n\t\t\n\t\t\n\t\tif (thickBorder) {\n\t\t\tshape.attr({\"stroke-width\": THICK_TASK_BORDER_STROKE});\n\t\t} else {\n\t\t\t//g.draw(rect);\n\t\t}\n\t\t\n\t\t// text\n\t\tif (name) {\n\t\t\tvar fontAttr = TASK_FONT;\n\t\t\t\n\t\t\t// Include some padding\n\t\t\tvar paddingX = 5;\n\t\t\tvar paddingY = 5;\n\t\t\tvar availableTextSpace = width - paddingX*2;\n\t\t\t\n\t\t\t// TODO: this.setFont\n\t\t\t// var originalFont = this.getFont();\n\t\t\t// this.setFont(TASK_FONT)\n\t\t\t/*\n\t\t\tvar truncated = this.fitTextToWidth(name, availableTextSpace);\n\t\t\tvar realWidth = this.getStringWidth(truncated, fontAttr);\n\t\t\tvar realHeight = this.getStringHeight(truncated, fontAttr);\n\t\t\t\n\t\t\t//var t = this.g.text(x + width/2 + realWidth*0/2 + paddingX*0, y + height/2, truncated).attr(fontAttr);\n\t\t\t*/\n\t\t\t//console.log(\"draw task name: \" + name);\n\t\t\tvar boxWidth = width - (2 * TEXT_PADDING);\n\t\t\tvar boxHeight = height - ICON_SIZE - ICON_PADDING - ICON_PADDING - MARKER_WIDTH - 2 - 2;\n\t\t\tvar boxX = x + width/2 - boxWidth/2;\n\t\t\tvar boxY = y + height/2 - boxHeight/2 + ICON_PADDING + ICON_PADDING - 2 - 2;\n\t\t\t/*\n\t\t\tvar boxWidth = width - (2 * ANNOTATION_TEXT_PADDING);\n\t\t\tvar boxHeight = height - (2 * ANNOTATION_TEXT_PADDING);\n\t\t\tvar boxX = x + width/2 - boxWidth/2;\n\t\t\tvar boxY = y + height/2 - boxHeight/2;\n\t\t\t*/\n\t\t\t\n\t\t\tthis.drawTaskLabel(name, boxX, boxY, boxWidth, boxHeight);\n\t\t}\n\t},\n\t\n\tdrawTaskLabel: function(text, x, y, boxWidth, boxHeight){\n\t\tvar originalFont = this.getFont();\n\t\tthis.setFont(TASK_FONT);\n\t\t\t\n\t\tthis._drawMultilineText(text, x, y, boxWidth, boxHeight, MULTILINE_VERTICAL_ALIGN_MIDDLE, MULTILINE_HORIZONTAL_ALIGN_MIDDLE);\n\t\t\n\t\tthis.setFont(originalFont);\n\t},\n\t\n\tdrawAnnotationText: function(text, x, y, width, height){\n\t\t//this._drawMultilineText(text, x, y, width, height, \"start\");\n\t\t\n\t\tvar originalPaint = this.getPaint();\n\t\tvar originalFont = this.getFont();\n\t\t\n\t\tthis.setPaint(Color.black);\n\t\tthis.setFont(TASK_FONT);\n\t\t\t\n\t\tthis._drawMultilineText(text, x, y, width, height, MULTILINE_VERTICAL_ALIGN_TOP, MULTILINE_HORIZONTAL_ALIGN_LEFT);\n\t\t\n\t\tthis.setPaint(originalPaint);\n\t\tthis.setFont(originalFont);\n\t},\n\t\n\tdrawLabel: function(text, x, y, width, height){\n\t\t//this._drawMultilineText(text, x, y, width, height, \"start\");\n\t\t\n\t\tvar originalPaint = this.getPaint();\n\t\tvar originalFont = this.getFont();\n\t\t\n\t\tthis.setPaint(LABEL_COLOR);\n\t\t//this.setFont(LABEL_FONT);\n\t\tthis.setFont(LABEL_FONT_SMOOTH);\n\t\t\n\t\t// predefined box width for labels\n\t\t// TODO: use label width as is, but not height (for stretching)\n\t\tif (!width || !height) {\n\t\t  width = 100;\n\t\t  height = 0;\n\t\t}\n\t\t\n\t\t// TODO: remove it. It is debug\n\t\tx = x - width/2;\n\t  \n\t\tthis._drawMultilineText(text, x, y, width, height, MULTILINE_VERTICAL_ALIGN_TOP, MULTILINE_HORIZONTAL_ALIGN_MIDDLE);\n\t\t\n\t\tthis.setPaint(originalPaint);\n\t\tthis.setFont(originalFont);\n\t},\n\t\n\t/*\n\tdrawMultilineLabel: function(text, x, y){\n\t\tvar originalFont = this.getFont();\n\t\tthis.setFont(LABEL_FONT_SMOOTH);\n\t\t\n\t\tvar boxWidth = 80;\n\t\tx = x - boxWidth/2\n\t\t\n\t\tthis._drawMultilineText(text, x, y, boxWidth, null, \"middle\");\n\t\tthis.setFont(originalFont);\n\t},\n\t*/\n\t\n\tgetStringWidth: function(text, fontAttrs){\n\t\tvar textElement = this.g.text(0, 0, text).attr(fontAttrs).hide();\n\t\tvar bb = textElement.getBBox();\n\t\t\n\t\t//console.log(\"string width: \", t.getBBox().width);\n\t\treturn textElement.getBBox().width;\n\t},\n\tgetStringHeight: function(text, fontAttrs){\n\t\tvar textElement = this.g.text(0, 0, text).attr(fontAttrs).hide();\n\t\tvar bb = textElement.getBBox();\n\t\t\n\t\t//console.log(\"string height: \", t.getBBox().height);\n\t\treturn textElement.getBBox().height;\n\t},\n\tfitTextToWidth: function(original, width) {\n\t\tvar text = original;\n\n\t\t// TODO: move attr on parameters\n\t\tvar attr = {font: \"11px Arial\", opacity: 0};\n\t\t\n\t\t// remove length for \"...\"\n\t\tvar dots = this.g.text(0, 0, \"...\").attr(attr).hide();\n\t\tvar dotsBB = dots.getBBox();\n\t\t\n\t\tvar maxWidth = width - dotsBB.width;\n\t\t\n\t\tvar textElement = this.g.text(0, 0, text).attr(attr).hide();\n\t\tvar bb = textElement.getBBox();\n\t\t\n\t\t// it's a little bit incorrect with \"...\"\n\t\twhile (bb.width > maxWidth && text.length > 0) {\n\t\t\ttext = text.substring(0, text.length - 1);\n\t\t\ttextElement.attr({\"text\": text});\n\t\t\tbb = textElement.getBBox();\n\t\t}\n\n\t\t// remove element from paper\n\t\ttextElement.remove();\n\t\t\n\t\tif (text != original) {\n\t\t\ttext = text + \"...\";\n\t\t}\n\n\t\treturn text;\n\t},\n\twrapTextToWidth: function(original, width){\n\t\n\t\t//return original;\n\t\t\n\t\tvar text = original;\n\t\tvar wrappedText = \"\\n\";\n\t\t\n\t\t// TODO: move attr on parameters\n\t\tvar attr = {font: \"11px Arial\", opacity: 0};\n\t\t\n\t\tvar textElement = this.g.text(0, 0, wrappedText).attr(attr).hide();\n\t\tvar bb = textElement.getBBox();\n\t\t\n\t\tvar resultText = \"\";\n\t\tvar i = 0, j = 0;\n\t\twhile (text.length > 0) {\n\t\t\twhile (bb.width < width && text.length>0) {\n\t\t\t\t// remove \"\\n\"\n\t\t\t\twrappedText = wrappedText.substring(0,wrappedText.length-1);\n\t\t\t\t// add new char, add \"\\n\"\n\t\t\t\twrappedText = wrappedText + text.substring(0,1) + \"\\n\";\n\t\t\t\ttext = text.substring(1);\n\t\t\t\t\n\t\t\t\ttextElement.attr({\"text\": wrappedText});\n\t\t\t\tbb = textElement.getBBox();\n\t\t\t\ti++;\n\t\t\t\tif (i>200) break;\n\t\t\t}\n\t\t\t// remove \"\\n\"\n\t\t\twrappedText = wrappedText.substring(0, wrappedText.length - 1);\n\t\t\t\n\t\t\tif (text.length == 0) {\n\t\t\t\tresultText += wrappedText;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\t\t\t// return last char to text\n\t\t\ttext = wrappedText.substring(wrappedText.length-1) + text;\n\t\t\t// remove last char from wrappedText\n\t\t\twrappedText = wrappedText.substring(0, wrappedText.length-1) + \"\\n\";\n\t\t\t\n\t\t\ttextElement.attr({\"text\": wrappedText});\n\t\t\tbb = textElement.getBBox();\n\t\t\t\n\t\t\t//console.log(\">> \", wrappedText, \", \", text);\n\t\t\tresultText += wrappedText;\n\t\t\twrappedText = \"\\n\";\n\t\t\t\n\t\t\tj++;\n\t\t\tif (j>20) break;\n\t\t}\n\t\t// remove element from paper\n\t\ttextElement.remove();\n\t\t\n\t\treturn resultText;\n\t},\n\t\n\twrapTextToWidth2: function(original, width){\n\t\tvar text = original;\n\t\tvar wrappedText = \"\\n\";\n\t\t\n\t\t// TODO: move attr on parameters\n\t\tvar attr = {font: \"11px Arial\", opacity: 0};\n\t\t\n\t\tvar textElement = this.g.text(0, 0, wrappedText).attr(attr).hide();\n\t\tvar bb = textElement.getBBox();\n\t\t\n\t\tvar resultText = \"\";\n\t\tvar i = 0, j = 0;\n\t\twhile (text.length > 0) {\n\t\t\twhile (bb.width < width && text.length>0) {\n\t\t\t\t// remove \"\\n\"\n\t\t\t\twrappedText = wrappedText.substring(0,wrappedText.length-1);\n\t\t\t\t// add new char, add \"\\n\"\n\t\t\t\twrappedText = wrappedText + text.substring(0,1) + \"\\n\";\n\t\t\t\ttext = text.substring(1);\n\t\t\t\t\n\t\t\t\ttextElement.attr({\"text\": wrappedText});\n\t\t\t\tbb = textElement.getBBox();\n\t\t\t\ti++;\n\t\t\t\tif (i>200) break;\n\t\t\t}\n\t\t\t// remove \"\\n\"\n\t\t\twrappedText = wrappedText.substring(0, wrappedText.length - 1);\n\t\t\t\n\t\t\tif (text.length == 0) {\n\t\t\t\tresultText += wrappedText;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\t\t\t// return last char to text\n\t\t\ttext = wrappedText.substring(wrappedText.length-1) + text;\n\t\t\t// remove last char from wrappedText\n\t\t\twrappedText = wrappedText.substring(0, wrappedText.length-1) + \"\\n\";\n\t\t\t\n\t\t\ttextElement.attr({\"text\": wrappedText});\n\t\t\tbb = textElement.getBBox();\n\t\t\t\n\t\t\t//console.log(\">> \", wrappedText, \", \", text);\n\t\t\tresultText += wrappedText;\n\t\t\twrappedText = \"\\n\";\n\t\t\t\n\t\t\tj++;\n\t\t\tif (j>20) break;\n\t\t}\n\t\t// remove element from paper\n\t\ttextElement.remove();\n\t\t\n\t\treturn resultText;\n\t},\n\t\n\tdrawUserTask: function(name, x, y, width, height) {\n\t  this.g.setStart();\n\t\tthis._drawTask(name, x, y, width, height);\n\t\tvar img = this.g.image(USERTASK_IMAGE, x + ICON_PADDING, y + ICON_PADDING, ICON_SIZE, ICON_SIZE);\n\t\tvar set = this.g.setFinish();\n\t\tthis.addHandlers(set, x, y, width, height, \"task\");\n\t},\n\t\n\tdrawScriptTask: function(name, x, y, width, height) {\n\t  this.g.setStart();\n\t\tthis._drawTask(name, x, y, width, height);\n\t\tvar img = this.g.image(SCRIPTTASK_IMAGE, x + ICON_PADDING, y + ICON_PADDING, ICON_SIZE, ICON_SIZE);\n\t\tvar set = this.g.setFinish();\n    this.addHandlers(set, x, y, width, height, \"task\");\n\t},\n\t\n\tdrawServiceTask: function(name, x, y, width, height) {\n\t  this.g.setStart();\n\t\tthis._drawTask(name, x, y, width, height);\n\t\tvar img = this.g.image(SERVICETASK_IMAGE, x + ICON_PADDING, y + ICON_PADDING, ICON_SIZE, ICON_SIZE);\n\t\tvar set = this.g.setFinish();\n    this.addHandlers(set, x, y, width, height, \"task\");\n\t},\n\t\n\tdrawReceiveTask: function(name, x, y, width, height) {\n\t  this.g.setStart();\n\t\tthis._drawTask(name, x, y, width, height);\n\t\tvar img = this.g.image(RECEIVETASK_IMAGE, x + 7, y + 7, ICON_SIZE, ICON_SIZE);\n\t\tvar set = this.g.setFinish();\n    this.addHandlers(set, x, y, width, height, \"task\");\n\t},\n\t\n\tdrawSendTask: function(name, x, y, width, height) {\n\t  this.g.setStart();\n\t\tthis._drawTask(name, x, y, width, height);\n\t\tvar img = this.g.image(SENDTASK_IMAGE, x + 7, y + 7, ICON_SIZE, ICON_SIZE);\n\t\tvar set = this.g.setFinish();\n    this.addHandlers(set, x, y, width, height, \"task\");\n\t},\n\t\n\tdrawManualTask: function(name, x, y, width, height) {\n\t  this.g.setStart();\n\t\tthis._drawTask(name, x, y, width, height);\n\t\tvar img = this.g.image(MANUALTASK_IMAGE, x + 7, y + 7, ICON_SIZE, ICON_SIZE);\n\t\tvar set = this.g.setFinish();\n    this.addHandlers(set, x, y, width, height, \"task\");\n\t},\n\t\n\tdrawBusinessRuleTask: function(name, x, y, width, height) {\n\t  this.g.setStart();\n\t\tthis._drawTask(name, x, y, width, height);\n\t\tvar img = this.g.image(BUSINESS_RULE_TASK_IMAGE, x + 7, y + 7, ICON_SIZE, ICON_SIZE);\n\t\tvar set = this.g.setFinish();\n    this.addHandlers(set, x, y, width, height, \"task\");\n\t},\n\t\n\tdrawExpandedSubProcess: function(name, x, y, width, height, isTriggeredByEvent){\n\t  this.g.setStart();\n\t\t// anti smoothing\n\t\tif (this.strokeWidth%2 == 1)\n\t\t\tx = Math.round(x) + .5, y = Math.round(y) + .5;\n\t\t\n\t\t// shape\n\t\tvar rect = this.g.rect(x, y, width, height, EXPANDED_SUBPROCESS_CORNER_ROUND);\n\t\t\n\t\t// Use different stroke (dashed)\n\t\tif(isTriggeredByEvent) {\n\t\t\trect.attr(EVENT_SUBPROCESS_ATTRS);\n\t\t} else {\n\t\t\trect.attr(EXPANDED_SUBPROCESS_ATTRS);\n\t\t}\n\t\t\n\t\tthis.setContextToElement(rect);\n\t\t\n\t\tvar fontAttr = EXPANDED_SUBPROCESS_FONT;\n\t\t\n\t\t// Include some padding\n\t\tvar paddingX = 10;\n\t\tvar paddingY = 5;\n\t\tvar availableTextSpace = width - paddingX*2;\n\t\t\n\t\tvar truncated = this.fitTextToWidth(name, availableTextSpace);\n\t\tvar realWidth = this.getStringWidth(truncated, fontAttr);\n\t\tvar realHeight = this.getStringHeight(truncated, fontAttr);\n\t\t\n\t\tvar textElement = this.g.text(x + width/2 - realWidth*0/2 + 0*paddingX, y + realHeight/2 + paddingY, truncated).attr(fontAttr);\n\t\t\n\t\tvar set = this.g.setFinish();\n\t\t// TODO: Expanded Sub Process may has specific handlers\n\t\t//this.addHandlers(set, x, y, width, height, \"task\");\n\t},\n\t\n\tdrawCollapsedSubProcess: function(name, x, y, width, height, isTriggeredByEvent) {\n\t  this.g.setStart();\n\t  this._drawCollapsedTask(name, x, y, width, height, false);\n\t  var set = this.g.setFinish();\n    this.addHandlers(set, x, y, width, height, \"task\");\n\t},\n\t\n\tdrawCollapsedCallActivity: function(name, x, y, width, height) {\n\t  this.g.setStart();\n\t\tthis._drawCollapsedTask(name, x, y, width, height, true);\n\t\tvar set = this.g.setFinish();\n    this.addHandlers(set, x, y, width, height, \"task\");\n\t},\n\n\t_drawCollapsedTask: function(name, x, y, width, height, thickBorder) {\n\t\t// The collapsed marker is now visualized separately\n\t\tthis._drawTask(name, x, y, width, height, thickBorder);\n\t},\n\t\n\tdrawCollapsedMarker: function(x, y, width, height){\n\t\t// rectangle\n\t\tvar rectangleWidth = MARKER_WIDTH;\n\t\tvar rectangleHeight = MARKER_WIDTH;\n\t\t\n\t\t// anti smoothing\n\t\tif (this.strokeWidth%2 == 1)\n\t\t\ty += .5;\n\t\t\n\t\tvar rect = this.g.rect(x + (width - rectangleWidth) / 2, y + height - rectangleHeight - 3, rectangleWidth, rectangleHeight);\n\t\t\n\t\t// plus inside rectangle\n\t\tvar cx = rect.attr(\"x\") + rect.attr(\"width\")/2;\n\t\tvar cy = rect.attr(\"y\") + rect.attr(\"height\")/2;\n\t\t\n\t\tvar line = this.g.path(\n\t\t\t\"M\" + cx + \" \" + (cy+2) + \"L\" + cx + \" \" + (cy-2) + \n\t\t\t\"M\" + (cx-2) + \" \" + cy + \"L\" + (cx+2) + \" \" + cy\n\t\t).attr({\"stroke-width\": this.strokeWidth});\n\t\t\n\t},\n\t\n\tdrawActivityMarkers: function(x, y, width, height, multiInstanceSequential, multiInstanceParallel, collapsed){\n\t\tif (collapsed) {\n\t\t\tif (!multiInstanceSequential && !multiInstanceParallel) {\n\t\t\t\tthis.drawCollapsedMarker(x, y, width, height);\n\t\t\t} else {\n\t\t\t\tthis.drawCollapsedMarker(x - MARKER_WIDTH / 2 - 2, y, width, height);\n\t\t\t\tif (multiInstanceSequential) {\n\t\t\t\t\tconsole.log(\"is collapsed and multiInstanceSequential\");\n\t\t\t\t\tthis.drawMultiInstanceMarker(true, x + MARKER_WIDTH / 2 + 2, y, width, height);\n\t\t\t\t} else if (multiInstanceParallel) {\n\t\t\t\t\tconsole.log(\"is collapsed and multiInstanceParallel\");\n\t\t\t\t\tthis.drawMultiInstanceMarker(false, x + MARKER_WIDTH / 2 + 2, y, width, height);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tif (multiInstanceSequential) {\n\t\t\t\tconsole.log(\"is multiInstanceSequential\");\n\t\t\t\tthis.drawMultiInstanceMarker(true, x, y, width, height);\n\t\t\t} else if (multiInstanceParallel) {\n\t\t\t\tconsole.log(\"is multiInstanceParallel\");\n\t\t\t\tthis.drawMultiInstanceMarker(false, x, y, width, height);\n\t\t\t}\n\t\t}\n\t},\n\t\n\tdrawGateway: function(x, y, width, height) {\n\t\t\n\t\tvar rhombus = this.g.path(\t\"M\" + x + \" \" + (y + (height / 2)) + \n\t\t\t\t\t\t\t\t\t\"L\" + (x + (width / 2)) + \" \" + (y + height) + \n\t\t\t\t\t\t\t\t\t\"L\" + (x + width) + \" \" + (y + (height / 2)) +\n\t\t\t\t\t\t\t\t\t\"L\" + (x + (width / 2)) + \" \" + y +\n\t\t\t\t\t\t\t\t\t\"z\"\n\t\t\t\t\t\t\t\t);\n\t\t\n\t\t// white shaddow\n\t\tthis.drawShaddow(rhombus);\n\t\t\n\t\trhombus.attr(\"stroke-width\", this.strokeWidth);\n\t\trhombus.attr(\"stroke\", Color.SlateGrey);\n\t\trhombus.attr({fill: Color.white});\n\t\t\n\t\tthis.setContextToElement(rhombus);\n\t\t\n\t\treturn rhombus;\n\t},\n\t\n\tdrawParallelGateway: function(x, y, width, height) {\n\t  this.g.setStart();\n\t  \n\t\t// rhombus\n\t\tthis.drawGateway(x, y, width, height);\n\n\t\t// plus inside rhombus\n\t\tvar originalStroke = this.getStroke();\n\t\tthis.setStroke(GATEWAY_TYPE_STROKE);\n\t\t\n\t\tvar plus = this.g.path(\n\t\t\t\"M\" + (x + 10) + \" \" + (y + height / 2) + \"L\" + (x + width - 10) + \" \" + (y + height / 2) +\t// horizontal\n\t\t\t\"M\" + (x + width / 2) + \" \" + (y + height - 10) + \"L\" + (x + width / 2) + \" \" + (y + 10)\t// vertical\n\t\t);\n\t\tplus.attr({\"stroke-width\": this.getStroke(), \"stroke\": this.getPaint()});\n\t\t\n\t\tthis.setStroke(originalStroke);\n\t\t\n\t\tvar set = this.g.setFinish();\n\t\tthis.addHandlers(set, x, y, width, height, \"gateway\");\n\t},\n\t\n\tdrawExclusiveGateway: function(x, y, width, height) {\n\t  this.g.setStart();\n\t  \n\t\t// rhombus\n\t\tvar rhombus = this.drawGateway(x, y, width, height);\n\n\t\tvar quarterWidth = width / 4;\n\t\tvar quarterHeight = height / 4;\n\t\t\n\t\t// X inside rhombus\n\t\tvar originalStroke = this.getStroke();\n\t\tthis.setStroke(GATEWAY_TYPE_STROKE);\n\t\t\n\t\tvar iks = this.g.path(\n\t\t\t\"M\" + (x + quarterWidth + 3) + \" \" + (y + quarterHeight + 3) + \"L\" + (x + 3 * quarterWidth - 3) + \" \" + (y + 3 * quarterHeight - 3) + \n\t\t\t\"M\" + (x + quarterWidth + 3) + \" \" + (y + 3 * quarterHeight - 3) + \"L\" + (x + 3 * quarterWidth - 3) + \" \" + (y + quarterHeight + 3)\n\t\t);\n\t\tiks.attr({\"stroke-width\": this.getStroke(), \"stroke\": this.getPaint()});\n\t\t\n\t\tthis.setStroke(originalStroke);\n\t\t\n\t\tvar set = this.g.setFinish();\n    this.addHandlers(set, x, y, width, height, \"gateway\");\n\t},\n\t\n\tdrawInclusiveGateway: function(x, y, width, height){\n\t  this.g.setStart();\n\t  \n\t\t// rhombus\n\t\tthis.drawGateway(x, y, width, height);\n\t\t\n\t\tvar diameter = width / 4;\n\t\t\n\t\t// circle inside rhombus\n\t\tvar originalStroke = this.getStroke();\n\t\tthis.setStroke(GATEWAY_TYPE_STROKE);\n\t\tvar circle = this.g.ellipse(width/2 + x, height/2 + y, diameter, diameter);\n\t\tcircle.attr({\"stroke-width\": this.getStroke(), \"stroke\": this.getPaint()});\n\t\t\n\t\tthis.setStroke(originalStroke);\n\t\t\n\t\tvar set = this.g.setFinish();\n    this.addHandlers(set, x, y, width, height, \"gateway\");\n\t},\n\t\n\tdrawEventBasedGateway: function(x, y, width, height){\n\t  this.g.setStart();\n\t  \n\t\t// rhombus\n\t\tthis.drawGateway(x, y, width, height);\n\t\t\n\t\tvar diameter = width / 2;\n\n\t    // rombus inside rhombus\n\t    var originalStroke = this.getStroke();\n\t\tthis.setStroke(GATEWAY_TYPE_STROKE);\n\t    \n\t    \n\t    // draw GeneralPath (polygon)\n\t    var n=5;\n\t    var angle = 2*Math.PI/n;\n\t    var x1Points = [];\n\t    var y1Points = [];\n\t\t\n\t\tfor ( var index = 0; index < n; index++ ) {\n\t\t\tvar v = index*angle - Math.PI/2;\n\t\t\tx1Points[index] = x + parseInt(Math.round(width/2)) + parseInt(Math.round((width/4)*Math.cos(v)));\n        \ty1Points[index] = y + parseInt(Math.round(height/2)) + parseInt(Math.round((height/4)*Math.sin(v)));\n\t\t}\n\t\t//g.drawPolygon(x1Points, y1Points, n);\n\t\t\n\t\tvar path = \"\";\n\t\tfor ( var index = 0; index < n; index++ ) {\n\t\t\tif (index == 0) \n\t\t\t\tpath += \"M\";\n\t\t\telse \n\t\t\t\tpath += \"L\";\n\t\t\tpath += x1Points[index] + \",\" + y1Points[index];\n\t\t}\n\t\tpath += \"z\";\n\t\tvar polygone = this.g.path(path);\n\t\tpolygone.attr(\"stroke-width\", this.strokeWidth);\n\t\tpolygone.attr(\"stroke\", this.getPaint());\n\t\t\n\t\tthis.setStroke(originalStroke);\n\t\t\n\t\tvar set = this.g.setFinish();\n    this.addHandlers(set, x, y, width, height, \"gateway\");\n\t},\n\t\n\t/*\n\t*  drawMultiInstanceMarker\n\t*  drawHighLight\n\t*  highLightFlow\n\t*/\n\t\n\tdrawMultiInstanceMarker: function(sequential, x, y, width, height) {\n\t\tvar rectangleWidth = MARKER_WIDTH;\n\t\tvar rectangleHeight = MARKER_WIDTH;\n\t\t\n\t\t// anti smoothing\n\t\tif (this.strokeWidth%2 == 1)\n\t\t\tx += .5;//, y += .5;\n\t\t\t\n\t\tvar lineX = x + (width - rectangleWidth) / 2;\n\t\tvar lineY = y + height - rectangleHeight - 3;\n\t\t\n\t\tvar originalStroke = this.getStroke();\n\t\tthis.setStroke(MULTI_INSTANCE_STROKE);\n\t\t\n\t\tif (sequential) {\n\t\t\tvar line = this.g.path(\n\t\t\t\t\"M\" + lineX + \" \" + lineY + \t\t\t\t\t\t\t\"L\" + (lineX + rectangleWidth) + \" \" + lineY + \n\t\t\t\t\"M\" + lineX + \" \" + (lineY + rectangleHeight / 2) + \t\"L\" + (lineX + rectangleWidth) + \" \" + (lineY + rectangleHeight / 2) + \n\t\t\t\t\"M\" + lineX + \" \" + (lineY + rectangleHeight) + \t\t\"L\" + (lineX + rectangleWidth) + \" \" + (lineY + rectangleHeight)\n\t\t\t).attr({\"stroke-width\": this.strokeWidth});\n\t\t} else {\n\t\t\tvar line = this.g.path(\n\t\t\t\t\"M\" + lineX + \" \" + \t\t\t\t\t\t\tlineY + \"L\" + lineX + \" \" + \t\t\t\t\t(lineY + rectangleHeight) +\n\t\t\t\t\"M\" + (lineX + rectangleWidth / 2) + \" \" + \tlineY + \"L\" + (lineX + rectangleWidth / 2) + \" \" + \t(lineY + rectangleHeight) + \n\t\t\t\t\"M\" + (lineX + rectangleWidth) + \" \" + \t\tlineY + \"L\" + (lineX + rectangleWidth) + \" \" + \t\t(lineY + rectangleHeight)\n\t\t\t).attr({\"stroke-width\": this.strokeWidth});\n\t\t}\n\t\t\n\t\tthis.setStroke(originalStroke);\n\t},\n\t\n\tdrawHighLight: function(x, y, width, height){\n\t\tvar originalPaint = this.getPaint();\n\t\tvar originalStroke = this.getStroke();\n\t\t\n\t\tthis.setPaint(HIGHLIGHT_COLOR);\n\t\tthis.setStroke(THICK_TASK_BORDER_STROKE);\n\n\t\t//var c = this.g.rect(x - width/2 - THICK_TASK_BORDER_STROKE, y - height/2 - THICK_TASK_BORDER_STROKE, width + THICK_TASK_BORDER_STROKE*2, height + THICK_TASK_BORDER_STROKE*2, 5);\n\t\tvar rect = this.g.rect(x - THICK_TASK_BORDER_STROKE, y - THICK_TASK_BORDER_STROKE, width + THICK_TASK_BORDER_STROKE*2, height + THICK_TASK_BORDER_STROKE*2, TASK_CORNER_ROUND);\n\t\trect.attr(\"stroke-width\", this.strokeWidth);\n\t\trect.attr(\"stroke\", this.getPaint());\n\t\t\n\t\tthis.setPaint(originalPaint);\n\t\tthis.setStroke(originalStroke);\n\t},\n\t\n\thighLightActivity: function(activityId){\n\t\tvar shape = this.g.getById(activityId);\n\t\tif (!shape) {\n\t\t\tconsole.error(\"Activity \" + activityId + \" not found\");\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tvar contextObject = shape.data(\"contextObject\");\n\t\tif (contextObject)\n\t\t\tconsole.log(\"--> highLightActivity: [\"+contextObject.getProperty(\"type\")+\"], activityId: \" + contextObject.getId());\n\t\telse\n\t\t\tconsole.log(\"--> highLightActivity: \", shape, shape.data(\"contextObject\"));\n\t\t\n\t\tshape.attr(\"stroke-width\", THICK_TASK_BORDER_STROKE);\n\t\tshape.attr(\"stroke\", HIGHLIGHT_COLOR);\n\t},\n\t\n\thighLightFlow: function(flowId){\n\t\tvar shapeFlow = this.g.getById(flowId);\n\t\tif (!shapeFlow) {\n\t\t\tconsole.error(\"Flow \" + flowId + \" not found\");\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tvar contextObject = shapeFlow.data(\"contextObject\");\n\t\tif (contextObject)\n\t\t\tconsole.log(\"--> highLightFlow: [\"+contextObject.id+\"] \" + contextObject.flow);\n\t\t//console.log(\"--> highLightFlow: \", flow.flow, flow.data(\"set\"));\n\t\t\n\t\tvar st = shapeFlow.data(\"set\");\n\t\t\n\t\tst.attr(\"stroke-width\", SEQUENCEFLOW_HIGHLIGHT_STROKE);\n\t\tst.attr(\"stroke\", HIGHLIGHT_COLOR);\n\t\tvar withArrowHead = shapeFlow.data(\"withArrowHead\");\n\t\tif (withArrowHead)\n\t\t\tst[1].attr(\"fill\", HIGHLIGHT_COLOR);\n\t\t\n\t\tst.forEach(function(el){\n\t\t\t//console.log(\"---->\", el);\n\t\t\t//el.attr(\"\")\n\t\t});\n\t},\n\t\n\n\t_drawClock: function(cx, cy, width, height){\n\t\t\n\t\tvar circle = this.g.ellipse(cx, cy, 1, 1).attr({stroke:\"none\", fill: Color.get(232, 239, 241)});\n\t\t//var c = this.g.ellipse(cx, cy, width, height).attr({stroke:\"none\", fill: Color.red});\n\t\t//x = cx - width/2;\n\t\t//y = cy - height/2;\n\t\n\t\tvar clock = this.g.path(\n\t\t/* outer circle */ \"M15.5,2.374\t\tC8.251,2.375,2.376,8.251,2.374,15.5\t\tC2.376,22.748,8.251,28.623,15.5,28.627c7.249-0.004,13.124-5.879,13.125-13.127C28.624,8.251,22.749,2.375,15.5,2.374z\" +\n\t\t/* inner circle */ \"M15.5,26.623\tC8.909,26.615,4.385,22.09,4.375,15.5\tC4.385,8.909,8.909,4.384,15.5,4.374c4.59,0.01,11.115,3.535,11.124,11.125C26.615,22.09,22.091,26.615,15.5,26.623z\" +\n\t\t/*  9 */ \"M8.625,15.5c-0.001-0.552-0.448-0.999-1.001-1c-0.553,0-1,0.448-1,1c0,0.553,0.449,1,1,1C8.176,16.5,8.624,16.053,8.625,15.5z\" +\n\t\t/*  8 */ \"M8.179,18.572c-0.478,0.277-0.642,0.889-0.365,1.367c0.275,0.479,0.889,0.641,1.365,0.365c0.479-0.275,0.643-0.887,0.367-1.367C9.27,18.461,8.658,18.297,8.179,18.572z\" +\n\t\t/* 10 */ \"M9.18,10.696c-0.479-0.276-1.09-0.112-1.366,0.366s-0.111,1.09,0.365,1.366c0.479,0.276,1.09,0.113,1.367-0.366C9.821,11.584,9.657,10.973,9.18,10.696z\" +\n\t\t/*  2 */ \"M22.822,12.428c0.478-0.275,0.643-0.888,0.366-1.366c-0.275-0.478-0.89-0.642-1.366-0.366c-0.479,0.278-0.642,0.89-0.366,1.367C21.732,12.54,22.344,12.705,22.822,12.428z\" +\n\t\t/*  7 */ \"M12.062,21.455c-0.478-0.275-1.089-0.111-1.366,0.367c-0.275,0.479-0.111,1.09,0.366,1.365c0.478,0.277,1.091,0.111,1.365-0.365C12.704,22.344,12.54,21.732,12.062,21.455z\" +\n\t\t/* 11 */ \"M12.062,9.545c0.479-0.276,0.642-0.888,0.366-1.366c-0.276-0.478-0.888-0.642-1.366-0.366s-0.642,0.888-0.366,1.366C10.973,9.658,11.584,9.822,12.062,9.545z\" +\n\t\t/*  4 */ \"M22.823,18.572c-0.48-0.275-1.092-0.111-1.367,0.365c-0.275,0.479-0.112,1.092,0.367,1.367c0.477,0.275,1.089,0.113,1.365-0.365C23.464,19.461,23.3,18.848,22.823,18.572z\" +\n\t\t/*  2 */ \"M19.938,7.813c-0.477-0.276-1.091-0.111-1.365,0.366c-0.275,0.48-0.111,1.091,0.366,1.367s1.089,0.112,1.366-0.366C20.581,8.702,20.418,8.089,19.938,7.813z\" +\n\t\t/*  3 */ \"M23.378,14.5c-0.554,0.002-1.001,0.45-1.001,1c0.001,0.552,0.448,1,1.001,1c0.551,0,1-0.447,1-1C24.378,14.949,23.929,14.5,23.378,14.5z\" +\n\t\t/* arrows */ \"M15.501,6.624c-0.552,0-1,0.448-1,1l-0.466,7.343l-3.004,1.96c-0.478,0.277-0.642,0.889-0.365,1.365c0.275,0.479,0.889,0.643,1.365,0.367l3.305-1.676C15.39,16.99,15.444,17,15.501,17c0.828,0,1.5-0.671,1.5-1.5l-0.5-7.876C16.501,7.072,16.053,6.624,15.501,6.624z\" +\n\t\t/*  9 */ \"M15.501,22.377c-0.552,0-1,0.447-1,1s0.448,1,1,1s1-0.447,1-1S16.053,22.377,15.501,22.377z\" +\n\t\t/*  8 */ \"M18.939,21.455c-0.479,0.277-0.643,0.889-0.366,1.367c0.275,0.477,0.888,0.643,1.366,0.365c0.478-0.275,0.642-0.889,0.366-1.365C20.028,21.344,19.417,21.18,18.939,21.455z\" +\n\t\t\"\");\n\t\tclock.attr({fill: Color.black, stroke: \"none\"});\n\t\t//clock.transform(\"t \" + (cx-29.75/2) + \" \" + (cy-29.75/2));\n\t\t//clock.transform(\"...s 0.85\");\n\t\t\n\t\t//clock.transform(\"...s \" + .85 + \" \" + .85);\n\t\tclock.transform(\"t \" + (-2.374) + \" \" + (-2.374)\t);\n\t\tclock.transform(\"...t -\" + (15.5-2.374) + \" -\" + (15.5-2.374)\t);\n\t\tclock.transform(\"...s \" + 1*(width/35) + \" \" + 1*(height/35));\n\t\tclock.transform(\"...T \" + cx + \" \" + cy);\n\t\t//clock.transform(\"t \" + (cx-width/2) + \" \" + (cy-height/2));\n\t\t\n\t\t//console.log(\".getBBox(): \", clock.getBBox());\n\t\t//console.log(\".attr(): \", c.attrs);\n\t\tcircle.attr(\"rx\", clock.getBBox().width/2);\n\t\tcircle.attr(\"ry\", clock.getBBox().height/2);\n\t\t\n\t\t//return circle\n\t},\n\t\n\t_drawPentagon: function(cx, cy, width, height, filled){\n\t\t// draw GeneralPath (polygon)\n\t    var n=5;\n\t    var angle = 2*Math.PI/n;\n\t    var waypoints = [];\n\t\t\n\t\tfor ( var index = 0; index < n; index++ ) {\n\t\t\tvar v = index*angle - Math.PI/2;\n\t\t\tvar point = {};\n\t\t\tpoint.x = -width*1.2/2 + parseInt(Math.round(width*1.2/2)) + parseInt(Math.round((width*1.2/4)*Math.cos(v)));\n        \tpoint.y = -height*1.2/2 + parseInt(Math.round(height*1.2/2)) + parseInt(Math.round((height*1.2/4)*Math.sin(v)));\n\t\t\twaypoints[index] = point;\n\t\t}\n\t\t\n\t\tvar polygone = new Polygone(waypoints, this.getStroke());\n\t\tpolygone.element = this.g.path(polygone.path);\n\t\tif (filled)\n\t\t\tpolygone.element.attr(\"fill\", Color.black);\n\t\telse\n\t\t\tpolygone.element.attr(\"fill\", Color.white);\n\t\t\n\t\tpolygone.element.transform(\"s \" + 1*(width/35) + \" \" + 1*(height/35));\n\t\tpolygone.element.transform(\"...T \" + cx + \" \" + cy);\n\t},\n\t\n\t//_drawMultilineText: function(text, x, y, boxWidth, boxHeight, textAnchor) {\n\t_drawMultilineText: function(text, x, y, boxWidth, boxHeight, verticalAlign, horizontalAlign) {\n\t\tif (!text || text == \"\") \n\t\t\treturn;\n\t\t\t\n\t\t// Autostretch boxHeight if boxHeight is 0\n\t\tif (boxHeight == 0)\n\t\t  verticalAlign = MULTILINE_VERTICAL_ALIGN_TOP;\t  \n\t\n\t\t//var TEXT_PADDING = 3;\n\t\tvar width = boxWidth;\n\t\tif (boxHeight)\n\t\t\tvar height = boxHeight;\n\t\n\t\tvar layouts = [];\n\t\t\n\t\t//var font = {font: \"11px Arial\", opacity: 1, \"fill\": LABEL_COLOR};\n\t\tvar font = this.getFont();\n\t\tvar measurer = new LineBreakMeasurer(this.g, x, y, text, font);\n\t\tvar lineHeight = measurer.rafaelTextObject.getBBox().height;\n\t\t//console.log(\"text: \", text.replace(/\\n/g, \"?\"));\n\t\t\n\t\tif (height) {\n\t\t\tvar availableLinesCount = parseInt(height/lineHeight);\n\t\t\t//console.log(\"availableLinesCount: \" + availableLinesCount);\n\t\t}\n\t\t\n\t\tvar i = 1;\n\t\twhile (measurer.getPosition() < measurer.text.getEndIndex()) {\n\t\t\tvar layout = measurer.nextLayout(width);\n\t\t\t//console.log(\"LAYOUT: \" + layout + \", getPosition: \" + measurer.getPosition());\n\t\t\t\n\t\t\tif (layout != null) {\n\t\t\t\t// TODO: and check if measurer has next layout. If no then don't draw  dots\n\t\t\t\tif (!availableLinesCount || i < availableLinesCount) {\n\t\t\t\t\tlayouts.push(layout);\n\t\t\t\t} else {\n\t\t\t\t\tlayouts.push(this.fitTextToWidth(layout + \"...\", boxWidth));\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\ti++;\n\t\t};\n\t\t//console.log(layouts);\n\t\t\n\t\tmeasurer.rafaelTextObject.attr({\"text\": layouts.join(\"\\n\")});\n\t\t\n\t\tif (horizontalAlign)\n\t\t\tmeasurer.rafaelTextObject.attr({\"text-anchor\": horizontalAlign}); // end, middle, start\n\t\t\t\n\t\tvar bb = measurer.rafaelTextObject.getBBox();\n\t\t// TODO: there is somethin wrong with wertical align. May be: measurer.rafaelTextObject.attr({\"y\": y + height/2 - bb.height/2})\n\t\tmeasurer.rafaelTextObject.attr({\"y\": y + bb.height/2});\n\t\t//var bb = measurer.rafaelTextObject.getBBox();\n\t\t\n\t\tif (measurer.rafaelTextObject.attr(\"text-anchor\") == MULTILINE_HORIZONTAL_ALIGN_MIDDLE )\n\t\t\tmeasurer.rafaelTextObject.attr(\"x\",  x +  boxWidth/2);\n\t\telse if (measurer.rafaelTextObject.attr(\"text-anchor\") == MULTILINE_HORIZONTAL_ALIGN_RIGHT )\n\t\t\tmeasurer.rafaelTextObject.attr(\"x\",  x +  boxWidth);\n\t\t\n\t\tvar boxStyle = {stroke: Color.LightSteelBlue2, \"stroke-width\": 1.0, \"stroke-dasharray\": \"- \"};\n\t\t//var box = this.g.rect(x+.5, y + .5, width, height).attr(boxStyle);\n\t\tvar textAreaCX = x + boxWidth/2;\n\t\t\t\tvar height = boxHeight;\n\t\t\t\tif (!height) height = bb.height;\n\t\t\t\tvar textAreaCY = y + height/2;\n\t\t\t\tvar dotLeftTop = this.g.ellipse(x, y, 3, 3).attr({\"stroke-width\": 0, fill: Color.LightSteelBlue, stroke: \"none\"}).hide();\n\t\t\t\tvar dotCenter = this.g.ellipse(textAreaCX, textAreaCY, 3, 3).attr({fill: Color.LightSteelBlue2, stroke: \"none\"}).hide();\n\n\t\t\t\t/*\n\t\t\t\t// real bbox\n\t\t\t\tvar bb = measurer.rafaelTextObject.getBBox();\n\t\t\t\tvar rect = paper.rect(bb.x+.5, bb.y + .5, bb.width, bb.height).attr({\"stroke-width\": 1});\n\t\t\t\t*/\n\t\t\t\tvar rect = this.g.rect(x, y, boxWidth, height).attr({\"stroke-width\": 1}).attr(boxStyle).hide();\n\t\t\t\tvar debugSet = this.g.set();\n\t\t\t\tdebugSet.push(dotLeftTop, dotCenter, rect);\n\t\t\t\t//debugSet.show();\n\t},\n\t\n\tdrawTextAnnotation: function(text, x, y, width, height){\n\t\tvar lineLength = 18;\n\t\tvar path = [];\n\t\t  path.push([\"M\", x + lineLength, y]);\n\t\t  path.push([\"L\", x, y]);\n\t\t  path.push([\"L\", x, y + height]);\n\t\t  path.push([\"L\", x + lineLength, y + height]);\n\t\t  \n\t\t  path.push([\"L\", x + lineLength, y + height -1]);\n\t\t  path.push([\"L\", x + 1, y + height -1]);\n\t\t  path.push([\"L\", x + 1, y + 1]);\n\t\t  path.push([\"L\", x + lineLength, y + 1]);\n\t\t  path.push([\"z\"]);\n\t\n\t\tvar textAreaLines = this.g.path(path);\n\t\t\n\t  var boxWidth = width - (2 * ANNOTATION_TEXT_PADDING);\n      var boxHeight = height - (2 * ANNOTATION_TEXT_PADDING);\n      var boxX = x + width/2 - boxWidth/2;\n      var boxY = y + height/2 - boxHeight/2;\n      \n      // for debug\n          var rectStyle = {stroke: Color(112, 146, 190), \"stroke-width\": 1.0, \"stroke-dasharray\": \"- \"};\n          var r = this.g.rect(boxX, boxY, boxWidth, boxHeight).attr(rectStyle);\n\t  //\n      \n\t  this.drawAnnotationText(text, boxX, boxY, boxWidth, boxHeight);\n\t},\n\t\n\tdrawLabel111111111: function(text, x, y, width, height, labelAttrs){\n\t\tvar  debug = false;\n\t\t\n\t\t// text\n\t\tif (text != null && text != undefined && text != \"\") {\n\t\t\tvar attr = LABEL_FONT;\n\t\t\t\n\t\t\t//console.log(\"x\", x, \"y\", y, \"width\", width, \"height\", height );\n\t\t\t\n\t\t\twrappedText = text;\n\t\t\tif (labelAttrs && labelAttrs.wrapWidth) {\n\t\t\t\twrappedText = this.wrapTextToWidth(wrappedText, labelAttrs.wrapWidth);\n\t\t\t}\n\t\t\tvar realWidth = this.getStringWidth(wrappedText, attr);\n\t\t\tvar realHeight = this.getStringHeight(wrappedText, attr);\n\t\t\t\n\t\t\tvar textAreaCX = x + width/2;\n\t\t\tvar textAreaCY = y + 3 + height + this.getStringHeight(wrappedText, attr)/2;\n\t\t\t\n\t\t\tvar textX = textAreaCX;\n\t\t\tvar textY = textAreaCY;\n\n\t\t\tvar textAttrs = {};\n\t\t\tif (labelAttrs && labelAttrs.align) {\n\t\t\t\tswitch (labelAttrs.align) {\n\t\t\t\t\tcase \"left\": \n\t\t\t\t\t\ttextAttrs[\"text-anchor\"] = \"start\"; \n\t\t\t\t\t\ttextX = textX - realWidth/2;\n\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"center\": \n\t\t\t\t\t\ttextAttrs[\"text-anchor\"] = \"middle\"; \n\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"right\": \n\t\t\t\t\t\ttextAttrs[\"text-anchor\"] = \"end\"; \n\t\t\t\t\t\ttextX = textX + realWidth/2;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (labelAttrs && labelAttrs.wrapWidth) {\n\t\t\t\tif (true) {\n\t\t\t\t\t// Draw frameborder\n\t\t\t\t\tvar textAreaStyle = {stroke: Color.LightSteelBlue2, \"stroke-width\": 1.0, \"stroke-dasharray\": \"- \"};\n\t\t\t\t\tvar textAreaX = textAreaCX - realWidth/2;\n\t\t\t\t\tvar textAreaY = textAreaCY+.5 - realHeight/2;\n\t\t\t\t\tvar textArea = this.g.rect(textAreaX, textAreaY, realWidth, realHeight).attr(textAreaStyle);\n\t\t\t\t\t\n\t\t\t\t\tvar textAreaLines = this.g.path(\"M\" + textAreaX + \" \" + textAreaY + \"L\" + (textAreaX+realWidth) + \" \" + (textAreaY+realHeight) + \"M\" +  + (textAreaX+realWidth) + \" \" + textAreaY + \"L\" + textAreaX + \" \" + (textAreaY+realHeight));\n\t\t\t\t\ttextAreaLines.attr(textAreaStyle);\n\t\t\t\t\t\n\t\t\t\t\tthis.g.ellipse(textAreaCX, textAreaCY, 3, 3).attr({fill: Color.LightSteelBlue2, stroke: \"none\"});\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tvar label = this.g.text(textX, textY, wrappedText).attr(attr).attr(textAttrs);\n\t\t\t//label.id = Raphael.createUUID();\n\t\t\t//console.log(\"label \", label.id, \", \", wrappedText);\n\t\t\t\n\t\t\tif (this.fontSmoothing) {\n\t\t\t\tlabel.attr({stroke: LABEL_COLOR, \"stroke-width\":.4});\n\t\t\t}\n\t\t\t\n\t\t\t// debug\n\t\t\tif (debug) {\n\t\t\t\tvar imageAreaStyle = {stroke: Color.grey61, \"stroke-width\": 1.0, \"stroke-dasharray\": \"- \"};\n\t\t\t\tvar imageArea = this.g.rect(x+.5, y+.5, width, height).attr(imageAreaStyle);\n\t\t\t\tvar imageAreaLines = this.g.path(\"M\" + x + \" \" + y + \"L\" + (x+width) + \" \" + (y+height) + \"M\" +  + (x+width) + \" \" + y + \"L\" + x + \" \" + (y+height));\n\t\t\t\timageAreaLines.attr(imageAreaStyle);\n\t\t\t\tvar dotStyle = {fill: Color.Coral, stroke: \"none\"};\n\t\t\t\tthis.g.ellipse(x, y, 3, 3).attr(dotStyle);\n\t\t\t\tthis.g.ellipse(x+width, y, 2, 2).attr(dotStyle);\n\t\t\t\tthis.g.ellipse(x+width, y+height, 2, 2).attr(dotStyle);\n\t\t\t\tthis.g.ellipse(x, y+height, 2, 2).attr(dotStyle);\n\t\t\t}\n\t\t\t\n\t\t\treturn label;\n\t\t}\n\t},\n\t\n\tvvoid: function(){}\n};\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/diagram-viewer/js/ProcessDiagramGenerator.js",
    "content": " /**\n * Class to generate an image based the diagram interchange information in a\n * BPMN 2.0 process.\n *\n * @author (Javascript) Dmitry Farafonov\n */\n \nvar ProcessDiagramGenerator = {\t\n\toptions: {},\n\t\n\tprocessDiagramCanvas: [],\n\t\n\tactivityDrawInstructions:{},\n\t\n\tprocessDiagrams: {},\n\t\n\tdiagramBreadCrumbs: null,\n\t\n\tinit: function(){\n\t\t// start event\n\t\tthis.activityDrawInstructions[\"startEvent\"] = function(){\n\t\t\tvar activityImpl = this.activity;\n\t\t\tvar processDiagramCanvas = this.processDiagramCanvas;\n\t\t\tprocessDiagramCanvas.setConextObject(activityImpl);\n\t\t\t\n\t\t\tprocessDiagramCanvas.drawNoneStartEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight());\n\t\t};\n\t\t\n\t\t// start timer event\n\t\tthis.activityDrawInstructions[\"startTimerEvent\"] = function(){\n\t\t\tvar activityImpl = this.activity;\n\t\t\tvar processDiagramCanvas = this.processDiagramCanvas;\n\t\t\tprocessDiagramCanvas.setConextObject(activityImpl);\n\t\t\t\n\t\t\tvar isInterrupting = activityImpl.getProperty(\"isInterrupting\");\n\t\t\tprocessDiagramCanvas.drawTimerStartEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), isInterrupting, activityImpl.getProperty(\"name\"));\n\t\t};\n\t\t\n\t\t// start event\n\t\tthis.activityDrawInstructions[\"messageStartEvent\"] = function(){\n\t\t\tvar activityImpl = this.activity;\n\t\t\tvar processDiagramCanvas = this.processDiagramCanvas;\n\t\t\tprocessDiagramCanvas.setConextObject(activityImpl);\n\t\t\t\n\t\t\tvar isInterrupting = activityImpl.getProperty(\"isInterrupting\");\n\t\t\tprocessDiagramCanvas.drawMessageStartEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), isInterrupting, activityImpl.getProperty(\"name\"));\n\t\t};\n\t\t\n\t\t// start signal event\n\t\tthis.activityDrawInstructions[\"startSignalEvent\"] = function(){\n\t\t\tvar activityImpl = this.activity;\n\t\t\tvar processDiagramCanvas = this.processDiagramCanvas;\n\t\t\tprocessDiagramCanvas.setConextObject(activityImpl);\n\t\t\t\n\t\t\tvar isInterrupting = activityImpl.getProperty(\"isInterrupting\");\n\t\t\tprocessDiagramCanvas.drawSignalStartEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), isInterrupting, activityImpl.getProperty(\"name\"));\n\t\t};\n\t\t\n\t\t// start multiple event\n\t\tthis.activityDrawInstructions[\"startMultipleEvent\"] = function(){\n\t\t\tvar activityImpl = this.activity;\n\t\t\tvar processDiagramCanvas = this.processDiagramCanvas;\n\t\t\tprocessDiagramCanvas.setConextObject(activityImpl);\n\t\t\t\n\t\t\tvar isInterrupting = activityImpl.getProperty(\"isInterrupting\");\n\t\t\tprocessDiagramCanvas.drawMultipleStartEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), isInterrupting, activityImpl.getProperty(\"name\"));\n\t\t};\n\t\t\n\t\t// signal catch\n\t\tthis.activityDrawInstructions[\"intermediateSignalCatch\"] = function(){\n\t\t\tvar activityImpl = this.activity;\n\t\t\tvar processDiagramCanvas = this.processDiagramCanvas;\n\t\t\tprocessDiagramCanvas.setConextObject(activityImpl);\n\t\t\t\n\t\t\tvar isInterrupting = activityImpl.getProperty(\"isInterrupting\");\n\t\t\tprocessDiagramCanvas.drawCatchingSignalEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), isInterrupting, null);\n\t\t\t\n\t\t\tvar label = ProcessDiagramGenerator.getActivitiLabel(activityImpl);\n\t\t\tif (label)\n\t\t\t  processDiagramCanvas.drawLabel(label.text, label.x, label.y, label.width, label.height);\n\t\t};\n\t\t\n\t\t// message catch\n\t\tthis.activityDrawInstructions[\"intermediateMessageCatch\"] = function(){\n\t\t\tvar activityImpl = this.activity;\n\t\t\tvar processDiagramCanvas = this.processDiagramCanvas;\n\t\t\tprocessDiagramCanvas.setConextObject(activityImpl);\n\t\t\t\n\t\t\tvar isInterrupting = activityImpl.getProperty(\"isInterrupting\");\n\t\t\tprocessDiagramCanvas.drawCatchingMessageEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), isInterrupting, null);\n\t\t\t\n\t\t\tvar label = ProcessDiagramGenerator.getActivitiLabel(activityImpl);\n      if (label)\n        processDiagramCanvas.drawLabel(label.text, label.x, label.y, label.width, label.height);\n\t\t};\n\t\t\n\t\t// multiple catch\n\t\tthis.activityDrawInstructions[\"intermediateMultipleCatch\"] = function(){\n\t\t\tvar activityImpl = this.activity;\n\t\t\tvar processDiagramCanvas = this.processDiagramCanvas;\n\t\t\tprocessDiagramCanvas.setConextObject(activityImpl);\n\t\t\t\n\t\t\tvar isInterrupting = activityImpl.getProperty(\"isInterrupting\");\n\t\t\tprocessDiagramCanvas.drawCatchingMultipleEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), isInterrupting, null);\n\t\t\t\n\t\t\tvar label = ProcessDiagramGenerator.getActivitiLabel(activityImpl);\n      if (label)\n        processDiagramCanvas.drawLabel(label.text, label.x, label.y, label.width, label.height);\n\t\t};\n\t\t\n\t\t\n\t\t\n\t\t// signal throw\n\t\tthis.activityDrawInstructions[\"intermediateSignalThrow\"] = function(){\n\t\t\tvar activityImpl = this.activity;\n\t\t\tvar processDiagramCanvas = this.processDiagramCanvas;\n\t\t\tprocessDiagramCanvas.setConextObject(activityImpl);\n\t\t\t\n\t\t\tprocessDiagramCanvas.drawThrowingSignalEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), activityImpl.getProperty(\"name\"));\n\t\t\t\n\t\t\tvar label = ProcessDiagramGenerator.getActivitiLabel(activityImpl);\n      if (label)\n        processDiagramCanvas.drawLabel(label.text, label.x, label.y, label.width, label.height);\n\t\t};\n\t\t\n\t\t// message throw\n\t\tthis.activityDrawInstructions[\"intermediateMessageThrow\"] = function(){\n\t\t\tvar activityImpl = this.activity;\n\t\t\tvar processDiagramCanvas = this.processDiagramCanvas;\n\t\t\tprocessDiagramCanvas.setConextObject(activityImpl);\n\t\t\t\n\t\t\tprocessDiagramCanvas.drawThrowingMessageEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), activityImpl.getProperty(\"name\"));\n\t\t\t\n\t\t\tvar label = ProcessDiagramGenerator.getActivitiLabel(activityImpl);\n      if (label)\n        processDiagramCanvas.drawLabel(label.text, label.x, label.y, label.width, label.height);\n\t\t};\n\t\t\n\t\t// multiple throw\n\t\tthis.activityDrawInstructions[\"intermediateMultipleThrow\"] = function(){\n\t\t\tvar activityImpl = this.activity;\n\t\t\tvar processDiagramCanvas = this.processDiagramCanvas;\n\t\t\tprocessDiagramCanvas.setConextObject(activityImpl);\n\t\t\t\n\t\t\tprocessDiagramCanvas.drawThrowingMultipleEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), activityImpl.getProperty(\"name\"));\n\t\t\t\n\t\t\tvar label = ProcessDiagramGenerator.getActivitiLabel(activityImpl);\n      if (label)\n        processDiagramCanvas.drawLabel(label.text, label.x, label.y, label.width, label.height);\n\t\t};\n\t\t\n\t\t// none throw\n\t\tthis.activityDrawInstructions[\"intermediateThrowEvent\"] = function() {\n\t\t\tvar activityImpl = this.activity;\n\t\t\tvar processDiagramCanvas = this.processDiagramCanvas;\n\t\t\tprocessDiagramCanvas.setConextObject(activityImpl);\n\t\t\t\n\t\t\tprocessDiagramCanvas.drawThrowingNoneEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), activityImpl.getProperty(\"name\"));\n\t\t\t\n\t\t\tvar label = ProcessDiagramGenerator.getActivitiLabel(activityImpl);\n      if (label)\n        processDiagramCanvas.drawLabel(label.text, label.x, label.y, label.width, label.height);\n\t\t};\n\t\t\n\t\t// end event\n\t\tthis.activityDrawInstructions[\"endEvent\"] = function(){\n\t\t\tvar activityImpl = this.activity;\n\t\t\tvar processDiagramCanvas = this.processDiagramCanvas;\n\t\t\tprocessDiagramCanvas.setConextObject(activityImpl);\n\t\t\t\n\t\t\tprocessDiagramCanvas.drawNoneEndEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight());\n\t\t};\n\t\t\n\t\t// error end event\n\t\tthis.activityDrawInstructions[\"errorEndEvent\"] = function(){\n\t\t\tvar activityImpl = this.activity;\n\t\t\tvar processDiagramCanvas = this.processDiagramCanvas;\n\t\t\tprocessDiagramCanvas.setConextObject(activityImpl);\n\t\t\t\n\t\t\tprocessDiagramCanvas.drawErrorEndEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), null);\n\t\t\t\n\t\t\tvar label = ProcessDiagramGenerator.getActivitiLabel(activityImpl);\n      if (label)\n        processDiagramCanvas.drawLabel(label.text, label.x, label.y, label.width, label.height);\n\t\t};\n\t\t\n\t\t// message end event\n\t\tthis.activityDrawInstructions[\"messageEndEvent\"] = function(){\n\t\t\tvar activityImpl = this.activity;\n\t\t\tvar processDiagramCanvas = this.processDiagramCanvas;\n\t\t\tprocessDiagramCanvas.setConextObject(activityImpl);\n\t\t\t\n\t\t\tprocessDiagramCanvas.drawMessageEndEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), null);\n\t\t\t\n\t\t\tvar label = ProcessDiagramGenerator.getActivitiLabel(activityImpl);\n      if (label)\n        processDiagramCanvas.drawLabel(label.text, label.x, label.y, label.width, label.height);\n\t\t};\n\t\t\n\t\t// signal end event\n\t\tthis.activityDrawInstructions[\"signalEndEvent\"] = function(){\n\t\t\tvar activityImpl = this.activity;\n\t\t\tvar processDiagramCanvas = this.processDiagramCanvas;\n\t\t\tprocessDiagramCanvas.setConextObject(activityImpl);\n\t\t\t\n\t\t\tprocessDiagramCanvas.drawSignalEndEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), null);\n\t\t\t\n\t\t\tvar label = ProcessDiagramGenerator.getActivitiLabel(activityImpl);\n      if (label)\n        processDiagramCanvas.drawLabel(label.text, label.x, label.y, label.width, label.height);\n\t\t};\n\t\t\n\t\t// multiple end event\n\t\tthis.activityDrawInstructions[\"multipleEndEvent\"] = function(){\n\t\t\tvar activityImpl = this.activity;\n\t\t\tvar processDiagramCanvas = this.processDiagramCanvas;\n\t\t\tprocessDiagramCanvas.setConextObject(activityImpl);\n\t\t\t\n\t\t\tprocessDiagramCanvas.drawMultipleEndEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), null);\n\t\t\t\n\t\t\tvar label = ProcessDiagramGenerator.getActivitiLabel(activityImpl);\n      if (label)\n        processDiagramCanvas.drawLabel(label.text, label.x, label.y, label.width, label.height);\n\t\t};\n\t\t\n\t\t// terminate end event\n\t\tthis.activityDrawInstructions[\"terminateEndEvent\"] = function(){\n\t\t\tvar activityImpl = this.activity;\n\t\t\tvar processDiagramCanvas = this.processDiagramCanvas;\n\t\t\tprocessDiagramCanvas.setConextObject(activityImpl);\n\t\t\t\n\t\t\tprocessDiagramCanvas.drawTerminateEndEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight());\n\t\t\t\n\t\t\tvar label = ProcessDiagramGenerator.getActivitiLabel(activityImpl);\n      if (label)\n        processDiagramCanvas.drawLabel(label.text, label.x, label.y, label.width, label.height);\n\t\t};\n\t\t\n\t\t// error start event\n\t\tthis.activityDrawInstructions[\"errorStartEvent\"] = function(){\n\t\t\tvar activityImpl = this.activity;\n\t\t\tvar processDiagramCanvas = this.processDiagramCanvas;\n\t\t\tprocessDiagramCanvas.setConextObject(activityImpl);\n\t\t\t\n\t\t\tprocessDiagramCanvas.drawErrorStartEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), activityImpl.getProperty(\"name\"));\n\t\t\t\n\t\t\tvar label = ProcessDiagramGenerator.getActivitiLabel(activityImpl);\n      if (label)\n        processDiagramCanvas.drawLabel(label.text, label.x, label.y, label.width, label.height);\n\t\t};\n\t\t\n\t\t// task\n\t\tthis.activityDrawInstructions[\"task\"] = function(){\n\t\t\tvar activityImpl = this.activity;\n\t\t\tvar processDiagramCanvas = this.processDiagramCanvas;\n\t\t\tprocessDiagramCanvas.setConextObject(activityImpl);\n\t\t\t\n\t\t\t// TODO: \n\t\t\t//console.error(\"task is not implemented yet\");\n\t\t\t/*\n\t\t\tvar activityImpl = this;\n\t\t\tprocessDiagramCanvas.drawTask(activityImpl.getProperty(\"name\"), activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), thickBorder);\n\t\t\t*/\n\t\t};\n\t\t\n\t\t\n\t\t// user task\n\t\tthis.activityDrawInstructions[\"userTask\"] = function(){\n\t\t\tvar activityImpl = this.activity;\n\t\t\tvar processDiagramCanvas = this.processDiagramCanvas;\n\t\t\tprocessDiagramCanvas.setConextObject(activityImpl);\n\t\t\t\n\t\t\tprocessDiagramCanvas.drawUserTask(activityImpl.getProperty(\"name\"), activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight());\n\t\t};\n\t\t\n\t\t// script task\n\t\tthis.activityDrawInstructions[\"scriptTask\"] = function(){\n\t\t\tvar activityImpl = this.activity;\n\t\t\tvar processDiagramCanvas = this.processDiagramCanvas;\n\t\t\tprocessDiagramCanvas.setConextObject(activityImpl);\n\t\t\t\n\t\t\tprocessDiagramCanvas.drawScriptTask(activityImpl.getProperty(\"name\"), activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight());\n\t\t};\n\t\t\n\t\t// service task\n\t\tthis.activityDrawInstructions[\"serviceTask\"] = function(){\n\t\t\tvar activityImpl = this.activity;\n\t\t\tvar processDiagramCanvas = this.processDiagramCanvas;\n\t\t\tprocessDiagramCanvas.setConextObject(activityImpl);\n\t\t\t\n\t\t\tprocessDiagramCanvas.drawServiceTask(activityImpl.getProperty(\"name\"), activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight());\n\t\t};\n\n\t\t// receive task\n\t\tthis.activityDrawInstructions[\"receiveTask\"] = function(){\n\t\t\tvar activityImpl = this.activity;\n\t\t\tvar processDiagramCanvas = this.processDiagramCanvas;\n\t\t\tprocessDiagramCanvas.setConextObject(activityImpl);\n\t\t\t\n\t\t\tprocessDiagramCanvas.drawReceiveTask(activityImpl.getProperty(\"name\"), activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight());\n\t\t};\n\t\t\n\t\t// send task\n\t\tthis.activityDrawInstructions[\"sendTask\"] = function(){\n\t\t\tvar activityImpl = this.activity;\n\t\t\tvar processDiagramCanvas = this.processDiagramCanvas;\n\t\t\tprocessDiagramCanvas.setConextObject(activityImpl);\n\t\t\t\n\t\t\tprocessDiagramCanvas.drawSendTask(activityImpl.getProperty(\"name\"), activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight());\n\t\t};\n\n\t\t// manual task\n\t\tthis.activityDrawInstructions[\"manualTask\"] = function(){\n\t\t\tvar activityImpl = this.activity;\n\t\t\tvar processDiagramCanvas = this.processDiagramCanvas;\n\t\t\tprocessDiagramCanvas.setConextObject(activityImpl);\n\t\t\n\t\t\tprocessDiagramCanvas.drawManualTask(activityImpl.getProperty(\"name\"), activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight());\n\t\t};\n\n\t\t// businessRuleTask task\n\t\tthis.activityDrawInstructions[\"businessRuleTask\"] = function(){\n\t\t\tvar activityImpl = this.activity;\n\t\t\tvar processDiagramCanvas = this.processDiagramCanvas;\n\t\t\tprocessDiagramCanvas.setConextObject(activityImpl);\n\t\t\t\n\t\t\tprocessDiagramCanvas.drawBusinessRuleTask(activityImpl.getProperty(\"name\"), activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight());\n\t\t};\n\n\t\t// exclusive gateway\n\t\tthis.activityDrawInstructions[\"exclusiveGateway\"] = function(){\n\t\t\tvar activityImpl = this.activity;\n\t\t\tvar processDiagramCanvas = this.processDiagramCanvas;\n\t\t\tprocessDiagramCanvas.setConextObject(activityImpl);\n\t\t\t\n\t\t\tprocessDiagramCanvas.drawExclusiveGateway(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight());\n\t\t};\n\t\t\n\t\t// inclusive gateway\n\t\tthis.activityDrawInstructions[\"inclusiveGateway\"] = function(){\n\t\t\tvar activityImpl = this.activity;\n\t\t\tvar processDiagramCanvas = this.processDiagramCanvas;\n\t\t\tprocessDiagramCanvas.setConextObject(activityImpl);\n\t\t\t\n\t\t\tprocessDiagramCanvas.drawInclusiveGateway(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight());\n\t\t};\n\t\t\n\t\t// parallel gateway\n\t\tthis.activityDrawInstructions[\"parallelGateway\"] = function(){\n\t\t\tvar activityImpl = this.activity;\n\t\t\tvar processDiagramCanvas = this.processDiagramCanvas;\n\t\t\tprocessDiagramCanvas.setConextObject(activityImpl);\n\t\t\t\n\t\t\tprocessDiagramCanvas.drawParallelGateway(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight());\n\t\t};\n\t\t\n\t\t// eventBasedGateway\n\t\tthis.activityDrawInstructions[\"eventBasedGateway\"] = function(){\n\t\t\tvar activityImpl = this.activity;\n\t\t\tvar processDiagramCanvas = this.processDiagramCanvas;\n\t\t\tprocessDiagramCanvas.setConextObject(activityImpl);\n\t\t\t\n\t\t\tprocessDiagramCanvas.drawEventBasedGateway(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight());\n\t\t};\n\t\t\n\t\t// Boundary timer\n\t\tthis.activityDrawInstructions[\"boundaryTimer\"] = function(){\n\t\t\tvar activityImpl = this.activity;\n\t\t\tvar processDiagramCanvas = this.processDiagramCanvas;\n\t\t\tprocessDiagramCanvas.setConextObject(activityImpl);\n\t\t\t\n\t\t\tvar isInterrupting = activityImpl.getProperty(\"isInterrupting\");\n\t\t\tprocessDiagramCanvas.drawCatchingTimerEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), isInterrupting, null);\n\t\t\t\n\t\t\tvar label = ProcessDiagramGenerator.getActivitiLabel(activityImpl);\n      if (label)\n        processDiagramCanvas.drawLabel(label.text, label.x, label.y, label.width, label.height);\n\t\t};\n\t\t\n\t\t// Boundary catch error\n\t\tthis.activityDrawInstructions[\"boundaryError\"] = function(){\n\t\t\tvar activityImpl = this.activity;\n\t\t\tvar processDiagramCanvas = this.processDiagramCanvas;\n\t\t\tprocessDiagramCanvas.setConextObject(activityImpl);\n\t\t\t\n\t\t\tvar isInterrupting = activityImpl.getProperty(\"isInterrupting\");\n\t\t\tprocessDiagramCanvas.drawCatchingErrorEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), isInterrupting, null);\n\t\t\t\n\t\t\tvar label = ProcessDiagramGenerator.getActivitiLabel(activityImpl);\n      if (label)\n        processDiagramCanvas.drawLabel(label.text, label.x, label.y, label.width, label.height);\n\t\t};\n\t\t\n\t\t// Boundary signal event\n\t\tthis.activityDrawInstructions[\"boundarySignal\"] = function(){\n\t\t\tvar activityImpl = this.activity;\n\t\t\tvar processDiagramCanvas = this.processDiagramCanvas;\n\t\t\tprocessDiagramCanvas.setConextObject(activityImpl);\n\t\t\t\n\t\t\tvar isInterrupting = activityImpl.getProperty(\"isInterrupting\");\n\t\t\tprocessDiagramCanvas.drawCatchingSignalEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), isInterrupting, null);\n\t\t\t\n\t\t\tvar label = ProcessDiagramGenerator.getActivitiLabel(activityImpl);\n      if (label)\n        processDiagramCanvas.drawLabel(label.text, label.x, label.y, label.width, label.height);\n\t\t};\n\n    // Boundary message event\n    this.activityDrawInstructions[\"boundaryMessage\"] = function(){\n        var activityImpl = this.activity;\n        var processDiagramCanvas = this.processDiagramCanvas;\n        processDiagramCanvas.setConextObject(activityImpl);\n\n        var isInterrupting = activityImpl.getProperty(\"isInterrupting\");\n        processDiagramCanvas.drawCatchingMessageEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), isInterrupting, null);\n\n        var label = ProcessDiagramGenerator.getActivitiLabel(activityImpl);\n        if (label)\n            processDiagramCanvas.drawLabel(label.text, label.x, label.y, label.width, label.height);\n    };\n\t\t\n\t\t// timer catch event\n\t\tthis.activityDrawInstructions[\"intermediateTimer\"] = function(){\n\t\t\tvar activityImpl = this.activity;\n\t\t\tvar processDiagramCanvas = this.processDiagramCanvas;\n\t\t\tprocessDiagramCanvas.setConextObject(activityImpl);\n\t\t\t\n\t\t\tvar isInterrupting = null;\n\t\t\tprocessDiagramCanvas.drawCatchingTimerEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), isInterrupting, activityImpl.getProperty(\"name\"));\n\t\t};\n\t\t\n\t\t// subprocess\n\t\tthis.activityDrawInstructions[\"subProcess\"] = function(){\n\t\t\tvar activityImpl = this.activity;\n\t\t\tvar processDiagramCanvas = this.processDiagramCanvas;\n\t\t\t// TODO: \n\t\t\t\n\t\t\tprocessDiagramCanvas.setConextObject(activityImpl);\n\t\t\t\n\t\t\tvar isExpanded = activityImpl.getProperty(\"isExpanded\");\n\t\t\tvar isTriggeredByEvent = activityImpl.getProperty(\"triggeredByEvent\");\n\t\t\tif(isTriggeredByEvent == undefined) {\n\t\t\t  isTriggeredByEvent = true;\n\t\t\t}\n\t\t\t// TODO: check why isTriggeredByEvent = true when undefined\n\t\t\tisTriggeredByEvent = false;\n\t\t\t\n\t\t\tif (isExpanded != undefined && isExpanded == false) {\n\t\t\t  processDiagramCanvas.drawCollapsedSubProcess(activityImpl.getProperty(\"name\"), activityImpl.getX(), activityImpl.getY(),\n\t\t\t\t\t  activityImpl.getWidth(), activityImpl.getHeight(), isTriggeredByEvent);\n\t\t\t} else {\n\t\t\t  processDiagramCanvas.drawExpandedSubProcess(activityImpl.getProperty(\"name\"), activityImpl.getX(), activityImpl.getY(),\n\t\t\t\t\t  activityImpl.getWidth(), activityImpl.getHeight(), isTriggeredByEvent);\n\t\t\t}\n\t\t\t\n\t\t\t//console.error(\"subProcess is not implemented yet\");\n\t\t};\n\t\t\n\t\t// call activity\n\t\tthis.activityDrawInstructions[\"callActivity\"] = function(){\n\t\t\tvar activityImpl = this.activity;\n\t\t\tvar processDiagramCanvas = this.processDiagramCanvas;\n\t\t\tprocessDiagramCanvas.setConextObject(activityImpl);\n\t\t\tprocessDiagramCanvas.drawCollapsedCallActivity(activityImpl.getProperty(\"name\"), activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight());\n\t\t};\n\t\t\n\t\t$(document).ready(function(){\n\t\t  // Protect right click on SVG elements (and on canvas too)\n\t\t  document.body.oncontextmenu = function(event) {\n\t\t    if (window.event.srcElement.tagName == \"shape\" || window.event.srcElement.tagName == \"DIV\" && window.event.srcElement.parentElement.className == \"diagram\") {\n\n\t\t      // IE DIAGRAM CANVAS OR SHAPE DETECTED!\n\t\t      return false;\n\t\t    }\n\t\t    return (!Object.isSVGElement(window.event.srcElement));\n\t\t  };\n\t\t});\n\t},\n\t\n\t getActivitiLabel:function(activityImpl){\n\t   /*\n\t     TODO: Label object should be in activityImpl and looks like:\n\t     {\n\t       x: 250,\n\t       y: 250,\n\t       width: 80,\n\t       height: 30\n\t     }\n\t     And then:\n\t     if (!activityImpl.label)\n\t       return null;\n\t     var label = activityImpl.label;\n\t     label.text = activityImpl.name;\n\t     return label;\n\t   */\n\n\t   // But now default label for all events is:\n\t   return {\n\t     text: activityImpl.getProperty(\"name\"),\n\t     x: activityImpl.getX() + .5 + activityImpl.getWidth()/2,\n\t     y: activityImpl.getY() + .5 + activityImpl.getHeight() + ICON_PADDING,\n\t     width: 100,\n\t     height: 0\n\t   };\n\t},\n\t\t\n\tgenerateDiagram: function(processDefinitionDiagramLayout){\n\t\t// Init canvas\n\t\tvar processDefinitionId = processDefinitionDiagramLayout.processDefinition.id;\n\t\t//console.log(\"Init canvas \", processDefinitionId);\n\t\t\n\t\tif (this.getProcessDiagram(processDefinitionId) != undefined) {\n\t\t\t// TODO: may be reset canvas if exists.. Or just show\n\t\t\t//console.log(\"ProcessDiagram '\" + processDefinitionId + \"' is already generated. Just show it.\");\n\t\t\treturn;\n\t\t}\n\t\tvar processDiagram = this.initProcessDiagramCanvas(processDefinitionDiagramLayout);\n\t\tvar processDiagramCanvas = processDiagram.diagramCanvas;\n\t\t\n\t\t// Draw pool shape, if process is participant in collaboration\n\t\t\n\t\tif(processDefinitionDiagramLayout.participantProcess != undefined) {\n\t\t  //console.log(\"Draw pool shape\");\n\t\t  var pProc = processDefinitionDiagramLayout.participantProcess;\n\t\t  processDiagramCanvas.drawPoolOrLane(pProc.x, pProc.y, pProc.width, pProc.height, pProc.name);\n\t\t}\n\t\t\n\t\tvar laneSets = processDefinitionDiagramLayout.laneSets;\n\t\tvar activities = processDefinitionDiagramLayout.activities;\n\t\tvar sequenceFlows = processDefinitionDiagramLayout.sequenceFlows;\n\t\t\n\t\t\n\t\tpb1.set('value', 0);\n\t\tvar cnt = 0;\n\t\tif (laneSets) \n\t\t\tfor(var i in laneSets) {\n\t\t\t\tcnt += laneSets[i].lanes.length;\n\t\t\t}\n\t\tif (activities) \n\t\t\tcnt += activities.length;\n\t\tif (sequenceFlows) \n\t\t\tcnt += sequenceFlows.length;\n\t\tvar step = (cnt>0)? 100/cnt : 0;\n\t\tvar progress = 0;\n\t\t//console.log(\"progress bar step: \", step);\n\t\t\n\t\tvar task1 = new $.AsyncQueue();\n\t\t\n\t\t\t// Draw lanes\n\t\t\t\n\t\t\ttask1.add(function (task1) {\n\t\t\t\tif (!laneSets) laneSets = [];\n\t\t\t\t//console.log(\"> draw lane sets, count:\", laneSets.length)\n\t\t\t});\n\t\t\t\n\t\t\tfor(var i in laneSets) {\n\t\t\t\tvar laneSet = laneSets[i];\n\t\t\t\t//laneSet.id, laneSet.name\n\t\t\t\t\n\t\t\t\ttask1.add(laneSet.lanes,function (task1, lane) {\n\t\t\t\t\tprogress += step;\n\t\t\t\t\tpb1.set('value', parseInt(progress));\n\t\t\t\t\t\n\t\t\t\t\t//console.log(\"--> laneId: \" + lane.name + \", name: \" + lane.name);\n\t\t\t\t\t\n\t\t\t\t\tprocessDiagramCanvas.drawPoolOrLane(lane.x, lane.y, lane.width, lane.height, lane.name);\n\t\t\t\t});\n\t\t\t}\n\t\t\t\n\t\t\t// Draw activities\n\t\t\t\n\t\t\ttask1.add(function (task1) {\n\t\t\t\tif (!activities) activities = [];\n\t\t\t\t//console.log(\"> draw activities, count:\", activities.length)\n\t\t\t});\n\t\t\t\n\t\t\tvar activitiesLength = activities.length;\n\t\t\ttask1.add(activities,function (task1, activityJson) {\n\t\t\t\tvar activity = new ActivityImpl(activityJson);\n\t\t\t\tactivitiesLength --;\n\t\t\t\tprogress += step;\n\t\t\t\tpb1.set('value', parseInt(progress));\n\t\t\t\t//console.log(activitiesLength, \"--> activityId: \" + activity.getId() + \", name: \" + activity.getProperty(\"name\"));\n\t\t\t\tProcessDiagramGenerator.drawActivity(processDiagramCanvas, activity);\n\t\t\t});\n\t\t\t\n\t\t\t// Draw sequence-flows\n\t\t\t\n\t\t\ttask1.add(function (task1) {\n\t\t\t\tif (!sequenceFlows) sequenceFlows = [];\n\t\t\t\t//console.log(\"> draw sequence flows, count:\", sequenceFlows.length)\n\t\t\t});\n\t\t\t\n\t\t\tvar flowsLength = sequenceFlows.length;\n\t\t\ttask1.add(sequenceFlows,function (task1, flow) {\n\t\t\t\tvar waypoints = [];\n\t\t\t\tfor(var j in flow.xPointArray) {\n\t\t\t\t\twaypoints[j] = {x: flow.xPointArray[j], y: flow.yPointArray[j]};\n\t\t\t\t}\n\t\t\t\tvar isDefault = flow.isDefault;\n\t\t\t\tvar isConditional = flow.isConditional;\n\t\t\t\tvar isHighLighted = flow.isHighLighted;\n\t\t\t\t\n\t\t\t\t// TODO: add source and destination for sequence flows in REST\n\t\t\t\t// parse for test\n\t\t\t\t\tvar f = flow.flow;\n\t\t\t\t\tvar matches = f.match(/\\((.*)\\)--.*-->\\((.*)\\)/);\n\t\t\t\t\tvar sourceActivityId, destinationActivityId;\n\t\t\t\t\tif (matches != null) {\n\t\t\t\t\t\tsourceActivityId = matches[1];\n\t\t\t\t\t\tdestinationActivityId = matches[2];\n\t\t\t\t\t}\n\t\t\t\t\tflow.sourceActivityId = sourceActivityId;\n\t\t\t\t\tflow.destinationActivityId = destinationActivityId;\n\t\t\t\t//\n\t\t\t\tflowsLength--;\n\t\t\t\tprogress += step;\n\t\t\t\tpb1.set('value', parseInt(progress));\n\t\t\t\t\n\t\t\t\t//console.log(flowsLength, \"--> flow: \" + flow.flow);\n\t\t\t\t\n\t\t\t\tprocessDiagramCanvas.setConextObject(flow);\n\t\t\t\tprocessDiagramCanvas.drawSequenceflow(waypoints, isConditional, isDefault, isHighLighted);\n\t\t\t});\n\t\t\t\n\t\t\ttask1.onComplete(function(){\n\t\t\t\tif (progress<100)\n\t\t\t\t\tpb1.set('value', 100);\n\t\t\t\t//console.log(\"COMPLETE!!!\");\n\t\t\t\t\t\n\t\t\t\t//console.timeEnd('generateDiagram');\n\t\t\t});\n\t\t\t\n\t\t\ttask1.run();\n\t},\n\t\n\tgetProcessDiagram: function (processDefinitionId) {\n\t\treturn this.processDiagrams[processDefinitionId];\n\t},\n\t\n\tinitProcessDiagramCanvas: function (processDefinitionDiagramLayout) {\n\t\tvar minX = 0;\n\t\tvar maxX = 0;\n\t\tvar minY = 0;\n\t\tvar maxY = 0;\n\t\t\n\t\tif(processDefinitionDiagramLayout.participantProcess != undefined) {\n\t\t  var pProc = processDefinitionDiagramLayout.participantProcess;\n\t\t  \n\t\t  minX = pProc.x;\n\t\t  maxX = pProc.x + pProc.width;\n\t\t  minY = pProc.y;\n\t\t  maxY = pProc.y + pProc.height;\n\t\t}\n\n\t\tvar activities = processDefinitionDiagramLayout.activities;\n\t\tfor(var i in activities) {\n\t\t\tvar activityJson = activities[i];\n\t\t\tvar activity = new ActivityImpl(activityJson);\n\t\t\t\n\t\t\t// width\n\t\t\tif (activity.getX() + activity.getWidth() > maxX) {\n\t\t\t\tmaxX = activity.getX() + activity.getWidth();\n\t\t\t}\n\t\t\tif (activity.getX() < minX) {\n\t\t\t\tminX = activity.getX();\n\t\t\t}\n\t\t\t// height\n\t\t\tif (activity.getY() + activity.getHeight() > maxY) {\n\t\t\t\tmaxY = activity.getY() + activity.getHeight();\n\t\t\t}\n\t\t\tif (activity.getY() < minY) {\n\t\t\t\tminY = activity.getY();\n\t\t\t}\n\t\t}\n\t\t\n\t\tvar sequenceFlows = processDefinitionDiagramLayout.sequenceFlows;\n\t\tfor(var i in sequenceFlows) {\n\t\t\tvar flow = sequenceFlows[i];\n\t\t\tvar waypoints = [];\n\t\t\tfor(var j in flow.xPointArray) {\n\t\t\t\twaypoints[j] = {x: flow.xPointArray[j], y: flow.yPointArray[j]};\n\t\t\t\t\n\t\t\t\t// width\n\t\t\t\tif (waypoints[j].x > maxX) {\n\t\t\t\t\tmaxX = waypoints[j].x;\n\t\t\t\t}\n\t\t\t\tif (waypoints[j].x < minX) {\n\t\t\t\t\tminX = waypoints[j].x;\n\t\t\t\t}\n\t\t\t\t// height\n\t\t\t\tif (waypoints[j].y > maxY) {\n\t\t\t\t\tmaxY = waypoints[j].y;\n\t\t\t\t}\n\t\t\t\tif (waypoints[j].y < minY) {\n\t\t\t\t\tminY = waypoints[j].y;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\tvar laneSets = processDefinitionDiagramLayout.laneSets;\n\t\tfor(var i in laneSets) {\n\t\t\tvar laneSet = laneSets[i];\n\t\t\t//laneSet.id, laneSet.name\n\t\t\t\n\t\t\tfor(var j in laneSet.lanes) {\n\t\t\t\tvar lane = laneSet.lanes[j];\n\t\t\t\t// width\n\t\t\t\tif (lane.x + lane.width > maxX) {\n\t\t\t\t  maxX = lane.x + lane.width;\n\t\t\t\t}\n\t\t\t\tif (lane.x < minX) {\n\t\t\t\t  minX = lane.x;\n\t\t\t\t}\n\t\t\t\t// height\n\t\t\t\tif (lane.y + lane.height > maxY) {\n\t\t\t\t  maxY = lane.y + lane.height;\n\t\t\t\t}\n\t\t\t\tif (lane.y < minY) {\n\t\t\t\t  minY = lane.y;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\n\t\tvar diagramCanvas = new ProcessDiagramCanvas();\n\t\tif (diagramCanvas) {\n\t\t\t\n\t\t\t// create div in diagramHolder\n\t\t\tvar diagramHolder = document.getElementById(this.options.diagramHolderId);\n\t\t\tif (!diagramHolder)\n\t\t\t\tthrow {msg: \"Diagram holder not found\", error: \"diagramHolderNotFound\"};\n\t\t\tvar div = document.createElement(\"DIV\");\n\t\t\tdiv.id = processDefinitionDiagramLayout.processDefinition.id;\n\t\t\tdiv.className = \"diagram\";\n\t\t\tdiagramHolder.appendChild(div);\n\t\t\t\n\t\t\tdiagramCanvas.init(maxX + 20, maxY + 20, processDefinitionDiagramLayout.processDefinition.id);\n\t\t\tthis.processDiagrams[processDefinitionDiagramLayout.processDefinition.id] = {\n\t\t\t\tprocessDefinitionDiagramLayout: processDefinitionDiagramLayout,\n\t\t\t\tdiagramCanvas: diagramCanvas\n\t\t\t};\n\t\t}\n\t\treturn this.getProcessDiagram(processDefinitionDiagramLayout.processDefinition.id);\n\t\t//return new DefaultProcessDiagramCanvas(maxX + 10, maxY + 10, minX, minY);\n\t},\n\t\n\tdrawActivity: function(processDiagramCanvas, activity, highLightedActivities) {\n\t\tvar type = activity.getProperty(\"type\");\n\t\tvar drawInstruction = this.activityDrawInstructions[type];\n\t\tif (drawInstruction != null) {\t\n\t\t\tdrawInstruction.apply({processDiagramCanvas:processDiagramCanvas, activity:activity});\n\t\t} else {\n\t\t\t//console.error(\"no drawInstruction for \" + type + \": \", activity);\n\t\t}\n\t\t\n\t\t// Actually draw the markers\n\t\tif (activity.getProperty(\"multiInstance\") != undefined || activity.getProperty(\"collapsed\") != undefined) {\n\t\t\t//console.log(activity.getProperty(\"name\"), activity.properties);\n\t\t\tvar multiInstanceSequential = (activity.getProperty(\"multiInstance\") == \"sequential\");\n\t\t\tvar multiInstanceParallel = (activity.getProperty(\"multiInstance\") == \"parrallel\");\n\t\t\tvar collapsed = activity.getProperty(\"collapsed\");\n\t\t\t\tprocessDiagramCanvas.drawActivityMarkers(activity.getX(), activity.getY(), activity.getWidth(), activity.getHeight(), \n\t\t\t\t\tmultiInstanceSequential, multiInstanceParallel, collapsed);\n\t\t}\n\t\t/*\n\t\tprocessDiagramCanvas.drawActivityMarkers(activity.getX(), activity.getY(), activity.getWidth(), activity.getHeight(), multiInstanceSequential,\n              multiInstanceParallel, collapsed);\n\t\t*/\n\n\t\t// TODO: Draw highlighted activities if they are present\n\t\t\n\t},\n\t\n\tsetHighLights: function(highLights){\n\t\tif (highLights.processDefinitionId == undefined) {\n\t\t\t//console.error(\"Process instance \" + highLights.processInstanceId + \" doesn't exist\");\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tvar processDiagram = this.getProcessDiagram(highLights.processDefinitionId);\n\t\tif (processDiagram == undefined) {\n\t\t\t//console.error(\"Process diagram \" + highLights.processDefinitionId + \" not found\");\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tvar processDiagramCanvas = processDiagram.diagramCanvas;\n\t\t\n\t\t// TODO: remove highLightes from all activities before set new highLight\n\t\tfor (var i in highLights.activities) {\n\t\t\tvar activityId = highLights.activities[i];\n\t\t\tprocessDiagramCanvas.highLightActivity(activityId);\n\t\t}\n\t\t\n\t\t// TODO: remove highLightes from all flows before set new highLight\n\t\tfor (var i in highLights.flows) {\n\t\t\tvar flowId = highLights.flows[i];\n\t\t\tvar object = processDiagramCanvas.g.getById(flowId);\n\t\t\tvar flow = object.data(\"contextObject\");\n\t\t\tflow.isHighLighted = true;\n\t\t\tprocessDiagramCanvas.highLightFlow(flowId);\n\t\t}\n\t},\n\t\n\tdrawHighLights: function(processInstanceId) {\n\t\t// Load highLights for the processInstanceId\n\t\t/*\n\t\tvar url = Lang.sub(this.options.processInstanceHighLightsUrl, {processInstanceId: processInstanceId});\n\t\t$.ajax({\n\t\t\turl: url,\n\t\t\ttype: 'GET',\n\t\t\tdataType: 'json',\n\t\t\tcache: false,\n\t\t\tasync: true,\n\t\t}).done(function(data) {\n\t\t\tvar highLights = data;\n\t\t\tif (!highLights) {\n\t\t\t\tconsole.log(\"highLights not found\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\tconsole.log(\"highLights[\" + highLights.processDefinitionId + \"][\" + processInstanceId + \"]: \", highLights);\n\t\t\t\n\t\t\tProcessDiagramGenerator.setHighLights(highLights);\n\t\t}).fail(function(jqXHR, textStatus){\n\t\t\tconsole.log('Get HighLights['+processDefinitionId+'] failure: ', textStatus, jqXHR);\n\t\t});\n\t\t*/\n\t\tActivitiRest.getHighLights(processInstanceId, this._drawHighLights);\n\t},\n\t_drawHighLights: function() {\n\t\tvar highLights = this.highLights;\n\t\tProcessDiagramGenerator.setHighLights(highLights);\n\t},\n\t\n\t// Load processDefinition\n\t\n\tdrawDiagram: function(processDefinitionId) {\n\t\t// Hide all diagrams\n\t\tvar diagrams = $(\"#\" + this.options.diagramHolderId + \" div.diagram\");\n\t\tdiagrams.addClass(\"hidden\");\n\t\n\t\n\t\t// If processDefinitionId doesn't contain \":\" then it's a \"processDefinitionKey\", not an id.\n\t\t// Get process definition by key\n\t\tif (processDefinitionId.indexOf(\":\") < 0) {\n\t\t\tActivitiRest.getProcessDefinitionByKey(processDefinitionId, this._drawDiagram);\n\t\t} else {\n\t\t\tthis._drawDiagram.apply({processDefinitionId: processDefinitionId});\n\t\t}\n\t},\n\t_drawDiagram: function() {\n\t\tvar processDefinitionId = this.processDefinitionId;\n\t\t\n\t\tProcessDiagramGenerator.addBreadCrumbsItem(processDefinitionId);\n\t\t\n\t\t\n\t\t// Check if processDefinition is already loaded and rendered\n\t\t\n\t\t\n\t\tvar processDiagram = ProcessDiagramGenerator.getProcessDiagram(processDefinitionId);\n\n\t\tif (processDiagram != undefined && processDiagram != null) {\n\t\t\t//console.log(\"Process diagram \" + processDefinitionId + \" is already loaded\");\n\t\t\t//return;\n\t\t\t\n\t\t\tvar diagram = document.getElementById(processDefinitionId);\n\t\t\t$(diagram).removeClass(\"hidden\");\n\t\t\t\n\t\t\t// Regenerate image\n\t\t\tvar processDefinitionDiagramLayout = processDiagram.processDefinitionDiagramLayout;\n\t\t\tProcessDiagramGenerator.generateDiagram(processDefinitionDiagramLayout);\n\t\t\t\n\t\t\treturn;\n\t\t}\n\n\t\t//console.time('loadDiagram');\n\t\t\n\t\t// Load processDefinition\n\t\t\n\t\tActivitiRest.getProcessDefinition(processDefinitionId, ProcessDiagramGenerator._generateDiagram);\n\t},\n\t_generateDiagram: function() {\n\t\tvar processDefinitionDiagramLayout = this.processDefinitionDiagramLayout;\n\t\t\n\t\t//console.log(\"process-definition-diagram-layout[\"+processDefinitionDiagramLayout.processDefinition.id+\"]: \", processDefinitionDiagramLayout);\n\t\t\n\t\t//console.timeEnd('loadDiagram');\n\t\t//console.time('generateDiagram');\n\t\t\n\t\tpb1.set('value', 0);\n\t\tProcessDiagramGenerator.generateDiagram(processDefinitionDiagramLayout);\n\t},\n\t\n\tgetProcessDefinitionByKey: function(processDefinitionKey) {\n\t\tvar url = Lang.sub(this.options.processDefinitionByKeyUrl, {processDefinitionKey: processDefinitionKey});\n\t\t\n\t\tvar processDefinition;\n\t\t$.ajax({\n\t\t\turl: url,\n\t\t\ttype: 'POST',\n\t\t\tdataType: 'json',\n\t\t\tcache: false,\n\t\t\tasync: false\n\t\t}).done(function(data) { \n\t\t\t//console.log(\"ajax returned data\");\n\t\t\t//console.log(\"ajax returned data:\", data);\n\t\t\tprocessDefinition = data;\n\t\t\tif (!processDefinition) {\n\t\t\t\t//console.error(\"Process definition '\" + processDefinitionKey + \"' not found\");\n\t\t\t}\n\t\t}).fail(function(jqXHR, textStatus){\n\t\t\t//console.error('Get diagram layout['+processDefinitionKey+'] failure: ', textStatus, jqXHR);\n\t\t});\n\t\t\n\t\tif (processDefinition) {\n\t\t\t//console.log(\"Get process definition by key '\" + processDefinitionKey + \"': \", processDefinition.id);\n\t\t\treturn processDefinition;\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t},\n\t\n\taddBreadCrumbsItem: function(processDefinitionId){\n\t\tvar TPL_UL_CONTAINER = '<ul></ul>',\n\t\t\tTPL_LI_CONTAINER = '<li id=\"{id}\", processDefinitionId=\"{processDefinitionId}\"><span>{name}</span></li>';\n\t\t\n\t\tif (!this.diagramBreadCrumbs)\n\t\t\tthis.diagramBreadCrumbs = $(\"#\" + this.options.diagramBreadCrumbsId);\n\t\tif (!this.diagramBreadCrumbs) return;\n\t\t\n\t\t\n\t\tvar ul = this.diagramBreadCrumbs.find(\"ul\");\n\t\t//console.log(\"ul: \", ul);\n\t\tif (ul.size() == 0) {\n\t\t\tul = $(TPL_UL_CONTAINER);\n\t\t\tthis.diagramBreadCrumbs.append(ul);\n\t\t\t\n\t\t}\n\t\tvar liListOld = ul.find(\"li\");\n\t\t//console.warn(\"liListOld\", liListOld);\n\t\t\n\t\t// TODO: if there is any items after current then remove that before adding new item (m.b. it is a duplicate)\n\t\tvar currentBreadCrumbsItemId = this.currentBreadCrumbsItemId;\n\t\t\tfound = false;\n\t\tliListOld.each(\n\t\t\tfunction(index, item) {\n\t\t\t\t//console.warn(\"item:\", $(this));\n\t\t\t\tif (!found && currentBreadCrumbsItemId == $(this).attr(\"id\")) {\n\t\t\t\t\tfound = true;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (found) {\n\t\t\t\t\t//console.warn(\"remove \", $(this).attr(\"id\"));\n\t\t\t\t\t$(this).remove();\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t\t\n\t\tvar liListNew = ul.find(\"li\");\n\t\t\n\t\t//console.log(\"liListNew size: \", liListNew.size());\n\t\tvar values = {\n\t\t\tid: 'breadCrumbsItem_' + liListNew.size(),\n\t\t\tprocessDefinitionId: processDefinitionId,\n\t\t\tname: processDefinitionId\n\t\t};\n\t\t\n\t\t\n\t\tvar tpl = Lang.sub(TPL_LI_CONTAINER, values);\n\t\t//console.log(\"tpl: \", tpl);\n\t\tul.append(tpl);\n\t\t\n\t\tvar li = ul.find(\"#\" + values.id);\n\t\t//console.warn(\"li:\", li);\n\t\t$('#' + values.id).on('click', this._breadCrumbsItemClick);\n\t\t\n\t\tul.find(\"li\").removeClass(\"selected\");\n\t\tli.attr(\"num\", liListNew.size());\n\t\tli.addClass(\"selected\");\n\t\tthis.currentBreadCrumbsItemId = li.attr(\"id\");\n\t},\n\t_breadCrumbsItemClick: function(){\n\t\tvar li = $(this),\n\t\t\tid = li.attr(\"id\"),\n\t\t\tprocessDefinitionId = li.attr(\"processDefinitionId\");\n\t\t//console.warn(\"_breadCrumbsItemClick: \", id, \", processDefinitionId: \", processDefinitionId);\n\t\t\n\t\tvar ul = ProcessDiagramGenerator.diagramBreadCrumbs.one(\"ul\");\n\t\tul.find(\"li\").removeClass(\"selected\");\n\t\tli.addClass(\"selected\");\n\t\tProcessDiagramGenerator.currentBreadCrumbsItemId = li.attr(\"id\");\n\t\t\n\t\t// Hide all diagrams\n\t\tvar diagrams = $(\"#\"+ProcessDiagramGenerator.options.diagramHolderId+\" div.diagram\");\n\t\tdiagrams.addClass(\"hidden\");\n\t\t\n\t\tvar processDiagram = ProcessDiagramGenerator.getProcessDiagram(processDefinitionId);\n\t\t\n\t\tvar diagram = document.getElementById(processDefinitionId);\n\t\tif (!diagram) return;\n\t\t$(diagram).removeClass(\"hidden\");\n\t\t\n\t\t// Regenerate image\n\t\tvar processDefinitionDiagramLayout = processDiagram.processDefinitionDiagramLayout;\n\t\tProcessDiagramGenerator.generateDiagram(processDefinitionDiagramLayout);\n\t},\n\t\n\tshowFlowInfo: function(flow){\n\t\tvar diagramInfo = $(\"#\" + this.options.diagramInfoId);\n\t\tif (!diagramInfo) return;\n\t\t\n\t\tvar values = {\n\t\t\tflow: flow.flow,\n\t\t\tisDefault: (flow.isDefault)? \"true\":\"\",\n\t\t\tisConditional: (flow.isConditional)? \"true\":\"\",\n\t\t\tisHighLighted: (flow.isHighLighted)? \"true\":\"\",\n\t\t\tsourceActivityId: flow.sourceActivityId,\n\t\t\tdestinationActivityId: flow.destinationActivityId\n\t\t};\n\t\tvar TPL_FLOW_INFO = '<div>{flow}</div>' \n\t\t\t\t+ '<div><b>sourceActivityId</b>: {sourceActivityId}</div>'\n\t\t\t\t+ '<div><b>destinationActivityId</b>: {destinationActivityId}</div>'\n\t\t\t\t+ '<div><b>isDefault</b>: {isDefault}</div>'\n\t\t\t\t+ '<div><b>isConditional</b>: {isConditional}</div>'\n\t\t\t\t+ '<div><b>isHighLighted</b>: {isHighLighted}</div>';\n\t\tvar tpl = Lang.sub(TPL_FLOW_INFO, values);\n\t\t//console.log(\"info: \", tpl);\n\t\tdiagramInfo.html(tpl);\n\t},\n\t\n\tshowActivityInfo: function(activity){\n\t\tvar diagramInfo = $(\"#\" + this.options.diagramInfoId);\n\t\tif (!diagramInfo) return;\n\t\t\n\t\tvar values = {\n\t\t\tactivityId: activity.getId(),\n\t\t\tname: activity.getProperty(\"name\"),\n\t\t\ttype: activity.getProperty(\"type\")\n\t\t};\n\t\tvar TPL_ACTIVITY_INFO = '' \n\t\t\t\t+ '<div><b>activityId</b>: {activityId}</div>'\n\t\t\t\t+ '<div><b>name</b>: {name}</div>'\n\t\t\t\t+ '<div><b>type</b>: {type}</div>';\n\t\tvar TPL_CALLACTIVITY_INFO = ''\n\t\t\t\t+ '<div><b>collapsed</b>: {collapsed}</div>'\n\t\t\t\t+ '<div><b>processDefinitonKey</b>: {processDefinitonKey}</div>';\n\t\t\n\t\tvar template = TPL_ACTIVITY_INFO;\n\t\tif (activity.getProperty(\"type\") == \"callActivity\") {\n\t\t\tvalues.collapsed = activity.getProperty(\"collapsed\");\n\t\t\tvalues.processDefinitonKey = activity.getProperty(\"processDefinitonKey\");\n\t\t\ttemplate += TPL_CALLACTIVITY_INFO;\n\t\t} else if (activity.getProperty(\"type\") == \"callActivity\") {\n\t\t\n\t\t}\n\t\t\t\t\n\t\tvar tpl = Lang.sub(template, values);\n\t\t//console.log(\"info: \", tpl);\n\t\tdiagramInfo.html(tpl);\n\t},\n\t\n\thideInfo: function(){\n\t  var diagramInfo = $(\"#\" + this.options.diagramInfoId);\n\t  if (!diagramInfo) return;\n\t  diagramInfo.html(\"\");\n\t},\n\t\n\tvvoid: function(){}\n};\n\nvar Lang = {\n\tSUBREGEX: /\\{\\s*([^\\|\\}]+?)\\s*(?:\\|([^\\}]*))?\\s*\\}/g,\n\tUNDEFINED: 'undefined',\n\tisUndefined: function(o) {\n\t\treturn typeof o === Lang.UNDEFINED;\n\t},\n\tsub: function(s, o) {\n\t\treturn ((s.replace) ? s.replace(Lang.SUBREGEX, function(match, key) {\n\t\t\treturn (!Lang.isUndefined(o[key])) ? o[key] : match;\n\t\t}) : s);\n\t}\n};\n\nif (Lang.isUndefined(console)) {\n    console = { log: function() {}, warn: function() {}, error: function() {}};\n}\nProcessDiagramGenerator.init();"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/diagram-viewer/js/jquery/jquery.asyncqueue.js",
    "content": "/*\n* This file is part of the jquery plugin \"asyncQueue\".\n*\n* (c) Sebastien Roch <roch.sebastien@gmail.com>\n* @author (parallel) Dmitry Farafonov\n*\n* For the full copyright and license information, please view the LICENSE\n* file that was distributed with this source code.\n*/\n(function($){\n    $.AsyncQueue = function() {\n        var that = this,\n            queue = [],\n\t\t\tcompleteFunc,\n            failureFunc,\n            paused = false,\n            lastCallbackData,\n            _run,\n\t\t\t_complete,\n\t\t\tinQueue = 0,\n\t\t\tdefaultTimeOut = 10;\n\n        _run = function() {\n            var f = queue.shift();\n\n            if (f) {\n\t\t\t\tinQueue++;\n\t\t\t\tsetTimeout(function(){\n\t\t\t\t\tf.fn.apply(that, [that]);\n\t\t\t\t\n\t\t\t\t\tif (!f.isParallel)\n\t\t\t\t\t\tif (paused === false) {\n\t\t\t\t\t\t\t_run();\n\t\t\t\t\t\t}\n\t\t\t\t\tinQueue --;\n\t\t\t\t\tif (inQueue == 0 && queue.length == 0)\n\t\t\t\t\t\t_complete();\n\t\t\t\t}, f.timeOut);                \n\t\t\t\t\n\t\t\t\tif (f.isParallel)\n\t\t\t\t\tif (paused === false) {\n\t\t\t\t\t\t_run();\n\t\t\t\t\t}\n            }\n        };\n\t\t\n\t\t_complete = function(){\n\t\t\tif (completeFunc)\n\t\t\t\t\tcompleteFunc.apply(that, [that]);\n\t\t};\n\n\t\tthis.onComplete = function(func) {\n            completeFunc = func;\n        };\n\t\t\n\t\tthis.onFailure = function(func) {\n            failureFunc = func;\n        };\n\n        this.add = function(func) {\n\t\t\t// TODO: add callback for queue[i] complete\n\t\t\t\n\t\t\tvar obj = arguments[0];\n\t\t\tif (obj && Object.prototype.toString.call(obj) === \"[object Array]\") {\n\t\t\t\tvar fn = arguments[1];\n\t\t\t\tvar timeOut = (typeof(arguments[2]) != \"undefined\")? arguments[2] : defaultTimeOut;\n\t\t\t\tif (typeof(fn) == \"function\") {\n\t\t\t\t\tfor(var i = 0; i < obj.length; i++) {\n\t\t\t\t\t\tvar f = function(objx){\n\t\t\t\t\t\t\tqueue.push({isParallel: true, fn: function(){fn.apply(that, [that, objx]);}, timeOut: timeOut});\n\t\t\t\t\t\t}(obj[i])\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tvar fn = arguments[0];\n\t\t\t\tvar timeOut = (typeof(arguments[1]) != \"undefined\")? arguments[2] : defaultTimeOut;\n\t\t\t\tqueue.push({isParallel: false, fn: func, timeOut: timeOut});\n\t\t\t}\n            return this;\n        };\n\t\t\n\t\tthis.addParallel = function(func, timeOut) {\n\t\t\t// TODO: add callback for queue[i] complete\n\t\t\t\n            queue.push({isParallel: true, fn: func, timeOut: timeOut});\n            return this;\n        };\n\n        this.storeData = function(dataObject) {\n            lastCallbackData = dataObject;\n            return this;\n        };\n\n        this.lastCallbackData = function () {\n            return lastCallbackData;\n        };\n\n        this.run = function() {\n            paused = false;\n            _run();\n        };\n\n        this.pause = function () {\n            paused = true;\n            return this;\n        };\n\n        this.failure = function() {\n            paused = true;\n            if (failureFunc) {\n                var args = [that];\n                for(i = 0; i < arguments.length; i++) {\n                    args.push(arguments[i]);\n                }\n                failureFunc.apply(that, args);\n            }\n        };\n\t\t\n\t\tthis.size = function(){\n\t\t\treturn queue.length;\n\t\t};\n\n        return this;\n    }\n})(jQuery);\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/diagram-viewer/js/jquery/jquery.js",
    "content": "/*!\n * jQuery JavaScript Library v1.7.1\n * http://jquery.com/\n *\n * Copyright 2011, John Resig\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n * Copyright 2011, The Dojo Foundation\n * Released under the MIT, BSD, and GPL Licenses.\n *\n * Date: Mon Nov 21 21:11:03 2011 -0500\n */\n(function( window, undefined ) {\n\n// Use the correct document accordingly with window argument (sandbox)\nvar document = window.document,\n\tnavigator = window.navigator,\n\tlocation = window.location;\nvar jQuery = (function() {\n\n// Define a local copy of jQuery\nvar jQuery = 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// 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// A central reference to the root jQuery(document)\n\trootjQuery,\n\n\t// A simple way to check for HTML strings or ID strings\n\t// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n\tquickExpr = /^(?:[^#<]*(<[\\w\\W]+>)[^>]*$|#([\\w\\-]*)$)/,\n\n\t// Check if a string has a non-whitespace character in it\n\trnotwhite = /\\S/,\n\n\t// Used for trimming whitespace\n\ttrimLeft = /^\\s+/,\n\ttrimRight = /\\s+$/,\n\n\t// Match a standalone tag\n\trsingleTag = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>)?$/,\n\n\t// JSON RegExp\n\trvalidchars = /^[\\],:{}\\s]*$/,\n\trvalidescape = /\\\\(?:[\"\\\\\\/bfnrt]|u[0-9a-fA-F]{4})/g,\n\trvalidtokens = /\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g,\n\trvalidbraces = /(?:^|:|,)(?:\\s*\\[)+/g,\n\n\t// Useragent RegExp\n\trwebkit = /(webkit)[ \\/]([\\w.]+)/,\n\tropera = /(opera)(?:.*version)?[ \\/]([\\w.]+)/,\n\trmsie = /(msie) ([\\w.]+)/,\n\trmozilla = /(mozilla)(?:.*? rv:([\\w.]+))?/,\n\n\t// Matches dashed string for camelizing\n\trdashAlpha = /-([a-z]|[0-9])/ig,\n\trmsPrefix = /^-ms-/,\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// Keep a UserAgent string for use with jQuery.browser\n\tuserAgent = navigator.userAgent,\n\n\t// For matching the engine and version of the browser\n\tbrowserMatch,\n\n\t// The deferred used on DOM ready\n\treadyList,\n\n\t// The ready event handler\n\tDOMContentLoaded,\n\n\t// Save a reference to some core methods\n\ttoString = Object.prototype.toString,\n\thasOwn = Object.prototype.hasOwnProperty,\n\tpush = Array.prototype.push,\n\tslice = Array.prototype.slice,\n\ttrim = String.prototype.trim,\n\tindexOf = Array.prototype.indexOf,\n\n\t// [[Class]] -> type pairs\n\tclass2type = {};\n\njQuery.fn = jQuery.prototype = {\n\tconstructor: jQuery,\n\tinit: function( selector, context, rootjQuery ) {\n\t\tvar match, elem, ret, doc;\n\n\t\t// Handle $(\"\"), $(null), or $(undefined)\n\t\tif ( !selector ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle $(DOMElement)\n\t\tif ( selector.nodeType ) {\n\t\t\tthis.context = this[0] = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\t\t}\n\n\t\t// The body element only exists once, optimize finding it\n\t\tif ( selector === \"body\" && !context && document.body ) {\n\t\t\tthis.context = document;\n\t\t\tthis[0] = document.body;\n\t\t\tthis.selector = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle HTML strings\n\t\tif ( typeof selector === \"string\" ) {\n\t\t\t// Are we dealing with HTML string or an ID?\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 = quickExpr.exec( selector );\n\t\t\t}\n\n\t\t\t// Verify a match, and that no context was 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\t\t\t\t\tdoc = ( context ? context.ownerDocument || context : document );\n\n\t\t\t\t\t// If a single string is passed in and it's a single tag\n\t\t\t\t\t// just do a createElement and skip the rest\n\t\t\t\t\tret = rsingleTag.exec( selector );\n\n\t\t\t\t\tif ( ret ) {\n\t\t\t\t\t\tif ( jQuery.isPlainObject( context ) ) {\n\t\t\t\t\t\t\tselector = [ document.createElement( ret[1] ) ];\n\t\t\t\t\t\t\tjQuery.fn.attr.call( selector, context, true );\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tselector = [ doc.createElement( ret[1] ) ];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tret = jQuery.buildFragment( [ match[1] ], [ doc ] );\n\t\t\t\t\t\tselector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn jQuery.merge( this, selector );\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: $(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 current version of jQuery being used\n\tjquery: \"1.7.1\",\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 slice.call( this, 0 );\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, name, selector ) {\n\t\t// Build a new jQuery matched element set\n\t\tvar ret = this.constructor();\n\n\t\tif ( jQuery.isArray( elems ) ) {\n\t\t\tpush.apply( ret, elems );\n\n\t\t} else {\n\t\t\tjQuery.merge( ret, elems );\n\t\t}\n\n\t\t// Add the old object onto the stack (as a reference)\n\t\tret.prevObject = this;\n\n\t\tret.context = this.context;\n\n\t\tif ( name === \"find\" ) {\n\t\t\tret.selector = this.selector + ( this.selector ? \" \" : \"\" ) + selector;\n\t\t} else if ( name ) {\n\t\t\tret.selector = this.selector + \".\" + name + \"(\" + selector + \")\";\n\t\t}\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// Attach the listeners\n\t\tjQuery.bindReady();\n\n\t\t// Add the callback\n\t\treadyList.add( fn );\n\n\t\treturn this;\n\t},\n\n\teq: function( i ) {\n\t\ti = +i;\n\t\treturn i === -1 ?\n\t\t\tthis.slice( i ) :\n\t\t\tthis.slice( i, i + 1 );\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\tslice: function() {\n\t\treturn this.pushStack( slice.apply( this, arguments ),\n\t\t\t\"slice\", slice.call(arguments).join(\",\") );\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: 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 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\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\t\t// Either a released hold or an DOMready/load event and not yet ready\n\t\tif ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {\n\t\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\t\tif ( !document.body ) {\n\t\t\t\treturn setTimeout( jQuery.ready, 1 );\n\t\t\t}\n\n\t\t\t// Remember that the DOM is ready\n\t\t\tjQuery.isReady = true;\n\n\t\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If there are functions bound, to execute\n\t\t\treadyList.fireWith( document, [ jQuery ] );\n\n\t\t\t// Trigger any bound ready events\n\t\t\tif ( jQuery.fn.trigger ) {\n\t\t\t\tjQuery( document ).trigger( \"ready\" ).off( \"ready\" );\n\t\t\t}\n\t\t}\n\t},\n\n\tbindReady: function() {\n\t\tif ( readyList ) {\n\t\t\treturn;\n\t\t}\n\n\t\treadyList = jQuery.Callbacks( \"once memory\" );\n\n\t\t// Catch cases where $(document).ready() is called after the\n\t\t// browser event has already occurred.\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\t\t\treturn setTimeout( jQuery.ready, 1 );\n\t\t}\n\n\t\t// Mozilla, Opera and webkit nightlies currently support this event\n\t\tif ( document.addEventListener ) {\n\t\t\t// Use the handy event callback\n\t\t\tdocument.addEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.addEventListener( \"load\", jQuery.ready, false );\n\n\t\t// If IE event model is used\n\t\t} else if ( document.attachEvent ) {\n\t\t\t// ensure firing before onload,\n\t\t\t// maybe late but safe also for iframes\n\t\t\tdocument.attachEvent( \"onreadystatechange\", DOMContentLoaded );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.attachEvent( \"onload\", jQuery.ready );\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 toplevel = false;\n\n\t\t\ttry {\n\t\t\t\ttoplevel = window.frameElement == null;\n\t\t\t} catch(e) {}\n\n\t\t\tif ( document.documentElement.doScroll && toplevel ) {\n\t\t\t\tdoScrollCheck();\n\t\t\t}\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\t// A crude way of determining if an object is a window\n\tisWindow: function( obj ) {\n\t\treturn obj && typeof obj === \"object\" && \"setInterval\" in obj;\n\t},\n\n\tisNumeric: function( obj ) {\n\t\treturn !isNaN( parseFloat(obj) ) && isFinite( obj );\n\t},\n\n\ttype: function( obj ) {\n\t\treturn obj == null ?\n\t\t\tString( obj ) :\n\t\t\tclass2type[ toString.call(obj) ] || \"object\";\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!hasOwn.call(obj, \"constructor\") &&\n\t\t\t\t!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 || hasOwn.call( obj, key );\n\t},\n\n\tisEmptyObject: function( obj ) {\n\t\tfor ( var 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\tparseJSON: function( data ) {\n\t\tif ( typeof data !== \"string\" || !data ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Make sure leading/trailing whitespace is removed (IE can't handle it)\n\t\tdata = jQuery.trim( data );\n\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\t// Make sure the incoming data is actual JSON\n\t\t// Logic borrowed from http://json.org/json2.js\n\t\tif ( rvalidchars.test( data.replace( rvalidescape, \"@\" )\n\t\t\t.replace( rvalidtokens, \"]\" )\n\t\t\t.replace( rvalidbraces, \"\")) ) {\n\n\t\t\treturn ( new Function( \"return \" + data ) )();\n\n\t\t}\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\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 && rnotwhite.test( 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.toUpperCase() === name.toUpperCase();\n\t},\n\n\t// args is for internal usage only\n\teach: function( object, callback, args ) {\n\t\tvar name, i = 0,\n\t\t\tlength = object.length,\n\t\t\tisObj = length === undefined || jQuery.isFunction( object );\n\n\t\tif ( args ) {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in object ) {\n\t\t\t\t\tif ( callback.apply( object[ name ], args ) === 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 < length; ) {\n\t\t\t\t\tif ( callback.apply( object[ i++ ], args ) === 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 util use of each\n\t\t} else {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in object ) {\n\t\t\t\t\tif ( callback.call( object[ name ], name, object[ name ] ) === 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 < length; ) {\n\t\t\t\t\tif ( callback.call( object[ i ], i, object[ i++ ] ) === 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 object;\n\t},\n\n\t// Use native String.trim function wherever possible\n\ttrim: trim ?\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\ttrim.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\ttext.toString().replace( trimLeft, \"\" ).replace( trimRight, \"\" );\n\t\t},\n\n\t// results is for internal usage only\n\tmakeArray: function( array, results ) {\n\t\tvar ret = results || [];\n\n\t\tif ( array != null ) {\n\t\t\t// The window, strings (and functions) also have 'length'\n\t\t\t// Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930\n\t\t\tvar type = jQuery.type( array );\n\n\t\t\tif ( array.length == null || type === \"string\" || type === \"function\" || type === \"regexp\" || jQuery.isWindow( array ) ) {\n\t\t\t\tpush.call( ret, array );\n\t\t\t} else {\n\t\t\t\tjQuery.merge( ret, array );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tinArray: function( elem, array, i ) {\n\t\tvar len;\n\n\t\tif ( array ) {\n\t\t\tif ( indexOf ) {\n\t\t\t\treturn indexOf.call( array, elem, i );\n\t\t\t}\n\n\t\t\tlen = array.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 array && array[ 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 i = first.length,\n\t\t\tj = 0;\n\n\t\tif ( typeof second.length === \"number\" ) {\n\t\t\tfor ( var l = second.length; j < l; j++ ) {\n\t\t\t\tfirst[ i++ ] = second[ j ];\n\t\t\t}\n\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 ret = [], retVal;\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 ( var i = 0, length = elems.length; 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, key, ret = [],\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\t// jquery objects are treated as arrays\n\t\t\tisArray = elems instanceof jQuery || length !== undefined && typeof length === \"number\" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;\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 ( key in elems ) {\n\t\t\t\tvalue = callback( elems[ key ], key, 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 ret.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\tif ( typeof context === \"string\" ) {\n\t\t\tvar tmp = 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\tvar args = slice.call( arguments, 2 ),\n\t\t\tproxy = function() {\n\t\t\t\treturn fn.apply( context, args.concat( slice.call( arguments ) ) );\n\t\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 || proxy.guid || jQuery.guid++;\n\n\t\treturn proxy;\n\t},\n\n\t// Mutifunctional method to get and set values to a collection\n\t// The value/s can optionally be executed if it's a function\n\taccess: function( elems, key, value, exec, fn, pass ) {\n\t\tvar length = elems.length;\n\n\t\t// Setting many attributes\n\t\tif ( typeof key === \"object\" ) {\n\t\t\tfor ( var k in key ) {\n\t\t\t\tjQuery.access( elems, k, key[k], exec, fn, value );\n\t\t\t}\n\t\t\treturn elems;\n\t\t}\n\n\t\t// Setting one attribute\n\t\tif ( value !== undefined ) {\n\t\t\t// Optionally, function values get executed if exec is true\n\t\t\texec = !pass && exec && jQuery.isFunction(value);\n\n\t\t\tfor ( var i = 0; i < length; i++ ) {\n\t\t\t\tfn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );\n\t\t\t}\n\n\t\t\treturn elems;\n\t\t}\n\n\t\t// Getting an attribute\n\t\treturn length ? fn( elems[0], key ) : undefined;\n\t},\n\n\tnow: function() {\n\t\treturn ( new Date() ).getTime();\n\t},\n\n\t// Use of jQuery.browser is frowned upon.\n\t// More details: http://docs.jquery.com/Utilities/jQuery.browser\n\tuaMatch: function( ua ) {\n\t\tua = ua.toLowerCase();\n\n\t\tvar match = rwebkit.exec( ua ) ||\n\t\t\tropera.exec( ua ) ||\n\t\t\trmsie.exec( ua ) ||\n\t\t\tua.indexOf(\"compatible\") < 0 && rmozilla.exec( ua ) ||\n\t\t\t[];\n\n\t\treturn { browser: match[1] || \"\", version: match[2] || \"0\" };\n\t},\n\n\tsub: function() {\n\t\tfunction jQuerySub( selector, context ) {\n\t\t\treturn new jQuerySub.fn.init( selector, context );\n\t\t}\n\t\tjQuery.extend( true, jQuerySub, this );\n\t\tjQuerySub.superclass = this;\n\t\tjQuerySub.fn = jQuerySub.prototype = this();\n\t\tjQuerySub.fn.constructor = jQuerySub;\n\t\tjQuerySub.sub = this.sub;\n\t\tjQuerySub.fn.init = function init( selector, context ) {\n\t\t\tif ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {\n\t\t\t\tcontext = jQuerySub( context );\n\t\t\t}\n\n\t\t\treturn jQuery.fn.init.call( this, selector, context, rootjQuerySub );\n\t\t};\n\t\tjQuerySub.fn.init.prototype = jQuerySub.fn;\n\t\tvar rootjQuerySub = jQuerySub(document);\n\t\treturn jQuerySub;\n\t},\n\n\tbrowser: {}\n});\n\n// Populate the class2type map\njQuery.each(\"Boolean Number String Function Array Date RegExp Object\".split(\" \"), function(i, name) {\n\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n});\n\nbrowserMatch = jQuery.uaMatch( userAgent );\nif ( browserMatch.browser ) {\n\tjQuery.browser[ browserMatch.browser ] = true;\n\tjQuery.browser.version = browserMatch.version;\n}\n\n// Deprecated, use jQuery.browser.webkit instead\nif ( jQuery.browser.webkit ) {\n\tjQuery.browser.safari = true;\n}\n\n// IE doesn't match non-breaking spaces with \\s\nif ( rnotwhite.test( \"\\xA0\" ) ) {\n\ttrimLeft = /^[\\s\\xA0]+/;\n\ttrimRight = /[\\s\\xA0]+$/;\n}\n\n// All jQuery objects should point back to these\nrootjQuery = jQuery(document);\n\n// Cleanup functions for the document ready method\nif ( document.addEventListener ) {\n\tDOMContentLoaded = function() {\n\t\tdocument.removeEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\t\tjQuery.ready();\n\t};\n\n} else if ( document.attachEvent ) {\n\tDOMContentLoaded = function() {\n\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\tdocument.detachEvent( \"onreadystatechange\", DOMContentLoaded );\n\t\t\tjQuery.ready();\n\t\t}\n\t};\n}\n\n// The DOM ready check for Internet Explorer\nfunction doScrollCheck() {\n\tif ( jQuery.isReady ) {\n\t\treturn;\n\t}\n\n\ttry {\n\t\t// If IE is used, use the trick by Diego Perini\n\t\t// http://javascript.nwbox.com/IEContentLoaded/\n\t\tdocument.documentElement.doScroll(\"left\");\n\t} catch(e) {\n\t\tsetTimeout( doScrollCheck, 1 );\n\t\treturn;\n\t}\n\n\t// and execute any waiting functions\n\tjQuery.ready();\n}\n\nreturn jQuery;\n\n})();\n\n\n// String to Object flags format cache\nvar flagsCache = {};\n\n// Convert String-formatted flags into Object-formatted ones and store in cache\nfunction createFlags( flags ) {\n\tvar object = flagsCache[ flags ] = {},\n\t\ti, length;\n\tflags = flags.split( /\\s+/ );\n\tfor ( i = 0, length = flags.length; i < length; i++ ) {\n\t\tobject[ flags[i] ] = true;\n\t}\n\treturn object;\n}\n\n/*\n * Create a callback list using the following parameters:\n *\n *\tflags:\tan optional list of space-separated flags that will change how\n *\t\t\tthe callback list behaves\n *\n * By default a callback list will act like an event callback list and can be\n * \"fired\" multiple times.\n *\n * Possible flags:\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( flags ) {\n\n\t// Convert flags from String-formatted to Object-formatted\n\t// (we check in cache first)\n\tflags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};\n\n\tvar // Actual callback list\n\t\tlist = [],\n\t\t// Stack of fire calls for repeatable lists\n\t\tstack = [],\n\t\t// Last fire value (for non-forgettable lists)\n\t\tmemory,\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// Add one or several callbacks to the list\n\t\tadd = function( args ) {\n\t\t\tvar i,\n\t\t\t\tlength,\n\t\t\t\telem,\n\t\t\t\ttype,\n\t\t\t\tactual;\n\t\t\tfor ( i = 0, length = args.length; i < length; i++ ) {\n\t\t\t\telem = args[ i ];\n\t\t\t\ttype = jQuery.type( elem );\n\t\t\t\tif ( type === \"array\" ) {\n\t\t\t\t\t// Inspect recursively\n\t\t\t\t\tadd( elem );\n\t\t\t\t} else if ( type === \"function\" ) {\n\t\t\t\t\t// Add if not in unique mode and callback is not in\n\t\t\t\t\tif ( !flags.unique || !self.has( elem ) ) {\n\t\t\t\t\t\tlist.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Fire callbacks\n\t\tfire = function( context, args ) {\n\t\t\targs = args || [];\n\t\t\tmemory = !flags.memory || [ context, args ];\n\t\t\tfiring = true;\n\t\t\tfiringIndex = firingStart || 0;\n\t\t\tfiringStart = 0;\n\t\t\tfiringLength = list.length;\n\t\t\tfor ( ; list && firingIndex < firingLength; firingIndex++ ) {\n\t\t\t\tif ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {\n\t\t\t\t\tmemory = true; // Mark as halted\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 ( !flags.once ) {\n\t\t\t\t\tif ( stack && stack.length ) {\n\t\t\t\t\t\tmemory = stack.shift();\n\t\t\t\t\t\tself.fireWith( memory[ 0 ], memory[ 1 ] );\n\t\t\t\t\t}\n\t\t\t\t} else if ( memory === true ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t} else {\n\t\t\t\t\tlist = [];\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\tvar length = list.length;\n\t\t\t\t\tadd( 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, unless previous\n\t\t\t\t\t// firing was halted (stopOnFalse)\n\t\t\t\t\t} else if ( memory && memory !== true ) {\n\t\t\t\t\t\tfiringStart = length;\n\t\t\t\t\t\tfire( memory[ 0 ], memory[ 1 ] );\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\tvar args = arguments,\n\t\t\t\t\t\targIndex = 0,\n\t\t\t\t\t\targLength = args.length;\n\t\t\t\t\tfor ( ; argIndex < argLength ; argIndex++ ) {\n\t\t\t\t\t\tfor ( var i = 0; i < list.length; i++ ) {\n\t\t\t\t\t\t\tif ( args[ argIndex ] === list[ i ] ) {\n\t\t\t\t\t\t\t\t// Handle firingIndex and firingLength\n\t\t\t\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\t\t\t\tif ( i <= firingLength ) {\n\t\t\t\t\t\t\t\t\t\tfiringLength--;\n\t\t\t\t\t\t\t\t\t\tif ( i <= firingIndex ) {\n\t\t\t\t\t\t\t\t\t\t\tfiringIndex--;\n\t\t\t\t\t\t\t\t\t\t}\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// Remove the element\n\t\t\t\t\t\t\t\tlist.splice( i--, 1 );\n\t\t\t\t\t\t\t\t// If we have some unicity property then\n\t\t\t\t\t\t\t\t// we only need to do this once\n\t\t\t\t\t\t\t\tif ( flags.unique ) {\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\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// Control if a given callback is in the list\n\t\t\thas: function( fn ) {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tvar i = 0,\n\t\t\t\t\t\tlength = list.length;\n\t\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\t\tif ( fn === list[ i ] ) {\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\treturn false;\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 || memory === true ) {\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 ( stack ) {\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tif ( !flags.once ) {\n\t\t\t\t\t\t\tstack.push( [ context, args ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if ( !( flags.once && memory ) ) {\n\t\t\t\t\t\tfire( context, 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 !!memory;\n\t\t\t}\n\t\t};\n\n\treturn self;\n};\n\n\n\n\nvar // Static reference to slice\n\tsliceDeferred = [].slice;\n\njQuery.extend({\n\n\tDeferred: function( func ) {\n\t\tvar doneList = jQuery.Callbacks( \"once memory\" ),\n\t\t\tfailList = jQuery.Callbacks( \"once memory\" ),\n\t\t\tprogressList = jQuery.Callbacks( \"memory\" ),\n\t\t\tstate = \"pending\",\n\t\t\tlists = {\n\t\t\t\tresolve: doneList,\n\t\t\t\treject: failList,\n\t\t\t\tnotify: progressList\n\t\t\t},\n\t\t\tpromise = {\n\t\t\t\tdone: doneList.add,\n\t\t\t\tfail: failList.add,\n\t\t\t\tprogress: progressList.add,\n\n\t\t\t\tstate: function() {\n\t\t\t\t\treturn state;\n\t\t\t\t},\n\n\t\t\t\t// Deprecated\n\t\t\t\tisResolved: doneList.fired,\n\t\t\t\tisRejected: failList.fired,\n\n\t\t\t\tthen: function( doneCallbacks, failCallbacks, progressCallbacks ) {\n\t\t\t\t\tdeferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\talways: function() {\n\t\t\t\t\tdeferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\tpipe: function( fnDone, fnFail, fnProgress ) {\n\t\t\t\t\treturn jQuery.Deferred(function( newDefer ) {\n\t\t\t\t\t\tjQuery.each( {\n\t\t\t\t\t\t\tdone: [ fnDone, \"resolve\" ],\n\t\t\t\t\t\t\tfail: [ fnFail, \"reject\" ],\n\t\t\t\t\t\t\tprogress: [ fnProgress, \"notify\" ]\n\t\t\t\t\t\t}, function( handler, data ) {\n\t\t\t\t\t\t\tvar fn = data[ 0 ],\n\t\t\t\t\t\t\t\taction = data[ 1 ],\n\t\t\t\t\t\t\t\treturned;\n\t\t\t\t\t\t\tif ( jQuery.isFunction( fn ) ) {\n\t\t\t\t\t\t\t\tdeferred[ handler ](function() {\n\t\t\t\t\t\t\t\t\treturned = fn.apply( this, arguments );\n\t\t\t\t\t\t\t\t\tif ( returned && jQuery.isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\t\t\t\treturned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify );\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tnewDefer[ action + \"With\" ]( this === deferred ? newDefer : this, [ returned ] );\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} else {\n\t\t\t\t\t\t\t\tdeferred[ handler ]( newDefer[ action ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\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\tif ( obj == null ) {\n\t\t\t\t\t\tobj = promise;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfor ( var key in promise ) {\n\t\t\t\t\t\t\tobj[ key ] = promise[ key ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn obj;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdeferred = promise.promise({}),\n\t\t\tkey;\n\n\t\tfor ( key in lists ) {\n\t\t\tdeferred[ key ] = lists[ key ].fire;\n\t\t\tdeferred[ key + \"With\" ] = lists[ key ].fireWith;\n\t\t}\n\n\t\t// Handle state\n\t\tdeferred.done( function() {\n\t\t\tstate = \"resolved\";\n\t\t}, failList.disable, progressList.lock ).fail( function() {\n\t\t\tstate = \"rejected\";\n\t\t}, doneList.disable, progressList.lock );\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( firstParam ) {\n\t\tvar args = sliceDeferred.call( arguments, 0 ),\n\t\t\ti = 0,\n\t\t\tlength = args.length,\n\t\t\tpValues = new Array( length ),\n\t\t\tcount = length,\n\t\t\tpCount = length,\n\t\t\tdeferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?\n\t\t\t\tfirstParam :\n\t\t\t\tjQuery.Deferred(),\n\t\t\tpromise = deferred.promise();\n\t\tfunction resolveFunc( i ) {\n\t\t\treturn function( value ) {\n\t\t\t\targs[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;\n\t\t\t\tif ( !( --count ) ) {\n\t\t\t\t\tdeferred.resolveWith( deferred, args );\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\tfunction progressFunc( i ) {\n\t\t\treturn function( value ) {\n\t\t\t\tpValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;\n\t\t\t\tdeferred.notifyWith( promise, pValues );\n\t\t\t};\n\t\t}\n\t\tif ( length > 1 ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) {\n\t\t\t\t\targs[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) );\n\t\t\t\t} else {\n\t\t\t\t\t--count;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( !count ) {\n\t\t\t\tdeferred.resolveWith( deferred, args );\n\t\t\t}\n\t\t} else if ( deferred !== firstParam ) {\n\t\t\tdeferred.resolveWith( deferred, length ? [ firstParam ] : [] );\n\t\t}\n\t\treturn promise;\n\t}\n});\n\n\n\n\njQuery.support = (function() {\n\n\tvar support,\n\t\tall,\n\t\ta,\n\t\tselect,\n\t\topt,\n\t\tinput,\n\t\tmarginDiv,\n\t\tfragment,\n\t\ttds,\n\t\tevents,\n\t\teventName,\n\t\ti,\n\t\tisSupported,\n\t\tdiv = document.createElement( \"div\" ),\n\t\tdocumentElement = document.documentElement;\n\n\t// Preliminary tests\n\tdiv.setAttribute(\"className\", \"t\");\n\tdiv.innerHTML = \"   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>\";\n\n\tall = div.getElementsByTagName( \"*\" );\n\ta = div.getElementsByTagName( \"a\" )[ 0 ];\n\n\t// Can't get basic test support\n\tif ( !all || !all.length || !a ) {\n\t\treturn {};\n\t}\n\n\t// First batch of supports tests\n\tselect = document.createElement( \"select\" );\n\topt = select.appendChild( document.createElement(\"option\") );\n\tinput = div.getElementsByTagName( \"input\" )[ 0 ];\n\n\tsupport = {\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.55/.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// Make sure that if no value is specified for a checkbox\n\t\t// that it defaults to \"on\".\n\t\t// (WebKit defaults to \"\" instead)\n\t\tcheckOn: ( input.value === \"on\" ),\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// 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// 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// Will be defined later\n\t\tsubmitBubbles: true,\n\t\tchangeBubbles: true,\n\t\tfocusinBubbles: false,\n\t\tdeleteExpando: true,\n\t\tnoCloneEvent: true,\n\t\tinlineBlockNeedsLayout: false,\n\t\tshrinkWrapBlocks: false,\n\t\treliableMarginRight: true\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// Test to see if it's possible to delete an expando from an element\n\t// Fails in Internet Explorer\n\ttry {\n\t\tdelete div.test;\n\t} catch( e ) {\n\t\tsupport.deleteExpando = false;\n\t}\n\n\tif ( !div.addEventListener && div.attachEvent && div.fireEvent ) {\n\t\tdiv.attachEvent( \"onclick\", function() {\n\t\t\t// Cloning a node shouldn't copy over any\n\t\t\t// bound event handlers (IE does this)\n\t\t\tsupport.noCloneEvent = false;\n\t\t});\n\t\tdiv.cloneNode( true ).fireEvent( \"onclick\" );\n\t}\n\n\t// Check if a radio maintains its value\n\t// after being appended to the DOM\n\tinput = document.createElement(\"input\");\n\tinput.value = \"t\";\n\tinput.setAttribute(\"type\", \"radio\");\n\tsupport.radioValue = input.value === \"t\";\n\n\tinput.setAttribute(\"checked\", \"checked\");\n\tdiv.appendChild( input );\n\tfragment = document.createDocumentFragment();\n\tfragment.appendChild( div.lastChild );\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// 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\tfragment.removeChild( input );\n\tfragment.appendChild( div );\n\n\tdiv.innerHTML = \"\";\n\n\t// Check if div with explicit width and no margin-right incorrectly\n\t// gets computed margin-right based on width of container. For more\n\t// info see bug #3333\n\t// Fails in WebKit before Feb 2011 nightlies\n\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\tif ( window.getComputedStyle ) {\n\t\tmarginDiv = document.createElement( \"div\" );\n\t\tmarginDiv.style.width = \"0\";\n\t\tmarginDiv.style.marginRight = \"0\";\n\t\tdiv.style.width = \"2px\";\n\t\tdiv.appendChild( marginDiv );\n\t\tsupport.reliableMarginRight =\n\t\t\t( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;\n\t}\n\n\t// Technique from Juriy Zaytsev\n\t// http://perfectionkills.com/detecting-event-support-without-browser-sniffing/\n\t// We only care about the case where non-standard event systems\n\t// are used, namely in IE. Short-circuiting here helps us to\n\t// avoid an eval call (in setAttribute) which can cause CSP\n\t// to go haywire. See: https://developer.mozilla.org/en/Security/CSP\n\tif ( div.attachEvent ) {\n\t\tfor( i in {\n\t\t\tsubmit: 1,\n\t\t\tchange: 1,\n\t\t\tfocusin: 1\n\t\t}) {\n\t\t\teventName = \"on\" + i;\n\t\t\tisSupported = ( eventName in div );\n\t\t\tif ( !isSupported ) {\n\t\t\t\tdiv.setAttribute( eventName, \"return;\" );\n\t\t\t\tisSupported = ( typeof div[ eventName ] === \"function\" );\n\t\t\t}\n\t\t\tsupport[ i + \"Bubbles\" ] = isSupported;\n\t\t}\n\t}\n\n\tfragment.removeChild( div );\n\n\t// Null elements to avoid leaks in IE\n\tfragment = select = opt = marginDiv = div = input = null;\n\n\t// Run tests that need a body at doc ready\n\tjQuery(function() {\n\t\tvar container, outer, inner, table, td, offsetSupport,\n\t\t\tconMarginTop, ptlm, vb, style, html,\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\tconMarginTop = 1;\n\t\tptlm = \"position:absolute;top:0;left:0;width:1px;height:1px;margin:0;\";\n\t\tvb = \"visibility:hidden;border:0;\";\n\t\tstyle = \"style='\" + ptlm + \"border:5px solid #000;padding:0;'\";\n\t\thtml = \"<div \" + style + \"><div></div></div>\" +\n\t\t\t\"<table \" + style + \" cellpadding='0' cellspacing='0'>\" +\n\t\t\t\"<tr><td></td></tr></table>\";\n\n\t\tcontainer = document.createElement(\"div\");\n\t\tcontainer.style.cssText = vb + \"width:0;height:0;position:static;top:0;margin-top:\" + conMarginTop + \"px\";\n\t\tbody.insertBefore( container, body.firstChild );\n\n\t\t// Construct the test element\n\t\tdiv = document.createElement(\"div\");\n\t\tcontainer.appendChild( div );\n\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\t// (only IE 8 fails this test)\n\t\tdiv.innerHTML = \"<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>\";\n\t\ttds = div.getElementsByTagName( \"td\" );\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// Check if empty table cells still have offsetWidth/Height\n\t\t// (IE <= 8 fail this test)\n\t\tsupport.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );\n\n\t\t// Figure out if the W3C box model works as expected\n\t\tdiv.innerHTML = \"\";\n\t\tdiv.style.width = div.style.paddingLeft = \"1px\";\n\t\tjQuery.boxModel = support.boxModel = div.offsetWidth === 2;\n\n\t\tif ( typeof div.style.zoom !== \"undefined\" ) {\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\t// (IE < 8 does this)\n\t\t\tdiv.style.display = \"inline\";\n\t\t\tdiv.style.zoom = 1;\n\t\t\tsupport.inlineBlockNeedsLayout = ( div.offsetWidth === 2 );\n\n\t\t\t// Check if elements with layout shrink-wrap their children\n\t\t\t// (IE 6 does this)\n\t\t\tdiv.style.display = \"\";\n\t\t\tdiv.innerHTML = \"<div style='width:4px;'></div>\";\n\t\t\tsupport.shrinkWrapBlocks = ( div.offsetWidth !== 2 );\n\t\t}\n\n\t\tdiv.style.cssText = ptlm + vb;\n\t\tdiv.innerHTML = html;\n\n\t\touter = div.firstChild;\n\t\tinner = outer.firstChild;\n\t\ttd = outer.nextSibling.firstChild.firstChild;\n\n\t\toffsetSupport = {\n\t\t\tdoesNotAddBorder: ( inner.offsetTop !== 5 ),\n\t\t\tdoesAddBorderForTableAndCells: ( td.offsetTop === 5 )\n\t\t};\n\n\t\tinner.style.position = \"fixed\";\n\t\tinner.style.top = \"20px\";\n\n\t\t// safari subtracts parent border width here which is 5px\n\t\toffsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 );\n\t\tinner.style.position = inner.style.top = \"\";\n\n\t\touter.style.overflow = \"hidden\";\n\t\touter.style.position = \"relative\";\n\n\t\toffsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 );\n\t\toffsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop );\n\n\t\tbody.removeChild( container );\n\t\tdiv  = container = null;\n\n\t\tjQuery.extend( support, offsetSupport );\n\t});\n\n\treturn support;\n})();\n\n\n\n\nvar rbrace = /^(?:\\{.*\\}|\\[.*\\])$/,\n\trmultiDash = /([A-Z])/g;\n\njQuery.extend({\n\tcache: {},\n\n\t// Please use with caution\n\tuuid: 0,\n\n\t// Unique for each copy of jQuery on the page\n\t// Non-digits removed to match rinlinejQuery\n\texpando: \"jQuery\" + ( jQuery.fn.jquery + 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, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar privateCache, thisCache, ret,\n\t\t\tinternalKey = jQuery.expando,\n\t\t\tgetByName = typeof name === \"string\",\n\n\t\t\t// We have to handle DOM nodes and JS objects differently because IE6-7\n\t\t\t// can't GC object references properly across the DOM-JS boundary\n\t\t\tisNode = elem.nodeType,\n\n\t\t\t// Only DOM nodes need the global jQuery cache; JS object data is\n\t\t\t// attached directly to the object so GC can occur automatically\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t\t// Only defining an ID for JS objects if its cache already exists allows\n\t\t\t// the code to shortcut on the same path as a DOM node with no cache\n\t\t\tid = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey,\n\t\t\tisEvents = name === \"events\";\n\n\t\t// Avoid doing any more work than we need to when trying to get data on an\n\t\t// object that has no data at all\n\t\tif ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !id ) {\n\t\t\t// Only DOM nodes need a new unique ID for each element since their data\n\t\t\t// ends up in the global cache\n\t\t\tif ( isNode ) {\n\t\t\t\telem[ internalKey ] = id = ++jQuery.uuid;\n\t\t\t} else {\n\t\t\t\tid = internalKey;\n\t\t\t}\n\t\t}\n\n\t\tif ( !cache[ id ] ) {\n\t\t\tcache[ id ] = {};\n\n\t\t\t// Avoids exposing jQuery metadata on plain JS objects when the object\n\t\t\t// is serialized using JSON.stringify\n\t\t\tif ( !isNode ) {\n\t\t\t\tcache[ id ].toJSON = jQuery.noop;\n\t\t\t}\n\t\t}\n\n\t\t// An object can be passed to jQuery.data instead of a key/value pair; this gets\n\t\t// shallow copied over onto the existing cache\n\t\tif ( typeof name === \"object\" || typeof name === \"function\" ) {\n\t\t\tif ( pvt ) {\n\t\t\t\tcache[ id ] = jQuery.extend( cache[ id ], name );\n\t\t\t} else {\n\t\t\t\tcache[ id ].data = jQuery.extend( cache[ id ].data, name );\n\t\t\t}\n\t\t}\n\n\t\tprivateCache = thisCache = cache[ id ];\n\n\t\t// jQuery data() is stored in a separate object inside the object's internal data\n\t\t// cache in order to avoid key collisions between internal data and user-defined\n\t\t// data.\n\t\tif ( !pvt ) {\n\t\t\tif ( !thisCache.data ) {\n\t\t\t\tthisCache.data = {};\n\t\t\t}\n\n\t\t\tthisCache = thisCache.data;\n\t\t}\n\n\t\tif ( data !== undefined ) {\n\t\t\tthisCache[ jQuery.camelCase( name ) ] = data;\n\t\t}\n\n\t\t// Users should not attempt to inspect the internal events object using jQuery.data,\n\t\t// it is undocumented and subject to change. But does anyone listen? No.\n\t\tif ( isEvents && !thisCache[ name ] ) {\n\t\t\treturn privateCache.events;\n\t\t}\n\n\t\t// Check for both converted-to-camel and non-converted data property names\n\t\t// If a data property was specified\n\t\tif ( getByName ) {\n\n\t\t\t// First Try to find as-is property data\n\t\t\tret = thisCache[ name ];\n\n\t\t\t// Test for null|undefined property data\n\t\t\tif ( ret == null ) {\n\n\t\t\t\t// Try to find the camelCased property\n\t\t\t\tret = thisCache[ jQuery.camelCase( name ) ];\n\t\t\t}\n\t\t} else {\n\t\t\tret = thisCache;\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tremoveData: function( elem, name, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar thisCache, i, l,\n\n\t\t\t// Reference to internal data cache key\n\t\t\tinternalKey = jQuery.expando,\n\n\t\t\tisNode = elem.nodeType,\n\n\t\t\t// See jQuery.data for more information\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t\t// See jQuery.data for more information\n\t\t\tid = isNode ? elem[ internalKey ] : internalKey;\n\n\t\t// If there is already no cache entry for this object, there is no\n\t\t// purpose in continuing\n\t\tif ( !cache[ id ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( name ) {\n\n\t\t\tthisCache = pvt ? cache[ id ] : cache[ id ].data;\n\n\t\t\tif ( thisCache ) {\n\n\t\t\t\t// Support array or space separated string names for data keys\n\t\t\t\tif ( !jQuery.isArray( name ) ) {\n\n\t\t\t\t\t// try the string as a key before any manipulation\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\n\t\t\t\t\t\t// split the camel cased version by spaces unless a key with the spaces exists\n\t\t\t\t\t\tname = jQuery.camelCase( name );\n\t\t\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\t\t\tname = [ name ];\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tname = name.split( \" \" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor ( i = 0, l = name.length; i < l; i++ ) {\n\t\t\t\t\tdelete thisCache[ name[i] ];\n\t\t\t\t}\n\n\t\t\t\t// If there is no data left in the cache, we want to continue\n\t\t\t\t// and let the cache object itself get destroyed\n\t\t\t\tif ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// See jQuery.data for more information\n\t\tif ( !pvt ) {\n\t\t\tdelete cache[ id ].data;\n\n\t\t\t// Don't destroy the parent cache unless the internal data object\n\t\t\t// had been the only thing left in it\n\t\t\tif ( !isEmptyDataObject(cache[ id ]) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// Browsers that fail expando deletion also refuse to delete expandos on\n\t\t// the window, but it will allow it on all other JS objects; other browsers\n\t\t// don't care\n\t\t// Ensure that `cache` is not a window object #10080\n\t\tif ( jQuery.support.deleteExpando || !cache.setInterval ) {\n\t\t\tdelete cache[ id ];\n\t\t} else {\n\t\t\tcache[ id ] = null;\n\t\t}\n\n\t\t// We destroyed the cache and need to eliminate the expando on the node to avoid\n\t\t// false lookups in the cache for entries that no longer exist\n\t\tif ( isNode ) {\n\t\t\t// IE does not allow us to delete expando properties from nodes,\n\t\t\t// nor does it have a removeAttribute function on Document nodes;\n\t\t\t// we must handle all of these cases\n\t\t\tif ( jQuery.support.deleteExpando ) {\n\t\t\t\tdelete elem[ internalKey ];\n\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\telem.removeAttribute( internalKey );\n\t\t\t} else {\n\t\t\t\telem[ internalKey ] = null;\n\t\t\t}\n\t\t}\n\t},\n\n\t// For internal use only.\n\t_data: function( elem, name, data ) {\n\t\treturn jQuery.data( elem, name, data, 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\tif ( elem.nodeName ) {\n\t\t\tvar match = jQuery.noData[ elem.nodeName.toLowerCase() ];\n\n\t\t\tif ( match ) {\n\t\t\t\treturn !(match === true || elem.getAttribute(\"classid\") !== match);\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n});\n\njQuery.fn.extend({\n\tdata: function( key, value ) {\n\t\tvar parts, attr, name,\n\t\t\tdata = null;\n\n\t\tif ( typeof key === \"undefined\" ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = jQuery.data( this[0] );\n\n\t\t\t\tif ( this[0].nodeType === 1 && !jQuery._data( this[0], \"parsedAttrs\" ) ) {\n\t\t\t\t\tattr = this[0].attributes;\n\t\t\t\t\tfor ( var i = 0, l = attr.length; i < l; i++ ) {\n\t\t\t\t\t\tname = attr[i].name;\n\n\t\t\t\t\t\tif ( name.indexOf( \"data-\" ) === 0 ) {\n\t\t\t\t\t\t\tname = jQuery.camelCase( name.substring(5) );\n\n\t\t\t\t\t\t\tdataAttr( this[0], name, data[ name ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tjQuery._data( this[0], \"parsedAttrs\", true );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t} else if ( 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\tparts = key.split(\".\");\n\t\tparts[1] = parts[1] ? \".\" + parts[1] : \"\";\n\n\t\tif ( value === undefined ) {\n\t\t\tdata = this.triggerHandler(\"getData\" + parts[1] + \"!\", [parts[0]]);\n\n\t\t\t// Try to fetch any internally stored data first\n\t\t\tif ( data === undefined && this.length ) {\n\t\t\t\tdata = jQuery.data( this[0], key );\n\t\t\t\tdata = dataAttr( this[0], key, data );\n\t\t\t}\n\n\t\t\treturn data === undefined && parts[1] ?\n\t\t\t\tthis.data( parts[0] ) :\n\t\t\t\tdata;\n\n\t\t} else {\n\t\t\treturn this.each(function() {\n\t\t\t\tvar self = jQuery( this ),\n\t\t\t\t\targs = [ parts[0], value ];\n\n\t\t\t\tself.triggerHandler( \"setData\" + parts[1] + \"!\", args );\n\t\t\t\tjQuery.data( this, key, value );\n\t\t\t\tself.triggerHandler( \"changeData\" + parts[1] + \"!\", args );\n\t\t\t});\n\t\t}\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\tdata === \"false\" ? false :\n\t\t\t\tdata === \"null\" ? null :\n\t\t\t\tjQuery.isNumeric( data ) ? parseFloat( 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\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\tfor ( var 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}\n\n\n\n\nfunction handleQueueMarkDefer( elem, type, src ) {\n\tvar deferDataKey = type + \"defer\",\n\t\tqueueDataKey = type + \"queue\",\n\t\tmarkDataKey = type + \"mark\",\n\t\tdefer = jQuery._data( elem, deferDataKey );\n\tif ( defer &&\n\t\t( src === \"queue\" || !jQuery._data(elem, queueDataKey) ) &&\n\t\t( src === \"mark\" || !jQuery._data(elem, markDataKey) ) ) {\n\t\t// Give room for hard-coded callbacks to fire first\n\t\t// and eventually mark/queue something else on the element\n\t\tsetTimeout( function() {\n\t\t\tif ( !jQuery._data( elem, queueDataKey ) &&\n\t\t\t\t!jQuery._data( elem, markDataKey ) ) {\n\t\t\t\tjQuery.removeData( elem, deferDataKey, true );\n\t\t\t\tdefer.fire();\n\t\t\t}\n\t\t}, 0 );\n\t}\n}\n\njQuery.extend({\n\n\t_mark: function( elem, type ) {\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"mark\";\n\t\t\tjQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 );\n\t\t}\n\t},\n\n\t_unmark: function( force, elem, type ) {\n\t\tif ( force !== true ) {\n\t\t\ttype = elem;\n\t\t\telem = force;\n\t\t\tforce = false;\n\t\t}\n\t\tif ( elem ) {\n\t\t\ttype = type || \"fx\";\n\t\t\tvar key = type + \"mark\",\n\t\t\t\tcount = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 );\n\t\t\tif ( count ) {\n\t\t\t\tjQuery._data( elem, key, count );\n\t\t\t} else {\n\t\t\t\tjQuery.removeData( elem, key, true );\n\t\t\t\thandleQueueMarkDefer( elem, type, \"mark\" );\n\t\t\t}\n\t\t}\n\t},\n\n\tqueue: function( elem, type, data ) {\n\t\tvar q;\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"queue\";\n\t\t\tq = 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 ( !q || jQuery.isArray(data) ) {\n\t\t\t\t\tq = jQuery._data( elem, type, jQuery.makeArray(data) );\n\t\t\t\t} else {\n\t\t\t\t\tq.push( data );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn q || [];\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\tfn = queue.shift(),\n\t\t\thooks = {};\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}\n\n\t\tif ( fn ) {\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\tjQuery._data( elem, type + \".run\", hooks );\n\t\t\tfn.call( elem, function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t}, hooks );\n\t\t}\n\n\t\tif ( !queue.length ) {\n\t\t\tjQuery.removeData( elem, type + \"queue \" + type + \".run\", true );\n\t\t\thandleQueueMarkDefer( elem, type, \"queue\" );\n\t\t}\n\t}\n});\n\njQuery.fn.extend({\n\tqueue: function( type, data ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tdata = type;\n\t\t\ttype = \"fx\";\n\t\t}\n\n\t\tif ( data === undefined ) {\n\t\t\treturn jQuery.queue( this[0], type );\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\tif ( type === \"fx\" && queue[0] !== \"inprogress\" ) {\n\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t}\n\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, object ) {\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tobject = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\ttype = type || \"fx\";\n\t\tvar defer = jQuery.Deferred(),\n\t\t\telements = this,\n\t\t\ti = elements.length,\n\t\t\tcount = 1,\n\t\t\tdeferDataKey = type + \"defer\",\n\t\t\tqueueDataKey = type + \"queue\",\n\t\t\tmarkDataKey = type + \"mark\",\n\t\t\ttmp;\n\t\tfunction resolve() {\n\t\t\tif ( !( --count ) ) {\n\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n\t\t\t}\n\t\t}\n\t\twhile( i-- ) {\n\t\t\tif (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||\n\t\t\t\t\t( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||\n\t\t\t\t\t\tjQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&\n\t\t\t\t\tjQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( \"once memory\" ), true ) )) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.add( resolve );\n\t\t\t}\n\t\t}\n\t\tresolve();\n\t\treturn defer.promise();\n\t}\n});\n\n\n\n\nvar rclass = /[\\n\\t\\r]/g,\n\trspace = /\\s+/,\n\trreturn = /\\r/g,\n\trtype = /^(?:button|input)$/i,\n\trfocusable = /^(?:button|input|object|select|textarea)$/i,\n\trclickable = /^a(?:rea)?$/i,\n\trboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,\n\tgetSetAttribute = jQuery.support.getSetAttribute,\n\tnodeHook, boolHook, fixSpecified;\n\njQuery.fn.extend({\n\tattr: function( name, value ) {\n\t\treturn jQuery.access( this, name, value, true, jQuery.attr );\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, name, value, true, jQuery.prop );\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 classNames, i, l, elem,\n\t\t\tsetClass, c, cl;\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 ( value && typeof value === \"string\" ) {\n\t\t\tclassNames = value.split( rspace );\n\n\t\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !elem.className && classNames.length === 1 ) {\n\t\t\t\t\t\telem.className = value;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsetClass = \" \" + elem.className + \" \";\n\n\t\t\t\t\t\tfor ( c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tif ( !~setClass.indexOf( \" \" + classNames[ c ] + \" \" ) ) {\n\t\t\t\t\t\t\t\tsetClass += classNames[ c ] + \" \";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telem.className = jQuery.trim( setClass );\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 classNames, i, l, elem, className, c, cl;\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\n\t\tif ( (value && typeof value === \"string\") || value === undefined ) {\n\t\t\tclassNames = ( value || \"\" ).split( rspace );\n\n\t\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.nodeType === 1 && elem.className ) {\n\t\t\t\t\tif ( value ) {\n\t\t\t\t\t\tclassName = (\" \" + elem.className + \" \").replace( rclass, \" \" );\n\t\t\t\t\t\tfor ( c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tclassName = className.replace(\" \" + classNames[ c ] + \" \", \" \");\n\t\t\t\t\t\t}\n\t\t\t\t\t\telem.className = jQuery.trim( className );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\telem.className = \"\";\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\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.split( rspace );\n\n\t\t\t\twhile ( (className = classNames[ i++ ]) ) {\n\t\t\t\t\t// check each className given, space seperated 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} else if ( type === \"undefined\" || 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// toggle whole className\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 ) > -1 ) {\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 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.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ];\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 util 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 self = jQuery(this), 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, 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.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ];\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, i, max, option,\n\t\t\t\t\tindex = elem.selectedIndex,\n\t\t\t\t\tvalues = [],\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tone = elem.type === \"select-one\";\n\n\t\t\t\t// Nothing was selected\n\t\t\t\tif ( index < 0 ) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\t// Loop through all the selected options\n\t\t\t\ti = one ? index : 0;\n\t\t\t\tmax = one ? index + 1 : options.length;\n\t\t\t\tfor ( ; i < max; i++ ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t// Don't return options that are disabled or in a disabled optgroup\n\t\t\t\t\tif ( option.selected && (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\t// Fixes Bug #2551 -- select.val() broken in IE after form.reset()\n\t\t\t\tif ( one && !values.length && options.length ) {\n\t\t\t\t\treturn jQuery( options[ index ] ).val();\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\tattrFn: {\n\t\tval: true,\n\t\tcss: true,\n\t\thtml: true,\n\t\ttext: true,\n\t\tdata: true,\n\t\twidth: true,\n\t\theight: true,\n\t\toffset: true\n\t},\n\n\tattr: function( elem, name, value, pass ) {\n\t\tvar ret, hooks, notxml,\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\tif ( pass && name in jQuery.attrFn ) {\n\t\t\treturn jQuery( elem )[ name ]( value );\n\t\t}\n\n\t\t// Fallback to prop when attributes are not supported\n\t\tif ( typeof elem.getAttribute === \"undefined\" ) {\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\t\t\t\treturn;\n\n\t\t\t} else if ( hooks && \"set\" in hooks && notxml && (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 && notxml && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\treturn ret;\n\n\t\t} else {\n\n\t\t\tret = elem.getAttribute( 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 propName, attrNames, name, l,\n\t\t\ti = 0;\n\n\t\tif ( value && elem.nodeType === 1 ) {\n\t\t\tattrNames = value.toLowerCase().split( rspace );\n\t\t\tl = attrNames.length;\n\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tname = attrNames[ i ];\n\n\t\t\t\tif ( name ) {\n\t\t\t\t\tpropName = jQuery.propFix[ name ] || name;\n\n\t\t\t\t\t// See #9699 for explanation of this approach (setting first, then removal)\n\t\t\t\t\tjQuery.attr( elem, name, \"\" );\n\t\t\t\t\telem.removeAttribute( getSetAttribute ? name : propName );\n\n\t\t\t\t\t// Set corresponding property to false for boolean attributes\n\t\t\t\t\tif ( rboolean.test( name ) && propName in elem ) {\n\t\t\t\t\t\telem[ propName ] = false;\n\t\t\t\t\t}\n\t\t\t\t}\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\t// We can't allow the type property to be changed (since it causes problems in IE)\n\t\t\t\tif ( rtype.test( elem.nodeName ) && elem.parentNode ) {\n\t\t\t\t\tjQuery.error( \"type property can't be changed\" );\n\t\t\t\t} else if ( !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 it's default in case type is set after value\n\t\t\t\t\t// This is for element 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\t// Use the value property for back compat\n\t\t// Use the nodeHook for button elements in IE6/7 (#1954)\n\t\tvalue: {\n\t\t\tget: function( elem, name ) {\n\t\t\t\tif ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\t\t\treturn nodeHook.get( elem, name );\n\t\t\t\t}\n\t\t\t\treturn name in elem ?\n\t\t\t\t\telem.value :\n\t\t\t\t\tnull;\n\t\t\t},\n\t\t\tset: function( elem, value, name ) {\n\t\t\t\tif ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\t\t\treturn nodeHook.set( elem, value, name );\n\t\t\t\t}\n\t\t\t\t// Does not return so that setAttribute is also used\n\t\t\t\telem.value = value;\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// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional)\njQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex;\n\n// Hook for boolean attributes\nboolHook = {\n\tget: function( elem, name ) {\n\t\t// Align boolean attributes with corresponding properties\n\t\t// Fall back to attribute presence where some booleans are not supported\n\t\tvar attrNode,\n\t\t\tproperty = jQuery.prop( elem, name );\n\t\treturn property === true || typeof property !== \"boolean\" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?\n\t\t\tname.toLowerCase() :\n\t\t\tundefined;\n\t},\n\tset: function( elem, value, name ) {\n\t\tvar propName;\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\t// value is true since we know at this point it's type boolean and not false\n\t\t\t// Set boolean attributes to the same name and set the DOM property\n\t\t\tpropName = jQuery.propFix[ name ] || name;\n\t\t\tif ( propName in elem ) {\n\t\t\t\t// Only set the IDL specifically if it already exists on the element\n\t\t\t\telem[ propName ] = true;\n\t\t\t}\n\n\t\t\telem.setAttribute( name, name.toLowerCase() );\n\t\t}\n\t\treturn name;\n\t}\n};\n\n// IE6/7 do not support getting/setting some attributes with get/setAttribute\nif ( !getSetAttribute ) {\n\n\tfixSpecified = {\n\t\tname: true,\n\t\tid: true\n\t};\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;\n\t\t\tret = elem.getAttributeNode( name );\n\t\t\treturn ret && ( fixSpecified[ name ] ? ret.nodeValue !== \"\" : ret.specified ) ?\n\t\t\t\tret.nodeValue :\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\tret = document.createAttribute( name );\n\t\t\t\telem.setAttributeNode( ret );\n\t\t\t}\n\t\t\treturn ( ret.nodeValue = value + \"\" );\n\t\t}\n\t};\n\n\t// Apply the nodeHook to tabindex\n\tjQuery.attrHooks.tabindex.set = nodeHook.set;\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\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\tif ( value === \"\" ) {\n\t\t\t\tvalue = \"false\";\n\t\t\t}\n\t\t\tnodeHook.set( elem, value, name );\n\t\t}\n\t};\n}\n\n\n// Some attributes require a special call on IE\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\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// Normalize to lowercase since IE uppercases css property names\n\t\t\treturn elem.style.cssText.toLowerCase() || 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});\n\n\n\n\nvar rformElems = /^(?:textarea|input|select)$/i,\n\trtypenamespace = /^([^\\.]*)?(?:\\.(.+))?$/,\n\trhoverHack = /\\bhover(\\.\\S+)?\\b/,\n\trkeyEvent = /^key/,\n\trmouseEvent = /^(?:mouse|contextmenu)|click/,\n\trfocusMorph = /^(?:focusinfocus|focusoutblur)$/,\n\trquickIs = /^(\\w*)(?:#([\\w\\-]+))?(?:\\.([\\w\\-]+))?$/,\n\tquickParse = function( selector ) {\n\t\tvar quick = rquickIs.exec( selector );\n\t\tif ( quick ) {\n\t\t\t//   0  1    2   3\n\t\t\t// [ _, tag, id, class ]\n\t\t\tquick[1] = ( quick[1] || \"\" ).toLowerCase();\n\t\t\tquick[3] = quick[3] && new RegExp( \"(?:^|\\\\s)\" + quick[3] + \"(?:\\\\s|$)\" );\n\t\t}\n\t\treturn quick;\n\t},\n\tquickIs = function( elem, m ) {\n\t\tvar attrs = elem.attributes || {};\n\t\treturn (\n\t\t\t(!m[1] || elem.nodeName.toLowerCase() === m[1]) &&\n\t\t\t(!m[2] || (attrs.id || {}).value === m[2]) &&\n\t\t\t(!m[3] || m[3].test( (attrs[ \"class\" ] || {}).value ))\n\t\t);\n\t},\n\thoverHack = function( events ) {\n\t\treturn jQuery.event.special.hover ? events : events.replace( rhoverHack, \"mouseenter$1 mouseleave$1\" );\n\t};\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\tadd: function( elem, types, handler, data, selector ) {\n\n\t\tvar elemData, eventHandle, events,\n\t\t\tt, tns, type, namespaces, handleObj,\n\t\t\thandleObjIn, quick, handlers, special;\n\n\t\t// Don't attach events to noData or text/comment nodes (allow plain objects tho)\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {\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}\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\tevents = elemData.events;\n\t\tif ( !events ) {\n\t\t\telemData.events = events = {};\n\t\t}\n\t\teventHandle = elemData.handle;\n\t\tif ( !eventHandle ) {\n\t\t\telemData.handle = eventHandle = 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 !== \"undefined\" && (!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 = jQuery.trim( hoverHack(types) ).split( \" \" );\n\t\tfor ( t = 0; t < types.length; t++ ) {\n\n\t\t\ttns = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = tns[1];\n\t\t\tnamespaces = ( tns[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: tns[1],\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\tquick: quickParse( 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\thandlers = events[ type ];\n\t\t\tif ( !handlers ) {\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\tglobal: {},\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 elemData = jQuery.hasData( elem ) && jQuery._data( elem ),\n\t\t\tt, tns, type, origType, namespaces, origCount,\n\t\t\tj, events, special, handle, eventType, handleObj;\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 = jQuery.trim( hoverHack( types || \"\" ) ).split(\" \");\n\t\tfor ( t = 0; t < types.length; t++ ) {\n\t\t\ttns = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = origType = tns[1];\n\t\t\tnamespaces = tns[2];\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\teventType = events[ type ] || [];\n\t\t\torigCount = eventType.length;\n\t\t\tnamespaces = namespaces ? new RegExp(\"(^|\\\\.)\" + namespaces.split(\".\").sort().join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\") : null;\n\n\t\t\t// Remove matching events\n\t\t\tfor ( j = 0; j < eventType.length; j++ ) {\n\t\t\t\thandleObj = eventType[ 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 ( !namespaces || namespaces.test( handleObj.namespace ) ) &&\n\t\t\t\t\t ( !selector || selector === handleObj.selector || selector === \"**\" && handleObj.selector ) ) {\n\t\t\t\t\teventType.splice( j--, 1 );\n\n\t\t\t\t\tif ( handleObj.selector ) {\n\t\t\t\t\t\teventType.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 ( eventType.length === 0 && origCount !== eventType.length ) {\n\t\t\t\tif ( !special.teardown || special.teardown.call( elem, namespaces ) === 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\thandle = elemData.handle;\n\t\t\tif ( handle ) {\n\t\t\t\thandle.elem = null;\n\t\t\t}\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\", \"handle\" ], true );\n\t\t}\n\t},\n\n\t// Events that are safe to short-circuit if no handlers are attached.\n\t// Native DOM events should not be added, they may have inline handlers.\n\tcustomEvent: {\n\t\t\"getData\": true,\n\t\t\"setData\": true,\n\t\t\"changeData\": true\n\t},\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\t\t// Don't do events on text and comment nodes\n\t\tif ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Event object or event type\n\t\tvar type = event.type || event,\n\t\t\tnamespaces = [],\n\t\t\tcache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType;\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// Exclusive events trigger only for the exact event (no namespaces)\n\t\t\ttype = type.slice(0, -1);\n\t\t\texclusive = true;\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\n\t\tif ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {\n\t\t\t// No jQuery handlers for this event type, and it can't have inline handlers\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an Event, Object, or just an event type string\n\t\tevent = typeof event === \"object\" ?\n\t\t\t// jQuery.Event object\n\t\t\tevent[ jQuery.expando ] ? event :\n\t\t\t// Object literal\n\t\t\tnew jQuery.Event( type, event ) :\n\t\t\t// Just the event type (string)\n\t\t\tnew jQuery.Event( type );\n\n\t\tevent.type = type;\n\t\tevent.isTrigger = true;\n\t\tevent.exclusive = exclusive;\n\t\tevent.namespace = namespaces.join( \".\" );\n\t\tevent.namespace_re = event.namespace? new RegExp(\"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\") : null;\n\t\tontype = type.indexOf( \":\" ) < 0 ? \"on\" + type : \"\";\n\n\t\t// Handle a global trigger\n\t\tif ( !elem ) {\n\n\t\t\t// TODO: Stop taunting the data cache; remove global events and always attach to document\n\t\t\tcache = jQuery.cache;\n\t\t\tfor ( i in cache ) {\n\t\t\t\tif ( cache[ i ].events && cache[ i ].events[ type ] ) {\n\t\t\t\t\tjQuery.event.trigger( event, data, cache[ i ].handle.elem, true );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\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 ? jQuery.makeArray( data ) : [];\n\t\tdata.unshift( event );\n\n\t\t// Allow special events to draw outside the lines\n\t\tspecial = jQuery.event.special[ type ] || {};\n\t\tif ( 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\teventPath = [[ elem, special.bindType || type ]];\n\t\tif ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {\n\n\t\t\tbubbleType = special.delegateType || type;\n\t\t\tcur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode;\n\t\t\told = null;\n\t\t\tfor ( ; cur; cur = cur.parentNode ) {\n\t\t\t\teventPath.push([ cur, bubbleType ]);\n\t\t\t\told = 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 ( old && old === elem.ownerDocument ) {\n\t\t\t\teventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);\n\t\t\t}\n\t\t}\n\n\t\t// Fire handlers on the event path\n\t\tfor ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) {\n\n\t\t\tcur = eventPath[i][0];\n\t\t\tevent.type = eventPath[i][1];\n\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\t\t\t// Note that this is a bare JS function and not a jQuery handler\n\t\t\thandle = ontype && cur[ ontype ];\n\t\t\tif ( handle && jQuery.acceptData( cur ) && 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\t// IE<9 dies on focus/blur to hidden element (#1486)\n\t\t\t\tif ( ontype && elem[ type ] && ((type !== \"focus\" && type !== \"blur\") || event.target.offsetWidth !== 0) && !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\told = elem[ ontype ];\n\n\t\t\t\t\tif ( old ) {\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 ( old ) {\n\t\t\t\t\t\telem[ ontype ] = old;\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 || window.event );\n\n\t\tvar handlers = ( (jQuery._data( this, \"events\" ) || {} )[ event.type ] || []),\n\t\t\tdelegateCount = handlers.delegateCount,\n\t\t\targs = [].slice.call( arguments, 0 ),\n\t\t\trun_all = !event.exclusive && !event.namespace,\n\t\t\thandlerQueue = [],\n\t\t\ti, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related;\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// Determine handlers that should run if there are delegated events\n\t\t// Avoid disabled elements in IE (#6911) and non-left-click bubbling in Firefox (#3861)\n\t\tif ( delegateCount && !event.target.disabled && !(event.button && event.type === \"click\") ) {\n\n\t\t\t// Pregenerate a single jQuery object for reuse with .is()\n\t\t\tjqcur = jQuery(this);\n\t\t\tjqcur.context = this.ownerDocument || this;\n\n\t\t\tfor ( cur = event.target; cur != this; cur = cur.parentNode || this ) {\n\t\t\t\tselMatch = {};\n\t\t\t\tmatches = [];\n\t\t\t\tjqcur[0] = cur;\n\t\t\t\tfor ( i = 0; i < delegateCount; i++ ) {\n\t\t\t\t\thandleObj = handlers[ i ];\n\t\t\t\t\tsel = handleObj.selector;\n\n\t\t\t\t\tif ( selMatch[ sel ] === undefined ) {\n\t\t\t\t\t\tselMatch[ sel ] = (\n\t\t\t\t\t\t\thandleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel )\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tif ( selMatch[ sel ] ) {\n\t\t\t\t\t\tmatches.push( handleObj );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif ( matches.length ) {\n\t\t\t\t\thandlerQueue.push({ elem: cur, matches: matches });\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 ( handlers.length > delegateCount ) {\n\t\t\thandlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });\n\t\t}\n\n\t\t// Run delegates first; they may want to stop propagation beneath us\n\t\tfor ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {\n\t\t\tmatched = handlerQueue[ i ];\n\t\t\tevent.currentTarget = matched.elem;\n\n\t\t\tfor ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {\n\t\t\t\thandleObj = matched.matches[ j ];\n\n\t\t\t\t// Triggered event must either 1) be non-exclusive and 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 ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {\n\n\t\t\t\t\tevent.data = handleObj.data;\n\t\t\t\t\tevent.handleObj = handleObj;\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\tevent.result = ret;\n\t\t\t\t\t\tif ( 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\treturn event.result;\n\t},\n\n\t// Includes some event props shared by KeyEvent and MouseEvent\n\t// *** attrChange attrName relatedNode srcElement  are not normalized, non-W3C, deprecated, will be removed in 1.8 ***\n\tprops: \"attrChange attrName relatedNode srcElement 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 eventDoc, doc, body,\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\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,\n\t\t\toriginalEvent = event,\n\t\t\tfixHook = jQuery.event.fixHooks[ event.type ] || {},\n\t\t\tcopy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;\n\n\t\tevent = jQuery.Event( originalEvent );\n\n\t\tfor ( i = copy.length; i; ) {\n\t\t\tprop = copy[ --i ];\n\t\t\tevent[ prop ] = originalEvent[ prop ];\n\t\t}\n\n\t\t// Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)\n\t\tif ( !event.target ) {\n\t\t\tevent.target = originalEvent.srcElement || document;\n\t\t}\n\n\t\t// Target should not be a text node (#504, Safari)\n\t\tif ( event.target.nodeType === 3 ) {\n\t\t\tevent.target = event.target.parentNode;\n\t\t}\n\n\t\t// For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8)\n\t\tif ( event.metaKey === undefined ) {\n\t\t\tevent.metaKey = event.ctrlKey;\n\t\t}\n\n\t\treturn fixHook.filter? fixHook.filter( event, originalEvent ) : event;\n\t},\n\n\tspecial: {\n\t\tready: {\n\t\t\t// Make sure the ready event is setup\n\t\t\tsetup: jQuery.bindReady\n\t\t},\n\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\n\t\tfocus: {\n\t\t\tdelegateType: \"focusin\"\n\t\t},\n\t\tblur: {\n\t\t\tdelegateType: \"focusout\"\n\t\t},\n\n\t\tbeforeunload: {\n\t\t\tsetup: function( data, namespaces, eventHandle ) {\n\t\t\t\t// We only want to do this special case on windows\n\t\t\t\tif ( jQuery.isWindow( this ) ) {\n\t\t\t\t\tthis.onbeforeunload = eventHandle;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tteardown: function( namespaces, eventHandle ) {\n\t\t\t\tif ( this.onbeforeunload === eventHandle ) {\n\t\t\t\t\tthis.onbeforeunload = null;\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\n// Some plugins are using, but it's undocumented/deprecated and will be removed.\n// The 1.7 special event interface should provide all the hooks needed now.\njQuery.event.handle = jQuery.event.dispatch;\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\tif ( elem.detachEvent ) {\n\t\t\telem.detachEvent( \"on\" + type, 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\nfunction returnFalse() {\n\treturn false;\n}\nfunction returnTrue() {\n\treturn 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\tpreventDefault: function() {\n\t\tthis.isDefaultPrevented = returnTrue;\n\n\t\tvar e = this.originalEvent;\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// otherwise set the returnValue property of the original event to false (IE)\n\t\t} else {\n\t\t\te.returnValue = false;\n\t\t}\n\t},\n\tstopPropagation: function() {\n\t\tthis.isPropagationStopped = returnTrue;\n\n\t\tvar e = this.originalEvent;\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\t\t// otherwise set the cancelBubble property of the original event to true (IE)\n\t\te.cancelBubble = true;\n\t},\n\tstopImmediatePropagation: function() {\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\t\tthis.stopPropagation();\n\t},\n\tisDefaultPrevented: returnFalse,\n\tisPropagationStopped: returnFalse,\n\tisImmediatePropagationStopped: returnFalse\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 target = this,\n\t\t\t\trelated = event.relatedTarget,\n\t\t\t\thandleObj = event.handleObj,\n\t\t\t\tselector = handleObj.selector,\n\t\t\t\tret;\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 && !form._submit_attached ) {\n\t\t\t\t\tjQuery.event.add( form, \"submit._submit\", function( event ) {\n\t\t\t\t\t\t// If form was submitted by the user, bubble the event up the tree\n\t\t\t\t\t\tif ( this.parentNode && !event.isTrigger ) {\n\t\t\t\t\t\t\tjQuery.event.simulate( \"submit\", this.parentNode, event, true );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tform._submit_attached = 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\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\tjQuery.event.simulate( \"change\", this, event, true );\n\t\t\t\t\t\t}\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 ) && !elem._change_attached ) {\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\telem._change_attached = 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 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 = 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.call( this, types, selector, data, fn, 1 );\n\t},\n\toff: function( types, selector, fn ) {\n\t\tif ( types && types.preventDefault && types.handleObj ) {\n\t\t\t// ( event )  dispatched jQuery.Event\n\t\t\tvar handleObj = types.handleObj;\n\t\t\tjQuery( types.delegateTarget ).off(\n\t\t\t\thandleObj.namespace? handleObj.type + \".\" + handleObj.namespace : handleObj.type,\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 ( var 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\tlive: function( types, data, fn ) {\n\t\tjQuery( this.context ).on( types, this.selector, data, fn );\n\t\treturn this;\n\t},\n\tdie: function( types, fn ) {\n\t\tjQuery( this.context ).off( types, this.selector || \"**\", fn );\n\t\treturn this;\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\tif ( this[0] ) {\n\t\t\treturn jQuery.event.trigger( type, data, this[0], true );\n\t\t}\n\t},\n\n\ttoggle: function( fn ) {\n\t\t// Save reference to arguments for access in closure\n\t\tvar args = arguments,\n\t\t\tguid = fn.guid || jQuery.guid++,\n\t\t\ti = 0,\n\t\t\ttoggler = function( event ) {\n\t\t\t\t// Figure out which function to execute\n\t\t\t\tvar lastToggle = ( jQuery._data( this, \"lastToggle\" + fn.guid ) || 0 ) % i;\n\t\t\t\tjQuery._data( this, \"lastToggle\" + fn.guid, lastToggle + 1 );\n\n\t\t\t\t// Make sure that clicks stop\n\t\t\t\tevent.preventDefault();\n\n\t\t\t\t// and execute the function\n\t\t\t\treturn args[ lastToggle ].apply( this, arguments ) || false;\n\t\t\t};\n\n\t\t// link all the functions, so any of them can unbind this click handler\n\t\ttoggler.guid = guid;\n\t\twhile ( i < args.length ) {\n\t\t\targs[ i++ ].guid = guid;\n\t\t}\n\n\t\treturn this.click( toggler );\n\t},\n\n\thover: function( fnOver, fnOut ) {\n\t\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n\t}\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\tif ( fn == null ) {\n\t\t\tfn = data;\n\t\t\tdata = null;\n\t\t}\n\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\tif ( jQuery.attrFn ) {\n\t\tjQuery.attrFn[ name ] = true;\n\t}\n\n\tif ( rkeyEvent.test( name ) ) {\n\t\tjQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;\n\t}\n\n\tif ( rmouseEvent.test( name ) ) {\n\t\tjQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;\n\t}\n});\n\n\n\n/*!\n * Sizzle CSS Selector Engine\n *  Copyright 2011, The Dojo Foundation\n *  Released under the MIT, BSD, and GPL Licenses.\n *  More information: http://sizzlejs.com/\n */\n(function(){\n\nvar chunker = /((?:\\((?:\\([^()]+\\)|[^()]+)+\\)|\\[(?:\\[[^\\[\\]]*\\]|['\"][^'\"]*['\"]|[^\\[\\]'\"]+)+\\]|\\\\.|[^ >+~,(\\[\\\\]+)+|[>+~])(\\s*,\\s*)?((?:.|\\r|\\n)*)/g,\n\texpando = \"sizcache\" + (Math.random() + '').replace('.', ''),\n\tdone = 0,\n\ttoString = Object.prototype.toString,\n\thasDuplicate = false,\n\tbaseHasDuplicate = true,\n\trBackslash = /\\\\/g,\n\trReturn = /\\r\\n/g,\n\trNonWord = /\\W/;\n\n// Here we check if the JavaScript engine is using some sort of\n// optimization where it does not always call our comparision\n// function. If that is the case, discard the hasDuplicate value.\n//   Thus far that includes Google Chrome.\n[0, 0].sort(function() {\n\tbaseHasDuplicate = false;\n\treturn 0;\n});\n\nvar Sizzle = function( selector, context, results, seed ) {\n\tresults = results || [];\n\tcontext = context || document;\n\n\tvar origContext = context;\n\n\tif ( context.nodeType !== 1 && context.nodeType !== 9 ) {\n\t\treturn [];\n\t}\n\t\n\tif ( !selector || typeof selector !== \"string\" ) {\n\t\treturn results;\n\t}\n\n\tvar m, set, checkSet, extra, ret, cur, pop, i,\n\t\tprune = true,\n\t\tcontextXML = Sizzle.isXML( context ),\n\t\tparts = [],\n\t\tsoFar = selector;\n\t\n\t// Reset the position of the chunker regexp (start from head)\n\tdo {\n\t\tchunker.exec( \"\" );\n\t\tm = chunker.exec( soFar );\n\n\t\tif ( m ) {\n\t\t\tsoFar = m[3];\n\t\t\n\t\t\tparts.push( m[1] );\n\t\t\n\t\t\tif ( m[2] ) {\n\t\t\t\textra = m[3];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t} while ( m );\n\n\tif ( parts.length > 1 && origPOS.exec( selector ) ) {\n\n\t\tif ( parts.length === 2 && Expr.relative[ parts[0] ] ) {\n\t\t\tset = posProcess( parts[0] + parts[1], context, seed );\n\n\t\t} else {\n\t\t\tset = Expr.relative[ parts[0] ] ?\n\t\t\t\t[ context ] :\n\t\t\t\tSizzle( parts.shift(), context );\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tselector = parts.shift();\n\n\t\t\t\tif ( Expr.relative[ selector ] ) {\n\t\t\t\t\tselector += parts.shift();\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tset = posProcess( selector, set, seed );\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\t// Take a shortcut and set the context if the root selector is an ID\n\t\t// (but not if it'll be faster if the inner selector is an ID)\n\t\tif ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&\n\t\t\t\tExpr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {\n\n\t\t\tret = Sizzle.find( parts.shift(), context, contextXML );\n\t\t\tcontext = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set )[0] :\n\t\t\t\tret.set[0];\n\t\t}\n\n\t\tif ( context ) {\n\t\t\tret = seed ?\n\t\t\t\t{ expr: parts.pop(), set: makeArray(seed) } :\n\t\t\t\tSizzle.find( parts.pop(), parts.length === 1 && (parts[0] === \"~\" || parts[0] === \"+\") && context.parentNode ? context.parentNode : context, contextXML );\n\n\t\t\tset = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set ) :\n\t\t\t\tret.set;\n\n\t\t\tif ( parts.length > 0 ) {\n\t\t\t\tcheckSet = makeArray( set );\n\n\t\t\t} else {\n\t\t\t\tprune = false;\n\t\t\t}\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tcur = parts.pop();\n\t\t\t\tpop = cur;\n\n\t\t\t\tif ( !Expr.relative[ cur ] ) {\n\t\t\t\t\tcur = \"\";\n\t\t\t\t} else {\n\t\t\t\t\tpop = parts.pop();\n\t\t\t\t}\n\n\t\t\t\tif ( pop == null ) {\n\t\t\t\t\tpop = context;\n\t\t\t\t}\n\n\t\t\t\tExpr.relative[ cur ]( checkSet, pop, contextXML );\n\t\t\t}\n\n\t\t} else {\n\t\t\tcheckSet = parts = [];\n\t\t}\n\t}\n\n\tif ( !checkSet ) {\n\t\tcheckSet = set;\n\t}\n\n\tif ( !checkSet ) {\n\t\tSizzle.error( cur || selector );\n\t}\n\n\tif ( toString.call(checkSet) === \"[object Array]\" ) {\n\t\tif ( !prune ) {\n\t\t\tresults.push.apply( results, checkSet );\n\n\t\t} else if ( context && context.nodeType === 1 ) {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && checkSet[i].nodeType === 1 ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\tmakeArray( checkSet, results );\n\t}\n\n\tif ( extra ) {\n\t\tSizzle( extra, origContext, results, seed );\n\t\tSizzle.uniqueSort( results );\n\t}\n\n\treturn results;\n};\n\nSizzle.uniqueSort = function( results ) {\n\tif ( sortOrder ) {\n\t\thasDuplicate = baseHasDuplicate;\n\t\tresults.sort( sortOrder );\n\n\t\tif ( hasDuplicate ) {\n\t\t\tfor ( var i = 1; i < results.length; i++ ) {\n\t\t\t\tif ( results[i] === results[ i - 1 ] ) {\n\t\t\t\t\tresults.splice( i--, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn results;\n};\n\nSizzle.matches = function( expr, set ) {\n\treturn Sizzle( expr, null, null, set );\n};\n\nSizzle.matchesSelector = function( node, expr ) {\n\treturn Sizzle( expr, null, null, [node] ).length > 0;\n};\n\nSizzle.find = function( expr, context, isXML ) {\n\tvar set, i, len, match, type, left;\n\n\tif ( !expr ) {\n\t\treturn [];\n\t}\n\n\tfor ( i = 0, len = Expr.order.length; i < len; i++ ) {\n\t\ttype = Expr.order[i];\n\t\t\n\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) ) {\n\t\t\tleft = match[1];\n\t\t\tmatch.splice( 1, 1 );\n\n\t\t\tif ( left.substr( left.length - 1 ) !== \"\\\\\" ) {\n\t\t\t\tmatch[1] = (match[1] || \"\").replace( rBackslash, \"\" );\n\t\t\t\tset = Expr.find[ type ]( match, context, isXML );\n\n\t\t\t\tif ( set != null ) {\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( !set ) {\n\t\tset = typeof context.getElementsByTagName !== \"undefined\" ?\n\t\t\tcontext.getElementsByTagName( \"*\" ) :\n\t\t\t[];\n\t}\n\n\treturn { set: set, expr: expr };\n};\n\nSizzle.filter = function( expr, set, inplace, not ) {\n\tvar match, anyFound,\n\t\ttype, found, item, filter, left,\n\t\ti, pass,\n\t\told = expr,\n\t\tresult = [],\n\t\tcurLoop = set,\n\t\tisXMLFilter = set && set[0] && Sizzle.isXML( set[0] );\n\n\twhile ( expr && set.length ) {\n\t\tfor ( type in Expr.filter ) {\n\t\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {\n\t\t\t\tfilter = Expr.filter[ type ];\n\t\t\t\tleft = match[1];\n\n\t\t\t\tanyFound = false;\n\n\t\t\t\tmatch.splice(1,1);\n\n\t\t\t\tif ( left.substr( left.length - 1 ) === \"\\\\\" ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif ( curLoop === result ) {\n\t\t\t\t\tresult = [];\n\t\t\t\t}\n\n\t\t\t\tif ( Expr.preFilter[ type ] ) {\n\t\t\t\t\tmatch = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );\n\n\t\t\t\t\tif ( !match ) {\n\t\t\t\t\t\tanyFound = found = true;\n\n\t\t\t\t\t} else if ( match === true ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( match ) {\n\t\t\t\t\tfor ( i = 0; (item = curLoop[i]) != null; i++ ) {\n\t\t\t\t\t\tif ( item ) {\n\t\t\t\t\t\t\tfound = filter( item, match, i, curLoop );\n\t\t\t\t\t\t\tpass = not ^ found;\n\n\t\t\t\t\t\t\tif ( inplace && found != null ) {\n\t\t\t\t\t\t\t\tif ( pass ) {\n\t\t\t\t\t\t\t\t\tanyFound = true;\n\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t} else if ( pass ) {\n\t\t\t\t\t\t\t\tresult.push( item );\n\t\t\t\t\t\t\t\tanyFound = 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\n\t\t\t\tif ( found !== undefined ) {\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tcurLoop = result;\n\t\t\t\t\t}\n\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\n\t\t\t\t\tif ( !anyFound ) {\n\t\t\t\t\t\treturn [];\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\n\t\t// Improper expression\n\t\tif ( expr === old ) {\n\t\t\tif ( anyFound == null ) {\n\t\t\t\tSizzle.error( expr );\n\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\told = expr;\n\t}\n\n\treturn curLoop;\n};\n\nSizzle.error = function( msg ) {\n\tthrow new Error( \"Syntax error, unrecognized expression: \" + msg );\n};\n\n/**\n * Utility function for retreiving the text value of an array of DOM nodes\n * @param {Array|Element} elem\n */\nvar getText = Sizzle.getText = function( elem ) {\n    var i, node,\n\t\tnodeType = elem.nodeType,\n\t\tret = \"\";\n\n\tif ( nodeType ) {\n\t\tif ( nodeType === 1 || nodeType === 9 ) {\n\t\t\t// Use textContent || innerText for elements\n\t\t\tif ( typeof elem.textContent === 'string' ) {\n\t\t\t\treturn elem.textContent;\n\t\t\t} else if ( typeof elem.innerText === 'string' ) {\n\t\t\t\t// Replace IE's carriage returns\n\t\t\t\treturn elem.innerText.replace( rReturn, '' );\n\t\t\t} else {\n\t\t\t\t// Traverse it's children\n\t\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling) {\n\t\t\t\t\tret += getText( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t} else if ( nodeType === 3 || nodeType === 4 ) {\n\t\t\treturn elem.nodeValue;\n\t\t}\n\t} else {\n\n\t\t// If no nodeType, this is expected to be an array\n\t\tfor ( i = 0; (node = elem[i]); i++ ) {\n\t\t\t// Do not traverse comment nodes\n\t\t\tif ( node.nodeType !== 8 ) {\n\t\t\t\tret += getText( node );\n\t\t\t}\n\t\t}\n\t}\n\treturn ret;\n};\n\nvar Expr = Sizzle.selectors = {\n\torder: [ \"ID\", \"NAME\", \"TAG\" ],\n\n\tmatch: {\n\t\tID: /#((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tCLASS: /\\.((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tNAME: /\\[name=['\"]*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)['\"]*\\]/,\n\t\tATTR: /\\[\\s*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)\\s*(?:(\\S?=)\\s*(?:(['\"])(.*?)\\3|(#?(?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)*)|)|)\\s*\\]/,\n\t\tTAG: /^((?:[\\w\\u00c0-\\uFFFF\\*\\-]|\\\\.)+)/,\n\t\tCHILD: /:(only|nth|last|first)-child(?:\\(\\s*(even|odd|(?:[+\\-]?\\d+|(?:[+\\-]?\\d*)?n\\s*(?:[+\\-]\\s*\\d+)?))\\s*\\))?/,\n\t\tPOS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\\((\\d*)\\))?(?=[^\\-]|$)/,\n\t\tPSEUDO: /:((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)(?:\\((['\"]?)((?:\\([^\\)]+\\)|[^\\(\\)]*)+)\\2\\))?/\n\t},\n\n\tleftMatch: {},\n\n\tattrMap: {\n\t\t\"class\": \"className\",\n\t\t\"for\": \"htmlFor\"\n\t},\n\n\tattrHandle: {\n\t\thref: function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\" );\n\t\t},\n\t\ttype: function( elem ) {\n\t\t\treturn elem.getAttribute( \"type\" );\n\t\t}\n\t},\n\n\trelative: {\n\t\t\"+\": function(checkSet, part){\n\t\t\tvar isPartStr = typeof part === \"string\",\n\t\t\t\tisTag = isPartStr && !rNonWord.test( part ),\n\t\t\t\tisPartStrNotTag = isPartStr && !isTag;\n\n\t\t\tif ( isTag ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t}\n\n\t\t\tfor ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {\n\t\t\t\tif ( (elem = checkSet[i]) ) {\n\t\t\t\t\twhile ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}\n\n\t\t\t\t\tcheckSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?\n\t\t\t\t\t\telem || false :\n\t\t\t\t\t\telem === part;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( isPartStrNotTag ) {\n\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t}\n\t\t},\n\n\t\t\">\": function( checkSet, part ) {\n\t\t\tvar elem,\n\t\t\t\tisPartStr = typeof part === \"string\",\n\t\t\t\ti = 0,\n\t\t\t\tl = checkSet.length;\n\n\t\t\tif ( isPartStr && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tvar parent = elem.parentNode;\n\t\t\t\t\t\tcheckSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tcheckSet[i] = isPartStr ?\n\t\t\t\t\t\t\telem.parentNode :\n\t\t\t\t\t\t\telem.parentNode === part;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( isPartStr ) {\n\t\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t\"\": function(checkSet, part, isXML){\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"parentNode\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t},\n\n\t\t\"~\": function( checkSet, part, isXML ) {\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"previousSibling\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t}\n\t},\n\n\tfind: {\n\t\tID: function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\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\n\t\tNAME: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByName !== \"undefined\" ) {\n\t\t\t\tvar ret = [],\n\t\t\t\t\tresults = context.getElementsByName( match[1] );\n\n\t\t\t\tfor ( var i = 0, l = results.length; i < l; i++ ) {\n\t\t\t\t\tif ( results[i].getAttribute(\"name\") === match[1] ) {\n\t\t\t\t\t\tret.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn ret.length === 0 ? null : ret;\n\t\t\t}\n\t\t},\n\n\t\tTAG: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\t\t\treturn context.getElementsByTagName( match[1] );\n\t\t\t}\n\t\t}\n\t},\n\tpreFilter: {\n\t\tCLASS: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tmatch = \" \" + match[1].replace( rBackslash, \"\" ) + \" \";\n\n\t\t\tif ( isXML ) {\n\t\t\t\treturn match;\n\t\t\t}\n\n\t\t\tfor ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {\n\t\t\t\tif ( elem ) {\n\t\t\t\t\tif ( not ^ (elem.className && (\" \" + elem.className + \" \").replace(/[\\t\\n\\r]/g, \" \").indexOf(match) >= 0) ) {\n\t\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\t\tresult.push( elem );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( inplace ) {\n\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\t\t},\n\n\t\tID: function( match ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" );\n\t\t},\n\n\t\tTAG: function( match, curLoop ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" ).toLowerCase();\n\t\t},\n\n\t\tCHILD: function( match ) {\n\t\t\tif ( match[1] === \"nth\" ) {\n\t\t\t\tif ( !match[2] ) {\n\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t}\n\n\t\t\t\tmatch[2] = match[2].replace(/^\\+|\\s*/g, '');\n\n\t\t\t\t// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'\n\t\t\t\tvar test = /(-?)(\\d*)(?:n([+\\-]?\\d*))?/.exec(\n\t\t\t\t\tmatch[2] === \"even\" && \"2n\" || match[2] === \"odd\" && \"2n+1\" ||\n\t\t\t\t\t!/\\D/.test( match[2] ) && \"0n+\" + match[2] || match[2]);\n\n\t\t\t\t// calculate the numbers (first)n+(last) including if they are negative\n\t\t\t\tmatch[2] = (test[1] + (test[2] || 1)) - 0;\n\t\t\t\tmatch[3] = test[3] - 0;\n\t\t\t}\n\t\t\telse if ( match[2] ) {\n\t\t\t\tSizzle.error( match[0] );\n\t\t\t}\n\n\t\t\t// TODO: Move to normal caching system\n\t\t\tmatch[0] = done++;\n\n\t\t\treturn match;\n\t\t},\n\n\t\tATTR: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tvar name = match[1] = match[1].replace( rBackslash, \"\" );\n\t\t\t\n\t\t\tif ( !isXML && Expr.attrMap[name] ) {\n\t\t\t\tmatch[1] = Expr.attrMap[name];\n\t\t\t}\n\n\t\t\t// Handle if an un-quoted value was used\n\t\t\tmatch[4] = ( match[4] || match[5] || \"\" ).replace( rBackslash, \"\" );\n\n\t\t\tif ( match[2] === \"~=\" ) {\n\t\t\t\tmatch[4] = \" \" + match[4] + \" \";\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\tPSEUDO: function( match, curLoop, inplace, result, not ) {\n\t\t\tif ( match[1] === \"not\" ) {\n\t\t\t\t// If we're dealing with a complex expression, or a simple one\n\t\t\t\tif ( ( chunker.exec(match[3]) || \"\" ).length > 1 || /^\\w/.test(match[3]) ) {\n\t\t\t\t\tmatch[3] = Sizzle(match[3], null, null, curLoop);\n\n\t\t\t\t} else {\n\t\t\t\t\tvar ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);\n\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tresult.push.apply( result, ret );\n\t\t\t\t\t}\n\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\t\n\t\t\treturn match;\n\t\t},\n\n\t\tPOS: function( match ) {\n\t\t\tmatch.unshift( true );\n\n\t\t\treturn match;\n\t\t}\n\t},\n\t\n\tfilters: {\n\t\tenabled: function( elem ) {\n\t\t\treturn elem.disabled === false && elem.type !== \"hidden\";\n\t\t},\n\n\t\tdisabled: function( elem ) {\n\t\t\treturn elem.disabled === true;\n\t\t},\n\n\t\tchecked: function( elem ) {\n\t\t\treturn elem.checked === true;\n\t\t},\n\t\t\n\t\tselected: 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\t\t\t\n\t\t\treturn elem.selected === true;\n\t\t},\n\n\t\tparent: function( elem ) {\n\t\t\treturn !!elem.firstChild;\n\t\t},\n\n\t\tempty: function( elem ) {\n\t\t\treturn !elem.firstChild;\n\t\t},\n\n\t\thas: function( elem, i, match ) {\n\t\t\treturn !!Sizzle( match[3], elem ).length;\n\t\t},\n\n\t\theader: function( elem ) {\n\t\t\treturn (/h\\d/i).test( elem.nodeName );\n\t\t},\n\n\t\ttext: function( elem ) {\n\t\t\tvar attr = elem.getAttribute( \"type\" ), type = elem.type;\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\" && \"text\" === type && ( attr === type || attr === null );\n\t\t},\n\n\t\tradio: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"radio\" === elem.type;\n\t\t},\n\n\t\tcheckbox: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"checkbox\" === elem.type;\n\t\t},\n\n\t\tfile: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"file\" === elem.type;\n\t\t},\n\n\t\tpassword: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"password\" === elem.type;\n\t\t},\n\n\t\tsubmit: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && \"submit\" === elem.type;\n\t\t},\n\n\t\timage: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"image\" === elem.type;\n\t\t},\n\n\t\treset: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && \"reset\" === elem.type;\n\t\t},\n\n\t\tbutton: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && \"button\" === elem.type || name === \"button\";\n\t\t},\n\n\t\tinput: function( elem ) {\n\t\t\treturn (/input|select|textarea|button/i).test( elem.nodeName );\n\t\t},\n\n\t\tfocus: function( elem ) {\n\t\t\treturn elem === elem.ownerDocument.activeElement;\n\t\t}\n\t},\n\tsetFilters: {\n\t\tfirst: function( elem, i ) {\n\t\t\treturn i === 0;\n\t\t},\n\n\t\tlast: function( elem, i, match, array ) {\n\t\t\treturn i === array.length - 1;\n\t\t},\n\n\t\teven: function( elem, i ) {\n\t\t\treturn i % 2 === 0;\n\t\t},\n\n\t\todd: function( elem, i ) {\n\t\t\treturn i % 2 === 1;\n\t\t},\n\n\t\tlt: function( elem, i, match ) {\n\t\t\treturn i < match[3] - 0;\n\t\t},\n\n\t\tgt: function( elem, i, match ) {\n\t\t\treturn i > match[3] - 0;\n\t\t},\n\n\t\tnth: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t},\n\n\t\teq: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t}\n\t},\n\tfilter: {\n\t\tPSEUDO: function( elem, match, i, array ) {\n\t\t\tvar name = match[1],\n\t\t\t\tfilter = Expr.filters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\n\t\t\t} else if ( name === \"contains\" ) {\n\t\t\t\treturn (elem.textContent || elem.innerText || getText([ elem ]) || \"\").indexOf(match[3]) >= 0;\n\n\t\t\t} else if ( name === \"not\" ) {\n\t\t\t\tvar not = match[3];\n\n\t\t\t\tfor ( var j = 0, l = not.length; j < l; j++ ) {\n\t\t\t\t\tif ( not[j] === elem ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\n\t\t\t} else {\n\t\t\t\tSizzle.error( name );\n\t\t\t}\n\t\t},\n\n\t\tCHILD: function( elem, match ) {\n\t\t\tvar first, last,\n\t\t\t\tdoneName, parent, cache,\n\t\t\t\tcount, diff,\n\t\t\t\ttype = match[1],\n\t\t\t\tnode = elem;\n\n\t\t\tswitch ( type ) {\n\t\t\t\tcase \"only\":\n\t\t\t\tcase \"first\":\n\t\t\t\t\twhile ( (node = node.previousSibling) )\t {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) { \n\t\t\t\t\t\t\treturn false; \n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( type === \"first\" ) { \n\t\t\t\t\t\treturn true; \n\t\t\t\t\t}\n\n\t\t\t\t\tnode = elem;\n\n\t\t\t\tcase \"last\":\n\t\t\t\t\twhile ( (node = node.nextSibling) )\t {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) { \n\t\t\t\t\t\t\treturn false; \n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn true;\n\n\t\t\t\tcase \"nth\":\n\t\t\t\t\tfirst = match[2];\n\t\t\t\t\tlast = match[3];\n\n\t\t\t\t\tif ( first === 1 && last === 0 ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tdoneName = match[0];\n\t\t\t\t\tparent = elem.parentNode;\n\t\n\t\t\t\t\tif ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) {\n\t\t\t\t\t\tcount = 0;\n\t\t\t\t\t\t\n\t\t\t\t\t\tfor ( node = parent.firstChild; node; node = node.nextSibling ) {\n\t\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\t\tnode.nodeIndex = ++count;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} \n\n\t\t\t\t\t\tparent[ expando ] = doneName;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tdiff = elem.nodeIndex - last;\n\n\t\t\t\t\tif ( first === 0 ) {\n\t\t\t\t\t\treturn diff === 0;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tID: function( elem, match ) {\n\t\t\treturn elem.nodeType === 1 && elem.getAttribute(\"id\") === match;\n\t\t},\n\n\t\tTAG: function( elem, match ) {\n\t\t\treturn (match === \"*\" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match;\n\t\t},\n\t\t\n\t\tCLASS: function( elem, match ) {\n\t\t\treturn (\" \" + (elem.className || elem.getAttribute(\"class\")) + \" \")\n\t\t\t\t.indexOf( match ) > -1;\n\t\t},\n\n\t\tATTR: function( elem, match ) {\n\t\t\tvar name = match[1],\n\t\t\t\tresult = Sizzle.attr ?\n\t\t\t\t\tSizzle.attr( elem, name ) :\n\t\t\t\t\tExpr.attrHandle[ name ] ?\n\t\t\t\t\tExpr.attrHandle[ name ]( elem ) :\n\t\t\t\t\telem[ name ] != null ?\n\t\t\t\t\t\telem[ name ] :\n\t\t\t\t\t\telem.getAttribute( name ),\n\t\t\t\tvalue = result + \"\",\n\t\t\t\ttype = match[2],\n\t\t\t\tcheck = match[4];\n\n\t\t\treturn result == null ?\n\t\t\t\ttype === \"!=\" :\n\t\t\t\t!type && Sizzle.attr ?\n\t\t\t\tresult != null :\n\t\t\t\ttype === \"=\" ?\n\t\t\t\tvalue === check :\n\t\t\t\ttype === \"*=\" ?\n\t\t\t\tvalue.indexOf(check) >= 0 :\n\t\t\t\ttype === \"~=\" ?\n\t\t\t\t(\" \" + value + \" \").indexOf(check) >= 0 :\n\t\t\t\t!check ?\n\t\t\t\tvalue && result !== false :\n\t\t\t\ttype === \"!=\" ?\n\t\t\t\tvalue !== check :\n\t\t\t\ttype === \"^=\" ?\n\t\t\t\tvalue.indexOf(check) === 0 :\n\t\t\t\ttype === \"$=\" ?\n\t\t\t\tvalue.substr(value.length - check.length) === check :\n\t\t\t\ttype === \"|=\" ?\n\t\t\t\tvalue === check || value.substr(0, check.length + 1) === check + \"-\" :\n\t\t\t\tfalse;\n\t\t},\n\n\t\tPOS: function( elem, match, i, array ) {\n\t\t\tvar name = match[2],\n\t\t\t\tfilter = Expr.setFilters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\t\t\t}\n\t\t}\n\t}\n};\n\nvar origPOS = Expr.match.POS,\n\tfescape = function(all, num){\n\t\treturn \"\\\\\" + (num - 0 + 1);\n\t};\n\nfor ( var type in Expr.match ) {\n\tExpr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\\[]*\\])(?![^\\(]*\\))/.source) );\n\tExpr.leftMatch[ type ] = new RegExp( /(^(?:.|\\r|\\n)*?)/.source + Expr.match[ type ].source.replace(/\\\\(\\d+)/g, fescape) );\n}\n\nvar makeArray = function( array, results ) {\n\tarray = Array.prototype.slice.call( array, 0 );\n\n\tif ( results ) {\n\t\tresults.push.apply( results, array );\n\t\treturn results;\n\t}\n\t\n\treturn array;\n};\n\n// Perform a simple check to determine if the browser is capable of\n// converting a NodeList to an array using builtin methods.\n// Also verifies that the returned array holds DOM nodes\n// (which is not the case in the Blackberry browser)\ntry {\n\tArray.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;\n\n// Provide a fallback method if it does not work\n} catch( e ) {\n\tmakeArray = function( array, results ) {\n\t\tvar i = 0,\n\t\t\tret = results || [];\n\n\t\tif ( toString.call(array) === \"[object Array]\" ) {\n\t\t\tArray.prototype.push.apply( ret, array );\n\n\t\t} else {\n\t\t\tif ( typeof array.length === \"number\" ) {\n\t\t\t\tfor ( var l = array.length; i < l; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; array[i]; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nvar sortOrder, siblingCheck;\n\nif ( document.documentElement.compareDocumentPosition ) {\n\tsortOrder = function( a, b ) {\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\tif ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {\n\t\t\treturn a.compareDocumentPosition ? -1 : 1;\n\t\t}\n\n\t\treturn a.compareDocumentPosition(b) & 4 ? -1 : 1;\n\t};\n\n} else {\n\tsortOrder = function( a, b ) {\n\t\t// The nodes are identical, we can exit early\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\n\t\t// Fallback to using sourceIndex (in IE) if it's available on both nodes\n\t\t} else if ( a.sourceIndex && b.sourceIndex ) {\n\t\t\treturn a.sourceIndex - b.sourceIndex;\n\t\t}\n\n\t\tvar al, bl,\n\t\t\tap = [],\n\t\t\tbp = [],\n\t\t\taup = a.parentNode,\n\t\t\tbup = b.parentNode,\n\t\t\tcur = aup;\n\n\t\t// If the nodes are siblings (or identical) we can do a quick check\n\t\tif ( aup === bup ) {\n\t\t\treturn siblingCheck( a, b );\n\n\t\t// If no parents were found then the nodes are disconnected\n\t\t} else if ( !aup ) {\n\t\t\treturn -1;\n\n\t\t} else if ( !bup ) {\n\t\t\treturn 1;\n\t\t}\n\n\t\t// Otherwise they're somewhere else in the tree so we need\n\t\t// to build up a full list of the parentNodes for comparison\n\t\twhile ( cur ) {\n\t\t\tap.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tcur = bup;\n\n\t\twhile ( cur ) {\n\t\t\tbp.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tal = ap.length;\n\t\tbl = bp.length;\n\n\t\t// Start walking down the tree looking for a discrepancy\n\t\tfor ( var i = 0; i < al && i < bl; i++ ) {\n\t\t\tif ( ap[i] !== bp[i] ) {\n\t\t\t\treturn siblingCheck( ap[i], bp[i] );\n\t\t\t}\n\t\t}\n\n\t\t// We ended someplace up the tree so do a sibling check\n\t\treturn i === al ?\n\t\t\tsiblingCheck( a, bp[i], -1 ) :\n\t\t\tsiblingCheck( ap[i], b, 1 );\n\t};\n\n\tsiblingCheck = function( a, b, ret ) {\n\t\tif ( a === b ) {\n\t\t\treturn ret;\n\t\t}\n\n\t\tvar cur = a.nextSibling;\n\n\t\twhile ( cur ) {\n\t\t\tif ( cur === b ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\n\t\t\tcur = cur.nextSibling;\n\t\t}\n\n\t\treturn 1;\n\t};\n}\n\n// Check to see if the browser returns elements by name when\n// querying by getElementById (and provide a workaround)\n(function(){\n\t// We're going to inject a fake input element with a specified name\n\tvar form = document.createElement(\"div\"),\n\t\tid = \"script\" + (new Date()).getTime(),\n\t\troot = document.documentElement;\n\n\tform.innerHTML = \"<a name='\" + id + \"'/>\";\n\n\t// Inject it into the root element, check its status, and remove it quickly\n\troot.insertBefore( form, root.firstChild );\n\n\t// The workaround has to do additional checks after a getElementById\n\t// Which slows things down for other browsers (hence the branching)\n\tif ( document.getElementById( id ) ) {\n\t\tExpr.find.ID = function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\n\n\t\t\t\treturn m ?\n\t\t\t\t\tm.id === match[1] || typeof m.getAttributeNode !== \"undefined\" && m.getAttributeNode(\"id\").nodeValue === match[1] ?\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\n\t\tExpr.filter.ID = function( elem, match ) {\n\t\t\tvar node = typeof elem.getAttributeNode !== \"undefined\" && elem.getAttributeNode(\"id\");\n\n\t\t\treturn elem.nodeType === 1 && node && node.nodeValue === match;\n\t\t};\n\t}\n\n\troot.removeChild( form );\n\n\t// release memory in IE\n\troot = form = null;\n})();\n\n(function(){\n\t// Check to see if the browser returns only elements\n\t// when doing getElementsByTagName(\"*\")\n\n\t// Create a fake element\n\tvar div = document.createElement(\"div\");\n\tdiv.appendChild( document.createComment(\"\") );\n\n\t// Make sure no comments are found\n\tif ( div.getElementsByTagName(\"*\").length > 0 ) {\n\t\tExpr.find.TAG = function( match, context ) {\n\t\t\tvar results = context.getElementsByTagName( match[1] );\n\n\t\t\t// Filter out possible comments\n\t\t\tif ( match[1] === \"*\" ) {\n\t\t\t\tvar tmp = [];\n\n\t\t\t\tfor ( var i = 0; results[i]; i++ ) {\n\t\t\t\t\tif ( results[i].nodeType === 1 ) {\n\t\t\t\t\t\ttmp.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tresults = tmp;\n\t\t\t}\n\n\t\t\treturn results;\n\t\t};\n\t}\n\n\t// Check to see if an attribute returns normalized href attributes\n\tdiv.innerHTML = \"<a href='#'></a>\";\n\n\tif ( div.firstChild && typeof div.firstChild.getAttribute !== \"undefined\" &&\n\t\t\tdiv.firstChild.getAttribute(\"href\") !== \"#\" ) {\n\n\t\tExpr.attrHandle.href = function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\", 2 );\n\t\t};\n\t}\n\n\t// release memory in IE\n\tdiv = null;\n})();\n\nif ( document.querySelectorAll ) {\n\t(function(){\n\t\tvar oldSizzle = Sizzle,\n\t\t\tdiv = document.createElement(\"div\"),\n\t\t\tid = \"__sizzle__\";\n\n\t\tdiv.innerHTML = \"<p class='TEST'></p>\";\n\n\t\t// Safari can't handle uppercase or unicode characters when\n\t\t// in quirks mode.\n\t\tif ( div.querySelectorAll && div.querySelectorAll(\".TEST\").length === 0 ) {\n\t\t\treturn;\n\t\t}\n\t\n\t\tSizzle = function( query, context, extra, seed ) {\n\t\t\tcontext = context || document;\n\n\t\t\t// Only use querySelectorAll on non-XML documents\n\t\t\t// (ID selectors don't work in non-HTML documents)\n\t\t\tif ( !seed && !Sizzle.isXML(context) ) {\n\t\t\t\t// See if we find a selector to speed up\n\t\t\t\tvar match = /^(\\w+$)|^\\.([\\w\\-]+$)|^#([\\w\\-]+$)/.exec( query );\n\t\t\t\t\n\t\t\t\tif ( match && (context.nodeType === 1 || context.nodeType === 9) ) {\n\t\t\t\t\t// Speed-up: Sizzle(\"TAG\")\n\t\t\t\t\tif ( match[1] ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByTagName( query ), extra );\n\t\t\t\t\t\n\t\t\t\t\t// Speed-up: Sizzle(\".CLASS\")\n\t\t\t\t\t} else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByClassName( match[2] ), extra );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif ( context.nodeType === 9 ) {\n\t\t\t\t\t// Speed-up: Sizzle(\"body\")\n\t\t\t\t\t// The body element only exists once, optimize finding it\n\t\t\t\t\tif ( query === \"body\" && context.body ) {\n\t\t\t\t\t\treturn makeArray( [ context.body ], extra );\n\t\t\t\t\t\t\n\t\t\t\t\t// Speed-up: Sizzle(\"#ID\")\n\t\t\t\t\t} else if ( match && match[3] ) {\n\t\t\t\t\t\tvar elem = context.getElementById( match[3] );\n\n\t\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\t\tif ( elem.id === match[3] ) {\n\t\t\t\t\t\t\t\treturn makeArray( [ elem ], extra );\n\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\treturn makeArray( [], extra );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn makeArray( context.querySelectorAll(query), extra );\n\t\t\t\t\t} catch(qsaError) {}\n\n\t\t\t\t// qSA works strangely on Element-rooted queries\n\t\t\t\t// We can work around this by specifying an extra ID on the root\n\t\t\t\t// and working up from there (Thanks to Andrew Dupont for the technique)\n\t\t\t\t// IE 8 doesn't work on object elements\n\t\t\t\t} else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== \"object\" ) {\n\t\t\t\t\tvar oldContext = context,\n\t\t\t\t\t\told = context.getAttribute( \"id\" ),\n\t\t\t\t\t\tnid = old || id,\n\t\t\t\t\t\thasParent = context.parentNode,\n\t\t\t\t\t\trelativeHierarchySelector = /^\\s*[+~]/.test( query );\n\n\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\tcontext.setAttribute( \"id\", nid );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnid = nid.replace( /'/g, \"\\\\$&\" );\n\t\t\t\t\t}\n\t\t\t\t\tif ( relativeHierarchySelector && hasParent ) {\n\t\t\t\t\t\tcontext = context.parentNode;\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif ( !relativeHierarchySelector || hasParent ) {\n\t\t\t\t\t\t\treturn makeArray( context.querySelectorAll( \"[id='\" + nid + \"'] \" + query ), extra );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} catch(pseudoError) {\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\t\toldContext.removeAttribute( \"id\" );\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\t\treturn oldSizzle(query, context, extra, seed);\n\t\t};\n\n\t\tfor ( var prop in oldSizzle ) {\n\t\t\tSizzle[ prop ] = oldSizzle[ prop ];\n\t\t}\n\n\t\t// release memory in IE\n\t\tdiv = null;\n\t})();\n}\n\n(function(){\n\tvar html = document.documentElement,\n\t\tmatches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;\n\n\tif ( matches ) {\n\t\t// Check to see if it's possible to do matchesSelector\n\t\t// on a disconnected node (IE 9 fails this)\n\t\tvar disconnectedMatch = !matches.call( document.createElement( \"div\" ), \"div\" ),\n\t\t\tpseudoWorks = false;\n\n\t\ttry {\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( document.documentElement, \"[test!='']:sizzle\" );\n\t\n\t\t} catch( pseudoError ) {\n\t\t\tpseudoWorks = true;\n\t\t}\n\n\t\tSizzle.matchesSelector = function( node, expr ) {\n\t\t\t// Make sure that attribute selectors are quoted\n\t\t\texpr = expr.replace(/\\=\\s*([^'\"\\]]*)\\s*\\]/g, \"='$1']\");\n\n\t\t\tif ( !Sizzle.isXML( node ) ) {\n\t\t\t\ttry { \n\t\t\t\t\tif ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {\n\t\t\t\t\t\tvar ret = matches.call( node, expr );\n\n\t\t\t\t\t\t// IE 9's matchesSelector returns false on disconnected nodes\n\t\t\t\t\t\tif ( ret || !disconnectedMatch ||\n\t\t\t\t\t\t\t\t// As well, disconnected nodes are said to be in a document\n\t\t\t\t\t\t\t\t// fragment in IE 9, so check for that\n\t\t\t\t\t\t\t\tnode.document && node.document.nodeType !== 11 ) {\n\t\t\t\t\t\t\treturn ret;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t\treturn Sizzle(expr, null, null, [node]).length > 0;\n\t\t};\n\t}\n})();\n\n(function(){\n\tvar div = document.createElement(\"div\");\n\n\tdiv.innerHTML = \"<div class='test e'></div><div class='test'></div>\";\n\n\t// Opera can't find a second classname (in 9.6)\n\t// Also, make sure that getElementsByClassName actually exists\n\tif ( !div.getElementsByClassName || div.getElementsByClassName(\"e\").length === 0 ) {\n\t\treturn;\n\t}\n\n\t// Safari caches class attributes, doesn't catch changes (in 3.2)\n\tdiv.lastChild.className = \"e\";\n\n\tif ( div.getElementsByClassName(\"e\").length === 1 ) {\n\t\treturn;\n\t}\n\t\n\tExpr.order.splice(1, 0, \"CLASS\");\n\tExpr.find.CLASS = function( match, context, isXML ) {\n\t\tif ( typeof context.getElementsByClassName !== \"undefined\" && !isXML ) {\n\t\t\treturn context.getElementsByClassName(match[1]);\n\t\t}\n\t};\n\n\t// release memory in IE\n\tdiv = null;\n})();\n\nfunction dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem[ expando ] === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 && !isXML ){\n\t\t\t\t\telem[ expando ] = doneName;\n\t\t\t\t\telem.sizset = i;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeName.toLowerCase() === cur ) {\n\t\t\t\t\tmatch = elem;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nfunction dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\t\t\t\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem[ expando ] === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !isXML ) {\n\t\t\t\t\t\telem[ expando ] = doneName;\n\t\t\t\t\t\telem.sizset = i;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( typeof cur !== \"string\" ) {\n\t\t\t\t\t\tif ( elem === cur ) {\n\t\t\t\t\t\t\tmatch = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {\n\t\t\t\t\t\tmatch = elem;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nif ( document.documentElement.contains ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn a !== b && (a.contains ? a.contains(b) : true);\n\t};\n\n} else if ( document.documentElement.compareDocumentPosition ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn !!(a.compareDocumentPosition(b) & 16);\n\t};\n\n} else {\n\tSizzle.contains = function() {\n\t\treturn false;\n\t};\n}\n\nSizzle.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 : 0).documentElement;\n\n\treturn documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\nvar posProcess = function( selector, context, seed ) {\n\tvar match,\n\t\ttmpSet = [],\n\t\tlater = \"\",\n\t\troot = context.nodeType ? [context] : context;\n\n\t// Position selectors must be done after the filter\n\t// And so must :not(positional) so we move all PSEUDOs to the end\n\twhile ( (match = Expr.match.PSEUDO.exec( selector )) ) {\n\t\tlater += match[0];\n\t\tselector = selector.replace( Expr.match.PSEUDO, \"\" );\n\t}\n\n\tselector = Expr.relative[selector] ? selector + \"*\" : selector;\n\n\tfor ( var i = 0, l = root.length; i < l; i++ ) {\n\t\tSizzle( selector, root[i], tmpSet, seed );\n\t}\n\n\treturn Sizzle.filter( later, tmpSet );\n};\n\n// EXPOSE\n// Override sizzle attribute retrieval\nSizzle.attr = jQuery.attr;\nSizzle.selectors.attrMap = {};\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\njQuery.expr[\":\"] = jQuery.expr.filters;\njQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\n\n\n})();\n\n\nvar runtil = /Until$/,\n\trparentsprev = /^(?:parents|prevUntil|prevAll)/,\n\t// Note: This RegExp should be improved, or likely pulled from Sizzle\n\trmultiselector = /,/,\n\tisSimple = /^.[^:#\\[\\.,]*$/,\n\tslice = Array.prototype.slice,\n\tPOS = jQuery.expr.match.POS,\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 self = this,\n\t\t\ti, l;\n\n\t\tif ( typeof selector !== \"string\" ) {\n\t\t\treturn jQuery( selector ).filter(function() {\n\t\t\t\tfor ( i = 0, l = self.length; i < l; 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\tvar ret = this.pushStack( \"\", \"find\", selector ),\n\t\t\tlength, n, r;\n\n\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\tlength = ret.length;\n\t\t\tjQuery.find( selector, this[i], ret );\n\n\t\t\tif ( i > 0 ) {\n\t\t\t\t// Make sure that the results are unique\n\t\t\t\tfor ( n = length; n < ret.length; n++ ) {\n\t\t\t\t\tfor ( r = 0; r < length; r++ ) {\n\t\t\t\t\t\tif ( ret[r] === ret[n] ) {\n\t\t\t\t\t\t\tret.splice(n--, 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\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\thas: function( target ) {\n\t\tvar targets = jQuery( target );\n\t\treturn this.filter(function() {\n\t\t\tfor ( var i = 0, l = targets.length; 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\tnot: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, false), \"not\", selector);\n\t},\n\n\tfilter: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, true), \"filter\", selector );\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 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\tPOS.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 ret = [], i, l, cur = this[0];\n\t\t\n\t\t// Array (deprecated as of jQuery 1.7)\n\t\tif ( jQuery.isArray( selectors ) ) {\n\t\t\tvar level = 1;\n\n\t\t\twhile ( cur && cur.ownerDocument && cur !== context ) {\n\t\t\t\tfor ( i = 0; i < selectors.length; i++ ) {\n\n\t\t\t\t\tif ( jQuery( cur ).is( selectors[ i ] ) ) {\n\t\t\t\t\t\tret.push({ selector: selectors[ i ], elem: cur, level: level });\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcur = cur.parentNode;\n\t\t\t\tlevel++;\n\t\t\t}\n\n\t\t\treturn ret;\n\t\t}\n\n\t\t// String\n\t\tvar pos = POS.test( selectors ) || typeof selectors !== \"string\" ?\n\t\t\t\tjQuery( selectors, context || this.context ) :\n\t\t\t\t0;\n\n\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\tcur = this[i];\n\n\t\t\twhile ( cur ) {\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\n\t\t\t\t} else {\n\t\t\t\t\tcur = cur.parentNode;\n\t\t\t\t\tif ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) {\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\tret = ret.length > 1 ? jQuery.unique( ret ) : ret;\n\n\t\treturn this.pushStack( ret, \"closest\", selectors );\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.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( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?\n\t\t\tall :\n\t\t\tjQuery.unique( all ) );\n\t},\n\n\tandSelf: function() {\n\t\treturn this.add( this.prevObject );\n\t}\n});\n\n// A painfully simple check to see if an element is disconnected\n// from a document (should be improved, where feasible).\nfunction isDisconnected( node ) {\n\treturn !node || !node.parentNode || node.parentNode.nodeType === 11;\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 jQuery.nth( elem, 2, \"nextSibling\" );\n\t},\n\tprev: function( elem ) {\n\t\treturn jQuery.nth( elem, 2, \"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.makeArray( 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 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {\n\t\t\tret = ret.reverse();\n\t\t}\n\n\t\treturn this.pushStack( ret, name, slice.call( arguments ).join(\",\") );\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\tnth: function( cur, result, dir, elem ) {\n\t\tresult = result || 1;\n\t\tvar num = 0;\n\n\t\tfor ( ; cur; cur = cur[dir] ) {\n\t\t\tif ( cur.nodeType === 1 && ++num === result ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn cur;\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, i ) {\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, i ) {\n\t\treturn ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;\n\t});\n}\n\n\n\n\nfunction createSafeFragment( document ) {\n\tvar list = nodeNames.split( \"|\" ),\n\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|canvas|datalist|details|figcaption|figure|footer|\" +\n\t\t\"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video\",\n\trinlinejQuery = / jQuery\\d+=\"(?:\\d+|null)\"/g,\n\trleadingWhitespace = /^\\s+/,\n\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/ig,\n\trtagName = /<([\\w:]+)/,\n\trtbody = /<tbody/i,\n\trhtml = /<|&#?\\w+;/,\n\trnoInnerhtml = /<(?:script|style)/i,\n\trnocache = /<(?:script|object|embed|option|style)/i,\n\trnoshimcache = new RegExp(\"<(?:\" + nodeNames + \")\", \"i\"),\n\t// checked=\"checked\" or checked\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\trscriptType = /\\/(java|ecma)script/i,\n\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|\\-\\-)/,\n\twrapMap = {\n\t\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\t\tlegend: [ 1, \"<fieldset>\", \"</fieldset>\" ],\n\t\tthead: [ 1, \"<table>\", \"</table>\" ],\n\t\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\t\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\t\tcol: [ 2, \"<table><tbody></tbody><colgroup>\", \"</colgroup></table>\" ],\n\t\tarea: [ 1, \"<map>\", \"</map>\" ],\n\t\t_default: [ 0, \"\", \"\" ]\n\t},\n\tsafeFragment = createSafeFragment( document );\n\nwrapMap.optgroup = wrapMap.option;\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n// IE can't serialize <link> and <script> tags normally\nif ( !jQuery.support.htmlSerialize ) {\n\twrapMap._default = [ 1, \"div<div>\", \"</div>\" ];\n}\n\njQuery.fn.extend({\n\ttext: function( text ) {\n\t\tif ( jQuery.isFunction(text) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tvar self = jQuery( this );\n\n\t\t\t\tself.text( text.call(this, i, self.text()) );\n\t\t\t});\n\t\t}\n\n\t\tif ( typeof text !== \"object\" && text !== undefined ) {\n\t\t\treturn this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );\n\t\t}\n\n\t\treturn jQuery.text( this );\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 ) {\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 ) {\n\t\t\t\tthis.insertBefore( elem, this.firstChild );\n\t\t\t}\n\t\t});\n\t},\n\n\tbefore: function() {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this );\n\t\t\t});\n\t\t} else if ( arguments.length ) {\n\t\t\tvar set = jQuery.clean( arguments );\n\t\t\tset.push.apply( set, this.toArray() );\n\t\t\treturn this.pushStack( set, \"before\", arguments );\n\t\t}\n\t},\n\n\tafter: function() {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n\t\t\t});\n\t\t} else if ( arguments.length ) {\n\t\t\tvar set = this.pushStack( this, \"after\", arguments );\n\t\t\tset.push.apply( set, jQuery.clean(arguments) );\n\t\t\treturn set;\n\t\t}\n\t},\n\n\t// keepData is for internal use only--do not document\n\tremove: function( selector, keepData ) {\n\t\tfor ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n\t\t\tif ( !selector || jQuery.filter( selector, [ elem ] ).length ) {\n\t\t\t\tif ( !keepData && elem.nodeType === 1 ) {\n\t\t\t\t\tjQuery.cleanData( elem.getElementsByTagName(\"*\") );\n\t\t\t\t\tjQuery.cleanData( [ elem ] );\n\t\t\t\t}\n\n\t\t\t\tif ( elem.parentNode ) {\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\tfor ( var i = 0, elem; (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( elem.getElementsByTagName(\"*\") );\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\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\tif ( value === undefined ) {\n\t\t\treturn this[0] && this[0].nodeType === 1 ?\n\t\t\t\tthis[0].innerHTML.replace(rinlinejQuery, \"\") :\n\t\t\t\tnull;\n\n\t\t// See if we can take a shortcut and just use innerHTML\n\t\t} else if ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n\t\t\t(jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&\n\t\t\t!wrapMap[ (rtagName.exec( value ) || [\"\", \"\"])[1].toLowerCase() ] ) {\n\n\t\t\tvalue = value.replace(rxhtmlTag, \"<$1></$2>\");\n\n\t\t\ttry {\n\t\t\t\tfor ( var i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\tif ( this[i].nodeType === 1 ) {\n\t\t\t\t\t\tjQuery.cleanData( this[i].getElementsByTagName(\"*\") );\n\t\t\t\t\t\tthis[i].innerHTML = value;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t} catch(e) {\n\t\t\t\tthis.empty().append( value );\n\t\t\t}\n\n\t\t} else if ( jQuery.isFunction( value ) ) {\n\t\t\tthis.each(function(i){\n\t\t\t\tvar self = jQuery( this );\n\n\t\t\t\tself.html( value.call(this, i, self.html()) );\n\t\t\t});\n\n\t\t} else {\n\t\t\tthis.empty().append( value );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\treplaceWith: function( value ) {\n\t\tif ( this[0] && this[0].parentNode ) {\n\t\t\t// Make sure that the elements are removed from the DOM before they are inserted\n\t\t\t// this can help fix replacing a parent with child elements\n\t\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\t\treturn this.each(function(i) {\n\t\t\t\t\tvar self = jQuery(this), old = self.html();\n\t\t\t\t\tself.replaceWith( value.call( this, i, old ) );\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif ( typeof value !== \"string\" ) {\n\t\t\t\tvalue = jQuery( value ).detach();\n\t\t\t}\n\n\t\t\treturn this.each(function() {\n\t\t\t\tvar next = this.nextSibling,\n\t\t\t\t\tparent = this.parentNode;\n\n\t\t\t\tjQuery( this ).remove();\n\n\t\t\t\tif ( next ) {\n\t\t\t\t\tjQuery(next).before( value );\n\t\t\t\t} else {\n\t\t\t\t\tjQuery(parent).append( value );\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\treturn this.length ?\n\t\t\t\tthis.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), \"replaceWith\", value ) :\n\t\t\t\tthis;\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\t\tvar results, first, fragment, parent,\n\t\t\tvalue = args[0],\n\t\t\tscripts = [];\n\n\t\t// We can't cloneNode fragments that contain checked, in WebKit\n\t\tif ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === \"string\" && rchecked.test( value ) ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery(this).domManip( args, table, callback, true );\n\t\t\t});\n\t\t}\n\n\t\tif ( jQuery.isFunction(value) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tvar self = jQuery(this);\n\t\t\t\targs[0] = value.call(this, i, table ? self.html() : undefined);\n\t\t\t\tself.domManip( args, table, callback );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\tparent = value && value.parentNode;\n\n\t\t\t// If we're in a fragment, just use that instead of building a new one\n\t\t\tif ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {\n\t\t\t\tresults = { fragment: parent };\n\n\t\t\t} else {\n\t\t\t\tresults = jQuery.buildFragment( args, this, scripts );\n\t\t\t}\n\n\t\t\tfragment = results.fragment;\n\n\t\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\t\tfirst = fragment = fragment.firstChild;\n\t\t\t} else {\n\t\t\t\tfirst = fragment.firstChild;\n\t\t\t}\n\n\t\t\tif ( first ) {\n\t\t\t\ttable = table && jQuery.nodeName( first, \"tr\" );\n\n\t\t\t\tfor ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {\n\t\t\t\t\tcallback.call(\n\t\t\t\t\t\ttable ?\n\t\t\t\t\t\t\troot(this[i], first) :\n\t\t\t\t\t\t\tthis[i],\n\t\t\t\t\t\t// Make sure that we do not leak memory by inadvertently discarding\n\t\t\t\t\t\t// the original fragment (which might have attached data) instead of\n\t\t\t\t\t\t// using it; in addition, use the original fragment object for the last\n\t\t\t\t\t\t// item instead of first because it can end up being emptied incorrectly\n\t\t\t\t\t\t// in certain situations (Bug #8070).\n\t\t\t\t\t\t// Fragments from the fragment cache must always be cloned and never used\n\t\t\t\t\t\t// in place.\n\t\t\t\t\t\tresults.cacheable || ( l > 1 && i < lastIndex ) ?\n\t\t\t\t\t\t\tjQuery.clone( fragment, true, true ) :\n\t\t\t\t\t\t\tfragment\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( scripts.length ) {\n\t\t\t\tjQuery.each( scripts, evalScript );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n});\n\nfunction root( elem, cur ) {\n\treturn jQuery.nodeName(elem, \"table\") ?\n\t\t(elem.getElementsByTagName(\"tbody\")[0] ||\n\t\telem.appendChild(elem.ownerDocument.createElement(\"tbody\"))) :\n\t\telem;\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 ].namespace ? \".\" : \"\" ) + events[ type ][ i ].namespace, events[ type ][ i ], events[ type ][ i ].data );\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 cloneFixAttributes( src, dest ) {\n\tvar nodeName;\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\t// clearAttributes removes the attributes, which we don't want,\n\t// but also removes the attachEvent events, which we *do* want\n\tif ( dest.clearAttributes ) {\n\t\tdest.clearAttributes();\n\t}\n\n\t// mergeAttributes, in contrast, only merges back on the\n\t// original attributes, not the events\n\tif ( dest.mergeAttributes ) {\n\t\tdest.mergeAttributes( src );\n\t}\n\n\tnodeName = dest.nodeName.toLowerCase();\n\n\t// IE6-8 fail to clone children inside object elements that use\n\t// the proprietary classid attribute value (rather than the type\n\t// attribute) to identify the type of content to display\n\tif ( nodeName === \"object\" ) {\n\t\tdest.outerHTML = src.outerHTML;\n\n\t} else if ( nodeName === \"input\" && (src.type === \"checkbox\" || src.type === \"radio\") ) {\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\t\tif ( src.checked ) {\n\t\t\tdest.defaultChecked = dest.checked = src.checked;\n\t\t}\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.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\t// Event data gets referenced instead of copied if the expando\n\t// gets copied too\n\tdest.removeAttribute( jQuery.expando );\n}\n\njQuery.buildFragment = function( args, nodes, scripts ) {\n\tvar fragment, cacheable, cacheresults, doc,\n\tfirst = args[ 0 ];\n\n\t// nodes may contain either an explicit document object,\n\t// a jQuery collection or context object.\n\t// If nodes[0] contains a valid object to assign to doc\n\tif ( nodes && nodes[0] ) {\n\t\tdoc = nodes[0].ownerDocument || nodes[0];\n\t}\n\n\t// Ensure that an attr object doesn't incorrectly stand in as a document object\n\t// Chrome and Firefox seem to allow this to occur and will throw exception\n\t// Fixes #8950\n\tif ( !doc.createDocumentFragment ) {\n\t\tdoc = document;\n\t}\n\n\t// Only cache \"small\" (1/2 KB) HTML strings that are associated with the main document\n\t// Cloning options loses the selected state, so don't cache them\n\t// IE 6 doesn't like it when you put <object> or <embed> elements in a fragment\n\t// Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache\n\t// Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501\n\tif ( args.length === 1 && typeof first === \"string\" && first.length < 512 && doc === document &&\n\t\tfirst.charAt(0) === \"<\" && !rnocache.test( first ) &&\n\t\t(jQuery.support.checkClone || !rchecked.test( first )) &&\n\t\t(jQuery.support.html5Clone || !rnoshimcache.test( first )) ) {\n\n\t\tcacheable = true;\n\n\t\tcacheresults = jQuery.fragments[ first ];\n\t\tif ( cacheresults && cacheresults !== 1 ) {\n\t\t\tfragment = cacheresults;\n\t\t}\n\t}\n\n\tif ( !fragment ) {\n\t\tfragment = doc.createDocumentFragment();\n\t\tjQuery.clean( args, doc, fragment, scripts );\n\t}\n\n\tif ( cacheable ) {\n\t\tjQuery.fragments[ first ] = cacheresults ? fragment : 1;\n\t}\n\n\treturn { fragment: fragment, cacheable: cacheable };\n};\n\njQuery.fragments = {};\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 ret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tparent = this.length === 1 && this[0].parentNode;\n\n\t\tif ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {\n\t\t\tinsert[ original ]( this[0] );\n\t\t\treturn this;\n\n\t\t} else {\n\t\t\tfor ( var i = 0, l = insert.length; i < l; i++ ) {\n\t\t\t\tvar elems = ( i > 0 ? this.clone(true) : this ).get();\n\t\t\t\tjQuery( insert[i] )[ original ]( elems );\n\t\t\t\tret = ret.concat( elems );\n\t\t\t}\n\n\t\t\treturn this.pushStack( ret, name, insert.selector );\n\t\t}\n\t};\n});\n\nfunction getAll( elem ) {\n\tif ( typeof elem.getElementsByTagName !== \"undefined\" ) {\n\t\treturn elem.getElementsByTagName( \"*\" );\n\n\t} else if ( typeof elem.querySelectorAll !== \"undefined\" ) {\n\t\treturn elem.querySelectorAll( \"*\" );\n\n\t} else {\n\t\treturn [];\n\t}\n}\n\n// Used in clean, fixes the defaultChecked property\nfunction fixDefaultChecked( elem ) {\n\tif ( elem.type === \"checkbox\" || elem.type === \"radio\" ) {\n\t\telem.defaultChecked = elem.checked;\n\t}\n}\n// Finds all inputs and passes them to fixDefaultChecked\nfunction findInputs( elem ) {\n\tvar nodeName = ( elem.nodeName || \"\" ).toLowerCase();\n\tif ( nodeName === \"input\" ) {\n\t\tfixDefaultChecked( elem );\n\t// Skip scripts, get other children\n\t} else if ( nodeName !== \"script\" && typeof elem.getElementsByTagName !== \"undefined\" ) {\n\t\tjQuery.grep( elem.getElementsByTagName(\"input\"), fixDefaultChecked );\n\t}\n}\n\n// Derived From: http://www.iecss.com/shimprove/javascript/shimprove.1-0-1.js\nfunction shimCloneNode( elem ) {\n\tvar div = document.createElement( \"div\" );\n\tsafeFragment.appendChild( div );\n\n\tdiv.innerHTML = elem.outerHTML;\n\treturn div.firstChild;\n}\n\njQuery.extend({\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar srcElements,\n\t\t\tdestElements,\n\t\t\ti,\n\t\t\t// IE<=8 does not properly clone detached, unknown element nodes\n\t\t\tclone = jQuery.support.html5Clone || !rnoshimcache.test( \"<\" + elem.nodeName ) ?\n\t\t\t\telem.cloneNode( true ) :\n\t\t\t\tshimCloneNode( elem );\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\t\t\t// IE copies events bound via attachEvent when using cloneNode.\n\t\t\t// Calling detachEvent on the clone will also remove the events\n\t\t\t// from the original. In order to get around this, we use some\n\t\t\t// proprietary methods to clear the events. Thanks to MooTools\n\t\t\t// guys for this hotness.\n\n\t\t\tcloneFixAttributes( elem, clone );\n\n\t\t\t// Using Sizzle here is crazy slow, so we use getElementsByTagName instead\n\t\t\tsrcElements = getAll( elem );\n\t\t\tdestElements = getAll( clone );\n\n\t\t\t// Weird iteration because IE will replace the length property\n\t\t\t// with an element if you are cloning the body and one of the\n\t\t\t// elements on the page has a name or id of \"length\"\n\t\t\tfor ( i = 0; srcElements[i]; ++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\tcloneFixAttributes( srcElements[i], 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\tcloneCopyEvent( elem, clone );\n\n\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\tsrcElements = getAll( elem );\n\t\t\t\tdestElements = getAll( clone );\n\n\t\t\t\tfor ( i = 0; srcElements[i]; ++i ) {\n\t\t\t\t\tcloneCopyEvent( srcElements[i], destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tsrcElements = destElements = null;\n\n\t\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tclean: function( elems, context, fragment, scripts ) {\n\t\tvar checkScriptType;\n\n\t\tcontext = context || document;\n\n\t\t// !context.createElement fails in IE with an error but returns typeof 'object'\n\t\tif ( typeof context.createElement === \"undefined\" ) {\n\t\t\tcontext = context.ownerDocument || context[0] && context[0].ownerDocument || document;\n\t\t}\n\n\t\tvar ret = [], j;\n\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( typeof elem === \"number\" ) {\n\t\t\t\telem += \"\";\n\t\t\t}\n\n\t\t\tif ( !elem ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Convert html string into DOM nodes\n\t\t\tif ( typeof elem === \"string\" ) {\n\t\t\t\tif ( !rhtml.test( elem ) ) {\n\t\t\t\t\telem = context.createTextNode( elem );\n\t\t\t\t} else {\n\t\t\t\t\t// Fix \"XHTML\"-style tags in all browsers\n\t\t\t\t\telem = elem.replace(rxhtmlTag, \"<$1></$2>\");\n\n\t\t\t\t\t// Trim whitespace, otherwise indexOf won't work as expected\n\t\t\t\t\tvar tag = ( rtagName.exec( elem ) || [\"\", \"\"] )[1].toLowerCase(),\n\t\t\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default,\n\t\t\t\t\t\tdepth = wrap[0],\n\t\t\t\t\t\tdiv = context.createElement(\"div\");\n\n\t\t\t\t\t// Append wrapper element to unknown element safe doc fragment\n\t\t\t\t\tif ( context === document ) {\n\t\t\t\t\t\t// Use the fragment we've already created for this document\n\t\t\t\t\t\tsafeFragment.appendChild( div );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Use a fragment created with the owner document\n\t\t\t\t\t\tcreateSafeFragment( context ).appendChild( div );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Go to html and back, then peel off extra wrappers\n\t\t\t\t\tdiv.innerHTML = wrap[1] + elem + wrap[2];\n\n\t\t\t\t\t// Move to the right depth\n\t\t\t\t\twhile ( depth-- ) {\n\t\t\t\t\t\tdiv = div.lastChild;\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\tvar hasBody = rtbody.test(elem),\n\t\t\t\t\t\t\ttbody = tag === \"table\" && !hasBody ?\n\t\t\t\t\t\t\t\tdiv.firstChild && div.firstChild.childNodes :\n\n\t\t\t\t\t\t\t\t// String was a bare <thead> or <tfoot>\n\t\t\t\t\t\t\t\twrap[1] === \"<table>\" && !hasBody ?\n\t\t\t\t\t\t\t\t\tdiv.childNodes :\n\t\t\t\t\t\t\t\t\t[];\n\n\t\t\t\t\t\tfor ( j = tbody.length - 1; j >= 0 ; --j ) {\n\t\t\t\t\t\t\tif ( jQuery.nodeName( tbody[ j ], \"tbody\" ) && !tbody[ j ].childNodes.length ) {\n\t\t\t\t\t\t\t\ttbody[ j ].parentNode.removeChild( tbody[ j ] );\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// IE completely kills leading whitespace when innerHTML is used\n\t\t\t\t\tif ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {\n\t\t\t\t\t\tdiv.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );\n\t\t\t\t\t}\n\n\t\t\t\t\telem = div.childNodes;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Resets defaultChecked for any radios and checkboxes\n\t\t\t// about to be appended to the DOM in IE 6/7 (#8060)\n\t\t\tvar len;\n\t\t\tif ( !jQuery.support.appendChecked ) {\n\t\t\t\tif ( elem[0] && typeof (len = elem.length) === \"number\" ) {\n\t\t\t\t\tfor ( j = 0; j < len; j++ ) {\n\t\t\t\t\t\tfindInputs( elem[j] );\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tfindInputs( elem );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( elem.nodeType ) {\n\t\t\t\tret.push( elem );\n\t\t\t} else {\n\t\t\t\tret = jQuery.merge( ret, elem );\n\t\t\t}\n\t\t}\n\n\t\tif ( fragment ) {\n\t\t\tcheckScriptType = function( elem ) {\n\t\t\t\treturn !elem.type || rscriptType.test( elem.type );\n\t\t\t};\n\t\t\tfor ( i = 0; ret[i]; i++ ) {\n\t\t\t\tif ( scripts && jQuery.nodeName( ret[i], \"script\" ) && (!ret[i].type || ret[i].type.toLowerCase() === \"text/javascript\") ) {\n\t\t\t\t\tscripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );\n\n\t\t\t\t} else {\n\t\t\t\t\tif ( ret[i].nodeType === 1 ) {\n\t\t\t\t\t\tvar jsTags = jQuery.grep( ret[i].getElementsByTagName( \"script\" ), checkScriptType );\n\n\t\t\t\t\t\tret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );\n\t\t\t\t\t}\n\t\t\t\t\tfragment.appendChild( ret[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tcleanData: function( elems ) {\n\t\tvar data, id,\n\t\t\tcache = jQuery.cache,\n\t\t\tspecial = jQuery.event.special,\n\t\t\tdeleteExpando = jQuery.support.deleteExpando;\n\n\t\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tid = elem[ jQuery.expando ];\n\n\t\t\tif ( id ) {\n\t\t\t\tdata = cache[ id ];\n\n\t\t\t\tif ( data && data.events ) {\n\t\t\t\t\tfor ( var type in data.events ) {\n\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Null the DOM reference to avoid IE6/7/8 leak (#7054)\n\t\t\t\t\tif ( data.handle ) {\n\t\t\t\t\t\tdata.handle.elem = null;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( deleteExpando ) {\n\t\t\t\t\tdelete elem[ jQuery.expando ];\n\n\t\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\t\telem.removeAttribute( jQuery.expando );\n\t\t\t\t}\n\n\t\t\t\tdelete cache[ id ];\n\t\t\t}\n\t\t}\n\t}\n});\n\nfunction evalScript( i, elem ) {\n\tif ( elem.src ) {\n\t\tjQuery.ajax({\n\t\t\turl: elem.src,\n\t\t\tasync: false,\n\t\t\tdataType: \"script\"\n\t\t});\n\t} else {\n\t\tjQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || \"\" ).replace( rcleanScript, \"/*$0*/\" ) );\n\t}\n\n\tif ( elem.parentNode ) {\n\t\telem.parentNode.removeChild( elem );\n\t}\n}\n\n\n\n\nvar ralpha = /alpha\\([^)]*\\)/i,\n\tropacity = /opacity=([^)]*)/,\n\t// fixed for IE9, see #8346\n\trupper = /([A-Z]|^ms)/g,\n\trnumpx = /^-?\\d+(?:px)?$/i,\n\trnum = /^-?\\d/,\n\trrelNum = /^([\\-+])=([\\-+.\\de]+)/,\n\n\tcssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\tcssWidth = [ \"Left\", \"Right\" ],\n\tcssHeight = [ \"Top\", \"Bottom\" ],\n\tcurCSS,\n\n\tgetComputedStyle,\n\tcurrentStyle;\n\njQuery.fn.css = function( name, value ) {\n\t// Setting 'undefined' is a no-op\n\tif ( arguments.length === 2 && value === undefined ) {\n\t\treturn this;\n\t}\n\n\treturn jQuery.access( this, name, value, true, function( elem, name, value ) {\n\t\treturn value !== undefined ?\n\t\t\tjQuery.style( elem, name, value ) :\n\t\t\tjQuery.css( elem, name );\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\", \"opacity\" );\n\t\t\t\t\treturn ret === \"\" ? \"1\" : ret;\n\n\t\t\t\t} else {\n\t\t\t\t\treturn elem.style.opacity;\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\"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, origName = jQuery.camelCase( name ),\n\t\t\tstyle = elem.style, hooks = jQuery.cssHooks[ origName ];\n\n\t\tname = jQuery.cssProps[ origName ] || 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// 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 )) !== undefined ) {\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 ) {\n\t\tvar ret, hooks;\n\n\t\t// Make sure that we're working with the right name\n\t\tname = jQuery.camelCase( name );\n\t\thooks = jQuery.cssHooks[ name ];\n\t\tname = jQuery.cssProps[ name ] || name;\n\n\t\t// cssFloat needs a special treatment\n\t\tif ( name === \"cssFloat\" ) {\n\t\t\tname = \"float\";\n\t\t}\n\n\t\t// If a hook was provided get the computed value from there\n\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {\n\t\t\treturn ret;\n\n\t\t// Otherwise, if a way to get the computed value exists, use that\n\t\t} else if ( curCSS ) {\n\t\t\treturn curCSS( elem, name );\n\t\t}\n\t},\n\n\t// A method for quickly swapping in/out CSS properties to get correct calculations\n\tswap: function( elem, options, callback ) {\n\t\tvar old = {};\n\n\t\t// Remember the old values, and insert the new ones\n\t\tfor ( var 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\tcallback.call( elem );\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\t}\n});\n\n// DEPRECATED, Use jQuery.css() instead\njQuery.curCSS = jQuery.css;\n\njQuery.each([\"height\", \"width\"], function( i, name ) {\n\tjQuery.cssHooks[ name ] = {\n\t\tget: function( elem, computed, extra ) {\n\t\t\tvar val;\n\n\t\t\tif ( computed ) {\n\t\t\t\tif ( elem.offsetWidth !== 0 ) {\n\t\t\t\t\treturn getWH( elem, name, extra );\n\t\t\t\t} else {\n\t\t\t\t\tjQuery.swap( elem, cssShow, function() {\n\t\t\t\t\t\tval = getWH( elem, name, extra );\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\treturn val;\n\t\t\t}\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\tif ( rnumpx.test( value ) ) {\n\t\t\t\t// ignore negative width and height values #1599\n\t\t\t\tvalue = parseFloat( value );\n\n\t\t\t\tif ( value >= 0 ) {\n\t\t\t\t\treturn value + \"px\";\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\treturn value;\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( parseFloat( RegExp.$1 ) / 100 ) + \"\" :\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\tif ( value >= 1 && jQuery.trim( filter.replace( ralpha, \"\" ) ) === \"\" ) {\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 there is no filter style applied in a css rule, we are done\n\t\t\t\tif ( 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\njQuery(function() {\n\t// This hook cannot be added until DOM ready because the support test\n\t// for it is not run until after DOM ready\n\tif ( !jQuery.support.reliableMarginRight ) {\n\t\tjQuery.cssHooks.marginRight = {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\t\t// Work around by temporarily setting element display to inline-block\n\t\t\t\tvar ret;\n\t\t\t\tjQuery.swap( elem, { \"display\": \"inline-block\" }, function() {\n\t\t\t\t\tif ( computed ) {\n\t\t\t\t\t\tret = curCSS( elem, \"margin-right\", \"marginRight\" );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tret = elem.style.marginRight;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t};\n\t}\n});\n\nif ( document.defaultView && document.defaultView.getComputedStyle ) {\n\tgetComputedStyle = function( elem, name ) {\n\t\tvar ret, defaultView, computedStyle;\n\n\t\tname = name.replace( rupper, \"-$1\" ).toLowerCase();\n\n\t\tif ( (defaultView = elem.ownerDocument.defaultView) &&\n\t\t\t\t(computedStyle = defaultView.getComputedStyle( elem, null )) ) {\n\t\t\tret = computedStyle.getPropertyValue( name );\n\t\t\tif ( ret === \"\" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {\n\t\t\t\tret = jQuery.style( elem, name );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nif ( document.documentElement.currentStyle ) {\n\tcurrentStyle = function( elem, name ) {\n\t\tvar left, rsLeft, uncomputed,\n\t\t\tret = elem.currentStyle && elem.currentStyle[ name ],\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 && (uncomputed = style[ name ]) ) {\n\t\t\tret = uncomputed;\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\tif ( !rnumpx.test( ret ) && rnum.test( ret ) ) {\n\n\t\t\t// Remember the original values\n\t\t\tleft = style.left;\n\t\t\trsLeft = elem.runtimeStyle && elem.runtimeStyle.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\telem.runtimeStyle.left = elem.currentStyle.left;\n\t\t\t}\n\t\t\tstyle.left = name === \"fontSize\" ? \"1em\" : ( ret || 0 );\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\telem.runtimeStyle.left = rsLeft;\n\t\t\t}\n\t\t}\n\n\t\treturn ret === \"\" ? \"auto\" : ret;\n\t};\n}\n\ncurCSS = getComputedStyle || currentStyle;\n\nfunction getWH( elem, name, extra ) {\n\n\t// Start with offset property\n\tvar val = name === \"width\" ? elem.offsetWidth : elem.offsetHeight,\n\t\twhich = name === \"width\" ? cssWidth : cssHeight,\n\t\ti = 0,\n\t\tlen = which.length;\n\n\tif ( val > 0 ) {\n\t\tif ( extra !== \"border\" ) {\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\tif ( !extra ) {\n\t\t\t\t\tval -= parseFloat( jQuery.css( elem, \"padding\" + which[ i ] ) ) || 0;\n\t\t\t\t}\n\t\t\t\tif ( extra === \"margin\" ) {\n\t\t\t\t\tval += parseFloat( jQuery.css( elem, extra + which[ i ] ) ) || 0;\n\t\t\t\t} else {\n\t\t\t\t\tval -= parseFloat( jQuery.css( elem, \"border\" + which[ i ] + \"Width\" ) ) || 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn val + \"px\";\n\t}\n\n\t// Fall back to computed then uncomputed css if necessary\n\tval = curCSS( elem, name, name );\n\tif ( val < 0 || val == null ) {\n\t\tval = elem.style[ name ] || 0;\n\t}\n\t// Normalize \"\", auto, and prepare for extra\n\tval = parseFloat( val ) || 0;\n\n\t// Add padding, border, margin\n\tif ( extra ) {\n\t\tfor ( ; i < len; i++ ) {\n\t\t\tval += parseFloat( jQuery.css( elem, \"padding\" + which[ i ] ) ) || 0;\n\t\t\tif ( extra !== \"padding\" ) {\n\t\t\t\tval += parseFloat( jQuery.css( elem, \"border\" + which[ i ] + \"Width\" ) ) || 0;\n\t\t\t}\n\t\t\tif ( extra === \"margin\" ) {\n\t\t\t\tval += parseFloat( jQuery.css( elem, extra + which[ i ] ) ) || 0;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn val + \"px\";\n}\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.hidden = function( elem ) {\n\t\tvar width = elem.offsetWidth,\n\t\t\theight = elem.offsetHeight;\n\n\t\treturn ( width === 0 && height === 0 ) || (!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\n\n\nvar r20 = /%20/g,\n\trbracket = /\\[\\]$/,\n\trCRLF = /\\r?\\n/g,\n\trhash = /#.*$/,\n\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/mg, // IE leaves an \\r character at EOL\n\trinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,\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\trquery = /\\?/,\n\trscript = /<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi,\n\trselectTextarea = /^(?:select|textarea)/i,\n\trspacesAjax = /\\s+/,\n\trts = /([?&])_=[^&]*/,\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// Document location\n\tajaxLocation,\n\n\t// Document location segments\n\tajaxLocParts,\n\n\t// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression\n\tallTypes = [\"*/\"] + [\"*\"];\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\tif ( jQuery.isFunction( func ) ) {\n\t\t\tvar dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),\n\t\t\t\ti = 0,\n\t\t\t\tlength = dataTypes.length,\n\t\t\t\tdataType,\n\t\t\t\tlist,\n\t\t\t\tplaceBefore;\n\n\t\t\t// For each dataType in the dataTypeExpression\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tdataType = dataTypes[ i ];\n\t\t\t\t// We control if we're asked to add before\n\t\t\t\t// any existing element\n\t\t\t\tplaceBefore = /^\\+/.test( dataType );\n\t\t\t\tif ( placeBefore ) {\n\t\t\t\t\tdataType = dataType.substr( 1 ) || \"*\";\n\t\t\t\t}\n\t\t\t\tlist = structure[ dataType ] = structure[ dataType ] || [];\n\t\t\t\t// then we add to the structure accordingly\n\t\t\t\tlist[ placeBefore ? \"unshift\" : \"push\" ]( func );\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\t\tdataType /* internal */, inspected /* internal */ ) {\n\n\tdataType = dataType || options.dataTypes[ 0 ];\n\tinspected = inspected || {};\n\n\tinspected[ dataType ] = true;\n\n\tvar list = structure[ dataType ],\n\t\ti = 0,\n\t\tlength = list ? list.length : 0,\n\t\texecuteOnly = ( structure === prefilters ),\n\t\tselection;\n\n\tfor ( ; i < length && ( executeOnly || !selection ); i++ ) {\n\t\tselection = list[ i ]( options, originalOptions, jqXHR );\n\t\t// If we got redirected to another dataType\n\t\t// we try there if executing only and not done already\n\t\tif ( typeof selection === \"string\" ) {\n\t\t\tif ( !executeOnly || inspected[ selection ] ) {\n\t\t\t\tselection = undefined;\n\t\t\t} else {\n\t\t\t\toptions.dataTypes.unshift( selection );\n\t\t\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\t\t\tstructure, options, originalOptions, jqXHR, selection, inspected );\n\t\t\t}\n\t\t}\n\t}\n\t// If we're only executing or nothing was selected\n\t// we try the catchall dataType if not done already\n\tif ( ( executeOnly || !selection ) && !inspected[ \"*\" ] ) {\n\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\tstructure, options, originalOptions, jqXHR, \"*\", inspected );\n\t}\n\t// unnecessary when only executing (prefilters)\n\t// but it'll be ignored by the caller in that case\n\treturn selection;\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\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\njQuery.fn.extend({\n\tload: function( url, params, callback ) {\n\t\tif ( typeof url !== \"string\" && _load ) {\n\t\t\treturn _load.apply( this, arguments );\n\n\t\t// Don't do a request if no elements are being requested\n\t\t} else if ( !this.length ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tvar off = url.indexOf( \" \" );\n\t\tif ( off >= 0 ) {\n\t\t\tvar selector = url.slice( off, url.length );\n\t\t\turl = url.slice( 0, off );\n\t\t}\n\n\t\t// Default to a GET request\n\t\tvar type = \"GET\";\n\n\t\t// If the second parameter was provided\n\t\tif ( params ) {\n\t\t\t// If it's a function\n\t\t\tif ( jQuery.isFunction( params ) ) {\n\t\t\t\t// We assume that it's the callback\n\t\t\t\tcallback = params;\n\t\t\t\tparams = undefined;\n\n\t\t\t// Otherwise, build a param string\n\t\t\t} else if ( typeof params === \"object\" ) {\n\t\t\t\tparams = jQuery.param( params, jQuery.ajaxSettings.traditional );\n\t\t\t\ttype = \"POST\";\n\t\t\t}\n\t\t}\n\n\t\tvar self = this;\n\n\t\t// Request the remote document\n\t\tjQuery.ajax({\n\t\t\turl: url,\n\t\t\ttype: type,\n\t\t\tdataType: \"html\",\n\t\t\tdata: params,\n\t\t\t// Complete callback (responseText is used internally)\n\t\t\tcomplete: function( jqXHR, status, responseText ) {\n\t\t\t\t// Store the response as specified by the jqXHR object\n\t\t\t\tresponseText = jqXHR.responseText;\n\t\t\t\t// If successful, inject the HTML into all the matched elements\n\t\t\t\tif ( jqXHR.isResolved() ) {\n\t\t\t\t\t// #4825: Get the actual response in case\n\t\t\t\t\t// a dataFilter is present in ajaxSettings\n\t\t\t\t\tjqXHR.done(function( r ) {\n\t\t\t\t\t\tresponseText = r;\n\t\t\t\t\t});\n\t\t\t\t\t// See if a selector was specified\n\t\t\t\t\tself.html( selector ?\n\t\t\t\t\t\t// Create a dummy div to hold the results\n\t\t\t\t\t\tjQuery(\"<div>\")\n\t\t\t\t\t\t\t// inject the contents of the document in, removing the scripts\n\t\t\t\t\t\t\t// to avoid any 'Permission Denied' errors in IE\n\t\t\t\t\t\t\t.append(responseText.replace(rscript, \"\"))\n\n\t\t\t\t\t\t\t// Locate the specified elements\n\t\t\t\t\t\t\t.find(selector) :\n\n\t\t\t\t\t\t// If not, just inject the full result\n\t\t\t\t\t\tresponseText );\n\t\t\t\t}\n\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tself.each( callback, [ responseText, status, jqXHR ] );\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn this;\n\t},\n\n\tserialize: function() {\n\t\treturn jQuery.param( this.serializeArray() );\n\t},\n\n\tserializeArray: function() {\n\t\treturn this.map(function(){\n\t\t\treturn this.elements ? jQuery.makeArray( this.elements ) : this;\n\t\t})\n\t\t.filter(function(){\n\t\t\treturn this.name && !this.disabled &&\n\t\t\t\t( this.checked || rselectTextarea.test( this.nodeName ) ||\n\t\t\t\t\trinput.test( this.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, i ){\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// Attach a bunch of functions for handling util AJAX events\njQuery.each( \"ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend\".split( \" \" ), function( i, o ){\n\tjQuery.fn[ o ] = function( f ){\n\t\treturn this.on( o, f );\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\ttype: method,\n\t\t\turl: url,\n\t\t\tdata: data,\n\t\t\tsuccess: callback,\n\t\t\tdataType: type\n\t\t});\n\t};\n});\n\njQuery.extend({\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\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\tif ( settings ) {\n\t\t\t// Building a settings object\n\t\t\tajaxExtend( target, jQuery.ajaxSettings );\n\t\t} else {\n\t\t\t// Extending ajaxSettings\n\t\t\tsettings = target;\n\t\t\ttarget = jQuery.ajaxSettings;\n\t\t}\n\t\tajaxExtend( target, settings );\n\t\treturn target;\n\t},\n\n\tajaxSettings: {\n\t\turl: ajaxLocation,\n\t\tisLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),\n\t\tglobal: true,\n\t\ttype: \"GET\",\n\t\tcontentType: \"application/x-www-form-urlencoded\",\n\t\tprocessData: true,\n\t\tasync: true,\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\ttraditional: false,\n\t\theaders: {},\n\t\t*/\n\n\t\taccepts: {\n\t\t\txml: \"application/xml, text/xml\",\n\t\t\thtml: \"text/html\",\n\t\t\ttext: \"text/plain\",\n\t\t\tjson: \"application/json, text/javascript\",\n\t\t\t\"*\": allTypes\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// List of data converters\n\t\t// 1) key format is \"source_type destination_type\" (a single space in-between)\n\t\t// 2) the catchall symbol \"*\" can be used for source_type\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\tcontext: true,\n\t\t\turl: true\n\t\t}\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 // 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\n\t\t\t// It's the callbackContext if one was provided in the options\n\t\t\t// and if it's a DOM node or a jQuery collection\n\t\t\tglobalEventContext = callbackContext !== s &&\n\t\t\t\t( callbackContext.nodeType || callbackContext instanceof jQuery ) ?\n\t\t\t\t\t\tjQuery( callbackContext ) : jQuery.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// ifModified key\n\t\t\tifModifiedKey,\n\t\t\t// Headers (they are sent all at once)\n\t\t\trequestHeaders = {},\n\t\t\trequestHeadersNames = {},\n\t\t\t// Response headers\n\t\t\tresponseHeadersString,\n\t\t\tresponseHeaders,\n\t\t\t// transport\n\t\t\ttransport,\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// The jqXHR state\n\t\t\tstate = 0,\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// Fake xhr\n\t\t\tjqXHR = {\n\n\t\t\t\treadyState: 0,\n\n\t\t\t\t// Caches the header\n\t\t\t\tsetRequestHeader: function( name, value ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\tvar lname = name.toLowerCase();\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// 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// 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 === undefined ? null : match;\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// Cancel the request\n\t\t\t\tabort: function( statusText ) {\n\t\t\t\t\tstatusText = statusText || \"abort\";\n\t\t\t\t\tif ( transport ) {\n\t\t\t\t\t\ttransport.abort( statusText );\n\t\t\t\t\t}\n\t\t\t\t\tdone( 0, statusText );\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Callback for when everything is done\n\t\t// It is defined here because jslint complains if it is declared\n\t\t// at the end of the function (which would be more logical and readable)\n\t\tfunction done( status, nativeStatusText, responses, headers ) {\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\tvar isSuccess,\n\t\t\t\tsuccess,\n\t\t\t\terror,\n\t\t\t\tstatusText = nativeStatusText,\n\t\t\t\tresponse = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined,\n\t\t\t\tlastModified,\n\t\t\t\tetag;\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\n\t\t\t\t\tif ( ( lastModified = jqXHR.getResponseHeader( \"Last-Modified\" ) ) ) {\n\t\t\t\t\t\tjQuery.lastModified[ ifModifiedKey ] = lastModified;\n\t\t\t\t\t}\n\t\t\t\t\tif ( ( etag = jqXHR.getResponseHeader( \"Etag\" ) ) ) {\n\t\t\t\t\t\tjQuery.etag[ ifModifiedKey ] = etag;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// If not modified\n\t\t\t\tif ( status === 304 ) {\n\n\t\t\t\t\tstatusText = \"notmodified\";\n\t\t\t\t\tisSuccess = true;\n\n\t\t\t\t// If we have data\n\t\t\t\t} else {\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tsuccess = ajaxConvert( s, response );\n\t\t\t\t\t\tstatusText = \"success\";\n\t\t\t\t\t\tisSuccess = true;\n\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\t// We have a parsererror\n\t\t\t\t\t\tstatusText = \"parsererror\";\n\t\t\t\t\t\terror = e;\n\t\t\t\t\t}\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 ( !statusText || status ) {\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( \"ajax\" + ( isSuccess ? \"Success\" : \"Error\" ),\n\t\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\t// Attach deferreds\n\t\tdeferred.promise( jqXHR );\n\t\tjqXHR.success = jqXHR.done;\n\t\tjqXHR.error = jqXHR.fail;\n\t\tjqXHR.complete = completeDeferred.add;\n\n\t\t// Status-dependent callbacks\n\t\tjqXHR.statusCode = function( map ) {\n\t\t\tif ( map ) {\n\t\t\t\tvar tmp;\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tfor ( tmp in map ) {\n\t\t\t\t\t\tstatusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttmp = map[ jqXHR.status ];\n\t\t\t\t\tjqXHR.then( tmp, tmp );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn this;\n\t\t};\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// We also use the url parameter if available\n\t\ts.url = ( ( url || s.url ) + \"\" ).replace( rhash, \"\" ).replace( rprotocol, ajaxLocParts[ 1 ] + \"//\" );\n\n\t\t// Extract dataTypes list\n\t\ts.dataTypes = jQuery.trim( s.dataType || \"*\" ).toLowerCase().split( rspacesAjax );\n\n\t\t// Determine if a cross-domain request is in order\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 prefiler, stop there\n\t\tif ( state === 2 ) {\n\t\t\treturn false;\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// 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// 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// 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\ts.url += ( rquery.test( s.url ) ? \"&\" : \"?\" ) + 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// Get ifModifiedKey before adding the anti-cache parameter\n\t\t\tifModifiedKey = s.url;\n\n\t\t\t// Add anti-cache in url if needed\n\t\t\tif ( s.cache === false ) {\n\n\t\t\t\tvar ts = jQuery.now(),\n\t\t\t\t\t// try replacing _= if it is there\n\t\t\t\t\tret = s.url.replace( rts, \"$1_=\" + ts );\n\n\t\t\t\t// if nothing was replaced, add timestamp to the end\n\t\t\t\ts.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? \"&\" : \"?\" ) + \"_=\" + ts : \"\" );\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 If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\tif ( s.ifModified ) {\n\t\t\tifModifiedKey = ifModifiedKey || s.url;\n\t\t\tif ( jQuery.lastModified[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ ifModifiedKey ] );\n\t\t\t}\n\t\t\tif ( jQuery.etag[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ ifModifiedKey ] );\n\t\t\t}\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\t// Abort if not done already\n\t\t\t\tjqXHR.abort();\n\t\t\t\treturn false;\n\n\t\t}\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\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\treturn jqXHR;\n\t},\n\n\t// Serialize an array of form elements or a set of\n\t// key/values into a query string\n\tparam: function( a, traditional ) {\n\t\tvar s = [],\n\t\t\tadd = function( key, value ) {\n\t\t\t\t// If value is a function, invoke it and return its value\n\t\t\t\tvalue = jQuery.isFunction( value ) ? value() : value;\n\t\t\t\ts[ s.length ] = encodeURIComponent( key ) + \"=\" + encodeURIComponent( value );\n\t\t\t};\n\n\t\t// Set traditional to true for jQuery <= 1.3.2 behavior.\n\t\tif ( traditional === undefined ) {\n\t\t\ttraditional = jQuery.ajaxSettings.traditional;\n\t\t}\n\n\t\t// If an array was passed in, assume that it is an array of form elements.\n\t\tif ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n\t\t\t// Serialize the form elements\n\t\t\tjQuery.each( a, function() {\n\t\t\t\tadd( this.name, this.value );\n\t\t\t});\n\n\t\t} else {\n\t\t\t// If traditional, encode the \"old\" way (the way 1.3.2 or older\n\t\t\t// did it), otherwise encode params recursively.\n\t\t\tfor ( var prefix in a ) {\n\t\t\t\tbuildParams( prefix, a[ prefix ], traditional, add );\n\t\t\t}\n\t\t}\n\n\t\t// Return the resulting serialization\n\t\treturn s.join( \"&\" ).replace( r20, \"+\" );\n\t}\n});\n\nfunction buildParams( prefix, obj, traditional, add ) {\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// If array item is non-scalar (array or object), encode its\n\t\t\t\t// numeric index to resolve deserialization ambiguity issues.\n\t\t\t\t// Note that rack (as of 1.0.0) can't currently deserialize\n\t\t\t\t// nested arrays properly, and attempting to do so may cause\n\t\t\t\t// a server error. Possible fixes are to modify rack's\n\t\t\t\t// deserialization algorithm or to provide an option or flag\n\t\t\t\t// to force array serialization to be shallow.\n\t\t\t\tbuildParams( prefix + \"[\" + ( typeof v === \"object\" || jQuery.isArray(v) ? i : \"\" ) + \"]\", v, traditional, add );\n\t\t\t}\n\t\t});\n\n\t} else if ( !traditional && obj != null && typeof obj === \"object\" ) {\n\t\t// Serialize object item.\n\t\tfor ( var 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// This is still on the jQuery object... for now\n// Want to move this to jQuery.ajax some day\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});\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\n\tvar contents = s.contents,\n\t\tdataTypes = s.dataTypes,\n\t\tresponseFields = s.responseFields,\n\t\tct,\n\t\ttype,\n\t\tfinalDataType,\n\t\tfirstDataType;\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\n\t// Apply the dataFilter if provided\n\tif ( s.dataFilter ) {\n\t\tresponse = s.dataFilter( response, s.dataType );\n\t}\n\n\tvar dataTypes = s.dataTypes,\n\t\tconverters = {},\n\t\ti,\n\t\tkey,\n\t\tlength = dataTypes.length,\n\t\ttmp,\n\t\t// Current and previous dataTypes\n\t\tcurrent = dataTypes[ 0 ],\n\t\tprev,\n\t\t// Conversion expression\n\t\tconversion,\n\t\t// Conversion function\n\t\tconv,\n\t\t// Conversion functions (transitive conversion)\n\t\tconv1,\n\t\tconv2;\n\n\t// For each dataType in the chain\n\tfor ( i = 1; i < length; i++ ) {\n\n\t\t// Create converters map\n\t\t// with lowercased keys\n\t\tif ( i === 1 ) {\n\t\t\tfor ( key in s.converters ) {\n\t\t\t\tif ( typeof key === \"string\" ) {\n\t\t\t\t\tconverters[ key.toLowerCase() ] = s.converters[ key ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Get the dataTypes\n\t\tprev = current;\n\t\tcurrent = dataTypes[ i ];\n\n\t\t// If current is auto dataType, update it to prev\n\t\tif ( current === \"*\" ) {\n\t\t\tcurrent = prev;\n\t\t// If no auto and dataTypes are actually different\n\t\t} else if ( prev !== \"*\" && prev !== current ) {\n\n\t\t\t// Get the converter\n\t\t\tconversion = prev + \" \" + current;\n\t\t\tconv = converters[ conversion ] || converters[ \"* \" + current ];\n\n\t\t\t// If there is no direct converter, search transitively\n\t\t\tif ( !conv ) {\n\t\t\t\tconv2 = undefined;\n\t\t\t\tfor ( conv1 in converters ) {\n\t\t\t\t\ttmp = conv1.split( \" \" );\n\t\t\t\t\tif ( tmp[ 0 ] === prev || tmp[ 0 ] === \"*\" ) {\n\t\t\t\t\t\tconv2 = converters[ tmp[1] + \" \" + current ];\n\t\t\t\t\t\tif ( conv2 ) {\n\t\t\t\t\t\t\tconv1 = converters[ conv1 ];\n\t\t\t\t\t\t\tif ( conv1 === true ) {\n\t\t\t\t\t\t\t\tconv = conv2;\n\t\t\t\t\t\t\t} else if ( conv2 === true ) {\n\t\t\t\t\t\t\t\tconv = conv1;\n\t\t\t\t\t\t\t}\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}\n\t\t\t// If we found no converter, dispatch an error\n\t\t\tif ( !( conv || conv2 ) ) {\n\t\t\t\tjQuery.error( \"No conversion from \" + conversion.replace(\" \",\" to \") );\n\t\t\t}\n\t\t\t// If found converter is not an equivalence\n\t\t\tif ( conv !== true ) {\n\t\t\t\t// Convert with 1 or 2 converters accordingly\n\t\t\t\tresponse = conv ? conv( response ) : conv2( conv1(response) );\n\t\t\t}\n\t\t}\n\t}\n\treturn response;\n}\n\n\n\n\nvar jsc = jQuery.now(),\n\tjsre = /(\\=)\\?(&|$)|\\?\\?/i;\n\n// Default jsonp settings\njQuery.ajaxSetup({\n\tjsonp: \"callback\",\n\tjsonpCallback: function() {\n\t\treturn jQuery.expando + \"_\" + ( jsc++ );\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 inspectData = s.contentType === \"application/x-www-form-urlencoded\" &&\n\t\t( typeof s.data === \"string\" );\n\n\tif ( s.dataTypes[ 0 ] === \"jsonp\" ||\n\t\ts.jsonp !== false && ( jsre.test( s.url ) ||\n\t\t\t\tinspectData && jsre.test( s.data ) ) ) {\n\n\t\tvar responseContainer,\n\t\t\tjsonpCallback = s.jsonpCallback =\n\t\t\t\tjQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,\n\t\t\tprevious = window[ jsonpCallback ],\n\t\t\turl = s.url,\n\t\t\tdata = s.data,\n\t\t\treplace = \"$1\" + jsonpCallback + \"$2\";\n\n\t\tif ( s.jsonp !== false ) {\n\t\t\turl = url.replace( jsre, replace );\n\t\t\tif ( s.url === url ) {\n\t\t\t\tif ( inspectData ) {\n\t\t\t\t\tdata = data.replace( jsre, replace );\n\t\t\t\t}\n\t\t\t\tif ( s.data === data ) {\n\t\t\t\t\t// Add callback manually\n\t\t\t\t\turl += (/\\?/.test( url ) ? \"&\" : \"?\") + s.jsonp + \"=\" + jsonpCallback;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ts.url = url;\n\t\ts.data = data;\n\n\t\t// Install callback\n\t\twindow[ jsonpCallback ] = function( response ) {\n\t\t\tresponseContainer = [ response ];\n\t\t};\n\n\t\t// Clean-up function\n\t\tjqXHR.always(function() {\n\t\t\t// Set callback back to previous value\n\t\t\twindow[ jsonpCallback ] = previous;\n\t\t\t// Call if it was a function and we have a response\n\t\t\tif ( responseContainer && jQuery.isFunction( previous ) ) {\n\t\t\t\twindow[ jsonpCallback ]( responseContainer[ 0 ] );\n\t\t\t}\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( jsonpCallback + \" 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// Delegate to script\n\t\treturn \"script\";\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: /javascript|ecmascript/\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 || document.getElementsByTagName( \"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 = \"async\";\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 ( head && script.parentNode ) {\n\t\t\t\t\t\t\thead.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 = undefined;\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\t\t\t\t// Use insertBefore instead of appendChild  to circumvent an IE6 bug.\n\t\t\t\t// This arises when a base node is used (#2709 and #4378).\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( 0, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n});\n\n\n\n\nvar // #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\tfor ( var key in xhrCallbacks ) {\n\t\t\txhrCallbacks[ key ]( 0, 1 );\n\t\t}\n\t} : false,\n\txhrId = 0,\n\txhrCallbacks;\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\n(function( xhr ) {\n\tjQuery.extend( jQuery.support, {\n\t\tajax: !!xhr,\n\t\tcors: !!xhr && ( \"withCredentials\" in xhr )\n\t});\n})( jQuery.ajaxSettings.xhr() );\n\n// Create transport if the browser can provide an xhr\nif ( jQuery.support.ajax ) {\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 xhr = s.xhr(),\n\t\t\t\t\t\thandle,\n\t\t\t\t\t\ti;\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( _ ) {}\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\n\t\t\t\t\t\tvar status,\n\t\t\t\t\t\t\tstatusText,\n\t\t\t\t\t\t\tresponseHeaders,\n\t\t\t\t\t\t\tresponses,\n\t\t\t\t\t\t\txml;\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 occured\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\tstatus = xhr.status;\n\t\t\t\t\t\t\t\t\tresponseHeaders = xhr.getAllResponseHeaders();\n\t\t\t\t\t\t\t\t\tresponses = {};\n\t\t\t\t\t\t\t\t\txml = xhr.responseXML;\n\n\t\t\t\t\t\t\t\t\t// Construct response list\n\t\t\t\t\t\t\t\t\tif ( xml && xml.documentElement /* #4958 */ ) {\n\t\t\t\t\t\t\t\t\t\tresponses.xml = xml;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tresponses.text = xhr.responseText;\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\t// if we're in sync mode or it's in cache\n\t\t\t\t\t// and has been retrieved directly (IE6 & IE7)\n\t\t\t\t\t// we need to manually fire the callback\n\t\t\t\t\tif ( !s.async || xhr.readyState === 4 ) {\n\t\t\t\t\t\tcallback();\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(0,1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t});\n}\n\n\n\n\nvar elemdisplay = {},\n\tiframe, iframeDoc,\n\trfxtypes = /^(?:toggle|show|hide)$/,\n\trfxnum = /^([+\\-]=)?([\\d+.\\-]+)([a-z%]*)$/i,\n\ttimerId,\n\tfxAttrs = [\n\t\t// height animations\n\t\t[ \"height\", \"marginTop\", \"marginBottom\", \"paddingTop\", \"paddingBottom\" ],\n\t\t// width animations\n\t\t[ \"width\", \"marginLeft\", \"marginRight\", \"paddingLeft\", \"paddingRight\" ],\n\t\t// opacity animations\n\t\t[ \"opacity\" ]\n\t],\n\tfxNow;\n\njQuery.fn.extend({\n\tshow: function( speed, easing, callback ) {\n\t\tvar elem, display;\n\n\t\tif ( speed || speed === 0 ) {\n\t\t\treturn this.animate( genFx(\"show\", 3), speed, easing, callback );\n\n\t\t} else {\n\t\t\tfor ( var i = 0, j = this.length; i < j; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = elem.style.display;\n\n\t\t\t\t\t// Reset the inline display of this element to learn if it is\n\t\t\t\t\t// being hidden by cascaded rules or not\n\t\t\t\t\tif ( !jQuery._data(elem, \"olddisplay\") && display === \"none\" ) {\n\t\t\t\t\t\tdisplay = elem.style.display = \"\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Set elements which have been overridden with display: none\n\t\t\t\t\t// in a stylesheet to whatever the default browser style is\n\t\t\t\t\t// for such an element\n\t\t\t\t\tif ( display === \"\" && jQuery.css(elem, \"display\") === \"none\" ) {\n\t\t\t\t\t\tjQuery._data( elem, \"olddisplay\", defaultDisplay(elem.nodeName) );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the display of most of the elements in a second loop\n\t\t\t// to avoid the constant reflow\n\t\t\tfor ( i = 0; i < j; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = elem.style.display;\n\n\t\t\t\t\tif ( display === \"\" || display === \"none\" ) {\n\t\t\t\t\t\telem.style.display = jQuery._data( elem, \"olddisplay\" ) || \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t},\n\n\thide: function( speed, easing, callback ) {\n\t\tif ( speed || speed === 0 ) {\n\t\t\treturn this.animate( genFx(\"hide\", 3), speed, easing, callback);\n\n\t\t} else {\n\t\t\tvar elem, display,\n\t\t\t\ti = 0,\n\t\t\t\tj = this.length;\n\n\t\t\tfor ( ; i < j; i++ ) {\n\t\t\t\telem = this[i];\n\t\t\t\tif ( elem.style ) {\n\t\t\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\n\t\t\t\t\tif ( display !== \"none\" && !jQuery._data( elem, \"olddisplay\" ) ) {\n\t\t\t\t\t\tjQuery._data( elem, \"olddisplay\", display );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the display of the elements in a second loop\n\t\t\t// to avoid the constant reflow\n\t\t\tfor ( i = 0; i < j; i++ ) {\n\t\t\t\tif ( this[i].style ) {\n\t\t\t\t\tthis[i].style.display = \"none\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\t},\n\n\t// Save the old toggle function\n\t_toggle: jQuery.fn.toggle,\n\n\ttoggle: function( fn, fn2, callback ) {\n\t\tvar bool = typeof fn === \"boolean\";\n\n\t\tif ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {\n\t\t\tthis._toggle.apply( this, arguments );\n\n\t\t} else if ( fn == null || bool ) {\n\t\t\tthis.each(function() {\n\t\t\t\tvar state = bool ? fn : jQuery(this).is(\":hidden\");\n\t\t\t\tjQuery(this)[ state ? \"show\" : \"hide\" ]();\n\t\t\t});\n\n\t\t} else {\n\t\t\tthis.animate(genFx(\"toggle\", 3), fn, fn2, callback);\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tfadeTo: function( speed, to, easing, callback ) {\n\t\treturn this.filter(\":hidden\").css(\"opacity\", 0).show().end()\n\t\t\t\t\t.animate({opacity: to}, speed, easing, callback);\n\t},\n\n\tanimate: function( prop, speed, easing, callback ) {\n\t\tvar optall = jQuery.speed( speed, easing, callback );\n\n\t\tif ( jQuery.isEmptyObject( prop ) ) {\n\t\t\treturn this.each( optall.complete, [ false ] );\n\t\t}\n\n\t\t// Do not change referenced properties as per-property easing will be lost\n\t\tprop = jQuery.extend( {}, prop );\n\n\t\tfunction doAnimation() {\n\t\t\t// XXX 'this' does not always have a nodeName when running the\n\t\t\t// test suite\n\n\t\t\tif ( optall.queue === false ) {\n\t\t\t\tjQuery._mark( this );\n\t\t\t}\n\n\t\t\tvar opt = jQuery.extend( {}, optall ),\n\t\t\t\tisElement = this.nodeType === 1,\n\t\t\t\thidden = isElement && jQuery(this).is(\":hidden\"),\n\t\t\t\tname, val, p, e,\n\t\t\t\tparts, start, end, unit,\n\t\t\t\tmethod;\n\n\t\t\t// will store per property easing and be used to determine when an animation is complete\n\t\t\topt.animatedProperties = {};\n\n\t\t\tfor ( p in prop ) {\n\n\t\t\t\t// property name normalization\n\t\t\t\tname = jQuery.camelCase( p );\n\t\t\t\tif ( p !== name ) {\n\t\t\t\t\tprop[ name ] = prop[ p ];\n\t\t\t\t\tdelete prop[ p ];\n\t\t\t\t}\n\n\t\t\t\tval = prop[ name ];\n\n\t\t\t\t// easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)\n\t\t\t\tif ( jQuery.isArray( val ) ) {\n\t\t\t\t\topt.animatedProperties[ name ] = val[ 1 ];\n\t\t\t\t\tval = prop[ name ] = val[ 0 ];\n\t\t\t\t} else {\n\t\t\t\t\topt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';\n\t\t\t\t}\n\n\t\t\t\tif ( val === \"hide\" && hidden || val === \"show\" && !hidden ) {\n\t\t\t\t\treturn opt.complete.call( this );\n\t\t\t\t}\n\n\t\t\t\tif ( isElement && ( name === \"height\" || name === \"width\" ) ) {\n\t\t\t\t\t// Make sure that nothing sneaks out\n\t\t\t\t\t// Record all 3 overflow attributes because IE does not\n\t\t\t\t\t// change the overflow attribute when overflowX and\n\t\t\t\t\t// overflowY are set to the same value\n\t\t\t\t\topt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];\n\n\t\t\t\t\t// Set display property to inline-block for height/width\n\t\t\t\t\t// animations on inline elements that are having width/height animated\n\t\t\t\t\tif ( jQuery.css( this, \"display\" ) === \"inline\" &&\n\t\t\t\t\t\t\tjQuery.css( this, \"float\" ) === \"none\" ) {\n\n\t\t\t\t\t\t// inline-level elements accept inline-block;\n\t\t\t\t\t\t// block-level elements need to be inline with layout\n\t\t\t\t\t\tif ( !jQuery.support.inlineBlockNeedsLayout || defaultDisplay( this.nodeName ) === \"inline\" ) {\n\t\t\t\t\t\t\tthis.style.display = \"inline-block\";\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.style.zoom = 1;\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\tif ( opt.overflow != null ) {\n\t\t\t\tthis.style.overflow = \"hidden\";\n\t\t\t}\n\n\t\t\tfor ( p in prop ) {\n\t\t\t\te = new jQuery.fx( this, opt, p );\n\t\t\t\tval = prop[ p ];\n\n\t\t\t\tif ( rfxtypes.test( val ) ) {\n\n\t\t\t\t\t// Tracks whether to show or hide based on private\n\t\t\t\t\t// data attached to the element\n\t\t\t\t\tmethod = jQuery._data( this, \"toggle\" + p ) || ( val === \"toggle\" ? hidden ? \"show\" : \"hide\" : 0 );\n\t\t\t\t\tif ( method ) {\n\t\t\t\t\t\tjQuery._data( this, \"toggle\" + p, method === \"show\" ? \"hide\" : \"show\" );\n\t\t\t\t\t\te[ method ]();\n\t\t\t\t\t} else {\n\t\t\t\t\t\te[ val ]();\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tparts = rfxnum.exec( val );\n\t\t\t\t\tstart = e.cur();\n\n\t\t\t\t\tif ( parts ) {\n\t\t\t\t\t\tend = parseFloat( parts[2] );\n\t\t\t\t\t\tunit = parts[3] || ( jQuery.cssNumber[ p ] ? \"\" : \"px\" );\n\n\t\t\t\t\t\t// We need to compute starting value\n\t\t\t\t\t\tif ( unit !== \"px\" ) {\n\t\t\t\t\t\t\tjQuery.style( this, p, (end || 1) + unit);\n\t\t\t\t\t\t\tstart = ( (end || 1) / e.cur() ) * start;\n\t\t\t\t\t\t\tjQuery.style( this, p, start + unit);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// If a +=/-= token was provided, we're doing a relative animation\n\t\t\t\t\t\tif ( parts[1] ) {\n\t\t\t\t\t\t\tend = ( (parts[ 1 ] === \"-=\" ? -1 : 1) * end ) + start;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\te.custom( start, end, unit );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\te.custom( start, val, \"\" );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// For JS strict compliance\n\t\t\treturn true;\n\t\t}\n\n\t\treturn optall.queue === false ?\n\t\t\tthis.each( doAnimation ) :\n\t\t\tthis.queue( optall.queue, doAnimation );\n\t},\n\n\tstop: function( type, clearQueue, gotoEnd ) {\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 index,\n\t\t\t\thadTimers = false,\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tdata = jQuery._data( this );\n\n\t\t\t// clear marker counters if we know they won't be\n\t\t\tif ( !gotoEnd ) {\n\t\t\t\tjQuery._unmark( true, this );\n\t\t\t}\n\n\t\t\tfunction stopQueue( elem, data, index ) {\n\t\t\t\tvar hooks = data[ index ];\n\t\t\t\tjQuery.removeData( elem, index, true );\n\t\t\t\thooks.stop( gotoEnd );\n\t\t\t}\n\n\t\t\tif ( type == null ) {\n\t\t\t\tfor ( index in data ) {\n\t\t\t\t\tif ( data[ index ] && data[ index ].stop && index.indexOf(\".run\") === index.length - 4 ) {\n\t\t\t\t\t\tstopQueue( this, data, index );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if ( data[ index = type + \".run\" ] && data[ index ].stop ){\n\t\t\t\tstopQueue( this, data, index );\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\tif ( gotoEnd ) {\n\n\t\t\t\t\t\t// force the next step to be the last\n\t\t\t\t\t\ttimers[ index ]( true );\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttimers[ index ].saveState();\n\t\t\t\t\t}\n\t\t\t\t\thadTimers = true;\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 ( !( gotoEnd && hadTimers ) ) {\n\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t}\n\t\t});\n\t}\n\n});\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n\tsetTimeout( clearFxNow, 0 );\n\treturn ( fxNow = jQuery.now() );\n}\n\nfunction clearFxNow() {\n\tfxNow = undefined;\n}\n\n// Generate parameters to create a standard animation\nfunction genFx( type, num ) {\n\tvar obj = {};\n\n\tjQuery.each( fxAttrs.concat.apply([], fxAttrs.slice( 0, num )), function() {\n\t\tobj[ this ] = type;\n\t});\n\n\treturn obj;\n}\n\n// Generate shortcuts for custom animations\njQuery.each({\n\tslideDown: genFx( \"show\", 1 ),\n\tslideUp: genFx( \"hide\", 1 ),\n\tslideToggle: genFx( \"toggle\", 1 ),\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.extend({\n\tspeed: function( speed, easing, fn ) {\n\t\tvar opt = speed && typeof speed === \"object\" ? jQuery.extend( {}, speed ) : {\n\t\t\tcomplete: fn || !fn && easing ||\n\t\t\t\tjQuery.isFunction( speed ) && speed,\n\t\t\tduration: speed,\n\t\t\teasing: fn && easing || easing && !jQuery.isFunction( easing ) && easing\n\t\t};\n\n\t\topt.duration = jQuery.fx.off ? 0 : typeof opt.duration === \"number\" ? opt.duration :\n\t\t\topt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;\n\n\t\t// normalize opt.queue - true/undefined/null -> \"fx\"\n\t\tif ( opt.queue == null || opt.queue === true ) {\n\t\t\topt.queue = \"fx\";\n\t\t}\n\n\t\t// Queueing\n\t\topt.old = opt.complete;\n\n\t\topt.complete = function( noUnmark ) {\n\t\t\tif ( jQuery.isFunction( opt.old ) ) {\n\t\t\t\topt.old.call( this );\n\t\t\t}\n\n\t\t\tif ( opt.queue ) {\n\t\t\t\tjQuery.dequeue( this, opt.queue );\n\t\t\t} else if ( noUnmark !== false ) {\n\t\t\t\tjQuery._unmark( this );\n\t\t\t}\n\t\t};\n\n\t\treturn opt;\n\t},\n\n\teasing: {\n\t\tlinear: function( p, n, firstNum, diff ) {\n\t\t\treturn firstNum + diff * p;\n\t\t},\n\t\tswing: function( p, n, firstNum, diff ) {\n\t\t\treturn ( ( -Math.cos( p*Math.PI ) / 2 ) + 0.5 ) * diff + firstNum;\n\t\t}\n\t},\n\n\ttimers: [],\n\n\tfx: function( elem, options, prop ) {\n\t\tthis.options = options;\n\t\tthis.elem = elem;\n\t\tthis.prop = prop;\n\n\t\toptions.orig = options.orig || {};\n\t}\n\n});\n\njQuery.fx.prototype = {\n\t// Simple function for setting a style value\n\tupdate: function() {\n\t\tif ( this.options.step ) {\n\t\t\tthis.options.step.call( this.elem, this.now, this );\n\t\t}\n\n\t\t( jQuery.fx.step[ this.prop ] || jQuery.fx.step._default )( this );\n\t},\n\n\t// Get the current size\n\tcur: function() {\n\t\tif ( this.elem[ this.prop ] != null && (!this.elem.style || this.elem.style[ this.prop ] == null) ) {\n\t\t\treturn this.elem[ this.prop ];\n\t\t}\n\n\t\tvar parsed,\n\t\t\tr = jQuery.css( this.elem, this.prop );\n\t\t// Empty strings, null, undefined and \"auto\" are converted to 0,\n\t\t// complex values such as \"rotate(1rad)\" are returned as is,\n\t\t// simple values such as \"10px\" are parsed to Float.\n\t\treturn isNaN( parsed = parseFloat( r ) ) ? !r || r === \"auto\" ? 0 : r : parsed;\n\t},\n\n\t// Start an animation from one number to another\n\tcustom: function( from, to, unit ) {\n\t\tvar self = this,\n\t\t\tfx = jQuery.fx;\n\n\t\tthis.startTime = fxNow || createFxNow();\n\t\tthis.end = to;\n\t\tthis.now = this.start = from;\n\t\tthis.pos = this.state = 0;\n\t\tthis.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? \"\" : \"px\" );\n\n\t\tfunction t( gotoEnd ) {\n\t\t\treturn self.step( gotoEnd );\n\t\t}\n\n\t\tt.queue = this.options.queue;\n\t\tt.elem = this.elem;\n\t\tt.saveState = function() {\n\t\t\tif ( self.options.hide && jQuery._data( self.elem, \"fxshow\" + self.prop ) === undefined ) {\n\t\t\t\tjQuery._data( self.elem, \"fxshow\" + self.prop, self.start );\n\t\t\t}\n\t\t};\n\n\t\tif ( t() && jQuery.timers.push(t) && !timerId ) {\n\t\t\ttimerId = setInterval( fx.tick, fx.interval );\n\t\t}\n\t},\n\n\t// Simple 'show' function\n\tshow: function() {\n\t\tvar dataShow = jQuery._data( this.elem, \"fxshow\" + this.prop );\n\n\t\t// Remember where we started, so that we can go back to it later\n\t\tthis.options.orig[ this.prop ] = dataShow || jQuery.style( this.elem, this.prop );\n\t\tthis.options.show = true;\n\n\t\t// Begin the animation\n\t\t// Make sure that we start at a small width/height to avoid any flash of content\n\t\tif ( dataShow !== undefined ) {\n\t\t\t// This show is picking up where a previous hide or show left off\n\t\t\tthis.custom( this.cur(), dataShow );\n\t\t} else {\n\t\t\tthis.custom( this.prop === \"width\" || this.prop === \"height\" ? 1 : 0, this.cur() );\n\t\t}\n\n\t\t// Start by showing the element\n\t\tjQuery( this.elem ).show();\n\t},\n\n\t// Simple 'hide' function\n\thide: function() {\n\t\t// Remember where we started, so that we can go back to it later\n\t\tthis.options.orig[ this.prop ] = jQuery._data( this.elem, \"fxshow\" + this.prop ) || jQuery.style( this.elem, this.prop );\n\t\tthis.options.hide = true;\n\n\t\t// Begin the animation\n\t\tthis.custom( this.cur(), 0 );\n\t},\n\n\t// Each step of an animation\n\tstep: function( gotoEnd ) {\n\t\tvar p, n, complete,\n\t\t\tt = fxNow || createFxNow(),\n\t\t\tdone = true,\n\t\t\telem = this.elem,\n\t\t\toptions = this.options;\n\n\t\tif ( gotoEnd || t >= options.duration + this.startTime ) {\n\t\t\tthis.now = this.end;\n\t\t\tthis.pos = this.state = 1;\n\t\t\tthis.update();\n\n\t\t\toptions.animatedProperties[ this.prop ] = true;\n\n\t\t\tfor ( p in options.animatedProperties ) {\n\t\t\t\tif ( options.animatedProperties[ p ] !== true ) {\n\t\t\t\t\tdone = false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( done ) {\n\t\t\t\t// Reset the overflow\n\t\t\t\tif ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {\n\n\t\t\t\t\tjQuery.each( [ \"\", \"X\", \"Y\" ], function( index, value ) {\n\t\t\t\t\t\telem.style[ \"overflow\" + value ] = options.overflow[ index ];\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Hide the element if the \"hide\" operation was done\n\t\t\t\tif ( options.hide ) {\n\t\t\t\t\tjQuery( elem ).hide();\n\t\t\t\t}\n\n\t\t\t\t// Reset the properties, if the item has been hidden or shown\n\t\t\t\tif ( options.hide || options.show ) {\n\t\t\t\t\tfor ( p in options.animatedProperties ) {\n\t\t\t\t\t\tjQuery.style( elem, p, options.orig[ p ] );\n\t\t\t\t\t\tjQuery.removeData( elem, \"fxshow\" + p, true );\n\t\t\t\t\t\t// Toggle data is no longer needed\n\t\t\t\t\t\tjQuery.removeData( elem, \"toggle\" + p, true );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Execute the complete function\n\t\t\t\t// in the event that the complete function throws an exception\n\t\t\t\t// we must ensure it won't be called twice. #5684\n\n\t\t\t\tcomplete = options.complete;\n\t\t\t\tif ( complete ) {\n\n\t\t\t\t\toptions.complete = false;\n\t\t\t\t\tcomplete.call( elem );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t} else {\n\t\t\t// classical easing cannot be used with an Infinity duration\n\t\t\tif ( options.duration == Infinity ) {\n\t\t\t\tthis.now = t;\n\t\t\t} else {\n\t\t\t\tn = t - this.startTime;\n\t\t\t\tthis.state = n / options.duration;\n\n\t\t\t\t// Perform the easing function, defaults to swing\n\t\t\t\tthis.pos = jQuery.easing[ options.animatedProperties[this.prop] ]( this.state, n, 0, 1, options.duration );\n\t\t\t\tthis.now = this.start + ( (this.end - this.start) * this.pos );\n\t\t\t}\n\t\t\t// Perform the next step of the animation\n\t\t\tthis.update();\n\t\t}\n\n\t\treturn true;\n\t}\n};\n\njQuery.extend( jQuery.fx, {\n\ttick: function() {\n\t\tvar timer,\n\t\t\ttimers = jQuery.timers,\n\t\t\ti = 0;\n\n\t\tfor ( ; i < timers.length; i++ ) {\n\t\t\ttimer = timers[ i ];\n\t\t\t// Checks the timer has not already been removed\n\t\t\tif ( !timer() && timers[ i ] === timer ) {\n\t\t\t\ttimers.splice( i--, 1 );\n\t\t\t}\n\t\t}\n\n\t\tif ( !timers.length ) {\n\t\t\tjQuery.fx.stop();\n\t\t}\n\t},\n\n\tinterval: 13,\n\n\tstop: function() {\n\t\tclearInterval( timerId );\n\t\ttimerId = null;\n\t},\n\n\tspeeds: {\n\t\tslow: 600,\n\t\tfast: 200,\n\t\t// Default speed\n\t\t_default: 400\n\t},\n\n\tstep: {\n\t\topacity: function( fx ) {\n\t\t\tjQuery.style( fx.elem, \"opacity\", fx.now );\n\t\t},\n\n\t\t_default: function( fx ) {\n\t\t\tif ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {\n\t\t\t\tfx.elem.style[ fx.prop ] = fx.now + fx.unit;\n\t\t\t} else {\n\t\t\t\tfx.elem[ fx.prop ] = fx.now;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Adds width/height step functions\n// Do not set anything below 0\njQuery.each([ \"width\", \"height\" ], function( i, prop ) {\n\tjQuery.fx.step[ prop ] = function( fx ) {\n\t\tjQuery.style( fx.elem, prop, Math.max(0, fx.now) + fx.unit );\n\t};\n});\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}\n\n// Try to restore the default display value of an element\nfunction defaultDisplay( nodeName ) {\n\n\tif ( !elemdisplay[ nodeName ] ) {\n\n\t\tvar body = document.body,\n\t\t\telem = jQuery( \"<\" + nodeName + \">\" ).appendTo( body ),\n\t\t\tdisplay = elem.css( \"display\" );\n\t\telem.remove();\n\n\t\t// If the simple way fails,\n\t\t// get element's real default display by attaching it to a temp iframe\n\t\tif ( display === \"none\" || display === \"\" ) {\n\t\t\t// No iframe to use yet, so create it\n\t\t\tif ( !iframe ) {\n\t\t\t\tiframe = document.createElement( \"iframe\" );\n\t\t\t\tiframe.frameBorder = iframe.width = iframe.height = 0;\n\t\t\t}\n\n\t\t\tbody.appendChild( iframe );\n\n\t\t\t// Create a cacheable copy of the iframe document on first call.\n\t\t\t// IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML\n\t\t\t// document to it; WebKit & Firefox won't allow reusing the iframe document.\n\t\t\tif ( !iframeDoc || !iframe.createElement ) {\n\t\t\t\tiframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;\n\t\t\t\tiframeDoc.write( ( document.compatMode === \"CSS1Compat\" ? \"<!doctype html>\" : \"\" ) + \"<html><body>\" );\n\t\t\t\tiframeDoc.close();\n\t\t\t}\n\n\t\t\telem = iframeDoc.createElement( nodeName );\n\n\t\t\tiframeDoc.body.appendChild( elem );\n\n\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\t\t\tbody.removeChild( iframe );\n\t\t}\n\n\t\t// Store the correct default display\n\t\telemdisplay[ nodeName ] = display;\n\t}\n\n\treturn elemdisplay[ nodeName ];\n}\n\n\n\n\nvar rtable = /^t(?:able|d|h)$/i,\n\trroot = /^(?:body|html)$/i;\n\nif ( \"getBoundingClientRect\" in document.documentElement ) {\n\tjQuery.fn.offset = function( options ) {\n\t\tvar elem = this[0], box;\n\n\t\tif ( options ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t});\n\t\t}\n\n\t\tif ( !elem || !elem.ownerDocument ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif ( elem === elem.ownerDocument.body ) {\n\t\t\treturn jQuery.offset.bodyOffset( elem );\n\t\t}\n\n\t\ttry {\n\t\t\tbox = elem.getBoundingClientRect();\n\t\t} catch(e) {}\n\n\t\tvar doc = elem.ownerDocument,\n\t\t\tdocElem = doc.documentElement;\n\n\t\t// Make sure we're not dealing with a disconnected DOM node\n\t\tif ( !box || !jQuery.contains( docElem, elem ) ) {\n\t\t\treturn box ? { top: box.top, left: box.left } : { top: 0, left: 0 };\n\t\t}\n\n\t\tvar body = doc.body,\n\t\t\twin = getWindow(doc),\n\t\t\tclientTop  = docElem.clientTop  || body.clientTop  || 0,\n\t\t\tclientLeft = docElem.clientLeft || body.clientLeft || 0,\n\t\t\tscrollTop  = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop,\n\t\t\tscrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,\n\t\t\ttop  = box.top  + scrollTop  - clientTop,\n\t\t\tleft = box.left + scrollLeft - clientLeft;\n\n\t\treturn { top: top, left: left };\n\t};\n\n} else {\n\tjQuery.fn.offset = function( options ) {\n\t\tvar elem = this[0];\n\n\t\tif ( options ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t});\n\t\t}\n\n\t\tif ( !elem || !elem.ownerDocument ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif ( elem === elem.ownerDocument.body ) {\n\t\t\treturn jQuery.offset.bodyOffset( elem );\n\t\t}\n\n\t\tvar computedStyle,\n\t\t\toffsetParent = elem.offsetParent,\n\t\t\tprevOffsetParent = elem,\n\t\t\tdoc = elem.ownerDocument,\n\t\t\tdocElem = doc.documentElement,\n\t\t\tbody = doc.body,\n\t\t\tdefaultView = doc.defaultView,\n\t\t\tprevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,\n\t\t\ttop = elem.offsetTop,\n\t\t\tleft = elem.offsetLeft;\n\n\t\twhile ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {\n\t\t\tif ( jQuery.support.fixedPosition && prevComputedStyle.position === \"fixed\" ) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcomputedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;\n\t\t\ttop  -= elem.scrollTop;\n\t\t\tleft -= elem.scrollLeft;\n\n\t\t\tif ( elem === offsetParent ) {\n\t\t\t\ttop  += elem.offsetTop;\n\t\t\t\tleft += elem.offsetLeft;\n\n\t\t\t\tif ( jQuery.support.doesNotAddBorder && !(jQuery.support.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {\n\t\t\t\t\ttop  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n\t\t\t\t\tleft += parseFloat( computedStyle.borderLeftWidth ) || 0;\n\t\t\t\t}\n\n\t\t\t\tprevOffsetParent = offsetParent;\n\t\t\t\toffsetParent = elem.offsetParent;\n\t\t\t}\n\n\t\t\tif ( jQuery.support.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== \"visible\" ) {\n\t\t\t\ttop  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n\t\t\t\tleft += parseFloat( computedStyle.borderLeftWidth ) || 0;\n\t\t\t}\n\n\t\t\tprevComputedStyle = computedStyle;\n\t\t}\n\n\t\tif ( prevComputedStyle.position === \"relative\" || prevComputedStyle.position === \"static\" ) {\n\t\t\ttop  += body.offsetTop;\n\t\t\tleft += body.offsetLeft;\n\t\t}\n\n\t\tif ( jQuery.support.fixedPosition && prevComputedStyle.position === \"fixed\" ) {\n\t\t\ttop  += Math.max( docElem.scrollTop, body.scrollTop );\n\t\t\tleft += Math.max( docElem.scrollLeft, body.scrollLeft );\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t};\n}\n\njQuery.offset = {\n\n\tbodyOffset: function( body ) {\n\t\tvar top = body.offsetTop,\n\t\t\tleft = body.offsetLeft;\n\n\t\tif ( jQuery.support.doesNotIncludeMarginInBodyOffset ) {\n\t\t\ttop  += parseFloat( jQuery.css(body, \"marginTop\") ) || 0;\n\t\t\tleft += parseFloat( jQuery.css(body, \"marginLeft\") ) || 0;\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t},\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 null;\n\t\t}\n\n\t\tvar elem = this[0],\n\n\t\t// Get *real* offsetParent\n\t\toffsetParent = this.offsetParent(),\n\n\t\t// Get correct offsets\n\t\toffset       = this.offset(),\n\t\tparentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();\n\n\t\t// Subtract 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\toffset.top  -= parseFloat( jQuery.css(elem, \"marginTop\") ) || 0;\n\t\toffset.left -= parseFloat( jQuery.css(elem, \"marginLeft\") ) || 0;\n\n\t\t// Add offsetParent borders\n\t\tparentOffset.top  += parseFloat( jQuery.css(offsetParent[0], \"borderTopWidth\") ) || 0;\n\t\tparentOffset.left += parseFloat( jQuery.css(offsetParent[0], \"borderLeftWidth\") ) || 0;\n\n\t\t// Subtract the two offsets\n\t\treturn {\n\t\t\ttop:  offset.top  - parentOffset.top,\n\t\t\tleft: offset.left - parentOffset.left\n\t\t};\n\t},\n\n\toffsetParent: function() {\n\t\treturn this.map(function() {\n\t\t\tvar offsetParent = this.offsetParent || document.body;\n\t\t\twhile ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, \"position\") === \"static\") ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\t\t\treturn offsetParent;\n\t\t});\n\t}\n});\n\n\n// Create scrollLeft and scrollTop methods\njQuery.each( [\"Left\", \"Top\"], function( i, name ) {\n\tvar method = \"scroll\" + name;\n\n\tjQuery.fn[ method ] = function( val ) {\n\t\tvar elem, win;\n\n\t\tif ( val === undefined ) {\n\t\t\telem = this[ 0 ];\n\n\t\t\tif ( !elem ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\twin = getWindow( elem );\n\n\t\t\t// Return the scroll offset\n\t\t\treturn win ? (\"pageXOffset\" in win) ? win[ i ? \"pageYOffset\" : \"pageXOffset\" ] :\n\t\t\t\tjQuery.support.boxModel && win.document.documentElement[ method ] ||\n\t\t\t\t\twin.document.body[ method ] :\n\t\t\t\telem[ method ];\n\t\t}\n\n\t\t// Set the scroll offset\n\t\treturn this.each(function() {\n\t\t\twin = getWindow( this );\n\n\t\t\tif ( win ) {\n\t\t\t\twin.scrollTo(\n\t\t\t\t\t!i ? val : jQuery( win ).scrollLeft(),\n\t\t\t\t\t i ? val : jQuery( win ).scrollTop()\n\t\t\t\t);\n\n\t\t\t} else {\n\t\t\t\tthis[ method ] = val;\n\t\t\t}\n\t\t});\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\n\n\n\n// Create width, height, innerHeight, innerWidth, outerHeight and outerWidth methods\njQuery.each([ \"Height\", \"Width\" ], function( i, name ) {\n\n\tvar type = name.toLowerCase();\n\n\t// innerHeight and innerWidth\n\tjQuery.fn[ \"inner\" + name ] = function() {\n\t\tvar elem = this[0];\n\t\treturn elem ?\n\t\t\telem.style ?\n\t\t\tparseFloat( jQuery.css( elem, type, \"padding\" ) ) :\n\t\t\tthis[ type ]() :\n\t\t\tnull;\n\t};\n\n\t// outerHeight and outerWidth\n\tjQuery.fn[ \"outer\" + name ] = function( margin ) {\n\t\tvar elem = this[0];\n\t\treturn elem ?\n\t\t\telem.style ?\n\t\t\tparseFloat( jQuery.css( elem, type, margin ? \"margin\" : \"border\" ) ) :\n\t\t\tthis[ type ]() :\n\t\t\tnull;\n\t};\n\n\tjQuery.fn[ type ] = function( size ) {\n\t\t// Get window width or height\n\t\tvar elem = this[0];\n\t\tif ( !elem ) {\n\t\t\treturn size == null ? null : this;\n\t\t}\n\n\t\tif ( jQuery.isFunction( size ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tvar self = jQuery( this );\n\t\t\t\tself[ type ]( size.call( this, i, self[ type ]() ) );\n\t\t\t});\n\t\t}\n\n\t\tif ( jQuery.isWindow( elem ) ) {\n\t\t\t// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode\n\t\t\t// 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat\n\t\t\tvar docElemProp = elem.document.documentElement[ \"client\" + name ],\n\t\t\t\tbody = elem.document.body;\n\t\t\treturn elem.document.compatMode === \"CSS1Compat\" && docElemProp ||\n\t\t\t\tbody && body[ \"client\" + name ] || docElemProp;\n\n\t\t// Get document width or height\n\t\t} else if ( elem.nodeType === 9 ) {\n\t\t\t// Either scroll[Width/Height] or offset[Width/Height], whichever is greater\n\t\t\treturn Math.max(\n\t\t\t\telem.documentElement[\"client\" + name],\n\t\t\t\telem.body[\"scroll\" + name], elem.documentElement[\"scroll\" + name],\n\t\t\t\telem.body[\"offset\" + name], elem.documentElement[\"offset\" + name]\n\t\t\t);\n\n\t\t// Get or set width or height on the element\n\t\t} else if ( size === undefined ) {\n\t\t\tvar orig = jQuery.css( elem, type ),\n\t\t\t\tret = parseFloat( orig );\n\n\t\t\treturn jQuery.isNumeric( ret ) ? ret : orig;\n\n\t\t// Set the width or height on the element (default to pixels if value is unitless)\n\t\t} else {\n\t\t\treturn this.css( type, typeof size === \"string\" ? size : size + \"px\" );\n\t\t}\n\t};\n\n});\n\n\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\n\n})( window );\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/diagram-viewer/js/jquery/jquery.progressbar.js",
    "content": "/*\n * @ Dmitry Farafonov\n */\n\n(function($){\n$.ProgressBar = function(options) {\n\tthis.element = $(options.boundingBox);\n\tif (options.on && options.on.complete){\n\t\tthis.onComplete = options.on.complete;\n\t}\n\tif (options.on && options.on.valueChange){\n\t\tthis.onValueChange = options.on.valueChange;\n\t}\n\t\n\tthis._create();\n\t\n\tif (options.label)\n\t\tthis.set(\"label\", options.label);\n\tif (options.value)\n\t\tthis.value(options.value);\n\tif (options.max)\n\t\tthis.set(\"max\", options.max);\n};\n$.ProgressBar.prototype = {\n\toptions: {\n\t\tvalue: 0,\n\t\tmax: 100\n\t},\n\n\tmin: 0,\n\n\t_create: function() {\n\t\tthis.element\n\t\t\t.addClass( \"ui-progressbar ui-widget ui-widget-content ui-corner-all\" )\n\t\t\t.attr({\n\t\t\t\trole: \"progressbar\",\n\t\t\t\t\"aria-valuemin\": this.min,\n\t\t\t\t\"aria-valuemax\": this.options.max,\n\t\t\t\t\"aria-valuenow\": this._value()\n\t\t\t});\n\n\t\tthis.valueDiv = $( \"<div class='ui-progressbar-label'></div>\" )\n\t\t\t.appendTo( this.element );\n\t\t\t\n\t\tthis.valueDiv = $( \"<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>\" )\n\t\t\t.appendTo( this.element );\n\n\t\tthis.oldValue = this._value();\n\t\tthis._refreshValue();\n\t},\n\n\t_destroy: function() {\n\t\tthis.element\n\t\t\t.removeClass( \"ui-progressbar ui-widget ui-widget-content ui-corner-all\" )\n\t\t\t.removeAttr( \"role\" )\n\t\t\t.removeAttr( \"aria-valuemin\" )\n\t\t\t.removeAttr( \"aria-valuemax\" )\n\t\t\t.removeAttr( \"aria-valuenow\" );\n\n\t\tthis.valueDiv.remove();\n\t},\n\n\tvalue: function( newValue ) {\n\t\tif ( newValue === undefined ) {\n\t\t\treturn this._value();\n\t\t}\n\n\t\tthis._setOption( \"value\", newValue );\n\t\treturn this;\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tif ( key === \"value\" ) {\n\t\t\t//var oldVal = this.options.value;\n\t\t\tthis.options.value = value;\n\t\t\tthis._refreshValue();\n\t\t\t\n\t\t\tif (this.onValueChange)\n\t\t\t\tthis.onValueChange.apply(this, [{oldVal: this.oldValue, newVal: value}]);\n\t\t\t\n\t\t\tif ( this._value() === this.options.max ) {\n\t\t\t\t//this._trigger( \"complete\" );\n\t\t\t\tif (this.onComplete)\n\t\t\t\t\tthis.onComplete.apply(this);\n\t\t\t}\n\t\t} else if (key === \"label\") {\n\t\t\t$(this.element).find(\".ui-progressbar-label\").html(value);\n\t\t} else if (key === \"max\") {\n\t\t\tthis.options.max = value;\n\t\t}\n\n\t\t//this._super( key, value );\n\t},\n\n\t_value: function() {\n\t\tvar val = this.options.value;\n\t\t// normalize invalid value\n\t\tif ( typeof val !== \"number\" ) {\n\t\t\tval = 0;\n\t\t}\n\t\treturn Math.min( this.options.max, Math.max( this.min, val ) );\n\t},\n\n\t_percentage: function() {\n\t\treturn 100 * this._value() / this.options.max;\n\t},\n\n\t_refreshValue: function() {\n\t\tvar value = this.value(),\n\t\t\tpercentage = this._percentage();\n\n\t\tif ( this.oldValue !== value ) {\n\t\t\tthis.oldValue = value;\n\t\t\t//this._trigger( \"change\" );\n\t\t}\n\n\t\tthis.valueDiv\n\t\t\t.toggle( value > this.min )\n\t\t\t.toggleClass( \"ui-corner-right\", value === this.options.max )\n\t\t\t.width( percentage.toFixed(0) + \"%\" );\n\t\tthis.element.attr( \"aria-valuenow\", value );\n\t\t\n\t\t//$(this.element).find(\".ui-progressbar-label\").html(value + \"%\");\n\t},\n\t\n\tset: function(key, value){\n\t\tthis._setOption(key, value);\n\t}\n};\n\n})( jQuery );"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/diagram-viewer/js/jstools.js",
    "content": "if (typeof(console) == \"undefined\") {\n  var console = {\n    info: function(){},\n    warn: function(){},\n    error: function(){},\n    log: function(){},\n    time: function(){},\n    timeEnd: function(){}\n  };\n}\n\nif(!Array.isArray) {\n  Array.isArray = function (vArg) {\n    return Object.prototype.toString.call(vArg) === \"[object Array]\";\n  };\n}\n\nif (!Object.isSVGElement) {\n  Object.isSVGElement = function(vArg) {\n  var str = Object.prototype.toString.call(vArg);\n  return (str.indexOf(\"[object SVG\") == 0);\n  };\n}\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/diagram-viewer/js/raphael.2.1.1.js",
    "content": "// ┌────────────────────────────────────────────────────────────────────┐ \\\\\n// │ Raphaël 2.1.1 - JavaScript Vector Library                          │ \\\\\n// ├────────────────────────────────────────────────────────────────────┤ \\\\\n// │ Copyright © 2008-2012 Dmitry Baranovskiy (http://raphaeljs.com)    │ \\\\\n// │ Copyright © 2008-2012 Sencha Labs (http://sencha.com)              │ \\\\\n// ├────────────────────────────────────────────────────────────────────┤ \\\\\n// │ Licensed under the MIT (http://raphaeljs.com/license.html) license.│ \\\\\n// └────────────────────────────────────────────────────────────────────┘ \\\\\n\n(function(a){var b=\"0.3.4\",c=\"hasOwnProperty\",d=/[\\.\\/]/,e=\"*\",f=function(){},g=function(a,b){return a-b},h,i,j={n:{}},k=function(a,b){var c=j,d=i,e=Array.prototype.slice.call(arguments,2),f=k.listeners(a),l=0,m=!1,n,o=[],p={},q=[],r=h,s=[];h=a,i=0;for(var t=0,u=f.length;t<u;t++)\"zIndex\"in f[t]&&(o.push(f[t].zIndex),f[t].zIndex<0&&(p[f[t].zIndex]=f[t]));o.sort(g);while(o[l]<0){n=p[o[l++]],q.push(n.apply(b,e));if(i){i=d;return q}}for(t=0;t<u;t++){n=f[t];if(\"zIndex\"in n)if(n.zIndex==o[l]){q.push(n.apply(b,e));if(i)break;do{l++,n=p[o[l]],n&&q.push(n.apply(b,e));if(i)break}while(n)}else p[n.zIndex]=n;else{q.push(n.apply(b,e));if(i)break}}i=d,h=r;return q.length?q:null};k.listeners=function(a){var b=a.split(d),c=j,f,g,h,i,k,l,m,n,o=[c],p=[];for(i=0,k=b.length;i<k;i++){n=[];for(l=0,m=o.length;l<m;l++){c=o[l].n,g=[c[b[i]],c[e]],h=2;while(h--)f=g[h],f&&(n.push(f),p=p.concat(f.f||[]))}o=n}return p},k.on=function(a,b){var c=a.split(d),e=j;for(var g=0,h=c.length;g<h;g++)e=e.n,!e[c[g]]&&(e[c[g]]={n:{}}),e=e[c[g]];e.f=e.f||[];for(g=0,h=e.f.length;g<h;g++)if(e.f[g]==b)return f;e.f.push(b);return function(a){+a==+a&&(b.zIndex=+a)}},k.stop=function(){i=1},k.nt=function(a){if(a)return(new RegExp(\"(?:\\\\.|\\\\/|^)\"+a+\"(?:\\\\.|\\\\/|$)\")).test(h);return h},k.off=k.unbind=function(a,b){var f=a.split(d),g,h,i,k,l,m,n,o=[j];for(k=0,l=f.length;k<l;k++)for(m=0;m<o.length;m+=i.length-2){i=[m,1],g=o[m].n;if(f[k]!=e)g[f[k]]&&i.push(g[f[k]]);else for(h in g)g[c](h)&&i.push(g[h]);o.splice.apply(o,i)}for(k=0,l=o.length;k<l;k++){g=o[k];while(g.n){if(b){if(g.f){for(m=0,n=g.f.length;m<n;m++)if(g.f[m]==b){g.f.splice(m,1);break}!g.f.length&&delete g.f}for(h in g.n)if(g.n[c](h)&&g.n[h].f){var p=g.n[h].f;for(m=0,n=p.length;m<n;m++)if(p[m]==b){p.splice(m,1);break}!p.length&&delete g.n[h].f}}else{delete g.f;for(h in g.n)g.n[c](h)&&g.n[h].f&&delete g.n[h].f}g=g.n}}},k.once=function(a,b){var c=function(){var d=b.apply(this,arguments);k.unbind(a,c);return d};return k.on(a,c)},k.version=b,k.toString=function(){return\"You are running Eve \"+b},typeof module!=\"undefined\"&&module.exports?module.exports=k:typeof define!=\"undefined\"?define(\"eve\",[],function(){return k}):a.eve=k})(this),function(){function cF(a){for(var b=0;b<cy.length;b++)cy[b].el.paper==a&&cy.splice(b--,1)}function cE(b,d,e,f,h,i){e=Q(e);var j,k,l,m=[],o,p,q,t=b.ms,u={},v={},w={};if(f)for(y=0,z=cy.length;y<z;y++){var x=cy[y];if(x.el.id==d.id&&x.anim==b){x.percent!=e?(cy.splice(y,1),l=1):k=x,d.attr(x.totalOrigin);break}}else f=+v;for(var y=0,z=b.percents.length;y<z;y++){if(b.percents[y]==e||b.percents[y]>f*b.top){e=b.percents[y],p=b.percents[y-1]||0,t=t/b.top*(e-p),o=b.percents[y+1],j=b.anim[e];break}f&&d.attr(b.anim[b.percents[y]])}if(!!j){if(!k){for(var A in j)if(j[g](A))if(U[g](A)||d.paper.customAttributes[g](A)){u[A]=d.attr(A),u[A]==null&&(u[A]=T[A]),v[A]=j[A];switch(U[A]){case C:w[A]=(v[A]-u[A])/t;break;case\"colour\":u[A]=a.getRGB(u[A]);var B=a.getRGB(v[A]);w[A]={r:(B.r-u[A].r)/t,g:(B.g-u[A].g)/t,b:(B.b-u[A].b)/t};break;case\"path\":var D=bR(u[A],v[A]),E=D[1];u[A]=D[0],w[A]=[];for(y=0,z=u[A].length;y<z;y++){w[A][y]=[0];for(var F=1,G=u[A][y].length;F<G;F++)w[A][y][F]=(E[y][F]-u[A][y][F])/t}break;case\"transform\":var H=d._,I=ca(H[A],v[A]);if(I){u[A]=I.from,v[A]=I.to,w[A]=[],w[A].real=!0;for(y=0,z=u[A].length;y<z;y++){w[A][y]=[u[A][y][0]];for(F=1,G=u[A][y].length;F<G;F++)w[A][y][F]=(v[A][y][F]-u[A][y][F])/t}}else{var J=d.matrix||new cb,K={_:{transform:H.transform},getBBox:function(){return d.getBBox(1)}};u[A]=[J.a,J.b,J.c,J.d,J.e,J.f],b$(K,v[A]),v[A]=K._.transform,w[A]=[(K.matrix.a-J.a)/t,(K.matrix.b-J.b)/t,(K.matrix.c-J.c)/t,(K.matrix.d-J.d)/t,(K.matrix.e-J.e)/t,(K.matrix.f-J.f)/t]}break;case\"csv\":var L=r(j[A])[s](c),M=r(u[A])[s](c);if(A==\"clip-rect\"){u[A]=M,w[A]=[],y=M.length;while(y--)w[A][y]=(L[y]-u[A][y])/t}v[A]=L;break;default:L=[][n](j[A]),M=[][n](u[A]),w[A]=[],y=d.paper.customAttributes[A].length;while(y--)w[A][y]=((L[y]||0)-(M[y]||0))/t}}var O=j.easing,P=a.easing_formulas[O];if(!P){P=r(O).match(N);if(P&&P.length==5){var R=P;P=function(a){return cC(a,+R[1],+R[2],+R[3],+R[4],t)}}else P=bf}q=j.start||b.start||+(new Date),x={anim:b,percent:e,timestamp:q,start:q+(b.del||0),status:0,initstatus:f||0,stop:!1,ms:t,easing:P,from:u,diff:w,to:v,el:d,callback:j.callback,prev:p,next:o,repeat:i||b.times,origin:d.attr(),totalOrigin:h},cy.push(x);if(f&&!k&&!l){x.stop=!0,x.start=new Date-t*f;if(cy.length==1)return cA()}l&&(x.start=new Date-x.ms*f),cy.length==1&&cz(cA)}else k.initstatus=f,k.start=new Date-k.ms*f;eve(\"raphael.anim.start.\"+d.id,d,b)}}function cD(a,b){var c=[],d={};this.ms=b,this.times=1;if(a){for(var e in a)a[g](e)&&(d[Q(e)]=a[e],c.push(Q(e)));c.sort(bd)}this.anim=d,this.top=c[c.length-1],this.percents=c}function cC(a,b,c,d,e,f){function o(a,b){var c,d,e,f,j,k;for(e=a,k=0;k<8;k++){f=m(e)-a;if(z(f)<b)return e;j=(3*i*e+2*h)*e+g;if(z(j)<1e-6)break;e=e-f/j}c=0,d=1,e=a;if(e<c)return c;if(e>d)return d;while(c<d){f=m(e);if(z(f-a)<b)return e;a>f?c=e:d=e,e=(d-c)/2+c}return e}function n(a,b){var c=o(a,b);return((l*c+k)*c+j)*c}function m(a){return((i*a+h)*a+g)*a}var g=3*b,h=3*(d-b)-g,i=1-g-h,j=3*c,k=3*(e-c)-j,l=1-j-k;return n(a,1/(200*f))}function cq(){return this.x+q+this.y+q+this.width+\" × \"+this.height}function cp(){return this.x+q+this.y}function cb(a,b,c,d,e,f){a!=null?(this.a=+a,this.b=+b,this.c=+c,this.d=+d,this.e=+e,this.f=+f):(this.a=1,this.b=0,this.c=0,this.d=1,this.e=0,this.f=0)}function bH(b,c,d){b=a._path2curve(b),c=a._path2curve(c);var e,f,g,h,i,j,k,l,m,n,o=d?0:[];for(var p=0,q=b.length;p<q;p++){var r=b[p];if(r[0]==\"M\")e=i=r[1],f=j=r[2];else{r[0]==\"C\"?(m=[e,f].concat(r.slice(1)),e=m[6],f=m[7]):(m=[e,f,e,f,i,j,i,j],e=i,f=j);for(var s=0,t=c.length;s<t;s++){var u=c[s];if(u[0]==\"M\")g=k=u[1],h=l=u[2];else{u[0]==\"C\"?(n=[g,h].concat(u.slice(1)),g=n[6],h=n[7]):(n=[g,h,g,h,k,l,k,l],g=k,h=l);var v=bG(m,n,d);if(d)o+=v;else{for(var w=0,x=v.length;w<x;w++)v[w].segment1=p,v[w].segment2=s,v[w].bez1=m,v[w].bez2=n;o=o.concat(v)}}}}}return o}function bG(b,c,d){var e=a.bezierBBox(b),f=a.bezierBBox(c);if(!a.isBBoxIntersect(e,f))return d?0:[];var g=bB.apply(0,b),h=bB.apply(0,c),i=~~(g/5),j=~~(h/5),k=[],l=[],m={},n=d?0:[];for(var o=0;o<i+1;o++){var p=a.findDotsAtSegment.apply(a,b.concat(o/i));k.push({x:p.x,y:p.y,t:o/i})}for(o=0;o<j+1;o++)p=a.findDotsAtSegment.apply(a,c.concat(o/j)),l.push({x:p.x,y:p.y,t:o/j});for(o=0;o<i;o++)for(var q=0;q<j;q++){var r=k[o],s=k[o+1],t=l[q],u=l[q+1],v=z(s.x-r.x)<.001?\"y\":\"x\",w=z(u.x-t.x)<.001?\"y\":\"x\",x=bD(r.x,r.y,s.x,s.y,t.x,t.y,u.x,u.y);if(x){if(m[x.x.toFixed(4)]==x.y.toFixed(4))continue;m[x.x.toFixed(4)]=x.y.toFixed(4);var y=r.t+z((x[v]-r[v])/(s[v]-r[v]))*(s.t-r.t),A=t.t+z((x[w]-t[w])/(u[w]-t[w]))*(u.t-t.t);y>=0&&y<=1&&A>=0&&A<=1&&(d?n++:n.push({x:x.x,y:x.y,t1:y,t2:A}))}}return n}function bF(a,b){return bG(a,b,1)}function bE(a,b){return bG(a,b)}function bD(a,b,c,d,e,f,g,h){if(!(x(a,c)<y(e,g)||y(a,c)>x(e,g)||x(b,d)<y(f,h)||y(b,d)>x(f,h))){var i=(a*d-b*c)*(e-g)-(a-c)*(e*h-f*g),j=(a*d-b*c)*(f-h)-(b-d)*(e*h-f*g),k=(a-c)*(f-h)-(b-d)*(e-g);if(!k)return;var l=i/k,m=j/k,n=+l.toFixed(2),o=+m.toFixed(2);if(n<+y(a,c).toFixed(2)||n>+x(a,c).toFixed(2)||n<+y(e,g).toFixed(2)||n>+x(e,g).toFixed(2)||o<+y(b,d).toFixed(2)||o>+x(b,d).toFixed(2)||o<+y(f,h).toFixed(2)||o>+x(f,h).toFixed(2))return;return{x:l,y:m}}}function bC(a,b,c,d,e,f,g,h,i){if(!(i<0||bB(a,b,c,d,e,f,g,h)<i)){var j=1,k=j/2,l=j-k,m,n=.01;m=bB(a,b,c,d,e,f,g,h,l);while(z(m-i)>n)k/=2,l+=(m<i?1:-1)*k,m=bB(a,b,c,d,e,f,g,h,l);return l}}function bB(a,b,c,d,e,f,g,h,i){i==null&&(i=1),i=i>1?1:i<0?0:i;var j=i/2,k=12,l=[-0.1252,.1252,-0.3678,.3678,-0.5873,.5873,-0.7699,.7699,-0.9041,.9041,-0.9816,.9816],m=[.2491,.2491,.2335,.2335,.2032,.2032,.1601,.1601,.1069,.1069,.0472,.0472],n=0;for(var o=0;o<k;o++){var p=j*l[o]+j,q=bA(p,a,c,e,g),r=bA(p,b,d,f,h),s=q*q+r*r;n+=m[o]*w.sqrt(s)}return j*n}function bA(a,b,c,d,e){var f=-3*b+9*c-9*d+3*e,g=a*f+6*b-12*c+6*d;return a*g-3*b+3*c}function by(a,b){var c=[];for(var d=0,e=a.length;e-2*!b>d;d+=2){var f=[{x:+a[d-2],y:+a[d-1]},{x:+a[d],y:+a[d+1]},{x:+a[d+2],y:+a[d+3]},{x:+a[d+4],y:+a[d+5]}];b?d?e-4==d?f[3]={x:+a[0],y:+a[1]}:e-2==d&&(f[2]={x:+a[0],y:+a[1]},f[3]={x:+a[2],y:+a[3]}):f[0]={x:+a[e-2],y:+a[e-1]}:e-4==d?f[3]=f[2]:d||(f[0]={x:+a[d],y:+a[d+1]}),c.push([\"C\",(-f[0].x+6*f[1].x+f[2].x)/6,(-f[0].y+6*f[1].y+f[2].y)/6,(f[1].x+6*f[2].x-f[3].x)/6,(f[1].y+6*f[2].y-f[3].y)/6,f[2].x,f[2].y])}return c}function bx(){return this.hex}function bv(a,b,c){function d(){var e=Array.prototype.slice.call(arguments,0),f=e.join(\"␀\"),h=d.cache=d.cache||{},i=d.count=d.count||[];if(h[g](f)){bu(i,f);return c?c(h[f]):h[f]}i.length>=1e3&&delete h[i.shift()],i.push(f),h[f]=a[m](b,e);return c?c(h[f]):h[f]}return d}function bu(a,b){for(var c=0,d=a.length;c<d;c++)if(a[c]===b)return a.push(a.splice(c,1)[0])}function bm(a){if(Object(a)!==a)return a;var b=new a.constructor;for(var c in a)a[g](c)&&(b[c]=bm(a[c]));return b}function a(c){if(a.is(c,\"function\"))return b?c():eve.on(\"raphael.DOMload\",c);if(a.is(c,E))return a._engine.create[m](a,c.splice(0,3+a.is(c[0],C))).add(c);var d=Array.prototype.slice.call(arguments,0);if(a.is(d[d.length-1],\"function\")){var e=d.pop();return b?e.call(a._engine.create[m](a,d)):eve.on(\"raphael.DOMload\",function(){e.call(a._engine.create[m](a,d))})}return a._engine.create[m](a,arguments)}a.version=\"2.1.0\",a.eve=eve;var b,c=/[, ]+/,d={circle:1,rect:1,path:1,ellipse:1,text:1,image:1},e=/\\{(\\d+)\\}/g,f=\"prototype\",g=\"hasOwnProperty\",h={doc:document,win:window},i={was:Object.prototype[g].call(h.win,\"Raphael\"),is:h.win.Raphael},j=function(){this.ca=this.customAttributes={}},k,l=\"appendChild\",m=\"apply\",n=\"concat\",o=\"createTouch\"in h.doc,p=\"\",q=\" \",r=String,s=\"split\",t=\"click dblclick mousedown mousemove mouseout mouseover mouseup touchstart touchmove touchend touchcancel\"[s](q),u={mousedown:\"touchstart\",mousemove:\"touchmove\",mouseup:\"touchend\"},v=r.prototype.toLowerCase,w=Math,x=w.max,y=w.min,z=w.abs,A=w.pow,B=w.PI,C=\"number\",D=\"string\",E=\"array\",F=\"toString\",G=\"fill\",H=Object.prototype.toString,I={},J=\"push\",K=a._ISURL=/^url\\(['\"]?([^\\)]+?)['\"]?\\)$/i,L=/^\\s*((#[a-f\\d]{6})|(#[a-f\\d]{3})|rgba?\\(\\s*([\\d\\.]+%?\\s*,\\s*[\\d\\.]+%?\\s*,\\s*[\\d\\.]+%?(?:\\s*,\\s*[\\d\\.]+%?)?)\\s*\\)|hsba?\\(\\s*([\\d\\.]+(?:deg|\\xb0|%)?\\s*,\\s*[\\d\\.]+%?\\s*,\\s*[\\d\\.]+(?:%?\\s*,\\s*[\\d\\.]+)?)%?\\s*\\)|hsla?\\(\\s*([\\d\\.]+(?:deg|\\xb0|%)?\\s*,\\s*[\\d\\.]+%?\\s*,\\s*[\\d\\.]+(?:%?\\s*,\\s*[\\d\\.]+)?)%?\\s*\\))\\s*$/i,M={NaN:1,Infinity:1,\"-Infinity\":1},N=/^(?:cubic-)?bezier\\(([^,]+),([^,]+),([^,]+),([^\\)]+)\\)/,O=w.round,P=\"setAttribute\",Q=parseFloat,R=parseInt,S=r.prototype.toUpperCase,T=a._availableAttrs={\"arrow-end\":\"none\",\"arrow-start\":\"none\",blur:0,\"clip-rect\":\"0 0 1e9 1e9\",cursor:\"default\",cx:0,cy:0,fill:\"#fff\",\"fill-opacity\":1,font:'10px \"Arial\"',\"font-family\":'\"Arial\"',\"font-size\":\"10\",\"font-style\":\"normal\",\"font-weight\":400,gradient:0,height:0,href:\"http://raphaeljs.com/\",\"letter-spacing\":0,opacity:1,path:\"M0,0\",r:0,rx:0,ry:0,src:\"\",stroke:\"#000\",\"stroke-dasharray\":\"\",\"stroke-linecap\":\"butt\",\"stroke-linejoin\":\"butt\",\"stroke-miterlimit\":0,\"stroke-opacity\":1,\"stroke-width\":1,target:\"_blank\",\"text-anchor\":\"middle\",title:\"Raphael\",transform:\"\",width:0,x:0,y:0},U=a._availableAnimAttrs={blur:C,\"clip-rect\":\"csv\",cx:C,cy:C,fill:\"colour\",\"fill-opacity\":C,\"font-size\":C,height:C,opacity:C,path:\"path\",r:C,rx:C,ry:C,stroke:\"colour\",\"stroke-opacity\":C,\"stroke-width\":C,transform:\"transform\",width:C,x:C,y:C},V=/[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]/g,W=/[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*,[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*/,X={hs:1,rg:1},Y=/,?([achlmqrstvxz]),?/gi,Z=/([achlmrqstvz])[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029,]*((-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*,?[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*)+)/ig,$=/([rstm])[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029,]*((-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*,?[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*)+)/ig,_=/(-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?)[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*,?[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*/ig,ba=a._radial_gradient=/^r(?:\\(([^,]+?)[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*,[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*([^\\)]+?)\\))?/,bb={},bc=function(a,b){return a.key-b.key},bd=function(a,b){return Q(a)-Q(b)},be=function(){},bf=function(a){return a},bg=a._rectPath=function(a,b,c,d,e){if(e)return[[\"M\",a+e,b],[\"l\",c-e*2,0],[\"a\",e,e,0,0,1,e,e],[\"l\",0,d-e*2],[\"a\",e,e,0,0,1,-e,e],[\"l\",e*2-c,0],[\"a\",e,e,0,0,1,-e,-e],[\"l\",0,e*2-d],[\"a\",e,e,0,0,1,e,-e],[\"z\"]];return[[\"M\",a,b],[\"l\",c,0],[\"l\",0,d],[\"l\",-c,0],[\"z\"]]},bh=function(a,b,c,d){d==null&&(d=c);return[[\"M\",a,b],[\"m\",0,-d],[\"a\",c,d,0,1,1,0,2*d],[\"a\",c,d,0,1,1,0,-2*d],[\"z\"]]},bi=a._getPath={path:function(a){return a.attr(\"path\")},circle:function(a){var b=a.attrs;return bh(b.cx,b.cy,b.r)},ellipse:function(a){var b=a.attrs;return bh(b.cx,b.cy,b.rx,b.ry)},rect:function(a){var b=a.attrs;return bg(b.x,b.y,b.width,b.height,b.r)},image:function(a){var b=a.attrs;return bg(b.x,b.y,b.width,b.height)},text:function(a){var b=a._getBBox();return bg(b.x,b.y,b.width,b.height)}},bj=a.mapPath=function(a,b){if(!b)return a;var c,d,e,f,g,h,i;a=bR(a);for(e=0,g=a.length;e<g;e++){i=a[e];for(f=1,h=i.length;f<h;f+=2)c=b.x(i[f],i[f+1]),d=b.y(i[f],i[f+1]),i[f]=c,i[f+1]=d}return a};a._g=h,a.type=h.win.SVGAngle||h.doc.implementation.hasFeature(\"http://www.w3.org/TR/SVG11/feature#BasicStructure\",\"1.1\")?\"SVG\":\"VML\";if(a.type==\"VML\"){var bk=h.doc.createElement(\"div\"),bl;bk.innerHTML='<v:shape adj=\"1\"/>',bl=bk.firstChild,bl.style.behavior=\"url(#default#VML)\";if(!bl||typeof bl.adj!=\"object\")return a.type=p;bk=null}a.svg=!(a.vml=a.type==\"VML\"),a._Paper=j,a.fn=k=j.prototype=a.prototype,a._id=0,a._oid=0,a.is=function(a,b){b=v.call(b);if(b==\"finite\")return!M[g](+a);if(b==\"array\")return a instanceof Array;return b==\"null\"&&a===null||b==typeof a&&a!==null||b==\"object\"&&a===Object(a)||b==\"array\"&&Array.isArray&&Array.isArray(a)||H.call(a).slice(8,-1).toLowerCase()==b},a.angle=function(b,c,d,e,f,g){if(f==null){var h=b-d,i=c-e;if(!h&&!i)return 0;return(180+w.atan2(-i,-h)*180/B+360)%360}return a.angle(b,c,f,g)-a.angle(d,e,f,g)},a.rad=function(a){return a%360*B/180},a.deg=function(a){return a*180/B%360},a.snapTo=function(b,c,d){d=a.is(d,\"finite\")?d:10;if(a.is(b,E)){var e=b.length;while(e--)if(z(b[e]-c)<=d)return b[e]}else{b=+b;var f=c%b;if(f<d)return c-f;if(f>b-d)return c-f+b}return c};var bn=a.createUUID=function(a,b){return function(){return\"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(a,b).toUpperCase()}}(/[xy]/g,function(a){var b=w.random()*16|0,c=a==\"x\"?b:b&3|8;return c.toString(16)});a.setWindow=function(b){eve(\"raphael.setWindow\",a,h.win,b),h.win=b,h.doc=h.win.document,a._engine.initWin&&a._engine.initWin(h.win)};var bo=function(b){if(a.vml){var c=/^\\s+|\\s+$/g,d;try{var e=new ActiveXObject(\"htmlfile\");e.write(\"<body>\"),e.close(),d=e.body}catch(f){d=createPopup().document.body}var g=d.createTextRange();bo=bv(function(a){try{d.style.color=r(a).replace(c,p);var b=g.queryCommandValue(\"ForeColor\");b=(b&255)<<16|b&65280|(b&16711680)>>>16;return\"#\"+(\"000000\"+b.toString(16)).slice(-6)}catch(e){return\"none\"}})}else{var i=h.doc.createElement(\"i\");i.title=\"Raphaël Colour Picker\",i.style.display=\"none\",h.doc.body.appendChild(i),bo=bv(function(a){i.style.color=a;return h.doc.defaultView.getComputedStyle(i,p).getPropertyValue(\"color\")})}return bo(b)},bp=function(){return\"hsb(\"+[this.h,this.s,this.b]+\")\"},bq=function(){return\"hsl(\"+[this.h,this.s,this.l]+\")\"},br=function(){return this.hex},bs=function(b,c,d){c==null&&a.is(b,\"object\")&&\"r\"in b&&\"g\"in b&&\"b\"in b&&(d=b.b,c=b.g,b=b.r);if(c==null&&a.is(b,D)){var e=a.getRGB(b);b=e.r,c=e.g,d=e.b}if(b>1||c>1||d>1)b/=255,c/=255,d/=255;return[b,c,d]},bt=function(b,c,d,e){b*=255,c*=255,d*=255;var f={r:b,g:c,b:d,hex:a.rgb(b,c,d),toString:br};a.is(e,\"finite\")&&(f.opacity=e);return f};a.color=function(b){var c;a.is(b,\"object\")&&\"h\"in b&&\"s\"in b&&\"b\"in b?(c=a.hsb2rgb(b),b.r=c.r,b.g=c.g,b.b=c.b,b.hex=c.hex):a.is(b,\"object\")&&\"h\"in b&&\"s\"in b&&\"l\"in b?(c=a.hsl2rgb(b),b.r=c.r,b.g=c.g,b.b=c.b,b.hex=c.hex):(a.is(b,\"string\")&&(b=a.getRGB(b)),a.is(b,\"object\")&&\"r\"in b&&\"g\"in b&&\"b\"in b?(c=a.rgb2hsl(b),b.h=c.h,b.s=c.s,b.l=c.l,c=a.rgb2hsb(b),b.v=c.b):(b={hex:\"none\"},b.r=b.g=b.b=b.h=b.s=b.v=b.l=-1)),b.toString=br;return b},a.hsb2rgb=function(a,b,c,d){this.is(a,\"object\")&&\"h\"in a&&\"s\"in a&&\"b\"in a&&(c=a.b,b=a.s,a=a.h,d=a.o),a*=360;var e,f,g,h,i;a=a%360/60,i=c*b,h=i*(1-z(a%2-1)),e=f=g=c-i,a=~~a,e+=[i,h,0,0,h,i][a],f+=[h,i,i,h,0,0][a],g+=[0,0,h,i,i,h][a];return bt(e,f,g,d)},a.hsl2rgb=function(a,b,c,d){this.is(a,\"object\")&&\"h\"in a&&\"s\"in a&&\"l\"in a&&(c=a.l,b=a.s,a=a.h);if(a>1||b>1||c>1)a/=360,b/=100,c/=100;a*=360;var e,f,g,h,i;a=a%360/60,i=2*b*(c<.5?c:1-c),h=i*(1-z(a%2-1)),e=f=g=c-i/2,a=~~a,e+=[i,h,0,0,h,i][a],f+=[h,i,i,h,0,0][a],g+=[0,0,h,i,i,h][a];return bt(e,f,g,d)},a.rgb2hsb=function(a,b,c){c=bs(a,b,c),a=c[0],b=c[1],c=c[2];var d,e,f,g;f=x(a,b,c),g=f-y(a,b,c),d=g==0?null:f==a?(b-c)/g:f==b?(c-a)/g+2:(a-b)/g+4,d=(d+360)%6*60/360,e=g==0?0:g/f;return{h:d,s:e,b:f,toString:bp}},a.rgb2hsl=function(a,b,c){c=bs(a,b,c),a=c[0],b=c[1],c=c[2];var d,e,f,g,h,i;g=x(a,b,c),h=y(a,b,c),i=g-h,d=i==0?null:g==a?(b-c)/i:g==b?(c-a)/i+2:(a-b)/i+4,d=(d+360)%6*60/360,f=(g+h)/2,e=i==0?0:f<.5?i/(2*f):i/(2-2*f);return{h:d,s:e,l:f,toString:bq}},a._path2string=function(){return this.join(\",\").replace(Y,\"$1\")};var bw=a._preload=function(a,b){var c=h.doc.createElement(\"img\");c.style.cssText=\"position:absolute;left:-9999em;top:-9999em\",c.onload=function(){b.call(this),this.onload=null,h.doc.body.removeChild(this)},c.onerror=function(){h.doc.body.removeChild(this)},h.doc.body.appendChild(c),c.src=a};a.getRGB=bv(function(b){if(!b||!!((b=r(b)).indexOf(\"-\")+1))return{r:-1,g:-1,b:-1,hex:\"none\",error:1,toString:bx};if(b==\"none\")return{r:-1,g:-1,b:-1,hex:\"none\",toString:bx};!X[g](b.toLowerCase().substring(0,2))&&b.charAt()!=\"#\"&&(b=bo(b));var c,d,e,f,h,i,j,k=b.match(L);if(k){k[2]&&(f=R(k[2].substring(5),16),e=R(k[2].substring(3,5),16),d=R(k[2].substring(1,3),16)),k[3]&&(f=R((i=k[3].charAt(3))+i,16),e=R((i=k[3].charAt(2))+i,16),d=R((i=k[3].charAt(1))+i,16)),k[4]&&(j=k[4][s](W),d=Q(j[0]),j[0].slice(-1)==\"%\"&&(d*=2.55),e=Q(j[1]),j[1].slice(-1)==\"%\"&&(e*=2.55),f=Q(j[2]),j[2].slice(-1)==\"%\"&&(f*=2.55),k[1].toLowerCase().slice(0,4)==\"rgba\"&&(h=Q(j[3])),j[3]&&j[3].slice(-1)==\"%\"&&(h/=100));if(k[5]){j=k[5][s](W),d=Q(j[0]),j[0].slice(-1)==\"%\"&&(d*=2.55),e=Q(j[1]),j[1].slice(-1)==\"%\"&&(e*=2.55),f=Q(j[2]),j[2].slice(-1)==\"%\"&&(f*=2.55),(j[0].slice(-3)==\"deg\"||j[0].slice(-1)==\"°\")&&(d/=360),k[1].toLowerCase().slice(0,4)==\"hsba\"&&(h=Q(j[3])),j[3]&&j[3].slice(-1)==\"%\"&&(h/=100);return a.hsb2rgb(d,e,f,h)}if(k[6]){j=k[6][s](W),d=Q(j[0]),j[0].slice(-1)==\"%\"&&(d*=2.55),e=Q(j[1]),j[1].slice(-1)==\"%\"&&(e*=2.55),f=Q(j[2]),j[2].slice(-1)==\"%\"&&(f*=2.55),(j[0].slice(-3)==\"deg\"||j[0].slice(-1)==\"°\")&&(d/=360),k[1].toLowerCase().slice(0,4)==\"hsla\"&&(h=Q(j[3])),j[3]&&j[3].slice(-1)==\"%\"&&(h/=100);return a.hsl2rgb(d,e,f,h)}k={r:d,g:e,b:f,toString:bx},k.hex=\"#\"+(16777216|f|e<<8|d<<16).toString(16).slice(1),a.is(h,\"finite\")&&(k.opacity=h);return k}return{r:-1,g:-1,b:-1,hex:\"none\",error:1,toString:bx}},a),a.hsb=bv(function(b,c,d){return a.hsb2rgb(b,c,d).hex}),a.hsl=bv(function(b,c,d){return a.hsl2rgb(b,c,d).hex}),a.rgb=bv(function(a,b,c){return\"#\"+(16777216|c|b<<8|a<<16).toString(16).slice(1)}),a.getColor=function(a){var b=this.getColor.start=this.getColor.start||{h:0,s:1,b:a||.75},c=this.hsb2rgb(b.h,b.s,b.b);b.h+=.075,b.h>1&&(b.h=0,b.s-=.2,b.s<=0&&(this.getColor.start={h:0,s:1,b:b.b}));return c.hex},a.getColor.reset=function(){delete this.start},a.parsePathString=function(b){if(!b)return null;var c=bz(b);if(c.arr)return bJ(c.arr);var d={a:7,c:6,h:1,l:2,m:2,r:4,q:4,s:4,t:2,v:1,z:0},e=[];a.is(b,E)&&a.is(b[0],E)&&(e=bJ(b)),e.length||r(b).replace(Z,function(a,b,c){var f=[],g=b.toLowerCase();c.replace(_,function(a,b){b&&f.push(+b)}),g==\"m\"&&f.length>2&&(e.push([b][n](f.splice(0,2))),g=\"l\",b=b==\"m\"?\"l\":\"L\");if(g==\"r\")e.push([b][n](f));else while(f.length>=d[g]){e.push([b][n](f.splice(0,d[g])));if(!d[g])break}}),e.toString=a._path2string,c.arr=bJ(e);return e},a.parseTransformString=bv(function(b){if(!b)return null;var c={r:3,s:4,t:2,m:6},d=[];a.is(b,E)&&a.is(b[0],E)&&(d=bJ(b)),d.length||r(b).replace($,function(a,b,c){var e=[],f=v.call(b);c.replace(_,function(a,b){b&&e.push(+b)}),d.push([b][n](e))}),d.toString=a._path2string;return d});var bz=function(a){var b=bz.ps=bz.ps||{};b[a]?b[a].sleep=100:b[a]={sleep:100},setTimeout(function(){for(var c in b)b[g](c)&&c!=a&&(b[c].sleep--,!b[c].sleep&&delete b[c])});return b[a]};a.findDotsAtSegment=function(a,b,c,d,e,f,g,h,i){var j=1-i,k=A(j,3),l=A(j,2),m=i*i,n=m*i,o=k*a+l*3*i*c+j*3*i*i*e+n*g,p=k*b+l*3*i*d+j*3*i*i*f+n*h,q=a+2*i*(c-a)+m*(e-2*c+a),r=b+2*i*(d-b)+m*(f-2*d+b),s=c+2*i*(e-c)+m*(g-2*e+c),t=d+2*i*(f-d)+m*(h-2*f+d),u=j*a+i*c,v=j*b+i*d,x=j*e+i*g,y=j*f+i*h,z=90-w.atan2(q-s,r-t)*180/B;(q>s||r<t)&&(z+=180);return{x:o,y:p,m:{x:q,y:r},n:{x:s,y:t},start:{x:u,y:v},end:{x:x,y:y},alpha:z}},a.bezierBBox=function(b,c,d,e,f,g,h,i){a.is(b,\"array\")||(b=[b,c,d,e,f,g,h,i]);var j=bQ.apply(null,b);return{x:j.min.x,y:j.min.y,x2:j.max.x,y2:j.max.y,width:j.max.x-j.min.x,height:j.max.y-j.min.y}},a.isPointInsideBBox=function(a,b,c){return b>=a.x&&b<=a.x2&&c>=a.y&&c<=a.y2},a.isBBoxIntersect=function(b,c){var d=a.isPointInsideBBox;return d(c,b.x,b.y)||d(c,b.x2,b.y)||d(c,b.x,b.y2)||d(c,b.x2,b.y2)||d(b,c.x,c.y)||d(b,c.x2,c.y)||d(b,c.x,c.y2)||d(b,c.x2,c.y2)||(b.x<c.x2&&b.x>c.x||c.x<b.x2&&c.x>b.x)&&(b.y<c.y2&&b.y>c.y||c.y<b.y2&&c.y>b.y)},a.pathIntersection=function(a,b){return bH(a,b)},a.pathIntersectionNumber=function(a,b){return bH(a,b,1)},a.isPointInsidePath=function(b,c,d){var e=a.pathBBox(b);return a.isPointInsideBBox(e,c,d)&&bH(b,[[\"M\",c,d],[\"H\",e.x2+10]],1)%2==1},a._removedFactory=function(a){return function(){eve(\"raphael.log\",null,\"Raphaël: you are calling to method “\"+a+\"” of removed object\",a)}};var bI=a.pathBBox=function(a){var b=bz(a);if(b.bbox)return bm(b.bbox);if(!a)return{x:0,y:0,width:0,height:0,x2:0,y2:0};a=bR(a);var c=0,d=0,e=[],f=[],g;for(var h=0,i=a.length;h<i;h++){g=a[h];if(g[0]==\"M\")c=g[1],d=g[2],e.push(c),f.push(d);else{var j=bQ(c,d,g[1],g[2],g[3],g[4],g[5],g[6]);e=e[n](j.min.x,j.max.x),f=f[n](j.min.y,j.max.y),c=g[5],d=g[6]}}var k=y[m](0,e),l=y[m](0,f),o=x[m](0,e),p=x[m](0,f),q={x:k,y:l,x2:o,y2:p,width:o-k,height:p-l};b.bbox=bm(q);return q},bJ=function(b){var c=bm(b);c.toString=a._path2string;return c},bK=a._pathToRelative=function(b){var c=bz(b);if(c.rel)return bJ(c.rel);if(!a.is(b,E)||!a.is(b&&b[0],E))b=a.parsePathString(b);var d=[],e=0,f=0,g=0,h=0,i=0;b[0][0]==\"M\"&&(e=b[0][1],f=b[0][2],g=e,h=f,i++,d.push([\"M\",e,f]));for(var j=i,k=b.length;j<k;j++){var l=d[j]=[],m=b[j];if(m[0]!=v.call(m[0])){l[0]=v.call(m[0]);switch(l[0]){case\"a\":l[1]=m[1],l[2]=m[2],l[3]=m[3],l[4]=m[4],l[5]=m[5],l[6]=+(m[6]-e).toFixed(3),l[7]=+(m[7]-f).toFixed(3);break;case\"v\":l[1]=+(m[1]-f).toFixed(3);break;case\"m\":g=m[1],h=m[2];default:for(var n=1,o=m.length;n<o;n++)l[n]=+(m[n]-(n%2?e:f)).toFixed(3)}}else{l=d[j]=[],m[0]==\"m\"&&(g=m[1]+e,h=m[2]+f);for(var p=0,q=m.length;p<q;p++)d[j][p]=m[p]}var r=d[j].length;switch(d[j][0]){case\"z\":e=g,f=h;break;case\"h\":e+=+d[j][r-1];break;case\"v\":f+=+d[j][r-1];break;default:e+=+d[j][r-2],f+=+d[j][r-1]}}d.toString=a._path2string,c.rel=bJ(d);return d},bL=a._pathToAbsolute=function(b){var c=bz(b);if(c.abs)return bJ(c.abs);if(!a.is(b,E)||!a.is(b&&b[0],E))b=a.parsePathString(b);if(!b||!b.length)return[[\"M\",0,0]];var d=[],e=0,f=0,g=0,h=0,i=0;b[0][0]==\"M\"&&(e=+b[0][1],f=+b[0][2],g=e,h=f,i++,d[0]=[\"M\",e,f]);var j=b.length==3&&b[0][0]==\"M\"&&b[1][0].toUpperCase()==\"R\"&&b[2][0].toUpperCase()==\"Z\";for(var k,l,m=i,o=b.length;m<o;m++){d.push(k=[]),l=b[m];if(l[0]!=S.call(l[0])){k[0]=S.call(l[0]);switch(k[0]){case\"A\":k[1]=l[1],k[2]=l[2],k[3]=l[3],k[4]=l[4],k[5]=l[5],k[6]=+(l[6]+e),k[7]=+(l[7]+f);break;case\"V\":k[1]=+l[1]+f;break;case\"H\":k[1]=+l[1]+e;break;case\"R\":var p=[e,f][n](l.slice(1));for(var q=2,r=p.length;q<r;q++)p[q]=+p[q]+e,p[++q]=+p[q]+f;d.pop(),d=d[n](by(p,j));break;case\"M\":g=+l[1]+e,h=+l[2]+f;default:for(q=1,r=l.length;q<r;q++)k[q]=+l[q]+(q%2?e:f)}}else if(l[0]==\"R\")p=[e,f][n](l.slice(1)),d.pop(),d=d[n](by(p,j)),k=[\"R\"][n](l.slice(-2));else for(var s=0,t=l.length;s<t;s++)k[s]=l[s];switch(k[0]){case\"Z\":e=g,f=h;break;case\"H\":e=k[1];break;case\"V\":f=k[1];break;case\"M\":g=k[k.length-2],h=k[k.length-1];default:e=k[k.length-2],f=k[k.length-1]}}d.toString=a._path2string,c.abs=bJ(d);return d},bM=function(a,b,c,d){return[a,b,c,d,c,d]},bN=function(a,b,c,d,e,f){var g=1/3,h=2/3;return[g*a+h*c,g*b+h*d,g*e+h*c,g*f+h*d,e,f]},bO=function(a,b,c,d,e,f,g,h,i,j){var k=B*120/180,l=B/180*(+e||0),m=[],o,p=bv(function(a,b,c){var d=a*w.cos(c)-b*w.sin(c),e=a*w.sin(c)+b*w.cos(c);return{x:d,y:e}});if(!j){o=p(a,b,-l),a=o.x,b=o.y,o=p(h,i,-l),h=o.x,i=o.y;var q=w.cos(B/180*e),r=w.sin(B/180*e),t=(a-h)/2,u=(b-i)/2,v=t*t/(c*c)+u*u/(d*d);v>1&&(v=w.sqrt(v),c=v*c,d=v*d);var x=c*c,y=d*d,A=(f==g?-1:1)*w.sqrt(z((x*y-x*u*u-y*t*t)/(x*u*u+y*t*t))),C=A*c*u/d+(a+h)/2,D=A*-d*t/c+(b+i)/2,E=w.asin(((b-D)/d).toFixed(9)),F=w.asin(((i-D)/d).toFixed(9));E=a<C?B-E:E,F=h<C?B-F:F,E<0&&(E=B*2+E),F<0&&(F=B*2+F),g&&E>F&&(E=E-B*2),!g&&F>E&&(F=F-B*2)}else E=j[0],F=j[1],C=j[2],D=j[3];var G=F-E;if(z(G)>k){var H=F,I=h,J=i;F=E+k*(g&&F>E?1:-1),h=C+c*w.cos(F),i=D+d*w.sin(F),m=bO(h,i,c,d,e,0,g,I,J,[F,H,C,D])}G=F-E;var K=w.cos(E),L=w.sin(E),M=w.cos(F),N=w.sin(F),O=w.tan(G/4),P=4/3*c*O,Q=4/3*d*O,R=[a,b],S=[a+P*L,b-Q*K],T=[h+P*N,i-Q*M],U=[h,i];S[0]=2*R[0]-S[0],S[1]=2*R[1]-S[1];if(j)return[S,T,U][n](m);m=[S,T,U][n](m).join()[s](\",\");var V=[];for(var W=0,X=m.length;W<X;W++)V[W]=W%2?p(m[W-1],m[W],l).y:p(m[W],m[W+1],l).x;return V},bP=function(a,b,c,d,e,f,g,h,i){var j=1-i;return{x:A(j,3)*a+A(j,2)*3*i*c+j*3*i*i*e+A(i,3)*g,y:A(j,3)*b+A(j,2)*3*i*d+j*3*i*i*f+A(i,3)*h}},bQ=bv(function(a,b,c,d,e,f,g,h){var i=e-2*c+a-(g-2*e+c),j=2*(c-a)-2*(e-c),k=a-c,l=(-j+w.sqrt(j*j-4*i*k))/2/i,n=(-j-w.sqrt(j*j-4*i*k))/2/i,o=[b,h],p=[a,g],q;z(l)>\"1e12\"&&(l=.5),z(n)>\"1e12\"&&(n=.5),l>0&&l<1&&(q=bP(a,b,c,d,e,f,g,h,l),p.push(q.x),o.push(q.y)),n>0&&n<1&&(q=bP(a,b,c,d,e,f,g,h,n),p.push(q.x),o.push(q.y)),i=f-2*d+b-(h-2*f+d),j=2*(d-b)-2*(f-d),k=b-d,l=(-j+w.sqrt(j*j-4*i*k))/2/i,n=(-j-w.sqrt(j*j-4*i*k))/2/i,z(l)>\"1e12\"&&(l=.5),z(n)>\"1e12\"&&(n=.5),l>0&&l<1&&(q=bP(a,b,c,d,e,f,g,h,l),p.push(q.x),o.push(q.y)),n>0&&n<1&&(q=bP(a,b,c,d,e,f,g,h,n),p.push(q.x),o.push(q.y));return{min:{x:y[m](0,p),y:y[m](0,o)},max:{x:x[m](0,p),y:x[m](0,o)}}}),bR=a._path2curve=bv(function(a,b){var c=!b&&bz(a);if(!b&&c.curve)return bJ(c.curve);var d=bL(a),e=b&&bL(b),f={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},g={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},h=function(a,b){var c,d;if(!a)return[\"C\",b.x,b.y,b.x,b.y,b.x,b.y];!(a[0]in{T:1,Q:1})&&(b.qx=b.qy=null);switch(a[0]){case\"M\":b.X=a[1],b.Y=a[2];break;case\"A\":a=[\"C\"][n](bO[m](0,[b.x,b.y][n](a.slice(1))));break;case\"S\":c=b.x+(b.x-(b.bx||b.x)),d=b.y+(b.y-(b.by||b.y)),a=[\"C\",c,d][n](a.slice(1));break;case\"T\":b.qx=b.x+(b.x-(b.qx||b.x)),b.qy=b.y+(b.y-(b.qy||b.y)),a=[\"C\"][n](bN(b.x,b.y,b.qx,b.qy,a[1],a[2]));break;case\"Q\":b.qx=a[1],b.qy=a[2],a=[\"C\"][n](bN(b.x,b.y,a[1],a[2],a[3],a[4]));break;case\"L\":a=[\"C\"][n](bM(b.x,b.y,a[1],a[2]));break;case\"H\":a=[\"C\"][n](bM(b.x,b.y,a[1],b.y));break;case\"V\":a=[\"C\"][n](bM(b.x,b.y,b.x,a[1]));break;case\"Z\":a=[\"C\"][n](bM(b.x,b.y,b.X,b.Y))}return a},i=function(a,b){if(a[b].length>7){a[b].shift();var c=a[b];while(c.length)a.splice(b++,0,[\"C\"][n](c.splice(0,6)));a.splice(b,1),l=x(d.length,e&&e.length||0)}},j=function(a,b,c,f,g){a&&b&&a[g][0]==\"M\"&&b[g][0]!=\"M\"&&(b.splice(g,0,[\"M\",f.x,f.y]),c.bx=0,c.by=0,c.x=a[g][1],c.y=a[g][2],l=x(d.length,e&&e.length||0))};for(var k=0,l=x(d.length,e&&e.length||0);k<l;k++){d[k]=h(d[k],f),i(d,k),e&&(e[k]=h(e[k],g)),e&&i(e,k),j(d,e,f,g,k),j(e,d,g,f,k);var o=d[k],p=e&&e[k],q=o.length,r=e&&p.length;f.x=o[q-2],f.y=o[q-1],f.bx=Q(o[q-4])||f.x,f.by=Q(o[q-3])||f.y,g.bx=e&&(Q(p[r-4])||g.x),g.by=e&&(Q(p[r-3])||g.y),g.x=e&&p[r-2],g.y=e&&p[r-1]}e||(c.curve=bJ(d));return e?[d,e]:d},null,bJ),bS=a._parseDots=bv(function(b){var c=[];for(var d=0,e=b.length;d<e;d++){var f={},g=b[d].match(/^([^:]*):?([\\d\\.]*)/);f.color=a.getRGB(g[1]);if(f.color.error)return null;f.color=f.color.hex,g[2]&&(f.offset=g[2]+\"%\"),c.push(f)}for(d=1,e=c.length-1;d<e;d++)if(!c[d].offset){var h=Q(c[d-1].offset||0),i=0;for(var j=d+1;j<e;j++)if(c[j].offset){i=c[j].offset;break}i||(i=100,j=e),i=Q(i);var k=(i-h)/(j-d+1);for(;d<j;d++)h+=k,c[d].offset=h+\"%\"}return c}),bT=a._tear=function(a,b){a==b.top&&(b.top=a.prev),a==b.bottom&&(b.bottom=a.next),a.next&&(a.next.prev=a.prev),a.prev&&(a.prev.next=a.next)},bU=a._tofront=function(a,b){b.top!==a&&(bT(a,b),a.next=null,a.prev=b.top,b.top.next=a,b.top=a)},bV=a._toback=function(a,b){b.bottom!==a&&(bT(a,b),a.next=b.bottom,a.prev=null,b.bottom.prev=a,b.bottom=a)},bW=a._insertafter=function(a,b,c){bT(a,c),b==c.top&&(c.top=a),b.next&&(b.next.prev=a),a.next=b.next,a.prev=b,b.next=a},bX=a._insertbefore=function(a,b,c){bT(a,c),b==c.bottom&&(c.bottom=a),b.prev&&(b.prev.next=a),a.prev=b.prev,b.prev=a,a.next=b},bY=a.toMatrix=function(a,b){var c=bI(a),d={_:{transform:p},getBBox:function(){return c}};b$(d,b);return d.matrix},bZ=a.transformPath=function(a,b){return bj(a,bY(a,b))},b$=a._extractTransform=function(b,c){if(c==null)return b._.transform;c=r(c).replace(/\\.{3}|\\u2026/g,b._.transform||p);var d=a.parseTransformString(c),e=0,f=0,g=0,h=1,i=1,j=b._,k=new cb;j.transform=d||[];if(d)for(var l=0,m=d.length;l<m;l++){var n=d[l],o=n.length,q=r(n[0]).toLowerCase(),s=n[0]!=q,t=s?k.invert():0,u,v,w,x,y;q==\"t\"&&o==3?s?(u=t.x(0,0),v=t.y(0,0),w=t.x(n[1],n[2]),x=t.y(n[1],n[2]),k.translate(w-u,x-v)):k.translate(n[1],n[2]):q==\"r\"?o==2?(y=y||b.getBBox(1),k.rotate(n[1],y.x+y.width/2,y.y+y.height/2),e+=n[1]):o==4&&(s?(w=t.x(n[2],n[3]),x=t.y(n[2],n[3]),k.rotate(n[1],w,x)):k.rotate(n[1],n[2],n[3]),e+=n[1]):q==\"s\"?o==2||o==3?(y=y||b.getBBox(1),k.scale(n[1],n[o-1],y.x+y.width/2,y.y+y.height/2),h*=n[1],i*=n[o-1]):o==5&&(s?(w=t.x(n[3],n[4]),x=t.y(n[3],n[4]),k.scale(n[1],n[2],w,x)):k.scale(n[1],n[2],n[3],n[4]),h*=n[1],i*=n[2]):q==\"m\"&&o==7&&k.add(n[1],n[2],n[3],n[4],n[5],n[6]),j.dirtyT=1,b.matrix=k}b.matrix=k,j.sx=h,j.sy=i,j.deg=e,j.dx=f=k.e,j.dy=g=k.f,h==1&&i==1&&!e&&j.bbox?(j.bbox.x+=+f,j.bbox.y+=+g):j.dirtyT=1},b_=function(a){var b=a[0];switch(b.toLowerCase()){case\"t\":return[b,0,0];case\"m\":return[b,1,0,0,1,0,0];case\"r\":return a.length==4?[b,0,a[2],a[3]]:[b,0];case\"s\":return a.length==5?[b,1,1,a[3],a[4]]:a.length==3?[b,1,1]:[b,1]}},ca=a._equaliseTransform=function(b,c){c=r(c).replace(/\\.{3}|\\u2026/g,b),b=a.parseTransformString(b)||[],c=a.parseTransformString(c)||[];var d=x(b.length,c.length),e=[],f=[],g=0,h,i,j,k;for(;g<d;g++){j=b[g]||b_(c[g]),k=c[g]||b_(j);if(j[0]!=k[0]||j[0].toLowerCase()==\"r\"&&(j[2]!=k[2]||j[3]!=k[3])||j[0].toLowerCase()==\"s\"&&(j[3]!=k[3]||j[4]!=k[4]))return;e[g]=[],f[g]=[];for(h=0,i=x(j.length,k.length);h<i;h++)h in j&&(e[g][h]=j[h]),h in k&&(f[g][h]=k[h])}return{from:e,to:f}};a._getContainer=function(b,c,d,e){var f;f=e==null&&!a.is(b,\"object\")?h.doc.getElementById(b):b;if(f!=null){if(f.tagName)return c==null?{container:f,width:f.style.pixelWidth||f.offsetWidth,height:f.style.pixelHeight||f.offsetHeight}:{container:f,width:c,height:d};return{container:1,x:b,y:c,width:d,height:e}}},a.pathToRelative=bK,a._engine={},a.path2curve=bR,a.matrix=function(a,b,c,d,e,f){return new cb(a,b,c,d,e,f)},function(b){function d(a){var b=w.sqrt(c(a));a[0]&&(a[0]/=b),a[1]&&(a[1]/=b)}function c(a){return a[0]*a[0]+a[1]*a[1]}b.add=function(a,b,c,d,e,f){var g=[[],[],[]],h=[[this.a,this.c,this.e],[this.b,this.d,this.f],[0,0,1]],i=[[a,c,e],[b,d,f],[0,0,1]],j,k,l,m;a&&a instanceof cb&&(i=[[a.a,a.c,a.e],[a.b,a.d,a.f],[0,0,1]]);for(j=0;j<3;j++)for(k=0;k<3;k++){m=0;for(l=0;l<3;l++)m+=h[j][l]*i[l][k];g[j][k]=m}this.a=g[0][0],this.b=g[1][0],this.c=g[0][1],this.d=g[1][1],this.e=g[0][2],this.f=g[1][2]},b.invert=function(){var a=this,b=a.a*a.d-a.b*a.c;return new cb(a.d/b,-a.b/b,-a.c/b,a.a/b,(a.c*a.f-a.d*a.e)/b,(a.b*a.e-a.a*a.f)/b)},b.clone=function(){return new cb(this.a,this.b,this.c,this.d,this.e,this.f)},b.translate=function(a,b){this.add(1,0,0,1,a,b)},b.scale=function(a,b,c,d){b==null&&(b=a),(c||d)&&this.add(1,0,0,1,c,d),this.add(a,0,0,b,0,0),(c||d)&&this.add(1,0,0,1,-c,-d)},b.rotate=function(b,c,d){b=a.rad(b),c=c||0,d=d||0;var e=+w.cos(b).toFixed(9),f=+w.sin(b).toFixed(9);this.add(e,f,-f,e,c,d),this.add(1,0,0,1,-c,-d)},b.x=function(a,b){return a*this.a+b*this.c+this.e},b.y=function(a,b){return a*this.b+b*this.d+this.f},b.get=function(a){return+this[r.fromCharCode(97+a)].toFixed(4)},b.toString=function(){return a.svg?\"matrix(\"+[this.get(0),this.get(1),this.get(2),this.get(3),this.get(4),this.get(5)].join()+\")\":[this.get(0),this.get(2),this.get(1),this.get(3),0,0].join()},b.toFilter=function(){return\"progid:DXImageTransform.Microsoft.Matrix(M11=\"+this.get(0)+\", M12=\"+this.get(2)+\", M21=\"+this.get(1)+\", M22=\"+this.get(3)+\", Dx=\"+this.get(4)+\", Dy=\"+this.get(5)+\", sizingmethod='auto expand')\"},b.offset=function(){return[this.e.toFixed(4),this.f.toFixed(4)]},b.split=function(){var b={};b.dx=this.e,b.dy=this.f;var e=[[this.a,this.c],[this.b,this.d]];b.scalex=w.sqrt(c(e[0])),d(e[0]),b.shear=e[0][0]*e[1][0]+e[0][1]*e[1][1],e[1]=[e[1][0]-e[0][0]*b.shear,e[1][1]-e[0][1]*b.shear],b.scaley=w.sqrt(c(e[1])),d(e[1]),b.shear/=b.scaley;var f=-e[0][1],g=e[1][1];g<0?(b.rotate=a.deg(w.acos(g)),f<0&&(b.rotate=360-b.rotate)):b.rotate=a.deg(w.asin(f)),b.isSimple=!+b.shear.toFixed(9)&&(b.scalex.toFixed(9)==b.scaley.toFixed(9)||!b.rotate),b.isSuperSimple=!+b.shear.toFixed(9)&&b.scalex.toFixed(9)==b.scaley.toFixed(9)&&!b.rotate,b.noRotation=!+b.shear.toFixed(9)&&!b.rotate;return b},b.toTransformString=function(a){var b=a||this[s]();if(b.isSimple){b.scalex=+b.scalex.toFixed(4),b.scaley=+b.scaley.toFixed(4),b.rotate=+b.rotate.toFixed(4);return(b.dx||b.dy?\"t\"+[b.dx,b.dy]:p)+(b.scalex!=1||b.scaley!=1?\"s\"+[b.scalex,b.scaley,0,0]:p)+(b.rotate?\"r\"+[b.rotate,0,0]:p)}return\"m\"+[this.get(0),this.get(1),this.get(2),this.get(3),this.get(4),this.get(5)]}}(cb.prototype);var cc=navigator.userAgent.match(/Version\\/(.*?)\\s/)||navigator.userAgent.match(/Chrome\\/(\\d+)/);navigator.vendor==\"Apple Computer, Inc.\"&&(cc&&cc[1]<4||navigator.platform.slice(0,2)==\"iP\")||navigator.vendor==\"Google Inc.\"&&cc&&cc[1]<8?k.safari=function(){var a=this.rect(-99,-99,this.width+99,this.height+99).attr({stroke:\"none\"});setTimeout(function(){a.remove()})}:k.safari=be;var cd=function(){this.returnValue=!1},ce=function(){return this.originalEvent.preventDefault()},cf=function(){this.cancelBubble=!0},cg=function(){return this.originalEvent.stopPropagation()},ch=function(){if(h.doc.addEventListener)return function(a,b,c,d){var e=o&&u[b]?u[b]:b,f=function(e){var f=h.doc.documentElement.scrollTop||h.doc.body.scrollTop,i=h.doc.documentElement.scrollLeft||h.doc.body.scrollLeft,j=e.clientX+i,k=e.clientY+f;if(o&&u[g](b))for(var l=0,m=e.targetTouches&&e.targetTouches.length;l<m;l++)if(e.targetTouches[l].target==a){var n=e;e=e.targetTouches[l],e.originalEvent=n,e.preventDefault=ce,e.stopPropagation=cg;break}return c.call(d,e,j,k)};a.addEventListener(e,f,!1);return function(){a.removeEventListener(e,f,!1);return!0}};if(h.doc.attachEvent)return function(a,b,c,d){var e=function(a){a=a||h.win.event;var b=h.doc.documentElement.scrollTop||h.doc.body.scrollTop,e=h.doc.documentElement.scrollLeft||h.doc.body.scrollLeft,f=a.clientX+e,g=a.clientY+b;a.preventDefault=a.preventDefault||cd,a.stopPropagation=a.stopPropagation||cf;return c.call(d,a,f,g)};a.attachEvent(\"on\"+b,e);var f=function(){a.detachEvent(\"on\"+b,e);return!0};return f}}(),ci=[],cj=function(a){var b=a.clientX,c=a.clientY,d=h.doc.documentElement.scrollTop||h.doc.body.scrollTop,e=h.doc.documentElement.scrollLeft||h.doc.body.scrollLeft,f,g=ci.length;while(g--){f=ci[g];if(o){var i=a.touches.length,j;while(i--){j=a.touches[i];if(j.identifier==f.el._drag.id){b=j.clientX,c=j.clientY,(a.originalEvent?a.originalEvent:a).preventDefault();break}}}else a.preventDefault();var k=f.el.node,l,m=k.nextSibling,n=k.parentNode,p=k.style.display;h.win.opera&&n.removeChild(k),k.style.display=\"none\",l=f.el.paper.getElementByPoint(b,c),k.style.display=p,h.win.opera&&(m?n.insertBefore(k,m):n.appendChild(k)),l&&eve(\"raphael.drag.over.\"+f.el.id,f.el,l),b+=e,c+=d,eve(\"raphael.drag.move.\"+f.el.id,f.move_scope||f.el,b-f.el._drag.x,c-f.el._drag.y,b,c,a)}},ck=function(b){a.unmousemove(cj).unmouseup(ck);var c=ci.length,d;while(c--)d=ci[c],d.el._drag={},eve(\"raphael.drag.end.\"+d.el.id,d.end_scope||d.start_scope||d.move_scope||d.el,b);ci=[]},cl=a.el={};for(var cm=t.length;cm--;)(function(b){a[b]=cl[b]=function(c,d){a.is(c,\"function\")&&(this.events=this.events||[],this.events.push({name:b,f:c,unbind:ch(this.shape||this.node||h.doc,b,c,d||this)}));return this},a[\"un\"+b]=cl[\"un\"+b]=function(a){var c=this.events||[],d=c.length;while(d--)if(c[d].name==b&&c[d].f==a){c[d].unbind(),c.splice(d,1),!c.length&&delete this.events;return this}return this}})(t[cm]);cl.data=function(b,c){var d=bb[this.id]=bb[this.id]||{};if(arguments.length==1){if(a.is(b,\"object\")){for(var e in b)b[g](e)&&this.data(e,b[e]);return this}eve(\"raphael.data.get.\"+this.id,this,d[b],b);return d[b]}d[b]=c,eve(\"raphael.data.set.\"+this.id,this,c,b);return this},cl.removeData=function(a){a==null?bb[this.id]={}:bb[this.id]&&delete bb[this.id][a];return this},cl.hover=function(a,b,c,d){return this.mouseover(a,c).mouseout(b,d||c)},cl.unhover=function(a,b){return this.unmouseover(a).unmouseout(b)};var cn=[];cl.drag=function(b,c,d,e,f,g){function i(i){(i.originalEvent||i).preventDefault();var j=h.doc.documentElement.scrollTop||h.doc.body.scrollTop,k=h.doc.documentElement.scrollLeft||h.doc.body.scrollLeft;this._drag.x=i.clientX+k,this._drag.y=i.clientY+j,this._drag.id=i.identifier,!ci.length&&a.mousemove(cj).mouseup(ck),ci.push({el:this,move_scope:e,start_scope:f,end_scope:g}),c&&eve.on(\"raphael.drag.start.\"+this.id,c),b&&eve.on(\"raphael.drag.move.\"+this.id,b),d&&eve.on(\"raphael.drag.end.\"+this.id,d),eve(\"raphael.drag.start.\"+this.id,f||e||this,i.clientX+k,i.clientY+j,i)}this._drag={},cn.push({el:this,start:i}),this.mousedown(i);return this},cl.onDragOver=function(a){a?eve.on(\"raphael.drag.over.\"+this.id,a):eve.unbind(\"raphael.drag.over.\"+this.id)},cl.undrag=function(){var b=cn.length;while(b--)cn[b].el==this&&(this.unmousedown(cn[b].start),cn.splice(b,1),eve.unbind(\"raphael.drag.*.\"+this.id));!cn.length&&a.unmousemove(cj).unmouseup(ck)},k.circle=function(b,c,d){var e=a._engine.circle(this,b||0,c||0,d||0);this.__set__&&this.__set__.push(e);return e},k.rect=function(b,c,d,e,f){var g=a._engine.rect(this,b||0,c||0,d||0,e||0,f||0);this.__set__&&this.__set__.push(g);return g},k.ellipse=function(b,c,d,e){var f=a._engine.ellipse(this,b||0,c||0,d||0,e||0);this.__set__&&this.__set__.push(f);return f},k.path=function(b){b&&!a.is(b,D)&&!a.is(b[0],E)&&(b+=p);var c=a._engine.path(a.format[m](a,arguments),this);this.__set__&&this.__set__.push(c);return c},k.image=function(b,c,d,e,f){var g=a._engine.image(this,b||\"about:blank\",c||0,d||0,e||0,f||0);this.__set__&&this.__set__.push(g);return g},k.text=function(b,c,d){var e=a._engine.text(this,b||0,c||0,r(d));this.__set__&&this.__set__.push(e);return e},k.set=function(b){!a.is(b,\"array\")&&(b=Array.prototype.splice.call(arguments,0,arguments.length));var c=new cG(b);this.__set__&&this.__set__.push(c);return c},k.setStart=function(a){this.__set__=a||this.set()},k.setFinish=function(a){var b=this.__set__;delete this.__set__;return b},k.setSize=function(b,c){return a._engine.setSize.call(this,b,c)},k.setViewBox=function(b,c,d,e,f){return a._engine.setViewBox.call(this,b,c,d,e,f)},k.top=k.bottom=null,k.raphael=a;var co=function(a){var b=a.getBoundingClientRect(),c=a.ownerDocument,d=c.body,e=c.documentElement,f=e.clientTop||d.clientTop||0,g=e.clientLeft||d.clientLeft||0,i=b.top+(h.win.pageYOffset||e.scrollTop||d.scrollTop)-f,j=b.left+(h.win.pageXOffset||e.scrollLeft||d.scrollLeft)-g;return{y:i,x:j}};k.getElementByPoint=function(a,b){var c=this,d=c.canvas,e=h.doc.elementFromPoint(a,b);if(h.win.opera&&e.tagName==\"svg\"){var f=co(d),g=d.createSVGRect();g.x=a-f.x,g.y=b-f.y,g.width=g.height=1;var i=d.getIntersectionList(g,null);i.length&&(e=i[i.length-1])}if(!e)return null;while(e.parentNode&&e!=d.parentNode&&!e.raphael)e=e.parentNode;e==c.canvas.parentNode&&(e=d),e=e&&e.raphael?c.getById(e.raphaelid):null;return e},k.getById=function(a){var b=this.bottom;while(b){if(b.id==a)return b;b=b.next}return null},k.forEach=function(a,b){var c=this.bottom;while(c){if(a.call(b,c)===!1)return this;c=c.next}return this},k.getElementsByPoint=function(a,b){var c=this.set();this.forEach(function(d){d.isPointInside(a,b)&&c.push(d)});return c},cl.isPointInside=function(b,c){var d=this.realPath=this.realPath||bi[this.type](this);return a.isPointInsidePath(d,b,c)},cl.getBBox=function(a){if(this.removed)return{};var b=this._;if(a){if(b.dirty||!b.bboxwt)this.realPath=bi[this.type](this),b.bboxwt=bI(this.realPath),b.bboxwt.toString=cq,b.dirty=0;return bm(b.bboxwt)}if(b.dirty||b.dirtyT||!b.bbox){if(b.dirty||!this.realPath)b.bboxwt=0,this.realPath=bi[this.type](this);b.bbox=bI(bj(this.realPath,this.matrix)),b.bbox.toString=cq,b.dirty=b.dirtyT=0}return bm(b.bbox)},cl.getBBoxWOTransform=function(){return this.getBBox(1)},cl.clone=function(){if(this.removed)return null;var a=this.paper[this.type]().attr(this.attr());this.__set__&&this.__set__.push(a);return a},cl.glow=function(a){if(this.type==\"text\")return null;a=a||{};var b={width:(a.width||10)+(+this.attr(\"stroke-width\")||1),fill:a.fill||!1,opacity:a.opacity||.5,offsetx:a.offsetx||0,offsety:a.offsety||0,color:a.color||\"#000\"},c=b.width/2,d=this.paper,e=d.set(),f=this.realPath||bi[this.type](this);f=this.matrix?bj(f,this.matrix):f;for(var g=1;g<c+1;g++)e.push(d.path(f).attr({stroke:b.color,fill:b.fill?b.color:\"none\",\"stroke-linejoin\":\"round\",\"stroke-linecap\":\"round\",\"stroke-width\":+(b.width/c*g).toFixed(3),opacity:+(b.opacity/c).toFixed(3)}));return e.insertBefore(this).translate(b.offsetx,b.offsety)};var cr={},cs=function(b,c,d,e,f,g,h,i,j){return j==null?bB(b,c,d,e,f,g,h,i):a.findDotsAtSegment(b,c,d,e,f,g,h,i,bC(b,c,d,e,f,g,h,i,j))},ct=function(b,c){return function(d,e,f){d=bR(d);var g,h,i,j,k=\"\",l={},m,n=0;for(var o=0,p=d.length;o<p;o++){i=d[o];if(i[0]==\"M\")g=+i[1],h=+i[2];else{j=cs(g,h,i[1],i[2],i[3],i[4],i[5],i[6]);if(n+j>e){if(c&&!l.start){m=cs(g,h,i[1],i[2],i[3],i[4],i[5],i[6],e-n),k+=[\"C\"+m.start.x,m.start.y,m.m.x,m.m.y,m.x,m.y];if(f)return k;l.start=k,k=[\"M\"+m.x,m.y+\"C\"+m.n.x,m.n.y,m.end.x,m.end.y,i[5],i[6]].join(),n+=j,g=+i[5],h=+i[6];continue}if(!b&&!c){m=cs(g,h,i[1],i[2],i[3],i[4],i[5],i[6],e-n);return{x:m.x,y:m.y,alpha:m.alpha}}}n+=j,g=+i[5],h=+i[6]}k+=i.shift()+i}l.end=k,m=b?n:c?l:a.findDotsAtSegment(g,h,i[0],i[1],i[2],i[3],i[4],i[5],1),m.alpha&&(m={x:m.x,y:m.y,alpha:m.alpha});return m}},cu=ct(1),cv=ct(),cw=ct(0,1);a.getTotalLength=cu,a.getPointAtLength=cv,a.getSubpath=function(a,b,c){if(this.getTotalLength(a)-c<1e-6)return cw(a,b).end;var d=cw(a,c,1);return b?cw(d,b).end:d},cl.getTotalLength=function(){if(this.type==\"path\"){if(this.node.getTotalLength)return this.node.getTotalLength();return cu(this.attrs.path)}},cl.getPointAtLength=function(a){if(this.type==\"path\")return cv(this.attrs.path,a)},cl.getSubpath=function(b,c){if(this.type==\"path\")return a.getSubpath(this.attrs.path,b,c)};var cx=a.easing_formulas={linear:function(a){return a},\"<\":function(a){return A(a,1.7)},\">\":function(a){return A(a,.48)},\"<>\":function(a){var b=.48-a/1.04,c=w.sqrt(.1734+b*b),d=c-b,e=A(z(d),1/3)*(d<0?-1:1),f=-c-b,g=A(z(f),1/3)*(f<0?-1:1),h=e+g+.5;return(1-h)*3*h*h+h*h*h},backIn:function(a){var b=1.70158;return a*a*((b+1)*a-b)},backOut:function(a){a=a-1;var b=1.70158;return a*a*((b+1)*a+b)+1},elastic:function(a){if(a==!!a)return a;return A(2,-10*a)*w.sin((a-.075)*2*B/.3)+1},bounce:function(a){var b=7.5625,c=2.75,d;a<1/c?d=b*a*a:a<2/c?(a-=1.5/c,d=b*a*a+.75):a<2.5/c?(a-=2.25/c,d=b*a*a+.9375):(a-=2.625/c,d=b*a*a+.984375);return d}};cx.easeIn=cx[\"ease-in\"]=cx[\"<\"],cx.easeOut=cx[\"ease-out\"]=cx[\">\"],cx.easeInOut=cx[\"ease-in-out\"]=cx[\"<>\"],cx[\"back-in\"]=cx.backIn,cx[\"back-out\"]=cx.backOut;var cy=[],cz=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(a){setTimeout(a,16)},cA=function(){var b=+(new Date),c=0;for(;c<cy.length;c++){var d=cy[c];if(d.el.removed||d.paused)continue;var e=b-d.start,f=d.ms,h=d.easing,i=d.from,j=d.diff,k=d.to,l=d.t,m=d.el,o={},p,r={},s;d.initstatus?(e=(d.initstatus*d.anim.top-d.prev)/(d.percent-d.prev)*f,d.status=d.initstatus,delete d.initstatus,d.stop&&cy.splice(c--,1)):d.status=(d.prev+(d.percent-d.prev)*(e/f))/d.anim.top;if(e<0)continue;if(e<f){var t=h(e/f);for(var u in i)if(i[g](u)){switch(U[u]){case C:p=+i[u]+t*f*j[u];break;case\"colour\":p=\"rgb(\"+[cB(O(i[u].r+t*f*j[u].r)),cB(O(i[u].g+t*f*j[u].g)),cB(O(i[u].b+t*f*j[u].b))].join(\",\")+\")\";break;case\"path\":p=[];for(var v=0,w=i[u].length;v<w;v++){p[v]=[i[u][v][0]];for(var x=1,y=i[u][v].length;x<y;x++)p[v][x]=+i[u][v][x]+t*f*j[u][v][x];p[v]=p[v].join(q)}p=p.join(q);break;case\"transform\":if(j[u].real){p=[];for(v=0,w=i[u].length;v<w;v++){p[v]=[i[u][v][0]];for(x=1,y=i[u][v].length;x<y;x++)p[v][x]=i[u][v][x]+t*f*j[u][v][x]}}else{var z=function(a){return+i[u][a]+t*f*j[u][a]};p=[[\"m\",z(0),z(1),z(2),z(3),z(4),z(5)]]}break;case\"csv\":if(u==\"clip-rect\"){p=[],v=4;while(v--)p[v]=+i[u][v]+t*f*j[u][v]}break;default:var A=[][n](i[u]);p=[],v=m.paper.customAttributes[u].length;while(v--)p[v]=+A[v]+t*f*j[u][v]}o[u]=p}m.attr(o),function(a,b,c){setTimeout(function(){eve(\"raphael.anim.frame.\"+a,b,c)})}(m.id,m,d.anim)}else{(function(b,c,d){setTimeout(function(){eve(\"raphael.anim.frame.\"+c.id,c,d),eve(\"raphael.anim.finish.\"+c.id,c,d),a.is(b,\"function\")&&b.call(c)})})(d.callback,m,d.anim),m.attr(k),cy.splice(c--,1);if(d.repeat>1&&!d.next){for(s in k)k[g](s)&&(r[s]=d.totalOrigin[s]);d.el.attr(r),cE(d.anim,d.el,d.anim.percents[0],null,d.totalOrigin,d.repeat-1)}d.next&&!d.stop&&cE(d.anim,d.el,d.next,null,d.totalOrigin,d.repeat)}}a.svg&&m&&m.paper&&m.paper.safari(),cy.length&&cz(cA)},cB=function(a){return a>255?255:a<0?0:a};cl.animateWith=function(b,c,d,e,f,g){var h=this;if(h.removed){g&&g.call(h);return h}var i=d instanceof cD?d:a.animation(d,e,f,g),j,k;cE(i,h,i.percents[0],null,h.attr());for(var l=0,m=cy.length;l<m;l++)if(cy[l].anim==c&&cy[l].el==b){cy[m-1].start=cy[l].start;break}return h},cl.onAnimation=function(a){a?eve.on(\"raphael.anim.frame.\"+this.id,a):eve.unbind(\"raphael.anim.frame.\"+this.id);return this},cD.prototype.delay=function(a){var b=new cD(this.anim,this.ms);b.times=this.times,b.del=+a||0;return b},cD.prototype.repeat=function(a){var b=new cD(this.anim,this.ms);b.del=this.del,b.times=w.floor(x(a,0))||1;return b},a.animation=function(b,c,d,e){if(b instanceof cD)return b;if(a.is(d,\"function\")||!d)e=e||d||null,d=null;b=Object(b),c=+c||0;var f={},h,i;for(i in b)b[g](i)&&Q(i)!=i&&Q(i)+\"%\"!=i&&(h=!0,f[i]=b[i]);if(!h)return new cD(b,c);d&&(f.easing=d),e&&(f.callback=e);return new cD({100:f},c)},cl.animate=function(b,c,d,e){var f=this;if(f.removed){e&&e.call(f);return f}var g=b instanceof cD?b:a.animation(b,c,d,e);cE(g,f,g.percents[0],null,f.attr());return f},cl.setTime=function(a,b){a&&b!=null&&this.status(a,y(b,a.ms)/a.ms);return this},cl.status=function(a,b){var c=[],d=0,e,f;if(b!=null){cE(a,this,-1,y(b,1));return this}e=cy.length;for(;d<e;d++){f=cy[d];if(f.el.id==this.id&&(!a||f.anim==a)){if(a)return f.status;c.push({anim:f.anim,status:f.status})}}if(a)return 0;return c},cl.pause=function(a){for(var b=0;b<cy.length;b++)cy[b].el.id==this.id&&(!a||cy[b].anim==a)&&eve(\"raphael.anim.pause.\"+this.id,this,cy[b].anim)!==!1&&(cy[b].paused=!0);return this},cl.resume=function(a){for(var b=0;b<cy.length;b++)if(cy[b].el.id==this.id&&(!a||cy[b].anim==a)){var c=cy[b];eve(\"raphael.anim.resume.\"+this.id,this,c.anim)!==!1&&(delete c.paused,this.status(c.anim,c.status))}return this},cl.stop=function(a){for(var b=0;b<cy.length;b++)cy[b].el.id==this.id&&(!a||cy[b].anim==a)&&eve(\"raphael.anim.stop.\"+this.id,this,cy[b].anim)!==!1&&cy.splice(b--,1);return this},eve.on(\"raphael.remove\",cF),eve.on(\"raphael.clear\",cF),cl.toString=function(){return\"Raphaël’s object\"};var cG=function(a){this.items=[],this.length=0,this.type=\"set\";if(a)for(var b=0,c=a.length;b<c;b++)a[b]&&(a[b].constructor==cl.constructor||a[b].constructor==cG)&&(this[this.items.length]=this.items[this.items.length]=a[b],this.length++)},cH=cG.prototype;cH.push=function(){var a,b;for(var c=0,d=arguments.length;c<d;c++)a=arguments[c],a&&(a.constructor==cl.constructor||a.constructor==cG)&&(b=this.items.length,this[b]=this.items[b]=a,this.length++);return this},cH.pop=function(){this.length&&delete this[this.length--];return this.items.pop()},cH.forEach=function(a,b){for(var c=0,d=this.items.length;c<d;c++)if(a.call(b,this.items[c],c)===!1)return this;return this};for(var cI in cl)cl[g](cI)&&(cH[cI]=function(a){return function(){var b=arguments;return this.forEach(function(c){c[a][m](c,b)})}}(cI));cH.attr=function(b,c){if(b&&a.is(b,E)&&a.is(b[0],\"object\"))for(var d=0,e=b.length;d<e;d++)this.items[d].attr(b[d]);else for(var f=0,g=this.items.length;f<g;f++)this.items[f].attr(b,c);return this},cH.clear=function(){while(this.length)this.pop()},cH.splice=function(a,b,c){a=a<0?x(this.length+a,0):a,b=x(0,y(this.length-a,b));var d=[],e=[],f=[],g;for(g=2;g<arguments.length;g++)f.push(arguments[g]);for(g=0;g<b;g++)e.push(this[a+g]);for(;g<this.length-a;g++)d.push(this[a+g]);var h=f.length;for(g=0;g<h+d.length;g++)this.items[a+g]=this[a+g]=g<h?f[g]:d[g-h];g=this.items.length=this.length-=b-h;while(this[g])delete this[g++];return new cG(e)},cH.exclude=function(a){for(var b=0,c=this.length;b<c;b++)if(this[b]==a){this.splice(b,1);return!0}},cH.animate=function(b,c,d,e){(a.is(d,\"function\")||!d)&&(e=d||null);var f=this.items.length,g=f,h,i=this,j;if(!f)return this;e&&(j=function(){!--f&&e.call(i)}),d=a.is(d,D)?d:j;var k=a.animation(b,c,d,j);h=this.items[--g].animate(k);while(g--)this.items[g]&&!this.items[g].removed&&this.items[g].animateWith(h,k,k);return this},cH.insertAfter=function(a){var b=this.items.length;while(b--)this.items[b].insertAfter(a);return this},cH.getBBox=function(){var a=[],b=[],c=[],d=[];for(var e=this.items.length;e--;)if(!this.items[e].removed){var f=this.items[e].getBBox();a.push(f.x),b.push(f.y),c.push(f.x+f.width),d.push(f.y+f.height)}a=y[m](0,a),b=y[m](0,b),c=x[m](0,c),d=x[m](0,d);return{x:a,y:b,x2:c,y2:d,width:c-a,height:d-b}},cH.clone=function(a){a=new cG;for(var b=0,c=this.items.length;b<c;b++)a.push(this.items[b].clone());return a},cH.toString=function(){return\"Raphaël‘s set\"},a.registerFont=function(a){if(!a.face)return a;this.fonts=this.fonts||{};var b={w:a.w,face:{},glyphs:{}},c=a.face[\"font-family\"];for(var d in a.face)a.face[g](d)&&(b.face[d]=a.face[d]);this.fonts[c]?this.fonts[c].push(b):this.fonts[c]=[b];if(!a.svg){b.face[\"units-per-em\"]=R(a.face[\"units-per-em\"],10);for(var e in a.glyphs)if(a.glyphs[g](e)){var f=a.glyphs[e];b.glyphs[e]={w:f.w,k:{},d:f.d&&\"M\"+f.d.replace(/[mlcxtrv]/g,function(a){return{l:\"L\",c:\"C\",x:\"z\",t:\"m\",r:\"l\",v:\"c\"}[a]||\"M\"})+\"z\"};if(f.k)for(var h in f.k)f[g](h)&&(b.glyphs[e].k[h]=f.k[h])}}return a},k.getFont=function(b,c,d,e){e=e||\"normal\",d=d||\"normal\",c=+c||{normal:400,bold:700,lighter:300,bolder:800}[c]||400;if(!!a.fonts){var f=a.fonts[b];if(!f){var h=new RegExp(\"(^|\\\\s)\"+b.replace(/[^\\w\\d\\s+!~.:_-]/g,p)+\"(\\\\s|$)\",\"i\");for(var i in a.fonts)if(a.fonts[g](i)&&h.test(i)){f=a.fonts[i];break}}var j;if(f)for(var k=0,l=f.length;k<l;k++){j=f[k];if(j.face[\"font-weight\"]==c&&(j.face[\"font-style\"]==d||!j.face[\"font-style\"])&&j.face[\"font-stretch\"]==e)break}return j}},k.print=function(b,d,e,f,g,h,i){h=h||\"middle\",i=x(y(i||0,1),-1);var j=r(e)[s](p),k=0,l=0,m=p,n;a.is(f,e)&&(f=this.getFont(f));if(f){n=(g||16)/f.face[\"units-per-em\"];var o=f.face.bbox[s](c),q=+o[0],t=o[3]-o[1],u=0,v=+o[1]+(h==\"baseline\"?t+ +f.face.descent:t/2);for(var w=0,z=j.length;w<z;w++){if(j[w]==\"\\n\")k=0,B=0,l=0,u+=t;else{var A=l&&f.glyphs[j[w-1]]||{},B=f.glyphs[j[w]];k+=l?(A.w||f.w)+(A.k&&A.k[j[w]]||0)+f.w*i:0,l=1}B&&B.d&&(m+=a.transformPath(B.d,[\"t\",k*n,u*n,\"s\",n,n,q,v,\"t\",(b-q)/n,(d-v)/n]))}}return this.path(m).attr({fill:\"#000\",stroke:\"none\"})},k.add=function(b){if(a.is(b,\"array\")){var c=this.set(),e=0,f=b.length,h;for(;e<f;e++)h=b[e]||{},d[g](h.type)&&c.push(this[h.type]().attr(h))}return c},a.format=function(b,c){var d=a.is(c,E)?[0][n](c):arguments;b&&a.is(b,D)&&d.length-1&&(b=b.replace(e,function(a,b){return d[++b]==null?p:d[b]}));return b||p},a.fullfill=function(){var a=/\\{([^\\}]+)\\}/g,b=/(?:(?:^|\\.)(.+?)(?=\\[|\\.|$|\\()|\\[('|\")(.+?)\\2\\])(\\(\\))?/g,c=function(a,c,d){var e=d;c.replace(b,function(a,b,c,d,f){b=b||d,e&&(b in e&&(e=e[b]),typeof e==\"function\"&&f&&(e=e()))}),e=(e==null||e==d?a:e)+\"\";return e};return function(b,d){return String(b).replace(a,function(a,b){return c(a,b,d)})}}(),a.ninja=function(){i.was?h.win.Raphael=i.is:delete Raphael;return a},a.st=cH,function(b,c,d){function e(){/in/.test(b.readyState)?setTimeout(e,9):a.eve(\"raphael.DOMload\")}b.readyState==null&&b.addEventListener&&(b.addEventListener(c,d=function(){b.removeEventListener(c,d,!1),b.readyState=\"complete\"},!1),b.readyState=\"loading\"),e()}(document,\"DOMContentLoaded\"),i.was?h.win.Raphael=a:Raphael=a,eve.on(\"raphael.DOMload\",function(){b=!0})}(),window.Raphael.svg&&function(a){var b=\"hasOwnProperty\",c=String,d=parseFloat,e=parseInt,f=Math,g=f.max,h=f.abs,i=f.pow,j=/[, ]+/,k=a.eve,l=\"\",m=\" \",n=\"http://www.w3.org/1999/xlink\",o={block:\"M5,0 0,2.5 5,5z\",classic:\"M5,0 0,2.5 5,5 3.5,3 3.5,2z\",diamond:\"M2.5,0 5,2.5 2.5,5 0,2.5z\",open:\"M6,1 1,3.5 6,6\",oval:\"M2.5,0A2.5,2.5,0,0,1,2.5,5 2.5,2.5,0,0,1,2.5,0z\"},p={};a.toString=function(){return\"Your browser supports SVG.\\nYou are running Raphaël \"+this.version};var q=function(d,e){if(e){typeof d==\"string\"&&(d=q(d));for(var f in e)e[b](f)&&(f.substring(0,6)==\"xlink:\"?d.setAttributeNS(n,f.substring(6),c(e[f])):d.setAttribute(f,c(e[f])))}else d=a._g.doc.createElementNS(\"http://www.w3.org/2000/svg\",d),d.style&&(d.style.webkitTapHighlightColor=\"rgba(0,0,0,0)\");return d},r=function(b,e){var j=\"linear\",k=b.id+e,m=.5,n=.5,o=b.node,p=b.paper,r=o.style,s=a._g.doc.getElementById(k);if(!s){e=c(e).replace(a._radial_gradient,function(a,b,c){j=\"radial\";if(b&&c){m=d(b),n=d(c);var e=(n>.5)*2-1;i(m-.5,2)+i(n-.5,2)>.25&&(n=f.sqrt(.25-i(m-.5,2))*e+.5)&&n!=.5&&(n=n.toFixed(5)-1e-5*e)}return l}),e=e.split(/\\s*\\-\\s*/);if(j==\"linear\"){var t=e.shift();t=-d(t);if(isNaN(t))return null;var u=[0,0,f.cos(a.rad(t)),f.sin(a.rad(t))],v=1/(g(h(u[2]),h(u[3]))||1);u[2]*=v,u[3]*=v,u[2]<0&&(u[0]=-u[2],u[2]=0),u[3]<0&&(u[1]=-u[3],u[3]=0)}var w=a._parseDots(e);if(!w)return null;k=k.replace(/[\\(\\)\\s,\\xb0#]/g,\"_\"),b.gradient&&k!=b.gradient.id&&(p.defs.removeChild(b.gradient),delete b.gradient);if(!b.gradient){s=q(j+\"Gradient\",{id:k}),b.gradient=s,q(s,j==\"radial\"?{fx:m,fy:n}:{x1:u[0],y1:u[1],x2:u[2],y2:u[3],gradientTransform:b.matrix.invert()}),p.defs.appendChild(s);for(var x=0,y=w.length;x<y;x++)s.appendChild(q(\"stop\",{offset:w[x].offset?w[x].offset:x?\"100%\":\"0%\",\"stop-color\":w[x].color||\"#fff\"}))}}q(o,{fill:\"url(#\"+k+\")\",opacity:1,\"fill-opacity\":1}),r.fill=l,r.opacity=1,r.fillOpacity=1;return 1},s=function(a){var b=a.getBBox(1);q(a.pattern,{patternTransform:a.matrix.invert()+\" translate(\"+b.x+\",\"+b.y+\")\"})},t=function(d,e,f){if(d.type==\"path\"){var g=c(e).toLowerCase().split(\"-\"),h=d.paper,i=f?\"end\":\"start\",j=d.node,k=d.attrs,m=k[\"stroke-width\"],n=g.length,r=\"classic\",s,t,u,v,w,x=3,y=3,z=5;while(n--)switch(g[n]){case\"block\":case\"classic\":case\"oval\":case\"diamond\":case\"open\":case\"none\":r=g[n];break;case\"wide\":y=5;break;case\"narrow\":y=2;break;case\"long\":x=5;break;case\"short\":x=2}r==\"open\"?(x+=2,y+=2,z+=2,u=1,v=f?4:1,w={fill:\"none\",stroke:k.stroke}):(v=u=x/2,w={fill:k.stroke,stroke:\"none\"}),d._.arrows?f?(d._.arrows.endPath&&p[d._.arrows.endPath]--,d._.arrows.endMarker&&p[d._.arrows.endMarker]--):(d._.arrows.startPath&&p[d._.arrows.startPath]--,d._.arrows.startMarker&&p[d._.arrows.startMarker]--):d._.arrows={};if(r!=\"none\"){var A=\"raphael-marker-\"+r,B=\"raphael-marker-\"+i+r+x+y;a._g.doc.getElementById(A)?p[A]++:(h.defs.appendChild(q(q(\"path\"),{\"stroke-linecap\":\"round\",d:o[r],id:A})),p[A]=1);var C=a._g.doc.getElementById(B),D;C?(p[B]++,D=C.getElementsByTagName(\"use\")[0]):(C=q(q(\"marker\"),{id:B,markerHeight:y,markerWidth:x,orient:\"auto\",refX:v,refY:y/2}),D=q(q(\"use\"),{\"xlink:href\":\"#\"+A,transform:(f?\"rotate(180 \"+x/2+\" \"+y/2+\") \":l)+\"scale(\"+x/z+\",\"+y/z+\")\",\"stroke-width\":(1/((x/z+y/z)/2)).toFixed(4)}),C.appendChild(D),h.defs.appendChild(C),p[B]=1),q(D,w);var F=u*(r!=\"diamond\"&&r!=\"oval\");f?(s=d._.arrows.startdx*m||0,t=a.getTotalLength(k.path)-F*m):(s=F*m,t=a.getTotalLength(k.path)-(d._.arrows.enddx*m||0)),w={},w[\"marker-\"+i]=\"url(#\"+B+\")\";if(t||s)w.d=Raphael.getSubpath(k.path,s,t);q(j,w),d._.arrows[i+\"Path\"]=A,d._.arrows[i+\"Marker\"]=B,d._.arrows[i+\"dx\"]=F,d._.arrows[i+\"Type\"]=r,d._.arrows[i+\"String\"]=e}else f?(s=d._.arrows.startdx*m||0,t=a.getTotalLength(k.path)-s):(s=0,t=a.getTotalLength(k.path)-(d._.arrows.enddx*m||0)),d._.arrows[i+\"Path\"]&&q(j,{d:Raphael.getSubpath(k.path,s,t)}),delete d._.arrows[i+\"Path\"],delete d._.arrows[i+\"Marker\"],delete d._.arrows[i+\"dx\"],delete d._.arrows[i+\"Type\"],delete d._.arrows[i+\"String\"];for(w in p)if(p[b](w)&&!p[w]){var G=a._g.doc.getElementById(w);G&&G.parentNode.removeChild(G)}}},u={\"\":[0],none:[0],\"-\":[3,1],\".\":[1,1],\"-.\":[3,1,1,1],\"-..\":[3,1,1,1,1,1],\". \":[1,3],\"- \":[4,3],\"--\":[8,3],\"- .\":[4,3,1,3],\"--.\":[8,3,1,3],\"--..\":[8,3,1,3,1,3]},v=function(a,b,d){b=u[c(b).toLowerCase()];if(b){var e=a.attrs[\"stroke-width\"]||\"1\",f={round:e,square:e,butt:0}[a.attrs[\"stroke-linecap\"]||d[\"stroke-linecap\"]]||0,g=[],h=b.length;while(h--)g[h]=b[h]*e+(h%2?1:-1)*f;q(a.node,{\"stroke-dasharray\":g.join(\",\")})}};k.on(\"raphael.util.attr.blur\",function(a){this.blur(a)}),k.on(\"raphael.util.attr.cursor\",function(a){this.node.style.cursor=a});var w=function(d,f){var i=d.node,m=d.attrs,o=i.style.visibility;i.style.visibility=\"hidden\";for(var p in f){k(\"raphael.util.attr.\"+p,d,f[p]);if(f[b](p)){if(!a._availableAttrs[b](p))continue;var u=f[p];m[p]=u;switch(p){case\"blur\":d.blur(u);break;case\"href\":case\"title\":case\"target\":var w=i.parentNode;if(w.tagName.toLowerCase()!=\"a\"){var x=q(\"a\");w.insertBefore(x,i),x.appendChild(i),w=x}p==\"target\"?w.setAttributeNS(n,\"show\",u==\"blank\"?\"new\":u):w.setAttributeNS(n,p,u);break;case\"cursor\":break;case\"transform\":d.transform(u);break;case\"arrow-start\":t(d,u);break;case\"arrow-end\":t(d,u,1);break;case\"clip-rect\":var z=c(u).split(j);if(z.length==4){d.clip&&d.clip.parentNode.parentNode.removeChild(d.clip.parentNode);var A=q(\"clipPath\"),B=q(\"rect\");A.id=a.createUUID(),q(B,{x:z[0],y:z[1],width:z[2],height:z[3]}),A.appendChild(B),d.paper.defs.appendChild(A),q(i,{\"clip-path\":\"url(#\"+A.id+\")\"}),d.clip=B}if(!u){var C=i.getAttribute(\"clip-path\");if(C){var D=a._g.doc.getElementById(C.replace(/(^url\\(#|\\)$)/g,l));D&&D.parentNode.removeChild(D),q(i,{\"clip-path\":l}),delete d.clip}}break;case\"path\":d.type==\"path\"&&(q(i,{d:u?m.path=a._pathToAbsolute(u):\"M0,0\"}),d._.dirty=1,d._.arrows&&(\"startString\"in d._.arrows&&t(d,d._.arrows.startString),\"endString\"in d._.arrows&&t(d,d._.arrows.endString,1)));break;case\"width\":i.setAttribute(p,u),d._.dirty=1;if(m.fx)p=\"x\",u=m.x;else break;case\"x\":m.fx&&(u=-m.x-(m.width||0));case\"rx\":if(p==\"rx\"&&d.type==\"rect\")break;case\"cx\":i.setAttribute(p,u),d.pattern&&s(d),d._.dirty=1;break;case\"height\":i.setAttribute(p,u),d._.dirty=1;if(m.fy)p=\"y\",u=m.y;else break;case\"y\":m.fy&&(u=-m.y-(m.height||0));case\"ry\":if(p==\"ry\"&&d.type==\"rect\")break;case\"cy\":i.setAttribute(p,u),d.pattern&&s(d),d._.dirty=1;break;case\"r\":d.type==\"rect\"?q(i,{rx:u,ry:u}):i.setAttribute(p,u),d._.dirty=1;break;case\"src\":d.type==\"image\"&&i.setAttributeNS(n,\"href\",u);break;case\"stroke-width\":if(d._.sx!=1||d._.sy!=1)u/=g(h(d._.sx),h(d._.sy))||1;d.paper._vbSize&&(u*=d.paper._vbSize),i.setAttribute(p,u),m[\"stroke-dasharray\"]&&v(d,m[\"stroke-dasharray\"],f),d._.arrows&&(\"startString\"in d._.arrows&&t(d,d._.arrows.startString),\"endString\"in d._.arrows&&t(d,d._.arrows.endString,1));break;case\"stroke-dasharray\":v(d,u,f);break;case\"fill\":var F=c(u).match(a._ISURL);if(F){A=q(\"pattern\");var G=q(\"image\");A.id=a.createUUID(),q(A,{x:0,y:0,patternUnits:\"userSpaceOnUse\",height:1,width:1}),q(G,{x:0,y:0,\"xlink:href\":F[1]}),A.appendChild(G),function(b){a._preload(F[1],function(){var a=this.offsetWidth,c=this.offsetHeight;q(b,{width:a,height:c}),q(G,{width:a,height:c}),d.paper.safari()})}(A),d.paper.defs.appendChild(A),q(i,{fill:\"url(#\"+A.id+\")\"}),d.pattern=A,d.pattern&&s(d);break}var H=a.getRGB(u);if(!H.error)delete f.gradient,delete m.gradient,!a.is(m.opacity,\"undefined\")&&a.is(f.opacity,\"undefined\")&&q(i,{opacity:m.opacity}),!a.is(m[\"fill-opacity\"],\"undefined\")&&a.is(f[\"fill-opacity\"],\"undefined\")&&q(i,{\"fill-opacity\":m[\"fill-opacity\"]});else if((d.type==\"circle\"||d.type==\"ellipse\"||c(u).charAt()!=\"r\")&&r(d,u)){if(\"opacity\"in m||\"fill-opacity\"in m){var I=a._g.doc.getElementById(i.getAttribute(\"fill\").replace(/^url\\(#|\\)$/g,l));if(I){var J=I.getElementsByTagName(\"stop\");q(J[J.length-1],{\"stop-opacity\":(\"opacity\"in m?m.opacity:1)*(\"fill-opacity\"in m?m[\"fill-opacity\"]:1)})}}m.gradient=u,m.fill=\"none\";break}H[b](\"opacity\")&&q(i,{\"fill-opacity\":H.opacity>1?H.opacity/100:H.opacity});case\"stroke\":H=a.getRGB(u),i.setAttribute(p,H.hex),p==\"stroke\"&&H[b](\"opacity\")&&q(i,{\"stroke-opacity\":H.opacity>1?H.opacity/100:H.opacity}),p==\"stroke\"&&d._.arrows&&(\"startString\"in d._.arrows&&t(d,d._.arrows.startString),\"endString\"in d._.arrows&&t(d,d._.arrows.endString,1));break;case\"gradient\":(d.type==\"circle\"||d.type==\"ellipse\"||c(u).charAt()!=\"r\")&&r(d,u);break;case\"opacity\":m.gradient&&!m[b](\"stroke-opacity\")&&q(i,{\"stroke-opacity\":u>1?u/100:u});case\"fill-opacity\":if(m.gradient){I=a._g.doc.getElementById(i.getAttribute(\"fill\").replace(/^url\\(#|\\)$/g,l)),I&&(J=I.getElementsByTagName(\"stop\"),q(J[J.length-1],{\"stop-opacity\":u}));break};default:p==\"font-size\"&&(u=e(u,10)+\"px\");var K=p.replace(/(\\-.)/g,function(a){return a.substring(1).toUpperCase()});i.style[K]=u,d._.dirty=1,i.setAttribute(p,u)}}}y(d,f),i.style.visibility=o},x=1.2,y=function(d,f){if(d.type==\"text\"&&!!(f[b](\"text\")||f[b](\"font\")||f[b](\"font-size\")||f[b](\"x\")||f[b](\"y\"))){var g=d.attrs,h=d.node,i=h.firstChild?e(a._g.doc.defaultView.getComputedStyle(h.firstChild,l).getPropertyValue(\"font-size\"),10):10;if(f[b](\"text\")){g.text=f.text;while(h.firstChild)h.removeChild(h.firstChild);var j=c(f.text).split(\"\\n\"),k=[],m;for(var n=0,o=j.length;n<o;n++)m=q(\"tspan\"),n&&q(m,{dy:i*x,x:g.x}),m.appendChild(a._g.doc.createTextNode(j[n])),h.appendChild(m),k[n]=m}else{k=h.getElementsByTagName(\"tspan\");for(n=0,o=k.length;n<o;n++)n?q(k[n],{dy:i*x,x:g.x}):q(k[0],{dy:0})}q(h,{x:g.x,y:g.y}),d._.dirty=1;var p=d._getBBox(),r=g.y-(p.y+p.height/2);r&&a.is(r,\"finite\")&&q(k[0],{dy:r})}},z=function(b,c){var d=0,e=0;this[0]=this.node=b,b.raphael=!0,this.id=a._oid++,b.raphaelid=this.id,this.matrix=a.matrix(),this.realPath=null,this.paper=c,this.attrs=this.attrs||{},this._={transform:[],sx:1,sy:1,deg:0,dx:0,dy:0,dirty:1},!c.bottom&&(c.bottom=this),this.prev=c.top,c.top&&(c.top.next=this),c.top=this,this.next=null},A=a.el;z.prototype=A,A.constructor=z,a._engine.path=function(a,b){var c=q(\"path\");b.canvas&&b.canvas.appendChild(c);var d=new z(c,b);d.type=\"path\",w(d,{fill:\"none\",stroke:\"#000\",path:a});return d},A.rotate=function(a,b,e){if(this.removed)return this;a=c(a).split(j),a.length-1&&(b=d(a[1]),e=d(a[2])),a=d(a[0]),e==null&&(b=e);if(b==null||e==null){var f=this.getBBox(1);b=f.x+f.width/2,e=f.y+f.height/2}this.transform(this._.transform.concat([[\"r\",a,b,e]]));return this},A.scale=function(a,b,e,f){if(this.removed)return this;a=c(a).split(j),a.length-1&&(b=d(a[1]),e=d(a[2]),f=d(a[3])),a=d(a[0]),b==null&&(b=a),f==null&&(e=f);if(e==null||f==null)var g=this.getBBox(1);e=e==null?g.x+g.width/2:e,f=f==null?g.y+g.height/2:f,this.transform(this._.transform.concat([[\"s\",a,b,e,f]]));return this},A.translate=function(a,b){if(this.removed)return this;a=c(a).split(j),a.length-1&&(b=d(a[1])),a=d(a[0])||0,b=+b||0,this.transform(this._.transform.concat([[\"t\",a,b]]));return this},A.transform=function(c){var d=this._;if(c==null)return d.transform;a._extractTransform(this,c),this.clip&&q(this.clip,{transform:this.matrix.invert()}),this.pattern&&s(this),this.node&&q(this.node,{transform:this.matrix});if(d.sx!=1||d.sy!=1){var e=this.attrs[b](\"stroke-width\")?this.attrs[\"stroke-width\"]:1;this.attr({\"stroke-width\":e})}return this},A.hide=function(){!this.removed&&this.paper.safari(this.node.style.display=\"none\");return this},A.show=function(){!this.removed&&this.paper.safari(this.node.style.display=\"\");return this},A.remove=function(){if(!this.removed&&!!this.node.parentNode){var b=this.paper;b.__set__&&b.__set__.exclude(this),k.unbind(\"raphael.*.*.\"+this.id),this.gradient&&b.defs.removeChild(this.gradient),a._tear(this,b),this.node.parentNode.tagName.toLowerCase()==\"a\"?this.node.parentNode.parentNode.removeChild(this.node.parentNode):this.node.parentNode.removeChild(this.node);for(var c in this)this[c]=typeof this[c]==\"function\"?a._removedFactory(c):null;this.removed=!0}},A._getBBox=function(){if(this.node.style.display==\"none\"){this.show();var a=!0}var b={};try{b=this.node.getBBox()}catch(c){}finally{b=b||{}}a&&this.hide();return b},A.attr=function(c,d){if(this.removed)return this;if(c==null){var e={};for(var f in this.attrs)this.attrs[b](f)&&(e[f]=this.attrs[f]);e.gradient&&e.fill==\"none\"&&(e.fill=e.gradient)&&delete e.gradient,e.transform=this._.transform;return e}if(d==null&&a.is(c,\"string\")){if(c==\"fill\"&&this.attrs.fill==\"none\"&&this.attrs.gradient)return this.attrs.gradient;if(c==\"transform\")return this._.transform;var g=c.split(j),h={};for(var i=0,l=g.length;i<l;i++)c=g[i],c in this.attrs?h[c]=this.attrs[c]:a.is(this.paper.customAttributes[c],\"function\")?h[c]=this.paper.customAttributes[c].def:h[c]=a._availableAttrs[c];return l-1?h:h[g[0]]}if(d==null&&a.is(c,\"array\")){h={};for(i=0,l=c.length;i<l;i++)h[c[i]]=this.attr(c[i]);return h}if(d!=null){var m={};m[c]=d}else c!=null&&a.is(c,\"object\")&&(m=c);for(var n in m)k(\"raphael.attr.\"+n+\".\"+this.id,this,m[n]);for(n in this.paper.customAttributes)if(this.paper.customAttributes[b](n)&&m[b](n)&&a.is(this.paper.customAttributes[n],\"function\")){var o=this.paper.customAttributes[n].apply(this,[].concat(m[n]));this.attrs[n]=m[n];for(var p in o)o[b](p)&&(m[p]=o[p])}w(this,m);return this},A.toFront=function(){if(this.removed)return this;this.node.parentNode.tagName.toLowerCase()==\"a\"?this.node.parentNode.parentNode.appendChild(this.node.parentNode):this.node.parentNode.appendChild(this.node);var b=this.paper;b.top!=this&&a._tofront(this,b);return this},A.toBack=function(){if(this.removed)return this;var b=this.node.parentNode;b.tagName.toLowerCase()==\"a\"?b.parentNode.insertBefore(this.node.parentNode,this.node.parentNode.parentNode.firstChild):b.firstChild!=this.node&&b.insertBefore(this.node,this.node.parentNode.firstChild),a._toback(this,this.paper);var c=this.paper;return this},A.insertAfter=function(b){if(this.removed)return this;var c=b.node||b[b.length-1].node;c.nextSibling?c.parentNode.insertBefore(this.node,c.nextSibling):c.parentNode.appendChild(this.node),a._insertafter(this,b,this.paper);return this},A.insertBefore=function(b){if(this.removed)return this;var c=b.node||b[0].node;c.parentNode.insertBefore(this.node,c),a._insertbefore(this,b,this.paper);return this},A.blur=function(b){var c=this;if(+b!==0){var d=q(\"filter\"),e=q(\"feGaussianBlur\");c.attrs.blur=b,d.id=a.createUUID(),q(e,{stdDeviation:+b||1.5}),d.appendChild(e),c.paper.defs.appendChild(d),c._blur=d,q(c.node,{filter:\"url(#\"+d.id+\")\"})}else c._blur&&(c._blur.parentNode.removeChild(c._blur),delete c._blur,delete c.attrs.blur),c.node.removeAttribute(\"filter\")},a._engine.circle=function(a,b,c,d){var e=q(\"circle\");a.canvas&&a.canvas.appendChild(e);var f=new z(e,a);f.attrs={cx:b,cy:c,r:d,fill:\"none\",stroke:\"#000\"},f.type=\"circle\",q(e,f.attrs);return f},a._engine.rect=function(a,b,c,d,e,f){var g=q(\"rect\");a.canvas&&a.canvas.appendChild(g);var h=new z(g,a);h.attrs={x:b,y:c,width:d,height:e,r:f||0,rx:f||0,ry:f||0,fill:\"none\",stroke:\"#000\"},h.type=\"rect\",q(g,h.attrs);return h},a._engine.ellipse=function(a,b,c,d,e){var f=q(\"ellipse\");a.canvas&&a.canvas.appendChild(f);var g=new z(f,a);g.attrs={cx:b,cy:c,rx:d,ry:e,fill:\"none\",stroke:\"#000\"},g.type=\"ellipse\",q(f,g.attrs);return g},a._engine.image=function(a,b,c,d,e,f){var g=q(\"image\");q(g,{x:c,y:d,width:e,height:f,preserveAspectRatio:\"none\"}),g.setAttributeNS(n,\"href\",b),a.canvas&&a.canvas.appendChild(g);var h=new z(g,a);h.attrs={x:c,y:d,width:e,height:f,src:b},h.type=\"image\";return h},a._engine.text=function(b,c,d,e){var f=q(\"text\");b.canvas&&b.canvas.appendChild(f);var g=new z(f,b);g.attrs={x:c,y:d,\"text-anchor\":\"middle\",text:e,font:a._availableAttrs.font,stroke:\"none\",fill:\"#000\"},g.type=\"text\",w(g,g.attrs);return g},a._engine.setSize=function(a,b){this.width=a||this.width,this.height=b||this.height,this.canvas.setAttribute(\"width\",this.width),this.canvas.setAttribute(\"height\",this.height),this._viewBox&&this.setViewBox.apply(this,this._viewBox);return this},a._engine.create=function(){var b=a._getContainer.apply(0,arguments),c=b&&b.container,d=b.x,e=b.y,f=b.width,g=b.height;if(!c)throw new Error(\"SVG container not found.\");var h=q(\"svg\"),i=\"overflow:hidden;\",j;d=d||0,e=e||0,f=f||512,g=g||342,q(h,{height:g,version:1.1,width:f,xmlns:\"http://www.w3.org/2000/svg\"}),c==1?(h.style.cssText=i+\"position:absolute;left:\"+d+\"px;top:\"+e+\"px\",a._g.doc.body.appendChild(h),j=1):(h.style.cssText=i+\"position:relative\",c.firstChild?c.insertBefore(h,c.firstChild):c.appendChild(h)),c=new a._Paper,c.width=f,c.height=g,c.canvas=h,c.clear(),c._left=c._top=0,j&&(c.renderfix=function(){}),c.renderfix();return c},a._engine.setViewBox=function(a,b,c,d,e){k(\"raphael.setViewBox\",this,this._viewBox,[a,b,c,d,e]);var f=g(c/this.width,d/this.height),h=this.top,i=e?\"meet\":\"xMinYMin\",j,l;a==null?(this._vbSize&&(f=1),delete this._vbSize,j=\"0 0 \"+this.width+m+this.height):(this._vbSize=f,j=a+m+b+m+c+m+d),q(this.canvas,{viewBox:j,preserveAspectRatio:i});while(f&&h)l=\"stroke-width\"in h.attrs?h.attrs[\"stroke-width\"]:1,h.attr({\"stroke-width\":l}),h._.dirty=1,h._.dirtyT=1,h=h.prev;this._viewBox=[a,b,c,d,!!e];return this},a.prototype.renderfix=function(){var a=this.canvas,b=a.style,c;try{c=a.getScreenCTM()||a.createSVGMatrix()}catch(d){c=a.createSVGMatrix()}var e=-c.e%1,f=-c.f%1;if(e||f)e&&(this._left=(this._left+e)%1,b.left=this._left+\"px\"),f&&(this._top=(this._top+f)%1,b.top=this._top+\"px\")},a.prototype.clear=function(){a.eve(\"raphael.clear\",this);var b=this.canvas;while(b.firstChild)b.removeChild(b.firstChild);this.bottom=this.top=null,(this.desc=q(\"desc\")).appendChild(a._g.doc.createTextNode(\"Created with Raphaël \"+a.version)),b.appendChild(this.desc),b.appendChild(this.defs=q(\"defs\"))},a.prototype.remove=function(){k(\"raphael.remove\",this),this.canvas.parentNode&&this.canvas.parentNode.removeChild(this.canvas);for(var b in this)this[b]=typeof this[b]==\"function\"?a._removedFactory(b):null};var B=a.st;for(var C in A)A[b](C)&&!B[b](C)&&(B[C]=function(a){return function(){var b=arguments;return this.forEach(function(c){c[a].apply(c,b)})}}(C))}(window.Raphael),window.Raphael.vml&&function(a){var b=\"hasOwnProperty\",c=String,d=parseFloat,e=Math,f=e.round,g=e.max,h=e.min,i=e.abs,j=\"fill\",k=/[, ]+/,l=a.eve,m=\" progid:DXImageTransform.Microsoft\",n=\" \",o=\"\",p={M:\"m\",L:\"l\",C:\"c\",Z:\"x\",m:\"t\",l:\"r\",c:\"v\",z:\"x\"},q=/([clmz]),?([^clmz]*)/gi,r=/ progid:\\S+Blur\\([^\\)]+\\)/g,s=/-?[^,\\s-]+/g,t=\"position:absolute;left:0;top:0;width:1px;height:1px\",u=21600,v={path:1,rect:1,image:1},w={circle:1,ellipse:1},x=function(b){var d=/[ahqstv]/ig,e=a._pathToAbsolute;c(b).match(d)&&(e=a._path2curve),d=/[clmz]/g;if(e==a._pathToAbsolute&&!c(b).match(d)){var g=c(b).replace(q,function(a,b,c){var d=[],e=b.toLowerCase()==\"m\",g=p[b];c.replace(s,function(a){e&&d.length==2&&(g+=d+p[b==\"m\"?\"l\":\"L\"],d=[]),d.push(f(a*u))});return g+d});return g}var h=e(b),i,j;g=[];for(var k=0,l=h.length;k<l;k++){i=h[k],j=h[k][0].toLowerCase(),j==\"z\"&&(j=\"x\");for(var m=1,r=i.length;m<r;m++)j+=f(i[m]*u)+(m!=r-1?\",\":o);g.push(j)}return g.join(n)},y=function(b,c,d){var e=a.matrix();e.rotate(-b,.5,.5);return{dx:e.x(c,d),dy:e.y(c,d)}},z=function(a,b,c,d,e,f){var g=a._,h=a.matrix,k=g.fillpos,l=a.node,m=l.style,o=1,p=\"\",q,r=u/b,s=u/c;m.visibility=\"hidden\";if(!!b&&!!c){l.coordsize=i(r)+n+i(s),m.rotation=f*(b*c<0?-1:1);if(f){var t=y(f,d,e);d=t.dx,e=t.dy}b<0&&(p+=\"x\"),c<0&&(p+=\" y\")&&(o=-1),m.flip=p,l.coordorigin=d*-r+n+e*-s;if(k||g.fillsize){var v=l.getElementsByTagName(j);v=v&&v[0],l.removeChild(v),k&&(t=y(f,h.x(k[0],k[1]),h.y(k[0],k[1])),v.position=t.dx*o+n+t.dy*o),g.fillsize&&(v.size=g.fillsize[0]*i(b)+n+g.fillsize[1]*i(c)),l.appendChild(v)}m.visibility=\"visible\"}};a.toString=function(){return\"Your browser doesn’t support SVG. Falling down to VML.\\nYou are running Raphaël \"+this.version};var A=function(a,b,d){var e=c(b).toLowerCase().split(\"-\"),f=d?\"end\":\"start\",g=e.length,h=\"classic\",i=\"medium\",j=\"medium\";while(g--)switch(e[g]){case\"block\":case\"classic\":case\"oval\":case\"diamond\":case\"open\":case\"none\":h=e[g];break;case\"wide\":case\"narrow\":j=e[g];break;case\"long\":case\"short\":i=e[g]}var k=a.node.getElementsByTagName(\"stroke\")[0];k[f+\"arrow\"]=h,k[f+\"arrowlength\"]=i,k[f+\"arrowwidth\"]=j},B=function(e,i){e.attrs=e.attrs||{};var l=e.node,m=e.attrs,p=l.style,q,r=v[e.type]&&(i.x!=m.x||i.y!=m.y||i.width!=m.width||i.height!=m.height||i.cx!=m.cx||i.cy!=m.cy||i.rx!=m.rx||i.ry!=m.ry||i.r!=m.r),s=w[e.type]&&(m.cx!=i.cx||m.cy!=i.cy||m.r!=i.r||m.rx!=i.rx||m.ry!=i.ry),t=e;for(var y in i)i[b](y)&&(m[y]=i[y]);r&&(m.path=a._getPath[e.type](e),e._.dirty=1),i.href&&(l.href=i.href),i.title&&(l.title=i.title),i.target&&(l.target=i.target),i.cursor&&(p.cursor=i.cursor),\"blur\"in i&&e.blur(i.blur);if(i.path&&e.type==\"path\"||r)l.path=x(~c(m.path).toLowerCase().indexOf(\"r\")?a._pathToAbsolute(m.path):m.path),e.type==\"image\"&&(e._.fillpos=[m.x,m.y],e._.fillsize=[m.width,m.height],z(e,1,1,0,0,0));\"transform\"in i&&e.transform(i.transform);if(s){var B=+m.cx,D=+m.cy,E=+m.rx||+m.r||0,G=+m.ry||+m.r||0;l.path=a.format(\"ar{0},{1},{2},{3},{4},{1},{4},{1}x\",f((B-E)*u),f((D-G)*u),f((B+E)*u),f((D+G)*u),f(B*u))}if(\"clip-rect\"in i){var H=c(i[\"clip-rect\"]).split(k);if(H.length==4){H[2]=+H[2]+ +H[0],H[3]=+H[3]+ +H[1];var I=l.clipRect||a._g.doc.createElement(\"div\"),J=I.style;J.clip=a.format(\"rect({1}px {2}px {3}px {0}px)\",H),l.clipRect||(J.position=\"absolute\",J.top=0,J.left=0,J.width=e.paper.width+\"px\",J.height=e.paper.height+\"px\",l.parentNode.insertBefore(I,l),I.appendChild(l),l.clipRect=I)}i[\"clip-rect\"]||l.clipRect&&(l.clipRect.style.clip=\"auto\")}if(e.textpath){var K=e.textpath.style;i.font&&(K.font=i.font),i[\"font-family\"]&&(K.fontFamily='\"'+i[\"font-family\"].split(\",\")[0].replace(/^['\"]+|['\"]+$/g,o)+'\"'),i[\"font-size\"]&&(K.fontSize=i[\"font-size\"]),i[\"font-weight\"]&&(K.fontWeight=i[\"font-weight\"]),i[\"font-style\"]&&(K.fontStyle=i[\"font-style\"])}\"arrow-start\"in i&&A(t,i[\"arrow-start\"]),\"arrow-end\"in i&&A(t,i[\"arrow-end\"],1);if(i.opacity!=null||i[\"stroke-width\"]!=null||i.fill!=null||i.src!=null||i.stroke!=null||i[\"stroke-width\"]!=null||i[\"stroke-opacity\"]!=null||i[\"fill-opacity\"]!=null||i[\"stroke-dasharray\"]!=null||i[\"stroke-miterlimit\"]!=null||i[\"stroke-linejoin\"]!=null||i[\"stroke-linecap\"]!=null){var L=l.getElementsByTagName(j),M=!1;L=L&&L[0],!L&&(M=L=F(j)),e.type==\"image\"&&i.src&&(L.src=i.src),i.fill&&(L.on=!0);if(L.on==null||i.fill==\"none\"||i.fill===null)L.on=!1;if(L.on&&i.fill){var N=c(i.fill).match(a._ISURL);if(N){L.parentNode==l&&l.removeChild(L),L.rotate=!0,L.src=N[1],L.type=\"tile\";var O=e.getBBox(1);L.position=O.x+n+O.y,e._.fillpos=[O.x,O.y],a._preload(N[1],function(){e._.fillsize=[this.offsetWidth,this.offsetHeight]})}else L.color=a.getRGB(i.fill).hex,L.src=o,L.type=\"solid\",a.getRGB(i.fill).error&&(t.type in{circle:1,ellipse:1}||c(i.fill).charAt()!=\"r\")&&C(t,i.fill,L)&&(m.fill=\"none\",m.gradient=i.fill,L.rotate=!1)}if(\"fill-opacity\"in i||\"opacity\"in i){var P=((+m[\"fill-opacity\"]+1||2)-1)*((+m.opacity+1||2)-1)*((+a.getRGB(i.fill).o+1||2)-1);P=h(g(P,0),1),L.opacity=P,L.src&&(L.color=\"none\")}l.appendChild(L);var Q=l.getElementsByTagName(\"stroke\")&&l.getElementsByTagName(\"stroke\")[0],T=!1;!Q&&(T=Q=F(\"stroke\"));if(i.stroke&&i.stroke!=\"none\"||i[\"stroke-width\"]||i[\"stroke-opacity\"]!=null||i[\"stroke-dasharray\"]||i[\"stroke-miterlimit\"]||i[\"stroke-linejoin\"]||i[\"stroke-linecap\"])Q.on=!0;(i.stroke==\"none\"||i.stroke===null||Q.on==null||i.stroke==0||i[\"stroke-width\"]==0)&&(Q.on=!1);var U=a.getRGB(i.stroke);Q.on&&i.stroke&&(Q.color=U.hex),P=((+m[\"stroke-opacity\"]+1||2)-1)*((+m.opacity+1||2)-1)*((+U.o+1||2)-1);var V=(d(i[\"stroke-width\"])||1)*.75;P=h(g(P,0),1),i[\"stroke-width\"]==null&&(V=m[\"stroke-width\"]),i[\"stroke-width\"]&&(Q.weight=V),V&&V<1&&(P*=V)&&(Q.weight=1),Q.opacity=P,i[\"stroke-linejoin\"]&&(Q.joinstyle=i[\"stroke-linejoin\"]||\"miter\"),Q.miterlimit=i[\"stroke-miterlimit\"]||8,i[\"stroke-linecap\"]&&(Q.endcap=i[\"stroke-linecap\"]==\"butt\"?\"flat\":i[\"stroke-linecap\"]==\"square\"?\"square\":\"round\");if(i[\"stroke-dasharray\"]){var W={\"-\":\"shortdash\",\".\":\"shortdot\",\"-.\":\"shortdashdot\",\"-..\":\"shortdashdotdot\",\". \":\"dot\",\"- \":\"dash\",\"--\":\"longdash\",\"- .\":\"dashdot\",\"--.\":\"longdashdot\",\"--..\":\"longdashdotdot\"};Q.dashstyle=W[b](i[\"stroke-dasharray\"])?W[i[\"stroke-dasharray\"]]:o}T&&l.appendChild(Q)}if(t.type==\"text\"){t.paper.canvas.style.display=o;var X=t.paper.span,Y=100,Z=m.font&&m.font.match(/\\d+(?:\\.\\d*)?(?=px)/);p=X.style,m.font&&(p.font=m.font),m[\"font-family\"]&&(p.fontFamily=m[\"font-family\"]),m[\"font-weight\"]&&(p.fontWeight=m[\"font-weight\"]),m[\"font-style\"]&&(p.fontStyle=m[\"font-style\"]),Z=d(m[\"font-size\"]||Z&&Z[0])||10,p.fontSize=Z*Y+\"px\",t.textpath.string&&(X.innerHTML=c(t.textpath.string).replace(/</g,\"&#60;\").replace(/&/g,\"&#38;\").replace(/\\n/g,\"<br>\"));var $=X.getBoundingClientRect();t.W=m.w=($.right-$.left)/Y,t.H=m.h=($.bottom-$.top)/Y,t.X=m.x,t.Y=m.y+t.H/2,(\"x\"in i||\"y\"in i)&&(t.path.v=a.format(\"m{0},{1}l{2},{1}\",f(m.x*u),f(m.y*u),f(m.x*u)+1));var _=[\"x\",\"y\",\"text\",\"font\",\"font-family\",\"font-weight\",\"font-style\",\"font-size\"];for(var ba=0,bb=_.length;ba<bb;ba++)if(_[ba]in i){t._.dirty=1;break}switch(m[\"text-anchor\"]){case\"start\":t.textpath.style[\"v-text-align\"]=\"left\",t.bbx=t.W/2;break;case\"end\":t.textpath.style[\"v-text-align\"]=\"right\",t.bbx=-t.W/2;break;default:t.textpath.style[\"v-text-align\"]=\"center\",t.bbx=0}t.textpath.style[\"v-text-kern\"]=!0}},C=function(b,f,g){b.attrs=b.attrs||{};var h=b.attrs,i=Math.pow,j,k,l=\"linear\",m=\".5 .5\";b.attrs.gradient=f,f=c(f).replace(a._radial_gradient,function(a,b,c){l=\"radial\",b&&c&&(b=d(b),c=d(c),i(b-.5,2)+i(c-.5,2)>.25&&(c=e.sqrt(.25-i(b-.5,2))*((c>.5)*2-1)+.5),m=b+n+c);return o}),f=f.split(/\\s*\\-\\s*/);if(l==\"linear\"){var p=f.shift();p=-d(p);if(isNaN(p))return null}var q=a._parseDots(f);if(!q)return null;b=b.shape||b.node;if(q.length){b.removeChild(g),g.on=!0,g.method=\"none\",g.color=q[0].color,g.color2=q[q.length-1].color;var r=[];for(var s=0,t=q.length;s<t;s++)q[s].offset&&r.push(q[s].offset+n+q[s].color);g.colors=r.length?r.join():\"0% \"+g.color,l==\"radial\"?(g.type=\"gradientTitle\",g.focus=\"100%\",g.focussize=\"0 0\",g.focusposition=m,g.angle=0):(g.type=\"gradient\",g.angle=(270-p)%360),b.appendChild(g)}return 1},D=function(b,c){this[0]=this.node=b,b.raphael=!0,this.id=a._oid++,b.raphaelid=this.id,this.X=0,this.Y=0,this.attrs={},this.paper=c,this.matrix=a.matrix(),this._={transform:[],sx:1,sy:1,dx:0,dy:0,deg:0,dirty:1,dirtyT:1},!c.bottom&&(c.bottom=this),this.prev=c.top,c.top&&(c.top.next=this),c.top=this,this.next=null},E=a.el;D.prototype=E,E.constructor=D,E.transform=function(b){if(b==null)return this._.transform;var d=this.paper._viewBoxShift,e=d?\"s\"+[d.scale,d.scale]+\"-1-1t\"+[d.dx,d.dy]:o,f;d&&(f=b=c(b).replace(/\\.{3}|\\u2026/g,this._.transform||o)),a._extractTransform(this,e+b);var g=this.matrix.clone(),h=this.skew,i=this.node,j,k=~c(this.attrs.fill).indexOf(\"-\"),l=!c(this.attrs.fill).indexOf(\"url(\");g.translate(-0.5,-0.5);if(l||k||this.type==\"image\"){h.matrix=\"1 0 0 1\",h.offset=\"0 0\",j=g.split();if(k&&j.noRotation||!j.isSimple){i.style.filter=g.toFilter();var m=this.getBBox(),p=this.getBBox(1),q=m.x-p.x,r=m.y-p.y;i.coordorigin=q*-u+n+r*-u,z(this,1,1,q,r,0)}else i.style.filter=o,z(this,j.scalex,j.scaley,j.dx,j.dy,j.rotate)}else i.style.filter=o,h.matrix=c(g),h.offset=g.offset();f&&(this._.transform=f);return this},E.rotate=function(a,b,e){if(this.removed)return this;if(a!=null){a=c(a).split(k),a.length-1&&(b=d(a[1]),e=d(a[2])),a=d(a[0]),e==null&&(b=e);if(b==null||e==null){var f=this.getBBox(1);b=f.x+f.width/2,e=f.y+f.height/2}this._.dirtyT=1,this.transform(this._.transform.concat([[\"r\",a,b,e]]));return this}},E.translate=function(a,b){if(this.removed)return this;a=c(a).split(k),a.length-1&&(b=d(a[1])),a=d(a[0])||0,b=+b||0,this._.bbox&&(this._.bbox.x+=a,this._.bbox.y+=b),this.transform(this._.transform.concat([[\"t\",a,b]]));return this},E.scale=function(a,b,e,f){if(this.removed)return this;a=c(a).split(k),a.length-1&&(b=d(a[1]),e=d(a[2]),f=d(a[3]),isNaN(e)&&(e=null),isNaN(f)&&(f=null)),a=d(a[0]),b==null&&(b=a),f==null&&(e=f);if(e==null||f==null)var g=this.getBBox(1);e=e==null?g.x+g.width/2:e,f=f==null?g.y+g.height/2:f,this.transform(this._.transform.concat([[\"s\",a,b,e,f]])),this._.dirtyT=1;return this},E.hide=function(){!this.removed&&(this.node.style.display=\"none\");return this},E.show=function(){!this.removed&&(this.node.style.display=o);return this},E._getBBox=function(){if(this.removed)return{};return{x:this.X+(this.bbx||0)-this.W/2,y:this.Y-this.H,width:this.W,height:this.H}},E.remove=function(){if(!this.removed&&!!this.node.parentNode){this.paper.__set__&&this.paper.__set__.exclude(this),a.eve.unbind(\"raphael.*.*.\"+this.id),a._tear(this,this.paper),this.node.parentNode.removeChild(this.node),this.shape&&this.shape.parentNode.removeChild(this.shape);for(var b in this)this[b]=typeof this[b]==\"function\"?a._removedFactory(b):null;this.removed=!0}},E.attr=function(c,d){if(this.removed)return this;if(c==null){var e={};for(var f in this.attrs)this.attrs[b](f)&&(e[f]=this.attrs[f]);e.gradient&&e.fill==\"none\"&&(e.fill=e.gradient)&&delete e.gradient,e.transform=this._.transform;return e}if(d==null&&a.is(c,\"string\")){if(c==j&&this.attrs.fill==\"none\"&&this.attrs.gradient)return this.attrs.gradient;var g=c.split(k),h={};for(var i=0,m=g.length;i<m;i++)c=g[i],c in this.attrs?h[c]=this.attrs[c]:a.is(this.paper.customAttributes[c],\"function\")?h[c]=this.paper.customAttributes[c].def:h[c]=a._availableAttrs[c];return m-1?h:h[g[0]]}if(this.attrs&&d==null&&a.is(c,\"array\")){h={};for(i=0,m=c.length;i<m;i++)h[c[i]]=this.attr(c[i]);return h}var n;d!=null&&(n={},n[c]=d),d==null&&a.is(c,\"object\")&&(n=c);for(var o in n)l(\"raphael.attr.\"+o+\".\"+this.id,this,n[o]);if(n){for(o in this.paper.customAttributes)if(this.paper.customAttributes[b](o)&&n[b](o)&&a.is(this.paper.customAttributes[o],\"function\")){var p=this.paper.customAttributes[o].apply(this,[].concat(n[o]));this.attrs[o]=n[o];for(var q in p)p[b](q)&&(n[q]=p[q])}n.text&&this.type==\"text\"&&(this.textpath.string=n.text),B(this,n)}return this},E.toFront=function(){!this.removed&&this.node.parentNode.appendChild(this.node),this.paper&&this.paper.top!=this&&a._tofront(this,this.paper);return this},E.toBack=function(){if(this.removed)return this;this.node.parentNode.firstChild!=this.node&&(this.node.parentNode.insertBefore(this.node,this.node.parentNode.firstChild),a._toback(this,this.paper));return this},E.insertAfter=function(b){if(this.removed)return this;b.constructor==a.st.constructor&&(b=b[b.length-1]),b.node.nextSibling?b.node.parentNode.insertBefore(this.node,b.node.nextSibling):b.node.parentNode.appendChild(this.node),a._insertafter(this,b,this.paper);return this},E.insertBefore=function(b){if(this.removed)return this;b.constructor==a.st.constructor&&(b=b[0]),b.node.parentNode.insertBefore(this.node,b.node),a._insertbefore(this,b,this.paper);return this},E.blur=function(b){var c=this.node.runtimeStyle,d=c.filter;d=d.replace(r,o),+b!==0?(this.attrs.blur=b,c.filter=d+n+m+\".Blur(pixelradius=\"+(+b||1.5)+\")\",c.margin=a.format(\"-{0}px 0 0 -{0}px\",f(+b||1.5))):(c.filter=d,c.margin=0,delete this.attrs.blur)},a._engine.path=function(a,b){var c=F(\"shape\");c.style.cssText=t,c.coordsize=u+n+u,c.coordorigin=b.coordorigin;var d=new D(c,b),e={fill:\"none\",stroke:\"#000\"};a&&(e.path=a),d.type=\"path\",d.path=[],d.Path=o,B(d,e),b.canvas.appendChild(c);var f=F(\"skew\");f.on=!0,c.appendChild(f),d.skew=f,d.transform(o);return d},a._engine.rect=function(b,c,d,e,f,g){var h=a._rectPath(c,d,e,f,g),i=b.path(h),j=i.attrs;i.X=j.x=c,i.Y=j.y=d,i.W=j.width=e,i.H=j.height=f,j.r=g,j.path=h,i.type=\"rect\";return i},a._engine.ellipse=function(a,b,c,d,e){var f=a.path(),g=f.attrs;f.X=b-d,f.Y=c-e,f.W=d*2,f.H=e*2,f.type=\"ellipse\",B(f,{cx:b,cy:c,rx:d,ry:e});return f},a._engine.circle=function(a,b,c,d){var e=a.path(),f=e.attrs;e.X=b-d,e.Y=c-d,e.W=e.H=d*2,e.type=\"circle\",B(e,{cx:b,cy:c,r:d});return e},a._engine.image=function(b,c,d,e,f,g){var h=a._rectPath(d,e,f,g),i=b.path(h).attr({stroke:\"none\"}),k=i.attrs,l=i.node,m=l.getElementsByTagName(j)[0];k.src=c,i.X=k.x=d,i.Y=k.y=e,i.W=k.width=f,i.H=k.height=g,k.path=h,i.type=\"image\",m.parentNode==l&&l.removeChild(m),m.rotate=!0,m.src=c,m.type=\"tile\",i._.fillpos=[d,e],i._.fillsize=[f,g],l.appendChild(m),z(i,1,1,0,0,0);return i},a._engine.text=function(b,d,e,g){var h=F(\"shape\"),i=F(\"path\"),j=F(\"textpath\");d=d||0,e=e||0,g=g||\"\",i.v=a.format(\"m{0},{1}l{2},{1}\",f(d*u),f(e*u),f(d*u)+1),i.textpathok=!0,j.string=c(g),j.on=!0,h.style.cssText=t,h.coordsize=u+n+u,h.coordorigin=\"0 0\";var k=new D(h,b),l={fill:\"#000\",stroke:\"none\",font:a._availableAttrs.font,text:g};k.shape=h,k.path=i,k.textpath=j,k.type=\"text\",k.attrs.text=c(g),k.attrs.x=d,k.attrs.y=e,k.attrs.w=1,k.attrs.h=1,B(k,l),h.appendChild(j),h.appendChild(i),b.canvas.appendChild(h);var m=F(\"skew\");m.on=!0,h.appendChild(m),k.skew=m,k.transform(o);return k},a._engine.setSize=function(b,c){var d=this.canvas.style;this.width=b,this.height=c,b==+b&&(b+=\"px\"),c==+c&&(c+=\"px\"),d.width=b,d.height=c,d.clip=\"rect(0 \"+b+\" \"+c+\" 0)\",this._viewBox&&a._engine.setViewBox.apply(this,this._viewBox);return this},a._engine.setViewBox=function(b,c,d,e,f){a.eve(\"raphael.setViewBox\",this,this._viewBox,[b,c,d,e,f]);var h=this.width,i=this.height,j=1/g(d/h,e/i),k,l;f&&(k=i/e,l=h/d,d*k<h&&(b-=(h-d*k)/2/k),e*l<i&&(c-=(i-e*l)/2/l)),this._viewBox=[b,c,d,e,!!f],this._viewBoxShift={dx:-b,dy:-c,scale:j},this.forEach(function(a){a.transform(\"...\")});return this};var F;a._engine.initWin=function(a){var b=a.document;b.createStyleSheet().addRule(\".rvml\",\"behavior:url(#default#VML)\");try{!b.namespaces.rvml&&b.namespaces.add(\"rvml\",\"urn:schemas-microsoft-com:vml\"),F=function(a){return b.createElement(\"<rvml:\"+a+' class=\"rvml\">')}}catch(c){F=function(a){return b.createElement(\"<\"+a+' xmlns=\"urn:schemas-microsoft.com:vml\" class=\"rvml\">')}}},a._engine.initWin(a._g.win),a._engine.create=function(){var b=a._getContainer.apply(0,arguments),c=b.container,d=b.height,e,f=b.width,g=b.x,h=b.y;if(!c)throw new Error(\"VML container not found.\");var i=new a._Paper,j=i.canvas=a._g.doc.createElement(\"div\"),k=j.style;g=g||0,h=h||0,f=f||512,d=d||342,i.width=f,i.height=d,f==+f&&(f+=\"px\"),d==+d&&(d+=\"px\"),i.coordsize=u*1e3+n+u*1e3,i.coordorigin=\"0 0\",i.span=a._g.doc.createElement(\"span\"),i.span.style.cssText=\"position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;\",j.appendChild(i.span),k.cssText=a.format(\"top:0;left:0;width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden\",f,d),c==1?(a._g.doc.body.appendChild(j),k.left=g+\"px\",k.top=h+\"px\",k.position=\"absolute\"):c.firstChild?c.insertBefore(j,c.firstChild):c.appendChild(j),i.renderfix=function(){};return i},a.prototype.clear=function(){a.eve(\"raphael.clear\",this),this.canvas.innerHTML=o,this.span=a._g.doc.createElement(\"span\"),this.span.style.cssText=\"position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;\",this.canvas.appendChild(this.span),this.bottom=this.top=null},a.prototype.remove=function(){a.eve(\"raphael.remove\",this),this.canvas.parentNode.removeChild(this.canvas);for(var b in this)this[b]=typeof this[b]==\"function\"?a._removedFactory(b):null;return!0};var G=a.st;for(var H in E)E[b](H)&&!G[b](H)&&(G[H]=function(a){return function(){var b=arguments;return this.forEach(function(c){c[a].apply(c,b)})}}(H))}(window.Raphael)"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/diagram-viewer/js/raphael.js",
    "content": "// ┌────────────────────────────────────────────────────────────────────┐ \\\\\n// │ Raphaël 2.1.1 - JavaScript Vector Library                          │ \\\\\n// ├────────────────────────────────────────────────────────────────────┤ \\\\\n// │ Copyright © 2008-2012 Dmitry Baranovskiy (http://raphaeljs.com)    │ \\\\\n// │ Copyright © 2008-2012 Sencha Labs (http://sencha.com)              │ \\\\\n// ├────────────────────────────────────────────────────────────────────┤ \\\\\n// │ Licensed under the MIT (http://raphaeljs.com/license.html) license.│ \\\\\n// └────────────────────────────────────────────────────────────────────┘ \\\\\n\n(function(a){var b=\"0.3.4\",c=\"hasOwnProperty\",d=/[\\.\\/]/,e=\"*\",f=function(){},g=function(a,b){return a-b},h,i,j={n:{}},k=function(a,b){var c=j,d=i,e=Array.prototype.slice.call(arguments,2),f=k.listeners(a),l=0,m=!1,n,o=[],p={},q=[],r=h,s=[];h=a,i=0;for(var t=0,u=f.length;t<u;t++)\"zIndex\"in f[t]&&(o.push(f[t].zIndex),f[t].zIndex<0&&(p[f[t].zIndex]=f[t]));o.sort(g);while(o[l]<0){n=p[o[l++]],q.push(n.apply(b,e));if(i){i=d;return q}}for(t=0;t<u;t++){n=f[t];if(\"zIndex\"in n)if(n.zIndex==o[l]){q.push(n.apply(b,e));if(i)break;do{l++,n=p[o[l]],n&&q.push(n.apply(b,e));if(i)break}while(n)}else p[n.zIndex]=n;else{q.push(n.apply(b,e));if(i)break}}i=d,h=r;return q.length?q:null};k.listeners=function(a){var b=a.split(d),c=j,f,g,h,i,k,l,m,n,o=[c],p=[];for(i=0,k=b.length;i<k;i++){n=[];for(l=0,m=o.length;l<m;l++){c=o[l].n,g=[c[b[i]],c[e]],h=2;while(h--)f=g[h],f&&(n.push(f),p=p.concat(f.f||[]))}o=n}return p},k.on=function(a,b){var c=a.split(d),e=j;for(var g=0,h=c.length;g<h;g++)e=e.n,!e[c[g]]&&(e[c[g]]={n:{}}),e=e[c[g]];e.f=e.f||[];for(g=0,h=e.f.length;g<h;g++)if(e.f[g]==b)return f;e.f.push(b);return function(a){+a==+a&&(b.zIndex=+a)}},k.stop=function(){i=1},k.nt=function(a){if(a)return(new RegExp(\"(?:\\\\.|\\\\/|^)\"+a+\"(?:\\\\.|\\\\/|$)\")).test(h);return h},k.off=k.unbind=function(a,b){var f=a.split(d),g,h,i,k,l,m,n,o=[j];for(k=0,l=f.length;k<l;k++)for(m=0;m<o.length;m+=i.length-2){i=[m,1],g=o[m].n;if(f[k]!=e)g[f[k]]&&i.push(g[f[k]]);else for(h in g)g[c](h)&&i.push(g[h]);o.splice.apply(o,i)}for(k=0,l=o.length;k<l;k++){g=o[k];while(g.n){if(b){if(g.f){for(m=0,n=g.f.length;m<n;m++)if(g.f[m]==b){g.f.splice(m,1);break}!g.f.length&&delete g.f}for(h in g.n)if(g.n[c](h)&&g.n[h].f){var p=g.n[h].f;for(m=0,n=p.length;m<n;m++)if(p[m]==b){p.splice(m,1);break}!p.length&&delete g.n[h].f}}else{delete g.f;for(h in g.n)g.n[c](h)&&g.n[h].f&&delete g.n[h].f}g=g.n}}},k.once=function(a,b){var c=function(){var d=b.apply(this,arguments);k.unbind(a,c);return d};return k.on(a,c)},k.version=b,k.toString=function(){return\"You are running Eve \"+b},typeof module!=\"undefined\"&&module.exports?module.exports=k:typeof define!=\"undefined\"?define(\"eve\",[],function(){return k}):a.eve=k})(this),function(){function cF(a){for(var b=0;b<cy.length;b++)cy[b].el.paper==a&&cy.splice(b--,1)}function cE(b,d,e,f,h,i){e=Q(e);var j,k,l,m=[],o,p,q,t=b.ms,u={},v={},w={};if(f)for(y=0,z=cy.length;y<z;y++){var x=cy[y];if(x.el.id==d.id&&x.anim==b){x.percent!=e?(cy.splice(y,1),l=1):k=x,d.attr(x.totalOrigin);break}}else f=+v;for(var y=0,z=b.percents.length;y<z;y++){if(b.percents[y]==e||b.percents[y]>f*b.top){e=b.percents[y],p=b.percents[y-1]||0,t=t/b.top*(e-p),o=b.percents[y+1],j=b.anim[e];break}f&&d.attr(b.anim[b.percents[y]])}if(!!j){if(!k){for(var A in j)if(j[g](A))if(U[g](A)||d.paper.customAttributes[g](A)){u[A]=d.attr(A),u[A]==null&&(u[A]=T[A]),v[A]=j[A];switch(U[A]){case C:w[A]=(v[A]-u[A])/t;break;case\"colour\":u[A]=a.getRGB(u[A]);var B=a.getRGB(v[A]);w[A]={r:(B.r-u[A].r)/t,g:(B.g-u[A].g)/t,b:(B.b-u[A].b)/t};break;case\"path\":var D=bR(u[A],v[A]),E=D[1];u[A]=D[0],w[A]=[];for(y=0,z=u[A].length;y<z;y++){w[A][y]=[0];for(var F=1,G=u[A][y].length;F<G;F++)w[A][y][F]=(E[y][F]-u[A][y][F])/t}break;case\"transform\":var H=d._,I=ca(H[A],v[A]);if(I){u[A]=I.from,v[A]=I.to,w[A]=[],w[A].real=!0;for(y=0,z=u[A].length;y<z;y++){w[A][y]=[u[A][y][0]];for(F=1,G=u[A][y].length;F<G;F++)w[A][y][F]=(v[A][y][F]-u[A][y][F])/t}}else{var J=d.matrix||new cb,K={_:{transform:H.transform},getBBox:function(){return d.getBBox(1)}};u[A]=[J.a,J.b,J.c,J.d,J.e,J.f],b$(K,v[A]),v[A]=K._.transform,w[A]=[(K.matrix.a-J.a)/t,(K.matrix.b-J.b)/t,(K.matrix.c-J.c)/t,(K.matrix.d-J.d)/t,(K.matrix.e-J.e)/t,(K.matrix.f-J.f)/t]}break;case\"csv\":var L=r(j[A])[s](c),M=r(u[A])[s](c);if(A==\"clip-rect\"){u[A]=M,w[A]=[],y=M.length;while(y--)w[A][y]=(L[y]-u[A][y])/t}v[A]=L;break;default:L=[][n](j[A]),M=[][n](u[A]),w[A]=[],y=d.paper.customAttributes[A].length;while(y--)w[A][y]=((L[y]||0)-(M[y]||0))/t}}var O=j.easing,P=a.easing_formulas[O];if(!P){P=r(O).match(N);if(P&&P.length==5){var R=P;P=function(a){return cC(a,+R[1],+R[2],+R[3],+R[4],t)}}else P=bf}q=j.start||b.start||+(new Date),x={anim:b,percent:e,timestamp:q,start:q+(b.del||0),status:0,initstatus:f||0,stop:!1,ms:t,easing:P,from:u,diff:w,to:v,el:d,callback:j.callback,prev:p,next:o,repeat:i||b.times,origin:d.attr(),totalOrigin:h},cy.push(x);if(f&&!k&&!l){x.stop=!0,x.start=new Date-t*f;if(cy.length==1)return cA()}l&&(x.start=new Date-x.ms*f),cy.length==1&&cz(cA)}else k.initstatus=f,k.start=new Date-k.ms*f;eve(\"raphael.anim.start.\"+d.id,d,b)}}function cD(a,b){var c=[],d={};this.ms=b,this.times=1;if(a){for(var e in a)a[g](e)&&(d[Q(e)]=a[e],c.push(Q(e)));c.sort(bd)}this.anim=d,this.top=c[c.length-1],this.percents=c}function cC(a,b,c,d,e,f){function o(a,b){var c,d,e,f,j,k;for(e=a,k=0;k<8;k++){f=m(e)-a;if(z(f)<b)return e;j=(3*i*e+2*h)*e+g;if(z(j)<1e-6)break;e=e-f/j}c=0,d=1,e=a;if(e<c)return c;if(e>d)return d;while(c<d){f=m(e);if(z(f-a)<b)return e;a>f?c=e:d=e,e=(d-c)/2+c}return e}function n(a,b){var c=o(a,b);return((l*c+k)*c+j)*c}function m(a){return((i*a+h)*a+g)*a}var g=3*b,h=3*(d-b)-g,i=1-g-h,j=3*c,k=3*(e-c)-j,l=1-j-k;return n(a,1/(200*f))}function cq(){return this.x+q+this.y+q+this.width+\" × \"+this.height}function cp(){return this.x+q+this.y}function cb(a,b,c,d,e,f){a!=null?(this.a=+a,this.b=+b,this.c=+c,this.d=+d,this.e=+e,this.f=+f):(this.a=1,this.b=0,this.c=0,this.d=1,this.e=0,this.f=0)}function bH(b,c,d){b=a._path2curve(b),c=a._path2curve(c);var e,f,g,h,i,j,k,l,m,n,o=d?0:[];for(var p=0,q=b.length;p<q;p++){var r=b[p];if(r[0]==\"M\")e=i=r[1],f=j=r[2];else{r[0]==\"C\"?(m=[e,f].concat(r.slice(1)),e=m[6],f=m[7]):(m=[e,f,e,f,i,j,i,j],e=i,f=j);for(var s=0,t=c.length;s<t;s++){var u=c[s];if(u[0]==\"M\")g=k=u[1],h=l=u[2];else{u[0]==\"C\"?(n=[g,h].concat(u.slice(1)),g=n[6],h=n[7]):(n=[g,h,g,h,k,l,k,l],g=k,h=l);var v=bG(m,n,d);if(d)o+=v;else{for(var w=0,x=v.length;w<x;w++)v[w].segment1=p,v[w].segment2=s,v[w].bez1=m,v[w].bez2=n;o=o.concat(v)}}}}}return o}function bG(b,c,d){var e=a.bezierBBox(b),f=a.bezierBBox(c);if(!a.isBBoxIntersect(e,f))return d?0:[];var g=bB.apply(0,b),h=bB.apply(0,c),i=~~(g/5),j=~~(h/5),k=[],l=[],m={},n=d?0:[];for(var o=0;o<i+1;o++){var p=a.findDotsAtSegment.apply(a,b.concat(o/i));k.push({x:p.x,y:p.y,t:o/i})}for(o=0;o<j+1;o++)p=a.findDotsAtSegment.apply(a,c.concat(o/j)),l.push({x:p.x,y:p.y,t:o/j});for(o=0;o<i;o++)for(var q=0;q<j;q++){var r=k[o],s=k[o+1],t=l[q],u=l[q+1],v=z(s.x-r.x)<.001?\"y\":\"x\",w=z(u.x-t.x)<.001?\"y\":\"x\",x=bD(r.x,r.y,s.x,s.y,t.x,t.y,u.x,u.y);if(x){if(m[x.x.toFixed(4)]==x.y.toFixed(4))continue;m[x.x.toFixed(4)]=x.y.toFixed(4);var y=r.t+z((x[v]-r[v])/(s[v]-r[v]))*(s.t-r.t),A=t.t+z((x[w]-t[w])/(u[w]-t[w]))*(u.t-t.t);y>=0&&y<=1&&A>=0&&A<=1&&(d?n++:n.push({x:x.x,y:x.y,t1:y,t2:A}))}}return n}function bF(a,b){return bG(a,b,1)}function bE(a,b){return bG(a,b)}function bD(a,b,c,d,e,f,g,h){if(!(x(a,c)<y(e,g)||y(a,c)>x(e,g)||x(b,d)<y(f,h)||y(b,d)>x(f,h))){var i=(a*d-b*c)*(e-g)-(a-c)*(e*h-f*g),j=(a*d-b*c)*(f-h)-(b-d)*(e*h-f*g),k=(a-c)*(f-h)-(b-d)*(e-g);if(!k)return;var l=i/k,m=j/k,n=+l.toFixed(2),o=+m.toFixed(2);if(n<+y(a,c).toFixed(2)||n>+x(a,c).toFixed(2)||n<+y(e,g).toFixed(2)||n>+x(e,g).toFixed(2)||o<+y(b,d).toFixed(2)||o>+x(b,d).toFixed(2)||o<+y(f,h).toFixed(2)||o>+x(f,h).toFixed(2))return;return{x:l,y:m}}}function bC(a,b,c,d,e,f,g,h,i){if(!(i<0||bB(a,b,c,d,e,f,g,h)<i)){var j=1,k=j/2,l=j-k,m,n=.01;m=bB(a,b,c,d,e,f,g,h,l);while(z(m-i)>n)k/=2,l+=(m<i?1:-1)*k,m=bB(a,b,c,d,e,f,g,h,l);return l}}function bB(a,b,c,d,e,f,g,h,i){i==null&&(i=1),i=i>1?1:i<0?0:i;var j=i/2,k=12,l=[-0.1252,.1252,-0.3678,.3678,-0.5873,.5873,-0.7699,.7699,-0.9041,.9041,-0.9816,.9816],m=[.2491,.2491,.2335,.2335,.2032,.2032,.1601,.1601,.1069,.1069,.0472,.0472],n=0;for(var o=0;o<k;o++){var p=j*l[o]+j,q=bA(p,a,c,e,g),r=bA(p,b,d,f,h),s=q*q+r*r;n+=m[o]*w.sqrt(s)}return j*n}function bA(a,b,c,d,e){var f=-3*b+9*c-9*d+3*e,g=a*f+6*b-12*c+6*d;return a*g-3*b+3*c}function by(a,b){var c=[];for(var d=0,e=a.length;e-2*!b>d;d+=2){var f=[{x:+a[d-2],y:+a[d-1]},{x:+a[d],y:+a[d+1]},{x:+a[d+2],y:+a[d+3]},{x:+a[d+4],y:+a[d+5]}];b?d?e-4==d?f[3]={x:+a[0],y:+a[1]}:e-2==d&&(f[2]={x:+a[0],y:+a[1]},f[3]={x:+a[2],y:+a[3]}):f[0]={x:+a[e-2],y:+a[e-1]}:e-4==d?f[3]=f[2]:d||(f[0]={x:+a[d],y:+a[d+1]}),c.push([\"C\",(-f[0].x+6*f[1].x+f[2].x)/6,(-f[0].y+6*f[1].y+f[2].y)/6,(f[1].x+6*f[2].x-f[3].x)/6,(f[1].y+6*f[2].y-f[3].y)/6,f[2].x,f[2].y])}return c}function bx(){return this.hex}function bv(a,b,c){function d(){var e=Array.prototype.slice.call(arguments,0),f=e.join(\"␀\"),h=d.cache=d.cache||{},i=d.count=d.count||[];if(h[g](f)){bu(i,f);return c?c(h[f]):h[f]}i.length>=1e3&&delete h[i.shift()],i.push(f),h[f]=a[m](b,e);return c?c(h[f]):h[f]}return d}function bu(a,b){for(var c=0,d=a.length;c<d;c++)if(a[c]===b)return a.push(a.splice(c,1)[0])}function bm(a){if(Object(a)!==a)return a;var b=new a.constructor;for(var c in a)a[g](c)&&(b[c]=bm(a[c]));return b}function a(c){if(a.is(c,\"function\"))return b?c():eve.on(\"raphael.DOMload\",c);if(a.is(c,E))return a._engine.create[m](a,c.splice(0,3+a.is(c[0],C))).add(c);var d=Array.prototype.slice.call(arguments,0);if(a.is(d[d.length-1],\"function\")){var e=d.pop();return b?e.call(a._engine.create[m](a,d)):eve.on(\"raphael.DOMload\",function(){e.call(a._engine.create[m](a,d))})}return a._engine.create[m](a,arguments)}a.version=\"2.1.0\",a.eve=eve;var b,c=/[, ]+/,d={circle:1,rect:1,path:1,ellipse:1,text:1,image:1},e=/\\{(\\d+)\\}/g,f=\"prototype\",g=\"hasOwnProperty\",h={doc:document,win:window},i={was:Object.prototype[g].call(h.win,\"Raphael\"),is:h.win.Raphael},j=function(){this.ca=this.customAttributes={}},k,l=\"appendChild\",m=\"apply\",n=\"concat\",o=\"createTouch\"in h.doc,p=\"\",q=\" \",r=String,s=\"split\",t=\"click dblclick mousedown mousemove mouseout mouseover mouseup touchstart touchmove touchend touchcancel\"[s](q),u={mousedown:\"touchstart\",mousemove:\"touchmove\",mouseup:\"touchend\"},v=r.prototype.toLowerCase,w=Math,x=w.max,y=w.min,z=w.abs,A=w.pow,B=w.PI,C=\"number\",D=\"string\",E=\"array\",F=\"toString\",G=\"fill\",H=Object.prototype.toString,I={},J=\"push\",K=a._ISURL=/^url\\(['\"]?([^\\)]+?)['\"]?\\)$/i,L=/^\\s*((#[a-f\\d]{6})|(#[a-f\\d]{3})|rgba?\\(\\s*([\\d\\.]+%?\\s*,\\s*[\\d\\.]+%?\\s*,\\s*[\\d\\.]+%?(?:\\s*,\\s*[\\d\\.]+%?)?)\\s*\\)|hsba?\\(\\s*([\\d\\.]+(?:deg|\\xb0|%)?\\s*,\\s*[\\d\\.]+%?\\s*,\\s*[\\d\\.]+(?:%?\\s*,\\s*[\\d\\.]+)?)%?\\s*\\)|hsla?\\(\\s*([\\d\\.]+(?:deg|\\xb0|%)?\\s*,\\s*[\\d\\.]+%?\\s*,\\s*[\\d\\.]+(?:%?\\s*,\\s*[\\d\\.]+)?)%?\\s*\\))\\s*$/i,M={NaN:1,Infinity:1,\"-Infinity\":1},N=/^(?:cubic-)?bezier\\(([^,]+),([^,]+),([^,]+),([^\\)]+)\\)/,O=w.round,P=\"setAttribute\",Q=parseFloat,R=parseInt,S=r.prototype.toUpperCase,T=a._availableAttrs={\"arrow-end\":\"none\",\"arrow-start\":\"none\",blur:0,\"clip-rect\":\"0 0 1e9 1e9\",cursor:\"default\",cx:0,cy:0,fill:\"#fff\",\"fill-opacity\":1,font:'10px \"Arial\"',\"font-family\":'\"Arial\"',\"font-size\":\"10\",\"font-style\":\"normal\",\"font-weight\":400,gradient:0,height:0,href:\"http://raphaeljs.com/\",\"letter-spacing\":0,opacity:1,path:\"M0,0\",r:0,rx:0,ry:0,src:\"\",stroke:\"#000\",\"stroke-dasharray\":\"\",\"stroke-linecap\":\"butt\",\"stroke-linejoin\":\"butt\",\"stroke-miterlimit\":0,\"stroke-opacity\":1,\"stroke-width\":1,target:\"_blank\",\"text-anchor\":\"middle\",title:\"Raphael\",transform:\"\",width:0,x:0,y:0},U=a._availableAnimAttrs={blur:C,\"clip-rect\":\"csv\",cx:C,cy:C,fill:\"colour\",\"fill-opacity\":C,\"font-size\":C,height:C,opacity:C,path:\"path\",r:C,rx:C,ry:C,stroke:\"colour\",\"stroke-opacity\":C,\"stroke-width\":C,transform:\"transform\",width:C,x:C,y:C},V=/[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]/g,W=/[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*,[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*/,X={hs:1,rg:1},Y=/,?([achlmqrstvxz]),?/gi,Z=/([achlmrqstvz])[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029,]*((-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*,?[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*)+)/ig,$=/([rstm])[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029,]*((-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*,?[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*)+)/ig,_=/(-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?)[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*,?[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*/ig,ba=a._radial_gradient=/^r(?:\\(([^,]+?)[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*,[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*([^\\)]+?)\\))?/,bb={},bc=function(a,b){return a.key-b.key},bd=function(a,b){return Q(a)-Q(b)},be=function(){},bf=function(a){return a},bg=a._rectPath=function(a,b,c,d,e){if(e)return[[\"M\",a+e,b],[\"l\",c-e*2,0],[\"a\",e,e,0,0,1,e,e],[\"l\",0,d-e*2],[\"a\",e,e,0,0,1,-e,e],[\"l\",e*2-c,0],[\"a\",e,e,0,0,1,-e,-e],[\"l\",0,e*2-d],[\"a\",e,e,0,0,1,e,-e],[\"z\"]];return[[\"M\",a,b],[\"l\",c,0],[\"l\",0,d],[\"l\",-c,0],[\"z\"]]},bh=function(a,b,c,d){d==null&&(d=c);return[[\"M\",a,b],[\"m\",0,-d],[\"a\",c,d,0,1,1,0,2*d],[\"a\",c,d,0,1,1,0,-2*d],[\"z\"]]},bi=a._getPath={path:function(a){return a.attr(\"path\")},circle:function(a){var b=a.attrs;return bh(b.cx,b.cy,b.r)},ellipse:function(a){var b=a.attrs;return bh(b.cx,b.cy,b.rx,b.ry)},rect:function(a){var b=a.attrs;return bg(b.x,b.y,b.width,b.height,b.r)},image:function(a){var b=a.attrs;return bg(b.x,b.y,b.width,b.height)},text:function(a){var b=a._getBBox();return bg(b.x,b.y,b.width,b.height)}},bj=a.mapPath=function(a,b){if(!b)return a;var c,d,e,f,g,h,i;a=bR(a);for(e=0,g=a.length;e<g;e++){i=a[e];for(f=1,h=i.length;f<h;f+=2)c=b.x(i[f],i[f+1]),d=b.y(i[f],i[f+1]),i[f]=c,i[f+1]=d}return a};a._g=h,a.type=h.win.SVGAngle||h.doc.implementation.hasFeature(\"http://www.w3.org/TR/SVG11/feature#BasicStructure\",\"1.1\")?\"SVG\":\"VML\";if(a.type==\"VML\"){var bk=h.doc.createElement(\"div\"),bl;bk.innerHTML='<v:shape adj=\"1\"/>',bl=bk.firstChild,bl.style.behavior=\"url(#default#VML)\";if(!bl||typeof bl.adj!=\"object\")return a.type=p;bk=null}a.svg=!(a.vml=a.type==\"VML\"),a._Paper=j,a.fn=k=j.prototype=a.prototype,a._id=0,a._oid=0,a.is=function(a,b){b=v.call(b);if(b==\"finite\")return!M[g](+a);if(b==\"array\")return a instanceof Array;return b==\"null\"&&a===null||b==typeof a&&a!==null||b==\"object\"&&a===Object(a)||b==\"array\"&&Array.isArray&&Array.isArray(a)||H.call(a).slice(8,-1).toLowerCase()==b},a.angle=function(b,c,d,e,f,g){if(f==null){var h=b-d,i=c-e;if(!h&&!i)return 0;return(180+w.atan2(-i,-h)*180/B+360)%360}return a.angle(b,c,f,g)-a.angle(d,e,f,g)},a.rad=function(a){return a%360*B/180},a.deg=function(a){return a*180/B%360},a.snapTo=function(b,c,d){d=a.is(d,\"finite\")?d:10;if(a.is(b,E)){var e=b.length;while(e--)if(z(b[e]-c)<=d)return b[e]}else{b=+b;var f=c%b;if(f<d)return c-f;if(f>b-d)return c-f+b}return c};var bn=a.createUUID=function(a,b){return function(){return\"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(a,b).toUpperCase()}}(/[xy]/g,function(a){var b=w.random()*16|0,c=a==\"x\"?b:b&3|8;return c.toString(16)});a.setWindow=function(b){eve(\"raphael.setWindow\",a,h.win,b),h.win=b,h.doc=h.win.document,a._engine.initWin&&a._engine.initWin(h.win)};var bo=function(b){if(a.vml){var c=/^\\s+|\\s+$/g,d;try{var e=new ActiveXObject(\"htmlfile\");e.write(\"<body>\"),e.close(),d=e.body}catch(f){d=createPopup().document.body}var g=d.createTextRange();bo=bv(function(a){try{d.style.color=r(a).replace(c,p);var b=g.queryCommandValue(\"ForeColor\");b=(b&255)<<16|b&65280|(b&16711680)>>>16;return\"#\"+(\"000000\"+b.toString(16)).slice(-6)}catch(e){return\"none\"}})}else{var i=h.doc.createElement(\"i\");i.title=\"Raphaël Colour Picker\",i.style.display=\"none\",h.doc.body.appendChild(i),bo=bv(function(a){i.style.color=a;return h.doc.defaultView.getComputedStyle(i,p).getPropertyValue(\"color\")})}return bo(b)},bp=function(){return\"hsb(\"+[this.h,this.s,this.b]+\")\"},bq=function(){return\"hsl(\"+[this.h,this.s,this.l]+\")\"},br=function(){return this.hex},bs=function(b,c,d){c==null&&a.is(b,\"object\")&&\"r\"in b&&\"g\"in b&&\"b\"in b&&(d=b.b,c=b.g,b=b.r);if(c==null&&a.is(b,D)){var e=a.getRGB(b);b=e.r,c=e.g,d=e.b}if(b>1||c>1||d>1)b/=255,c/=255,d/=255;return[b,c,d]},bt=function(b,c,d,e){b*=255,c*=255,d*=255;var f={r:b,g:c,b:d,hex:a.rgb(b,c,d),toString:br};a.is(e,\"finite\")&&(f.opacity=e);return f};a.color=function(b){var c;a.is(b,\"object\")&&\"h\"in b&&\"s\"in b&&\"b\"in b?(c=a.hsb2rgb(b),b.r=c.r,b.g=c.g,b.b=c.b,b.hex=c.hex):a.is(b,\"object\")&&\"h\"in b&&\"s\"in b&&\"l\"in b?(c=a.hsl2rgb(b),b.r=c.r,b.g=c.g,b.b=c.b,b.hex=c.hex):(a.is(b,\"string\")&&(b=a.getRGB(b)),a.is(b,\"object\")&&\"r\"in b&&\"g\"in b&&\"b\"in b?(c=a.rgb2hsl(b),b.h=c.h,b.s=c.s,b.l=c.l,c=a.rgb2hsb(b),b.v=c.b):(b={hex:\"none\"},b.r=b.g=b.b=b.h=b.s=b.v=b.l=-1)),b.toString=br;return b},a.hsb2rgb=function(a,b,c,d){this.is(a,\"object\")&&\"h\"in a&&\"s\"in a&&\"b\"in a&&(c=a.b,b=a.s,a=a.h,d=a.o),a*=360;var e,f,g,h,i;a=a%360/60,i=c*b,h=i*(1-z(a%2-1)),e=f=g=c-i,a=~~a,e+=[i,h,0,0,h,i][a],f+=[h,i,i,h,0,0][a],g+=[0,0,h,i,i,h][a];return bt(e,f,g,d)},a.hsl2rgb=function(a,b,c,d){this.is(a,\"object\")&&\"h\"in a&&\"s\"in a&&\"l\"in a&&(c=a.l,b=a.s,a=a.h);if(a>1||b>1||c>1)a/=360,b/=100,c/=100;a*=360;var e,f,g,h,i;a=a%360/60,i=2*b*(c<.5?c:1-c),h=i*(1-z(a%2-1)),e=f=g=c-i/2,a=~~a,e+=[i,h,0,0,h,i][a],f+=[h,i,i,h,0,0][a],g+=[0,0,h,i,i,h][a];return bt(e,f,g,d)},a.rgb2hsb=function(a,b,c){c=bs(a,b,c),a=c[0],b=c[1],c=c[2];var d,e,f,g;f=x(a,b,c),g=f-y(a,b,c),d=g==0?null:f==a?(b-c)/g:f==b?(c-a)/g+2:(a-b)/g+4,d=(d+360)%6*60/360,e=g==0?0:g/f;return{h:d,s:e,b:f,toString:bp}},a.rgb2hsl=function(a,b,c){c=bs(a,b,c),a=c[0],b=c[1],c=c[2];var d,e,f,g,h,i;g=x(a,b,c),h=y(a,b,c),i=g-h,d=i==0?null:g==a?(b-c)/i:g==b?(c-a)/i+2:(a-b)/i+4,d=(d+360)%6*60/360,f=(g+h)/2,e=i==0?0:f<.5?i/(2*f):i/(2-2*f);return{h:d,s:e,l:f,toString:bq}},a._path2string=function(){return this.join(\",\").replace(Y,\"$1\")};var bw=a._preload=function(a,b){var c=h.doc.createElement(\"img\");c.style.cssText=\"position:absolute;left:-9999em;top:-9999em\",c.onload=function(){b.call(this),this.onload=null,h.doc.body.removeChild(this)},c.onerror=function(){h.doc.body.removeChild(this)},h.doc.body.appendChild(c),c.src=a};a.getRGB=bv(function(b){if(!b||!!((b=r(b)).indexOf(\"-\")+1))return{r:-1,g:-1,b:-1,hex:\"none\",error:1,toString:bx};if(b==\"none\")return{r:-1,g:-1,b:-1,hex:\"none\",toString:bx};!X[g](b.toLowerCase().substring(0,2))&&b.charAt()!=\"#\"&&(b=bo(b));var c,d,e,f,h,i,j,k=b.match(L);if(k){k[2]&&(f=R(k[2].substring(5),16),e=R(k[2].substring(3,5),16),d=R(k[2].substring(1,3),16)),k[3]&&(f=R((i=k[3].charAt(3))+i,16),e=R((i=k[3].charAt(2))+i,16),d=R((i=k[3].charAt(1))+i,16)),k[4]&&(j=k[4][s](W),d=Q(j[0]),j[0].slice(-1)==\"%\"&&(d*=2.55),e=Q(j[1]),j[1].slice(-1)==\"%\"&&(e*=2.55),f=Q(j[2]),j[2].slice(-1)==\"%\"&&(f*=2.55),k[1].toLowerCase().slice(0,4)==\"rgba\"&&(h=Q(j[3])),j[3]&&j[3].slice(-1)==\"%\"&&(h/=100));if(k[5]){j=k[5][s](W),d=Q(j[0]),j[0].slice(-1)==\"%\"&&(d*=2.55),e=Q(j[1]),j[1].slice(-1)==\"%\"&&(e*=2.55),f=Q(j[2]),j[2].slice(-1)==\"%\"&&(f*=2.55),(j[0].slice(-3)==\"deg\"||j[0].slice(-1)==\"°\")&&(d/=360),k[1].toLowerCase().slice(0,4)==\"hsba\"&&(h=Q(j[3])),j[3]&&j[3].slice(-1)==\"%\"&&(h/=100);return a.hsb2rgb(d,e,f,h)}if(k[6]){j=k[6][s](W),d=Q(j[0]),j[0].slice(-1)==\"%\"&&(d*=2.55),e=Q(j[1]),j[1].slice(-1)==\"%\"&&(e*=2.55),f=Q(j[2]),j[2].slice(-1)==\"%\"&&(f*=2.55),(j[0].slice(-3)==\"deg\"||j[0].slice(-1)==\"°\")&&(d/=360),k[1].toLowerCase().slice(0,4)==\"hsla\"&&(h=Q(j[3])),j[3]&&j[3].slice(-1)==\"%\"&&(h/=100);return a.hsl2rgb(d,e,f,h)}k={r:d,g:e,b:f,toString:bx},k.hex=\"#\"+(16777216|f|e<<8|d<<16).toString(16).slice(1),a.is(h,\"finite\")&&(k.opacity=h);return k}return{r:-1,g:-1,b:-1,hex:\"none\",error:1,toString:bx}},a),a.hsb=bv(function(b,c,d){return a.hsb2rgb(b,c,d).hex}),a.hsl=bv(function(b,c,d){return a.hsl2rgb(b,c,d).hex}),a.rgb=bv(function(a,b,c){return\"#\"+(16777216|c|b<<8|a<<16).toString(16).slice(1)}),a.getColor=function(a){var b=this.getColor.start=this.getColor.start||{h:0,s:1,b:a||.75},c=this.hsb2rgb(b.h,b.s,b.b);b.h+=.075,b.h>1&&(b.h=0,b.s-=.2,b.s<=0&&(this.getColor.start={h:0,s:1,b:b.b}));return c.hex},a.getColor.reset=function(){delete this.start},a.parsePathString=function(b){if(!b)return null;var c=bz(b);if(c.arr)return bJ(c.arr);var d={a:7,c:6,h:1,l:2,m:2,r:4,q:4,s:4,t:2,v:1,z:0},e=[];a.is(b,E)&&a.is(b[0],E)&&(e=bJ(b)),e.length||r(b).replace(Z,function(a,b,c){var f=[],g=b.toLowerCase();c.replace(_,function(a,b){b&&f.push(+b)}),g==\"m\"&&f.length>2&&(e.push([b][n](f.splice(0,2))),g=\"l\",b=b==\"m\"?\"l\":\"L\");if(g==\"r\")e.push([b][n](f));else while(f.length>=d[g]){e.push([b][n](f.splice(0,d[g])));if(!d[g])break}}),e.toString=a._path2string,c.arr=bJ(e);return e},a.parseTransformString=bv(function(b){if(!b)return null;var c={r:3,s:4,t:2,m:6},d=[];a.is(b,E)&&a.is(b[0],E)&&(d=bJ(b)),d.length||r(b).replace($,function(a,b,c){var e=[],f=v.call(b);c.replace(_,function(a,b){b&&e.push(+b)}),d.push([b][n](e))}),d.toString=a._path2string;return d});var bz=function(a){var b=bz.ps=bz.ps||{};b[a]?b[a].sleep=100:b[a]={sleep:100},setTimeout(function(){for(var c in b)b[g](c)&&c!=a&&(b[c].sleep--,!b[c].sleep&&delete b[c])});return b[a]};a.findDotsAtSegment=function(a,b,c,d,e,f,g,h,i){var j=1-i,k=A(j,3),l=A(j,2),m=i*i,n=m*i,o=k*a+l*3*i*c+j*3*i*i*e+n*g,p=k*b+l*3*i*d+j*3*i*i*f+n*h,q=a+2*i*(c-a)+m*(e-2*c+a),r=b+2*i*(d-b)+m*(f-2*d+b),s=c+2*i*(e-c)+m*(g-2*e+c),t=d+2*i*(f-d)+m*(h-2*f+d),u=j*a+i*c,v=j*b+i*d,x=j*e+i*g,y=j*f+i*h,z=90-w.atan2(q-s,r-t)*180/B;(q>s||r<t)&&(z+=180);return{x:o,y:p,m:{x:q,y:r},n:{x:s,y:t},start:{x:u,y:v},end:{x:x,y:y},alpha:z}},a.bezierBBox=function(b,c,d,e,f,g,h,i){a.is(b,\"array\")||(b=[b,c,d,e,f,g,h,i]);var j=bQ.apply(null,b);return{x:j.min.x,y:j.min.y,x2:j.max.x,y2:j.max.y,width:j.max.x-j.min.x,height:j.max.y-j.min.y}},a.isPointInsideBBox=function(a,b,c){return b>=a.x&&b<=a.x2&&c>=a.y&&c<=a.y2},a.isBBoxIntersect=function(b,c){var d=a.isPointInsideBBox;return d(c,b.x,b.y)||d(c,b.x2,b.y)||d(c,b.x,b.y2)||d(c,b.x2,b.y2)||d(b,c.x,c.y)||d(b,c.x2,c.y)||d(b,c.x,c.y2)||d(b,c.x2,c.y2)||(b.x<c.x2&&b.x>c.x||c.x<b.x2&&c.x>b.x)&&(b.y<c.y2&&b.y>c.y||c.y<b.y2&&c.y>b.y)},a.pathIntersection=function(a,b){return bH(a,b)},a.pathIntersectionNumber=function(a,b){return bH(a,b,1)},a.isPointInsidePath=function(b,c,d){var e=a.pathBBox(b);return a.isPointInsideBBox(e,c,d)&&bH(b,[[\"M\",c,d],[\"H\",e.x2+10]],1)%2==1},a._removedFactory=function(a){return function(){eve(\"raphael.log\",null,\"Raphaël: you are calling to method “\"+a+\"” of removed object\",a)}};var bI=a.pathBBox=function(a){var b=bz(a);if(b.bbox)return bm(b.bbox);if(!a)return{x:0,y:0,width:0,height:0,x2:0,y2:0};a=bR(a);var c=0,d=0,e=[],f=[],g;for(var h=0,i=a.length;h<i;h++){g=a[h];if(g[0]==\"M\")c=g[1],d=g[2],e.push(c),f.push(d);else{var j=bQ(c,d,g[1],g[2],g[3],g[4],g[5],g[6]);e=e[n](j.min.x,j.max.x),f=f[n](j.min.y,j.max.y),c=g[5],d=g[6]}}var k=y[m](0,e),l=y[m](0,f),o=x[m](0,e),p=x[m](0,f),q={x:k,y:l,x2:o,y2:p,width:o-k,height:p-l};b.bbox=bm(q);return q},bJ=function(b){var c=bm(b);c.toString=a._path2string;return c},bK=a._pathToRelative=function(b){var c=bz(b);if(c.rel)return bJ(c.rel);if(!a.is(b,E)||!a.is(b&&b[0],E))b=a.parsePathString(b);var d=[],e=0,f=0,g=0,h=0,i=0;b[0][0]==\"M\"&&(e=b[0][1],f=b[0][2],g=e,h=f,i++,d.push([\"M\",e,f]));for(var j=i,k=b.length;j<k;j++){var l=d[j]=[],m=b[j];if(m[0]!=v.call(m[0])){l[0]=v.call(m[0]);switch(l[0]){case\"a\":l[1]=m[1],l[2]=m[2],l[3]=m[3],l[4]=m[4],l[5]=m[5],l[6]=+(m[6]-e).toFixed(3),l[7]=+(m[7]-f).toFixed(3);break;case\"v\":l[1]=+(m[1]-f).toFixed(3);break;case\"m\":g=m[1],h=m[2];default:for(var n=1,o=m.length;n<o;n++)l[n]=+(m[n]-(n%2?e:f)).toFixed(3)}}else{l=d[j]=[],m[0]==\"m\"&&(g=m[1]+e,h=m[2]+f);for(var p=0,q=m.length;p<q;p++)d[j][p]=m[p]}var r=d[j].length;switch(d[j][0]){case\"z\":e=g,f=h;break;case\"h\":e+=+d[j][r-1];break;case\"v\":f+=+d[j][r-1];break;default:e+=+d[j][r-2],f+=+d[j][r-1]}}d.toString=a._path2string,c.rel=bJ(d);return d},bL=a._pathToAbsolute=function(b){var c=bz(b);if(c.abs)return bJ(c.abs);if(!a.is(b,E)||!a.is(b&&b[0],E))b=a.parsePathString(b);if(!b||!b.length)return[[\"M\",0,0]];var d=[],e=0,f=0,g=0,h=0,i=0;b[0][0]==\"M\"&&(e=+b[0][1],f=+b[0][2],g=e,h=f,i++,d[0]=[\"M\",e,f]);var j=b.length==3&&b[0][0]==\"M\"&&b[1][0].toUpperCase()==\"R\"&&b[2][0].toUpperCase()==\"Z\";for(var k,l,m=i,o=b.length;m<o;m++){d.push(k=[]),l=b[m];if(l[0]!=S.call(l[0])){k[0]=S.call(l[0]);switch(k[0]){case\"A\":k[1]=l[1],k[2]=l[2],k[3]=l[3],k[4]=l[4],k[5]=l[5],k[6]=+(l[6]+e),k[7]=+(l[7]+f);break;case\"V\":k[1]=+l[1]+f;break;case\"H\":k[1]=+l[1]+e;break;case\"R\":var p=[e,f][n](l.slice(1));for(var q=2,r=p.length;q<r;q++)p[q]=+p[q]+e,p[++q]=+p[q]+f;d.pop(),d=d[n](by(p,j));break;case\"M\":g=+l[1]+e,h=+l[2]+f;default:for(q=1,r=l.length;q<r;q++)k[q]=+l[q]+(q%2?e:f)}}else if(l[0]==\"R\")p=[e,f][n](l.slice(1)),d.pop(),d=d[n](by(p,j)),k=[\"R\"][n](l.slice(-2));else for(var s=0,t=l.length;s<t;s++)k[s]=l[s];switch(k[0]){case\"Z\":e=g,f=h;break;case\"H\":e=k[1];break;case\"V\":f=k[1];break;case\"M\":g=k[k.length-2],h=k[k.length-1];default:e=k[k.length-2],f=k[k.length-1]}}d.toString=a._path2string,c.abs=bJ(d);return d},bM=function(a,b,c,d){return[a,b,c,d,c,d]},bN=function(a,b,c,d,e,f){var g=1/3,h=2/3;return[g*a+h*c,g*b+h*d,g*e+h*c,g*f+h*d,e,f]},bO=function(a,b,c,d,e,f,g,h,i,j){var k=B*120/180,l=B/180*(+e||0),m=[],o,p=bv(function(a,b,c){var d=a*w.cos(c)-b*w.sin(c),e=a*w.sin(c)+b*w.cos(c);return{x:d,y:e}});if(!j){o=p(a,b,-l),a=o.x,b=o.y,o=p(h,i,-l),h=o.x,i=o.y;var q=w.cos(B/180*e),r=w.sin(B/180*e),t=(a-h)/2,u=(b-i)/2,v=t*t/(c*c)+u*u/(d*d);v>1&&(v=w.sqrt(v),c=v*c,d=v*d);var x=c*c,y=d*d,A=(f==g?-1:1)*w.sqrt(z((x*y-x*u*u-y*t*t)/(x*u*u+y*t*t))),C=A*c*u/d+(a+h)/2,D=A*-d*t/c+(b+i)/2,E=w.asin(((b-D)/d).toFixed(9)),F=w.asin(((i-D)/d).toFixed(9));E=a<C?B-E:E,F=h<C?B-F:F,E<0&&(E=B*2+E),F<0&&(F=B*2+F),g&&E>F&&(E=E-B*2),!g&&F>E&&(F=F-B*2)}else E=j[0],F=j[1],C=j[2],D=j[3];var G=F-E;if(z(G)>k){var H=F,I=h,J=i;F=E+k*(g&&F>E?1:-1),h=C+c*w.cos(F),i=D+d*w.sin(F),m=bO(h,i,c,d,e,0,g,I,J,[F,H,C,D])}G=F-E;var K=w.cos(E),L=w.sin(E),M=w.cos(F),N=w.sin(F),O=w.tan(G/4),P=4/3*c*O,Q=4/3*d*O,R=[a,b],S=[a+P*L,b-Q*K],T=[h+P*N,i-Q*M],U=[h,i];S[0]=2*R[0]-S[0],S[1]=2*R[1]-S[1];if(j)return[S,T,U][n](m);m=[S,T,U][n](m).join()[s](\",\");var V=[];for(var W=0,X=m.length;W<X;W++)V[W]=W%2?p(m[W-1],m[W],l).y:p(m[W],m[W+1],l).x;return V},bP=function(a,b,c,d,e,f,g,h,i){var j=1-i;return{x:A(j,3)*a+A(j,2)*3*i*c+j*3*i*i*e+A(i,3)*g,y:A(j,3)*b+A(j,2)*3*i*d+j*3*i*i*f+A(i,3)*h}},bQ=bv(function(a,b,c,d,e,f,g,h){var i=e-2*c+a-(g-2*e+c),j=2*(c-a)-2*(e-c),k=a-c,l=(-j+w.sqrt(j*j-4*i*k))/2/i,n=(-j-w.sqrt(j*j-4*i*k))/2/i,o=[b,h],p=[a,g],q;z(l)>\"1e12\"&&(l=.5),z(n)>\"1e12\"&&(n=.5),l>0&&l<1&&(q=bP(a,b,c,d,e,f,g,h,l),p.push(q.x),o.push(q.y)),n>0&&n<1&&(q=bP(a,b,c,d,e,f,g,h,n),p.push(q.x),o.push(q.y)),i=f-2*d+b-(h-2*f+d),j=2*(d-b)-2*(f-d),k=b-d,l=(-j+w.sqrt(j*j-4*i*k))/2/i,n=(-j-w.sqrt(j*j-4*i*k))/2/i,z(l)>\"1e12\"&&(l=.5),z(n)>\"1e12\"&&(n=.5),l>0&&l<1&&(q=bP(a,b,c,d,e,f,g,h,l),p.push(q.x),o.push(q.y)),n>0&&n<1&&(q=bP(a,b,c,d,e,f,g,h,n),p.push(q.x),o.push(q.y));return{min:{x:y[m](0,p),y:y[m](0,o)},max:{x:x[m](0,p),y:x[m](0,o)}}}),bR=a._path2curve=bv(function(a,b){var c=!b&&bz(a);if(!b&&c.curve)return bJ(c.curve);var d=bL(a),e=b&&bL(b),f={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},g={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},h=function(a,b){var c,d;if(!a)return[\"C\",b.x,b.y,b.x,b.y,b.x,b.y];!(a[0]in{T:1,Q:1})&&(b.qx=b.qy=null);switch(a[0]){case\"M\":b.X=a[1],b.Y=a[2];break;case\"A\":a=[\"C\"][n](bO[m](0,[b.x,b.y][n](a.slice(1))));break;case\"S\":c=b.x+(b.x-(b.bx||b.x)),d=b.y+(b.y-(b.by||b.y)),a=[\"C\",c,d][n](a.slice(1));break;case\"T\":b.qx=b.x+(b.x-(b.qx||b.x)),b.qy=b.y+(b.y-(b.qy||b.y)),a=[\"C\"][n](bN(b.x,b.y,b.qx,b.qy,a[1],a[2]));break;case\"Q\":b.qx=a[1],b.qy=a[2],a=[\"C\"][n](bN(b.x,b.y,a[1],a[2],a[3],a[4]));break;case\"L\":a=[\"C\"][n](bM(b.x,b.y,a[1],a[2]));break;case\"H\":a=[\"C\"][n](bM(b.x,b.y,a[1],b.y));break;case\"V\":a=[\"C\"][n](bM(b.x,b.y,b.x,a[1]));break;case\"Z\":a=[\"C\"][n](bM(b.x,b.y,b.X,b.Y))}return a},i=function(a,b){if(a[b].length>7){a[b].shift();var c=a[b];while(c.length)a.splice(b++,0,[\"C\"][n](c.splice(0,6)));a.splice(b,1),l=x(d.length,e&&e.length||0)}},j=function(a,b,c,f,g){a&&b&&a[g][0]==\"M\"&&b[g][0]!=\"M\"&&(b.splice(g,0,[\"M\",f.x,f.y]),c.bx=0,c.by=0,c.x=a[g][1],c.y=a[g][2],l=x(d.length,e&&e.length||0))};for(var k=0,l=x(d.length,e&&e.length||0);k<l;k++){d[k]=h(d[k],f),i(d,k),e&&(e[k]=h(e[k],g)),e&&i(e,k),j(d,e,f,g,k),j(e,d,g,f,k);var o=d[k],p=e&&e[k],q=o.length,r=e&&p.length;f.x=o[q-2],f.y=o[q-1],f.bx=Q(o[q-4])||f.x,f.by=Q(o[q-3])||f.y,g.bx=e&&(Q(p[r-4])||g.x),g.by=e&&(Q(p[r-3])||g.y),g.x=e&&p[r-2],g.y=e&&p[r-1]}e||(c.curve=bJ(d));return e?[d,e]:d},null,bJ),bS=a._parseDots=bv(function(b){var c=[];for(var d=0,e=b.length;d<e;d++){var f={},g=b[d].match(/^([^:]*):?([\\d\\.]*)/);f.color=a.getRGB(g[1]);if(f.color.error)return null;f.color=f.color.hex,g[2]&&(f.offset=g[2]+\"%\"),c.push(f)}for(d=1,e=c.length-1;d<e;d++)if(!c[d].offset){var h=Q(c[d-1].offset||0),i=0;for(var j=d+1;j<e;j++)if(c[j].offset){i=c[j].offset;break}i||(i=100,j=e),i=Q(i);var k=(i-h)/(j-d+1);for(;d<j;d++)h+=k,c[d].offset=h+\"%\"}return c}),bT=a._tear=function(a,b){a==b.top&&(b.top=a.prev),a==b.bottom&&(b.bottom=a.next),a.next&&(a.next.prev=a.prev),a.prev&&(a.prev.next=a.next)},bU=a._tofront=function(a,b){b.top!==a&&(bT(a,b),a.next=null,a.prev=b.top,b.top.next=a,b.top=a)},bV=a._toback=function(a,b){b.bottom!==a&&(bT(a,b),a.next=b.bottom,a.prev=null,b.bottom.prev=a,b.bottom=a)},bW=a._insertafter=function(a,b,c){bT(a,c),b==c.top&&(c.top=a),b.next&&(b.next.prev=a),a.next=b.next,a.prev=b,b.next=a},bX=a._insertbefore=function(a,b,c){bT(a,c),b==c.bottom&&(c.bottom=a),b.prev&&(b.prev.next=a),a.prev=b.prev,b.prev=a,a.next=b},bY=a.toMatrix=function(a,b){var c=bI(a),d={_:{transform:p},getBBox:function(){return c}};b$(d,b);return d.matrix},bZ=a.transformPath=function(a,b){return bj(a,bY(a,b))},b$=a._extractTransform=function(b,c){if(c==null)return b._.transform;c=r(c).replace(/\\.{3}|\\u2026/g,b._.transform||p);var d=a.parseTransformString(c),e=0,f=0,g=0,h=1,i=1,j=b._,k=new cb;j.transform=d||[];if(d)for(var l=0,m=d.length;l<m;l++){var n=d[l],o=n.length,q=r(n[0]).toLowerCase(),s=n[0]!=q,t=s?k.invert():0,u,v,w,x,y;q==\"t\"&&o==3?s?(u=t.x(0,0),v=t.y(0,0),w=t.x(n[1],n[2]),x=t.y(n[1],n[2]),k.translate(w-u,x-v)):k.translate(n[1],n[2]):q==\"r\"?o==2?(y=y||b.getBBox(1),k.rotate(n[1],y.x+y.width/2,y.y+y.height/2),e+=n[1]):o==4&&(s?(w=t.x(n[2],n[3]),x=t.y(n[2],n[3]),k.rotate(n[1],w,x)):k.rotate(n[1],n[2],n[3]),e+=n[1]):q==\"s\"?o==2||o==3?(y=y||b.getBBox(1),k.scale(n[1],n[o-1],y.x+y.width/2,y.y+y.height/2),h*=n[1],i*=n[o-1]):o==5&&(s?(w=t.x(n[3],n[4]),x=t.y(n[3],n[4]),k.scale(n[1],n[2],w,x)):k.scale(n[1],n[2],n[3],n[4]),h*=n[1],i*=n[2]):q==\"m\"&&o==7&&k.add(n[1],n[2],n[3],n[4],n[5],n[6]),j.dirtyT=1,b.matrix=k}b.matrix=k,j.sx=h,j.sy=i,j.deg=e,j.dx=f=k.e,j.dy=g=k.f,h==1&&i==1&&!e&&j.bbox?(j.bbox.x+=+f,j.bbox.y+=+g):j.dirtyT=1},b_=function(a){var b=a[0];switch(b.toLowerCase()){case\"t\":return[b,0,0];case\"m\":return[b,1,0,0,1,0,0];case\"r\":return a.length==4?[b,0,a[2],a[3]]:[b,0];case\"s\":return a.length==5?[b,1,1,a[3],a[4]]:a.length==3?[b,1,1]:[b,1]}},ca=a._equaliseTransform=function(b,c){c=r(c).replace(/\\.{3}|\\u2026/g,b),b=a.parseTransformString(b)||[],c=a.parseTransformString(c)||[];var d=x(b.length,c.length),e=[],f=[],g=0,h,i,j,k;for(;g<d;g++){j=b[g]||b_(c[g]),k=c[g]||b_(j);if(j[0]!=k[0]||j[0].toLowerCase()==\"r\"&&(j[2]!=k[2]||j[3]!=k[3])||j[0].toLowerCase()==\"s\"&&(j[3]!=k[3]||j[4]!=k[4]))return;e[g]=[],f[g]=[];for(h=0,i=x(j.length,k.length);h<i;h++)h in j&&(e[g][h]=j[h]),h in k&&(f[g][h]=k[h])}return{from:e,to:f}};a._getContainer=function(b,c,d,e){var f;f=e==null&&!a.is(b,\"object\")?h.doc.getElementById(b):b;if(f!=null){if(f.tagName)return c==null?{container:f,width:f.style.pixelWidth||f.offsetWidth,height:f.style.pixelHeight||f.offsetHeight}:{container:f,width:c,height:d};return{container:1,x:b,y:c,width:d,height:e}}},a.pathToRelative=bK,a._engine={},a.path2curve=bR,a.matrix=function(a,b,c,d,e,f){return new cb(a,b,c,d,e,f)},function(b){function d(a){var b=w.sqrt(c(a));a[0]&&(a[0]/=b),a[1]&&(a[1]/=b)}function c(a){return a[0]*a[0]+a[1]*a[1]}b.add=function(a,b,c,d,e,f){var g=[[],[],[]],h=[[this.a,this.c,this.e],[this.b,this.d,this.f],[0,0,1]],i=[[a,c,e],[b,d,f],[0,0,1]],j,k,l,m;a&&a instanceof cb&&(i=[[a.a,a.c,a.e],[a.b,a.d,a.f],[0,0,1]]);for(j=0;j<3;j++)for(k=0;k<3;k++){m=0;for(l=0;l<3;l++)m+=h[j][l]*i[l][k];g[j][k]=m}this.a=g[0][0],this.b=g[1][0],this.c=g[0][1],this.d=g[1][1],this.e=g[0][2],this.f=g[1][2]},b.invert=function(){var a=this,b=a.a*a.d-a.b*a.c;return new cb(a.d/b,-a.b/b,-a.c/b,a.a/b,(a.c*a.f-a.d*a.e)/b,(a.b*a.e-a.a*a.f)/b)},b.clone=function(){return new cb(this.a,this.b,this.c,this.d,this.e,this.f)},b.translate=function(a,b){this.add(1,0,0,1,a,b)},b.scale=function(a,b,c,d){b==null&&(b=a),(c||d)&&this.add(1,0,0,1,c,d),this.add(a,0,0,b,0,0),(c||d)&&this.add(1,0,0,1,-c,-d)},b.rotate=function(b,c,d){b=a.rad(b),c=c||0,d=d||0;var e=+w.cos(b).toFixed(9),f=+w.sin(b).toFixed(9);this.add(e,f,-f,e,c,d),this.add(1,0,0,1,-c,-d)},b.x=function(a,b){return a*this.a+b*this.c+this.e},b.y=function(a,b){return a*this.b+b*this.d+this.f},b.get=function(a){return+this[r.fromCharCode(97+a)].toFixed(4)},b.toString=function(){return a.svg?\"matrix(\"+[this.get(0),this.get(1),this.get(2),this.get(3),this.get(4),this.get(5)].join()+\")\":[this.get(0),this.get(2),this.get(1),this.get(3),0,0].join()},b.toFilter=function(){return\"progid:DXImageTransform.Microsoft.Matrix(M11=\"+this.get(0)+\", M12=\"+this.get(2)+\", M21=\"+this.get(1)+\", M22=\"+this.get(3)+\", Dx=\"+this.get(4)+\", Dy=\"+this.get(5)+\", sizingmethod='auto expand')\"},b.offset=function(){return[this.e.toFixed(4),this.f.toFixed(4)]},b.split=function(){var b={};b.dx=this.e,b.dy=this.f;var e=[[this.a,this.c],[this.b,this.d]];b.scalex=w.sqrt(c(e[0])),d(e[0]),b.shear=e[0][0]*e[1][0]+e[0][1]*e[1][1],e[1]=[e[1][0]-e[0][0]*b.shear,e[1][1]-e[0][1]*b.shear],b.scaley=w.sqrt(c(e[1])),d(e[1]),b.shear/=b.scaley;var f=-e[0][1],g=e[1][1];g<0?(b.rotate=a.deg(w.acos(g)),f<0&&(b.rotate=360-b.rotate)):b.rotate=a.deg(w.asin(f)),b.isSimple=!+b.shear.toFixed(9)&&(b.scalex.toFixed(9)==b.scaley.toFixed(9)||!b.rotate),b.isSuperSimple=!+b.shear.toFixed(9)&&b.scalex.toFixed(9)==b.scaley.toFixed(9)&&!b.rotate,b.noRotation=!+b.shear.toFixed(9)&&!b.rotate;return b},b.toTransformString=function(a){var b=a||this[s]();if(b.isSimple){b.scalex=+b.scalex.toFixed(4),b.scaley=+b.scaley.toFixed(4),b.rotate=+b.rotate.toFixed(4);return(b.dx||b.dy?\"t\"+[b.dx,b.dy]:p)+(b.scalex!=1||b.scaley!=1?\"s\"+[b.scalex,b.scaley,0,0]:p)+(b.rotate?\"r\"+[b.rotate,0,0]:p)}return\"m\"+[this.get(0),this.get(1),this.get(2),this.get(3),this.get(4),this.get(5)]}}(cb.prototype);var cc=navigator.userAgent.match(/Version\\/(.*?)\\s/)||navigator.userAgent.match(/Chrome\\/(\\d+)/);navigator.vendor==\"Apple Computer, Inc.\"&&(cc&&cc[1]<4||navigator.platform.slice(0,2)==\"iP\")||navigator.vendor==\"Google Inc.\"&&cc&&cc[1]<8?k.safari=function(){var a=this.rect(-99,-99,this.width+99,this.height+99).attr({stroke:\"none\"});setTimeout(function(){a.remove()})}:k.safari=be;var cd=function(){this.returnValue=!1},ce=function(){return this.originalEvent.preventDefault()},cf=function(){this.cancelBubble=!0},cg=function(){return this.originalEvent.stopPropagation()},ch=function(){if(h.doc.addEventListener)return function(a,b,c,d){var e=o&&u[b]?u[b]:b,f=function(e){var f=h.doc.documentElement.scrollTop||h.doc.body.scrollTop,i=h.doc.documentElement.scrollLeft||h.doc.body.scrollLeft,j=e.clientX+i,k=e.clientY+f;if(o&&u[g](b))for(var l=0,m=e.targetTouches&&e.targetTouches.length;l<m;l++)if(e.targetTouches[l].target==a){var n=e;e=e.targetTouches[l],e.originalEvent=n,e.preventDefault=ce,e.stopPropagation=cg;break}return c.call(d,e,j,k)};a.addEventListener(e,f,!1);return function(){a.removeEventListener(e,f,!1);return!0}};if(h.doc.attachEvent)return function(a,b,c,d){var e=function(a){a=a||h.win.event;var b=h.doc.documentElement.scrollTop||h.doc.body.scrollTop,e=h.doc.documentElement.scrollLeft||h.doc.body.scrollLeft,f=a.clientX+e,g=a.clientY+b;a.preventDefault=a.preventDefault||cd,a.stopPropagation=a.stopPropagation||cf;return c.call(d,a,f,g)};a.attachEvent(\"on\"+b,e);var f=function(){a.detachEvent(\"on\"+b,e);return!0};return f}}(),ci=[],cj=function(a){var b=a.clientX,c=a.clientY,d=h.doc.documentElement.scrollTop||h.doc.body.scrollTop,e=h.doc.documentElement.scrollLeft||h.doc.body.scrollLeft,f,g=ci.length;while(g--){f=ci[g];if(o){var i=a.touches.length,j;while(i--){j=a.touches[i];if(j.identifier==f.el._drag.id){b=j.clientX,c=j.clientY,(a.originalEvent?a.originalEvent:a).preventDefault();break}}}else a.preventDefault();var k=f.el.node,l,m=k.nextSibling,n=k.parentNode,p=k.style.display;h.win.opera&&n.removeChild(k),k.style.display=\"none\",l=f.el.paper.getElementByPoint(b,c),k.style.display=p,h.win.opera&&(m?n.insertBefore(k,m):n.appendChild(k)),l&&eve(\"raphael.drag.over.\"+f.el.id,f.el,l),b+=e,c+=d,eve(\"raphael.drag.move.\"+f.el.id,f.move_scope||f.el,b-f.el._drag.x,c-f.el._drag.y,b,c,a)}},ck=function(b){a.unmousemove(cj).unmouseup(ck);var c=ci.length,d;while(c--)d=ci[c],d.el._drag={},eve(\"raphael.drag.end.\"+d.el.id,d.end_scope||d.start_scope||d.move_scope||d.el,b);ci=[]},cl=a.el={};for(var cm=t.length;cm--;)(function(b){a[b]=cl[b]=function(c,d){a.is(c,\"function\")&&(this.events=this.events||[],this.events.push({name:b,f:c,unbind:ch(this.shape||this.node||h.doc,b,c,d||this)}));return this},a[\"un\"+b]=cl[\"un\"+b]=function(a){var c=this.events||[],d=c.length;while(d--)if(c[d].name==b&&c[d].f==a){c[d].unbind(),c.splice(d,1),!c.length&&delete this.events;return this}return this}})(t[cm]);cl.data=function(b,c){var d=bb[this.id]=bb[this.id]||{};if(arguments.length==1){if(a.is(b,\"object\")){for(var e in b)b[g](e)&&this.data(e,b[e]);return this}eve(\"raphael.data.get.\"+this.id,this,d[b],b);return d[b]}d[b]=c,eve(\"raphael.data.set.\"+this.id,this,c,b);return this},cl.removeData=function(a){a==null?bb[this.id]={}:bb[this.id]&&delete bb[this.id][a];return this},cl.hover=function(a,b,c,d){return this.mouseover(a,c).mouseout(b,d||c)},cl.unhover=function(a,b){return this.unmouseover(a).unmouseout(b)};var cn=[];cl.drag=function(b,c,d,e,f,g){function i(i){(i.originalEvent||i).preventDefault();var j=h.doc.documentElement.scrollTop||h.doc.body.scrollTop,k=h.doc.documentElement.scrollLeft||h.doc.body.scrollLeft;this._drag.x=i.clientX+k,this._drag.y=i.clientY+j,this._drag.id=i.identifier,!ci.length&&a.mousemove(cj).mouseup(ck),ci.push({el:this,move_scope:e,start_scope:f,end_scope:g}),c&&eve.on(\"raphael.drag.start.\"+this.id,c),b&&eve.on(\"raphael.drag.move.\"+this.id,b),d&&eve.on(\"raphael.drag.end.\"+this.id,d),eve(\"raphael.drag.start.\"+this.id,f||e||this,i.clientX+k,i.clientY+j,i)}this._drag={},cn.push({el:this,start:i}),this.mousedown(i);return this},cl.onDragOver=function(a){a?eve.on(\"raphael.drag.over.\"+this.id,a):eve.unbind(\"raphael.drag.over.\"+this.id)},cl.undrag=function(){var b=cn.length;while(b--)cn[b].el==this&&(this.unmousedown(cn[b].start),cn.splice(b,1),eve.unbind(\"raphael.drag.*.\"+this.id));!cn.length&&a.unmousemove(cj).unmouseup(ck)},k.circle=function(b,c,d){var e=a._engine.circle(this,b||0,c||0,d||0);this.__set__&&this.__set__.push(e);return e},k.rect=function(b,c,d,e,f){var g=a._engine.rect(this,b||0,c||0,d||0,e||0,f||0);this.__set__&&this.__set__.push(g);return g},k.ellipse=function(b,c,d,e){var f=a._engine.ellipse(this,b||0,c||0,d||0,e||0);this.__set__&&this.__set__.push(f);return f},k.path=function(b){b&&!a.is(b,D)&&!a.is(b[0],E)&&(b+=p);var c=a._engine.path(a.format[m](a,arguments),this);this.__set__&&this.__set__.push(c);return c},k.image=function(b,c,d,e,f){var g=a._engine.image(this,b||\"about:blank\",c||0,d||0,e||0,f||0);this.__set__&&this.__set__.push(g);return g},k.text=function(b,c,d){var e=a._engine.text(this,b||0,c||0,r(d));this.__set__&&this.__set__.push(e);return e},k.set=function(b){!a.is(b,\"array\")&&(b=Array.prototype.splice.call(arguments,0,arguments.length));var c=new cG(b);this.__set__&&this.__set__.push(c);return c},k.setStart=function(a){this.__set__=a||this.set()},k.setFinish=function(a){var b=this.__set__;delete this.__set__;return b},k.setSize=function(b,c){return a._engine.setSize.call(this,b,c)},k.setViewBox=function(b,c,d,e,f){return a._engine.setViewBox.call(this,b,c,d,e,f)},k.top=k.bottom=null,k.raphael=a;var co=function(a){var b=a.getBoundingClientRect(),c=a.ownerDocument,d=c.body,e=c.documentElement,f=e.clientTop||d.clientTop||0,g=e.clientLeft||d.clientLeft||0,i=b.top+(h.win.pageYOffset||e.scrollTop||d.scrollTop)-f,j=b.left+(h.win.pageXOffset||e.scrollLeft||d.scrollLeft)-g;return{y:i,x:j}};k.getElementByPoint=function(a,b){var c=this,d=c.canvas,e=h.doc.elementFromPoint(a,b);if(h.win.opera&&e.tagName==\"svg\"){var f=co(d),g=d.createSVGRect();g.x=a-f.x,g.y=b-f.y,g.width=g.height=1;var i=d.getIntersectionList(g,null);i.length&&(e=i[i.length-1])}if(!e)return null;while(e.parentNode&&e!=d.parentNode&&!e.raphael)e=e.parentNode;e==c.canvas.parentNode&&(e=d),e=e&&e.raphael?c.getById(e.raphaelid):null;return e},k.getById=function(a){var b=this.bottom;while(b){if(b.id==a)return b;b=b.next}return null},k.forEach=function(a,b){var c=this.bottom;while(c){if(a.call(b,c)===!1)return this;c=c.next}return this},k.getElementsByPoint=function(a,b){var c=this.set();this.forEach(function(d){d.isPointInside(a,b)&&c.push(d)});return c},cl.isPointInside=function(b,c){var d=this.realPath=this.realPath||bi[this.type](this);return a.isPointInsidePath(d,b,c)},cl.getBBox=function(a){if(this.removed)return{};var b=this._;if(a){if(b.dirty||!b.bboxwt)this.realPath=bi[this.type](this),b.bboxwt=bI(this.realPath),b.bboxwt.toString=cq,b.dirty=0;return bm(b.bboxwt)}if(b.dirty||b.dirtyT||!b.bbox){if(b.dirty||!this.realPath)b.bboxwt=0,this.realPath=bi[this.type](this);b.bbox=bI(bj(this.realPath,this.matrix)),b.bbox.toString=cq,b.dirty=b.dirtyT=0}return bm(b.bbox)},cl.getBBoxWOTransform=function(){return this.getBBox(1)},cl.clone=function(){if(this.removed)return null;var a=this.paper[this.type]().attr(this.attr());this.__set__&&this.__set__.push(a);return a},cl.glow=function(a){if(this.type==\"text\")return null;a=a||{};var b={width:(a.width||10)+(+this.attr(\"stroke-width\")||1),fill:a.fill||!1,opacity:a.opacity||.5,offsetx:a.offsetx||0,offsety:a.offsety||0,color:a.color||\"#000\"},c=b.width/2,d=this.paper,e=d.set(),f=this.realPath||bi[this.type](this);f=this.matrix?bj(f,this.matrix):f;for(var g=1;g<c+1;g++)e.push(d.path(f).attr({stroke:b.color,fill:b.fill?b.color:\"none\",\"stroke-linejoin\":\"round\",\"stroke-linecap\":\"round\",\"stroke-width\":+(b.width/c*g).toFixed(3),opacity:+(b.opacity/c).toFixed(3)}));return e.insertBefore(this).translate(b.offsetx,b.offsety)};var cr={},cs=function(b,c,d,e,f,g,h,i,j){return j==null?bB(b,c,d,e,f,g,h,i):a.findDotsAtSegment(b,c,d,e,f,g,h,i,bC(b,c,d,e,f,g,h,i,j))},ct=function(b,c){return function(d,e,f){d=bR(d);var g,h,i,j,k=\"\",l={},m,n=0;for(var o=0,p=d.length;o<p;o++){i=d[o];if(i[0]==\"M\")g=+i[1],h=+i[2];else{j=cs(g,h,i[1],i[2],i[3],i[4],i[5],i[6]);if(n+j>e){if(c&&!l.start){m=cs(g,h,i[1],i[2],i[3],i[4],i[5],i[6],e-n),k+=[\"C\"+m.start.x,m.start.y,m.m.x,m.m.y,m.x,m.y];if(f)return k;l.start=k,k=[\"M\"+m.x,m.y+\"C\"+m.n.x,m.n.y,m.end.x,m.end.y,i[5],i[6]].join(),n+=j,g=+i[5],h=+i[6];continue}if(!b&&!c){m=cs(g,h,i[1],i[2],i[3],i[4],i[5],i[6],e-n);return{x:m.x,y:m.y,alpha:m.alpha}}}n+=j,g=+i[5],h=+i[6]}k+=i.shift()+i}l.end=k,m=b?n:c?l:a.findDotsAtSegment(g,h,i[0],i[1],i[2],i[3],i[4],i[5],1),m.alpha&&(m={x:m.x,y:m.y,alpha:m.alpha});return m}},cu=ct(1),cv=ct(),cw=ct(0,1);a.getTotalLength=cu,a.getPointAtLength=cv,a.getSubpath=function(a,b,c){if(this.getTotalLength(a)-c<1e-6)return cw(a,b).end;var d=cw(a,c,1);return b?cw(d,b).end:d},cl.getTotalLength=function(){if(this.type==\"path\"){if(this.node.getTotalLength)return this.node.getTotalLength();return cu(this.attrs.path)}},cl.getPointAtLength=function(a){if(this.type==\"path\")return cv(this.attrs.path,a)},cl.getSubpath=function(b,c){if(this.type==\"path\")return a.getSubpath(this.attrs.path,b,c)};var cx=a.easing_formulas={linear:function(a){return a},\"<\":function(a){return A(a,1.7)},\">\":function(a){return A(a,.48)},\"<>\":function(a){var b=.48-a/1.04,c=w.sqrt(.1734+b*b),d=c-b,e=A(z(d),1/3)*(d<0?-1:1),f=-c-b,g=A(z(f),1/3)*(f<0?-1:1),h=e+g+.5;return(1-h)*3*h*h+h*h*h},backIn:function(a){var b=1.70158;return a*a*((b+1)*a-b)},backOut:function(a){a=a-1;var b=1.70158;return a*a*((b+1)*a+b)+1},elastic:function(a){if(a==!!a)return a;return A(2,-10*a)*w.sin((a-.075)*2*B/.3)+1},bounce:function(a){var b=7.5625,c=2.75,d;a<1/c?d=b*a*a:a<2/c?(a-=1.5/c,d=b*a*a+.75):a<2.5/c?(a-=2.25/c,d=b*a*a+.9375):(a-=2.625/c,d=b*a*a+.984375);return d}};cx.easeIn=cx[\"ease-in\"]=cx[\"<\"],cx.easeOut=cx[\"ease-out\"]=cx[\">\"],cx.easeInOut=cx[\"ease-in-out\"]=cx[\"<>\"],cx[\"back-in\"]=cx.backIn,cx[\"back-out\"]=cx.backOut;var cy=[],cz=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(a){setTimeout(a,16)},cA=function(){var b=+(new Date),c=0;for(;c<cy.length;c++){var d=cy[c];if(d.el.removed||d.paused)continue;var e=b-d.start,f=d.ms,h=d.easing,i=d.from,j=d.diff,k=d.to,l=d.t,m=d.el,o={},p,r={},s;d.initstatus?(e=(d.initstatus*d.anim.top-d.prev)/(d.percent-d.prev)*f,d.status=d.initstatus,delete d.initstatus,d.stop&&cy.splice(c--,1)):d.status=(d.prev+(d.percent-d.prev)*(e/f))/d.anim.top;if(e<0)continue;if(e<f){var t=h(e/f);for(var u in i)if(i[g](u)){switch(U[u]){case C:p=+i[u]+t*f*j[u];break;case\"colour\":p=\"rgb(\"+[cB(O(i[u].r+t*f*j[u].r)),cB(O(i[u].g+t*f*j[u].g)),cB(O(i[u].b+t*f*j[u].b))].join(\",\")+\")\";break;case\"path\":p=[];for(var v=0,w=i[u].length;v<w;v++){p[v]=[i[u][v][0]];for(var x=1,y=i[u][v].length;x<y;x++)p[v][x]=+i[u][v][x]+t*f*j[u][v][x];p[v]=p[v].join(q)}p=p.join(q);break;case\"transform\":if(j[u].real){p=[];for(v=0,w=i[u].length;v<w;v++){p[v]=[i[u][v][0]];for(x=1,y=i[u][v].length;x<y;x++)p[v][x]=i[u][v][x]+t*f*j[u][v][x]}}else{var z=function(a){return+i[u][a]+t*f*j[u][a]};p=[[\"m\",z(0),z(1),z(2),z(3),z(4),z(5)]]}break;case\"csv\":if(u==\"clip-rect\"){p=[],v=4;while(v--)p[v]=+i[u][v]+t*f*j[u][v]}break;default:var A=[][n](i[u]);p=[],v=m.paper.customAttributes[u].length;while(v--)p[v]=+A[v]+t*f*j[u][v]}o[u]=p}m.attr(o),function(a,b,c){setTimeout(function(){eve(\"raphael.anim.frame.\"+a,b,c)})}(m.id,m,d.anim)}else{(function(b,c,d){setTimeout(function(){eve(\"raphael.anim.frame.\"+c.id,c,d),eve(\"raphael.anim.finish.\"+c.id,c,d),a.is(b,\"function\")&&b.call(c)})})(d.callback,m,d.anim),m.attr(k),cy.splice(c--,1);if(d.repeat>1&&!d.next){for(s in k)k[g](s)&&(r[s]=d.totalOrigin[s]);d.el.attr(r),cE(d.anim,d.el,d.anim.percents[0],null,d.totalOrigin,d.repeat-1)}d.next&&!d.stop&&cE(d.anim,d.el,d.next,null,d.totalOrigin,d.repeat)}}a.svg&&m&&m.paper&&m.paper.safari(),cy.length&&cz(cA)},cB=function(a){return a>255?255:a<0?0:a};cl.animateWith=function(b,c,d,e,f,g){var h=this;if(h.removed){g&&g.call(h);return h}var i=d instanceof cD?d:a.animation(d,e,f,g),j,k;cE(i,h,i.percents[0],null,h.attr());for(var l=0,m=cy.length;l<m;l++)if(cy[l].anim==c&&cy[l].el==b){cy[m-1].start=cy[l].start;break}return h},cl.onAnimation=function(a){a?eve.on(\"raphael.anim.frame.\"+this.id,a):eve.unbind(\"raphael.anim.frame.\"+this.id);return this},cD.prototype.delay=function(a){var b=new cD(this.anim,this.ms);b.times=this.times,b.del=+a||0;return b},cD.prototype.repeat=function(a){var b=new cD(this.anim,this.ms);b.del=this.del,b.times=w.floor(x(a,0))||1;return b},a.animation=function(b,c,d,e){if(b instanceof cD)return b;if(a.is(d,\"function\")||!d)e=e||d||null,d=null;b=Object(b),c=+c||0;var f={},h,i;for(i in b)b[g](i)&&Q(i)!=i&&Q(i)+\"%\"!=i&&(h=!0,f[i]=b[i]);if(!h)return new cD(b,c);d&&(f.easing=d),e&&(f.callback=e);return new cD({100:f},c)},cl.animate=function(b,c,d,e){var f=this;if(f.removed){e&&e.call(f);return f}var g=b instanceof cD?b:a.animation(b,c,d,e);cE(g,f,g.percents[0],null,f.attr());return f},cl.setTime=function(a,b){a&&b!=null&&this.status(a,y(b,a.ms)/a.ms);return this},cl.status=function(a,b){var c=[],d=0,e,f;if(b!=null){cE(a,this,-1,y(b,1));return this}e=cy.length;for(;d<e;d++){f=cy[d];if(f.el.id==this.id&&(!a||f.anim==a)){if(a)return f.status;c.push({anim:f.anim,status:f.status})}}if(a)return 0;return c},cl.pause=function(a){for(var b=0;b<cy.length;b++)cy[b].el.id==this.id&&(!a||cy[b].anim==a)&&eve(\"raphael.anim.pause.\"+this.id,this,cy[b].anim)!==!1&&(cy[b].paused=!0);return this},cl.resume=function(a){for(var b=0;b<cy.length;b++)if(cy[b].el.id==this.id&&(!a||cy[b].anim==a)){var c=cy[b];eve(\"raphael.anim.resume.\"+this.id,this,c.anim)!==!1&&(delete c.paused,this.status(c.anim,c.status))}return this},cl.stop=function(a){for(var b=0;b<cy.length;b++)cy[b].el.id==this.id&&(!a||cy[b].anim==a)&&eve(\"raphael.anim.stop.\"+this.id,this,cy[b].anim)!==!1&&cy.splice(b--,1);return this},eve.on(\"raphael.remove\",cF),eve.on(\"raphael.clear\",cF),cl.toString=function(){return\"Raphaël’s object\"};var cG=function(a){this.items=[],this.length=0,this.type=\"set\";if(a)for(var b=0,c=a.length;b<c;b++)a[b]&&(a[b].constructor==cl.constructor||a[b].constructor==cG)&&(this[this.items.length]=this.items[this.items.length]=a[b],this.length++)},cH=cG.prototype;cH.push=function(){var a,b;for(var c=0,d=arguments.length;c<d;c++)a=arguments[c],a&&(a.constructor==cl.constructor||a.constructor==cG)&&(b=this.items.length,this[b]=this.items[b]=a,this.length++);return this},cH.pop=function(){this.length&&delete this[this.length--];return this.items.pop()},cH.forEach=function(a,b){for(var c=0,d=this.items.length;c<d;c++)if(a.call(b,this.items[c],c)===!1)return this;return this};for(var cI in cl)cl[g](cI)&&(cH[cI]=function(a){return function(){var b=arguments;return this.forEach(function(c){c[a][m](c,b)})}}(cI));cH.attr=function(b,c){if(b&&a.is(b,E)&&a.is(b[0],\"object\"))for(var d=0,e=b.length;d<e;d++)this.items[d].attr(b[d]);else for(var f=0,g=this.items.length;f<g;f++)this.items[f].attr(b,c);return this},cH.clear=function(){while(this.length)this.pop()},cH.splice=function(a,b,c){a=a<0?x(this.length+a,0):a,b=x(0,y(this.length-a,b));var d=[],e=[],f=[],g;for(g=2;g<arguments.length;g++)f.push(arguments[g]);for(g=0;g<b;g++)e.push(this[a+g]);for(;g<this.length-a;g++)d.push(this[a+g]);var h=f.length;for(g=0;g<h+d.length;g++)this.items[a+g]=this[a+g]=g<h?f[g]:d[g-h];g=this.items.length=this.length-=b-h;while(this[g])delete this[g++];return new cG(e)},cH.exclude=function(a){for(var b=0,c=this.length;b<c;b++)if(this[b]==a){this.splice(b,1);return!0}},cH.animate=function(b,c,d,e){(a.is(d,\"function\")||!d)&&(e=d||null);var f=this.items.length,g=f,h,i=this,j;if(!f)return this;e&&(j=function(){!--f&&e.call(i)}),d=a.is(d,D)?d:j;var k=a.animation(b,c,d,j);h=this.items[--g].animate(k);while(g--)this.items[g]&&!this.items[g].removed&&this.items[g].animateWith(h,k,k);return this},cH.insertAfter=function(a){var b=this.items.length;while(b--)this.items[b].insertAfter(a);return this},cH.getBBox=function(){var a=[],b=[],c=[],d=[];for(var e=this.items.length;e--;)if(!this.items[e].removed){var f=this.items[e].getBBox();a.push(f.x),b.push(f.y),c.push(f.x+f.width),d.push(f.y+f.height)}a=y[m](0,a),b=y[m](0,b),c=x[m](0,c),d=x[m](0,d);return{x:a,y:b,x2:c,y2:d,width:c-a,height:d-b}},cH.clone=function(a){a=new cG;for(var b=0,c=this.items.length;b<c;b++)a.push(this.items[b].clone());return a},cH.toString=function(){return\"Raphaël‘s set\"},a.registerFont=function(a){if(!a.face)return a;this.fonts=this.fonts||{};var b={w:a.w,face:{},glyphs:{}},c=a.face[\"font-family\"];for(var d in a.face)a.face[g](d)&&(b.face[d]=a.face[d]);this.fonts[c]?this.fonts[c].push(b):this.fonts[c]=[b];if(!a.svg){b.face[\"units-per-em\"]=R(a.face[\"units-per-em\"],10);for(var e in a.glyphs)if(a.glyphs[g](e)){var f=a.glyphs[e];b.glyphs[e]={w:f.w,k:{},d:f.d&&\"M\"+f.d.replace(/[mlcxtrv]/g,function(a){return{l:\"L\",c:\"C\",x:\"z\",t:\"m\",r:\"l\",v:\"c\"}[a]||\"M\"})+\"z\"};if(f.k)for(var h in f.k)f[g](h)&&(b.glyphs[e].k[h]=f.k[h])}}return a},k.getFont=function(b,c,d,e){e=e||\"normal\",d=d||\"normal\",c=+c||{normal:400,bold:700,lighter:300,bolder:800}[c]||400;if(!!a.fonts){var f=a.fonts[b];if(!f){var h=new RegExp(\"(^|\\\\s)\"+b.replace(/[^\\w\\d\\s+!~.:_-]/g,p)+\"(\\\\s|$)\",\"i\");for(var i in a.fonts)if(a.fonts[g](i)&&h.test(i)){f=a.fonts[i];break}}var j;if(f)for(var k=0,l=f.length;k<l;k++){j=f[k];if(j.face[\"font-weight\"]==c&&(j.face[\"font-style\"]==d||!j.face[\"font-style\"])&&j.face[\"font-stretch\"]==e)break}return j}},k.print=function(b,d,e,f,g,h,i){h=h||\"middle\",i=x(y(i||0,1),-1);var j=r(e)[s](p),k=0,l=0,m=p,n;a.is(f,e)&&(f=this.getFont(f));if(f){n=(g||16)/f.face[\"units-per-em\"];var o=f.face.bbox[s](c),q=+o[0],t=o[3]-o[1],u=0,v=+o[1]+(h==\"baseline\"?t+ +f.face.descent:t/2);for(var w=0,z=j.length;w<z;w++){if(j[w]==\"\\n\")k=0,B=0,l=0,u+=t;else{var A=l&&f.glyphs[j[w-1]]||{},B=f.glyphs[j[w]];k+=l?(A.w||f.w)+(A.k&&A.k[j[w]]||0)+f.w*i:0,l=1}B&&B.d&&(m+=a.transformPath(B.d,[\"t\",k*n,u*n,\"s\",n,n,q,v,\"t\",(b-q)/n,(d-v)/n]))}}return this.path(m).attr({fill:\"#000\",stroke:\"none\"})},k.add=function(b){if(a.is(b,\"array\")){var c=this.set(),e=0,f=b.length,h;for(;e<f;e++)h=b[e]||{},d[g](h.type)&&c.push(this[h.type]().attr(h))}return c},a.format=function(b,c){var d=a.is(c,E)?[0][n](c):arguments;b&&a.is(b,D)&&d.length-1&&(b=b.replace(e,function(a,b){return d[++b]==null?p:d[b]}));return b||p},a.fullfill=function(){var a=/\\{([^\\}]+)\\}/g,b=/(?:(?:^|\\.)(.+?)(?=\\[|\\.|$|\\()|\\[('|\")(.+?)\\2\\])(\\(\\))?/g,c=function(a,c,d){var e=d;c.replace(b,function(a,b,c,d,f){b=b||d,e&&(b in e&&(e=e[b]),typeof e==\"function\"&&f&&(e=e()))}),e=(e==null||e==d?a:e)+\"\";return e};return function(b,d){return String(b).replace(a,function(a,b){return c(a,b,d)})}}(),a.ninja=function(){i.was?h.win.Raphael=i.is:delete Raphael;return a},a.st=cH,function(b,c,d){function e(){/in/.test(b.readyState)?setTimeout(e,9):a.eve(\"raphael.DOMload\")}b.readyState==null&&b.addEventListener&&(b.addEventListener(c,d=function(){b.removeEventListener(c,d,!1),b.readyState=\"complete\"},!1),b.readyState=\"loading\"),e()}(document,\"DOMContentLoaded\"),i.was?h.win.Raphael=a:Raphael=a,eve.on(\"raphael.DOMload\",function(){b=!0})}(),window.Raphael.svg&&function(a){var b=\"hasOwnProperty\",c=String,d=parseFloat,e=parseInt,f=Math,g=f.max,h=f.abs,i=f.pow,j=/[, ]+/,k=a.eve,l=\"\",m=\" \",n=\"http://www.w3.org/1999/xlink\",o={block:\"M5,0 0,2.5 5,5z\",classic:\"M5,0 0,2.5 5,5 3.5,3 3.5,2z\",diamond:\"M2.5,0 5,2.5 2.5,5 0,2.5z\",open:\"M6,1 1,3.5 6,6\",oval:\"M2.5,0A2.5,2.5,0,0,1,2.5,5 2.5,2.5,0,0,1,2.5,0z\"},p={};a.toString=function(){return\"Your browser supports SVG.\\nYou are running Raphaël \"+this.version};var q=function(d,e){if(e){typeof d==\"string\"&&(d=q(d));for(var f in e)e[b](f)&&(f.substring(0,6)==\"xlink:\"?d.setAttributeNS(n,f.substring(6),c(e[f])):d.setAttribute(f,c(e[f])))}else d=a._g.doc.createElementNS(\"http://www.w3.org/2000/svg\",d),d.style&&(d.style.webkitTapHighlightColor=\"rgba(0,0,0,0)\");return d},r=function(b,e){var j=\"linear\",k=b.id+e,m=.5,n=.5,o=b.node,p=b.paper,r=o.style,s=a._g.doc.getElementById(k);if(!s){e=c(e).replace(a._radial_gradient,function(a,b,c){j=\"radial\";if(b&&c){m=d(b),n=d(c);var e=(n>.5)*2-1;i(m-.5,2)+i(n-.5,2)>.25&&(n=f.sqrt(.25-i(m-.5,2))*e+.5)&&n!=.5&&(n=n.toFixed(5)-1e-5*e)}return l}),e=e.split(/\\s*\\-\\s*/);if(j==\"linear\"){var t=e.shift();t=-d(t);if(isNaN(t))return null;var u=[0,0,f.cos(a.rad(t)),f.sin(a.rad(t))],v=1/(g(h(u[2]),h(u[3]))||1);u[2]*=v,u[3]*=v,u[2]<0&&(u[0]=-u[2],u[2]=0),u[3]<0&&(u[1]=-u[3],u[3]=0)}var w=a._parseDots(e);if(!w)return null;k=k.replace(/[\\(\\)\\s,\\xb0#]/g,\"_\"),b.gradient&&k!=b.gradient.id&&(p.defs.removeChild(b.gradient),delete b.gradient);if(!b.gradient){s=q(j+\"Gradient\",{id:k}),b.gradient=s,q(s,j==\"radial\"?{fx:m,fy:n}:{x1:u[0],y1:u[1],x2:u[2],y2:u[3],gradientTransform:b.matrix.invert()}),p.defs.appendChild(s);for(var x=0,y=w.length;x<y;x++)s.appendChild(q(\"stop\",{offset:w[x].offset?w[x].offset:x?\"100%\":\"0%\",\"stop-color\":w[x].color||\"#fff\"}))}}q(o,{fill:\"url(#\"+k+\")\",opacity:1,\"fill-opacity\":1}),r.fill=l,r.opacity=1,r.fillOpacity=1;return 1},s=function(a){var b=a.getBBox(1);q(a.pattern,{patternTransform:a.matrix.invert()+\" translate(\"+b.x+\",\"+b.y+\")\"})},t=function(d,e,f){if(d.type==\"path\"){var g=c(e).toLowerCase().split(\"-\"),h=d.paper,i=f?\"end\":\"start\",j=d.node,k=d.attrs,m=k[\"stroke-width\"],n=g.length,r=\"classic\",s,t,u,v,w,x=3,y=3,z=5;while(n--)switch(g[n]){case\"block\":case\"classic\":case\"oval\":case\"diamond\":case\"open\":case\"none\":r=g[n];break;case\"wide\":y=5;break;case\"narrow\":y=2;break;case\"long\":x=5;break;case\"short\":x=2}r==\"open\"?(x+=2,y+=2,z+=2,u=1,v=f?4:1,w={fill:\"none\",stroke:k.stroke}):(v=u=x/2,w={fill:k.stroke,stroke:\"none\"}),d._.arrows?f?(d._.arrows.endPath&&p[d._.arrows.endPath]--,d._.arrows.endMarker&&p[d._.arrows.endMarker]--):(d._.arrows.startPath&&p[d._.arrows.startPath]--,d._.arrows.startMarker&&p[d._.arrows.startMarker]--):d._.arrows={};if(r!=\"none\"){var A=\"raphael-marker-\"+r,B=\"raphael-marker-\"+i+r+x+y;a._g.doc.getElementById(A)?p[A]++:(h.defs.appendChild(q(q(\"path\"),{\"stroke-linecap\":\"round\",d:o[r],id:A})),p[A]=1);var C=a._g.doc.getElementById(B),D;C?(p[B]++,D=C.getElementsByTagName(\"use\")[0]):(C=q(q(\"marker\"),{id:B,markerHeight:y,markerWidth:x,orient:\"auto\",refX:v,refY:y/2}),D=q(q(\"use\"),{\"xlink:href\":\"#\"+A,transform:(f?\"rotate(180 \"+x/2+\" \"+y/2+\") \":l)+\"scale(\"+x/z+\",\"+y/z+\")\",\"stroke-width\":(1/((x/z+y/z)/2)).toFixed(4)}),C.appendChild(D),h.defs.appendChild(C),p[B]=1),q(D,w);var F=u*(r!=\"diamond\"&&r!=\"oval\");f?(s=d._.arrows.startdx*m||0,t=a.getTotalLength(k.path)-F*m):(s=F*m,t=a.getTotalLength(k.path)-(d._.arrows.enddx*m||0)),w={},w[\"marker-\"+i]=\"url(#\"+B+\")\";if(t||s)w.d=Raphael.getSubpath(k.path,s,t);q(j,w),d._.arrows[i+\"Path\"]=A,d._.arrows[i+\"Marker\"]=B,d._.arrows[i+\"dx\"]=F,d._.arrows[i+\"Type\"]=r,d._.arrows[i+\"String\"]=e}else f?(s=d._.arrows.startdx*m||0,t=a.getTotalLength(k.path)-s):(s=0,t=a.getTotalLength(k.path)-(d._.arrows.enddx*m||0)),d._.arrows[i+\"Path\"]&&q(j,{d:Raphael.getSubpath(k.path,s,t)}),delete d._.arrows[i+\"Path\"],delete d._.arrows[i+\"Marker\"],delete d._.arrows[i+\"dx\"],delete d._.arrows[i+\"Type\"],delete d._.arrows[i+\"String\"];for(w in p)if(p[b](w)&&!p[w]){var G=a._g.doc.getElementById(w);G&&G.parentNode.removeChild(G)}}},u={\"\":[0],none:[0],\"-\":[3,1],\".\":[1,1],\"-.\":[3,1,1,1],\"-..\":[3,1,1,1,1,1],\". \":[1,3],\"- \":[4,3],\"--\":[8,3],\"- .\":[4,3,1,3],\"--.\":[8,3,1,3],\"--..\":[8,3,1,3,1,3]},v=function(a,b,d){b=u[c(b).toLowerCase()];if(b){var e=a.attrs[\"stroke-width\"]||\"1\",f={round:e,square:e,butt:0}[a.attrs[\"stroke-linecap\"]||d[\"stroke-linecap\"]]||0,g=[],h=b.length;while(h--)g[h]=b[h]*e+(h%2?1:-1)*f;q(a.node,{\"stroke-dasharray\":g.join(\",\")})}};k.on(\"raphael.util.attr.blur\",function(a){this.blur(a)}),k.on(\"raphael.util.attr.cursor\",function(a){this.node.style.cursor=a});var w=function(d,f){var i=d.node,m=d.attrs,o=i.style.visibility;i.style.visibility=\"hidden\";for(var p in f){k(\"raphael.util.attr.\"+p,d,f[p]);if(f[b](p)){if(!a._availableAttrs[b](p))continue;var u=f[p];m[p]=u;switch(p){case\"blur\":d.blur(u);break;case\"href\":case\"title\":case\"target\":var w=i.parentNode;if(w.tagName.toLowerCase()!=\"a\"){var x=q(\"a\");w.insertBefore(x,i),x.appendChild(i),w=x}p==\"target\"?w.setAttributeNS(n,\"show\",u==\"blank\"?\"new\":u):w.setAttributeNS(n,p,u);break;case\"cursor\":break;case\"transform\":d.transform(u);break;case\"arrow-start\":t(d,u);break;case\"arrow-end\":t(d,u,1);break;case\"clip-rect\":var z=c(u).split(j);if(z.length==4){d.clip&&d.clip.parentNode.parentNode.removeChild(d.clip.parentNode);var A=q(\"clipPath\"),B=q(\"rect\");A.id=a.createUUID(),q(B,{x:z[0],y:z[1],width:z[2],height:z[3]}),A.appendChild(B),d.paper.defs.appendChild(A),q(i,{\"clip-path\":\"url(#\"+A.id+\")\"}),d.clip=B}if(!u){var C=i.getAttribute(\"clip-path\");if(C){var D=a._g.doc.getElementById(C.replace(/(^url\\(#|\\)$)/g,l));D&&D.parentNode.removeChild(D),q(i,{\"clip-path\":l}),delete d.clip}}break;case\"path\":d.type==\"path\"&&(q(i,{d:u?m.path=a._pathToAbsolute(u):\"M0,0\"}),d._.dirty=1,d._.arrows&&(\"startString\"in d._.arrows&&t(d,d._.arrows.startString),\"endString\"in d._.arrows&&t(d,d._.arrows.endString,1)));break;case\"width\":i.setAttribute(p,u),d._.dirty=1;if(m.fx)p=\"x\",u=m.x;else break;case\"x\":m.fx&&(u=-m.x-(m.width||0));case\"rx\":if(p==\"rx\"&&d.type==\"rect\")break;case\"cx\":i.setAttribute(p,u),d.pattern&&s(d),d._.dirty=1;break;case\"height\":i.setAttribute(p,u),d._.dirty=1;if(m.fy)p=\"y\",u=m.y;else break;case\"y\":m.fy&&(u=-m.y-(m.height||0));case\"ry\":if(p==\"ry\"&&d.type==\"rect\")break;case\"cy\":i.setAttribute(p,u),d.pattern&&s(d),d._.dirty=1;break;case\"r\":d.type==\"rect\"?q(i,{rx:u,ry:u}):i.setAttribute(p,u),d._.dirty=1;break;case\"src\":d.type==\"image\"&&i.setAttributeNS(n,\"href\",u);break;case\"stroke-width\":if(d._.sx!=1||d._.sy!=1)u/=g(h(d._.sx),h(d._.sy))||1;d.paper._vbSize&&(u*=d.paper._vbSize),i.setAttribute(p,u),m[\"stroke-dasharray\"]&&v(d,m[\"stroke-dasharray\"],f),d._.arrows&&(\"startString\"in d._.arrows&&t(d,d._.arrows.startString),\"endString\"in d._.arrows&&t(d,d._.arrows.endString,1));break;case\"stroke-dasharray\":v(d,u,f);break;case\"fill\":var F=c(u).match(a._ISURL);if(F){A=q(\"pattern\");var G=q(\"image\");A.id=a.createUUID(),q(A,{x:0,y:0,patternUnits:\"userSpaceOnUse\",height:1,width:1}),q(G,{x:0,y:0,\"xlink:href\":F[1]}),A.appendChild(G),function(b){a._preload(F[1],function(){var a=this.offsetWidth,c=this.offsetHeight;q(b,{width:a,height:c}),q(G,{width:a,height:c}),d.paper.safari()})}(A),d.paper.defs.appendChild(A),q(i,{fill:\"url(#\"+A.id+\")\"}),d.pattern=A,d.pattern&&s(d);break}var H=a.getRGB(u);if(!H.error)delete f.gradient,delete m.gradient,!a.is(m.opacity,\"undefined\")&&a.is(f.opacity,\"undefined\")&&q(i,{opacity:m.opacity}),!a.is(m[\"fill-opacity\"],\"undefined\")&&a.is(f[\"fill-opacity\"],\"undefined\")&&q(i,{\"fill-opacity\":m[\"fill-opacity\"]});else if((d.type==\"circle\"||d.type==\"ellipse\"||c(u).charAt()!=\"r\")&&r(d,u)){if(\"opacity\"in m||\"fill-opacity\"in m){var I=a._g.doc.getElementById(i.getAttribute(\"fill\").replace(/^url\\(#|\\)$/g,l));if(I){var J=I.getElementsByTagName(\"stop\");q(J[J.length-1],{\"stop-opacity\":(\"opacity\"in m?m.opacity:1)*(\"fill-opacity\"in m?m[\"fill-opacity\"]:1)})}}m.gradient=u,m.fill=\"none\";break}H[b](\"opacity\")&&q(i,{\"fill-opacity\":H.opacity>1?H.opacity/100:H.opacity});case\"stroke\":H=a.getRGB(u),i.setAttribute(p,H.hex),p==\"stroke\"&&H[b](\"opacity\")&&q(i,{\"stroke-opacity\":H.opacity>1?H.opacity/100:H.opacity}),p==\"stroke\"&&d._.arrows&&(\"startString\"in d._.arrows&&t(d,d._.arrows.startString),\"endString\"in d._.arrows&&t(d,d._.arrows.endString,1));break;case\"gradient\":(d.type==\"circle\"||d.type==\"ellipse\"||c(u).charAt()!=\"r\")&&r(d,u);break;case\"opacity\":m.gradient&&!m[b](\"stroke-opacity\")&&q(i,{\"stroke-opacity\":u>1?u/100:u});case\"fill-opacity\":if(m.gradient){I=a._g.doc.getElementById(i.getAttribute(\"fill\").replace(/^url\\(#|\\)$/g,l)),I&&(J=I.getElementsByTagName(\"stop\"),q(J[J.length-1],{\"stop-opacity\":u}));break};default:p==\"font-size\"&&(u=e(u,10)+\"px\");var K=p.replace(/(\\-.)/g,function(a){return a.substring(1).toUpperCase()});i.style[K]=u,d._.dirty=1,i.setAttribute(p,u)}}}y(d,f),i.style.visibility=o},x=1.2,y=function(d,f){if(d.type==\"text\"&&!!(f[b](\"text\")||f[b](\"font\")||f[b](\"font-size\")||f[b](\"x\")||f[b](\"y\"))){var g=d.attrs,h=d.node,i=h.firstChild?e(a._g.doc.defaultView.getComputedStyle(h.firstChild,l).getPropertyValue(\"font-size\"),10):10;if(f[b](\"text\")){g.text=f.text;while(h.firstChild)h.removeChild(h.firstChild);var j=c(f.text).split(\"\\n\"),k=[],m;for(var n=0,o=j.length;n<o;n++)m=q(\"tspan\"),n&&q(m,{dy:i*x,x:g.x}),m.appendChild(a._g.doc.createTextNode(j[n])),h.appendChild(m),k[n]=m}else{k=h.getElementsByTagName(\"tspan\");for(n=0,o=k.length;n<o;n++)n?q(k[n],{dy:i*x,x:g.x}):q(k[0],{dy:0})}q(h,{x:g.x,y:g.y}),d._.dirty=1;var p=d._getBBox(),r=g.y-(p.y+p.height/2);r&&a.is(r,\"finite\")&&q(k[0],{dy:r})}},z=function(b,c){var d=0,e=0;this[0]=this.node=b,b.raphael=!0,this.id=a._oid++,b.raphaelid=this.id,this.matrix=a.matrix(),this.realPath=null,this.paper=c,this.attrs=this.attrs||{},this._={transform:[],sx:1,sy:1,deg:0,dx:0,dy:0,dirty:1},!c.bottom&&(c.bottom=this),this.prev=c.top,c.top&&(c.top.next=this),c.top=this,this.next=null},A=a.el;z.prototype=A,A.constructor=z,a._engine.path=function(a,b){var c=q(\"path\");b.canvas&&b.canvas.appendChild(c);var d=new z(c,b);d.type=\"path\",w(d,{fill:\"none\",stroke:\"#000\",path:a});return d},A.rotate=function(a,b,e){if(this.removed)return this;a=c(a).split(j),a.length-1&&(b=d(a[1]),e=d(a[2])),a=d(a[0]),e==null&&(b=e);if(b==null||e==null){var f=this.getBBox(1);b=f.x+f.width/2,e=f.y+f.height/2}this.transform(this._.transform.concat([[\"r\",a,b,e]]));return this},A.scale=function(a,b,e,f){if(this.removed)return this;a=c(a).split(j),a.length-1&&(b=d(a[1]),e=d(a[2]),f=d(a[3])),a=d(a[0]),b==null&&(b=a),f==null&&(e=f);if(e==null||f==null)var g=this.getBBox(1);e=e==null?g.x+g.width/2:e,f=f==null?g.y+g.height/2:f,this.transform(this._.transform.concat([[\"s\",a,b,e,f]]));return this},A.translate=function(a,b){if(this.removed)return this;a=c(a).split(j),a.length-1&&(b=d(a[1])),a=d(a[0])||0,b=+b||0,this.transform(this._.transform.concat([[\"t\",a,b]]));return this},A.transform=function(c){var d=this._;if(c==null)return d.transform;a._extractTransform(this,c),this.clip&&q(this.clip,{transform:this.matrix.invert()}),this.pattern&&s(this),this.node&&q(this.node,{transform:this.matrix});if(d.sx!=1||d.sy!=1){var e=this.attrs[b](\"stroke-width\")?this.attrs[\"stroke-width\"]:1;this.attr({\"stroke-width\":e})}return this},A.hide=function(){!this.removed&&this.paper.safari(this.node.style.display=\"none\");return this},A.show=function(){!this.removed&&this.paper.safari(this.node.style.display=\"\");return this},A.remove=function(){if(!this.removed&&!!this.node.parentNode){var b=this.paper;b.__set__&&b.__set__.exclude(this),k.unbind(\"raphael.*.*.\"+this.id),this.gradient&&b.defs.removeChild(this.gradient),a._tear(this,b),this.node.parentNode.tagName.toLowerCase()==\"a\"?this.node.parentNode.parentNode.removeChild(this.node.parentNode):this.node.parentNode.removeChild(this.node);for(var c in this)this[c]=typeof this[c]==\"function\"?a._removedFactory(c):null;this.removed=!0}},A._getBBox=function(){if(this.node.style.display==\"none\"){this.show();var a=!0}var b={};try{b=this.node.getBBox()}catch(c){}finally{b=b||{}}a&&this.hide();return b},A.attr=function(c,d){if(this.removed)return this;if(c==null){var e={};for(var f in this.attrs)this.attrs[b](f)&&(e[f]=this.attrs[f]);e.gradient&&e.fill==\"none\"&&(e.fill=e.gradient)&&delete e.gradient,e.transform=this._.transform;return e}if(d==null&&a.is(c,\"string\")){if(c==\"fill\"&&this.attrs.fill==\"none\"&&this.attrs.gradient)return this.attrs.gradient;if(c==\"transform\")return this._.transform;var g=c.split(j),h={};for(var i=0,l=g.length;i<l;i++)c=g[i],c in this.attrs?h[c]=this.attrs[c]:a.is(this.paper.customAttributes[c],\"function\")?h[c]=this.paper.customAttributes[c].def:h[c]=a._availableAttrs[c];return l-1?h:h[g[0]]}if(d==null&&a.is(c,\"array\")){h={};for(i=0,l=c.length;i<l;i++)h[c[i]]=this.attr(c[i]);return h}if(d!=null){var m={};m[c]=d}else c!=null&&a.is(c,\"object\")&&(m=c);for(var n in m)k(\"raphael.attr.\"+n+\".\"+this.id,this,m[n]);for(n in this.paper.customAttributes)if(this.paper.customAttributes[b](n)&&m[b](n)&&a.is(this.paper.customAttributes[n],\"function\")){var o=this.paper.customAttributes[n].apply(this,[].concat(m[n]));this.attrs[n]=m[n];for(var p in o)o[b](p)&&(m[p]=o[p])}w(this,m);return this},A.toFront=function(){if(this.removed)return this;this.node.parentNode.tagName.toLowerCase()==\"a\"?this.node.parentNode.parentNode.appendChild(this.node.parentNode):this.node.parentNode.appendChild(this.node);var b=this.paper;b.top!=this&&a._tofront(this,b);return this},A.toBack=function(){if(this.removed)return this;var b=this.node.parentNode;b.tagName.toLowerCase()==\"a\"?b.parentNode.insertBefore(this.node.parentNode,this.node.parentNode.parentNode.firstChild):b.firstChild!=this.node&&b.insertBefore(this.node,this.node.parentNode.firstChild),a._toback(this,this.paper);var c=this.paper;return this},A.insertAfter=function(b){if(this.removed)return this;var c=b.node||b[b.length-1].node;c.nextSibling?c.parentNode.insertBefore(this.node,c.nextSibling):c.parentNode.appendChild(this.node),a._insertafter(this,b,this.paper);return this},A.insertBefore=function(b){if(this.removed)return this;var c=b.node||b[0].node;c.parentNode.insertBefore(this.node,c),a._insertbefore(this,b,this.paper);return this},A.blur=function(b){var c=this;if(+b!==0){var d=q(\"filter\"),e=q(\"feGaussianBlur\");c.attrs.blur=b,d.id=a.createUUID(),q(e,{stdDeviation:+b||1.5}),d.appendChild(e),c.paper.defs.appendChild(d),c._blur=d,q(c.node,{filter:\"url(#\"+d.id+\")\"})}else c._blur&&(c._blur.parentNode.removeChild(c._blur),delete c._blur,delete c.attrs.blur),c.node.removeAttribute(\"filter\")},a._engine.circle=function(a,b,c,d){var e=q(\"circle\");a.canvas&&a.canvas.appendChild(e);var f=new z(e,a);f.attrs={cx:b,cy:c,r:d,fill:\"none\",stroke:\"#000\"},f.type=\"circle\",q(e,f.attrs);return f},a._engine.rect=function(a,b,c,d,e,f){var g=q(\"rect\");a.canvas&&a.canvas.appendChild(g);var h=new z(g,a);h.attrs={x:b,y:c,width:d,height:e,r:f||0,rx:f||0,ry:f||0,fill:\"none\",stroke:\"#000\"},h.type=\"rect\",q(g,h.attrs);return h},a._engine.ellipse=function(a,b,c,d,e){var f=q(\"ellipse\");a.canvas&&a.canvas.appendChild(f);var g=new z(f,a);g.attrs={cx:b,cy:c,rx:d,ry:e,fill:\"none\",stroke:\"#000\"},g.type=\"ellipse\",q(f,g.attrs);return g},a._engine.image=function(a,b,c,d,e,f){var g=q(\"image\");q(g,{x:c,y:d,width:e,height:f,preserveAspectRatio:\"none\"}),g.setAttributeNS(n,\"href\",b),a.canvas&&a.canvas.appendChild(g);var h=new z(g,a);h.attrs={x:c,y:d,width:e,height:f,src:b},h.type=\"image\";return h},a._engine.text=function(b,c,d,e){var f=q(\"text\");b.canvas&&b.canvas.appendChild(f);var g=new z(f,b);g.attrs={x:c,y:d,\"text-anchor\":\"middle\",text:e,font:a._availableAttrs.font,stroke:\"none\",fill:\"#000\"},g.type=\"text\",w(g,g.attrs);return g},a._engine.setSize=function(a,b){this.width=a||this.width,this.height=b||this.height,this.canvas.setAttribute(\"width\",this.width),this.canvas.setAttribute(\"height\",this.height),this._viewBox&&this.setViewBox.apply(this,this._viewBox);return this},a._engine.create=function(){var b=a._getContainer.apply(0,arguments),c=b&&b.container,d=b.x,e=b.y,f=b.width,g=b.height;if(!c)throw new Error(\"SVG container not found.\");var h=q(\"svg\"),i=\"overflow:hidden;\",j;d=d||0,e=e||0,f=f||512,g=g||342,q(h,{height:g,version:1.1,width:f,xmlns:\"http://www.w3.org/2000/svg\"}),c==1?(h.style.cssText=i+\"position:absolute;left:\"+d+\"px;top:\"+e+\"px\",a._g.doc.body.appendChild(h),j=1):(h.style.cssText=i+\"position:relative\",c.firstChild?c.insertBefore(h,c.firstChild):c.appendChild(h)),c=new a._Paper,c.width=f,c.height=g,c.canvas=h,c.clear(),c._left=c._top=0,j&&(c.renderfix=function(){}),c.renderfix();return c},a._engine.setViewBox=function(a,b,c,d,e){k(\"raphael.setViewBox\",this,this._viewBox,[a,b,c,d,e]);var f=g(c/this.width,d/this.height),h=this.top,i=e?\"meet\":\"xMinYMin\",j,l;a==null?(this._vbSize&&(f=1),delete this._vbSize,j=\"0 0 \"+this.width+m+this.height):(this._vbSize=f,j=a+m+b+m+c+m+d),q(this.canvas,{viewBox:j,preserveAspectRatio:i});while(f&&h)l=\"stroke-width\"in h.attrs?h.attrs[\"stroke-width\"]:1,h.attr({\"stroke-width\":l}),h._.dirty=1,h._.dirtyT=1,h=h.prev;this._viewBox=[a,b,c,d,!!e];return this},a.prototype.renderfix=function(){var a=this.canvas,b=a.style,c;try{c=a.getScreenCTM()||a.createSVGMatrix()}catch(d){c=a.createSVGMatrix()}var e=-c.e%1,f=-c.f%1;if(e||f)e&&(this._left=(this._left+e)%1,b.left=this._left+\"px\"),f&&(this._top=(this._top+f)%1,b.top=this._top+\"px\")},a.prototype.clear=function(){a.eve(\"raphael.clear\",this);var b=this.canvas;while(b.firstChild)b.removeChild(b.firstChild);this.bottom=this.top=null,(this.desc=q(\"desc\")).appendChild(a._g.doc.createTextNode(\"Created with Raphaël \"+a.version)),b.appendChild(this.desc),b.appendChild(this.defs=q(\"defs\"))},a.prototype.remove=function(){k(\"raphael.remove\",this),this.canvas.parentNode&&this.canvas.parentNode.removeChild(this.canvas);for(var b in this)this[b]=typeof this[b]==\"function\"?a._removedFactory(b):null};var B=a.st;for(var C in A)A[b](C)&&!B[b](C)&&(B[C]=function(a){return function(){var b=arguments;return this.forEach(function(c){c[a].apply(c,b)})}}(C))}(window.Raphael),window.Raphael.vml&&function(a){var b=\"hasOwnProperty\",c=String,d=parseFloat,e=Math,f=e.round,g=e.max,h=e.min,i=e.abs,j=\"fill\",k=/[, ]+/,l=a.eve,m=\" progid:DXImageTransform.Microsoft\",n=\" \",o=\"\",p={M:\"m\",L:\"l\",C:\"c\",Z:\"x\",m:\"t\",l:\"r\",c:\"v\",z:\"x\"},q=/([clmz]),?([^clmz]*)/gi,r=/ progid:\\S+Blur\\([^\\)]+\\)/g,s=/-?[^,\\s-]+/g,t=\"position:absolute;left:0;top:0;width:1px;height:1px\",u=21600,v={path:1,rect:1,image:1},w={circle:1,ellipse:1},x=function(b){var d=/[ahqstv]/ig,e=a._pathToAbsolute;c(b).match(d)&&(e=a._path2curve),d=/[clmz]/g;if(e==a._pathToAbsolute&&!c(b).match(d)){var g=c(b).replace(q,function(a,b,c){var d=[],e=b.toLowerCase()==\"m\",g=p[b];c.replace(s,function(a){e&&d.length==2&&(g+=d+p[b==\"m\"?\"l\":\"L\"],d=[]),d.push(f(a*u))});return g+d});return g}var h=e(b),i,j;g=[];for(var k=0,l=h.length;k<l;k++){i=h[k],j=h[k][0].toLowerCase(),j==\"z\"&&(j=\"x\");for(var m=1,r=i.length;m<r;m++)j+=f(i[m]*u)+(m!=r-1?\",\":o);g.push(j)}return g.join(n)},y=function(b,c,d){var e=a.matrix();e.rotate(-b,.5,.5);return{dx:e.x(c,d),dy:e.y(c,d)}},z=function(a,b,c,d,e,f){var g=a._,h=a.matrix,k=g.fillpos,l=a.node,m=l.style,o=1,p=\"\",q,r=u/b,s=u/c;m.visibility=\"hidden\";if(!!b&&!!c){l.coordsize=i(r)+n+i(s),m.rotation=f*(b*c<0?-1:1);if(f){var t=y(f,d,e);d=t.dx,e=t.dy}b<0&&(p+=\"x\"),c<0&&(p+=\" y\")&&(o=-1),m.flip=p,l.coordorigin=d*-r+n+e*-s;if(k||g.fillsize){var v=l.getElementsByTagName(j);v=v&&v[0],l.removeChild(v),k&&(t=y(f,h.x(k[0],k[1]),h.y(k[0],k[1])),v.position=t.dx*o+n+t.dy*o),g.fillsize&&(v.size=g.fillsize[0]*i(b)+n+g.fillsize[1]*i(c)),l.appendChild(v)}m.visibility=\"visible\"}};a.toString=function(){return\"Your browser doesn’t support SVG. Falling down to VML.\\nYou are running Raphaël \"+this.version};var A=function(a,b,d){var e=c(b).toLowerCase().split(\"-\"),f=d?\"end\":\"start\",g=e.length,h=\"classic\",i=\"medium\",j=\"medium\";while(g--)switch(e[g]){case\"block\":case\"classic\":case\"oval\":case\"diamond\":case\"open\":case\"none\":h=e[g];break;case\"wide\":case\"narrow\":j=e[g];break;case\"long\":case\"short\":i=e[g]}var k=a.node.getElementsByTagName(\"stroke\")[0];k[f+\"arrow\"]=h,k[f+\"arrowlength\"]=i,k[f+\"arrowwidth\"]=j},B=function(e,i){e.attrs=e.attrs||{};var l=e.node,m=e.attrs,p=l.style,q,r=v[e.type]&&(i.x!=m.x||i.y!=m.y||i.width!=m.width||i.height!=m.height||i.cx!=m.cx||i.cy!=m.cy||i.rx!=m.rx||i.ry!=m.ry||i.r!=m.r),s=w[e.type]&&(m.cx!=i.cx||m.cy!=i.cy||m.r!=i.r||m.rx!=i.rx||m.ry!=i.ry),t=e;for(var y in i)i[b](y)&&(m[y]=i[y]);r&&(m.path=a._getPath[e.type](e),e._.dirty=1),i.href&&(l.href=i.href),i.title&&(l.title=i.title),i.target&&(l.target=i.target),i.cursor&&(p.cursor=i.cursor),\"blur\"in i&&e.blur(i.blur);if(i.path&&e.type==\"path\"||r)l.path=x(~c(m.path).toLowerCase().indexOf(\"r\")?a._pathToAbsolute(m.path):m.path),e.type==\"image\"&&(e._.fillpos=[m.x,m.y],e._.fillsize=[m.width,m.height],z(e,1,1,0,0,0));\"transform\"in i&&e.transform(i.transform);if(s){var B=+m.cx,D=+m.cy,E=+m.rx||+m.r||0,G=+m.ry||+m.r||0;l.path=a.format(\"ar{0},{1},{2},{3},{4},{1},{4},{1}x\",f((B-E)*u),f((D-G)*u),f((B+E)*u),f((D+G)*u),f(B*u))}if(\"clip-rect\"in i){var H=c(i[\"clip-rect\"]).split(k);if(H.length==4){H[2]=+H[2]+ +H[0],H[3]=+H[3]+ +H[1];var I=l.clipRect||a._g.doc.createElement(\"div\"),J=I.style;J.clip=a.format(\"rect({1}px {2}px {3}px {0}px)\",H),l.clipRect||(J.position=\"absolute\",J.top=0,J.left=0,J.width=e.paper.width+\"px\",J.height=e.paper.height+\"px\",l.parentNode.insertBefore(I,l),I.appendChild(l),l.clipRect=I)}i[\"clip-rect\"]||l.clipRect&&(l.clipRect.style.clip=\"auto\")}if(e.textpath){var K=e.textpath.style;i.font&&(K.font=i.font),i[\"font-family\"]&&(K.fontFamily='\"'+i[\"font-family\"].split(\",\")[0].replace(/^['\"]+|['\"]+$/g,o)+'\"'),i[\"font-size\"]&&(K.fontSize=i[\"font-size\"]),i[\"font-weight\"]&&(K.fontWeight=i[\"font-weight\"]),i[\"font-style\"]&&(K.fontStyle=i[\"font-style\"])}\"arrow-start\"in i&&A(t,i[\"arrow-start\"]),\"arrow-end\"in i&&A(t,i[\"arrow-end\"],1);if(i.opacity!=null||i[\"stroke-width\"]!=null||i.fill!=null||i.src!=null||i.stroke!=null||i[\"stroke-width\"]!=null||i[\"stroke-opacity\"]!=null||i[\"fill-opacity\"]!=null||i[\"stroke-dasharray\"]!=null||i[\"stroke-miterlimit\"]!=null||i[\"stroke-linejoin\"]!=null||i[\"stroke-linecap\"]!=null){var L=l.getElementsByTagName(j),M=!1;L=L&&L[0],!L&&(M=L=F(j)),e.type==\"image\"&&i.src&&(L.src=i.src),i.fill&&(L.on=!0);if(L.on==null||i.fill==\"none\"||i.fill===null)L.on=!1;if(L.on&&i.fill){var N=c(i.fill).match(a._ISURL);if(N){L.parentNode==l&&l.removeChild(L),L.rotate=!0,L.src=N[1],L.type=\"tile\";var O=e.getBBox(1);L.position=O.x+n+O.y,e._.fillpos=[O.x,O.y],a._preload(N[1],function(){e._.fillsize=[this.offsetWidth,this.offsetHeight]})}else L.color=a.getRGB(i.fill).hex,L.src=o,L.type=\"solid\",a.getRGB(i.fill).error&&(t.type in{circle:1,ellipse:1}||c(i.fill).charAt()!=\"r\")&&C(t,i.fill,L)&&(m.fill=\"none\",m.gradient=i.fill,L.rotate=!1)}if(\"fill-opacity\"in i||\"opacity\"in i){var P=((+m[\"fill-opacity\"]+1||2)-1)*((+m.opacity+1||2)-1)*((+a.getRGB(i.fill).o+1||2)-1);P=h(g(P,0),1),L.opacity=P,L.src&&(L.color=\"none\")}l.appendChild(L);var Q=l.getElementsByTagName(\"stroke\")&&l.getElementsByTagName(\"stroke\")[0],T=!1;!Q&&(T=Q=F(\"stroke\"));if(i.stroke&&i.stroke!=\"none\"||i[\"stroke-width\"]||i[\"stroke-opacity\"]!=null||i[\"stroke-dasharray\"]||i[\"stroke-miterlimit\"]||i[\"stroke-linejoin\"]||i[\"stroke-linecap\"])Q.on=!0;(i.stroke==\"none\"||i.stroke===null||Q.on==null||i.stroke==0||i[\"stroke-width\"]==0)&&(Q.on=!1);var U=a.getRGB(i.stroke);Q.on&&i.stroke&&(Q.color=U.hex),P=((+m[\"stroke-opacity\"]+1||2)-1)*((+m.opacity+1||2)-1)*((+U.o+1||2)-1);var V=(d(i[\"stroke-width\"])||1)*.75;P=h(g(P,0),1),i[\"stroke-width\"]==null&&(V=m[\"stroke-width\"]),i[\"stroke-width\"]&&(Q.weight=V),V&&V<1&&(P*=V)&&(Q.weight=1),Q.opacity=P,i[\"stroke-linejoin\"]&&(Q.joinstyle=i[\"stroke-linejoin\"]||\"miter\"),Q.miterlimit=i[\"stroke-miterlimit\"]||8,i[\"stroke-linecap\"]&&(Q.endcap=i[\"stroke-linecap\"]==\"butt\"?\"flat\":i[\"stroke-linecap\"]==\"square\"?\"square\":\"round\");if(i[\"stroke-dasharray\"]){var W={\"-\":\"shortdash\",\".\":\"shortdot\",\"-.\":\"shortdashdot\",\"-..\":\"shortdashdotdot\",\". \":\"dot\",\"- \":\"dash\",\"--\":\"longdash\",\"- .\":\"dashdot\",\"--.\":\"longdashdot\",\"--..\":\"longdashdotdot\"};Q.dashstyle=W[b](i[\"stroke-dasharray\"])?W[i[\"stroke-dasharray\"]]:o}T&&l.appendChild(Q)}if(t.type==\"text\"){t.paper.canvas.style.display=o;var X=t.paper.span,Y=100,Z=m.font&&m.font.match(/\\d+(?:\\.\\d*)?(?=px)/);p=X.style,m.font&&(p.font=m.font),m[\"font-family\"]&&(p.fontFamily=m[\"font-family\"]),m[\"font-weight\"]&&(p.fontWeight=m[\"font-weight\"]),m[\"font-style\"]&&(p.fontStyle=m[\"font-style\"]),Z=d(m[\"font-size\"]||Z&&Z[0])||10,p.fontSize=Z*Y+\"px\",t.textpath.string&&(X.innerHTML=c(t.textpath.string).replace(/</g,\"&#60;\").replace(/&/g,\"&#38;\").replace(/\\n/g,\"<br>\"));var $=X.getBoundingClientRect();t.W=m.w=($.right-$.left)/Y,t.H=m.h=($.bottom-$.top)/Y,t.X=m.x,t.Y=m.y+t.H/2,(\"x\"in i||\"y\"in i)&&(t.path.v=a.format(\"m{0},{1}l{2},{1}\",f(m.x*u),f(m.y*u),f(m.x*u)+1));var _=[\"x\",\"y\",\"text\",\"font\",\"font-family\",\"font-weight\",\"font-style\",\"font-size\"];for(var ba=0,bb=_.length;ba<bb;ba++)if(_[ba]in i){t._.dirty=1;break}switch(m[\"text-anchor\"]){case\"start\":t.textpath.style[\"v-text-align\"]=\"left\",t.bbx=t.W/2;break;case\"end\":t.textpath.style[\"v-text-align\"]=\"right\",t.bbx=-t.W/2;break;default:t.textpath.style[\"v-text-align\"]=\"center\",t.bbx=0}t.textpath.style[\"v-text-kern\"]=!0}},C=function(b,f,g){b.attrs=b.attrs||{};var h=b.attrs,i=Math.pow,j,k,l=\"linear\",m=\".5 .5\";b.attrs.gradient=f,f=c(f).replace(a._radial_gradient,function(a,b,c){l=\"radial\",b&&c&&(b=d(b),c=d(c),i(b-.5,2)+i(c-.5,2)>.25&&(c=e.sqrt(.25-i(b-.5,2))*((c>.5)*2-1)+.5),m=b+n+c);return o}),f=f.split(/\\s*\\-\\s*/);if(l==\"linear\"){var p=f.shift();p=-d(p);if(isNaN(p))return null}var q=a._parseDots(f);if(!q)return null;b=b.shape||b.node;if(q.length){b.removeChild(g),g.on=!0,g.method=\"none\",g.color=q[0].color,g.color2=q[q.length-1].color;var r=[];for(var s=0,t=q.length;s<t;s++)q[s].offset&&r.push(q[s].offset+n+q[s].color);g.colors=r.length?r.join():\"0% \"+g.color,l==\"radial\"?(g.type=\"gradientTitle\",g.focus=\"100%\",g.focussize=\"0 0\",g.focusposition=m,g.angle=0):(g.type=\"gradient\",g.angle=(270-p)%360),b.appendChild(g)}return 1},D=function(b,c){this[0]=this.node=b,b.raphael=!0,this.id=a._oid++,b.raphaelid=this.id,this.X=0,this.Y=0,this.attrs={},this.paper=c,this.matrix=a.matrix(),this._={transform:[],sx:1,sy:1,dx:0,dy:0,deg:0,dirty:1,dirtyT:1},!c.bottom&&(c.bottom=this),this.prev=c.top,c.top&&(c.top.next=this),c.top=this,this.next=null},E=a.el;D.prototype=E,E.constructor=D,E.transform=function(b){if(b==null)return this._.transform;var d=this.paper._viewBoxShift,e=d?\"s\"+[d.scale,d.scale]+\"-1-1t\"+[d.dx,d.dy]:o,f;d&&(f=b=c(b).replace(/\\.{3}|\\u2026/g,this._.transform||o)),a._extractTransform(this,e+b);var g=this.matrix.clone(),h=this.skew,i=this.node,j,k=~c(this.attrs.fill).indexOf(\"-\"),l=!c(this.attrs.fill).indexOf(\"url(\");g.translate(-0.5,-0.5);if(l||k||this.type==\"image\"){h.matrix=\"1 0 0 1\",h.offset=\"0 0\",j=g.split();if(k&&j.noRotation||!j.isSimple){i.style.filter=g.toFilter();var m=this.getBBox(),p=this.getBBox(1),q=m.x-p.x,r=m.y-p.y;i.coordorigin=q*-u+n+r*-u,z(this,1,1,q,r,0)}else i.style.filter=o,z(this,j.scalex,j.scaley,j.dx,j.dy,j.rotate)}else i.style.filter=o,h.matrix=c(g),h.offset=g.offset();f&&(this._.transform=f);return this},E.rotate=function(a,b,e){if(this.removed)return this;if(a!=null){a=c(a).split(k),a.length-1&&(b=d(a[1]),e=d(a[2])),a=d(a[0]),e==null&&(b=e);if(b==null||e==null){var f=this.getBBox(1);b=f.x+f.width/2,e=f.y+f.height/2}this._.dirtyT=1,this.transform(this._.transform.concat([[\"r\",a,b,e]]));return this}},E.translate=function(a,b){if(this.removed)return this;a=c(a).split(k),a.length-1&&(b=d(a[1])),a=d(a[0])||0,b=+b||0,this._.bbox&&(this._.bbox.x+=a,this._.bbox.y+=b),this.transform(this._.transform.concat([[\"t\",a,b]]));return this},E.scale=function(a,b,e,f){if(this.removed)return this;a=c(a).split(k),a.length-1&&(b=d(a[1]),e=d(a[2]),f=d(a[3]),isNaN(e)&&(e=null),isNaN(f)&&(f=null)),a=d(a[0]),b==null&&(b=a),f==null&&(e=f);if(e==null||f==null)var g=this.getBBox(1);e=e==null?g.x+g.width/2:e,f=f==null?g.y+g.height/2:f,this.transform(this._.transform.concat([[\"s\",a,b,e,f]])),this._.dirtyT=1;return this},E.hide=function(){!this.removed&&(this.node.style.display=\"none\");return this},E.show=function(){!this.removed&&(this.node.style.display=o);return this},E._getBBox=function(){if(this.removed)return{};return{x:this.X+(this.bbx||0)-this.W/2,y:this.Y-this.H,width:this.W,height:this.H}},E.remove=function(){if(!this.removed&&!!this.node.parentNode){this.paper.__set__&&this.paper.__set__.exclude(this),a.eve.unbind(\"raphael.*.*.\"+this.id),a._tear(this,this.paper),this.node.parentNode.removeChild(this.node),this.shape&&this.shape.parentNode.removeChild(this.shape);for(var b in this)this[b]=typeof this[b]==\"function\"?a._removedFactory(b):null;this.removed=!0}},E.attr=function(c,d){if(this.removed)return this;if(c==null){var e={};for(var f in this.attrs)this.attrs[b](f)&&(e[f]=this.attrs[f]);e.gradient&&e.fill==\"none\"&&(e.fill=e.gradient)&&delete e.gradient,e.transform=this._.transform;return e}if(d==null&&a.is(c,\"string\")){if(c==j&&this.attrs.fill==\"none\"&&this.attrs.gradient)return this.attrs.gradient;var g=c.split(k),h={};for(var i=0,m=g.length;i<m;i++)c=g[i],c in this.attrs?h[c]=this.attrs[c]:a.is(this.paper.customAttributes[c],\"function\")?h[c]=this.paper.customAttributes[c].def:h[c]=a._availableAttrs[c];return m-1?h:h[g[0]]}if(this.attrs&&d==null&&a.is(c,\"array\")){h={};for(i=0,m=c.length;i<m;i++)h[c[i]]=this.attr(c[i]);return h}var n;d!=null&&(n={},n[c]=d),d==null&&a.is(c,\"object\")&&(n=c);for(var o in n)l(\"raphael.attr.\"+o+\".\"+this.id,this,n[o]);if(n){for(o in this.paper.customAttributes)if(this.paper.customAttributes[b](o)&&n[b](o)&&a.is(this.paper.customAttributes[o],\"function\")){var p=this.paper.customAttributes[o].apply(this,[].concat(n[o]));this.attrs[o]=n[o];for(var q in p)p[b](q)&&(n[q]=p[q])}n.text&&this.type==\"text\"&&(this.textpath.string=n.text),B(this,n)}return this},E.toFront=function(){!this.removed&&this.node.parentNode.appendChild(this.node),this.paper&&this.paper.top!=this&&a._tofront(this,this.paper);return this},E.toBack=function(){if(this.removed)return this;this.node.parentNode.firstChild!=this.node&&(this.node.parentNode.insertBefore(this.node,this.node.parentNode.firstChild),a._toback(this,this.paper));return this},E.insertAfter=function(b){if(this.removed)return this;b.constructor==a.st.constructor&&(b=b[b.length-1]),b.node.nextSibling?b.node.parentNode.insertBefore(this.node,b.node.nextSibling):b.node.parentNode.appendChild(this.node),a._insertafter(this,b,this.paper);return this},E.insertBefore=function(b){if(this.removed)return this;b.constructor==a.st.constructor&&(b=b[0]),b.node.parentNode.insertBefore(this.node,b.node),a._insertbefore(this,b,this.paper);return this},E.blur=function(b){var c=this.node.runtimeStyle,d=c.filter;d=d.replace(r,o),+b!==0?(this.attrs.blur=b,c.filter=d+n+m+\".Blur(pixelradius=\"+(+b||1.5)+\")\",c.margin=a.format(\"-{0}px 0 0 -{0}px\",f(+b||1.5))):(c.filter=d,c.margin=0,delete this.attrs.blur)},a._engine.path=function(a,b){var c=F(\"shape\");c.style.cssText=t,c.coordsize=u+n+u,c.coordorigin=b.coordorigin;var d=new D(c,b),e={fill:\"none\",stroke:\"#000\"};a&&(e.path=a),d.type=\"path\",d.path=[],d.Path=o,B(d,e),b.canvas.appendChild(c);var f=F(\"skew\");f.on=!0,c.appendChild(f),d.skew=f,d.transform(o);return d},a._engine.rect=function(b,c,d,e,f,g){var h=a._rectPath(c,d,e,f,g),i=b.path(h),j=i.attrs;i.X=j.x=c,i.Y=j.y=d,i.W=j.width=e,i.H=j.height=f,j.r=g,j.path=h,i.type=\"rect\";return i},a._engine.ellipse=function(a,b,c,d,e){var f=a.path(),g=f.attrs;f.X=b-d,f.Y=c-e,f.W=d*2,f.H=e*2,f.type=\"ellipse\",B(f,{cx:b,cy:c,rx:d,ry:e});return f},a._engine.circle=function(a,b,c,d){var e=a.path(),f=e.attrs;e.X=b-d,e.Y=c-d,e.W=e.H=d*2,e.type=\"circle\",B(e,{cx:b,cy:c,r:d});return e},a._engine.image=function(b,c,d,e,f,g){var h=a._rectPath(d,e,f,g),i=b.path(h).attr({stroke:\"none\"}),k=i.attrs,l=i.node,m=l.getElementsByTagName(j)[0];k.src=c,i.X=k.x=d,i.Y=k.y=e,i.W=k.width=f,i.H=k.height=g,k.path=h,i.type=\"image\",m.parentNode==l&&l.removeChild(m),m.rotate=!0,m.src=c,m.type=\"tile\",i._.fillpos=[d,e],i._.fillsize=[f,g],l.appendChild(m),z(i,1,1,0,0,0);return i},a._engine.text=function(b,d,e,g){var h=F(\"shape\"),i=F(\"path\"),j=F(\"textpath\");d=d||0,e=e||0,g=g||\"\",i.v=a.format(\"m{0},{1}l{2},{1}\",f(d*u),f(e*u),f(d*u)+1),i.textpathok=!0,j.string=c(g),j.on=!0,h.style.cssText=t,h.coordsize=u+n+u,h.coordorigin=\"0 0\";var k=new D(h,b),l={fill:\"#000\",stroke:\"none\",font:a._availableAttrs.font,text:g};k.shape=h,k.path=i,k.textpath=j,k.type=\"text\",k.attrs.text=c(g),k.attrs.x=d,k.attrs.y=e,k.attrs.w=1,k.attrs.h=1,B(k,l),h.appendChild(j),h.appendChild(i),b.canvas.appendChild(h);var m=F(\"skew\");m.on=!0,h.appendChild(m),k.skew=m,k.transform(o);return k},a._engine.setSize=function(b,c){var d=this.canvas.style;this.width=b,this.height=c,b==+b&&(b+=\"px\"),c==+c&&(c+=\"px\"),d.width=b,d.height=c,d.clip=\"rect(0 \"+b+\" \"+c+\" 0)\",this._viewBox&&a._engine.setViewBox.apply(this,this._viewBox);return this},a._engine.setViewBox=function(b,c,d,e,f){a.eve(\"raphael.setViewBox\",this,this._viewBox,[b,c,d,e,f]);var h=this.width,i=this.height,j=1/g(d/h,e/i),k,l;f&&(k=i/e,l=h/d,d*k<h&&(b-=(h-d*k)/2/k),e*l<i&&(c-=(i-e*l)/2/l)),this._viewBox=[b,c,d,e,!!f],this._viewBoxShift={dx:-b,dy:-c,scale:j},this.forEach(function(a){a.transform(\"...\")});return this};var F;a._engine.initWin=function(a){var b=a.document;b.createStyleSheet().addRule(\".rvml\",\"behavior:url(#default#VML)\");try{!b.namespaces.rvml&&b.namespaces.add(\"rvml\",\"urn:schemas-microsoft-com:vml\"),F=function(a){return b.createElement(\"<rvml:\"+a+' class=\"rvml\">')}}catch(c){F=function(a){return b.createElement(\"<\"+a+' xmlns=\"urn:schemas-microsoft.com:vml\" class=\"rvml\">')}}},a._engine.initWin(a._g.win),a._engine.create=function(){var b=a._getContainer.apply(0,arguments),c=b.container,d=b.height,e,f=b.width,g=b.x,h=b.y;if(!c)throw new Error(\"VML container not found.\");var i=new a._Paper,j=i.canvas=a._g.doc.createElement(\"div\"),k=j.style;g=g||0,h=h||0,f=f||512,d=d||342,i.width=f,i.height=d,f==+f&&(f+=\"px\"),d==+d&&(d+=\"px\"),i.coordsize=u*1e3+n+u*1e3,i.coordorigin=\"0 0\",i.span=a._g.doc.createElement(\"span\"),i.span.style.cssText=\"position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;\",j.appendChild(i.span),k.cssText=a.format(\"top:0;left:0;width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden\",f,d),c==1?(a._g.doc.body.appendChild(j),k.left=g+\"px\",k.top=h+\"px\",k.position=\"absolute\"):c.firstChild?c.insertBefore(j,c.firstChild):c.appendChild(j),i.renderfix=function(){};return i},a.prototype.clear=function(){a.eve(\"raphael.clear\",this),this.canvas.innerHTML=o,this.span=a._g.doc.createElement(\"span\"),this.span.style.cssText=\"position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;\",this.canvas.appendChild(this.span),this.bottom=this.top=null},a.prototype.remove=function(){a.eve(\"raphael.remove\",this),this.canvas.parentNode.removeChild(this.canvas);for(var b in this)this[b]=typeof this[b]==\"function\"?a._removedFactory(b):null;return!0};var G=a.st;for(var H in E)E[b](H)&&!G[b](H)&&(G[H]=function(a){return function(){var b=arguments;return this.forEach(function(c){c[a].apply(c,b)})}}(H))}(window.Raphael)"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/diagram-viewer/js/raphael_uncompressed.js",
    "content": "// ┌────────────────────────────────────────────────────────────────────┐ \\\\\n// │ Raphaël 2.1.0 - JavaScript Vector Library                          │ \\\\\n// ├────────────────────────────────────────────────────────────────────┤ \\\\\n// │ Copyright © 2008-2012 Dmitry Baranovskiy (http://raphaeljs.com)    │ \\\\\n// │ Copyright © 2008-2012 Sencha Labs (http://sencha.com)              │ \\\\\n// ├────────────────────────────────────────────────────────────────────┤ \\\\\n// │ Licensed under the MIT (http://raphaeljs.com/license.html) license.│ \\\\\n// └────────────────────────────────────────────────────────────────────┘ \\\\\n\n// ┌──────────────────────────────────────────────────────────────────────────────────────┐ \\\\\n// │ Eve 0.3.4 - JavaScript Events Library                                                │ \\\\\n// ├──────────────────────────────────────────────────────────────────────────────────────┤ \\\\\n// │ Copyright (c) 2008-2011 Dmitry Baranovskiy (http://dmitry.baranovskiy.com/)          │ \\\\\n// │ Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license. │ \\\\\n// └──────────────────────────────────────────────────────────────────────────────────────┘ \\\\\n\n(function (glob) {\n    var version = \"0.3.4\",\n        has = \"hasOwnProperty\",\n        separator = /[\\.\\/]/,\n        wildcard = \"*\",\n        fun = function () {},\n        numsort = function (a, b) {\n            return a - b;\n        },\n        current_event,\n        stop,\n        events = {n: {}},\n    \n        eve = function (name, scope) {\n            var e = events,\n                oldstop = stop,\n                args = Array.prototype.slice.call(arguments, 2),\n                listeners = eve.listeners(name),\n                z = 0,\n                f = false,\n                l,\n                indexed = [],\n                queue = {},\n                out = [],\n                ce = current_event,\n                errors = [];\n            current_event = name;\n            stop = 0;\n            for (var i = 0, ii = listeners.length; i < ii; i++) if (\"zIndex\" in listeners[i]) {\n                indexed.push(listeners[i].zIndex);\n                if (listeners[i].zIndex < 0) {\n                    queue[listeners[i].zIndex] = listeners[i];\n                }\n            }\n            indexed.sort(numsort);\n            while (indexed[z] < 0) {\n                l = queue[indexed[z++]];\n                out.push(l.apply(scope, args));\n                if (stop) {\n                    stop = oldstop;\n                    return out;\n                }\n            }\n            for (i = 0; i < ii; i++) {\n                l = listeners[i];\n                if (\"zIndex\" in l) {\n                    if (l.zIndex == indexed[z]) {\n                        out.push(l.apply(scope, args));\n                        if (stop) {\n                            break;\n                        }\n                        do {\n                            z++;\n                            l = queue[indexed[z]];\n                            l && out.push(l.apply(scope, args));\n                            if (stop) {\n                                break;\n                            }\n                        } while (l)\n                    } else {\n                        queue[l.zIndex] = l;\n                    }\n                } else {\n                    out.push(l.apply(scope, args));\n                    if (stop) {\n                        break;\n                    }\n                }\n            }\n            stop = oldstop;\n            current_event = ce;\n            return out.length ? out : null;\n        };\n    \n    eve.listeners = function (name) {\n        var names = name.split(separator),\n            e = events,\n            item,\n            items,\n            k,\n            i,\n            ii,\n            j,\n            jj,\n            nes,\n            es = [e],\n            out = [];\n        for (i = 0, ii = names.length; i < ii; i++) {\n            nes = [];\n            for (j = 0, jj = es.length; j < jj; j++) {\n                e = es[j].n;\n                items = [e[names[i]], e[wildcard]];\n                k = 2;\n                while (k--) {\n                    item = items[k];\n                    if (item) {\n                        nes.push(item);\n                        out = out.concat(item.f || []);\n                    }\n                }\n            }\n            es = nes;\n        }\n        return out;\n    };\n    \n    \n    eve.on = function (name, f) {\n        var names = name.split(separator),\n            e = events;\n        for (var i = 0, ii = names.length; i < ii; i++) {\n            e = e.n;\n            !e[names[i]] && (e[names[i]] = {n: {}});\n            e = e[names[i]];\n        }\n        e.f = e.f || [];\n        for (i = 0, ii = e.f.length; i < ii; i++) if (e.f[i] == f) {\n            return fun;\n        }\n        e.f.push(f);\n        return function (zIndex) {\n            if (+zIndex == +zIndex) {\n                f.zIndex = +zIndex;\n            }\n        };\n    };\n    \n    eve.stop = function () {\n        stop = 1;\n    };\n    \n    eve.nt = function (subname) {\n        if (subname) {\n            return new RegExp(\"(?:\\\\.|\\\\/|^)\" + subname + \"(?:\\\\.|\\\\/|$)\").test(current_event);\n        }\n        return current_event;\n    };\n    \n    \n    eve.off = eve.unbind = function (name, f) {\n        var names = name.split(separator),\n            e,\n            key,\n            splice,\n            i, ii, j, jj,\n            cur = [events];\n        for (i = 0, ii = names.length; i < ii; i++) {\n            for (j = 0; j < cur.length; j += splice.length - 2) {\n                splice = [j, 1];\n                e = cur[j].n;\n                if (names[i] != wildcard) {\n                    if (e[names[i]]) {\n                        splice.push(e[names[i]]);\n                    }\n                } else {\n                    for (key in e) if (e[has](key)) {\n                        splice.push(e[key]);\n                    }\n                }\n                cur.splice.apply(cur, splice);\n            }\n        }\n        for (i = 0, ii = cur.length; i < ii; i++) {\n            e = cur[i];\n            while (e.n) {\n                if (f) {\n                    if (e.f) {\n                        for (j = 0, jj = e.f.length; j < jj; j++) if (e.f[j] == f) {\n                            e.f.splice(j, 1);\n                            break;\n                        }\n                        !e.f.length && delete e.f;\n                    }\n                    for (key in e.n) if (e.n[has](key) && e.n[key].f) {\n                        var funcs = e.n[key].f;\n                        for (j = 0, jj = funcs.length; j < jj; j++) if (funcs[j] == f) {\n                            funcs.splice(j, 1);\n                            break;\n                        }\n                        !funcs.length && delete e.n[key].f;\n                    }\n                } else {\n                    delete e.f;\n                    for (key in e.n) if (e.n[has](key) && e.n[key].f) {\n                        delete e.n[key].f;\n                    }\n                }\n                e = e.n;\n            }\n        }\n    };\n    \n    eve.once = function (name, f) {\n        var f2 = function () {\n            var res = f.apply(this, arguments);\n            eve.unbind(name, f2);\n            return res;\n        };\n        return eve.on(name, f2);\n    };\n    \n    eve.version = version;\n    eve.toString = function () {\n        return \"You are running Eve \" + version;\n    };\n    (typeof module != \"undefined\" && module.exports) ? (module.exports = eve) : (typeof define != \"undefined\" ? (define(\"eve\", [], function() { return eve; })) : (glob.eve = eve));\n})(this);\n\n\n// ┌─────────────────────────────────────────────────────────────────────┐ \\\\\n// │ \"Raphaël 2.1.0\" - JavaScript Vector Library                         │ \\\\\n// ├─────────────────────────────────────────────────────────────────────┤ \\\\\n// │ Copyright (c) 2008-2011 Dmitry Baranovskiy (http://raphaeljs.com)   │ \\\\\n// │ Copyright (c) 2008-2011 Sencha Labs (http://sencha.com)             │ \\\\\n// │ Licensed under the MIT (http://raphaeljs.com/license.html) license. │ \\\\\n// └─────────────────────────────────────────────────────────────────────┘ \\\\\n(function () {\n    \n    function R(first) {\n        if (R.is(first, \"function\")) {\n            return loaded ? first() : eve.on(\"raphael.DOMload\", first);\n        } else if (R.is(first, array)) {\n            return R._engine.create[apply](R, first.splice(0, 3 + R.is(first[0], nu))).add(first);\n        } else {\n            var args = Array.prototype.slice.call(arguments, 0);\n            if (R.is(args[args.length - 1], \"function\")) {\n                var f = args.pop();\n                return loaded ? f.call(R._engine.create[apply](R, args)) : eve.on(\"raphael.DOMload\", function () {\n                    f.call(R._engine.create[apply](R, args));\n                });\n            } else {\n                return R._engine.create[apply](R, arguments);\n            }\n        }\n    }\n    R.version = \"2.1.0\";\n    R.eve = eve;\n    var loaded,\n        separator = /[, ]+/,\n        elements = {circle: 1, rect: 1, path: 1, ellipse: 1, text: 1, image: 1},\n        formatrg = /\\{(\\d+)\\}/g,\n        proto = \"prototype\",\n        has = \"hasOwnProperty\",\n        g = {\n            doc: document,\n            win: window\n        },\n        oldRaphael = {\n            was: Object.prototype[has].call(g.win, \"Raphael\"),\n            is: g.win.Raphael\n        },\n        Paper = function () {\n            \n            \n            this.ca = this.customAttributes = {};\n        },\n        paperproto,\n        appendChild = \"appendChild\",\n        apply = \"apply\",\n        concat = \"concat\",\n        supportsTouch = \"createTouch\" in g.doc,\n        E = \"\",\n        S = \" \",\n        Str = String,\n        split = \"split\",\n        events = \"click dblclick mousedown mousemove mouseout mouseover mouseup touchstart touchmove touchend touchcancel\"[split](S),\n        touchMap = {\n            mousedown: \"touchstart\",\n            mousemove: \"touchmove\",\n            mouseup: \"touchend\"\n        },\n        lowerCase = Str.prototype.toLowerCase,\n        math = Math,\n        mmax = math.max,\n        mmin = math.min,\n        abs = math.abs,\n        pow = math.pow,\n        PI = math.PI,\n        nu = \"number\",\n        string = \"string\",\n        array = \"array\",\n        toString = \"toString\",\n        fillString = \"fill\",\n        objectToString = Object.prototype.toString,\n        paper = {},\n        push = \"push\",\n        ISURL = R._ISURL = /^url\\(['\"]?([^\\)]+?)['\"]?\\)$/i,\n        colourRegExp = /^\\s*((#[a-f\\d]{6})|(#[a-f\\d]{3})|rgba?\\(\\s*([\\d\\.]+%?\\s*,\\s*[\\d\\.]+%?\\s*,\\s*[\\d\\.]+%?(?:\\s*,\\s*[\\d\\.]+%?)?)\\s*\\)|hsba?\\(\\s*([\\d\\.]+(?:deg|\\xb0|%)?\\s*,\\s*[\\d\\.]+%?\\s*,\\s*[\\d\\.]+(?:%?\\s*,\\s*[\\d\\.]+)?)%?\\s*\\)|hsla?\\(\\s*([\\d\\.]+(?:deg|\\xb0|%)?\\s*,\\s*[\\d\\.]+%?\\s*,\\s*[\\d\\.]+(?:%?\\s*,\\s*[\\d\\.]+)?)%?\\s*\\))\\s*$/i,\n        isnan = {\"NaN\": 1, \"Infinity\": 1, \"-Infinity\": 1},\n        bezierrg = /^(?:cubic-)?bezier\\(([^,]+),([^,]+),([^,]+),([^\\)]+)\\)/,\n        round = math.round,\n        setAttribute = \"setAttribute\",\n        toFloat = parseFloat,\n        toInt = parseInt,\n        upperCase = Str.prototype.toUpperCase,\n        availableAttrs = R._availableAttrs = {\n            \"arrow-end\": \"none\",\n            \"arrow-start\": \"none\",\n            blur: 0,\n            \"clip-rect\": \"0 0 1e9 1e9\",\n            cursor: \"default\",\n            cx: 0,\n            cy: 0,\n            fill: \"#fff\",\n            \"fill-opacity\": 1,\n            font: '10px \"Arial\"',\n            \"font-family\": '\"Arial\"',\n            \"font-size\": \"10\",\n            \"font-style\": \"normal\",\n            \"font-weight\": 400,\n            gradient: 0,\n            height: 0,\n            href: \"http://raphaeljs.com/\",\n            \"letter-spacing\": 0,\n            opacity: 1,\n            path: \"M0,0\",\n            r: 0,\n            rx: 0,\n            ry: 0,\n            src: \"\",\n            stroke: \"#000\",\n            \"stroke-dasharray\": \"\",\n            \"stroke-linecap\": \"butt\",\n            \"stroke-linejoin\": \"butt\",\n            \"stroke-miterlimit\": 0,\n            \"stroke-opacity\": 1,\n            \"stroke-width\": 1,\n            target: \"_blank\",\n            \"text-anchor\": \"middle\",\n            title: \"Raphael\",\n            transform: \"\",\n            width: 0,\n            x: 0,\n            y: 0\n        },\n        availableAnimAttrs = R._availableAnimAttrs = {\n            blur: nu,\n            \"clip-rect\": \"csv\",\n            cx: nu,\n            cy: nu,\n            fill: \"colour\",\n            \"fill-opacity\": nu,\n            \"font-size\": nu,\n            height: nu,\n            opacity: nu,\n            path: \"path\",\n            r: nu,\n            rx: nu,\n            ry: nu,\n            stroke: \"colour\",\n            \"stroke-opacity\": nu,\n            \"stroke-width\": nu,\n            transform: \"transform\",\n            width: nu,\n            x: nu,\n            y: nu\n        },\n        whitespace = /[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]/g,\n        commaSpaces = /[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*,[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*/,\n        hsrg = {hs: 1, rg: 1},\n        p2s = /,?([achlmqrstvxz]),?/gi,\n        pathCommand = /([achlmrqstvz])[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029,]*((-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*,?[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*)+)/ig,\n        tCommand = /([rstm])[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029,]*((-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*,?[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*)+)/ig,\n        pathValues = /(-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?)[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*,?[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*/ig,\n        radial_gradient = R._radial_gradient = /^r(?:\\(([^,]+?)[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*,[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*([^\\)]+?)\\))?/,\n        eldata = {},\n        sortByKey = function (a, b) {\n            return a.key - b.key;\n        },\n        sortByNumber = function (a, b) {\n            return toFloat(a) - toFloat(b);\n        },\n        fun = function () {},\n        pipe = function (x) {\n            return x;\n        },\n        rectPath = R._rectPath = function (x, y, w, h, r) {\n            if (r) {\n                return [[\"M\", x + r, y], [\"l\", w - r * 2, 0], [\"a\", r, r, 0, 0, 1, r, r], [\"l\", 0, h - r * 2], [\"a\", r, r, 0, 0, 1, -r, r], [\"l\", r * 2 - w, 0], [\"a\", r, r, 0, 0, 1, -r, -r], [\"l\", 0, r * 2 - h], [\"a\", r, r, 0, 0, 1, r, -r], [\"z\"]];\n            }\n            return [[\"M\", x, y], [\"l\", w, 0], [\"l\", 0, h], [\"l\", -w, 0], [\"z\"]];\n        },\n        ellipsePath = function (x, y, rx, ry) {\n            if (ry == null) {\n                ry = rx;\n            }\n            return [[\"M\", x, y], [\"m\", 0, -ry], [\"a\", rx, ry, 0, 1, 1, 0, 2 * ry], [\"a\", rx, ry, 0, 1, 1, 0, -2 * ry], [\"z\"]];\n        },\n        getPath = R._getPath = {\n            path: function (el) {\n                return el.attr(\"path\");\n            },\n            circle: function (el) {\n                var a = el.attrs;\n                return ellipsePath(a.cx, a.cy, a.r);\n            },\n            ellipse: function (el) {\n                var a = el.attrs;\n                return ellipsePath(a.cx, a.cy, a.rx, a.ry);\n            },\n            rect: function (el) {\n                var a = el.attrs;\n                return rectPath(a.x, a.y, a.width, a.height, a.r);\n            },\n            image: function (el) {\n                var a = el.attrs;\n                return rectPath(a.x, a.y, a.width, a.height);\n            },\n            text: function (el) {\n                var bbox = el._getBBox();\n                return rectPath(bbox.x, bbox.y, bbox.width, bbox.height);\n            }\n        },\n        \n        mapPath = R.mapPath = function (path, matrix) {\n            if (!matrix) {\n                return path;\n            }\n            var x, y, i, j, ii, jj, pathi;\n            path = path2curve(path);\n            for (i = 0, ii = path.length; i < ii; i++) {\n                pathi = path[i];\n                for (j = 1, jj = pathi.length; j < jj; j += 2) {\n                    x = matrix.x(pathi[j], pathi[j + 1]);\n                    y = matrix.y(pathi[j], pathi[j + 1]);\n                    pathi[j] = x;\n                    pathi[j + 1] = y;\n                }\n            }\n            return path;\n        };\n\n    R._g = g;\n    \n    R.type = (g.win.SVGAngle || g.doc.implementation.hasFeature(\"http://www.w3.org/TR/SVG11/feature#BasicStructure\", \"1.1\") ? \"SVG\" : \"VML\");\n    if (R.type == \"VML\") {\n        var d = g.doc.createElement(\"div\"),\n            b;\n        d.innerHTML = '<v:shape adj=\"1\"/>';\n        b = d.firstChild;\n        b.style.behavior = \"url(#default#VML)\";\n        if (!(b && typeof b.adj == \"object\")) {\n            return (R.type = E);\n        }\n        d = null;\n    }\n    \n    \n    R.svg = !(R.vml = R.type == \"VML\");\n    R._Paper = Paper;\n    \n    R.fn = paperproto = Paper.prototype = R.prototype;\n    R._id = 0;\n    R._oid = 0;\n    \n    R.is = function (o, type) {\n        type = lowerCase.call(type);\n        if (type == \"finite\") {\n            return !isnan[has](+o);\n        }\n        if (type == \"array\") {\n            return o instanceof Array;\n        }\n        return  (type == \"null\" && o === null) ||\n                (type == typeof o && o !== null) ||\n                (type == \"object\" && o === Object(o)) ||\n                (type == \"array\" && Array.isArray && Array.isArray(o)) ||\n                objectToString.call(o).slice(8, -1).toLowerCase() == type;\n    };\n\n    function clone(obj) {\n        if (Object(obj) !== obj) {\n            return obj;\n        }\n        var res = new obj.constructor;\n        for (var key in obj) if (obj[has](key)) {\n            res[key] = clone(obj[key]);\n        }\n        return res;\n    }\n\n    \n    R.angle = function (x1, y1, x2, y2, x3, y3) {\n        if (x3 == null) {\n            var x = x1 - x2,\n                y = y1 - y2;\n            if (!x && !y) {\n                return 0;\n            }\n            return (180 + math.atan2(-y, -x) * 180 / PI + 360) % 360;\n        } else {\n            return R.angle(x1, y1, x3, y3) - R.angle(x2, y2, x3, y3);\n        }\n    };\n    \n    R.rad = function (deg) {\n        return deg % 360 * PI / 180;\n    };\n    \n    R.deg = function (rad) {\n        return rad * 180 / PI % 360;\n    };\n    \n    R.snapTo = function (values, value, tolerance) {\n        tolerance = R.is(tolerance, \"finite\") ? tolerance : 10;\n        if (R.is(values, array)) {\n            var i = values.length;\n            while (i--) if (abs(values[i] - value) <= tolerance) {\n                return values[i];\n            }\n        } else {\n            values = +values;\n            var rem = value % values;\n            if (rem < tolerance) {\n                return value - rem;\n            }\n            if (rem > values - tolerance) {\n                return value - rem + values;\n            }\n        }\n        return value;\n    };\n    \n    \n    var createUUID = R.createUUID = (function (uuidRegEx, uuidReplacer) {\n        return function () {\n            return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(uuidRegEx, uuidReplacer).toUpperCase();\n        };\n    })(/[xy]/g, function (c) {\n        var r = math.random() * 16 | 0,\n            v = c == \"x\" ? r : (r & 3 | 8);\n        return v.toString(16);\n    });\n\n    \n    R.setWindow = function (newwin) {\n        eve(\"raphael.setWindow\", R, g.win, newwin);\n        g.win = newwin;\n        g.doc = g.win.document;\n        if (R._engine.initWin) {\n            R._engine.initWin(g.win);\n        }\n    };\n    var toHex = function (color) {\n        if (R.vml) {\n            // http://dean.edwards.name/weblog/2009/10/convert-any-colour-value-to-hex-in-msie/\n            var trim = /^\\s+|\\s+$/g;\n            var bod;\n            try {\n                var docum = new ActiveXObject(\"htmlfile\");\n                docum.write(\"<body>\");\n                docum.close();\n                bod = docum.body;\n            } catch(e) {\n                bod = createPopup().document.body;\n            }\n            var range = bod.createTextRange();\n            toHex = cacher(function (color) {\n                try {\n                    bod.style.color = Str(color).replace(trim, E);\n                    var value = range.queryCommandValue(\"ForeColor\");\n                    value = ((value & 255) << 16) | (value & 65280) | ((value & 16711680) >>> 16);\n                    return \"#\" + (\"000000\" + value.toString(16)).slice(-6);\n                } catch(e) {\n                    return \"none\";\n                }\n            });\n        } else {\n            var i = g.doc.createElement(\"i\");\n            i.title = \"Rapha\\xebl Colour Picker\";\n            i.style.display = \"none\";\n            g.doc.body.appendChild(i);\n            toHex = cacher(function (color) {\n                i.style.color = color;\n                return g.doc.defaultView.getComputedStyle(i, E).getPropertyValue(\"color\");\n            });\n        }\n        return toHex(color);\n    },\n    hsbtoString = function () {\n        return \"hsb(\" + [this.h, this.s, this.b] + \")\";\n    },\n    hsltoString = function () {\n        return \"hsl(\" + [this.h, this.s, this.l] + \")\";\n    },\n    rgbtoString = function () {\n        return this.hex;\n    },\n    prepareRGB = function (r, g, b) {\n        if (g == null && R.is(r, \"object\") && \"r\" in r && \"g\" in r && \"b\" in r) {\n            b = r.b;\n            g = r.g;\n            r = r.r;\n        }\n        if (g == null && R.is(r, string)) {\n            var clr = R.getRGB(r);\n            r = clr.r;\n            g = clr.g;\n            b = clr.b;\n        }\n        if (r > 1 || g > 1 || b > 1) {\n            r /= 255;\n            g /= 255;\n            b /= 255;\n        }\n        \n        return [r, g, b];\n    },\n    packageRGB = function (r, g, b, o) {\n        r *= 255;\n        g *= 255;\n        b *= 255;\n        var rgb = {\n            r: r,\n            g: g,\n            b: b,\n            hex: R.rgb(r, g, b),\n            toString: rgbtoString\n        };\n        R.is(o, \"finite\") && (rgb.opacity = o);\n        return rgb;\n    };\n    \n    \n    R.color = function (clr) {\n        var rgb;\n        if (R.is(clr, \"object\") && \"h\" in clr && \"s\" in clr && \"b\" in clr) {\n            rgb = R.hsb2rgb(clr);\n            clr.r = rgb.r;\n            clr.g = rgb.g;\n            clr.b = rgb.b;\n            clr.hex = rgb.hex;\n        } else if (R.is(clr, \"object\") && \"h\" in clr && \"s\" in clr && \"l\" in clr) {\n            rgb = R.hsl2rgb(clr);\n            clr.r = rgb.r;\n            clr.g = rgb.g;\n            clr.b = rgb.b;\n            clr.hex = rgb.hex;\n        } else {\n            if (R.is(clr, \"string\")) {\n                clr = R.getRGB(clr);\n            }\n            if (R.is(clr, \"object\") && \"r\" in clr && \"g\" in clr && \"b\" in clr) {\n                rgb = R.rgb2hsl(clr);\n                clr.h = rgb.h;\n                clr.s = rgb.s;\n                clr.l = rgb.l;\n                rgb = R.rgb2hsb(clr);\n                clr.v = rgb.b;\n            } else {\n                clr = {hex: \"none\"};\n                clr.r = clr.g = clr.b = clr.h = clr.s = clr.v = clr.l = -1;\n            }\n        }\n        clr.toString = rgbtoString;\n        return clr;\n    };\n    \n    R.hsb2rgb = function (h, s, v, o) {\n        if (this.is(h, \"object\") && \"h\" in h && \"s\" in h && \"b\" in h) {\n            v = h.b;\n            s = h.s;\n            h = h.h;\n            o = h.o;\n        }\n        h *= 360;\n        var R, G, B, X, C;\n        h = (h % 360) / 60;\n        C = v * s;\n        X = C * (1 - abs(h % 2 - 1));\n        R = G = B = v - C;\n\n        h = ~~h;\n        R += [C, X, 0, 0, X, C][h];\n        G += [X, C, C, X, 0, 0][h];\n        B += [0, 0, X, C, C, X][h];\n        return packageRGB(R, G, B, o);\n    };\n    \n    R.hsl2rgb = function (h, s, l, o) {\n        if (this.is(h, \"object\") && \"h\" in h && \"s\" in h && \"l\" in h) {\n            l = h.l;\n            s = h.s;\n            h = h.h;\n        }\n        if (h > 1 || s > 1 || l > 1) {\n            h /= 360;\n            s /= 100;\n            l /= 100;\n        }\n        h *= 360;\n        var R, G, B, X, C;\n        h = (h % 360) / 60;\n        C = 2 * s * (l < .5 ? l : 1 - l);\n        X = C * (1 - abs(h % 2 - 1));\n        R = G = B = l - C / 2;\n\n        h = ~~h;\n        R += [C, X, 0, 0, X, C][h];\n        G += [X, C, C, X, 0, 0][h];\n        B += [0, 0, X, C, C, X][h];\n        return packageRGB(R, G, B, o);\n    };\n    \n    R.rgb2hsb = function (r, g, b) {\n        b = prepareRGB(r, g, b);\n        r = b[0];\n        g = b[1];\n        b = b[2];\n\n        var H, S, V, C;\n        V = mmax(r, g, b);\n        C = V - mmin(r, g, b);\n        H = (C == 0 ? null :\n             V == r ? (g - b) / C :\n             V == g ? (b - r) / C + 2 :\n                      (r - g) / C + 4\n            );\n        H = ((H + 360) % 6) * 60 / 360;\n        S = C == 0 ? 0 : C / V;\n        return {h: H, s: S, b: V, toString: hsbtoString};\n    };\n    \n    R.rgb2hsl = function (r, g, b) {\n        b = prepareRGB(r, g, b);\n        r = b[0];\n        g = b[1];\n        b = b[2];\n\n        var H, S, L, M, m, C;\n        M = mmax(r, g, b);\n        m = mmin(r, g, b);\n        C = M - m;\n        H = (C == 0 ? null :\n             M == r ? (g - b) / C :\n             M == g ? (b - r) / C + 2 :\n                      (r - g) / C + 4);\n        H = ((H + 360) % 6) * 60 / 360;\n        L = (M + m) / 2;\n        S = (C == 0 ? 0 :\n             L < .5 ? C / (2 * L) :\n                      C / (2 - 2 * L));\n        return {h: H, s: S, l: L, toString: hsltoString};\n    };\n    R._path2string = function () {\n        return this.join(\",\").replace(p2s, \"$1\");\n    };\n    function repush(array, item) {\n        for (var i = 0, ii = array.length; i < ii; i++) if (array[i] === item) {\n            return array.push(array.splice(i, 1)[0]);\n        }\n    }\n    function cacher(f, scope, postprocessor) {\n        function newf() {\n            var arg = Array.prototype.slice.call(arguments, 0),\n                args = arg.join(\"\\u2400\"),\n                cache = newf.cache = newf.cache || {},\n                count = newf.count = newf.count || [];\n            if (cache[has](args)) {\n                repush(count, args);\n                return postprocessor ? postprocessor(cache[args]) : cache[args];\n            }\n            count.length >= 1e3 && delete cache[count.shift()];\n            count.push(args);\n            cache[args] = f[apply](scope, arg);\n            return postprocessor ? postprocessor(cache[args]) : cache[args];\n        }\n        return newf;\n    }\n\n    var preload = R._preload = function (src, f) {\n        var img = g.doc.createElement(\"img\");\n        img.style.cssText = \"position:absolute;left:-9999em;top:-9999em\";\n        img.onload = function () {\n            f.call(this);\n            this.onload = null;\n            g.doc.body.removeChild(this);\n        };\n        img.onerror = function () {\n            g.doc.body.removeChild(this);\n        };\n        g.doc.body.appendChild(img);\n        img.src = src;\n    };\n    \n    function clrToString() {\n        return this.hex;\n    }\n\n    \n    R.getRGB = cacher(function (colour) {\n        if (!colour || !!((colour = Str(colour)).indexOf(\"-\") + 1)) {\n            return {r: -1, g: -1, b: -1, hex: \"none\", error: 1, toString: clrToString};\n        }\n        if (colour == \"none\") {\n            return {r: -1, g: -1, b: -1, hex: \"none\", toString: clrToString};\n        }\n        !(hsrg[has](colour.toLowerCase().substring(0, 2)) || colour.charAt() == \"#\") && (colour = toHex(colour));\n        var res,\n            red,\n            green,\n            blue,\n            opacity,\n            t,\n            values,\n            rgb = colour.match(colourRegExp);\n        if (rgb) {\n            if (rgb[2]) {\n                blue = toInt(rgb[2].substring(5), 16);\n                green = toInt(rgb[2].substring(3, 5), 16);\n                red = toInt(rgb[2].substring(1, 3), 16);\n            }\n            if (rgb[3]) {\n                blue = toInt((t = rgb[3].charAt(3)) + t, 16);\n                green = toInt((t = rgb[3].charAt(2)) + t, 16);\n                red = toInt((t = rgb[3].charAt(1)) + t, 16);\n            }\n            if (rgb[4]) {\n                values = rgb[4][split](commaSpaces);\n                red = toFloat(values[0]);\n                values[0].slice(-1) == \"%\" && (red *= 2.55);\n                green = toFloat(values[1]);\n                values[1].slice(-1) == \"%\" && (green *= 2.55);\n                blue = toFloat(values[2]);\n                values[2].slice(-1) == \"%\" && (blue *= 2.55);\n                rgb[1].toLowerCase().slice(0, 4) == \"rgba\" && (opacity = toFloat(values[3]));\n                values[3] && values[3].slice(-1) == \"%\" && (opacity /= 100);\n            }\n            if (rgb[5]) {\n                values = rgb[5][split](commaSpaces);\n                red = toFloat(values[0]);\n                values[0].slice(-1) == \"%\" && (red *= 2.55);\n                green = toFloat(values[1]);\n                values[1].slice(-1) == \"%\" && (green *= 2.55);\n                blue = toFloat(values[2]);\n                values[2].slice(-1) == \"%\" && (blue *= 2.55);\n                (values[0].slice(-3) == \"deg\" || values[0].slice(-1) == \"\\xb0\") && (red /= 360);\n                rgb[1].toLowerCase().slice(0, 4) == \"hsba\" && (opacity = toFloat(values[3]));\n                values[3] && values[3].slice(-1) == \"%\" && (opacity /= 100);\n                return R.hsb2rgb(red, green, blue, opacity);\n            }\n            if (rgb[6]) {\n                values = rgb[6][split](commaSpaces);\n                red = toFloat(values[0]);\n                values[0].slice(-1) == \"%\" && (red *= 2.55);\n                green = toFloat(values[1]);\n                values[1].slice(-1) == \"%\" && (green *= 2.55);\n                blue = toFloat(values[2]);\n                values[2].slice(-1) == \"%\" && (blue *= 2.55);\n                (values[0].slice(-3) == \"deg\" || values[0].slice(-1) == \"\\xb0\") && (red /= 360);\n                rgb[1].toLowerCase().slice(0, 4) == \"hsla\" && (opacity = toFloat(values[3]));\n                values[3] && values[3].slice(-1) == \"%\" && (opacity /= 100);\n                return R.hsl2rgb(red, green, blue, opacity);\n            }\n            rgb = {r: red, g: green, b: blue, toString: clrToString};\n            rgb.hex = \"#\" + (16777216 | blue | (green << 8) | (red << 16)).toString(16).slice(1);\n            R.is(opacity, \"finite\") && (rgb.opacity = opacity);\n            return rgb;\n        }\n        return {r: -1, g: -1, b: -1, hex: \"none\", error: 1, toString: clrToString};\n    }, R);\n    \n    R.hsb = cacher(function (h, s, b) {\n        return R.hsb2rgb(h, s, b).hex;\n    });\n    \n    R.hsl = cacher(function (h, s, l) {\n        return R.hsl2rgb(h, s, l).hex;\n    });\n    \n    R.rgb = cacher(function (r, g, b) {\n        return \"#\" + (16777216 | b | (g << 8) | (r << 16)).toString(16).slice(1);\n    });\n    \n    R.getColor = function (value) {\n        var start = this.getColor.start = this.getColor.start || {h: 0, s: 1, b: value || .75},\n            rgb = this.hsb2rgb(start.h, start.s, start.b);\n        start.h += .075;\n        if (start.h > 1) {\n            start.h = 0;\n            start.s -= .2;\n            start.s <= 0 && (this.getColor.start = {h: 0, s: 1, b: start.b});\n        }\n        return rgb.hex;\n    };\n    \n    R.getColor.reset = function () {\n        delete this.start;\n    };\n\n    // http://schepers.cc/getting-to-the-point\n    function catmullRom2bezier(crp, z) {\n        var d = [];\n        for (var i = 0, iLen = crp.length; iLen - 2 * !z > i; i += 2) {\n            var p = [\n                        {x: +crp[i - 2], y: +crp[i - 1]},\n                        {x: +crp[i],     y: +crp[i + 1]},\n                        {x: +crp[i + 2], y: +crp[i + 3]},\n                        {x: +crp[i + 4], y: +crp[i + 5]}\n                    ];\n            if (z) {\n                if (!i) {\n                    p[0] = {x: +crp[iLen - 2], y: +crp[iLen - 1]};\n                } else if (iLen - 4 == i) {\n                    p[3] = {x: +crp[0], y: +crp[1]};\n                } else if (iLen - 2 == i) {\n                    p[2] = {x: +crp[0], y: +crp[1]};\n                    p[3] = {x: +crp[2], y: +crp[3]};\n                }\n            } else {\n                if (iLen - 4 == i) {\n                    p[3] = p[2];\n                } else if (!i) {\n                    p[0] = {x: +crp[i], y: +crp[i + 1]};\n                }\n            }\n            d.push([\"C\",\n                  (-p[0].x + 6 * p[1].x + p[2].x) / 6,\n                  (-p[0].y + 6 * p[1].y + p[2].y) / 6,\n                  (p[1].x + 6 * p[2].x - p[3].x) / 6,\n                  (p[1].y + 6*p[2].y - p[3].y) / 6,\n                  p[2].x,\n                  p[2].y\n            ]);\n        }\n\n        return d;\n    }\n    \n    R.parsePathString = function (pathString) {\n        if (!pathString) {\n            return null;\n        }\n        var pth = paths(pathString);\n        if (pth.arr) {\n            return pathClone(pth.arr);\n        }\n        \n        var paramCounts = {a: 7, c: 6, h: 1, l: 2, m: 2, r: 4, q: 4, s: 4, t: 2, v: 1, z: 0},\n            data = [];\n        if (R.is(pathString, array) && R.is(pathString[0], array)) { // rough assumption\n            data = pathClone(pathString);\n        }\n        if (!data.length) {\n            Str(pathString).replace(pathCommand, function (a, b, c) {\n                var params = [],\n                    name = b.toLowerCase();\n                c.replace(pathValues, function (a, b) {\n                    b && params.push(+b);\n                });\n                if (name == \"m\" && params.length > 2) {\n                    data.push([b][concat](params.splice(0, 2)));\n                    name = \"l\";\n                    b = b == \"m\" ? \"l\" : \"L\";\n                }\n                if (name == \"r\") {\n                    data.push([b][concat](params));\n                } else while (params.length >= paramCounts[name]) {\n                    data.push([b][concat](params.splice(0, paramCounts[name])));\n                    if (!paramCounts[name]) {\n                        break;\n                    }\n                }\n            });\n        }\n        data.toString = R._path2string;\n        pth.arr = pathClone(data);\n        return data;\n    };\n    \n    R.parseTransformString = cacher(function (TString) {\n        if (!TString) {\n            return null;\n        }\n        var paramCounts = {r: 3, s: 4, t: 2, m: 6},\n            data = [];\n        if (R.is(TString, array) && R.is(TString[0], array)) { // rough assumption\n            data = pathClone(TString);\n        }\n        if (!data.length) {\n            Str(TString).replace(tCommand, function (a, b, c) {\n                var params = [],\n                    name = lowerCase.call(b);\n                c.replace(pathValues, function (a, b) {\n                    b && params.push(+b);\n                });\n                data.push([b][concat](params));\n            });\n        }\n        data.toString = R._path2string;\n        return data;\n    });\n    // PATHS\n    var paths = function (ps) {\n        var p = paths.ps = paths.ps || {};\n        if (p[ps]) {\n            p[ps].sleep = 100;\n        } else {\n            p[ps] = {\n                sleep: 100\n            };\n        }\n        setTimeout(function () {\n            for (var key in p) if (p[has](key) && key != ps) {\n                p[key].sleep--;\n                !p[key].sleep && delete p[key];\n            }\n        });\n        return p[ps];\n    };\n    \n    R.findDotsAtSegment = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) {\n        var t1 = 1 - t,\n            t13 = pow(t1, 3),\n            t12 = pow(t1, 2),\n            t2 = t * t,\n            t3 = t2 * t,\n            x = t13 * p1x + t12 * 3 * t * c1x + t1 * 3 * t * t * c2x + t3 * p2x,\n            y = t13 * p1y + t12 * 3 * t * c1y + t1 * 3 * t * t * c2y + t3 * p2y,\n            mx = p1x + 2 * t * (c1x - p1x) + t2 * (c2x - 2 * c1x + p1x),\n            my = p1y + 2 * t * (c1y - p1y) + t2 * (c2y - 2 * c1y + p1y),\n            nx = c1x + 2 * t * (c2x - c1x) + t2 * (p2x - 2 * c2x + c1x),\n            ny = c1y + 2 * t * (c2y - c1y) + t2 * (p2y - 2 * c2y + c1y),\n            ax = t1 * p1x + t * c1x,\n            ay = t1 * p1y + t * c1y,\n            cx = t1 * c2x + t * p2x,\n            cy = t1 * c2y + t * p2y,\n            alpha = (90 - math.atan2(mx - nx, my - ny) * 180 / PI);\n        (mx > nx || my < ny) && (alpha += 180);\n        return {\n            x: x,\n            y: y,\n            m: {x: mx, y: my},\n            n: {x: nx, y: ny},\n            start: {x: ax, y: ay},\n            end: {x: cx, y: cy},\n            alpha: alpha\n        };\n    };\n    \n    R.bezierBBox = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) {\n        if (!R.is(p1x, \"array\")) {\n            p1x = [p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y];\n        }\n        var bbox = curveDim.apply(null, p1x);\n        return {\n            x: bbox.min.x,\n            y: bbox.min.y,\n            x2: bbox.max.x,\n            y2: bbox.max.y,\n            width: bbox.max.x - bbox.min.x,\n            height: bbox.max.y - bbox.min.y\n        };\n    };\n    \n    R.isPointInsideBBox = function (bbox, x, y) {\n        return x >= bbox.x && x <= bbox.x2 && y >= bbox.y && y <= bbox.y2;\n    };\n    \n    R.isBBoxIntersect = function (bbox1, bbox2) {\n        var i = R.isPointInsideBBox;\n        return i(bbox2, bbox1.x, bbox1.y)\n            || i(bbox2, bbox1.x2, bbox1.y)\n            || i(bbox2, bbox1.x, bbox1.y2)\n            || i(bbox2, bbox1.x2, bbox1.y2)\n            || i(bbox1, bbox2.x, bbox2.y)\n            || i(bbox1, bbox2.x2, bbox2.y)\n            || i(bbox1, bbox2.x, bbox2.y2)\n            || i(bbox1, bbox2.x2, bbox2.y2)\n            || (bbox1.x < bbox2.x2 && bbox1.x > bbox2.x || bbox2.x < bbox1.x2 && bbox2.x > bbox1.x)\n            && (bbox1.y < bbox2.y2 && bbox1.y > bbox2.y || bbox2.y < bbox1.y2 && bbox2.y > bbox1.y);\n    };\n    function base3(t, p1, p2, p3, p4) {\n        var t1 = -3 * p1 + 9 * p2 - 9 * p3 + 3 * p4,\n            t2 = t * t1 + 6 * p1 - 12 * p2 + 6 * p3;\n        return t * t2 - 3 * p1 + 3 * p2;\n    }\n    function bezlen(x1, y1, x2, y2, x3, y3, x4, y4, z) {\n        if (z == null) {\n            z = 1;\n        }\n        z = z > 1 ? 1 : z < 0 ? 0 : z;\n        var z2 = z / 2,\n            n = 12,\n            Tvalues = [-0.1252,0.1252,-0.3678,0.3678,-0.5873,0.5873,-0.7699,0.7699,-0.9041,0.9041,-0.9816,0.9816],\n            Cvalues = [0.2491,0.2491,0.2335,0.2335,0.2032,0.2032,0.1601,0.1601,0.1069,0.1069,0.0472,0.0472],\n            sum = 0;\n        for (var i = 0; i < n; i++) {\n            var ct = z2 * Tvalues[i] + z2,\n                xbase = base3(ct, x1, x2, x3, x4),\n                ybase = base3(ct, y1, y2, y3, y4),\n                comb = xbase * xbase + ybase * ybase;\n            sum += Cvalues[i] * math.sqrt(comb);\n        }\n        return z2 * sum;\n    }\n    function getTatLen(x1, y1, x2, y2, x3, y3, x4, y4, ll) {\n        if (ll < 0 || bezlen(x1, y1, x2, y2, x3, y3, x4, y4) < ll) {\n            return;\n        }\n        var t = 1,\n            step = t / 2,\n            t2 = t - step,\n            l,\n            e = .01;\n        l = bezlen(x1, y1, x2, y2, x3, y3, x4, y4, t2);\n        while (abs(l - ll) > e) {\n            step /= 2;\n            t2 += (l < ll ? 1 : -1) * step;\n            l = bezlen(x1, y1, x2, y2, x3, y3, x4, y4, t2);\n        }\n        return t2;\n    }\n    function intersect(x1, y1, x2, y2, x3, y3, x4, y4) {\n        if (\n            mmax(x1, x2) < mmin(x3, x4) ||\n            mmin(x1, x2) > mmax(x3, x4) ||\n            mmax(y1, y2) < mmin(y3, y4) ||\n            mmin(y1, y2) > mmax(y3, y4)\n        ) {\n            return;\n        }\n        var nx = (x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4),\n            ny = (x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4),\n            denominator = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);\n\n        if (!denominator) {\n            return;\n        }\n        var px = nx / denominator,\n            py = ny / denominator,\n            px2 = +px.toFixed(2),\n            py2 = +py.toFixed(2);\n        if (\n            px2 < +mmin(x1, x2).toFixed(2) ||\n            px2 > +mmax(x1, x2).toFixed(2) ||\n            px2 < +mmin(x3, x4).toFixed(2) ||\n            px2 > +mmax(x3, x4).toFixed(2) ||\n            py2 < +mmin(y1, y2).toFixed(2) ||\n            py2 > +mmax(y1, y2).toFixed(2) ||\n            py2 < +mmin(y3, y4).toFixed(2) ||\n            py2 > +mmax(y3, y4).toFixed(2)\n        ) {\n            return;\n        }\n        return {x: px, y: py};\n    }\n    function inter(bez1, bez2) {\n        return interHelper(bez1, bez2);\n    }\n    function interCount(bez1, bez2) {\n        return interHelper(bez1, bez2, 1);\n    }\n    function interHelper(bez1, bez2, justCount) {\n        var bbox1 = R.bezierBBox(bez1),\n            bbox2 = R.bezierBBox(bez2);\n        if (!R.isBBoxIntersect(bbox1, bbox2)) {\n            return justCount ? 0 : [];\n        }\n        var l1 = bezlen.apply(0, bez1),\n            l2 = bezlen.apply(0, bez2),\n            n1 = ~~(l1 / 5),\n            n2 = ~~(l2 / 5),\n            dots1 = [],\n            dots2 = [],\n            xy = {},\n            res = justCount ? 0 : [];\n        for (var i = 0; i < n1 + 1; i++) {\n            var p = R.findDotsAtSegment.apply(R, bez1.concat(i / n1));\n            dots1.push({x: p.x, y: p.y, t: i / n1});\n        }\n        for (i = 0; i < n2 + 1; i++) {\n            p = R.findDotsAtSegment.apply(R, bez2.concat(i / n2));\n            dots2.push({x: p.x, y: p.y, t: i / n2});\n        }\n        for (i = 0; i < n1; i++) {\n            for (var j = 0; j < n2; j++) {\n                var di = dots1[i],\n                    di1 = dots1[i + 1],\n                    dj = dots2[j],\n                    dj1 = dots2[j + 1],\n                    ci = abs(di1.x - di.x) < .001 ? \"y\" : \"x\",\n                    cj = abs(dj1.x - dj.x) < .001 ? \"y\" : \"x\",\n                    is = intersect(di.x, di.y, di1.x, di1.y, dj.x, dj.y, dj1.x, dj1.y);\n                if (is) {\n                    if (xy[is.x.toFixed(4)] == is.y.toFixed(4)) {\n                        continue;\n                    }\n                    xy[is.x.toFixed(4)] = is.y.toFixed(4);\n                    var t1 = di.t + abs((is[ci] - di[ci]) / (di1[ci] - di[ci])) * (di1.t - di.t),\n                        t2 = dj.t + abs((is[cj] - dj[cj]) / (dj1[cj] - dj[cj])) * (dj1.t - dj.t);\n                    if (t1 >= 0 && t1 <= 1 && t2 >= 0 && t2 <= 1) {\n                        if (justCount) {\n                            res++;\n                        } else {\n                            res.push({\n                                x: is.x,\n                                y: is.y,\n                                t1: t1,\n                                t2: t2\n                            });\n                        }\n                    }\n                }\n            }\n        }\n        return res;\n    }\n    \n    R.pathIntersection = function (path1, path2) {\n        return interPathHelper(path1, path2);\n    };\n    R.pathIntersectionNumber = function (path1, path2) {\n        return interPathHelper(path1, path2, 1);\n    };\n    function interPathHelper(path1, path2, justCount) {\n        path1 = R._path2curve(path1);\n        path2 = R._path2curve(path2);\n        var x1, y1, x2, y2, x1m, y1m, x2m, y2m, bez1, bez2,\n            res = justCount ? 0 : [];\n        for (var i = 0, ii = path1.length; i < ii; i++) {\n            var pi = path1[i];\n            if (pi[0] == \"M\") {\n                x1 = x1m = pi[1];\n                y1 = y1m = pi[2];\n            } else {\n                if (pi[0] == \"C\") {\n                    bez1 = [x1, y1].concat(pi.slice(1));\n                    x1 = bez1[6];\n                    y1 = bez1[7];\n                } else {\n                    bez1 = [x1, y1, x1, y1, x1m, y1m, x1m, y1m];\n                    x1 = x1m;\n                    y1 = y1m;\n                }\n                for (var j = 0, jj = path2.length; j < jj; j++) {\n                    var pj = path2[j];\n                    if (pj[0] == \"M\") {\n                        x2 = x2m = pj[1];\n                        y2 = y2m = pj[2];\n                    } else {\n                        if (pj[0] == \"C\") {\n                            bez2 = [x2, y2].concat(pj.slice(1));\n                            x2 = bez2[6];\n                            y2 = bez2[7];\n                        } else {\n                            bez2 = [x2, y2, x2, y2, x2m, y2m, x2m, y2m];\n                            x2 = x2m;\n                            y2 = y2m;\n                        }\n                        var intr = interHelper(bez1, bez2, justCount);\n                        if (justCount) {\n                            res += intr;\n                        } else {\n                            for (var k = 0, kk = intr.length; k < kk; k++) {\n                                intr[k].segment1 = i;\n                                intr[k].segment2 = j;\n                                intr[k].bez1 = bez1;\n                                intr[k].bez2 = bez2;\n                            }\n                            res = res.concat(intr);\n                        }\n                    }\n                }\n            }\n        }\n        return res;\n    }\n    \n    R.isPointInsidePath = function (path, x, y) {\n        var bbox = R.pathBBox(path);\n        return R.isPointInsideBBox(bbox, x, y) &&\n               interPathHelper(path, [[\"M\", x, y], [\"H\", bbox.x2 + 10]], 1) % 2 == 1;\n    };\n    R._removedFactory = function (methodname) {\n        return function () {\n            eve(\"raphael.log\", null, \"Rapha\\xebl: you are calling to method \\u201c\" + methodname + \"\\u201d of removed object\", methodname);\n        };\n    };\n    \n    var pathDimensions = R.pathBBox = function (path) {\n        var pth = paths(path);\n        if (pth.bbox) {\n            return pth.bbox;\n        }\n        if (!path) {\n            return {x: 0, y: 0, width: 0, height: 0, x2: 0, y2: 0};\n        }\n        path = path2curve(path);\n        var x = 0, \n            y = 0,\n            X = [],\n            Y = [],\n            p;\n        for (var i = 0, ii = path.length; i < ii; i++) {\n            p = path[i];\n            if (p[0] == \"M\") {\n                x = p[1];\n                y = p[2];\n                X.push(x);\n                Y.push(y);\n            } else {\n                var dim = curveDim(x, y, p[1], p[2], p[3], p[4], p[5], p[6]);\n                X = X[concat](dim.min.x, dim.max.x);\n                Y = Y[concat](dim.min.y, dim.max.y);\n                x = p[5];\n                y = p[6];\n            }\n        }\n        var xmin = mmin[apply](0, X),\n            ymin = mmin[apply](0, Y),\n            xmax = mmax[apply](0, X),\n            ymax = mmax[apply](0, Y),\n            bb = {\n                x: xmin,\n                y: ymin,\n                x2: xmax,\n                y2: ymax,\n                width: xmax - xmin,\n                height: ymax - ymin\n            };\n        pth.bbox = clone(bb);\n        return bb;\n    },\n        pathClone = function (pathArray) {\n            var res = clone(pathArray);\n            res.toString = R._path2string;\n            return res;\n        },\n        pathToRelative = R._pathToRelative = function (pathArray) {\n            var pth = paths(pathArray);\n            if (pth.rel) {\n                return pathClone(pth.rel);\n            }\n            if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption\n                pathArray = R.parsePathString(pathArray);\n            }\n            var res = [],\n                x = 0,\n                y = 0,\n                mx = 0,\n                my = 0,\n                start = 0;\n            if (pathArray[0][0] == \"M\") {\n                x = pathArray[0][1];\n                y = pathArray[0][2];\n                mx = x;\n                my = y;\n                start++;\n                res.push([\"M\", x, y]);\n            }\n            for (var i = start, ii = pathArray.length; i < ii; i++) {\n                var r = res[i] = [],\n                    pa = pathArray[i];\n                if (pa[0] != lowerCase.call(pa[0])) {\n                    r[0] = lowerCase.call(pa[0]);\n                    switch (r[0]) {\n                        case \"a\":\n                            r[1] = pa[1];\n                            r[2] = pa[2];\n                            r[3] = pa[3];\n                            r[4] = pa[4];\n                            r[5] = pa[5];\n                            r[6] = +(pa[6] - x).toFixed(3);\n                            r[7] = +(pa[7] - y).toFixed(3);\n                            break;\n                        case \"v\":\n                            r[1] = +(pa[1] - y).toFixed(3);\n                            break;\n                        case \"m\":\n                            mx = pa[1];\n                            my = pa[2];\n                        default:\n                            for (var j = 1, jj = pa.length; j < jj; j++) {\n                                r[j] = +(pa[j] - ((j % 2) ? x : y)).toFixed(3);\n                            }\n                    }\n                } else {\n                    r = res[i] = [];\n                    if (pa[0] == \"m\") {\n                        mx = pa[1] + x;\n                        my = pa[2] + y;\n                    }\n                    for (var k = 0, kk = pa.length; k < kk; k++) {\n                        res[i][k] = pa[k];\n                    }\n                }\n                var len = res[i].length;\n                switch (res[i][0]) {\n                    case \"z\":\n                        x = mx;\n                        y = my;\n                        break;\n                    case \"h\":\n                        x += +res[i][len - 1];\n                        break;\n                    case \"v\":\n                        y += +res[i][len - 1];\n                        break;\n                    default:\n                        x += +res[i][len - 2];\n                        y += +res[i][len - 1];\n                }\n            }\n            res.toString = R._path2string;\n            pth.rel = pathClone(res);\n            return res;\n        },\n        pathToAbsolute = R._pathToAbsolute = function (pathArray) {\n            var pth = paths(pathArray);\n            if (pth.abs) {\n                return pathClone(pth.abs);\n            }\n            if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption\n                pathArray = R.parsePathString(pathArray);\n            }\n            if (!pathArray || !pathArray.length) {\n                return [[\"M\", 0, 0]];\n            }\n            var res = [],\n                x = 0,\n                y = 0,\n                mx = 0,\n                my = 0,\n                start = 0;\n            if (pathArray[0][0] == \"M\") {\n                x = +pathArray[0][1];\n                y = +pathArray[0][2];\n                mx = x;\n                my = y;\n                start++;\n                res[0] = [\"M\", x, y];\n            }\n            var crz = pathArray.length == 3 && pathArray[0][0] == \"M\" && pathArray[1][0].toUpperCase() == \"R\" && pathArray[2][0].toUpperCase() == \"Z\";\n            for (var r, pa, i = start, ii = pathArray.length; i < ii; i++) {\n                res.push(r = []);\n                pa = pathArray[i];\n                if (pa[0] != upperCase.call(pa[0])) {\n                    r[0] = upperCase.call(pa[0]);\n                    switch (r[0]) {\n                        case \"A\":\n                            r[1] = pa[1];\n                            r[2] = pa[2];\n                            r[3] = pa[3];\n                            r[4] = pa[4];\n                            r[5] = pa[5];\n                            r[6] = +(pa[6] + x);\n                            r[7] = +(pa[7] + y);\n                            break;\n                        case \"V\":\n                            r[1] = +pa[1] + y;\n                            break;\n                        case \"H\":\n                            r[1] = +pa[1] + x;\n                            break;\n                        case \"R\":\n                            var dots = [x, y][concat](pa.slice(1));\n                            for (var j = 2, jj = dots.length; j < jj; j++) {\n                                dots[j] = +dots[j] + x;\n                                dots[++j] = +dots[j] + y;\n                            }\n                            res.pop();\n                            res = res[concat](catmullRom2bezier(dots, crz));\n                            break;\n                        case \"M\":\n                            mx = +pa[1] + x;\n                            my = +pa[2] + y;\n                        default:\n                            for (j = 1, jj = pa.length; j < jj; j++) {\n                                r[j] = +pa[j] + ((j % 2) ? x : y);\n                            }\n                    }\n                } else if (pa[0] == \"R\") {\n                    dots = [x, y][concat](pa.slice(1));\n                    res.pop();\n                    res = res[concat](catmullRom2bezier(dots, crz));\n                    r = [\"R\"][concat](pa.slice(-2));\n                } else {\n                    for (var k = 0, kk = pa.length; k < kk; k++) {\n                        r[k] = pa[k];\n                    }\n                }\n                switch (r[0]) {\n                    case \"Z\":\n                        x = mx;\n                        y = my;\n                        break;\n                    case \"H\":\n                        x = r[1];\n                        break;\n                    case \"V\":\n                        y = r[1];\n                        break;\n                    case \"M\":\n                        mx = r[r.length - 2];\n                        my = r[r.length - 1];\n                    default:\n                        x = r[r.length - 2];\n                        y = r[r.length - 1];\n                }\n            }\n            res.toString = R._path2string;\n            pth.abs = pathClone(res);\n            return res;\n        },\n        l2c = function (x1, y1, x2, y2) {\n            return [x1, y1, x2, y2, x2, y2];\n        },\n        q2c = function (x1, y1, ax, ay, x2, y2) {\n            var _13 = 1 / 3,\n                _23 = 2 / 3;\n            return [\n                    _13 * x1 + _23 * ax,\n                    _13 * y1 + _23 * ay,\n                    _13 * x2 + _23 * ax,\n                    _13 * y2 + _23 * ay,\n                    x2,\n                    y2\n                ];\n        },\n        a2c = function (x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2, recursive) {\n            // for more information of where this math came from visit:\n            // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes\n            var _120 = PI * 120 / 180,\n                rad = PI / 180 * (+angle || 0),\n                res = [],\n                xy,\n                rotate = cacher(function (x, y, rad) {\n                    var X = x * math.cos(rad) - y * math.sin(rad),\n                        Y = x * math.sin(rad) + y * math.cos(rad);\n                    return {x: X, y: Y};\n                });\n            if (!recursive) {\n                xy = rotate(x1, y1, -rad);\n                x1 = xy.x;\n                y1 = xy.y;\n                xy = rotate(x2, y2, -rad);\n                x2 = xy.x;\n                y2 = xy.y;\n                var cos = math.cos(PI / 180 * angle),\n                    sin = math.sin(PI / 180 * angle),\n                    x = (x1 - x2) / 2,\n                    y = (y1 - y2) / 2;\n                var h = (x * x) / (rx * rx) + (y * y) / (ry * ry);\n                if (h > 1) {\n                    h = math.sqrt(h);\n                    rx = h * rx;\n                    ry = h * ry;\n                }\n                var rx2 = rx * rx,\n                    ry2 = ry * ry,\n                    k = (large_arc_flag == sweep_flag ? -1 : 1) *\n                        math.sqrt(abs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x))),\n                    cx = k * rx * y / ry + (x1 + x2) / 2,\n                    cy = k * -ry * x / rx + (y1 + y2) / 2,\n                    f1 = math.asin(((y1 - cy) / ry).toFixed(9)),\n                    f2 = math.asin(((y2 - cy) / ry).toFixed(9));\n\n                f1 = x1 < cx ? PI - f1 : f1;\n                f2 = x2 < cx ? PI - f2 : f2;\n                f1 < 0 && (f1 = PI * 2 + f1);\n                f2 < 0 && (f2 = PI * 2 + f2);\n                if (sweep_flag && f1 > f2) {\n                    f1 = f1 - PI * 2;\n                }\n                if (!sweep_flag && f2 > f1) {\n                    f2 = f2 - PI * 2;\n                }\n            } else {\n                f1 = recursive[0];\n                f2 = recursive[1];\n                cx = recursive[2];\n                cy = recursive[3];\n            }\n            var df = f2 - f1;\n            if (abs(df) > _120) {\n                var f2old = f2,\n                    x2old = x2,\n                    y2old = y2;\n                f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1);\n                x2 = cx + rx * math.cos(f2);\n                y2 = cy + ry * math.sin(f2);\n                res = a2c(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [f2, f2old, cx, cy]);\n            }\n            df = f2 - f1;\n            var c1 = math.cos(f1),\n                s1 = math.sin(f1),\n                c2 = math.cos(f2),\n                s2 = math.sin(f2),\n                t = math.tan(df / 4),\n                hx = 4 / 3 * rx * t,\n                hy = 4 / 3 * ry * t,\n                m1 = [x1, y1],\n                m2 = [x1 + hx * s1, y1 - hy * c1],\n                m3 = [x2 + hx * s2, y2 - hy * c2],\n                m4 = [x2, y2];\n            m2[0] = 2 * m1[0] - m2[0];\n            m2[1] = 2 * m1[1] - m2[1];\n            if (recursive) {\n                return [m2, m3, m4][concat](res);\n            } else {\n                res = [m2, m3, m4][concat](res).join()[split](\",\");\n                var newres = [];\n                for (var i = 0, ii = res.length; i < ii; i++) {\n                    newres[i] = i % 2 ? rotate(res[i - 1], res[i], rad).y : rotate(res[i], res[i + 1], rad).x;\n                }\n                return newres;\n            }\n        },\n        findDotAtSegment = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) {\n            var t1 = 1 - t;\n            return {\n                x: pow(t1, 3) * p1x + pow(t1, 2) * 3 * t * c1x + t1 * 3 * t * t * c2x + pow(t, 3) * p2x,\n                y: pow(t1, 3) * p1y + pow(t1, 2) * 3 * t * c1y + t1 * 3 * t * t * c2y + pow(t, 3) * p2y\n            };\n        },\n        curveDim = cacher(function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) {\n            var a = (c2x - 2 * c1x + p1x) - (p2x - 2 * c2x + c1x),\n                b = 2 * (c1x - p1x) - 2 * (c2x - c1x),\n                c = p1x - c1x,\n                t1 = (-b + math.sqrt(b * b - 4 * a * c)) / 2 / a,\n                t2 = (-b - math.sqrt(b * b - 4 * a * c)) / 2 / a,\n                y = [p1y, p2y],\n                x = [p1x, p2x],\n                dot;\n            abs(t1) > \"1e12\" && (t1 = .5);\n            abs(t2) > \"1e12\" && (t2 = .5);\n            if (t1 > 0 && t1 < 1) {\n                dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1);\n                x.push(dot.x);\n                y.push(dot.y);\n            }\n            if (t2 > 0 && t2 < 1) {\n                dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2);\n                x.push(dot.x);\n                y.push(dot.y);\n            }\n            a = (c2y - 2 * c1y + p1y) - (p2y - 2 * c2y + c1y);\n            b = 2 * (c1y - p1y) - 2 * (c2y - c1y);\n            c = p1y - c1y;\n            t1 = (-b + math.sqrt(b * b - 4 * a * c)) / 2 / a;\n            t2 = (-b - math.sqrt(b * b - 4 * a * c)) / 2 / a;\n            abs(t1) > \"1e12\" && (t1 = .5);\n            abs(t2) > \"1e12\" && (t2 = .5);\n            if (t1 > 0 && t1 < 1) {\n                dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1);\n                x.push(dot.x);\n                y.push(dot.y);\n            }\n            if (t2 > 0 && t2 < 1) {\n                dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2);\n                x.push(dot.x);\n                y.push(dot.y);\n            }\n            return {\n                min: {x: mmin[apply](0, x), y: mmin[apply](0, y)},\n                max: {x: mmax[apply](0, x), y: mmax[apply](0, y)}\n            };\n        }),\n        path2curve = R._path2curve = cacher(function (path, path2) {\n            var pth = !path2 && paths(path);\n            if (!path2 && pth.curve) {\n                return pathClone(pth.curve);\n            }\n            var p = pathToAbsolute(path),\n                p2 = path2 && pathToAbsolute(path2),\n                attrs = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null},\n                attrs2 = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null},\n                processPath = function (path, d) {\n                    var nx, ny;\n                    if (!path) {\n                        return [\"C\", d.x, d.y, d.x, d.y, d.x, d.y];\n                    }\n                    !(path[0] in {T:1, Q:1}) && (d.qx = d.qy = null);\n                    switch (path[0]) {\n                        case \"M\":\n                            d.X = path[1];\n                            d.Y = path[2];\n                            break;\n                        case \"A\":\n                            path = [\"C\"][concat](a2c[apply](0, [d.x, d.y][concat](path.slice(1))));\n                            break;\n                        case \"S\":\n                            nx = d.x + (d.x - (d.bx || d.x));\n                            ny = d.y + (d.y - (d.by || d.y));\n                            path = [\"C\", nx, ny][concat](path.slice(1));\n                            break;\n                        case \"T\":\n                            d.qx = d.x + (d.x - (d.qx || d.x));\n                            d.qy = d.y + (d.y - (d.qy || d.y));\n                            path = [\"C\"][concat](q2c(d.x, d.y, d.qx, d.qy, path[1], path[2]));\n                            break;\n                        case \"Q\":\n                            d.qx = path[1];\n                            d.qy = path[2];\n                            path = [\"C\"][concat](q2c(d.x, d.y, path[1], path[2], path[3], path[4]));\n                            break;\n                        case \"L\":\n                            path = [\"C\"][concat](l2c(d.x, d.y, path[1], path[2]));\n                            break;\n                        case \"H\":\n                            path = [\"C\"][concat](l2c(d.x, d.y, path[1], d.y));\n                            break;\n                        case \"V\":\n                            path = [\"C\"][concat](l2c(d.x, d.y, d.x, path[1]));\n                            break;\n                        case \"Z\":\n                            path = [\"C\"][concat](l2c(d.x, d.y, d.X, d.Y));\n                            break;\n                    }\n                    return path;\n                },\n                fixArc = function (pp, i) {\n                    if (pp[i].length > 7) {\n                        pp[i].shift();\n                        var pi = pp[i];\n                        while (pi.length) {\n                            pp.splice(i++, 0, [\"C\"][concat](pi.splice(0, 6)));\n                        }\n                        pp.splice(i, 1);\n                        ii = mmax(p.length, p2 && p2.length || 0);\n                    }\n                },\n                fixM = function (path1, path2, a1, a2, i) {\n                    if (path1 && path2 && path1[i][0] == \"M\" && path2[i][0] != \"M\") {\n                        path2.splice(i, 0, [\"M\", a2.x, a2.y]);\n                        a1.bx = 0;\n                        a1.by = 0;\n                        a1.x = path1[i][1];\n                        a1.y = path1[i][2];\n                        ii = mmax(p.length, p2 && p2.length || 0);\n                    }\n                };\n            for (var i = 0, ii = mmax(p.length, p2 && p2.length || 0); i < ii; i++) {\n                p[i] = processPath(p[i], attrs);\n                fixArc(p, i);\n                p2 && (p2[i] = processPath(p2[i], attrs2));\n                p2 && fixArc(p2, i);\n                fixM(p, p2, attrs, attrs2, i);\n                fixM(p2, p, attrs2, attrs, i);\n                var seg = p[i],\n                    seg2 = p2 && p2[i],\n                    seglen = seg.length,\n                    seg2len = p2 && seg2.length;\n                attrs.x = seg[seglen - 2];\n                attrs.y = seg[seglen - 1];\n                attrs.bx = toFloat(seg[seglen - 4]) || attrs.x;\n                attrs.by = toFloat(seg[seglen - 3]) || attrs.y;\n                attrs2.bx = p2 && (toFloat(seg2[seg2len - 4]) || attrs2.x);\n                attrs2.by = p2 && (toFloat(seg2[seg2len - 3]) || attrs2.y);\n                attrs2.x = p2 && seg2[seg2len - 2];\n                attrs2.y = p2 && seg2[seg2len - 1];\n            }\n            if (!p2) {\n                pth.curve = pathClone(p);\n            }\n            return p2 ? [p, p2] : p;\n        }, null, pathClone),\n        parseDots = R._parseDots = cacher(function (gradient) {\n            var dots = [];\n            for (var i = 0, ii = gradient.length; i < ii; i++) {\n                var dot = {},\n                    par = gradient[i].match(/^([^:]*):?([\\d\\.]*)/);\n                dot.color = R.getRGB(par[1]);\n                if (dot.color.error) {\n                    return null;\n                }\n                dot.color = dot.color.hex;\n                par[2] && (dot.offset = par[2] + \"%\");\n                dots.push(dot);\n            }\n            for (i = 1, ii = dots.length - 1; i < ii; i++) {\n                if (!dots[i].offset) {\n                    var start = toFloat(dots[i - 1].offset || 0),\n                        end = 0;\n                    for (var j = i + 1; j < ii; j++) {\n                        if (dots[j].offset) {\n                            end = dots[j].offset;\n                            break;\n                        }\n                    }\n                    if (!end) {\n                        end = 100;\n                        j = ii;\n                    }\n                    end = toFloat(end);\n                    var d = (end - start) / (j - i + 1);\n                    for (; i < j; i++) {\n                        start += d;\n                        dots[i].offset = start + \"%\";\n                    }\n                }\n            }\n            return dots;\n        }),\n        tear = R._tear = function (el, paper) {\n            el == paper.top && (paper.top = el.prev);\n            el == paper.bottom && (paper.bottom = el.next);\n            el.next && (el.next.prev = el.prev);\n            el.prev && (el.prev.next = el.next);\n        },\n        tofront = R._tofront = function (el, paper) {\n            if (paper.top === el) {\n                return;\n            }\n            tear(el, paper);\n            el.next = null;\n            el.prev = paper.top;\n            paper.top.next = el;\n            paper.top = el;\n        },\n        toback = R._toback = function (el, paper) {\n            if (paper.bottom === el) {\n                return;\n            }\n            tear(el, paper);\n            el.next = paper.bottom;\n            el.prev = null;\n            paper.bottom.prev = el;\n            paper.bottom = el;\n        },\n        insertafter = R._insertafter = function (el, el2, paper) {\n            tear(el, paper);\n            el2 == paper.top && (paper.top = el);\n            el2.next && (el2.next.prev = el);\n            el.next = el2.next;\n            el.prev = el2;\n            el2.next = el;\n        },\n        insertbefore = R._insertbefore = function (el, el2, paper) {\n            tear(el, paper);\n            el2 == paper.bottom && (paper.bottom = el);\n            el2.prev && (el2.prev.next = el);\n            el.prev = el2.prev;\n            el2.prev = el;\n            el.next = el2;\n        },\n        \n        toMatrix = R.toMatrix = function (path, transform) {\n            var bb = pathDimensions(path),\n                el = {\n                    _: {\n                        transform: E\n                    },\n                    getBBox: function () {\n                        return bb;\n                    }\n                };\n            extractTransform(el, transform);\n            return el.matrix;\n        },\n        \n        transformPath = R.transformPath = function (path, transform) {\n            return mapPath(path, toMatrix(path, transform));\n        },\n        extractTransform = R._extractTransform = function (el, tstr) {\n            if (tstr == null) {\n                return el._.transform;\n            }\n            tstr = Str(tstr).replace(/\\.{3}|\\u2026/g, el._.transform || E);\n            var tdata = R.parseTransformString(tstr),\n                deg = 0,\n                dx = 0,\n                dy = 0,\n                sx = 1,\n                sy = 1,\n                _ = el._,\n                m = new Matrix;\n            _.transform = tdata || [];\n            if (tdata) {\n                for (var i = 0, ii = tdata.length; i < ii; i++) {\n                    var t = tdata[i],\n                        tlen = t.length,\n                        command = Str(t[0]).toLowerCase(),\n                        absolute = t[0] != command,\n                        inver = absolute ? m.invert() : 0,\n                        x1,\n                        y1,\n                        x2,\n                        y2,\n                        bb;\n                    if (command == \"t\" && tlen == 3) {\n                        if (absolute) {\n                            x1 = inver.x(0, 0);\n                            y1 = inver.y(0, 0);\n                            x2 = inver.x(t[1], t[2]);\n                            y2 = inver.y(t[1], t[2]);\n                            m.translate(x2 - x1, y2 - y1);\n                        } else {\n                            m.translate(t[1], t[2]);\n                        }\n                    } else if (command == \"r\") {\n                        if (tlen == 2) {\n                            bb = bb || el.getBBox(1);\n                            m.rotate(t[1], bb.x + bb.width / 2, bb.y + bb.height / 2);\n                            deg += t[1];\n                        } else if (tlen == 4) {\n                            if (absolute) {\n                                x2 = inver.x(t[2], t[3]);\n                                y2 = inver.y(t[2], t[3]);\n                                m.rotate(t[1], x2, y2);\n                            } else {\n                                m.rotate(t[1], t[2], t[3]);\n                            }\n                            deg += t[1];\n                        }\n                    } else if (command == \"s\") {\n                        if (tlen == 2 || tlen == 3) {\n                            bb = bb || el.getBBox(1);\n                            m.scale(t[1], t[tlen - 1], bb.x + bb.width / 2, bb.y + bb.height / 2);\n                            sx *= t[1];\n                            sy *= t[tlen - 1];\n                        } else if (tlen == 5) {\n                            if (absolute) {\n                                x2 = inver.x(t[3], t[4]);\n                                y2 = inver.y(t[3], t[4]);\n                                m.scale(t[1], t[2], x2, y2);\n                            } else {\n                                m.scale(t[1], t[2], t[3], t[4]);\n                            }\n                            sx *= t[1];\n                            sy *= t[2];\n                        }\n                    } else if (command == \"m\" && tlen == 7) {\n                        m.add(t[1], t[2], t[3], t[4], t[5], t[6]);\n                    }\n                    _.dirtyT = 1;\n                    el.matrix = m;\n                }\n            }\n\n            \n            el.matrix = m;\n\n            _.sx = sx;\n            _.sy = sy;\n            _.deg = deg;\n            _.dx = dx = m.e;\n            _.dy = dy = m.f;\n\n            if (sx == 1 && sy == 1 && !deg && _.bbox) {\n                _.bbox.x += +dx;\n                _.bbox.y += +dy;\n            } else {\n                _.dirtyT = 1;\n            }\n        },\n        getEmpty = function (item) {\n            var l = item[0];\n            switch (l.toLowerCase()) {\n                case \"t\": return [l, 0, 0];\n                case \"m\": return [l, 1, 0, 0, 1, 0, 0];\n                case \"r\": if (item.length == 4) {\n                    return [l, 0, item[2], item[3]];\n                } else {\n                    return [l, 0];\n                }\n                case \"s\": if (item.length == 5) {\n                    return [l, 1, 1, item[3], item[4]];\n                } else if (item.length == 3) {\n                    return [l, 1, 1];\n                } else {\n                    return [l, 1];\n                }\n            }\n        },\n        equaliseTransform = R._equaliseTransform = function (t1, t2) {\n            t2 = Str(t2).replace(/\\.{3}|\\u2026/g, t1);\n            t1 = R.parseTransformString(t1) || [];\n            t2 = R.parseTransformString(t2) || [];\n            var maxlength = mmax(t1.length, t2.length),\n                from = [],\n                to = [],\n                i = 0, j, jj,\n                tt1, tt2;\n            for (; i < maxlength; i++) {\n                tt1 = t1[i] || getEmpty(t2[i]);\n                tt2 = t2[i] || getEmpty(tt1);\n                if ((tt1[0] != tt2[0]) ||\n                    (tt1[0].toLowerCase() == \"r\" && (tt1[2] != tt2[2] || tt1[3] != tt2[3])) ||\n                    (tt1[0].toLowerCase() == \"s\" && (tt1[3] != tt2[3] || tt1[4] != tt2[4]))\n                    ) {\n                    return;\n                }\n                from[i] = [];\n                to[i] = [];\n                for (j = 0, jj = mmax(tt1.length, tt2.length); j < jj; j++) {\n                    j in tt1 && (from[i][j] = tt1[j]);\n                    j in tt2 && (to[i][j] = tt2[j]);\n                }\n            }\n            return {\n                from: from,\n                to: to\n            };\n        };\n    R._getContainer = function (x, y, w, h) {\n        var container;\n        container = h == null && !R.is(x, \"object\") ? g.doc.getElementById(x) : x;\n        if (container == null) {\n            return;\n        }\n        if (container.tagName) {\n            if (y == null) {\n                return {\n                    container: container,\n                    width: container.style.pixelWidth || container.offsetWidth,\n                    height: container.style.pixelHeight || container.offsetHeight\n                };\n            } else {\n                return {\n                    container: container,\n                    width: y,\n                    height: w\n                };\n            }\n        }\n        return {\n            container: 1,\n            x: x,\n            y: y,\n            width: w,\n            height: h\n        };\n    };\n    \n    R.pathToRelative = pathToRelative;\n    R._engine = {};\n    \n    R.path2curve = path2curve;\n    \n    R.matrix = function (a, b, c, d, e, f) {\n        return new Matrix(a, b, c, d, e, f);\n    };\n    function Matrix(a, b, c, d, e, f) {\n        if (a != null) {\n            this.a = +a;\n            this.b = +b;\n            this.c = +c;\n            this.d = +d;\n            this.e = +e;\n            this.f = +f;\n        } else {\n            this.a = 1;\n            this.b = 0;\n            this.c = 0;\n            this.d = 1;\n            this.e = 0;\n            this.f = 0;\n        }\n    }\n    (function (matrixproto) {\n        \n        matrixproto.add = function (a, b, c, d, e, f) {\n            var out = [[], [], []],\n                m = [[this.a, this.c, this.e], [this.b, this.d, this.f], [0, 0, 1]],\n                matrix = [[a, c, e], [b, d, f], [0, 0, 1]],\n                x, y, z, res;\n\n            if (a && a instanceof Matrix) {\n                matrix = [[a.a, a.c, a.e], [a.b, a.d, a.f], [0, 0, 1]];\n            }\n\n            for (x = 0; x < 3; x++) {\n                for (y = 0; y < 3; y++) {\n                    res = 0;\n                    for (z = 0; z < 3; z++) {\n                        res += m[x][z] * matrix[z][y];\n                    }\n                    out[x][y] = res;\n                }\n            }\n            this.a = out[0][0];\n            this.b = out[1][0];\n            this.c = out[0][1];\n            this.d = out[1][1];\n            this.e = out[0][2];\n            this.f = out[1][2];\n        };\n        \n        matrixproto.invert = function () {\n            var me = this,\n                x = me.a * me.d - me.b * me.c;\n            return new Matrix(me.d / x, -me.b / x, -me.c / x, me.a / x, (me.c * me.f - me.d * me.e) / x, (me.b * me.e - me.a * me.f) / x);\n        };\n        \n        matrixproto.clone = function () {\n            return new Matrix(this.a, this.b, this.c, this.d, this.e, this.f);\n        };\n        \n        matrixproto.translate = function (x, y) {\n            this.add(1, 0, 0, 1, x, y);\n        };\n        \n        matrixproto.scale = function (x, y, cx, cy) {\n            y == null && (y = x);\n            (cx || cy) && this.add(1, 0, 0, 1, cx, cy);\n            this.add(x, 0, 0, y, 0, 0);\n            (cx || cy) && this.add(1, 0, 0, 1, -cx, -cy);\n        };\n        \n        matrixproto.rotate = function (a, x, y) {\n            a = R.rad(a);\n            x = x || 0;\n            y = y || 0;\n            var cos = +math.cos(a).toFixed(9),\n                sin = +math.sin(a).toFixed(9);\n            this.add(cos, sin, -sin, cos, x, y);\n            this.add(1, 0, 0, 1, -x, -y);\n        };\n        \n        matrixproto.x = function (x, y) {\n            return x * this.a + y * this.c + this.e;\n        };\n        \n        matrixproto.y = function (x, y) {\n            return x * this.b + y * this.d + this.f;\n        };\n        matrixproto.get = function (i) {\n            return +this[Str.fromCharCode(97 + i)].toFixed(4);\n        };\n        matrixproto.toString = function () {\n            return R.svg ?\n                \"matrix(\" + [this.get(0), this.get(1), this.get(2), this.get(3), this.get(4), this.get(5)].join() + \")\" :\n                [this.get(0), this.get(2), this.get(1), this.get(3), 0, 0].join();\n        };\n        matrixproto.toFilter = function () {\n            return \"progid:DXImageTransform.Microsoft.Matrix(M11=\" + this.get(0) +\n                \", M12=\" + this.get(2) + \", M21=\" + this.get(1) + \", M22=\" + this.get(3) +\n                \", Dx=\" + this.get(4) + \", Dy=\" + this.get(5) + \", sizingmethod='auto expand')\";\n        };\n        matrixproto.offset = function () {\n            return [this.e.toFixed(4), this.f.toFixed(4)];\n        };\n        function norm(a) {\n            return a[0] * a[0] + a[1] * a[1];\n        }\n        function normalize(a) {\n            var mag = math.sqrt(norm(a));\n            a[0] && (a[0] /= mag);\n            a[1] && (a[1] /= mag);\n        }\n        \n        matrixproto.split = function () {\n            var out = {};\n            // translation\n            out.dx = this.e;\n            out.dy = this.f;\n\n            // scale and shear\n            var row = [[this.a, this.c], [this.b, this.d]];\n            out.scalex = math.sqrt(norm(row[0]));\n            normalize(row[0]);\n\n            out.shear = row[0][0] * row[1][0] + row[0][1] * row[1][1];\n            row[1] = [row[1][0] - row[0][0] * out.shear, row[1][1] - row[0][1] * out.shear];\n\n            out.scaley = math.sqrt(norm(row[1]));\n            normalize(row[1]);\n            out.shear /= out.scaley;\n\n            // rotation\n            var sin = -row[0][1],\n                cos = row[1][1];\n            if (cos < 0) {\n                out.rotate = R.deg(math.acos(cos));\n                if (sin < 0) {\n                    out.rotate = 360 - out.rotate;\n                }\n            } else {\n                out.rotate = R.deg(math.asin(sin));\n            }\n\n            out.isSimple = !+out.shear.toFixed(9) && (out.scalex.toFixed(9) == out.scaley.toFixed(9) || !out.rotate);\n            out.isSuperSimple = !+out.shear.toFixed(9) && out.scalex.toFixed(9) == out.scaley.toFixed(9) && !out.rotate;\n            out.noRotation = !+out.shear.toFixed(9) && !out.rotate;\n            return out;\n        };\n        \n        matrixproto.toTransformString = function (shorter) {\n            var s = shorter || this[split]();\n            if (s.isSimple) {\n                s.scalex = +s.scalex.toFixed(4);\n                s.scaley = +s.scaley.toFixed(4);\n                s.rotate = +s.rotate.toFixed(4);\n                return  (s.dx || s.dy ? \"t\" + [s.dx, s.dy] : E) + \n                        (s.scalex != 1 || s.scaley != 1 ? \"s\" + [s.scalex, s.scaley, 0, 0] : E) +\n                        (s.rotate ? \"r\" + [s.rotate, 0, 0] : E);\n            } else {\n                return \"m\" + [this.get(0), this.get(1), this.get(2), this.get(3), this.get(4), this.get(5)];\n            }\n        };\n    })(Matrix.prototype);\n\n    // WebKit rendering bug workaround method\n    var version = navigator.userAgent.match(/Version\\/(.*?)\\s/) || navigator.userAgent.match(/Chrome\\/(\\d+)/);\n    if ((navigator.vendor == \"Apple Computer, Inc.\") && (version && version[1] < 4 || navigator.platform.slice(0, 2) == \"iP\") ||\n        (navigator.vendor == \"Google Inc.\" && version && version[1] < 8)) {\n        \n        paperproto.safari = function () {\n            var rect = this.rect(-99, -99, this.width + 99, this.height + 99).attr({stroke: \"none\"});\n            setTimeout(function () {rect.remove();});\n        };\n    } else {\n        paperproto.safari = fun;\n    }\n \n    var preventDefault = function () {\n        this.returnValue = false;\n    },\n    preventTouch = function () {\n        return this.originalEvent.preventDefault();\n    },\n    stopPropagation = function () {\n        this.cancelBubble = true;\n    },\n    stopTouch = function () {\n        return this.originalEvent.stopPropagation();\n    },\n    addEvent = (function () {\n        if (g.doc.addEventListener) {\n            return function (obj, type, fn, element) {\n                var realName = supportsTouch && touchMap[type] ? touchMap[type] : type,\n                    f = function (e) {\n                        var scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop,\n                            scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft,\n                            x = e.clientX + scrollX,\n                            y = e.clientY + scrollY;\n                    if (supportsTouch && touchMap[has](type)) {\n                        for (var i = 0, ii = e.targetTouches && e.targetTouches.length; i < ii; i++) {\n                            if (e.targetTouches[i].target == obj) {\n                                var olde = e;\n                                e = e.targetTouches[i];\n                                e.originalEvent = olde;\n                                e.preventDefault = preventTouch;\n                                e.stopPropagation = stopTouch;\n                                break;\n                            }\n                        }\n                    }\n                    return fn.call(element, e, x, y);\n                };\n                obj.addEventListener(realName, f, false);\n                return function () {\n                    obj.removeEventListener(realName, f, false);\n                    return true;\n                };\n            };\n        } else if (g.doc.attachEvent) {\n            return function (obj, type, fn, element) {\n                var f = function (e) {\n                    e = e || g.win.event;\n                    var scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop,\n                        scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft,\n                        x = e.clientX + scrollX,\n                        y = e.clientY + scrollY;\n                    e.preventDefault = e.preventDefault || preventDefault;\n                    e.stopPropagation = e.stopPropagation || stopPropagation;\n                    return fn.call(element, e, x, y);\n                };\n                obj.attachEvent(\"on\" + type, f);\n                var detacher = function () {\n                    obj.detachEvent(\"on\" + type, f);\n                    return true;\n                };\n                return detacher;\n            };\n        }\n    })(),\n    drag = [],\n    dragMove = function (e) {\n        var x = e.clientX,\n            y = e.clientY,\n            scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop,\n            scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft,\n            dragi,\n            j = drag.length;\n        while (j--) {\n            dragi = drag[j];\n            if (supportsTouch) {\n                var i = e.touches.length,\n                    touch;\n                while (i--) {\n                    touch = e.touches[i];\n                    if (touch.identifier == dragi.el._drag.id) {\n                        x = touch.clientX;\n                        y = touch.clientY;\n                        (e.originalEvent ? e.originalEvent : e).preventDefault();\n                        break;\n                    }\n                }\n            } else {\n                e.preventDefault();\n            }\n            var node = dragi.el.node,\n                o,\n                next = node.nextSibling,\n                parent = node.parentNode,\n                display = node.style.display;\n            g.win.opera && parent.removeChild(node);\n            node.style.display = \"none\";\n            o = dragi.el.paper.getElementByPoint(x, y);\n            node.style.display = display;\n            g.win.opera && (next ? parent.insertBefore(node, next) : parent.appendChild(node));\n            o && eve(\"raphael.drag.over.\" + dragi.el.id, dragi.el, o);\n            x += scrollX;\n            y += scrollY;\n            eve(\"raphael.drag.move.\" + dragi.el.id, dragi.move_scope || dragi.el, x - dragi.el._drag.x, y - dragi.el._drag.y, x, y, e);\n        }\n    },\n    dragUp = function (e) {\n        R.unmousemove(dragMove).unmouseup(dragUp);\n        var i = drag.length,\n            dragi;\n        while (i--) {\n            dragi = drag[i];\n            dragi.el._drag = {};\n            eve(\"raphael.drag.end.\" + dragi.el.id, dragi.end_scope || dragi.start_scope || dragi.move_scope || dragi.el, e);\n        }\n        drag = [];\n    },\n    \n    elproto = R.el = {};\n    \n    \n    \n    \n    \n    \n    \n    \n    \n    \n    \n    \n    \n    \n    \n    \n    \n    \n    \n    \n    \n    \n    \n    \n    \n    \n    \n    \n    \n    \n    \n    \n    for (var i = events.length; i--;) {\n        (function (eventName) {\n            R[eventName] = elproto[eventName] = function (fn, scope) {\n                if (R.is(fn, \"function\")) {\n                    this.events = this.events || [];\n                    this.events.push({name: eventName, f: fn, unbind: addEvent(this.shape || this.node || g.doc, eventName, fn, scope || this)});\n                }\n                return this;\n            };\n            R[\"un\" + eventName] = elproto[\"un\" + eventName] = function (fn) {\n                var events = this.events || [],\n                    l = events.length;\n                while (l--) if (events[l].name == eventName && events[l].f == fn) {\n                    events[l].unbind();\n                    events.splice(l, 1);\n                    !events.length && delete this.events;\n                    return this;\n                }\n                return this;\n            };\n        })(events[i]);\n    }\n    \n    \n    elproto.data = function (key, value) {\n        var data = eldata[this.id] = eldata[this.id] || {};\n        if (arguments.length == 1) {\n            if (R.is(key, \"object\")) {\n                for (var i in key) if (key[has](i)) {\n                    this.data(i, key[i]);\n                }\n                return this;\n            }\n            eve(\"raphael.data.get.\" + this.id, this, data[key], key);\n            return data[key];\n        }\n        data[key] = value;\n        eve(\"raphael.data.set.\" + this.id, this, value, key);\n        return this;\n    };\n    \n    elproto.removeData = function (key) {\n        if (key == null) {\n            eldata[this.id] = {};\n        } else {\n            eldata[this.id] && delete eldata[this.id][key];\n        }\n        return this;\n    };\n    \n    elproto.hover = function (f_in, f_out, scope_in, scope_out) {\n        return this.mouseover(f_in, scope_in).mouseout(f_out, scope_out || scope_in);\n    };\n    \n    elproto.unhover = function (f_in, f_out) {\n        return this.unmouseover(f_in).unmouseout(f_out);\n    };\n    var draggable = [];\n    \n    elproto.drag = function (onmove, onstart, onend, move_scope, start_scope, end_scope) {\n        function start(e) {\n            (e.originalEvent || e).preventDefault();\n            var scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop,\n                scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft;\n            this._drag.x = e.clientX + scrollX;\n            this._drag.y = e.clientY + scrollY;\n            this._drag.id = e.identifier;\n            !drag.length && R.mousemove(dragMove).mouseup(dragUp);\n            drag.push({el: this, move_scope: move_scope, start_scope: start_scope, end_scope: end_scope});\n            onstart && eve.on(\"raphael.drag.start.\" + this.id, onstart);\n            onmove && eve.on(\"raphael.drag.move.\" + this.id, onmove);\n            onend && eve.on(\"raphael.drag.end.\" + this.id, onend);\n            eve(\"raphael.drag.start.\" + this.id, start_scope || move_scope || this, e.clientX + scrollX, e.clientY + scrollY, e);\n        }\n        this._drag = {};\n        draggable.push({el: this, start: start});\n        this.mousedown(start);\n        return this;\n    };\n    \n    elproto.onDragOver = function (f) {\n        f ? eve.on(\"raphael.drag.over.\" + this.id, f) : eve.unbind(\"raphael.drag.over.\" + this.id);\n    };\n    \n    elproto.undrag = function () {\n        var i = draggable.length;\n        while (i--) if (draggable[i].el == this) {\n            this.unmousedown(draggable[i].start);\n            draggable.splice(i, 1);\n            eve.unbind(\"raphael.drag.*.\" + this.id);\n        }\n        !draggable.length && R.unmousemove(dragMove).unmouseup(dragUp);\n    };\n    \n    paperproto.circle = function (x, y, r) {\n        var out = R._engine.circle(this, x || 0, y || 0, r || 0);\n        this.__set__ && this.__set__.push(out);\n        return out;\n    };\n    \n    paperproto.rect = function (x, y, w, h, r) {\n        var out = R._engine.rect(this, x || 0, y || 0, w || 0, h || 0, r || 0);\n        this.__set__ && this.__set__.push(out);\n        return out;\n    };\n    \n    paperproto.ellipse = function (x, y, rx, ry) {\n        var out = R._engine.ellipse(this, x || 0, y || 0, rx || 0, ry || 0);\n        this.__set__ && this.__set__.push(out);\n        return out;\n    };\n    \n    paperproto.path = function (pathString) {\n        pathString && !R.is(pathString, string) && !R.is(pathString[0], array) && (pathString += E);\n        var out = R._engine.path(R.format[apply](R, arguments), this);\n        this.__set__ && this.__set__.push(out);\n        return out;\n    };\n    \n    paperproto.image = function (src, x, y, w, h) {\n        var out = R._engine.image(this, src || \"about:blank\", x || 0, y || 0, w || 0, h || 0);\n        this.__set__ && this.__set__.push(out);\n        return out;\n    };\n    \n    paperproto.text = function (x, y, text) {\n        var out = R._engine.text(this, x || 0, y || 0, Str(text));\n        this.__set__ && this.__set__.push(out);\n        return out;\n    };\n    \n    paperproto.set = function (itemsArray) {\n        !R.is(itemsArray, \"array\") && (itemsArray = Array.prototype.splice.call(arguments, 0, arguments.length));\n        var out = new Set(itemsArray);\n        this.__set__ && this.__set__.push(out);\n        return out;\n    };\n    \n    paperproto.setStart = function (set) {\n        this.__set__ = set || this.set();\n    };\n    \n    paperproto.setFinish = function (set) {\n        var out = this.__set__;\n        delete this.__set__;\n        return out;\n    };\n    \n    paperproto.setSize = function (width, height) {\n        return R._engine.setSize.call(this, width, height);\n    };\n    \n    paperproto.setViewBox = function (x, y, w, h, fit) {\n        return R._engine.setViewBox.call(this, x, y, w, h, fit);\n    };\n    \n    \n    paperproto.top = paperproto.bottom = null;\n    \n    paperproto.raphael = R;\n    var getOffset = function (elem) {\n        var box = elem.getBoundingClientRect(),\n            doc = elem.ownerDocument,\n            body = doc.body,\n            docElem = doc.documentElement,\n            clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0,\n            top  = box.top  + (g.win.pageYOffset || docElem.scrollTop || body.scrollTop ) - clientTop,\n            left = box.left + (g.win.pageXOffset || docElem.scrollLeft || body.scrollLeft) - clientLeft;\n        return {\n            y: top,\n            x: left\n        };\n    };\n    \n    paperproto.getElementByPoint = function (x, y) {\n        var paper = this,\n            svg = paper.canvas,\n            target = g.doc.elementFromPoint(x, y);\n        if (g.win.opera && target.tagName == \"svg\") {\n            var so = getOffset(svg),\n                sr = svg.createSVGRect();\n            sr.x = x - so.x;\n            sr.y = y - so.y;\n            sr.width = sr.height = 1;\n            var hits = svg.getIntersectionList(sr, null);\n            if (hits.length) {\n                target = hits[hits.length - 1];\n            }\n        }\n        if (!target) {\n            return null;\n        }\n        while (target.parentNode && target != svg.parentNode && !target.raphael) {\n            target = target.parentNode;\n        }\n        target == paper.canvas.parentNode && (target = svg);\n        target = target && target.raphael ? paper.getById(target.raphaelid) : null;\n        return target;\n    };\n    \n    paperproto.getById = function (id) {\n        var bot = this.bottom;\n        while (bot) {\n            if (bot.id == id) {\n                return bot;\n            }\n            bot = bot.next;\n        }\n        return null;\n    };\n    \n    paperproto.forEach = function (callback, thisArg) {\n        var bot = this.bottom;\n        while (bot) {\n            if (callback.call(thisArg, bot) === false) {\n                return this;\n            }\n            bot = bot.next;\n        }\n        return this;\n    };\n    \n    paperproto.getElementsByPoint = function (x, y) {\n        var set = this.set();\n        this.forEach(function (el) {\n            if (el.isPointInside(x, y)) {\n                set.push(el);\n            }\n        });\n        return set;\n    };\n    function x_y() {\n        return this.x + S + this.y;\n    }\n    function x_y_w_h() {\n        return this.x + S + this.y + S + this.width + \" \\xd7 \" + this.height;\n    }\n    \n    elproto.isPointInside = function (x, y) {\n        var rp = this.realPath = this.realPath || getPath[this.type](this);\n        return R.isPointInsidePath(rp, x, y);\n    };\n    \n    elproto.getBBox = function (isWithoutTransform) {\n        if (this.removed) {\n            return {};\n        }\n        var _ = this._;\n        if (isWithoutTransform) {\n            if (_.dirty || !_.bboxwt) {\n                this.realPath = getPath[this.type](this);\n                _.bboxwt = pathDimensions(this.realPath);\n                _.bboxwt.toString = x_y_w_h;\n                _.dirty = 0;\n            }\n            return _.bboxwt;\n        }\n        if (_.dirty || _.dirtyT || !_.bbox) {\n            if (_.dirty || !this.realPath) {\n                _.bboxwt = 0;\n                this.realPath = getPath[this.type](this);\n            }\n            _.bbox = pathDimensions(mapPath(this.realPath, this.matrix));\n            _.bbox.toString = x_y_w_h;\n            _.dirty = _.dirtyT = 0;\n        }\n        return _.bbox;\n    };\n    \n    elproto.clone = function () {\n        if (this.removed) {\n            return null;\n        }\n        var out = this.paper[this.type]().attr(this.attr());\n        this.__set__ && this.__set__.push(out);\n        return out;\n    };\n    \n    elproto.glow = function (glow) {\n        if (this.type == \"text\") {\n            return null;\n        }\n        glow = glow || {};\n        var s = {\n            width: (glow.width || 10) + (+this.attr(\"stroke-width\") || 1),\n            fill: glow.fill || false,\n            opacity: glow.opacity || .5,\n            offsetx: glow.offsetx || 0,\n            offsety: glow.offsety || 0,\n            color: glow.color || \"#000\"\n        },\n            c = s.width / 2,\n            r = this.paper,\n            out = r.set(),\n            path = this.realPath || getPath[this.type](this);\n        path = this.matrix ? mapPath(path, this.matrix) : path;\n        for (var i = 1; i < c + 1; i++) {\n            out.push(r.path(path).attr({\n                stroke: s.color,\n                fill: s.fill ? s.color : \"none\",\n                \"stroke-linejoin\": \"round\",\n                \"stroke-linecap\": \"round\",\n                \"stroke-width\": +(s.width / c * i).toFixed(3),\n                opacity: +(s.opacity / c).toFixed(3)\n            }));\n        }\n        return out.insertBefore(this).translate(s.offsetx, s.offsety);\n    };\n    var curveslengths = {},\n    getPointAtSegmentLength = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length) {\n        if (length == null) {\n            return bezlen(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y);\n        } else {\n            return R.findDotsAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, getTatLen(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length));\n        }\n    },\n    getLengthFactory = function (istotal, subpath) {\n        return function (path, length, onlystart) {\n            path = path2curve(path);\n            var x, y, p, l, sp = \"\", subpaths = {}, point,\n                len = 0;\n            for (var i = 0, ii = path.length; i < ii; i++) {\n                p = path[i];\n                if (p[0] == \"M\") {\n                    x = +p[1];\n                    y = +p[2];\n                } else {\n                    l = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6]);\n                    if (len + l > length) {\n                        if (subpath && !subpaths.start) {\n                            point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len);\n                            sp += [\"C\" + point.start.x, point.start.y, point.m.x, point.m.y, point.x, point.y];\n                            if (onlystart) {return sp;}\n                            subpaths.start = sp;\n                            sp = [\"M\" + point.x, point.y + \"C\" + point.n.x, point.n.y, point.end.x, point.end.y, p[5], p[6]].join();\n                            len += l;\n                            x = +p[5];\n                            y = +p[6];\n                            continue;\n                        }\n                        if (!istotal && !subpath) {\n                            point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len);\n                            return {x: point.x, y: point.y, alpha: point.alpha};\n                        }\n                    }\n                    len += l;\n                    x = +p[5];\n                    y = +p[6];\n                }\n                sp += p.shift() + p;\n            }\n            subpaths.end = sp;\n            point = istotal ? len : subpath ? subpaths : R.findDotsAtSegment(x, y, p[0], p[1], p[2], p[3], p[4], p[5], 1);\n            point.alpha && (point = {x: point.x, y: point.y, alpha: point.alpha});\n            return point;\n        };\n    };\n    var getTotalLength = getLengthFactory(1),\n        getPointAtLength = getLengthFactory(),\n        getSubpathsAtLength = getLengthFactory(0, 1);\n    \n    R.getTotalLength = getTotalLength;\n    \n    R.getPointAtLength = getPointAtLength;\n    \n    R.getSubpath = function (path, from, to) {\n        if (this.getTotalLength(path) - to < 1e-6) {\n            return getSubpathsAtLength(path, from).end;\n        }\n        var a = getSubpathsAtLength(path, to, 1);\n        return from ? getSubpathsAtLength(a, from).end : a;\n    };\n    \n    elproto.getTotalLength = function () {\n        if (this.type != \"path\") {return;}\n        if (this.node.getTotalLength) {\n            return this.node.getTotalLength();\n        }\n        return getTotalLength(this.attrs.path);\n    };\n    \n    elproto.getPointAtLength = function (length) {\n        if (this.type != \"path\") {return;}\n        return getPointAtLength(this.attrs.path, length);\n    };\n    \n    elproto.getSubpath = function (from, to) {\n        if (this.type != \"path\") {return;}\n        return R.getSubpath(this.attrs.path, from, to);\n    };\n    \n    var ef = R.easing_formulas = {\n        linear: function (n) {\n            return n;\n        },\n        \"<\": function (n) {\n            return pow(n, 1.7);\n        },\n        \">\": function (n) {\n            return pow(n, .48);\n        },\n        \"<>\": function (n) {\n            var q = .48 - n / 1.04,\n                Q = math.sqrt(.1734 + q * q),\n                x = Q - q,\n                X = pow(abs(x), 1 / 3) * (x < 0 ? -1 : 1),\n                y = -Q - q,\n                Y = pow(abs(y), 1 / 3) * (y < 0 ? -1 : 1),\n                t = X + Y + .5;\n            return (1 - t) * 3 * t * t + t * t * t;\n        },\n        backIn: function (n) {\n            var s = 1.70158;\n            return n * n * ((s + 1) * n - s);\n        },\n        backOut: function (n) {\n            n = n - 1;\n            var s = 1.70158;\n            return n * n * ((s + 1) * n + s) + 1;\n        },\n        elastic: function (n) {\n            if (n == !!n) {\n                return n;\n            }\n            return pow(2, -10 * n) * math.sin((n - .075) * (2 * PI) / .3) + 1;\n        },\n        bounce: function (n) {\n            var s = 7.5625,\n                p = 2.75,\n                l;\n            if (n < (1 / p)) {\n                l = s * n * n;\n            } else {\n                if (n < (2 / p)) {\n                    n -= (1.5 / p);\n                    l = s * n * n + .75;\n                } else {\n                    if (n < (2.5 / p)) {\n                        n -= (2.25 / p);\n                        l = s * n * n + .9375;\n                    } else {\n                        n -= (2.625 / p);\n                        l = s * n * n + .984375;\n                    }\n                }\n            }\n            return l;\n        }\n    };\n    ef.easeIn = ef[\"ease-in\"] = ef[\"<\"];\n    ef.easeOut = ef[\"ease-out\"] = ef[\">\"];\n    ef.easeInOut = ef[\"ease-in-out\"] = ef[\"<>\"];\n    ef[\"back-in\"] = ef.backIn;\n    ef[\"back-out\"] = ef.backOut;\n\n    var animationElements = [],\n        requestAnimFrame = window.requestAnimationFrame       ||\n                           window.webkitRequestAnimationFrame ||\n                           window.mozRequestAnimationFrame    ||\n                           window.oRequestAnimationFrame      ||\n                           window.msRequestAnimationFrame     ||\n                           function (callback) {\n                               setTimeout(callback, 16);\n                           },\n        animation = function () {\n            var Now = +new Date,\n                l = 0;\n            for (; l < animationElements.length; l++) {\n                var e = animationElements[l];\n                if (e.el.removed || e.paused) {\n                    continue;\n                }\n                var time = Now - e.start,\n                    ms = e.ms,\n                    easing = e.easing,\n                    from = e.from,\n                    diff = e.diff,\n                    to = e.to,\n                    t = e.t,\n                    that = e.el,\n                    set = {},\n                    now,\n                    init = {},\n                    key;\n                if (e.initstatus) {\n                    time = (e.initstatus * e.anim.top - e.prev) / (e.percent - e.prev) * ms;\n                    e.status = e.initstatus;\n                    delete e.initstatus;\n                    e.stop && animationElements.splice(l--, 1);\n                } else {\n                    e.status = (e.prev + (e.percent - e.prev) * (time / ms)) / e.anim.top;\n                }\n                if (time < 0) {\n                    continue;\n                }\n                if (time < ms) {\n                    var pos = easing(time / ms);\n                    for (var attr in from) if (from[has](attr)) {\n                        switch (availableAnimAttrs[attr]) {\n                            case nu:\n                                now = +from[attr] + pos * ms * diff[attr];\n                                break;\n                            case \"colour\":\n                                now = \"rgb(\" + [\n                                    upto255(round(from[attr].r + pos * ms * diff[attr].r)),\n                                    upto255(round(from[attr].g + pos * ms * diff[attr].g)),\n                                    upto255(round(from[attr].b + pos * ms * diff[attr].b))\n                                ].join(\",\") + \")\";\n                                break;\n                            case \"path\":\n                                now = [];\n                                for (var i = 0, ii = from[attr].length; i < ii; i++) {\n                                    now[i] = [from[attr][i][0]];\n                                    for (var j = 1, jj = from[attr][i].length; j < jj; j++) {\n                                        now[i][j] = +from[attr][i][j] + pos * ms * diff[attr][i][j];\n                                    }\n                                    now[i] = now[i].join(S);\n                                }\n                                now = now.join(S);\n                                break;\n                            case \"transform\":\n                                if (diff[attr].real) {\n                                    now = [];\n                                    for (i = 0, ii = from[attr].length; i < ii; i++) {\n                                        now[i] = [from[attr][i][0]];\n                                        for (j = 1, jj = from[attr][i].length; j < jj; j++) {\n                                            now[i][j] = from[attr][i][j] + pos * ms * diff[attr][i][j];\n                                        }\n                                    }\n                                } else {\n                                    var get = function (i) {\n                                        return +from[attr][i] + pos * ms * diff[attr][i];\n                                    };\n                                    // now = [[\"r\", get(2), 0, 0], [\"t\", get(3), get(4)], [\"s\", get(0), get(1), 0, 0]];\n                                    now = [[\"m\", get(0), get(1), get(2), get(3), get(4), get(5)]];\n                                }\n                                break;\n                            case \"csv\":\n                                if (attr == \"clip-rect\") {\n                                    now = [];\n                                    i = 4;\n                                    while (i--) {\n                                        now[i] = +from[attr][i] + pos * ms * diff[attr][i];\n                                    }\n                                }\n                                break;\n                            default:\n                                var from2 = [][concat](from[attr]);\n                                now = [];\n                                i = that.paper.customAttributes[attr].length;\n                                while (i--) {\n                                    now[i] = +from2[i] + pos * ms * diff[attr][i];\n                                }\n                                break;\n                        }\n                        set[attr] = now;\n                    }\n                    that.attr(set);\n                    (function (id, that, anim) {\n                        setTimeout(function () {\n                            eve(\"raphael.anim.frame.\" + id, that, anim);\n                        });\n                    })(that.id, that, e.anim);\n                } else {\n                    (function(f, el, a) {\n                        setTimeout(function() {\n                            eve(\"raphael.anim.frame.\" + el.id, el, a);\n                            eve(\"raphael.anim.finish.\" + el.id, el, a);\n                            R.is(f, \"function\") && f.call(el);\n                        });\n                    })(e.callback, that, e.anim);\n                    that.attr(to);\n                    animationElements.splice(l--, 1);\n                    if (e.repeat > 1 && !e.next) {\n                        for (key in to) if (to[has](key)) {\n                            init[key] = e.totalOrigin[key];\n                        }\n                        e.el.attr(init);\n                        runAnimation(e.anim, e.el, e.anim.percents[0], null, e.totalOrigin, e.repeat - 1);\n                    }\n                    if (e.next && !e.stop) {\n                        runAnimation(e.anim, e.el, e.next, null, e.totalOrigin, e.repeat);\n                    }\n                }\n            }\n            R.svg && that && that.paper && that.paper.safari();\n            animationElements.length && requestAnimFrame(animation);\n        },\n        upto255 = function (color) {\n            return color > 255 ? 255 : color < 0 ? 0 : color;\n        };\n    \n    elproto.animateWith = function (el, anim, params, ms, easing, callback) {\n        var element = this;\n        if (element.removed) {\n            callback && callback.call(element);\n            return element;\n        }\n        var a = params instanceof Animation ? params : R.animation(params, ms, easing, callback),\n            x, y;\n        runAnimation(a, element, a.percents[0], null, element.attr());\n        for (var i = 0, ii = animationElements.length; i < ii; i++) {\n            if (animationElements[i].anim == anim && animationElements[i].el == el) {\n                animationElements[ii - 1].start = animationElements[i].start;\n                break;\n            }\n        }\n        return element;\n        // \n        // \n        // var a = params ? R.animation(params, ms, easing, callback) : anim,\n        //     status = element.status(anim);\n        // return this.animate(a).status(a, status * anim.ms / a.ms);\n    };\n    function CubicBezierAtTime(t, p1x, p1y, p2x, p2y, duration) {\n        var cx = 3 * p1x,\n            bx = 3 * (p2x - p1x) - cx,\n            ax = 1 - cx - bx,\n            cy = 3 * p1y,\n            by = 3 * (p2y - p1y) - cy,\n            ay = 1 - cy - by;\n        function sampleCurveX(t) {\n            return ((ax * t + bx) * t + cx) * t;\n        }\n        function solve(x, epsilon) {\n            var t = solveCurveX(x, epsilon);\n            return ((ay * t + by) * t + cy) * t;\n        }\n        function solveCurveX(x, epsilon) {\n            var t0, t1, t2, x2, d2, i;\n            for(t2 = x, i = 0; i < 8; i++) {\n                x2 = sampleCurveX(t2) - x;\n                if (abs(x2) < epsilon) {\n                    return t2;\n                }\n                d2 = (3 * ax * t2 + 2 * bx) * t2 + cx;\n                if (abs(d2) < 1e-6) {\n                    break;\n                }\n                t2 = t2 - x2 / d2;\n            }\n            t0 = 0;\n            t1 = 1;\n            t2 = x;\n            if (t2 < t0) {\n                return t0;\n            }\n            if (t2 > t1) {\n                return t1;\n            }\n            while (t0 < t1) {\n                x2 = sampleCurveX(t2);\n                if (abs(x2 - x) < epsilon) {\n                    return t2;\n                }\n                if (x > x2) {\n                    t0 = t2;\n                } else {\n                    t1 = t2;\n                }\n                t2 = (t1 - t0) / 2 + t0;\n            }\n            return t2;\n        }\n        return solve(t, 1 / (200 * duration));\n    }\n    elproto.onAnimation = function (f) {\n        f ? eve.on(\"raphael.anim.frame.\" + this.id, f) : eve.unbind(\"raphael.anim.frame.\" + this.id);\n        return this;\n    };\n    function Animation(anim, ms) {\n        var percents = [],\n            newAnim = {};\n        this.ms = ms;\n        this.times = 1;\n        if (anim) {\n            for (var attr in anim) if (anim[has](attr)) {\n                newAnim[toFloat(attr)] = anim[attr];\n                percents.push(toFloat(attr));\n            }\n            percents.sort(sortByNumber);\n        }\n        this.anim = newAnim;\n        this.top = percents[percents.length - 1];\n        this.percents = percents;\n    }\n    \n    Animation.prototype.delay = function (delay) {\n        var a = new Animation(this.anim, this.ms);\n        a.times = this.times;\n        a.del = +delay || 0;\n        return a;\n    };\n    \n    Animation.prototype.repeat = function (times) { \n        var a = new Animation(this.anim, this.ms);\n        a.del = this.del;\n        a.times = math.floor(mmax(times, 0)) || 1;\n        return a;\n    };\n    function runAnimation(anim, element, percent, status, totalOrigin, times) {\n        percent = toFloat(percent);\n        var params,\n            isInAnim,\n            isInAnimSet,\n            percents = [],\n            next,\n            prev,\n            timestamp,\n            ms = anim.ms,\n            from = {},\n            to = {},\n            diff = {};\n        if (status) {\n            for (i = 0, ii = animationElements.length; i < ii; i++) {\n                var e = animationElements[i];\n                if (e.el.id == element.id && e.anim == anim) {\n                    if (e.percent != percent) {\n                        animationElements.splice(i, 1);\n                        isInAnimSet = 1;\n                    } else {\n                        isInAnim = e;\n                    }\n                    element.attr(e.totalOrigin);\n                    break;\n                }\n            }\n        } else {\n            status = +to; // NaN\n        }\n        for (var i = 0, ii = anim.percents.length; i < ii; i++) {\n            if (anim.percents[i] == percent || anim.percents[i] > status * anim.top) {\n                percent = anim.percents[i];\n                prev = anim.percents[i - 1] || 0;\n                ms = ms / anim.top * (percent - prev);\n                next = anim.percents[i + 1];\n                params = anim.anim[percent];\n                break;\n            } else if (status) {\n                element.attr(anim.anim[anim.percents[i]]);\n            }\n        }\n        if (!params) {\n            return;\n        }\n        if (!isInAnim) {\n            for (var attr in params) if (params[has](attr)) {\n                if (availableAnimAttrs[has](attr) || element.paper.customAttributes[has](attr)) {\n                    from[attr] = element.attr(attr);\n                    (from[attr] == null) && (from[attr] = availableAttrs[attr]);\n                    to[attr] = params[attr];\n                    switch (availableAnimAttrs[attr]) {\n                        case nu:\n                            diff[attr] = (to[attr] - from[attr]) / ms;\n                            break;\n                        case \"colour\":\n                            from[attr] = R.getRGB(from[attr]);\n                            var toColour = R.getRGB(to[attr]);\n                            diff[attr] = {\n                                r: (toColour.r - from[attr].r) / ms,\n                                g: (toColour.g - from[attr].g) / ms,\n                                b: (toColour.b - from[attr].b) / ms\n                            };\n                            break;\n                        case \"path\":\n                            var pathes = path2curve(from[attr], to[attr]),\n                                toPath = pathes[1];\n                            from[attr] = pathes[0];\n                            diff[attr] = [];\n                            for (i = 0, ii = from[attr].length; i < ii; i++) {\n                                diff[attr][i] = [0];\n                                for (var j = 1, jj = from[attr][i].length; j < jj; j++) {\n                                    diff[attr][i][j] = (toPath[i][j] - from[attr][i][j]) / ms;\n                                }\n                            }\n                            break;\n                        case \"transform\":\n                            var _ = element._,\n                                eq = equaliseTransform(_[attr], to[attr]);\n                            if (eq) {\n                                from[attr] = eq.from;\n                                to[attr] = eq.to;\n                                diff[attr] = [];\n                                diff[attr].real = true;\n                                for (i = 0, ii = from[attr].length; i < ii; i++) {\n                                    diff[attr][i] = [from[attr][i][0]];\n                                    for (j = 1, jj = from[attr][i].length; j < jj; j++) {\n                                        diff[attr][i][j] = (to[attr][i][j] - from[attr][i][j]) / ms;\n                                    }\n                                }\n                            } else {\n                                var m = (element.matrix || new Matrix),\n                                    to2 = {\n                                        _: {transform: _.transform},\n                                        getBBox: function () {\n                                            return element.getBBox(1);\n                                        }\n                                    };\n                                from[attr] = [\n                                    m.a,\n                                    m.b,\n                                    m.c,\n                                    m.d,\n                                    m.e,\n                                    m.f\n                                ];\n                                extractTransform(to2, to[attr]);\n                                to[attr] = to2._.transform;\n                                diff[attr] = [\n                                    (to2.matrix.a - m.a) / ms,\n                                    (to2.matrix.b - m.b) / ms,\n                                    (to2.matrix.c - m.c) / ms,\n                                    (to2.matrix.d - m.d) / ms,\n                                    (to2.matrix.e - m.e) / ms,\n                                    (to2.matrix.f - m.f) / ms\n                                ];\n                                // from[attr] = [_.sx, _.sy, _.deg, _.dx, _.dy];\n                                // var to2 = {_:{}, getBBox: function () { return element.getBBox(); }};\n                                // extractTransform(to2, to[attr]);\n                                // diff[attr] = [\n                                //     (to2._.sx - _.sx) / ms,\n                                //     (to2._.sy - _.sy) / ms,\n                                //     (to2._.deg - _.deg) / ms,\n                                //     (to2._.dx - _.dx) / ms,\n                                //     (to2._.dy - _.dy) / ms\n                                // ];\n                            }\n                            break;\n                        case \"csv\":\n                            var values = Str(params[attr])[split](separator),\n                                from2 = Str(from[attr])[split](separator);\n                            if (attr == \"clip-rect\") {\n                                from[attr] = from2;\n                                diff[attr] = [];\n                                i = from2.length;\n                                while (i--) {\n                                    diff[attr][i] = (values[i] - from[attr][i]) / ms;\n                                }\n                            }\n                            to[attr] = values;\n                            break;\n                        default:\n                            values = [][concat](params[attr]);\n                            from2 = [][concat](from[attr]);\n                            diff[attr] = [];\n                            i = element.paper.customAttributes[attr].length;\n                            while (i--) {\n                                diff[attr][i] = ((values[i] || 0) - (from2[i] || 0)) / ms;\n                            }\n                            break;\n                    }\n                }\n            }\n            var easing = params.easing,\n                easyeasy = R.easing_formulas[easing];\n            if (!easyeasy) {\n                easyeasy = Str(easing).match(bezierrg);\n                if (easyeasy && easyeasy.length == 5) {\n                    var curve = easyeasy;\n                    easyeasy = function (t) {\n                        return CubicBezierAtTime(t, +curve[1], +curve[2], +curve[3], +curve[4], ms);\n                    };\n                } else {\n                    easyeasy = pipe;\n                }\n            }\n            timestamp = params.start || anim.start || +new Date;\n            e = {\n                anim: anim,\n                percent: percent,\n                timestamp: timestamp,\n                start: timestamp + (anim.del || 0),\n                status: 0,\n                initstatus: status || 0,\n                stop: false,\n                ms: ms,\n                easing: easyeasy,\n                from: from,\n                diff: diff,\n                to: to,\n                el: element,\n                callback: params.callback,\n                prev: prev,\n                next: next,\n                repeat: times || anim.times,\n                origin: element.attr(),\n                totalOrigin: totalOrigin\n            };\n            animationElements.push(e);\n            if (status && !isInAnim && !isInAnimSet) {\n                e.stop = true;\n                e.start = new Date - ms * status;\n                if (animationElements.length == 1) {\n                    return animation();\n                }\n            }\n            if (isInAnimSet) {\n                e.start = new Date - e.ms * status;\n            }\n            animationElements.length == 1 && requestAnimFrame(animation);\n        } else {\n            isInAnim.initstatus = status;\n            isInAnim.start = new Date - isInAnim.ms * status;\n        }\n        eve(\"raphael.anim.start.\" + element.id, element, anim);\n    }\n    \n    R.animation = function (params, ms, easing, callback) {\n        if (params instanceof Animation) {\n            return params;\n        }\n        if (R.is(easing, \"function\") || !easing) {\n            callback = callback || easing || null;\n            easing = null;\n        }\n        params = Object(params);\n        ms = +ms || 0;\n        var p = {},\n            json,\n            attr;\n        for (attr in params) if (params[has](attr) && toFloat(attr) != attr && toFloat(attr) + \"%\" != attr) {\n            json = true;\n            p[attr] = params[attr];\n        }\n        if (!json) {\n            return new Animation(params, ms);\n        } else {\n            easing && (p.easing = easing);\n            callback && (p.callback = callback);\n            return new Animation({100: p}, ms);\n        }\n    };\n    \n    elproto.animate = function (params, ms, easing, callback) {\n        var element = this;\n        if (element.removed) {\n            callback && callback.call(element);\n            return element;\n        }\n        var anim = params instanceof Animation ? params : R.animation(params, ms, easing, callback);\n        runAnimation(anim, element, anim.percents[0], null, element.attr());\n        return element;\n    };\n    \n    elproto.setTime = function (anim, value) {\n        if (anim && value != null) {\n            this.status(anim, mmin(value, anim.ms) / anim.ms);\n        }\n        return this;\n    };\n    \n    elproto.status = function (anim, value) {\n        var out = [],\n            i = 0,\n            len,\n            e;\n        if (value != null) {\n            runAnimation(anim, this, -1, mmin(value, 1));\n            return this;\n        } else {\n            len = animationElements.length;\n            for (; i < len; i++) {\n                e = animationElements[i];\n                if (e.el.id == this.id && (!anim || e.anim == anim)) {\n                    if (anim) {\n                        return e.status;\n                    }\n                    out.push({\n                        anim: e.anim,\n                        status: e.status\n                    });\n                }\n            }\n            if (anim) {\n                return 0;\n            }\n            return out;\n        }\n    };\n    \n    elproto.pause = function (anim) {\n        for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) {\n            if (eve(\"raphael.anim.pause.\" + this.id, this, animationElements[i].anim) !== false) {\n                animationElements[i].paused = true;\n            }\n        }\n        return this;\n    };\n    \n    elproto.resume = function (anim) {\n        for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) {\n            var e = animationElements[i];\n            if (eve(\"raphael.anim.resume.\" + this.id, this, e.anim) !== false) {\n                delete e.paused;\n                this.status(e.anim, e.status);\n            }\n        }\n        return this;\n    };\n    \n    elproto.stop = function (anim) {\n        for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) {\n            if (eve(\"raphael.anim.stop.\" + this.id, this, animationElements[i].anim) !== false) {\n                animationElements.splice(i--, 1);\n            }\n        }\n        return this;\n    };\n    function stopAnimation(paper) {\n        for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.paper == paper) {\n            animationElements.splice(i--, 1);\n        }\n    }\n    eve.on(\"raphael.remove\", stopAnimation);\n    eve.on(\"raphael.clear\", stopAnimation);\n    elproto.toString = function () {\n        return \"Rapha\\xebl\\u2019s object\";\n    };\n\n    // Set\n    var Set = function (items) {\n        this.items = [];\n        this.length = 0;\n        this.type = \"set\";\n        if (items) {\n            for (var i = 0, ii = items.length; i < ii; i++) {\n                if (items[i] && (items[i].constructor == elproto.constructor || items[i].constructor == Set)) {\n                    this[this.items.length] = this.items[this.items.length] = items[i];\n                    this.length++;\n                }\n            }\n        }\n    },\n    setproto = Set.prototype;\n    \n    setproto.push = function () {\n        var item,\n            len;\n        for (var i = 0, ii = arguments.length; i < ii; i++) {\n            item = arguments[i];\n            if (item && (item.constructor == elproto.constructor || item.constructor == Set)) {\n                len = this.items.length;\n                this[len] = this.items[len] = item;\n                this.length++;\n            }\n        }\n        return this;\n    };\n    \n    setproto.pop = function () {\n        this.length && delete this[this.length--];\n        return this.items.pop();\n    };\n    \n    setproto.forEach = function (callback, thisArg) {\n        for (var i = 0, ii = this.items.length; i < ii; i++) {\n            if (callback.call(thisArg, this.items[i], i) === false) {\n                return this;\n            }\n        }\n        return this;\n    };\n    for (var method in elproto) if (elproto[has](method)) {\n        setproto[method] = (function (methodname) {\n            return function () {\n                var arg = arguments;\n                return this.forEach(function (el) {\n                    el[methodname][apply](el, arg);\n                });\n            };\n        })(method);\n    }\n    setproto.attr = function (name, value) {\n        if (name && R.is(name, array) && R.is(name[0], \"object\")) {\n            for (var j = 0, jj = name.length; j < jj; j++) {\n                this.items[j].attr(name[j]);\n            }\n        } else {\n            for (var i = 0, ii = this.items.length; i < ii; i++) {\n                this.items[i].attr(name, value);\n            }\n        }\n        return this;\n    };\n    \n    setproto.clear = function () {\n        while (this.length) {\n            this.pop();\n        }\n    };\n    \n    setproto.splice = function (index, count, insertion) {\n        index = index < 0 ? mmax(this.length + index, 0) : index;\n        count = mmax(0, mmin(this.length - index, count));\n        var tail = [],\n            todel = [],\n            args = [],\n            i;\n        for (i = 2; i < arguments.length; i++) {\n            args.push(arguments[i]);\n        }\n        for (i = 0; i < count; i++) {\n            todel.push(this[index + i]);\n        }\n        for (; i < this.length - index; i++) {\n            tail.push(this[index + i]);\n        }\n        var arglen = args.length;\n        for (i = 0; i < arglen + tail.length; i++) {\n            this.items[index + i] = this[index + i] = i < arglen ? args[i] : tail[i - arglen];\n        }\n        i = this.items.length = this.length -= count - arglen;\n        while (this[i]) {\n            delete this[i++];\n        }\n        return new Set(todel);\n    };\n    \n    setproto.exclude = function (el) {\n        for (var i = 0, ii = this.length; i < ii; i++) if (this[i] == el) {\n            this.splice(i, 1);\n            return true;\n        }\n    };\n    setproto.animate = function (params, ms, easing, callback) {\n        (R.is(easing, \"function\") || !easing) && (callback = easing || null);\n        var len = this.items.length,\n            i = len,\n            item,\n            set = this,\n            collector;\n        if (!len) {\n            return this;\n        }\n        callback && (collector = function () {\n            !--len && callback.call(set);\n        });\n        easing = R.is(easing, string) ? easing : collector;\n        var anim = R.animation(params, ms, easing, collector);\n        item = this.items[--i].animate(anim);\n        while (i--) {\n            this.items[i] && !this.items[i].removed && this.items[i].animateWith(item, anim, anim);\n        }\n        return this;\n    };\n    setproto.insertAfter = function (el) {\n        var i = this.items.length;\n        while (i--) {\n            this.items[i].insertAfter(el);\n        }\n        return this;\n    };\n    setproto.getBBox = function () {\n        var x = [],\n            y = [],\n            x2 = [],\n            y2 = [];\n        for (var i = this.items.length; i--;) if (!this.items[i].removed) {\n            var box = this.items[i].getBBox();\n            x.push(box.x);\n            y.push(box.y);\n            x2.push(box.x + box.width);\n            y2.push(box.y + box.height);\n        }\n        x = mmin[apply](0, x);\n        y = mmin[apply](0, y);\n        x2 = mmax[apply](0, x2);\n        y2 = mmax[apply](0, y2);\n        return {\n            x: x,\n            y: y,\n            x2: x2,\n            y2: y2,\n            width: x2 - x,\n            height: y2 - y\n        };\n    };\n    setproto.clone = function (s) {\n        s = new Set;\n        for (var i = 0, ii = this.items.length; i < ii; i++) {\n            s.push(this.items[i].clone());\n        }\n        return s;\n    };\n    setproto.toString = function () {\n        return \"Rapha\\xebl\\u2018s set\";\n    };\n\n    \n    R.registerFont = function (font) {\n        if (!font.face) {\n            return font;\n        }\n        this.fonts = this.fonts || {};\n        var fontcopy = {\n                w: font.w,\n                face: {},\n                glyphs: {}\n            },\n            family = font.face[\"font-family\"];\n        for (var prop in font.face) if (font.face[has](prop)) {\n            fontcopy.face[prop] = font.face[prop];\n        }\n        if (this.fonts[family]) {\n            this.fonts[family].push(fontcopy);\n        } else {\n            this.fonts[family] = [fontcopy];\n        }\n        if (!font.svg) {\n            fontcopy.face[\"units-per-em\"] = toInt(font.face[\"units-per-em\"], 10);\n            for (var glyph in font.glyphs) if (font.glyphs[has](glyph)) {\n                var path = font.glyphs[glyph];\n                fontcopy.glyphs[glyph] = {\n                    w: path.w,\n                    k: {},\n                    d: path.d && \"M\" + path.d.replace(/[mlcxtrv]/g, function (command) {\n                            return {l: \"L\", c: \"C\", x: \"z\", t: \"m\", r: \"l\", v: \"c\"}[command] || \"M\";\n                        }) + \"z\"\n                };\n                if (path.k) {\n                    for (var k in path.k) if (path[has](k)) {\n                        fontcopy.glyphs[glyph].k[k] = path.k[k];\n                    }\n                }\n            }\n        }\n        return font;\n    };\n    \n    paperproto.getFont = function (family, weight, style, stretch) {\n        stretch = stretch || \"normal\";\n        style = style || \"normal\";\n        weight = +weight || {normal: 400, bold: 700, lighter: 300, bolder: 800}[weight] || 400;\n        if (!R.fonts) {\n            return;\n        }\n        var font = R.fonts[family];\n        if (!font) {\n            var name = new RegExp(\"(^|\\\\s)\" + family.replace(/[^\\w\\d\\s+!~.:_-]/g, E) + \"(\\\\s|$)\", \"i\");\n            for (var fontName in R.fonts) if (R.fonts[has](fontName)) {\n                if (name.test(fontName)) {\n                    font = R.fonts[fontName];\n                    break;\n                }\n            }\n        }\n        var thefont;\n        if (font) {\n            for (var i = 0, ii = font.length; i < ii; i++) {\n                thefont = font[i];\n                if (thefont.face[\"font-weight\"] == weight && (thefont.face[\"font-style\"] == style || !thefont.face[\"font-style\"]) && thefont.face[\"font-stretch\"] == stretch) {\n                    break;\n                }\n            }\n        }\n        return thefont;\n    };\n    \n    paperproto.print = function (x, y, string, font, size, origin, letter_spacing) {\n        origin = origin || \"middle\"; // baseline|middle\n        letter_spacing = mmax(mmin(letter_spacing || 0, 1), -1);\n        var letters = Str(string)[split](E),\n            shift = 0,\n            notfirst = 0,\n            path = E,\n            scale;\n        R.is(font, string) && (font = this.getFont(font));\n        if (font) {\n            scale = (size || 16) / font.face[\"units-per-em\"];\n            var bb = font.face.bbox[split](separator),\n                top = +bb[0],\n                lineHeight = bb[3] - bb[1],\n                shifty = 0,\n                height = +bb[1] + (origin == \"baseline\" ? lineHeight + (+font.face.descent) : lineHeight / 2);\n            for (var i = 0, ii = letters.length; i < ii; i++) {\n                if (letters[i] == \"\\n\") {\n                    shift = 0;\n                    curr = 0;\n                    notfirst = 0;\n                    shifty += lineHeight;\n                } else {\n                    var prev = notfirst && font.glyphs[letters[i - 1]] || {},\n                        curr = font.glyphs[letters[i]];\n                    shift += notfirst ? (prev.w || font.w) + (prev.k && prev.k[letters[i]] || 0) + (font.w * letter_spacing) : 0;\n                    notfirst = 1;\n                }\n                if (curr && curr.d) {\n                    path += R.transformPath(curr.d, [\"t\", shift * scale, shifty * scale, \"s\", scale, scale, top, height, \"t\", (x - top) / scale, (y - height) / scale]);\n                }\n            }\n        }\n        return this.path(path).attr({\n            fill: \"#000\",\n            stroke: \"none\"\n        });\n    };\n\n    \n    paperproto.add = function (json) {\n        if (R.is(json, \"array\")) {\n            var res = this.set(),\n                i = 0,\n                ii = json.length,\n                j;\n            for (; i < ii; i++) {\n                j = json[i] || {};\n                elements[has](j.type) && res.push(this[j.type]().attr(j));\n            }\n        }\n        return res;\n    };\n\n    \n    R.format = function (token, params) {\n        var args = R.is(params, array) ? [0][concat](params) : arguments;\n        token && R.is(token, string) && args.length - 1 && (token = token.replace(formatrg, function (str, i) {\n            return args[++i] == null ? E : args[i];\n        }));\n        return token || E;\n    };\n    \n    R.fullfill = (function () {\n        var tokenRegex = /\\{([^\\}]+)\\}/g,\n            objNotationRegex = /(?:(?:^|\\.)(.+?)(?=\\[|\\.|$|\\()|\\[('|\")(.+?)\\2\\])(\\(\\))?/g, // matches .xxxxx or [\"xxxxx\"] to run over object properties\n            replacer = function (all, key, obj) {\n                var res = obj;\n                key.replace(objNotationRegex, function (all, name, quote, quotedName, isFunc) {\n                    name = name || quotedName;\n                    if (res) {\n                        if (name in res) {\n                            res = res[name];\n                        }\n                        typeof res == \"function\" && isFunc && (res = res());\n                    }\n                });\n                res = (res == null || res == obj ? all : res) + \"\";\n                return res;\n            };\n        return function (str, obj) {\n            return String(str).replace(tokenRegex, function (all, key) {\n                return replacer(all, key, obj);\n            });\n        };\n    })();\n    \n    R.ninja = function () {\n        oldRaphael.was ? (g.win.Raphael = oldRaphael.is) : delete Raphael;\n        return R;\n    };\n    \n    R.st = setproto;\n    // Firefox <3.6 fix: http://webreflection.blogspot.com/2009/11/195-chars-to-help-lazy-loading.html\n    (function (doc, loaded, f) {\n        if (doc.readyState == null && doc.addEventListener){\n            doc.addEventListener(loaded, f = function () {\n                doc.removeEventListener(loaded, f, false);\n                doc.readyState = \"complete\";\n            }, false);\n            doc.readyState = \"loading\";\n        }\n        function isLoaded() {\n            (/in/).test(doc.readyState) ? setTimeout(isLoaded, 9) : R.eve(\"raphael.DOMload\");\n        }\n        isLoaded();\n    })(document, \"DOMContentLoaded\");\n\n    oldRaphael.was ? (g.win.Raphael = R) : (Raphael = R);\n    \n    eve.on(\"raphael.DOMload\", function () {\n        loaded = true;\n    });\n})();\n\n\n// ┌─────────────────────────────────────────────────────────────────────┐ \\\\\n// │ Raphaël - JavaScript Vector Library                                 │ \\\\\n// ├─────────────────────────────────────────────────────────────────────┤ \\\\\n// │ SVG Module                                                          │ \\\\\n// ├─────────────────────────────────────────────────────────────────────┤ \\\\\n// │ Copyright (c) 2008-2011 Dmitry Baranovskiy (http://raphaeljs.com)   │ \\\\\n// │ Copyright (c) 2008-2011 Sencha Labs (http://sencha.com)             │ \\\\\n// │ Licensed under the MIT (http://raphaeljs.com/license.html) license. │ \\\\\n// └─────────────────────────────────────────────────────────────────────┘ \\\\\nwindow.Raphael.svg && function (R) {\n    var has = \"hasOwnProperty\",\n        Str = String,\n        toFloat = parseFloat,\n        toInt = parseInt,\n        math = Math,\n        mmax = math.max,\n        abs = math.abs,\n        pow = math.pow,\n        separator = /[, ]+/,\n        eve = R.eve,\n        E = \"\",\n        S = \" \";\n    var xlink = \"http://www.w3.org/1999/xlink\",\n        markers = {\n            block: \"M5,0 0,2.5 5,5z\",\n            classic: \"M5,0 0,2.5 5,5 3.5,3 3.5,2z\",\n            diamond: \"M2.5,0 5,2.5 2.5,5 0,2.5z\",\n            open: \"M6,1 1,3.5 6,6\",\n            oval: \"M2.5,0A2.5,2.5,0,0,1,2.5,5 2.5,2.5,0,0,1,2.5,0z\"\n        },\n        markerCounter = {};\n    R.toString = function () {\n        return  \"Your browser supports SVG.\\nYou are running Rapha\\xebl \" + this.version;\n    };\n    var $ = function (el, attr) {\n        if (attr) {\n            if (typeof el == \"string\") {\n                el = $(el);\n            }\n            for (var key in attr) if (attr[has](key)) {\n                if (key.substring(0, 6) == \"xlink:\") {\n                    el.setAttributeNS(xlink, key.substring(6), Str(attr[key]));\n                } else {\n                    el.setAttribute(key, Str(attr[key]));\n                }\n            }\n        } else {\n            el = R._g.doc.createElementNS(\"http://www.w3.org/2000/svg\", el);\n            el.style && (el.style.webkitTapHighlightColor = \"rgba(0,0,0,0)\");\n        }\n        return el;\n    },\n    addGradientFill = function (element, gradient) {\n        var type = \"linear\",\n            id = element.id + gradient,\n            fx = .5, fy = .5,\n            o = element.node,\n            SVG = element.paper,\n            s = o.style,\n            el = R._g.doc.getElementById(id);\n        if (!el) {\n            gradient = Str(gradient).replace(R._radial_gradient, function (all, _fx, _fy) {\n                type = \"radial\";\n                if (_fx && _fy) {\n                    fx = toFloat(_fx);\n                    fy = toFloat(_fy);\n                    var dir = ((fy > .5) * 2 - 1);\n                    pow(fx - .5, 2) + pow(fy - .5, 2) > .25 &&\n                        (fy = math.sqrt(.25 - pow(fx - .5, 2)) * dir + .5) &&\n                        fy != .5 &&\n                        (fy = fy.toFixed(5) - 1e-5 * dir);\n                }\n                return E;\n            });\n            gradient = gradient.split(/\\s*\\-\\s*/);\n            if (type == \"linear\") {\n                var angle = gradient.shift();\n                angle = -toFloat(angle);\n                if (isNaN(angle)) {\n                    return null;\n                }\n                var vector = [0, 0, math.cos(R.rad(angle)), math.sin(R.rad(angle))],\n                    max = 1 / (mmax(abs(vector[2]), abs(vector[3])) || 1);\n                vector[2] *= max;\n                vector[3] *= max;\n                if (vector[2] < 0) {\n                    vector[0] = -vector[2];\n                    vector[2] = 0;\n                }\n                if (vector[3] < 0) {\n                    vector[1] = -vector[3];\n                    vector[3] = 0;\n                }\n            }\n            var dots = R._parseDots(gradient);\n            if (!dots) {\n                return null;\n            }\n            id = id.replace(/[\\(\\)\\s,\\xb0#]/g, \"_\");\n            \n            if (element.gradient && id != element.gradient.id) {\n                SVG.defs.removeChild(element.gradient);\n                delete element.gradient;\n            }\n\n            if (!element.gradient) {\n                el = $(type + \"Gradient\", {id: id});\n                element.gradient = el;\n                $(el, type == \"radial\" ? {\n                    fx: fx,\n                    fy: fy\n                } : {\n                    x1: vector[0],\n                    y1: vector[1],\n                    x2: vector[2],\n                    y2: vector[3],\n                    gradientTransform: element.matrix.invert()\n                });\n                SVG.defs.appendChild(el);\n                for (var i = 0, ii = dots.length; i < ii; i++) {\n                    el.appendChild($(\"stop\", {\n                        offset: dots[i].offset ? dots[i].offset : i ? \"100%\" : \"0%\",\n                        \"stop-color\": dots[i].color || \"#fff\"\n                    }));\n                }\n            }\n        }\n        $(o, {\n            fill: \"url(#\" + id + \")\",\n            opacity: 1,\n            \"fill-opacity\": 1\n        });\n        s.fill = E;\n        s.opacity = 1;\n        s.fillOpacity = 1;\n        return 1;\n    },\n    updatePosition = function (o) {\n        var bbox = o.getBBox(1);\n        $(o.pattern, {patternTransform: o.matrix.invert() + \" translate(\" + bbox.x + \",\" + bbox.y + \")\"});\n    },\n    addArrow = function (o, value, isEnd) {\n        if (o.type == \"path\") {\n            var values = Str(value).toLowerCase().split(\"-\"),\n                p = o.paper,\n                se = isEnd ? \"end\" : \"start\",\n                node = o.node,\n                attrs = o.attrs,\n                stroke = attrs[\"stroke-width\"],\n                i = values.length,\n                type = \"classic\",\n                from,\n                to,\n                dx,\n                refX,\n                attr,\n                w = 3,\n                h = 3,\n                t = 5;\n            while (i--) {\n                switch (values[i]) {\n                    case \"block\":\n                    case \"classic\":\n                    case \"oval\":\n                    case \"diamond\":\n                    case \"open\":\n                    case \"none\":\n                        type = values[i];\n                        break;\n                    case \"wide\": h = 5; break;\n                    case \"narrow\": h = 2; break;\n                    case \"long\": w = 5; break;\n                    case \"short\": w = 2; break;\n                }\n            }\n            if (type == \"open\") {\n                w += 2;\n                h += 2;\n                t += 2;\n                dx = 1;\n                refX = isEnd ? 4 : 1;\n                attr = {\n                    fill: \"none\",\n                    stroke: attrs.stroke\n                };\n            } else {\n                refX = dx = w / 2;\n                attr = {\n                    fill: attrs.stroke,\n                    stroke: \"none\"\n                };\n            }\n            if (o._.arrows) {\n                if (isEnd) {\n                    o._.arrows.endPath && markerCounter[o._.arrows.endPath]--;\n                    o._.arrows.endMarker && markerCounter[o._.arrows.endMarker]--;\n                } else {\n                    o._.arrows.startPath && markerCounter[o._.arrows.startPath]--;\n                    o._.arrows.startMarker && markerCounter[o._.arrows.startMarker]--;\n                }\n            } else {\n                o._.arrows = {};\n            }\n            if (type != \"none\") {\n                var pathId = \"raphael-marker-\" + type,\n                    markerId = \"raphael-marker-\" + se + type + w + h;\n                if (!R._g.doc.getElementById(pathId)) {\n                    p.defs.appendChild($($(\"path\"), {\n                        \"stroke-linecap\": \"round\",\n                        d: markers[type],\n                        id: pathId\n                    }));\n                    markerCounter[pathId] = 1;\n                } else {\n                    markerCounter[pathId]++;\n                }\n                var marker = R._g.doc.getElementById(markerId),\n                    use;\n                if (!marker) {\n                    marker = $($(\"marker\"), {\n                        id: markerId,\n                        markerHeight: h,\n                        markerWidth: w,\n                        orient: \"auto\",\n                        refX: refX,\n                        refY: h / 2\n                    });\n                    use = $($(\"use\"), {\n                        \"xlink:href\": \"#\" + pathId,\n                        transform: (isEnd ? \"rotate(180 \" + w / 2 + \" \" + h / 2 + \") \" : E) + \"scale(\" + w / t + \",\" + h / t + \")\",\n                        \"stroke-width\": (1 / ((w / t + h / t) / 2)).toFixed(4)\n                    });\n                    marker.appendChild(use);\n                    p.defs.appendChild(marker);\n                    markerCounter[markerId] = 1;\n                } else {\n                    markerCounter[markerId]++;\n                    use = marker.getElementsByTagName(\"use\")[0];\n                }\n                $(use, attr);\n                var delta = dx * (type != \"diamond\" && type != \"oval\");\n                if (isEnd) {\n                    from = o._.arrows.startdx * stroke || 0;\n                    to = R.getTotalLength(attrs.path) - delta * stroke;\n                } else {\n                    from = delta * stroke;\n                    to = R.getTotalLength(attrs.path) - (o._.arrows.enddx * stroke || 0);\n                }\n                attr = {};\n                attr[\"marker-\" + se] = \"url(#\" + markerId + \")\";\n                if (to || from) {\n                    attr.d = Raphael.getSubpath(attrs.path, from, to);\n                }\n                $(node, attr);\n                o._.arrows[se + \"Path\"] = pathId;\n                o._.arrows[se + \"Marker\"] = markerId;\n                o._.arrows[se + \"dx\"] = delta;\n                o._.arrows[se + \"Type\"] = type;\n                o._.arrows[se + \"String\"] = value;\n            } else {\n                if (isEnd) {\n                    from = o._.arrows.startdx * stroke || 0;\n                    to = R.getTotalLength(attrs.path) - from;\n                } else {\n                    from = 0;\n                    to = R.getTotalLength(attrs.path) - (o._.arrows.enddx * stroke || 0);\n                }\n                o._.arrows[se + \"Path\"] && $(node, {d: Raphael.getSubpath(attrs.path, from, to)});\n                delete o._.arrows[se + \"Path\"];\n                delete o._.arrows[se + \"Marker\"];\n                delete o._.arrows[se + \"dx\"];\n                delete o._.arrows[se + \"Type\"];\n                delete o._.arrows[se + \"String\"];\n            }\n            for (attr in markerCounter) if (markerCounter[has](attr) && !markerCounter[attr]) {\n                var item = R._g.doc.getElementById(attr);\n                item && item.parentNode.removeChild(item);\n            }\n        }\n    },\n    dasharray = {\n        \"\": [0],\n        \"none\": [0],\n        \"-\": [3, 1],\n        \".\": [1, 1],\n        \"-.\": [3, 1, 1, 1],\n        \"-..\": [3, 1, 1, 1, 1, 1],\n        \". \": [1, 3],\n        \"- \": [4, 3],\n        \"--\": [8, 3],\n        \"- .\": [4, 3, 1, 3],\n        \"--.\": [8, 3, 1, 3],\n        \"--..\": [8, 3, 1, 3, 1, 3]\n    },\n    addDashes = function (o, value, params) {\n        value = dasharray[Str(value).toLowerCase()];\n        if (value) {\n            var width = o.attrs[\"stroke-width\"] || \"1\",\n                butt = {round: width, square: width, butt: 0}[o.attrs[\"stroke-linecap\"] || params[\"stroke-linecap\"]] || 0,\n                dashes = [],\n                i = value.length;\n            while (i--) {\n                dashes[i] = value[i] * width + ((i % 2) ? 1 : -1) * butt;\n            }\n            $(o.node, {\"stroke-dasharray\": dashes.join(\",\")});\n        }\n    },\n    setFillAndStroke = function (o, params) {\n        var node = o.node,\n            attrs = o.attrs,\n            vis = node.style.visibility;\n        node.style.visibility = \"hidden\";\n        for (var att in params) {\n            if (params[has](att)) {\n                if (!R._availableAttrs[has](att)) {\n                    continue;\n                }\n                var value = params[att];\n                attrs[att] = value;\n                switch (att) {\n                    case \"blur\":\n                        o.blur(value);\n                        break;\n                    case \"href\":\n                    case \"title\":\n                    case \"target\":\n                        var pn = node.parentNode;\n                        if (pn.tagName.toLowerCase() != \"a\") {\n                            var hl = $(\"a\");\n                            pn.insertBefore(hl, node);\n                            hl.appendChild(node);\n                            pn = hl;\n                        }\n                        if (att == \"target\") {\n                            pn.setAttributeNS(xlink, \"show\", value == \"blank\" ? \"new\" : value);\n                        } else {\n                            pn.setAttributeNS(xlink, att, value);\n                        }\n                        break;\n                    case \"cursor\":\n                        node.style.cursor = value;\n                        break;\n                    case \"transform\":\n                        o.transform(value);\n                        break;\n                    case \"arrow-start\":\n                        addArrow(o, value);\n                        break;\n                    case \"arrow-end\":\n                        addArrow(o, value, 1);\n                        break;\n                    case \"clip-rect\":\n                        var rect = Str(value).split(separator);\n                        if (rect.length == 4) {\n                            o.clip && o.clip.parentNode.parentNode.removeChild(o.clip.parentNode);\n                            var el = $(\"clipPath\"),\n                                rc = $(\"rect\");\n                            el.id = R.createUUID();\n                            $(rc, {\n                                x: rect[0],\n                                y: rect[1],\n                                width: rect[2],\n                                height: rect[3]\n                            });\n                            el.appendChild(rc);\n                            o.paper.defs.appendChild(el);\n                            $(node, {\"clip-path\": \"url(#\" + el.id + \")\"});\n                            o.clip = rc;\n                        }\n                        if (!value) {\n                            var path = node.getAttribute(\"clip-path\");\n                            if (path) {\n                                var clip = R._g.doc.getElementById(path.replace(/(^url\\(#|\\)$)/g, E));\n                                clip && clip.parentNode.removeChild(clip);\n                                $(node, {\"clip-path\": E});\n                                delete o.clip;\n                            }\n                        }\n                    break;\n                    case \"path\":\n                        if (o.type == \"path\") {\n                            $(node, {d: value ? attrs.path = R._pathToAbsolute(value) : \"M0,0\"});\n                            o._.dirty = 1;\n                            if (o._.arrows) {\n                                \"startString\" in o._.arrows && addArrow(o, o._.arrows.startString);\n                                \"endString\" in o._.arrows && addArrow(o, o._.arrows.endString, 1);\n                            }\n                        }\n                        break;\n                    case \"width\":\n                        node.setAttribute(att, value);\n                        o._.dirty = 1;\n                        if (attrs.fx) {\n                            att = \"x\";\n                            value = attrs.x;\n                        } else {\n                            break;\n                        }\n                    case \"x\":\n                        if (attrs.fx) {\n                            value = -attrs.x - (attrs.width || 0);\n                        }\n                    case \"rx\":\n                        if (att == \"rx\" && o.type == \"rect\") {\n                            break;\n                        }\n                    case \"cx\":\n                        node.setAttribute(att, value);\n                        o.pattern && updatePosition(o);\n                        o._.dirty = 1;\n                        break;\n                    case \"height\":\n                        node.setAttribute(att, value);\n                        o._.dirty = 1;\n                        if (attrs.fy) {\n                            att = \"y\";\n                            value = attrs.y;\n                        } else {\n                            break;\n                        }\n                    case \"y\":\n                        if (attrs.fy) {\n                            value = -attrs.y - (attrs.height || 0);\n                        }\n                    case \"ry\":\n                        if (att == \"ry\" && o.type == \"rect\") {\n                            break;\n                        }\n                    case \"cy\":\n                        node.setAttribute(att, value);\n                        o.pattern && updatePosition(o);\n                        o._.dirty = 1;\n                        break;\n                    case \"r\":\n                        if (o.type == \"rect\") {\n                            $(node, {rx: value, ry: value});\n                        } else {\n                            node.setAttribute(att, value);\n                        }\n                        o._.dirty = 1;\n                        break;\n                    case \"src\":\n                        if (o.type == \"image\") {\n                            node.setAttributeNS(xlink, \"href\", value);\n                        }\n                        break;\n                    case \"stroke-width\":\n                        if (o._.sx != 1 || o._.sy != 1) {\n                            value /= mmax(abs(o._.sx), abs(o._.sy)) || 1;\n                        }\n                        if (o.paper._vbSize) {\n                            value *= o.paper._vbSize;\n                        }\n                        node.setAttribute(att, value);\n                        if (attrs[\"stroke-dasharray\"]) {\n                            addDashes(o, attrs[\"stroke-dasharray\"], params);\n                        }\n                        if (o._.arrows) {\n                            \"startString\" in o._.arrows && addArrow(o, o._.arrows.startString);\n                            \"endString\" in o._.arrows && addArrow(o, o._.arrows.endString, 1);\n                        }\n                        break;\n                    case \"stroke-dasharray\":\n                        addDashes(o, value, params);\n                        break;\n                    case \"fill\":\n                        var isURL = Str(value).match(R._ISURL);\n                        if (isURL) {\n                            el = $(\"pattern\");\n                            var ig = $(\"image\");\n                            el.id = R.createUUID();\n                            $(el, {x: 0, y: 0, patternUnits: \"userSpaceOnUse\", height: 1, width: 1});\n                            $(ig, {x: 0, y: 0, \"xlink:href\": isURL[1]});\n                            el.appendChild(ig);\n\n                            (function (el) {\n                                R._preload(isURL[1], function () {\n                                    var w = this.offsetWidth,\n                                        h = this.offsetHeight;\n                                    $(el, {width: w, height: h});\n                                    $(ig, {width: w, height: h});\n                                    o.paper.safari();\n                                });\n                            })(el);\n                            o.paper.defs.appendChild(el);\n                            $(node, {fill: \"url(#\" + el.id + \")\"});\n                            o.pattern = el;\n                            o.pattern && updatePosition(o);\n                            break;\n                        }\n                        var clr = R.getRGB(value);\n                        if (!clr.error) {\n                            delete params.gradient;\n                            delete attrs.gradient;\n                            !R.is(attrs.opacity, \"undefined\") &&\n                                R.is(params.opacity, \"undefined\") &&\n                                $(node, {opacity: attrs.opacity});\n                            !R.is(attrs[\"fill-opacity\"], \"undefined\") &&\n                                R.is(params[\"fill-opacity\"], \"undefined\") &&\n                                $(node, {\"fill-opacity\": attrs[\"fill-opacity\"]});\n                        } else if ((o.type == \"circle\" || o.type == \"ellipse\" || Str(value).charAt() != \"r\") && addGradientFill(o, value)) {\n                            if (\"opacity\" in attrs || \"fill-opacity\" in attrs) {\n                                var gradient = R._g.doc.getElementById(node.getAttribute(\"fill\").replace(/^url\\(#|\\)$/g, E));\n                                if (gradient) {\n                                    var stops = gradient.getElementsByTagName(\"stop\");\n                                    $(stops[stops.length - 1], {\"stop-opacity\": (\"opacity\" in attrs ? attrs.opacity : 1) * (\"fill-opacity\" in attrs ? attrs[\"fill-opacity\"] : 1)});\n                                }\n                            }\n                            attrs.gradient = value;\n                            attrs.fill = \"none\";\n                            break;\n                        }\n                        clr[has](\"opacity\") && $(node, {\"fill-opacity\": clr.opacity > 1 ? clr.opacity / 100 : clr.opacity});\n                    case \"stroke\":\n                        clr = R.getRGB(value);\n                        node.setAttribute(att, clr.hex);\n                        att == \"stroke\" && clr[has](\"opacity\") && $(node, {\"stroke-opacity\": clr.opacity > 1 ? clr.opacity / 100 : clr.opacity});\n                        if (att == \"stroke\" && o._.arrows) {\n                            \"startString\" in o._.arrows && addArrow(o, o._.arrows.startString);\n                            \"endString\" in o._.arrows && addArrow(o, o._.arrows.endString, 1);\n                        }\n                        break;\n                    case \"gradient\":\n                        (o.type == \"circle\" || o.type == \"ellipse\" || Str(value).charAt() != \"r\") && addGradientFill(o, value);\n                        break;\n                    case \"opacity\":\n                        if (attrs.gradient && !attrs[has](\"stroke-opacity\")) {\n                            $(node, {\"stroke-opacity\": value > 1 ? value / 100 : value});\n                        }\n                        // fall\n                    case \"fill-opacity\":\n                        if (attrs.gradient) {\n                            gradient = R._g.doc.getElementById(node.getAttribute(\"fill\").replace(/^url\\(#|\\)$/g, E));\n                            if (gradient) {\n                                stops = gradient.getElementsByTagName(\"stop\");\n                                $(stops[stops.length - 1], {\"stop-opacity\": value});\n                            }\n                            break;\n                        }\n                    default:\n                        att == \"font-size\" && (value = toInt(value, 10) + \"px\");\n                        var cssrule = att.replace(/(\\-.)/g, function (w) {\n                            return w.substring(1).toUpperCase();\n                        });\n                        node.style[cssrule] = value;\n                        o._.dirty = 1;\n                        node.setAttribute(att, value);\n                        break;\n                }\n            }\n        }\n\n        tuneText(o, params);\n        node.style.visibility = vis;\n    },\n    leading = 1.2,\n    tuneText = function (el, params) {\n        if (el.type != \"text\" || !(params[has](\"text\") || params[has](\"font\") || params[has](\"font-size\") || params[has](\"x\") || params[has](\"y\"))) {\n            return;\n        }\n        var a = el.attrs,\n            node = el.node,\n            fontSize = node.firstChild ? toInt(R._g.doc.defaultView.getComputedStyle(node.firstChild, E).getPropertyValue(\"font-size\"), 10) : 10;\n\n        if (params[has](\"text\")) {\n            a.text = params.text;\n            while (node.firstChild) {\n                node.removeChild(node.firstChild);\n            }\n            var texts = Str(params.text).split(\"\\n\"),\n                tspans = [],\n                tspan;\n            for (var i = 0, ii = texts.length; i < ii; i++) {\n                tspan = $(\"tspan\");\n                i && $(tspan, {dy: fontSize * leading, x: a.x});\n                tspan.appendChild(R._g.doc.createTextNode(texts[i]));\n                node.appendChild(tspan);\n                tspans[i] = tspan;\n            }\n        } else {\n            tspans = node.getElementsByTagName(\"tspan\");\n            for (i = 0, ii = tspans.length; i < ii; i++) if (i) {\n                $(tspans[i], {dy: fontSize * leading, x: a.x});\n            } else {\n                $(tspans[0], {dy: 0});\n            }\n        }\n        $(node, {x: a.x, y: a.y});\n        el._.dirty = 1;\n        var bb = el._getBBox(),\n            dif = a.y - (bb.y + bb.height / 2);\n        dif && R.is(dif, \"finite\") && $(tspans[0], {dy: dif});\n    },\n    Element = function (node, svg) {\n        var X = 0,\n            Y = 0;\n        \n        this[0] = this.node = node;\n        \n        node.raphael = true;\n        \n        this.id = R._oid++;\n        node.raphaelid = this.id;\n        this.matrix = R.matrix();\n        this.realPath = null;\n        \n        this.paper = svg;\n        this.attrs = this.attrs || {};\n        this._ = {\n            transform: [],\n            sx: 1,\n            sy: 1,\n            deg: 0,\n            dx: 0,\n            dy: 0,\n            dirty: 1\n        };\n        !svg.bottom && (svg.bottom = this);\n        \n        this.prev = svg.top;\n        svg.top && (svg.top.next = this);\n        svg.top = this;\n        \n        this.next = null;\n    },\n    elproto = R.el;\n\n    Element.prototype = elproto;\n    elproto.constructor = Element;\n\n    R._engine.path = function (pathString, SVG) {\n        var el = $(\"path\");\n        SVG.canvas && SVG.canvas.appendChild(el);\n        var p = new Element(el, SVG);\n        p.type = \"path\";\n        setFillAndStroke(p, {\n            fill: \"none\",\n            stroke: \"#000\",\n            path: pathString\n        });\n        return p;\n    };\n    \n    elproto.rotate = function (deg, cx, cy) {\n        if (this.removed) {\n            return this;\n        }\n        deg = Str(deg).split(separator);\n        if (deg.length - 1) {\n            cx = toFloat(deg[1]);\n            cy = toFloat(deg[2]);\n        }\n        deg = toFloat(deg[0]);\n        (cy == null) && (cx = cy);\n        if (cx == null || cy == null) {\n            var bbox = this.getBBox(1);\n            cx = bbox.x + bbox.width / 2;\n            cy = bbox.y + bbox.height / 2;\n        }\n        this.transform(this._.transform.concat([[\"r\", deg, cx, cy]]));\n        return this;\n    };\n    \n    elproto.scale = function (sx, sy, cx, cy) {\n        if (this.removed) {\n            return this;\n        }\n        sx = Str(sx).split(separator);\n        if (sx.length - 1) {\n            sy = toFloat(sx[1]);\n            cx = toFloat(sx[2]);\n            cy = toFloat(sx[3]);\n        }\n        sx = toFloat(sx[0]);\n        (sy == null) && (sy = sx);\n        (cy == null) && (cx = cy);\n        if (cx == null || cy == null) {\n            var bbox = this.getBBox(1);\n        }\n        cx = cx == null ? bbox.x + bbox.width / 2 : cx;\n        cy = cy == null ? bbox.y + bbox.height / 2 : cy;\n        this.transform(this._.transform.concat([[\"s\", sx, sy, cx, cy]]));\n        return this;\n    };\n    \n    elproto.translate = function (dx, dy) {\n        if (this.removed) {\n            return this;\n        }\n        dx = Str(dx).split(separator);\n        if (dx.length - 1) {\n            dy = toFloat(dx[1]);\n        }\n        dx = toFloat(dx[0]) || 0;\n        dy = +dy || 0;\n        this.transform(this._.transform.concat([[\"t\", dx, dy]]));\n        return this;\n    };\n    \n    elproto.transform = function (tstr) {\n        var _ = this._;\n        if (tstr == null) {\n            return _.transform;\n        }\n        R._extractTransform(this, tstr);\n\n        this.clip && $(this.clip, {transform: this.matrix.invert()});\n        this.pattern && updatePosition(this);\n        this.node && $(this.node, {transform: this.matrix});\n    \n        if (_.sx != 1 || _.sy != 1) {\n            var sw = this.attrs[has](\"stroke-width\") ? this.attrs[\"stroke-width\"] : 1;\n            this.attr({\"stroke-width\": sw});\n        }\n\n        return this;\n    };\n    \n    elproto.hide = function () {\n        !this.removed && this.paper.safari(this.node.style.display = \"none\");\n        return this;\n    };\n    \n    elproto.show = function () {\n        !this.removed && this.paper.safari(this.node.style.display = \"\");\n        return this;\n    };\n    \n    elproto.remove = function () {\n        if (this.removed || !this.node.parentNode) {\n            return;\n        }\n        var paper = this.paper;\n        paper.__set__ && paper.__set__.exclude(this);\n        eve.unbind(\"raphael.*.*.\" + this.id);\n        if (this.gradient) {\n            paper.defs.removeChild(this.gradient);\n        }\n        R._tear(this, paper);\n        if (this.node.parentNode.tagName.toLowerCase() == \"a\") {\n            this.node.parentNode.parentNode.removeChild(this.node.parentNode);\n        } else {\n            this.node.parentNode.removeChild(this.node);\n        }\n        for (var i in this) {\n            this[i] = typeof this[i] == \"function\" ? R._removedFactory(i) : null;\n        }\n        this.removed = true;\n    };\n    elproto._getBBox = function () {\n        if (this.node.style.display == \"none\") {\n            this.show();\n            var hide = true;\n        }\n        var bbox = {};\n        try {\n            bbox = this.node.getBBox();\n        } catch(e) {\n            // Firefox 3.0.x plays badly here\n        } finally {\n            bbox = bbox || {};\n        }\n        hide && this.hide();\n        return bbox;\n    };\n    \n    elproto.attr = function (name, value) {\n        if (this.removed) {\n            return this;\n        }\n        if (name == null) {\n            var res = {};\n            for (var a in this.attrs) if (this.attrs[has](a)) {\n                res[a] = this.attrs[a];\n            }\n            res.gradient && res.fill == \"none\" && (res.fill = res.gradient) && delete res.gradient;\n            res.transform = this._.transform;\n            return res;\n        }\n        if (value == null && R.is(name, \"string\")) {\n            if (name == \"fill\" && this.attrs.fill == \"none\" && this.attrs.gradient) {\n                return this.attrs.gradient;\n            }\n            if (name == \"transform\") {\n                return this._.transform;\n            }\n            var names = name.split(separator),\n                out = {};\n            for (var i = 0, ii = names.length; i < ii; i++) {\n                name = names[i];\n                if (name in this.attrs) {\n                    out[name] = this.attrs[name];\n                } else if (R.is(this.paper.customAttributes[name], \"function\")) {\n                    out[name] = this.paper.customAttributes[name].def;\n                } else {\n                    out[name] = R._availableAttrs[name];\n                }\n            }\n            return ii - 1 ? out : out[names[0]];\n        }\n        if (value == null && R.is(name, \"array\")) {\n            out = {};\n            for (i = 0, ii = name.length; i < ii; i++) {\n                out[name[i]] = this.attr(name[i]);\n            }\n            return out;\n        }\n        if (value != null) {\n            var params = {};\n            params[name] = value;\n        } else if (name != null && R.is(name, \"object\")) {\n            params = name;\n        }\n        for (var key in params) {\n            eve(\"raphael.attr.\" + key + \".\" + this.id, this, params[key]);\n        }\n        for (key in this.paper.customAttributes) if (this.paper.customAttributes[has](key) && params[has](key) && R.is(this.paper.customAttributes[key], \"function\")) {\n            var par = this.paper.customAttributes[key].apply(this, [].concat(params[key]));\n            this.attrs[key] = params[key];\n            for (var subkey in par) if (par[has](subkey)) {\n                params[subkey] = par[subkey];\n            }\n        }\n        setFillAndStroke(this, params);\n        return this;\n    };\n    \n    elproto.toFront = function () {\n        if (this.removed) {\n            return this;\n        }\n        if (this.node.parentNode.tagName.toLowerCase() == \"a\") {\n            this.node.parentNode.parentNode.appendChild(this.node.parentNode);\n        } else {\n            this.node.parentNode.appendChild(this.node);\n        }\n        var svg = this.paper;\n        svg.top != this && R._tofront(this, svg);\n        return this;\n    };\n    \n    elproto.toBack = function () {\n        if (this.removed) {\n            return this;\n        }\n        var parent = this.node.parentNode;\n        if (parent.tagName.toLowerCase() == \"a\") {\n            parent.parentNode.insertBefore(this.node.parentNode, this.node.parentNode.parentNode.firstChild); \n        } else if (parent.firstChild != this.node) {\n            parent.insertBefore(this.node, this.node.parentNode.firstChild);\n        }\n        R._toback(this, this.paper);\n        var svg = this.paper;\n        return this;\n    };\n    \n    elproto.insertAfter = function (element) {\n        if (this.removed) {\n            return this;\n        }\n        var node = element.node || element[element.length - 1].node;\n        if (node.nextSibling) {\n            node.parentNode.insertBefore(this.node, node.nextSibling);\n        } else {\n            node.parentNode.appendChild(this.node);\n        }\n        R._insertafter(this, element, this.paper);\n        return this;\n    };\n    \n    elproto.insertBefore = function (element) {\n        if (this.removed) {\n            return this;\n        }\n        var node = element.node || element[0].node;\n        node.parentNode.insertBefore(this.node, node);\n        R._insertbefore(this, element, this.paper);\n        return this;\n    };\n    elproto.blur = function (size) {\n        // Experimental. No Safari support. Use it on your own risk.\n        var t = this;\n        if (+size !== 0) {\n            var fltr = $(\"filter\"),\n                blur = $(\"feGaussianBlur\");\n            t.attrs.blur = size;\n            fltr.id = R.createUUID();\n            $(blur, {stdDeviation: +size || 1.5});\n            fltr.appendChild(blur);\n            t.paper.defs.appendChild(fltr);\n            t._blur = fltr;\n            $(t.node, {filter: \"url(#\" + fltr.id + \")\"});\n        } else {\n            if (t._blur) {\n                t._blur.parentNode.removeChild(t._blur);\n                delete t._blur;\n                delete t.attrs.blur;\n            }\n            t.node.removeAttribute(\"filter\");\n        }\n    };\n    R._engine.circle = function (svg, x, y, r) {\n        var el = $(\"circle\");\n        svg.canvas && svg.canvas.appendChild(el);\n        var res = new Element(el, svg);\n        res.attrs = {cx: x, cy: y, r: r, fill: \"none\", stroke: \"#000\"};\n        res.type = \"circle\";\n        $(el, res.attrs);\n        return res;\n    };\n    R._engine.rect = function (svg, x, y, w, h, r) {\n        var el = $(\"rect\");\n        svg.canvas && svg.canvas.appendChild(el);\n        var res = new Element(el, svg);\n        res.attrs = {x: x, y: y, width: w, height: h, r: r || 0, rx: r || 0, ry: r || 0, fill: \"none\", stroke: \"#000\"};\n        res.type = \"rect\";\n        $(el, res.attrs);\n        return res;\n    };\n    R._engine.ellipse = function (svg, x, y, rx, ry) {\n        var el = $(\"ellipse\");\n        svg.canvas && svg.canvas.appendChild(el);\n        var res = new Element(el, svg);\n        res.attrs = {cx: x, cy: y, rx: rx, ry: ry, fill: \"none\", stroke: \"#000\"};\n        res.type = \"ellipse\";\n        $(el, res.attrs);\n        return res;\n    };\n    R._engine.image = function (svg, src, x, y, w, h) {\n        var el = $(\"image\");\n        $(el, {x: x, y: y, width: w, height: h, preserveAspectRatio: \"none\"});\n        el.setAttributeNS(xlink, \"href\", src);\n        svg.canvas && svg.canvas.appendChild(el);\n        var res = new Element(el, svg);\n        res.attrs = {x: x, y: y, width: w, height: h, src: src};\n        res.type = \"image\";\n        return res;\n    };\n    R._engine.text = function (svg, x, y, text) {\n        var el = $(\"text\");\n        svg.canvas && svg.canvas.appendChild(el);\n        var res = new Element(el, svg);\n        res.attrs = {\n            x: x,\n            y: y,\n            \"text-anchor\": \"middle\",\n            text: text,\n            font: R._availableAttrs.font,\n            stroke: \"none\",\n            fill: \"#000\"\n        };\n        res.type = \"text\";\n        setFillAndStroke(res, res.attrs);\n        return res;\n    };\n    R._engine.setSize = function (width, height) {\n        this.width = width || this.width;\n        this.height = height || this.height;\n        this.canvas.setAttribute(\"width\", this.width);\n        this.canvas.setAttribute(\"height\", this.height);\n        if (this._viewBox) {\n            this.setViewBox.apply(this, this._viewBox);\n        }\n        return this;\n    };\n    R._engine.create = function () {\n        var con = R._getContainer.apply(0, arguments),\n            container = con && con.container,\n            x = con.x,\n            y = con.y,\n            width = con.width,\n            height = con.height;\n        if (!container) {\n            throw new Error(\"SVG container not found.\");\n        }\n        var cnvs = $(\"svg\"),\n            css = \"overflow:hidden;\",\n            isFloating;\n        x = x || 0;\n        y = y || 0;\n        width = width || 512;\n        height = height || 342;\n        $(cnvs, {\n            height: height,\n            version: 1.1,\n            width: width,\n            xmlns: \"http://www.w3.org/2000/svg\"\n        });\n        if (container == 1) {\n            cnvs.style.cssText = css + \"position:absolute;left:\" + x + \"px;top:\" + y + \"px\";\n            R._g.doc.body.appendChild(cnvs);\n            isFloating = 1;\n        } else {\n            cnvs.style.cssText = css + \"position:relative\";\n            if (container.firstChild) {\n                container.insertBefore(cnvs, container.firstChild);\n            } else {\n                container.appendChild(cnvs);\n            }\n        }\n        container = new R._Paper;\n        container.width = width;\n        container.height = height;\n        container.canvas = cnvs;\n        container.clear();\n        container._left = container._top = 0;\n        isFloating && (container.renderfix = function () {});\n        container.renderfix();\n        return container;\n    };\n    R._engine.setViewBox = function (x, y, w, h, fit) {\n        eve(\"raphael.setViewBox\", this, this._viewBox, [x, y, w, h, fit]);\n        var size = mmax(w / this.width, h / this.height),\n            top = this.top,\n            aspectRatio = fit ? \"meet\" : \"xMinYMin\",\n            vb,\n            sw;\n        if (x == null) {\n            if (this._vbSize) {\n                size = 1;\n            }\n            delete this._vbSize;\n            vb = \"0 0 \" + this.width + S + this.height;\n        } else {\n            this._vbSize = size;\n            vb = x + S + y + S + w + S + h;\n        }\n        $(this.canvas, {\n            viewBox: vb,\n            preserveAspectRatio: aspectRatio\n        });\n        while (size && top) {\n            sw = \"stroke-width\" in top.attrs ? top.attrs[\"stroke-width\"] : 1;\n            top.attr({\"stroke-width\": sw});\n            top._.dirty = 1;\n            top._.dirtyT = 1;\n            top = top.prev;\n        }\n        this._viewBox = [x, y, w, h, !!fit];\n        return this;\n    };\n    \n    R.prototype.renderfix = function () {\n        var cnvs = this.canvas,\n            s = cnvs.style,\n            pos;\n        try {\n            pos = cnvs.getScreenCTM() || cnvs.createSVGMatrix();\n        } catch (e) {\n            pos = cnvs.createSVGMatrix();\n        }\n        var left = -pos.e % 1,\n            top = -pos.f % 1;\n        if (left || top) {\n            if (left) {\n                this._left = (this._left + left) % 1;\n                s.left = this._left + \"px\";\n            }\n            if (top) {\n                this._top = (this._top + top) % 1;\n                s.top = this._top + \"px\";\n            }\n        }\n    };\n    \n    R.prototype.clear = function () {\n        R.eve(\"raphael.clear\", this);\n        var c = this.canvas;\n        while (c.firstChild) {\n            c.removeChild(c.firstChild);\n        }\n        this.bottom = this.top = null;\n        (this.desc = $(\"desc\")).appendChild(R._g.doc.createTextNode(\"Created with Rapha\\xebl \" + R.version));\n        c.appendChild(this.desc);\n        c.appendChild(this.defs = $(\"defs\"));\n    };\n    \n    R.prototype.remove = function () {\n        eve(\"raphael.remove\", this);\n        this.canvas.parentNode && this.canvas.parentNode.removeChild(this.canvas);\n        for (var i in this) {\n            this[i] = typeof this[i] == \"function\" ? R._removedFactory(i) : null;\n        }\n    };\n    var setproto = R.st;\n    for (var method in elproto) if (elproto[has](method) && !setproto[has](method)) {\n        setproto[method] = (function (methodname) {\n            return function () {\n                var arg = arguments;\n                return this.forEach(function (el) {\n                    el[methodname].apply(el, arg);\n                });\n            };\n        })(method);\n    }\n}(window.Raphael);\n\n// ┌─────────────────────────────────────────────────────────────────────┐ \\\\\n// │ Raphaël - JavaScript Vector Library                                 │ \\\\\n// ├─────────────────────────────────────────────────────────────────────┤ \\\\\n// │ VML Module                                                          │ \\\\\n// ├─────────────────────────────────────────────────────────────────────┤ \\\\\n// │ Copyright (c) 2008-2011 Dmitry Baranovskiy (http://raphaeljs.com)   │ \\\\\n// │ Copyright (c) 2008-2011 Sencha Labs (http://sencha.com)             │ \\\\\n// │ Licensed under the MIT (http://raphaeljs.com/license.html) license. │ \\\\\n// └─────────────────────────────────────────────────────────────────────┘ \\\\\nwindow.Raphael.vml && function (R) {\n    var has = \"hasOwnProperty\",\n        Str = String,\n        toFloat = parseFloat,\n        math = Math,\n        round = math.round,\n        mmax = math.max,\n        mmin = math.min,\n        abs = math.abs,\n        fillString = \"fill\",\n        separator = /[, ]+/,\n        eve = R.eve,\n        ms = \" progid:DXImageTransform.Microsoft\",\n        S = \" \",\n        E = \"\",\n        map = {M: \"m\", L: \"l\", C: \"c\", Z: \"x\", m: \"t\", l: \"r\", c: \"v\", z: \"x\"},\n        bites = /([clmz]),?([^clmz]*)/gi,\n        blurregexp = / progid:\\S+Blur\\([^\\)]+\\)/g,\n        val = /-?[^,\\s-]+/g,\n        cssDot = \"position:absolute;left:0;top:0;width:1px;height:1px\",\n        zoom = 21600,\n        pathTypes = {path: 1, rect: 1, image: 1},\n        ovalTypes = {circle: 1, ellipse: 1},\n        path2vml = function (path) {\n            var total =  /[ahqstv]/ig,\n                command = R._pathToAbsolute;\n            Str(path).match(total) && (command = R._path2curve);\n            total = /[clmz]/g;\n            if (command == R._pathToAbsolute && !Str(path).match(total)) {\n                var res = Str(path).replace(bites, function (all, command, args) {\n                    var vals = [],\n                        isMove = command.toLowerCase() == \"m\",\n                        res = map[command];\n                    args.replace(val, function (value) {\n                        if (isMove && vals.length == 2) {\n                            res += vals + map[command == \"m\" ? \"l\" : \"L\"];\n                            vals = [];\n                        }\n                        vals.push(round(value * zoom));\n                    });\n                    return res + vals;\n                });\n                return res;\n            }\n            var pa = command(path), p, r;\n            res = [];\n            for (var i = 0, ii = pa.length; i < ii; i++) {\n                p = pa[i];\n                r = pa[i][0].toLowerCase();\n                r == \"z\" && (r = \"x\");\n                for (var j = 1, jj = p.length; j < jj; j++) {\n                    r += round(p[j] * zoom) + (j != jj - 1 ? \",\" : E);\n                }\n                res.push(r);\n            }\n            return res.join(S);\n        },\n        compensation = function (deg, dx, dy) {\n            var m = R.matrix();\n            m.rotate(-deg, .5, .5);\n            return {\n                dx: m.x(dx, dy),\n                dy: m.y(dx, dy)\n            };\n        },\n        setCoords = function (p, sx, sy, dx, dy, deg) {\n            var _ = p._,\n                m = p.matrix,\n                fillpos = _.fillpos,\n                o = p.node,\n                s = o.style,\n                y = 1,\n                flip = \"\",\n                dxdy,\n                kx = zoom / sx,\n                ky = zoom / sy;\n            s.visibility = \"hidden\";\n            if (!sx || !sy) {\n                return;\n            }\n            o.coordsize = abs(kx) + S + abs(ky);\n            s.rotation = deg * (sx * sy < 0 ? -1 : 1);\n            if (deg) {\n                var c = compensation(deg, dx, dy);\n                dx = c.dx;\n                dy = c.dy;\n            }\n            sx < 0 && (flip += \"x\");\n            sy < 0 && (flip += \" y\") && (y = -1);\n            s.flip = flip;\n            o.coordorigin = (dx * -kx) + S + (dy * -ky);\n            if (fillpos || _.fillsize) {\n                var fill = o.getElementsByTagName(fillString);\n                fill = fill && fill[0];\n                o.removeChild(fill);\n                if (fillpos) {\n                    c = compensation(deg, m.x(fillpos[0], fillpos[1]), m.y(fillpos[0], fillpos[1]));\n                    fill.position = c.dx * y + S + c.dy * y;\n                }\n                if (_.fillsize) {\n                    fill.size = _.fillsize[0] * abs(sx) + S + _.fillsize[1] * abs(sy);\n                }\n                o.appendChild(fill);\n            }\n            s.visibility = \"visible\";\n        };\n    R.toString = function () {\n        return  \"Your browser doesn\\u2019t support SVG. Falling down to VML.\\nYou are running Rapha\\xebl \" + this.version;\n    };\n    var addArrow = function (o, value, isEnd) {\n        var values = Str(value).toLowerCase().split(\"-\"),\n            se = isEnd ? \"end\" : \"start\",\n            i = values.length,\n            type = \"classic\",\n            w = \"medium\",\n            h = \"medium\";\n        while (i--) {\n            switch (values[i]) {\n                case \"block\":\n                case \"classic\":\n                case \"oval\":\n                case \"diamond\":\n                case \"open\":\n                case \"none\":\n                    type = values[i];\n                    break;\n                case \"wide\":\n                case \"narrow\": h = values[i]; break;\n                case \"long\":\n                case \"short\": w = values[i]; break;\n            }\n        }\n        var stroke = o.node.getElementsByTagName(\"stroke\")[0];\n        stroke[se + \"arrow\"] = type;\n        stroke[se + \"arrowlength\"] = w;\n        stroke[se + \"arrowwidth\"] = h;\n    },\n    setFillAndStroke = function (o, params) {\n        // o.paper.canvas.style.display = \"none\";\n        o.attrs = o.attrs || {};\n        var node = o.node,\n            a = o.attrs,\n            s = node.style,\n            xy,\n            newpath = pathTypes[o.type] && (params.x != a.x || params.y != a.y || params.width != a.width || params.height != a.height || params.cx != a.cx || params.cy != a.cy || params.rx != a.rx || params.ry != a.ry || params.r != a.r),\n            isOval = ovalTypes[o.type] && (a.cx != params.cx || a.cy != params.cy || a.r != params.r || a.rx != params.rx || a.ry != params.ry),\n            res = o;\n\n\n        for (var par in params) if (params[has](par)) {\n            a[par] = params[par];\n        }\n        if (newpath) {\n            a.path = R._getPath[o.type](o);\n            o._.dirty = 1;\n        }\n        params.href && (node.href = params.href);\n        params.title && (node.title = params.title);\n        params.target && (node.target = params.target);\n        params.cursor && (s.cursor = params.cursor);\n        \"blur\" in params && o.blur(params.blur);\n        if (params.path && o.type == \"path\" || newpath) {\n            node.path = path2vml(~Str(a.path).toLowerCase().indexOf(\"r\") ? R._pathToAbsolute(a.path) : a.path);\n            if (o.type == \"image\") {\n                o._.fillpos = [a.x, a.y];\n                o._.fillsize = [a.width, a.height];\n                setCoords(o, 1, 1, 0, 0, 0);\n            }\n        }\n        \"transform\" in params && o.transform(params.transform);\n        if (isOval) {\n            var cx = +a.cx,\n                cy = +a.cy,\n                rx = +a.rx || +a.r || 0,\n                ry = +a.ry || +a.r || 0;\n            node.path = R.format(\"ar{0},{1},{2},{3},{4},{1},{4},{1}x\", round((cx - rx) * zoom), round((cy - ry) * zoom), round((cx + rx) * zoom), round((cy + ry) * zoom), round(cx * zoom));\n        }\n        if (\"clip-rect\" in params) {\n            var rect = Str(params[\"clip-rect\"]).split(separator);\n            if (rect.length == 4) {\n                rect[2] = +rect[2] + (+rect[0]);\n                rect[3] = +rect[3] + (+rect[1]);\n                var div = node.clipRect || R._g.doc.createElement(\"div\"),\n                    dstyle = div.style;\n                dstyle.clip = R.format(\"rect({1}px {2}px {3}px {0}px)\", rect);\n                if (!node.clipRect) {\n                    dstyle.position = \"absolute\";\n                    dstyle.top = 0;\n                    dstyle.left = 0;\n                    dstyle.width = o.paper.width + \"px\";\n                    dstyle.height = o.paper.height + \"px\";\n                    node.parentNode.insertBefore(div, node);\n                    div.appendChild(node);\n                    node.clipRect = div;\n                }\n            }\n            if (!params[\"clip-rect\"]) {\n                node.clipRect && (node.clipRect.style.clip = \"auto\");\n            }\n        }\n        if (o.textpath) {\n            var textpathStyle = o.textpath.style;\n            params.font && (textpathStyle.font = params.font);\n            params[\"font-family\"] && (textpathStyle.fontFamily = '\"' + params[\"font-family\"].split(\",\")[0].replace(/^['\"]+|['\"]+$/g, E) + '\"');\n            params[\"font-size\"] && (textpathStyle.fontSize = params[\"font-size\"]);\n            params[\"font-weight\"] && (textpathStyle.fontWeight = params[\"font-weight\"]);\n            params[\"font-style\"] && (textpathStyle.fontStyle = params[\"font-style\"]);\n        }\n        if (\"arrow-start\" in params) {\n            addArrow(res, params[\"arrow-start\"]);\n        }\n        if (\"arrow-end\" in params) {\n            addArrow(res, params[\"arrow-end\"], 1);\n        }\n        if (params.opacity != null || \n            params[\"stroke-width\"] != null ||\n            params.fill != null ||\n            params.src != null ||\n            params.stroke != null ||\n            params[\"stroke-width\"] != null ||\n            params[\"stroke-opacity\"] != null ||\n            params[\"fill-opacity\"] != null ||\n            params[\"stroke-dasharray\"] != null ||\n            params[\"stroke-miterlimit\"] != null ||\n            params[\"stroke-linejoin\"] != null ||\n            params[\"stroke-linecap\"] != null) {\n            var fill = node.getElementsByTagName(fillString),\n                newfill = false;\n            fill = fill && fill[0];\n            !fill && (newfill = fill = createNode(fillString));\n            if (o.type == \"image\" && params.src) {\n                fill.src = params.src;\n            }\n            params.fill && (fill.on = true);\n            if (fill.on == null || params.fill == \"none\" || params.fill === null) {\n                fill.on = false;\n            }\n            if (fill.on && params.fill) {\n                var isURL = Str(params.fill).match(R._ISURL);\n                if (isURL) {\n                    fill.parentNode == node && node.removeChild(fill);\n                    fill.rotate = true;\n                    fill.src = isURL[1];\n                    fill.type = \"tile\";\n                    var bbox = o.getBBox(1);\n                    fill.position = bbox.x + S + bbox.y;\n                    o._.fillpos = [bbox.x, bbox.y];\n\n                    R._preload(isURL[1], function () {\n                        o._.fillsize = [this.offsetWidth, this.offsetHeight];\n                    });\n                } else {\n                    fill.color = R.getRGB(params.fill).hex;\n                    fill.src = E;\n                    fill.type = \"solid\";\n                    if (R.getRGB(params.fill).error && (res.type in {circle: 1, ellipse: 1} || Str(params.fill).charAt() != \"r\") && addGradientFill(res, params.fill, fill)) {\n                        a.fill = \"none\";\n                        a.gradient = params.fill;\n                        fill.rotate = false;\n                    }\n                }\n            }\n            if (\"fill-opacity\" in params || \"opacity\" in params) {\n                var opacity = ((+a[\"fill-opacity\"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1) * ((+R.getRGB(params.fill).o + 1 || 2) - 1);\n                opacity = mmin(mmax(opacity, 0), 1);\n                fill.opacity = opacity;\n                if (fill.src) {\n                    fill.color = \"none\";\n                }\n            }\n            node.appendChild(fill);\n            var stroke = (node.getElementsByTagName(\"stroke\") && node.getElementsByTagName(\"stroke\")[0]),\n            newstroke = false;\n            !stroke && (newstroke = stroke = createNode(\"stroke\"));\n            if ((params.stroke && params.stroke != \"none\") ||\n                params[\"stroke-width\"] ||\n                params[\"stroke-opacity\"] != null ||\n                params[\"stroke-dasharray\"] ||\n                params[\"stroke-miterlimit\"] ||\n                params[\"stroke-linejoin\"] ||\n                params[\"stroke-linecap\"]) {\n                stroke.on = true;\n            }\n            (params.stroke == \"none\" || params.stroke === null || stroke.on == null || params.stroke == 0 || params[\"stroke-width\"] == 0) && (stroke.on = false);\n            var strokeColor = R.getRGB(params.stroke);\n            stroke.on && params.stroke && (stroke.color = strokeColor.hex);\n            opacity = ((+a[\"stroke-opacity\"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1) * ((+strokeColor.o + 1 || 2) - 1);\n            var width = (toFloat(params[\"stroke-width\"]) || 1) * .75;\n            opacity = mmin(mmax(opacity, 0), 1);\n            params[\"stroke-width\"] == null && (width = a[\"stroke-width\"]);\n            params[\"stroke-width\"] && (stroke.weight = width);\n            width && width < 1 && (opacity *= width) && (stroke.weight = 1);\n            stroke.opacity = opacity;\n        \n            params[\"stroke-linejoin\"] && (stroke.joinstyle = params[\"stroke-linejoin\"] || \"miter\");\n            stroke.miterlimit = params[\"stroke-miterlimit\"] || 8;\n            params[\"stroke-linecap\"] && (stroke.endcap = params[\"stroke-linecap\"] == \"butt\" ? \"flat\" : params[\"stroke-linecap\"] == \"square\" ? \"square\" : \"round\");\n            if (params[\"stroke-dasharray\"]) {\n                var dasharray = {\n                    \"-\": \"shortdash\",\n                    \".\": \"shortdot\",\n                    \"-.\": \"shortdashdot\",\n                    \"-..\": \"shortdashdotdot\",\n                    \". \": \"dot\",\n                    \"- \": \"dash\",\n                    \"--\": \"longdash\",\n                    \"- .\": \"dashdot\",\n                    \"--.\": \"longdashdot\",\n                    \"--..\": \"longdashdotdot\"\n                };\n                stroke.dashstyle = dasharray[has](params[\"stroke-dasharray\"]) ? dasharray[params[\"stroke-dasharray\"]] : E;\n            }\n            newstroke && node.appendChild(stroke);\n        }\n        if (res.type == \"text\") {\n            res.paper.canvas.style.display = E;\n            var span = res.paper.span,\n                m = 100,\n                fontSize = a.font && a.font.match(/\\d+(?:\\.\\d*)?(?=px)/);\n            s = span.style;\n            a.font && (s.font = a.font);\n            a[\"font-family\"] && (s.fontFamily = a[\"font-family\"]);\n            a[\"font-weight\"] && (s.fontWeight = a[\"font-weight\"]);\n            a[\"font-style\"] && (s.fontStyle = a[\"font-style\"]);\n            fontSize = toFloat(a[\"font-size\"] || fontSize && fontSize[0]) || 10;\n            s.fontSize = fontSize * m + \"px\";\n            res.textpath.string && (span.innerHTML = Str(res.textpath.string).replace(/</g, \"&#60;\").replace(/&/g, \"&#38;\").replace(/\\n/g, \"<br>\"));\n            var brect = span.getBoundingClientRect();\n            res.W = a.w = (brect.right - brect.left) / m;\n            res.H = a.h = (brect.bottom - brect.top) / m;\n            // res.paper.canvas.style.display = \"none\";\n            res.X = a.x;\n            res.Y = a.y + res.H / 2;\n\n            (\"x\" in params || \"y\" in params) && (res.path.v = R.format(\"m{0},{1}l{2},{1}\", round(a.x * zoom), round(a.y * zoom), round(a.x * zoom) + 1));\n            var dirtyattrs = [\"x\", \"y\", \"text\", \"font\", \"font-family\", \"font-weight\", \"font-style\", \"font-size\"];\n            for (var d = 0, dd = dirtyattrs.length; d < dd; d++) if (dirtyattrs[d] in params) {\n                res._.dirty = 1;\n                break;\n            }\n        \n            // text-anchor emulation\n            switch (a[\"text-anchor\"]) {\n                case \"start\":\n                    res.textpath.style[\"v-text-align\"] = \"left\";\n                    res.bbx = res.W / 2;\n                break;\n                case \"end\":\n                    res.textpath.style[\"v-text-align\"] = \"right\";\n                    res.bbx = -res.W / 2;\n                break;\n                default:\n                    res.textpath.style[\"v-text-align\"] = \"center\";\n                    res.bbx = 0;\n                break;\n            }\n            res.textpath.style[\"v-text-kern\"] = true;\n        }\n        // res.paper.canvas.style.display = E;\n    },\n    addGradientFill = function (o, gradient, fill) {\n        o.attrs = o.attrs || {};\n        var attrs = o.attrs,\n            pow = Math.pow,\n            opacity,\n            oindex,\n            type = \"linear\",\n            fxfy = \".5 .5\";\n        o.attrs.gradient = gradient;\n        gradient = Str(gradient).replace(R._radial_gradient, function (all, fx, fy) {\n            type = \"radial\";\n            if (fx && fy) {\n                fx = toFloat(fx);\n                fy = toFloat(fy);\n                pow(fx - .5, 2) + pow(fy - .5, 2) > .25 && (fy = math.sqrt(.25 - pow(fx - .5, 2)) * ((fy > .5) * 2 - 1) + .5);\n                fxfy = fx + S + fy;\n            }\n            return E;\n        });\n        gradient = gradient.split(/\\s*\\-\\s*/);\n        if (type == \"linear\") {\n            var angle = gradient.shift();\n            angle = -toFloat(angle);\n            if (isNaN(angle)) {\n                return null;\n            }\n        }\n        var dots = R._parseDots(gradient);\n        if (!dots) {\n            return null;\n        }\n        o = o.shape || o.node;\n        if (dots.length) {\n            o.removeChild(fill);\n            fill.on = true;\n            fill.method = \"none\";\n            fill.color = dots[0].color;\n            fill.color2 = dots[dots.length - 1].color;\n            var clrs = [];\n            for (var i = 0, ii = dots.length; i < ii; i++) {\n                dots[i].offset && clrs.push(dots[i].offset + S + dots[i].color);\n            }\n            fill.colors = clrs.length ? clrs.join() : \"0% \" + fill.color;\n            if (type == \"radial\") {\n                fill.type = \"gradientTitle\";\n                fill.focus = \"100%\";\n                fill.focussize = \"0 0\";\n                fill.focusposition = fxfy;\n                fill.angle = 0;\n            } else {\n                // fill.rotate= true;\n                fill.type = \"gradient\";\n                fill.angle = (270 - angle) % 360;\n            }\n            o.appendChild(fill);\n        }\n        return 1;\n    },\n    Element = function (node, vml) {\n        this[0] = this.node = node;\n        node.raphael = true;\n        this.id = R._oid++;\n        node.raphaelid = this.id;\n        this.X = 0;\n        this.Y = 0;\n        this.attrs = {};\n        this.paper = vml;\n        this.matrix = R.matrix();\n        this._ = {\n            transform: [],\n            sx: 1,\n            sy: 1,\n            dx: 0,\n            dy: 0,\n            deg: 0,\n            dirty: 1,\n            dirtyT: 1\n        };\n        !vml.bottom && (vml.bottom = this);\n        this.prev = vml.top;\n        vml.top && (vml.top.next = this);\n        vml.top = this;\n        this.next = null;\n    };\n    var elproto = R.el;\n\n    Element.prototype = elproto;\n    elproto.constructor = Element;\n    elproto.transform = function (tstr) {\n        if (tstr == null) {\n            return this._.transform;\n        }\n        var vbs = this.paper._viewBoxShift,\n            vbt = vbs ? \"s\" + [vbs.scale, vbs.scale] + \"-1-1t\" + [vbs.dx, vbs.dy] : E,\n            oldt;\n        if (vbs) {\n            oldt = tstr = Str(tstr).replace(/\\.{3}|\\u2026/g, this._.transform || E);\n        }\n        R._extractTransform(this, vbt + tstr);\n        var matrix = this.matrix.clone(),\n            skew = this.skew,\n            o = this.node,\n            split,\n            isGrad = ~Str(this.attrs.fill).indexOf(\"-\"),\n            isPatt = !Str(this.attrs.fill).indexOf(\"url(\");\n        matrix.translate(-.5, -.5);\n        if (isPatt || isGrad || this.type == \"image\") {\n            skew.matrix = \"1 0 0 1\";\n            skew.offset = \"0 0\";\n            split = matrix.split();\n            if ((isGrad && split.noRotation) || !split.isSimple) {\n                o.style.filter = matrix.toFilter();\n                var bb = this.getBBox(),\n                    bbt = this.getBBox(1),\n                    dx = bb.x - bbt.x,\n                    dy = bb.y - bbt.y;\n                o.coordorigin = (dx * -zoom) + S + (dy * -zoom);\n                setCoords(this, 1, 1, dx, dy, 0);\n            } else {\n                o.style.filter = E;\n                setCoords(this, split.scalex, split.scaley, split.dx, split.dy, split.rotate);\n            }\n        } else {\n            o.style.filter = E;\n            skew.matrix = Str(matrix);\n            skew.offset = matrix.offset();\n        }\n        oldt && (this._.transform = oldt);\n        return this;\n    };\n    elproto.rotate = function (deg, cx, cy) {\n        if (this.removed) {\n            return this;\n        }\n        if (deg == null) {\n            return;\n        }\n        deg = Str(deg).split(separator);\n        if (deg.length - 1) {\n            cx = toFloat(deg[1]);\n            cy = toFloat(deg[2]);\n        }\n        deg = toFloat(deg[0]);\n        (cy == null) && (cx = cy);\n        if (cx == null || cy == null) {\n            var bbox = this.getBBox(1);\n            cx = bbox.x + bbox.width / 2;\n            cy = bbox.y + bbox.height / 2;\n        }\n        this._.dirtyT = 1;\n        this.transform(this._.transform.concat([[\"r\", deg, cx, cy]]));\n        return this;\n    };\n    elproto.translate = function (dx, dy) {\n        if (this.removed) {\n            return this;\n        }\n        dx = Str(dx).split(separator);\n        if (dx.length - 1) {\n            dy = toFloat(dx[1]);\n        }\n        dx = toFloat(dx[0]) || 0;\n        dy = +dy || 0;\n        if (this._.bbox) {\n            this._.bbox.x += dx;\n            this._.bbox.y += dy;\n        }\n        this.transform(this._.transform.concat([[\"t\", dx, dy]]));\n        return this;\n    };\n    elproto.scale = function (sx, sy, cx, cy) {\n        if (this.removed) {\n            return this;\n        }\n        sx = Str(sx).split(separator);\n        if (sx.length - 1) {\n            sy = toFloat(sx[1]);\n            cx = toFloat(sx[2]);\n            cy = toFloat(sx[3]);\n            isNaN(cx) && (cx = null);\n            isNaN(cy) && (cy = null);\n        }\n        sx = toFloat(sx[0]);\n        (sy == null) && (sy = sx);\n        (cy == null) && (cx = cy);\n        if (cx == null || cy == null) {\n            var bbox = this.getBBox(1);\n        }\n        cx = cx == null ? bbox.x + bbox.width / 2 : cx;\n        cy = cy == null ? bbox.y + bbox.height / 2 : cy;\n    \n        this.transform(this._.transform.concat([[\"s\", sx, sy, cx, cy]]));\n        this._.dirtyT = 1;\n        return this;\n    };\n    elproto.hide = function () {\n        !this.removed && (this.node.style.display = \"none\");\n        return this;\n    };\n    elproto.show = function () {\n        !this.removed && (this.node.style.display = E);\n        return this;\n    };\n    elproto._getBBox = function () {\n        if (this.removed) {\n            return {};\n        }\n        return {\n            x: this.X + (this.bbx || 0) - this.W / 2,\n            y: this.Y - this.H,\n            width: this.W,\n            height: this.H\n        };\n    };\n    elproto.remove = function () {\n        if (this.removed || !this.node.parentNode) {\n            return;\n        }\n        this.paper.__set__ && this.paper.__set__.exclude(this);\n        R.eve.unbind(\"raphael.*.*.\" + this.id);\n        R._tear(this, this.paper);\n        this.node.parentNode.removeChild(this.node);\n        this.shape && this.shape.parentNode.removeChild(this.shape);\n        for (var i in this) {\n            this[i] = typeof this[i] == \"function\" ? R._removedFactory(i) : null;\n        }\n        this.removed = true;\n    };\n    elproto.attr = function (name, value) {\n        if (this.removed) {\n            return this;\n        }\n        if (name == null) {\n            var res = {};\n            for (var a in this.attrs) if (this.attrs[has](a)) {\n                res[a] = this.attrs[a];\n            }\n            res.gradient && res.fill == \"none\" && (res.fill = res.gradient) && delete res.gradient;\n            res.transform = this._.transform;\n            return res;\n        }\n        if (value == null && R.is(name, \"string\")) {\n            if (name == fillString && this.attrs.fill == \"none\" && this.attrs.gradient) {\n                return this.attrs.gradient;\n            }\n            var names = name.split(separator),\n                out = {};\n            for (var i = 0, ii = names.length; i < ii; i++) {\n                name = names[i];\n                if (name in this.attrs) {\n                    out[name] = this.attrs[name];\n                } else if (R.is(this.paper.customAttributes[name], \"function\")) {\n                    out[name] = this.paper.customAttributes[name].def;\n                } else {\n                    out[name] = R._availableAttrs[name];\n                }\n            }\n            return ii - 1 ? out : out[names[0]];\n        }\n        if (this.attrs && value == null && R.is(name, \"array\")) {\n            out = {};\n            for (i = 0, ii = name.length; i < ii; i++) {\n                out[name[i]] = this.attr(name[i]);\n            }\n            return out;\n        }\n        var params;\n        if (value != null) {\n            params = {};\n            params[name] = value;\n        }\n        value == null && R.is(name, \"object\") && (params = name);\n        for (var key in params) {\n            eve(\"raphael.attr.\" + key + \".\" + this.id, this, params[key]);\n        }\n        if (params) {\n            for (key in this.paper.customAttributes) if (this.paper.customAttributes[has](key) && params[has](key) && R.is(this.paper.customAttributes[key], \"function\")) {\n                var par = this.paper.customAttributes[key].apply(this, [].concat(params[key]));\n                this.attrs[key] = params[key];\n                for (var subkey in par) if (par[has](subkey)) {\n                    params[subkey] = par[subkey];\n                }\n            }\n            // this.paper.canvas.style.display = \"none\";\n            if (params.text && this.type == \"text\") {\n                this.textpath.string = params.text;\n            }\n            setFillAndStroke(this, params);\n            // this.paper.canvas.style.display = E;\n        }\n        return this;\n    };\n    elproto.toFront = function () {\n        !this.removed && this.node.parentNode.appendChild(this.node);\n        this.paper && this.paper.top != this && R._tofront(this, this.paper);\n        return this;\n    };\n    elproto.toBack = function () {\n        if (this.removed) {\n            return this;\n        }\n        if (this.node.parentNode.firstChild != this.node) {\n            this.node.parentNode.insertBefore(this.node, this.node.parentNode.firstChild);\n            R._toback(this, this.paper);\n        }\n        return this;\n    };\n    elproto.insertAfter = function (element) {\n        if (this.removed) {\n            return this;\n        }\n        if (element.constructor == R.st.constructor) {\n            element = element[element.length - 1];\n        }\n        if (element.node.nextSibling) {\n            element.node.parentNode.insertBefore(this.node, element.node.nextSibling);\n        } else {\n            element.node.parentNode.appendChild(this.node);\n        }\n        R._insertafter(this, element, this.paper);\n        return this;\n    };\n    elproto.insertBefore = function (element) {\n        if (this.removed) {\n            return this;\n        }\n        if (element.constructor == R.st.constructor) {\n            element = element[0];\n        }\n        element.node.parentNode.insertBefore(this.node, element.node);\n        R._insertbefore(this, element, this.paper);\n        return this;\n    };\n    elproto.blur = function (size) {\n        var s = this.node.runtimeStyle,\n            f = s.filter;\n        f = f.replace(blurregexp, E);\n        if (+size !== 0) {\n            this.attrs.blur = size;\n            s.filter = f + S + ms + \".Blur(pixelradius=\" + (+size || 1.5) + \")\";\n            s.margin = R.format(\"-{0}px 0 0 -{0}px\", round(+size || 1.5));\n        } else {\n            s.filter = f;\n            s.margin = 0;\n            delete this.attrs.blur;\n        }\n    };\n\n    R._engine.path = function (pathString, vml) {\n        var el = createNode(\"shape\");\n        el.style.cssText = cssDot;\n        el.coordsize = zoom + S + zoom;\n        el.coordorigin = vml.coordorigin;\n        var p = new Element(el, vml),\n            attr = {fill: \"none\", stroke: \"#000\"};\n        pathString && (attr.path = pathString);\n        p.type = \"path\";\n        p.path = [];\n        p.Path = E;\n        setFillAndStroke(p, attr);\n        vml.canvas.appendChild(el);\n        var skew = createNode(\"skew\");\n        skew.on = true;\n        el.appendChild(skew);\n        p.skew = skew;\n        p.transform(E);\n        return p;\n    };\n    R._engine.rect = function (vml, x, y, w, h, r) {\n        var path = R._rectPath(x, y, w, h, r),\n            res = vml.path(path),\n            a = res.attrs;\n        res.X = a.x = x;\n        res.Y = a.y = y;\n        res.W = a.width = w;\n        res.H = a.height = h;\n        a.r = r;\n        a.path = path;\n        res.type = \"rect\";\n        return res;\n    };\n    R._engine.ellipse = function (vml, x, y, rx, ry) {\n        var res = vml.path(),\n            a = res.attrs;\n        res.X = x - rx;\n        res.Y = y - ry;\n        res.W = rx * 2;\n        res.H = ry * 2;\n        res.type = \"ellipse\";\n        setFillAndStroke(res, {\n            cx: x,\n            cy: y,\n            rx: rx,\n            ry: ry\n        });\n        return res;\n    };\n    R._engine.circle = function (vml, x, y, r) {\n        var res = vml.path(),\n            a = res.attrs;\n        res.X = x - r;\n        res.Y = y - r;\n        res.W = res.H = r * 2;\n        res.type = \"circle\";\n        setFillAndStroke(res, {\n            cx: x,\n            cy: y,\n            r: r\n        });\n        return res;\n    };\n    R._engine.image = function (vml, src, x, y, w, h) {\n        var path = R._rectPath(x, y, w, h),\n            res = vml.path(path).attr({stroke: \"none\"}),\n            a = res.attrs,\n            node = res.node,\n            fill = node.getElementsByTagName(fillString)[0];\n        a.src = src;\n        res.X = a.x = x;\n        res.Y = a.y = y;\n        res.W = a.width = w;\n        res.H = a.height = h;\n        a.path = path;\n        res.type = \"image\";\n        fill.parentNode == node && node.removeChild(fill);\n        fill.rotate = true;\n        fill.src = src;\n        fill.type = \"tile\";\n        res._.fillpos = [x, y];\n        res._.fillsize = [w, h];\n        node.appendChild(fill);\n        setCoords(res, 1, 1, 0, 0, 0);\n        return res;\n    };\n    R._engine.text = function (vml, x, y, text) {\n        var el = createNode(\"shape\"),\n            path = createNode(\"path\"),\n            o = createNode(\"textpath\");\n        x = x || 0;\n        y = y || 0;\n        text = text || \"\";\n        path.v = R.format(\"m{0},{1}l{2},{1}\", round(x * zoom), round(y * zoom), round(x * zoom) + 1);\n        path.textpathok = true;\n        o.string = Str(text);\n        o.on = true;\n        el.style.cssText = cssDot;\n        el.coordsize = zoom + S + zoom;\n        el.coordorigin = \"0 0\";\n        var p = new Element(el, vml),\n            attr = {\n                fill: \"#000\",\n                stroke: \"none\",\n                font: R._availableAttrs.font,\n                text: text\n            };\n        p.shape = el;\n        p.path = path;\n        p.textpath = o;\n        p.type = \"text\";\n        p.attrs.text = Str(text);\n        p.attrs.x = x;\n        p.attrs.y = y;\n        p.attrs.w = 1;\n        p.attrs.h = 1;\n        setFillAndStroke(p, attr);\n        el.appendChild(o);\n        el.appendChild(path);\n        vml.canvas.appendChild(el);\n        var skew = createNode(\"skew\");\n        skew.on = true;\n        el.appendChild(skew);\n        p.skew = skew;\n        p.transform(E);\n        return p;\n    };\n    R._engine.setSize = function (width, height) {\n        var cs = this.canvas.style;\n        this.width = width;\n        this.height = height;\n        width == +width && (width += \"px\");\n        height == +height && (height += \"px\");\n        cs.width = width;\n        cs.height = height;\n        cs.clip = \"rect(0 \" + width + \" \" + height + \" 0)\";\n        if (this._viewBox) {\n            R._engine.setViewBox.apply(this, this._viewBox);\n        }\n        return this;\n    };\n    R._engine.setViewBox = function (x, y, w, h, fit) {\n        R.eve(\"raphael.setViewBox\", this, this._viewBox, [x, y, w, h, fit]);\n        var width = this.width,\n            height = this.height,\n            size = 1 / mmax(w / width, h / height),\n            H, W;\n        if (fit) {\n            H = height / h;\n            W = width / w;\n            if (w * H < width) {\n                x -= (width - w * H) / 2 / H;\n            }\n            if (h * W < height) {\n                y -= (height - h * W) / 2 / W;\n            }\n        }\n        this._viewBox = [x, y, w, h, !!fit];\n        this._viewBoxShift = {\n            dx: -x,\n            dy: -y,\n            scale: size\n        };\n        this.forEach(function (el) {\n            el.transform(\"...\");\n        });\n        return this;\n    };\n    var createNode;\n    R._engine.initWin = function (win) {\n            var doc = win.document;\n            doc.createStyleSheet().addRule(\".rvml\", \"behavior:url(#default#VML)\");\n            try {\n                !doc.namespaces.rvml && doc.namespaces.add(\"rvml\", \"urn:schemas-microsoft-com:vml\");\n                createNode = function (tagName) {\n                    return doc.createElement('<rvml:' + tagName + ' class=\"rvml\">');\n                };\n            } catch (e) {\n                createNode = function (tagName) {\n                    return doc.createElement('<' + tagName + ' xmlns=\"urn:schemas-microsoft.com:vml\" class=\"rvml\">');\n                };\n            }\n        };\n    R._engine.initWin(R._g.win);\n    R._engine.create = function () {\n        var con = R._getContainer.apply(0, arguments),\n            container = con.container,\n            height = con.height,\n            s,\n            width = con.width,\n            x = con.x,\n            y = con.y;\n        if (!container) {\n            throw new Error(\"VML container not found.\");\n        }\n        var res = new R._Paper,\n            c = res.canvas = R._g.doc.createElement(\"div\"),\n            cs = c.style;\n        x = x || 0;\n        y = y || 0;\n        width = width || 512;\n        height = height || 342;\n        res.width = width;\n        res.height = height;\n        width == +width && (width += \"px\");\n        height == +height && (height += \"px\");\n        res.coordsize = zoom * 1e3 + S + zoom * 1e3;\n        res.coordorigin = \"0 0\";\n        res.span = R._g.doc.createElement(\"span\");\n        res.span.style.cssText = \"position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;\";\n        c.appendChild(res.span);\n        cs.cssText = R.format(\"top:0;left:0;width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden\", width, height);\n        if (container == 1) {\n            R._g.doc.body.appendChild(c);\n            cs.left = x + \"px\";\n            cs.top = y + \"px\";\n            cs.position = \"absolute\";\n        } else {\n            if (container.firstChild) {\n                container.insertBefore(c, container.firstChild);\n            } else {\n                container.appendChild(c);\n            }\n        }\n        res.renderfix = function () {};\n        return res;\n    };\n    R.prototype.clear = function () {\n        R.eve(\"raphael.clear\", this);\n        this.canvas.innerHTML = E;\n        this.span = R._g.doc.createElement(\"span\");\n        this.span.style.cssText = \"position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;\";\n        this.canvas.appendChild(this.span);\n        this.bottom = this.top = null;\n    };\n    R.prototype.remove = function () {\n        R.eve(\"raphael.remove\", this);\n        this.canvas.parentNode.removeChild(this.canvas);\n        for (var i in this) {\n            this[i] = typeof this[i] == \"function\" ? R._removedFactory(i) : null;\n        }\n        return true;\n    };\n\n    var setproto = R.st;\n    for (var method in elproto) if (elproto[has](method) && !setproto[has](method)) {\n        setproto[method] = (function (methodname) {\n            return function () {\n                var arg = arguments;\n                return this.forEach(function (el) {\n                    el[methodname].apply(el, arg);\n                });\n            };\n        })(method);\n    }\n}(window.Raphael);"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/diagram-viewer/js/textlayout.js",
    "content": "﻿\twindow.onload = function () {\n\t\t\tvar paper = Raphael(\"holder\");\n\n\t\t\t//var curve = paper.ellipse(100, 100, 1, 1).attr({\"stroke-width\": 0, fill: Color.red});\n\t\t\t\n\t\t\tvar text = \"Betty Botter bought some butter but, she said, the butter's bitter. If I put it in my batter, it will make my batter bitter. But a bit of better butter will make my batter better. So, she bought a bit of butter, better than her bitter butter, and she put it in her batter, and the batter was not bitter. It was better Betty Botter bought a bit better butter.\";\n\t\t\tvar font = {font: \"11px Arial\", \"font-style\":\"italic\", opacity: 1, \"fill\": LABEL_COLOR, stroke: LABEL_COLOR, \"stroke-width\":.3};\n\t\t\tvar font = {font: \"11px Arial\", opacity: 1, \"fill\": LABEL_COLOR};\n\t\t\tvar boxWidth = 100\n\t\t\t\n\t\t\tvar AttributedStringIterator = function(text){\n\t\t\t\t//this.text = this.rtrim(this.ltrim(text));\n\t\t\t\ttext = text.replace(/(\\s)+/, \" \");\n\t\t\t\tthis.text = this.rtrim(text);\n\t\t\t\t/*\n\t\t\t\tif (beginIndex < 0 || beginIndex > endIndex || endIndex > length()) {\n\t\t\t\t\tthrow new IllegalArgumentException(\"Invalid substring range\");\n\t\t\t\t}\n\t\t\t\t*/\n\t\t\t\tthis.beginIndex = 0;\n\t\t\t\tthis.endIndex = this.text.length;\n\t\t\t\tthis.currentIndex = this.beginIndex;\n\t\t\t\t\n\t\t\t\t//console.group(\"[AttributedStringIterator]\");\n\t\t\t\tvar i = 0;\n\t\t\t\tvar string = this.text;\n\t\t\t\tvar fullPos = 0;\n\t\t\t\t\n\t\t\t\t//console.log(\"string: \\\"\" + string + \"\\\", length: \" + string.length);\n\t\t\t\tthis.startWordOffsets = [];\n\t\t\t\tthis.startWordOffsets.push(fullPos);\n\t\t\t\t\n\t\t\t\t// TODO: remove i 1000\n\t\t\t\twhile (i<1000) {\n\t\t\t\t\tvar pos = string.search(/[ \\t\\n\\f-\\.\\,]/);\n\t\t\t\t\tif (pos == -1)\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\n\t\t\t\t\t// whitespace start\n\t\t\t\t\tfullPos += pos;\n\t\t\t\t\tstring = string.substr(pos);\n\t\t\t\t\t////console.log(\"fullPos: \" + fullPos + \", pos: \" + pos +  \", string: \", string);\n\t\t\t\t\t\n\t\t\t\t\t// remove whitespaces\n\t\t\t\t\tvar pos = string.search(/[^ \\t\\n\\f-\\.\\,]/);\n\t\t\t\t\tif (pos == -1)\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\n\t\t\t\t\t// whitespace end\n\t\t\t\t\tfullPos += pos;\n\t\t\t\t\tstring = string.substr(pos);\n\t\t\t\t\t\n\t\t\t\t\t////console.log(\"fullPos: \" + fullPos);\n\t\t\t\t\tthis.startWordOffsets.push(fullPos);\n\t\t\t\t\t\n\t\t\t\t\ti++;\n\t\t\t\t}\n\t\t\t\t//console.log(\"startWordOffsets: \", this.startWordOffsets);\n\t\t\t\t//console.groupEnd();\n\t\t\t};\n\t\t\tAttributedStringIterator.prototype = {\n\t\t\t\tgetEndIndex: function(pos){\n\t\t\t\t\tif (typeof(pos) == \"undefined\")\n\t\t\t\t\t\treturn this.endIndex;\n\t\t\t\t\t\t\n\t\t\t\t\tvar string = this.text.substr(pos, this.endIndex - pos);\n\t\t\t\t\t\n\t\t\t\t\tvar posEndOfLine = string.search(/[\\n]/);\n\t\t\t\t\tif (posEndOfLine == -1)\n\t\t\t\t\t\treturn this.endIndex;\n\t\t\t\t\telse\n\t\t\t\t\t\treturn pos + posEndOfLine;\n\t\t\t\t},\n\t\t\t\tgetBeginIndex: function(){\n\t\t\t\t\treturn this.beginIndex;\n\t\t\t\t},\n\t\t\t\tisWhitespace: function(pos){\n\t\t\t\t\tvar str = this.text[pos];\n\t\t\t\t\tvar whitespaceChars = \" \\t\\n\\f\";\n\t\t\t\t\t\n\t\t\t\t\treturn (whitespaceChars.indexOf(str) != -1);\n\t\t\t\t},\n\t\t\t\tisNewLine: function(pos){\n\t\t\t\t\tvar str = this.text[pos];\n\t\t\t\t\tvar whitespaceChars = \"\\n\";\n\t\t\t\t\t\n\t\t\t\t\treturn (whitespaceChars.indexOf(str) != -1);\n\t\t\t\t},\n\t\t\t\tpreceding: function(pos){\n\t\t\t\t\t//console.group(\"[AttributedStringIterator.preceding]\");\n\t\t\t\t\tfor(var i in this.startWordOffsets) {\n\t\t\t\t\t\tvar startWordOffset = this.startWordOffsets[i];\n\t\t\t\t\t\tif (pos < startWordOffset && i>0) {\n\t\t\t\t\t\t\t//console.log(\"startWordOffset: \" + this.startWordOffsets[i-1]);\n\t\t\t\t\t\t\t//console.groupEnd();\n\t\t\t\t\t\t\treturn this.startWordOffsets[i-1];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t//console.log(\"pos: \" + pos);\n\t\t\t\t\t//console.groupEnd();\n\t\t\t\t\treturn this.startWordOffsets[i];\n\t\t\t\t},\n\t\t\t\tfollowing: function(pos){\n\t\t\t\t\t//console.group(\"[AttributedStringIterator.following]\");\n\t\t\t\t\tfor(var i in this.startWordOffsets) {\n\t\t\t\t\t\tvar startWordOffset = this.startWordOffsets[i];\n\t\t\t\t\t\tif (pos < startWordOffset && i>0) {\n\t\t\t\t\t\t\t//console.log(\"startWordOffset: \" + this.startWordOffsets[i]);\n\t\t\t\t\t\t\t//console.groupEnd();\n\t\t\t\t\t\t\treturn this.startWordOffsets[i];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t//console.log(\"pos: \" + pos);\n\t\t\t\t\t//console.groupEnd();\n\t\t\t\t\treturn this.startWordOffsets[i];\n\t\t\t\t},\n\t\t\t\tltrim: function(str){\n\t\t\t\t\tvar patt2=/^\\s+/g;\n\t\t\t\t\treturn str.replace(patt2, \"\");\n\t\t\t\t}, \n\t\t\t\trtrim: function(str){\n\t\t\t\t\tvar patt2=/\\s+$/g;\n\t\t\t\t\treturn str.replace(patt2, \"\");\n\t\t\t\t},\n\t\t\t\tgetLayout: function(start, limit){\n\t\t\t\t\treturn this.text.substr(start, limit - start);\n\t\t\t\t},\n\t\t\t\tgetCharAtPos: function(pos) {\n\t\t\t\t\treturn this.text[pos];\n\t\t\t\t}\n\t\t\t};\n\t\t\t\n\t\t\t/*\n\t\t\tvar TextMeasurer = function(paper, text, fontAttrs){\n\t\t\t\tthis.text = text;\n\t\t\t\tthis.paper = paper;\n\t\t\t\tthis.fontAttrs = fontAttrs;\n\t\t\t\t\n\t\t\t\tthis.fStart = this.text.getBeginIndex();\n\n\t\t\t};\n\t\t\tTextMeasurer.prototype = {\n\t\t\t\tgetLineBreakIndex: function(start, maxAdvance){\n\t\t\t\t\tvar localStart = start - this.fStart;\n\t\t\t\t},\n\t\t\t\tgetLayout: function(){\n\t\t\t\t}\n\t\t\t}\n\t\t\t*/\n\t\t\t\n\t\t\t\n\t\t\tvar LineBreakMeasurer = function(paper, text, fontAttrs){\n\t\t\t\tthis.paper = paper;\n\t\t\t\tthis.text = new AttributedStringIterator(text);\n\t\t\t\tthis.fontAttrs = fontAttrs;\n\t\t\t\t\n\t\t\t\tif (this.text.getEndIndex() - this.text.getBeginIndex() < 1) {\n\t\t\t\t\tthrow {message: \"Text must contain at least one character.\", code: \"IllegalArgumentException\"};\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t//this.measurer = new TextMeasurer(paper, this.text, this.fontAttrs);\n\t\t\t\tthis.limit = this.text.getEndIndex();\n\t\t\t\tthis.pos = this.start = this.text.getBeginIndex();\n\t\t\t\t\n\t\t\t\tthis.rafaelTextObject = this.paper.text(100, 100, this.text.text).attr(fontAttrs).attr(\"text-anchor\", \"start\");\n\t\t\t\tthis.svgTextObject = this.rafaelTextObject[0];\n\t\t\t};\n\t\t\tLineBreakMeasurer.prototype = {\n\t\t\t\tnextOffset: function(wrappingWidth, offsetLimit, requireNextWord) {\n\t\t\t\t\t//console.group(\"[nextOffset]\");\n\t\t\t\t\tvar nextOffset = this.pos;\n\t\t\t\t\tif (this.pos < this.limit) {\n\t\t\t\t\t\tif (offsetLimit <= this.pos) {\n\t\t\t\t\t\t\tthrow {message: \"offsetLimit must be after current position\", code: \"IllegalArgumentException\"};\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tvar charAtMaxAdvance = this.getLineBreakIndex(this.pos, wrappingWidth);\n\t\t\t\t\t\t//charAtMaxAdvance --;\n\t\t\t\t\t\t//console.log(\"charAtMaxAdvance:\", charAtMaxAdvance, \", [\" + this.text.getCharAtPos(charAtMaxAdvance) + \"]\");\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (charAtMaxAdvance == this.limit) {\n\t\t\t\t\t\t\tnextOffset = this.limit;\n\t\t\t\t\t\t\t//console.log(\"charAtMaxAdvance == this.limit\");\n\t\t\t\t\t\t} else if (this.text.isNewLine(charAtMaxAdvance)) {\n\t\t\t\t\t\t\tconsole.log(\"isNewLine\");\n\t\t\t\t\t\t\tnextOffset = charAtMaxAdvance+1;\n\t\t\t\t\t\t} else if (this.text.isWhitespace(charAtMaxAdvance)) {\n\t\t\t\t\t\t\t// TODO: find next noSpaceChar\n\t\t\t\t\t\t\t//return nextOffset;\n\t\t\t\t\t\t\tnextOffset = this.text.following(charAtMaxAdvance);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Break is in a word;  back up to previous break.\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\tvar testPos = charAtMaxAdvance + 1;\n\t\t\t\t\t\t\tif (testPos == this.limit) {\n\t\t\t\t\t\t\t\tconsole.error(\"hbz...\");\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tnextOffset = this.text.preceding(charAtMaxAdvance);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tnextOffset = this.text.preceding(charAtMaxAdvance);\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif (nextOffset <= this.pos) {\n\t\t\t\t\t\t\t\tnextOffset = Math.max(this.pos+1, charAtMaxAdvance);\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 (nextOffset > offsetLimit) {\n\t\t\t\t\t\tnextOffset = offsetLimit;\n\t\t\t\t\t}\n\t\t\t\t\t//console.log(\"nextOffset: \" + nextOffset);\n\t\t\t\t\t//console.groupEnd();\n\t\t\t\t\treturn nextOffset;\n\t\t\t\t},\n\t\t\t\tnextLayout: function(wrappingWidth) {\n\t\t\t\t\t//console.groupCollapsed(\"[nextLayout]\");\n\t\t\t\t\tif (this.pos < this.limit) {\n\t\t\t\t\t\tvar requireNextWord = false;\n\t\t\t\t\t\tvar layoutLimit = this.nextOffset(wrappingWidth, this.limit, requireNextWord);\n\t\t\t\t\t\t//console.log(\"layoutLimit:\", layoutLimit);\n\t\t\t\t\t\tif (layoutLimit == this.pos) {\n\t\t\t\t\t\t\t//console.groupEnd();\n\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvar result = this.text.getLayout(this.pos, layoutLimit);\n\t\t\t\t\t\t//console.log(\"layout: \\\"\" + result + \"\\\"\");\n\t\t\t\t\t\t\n\t\t\t\t\t\t// remove end of line\n\t\t\t\t\t\t\n\t\t\t\t\t\t//var posEndOfLine = this.text.getEndIndex(this.pos);\n\t\t\t\t\t\t//if (posEndOfLine < result.length)\n\t\t\t\t\t\t//\tresult = result.substr(0, posEndOfLine);\n\t\t\t\t\t\t\n\t\t\t\t\t\tthis.pos = layoutLimit;\n\t\t\t\t\t\t\n\t\t\t\t\t\t//console.groupEnd();\n\t\t\t\t\t\treturn result;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t//console.groupEnd();\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tgetLineBreakIndex: function(pos, wrappingWidth) {\n\t\t\t\t\t//console.group(\"[getLineBreakIndex]\");\n\t\t\t\t\t//console.log(\"pos:\"+pos + \", text: \\\"\"+ this.text.text.replace(/\\n/g, \"_\").substr(pos, 1) + \"\\\"\");\n\t\t\t\t\t\n\t\t\t\t\tvar bb = this.rafaelTextObject.getBBox();\n\t\t\t\t\t\n\t\t\t\t\tvar charNum = -1;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tvar svgPoint = this.svgTextObject.getStartPositionOfChar(pos);\n\t\t\t\t\t\t//var dot = this.paper.ellipse(svgPoint.x, svgPoint.y, 1, 1).attr({\"stroke-width\": 0, fill: Color.blue});\n\t\t\t\t\t\tsvgPoint.x = svgPoint.x + wrappingWidth;\n\t\t\t\t\t\t//svgPoint.y = bb.y;\n\t\t\t\t\t\t//console.log(\"svgPoint:\", svgPoint);\n\t\t\t\t\t\n\t\t\t\t\t\t//var dot = this.paper.ellipse(svgPoint.x, svgPoint.y, 1, 1).attr({\"stroke-width\": 0, fill: Color.red});\n\t\t\t\t\t\n\t\t\t\t\t\tcharNum = this.svgTextObject.getCharNumAtPosition(svgPoint);\n\t\t\t\t\t} catch (e){\n\t\t\t\t\t\tconsole.warn(\"getStartPositionOfChar error, pos:\" + pos);\n\t\t\t\t\t\t/*\n\t\t\t\t\t\tvar testPos = pos + 1;\n\t\t\t\t\t\tif (testPos < this.limit) {\n\t\t\t\t\t\t\treturn testPos\n\t\t\t\t\t\t}\n\t\t\t\t\t\t*/\n\t\t\t\t\t}\n\t\t\t\t\t//console.log(\"charNum:\", charNum);\n\t\t\t\t\tif (charNum == -1) {\n\t\t\t\t\t\t//console.groupEnd();\n\t\t\t\t\t\treturn this.text.getEndIndex(pos);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// When case there is new line between pos and charnum then use this new line\n\t\t\t\t\t\tvar newLineIndex = this.text.getEndIndex(pos);\n\t\t\t\t\t\tif (newLineIndex < charNum ) {\n\t\t\t\t\t\t\tconsole.log(\"newLineIndex <= charNum, newLineIndex:\"+newLineIndex+\", charNum:\"+charNum, \"\\\"\" + this.text.text.substr(newLineIndex+1).replace(/\\n/g, \"↵\") + \"\\\"\");\n\t\t\t\t\t\t\t//console.groupEnd();\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\treturn newLineIndex;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t//var charAtMaxAdvance  = this.text.text.substring(charNum, charNum + 1);\n\t\t\t\t\t\tvar charAtMaxAdvance  = this.text.getCharAtPos(charNum);\n\t\t\t\t\t\t//console.log(\"!!charAtMaxAdvance: \" + charAtMaxAdvance);\n\t\t\t\t\t\t//console.groupEnd();\n\t\t\t\t\t\treturn charNum;\n\t\t\t\t\t}\n\t\t\t\t}, \n\t\t\t\tgetPosition: function() {\n\t\t\t\t\treturn this.pos;\n\t\t\t\t}\n\t\t\t};\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t// ******\n\t\t\tfunction drawMultilineText(text, x, y, boxWidth, boxHeight, options) {\n\t\t\t\tvar TEXT_PADDING = 3;\n\t\t\t\tvar width = boxWidth - (2 * TEXT_PADDING);\n\t\t\t\tif (boxHeight)\n\t\t\t\t\tvar height = boxHeight - (2 * TEXT_PADDING);\n\t\t\t\n\t\t\t\tvar layouts = [];\n\t\t\t\t\n\t\t\t\tvar measurer = new LineBreakMeasurer(paper, text, font);\n\t\t\t\tvar lineHeight = measurer.rafaelTextObject.getBBox().height;\n\t\t\t\tconsole.log(\"text: \", text.replace(/\\n/g, \"↵\"));\n\t\t\t\t\n\t\t\t\tif (height) {\n\t\t\t\t\tvar availableLinesCount = parseInt(height/lineHeight);\n\t\t\t\t\tconsole.log(\"availableLinesCount: \" + availableLinesCount);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tvar i = 1;\n\t\t\t\twhile (measurer.getPosition() < measurer.text.getEndIndex()) {\n\t\t\t\t\tvar layout = measurer.nextLayout(width);\n\t\t\t\t\t//console.log(\"LAYOUT: \" + layout + \", getPosition: \" + measurer.getPosition());\n\t\t\t\t\t\n\t\t\t\t\tif (layout != null) {\n\t\t\t\t\t\tif (!availableLinesCount || i < availableLinesCount) {\n\t\t\t\t\t\t\tlayouts.push(layout);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlayouts.push(fitTextToWidth(layout + \"...\", boxWidth));\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\ti++;\n\t\t\t\t};\n\t\t\t\tconsole.log(layouts);\n\t\t\t\t\n\t\t\t\tmeasurer.rafaelTextObject.attr({\"text\": layouts.join(\"\\n\")});\n\t\t\t\t//measurer.rafaelTextObject.attr({\"text-anchor\": \"end\"});\n\t\t\t\t//measurer.rafaelTextObject.attr({\"text-anchor\": \"middle\"});\n\t\t\t\tif (options)\n\t\t\t\t\tmeasurer.rafaelTextObject.attr({\"text-anchor\": options[\"text-anchor\"]});\n\t\t\t\t\t\n\t\t\t\tvar bb = measurer.rafaelTextObject.getBBox();\n\t\t\t\t//measurer.rafaelTextObject.attr({\"x\": x + boxWidth/2});\n\t\t\t\tif (options[\"vertical-align\"] == \"top\")\n\t\t\t\t\tmeasurer.rafaelTextObject.attr({\"y\": y + bb.height/2 + TEXT_PADDING});\n\t\t\t\telse\n\t\t\t\t\tmeasurer.rafaelTextObject.attr({\"y\": y + height/2});\n\t\t\t\t//var bb = measurer.rafaelTextObject.getBBox();\n\t\t\t\t\n\t\t\t\tif (measurer.rafaelTextObject.attr(\"text-anchor\") == \"middle\" )\n\t\t\t\t\tmeasurer.rafaelTextObject.attr(\"x\",  x + boxWidth/2 + TEXT_PADDING/2);\n\t\t\t\telse if (measurer.rafaelTextObject.attr(\"text-anchor\") == \"end\" )\n\t\t\t\t\tmeasurer.rafaelTextObject.attr(\"x\",  x + boxWidth + TEXT_PADDING/2);\n\t\t\t\telse \n\t\t\t\t\tmeasurer.rafaelTextObject.attr(\"x\", x + boxWidth/2 - bb.width/2 + TEXT_PADDING/2);\n\t\t\t\t\n\t\t\t\tvar boxStyle = {stroke: Color.LightSteelBlue2, \"stroke-width\": 1.0, \"stroke-dasharray\": \"- \"};\n\t\t\t\t/*\n\t\t\t\tvar box = paper.rect(x+.0 + boxWidth/2 - bb.width/2+ TEXT_PADDING/2, y + .5 + boxHeight/2 - bb.height/2, width, height).attr(boxStyle);\n\t\t\t\tbox.attr(\"height\", bb.height);\n\t\t\t\t*/\n\t\t\t\t//var box = paper.rect(bb.x - .5 + bb.width/2 + TEXT_PADDING, bb.y + bb.height/2, bb.width, bb.height).attr(boxStyle);\n\t\t\t\t\n\t\t\t\tvar textAreaCX = x + boxWidth/2;\n\t\t\t\tvar textAreaCY = y + height/2;\n\t\t\t\tvar dotLeftTop = paper.ellipse(x, y, 3, 3).attr({\"stroke-width\": 0, fill: Color.LightSteelBlue, stroke: \"none\"});\n\t\t\t\tvar dotCenter = paper.ellipse(textAreaCX, textAreaCY, 3, 3).attr({fill: Color.LightSteelBlue2, stroke: \"none\"});\n\n\t\t\t\t/*\n\t\t\t\t// real bbox\n\t\t\t\tvar bb = measurer.rafaelTextObject.getBBox();\n\t\t\t\tvar rect = paper.rect(bb.x+.5, bb.y + .5, bb.width, bb.height).attr({\"stroke-width\": 1});\n\t\t\t\t*/\n\t\t\t\tvar boxStyle = {stroke: Color.LightSteelBlue2, \"stroke-width\": 1.0, \"stroke-dasharray\": \"- \"};\n\t\t\t\tvar rect = paper.rect(x+.5, y + .5, boxWidth, boxHeight).attr(boxStyle);\n\t\t\t}\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t/*\n\t\t\tfor (var i=0; i<1; i++) {\n\t\t\t\tvar t = text;\n\t\t\t\t//var t = \"Высококвалифицирова\";\n\t\t\t\t\n\t\t\t\tvar text = paper.text(300, 100, t).attr(font).attr(\"text-anchor\", \"start\");\n\t\t\t\tvar bbText = text.getBBox();\n\t\t\t\tpaper.rect(300+.5, 100 + .5, bbText.width, bbText.height).attr({\"stroke-width\": 1});\n\t\t\t\tconsole.log(\"t: \", t.replace(/\\n/g, \"↵\"));\n\t\t\t\t\n\t\t\t\twhile (measurer.getPosition() < measurer.text.getEndIndex()) {\n\t\t\t\t\tvar layout = measurer.nextLayout(width);\n\t\t\t\t\t//console.log(\"LAYOUT: \" + layout + \", getPosition: \" + measurer.getPosition());\n\t\t\t\t\tif (layout != null)\n\t\t\t\t\t\tlayouts.push(layout);\n\t\t\t\t};\n\t\t\t\t\n\t\t\t\tmeasurer.rafaelTextObject.attr(\"text\", layouts.join(\"\\n\"));\n\t\t\t\tvar bb = measurer.rafaelTextObject.getBBox();\n\t\t\t\tvar rect = paper.rect(bb.x+.5, bb.y + .5, bb.width, bb.height).attr({\"stroke-width\": 1});\n\t\t\t\t\n\t\t\t\tlay.push(layouts);\n\t\t\t\tconsole.log(layouts);\n\t\t\t}\n\t\t\t*/\n\t\t\t\n\t\t\t\n\t\t\tvar fitTextToWidth = function(original, width) {\n\t\t\t\tvar text = original;\n\n\t\t\t\t// TODO: move attr on parameters\n\t\t\t\tvar attr = {font: \"11px Arial\", opacity: 0};\n\t\t\t\t\n\t\t\t\t// remove length for \"...\"\n\t\t\t\tvar dots = paper.text(0, 0, \"...\").attr(attr).hide();\n\t\t\t\tvar dotsBB = dots.getBBox();\n\t\t\t\t\n\t\t\t\tvar maxWidth = width - dotsBB.width;\n\t\t\t\t\n\t\t\t\tvar textElement = paper.text(0, 0, text).attr(attr).hide();\n\t\t\t\tvar bb = textElement.getBBox();\n\t\t\t\t\n\t\t\t\t// it's a little bit incorrect with \"...\"\n\t\t\t\twhile (bb.width > maxWidth && text.length > 0) {\n\t\t\t\t\ttext = text.substring(0, text.length - 1);\n\t\t\t\t\ttextElement.attr({\"text\": text});\n\t\t\t\t\tbb = textElement.getBBox();\n\t\t\t\t}\n\n\t\t\t\t// remove element from paper\n\t\t\t\ttextElement.remove();\n\t\t\t\t\n\t\t\t\tif (text != original) {\n\t\t\t\t\ttext = text + \"...\";\n\t\t\t\t}\n\n\t\t\t\treturn text;\n\t\t\t}\n\t\t\t\n\t\t\t\n\t\t\tvar x=100, y=90, height=20;\n\t\t\tvar options = {\"text-anchor\": \"middle\", \"boxHeight\": 150, \"vertical-align\": \"top\"};\n\t\t\tvar options = {\"boxHeight\": 150, \"vertical-align\": \"top\"};\n\t\t\tdrawMultilineText(text, x, y, 150, 100, options);\n\t};"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/diagram-viewer/style.css",
    "content": "body {\r    background: #fafafa;\r    color: #708090;\r    /* font: 300 100.1% \"Helvetica Neue\", Helvetica, \"Arial Unicode MS\", Arial, sans-serif; */\r\tfont-family: Verdana, sans-serif, Arial;\r\tfont-size: 10px;\r}\r.wrapper{\r\theight: 100%;\r\tposition: relative;\r\twidth: 100%;\r}\r/*\r#holder {\r    height: 480px;\r    width: 640px;\r\tb_ackground: #F8F8FF;\r\t\r\t-moz-border-radius: 10px;\r\t-webkit-border-radius: 10px;\r\t-webkit-box-shadow: 0 1px 3px #666;\r\tbackground: #DDD url(./images/bg.png);\r\t/* background: #DDD url(./images/checker-bg.png); * /\r\tb_order:0px solid #dedede;\r}\r*/\rdiv.diagramHolder {\r\tfloat:left; \r}\rdiv.diagram{\r\tborder:1px solid #dedede;\r\tmargin: 5px;\r\tpadding: 5px;\r\tbackground: #FFF;\r}\rdiv.diagram.hidden{\r\tdisplay:none;\r}\rsvg {\r\tbackground: #DDD url(./images/bg.png);\r}\r\rdiv.diagram-info {\r\tfloat:left;\r\tposition: relative;\r\tpadding: 5px;\r}\r\r/* Breadcrumbs */\r\r#diagramBreadCrumbs {\r\tmargin-left: 2px;\r\tmargin-right: 2px;\r\tmargin-top: 10px;\r}\r#diagramBreadCrumbs ul {\r\tlist-style: none;\r\t\r\tbackground-color: white;\r\tborder: 1px solid #DEDEDE;\r\tborder-color: #C0C2C5;\r\tmargin: 0;\r\t\r\tmargin-bottom: 10px;\r\tmargin-left: 0;\r\t\r\t-webkit-padding-start: 0px;\r\t-moz-border-radius: 4px;\r\t-webkit-border-radius: 4px;\r\tborder-radius: 4px;\r}\r#diagramBreadCrumbs li {\r\t/*text-decoration: underline;*/\r\tdisplay: inline-block;\r\tvertical-align: middle;\r\tpadding-left: .75em;\r\tpadding-right: 0;\r\tcursor: pointer;\r}\r#diagramBreadCrumbs li.selected {\r\tcolor: #9370DB;\r\tcolor: #4876FF;\r\tcolor: #4F94CD;\r\tfont-weight: bold;\r}\r#diagramBreadCrumbs li span {\r\tbackground: url(images/breadcrumbs.png) no-repeat 100% 50%;\r\tdisplay: block;\r\tpadding: .5em 15px .5em 0;\r}\r\r\r/* Progress bar */\r\r.ui-progressbar { \r\theight: 25px;\r\t/*height:2em; text-align: left; overflow: hidden; */\r\tbackground: white;\r\tborder: 1px solid #949DAD;\r\tmargin: 2px;\r\toverflow: hidden;\r\tpadding: 1px;\r\tposition: relative;\r\r\t-moz-border-radius: 4px;\r\t-webkit-border-radius: 4px;\r\tborder-radius: 4px;\r}\r.ui-progressbar .ui-progressbar-value {\r\tm_argin: -1px;\r\theight:100%;\r\tbackground: #D4E4FF;\r\t\r\t-moz-border-radius: 4px;\r\t-webkit-border-radius: 4px;\r\tborder-radius: 4px;\r}\r.ui-widget-header a { color: #222222/*{fcHeader}*/; }\r\r.ui-progressbar .ui-progressbar-label{\r\tposition: absolute;\r\tmargin-top: 7px;\r\tborder:0px solid red;\r\twidth: 100%;\r\ttext-align: center;\r}"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/app-cfg.js",
    "content": "/*\n * Activiti Modeler component part of the Activiti project\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * \n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n */\n'use strict';\n\nvar ACTIVITI = ACTIVITI || {};\n\nACTIVITI.CONFIG = {\n\t'contextRoot' : '/service',\n};\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/app.js",
    "content": "/*\n * Activiti Modeler component part of the Activiti project\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * \n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n */\n'use strict';\n\nvar activitiModeler = angular.module('activitiModeler', [\n  'ngCookies',\n  'ngResource',\n  'ngSanitize',\n  'ngRoute',\n  'ngDragDrop',\n  'mgcrea.ngStrap', \n  'ngGrid',\n  'ngAnimate',\n  'pascalprecht.translate',\n  'duScroll'\n]);\n\nvar activitiModule = activitiModeler;\n\nactivitiModeler\n  // Initialize routes\n  .config(['$selectProvider', '$translateProvider', function ($selectProvider, $translateProvider) {\n\n      // Override caret for bs-select directive\n      angular.extend($selectProvider.defaults, {\n          caretHtml: '&nbsp;<i class=\"icon icon-caret-down\"></i>'\n      });\n        \n        // Initialize angular-translate\n        $translateProvider.useStaticFilesLoader({\n            prefix: './editor-app/i18n/',\n            suffix: '.json'\n        });\n\n        $translateProvider.preferredLanguage('en');\n\n        // remember language\n        $translateProvider.useCookieStorage();\n        \n  }])\n  .run(['$rootScope', '$timeout', '$modal', '$translate', '$location', '$window', '$http', '$q',\n        function($rootScope, $timeout, $modal, $translate, $location, $window, $http, $q) {\n\t  \n\t\t\t  $rootScope.config = ACTIVITI.CONFIG;\n\t\t\t  \n\t\t\t  $rootScope.editorInitialized = false;\n\t\t      \n\t\t      $rootScope.editorFactory = $q.defer();\n\t\t\n\t\t      $rootScope.forceSelectionRefresh = false;\n\t\t\n\t\t      $rootScope.ignoreChanges = false; // by default never ignore changes\n\t\t      \n\t\t      $rootScope.validationErrors = [];\n\t\t      \n\t\t      $rootScope.staticIncludeVersion = Date.now();\n\n\t\t\t  /**\n\t\t       * A 'safer' apply that avoids concurrent updates (which $apply allows).\n\t\t       */\n\t\t      $rootScope.safeApply = function(fn) {\n\t\t          var phase = this.$root.$$phase;\n\t\t          if(phase == '$apply' || phase == '$digest') {\n\t\t              if(fn && (typeof(fn) === 'function')) {\n\t\t                  fn();\n\t\t              }\n\t\t          } else {\n\t\t              this.$apply(fn);\n\t\t          }\n\t\t      };\n\t  \n\t  \n            /**\n             * Initialize the event bus: couple all Oryx events with a dispatch of the\n             * event of the event bus. This way, it gets much easier to attach custom logic\n             * to any event.\n             */\n\n            /* Helper method to fetch model from server (always needed) */\n            function fetchModel(modelId) {\n\n                var modelUrl = KISBPM.URL.getModel(modelId);\n                // alert(modelUrl);\n\n                $http({method: 'GET', url: modelUrl}).\n                    success(function (data, status, headers, config) {\n                        $rootScope.editor = new ORYX.Editor(data);\n                        $rootScope.modelData = angular.fromJson(data);\n                        $rootScope.editorFactory.resolve();\n                    }).\n                    error(function (data, status, headers, config) {\n                      console.log('Error loading model with id ' + modelId + ' ' + data);\n                    });\n            }\n\n\n            function initScrollHandling() {\n                var canvasSection = jQuery('#canvasSection');\n                canvasSection.scroll(function() {\n\n                    // Hides the resizer and quick menu items during scrolling\n\n                    var selectedElements = $rootScope.editor.selection;\n                    var subSelectionElements = $rootScope.editor._subSelection;\n\n                    $rootScope.selectedElements = selectedElements;\n                    $rootScope.subSelectionElements = subSelectionElements;\n                    if (selectedElements && selectedElements.length > 0) {\n                    \t$rootScope.selectedElementBeforeScrolling = selectedElements[0];\n                    }\n\n                    jQuery('.Oryx_button').each(function(i, obj) {\n                    \t$rootScope.orginalOryxButtonStyle = obj.style.display;\n                    \tobj.style.display = 'none';\n                    });\n                    \n                    jQuery('.resizer_southeast').each(function(i, obj) {\n                    \t$rootScope.orginalResizerSEStyle = obj.style.display;\n                        obj.style.display = 'none';\n                    });\n                    jQuery('.resizer_northwest').each(function(i, obj) {\n                    \t$rootScope.orginalResizerNWStyle = obj.style.display;\n                        obj.style.display = 'none';\n                    });\n                    $rootScope.editor.handleEvents({type:ORYX.CONFIG.EVENT_CANVAS_SCROLL});\n                });\n\n                canvasSection.scrollStopped(function(){\n\n                    // Puts the quick menu items and resizer back when scroll is stopped.\n\n                    $rootScope.editor.setSelection([]); // needed cause it checks for element changes and does nothing if the elements are the same\n                    $rootScope.editor.setSelection($rootScope.selectedElements, $rootScope.subSelectionElements);\n                    $rootScope.selectedElements = undefined;\n                    $rootScope.subSelectionElements = undefined;\n\n                    function handleDisplayProperty(obj) {\n                        if (jQuery(obj).position().top > 0) {\n                            obj.style.display = 'block';\n                        } else {\n                            obj.style.display = 'none';\n                        }\n                    }\n\n                    jQuery('.Oryx_button').each(function(i, obj) {\n                        handleDisplayProperty(obj);\n                    });\n                    \n                    jQuery('.resizer_southeast').each(function(i, obj) {\n                        handleDisplayProperty(obj);\n                    });\n                    jQuery('.resizer_northwest').each(function(i, obj) {\n                        handleDisplayProperty(obj);\n                    });\n\n                });\n            }\n\n            /**\n             * Initialize the Oryx Editor when the content has been loaded\n             */\n            $rootScope.$on('$includeContentLoaded', function (event) {\n\t            if (!$rootScope.editorInitialized) {\n\n\t            \tORYX._loadPlugins();\n\t\n\t                var modelId = EDITOR.UTIL.getParameterByName('modelId');\n\t                fetchModel(modelId);\n\t\n\t                $rootScope.window = {};\n\t                var updateWindowSize = function() {\n\t                    $rootScope.window.width = $window.innerWidth;\n\t                    $rootScope.window.height  = $window.innerHeight;\n\t                };\n\t\n\t                // Window resize hook\n\t                angular.element($window).bind('resize', function() {\n\t                    $rootScope.safeApply(updateWindowSize());\n\t                });\n\t\n\t                $rootScope.$watch('window.forceRefresh', function(newValue) {\n\t                    if(newValue) {\n\t                        $timeout(function() {\n\t                            updateWindowSize();\n\t                            $rootScope.window.forceRefresh = false;\n\t                        });\n\t                    }\n\t                });\n\t\n\t                updateWindowSize();\n\n\t                // Hook in resizing of main panels when window resizes\n\t                // TODO: perhaps move to a separate JS-file?\n\t                jQuery(window).resize(function () {\n\n\t                    // Calculate the offset based on the bottom of the module header\n\t                    var offset = jQuery(\"#editor-header\").offset();\n\t                    var propSectionHeight = jQuery('#propertySection').height();\n\t                    var canvas = jQuery('#canvasSection');\n\t                    var mainHeader = jQuery('#main-header');\n\n\t                    if (offset == undefined || offset === null\n\t                        || propSectionHeight === undefined || propSectionHeight === null\n\t                        || canvas === undefined || canvas === null || mainHeader === null) {\n\t                        return;\n\t                    }\n\t                    \n\t                    if ($rootScope.editor)\n\t                \t{\n\t        \t        \tvar selectedElements = $rootScope.editor.selection;\n\t        \t            var subSelectionElements = $rootScope.editor._subSelection;\n\t        \t\n\t        \t            $rootScope.selectedElements = selectedElements;\n\t        \t            $rootScope.subSelectionElements = subSelectionElements;\n\t        \t            if (selectedElements && selectedElements.length > 0)\n\t        \t            {\n\t        \t            \t$rootScope.selectedElementBeforeScrolling = selectedElements[0];\n\t        \t            \t\n\t        \t            \t$rootScope.editor.setSelection([]); // needed cause it checks for element changes and does nothing if the elements are the same\n\t        \t                $rootScope.editor.setSelection($rootScope.selectedElements, $rootScope.subSelectionElements);\n\t        \t                $rootScope.selectedElements = undefined;\n\t        \t                $rootScope.subSelectionElements = undefined;\n\t        \t            }\n\t                \t}\n\n\t                    var totalAvailable = jQuery(window).height() - offset.top - mainHeader.height() - 21;\n\t                    canvas.height(totalAvailable - propSectionHeight);\n\t                    jQuery('#paletteSection').height(totalAvailable);\n\n\t                    // Update positions of the resize-markers, according to the canvas\n\n\t                    var actualCanvas = null;\n\t                    if (canvas && canvas[0].children[1]) {\n\t                        actualCanvas = canvas[0].children[1];\n\t                    }\n\n\t                    var canvasTop = canvas.position().top;\n\t                    var canvasLeft = canvas.position().left;\n\t                    var canvasHeight = canvas[0].clientHeight;\n\t                    var canvasWidth = canvas[0].clientWidth;\n\t                    var iconCenterOffset = 8;\n\t                    var widthDiff = 0;\n\n\t                    var actualWidth = 0;\n\t                    if(actualCanvas) {\n\t                        // In some browsers, the SVG-element clientwidth isn't available, so we revert to the parent\n\t                        actualWidth = actualCanvas.clientWidth || actualCanvas.parentNode.clientWidth;\n\t                    }\n\n\n\t                    if(actualWidth < canvas[0].clientWidth) {\n\t                        widthDiff = actualWidth - canvas[0].clientWidth;\n\t                        // In case the canvas is smaller than the actual viewport, the resizers should be moved\n\t                        canvasLeft -= widthDiff / 2;\n\t                        canvasWidth += widthDiff;\n\t                    }\n\n\t                    var iconWidth = 17;\n\t                    var iconOffset = 20;\n\n\t                    var north = jQuery('#canvas-grow-N');\n\t                    north.css('top', canvasTop + iconOffset + 'px');\n\t                    north.css('left', canvasLeft - 10 + (canvasWidth - iconWidth) / 2 + 'px');\n\n\t                    var south = jQuery('#canvas-grow-S');\n\t                    south.css('top', (canvasTop + canvasHeight - iconOffset - iconCenterOffset) +  'px');\n\t                    south.css('left', canvasLeft - 10 + (canvasWidth - iconWidth) / 2 + 'px');\n\n\t                    var east = jQuery('#canvas-grow-E');\n\t                    east.css('top', canvasTop - 10 + (canvasHeight - iconWidth) / 2 + 'px');\n\t                    east.css('left', (canvasLeft + canvasWidth - iconOffset - iconCenterOffset) + 'px');\n\n\t                    var west = jQuery('#canvas-grow-W');\n\t                    west.css('top', canvasTop -10 + (canvasHeight - iconWidth) / 2 + 'px');\n\t                    west.css('left', canvasLeft + iconOffset + 'px');\n\n\t                    north = jQuery('#canvas-shrink-N');\n\t                    north.css('top', canvasTop + iconOffset + 'px');\n\t                    north.css('left', canvasLeft + 10 + (canvasWidth - iconWidth) / 2 + 'px');\n\n\t                    south = jQuery('#canvas-shrink-S');\n\t                    south.css('top', (canvasTop + canvasHeight - iconOffset - iconCenterOffset) +  'px');\n\t                    south.css('left', canvasLeft +10 + (canvasWidth - iconWidth) / 2 + 'px');\n\n\t                    east = jQuery('#canvas-shrink-E');\n\t                    east.css('top', canvasTop + 10 + (canvasHeight - iconWidth) / 2 +  'px');\n\t                    east.css('left', (canvasLeft + canvasWidth - iconOffset - iconCenterOffset) + 'px');\n\n\t                    west = jQuery('#canvas-shrink-W');\n\t                    west.css('top', canvasTop + 10 + (canvasHeight - iconWidth) / 2 + 'px');\n\t                    west.css('left', canvasLeft + iconOffset + 'px');\n\t                });\n\n\t                jQuery(window).trigger('resize');\n\n\t                jQuery.fn.scrollStopped = function(callback) {\n\t                    jQuery(this).scroll(function(){\n\t                        var self = this, $this = jQuery(self);\n\t                        if ($this.data('scrollTimeout')) {\n\t                            clearTimeout($this.data('scrollTimeout'));\n\t                        }\n\t                        $this.data('scrollTimeout', setTimeout(callback,50,self));\n\t                    });\n\t                };\n\t                \n\t                // Always needed, cause the DOM element on which the scroll event listeners are attached are changed for every new model\n\t                initScrollHandling();\n\t                \n\t                $rootScope.editorInitialized = true;\n\t            }\n            });\n\n            /**\n             * Initialize the event bus: couple all Oryx events with a dispatch of the\n             * event of the event bus. This way, it gets much easier to attach custom logic\n             * to any event.\n             */\n\n            $rootScope.editorFactory.promise.then(function() {\n\n                KISBPM.eventBus.editor = $rootScope.editor;\n\n                var eventMappings = [\n                    { oryxType : ORYX.CONFIG.EVENT_SELECTION_CHANGED, kisBpmType : KISBPM.eventBus.EVENT_TYPE_SELECTION_CHANGE },\n                    { oryxType : ORYX.CONFIG.EVENT_DBLCLICK, kisBpmType : KISBPM.eventBus.EVENT_TYPE_DOUBLE_CLICK },\n                    { oryxType : ORYX.CONFIG.EVENT_MOUSEOUT, kisBpmType : KISBPM.eventBus.EVENT_TYPE_MOUSE_OUT },\n                    { oryxType : ORYX.CONFIG.EVENT_MOUSEOVER, kisBpmType : KISBPM.eventBus.EVENT_TYPE_MOUSE_OVER }\n\n                ];\n\n                eventMappings.forEach(function(eventMapping) {\n                    $rootScope.editor.registerOnEvent(eventMapping.oryxType, function(event) {\n                        KISBPM.eventBus.dispatch(eventMapping.kisBpmType, event);\n                    });\n                });\n                \n                $rootScope.editor.registerOnEvent(ORYX.CONFIG.EVENT_SHAPEREMOVED, function (event) {\n    \t    \t\tvar validateButton = document.getElementById(event.shape.resourceId + \"-validate-button\");\n    \t    \t\tif (validateButton)\n    \t    \t\t{\n    \t    \t\t\tvalidateButton.style.display = 'none';\n    \t    \t\t}\n                });\n\n                // The Oryx canvas is ready (we know since we're in this promise callback) and the\n                // event bus is ready. The editor is now ready for use\n                KISBPM.eventBus.dispatch(KISBPM.eventBus.EVENT_TYPE_EDITOR_READY, {type : KISBPM.eventBus.EVENT_TYPE_EDITOR_READY});\n\n            });\n            \n            // Alerts\n            $rootScope.alerts = {\n                queue: []\n            };\n          \n            $rootScope.showAlert = function(alert) {\n                if(alert.queue.length > 0) {\n                    alert.current = alert.queue.shift();\n                    // Start timout for message-pruning\n                    alert.timeout = $timeout(function() {\n                        if (alert.queue.length == 0) {\n                            alert.current = undefined;\n                            alert.timeout = undefined;\n                        } else {\n                            $rootScope.showAlert(alert);\n                        }\n                    }, (alert.current.type == 'error' ? 5000 : 1000));\n                } else {\n                    $rootScope.alerts.current = undefined;\n                }\n            };\n          \n            $rootScope.addAlert = function(message, type) {\n                var newAlert = {message: message, type: type};\n                if (!$rootScope.alerts.timeout) {\n                    // Timeout for message queue is not running, start one\n                    $rootScope.alerts.queue.push(newAlert);\n                    $rootScope.showAlert($rootScope.alerts);\n                } else {\n                    $rootScope.alerts.queue.push(newAlert);\n                }\n            };\n          \n            $rootScope.dismissAlert = function() {\n                if (!$rootScope.alerts.timeout) {\n                    $rootScope.alerts.current = undefined;\n                } else {\n                    $timeout.cancel($rootScope.alerts.timeout);\n                    $rootScope.alerts.timeout = undefined;\n                    $rootScope.showAlert($rootScope.alerts);\n                }\n            };\n          \n            $rootScope.addAlertPromise = function(promise, type) {\n                if (promise) {\n                    promise.then(function(data) {\n                        $rootScope.addAlert(data, type);\n                    });\n                }\n            };\n          \n        }\n  ])\n\n    // Moment-JS date-formatting filter\n    .filter('dateformat', function() {\n        return function(date, format) {\n            if (date) {\n                if (format) {\n                    return moment(date).format(format);\n                } else {\n                    return moment(date).calendar();\n                }\n            }\n            return '';\n        };\n    });\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/assignment-display-template.html",
    "content": "<span ng-if=\"property.value.assignment.assignee\">{{'PROPERTY.ASSIGNMENT.ASSIGNEE_DISPLAY' | translate:property.value.assignment }} </span>\n<span ng-if=\"property.value.assignment.candidateUsers.length > 0\">{{'PROPERTY.ASSIGNMENT.CANDIDATE_USERS_DISPLAY' | translate:property.value.assignment.candidateUsers}} </span>\n<span ng-if=\"property.value.assignment.candidateGroups.length > 0\">{{'PROPERTY.ASSIGNMENT.CANDIDATE_GROUPS_DISPLAY' | translate:property.value.assignment.candidateGroups}} </span>\n<span ng-if=\"!property.value.assignment.assignee && (!property.value.assignment.candidateUsers || property.value.assignment.candidateUsers.length == 0) && (!property.value.assignment.candidateGroups || property.value.assignment.candidateGroups.length == 0)\" translate>PROPERTY.ASSIGNMENT.EMPTY</span>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/assignment-popup.html",
    "content": "<div class=\"modal\" ng-controller=\"KisBpmAssignmentPopupCtrl\">\n    <div class=\"modal-dialog\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header\">\n                <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\" ng-click=\"close()\">&times;</button>\n                <h2 translate>PROPERTY.ASSIGNMENT.TITLE</h2>\n            </div>\n            <div class=\"modal-body\">\n            \n            \t<div class=\"row row-no-gutter\">\n            \t\t<div class=\"form-group\">\n            \t\t\t<label for=\"assigneeField\">{{'PROPERTY.ASSIGNMENT.ASSIGNEE' | translate}}</label>\n            \t\t\t<input type=\"text\" id=\"assigneeField\" class=\"form-control\" ng-model=\"assignment.assignee\" placeholder=\"{{'PROPERTY.ASSIGNMENT.ASSIGNEE_PLACEHOLDER' | translate}}\" />\n            \t\t</div>\n            \t</div>\n            \t\n                <div class=\"row row-no-gutter\">\n                    <div class=\"form-group\">\n                    \t<label for=\"userField\">{{'PROPERTY.ASSIGNMENT.CANDIDATE_USERS' | translate}}</label>\n                        <div ng-repeat=\"candidateUser in assignment.candidateUsers\">\n            \t            <input id=\"userField\" class=\"form-control\" type=\"text\" ng-model=\"candidateUser.value\" />\n            \t            <i class=\"glyphicon glyphicon-minus clickable-property\" ng-click=\"removeCandidateUserValue($index)\"></i>\n            \t            <i ng-if=\"$index == (assignment.candidateUsers.length - 1)\" class=\"glyphicon glyphicon-plus clickable-property\" ng-click=\"addCandidateUserValue($index)\"></i>\n                        </div>\n                   \t</div>\n            \n                    <div class=\"form-group\">\n                    \t<label for=\"groupField\">{{'PROPERTY.ASSIGNMENT.CANDIDATE_GROUPS' | translate}}</label>\n                        <div ng-repeat=\"candidateGroup in assignment.candidateGroups\">\n            \t          \t<input id=\"groupField\" class=\"form-control\" type=\"text\" ng-model=\"candidateGroup.value\" />\n            \t          \t<i class=\"glyphicon glyphicon-minus clickable-property\" ng-click=\"removeCandidateGroupValue($index)\"></i>\n            \t          \t<i ng-if=\"$index == (assignment.candidateGroups.length - 1)\" class=\"glyphicon glyphicon-plus clickable-property\" ng-click=\"addCandidateGroupValue($index)\"></i>\n                        </div>\n                    </div>\n                </div>\n            \n            </div>\n            <div class=\"modal-footer\">\n                <button ng-click=\"close()\" class=\"btn btn-primary\" translate>ACTION.CANCEL</button>\n                <button ng-click=\"save()\" class=\"btn btn-primary\" translate>ACTION.SAVE</button>\n            </div>\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/assignment-write-template.html",
    "content": "\n<!-- Just need to instantiate the controller, and it will take care of showing the modal dialog -->\n<span ng-controller=\"KisBpmAssignmentCtrl\">\n</span>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/boolean-property-template.html",
    "content": "\n<div ng-controller=\"KisBpmBooleanPropertyCtrl\">\n    <input type=\"checkbox\" ng-model=\"property.value\" ng-change=\"changeValue()\"/>\n</div>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/condition-expression-display-template.html",
    "content": "<span ng-if=\"property.value\">{{property.value|limitTo:20}}</span>\n<span ng-if=\"!property.value\">{{'PROPERTY.SEQUENCEFLOW.CONDITION.NO-CONDITION-DISPLAY' | translate}}</span>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/condition-expression-popup.html",
    "content": "\n<div class=\"modal\" ng-controller=\"KisBpmConditionExpressionPopupCtrl\">\n<div class=\"modal-dialog\">\n<div class=\"modal-content\">\n<div class=\"modal-header\">\n    <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\" ng-click=\"close()\">&times;</button>\n    <h2 translate>PROPERTY.SEQUENCEFLOW.CONDITION.TITLE</h2>\n</div>\n<div class=\"modal-body\">\n\n    <div class=\"detail-group clearfix\">\n        \n        <div class=\"form-group clearfix\">\n            <div class=\"col-xs-12\">\n                <label class=\"col-xs-3\">{{'PROPERTY.SEQUENCEFLOW.CONDITION.STATIC' | translate}}</label>\n                <div class=\"col-xs-9\">\n                    <textarea class=\"form-control\" ng-model=\"conditionExpression.value\" style=\"width:90%; height:100%; max-width: 100%; max-height: 100%; min-height: 100px\"/>\n                </div>\n            </div>\n        </div>\n\n    </div>\n    <div class=\"modal-footer\">\n        <button ng-click=\"close()\" class=\"btn btn-primary\" translate>ACTION.CANCEL</button>\n        <button ng-click=\"save()\" class=\"btn btn-primary\" translate>ACTION.SAVE</button>\n    </div>\n</div>\n</div>\n</div>\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/condition-expression-write-template.html",
    "content": "\n<!-- Just need to instantiate the controller, and it will take care of showing the modal dialog -->\n<span ng-controller=\"KisBpmConditionExpressionCtrl\">\n</span>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/default-value-display-template.html",
    "content": "\n<span ng-if=\"!property.noValue\">{{property.value|limitTo:20}}</span>\n<span ng-if=\"!property.noValue && property.value != null && property.value.length > 20\">...</span>\n<span ng-if=\"property.noValue\" translate>PROPERTY.EMPTY</span>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/event-listeners-display-template.html",
    "content": "\n<span ng-if=\"!property.noValue\">{{'PROPERTY.EVENTLISTENERS.DISPLAY' | translate:property.value.eventListeners}}</span>\n<span ng-if=\"property.noValue\" translate>PROPERTY.EVENTLISTENERS.EMPTY</span>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/event-listeners-popup.html",
    "content": "\n<div class=\"modal\" ng-controller=\"KisBpmEventListenersPopupCtrl\">\n    <div class=\"modal-dialog modal-wide\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header\">\n                <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\" ng-click=\"close()\">&times;</button>\n                <h2>{{'PROPERTY.PROPERTY.EDIT.TITLE' | translate:property}}</h2>\n            </div>\n            <div class=\"modal-body\">\n            \n                <div class=\"row row-no-gutter\">\n                \t<div class=\"col-xs-10\">\n            \t        <div ng-if=\"translationsRetrieved\" class=\"kis-listener-grid\" ng-grid=\"gridOptions\"></div>\n            \t        <div class=\"pull-right\">\n            \t            <div class=\"btn-group\">\n            \t                <a class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{ACTION.MOVE.UP | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"moveListenerUp()\"><i class=\"glyphicon glyphicon-arrow-up\"></i></a>\n            \t                <a class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{ACTION.MOVE.DOWN | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"moveListenerDown()\"><i class=\"glyphicon glyphicon-arrow-down\"></i></a>\n            \t            </div>\n            \t            <div class=\"btn-group\">\n            \t                <a class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{ACTION.ADD | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"addNewListener()\"><i class=\"glyphicon glyphicon-plus\"></i></a>\n            \t                <a class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{ACTION.REMOVE | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"removeListener()\"><i class=\"glyphicon glyphicon-minus\"></i></a>\n            \t            </div>\n            \t        </div>\n            \t\t</div>\n            \t</div>\n            \t\n            \t<div class=\"row row-no-gutter\">\n                  \t<div ng-if=\"translationsRetrieved\" ng-show=\"selectedListeners.length > 0\" class=\"col-xs-6\">\n            \t\t\t<div class=\"form-group\">\n            \t        \t<label for=\"userField\">{{'PROPERTY.EVENTLISTENERS.EVENTS' | translate}}</label>\n            \t            <div ng-repeat=\"eventDefinition in selectedListeners[0].events\">\n            \t            \t<select id=\"eventField\" class=\"form-control\" ng-model=\"eventDefinition.event\" ng-change=\"listenerDetailsChanged()\">\n            \t            \t\t<option title=\"{{'EVENT_TYPE.ACTIVITY.COMPENSATE.TOOLTIP' | translate}}\">ACTIVITY_COMPENSATE</option>\n            \t            \t\t<option title=\"{{'EVENT_TYPE.ACTIVITY.COMPLETED.TOOLTIP' | translate}}\">ACTIVITY_COMPLETED</option>\n            \t            \t\t<option title=\"bla\">ACTIVITY_ERROR_RECEIVED</option>\n            \t            \t\t<option>ACTIVITY_MESSAGE_RECEIVED</option>\n            \t            \t\t<option>ACTIVITY_SIGNALED</option>\n            \t            \t\t<option>ACTIVITY_STARTED</option>\n            \t            \t\t<option>ENGINE_CLOSED</option>\n            \t            \t\t<option>ENGINE_CREATED</option>\n            \t            \t\t<option>ENTITY_ACTIVATED</option>\n            \t                \t<option>ENTITY_CREATED</option>\n            \t                \t<option>ENTITY_DELETED</option>\n            \t                \t<option>ENTITY_INITIALIZED</option>\n            \t                \t<option>ENTITY_SUSPENDED</option>\n            \t                \t<option>ENTITY_UPDATED</option>\n            \t                \t<option>JOB_EXECUTION_FAILURE</option>\n            \t                \t<option>JOB_EXECUTION_SUCCESS</option>\n            \t                \t<option>JOB_RETRIES_DECREMENTED</option>\n            \t                \t<option title=\"{{'EVENT_TYPE.MEMBERSHIP.CREATED.TOOLTIP' | translate}}\">MEMBERSHIP_CREATED</option>\n            \t                \t<option title=\"{{'EVENT_TYPE.MEMBERSHIP.DELETED.TOOLTIP' | translate}}\">MEMBERSHIP_DELETED</option>\n            \t                \t<option title=\"{{'EVENT_TYPE.MEMBERSHIPS.DELETED.TOOLTIP' | translate}}\">MEMBERSHIPS_DELETED</option>\n            \t                \t<option title=\"{{'EVENT_TYPE.TASK.ASSIGNED.TOOLTIP' | translate}}\">TASK_ASSIGNED</option>\n            \t                \t<option title=\"{{'EVENT_TYPE.TASK.COMPLETED.TOOLTIP' | translate}}\">TASK_COMPLETED</option>\n            \t                \t<option>TIMER_FIRED</option>\n            \t                \t<option title=\"{{'EVENT_TYPE.UNCAUGHT.BPMNERROR.TOOLTIP' | translate}}\">UNCAUGHT_BPMN_ERROR</option>\n            \t                \t<option title=\"{{'EVENT_TYPE.VARIABLE.CREATED.TOOLTIP' | translate}}\">VARIABLE_CREATED</option>\n            \t                \t<option title=\"{{'EVENT_TYPE.VARIABLE.DELETED.TOOLTIP' | translate}}\">VARIABLE_DELETED</option>\n            \t                \t<option title=\"{{'EVENT_TYPE.VARIABLE.UPDATED.TOOLTIP' | translate}}\">VARIABLE_UPDATED</option>\n            \t               \t</select>\n            \t\t            <i ng-if=\"$index > 0\" class=\"glyphicon glyphicon-minus clickable-property\" ng-click=\"removeEventValue($index)\"></i>\n            \t\t            <i class=\"glyphicon glyphicon-plus clickable-property\" ng-click=\"addEventValue($index)\"></i>\n            \t            </div>\n            \t            <div class=\"form-group\">\n            \t\t\t   \t\t<label for=\"classField\">{{'PROPERTY.EVENTLISTENERS.RETHROW' | translate}}</label>\n            \t\t\t   \t\t<input type=\"checkbox\" id=\"rethrowField\" class=\"form-control\" ng-model=\"selectedListeners[0].rethrowEvent\" ng-change=\"listenerDetailsChanged()\" />\n            \t\t\t\t</div>\n            \t       \t</div>\n                     </div>\n                     <div ng-show=\"selectedListeners.length > 0 && selectedListeners[0].events[0].event\" class=\"col-xs-6\">\n                     \t<div class=\"form-group\" ng-if=\"!selectedListeners[0].rethrowEvent\">\n            \t\t   \t\t<label for=\"classField\">{{'PROPERTY.EVENTLISTENERS.CLASS' | translate}}</label>\n            \t\t   \t\t<input type=\"text\" id=\"classField\" class=\"form-control\" ng-model=\"selectedListeners[0].className\" ng-change=\"listenerDetailsChanged()\" placeholder=\"{{'PROPERTY.EVENTLISTENERS.CLASS.PLACEHOLDER' | translate}}\" />\n            \t\t\t</div>\n            \t\t\t<div class=\"form-group\" ng-if=\"!selectedListeners[0].rethrowEvent\">\n            \t\t   \t\t<label for=\"delegateExpressionField\">{{'PROPERTY.EVENTLISTENERS.DELEGATEEXPRESSION' | translate}}</label>\n            \t\t   \t\t<input type=\"text\" id=\"delegateExpressionField\" class=\"form-control\" ng-model=\"selectedListeners[0].delegateExpression\" ng-change=\"listenerDetailsChanged()\" placeholder=\"{{'PROPERTY.EVENTLISTENERS.DELEGATEEXPRESSION.PLACEHOLDER' | translate}}\" />\n            \t\t\t</div>\n            \t\t\t<div class=\"form-group\" ng-if=\"!selectedListeners[0].rethrowEvent\">\n            \t\t   \t\t<label for=\"entityTypeField\">{{'PROPERTY.EVENTLISTENERS.ENTITYTYPE' | translate}}</label>\n            \t\t   \t\t<input type=\"text\" id=\"entityTypeField\" class=\"form-control\" ng-model=\"selectedListeners[0].entityType\" ng-change=\"listenerDetailsChanged()\" placeholder=\"{{'PROPERTY.EVENTLISTENERS.ENTITYTYPE.PLACEHOLDER' | translate}}\" />\n            \t\t\t</div>\n            \t\t\t<div class=\"form-group\" ng-if=\"selectedListeners[0].rethrowEvent\">\n            \t\t   \t\t<label for=\"delegateExpressionField\">{{'PROPERTY.EVENTLISTENERS.RETHROWTYPE' | translate}}</label>\n            \t\t   \t\t<select id=\"rethrowTypeField\" class=\"form-control\" ng-model=\"selectedListeners[0].rethrowType\" ng-change=\"rethrowTypeChanged()\">\n                                <option>error</option>\n                                <option>message</option>\n                                <option>signal</option>\n                                <option>globalSignal</option>\n                            </select>\n            \t\t\t</div>\n            \t\t\t<div class=\"form-group\" ng-if=\"selectedListeners[0].rethrowType === 'error'\">\n            \t\t   \t\t<label for=\"errorCodeField\">{{'PROPERTY.EVENTLISTENERS.ERRORCODE' | translate}}</label>\n            \t\t   \t\t<input type=\"text\" id=\"errorCodeField\" class=\"form-control\" ng-model=\"selectedListeners[0].errorcode\" ng-change=\"listenerDetailsChanged()\" placeholder=\"{{'PROPERTY.EVENTLISTENERS.ERRORCODE.PLACEHOLDER' | translate}}\" />\n            \t\t\t</div>\n            \t\t\t<div class=\"form-group\" ng-if=\"selectedListeners[0].rethrowType === 'message'\">\n            \t\t   \t\t<label for=\"messageNameField\">{{'PROPERTY.EVENTLISTENERS.MESSAGENAME' | translate}}</label>\n            \t\t   \t\t<input type=\"text\" id=\"messageNameField\" class=\"form-control\" ng-model=\"selectedListeners[0].messagename\" ng-change=\"listenerDetailsChanged()\" placeholder=\"{{'PROPERTY.EVENTLISTENERS.MESSAGENAME.PLACEHOLDER' | translate}}\" />\n            \t\t\t</div>\n            \t\t\t<div class=\"form-group\" ng-if=\"selectedListeners[0].rethrowType === 'signal' || selectedListeners[0].rethrowType === 'globalSignal'\">\n            \t\t   \t\t<label for=\"messageNameField\">{{'PROPERTY.EVENTLISTENERS.SIGNALNAME' | translate}}</label>\n            \t\t   \t\t<input type=\"text\" id=\"signalNameField\" class=\"form-control\" ng-model=\"selectedListeners[0].signalname\" ng-change=\"listenerDetailsChanged()\" placeholder=\"{{'PROPERTY.EVENTLISTENERS.SIGNALNAME.PLACEHOLDER' | translate}}\" />\n            \t\t\t</div>\n                     </div>\n                     <div ng-show=\"selectedListeners.length == 0\" class=\"col-xs-6 muted no-property-selected\" translate>PROPERTY.EVENTLISTENERS.UNSELECTED</div>\n                </div>\n            \n            </div>\n            <div class=\"modal-footer\">\n                <button ng-click=\"cancel()\" class=\"btn btn-primary\" translate>ACTION.CANCEL</button>\n                <button ng-click=\"save()\" class=\"btn btn-primary\" translate>ACTION.SAVE</button>\n            </div>\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/event-listeners-write-template.html",
    "content": "\n<!-- Just need to instantiate the controller, and it will take care of showing the modal dialog -->\n<span ng-controller=\"KisBpmEventListenersCtrl\">\n</span>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/execution-listeners-display-template.html",
    "content": "\n<span ng-if=\"!property.noValue\">{{'PROPERTY.EXECUTIONLISTENERS.DISPLAY' | translate:property.value.executionListeners}}</span>\n<span ng-if=\"property.noValue\" translate>PROPERTY.EXECUTIONLISTENERS.EMPTY</span>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/execution-listeners-popup.html",
    "content": "\n<div class=\"modal\" ng-controller=\"KisBpmExecutionListenersPopupCtrl\">\n    <div class=\"modal-dialog modal-wide\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header\">\n                <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\" ng-click=\"close()\">&times;</button>\n                <h2>{{'PROPERTY.PROPERTY.EDIT.TITLE' | translate:property}}</h2>\n            </div>\n            <div class=\"modal-body\">\n            \n                <div class=\"row row-no-gutter\">\n                    <div class=\"col-xs-6\">\n                        <div ng-if=\"translationsRetrieved\" class=\"kis-listener-grid\" ng-grid=\"gridOptions\"></div>\n                        <div class=\"pull-right\">\n                            <div class=\"btn-group\">\n                                <a class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{ACTION.MOVE.UP | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"moveListenerUp()\"><i class=\"glyphicon glyphicon-arrow-up\"></i></a>\n                                <a class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{ACTION.MOVE.DOWN | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"moveListenerDown()\"><i class=\"glyphicon glyphicon-arrow-down\"></i></a>\n                            </div>\n                            <div class=\"btn-group\">\n                                <a class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{ACTION.ADD | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"addNewListener()\"><i class=\"glyphicon glyphicon-plus\"></i></a>\n                                <a class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{ACTION.REMOVE | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"removeListener()\"><i class=\"glyphicon glyphicon-minus\"></i></a>\n                            </div>\n                        </div>\n                    </div>\n            \n                    <div class=\"col-xs-6\">\n                        <div ng-show=\"selectedListeners.length > 0\">\n            \n                            <div class=\"form-group\">\n            \t\t\t   \t\t<label for=\"eventField\">{{'PROPERTY.EXECUTIONLISTENERS.EVENT' | translate}}</label>\n            \t\t\t   \t\t<select id=\"eventField\" class=\"form-control\" ng-model=\"selectedListeners[0].event\">\n                                    <option>start</option>\n                                    <option>end</option>\n                                    <option>take</option>\n                                </select>\n            \t\t\t\t</div>\n            \t\t\t\t<div class=\"form-group\">\n            \t\t\t   \t\t<label for=\"classField\">{{'PROPERTY.EXECUTIONLISTENERS.CLASS' | translate}}</label>\n            \t\t\t   \t\t<input type=\"text\" id=\"classField\" class=\"form-control\" ng-model=\"selectedListeners[0].className\" ng-change=\"listenerDetailsChanged()\" placeholder=\"{{'PROPERTY.EXECUTIONLISTENERS.CLASS.PLACEHOLDER' | translate}}\" />\n            \t\t\t\t</div>\n            \t\t\t\t<div class=\"form-group\">\n            \t\t\t   \t\t<label for=\"expressionField\">{{'PROPERTY.EXECUTIONLISTENERS.EXPRESSION' | translate}}</label>\n            \t\t\t   \t\t<input type=\"text\" id=\"expressionField\" class=\"form-control\" ng-model=\"selectedListeners[0].expression\" ng-change=\"listenerDetailsChanged()\" placeholder=\"{{'PROPERTY.EXECUTIONLISTENERS.EXPRESSION.PLACEHOLDER' | translate}}\" />\n            \t\t\t\t</div>\n            \t\t\t\t<div class=\"form-group\">\n            \t\t\t   \t\t<label for=\"delegateExpressionField\">{{'PROPERTY.EXECUTIONLISTENERS.DELEGATEEXPRESSION' | translate}}</label>\n            \t\t\t   \t\t<input type=\"text\" id=\"delegateExpressionField\" class=\"form-control\" ng-model=\"selectedListeners[0].delegateExpression\" ng-change=\"listenerDetailsChanged()\" placeholder=\"{{'PROPERTY.EXECUTIONLISTENERS.DELEGATEEXPRESSION.PLACEHOLDER' | translate}}\" />\n            \t\t\t\t</div>\n                        </div>\n                        <div ng-show=\"selectedListeners.length == 0\" class=\"muted no-property-selected\" translate>PROPERTY.EXECUTIONLISTENERS.UNSELECTED</div>\n                    </div>\n                </div>\n                \n                <div class=\"row row-no-gutter\">\n                    <div class=\"col-xs-6\">\n                        <div ng-if=\"translationsRetrieved\" class=\"kis-field-grid\" ng-grid=\"gridFieldOptions\"></div>\n                        <div class=\"pull-right\">\n                            <div class=\"btn-group\">\n                                <a class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{ACTION.MOVE.UP | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"moveFieldUp()\"><i class=\"glyphicon glyphicon-arrow-up\"></i></a>\n                                <a class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{ACTION.MOVE.DOWN | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"moveFieldDown()\"><i class=\"glyphicon glyphicon-arrow-down\"></i></a>\n                            </div>\n                            <div class=\"btn-group\">\n                                <a class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{ACTION.ADD | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"addNewField()\"><i class=\"glyphicon glyphicon-plus\"></i></a>\n                                <a class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{ACTION.REMOVE | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"removeField()\"><i class=\"glyphicon glyphicon-minus\"></i></a>\n                            </div>\n                        </div>\n                    </div>\n            \n                    <div class=\"col-xs-6\">\n                        <div ng-show=\"selectedFields.length > 0\">\n            \n            \t\t\t\t<div class=\"form-group\">\n            \t\t\t   \t\t<label for=\"nameField\">{{'PROPERTY.EXECUTIONLISTENERS.FIELDS.NAME' | translate}}</label>\n            \t\t\t   \t\t<input type=\"text\" id=\"nameField\" class=\"form-control\" ng-model=\"selectedFields[0].name\" placeholder=\"{{'PROPERTY.EXECUTIONLISTENERS.FIELDS.NAME.PLACEHOLDER' | translate}}\" />\n            \t\t\t\t</div>\n                            <div class=\"form-group\">\n            \t\t\t   \t\t<label for=\"stringValueField\">{{'PROPERTY.EXECUTIONLISTENERS.FIELDS.STRINGVALUE' | translate}}</label>\n            \t\t\t   \t\t<input type=\"text\" id=\"stringValueField\" class=\"form-control\" ng-model=\"selectedFields[0].stringValue\" ng-change=\"fieldDetailsChanged()\" placeholder=\"{{'PROPERTY.EXECUTIONLISTENERS.FIELDS.STRINGVALUE.PLACEHOLDER' | translate}}\" />\n            \t\t\t\t</div>\n            \t\t\t\t<div class=\"form-group\">\n            \t\t\t   \t\t<label for=\"expressionField\">{{'PROPERTY.EXECUTIONLISTENERS.FIELDS.EXPRESSION' | translate}}</label>\n            \t\t\t   \t\t<input type=\"text\" id=\"expressionField\" class=\"form-control\" ng-model=\"selectedFields[0].expression\" ng-change=\"fieldDetailsChanged()\" placeholder=\"{{'PROPERTY.EXECUTIONLISTENERS.FIELDS.EXPRESSION.PLACEHOLDER' | translate}}\" />\n            \t\t\t\t</div>\n            \t\t\t\t<div class=\"form-group\">\n            \t\t\t   \t\t<label for=\"stringField\">{{'PROPERTY.EXECUTIONLISTENERS.FIELDS.STRING' | translate}}</label>\n            \t\t\t   \t\t<textarea id=\"stringField\" class=\"form-control\" ng-model=\"selectedFields[0].string\" ng-change=\"fieldDetailsChanged()\" placeholder=\"{{'PROPERTY.EXECUTIONLISTENERS.FIELDS.STRING.PLACEHOLDER' | translate}}\"></textarea>\n            \t\t\t\t</div>\n                            \n                        </div>\n                        <div ng-show=\"selectedFields.length == 0\" class=\"muted no-property-selected\"translate>PROPERTY.EXECUTIONLISTENERS.FIELDS.EMPTY</div>\n                    </div>\n                </div>\n            \n            </div>\n            <div class=\"modal-footer\">\n                <button ng-click=\"cancel()\" class=\"btn btn-primary\" translate>ACTION.CANCEL</button>\n                <button ng-click=\"save()\" class=\"btn btn-primary\" translate>ACTION.SAVE</button>\n            </div>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/execution-listeners-write-template.html",
    "content": "\n<!-- Just need to instantiate the controller, and it will take care of showing the modal dialog -->\n<span ng-controller=\"KisBpmExecutionListenersCtrl\">\n</span>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/feedback-popup.html",
    "content": "\n<div class=\"modal\" ng-controller=\"BpmnFeedbackPopupCtrl\">\n    <div class=\"modal-dialog\">\n        <div class=\"modal-content\">\n\t\t\t<div class=\"modal-header\">\n            \t<h2>{{'PROPERTY.FEEDBACK.TITLE' | translate:property}}</h2>\n            </div>\n            <div class=\"modal-body\">\n            \t<p><textarea auto-focus class=\"form-control\" ng-model=\"model.feedback\" style=\"width:90%; height:100%; max-width: 100%; max-height: 100%; min-height: 300px\"/></p>\n           \t</div>\n           \t<div class=\"modal-footer\">\n            \t<button ng-click=\"cancel()\" class=\"btn btn-primary\" translate >ACTION.CANCEL</button>\n              \t<button ng-click=\"send()\" ng-disabled=\"model.feedback.length === 0\" class=\"btn btn-primary\" translate >ACTION.SEND</button>\n            </div>\n\t\t</div>\n\t</div>\n</div>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/fields-display-template.html",
    "content": "\n<span ng-if=\"!property.noValue\">{{'PROPERTY.FIELDS' | translate:property.value.fields}}</span>\n<span ng-if=\"property.noValue\">{{'PROPERTY.FIELDS.EMPTY' | translate}}</span>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/fields-popup.html",
    "content": "\n<div class=\"modal\" ng-controller=\"KisBpmFieldsPopupCtrl\">\n    <div class=\"modal-dialog modal-wide\">\n        <div class=\"modal-content\">\n\t\t\t<div class=\"modal-header\">\n\t\t\t    <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\" ng-click=\"close()\">&times;</button>\n\t\t\t    <h3>{{'PROPERTY.PROPERTY.EDIT.TITLE' | translate:property}}</h3>\n\t\t\t</div>\n\t\t\t<div class=\"modal-body\">\n\n\t\t\t    <div class=\"row row-no-gutter\">\n\t\t\t        <div class=\"col-xs-6\">\n                        <div ng-if=\"translationsRetrieved\" class=\"kis-listener-grid\" ng-grid=\"gridOptions\"></div>\n\t\t\t            <div class=\"pull-right\">\n\t\t\t                <div class=\"btn-group\">\n\t\t\t                    <a href=\"#\" class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{'ACTION.MOVE.UP' | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"moveFieldUp()\"><i class=\"glyphicon glyphicon-arrow-up\"></i></a>\n\t\t\t                    <a href=\"#\" class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{'ACTION.MOVE.DOWN' | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"moveFieldDown()\"><i class=\"glyphicon glyphicon-arrow-down\"></i></a>\n\t\t\t                </div>\n\t\t\t                <div class=\"btn-group\">\n\t\t\t                    <a href=\"#\" class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{'ACTION.ADD' | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"addNewField()\"><i class=\"glyphicon glyphicon-plus\"></i></a>\n\t\t\t                    <a href=\"#\" class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{'ACTION.REMOVE' | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"removeField()\"><i class=\"glyphicon glyphicon-minus\"></i></a>\n\t\t\t                </div>\n\t\t\t            </div>\n\t\t\t        </div>\n\n\t\t\t       <div class=\"col-xs-6\">\n\t\t\t            <div ng-show=\"selectedFields.length > 0\">\n\n\t\t\t                <div class=\"form-group\">\n                                <label for=\"fieldName\">{{'PROPERTY.FIELDS.NAME' | translate}}</label>\n                                <input type=\"text\" id=\"fieldName\"  class=\"form-control\" ng-model=\"selectedFields[0].name\" placeholder=\"{{'PROPERTY.FIELDS.NAME.PLACEHOLDER' | translate}}\" />\n                            </div>\n\n                            <div class=\"form-group\">\n                            <label for=\"fieldStringValue\">{{'PROPERTY.FIELDS.STRINGVALUE' | translate}}</label>\n                                <input type=\"text\" id=\"fieldStringValue\"  class=\"form-control\" ng-model=\"selectedFields[0].stringValue\" ng-change=\"fieldDetailsChanged()\" placeholder=\"{{'PROPERTY.FIELDS.STRINGVALUE.PLACEHOLDER' | translate}}\" />\n                            </div>\n\n                            <div class=\"form-group\">\n                            <label for=\"fieldExpression\">{{'PROPERTY.FIELDS.EXPRESSION' | translate}}</label>\n                                <input type=\"text\" id=\"fieldExpression\"  class=\"form-control\" ng-model=\"selectedFields[0].expression\" ng-change=\"fieldDetailsChanged()\" placeholder=\"{{'PROPERTY.FIELDS.EXPRESSION.PLACEHOLDER' | translate}}\" />\n                            </div>\n\n                            <div class=\"form-group\">\n                            <label for=\"fieldString\">{{'PROPERTY.FIELDS.STRING' | translate}}</label>\n\t\t\t                        <textarea type=\"text\" id=\"fieldString\"  class=\"form-control\" ng-model=\"selectedFields[0].string\" ng-change=\"fieldDetailsChanged()\" placeholder=\"{{'PROPERTY.FIELDS.STRING.PLACEHOLDER' | translate}}\"></textarea>\n                            </div>\n\n\t\t\t            </div>\n\t\t\t            <div ng-show=\"selectedFields.length == 0\" class=\"muted no-property-selected\" translate>PROPERTY.FIELDS.EMPTY</div>\n\t\t\t        </div>\n\t\t\t    </div>\n\t\t\t\n\t\t\t</div>\n\t\t\t<div class=\"modal-footer\">\n\t\t\t    <button ng-click=\"cancel()\" class=\"btn btn-primary\" translate>ACTION.CANCEL</button>\n\t\t\t    <button ng-click=\"save()\" class=\"btn btn-primary\" translate>ACTION.SAVE</button>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/fields-write-template.html",
    "content": "\n<!-- Just need to instantiate the controller, and it will take care of showing the modal dialog -->\n<span ng-controller=\"KisBpmFieldsCtrl\">\n</span>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/form-properties-display-template.html",
    "content": "\n<span ng-if=\"!property.noValue\">{{'PROPERTY.FORMPROPERTIES.VALUE' | translate:property.value.formProperties}}</span>\n<span ng-if=\"property.noValue\" translate>PROPERTY.FORMPROPERTIES.EMPTY</span>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/form-properties-popup.html",
    "content": "\n<div class=\"modal\" ng-controller=\"KisBpmFormPropertiesPopupCtrl\">\n    <div class=\"modal-dialog modal-wide\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header\">\n                <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\" ng-click=\"close()\">&times;</button>\n                <h2>{{'PROPERTY.PROPERTY.EDIT.TITLE' | translate:property}}</h2>\n            </div>\n            <div class=\"modal-body\">\n            \n                <div class=\"row row-no-gutter\">\n                    <div class=\"col-xs-6\">\n                        <div ng-if=\"translationsRetrieved\" class=\"default-grid\" ng-grid=\"gridOptions\"></div>\n                        <div class=\"pull-right\">\n                            <div class=\"btn-group\">\n                                <a class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{'ACTION.MOVE.UP' | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"movePropertyUp()\"><i class=\"glyphicon glyphicon-arrow-up\"></i></a>\n                                <a class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{'ACTION.MOVE.DOWN' | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"movePropertyDown()\"><i class=\"glyphicon glyphicon-arrow-down\"></i></a>\n                            </div>\n                            <div class=\"btn-group\">\n                                <a class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{'ACTION.ADD' | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"addNewProperty()\"><i class=\"glyphicon glyphicon-plus\"></i></a>\n                                <a class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{'ACTION.REMOVE' | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"removeProperty()\"><i class=\"glyphicon glyphicon-minus\"></i></a>\n                            </div>\n                        </div>\n                    </div>\n            \n                    <div class=\"col-xs-6\">\n                        <div ng-show=\"selectedProperties.length > 0\">\n            \n                            <div class=\"form-group\">\n            \t\t\t   \t\t<label for=\"idField\">{{'PROPERTY.FORMPROPERTIES.ID' | translate}}</label>\n            \t\t\t   \t\t<input id=\"idField\" class=\"form-control\" type=\"text\" ng-model=\"selectedProperties[0].id\" placeholder=\"{{'PROPERTY.FORMPROPERTIES.ID.PLACEHOLDER' | translate }}\" />\n            \t\t\t\t</div>\n            \t\t\t\t<div class=\"form-group\">\n            \t\t\t   \t\t<label for=\"nameField\">{{'PROPERTY.FORMPROPERTIES.NAME' | translate}}</label>\n            \t\t\t   \t\t<input id=\"nameField\" class=\"form-control\" type=\"text\" ng-model=\"selectedProperties[0].name\" placeholder=\"{{'PROPERTY.FORMPROPERTIES.NAME.PLACEHOLDER' | translate }}\" />\n            \t\t\t\t</div>\n            \t\t\t\t<div class=\"form-group\">\n            \t\t\t   \t\t<label for=\"typeField\">{{'PROPERTY.FORMPROPERTIES.TYPE' | translate}}</label>\n            \t\t\t   \t\t<select id=\"typeField\" class=\"form-control\" ng-model=\"selectedProperties[0].type\" ng-change=\"propertyTypeChanged()\">\n                                    <option>string</option>\n                                    <option>long</option>\n                                    <option>boolean</option>\n                                    <option>date</option>\n                                    <option>enum</option>\n                                </select>\n            \t\t\t\t</div>\n                           \t<div class=\"form-group\" ng-show=\"selectedProperties[0].datePattern\">\n            \t\t\t   \t\t<label for=\"datePatternField\">{{'PROPERTY.FORMPROPERTIES.DATEPATTERN' | translate}}</label>\n            \t\t\t   \t\t<input id=\"datePatternField\" class=\"form-control\" type=\"text\" ng-model=\"selectedProperties[0].datePattern\" placeholder=\"{{'PROPERTY.FORMPROPERTIES.DATEPATTERN.PLACEHOLDER' | translate }}\" />\n            \t\t\t\t</div>\n                            <div ng-if=\"selectedProperties[0].type == 'enum'\" style=\"padding-bottom:10px\">\n            \t\t\t   \t\t<div class=\"row row-no-gutter\">\n\t\t\t\t                    <div class=\"col-xs-6\">\n\t\t\t\t                        <div ng-if=\"translationsRetrieved\" class=\"kis-listener-grid\" ng-grid=\"enumGridOptions\"></div>\n\t\t\t\t                        <div class=\"pull-right\">\n\t\t\t\t                            <div class=\"btn-group\">\n\t\t\t\t                                <a class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{ACTION.MOVE.UP | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"moveEnumValueUp()\"><i class=\"glyphicon glyphicon-arrow-up\"></i></a>\n\t\t\t\t                                <a class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{ACTION.MOVE.DOWN | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"moveEnumValueDown()\"><i class=\"glyphicon glyphicon-arrow-down\"></i></a>\n\t\t\t\t                            </div>\n\t\t\t\t                            <div class=\"btn-group\">\n\t\t\t\t                                <a class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{ACTION.ADD | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"addNewEnumValue()\"><i class=\"glyphicon glyphicon-plus\"></i></a>\n\t\t\t\t                                <a class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{ACTION.REMOVE | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"removeEnumValue()\"><i class=\"glyphicon glyphicon-minus\"></i></a>\n\t\t\t\t                            </div>\n\t\t\t\t                        </div>\n\t\t\t\t                    </div>\n\t\t\t\t            \n\t\t\t\t                    <div class=\"col-xs-6\">\n\t\t\t\t                        <div ng-show=\"selectedEnumValues.length > 0\">\n\t\t\t\t            \n\t\t\t\t                            <div class=\"form-group\">\n\t\t\t\t            \t\t\t   \t\t<label for=\"classField\">{{'PROPERTY.FORMPROPERTIES.VALUES.ID' | translate}}</label>\n\t\t\t\t            \t\t\t   \t\t<input type=\"text\" id=\"classField\" class=\"form-control\" ng-model=\"selectedEnumValues[0].id\" placeholder=\"{{'PROPERTY.FORMPROPERTIES.VALUES.ID.PLACEHOLDER' | translate}}\" />\n\t\t\t\t            \t\t\t\t</div>\n\t\t\t\t            \t\t\t\t<div class=\"form-group\">\n\t\t\t\t            \t\t\t   \t\t<label for=\"classField\">{{'PROPERTY.FORMPROPERTIES.VALUES.NAME' | translate}}</label>\n\t\t\t\t            \t\t\t   \t\t<input type=\"text\" id=\"classField\" class=\"form-control\" ng-model=\"selectedEnumValues[0].name\" placeholder=\"{{'PROPERTY.FORMPROPERTIES.VALUES.NAME.PLACEHOLDER' | translate}}\" />\n\t\t\t\t            \t\t\t\t</div>\n\t\t\t\t                        </div>\n\t\t\t\t                        <div ng-show=\"selectedEnumValues.length == 0\" class=\"muted no-property-selected\" translate>PROPERTY.FORMPROPERTIES.ENUMVALUES.EMPTY</div>\n\t\t\t\t                    </div>\n\t\t\t\t                </div>\n            \t\t\t\t</div>\n                            <div class=\"form-group\">\n            \t\t\t   \t\t<label for=\"expressionField\">{{'PROPERTY.FORMPROPERTIES.EXPRESSION' | translate}}</label>\n            \t\t\t   \t\t<input id=\"expressionField\" class=\"form-control\" type=\"text\" ng-model=\"selectedProperties[0].expression\" placeholder=\"{{'PROPERTY.FORMPROPERTIES.EXPRESSION.PLACEHOLDER' | translate }}\" />\n            \t\t\t\t</div>\n            \t\t\t\t<div class=\"form-group\">\n            \t\t\t   \t\t<label for=\"variableField\">{{'PROPERTY.FORMPROPERTIES.VARIABLE' | translate}}</label>\n            \t\t\t   \t\t<input id=\"variableField\" class=\"form-control\" type=\"text\" ng-model=\"selectedProperties[0].variable\" placeholder=\"{{'PROPERTY.FORMPROPERTIES.VARIABLE.PLACEHOLDER' | translate }}\" />\n            \t\t\t\t</div>\n            \t\t\t\t<div class=\"form-inline\">\n            \t\t\t\t\t<div class=\"form-group col-xs-2\" >\n            \t\t\t\t   \t\t<label for=\"requiredField\">{{'PROPERTY.FORMPROPERTIES.REQUIRED' | translate}}</label>\n            \t\t\t\t   \t\t<input id=\"requiredField\" class=\"form-control\" type=\"checkbox\" ng-model=\"selectedProperties[0].required\" />\n            \t\t\t\t   \t</div>\n            \t\t\t\t   \t<div class=\"form-group col-xs-2\">\n            \t\t\t\t   \t\t<label for=\"readableField\">{{'PROPERTY.FORMPROPERTIES.READABLE' | translate}}</label>\n            \t\t\t\t   \t\t<input id=\"readableField\" class=\"form-control\" type=\"checkbox\" ng-model=\"selectedProperties[0].readable\" />\n            \t\t\t\t\t</div>\n            \t\t\t\t\t<div class=\"form-group col-xs-2\">\n            \t\t\t\t\t\t<label for=\"writableField\">{{'PROPERTY.FORMPROPERTIES.WRITABLE' | translate}}</label>\n            \t\t\t   \t\t\t<input id=\"writableField\" class=\"form-control\" type=\"checkbox\" ng-model=\"selectedProperties[0].writable\" />\n            \t\t\t\t\t</div>\n            \t\t\t\t</div>\n                        </div>\n                        <div ng-show=\"selectedProperties.length == 0\" class=\"muted no-property-selected\" translate>PROPERTY.FORMPROPERTIES.EMPTY</div>\n                    </div>\n                </div>\n            \n            </div>\n            <div class=\"modal-footer\">\n                <button ng-click=\"cancel()\" class=\"btn btn-primary\" translate>ACTION.CANCEL</button>\n                <button ng-click=\"save()\" class=\"btn btn-primary\" translate>ACTION.SAVE</button>\n            </div>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/form-properties-write-template.html",
    "content": "\n<!-- Just need to instantiate the controller, and it will take care of showing the modal dialog -->\n<span ng-controller=\"KisBpmFormPropertiesCtrl\">\n</span>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/in-parameters-display-template.html",
    "content": "\n<span ng-if=\"!property.noValue\">{{'PROPERTY.INPARAMETERS.VALUE' | translate:property.value.inParameters}}</span>\n<span ng-if=\"property.noValue\" translate>PROPERTY.INPARAMETERS.EMPTY</span>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/in-parameters-popup.html",
    "content": "\n<div class=\"modal\" ng-controller=\"KisBpmInParametersPopupCtrl\">\n    <div class=\"modal-dialog modal-wide\">\n        <div class=\"modal-content\">\n\t\t\t<div class=\"modal-header\">\n\t\t\t    <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\" ng-click=\"close()\">&times;</button>\n\t\t\t    <h2>{{'PROPERTY.PROPERTY.EDIT.TITLE' | translate:property}}</h2>\n\t\t\t</div>\n\t\t\t<div class=\"modal-body\">\n\t\t\t\n\t\t\t    <div class=\"row row-no-gutter\">\n\t\t\t        <div class=\"col-xs-6\">\n\t\t\t            <div ng-if=\"translationsRetrieved\" class=\"kis-listener-grid\" ng-grid=\"gridOptions\"></div>\n\t\t\t            <div class=\"pull-right\">\n\t\t\t                <div class=\"btn-group\">\n\t\t\t                    <a class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{'ACTION.MOVE.UP' | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"moveParameterUp()\"><i class=\"glyphicon glyphicon-arrow-up\"></i></a>\n\t\t\t                    <a class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{'ACTION.MOVE.DOWN' | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"moveParameterDown()\"><i class=\"glyphicon glyphicon-arrow-down\"></i></a>\n\t\t\t                </div>\n\t\t\t                <div class=\"btn-group\">\n\t\t\t                    <a class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{'ACTION.ADD' | translate:property}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"addNewParameter()\"><i class=\"glyphicon glyphicon-plus\"></i></a>\n\t\t\t                    <a class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{'ACTION.REMOVE' | translate:property}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"removeParameter()\"><i class=\"glyphicon glyphicon-minus\"></i></a>\n\t\t\t                </div>\n\t\t\t            </div>\n\t\t\t        </div>\n\t\t\t\n\t\t\t        <div class=\"col-xs-6\">\n\t\t\t            <div ng-show=\"selectedParameters.length > 0\">\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t   \t\t<label for=\"sourceField\">{{'PROPERTY.PARAMETER.SOURCE' | translate}}</label>\n\t\t\t\t\t\t   \t\t<input type=\"text\" id=\"sourceField\" class=\"form-control\" ng-model=\"selectedParameters[0].source\" placeholder=\"{{'PROPERTY.PARAMETER.SOURCE.PLACEHOLDER' | translate}}\" />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t   \t\t<label for=\"expressionField\">{{'PROPERTY.PARAMETER.SOURCEEXPRESSION' | translate}}</label>\n\t\t\t\t\t\t   \t\t<input type=\"text\" id=\"expressionField\" class=\"form-control\" ng-model=\"selectedParameters[0].sourceExpression\" placeholder=\"{{'PROPERTY.PARAMETER.SOURCEEXPRESSION.PLACEHOLDER' | translate}}\" />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t   \t\t<label for=\"expressionField\">{{'PROPERTY.PARAMETER.TARGET' | translate}}</label>\n\t\t\t\t\t\t   \t\t<input type=\"text\" id=\"expressionField\" class=\"form-control\" ng-model=\"selectedParameters[0].target\" placeholder=\"{{'PROPERTY.PARAMETER.TARGET.PLACEHOLDER' | translate}}\" />\n\t\t\t\t\t\t\t</div>\n\t\t\t                \n\t\t\t            </div>\n\t\t\t            <div ng-show=\"selectedParameters.length == 0\" class=\"muted no-property-selected\" translate>PROPERTY.PARAMETER.EMPTY</div>\n\t\t\t        </div>\n\t\t\t    </div>\n\t\t\t</div>\n\t\t\t<div class=\"modal-footer\">\n\t\t\t    <button ng-click=\"cancel()\" class=\"btn btn-primary\" translate>ACTION.CANCEL</button>\n\t\t\t    <button ng-click=\"save()\" class=\"btn btn-primary\" translate>ACTION.SAVE</button>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/in-parameters-write-template.html",
    "content": "\n<!-- Just need to instantiate the controller, and it will take care of showing the modal dialog -->\n<span ng-controller=\"KisBpmInParametersCtrl\">\n</span>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/message-definitions-display-template.html",
    "content": "<span ng-if=\"!property.noValue\">{{'PROPERTY.MESSAGEDEFINITIONS.DISPLAY' | translate:property.value}}</span>\n<span ng-if=\"property.noValue\" translate>PROPERTY.MESSAGEDEFINITIONS.EMPTY</span>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/message-definitions-popup.html",
    "content": "\n<div class=\"modal\" ng-controller=\"ActivitiMessageDefinitionsPopupCtrl\">\n    <div class=\"modal-dialog modal-wide\">\n        <div class=\"modal-content\">\n\n            <div class=\"modal-header\">\n                <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\" ng-click=\"close()\">&times;</button>\n                <h2>{{'PROPERTY.PROPERTY.EDIT.TITLE' | translate:property}}</h2>\n            </div>\n\n            <div class=\"modal-body\">\n            \n                <div class=\"row row-no-gutter\">\n\n                \t<div class=\"col-xs-8\">\n                        <div ng-if=\"translationsRetrieved\" class=\"kis-listener-grid\" ng-grid=\"gridOptions\"></div>\n            \t        <div class=\"pull-right\">\n            \t            <div class=\"btn-group\">\n            \t                <a class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{ACTION.ADD | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"addNewMessageDefinition()\"><i class=\"glyphicon glyphicon-plus\"></i></a>\n            \t                <a class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{ACTION.REMOVE | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"removeMessageDefinition()\"><i class=\"glyphicon glyphicon-minus\"></i></a>\n            \t            </div>\n            \t        </div>\n            \t\t</div>\n\n                    <div class=\"col-xs-4\" ng-show=\"selectedMessages && selectedMessages.length > 0\">\n\n                        <div class=\"form-group\">\n                            <label>{{'PROPERTY.MESSAGEDEFINITIONS.ID' | translate}}</label>\n                            <input type=\"text\" class=\"form-control\" ng-model=\"selectedMessages[0].id\">\n                        </div>\n\n                        <div class=\"form-group\">\n                            <label>{{'PROPERTY.MESSAGEDEFINITIONS.NAME' | translate}}</label>\n                            <input type=\"text\" class=\"form-control\" ng-model=\"selectedMessages[0].name\">\n                        </div>\n\n                    </div>\n\n            \t</div>\n            \t\n            </div>\n\n            <div class=\"modal-footer\">\n                <button ng-click=\"cancel()\" class=\"btn btn-primary\" translate>ACTION.CANCEL</button>\n                <button ng-click=\"save()\" class=\"btn btn-primary\" translate>ACTION.SAVE</button>\n            </div>\n\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/message-definitions-write-template.html",
    "content": "<!-- Just need to instantiate the controller, and it will take care of showing the modal dialog -->\n<span ng-controller=\"ActivitiMessageDefinitionsCtrl\">\n</span>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/message-property-write-template.html",
    "content": "<div ng-controller=\"ActivitiMessageRefCtrl\">\n    <select ng-model=\"property.value\" ng-change=\"messageChanged()\" ng-options=\"messageDefinition.id as (messageDefinition.name + ' (' + messageDefinition.id + ')') for messageDefinition in messageDefinitions\">\n    </select>\n</div>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/multiinstance-property-write-template.html",
    "content": "\n<div ng-controller=\"KisBpmMultiInstanceCtrl\">\n    <select ng-model=\"property.value\" ng-change=\"multiInstanceChanged()\">\n    \t<option>None</option>\n    \t<option>Parallel</option>\n    \t<option>Sequential</option>\n    </select>\n</div>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/out-parameters-display-template.html",
    "content": "\n<span ng-if=\"!property.noValue\">{{'PROPERTY.OUTPARAMETERS.VALUE' | translate:property.value.outParameters}}</span>\n<span ng-if=\"property.noValue\" translate>PROPERTY.OUTPARAMETERS.EMPTY</span>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/out-parameters-popup.html",
    "content": "\n<div class=\"modal\" ng-controller=\"KisBpmOutParametersPopupCtrl\">\n    <div class=\"modal-dialog modal-wide\">\n        <div class=\"modal-content\">\n\t\t\t<div class=\"modal-header\">\n\t\t\t    <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\" ng-click=\"close()\">&times;</button>\n\t\t\t    <h2>{{'PROPERTY.PROPERTY.EDIT.TITLE' | translate:property}}</h2>\n\t\t\t</div>\n\t\t\t<div class=\"modal-body\">\n\t\t\t\n\t\t\t    <div class=\"row row-no-gutter\">\n\t\t\t        <div class=\"col-xs-6\">\n\t\t\t            <div ng-if=\"translationsRetrieved\" class=\"kis-listener-grid\" ng-grid=\"gridOptions\"></div>\n\t\t\t            <div class=\"pull-right\">\n\t\t\t                <div class=\"btn-group\">\n\t\t\t                    <a class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{'ACTION.MOVE.UP' | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"moveParameterUp()\"><i class=\"glyphicon glyphicon-arrow-up\"></i></a>\n\t\t\t                    <a class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{'ACTION.MOVE.DOWN' | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"moveParameterDown()\"><i class=\"glyphicon glyphicon-arrow-down\"></i></a>\n\t\t\t                </div>\n\t\t\t                <div class=\"btn-group\">\n\t\t\t                    <a class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{'ACTION.ADD' | translate:property}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"addNewParameter()\"><i class=\"glyphicon glyphicon-plus\"></i></a>\n\t\t\t                    <a class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{'ACTION.REMOVE' | translate:property}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"removeParameter()\"><i class=\"glyphicon glyphicon-minus\"></i></a>\n\t\t\t                </div>\n\t\t\t            </div>\n\t\t\t        </div>\n\t\t\t\n\t\t\t        <div class=\"col-xs-6\">\n\t\t\t            <div ng-show=\"selectedParameters.length > 0\">\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t   \t\t<label for=\"sourceField\">{{'PROPERTY.PARAMETER.SOURCE' | translate}}</label>\n\t\t\t\t\t\t   \t\t<input type=\"text\" id=\"sourceField\" class=\"form-control\" ng-model=\"selectedParameters[0].source\" placeholder=\"{{'PROPERTY.PARAMETER.SOURCE.PLACEHOLDER' | translate}}\" />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t   \t\t<label for=\"expressionField\">{{'PROPERTY.PARAMETER.SOURCEEXPRESSION' | translate}}</label>\n\t\t\t\t\t\t   \t\t<input type=\"text\" id=\"expressionField\" class=\"form-control\" ng-model=\"selectedParameters[0].sourceExpression\" placeholder=\"{{'PROPERTY.PARAMETER.SOURCEEXPRESSION.PLACEHOLDER' | translate}}\" />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t   \t\t<label for=\"expressionField\">{{'PROPERTY.PARAMETER.TARGET' | translate}}</label>\n\t\t\t\t\t\t   \t\t<input type=\"text\" id=\"expressionField\" class=\"form-control\" ng-model=\"selectedParameters[0].target\" placeholder=\"{{'PROPERTY.PARAMETER.TARGET.PLACEHOLDER' | translate}}\" />\n\t\t\t\t\t\t\t</div>\n\t\t\t                \n\t\t\t            </div>\n\t\t\t            <div ng-show=\"selectedParameters.length == 0\" class=\"muted no-property-selected\" translate>PROPERTY.PARAMETER.EMPTY</div>\n\t\t\t        </div>\n\t\t\t    </div>\n\t\t\t</div>\n\t\t\t<div class=\"modal-footer\">\n\t\t\t    <button ng-click=\"cancel()\" class=\"btn btn-primary\" translate>ACTION.CANCEL</button>\n\t\t\t    <button ng-click=\"save()\" class=\"btn btn-primary\" translate>ACTION.SAVE</button>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/out-parameters-write-template.html",
    "content": "\n<!-- Just need to instantiate the controller, and it will take care of showing the modal dialog -->\n<span ng-controller=\"KisBpmOutParametersCtrl\">\n</span>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/sequenceflow-order-display-template.html",
    "content": "\n<span ng-if=\"!property.noValue\" translate>PROPERTY.SEQUENCEFLOW.ORDER.NOT.EMPTY</span>\n<span ng-if=\"property.noValue\" translate>PROPERTY.SEQUENCEFLOW.ORDER.EMPTY</span>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/sequenceflow-order-popup.html",
    "content": "\n<div class=\"modal\" ng-controller=\"KisBpmSequenceFlowOrderPopupCtrl\">\n    <div class=\"modal-dialog\">\n        <div class=\"modal-content\">\n\t\t\t<div class=\"modal-header\">\n\t\t\t    <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\" ng-click=\"close()\">&times;</button>\n\t\t\t    <h3>{{'PROPERTY.PROPERTY.EDIT.TITLE' | translate:property}}</h3>\n\t\t\t</div>\n\t\t\t\n\t\t\t<div class=\"modal-body\">\n\t\t\t\n\t\t\t    <div translate>PROPERTY.SEQUENCEFLOW.ORDER.DESCRIPTION</div>\n\t\t\t    <br/>\n\t\t\t    <ol>\n\t\t\t        <li class=\"sequence-flow-order-element\" ng-repeat=\"sequenceFlow in outgoingSequenceFlow\">\n\t\t\t            {{'PROPERTY.SEQUENCEFLOW.ORDER.SEQUENCEFLOW.VALUE' | translate:sequenceFlow}}\n\t\t\t            <a class=\"btn btn-icon btn-sm\"\n\t\t\t               rel=\"tooltip\"\n\t\t\t               data-title=\"{{'ACTION.MOVE.UP' | translate}}\"\n\t\t\t               data-placement=\"bottom\"\n\t\t\t               data-original-title=\"\" title=\"\"\n\t\t\t               ng-click=\"moveUp($index)\"\n\t\t\t               ng-if=\"$index > 0\">\n\t\t\t                 <i class=\"glyphicon glyphicon-arrow-up\"></i>\n\t\t\t            </a>\n\t\t\t            <a class=\"btn btn-icon btn-sm\"\n\t\t\t               rel=\"tooltip\"\n\t\t\t               data-title=\"{{'ACTION.MOVE.DOWN' | translate}}\"\n\t\t\t               data-placement=\"bottom\"\n\t\t\t               data-original-title=\"\"\n\t\t\t               title=\"\"\n\t\t\t               ng-click=\"moveDown($index)\"\n\t\t\t               ng-if=\"$index < outgoingSequenceFlow.length - 1\">\n\t\t\t                 <i class=\"glyphicon glyphicon-arrow-down\"></i>\n\t\t\t            </a>\n\t\t\t        </li>\n\t\t\t    </ol>\n\t\t\t\n\t\t\t\n\t\t\t</div>\n\t\t\t<div class=\"modal-footer\">\n\t\t\t    <button ng-click=\"cancel()\" class=\"btn btn-primary\" translate>ACTION.CANCEL</button>\n\t\t\t    <button ng-click=\"save()\" class=\"btn btn-primary\" translate>ACTION.SAVE</button>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/sequenceflow-order-write-template.html",
    "content": "\n<!-- Just need to instantiate the controller, and it will take care of showing the modal dialog -->\n<span ng-controller=\"KisBpmSequenceFlowOrderCtrl\">\n</span>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/signal-definitions-display-template.html",
    "content": "\n<span ng-if=\"!property.noValue\">{{'PROPERTY.SIGNALDEFINITIONS.DISPLAY' | translate:property.value}}</span>\n<span ng-if=\"property.noValue\" translate>PROPERTY.SIGNALDEFINITIONS.EMPTY</span>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/signal-definitions-popup.html",
    "content": "\n<div class=\"modal\" ng-controller=\"ActivitiSignalDefinitionsPopupCtrl\">\n    <div class=\"modal-dialog modal-wide\">\n        <div class=\"modal-content\">\n\n            <div class=\"modal-header\">\n                <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\" ng-click=\"close()\">&times;</button>\n                <h2>{{'PROPERTY.PROPERTY.EDIT.TITLE' | translate:property}}</h2>\n            </div>\n\n            <div class=\"modal-body\">\n            \n                <div class=\"row row-no-gutter\">\n\n                \t<div class=\"col-xs-8\">\n                        <div ng-if=\"translationsRetrieved\" class=\"kis-listener-grid\" ng-grid=\"gridOptions\"></div>\n            \t        <div class=\"pull-right\">\n            \t            <div class=\"btn-group\">\n            \t                <a class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{ACTION.ADD | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"addNewSignalDefinition()\"><i class=\"glyphicon glyphicon-plus\"></i></a>\n            \t                <a class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{ACTION.REMOVE | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"removeSignalDefinition()\"><i class=\"glyphicon glyphicon-minus\"></i></a>\n            \t            </div>\n            \t        </div>\n            \t\t</div>\n\n                    <div class=\"col-xs-4\" ng-show=\"selectedSignals && selectedSignals.length > 0\">\n\n                        <div class=\"form-group\">\n                            <label>{{'PROPERTY.SIGNALDEFINITIONS.ID' | translate}}</label>\n                            <input type=\"text\" class=\"form-control\" ng-model=\"selectedSignals[0].id\">\n                        </div>\n\n                        <div class=\"form-group\">\n                            <label>{{'PROPERTY.SIGNALDEFINITIONS.NAME' | translate}}</label>\n                            <input type=\"text\" class=\"form-control\" ng-model=\"selectedSignals[0].name\">\n                        </div>\n\n                        <div class=\"form-group\">\n                            <label>{{'PROPERTY.SIGNALDEFINITIONS.SCOPE' | translate}}</label>\n                            <select class=\"form-control\" ng-model=\"selectedSignals[0].scope\">\n                                <option value=\"global\">{{'PROPERTY.SIGNALDEFINITIONS.SCOPE-GLOBAL' | translate}}</option>\n                                <option value=\"processInstance\">{{'PROPERTY.SIGNALDEFINITIONS.SCOPE-PROCESSINSTANCE' | translate}}</option>\n                            </select>\n                        </div>\n\n                    </div>\n\n            \t</div>\n            \t\n            </div>\n\n            <div class=\"modal-footer\">\n                <button ng-click=\"cancel()\" class=\"btn btn-primary\" translate>ACTION.CANCEL</button>\n                <button ng-click=\"save()\" class=\"btn btn-primary\" translate>ACTION.SAVE</button>\n            </div>\n\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/signal-definitions-write-template.html",
    "content": "\n<!-- Just need to instantiate the controller, and it will take care of showing the modal dialog -->\n<span ng-controller=\"ActivitiSignalDefinitionsCtrl\">\n</span>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/signal-property-write-template.html",
    "content": "<div ng-controller=\"ActivitiSignalRefCtrl\">\n    <select ng-model=\"property.value\" ng-change=\"signalChanged()\" ng-options=\"signalDefinition.id as (signalDefinition.name + ' (' + signalDefinition.id + ')') for signalDefinition in signalDefinitions\">\n    </select>\n</div>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/string-property-write-mode-template.html",
    "content": "\n<div ng-controller=\"KisBpmStringPropertyCtrl\">\n    <input type=\"text\" ng-model=\"property.value\"\n    \t   class=\"form-control\" \n           auto-focus\n           ng-blur=\"inputBlurred()\"\n           ng-keypress=\"enterPressed($event)\"/>\n</div>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/subprocess-reference-display-template.html",
    "content": "\n<span ng-if=\"property.value.name\">{{property.value.name}}</span>\n<span ng-if=\"!property.value || !property.value.name\" translate>PROPERTY.SUBPROCESSREFERENCE.EMPTY</span>\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/subprocess-reference-popup.html",
    "content": "\n<div class=\"modal\" ng-controller=\"KisBpmCollapsedSubprocessReferencePopupCrtl\">\n    <div class=\"modal-dialog modal-wide\">\n        <div class=\"modal-content\">\n\t\t\t<div class=\"modal-header\">\n\t\t\t    <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\" ng-click=\"close()\">&times;</button>\n\t\t\t    <h2>\n\t\t\t        {{'PROPERTY.SUBPROCESSREFERENCE.TITLE' | translate}}\n\t\t\t        <span ng-show=\"selectedSubProcess != null\"> - {{selectedSubProcess.name}}</span>\n\t\t\t        <span ng-show=\"selectedSubProcess == null\"> - {{'PROPERTY.SUBPROCESSREFERENCE.EMPTY' | translate}}</span> \n\t\t\t    \n\t\t\t    </h2>\n\t\t\t</div>\n\t\t\t<div class=\"modal-body\">\n\t\t\t    <div class=\"detail-group clearfix\">\n                    <div class=\"col-xs-12\">\n\t\t\t            <div class=\"alert alert-error\" ng-show=\"(!state.loadingFolders && !state.loadingSubprocesses) && state.subprocessError\" translate>PROPERTY.SUBPROCESSREFERENCE.ERROR.SUBPROCESS</div>\n\t\t\t        </div>\n\t\t\t    </div>\n\t\t\t    <div class=\"detail-group clearfix\">\n                    <div class=\"col-xs-12 editor-item-picker\">\n\t\t\t            <div ng-if=\"!state.loadingSubprocesses && !state.subprocessError\" class=\"col-xs-4 editor-item-picker-component\" ng-repeat=\"sub in subProcesses\" ng-class=\"{'selected' : sub.id == selectedSubProcess.id}\" ng-click=\"selectSubProcess(sub, $event)\">\n\t\t\t               <div class=\"controls\">\n\t\t\t                   <input type=\"checkbox\" value=\"option1\" ng-click=\"selectSubProcess(sub, $event)\" ng-checked=\"sub.id == selectedSubProcess.id\" />\n\t\t\t               </div>\n\t\t\t               <h4>{{sub.name}}</h4>\n\t\t\t               <img src=\"{{config.contextRoot}}/app/rest/models/{{sub.id}}/thumbnail\" />\n\t\t\t             </div>\n\t\t\t             <div ng-show=\"state.loadingSubprocesses\">\n\t\t\t               <p class=\"loading\" translate>PROPERTY.SUBPROCESSREFERENCE.SUBPROCESS.LOADING</p>\n\t\t\t             </div>\n\t\t\t             <div ng-show=\"!state.loadingSubprocesses && subProcesses.length == 0\">\n\t\t\t                <p translate>PROPERTY.SUBPROCESSREFERENCE.SUBPROCESS.EMPTY</p>\n\t\t\t             </div>\n\t\t\t        </div>\n\t\t\t    </div>\n\t\t\t</div>\n\t\t\t<div class=\"modal-footer\">\n\t\t\t    <button ng-disabled=\"state.subprocessError\" ng-click=\"save()\" class=\"btn btn-primary\" translate>ACTION.SAVE</button>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/subprocess-reference-write-template.html",
    "content": "\n<!-- Just need to instantiate the controller, and it will take care of showing the modal dialog -->\n<span ng-controller=\"KisBpmCollapsedSubprocessReferenceCrtl\">\n</span>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/task-listeners-display-template.html",
    "content": "\n<span ng-if=\"!property.noValue\">{{'PROPERTY.TASKLISTENERS.VALUE' | translate:property.value.taskListeners}}</span>\n<span ng-if=\"property.noValue\" translate>PROPERTY.TASKLISTENERS.EMPTY</span>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/task-listeners-popup.html",
    "content": "\n<div class=\"modal\" ng-controller=\"KisBpmTaskListenersPopupCtrl\">\n    <div class=\"modal-dialog modal-wide\">\n        <div class=\"modal-content\">\n\t\t\t<div class=\"modal-header\">\n\t\t\t    <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\" ng-click=\"close()\">&times;</button>\n\t\t\t    <h2>{{'PROPERTY.PROPERTY.EDIT.TITLE' | translate:property}}</h2>\n\t\t\t</div>\n\t\t\t<div class=\"modal-body\">\n\t\t\t\n\t\t\t    <div class=\"row row-no-gutter\">\n\t\t\t        <div class=\"col-xs-6\">\n\t\t\t            <div ng-if=\"translationsRetrieved\" class=\"kis-listener-grid\" ng-grid=\"gridOptions\"></div>\n\t\t\t            <div class=\"pull-right\">\n\t\t\t                <div class=\"btn-group\">\n\t\t\t                    <a class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{ACTION.MOVE.UP | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"moveListenerUp()\"><i class=\"glyphicon glyphicon-arrow-up\"></i></a>\n\t\t\t                    <a class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{ACTION.MOVE.DOWN | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"moveListenerDown()\"><i class=\"glyphicon glyphicon-arrow-down\"></i></a>\n\t\t\t                </div>\n\t\t\t                <div class=\"btn-group\">\n\t\t\t                    <a class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{ACTION.ADD | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"addNewListener()\"><i class=\"glyphicon glyphicon-plus\"></i></a>\n\t\t\t                    <a class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{ACTION.REMOVE | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"removeListener()\"><i class=\"glyphicon glyphicon-minus\"></i></a>\n\t\t\t                </div>\n\t\t\t            </div>\n\t\t\t        </div>\n\t\t\t\n\t\t\t        <div class=\"col-xs-6\">\n\t\t\t            <div ng-show=\"selectedListeners.length > 0\">\n\t\t\t\n\t\t\t                <div class=\"form-group\">\n\t\t\t\t\t\t   \t\t<label for=\"eventField\">{{'PROPERTY.TASKLISTENERS.EVENT' | translate}}</label>\n\t\t\t\t\t\t   \t\t<select id=\"eventField\" class=\"form-control\" ng-model=\"selectedListeners[0].event\">\n\t\t\t                        <option>create</option>\n\t\t\t                        <option>assignment</option>\n\t\t\t                        <option>complete</option>\n\t\t\t                        <option>delete</option>\n\t\t\t                    </select>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t   \t\t<label for=\"classField\">{{'PROPERTY.TASKLISTENERS.CLASS' | translate}}</label>\n\t\t\t\t\t\t   \t\t<input type=\"text\" id=\"classField\" class=\"form-control\" ng-model=\"selectedListeners[0].className\" ng-change=\"listenerDetailsChanged()\" placeholder=\"{{'PROPERTY.TASKLISTENERS.CLASS.PLACEHOLDER' | translate}}\" />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t   \t\t<label for=\"expressionField\">{{'PROPERTY.TASKLISTENERS.EXPRESSION' | translate}}</label>\n\t\t\t\t\t\t   \t\t<input type=\"text\" id=\"expressionField\" class=\"form-control\" ng-model=\"selectedListeners[0].expression\" ng-change=\"listenerDetailsChanged()\" placeholder=\"{{'PROPERTY.TASKLISTENERS.EXPRESSION.PLACEHOLDER' | translate}}\" />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t   \t\t<label for=\"delegateExpressionField\">{{'PROPERTY.TASKLISTENERS.DELEGATEEXPRESSION' | translate}}</label>\n\t\t\t\t\t\t   \t\t<input type=\"text\" id=\"delegateExpressionField\" class=\"form-control\" ng-model=\"selectedListeners[0].delegateExpression\" ng-change=\"listenerDetailsChanged()\" placeholder=\"{{'PROPERTY.TASKLISTENERS.DELEGATEEXPRESSION.PLACEHOLDER' | translate}}\" />\n\t\t\t\t\t\t\t</div>\n\t\t\t            </div>\n\t\t\t            <div ng-show=\"selectedListeners.length == 0\" class=\"muted no-property-selected\" translate>PROPERTY.TASKLISTENERS.UNSELECTED</div>\n\t\t\t        </div>\n\t\t\t    </div>\n\t\t\t    \n\t\t\t    <div class=\"row row-no-gutter\">\n\t\t\t        <div class=\"col-xs-6\">\n\t\t\t            <div ng-if=\"translationsRetrieved\" class=\"kis-field-grid\" ng-grid=\"gridFieldOptions\"></div>\n\t\t\t            <div class=\"pull-right\">\n\t\t\t                <div class=\"btn-group\">\n\t\t\t                    <a class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{ACTION.MOVE.UP | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"moveFieldUp()\"><i class=\"glyphicon glyphicon-arrow-up\"></i></a>\n\t\t\t                    <a class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{ACTION.MOVE.DOWN | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"moveFieldDown()\"><i class=\"glyphicon glyphicon-arrow-down\"></i></a>\n\t\t\t                </div>\n\t\t\t                <div class=\"btn-group\">\n\t\t\t                    <a class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{ACTION.ADD | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"addNewField()\"><i class=\"glyphicon glyphicon-plus\"></i></a>\n\t\t\t                    <a class=\"btn btn-icon btn-lg\" rel=\"tooltip\" data-title=\"{{ACTION.REMOVE | translate}}\" data-placement=\"bottom\" data-original-title=\"\" title=\"\" ng-click=\"removeField()\"><i class=\"glyphicon glyphicon-minus\"></i></a>\n\t\t\t                </div>\n\t\t\t            </div>\n\t\t\t        </div>\n\t\t\t\n\t\t\t        <div class=\"col-xs-6\">\n\t\t\t            <div ng-show=\"selectedFields.length > 0\">\n\t\t\t\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t   \t\t<label for=\"nameField\">{{'PROPERTY.TASKLISTENERS.FIELDS.NAME' | translate}}</label>\n\t\t\t\t\t\t   \t\t<input type=\"text\" id=\"nameField\" class=\"form-control\" ng-model=\"selectedFields[0].name\" placeholder=\"{{'PROPERTY.TASKLISTENERS.FIELDS.NAME.PLACEHOLDER' | translate}}\" />\n\t\t\t\t\t\t\t</div>\n\t\t\t                <div class=\"form-group\">\n\t\t\t\t\t\t   \t\t<label for=\"stringValueField\">{{'PROPERTY.TASKLISTENERS.FIELDS.STRINGVALUE' | translate}}</label>\n\t\t\t\t\t\t   \t\t<input type=\"text\" id=\"stringValueField\" class=\"form-control\" ng-model=\"selectedFields[0].stringValue\" ng-change=\"fieldDetailsChanged()\" placeholder=\"{{'PROPERTY.TASKLISTENERS.FIELDS.STRINGVALUE.PLACEHOLDER' | translate}}\" />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t   \t\t<label for=\"expressionField\">{{'PROPERTY.TASKLISTENERS.FIELDS.EXPRESSION' | translate}}</label>\n\t\t\t\t\t\t   \t\t<input type=\"text\" id=\"expressionField\" class=\"form-control\" ng-model=\"selectedFields[0].expression\" ng-change=\"fieldDetailsChanged()\" placeholder=\"{{'PROPERTY.TASKLISTENERS.FIELDS.EXPRESSION.PLACEHOLDER' | translate}}\" />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t   \t\t<label for=\"stringField\">{{'PROPERTY.TASKLISTENERS.FIELDS.STRING' | translate}}</label>\n\t\t\t\t\t\t   \t\t<textarea id=\"stringField\" class=\"form-control\" ng-model=\"selectedFields[0].string\" ng-change=\"fieldDetailsChanged()\" placeholder=\"{{'PROPERTY.TASKLISTENERS.FIELDS.STRING.PLACEHOLDER' | translate}}\"></textarea>\n\t\t\t\t\t\t\t</div>\n\t\t\t                \n\t\t\t            </div>\n\t\t\t            <div ng-show=\"selectedFields.length == 0\" class=\"muted no-property-selected\"translate>PROPERTY.TASKLISTENERS.FIELDS.EMPTY</div>\n\t\t\t        </div>\n\t\t\t    </div>\n\t\t\t\n\t\t\t</div>\n\t\t\t<div class=\"modal-footer\">\n\t\t\t    <button ng-click=\"cancel()\" class=\"btn btn-primary\" translate>ACTION.CANCEL</button>\n\t\t\t    <button ng-click=\"save()\" class=\"btn btn-primary\" translate>ACTION.SAVE</button>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/task-listeners-write-template.html",
    "content": "\n<!-- Just need to instantiate the controller, and it will take care of showing the modal dialog -->\n<span ng-controller=\"KisBpmTaskListenersCtrl\">\n</span>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/text-popup.html",
    "content": "\n<div class=\"modal\" ng-controller=\"KisBpmTextPropertyPopupCtrl\">\n    <div class=\"modal-dialog\">\n        <div class=\"modal-content\">\n\t\t\t<div class=\"modal-header\">\n\t\t\t\t<button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\" ng-click=\"close()\">&times;</button>\n\t\t\t    <h3>{{'PROPERTY.PROPERTY.EDIT.TITLE' | translate:property}}</h3>\n\t\t\t</div>\n\t\t\t<div class=\"modal-body\">\n\t\t\t\t<p><textarea auto-focus class=\"form-control\" ng-model=\"property.value\" style=\"width:70%; height:100%; max-width: 100%; max-height: 100%; min-height: 200px\"/></p>\n\t\t\t</div>\n\t\t\t<div class=\"modal-footer\">\n\t\t\t\t<button ng-click=\"save()\" class=\"btn btn-primary\" translate >ACTION.SAVE</button>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties/text-property-write-template.html",
    "content": "\n<!-- Just need to instantiate the controller, and it will take care of showing the modal dialog -->\n<span ng-controller=\"KisBpmTextPropertyCtrl\">\n</span>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties-assignment-controller.js",
    "content": "/*\n * Activiti Modeler component part of the Activiti project\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * \n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n */\n\n/*\n * Assignment\n */\nvar KisBpmAssignmentCtrl = [ '$scope', '$modal', function($scope, $modal) {\n\n    // Config for the modal window\n    var opts = {\n        template:  'editor-app/configuration/properties/assignment-popup.html?version=' + Date.now(),\n        scope: $scope\n    };\n\n    // Open the dialog\n    $modal(opts);\n}];\n\nvar KisBpmAssignmentPopupCtrl = [ '$scope', function($scope) {\n    \t\n    // Put json representing assignment on scope\n    if ($scope.property.value !== undefined && $scope.property.value !== null\n        && $scope.property.value.assignment !== undefined\n        && $scope.property.value.assignment !== null) \n    {\n        $scope.assignment = $scope.property.value.assignment;\n    } else {\n        $scope.assignment = {};\n    }\n\n    if ($scope.assignment.candidateUsers == undefined || $scope.assignment.candidateUsers.length == 0)\n    {\n    \t$scope.assignment.candidateUsers = [{value: ''}];\n    }\n    \n    // Click handler for + button after enum value\n    var userValueIndex = 1;\n    $scope.addCandidateUserValue = function(index) {\n        $scope.assignment.candidateUsers.splice(index + 1, 0, {value: 'value ' + userValueIndex++});\n    };\n\n    // Click handler for - button after enum value\n    $scope.removeCandidateUserValue = function(index) {\n        $scope.assignment.candidateUsers.splice(index, 1);\n    };\n    \n    if ($scope.assignment.candidateGroups == undefined || $scope.assignment.candidateGroups.length == 0)\n    {\n    \t$scope.assignment.candidateGroups = [{value: ''}];\n    }\n    \n    var groupValueIndex = 1;\n    $scope.addCandidateGroupValue = function(index) {\n        $scope.assignment.candidateGroups.splice(index + 1, 0, {value: 'value ' + groupValueIndex++});\n    };\n\n    // Click handler for - button after enum value\n    $scope.removeCandidateGroupValue = function(index) {\n        $scope.assignment.candidateGroups.splice(index, 1);\n    };\n\n    $scope.save = function() {\n\n        $scope.property.value = {};\n        handleAssignmentInput($scope);\n        $scope.property.value.assignment = $scope.assignment;\n        \n        $scope.updatePropertyInModel($scope.property);\n        $scope.close();\n    };\n\n    // Close button handler\n    $scope.close = function() {\n    \thandleAssignmentInput($scope);\n    \t$scope.property.mode = 'read';\n    \t$scope.$hide();\n    };\n    \n    var handleAssignmentInput = function($scope) {\n    \tif ($scope.assignment.candidateUsers)\n    \t{\n\t    \tvar emptyUsers = true;\n\t    \tvar toRemoveIndexes = [];\n\t        for (var i = 0; i < $scope.assignment.candidateUsers.length; i++)\n\t        {\n\t        \tif ($scope.assignment.candidateUsers[i].value != '')\n\t        \t{\n\t        \t\temptyUsers = false;\n\t        \t}\n\t        \telse\n\t        \t{\n\t        \t\ttoRemoveIndexes[toRemoveIndexes.length] = i;\n\t        \t}\n\t        }\n\t        \n\t        for (var i = 0; i < toRemoveIndexes.length; i++)\n\t        {\n\t        \t$scope.assignment.candidateUsers.splice(toRemoveIndexes[i], 1);\n\t        }\n\t        \n\t        if (emptyUsers)\n\t        {\n\t        \t$scope.assignment.candidateUsers = undefined;\n\t        }\n    \t}\n        \n    \tif ($scope.assignment.candidateGroups)\n    \t{\n\t        var emptyGroups = true;\n\t        var toRemoveIndexes = [];\n\t        for (var i = 0; i < $scope.assignment.candidateGroups.length; i++)\n\t        {\n\t        \tif ($scope.assignment.candidateGroups[i].value != '')\n\t        \t{\n\t        \t\temptyGroups = false;\n\t        \t}\n\t        \telse\n\t        \t{\n\t        \t\ttoRemoveIndexes[toRemoveIndexes.length] = i;\n\t        \t}\n\t        }\n\t        \n\t        for (var i = 0; i < toRemoveIndexes.length; i++)\n\t        {\n\t        \t$scope.assignment.candidateGroups.splice(toRemoveIndexes[i], 1);\n\t        }\n\t        \n\t        if (emptyGroups)\n\t        {\n\t        \t$scope.assignment.candidateGroups = undefined;\n\t        }\n    \t}\n    };\n}];"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties-condition-expression-controller.js",
    "content": "/*\n * Activiti Modeler component part of the Activiti project\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * \n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n */\n\n/*\n * Condition expression\n */\n\nvar KisBpmConditionExpressionCtrl = [ '$scope', '$modal', function($scope, $modal) {\n\n    // Config for the modal window\n    var opts = {\n        template:  'editor-app/configuration/properties/condition-expression-popup.html?version=' + Date.now(),\n        scope: $scope\n    };\n\n    // Open the dialog\n    $modal(opts);\n}];\n\nvar KisBpmConditionExpressionPopupCtrl = [ '$scope', '$translate', '$http', function($scope, $translate, $http) {\n\n\t// Put json representing condition on scope\n    if ($scope.property.value !== undefined && $scope.property.value !== null) {\n\n        $scope.conditionExpression = {value: $scope.property.value};\n        \n    } else {\n        $scope.conditionExpression = {value: ''};\n    }\n\t\n    $scope.save = function() {\n        $scope.property.value = $scope.conditionExpression.value;\n        $scope.updatePropertyInModel($scope.property);\n        $scope.close();\n    };\n\n    // Close button handler\n    $scope.close = function() {\n    \t$scope.property.mode = 'read';\n    \t$scope.$hide();\n    };\n}];"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties-custom-controllers.js",
    "content": "/*\n * Activiti Modeler component part of the Activiti project\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * \n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n */\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties-default-controllers.js",
    "content": "/*\n * Activiti Modeler component part of the Activiti project\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * \n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n */\n\n/*\n * String controller\n */\n\nvar KisBpmStringPropertyCtrl = [ '$scope', function ($scope) {\n\n\t$scope.shapeId = $scope.selectedShape.id;\n\t$scope.valueFlushed = false;\n    /** Handler called when input field is blurred */\n    $scope.inputBlurred = function() {\n    \t$scope.valueFlushed = true;\n    \tif ($scope.property.value) {\n    \t\t$scope.property.value = $scope.property.value.replace(/(<([^>]+)>)/ig,\"\");\n    \t}\n        $scope.updatePropertyInModel($scope.property);\n    };\n\n    $scope.enterPressed = function(keyEvent) {\n    \tif (keyEvent && keyEvent.which === 13) {\n    \t\tkeyEvent.preventDefault();\n\t        $scope.inputBlurred(); // we want to do the same as if the user would blur the input field\n    \t}\n    };\n    \n    $scope.$on('$destroy', function controllerDestroyed() {\n    \tif(!$scope.valueFlushed) {\n    \t\tif ($scope.property.value) {\n        \t\t$scope.property.value = $scope.property.value.replace(/(<([^>]+)>)/ig,\"\");\n        \t}\n    \t\t$scope.updatePropertyInModel($scope.property, $scope.shapeId);\n    \t}\n    });\n\n}];\n\n/*\n * Boolean controller\n */\n\nvar KisBpmBooleanPropertyCtrl = ['$scope', function ($scope) {\n\n    $scope.changeValue = function() {\n        if ($scope.property.key === 'oryx-defaultflow' && $scope.property.value) {\n            var selectedShape = $scope.selectedShape;\n            if (selectedShape) {\n                var incomingNodes = selectedShape.getIncomingShapes();\n                if (incomingNodes && incomingNodes.length > 0) {\n                    // get first node, since there can be only one for a sequence flow\n                    var rootNode = incomingNodes[0];\n                    var flows = rootNode.getOutgoingShapes();\n                    if (flows && flows.length > 1) {\n                        // in case there are more flows, check if another flow is already defined as default\n                        for (var i = 0; i < flows.length; i++) {\n                            if (flows[i].resourceId != selectedShape.resourceId) {\n                                var defaultFlowProp = flows[i].properties['oryx-defaultflow'];\n                                if (defaultFlowProp) {\n                                    flows[i].setProperty('oryx-defaultflow', false, true);\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        $scope.updatePropertyInModel($scope.property);\n    };\n\n}];\n\n/*\n * Text controller\n */\n\nvar KisBpmTextPropertyCtrl = [ '$scope', '$modal', function($scope, $modal) {\n\n    var opts = {\n        template:  'editor-app/configuration/properties/text-popup.html?version=' + Date.now(),\n        scope: $scope\n    };\n\n    // Open the dialog\n    $modal(opts);\n}];\n\nvar KisBpmTextPropertyPopupCtrl = ['$scope', function($scope) {\n    \n    $scope.save = function() {\n        $scope.updatePropertyInModel($scope.property);\n        $scope.close();\n    };\n\n    $scope.close = function() {\n        $scope.property.mode = 'read';\n        $scope.$hide();\n    };\n}];"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties-event-listeners-controller.js",
    "content": "/*\n * Activiti Modeler component part of the Activiti project\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * \n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n */\n\n/*\n * Execution listeners\n */\n\nvar KisBpmEventListenersCtrl = [ '$scope', '$modal', '$timeout', '$translate', function($scope, $modal, $timeout, $translate) {\n\n    // Config for the modal window\n    var opts = {\n        template:  'editor-app/configuration/properties/event-listeners-popup.html?version=' + Date.now(),\n        scope: $scope\n    };\n\n    // Open the dialog\n    $modal(opts);\n}];\n\n//Need a separate controller for the modal window due to https://github.com/angular-ui/bootstrap/issues/259\n// Will be fixed in a newer version of Angular UI\nvar KisBpmEventListenersPopupCtrl = [ '$scope', '$q', '$translate', function($scope, $q, $translate) {\n\n    // Put json representing form properties on scope\n    if ($scope.property.value !== undefined && $scope.property.value !== null\n        && $scope.property.value.eventListeners !== undefined\n        && $scope.property.value.eventListeners !== null) {\n    \t\n    \tif ($scope.property.value.eventListeners.constructor == String)\n    \t{\n    \t\t$scope.eventListeners = JSON.parse($scope.property.value.eventListeners);\n    \t}\n    \telse\n    \t{\n    \t\t// Note that we clone the json object rather then setting it directly,\n            // this to cope with the fact that the user can click the cancel button and no changes should have happened\n    \t\t$scope.eventListeners = angular.copy($scope.property.value.eventListeners);\n    \t}\n    \t\n    } else {\n        $scope.eventListeners = [];\n    }\n\n    // Array to contain selected properties (yes - we only can select one, but ng-grid isn't smart enough)\n    $scope.selectedListeners = [];\n    $scope.translationsRetrieved = false;\n    \n    $scope.labels = {};\n    \n    var eventPromise = $translate('PROPERTY.EXECUTIONLISTENERS.EVENT');\n    var implementationPromise = $translate('PROPERTY.EXECUTIONLISTENERS.FIELDS.IMPLEMENTATION');\n    var namePromise = $translate('PROPERTY.EXECUTIONLISTENERS.FIELDS.NAME');\n    \n    $q.all([eventPromise, implementationPromise, namePromise]).then(function(results) { \n        $scope.labels.eventLabel = results[0];\n        $scope.labels.implementationLabel = results[1];\n        $scope.labels.nameLabel = results[2];\n        $scope.translationsRetrieved = true;\n        \n        // Config for grid\n        $scope.gridOptions = {\n            data: 'eventListeners',\n            enableRowReordering: true,\n            headerRowHeight: 28,\n            multiSelect: false,\n            keepLastSelected : false,\n            selectedItems: $scope.selectedListeners,\n            afterSelectionChange: function (rowItem, event) {\n            \t\n            \tif ($scope.selectedListeners.length > 0)\n            \t{\n\t            \tvar fields = $scope.selectedListeners[0].fields;\n\t            \tif (fields !== undefined && fields !== null)\n\t            \t{\n\t            \t\tfor (var i = 0; i < fields.length; i++)\n\t            \t\t{\n\t            \t\t\tvar field = fields[i];\n\t            \t\t\tif (field.stringValue !== undefined && field.stringValue !== '')\n\t                    \t{\n\t            \t\t\t\tfield.implementation = field.stringValue;\n\t                    \t}\n\t                    \telse if (field.expression !== undefined && field.expression !== '')\n\t                    \t{\n\t                    \t\tfield.implementation = field.expression;\n\t                    \t}\n\t                    \telse if (field.string !== undefined && field.string !== '')\n\t                    \t{\n\t                    \t\tfield.implementation = field.string;\n\t                    \t}\n\t            \t\t}\n\t            \t}\n\t            \t\n\t            \tif (!$scope.selectedListeners[0].events || $scope.selectedListeners[0].events.length == 0)\n\t                {\n\t                \t$scope.selectedListeners[0].events = [{event: ''}];\n\t                }\n            \t}\n            },\n            columnDefs: [{ field: 'event', displayName: $scope.labels.eventLabel },\n                { field: 'implementation', displayName: $scope.labels.implementationLabel }]\n        };\n    });\n    \n    // Click handler for + button after enum value\n    $scope.addEventValue = function(index) {\n        $scope.selectedListeners[0].events.splice(index + 1, 0, {event: ''});\n    };\n\n    // Click handler for - button after enum value\n    $scope.removeEventValue = function(index) {\n        $scope.selectedListeners[0].events.splice(index, 1);\n        $scope.listenerDetailsChanged();\n    };\n    \n    $scope.listenerDetailsChanged = function() {\n    \tvar listener = $scope.selectedListeners[0];\n    \tif (listener.events)\n    \t{\n    \t\tvar eventText = '';\n    \t\tfor (var i = 0; i < listener.events.length; i++)\n    \t\t{\n    \t\t\tif (i > 0)\n    \t\t\t{\n    \t\t\t\teventText += \", \";\n    \t\t\t}\n    \t\t\teventText += listener.events[i].event;\n    \t\t}\n    \t\t$scope.selectedListeners[0].event = eventText;\n    \t}\n    \t\n    \tif (listener.rethrowEvent)\n    \t{\n    \t\tvar implementationText = '';\n    \t\tif (listener.rethrowType && listener.rethrowType.length > 0)\n    \t\t{\n    \t\t\tif (listener.rethrowType === 'error' && listener.errorcode !== '')\n\t        \t{\n\t        \t\timplementationText = \"Rethrow as error \" + listener.errorcode;\n\t        \t}\n    \t\t\telse if (listener.rethrowType === 'message' && listener.messagename !== '')\n\t        \t{\n\t        \t\timplementationText = \"Rethrow as message \" + listener.messagename;\n\t        \t}\n    \t\t\telse if ((listener.rethrowType === 'signal' || listener.rethrowType === 'globalSignal') && listener.signalname !== '')\n\t        \t{\n\t        \t\timplementationText = \"Rethrow as signal \" + listener.signalname;\n\t        \t}\n    \t\t}\n    \t\t$scope.selectedListeners[0].implementation = implementationText;\n    \t}\n    \telse\n    \t{\n        \tif ($scope.selectedListeners[0].className !== '')\n        \t{\n        \t\t$scope.selectedListeners[0].implementation = $scope.selectedListeners[0].className;\n        \t}\n        \telse if ($scope.selectedListeners[0].delegateExpression !== '')\n        \t{\n        \t\t$scope.selectedListeners[0].implementation = $scope.selectedListeners[0].delegateExpression;\n        \t}\n        \telse\n        \t{\n        \t\t$scope.selectedListeners[0].implementation = '';\n        \t}\n    \t}\n    };\n\n    // Click handler for add button\n    $scope.addNewListener = function() {\n        $scope.eventListeners.push({ event : '',\n            implementation : '',\n            className : '',\n            delegateExpression: '',\n            retrowEvent: false});\n    };\n\n    // Click handler for remove button\n    $scope.removeListener = function() {\n        if ($scope.selectedListeners.length > 0) {\n            var index = $scope.eventListeners.indexOf($scope.selectedListeners[0]);\n            $scope.gridOptions.selectItem(index, false);\n            $scope.eventListeners.splice(index, 1);\n\n            $scope.selectedListeners.length = 0;\n            if (index < $scope.eventListeners.length) {\n                $scope.gridOptions.selectItem(index + 1, true);\n            } else if ($scope.eventListeners.length > 0) {\n                $scope.gridOptions.selectItem(index - 1, true);\n            }\n        }\n    };\n\n    // Click handler for up button\n    $scope.moveListenerUp = function() {\n        if ($scope.selectedListeners.length > 0) {\n            var index = $scope.eventListeners.indexOf($scope.selectedListeners[0]);\n            if (index != 0) { // If it's the first, no moving up of course\n                // Reason for funny way of swapping, see https://github.com/angular-ui/ng-grid/issues/272\n                var temp = $scope.eventListeners[index];\n                $scope.eventListeners.splice(index, 1);\n                $timeout(function(){\n                    $scope.eventListeners.splice(index + -1, 0, temp);\n                }, 100);\n\n            }\n        }\n    };\n\n    // Click handler for down button\n    $scope.moveListenerDown = function() {\n        if ($scope.selectedListeners.length > 0) {\n            var index = $scope.eventListeners.indexOf($scope.selectedListeners[0]);\n            if (index != $scope.eventListeners.length - 1) { // If it's the last element, no moving down of course\n                // Reason for funny way of swapping, see https://github.com/angular-ui/ng-grid/issues/272\n                var temp = $scope.eventListeners[index];\n                $scope.eventListeners.splice(index, 1);\n                $timeout(function(){\n                    $scope.eventListeners.splice(index + 1, 0, temp);\n                }, 100);\n\n            }\n        }\n    };\n\n    // Click handler for save button\n    $scope.save = function() {\n\n        if ($scope.eventListeners.length > 0) {\n            $scope.property.value = {};\n            $scope.property.value.eventListeners = $scope.eventListeners;\n        } else {\n            $scope.property.value = null;\n        }\n\n        $scope.updatePropertyInModel($scope.property);\n        $scope.close();\n    };\n\n    $scope.cancel = function() {\n    \t$scope.property.mode = 'read';\n    \t$scope.$hide();\n    };\n\n    // Close button handler\n    $scope.close = function() {\n    \t$scope.property.mode = 'read';\n    \t$scope.$hide();\n    };\n\n}];"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties-execution-listeners-controller.js",
    "content": "/*\n * Activiti Modeler component part of the Activiti project\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * \n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n */\n\n/*\n * Execution listeners\n */\n\nvar KisBpmExecutionListenersCtrl = [ '$scope', '$modal', '$timeout', '$translate', function($scope, $modal, $timeout, $translate) {\n\n    // Config for the modal window\n    var opts = {\n        template:  'editor-app/configuration/properties/execution-listeners-popup.html?version=' + Date.now(),\n        scope: $scope\n    };\n\n    // Open the dialog\n    $modal(opts);\n}];\n\nvar KisBpmExecutionListenersPopupCtrl = [ '$scope', '$q', '$translate', function($scope, $q, $translate) {\n\n    // Put json representing form properties on scope\n    if ($scope.property.value !== undefined && $scope.property.value !== null\n        && $scope.property.value.executionListeners !== undefined\n        && $scope.property.value.executionListeners !== null) {\n        \n        if ($scope.property.value.executionListeners.constructor == String)\n        {\n            $scope.executionListeners = JSON.parse($scope.property.value.executionListeners);\n        }\n        else\n        {\n            // Note that we clone the json object rather then setting it directly,\n            // this to cope with the fact that the user can click the cancel button and no changes should have happened\n            $scope.executionListeners = angular.copy($scope.property.value.executionListeners);\n        }\n        \n        for (var i = 0; i < $scope.executionListeners.length; i++)\n        {\n            var executionListener = $scope.executionListeners[i];\n            if (executionListener.className !== undefined && executionListener.className !== '')\n            {\n                executionListener.implementation = executionListener.className;\n            }\n            else if (executionListener.expression !== undefined && executionListener.expression !== '')\n            {\n                executionListener.implementation = executionListener.expression;\n            }\n            else if (executionListener.delegateExpression !== undefined && executionListener.delegateExpression !== '')\n            {\n                executionListener.implementation = executionListener.delegateExpression;\n            }\n        }\n    } else {\n        $scope.executionListeners = [];\n    }\n\n    // Array to contain selected properties (yes - we only can select one, but ng-grid isn't smart enough)\n    $scope.selectedListeners = [];\n    $scope.selectedFields = [];\n    $scope.translationsRetrieved = false;\n    \n    $scope.labels = {};\n    \n    var eventPromise = $translate('PROPERTY.EXECUTIONLISTENERS.EVENT');\n    var implementationPromise = $translate('PROPERTY.EXECUTIONLISTENERS.FIELDS.IMPLEMENTATION');\n    var namePromise = $translate('PROPERTY.EXECUTIONLISTENERS.FIELDS.NAME');\n    \n    $q.all([eventPromise, implementationPromise, namePromise]).then(function(results) { \n        $scope.labels.eventLabel = results[0];\n        $scope.labels.implementationLabel = results[1];\n        $scope.labels.nameLabel = results[2];\n        $scope.translationsRetrieved = true;\n        \n        // Config for grid\n        $scope.gridOptions = {\n            data: 'executionListeners',\n            enableRowReordering: true,\n            headerRowHeight: 28,\n            multiSelect: false,\n            keepLastSelected : false,\n            selectedItems: $scope.selectedListeners,\n            afterSelectionChange: function (rowItem, event) {\n                $scope.selectedFields.length = 0;\n                if ($scope.selectedListeners.length > 0)\n                {\n                    var fields = $scope.selectedListeners[0].fields;\n                    if (fields !== undefined && fields !== null)\n                    {\n                        for (var i = 0; i < fields.length; i++)\n                        {\n                            var field = fields[i];\n                            if (field.stringValue !== undefined && field.stringValue !== '')\n                            {\n                                field.implementation = field.stringValue;\n                            }\n                            else if (field.expression !== undefined && field.expression !== '')\n                            {\n                                field.implementation = field.expression;\n                            }\n                            else if (field.string !== undefined && field.string !== '')\n                            {\n                                field.implementation = field.string;\n                            }\n                        }\n                    }\n                }\n            },\n            columnDefs: [{ field: 'event', displayName: $scope.labels.eventLabel },\n                { field: 'implementation', displayName: $scope.labels.implementationLabel }]\n        };\n        \n        // Config for field grid\n        $scope.gridFieldOptions = {\n            data: 'selectedListeners[0].fields',\n            enableRowReordering: true,\n            headerRowHeight: 28,\n            multiSelect: false,\n            keepLastSelected : false,\n            selectedItems: $scope.selectedFields,\n            columnDefs: [{ field: 'name', displayName: $scope.labels.nameLabel },\n                { field: 'implementation', displayName: $scope.labels.implementationLabel}]\n        };\n    });\n    \n    $scope.listenerDetailsChanged = function() {\n        if ($scope.selectedListeners[0].className !== '')\n        {\n            $scope.selectedListeners[0].implementation = $scope.selectedListeners[0].className;\n        }\n        else if ($scope.selectedListeners[0].expression !== '')\n        {\n            $scope.selectedListeners[0].implementation = $scope.selectedListeners[0].expression;\n        }\n        else if ($scope.selectedListeners[0].delegateExpression !== '')\n        {\n            $scope.selectedListeners[0].implementation = $scope.selectedListeners[0].delegateExpression;\n        }\n        else\n        {\n            $scope.selectedListeners[0].implementation = '';\n        }\n    };\n\n    // Click handler for add button\n    $scope.addNewListener = function() {\n        $scope.executionListeners.push({ event : 'start',\n            implementation : '',\n            className : '',\n            expression: '',\n            delegateExpression: ''});\n    };\n\n    // Click handler for remove button\n    $scope.removeListener = function() {\n        if ($scope.selectedListeners.length > 0) {\n            var index = $scope.executionListeners.indexOf($scope.selectedListeners[0]);\n            $scope.gridOptions.selectItem(index, false);\n            $scope.executionListeners.splice(index, 1);\n\n            $scope.selectedListeners.length = 0;\n            if (index < $scope.executionListeners.length) {\n                $scope.gridOptions.selectItem(index + 1, true);\n            } else if ($scope.executionListeners.length > 0) {\n                $scope.gridOptions.selectItem(index - 1, true);\n            }\n        }\n    };\n\n    // Click handler for up button\n    $scope.moveListenerUp = function() {\n        if ($scope.selectedListeners.length > 0) {\n            var index = $scope.executionListeners.indexOf($scope.selectedListeners[0]);\n            if (index != 0) { // If it's the first, no moving up of course\n                // Reason for funny way of swapping, see https://github.com/angular-ui/ng-grid/issues/272\n                var temp = $scope.executionListeners[index];\n                $scope.executionListeners.splice(index, 1);\n                $timeout(function(){\n                    $scope.executionListeners.splice(index + -1, 0, temp);\n                }, 100);\n\n            }\n        }\n    };\n\n    // Click handler for down button\n    $scope.moveListenerDown = function() {\n        if ($scope.selectedListeners.length > 0) {\n            var index = $scope.executionListeners.indexOf($scope.selectedListeners[0]);\n            if (index != $scope.executionListeners.length - 1) { // If it's the last element, no moving down of course\n                // Reason for funny way of swapping, see https://github.com/angular-ui/ng-grid/issues/272\n                var temp = $scope.executionListeners[index];\n                $scope.executionListeners.splice(index, 1);\n                $timeout(function(){\n                    $scope.executionListeners.splice(index + 1, 0, temp);\n                }, 100);\n\n            }\n        }\n    };\n    \n    $scope.fieldDetailsChanged = function() {\n        if ($scope.selectedFields[0].stringValue !== '')\n        {\n            $scope.selectedFields[0].implementation = $scope.selectedFields[0].stringValue;\n        }\n        else if ($scope.selectedFields[0].expression !== '')\n        {\n            $scope.selectedFields[0].implementation = $scope.selectedFields[0].expression;\n        }\n        else if ($scope.selectedFields[0].string !== '')\n        {\n            $scope.selectedFields[0].implementation = $scope.selectedFields[0].string;\n        }\n        else\n        {\n            $scope.selectedFields[0].implementation = '';\n        }\n    };\n\n    // Click handler for add button\n    $scope.addNewField = function() {\n        if ($scope.selectedListeners.length > 0)\n        {\n            if ($scope.selectedListeners[0].fields == undefined)\n            {\n                $scope.selectedListeners[0].fields = [];\n            }\n            $scope.selectedListeners[0].fields.push({ name : 'fieldName',\n                implementation : '',\n                stringValue : '',\n                expression: '',\n                string: ''});\n        }\n    };\n\n    // Click handler for remove button\n    $scope.removeField = function() {\n        if ($scope.selectedFields.length > 0) {\n            var index = $scope.selectedListeners[0].fields.indexOf($scope.selectedFields[0]);\n            $scope.gridFieldOptions.selectItem(index, false);\n            $scope.selectedListeners[0].fields.splice(index, 1);\n\n            $scope.selectedFields.length = 0;\n            if (index < $scope.selectedListeners[0].fields.length) {\n                $scope.gridFieldOptions.selectItem(index + 1, true);\n            } else if ($scope.selectedListeners[0].fields.length > 0) {\n                $scope.gridFieldOptions.selectItem(index - 1, true);\n            }\n        }\n    };\n\n    // Click handler for up button\n    $scope.moveFieldUp = function() {\n        if ($scope.selectedFields.length > 0) {\n            var index = $scope.selectedListeners[0].fields.indexOf($scope.selectedFields[0]);\n            if (index != 0) { // If it's the first, no moving up of course\n                // Reason for funny way of swapping, see https://github.com/angular-ui/ng-grid/issues/272\n                var temp = $scope.selectedListeners[0].fields[index];\n                $scope.selectedListeners[0].fields.splice(index, 1);\n                $timeout(function(){\n                    $scope.selectedListeners[0].fields.splice(index + -1, 0, temp);\n                }, 100);\n\n            }\n        }\n    };\n\n    // Click handler for down button\n    $scope.moveFieldDown = function() {\n        if ($scope.selectedFields.length > 0) {\n            var index = $scope.selectedListeners[0].fields.indexOf($scope.selectedFields[0]);\n            if (index != $scope.selectedListeners[0].fields.length - 1) { // If it's the last element, no moving down of course\n                // Reason for funny way of swapping, see https://github.com/angular-ui/ng-grid/issues/272\n                var temp = $scope.selectedListeners[0].fields[index];\n                $scope.selectedListeners[0].fields.splice(index, 1);\n                $timeout(function(){\n                    $scope.selectedListeners[0].fields.splice(index + 1, 0, temp);\n                }, 100);\n\n            }\n        }\n    };\n\n    // Click handler for save button\n    $scope.save = function() {\n\n        if ($scope.executionListeners.length > 0) {\n            $scope.property.value = {};\n            $scope.property.value.executionListeners = $scope.executionListeners;\n        } else {\n            $scope.property.value = null;\n        }\n\n        $scope.updatePropertyInModel($scope.property);\n        $scope.close();\n    };\n\n    $scope.cancel = function() {\n        $scope.$hide();\n        $scope.property.mode = 'read';\n    };\n\n    // Close button handler\n    $scope.close = function() {\n        $scope.$hide();\n        $scope.property.mode = 'read';\n    };\n\n}];"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties-fields-controller.js",
    "content": "/*\n * Activiti Modeler component part of the Activiti project\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * \n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n */\n\n/*\n * Task listeners\n */\n\nvar KisBpmFieldsCtrl = [ '$scope', '$modal', '$timeout', '$translate', function($scope, $modal, $timeout, $translate) {\n\n    // Config for the modal window\n    var opts = {\n        template:  'editor-app/configuration/properties/fields-popup.html',\n        scope: $scope\n    };\n\n    // Open the dialog\n    $modal(opts);\n}];\n\nvar KisBpmFieldsPopupCtrl = [ '$scope', '$q', '$translate', function($scope, $q, $translate) {\n\n    // Put json representing form properties on scope\n    if ($scope.property.value !== undefined && $scope.property.value !== null\n        && $scope.property.value.fields !== undefined\n        && $scope.property.value.fields !== null) {\n        // Note that we clone the json object rather then setting it directly,\n        // this to cope with the fact that the user can click the cancel button and no changes should have happened\n        $scope.fields = angular.copy($scope.property.value.fields);\n        \n        for (var i = 0; i < $scope.fields.length; i++)\n\t\t{\n\t\t\tvar field = $scope.fields[i];\n\t\t\tif (field.stringValue !== undefined && field.stringValue !== '')\n        \t{\n\t\t\t\tfield.implementation = field.stringValue;\n        \t}\n        \telse if (field.expression !== undefined && field.expression !== '')\n        \t{\n        \t\tfield.implementation = field.expression;\n        \t}\n        \telse if (field.string !== undefined && field.string !== '')\n        \t{\n        \t\tfield.implementation = field.string;\n        \t}\n\t\t}\n        \n    } else {\n        $scope.fields = [];\n    }\n\n    // Array to contain selected properties (yes - we only can select one, but ng-grid isn't smart enough)\n    $scope.selectedFields = [];\n    $scope.translationsRetrieved = false;\n    $scope.labels = {};\n\n    var namePromise = $translate('PROPERTY.FIELDS.NAME');\n    var implementationPromise = $translate('PROPERTY.FIELDS.IMPLEMENTATION');\n\n    $q.all([namePromise, implementationPromise]).then(function(results) {\n        $scope.labels.nameLabel = results[0];\n        $scope.labels.implementationLabel = results[1];\n        $scope.translationsRetrieved = true;\n\n        // Config for grid\n        $scope.gridOptions = {\n            data: 'fields',\n            enableRowReordering: true,\n            headerRowHeight: 28,\n            multiSelect: false,\n            keepLastSelected: false,\n            selectedItems: $scope.selectedFields,\n            columnDefs: [{field: 'name', displayName: $scope.labels.nameLabel},\n                {field: 'implementation', displayName: $scope.labels.implementationLabel}]\n        };\n    });\n    \n    $scope.fieldDetailsChanged = function() {\n    \tif ($scope.selectedFields[0].stringValue != '')\n    \t{\n    \t\t$scope.selectedFields[0].implementation = $scope.selectedFields[0].stringValue;\n    \t}\n    \telse if ($scope.selectedFields[0].expression != '')\n    \t{\n    \t\t$scope.selectedFields[0].implementation = $scope.selectedFields[0].expression;\n    \t}\n    \telse if ($scope.selectedFields[0].string != '')\n    \t{\n    \t\t$scope.selectedFields[0].implementation = $scope.selectedFields[0].string;\n    \t}\n    \telse\n    \t{\n    \t\t$scope.selectedFields[0].implementation = '';\n    \t}\n    };\n\n    // Click handler for add button\n    $scope.addNewField = function() {\n    \t$scope.fields.push({ name : 'fieldName',\n            implementation : '',\n            stringValue : '',\n            expression: '',\n            string: ''});\n    };\n\n    // Click handler for remove button\n    $scope.removeField = function() {\n        if ($scope.selectedFields.length > 0) {\n            var index = $scope.fields.indexOf($scope.selectedFields[0]);\n            $scope.gridOptions.selectItem(index, false);\n            $scope.fields.splice(index, 1);\n\n            $scope.selectedFields.length = 0;\n            if (index < $scope.fields.length) {\n                $scope.gridOptions.selectItem(index + 1, true);\n            } else if ($scope.fields.length > 0) {\n                $scope.gridOptions.selectItem(index - 1, true);\n            }\n        }\n    };\n\n    // Click handler for up button\n    $scope.moveFieldUp = function() {\n        if ($scope.selectedFields.length > 0) {\n            var index = $scope.fields.indexOf($scope.selectedFields[0]);\n            if (index != 0) { // If it's the first, no moving up of course\n                // Reason for funny way of swapping, see https://github.com/angular-ui/ng-grid/issues/272\n                var temp = $scope.fields[index];\n                $scope.fields.splice(index, 1);\n                $timeout(function(){\n                \t$scope.fields.splice(index + -1, 0, temp);\n                }, 100);\n\n            }\n        }\n    };\n\n    // Click handler for down button\n    $scope.moveFieldDown = function() {\n        if ($scope.selectedFields.length > 0) {\n            var index = $scope.fields.indexOf($scope.selectedFields[0]);\n            if (index != $scope.fields.length - 1) { // If it's the last element, no moving down of course\n                // Reason for funny way of swapping, see https://github.com/angular-ui/ng-grid/issues/272\n                var temp = $scope.fields[index];\n                $scope.fields.splice(index, 1);\n                $timeout(function(){\n                \t$scope.fields.splice(index + 1, 0, temp);\n                }, 100);\n\n            }\n        }\n    };\n\n    // Click handler for save button\n    $scope.save = function() {\n\n        if ($scope.fields.length > 0) {\n            $scope.property.value = {};\n            $scope.property.value.fields = $scope.fields;\n        } else {\n            $scope.property.value = null;\n        }\n\n        $scope.updatePropertyInModel($scope.property);\n        $scope.close();\n    };\n\n    $scope.cancel = function() {\n        $scope.close();\n    };\n\n    // Close button handler\n    $scope.close = function() {\n        $scope.property.mode = 'read';\n        $scope.$hide();\n    };\n}];"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties-form-properties-controller.js",
    "content": "/*\n * Activiti Modeler component part of the Activiti project\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * \n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n */\n\n/*\n * Form Properties\n */\n\nvar KisBpmFormPropertiesCtrl = [ '$scope', '$modal', '$timeout', '$translate', function($scope, $modal, $timeout, $translate) {\n\n    // Config for the modal window\n    var opts = {\n        template:  'editor-app/configuration/properties/form-properties-popup.html?version=' + Date.now(),\n        scope: $scope\n    };\n\n    // Open the dialog\n    $modal(opts);\n}];\n\nvar KisBpmFormPropertiesPopupCtrl = ['$scope', '$q', '$translate', '$timeout', function($scope, $q, $translate, $timeout) {\n\n    // Put json representing form properties on scope\n    if ($scope.property.value !== undefined && $scope.property.value !== null\n        && $scope.property.value.formProperties !== undefined\n        && $scope.property.value.formProperties !== null) {\n        // Note that we clone the json object rather then setting it directly,\n        // this to cope with the fact that the user can click the cancel button and no changes should have happended\n        $scope.formProperties = angular.copy($scope.property.value.formProperties);\n        \n        for (var i = 0; i < $scope.formProperties.length; i++) {\n        \tvar formProperty = $scope.formProperties[i];\n        \tif (formProperty.enumValues && formProperty.enumValues.length > 0) {\n        \t\tfor (var j = 0; j < formProperty.enumValues.length; j++) {\n        \t\t\tvar enumValue = formProperty.enumValues[j];\n        \t\t\tif (!enumValue.id && !enumValue.name && enumValue.value) {\n        \t\t\t\tenumValue.id = enumValue.value;\n        \t\t\t\tenumValue.name = enumValue.value;\n        \t\t\t}\n        \t\t}\n        \t}\n        }\n        \n    } else {\n        $scope.formProperties = [];\n    }\n\n    // Array to contain selected properties (yes - we only can select one, but ng-grid isn't smart enough)\n    $scope.selectedProperties = [];\n    $scope.selectedEnumValues = [];\n    \n    $scope.translationsRetrieved = false;\n    \n    $scope.labels = {};\n    \n    var idPromise = $translate('PROPERTY.FORMPROPERTIES.ID');\n    var namePromise = $translate('PROPERTY.FORMPROPERTIES.NAME');\n    var typePromise = $translate('PROPERTY.FORMPROPERTIES.TYPE');\n    \n    $q.all([idPromise, namePromise, typePromise]).then(function(results) { \n    \t$scope.labels.idLabel = results[0];\n        $scope.labels.nameLabel = results[1];\n        $scope.labels.typeLabel = results[2];\n        $scope.translationsRetrieved = true;\n        \n    \t// Config for grid\n        $scope.gridOptions = {\n            data: 'formProperties',\n            enableRowReordering: true,\n            headerRowHeight: 28,\n            multiSelect: false,\n            keepLastSelected : false,\n            selectedItems: $scope.selectedProperties,\n            columnDefs: [{ field: 'id', displayName: $scope.labels.idLabel },\n                { field: 'name', displayName: $scope.labels.nameLabel},\n                { field: 'type', displayName: $scope.labels.typeLabel}]\n        };\n        \n        $scope.enumGridOptions = {\n    \t\tdata: 'selectedProperties[0].enumValues',\n            enableRowReordering: true,\n            headerRowHeight: 28,\n            multiSelect: false,\n            keepLastSelected : false,\n            selectedItems: $scope.selectedEnumValues,\n            columnDefs: [{ field: 'id', displayName: $scope.labels.idLabel },\n                { field: 'name', displayName: $scope.labels.nameLabel}]\n        }\n    });\n\n    // Handler for when the value of the type dropdown changes\n    $scope.propertyTypeChanged = function() {\n\n        // Check date. If date, show date pattern\n        if ($scope.selectedProperties[0].type === 'date') {\n            $scope.selectedProperties[0].datePattern = 'MM-dd-yyyy hh:mm';\n            \n        } else {\n            delete $scope.selectedProperties[0].datePattern;\n        }\n\n        // Check enum. If enum, show list of options\n        if ($scope.selectedProperties[0].type === 'enum') {\n            $scope.selectedProperties[0].enumValues = [ {id: 'value1', name: 'Value 1'}, {id: 'value2', name: 'Value 2'}];\n            \n        } else {\n            delete $scope.selectedProperties[0].enumValues;\n        }\n    };\n\n    // Click handler for add button\n    var propertyIndex = 1;\n    $scope.addNewProperty = function() {\n        $scope.formProperties.push({ id : 'new_property_' + propertyIndex++,\n            name : '',\n            type : 'string',\n            readable: true,\n            writable: true});\n        \n        $timeout(function(){\n        \t$scope.gridOptions.selectItem($scope.formProperties.length - 1, true);\n        });\n    };\n\n    // Click handler for remove button\n    $scope.removeProperty = function() {\n        if ($scope.selectedProperties.length > 0) {\n            var index = $scope.formProperties.indexOf($scope.selectedProperties[0]);\n            $scope.gridOptions.selectItem(index, false);\n            $scope.formProperties.splice(index, 1);\n\n            $scope.selectedProperties.length = 0;\n            if (index < $scope.formProperties.length) {\n                $scope.gridOptions.selectItem(index + 1, true);\n            } else if ($scope.formProperties.length > 0) {\n                $scope.gridOptions.selectItem(index - 1, true);\n            }\n        }\n    };\n\n    // Click handler for up button\n    $scope.movePropertyUp = function() {\n        if ($scope.selectedProperties.length > 0) {\n            var index = $scope.formProperties.indexOf($scope.selectedProperties[0]);\n            if (index != 0) { // If it's the first, no moving up of course\n                // Reason for funny way of swapping, see https://github.com/angular-ui/ng-grid/issues/272\n                var temp = $scope.formProperties[index];\n                $scope.formProperties.splice(index, 1);\n                $timeout(function(){\n                    $scope.formProperties.splice(index + -1, 0, temp);\n                }, 100);\n\n            }\n        }\n    };\n\n    // Click handler for down button\n    $scope.movePropertyDown = function() {\n        if ($scope.selectedProperties.length > 0) {\n            var index = $scope.formProperties.indexOf($scope.selectedProperties[0]);\n            if (index != $scope.formProperties.length - 1) { // If it's the last element, no moving down of course\n                // Reason for funny way of swapping, see https://github.com/angular-ui/ng-grid/issues/272\n                var temp = $scope.formProperties[index];\n                $scope.formProperties.splice(index, 1);\n                $timeout(function(){\n                    $scope.formProperties.splice(index + 1, 0, temp);\n                }, 100);\n\n            }\n        }\n    };\n    \n    $scope.addNewEnumValue = function() {\n    \tif ($scope.selectedProperties.length > 0) {\n\t        $scope.selectedProperties[0].enumValues.push({ id : '', name : ''});\n    \t}\n    \t\n    \t$timeout(function(){\n        \t$scope.enumGridOptions.selectItem($scope.selectedProperties[0].enumValues.length - 1, true);\n        });\n    };\n\n    // Click handler for remove button\n    $scope.removeEnumValue = function() {\n    \tif ($scope.selectedProperties.length > 0 && $scope.selectedEnumValues.length > 0) {\n            var index = $scope.selectedProperties[0].enumValues.indexOf($scope.selectedEnumValues[0]);\n            $scope.enumGridOptions.selectItem(index, false);\n            $scope.selectedProperties[0].enumValues.splice(index, 1);\n\n            $scope.selectedEnumValues.length = 0;\n            if (index < $scope.selectedProperties[0].enumValues.length) {\n            \t$timeout(function(){\n            \t\t$scope.enumGridOptions.selectItem(index + 1, true);\n            \t});\n            \t\n            } else if ($scope.selectedProperties[0].enumValues.length > 0) {\n            \t$timeout(function(){\n            \t\t$scope.enumGridOptions.selectItem(index - 1, true);\n            \t});\n            }\n        }\n    };\n\n    // Click handler for up button\n    $scope.moveEnumValueUp = function() {\n    \tif ($scope.selectedProperties.length > 0 && $scope.selectedEnumValues.length > 0) {\n    \t\tvar index = $scope.selectedProperties[0].enumValues.indexOf($scope.selectedEnumValues[0]);\n            if (index != 0) { // If it's the first, no moving up of course\n                // Reason for funny way of swapping, see https://github.com/angular-ui/ng-grid/issues/272\n                var temp = $scope.selectedProperties[0].enumValues[index];\n                $scope.selectedProperties[0].enumValues.splice(index, 1);\n                $timeout(function(){\n                    $scope.selectedProperties[0].enumValues.splice(index + -1, 0, temp);\n                });\n\n            }\n        }\n    };\n\n    // Click handler for down button\n    $scope.moveEnumValueDown = function() {\n    \tif ($scope.selectedProperties.length > 0 && $scope.selectedEnumValues.length > 0) {\n    \t\tvar index = $scope.selectedProperties[0].enumValues.indexOf($scope.selectedEnumValues[0]);\n            if (index != $scope.selectedProperties[0].enumValues.length - 1) { // If it's the last element, no moving down of course\n                // Reason for funny way of swapping, see https://github.com/angular-ui/ng-grid/issues/272\n                var temp = $scope.selectedProperties[0].enumValues[index];\n                $scope.selectedProperties[0].enumValues.splice(index, 1);\n                $timeout(function(){\n                    $scope.selectedProperties[0].enumValues.splice(index + 1, 0, temp);\n                });\n\n            }\n        }\n    };\n\n    // Click handler for save button\n    $scope.save = function() {\n\n        if ($scope.formProperties.length > 0) {\n            $scope.property.value = {};\n            $scope.property.value.formProperties = $scope.formProperties;\n        } else {\n            $scope.property.value = null;\n        }\n\n        $scope.updatePropertyInModel($scope.property);\n        $scope.close();\n    };\n\n    $scope.cancel = function() {\n    \t$scope.$hide();\n    \t$scope.property.mode = 'read';\n    };\n\n    // Close button handler\n    $scope.close = function() {\n    \t$scope.$hide();\n    \t$scope.property.mode = 'read';\n    };\n\n}];"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties-in-parameters-controller.js",
    "content": "/*\n * Activiti Modeler component part of the Activiti project\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * \n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n */\n\n/*\n * Input parameters for call activity\n */\n\nvar KisBpmInParametersCtrl = [ '$scope', '$modal', '$timeout', '$translate', function($scope, $modal, $timeout, $translate) {\n\n    // Config for the modal window\n    var opts = {\n        template:  'editor-app/configuration/properties/in-parameters-popup.html?version=' + Date.now(),\n        scope: $scope\n    };\n\n    // Open the dialog\n    $modal(opts);\n}];\n\nvar KisBpmInParametersPopupCtrl = ['$scope', '$q', '$translate', function($scope, $q, $translate) {\n\n    // Put json representing form properties on scope\n    if ($scope.property.value !== undefined && $scope.property.value !== null\n        && $scope.property.value.inParameters !== undefined\n        && $scope.property.value.inParameters !== null) {\n        // Note that we clone the json object rather then setting it directly,\n        // this to cope with the fact that the user can click the cancel button and no changes should have happened\n        $scope.parameters = angular.copy($scope.property.value.inParameters);\n    } else {\n        $scope.parameters = [];\n    }\n\n    // Array to contain selected properties (yes - we only can select one, but ng-grid isn't smart enough)\n    $scope.selectedParameters = [];\n    $scope.translationsRetrieved = false;\n    \n    $scope.labels = {};\n    \n    var sourcePromise = $translate('PROPERTY.PARAMETER.SOURCE');\n    var sourceExpressionPromise = $translate('PROPERTY.PARAMETER.SOURCEEXPRESSION');\n    var targetPromise = $translate('PROPERTY.PARAMETER.TARGET');\n    \n    $q.all([sourcePromise, sourceExpressionPromise, targetPromise]).then(function(results) { \n        $scope.labels.sourceLabel = results[0];\n        $scope.labels.sourceExpressionLabel = results[1];\n        $scope.labels.targetLabel = results[2];\n        $scope.translationsRetrieved = true;\n\n        // Config for grid\n        $scope.gridOptions = {\n            data: 'parameters',\n            enableRowReordering: true,\n            headerRowHeight: 28,\n            multiSelect: false,\n            keepLastSelected : false,\n            selectedItems: $scope.selectedParameters,\n            columnDefs: [{ field: 'source', displayName: $scope.labels.sourceLabel },\n                         { field: 'sourceExpression', displayName: $scope.labels.sourceExpressionLabel },\n                         { field: 'target', displayName: $scope.labels.targetLabel }]\n        };\n    });\n\n    // Click handler for add button\n    $scope.addNewParameter = function() {\n        $scope.parameters.push({ source : '',\n            sourceExpression : '',\n            target : ''});\n    };\n\n    // Click handler for remove button\n    $scope.removeParameter = function() {\n        if ($scope.selectedParameters.length > 0) {\n            var index = $scope.parameters.indexOf($scope.selectedParameters[0]);\n            $scope.gridOptions.selectItem(index, false);\n            $scope.parameters.splice(index, 1);\n\n            $scope.selectedParameters.length = 0;\n            if (index < $scope.parameters.length) {\n                $scope.gridOptions.selectItem(index + 1, true);\n            } else if ($scope.parameters.length > 0) {\n                $scope.gridOptions.selectItem(index - 1, true);\n            }\n        }\n    };\n\n    // Click handler for up button\n    $scope.moveParameterUp = function() {\n        if ($scope.selectedParameters.length > 0) {\n            var index = $scope.parameters.indexOf($scope.selectedParameters[0]);\n            if (index != 0) { // If it's the first, no moving up of course\n                // Reason for funny way of swapping, see https://github.com/angular-ui/ng-grid/issues/272\n                var temp = $scope.parameters[index];\n                $scope.parameters.splice(index, 1);\n                $timeout(function(){\n                    $scope.parameters.splice(index + -1, 0, temp);\n                }, 100);\n\n            }\n        }\n    };\n\n    // Click handler for down button\n    $scope.moveParameterDown = function() {\n        if ($scope.selectedParameters.length > 0) {\n            var index = $scope.parameters.indexOf($scope.selectedParameters[0]);\n            if (index != $scope.parameters.length - 1) { // If it's the last element, no moving down of course\n                // Reason for funny way of swapping, see https://github.com/angular-ui/ng-grid/issues/272\n                var temp = $scope.parameters[index];\n                $scope.parameters.splice(index, 1);\n                $timeout(function(){\n                    $scope.parameters.splice(index + 1, 0, temp);\n                }, 100);\n\n            }\n        }\n    };\n\n    // Click handler for save button\n    $scope.save = function() {\n\n        if ($scope.parameters.length > 0) {\n            $scope.property.value = {};\n            $scope.property.value.inParameters = $scope.parameters;\n        } else {\n            $scope.property.value = null;\n        }\n\n        $scope.updatePropertyInModel($scope.property);\n        $scope.close();\n    };\n\n    $scope.cancel = function() {\n        $scope.close();\n    };\n\n    // Close button handler\n    $scope.close = function() {\n        $scope.property.mode = 'read';\n        $scope.$hide();\n    };\n\n}];"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties-message-definitions-controller.js",
    "content": "/*\n * Activiti Modeler component part of the Activiti project\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * \n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n */\n\n/*\n * Execution listeners\n */\n\nangular.module('activitiModeler').controller('ActivitiMessageDefinitionsCtrl', ['$scope', '$modal', function ($scope, $modal) {\n\n    // Config for the modal window\n    var opts = {\n        template: 'editor-app/configuration/properties/message-definitions-popup.html?version=' + Date.now(),\n        scope: $scope\n    };\n\n    // Open the dialog\n    $modal(opts);\n}]);\n\n//Need a separate controller for the modal window due to https://github.com/angular-ui/bootstrap/issues/259\n// Will be fixed in a newer version of Angular UI\nangular.module('activitiModeler').controller('ActivitiMessageDefinitionsPopupCtrl',\n    ['$scope', '$q', '$translate', '$timeout', function ($scope, $q, $translate, $timeout) {\n\n        // Put json representing mesage definitions on scope\n        if ($scope.property.value !== undefined && $scope.property.value !== null && $scope.property.value.length > 0) {\n\n            if ($scope.property.value.constructor == String) {\n                $scope.messageDefinitions = JSON.parse($scope.property.value);\n            }\n            else {\n                // Note that we clone the json object rather then setting it directly,\n                // this to cope with the fact that the user can click the cancel button and no changes should have happened\n                $scope.messageDefinitions = angular.copy($scope.property.value);\n            }\n\n        } else {\n            $scope.messageDefinitions = [];\n        }\n\n        // Array to contain selected mesage definitions (yes - we only can select one, but ng-grid isn't smart enough)\n        $scope.selectedMessages = [];\n        $scope.translationsRetrieved = false;\n\n        $scope.labels = {};\n\n        var idPromise = $translate('PROPERTY.MESSAGEDEFINITIONS.ID');\n        var namePromise = $translate('PROPERTY.MESSAGEDEFINITIONS.NAME');\n\n        $q.all([idPromise, namePromise]).then(function (results) {\n\n            $scope.labels.idLabel = results[0];\n            $scope.labels.nameLabel = results[1];\n            $scope.translationsRetrieved = true;\n\n         // Config for grid\n            $scope.gridOptions = {\n                data: 'messageDefinitions',\n                headerRowHeight: 28,\n                enableRowSelection: true,\n                enableRowHeaderSelection: false,\n                multiSelect: false,\n                keepLastSelected : false,\n                selectedItems: $scope.selectedMessages,\n                columnDefs: [\n                    {field: 'id', displayName: $scope.labels.idLabel},\n                    {field: 'name', displayName: $scope.labels.nameLabel}]\n            };\n        });\n\n        // Click handler for add button\n        $scope.addNewMessageDefinition = function () {\n            var newMessageDefinition = {id: '', name: ''};\n\n            $scope.messageDefinitions.push(newMessageDefinition);\n            $timeout(function () {\n            \t$scope.gridOptions.selectItem($scope.messageDefinitions.length - 1, true);\n            });\n        };\n\n        // Click handler for remove button\n        $scope.removeMessageDefinition = function () {\n        \tif ($scope.selectedMessages && $scope.selectedMessages.length > 0) {\n            \tvar index = $scope.messageDefinitions.indexOf($scope.selectedMessages[0]);\n                $scope.gridOptions.selectItem(index, false);\n                $scope.messageDefinitions.splice(index, 1);\n\n                $scope.selectedMessages.length = 0;\n                if (index < $scope.messageDefinitions.length) {\n                    $scope.gridOptions.selectItem(index + 1, true);\n                } else if ($scope.messageDefinitions.length > 0) {\n                    $scope.gridOptions.selectItem(index - 1, true);\n                }\n            }\n        };\n\n        // Click handler for save button\n        $scope.save = function () {\n\n            if ($scope.messageDefinitions.length > 0) {\n                $scope.property.value = $scope.messageDefinitions;\n            } else {\n                $scope.property.value = null;\n            }\n\n            $scope.updatePropertyInModel($scope.property);\n            $scope.close();\n        };\n\n        $scope.cancel = function () {\n            $scope.property.mode = 'read';\n            $scope.$hide();\n        };\n\n        // Close button handler\n        $scope.close = function () {\n            $scope.property.mode = 'read';\n            $scope.$hide();\n        };\n\n    }]);"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties-message-scope-controller.js",
    "content": "/*\n * Activiti Modeler component part of the Activiti project\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * \n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n */\n\nangular.module('activitiModeler').controller('ActivitiMessageRefCtrl', [ '$scope', function($scope) {\n\n    // Find the parent shape on which the message definitions are defined\n    var messageDefinitionsProperty = undefined;\n    var parent = $scope.selectedShape;\n    while (parent !== null && parent !== undefined && messageDefinitionsProperty === undefined) {\n        if (parent.properties && parent.properties['oryx-messagedefinitions']) {\n            messageDefinitionsProperty = parent.properties['oryx-messagedefinitions'];\n        } else {\n            parent = parent.parent;\n        }\n    }\n\n    try {\n        messageDefinitionsProperty = JSON.parse(messageDefinitionsProperty);\n        if (typeof messageDefinitionsProperty == 'string') {\n            messageDefinitionsProperty = JSON.parse(messageDefinitionsProperty);\n        }\n    } catch (err) {\n        // Do nothing here, just to be sure we try-catch it\n    }\n\n    $scope.messageDefinitions = messageDefinitionsProperty;\n\n\n    $scope.messageChanged = function() {\n    \t$scope.updatePropertyInModel($scope.property);\n    };\n}]);"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties-multiinstance-controller.js",
    "content": "/*\n * Activiti Modeler component part of the Activiti project\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * \n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n */\n\n/*\n * Execution listeners\n */\n\nvar KisBpmMultiInstanceCtrl = [ '$scope', function($scope) {\n\n    if ($scope.property.value == undefined && $scope.property.value == null)\n    {\n    \t$scope.property.value = 'None';\n    }\n        \n    $scope.multiInstanceChanged = function() {\n    \t$scope.updatePropertyInModel($scope.property);\n    };\n}];"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties-out-parameters-controller.js",
    "content": "/*\n * Activiti Modeler component part of the Activiti project\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * \n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n */\n\n/*\n * Input parameters for call activity\n */\n\nvar KisBpmOutParametersCtrl = [ '$scope' , '$modal', '$timeout', '$translate', function($scope, $modal, $timeout, $translate) {\n\n    // Config for the modal window\n    var opts = {\n        template:  'editor-app/configuration/properties/out-parameters-popup.html?version=' + Date.now(),\n        scope: $scope\n    };\n\n    // Open the dialog\n    $modal(opts);\n}];\n\nvar KisBpmOutParametersPopupCtrl = [ '$scope', '$q', '$translate', function($scope, $q, $translate) {\n\n    // Put json representing form properties on scope\n    if ($scope.property.value !== undefined && $scope.property.value !== null\n        && $scope.property.value.outParameters !== undefined\n        && $scope.property.value.outParameters !== null) {\n        // Note that we clone the json object rather then setting it directly,\n        // this to cope with the fact that the user can click the cancel button and no changes should have happened\n        $scope.parameters = angular.copy($scope.property.value.outParameters);\n    } else {\n        $scope.parameters = [];\n    }\n\n    // Array to contain selected properties (yes - we only can select one, but ng-grid isn't smart enough)\n    $scope.selectedParameters = [];\n    $scope.translationsRetrieved = false;\n    \n    $scope.labels = {};\n    \n    var sourcePromise = $translate('PROPERTY.PARAMETER.SOURCE');\n    var sourceExpressionPromise = $translate('PROPERTY.PARAMETER.SOURCEEXPRESSION');\n    var targetPromise = $translate('PROPERTY.PARAMETER.TARGET');\n    \n    $q.all([sourcePromise, sourceExpressionPromise, targetPromise]).then(function(results) { \n        $scope.labels.sourceLabel = results[0];\n        $scope.labels.sourceExpressionLabel = results[1];\n        $scope.labels.targetLabel = results[2];\n        $scope.translationsRetrieved = true;\n        \n        // Config for grid\n        $scope.gridOptions = {\n            data: 'parameters',\n            enableRowReordering: true,\n            headerRowHeight: 28,\n            multiSelect: false,\n            keepLastSelected : false,\n            selectedItems: $scope.selectedParameters,\n            columnDefs: [{ field: 'source', displayName: $scope.labels.sourceLabel },\n                         { field: 'sourceExpression', displayName: $scope.labels.sourceExpressionLabel },\n                         { field: 'target', displayName: $scope.labels.targetLabel }]\n        };\n    });\n\n    // Click handler for add button\n    $scope.addNewParameter = function() {\n        $scope.parameters.push({ source : '',\n            sourceExpression : '',\n            target : ''});\n    };\n\n    // Click handler for remove button\n    $scope.removeParameter = function() {\n        if ($scope.selectedParameters.length > 0) {\n            var index = $scope.parameters.indexOf($scope.selectedParameters[0]);\n            $scope.gridOptions.selectItem(index, false);\n            $scope.parameters.splice(index, 1);\n\n            $scope.selectedParameters.length = 0;\n            if (index < $scope.parameters.length) {\n                $scope.gridOptions.selectItem(index + 1, true);\n            } else if ($scope.parameters.length > 0) {\n                $scope.gridOptions.selectItem(index - 1, true);\n            }\n        }\n    };\n\n    // Click handler for up button\n    $scope.moveParameterUp = function() {\n        if ($scope.selectedParameters.length > 0) {\n            var index = $scope.parameters.indexOf($scope.selectedParameters[0]);\n            if (index != 0) { // If it's the first, no moving up of course\n                // Reason for funny way of swapping, see https://github.com/angular-ui/ng-grid/issues/272\n                var temp = $scope.parameters[index];\n                $scope.parameters.splice(index, 1);\n                $timeout(function(){\n                    $scope.parameters.splice(index + -1, 0, temp);\n                }, 100);\n\n            }\n        }\n    };\n\n    // Click handler for down button\n    $scope.moveParameterDown = function() {\n        if ($scope.selectedParameters.length > 0) {\n            var index = $scope.parameters.indexOf($scope.selectedParameters[0]);\n            if (index != $scope.parameters.length - 1) { // If it's the last element, no moving down of course\n                // Reason for funny way of swapping, see https://github.com/angular-ui/ng-grid/issues/272\n                var temp = $scope.parameters[index];\n                $scope.parameters.splice(index, 1);\n                $timeout(function(){\n                    $scope.parameters.splice(index + 1, 0, temp);\n                }, 100);\n\n            }\n        }\n    };\n\n    // Click handler for save button\n    $scope.save = function() {\n\n        if ($scope.parameters.length > 0) {\n            $scope.property.value = {};\n            $scope.property.value.outParameters = $scope.parameters;\n        } else {\n            $scope.property.value = null;\n        }\n\n        $scope.updatePropertyInModel($scope.property);\n        $scope.close();\n    };\n\n    $scope.cancel = function() {\n        $scope.close();\n    };\n\n    // Close button handler\n    $scope.close = function() {\n        $scope.property.mode = 'read';\n        $scope.$hide();\n    };\n\n}];"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties-sequenceflow-order-controller.js",
    "content": "/*\n * Activiti Modeler component part of the Activiti project\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * \n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n */\n\n/*\n * Sequence flow order controller\n */\n\nvar KisBpmSequenceFlowOrderCtrl = [ '$scope', '$modal', '$timeout', '$translate', function($scope, $modal, $timeout, $translate) {\n\n    // Config for the modal window\n    var opts = {\n        template:  'editor-app/configuration/properties/sequenceflow-order-popup.html?version=' + Date.now(),\n        scope: $scope\n    };\n\n    $modal(opts);\n}];\n\nvar KisBpmSequenceFlowOrderPopupCtrl = ['$scope', '$translate', function($scope, $translate) {\n\n    // Find the outgoing sequence flow of the current selected shape\n    var outgoingSequenceFlow = [];\n    var selectedShape = $scope.selectedShape;\n    if (selectedShape) {\n        var outgoingNodes = selectedShape.getOutgoingShapes();\n        for (var i=0; i<outgoingNodes.length; i++) {\n            if (outgoingNodes[i].getStencil().title() === 'Sequence flow') {\n                var targetActivity = outgoingNodes[i].getTarget();\n                // We need the resourceId of a sequence flow, not the id because that will change with every editor load\n                outgoingSequenceFlow.push({\n                    id : outgoingNodes[i].resourceId,\n                    targetTitle : targetActivity.properties['oryx-name'],\n                    targetType : targetActivity.getStencil().title()\n                });\n            }\n        }\n    } else {\n        console.log('Programmatic error: no selected shape found');\n    }\n\n    // Now we can apply the order which was (possibly) previously saved\n    var orderedOutgoingSequenceFlow = [];\n    if ($scope.property.value && $scope.property.value.sequenceFlowOrder) {\n\n        var sequenceFlowOrderList = $scope.property.value.sequenceFlowOrder;\n\n        // Loop the list of sequence flow that was saved  in the json model and match them with the outgoing sequence flow found above\n        for (var flowIndex=0; flowIndex < sequenceFlowOrderList.length; flowIndex++) {\n\n            // find the sequence flow in the outgoing sequence flows.\n\n            for (var outgoingFlowIndex=0; outgoingFlowIndex < outgoingSequenceFlow.length; outgoingFlowIndex++) {\n                if (outgoingSequenceFlow[outgoingFlowIndex].id === sequenceFlowOrderList[flowIndex]) {\n                    orderedOutgoingSequenceFlow.push(outgoingSequenceFlow[outgoingFlowIndex]);\n                    outgoingSequenceFlow.splice(outgoingFlowIndex, 1);\n                    break;\n                }\n            }\n        }\n\n        // Now all the matching sequence flow we're removed from the outgoing sequence flow list\n        // We can simply apply the remaining ones (these are new vs. the time when the values were saved to the model)\n        orderedOutgoingSequenceFlow = orderedOutgoingSequenceFlow.concat(outgoingSequenceFlow);\n\n    } else {\n        orderedOutgoingSequenceFlow = outgoingSequenceFlow;\n    }\n\n    // Now we can put it on the scope\n    $scope.outgoingSequenceFlow = orderedOutgoingSequenceFlow;\n\n    // Move up click handler\n    $scope.moveUp = function(index) {\n        var temp = $scope.outgoingSequenceFlow[index];\n        $scope.outgoingSequenceFlow[index] = $scope.outgoingSequenceFlow[index - 1];\n        $scope.outgoingSequenceFlow[index - 1] = temp;\n    };\n\n    // Move down click handler\n    $scope.moveDown = function(index) {\n        var temp = $scope.outgoingSequenceFlow[index];\n        $scope.outgoingSequenceFlow[index] = $scope.outgoingSequenceFlow[index + 1];\n        $scope.outgoingSequenceFlow[index + 1] = temp;\n    };\n\n    // Save click handler\n    $scope.save = function() {\n        if ($scope.outgoingSequenceFlow.length > 0) {\n            $scope.property.value = {};\n            $scope.property.value.sequenceFlowOrder = [];\n\n            for (var flowIndex=0; flowIndex < $scope.outgoingSequenceFlow.length; flowIndex++) {\n                $scope.property.value.sequenceFlowOrder.push($scope.outgoingSequenceFlow[flowIndex].id);\n            }\n        } else {\n            $scope.property.value = null;\n        }\n\n        $scope.updatePropertyInModel($scope.property);\n        $scope.close();\n    };\n\n    // Cancel click handler\n    $scope.cancel = function() {\n        $scope.close();\n    };\n\n    // Close button handler\n    $scope.close = function() {\n        $scope.property.mode = 'read';\n        $scope.$hide();\n    };\n\n}];"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties-signal-definitions-controller.js",
    "content": "/*\n * Activiti Modeler component part of the Activiti project\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * \n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n */\n\nangular.module('activitiModeler').controller('ActivitiSignalDefinitionsCtrl', ['$scope', '$modal', function ($scope, $modal) {\n\n    // Config for the modal window\n    var opts = {\n        template: 'editor-app/configuration/properties/signal-definitions-popup.html?version=' + Date.now(),\n        scope: $scope\n    };\n\n    // Open the dialog\n    $modal(opts);\n}]);\n\n//Need a separate controller for the modal window due to https://github.com/angular-ui/bootstrap/issues/259\n// Will be fixed in a newer version of Angular UI\nangular.module('activitiModeler').controller('ActivitiSignalDefinitionsPopupCtrl',\n    ['$scope', '$q', '$translate', '$timeout', function ($scope, $q, $translate, $timeout) {\n\n        // Put json representing signal definitions on scope\n        if ($scope.property.value !== undefined && $scope.property.value !== null && $scope.property.value.length > 0) {\n\n            if ($scope.property.value.constructor == String) {\n                $scope.signalDefinitions = JSON.parse($scope.property.value);\n            }\n            else {\n                // Note that we clone the json object rather then setting it directly,\n                // this to cope with the fact that the user can click the cancel button and no changes should have happened\n                $scope.signalDefinitions = angular.copy($scope.property.value);\n            }\n\n        } else {\n            $scope.signalDefinitions = [];\n        }\n\n        // Array to contain selected signal definitions (yes - we only can select one, but ng-grid isn't smart enough)\n        $scope.selectedSignals = [];\n        $scope.translationsRetrieved = false;\n\n        $scope.labels = {};\n\n        var idPromise = $translate('PROPERTY.SIGNALDEFINITIONS.ID');\n        var namePromise = $translate('PROPERTY.SIGNALDEFINITIONS.NAME');\n        var scopePromise = $translate('PROPERTY.SIGNALDEFINITIONS.SCOPE');\n\n        $q.all([idPromise, namePromise, scopePromise]).then(function (results) {\n\n            $scope.labels.idLabel = results[0];\n            $scope.labels.nameLabel = results[1];\n            $scope.labels.scopeLabel = results[2];\n            $scope.translationsRetrieved = true;\n\n            // Config for grid\n            $scope.gridOptions = {\n                data: 'signalDefinitions',\n                headerRowHeight: 28,\n                enableRowSelection: true,\n                enableRowHeaderSelection: false,\n                multiSelect: false,\n                keepLastSelected : false,\n                selectedItems: $scope.selectedSignals,\n                columnDefs: [\n                    {field: 'id', displayName: $scope.labels.idLabel},\n                    {field: 'name', displayName: $scope.labels.nameLabel},\n                    {field: 'scope', displayName: $scope.labels.scopeLabel}]\n            };\n        });\n\n        // Click handler for add button\n        $scope.addNewSignalDefinition = function () {\n            var newSignalDefinition = {id: '', name: '', scope: 'global'};\n\n            $scope.signalDefinitions.push(newSignalDefinition);\n            $timeout(function () {\n            \t$scope.gridOptions.selectItem($scope.signalDefinitions.length - 1, true);\n            });\n        };\n\n        // Click handler for remove button\n        $scope.removeSignalDefinition = function () {\n            if ($scope.selectedSignals && $scope.selectedSignals.length > 0) {\n            \tvar index = $scope.signalDefinitions.indexOf($scope.selectedSignals[0]);\n                $scope.gridOptions.selectItem(index, false);\n                $scope.signalDefinitions.splice(index, 1);\n\n                $scope.selectedSignals.length = 0;\n                if (index < $scope.signalDefinitions.length) {\n                    $scope.gridOptions.selectItem(index + 1, true);\n                } else if ($scope.signalDefinitions.length > 0) {\n                    $scope.gridOptions.selectItem(index - 1, true);\n                }\n            }\n        };\n\n        // Click handler for save button\n        $scope.save = function () {\n\n            if ($scope.signalDefinitions.length > 0) {\n                $scope.property.value = $scope.signalDefinitions;\n            } else {\n                $scope.property.value = null;\n            }\n\n            $scope.updatePropertyInModel($scope.property);\n            $scope.close();\n        };\n\n        $scope.cancel = function () {\n            $scope.property.mode = 'read';\n            $scope.$hide();\n        };\n\n        // Close button handler\n        $scope.close = function () {\n            $scope.property.mode = 'read';\n            $scope.$hide();\n        };\n\n    }]);"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties-signal-scope-controller.js",
    "content": "/*\n * Activiti Modeler component part of the Activiti project\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * \n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n */\nangular.module('activitiModeler').controller('ActivitiSignalRefCtrl', [ '$scope', function($scope) {\n\n    // Find the parent shape on which the signal definitions are defined\n    var signalDefinitionsProperty = undefined;\n    var parent = $scope.selectedShape;\n    while (parent !== null && parent !== undefined && signalDefinitionsProperty === undefined) {\n        if (parent.properties && parent.properties['oryx-signaldefinitions']) {\n            signalDefinitionsProperty = parent.properties['oryx-signaldefinitions'];\n        } else {\n            parent = parent.parent;\n        }\n    }\n\n    try {\n        signalDefinitionsProperty = JSON.parse(signalDefinitionsProperty);\n        if (typeof signalDefinitionsProperty == 'string') {\n            signalDefinitionsProperty = JSON.parse(signalDefinitionsProperty);\n        }\n    } catch (err) {\n        // Do nothing here, just to be sure we try-catch it\n    }\n\n    $scope.signalDefinitions = signalDefinitionsProperty;\n\n\n    $scope.signalChanged = function() {\n    \t$scope.updatePropertyInModel($scope.property);\n    };\n}]);"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties-task-listeners-controller.js",
    "content": "/*\n * Activiti Modeler component part of the Activiti project\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * \n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n */\n\n/*\n * Task listeners\n */\n\nvar KisBpmTaskListenersCtrl = [ '$scope', '$modal', '$timeout', '$translate', function($scope, $modal, $timeout, $translate) {\n\n    // Config for the modal window\n    var opts = {\n        template:  'editor-app/configuration/properties/task-listeners-popup.html?version=' + Date.now(),\n        scope: $scope\n    };\n\n    // Open the dialog\n    $modal(opts);\n}];\n\nvar KisBpmTaskListenersPopupCtrl = [ '$scope', '$q', '$translate', function($scope, $q, $translate) {\n\n    // Put json representing form properties on scope\n    if ($scope.property.value !== undefined && $scope.property.value !== null\n        && $scope.property.value.taskListeners !== undefined\n        && $scope.property.value.taskListeners !== null) {\n        \n        if ($scope.property.value.taskListeners.constructor == String)\n        {\n            $scope.taskListeners = JSON.parse($scope.property.value.taskListeners);\n        }\n        else\n        {\n            // Note that we clone the json object rather then setting it directly,\n            // this to cope with the fact that the user can click the cancel button and no changes should have happened\n            $scope.taskListeners = angular.copy($scope.property.value.taskListeners);\n        }\n        \n        for (var i = 0; i < $scope.taskListeners.length; i++)\n        {\n            var taskListener = $scope.taskListeners[i];\n            if (taskListener.className !== undefined && taskListener.className !== '')\n            {\n                taskListener.implementation = taskListener.className;\n            }\n            else if (taskListener.expression !== undefined && taskListener.expression !== '')\n            {\n                taskListener.implementation = taskListener.expression;\n            }\n            else if (taskListener.delegateExpression !== undefined && taskListener.delegateExpression !== '')\n            {\n                taskListener.implementation = taskListener.delegateExpression;\n            }\n        }\n    } else {\n        $scope.taskListeners = [];\n    }\n\n    // Array to contain selected properties (yes - we only can select one, but ng-grid isn't smart enough)\n    $scope.selectedListeners = [];\n    $scope.selectedFields = [];\n    $scope.translationsRetrieved = false;\n    \n    $scope.labels = {};\n    \n    var eventPromise = $translate('PROPERTY.TASKLISTENERS.EVENT');\n    var implementationPromise = $translate('PROPERTY.TASKLISTENERS.FIELDS.IMPLEMENTATION');\n    var namePromise = $translate('PROPERTY.TASKLISTENERS.FIELDS.NAME');\n    \n    $q.all([eventPromise, implementationPromise, namePromise]).then(function(results) { \n        $scope.labels.eventLabel = results[0];\n        $scope.labels.implementationLabel = results[1];\n        $scope.labels.nameLabel = results[2];\n        $scope.translationsRetrieved = true;\n\n        // Config for grid\n        $scope.gridOptions = {\n            data: 'taskListeners',\n            enableRowReordering: true,\n            headerRowHeight: 28,\n            multiSelect: false,\n            keepLastSelected : false,\n            selectedItems: $scope.selectedListeners,\n            afterSelectionChange: function (rowItem, event) {\n                $scope.selectedFields.length = 0;\n                if ($scope.selectedListeners.length > 0)\n                {\n                    var fields = $scope.selectedListeners[0].fields;\n                    if (fields !== undefined && fields !== null)\n                    {\n                        for (var i = 0; i < fields.length; i++)\n                        {\n                            var field = fields[i];\n                            if (field.stringValue !== undefined && field.stringValue !== '')\n                            {\n                                field.implementation = field.stringValue;\n                            }\n                            else if (field.expression !== undefined && field.expression !== '')\n                            {\n                                field.implementation = field.expression;\n                            }\n                            else if (field.string !== undefined && field.string !== '')\n                            {\n                                field.implementation = field.string;\n                            }\n                        }\n                    }\n                }\n            },\n            columnDefs: [{ field: 'event', displayName: $scope.labels.eventLabel },\n                { field: 'implementation', displayName: $scope.labels.implementationLabel}]\n        };\n        \n        // Config for field grid\n        $scope.gridFieldOptions = {\n            data: 'selectedListeners[0].fields',\n            enableRowReordering: true,\n            headerRowHeight: 28,\n            multiSelect: false,\n            keepLastSelected : false,\n            selectedItems: $scope.selectedFields,\n            columnDefs: [{ field: 'name', displayName: $scope.labels.name },\n                { field: 'implementation', displayName: $scope.labels.implementationLabel}]\n        };\n    });\n    \n    $scope.listenerDetailsChanged = function() {\n        if ($scope.selectedListeners[0].className !== '')\n        {\n            $scope.selectedListeners[0].implementation = $scope.selectedListeners[0].className;\n        }\n        else if ($scope.selectedListeners[0].expression !== '')\n        {\n            $scope.selectedListeners[0].implementation = $scope.selectedListeners[0].expression;\n        }\n        else if ($scope.selectedListeners[0].delegateExpression !== '')\n        {\n            $scope.selectedListeners[0].implementation = $scope.selectedListeners[0].delegateExpression;\n        }\n        else\n        {\n            $scope.selectedListeners[0].implementation = '';\n        }\n    };\n\n    // Click handler for add button\n    $scope.addNewListener = function() {\n        $scope.taskListeners.push({ event : 'create',\n            implementation : '',\n            className : '',\n            expression: '',\n            delegateExpression: ''});\n    };\n\n    // Click handler for remove button\n    $scope.removeListener = function() {\n        if ($scope.selectedListeners.length > 0) {\n            var index = $scope.taskListeners.indexOf($scope.selectedListeners[0]);\n            $scope.gridOptions.selectItem(index, false);\n            $scope.taskListeners.splice(index, 1);\n\n            $scope.selectedListeners.length = 0;\n            if (index < $scope.taskListeners.length) {\n                $scope.gridOptions.selectItem(index + 1, true);\n            } else if ($scope.taskListeners.length > 0) {\n                $scope.gridOptions.selectItem(index - 1, true);\n            }\n        }\n    };\n\n    // Click handler for up button\n    $scope.moveListenerUp = function() {\n        if ($scope.selectedListeners.length > 0) {\n            var index = $scope.taskListeners.indexOf($scope.selectedListeners[0]);\n            if (index != 0) { // If it's the first, no moving up of course\n                // Reason for funny way of swapping, see https://github.com/angular-ui/ng-grid/issues/272\n                var temp = $scope.taskListeners[index];\n                $scope.taskListeners.splice(index, 1);\n                $timeout(function(){\n                    $scope.taskListeners.splice(index + -1, 0, temp);\n                }, 100);\n\n            }\n        }\n    };\n\n    // Click handler for down button\n    $scope.moveListenerDown = function() {\n        if ($scope.selectedListeners.length > 0) {\n            var index = $scope.taskListeners.indexOf($scope.selectedListeners[0]);\n            if (index != $scope.taskListeners.length - 1) { // If it's the last element, no moving down of course\n                // Reason for funny way of swapping, see https://github.com/angular-ui/ng-grid/issues/272\n                var temp = $scope.taskListeners[index];\n                $scope.taskListeners.splice(index, 1);\n                $timeout(function(){\n                    $scope.taskListeners.splice(index + 1, 0, temp);\n                }, 100);\n\n            }\n        }\n    };\n    \n    $scope.fieldDetailsChanged = function() {\n        if ($scope.selectedFields[0].stringValue != '')\n        {\n            $scope.selectedFields[0].implementation = $scope.selectedFields[0].stringValue;\n        }\n        else if ($scope.selectedFields[0].expression != '')\n        {\n            $scope.selectedFields[0].implementation = $scope.selectedFields[0].expression;\n        }\n        else if ($scope.selectedFields[0].string != '')\n        {\n            $scope.selectedFields[0].implementation = $scope.selectedFields[0].string;\n        }\n        else\n        {\n            $scope.selectedFields[0].implementation = '';\n        }\n    };\n\n    // Click handler for add button\n    $scope.addNewField = function() {\n        if ($scope.selectedListeners.length > 0)\n        {\n            if ($scope.selectedListeners[0].fields == undefined)\n            {\n                $scope.selectedListeners[0].fields = [];\n            }\n            $scope.selectedListeners[0].fields.push({ name : 'fieldName',\n                implementation : '',\n                stringValue : '',\n                expression: '',\n                string: ''});\n        }\n    };\n\n    // Click handler for remove button\n    $scope.removeField = function() {\n        if ($scope.selectedFields.length > 0) {\n            var index = $scope.selectedListeners[0].fields.indexOf($scope.selectedFields[0]);\n            $scope.gridFieldOptions.selectItem(index, false);\n            $scope.selectedListeners[0].fields.splice(index, 1);\n\n            $scope.selectedFields.length = 0;\n            if (index < $scope.selectedListeners[0].fields.length) {\n                $scope.gridFieldOptions.selectItem(index + 1, true);\n            } else if ($scope.selectedListeners[0].fields.length > 0) {\n                $scope.gridFieldOptions.selectItem(index - 1, true);\n            }\n        }\n    };\n\n    // Click handler for up button\n    $scope.moveFieldUp = function() {\n        if ($scope.selectedFields.length > 0) {\n            var index = $scope.selectedListeners[0].fields.indexOf($scope.selectedFields[0]);\n            if (index != 0) { // If it's the first, no moving up of course\n                // Reason for funny way of swapping, see https://github.com/angular-ui/ng-grid/issues/272\n                var temp = $scope.selectedListeners[0].fields[index];\n                $scope.selectedListeners[0].fields.splice(index, 1);\n                $timeout(function(){\n                    $scope.selectedListeners[0].fields.splice(index + -1, 0, temp);\n                }, 100);\n\n            }\n        }\n    };\n\n    // Click handler for down button\n    $scope.moveFieldDown = function() {\n        if ($scope.selectedFields.length > 0) {\n            var index = $scope.selectedListeners[0].fields.indexOf($scope.selectedFields[0]);\n            if (index != $scope.selectedListeners[0].fields.length - 1) { // If it's the last element, no moving down of course\n                // Reason for funny way of swapping, see https://github.com/angular-ui/ng-grid/issues/272\n                var temp = $scope.selectedListeners[0].fields[index];\n                $scope.selectedListeners[0].fields.splice(index, 1);\n                $timeout(function(){\n                    $scope.selectedListeners[0].fields.splice(index + 1, 0, temp);\n                }, 100);\n\n            }\n        }\n    };\n\n    // Click handler for save button\n    $scope.save = function() {\n\n        if ($scope.taskListeners.length > 0) {\n            $scope.property.value = {};\n            $scope.property.value.taskListeners = $scope.taskListeners;\n        } else {\n            $scope.property.value = null;\n        }\n\n        $scope.updatePropertyInModel($scope.property);\n        $scope.close();\n    };\n\n    $scope.cancel = function() {\n        $scope.close();\n    };\n\n    // Close button handler\n    $scope.close = function() {\n        $scope.property.mode = 'read';\n        $scope.$hide();\n    };\n\n}];"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/properties.js",
    "content": "/*\n * Activiti Modeler component part of the Activiti project\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * \n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n */\n'use strict';\n\nvar KISBPM = KISBPM || {};\nKISBPM.PROPERTY_CONFIG =\n{\n    \"string\": {\n        \"readModeTemplateUrl\": \"editor-app/configuration/properties/default-value-display-template.html\",\n        \"writeModeTemplateUrl\": \"editor-app/configuration/properties/string-property-write-mode-template.html\"\n    },\n    \"boolean\": {\n        \"templateUrl\": \"editor-app/configuration/properties/boolean-property-template.html\"\n    },\n    \"text\" : {\n        \"readModeTemplateUrl\": \"editor-app/configuration/properties/default-value-display-template.html\",\n        \"writeModeTemplateUrl\": \"editor-app/configuration/properties/text-property-write-template.html\"\n    },\n    \"kisbpm-multiinstance\" : {\n        \"readModeTemplateUrl\": \"editor-app/configuration/properties/default-value-display-template.html\",\n        \"writeModeTemplateUrl\": \"editor-app/configuration/properties/multiinstance-property-write-template.html\"\n    },\n    \"oryx-formproperties-complex\": {\n        \"readModeTemplateUrl\": \"editor-app/configuration/properties/form-properties-display-template.html\",\n        \"writeModeTemplateUrl\": \"editor-app/configuration/properties/form-properties-write-template.html\"\n    },\n    \"oryx-executionlisteners-multiplecomplex\": {\n        \"readModeTemplateUrl\": \"editor-app/configuration/properties/execution-listeners-display-template.html\",\n        \"writeModeTemplateUrl\": \"editor-app/configuration/properties/execution-listeners-write-template.html\"\n    },\n    \"oryx-tasklisteners-multiplecomplex\": {\n        \"readModeTemplateUrl\": \"editor-app/configuration/properties/task-listeners-display-template.html\",\n        \"writeModeTemplateUrl\": \"editor-app/configuration/properties/task-listeners-write-template.html\"\n    },\n    \"oryx-eventlisteners-multiplecomplex\": {\n        \"readModeTemplateUrl\": \"editor-app/configuration/properties/event-listeners-display-template.html\",\n        \"writeModeTemplateUrl\": \"editor-app/configuration/properties/event-listeners-write-template.html\"\n    },\n    \"oryx-usertaskassignment-complex\": {\n        \"readModeTemplateUrl\": \"editor-app/configuration/properties/assignment-display-template.html\",\n        \"writeModeTemplateUrl\": \"editor-app/configuration/properties/assignment-write-template.html\"\n    },\n    \"oryx-servicetaskfields-complex\": {\n        \"readModeTemplateUrl\": \"editor-app/configuration/properties/fields-display-template.html\",\n        \"writeModeTemplateUrl\": \"editor-app/configuration/properties/fields-write-template.html\"\n    },\n    \"oryx-callactivityinparameters-complex\": {\n        \"readModeTemplateUrl\": \"editor-app/configuration/properties/in-parameters-display-template.html\",\n        \"writeModeTemplateUrl\": \"editor-app/configuration/properties/in-parameters-write-template.html\"\n    },\n    \"oryx-callactivityoutparameters-complex\": {\n        \"readModeTemplateUrl\": \"editor-app/configuration/properties/out-parameters-display-template.html\",\n        \"writeModeTemplateUrl\": \"editor-app/configuration/properties/out-parameters-write-template.html\"\n    },\n    \"oryx-subprocessreference-complex\": {\n        \"readModeTemplateUrl\": \"editor-app/configuration/properties/subprocess-reference-display-template.html\",\n        \"writeModeTemplateUrl\": \"editor-app/configuration/properties/subprocess-reference-write-template.html\"\n    },\n    \"oryx-sequencefloworder-complex\" : {\n        \"readModeTemplateUrl\": \"editor-app/configuration/properties/sequenceflow-order-display-template.html\",\n        \"writeModeTemplateUrl\": \"editor-app/configuration/properties/sequenceflow-order-write-template.html\"\n    },\n    \"oryx-conditionsequenceflow-complex\" : {\n        \"readModeTemplateUrl\": \"editor-app/configuration/properties/condition-expression-display-template.html\",\n        \"writeModeTemplateUrl\": \"editor-app/configuration/properties/condition-expression-write-template.html\"\n    },\n    \"oryx-signaldefinitions-multiplecomplex\" : {\n        \"readModeTemplateUrl\": \"editor-app/configuration/properties/signal-definitions-display-template.html\",\n        \"writeModeTemplateUrl\": \"editor-app/configuration/properties/signal-definitions-write-template.html\"\n    },\n    \"oryx-signalref-string\" : {\n        \"readModeTemplateUrl\": \"editor-app/configuration/properties/default-value-display-template.html\",\n        \"writeModeTemplateUrl\": \"editor-app/configuration/properties/signal-property-write-template.html\"\n    },\n    \"oryx-messagedefinitions-multiplecomplex\" : {\n        \"readModeTemplateUrl\": \"editor-app/configuration/properties/message-definitions-display-template.html\",\n        \"writeModeTemplateUrl\": \"editor-app/configuration/properties/message-definitions-write-template.html\"\n    },\n    \"oryx-messageref-string\" : {\n        \"readModeTemplateUrl\": \"editor-app/configuration/properties/default-value-display-template.html\",\n        \"writeModeTemplateUrl\": \"editor-app/configuration/properties/message-property-write-template.html\"\n    }\n};\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/toolbar-custom-actions.js",
    "content": "/*\n * Activiti Modeler component part of the Activiti project\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * \n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n */\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/toolbar-default-actions.js",
    "content": "/*\n * Activiti Modeler component part of the Activiti project\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * \n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n */\n'use strict';\n\nvar KISBPM = KISBPM || {};\nKISBPM.TOOLBAR = {\n    ACTIONS: {\n\n        saveModel: function (services) {\n\n            var modal = services.$modal({\n                backdrop: true,\n                keyboard: true,\n                template: 'editor-app/popups/save-model.html?version=' + Date.now(),\n                scope: services.$scope\n            });\n        },\n\n        undo: function (services) {\n\n            // Get the last commands\n            var lastCommands = services.$scope.undoStack.pop();\n\n            if (lastCommands) {\n                // Add the commands to the redo stack\n                services.$scope.redoStack.push(lastCommands);\n\n                // Force refresh of selection, might be that the undo command\n                // impacts properties in the selected item\n                if (services.$rootScope && services.$rootScope.forceSelectionRefresh) \n                {\n                \tservices.$rootScope.forceSelectionRefresh = true;\n                }\n                \n                // Rollback every command\n                for (var i = lastCommands.length - 1; i >= 0; --i) {\n                    lastCommands[i].rollback();\n                }\n                \n                // Update and refresh the canvas\n                services.$scope.editor.handleEvents({\n                    type: ORYX.CONFIG.EVENT_UNDO_ROLLBACK,\n                    commands: lastCommands\n                });\n                \n                // Update\n                services.$scope.editor.getCanvas().update();\n                services.$scope.editor.updateSelection();\n            }\n            \n            var toggleUndo = false;\n            if (services.$scope.undoStack.length == 0)\n            {\n            \ttoggleUndo = true;\n            }\n            \n            var toggleRedo = false;\n            if (services.$scope.redoStack.length > 0)\n            {\n            \ttoggleRedo = true;\n            }\n\n            if (toggleUndo || toggleRedo) {\n                for (var i = 0; i < services.$scope.items.length; i++) {\n                    var item = services.$scope.items[i];\n                    if (toggleUndo && item.action === 'KISBPM.TOOLBAR.ACTIONS.undo') {\n                        services.$scope.safeApply(function () {\n                            item.enabled = false;\n                        });\n                    }\n                    else if (toggleRedo && item.action === 'KISBPM.TOOLBAR.ACTIONS.redo') {\n                        services.$scope.safeApply(function () {\n                            item.enabled = true;\n                        });\n                    }\n                }\n            }\n        },\n\n        redo: function (services) {\n\n            // Get the last commands from the redo stack\n            var lastCommands = services.$scope.redoStack.pop();\n\n            if (lastCommands) {\n                // Add this commands to the undo stack\n                services.$scope.undoStack.push(lastCommands);\n                \n                // Force refresh of selection, might be that the redo command\n                // impacts properties in the selected item\n                if (services.$rootScope && services.$rootScope.forceSelectionRefresh) \n                {\n                \tservices.$rootScope.forceSelectionRefresh = true;\n                }\n\n                // Execute those commands\n                lastCommands.each(function (command) {\n                    command.execute();\n                });\n\n                // Update and refresh the canvas\n                services.$scope.editor.handleEvents({\n                    type: ORYX.CONFIG.EVENT_UNDO_EXECUTE,\n                    commands: lastCommands\n                });\n\n                // Update\n                services.$scope.editor.getCanvas().update();\n                services.$scope.editor.updateSelection();\n            }\n\n            var toggleUndo = false;\n            if (services.$scope.undoStack.length > 0) {\n                toggleUndo = true;\n            }\n\n            var toggleRedo = false;\n            if (services.$scope.redoStack.length == 0) {\n                toggleRedo = true;\n            }\n\n            if (toggleUndo || toggleRedo) {\n                for (var i = 0; i < services.$scope.items.length; i++) {\n                    var item = services.$scope.items[i];\n                    if (toggleUndo && item.action === 'KISBPM.TOOLBAR.ACTIONS.undo') {\n                        services.$scope.safeApply(function () {\n                            item.enabled = true;\n                        });\n                    }\n                    else if (toggleRedo && item.action === 'KISBPM.TOOLBAR.ACTIONS.redo') {\n                        services.$scope.safeApply(function () {\n                            item.enabled = false;\n                        });\n                    }\n                }\n            }\n        },\n\n        cut: function (services) {\n            KISBPM.TOOLBAR.ACTIONS._getOryxEditPlugin(services.$scope).editCut();\n            for (var i = 0; i < services.$scope.items.length; i++) {\n                var item = services.$scope.items[i];\n                if (item.action === 'KISBPM.TOOLBAR.ACTIONS.paste') {\n                    services.$scope.safeApply(function () {\n                        item.enabled = true;\n                    });\n                }\n            }\n        },\n\n        copy: function (services) {\n            KISBPM.TOOLBAR.ACTIONS._getOryxEditPlugin(services.$scope).editCopy();\n            for (var i = 0; i < services.$scope.items.length; i++) {\n                var item = services.$scope.items[i];\n                if (item.action === 'KISBPM.TOOLBAR.ACTIONS.paste') {\n                    services.$scope.safeApply(function () {\n                        item.enabled = true;\n                    });\n                }\n            }\n        },\n\n        paste: function (services) {\n            KISBPM.TOOLBAR.ACTIONS._getOryxEditPlugin(services.$scope).editPaste();\n        },\n\n        deleteItem: function (services) {\n            KISBPM.TOOLBAR.ACTIONS._getOryxEditPlugin(services.$scope).editDelete();\n        },\n\n        addBendPoint: function (services) {\n\n            var dockerPlugin = KISBPM.TOOLBAR.ACTIONS._getOryxDockerPlugin(services.$scope);\n\n            var enableAdd = !dockerPlugin.enabledAdd();\n            dockerPlugin.setEnableAdd(enableAdd);\n            if (enableAdd)\n            {\n            \tdockerPlugin.setEnableRemove(false);\n            \tdocument.body.style.cursor = 'pointer';\n            }\n            else\n            {\n            \tdocument.body.style.cursor = 'default';\n            }\n        },\n\n        removeBendPoint: function (services) {\n\n            var dockerPlugin = KISBPM.TOOLBAR.ACTIONS._getOryxDockerPlugin(services.$scope);\n\n            var enableRemove = !dockerPlugin.enabledRemove();\n            dockerPlugin.setEnableRemove(enableRemove);\n            if (enableRemove)\n            {\n            \tdockerPlugin.setEnableAdd(false);\n            \tdocument.body.style.cursor = 'pointer';\n            }\n            else\n            {\n            \tdocument.body.style.cursor = 'default';\n            }\n        },\n\n        /**\n         * Helper method: fetches the Oryx Edit plugin from the provided scope,\n         * if not on the scope, it is created and put on the scope for further use.\n         *\n         * It's important to reuse the same EditPlugin while the same scope is active,\n         * as the clipboard is stored for the whole lifetime of the scope.\n         */\n        _getOryxEditPlugin: function ($scope) {\n            if ($scope.oryxEditPlugin === undefined || $scope.oryxEditPlugin === null) {\n                $scope.oryxEditPlugin = new ORYX.Plugins.Edit($scope.editor);\n            }\n            return $scope.oryxEditPlugin;\n        },\n\n        zoomIn: function (services) {\n            KISBPM.TOOLBAR.ACTIONS._getOryxViewPlugin(services.$scope).zoom([1.0 + ORYX.CONFIG.ZOOM_OFFSET]);\n        },\n\n        zoomOut: function (services) {\n            KISBPM.TOOLBAR.ACTIONS._getOryxViewPlugin(services.$scope).zoom([1.0 - ORYX.CONFIG.ZOOM_OFFSET]);\n        },\n        \n        zoomActual: function (services) {\n            KISBPM.TOOLBAR.ACTIONS._getOryxViewPlugin(services.$scope).setAFixZoomLevel(1);\n        },\n        \n        zoomFit: function (services) {\n        \tKISBPM.TOOLBAR.ACTIONS._getOryxViewPlugin(services.$scope).zoomFitToModel();\n        },\n        \n        alignVertical: function (services) {\n        \tKISBPM.TOOLBAR.ACTIONS._getOryxArrangmentPlugin(services.$scope).alignShapes([ORYX.CONFIG.EDITOR_ALIGN_MIDDLE]);\n        },\n        \n        alignHorizontal: function (services) {\n        \tKISBPM.TOOLBAR.ACTIONS._getOryxArrangmentPlugin(services.$scope).alignShapes([ORYX.CONFIG.EDITOR_ALIGN_CENTER]);\n        },\n        \n        sameSize: function (services) {\n        \tKISBPM.TOOLBAR.ACTIONS._getOryxArrangmentPlugin(services.$scope).alignShapes([ORYX.CONFIG.EDITOR_ALIGN_SIZE]);\n        },\n        \n        closeEditor: function(services) {\n          var index = parent.layer.getFrameIndex(window.name);\n          parent.layer.close(index);\n        },\n        \n        /**\n         * Helper method: fetches the Oryx View plugin from the provided scope,\n         * if not on the scope, it is created and put on the scope for further use.\n         */\n        _getOryxViewPlugin: function ($scope) {\n            if ($scope.oryxViewPlugin === undefined || $scope.oryxViewPlugin === null) {\n                $scope.oryxViewPlugin = new ORYX.Plugins.View($scope.editor);\n            }\n            return $scope.oryxViewPlugin;\n        },\n        \n        _getOryxArrangmentPlugin: function ($scope) {\n            if ($scope.oryxArrangmentPlugin === undefined || $scope.oryxArrangmentPlugin === null) {\n                $scope.oryxArrangmentPlugin = new ORYX.Plugins.Arrangement($scope.editor);\n            }\n            return $scope.oryxArrangmentPlugin;\n        },\n\n        _getOryxDockerPlugin: function ($scope) {\n            if ($scope.oryxDockerPlugin === undefined || $scope.oryxDockerPlugin === null) {\n                $scope.oryxDockerPlugin = new ORYX.Plugins.AddDocker($scope.editor);\n            }\n            return $scope.oryxDockerPlugin;\n        }\n    }\n};\n\n/** Custom controller for the save dialog */\nvar SaveModelCtrl = [ '$rootScope', '$scope', '$http', '$route', '$location',\n    function ($rootScope, $scope, $http, $route, $location) {\n\n    var modelMetaData = $scope.editor.getModelMetaData();\n\n    var description = '';\n    if (modelMetaData.description) {\n    \tdescription = modelMetaData.description;\n    }\n    \n    var saveDialog = { 'name' : modelMetaData.name,\n            'description' : description};\n    \n    $scope.saveDialog = saveDialog;\n    \n    var json = $scope.editor.getJSON();\n    json = JSON.stringify(json);\n\n    var params = {\n        modeltype: modelMetaData.model.modelType,\n        json_xml: json,\n        name: 'model'\n    };\n\n    $scope.status = {\n        loading: false\n    };\n\n    $scope.close = function () {\n    \t$scope.$hide();\n    };\n\n    $scope.saveAndClose = function () {\n    \t$scope.save(function() {\n        var index = parent.layer.getFrameIndex(window.name);\n        parent.layer.close(index);\n    \t});\n    };\n    $scope.save = function (successCallback) {\n\n        if (!$scope.saveDialog.name || $scope.saveDialog.name.length == 0) {\n            return;\n        }\n\n        // Indicator spinner image\n        $scope.status = {\n        \tloading: true\n        };\n        \n        modelMetaData.name = $scope.saveDialog.name;\n        modelMetaData.description = $scope.saveDialog.description;\n\n        var json = $scope.editor.getJSON();\n        json = JSON.stringify(json);\n        \n        var selection = $scope.editor.getSelection();\n        $scope.editor.setSelection([]);\n        \n        // Get the serialized svg image source\n        var svgClone = $scope.editor.getCanvas().getSVGRepresentation(true);\n        $scope.editor.setSelection(selection);\n        if ($scope.editor.getCanvas().properties[\"oryx-showstripableelements\"] === false) {\n            var stripOutArray = jQuery(svgClone).find(\".stripable-element\");\n            for (var i = stripOutArray.length - 1; i >= 0; i--) {\n            \tstripOutArray[i].remove();\n            }\n        }\n\n        // Remove all forced stripable elements\n        var stripOutArray = jQuery(svgClone).find(\".stripable-element-force\");\n        for (var i = stripOutArray.length - 1; i >= 0; i--) {\n            stripOutArray[i].remove();\n        }\n\n        // Parse dom to string\n        var svgDOM = DataManager.serialize(svgClone);\n\n        var params = {\n            json_xml: json,\n            svg_xml: svgDOM,\n            name: $scope.saveDialog.name,\n            description: $scope.saveDialog.description\n        };\n        console.info('json_xml:'+json);\n        // Update\n        $http({    method: 'POST',\n            data:params,\n            ignoreErrors: true,\n            headers: {'Accept': 'application/json',\n                      'Content-Type': 'application/x-www-form-urlencoded'},\n        ransformRequest: function (obj) {\n                var str = [];\n                for (var p in obj) {\n                    str.push(encodeURIComponent(p) + \"=\" + encodeURIComponent(obj[p]));\n                }\n                return str.join(\"&\");\n            },\n          url: KISBPM.URL.putModel(modelMetaData.modelId)})\n\n            .success(function (data, status, headers, config) {\n                $scope.editor.handleEvents({\n                    type: ORYX.CONFIG.EVENT_SAVED\n                });\n                $scope.modelData.name = $scope.saveDialog.name;\n                $scope.modelData.lastUpdated = data.lastUpdated;\n                \n                $scope.status.loading = false;\n                $scope.$hide();\n\n                // Fire event to all who is listening\n                var saveEvent = {\n                    type: KISBPM.eventBus.EVENT_TYPE_MODEL_SAVED,\n                    model: params,\n                    modelId: modelMetaData.modelId,\n\t\t            eventType: 'update-model'\n                };\n                KISBPM.eventBus.dispatch(KISBPM.eventBus.EVENT_TYPE_MODEL_SAVED, saveEvent);\n\n                // Reset state\n                $scope.error = undefined;\n                $scope.status.loading = false;\n\n                // Execute any callback\n                if (successCallback) {\n                    successCallback();\n                }\n\n            })\n            .error(function (data, status, headers, config) {\n                $scope.error = {};\n                console.log('Something went wrong when updating the process model:' + JSON.stringify(data));\n                $scope.status.loading = false;\n            });\n    };\n\n}];"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/toolbar.js",
    "content": "/*\n * Activiti Modeler component part of the Activiti project\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * \n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n */\n'use strict';\n\nvar KISBPM = KISBPM || {};\nKISBPM.TOOLBAR_CONFIG = {\n    \"items\" : [\n        {\n            \"type\" : \"button\",\n            \"title\" : \"TOOLBAR.ACTION.SAVE\",\n            \"cssClass\" : \"editor-icon editor-icon-save\",\n            \"action\" : \"KISBPM.TOOLBAR.ACTIONS.saveModel\"\n        },\n        {\n            \"type\" : \"separator\",\n            \"title\" : \"\",\n            \"cssClass\" : \"toolbar-separator\"\n        },\n        {\n            \"type\" : \"button\",\n            \"title\" : \"TOOLBAR.ACTION.CUT\",\n            \"cssClass\" : \"editor-icon editor-icon-cut\",\n            \"action\" : \"KISBPM.TOOLBAR.ACTIONS.cut\",\n            \"enabled\" : false,\n            \"enabledAction\" : \"element\"\n        },\n        {\n            \"type\" : \"button\",\n            \"title\" : \"TOOLBAR.ACTION.COPY\",\n            \"cssClass\" : \"editor-icon editor-icon-copy\",\n            \"action\" : \"KISBPM.TOOLBAR.ACTIONS.copy\",\n            \"enabled\" : false,\n            \"enabledAction\" : \"element\"\n        },\n        {\n            \"type\" : \"button\",\n            \"title\" : \"TOOLBAR.ACTION.PASTE\",\n            \"cssClass\" : \"editor-icon editor-icon-paste\",\n            \"action\" : \"KISBPM.TOOLBAR.ACTIONS.paste\",\n            \"enabled\" : false\n        },\n        {\n            \"type\" : \"button\",\n            \"title\" : \"TOOLBAR.ACTION.DELETE\",\n            \"cssClass\" : \"editor-icon editor-icon-delete\",\n            \"action\" : \"KISBPM.TOOLBAR.ACTIONS.deleteItem\",\n            \"enabled\" : false,\n            \"enabledAction\" : \"element\"\n        },\n        {\n            \"type\" : \"separator\",\n            \"title\" : \"TOOLBAR.ACTION.SAVE\",\n            \"cssClass\" : \"toolbar-separator\"\n        },\n        {\n            \"type\" : \"button\",\n            \"title\" : \"TOOLBAR.ACTION.REDO\",\n            \"cssClass\" : \"editor-icon editor-icon-redo\",\n            \"action\" : \"KISBPM.TOOLBAR.ACTIONS.redo\",\n            \"enabled\" : false\n        },\n        {\n            \"type\" : \"button\",\n            \"title\" : \"TOOLBAR.ACTION.UNDO\",\n            \"cssClass\" : \"editor-icon editor-icon-undo\",\n            \"action\" : \"KISBPM.TOOLBAR.ACTIONS.undo\",\n            \"enabled\" : false\n        },\n        {\n            \"type\" : \"separator\",\n            \"title\" : \"TOOLBAR.ACTION.SAVE\",\n            \"cssClass\" : \"toolbar-separator\"\n        },\n        {\n            \"type\" : \"button\",\n            \"title\" : \"TOOLBAR.ACTION.ALIGNVERTICAL\",\n            \"cssClass\" : \"editor-icon editor-icon-align-vertical\",\n            \"action\" : \"KISBPM.TOOLBAR.ACTIONS.alignVertical\",\n            \"enabled\" : false,\n            \"enabledAction\" : \"element\",\n            \"minSelectionCount\" : 2\n        },\n        {\n            \"type\" : \"button\",\n            \"title\" : \"TOOLBAR.ACTION.ALIGNHORIZONTAL\",\n            \"cssClass\" : \"editor-icon editor-icon-align-horizontal\",\n            \"action\" : \"KISBPM.TOOLBAR.ACTIONS.alignHorizontal\",\n            \"enabledAction\" : \"element\",\n            \"enabled\" : false,\n            \"minSelectionCount\" : 2\n        },\n        {\n            \"type\" : \"button\",\n            \"title\" : \"TOOLBAR.ACTION.SAMESIZE\",\n            \"cssClass\" : \"editor-icon editor-icon-same-size\",\n            \"action\" : \"KISBPM.TOOLBAR.ACTIONS.sameSize\",\n            \"enabledAction\" : \"element\",\n            \"enabled\" : false,\n            \"minSelectionCount\" : 2\n        },\n        {\n        \t\"type\" : \"separator\",\n        \t\"title\" : \"TOOLBAR.ACTION.SAVE\",\n        \t\"cssClass\" : \"toolbar-separator\"\n        },\n        {\n            \"type\" : \"button\",\n            \"title\" : \"TOOLBAR.ACTION.ZOOMIN\",\n            \"cssClass\" : \"editor-icon editor-icon-zoom-in\",\n            \"action\" : \"KISBPM.TOOLBAR.ACTIONS.zoomIn\"\n        },\n        {\n            \"type\" : \"button\",\n            \"title\" : \"TOOLBAR.ACTION.ZOOMOUT\",\n            \"cssClass\" : \"editor-icon editor-icon-zoom-out\",\n            \"action\" : \"KISBPM.TOOLBAR.ACTIONS.zoomOut\"\n        },\n        {\n            \"type\" : \"button\",\n            \"title\" : \"TOOLBAR.ACTION.ZOOMACTUAL\",\n            \"cssClass\" : \"editor-icon editor-icon-zoom-actual\",\n            \"action\" : \"KISBPM.TOOLBAR.ACTIONS.zoomActual\"\n        },\n        {\n            \"type\" : \"button\",\n            \"title\" : \"TOOLBAR.ACTION.ZOOMFIT\",\n            \"cssClass\" : \"editor-icon editor-icon-zoom-fit\",\n            \"action\" : \"KISBPM.TOOLBAR.ACTIONS.zoomFit\"\n        },\n        {\n            \"type\" : \"separator\",\n            \"title\" : \"TOOLBAR.ACTION.SAVE\",\n            \"cssClass\" : \"toolbar-separator\"\n        },\n    \t{\n            \"type\" : \"button\",\n            \"title\" : \"TOOLBAR.ACTION.BENDPOINT.ADD\",\n            \"cssClass\" : \"editor-icon editor-icon-bendpoint-add\",\n            \"action\" : \"KISBPM.TOOLBAR.ACTIONS.addBendPoint\",\n            \"id\" : \"add-bendpoint-button\"\n    \t},\n    \t{\n    \t    \"type\" : \"button\",\n    \t    \"title\" : \"TOOLBAR.ACTION.BENDPOINT.REMOVE\",\n    \t    \"cssClass\" : \"editor-icon editor-icon-bendpoint-remove\",\n    \t    \"action\" : \"KISBPM.TOOLBAR.ACTIONS.removeBendPoint\",\n    \t    \"id\" : \"remove-bendpoint-button\"\n    \t}\n    ],\n    \n    \"secondaryItems\" : [\n\t\t{\n\t\t    \"type\" : \"button\",\n\t\t    \"title\" : \"Close\",\n\t\t    \"cssClass\" : \"editor-icon editor-icon-close\",\n\t\t    \"action\" : \"KISBPM.TOOLBAR.ACTIONS.closeEditor\"\n\t\t}\n    ]\n};"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/configuration/url-config.js",
    "content": "/*\n * Activiti Modeler component part of the Activiti project\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * \n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n */\nvar KISBPM = KISBPM || {};\n\nKISBPM.URL = {\n\n    getModel: function(modelId) {\n        return ACTIVITI.CONFIG.contextRoot + '/model/' + modelId + '/json'+\"?access_token=\"+localStorage.getItem(\"token\");\n    },\n\n    getStencilSet: function() {\n        return ACTIVITI.CONFIG.contextRoot + '/editor/stencilset?version=' + Date.now()+\"&access_token=\"+localStorage.getItem(\"token\");\n    },\n\n    putModel: function(modelId) {\n        return ACTIVITI.CONFIG.contextRoot + '/model/' + modelId + '/save'+\"?access_token=\"+localStorage.getItem(\"token\");\n    }\n};"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/css/style-common.css",
    "content": "/**\n Colors:\n\n  - Header: #333333\n  - Subheader: #e8edf1\n  - Subheader border: #a4acb9\n  - Highlight buttons/text: #36a7c4\n  - Text color: #1a1a1a\n  - Filter color: #373e48\n  - Dark highlight: #606b7d\n*/\n\n.form-control {\n    -webkit-border-radius: 0;\n    -moz-border-radius: 0;\n    border-radius: 0;\n    padding: 4px 8px;\n}\n\nbody {\n    font-family: 'Lato', sans-serif;\n}\n\n.label {\n    font-size: 18px;\n    font-weight: normal;\n    margin-bottom: 0;\n    color: #1a1a1a;\n}\n\n.subtle {\n    color: #999999;\n    font-size: 13px;\n}\n\n\n.simple-list {\n    list-style: none inside;\n    padding: 0;\n    margin: 5px 0;\n}\n\n.simple-list.pack {\n    max-height: 250px;\n    overflow: auto;\n}\n\n.simple-list li {\n    padding: 6px;\n    position: relative;\n}\n\n.simple-list li > .icon {\n    padding-right: 5px;\n}\n\n.simple-list li:hover {\n    background-color:  #f8f8f9;\n}\n\n.simple-list li.nothing-to-see:hover {\n    background-color:  transparent;\n}\n\n.simple-list li.active {\n    background-color:  #eeeeee;\n}\n\n.simple-list li >.actions {\n    visibility: hidden;\n    position: absolute;\n    top: 3px;\n    right: 5px;\n    font-size: 20px;\n    background-color: #f8f8f9;\n    padding: 0 0 0 4px;\n}\n\n.simple-list li >.actions a {\n     padding: 4px 4px 0 4px;\n }\n\n.simple-list li >.actions a:hover {\n    background-color: #ffffff;\n}\n\n.simple-list li:hover >.actions {\n    visibility: visible;\n}\n\n.simple-list.grid li {\n    border-bottom: 1px solid #eeeeee;\n}\n\n.simple-list.grid li:first-child {\n    border-top: 1px solid #eeeeee;\n}\n\n.simple-list li .subtle {\n    color: #999999;\n    font-size: 13px;\n}\n\n.simple-list.selectable li {\n    cursor: pointer;\n}\n\n.simple-list .loading {\n    position: absolute;\n    left: 50%;\n    margin-left: -15px;\n    line-height: 30px;\n    top: 8px;\n    z-index: 1030;\n}\n\n\n.lt-ie9 .container {\n    display: none !important;\n    visibility: hidden !important;\n}\n\n.unsupported-browser {\n    margin: 60px 20px 20px 20px;\n}\n\na {\n    cursor: pointer;\n}\n\na:hover {\n    text-decoration: none;\n}\n\nlabel {\n    font-weight: normal;\n    color: #636363;\n    font-size: 14px;\n}\n\n[ng\\:cloak], [ng-cloak], .ng-cloak { display: none; }\n\n.nothing-to-see {\n    padding: 5px 0 20px 0;\n    cursor: default;\n}\n\n.nothing-to-see span {\n    font-size: 14px;\n    color: #aaaaaa;\n}\n\n.fixed-container {\n    max-width: 1400px;\n    min-width: 1000px;\n    margin: 0 auto;\n}\n\n.well {\n    -moz-border-radius: 0;\n    -webkit-border-radius: 0;\n    border-radius: 0;\n}\n\n/** Buttons **/\nbutton.btn, a.btn {\n    background-color: #36a7c4;\n    color: #ffffff;\n    border-color: #ffffff;\n    font-size: 15px;\n}\n\nbutton.btn-subtle, a.btn-subtle {\n    background-color: #fafafb;\n    color: #1a1a1a;\n    font-size: 15px;\n}\n\n.btn-xs {\n    padding: 1px 8px;\n}\n\nbutton.btn.btn-danger {\n    background-color: #d35f5f;\n}\n\n.btn.btn-danger:hover, .btn.btn-danger.active, .btn.btn-danger:focus {\n    background-color: #c83737;\n}\n\n.btn:hover, .btn.active, .btn:focus {\n    background-color: #2a8198;\n    border-color: #ffffff;\n    color: #ffffff;\n}\n\n.btn.disabled, .btn[disabled], .btn[disabled]:active, .btn[disabled]:hover {\n    background-color: #668b94;\n    border-color: #668b94;\n    color: #ffffff;\n}\n\n.btn-subtle:hover, .btn-subtle.active, .btn-subtle:focus {\n    background-color: #f6f6f7;\n    border-color: #ffffff;\n    color: #000000;\n}\n\n.btn-subtle[disabled] {\n    background-color: #f6f6f7;\n    color: #555555;\n}\n\n.modal-header .btn, .header .btn {\n    border-color: #e8edf1;\n}\n\n.content {\n    padding: 0 10px;\n    overflow: auto;\n}\n\n.content.split {\n    background: transparent url('../../images/line-1px.png') repeat-y 60% 0;\n}\n\n.content .split-left {\n    float: left;\n    width: 60%;\n    padding: 0 10px 0 5px;\n}\n\n.content .split-right {\n    float: right;\n    width: 40%;\n    padding: 0 0 0 15px;\n}\n\n\n.form-group .pull-right {\n    margin: 10px 0 0 5px;\n}\n\n.form-group.box {\n    padding-bottom: 10px;\n    margin-bottom: 5px;\n    border-bottom: 1px dotted #eeeeee;\n}\n\n.form-group .marker {\n    font-size: 15px;\n    color: #666666;\n}\n\n/** Dropdowns and dropdown triggers */\n\n.dropdown-menu {\n    -webkit-border-radius: 0px;\n    -moz-border-radius: 0px;\n    border-radius: 0px;\n    box-shadow: none;\n}\n\n.dropdown-menu:focus {\n    outline: none;\n}\n\n.dropdown-menu > li > a:hover, .dropdown-menu > ul > li > a:hover {\n    background: #36a7c4;\n    color: #ffffff;\n}\n\n\n.dropdown-menu > li.active > a, .dropdown-menu > li.active > a:hover {\n    background: #e8edf1;\n    color: #1a1a1a;\n}\n\n.dropdown-menu > ul > li > a {\n    display: block;\n    text-decoration: none;\n    color: #1a1a1a;\n    padding: 5px;\n    cursor: pointer;\n}\n\n.dropdown-menu > ul {\n    padding: 10px;\n}\n\n.dropdown-menu.large-width {\n    min-width: 300px;\n}\n\na.dropdown-toggle {\n    color: #1a1a1a;\n    text-decoration: none;\n}\n\n.open a.dropdown-toggle, a.dropdown-toggle:hover {\n    color: #36a7c4;\n}\n\n.btn-group.open .dropdown-toggle {\n    -moz-box-shadow: none;\n    -webkit-box-shadow: none;\n    box-shadow: none;\n}\n\n/** Subtle dropdown (eg. sort) */\n\n.dropdown-subtle {\n\tmargin-right: 5px;\n\tcolor: #606b7d;\n}\n\n.dropdown-subtle .btn {\n\tbackground: transparent;\n\tline-height: 36px;\n\tcolor: #606b7d;\n\tpadding: 0;\n\tfont-size: 14px;\n\tborder: none;\n\tbox-shadow: none;\n\t-webkit-box-shadow: none;\n\t-moz-box-shadow: none;\n}\n\n.dropdown-subtle .btn-group.open .dropdown-toggle {\n\tbox-shadow: none;\n\t-webkit-box-shadow: none;\n\t-moz-box-shadow: none;\n}\n\n.dropdown-subtle .btn:hover, .dropdown-subtle .btn:focus {\n\tbackground: transparent;\n\tcolor: #333333;\n}\n\n.dropdown-subtle a {\n\tcursor: pointer;\n}\n\n/** Popovers */\n.popover {\n    -moz-border-radius: 0;\n    -webkit-border-radius: 0;\n    border-radius: 0;\n    max-width: 400px;\n    min-width: 300px;\n    padding: 0px;\n}\n\n.popover.bottom-left, .popover.bottom-right {\n    margin-top: 10px;\n}\n .popover>.arrow, .popover>.arrow {\n    margin-left: -11px;\n    border-top-width: 0;\n    border-bottom-color: #999;\n    border-bottom-color: rgba(0,0,0,.25);\n    top: -11px;\n\n}\n\n.popover.bottom-left>.arrow {\n    left: 40px;\n}\n\n.popover.bottom-right>.arrow {\n    right: 40px;\n}\n\n.popover.bottom-left>.arrow:after, .popover.bottom-right>.arrow:after, .popover.bottom>.arrow:after {\n    content: \" \";\n    top: 1px;\n    margin-left: -10px;\n    border-top-width: 0;\n    border-bottom-color: #e8edf1;\n}\n\n.popover-wrapper {\n    padding: 10px;\n}\n\n.popover-header {\n    position: relative;\n    background-color: #e8edf1;\n    min-height: 30px;\n    font-size: 18px;\n    color: #a4acb9;\n    padding: 10px 0;\n}\n\n.popover-footer {\n    overflow: hidden;\n    clear: both;\n    padding: 5px 10px 10px 10px;\n}\n\n.popover-header .actions {\n    position: absolute;\n    top: 6px;\n    right: 5px;\n    font-size: 12px;\n}\n\n.popover-header .actions a{\n    display: inline-block;\n    padding: 8px 5px;\n}\n\n.popover-header span {\n    padding: 0 10px;\n}\n\n.popover-wrapper .form-group {\n    margin-bottom: 10px;\n}\n\n.popover.wide {\n    max-width: 1000px;\n    min-width: 1000px;\n}\n\n.popover.wide .popover-wrapper {\n    max-height: 400px;\n    overflow: auto;\n}\n\n.popover.medium {\n    max-width: 600px;\n    min-width: 250px;\n}\n\n.popover .section {\n    border-top: 1px solid #eeeeee;\n}\n\n.center {\n    text-align: center;\n}\n\n.popover .center .btn, .popover .center .btn-group > .btn:hover, .popover .center .btn-group > .btn:focus {\n    border-color: #ffffff;\n}\n\n/* Navigation */\n\n.navbar {\n    background-color: #333333;\n    border: none;\n    min-height: 40px;\n}\n\n\n.navbar .btn-group .btn-default {\n    border: none;\n    color: #ffffff;\n    background-color: transparent;\n    padding-top: 0px;\n    padding-bottom: 0px;\n    line-height: 40px;\n    -webkit-border-radius: 0px;\n    -moz-border-radius: 0px;\n    border-radius: 0px;\n    font-size: 13px;\n}\n\n.navbar .btn-group .btn-default:hover, .navbar .btn-group .btn-default:focus {\n    background-color: #121212;\n}\n\n.navbar .btn-group .btn-default {\n    border: none;\n    color: #ffffff;\n    background-color: transparent;\n}\n\n.navbar .btn-group .btn-icon {\n    font-size: 22px;\n}\n\n\n.navbar-header .navbar-brand {\n    padding-top: 0px;\n    line-height: 40px;\n    height: 40px;\n    /*background: url(../images/logo.png) no-repeat 10px center;*/\n    width: 220px;\n    font-weight:800;\n}\n\n\n.navbar-nav {\n    height: 40px;\n}\n\n.navbar-nav > li > a {\n    line-height: 20px;\n    padding: 10px;\n    font-size: 17px;\n    padding: 10px 35px 10px 35px;\n    color: #ffffff;\n}\n\n.navbar-nav > li.active:after {\n    top: 100%;\n    left: 50%;\n    border: solid transparent;\n    content: \" \";\n    height: 0;\n    width: 0;\n    position: absolute;\n    pointer-events: none;\n    border-color: rgba(0, 0, 0, 0);\n    border-top-color: #000000;\n    border-width: 6px;\n    margin-left: -6px;\n}\n\n.navbar-nav > li.active {\n    background-color: #000000;\n    position: relative;\n}\n\n\n.navbar-nav > li.active > a {\n    color: #36a7c4;\n}\n\n/* Sub header */\n.subheader {\n    background-color: #e8edf1;\n    min-height: 60px;\n    border-bottom: 1px solid #a4acb9;\n}\n\n.subheader > div > .btn-group {\n    margin: 12px 15px 0px 0px;\n}\n\n.subheader h2 {\n    font-family: 'Lato', sans-serif;\n    color: #1a1a1a;\n    font-size: 20px;\n    font-weight: normal;\n    padding: 19px 0px 5px 10px;\n    margin-top: 0px;\n}\n\n.subheader  .version {\n    font-weight: bold;\n    color: #36a7c4;\n    font-size: 110%;\n    padding-left: 5px;\n    line-height: 1;\n    padding-right: 5px;\n    border-right: 1px solid #a4acb9;\n    margin-right: 5px;\n}\n.subheader .btn {\n    border-color: #e8edf1;\n}\n\n.subheader a.btn:hover, .subheader a.btn:focus  {\n    border-color: #e8edf1;\n    color: #ffffff;\n}\n\n.subheader .dropdown-menu .detail {\n    vertical-align:middle;\n    color: #1a1a1a;\n}\n\n.subheader p {\n    font-size: 14px;\n    color: #1a1a1a;\n    word-wrap:break-word;\n}\n\n.subheader p.hint a {\n    cursor: pointer;\n    color: #1a1a1a;\n}\n\n.subheader .details.subheader .details {\n    margin-bottom: 5px;\n    margin-left: -1px;\n    border-right: 1px solid #a4acb9;\n    border-left: 1px solid #a4acb9;\n    padding: 0px 15px 5px 15px;\n}\n\n.subheader .details:first-child {\n    border-left: none;\n}\n\n.subheader .details:last-child {\n    border-right: none;\n}\n\n.subheader .details > span, span.detail {\n    font-size: 13px;\n    display: block;\n    padding-bottom: 5px;\n}\n\n.subheader .details p {\n    font-size: 13px;\n}\n\n.subheader .related {\n    float: right;\n    margin: 0 -10px 10px 10px;\n}\n\n.subheader .details span i, span.detail i {\n    font-size: 90%;\n    padding-right: 8px;\n}\n\n.subheader >div>.pull-right {\n    margin-top: 12px;\n    margin-right: 5px;\n}\n\n.subheader a.action {\n    color: #1a1a1a;\n    margin-right: 10px;\n    line-height: 36px;\n    text-decoration: underline;\n    font-size: 14px;\n}\n\n.subheader a.action i {\n    text-decoration: none;\n    font-style: normal;\n}\n\n.subheader a:hover {\n    color: #606b7d;\n}\n\n.subheader .highlight {\n    color: #ffeeaa;\n}\n\n\n/** Custom icons **/\n\n.icon {\n    position: relative;\n    top: 1px;\n    display: inline-block;\n    font-family: 'cherokeeregular';\n    font-style: normal;\n    font-weight: 400;\n    line-height: 1;\n    -webkit-font-smoothing: antialiased;\n    -moz-osx-font-smoothing: grayscale;\n}\n\n.icon-user-add:before {\n    content: \"\\e008\";\n}\n\n.icon-comment-add:before {\n    content: \"\\e111\";\n}\n\n.icon-diagram:before {\n    content: \"\\e011\";\n}\n\n.icon-caret-down:before {\n    content: \"\\e114\";\n}\n\n.icon-caret-left:before {\n    content: \"\\e115\";\n}\n\n.icon-caret-right:before {\n    content: \"\\e116\";\n}\n\n.icon-remove:before {\n    content: \"\\e117\";\n}\n\n.icon-pencil:before {\n  content: \"\\270f\";\n}\n\n.icon-caret-up:before {\n    content: \"\\e118\";\n}\n\n.icon-user:before {\n    content: \"\\e119\";\n}\n\n.icon-choice:before {\n    content: \"\\e120\";\n}\n\n.icon-move:before {\n    content: \"\\e121\";\n}\n\n.icon-mail:before {\n    content: \"\\e122\";\n}\n\n.icon-clock:before {\n    content: \"\\e123\";\n}\n\n.icon-download:before {\n    content: \"\\e124\";\n}\n\n.icon-word:before {\n    content: \"\\e125\";\n}\n\n.icon-excel:before {\n    content: \"\\e126\";\n}\n\n.icon-powerpoint:before {\n    content: \"\\e127\";\n}\n\n.icon-pdf:before {\n    content: \"\\e128\";\n}\n\n.icon-content:before {\n    content: \"\\e129\";\n}\n\n.icon-folder:before {\n    content: \"\\e130\";\n}\n\n.icon-image:before {\n    content: \"\\e131\";\n}\n\n.icon-bpmn-stencil:before {\n    content: \"\\e132\";\n}\n\n.icon-kickstart-stencil:before {\n    content: \"\\e133\";\n}\n\n.icon-form-stencil:before {\n    content: \"\\e134\";\n}\n\n.simple-list .icon-image, .related-content .icon-image {\n    color: #484b84;\n}\n\n.simple-list .icon-pdf, .related-content .icon-pdf {\n    color: #ac2020;\n}\n\n.simple-list .icon-powerpoint, .related-content .icon-powerpoint {\n    color: #dc5b31;\n}\n\n.simple-list .icon-excel, .related-content .icon-excel {\n    color: #13743d;\n}\n\n.simple-list .icon-word, .related-content .icon-word {\n    color: #2974b8;\n}\n\n.simple-list .icon-content, .related-content .icon-content {\n    color: #666666;\n}\n\n.loading {\n    margin: 0px 15px;\n    text-align: center;\n    line-height: 34px;\n}\n\n.loading > div {\n    width: 10px;\n    height: 10px;\n    background-color: #9fd7e5;\n    margin: 1px;\n\n    border-radius: 100%;\n    display: inline-block;\n    -webkit-animation: bouncedelay 1.4s infinite ease-in-out;\n    animation: bouncedelay 1.4s infinite ease-in-out;\n    /* Prevent first frame from flickering when animation starts */\n    -webkit-animation-fill-mode: both;\n    animation-fill-mode: both;\n}\n\n.loading .l1 {\n    -webkit-animation-delay: -0.32s;\n    animation-delay: -0.32s;\n}\n\n.loading .l2 {\n    -webkit-animation-delay: -0.16s;\n    animation-delay: -0.16s;\n}\n\n.loading-box {\n    text-align: center;\n    margin: 50px auto 10px auto;\n    padding: 20px 50px;\n    max-width: 400px;\n}\n\n.loading-box span {\n    font-size: 16px;\n    color: #333333;\n}\n\n\n@-webkit-keyframes bouncedelay {\n    0%, 80%, 100% { -webkit-transform: scale(0.0) }\n    40% { -webkit-transform: scale(1.0) }\n}\n\n@keyframes bouncedelay {\n    0%, 80%, 100% {\n        transform: scale(0.0);\n        -webkit-transform: scale(0.0);\n    } 40% {\n          transform: scale(1.0);\n          -webkit-transform: scale(1.0);\n      }\n}\n\n/** Alerts */\n.alert-wrapper {\n\n}\n\n.alert-wrapper {\n    position: fixed;\n    top: 40px;\n    left: 0;\n    right: 0;\n    z-index: 1010;\n}\n\n.alert-wrapper.no-header  {\n    top: 0px;\n}\n\n.alert {\n    text-align: center;\n    width: 100%;\n    min-height: 20px;\n    background-color: #eef4d7;\n    background-color: rgba(238, 244, 215, .7);\n    padding: 8px 10px;\n    cursor: pointer;\n    border: none;\n    border-bottom: 1px solid #bcd35f;\n\n    -moz-border-radius: 0px;\n    -webkit-border-radius: 0px;\n    border-radius: 0px;\n\n    -webkit-transition: all .5s ease;\n    -moz-transition: all .5s ease;\n    -o-transition: all .5s ease;\n    transition: all .5s ease;\n}\n\n.alert.ng-hide-remove {\n    opacity: 1;\n    display:block!important;\n }\n\n\n.alert.ng-hide {\n    opacity: 0;\n}\n\n.alert .badge {\n    background-color: #bcd35f;\n    color: #ffffff;\n    font-size: 12px;\n    margin-top: 2px;\n    margin-left: 10px;\n}\n\n\n.alert .glyphicon {\n    padding-right: 8px;\n    color:  #bcd35f;\n}\n\n.alert span {\n    color: #445016;\n    font-size: 15px;\n}\n\n.alert.error {\n    background-color: #e9af9f;\n    border-color: #e4593d;\n    background-color: rgba(228, 89, 61, .7);\n}\n.alert.error .glyphicon {\n    color: #e4593d;\n}\n\n.alert.error span {\n    color: #471313;\n}\n\n.alert.error .badge {\n    background-color: #e4593d;\n    color: #ffffff;\n}\n\n.wrapper {\n    padding: 55px 15px 15px 15px;\n    max-width: 1400px;\n    min-width: 1024px;\n    margin: 0 auto;\n}\n\n.wrapper.full {\n    padding: 40px 0px 0px 0px;\n    overflow: hidden;\n    max-width: 100%;\n    min-width: 100%;\n}\n\n.wrapper.no-header {\n    padding-top: 10px;\n}\n\n/** Main list **/\n.main-list {\n    position: relative;\n    float: left;\n    width: 400px;\n    border: 1px solid #cccccc;\n    background-color: #ffffff;\n    margin-right: 20px;\n\n    -webkit-box-shadow: 2px 2px 2px 0px rgba(220,220,220,0.50);\n    -moz-box-shadow: 2px 2px 2px 0px rgba(220,220,220,0.50);\n    box-shadow: 2px 2px 2px 0px rgba(220,220,220,0.50);\n}\n\n.main-list .sort {\n    position: absolute;\n    top: 12px;\n    right: 5px;\n}\n\n.list-header {\n    position: absolute;\n    top: 0;\n    left: 0;\n    right: 0;\n    background-color: #ffffff;\n    background-color: rgba(255, 255, 255, .9);\n    border-bottom: 1px solid #cccccc;\n\n    -webkit-box-shadow: 0px 1px 1px 0px rgba(220,220,220,0.65);\n    -moz-box-shadow: 0px 1px 1px 0px rgba(220,220,220,0.65);\n    box-shadow: 0px 1px 1px 0px rgba(220,220,220,0.65);\n    z-index: 2;\n\n}\n\n.list-header .loading {\n    position: absolute;\n    left: 50%;\n    margin-left: -15px;\n    line-height: 30px;\n}\n\n.list-header .summary {\n    cursor: pointer;\n    padding: 10px 10px 10px 10px;\n    min-height: 30px;\n}\n\n.list-header .summary > span {\n    color: #373e48;\n}\n\n.list-header .summary .divider {\n    content: '&bull';\n    font-size: 70%;\n    line-height: 1;\n    font-style: normal;\n    padding: 0 5px;\n}\n\n.list-header .form-group {\n    margin-bottom: 10px;\n    position: relative;\n}\n\n.selection {\n    position: relative;\n    margin: 0;\n    padding: 6px 8px;\n\n    border: 1px solid #cccccc;\n    -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.075);\n    -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075);\n    box-shadow: inset 0 1px 1px rgba(0,0,0,.075);\n    background-color: #ffffff;\n\n    font-size: 14px;\n\n    cursor: pointer;\n}\n\n.selection  .glyphicon, .selection  .icon {\n    padding-right: 5px;\n}\n\n.selection .actions {\n    float: right;\n}\n.selection .actions.no-upload {\n    float: left;\n    margin-right: 10px;\n}\n\n.selection.narrow {\n    padding: 0;\n}\n\n.selection .pull-right {\n    margin: 4px 4px 4px 0;\n}\n\n.selection.narrow .simple-list {\n    margin-bottom: 0;\n    padding-bottom: 0;\n}\n\n.selection.narrow .simple-list li {\n    border-top: 1px dotted #eeeeee;\n}\n\n.selection.narrow .simple-list li:first-child {\n    border-top: none;\n}\n\n\n.selection.narrow .no-results {\n    padding: 6px 0 0 5px;\n}\n\n.selection.narrow .details {\n    margin: 5px;\n    border: none;\n}\n\n.selection.narrow .label {\n    font-size: 13px;\n    padding:0 10px 0 0;\n    margin: 0;\n    color: #666666;\n}\n\n.selection > .icon-caret-down {\n    visibility: hidden;\n    position: absolute;\n    top: 8px;\n    right: 5px;\n}\n\n.selection .empty {\n    color: #666666;\n}\n\n.selection:hover > .icon-caret-down, button.selection:active > .icon-caret-down, button.selection:focus > .icon-caret-down {\n    visibility: visible;\n}\n\n.selection[disabled]:hover > .icon-caret-down, button.selection[disabled]:active > .icon-caret-down, button[disabled].selection:focus > .icon-caret-down {\n    visibility: hidden;\n}\n\n.selection[disabled] {\n    background-color: #f6f6f7;\n    color: #999999;\n}\n\n.selection+.dropdown-menu {\n    width: 100%;\n}\n\nbutton.selection:active, button.selection:focus {\n    outline: none;\n    border-color: #acacac;\n}\n\n.selection.toggle {\n    overflow: hidden;\n    clear: both;\n    padding: 0;\n}\n\n.selection.toggle .toggle-2 {\n    width: 50%;\n    float: left;\n}\n\n\n.selection.toggle .toggle-3 {\n    width: 33.333%;\n    float: left;\n}\n\n.selection.toggle .toggle-4 {\n    width: 25%;\n    float: left;\n}\n\n.selection.toggle .btn {\n    border: none;\n    border-right: 1px solid #bbbbbb;\n    width: 100%;\n    background-color: #eeeeee;\n    -moz-border-radius: 0px;\n    -webkit-border-radius: 0px;\n    border-radius: 0px;\n    color: #666666;\n    -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.075);\n    -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075);\n    box-shadow: inset 0 1px 1px rgba(0,0,0,.075);\n\n}\n\n.selection.toggle .btn:active, .selection.toggle .btn:focus {\n    outline: none;\n    color: #1a1a1a;\n    background-color: #f8f8f8;\n}\n\n.selection.toggle > .active .btn {\n    background-color: #ffffff;\n    color: #1a1a1a;\n    -moz-box-shadow: none;\n    -webkit-box-shadow: none;\n    box-shadow: none;\n}\n\n.selection.toggle > div:last-child .btn {\n    border: none;\n}\n\n.subtle-select {\n    padding: 6px 8px;\n    background-color: transparent;\n    color: #1a1a1a;\n    text-decoration: none;\n}\n\n.subtle-select .icon {\n    visibility: hidden;\n}\n\n.subtle-select:hover .icon {\n    visibility: visible;\n}\n\n.subtle-select:hover, .header .detail a.subtle-select:hover {\n    background-color: #ffffff;\n    text-decoration: none;\n    color:#1a1a1a;\n}\n\n\n.list-header .summary label, .list-header .summary .filter-action {\n    font-size: 11px;\n    font-weight: normal;\n    text-transform: uppercase;\n    margin-bottom: 0;\n    color: #1a1a1a;\n}\n\n.list-wrapper {\n   overflow: auto;\n}\n\n\n.main-list {\n    height: 100%;\n    overflow: hidden;\n}\n\n.main-list .nothing-to-see {\n    text-align: center;\n    padding:50px 20px;\n}\n\n.main-list .nothing-to-see span {\n    font-size: 17px;\n}\n.main-list .popover {\n    width: 375px;\n}\n\n.list-header .summary .filter-action:hover {\n    color: #36a7c4;\n}\n\n.main-list .list-subheader {\n    margin-top: 40px;\n    position: relative;\n    z-index: 1;\n    border-bottom: 1px solid #f2f2f2;\n}\n\n.main-list .list-subheader > .btn-group {\n    margin: 10px 5px 10px 10px;\n}\n\n.full-list li.more {\n    padding: 10px 15px;\n    background-color: #ffffff;\n    color: #666666;\n}\n\n.full-list li.more i.icon {\n    font-size: 70%;\n}\n\n.full-list {\n    list-style: none;\n    padding: 0;\n    margin-bottom: 0;\n}\n\n.full-list li {\n    position: relative;\n    display: block;\n    border-bottom: 1px solid #f5f5f5;\n    cursor: pointer;\n    padding: 2px 0px 2px 0px;\n}\n\n.full-list li .badge, .simple-list li .badge{\n    font-size: 12px;\n    line-height: 12px;\n\n    padding-right: 0;\n    border-radius: 3px;\n    background-color: #e8edf1;\n    color: #36a7c4;\n    background-color: transparent;\n    font-weight: normal;\n\n}\n\n\n.full-list li.active {\n    background-color: #fafafb;\n}\n\n.full-list li:hover {\n    background-color: #fafafb;\n}\n\n.full-list li > div:hover {\n    border-color: #d8dde1;\n}\n\n.full-list li > div {\n    margin: 0 6px 0 4px;\n    border-left: 4px solid #e8edf1;\n    min-height: 50px;\n    padding: 5px 5px 5px 5px;\n}\n\n.full-list li.active > div {\n    border-left-color: #36a7c4;\n}\n\n.full-list li .title {\n    font-size: 16px;\n    margin: 0 0 0 5px;\n\n    white-space: nowrap;\n    overflow: hidden;\n    text-overflow: ellipsis;\n}\n\n.full-list li .summary {\n    clear: both;\n    margin: 3px 5px 0px 5px;\n    font-size: 13px;\n    color: #1a1a1a;\n    white-space: nowrap;\n    width: 100%;\n    overflow: hidden;\n    text-overflow: ellipsis;\n}\n\n.full-list li .detail {\n    margin: 0 5px;\n    font-size: 12px;\n    color: #999999;\n    white-space: nowrap;\n    width: 100%;\n    overflow: hidden;\n    text-overflow: ellipsis;\n}\n\n.main-content {\n    border: 1px solid #cccccc;\n\n\n    height: 100%;\n    max-height: 100%;\n    overflow: hidden;\n    padding-bottom: 10px;\n}\n\n.main-content-wrapper {\n    height: 100%;\n    max-height: 100%;\n    overflow: hidden;\n    -webkit-box-shadow: 2px 2px 2px 0px rgba(220,220,220,0.50);\n    -moz-box-shadow: 2px 2px 2px 0px rgba(220,220,220,0.50);\n    box-shadow: 2px 2px 2px 0px rgba(220,220,220,0.50);\n}\n\n.main-content > .header {\n    background-color: #e8edf1;\n    min-height: 60px;\n    border-bottom: 1px solid #a4acb9;\n    padding: 15px 15px;\n}\n\n.main-content > .header h2 {\n    margin: 0 0 5px 0;\n    font-size: 26px;\n}\n\n.main-content > .header .btn:hover, .main-content > .header .btn:focus  {\n    border-color: #e8edf1;\n    color: #ffffff;\n}\n\n .modal-header .label, .header .label {\n    padding: 0 3px 0 15px;\n    color: #1a1a1a;\n    font-weight: normal;\n    font-size: 13px;\n    color: #666666;\n}\n\n.header > .detail >.label:first-child {\n    padding-left: 0;\n}\n\n.header .detail a {\n    color: #1a1a1a;\n}\n\n.header .detail a:hover {\n    color: #36a7c4;\n    text-decoration: underline;\n}\n\n.jumpers {\n    list-style: none inside;\n    padding: 0 10px 10px 10px;\n    margin: 5px 0px 0 0px;\n    border-bottom: 1px solid #eeeeee;\n}\n\n.jumpers li {\n    display: inline-block;\n    border: 1px solid #e8edf1;\n    margin: 5px 0 0 2px;\n    padding: 5px 25px;\n    -moz-border-radius: 2px;\n    -webkit-border-radius: 2px;\n    border-radius: 2px;\n    cursor: pointer;\n}\n\n.jumpers li.pending {\n    border: 1px dotted #d8dde1;\n}\n\n.jumpers li:hover {\n    background-color: #f8f8f9;\n}\n\n.jumpers li.selected {\n    color: white;\n    background-color: #36a7c4;\n}\n\n\n.jumpers li span {\n    background-color: #f2f2f2;\n    padding: 1px 5px;\n    margin-left: 5px;\n    -moz-border-radius: 2px;\n    -webkit-border-radius: 2px;\n    border-radius: 2px;\n    color: #999999;\n}\n\n.jumpers li:hover span {\n    background-color: #e2e2e2;\n}\n\n\n\n.section {\n    margin: 10px 0;\n    padding: 10px 0 0px 0;\n    min-height: 120px;\n}\n\n.section.pack {\n    min-height: inherit;\n}\n\n.col-xs-12.seperator {\n    height: 1px;\n    border-top: 1px solid #eeeeee;\n    margin: 5px 0;\n}\n\n.section > h3 {\n    position: relative;\n    margin: 0px;\n    font-size: 18px;\n    cursor: pointer;\n}\n\n.section > h3 .action > a {\n    font-weight: bold;\n    padding-left: 5px;\n    color: #999999;\n}\n\n\n.section > .form-group, .section > div > .form-group {\n    margin: 5px 0;\n}\n\n.modal-backdrop {\n    background-color: #999999; /** Non alpha-supporting browser fallback */\n    background-color: rgba(100, 100, 100, .75);\n    background-image: url('../../images/glasspane.png');\n}\n.modal-content {\n    -webkit-border-radius: 0;\n    -moz-border-radius: 0;\n    border-radius: 0;\n    border: none;\n}\n\n.modal-dialog.wide {\n    margin-left: auto;\n    margin-right: auto;\n    width: 80%;\n    max-width: 1200px;\n}\n\n.modal-body {\n}\n\n\n.modal .modal-header {\n    position: relative;\n    background-color: #e8edf1;\n    min-height: 60px;\n    border-bottom: 1px solid #a4acb9;\n    padding: 15px 15px;\n}\n\n.modal-header .actions {\n    margin-right: 20px;\n}\n\n.modal-body .form-actions {\n    border-top: 1px solid #eeeeee;\n    margin: 0 -30px;\n    padding: 10px 10px 10px 10px;\n}\n\n.modal-body.includes-footer {\n    padding-bottom: 0px;\n}\n\n.fullscreen .modal-header h3 {\n    margin: 0 0 5px 0px;\n    font-size: 22px;\n}\n\n.fullscreen .modal-header h3 .summary {\n    font-size: 13px;\n}"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/css/style-editor.css",
    "content": "/**\n Colors:\n \n  - Header: #333333\n  - Subheader: #e8edf1\n  - Subheader border: #a4acb9\n  - Highlight buttons/text: #36a7c4\n  - Text color: #1a1a1a\n  - Filter color: #373e48\n  - Dark highlight: #606b7d\n\n */\n.container-fluid {\n\tmax-width: 1400px;\n\tmin-width: 1000px;\n\tmargin: 0 auto;\n}\n\n.subtle-select .glyphicon {\n    visibility: hidden;\n    padding-left: 5px;\n}\n\na.subtle-select:hover .glyphicon {\n    visibility: visible;\n}\n\n.full {\n\tpadding: 0 15px;\n\twidth: 100%;\n}\n\n.inline {\n    display: inline;\n}\n\n.greyish {\n    color: #afafaf;\n}\n\n.roweditor-canvas {\n    margin-top: 50px;\n}\n\n.no-pad {\n\tmargin: 0;\n\tmax-width: 1300px;\n    min-width: 1100px;\n}\n\n.content.no-pad {\n    max-width: 100%;\n    min-width: 100%;\n}\n\n.inset .col-sm-3 {\n    margin-left: -15px;\n}\n.no-pad > div{\n\tpadding: 0;\n}\n\n\n.dropdown-toggle .icon-caret-down {\n\tpadding-left: 10px;\n\tfont-size: 85%;\n}\n\nh1 {\n\tmargin: 0 0 0 15px;\n\tpadding: 0;\n\tfont-size: 22px;\n\tline-height: 40px;\n\tborder: none;\n\tcolor: #ffffff;\n\tfont-family: 'Lato', sans-serif; \n}\n\n.truncate, .truncate > span {\n  white-space: nowrap;\n  width: 100%;                   \n  overflow: hidden; \n  text-overflow: ellipsis;\n}\n\n.subheader .details .counter {\n\ttop: -1px;\n\tline-height: 1;\n\tdisplay: inline-block;\n\tpadding: 2px 6px;\n\tmin-width: 20px;\n\tbackground-color: #e8edf1;\n\tcolor: #333333;\n}\n\n.subheader .subtle-select {\n\tmargin: -6px 0 0 -8px;\n}\n\n.btn .icon-and-label {\n\tpadding-right: 5px;\n} \n\n.dropdown-menu .title {\n\tmargin: 5px 10px 0px 10px;\n\tfont-size: 17px;\n\tmin-width: 250px;\n}\n\n.dropdown-menu ul {\n\tlist-style: none;\n\tlist-style-position: inside;\n\tpadding: 5px 10px;\n}\n\n.input-group-addon {\n\tbackground-color: transparent;\n}\n\n/* List Filter */\n.filter-wrapper {\n\tmin-height: 400px;\n\tmargin-top: 10px;\n    margin-left: -15px;\n}\n\nul.filter-list {\n\tlist-style: none;\n\tlist-style-position: inside;\n\tpadding-left: 0px;\n\tpadding-top: 10px;\n}\n\nul.filter-list li a {\n\tdisplay: block;\n\tcolor: #373e48;\n\tfont-size: 17px;\n\tmargin: 10px 5px 10px 0px;\n\tpadding-left: 10px;\n}\n\nul.filter-list li.current a {\n\tcolor: #36a7c4;\n\tpadding-left: 5px;\n\tborder-left: 4px solid #36a7c4;\n}\n\nul.filter-list li a:hover, ul.filter-list li a:focus {\n\ttext-decoration: none;\n\tbackground-color: #e8edf1;\n}\n\nul.filter-list li.current a:hover, ul.filter-list li.current a:focus {\n\tbackground-color: transparent;\n\tcolor: #36a7c4;\n\tcursor: default;\n\ttext-decoration: none;\n}\n\n\n/* Result items */\n\n\n.item-wrapper {\n\tpadding-left: 0;\n\tmargin-top: 5px;\n}\n\n.item-wrapper .message {\n\ttext-align: left;\n\tmargin-left: 5px;\n\tline-height: 40px;\n\tcolor: #606b7d;\n}\n.item-wrapper .message span {\n\tfont-size: 14px;\t\n}\n\n.item-wrapper .item {\n\twidth: 25%;\n\tpadding: 0;\n\tmargin: 0;\n\tfloat: left;\n}\n\n.item-wrapper .item .btn-default.disabled, \n.item-wrapper .item .btn-default[disabled],\n.item-wrapper .item .btn-default[disabled]:active,\n.item-wrapper .item .btn-default[disabled]:hover {\n\tborder-color: #ffffff;\n\tcursor: default;\t\n}\n\n.item-wrapper .item .item-box {\n\tmargin: 5px;\n\tborder: 1px solid #e8edf1;\n\theight: 250px;\n\toverflow: hidden;\n\tcursor: pointer;\n\tbackground-repeat: no-repeat;\n\tbackground-position: center 20px;\n\tbackground-size: auto;\n    position: relative;\n}\n\n.item-box .details {\n    position: relative;\n\tbackground-color: #e8edf1;\n\theight: 160px;\n\tmargin-top: 120px;\n\tpadding: 5px;\n\tcolor: #373e48;\n\tfont-size: 13px;\n\t\n\ttransition: margin-top .5s ease;\n\t-moz-transition: margin-top .5s ease;\n\t-webkit-transition: margin-top .5s ease;\n\t-o-transition: margin-top .5s ease;\n}\n\n.item-box:hover .details, .item-box.active .details {\n\tmargin-top: 50px;\n}\n\n.item-box .actions {\n\tpadding: 5px;\n\theight: 45px;\n}\n\n.item-box .actions .btn-group {\n\tvisibility: hidden;\n}\n\n.item-box:hover .actions .btn-group, .item-box.active .actions .btn-group {\n\tvisibility: inherit;\n}\n\n\n.item-box .details h3 {\n\tfont-size: 14px;\n\tmargin: 0;\n\tpadding: 2px;\n\tcolor: #373e48;\n}\n\n.item-box .details span {\n\tdisplay: block;\n\tmargin-top: 5px;\n}\n\n.item-box .details span i {\n\tpadding-right: 10px;\n\tpadding-left: 5px;\n}\n\n.item-box .details .basic-details {\n\tmin-height: 60px;\n}\n\n.item-box .details p {\n\twidth: 100%;\n\theight: 70px;\n\tfont-size: 12px;\n\toverflow: hidden;\n}\n\n.create-inline {\n\tpadding: 100px 20px 80px 20px;\n\tborder: 1px solid #e8edf1;\n}\n.create-inline span {\n\tdisplay: block;\n\tfont-size: 18px;\n\tcolor: #1a1a1a;\n\ttext-align: center;\n\tmargin-bottom: 20px;\n} \n\n.create-inline .glyphicon {\n\tmargin-right: 10px;\n}\n\n.show-more {\n\tclear: both;\n\theight: 50px;\n\ttext-align: center;\n\tpadding-top: 5px;\n\tmargin: 5px;\n}\n\n.show-more a {\n\tdisplay: block;\n\tpadding: 5px;\n\tfont-size: 15px;\n\ttext-decoration: none;\n\tcursor: pointer;\n\tcolor: #666666;\n}\n\n.show-more a:hover {\n\tcolor: #1a1a1a;\n\tbackground: #e8edf1;\n}\n\n.content-canvas-wrapper {\n    -moz-box-shadow:    inset  0  3px 3px -4px #ababab;\n    -webkit-box-shadow: inset  0  3px 3px -4px #ababab;\n    box-shadow:        inset  0  3px 3px -4px #ababab;\n    margin: 15px 7px 0 7px;\n    z-index: 0;\n}\n.content-canvas {\n    background-color: #f9f9f9;\n    margin: 0 3px 0 3px;\n\n    -moz-box-shadow:    inset  0  3px 3px -4px #ababab;\n    -webkit-box-shadow: inset  0  3px 3px -4px #ababab;\n    box-shadow:        inset  0  3px 3px -4px #ababab;\n\n    padding: 20px;\n}\n\n\n.content-canvas h3 {\n    margin-bottom: 5px;\n}\n\n.content-canvas .no-results{\n    color: #999999;\n    font-size: 16px;\n    margin: 10px 0px;\n}\n\n.content-canvas .item-wrapper {\n    margin: 5px 10px;\n}\n\n/* History */\ntable.history {\n\tmargin: 0;\n\tpadding: 0;\n}\n\n.subheader table.history {\n\tmin-width: 250px;\t\n}\n\ntable.history td {\n\tvertical-align: middle;\t\n}\n\ntable.history tr td:last-child {\n\twidth: 90%;\n}\n\ntable.history tr:hover {\n\tbackground-color: #f3f6f8;\n\tcursor: pointer;\n}\ntable.history tr.current:hover {\n\tbackground-color: #e8edf1;\n\tcursor: inherit;\n}\n\n\ntable.history a:hover {\n\ttext-decoration: none;\n\t\n}\n\ntable.history .version {\n\tfont-size: 30px;\n\tdisplay: inline-block;\n\tcolor: #36a7c4;\n\tpadding: 5px 10px;\n\tvertical-align:middle;\n\tcolor: #36a7c4;\n}\n\ntable.history .detail {\n\tpadding: 5px 5px;\n\tfont-size: 15px;\n\tcolor: #1a1a1a;\n\tdisplay: inline-block;\n}\n\ntable.history tr.current {\n\tfont-weight: bold;\n\tbackground-color: #e8edf1;\n}\ntable.history tr.current td {\n\tbackground-color: #e8edf1;\n}\n\n.comments {\n\tclear: both;\n\twidth: 350px;\n\tborder-top: 1px solid #eeeeee;\n\tmargin-top: 5px;\n\tmax-height: 350px;\n\toverflow: auto;\t\n}\n\n.comment {\n\tmargin: 10px 0px 20px 0px;\t\n\tfont-size: 12px;\n}\n\n.comment .date {\n\tcolor: #999999;\n\tfont-size: 12px;\n}\n\n.comment .author {\n\tcolor: #36a7c4;\n\tfont-size: 18px;\n}\n\n.comment p {\n\t word-wrap: break-word;\n}\n\n.modal.modal-wide .modal-dialog {\n\twidth: 1000px;\t\n}\n\n.modal-dialog.modal-wide {\n    width: 1000px;  \n}\n\n.modal-body p {\n\tfont-size: 15px;\n}\n\n.modal-body p.danger {\n\tcolor: #d35f5f;\n\tmargin-top: 10px;\n}\n\n.form-group .inline-help {\n    font-size: 11px;\n    color: #666666;\n    margin-top: 5px;\n}\n\n.form-group .message {\n    color: #1a1a1a;\n    font-size: 14px;\n}\n\n.people-select > .selection {\n    width: 100%;\n    text-align: left;\n}\n.popup-wrapper .people-select {\n    max-height: 160px;\n}\n\n.people-select .nothing-to-see {\n    padding: 5px 0;\n\n    color: #999999;\n}\n\n.inline-people-select {\n    max-height: 120px;\n    overflow: auto;\n}\n\n/** Center tabbed pane */\n.center-pane {\n    overflow: auto;\n    padding-bottom: 20px;\n}\n\n.center-pane .content {\n    overflow: hidden;\n}\n.center-pane .tab-actions {\n    padding: 8px;\n}\n\n.center-pane .tabs-wrapper > .pull-right {\n    margin-right: 5px;\n}\n.center-pane .content {\n    padding: 10px;\n}\n\n.center-pane.content {\n    padding: 0;\n}\n\n.center-pane .content .tabs, .center-pane.content .tabs {\n    padding-left: 15px;\n}\n\n.center-pane .content .tabs > li a, .center-pane.content .tabs > li a {\n    padding: 8px 30px;\n}\n\n.center-pane .header h1 {\n    font-size: 30px;\n    margin: 0;\n    padding:0;\n}\n\n.center-pane .header h2 {\n    font-size: 24px;\n    margin: 0 0 5px 0;\n    padding:0;\n}\n\n.center-pane .header {\n    padding: 5px 10px 25px 10px;\n}\n\n\n.center-pane .header.compact {\n    padding-bottom: 5px;\n}\n\n.center-pane .well {\n    -moz-border-radius: 0px;\n    -webkit-border-radius: px;\n    border-radius: 0px;\n    background-color: #f9f9f9;\n    padding: 12px 10px;\n    margin: 15px 0 0 0;\n    border: 1px solid #eeeeee;\n}\n\n/** General button styling */\n.btn.btn-clean {\n    border: none;\n    background-color: transparent;\n    font-size: 24px;\n    padding: 2px 6px;\n    color: #444444;\n\n    -webkit-box-shadow: none;\n    -moz-box-shadow: none;\n    box-shadow: none;\n}\n\n.btn-clean:hover .icon-remove {\n    color: #a02828;\n}\n\n.btn-clean:focus, .btn-clean:hover {\n    color: #5f8dd3;\n    -webkit-box-shadow: none;\n    -moz-box-shadow: none;\n    box-shadow: none;\n}\n\n\n.btn-clean:active {\n    color: #2c5aa0;\n    -webkit-box-shadow: none;\n    -moz-box-shadow: none;\n    box-shadow: none;\n}\n\n/* Show list in popup */\n\nul.list {\n    list-style: none inside;\n    padding: 0px;\n    margin-bottom: 3px;\n}\n\nul.list>li {\n    line-height: 30px;\n    margin: 0;\n    padding: 4px;\n    cursor: pointer;\n}\n\n.popup-wrapper ul.list>li {\n    border-top: 1px solid #eeeeee;\n}\n\n.popup-wrapper ul.list>li:last-child {\n    border-bottom: 1px solid #eeeeee;\n}\n\nul.list>li:hover, ul.list>li.active {\n    background-color: #f2f2f2;\n}\n\nul.list >li .actions {\n    float:right;\n    margin: 0px 0px 0px 5px;\n    visibility: hidden;\n}\n\nul.list>li:hover .actions {\n    visibility: inherit;\n}\n\n/** Animations **/\n.fadein.ng-enter, \n.fadein.ng-move {\n  -webkit-transition: 0.5s linear opacity;\n  transition: 0.5s linear all;\n}\n\n.fadein.ng-enter {\n  opacity:0;\n}\n.fadein.ng-enter.ng-enter-active {\n  opacity:1;\n}\n\n.fadein.ng-move {\n  opacity:0.5;\n}\n.fadein.ng-move.ng-move-active {\n  opacity:1;\n}\n\n.popup-error {\n    color: red;\n    padding: 0 5px 8px 0;\n}\n\n/** Passwords */\n\n.password-field {\n    width: 320px;\n}\n\n/** LOADING */\n\n.message .loading {\n\tline-height: 40px;\n\tmargin-left: 0px;\t\n}"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/css/style.css",
    "content": "@font-face {\n    font-family: 'ActivitiModeler';\n    src: url('../fonts/activiti-admin-webfont.eot');\n    src: url('../fonts/activiti-admin-webfont.eot?#iefix') format('embedded-opentype'),\n         url('../fonts/activiti-admin-webfont.woff') format('woff'),\n         url('../fonts/activiti-admin-webfont.ttf') format('truetype'),\n         url('../fonts/activiti-admin-webfont.svg#activitimodelerregular') format('svg');\n    font-weight: normal;\n    font-style: normal;\n}\n\n.row-no-gutter .col-xs-9 {\n\tpadding-left: 0px;\n\tpadding-right: 0px;\n\tz-index: 50;\n}\n\n.row-no-gutter .col-xs-3 {\n\tpadding-left: 0px;\n\tpadding-right: 0px;\n\tz-index: 100;\n}\n\n.editor-item-picker {\n    height: 400px;\n    max-height: 400px;\n    min-height: 400px;\n    overflow: auto;\n}\n\n.editor-item-picker-component {\n    height: 185px;\n    max-height: 185px;\n    overflow: hidden;\n}\n\n.editor-toolbar {\n\tpadding-left: 5px;\n}\n\n.editor-toolbar > .btn-group {\n\tmargin: 12px 15px 0px 0px;\n}\n\n.editor-toolbar  > .btn-group.pull-right {\n\tmargin: 0;\n}\n\n.editor-toolbar .btn.btn-inverse {\n\tfont-size: 24px;\n\tcolor: #FFFFFF;\n    border-color: rgba(0, 0, 0, 0);\n    padding: 3px 6px 0px 6px;\n    box-shadow: none;\n    text-shadow: none;\n    text-align: center;\n    border: none;\n    margin: 0px 0px 0px 5px;\n    height: 36px;\n    min-width: 36px;\n}\n.editor-toolbar .btn.btn-inverse.pressed {\n\tbackground-color: #287d92;\n\tcolor: #174753;\n}\n\n.editor-toolbar .btn.btn-inverse.disabled, .editor-toolbar .btn.btn-inverse[disabled], .editor-toolbar .btn.btn-inverse[disabled]:active, .editor-toolbar .btn.btn-inverse[disabled]:hover {\n\tbackground-color: #668b94;\n\tborder-color: #668b94;\n}\n\n.editor-toolbar .btn.btn-inverse.separator {\n\tbackground: transparent;\n\tpadding: 4px 5px 0px 5px;\n\twidth: 1px;\n\tmin-width: 1px;\n}\n\n.editor-toolbar .toolbar-separator {\n\tbackground: #a4acb9;\n\twidth: 1px;\n\theight: 30px;\n}\n\n.stencils {\n\tborder-right: 1pt solid #c7cacd;\n\toverflow: auto;\n\tz-index: 5000;\n}\n\n.stencils ul {\n\tpadding-left: 0;\n}\n\n.stencils > div {\n\tmargin-top: 10px;\n}\n\n.stencil-group {\n\tlist-style: none;\n\tlist-style-position: outside;\n\tmargin: 0px 15px 0px 0px;\n}\n\n\n.stencil-group > li {\n\tlist-style: none;\n\tlist-style-position: outside;\n\tmargin: 0px 0px 5px 15px;\n\tbackground-color: #ffffff;\n\tfont-family: Arial, Regular;\n\tfont-size: 17px;\n\tcolor: #323437;\n}\n\n.stencil-group > li > span {\n\tmargin-left: 5px;\n\tpadding-top:5px;\n\tpadding-bottom: 5px;\n\tdisplay: block;\n\tcursor: pointer;\n}\n\n.stencil-group > li > span > i {\n\tfont-size: 12px;\t\n\tline-height: 17px;\n}\n.stencil-group > li > ul {\n\tlist-style: none;\n\tlist-style-position: inside;\n\tbackground-color: transparent;\n\tmargin: 0px;\n\toverflow: hidden;\n\tpadding-left: 20px;\n}\n\n.stencil-group.collapsed > li {\n\tcolor: #000000;\n}\n.stencil-group.collapsed > li > ul {\n\tmax-height: 0px;\n\tpadding-top: 0;\n\tpadding-bottom: 0;\n}\n\n.stencil-group-non-root > li {\n    background-color: #ffffff;\n}\n\n.stencil-item {\n    cursor: pointer;\n    padding: 5px;\n}\n\n.root-stencil-item {\n    margin: 0 0 0 15px;\n    font-family: Arial, Regular;\n    font-size: 17px;\n}\n\n.ui-draggable.stencil-item.stencil-item-dragged {\n    display: block;\n    text-overflow: ellipsis;\n    white-space: nowrap;\n}\n\n\n/* Modeling Canvas\n-------------------------------- */\ndiv.canvas-wrapper {\n\toverflow: auto;\n\tbackground-color: #F8F8F8;\n}\n\n.canvas_resize_indicator i {\n\tfont-size: 15px;\n\tcolor: #ffffff;\n\tcursor: pointer;\n}\n\n.canvas_resize_indicator.N, .canvas_resize_indicator.S, .canvas_resize_indicator.E, .canvas_resize_indicator.W {\n\tbackground: #5fbcd3;\n\theight: 17px;\n\twidth: 17px;\n\ttext-align: center;\n\t-webkit-border-radius:3px;\n\t-moz-border-radius:3px;\n\tborder-radius:3px;\n}\n\n#canvas-grow-N.canvas_resize_indicator, #canvas-shrink-S.canvas_resize_indicator {\n\tmargin: 0;\n\ttop: auto;\n}\n\n#canvas-grow-S.canvas_resize_indicator, #canvas-shrink-N.canvas_resize_indicator {\n\tmargin: 0;\n\tbottom: auto;\n}\n\n#canvas-grow-E.canvas_resize_indicator, #canvas-shrink-W.canvas_resize_indicator {\n\tmargin: 0;\n\tright: auto;\n}\n\n#canvas-grow-W.canvas_resize_indicator, #canvas-shrink-E.canvas_resize_indicator {\n\tmargin: 0;\n\tleft: auto;\n}\n\n.x-panel-body.x-panel-body-noheader.x-panel-body-noborder, .ORYX_Editor x-panel {\n\tbackground-color: #F8F8F8;\n}\n\n.canvas-message {\n\tposition: absolute;\n\ttop: 60px;\n\tright: 10px;\n\tbackground: transparent;\n\tfont-size: 10pt;\n}\n\n\ndiv.propertySection {\n\theight: 250px;\n    background-color: #e8edf1;\n\tmargin-bottom: 0px;\n}\n\n.selected-item-title {\n    font-size: 25px;\n    font-weight: bold;\n    padding: 8px 0 8px 8px;\n    border-bottom: 1px solid #a4acb9;\n    cursor: pointer;\n}\n\n.selected-item-title a {\n\tdisplay: block;\n\tcolor: #1a1a1a;\n}\n\n.selected-item-title .glyphicon {\n\tline-height: 25px;\n\tfont-size: 14px;\n}\n\n.selected-item-title a:hover, .selected-item-title a:focus {\n\tcolor: #1a1a1a;\n\ttext-decoration: none;\n}\n\n.selected-item-section > div > .pull-right {\n\tline-height: 50px;\n\tmargin: 0px 10px;\n\tfont-size: 14px;\n}\n\n.selected-item-body .property-row {\n\tfloat: left;\n\twidth: 50%;\n\tborder: 0;\n\tmargin: 0;\n\tpadding: 0;\n\tfont-size: 13px;\n\toverflow: hidden;\n}\n\n.selected-item-body .property-row:hover {\n\tbackground-color: #d7dfe6;\t\n}\n\n.selected-item-body {\n\tpadding: 0;\n\toverflow: auto;\n\theight: 199px;\n}\n\n.selected-item-body > div {\n\toverflow: hidden;\t\n\tmargin: 5px 20px;\n}\n\n.property-row > span {\n\tdisplay: block;\n\tfloat: left;\n\tmargin: 2px 2%;\n\tpadding: 0;\t\n\tmin-height: 25px;\n}\n\n.property-row span.value {\n\tcursor: pointer;\n\twidth: 46%;\n\tpadding: 0;\n\tmargin: 0;\n}\n\n.property-row span.value:hover {\n\tcursor: pointer;\n}\n\n.property-row span.title {\n\tfont-size: 13px;\n\tfont-weight: bold;\n\twidth: 46%;\n}\n\n.property-row span.title-removed {\n\tfont-size: 13px;\n\tfont-weight: normal;\n\twidth: 46%;\n}\n\n.propertySection.collapsed {\n\tmax-height: 50px;\n\theight: 50px;\n\toverflow: hidden;\n}\n\n.propertySection.collapsed .selected-item-title {\n\tborder: none;\n}\n\n.property-row input[type=\"text\"] {\n\theight: 25px;\n\tmargin: 2px 0;\n\tpadding: 0px 5px;\n\twidth: 100%;\n    outline: none;\n    border:none !important;\n    box-shadow:none !important;\n}\n\n.default-grid {\n    border: 1px solid rgb(212,212,212);\n    width: 100%;\n    height: 300px;\n    margin-bottom: 10px;\n}\n\n.kis-listener-grid {\n    border: 1px solid rgb(212,212,212);\n    width: 100%;\n    height: 200px;\n    margin-bottom: 10px;\n}\n\n.kis-field-grid {\n    border: 1px solid rgb(212,212,212);\n    width: 100%;\n    height: 150px;\n    margin-bottom: 10px;\n}\n\n.saving-text {\n    display: table;\n    margin: 0 auto;\n    padding: 20px 0 0px 0;\n}\n\n\n.form-property-checkbox {\n    margin:0;\n}\n\n/* Oryx overrides\n-------------------------------- */\nul.x-menu-list {\n\tlist-style: none;\n\tlist-style-position: inside;\n\twidth: 200px;\n\tbackground-color: #FFFFFF;\n\tborder: 1px solid #E1E2E5;\n\t-webkit-border-radius:3px;\n\t-moz-border-radius:3px;\n\tborder-radius:3px;\n\tpadding: 3px;\n}\n\nimg.x-menu-item-icon  {\n\twidth: auto;\n\theight: auto;\n\tmargin-right: 5px;\n}\n\nli.x-menu-list-item {\n\tmargin: 3px 0px;\n}\n\nli.x-menu-list-item.x-menu-item-active {\n\tbackground-color: #EFEFEF;\n}\n\nli.x-menu-list-item a {\n\tcolor: #000000;\n}\n\nli.x-menu-list-item.x-menu-item-active a {\n\ttext-decoration: none;\n}\n\n.sequence-flow-order-element {\n    margin: 12px 0 12px 0;\n}\n\n/* Editor icon font */\n.editor-icon {\n\tposition: relative;\n\ttop: 1px;\n\tdisplay: inline-block;\n\tfont-family: 'ActivitiModeler';\n\tfont-style: normal;\n\tfont-weight: 400;\n\tline-height: 1;\n\t-webkit-font-smoothing: antialiased;\n\t-moz-osx-font-smoothing: grayscale;\n}\n\n.editor-icon-save:before {\n\tcontent: 'a';\n}\n\n.editor-icon-edit:before {\n\tcontent: 'b';\n}\n\n.editor-icon-cut:before {\n\tcontent: 'c';\n}\n\n.editor-icon-copy:before {\n\tcontent: 'd';\n}\n\n.editor-icon-paste:before {\n\tcontent: 'e';\n}\n.editor-icon-delete:before {\n\tcontent: 'f';\n}\n.editor-icon-redo:before {\n\tcontent: 'h';\n}\n.editor-icon-undo:before {\n\tcontent: 'g';\n}\n.editor-icon-same-size:before {\n\tcontent: 'i';\n}\n.editor-icon-zoom-in:before {\n\tcontent: 'k';\n}\n.editor-icon-zoom-out:before {\n\tcontent: 'l';\n}\n.editor-icon-zoom-actual:before {\n\tcontent: 'm';\n}\n.editor-icon-zoom-fit:before {\n\tcontent: 'j';\n}\n.editor-icon-bendpoint-add:before {\n\tcontent: 'n';\n}\n.editor-icon-bendpoint-remove:before {\n\tcontent: 'o';\n}\n.editor-icon-align-horizontal:before {\n\tcontent: 'p';\n}\n.editor-icon-align-vertical:before {\n\tcontent: 'q';\n}\n.editor-icon-close:before {\n    content: \"X\";\n}\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/editor/css/editor.css",
    "content": "body, html {\n    font-family: tahoma,arial,helvetica,sans-serif;\n    font-size: 12px;\n}\n\n/*********\n * SVG Style\n */\n\ntext,\ntext * {\n    cursor:default;\n    -webkit-user-select: none;\n}\n\n/*********\n * HEADER SECTION\n *\n */\n\n#oryx_canvas_htmlContainer {\n\n}\n\n.ORYX_Editor {\n    background: white;\n    border: none;\n    margin:-5px;\n    margin-top:0px;\n    width:1200px;\n    height:600px;\n}\n\n.icon-large {\n\twidth:18px !important;\n}\n\n#oryxcanvas {\n\twidth:1200px;\n\theight:600px;\n}\n\n/** Resizer for the Canvas **/\n.canvas_resize_indicator_area {\n\n\tmargin\t\t:auto;\n\tdisplay\t\t:block;\n\theight\t\t:30px;\n\tleft\t\t:20%;\n\tposition\t:absolute;\n\ttext-align\t:center;\n\ttop\t\t\t:0;\n\twidth\t\t:60%;\n\n}\n\n.canvas_resize_indicator {\n\n\twidth\t\t: 15px;\n\theight\t\t: 15px;\n\tposition\t: absolute;\n\tdisplay\t\t: block;\n\tmargin\t\t: auto;\n\topacity\t\t: 0.6;\n}\n\n.canvas_resize_indicator:hover {\n\n\topacity\t\t: 1.0;\n}\n/** End Resizer **/\n\n.Oryx_down {\n\n}\n\n.Oryx_button img {\n\twidth:16px;\n\theight:16px;\n\ttop:0px;\n\tleft:0px;\n\tline-height: 16px;\n}\n\n.Oryx_Right .Oryx_button,\n.Oryx_Left .Oryx_button,\n.Oryx_Top .Oryx_button,\n.Oryx_Bottom .Oryx_button {\n\topacity: 0.5;\n}\n\n.Oryx_button.x-opacity-0 {\n\topacity: 0;\n\tdisplay:none;\n}\n\n.Oryx_button.x-opacity-10 {\n\topacity: 0.1;\n}\n\n.Oryx_button.x-opacity-20 {\n\topacity: 0.2;\n}\n\n.Oryx_button.x-opacity-50 {\n\topacity: 0.5;\n}\n\n.Oryx_Right:hover .Oryx_button,\n.Oryx_Left:hover .Oryx_button,\n.Oryx_Top:hover .Oryx_button,\n.Oryx_Bottom:hover .Oryx_button {\n\topacity: 0.7;\n\tdisplay:block;\n}\n\n\n.Oryx_button img {\n\ttop:0px;\n}\n\n.Oryx_Left img {\n\ttop:0px;\n}\n\n.Oryx_button {\n\twidth:24px;\n\theight:24px;\n\tpadding:2px;\n\tposition:absolute;\n\tbackground-color: #ffffff;\n\tbackground-color: rgba(255,255,255,0.7);\n\tcursor: pointer;\n}\n\n.Oryx_button_with_caption {\n\twidth:inherit;\n\theight:16px;\n\tpadding:4px;\n\tposition:absolute;\n}\n\n/*** Resizer ***/\n\n.resizer_southeast,\n.resizer_northwest {\n\twidth:12px;\n\theight:12px;\n\tposition:relative;\n\tbackground-color: transparent;\n\tbackground-repeat:no-repeat;\n}\n\n/*** Selection Frame ***/\n\n.Oryx_SelectionFrame{\n\tposition:absolute;\n\tborder:1px dotted gray;\n\tbackground:none;\n}\n\n.LoadingIndicator {\n    background-image: url('../../images/loading.gif');\n}\n\n.Oryx_hover, .Oryx_button:hover {\n    background-color: #999999;\n    background-color: rgba(193, 229, 238, 0.7);\n    opacity: 1 !important;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n}\n\n.ValidateButton {\n    width:24px;\n    height:24px;\n    padding:2px;\n    position:absolute;\n    cursor: pointer;\n}\n\n.ValidateButton:hover {\n    background-color: #999999;\n    background-color: rgba(193, 229, 238, 0.7);\n    opacity: 1 !important;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n}\n\n.resizer_southeast {\n    background-image:url(../../images/se-handle-dark.gif);\n    cursor: se-resize;\n    background-position: 4px 4px;\n}\n\n.resizer_northwest {\n    background-image:url(../../images/nw-handle-dark.gif);\n    cursor: nw-resize;\n    background-position: -2px -2px;\n}\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/editor/i18n/translation_de.js",
    "content": "/**\n * @author nicolas.peters\n * \n * Contains all strings for German language.\n * Version 1 - 08/29/08\n */\nif(!ORYX) var ORYX = {};\n\nif(!ORYX.I18N) ORYX.I18N = {};\n\nORYX.I18N.Language = \"de_DE\"; //Pattern <ISO language code>_<ISO country code> in lower case!\n\nif(!ORYX.I18N.Oryx) ORYX.I18N.Oryx = {};\n\nORYX.I18N.Oryx.pleaseWait = \"Editor wird geladen. Bitte warten...\";\nORYX.I18N.Oryx.notLoggedOn = \"Nicht angemeldet\";\nORYX.I18N.Oryx.noBackendDefined\t= \"Achtung! \\n Es wurde kein Repository definiert.\\n Ihr Model kann nicht geladen werden. Bitte nutzen sie eine Editor Konfiguration mit einem Speicher Plugin.\";\n\nif(!ORYX.I18N.AddDocker) ORYX.I18N.AddDocker = {};\n\nORYX.I18N.AddDocker.group = \"Docker\";\nORYX.I18N.AddDocker.add = \"Docker Hinzufügen\";\nORYX.I18N.AddDocker.addDesc = \"Fügen Sie einer Kante einen Docker hinzu, indem Sie auf die Kante klicken\";\nORYX.I18N.AddDocker.del = \"Docker Löschen\";\nORYX.I18N.AddDocker.delDesc = \"Löscht einen Docker durch Klicken auf den zu löschenden Docker\";\n\nif(!ORYX.I18N.Arrangement) ORYX.I18N.Arrangement = {};\n\nORYX.I18N.Arrangement.groupZ = \"Z-Order\";\nORYX.I18N.Arrangement.btf = \"In den Vordergrund\";\nORYX.I18N.Arrangement.btfDesc = \"In den Vordergrund\";\nORYX.I18N.Arrangement.btb = \"In den Hintergrund\";\nORYX.I18N.Arrangement.btbDesc = \"In den Hintergrund\";\nORYX.I18N.Arrangement.bf = \"Eine Ebene nach Vorne\";\nORYX.I18N.Arrangement.bfDesc = \"Eine Ebene nach Vorne\";\nORYX.I18N.Arrangement.bb = \"Eine Ebene nach Hinten\";\nORYX.I18N.Arrangement.bbDesc = \"Eine Ebene nach Hinten\";\nORYX.I18N.Arrangement.groupA = \"Alignment\";\nORYX.I18N.Arrangement.ab = \"Unten ausrichten\";\nORYX.I18N.Arrangement.abDesc = \"Unten ausrichten\";\nORYX.I18N.Arrangement.am = \"Horizontal ausrichten\";\nORYX.I18N.Arrangement.amDesc = \"Horizontal ausrichten\";\nORYX.I18N.Arrangement.at = \"Oben ausrichten\";\nORYX.I18N.Arrangement.atDesc = \"Oben ausrichten\";\nORYX.I18N.Arrangement.al = \"Links ausrichten\";\nORYX.I18N.Arrangement.alDesc = \"Links ausrichten\";\nORYX.I18N.Arrangement.ac = \"Vertikal ausrichten\";\nORYX.I18N.Arrangement.acDesc = \"Vertikal ausrichten\";\nORYX.I18N.Arrangement.ar = \"Rechts ausrichten\";\nORYX.I18N.Arrangement.arDesc = \"Rechts ausrichten\";\nORYX.I18N.Arrangement.as = \"Größenangleichung\";\nORYX.I18N.Arrangement.asDesc = \"Größenangleichung\";\n\nif(!ORYX.I18N.Edit) ORYX.I18N.Edit = {};\n\nORYX.I18N.Edit.group = \"Edit\";\nORYX.I18N.Edit.cut = \"Ausschneiden\";\nORYX.I18N.Edit.cutDesc = \"Ausschneiden der selektierten Elemente\";\nORYX.I18N.Edit.copy = \"Kopieren\";\nORYX.I18N.Edit.copyDesc = \"Kopieren der selektierten Elemente\";\nORYX.I18N.Edit.paste = \"Einfügen\";\nORYX.I18N.Edit.pasteDesc = \"Einfügen von kopierten/ausgeschnittenen Elementen\";\nORYX.I18N.Edit.del = \"Löschen\";\nORYX.I18N.Edit.delDesc = \"Löschen der selektierten Elemente\";\n\nif(!ORYX.I18N.EPCSupport) ORYX.I18N.EPCSupport = {};\n\nORYX.I18N.EPCSupport.group = \"EPC\";\nORYX.I18N.EPCSupport.exp = \"EPML Export\";\nORYX.I18N.EPCSupport.expDesc = \"Exportieren nach EPML\";\nORYX.I18N.EPCSupport.imp = \"EPML Import\";\nORYX.I18N.EPCSupport.impDesc = \"Importieren einer EPML Datei\";\nORYX.I18N.EPCSupport.progressExp = \"Exportiere Modell\";\nORYX.I18N.EPCSupport.selectFile = \"Wählen Sie eine EPML Datei aus, die Sie importieren möchten.\";\nORYX.I18N.EPCSupport.file = \"Datei\";\nORYX.I18N.EPCSupport.impPanel = \"EPML Datei importieren\";\nORYX.I18N.EPCSupport.impBtn = \"Importieren\";\nORYX.I18N.EPCSupport.close = \"Schließen\";\nORYX.I18N.EPCSupport.error = \"Fehler\";\nORYX.I18N.EPCSupport.progressImp = \"Importiere...\";\n\nif(!ORYX.I18N.ERDFSupport) ORYX.I18N.ERDFSupport = {};\n\nORYX.I18N.ERDFSupport.exp = \"ERDF Export\";\nORYX.I18N.ERDFSupport.expDesc = \"Exportieren nach ERDF\";\nORYX.I18N.ERDFSupport.imp = \"ERDF Import\";\nORYX.I18N.ERDFSupport.impDesc = \"ERDF Datei importieren\";\nORYX.I18N.ERDFSupport.impFailed = \"Anfrage für den Import der ERDF Datei ist fehlgeschlagen.\";\nORYX.I18N.ERDFSupport.impFailed2 = \"Während des Importierens ist ein Fehler aufgetreten. <br/>Fehlermeldung: <br/><br/>\";\nORYX.I18N.ERDFSupport.error = \"Fehler\";\nORYX.I18N.ERDFSupport.noCanvas = \"Das XML Dokument enthält keinen Oryx Canvas Knoten.\";\nORYX.I18N.ERDFSupport.noSS = \"Im XML Dokument ist kein Stencil Set referenziert.\";\nORYX.I18N.ERDFSupport.wrongSS = \"Das im XML Dokument referenzierte Stencil Set passt nicht zu dem im Editor geladenen Stencil Set.\";\nORYX.I18N.ERDFSupport.selectFile = \"Wählen sie eine ERDF Datei (.xml) aus oder geben Sie den ERDF Code im Textfeld ein.\";\nORYX.I18N.ERDFSupport.file = \"Datei\";\nORYX.I18N.ERDFSupport.impERDF = \"ERDF importieren\";\nORYX.I18N.ERDFSupport.impBtn = \"Importieren\";\nORYX.I18N.ERDFSupport.impProgress = \"Importiere...\";\nORYX.I18N.ERDFSupport.close = \"Schließen\";\nORYX.I18N.ERDFSupport.deprTitle = \"Wirklich nach eRDF exportieren?\";\nORYX.I18N.ERDFSupport.deprText = \"Der Export nach eRDF wird nicht empfohlen, da dieses Format in zukünftigen Versionen des Oryx Editors nicht mehr unterstützt wird. Verwenden Sie statt dessen den Export nach JSON, falls möglich. Wollen Sie dennoch das Model nach eRDF exportieren?\";\n\nif(!ORYX.I18N.jPDLSupport) ORYX.I18N.jPDLSupport = {};\n\nORYX.I18N.jPDLSupport.group = \"ExecBPMN\";\nORYX.I18N.jPDLSupport.exp = \"jPDL Export\";\nORYX.I18N.jPDLSupport.expDesc = \"Exportieren nach jPDL\";\nORYX.I18N.jPDLSupport.imp = \"jPDL Import\";\nORYX.I18N.jPDLSupport.impDesc = \"jPDL Datei importieren\";\nORYX.I18N.jPDLSupport.impFailedReq = \"Anfrage für den Import der jPDL Datei ist fehlgeschlagen.\";\nORYX.I18N.jPDLSupport.impFailedJson = \"Transformation der jPDL Datei ist fehlgeschlagen.\";\nORYX.I18N.jPDLSupport.impFailedJsonAbort = \"Import abgebrochen.\";\nORYX.I18N.jPDLSupport.loadSseQuestionTitle = \"Stencil Set Erweiterung für jBPM muss geladen werden\"; \nORYX.I18N.jPDLSupport.loadSseQuestionBody = \"Um jPDL importieren zu können, muss die Stencil Set Erweiterung für jBPM geladen werden. Möchten Sie fortfahren?\";\nORYX.I18N.jPDLSupport.expFailedReq = \"Anfrage für den Export des Models ist fehlgeschlagen.\";\nORYX.I18N.jPDLSupport.expFailedXml = \"Export nach jPDL ist fehlgeschlagen. Exporter meldet: \";\nORYX.I18N.jPDLSupport.error = \"Fehler\";\nORYX.I18N.jPDLSupport.selectFile = \"Wählen sie eine jPDL Datei (.xml) aus oder geben Sie den jPDL Code im Textfeld ein.\";\nORYX.I18N.jPDLSupport.file = \"Datei\";\nORYX.I18N.jPDLSupport.impJPDL = \"jPDL importieren\";\nORYX.I18N.jPDLSupport.impBtn = \"Importieren\";\nORYX.I18N.jPDLSupport.impProgress = \"Importiere...\";\nORYX.I18N.jPDLSupport.close = \"Schließen\";\n\nif(!ORYX.I18N.Save) ORYX.I18N.Save = {};\n\nORYX.I18N.Save.group = \"File\";\nORYX.I18N.Save.save = \"Speichern\";\nORYX.I18N.Save.saveDesc = \"Speichern\";\nORYX.I18N.Save.saveAs = \"Speichern als...\";\nORYX.I18N.Save.saveAsDesc = \"Speichern als...\";\nORYX.I18N.Save.unsavedData = \"Das Diagramm enthält nicht gespeicherte Daten. Sind Sie sicher, daß Sie den Editor schließen möchten?\";\nORYX.I18N.Save.newProcess = \"Neuer Prozess\";\nORYX.I18N.Save.saveAsTitle = \"Speichern als...\";\nORYX.I18N.Save.saveBtn = \"Speichern\";\nORYX.I18N.Save.close = \"Schließen\";\nORYX.I18N.Save.savedAs = \"Gespeichert als\";\nORYX.I18N.Save.saved = \"Gespeichert\";\nORYX.I18N.Save.failed = \"Das Speichern ist fehlgeschlagen.\";\nORYX.I18N.Save.noRights = \"Sie haben nicht die erforderlichen Rechte, um Änderungen zu speichern.\";\nORYX.I18N.Save.saving = \"Speichern\";\nORYX.I18N.Save.saveAsHint = \"Das Diagramm wurde unter folgendem Link gespeichert:\";\n\nif(!ORYX.I18N.File) ORYX.I18N.File = {};\n\nORYX.I18N.File.group = \"File\";\nORYX.I18N.File.print = \"Drucken\";\nORYX.I18N.File.printDesc = \"Drucken\";\nORYX.I18N.File.pdf = \"PDF Export\";\nORYX.I18N.File.pdfDesc = \"Exportieren nach PDF\";\nORYX.I18N.File.info = \"Über\";\nORYX.I18N.File.infoDesc = \"Über\";\nORYX.I18N.File.genPDF = \"PDF wird generiert\";\nORYX.I18N.File.genPDFFailed = \"Die Generierung der PDF Datei ist fehlgeschlagen.\";\nORYX.I18N.File.printTitle = \"Drucken\";\nORYX.I18N.File.printMsg = \"Leider arbeitet die Druckfunktion zur Zeit nicht immer korrekt. Bitte nutzen Sie den PDF Export, und drucken Sie das PDF Dokument aus. Möchten Sie dennoch mit dem Drucken fortfahren?\";\n\nif(!ORYX.I18N.Grouping) ORYX.I18N.Grouping = {};\n\nORYX.I18N.Grouping.grouping = \"Grouping\";\nORYX.I18N.Grouping.group = \"Gruppieren\";\nORYX.I18N.Grouping.groupDesc = \"Gruppierung der selektierten Elemente\";\nORYX.I18N.Grouping.ungroup = \"Gruppierung aufheben\";\nORYX.I18N.Grouping.ungroupDesc = \"Aufheben aller Gruppierungen der selektierten Elemente\";\n\nif(!ORYX.I18N.Loading) ORYX.I18N.Loading = {};\n\nORYX.I18N.Loading.waiting =\"Bitte warten...\";\n\nif(!ORYX.I18N.PropertyWindow) ORYX.I18N.PropertyWindow = {};\n\nORYX.I18N.PropertyWindow.name = \"Name\";\nORYX.I18N.PropertyWindow.value = \"Wert\";\nORYX.I18N.PropertyWindow.selected = \"ausgewählt\";\nORYX.I18N.PropertyWindow.clickIcon = \"Symbol anklicken\";\nORYX.I18N.PropertyWindow.add = \"Hinzufügen\";\nORYX.I18N.PropertyWindow.rem = \"Löschen\";\nORYX.I18N.PropertyWindow.complex = \"Editor für komplexe Eigenschaft\";\nORYX.I18N.PropertyWindow.text = \"Editor für einen Text\";\nORYX.I18N.PropertyWindow.ok = \"Ok\";\nORYX.I18N.PropertyWindow.cancel = \"Abbrechen\";\nORYX.I18N.PropertyWindow.dateFormat = \"d/m/y\";\n\nif(!ORYX.I18N.ShapeMenuPlugin) ORYX.I18N.ShapeMenuPlugin = {};\n\nORYX.I18N.ShapeMenuPlugin.drag = \"Ziehen\";\nORYX.I18N.ShapeMenuPlugin.clickDrag = \"Klicken oder ziehen\";\nORYX.I18N.ShapeMenuPlugin.morphMsg = \"Shape morphen\";\n\nif(!ORYX.I18N.SyntaxChecker) ORYX.I18N.SyntaxChecker = {};\n\nORYX.I18N.SyntaxChecker.group = \"Verification\";\nORYX.I18N.SyntaxChecker.name = \"Syntax-Checker\";\nORYX.I18N.SyntaxChecker.desc = \"Überprüfung der Syntax\";\nORYX.I18N.SyntaxChecker.noErrors = \"Es wurden keine Syntaxfehler gefunden.\";\nORYX.I18N.SyntaxChecker.invalid = \"Ungültige Antwort vom Server.\";\nORYX.I18N.SyntaxChecker.checkingMessage = \"Überprüfung wird durchgeführt ...\";\n\nif(!ORYX.I18N.Undo) ORYX.I18N.Undo = {};\n\nORYX.I18N.Undo.group = \"Undo\";\nORYX.I18N.Undo.undo = \"Rückgängig\";\nORYX.I18N.Undo.undoDesc = \"Rückgängig\";\nORYX.I18N.Undo.redo = \"Wiederherstellen\";\nORYX.I18N.Undo.redoDesc = \"Wiederherstellen\";\n\nif(!ORYX.I18N.View) ORYX.I18N.View = {};\n\nORYX.I18N.View.group = \"Zoom\";\nORYX.I18N.View.zoomIn = \"Vergrößern\";\nORYX.I18N.View.zoomInDesc = \"Vergrößern\";\nORYX.I18N.View.zoomOut = \"Verkleinern\";\nORYX.I18N.View.zoomOutDesc = \"Verkleinern\";\nORYX.I18N.View.zoomStandard = \"Originalgröße\";\nORYX.I18N.View.zoomStandardDesc = \"Originalgröße\";\nORYX.I18N.View.zoomFitToModel = \"Modelgröße\";\nORYX.I18N.View.zoomFitToModelDesc = \"Modelgröße\";\n\n/** New Language Properties: 08.12.2008 **/\n\nORYX.I18N.PropertyWindow.title = \"Eigenschaften\";\n\nif(!ORYX.I18N.ShapeRepository) ORYX.I18N.ShapeRepository = {};\nORYX.I18N.ShapeRepository.title = \"Shape Verzeichnis\";\n\nORYX.I18N.Save.dialogDesciption = \"Bitte geben Sie einen Namen, eine Beschreibung und einen Kommentar ein.\";\nORYX.I18N.Save.dialogLabelTitle = \"Titel\";\nORYX.I18N.Save.dialogLabelDesc = \"Beschreibung\";\nORYX.I18N.Save.dialogLabelType = \"Typ\";\nORYX.I18N.Save.dialogLabelComment = \"Revisionskommentar\";\n\nif(!ORYX.I18N.Perspective) ORYX.I18N.Perspective = {};\nORYX.I18N.Perspective.no = \"Keine Perspektive\"\nORYX.I18N.Perspective.noTip = \"Zurücksetzen der aktuellen Perspektive\"\n\n/** New Language Properties: 21.04.2009 */\nORYX.I18N.JSONSupport = {\n    imp: {\n        name: \"JSON importieren\",\n        desc: \"Importiert ein neues Modell aus JSON\",\n        group: \"Export\",\n        selectFile: \"Wählen Sie eine JSON-Datei (*.json) aus, die Sie importieren möchten, oder fügen Sie JSON in das Textfeld ein.\",\n        file: \"Datei\",\n        btnImp: \"Importieren\",\n        btnClose: \"Schließen\",\n        progress: \"Importieren ...\",\n        syntaxError: \"Syntaxfehler\"\n    },\n    exp: {\n        name: \"Nach JSON exportieren\",\n        desc: \"Exportiert das aktuelle Modell nach JSON\",\n        group: \"Export\"\n    }\n};\n\n/** New Language Properties: 09.05.2009 */\nif(!ORYX.I18N.JSONImport) ORYX.I18N.JSONImport = {};\n\nORYX.I18N.JSONImport.title = \"JSON Import\";\nORYX.I18N.JSONImport.wrongSS = \"Das Stencil Set der importierten Datei ({0}) entspricht nicht dem geladenen Stencil Set ({1}).\"\n\n/** New Language Properties: 14.05.2009 */\nif(!ORYX.I18N.RDFExport) ORYX.I18N.RDFExport = {};\nORYX.I18N.RDFExport.group = \"Export\";\nORYX.I18N.RDFExport.rdfExport = \"Nach RDF exportieren\";\nORYX.I18N.RDFExport.rdfExportDescription = \"Exportiert das aktuelle Model in die XML-Serialisierung des Resource Description Frameworks (RDF)\";\n\n/** New Language Properties: 15.05.2009*/\nif(!ORYX.I18N.SyntaxChecker.BPMN) ORYX.I18N.SyntaxChecker.BPMN={};\nORYX.I18N.SyntaxChecker.BPMN_NO_SOURCE = \"Eine Kante muss einen Ursprung haben.\";\nORYX.I18N.SyntaxChecker.BPMN_NO_TARGET = \"Eine Kante muss ein Ziel haben.\";\nORYX.I18N.SyntaxChecker.BPMN_DIFFERENT_PROCESS = \"Ursprungs- und Zielknoten müssen im gleichen Prozess sein.\";\nORYX.I18N.SyntaxChecker.BPMN_SAME_PROCESS = \"Ursprungs- und Zielknoten müssen in verschiedenen Pools enthalten sein.\";\nORYX.I18N.SyntaxChecker.BPMN_FLOWOBJECT_NOT_CONTAINED_IN_PROCESS = \"Ein Kontrollflussobjekt muss sich in einem Prozess befinden.\";\nORYX.I18N.SyntaxChecker.BPMN_ENDEVENT_WITHOUT_INCOMING_CONTROL_FLOW = \"Ein End-Ereignis muss einen eingehenden Sequenzfluss haben.\";\nORYX.I18N.SyntaxChecker.BPMN_STARTEVENT_WITHOUT_OUTGOING_CONTROL_FLOW = \"Ein Start-Ereignis muss einen ausgehenden Sequenzfluss haben.\";\nORYX.I18N.SyntaxChecker.BPMN_STARTEVENT_WITH_INCOMING_CONTROL_FLOW = \"Start-Ereignisse dürfen keinen eingehenden Sequenzfluss haben.\";\nORYX.I18N.SyntaxChecker.BPMN_ATTACHEDINTERMEDIATEEVENT_WITH_INCOMING_CONTROL_FLOW = \"Angeheftete Zwischen-Ereignisse dürfen keinen eingehenden Sequenzfluss haben.\";\nORYX.I18N.SyntaxChecker.BPMN_ATTACHEDINTERMEDIATEEVENT_WITHOUT_OUTGOING_CONTROL_FLOW = \"Angeheftete Zwischen-Ereignisse müssen genau einen ausgehenden Sequenzfluss haben.\";\nORYX.I18N.SyntaxChecker.BPMN_ENDEVENT_WITH_OUTGOING_CONTROL_FLOW = \"End-Ereignisse dürfen keinen ausgehenden Sequenzfluss haben.\";\nORYX.I18N.SyntaxChecker.BPMN_EVENTBASEDGATEWAY_BADCONTINUATION = \"Auf Ereignis-basierte Gateways dürfen weder Gateways noch Subprozesse folgen.\";\nORYX.I18N.SyntaxChecker.BPMN_NODE_NOT_ALLOWED = \"Knotentyp ist nicht erlaubt.\";\n\nif(!ORYX.I18N.SyntaxChecker.IBPMN) ORYX.I18N.SyntaxChecker.IBPMN={};\nORYX.I18N.SyntaxChecker.IBPMN_NO_ROLE_SET = \"Für Interaktionen muss ein Sender und ein Empfänger definiert sein.\";\nORYX.I18N.SyntaxChecker.IBPMN_NO_INCOMING_SEQFLOW = \"Dieser Knoten muss eingehenden Sequenzfluss besitzen.\";\nORYX.I18N.SyntaxChecker.IBPMN_NO_OUTGOING_SEQFLOW = \"Dieser Knoten muss ausgehenden Sequenzfluss besitzen.\";\n\nif(!ORYX.I18N.SyntaxChecker.InteractionNet) ORYX.I18N.SyntaxChecker.InteractionNet={};\nORYX.I18N.SyntaxChecker.InteractionNet_SENDER_NOT_SET = \"Sender ist nicht definiert\";\nORYX.I18N.SyntaxChecker.InteractionNet_RECEIVER_NOT_SET = \"Empfänger ist nicht definiert\";\nORYX.I18N.SyntaxChecker.InteractionNet_MESSAGETYPE_NOT_SET = \"Nachrichtentyp ist nicht definiert.\";\nORYX.I18N.SyntaxChecker.InteractionNet_ROLE_NOT_SET = \"Rolle ist nicht definiert.\";\n\nif(!ORYX.I18N.SyntaxChecker.EPC) ORYX.I18N.SyntaxChecker.EPC={};\nORYX.I18N.SyntaxChecker.EPC_NO_SOURCE = \"Eine Kante muss einen Ursprung haben.\";\nORYX.I18N.SyntaxChecker.EPC_NO_TARGET = \"Eine Kante muss ein Ziel haben.\";\nORYX.I18N.SyntaxChecker.EPC_NOT_CONNECTED = \"Dieser Knoten muss eingehende oder ausgehende Kanten besitzen.\";\nORYX.I18N.SyntaxChecker.EPC_NOT_CONNECTED_2 = \"Dieser Knoten muss sowohl eingehende als auch ausgehende Kanten besitzen.\";\nORYX.I18N.SyntaxChecker.EPC_TOO_MANY_EDGES = \"Knoten ist mit zu vielen Kanten verbunden.\";\nORYX.I18N.SyntaxChecker.EPC_NO_CORRECT_CONNECTOR = \"Knoten ist kein korrekter Konnektor.\";\nORYX.I18N.SyntaxChecker.EPC_MANY_STARTS = \"Es darf nur ein Start-Ereignis geben.\";\nORYX.I18N.SyntaxChecker.EPC_FUNCTION_AFTER_OR = \"Funktionen hinter einem OR-/XOR-Split sind nicht erlaubt.\";\nORYX.I18N.SyntaxChecker.EPC_PI_AFTER_OR = \"Prozessschnittstellen hinter einem OR-/XOR-Split ist nicht erlaubt.\";\nORYX.I18N.SyntaxChecker.EPC_FUNCTION_AFTER_FUNCTION =  \"Auf eine Funktion darf keine Funktion folgen.\";\nORYX.I18N.SyntaxChecker.EPC_EVENT_AFTER_EVENT =  \"Auf ein Ereignis darf kein Ereignis folgen.\";\nORYX.I18N.SyntaxChecker.EPC_PI_AFTER_FUNCTION =  \"Auf eine Funktion darf keine Prozessschnittstelle folgen.\";\nORYX.I18N.SyntaxChecker.EPC_FUNCTION_AFTER_PI =  \"Auf eine Prozessschnittstelle darf keine Funktion folgen.\";\nORYX.I18N.SyntaxChecker.EPC_SOURCE_EQUALS_TARGET = \"Eine Kante muss zwei verschiedene Knoten verbinden.\"\n\nif(!ORYX.I18N.SyntaxChecker.PetriNet) ORYX.I18N.SyntaxChecker.PetriNet={};\nORYX.I18N.SyntaxChecker.PetriNet_NOT_BIPARTITE = \"Der Graph ist nicht bepartit.\";\nORYX.I18N.SyntaxChecker.PetriNet_NO_LABEL = \"Bezeichnung für einen bezeichnete Transition ist nicht gesetzt.\";\nORYX.I18N.SyntaxChecker.PetriNet_NO_ID = \"Ein Knoten besitzt keine ID.\";\nORYX.I18N.SyntaxChecker.PetriNet_SAME_SOURCE_AND_TARGET = \"Zwei Flussbeziehungen besitzen den gleichen Ursprung und das gleiche Ziel.\";\nORYX.I18N.SyntaxChecker.PetriNet_NODE_NOT_SET = \"Ein Knoten ist nicht definiert für einen Flussbeziehung.\";\n\n/** New Language Properties: 02.06.2009*/\nORYX.I18N.Edge = \"Kante\";\nORYX.I18N.Node = \"Knoten\";\n\n/** New Language Properties: 02.06.2009*/\nORYX.I18N.SyntaxChecker.notice = \"Bitte bewegen Sie den Mauszeiger über ein rotes Kreuz, um die Details zu erfahren.\";\n\n/** New Language Properties: 15.07.2009*/\nif(!ORYX.I18N.Layouting) ORYX.I18N.Layouting ={};\nORYX.I18N.Layouting.doing = \"Layouten...\";\n\n/** New Language Properties: 18.08.2009*/\nORYX.I18N.SyntaxChecker.MULT_ERRORS = \"Mehrere Fehler\";\n\n/** New Language Properties: 08.09.2009*/\nif(!ORYX.I18N.PropertyWindow) ORYX.I18N.PropertyWindow = {};\nORYX.I18N.PropertyWindow.oftenUsed = \"Hauptattribute\";\nORYX.I18N.PropertyWindow.moreProps = \"Mehr Attribute\";\n\n/** New Language Properties 01.10.2009 */\nif(!ORYX.I18N.SyntaxChecker.BPMN2) ORYX.I18N.SyntaxChecker.BPMN2 = {};\n\nORYX.I18N.SyntaxChecker.BPMN2_DATA_INPUT_WITH_INCOMING_DATA_ASSOCIATION = \"Ein Dateninput darf keine ausgehenden Datenassoziationen haben.\";\nORYX.I18N.SyntaxChecker.BPMN2_DATA_OUTPUT_WITH_OUTGOING_DATA_ASSOCIATION = \"Ein Datenoutput darf keine eingehenden Datenassoziationen haben.\";\nORYX.I18N.SyntaxChecker.BPMN2_EVENT_BASED_TARGET_WITH_TOO_MANY_INCOMING_SEQUENCE_FLOWS = \"Ziele von Ereignis-basierten Gateways dürfen nicht mehr als einen eingehenden Sequenzfluss haben.\";\n\n/** New Language Properties 02.10.2009 */\nORYX.I18N.SyntaxChecker.BPMN2_EVENT_BASED_WITH_TOO_LESS_OUTGOING_SEQUENCE_FLOWS = \"Ein Ereignis-basiertes Gateway muss 2 oder mehr ausgehende Sequenzflüsse besitzen.\";\nORYX.I18N.SyntaxChecker.BPMN2_EVENT_BASED_EVENT_TARGET_CONTRADICTION = \"Wenn Nachrichten-Zwischenereignisse im Diagramm verwendet werden, dann dürfen Receive Tasks nicht verwendet werden und umgekehrt.\";\nORYX.I18N.SyntaxChecker.BPMN2_EVENT_BASED_WRONG_TRIGGER = \"Nur die folgenden Zwischen-Ereignis-Auslöser sind hier zulässig: Nachricht, Signal, Timer, Bedingungs und Mehrfach.\";\nORYX.I18N.SyntaxChecker.BPMN2_EVENT_BASED_WRONG_CONDITION_EXPRESSION = \"Die ausgehenden Sequenzflüsse eines Ereignis-Gateways dürfen keinen Bedingungsausdruck besitzen.\";\nORYX.I18N.SyntaxChecker.BPMN2_EVENT_BASED_NOT_INSTANTIATING = \"Das Gateway erfüllt nicht die Voraussetzungen um den Prozess zu instantiieren. Bitte verwenden Sie ein Start-Ereignis oder setzen Sie die Instanziierungs-Attribute korrekt.\";\n\n/** New Language Properties 05.10.2009 */\nORYX.I18N.SyntaxChecker.BPMN2_GATEWAYDIRECTION_MIXED_FAILURE = \"Das Gateway muss mehrere eingehende und ausgehende Sequenzflüsse besitzen.\";\nORYX.I18N.SyntaxChecker.BPMN2_GATEWAYDIRECTION_CONVERGING_FAILURE = \"Das Gateway muss mehrere eingehende aber darf keine mehrfache ausgehende Sequenzflüsse besitzen.\";\nORYX.I18N.SyntaxChecker.BPMN2_GATEWAYDIRECTION_DIVERGING_FAILURE = \"Das Gateway darf keine mehrfachen eingehenden aber muss mehrfache ausgehende Sequenzflüsse besitzen.\";\nORYX.I18N.SyntaxChecker.BPMN2_GATEWAY_WITH_NO_OUTGOING_SEQUENCE_FLOW = \"Ein Gateway muss mindestens einen ausgehenden Sequenzfluss besitzen.\";\nORYX.I18N.SyntaxChecker.BPMN2_RECEIVE_TASK_WITH_ATTACHED_EVENT = \"Empfangende Tasks, die in Ereignis-Gateway-Konfigurationen benutzt werden, dürfen keine angehefteten Zwischen-Ereignisse besitzen.\";\nORYX.I18N.SyntaxChecker.BPMN2_EVENT_SUBPROCESS_BAD_CONNECTION = \"Ein Ereignis-Unterprozess darf keinen eingehenden oder ausgehenden Sequenzfluss besitzen.\";\n\n/** New Language Properties 13.10.2009 */\nORYX.I18N.SyntaxChecker.BPMN_MESSAGE_FLOW_NOT_CONNECTED = \"Mindestens ein Ende des Nachrichtenflusses muss mit einem anderen Objekt verbunden sein.\";\n\n/** New Language Properties 05.11.2009 */\nif(!ORYX.I18N.RESIZE) ORYX.I18N.RESIZE = {};\nORYX.I18N.RESIZE.tipGrow = \"Zeichenfläche vergrößern:\";\nORYX.I18N.RESIZE.tipShrink = \"Zeichenfläche verkleinern:\";\nORYX.I18N.RESIZE.N = \"Nach oben\";\nORYX.I18N.RESIZE.W = \"Nach links\";\nORYX.I18N.RESIZE.S =\"Nach unten\";\nORYX.I18N.RESIZE.E =\"Nach rechts\";\n\n/** New Language Properties 24.11.2009 */\nORYX.I18N.SyntaxChecker.BPMN2_TOO_MANY_INITIATING_MESSAGES = \"Eine Choreographie-Aktivität darf nur eine initiierende Nachricht besitzen.\";\nORYX.I18N.SyntaxChecker.BPMN_MESSAGE_FLOW_NOT_ALLOWED = \"Ein Nachrichtenfluss ist an dieser Stelle nicht erlaubt.\";\n\n/** New Language Properties 27.11.2009 */\nORYX.I18N.SyntaxChecker.BPMN2_EVENT_BASED_WITH_TOO_LESS_INCOMING_SEQUENCE_FLOWS = \"Ein Ereignis-basiertes Gateway, dass nicht instanziierend ist, muss mindestens einen eingehenden Kontrollfluss besitzen.\";\nORYX.I18N.SyntaxChecker.BPMN2_TOO_FEW_INITIATING_PARTICIPANTS = \"Eine Choreographie-Aktivität musst genau einen initiierenden Teilnehmer (weiß) besitzen.\";\nORYX.I18N.SyntaxChecker.BPMN2_TOO_MANY_INITIATING_PARTICIPANTS = \"Eine Choreographie-Aktivität darf nicht mehr als einen initiierenden Teilnehmer (weiß) besitzen.\"\n\nORYX.I18N.SyntaxChecker.COMMUNICATION_AT_LEAST_TWO_PARTICIPANTS = \"Die Kommunikation oder Sub-Konversation muss mit mindestens zwei Teilnehmern verbunden sein.\";\nORYX.I18N.SyntaxChecker.MESSAGEFLOW_START_MUST_BE_PARTICIPANT = \"Die Nachrichtenflussquelle muss ein Teilnehmer sein.\";\nORYX.I18N.SyntaxChecker.MESSAGEFLOW_END_MUST_BE_PARTICIPANT = \"Das Nachrichtenflussziel muss ein Teilnehmer sein.\";\nORYX.I18N.SyntaxChecker.CONV_LINK_CANNOT_CONNECT_CONV_NODES = \"Der Konversationslink muss eine Kommunikation oder Sub-Konversation mit einem Teilnehmer verbinden.\";\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/editor/i18n/translation_en_us.js",
    "content": "/**\n * @author nicolas.peters\n * \n * Contains all strings for the default language (en-us).\n * Version 1 - 08/29/08\n */\nif(!ORYX) var ORYX = {};\n\nif(!ORYX.I18N) ORYX.I18N = {};\n\nORYX.I18N.Language = \"en_us\"; //Pattern <ISO language code>_<ISO country code> in lower case!\n\nif(!ORYX.I18N.Oryx) ORYX.I18N.Oryx = {};\n\nORYX.I18N.Oryx.title\t\t= \"Oryx\";\nORYX.I18N.Oryx.noBackendDefined\t= \"Caution! \\nNo Backend defined.\\n The requested model cannot be loaded. Try to load a configuration with a save plugin.\";\nORYX.I18N.Oryx.pleaseWait \t= \"Please wait while loading...\";\nORYX.I18N.Oryx.notLoggedOn = \"Not logged on\";\nORYX.I18N.Oryx.editorOpenTimeout = \"The editor does not seem to be started yet. Please check, whether you have a popup blocker enabled and disable it or allow popups for this site. We will never display any commercials on this site.\";\n\nif(!ORYX.I18N.AddDocker) ORYX.I18N.AddDocker = {};\n\nORYX.I18N.AddDocker.group = \"Docker\";\nORYX.I18N.AddDocker.add = \"Add Docker\";\nORYX.I18N.AddDocker.addDesc = \"Add a Docker to an edge, by clicking on it\";\nORYX.I18N.AddDocker.del = \"Delete Docker\";\nORYX.I18N.AddDocker.delDesc = \"Delete a Docker\";\n\nif(!ORYX.I18N.Arrangement) ORYX.I18N.Arrangement = {};\n\nORYX.I18N.Arrangement.groupZ = \"Z-Order\";\nORYX.I18N.Arrangement.btf = \"Bring To Front\";\nORYX.I18N.Arrangement.btfDesc = \"Bring to Front\";\nORYX.I18N.Arrangement.btb = \"Bring To Back\";\nORYX.I18N.Arrangement.btbDesc = \"Bring To Back\";\nORYX.I18N.Arrangement.bf = \"Bring Forward\";\nORYX.I18N.Arrangement.bfDesc = \"Bring Forward\";\nORYX.I18N.Arrangement.bb = \"Bring Backward\";\nORYX.I18N.Arrangement.bbDesc = \"Bring Backward\";\nORYX.I18N.Arrangement.groupA = \"Alignment\";\nORYX.I18N.Arrangement.ab = \"Alignment Bottom\";\nORYX.I18N.Arrangement.abDesc = \"Bottom\";\nORYX.I18N.Arrangement.am = \"Alignment Middle\";\nORYX.I18N.Arrangement.amDesc = \"Middle\";\nORYX.I18N.Arrangement.at = \"Alignment Top\";\nORYX.I18N.Arrangement.atDesc = \"Top\";\nORYX.I18N.Arrangement.al = \"Alignment Left\";\nORYX.I18N.Arrangement.alDesc = \"Left\";\nORYX.I18N.Arrangement.ac = \"Alignment Center\";\nORYX.I18N.Arrangement.acDesc = \"Center\";\nORYX.I18N.Arrangement.ar = \"Alignment Right\";\nORYX.I18N.Arrangement.arDesc = \"Right\";\nORYX.I18N.Arrangement.as = \"Alignment Same Size\";\nORYX.I18N.Arrangement.asDesc = \"Same Size\";\n\nif(!ORYX.I18N.Edit) ORYX.I18N.Edit = {};\n\nORYX.I18N.Edit.group = \"Edit\";\nORYX.I18N.Edit.cut = \"Cut\";\nORYX.I18N.Edit.cutDesc = \"Cuts the selection into an Oryx clipboard\";\nORYX.I18N.Edit.copy = \"Copy\";\nORYX.I18N.Edit.copyDesc = \"Copies the selection into an Oryx clipboard\";\nORYX.I18N.Edit.paste = \"Paste\";\nORYX.I18N.Edit.pasteDesc = \"Pastes the Oryx clipboard to the canvas\";\nORYX.I18N.Edit.del = \"Delete\";\nORYX.I18N.Edit.delDesc = \"Deletes all selected shapes\";\n\nif(!ORYX.I18N.EPCSupport) ORYX.I18N.EPCSupport = {};\n\nORYX.I18N.EPCSupport.group = \"EPC\";\nORYX.I18N.EPCSupport.exp = \"Export EPC\";\nORYX.I18N.EPCSupport.expDesc = \"Export diagram to EPML\";\nORYX.I18N.EPCSupport.imp = \"Import EPC\";\nORYX.I18N.EPCSupport.impDesc = \"Import an EPML file\";\nORYX.I18N.EPCSupport.progressExp = \"Exporting model\";\nORYX.I18N.EPCSupport.selectFile = \"Select an EPML (.empl) file to import.\";\nORYX.I18N.EPCSupport.file = \"File\";\nORYX.I18N.EPCSupport.impPanel = \"Import EPML File\";\nORYX.I18N.EPCSupport.impBtn = \"Import\";\nORYX.I18N.EPCSupport.close = \"Close\";\nORYX.I18N.EPCSupport.error = \"Error\";\nORYX.I18N.EPCSupport.progressImp = \"Import...\";\n\nif(!ORYX.I18N.ERDFSupport) ORYX.I18N.ERDFSupport = {};\n\nORYX.I18N.ERDFSupport.exp = \"Export to ERDF\";\nORYX.I18N.ERDFSupport.expDesc = \"Export to ERDF\";\nORYX.I18N.ERDFSupport.imp = \"Import from ERDF\";\nORYX.I18N.ERDFSupport.impDesc = \"Import from ERDF\";\nORYX.I18N.ERDFSupport.impFailed = \"Request for import of ERDF failed.\";\nORYX.I18N.ERDFSupport.impFailed2 = \"An error while importing occurs! <br/>Please check error message: <br/><br/>\";\nORYX.I18N.ERDFSupport.error = \"Error\";\nORYX.I18N.ERDFSupport.noCanvas = \"The xml document has no Oryx canvas node included!\";\nORYX.I18N.ERDFSupport.noSS = \"The Oryx canvas node has no stencil set definition included!\";\nORYX.I18N.ERDFSupport.wrongSS = \"The given stencil set does not fit to the current editor!\";\nORYX.I18N.ERDFSupport.selectFile = \"Select an ERDF (.xml) file or type in the ERDF to import it!\";\nORYX.I18N.ERDFSupport.file = \"File\";\nORYX.I18N.ERDFSupport.impERDF = \"Import ERDF\";\nORYX.I18N.ERDFSupport.impBtn = \"Import\";\nORYX.I18N.ERDFSupport.impProgress = \"Importing...\";\nORYX.I18N.ERDFSupport.close = \"Close\";\nORYX.I18N.ERDFSupport.deprTitle = \"Really export to eRDF?\";\nORYX.I18N.ERDFSupport.deprText = \"Exporting to eRDF is not recommended anymore because the support will be stopped in future versions of the Oryx editor. If possible, export the model to JSON. Do you want to export anyway?\";\n\nif(!ORYX.I18N.jPDLSupport) ORYX.I18N.jPDLSupport = {};\n\nORYX.I18N.jPDLSupport.group = \"ExecBPMN\";\nORYX.I18N.jPDLSupport.exp = \"Export to jPDL\";\nORYX.I18N.jPDLSupport.expDesc = \"Export to jPDL\";\nORYX.I18N.jPDLSupport.imp = \"Import from jPDL\";\nORYX.I18N.jPDLSupport.impDesc = \"Import jPDL File\";\nORYX.I18N.jPDLSupport.impFailedReq = \"Request for import of jPDL failed.\";\nORYX.I18N.jPDLSupport.impFailedJson = \"Transformation of jPDL failed.\";\nORYX.I18N.jPDLSupport.impFailedJsonAbort = \"Import aborted.\";\nORYX.I18N.jPDLSupport.loadSseQuestionTitle = \"jBPM stencil set extension needs to be loaded\"; \nORYX.I18N.jPDLSupport.loadSseQuestionBody = \"In order to import jPDL, the stencil set extension has to be loaded. Do you want to proceed?\";\nORYX.I18N.jPDLSupport.expFailedReq = \"Request for export of model failed.\";\nORYX.I18N.jPDLSupport.expFailedXml = \"Export to jPDL failed. Exporter reported: \";\nORYX.I18N.jPDLSupport.error = \"Error\";\nORYX.I18N.jPDLSupport.selectFile = \"Select an jPDL (.xml) file or type in the jPDL to import it!\";\nORYX.I18N.jPDLSupport.file = \"File\";\nORYX.I18N.jPDLSupport.impJPDL = \"Import jPDL\";\nORYX.I18N.jPDLSupport.impBtn = \"Import\";\nORYX.I18N.jPDLSupport.impProgress = \"Importing...\";\nORYX.I18N.jPDLSupport.close = \"Close\";\n\nif(!ORYX.I18N.Save) ORYX.I18N.Save = {};\n\nORYX.I18N.Save.group = \"File\";\nORYX.I18N.Save.save = \"Save\";\nORYX.I18N.Save.saveDesc = \"Save\";\nORYX.I18N.Save.saveAs = \"Save As...\";\nORYX.I18N.Save.saveAsDesc = \"Save As...\";\nORYX.I18N.Save.unsavedData = \"There are unsaved data, please save before you leave, otherwise your changes get lost!\";\nORYX.I18N.Save.newProcess = \"New Process\";\nORYX.I18N.Save.saveAsTitle = \"Save as...\";\nORYX.I18N.Save.saveBtn = \"Save\";\nORYX.I18N.Save.close = \"Close\";\nORYX.I18N.Save.savedAs = \"Saved As\";\nORYX.I18N.Save.saved = \"Saved!\";\nORYX.I18N.Save.failed = \"Saving failed.\";\nORYX.I18N.Save.noRights = \"You have no rights to save changes.\";\nORYX.I18N.Save.saving = \"Saving\";\nORYX.I18N.Save.saveAsHint = \"The process diagram is stored under:\";\n\nif(!ORYX.I18N.File) ORYX.I18N.File = {};\n\nORYX.I18N.File.group = \"File\";\nORYX.I18N.File.print = \"Print\";\nORYX.I18N.File.printDesc = \"Print current model\";\nORYX.I18N.File.pdf = \"Export as PDF\";\nORYX.I18N.File.pdfDesc = \"Export as PDF\";\nORYX.I18N.File.info = \"Info\";\nORYX.I18N.File.infoDesc = \"Info\";\nORYX.I18N.File.genPDF = \"Generating PDF\";\nORYX.I18N.File.genPDFFailed = \"Generating PDF failed.\";\nORYX.I18N.File.printTitle = \"Print\";\nORYX.I18N.File.printMsg = \"We are currently experiencing problems with the printing function. We recommend using the PDF Export to print the diagram. Do you really want to continue printing?\";\n\nif(!ORYX.I18N.Grouping) ORYX.I18N.Grouping = {};\n\nORYX.I18N.Grouping.grouping = \"Grouping\";\nORYX.I18N.Grouping.group = \"Group\";\nORYX.I18N.Grouping.groupDesc = \"Groups all selected shapes\";\nORYX.I18N.Grouping.ungroup = \"Ungroup\";\nORYX.I18N.Grouping.ungroupDesc = \"Deletes the group of all selected Shapes\";\n\nif(!ORYX.I18N.Loading) ORYX.I18N.Loading = {};\n\nORYX.I18N.Loading.waiting =\"Please wait...\";\n\nif(!ORYX.I18N.PropertyWindow) ORYX.I18N.PropertyWindow = {};\n\nORYX.I18N.PropertyWindow.name = \"Name\";\nORYX.I18N.PropertyWindow.value = \"Value\";\nORYX.I18N.PropertyWindow.selected = \"selected\";\nORYX.I18N.PropertyWindow.clickIcon = \"Click Icon\";\nORYX.I18N.PropertyWindow.add = \"Add\";\nORYX.I18N.PropertyWindow.rem = \"Remove\";\nORYX.I18N.PropertyWindow.complex = \"Editor for a Complex Type\";\nORYX.I18N.PropertyWindow.text = \"Editor for a Text Type\";\nORYX.I18N.PropertyWindow.ok = \"Ok\";\nORYX.I18N.PropertyWindow.cancel = \"Cancel\";\nORYX.I18N.PropertyWindow.dateFormat = \"m/d/y\";\n\nif(!ORYX.I18N.ShapeMenuPlugin) ORYX.I18N.ShapeMenuPlugin = {};\n\nORYX.I18N.ShapeMenuPlugin.drag = \"Drag\";\nORYX.I18N.ShapeMenuPlugin.clickDrag = \"Click or drag\";\nORYX.I18N.ShapeMenuPlugin.morphMsg = \"Morph shape\";\n\nif(!ORYX.I18N.SyntaxChecker) ORYX.I18N.SyntaxChecker = {};\n\nORYX.I18N.SyntaxChecker.group = \"Verification\";\nORYX.I18N.SyntaxChecker.name = \"Syntax Checker\";\nORYX.I18N.SyntaxChecker.desc = \"Check Syntax\";\nORYX.I18N.SyntaxChecker.noErrors = \"There are no syntax errors.\";\nORYX.I18N.SyntaxChecker.invalid = \"Invalid answer from server.\";\nORYX.I18N.SyntaxChecker.checkingMessage = \"Checking ...\";\n\nif(!ORYX.I18N.FormHandler) ORYX.I18N.FormHandler = {};\n\nORYX.I18N.FormHandler.group = \"FormHandling\";\nORYX.I18N.FormHandler.name = \"FormHandler\";\nORYX.I18N.FormHandler.desc = \"Testing from handling\";\n\nif(!ORYX.I18N.Deployer) ORYX.I18N.Deployer = {};\n\nORYX.I18N.Deployer.group = \"Deployment\";\nORYX.I18N.Deployer.name = \"Deployer\";\nORYX.I18N.Deployer.desc = \"Deploy to engine\";\n\nif(!ORYX.I18N.Tester) ORYX.I18N.Tester = {};\n\nORYX.I18N.Tester.group = \"Testing\";\nORYX.I18N.Tester.name = \"Test process\";\nORYX.I18N.Tester.desc = \"Open the test component to test this process definition\";\n\nif(!ORYX.I18N.Undo) ORYX.I18N.Undo = {};\n\nORYX.I18N.Undo.group = \"Undo\";\nORYX.I18N.Undo.undo = \"Undo\";\nORYX.I18N.Undo.undoDesc = \"Undo the last action\";\nORYX.I18N.Undo.redo = \"Redo\";\nORYX.I18N.Undo.redoDesc = \"Redo the last undone action\";\n\nif(!ORYX.I18N.View) ORYX.I18N.View = {};\n\nORYX.I18N.View.group = \"Zoom\";\nORYX.I18N.View.zoomIn = \"Zoom In\";\nORYX.I18N.View.zoomInDesc = \"Zoom into the model\";\nORYX.I18N.View.zoomOut = \"Zoom Out\";\nORYX.I18N.View.zoomOutDesc = \"Zoom out of the model\";\nORYX.I18N.View.zoomStandard = \"Zoom Standard\";\nORYX.I18N.View.zoomStandardDesc = \"Zoom to the standard level\";\nORYX.I18N.View.zoomFitToModel = \"Zoom fit to model\";\nORYX.I18N.View.zoomFitToModelDesc = \"Zoom to fit the model size\";\n\nif(!ORYX.I18N.XFormsSerialization) ORYX.I18N.XFormsSerialization = {};\n\nORYX.I18N.XFormsSerialization.group = \"XForms Serialization\";\nORYX.I18N.XFormsSerialization.exportXForms = \"XForms Export\";\nORYX.I18N.XFormsSerialization.exportXFormsDesc = \"Export XForms+XHTML markup\";\nORYX.I18N.XFormsSerialization.importXForms = \"XForms Import\";\nORYX.I18N.XFormsSerialization.importXFormsDesc = \"Import XForms+XHTML markup\";\nORYX.I18N.XFormsSerialization.noClientXFormsSupport = \"No XForms support\";\nORYX.I18N.XFormsSerialization.noClientXFormsSupportDesc = \"<h2>Your browser does not support XForms. Please install the <a href=\\\"https://addons.mozilla.org/firefox/addon/824\\\" target=\\\"_blank\\\">Mozilla XForms Add-on</a> for Firefox.</h2>\";\nORYX.I18N.XFormsSerialization.ok = \"Ok\";\nORYX.I18N.XFormsSerialization.selectFile = \"Select a XHTML (.xhtml) file or type in the XForms+XHTML markup to import it!\";\nORYX.I18N.XFormsSerialization.selectCss = \"Please insert url of css file\";\nORYX.I18N.XFormsSerialization.file = \"File\";\nORYX.I18N.XFormsSerialization.impFailed = \"Request for import of document failed.\";\nORYX.I18N.XFormsSerialization.impTitle = \"Import XForms+XHTML document\";\nORYX.I18N.XFormsSerialization.expTitle = \"Export XForms+XHTML document\";\nORYX.I18N.XFormsSerialization.impButton = \"Import\";\nORYX.I18N.XFormsSerialization.impProgress = \"Importing...\";\nORYX.I18N.XFormsSerialization.close = \"Close\";\n\n/** New Language Properties: 08.12.2008 */\n\nORYX.I18N.PropertyWindow.title = \"Properties\";\n\nif(!ORYX.I18N.ShapeRepository) ORYX.I18N.ShapeRepository = {};\nORYX.I18N.ShapeRepository.title = \"Shape Repository\";\n\nORYX.I18N.Save.dialogDesciption = \"Please enter a name, a description and a comment.\";\nORYX.I18N.Save.dialogLabelTitle = \"Title\";\nORYX.I18N.Save.dialogLabelDesc = \"Description\";\nORYX.I18N.Save.dialogLabelType = \"Type\";\nORYX.I18N.Save.dialogLabelComment = \"Revision comment\";\n\nif(!ORYX.I18N.Perspective) ORYX.I18N.Perspective = {};\nORYX.I18N.Perspective.no = \"No Perspective\"\nORYX.I18N.Perspective.noTip = \"Unload the current perspective\"\n\n/** New Language Properties: 21.04.2009 */\nORYX.I18N.JSONSupport = {\n    imp: {\n        name: \"Import from JSON\",\n        desc: \"Imports a model from JSON\",\n        group: \"Export\",\n        selectFile: \"Select an JSON (.json) file or type in JSON to import it!\",\n        file: \"File\",\n        btnImp: \"Import\",\n        btnClose: \"Close\",\n        progress: \"Importing ...\",\n        syntaxError: \"Syntax error\"\n    },\n    exp: {\n        name: \"Export to JSON\",\n        desc: \"Exports current model to JSON\",\n        group: \"Export\"\n    }\n};\n\n/** New Language Properties: 09.05.2009 */\nif(!ORYX.I18N.JSONImport) ORYX.I18N.JSONImport = {};\n\nORYX.I18N.JSONImport.title = \"JSON Import\";\nORYX.I18N.JSONImport.wrongSS = \"The stencil set of the imported file ({0}) does not match to the loaded stencil set ({1}).\"\n\n/** New Language Properties: 14.05.2009 */\nif(!ORYX.I18N.RDFExport) ORYX.I18N.RDFExport = {};\nORYX.I18N.RDFExport.group = \"Export\";\nORYX.I18N.RDFExport.rdfExport = \"Export to RDF\";\nORYX.I18N.RDFExport.rdfExportDescription = \"Exports current model to the XML serialization defined for the Resource Description Framework (RDF)\";\n\n/** New Language Properties: 15.05.2009*/\nif(!ORYX.I18N.SyntaxChecker.BPMN) ORYX.I18N.SyntaxChecker.BPMN={};\nORYX.I18N.SyntaxChecker.BPMN_NO_SOURCE = \"An edge must have a source.\";\nORYX.I18N.SyntaxChecker.BPMN_NO_TARGET = \"An edge must have a target.\";\nORYX.I18N.SyntaxChecker.BPMN_DIFFERENT_PROCESS = \"Source and target node must be contained in the same process.\";\nORYX.I18N.SyntaxChecker.BPMN_SAME_PROCESS = \"Source and target node must be contained in different pools.\";\nORYX.I18N.SyntaxChecker.BPMN_FLOWOBJECT_NOT_CONTAINED_IN_PROCESS = \"A flow object must be contained in a process.\";\nORYX.I18N.SyntaxChecker.BPMN_ENDEVENT_WITHOUT_INCOMING_CONTROL_FLOW = \"An end event must have an incoming sequence flow.\";\nORYX.I18N.SyntaxChecker.BPMN_STARTEVENT_WITHOUT_OUTGOING_CONTROL_FLOW = \"A start event must have an outgoing sequence flow.\";\nORYX.I18N.SyntaxChecker.BPMN_STARTEVENT_WITH_INCOMING_CONTROL_FLOW = \"Start events must not have incoming sequence flows.\";\nORYX.I18N.SyntaxChecker.BPMN_ATTACHEDINTERMEDIATEEVENT_WITH_INCOMING_CONTROL_FLOW = \"Attached intermediate events must not have incoming sequence flows.\";\nORYX.I18N.SyntaxChecker.BPMN_ATTACHEDINTERMEDIATEEVENT_WITHOUT_OUTGOING_CONTROL_FLOW = \"Attached intermediate events must have exactly one outgoing sequence flow.\";\nORYX.I18N.SyntaxChecker.BPMN_ENDEVENT_WITH_OUTGOING_CONTROL_FLOW = \"End events must not have outgoing sequence flows.\";\nORYX.I18N.SyntaxChecker.BPMN_EVENTBASEDGATEWAY_BADCONTINUATION = \"Event-based gateways must not be followed by gateways or subprocesses.\";\nORYX.I18N.SyntaxChecker.BPMN_NODE_NOT_ALLOWED = \"Node type is not allowed.\";\n\nif(!ORYX.I18N.SyntaxChecker.IBPMN) ORYX.I18N.SyntaxChecker.IBPMN={};\nORYX.I18N.SyntaxChecker.IBPMN_NO_ROLE_SET = \"Interactions must have a sender and a receiver role set\";\nORYX.I18N.SyntaxChecker.IBPMN_NO_INCOMING_SEQFLOW = \"This node must have incoming sequence flow.\";\nORYX.I18N.SyntaxChecker.IBPMN_NO_OUTGOING_SEQFLOW = \"This node must have outgoing sequence flow.\";\n\nif(!ORYX.I18N.SyntaxChecker.InteractionNet) ORYX.I18N.SyntaxChecker.InteractionNet={};\nORYX.I18N.SyntaxChecker.InteractionNet_SENDER_NOT_SET = \"Sender not set\";\nORYX.I18N.SyntaxChecker.InteractionNet_RECEIVER_NOT_SET = \"Receiver not set\";\nORYX.I18N.SyntaxChecker.InteractionNet_MESSAGETYPE_NOT_SET = \"Message type not set\";\nORYX.I18N.SyntaxChecker.InteractionNet_ROLE_NOT_SET = \"Role not set\";\n\nif(!ORYX.I18N.SyntaxChecker.EPC) ORYX.I18N.SyntaxChecker.EPC={};\nORYX.I18N.SyntaxChecker.EPC_NO_SOURCE = \"Each edge must have a source.\";\nORYX.I18N.SyntaxChecker.EPC_NO_TARGET = \"Each edge must have a target.\";\nORYX.I18N.SyntaxChecker.EPC_NOT_CONNECTED = \"Node must be connected with edges.\";\nORYX.I18N.SyntaxChecker.EPC_NOT_CONNECTED_2 = \"Node must be connected with more edges.\";\nORYX.I18N.SyntaxChecker.EPC_TOO_MANY_EDGES = \"Node has too many connected edges.\";\nORYX.I18N.SyntaxChecker.EPC_NO_CORRECT_CONNECTOR = \"Node is no correct connector.\";\nORYX.I18N.SyntaxChecker.EPC_MANY_STARTS = \"There must be only one start event.\";\nORYX.I18N.SyntaxChecker.EPC_FUNCTION_AFTER_OR = \"There must be no functions after a splitting OR/XOR.\";\nORYX.I18N.SyntaxChecker.EPC_PI_AFTER_OR = \"There must be no process interface after a splitting OR/XOR.\";\nORYX.I18N.SyntaxChecker.EPC_FUNCTION_AFTER_FUNCTION =  \"There must be no function after a function.\";\nORYX.I18N.SyntaxChecker.EPC_EVENT_AFTER_EVENT =  \"There must be no event after an event.\";\nORYX.I18N.SyntaxChecker.EPC_PI_AFTER_FUNCTION =  \"There must be no process interface after a function.\";\nORYX.I18N.SyntaxChecker.EPC_FUNCTION_AFTER_PI =  \"There must be no function after a process interface.\";\nORYX.I18N.SyntaxChecker.EPC_SOURCE_EQUALS_TARGET = \"Edge must connect two distinct nodes.\"\n\nif(!ORYX.I18N.SyntaxChecker.PetriNet) ORYX.I18N.SyntaxChecker.PetriNet={};\nORYX.I18N.SyntaxChecker.PetriNet_NOT_BIPARTITE = \"The graph is not bipartite\";\nORYX.I18N.SyntaxChecker.PetriNet_NO_LABEL = \"Label not set for a labeled transition\";\nORYX.I18N.SyntaxChecker.PetriNet_NO_ID = \"There is a node without id\";\nORYX.I18N.SyntaxChecker.PetriNet_SAME_SOURCE_AND_TARGET = \"Two flow relationships have the same source and target\";\nORYX.I18N.SyntaxChecker.PetriNet_NODE_NOT_SET = \"A node is not set for a flowrelationship\";\n\n/** New Language Properties: 02.06.2009*/\nORYX.I18N.Edge = \"Edge\";\nORYX.I18N.Node = \"Node\";\n\n/** New Language Properties: 03.06.2009*/\nORYX.I18N.SyntaxChecker.notice = \"Move the mouse over a red cross icon to see the error message.\";\n\n/** New Language Properties: 05.06.2009*/\nif(!ORYX.I18N.RESIZE) ORYX.I18N.RESIZE = {};\nORYX.I18N.RESIZE.tipGrow = \"Increase canvas size:\";\nORYX.I18N.RESIZE.tipShrink = \"Decrease canvas size:\";\nORYX.I18N.RESIZE.N = \"Top\";\nORYX.I18N.RESIZE.W = \"Left\";\nORYX.I18N.RESIZE.S =\"Down\";\nORYX.I18N.RESIZE.E =\"Right\";\n\n/** New Language Properties: 15.07.2009*/\nif(!ORYX.I18N.Layouting) ORYX.I18N.Layouting ={};\nORYX.I18N.Layouting.doing = \"Layouting...\";\n\n/** New Language Properties: 18.08.2009*/\nORYX.I18N.SyntaxChecker.MULT_ERRORS = \"Multiple Errors\";\n\n/** New Language Properties: 08.09.2009*/\nif(!ORYX.I18N.PropertyWindow) ORYX.I18N.PropertyWindow = {};\nORYX.I18N.PropertyWindow.oftenUsed = \"Often used\";\nORYX.I18N.PropertyWindow.moreProps = \"More Properties\";\n\n/** New Language Properties 01.10.2009 */\nif(!ORYX.I18N.SyntaxChecker.BPMN2) ORYX.I18N.SyntaxChecker.BPMN2 = {};\n\nORYX.I18N.SyntaxChecker.BPMN2_DATA_INPUT_WITH_INCOMING_DATA_ASSOCIATION = \"A Data Input must not have any incoming Data Associations.\";\nORYX.I18N.SyntaxChecker.BPMN2_DATA_OUTPUT_WITH_OUTGOING_DATA_ASSOCIATION = \"A Data Output must not have any outgoing Data Associations.\";\nORYX.I18N.SyntaxChecker.BPMN2_EVENT_BASED_TARGET_WITH_TOO_MANY_INCOMING_SEQUENCE_FLOWS = \"Targets of Event-based Gateways may only have one incoming Sequence Flow.\";\n\n/** New Language Properties 02.10.2009 */\nORYX.I18N.SyntaxChecker.BPMN2_EVENT_BASED_WITH_TOO_LESS_OUTGOING_SEQUENCE_FLOWS = \"An Event-based Gateway must have two or more outgoing Sequence Flows.\";\nORYX.I18N.SyntaxChecker.BPMN2_EVENT_BASED_EVENT_TARGET_CONTRADICTION = \"If Message Intermediate Events are used in the configuration, then Receive Tasks must not be used and vice versa.\";\nORYX.I18N.SyntaxChecker.BPMN2_EVENT_BASED_WRONG_TRIGGER = \"Only the following Intermediate Event triggers are valid: Message, Signal, Timer, Conditional and Multiple.\";\nORYX.I18N.SyntaxChecker.BPMN2_EVENT_BASED_WRONG_CONDITION_EXPRESSION = \"The outgoing Sequence Flows of the Event Gateway must not have a condition expression.\";\nORYX.I18N.SyntaxChecker.BPMN2_EVENT_BASED_NOT_INSTANTIATING = \"The Gateway does not meet the conditions to instantiate the process. Please use a start event or an instantiating attribute for the gateway.\";\n\n/** New Language Properties 05.10.2009 */\nORYX.I18N.SyntaxChecker.BPMN2_GATEWAYDIRECTION_MIXED_FAILURE = \"The Gateway must have both multiple incoming and outgoing Sequence Flows.\";\nORYX.I18N.SyntaxChecker.BPMN2_GATEWAYDIRECTION_CONVERGING_FAILURE = \"The Gateway must have multiple incoming but most NOT have multiple outgoing Sequence Flows.\";\nORYX.I18N.SyntaxChecker.BPMN2_GATEWAYDIRECTION_DIVERGING_FAILURE = \"The Gateway must NOT have multiple incoming but must have multiple outgoing Sequence Flows.\";\nORYX.I18N.SyntaxChecker.BPMN2_GATEWAY_WITH_NO_OUTGOING_SEQUENCE_FLOW = \"A Gateway must have a minimum of one outgoing Sequence Flow.\";\nORYX.I18N.SyntaxChecker.BPMN2_RECEIVE_TASK_WITH_ATTACHED_EVENT = \"Receive Tasks used in Event Gateway configurations must not have any attached Intermediate Events.\";\nORYX.I18N.SyntaxChecker.BPMN2_EVENT_SUBPROCESS_BAD_CONNECTION = \"An Event Subprocess must not have any incoming or outgoing Sequence Flow.\";\n\n/** New Language Properties 13.10.2009 */\nORYX.I18N.SyntaxChecker.BPMN_MESSAGE_FLOW_NOT_CONNECTED = \"At least one side of the Message Flow has to be connected.\";\n\n/** New Language Properties 24.11.2009 */\nORYX.I18N.SyntaxChecker.BPMN2_TOO_MANY_INITIATING_MESSAGES = \"A Choreography Activity may only have one initiating message.\";\nORYX.I18N.SyntaxChecker.BPMN_MESSAGE_FLOW_NOT_ALLOWED = \"A Message Flow is not allowed here.\";\n\n/** New Language Properties 27.11.2009 */\nORYX.I18N.SyntaxChecker.BPMN2_EVENT_BASED_WITH_TOO_LESS_INCOMING_SEQUENCE_FLOWS = \"An Event-based Gateway that is not instantiating must have a minimum of one incoming Sequence Flow.\";\nORYX.I18N.SyntaxChecker.BPMN2_TOO_FEW_INITIATING_PARTICIPANTS = \"A Choreography Activity must have one initiating Participant (white).\";\nORYX.I18N.SyntaxChecker.BPMN2_TOO_MANY_INITIATING_PARTICIPANTS = \"A Choreography Acitivity must not have more than one initiating Participant (white).\"\n\nORYX.I18N.SyntaxChecker.COMMUNICATION_AT_LEAST_TWO_PARTICIPANTS = \"The communication must be connected to at least two participants.\";\nORYX.I18N.SyntaxChecker.MESSAGEFLOW_START_MUST_BE_PARTICIPANT = \"The message flow's source must be a participant.\";\nORYX.I18N.SyntaxChecker.MESSAGEFLOW_END_MUST_BE_PARTICIPANT = \"The message flow's target must be a participant.\";\nORYX.I18N.SyntaxChecker.CONV_LINK_CANNOT_CONNECT_CONV_NODES = \"The conversation link must connect a communication or sub conversation node with a participant.\";\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/editor/i18n/translation_signavio_de.js",
    "content": "Ext.PagingToolbar.prototype.firstText = \"Erste Seite\";\nExt.PagingToolbar.prototype.prevText = \"Vorherige Seite\";\nExt.PagingToolbar.prototype.nextText = \"Nächste Seite\";\nExt.PagingToolbar.prototype.lastText  = \"Letzte Seite\";\n\t\n\nORYX.I18N.PropertyWindow.dateFormat = \"d.m.y\";\n\n\nORYX.I18N.View.East = \"Attribute\";\nORYX.I18N.View.West = \"Modellierungselemente\";\n\nORYX.I18N.Oryx.pleaseWait = \"Der Signavio Process Editor wird geladen. Bitte warten...\";\nORYX.I18N.AddDocker.add = \"Docker hinzufügen\";\nORYX.I18N.AddDocker.del = \"Docker löschen\";\nORYX.I18N.ERDFSupport.noCanvas = \"Das XML Dokument enthält keinen Canvas Knoten.\";\nORYX.I18N.ERDFSupport.deprText = \"Der Export nach eRDF wird nicht empfohlen, da dieses Format in zukünftigen Versionen des Signavio Process Editors nicht mehr unterstützt wird. Verwenden Sie stattdessen den Export nach JSON, falls möglich. Wollen Sie dennoch das Model nach eRDF exportieren?\";\nORYX.I18N.Save.unsavedData = \"Das Diagramm enthält nicht gespeicherte Daten. Sind Sie sicher, dass Sie den Editor schließen möchten?\";\nORYX.I18N.Save.pleaseWait = \"Bitte warten Sie, während<br/>das Diagramm gespeichert wird.\";\nORYX.I18N.File.info = \"Info\";\nORYX.I18N.File.infoDesc = \"Info\";\nORYX.I18N.PropertyWindow.name = \"Attribut\";\nORYX.I18N.View.zoomStandard = \"Zoom: Originalgröße\";\nORYX.I18N.View.zoomStandardDesc = \"Zoom: Originalgröße\";\nORYX.I18N.View.zoomFitToModel = \"Zoom: Modellgröße\";\nORYX.I18N.View.zoomFitToModelDesc = \"Zoom: Modellgröße\";\nORYX.I18N.ShapeRepository.title = \"Modellierungselemente\";\nORYX.I18N.Save.dialogLabelComment = \"Änderungs-\\nkommentar\";\n\nORYX.I18N.Save.saveAs = \"Kopie speichern...\";\nORYX.I18N.Save.saveAsDesc = \"Kopie speichern...\";\nORYX.I18N.Save.saveAsTitle = \"Kopie speichern...\";\nORYX.I18N.Save.savedAs = \"Kopie gespeichert\";\nORYX.I18N.Save.savedDescription = \"Das kopierte Diagramm ist unter folgendem Link gespeichert\";\nORYX.I18N.Save.notAuthorized = \"Sie sind derzeit nicht angemeldet. Bitte melden Sie sich in einem <a href='/p/login' target='_blank'>neuen Fenstern</a> an, damit Sie diese Model speichern können.\"\nORYX.I18N.Save.transAborted = \"Die Anfrage zum Speichern Ihres Diagramms hat zu lange gedauert. Bitte benutzen Sie eine schnellere Internetverbindung. Wenn Sie eine kabellose Internetverbindung benutzen, dann überprüfen Sie bitte die Signalstärke.\";\nORYX.I18N.Save.noRights = \"Sie haben nicht die benötigten Rechte, um das Diagramm abzuspeichern. Bitte überprüfen Sie im <a href='/p/explorer' target='_blank'>Signavio Explorer</a>, ob Sie noch die benötigten Rechte im Zielordner besitzen.\";\nORYX.I18N.Save.comFailed = \"Die Kommunikation mit dem Signavio Server ist fehlgeschlagen. Bitte überprüfen Sie Ihre Internetverbindung. Wenn das Problem weiterhin besteht, wenden Sie sich bitte an den Signavio Support über das Briefumschlagssymbol in der Toolbar.\";\nORYX.I18N.Save.failed = \"Beim Speichern Ihres Diagramms ist ein Problem aufgetreten. Bitte versuchen Sie es erneut. Wenn das Problem weiterhin besteht, wenden Sie sich bitte an den Signavio Support über das Briefumschlagssymbol in der Toolbar.\";\nORYX.I18N.Save.exception = \"Beim Speichern Ihres Diagramms sind einige Probleme aufgetreten. Bitte versuchen Sie es erneut. Wenn das Problem weiterhin besteht, wenden Sie sich bitte an den Signavio Support über das Briefumschlagssymbol in der Toolbar.\";\nORYX.I18N.Save.retrieveData = \"Bitte warten, Daten werden geladen\";\n\n/** New Language Properties: 10.6.09*/\nif(!ORYX.I18N.ShapeMenuPlugin) ORYX.I18N.ShapeMenuPlugin = {};\nORYX.I18N.ShapeMenuPlugin.morphMsg = \"Umwandeln\";\nORYX.I18N.ShapeMenuPlugin.morphWarningTitleMsg = \"Umwandeln\";\nORYX.I18N.ShapeMenuPlugin.morphWarningMsg = \"Einige Kindelemente können nicht im neuen Element enthalten sein.<br/>Möchten Sie dennoch das Element umwandeln?\";\n\nif (!Signavio) { var Signavio = {}; }\nif (!Signavio.I18N) { Signavio.I18N = {} }\nif (!Signavio.I18N.Editor) { Signavio.I18N.Editor = {} }\n\nif (!Signavio.I18N.Editor.Linking) { Signavio.I18N.Editor.Linking = {} }\nSignavio.I18N.Editor.Linking.CreateDiagram = \"Neues Diagramm erstellen:\";\nSignavio.I18N.Editor.Linking.UseDiagram = \"Vorhandenes Diagramm verwenden\";\nSignavio.I18N.Editor.Linking.UseLink = \"Web-Link verwenden\";\nSignavio.I18N.Editor.Linking.CreateTitle = \"Verlinkung setzen\";\nSignavio.I18N.Editor.Linking.Close = \"Schließen\";\nSignavio.I18N.Editor.Linking.Cancel = \"Abbrechen\";\nSignavio.I18N.Editor.Linking.UseName = \"Diagrammnamen übernehmen\";\nSignavio.I18N.Editor.Linking.UseNameHint = \"Ersetzt den Bezeichner des aktuellen Elements ({type}) durch den Namen des zu verlinkenden Diagramms.\";\nSignavio.I18N.Editor.Linking.AlertSelectModel = \"Bitte selektieren Sie ein Diagramm.\";\nSignavio.I18N.Editor.Linking.ButtonLink = \"Verlinkung setzen\";\nSignavio.I18N.Editor.Linking.LinkNoAccess = \"Sie haben keine Berechtigung für das Diagramm.\";\nSignavio.I18N.Editor.Linking.LinkUnavailable = \"Das Diagramm ist nicht verfügbar.\";\nSignavio.I18N.Editor.Linking.RemoveLink = \"Link löschen\";\nSignavio.I18N.Editor.Linking.EditLink = \"Link ändern\";\nSignavio.I18N.Editor.Linking.OpenLink = \"Öffnen\";\nSignavio.I18N.Editor.Linking.BrokenLink = \"Der Link ist nicht verfügbar!\";\nSignavio.I18N.Editor.Linking.PreviewTitle = \"Vorschau\";\n\nif(!ORYX.I18N.PropertyWindow) ORYX.I18N.PropertyWindow = {};\nORYX.I18N.PropertyWindow.oftenUsed = \"Hauptattribute\";\nORYX.I18N.PropertyWindow.moreProps = \"Weitere Attribute\";\nORYX.I18N.PropertyWindow.characteristicNr = \"Kennzahlen\";\nORYX.I18N.PropertyWindow.meta = \"Eigene Attribute\";\n\nif(!ORYX.I18N.PropertyWindow.Category){ORYX.I18N.PropertyWindow.Category = {}}\nORYX.I18N.PropertyWindow.Category.popular = \"Hauptattribute\";\nORYX.I18N.PropertyWindow.Category.characteristicnr = \"Kennzahlen\";\nORYX.I18N.PropertyWindow.Category.others = \"Weitere Attribute\";\nORYX.I18N.PropertyWindow.Category.meta = \"Eigene Attribute\";\n\nif(!ORYX.I18N.PropertyWindow.ListView) ORYX.I18N.PropertyWindow.ListView = {};\nORYX.I18N.PropertyWindow.ListView.title = \"Attribut: \";\nORYX.I18N.PropertyWindow.ListView.dataViewLabel = \"Bereits vorhandene Einträge\";\nORYX.I18N.PropertyWindow.ListView.dataViewEmptyText = \"Es sind noch keine Einträge vorhanden.\";\nORYX.I18N.PropertyWindow.ListView.addEntryLabel = \"Neuen Eintrag hinzufügen\";\nORYX.I18N.PropertyWindow.ListView.buttonAdd = \"Hinzufügen\";\nORYX.I18N.PropertyWindow.ListView.save = \"Speichern\";\nORYX.I18N.PropertyWindow.ListView.cancel = \"Abbrachen\";\n\nif(!Signavio.I18N.Buttons) Signavio.I18N.Buttons = {};\nSignavio.I18N.Buttons.save\t\t= \"Speichern\";\nSignavio.I18N.Buttons.cancel \t= \"Abbrechen\";\nSignavio.I18N.Buttons.remove\t= \"Entfernen\";\n\nif(!Signavio.I18N.btn) {Signavio.I18N.btn = {};}\nSignavio.I18N.btn.btnEdit = \"Editieren\";\nSignavio.I18N.btn.btnRemove = \"Löschen\";\nSignavio.I18N.btn.moveUp = \"Nach oben\";\nSignavio.I18N.btn.moveDown = \"Nach unten\";\n\nif(!Signavio.I18N.field) {Signavio.I18N.field = {};}\nSignavio.I18N.field.Url = \"URL\";\nSignavio.I18N.field.UrlLabel = \"Label\";"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/editor/i18n/translation_signavio_en_us.js",
    "content": "ORYX.I18N.PropertyWindow.dateFormat = \"d/m/y\";\n\nORYX.I18N.View.East = \"Attributes\";\nORYX.I18N.View.West = \"Modeling Elements\";\n\nORYX.I18N.Oryx.title\t= \"Signavio\";\nORYX.I18N.Oryx.pleaseWait = \"Please wait while the Signavio Process Editor is loading...\";\nORYX.I18N.Edit.cutDesc = \"Cuts the selection into the clipboard\";\nORYX.I18N.Edit.copyDesc = \"Copies the selection into the clipboard\";\nORYX.I18N.Edit.pasteDesc = \"Pastes the clipboard to the canvas\";\nORYX.I18N.ERDFSupport.noCanvas = \"The xml document has no canvas node included!\";\nORYX.I18N.ERDFSupport.noSS = \"The Signavio Process Editor canvas node has no stencil set definition included!\";\nORYX.I18N.ERDFSupport.deprText = \"Exporting to eRDF is not recommended anymore because the support will be stopped in future versions of the Signavio Process Editor. If possible, export the model to JSON. Do you want to export anyway?\";\nORYX.I18N.Save.pleaseWait = \"Please wait<br/>while saving...\";\n\nORYX.I18N.Save.saveAs = \"Save a copy...\";\nORYX.I18N.Save.saveAsDesc = \"Save a copy...\";\nORYX.I18N.Save.saveAsTitle = \"Save a copy...\";\nORYX.I18N.Save.savedAs = \"Copy saved\";\nORYX.I18N.Save.savedDescription = \"The process diagram is stored under\";\nORYX.I18N.Save.notAuthorized = \"You are currently not logged in. Please <a href='/p/login' target='_blank'>log in</a> in a new window so that you can save the current diagram.\"\nORYX.I18N.Save.transAborted = \"The saving request took too long. You may use a faster internet connection. If you use wireless LAN, please check the strength of your connection.\";\nORYX.I18N.Save.noRights = \"You do not have the required rights to store that model. Please check in the <a href='/p/explorer' target='_blank'>Signavio Explorer</a>, if you still have the rights to write in the target directory.\";\nORYX.I18N.Save.comFailed = \"The communication with the Signavio server failed. Please check your internet connection. If the problem resides, please contact the Signavio Support via the envelope symbol in the toolbar.\";\nORYX.I18N.Save.failed = \"Something went wrong when trying to save your diagram. Please try again. If the problem resides, please contact the Signavio Support via the envelope symbol in the toolbar.\";\nORYX.I18N.Save.exception = \"Some exceptions are raised while trying to save your diagram. Please try again. If the problem resides, please contact the Signavio Support via the envelope symbol in the toolbar.\";\nORYX.I18N.Save.retrieveData = \"Please wait, data is retrieving.\";\n\n/** New Language Properties: 10.6.09*/\nif(!ORYX.I18N.ShapeMenuPlugin) ORYX.I18N.ShapeMenuPlugin = {};\nORYX.I18N.ShapeMenuPlugin.morphMsg = \"Transform shape\";\nORYX.I18N.ShapeMenuPlugin.morphWarningTitleMsg = \"Transform shape\";\nORYX.I18N.ShapeMenuPlugin.morphWarningMsg = \"There are child shape which can not be contained in the transformed element.<br/>Do you want to transform anyway?\";\n\nif (!Signavio) { var Signavio = {}; }\nif (!Signavio.I18N) { Signavio.I18N = {} }\nif (!Signavio.I18N.Editor) { Signavio.I18N.Editor = {} }\n\nif (!Signavio.I18N.Editor.Linking) { Signavio.I18N.Editor.Linking = {} }\nSignavio.I18N.Editor.Linking.CreateDiagram = \"Create a new diagram\";\nSignavio.I18N.Editor.Linking.UseDiagram = \"Use existing diagram\";\nSignavio.I18N.Editor.Linking.UseLink = \"Use web link\";\nSignavio.I18N.Editor.Linking.Close = \"Close\";\nSignavio.I18N.Editor.Linking.Cancel = \"Cancel\";\nSignavio.I18N.Editor.Linking.UseName = \"Adopt diagram name\";\nSignavio.I18N.Editor.Linking.UseNameHint = \"Replaces the current name of the modeling element ({type}) with the name of the linked diagram.\";\nSignavio.I18N.Editor.Linking.CreateTitle = \"Establish link\";\nSignavio.I18N.Editor.Linking.AlertSelectModel = \"You have to select a model.\";\nSignavio.I18N.Editor.Linking.ButtonLink = \"Link diagram\";\nSignavio.I18N.Editor.Linking.LinkNoAccess = \"You have no access to this diagram.\";\nSignavio.I18N.Editor.Linking.LinkUnavailable = \"The diagram is unavailable.\";\nSignavio.I18N.Editor.Linking.RemoveLink = \"Remove link\";\nSignavio.I18N.Editor.Linking.EditLink = \"Edit Link\";\nSignavio.I18N.Editor.Linking.OpenLink = \"Open\";\nSignavio.I18N.Editor.Linking.BrokenLink = \"The link is broken!\";\nSignavio.I18N.Editor.Linking.PreviewTitle = \"Preview\";\n\nif(!Signavio.I18N.Glossary_Support) { Signavio.I18N.Glossary_Support = {}; }\nSignavio.I18N.Glossary_Support.renameEmpty = \"No dictionary entry\";\nSignavio.I18N.Glossary_Support.renameLoading = \"Searching...\";\n\n/** New Language Properties: 08.09.2009*/\nif(!ORYX.I18N.PropertyWindow) ORYX.I18N.PropertyWindow = {};\nORYX.I18N.PropertyWindow.oftenUsed = \"Main properties\";\nORYX.I18N.PropertyWindow.moreProps = \"More properties\";\n\nORYX.I18N.PropertyWindow.btnOpen = \"Open\";\nORYX.I18N.PropertyWindow.btnRemove = \"Remove\";\nORYX.I18N.PropertyWindow.btnEdit = \"Edit\";\nORYX.I18N.PropertyWindow.btnUp = \"Move up\";\nORYX.I18N.PropertyWindow.btnDown = \"Move down\";\nORYX.I18N.PropertyWindow.createNew = \"Create new\";\n\nif(!ORYX.I18N.PropertyWindow) ORYX.I18N.PropertyWindow = {};\nORYX.I18N.PropertyWindow.oftenUsed = \"Main attributes\";\nORYX.I18N.PropertyWindow.moreProps = \"More attributes\";\nORYX.I18N.PropertyWindow.characteristicNr = \"Cost &amp; Resource Analysis\";\nORYX.I18N.PropertyWindow.meta = \"Custom attributes\";\n\nif(!ORYX.I18N.PropertyWindow.Category){ORYX.I18N.PropertyWindow.Category = {}}\nORYX.I18N.PropertyWindow.Category.popular = \"Main Attributes\";\nORYX.I18N.PropertyWindow.Category.characteristicnr = \"Cost &amp; Resource Analysis\";\nORYX.I18N.PropertyWindow.Category.others = \"More Attributes\";\nORYX.I18N.PropertyWindow.Category.meta = \"Custom Attributes\";\n\nif(!ORYX.I18N.PropertyWindow.ListView) ORYX.I18N.PropertyWindow.ListView = {};\nORYX.I18N.PropertyWindow.ListView.title = \"Edit: \";\nORYX.I18N.PropertyWindow.ListView.dataViewLabel = \"Already existing entries.\";\nORYX.I18N.PropertyWindow.ListView.dataViewEmptyText = \"No list entries.\";\nORYX.I18N.PropertyWindow.ListView.addEntryLabel = \"Add a new entry\";\nORYX.I18N.PropertyWindow.ListView.buttonAdd = \"Add\";\nORYX.I18N.PropertyWindow.ListView.save = \"Save\";\nORYX.I18N.PropertyWindow.ListView.cancel = \"Cancel\";\n\nif(!Signavio.I18N.Buttons) Signavio.I18N.Buttons = {};\nSignavio.I18N.Buttons.save\t\t= \"Save\";\nSignavio.I18N.Buttons.cancel \t= \"Cancel\";\nSignavio.I18N.Buttons.remove\t= \"Remove\";\n\nif(!Signavio.I18N.btn) {Signavio.I18N.btn = {};}\nSignavio.I18N.btn.btnEdit = \"Edit\";\nSignavio.I18N.btn.btnRemove = \"Remove\";\nSignavio.I18N.btn.moveUp = \"Move up\";\nSignavio.I18N.btn.moveDown = \"Move down\";\n\nif(!Signavio.I18N.field) {Signavio.I18N.field = {};}\nSignavio.I18N.field.Url = \"URL\";\nSignavio.I18N.field.UrlLabel = \"Label\";\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/editor/oryx.debug.js",
    "content": "/**\n * @namespace Oryx name space for different utility methods\n * @name ORYX.Utils\n*/\n\nif(!ORYX) var ORYX = {};\n\nORYX.Utils = {\n    /**\n     * General helper method for parsing a param out of current location url\n     * @example\n     * // Current url in Browser => \"http://oryx.org?param=value\"\n     * ORYX.Utils.getParamFromUrl(\"param\") // => \"value\" \n     * @param {Object} name\n     */\n    getParamFromUrl: function(name){\n        name = name.replace(/[\\[]/, \"\\\\\\[\").replace(/[\\]]/, \"\\\\\\]\");\n        var regexS = \"[\\\\?&]\" + name + \"=([^&#]*)\";\n        var regex = new RegExp(regexS);\n        var results = regex.exec(window.location.href);\n        if (results == null) {\n            return null;\n        }\n        else {\n            return results[1];\n        }\n    },\n\t\n\tadjustLightness: function(){\n\t\treturn arguments[0];\t\n\t},\n\t\n\tadjustGradient: function(gradient, reference){\n\t\t\n\t\tif (ORYX.CONFIG.DISABLE_GRADIENT && gradient){\n\t\t\n\t\t\tvar col = reference.getAttributeNS(null, \"stop-color\") || \"#ffffff\";\n\t\t\t\n\t\t\t$A(gradient.getElementsByTagName(\"stop\")).each(function(stop){\n\t\t\t\tif (stop == reference){ return; }\n\t\t\t\tstop.setAttributeNS(null, \"stop-color\", col);\n\t\t\t});\n\t\t}\n\t}\n}\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nXMLNS = {\n\tATOM:\t\"http://www.w3.org/2005/Atom\",\n\tXHTML:\t\"http://www.w3.org/1999/xhtml\",\n\tERDF:\t\"http://purl.org/NET/erdf/profile\",\n\tRDFS:\t\"http://www.w3.org/2000/01/rdf-schema#\",\n\tRDF:\t\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\",\n\tRAZIEL: \"http://b3mn.org/Raziel\",\n\n\tSCHEMA: \"\"\n};\n\n//TODO kann kickstart sich vielleicht auch um die erzeugung von paketen/\n// namespaces k???mmern? z.b. requireNamespace(\"ORYX.Core.SVG\");\nvar Kickstart = {\n \tstarted: false,\n\tcallbacks: [],\n\talreadyLoaded: [],\n\tPATH: '',\n\n\tload: function() { Kickstart.kick(); },\n\n\tkick: function() {\n\t\t//console.profile(\"loading\");\n\t\tif(!Kickstart.started) {\n\t\t\tKickstart.started = true;\n\t\t\tKickstart.callbacks.each(function(callback){\n\t\t\t\t// call the registered callback asynchronously.\n\t\t\t\twindow.setTimeout(callback, 1);\n\t\t\t});\n\t\t}\n\t},\n\n\tregister: function(callback) {\n\t\t//TODO Add some mutual exclusion between kick and register calls.\n\t\twith(Kickstart) {\n\t\t\tif(started) window.setTimeout(callback, 1);\n\t\t\telse Kickstart.callbacks.push(callback)\n\t\t}\n\t},\n\n\t/**\n\t * Loads a js, assuring that it has only been downloaded once.\n\t * @param {String} url the script to load.\n\t */\n\trequire: function(url) {\n\t\t// if not already loaded, include it.\n\t\tif(Kickstart.alreadyLoaded.member(url))\n\t\t\treturn false;\n\t\treturn Kickstart.include(url);\n\t},\n\n\t/**\n\t * Loads a js, regardless of whether it has only been already downloaded.\n\t * @param {String} url the script to load.\n\t */\n\tinclude: function(url) {\n\n\t\t// prepare a script tag and place it in html head.\n\t\tvar head = document.getElementsByTagNameNS(XMLNS.XHTML, 'head')[0];\n\t\tvar s = document.createElementNS(XMLNS.XHTML, \"script\");\n\t\ts.setAttributeNS(XMLNS.XHTML, 'type', 'text/javascript');\n\t   \ts.src = Kickstart.PATH + url;\n\n\t\t//TODO macht es sinn, dass neue skript als letztes kind in den head\n\t\t// einzubinden (stichwort reihenfolge der skript tags)?\n\t   \thead.appendChild(s);\n\n\t\t// remember this url.\n\t\tKickstart.alreadyLoaded.push(url);\n\n\t\treturn true;\n\t}\n}\n\n// register kickstart as the new onload event listener on current window.\n// previous listener(s) are triggered to launch with kickstart.\nEvent.observe(window, 'load', Kickstart.load);/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nvar ERDF = {\n\n\tLITERAL: 0x01,\n\tRESOURCE: 0x02,\n\tDELIMITERS: ['.', '-'],\n\tHASH: '#',\n\tHYPHEN: \"-\",\n\n\tschemas: [],\n\tcallback: undefined,\n\tlog: undefined,\n\n\tinit: function(callback) {\n\t\t\n\t\t// init logging.\n\t\t//ERDF.log = Log4js.getLogger(\"oryx\");\n\t\t//ERDF.log.setLevel(Log4js.Level.ALL);\n\t\t//ERDF.log.addAppender(new ConsoleAppender(ERDF.log, false));\n\n\t\t//if(ERDF.log.isTraceEnabled())\n\t\t//\tERDF.log.trace(\"ERDF Parser is initialized.\");\n\n\t\t// register callbacks and default schemas.\n\t\tERDF.callback = callback;\n\t\tERDF.registerSchema('schema', XMLNS.SCHEMA);\n\t\tERDF.registerSchema('rdfs', XMLNS.RDFS);\n\t},\n\n\trun: function() {\n\n\t\t//if(ERDF.log.isTraceEnabled())\n\t\t//\tERDF.log.trace(\"ERDF Parser is running.\");\n\n\t\t// do the work.\n\t\treturn ERDF._checkProfile() && ERDF.parse();\n\t},\n\t\n\tparse: function() {\n\t\t\n\t\t//(ERDF.log.isDebugEnabled())\n\t\t//\tERDF.log.debug(\"Begin parsing document metadata.\");\n\t\t\n\t\t// time measuring\n\t\tERDF.__startTime = new Date();\n\n\t\tvar bodies = document.getElementsByTagNameNS(XMLNS.XHTML, 'body');\n\t\tvar subject = {type: ERDF.RESOURCE, value: ''};\n\n\t\tvar result = ERDF._parseDocumentMetadata() &&\n\t\t\tERDF._parseFromTag(bodies[0], subject);\n\t\t\t\n\t\t// time measuring\n\t\tERDF.__stopTime = new Date();\n\n\t\tvar duration = (ERDF.__stopTime - ERDF.__startTime)/1000.;\n\t\t//alert('ERDF parsing took ' + duration + ' s.');\n\t\t\n\t\treturn result;\n\t},\n\t\n\t_parseDocumentMetadata: function() {\n\n\t\t// get links from head element.\n\t\tvar heads = document.getElementsByTagNameNS(XMLNS.XHTML, 'head');\n\t\tvar links = heads[0].getElementsByTagNameNS(XMLNS.XHTML, 'link');\n\t\tvar metas = heads[0].getElementsByTagNameNS(XMLNS.XHTML, 'meta');\n\n\t\t// process links first, since they could contain schema definitions.\n\t\t$A(links).each(function(link) {\n\t\t\tvar properties = link.getAttribute('rel');\n\t\t\tvar reversedProperties = link.getAttribute('rev');\n\t\t\tvar value = link.getAttribute('href');\n\t\t\t\n\t\t\tERDF._parseTriplesFrom(\n\t\t\t\tERDF.RESOURCE, '',\n\t\t\t\tproperties,\n\t\t\t\tERDF.RESOURCE, value);\n\t\t\t\t\n\t\t\tERDF._parseTriplesFrom(\n\t\t\t\tERDF.RESOURCE, value,\n\t\t\t\treversedProperties,\n\t\t\t\tERDF.RESOURCE, '');\n\t\t});\n\n\t\t// continue with metas.\n\t\t$A(metas).each(function(meta) {\n\t\t\tvar property = meta.getAttribute('name');\n\t\t\tvar value = meta.getAttribute('content');\n\t\t\t\n\t\t\tERDF._parseTriplesFrom(\n\t\t\t\tERDF.RESOURCE, '',\n\t\t\t\tproperty,\n\t\t\t\tERDF.LITERAL, value);\n\t\t});\n\n\t\treturn true;\n\t},\n\t\n\t_parseFromTag: function(node, subject, depth) {\n\t\t\n\t\t// avoid parsing non-xhtml content.\n\t\tif(!node || !node.namespaceURI || node.namespaceURI != XMLNS.XHTML) { return; }\n\t\t\n\t\t// housekeeping.\n\t\tif(!depth) depth=0;\n\t\tvar id = node.getAttribute('id');\n\n\t\t// some logging.\n\t\t//if(ERDF.log.isTraceEnabled())\n\t\t//\tERDF.log.trace(\">\".times(depth) + \" Parsing \" + node.nodeName + \" (\"+node.nodeType+\") for data on \" +\n\t\t//\t\t((subject.type == ERDF.RESOURCE) ? ('&lt;' + subject.value + '&gt;') : '') +\n\t\t//\t\t((subject.type == ERDF.LITERAL) ? '\"' + subject.value + '\"' : ''));\n\t\t\n\t\t/* triple finding! */\n\t\t\n\t\t// in a-tags...\n\t\tif(node.nodeName.endsWith(':a') || node.nodeName == 'a') {\n\t\t\tvar properties = node.getAttribute('rel');\n\t\t\tvar reversedProperties = node.getAttribute('rev');\n\t\t\tvar value = node.getAttribute('href');\n\t\t\tvar title = node.getAttribute('title');\n\t\t\tvar content = node.textContent;\n\n\t\t\t// rel triples\n\t\t\tERDF._parseTriplesFrom(\n\t\t\t\tsubject.type, subject.value,\n\t\t\t\tproperties,\n\t\t\t\tERDF.RESOURCE, value,\n\t\t\t\tfunction(triple) {\n\t\t\t\t\tvar label = title? title : content;\n\t\t\t\t\t\n\t\t\t\t\t// label triples\n\t\t\t\t\tERDF._parseTriplesFrom(\n\t\t\t\t\t\ttriple.object.type, triple.object.value,\n\t\t\t\t\t\t'rdfs.label',\n\t\t\t\t\t\tERDF.LITERAL, label);\n\t\t\t\t});\n\n\t\t\t// rev triples\n\t\t\tERDF._parseTriplesFrom(\n\t\t\t\tsubject.type, subject.value,\n\t\t\t\treversedProperties,\n\t\t\t\tERDF.RESOURCE, '');\n\t\t\t\t\n\t\t\t// type triples\n\t\t\tERDF._parseTypeTriplesFrom(\n\t\t\t\tsubject.type, subject.value,\n\t\t\t\tproperties);\n\n\t\t// in img-tags...\n\t\t} else if(node.nodeName.endsWith(':img') || node.nodeName == 'img') {\n\t\t\tvar properties = node.getAttribute('class');\n\t\t\tvar value = node.getAttribute('src');\n\t\t\tvar alt = node.getAttribute('alt');\n\n\t\t\tERDF._parseTriplesFrom(\n\t\t\t\tsubject.type, subject.value,\n\t\t\t\tproperties,\n\t\t\t\tERDF.RESOURCE, value,\n\t\t\t\tfunction(triple) {\n\t\t\t\t\tvar label = alt;\n\t\t\t\t\t\n\t\t\t\t\t// label triples\n\t\t\t\t\tERDF._parseTriplesFrom(\n\t\t\t\t\t\ttriple.object.type, triple.object.value,\n\t\t\t\t\t\t'rdfs.label',\n\t\t\t\t\t\tERDF.LITERAL, label);\n\t\t\t\t});\n\n\t\t}\n\t\t\n\t\t// in every tag\n\t\tvar properties = node.getAttribute('class');\n\t\tvar title = node.getAttribute('title');\n\t\tvar content = node.textContent;\n\t\tvar label = title ? title : content;\n\t\t\n\t\t// regular triples\n\t\tERDF._parseTriplesFrom(\n\t\t\tsubject.type, subject.value,\n\t\t\tproperties,\n\t\t\tERDF.LITERAL, label);\n\n\t\tif(id) subject = {type: ERDF.RESOURCE, value: ERDF.HASH+id};\n\t\t\n\t\t// type triples\n\t\tERDF._parseTypeTriplesFrom(\n\t\t\tsubject.type, subject.value,\n\t\t\tproperties);\n\n\t\t// parse all children that are element nodes.\n\t\tvar children = node.childNodes;\n\t\tif(children) $A(children).each(function(_node) {\n\t\t\tif(_node.nodeType == _node.ELEMENT_NODE)\n\t\t\t\tERDF._parseFromTag(_node, subject, depth+1); });\n\t},\n\t\n\t_parseTriplesFrom: function(subjectType, subject, properties,\n\t\tobjectType, object, callback) {\n\t\t\n\t\tif(!properties) return;\n\t\tproperties.toLowerCase().split(' ').each( function(property) {\n\t\t\t\n\t\t\t//if(ERDF.log.isTraceEnabled())\n\t\t\t//\tERDF.log.trace(\"Going for property \" + property);\n\n\t\t\tvar schema = ERDF.schemas.find( function(schema) {\n\t\t\t\treturn false || ERDF.DELIMITERS.find( function(delimiter) {\n\t\t\t\t\treturn property.startsWith(schema.prefix + delimiter);\n\t\t\t\t});\n\t\t\t});\n\t\t\t\n\t\t\tif(schema && object) {\n\t\t\t\tproperty = property.substring(\n\t\t\t\t\tschema.prefix.length+1, property.length);\n\t\t\t\tvar triple = ERDF.registerTriple(\n\t\t\t\t\tnew ERDF.Resource(subject),\n\t\t\t\t\t{prefix: schema.prefix, name: property},\n\t\t\t\t\t(objectType == ERDF.RESOURCE) ?\n\t\t\t\t\t\tnew ERDF.Resource(object) :\n\t\t\t\t\t\tnew ERDF.Literal(object));\n\t\t\t\t\t\t\n\t\t\t\tif(callback) callback(triple);\n\t\t\t}\n\t\t});\n\t},\n\t\n\t_parseTypeTriplesFrom: function(subjectType, subject, properties, callback) {\n\t\t\n\t\tif(!properties) return;\n\t\tproperties.toLowerCase().split(' ').each( function(property) {\n\t\t\t\n\t\t\t//if(ERDF.log.isTraceEnabled())\n\t\t\t//\tERDF.log.trace(\"Going for property \" + property);\n\t\t\t\t\n\t\t\tvar schema = ERDF.schemas.find( function(schema) {\n\t\t\t\treturn false || ERDF.DELIMITERS.find( function(delimiter) {\n\t\t\t\t\treturn property.startsWith(ERDF.HYPHEN + schema.prefix + delimiter);\n\t\t\t\t});\n\t\t\t});\n\t\t\t\n\t\t\tif(schema && subject) {\n\t\t\t\tproperty = property.substring(schema.prefix.length+2, property.length);\n\t\t\t\tvar triple = ERDF.registerTriple(\n\t\t\t\t\t(subjectType == ERDF.RESOURCE) ?\n\t\t\t\t\t\tnew ERDF.Resource(subject) :\n\t\t\t\t\t\tnew ERDF.Literal(subject),\n\t\t\t\t\t{prefix: 'rdf', name: 'type'},\n\t\t\t\t\tnew ERDF.Resource(schema.namespace+property));\n\t\t\t\tif(callback) callback(triple);\n\t\t\t}\n\t\t});\n\t},\n\t\n\t/**\n\t * Checks for ERDF profile declaration in head of document.\n\t */\n\t_checkProfile: function() {\n\n\t\t// get profiles from head element.\n\t\tvar heads = document.getElementsByTagNameNS(XMLNS.XHTML, 'head');\n\t\tvar profiles = heads[0].getAttribute(\"profile\");\n\t\tvar found = false;\n\n\t\t// if erdf profile is contained.\n\t\tif(profiles && profiles.split(\" \").member(XMLNS.ERDF)) {\n\n\t\t\t// pass check.\n\t\t\t//if(ERDF.log.isTraceEnabled())\n\t\t\t//\tERDF.log.trace(\"Found ERDF profile \" + XMLNS.ERDF);\n\t\t\treturn true;\n\t\t\t\n\t\t} else {\n\t\t\n\t\t\t// otherwise fail check.\n\t\t\t//if(ERDF.log.isFatalEnabled())\n\t\t\t//\tERDF.log.fatal(\"No ERDF profile found.\");\n\t\t\treturn false;\n\t\t}\n\t},\n\t\n\t__stripHashes: function(s) {\n\t\treturn (s && (typeof s.substring == 'function') && s.substring(0, 1)=='#') ? s.substring(1, s.length) : s;\n\t},\n\t\n\tregisterSchema: function(prefix, namespace) {\n\t\t\n\t\t// TODO check whether already registered, if so, complain.\n\t\tERDF.schemas.push({\n\t\t\tprefix: prefix,\n\t\t\tnamespace: namespace\n\t\t});\n\t\t\n\t\t//if(ERDF.log.isDebugEnabled())\n\t\t//\tERDF.log.debug(\"Prefix '\"+prefix+\"' for '\"+namespace+\"' registered.\");\n\t},\n\t\n\tregisterTriple: function(subject, predicate, object) {\n\t\t\n\t\t// if prefix is schema, this is a schema definition.\n\t\tif(predicate.prefix.toLowerCase() == 'schema')\n\t\t\tthis.registerSchema(predicate.name, object.value);\n\t\t\t\n\t\tvar triple = new ERDF.Triple(subject, predicate, object);\n\t\tERDF.callback(triple);\n\t\t\n\t\t//if(ERDF.log.isInfoEnabled())\n\t\t//\tERDF.log.info(triple)\n\t\t\n\t\t// return the registered triple.\n\t\treturn triple;\n\t},\n\t\n\t__enhanceObject: function() {\n\t\t\n\t\t/* Resource state querying methods */\n\t\tthis.isResource = function() {\n\t\t\treturn this.type == ERDF.RESOURCE };\n\t\tthis.isLocal = function() {\n\t\t\treturn this.isResource() && this.value.startsWith('#') };\n\t\tthis.isCurrentDocument = function() {\n\t\t\treturn this.isResource() && (this.value == '') };\n\t\t\n\t\t/* Resource getter methods.*/\n\t\tthis.getId = function() {\n\t\t\treturn this.isLocal() ? ERDF.__stripHashes(this.value) : false; };\n\n\t\t/* Liiteral state querying methods  */\n\t\tthis.isLiteral = function() {\n\t\t\treturn this.type == ERDF.LIITERAL };\n\t},\n\t\n\tserialize: function(literal) {\n\t\t\n\t\tif(!literal){\n\t\t\treturn \"\";\n\t\t}else if(literal.constructor == String) {\n\t\t\treturn literal;\n\t\t} else if(literal.constructor == Boolean) {\n\t\t\treturn literal? 'true':'false';\n\t\t} else {\n\t\t\treturn literal.toString();\n\t\t}\n\t}\n};\n\n\nERDF.Triple = function(subject, predicate, object) {\n\t\n\tthis.subject = subject;\n\tthis.predicate = predicate;\n\tthis.object = object;\n\t\n\tthis.toString = function() {\n\t\t\n\t\treturn \"[ERDF.Triple] \" +\n\t\t\tthis.subject.toString() + ' ' +\n\t\t\tthis.predicate.prefix + ':' + this.predicate.name + ' ' +\n\t\t\tthis.object.toString();\n\t\t};\n};\n\nERDF.Resource = function(uri) {\n\t\n\tthis.type = ERDF.RESOURCE;\n\tthis.value = uri;\n\tERDF.__enhanceObject.apply(this);\n\t\n\tthis.toString = function() {\n\t\treturn '&lt;' + this.value + '&gt;';\n\t}\n\t\n};\n\nERDF.Literal = function(literal) {\n\t\n\tthis.type = ERDF.LITERAL;\n\tthis.value = ERDF.serialize(literal);\n\tERDF.__enhanceObject.apply(this);\n\n\tthis.toString = function() {\n\t\treturn '\"' + this.value + '\"';\n\t}\n};/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/*\n * Save and triple generation behaviour. Use this area to configure\n * data management to your needs.\n */\nvar USE_ASYNCHRONOUS_REQUESTS =\t\ttrue;\nvar DISCARD_UNUSED_TRIPLES =\t\t\ttrue;\nvar PREFER_SPANS_OVER_DIVS =\t\t\ttrue;\nvar PREFER_TITLE_OVER_TEXTNODE =\t\tfalse;\nvar RESOURCE_ID_PREFIX =\t\t\t\t'resource';\n\nvar SHOW_DEBUG_ALERTS_WHEN_SAVING =\tfalse;\nvar SHOW_EXTENDED_DEBUG_INFORMATION =\tfalse;\n\n/*\n * Back end specific workarounds.\n */\n\nvar USE_ARESS_WORKAROUNDS =\t\ttrue;\n\n/*\n * Data management constants. Do not change these, as they are used\n * both internally and externally to communicate on events and to identify\n * command object actions in triple production and embedding rules.\n */\n\n// Resource constants\nvar RESOURCE_CREATED =\t\t\t0x01;\nvar RESOURCE_REMOVED =\t\t\t0x02;\nvar RESOURCE_SAVED =\t\t\t\t0x04;\nvar RESOURCE_RELOADED =\t\t\t0x08;\nvar RESOURCE_SYNCHRONIZED = \t\t0x10;\n\n// Triple constants\nvar TRIPLE_REMOVE =\t0x01;\nvar TRIPLE_ADD =\t\t0x02;\nvar TRIPLE_RELOAD =\t0x04;\nvar TRIPLE_SAVE =\t\t0x08;\n\nvar PROCESSDATA_REF = 'processdata';\n\n// HTTP status code constants\n//\n//// 2xx\n//const 200_OK =\t\t\t'Ok';\n//const 201_CREATED =\t\t'Created';\n//const 202_ACCEPTED =\t\t'Accepted';\n//const 204_NO_CONTENT =\t'No Content';\n//\n//// 3xx\n//const 301_MOVED_PERMANENTLY =\t'Moved Permanently';\n//const 302_MOVED_TEMPORARILY =\t'Moved Temporarily';\n//const 304_NOT_MODIFIED =\t\t'Not Modified';\n//\n//// 4xx\n//const 400_BAD_REQUEST =\t'Bad Request';\n//const 401_UNAUTHORIZED =\t'Unauthorized';\n//const 403_FORBIDDEN =\t\t'Forbidden';\n//const 404_NOT_FOUND =\t\t'Not Found';\n//const 409_CONFLICT =\t\t'Conflict';\n//\n//// 5xx\n//const 500_INTERNAL_SERVER_ERROR =\t\t'Internal Server Error';\n//const 501_NOT_IMPLEMENTED =\t\t\t'Not Implemented';\n//const 502_BAD_GATEWAY =\t\t\t\t'Bad Gateway';\n//const 503_SERVICE_UNAVAILABLE =\t\t'Service Unavailable';\n//\n/**\n * The Data Management object. Use this one when interacting with page internal\n * data. Initialize data management by DataManager.init();\n * @class DataManager\n */\nvar DataManager = {\n\t\n\t/**\n\t * The init method should be called once in the DataManagers lifetime.\n\t * It causes the DataManager to initialize itself, the erdf parser, do all\n\t * neccessary registrations and configurations, to run the parser and\n\t * from then on deliver all resulting triples.\n\t * No parameters needed are needed in a call to this method.\n\t */\n\tinit: function() {\n\t\tERDF.init(DataManager._registerTriple);\n\t\tDataManager.__synclocal();\n\t},\n\t\n\t/**\n\t * This triple array is meant to be the whole knowledge of the DataManager.\n\t */\n\t_triples: [],\n\t\n\t/**\n\t * This method is meant for callback from erdf parsing. It is not to be\n\t * used in another way than to add triples to the triple store.\n\t * @param {Object} triple the triple to add to the triple store.\n\t */\n\t_registerTriple: function(triple) {\n\t\tDataManager._triples.push(triple)\n\t},\n\t\n\t/**\n\t * The __synclocal method is for internal usage only.\n\t * It performs synchronization with the local document, that is, the triple\n\t * store is adjustet to the content of the document, which could have been\n\t * changed by any other applications running on the same page.\n\t */\n\t__synclocal: function() {\n\t\tDataManager._triples = [];\n\t\tERDF.run();\n\t},\n\t\n\t/**\n\t * Makes the shape passed into this method synchronize itself with the DOM.\n\t * This method returns the shapes resource object for further manipulation.\n\t * @param {Object} shape\n\t */\n\t__synchronizeShape: function(shape) {\n\n\t\tvar r = ResourceManager.getResource(shape.resourceId);\n\t\tvar serialize = shape.serialize();\n\n\t\t// store all serialize values\n\t\tserialize.each( function(ser) {\n\t\t\t\n\t\t\tvar resource = (ser.type == 'resource');\n\t\t\tvar _triple = new ERDF.Triple(\n\t\t\t\tnew ERDF.Resource(shape.resourceId),\n\t\t\t\t{prefix: ser.prefix, name: ser.name},\n\t\t\t\tresource ?\n\t\t\t\t\tnew ERDF.Resource(ser.value) :\n\t\t\t\t\tnew ERDF.Literal(ser.value)\n\t\t\t);\n\t\t\tDataManager.setObject(_triple);\n\t\t});\n\t\t\n\t\treturn r;\n\t},\n\n\t__storeShape: function(shape) {\n\t\t\n\t\t// first synchronize the shape,\n\t\tvar resource = DataManager.__synchronizeShape(shape);\n\t\t\n\t\t// then save the synchronized dom.\n\t\tresource.save();\n\t},\n\t\t\n\t__forceExistance: function(shape) {\n\t\t\n\t\tif(!$(shape.resourceId)) {\n\t\t\t\n\t\t\tif(!$$('.' + PROCESSDATA_REF)[0])\n\t\t\t\tDataManager.graft(XMLNS.XHTML,\n\t\t\t\t\tdocument.getElementsByTagNameNS(XMLNS.XHTML, 'body').item(0), ['div', {'class': PROCESSDATA_REF, 'style':'display:none;'}]);\n\t\t\t\t\n\t\t\t// object is literal\n\t\t\tDataManager.graft(XMLNS.XHTML,\n\t\t\t\t$$('.' + PROCESSDATA_REF)[0], [\n\t\t\t\t\n\t\t\t\t'div', {\n                    'id': shape.resourceId,\n                    //This should be done in a more dynamic way!!!!!\n                    'class': (shape instanceof ORYX.Core.Canvas) ? \"-oryx-canvas\" : undefined\n                }\n\t\t\t]);\n\t\t\t\n\t\t} else {\n\t\t\tvar resource = $(shape.resourceId)\n\t\t\tvar children = $A(resource.childNodes)\n\t\t\tchildren.each( function(child) {\n\t\t\t\tresource.removeChild(child);\n\t\t\t});\n\t\t};\n\t},\n\t\n\t__persistShape: function(shape) {\n\n\t\t// a shape serialization.\n\t\tvar shapeData = shape.serialize();\n\t\t\n\t\t// initialize a triple array and construct a shape resource\n\t\t// to be used in triple generation.\n\t\tvar triplesArray = [];\n\t\tvar shapeResource = new ERDF.Resource(shape.resourceId);\n\n\t\t// remove all triples for this particular shape's resource\n\t\tDataManager.removeTriples( DataManager.query(\n\t\t\tshapeResource, undefined, undefined));\n\n\t\t// for each data set in the shape's serialization\n\t\tshapeData.each( function(data) {\n\n\t\t\t// construct a triple's value\n\t\t\tvar value = (data.type == 'resource') ?\n\t\t\t\tnew ERDF.Resource(data.value) :\n\t\t\t\tnew ERDF.Literal(data.value);\n\n\t\t\t// construct triple and add it to the DOM.\n\t\t\tDataManager.addTriple( new ERDF.Triple(\n\t\t\t\tshapeResource,\n\t\t\t\t{prefix: data.prefix, name: data.name},\n\t\t\t\tvalue\n\t\t\t));\n\t\t});\n\t},\n\t\n\t__persistDOM: function(facade) {\n\n\t\t// getChildShapes gets all shapes (nodes AND edges), deep flag\n\t\t// makes it return a flattened child hierarchy.\n\t\t\n\t\tvar canvas = facade.getCanvas();\n\t\tvar shapes = canvas.getChildShapes(true);\n\t\tvar result = '';\n\t\t\n\t\t// persist all shapes.\n\t\tshapes.each( function(shape) {\n\t\t\tDataManager.__forceExistance(shape);\n\t\t});\n\t\t//DataManager.__synclocal();\n\t\t\n\t\tDataManager.__renderCanvas(facade);\n\t\tresult += DataManager.serialize(\n\t\t\t\t$(ERDF.__stripHashes(facade.getCanvas().resourceId)), true);\n\t\t\t\t\n\t\tshapes.each( function(shape) {\n\t\t\t\n\t\t\tDataManager.__persistShape(shape);\n\t\t\tresult += DataManager.serialize(\n\t\t\t\t$(ERDF.__stripHashes(shape.resourceId)), true);\n\t\t});\n\t\t\n\t\t//result += DataManager.__renderCanvas(facade);\n\t\t\n\t\treturn result;\n\t},\n\n\t__renderCanvas: function(facade) {\n\n\t\tvar canvas = facade.getCanvas();\n\t\tvar stencilSets = facade.getStencilSets();\n\t\tvar shapes = canvas.getChildShapes(true);\n\t\t\n\t\tDataManager.__forceExistance(canvas);\n\t\t\n\t\tDataManager.__persistShape(canvas);\n\t\t\n\t\tvar shapeResource = new ERDF.Resource(canvas.resourceId);\n\n\t\t// remove all triples for this particular shape's resource\n\t\tDataManager.removeTriples( DataManager.query(\n\t\t\tshapeResource, undefined, undefined));\n\n\t\tDataManager.addTriple( new ERDF.Triple(\n\t\t\tshapeResource,\n\t\t\t{prefix: \"oryx\", name: \"mode\"},\n\t\t\tnew ERDF.Literal(\"writable\")\n\t\t));\n\n\t\tDataManager.addTriple( new ERDF.Triple(\n\t\t\tshapeResource,\n\t\t\t{prefix: \"oryx\", name: \"mode\"},\n\t\t\tnew ERDF.Literal(\"fullscreen\")\n\t\t));\n\n\t\tstencilSets.values().each(function(stencilset) {\n\t\t\tDataManager.addTriple( new ERDF.Triple(\n\t\t\t\tshapeResource,\n\t\t\t\t{prefix: \"oryx\", name: \"stencilset\"},\n\t\t\t\tnew ERDF.Resource(stencilset.source().replace(/&/g, \"%26\"))\n\t\t\t));\n\t\t\t\n\t\t\tDataManager.addTriple( new ERDF.Triple(\n\t\t\t\tshapeResource,\n\t\t\t\t{prefix: \"oryx\", name: \"ssnamespace\"},\n\t\t\t\tnew ERDF.Resource(stencilset.namespace())\n\t\t\t));\n\t\t\t\n\t\t\tstencilset.extensions().keys().each(function(extension) {\n\t\t\t\tDataManager.addTriple( new ERDF.Triple(\n\t\t\t\t\tshapeResource,\n\t\t\t\t\t{prefix: \"oryx\", name: \"ssextension\"},\n\t\t\t\t\tnew ERDF.Literal(extension)\n\t\t\t\t));\n\t\t\t});\n\t\t});\n\t\t\t\t\t\t\n\t\tshapes.each(function(shape) {\n\t\t\tDataManager.addTriple( new ERDF.Triple(\n\t\t\t\tshapeResource,\n\t\t\t\t{prefix: \"oryx\", name: \"render\"},\n\t\t\t\tnew ERDF.Resource(\"#\" + shape.resourceId)\n\t\t\t));\n\t\t});\n\t},\n\n\t__counter: 0,\n\t__provideId: function() {\n\t\t\n\t\twhile($(RESOURCE_ID_PREFIX+DataManager.__counter))\n\t\t\tDataManager.__counter++;\n\t\t\t\n\t\treturn RESOURCE_ID_PREFIX+DataManager.__counter;\n\t},\n\t\t\n\tserializeDOM: function(facade) {\n\t\t\n\t\treturn DataManager.__persistDOM(facade);\n\t},\n\t\n\tsyncGlobal: function(facade) {\n\t\t\n\t\treturn DataManager.__syncglobal(facade);\n\t},\n\t\n\t/**\n\t * This method is used to synchronize local DOM with remote resources.\n\t * Local changes are commited to the server, and remote changes are\n\t * performed to the local document.\n\t * @param {Object} facade The facade of the editor that holds certain\n\t * resource representations as shapes.\n\t */\n\t__syncglobal: function(facade) {\n\n\t\t// getChildShapes gets all shapes (nodes AND edges), deep flag\n\t\t// makes it return a flattened child hierarchy.\n\t\t\n\t\tvar canvas = facade.getCanvas();\n\t\tvar shapes = canvas.getChildShapes(true);\n\n\t\t// create dummy resource representations in the dom\n\t\t// for all shapes that were newly created.\n\n\t\tshapes.select( function(shape) {\n\n\t\t\t// select shapes without resource id.\n\n\t\t\treturn !($(shape.resourceId));\n\n\t\t}).each( function(shape) {\n\n\t\t\t// create new resources for them.\n\t\t\tif(USE_ARESS_WORKAROUNDS) {\n\t\t\t\t\n\t\t\t\t/*\n\t\t\t\t * This is a workaround due to a bug in aress. Resources are\n\t\t\t\t * ignoring changes to raziel:type property once they are\n\t\t\t\t * created. As long as this is not fixed, the resource is now\n\t\t\t\t * being created using a randomly guessed id, this temporary id\n\t\t\t\t * is then used in references and the appropriate div is being\n\t\t\t\t * populated with properties.\n\t\t\t\t * \n\t\t\t\t * AFTER THIS PHASE THE DATA IS INCONSISTENT AS REFERENCES POINT\n\t\t\t\t * TO IDS THAT ARE UNKNOWN TO THE BACK END.\n\t\t\t\t * \n\t\t\t\t * After the resource is actually created in aress, it gets an id\n\t\t\t\t * that is persistent. All shapes are then being populated with the\n\t\t\t\t * correct id references and stored on the server.\n\t\t\t\t * \n\t\t\t\t * AFTER THE SAVE PROCESS HAS RETURNED, THE DATA IS CONSISTENT\n\t\t\t\t * REGARDING THE ID REFERENCES AGAIN.\n\t\t\t\t */\n\t\t\t\t\n\t\t\t\tvar razielType = shape.properties['raziel-type'];\n\t\t\t\t\n\t\t\t\tvar div = '<div xmlns=\"http://www.w3.org/1999/xhtml\">' +\n\t\t\t\t\t'<span class=\"raziel-type\">'+razielType+'</span></div>';\n\n\t\t\t\tvar r = ResourceManager.__createResource(div);\n\t\t\t\tshape.resourceId = r.id();\n\t\t\t\t\n\t\t\t} else {\n\t\t\n\t\t\t\tvar r = ResourceManager.__createResource();\n\t\t\t\tshape.resourceId = r.id();\n\t\t\t}\n\n\t\t});\n\n\t\tshapes.each( function(shape) {\n\t\t\t\n\t\t\t// store all shapes.\n\t\t\tDataManager.__storeShape(shape);\n\t\t});\n\t},\n\t\n\t/**\n\t * This method serializes a single div into a string that satisfies the\n\t * client/server communication protocol. It ingnores all elements that have\n\t * an attribute named class that includes 'transient'.\n\t * @param {Object} node the element to serialize.\n\t * @param {Object} preserveNamespace whether to preserve the parent's\n\t *                 namespace. If you are not sure about namespaces, provide\n\t *                 just the element to be serialized.\n\t */\n\tserialize: function(node, preserveNamespace) {\n\n\t\tif (node.nodeType == node.ELEMENT_NODE) {\n\t\t\t// serialize an element node.\n\t\t\t\n\t\t\tvar children = $A(node.childNodes);\n\t\t\tvar attributes = $A(node.attributes);\n\t\t\tvar clazz = new String(node.getAttribute('class'));\n\t\t\tvar ignore = clazz.split(' ').member('transient');\n\n\t\t\t// ignore transients.\n\n\t\t\tif(ignore)\n\t\t\t\treturn '';\n\n\t\t\t// start serialization.\n\t\t\t\n\t\t\tvar result = '<' + node.nodeName;\n\t\t\t\n\t\t\t// preserve namespace?\n\t\t\tif(!preserveNamespace) \n\t\t\t\tresult += ' xmlns=\"' + (node.namespaceURI ? node.namespaceURI : XMLNS.XHTML) + '\" xmlns:oryx=\"http://oryx-editor.org\"';\n\t\t\t\n\t\t\t// add all attributes.\n\t\t\t\n\t\t\tattributes.each(function(attribute) {\n\t\t\t\tresult += ' ' + attribute.nodeName + '=\"' +\n\t\t\t\t\tattribute.nodeValue + '\"';});\n\t\t\t\n\t\t\t// close if no children.\n\t\t\t\n\t\t\tif(children.length == 0)\n\t\t\t\tresult += '/>';\n\t\t\t\t\n\t\t\telse {\n\t\t\t\t\n\t\t\t\t// serialize all children.\n\t\t\t\t\n\t\t\t\tresult += '>';\n\t\t\t\tchildren.each(function(_node) {\n\t\t\t\t\tresult += DataManager.serialize(_node, true)});\n\t\t\t\tresult += '</' + node.nodeName + '>'\n\t\t\t}\n\n\t\t\treturn result;\n\t\t\t\n\t\t} else if (node.nodeType == node.TEXT_NODE) {\n\t\t\t\n\t\t\t// serialize a text node.\n\t\t\treturn  node.nodeValue;\n\t\t}\n\t\t\n\t\t//TODO serialize cdata areas also.\n\t\t//TODO work on namespace awareness.\n\t},\n\n\taddTriple: function(triple) {\n\n\t\t// assert the subject is a resource\n\t\t\n\t\tif(!triple.subject.type == ERDF.LITERAL)\n\t\t\tthrow 'Cannot add the triple ' + triple.toString() +\n\t\t\t\t' because the subject is not a resource.'\n\t\t\n\t\t// get the element which represents this triple's subject.\n\t\tvar elementId = ERDF.__stripHashes(triple.subject.value);\n\t\tvar element = $(elementId);\n\t\t\t\t\n\t\t// assert the subject is inside this document.\n\t\tif(!element)\n\t\t\tthrow 'Cannot add the triple ' + triple.toString() +\n\t\t\t\t' because the subject \"'+elementId+'\" is not in the document.';\n\n\t\tif(triple.object.type == ERDF.LITERAL)\n\n\t\t\t// object is literal\n\t\t\tDataManager.graft(XMLNS.XHTML, element, [\n\t\t\t\t'span', {'class': (triple.predicate.prefix + \"-\" +\n\t\t\t\t\ttriple.predicate.name)}, triple.object.value.escapeHTML()\n\t\t\t]);\n\t\t\t\n\t\telse {\n\n\t\t\t// object is resource\n\t\t\tDataManager.graft(XMLNS.XHTML, element, [\n\t\t\t\t'a', {'rel': (triple.predicate.prefix + \"-\" +\n\t\t\t\t\ttriple.predicate.name), 'href': triple.object.value}\n\t\t\t]);\n\t\t\t\n\t\t}\n\n\t\treturn true;\n\t},\n\t\n\tremoveTriples: function(triples) {\n\n\t\t// alert('Removing ' +triples.length+' triples.');\n\n\t\t// from all the triples select those ...\n\t\tvar removed = triples.select(\n\n\t\t\tfunction(triple) {\n\t\t\t\t\n\t\t\t\t// TODO remove also from triple store.\n\t\t\t\t// ... that were actually removed.\n\t\t\t\treturn DataManager.__removeTriple(triple);\n\t\t\t});\n\t\t\n\t\t// sync and return removed triples.\n\t\t// DataManager.__synclocal();\n\t\treturn removed;\n\t},\n\t\n\tremoveTriple: function(triple) {\n\t\t\n\t\t// remember whether the triple was actually removed.\n\t\tvar result = DataManager.__removeTriple(triple);\n\n\t\t// sync and return removed triples.\n\t\t// DataManager.__synclocal();\n\t\treturn result;\n\t},\n\n\t__removeTriple: function(triple) {\n\t\t\n\t\t// assert the subject is a resource\n\t\tif(!triple.subject.type == ERDF.LITERAL)\n\t\t\n\t\t\tthrow 'Cannot remove the triple ' + triple.toString() +\n\t\t\t\t' because the subject is not a resource.';\n\n\t\t// get the element which represents this triple's subject.\n\t\tvar elementId = ERDF.__stripHashes(triple.subject.value);\n\t\tvar element = $(elementId);\n\n\t\t// assert the subject is inside this document.\n\t\tif(!element)\n\t\t\n\t\t\tthrow 'Cannot remove the triple ' + triple.toString() +\n\t\t\t\t' because the subject is not in the document.';\n\t  \n\t\tif(triple.object.type == ERDF.LITERAL) {\n\t  \n  \t\t\t// continue searching actively for the triple.\n\t\t\tvar result = DataManager.__removeTripleRecursively(triple, element);\n\t\t\treturn result;\n\t\t}\n\t},\n\n\t__removeTripleRecursively: function(triple, continueFrom) {  \n\n\t\t// return when this node is not an element node.\n\t\tif(continueFrom.nodeType != continueFrom.ELEMENT_NODE)\n\t\t\treturn false;\n\t\t\n\t\tvar classes = new String(continueFrom.getAttribute('class'));\n\t\tvar children = $A(continueFrom.childNodes);\n\t\t\n\t\tif(classes.include(triple.predicate.prefix + '-' + triple.predicate.name)) {\n\t\t  \n\t\t\tvar content = continueFrom.textContent;\n\t\t\tif(\t(triple.object.type == ERDF.LITERAL) &&\n\t\t\t\t(triple.object.value == content))\n\n\t\t\t\tcontinueFrom.parentNode.removeChild(continueFrom);\n\t\t\t\n\t\t\treturn true;\n\t\t  \n\t\t} else {\n\t\t \n\t\t\tchildren.each(function(_node) {\n\t\t\tDataManager.__removeTripleRecursively(triple, _node)});\n\t\t\treturn false;\n\t\t}\n\n\t},\n\n\t/**\n\t * graft() function\n\t * Originally by Sean M. Burke from interglacial.com, altered for usage with\n\t * SVG and namespace (xmlns) support. Be sure you understand xmlns before\n\t * using this funtion, as it creates all grafted elements in the xmlns\n\t * provided by you and all element's attribures in default xmlns. If you\n\t * need to graft elements in a certain xmlns and wish to assign attributes\n\t * in both that and another xmlns, you will need to do stepwise grafting,\n\t * adding non-default attributes yourself or you'll have to enhance this\n\t * function. Latter, I would appreciate: martin???apfelfabrik.de\n\t * @param {Object} namespace The namespace in which\n\t * \t\t\t\t\telements should be grafted.\n\t * @param {Object} parent The element that should contain the grafted\n\t * \t\t\t\t\tstructure after the function returned.\n\t * @param {Object} t the crafting structure.\n\t * @param {Object} doc the document in which grafting is performed.\n\t */\n\tgraft: function(namespace, parent, t, doc) {\n\t\t\n\t    doc = (doc || (parent && parent.ownerDocument) || document);\n\t    var e;\n\t    if(t === undefined) {\n\t        echo( \"Can't graft an undefined value\");\n\t    } else if(t.constructor == String) {\n\t        e = doc.createTextNode( t );\n\t    } else {\n\t        for(var i = 0; i < t.length; i++) {\n\t            if( i === 0 && t[i].constructor == String ) {\n\t\t\t\t\tvar snared = t[i].match( /^([a-z][a-z0-9]*)\\.([^\\s\\.]+)$/i );\n\t                if( snared ) {\n\t                    e = doc.createElementNS(namespace, snared[1]);\n\t                    e.setAttributeNS(null, 'class', snared[2] );\n\t                    continue;\n\t                }\n\t                snared = t[i].match( /^([a-z][a-z0-9]*)$/i );\n\t                if( snared ) {\n\t                    e = doc.createElementNS(namespace, snared[1]);  // but no class\n\t                    continue;\n\t                }\n\t\n\t                // Otherwise:\n\t                e = doc.createElementNS(namespace, \"span\");\n\t                e.setAttribute(null, \"class\", \"namelessFromLOL\" );\n\t            }\n\t\n\t            if( t[i] === undefined ) {\n\t                echo(\"Can't graft an undefined value in a list!\");\n\t            } else if( t[i].constructor == String || t[i].constructor == Array) {\n\t                this.graft(namespace, e, t[i], doc );\n\t            } else if(  t[i].constructor == Number ) {\n\t                this.graft(namespace, e, t[i].toString(), doc );\n\t            } else if(  t[i].constructor == Object ) {\n\t                // hash's properties => element's attributes\n\t                for(var k in t[i]) { e.setAttributeNS(null, k, t[i][k] ); }\n\t            } else if(  t[i].constructor == Boolean ) {\n\t                this.graft(namespace, e, t[i] ? 'true' : 'false', doc );\n\t\t\t\t} else\n\t\t\t\t\tthrow \"Object \" + t[i] + \" is inscrutable as an graft arglet.\";\n\t        }\n\t    }\n\t\t\n\t\tif(parent) parent.appendChild(e);\n\t\n\t    return Element.extend(e); // return the topmost created node\n\t},\n\n\tsetObject: function(triple) {\n\n\t\t/**\n\t\t * Erwartungen von Arvid an diese Funktion:\n\t\t * - Es existiert genau ein triple mit dem Subjekt und Praedikat,\n\t\t *   das uebergeben wurde, und dieses haelt uebergebenes Objekt.\n\t\t */\n\n\t\tvar triples = DataManager.query(\n\t\t\ttriple.subject,\n\t\t\ttriple.predicate,\n\t\t\tundefined\n\t\t);\n\t\t\n\t\tDataManager.removeTriples(triples);\n\n\t\tDataManager.addTriple(triple);\n\n\t\treturn true;\n\t},\n\t\n\tquery: function(subject, predicate, object) {\n\n\t\t/*\n\t\t * Typical triple.\n\t\t *\t{value: subject, type: subjectType},\n\t\t *\t{prefix: schema.prefix, name: property},\n\t\t *\t{value: object, type: objectType});\n\t\t */\t\n\t\t \t\n\t\treturn DataManager._triples.select(function(triple) {\n\t\t\t\n\t\t\tvar select = ((subject) ?\n\t\t\t\t(triple.subject.type == subject.type) &&\n\t\t\t\t(triple.subject.value == subject.value) : true);\n\t\t\tif(predicate) {\n\t\t\t\tselect = select && ((predicate.prefix) ?\n\t\t\t\t\t(triple.predicate.prefix == predicate.prefix) : true);\n\t\t\t\tselect = select && ((predicate.name) ?\n\t\t\t\t\t(triple.predicate.name == predicate.name) : true);\n\t\t\t}\n\t\t\tselect = select && ((object) ?\n\t\t\t\t(triple.object.type == object.type) &&\n\t\t\t\t(triple.object.value == object.value) : true);\n\t\t\treturn select;\n\t\t});\n\t}\n}\n\nKickstart.register(DataManager.init);\n\nfunction assert(expr, m) { if(!expr) throw m; };\n\nfunction DMCommand(action, triple) {\n\t\n\t// store action and triple.\n\tthis.action = action;\n\tthis.triple = triple;\n\t\n\tthis.toString = function() {\n\t\treturn 'Command('+action+', '+triple+')';\n\t};\n}\n\nfunction DMCommandHandler(nextHandler) {\n\t\n\t/**\n\t * Private method to set the next handler in the Chain of Responsibility\n\t * (see http://en.wikipedia.org/wiki/Chain-of-responsibility_pattern for\n\t * details).\n\t * @param {DMCommandHandler} handler The handler that is next in the chain.\n\t */\n\tthis.__setNext = function(handler) {\n\t\tvar _next = this.__next;\n\t\tthis.__next = nextHandler;\n\t\treturn _next ? _next : true;\n\t};\n\tthis.__setNext(nextHandler);\n\n\t/**\n\t * Invokes the next handler. If there is no next handler, this method\n\t * returns false, otherwise it forwards the result of the handling.\n\t * @param {Object} command The command object to be processed.\n\t */\n\tthis.__invokeNext = function(command) {\n\t\treturn this.__next ? this.__next.handle(command) : false;\n\t};\n\t\n\t/**\n\t * Handles a command. The abstract method process() is called with the\n\t * command object that has been passed. If the process method catches the\n\t * command (returns true on completion), the handle() method returns true.\n\t * If the process() method doesn't catch the command, the next handler will\n\t * be invoked.\n\t * @param {Object} command The command object to be processed.\n\t */\n\tthis.handle = function(command) {\n\t\treturn this.process(command) ? true : this.__invokeNext(command);\n\t}\n\t\n\t/**\n\t * Empty process() method returning false. If javascript knew abstract\n\t * class members, this would be one.\n\t * @param {Object} command The command object to process.\n\t */\n\tthis.process = function(command) { return false; };\n};\n\n/**\n * This Handler manages the addition and the removal of meta elements in the\n * head of the document.\n * @param {DMCommandHandler} next The handler that is next in the chain.\n */\nfunction MetaTagHandler(next) {\n\t\n\tDMCommandHandler.apply(this, [next]);\n\tthis.process = function(command) {\n\t\t\n\t\twith(command.triple) {\n\t\t\t\n\t\t\t/* assert prerequisites */\n\t\t\tif( !(\n\t\t\t\t(subject instanceof ERDF.Resource) &&\n\t\t\t\t(subject.isCurrentDocument()) &&\n\t\t\t\t(object instanceof ERDF.Literal)\n\t\t\t))\treturn false;\n\t\t}\n\t\t\n\t};\n};\n\nvar chain =\tnew MetaTagHandler();\nvar command = new DMCommand(TRIPLE_ADD, new ERDF.Triple(\n\tnew ERDF.Resource(''),\n\t'rdf:tool',\n\tnew ERDF.Literal('')\n));\n\n/*\nif(chain.handle(command))\n\talert('Handled!');\n*/\n\nResourceManager = {\n\t\n\t__corrupt: false,\n\t__latelyCreatedResource: undefined,\n\t__listeners: $H(),\n\t__token: 1,\n\t\n\taddListener: function(listener, mask) {\n\n\t\tif(!(listener instanceof Function))\n\t\t\tthrow 'Resource event listener is not a function!';\n\t\tif(!(mask))\n\t\t\tthrow 'Invalid mask for resource event listener registration.';\n\n\t\t// construct controller and token.\n\t\tvar controller = {listener: listener, mask: mask};\n\t\tvar token = ResourceManager.__token++;\n\t\t\n\t\t// add new listener.\n\t\tResourceManager.__listeners[token] = controller;\n\t\t\n\t\t// return the token generated.\n\t\treturn token;\n\t},\n\t\n\tremoveListener: function(token) {\n\t\t\n\t\t// remove the listener with the token and return it.\n\t\treturn ResourceManager.__listners.remove(token);\n\t},\n\t\n\t__Event: function(action, resourceId) {\n\t\tthis.action = action;\n\t\tthis.resourceId = resourceId;\n\t},\n\t\n\t__dispatchEvent: function(event) {\n\t\t\n\t\t// get all listeners. for each listener, ...\n\t\tResourceManager.__listeners.values().each(function(controller) {\n\t\t\t\n\t\t\t// .. if listener subscribed to this type of event ...\n\t\t\tif(event.action & controller.mask)\n\t\t\t\treturn controller.listener(event);\n\t\t});\n\t},\n\n\tgetResource: function(id) {\n\n\t\t// get all possible resources for this.\n\t\tid = ERDF.__stripHashes(id);\n\t\tvar resources = DataManager.query(\n\t\t\tnew ERDF.Resource('#'+id),\n\t\t\t{prefix: 'raziel', name: 'entry'},\n\t\t\tundefined\n\t\t);\n\n\t\t// check for consistency.\n\t\tif((resources.length == 1) && (resources[0].object.isResource())) {\n\t\t\tvar entryUrl = resources[0].object.value;\n\t\t\treturn new ResourceManager.__Resource(id, entryUrl);\n\t\t}\n\n\t\t// else throw an error message.\n\t\tthrow ('Resource with id ' +id+ ' not recognized as such. ' +\n\t\t\t((resources.length > 1) ?\n\t\t\t\t' There is more than one raziel:entry URL.' :\n\t\t\t\t' There is no raziel:entry URL.'));\n\n\t\treturn false;\n\t},\n\n\t__createResource: function(alternativeDiv) {\n\t\t\n\t\tvar collectionUrls = DataManager.query(\n\t\t\tnew ERDF.Resource(''),\n\t\t\t// TODO This will become raziel:collection in near future.\n\t\t\t{prefix: 'raziel', name: 'collection'},\n\t\t\tundefined\n\t\t);\n\n\t\t// check for consistency.\n\t\t\n\t\tif(\t(collectionUrls.length == 1) &&\n\t\t\t(collectionUrls[0].object.isResource())) {\n\n\t\t\t// get the collection url.\n\t\t\t\n\t\t\tvar collectionUrl = collectionUrls[0].object.value;\n\t\t\tvar resource = undefined;\n\t\t\t\n\t\t\t// if there is an old id, serialize the dummy div from there,\n\t\t\t// otherwise create a dummy div on the fly.\n\t\t\t\n\t\t\tvar serialization = alternativeDiv? alternativeDiv : \n\t\t\t\t\t'<div xmlns=\"http://www.w3.org/1999/xhtml\"></div>';\n\t\t\t\t\t\n\t\t\tResourceManager.__request(\n\t\t\t\t'POST', collectionUrl, serialization,\n\n\t\t\t\t// on success\n\t\t\t\tfunction() {\n\t\t\t\t\t\n\t\t\t\t\t// get div and id that have been generated by the server.\n\t\t\t\t\t\n\t\t\t\t\tvar response = (this.responseXML);\n\t\t\t\t\tvar div = response.childNodes[0];\n\t\t\t\t\tvar id = div.getAttribute('id');\n\t\t\t\t\t\n\t\t\t\t\t// store div in DOM\n\t\t\t\t\tif(!$$('.' + PROCESSDATA_REF)[0])\n\t\t\t\t\t\tDataManager.graft(XMLNS.XHTML,\n\t\t\t\t\t\t\tdocument.getElementsByTagNameNS(XMLNS.XHTML, 'body').item(0), ['div', {'class': PROCESSDATA_REF, 'style':'display:none;'}]);\n\t\t\t\t\n\t\t\t\t\t$$('.' + PROCESSDATA_REF)[0].appendChild(div.cloneNode(true));\n\n\t\t\t\t\t// parse local erdf data once more.\n\t\t\t\t\t\n\t\t\t\t\tDataManager.__synclocal();\n\t\t\t\t\t\n\t\t\t\t\t// get new resource object.\n\n\t\t\t\t\tresource = new ResourceManager.getResource(id);\n\n\t\t\t\t\t// set up an action informing of the creation.\n\t\t\t\t\t\n\t\t\t\t\tResourceManager.__resourceActionSucceeded(\n\t\t\t\t\t\tthis, RESOURCE_CREATED, undefined);\n\t\t\t\t},\n\n\t\t\t\tfunction() { ResourceManager.__resourceActionFailed(\n\t\t\t\t\tthis, RESOURCE_CREATED, undefined);},\n\t\t\t\tfalse\n\t\t\t);\n\t\t\t\n\t\t\treturn resource;\n\t\t}\n\t\t\n\t\t// else\n\t\tthrow 'Could not create resource! raziel:collection URL is missing!';\n\t\treturn false;\n\n\t},\n\t\n\t__Resource: function(id, url) {\n\t\t\n\t\tthis.__id = id;\n\t\tthis.__url = url;\n\t\t\n\t\t/*\n\t\t * Process URL is no longer needed to refer to the shape element on the\n\t\t * canvas. AReSS uses the id's to gather information on fireing\n\t\t * behaviour now.\n\t\t */\n\t\t\n//\t\t// find the process url.\t\t\n//\t\tvar processUrl = undefined;\n//\t\t\n//\t\tvar urls = DataManager.query(\n//\t\t\tnew ERDF.Resource('#'+this.__id),\n//\t\t\t{prefix: 'raziel', name: 'process'},\n//\t\t\tundefined\n//\t\t);\n//\t\t\n//\t\tif(urls.length == 0) { throw 'The resource with the id ' +id+ ' has no process url.'};\n//\t\t\n//\t\turls.each( function(triple) {\n//\t\t\t\n//\t\t\t// if there are more urls, use the last one.\n//\t\t\tprocessUrl = triple.object.value;\n//\t\t});\n//\t\t\n//\t\tthis.__processUrl = processUrl;\n//\n//\t\t// convenience function for getting the process url.\n//\t\tthis.processUrl = function() {\n//\t\t\treturn this.__processUrl;\n//\t\t}\n\n\n\t\t// convenience finction for getting the id.\n\t\tthis.id = function() {\n\t\t\treturn this.__id;\n\t\t}\n\n\t\t// convenience finction for getting the entry url.\n\t\tthis.url = function() {\n\t\t\treturn this.__url;\n\t\t}\n\t\t\n\t\tthis.reload = function() {\n\t\t\tvar _url = this.__url;\n\t\t\tvar _id = this.__id;\n\t\t\tResourceManager.__request(\n\t\t\t\t'GET', _url, null,\n\t\t\t\tfunction() { ResourceManager.__resourceActionSucceeded(\n\t\t\t\t\tthis, RESOURCE_RELOADED, _id); },\n\t\t\t\tfunction() { ResourceManager.__resourceActionFailed(\n\t\t\t\t\tthis, RESURCE_RELOADED, _id); },\n\t\t\t\tUSE_ASYNCHRONOUS_REQUESTS\n\t\t\t);\n\t\t};\n\t\t\n\t\tthis.save = function(synchronize) {\n\t\t\tvar _url = this.__url;\n\t\t\tvar _id = this.__id;\n\t\t\tdata = DataManager.serialize($(_id));\n\t\t\tResourceManager.__request(\n\t\t\t\t'PUT', _url, data,\n\t\t\t\tfunction() { ResourceManager.__resourceActionSucceeded(\n\t\t\t\t\tthis, synchronize ? RESOURCE_SAVED | RESOURCE_SYNCHRONIZED : RESOURCE_SAVED, _id); },\n\t\t\t\tfunction() { ResourceManager.__resourceActionFailed(\n\t\t\t\t\tthis, synchronize ? RESOURCE_SAVED | RESOURCE_SYNCHRONIZED : RESOURCE.SAVED, _id); },\n\t\t\t\tUSE_ASYNCHRONOUS_REQUESTS\n\t\t\t);\n\t\t};\n\t\t\n\t\tthis.remove = function() {\n\t\t\tvar _url = this.__url;\n\t\t\tvar _id = this.__id;\n\t\t\tResourceManager.__request(\n\t\t\t\t'DELETE', _url, null,\n\t\t\t\tfunction() { ResourceManager.__resourceActionSucceeded(\n\t\t\t\t\tthis, RESOURCE_REMOVED, _id); },\n\t\t\t\tfunction() { ResourceManager.__resourceActionFailed(\n\t\t\t\t\tthis, RESOURCE_REMOVED, _id);},\n\t\t\t\tUSE_ASYNCHRONOUS_REQUESTS\n\t\t\t);\n\t\t};\n\t},\n\n\trequest: function(url, requestOptions) {\n\n\t\tvar options = {\n\t\t\tmethod:       'get',\n\t\t\tasynchronous: true,\n\t\t\tparameters:   {}\n\t\t};\n\n\t\tObject.extend(options, requestOptions || {});\n \t\t\n\t\tvar params = Hash.toQueryString(options.parameters);\n\t\tif (params) \n\t\t\turl += (url.include('?') ? '&' : '?') + params;\n   \n\t\treturn ResourceManager.__request(\n\t\t\toptions.method, \n\t\t\turl, \n\t\t\toptions.data, \n\t\t\t(options.onSuccess instanceof Function ? function() { options.onSuccess(this); } : undefined ), \n\t\t\t(options.onFailure instanceof Function ? function() { options.onFailure(this); } : undefined ), \n\t\t\toptions.asynchronous && USE_ASYNCHRONOUS_REQUESTS,\n\t\t\toptions.headers);\n\t},\n\t\n\t__request: function(method, url, data, success, error, async, headers) {\n\t\t\n\t\t// get a request object\n\t\tvar httpRequest = Try.these(\n\n\t\t\t/* do the Mozilla/Safari/Opera stuff */\n\t\t\tfunction() { return new XMLHttpRequest(); },\n\t\t\t\n\t\t\t/* do the IE stuff */\n\t\t\tfunction() { return new ActiveXObject(\"Msxml2.XMLHTTP\"); },\n\t\t\tfunction() { return new ActiveXObject(\"Microsoft.XMLHTTP\") }\n\t\t);\n\n\t\t// if there is no request object ...\n        if (!httpRequest) {\n\t\t\tif(!this.__corrupt)\n\t\t\t\tthrow 'This browser does not provide any AJAX functionality. You will not be able to use the software provided with the page you are viewing. Please consider installing appropriate extensions.';\n\t\t\tthis.__corrupt = true;\n\t\t\treturn false;\n        }\n\t\t\n\t\tif(success instanceof Function)\n\t\t\thttpRequest.onload = success;\n\t\tif(error instanceof Function) {\n\t\t\thttpRequest.onerror = error;\n\t\t}\n\t\t\n\t\tvar h = $H(headers)\n\t\th.keys().each(function(key) {\n\t\t\t\n\t\t\thttpRequest.setRequestHeader(key, h[key]);\n\t\t}); \n\t\t\n\t\ttry {\n\n\t\t\tif(SHOW_DEBUG_ALERTS_WHEN_SAVING)\n\t\t\t\n\t\t\t\talert(method + ' ' + url + '\\n' +\n\t\t\t\t\tSHOW_EXTENDED_DEBUG_INFORMATION ? data : '');\n\n\t\t\t// TODO Remove synchronous calls to the server as soon as xenodot\n\t\t\t// handles asynchronous requests without failure.\n\t        httpRequest.open(method, url, !async?false:true);\n\t        httpRequest.send(data);\n\t\t\t\n\t\t} catch(e) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n    },\n\n\t__resourceActionSucceeded: function(transport, action, id) {\n\t\t\n\t\tvar status = transport.status;\n\t\tvar response = transport.responseText;\n\t\t\n\t\tif(SHOW_DEBUG_ALERTS_WHEN_SAVING)\n\n\t\t\talert(status + ' ' + url + '\\n' +\n\t\t\t\tSHOW_EXTENDED_DEBUG_INFORMATION ? data : '');\n\n\t\t// if the status code is not in 2xx, throw an error.\n\t\tif(status >= 300)\n\t\t\tthrow 'The server responded with an error: ' + status + '\\n' + (SHOW_EXTENDED_DEBUG_INFORMATION ? + data : 'If you need additional information here, including the data sent by the server, consider setting SHOW_EXTENDED_DEBUG_INFORMATION to true.');\n\n\t\tswitch(action) {\n\t\t\t\n\t\t\tcase RESOURCE_REMOVED:\n\n\t\t\t\t// get div and id\n\t\t\t\tvar response = (transport.responseXML);\n\t\t\t\tvar div = response.childNodes[0];\n\t\t\t\tvar id = div.getAttribute('id');\n\t\t\t\t\n\t\t\t\t// remove the resource from DOM\n\t\t\t\tvar localDiv = document.getElementById(id);\n\t\t\t\tlocalDiv.parentNode.removeChild(localDiv);\n\t\t\t\tbreak;\n\n\t\t\tcase RESOURCE_CREATED:\n\n\t\t\t\t// nothing remains to be done.\n\t\t\t\tbreak;\n\t\n\t\t\tcase RESOURCE_SAVED | RESOURCE_SYNCHRONIZED:\n\n\t\t\t\tDataManager.__synclocal();\n\n\t\t\tcase RESOURCE_SAVED:\n\n\t\t\t\t// nothing remains to be done.\n\t\t\t\tbreak;\n\n\t\t\tcase RESOURCE_RELOADED:\n\t\t\t\n\t\t\t\t// get div and id\n\t\t\t\tvar response = (transport.responseXML);\n\t\t\t\tvar div = response.childNodes[0];\n\t\t\t\tvar id = div.getAttribute('id');\n\t\t\t\t\n\t\t\t\t// remove the local resource representation from DOM\n\t\t\t\tvar localDiv = document.getElementById(id)\n\t\t\t\tlocalDiv.parentNode.removeChild(localDiv);\n\t\t\t\t\n\t\t\t\t// store div in DOM\n\t\t\t\tif(!$$(PROCESSDATA_REF)[0])\n\t\t\t\t\tDataManager.graft(XMLNS.XHTML,\n\t\t\t\t\t\tdocument.getElementsByTagNameNS(XMLNS.XHTML, 'body').item(0), ['div', {'class': PROCESSDATA_REF, 'style':'display:none;'}]);\n\t\t\t\t\n\t\t\t\t$$(PROCESSDATA_REF)[0].appendChild(div.cloneNode(true));\n\t\t\t\tDataManager.__synclocal();\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tDataManager.__synclocal();\n\n\t\t}\n\t\t \n\t\t// dispatch to all listeners ...\n\t\tResourceManager.__dispatchEvent(\n\n\t\t\t// ... an event describing the change that happened here.\n\t\t\tnew ResourceManager.__Event(action, id)\n\t\t);\n\t},\n\n\t__resourceActionFailed: function(transport, action, id) {\n\t\tthrow \"Fatal: Resource action failed. There is something horribly \" +\n\t\t\t\"wrong with either the server, the transport protocol or your \" +\n\t\t\t\"online status. Sure you're online?\";\n\t}\n}/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * The super class for all classes in ORYX. Adds some OOP feeling to javascript.\n * See article \"Object Oriented Super Class Method Calling with JavaScript\" on\n * http://truecode.blogspot.com/2006/08/object-oriented-super-class-method.html\n * for a documentation on this. Fairly good article that points out errors in\n * Douglas Crockford's inheritance and super method calling approach.\n * Worth reading.\n * @class Clazz\n */\nvar Clazz = function() {};\n\n/**\n * Empty constructor.\n * @methodOf Clazz.prototype\n */\nClazz.prototype.construct = function() {};\n\n/**\n * Can be used to build up inheritances of classes.\n * @example\n * var MyClass = Clazz.extend({\n *   construct: function(myParam){\n *     // Do sth.\n *   }\n * });\n * var MySubClass = MyClass.extend({\n *   construct: function(myParam){\n *     // Use this to call constructor of super class\n *     arguments.callee.$.construct.apply(this, arguments);\n *     // Do sth.\n *   }\n * });\n * @param {Object} def The definition of the new class.\n */\nClazz.extend = function(def) {\n    var classDef = function() {\n        if (arguments[0] !== Clazz) { this.construct.apply(this, arguments); }\n    };\n    \n    var proto = new this(Clazz);\n    var superClass = this.prototype;\n    \n    for (var n in def) {\n        var item = def[n];                        \n        if (item instanceof Function) item.$ = superClass;\n        proto[n] = item;\n    }\n\n    classDef.prototype = proto;\n    \n    //Give this new class the same static extend method    \n    classDef.extend = this.extend;        \n    return classDef;\n};/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nif(!ORYX) var ORYX = {};\n\nif(!ORYX.CONFIG) ORYX.CONFIG = {};\n\n/**\n * This file contains URI constants that may be used for XMLHTTPRequests.\n */\n\nORYX.CONFIG.ROOT_PATH =\t\t\t\t\t\"editor/\"; //TODO: Remove last slash!!\nORYX.CONFIG.EXPLORER_PATH =\t\t\t\t\"explorer\";\nORYX.CONFIG.LIBS_PATH =\t\t\t\t\t\"libs\";\n\n/**\n * Regular Config\n */\t\nORYX.CONFIG.SERVER_HANDLER_ROOT = \t\t\t\"service\";\nORYX.CONFIG.SERVER_EDITOR_HANDLER =\t\t\tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/editor\";\nORYX.CONFIG.SERVER_MODEL_HANDLER =\t\t\tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/model\";\nORYX.CONFIG.STENCILSET_HANDLER = \t\t\tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/editor_stencilset?embedsvg=true&url=true&namespace=\";    \nORYX.CONFIG.STENCIL_SETS_URL = \t\t\t\tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/editor_stencilset\";\n\nORYX.CONFIG.PLUGINS_CONFIG =\t\t\t\t\"editor-app/plugins.xml\";\nORYX.CONFIG.SYNTAXCHECKER_URL =\t\t\t\tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/syntaxchecker\";\nORYX.CONFIG.DEPLOY_URL = \t\t\t\t\tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/model/deploy\";\nORYX.CONFIG.MODEL_LIST_URL = \t\t\t\tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/models\";\nORYX.CONFIG.FORM_FLOW_LIST_URL = \t\t\tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/formflows\";\nORYX.CONFIG.FORM_FLOW_IMAGE_URL = \t\t\tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/formflow\";\nORYX.CONFIG.FORM_LIST_URL = \t\t\t\tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/forms\";\nORYX.CONFIG.FORM_IMAGE_URL = \t\t\t\tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/form\";\nORYX.CONFIG.SUB_PROCESS_LIST_URL = \t\t\tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/subprocesses\";\nORYX.CONFIG.SUB_PROCESS_IMAGE_URL = \t\tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/subprocess\";\nORYX.CONFIG.TEST_SERVICE_URL = \t\t\t\tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/service/\";\n\nORYX.CONFIG.SERVICE_LIST_URL = \t\t\t\tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/services\";\nORYX.CONFIG.CONDITION_ELEMENT_LIST_URL = \tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/conditionelements\";\nORYX.CONFIG.VARIABLEDEF_ELEMENT_LIST_URL = \tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/variabledefinitionelements\";\nORYX.CONFIG.VALIDATOR_LIST_URL = \t\t\tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/validators\";\n\nORYX.CONFIG.SS_EXTENSIONS_FOLDER =\t\t\tORYX.CONFIG.ROOT_PATH + \"stencilsets/extensions/\";\nORYX.CONFIG.SS_EXTENSIONS_CONFIG =\t\t\tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/editor_ssextensions\";\t\nORYX.CONFIG.ORYX_NEW_URL =\t\t\t\t\t\"/new\";\t\nORYX.CONFIG.BPMN_LAYOUTER =\t\t\t\t\tORYX.CONFIG.ROOT_PATH + \"bpmnlayouter\";\n\nORYX.CONFIG.EXPRESSION_METADATA_URL = \t\t\tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/expression-metadata\";\nORYX.CONFIG.DATASOURCE_METADATA_URL = \t\t\tORYX.CONFIG.SERVER_HANDLER_ROOT + \"/datasource-metadata\";/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nif(!ORYX) var ORYX = {};\n\nif(!ORYX.CONFIG) ORYX.CONFIG = {};\n\n/**\n * Signavio specific variables\n */\nORYX.CONFIG.BACKEND_SWITCH \t\t= \t\ttrue;\nORYX.CONFIG.PANEL_LEFT_WIDTH \t= \t\t250;\nORYX.CONFIG.PANEL_RIGHT_COLLAPSED \t= \ttrue;\nORYX.CONFIG.PANEL_RIGHT_WIDTH\t= \t\t300;\nORYX.CONFIG.APPNAME = \t\t\t\t\t'KISBPM';\nORYX.CONFIG.WEB_URL = \t\t\t\t\t\".\";\n\nORYX.CONFIG.BLANK_IMAGE = ORYX.CONFIG.LIBS_PATH + '/ext-2.0.2/resources/images/default/s.gif';\n\n/* Specify offset of header */\nORYX.CONFIG.OFFSET_HEADER = 61;\n\n/* Show grid line while dragging */\nORYX.CONFIG.SHOW_GRIDLINE = \t\t\ttrue;\n\n\t/* Editor-Mode */\nORYX.CONFIG.MODE_READONLY =\t\t\t\t\"readonly\";\nORYX.CONFIG.MODE_FULLSCREEN =\t\t\t\"fullscreen\";\nORYX.CONFIG.WINDOW_HEIGHT = \t\t\t800;\t\nORYX.CONFIG.PREVENT_LOADINGMASK_AT_READY = false;\n\n\t/* Plugins */\nORYX.CONFIG.PLUGINS_ENABLED =\t\t\ttrue;\nORYX.CONFIG.PLUGINS_FOLDER =\t\t\t\"Plugins/\";\n\nORYX.CONFIG.BPMN20_SCHEMA_VALIDATION_ON = true;\n\n\t/* Namespaces */\nORYX.CONFIG.NAMESPACE_ORYX =\t\t\t\"http://www.b3mn.org/oryx\";\nORYX.CONFIG.NAMESPACE_SVG =\t\t\t\t\"http://www.w3.org/2000/svg\";\n\n\t/* UI */\nORYX.CONFIG.CANVAS_WIDTH =\t\t\t\t1200; \nORYX.CONFIG.CANVAS_HEIGHT =\t\t\t\t1050;\nORYX.CONFIG.CANVAS_RESIZE_INTERVAL =\t100;\nORYX.CONFIG.CANVAS_MIN_WIDTH =  800;\nORYX.CONFIG.CANVAS_MIN_HEIGHT =  300;\nORYX.CONFIG.SELECTED_AREA_PADDING =\t\t4;\nORYX.CONFIG.CANVAS_BACKGROUND_COLOR =\t\"none\";\nORYX.CONFIG.GRID_DISTANCE =\t\t\t\t30;\nORYX.CONFIG.GRID_ENABLED =\t\t\t\ttrue;\nORYX.CONFIG.ZOOM_OFFSET =\t\t\t\t0.1;\nORYX.CONFIG.DEFAULT_SHAPE_MARGIN =\t\t60;\nORYX.CONFIG.SCALERS_SIZE =\t\t\t\t7;\nORYX.CONFIG.MINIMUM_SIZE =\t\t\t\t20;\nORYX.CONFIG.MAXIMUM_SIZE =\t\t\t\t10000;\nORYX.CONFIG.OFFSET_MAGNET =\t\t\t\t15;\nORYX.CONFIG.OFFSET_EDGE_LABEL_TOP =\t\t8;\nORYX.CONFIG.OFFSET_EDGE_LABEL_BOTTOM =\t8;\nORYX.CONFIG.OFFSET_EDGE_BOUNDS =\t\t5;\nORYX.CONFIG.COPY_MOVE_OFFSET =\t\t\t30;\n\t\nORYX.CONFIG.BORDER_OFFSET =\t\t\t\t14;\n\nORYX.CONFIG.MAX_NUM_SHAPES_NO_GROUP\t=\t20; // Updated so the form editor shows all elements at once\n\nORYX.CONFIG.SHAPEMENU_CREATE_OFFSET_CORNER = 30;\nORYX.CONFIG.SHAPEMENU_CREATE_OFFSET = 45;\n\n\t/* Shape-Menu Align */\nORYX.CONFIG.SHAPEMENU_RIGHT =\t\t\t\"Oryx_Right\";\nORYX.CONFIG.SHAPEMENU_BOTTOM =\t\t\t\"Oryx_Bottom\";\nORYX.CONFIG.SHAPEMENU_LEFT =\t\t\t\"Oryx_Left\";\nORYX.CONFIG.SHAPEMENU_TOP =\t\t\t\t\"Oryx_Top\";\n\n\n\t/* Morph-Menu Item */\nORYX.CONFIG.MORPHITEM_DISABLED =\t\t\"Oryx_MorphItem_disabled\";\n\n\t/* Property type names */\nORYX.CONFIG.TYPE_STRING =\t\t\t\t\"string\";\nORYX.CONFIG.TYPE_BOOLEAN =\t\t\t\t\"boolean\";\nORYX.CONFIG.TYPE_INTEGER =\t\t\t\t\"integer\";\nORYX.CONFIG.TYPE_FLOAT =\t\t\t\t\"float\";\nORYX.CONFIG.TYPE_COLOR =\t\t\t\t\"color\";\nORYX.CONFIG.TYPE_DATE =\t\t\t\t\t\"date\";\nORYX.CONFIG.TYPE_CHOICE =\t\t\t\t\"choice\";\nORYX.CONFIG.TYPE_URL =\t\t\t\t\t\"url\";\nORYX.CONFIG.TYPE_DIAGRAM_LINK =\t\t\t\"diagramlink\";\nORYX.CONFIG.TYPE_COMPLEX =\t\t\t\t\"complex\";\nORYX.CONFIG.TYPE_MULTIPLECOMPLEX =\t\t\"multiplecomplex\";\nORYX.CONFIG.TYPE_TEXT =\t\t\t\t\t\"text\";\nORYX.CONFIG.TYPE_KISBPM_MULTIINSTANCE =\t\"kisbpm-multiinstance\";\nORYX.CONFIG.TYPE_MODEL_LINK =\t\t\t\"modellink\";\nORYX.CONFIG.TYPE_FORM_FLOW_LINK =\t\t\"formflowlink\";\nORYX.CONFIG.TYPE_FORM_LINK =\t\t\t\"formlink\";\nORYX.CONFIG.TYPE_SUB_PROCESS_LINK =\t\t\"subprocesslink\";\nORYX.CONFIG.TYPE_SERVICE_LINK =\t\t\t\"servicelink\";\nORYX.CONFIG.TYPE_CONDITIONS =\t\t\t\"conditions\";\nORYX.CONFIG.TYPE_VARIABLES = \t\t\t\"variables\";\nORYX.CONFIG.TYPE_LISTENER =\t\t\t\t\"listener\";\nORYX.CONFIG.TYPE_EPC_FREQ = \t\t\t\"epcfrequency\";\nORYX.CONFIG.TYPE_GLOSSARY_LINK =\t\t\"glossarylink\";\nORYX.CONFIG.TYPE_EXPRESSION = \t\t\t\"expression\";\nORYX.CONFIG.TYPE_DATASOURCE = \t\t\t\"datasource\";\nORYX.CONFIG.TYPE_DATASOURCE_MINIMAL =\t\"datasource-minimal\";\nORYX.CONFIG.TYPE_VALIDATORS =\t\t\t\"validators\";\n\n\t\n\t/* Vertical line distance of multiline labels */\nORYX.CONFIG.LABEL_LINE_DISTANCE =\t\t2;\nORYX.CONFIG.LABEL_DEFAULT_LINE_HEIGHT =\t12;\n\n\t/* Open Morph Menu with Hover */\nORYX.CONFIG.ENABLE_MORPHMENU_BY_HOVER = false;\n\n\n\t/* Editor constants come here */\nORYX.CONFIG.EDITOR_ALIGN_BOTTOM =\t\t0x01;\nORYX.CONFIG.EDITOR_ALIGN_MIDDLE =\t\t0x02;\nORYX.CONFIG.EDITOR_ALIGN_TOP =\t\t\t0x04;\nORYX.CONFIG.EDITOR_ALIGN_LEFT =\t\t\t0x08;\nORYX.CONFIG.EDITOR_ALIGN_CENTER =\t\t0x10;\nORYX.CONFIG.EDITOR_ALIGN_RIGHT =\t\t0x20;\nORYX.CONFIG.EDITOR_ALIGN_SIZE =\t\t\t0x30;\n\n\t/* Event types */\nORYX.CONFIG.EVENT_MOUSEDOWN =\t\t\t\"mousedown\";\nORYX.CONFIG.EVENT_MOUSEUP =\t\t\t\t\"mouseup\";\nORYX.CONFIG.EVENT_MOUSEOVER =\t\t\t\"mouseover\";\nORYX.CONFIG.EVENT_MOUSEOUT =\t\t\t\"mouseout\";\nORYX.CONFIG.EVENT_MOUSEMOVE =\t\t\t\"mousemove\";\nORYX.CONFIG.EVENT_DBLCLICK =\t\t\t\"dblclick\";\nORYX.CONFIG.EVENT_KEYDOWN =\t\t\t\t\"keydown\";\nORYX.CONFIG.EVENT_KEYUP =\t\t\t\t\"keyup\";\n\nORYX.CONFIG.EVENT_LOADED =\t\t\t\t\"editorloaded\";\nORYX.CONFIG.EVENT_SAVED =\t\t\t\t\"editorSaved\";\n\t\nORYX.CONFIG.EVENT_EXECUTE_COMMANDS =\t\t\"executeCommands\";\nORYX.CONFIG.EVENT_STENCIL_SET_LOADED =\t\t\"stencilSetLoaded\";\nORYX.CONFIG.EVENT_SELECTION_CHANGED =\t\t\"selectionchanged\";\nORYX.CONFIG.EVENT_SHAPEADDED =\t\t\t\t\"shapeadded\";\nORYX.CONFIG.EVENT_SHAPEREMOVED =\t\t\t\"shaperemoved\";\nORYX.CONFIG.EVENT_PROPERTY_CHANGED =\t\t\"propertyChanged\";\nORYX.CONFIG.EVENT_DRAGDROP_START =\t\t\t\"dragdrop.start\";\nORYX.CONFIG.EVENT_SHAPE_MENU_CLOSE =\t\t\"shape.menu.close\";\nORYX.CONFIG.EVENT_DRAGDROP_END =\t\t\t\"dragdrop.end\";\nORYX.CONFIG.EVENT_RESIZE_START =\t\t\t\"resize.start\";\nORYX.CONFIG.EVENT_RESIZE_END =\t\t\t\t\"resize.end\";\nORYX.CONFIG.EVENT_DRAGDOCKER_DOCKED =\t\t\"dragDocker.docked\";\nORYX.CONFIG.EVENT_HIGHLIGHT_SHOW =\t\t\t\"highlight.showHighlight\";\nORYX.CONFIG.EVENT_HIGHLIGHT_HIDE =\t\t\t\"highlight.hideHighlight\";\nORYX.CONFIG.EVENT_LOADING_ENABLE =\t\t\t\"loading.enable\";\nORYX.CONFIG.EVENT_LOADING_DISABLE =\t\t\t\"loading.disable\";\nORYX.CONFIG.EVENT_LOADING_STATUS =\t\t\t\"loading.status\";\nORYX.CONFIG.EVENT_OVERLAY_SHOW =\t\t\t\"overlay.show\";\nORYX.CONFIG.EVENT_OVERLAY_HIDE =\t\t\t\"overlay.hide\";\nORYX.CONFIG.EVENT_ARRANGEMENT_TOP =\t\t\t\"arrangement.setToTop\";\nORYX.CONFIG.EVENT_ARRANGEMENT_BACK =\t\t\"arrangement.setToBack\";\nORYX.CONFIG.EVENT_ARRANGEMENT_FORWARD =\t\t\"arrangement.setForward\";\nORYX.CONFIG.EVENT_ARRANGEMENT_BACKWARD =\t\"arrangement.setBackward\";\nORYX.CONFIG.EVENT_PROPWINDOW_PROP_CHANGED =\t\"propertyWindow.propertyChanged\";\nORYX.CONFIG.EVENT_LAYOUT_ROWS =\t\t\t\t\"layout.rows\";\nORYX.CONFIG.EVENT_LAYOUT_BPEL =\t\t\t\t\"layout.BPEL\";\nORYX.CONFIG.EVENT_LAYOUT_BPEL_VERTICAL =    \"layout.BPEL.vertical\";\nORYX.CONFIG.EVENT_LAYOUT_BPEL_HORIZONTAL =  \"layout.BPEL.horizontal\";\nORYX.CONFIG.EVENT_LAYOUT_BPEL_SINGLECHILD = \"layout.BPEL.singlechild\";\nORYX.CONFIG.EVENT_LAYOUT_BPEL_AUTORESIZE =\t\"layout.BPEL.autoresize\";\nORYX.CONFIG.EVENT_AUTOLAYOUT_LAYOUT =\t\t\"autolayout.layout\";\nORYX.CONFIG.EVENT_UNDO_EXECUTE =\t\t\t\"undo.execute\";\nORYX.CONFIG.EVENT_UNDO_ROLLBACK =\t\t\t\"undo.rollback\";\nORYX.CONFIG.EVENT_BUTTON_UPDATE =           \"toolbar.button.update\";\nORYX.CONFIG.EVENT_LAYOUT = \t\t\t\t\t\"layout.dolayout\";\nORYX.CONFIG.EVENT_GLOSSARY_LINK_EDIT = \t\t\"glossary.link.edit\";\nORYX.CONFIG.EVENT_GLOSSARY_SHOW =\t\t\t\"glossary.show.info\";\nORYX.CONFIG.EVENT_GLOSSARY_NEW =\t\t\t\"glossary.show.new\";\nORYX.CONFIG.EVENT_DOCKERDRAG = \t\t\t\t\"dragTheDocker\";\nORYX.CONFIG.EVENT_CANVAS_SCROLL = \t\t\t\"canvas.scroll\";\n\t\nORYX.CONFIG.EVENT_SHOW_PROPERTYWINDOW =\t\t\"propertywindow.show\";\nORYX.CONFIG.EVENT_ABOUT_TO_SAVE = \"file.aboutToSave\";\n\t\n\t/* Selection Shapes Highlights */\nORYX.CONFIG.SELECTION_HIGHLIGHT_SIZE =\t\t\t\t5;\nORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR =\t\t\t\t\"#4444FF\";\nORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR2 =\t\t\t\"#9999FF\";\n\t\nORYX.CONFIG.SELECTION_HIGHLIGHT_STYLE_CORNER = \t\t\"corner\";\nORYX.CONFIG.SELECTION_HIGHLIGHT_STYLE_RECTANGLE = \t\"rectangle\";\n\t\nORYX.CONFIG.SELECTION_VALID_COLOR =\t\t\t\t\t\"#00FF00\";\nORYX.CONFIG.SELECTION_INVALID_COLOR =\t\t\t\t\"#FF0000\";\n\n\nORYX.CONFIG.DOCKER_DOCKED_COLOR =\t\t\"#00FF00\";\nORYX.CONFIG.DOCKER_UNDOCKED_COLOR =\t\t\"#FF0000\";\nORYX.CONFIG.DOCKER_SNAP_OFFSET =\t\t10;\n\t\t\n\t/* Copy & Paste */\nORYX.CONFIG.EDIT_OFFSET_PASTE =\t\t\t10;\n\n\t/* Key-Codes */\nORYX.CONFIG.KEY_CODE_X = \t\t\t\t88;\nORYX.CONFIG.KEY_CODE_C = \t\t\t\t67;\nORYX.CONFIG.KEY_CODE_V = \t\t\t\t86;\nORYX.CONFIG.KEY_CODE_DELETE = \t\t\t46;\nORYX.CONFIG.KEY_CODE_META =\t\t\t\t224;\nORYX.CONFIG.KEY_CODE_BACKSPACE =\t\t8;\nORYX.CONFIG.KEY_CODE_LEFT =\t\t\t\t37;\nORYX.CONFIG.KEY_CODE_RIGHT =\t\t\t39;\nORYX.CONFIG.KEY_CODE_UP =\t\t\t\t38;\nORYX.CONFIG.KEY_CODE_DOWN =\t\t\t\t40;\n\n\t// TODO Determine where the lowercase constants are still used and remove them from here.\nORYX.CONFIG.KEY_Code_enter =\t\t\t12;\nORYX.CONFIG.KEY_Code_left =\t\t\t\t37;\nORYX.CONFIG.KEY_Code_right =\t\t\t39;\nORYX.CONFIG.KEY_Code_top =\t\t\t\t38;\nORYX.CONFIG.KEY_Code_bottom =\t\t\t40;\n\n/* Supported Meta Keys */\n\t\nORYX.CONFIG.META_KEY_META_CTRL = \t\t\"metactrl\";\nORYX.CONFIG.META_KEY_ALT = \t\t\t\t\"alt\";\nORYX.CONFIG.META_KEY_SHIFT = \t\t\t\"shift\";\n\n/* Key Actions */\n\nORYX.CONFIG.KEY_ACTION_DOWN = \t\t\t\"down\";\nORYX.CONFIG.KEY_ACTION_UP = \t\t\t\"up\";\n\n\n/* Form Rowlayouting */\nORYX.CONFIG.FORM_ROW_WIDTH =            350;\nORYX.CONFIG.FORM_GROUP_MARGIN =            5;\nORYX.CONFIG.FORM_GROUP_EMPTY_HEIGHT =   100;\n\n/* Form element types */\nORYX.CONFIG.FORM_ELEMENT_ID_PREFIX = \t\t\t\t'http://b3mn.org/stencilset/xforms';\nORYX.CONFIG.FORM_ELEMENT_TYPE_ROOT = \t\t\t\t'http://b3mn.org/stencilset/xforms#XForm';\nORYX.CONFIG.FORM_ELEMENT_TYPE_GROUP = \t\t\t\t'http://b3mn.org/stencilset/xforms#Group';\nORYX.CONFIG.FORM_ELEMENT_TYPE_REPEATING_GROUP =\t\t'http://b3mn.org/stencilset/xforms#RepeatingGroup';\nORYX.CONFIG.FORM_ELEMENT_TYPE_LABEL_FIELD = \t\t'http://b3mn.org/stencilset/xforms#LabelField';\n\t\n\t/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nfunction printf() {\n\t\n\tvar result = arguments[0];\n\tfor (var i=1; i<arguments.length; i++)\n\t\tresult = result.replace('%' + (i-1), arguments[i]);\n\treturn result;\n}\n\n// oryx constants.\nvar ORYX_LOGLEVEL_TRACE = 5;\nvar ORYX_LOGLEVEL_DEBUG = 4;\nvar ORYX_LOGLEVEL_INFO = 3;\nvar ORYX_LOGLEVEL_WARN = 2;\nvar ORYX_LOGLEVEL_ERROR = 1;\nvar ORYX_LOGLEVEL_FATAL = 0;\nvar ORYX_LOGLEVEL = 3;\nvar ORYX_CONFIGURATION_DELAY = 100;\nvar ORYX_CONFIGURATION_WAIT_ATTEMPTS = 10;\n\nif(!ORYX) var ORYX = {};\n\nORYX = Object.extend(ORYX, {\n\n\t//set the path in the config.js file!!!!\n\tPATH: ORYX.CONFIG.ROOT_PATH,\n\t//CONFIGURATION: \"config.js\",\n\n\tURLS: [],\n\n\talreadyLoaded: [],\n\n\tconfigrationRetries: 0,\n\n\tVersion: '0.1.1',\n\n\tavailablePlugins: [],\n\n\t/**\n\t * The ORYX.Log logger.\n\t */\n\tLog: {\n\t\n\t\t__appenders: [\n\t\t\t{ \n\t\t\t\tappend: function(message) {\n\t\t\t\t\tif(typeof(console) !== \"undefined\" && console.log !== undefined) {\n\t\t\t\t\t\tconsole.log(message); \n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t],\n\t\n\t\ttrace: function() {\tif(ORYX_LOGLEVEL >= ORYX_LOGLEVEL_TRACE)\n\t\t\tORYX.Log.__log('TRACE', arguments); },\n\t\tdebug: function() { if(ORYX_LOGLEVEL >= ORYX_LOGLEVEL_DEBUG)\n\t\t\tORYX.Log.__log('DEBUG', arguments); },\n\t\tinfo: function() { if(ORYX_LOGLEVEL >= ORYX_LOGLEVEL_INFO)\n\t\t\tORYX.Log.__log('INFO', arguments); },\n\t\twarn: function() { if(ORYX_LOGLEVEL >= ORYX_LOGLEVEL_WARN)\n\t\t\tORYX.Log.__log('WARN', arguments); },\n\t\terror: function() { if(ORYX_LOGLEVEL >= ORYX_LOGLEVEL_ERROR)\n\t\t\tORYX.Log.__log('ERROR', arguments); },\n\t\tfatal: function() { if(ORYX_LOGLEVEL >= ORYX_LOGLEVEL_FATAL)\n\t\t\tORYX.Log.__log('FATAL', arguments); },\n\t\t\n\t\t__log: function(prefix, messageParts) {\n\t\t\t\n\t\t\tmessageParts[0] = (new Date()).getTime() + \" \"\n\t\t\t\t+ prefix + \" \" + messageParts[0];\n\t\t\tvar message = printf.apply(null, messageParts);\n\t\t\t\n\t\t\tORYX.Log.__appenders.each(function(appender) {\n\t\t\t\tappender.append(message);\n\t\t\t});\n\t\t},\n\t\t\n\t\taddAppender: function(appender) {\n\t\t\tORYX.Log.__appenders.push(appender);\n\t\t}\n\t},\n\n\t/**\n\t * First bootstrapping layer. The Oryx loading procedure begins. In this\n\t * step, all preliminaries that are not in the responsibility of Oryx to be\n\t * met have to be checked here, such as the existance of the prototpe\n\t * library in the current execution environment. After that, the second\n\t * bootstrapping layer is being invoked. Failing to ensure that any\n\t * preliminary condition is not met has to fail with an error.\n\t */\n\tload: function() {\n\t\t\n\t\tORYX.Log.debug(\"Oryx begins loading procedure.\");\n\t\t\n\t\t// check for prototype\n\t\tif( (typeof Prototype=='undefined') ||\n\t\t\t(typeof Element == 'undefined') ||\n\t\t\t(typeof Element.Methods=='undefined') ||\n\t\t\tparseFloat(Prototype.Version.split(\".\")[0] + \".\" +\n\t\t\t\tPrototype.Version.split(\".\")[1]) < 1.5)\n\n\t\t\tthrow(\"Application requires the Prototype JavaScript framework >= 1.5.3\");\n\t\t\n\t\tORYX.Log.debug(\"Prototype > 1.5 found.\");\n\n\t\t// continue loading.\n\t\tORYX._load();\n\t},\n\n\t/**\n\t * Second bootstrapping layer. The oryx configuration is checked. When not\n\t * yet loaded, config.js is being requested from the server. A repeated\n\t * error in retrieving the configuration will result in an error to be\n\t * thrown after a certain time of retries. Once the configuration is there,\n\t * all urls that are registered with oryx loading are being requested from\n\t * the server. Once everything is loaded, the third layer is being invoked.\n\t */\n\t_load: function() {\n\t/*\n\t\t// if configuration not there already,\n\t\tif(!(ORYX.CONFIG)) {\n\t\t\t\n\t\t\t// if this is the first attempt...\n\t\t\tif(ORYX.configrationRetries == 0) {\n\t\t\t\t\n\t\t\t\t// get the path and filename.\n\t\t\t\tvar configuration = ORYX.PATH + ORYX.CONFIGURATION;\n\t\n\t\t\t\tORYX.Log.debug(\"Configuration not found, loading from '%0'.\",\n\t\t\t\t\tconfiguration);\n\t\t\t\t\n\t\t\t\t// require configuration file.\n\t\t\t\tKickstart.require(configuration);\n\t\t\t\t\n\t\t\t// else if attempts exceeded ...\n\t\t\t} else if(ORYX.configrationRetries >= ORYX_CONFIGURATION_WAIT_ATTEMPTS) {\n\t\t\t\t\n\t\t\t\tthrow \"Tried to get configuration\" +\n\t\t\t\t\tORYX_CONFIGURATION_WAIT_ATTEMPTS +\n\t\t\t\t\t\" times from '\" + configuration + \"'. Giving up.\"\n\t\t\t\t\t\n\t\t\t} else if(ORYX.configrationRetries > 0){\n\t\t\t\t\n\t\t\t\t// point out how many attempts are left...\n\t\t\t\tORYX.Log.debug(\"Waiting once more (%0 attempts left)\",\n\t\t\t\t\t(ORYX_CONFIGURATION_WAIT_ATTEMPTS -\n\t\t\t\t\t\tORYX.configrationRetries));\n\n\t\t\t}\n\t\t\t\n\t\t\t// any case: continue in a moment with increased retry count.\n\t\t\tORYX.configrationRetries++;\n\t\t\twindow.setTimeout(ORYX._load, ORYX_CONFIGURATION_DELAY);\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tORYX.Log.info(\"Configuration loaded.\");\n\t\t\n\t\t// load necessary scripts.\n\t\tORYX.URLS.each(function(url) {\n\t\t\tORYX.Log.debug(\"Requireing '%0'\", url);\n\t\t\tKickstart.require(ORYX.PATH + url) });\n\t*/\n\t\t// configurate logging and load plugins.\n\t\tORYX.loadPlugins();\n\t},\n\n\t/**\n\t * Third bootstrapping layer. This is where first the plugin coniguration\n\t * file is loaded into oryx, analyzed, and where all plugins are being\n\t * requested by the server. Afterwards, all editor instances will be\n\t * initialized.\n\t */\n\tloadPlugins: function() {\n\t\t\n\t\t// load plugins if enabled.\n\t\tif(ORYX.CONFIG.PLUGINS_ENABLED)\n\t\t\tORYX._loadPlugins()\n\t\telse\n\t\t\tORYX.Log.warn(\"Ignoring plugins, loading Core only.\");\n\n\t\t// init the editor instances.\n\t\tinit();\n\t},\n\t\n\t_loadPlugins: function() {\n\n\t\t// load plugin configuration file.\n\t\tvar source = ORYX.CONFIG.PLUGINS_CONFIG;\n\n\t\tORYX.Log.debug(\"Loading plugin configuration from '%0'.\", source);\n\t\n\t\tnew Ajax.Request(source, {\n\t\t\tasynchronous: false,\n\t\t\tmethod: 'get',\n\t\t\tonSuccess: function(result) {\n\n\t\t\t\t/*\n\t\t\t\t * This is the method that is being called when the plugin\n\t\t\t\t * configuration was successfully loaded from the server. The\n\t\t\t\t * file has to be processed and the contents need to be\n\t\t\t\t * considered for further plugin requireation.\n\t\t\t\t */\n\t\t\t\t\n\t\t\t\tORYX.Log.info(\"Plugin configuration file loaded.\");\n\t\t\n\t\t\t\t// get plugins.xml content\n\t\t\t\tvar resultXml = result.responseXML;\n\t\t\t\t\n\t\t\t\t// TODO: Describe how properties are handled.\n\t\t\t\t// Get the globale Properties\n\t\t\t\tvar globalProperties = [];\n\t\t\t\tvar preferences = $A(resultXml.getElementsByTagName(\"properties\"));\n\t\t\t\tpreferences.each( function(p) {\n\n\t\t\t\t\tvar props = $A(p.childNodes);\n\t\t\t\t\tprops.each( function(prop) {\n\t\t\t\t\t\tvar property = new Hash(); \n\t\t\t\t\t\t\n\t\t\t\t\t\t// get all attributes from the node and set to global properties\n\t\t\t\t\t\tvar attributes = $A(prop.attributes)\n\t\t\t\t\t\tattributes.each(function(attr){property[attr.nodeName] = attr.nodeValue});\t\t\t\t\n\t\t\t\t\t\tif(attributes.length > 0) { globalProperties.push(property) };\t\t\t\t\n\t\t\t\t\t});\n\t\t\t\t});\n\n\t\t\t\t\n\t\t\t\t// TODO Why are we using XML if we don't respect structure anyway?\n\t\t\t\t// for each plugin element in the configuration..\n\t\t\t\tvar plugin = resultXml.getElementsByTagName(\"plugin\");\n\t\t\t\t$A(plugin).each( function(node) {\n\t\t\t\t\t\n\t\t\t\t\t// get all element's attributes.\n\t\t\t\t\t// TODO: What about: var pluginData = $H(node.attributes) !?\n\t\t\t\t\tvar pluginData = new Hash();\n\t\t\t\t\t$A(node.attributes).each( function(attr){\n\t\t\t\t\t\tpluginData[attr.nodeName] = attr.nodeValue});\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t// ensure there's a name attribute.\n\t\t\t\t\tif(!pluginData['name']) {\n\t\t\t\t\t\tORYX.Log.error(\"A plugin is not providing a name. Ingnoring this plugin.\");\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t// ensure there's a source attribute.\n\t\t\t\t\tif(!pluginData['source']) {\n\t\t\t\t\t\tORYX.Log.error(\"Plugin with name '%0' doesn't provide a source attribute.\", pluginData['name']);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t// Get all private Properties\n\t\t\t\t\tvar propertyNodes = node.getElementsByTagName(\"property\");\n\t\t\t\t\tvar properties = [];\n\t\t\t\t\t$A(propertyNodes).each(function(prop) {\n\t\t\t\t\t\tvar property = new Hash(); \n\t\t\t\t\t\t\n\t\t\t\t\t\t// Get all Attributes from the Node\t\t\t\n\t\t\t\t\t\tvar attributes = $A(prop.attributes)\n\t\t\t\t\t\tattributes.each(function(attr){property[attr.nodeName] = attr.nodeValue});\t\t\t\t\n\t\t\t\t\t\tif(attributes.length > 0) { properties.push(property) };\t\n\t\t\t\t\t\n\t\t\t\t\t});\n\t\t\t\t\t\n\t\t\t\t\t// Set all Global-Properties to the Properties\n\t\t\t\t\tproperties = properties.concat(globalProperties);\n\t\t\t\t\t\n\t\t\t\t\t// Set Properties to Plugin-Data\n\t\t\t\t\tpluginData['properties'] = properties;\n\t\t\t\t\t\n\t\t\t\t\t// Get the RequieredNodes\n\t\t\t\t\tvar requireNodes = node.getElementsByTagName(\"requires\");\n\t\t\t\t\tvar requires;\n\t\t\t\t\t$A(requireNodes).each(function(req) {\t\t\t\n\t\t\t\t\t\tvar namespace = $A(req.attributes).find(function(attr){ return attr.name == \"namespace\"})\n\t\t\t\t\t\tif( namespace && namespace.nodeValue ){\n\t\t\t\t\t\t\tif( !requires ){\n\t\t\t\t\t\t\t\trequires = {namespaces:[]}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\t\trequires.namespaces.push(namespace.nodeValue)\n\t\t\t\t\t\t} \n\t\t\t\t\t});\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t// Set Requires to the Plugin-Data, if there is one\n\t\t\t\t\tif( requires ){\n\t\t\t\t\t\tpluginData['requires'] = requires;\n\t\t\t\t\t}\n\n\n\t\t\t\t\t// Get the RequieredNodes\n\t\t\t\t\tvar notUsesInNodes = node.getElementsByTagName(\"notUsesIn\");\n\t\t\t\t\tvar notUsesIn;\n\t\t\t\t\t$A(notUsesInNodes).each(function(not) {\t\t\t\n\t\t\t\t\t\tvar namespace = $A(not.attributes).find(function(attr){ return attr.name == \"namespace\"})\n\t\t\t\t\t\tif( namespace && namespace.nodeValue ){\n\t\t\t\t\t\t\tif( !notUsesIn ){\n\t\t\t\t\t\t\t\tnotUsesIn = {namespaces:[]}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\t\tnotUsesIn.namespaces.push(namespace.nodeValue)\n\t\t\t\t\t\t} \n\t\t\t\t\t});\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t// Set Requires to the Plugin-Data, if there is one\n\t\t\t\t\tif( notUsesIn ){\n\t\t\t\t\t\tpluginData['notUsesIn'] = notUsesIn;\n\t\t\t\t\t}\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\tvar url = ORYX.PATH + ORYX.CONFIG.PLUGINS_FOLDER + pluginData['source'];\n\t\t\n\t\t\t\t\tORYX.Log.debug(\"Requireing '%0'\", url);\n\t\t\n\t\t\t\t\t// Add the Script-Tag to the Site\n\t\t\t\t\t//Kickstart.require(url);\n\t\t\n\t\t\t\t\tORYX.Log.info(\"Plugin '%0' successfully loaded.\", pluginData['name']);\n\t\t\n\t\t\t\t\t// Add the Plugin-Data to all available Plugins\n\t\t\t\t\tORYX.availablePlugins.push(pluginData);\n\t\t\n\t\t\t\t});\n\t\t\n\t\t\t},\n\t\t\tonFailure:this._loadPluginsOnFails\n\t\t});\n\n\t},\n\n\t_loadPluginsOnFails: function(result) {\n\n\t\tORYX.Log.error(\"Plugin configuration file not available.\");\n\t}\n});\n\n\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespaces\n */\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\nif(!ORYX.Core.SVG) {ORYX.Core.SVG = {};}\n\n\n/**\n * EditPathHandler\n * \n * Edit SVG paths' coordinates according to specified from-to movement and\n * horizontal and vertical scaling factors. \n * The resulting path's d attribute is stored in instance variable d.\n * \n * @constructor\n */\nORYX.Core.SVG.EditPathHandler = Clazz.extend({\n\t\n\tconstruct: function() {\n\t\targuments.callee.$.construct.apply(this, arguments);\n\t\t\n\t\tthis.x = 0;\n\t\tthis.y = 0;\n\t\tthis.oldX = 0;\n\t\tthis.oldY = 0;\n\t\tthis.deltaWidth = 1;\n\t\tthis.deltaHeight = 1;\n\t\t\n\t\tthis.d = \"\";\n\t},\n\t\n\t/**\n\t * init\n\t * \n\t * @param {float} x Target point's x-coordinate\n\t * @param {float} y Target point's y-coordinate\n\t * @param {float} oldX Reference point's x-coordinate\n\t * @param {float} oldY Reference point's y-coordinate\n\t * @param {float} deltaWidth Horizontal scaling factor\n\t * @param {float} deltaHeight Vertical scaling factor\n\t */\n\tinit: function(x, y, oldX, oldY, deltaWidth, deltaHeight) {\n\t\tthis.x = x;\n\t\tthis.y = y;\n\t\tthis.oldX = oldX;\n\t\tthis.oldY = oldY;\n\t\tthis.deltaWidth = deltaWidth;\n\t\tthis.deltaHeight = deltaHeight;\n\t\t\n\t\tthis.d = \"\";\n\t},\n\n\t/**\n\t * editPointsAbs\n\t * \n\t * @param {Array} points Array of absolutePoints\n\t */\n\teditPointsAbs: function(points) {\n\t\tif(points instanceof Array) {\n\t\t\tvar newPoints = [];\n\t\t\tvar x, y;\n\t\t\tfor(var i = 0; i < points.length; i++) {\n\t\t\t\tx = (parseFloat(points[i]) - this.oldX)*this.deltaWidth + this.x;\n\t\t\t\ti++;\n\t\t\t\ty = (parseFloat(points[i]) - this.oldY)*this.deltaHeight + this.y;\n\t\t\t\tnewPoints.push(x);\n\t\t\t\tnewPoints.push(y);\n\t\t\t}\n\t\t\t\n\t\t\treturn newPoints;\n\t\t} else {\n\t\t\t//TODO error\n\t\t}\n\t},\n\t\n\t/**\n\t * editPointsRel\n\t * \n\t * @param {Array} points Array of absolutePoints\n\t */\n\teditPointsRel: function(points) {\n\t\tif(points instanceof Array) {\n\t\t\tvar newPoints = [];\n\t\t\tvar x, y;\n\t\t\tfor(var i = 0; i < points.length; i++) {\n\t\t\t\tx = parseFloat(points[i])*this.deltaWidth;\n\t\t\t\ti++;\n\t\t\t\ty = parseFloat(points[i])*this.deltaHeight;\n\t\t\t\tnewPoints.push(x);\n\t\t\t\tnewPoints.push(y);\n\t\t\t}\n\t\t\t\n\t\t\treturn newPoints;\n\t\t} else {\n\t\t\t//TODO error\n\t\t}\n\t},\n\n\t/**\n\t * arcAbs - A\n\t * \n\t * @param {Number} rx\n\t * @param {Number} ry\n\t * @param {Number} xAxisRotation\n\t * @param {Boolean} largeArcFlag\n\t * @param {Boolean} sweepFlag\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tarcAbs: function(rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) {\n\t    var pointsAbs = this.editPointsAbs([x, y]);\n\t\tvar pointsRel = this.editPointsRel([rx, ry]);\n\t\t\n\t\tthis.d = this.d.concat(\" A\" + pointsRel[0] + \" \" + pointsRel[1] + \n\t\t\t\t\t\t\t\t\" \" + xAxisRotation + \" \" + largeArcFlag + \n\t\t\t\t\t\t\t\t\" \" + sweepFlag + \" \" + pointsAbs[0] + \" \" +\n\t\t\t\t\t\t\t\tpointsAbs[1] + \" \");\t\t\t\t\t\n\t},\n\n\t/**\n\t * arcRel - a\n\t * \n\t * @param {Number} rx\n\t * @param {Number} ry\n\t * @param {Number} xAxisRotation\n\t * @param {Boolean} largeArcFlag\n\t * @param {Boolean} sweepFlag\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tarcRel: function(rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) {\n\t\tvar pointsRel = this.editPointsRel([rx, ry, x, y]);\n\t\t\n\t\tthis.d = this.d.concat(\" a\" + pointsRel[0] + \" \" + pointsRel[1] + \n\t\t\t\t\t\t\t\t\" \" + xAxisRotation + \" \" + largeArcFlag + \n\t\t\t\t\t\t\t\t\" \" + sweepFlag + \" \" + pointsRel[2] + \" \" +\n\t\t\t\t\t\t\t\tpointsRel[3] + \" \");\t\n\t},\n\n\t/**\n\t * curvetoCubicAbs - C\n\t * \n\t * @param {Number} x1\n\t * @param {Number} y1\n\t * @param {Number} x2\n\t * @param {Number} y2\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoCubicAbs: function(x1, y1, x2, y2, x, y) {\n\t    var pointsAbs = this.editPointsAbs([x1, y1, x2, y2, x, y]);\n\t\t\n\t\tthis.d = this.d.concat(\" C\" + pointsAbs[0] + \" \" + pointsAbs[1] + \n\t\t\t\t\t\t\t\t\" \" + pointsAbs[2] + \" \" + pointsAbs[3] + \n\t\t\t\t\t\t\t\t\" \" + pointsAbs[4] + \" \" + pointsAbs[5] + \" \");\t\n\t},\n\n\t/**\n\t * curvetoCubicRel - c\n\t * \n\t * @param {Number} x1\n\t * @param {Number} y1\n\t * @param {Number} x2\n\t * @param {Number} y2\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoCubicRel: function(x1, y1, x2, y2, x, y) {\n\t    var pointsRel = this.editPointsRel([x1, y1, x2, y2, x, y]);\n\t\t\n\t\tthis.d = this.d.concat(\" c\" + pointsRel[0] + \" \" + pointsRel[1] + \n\t\t\t\t\t\t\t\t\" \" + pointsRel[2] + \" \" + pointsRel[3] + \n\t\t\t\t\t\t\t\t\" \" + pointsRel[4] + \" \" + pointsRel[5] + \" \");\t\n\t},\n\n\t/**\n\t * linetoHorizontalAbs - H\n\t * \n\t * @param {Number} x\n\t */\n\tlinetoHorizontalAbs: function(x) {\n\t    var pointsAbs = this.editPointsAbs([x, 0]);\n\t\t\n\t\tthis.d = this.d.concat(\" H\" + pointsAbs[0] + \" \");\t\n\t},\n\n\t/**\n\t * linetoHorizontalRel - h\n\t * \n\t * @param {Number} x\n\t */\n\tlinetoHorizontalRel: function(x) {\n\t    var pointsRel = this.editPointsRel([x, 0]);\n\t\t\n\t\tthis.d = this.d.concat(\" h\" + pointsRel[0] + \" \");\t\n\t},\n\n\t/**\n\t * linetoAbs - L\n\t * \n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tlinetoAbs: function(x, y) {\n\t    var pointsAbs = this.editPointsAbs([x, y]);\n\t\t\n\t\tthis.d = this.d.concat(\" L\" + pointsAbs[0] + \" \" + pointsAbs[1] + \" \");\n\t},\n\n\t/**\n\t * linetoRel - l\n\t * \n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tlinetoRel: function(x, y) {\n\t    var pointsRel = this.editPointsRel([x, y]);\n\t\t\n\t\tthis.d = this.d.concat(\" l\" + pointsRel[0] + \" \" + pointsRel[1] + \" \");\n\t},\n\n\t/**\n\t * movetoAbs - M\n\t * \n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tmovetoAbs: function(x, y) {\n\t    var pointsAbs = this.editPointsAbs([x, y]);\n\t\t\n\t\tthis.d = this.d.concat(\" M\" + pointsAbs[0] + \" \" + pointsAbs[1] + \" \");\n\t},\n\n\t/**\n\t * movetoRel - m\n\t * \n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tmovetoRel: function(x, y) {\n\t    var pointsRel;\n\t\tif(this.d === \"\") {\n\t\t\tpointsRel = this.editPointsAbs([x, y]);\n\t\t} else {\n\t\t\tpointsRel = this.editPointsRel([x, y]);\n\t\t}\n\t\t\n\t\tthis.d = this.d.concat(\" m\" + pointsRel[0] + \" \" + pointsRel[1] + \" \");\n\t},\n\n\t/**\n\t * curvetoQuadraticAbs - Q\n\t * \n\t * @param {Number} x1\n\t * @param {Number} y1\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoQuadraticAbs: function(x1, y1, x, y) {\n\t    var pointsAbs = this.editPointsAbs([x1, y1, x, y]);\n\t\t\n\t\tthis.d = this.d.concat(\" Q\" + pointsAbs[0] + \" \" + pointsAbs[1] + \" \" +\n\t\t\t\t\t\t\t\tpointsAbs[2] + \" \" + pointsAbs[3] + \" \");\n\t},\n\n\t/**\n\t * curvetoQuadraticRel - q\n\t * \n\t * @param {Number} x1\n\t * @param {Number} y1\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoQuadraticRel: function(x1, y1, x, y) {\n\t    var pointsRel = this.editPointsRel([x1, y1, x, y]);\n\t\t\n\t\tthis.d = this.d.concat(\" q\" + pointsRel[0] + \" \" + pointsRel[1] + \" \" +\n\t\t\t\t\t\t\t\tpointsRel[2] + \" \" + pointsRel[3] + \" \");\n\t},\n\n\t/**\n\t * curvetoCubicSmoothAbs - S\n\t * \n\t * @param {Number} x2\n\t * @param {Number} y2\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoCubicSmoothAbs: function(x2, y2, x, y) {\n\t    var pointsAbs = this.editPointsAbs([x2, y2, x, y]);\n\t\t\n\t\tthis.d = this.d.concat(\" S\" + pointsAbs[0] + \" \" + pointsAbs[1] + \" \" +\n\t\t\t\t\t\t\t\tpointsAbs[2] + \" \" + pointsAbs[3] + \" \");\n\t},\n\n\t/**\n\t * curvetoCubicSmoothRel - s\n\t * \n\t * @param {Number} x2\n\t * @param {Number} y2\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoCubicSmoothRel: function(x2, y2, x, y) {\n\t    var pointsRel = this.editPointsRel([x2, y2, x, y]);\n\t\t\n\t\tthis.d = this.d.concat(\" s\" + pointsRel[0] + \" \" + pointsRel[1] + \" \" +\n\t\t\t\t\t\t\t\tpointsRel[2] + \" \" + pointsRel[3] + \" \");\n\t},\n\n\t/**\n\t * curvetoQuadraticSmoothAbs - T\n\t * \n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoQuadraticSmoothAbs: function(x, y) {\n\t    var pointsAbs = this.editPointsAbs([x, y]);\n\t\t\n\t\tthis.d = this.d.concat(\" T\" + pointsAbs[0] + \" \" + pointsAbs[1] + \" \");\n\t},\n\n\t/**\n\t * curvetoQuadraticSmoothRel - t\n\t * \n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoQuadraticSmoothRel: function(x, y) {\n\t    var pointsRel = this.editPointsRel([x, y]);\n\t\t\n\t\tthis.d = this.d.concat(\" t\" + pointsRel[0] + \" \" + pointsRel[1] + \" \");\n\t},\n\n\t/**\n\t * linetoVerticalAbs - V\n\t * \n\t * @param {Number} y\n\t */\n\tlinetoVerticalAbs: function(y) {\n\t    var pointsAbs = this.editPointsAbs([0, y]);\n\t\t\n\t\tthis.d = this.d.concat(\" V\" + pointsAbs[1] + \" \");\n\t},\n\n\t/**\n\t * linetoVerticalRel - v\n\t * \n\t * @param {Number} y\n\t */\n\tlinetoVerticalRel: function(y) {\n\t    var pointsRel = this.editPointsRel([0, y]);\n\t\t\n\t\tthis.d = this.d.concat(\" v\" + pointsRel[1] + \" \");\n\t},\n\n\t/**\n\t * closePath - z or Z\n\t */\n\tclosePath: function() {\n\t    this.d = this.d.concat(\" z\");\n\t}\n\n});/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespaces\n */\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\nif(!ORYX.Core.SVG) {ORYX.Core.SVG = {};}\n\n\n/**\n * MinMaxPathHandler\n * \n * Determine the minimum and maximum of a SVG path's absolute coordinates.\n * For relative coordinates the absolute value is computed for consideration.\n * The values are stored in attributes minX, minY, maxX, and maxY.\n * \n * @constructor\n */\nORYX.Core.SVG.MinMaxPathHandler = Clazz.extend({\n\t\n\tconstruct: function() {\n\t\targuments.callee.$.construct.apply(this, arguments);\n\t\t\n\t\tthis.minX = undefined;\n\t\tthis.minY = undefined;\n\t\tthis.maxX = undefined;\n\t\tthis.maxY = undefined;\n\t\t\n\t\tthis._lastAbsX = undefined;\n\t\tthis._lastAbsY = undefined;\n\t},\n\n\t/**\n\t * Store minimal and maximal coordinates of passed points to attributes minX, maxX, minY, maxY\n\t * \n\t * @param {Array} points Array of absolutePoints\n\t */\n\tcalculateMinMax: function(points) {\n\t\tif(points instanceof Array) {\n\t\t\tvar x, y;\n\t\t\tfor(var i = 0; i < points.length; i++) {\n\t\t\t\tx = parseFloat(points[i]);\n\t\t\t\ti++;\n\t\t\t\ty = parseFloat(points[i]);\n\t\t\t\t\n\t\t\t\tthis.minX = (this.minX !== undefined) ? Math.min(this.minX, x) : x;\n\t\t\t\tthis.maxX = (this.maxX !== undefined) ? Math.max(this.maxX, x) : x;\n\t\t\t\tthis.minY = (this.minY !== undefined) ? Math.min(this.minY, y) : y;\n\t\t\t\tthis.maxY = (this.maxY !== undefined) ? Math.max(this.maxY, y) : y;\n\t\t\t\t\t\n\t\t\t\tthis._lastAbsX = x;\n\t\t\t\tthis._lastAbsY = y;\n\t\t\t}\n\t\t} else {\n\t\t\t//TODO error\n\t\t}\n\t},\n\n\t/**\n\t * arcAbs - A\n\t * \n\t * @param {Number} rx\n\t * @param {Number} ry\n\t * @param {Number} xAxisRotation\n\t * @param {Boolean} largeArcFlag\n\t * @param {Boolean} sweepFlag\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tarcAbs: function(rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) {\n\t    this.calculateMinMax([x, y]);\n\t},\n\n\t/**\n\t * arcRel - a\n\t * \n\t * @param {Number} rx\n\t * @param {Number} ry\n\t * @param {Number} xAxisRotation\n\t * @param {Boolean} largeArcFlag\n\t * @param {Boolean} sweepFlag\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tarcRel: function(rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) {\n\t    this.calculateMinMax([this._lastAbsX + x, this._lastAbsY + y]);\n\t},\n\n\t/**\n\t * curvetoCubicAbs - C\n\t * \n\t * @param {Number} x1\n\t * @param {Number} y1\n\t * @param {Number} x2\n\t * @param {Number} y2\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoCubicAbs: function(x1, y1, x2, y2, x, y) {\n\t    this.calculateMinMax([x1, y1, x2, y2, x, y]);\n\t},\n\n\t/**\n\t * curvetoCubicRel - c\n\t * \n\t * @param {Number} x1\n\t * @param {Number} y1\n\t * @param {Number} x2\n\t * @param {Number} y2\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoCubicRel: function(x1, y1, x2, y2, x, y) {\n\t    this.calculateMinMax([this._lastAbsX + x1, this._lastAbsY + y1,\n\t\t\t\t\t\t\t  this._lastAbsX + x2, this._lastAbsY + y2,\n\t\t\t\t\t\t\t  this._lastAbsX + x, this._lastAbsY + y]);\n\t},\n\n\t/**\n\t * linetoHorizontalAbs - H\n\t * \n\t * @param {Number} x\n\t */\n\tlinetoHorizontalAbs: function(x) {\n\t    this.calculateMinMax([x, this._lastAbsY]);\n\t},\n\n\t/**\n\t * linetoHorizontalRel - h\n\t * \n\t * @param {Number} x\n\t */\n\tlinetoHorizontalRel: function(x) {\n\t    this.calculateMinMax([this._lastAbsX + x, this._lastAbsY]);\n\t},\n\n\t/**\n\t * linetoAbs - L\n\t * \n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tlinetoAbs: function(x, y) {\n\t    this.calculateMinMax([x, y]);\n\t},\n\n\t/**\n\t * linetoRel - l\n\t * \n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tlinetoRel: function(x, y) {\n\t    this.calculateMinMax([this._lastAbsX + x, this._lastAbsY + y]);\n\t},\n\n\t/**\n\t * movetoAbs - M\n\t * \n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tmovetoAbs: function(x, y) {\n\t    this.calculateMinMax([x, y]);\n\t},\n\n\t/**\n\t * movetoRel - m\n\t * \n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tmovetoRel: function(x, y) {\n\t    if(this._lastAbsX && this._lastAbsY) {\n\t\t\tthis.calculateMinMax([this._lastAbsX + x, this._lastAbsY + y]);\n\t\t} else {\n\t\t\tthis.calculateMinMax([x, y]);\n\t\t}\n\t},\n\n\t/**\n\t * curvetoQuadraticAbs - Q\n\t * \n\t * @param {Number} x1\n\t * @param {Number} y1\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoQuadraticAbs: function(x1, y1, x, y) {\n\t    this.calculateMinMax([x1, y1, x, y]);\n\t},\n\n\t/**\n\t * curvetoQuadraticRel - q\n\t * \n\t * @param {Number} x1\n\t * @param {Number} y1\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoQuadraticRel: function(x1, y1, x, y) {\n\t    this.calculateMinMax([this._lastAbsX + x1, this._lastAbsY + y1, this._lastAbsX + x, this._lastAbsY + y]);\n\t},\n\n\t/**\n\t * curvetoCubicSmoothAbs - S\n\t * \n\t * @param {Number} x2\n\t * @param {Number} y2\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoCubicSmoothAbs: function(x2, y2, x, y) {\n\t    this.calculateMinMax([x2, y2, x, y]);\n\t},\n\n\t/**\n\t * curvetoCubicSmoothRel - s\n\t * \n\t * @param {Number} x2\n\t * @param {Number} y2\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoCubicSmoothRel: function(x2, y2, x, y) {\n\t    this.calculateMinMax([this._lastAbsX + x2, this._lastAbsY + y2, this._lastAbsX + x, this._lastAbsY + y]);\n\t},\n\n\t/**\n\t * curvetoQuadraticSmoothAbs - T\n\t * \n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoQuadraticSmoothAbs: function(x, y) {\n\t    this.calculateMinMax([x, y]);\n\t},\n\n\t/**\n\t * curvetoQuadraticSmoothRel - t\n\t * \n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoQuadraticSmoothRel: function(x, y) {\n\t    this.calculateMinMax([this._lastAbsX + x, this._lastAbsY + y]);\n\t},\n\n\t/**\n\t * linetoVerticalAbs - V\n\t * \n\t * @param {Number} y\n\t */\n\tlinetoVerticalAbs: function(y) {\n\t    this.calculateMinMax([this._lastAbsX, y]);\n\t},\n\n\t/**\n\t * linetoVerticalRel - v\n\t * \n\t * @param {Number} y\n\t */\n\tlinetoVerticalRel: function(y) {\n\t    this.calculateMinMax([this._lastAbsX, this._lastAbsY + y]);\n\t},\n\n\t/**\n\t * closePath - z or Z\n\t */\n\tclosePath: function() {\n\t    return;// do nothing\n\t}\n\n});/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespaces\n */\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\nif(!ORYX.Core.SVG) {ORYX.Core.SVG = {};}\n\n\n/**\n * PathHandler\n * \n * Determine absolute points of a SVG path. The coordinates are stored \n * sequentially in the attribute points (x-coordinates at even indices,\n * y-coordinates at odd indices).\n * \n * @constructor\n */\nORYX.Core.SVG.PointsPathHandler = Clazz.extend({\n\t\n\tconstruct: function() {\n\t\targuments.callee.$.construct.apply(this, arguments);\n\t\t\n\t\tthis.points = [];\n\t\t\n\t\tthis._lastAbsX = undefined;\n\t\tthis._lastAbsY = undefined;\n\t},\n\n\t/**\n\t * addPoints\n\t * \n\t * @param {Array} points Array of absolutePoints\n\t */\n\taddPoints: function(points) {\n\t\tif(points instanceof Array) {\n\t\t\tvar x, y;\n\t\t\tfor(var i = 0; i < points.length; i++) {\n\t\t\t\tx = parseFloat(points[i]);\n\t\t\t\ti++;\n\t\t\t\ty = parseFloat(points[i]);\n\t\t\t\t\n\t\t\t\tthis.points.push(x);\n\t\t\t\tthis.points.push(y);\n\t\t\t\t//this.points.push({x:x, y:y});\n\t\t\t\t\t\n\t\t\t\tthis._lastAbsX = x;\n\t\t\t\tthis._lastAbsY = y;\n\t\t\t}\n\t\t} else {\n\t\t\t//TODO error\n\t\t}\n\t},\n\n\t/**\n\t * arcAbs - A\n\t * \n\t * @param {Number} rx\n\t * @param {Number} ry\n\t * @param {Number} xAxisRotation\n\t * @param {Boolean} largeArcFlag\n\t * @param {Boolean} sweepFlag\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tarcAbs: function(rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) {\n\t    this.addPoints([x, y]);\n\t},\n\n\t/**\n\t * arcRel - a\n\t * \n\t * @param {Number} rx\n\t * @param {Number} ry\n\t * @param {Number} xAxisRotation\n\t * @param {Boolean} largeArcFlag\n\t * @param {Boolean} sweepFlag\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tarcRel: function(rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) {\n\t    this.addPoints([this._lastAbsX + x, this._lastAbsY + y]);\n\t},\n\n\t/**\n\t * curvetoCubicAbs - C\n\t * \n\t * @param {Number} x1\n\t * @param {Number} y1\n\t * @param {Number} x2\n\t * @param {Number} y2\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoCubicAbs: function(x1, y1, x2, y2, x, y) {\n\t    this.addPoints([x, y]);\n\t},\n\n\t/**\n\t * curvetoCubicRel - c\n\t * \n\t * @param {Number} x1\n\t * @param {Number} y1\n\t * @param {Number} x2\n\t * @param {Number} y2\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoCubicRel: function(x1, y1, x2, y2, x, y) {\n\t    this.addPoints([this._lastAbsX + x, this._lastAbsY + y]);\n\t},\n\n\t/**\n\t * linetoHorizontalAbs - H\n\t * \n\t * @param {Number} x\n\t */\n\tlinetoHorizontalAbs: function(x) {\n\t    this.addPoints([x, this._lastAbsY]);\n\t},\n\n\t/**\n\t * linetoHorizontalRel - h\n\t * \n\t * @param {Number} x\n\t */\n\tlinetoHorizontalRel: function(x) {\n\t    this.addPoints([this._lastAbsX + x, this._lastAbsY]);\n\t},\n\n\t/**\n\t * linetoAbs - L\n\t * \n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tlinetoAbs: function(x, y) {\n\t    this.addPoints([x, y]);\n\t},\n\n\t/**\n\t * linetoRel - l\n\t * \n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tlinetoRel: function(x, y) {\n\t    this.addPoints([this._lastAbsX + x, this._lastAbsY + y]);\n\t},\n\n\t/**\n\t * movetoAbs - M\n\t * \n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tmovetoAbs: function(x, y) {\n\t    this.addPoints([x, y]);\n\t},\n\n\t/**\n\t * movetoRel - m\n\t * \n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tmovetoRel: function(x, y) {\n\t    if(this._lastAbsX && this._lastAbsY) {\n\t\t\tthis.addPoints([this._lastAbsX + x, this._lastAbsY + y]);\n\t\t} else {\n\t\t\tthis.addPoints([x, y]);\n\t\t}\n\t},\n\n\t/**\n\t * curvetoQuadraticAbs - Q\n\t * \n\t * @param {Number} x1\n\t * @param {Number} y1\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoQuadraticAbs: function(x1, y1, x, y) {\n\t    this.addPoints([x, y]);\n\t},\n\n\t/**\n\t * curvetoQuadraticRel - q\n\t * \n\t * @param {Number} x1\n\t * @param {Number} y1\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoQuadraticRel: function(x1, y1, x, y) {\n\t    this.addPoints([this._lastAbsX + x, this._lastAbsY + y]);\n\t},\n\n\t/**\n\t * curvetoCubicSmoothAbs - S\n\t * \n\t * @param {Number} x2\n\t * @param {Number} y2\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoCubicSmoothAbs: function(x2, y2, x, y) {\n\t    this.addPoints([x, y]);\n\t},\n\n\t/**\n\t * curvetoCubicSmoothRel - s\n\t * \n\t * @param {Number} x2\n\t * @param {Number} y2\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoCubicSmoothRel: function(x2, y2, x, y) {\n\t    this.addPoints([this._lastAbsX + x, this._lastAbsY + y]);\n\t},\n\n\t/**\n\t * curvetoQuadraticSmoothAbs - T\n\t * \n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoQuadraticSmoothAbs: function(x, y) {\n\t    this.addPoints([x, y]);\n\t},\n\n\t/**\n\t * curvetoQuadraticSmoothRel - t\n\t * \n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tcurvetoQuadraticSmoothRel: function(x, y) {\n\t    this.addPoints([this._lastAbsX + x, this._lastAbsY + y]);\n\t},\n\n\t/**\n\t * linetoVerticalAbs - V\n\t * \n\t * @param {Number} y\n\t */\n\tlinetoVerticalAbs: function(y) {\n\t    this.addPoints([this._lastAbsX, y]);\n\t},\n\n\t/**\n\t * linetoVerticalRel - v\n\t * \n\t * @param {Number} y\n\t */\n\tlinetoVerticalRel: function(y) {\n\t    this.addPoints([this._lastAbsX, this._lastAbsY + y]);\n\t},\n\n\t/**\n\t * closePath - z or Z\n\t */\n\tclosePath: function() {\n\t    return;// do nothing\n\t}\n\n});/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n *\n * Config variables\n */\nNAMESPACE_ORYX = \"http://www.b3mn.org/oryx\";\nNAMESPACE_SVG = \"http://www.w3.org/2000/svg/\";\n\n/**\n * @classDescription This class wraps the manipulation of a SVG marker.\n * @namespace ORYX.Core.SVG\n * uses Inheritance (Clazz)\n * uses Prototype 1.5.0\n *\n */\n\n/**\n * Init package\n */\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\nif(!ORYX.Core.SVG) {ORYX.Core.SVG = {};}\n\nORYX.Core.SVG.SVGMarker = Clazz.extend({\n\n\t/**\n\t * Constructor\n\t * @param markerElement {SVGMarkerElement}\n\t */\n\tconstruct: function(markerElement) {\n\t\targuments.callee.$.construct.apply(this, arguments);\n\n\t\tthis.id = undefined;\n\t\tthis.element = markerElement;\n\t\tthis.refX = undefined;\n\t\tthis.refY = undefined;\n\t\tthis.markerWidth = undefined;\n\t\tthis.markerHeight = undefined;\n\t\tthis.oldRefX = undefined;\n\t\tthis.oldRefY = undefined;\n\t\tthis.oldMarkerWidth = undefined;\n\t\tthis.oldMarkerHeight = undefined;\n\t\tthis.optional = false;\n\t\tthis.enabled = true;\n\t\tthis.minimumLength = undefined;\n\t\tthis.resize = false;\n\n\t\tthis.svgShapes = [];\n\n\t\tthis._init(); //initialisation of all the properties declared above.\n\t},\n\n\t/**\n\t * Initializes the values that are defined in the constructor.\n\t */\n\t_init: function() {\n\t\t//check if this.element is a SVGMarkerElement\n\t\tif(!( this.element == \"[object SVGMarkerElement]\")) {\n\t\t\tthrow \"SVGMarker: Argument is not an instance of SVGMarkerElement.\";\n\t\t}\n\n\t\tthis.id = this.element.getAttributeNS(null, \"id\");\n\t\t\n\t\t//init svg marker attributes\n\t\tvar refXValue = this.element.getAttributeNS(null, \"refX\");\n\t\tif(refXValue) {\n\t\t\tthis.refX = parseFloat(refXValue);\n\t\t} else {\n\t\t\tthis.refX = 0;\n\t\t}\n\t\tvar refYValue = this.element.getAttributeNS(null, \"refY\");\n\t\tif(refYValue) {\n\t\t\tthis.refY = parseFloat(refYValue);\n\t\t} else {\n\t\t\tthis.refY = 0;\n\t\t}\n\t\tvar markerWidthValue = this.element.getAttributeNS(null, \"markerWidth\");\n\t\tif(markerWidthValue) {\n\t\t\tthis.markerWidth = parseFloat(markerWidthValue);\n\t\t} else {\n\t\t\tthis.markerWidth = 3;\n\t\t}\n\t\tvar markerHeightValue = this.element.getAttributeNS(null, \"markerHeight\");\n\t\tif(markerHeightValue) {\n\t\t\tthis.markerHeight = parseFloat(markerHeightValue);\n\t\t} else {\n\t\t\tthis.markerHeight = 3;\n\t\t}\n\n\t\tthis.oldRefX = this.refX;\n\t\tthis.oldRefY = this.refY;\n\t\tthis.oldMarkerWidth = this.markerWidth;\n\t\tthis.oldMarkerHeight = this.markerHeight;\n\n\t\t//init oryx attributes\n\t\tvar optionalAttr = this.element.getAttributeNS(NAMESPACE_ORYX, \"optional\");\n\t\tif(optionalAttr) {\n\t\t\toptionalAttr = optionalAttr.strip();\n\t\t\tthis.optional = (optionalAttr.toLowerCase() === \"yes\");\n\t\t} else {\n\t\t\tthis.optional = false;\n\t\t}\n\n\t\tvar enabledAttr = this.element.getAttributeNS(NAMESPACE_ORYX, \"enabled\");\n\t\tif(enabledAttr) {\n\t\t\tenabledAttr = enabledAttr.strip();\n\t\t\tthis.enabled = !(enabledAttr.toLowerCase() === \"no\");\n\t\t} else {\n\t\t\tthis.enabled = true;\n\t\t}\n\n\t\tvar minLengthAttr = this.element.getAttributeNS(NAMESPACE_ORYX, \"minimumLength\");\n\t\tif(minLengthAttr) {\n\t\t\tthis.minimumLength = parseFloat(minLengthAttr);\n\t\t}\n\n\t\tvar resizeAttr = this.element.getAttributeNS(NAMESPACE_ORYX, \"resize\");\n\t\tif(resizeAttr) {\n\t\t\tresizeAttr = resizeAttr.strip();\n\t\t\tthis.resize = (resizeAttr.toLowerCase() === \"yes\");\n\t\t} else {\n\t\t\tthis.resize = false;\n\t\t}\n\n\t\t//init SVGShape objects\n\t\t//this.svgShapes = this._getSVGShapes(this.element);\n\t},\n\n\t/**\n\t *\n\t */\n\t_getSVGShapes: function(svgElement) {\n\t\tif(svgElement.hasChildNodes) {\n\t\t\tvar svgShapes = [];\n\t\t\tvar me = this;\n\t\t\t$A(svgElement.childNodes).each(function(svgChild) {\n\t\t\t\ttry {\n\t\t\t\t\tvar svgShape = new ORYX.Core.SVG.SVGShape(svgChild);\n\t\t\t\t\tsvgShapes.push(svgShape);\n\t\t\t\t} catch (e) {\n\t\t\t\t\tsvgShapes = svgShapes.concat(me._getSVGShapes(svgChild));\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn svgShapes;\n\t\t}\n\t},\n\n\t/**\n\t * Writes the changed values into the SVG marker.\n\t */\n\tupdate: function() {\n\t\t//TODO mache marker resizebar!!! aber erst wenn der rest der connectingshape funzt!\n\n//\t\t//update marker attributes\n//\t\tif(this.refX != this.oldRefX) {\n//\t\t\tthis.element.setAttributeNS(null, \"refX\", this.refX);\n//\t\t}\n//\t\tif(this.refY != this.oldRefY) {\n//\t\t\tthis.element.setAttributeNS(null, \"refY\", this.refY);\n//\t\t}\n//\t\tif(this.markerWidth != this.oldMarkerWidth) {\n//\t\t\tthis.element.setAttributeNS(null, \"markerWidth\", this.markerWidth);\n//\t\t}\n//\t\tif(this.markerHeight != this.oldMarkerHeight) {\n//\t\t\tthis.element.setAttributeNS(null, \"markerHeight\", this.markerHeight);\n//\t\t}\n//\n//\t\t//update SVGShape objects\n//\t\tvar widthDelta = this.markerWidth / this.oldMarkerWidth;\n//\t\tvar heightDelta = this.markerHeight / this.oldMarkerHeight;\n//\t\tif(widthDelta != 1 && heightDelta != 1) {\n//\t\t\tthis.svgShapes.each(function(svgShape) {\n//\n//\t\t\t});\n//\t\t}\n\n\t\t//update old values to prepare the next update\n\t\tthis.oldRefX = this.refX;\n\t\tthis.oldRefY = this.refY;\n\t\tthis.oldMarkerWidth = this.markerWidth;\n\t\tthis.oldMarkerHeight = this.markerHeight;\n\t},\n\t\n\ttoString: function() { return (this.element) ? \"SVGMarker \" + this.element.id : \"SVGMarker \" + this.element;}\n });/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n *\n * Config variables\n */\nNAMESPACE_ORYX = \"http://www.b3mn.org/oryx\";\nNAMESPACE_SVG = \"http://www.w3.org/2000/svg/\";\n\n/**\n * @classDescription This class wraps the manipulation of a SVG basic shape or a path.\n * @namespace ORYX.Core.SVG\n * uses Inheritance (Clazz)\n * uses Prototype 1.5.0\n * uses PathParser by Kevin Lindsey (http://kevlindev.com/)\n * uses MinMaxPathHandler\n * uses EditPathHandler\n *\n */\n\n//init package\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\nif(!ORYX.Core.SVG) {ORYX.Core.SVG = {};}\n\nORYX.Core.SVG.SVGShape = Clazz.extend({\n\n\t/**\n\t * Constructor\n\t * @param svgElem {SVGElement} An SVGElement that is a basic shape or a path.\n\t */\n\tconstruct: function(svgElem) {\n\t\targuments.callee.$.construct.apply(this, arguments);\n\n\t\tthis.type;\n\t\tthis.element = svgElem;\n\t\tthis.x = undefined;\n\t\tthis.y = undefined;\n\t\tthis.width = undefined;\n\t\tthis.height = undefined;\n\t\tthis.oldX = undefined;\n\t\tthis.oldY = undefined;\n\t\tthis.oldWidth = undefined;\n\t\tthis.oldHeight = undefined;\n\t\tthis.radiusX = undefined;\n\t\tthis.radiusY = undefined;\n\t\tthis.isHorizontallyResizable = false;\n\t\tthis.isVerticallyResizable = false;\n\t\t//this.anchors = [];\n\t\tthis.anchorLeft = false;\n\t\tthis.anchorRight = false;\n\t\tthis.anchorTop = false;\n\t\tthis.anchorBottom = false;\n\t\t\n\t\t//attributes of path elements of edge objects\n\t\tthis.allowDockers = true;\n\t\tthis.resizeMarkerMid = false;\n\n\t\tthis.editPathParser;\n\t\tthis.editPathHandler;\n\n\t\tthis.init(); //initialisation of all the properties declared above.\n\t},\n\n\t/**\n\t * Initializes the values that are defined in the constructor.\n\t */\n\tinit: function() {\n\n\t\t/**initialize position and size*/\n\t\tif(ORYX.Editor.checkClassType(this.element, SVGRectElement) || ORYX.Editor.checkClassType(this.element, SVGImageElement)) {\n\t\t\tthis.type = \"Rect\";\n\t\t\t\n\t\t\tvar xAttr = this.element.getAttributeNS(null, \"x\");\n\t\t\tif(xAttr) {\n\t\t\t\tthis.oldX = parseFloat(xAttr);\n\t\t\t} else {\n\t\t\t\tthrow \"Missing attribute in element \" + this.element;\n\t\t\t}\n\t\t\tvar yAttr = this.element.getAttributeNS(null, \"y\");\n\t\t\tif(yAttr) {\n\t\t\t\tthis.oldY = parseFloat(yAttr);\n\t\t\t} else {\n\t\t\t\tthrow \"Missing attribute in element \" + this.element;\n\t\t\t}\n\t\t\tvar widthAttr = this.element.getAttributeNS(null, \"width\");\n\t\t\tif(widthAttr) {\n\t\t\t\tthis.oldWidth = parseFloat(widthAttr);\n\t\t\t} else {\n\t\t\t\tthrow \"Missing attribute in element \" + this.element;\n\t\t\t}\n\t\t\tvar heightAttr = this.element.getAttributeNS(null, \"height\");\n\t\t\tif(heightAttr) {\n\t\t\t\tthis.oldHeight = parseFloat(heightAttr);\n\t\t\t} else {\n\t\t\t\tthrow \"Missing attribute in element \" + this.element;\n\t\t\t}\n\n\t\t} else if(ORYX.Editor.checkClassType(this.element, SVGCircleElement)) {\n\t\t\tthis.type = \"Circle\";\n\t\t\t\n\t\t\tvar cx = undefined;\n\t\t\tvar cy = undefined;\n\t\t\t//var r = undefined;\n\n\t\t\tvar cxAttr = this.element.getAttributeNS(null, \"cx\");\n\t\t\tif(cxAttr) {\n\t\t\t\tcx = parseFloat(cxAttr);\n\t\t\t} else {\n\t\t\t\tthrow \"Missing attribute in element \" + this.element;\n\t\t\t}\n\t\t\tvar cyAttr = this.element.getAttributeNS(null, \"cy\");\n\t\t\tif(cyAttr) {\n\t\t\t\tcy = parseFloat(cyAttr);\n\t\t\t} else {\n\t\t\t\tthrow \"Missing attribute in element \" + this.element;\n\t\t\t}\n\t\t\tvar rAttr = this.element.getAttributeNS(null, \"r\");\n\t\t\tif(rAttr) {\n\t\t\t\t//r = parseFloat(rAttr);\n\t\t\t\tthis.radiusX = parseFloat(rAttr);\n\t\t\t} else {\n\t\t\t\tthrow \"Missing attribute in element \" + this.element;\n\t\t\t}\n\t\t\tthis.oldX = cx - this.radiusX;\n\t\t\tthis.oldY = cy - this.radiusX;\n\t\t\tthis.oldWidth = 2*this.radiusX;\n\t\t\tthis.oldHeight = 2*this.radiusX;\n\n\t\t} else if(ORYX.Editor.checkClassType(this.element, SVGEllipseElement)) {\n\t\t\tthis.type = \"Ellipse\";\n\t\t\t\n\t\t\tvar cx = undefined;\n\t\t\tvar cy = undefined;\n\t\t\t//var rx = undefined;\n\t\t\t//var ry = undefined;\n\t\t\tvar cxAttr = this.element.getAttributeNS(null, \"cx\");\n\t\t\tif(cxAttr) {\n\t\t\t\tcx = parseFloat(cxAttr);\n\t\t\t} else {\n\t\t\t\tthrow \"Missing attribute in element \" + this.element;\n\t\t\t}\n\t\t\tvar cyAttr = this.element.getAttributeNS(null, \"cy\");\n\t\t\tif(cyAttr) {\n\t\t\t\tcy = parseFloat(cyAttr);\n\t\t\t} else {\n\t\t\t\tthrow \"Missing attribute in element \" + this.element;\n\t\t\t}\n\t\t\tvar rxAttr = this.element.getAttributeNS(null, \"rx\");\n\t\t\tif(rxAttr) {\n\t\t\t\tthis.radiusX = parseFloat(rxAttr);\n\t\t\t} else {\n\t\t\t\tthrow \"Missing attribute in element \" + this.element;\n\t\t\t}\n\t\t\tvar ryAttr = this.element.getAttributeNS(null, \"ry\");\n\t\t\tif(ryAttr) {\n\t\t\t\tthis.radiusY = parseFloat(ryAttr);\n\t\t\t} else {\n\t\t\t\tthrow \"Missing attribute in element \" + this.element;\n\t\t\t}\n\t\t\tthis.oldX = cx - this.radiusX;\n\t\t\tthis.oldY = cy - this.radiusY;\n\t\t\tthis.oldWidth = 2*this.radiusX;\n\t\t\tthis.oldHeight = 2*this.radiusY;\n\n\t\t} else if(ORYX.Editor.checkClassType(this.element, SVGLineElement)) {\n\t\t\tthis.type = \"Line\";\n\t\t\t\n\t\t\tvar x1 = undefined;\n\t\t\tvar y1 = undefined;\n\t\t\tvar x2 = undefined;\n\t\t\tvar y2 = undefined;\n\t\t\tvar x1Attr = this.element.getAttributeNS(null, \"x1\");\n\t\t\tif(x1Attr) {\n\t\t\t\tx1 = parseFloat(x1Attr);\n\t\t\t} else {\n\t\t\t\tthrow \"Missing attribute in element \" + this.element;\n\t\t\t}\n\t\t\tvar y1Attr = this.element.getAttributeNS(null, \"y1\");\n\t\t\tif(y1Attr) {\n\t\t\t\ty1 = parseFloat(y1Attr);\n\t\t\t} else {\n\t\t\t\tthrow \"Missing attribute in element \" + this.element;\n\t\t\t}\n\t\t\tvar x2Attr = this.element.getAttributeNS(null, \"x2\");\n\t\t\tif(x2Attr) {\n\t\t\t\tx2 = parseFloat(x2Attr);\n\t\t\t} else {\n\t\t\t\tthrow \"Missing attribute in element \" + this.element;\n\t\t\t}\n\t\t\tvar y2Attr = this.element.getAttributeNS(null, \"y2\");\n\t\t\tif(y2Attr) {\n\t\t\t\ty2 = parseFloat(y2Attr);\n\t\t\t} else {\n\t\t\t\tthrow \"Missing attribute in element \" + this.element;\n\t\t\t}\n\t\t\tthis.oldX = Math.min(x1,x2);\n\t\t\tthis.oldY = Math.min(y1,y2);\n\t\t\tthis.oldWidth = Math.abs(x1-x2);\n\t\t\tthis.oldHeight = Math.abs(y1-y2);\n\n\t\t} else if(ORYX.Editor.checkClassType(this.element, SVGPolylineElement) || ORYX.Editor.checkClassType(this.element, SVGPolygonElement)) {\n\t\t\tthis.type = \"Polyline\";\n\t\t\t\n\t\t\tvar pointsArray = [];\n\t\t\tif (this.element.points&&this.element.points.numberOfItems){\n\t\t\t    for(var i=0, size=this.element.points.numberOfItems; i<size; i++){\n\t\t\t        pointsArray.push(this.element.points.getItem(i).x)\n\t\t\t        pointsArray.push(this.element.points.getItem(i).y)\n\t\t\t    }\n\t\t\t} else {\n\t\t\t\tvar points = this.element.getAttributeNS(null, \"points\");\n\t\t\t\tif(points) {\n\t\t\t\t\tpoints = points.replace(/,/g , \" \");\n\t\t\t\t\tpointsArray = points.split(\" \");\n\t\t\t\t\tpointsArray = pointsArray.without(\"\");\n\t\t\t\t} else {\n\t\t\t\t\tthrow \"Missing attribute in element \" + this.element;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\n\t\t\tif(pointsArray && pointsArray.length && pointsArray.length > 1) {\n\t\t\t\tvar minX = parseFloat(pointsArray[0]);\n\t\t\t\tvar minY = parseFloat(pointsArray[1]);\n\t\t\t\tvar maxX = parseFloat(pointsArray[0]);\n\t\t\t\tvar maxY = parseFloat(pointsArray[1]);\n\n\t\t\t\tfor(var i = 0; i < pointsArray.length; i++) {\n\t\t\t\t\tminX = Math.min(minX, parseFloat(pointsArray[i]));\n\t\t\t\t\tmaxX = Math.max(maxX, parseFloat(pointsArray[i]));\n\t\t\t\t\ti++;\n\t\t\t\t\tminY = Math.min(minY, parseFloat(pointsArray[i]));\n\t\t\t\t\tmaxY = Math.max(maxY, parseFloat(pointsArray[i]));\n\t\t\t\t}\n\n\t\t\t\tthis.oldX = minX;\n\t\t\t\tthis.oldY = minY;\n\t\t\t\tthis.oldWidth = maxX-minX;\n\t\t\t\tthis.oldHeight = maxY-minY;\n\t\t\t} else {\n\t\t\t\tthrow \"Missing attribute in element \" + this.element;\n\t\t\t}\n\n\t\t} else if(ORYX.Editor.checkClassType(this.element, SVGPathElement)) {\n\t\t\tthis.type = \"Path\";\n\t\t\t\n\t\t\tthis.editPathParser = new PathParser();\n\t\t\tthis.editPathHandler = new ORYX.Core.SVG.EditPathHandler();\n\t\t\tthis.editPathParser.setHandler(this.editPathHandler);\n\t\t\n\t\t\tvar parser = new PathParser();\n\t\t\tvar handler = new ORYX.Core.SVG.MinMaxPathHandler();\n\t\t\tparser.setHandler(handler);\n\t\t\tparser.parsePath(this.element);\n\n\t\t\tthis.oldX = handler.minX;\n\t\t\tthis.oldY = handler.minY;\n\t\t\tthis.oldWidth = handler.maxX - handler.minX;\n\t\t\tthis.oldHeight = handler.maxY - handler.minY;\n\n\t\t\tdelete parser;\n\t\t\tdelete handler;\n\t\t} else {\n\t\t\tthrow \"Element is not a shape.\";\n\t\t}\n\n\t\t/** initialize attributes of oryx namespace */\n\t\t//resize\n\t\tvar resizeAttr = this.element.getAttributeNS(NAMESPACE_ORYX, \"resize\");\n\t\tif(resizeAttr) {\n\t\t\tresizeAttr = resizeAttr.toLowerCase();\n\t\t\tif(resizeAttr.match(/horizontal/)) {\n\t\t\t\tthis.isHorizontallyResizable = true;\n\t\t\t} else {\n\t\t\t\tthis.isHorizontallyResizable = false;\n\t\t\t}\n\t\t\tif(resizeAttr.match(/vertical/)) {\n\t\t\t\tthis.isVerticallyResizable = true;\n\t\t\t} else {\n\t\t\t\tthis.isVerticallyResizable = false;\n\t\t\t}\n\t\t} else {\n\t\t\tthis.isHorizontallyResizable = false;\n\t\t\tthis.isVerticallyResizable = false;\n\t\t}\n\n\t\t//anchors\n\t\tvar anchorAttr = this.element.getAttributeNS(NAMESPACE_ORYX, \"anchors\");\n\t\tif(anchorAttr) {\n\t\t\tanchorAttr = anchorAttr.replace(\"/,/g\", \" \");\n\t\t\tvar anchors = anchorAttr.split(\" \").without(\"\");\n\t\t\t\n\t\t\tfor(var i = 0; i < anchors.length; i++) {\n\t\t\t\tswitch(anchors[i].toLowerCase()) {\n\t\t\t\t\tcase \"left\":\n\t\t\t\t\t\tthis.anchorLeft = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"right\":\n\t\t\t\t\t\tthis.anchorRight = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"top\":\n\t\t\t\t\t\tthis.anchorTop = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"bottom\":\n\t\t\t\t\t\tthis.anchorBottom = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\t//allowDockers and resizeMarkerMid\n\t\tif(ORYX.Editor.checkClassType(this.element, SVGPathElement)) {\n\t\t\tvar allowDockersAttr = this.element.getAttributeNS(NAMESPACE_ORYX, \"allowDockers\"); \n\t\t\tif(allowDockersAttr) {\n\t\t\t\tif(allowDockersAttr.toLowerCase() === \"no\") {\n\t\t\t\t\tthis.allowDockers = false; \n\t\t\t\t} else {\n\t\t\t\t\tthis.allowDockers = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tvar resizeMarkerMidAttr = this.element.getAttributeNS(NAMESPACE_ORYX, \"resizeMarker-mid\"); \n\t\t\tif(resizeMarkerMidAttr) {\n\t\t\t\tif(resizeMarkerMidAttr.toLowerCase() === \"yes\") {\n\t\t\t\t\tthis.resizeMarkerMid = true; \n\t\t\t\t} else {\n\t\t\t\t\tthis.resizeMarkerMid = false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\t\n\t\t\t\n\t\tthis.x = this.oldX;\n\t\tthis.y = this.oldY;\n\t\tthis.width = this.oldWidth;\n\t\tthis.height = this.oldHeight;\n\t},\n\n\t/**\n\t * Writes the changed values into the SVG element.\n\t */\n\tupdate: function() {\n\t\t\n\t\tif(this.x !== this.oldX || this.y !== this.oldY || this.width !== this.oldWidth || this.height !== this.oldHeight) {\n\t\t\tswitch(this.type) {\n\t\t\t\tcase \"Rect\":\n\t\t\t\t\tif(this.x !== this.oldX) this.element.setAttributeNS(null, \"x\", this.x);\n\t\t\t\t\tif(this.y !== this.oldY) this.element.setAttributeNS(null, \"y\", this.y);\n\t\t\t\t \tif(this.width !== this.oldWidth) this.element.setAttributeNS(null, \"width\", this.width);\n\t\t\t\t\tif(this.height !== this.oldHeight) this.element.setAttributeNS(null, \"height\", this.height);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"Circle\":\n\t\t\t\t\t//calculate the radius\n\t\t\t\t\t//var r;\n//\t\t\t\t\tif(this.width/this.oldWidth <= this.height/this.oldHeight) {\n//\t\t\t\t\t\tthis.radiusX = ((this.width > this.height) ? this.width : this.height)/2.0;\n//\t\t\t\t\t} else {\n\t\t\t\t\t \tthis.radiusX = ((this.width < this.height) ? this.width : this.height)/2.0;\n\t\t\t\t\t//}\n\t\n\t\t\t\t\tthis.element.setAttributeNS(null, \"cx\", this.x + this.width/2.0);\n\t\t\t\t\tthis.element.setAttributeNS(null, \"cy\", this.y + this.height/2.0);\n\t\t\t\t\tthis.element.setAttributeNS(null, \"r\", this.radiusX);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"Ellipse\":\n\t\t\t\t\tthis.radiusX = this.width/2;\n\t\t\t\t\tthis.radiusY = this.height/2;\n\t\n\t\t\t\t\tthis.element.setAttributeNS(null, \"cx\", this.x + this.radiusX);\n\t\t\t\t\tthis.element.setAttributeNS(null, \"cy\", this.y + this.radiusY);\n\t\t\t\t\tthis.element.setAttributeNS(null, \"rx\", this.radiusX);\n\t\t\t\t\tthis.element.setAttributeNS(null, \"ry\", this.radiusY);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"Line\":\n\t\t\t\t\tif(this.x !== this.oldX)\n\t\t\t\t\t\tthis.element.setAttributeNS(null, \"x1\", this.x);\n\t\t\t\t\t\t\n\t\t\t\t\tif(this.y !== this.oldY)\n\t\t\t\t\t\tthis.element.setAttributeNS(null, \"y1\", this.y);\n\t\t\t\t\t\t\n\t\t\t\t\tif(this.x !== this.oldX || this.width !== this.oldWidth)\n\t\t\t\t\t\tthis.element.setAttributeNS(null, \"x2\", this.x + this.width);\n\t\t\t\t\t\n\t\t\t\t\tif(this.y !== this.oldY || this.height !== this.oldHeight)\n\t\t\t\t\t\tthis.element.setAttributeNS(null, \"y2\", this.y + this.height);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"Polyline\":\n\t\t\t\t\tvar points = this.element.getAttributeNS(null, \"points\");\n\t\t\t\t\tif(points) {\n\t\t\t\t\t\tpoints = points.replace(/,/g, \" \").split(\" \").without(\"\");\n\t\n\t\t\t\t\t\tif(points && points.length && points.length > 1) {\n\t\n\t\t\t\t\t\t\t//TODO what if oldWidth == 0?\n\t\t\t\t\t\t\tvar widthDelta = (this.oldWidth === 0) ? 0 : this.width / this.oldWidth;\n\t\t\t\t\t\t    var heightDelta = (this.oldHeight === 0) ? 0 : this.height / this.oldHeight;\n\t\n\t\t\t\t\t\t\tvar updatedPoints = \"\";\n\t\t\t\t\t\t    for(var i = 0; i < points.length; i++) {\n\t\t\t\t\t\t\t\tvar x = (parseFloat(points[i])-this.oldX)*widthDelta + this.x;\n\t\t\t\t\t\t\t\ti++;\n\t\t\t\t\t\t\t\tvar y = (parseFloat(points[i])-this.oldY)*heightDelta + this.y;\n\t\t    \t\t\t\t\tupdatedPoints += x + \" \" + y + \" \";\n\t\t\t\t\t\t    }\n\t\t\t\t\t\t\tthis.element.setAttributeNS(null, \"points\", updatedPoints);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t//TODO error\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t//TODO error\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"Path\":\n\t\t\t\t\t//calculate scaling delta\n\t\t\t\t\t//TODO what if oldWidth == 0?\n\t\t\t\t\tvar widthDelta = (this.oldWidth === 0) ? 0 : this.width / this.oldWidth;\n\t\t\t\t\tvar heightDelta = (this.oldHeight === 0) ? 0 : this.height / this.oldHeight;\n\t\n\t\t\t\t\t//use path parser to edit each point of the path\n\t\t\t\t\tthis.editPathHandler.init(this.x, this.y, this.oldX, this.oldY, widthDelta, heightDelta);\n\t\t\t\t\tthis.editPathParser.parsePath(this.element);\n\t\n\t\t\t\t\t//change d attribute of path\n\t\t\t\t\tthis.element.setAttributeNS(null, \"d\", this.editPathHandler.d);\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tthis.oldX = this.x;\n\t\t\tthis.oldY = this.y;\n\t\t\tthis.oldWidth = this.width;\n\t\t\tthis.oldHeight = this.height;\n\t\t}\n\t\t\n\t\t// Remove cached variables\n\t\tdelete this.visible;\n\t\tdelete this.handler;\n\t},\n\t\n\tisPointIncluded: function(pointX, pointY) {\n\n\t\t// Check if there are the right arguments and if the node is visible\n\t\tif(!pointX || !pointY || !this.isVisible()) {\n\t\t\treturn false;\n\t\t}\n\n\t\tswitch(this.type) {\n\t\t\tcase \"Rect\":\n\t\t\t\treturn (pointX >= this.x && pointX <= this.x + this.width &&\n\t\t\t\t\t\tpointY >= this.y && pointY <= this.y+this.height);\n\t\t\t\tbreak;\n\t\t\tcase \"Circle\":\n\t\t\t\t//calculate the radius\n//\t\t\t\tvar r;\n//\t\t\t\tif(this.width/this.oldWidth <= this.height/this.oldHeight) {\n//\t\t\t\t\tr = ((this.width > this.height) ? this.width : this.height)/2.0;\n//\t\t\t\t} else {\n//\t\t\t\t \tr = ((this.width < this.height) ? this.width : this.height)/2.0;\n//\t\t\t\t}\n\t\t\t\treturn ORYX.Core.Math.isPointInEllipse(pointX, pointY, this.x + this.width/2.0, this.y + this.height/2.0, this.radiusX, this.radiusX);\n\t\t\t\tbreak;\n\t\t\tcase \"Ellipse\":\n\t\t\t\treturn ORYX.Core.Math.isPointInEllipse(pointX, pointY, this.x + this.radiusX, this.y + this.radiusY, this.radiusX, this.radiusY);\t\t\t\n\t\t\t\tbreak;\n\t\t\tcase \"Line\":\n\t\t\t\treturn ORYX.Core.Math.isPointInLine(pointX, pointY, this.x, this.y, this.x + this.width, this.y + this.height);\n\t\t\t\tbreak;\n\t\t\tcase \"Polyline\":\n\t\t\t\tvar points = this.element.getAttributeNS(null, \"points\");\n\t\n\t\t\t\tif(points) {\n\t\t\t\t\tpoints = points.replace(/,/g , \" \").split(\" \").without(\"\");\n\t\n\t\t\t\t\tpoints = points.collect(function(n) {\n\t\t\t\t\t\treturn parseFloat(n);\n\t\t\t\t\t});\n\t\t\t\t\t\n\t\t\t\t\treturn ORYX.Core.Math.isPointInPolygone(pointX, pointY, points);\n\t\t\t\t} else {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"Path\":\n\t\t\t\t\n\t\t\t\t// Cache Path handler\n\t\t\t\tif (!this.handler) {\n\t\t\t\t\tvar parser = new PathParser();\n\t\t\t\t\tthis.handler = new ORYX.Core.SVG.PointsPathHandler();\n\t\t\t\t\tparser.setHandler(this.handler);\n\t\t\t\t\tparser.parsePath(this.element);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\treturn ORYX.Core.Math.isPointInPolygone(pointX, pointY, this.handler.points);\n\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\treturn false;\n\t\t}\n\t},\n\n\t/**\n\t * Returns true if the element is visible\n\t * @param {SVGElement} elem\n\t * @return boolean\n\t */\n\tisVisible: function(elem) {\n\t\t\n\t\tif (this.visible !== undefined){\n\t\t\treturn this.visible;\n\t\t}\n\t\t\t\n\t\tif (!elem) {\n\t\t\telem = this.element;\n\t\t}\n\n\t\tvar hasOwnerSVG = false;\n\t\ttry { \n\t\t\thasOwnerSVG = !!elem.ownerSVGElement;\n\t\t} catch(e){}\n\t\t\n\t\t// Is SVG context\n\t\tif ( hasOwnerSVG ) {\n\t\t\t// IF G-Element\n\t\t\tif (ORYX.Editor.checkClassType(elem, SVGGElement)) {\n\t\t\t\tif (elem.className && elem.className.baseVal == \"me\") {\n\t\t\t\t\tthis.visible = true;\n\t\t\t\t\treturn this.visible;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check if fill or stroke is set\n\t\t\tvar fill = elem.getAttributeNS(null, \"fill\");\n\t\t\tvar stroke = elem.getAttributeNS(null, \"stroke\");\n\t\t\tif (fill && fill == \"none\" && stroke && stroke == \"none\") {\n\t\t\t\tthis.visible = false;\n\t\t\t} else {\n\t\t\t\t// Check if displayed\n\t\t\t\tvar attr = elem.getAttributeNS(null, \"display\");\n\t\t\t\tif(!attr)\n\t\t\t\t\tthis.visible = this.isVisible(elem.parentNode);\n\t\t\t\telse if (attr == \"none\") \n\t\t\t\t\tthis.visible = false;\n\t\t\t\telse\n\t\t\t\t\tthis.visible = true;\n\t\t\t}\n\t\t} else {\n\t\t\tthis.visible = true;\n\t\t}\n\t\t\n\t\treturn this.visible;\n\t},\n\n\ttoString: function() { return (this.element) ? \"SVGShape \" + this.element.id : \"SVGShape \" + this.element;}\n });/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespaces\n */\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\nif(!ORYX.Core.SVG) {ORYX.Core.SVG = {};}\n\n/**\n * @classDescription Class for adding text to a shape.\n * \n */\nORYX.Core.SVG.Label = Clazz.extend({\n\t\n\t_characterSets:[\n\t\t\"%W\",\n\t\t\"@\",\n\t\t\"m\",\n\t\t\"wDGMOQ?????#+=<>~^\",\n\t\t\"ABCHKNRSUVXZ??????????&\",\n\t\t\"bdghnopqux???????????ETY1234567890?????_????${}*????`???????????\",\n\t\t\"aeksvyz?????FLP????????????????\",\n\t\t\"c-\",\n\t\t\"rtJ\\\"/()[]:;!|\\\\\",\n\t\t\"fjI., \",\n\t\t\"'\",\n\t\t\"il\"\n\t\t],\n\t_characterSetValues:[15,14,13,11,10,9,8,7,6,5,4,3],\n\n\t/**\n\t * Constructor\n\t * @param options {Object} :\n\t * \ttextElement\n\t * \n\t */\n\tconstruct: function(options) {\n\t\targuments.callee.$.construct.apply(this, arguments);\n\t\t\n\t\tif(!options.textElement) {\n\t\t\tthrow \"Label: No parameter textElement.\" \n\t\t} else if (!ORYX.Editor.checkClassType( options.textElement, SVGTextElement ) ) {\n\t\t\tthrow \"Label: Parameter textElement is not an SVGTextElement.\"\t\n\t\t}\n\t\t\n\t\tthis.invisibleRenderPoint = -5000;\n\t\t\n\t\tthis.node = options.textElement;\n\t\t\n\t\t\n\t\tthis.node.setAttributeNS(null, 'stroke-width', '0pt');\n\t\tthis.node.setAttributeNS(null, 'letter-spacing', '-0.01px');\n\t\t\n\t\tthis.shapeId = options.shapeId;\n\t\t\n\t\tthis.id;\n\t\t\n\t\tthis.fitToElemId;\n\t\t\n\t\tthis.edgePosition;\n\t\t\n\t\tthis.x;\n\t\tthis.y;\n\t\tthis.oldX;\n\t\tthis.oldY;\n\t\t\n\t\tthis.isVisible = true;\n\t\t\n\t\tthis._text;\n\t\tthis._verticalAlign;\n\t\tthis._horizontalAlign;\n\t\tthis._rotate;\n\t\tthis._rotationPoint;\n\t\t\n\t\t//this.anchors = [];\n\t\tthis.anchorLeft;\n\t\tthis.anchorRight;\n\t\tthis.anchorTop;\n\t\tthis.anchorBottom;\n\t\t\n\t\tthis._isChanged = true;\n\n\t\t//if the text element already has an id, don't change it.\n\t\tvar _id = this.node.getAttributeNS(null, 'id');\n\t\tif(_id) {\n\t\t\tthis.id = _id;\n\t\t}\n\t\t\n\t\t//initialization\t\n\t\t\n\t\t//set referenced element the text is fit to\n\t\tthis.fitToElemId = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'fittoelem');\n\t\tif(this.fitToElemId)\n\t\t\tthis.fitToElemId = this.shapeId + this.fitToElemId;\n\t\t\n\t\t//set alignment\t\n\t\tvar alignValues = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'align');\n\t\tif(alignValues) {\n\t\t\talignValues = alignValues.replace(/,/g, \" \");\n\t\t\talignValues = alignValues.split(\" \");\n\t\t\talignValues = alignValues.without(\"\");\n\t\t\t\n\t\t\talignValues.each((function(alignValue) {\n\t\t\t\tswitch (alignValue) {\n\t\t\t\t\tcase 'top':\n\t\t\t\t\tcase 'middle':\n\t\t\t\t\tcase 'bottom':\n\t\t\t\t\t\tif(!this._verticalAlign){this._originVerticalAlign = this._verticalAlign = alignValue;}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'left':\n\t\t\t\t\tcase 'center':\n\t\t\t\t\tcase 'right':\n\t\t\t\t\t\tif(!this._horizontalAlign){this._originHorizontalAlign = this._horizontalAlign = alignValue;}\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}).bind(this));\n\t\t}\n\t\t\n\t\t//set edge position (only in case the label belongs to an edge)\n\t\tthis.edgePosition = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'edgePosition');\n\t\tif(this.edgePosition) {\n\t\t\tthis.originEdgePosition = this.edgePosition = this.edgePosition.toLowerCase();\n\t\t}\n\t\t\n\t\t\n\t\t//get offset top\n\t\tthis.offsetTop = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'offsetTop') || ORYX.CONFIG.OFFSET_EDGE_LABEL_TOP;\n\t\tif(this.offsetTop) {\n\t\t\tthis.offsetTop = parseInt(this.offsetTop);\n\t\t}\n\t\t\n\t\t//get offset top\n\t\tthis.offsetBottom = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'offsetBottom') || ORYX.CONFIG.OFFSET_EDGE_LABEL_BOTTOM;\n\t\tif(this.offsetBottom) {\n\t\t\tthis.offsetBottom = parseInt(this.offsetBottom);\n\t\t}\n\t\t\n\t\t\t\t\n\t\t//set rotation\n\t\tvar rotateValue = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'rotate');\n\t\tif(rotateValue) {\n\t\t\ttry {\n\t\t\t\tthis._rotate = parseFloat(rotateValue);\n\t\t\t} catch (e) {\n\t\t\t\tthis._rotate = 0;\n\t\t\t}\n\t\t} else {\n\t\t\tthis._rotate = 0;\n\t\t}\n\t\t\n\t\t//anchors\n\t\tvar anchorAttr = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, \"anchors\");\n\t\tif(anchorAttr) {\n\t\t\tanchorAttr = anchorAttr.replace(\"/,/g\", \" \");\n\t\t\tvar anchors = anchorAttr.split(\" \").without(\"\");\n\t\t\t\n\t\t\tfor(var i = 0; i < anchors.length; i++) {\n\t\t\t\tswitch(anchors[i].toLowerCase()) {\n\t\t\t\t\tcase \"left\":\n\t\t\t\t\t\tthis.originAnchorLeft = this.anchorLeft = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"right\":\n\t\t\t\t\t\tthis.originAnchorRight = this.anchorRight = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"top\":\n\t\t\t\t\t\tthis.originAnchorTop = this.anchorTop = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"bottom\":\n\t\t\t\t\t\tthis.originAnchorBottom = this.anchorBottom = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\t//if no alignment defined, set default alignment\n\t\tif(!this._verticalAlign) { this._verticalAlign = 'bottom'; }\n\t\tif(!this._horizontalAlign) { this._horizontalAlign = 'left'; }\n\n\t\tvar xValue = this.node.getAttributeNS(null, 'x');\n\t\tif(xValue) {\n\t\t\tthis.oldX = this.x = parseFloat(xValue);\n\t\t} else {\n\t\t\t//TODO error\n\t\t}\n\t\t\n\t\tvar yValue = this.node.getAttributeNS(null, 'y');\n\t\tif(yValue) {\n\t\t\tthis.oldY = this.y = parseFloat(yValue);\n\t\t} else {\n\t\t\t//TODO error\n\t\t}\n\t\t\n\t\t//set initial text\n\t\tthis.text(this.node.textContent);\n\t},\n\t\n\t/**\n\t * Reset the anchor position to the original value\n\t * which was specified in the stencil set\n\t * \n\t */\n\tresetAnchorPosition: function(){\n\t\tthis.anchorLeft = this.originAnchorLeft || false;\n\t\tthis.anchorRight = this.originAnchorRight || false;\n\t\tthis.anchorTop = this.originAnchorTop || false;\n\t\tthis.anchorBottom = this.originAnchorBottom || false;\n\t},\n\t\n\tisOriginAnchorLeft: function(){ return this.originAnchorLeft || false; },\n\tisOriginAnchorRight: function(){ return this.originAnchorRight || false; },\n\tisOriginAnchorTop: function(){ return this.originAnchorTop || false; },\n\tisOriginAnchorBottom: function(){ return this.originAnchorBottom || false; },\n\t\n\t\n\tisAnchorLeft: function(){ return this.anchorLeft || false; },\n\tisAnchorRight: function(){ return this.anchorRight || false; },\n\tisAnchorTop: function(){ return this.anchorTop || false; },\n\tisAnchorBottom: function(){ return this.anchorBottom || false; },\n\t\n\t/**\n\t * Returns the x coordinate\n\t * @return {number}\n\t */\n\tgetX: function(){\n\t\ttry {\n\t\t\tvar x = this.node.x.baseVal.getItem(0).value;\n\t\t\tswitch(this.horizontalAlign()){\n\t\t\t\tcase \"left\": return x;\n\t\t\t\tcase \"center\": return x - (this.getWidth()/2);\n\t\t\t\tcase \"right\": return x - this.getWidth();\n\t\t\t}\n\t\t\treturn this.node.getBBox().x;\n\t\t} catch(e){\n\t\t\treturn this.x;\n\t\t}\n\t},\n\t\t\n\tsetX: function(x){\n\t\tif (this.position)\n\t\t\tthis.position.x = x;\n\t\telse \n\t\t\tthis.setOriginX(x);\n\t},\n\t\n\t\n\t/**\n\t * Returns the y coordinate\n\t * @return {number}\n\t */\n\tgetY: function(){\n\t\ttry {\n\t\t\treturn this.node.getBBox().y;\n\t\t} catch(e){\n\t\t\treturn this.y;\n\t\t}\n\t},\n\t\n\tsetY: function(y){\n\t\tif (this.position)\n\t\t\tthis.position.y = y;\n\t\telse \n\t\t\tthis.setOriginY(y);\n\t},\n\t\n\tsetOriginX: function(x){\n\t\tthis.x = x;\n\t},\n\t\n\tsetOriginY: function(y){\n\t\tthis.y = y;\n\t},\n\n\t\n\t/**\n\t * Returns the width of the label\n\t * @return {number}\n\t */\n\tgetWidth: function(){\n\t\ttry {\n\t\t\ttry {\n\t\t\t\tvar width, cn = this.node.childNodes;\n\t\t\t\tif (cn.length == 0) {\n\t\t\t\t\twidth = this.node.getBBox().width;\n\t\t\t\t} else {\n\t\t\t\t\tfor (var i = 0, size = cn.length; i < size; ++i) {\n\t\t\t\t\t\tvar w = cn[i].getComputedTextLength();\n\t\t\t\t\t\tif (\"undefined\" == typeof width || width < w) {\n\t\t\t\t\t\t\twidth = w;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn width+(width%2==0?0:1);\n\t\t\t} catch (ee) {\n\t\t\t\treturn this.node.getBBox().width;\n\t\t\t}\n\t\t} catch(e){\n\t\t\treturn 0;\n\t\t}\n\t},\n\t\n\tgetOriginUpperLeft: function(){\n\t\tvar x = this.x, y = this.y;\n\t\tswitch (this._horizontalAlign){\n\t\t\tcase 'center' :\n\t\t\t\tx -= this.getWidth()/2;\n\t\t\t\tbreak;\n\t\t\tcase 'right' :\n\t\t\t\tx -= this.getWidth();\n\t\t\t\tbreak;\n\t\t}\n\t\tswitch (this._verticalAlign){\n\t\t\tcase 'middle' :\n\t\t\t\ty -= this.getHeight()/2;\n\t\t\t\tbreak;\n\t\t\tcase 'bottom' :\n\t\t\t\ty -= this.getHeight();\n\t\t\t\tbreak;\n\t\t}\n\t\treturn {x:x, y:y};\n\t},\n\t\n\t/**\n\t * Returns the height of the label\n\t * @return {number}\n\t */\n\tgetHeight: function(){\n\t\ttry {\n\t\t\treturn this.node.getBBox().height;\n\t\t} catch(e){\n\t\t\treturn 0;\n\t\t}\n\t},\n\t\n\t/**\n\t * Returns the relative center position of the label \n\t * to its parent shape.\n\t * @return {Object}\n\t */\n\tgetCenter: function(){\n\t\tvar up = {x: this.getX(), y: this.getY()};\n\t\tup.x += this.getWidth()/2;\n\t\tup.y += this.getHeight()/2;\n\t\treturn up;\n\t},\n\t\n\t/**\n\t * Sets the position of a label relative to the parent.\n\t * @param {Object} position\n\t */\n\tsetPosition: function(position){\n\t\tif (!position || position.x === undefined || position.y === undefined) {\n\t\t\tdelete this.position;\n\t\t} else {\n\t\t\tthis.position = position;\n\t\t}\n\t\t\n\t\tif (this.position){\n\t\t\tdelete this._referencePoint;\n\t\t\tdelete this.edgePosition;\n\t\t}\n\t\t\n\t\tthis._isChanged = true;\n\t\tthis.update();\n\t},\n\t\n\t/**\n\t * Return the position\n\t */\n\tgetPosition: function(){\n\t\treturn this.position;\n\t},\n\t\n\tsetReferencePoint: function(ref){\n\t\tif (ref) {\n\t\t\tthis._referencePoint = ref;\n\t\t} else {\n\t\t\tdelete this._referencePoint;\n\t\t}\n\t\tif (this._referencePoint){\n\t\t\tdelete this.position;\n\t\t}\n\t},\n\t\n\tgetReferencePoint: function(){\n\t\treturn this._referencePoint || undefined;\n\t},\n\t\n\tchanged: function() {\n\t\tthis._isChanged = true;\n\t},\n\t\n\t/**\n\t * Register a callback which will be called if the label\n\t * was rendered.\n\t * @param {Object} fn\n\t */\n\tregisterOnChange: function(fn){\n\t\tif (!this.changeCallbacks){\n\t\t\tthis.changeCallbacks = [];\n\t\t}\n\t\tif (fn instanceof Function && !this.changeCallbacks.include(fn)){\n\t\t\tthis.changeCallbacks.push(fn);\n\t\t}\n\t},\n\t\n\t/**\n\t * Unregister the callback for changes.\n\t * @param {Object} fn\n\t */\n\tunregisterOnChange: function(fn){\n\t\tif (this.changeCallbacks && fn instanceof Function && this.changeCallbacks.include(fn)){\n\t\t\tthis.changeCallbacks = this.changeCallbacks.without(fn);\n\t\t}\n\t},\n\t\n\t/**\n\t * Returns TRUE if the labe is currently in\n\t * the update mechanism.\n\t * @return {Boolean}\n\t */\n\tisUpdating: function(){\n\t\treturn !!this._isUpdating;\t\n\t},\n\t\n\t\n\tgetOriginEdgePosition: function(){\n\t\treturn this.originEdgePosition;\t\n\t},\n\t\n\t/**\n\t * Returns the edgeposition.\n\t * \n\t * @return {String} \"starttop\", \"startmiddle\", \"startbottom\", \n\t * \"midtop\", \"midbottom\", \"endtop\", \"endbottom\" or null\n\t */\n\tgetEdgePosition: function(){\n\t\treturn this.edgePosition || null;\t\n\t},\n\t\n\t/**\n\t * Set the edge position, must be one of the valid\n\t * edge positions (see getEdgePosition).\n\t * Removes the reference point and the absolute position as well.\n\t * \n\t * @param {Object} position\n\t */\n\tsetEdgePosition: function(position){\n\t\tif ([\"starttop\", \"startmiddle\", \"startbottom\", \n\t\t\t\"midtop\", \"midbottom\", \"endtop\", \"endbottom\"].include(position)){\n\t\t\tthis.edgePosition = position;\n\t\t\tdelete this.position;\n\t\t\tdelete this._referencePoint;\n\t\t} else {\n\t\t\tdelete this.edgePosition;\n\t\t}\n\t},\n\t\n\t/**\n\t * Update the SVG text element.\n\t */\n\tupdate: function(force) {\n\t\t\n\t\tvar x = this.x, y = this.y;\n\t\tif (this.position){\n\t\t\tx = this.position.x;\n\t\t\ty = this.position.y;\n\t\t}\n\t\tx = Math.floor(x); y = Math.floor(y);\n\t\t\n\t\tif(this._isChanged || x !== this.oldX || y !== this.oldY || force === true) {\n\t\t\tif (this.isVisible) {\n\t\t\t\tthis._isChanged = false;\n\t\t\t\tthis._isUpdating = true;\n\t\t\t\t\n\t\t\t\tthis.node.setAttributeNS(null, 'x', x);\n\t\t\t\tthis.node.setAttributeNS(null, 'y', y);\n\t\t\t\tthis.node.removeAttributeNS(null, \"fill-opacity\");\n\t\t\t\t\n\t\t\t\t//this.node.setAttributeNS(null, 'font-size', this._fontSize);\n\t\t\t\t//this.node.setAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'align', this._horizontalAlign + \" \" + this._verticalAlign);\n\t\t\t\t\n\t\t\t\tthis.oldX = x;\n\t\t\t\tthis.oldY = y;\n\t\t\t\t\n\t\t\t\t//set rotation\n\t\t\t\tif (!this.position && !this.getReferencePoint()) {\n\t\t\t\t\tif (this._rotate !== undefined) {\n\t\t\t\t\t\tif (this._rotationPoint) \n\t\t\t\t\t\t\tthis.node.setAttributeNS(null, 'transform', 'rotate(' + this._rotate + ' ' + Math.floor(this._rotationPoint.x) + ' ' + Math.floor(this._rotationPoint.y) + ')');\n\t\t\t\t\t\telse \n\t\t\t\t\t\t\tthis.node.setAttributeNS(null, 'transform', 'rotate(' + this._rotate + ' ' + Math.floor(x) + ' ' + Math.floor(y) + ')');\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tthis.node.removeAttributeNS(null, 'transform');\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tvar textLines = this._text.split(\"\\n\");\n\t\t\t\twhile (textLines.last() == \"\") \n\t\t\t\t\ttextLines.pop();\n\t\t\t\t\n\t\t\t\t\n\t\t\t\tif (this.node.ownerDocument) {\n\t\t\t\t\t// Only reset the tspans if the text \n\t\t\t\t\t// has changed or has to be wrapped\n\t\t\t\t\tif (this.fitToElemId || this._textHasChanged){\n\t\t\t\t\t\tthis.node.textContent = \"\"; // Remove content\n\t\t\t\t\t\ttextLines.each((function(textLine, index){\n\t\t\t\t\t\t\tvar tspan = this.node.ownerDocument.createElementNS(ORYX.CONFIG.NAMESPACE_SVG, 'tspan');\n\t\t\t\t\t\t\ttspan.textContent = textLine.trim();\n\t\t\t\t\t\t\tif (this.fitToElemId) {\n\t\t\t\t\t\t\t\ttspan.setAttributeNS(null, 'x', this.invisibleRenderPoint);\n\t\t\t\t\t\t\t\ttspan.setAttributeNS(null, 'y', this.invisibleRenderPoint);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t * Chrome's getBBox() method fails, if a text node contains an empty tspan element.\n\t\t\t\t\t\t\t * So, we add a whitespace to such a tspan element.\n\t\t\t\t\t\t\t */\n\t\t\t\t\t\t\tif(tspan.textContent === \"\") {\n\t\t\t\t\t\t\t\ttspan.textContent = \" \";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t//append tspan to text node\n\t\t\t\t\t\t\tthis.node.appendChild(tspan);\n\t\t\t\t\t\t}).bind(this));\n\t\t\t\t\t\tdelete this._textHasChanged;\n\t\t\t\t\t\tdelete this.indices;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t//Work around for Mozilla bug 293581\n\t\t\t\t\tif (this.isVisible && this.fitToElemId) {\n\t\t\t\t\t\tthis.node.setAttributeNS(null, 'visibility', 'hidden');\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif (this.fitToElemId) {\n\t\t\t\t\t\twindow.setTimeout(this._checkFittingToReferencedElem.bind(this), 0);\n\t\t\t\t\t\t//this._checkFittingToReferencedElem();\n\t\t\t\t\t} else {\n\t\t\t\t\t\twindow.setTimeout(this._positionText.bind(this), 0);\n\t\t\t\t\t\t//this._positionText();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.node.textContent = \"\";\n\t\t\t\t//this.node.setAttributeNS(null, \"fill-opacity\", \"0.2\");\n\t\t\t}\n\t\t}\n\t},\n\t\n\t_checkFittingToReferencedElem: function() {\n\t\ttry {\n\t\t\tvar tspans = $A(this.node.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'tspan'));\n\t\t\t\n\t\t\t//only do this in firefox 3. all other browsers do not support word wrapping!!!!!\n\t\t\t//if (/Firefox[\\/\\s](\\d+\\.\\d+)/.test(navigator.userAgent) && new Number(RegExp.$1)>=3) {\n\t\t\t\tvar newtspans = [];\n\t\t\t\t\n\t\t\t\tvar refNode = this.node.ownerDocument.getElementById(this.fitToElemId);\n\t\t\t\t\n\t\t\t\tif (refNode) {\n\t\t\t\t\tvar refbb = refNode.getBBox();\n\t\t\t\t\t\n\t\t\t\t\tvar fontSize = this.getFontSize();\n\t\t\t\t\t\n\t\t\t\t\tfor (var j = 0; j < tspans.length; j++) {\n\t\t\t\t\t\tvar tspan = tspans[j];\n\t\t\t\t\t\t\n\t\t\t\t\t\tvar textLength = this._getRenderedTextLength(tspan, undefined, undefined, fontSize);\n\t\t\t\t\t\t\n\t\t\t\t\t\tvar refBoxLength = (this._rotate != 0 \n\t\t\t\t\t\t\t\t&& this._rotate % 180 != 0 \n\t\t\t\t\t\t\t\t&& this._rotate % 90 == 0 ? \n\t\t\t\t\t\t\t\t\t\trefbb.height : refbb.width);\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (textLength > refBoxLength) {\n\t\t\t\t\t\t\n\t\t\t\t\t\t\tvar startIndex = 0;\n\t\t\t\t\t\t\tvar lastSeperatorIndex = 0;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tvar numOfChars = this.getTrimmedTextLength(tspan.textContent);\n\t\t\t\t\t\t\tfor (var i = 0; i < numOfChars; i++) {\n\t\t\t\t\t\t\t\tvar sslength = this._getRenderedTextLength(tspan, startIndex, i-startIndex, fontSize);\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tif (sslength > refBoxLength - 2) {\n\t\t\t\t\t\t\t\t\tvar newtspan = this.node.ownerDocument.createElementNS(ORYX.CONFIG.NAMESPACE_SVG, 'tspan');\n\t\t\t\t\t\t\t\t\tif (lastSeperatorIndex <= startIndex) {\n\t\t\t\t\t\t\t\t\t\tlastSeperatorIndex = (i == 0) ? i : i-1;\n\t\t\t\t\t\t\t\t\t\tnewtspan.textContent = tspan.textContent.slice(startIndex, lastSeperatorIndex).trim();\n\t\t\t\t\t\t\t\t\t\t//lastSeperatorIndex = i;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\t\tnewtspan.textContent = tspan.textContent.slice(startIndex, ++lastSeperatorIndex).trim();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tnewtspan.setAttributeNS(null, 'x', this.invisibleRenderPoint);\n\t\t\t\t\t\t\t\t\tnewtspan.setAttributeNS(null, 'y', this.invisibleRenderPoint);\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t//insert tspan to text node\n\t\t\t\t\t\t\t\t\t//this.node.insertBefore(newtspan, tspan);\n\t\t\t\t\t\t\t\t\tnewtspans.push(newtspan);\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tstartIndex = lastSeperatorIndex;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\tvar curChar = tspan.textContent.charAt(i);\n\t\t\t\t\t\t\t\t\tif (curChar == ' ' ||\n\t\t\t\t\t\t\t\t\tcurChar == '-' ||\n\t\t\t\t\t\t\t\t\tcurChar == \".\" ||\n\t\t\t\t\t\t\t\t\tcurChar == \",\" ||\n\t\t\t\t\t\t\t\t\tcurChar == \";\" ||\n\t\t\t\t\t\t\t\t\tcurChar == \":\") {\n\t\t\t\t\t\t\t\t\t\tlastSeperatorIndex = i;\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\t\n\t\t\t\t\t\t\ttspan.textContent = tspan.textContent.slice(startIndex).trim();\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tnewtspans.push(tspan);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\twhile (this.node.hasChildNodes()) \n\t\t\t\t\t\tthis.node.removeChild(this.node.childNodes[0]);\n\t\t\t\t\t\n\t\t\t\t\twhile (newtspans.length > 0) {\n\t\t\t\t\t\tthis.node.appendChild(newtspans.shift());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t//}\n\t\t} catch (e) {\n\t\t\tORYX.Log.fatal(\"Error \" + e);\n\t\t}\n\t\twindow.setTimeout(this._positionText.bind(this), 0);\n\t\t//this._positionText();\n\t},\n\t\n\t/**\n\t * This is a work around method for Mozilla bug 293581.\n\t * Before the method getComputedTextLength works, the text has to be rendered.\n\t */\n\t_positionText: function() {\n\t\ttry {\n\t\t\t\n\t\t\tvar tspans = this.node.childNodes;\n\t\t\t\n\t\t\tvar fontSize = this.getFontSize(this.node); \n\t\t\t\n\t\t\tvar invalidTSpans = [];\n\t\t\t\n\t\t\tvar x = this.x, y = this.y;\n\t\t\tif (this.position){\n\t\t\t\tx = this.position.x;\n\t\t\t\ty = this.position.y;\n\t\t\t}\n\t\t\tx = Math.floor(x); y = Math.floor(y);\n\t\t\t\n\t\t\tvar i = 0, indic = []; // Cache indices if the _positionText is called again, before update is called \n\t\t\tvar is =(this.indices || $R(0,tspans.length-1).toArray());\n\t\t\tvar length = is.length;\n\t\t\tis.each((function(index){\n\t\t\t\tif (\"undefined\" == typeof index){\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tvar tspan = tspans[i++];\n\t\t\t\t\n\t\t\t\tif(tspan.textContent.trim() === \"\") {\n\t\t\t\t\tinvalidTSpans.push(tspan);\n\t\t\t\t} else {\n\t\t\t\t\t//set vertical position\n\t\t\t\t\tvar dy = 0;\n\t\t\t\t\tswitch (this._verticalAlign) {\n\t\t\t\t\t\tcase 'bottom':\n\t\t\t\t\t\t\tdy = -(length - index - 1) * (fontSize);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'middle':\n\t\t\t\t\t\t\tdy = -(length / 2.0 - index - 1) * (fontSize);\n\t\t\t\t\t\t\tdy -= ORYX.CONFIG.LABEL_LINE_DISTANCE / 2;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'top':\n\t\t\t\t\t\t\tdy = index * (fontSize);\n\t\t\t\t\t\t\tdy += fontSize;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\ttspan.setAttributeNS(null, 'dy', Math.floor(dy));\n\t\t\t\t\t\n\t\t\t\t\ttspan.setAttributeNS(null, 'x', x);\n\t\t\t\t\ttspan.setAttributeNS(null, 'y', y);\n\t\t\t\t\tindic.push(index);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t}).bind(this));\n\t\t\t\n\t\t\tindic.length = tspans.length;\n\t\t\tthis.indices = this.indices || indic;\n\t\t\t\n\t\t\tinvalidTSpans.each(function(tspan) {\n\t\t\t\tthis.node.removeChild(tspan)\n\t\t\t}.bind(this));\n\t\t\t\n\t\t\t//set horizontal alignment\n\t\t\tswitch (this._horizontalAlign) {\n\t\t\t\tcase 'left':\n\t\t\t\t\tthis.node.setAttributeNS(null, 'text-anchor', 'start');\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'center':\n\t\t\t\t\tthis.node.setAttributeNS(null, 'text-anchor', 'middle');\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'right':\n\t\t\t\t\tthis.node.setAttributeNS(null, 'text-anchor', 'end');\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\t\t} catch(e) {\n\t\t\t//console.log(e);\n\t\t\tthis._isChanged = true;\n\t\t}\n\t\t\n\t\t\n\t\tif(this.isVisible) {\n\t\t\tthis.node.removeAttributeNS(null, 'visibility');\n\t\t}\t\t\n\t\t\n\t\t\n\t\t// Finished\n\t\tdelete this._isUpdating;\n\t\t\n\t\t// Raise change event\n\t\t(this.changeCallbacks||[]).each(function(fn){\n\t\t\tfn.apply(fn);\n\t\t})\n\t\t\t\t\n\t},\n\t\n\t/**\n\t * Returns the text length of the text content of an SVG tspan element.\n\t * For all browsers but Firefox 3 the values are estimated.\n\t * @param {TSpanSVGElement} tspan\n\t * @param {int} startIndex Optional, for sub strings\n\t * @param {int} endIndex Optional, for sub strings\n\t */\n\t_getRenderedTextLength: function(tspan, startIndex, endIndex, fontSize) {\n\t\t//if (/Firefox[\\/\\s](\\d+\\.\\d+)/.test(navigator.userAgent) && new Number(RegExp.$1) >= 3) {\n\t\t\tif(startIndex === undefined) {\n//test string: abcdefghijklmnopqrstuvwxyz????????????????,.-#+ 1234567890?????ABCDEFGHIJKLMNOPQRSTUVWXYZ;:_'*???????????????!\"????$%&/()=?[]{}|<>'~????`\\^?????????@?????????????????\n//\t\t\t\tfor(var i = 0; i < tspan.textContent.length; i++) {\n//\t\t\t\t\tconsole.log(tspan.textContent.charAt(i), tspan.getSubStringLength(i,1), this._estimateCharacterWidth(tspan.textContent.charAt(i))*(fontSize/14.0));\n//\t\t\t\t}\n\t\t\t\treturn tspan.getComputedTextLength();\n\t\t\t} else {\n\t\t\t\treturn tspan.getSubStringLength(startIndex, endIndex);\n\t\t\t}\n\t\t/*} else {\n\t\t\tif(startIndex === undefined) {\n\t\t\t\treturn this._estimateTextWidth(tspan.textContent, fontSize);\n\t\t\t} else {\n\t\t\t\treturn this._estimateTextWidth(tspan.textContent.substr(startIndex, endIndex).trim(), fontSize);\n\t\t\t}\n\t\t}*/\n\t},\n\t\n\t/**\n\t * Estimates the text width for a string.\n\t * Used for word wrapping in all browser but FF3.\n\t * @param {Object} text\n\t */\n\t_estimateTextWidth: function(text, fontSize) {\n\t\tvar sum = 0.0;\n\t\tfor(var i = 0; i < text.length; i++) {\n\t\t\tsum += this._estimateCharacterWidth(text.charAt(i));\n\t\t}\n\t\t\n\t\treturn sum*(fontSize/14.0);\n\t},\n\t\n\t/**\n\t * Estimates the width of a single character for font size 14.\n\t * Used for word wrapping in all browser but FF3.\n\t * @param {Object} character\n\t */\n\t_estimateCharacterWidth: function(character) {\n\t\tfor(var i = 0; i < this._characterSets.length; i++) {\n \t\t\tif(this._characterSets[i].indexOf(character) >= 0) {\n\t\t\t\treturn this._characterSetValues[i];\n\t\t\t}\n \t\t}\t\n\t\treturn 9;\n \t},\n\t\n\tgetReferencedElementWidth: function() {\n\t\tvar refNode = this.node.ownerDocument.getElementById(this.fitToElemId);\n\t\t\n\t\tif(refNode) {\n\t\t\tvar refbb = refNode.getBBox();\n\t\t\t\t\n\t\t\tif(refbb) {\n\t\t\t\treturn (this._rotate != 0 \n\t\t\t\t\t\t&& this._rotate % 180 != 0 \n\t\t\t\t\t\t&& this._rotate % 90 == 0 ? \n\t\t\t\t\t\t\t\trefbb.height : refbb.width);\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn undefined;\n\t},\n\t\n\t/**\n\t * If no parameter is provided, this method returns the current text.\n\t * @param text {String} Optional. Replaces the old text with this one.\n\t */\n\ttext: function() {\n\t\tswitch (arguments.length) {\n\t\t\tcase 0:\n\t\t\t\treturn this._text\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase 1:\n\t\t\t\tvar oldText = this._text;\n\t\t\t\tif(arguments[0]) {\n\t\t\t\t\t// Filter out multiple spaces to fix issue in chrome for line-wrapping\n\t\t\t\t\tthis._text = arguments[0].toString();\n\t\t\t\t\tif(this._text != null && this._text != undefined) {\n\t\t\t\t\t\tthis._text = this._text.replace(/ {2,}/g,' ');\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tthis._text = \"\";\n\t\t\t\t}\n\t\t\t\tif(oldText !== this._text) {\n\t\t\t\t\tthis._isChanged = true;\n\t\t\t\t\tthis._textHasChanged = true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t\t\n\t\t\tdefault: \n\t\t\t\t//TODO error\n\t\t\t\tbreak;\n\t\t}\n\t},\n\t\n\tgetOriginVerticalAlign: function(){\n\t\treturn this._originVerticalAlign;\n\t},\n\t\n\tverticalAlign: function() {\n\t\tswitch(arguments.length) {\n\t\t\tcase 0:\n\t\t\t\treturn this._verticalAlign;\n\t\t\tcase 1:\n\t\t\t\tif(['top', 'middle', 'bottom'].member(arguments[0])) {\n\t\t\t\t\tvar oldValue = this._verticalAlign;\n\t\t\t\t\tthis._verticalAlign = arguments[0];\n\t\t\t\t\tif(this._verticalAlign !== oldValue) {\n\t\t\t\t\t\tthis._isChanged = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t\t\n\t\t\tdefault:\n\t\t\t\t//TODO error\n\t\t\t\tbreak;\n\t\t}\n\t},\n\t\n\tgetOriginHorizontalAlign: function(){\n\t\treturn this._originHorizontalAlign;\n\t},\n\t\n\thorizontalAlign: function() {\n\t\tswitch(arguments.length) {\n\t\t\tcase 0:\n\t\t\t\treturn this._horizontalAlign;\n\t\t\tcase 1:\n\t\t\t\tif(['left', 'center', 'right'].member(arguments[0])) {\n\t\t\t\t\tvar oldValue = this._horizontalAlign;\n\t\t\t\t\tthis._horizontalAlign = arguments[0];\n\t\t\t\t\tif(this._horizontalAlign !== oldValue) {\n\t\t\t\t\t\tthis._isChanged = true;\n\t\t\t\t\t}\t\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t\t\n\t\t\tdefault:\n\t\t\t\t//TODO error\n\t\t\t\tbreak;\n\t\t}\n\t},\n\t\n\trotate: function() {\n\t\tswitch(arguments.length) {\n\t\t\tcase 0:\n\t\t\t\treturn this._rotate;\n\t\t\tcase 1:\n\t\t\t\tif (this._rotate != arguments[0]) {\n\t\t\t\t\tthis._rotate = arguments[0];\n\t\t\t\t\tthis._rotationPoint = undefined;\n\t\t\t\t\tthis._isChanged = true;\n\t\t\t\t}\n\t\t\tcase 2:\n\t\t\t\tif(this._rotate != arguments[0] ||\n\t\t\t\t   !this._rotationPoint ||\n\t\t\t\t   this._rotationPoint.x != arguments[1].x ||\n\t\t\t\t   this._rotationPoint.y != arguments[1].y) {\n\t\t\t\t\tthis._rotate = arguments[0];\n\t\t\t\t\tthis._rotationPoint = arguments[1];\n\t\t\t\t\tthis._isChanged = true;\n\t\t\t\t}\n\t\t\t\t\n\t\t}\n\t},\n\t\n\thide: function() {\n\t\tif(this.isVisible) {\n\t\t\tthis.isVisible = false;\n\t\t\tthis._isChanged = true;\n\t\t}\n\t},\n\t\n\tshow: function() {\n\t\tif(!this.isVisible) {\n\t\t\tthis.isVisible = true;\n\t\t\tthis._isChanged = true;\n\n\t\t\t// Since text is removed from the tspan when \"hidden\", mark\n\t\t\t// the text as changed to get it redrawn\n\t\t\tthis._textHasChanged = true;\n\t\t}\n\t},\n\t\n\t/**\n\t * iterates parent nodes till it finds a SVG font-size\n\t * attribute.\n\t * @param {SVGElement} node\n\t */\n\tgetInheritedFontSize: function(node) {\n\t\tif(!node || !node.getAttributeNS)\n\t\t\treturn;\n\t\t\t\n\t\tvar attr = node.getAttributeNS(null, \"font-size\");\n\t\tif(attr) {\n\t\t\treturn parseFloat(attr);\n\t\t} else if(!ORYX.Editor.checkClassType(node, SVGSVGElement)) {\n\t\t\treturn this.getInheritedFontSize(node.parentNode);\n\t\t}\n\t},\n\t\n\tgetFontSize: function(node) {\n\t\tvar tspans = this.node.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'tspan');\n\t\t\t\n\t\t//trying to get an inherited font-size attribute\n\t\t//NO CSS CONSIDERED!\n\t\tvar fontSize = this.getInheritedFontSize(this.node); \n\t\t\n\t\tif (!fontSize) {\n\t\t\t//because this only works in firefox 3, all other browser use the default line height\n\t\t\tif (tspans[0] && /Firefox[\\/\\s](\\d+\\.\\d+)/.test(navigator.userAgent) && new Number(RegExp.$1) >= 3) {\n\t\t\t\tfontSize = tspans[0].getExtentOfChar(0).height;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tfontSize = ORYX.CONFIG.LABEL_DEFAULT_LINE_HEIGHT;\n\t\t\t}\n\t\t\t\n\t\t\t//handling of unsupported method in webkit\n\t\t\tif (fontSize <= 0) {\n\t\t\t\tfontSize = ORYX.CONFIG.LABEL_DEFAULT_LINE_HEIGHT;\n\t\t\t}\n\t\t}\n\t\t\n\t\tif(fontSize)\n\t\t\tthis.node.setAttribute(\"oryx:fontSize\", fontSize);\n\t\t\n\t\treturn fontSize;\n\t},\n\t\n\t/**\n\t * Get trimmed text length for use with\n\t * getExtentOfChar and getSubStringLength.\n\t * @param {String} text\n\t */\n\tgetTrimmedTextLength: function(text) {\n\t\ttext = text.strip().gsub('  ', ' ');\n\t\t\n\t\tvar oldLength;\n\t\tdo {\n\t\t\toldLength = text.length;\n\t\t\ttext = text.gsub('  ', ' ');\n\t\t} while (oldLength > text.length);\n\n\t\treturn text.length;\n\t},\n\t\n\t/**\n\t * Returns the offset from\n\t * edge to the label which is \n\t * positioned under the edge\n\t * @return {int}\n\t */\n\tgetOffsetBottom: function(){\n\t\treturn this.offsetBottom;\n\t},\n\t\n\t\t\n\t/**\n\t * Returns the offset from\n\t * edge to the label which is \n\t * positioned over the edge\n\t * @return {int}\n\t */\n\tgetOffsetTop: function(){\n\t\treturn this.offsetTop;\n\t},\n\t\n\t/**\n\t * \n\t * @param {Object} obj\n\t */\n\tdeserialize: function(obj, shape){\n\t\tif (obj && \"undefined\" != typeof obj.x && \"undefined\" != typeof obj.y){\t\t\t\n\t\t\tthis.setPosition({x:obj.x, y:obj.y});\n\t\t\t\n\t\t\tif (\"undefined\" != typeof obj.distance){\n\t\t\t\tvar from = shape.dockers[obj.from];\n\t\t\t\tvar to = shape.dockers[obj.to];\n\t\t\t\tif (from && to){\n\t\t\t\t\tthis.setReferencePoint({\n\t\t\t\t\t\tdirty : true,\n\t\t\t\t\t\tdistance : obj.distance,\n\t\t\t\t\t\tintersection : {x: obj.x, y: obj.y},\n\t\t\t\t\t\torientation : obj.orientation,\n\t\t\t\t\t\tsegment: {\n\t\t\t\t\t\t\tfrom: from,\n\t\t\t\t\t\t\tfromIndex: obj.from,\n\t\t\t\t\t\t\tfromPosition: from.bounds.center(),\n\t\t\t\t\t\t\tto: to,\n\t\t\t\t\t\t\ttoIndex: obj.to,\n\t\t\t\t\t\t\ttoPosition: to.bounds.center()\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\n\t\t\tif (obj.left) this.anchorLeft = true;\n\t\t\tif (obj.right) this.anchorRight = true;\n\t\t\tif (obj.top) this.anchorTop = true;\n\t\t\tif (obj.bottom) this.anchorBottom = true;\n\t\t\tif (obj.valign) this.verticalAlign(obj.valign);\n\t\t\tif (obj.align) this.horizontalAlign(obj.align);\n\t\t\t\n\t\t} else if (obj && \"undefined\" != typeof obj.edge){\n\t\t\tthis.setEdgePosition(obj.edge);\n\t\t}\n\t},\n\n\t/**\n\t * \n\t * @return {Object}\n\t */\n\tserialize: function(){\n\t\t\n\t\t// On edge position\n\t\tif (this.getEdgePosition()){\n\t\t\tif (this.getOriginEdgePosition() !== this.getEdgePosition()){\n\t\t\t\treturn {edge: this.getEdgePosition()};\n\t\t\t} else {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\t\t\n\t\t// On self defined position\n\t\tif (this.position){\n\t\t\tvar pos = {x: this.position.x, y: this.position.y};\n\t\t\tif (this.isAnchorLeft() && this.isAnchorLeft() !== this.isOriginAnchorLeft()){\n\t\t\t\tpos.left = true;\n\t\t\t}\n\t\t\tif (this.isAnchorRight() && this.isAnchorRight() !== this.isOriginAnchorRight()){\n\t\t\t\tpos.right = true;\n\t\t\t}\n\t\t\tif (this.isAnchorTop() && this.isAnchorTop() !== this.isOriginAnchorTop()){\n\t\t\t\tpos.top = true;\n\t\t\t}\n\t\t\tif (this.isAnchorBottom() && this.isAnchorBottom() !== this.isOriginAnchorBottom()){\n\t\t\t\tpos.bottom = true;\n\t\t\t}\n\t\t\t\n\t\t\tif (this.getOriginVerticalAlign() !== this.verticalAlign()){\n\t\t\t\tpos.valign = this.verticalAlign();\n\t\t\t}\n\t\t\tif (this.getOriginHorizontalAlign() !== this.horizontalAlign()){\n\t\t\t\tpos.align = this.horizontalAlign();\n\t\t\t}\n\t\t\t\n\t\t\treturn pos;\n\t\t}\n\t\t\n\t\t// On reference point which is interesting for edges\n\t\tif (this.getReferencePoint()){\n\t\t\tvar ref = this.getReferencePoint();\n\t\t\treturn {\n\t\t\t\tdistance : ref.distance,\n\t\t\t\tx : ref.intersection.x,\n\t\t\t\ty : ref.intersection.y,\n\t\t\t\tfrom : ref.segment.fromIndex,\n\t\t\t\tto : ref.segment.toIndex,\n\t\t\t\torientation : ref.orientation,\n\t\t\t\tvalign : this.verticalAlign(),\n\t\t\t\talign : this.horizontalAlign()\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t},\n\t\n\ttoString: function() { return \"Label \" + this.id }\n });/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespaces\n */\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\nif(!ORYX.Core.Math) {ORYX.Core.Math = {};}\n\t\n/**\n * Calculate the middle point between two given points\n * @param {x:double, y:double} point1\n * @param {x:double, y:double} point2\n * @return the middle point\n */\nORYX.Core.Math.midPoint = function(point1, point2) {\n\treturn \t{\n\t\t\t\tx: (point1.x + point2.x) / 2.0,\n\t\t\t\ty: (point1.y + point2.y) / 2.0\n\t\t\t}\n}\n\t\t\t\n/**\n * Returns a TRUE if the point is over a line (defined by\n * point1 and point 2). In Addition a threshold can be set,\n * which defines the weight of those line.\n * \n * @param {int} pointX - Point X\n * @param {int} pointY - Point Y\n * @param {int} lPoint1X - Line first Point X\n * @param {int} lPoint1Y - Line first Point Y\n * @param {int} lPoint2X - Line second Point X\n * @param {int} lPoint2Y - Line second Point y\n * @param {int} offset {optional} - maximal distance to line\n * @class ORYX.Core.Math.prototype\n */\nORYX.Core.Math.isPointInLine = function (pointX, pointY, lPoint1X, lPoint1Y, lPoint2X, lPoint2Y, offset) {\n\n\toffset = offset ? Math.abs(offset) : 1;\n\t\n\t// Check if the edge is vertical\n\tif(Math.abs(lPoint1X-lPoint2X)<=offset && Math.abs(pointX-lPoint1X)<=offset && pointY-Math.max(lPoint1Y, lPoint2Y)<=offset && Math.min(lPoint1Y, lPoint2Y)-pointY<=offset) {\n\t\treturn true\n\t}\n\n\t// Check if the edge is horizontal\n\tif(Math.abs(lPoint1Y-lPoint2Y)<=offset && Math.abs(pointY-lPoint1Y)<=offset && pointX-Math.max(lPoint1X, lPoint2X)<=offset && Math.min(lPoint1X, lPoint2X)-pointX<=offset) {\n\t\treturn true\n\t}\n\n\tif(pointX > Math.max(lPoint1X, lPoint2X) || pointX < Math.min(lPoint1X, lPoint2X)) {\n\t\treturn false\n\t}\n\n\tif(pointY > Math.max(lPoint1Y, lPoint2Y) || pointY < Math.min(lPoint1Y, lPoint2Y)) {\n\t\treturn false\n\t}\n\t\t\t\n\tvar s = (lPoint1Y - lPoint2Y) / (lPoint1X - lPoint2X);\n\t\n\treturn \tMath.abs(pointY - ((s * pointX) + lPoint1Y - s * lPoint1X)) < offset\n}\n\n/**\n * Get a boolean if the point is in the polygone\n * \n */\nORYX.Core.Math.isPointInEllipse = function (pointX, pointY, cx, cy, rx, ry) {\n\n\tif(cx === undefined || cy === undefined || rx === undefined || ry === undefined) {\n\t\tthrow \"ORYX.Core.Math.isPointInEllipse needs a ellipse with these properties: x, y, radiusX, radiusY\"\n\t} \n\t\n    var tx = (pointX - cx) / rx;\n    var ty = (pointY - cy) / ry;\n\t\n    return tx * tx + ty * ty < 1.0;\n}\n\t\n/**\n * Get a boolean if the point is in the polygone\n * @param {int} pointX\n * @param {int} pointY\n * @param {[int]} Cornerpoints of the Polygone (x,y,x,y,...)\n */\nORYX.Core.Math.isPointInPolygone = function(pointX, pointY, polygone){\n\n\tif (arguments.length < 3) {\n\t\tthrow \"ORYX.Core.Math.isPointInPolygone needs two arguments\"\n\t}\n\t\n\tvar lastIndex = polygone.length-1;\n\t\n\tif (polygone[0] !== polygone[lastIndex - 1] || polygone[1] !== polygone[lastIndex]) {\n\t\tpolygone.push(polygone[0]);\n\t\tpolygone.push(polygone[1]);\n\t}\n\t\n\tvar crossings = 0;\n\n\tvar x1, y1, x2, y2, d;\n\t\n    for (var i = 0; i < polygone.length - 3; ) {\n        x1=polygone[i];\n        y1=polygone[++i];\n        x2=polygone[++i];\n        y2=polygone[i+1];\n        d=(pointY - y1) * (x2 - x1) - (pointX - x1) * (y2 - y1);\n\n        if ((y1 >= pointY) != (y2 >= pointY)) {\n            crossings += y2 - y1 >= 0 ? d >= 0 : d <= 0;\n        }\n        if (!d && Math.min(x1,x2) <= pointX && pointX <= Math.max(x1,x2)\n            && Math.min(y1,y2) <= pointY && pointY <= Math.max(y1,y2)) {\n            return true;\n        }\n    }\n\treturn (crossings%2)?true:false;\n}\n\n/**\n *\tCalculates the distance between a point and a line. It is also testable, if \n *  the distance orthogonal to the line, matches the segment of the line.\n *  \n *  @param {float} lineP1\n *  \tThe starting point of the line segment\n *  @param {float} lineP2\n *  \tThe end point of the line segment\n *  @param {Point} point\n *  \tThe point to calculate the distance to.\n *  @param {boolean} toSegmentOnly\n *  \tFlag to signal if only the segment of the line shell be evaluated.\n */\nORYX.Core.Math.distancePointLinie = function(\n\t\t\t\t\t\t\t\t\tlineP1, \n\t\t\t\t\t\t\t\t\tlineP2, \n\t\t\t\t\t\t\t\t\tpoint, \n\t\t\t\t\t\t\t\t\ttoSegmentOnly) {\n\t\n\tvar intersectionPoint = \n\t\t\t\tORYX.Core.Math.getPointOfIntersectionPointLine(lineP1, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tlineP2, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tpoint, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttoSegmentOnly);\n\t\n\tif(!intersectionPoint) {\n\t\treturn null;\n\t}\n\t\n\treturn ORYX.Core.Math.getDistancePointToPoint(point, intersectionPoint);\n};\n\n/**\n * Calculates the distance between two points.\n * \n * @param {point} point1\n * @param {point} point2\n */\nORYX.Core.Math.getDistancePointToPoint = function(point1, point2) {\n\treturn Math.sqrt(Math.pow(point1.x - point2.x, 2) + Math.pow(point1.y - point2.y, 2));\n};\n\n/**\n * Calculates the relative distance of a point which is between two other points.\n * \n * @param {point} between1\n * @param {point} between2\n * @param {point} point\n */\nORYX.Core.Math.getDistanceBetweenTwoPoints = function(between1, between2, point) {\n\treturn \tORYX.Core.Math.getDistancePointToPoint(point, between1) /\n\t\t\tORYX.Core.Math.getDistancePointToPoint(between1, between2);\n};\n\n\n/**\n * Returns true, if the point is of the left hand\n * side of the regarding the line.\n * \n * @param {point} lineP1 Line first point\n * @param {point} lineP2 Line second point\n * @param {point} point\n */\nORYX.Core.Math.pointIsLeftOfLine = function(lineP1, lineP2, point){\n\t\n\tvar vec1 = ORYX.Core.Math.getVector(lineP1, lineP2);\n\tvar vec2 = ORYX.Core.Math.getVector(lineP1, point);\n\t// if the cross produkt is more than 0\n\treturn ((vec1.x*vec2.y) - (vec2.x*vec1.y)) > 0\n};\n\n/**\n * Calculates the a point which is relatively between two other points.\n * \n * @param {point} point1\n * @param {point} point2\n * @param {number} relative Relative which is between 0 and 1\n */\nORYX.Core.Math.getPointBetweenTwoPoints = function(point1, point2, relative) {\n\trelative = Math.max(Math.min(relative || 0, 1), 0);\n\t\n\tif (relative === 0){\n\t\treturn point1;\n\t} else if (relative === 1){\n\t\treturn point2;\n\t}\n\t\n\treturn {\n\t\tx: point1.x + ((point2.x - point1.x) * relative),\n\t\ty: point1.y + ((point2.y - point1.y) * relative)\n\t}\n};\n\n\n/**\n * Returns the vector of the both points\n *\n * @param {point} point1\n * @param {point} point2\n */\nORYX.Core.Math.getVector = function(point1, point2){\n\treturn {\n\t\tx: point2.x - point1.x,\n\t\ty: point2.y - point1.y\n\t}\n}\n\n/**\n * Returns the an identity vector of the given vector, \n * which has the length ot one.\n *\n * @param {point} vector\n * or \n * @param {point} point1\n * @param {point} point2\n */\nORYX.Core.Math.getIdentityVector = function(vector){\n\t\n\tif (arguments.length == 2){\n\t\tvector = ORYX.Core.Math.getVector(arguments[0], arguments[1]);\n\t}\n\t\n\tvar length = Math.sqrt((vector.x*vector.x)+(vector.y*vector.y))\n\treturn {\n\t\tx: vector.x / (length || 1),\n\t\ty: vector.y / (length || 1)\n\t}\n}\n\n\nORYX.Core.Math.getOrthogonalIdentityVector = function(point1, point2){\n\tvar vec = arguments.length == 1 ? point1 : ORYX.Core.Math.getIdentityVector(point1, point2);\n\treturn {\n\t\tx: vec.y,\n\t\ty: -vec.x\n\t}\n}\n\n\n/**\n * Returns the intersection point of a line and a point that defines a line\n * orthogonal to the given line.\n * \n *  @param {float} lineP1\n *  \tThe starting point of the line segment\n *  @param {float} lineP2\n *  \tThe end point of the line segment\n *  @param {Point} point\n *  \tThe point to calculate the distance to.\n *  @param {boolean} onSegmentOnly\n *  \tFlag to signal if only the segment of the line shell be evaluated.\n */\nORYX.Core.Math.getPointOfIntersectionPointLine = function(\n\t\t\t\t\t\t\t\t\t\t\t\t\tlineP1, \n\t\t\t\t\t\t\t\t\t\t\t\t\tlineP2, \n\t\t\t\t\t\t\t\t\t\t\t\t\tpoint, \n\t\t\t\t\t\t\t\t\t\t\t\t\tonSegmentOnly) {\n\n\t/* \n\t * [P3 - P1 - u(P2 - P1)] dot (P2 - P1) = 0\n\t * u =((x3-x1)(x2-x1)+(y3-y1)(y2-y1))/(p2-p1)??\n\t */\n\tvar denominator = Math.pow(lineP2.x - lineP1.x, 2) \n\t\t\t\t\t\t+ Math.pow(lineP2.y - lineP1.y, 2);\n\tif(denominator == 0) {\n\t\treturn undefined;\n\t}\n\t\n\tvar u = ((point.x - lineP1.x) * (lineP2.x - lineP1.x)  \n\t\t\t+ (point.y - lineP1.y) * (lineP2.y - lineP1.y))\n\t\t\t/ denominator;\n\t\t\t\n\tif(onSegmentOnly) {\n\t\tif (!(0 <= u && u <= 1)) {\n\t\t\treturn undefined;\n\t\t}\n\t}\n\t\n\tpointOfIntersection = new Object();\n\tpointOfIntersection.x = lineP1.x + u * (lineP2.x - lineP1.x);\n\tpointOfIntersection.y = lineP1.y + u * (lineP2.y - lineP1.y);\t\n\t\n\treturn pointOfIntersection;\t\t\t\t\t\t\t\t\t\t\t\t\n};\n\n/**\n * Translated the point with the given matrix.\n * @param {Point} point\n * @param {Matrix} matrix \n * @return {Object} Includes x, y\n */\nORYX.Core.Math.getTranslatedPoint = function(point, matrix){\n\tvar x = matrix.a*point.x+matrix.c*point.y+matrix.e*1;\n\tvar y = matrix.b*point.x+matrix.d*point.y+matrix.f*1;\n    return {x:x, y:y}\n}\n\n\n/**\n * Returns the inverse matrix of the given SVG transformation matrix\n * @param {SVGTransformationMatrix} matrix\n * @return {Matrix}\n */\nORYX.Core.Math.getInverseMatrix = function(matrix){\n\n\tvar det = ORYX.Core.Math.getDeterminant(matrix), m = matrix;\n\t// +-     -+\n\t// | a c e |\n\t// | b d f |\n\t// | 0 0 1 |\n\t// +-     -+\n\treturn {\n\t\ta: det * ((m.d*1)-(m.f*0)),\n\t\tb: det * ((m.f*0)-(m.b*1)),\n\t\tc: det * ((m.e*0)-(m.c*1)),\n\t\td: det * ((m.a*1)-(m.e*0)),\n\t\te: det * ((m.c*m.f)-(m.e*m.d)),\n\t\tf: det * ((m.e*m.b)-(m.a*m.f))\n\t}\n}\n\n/**\n * Returns the determinant of the svg transformation matrix\n * @param {SVGTranformationMatrix} matrix\n * @return {Number}\n *\n */\nORYX.Core.Math.getDeterminant = function(m){\n\t// a11a22a33+a12a23a31+a13a21a32-a13a22a31-a12a21a33-a11a23a32\n\treturn (m.a*m.d*1)+(m.c*m.f*0)+(m.e*m.b*0)-(m.e*m.d*0)-(m.c*m.b*1)-(m.a*m.f*0);\n}\n\n/**\n * Returns the bounding box of the given node. Translates the \n * origin bounding box with the tranlation matrix.\n * @param {SVGElement} node\n * @return {Object} Includes x, y, width, height\n */\nORYX.Core.Math.getTranslatedBoundingBox = function(node){\n\tvar matrix = node.getCTM();\n\tvar bb = node.getBBox();\n\tvar ul = ORYX.Core.Math.getTranslatedPoint({x:bb.x, y:bb.y}, matrix);\n\tvar ll = ORYX.Core.Math.getTranslatedPoint({x:bb.x, y:bb.y+bb.height}, matrix);\n\tvar ur = ORYX.Core.Math.getTranslatedPoint({x:bb.x+bb.width, y:bb.y}, matrix);\n\tvar lr = ORYX.Core.Math.getTranslatedPoint({x:bb.x+bb.width, y:bb.y+bb.height}, matrix);\n\t\n\tvar minPoint = {\n\t    x: Math.min(ul.x, ll.x, ur.x, lr.x),\n\t    y: Math.min(ul.y, ll.y, ur.y, lr.y)\n\t}\n\tvar maxPoint = {\n\t    x: Math.max(ul.x, ll.x, ur.x, lr.x),\n\t    y: Math.max(ul.y, ll.y, ur.y, lr.y)\n\t}\n\treturn {\n\t    x: minPoint.x,\n\t    y: minPoint.y,\n\t    width: maxPoint.x - minPoint.x,\n\t    height: maxPoint.y - minPoint.y\n\t}\n};\n\n\n/**\n * Returns the angle of the given line, which is representated by the two points\n * @param {Point} p1\n * @param {Point} p2\n * @return {Number} 0 <= x <= 359.99999\n */\nORYX.Core.Math.getAngle = function(p1, p2){\n\tif(p1.x == p2.x && p1.y == p2.y)\n\t\treturn 0;\n\n\tvar angle = Math.asin(Math.sqrt(Math.pow(p1.y-p2.y, 2))\n\t\t\t\t/(Math.sqrt(Math.pow(p2.x-p1.x, 2)+Math.pow(p1.y-p2.y, 2))))\n\t\t\t\t*180/Math.PI;\n\t\n\tif(p2.x >= p1.x && p2.y <= p1.y)\n\t\treturn angle;\n\telse if(p2.x < p1.x && p2.y <= p1.y)\n\t\treturn 180 - angle;\n\telse if(p2.x < p1.x && p2.y > p1.y)\n\t\treturn 180 + angle;\n\telse\n\t\treturn 360 - angle;\n};\n\n\n/**\n * Implementation of the cohen-sutherland algorithm\n */\nnew function(){\n\t\n\tvar RIGHT = 2, TOP = 8,  BOTTOM = 4, LEFT = 1;\n\t\n \tfunction computeOutCode (x, y, xmin, ymin, xmax, ymax) {\n\t\tvar code = 0;\n\t\tif (y > ymax)\n\t\t    code |= TOP;\n\t\telse if (y < ymin)\n\t\t    code |= BOTTOM;\n\t\tif (x > xmax)\n\t\t    code |= RIGHT;\n\t\telse if (x < xmin)\n\t\t    code |= LEFT;\n\t\treturn code;\n\t}\n\t\n\t/**\n\t * Returns TRUE if the rectangle is over the edge and has intersection points or includes it\n\t * @param {Object} x1 Point A of the line\n\t * @param {Object} y1\n\t * @param {Object} x2 Point B of the line\n\t * @param {Object} y2\n\t * @param {Object} xmin Point A of the rectangle\n\t * @param {Object} ymin\n\t * @param {Object} xmax Point B of the rectangle\n\t * @param {Object} ymax\n\t */\n\tORYX.Core.Math.isRectOverLine = function(x1, y1, x2, y2, xmin, ymin, xmax, ymax){\n\t\treturn !!ORYX.Core.Math.clipLineOnRect.apply(ORYX.Core.Math, arguments);\n\t}\n\t\n\t/**\n\t * Returns the clipped line on the given rectangle. If there is \n\t * no intersection, it will return NULL.\n\t *  \n\t * @param {Object} x1 Point A of the line\n\t * @param {Object} y1\n\t * @param {Object} x2 Point B of the line\n\t * @param {Object} y2\n\t * @param {Object} xmin Point A of the rectangle\n\t * @param {Object} ymin\n\t * @param {Object} xmax Point B of the rectangle\n\t * @param {Object} ymax\n\t */\n\tORYX.Core.Math.clipLineOnRect = function(x1, y1, x2, y2, xmin, ymin, xmax, ymax){\n        //Outcodes for P0, P1, and whatever point lies outside the clip rectangle\n        var outcode0, outcode1, outcodeOut, hhh = 0;\n        var accept = false, done = false;\n \n        //compute outcodes\n        outcode0 = computeOutCode(x1, y1, xmin, ymin, xmax, ymax);\n        outcode1 = computeOutCode(x2, y2, xmin, ymin, xmax, ymax);\n \n        do {\n            if ((outcode0 | outcode1) == 0 ){\n                accept = true;\n                done = true;\n            } else if ( (outcode0 & outcode1) > 0 ) {\n                done = true;\n            } else {\n                //failed both tests, so calculate the line segment to clip\n                //from an outside point to an intersection with clip edge\n                var x = 0, y = 0;\n                //At least one endpoint is outside the clip rectangle; pick it.\n                outcodeOut = outcode0 != 0 ? outcode0: outcode1;\n                //Now find the intersection point;\n                //use formulas y = y0 + slope * (x - x0), x = x0 + (1/slope)* (y - y0)\n                if ( (outcodeOut & TOP) > 0 ) {\n                    x = x1 + (x2 - x1) * (ymax - y1)/(y2 - y1);\n                    y = ymax;\n                } else if ((outcodeOut & BOTTOM) > 0 ) {\n                    x = x1 + (x2 - x1) * (ymin - y1)/(y2 - y1);\n                    y = ymin;\n                } else if ((outcodeOut & RIGHT)> 0) {\n                    y = y1 + (y2 - y1) * (xmax - x1)/(x2 - x1);\n                    x = xmax;\n                } else if ((outcodeOut & LEFT) > 0) {\n                    y = y1 + (y2 - y1) * (xmin - x1)/(x2 - x1);\n                    x = xmin;\n                }\n\t\t\t\t\n                //Now we move outside point to intersection point to clip\n                //and get ready for next pass.\n                if (outcodeOut == outcode0) {\n                    x1 = x;\n                    y1 = y;\n                    outcode0 = computeOutCode (x1, y1, xmin, ymin, xmax, ymax);\n                } else {\n                    x2 = x;\n                    y2 = y;\n                    outcode1 = computeOutCode (x2, y2, xmin, ymin, xmax, ymax);\n                }\n            }\n            hhh ++;\n        } while (done  != true && hhh < 5000);\n \n        if(accept) {\n            return {a:{x:x1, y:y1}, b:{x:x2, y:y2}};\n        }\n\t\treturn null;\n    }\n}();\n\n\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespace\n */\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\nif(!ORYX.Core.StencilSet) {ORYX.Core.StencilSet = {};}\n\n/**\n * Class Stencil\n * uses Prototpye 1.5.0\n * uses Inheritance\n * \n * This class represents one stencil of a stencil set.\n */\nORYX.Core.StencilSet.Stencil = {\n\n\t/**\n\t * Constructor\n\t */\n\tconstruct: function(jsonStencil, namespace, source, stencilSet, propertyPackages, defaultPosition) {\n\t\targuments.callee.$.construct.apply(this, arguments); // super();\n\t\t\n\t\t// check arguments and set defaults.\n\t\tif(!jsonStencil) throw \"Stencilset seems corrupt.\";\n\t\tif(!namespace) throw \"Stencil does not provide namespace.\";\n\t\tif(!source) throw \"Stencil does not provide SVG source.\";\n\t\tif(!stencilSet) throw \"Fatal internal error loading stencilset.\";\n\t\t//if(!propertyPackages) throw \"Fatal internal error loading stencilset.\";\n\t\t\n\t\tthis._source = source;\n\t\tthis._jsonStencil = jsonStencil;\n\t\tthis._stencilSet = stencilSet;\n\t\tthis._namespace = namespace;\n\t\tthis._propertyPackages = propertyPackages;\n\t\t\n\t\tif(defaultPosition && !this._jsonStencil.position) \n\t\t\tthis._jsonStencil.position = defaultPosition;\n\t\t\n\t\tthis._view;\n\t\tthis._properties = new Hash();\n\n\t\t// check stencil consistency and set defaults.\n\t\t/*with(this._jsonStencil) {\n\t\t\t\n\t\t\tif(!type) throw \"Stencil does not provide type.\";\n\t\t\tif((type != \"edge\") && (type != \"node\"))\n\t\t\t\tthrow \"Stencil type must be 'edge' or 'node'.\";\n\t\t\tif(!id || id == \"\") throw \"Stencil does not provide valid id.\";\n\t\t\tif(!title || title == \"\")\n\t\t\t\tthrow \"Stencil does not provide title\";\n\t\t\tif(!description) { description = \"\"; };\n\t\t\tif(!groups) { groups = []; }\n\t\t\tif(!roles) { roles = []; }\n\n\t\t\t// add id of stencil to its roles\n\t\t\troles.push(id);\n\t\t}*/\n\t\t\n\t\t//init all JSON values\n\t\tif(!this._jsonStencil.type || !(this._jsonStencil.type === \"edge\" || this._jsonStencil.type === \"node\")) {\n\t\t\tthrow \"ORYX.Core.StencilSet.Stencil(construct): Type is not defined.\";\n\t\t}\n\t\tif(!this._jsonStencil.id || this._jsonStencil.id === \"\") {\n\t\t\tthrow \"ORYX.Core.StencilSet.Stencil(construct): Id is not defined.\";\n\t\t}\n\t\tif(!this._jsonStencil.title || this._jsonStencil.title === \"\") {\n\t\t\tthrow \"ORYX.Core.StencilSet.Stencil(construct): Title is not defined.\";\n\t\t}\n\n\t\tif(!this._jsonStencil.description) { this._jsonStencil.description = \"\"; };\n\t\tif(!this._jsonStencil.groups) { this._jsonStencil.groups = []; }\n\t\tif(!this._jsonStencil.roles) { this._jsonStencil.roles = []; }\n\t\t\n\t\t//add id of stencil to its roles\n\t\tthis._jsonStencil.roles.push(this._jsonStencil.id);\n\n\t\t//prepend namespace to each role\n\t\tthis._jsonStencil.roles.each((function(role, index) {\n\t\t\tthis._jsonStencil.roles[index] = namespace + role;\n\t\t}).bind(this));\n\n\t\t//delete duplicate roles\n\t\tthis._jsonStencil.roles = this._jsonStencil.roles.uniq();\n\n\t\t//make id unique by prepending namespace of stencil set\n\t\tthis._jsonStencil.id = namespace + this._jsonStencil.id;\n\n\t\tthis.postProcessProperties();\n\t\t\n\t\t// init serialize callback\n\t\tif(!this._jsonStencil.serialize) {\n\t\t\tthis._jsonStencil.serialize = {};\n\t\t\t//this._jsonStencil.serialize = function(shape, data) { return data;};\n\t\t}\n\t\t\n\t\t// init deserialize callback\n\t\tif(!this._jsonStencil.deserialize) {\n\t\t\tthis._jsonStencil.deserialize = {};\n\t\t\t//this._jsonStencil.deserialize = function(shape, data) { return data;};\n\t\t}\n\t\t\n\t\t// init layout callback\n\t\tif(!this._jsonStencil.layout) {\n\t\t\tthis._jsonStencil.layout = []\n\t\t\t//this._jsonStencil.layout = function() {return true;}\n\t\t}\n\t\t\n\t\t//TODO does not work correctly, if the url does not exist\n\t\t//How to guarantee that the view is loaded correctly before leaving the constructor???\n\t\tvar url = source + \"view/\" + jsonStencil.view;\n\t\t// override content type when this is webkit.\n\t\t\n\t\tif(this._jsonStencil.view.trim().match(/</)) {\n\t\t\tvar parser\t= new DOMParser();\t\t\n\t\t\tvar xml \t= parser.parseFromString( this._jsonStencil.view ,\"text/xml\");\n\t\t\t\n\t\t\t//check if result is a SVG document\n\t\t\tif( ORYX.Editor.checkClassType( xml.documentElement, SVGSVGElement )) {\n\t\n\t\t\t\tthis._view = xml.documentElement;\n\t\t\t\t\n\t\t\t} else {\n\t\t\t\tthrow \"ORYX.Core.StencilSet.Stencil(_loadSVGOnSuccess): The response is not a SVG document.\"\n\t\t\t}\n\t\t} else {\n\t\t\tnew Ajax.Request(\n\t\t\t\turl, {\n\t\t\t\t\tasynchronous:false, method:'get',\n\t\t\t\t\tonSuccess:this._loadSVGOnSuccess.bind(this),\n\t\t\t\t\tonFailure:this._loadSVGOnFailure.bind(this)\n\t\t\t});\n\t\t}\n\t},\n\n\tpostProcessProperties: function() {\n\n\t\t// init property packages\n\t\tif(this._jsonStencil.propertyPackages && this._jsonStencil.propertyPackages instanceof Array) {\n\t\t\t\n\t\t\tthis._jsonStencil.propertyPackages.each((function(ppId) {\n\t\t\t\tvar pp = this._propertyPackages[ppId];\n\t\t\t\t\n\t\t\t\tif(pp) {\n\t\t\t\t\tpp.each((function(prop){\n\t\t\t\t\t\tvar oProp = new ORYX.Core.StencilSet.Property(prop, this._namespace, this);\n\t\t\t\t\t\tthis._properties[oProp.prefix() + \"-\" + oProp.id()] = oProp;\n\t\t\t\t\t\t\n\t\t\t\t\t}).bind(this));\n\t\t\t\t}\n\t\t\t}).bind(this));\n\t\t}\n\t\t\n\t\t// init properties\n\t\tif(this._jsonStencil.properties && this._jsonStencil.properties instanceof Array) {\n\t\t\tthis._jsonStencil.properties.each((function(prop) {\n\t\t\t\tvar oProp = new ORYX.Core.StencilSet.Property(prop, this._namespace, this);\n\t\t\t\tthis._properties[oProp.prefix() + \"-\" + oProp.id()] = oProp;\n\t\t\t}).bind(this));\n\t\t}\n\n\t},\n\n\t/**\n\t * @param {ORYX.Core.StencilSet.Stencil} stencil\n\t * @return {Boolean} True, if stencil has the same namespace and type.\n\t */\n\tequals: function(stencil) {\n\t\treturn (this.id() === stencil.id());\n\t},\n\n\tstencilSet: function() {\n\t\treturn this._stencilSet;\n\t},\n\n\ttype: function() {\n\t\treturn this._jsonStencil.type;\n\t},\n\n\tnamespace: function() {\n\t\treturn this._namespace;\n\t},\n\n\tid: function() {\n\t\treturn this._jsonStencil.id;\n\t},\n    \n    idWithoutNs: function(){\n        return this.id().replace(this.namespace(),\"\");\n    },\n\n\ttitle: function() {\n\t\treturn ORYX.Core.StencilSet.getTranslation(this._jsonStencil, \"title\");\n\t},\n\n\tdescription: function() {\n\t\treturn ORYX.Core.StencilSet.getTranslation(this._jsonStencil, \"description\");\n\t},\n\t\n\tgroups: function() {\n\t\treturn ORYX.Core.StencilSet.getTranslation(this._jsonStencil, \"groups\");\n\t},\n\t\n\tposition: function() {\n\t\treturn (isNaN(this._jsonStencil.position) ? 0 : this._jsonStencil.position);\n\t},\n\n\tview: function() {\n\t\treturn this._view.cloneNode(true) || this._view;\n\t},\n\n\ticon: function() {\n\t\treturn this._jsonStencil.icon;\n\t},\n\t\n\tfixedAspectRatio: function() {\n\t\treturn this._jsonStencil.fixedAspectRatio === true;\n\t},\n\t\n\thasMultipleRepositoryEntries: function() {\n\t\treturn (this.getRepositoryEntries().length > 0);\n\t},\n\t\n\tgetRepositoryEntries: function() {\n\t\treturn (this._jsonStencil.repositoryEntries) ?\n\t\t\t$A(this._jsonStencil.repositoryEntries) : $A([]);\n\t},\n\t\n\tproperties: function() {\n\t\treturn this._properties.values();\n\t},\n\n\tproperty: function(id) {\n\t\treturn this._properties[id];\n\t},\n\n\troles: function() {\n\t\treturn this._jsonStencil.roles;\n\t},\n\t\n\tdefaultAlign: function() {\n\t\tif(!this._jsonStencil.defaultAlign)\n\t\t\treturn \"east\";\n\t\treturn this._jsonStencil.defaultAlign;\n\t},\n\n\tserialize: function(shape, data) {\n\t\treturn this._jsonStencil.serialize;\n\t\t//return this._jsonStencil.serialize(shape, data);\n\t},\n\t\n\tdeserialize: function(shape, data) {\n\t\treturn this._jsonStencil.deserialize;\n\t\t//return this._jsonStencil.deserialize(shape, data);\n\t},\n\t\n\t// in which case is targetShape used?\n//\tlayout: function(shape, targetShape) {\n//\t\treturn this._jsonStencil.layout(shape, targetShape);\n//\t},\n\t// layout property to store events for layouting in plugins\n\tlayout: function(shape) {\n\t\treturn this._jsonStencil.layout\n\t},\n\t\n\taddProperty: function(property, namespace) {\n\t\tif(property && namespace) {\n\t\t\tvar oProp = new ORYX.Core.StencilSet.Property(property, namespace, this);\n\t\t\tthis._properties[oProp.prefix() + \"-\" + oProp.id()] = oProp;\n\t\t}\n\t},\n\t\n\tremoveProperty: function(propertyId) {\n\t\tif(propertyId) {\n\t\t\tvar oProp = this._properties.values().find(function(prop) {\n\t\t\t\treturn (propertyId == prop.id());\n\t\t\t});\n\t\t\tif(oProp)\n\t\t\t\tdelete this._properties[oProp.prefix() + \"-\" + oProp.id()];\n\t\t}\n\t},\n\n\t_loadSVGOnSuccess: function(result) {\n\t\t\n\t\tvar xml = null;\n\t\t\n\t\t/*\n\t\t * We want to get a dom object for the requested file. Unfortunately,\n\t\t * safari has some issues here. this is meant as a fallback for all\n\t\t * browsers that don't recognize the svg mimetype as XML but support\n\t\t * data: urls on Ajax calls.\n\t\t */\n\t\t\n\t\t// responseXML != undefined.\n\t\t// if(!(result.responseXML))\n\t\t\n\t\t\t// get the dom by data: url.\n\t\t\t// xml = _evenMoreEvilHack(result.responseText, 'text/xml');\n\t\t\n\t\t// else\n\t\t\n\t\t\t// get it the usual way.\n\t\t\txml = result.responseXML;\n\n\t\t//check if result is a SVG document\n\t\tif( ORYX.Editor.checkClassType( xml.documentElement, SVGSVGElement )) {\n\n\t\t\tthis._view = xml.documentElement;\n\t\t\t\n\t\t} else {\n\t\t\tthrow \"ORYX.Core.StencilSet.Stencil(_loadSVGOnSuccess): The response is not a SVG document.\"\n\t\t}\n\t},\n\n\t_loadSVGOnFailure: function(result) {\n\t\tthrow \"ORYX.Core.StencilSet.Stencil(_loadSVGOnFailure): Loading SVG document failed.\"\n\t},\n\n\ttoString: function() { return \"Stencil \" + this.title() + \" (\" + this.id() + \")\"; }\n};\n\nORYX.Core.StencilSet.Stencil = Clazz.extend(ORYX.Core.StencilSet.Stencil);\n\n/**\n * Transform a string into an xml document, the Safari way, as long as\n * the nightlies are broken. Even more evil version.\n * @param {Object} str\n * @param {Object} contentType\n */\nfunction _evenMoreEvilHack(str, contentType) {\n\t\n\t/*\n\t * This even more evil hack was taken from\n\t * http://web-graphics.com/mtarchive/001606.php#chatty004999\n\t */\n\t\n\tif (window.ActiveXObject) {\n\t\tvar d = new ActiveXObject(\"MSXML.DomDocument\");\n\t\td.loadXML(str);\n\t\treturn d;\n\t} else if (window.XMLHttpRequest) {\n\t\tvar req = new XMLHttpRequest;\n\t\treq.open(\"GET\", \"data:\" + (contentType || \"application/xml\") +\n\t\t\t\t\t\t\";charset=utf-8,\" + encodeURIComponent(str), false);\n\t\tif (req.overrideMimeType) {\n\t\t\treq.overrideMimeType(contentType);\n\t\t}\n\t\treq.send(null);\n\t\treturn req.responseXML;\n\t}\n}\n\n/**\n * Transform a string into an xml document, the Safari way, as long as\n * the nightlies are broken.\n * @param {Object} result the xml document object.\n */\nfunction _evilSafariHack(serializedXML) {\n\t\n\t/*\n\t *  The Dave way. Taken from:\n\t *  http://web-graphics.com/mtarchive/001606.php\n\t *  \n\t *  There is another possibility to parse XML in Safari, by implementing\n\t *  the DOMParser in javascript. However, in the latest nightlies of\n\t *  WebKit, DOMParser is already available, but still buggy. So, this is\n\t *  the best compromise for the time being.\n\t */\t\t\n\t\n\tvar xml = serializedXML;\n\tvar url = \"data:text/xml;charset=utf-8,\" + encodeURIComponent(xml);\n\tvar dom = null;\n\t\n\t// your standard AJAX stuff\n\tvar req = new XMLHttpRequest();\n\treq.open(\"GET\", url);\n\treq.onload = function() { dom = req.responseXML; }\n\treq.send(null);\n\t\n\treturn dom;\n}\n\t/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespace\n */\nif (!ORYX) {\n    var ORYX = {};\n}\nif (!ORYX.Core) {\n    ORYX.Core = {};\n}\nif (!ORYX.Core.StencilSet) {\n    ORYX.Core.StencilSet = {};\n}\n\n/**\n * Class Property\n * uses Prototpye 1.5.0\n * uses Inheritance\n */\nORYX.Core.StencilSet.Property = Clazz.extend({\n\n    /**\n     * Constructor\n     */\n    construct: function(jsonProp, namespace, stencil){\n        arguments.callee.$.construct.apply(this, arguments);\n        \n        this._jsonProp = jsonProp || ORYX.Log.error(\"Parameter jsonProp is not defined.\");\n        this._namespace = namespace || ORYX.Log.error(\"Parameter namespace is not defined.\");\n        this._stencil = stencil || ORYX.Log.error(\"Parameter stencil is not defined.\");\n        \n        this._items = {};\n        this._complexItems = {};\n        \n\t    // Flag to indicate whether or not the property should be hidden \n\t    // This can be for example when the stencil set is upgraded, but the model\n        // has a value for that specific property filled in which we still want to show.\n        // If the value is missing, the property can simply be not shown.\n        this._hidden = false;\n        \n        jsonProp.id = jsonProp.id || ORYX.Log.error(\"ORYX.Core.StencilSet.Property(construct): Id is not defined.\");\n\t\tjsonProp.id = jsonProp.id.toLowerCase();\n\t\t\n        if (!jsonProp.type) {\n            ORYX.Log.info(\"Type is not defined for stencil '%0', id '%1'. Falling back to 'String'.\", stencil, jsonProp.id);\n            jsonProp.type = \"string\";\n        }\n        else {\n            jsonProp.type = jsonProp.type.toLowerCase();\n        }\n        \n        jsonProp.prefix = jsonProp.prefix || \"oryx\";\n        jsonProp.title = jsonProp.title || \"\";\n        jsonProp.value = jsonProp.value || \"\";\n        jsonProp.description = jsonProp.description || \"\";\n        jsonProp.readonly = jsonProp.readonly || false;\n        jsonProp.optional = jsonProp.optional !== false;\n        \n        //init refToView\n        if (this._jsonProp.refToView) {\n            if (!(this._jsonProp.refToView instanceof Array)) {\n                this._jsonProp.refToView = [this._jsonProp.refToView];\n            }\n        }\n        else {\n            this._jsonProp.refToView = [];\n        }\n        \n\t\tvar globalMin = this.getMinForType(jsonProp.type);\n        if (jsonProp.min === undefined || jsonProp.min === null) {\n            jsonProp.min =globalMin;\n        } else if (jsonProp.min < globalMin) {\n\t\t\tjsonProp.min = globalMin;\n\t\t}\n        \n\t\tvar globalMax = this.getMaxForType(jsonProp.type);\n        if (jsonProp.max === undefined || jsonProp.max === null) {\n            jsonProp.max = globalMax;\n        } else if (jsonProp.max > globalMax) {\n\t\t\tjsonProp.min = globalMax;\n\t\t}\n        \n        if (!jsonProp.fillOpacity) {\n            jsonProp.fillOpacity = false;\n        }\n\t\t\n\t\tif (\"number\" != typeof jsonProp.lightness) {\n\t\t\tjsonProp.lightness = 1;\n\t\t} else {\n\t\t\tjsonProp.lightness = Math.max(0, Math.min(1, jsonProp.lightness));\n\t\t}\n        \n        if (!jsonProp.strokeOpacity) {\n            jsonProp.strokeOpacity = false;\n        }\n        \n        if (jsonProp.length === undefined || jsonProp.length === null) {\n            jsonProp.length = Number.MAX_VALUE;\n        }\n        \n        if (!jsonProp.wrapLines) {\n            jsonProp.wrapLines = false;\n        }\n        \n        if (!jsonProp.dateFormat) {\n            jsonProp.dateFormat = ORYX.I18N.PropertyWindow.dateFormat || \"m/d/y\";\n        }\n        \n        if (!jsonProp.fill) {\n            jsonProp.fill = false;\n        }\n        \n        if (!jsonProp.stroke) {\n            jsonProp.stroke = false;\n        }\n        \n        if(!jsonProp.inverseBoolean) {\n        \tjsonProp.inverseBoolean = false;\n        }\n\t\t\n\t\tif(!jsonProp.directlyEditable && jsonProp.directlyEditable != false) {\n        \tjsonProp.directlyEditable = true;\n        }\n\t\t\n\t\tif(jsonProp.visible !== false) {\n\t\t\tjsonProp.visible = true;\n\t\t}\n\t\t\n\t\tif(jsonProp.isList !== true) {\n\t\t\tjsonProp.isList = false;\n\t\t\t\n\t\t\tif(!jsonProp.list || !(jsonProp.list instanceof Array)) {\n\t\t\t\tjsonProp.list = [];\n\t\t\t}\t\n\t\t}\n\t\t\n\t\tif(!jsonProp.category) {\n\t\t\tif (jsonProp.popular) {\n\t\t\t\tjsonProp.category = \"popular\";\n\t\t\t} else {\n\t\t\t\tjsonProp.category = \"others\";\n\t\t\t}\n\t\t}\n\t\t\n\t\tif(!jsonProp.alwaysAppearInMultiselect) {\n\t\t\tjsonProp.alwaysAppearInMultiselect = false;\n\t\t}\n        \n        if (jsonProp.type === ORYX.CONFIG.TYPE_CHOICE) {\n            if (jsonProp.items && jsonProp.items instanceof Array) {\n                jsonProp.items.each((function(jsonItem){\n                \t// why is the item's value used as the key???\n                    this._items[jsonItem.value.toLowerCase()] = new ORYX.Core.StencilSet.PropertyItem(jsonItem, namespace, this);\n                }).bind(this));\n            }\n            else {\n                throw \"ORYX.Core.StencilSet.Property(construct): No property items defined.\"\n            }\n            // extended by Kerstin (start)\n        }\n        else \n            if (jsonProp.type === ORYX.CONFIG.TYPE_COMPLEX || jsonProp.type == ORYX.CONFIG.TYPE_MULTIPLECOMPLEX) {\n                if (jsonProp.complexItems && jsonProp.complexItems instanceof Array) {\n                    jsonProp.complexItems.each((function(jsonComplexItem){\n                        this._complexItems[jsonComplexItem.id.toLowerCase()] = new ORYX.Core.StencilSet.ComplexPropertyItem(jsonComplexItem, namespace, this);\n                    }).bind(this));\n                }\n            }\n        // extended by Kerstin (end)\n    },\n\t\n\tgetMinForType : function(type) {\n\t\tif (type.toLowerCase() == ORYX.CONFIG.TYPE_INTEGER) {\n\t\t\treturn -Math.pow(2,31)\n\t\t} else {\n\t\t\treturn -Number.MAX_VALUE+1;\n\t\t}\n\t}, \n\tgetMaxForType : function(type) {\n\t\tif (type.toLowerCase() == ORYX.CONFIG.TYPE_INTEGER) {\n\t\t\treturn Math.pow(2,31)-1\n\t\t} else {\n\t\t\treturn Number.MAX_VALUE;\n\t\t}\n\t},\n    \n    /**\n     * @param {ORYX.Core.StencilSet.Property} property\n     * @return {Boolean} True, if property has the same namespace and id.\n     */\n    equals: function(property){\n        return (this._namespace === property.namespace() &&\n        this.id() === property.id()) ? true : false;\n    },\n    \n    namespace: function(){\n        return this._namespace;\n    },\n    \n    stencil: function(){\n        return this._stencil;\n    },\n    \n    id: function(){\n        return this._jsonProp.id;\n    },\n    \n    prefix: function(){\n        return this._jsonProp.prefix;\n    },\n    \n    type: function(){\n        return this._jsonProp.type;\n    },\n    \n    inverseBoolean: function() {\n    \treturn this._jsonProp.inverseBoolean;\n    },\n\t\n\tcategory: function() {\n\t\treturn this._jsonProp.category;\n\t},\n\t\n\tsetCategory: function(value) {\n\t\tthis._jsonProp.category = value;\n\t},\n\t\n\tdirectlyEditable: function() {\n\t\treturn this._jsonProp.directlyEditable;\n\t},\n\t\n\tvisible: function() {\n\t\treturn this._jsonProp.visible;\n\t},\n    \n    title: function(){\n        return ORYX.Core.StencilSet.getTranslation(this._jsonProp, \"title\");\n    },\n    \n    value: function(){\n        return this._jsonProp.value;\n    },\n    \n    readonly: function(){\n        return this._jsonProp.readonly;\n    },\n    \n    optional: function(){\n        return this._jsonProp.optional;\n    },\n    \n    description: function(){\n        return ORYX.Core.StencilSet.getTranslation(this._jsonProp, \"description\");\n    },\n\t\n    /**\n     * An optional link to a SVG element so that the property affects the\n     * graphical representation of the stencil.\n     */\n    refToView: function(){\n        return this._jsonProp.refToView;\n    },\n    \n    /**\n     * If type is integer or float, min is the lower bounds of value.\n     */\n    min: function(){\n        return this._jsonProp.min;\n    },\n    \n    /**\n     * If type ist integer or float, max is the upper bounds of value.\n     */\n    max: function(){\n        return this._jsonProp.max;\n    },\n    \n    /**\n     * If type is float, this method returns if the fill-opacity property should\n     *  be set.\n     *  @return {Boolean}\n     */\n    fillOpacity: function(){\n        return this._jsonProp.fillOpacity;\n    },\n    \n    /**\n     * If type is float, this method returns if the stroke-opacity property should\n     *  be set.\n     *  @return {Boolean}\n     */\n    strokeOpacity: function(){\n        return this._jsonProp.strokeOpacity;\n    },\n    \n    /**\n     * If type is string or richtext, length is the maximum length of the text.\n     * TODO how long can a string be.\n     */\n    length: function(){\n        return this._jsonProp.length ? this._jsonProp.length : Number.MAX_VALUE;\n    },\n    \n    wrapLines: function(){\n        return this._jsonProp.wrapLines;\n    },\n    \n    /**\n     * If type is date, dateFormat specifies the format of the date. The format\n     * specification of the ext library is used:\n     *\n     * Format  Output      Description\n     *\t------  ----------  --------------------------------------------------------------\n     *\t  d      10         Day of the month, 2 digits with leading zeros\n     *\t  D      Wed        A textual representation of a day, three letters\n     *\t  j      10         Day of the month without leading zeros\n     *\t  l      Wednesday  A full textual representation of the day of the week\n     *\t  S      th         English ordinal day of month suffix, 2 chars (use with j)\n     *\t  w      3          Numeric representation of the day of the week\n     *\t  z      9          The julian date, or day of the year (0-365)\n     *\t  W      01         ISO-8601 2-digit week number of year, weeks starting on Monday (00-52)\n     *\t  F      January    A full textual representation of the month\n     *\t  m      01         Numeric representation of a month, with leading zeros\n     *\t  M      Jan        Month name abbreviation, three letters\n     *\t  n      1          Numeric representation of a month, without leading zeros\n     *\t  t      31         Number of days in the given month\n     *\t  L      0          Whether its a leap year (1 if it is a leap year, else 0)\n     *\t  Y      2007       A full numeric representation of a year, 4 digits\n     *\t  y      07         A two digit representation of a year\n     *\t  a      pm         Lowercase Ante meridiem and Post meridiem\n     *\t  A      PM         Uppercase Ante meridiem and Post meridiem\n     *\t  g      3          12-hour format of an hour without leading zeros\n     *\t  G      15         24-hour format of an hour without leading zeros\n     *\t  h      03         12-hour format of an hour with leading zeros\n     *\t  H      15         24-hour format of an hour with leading zeros\n     *\t  i      05         Minutes with leading zeros\n     *\t  s      01         Seconds, with leading zeros\n     *\t  O      -0600      Difference to Greenwich time (GMT) in hours\n     *\t  T      CST        Timezone setting of the machine running the code\n     *\t  Z      -21600     Timezone offset in seconds (negative if west of UTC, positive if east)\n     *\n     * Example:\n     *  F j, Y, g:i a  ->  January 10, 2007, 3:05 pm\n     */\n    dateFormat: function(){\n        return this._jsonProp.dateFormat;\n    },\n    \n    /**\n     * If type is color, this method returns if the fill property should\n     *  be set.\n     *  @return {Boolean}\n     */\n    fill: function(){\n        return this._jsonProp.fill;\n    },\n\t\n\t/**\n\t * Lightness defines the satiation of the color\n\t * 0 is the pure color\n\t * 1 is white\n\t * @return {Integer} lightness\n\t */\n\tlightness: function(){\n\t\treturn this._jsonProp.lightness;\n\t},\n    \n    /**\n     * If type is color, this method returns if the stroke property should\n     *  be set.\n     *  @return {Boolean}\n     */\n    stroke: function(){\n        return this._jsonProp.stroke;\n    },\n    \n    /**\n     * If type is choice, items is a hash map with all alternative values\n     * (PropertyItem objects) with id as keys.\n     */\n    items: function(){\n        return $H(this._items).values();\n    },\n    \n    item: function(value){\n        if (value) {\n\t\t\treturn this._items[value.toLowerCase()];\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n    },\n    \n    toString: function(){\n        return \"Property \" + this.title() + \" (\" + this.id() + \")\";\n    },\n    \n    complexItems: function(){\n        return $H(this._complexItems).values();\n    },\n    \n    complexItem: function(id){\n        if(id) {\n\t\t\treturn this._complexItems[id.toLowerCase()];\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t\t\n    },\n    \n    complexAttributeToView: function(){\n        return this._jsonProp.complexAttributeToView || \"\";\n    },\n    \n    isList: function() {\n    \treturn !!this._jsonProp.isList;\n    },\n    \n    getListItems: function() {\n    \treturn this._jsonProp.list;\n    },\n\t\n\t/**\n\t * If type is glossary link, the \n\t * type of category can be defined where\n\t * the link only can go to.\n\t * @return {String} The glossary category id \n\t */\n\tlinkableType: function(){\n\t\treturn this._jsonProp.linkableType || \"\";\n\t},\n\t\n\talwaysAppearInMultiselect : function() {\n\t\treturn this._jsonProp.alwaysAppearInMultiselect;\n\t},\n\t\n\tpopular: function() {\n\t\treturn this._jsonProp.popular || false;\n\t},\n\t\n\tsetPopular: function() {\n\t\tthis._jsonProp.popular = true;\n\t},\n\t\n\thide: function() {\n\t\tthis._hidden = true;\n\t},\n\t\n\tisHidden: function() {\n\t\treturn this._hidden;\n\t}\n\t\n});\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespace\n */\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\nif(!ORYX.Core.StencilSet) {ORYX.Core.StencilSet = {};}\n\n/**\n * Class Stencil\n * uses Prototpye 1.5.0\n * uses Inheritance\n */\nORYX.Core.StencilSet.PropertyItem = Clazz.extend({\n\n\t/**\n\t * Constructor\n\t */\n\tconstruct: function(jsonItem, namespace, property) {\n\t\targuments.callee.$.construct.apply(this, arguments);\n\n\t\tif(!jsonItem) {\n\t\t\tthrow \"ORYX.Core.StencilSet.PropertyItem(construct): Parameter jsonItem is not defined.\";\n\t\t}\n\t\tif(!namespace) {\n\t\t\tthrow \"ORYX.Core.StencilSet.PropertyItem(construct): Parameter namespace is not defined.\";\n\t\t}\n\t\tif(!property) {\n\t\t\tthrow \"ORYX.Core.StencilSet.PropertyItem(construct): Parameter property is not defined.\";\n\t\t}\n\t\t\n\t\tthis._jsonItem = jsonItem;\n\t\tthis._namespace = namespace;\n\t\tthis._property = property;\n\t\t\n\t\t//init all values\n\t\tif(!jsonItem.value) {\n\t\t\tthrow \"ORYX.Core.StencilSet.PropertyItem(construct): Value is not defined.\";\n\t\t}\n\t\t\n\t\tif(this._jsonItem.refToView) {\n\t\t\tif(!(this._jsonItem.refToView instanceof Array)) {\n\t\t\t\tthis._jsonItem.refToView = [this._jsonItem.refToView];\n\t\t\t}\n\t\t} else {\n\t\t\tthis._jsonItem.refToView = [];\n\t\t}\n\t},\n\n\t/**\n\t * @param {ORYX.Core.StencilSet.PropertyItem} item\n\t * @return {Boolean} True, if item has the same namespace and id.\n\t */\n\tequals: function(item) {\n\t\treturn (this.property().equals(item.property()) &&\n\t\t\tthis.value() === item.value());\n\t},\n\n\tnamespace: function() {\n\t\treturn this._namespace;\n\t},\n\n\tproperty: function() {\n\t\treturn this._property;\n\t},\n\n\tvalue: function() {\n\t\treturn this._jsonItem.value;\n\t},\n\t\n\ttitle: function() {\n\t\treturn ORYX.Core.StencilSet.getTranslation(this._jsonItem, \"title\");\n\t},\n\n\trefToView: function() {\n\t\treturn this._jsonItem.refToView;\n\t},\n\t\n\ticon: function() {\n\t\treturn (this._jsonItem.icon) ? this.property().stencil()._source + \"icons/\" + this._jsonItem.icon : \"\";\n\t},\n\n\ttoString: function() { return \"PropertyItem \" + this.property() + \" (\" + this.value() + \")\"; }\n});/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespaces\n */\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\nif(!ORYX.Core.StencilSet) {ORYX.Core.StencilSet = {};}\n\n/**\n * Class Stencil\n * uses Prototpye 1.5.0\n * uses Inheritance\n */\nORYX.Core.StencilSet.ComplexPropertyItem = Clazz.extend({\n\n\t/**\n\t * Constructor\n\t */\n\tconstruct: function(jsonItem, namespace, property) {\n\t\targuments.callee.$.construct.apply(this, arguments);\n\n\t\tif(!jsonItem) {\n\t\t\tthrow \"ORYX.Core.StencilSet.ComplexPropertyItem(construct): Parameter jsonItem is not defined.\";\n\t\t}\n\t\tif(!namespace) {\n\t\t\tthrow \"ORYX.Core.StencilSet.ComplexPropertyItem(construct): Parameter namespace is not defined.\";\n\t\t}\n\t\tif(!property) {\n\t\t\tthrow \"ORYX.Core.StencilSet.ComplexPropertyItem(construct): Parameter property is not defined.\";\n\t\t}\n\t\t\n\t\tthis._jsonItem = jsonItem;\n\t\tthis._namespace = namespace;\n\t\tthis._property = property;\n\t\tthis._items = new Hash();\n\t\tthis._complexItems = new Hash();\n\t\t\n\t\t//init all values\n\t\tif(!jsonItem.name) {\n\t\t\tthrow \"ORYX.Core.StencilSet.ComplexPropertyItem(construct): Name is not defined.\";\n\t\t}\n\t\t\n\t\tif(!jsonItem.type) {\n\t\t\tthrow \"ORYX.Core.StencilSet.ComplexPropertyItem(construct): Type is not defined.\";\n\t\t} else {\n\t\t\tjsonItem.type = jsonItem.type.toLowerCase();\n\t\t}\n\t\t\n\t\tif(jsonItem.type === ORYX.CONFIG.TYPE_CHOICE) {\n\t\t\tif(jsonItem.items && jsonItem.items instanceof Array) {\n\t\t\t\tjsonItem.items.each((function(item) {\n\t\t\t\t\tthis._items[item.value] = new ORYX.Core.StencilSet.PropertyItem(item, namespace, this);\n\t\t\t\t}).bind(this));\n\t\t\t} else {\n\t\t\t\tthrow \"ORYX.Core.StencilSet.Property(construct): No property items defined.\"\n\t\t\t}\n\t\t} else if(jsonItem.type === ORYX.CONFIG.TYPE_COMPLEX) {\n\t\t\tif(jsonItem.complexItems && jsonItem.complexItems instanceof Array) {\n\t\t\t\tjsonItem.complexItems.each((function(complexItem) {\n\t\t\t\t\tthis._complexItems[complexItem.id] = new ORYX.Core.StencilSet.ComplexPropertyItem(complexItem, namespace, this);\n\t\t\t\t}).bind(this));\n\t\t\t} else {\n\t\t\t\tthrow \"ORYX.Core.StencilSet.Property(construct): No property items defined.\"\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * @param {ORYX.Core.StencilSet.PropertyItem} item\n\t * @return {Boolean} True, if item has the same namespace and id.\n\t */\n\tequals: function(item) {\n\t\treturn (this.property().equals(item.property()) &&\n\t\t\tthis.name() === item.name());\n\t},\n\n\tnamespace: function() {\n\t\treturn this._namespace;\n\t},\n\n\tproperty: function() {\n\t\treturn this._property;\n\t},\n\n\tname: function() {\n\t\treturn ORYX.Core.StencilSet.getTranslation(this._jsonItem, \"name\");\n\t},\n\t\n\tid: function() {\n\t\treturn this._jsonItem.id;\n\t},\n\t\n\ttype: function() {\n\t\treturn this._jsonItem.type;\n\t},\n\t\n\toptional: function() {\n\t\treturn this._jsonItem.optional;\n\t},\n\t\n\twidth: function() {\n\t\treturn this._jsonItem.width;\n\t},\n\t\n\tvalue: function() {\n\t\treturn this._jsonItem.value;\n\t},\n\t\n\titems: function() {\n\t\treturn this._items.values();\n\t},\n\t\n\tcomplexItems: function() {\n\t\treturn this._complexItems.values();\n\t},\n\t\n\tdisable: function() {\n\t\treturn this._jsonItem.disable;\n\t}\n});/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespaces\n */\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\nif(!ORYX.Core.StencilSet) {ORYX.Core.StencilSet = {};}\n\n/**\n * Class Rules uses Prototpye 1.5.0 uses Inheritance\n * \n * This class implements the API to check the stencil sets' rules.\n */\nORYX.Core.StencilSet.Rules = {\n\n\t/**\n\t * Constructor\n\t */\n\tconstruct: function() {\n\t\targuments.callee.$.construct.apply(this, arguments);\n\n\t\tthis._stencilSets = [];\n\t\tthis._stencils = [];\n\t\tthis._containerStencils = [];\n\t\t\n\t\tthis._cachedConnectSET = new Hash();\n\t\tthis._cachedConnectSE = new Hash();\n\t\tthis._cachedConnectTE = new Hash();\n\t\tthis._cachedCardSE = new Hash();\n\t\tthis._cachedCardTE = new Hash();\n\t\tthis._cachedContainPC = new Hash();\n\t\tthis._cachedMorphRS = new Hash();\n\t\t\n\t\tthis._connectionRules = new Hash();\n\t\tthis._cardinalityRules = new Hash();\n\t\tthis._containmentRules = new Hash();\n\t\tthis._morphingRules = new Hash();\n\t\tthis._layoutRules = new Hash();\n\t},\n\t\n\t/**\n\t * Call this method to initialize the rules for a stencil set and all of its\n\t * active extensions.\n\t * \n\t * @param {Object}\n\t *            stencilSet\n\t */\n\tinitializeRules: function(stencilSet) {\n\t\t\n\t\tvar existingSS = this._stencilSets.find(function(ss) {\n\t\t\t\t\t\t\treturn (ss.namespace() == stencilSet.namespace());\n\t\t\t\t\t\t});\n\t\tif (existingSS) {\n\t\t\t// reinitialize all rules\n\t\t\tvar stencilsets = this._stencilSets.clone();\n\t\t\tstencilsets = stencilsets.without(existingSS);\n\t\t\tstencilsets.push(stencilSet);\n\t\t\t\n\t\t\tthis._stencilSets = [];\n\t\t\tthis._stencils = [];\n\t\t\tthis._containerStencils = [];\n\t\t\t\n\t\t\tthis._cachedConnectSET = new Hash();\n\t\t\tthis._cachedConnectSE = new Hash();\n\t\t\tthis._cachedConnectTE = new Hash();\n\t\t\tthis._cachedCardSE = new Hash();\n\t\t\tthis._cachedCardTE = new Hash();\n\t\t\tthis._cachedContainPC = new Hash();\n\t\t\tthis._cachedMorphRS = new Hash();\n\t\t\t\n\t\t\tthis._connectionRules = new Hash();\n\t\t\tthis._cardinalityRules = new Hash();\n\t\t\tthis._containmentRules = new Hash();\n\t\t\tthis._morphingRules = new Hash();\n\t\t\tthis._layoutRules = new Hash();\n\t\t\t\n\t\t\tstencilsets.each(function(ss){\n\t\t\t\tthis.initializeRules(ss);\n\t\t\t}.bind(this));\n\t\t\treturn;\n\t\t}\n\t\telse {\n\t\t\tthis._stencilSets.push(stencilSet);\n\t\t\t\n\t\t\tvar jsonRules = new Hash(stencilSet.jsonRules());\n\t\t\tvar namespace = stencilSet.namespace();\n\t\t\tvar stencils = stencilSet.stencils();\n\t\t\t\n\t\t\tstencilSet.extensions().values().each(function(extension) {\n\t\t\t\tif(extension.rules) {\n\t\t\t\t\tif(extension.rules.connectionRules)\n\t\t\t\t\t\tjsonRules.connectionRules = jsonRules.connectionRules.concat(extension.rules.connectionRules);\n\t\t\t\t\tif(extension.rules.cardinalityRules)\n\t\t\t\t\t\tjsonRules.cardinalityRules = jsonRules.cardinalityRules.concat(extension.rules.cardinalityRules);\n\t\t\t\t\tif(extension.rules.containmentRules)\n\t\t\t\t\t\tjsonRules.containmentRules = jsonRules.containmentRules.concat(extension.rules.containmentRules);\n\t\t\t\t\tif(extension.rules.morphingRules)\n\t\t\t\t\t\tjsonRules.morphingRules = jsonRules.morphingRules.concat(extension.rules.morphingRules);\n\t\t\t\t}\n\t\t\t\tif(extension.stencils) \n\t\t\t\t\tstencils = stencils.concat(extension.stencils);\n\t\t\t});\n\t\t\t\n\t\t\tthis._stencils = this._stencils.concat(stencilSet.stencils());\n\t\t\t\n\t\t\t// init connection rules\n\t\t\tvar cr = this._connectionRules;\n\t\t\tif (jsonRules.connectionRules) {\n\t\t\t\tjsonRules.connectionRules.each((function(rules){\n\t\t\t\t\tif (this._isRoleOfOtherNamespace(rules.role)) {\n\t\t\t\t\t\tif (!cr[rules.role]) {\n\t\t\t\t\t\t\tcr[rules.role] = new Hash();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tif (!cr[namespace + rules.role]) \n\t\t\t\t\t\t\tcr[namespace + rules.role] = new Hash();\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\trules.connects.each((function(connect){\n\t\t\t\t\t\tvar toRoles = [];\n\t\t\t\t\t\tif (connect.to) {\n\t\t\t\t\t\t\tif (!(connect.to instanceof Array)) {\n\t\t\t\t\t\t\t\tconnect.to = [connect.to];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconnect.to.each((function(to){\n\t\t\t\t\t\t\t\tif (this._isRoleOfOtherNamespace(to)) {\n\t\t\t\t\t\t\t\t\ttoRoles.push(to);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\ttoRoles.push(namespace + to);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}).bind(this));\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tvar role, from;\n\t\t\t\t\t\tif (this._isRoleOfOtherNamespace(rules.role)) \n\t\t\t\t\t\t\trole = rules.role;\n\t\t\t\t\t\telse \n\t\t\t\t\t\t\trole = namespace + rules.role;\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (this._isRoleOfOtherNamespace(connect.from)) \n\t\t\t\t\t\t\tfrom = connect.from;\n\t\t\t\t\t\telse \n\t\t\t\t\t\t\tfrom = namespace + connect.from;\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (!cr[role][from]) \n\t\t\t\t\t\t\tcr[role][from] = toRoles;\n\t\t\t\t\t\telse \n\t\t\t\t\t\t\tcr[role][from] = cr[role][from].concat(toRoles);\n\t\t\t\t\t\t\n\t\t\t\t\t}).bind(this));\n\t\t\t\t}).bind(this));\n\t\t\t}\n\t\t\t\n\t\t\t// init cardinality rules\n\t\t\tvar cardr = this._cardinalityRules;\n\t\t\tif (jsonRules.cardinalityRules) {\n\t\t\t\tjsonRules.cardinalityRules.each((function(rules){\n\t\t\t\t\tvar cardrKey;\n\t\t\t\t\tif (this._isRoleOfOtherNamespace(rules.role)) {\n\t\t\t\t\t\tcardrKey = rules.role;\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tcardrKey = namespace + rules.role;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif (!cardr[cardrKey]) {\n\t\t\t\t\t\tcardr[cardrKey] = {};\n\t\t\t\t\t\tfor (i in rules) {\n\t\t\t\t\t\t\tcardr[cardrKey][i] = rules[i];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tvar oe = new Hash();\n\t\t\t\t\tif (rules.outgoingEdges) {\n\t\t\t\t\t\trules.outgoingEdges.each((function(rule){\n\t\t\t\t\t\t\tif (this._isRoleOfOtherNamespace(rule.role)) {\n\t\t\t\t\t\t\t\toe[rule.role] = rule;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\toe[namespace + rule.role] = rule;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}).bind(this));\n\t\t\t\t\t}\n\t\t\t\t\tcardr[cardrKey].outgoingEdges = oe;\n\t\t\t\t\tvar ie = new Hash();\n\t\t\t\t\tif (rules.incomingEdges) {\n\t\t\t\t\t\trules.incomingEdges.each((function(rule){\n\t\t\t\t\t\t\tif (this._isRoleOfOtherNamespace(rule.role)) {\n\t\t\t\t\t\t\t\tie[rule.role] = rule;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tie[namespace + rule.role] = rule;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}).bind(this));\n\t\t\t\t\t}\n\t\t\t\t\tcardr[cardrKey].incomingEdges = ie;\n\t\t\t\t}).bind(this));\n\t\t\t}\n\t\t\t\n\t\t\t// init containment rules\n\t\t\tvar conr = this._containmentRules;\n\t\t\tif (jsonRules.containmentRules) {\n\t\t\t\tjsonRules.containmentRules.each((function(rules){\n\t\t\t\t\tvar conrKey;\n\t\t\t\t\tif (this._isRoleOfOtherNamespace(rules.role)) {\n\t\t\t\t\t\tconrKey = rules.role;\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tthis._containerStencils.push(namespace + rules.role);\n\t\t\t\t\t\tconrKey = namespace + rules.role;\n\t\t\t\t\t}\n\t\t\t\t\tif (!conr[conrKey]) {\n\t\t\t\t\t\tconr[conrKey] = [];\n\t\t\t\t\t}\n\t\t\t\t\t(rules.contains||[]).each((function(containRole){\n\t\t\t\t\t\tif (this._isRoleOfOtherNamespace(containRole)) {\n\t\t\t\t\t\t\tconr[conrKey].push(containRole);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tconr[conrKey].push(namespace + containRole);\n\t\t\t\t\t\t}\n\t\t\t\t\t}).bind(this));\n\t\t\t\t}).bind(this));\n\t\t\t}\n\t\t\t\n\t\t\t// init morphing rules\n\t\t\tvar morphr = this._morphingRules;\n\t\t\tif (jsonRules.morphingRules) {\n\t\t\t\tjsonRules.morphingRules.each((function(rules){\n\t\t\t\t\tvar morphrKey;\n\t\t\t\t\tif (this._isRoleOfOtherNamespace(rules.role)) {\n\t\t\t\t\t\tmorphrKey = rules.role;\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tmorphrKey = namespace + rules.role;\n\t\t\t\t\t}\n\t\t\t\t\tif (!morphr[morphrKey]) {\n\t\t\t\t\t\tmorphr[morphrKey] = [];\n\t\t\t\t\t}\n\t\t\t\t\tif(!rules.preserveBounds) {\n\t\t\t\t\t\trules.preserveBounds = false;\n\t\t\t\t\t}\n\t\t\t\t\trules.baseMorphs.each((function(baseMorphStencilId){\n\t\t\t\t\t\tvar morphStencil = this._getStencilById(namespace + baseMorphStencilId);\n\t\t\t\t\t\tif(morphStencil) {\n\t\t\t\t\t\t\tmorphr[morphrKey].push(morphStencil);\n\t\t\t\t\t\t}\n\t\t\t\t\t}).bind(this));\n\t\t\t\t}).bind(this));\n\t\t\t}\n\t\t\t\n\t\t\t// init layouting rules\n\t\t\tvar layoutRules = this._layoutRules;\n\t\t\tif (jsonRules.layoutRules) {\n\t\t\t\t\n\t\t\t\tvar getDirections = function(o){\n\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\"edgeRole\":o.edgeRole||undefined,\n\t\t\t\t\t\t\t\"t\": o[\"t\"]||1,\n\t\t\t\t\t\t\t\"r\": o[\"r\"]||1,\n\t\t\t\t\t\t\t\"b\": o[\"b\"]||1,\n\t\t\t\t\t\t\t\"l\": o[\"l\"]||1\n\t\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tjsonRules.layoutRules.each(function(rules){\n\t\t\t\t\tvar layoutKey;\n\t\t\t\t\tif (this._isRoleOfOtherNamespace(rules.role)) {\n\t\t\t\t\t\tlayoutKey = rules.role;\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tlayoutKey = namespace + rules.role;\n\t\t\t\t\t}\n\t\t\t\t\tif (!layoutRules[layoutKey]) {\n\t\t\t\t\t\tlayoutRules[layoutKey] = {};\n\t\t\t\t\t}\n\t\t\t\t\tif (rules[\"in\"]){\n\t\t\t\t\t\tlayoutRules[layoutKey][\"in\"] = getDirections(rules[\"in\"]);\n\t\t\t\t\t}\n\t\t\t\t\tif (rules[\"ins\"]){\n\t\t\t\t\t\tlayoutRules[layoutKey][\"ins\"] = (rules[\"ins\"]||[]).map(function(e){ return getDirections(e) })\n\t\t\t\t\t}\n\t\t\t\t\tif (rules[\"out\"]) {\n\t\t\t\t\t\tlayoutRules[layoutKey][\"out\"] = getDirections(rules[\"out\"]);\n\t\t\t\t\t}\n\t\t\t\t\tif (rules[\"outs\"]){\n\t\t\t\t\t\tlayoutRules[layoutKey][\"outs\"] = (rules[\"outs\"]||[]).map(function(e){ return getDirections(e) })\n\t\t\t\t\t}\n\t\t\t\t}.bind(this));\n\t\t\t}\t\t\t\n\t\t}\n\t},\n\t\n\t_getStencilById: function(id) {\n\t\treturn this._stencils.find(function(stencil) {\n\t\t\treturn stencil.id()==id;\n\t\t});\n\t},\n\t\n\t_cacheConnect: function(args) {\n\t\tresult = this._canConnect(args);\n\t\t\n\t\tif (args.sourceStencil && args.targetStencil) {\n\t\t\tvar source = this._cachedConnectSET[args.sourceStencil.id()];\n\t\t\t\n\t\t\tif(!source) {\n\t\t\t\tsource = new Hash();\n\t\t\t\tthis._cachedConnectSET[args.sourceStencil.id()] = source;\n\t\t\t}\n\t\t\t\n\t\t\tvar edge = source[args.edgeStencil.id()];\n\t\t\t\n\t\t\tif(!edge) {\n\t\t\t\tedge = new Hash();\n\t\t\t\tsource[args.edgeStencil.id()] = edge;\n\t\t\t}\n\t\t\t\n\t\t\tedge[args.targetStencil.id()] = result;\n\t\t\t\n\t\t} else if (args.sourceStencil) {\n\t\t\tvar source = this._cachedConnectSE[args.sourceStencil.id()];\n\t\t\t\n\t\t\tif(!source) {\n\t\t\t\tsource = new Hash();\n\t\t\t\tthis._cachedConnectSE[args.sourceStencil.id()] = source;\n\t\t\t}\n\t\t\t\n\t\t\tsource[args.edgeStencil.id()] = result;\n\n\t\t} else {\n\t\t\tvar target = this._cachedConnectTE[args.targetStencil.id()];\n\t\t\t\n\t\t\tif(!target) {\n\t\t\t\ttarget = new Hash();\n\t\t\t\tthis._cachedConnectTE[args.targetStencil.id()] = target;\n\t\t\t}\n\t\t\t\n\t\t\ttarget[args.edgeStencil.id()] = result;\n\t\t}\n\t\t\n\t\treturn result;\n\t},\n\t\n\t_cacheCard: function(args) {\n\t\t\t\n\t\tif(args.sourceStencil) {\n\t\t\tvar source = this._cachedCardSE[args.sourceStencil.id()]\n\t\t\t\n\t\t\tif(!source) {\n\t\t\t\tsource = new Hash();\n\t\t\t\tthis._cachedCardSE[args.sourceStencil.id()] = source;\n\t\t\t}\n\t\t\t\n\t\t\tvar max = this._getMaximumNumberOfOutgoingEdge(args);\n\t\t\tif(max == undefined)\n\t\t\t\tmax = -1;\n\t\t\t\t\n\t\t\tsource[args.edgeStencil.id()] = max;\n\t\t}\t\n\t\t\n\t\tif(args.targetStencil) {\n\t\t\tvar target = this._cachedCardTE[args.targetStencil.id()]\n\t\t\t\n\t\t\tif(!target) {\n\t\t\t\ttarget = new Hash();\n\t\t\t\tthis._cachedCardTE[args.targetStencil.id()] = target;\n\t\t\t}\n\t\t\t\n\t\t\tvar max = this._getMaximumNumberOfIncomingEdge(args);\n\t\t\tif(max == undefined)\n\t\t\t\tmax = -1;\n\t\t\t\t\n\t\t\ttarget[args.edgeStencil.id()] = max;\n\t\t}\n\t},\n\t\n\t_cacheContain: function(args) {\n\t\t\n\t\tvar result = [this._canContain(args), \n\t\t\t\t\t  this._getMaximumOccurrence(args.containingStencil, args.containedStencil)]\n\t\t\n\t\tif(result[1] == undefined) \n\t\t\tresult[1] = -1;\n\t\t\n\t\tvar children = this._cachedContainPC[args.containingStencil.id()];\n\t\t\n\t\tif(!children) {\n\t\t\tchildren = new Hash();\n\t\t\tthis._cachedContainPC[args.containingStencil.id()] = children;\n\t\t}\n\t\t\n\t\tchildren[args.containedStencil.id()] = result;\n\t\t\n\t\treturn result;\n\t},\n\t\n\t/**\n\t * Returns all stencils belonging to a morph group. (calculation result is\n\t * cached)\n\t */\n\t_cacheMorph: function(role) {\n\t\t\n\t\tvar morphs = this._cachedMorphRS[role];\n\t\t\n\t\tif(!morphs) {\n\t\t\tmorphs = [];\n\t\t\t\n\t\t\tif(this._morphingRules.keys().include(role)) {\n\t\t\t\tmorphs = this._stencils.select(function(stencil) {\n\t\t\t\t\treturn stencil.roles().include(role);\n\t\t\t\t});\n\t\t\t}\n\t\t\t\n\t\t\tthis._cachedMorphRS[role] = morphs;\n\t\t}\n\t\treturn morphs;\n\t},\n\t\n\t/** Begin connection rules' methods */\n\t\n\t/**\n\t * \n\t * @param {Object}\n\t *            args sourceStencil: ORYX.Core.StencilSet.Stencil | undefined\n\t *            sourceShape: ORYX.Core.Shape | undefined\n\t * \n\t * At least sourceStencil or sourceShape has to be specified\n\t * \n\t * @return {Array} Array of stencils of edges that can be outgoing edges of\n\t *         the source.\n\t */\n\toutgoingEdgeStencils: function(args) {\n\t\t// check arguments\n\t\tif(!args.sourceShape && !args.sourceStencil) {\n\t\t\treturn [];\n\t\t}\n\t\t\n\t\t// init arguments\n\t\tif(args.sourceShape) {\n\t\t\targs.sourceStencil = args.sourceShape.getStencil();\n\t\t}\n\t\t\n\t\tvar _edges = [];\n\t\t\n\t\t// test each edge, if it can connect to source\n\t\tthis._stencils.each((function(stencil) {\n\t\t\tif(stencil.type() === \"edge\") {\n\t\t\t\tvar newArgs = Object.clone(args);\n\t\t\t\tnewArgs.edgeStencil = stencil;\n\t\t\t\tif(this.canConnect(newArgs)) {\n\t\t\t\t\t_edges.push(stencil);\n\t\t\t\t}\n\t\t\t}\n\t\t}).bind(this));\n\n\t\treturn _edges;\n\t},\n\n\t/**\n\t * \n\t * @param {Object}\n\t *            args targetStencil: ORYX.Core.StencilSet.Stencil | undefined\n\t *            targetShape: ORYX.Core.Shape | undefined\n\t * \n\t * At least targetStencil or targetShape has to be specified\n\t * \n\t * @return {Array} Array of stencils of edges that can be incoming edges of\n\t *         the target.\n\t */\n\tincomingEdgeStencils: function(args) {\n\t\t// check arguments\n\t\tif(!args.targetShape && !args.targetStencil) {\n\t\t\treturn [];\n\t\t}\n\t\t\n\t\t// init arguments\n\t\tif(args.targetShape) {\n\t\t\targs.targetStencil = args.targetShape.getStencil();\n\t\t}\n\t\t\n\t\tvar _edges = [];\n\t\t\n\t\t// test each edge, if it can connect to source\n\t\tthis._stencils.each((function(stencil) {\n\t\t\tif(stencil.type() === \"edge\") {\n\t\t\t\tvar newArgs = Object.clone(args);\n\t\t\t\tnewArgs.edgeStencil = stencil;\n\t\t\t\tif(this.canConnect(newArgs)) {\n\t\t\t\t\t_edges.push(stencil);\n\t\t\t\t}\n\t\t\t}\n\t\t}).bind(this));\n\n\t\treturn _edges;\n\t},\n\t\n\t/**\n\t * \n\t * @param {Object}\n\t *            args edgeStencil: ORYX.Core.StencilSet.Stencil | undefined\n\t *            edgeShape: ORYX.Core.Edge | undefined targetStencil:\n\t *            ORYX.Core.StencilSet.Stencil | undefined targetShape:\n\t *            ORYX.Core.Node | undefined\n\t * \n\t * At least edgeStencil or edgeShape has to be specified!!!\n\t * \n\t * @return {Array} Returns an array of stencils that can be source of the\n\t *         specified edge.\n\t */\n\tsourceStencils: function(args) {\n\t\t// check arguments\n\t\tif(!args || \n\t\t   !args.edgeShape && !args.edgeStencil) {\n\t\t\treturn [];\n\t\t}\n\t\t\n\t\t// init arguments\n\t\tif(args.targetShape) {\n\t\t\targs.targetStencil = args.targetShape.getStencil();\n\t\t}\n\t\t\n\t\tif(args.edgeShape) {\n\t\t\targs.edgeStencil = args.edgeShape.getStencil();\n\t\t}\n\t\t\n\t\tvar _sources = [];\n\t\t\n\t\t// check each stencil, if it can be a source\n\t\tthis._stencils.each((function(stencil) {\n\t\t\tvar newArgs = Object.clone(args);\n\t\t\tnewArgs.sourceStencil = stencil;\n\t\t\tif(this.canConnect(newArgs)) {\n\t\t\t\t_sources.push(stencil);\n\t\t\t}\n\t\t}).bind(this));\n\n\t\treturn _sources;\n\t},\n\t\n\t/**\n\t * \n\t * @param {Object}\n\t *            args edgeStencil: ORYX.Core.StencilSet.Stencil | undefined\n\t *            edgeShape: ORYX.Core.Edge | undefined sourceStencil:\n\t *            ORYX.Core.StencilSet.Stencil | undefined sourceShape:\n\t *            ORYX.Core.Node | undefined\n\t * \n\t * At least edgeStencil or edgeShape has to be specified!!!\n\t * \n\t * @return {Array} Returns an array of stencils that can be target of the\n\t *         specified edge.\n\t */\n\ttargetStencils: function(args) {\n\t\t// check arguments\n\t\tif(!args || \n\t\t   !args.edgeShape && !args.edgeStencil) {\n\t\t\treturn [];\n\t\t}\n\t\t\n\t\t// init arguments\n\t\tif(args.sourceShape) {\n\t\t\targs.sourceStencil = args.sourceShape.getStencil();\n\t\t}\n\t\t\n\t\tif(args.edgeShape) {\n\t\t\targs.edgeStencil = args.edgeShape.getStencil();\n\t\t}\n\t\t\n\t\tvar _targets = [];\n\t\t\n\t\t// check stencil, if it can be a target\n\t\tthis._stencils.each((function(stencil) {\n\t\t\tvar newArgs = Object.clone(args);\n\t\t\tnewArgs.targetStencil = stencil;\n\t\t\tif(this.canConnect(newArgs)) {\n\t\t\t\t_targets.push(stencil);\n\t\t\t}\n\t\t}).bind(this));\n\n\t\treturn _targets;\n\t},\n\n\t/**\n\t * \n\t * @param {Object}\n\t *            args edgeStencil: ORYX.Core.StencilSet.Stencil edgeShape:\n\t *            ORYX.Core.Edge |undefined sourceStencil:\n\t *            ORYX.Core.StencilSet.Stencil | undefined sourceShape:\n\t *            ORYX.Core.Node |undefined targetStencil:\n\t *            ORYX.Core.StencilSet.Stencil | undefined targetShape:\n\t *            ORYX.Core.Node |undefined\n\t * \n\t * At least source or target has to be specified!!!\n\t * \n\t * @return {Boolean} Returns, if the edge can connect source and target.\n\t */\n\tcanConnect: function(args) {\t\n\t\t// check arguments\n\t\tif(!args ||\n\t\t   (!args.sourceShape && !args.sourceStencil &&\n\t\t    !args.targetShape && !args.targetStencil) ||\n\t\t    !args.edgeShape && !args.edgeStencil) {\n\t\t   \treturn false; \n\t\t}\n\t\t\n\t\t// init arguments\n\t\tif(args.sourceShape) {\n\t\t\targs.sourceStencil = args.sourceShape.getStencil();\n\t\t}\n\t\tif(args.targetShape) {\n\t\t\targs.targetStencil = args.targetShape.getStencil();\n\t\t}\n\t\tif(args.edgeShape) {\n\t\t\targs.edgeStencil = args.edgeShape.getStencil();\n\t\t}\n\t\t\n\t\tvar result;\n\t\t\n\t\tif(args.sourceStencil && args.targetStencil) {\n\t\t\tvar source = this._cachedConnectSET[args.sourceStencil.id()];\n\t\t\t\n\t\t\tif(!source)\n\t\t\t\tresult = this._cacheConnect(args);\n\t\t\telse {\n\t\t\t\tvar edge = source[args.edgeStencil.id()];\n\n\t\t\t\tif(!edge)\n\t\t\t\t\tresult = this._cacheConnect(args);\n\t\t\t\telse {\t\n\t\t\t\t\tvar target = edge[args.targetStencil.id()];\n\n\t\t\t\t\tif(target == undefined)\n\t\t\t\t\t\tresult = this._cacheConnect(args);\n\t\t\t\t\telse\n\t\t\t\t\t\tresult = target;\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (args.sourceStencil) {\t\n\t\t\tvar source = this._cachedConnectSE[args.sourceStencil.id()];\n\t\t\t\n\t\t\tif(!source)\n\t\t\t\tresult = this._cacheConnect(args);\n\t\t\telse {\n\t\t\t\tvar edge = source[args.edgeStencil.id()];\n\t\t\t\t\t\n\t\t\t\tif(edge == undefined)\n\t\t\t\t\tresult = this._cacheConnect(args);\n\t\t\t\telse\n\t\t\t\t\tresult = edge;\n\t\t\t}\n\t\t} else { // args.targetStencil\n\t\t\tvar target = this._cachedConnectTE[args.targetStencil.id()];\n\t\t\t\n\t\t\tif(!target)\n\t\t\t\tresult = this._cacheConnect(args);\n\t\t\telse {\n\t\t\t\tvar edge = target[args.edgeStencil.id()];\n\t\t\t\t\t\n\t\t\t\tif(edge == undefined)\n\t\t\t\t\tresult = this._cacheConnect(args);\n\t\t\t\telse\n\t\t\t\t\tresult = edge;\n\t\t\t}\n\t\t}\t\n\t\t\t\n\t\t// check cardinality\n\t\tif (result) {\n\t\t\tif(args.sourceShape) {\n\t\t\t\tvar source = this._cachedCardSE[args.sourceStencil.id()];\n\t\t\t\t\n\t\t\t\tif(!source) {\n\t\t\t\t\tthis._cacheCard(args);\n\t\t\t\t\tsource = this._cachedCardSE[args.sourceStencil.id()];\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tvar max = source[args.edgeStencil.id()];\n\t\t\t\t\n\t\t\t\tif(max == undefined) {\n\t\t\t\t\tthis._cacheCard(args);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tmax = source[args.edgeStencil.id()];\n\t\t\t\t\n\t\t\t\tif(max != -1) {\n\t\t\t\t\tresult = args.sourceShape.getOutgoingShapes().all(function(cs) {\n\t\t\t\t\t\t\t\tif((cs.getStencil().id() === args.edgeStencil.id()) && \n\t\t\t\t\t\t\t\t   ((args.edgeShape) ? cs !== args.edgeShape : true)) {\n\t\t\t\t\t\t\t\t\tmax--;\n\t\t\t\t\t\t\t\t\treturn (max > 0) ? true : false;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} \n\t\t\t\n\t\t\tif (args.targetShape) {\n\t\t\t\tvar target = this._cachedCardTE[args.targetStencil.id()];\n\t\t\t\t\n\t\t\t\tif(!target) {\n\t\t\t\t\tthis._cacheCard(args);\n\t\t\t\t\ttarget = this._cachedCardTE[args.targetStencil.id()];\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tvar max = target[args.edgeStencil.id()];\n\t\t\t\t\n\t\t\t\tif(max == undefined) {\n\t\t\t\t\tthis._cacheCard(args);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tmax = target[args.edgeStencil.id()];\n\t\t\t\t\n\t\t\t\tif(max != -1) {\n\t\t\t\t\tresult = args.targetShape.getIncomingShapes().all(function(cs){\n\t\t\t\t\t\t\t\tif ((cs.getStencil().id() === args.edgeStencil.id()) &&\n\t\t\t\t\t\t\t\t((args.edgeShape) ? cs !== args.edgeShape : true)) {\n\t\t\t\t\t\t\t\t\tmax--;\n\t\t\t\t\t\t\t\t\treturn (max > 0) ? true : false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn result;\n\t},\n\t\n\t/**\n\t * \n\t * @param {Object}\n\t *            args edgeStencil: ORYX.Core.StencilSet.Stencil edgeShape:\n\t *            ORYX.Core.Edge |undefined sourceStencil:\n\t *            ORYX.Core.StencilSet.Stencil | undefined sourceShape:\n\t *            ORYX.Core.Node |undefined targetStencil:\n\t *            ORYX.Core.StencilSet.Stencil | undefined targetShape:\n\t *            ORYX.Core.Node |undefined\n\t * \n\t * At least source or target has to be specified!!!\n\t * \n\t * @return {Boolean} Returns, if the edge can connect source and target.\n\t */\n\t_canConnect: function(args) {\n\t\t// check arguments\n\t\tif(!args ||\n\t\t   (!args.sourceShape && !args.sourceStencil &&\n\t\t    !args.targetShape && !args.targetStencil) ||\n\t\t    !args.edgeShape && !args.edgeStencil) {\n\t\t   \treturn false; \n\t\t}\n\t\t\n\t\t// init arguments\n\t\tif(args.sourceShape) {\n\t\t\targs.sourceStencil = args.sourceShape.getStencil();\n\t\t}\n\t\tif(args.targetShape) {\n\t\t\targs.targetStencil = args.targetShape.getStencil();\n\t\t}\n\t\tif(args.edgeShape) {\n\t\t\targs.edgeStencil = args.edgeShape.getStencil();\n\t\t}\n\n\t\t// 1. check connection rules\n\t\tvar resultCR;\n\t\t\n\t\t// get all connection rules for this edge\n\t\tvar edgeRules = this._getConnectionRulesOfEdgeStencil(args.edgeStencil);\n\n\t\t// check connection rules, if the source can be connected to the target\n\t\t// with the specified edge.\n\t\tif(edgeRules.keys().length === 0) {\n\t\t\tresultCR = false;\n\t\t} else {\n\t\t\tif(args.sourceStencil) {\n\t\t\t\tresultCR = args.sourceStencil.roles().any(function(sourceRole) {\n\t\t\t\t\tvar targetRoles = edgeRules[sourceRole];\n\n\t\t\t\t\tif(!targetRoles) {return false;}\n\t\t\n\t\t\t\t\tif(args.targetStencil) {\n\t\t\t\t\t\treturn (targetRoles.any(function(targetRole) {\n\t\t\t\t\t\t\treturn args.targetStencil.roles().member(targetRole);\n\t\t\t\t\t\t}));\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} else { // !args.sourceStencil -> there is args.targetStencil\n\t\t\t\tresultCR = edgeRules.values().any(function(targetRoles) {\n\t\t\t\t\treturn args.targetStencil.roles().any(function(targetRole) {\n\t\t\t\t\t\treturn targetRoles.member(targetRole);\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn resultCR;\n\t},\n\n\t/** End connection rules' methods */\n\n\n\t/** Begin containment rules' methods */\n\n\tisContainer: function(shape) {\n\t\treturn this._containerStencils.member(shape.getStencil().id());\n\t},\n\n\t/**\n\t * \n\t * @param {Object}\n\t *            args containingStencil: ORYX.Core.StencilSet.Stencil\n\t *            containingShape: ORYX.Core.AbstractShape containedStencil:\n\t *            ORYX.Core.StencilSet.Stencil containedShape: ORYX.Core.Shape\n\t */\n\tcanContain: function(args) {\n\t\tif(!args ||\n\t\t   !args.containingStencil && !args.containingShape ||\n\t\t   !args.containedStencil && !args.containedShape) {\n\t\t   \treturn false;\n\t\t}\n\t\t\n\t\t// init arguments\n\t\tif(args.containedShape) {\n\t\t\targs.containedStencil = args.containedShape.getStencil();\n\t\t}\n\t\t\n\t\tif(args.containingShape) {\n\t\t\targs.containingStencil = args.containingShape.getStencil();\n\t\t}\n\t\t\n\t\t//if(args.containingStencil.type() == 'edge' || args.containedStencil.type() == 'edge')\n\t\t//\treturn false;\n\t\tif(args.containedStencil.type() == 'edge') \n\t\t\treturn false;\n\t\t\n\t\tvar childValues;\n\t\t\n\t\tvar parent = this._cachedContainPC[args.containingStencil.id()];\n\t\t\n\t\tif(!parent)\n\t\t\tchildValues = this._cacheContain(args);\n\t\telse {\n\t\t\tchildValues = parent[args.containedStencil.id()];\n\t\t\t\n\t\t\tif(!childValues)\n\t\t\t\tchildValues = this._cacheContain(args);\n\t\t}\n\n\t\tif(!childValues[0])\n\t\t\treturn false;\n\t\telse if (childValues[1] == -1)\n\t\t\treturn true;\n\t\telse {\n\t\t\tif(args.containingShape) {\n\t\t\t\tvar max = childValues[1];\n\t\t\t\treturn args.containingShape.getChildShapes(false).all(function(as) {\n\t\t\t\t\tif(as.getStencil().id() === args.containedStencil.id()) {\n\t\t\t\t\t\tmax--;\n\t\t\t\t\t\treturn (max > 0) ? true : false;\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t},\n\t\n\t/**\n\t * \n\t * @param {Object}\n\t *            args containingStencil: ORYX.Core.StencilSet.Stencil\n\t *            containingShape: ORYX.Core.AbstractShape containedStencil:\n\t *            ORYX.Core.StencilSet.Stencil containedShape: ORYX.Core.Shape\n\t */\n\t_canContain: function(args) {\n\t\tif(!args ||\n\t\t   !args.containingStencil && !args.containingShape ||\n\t\t   !args.containedStencil && !args.containedShape) {\n\t\t   \treturn false;\n\t\t}\n\t\t\n\t\t// init arguments\n\t\tif(args.containedShape) {\n\t\t\targs.containedStencil = args.containedShape.getStencil();\n\t\t}\n\t\t\n\t\tif(args.containingShape) {\n\t\t\targs.containingStencil = args.containingShape.getStencil();\n\t\t}\n\t\t\n//\t\tif(args.containingShape) {\n//\t\t\tif(args.containingShape instanceof ORYX.Core.Edge) {\n//\t\t\t\t// edges cannot contain other shapes\n//\t\t\t\treturn false;\n//\t\t\t}\n//\t\t}\n\n\t\t\n\t\tvar result;\n\t\t\n\t\t// check containment rules\n\t\tresult = args.containingStencil.roles().any((function(role) {\n\t\t\tvar roles = this._containmentRules[role];\n\t\t\tif(roles) {\n\t\t\t\treturn roles.any(function(role) {\n\t\t\t\t\treturn args.containedStencil.roles().member(role);\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}).bind(this));\n\t\t\n\t\treturn result;\n\t},\n\t\n\t/** End containment rules' methods */\n\t\n\t\n\t/** Begin morphing rules' methods */\n\t\n\t/**\n\t * \n\t * @param {Object}\n\t *           args \n\t *            stencil: ORYX.Core.StencilSet.Stencil | undefined \n\t *            shape: ORYX.Core.Shape | undefined\n\t * \n\t * At least stencil or shape has to be specified\n\t * \n\t * @return {Array} Array of stencils that the passed stencil/shape can be\n\t *         transformed to (including the current stencil itself)\n\t */\n\tmorphStencils: function(args) {\n\t\t// check arguments\n\t\tif(!args.stencil && !args.shape) {\n\t\t\treturn [];\n\t\t}\n\t\t\n\t\t// init arguments\n\t\tif(args.shape) {\n\t\t\targs.stencil = args.shape.getStencil();\n\t\t}\n\t\t\n\t\tvar _morphStencils = [];\n\t\targs.stencil.roles().each(function(role) {\n\t\t\tthis._cacheMorph(role).each(function(stencil) {\n\t\t\t\t_morphStencils.push(stencil);\n\t\t\t})\n\t\t}.bind(this));\n\n\n\t\tvar baseMorphs = this.baseMorphs();\n\t\t// BaseMorphs should be in the front of the array\n\t\t_morphStencils = _morphStencils.uniq().sort(function(a,b){ return baseMorphs.include(a)&&!baseMorphs.include(b) ? -1 : (baseMorphs.include(b)&&!baseMorphs.include(a) ? 1 : 0)})\n\t\treturn _morphStencils;\n\t},\n\t\n\t/**\n\t * @return {Array} An array of all base morph stencils\n\t */\n\tbaseMorphs: function() {\n\t\tvar _baseMorphs = [];\n\t\tthis._morphingRules.each(function(pair) {\n\t\t\tpair.value.each(function(baseMorph) {\n\t\t\t\t_baseMorphs.push(baseMorph);\n\t\t\t});\n\t\t});\n\t\treturn _baseMorphs;\n\t},\n\t\n\t/**\n\t * Returns true if there are morphing rules defines\n\t * @return {boolean} \n\t */\n\tcontainsMorphingRules: function(){\n\t\treturn this._stencilSets.any(function(ss){ return !!ss.jsonRules().morphingRules});\n\t},\n\t\n\t/**\n\t * \n\t * @param {Object}\n\t *            args \n\t *            sourceStencil:\n\t *            ORYX.Core.StencilSet.Stencil | undefined \n\t *            sourceShape:\n\t *            ORYX.Core.Node |undefined \n\t *            targetStencil:\n\t *            ORYX.Core.StencilSet.Stencil | undefined \n\t *            targetShape:\n\t *            ORYX.Core.Node |undefined\n\t * \n\t * \n\t * @return {Stencil} Returns, the stencil for the connecting edge \n\t * or null if connection is not possible\n\t */\n\tconnectMorph: function(args) {\t\n\t\t// check arguments\n\t\tif(!args ||\n\t\t   (!args.sourceShape && !args.sourceStencil &&\n\t\t    !args.targetShape && !args.targetStencil)) {\n\t\t   \treturn false; \n\t\t}\n\t\t\n\t\t// init arguments\n\t\tif(args.sourceShape) {\n\t\t\targs.sourceStencil = args.sourceShape.getStencil();\n\t\t}\n\t\tif(args.targetShape) {\n\t\t\targs.targetStencil = args.targetShape.getStencil();\n\t\t}\n\t\t\n\t\tvar incoming = this.incomingEdgeStencils(args);\n\t\tvar outgoing = this.outgoingEdgeStencils(args);\n\t\t\n\t\tvar edgeStencils = incoming.select(function(e) { return outgoing.member(e); }); // intersection of sets\n\t\tvar baseEdgeStencils = this.baseMorphs().select(function(e) { return edgeStencils.member(e); }); // again: intersection of sets\n\t\t\n\t\tif(baseEdgeStencils.size()>0)\n\t\t\treturn baseEdgeStencils[0]; // return any of the possible base morphs\n\t\telse if(edgeStencils.size()>0)\n\t\t\treturn edgeStencils[0];\t// return any of the possible stencils\n\t\t\n\t\treturn null; //connection not possible\n\t},\n\t\n\t/**\n\t * Return true if the stencil should be located in the shape menu\n\t * @param {ORYX.Core.StencilSet.Stencil} morph\n\t * @return {Boolean} Returns true if the morphs in the morph group of the\n\t * specified morph shall be displayed in the shape menu\n\t */\n\tshowInShapeMenu: function(stencil) {\n\t\treturn \tthis._stencilSets.any(function(ss){\n\t\t\t\t    return ss.jsonRules().morphingRules\n\t\t\t\t\t\t\t.any(function(r){\n\t\t\t\t\t\t\t\treturn \tstencil.roles().include(ss.namespace() + r.role) \n\t\t\t\t\t\t\t\t\t\t&& r.showInShapeMenu !== false;\n\t\t\t\t\t\t\t})\n\t\t\t\t});\n\t},\n\t\n\tpreserveBounds: function(stencil) {\n\t\treturn this._stencilSets.any(function(ss) {\n\t\t\treturn ss.jsonRules().morphingRules.any(function(r) {\n\t\t\t\t\n\t\t\t\t\n\t\t\t\treturn stencil.roles().include(ss.namespace() + r.role) \n\t\t\t\t\t&& r.preserveBounds;\n\t\t\t})\n\t\t})\n\t},\n\t\n\t/** End morphing rules' methods */\n\n\n\t/** Begin layouting rules' methods */\n\t\n\t/**\n\t * Returns a set on \"in\" and \"out\" layouting rules for a given shape\n\t * @param {Object} shape\n\t * @param {Object} edgeShape (Optional)\n\t * @return {Object} \"in\" and \"out\" with a default value of {\"t\":1, \"r\":1, \"b\":1, \"r\":1} if not specified in the json\n\t */\n\tgetLayoutingRules : function(shape, edgeShape){\n\t\t\n\t\tif (!shape||!(shape instanceof ORYX.Core.Shape)){ return }\n\t\t\n\t\tvar layout = {\"in\":{},\"out\":{}};\n\t\t\n\t\tvar parseValues = function(o, v){\n\t\t\tif (o && o[v]){\n\t\t\t\t[\"t\",\"r\",\"b\",\"l\"].each(function(d){\n\t\t\t\t\tlayout[v][d]=Math.max(o[v][d],layout[v][d]||0);\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (o && o[v+\"s\"] instanceof Array){\n\t\t\t\t[\"t\",\"r\",\"b\",\"l\"].each(function(d){\n\t\t\t\t\tvar defaultRule = o[v+\"s\"].find(function(e){ return !e.edgeRole });\n\t\t\t\t\tvar edgeRule;\n\t\t\t\t\tif (edgeShape instanceof ORYX.Core.Edge) {\n\t\t\t\t\t\tedgeRule = o[v + \"s\"].find(function(e){return this._hasRole(edgeShape, e.edgeRole) }.bind(this));\n\t\t\t\t\t}\n\t\t\t\t\tlayout[v][d]=Math.max(edgeRule?edgeRule[d]:defaultRule[d],layout[v][d]||0);\n\t\t\t\t}.bind(this));\n\t\t\t}\n\t\t}.bind(this)\n\t\t\n\t\t// For each role\n\t\tshape.getStencil().roles().each(function(role) {\n\t\t\t// check if there are layout information\n\t\t\tif (this._layoutRules[role]){\n\t\t\t\t// if so, parse those information to the 'layout' variable\n\t\t\t\tparseValues(this._layoutRules[role], \"in\");\n\t\t\t\tparseValues(this._layoutRules[role], \"out\");\n\t\t\t}\n\t\t}.bind(this));\n\t\t\n\t\t// Make sure, that every attribute has an value,\n\t\t// otherwise set 1\n\t\t[\"in\",\"out\"].each(function(v){\n\t\t\t[\"t\",\"r\",\"b\",\"l\"].each(function(d){\n\t\t\t\t\tlayout[v][d]=layout[v][d]!==undefined?layout[v][d]:1;\n\t\t\t\t});\n\t\t})\n\t\t\n\t\treturn layout;\n\t},\n\t\n\t/** End layouting rules' methods */\n\t\n\t/** Helper methods */\n\n\t/**\n\t * Checks wether a shape contains the given role or the role is equal the stencil id \n\t * @param {ORYX.Core.Shape} shape\n\t * @param {String} role\n\t */\n\t_hasRole: function(shape, role){\n\t\tif (!(shape instanceof ORYX.Core.Shape)||!role){ return }\n\t\tvar isRole = shape.getStencil().roles().any(function(r){ return r == role});\n\t\t\n\t\treturn isRole || shape.getStencil().id() == (shape.getStencil().namespace()+role);\n\t},\n\n\t/**\n\t * \n\t * @param {String}\n\t *            role\n\t * \n\t * @return {Array} Returns an array of stencils that can act as role.\n\t */\n\t_stencilsWithRole: function(role) {\n\t\treturn this._stencils.findAll(function(stencil) {\n\t\t\treturn (stencil.roles().member(role)) ? true : false;\n\t\t});\n\t},\n\t\n\t/**\n\t * \n\t * @param {String}\n\t *            role\n\t * \n\t * @return {Array} Returns an array of stencils that can act as role and\n\t *         have the type 'edge'.\n\t */\n\t_edgesWithRole: function(role) {\n\t\treturn this._stencils.findAll(function(stencil) {\n\t\t\treturn (stencil.roles().member(role) && stencil.type() === \"edge\") ? true : false;\n\t\t});\n\t},\n\t\n\t/**\n\t * \n\t * @param {String}\n\t *            role\n\t * \n\t * @return {Array} Returns an array of stencils that can act as role and\n\t *         have the type 'node'.\n\t */\n\t_nodesWithRole: function(role) {\n\t\treturn this._stencils.findAll(function(stencil) {\n\t\t\treturn (stencil.roles().member(role) && stencil.type() === \"node\") ? true : false;\n\t\t});\n\t},\n\n\t/**\n\t * \n\t * @param {ORYX.Core.StencilSet.Stencil}\n\t *            parent\n\t * @param {ORYX.Core.StencilSet.Stencil}\n\t *            child\n\t * \n\t * @returns {Boolean} Returns the maximum occurrence of shapes of the\n\t *          stencil's type inside the parent.\n\t */\n\t_getMaximumOccurrence: function(parent, child) {\n\t\tvar max;\n\t\tchild.roles().each((function(role) {\n\t\t\tvar cardRule = this._cardinalityRules[role];\n\t\t\tif(cardRule && cardRule.maximumOccurrence) {\n\t\t\t\tif(max) {\n\t\t\t\t\tmax = Math.min(max, cardRule.maximumOccurrence);\n\t\t\t\t} else {\n\t\t\t\t\tmax = cardRule.maximumOccurrence;\n\t\t\t\t}\n\t\t\t}\n\t\t}).bind(this));\n\n\t\treturn max;\n\t},\n\n\n\t/**\n\t * \n\t * @param {Object}\n\t *            args sourceStencil: ORYX.Core.Node edgeStencil:\n\t *            ORYX.Core.StencilSet.Stencil\n\t * \n\t * @return {Boolean} Returns, the maximum number of outgoing edges of the\n\t *         type specified by edgeStencil of the sourceShape.\n\t */\n\t_getMaximumNumberOfOutgoingEdge: function(args) {\n\t\tif(!args ||\n\t\t   !args.sourceStencil ||\n\t\t   !args.edgeStencil) {\n\t\t   \treturn false;\n\t\t}\n\t\t\n\t\tvar max;\n\t\targs.sourceStencil.roles().each((function(role) {\n\t\t\tvar cardRule = this._cardinalityRules[role];\n\n\t\t\tif(cardRule && cardRule.outgoingEdges) {\n\t\t\t\targs.edgeStencil.roles().each(function(edgeRole) {\n\t\t\t\t\tvar oe = cardRule.outgoingEdges[edgeRole];\n\n\t\t\t\t\tif(oe && oe.maximum) {\n\t\t\t\t\t\tif(max) {\n\t\t\t\t\t\t\tmax = Math.min(max, oe.maximum);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tmax = oe.maximum;\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}).bind(this));\n\n\t\treturn max;\n\t},\n\t\n\t/**\n\t * \n\t * @param {Object}\n\t *            args targetStencil: ORYX.Core.StencilSet.Stencil edgeStencil:\n\t *            ORYX.Core.StencilSet.Stencil\n\t * \n\t * @return {Boolean} Returns the maximum number of incoming edges of the\n\t *         type specified by edgeStencil of the targetShape.\n\t */\n\t_getMaximumNumberOfIncomingEdge: function(args) {\n\t\tif(!args ||\n\t\t   !args.targetStencil ||\n\t\t   !args.edgeStencil) {\n\t\t   \treturn false;\n\t\t}\n\t\t\n\t\tvar max;\n\t\targs.targetStencil.roles().each((function(role) {\n\t\t\tvar cardRule = this._cardinalityRules[role];\n\t\t\tif(cardRule && cardRule.incomingEdges) {\n\t\t\t\targs.edgeStencil.roles().each(function(edgeRole) {\n\t\t\t\t\tvar ie = cardRule.incomingEdges[edgeRole];\n\t\t\t\t\tif(ie && ie.maximum) {\n\t\t\t\t\t\tif(max) {\n\t\t\t\t\t\t\tmax = Math.min(max, ie.maximum);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tmax = ie.maximum;\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}).bind(this));\n\n\t\treturn max;\n\t},\n\t\n\t/**\n\t * \n\t * @param {ORYX.Core.StencilSet.Stencil}\n\t *            edgeStencil\n\t * \n\t * @return {Hash} Returns a hash map of all connection rules for\n\t *         edgeStencil.\n\t */\n\t_getConnectionRulesOfEdgeStencil: function(edgeStencil) {\n\t\tvar edgeRules = new Hash();\n\t\tedgeStencil.roles().each((function(role) {\n\t\t\tif(this._connectionRules[role]) {\n\t\t\t\tthis._connectionRules[role].each(function(cr) {\n\t\t\t\t\tif(edgeRules[cr.key]) {\n\t\t\t\t\t\tedgeRules[cr.key] = edgeRules[cr.key].concat(cr.value);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tedgeRules[cr.key] = cr.value;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}).bind(this));\n\t\t\n\t\treturn edgeRules;\n\t},\n\t\n\t_isRoleOfOtherNamespace: function(role) {\n\t\treturn (role.indexOf(\"#\") > 0);\n\t},\n\n\ttoString: function() { return \"Rules\"; }\n}\nORYX.Core.StencilSet.Rules = Clazz.extend(ORYX.Core.StencilSet.Rules);\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespace\n */\nif (!ORYX) {\n    var ORYX = {};\n}\nif (!ORYX.Core) {\n    ORYX.Core = {};\n}\nif (!ORYX.Core.StencilSet) {\n    ORYX.Core.StencilSet = {};\n}\n\n/**\n * This class represents a stencil set. It offers methods for accessing\n *  the attributes of the stencil set description JSON file and the stencil set's\n *  stencils.\n */\nORYX.Core.StencilSet.StencilSet = Clazz.extend({\n\n    /**\n     * Constructor\n     * @param source {URL} A reference to the stencil set specification.\n     *\n     */\n    construct: function(source, modelMetaData, editorId){\n        arguments.callee.$.construct.apply(this, arguments);\n        \n        if (!source) {\n            throw \"ORYX.Core.StencilSet.StencilSet(construct): Parameter 'source' is not defined.\";\n        }\n        \n        if (source.endsWith(\"/\")) {\n            source = source.substr(0, source.length - 1);\n        }\n\t\t\n\t\tthis._extensions = new Hash();\n        \n        this._source = source;\n        this._baseUrl = source.substring(0, source.lastIndexOf(\"/\") + 1);\n        \n        this._jsonObject = {};\n        \n        this._stencils = new Hash();\n\t\tthis._availableStencils = new Hash();\n        \n\t\tif(ORYX.CONFIG.BACKEND_SWITCH) {\n\t\t\tthis._baseUrl = \"editor/stencilsets/bpmn2.0/\";\n\t\t\tthis._source = \"stencilsets/bpmn2.0/bpmn2.0.json\";\n\t\t\t\n\t\t\tnew Ajax.Request(ACTIVITI.CONFIG.contextRoot + '/editor/stencilset?version=' + Date.now() +\"&access_token=\"+localStorage.getItem(\"token\") , {\n\t            asynchronous: false,\n\t            method: 'get',\n\t            onSuccess: this._init.bind(this),\n\t            onFailure: this._cancelInit.bind(this)\n\t        });\n\t\t\t\n\t\t} else {\n\t\t\tnew Ajax.Request(source, {\n\t            asynchronous: false,\n\t            method: 'get',\n\t            onSuccess: this._init.bind(this),\n\t            onFailure: this._cancelInit.bind(this)\n\t        });\n\t\t}\n        \n        if (this.errornous) \n            throw \"Loading stencil set \" + source + \" failed.\";\n    },\n    \n    /**\n     * Finds a root stencil in this stencil set. There may be many of these. If\n     * there are, the first one found will be used. In Firefox, this is the\n     * topmost definition in the stencil set description file.\n     */\n    findRootStencilName: function(){\n    \n        // find any stencil that may be root.\n        var rootStencil = this._stencils.values().find(function(stencil){\n            return stencil._jsonStencil.mayBeRoot\n        });\n        \n\t\t// if there is none, just guess the first.\n\t\tif (!rootStencil) {\n\t\t\tORYX.Log.warn(\"Did not find any stencil that may be root. Taking a guess.\");\n\t\t\trootStencil = this._stencils.values()[0];\n\t\t}\n\n        // return its id.\n        return rootStencil.id();\n    },\n    \n    /**\n     * @param {ORYX.Core.StencilSet.StencilSet} stencilSet\n     * @return {Boolean} True, if stencil set has the same namespace.\n     */\n    equals: function(stencilSet){\n        return (this.namespace() === stencilSet.namespace());\n    },\n    \n\t/**\n\t * \n\t * @param {Oryx.Core.StencilSet.Stencil} rootStencil If rootStencil is defined, it only returns stencils\n\t * \t\t\tthat could be (in)direct child of that stencil.\n\t */\n    stencils: function(rootStencil, rules, sortByGroup){\n\t\tif(rootStencil && rules) {\n\t\t\tvar stencils = this._availableStencils.values();\n\t\t\tvar containers = [rootStencil];\n\t\t\tvar checkedContainers = [];\n\t\t\t\n\t\t\tvar result = [];\n\t\t\t\n\t\t\twhile (containers.size() > 0) {\n\t\t\t\tvar container = containers.pop();\n\t\t\t\tcheckedContainers.push(container);\n\t\t\t\tvar children = stencils.findAll(function(stencil){\n\t\t\t\t\tvar args = {\n\t\t\t\t\t\tcontainingStencil: container,\n\t\t\t\t\t\tcontainedStencil: stencil\n\t\t\t\t\t};\n\t\t\t\t\treturn rules.canContain(args);\n\t\t\t\t});\n\t\t\t\tfor(var i = 0; i < children.size(); i++) {\n\t\t\t\t\tif (!checkedContainers.member(children[i])) {\n\t\t\t\t\t\tcontainers.push(children[i]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tresult = result.concat(children).uniq();\n\t\t\t}\n\t\t\t\n\t\t\t// Sort the result to the origin order\n\t\t\tresult = result.sortBy(function(stencil) {\n\t\t\t\treturn stencils.indexOf(stencil);\n\t\t\t});\n\t\t\t\n\t\t\t\n\t\t\tif(sortByGroup) {\n\t\t\t\tresult = result.sortBy(function(stencil) {\n\t\t\t\t\treturn stencil.groups().first();\n\t\t\t\t});\n\t\t\t}\n\t\t\t\n\t\t\tvar edges = stencils.findAll(function(stencil) {\n\t\t\t\treturn stencil.type() == \"edge\";\n\t\t\t});\n\t\t\tresult = result.concat(edges);\n\t\t\t\n\t\t\treturn result;\n\t\t\t\n\t\t} else {\n        \tif(sortByGroup) {\n\t\t\t\treturn this._availableStencils.values().sortBy(function(stencil) {\n\t\t\t\t\treturn stencil.groups().first();\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\treturn this._availableStencils.values();\n\t\t\t}\n\t\t}\n    },\n    \n    nodes: function(){\n        return this._availableStencils.values().findAll(function(stencil){\n            return (stencil.type() === 'node')\n        });\n    },\n    \n    edges: function(){\n        return this._availableStencils.values().findAll(function(stencil){\n            return (stencil.type() === 'edge')\n        });\n    },\n    \n    stencil: function(id){\n        return this._stencils[id];\n    },\n    \n    title: function(){\n        return ORYX.Core.StencilSet.getTranslation(this._jsonObject, \"title\");\n    },\n    \n    description: function(){\n        return ORYX.Core.StencilSet.getTranslation(this._jsonObject, \"description\");\n    },\n    \n    namespace: function(){\n        return this._jsonObject ? this._jsonObject.namespace : null;\n    },\n    \n    jsonRules: function(){\n        return this._jsonObject ? this._jsonObject.rules : null;\n    },\n    \n    source: function(){\n        return this._source;\n    },\n\t\n\textensions: function() {\n\t\treturn this._extensions;\n\t},\n\t\n\taddExtension: function(url) {\n\t\t\n\t\tnew Ajax.Request(url, {\n            method: 'GET',\n            asynchronous: false,\n\t\t\tonSuccess: (function(transport) {\n\t\t\t\tthis.addExtensionDirectly(transport.responseText);\n\t\t\t}).bind(this),\n\t\t\tonFailure: (function(transport) {\n\t\t\t\tORYX.Log.debug(\"Loading stencil set extension file failed. The request returned an error.\" + transport);\n\t\t\t}).bind(this),\n\t\t\tonException: (function(transport) {\n\t\t\t\tORYX.Log.debug(\"Loading stencil set extension file failed. The request returned an error.\" + transport);\n\t\t\t}).bind(this)\n\t\t\n\t\t});\n\t},\n\t\n\taddExtensionDirectly: function(str){\n\n\t\ttry {\n\t\t\teval(\"var jsonExtension = \" + str);\n\n\t\t\tif(!(jsonExtension[\"extends\"].endsWith(\"#\")))\n\t\t\t\t\tjsonExtension[\"extends\"] += \"#\";\n\t\t\t\t\t\n\t\t\tif(jsonExtension[\"extends\"] == this.namespace()) {\n\t\t\t\tthis._extensions[jsonExtension.namespace] = jsonExtension;\n\t\t\t\t\n\t\t\t\tvar defaultPosition = this._stencils.keys().size();\n\t\t\t\t//load new stencils\n\t\t\t\tif(jsonExtension.stencils) {\n\t\t\t\t\t$A(jsonExtension.stencils).each(function(stencil) {\n\t\t\t\t\t\tdefaultPosition++;\n\t\t\t\t\t\tvar oStencil = new ORYX.Core.StencilSet.Stencil(stencil, this.namespace(), this._baseUrl, this, undefined, defaultPosition);            \n\t\t\t\t\t\tthis._stencils[oStencil.id()] = oStencil;\n\t\t\t\t\t\tthis._availableStencils[oStencil.id()] = oStencil;\n\t\t\t\t\t}.bind(this));\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t//load additional properties\n\t\t\t\tif (jsonExtension.properties) {\n\t\t\t\t\tvar stencils = this._stencils.values();\n\t\t\t\t\t\n\t\t\t\t\tstencils.each(function(stencil){\n\t\t\t\t\t\tvar roles = stencil.roles();\n\t\t\t\t\t\t\n\t\t\t\t\t\tjsonExtension.properties.each(function(prop){\n\t\t\t\t\t\t\tprop.roles.any(function(role){\n\t\t\t\t\t\t\t\trole = jsonExtension[\"extends\"] + role;\n\t\t\t\t\t\t\t\tif (roles.member(role)) {\n\t\t\t\t\t\t\t\t\tprop.properties.each(function(property){\n\t\t\t\t\t\t\t\t\t\tstencil.addProperty(property, jsonExtension.namespace);\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse \n\t\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}.bind(this));\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t//remove stencil properties\n\t\t\t\tif(jsonExtension.removeproperties) {\n\t\t\t\t\tjsonExtension.removeproperties.each(function(remprop) {\n\t\t\t\t\t\tvar stencil = this.stencil(jsonExtension[\"extends\"] + remprop.stencil);\n\t\t\t\t\t\tif(stencil) {\n\t\t\t\t\t\t\tremprop.properties.each(function(propId) {\n\t\t\t\t\t\t\t\tstencil.removeProperty(propId);\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}.bind(this));\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t//remove stencils\n\t\t\t\tif(jsonExtension.removestencils) {\n\t\t\t\t\t$A(jsonExtension.removestencils).each(function(remstencil) {\n\t\t\t\t\t\tdelete this._availableStencils[jsonExtension[\"extends\"] + remstencil];\n\t\t\t\t\t}.bind(this));\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tORYX.Log.debug(\"StencilSet.addExtension: Something went wrong when initialising the stencil set extension. \" + e);\n\t\t}\t\n\t},\n\t\n\tremoveExtension: function(namespace) {\n\t\tvar jsonExtension = this._extensions[namespace];\n\t\tif(jsonExtension) {\n\t\t\t\n\t\t\t//unload extension's stencils\n\t\t\tif(jsonExtension.stencils) {\n\t\t\t\t$A(jsonExtension.stencils).each(function(stencil) {\n\t\t\t\t\tvar oStencil = new ORYX.Core.StencilSet.Stencil(stencil, this.namespace(), this._baseUrl, this);            \n\t\t\t\t\tdelete this._stencils[oStencil.id()]; // maybe not ??\n\t\t\t\t\tdelete this._availableStencils[oStencil.id()];\n\t\t\t\t}.bind(this));\n\t\t\t}\n\t\t\t\n\t\t\t//unload extension's properties\n\t\t\tif (jsonExtension.properties) {\n\t\t\t\tvar stencils = this._stencils.values();\n\t\t\t\t\n\t\t\t\tstencils.each(function(stencil){\n\t\t\t\t\tvar roles = stencil.roles();\n\t\t\t\t\t\n\t\t\t\t\tjsonExtension.properties.each(function(prop){\n\t\t\t\t\t\tprop.roles.any(function(role){\n\t\t\t\t\t\t\trole = jsonExtension[\"extends\"] + role;\n\t\t\t\t\t\t\tif (roles.member(role)) {\n\t\t\t\t\t\t\t\tprop.properties.each(function(property){\n\t\t\t\t\t\t\t\t\tstencil.removeProperty(property.id);\n\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\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse \n\t\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}.bind(this));\n\t\t\t}\n\t\t\t\n\t\t\t//restore removed stencil properties\n\t\t\tif(jsonExtension.removeproperties) {\n\t\t\t\tjsonExtension.removeproperties.each(function(remprop) {\n\t\t\t\t\tvar stencil = this.stencil(jsonExtension[\"extends\"] + remprop.stencil);\n\t\t\t\t\tif(stencil) {\n\t\t\t\t\t\tvar stencilJson = $A(this._jsonObject.stencils).find(function(s) { return s.id == stencil.id() });\n\t\t\t\t\t\tremprop.properties.each(function(propId) {\n\t\t\t\t\t\t\tvar propertyJson = $A(stencilJson.properties).find(function(p) { return p.id == propId });\n\t\t\t\t\t\t\tstencil.addProperty(propertyJson, this.namespace());\n\t\t\t\t\t\t}.bind(this));\n\t\t\t\t\t}\n\t\t\t\t}.bind(this));\n\t\t\t}\n\t\t\t\n\t\t\t//restore removed stencils\n\t\t\tif(jsonExtension.removestencils) {\n\t\t\t\t$A(jsonExtension.removestencils).each(function(remstencil) {\n\t\t\t\t\tvar sId = jsonExtension[\"extends\"] + remstencil;\n\t\t\t\t\tthis._availableStencils[sId] = this._stencils[sId];\n\t\t\t\t}.bind(this));\n\t\t\t}\n\t\t}\n\t\tdelete this._extensions[namespace];\n\t},\n    \n    __handleStencilset: function(response){\n    \n        try {\n            // using eval instead of prototype's parsing,\n            // since there are functions in this JSON.\n            eval(\"this._jsonObject =\" + response.responseText);\n        } \n        catch (e) {\n            throw \"Stenciset corrupt: \" + e;\n        }\n        \n        // assert it was parsed.\n        if (!this._jsonObject) {\n            throw \"Error evaluating stencilset. It may be corrupt.\";\n        }\n        \n        with (this._jsonObject) {\n        \n            // assert there is a namespace.\n            if (!namespace || namespace === \"\") \n                throw \"Namespace definition missing in stencilset.\";\n            \n            if (!(stencils instanceof Array)) \n                throw \"Stencilset corrupt.\";\n            \n            // assert namespace ends with '#'.\n            if (!namespace.endsWith(\"#\")) \n                namespace = namespace + \"#\";\n            \n            // assert title and description are strings.\n            if (!title) \n                title = \"\";\n            if (!description) \n                description = \"\";\n        }\n    },\n    \n    /**\n     * This method is called when the HTTP request to get the requested stencil\n     * set succeeds. The response is supposed to be a JSON representation\n     * according to the stencil set specification.\n     * @param {Object} response The JSON representation according to the\n     * \t\t\tstencil set specification.\n     */\n    _init: function(response){\n    \n        // init and check consistency.\n        this.__handleStencilset(response);\n\t\t\n\t\tvar pps = new Hash();\n\t\t\n\t\t// init property packages\n\t\tif(this._jsonObject.propertyPackages) {\n\t\t\t$A(this._jsonObject.propertyPackages).each((function(pp) {\n\t\t\t\tpps[pp.name] = pp.properties;\n\t\t\t}).bind(this));\n\t\t}\n\t\t\n\t\tvar defaultPosition = 0;\n\t\t\n        // init each stencil\n        $A(this._jsonObject.stencils).each((function(stencil){\n        \tdefaultPosition++;\n        \t\n            // instantiate normally.\n            var oStencil = new ORYX.Core.StencilSet.Stencil(stencil, this.namespace(), this._baseUrl, this, pps, defaultPosition);      \n\t\t\tthis._stencils[oStencil.id()] = oStencil;\n\t\t\tthis._availableStencils[oStencil.id()] = oStencil;\n            \n        }).bind(this));\n    },\n    \n    _cancelInit: function(response){\n        this.errornous = true;\n    },\n    \n    toString: function(){\n        return \"StencilSet \" + this.title() + \" (\" + this.namespace() + \")\";\n    }\n});\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespace\n */\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\nif(!ORYX.Core.StencilSet) {ORYX.Core.StencilSet = {};}\n\n/**\n * Class StencilSets\n * uses Prototpye 1.5.0\n * uses Inheritance\n *\n * Singleton\n */\n//storage for loaded stencil sets by namespace\nORYX.Core.StencilSet._stencilSetsByNamespace = new Hash();\n\n//storage for stencil sets by url\nORYX.Core.StencilSet._stencilSetsByUrl = new Hash();\t\n\n//storage for stencil set namespaces by editor instances\nORYX.Core.StencilSet._StencilSetNSByEditorInstance = new Hash();\n\n//storage for rules by editor instances\nORYX.Core.StencilSet._rulesByEditorInstance = new Hash();\n\n/**\n * \n * @param {String} editorId\n * \n * @return {Hash} Returns a hash map with all stencil sets that are loaded by\n * \t\t\t\t\tthe editor with the editorId.\n */\nORYX.Core.StencilSet.stencilSets = function(editorId) {\n\tvar stencilSetNSs = ORYX.Core.StencilSet._StencilSetNSByEditorInstance[editorId];\n\tvar stencilSets = new Hash();\n\tif(stencilSetNSs) {\n\t\tstencilSetNSs.each(function(stencilSetNS) {\n\t\t\tvar stencilSet = ORYX.Core.StencilSet.stencilSet(stencilSetNS)\n\t\t\tstencilSets[stencilSet.namespace()] = stencilSet;\n\t\t});\n\t}\n\treturn stencilSets;\n};\n\n/**\n * \n * @param {String} namespace\n * \n * @return {ORYX.Core.StencilSet.StencilSet} Returns the stencil set with the specified\n * \t\t\t\t\t\t\t\t\t\tnamespace.\n * \n * The method can handle namespace strings like\n *  http://www.example.org/stencilset\n *  http://www.example.org/stencilset#\n *  http://www.example.org/stencilset#ANode\n */\nORYX.Core.StencilSet.stencilSet = function(namespace) {\n\tORYX.Log.trace(\"Getting stencil set %0\", namespace);\n\tvar splitted = namespace.split(\"#\", 1);\n\tif(splitted.length === 1) {\n\t\tORYX.Log.trace(\"Getting stencil set %0\", splitted[0]);\n\t\treturn ORYX.Core.StencilSet._stencilSetsByNamespace[splitted[0] + \"#\"];\n\t} else {\n\t\treturn undefined;\n\t}\n};\n\n/**\n * \n * @param {String} id\n * \n * @return {ORYX.Core.StencilSet.Stencil} Returns the stencil specified by the id.\n * \n * The id must be unique and contains the namespace of the stencil's stencil set.\n * e.g. http://www.example.org/stencilset#ANode\n */\nORYX.Core.StencilSet.stencil = function(id) {\n\tORYX.Log.trace(\"Getting stencil for %0\", id);\n\tvar ss = ORYX.Core.StencilSet.stencilSet(id);\n\tif(ss) {\n\t\treturn ss.stencil(id);\n\t} else {\n\n\t\tORYX.Log.trace(\"Cannot fild stencil for %0\", id);\n\t\treturn undefined;\n\t}\n};\n\n/**\n * \n * @param {String} editorId\n * \n * @return {ORYX.Core.StencilSet.Rules} Returns the rules object for the editor\n * \t\t\t\t\t\t\t\t\tspecified by its editor id.\n */\nORYX.Core.StencilSet.rules = function(editorId) {\n\tif(!ORYX.Core.StencilSet._rulesByEditorInstance[editorId]) {\n\t\tORYX.Core.StencilSet._rulesByEditorInstance[editorId] = new ORYX.Core.StencilSet.Rules();\n\t}\n\treturn ORYX.Core.StencilSet._rulesByEditorInstance[editorId];\n};\n\n/**\n * \n * @param {String} url\n * @param {String} editorId\n * \n * Loads a stencil set from url, if it is not already loaded.\n * It also stores which editor instance loads the stencil set and \n * initializes the Rules object for the editor instance.\n */\nORYX.Core.StencilSet.loadStencilSet = function(url, modelMetaData, editorId) {\n\t\n\t// Alfresco: disable cache, because stencil sets are now flexible\n\t\n\t//var stencilSet = ORYX.Core.StencilSet._stencilSetsByUrl[url];\n\n\t//if(!stencilSet) {\n\t\t//load stencil set\n\t\tstencilSet = new ORYX.Core.StencilSet.StencilSet(url, modelMetaData, editorId);\n\t\t\n\t\t//store stencil set\n\t\tORYX.Core.StencilSet._stencilSetsByNamespace[stencilSet.namespace()] = stencilSet;\n\t\t\n\t\t//store stencil set by url\n\t\tORYX.Core.StencilSet._stencilSetsByUrl[url] = stencilSet;\n\t//}\n\t\n\tvar namespace = stencilSet.namespace();\n\t\n\t//store which editorInstance loads the stencil set\n\tif(ORYX.Core.StencilSet._StencilSetNSByEditorInstance[editorId]) {\n\t\tORYX.Core.StencilSet._StencilSetNSByEditorInstance[editorId].push(namespace);\n\t} else {\n\t\tORYX.Core.StencilSet._StencilSetNSByEditorInstance[editorId] = [namespace];\n\t}\n\n\t//store the rules for the editor instance\n\tif(ORYX.Core.StencilSet._rulesByEditorInstance[editorId]) {\n\t\tORYX.Core.StencilSet._rulesByEditorInstance[editorId].initializeRules(stencilSet);\n\t} else {\n\t\tvar rules = new ORYX.Core.StencilSet.Rules();\n\t\trules.initializeRules(stencilSet);\n\t\tORYX.Core.StencilSet._rulesByEditorInstance[editorId] = rules;\n\t}\n};\n\n/**\n * Returns the translation of an attribute in jsonObject specified by its name\n * according to navigator.language\n */\nORYX.Core.StencilSet.getTranslation = function(jsonObject, name) {\n\tvar lang = ORYX.I18N.Language.toLowerCase();\n\t\n\tvar result = jsonObject[name + \"_\" + lang];\n\t\n\tif(result)\n\t\treturn result;\n\t\t\n\tresult = jsonObject[name + \"_\" + lang.substr(0, 2)];\n\t\n\tif(result)\n\t\treturn result;\n\t\t\n\treturn jsonObject[name];\n};\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespaces\n */\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\n\n\n/**\n * @classDescription With Bounds you can set and get position and size of UIObjects.\n */\nORYX.Core.Command = Clazz.extend({\n\n\t/**\n\t * Constructor\n\t */\n\tconstruct: function() {\n\n\t},\n\t\n\texecute: function(){\n\t\tthrow \"Command.execute() has to be implemented!\"\n\t},\n\t\n\trollback: function(){\n\t\tthrow \"Command.rollback() has to be implemented!\"\n\t}\n\t\n\t\n });/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespaces\n */\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\n\n\n/**\n * @classDescription With Bounds you can set and get position and size of UIObjects.\n */\nORYX.Core.Bounds = {\n\n\t/**\n\t * Constructor\n\t */\n\tconstruct: function() {\n\t\tthis._changedCallbacks = []; //register a callback with changedCallacks.push(this.method.bind(this));\n\t\tthis.a = {};\n\t\tthis.b = {};\n\t\tthis.set.apply(this, arguments);\n\t\tthis.suspendChange = false;\n\t\tthis.changedWhileSuspend = false;\n\t},\n\t\n\t/**\n\t * Calls all registered callbacks.\n\t */\n\t_changed: function(sizeChanged) {\n\t\tif(!this.suspendChange) {\n\t\t\tthis._changedCallbacks.each(function(callback) {\n\t\t\t\tcallback(this, sizeChanged);\n\t\t\t}.bind(this));\n\t\t\tthis.changedWhileSuspend = false;\n\t\t} else\n\t\t\tthis.changedWhileSuspend = true;\n\t},\n\t\n\t/**\n\t * Registers a callback that is called, if the bounds changes.\n\t * @param callback {Function} The callback function.\n\t */\n\tregisterCallback: function(callback) {\n\t\tif(!this._changedCallbacks.member(callback)) {\n\t\t\tthis._changedCallbacks.push(callback);\t\n\t\t}\n\t},\n\t\n\t/**\n\t * Unregisters a callback.\n\t * @param callback {Function} The callback function.\n\t */\n\tunregisterCallback: function(callback) {\n\t\t\tthis._changedCallbacks = this._changedCallbacks.without(callback);\n\t},\n\t\n\t/**\n\t * Sets position and size of the shape dependent of four coordinates\n\t * (set(ax, ay, bx, by);), two points (set({x: ax, y: ay}, {x: bx, y: by});)\n\t * or one bound (set({a: {x: ax, y: ay}, b: {x: bx, y: by}});).\n\t */\n\tset: function() {\n\t\t\n\t\tvar changed = false;\n\t\t\n\t\tswitch (arguments.length) {\n\t\t\n\t\t\tcase 1:\n\t\t\t\tif(this.a.x !== arguments[0].a.x) {\n\t\t\t\t\tchanged = true;\n\t\t\t\t\tthis.a.x = arguments[0].a.x;\n\t\t\t\t}\n\t\t\t\tif(this.a.y !== arguments[0].a.y) {\n\t\t\t\t\tchanged = true;\n\t\t\t\t\tthis.a.y = arguments[0].a.y;\n\t\t\t\t}\n\t\t\t\tif(this.b.x !== arguments[0].b.x) {\n\t\t\t\t\tchanged = true;\n\t\t\t\t\tthis.b.x = arguments[0].b.x;\n\t\t\t\t}\n\t\t\t\tif(this.b.y !== arguments[0].b.y) {\n\t\t\t\t\tchanged = true;\n\t\t\t\t\tthis.b.y = arguments[0].b.y;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase 2:\n\t\t\t\tvar ax = Math.min(arguments[0].x, arguments[1].x);\n\t\t\t\tvar ay = Math.min(arguments[0].y, arguments[1].y);\n\t\t\t\tvar bx = Math.max(arguments[0].x, arguments[1].x);\n\t\t\t\tvar by = Math.max(arguments[0].y, arguments[1].y);\n\t\t\t\tif(this.a.x !== ax) {\n\t\t\t\t\tchanged = true;\n\t\t\t\t\tthis.a.x = ax;\n\t\t\t\t}\n\t\t\t\tif(this.a.y !== ay) {\n\t\t\t\t\tchanged = true;\n\t\t\t\t\tthis.a.y = ay;\n\t\t\t\t}\n\t\t\t\tif(this.b.x !== bx) {\n\t\t\t\t\tchanged = true;\n\t\t\t\t\tthis.b.x = bx;\n\t\t\t\t}\n\t\t\t\tif(this.b.y !== by) {\n\t\t\t\t\tchanged = true;\n\t\t\t\t\tthis.b.y = by;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase 4:\n\t\t\t\tvar ax = Math.min(arguments[0], arguments[2]);\n\t\t\t\tvar ay = Math.min(arguments[1], arguments[3]);\n\t\t\t\tvar bx = Math.max(arguments[0], arguments[2]);\n\t\t\t\tvar by = Math.max(arguments[1], arguments[3]);\n\t\t\t\tif(this.a.x !== ax) {\n\t\t\t\t\tchanged = true;\n\t\t\t\t\tthis.a.x = ax;\n\t\t\t\t}\n\t\t\t\tif(this.a.y !== ay) {\n\t\t\t\t\tchanged = true;\n\t\t\t\t\tthis.a.y = ay;\n\t\t\t\t}\n\t\t\t\tif(this.b.x !== bx) {\n\t\t\t\t\tchanged = true;\n\t\t\t\t\tthis.b.x = bx;\n\t\t\t\t}\n\t\t\t\tif(this.b.y !== by) {\n\t\t\t\t\tchanged = true;\n\t\t\t\t\tthis.b.y = by;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t\t\n\t\tif(changed) {\n\t\t\tthis._changed(true);\n\t\t}\n\t},\n\t\n\t/**\n\t * Moves the bounds so that the point p will be the new upper left corner.\n\t * @param {Point} p\n\t * or\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\tmoveTo: function() {\n\t\t\n\t\tvar currentPosition = this.upperLeft();\n\t\tswitch (arguments.length) {\n\t\t\tcase 1:\n\t\t\t\tthis.moveBy({\n\t\t\t\t\tx: arguments[0].x - currentPosition.x,\n\t\t\t\t\ty: arguments[0].y - currentPosition.y\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\tthis.moveBy({\n\t\t\t\t\tx: arguments[0] - currentPosition.x,\n\t\t\t\t\ty: arguments[1] - currentPosition.y\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\t//TODO error\n\t\t}\n\t\t\n\t},\n\t\n\t/**\n\t * Moves the bounds relatively by p.\n\t * @param {Point} p\n\t * or\n\t * @param {Number} x\n\t * @param {Number} y\n\t * \n\t */\n\tmoveBy: function() {\n\t\tvar changed = false;\n\t\t\n\t\tswitch (arguments.length) {\n\t\t\tcase 1:\n\t\t\t\tvar p = arguments[0];\n\t\t\t\tif(p.x !== 0 || p.y !== 0) {\n\t\t\t\t\tchanged = true;\n\t\t\t\t\tthis.a.x += p.x;\n\t\t\t\t\tthis.b.x += p.x;\n\t\t\t\t\tthis.a.y += p.y;\n\t\t\t\t\tthis.b.y += p.y;\n\t\t\t\t}\n\t\t\t\tbreak;\t\n\t\t\tcase 2:\n\t\t\t\tvar x = arguments[0];\n\t\t\t\tvar y = arguments[1];\n\t\t\t\tif(x !== 0 || y !== 0) {\n\t\t\t\t\tchanged = true;\n\t\t\t\t\tthis.a.x += x;\n\t\t\t\t\tthis.b.x += x;\n\t\t\t\t\tthis.a.y += y;\n\t\t\t\t\tthis.b.y += y;\n\t\t\t\t}\n\t\t\t\tbreak;\t\n\t\t\tdefault:\n\t\t\t\t//TODO error\n\t\t}\n\t\t\n\t\tif(changed) {\n\t\t\tthis._changed();\n\t\t}\n\t},\n\t\n\t/***\n\t * Includes the bounds b into the current bounds.\n\t * @param {Bounds} b\n\t */\n\tinclude: function(b) {\n\t\t\n\t\tif( (this.a.x === undefined) && (this.a.y === undefined) &&\n\t\t\t(this.b.x === undefined) && (this.b.y === undefined)) {\n\t\t\treturn b;\n\t\t};\n\t\t\n\t\tvar cx = Math.min(this.a.x,b.a.x);\n\t\tvar cy = Math.min(this.a.y,b.a.y);\n\t\t\n\t\tvar dx = Math.max(this.b.x,b.b.x);\n\t\tvar dy = Math.max(this.b.y,b.b.y);\n\n\t\t\n\t\tthis.set(cx, cy, dx, dy);\n\t},\n\t\n\t/**\n\t * Relatively extends the bounds by p.\n\t * @param {Point} p\n\t */\n\textend: function(p) {\n\t\t\n\t\tif(p.x !== 0 || p.y !== 0) {\n\t\t\t// this is over cross for the case that a and b have same coordinates.\n\t\t\t//((this.a.x > this.b.x) ? this.a : this.b).x += p.x;\n\t\t\t//((this.b.y > this.a.y) ? this.b : this.a).y += p.y;\n\t\t\tthis.b.x += p.x;\n\t\t\tthis.b.y += p.y;\n\t\t\t\n\t\t\tthis._changed(true);\n\t\t}\n\t},\n\t\n\t/**\n\t * Widens the scope of the bounds by x.\n\t * @param {Number} x\n\t */\n\twiden: function(x) {\n\t\tif (x !== 0) {\n\t\t\tthis.suspendChange = true;\n\t\t\tthis.moveBy({x: -x, y: -x});\n\t\t\tthis.extend({x: 2*x, y: 2*x});\n\t\t\tthis.suspendChange = false;\n\t\t\tif(this.changedWhileSuspend) {\n\t\t\t\tthis._changed(true);\n\t\t\t}\n\t\t}\n\t},\n\t\n\t/**\n\t * Returns the upper left corner's point regardless of the\n\t * bound delimiter points.\n\t */\n\tupperLeft: function() {\n\t\tvar result = {};\n\t\tresult.x = this.a.x;\n\t\tresult.y = this.a.y;\n\t\treturn result;\n\t},\n\t\n\t/**\n\t * Returns the lower Right left corner's point regardless of the\n\t * bound delimiter points.\n\t */\n\tlowerRight: function() {\n\t\tvar result = {};\n\t\tresult.x = this.b.x;\n\t\tresult.y = this.b.y;\n\t\treturn result;\n\t},\n\t\n\t/**\n\t * @return {Number} Width of bounds.\n\t */\n\twidth: function() {\n\t\treturn this.b.x - this.a.x;\n\t},\n\t\n\t/**\n\t * @return {Number} Height of bounds.\n\t */\n\theight: function() {\n\t\treturn this.b.y - this.a.y;\n\t},\n\t\n\t/**\n\t * @return {Point} The center point of this bounds.\n\t */\n\tcenter: function() {\n\t\tvar center = {};\n\t\tcenter.x =(this.a.x + this.b.x)/2.0; \n\t\tcenter.y =(this.a.y + this.b.y)/2.0;\n\t\treturn center;\n\t},\n\n\t\n\t/**\n\t * @return {Point} The center point of this bounds relative to upperLeft.\n\t */\n\tmidPoint: function() {\n\t\t\n\t\tvar midpoint = {};\n\t\tmidpoint.x = (this.b.x - this.a.x)/2.0; \n\t\tmidpoint.y = (this.b.y - this.a.y)/2.0;\n\t\treturn midpoint;\n\t},\n\t\t\n\t/**\n\t * Moves the center point of this bounds to the new position.\n\t * @param p {Point} \n\t * or\n\t * @param x {Number}\n\t * @param y {Number}\n\t */\n\tcenterMoveTo: function() {\n\t\tvar currentPosition = this.center();\n\t\t\n\t\tswitch (arguments.length) {\n\t\t\t\n\t\t\tcase 1:\n\t\t\t\tthis.moveBy(arguments[0].x - currentPosition.x,\n\t\t\t\t\t\t\targuments[0].y - currentPosition.y);\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase 2:\n\t\t\t\tthis.moveBy(arguments[0] - currentPosition.x,\n\t\t\t\t\t\t\targuments[1] - currentPosition.y);\n\t\t\t\tbreak;\n\t\t}\n\t},\n\t\n\tisIncluded: function(point, offset) {\n\t\t\n\t\tvar pointX, pointY, offset;\n\n\t\t// Get the the two Points\t\n\t\tswitch(arguments.length) {\n\t\t\tcase 1:\n\t\t\t\tpointX = arguments[0].x;\n\t\t\t\tpointY = arguments[0].y;\n\t\t\t\toffset = 0;\n\t\t\t\t\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\tif(arguments[0].x && arguments[0].y) {\n\t\t\t\t\tpointX = arguments[0].x;\n\t\t\t\t\tpointY = arguments[0].y;\n\t\t\t\t\toffset = Math.abs(arguments[1]);\n\t\t\t\t} else {\n\t\t\t\t\tpointX = arguments[0];\n\t\t\t\t\tpointY = arguments[1];\n\t\t\t\t\toffset = 0;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 3:\n\t\t\t\tpointX = arguments[0];\n\t\t\t\tpointY = arguments[1];\n\t\t\t\toffset = Math.abs(arguments[2]);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthrow \"isIncluded needs one, two or three arguments\";\n\t\t}\n\t\t\t\t\n\t\tvar ul = this.upperLeft();\n\t\tvar lr = this.lowerRight();\n\t\t\n\t\tif(pointX >= ul.x - offset \n\t\t\t&& pointX <= lr.x + offset && pointY >= ul.y - offset \n\t\t\t&& pointY <= lr.y + offset)\n\t\t\treturn true;\n\t\telse \n\t\t\treturn false;\n\t},\n\t\n\t/**\n\t * @return {Bounds} A copy of this bounds.\n\t */\n\tclone: function() {\n\t\t\n\t\t//Returns a new bounds object without the callback\n\t\t// references of the original bounds\n\t\treturn new ORYX.Core.Bounds(this);\n\t},\n\t\n\ttoString: function() {\n\t\t\n\t\treturn \"( \"+this.a.x+\" | \"+this.a.y+\" )/( \"+this.b.x+\" | \"+this.b.y+\" )\";\n\t},\n\t\n\tserializeForERDF: function() {\n\n\t\treturn this.a.x+\",\"+this.a.y+\",\"+this.b.x+\",\"+this.b.y;\n\t}\n };\n \nORYX.Core.Bounds = Clazz.extend(ORYX.Core.Bounds);/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespaces\n */\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\n\n\n/**\n * @classDescription Abstract base class for all objects that have a graphical representation\n * within the editor.\n * @extends Clazz\n */\nORYX.Core.UIObject = {\n\t/**\n\t * Constructor of the UIObject class.\n\t */\n\tconstruct: function(options) {\t\n\t\t\n\t\tthis.isChanged = true;\t\t\t//Flag, if UIObject has been changed since last update.\n\t\tthis.isResized = true;\n\t\tthis.isVisible = true;\t\t\t//Flag, if UIObject's display attribute is set to 'inherit' or 'none'\n\t\tthis.isSelectable = false;\t\t//Flag, if UIObject is selectable.\n\t\tthis.isResizable = false;\t\t//Flag, if UIObject is resizable.\n\t\tthis.isMovable = false;\t\t\t//Flag, if UIObject is movable.\n\t\t\n\t\tthis.id = ORYX.Editor.provideId();\t//get unique id\n\t\tthis.parent = undefined;\t\t//parent is defined, if this object is added to another uiObject.\n\t\tthis.node = undefined;\t\t\t//this is a reference to the SVG representation, either locally or in DOM.\n\t\tthis.children = [];\t\t\t\t//array for all add uiObjects\n\t\t\n\t\tthis.bounds = new ORYX.Core.Bounds();\t\t//bounds with undefined values\n\n\t\tthis._changedCallback = this._changed.bind(this);\t//callback reference for calling _changed\n\t\tthis.bounds.registerCallback(this._changedCallback);\t//set callback in bounds\n\t\t\n\t\tif(options && options.eventHandlerCallback) {\n\t\t\tthis.eventHandlerCallback = options.eventHandlerCallback;\n\t\t}\n\t},\n\t\n\t/**\n\t * Sets isChanged flag to true. Callback for the bounds object.\n\t */\n\t_changed: function(bounds, isResized) {\n\t\tthis.isChanged = true;\n\t\tif(this.bounds == bounds)\n\t\t\tthis.isResized = isResized || this.isResized;\n\t},\n\t\n\t/**\n\t * If something changed, this method calls the refresh method that must be implemented by subclasses.\n\t */\n\tupdate: function() {\n\t\tif(this.isChanged) {\n\t\t\tthis.refresh();\n\t\t\tthis.isChanged = false;\n\t\t\t\n\t\t\t//call update of all children\n\t\t\tthis.children.each(function(value) {\n\t\t\t\tvalue.update();\n\t\t\t});\n\t\t}\n\t},\n\t\n\t/**\n\t * Is called in update method, if isChanged is set to true. Sub classes should call the super class method.\n\t */\n\trefresh: function() {\n\t\t\n\t},\n\t\n\t/**\n\t * @return {Array} Array of all child UIObjects.\n\t */\n\tgetChildren: function() {\n\t\treturn this.children.clone();\n\t},\n\t\n\t/**\n\t * @return {Array} Array of all parent UIObjects.\n\t */\n\tgetParents: function(){\n\t\tvar parents = [];\n\t\tvar parent = this.parent;\n\t\twhile(parent){\n\t\t\tparents.push(parent);\n\t\t\tparent = parent.parent;\n\t\t}\n\t\treturn parents;\n\t},\n\t\n\t/**\n\t * Returns TRUE if the given parent is one of the UIObjects parents or the UIObject themselves, otherwise FALSE.\n\t * @param {UIObject} parent\n\t * @return {Boolean} \n\t */\n\tisParent: function(parent){\n\t\tvar cparent = this;\n\t\twhile(cparent){\n\t\t\tif (cparent === parent){\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tcparent = cparent.parent;\n\t\t}\n\t\treturn false;\n\t},\n\t\n\t/**\n\t * @return {String} Id of this UIObject\n\t */\n\tgetId: function() {\n\t\treturn this.id;\n\t},\n\t\n\t/**\n\t * Method for accessing child uiObjects by id.\n\t * @param {String} id\n\t * @param {Boolean} deep\n\t * \n\t * @return {UIObject} If found, it returns the UIObject with id.\n\t */\n\tgetChildById: function(id, deep) {\n\t\treturn this.children.find(function(uiObj) {\n\t\t\tif(uiObj.getId() === id) {\n\t\t\t\treturn uiObj;\n\t\t\t} else {\n\t\t\t\tif(deep) {\n\t\t\t\t\tvar obj = uiObj.getChildById(id, deep);\n\t\t\t\t\tif(obj) {\n\t\t\t\t\t\treturn obj;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n\t\n\t/**\n\t * Adds an UIObject to this UIObject and sets the parent of the\n\t * added UIObject. It is also added to the SVG representation of this\n\t * UIObject.\n\t * @param {UIObject} uiObject\n\t */\n\tadd: function(uiObject) {\n\t\t//add uiObject, if it is not already a child of this object\n\t\tif (!(this.children.member(uiObject))) {\n\t\t\t//if uiObject is child of another parent, remove it from that parent.\n\t\t\tif(uiObject.parent) {\n\t\t\t\tuiObject.remove(uiObject);\n\t\t\t}\n\t\t\t\n\t\t\t//add uiObject to children\n\t\t\tthis.children.push(uiObject);\n\t\t\t\n\t\t\t//set parent reference\n\t\t\tuiObject.parent = this;\n\t\t\t\n\t\t\t//add uiObject.node to this.node\n\t\t\tuiObject.node = this.node.appendChild(uiObject.node);\n\t\t\t\n\t\t\t//register callback to get informed, if child is changed\n\t\t\tuiObject.bounds.registerCallback(this._changedCallback);\n\n\t\t\t//uiObject.update();\n\t\t} else {\n\t\t\tORYX.Log.info(\"add: ORYX.Core.UIObject is already a child of this object.\");\n\t\t}\n\t},\n\t\n\t/**\n\t * Removes UIObject from this UIObject. The SVG representation will also\n\t * be removed from this UIObject's SVG representation.\n\t * @param {UIObject} uiObject\n\t */\n\tremove: function(uiObject) {\n\t\t//if uiObject is a child of this object, remove it.\n\t\tif (this.children.member(uiObject)) {\n\t\t\t//remove uiObject from children\n\t\t\tthis.children = this._uiObjects.without(uiObject);\n\t\t\t\n\t\t\t//delete parent reference of uiObject\n\t\t\tuiObject.parent = undefined;\n\t\t\t\n\t\t\t//delete uiObject.node from this.node\n\t\t\tuiObject.node = this.node.removeChild(uiObject.node);\n\t\t\t\n\t\t\t//unregister callback to get informed, if child is changed\n\t\t\tuiObject.bounds.unregisterCallback(this._changedCallback);\n\t\t} else {\n\t\t\tORYX.Log.info(\"remove: ORYX.Core.UIObject is not a child of this object.\");\n\t\t}\n\t\t\n\t},\n\t\n\t/**\n\t * Calculates absolute bounds of this UIObject.\n\t */\n\tabsoluteBounds: function() {\n\t\tif(this.parent) {\n\t\t\tvar absUL = this.absoluteXY();\n\t\t\treturn new ORYX.Core.Bounds(absUL.x, absUL.y,\n\t\t\t\t\t\t\tabsUL.x + this.bounds.width(),\n\t\t\t\t\t\t\tabsUL.y + this.bounds.height());\n\t\t} else {\n\t\t\treturn this.bounds.clone();\n\t\t}\n\t},\n\n\t/**\n\t * @return {Point} The absolute position of this UIObject.\n\t */\n\tabsoluteXY: function() {\n\t\tif(this.parent) {\n\t\t\tvar pXY = this.parent.absoluteXY();\n\t\t\tvar result = {};\n\t\t\tresult.x = pXY.x + this.bounds.upperLeft().x;\n\t\t\tresult.y = pXY.y + this.bounds.upperLeft().y;\n\t\t\treturn result;\n\t\t} else {\n\t\t\tvar result = {};\n\t\t\tresult.x = this.bounds.upperLeft().x;\n\t\t\tresult.y = this.bounds.upperLeft().y;\n\t\t\treturn result;\n\t\t}\n\t},\n\n\t/**\n\t * @return {Point} The absolute position from the Center of this UIObject.\n\t */\n\tabsoluteCenterXY: function() {\n\t\tif(this.parent) {\n\t\t\tvar pXY = this.parent.absoluteXY();\t\n\t\t\tvar result = {};\n\t\t\tresult.x = pXY.x + this.bounds.center().x;\n\t\t\tresult.y = pXY.y + this.bounds.center().y;\n\t\t\treturn result;\n\t\t\t\n\t\t} else {\n\t\t\tvar result = {};\n\t\t\tresult.x = this.bounds.center().x;\n\t\t\tresult.y = this.bounds.center().y;\n\t\t\treturn result;\n\t\t}\n\t},\n\t\n\t/**\n\t * Hides this UIObject and all its children.\n\t */\n\thide: function() {\n\t\tthis.node.setAttributeNS(null, 'display', 'none');\n\t\tthis.isVisible = false;\n\t\tthis.children.each(function(uiObj) {\n\t\t\tuiObj.hide();\t\n\t\t});\n\t},\n\t\n\t/**\n\t * Enables visibility of this UIObject and all its children.\n\t */\n\tshow: function() {\n\t\tthis.node.setAttributeNS(null, 'display', 'inherit');\n\t\tthis.isVisible = true;\n\t\tthis.children.each(function(uiObj) {\n\t\t\tuiObj.show();\t\n\t\t});\t\t\n\t},\n\t\n\taddEventHandlers: function(node) {\n\t\t\n\t\tnode.addEventListener(ORYX.CONFIG.EVENT_MOUSEDOWN, this._delegateEvent.bind(this), false);\n\t\tnode.addEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, this._delegateEvent.bind(this), false);\t\n\t\tnode.addEventListener(ORYX.CONFIG.EVENT_MOUSEUP, this._delegateEvent.bind(this), false);\n\t\tnode.addEventListener(ORYX.CONFIG.EVENT_MOUSEOVER, this._delegateEvent.bind(this), false);\n\t\tnode.addEventListener(ORYX.CONFIG.EVENT_MOUSEOUT, this._delegateEvent.bind(this), false);\n\t\tnode.addEventListener('click', this._delegateEvent.bind(this), false);\n\t\tnode.addEventListener(ORYX.CONFIG.EVENT_DBLCLICK, this._delegateEvent.bind(this), false);\n\t\t\t\n\t},\n\t\t\n\t_delegateEvent: function(event) {\n\t\tif(this.eventHandlerCallback) {\n\t\t\tthis.eventHandlerCallback(event, this);\n\t\t}\n\t},\n\t\n\ttoString: function() { return \"UIObject \" + this.id }\n };\n ORYX.Core.UIObject = Clazz.extend(ORYX.Core.UIObject);/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespaces\n */\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\n\n/**\n * Top Level uiobject.\n * @class ORYX.Core.AbstractShape\n * @extends ORYX.Core.UIObject\n */\nORYX.Core.AbstractShape = ORYX.Core.UIObject.extend(\n/** @lends ORYX.Core.AbstractShape.prototype */\n{\n\n\t/**\n\t * Constructor\n\t */\n\tconstruct: function(options, stencil, facade) {\n\t\t\n\t\targuments.callee.$.construct.apply(this, arguments);\n\t\t\n\t\tthis.resourceId = ORYX.Editor.provideId(); //Id of resource in DOM\n\t\t\n\t\t// stencil reference\n\t\tthis._stencil = stencil;\n\t\t// if the stencil defines a super stencil that should be used for its instances, set it.\n\t\tif (this._stencil._jsonStencil.superId){\n\t\t\tstencilId = this._stencil.id()\n\t\t\tsuperStencilId = stencilId.substring(0, stencilId.indexOf(\"#\") + 1) + stencil._jsonStencil.superId;\n\t\t\tstencilSet =  this._stencil.stencilSet();\n\t\t\tthis._stencil = stencilSet.stencil(superStencilId);\n\t\t}\n\t\t\n\t\t//Hash map for all properties. Only stores the values of the properties.\n\t\tthis.properties = new Hash();\n\t\tthis.propertiesChanged = new Hash();\n\n\t\t// List of properties which are not included in the stencilset, \n\t\t// but which gets (de)serialized\n\t\tthis.hiddenProperties = new Hash();\n\t\t\n\t\t\n\t\t//Initialization of property map and initial value.\n\t\tthis._stencil.properties().each((function(property) {\n\t\t\tvar key = property.prefix() + \"-\" + property.id();\n\t\t\tthis.properties[key] = property.value();\n\t\t\tthis.propertiesChanged[key] = true;\n\t\t}).bind(this));\n\t\t\n\t\t// if super stencil was defined, also regard stencil's properties:\n\t\tif (stencil._jsonStencil.superId) {\n\t\t\tstencil.properties().each((function(property) {\n\t\t\t\tvar key = property.prefix() + \"-\" + property.id();\n\t\t\t\tvar value = property.value();\n\t\t\t\tvar oldValue = this.properties[key];\n\t\t\t\tthis.properties[key] = value;\n\t\t\t\tthis.propertiesChanged[key] = true;\n\n\t\t\t\t// Raise an event, to show that the property has changed\n\t\t\t\t// required for plugins like processLink.js\n\t\t\t\t//window.setTimeout( function(){\n\n\t\t\t\t\tthis._delegateEvent({\n\t\t\t\t\t\t\ttype\t: ORYX.CONFIG.EVENT_PROPERTY_CHANGED, \n\t\t\t\t\t\t\tname\t: key, \n\t\t\t\t\t\t\tvalue\t: value,\n\t\t\t\t\t\t\toldValue: oldValue\n\t\t\t\t\t\t});\n\n\t\t\t\t//}.bind(this), 10)\n\n\t\t\t}).bind(this));\n\t\t}\n\n\t},\n\n\tlayout: function() {\n\n\t},\n\t\n\t/**\n\t * Returns the stencil object specifiing the type of the shape.\n\t */\n\tgetStencil: function() {\n\t\treturn this._stencil;\n\t},\n\t\n\t/**\n\t * \n\t * @param {Object} resourceId\n\t */\n\tgetChildShapeByResourceId: function(resourceId) {\n\n\t\tresourceId = ERDF.__stripHashes(resourceId);\n\t\t\n\t\treturn this.getChildShapes(true).find(function(shape) {\n\t\t\t\t\treturn shape.resourceId == resourceId\n\t\t\t\t});\n\t},\n\t/**\n\t * \n\t * @param {Object} deep\n\t * @param {Object} iterator\n\t */\n\tgetChildShapes: function(deep, iterator) {\n\t\tvar result = [];\n\n\t\tthis.children.each(function(uiObject) {\n\t\t\tif(uiObject instanceof ORYX.Core.Shape && uiObject.isVisible ) {\n\t\t\t\tif(iterator) {\n\t\t\t\t\titerator(uiObject);\n\t\t\t\t}\n\t\t\t\tresult.push(uiObject);\n\t\t\t\tif(deep) {\n\t\t\t\t\tresult = result.concat(uiObject.getChildShapes(deep, iterator));\n\t\t\t\t} \n\t\t\t}\n\t\t});\n\n\t\treturn result;\n\t},\n    \n    /**\n     * @param {Object} shape\n     * @return {boolean} true if any of shape's childs is given shape\n     */\n    hasChildShape: function(shape){\n        return this.getChildShapes().any(function(child){\n            return (child === shape) || child.hasChildShape(shape);\n        });\n    },\n\t\n\t/**\n\t * \n\t * @param {Object} deep\n\t * @param {Object} iterator\n\t */\n\tgetChildNodes: function(deep, iterator) {\n\t\tvar result = [];\n\n\t\tthis.children.each(function(uiObject) {\n\t\t\tif(uiObject instanceof ORYX.Core.Node && uiObject.isVisible) {\n\t\t\t\tif(iterator) {\n\t\t\t\t\titerator(uiObject);\n\t\t\t\t}\n\t\t\t\tresult.push(uiObject);\n\t\t\t}\n\t\t\tif(uiObject instanceof ORYX.Core.Shape) {\n\t\t\t\tif(deep) {\n\t\t\t\t\tresult = result.concat(uiObject.getChildNodes(deep, iterator));\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn result;\n\t},\n\t\n\t/**\n\t * \n\t * @param {Object} deep\n\t * @param {Object} iterator\n\t */\n\tgetChildEdges: function(deep, iterator) {\n\t\tvar result = [];\n\n\t\tthis.children.each(function(uiObject) {\n\t\t\tif(uiObject instanceof ORYX.Core.Edge && uiObject.isVisible) {\n\t\t\t\tif(iterator) {\n\t\t\t\t\titerator(uiObject);\n\t\t\t\t}\n\t\t\t\tresult.push(uiObject);\n\t\t\t}\n\t\t\tif(uiObject instanceof ORYX.Core.Shape) {\n\t\t\t\tif(deep) {\n\t\t\t\t\tresult = result.concat(uiObject.getChildEdges(deep, iterator));\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn result;\n\t},\n\t\n\t/**\n\t * Returns a sorted array of ORYX.Core.Node objects.\n\t * Ordered in z Order, the last object has the highest z Order.\n\t */\n\t//TODO deep iterator\n\tgetAbstractShapesAtPosition: function() {\n\t\tvar x, y;\n\t\tswitch (arguments.length) {\n\t\t\tcase 1:\n\t\t\t\tx = arguments[0].x;\n\t\t\t\ty = arguments[0].y;\n\t\t\t\tbreak;\n\t\t\tcase 2:\t//two or more arguments\n\t\t\t\tx = arguments[0];\n\t\t\t\ty = arguments[1];\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthrow \"getAbstractShapesAtPosition needs 1 or 2 arguments!\"\n\t\t}\n\n\t\tif(this.isPointIncluded(x, y)) {\n\n\t\t\tvar result = [];\n\t\t\tresult.push(this);\n\n\t\t\t//check, if one child is at that position\t\t\t\t\t\t\n\t\t\t\n\t\t\t\n\t\t\tvar childNodes = this.getChildNodes();\n\t\t\tvar childEdges = this.getChildEdges();\n\t\t\t\n\t\t\t[childNodes, childEdges].each(function(ne){\n\t\t\t\tvar nodesAtPosition = new Hash();\n\t\t\t\t\n\t\t\t\tne.each(function(node) {\n\t\t\t\t\tif(!node.isVisible){ return }\n\t\t\t\t\tvar candidates = node.getAbstractShapesAtPosition( x , y );\n\t\t\t\t\tif(candidates.length > 0) {\n\t\t\t\t\t\tvar nodesInZOrder = $A(node.node.parentNode.childNodes);\n\t\t\t\t\t\tvar zOrderIndex = nodesInZOrder.indexOf(node.node);\n\t\t\t\t\t\tnodesAtPosition[zOrderIndex] = candidates;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\tnodesAtPosition.keys().sort().each(function(key) {\n\t\t\t\t\tresult = result.concat(nodesAtPosition[key]);\n\t\t\t\t});\n \t\t\t});\n\t\t\t\t\t\t\n\t\t\treturn result;\n\t\t\t\n\t\t} else {\n\t\t\treturn [];\n\t\t}\n\t},\n\t\n\t/**\n\t * \n\t * @param key {String} Must be 'prefix-id' of property\n\t * @param value {Object} Can be of type String or Number according to property type.\n\t */\n\tsetProperty: function(key, value, force) {\n\t\tvar oldValue = this.properties[key];\n\t\tif(oldValue !== value || force === true) {\n\t\t\tthis.properties[key] = value;\n\t\t\tthis.propertiesChanged[key] = true;\n\t\t\tthis._changed();\n\t\t\t\n\t\t\t// Raise an event, to show that the property has changed\n\t\t\t//window.setTimeout( function(){\n\n\t\t\tif (!this._isInSetProperty) {\n\t\t\t\tthis._isInSetProperty = true;\n\t\t\t\t\n\t\t\t\tthis._delegateEvent({\n\t\t\t\t\t\ttype\t: ORYX.CONFIG.EVENT_PROPERTY_CHANGED, \n\t\t\t\t\t\telements : [this],\n\t\t\t\t\t\tname\t: key, \n\t\t\t\t\t\tvalue\t: value,\n\t\t\t\t\t\toldValue: oldValue\n\t\t\t\t\t});\n\t\t\t\t\n\t\t\t\tdelete this._isInSetProperty;\n\t\t\t}\n\t\t\t//}.bind(this), 10)\n\t\t}\n\t},\n\t\n\t/**\n\t * Returns TRUE if one of the properties is flagged as dirty\n\t * @return {boolean}\n\t */\n\tisPropertyChanged: function(){\n\t\treturn this.propertiesChanged.any(function(property){ return property.value });\n\t},\n\n\t/**\n\t * \n\t * @param {String} Must be 'prefix-id' of property\n\t * @param {Object} Can be of type String or Number according to property type.\n\t */\n\tsetHiddenProperty: function(key, value) {\n\t\t// IF undefined, Delete\n\t\tif (value === undefined) {\n\t\t\tdelete this.hiddenProperties[key];\n\t\t\treturn;\n\t\t}\n\t\tvar oldValue = this.hiddenProperties[key];\n\t\tif (oldValue !== value) {\n\t\t\tthis.hiddenProperties[key] = value;\n\t\t}\n\t},\n\t/**\n\t * Calculate if the point is inside the Shape\n\t * @param {Point}\n\t */\n\tisPointIncluded: function(pointX, pointY, absoluteBounds) {\n\t\tvar absBounds = absoluteBounds ? absoluteBounds : this.absoluteBounds();\n\t\treturn absBounds.isIncluded(pointX, pointY);\n\t\t\t\t\n\t},\n\t\n\t/**\n\t * Get the serialized object\n\t * return Array with hash-entrees (prefix, name, value)\n\t * Following values will given:\n\t * \t\tType\n\t * \t\tProperties\n\t */\n\tserialize: function() {\n\t\tvar serializedObject = [];\n\t\t\n\t\t// Add the type\n\t\tserializedObject.push({name: 'type', prefix:'oryx', value: this.getStencil().id(), type: 'literal'});\t\n\t\n\t\t// Add hidden properties\n\t\tthis.hiddenProperties.each(function(prop){\n\t\t\tserializedObject.push({name: prop.key.replace(\"oryx-\", \"\"), prefix: \"oryx\", value: prop.value, type: 'literal'});\n\t\t}.bind(this));\n\t\t\n\t\t// Add all properties\n\t\tthis.getStencil().properties().each((function(property){\n\t\t\t\n\t\t\tvar prefix = property.prefix();\t// Get prefix\n\t\t\tvar name = property.id();\t\t// Get name\n\t\t\t\n\t\t\t//if(typeof this.properties[prefix+'-'+name] == 'boolean' || this.properties[prefix+'-'+name] != \"\")\n\t\t\t\tserializedObject.push({name: name, prefix: prefix, value: this.properties[prefix+'-'+name], type: 'literal'});\n\n\t\t}).bind(this));\n\t\t\n\t\treturn serializedObject;\n\t},\n\t\t\n\t\t\n\tdeserialize: function(serialize){\n\t\t// Search in Serialize\n\t\tvar initializedDocker = 0;\n\t\t\n\t\t// Sort properties so that the hidden properties are first in the list\n\t\tserialize = serialize.sort(function(a,b){ a = Number(this.properties.keys().member(a.prefix+\"-\"+a.name)); b = Number(this.properties.keys().member(b.prefix+\"-\"+b.name)); return a > b ? 1 : (a < b ? -1 : 0) }.bind(this));\n\t\t\n\t\tserialize.each((function(obj){\n\t\t\t\n\t\t\tvar name \t= obj.name;\n\t\t\tvar prefix \t= obj.prefix;\n\t\t\tvar value \t= obj.value;\n            \n            // Complex properties can be real json objects, encode them to a string\n            if (Object.prototype.toString.call(value) === \"Object\") value = JSON.stringify(value);\n\n\t\t\tswitch(prefix + \"-\" + name){\n\t\t\t\tcase 'raziel-parent': \n\t\t\t\t\t\t\t// Set parent\n\t\t\t\t\t\t\tif(!this.parent) {break};\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t// Set outgoing Shape\n\t\t\t\t\t\t\tvar parent = this.getCanvas().getChildShapeByResourceId(value);\n\t\t\t\t\t\t\tif(parent) {\n\t\t\t\t\t\t\t\tparent.add(this);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tbreak;\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\tdefault:\n\t\t\t\t\t\t\t// If list, eval as an array\n\t\t\t\t\t\t\tvar prop = this.getStencil().property(prefix+\"-\"+name);\n\t\t\t\t\t\t\tif (prop && prop.isList() && typeof value === \"string\"){\n\t\t\t\t\t\t\t\tif ((value||\"\").strip()&&!value.startsWith(\"[\")&&!value.startsWith(\"]\"))\n\t\t\t\t\t\t\t\t\tvalue = \"[\\\"\"+value.strip()+\"\\\"]\";\n\t\t\t\t\t\t\t\tvalue = ((value||\"\").strip()||\"[]\").evalJSON();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t// Set property\n\t\t\t\t\t\t\tif(this.properties.keys().member(prefix+\"-\"+name)) {\n\t\t\t\t\t\t\t\tthis.setProperty(prefix+\"-\"+name, value);\n\t\t\t\t\t\t\t} else if(!(name === \"bounds\"||name === \"parent\"||name === \"target\"||name === \"dockers\"||name === \"docker\"||name === \"outgoing\"||name === \"incoming\")) {\n\t\t\t\t\t\t\t\tthis.setHiddenProperty(prefix+\"-\"+name, value);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t}\n\t\t}).bind(this));\n\t},\n\t\n\ttoString: function() { return \"ORYX.Core.AbstractShape \" + this.id },\n    \n    /**\n     * Converts the shape to a JSON representation.\n     * @return {Object} A JSON object with included ORYX.Core.AbstractShape.JSONHelper and getShape() method.\n     */\n    toJSON: function(){\n        var json = {\n            resourceId: this.resourceId,\n            properties: jQuery.extend({}, this.properties, this.hiddenProperties).inject({}, function(props, prop){\n              var key = prop[0];\n              var value = prop[1];\n                \n              //If complex property, value should be a json object\n              if ( this.getStencil().property(key)\n                \t&& this.getStencil().property(key).type() === ORYX.CONFIG.TYPE_COMPLEX \n                \t&& Object.prototype.toString.call(value) === \"String\"){\n\t\t\t\t\t\t\n                  try {value = JSON.parse(value);} catch(error){}\n            \t  //try {value = JSON.parse(value);} catch(error){}\n              \n\t\t\t  // Parse date\n\t\t\t  } else if (value instanceof Date&&this.getStencil().property(key)){\n\t\t\t  \ttry {\n\t\t\t\t\tvalue = value.format(this.getStencil().property(key).dateFormat());\n\t\t\t\t} catch(e){}\n\t\t\t  }\n              \n              //Takes \"my_property\" instead of \"oryx-my_property\" as key\n              key = key.replace(/^[\\w_]+-/, \"\");\n              props[key] = value;\n              \n              return props;\n            }.bind(this)),\n            stencil: {\n                id: this.getStencil().idWithoutNs()\n            },\n            childShapes: this.getChildShapes().map(function(shape){\n                return shape.toJSON();\n            })\n        };\n        \n        if(this.getOutgoingShapes){\n            json.outgoing = this.getOutgoingShapes().map(function(shape){\n                return {\n                    resourceId: shape.resourceId\n                };\n            });\n        }\n        \n        if(this.bounds){\n            json.bounds = { \n                lowerRight: this.bounds.lowerRight(), \n                upperLeft: this.bounds.upperLeft() \n            };\n        }\n        \n        if(this.dockers){\n            json.dockers = this.dockers.map(function(docker){\n                var d = docker.getDockedShape() && docker.referencePoint ? docker.referencePoint : docker.bounds.center();\n                d.getDocker = function(){return docker;};\n                return d;\n            });\n        }\n        \n        jQuery.extend(json, ORYX.Core.AbstractShape.JSONHelper);\n        \n        // do not pollute the json attributes (for serialization), so put the corresponding\n        // shape is encapsulated in a method\n        json.getShape = function(){\n            return this;\n        }.bind(this);\n        \n        return json;\n    }\n });\n \n/**\n * @namespace Collection of methods which can be used on a shape json object (ORYX.Core.AbstractShape#toJSON()).\n * @example\n * jQuery.extend(shapeAsJson, ORYX.Core.AbstractShape.JSONHelper);\n */\nORYX.Core.AbstractShape.JSONHelper = {\n     /**\n      * Iterates over each child shape.\n      * @param {Object} iterator Iterator function getting a child shape and his parent as arguments.\n      * @param {boolean} [deep=false] Iterate recursively (childShapes of childShapes)\n      * @param {boolean} [modify=false] If true, the result of the iterator function is taken as new shape, return false to delete it. This enables modifying the object while iterating through the child shapes.\n      * @example\n      * // Increases the lowerRight x value of each direct child shape by one. \n      * myShapeAsJson.eachChild(function(shape, parentShape){\n      *     shape.bounds.lowerRight.x = shape.bounds.lowerRight.x + 1;\n      *     return shape;\n      * }, false, true);\n      */\n     eachChild: function(iterator, deep, modify){\n         if(!this.childShapes) return;\n         \n         var newChildShapes = []; //needed if modify = true\n         \n         this.childShapes.each(function(shape){\n\t\t \t if (!(shape.eachChild instanceof Function)){\n\t\t \t\tjQuery.extend(shape, ORYX.Core.AbstractShape.JSONHelper);\n\t\t\t }\n             var res = iterator(shape, this);\n             if(res) newChildShapes.push(res); //if false is returned, and modify = true, current shape is deleted.\n             \n             if(deep) shape.eachChild(iterator, deep, modify);\n         }.bind(this));\n         \n         if(modify) this.childShapes = newChildShapes;\n     },\n     \n\t getShape: function(){\n\t \treturn null;\n\t },\n     getChildShapes: function(deep){\n         var allShapes = this.childShapes;\n         \n         if(deep){\n             this.eachChild(function(shape){\n\t\t\t \t if (!(shape.getChildShapes instanceof Function)){\n\t\t\t \t\tjQuery.extend(shape, ORYX.Core.AbstractShape.JSONHelper);\n\t\t\t\t }\n                 allShapes = allShapes.concat(shape.getChildShapes(deep));\n             }, true);\n         }\n         \n         return allShapes;\n     },\n     \n     /**\n      * @return {String} Serialized JSON object\n      */\n     serialize: function(){\n         return JSON.stringify(this);\n     }\n }\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespaces\n */\nif(!ORYX) {var ORYX = {};}\n\n/**\n   @namespace Namespace for the Oryx core elements.\n   @name ORYX.Core\n*/\nif(!ORYX.Core) {ORYX.Core = {};}\n\n/**\n * @class Oryx canvas.\n * @extends ORYX.Core.AbstractShape\n *\n */\nORYX.Core.Canvas = ORYX.Core.AbstractShape.extend({\n    /** @lends ORYX.Core.Canvas.prototype */\n\n\t/**\n\t * Defines the current zoom level\n\t */\n\tzoomLevel:1,\n\n\t/**\n\t * Constructor\n\t */\n\tconstruct: function(options, stencil, facade) {\n\t\targuments.callee.$.construct.apply(this, arguments);\n\n\t\tif(!(options && options.width && options.height)) {\n\t\t\n\t\t\tORYX.Log.fatal(\"Canvas is missing mandatory parameters options.width and options.height.\");\n\t\t\treturn;\n\t\t}\n\t\tthis.facade = facade;\t\n\t\t//TODO: set document resource id\n\t\tthis.resourceId = options.id;\n\n\t\tthis.nodes = [];\n\t\t\n\t\tthis.edges = [];\n\t\t\n\t\t// Row highlighting states\n\t\tthis.colHighlightState = 0;\n\t\t\n\t\tthis.colHighlightEnabled = false; \n\t\t\n\t\t//init svg document\n\t\tthis.rootNode = ORYX.Editor.graft(\"http://www.w3.org/2000/svg\", options.parentNode,\n\t\t\t['svg', {id: this.id, width: options.width, height: options.height},\n\t\t\t\t['defs', {}]\n\t\t\t]);\n\t\t\t\n\t\tthis.rootNode.setAttribute(\"xmlns:xlink\", \"http://www.w3.org/1999/xlink\");\n\t\tthis.rootNode.setAttribute(\"xmlns:svg\", \"http://www.w3.org/2000/svg\");\n\n\t\tthis._htmlContainer = ORYX.Editor.graft(\"http://www.w3.org/1999/xhtml\", options.parentNode,\n\t\t\t['div', {id: \"oryx_canvas_htmlContainer\", style:\"position:absolute; top:5px\"}]);\n\n\t\t// Additional SVG-node BELOW the stencils to allow underlays (if that is even a word) by plugins\n\t\tthis.underlayNode = ORYX.Editor.graft(\"http://www.w3.org/2000/svg\", this.rootNode,\n\t\t\t\t['svg', {id: \"underlay-container\"}]);\n\t\t\n\t\t// Create 2 svg-elements in the svg-container\n\t\tthis.columnHightlight1 = ORYX.Editor.graft(\"http://www.w3.org/2000/svg\", this.underlayNode,\n\t\t\t\t['rect', {x: 0, width: ORYX.CONFIG.FORM_ROW_WIDTH + 35, height: \"100%\", style: \"fill: #fff6d5\", visibility: \"hidden\"}]);\n\t\t\n\t\tthis.columnHightlight2 = ORYX.Editor.graft(\"http://www.w3.org/2000/svg\", this.underlayNode,\n\t\t\t\t['rect', {x: ORYX.CONFIG.FORM_ROW_WIDTH + 35, width: ORYX.CONFIG.FORM_ROW_WIDTH + 25, height: \"100%\", style: \"fill: #fff6d5\", visibility: \"hidden\"}]);\n\t\t\n\t\tthis.node = ORYX.Editor.graft(\"http://www.w3.org/2000/svg\", this.rootNode,\n\t\t\t['g', {},\n\t\t\t\t['g', {\"class\": \"stencils\"},\n\t\t\t\t\t['g', {\"class\": \"me\"}],\n\t\t\t\t\t['g', {\"class\": \"children\"}],\n\t\t\t\t\t['g', {\"class\": \"edge\"}]\n\t\t\t\t],\n\t\t\t\t['g', {\"class\":\"svgcontainer\"}]\n\t\t\t]);\n\t\t\n\t\t/*\n\t\tvar off = 2 * ORYX.CONFIG.GRID_DISTANCE;\n\t\tvar size = 3;\n\t\tvar d = \"\";\n\t\tfor(var i = 0; i <= options.width; i += off)\n\t\t\tfor(var j = 0; j <= options.height; j += off)\n\t\t\t\td = d + \"M\" + (i - size) + \" \" + j + \" l\" + (2*size) + \" 0 m\" + (-size) + \" \" + (-size) + \" l0 \" + (2*size) + \" m0\" + (-size) + \" \";\n\t\t\t\t\t\t\t\n\t\tORYX.Editor.graft(\"http://www.w3.org/2000/svg\", this.node.firstChild.firstChild,\n\t\t\t['path', {d:d , stroke:'#000000', 'stroke-width':'0.15px'},]);\n\t\t*/\n\t\t\n\t\t//Global definition of default font for shapes\n\t\t//Definitions in the SVG definition of a stencil will overwrite these settings for\n\t\t// that stencil.\n\t\t/*if(navigator.platform.indexOf(\"Mac\") > -1) {\n\t\t\tthis.node.setAttributeNS(null, 'stroke', 'black');\n\t\t\tthis.node.setAttributeNS(null, 'stroke-width', '0.5px');\n\t\t\tthis.node.setAttributeNS(null, 'font-family', 'Skia');\n\t\t\t//this.node.setAttributeNS(null, 'letter-spacing', '2px');\n\t\t\tthis.node.setAttributeNS(null, 'font-size', ORYX.CONFIG.LABEL_DEFAULT_LINE_HEIGHT);\n\t\t} else {\n\t\t\tthis.node.setAttributeNS(null, 'stroke', 'none');\n\t\t\tthis.node.setAttributeNS(null, 'font-family', 'Verdana');\n\t\t\tthis.node.setAttributeNS(null, 'font-size', ORYX.CONFIG.LABEL_DEFAULT_LINE_HEIGHT);\n\t\t}*/\n\t\t\n\t\tthis.node.setAttributeNS(null, 'stroke', 'none');\n\t\tthis.node.setAttributeNS(null, 'font-family', 'Verdana, sans-serif');\n\t\tthis.node.setAttributeNS(null, 'font-size-adjust', 'none');\n\t\tthis.node.setAttributeNS(null, 'font-style', 'normal');\n\t\tthis.node.setAttributeNS(null, 'font-variant', 'normal');\n\t\tthis.node.setAttributeNS(null, 'font-weight', 'normal');\n\t\tthis.node.setAttributeNS(null, 'line-heigth', 'normal');\n\t\t\n\t\tthis.node.setAttributeNS(null, 'font-size', ORYX.CONFIG.LABEL_DEFAULT_LINE_HEIGHT);\n\t\t\t\n\t\tthis.bounds.set(0,0,options.width, options.height);\n\t\t\n\t\tthis.addEventHandlers(this.rootNode.parentNode);\n\t\t\n\t\t//disable context menu\n\t\tthis.rootNode.oncontextmenu = function() {return false;};\n\t},\n\t\n\tfocus: function(){\n\t\t\n\t\ttry {\n\t\t\t// Get a href\n\t\t\tif (!this.focusEl) \n\t\t\t{\n\t\t\t\tthis.focusEl = jQuery('body').append(jQuery('<a href=\"#\" class=\"x-grid3-focus x-grid3-focus-canvas\"/>'));\n\t\t\t\tthis.focusEl.swallowEvent(\"click\", true);\n\t\t\t}\n\t\t\t\n\t\t\t// Focus it\n\t\t\tthis.focusEl.focus.defer(1, this.focusEl);\n\t\t\tthis.focusEl.blur.defer(3, this.focusEl);\n\t\t\t\n\t\t} catch(e){}\n\t},\n\t\n\tsetHightlightState: function(state) {\n\t\tif(this.colHighlightEnabled && this.colHighlightState != state) {\n\t\t\tif(state == 0) {\n\t\t\t\tthis.columnHightlight1.setAttribute(\"visibility\", \"hidden\");\n\t\t\t\tthis.columnHightlight2.setAttribute(\"visibility\", \"hidden\");\n\t\t\t} else if(state == 1) {\n\t\t\t\tthis.columnHightlight1.setAttribute(\"visibility\", \"visible\");\n\t\t\t\tthis.columnHightlight2.setAttribute(\"visibility\", \"hidden\");\n\t\t\t} else if(state == 2) {\n\t\t\t\tthis.columnHightlight1.setAttribute(\"visibility\", \"hidden\");\n\t\t\t\tthis.columnHightlight2.setAttribute(\"visibility\", \"visible\");\n\t\t\t} else if(state == 3) {\n\t\t\t\tthis.columnHightlight1.setAttribute(\"visibility\", \"visible\");\n\t\t\t\tthis.columnHightlight2.setAttribute(\"visibility\", \"visible\");\n\t\t\t}\n\t\t\tthis.colHighlightState = state;\n\t\t}\n\t},\n\t\n\tsetHightlightStateBasedOnX : function(x) {\n\t\tif(x > ORYX.CONFIG.FORM_ROW_WIDTH + 30) {\n\t\t\tthis.setHightlightState(2);\n\t\t} else {\n\t\t\tthis.setHightlightState(1);\n\t\t}\n\t},\n\t\n\tupdate: function() {\n\t\t\n\t\tthis.nodes.each(function(node) {\n\t\t\tthis._traverseForUpdate(node);\n\t\t}.bind(this));\n\t\t\n\t\t// call stencil's layout callback\n\t\t// (needed for row layouting of xforms)\n\t\t//this.getStencil().layout(this);\n\t\t\n\t\tvar layoutEvents = this.getStencil().layout();\n\t\t\n\t\tif(layoutEvents) {\n\t\t\tlayoutEvents.each(function(event) {\n\t\t\n\t\t\t\t// setup additional attributes\n\t\t\t\tevent.shape = this;\n\t\t\t\tevent.forceExecution = true;\n\t\t\t\tevent.target = this.rootNode;\n\t\t\t\t\n\t\t\t\t// do layouting\n\t\t\t\t\n\t\t\t\tthis._delegateEvent(event);\n\t\t\t}.bind(this))\n\t\t}\n\t\t\n\t\tthis.nodes.invoke(\"_update\");\n\t\t\n\t\tthis.edges.invoke(\"_update\", true);\n\t\t\n\t\t/*this.children.each(function(child) {\n\t\t\tchild._update();\n\t\t});*/\n\t},\n\t\n\t_traverseForUpdate: function(shape) {\n\t\tvar childRet = shape.isChanged;\n\t\tshape.getChildNodes(false, function(child) {\n\t\t\tif(this._traverseForUpdate(child)) {\n\t\t\t\tchildRet = true;\n\t\t\t}\n\t\t}.bind(this));\n\t\t\n\t\tif(childRet) {\n\t\t\tshape.layout();\n\t\t\treturn true;\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t},\n\t\n\tlayout: function() {\n\t\t\n\t\t\n\t\t\n\t},\n\t\n\t/**\n\t * \n\t * @param {Object} deep\n\t * @param {Object} iterator\n\t */\n\tgetChildNodes: function(deep, iterator) {\n\t\tif(!deep && !iterator) {\n\t\t\treturn this.nodes.clone();\n\t\t} else {\n\t\t\tvar result = [];\n\t\t\tthis.nodes.each(function(uiObject) {\n\t\t\t\tif(iterator) {\n\t\t\t\t\titerator(uiObject);\n\t\t\t\t}\n\t\t\t\tresult.push(uiObject);\n\t\t\t\t\n\t\t\t\tif(deep && uiObject instanceof ORYX.Core.Shape) {\n\t\t\t\t\tresult = result.concat(uiObject.getChildNodes(deep, iterator));\n\t\t\t\t}\n\t\t\t});\n\t\n\t\t\treturn result;\n\t\t}\n\t},\n\t\n\t/**\n\t * buggy crap! use base class impl instead! \n\t * @param {Object} iterator\n\t */\n/*\tgetChildEdges: function(iterator) {\n\t\tif(iterator) {\n\t\t\tthis.edges.each(function(edge) {\n\t\t\t\titerator(edge);\n\t\t\t});\n\t\t}\n\t\t\n\t\treturn this.edges.clone();\n\t},\n*/\t\n\t/**\n\t * Overrides the UIObject.add method. Adds uiObject to the correct sub node.\n\t * @param {UIObject} uiObject\n\t */\n\tadd: function(uiObject, index, silent) {\n\t\t//if uiObject is child of another UIObject, remove it.\n\t\tif(uiObject instanceof ORYX.Core.UIObject) {\n\t\t\tif (!(this.children.member(uiObject))) {\n\t\t\t\t//if uiObject is child of another parent, remove it from that parent.\n\t\t\t\tif(uiObject.parent) {\n\t\t\t\t\tuiObject.parent.remove(uiObject, true);\n\t\t\t\t}\n\n\t\t\t\t//add uiObject to the Canvas\n\t\t\t\t//add uiObject to this Shape\n\t\t\t\tif(index != undefined)\n\t\t\t\t\tthis.children.splice(index, 0, uiObject);\n\t\t\t\telse\n\t\t\t\t\tthis.children.push(uiObject);\n\n\t\t\t\t//set parent reference\n\t\t\t\tuiObject.parent = this;\n\n\t\t\t\t//add uiObject.node to this.node depending on the type of uiObject\n\t\t\t\tif(uiObject instanceof ORYX.Core.Shape) {\n\t\t\t\t\tif(uiObject instanceof ORYX.Core.Edge) {\n\t\t\t\t\t\tuiObject.addMarkers(this.rootNode.getElementsByTagNameNS(NAMESPACE_SVG, \"defs\")[0]);\n\t\t\t\t\t\tuiObject.node = this.node.childNodes[0].childNodes[2].appendChild(uiObject.node);\n\t\t\t\t\t\tthis.edges.push(uiObject);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tuiObject.node = this.node.childNodes[0].childNodes[1].appendChild(uiObject.node);\n\t\t\t\t\t\tthis.nodes.push(uiObject);\n\t\t\t\t\t}\n\t\t\t\t} else {\t//UIObject\n\t\t\t\t\tuiObject.node = this.node.appendChild(uiObject.node);\n\t\t\t\t}\n\n\t\t\t\tuiObject.bounds.registerCallback(this._changedCallback);\n\t\t\t\t\t\n\t\t\t\tif(this.eventHandlerCallback && silent !== true)\n\t\t\t\t\tthis.eventHandlerCallback({type:ORYX.CONFIG.EVENT_SHAPEADDED,shape:uiObject})\n\t\t\t} else {\n\t\t\t\t\n\t\t\t\tORYX.Log.warn(\"add: ORYX.Core.UIObject is already a child of this object.\");\n\t\t\t}\n\t\t} else {\n\n\t\t\tORYX.Log.fatal(\"add: Parameter is not of type ORYX.Core.UIObject.\");\n\t\t}\n\t},\n\n\t/**\n\t * Overrides the UIObject.remove method. Removes uiObject.\n\t * @param {UIObject} uiObject\n\t */\n\tremove: function(uiObject, silent) {\n\t\t//if uiObject is a child of this object, remove it.\n\t\tif (this.children.member(uiObject)) {\n\t\t\t//remove uiObject from children\n\t\t\tvar parent = uiObject.parent;\n\t\t\t\t\t\t\n\t\t\tthis.children = this.children.without(uiObject);\n\n\t\t\t//delete parent reference of uiObject\n\t\t\tuiObject.parent = undefined;\n\n\t\t\t//delete uiObject.node from this.node\n\t\t\tif(uiObject instanceof ORYX.Core.Shape) {\n\t\t\t\tif(uiObject instanceof ORYX.Core.Edge) {\n\t\t\t\t\tuiObject.removeMarkers();\n\t\t\t\t\tuiObject.node = this.node.childNodes[0].childNodes[2].removeChild(uiObject.node);\n\t\t\t\t\tthis.edges = this.edges.without(uiObject);\n\t\t\t\t} else {\n\t\t\t\t\tuiObject.node = this.node.childNodes[0].childNodes[1].removeChild(uiObject.node);\n\t\t\t\t\tthis.nodes = this.nodes.without(uiObject);\n\t\t\t\t}\n\t\t\t} else {\t//UIObject\n\t\t\t\t\tuiObject.node = this.node.removeChild(uiObject.node);\n\t\t\t}\n\n\t\t\tif(this.eventHandlerCallback && silent !== true)\n\t\t\t\tthis.eventHandlerCallback({type:ORYX.CONFIG.EVENT_SHAPEREMOVED,shape:uiObject, parent:parent});\n\t\t\t\t\n\t\t\tuiObject.bounds.unregisterCallback(this._changedCallback);\n\t\t} else {\n\n\t\t\tORYX.Log.warn(\"remove: ORYX.Core.UIObject is not a child of this object.\");\n\t\t}\n\t},\n    \n    /**\n     * Creates shapes out of the given collection of shape objects and adds them to the canvas.\n     * @example \n     * canvas.addShapeObjects({\n         bounds:{ lowerRight:{ y:510, x:633 }, upperLeft:{ y:146, x:210 } },\n         resourceId:\"oryx_F0715955-50F2-403D-9851-C08CFE70F8BD\",\n         childShapes:[],\n         properties:{},\n         stencil:{\n           id:\"Subprocess\"\n         },\n         outgoing:[{resourceId: 'aShape'}],\n         target: {resourceId: 'aShape'}\n       });\n     * @param {Object} shapeObjects \n     * @param {Function} [eventHandler] An event handler passed to each newly created shape (as eventHandlerCallback)\n     * @return {Array} A collection of ORYX.Core.Shape\n     * @methodOf ORYX.Core.Canvas.prototype\n     */\n    addShapeObjects: function(shapeObjects, eventHandler){\n        if(!shapeObjects) return;\n\t\t\n\t\tthis.initializingShapes = true;\n        \n        /*FIXME This implementation is very evil! At first, all shapes are created on\n          canvas. In a second step, the attributes are applied. There must be a distinction\n          between the configuration phase (where the outgoings, for example, are just named),\n          and the creation phase (where the outgoings are evaluated). This must be reflected\n          in code to provide a nicer API/ implementation!!! */\n        \n        var addShape = function(shape, parent){\n            // Create a new Stencil\n            var stencil = ORYX.Core.StencilSet.stencil(this.getStencil().namespace() + shape.stencil.id );\n\n            // Create a new Shape\n            var ShapeClass = (stencil.type() == \"node\") ? ORYX.Core.Node : ORYX.Core.Edge;\n            var newShape = new ShapeClass(\n              {'eventHandlerCallback': eventHandler},\n              stencil, this.facade);\n            \n            // Set the resource id\n            newShape.resourceId = shape.resourceId;\n            newShape.node.id = \"svg-\" + shape.resourceId;\n\t\t\t\n            // Set parent to json object to be used later\n            // Due to the nested json structure, normally shape.parent is not set/ must not be set. \n            // In special cases, it can be easier to set this directly instead of a nested structure.\n            shape.parent = \"#\" + ((shape.parent && shape.parent.resourceId) || parent.resourceId);\n            \n            // Add the shape to the canvas\n            this.add( newShape );\n\n            return {\n              json: shape,\n              object: newShape\n            };\n        }.bind(this);\n        \n        /** Builds up recursively a flatted array of shapes, including a javascript object and json representation\n         * @param {Object} shape Any object that has Object#childShapes\n         */\n        var addChildShapesRecursively = function(shape){\n            var addedShapes = [];\n        \n            if (shape.childShapes && shape.childShapes.constructor == String)\n            {\n            \tshape.childShapes = JSON.parse(shape.childShapes);\n            }\n \n            shape.childShapes.each(function(childShape){\n              addedShapes.push(addShape(childShape, shape));\n              addedShapes = addedShapes.concat(addChildShapesRecursively(childShape));\n            });\n            \n            return addedShapes;\n        }.bind(this);\n\n        var shapes = addChildShapesRecursively({\n            childShapes: shapeObjects, \n            resourceId: this.resourceId\n        });\n                    \n\n        // prepare deserialisation parameter\n        shapes.each(\n            function(shape){\n            \tvar properties = [];\n                for(field in shape.json.properties){\n                    properties.push({\n                      prefix: 'oryx',\n                      name: field,\n                      value: shape.json.properties[field]\n                    });\n                  }\n                  \n                  // Outgoings\n                  shape.json.outgoing.each(function(out){\n                    properties.push({\n                      prefix: 'raziel',\n                      name: 'outgoing',\n                      value: \"#\"+out.resourceId\n                    });\n                  });\n                  \n                  // Target \n                  // (because of a bug, the first outgoing is taken when there is no target,\n                  // can be removed after some time)\n                  if(shape.object instanceof ORYX.Core.Edge) {\n\t                  var target = shape.json.target || shape.json.outgoing[0];\n\t                  if(target){\n\t                    properties.push({\n\t                      prefix: 'raziel',\n\t                      name: 'target',\n\t                      value: \"#\"+target.resourceId\n\t                    });\n\t                  }\n                  }\n                  \n                  // Bounds\n                  if (shape.json.bounds) {\n                      properties.push({\n                          prefix: 'oryx',\n                          name: 'bounds',\n                          value: shape.json.bounds.upperLeft.x + \",\" + shape.json.bounds.upperLeft.y + \",\" + shape.json.bounds.lowerRight.x + \",\" + shape.json.bounds.lowerRight.y\n                      });\n                  }\n                  \n                  //Dockers [{x:40, y:50}, {x:30, y:60}] => \"40 50 30 60  #\"\n                  if(shape.json.dockers){\n                    properties.push({\n                      prefix: 'oryx',\n                      name: 'dockers',\n                      value: shape.json.dockers.inject(\"\", function(dockersStr, docker){\n                        return dockersStr + docker.x + \" \" + docker.y + \" \";\n                      }) + \" #\"\n                    });\n                  }\n                  \n                  //Parent\n                  properties.push({\n                    prefix: 'raziel',\n                    name: 'parent',\n                    value: shape.json.parent\n                  });\n            \n                  shape.__properties = properties;\n\t         }.bind(this)\n        );\n  \n        // Deserialize the properties from the shapes\n        // This can't be done earlier because Shape#deserialize expects that all referenced nodes are already there\n        \n        // first, deserialize all nodes\n        shapes.each(function(shape) {\n        \tif(shape.object instanceof ORYX.Core.Node) {\n        \t\tshape.object.deserialize(shape.__properties, shape.json);\n        \t}\n        });\n        \n        // second, deserialize all edges\n        shapes.each(function(shape) {\n        \tif(shape.object instanceof ORYX.Core.Edge) {\n        \t\tshape.object.deserialize(shape.__properties, shape.json);\n\t\t\t\tshape.object._oldBounds = shape.object.bounds.clone();\n\t\t\t\tshape.object._update();\n        \t}\n        });\n       \n\t\tdelete this.initializingShapes;\n        return shapes.pluck(\"object\");\n    },\n    \n    /**\n     * Updates the size of the canvas, regarding to the containg shapes.\n     */\n    updateSize: function(){\n        // Check the size for the canvas\n        var maxWidth    = 0;\n        var maxHeight   = 0;\n        var offset      = 100;\n        this.getChildShapes(true, function(shape){\n            var b = shape.bounds;\n            maxWidth    = Math.max( maxWidth, b.lowerRight().x + offset)\n            maxHeight   = Math.max( maxHeight, b.lowerRight().y + offset)\n        }); \n        \n        if( this.bounds.width() < maxWidth || this.bounds.height() < maxHeight ){\n            this.setSize({width: Math.max(this.bounds.width(), maxWidth), height: Math.max(this.bounds.height(), maxHeight)})\n        }\n    },\n\n\tgetRootNode: function() {\n\t\treturn this.rootNode;\n\t},\n\t\n\tgetUnderlayNode: function() {\n\t\treturn this.underlayNode;\n\t},\n\t\n\tgetSvgContainer: function() {\n\t\treturn this.node.childNodes[1];\n\t},\n\t\n\tgetHTMLContainer: function() {\n\t\treturn this._htmlContainer;\n\t},\t\n\n\t/**\n\t * Return all elements of the same highest level\n\t * @param {Object} elements\n\t */\n\tgetShapesWithSharedParent: function(elements) {\n\n\t\t// If there is no elements, return []\n\t\tif(!elements || elements.length < 1) { return []; }\n\t\t// If there is one element, return this element\n\t\tif(elements.length == 1) { return elements;}\n\n\t\treturn elements.findAll(function(value){\n\t\t\tvar parentShape = value.parent;\n\t\t\twhile(parentShape){\n\t\t\t\tif(elements.member(parentShape)) return false;\n\t\t\t\tparentShape = parentShape.parent;\n\t\t\t}\n\t\t\treturn true;\n\t\t});\t\t\n\n\t},\n\n\tsetSize: function(size, dontSetBounds) {\n\t\tif(!size || !size.width || !size.height){return;};\n\t\t\n\t\tif(this.rootNode.parentNode){\n\t\t\tthis.rootNode.parentNode.style.width = size.width + 'px';\n\t\t\tthis.rootNode.parentNode.style.height = size.height + 'px';\n\t\t}\n\t\t\n\t\tthis.rootNode.setAttributeNS(null, 'width', size.width);\n\t\tthis.rootNode.setAttributeNS(null, 'height', size.height);\n\n\t\t//this._htmlContainer.style.top = \"-\" + (size.height + 4) + 'px';\t\t\n\t\tif( !dontSetBounds ){\n\t\t\tthis.bounds.set({a:{x:0,y:0},b:{x:size.width/this.zoomLevel,y:size.height/this.zoomLevel}});\n\t\t}\n\t},\n\t\n\t/**\n\t * Returns an SVG document of the current process.\n\t * @param {Boolean} escapeText Use true, if you want to parse it with an XmlParser,\n\t * \t\t\t\t\tfalse, if you want to use the SVG document in browser on client side.\n\t */\n\tgetSVGRepresentation: function(escapeText) {\n\t\t// Get the serialized svg image source\n        var svgClone = this.getRootNode().cloneNode(true);\n\t\t\n\t\tthis._removeInvisibleElements(svgClone);\n\t\t\n\t\tvar x1, y1, x2, y2;\n\t\tthis.getChildShapes(true).each(function(shape) {\n\t\t\tvar absBounds = shape.absoluteBounds();\n\t\t\tvar ul = absBounds.upperLeft();\n\t\t\tvar lr = absBounds.lowerRight();\n\t\t\tif(x1 == undefined) {\n\t\t\t\tx1 = ul.x;\n\t\t\t\ty1 = ul.y;\n\t\t\t\tx2 = lr.x;\n\t\t\t\ty2 = lr.y;\n\t\t\t} else {\n\t\t\t\tx1 = Math.min(x1, ul.x);\n\t\t\t\ty1 = Math.min(y1, ul.y);\n\t\t\t\tx2 = Math.max(x2, lr.x);\n\t\t\t\ty2 = Math.max(y2, lr.y);\n\t\t\t}\n\t\t});\n\t\t\n\t\tvar margin = 50;\n\t\tvar width, height, tx, ty;\n\t\tif(x1 == undefined) {\n\t\t\twidth = 0;\n\t\t\theight = 0;\n\t\t\ttx = 0;\n\t\t\tty = 0;\n\t\t} else {\n\t\t\twidth = x2;\n\t\t\theight = y2;\n\t\t\ttx = -x1+margin/2;\n\t\t\tty = -y1+margin/2;\n\t\t}\n\t\t\n        // Set the width and height\n        svgClone.setAttributeNS(null, 'width', width + margin);\n        svgClone.setAttributeNS(null, 'height', height + margin);\n\t\t\n\t\t//remove scale factor\n\t\tsvgClone.childNodes[1].removeAttributeNS(null, 'transform');\n\t\t\n\t\ttry{\n\t\t\tvar svgCont = svgClone.childNodes[1].childNodes[1];\n\t\t\tsvgCont.parentNode.removeChild(svgCont);\n\t\t} catch(e) {}\n\n\t\tif(escapeText) {\n\t\t\t$A(svgClone.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'tspan')).each(function(elem) {\n\t\t\t\telem.textContent = elem.textContent.escapeHTML();\n\t\t\t});\n\t\t\t\n\t\t\t$A(svgClone.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'text')).each(function(elem) {\n\t\t\t\tif(elem.childNodes.length == 0)\n\t\t\t\t\telem.textContent = elem.textContent.escapeHTML();\n\t\t\t});\n\t\t}\n\t\t\n\t\t// generating absolute urls for the pdf-exporter\n\t\t$A(svgClone.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'image')).each(function(elem) {\n\t\t\tvar href = elem.getAttributeNS(\"http://www.w3.org/1999/xlink\",\"href\");\n\t\t\t\n\t\t\tif(!href.match(\"^(http|https)://\")) {\n\t\t\t\thref = window.location.protocol + \"//\" + window.location.host + href;\n\t\t\t\telem.setAttributeNS(\"http://www.w3.org/1999/xlink\", \"href\", href);\n\t\t\t}\n\t\t});\n\t\t\n\t\t\n\t\t// escape all links\n\t\t$A(svgClone.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'a')).each(function(elem) {\n\t\t\telem.setAttributeNS(\"http://www.w3.org/1999/xlink\", \"xlink:href\", (elem.getAttributeNS(\"http://www.w3.org/1999/xlink\",\"href\")||\"\").escapeHTML());\n\t\t});\n\t\t\n        return svgClone;\n\t},\n\t\n\t/**   \n\t* Removes all nodes (and its children) that has the\n\t* attribute visibility set to \"hidden\"\n\t*/\n\t_removeInvisibleElements: function(element) {\n\t\tvar index = 0;\n\t\twhile(index < element.childNodes.length) {\n\t\t\tvar child = element.childNodes[index];\n\t\t\tif(child.getAttributeNS &&\n\t\t\t\tchild.getAttributeNS(null, \"visibility\") === \"hidden\") {\n\t\t\t\telement.removeChild(child);\n\t\t\t} else {\n\t\t\t\tthis._removeInvisibleElements(child);\n\t\t\t\tindex++; \n\t\t\t}\n\t\t}\n\t\t\n\t},\n\t\n\t/**\n\t * This method checks all shapes on the canvas and removes all shapes that\n\t * contain invalid bounds values or dockers values(NaN)\n\t */\n\t/*cleanUp: function(parent) {\n\t\tif (!parent) {\n\t\t\tparent = this;\n\t\t}\n\t\tparent.getChildShapes().each(function(shape){\n\t\t\tvar a = shape.bounds.a;\n\t\t\tvar b = shape.bounds.b;\n\t\t\tif (isNaN(a.x) || isNaN(a.y) || isNaN(b.x) || isNaN(b.y)) {\n\t\t\t\tparent.remove(shape);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tshape.getDockers().any(function(docker) {\n\t\t\t\t\ta = docker.bounds.a;\n\t\t\t\t\tb = docker.bounds.b;\n\t\t\t\t\tif (isNaN(a.x) || isNaN(a.y) || isNaN(b.x) || isNaN(b.y)) {\n\t\t\t\t\t\tparent.remove(shape);\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\treturn false;\n\t\t\t\t});\n\t\t\t\tshape.getMagnets().any(function(magnet) {\n\t\t\t\t\ta = magnet.bounds.a;\n\t\t\t\t\tb = magnet.bounds.b;\n\t\t\t\t\tif (isNaN(a.x) || isNaN(a.y) || isNaN(b.x) || isNaN(b.y)) {\n\t\t\t\t\t\tparent.remove(shape);\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\treturn false;\n\t\t\t\t});\n\t\t\t\tthis.cleanUp(shape);\n\t\t\t}\n\t\t}.bind(this));\n\t},*/\n\n\t_delegateEvent: function(event) {\n\t\tif(this.eventHandlerCallback && ( event.target == this.rootNode || event.target == this.rootNode.parentNode )) {\n\t\t\tthis.eventHandlerCallback(event, this);\n\t\t}\n\t},\n\t\n\ttoString: function() { return \"Canvas \" + this.id },\n    \n    /**\n     * Calls {@link ORYX.Core.AbstractShape#toJSON} and adds some stencil set information.\n     */\n    toJSON: function() {\n        var json = arguments.callee.$.toJSON.apply(this, arguments);\n        \n//\t\tif(ORYX.CONFIG.STENCILSET_HANDLER.length > 0) {\n//\t\t\tjson.stencilset = {\n//\t\t\t\turl: this.getStencil().stencilSet().namespace()\n//\t        };\n//\t\t} else {\n\t\t\tjson.stencilset = {\n\t\t\t\turl: this.getStencil().stencilSet().source(),\n\t\t\t\tnamespace: this.getStencil().stencilSet().namespace()\n\t        };\t\n//\t\t}\n        \n        \n        return json;\n    }\n });/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\nvar idCounter = 0;\nvar ID_PREFIX = \"resource\";\n\n/**\n * Main initialization method. To be called when loading\n * of the document, including all scripts, is completed.\n */\nfunction init() {\n\n\tORYX.Log.debug(\"Querying editor instances\");\n\n\t// Hack for WebKit to set the SVGElement-Classes\n\tORYX.Editor.setMissingClasses();\n    \n    // If someone wants to create the editor instance himself\n    if (window.onOryxResourcesLoaded) {\n        window.onOryxResourcesLoaded();\n    } \n    // Else fetch the model from server and display editor\n    else {\n\t\tvar modelId = window.location.search.substring(4);\n\t\tvar modelUrl = \"./service/model/\" + modelId;\n\n        ORYX.Editor.createByUrl(modelUrl);\n    }\n}\n\n/**\n   @namespace Global Oryx name space\n   @name ORYX\n*/\nif(!ORYX) {var ORYX = {};}\n\n/**\n * The Editor class.\n * @class ORYX.Editor\n * @extends Clazz\n * @param {Object} config An editor object, passed to {@link ORYX.Editor#loadSerialized}\n * @param {String} config.id Any ID that can be used inside the editor. If fullscreen=false, any HTML node with this id must be present to render the editor to this node.\n * @param {boolean} [config.fullscreen=true] Render editor in fullscreen mode or not.\n * @param {String} config.stencilset.url Stencil set URL.\n * @param {String} [config.stencil.id] Stencil type used for creating the canvas.  \n * @param {Object} config.properties Any properties applied to the canvas.\n*/\nORYX.Editor = {\n    /** @lends ORYX.Editor.prototype */\n\t// Defines the global dom event listener \n\tDOMEventListeners: new Hash(),\n\n\t// Defines the selection\n\tselection: [],\n\t\n\t// Defines the current zoom level\n\tzoomLevel:1.0,\n\n\tconstruct: function(config) {\n\t\t\n\t\t// initialization.\n\t\tthis._eventsQueue \t= [];\n\t\tthis.loadedPlugins \t= [];\n\t\tthis.pluginsData \t= [];\n\t\t\n\t\t\n\t\t//meta data about the model for the signavio warehouse\n\t\t//directory, new, name, description, revision, model (the model data)\n\t\t\n\t\tthis.modelMetaData = config;\n\t\t\n\t\tvar model = config;\n\t\t\n\t\tthis.id = model.modelId;\n\t\t\n\t\tif(config.model) {\n\t\t\tmodel = config.model;\n\t\t}\n\t\t\n        if(!this.id) {\n        \tthis.id = model.id;\n        \tif(!this.id) {\n        \t\tthis.id = ORYX.Editor.provideId();\n        \t}\n        }\n\t\t\n        // Defines if the editor should be fullscreen or not\n\t\tthis.fullscreen = config.fullscreen !== false;\n\t\t\n\t\t// Initialize the eventlistener\n\t\tthis._initEventListener();\n\n\t\t// Load particular stencilset\n\t\tif(ORYX.CONFIG.BACKEND_SWITCH) {\n\t\t\tvar ssUrl = (model.stencilset.namespace||model.stencilset.url).replace(\"#\", \"%23\");\n        \tORYX.Core.StencilSet.loadStencilSet(ssUrl, this.modelMetaData, this.id);\n\t\t} else {\n\t\t\tvar ssUrl = model.stencilset.url;\n        \tORYX.Core.StencilSet.loadStencilSet(ssUrl, this.modelMetaData, this.id);\n\t\t}\n\n\t\t// CREATES the canvas\n\t\tthis._createCanvas(model.stencil ? model.stencil.id : null, model.properties);\n\n\t\t// GENERATES the whole EXT.VIEWPORT\n\t\tthis._generateGUI();\n\n\t\t// Initializing of a callback to check loading ends\n\t\tvar loadPluginFinished \t= false;\n\t\tvar loadContentFinished = false;\n\t\tvar initFinished = function(){\t\n\t\t\tif( !loadPluginFinished || !loadContentFinished ){ return }\n\t\t\tthis._finishedLoading();\n\t\t}.bind(this)\n\t\t\n\t\t// LOAD the plugins\n\t\twindow.setTimeout(function(){\n\t\t\tthis.loadPlugins();\n\t\t\tloadPluginFinished = true;\n\t\t\tinitFinished();\n\t\t}.bind(this), 100);\n\n\t\t// LOAD the content of the current editor instance\n\t\twindow.setTimeout(function(){\n            this.loadSerialized(model, true); // Request the meta data as well\n            this.getCanvas().update();\n\t\t\tloadContentFinished = true;\n\t\t\tinitFinished();\n\t\t}.bind(this), 200);\n\t},\n\t\n\t_finishedLoading: function() {\n\t\t// Raise Loaded Event\n\t\tthis.handleEvents( {type:ORYX.CONFIG.EVENT_LOADED} )\n\t},\n\t\n\t_initEventListener: function(){\n\n\t\t// Register on Events\n\t\t\n\t\tdocument.documentElement.addEventListener(ORYX.CONFIG.EVENT_KEYDOWN, this.catchKeyDownEvents.bind(this), false);\n\t\tdocument.documentElement.addEventListener(ORYX.CONFIG.EVENT_KEYUP, this.catchKeyUpEvents.bind(this), false);\n\n\t\t// Enable Key up and down Event\n\t\tthis._keydownEnabled = \ttrue;\n\t\tthis._keyupEnabled =  \ttrue;\n\n\t\tthis.DOMEventListeners[ORYX.CONFIG.EVENT_MOUSEDOWN] = [];\n\t\tthis.DOMEventListeners[ORYX.CONFIG.EVENT_MOUSEUP] \t= [];\n\t\tthis.DOMEventListeners[ORYX.CONFIG.EVENT_MOUSEOVER] = [];\n\t\tthis.DOMEventListeners[ORYX.CONFIG.EVENT_MOUSEOUT] \t= [];\n\t\tthis.DOMEventListeners[ORYX.CONFIG.EVENT_SELECTION_CHANGED] = [];\n\t\tthis.DOMEventListeners[ORYX.CONFIG.EVENT_MOUSEMOVE] = [];\n\t\t\t\t\n\t},\n\t\n\t/**\n\t * Generate the whole viewport of the\n\t * Editor and initialized the Ext-Framework\n\t * \n\t */\n\t_generateGUI: function() {\n\n\t\t// Defines the layout height if it's NOT fullscreen\n\t\tvar layoutHeight \t= ORYX.CONFIG.WINDOW_HEIGHT;\n\t\tvar canvasParent\t= this.getCanvas().rootNode.parentNode;\n\t\t\n\t\tjQuery(\"#canvasSection\").append(canvasParent);\n\t\t\n\t\t// Set the editor to the center, and refresh the size\n\t \tcanvasParent.parentNode.setAttributeNS(null, 'align', 'center');\n\t \tcanvasParent.setAttributeNS(null, 'align', 'left');\n\t\tthis.getCanvas().setSize({\n\t\t\twidth\t: ORYX.CONFIG.CANVAS_WIDTH,\n\t\t\theight\t: ORYX.CONFIG.CANVAS_HEIGHT\n\t\t});\t\t\n\t\t\t\t\t\t\n\t},\n\t\n\tgetAvailablePlugins: function(){\n\t\tvar curAvailablePlugins=ORYX.availablePlugins.clone();\n\t\tcurAvailablePlugins.each(function(plugin){\n\t\t\tif(this.loadedPlugins.find(function(loadedPlugin){\n\t\t\t\treturn loadedPlugin.type==this.name;\n\t\t\t}.bind(plugin))){\n\t\t\t\tplugin.engaged=true;\n\t\t\t}else{\n\t\t\t\tplugin.engaged=false;\n\t\t\t}\n\t\t\t}.bind(this));\n\t\treturn curAvailablePlugins;\n\t},\n\n\tloadScript: function (url, callback){\n\t    var script = document.createElement(\"script\")\n\t    script.type = \"text/javascript\";\n\t    if (script.readyState){  //IE\n\t        script.onreadystatechange = function(){\n\t            if (script.readyState == \"loaded\" || script.readyState == \"complete\"){\n\t                script.onreadystatechange = null;\n\t                callback();\n\t            }\n        \t};\n    \t} else {  //Others\n\t        script.onload = function(){\n\t            callback();\n\t        };\n\t\t}\n\t    script.src = url;\n\t\tdocument.getElementsByTagName(\"head\")[0].appendChild(script);\n\t},\n\t/**\n\t * activate Plugin\n\t * \n\t * @param {String} name\n\t * @param {Function} callback\n\t * \t\tcallback(sucess, [errorCode])\n\t * \t\t\terrorCodes: NOTUSEINSTENCILSET, REQUIRESTENCILSET, NOTFOUND, YETACTIVATED\n\t */\n\tactivatePluginByName: function(name, callback, loadTry){\n\n\t\tvar match=this.getAvailablePlugins().find(function(value){return value.name==name});\n\t\tif(match && (!match.engaged || (match.engaged==='false'))){\t\t\n\t\t\t\tvar loadedStencilSetsNamespaces = this.getStencilSets().keys();\n\t\t\t\tvar facade = this._getPluginFacade();\n\t\t\t\tvar newPlugin;\n\t\t\t\tvar me=this;\n\t\t\t\tORYX.Log.debug(\"Initializing plugin '%0'\", match.name);\n\t\t\t\t\n\t\t\t\t\tif (!match.requires \t|| !match.requires.namespaces \t|| match.requires.namespaces.any(function(req){ return loadedStencilSetsNamespaces.indexOf(req) >= 0 }) ){\n\t\t\t\t\t\tif(!match.notUsesIn \t|| !match.notUsesIn.namespaces \t|| !match.notUsesIn.namespaces.any(function(req){ return loadedStencilSetsNamespaces.indexOf(req) >= 0 })){\n\t\n\t\t\t\t\ttry {\n\t\t\t\t\t\t\n\t\t\t\t\t\tvar className \t= eval(match.name);\n\t\t\t\t\t\t\tvar newPlugin = new className(facade, match);\n\t\t\t\t\t\t\tnewPlugin.type = match.name;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t// If there is an GUI-Plugin, they get all Plugins-Offer-Meta-Data\n\t\t\t\t\t\t\tif (newPlugin.registryChanged) \n\t\t\t\t\t\t\t\tnewPlugin.registryChanged(me.pluginsData);\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t// If there have an onSelection-Method it will pushed to the Editor Event-Handler\n\t\t\t\t\t\t\tif (newPlugin.onSelectionChanged) \n\t\t\t\t\t\t\t\tme.registerOnEvent(ORYX.CONFIG.EVENT_SELECTION_CHANGED, newPlugin.onSelectionChanged.bind(newPlugin));\n\t\t\t\t\t\t\tthis.loadedPlugins.push(newPlugin);\n\t\t\t\t\t\t\tthis.loadedPlugins.each(function(loaded){\n\t\t\t\t\t\t\t\tif(loaded.registryChanged)\n\t\t\t\t\t\t\t\t\tloaded.registryChanged(this.pluginsData);\n\t\t\t\t\t\t\t}.bind(me));\n\t\t\t\t\t\t\tcallback(true);\n\t\t\t\t\t\t\n\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\tORYX.Log.warn(\"Plugin %0 is not available\", match.name);\n\t\t\t\t\t\tif(!!loadTry){\n\t\t\t\t\t\t\tcallback(false,\"INITFAILED\");\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthis.loadScript(\"plugins/scripts/\"+match.source, this.activatePluginByName.bind(this,match.name,callback,true));\n\t\t\t\t\t}\n\t\t\t\t\t}else{\n\t\t\t\t\t\tcallback(false,\"NOTUSEINSTENCILSET\");\n\t\t\t\t\t\tORYX.Log.info(\"Plugin need a stencilset which is not loaded'\", match.name);\n\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\n\t\t\t\t} else {\n\t\t\t\t\tcallback(false,\"REQUIRESTENCILSET\");\n\t\t\t\t\tORYX.Log.info(\"Plugin need a stencilset which is not loaded'\", match.name);\n\t\t\t\t}\n\n\t\t\t\n\t\t\t}else{\n\t\t\t\tcallback(false, match?\"NOTFOUND\":\"YETACTIVATED\");\n\t\t\t\t//TODO error handling\n\t\t\t}\n\t},\n\n\t/**\n\t *  Laden der Plugins\n\t */\n\tloadPlugins: function() {\n\t\t\n\t\t// if there should be plugins but still are none, try again.\n\t\t// TODO this should wait for every plugin respectively.\n\t\t/*if (!ORYX.Plugins && ORYX.availablePlugins.length > 0) {\n\t\t\twindow.setTimeout(this.loadPlugins.bind(this), 100);\n\t\t\treturn;\n\t\t}*/\n\t\t\n\t\tvar me = this;\n\t\tvar newPlugins = [];\n\n\n\t\tvar loadedStencilSetsNamespaces = this.getStencilSets().keys();\n\n\t\t// Available Plugins will be initalize\n\t\tvar facade = this._getPluginFacade();\n\t\t\n\t\t// If there is an Array where all plugins are described, than only take those\n\t\t// (that comes from the usage of oryx with a mashup api)\n\t\tif( ORYX.MashupAPI && ORYX.MashupAPI.loadablePlugins && ORYX.MashupAPI.loadablePlugins instanceof Array ){\n\t\t\n\t\t\t// Get the plugins from the available plugins (those who are in the plugins.xml)\n\t\t\tORYX.availablePlugins = $A(ORYX.availablePlugins).findAll(function(value){\n\t\t\t\t\t\t\t\t\t\treturn ORYX.MashupAPI.loadablePlugins.include( value.name )\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\n\t\t\t// Add those plugins to the list, which are only in the loadablePlugins list\n\t\t\tORYX.MashupAPI.loadablePlugins.each(function( className ){\n\t\t\t\tif( !(ORYX.availablePlugins.find(function(val){ return val.name == className }))){\n\t\t\t\t\tORYX.availablePlugins.push( {name: className } );\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t\t\n\t\t\n\t\tORYX.availablePlugins.each(function(value) {\n\t\t\tORYX.Log.debug(\"Initializing plugin '%0'\", value.name);\n\t\t\t\tif( (!value.requires \t|| !value.requires.namespaces \t|| value.requires.namespaces.any(function(req){ return loadedStencilSetsNamespaces.indexOf(req) >= 0 }) ) &&\n\t\t\t\t\t(!value.notUsesIn \t|| !value.notUsesIn.namespaces \t|| !value.notUsesIn.namespaces.any(function(req){ return loadedStencilSetsNamespaces.indexOf(req) >= 0 }) )&&\n\t\t\t\t\t/*only load activated plugins or undefined */\n\t\t\t\t\t(value.engaged || (value.engaged===undefined)) ){\n\n\t\t\t\ttry {\n\t\t\t\t\tvar className \t= eval(value.name);\n\t\t\t\t\tif( className ){\n\t\t\t\t\t\tvar plugin\t\t= new className(facade, value);\n\t\t\t\t\t\tplugin.type\t\t= value.name;\n\t\t\t\t\t\tnewPlugins.push( plugin );\n\t\t\t\t\t\tplugin.engaged=true;\n\t\t\t\t\t}\n\t\t\t\t} catch(e) {\n\t\t\t\t\tORYX.Log.warn(\"Plugin %0 is not available %1\", value.name, e);\n\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t} else {\n\t\t\t\tORYX.Log.info(\"Plugin need a stencilset which is not loaded'\", value.name);\n\t\t\t}\n\t\t\t\n\t\t});\n\n\t\tnewPlugins.each(function(value) {\n\t\t\t// If there is an GUI-Plugin, they get all Plugins-Offer-Meta-Data\n\t\t\tif(value.registryChanged)\n\t\t\t\tvalue.registryChanged(me.pluginsData);\n\n\t\t\t// If there have an onSelection-Method it will pushed to the Editor Event-Handler\n\t\t\tif(value.onSelectionChanged)\n\t\t\t\tme.registerOnEvent(ORYX.CONFIG.EVENT_SELECTION_CHANGED, value.onSelectionChanged.bind(value));\n\t\t});\n\n\t\tthis.loadedPlugins = newPlugins;\n\t\t\n\t\tthis.registerPluginsOnKeyEvents();\n\t\t\n\t\tthis.setSelection();\n\t\t\n\t},\n\n\t/**\n\t * Creates the Canvas\n\t * @param {String} [stencilType] The stencil type used for creating the canvas. If not given, a stencil with myBeRoot = true from current stencil set is taken.\n\t * @param {Object} [canvasConfig] Any canvas properties (like language).\n\t */\n\t_createCanvas: function(stencilType, canvasConfig) {\n        if (stencilType) {\n            // Add namespace to stencilType\n            if (stencilType.search(/^http/) === -1) {\n                stencilType = this.getStencilSets().values()[0].namespace() + stencilType;\n            }\n        }\n        else {\n            // Get any root stencil type\n            stencilType = this.getStencilSets().values()[0].findRootStencilName();\n        }\n        \n\t\t// get the stencil associated with the type\n\t\tvar canvasStencil = ORYX.Core.StencilSet.stencil(stencilType);\n\t\t\t\n\t\tif (!canvasStencil) \n\t\t\tORYX.Log.fatal(\"Initialisation failed, because the stencil with the type %0 is not part of one of the loaded stencil sets.\", stencilType);\n\t\t\n\t\t// create all dom\n\t\t// TODO fix border, so the visible canvas has a double border and some spacing to the scrollbars\n\t\tvar div = ORYX.Editor.graft(\"http://www.w3.org/1999/xhtml\", null, ['div']);\n\t\t// set class for custom styling\n\t\tdiv.addClassName(\"ORYX_Editor\");\n\t\t\t\t\t\t\n\t\t// create the canvas\n\t\tthis._canvas = new ORYX.Core.Canvas({\n\t\t\twidth\t\t\t\t\t: ORYX.CONFIG.CANVAS_WIDTH,\n\t\t\theight\t\t\t\t\t: ORYX.CONFIG.CANVAS_HEIGHT,\n\t\t\t'eventHandlerCallback'\t: this.handleEvents.bind(this),\n\t\t\tid\t\t\t\t\t\t: this.id,\n\t\t\tparentNode\t\t\t\t: div\n\t\t}, canvasStencil, this._getPluginFacade());\n        \n        if (canvasConfig) {\n          // Migrate canvasConfig to an RDF-like structure\n          //FIXME this isn't nice at all because we don't want rdf any longer\n          var properties = [];\n          for(field in canvasConfig){\n            properties.push({\n              prefix: 'oryx',\n              name: field,\n              value: canvasConfig[field]\n            });\n          }\n            \n          this._canvas.deserialize(properties);\n        }\n\t\t\t\t\n\t},\n\n\t/**\n\t * Returns a per-editor singleton plugin facade.\n\t * To be used in plugin initialization.\n\t */\n\t_getPluginFacade: function() {\n\n\t\t// if there is no pluginfacade already created:\n\t\tif(!(this._pluginFacade))\n\n\t\t\t// create it.\n\t\t\tthis._pluginFacade = {\n\n\t\t\t\tactivatePluginByName:\t\tthis.activatePluginByName.bind(this),\n\t\t\t\t//deactivatePluginByName:\t\tthis.deactivatePluginByName.bind(this),\n\t\t\t\tgetAvailablePlugins:\tthis.getAvailablePlugins.bind(this),\n\t\t\t\toffer:\t\t\t\t\tthis.offer.bind(this),\n\t\t\t\tgetStencilSets:\t\t\tthis.getStencilSets.bind(this),\n\t\t\t\tgetStencilSetExtensionDefinition:function(){ return Object.clone(this.ss_extensions_def||{})}.bind(this),\n\t\t\t\tgetRules:\t\t\t\tthis.getRules.bind(this),\n\t\t\t\tloadStencilSet:\t\t\tthis.loadStencilSet.bind(this),\n\t\t\t\tcreateShape:\t\t\tthis.createShape.bind(this),\n\t\t\t\tdeleteShape:\t\t\tthis.deleteShape.bind(this),\n\t\t\t\tgetSelection:\t\t\tthis.getSelection.bind(this),\n\t\t\t\tsetSelection:\t\t\tthis.setSelection.bind(this),\n\t\t\t\tupdateSelection:\t\tthis.updateSelection.bind(this),\n\t\t\t\tgetCanvas:\t\t\t\tthis.getCanvas.bind(this),\n\t\t\t\t\n\t\t\t\timportJSON:\t\t\t\tthis.importJSON.bind(this),\n                getJSON:                this.getJSON.bind(this),\n                getSerializedJSON:      this.getSerializedJSON.bind(this),\n\t\t\t\t\n\t\t\t\texecuteCommands:\t\tthis.executeCommands.bind(this),\n\t\t\t\tisExecutingCommands:\tthis.isExecutingCommands.bind(this),\n\t\t\t\t\n\t\t\t\tregisterOnEvent:\t\tthis.registerOnEvent.bind(this),\n\t\t\t\tunregisterOnEvent:\t\tthis.unregisterOnEvent.bind(this),\n\t\t\t\traiseEvent:\t\t\t\tthis.handleEvents.bind(this),\n\t\t\t\tenableEvent:\t\t\tthis.enableEvent.bind(this),\n\t\t\t\tdisableEvent:\t\t\tthis.disableEvent.bind(this),\n\t\t\t\t\n\t\t\t\teventCoordinates:\t\tthis.eventCoordinates.bind(this),\n\t\t\t\teventCoordinatesXY:\t\tthis.eventCoordinatesXY.bind(this),\n\t\t\t\t\t\t\t\t\n\t\t\t\tgetModelMetaData:\t\tthis.getModelMetaData.bind(this)\n\t\t\t};\n\n\t\t// return it.\n\t\treturn this._pluginFacade;\n\t},\n\n\tisExecutingCommands: function(){\n\t\treturn !!this.commandExecuting;\n\t},\n\n\t/**\n\t * Implementes the command pattern\n\t * (The real usage of the command pattern\n\t * is implemented and shown in the Plugins/undo.js)\n\t *\n\t * @param <Oryx.Core.Command>[] Array of commands\n\t */\n\texecuteCommands: function(commands){\n\t\t\n\t\tif (!this.commandStack){\n\t\t\tthis.commandStack = [];\n\t\t}\n\t\tif (!this.commandStackExecuted){\n\t\t\tthis.commandStackExecuted = [];\n\t\t}\n\t\t\n\t\t\n\t\tthis.commandStack = [].concat(this.commandStack)\n\t\t\t\t\t\t\t  .concat(commands);\n\t\t\n\t\t// Check if already executes\n\t\tif (this.commandExecuting){ return; }\n\t\t\n\t\t// Start execution\n\t\tthis.commandExecuting = true;\n\t\t\n\t\t// Iterate over all commands\n\t\twhile(this.commandStack.length > 0){\n\t\t\tvar command = this.commandStack.shift();\n\t\t\t// and execute it\n\t\t\tcommand.execute();\n\t\t\tthis.commandStackExecuted.push(command);\n\t\t}\n\t\t\n\t\t// Raise event for executing commands\n\t\tthis.handleEvents({\n\t\t\ttype\t\t: ORYX.CONFIG.EVENT_EXECUTE_COMMANDS,\n\t\t\tcommands\t: this.commandStackExecuted\n\t\t});\n\t\t\n\t\t// Remove temporary vars\n\t\tdelete this.commandStack;\n\t\tdelete this.commandStackExecuted;\n\t\tdelete this.commandExecuting;\n\t\t\n\t\t\n\t\tthis.updateSelection();\n\n\t},\n\t\n    /**\n     * Returns JSON of underlying canvas (calls ORYX.Canvas#toJSON()).\n     * @return {Object} Returns JSON representation as JSON object.\n     */\n    getJSON: function(){\n    \tdelete Array.prototype.toJSON;\n        var canvasJSON = this.getCanvas().toJSON();\n        canvasJSON.ssextensions = this.getStencilSets().values()[0].extensions().keys().findAll(function(sse){ return !sse.endsWith('/meta#') });\n        return canvasJSON;\n    },\n    \n    /**\n     * Serializes a call to toJSON().\n     * @return {String} Returns JSON representation as string.\n     */\n    getSerializedJSON: function(){\n        return JSON.stringify(this.getJSON());\n    },\n    \n\t/**\n\t* Imports shapes in JSON as expected by {@link ORYX.Editor#loadSerialized}\n\t* @param {Object|String} jsonObject The (serialized) json object to be imported\n\t* @param {boolean } [noSelectionAfterImport=false] Set to true if no shapes should be selected after import\n\t* @throws {SyntaxError} If the serialized json object contains syntax errors\n\t*/\n\timportJSON: function(jsonObject, noSelectionAfterImport) {\n\t\t\n        try {\n            jsonObject = this.renewResourceIds(jsonObject);\n        } catch(error){\n            throw error;\n        }     \n\t\t//check, if the imported json model can be loaded in this editor\n\t\t// (stencil set has to fit)\n\t\tif(jsonObject.stencilset.namespace && jsonObject.stencilset.namespace !== this.getCanvas().getStencil().stencilSet().namespace()) {\n\t\t\talert(String.format(ORYX.I18N.JSONImport.wrongSS, jsonObject.stencilset.namespace, this.getCanvas().getStencil().stencilSet().namespace()));\n\t\t\treturn null;\n\t\t} else {\n\t\t\tvar commandClass = ORYX.Core.Command.extend({\n\t\t\tconstruct: function(jsonObject, loadSerializedCB, noSelectionAfterImport, facade){\n\t\t\t\tthis.jsonObject = jsonObject;\n\t\t\t\tthis.noSelection = noSelectionAfterImport;\n\t\t\t\tthis.facade = facade;\n\t\t\t\tthis.shapes;\n\t\t\t\tthis.connections = [];\n\t\t\t\tthis.parents = new Hash();\n\t\t\t\tthis.selection = this.facade.getSelection();\n\t\t\t\tthis.loadSerialized = loadSerializedCB;\n\t\t\t},\t\t\t\n\t\t\texecute: function(){\n\t\t\t\t\n\t\t\t\tif (!this.shapes) {\n\t\t\t\t\t// Import the shapes out of the serialization\t\t\n\t\t\t\t\tthis.shapes\t= this.loadSerialized( this.jsonObject );\t\t\n\t\t\t\t\t\n\t\t\t\t\t//store all connections\n\t\t\t\t\tthis.shapes.each(function(shape) {\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (shape.getDockers) {\n\t\t\t\t\t\t\tvar dockers = shape.getDockers();\n\t\t\t\t\t\t\tif (dockers) {\n\t\t\t\t\t\t\t\tif (dockers.length > 0) {\n\t\t\t\t\t\t\t\t\tthis.connections.push([dockers.first(), dockers.first().getDockedShape(), dockers.first().referencePoint]);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (dockers.length > 1) {\n\t\t\t\t\t\t\t\t\tthis.connections.push([dockers.last(), dockers.last().getDockedShape(), dockers.last().referencePoint]);\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\t\n\t\t\t\t\t\t//store parents\n\t\t\t\t\t\tthis.parents[shape.id] = shape.parent;\n\t\t\t\t\t}.bind(this));\n\t\t\t\t} else {\n\t\t\t\t\tthis.shapes.each(function(shape) {\n\t\t\t\t\t\tthis.parents[shape.id].add(shape);\n\t\t\t\t\t}.bind(this));\n\t\t\t\t\t\n\t\t\t\t\tthis.connections.each(function(con) {\n\t\t\t\t\t\tcon[0].setDockedShape(con[1]);\n\t\t\t\t\t\tcon[0].setReferencePoint(con[2]);\n\t\t\t\t\t\tcon[0].update();\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t//this.parents.values().uniq().invoke(\"update\");\n\t\t\t\tthis.facade.getCanvas().update();\t\t\t\n\t\t\t\t\t\n\t\t\t\tif(!this.noSelection)\n\t\t\t\t\tthis.facade.setSelection(this.shapes);\n\t\t\t\telse\n\t\t\t\t\tthis.facade.updateSelection();\n\t\t\t\t\t\n\t\t\t\t// call updateSize again, because during loadSerialized the edges' bounds  \n\t\t\t\t// are not yet initialized properly\n\t\t\t\tthis.facade.getCanvas().updateSize();\t\n\t\t\t\t\t\n\t\t\t\t},\n\t\t\t\trollback: function(){\n\t\t\t\t\tvar selection = this.facade.getSelection();\n\t\t\t\t\t\n\t\t\t\t\tthis.shapes.each(function(shape) {\n\t\t\t\t\t\tselection = selection.without(shape);\n\t\t\t\t\t\tthis.facade.deleteShape(shape);\n\t\t\t\t\t}.bind(this));\n\t\t\t\t\t\n\t\t\t\t\t/*this.parents.values().uniq().each(function(parent) {\n\t\t\t\t\t\tif(!this.shapes.member(parent))\n\t\t\t\t\t\t\tparent.update();\n\t\t\t\t\t}.bind(this));*/\n\t\t\t\t\t\n\t\t\t\t\tthis.facade.getCanvas().update();\n\t\t\t\t\t\n\t\t\t\t\tthis.facade.setSelection(selection);\n\t\t\t\t}\n\t\t\t})\n\t\t\t\n\t\t\tvar command = new commandClass(jsonObject, \n\t\t\t\t\t\t\t\t\t\t\tthis.loadSerialized.bind(this),\n\t\t\t\t\t\t\t\t\t\t\tnoSelectionAfterImport,\n\t\t\t\t\t\t\t\t\t\t\tthis._getPluginFacade());\n\t\t\t\n\t\t\tthis.executeCommands([command]);\t\n\t\t\t\n\t\t\treturn command.shapes.clone();\n\t\t}\n\t},\n    \n    /**\n     * This method renew all resource Ids and according references.\n     * Warning: The implementation performs a substitution on the serialized object for\n     * easier implementation. This results in a low performance which is acceptable if this\n     * is only used when importing models.\n     * @param {Object|String} jsonObject\n     * @throws {SyntaxError} If the serialized json object contains syntax errors.\n     * @return {Object} The jsonObject with renewed ids.\n     * @private\n     */\n    renewResourceIds: function(jsonObject){\n        // For renewing resource ids, a serialized and object version is needed\n        if(Object.prototype.toString.call(jsonObject) === \"String\"){\n            try {\n                var serJsonObject = jsonObject;\n                jsonObject = JSON.parse(jsonObject);\n            } catch(error){\n                throw new SyntaxError(error.message);\n            }\n        } else {\n            var serJsonObject = JSON.stringify(jsonObject);\n        }        \n        \n        // collect all resourceIds recursively\n        var collectResourceIds = function(shapes){\n            if(!shapes) return [];\n            \n            return shapes.map(function(shape){\n                return collectResourceIds(shape.childShapes).concat(shape.resourceId);\n            }).flatten();\n        }\n        var resourceIds = collectResourceIds(jsonObject.childShapes);\n        \n        // Replace each resource id by a new one\n        resourceIds.each(function(oldResourceId){\n            var newResourceId = ORYX.Editor.provideId();\n            serJsonObject = serJsonObject.replace(new RegExp(oldResourceId, 'g'), newResourceId);\n        });\n        \n        return JSON.parse(serJsonObject);\n    },\n\n    /**\n     * Loads serialized model to the oryx.\n     * @example\n     * editor.loadSerialized({\n     *    resourceId: \"mymodel1\",\n     *    childShapes: [\n     *       {\n     *          stencil:{ id:\"Subprocess\" },\n     *          outgoing:[{resourceId: 'aShape'}],\n     *          target: {resourceId: 'aShape'},\n     *          bounds:{ lowerRight:{ y:510, x:633 }, upperLeft:{ y:146, x:210 } },\n     *          resourceId: \"myshape1\",\n     *          childShapes:[],\n     *          properties:{},\n     *       }\n     *    ],\n     *    properties:{\n     *       language: \"English\"\n     *    },\n     *    stencilset:{\n     *       url:\"http://localhost:8080/oryx/stencilsets/bpmn1.1/bpmn1.1.json\"\n     *    },\n     *    stencil:{\n     *       id:\"BPMNDiagram\"\n     *    }\n     * });\n     * @param {Object} model Description of the model to load.\n     * @param {Array} [model.ssextensions] List of stenctil set extensions.\n     * @param {String} model.stencilset.url\n     * @param {String} model.stencil.id \n     * @param {Array} model.childShapes\n     * @param {Array} [model.properties]\n     * @param {String} model.resourceId\n     * @return {ORYX.Core.Shape[]} List of created shapes\n     * @methodOf ORYX.Editor.prototype\n     */\n    loadSerialized: function(model, requestMeta){\n        var canvas  = this.getCanvas();\n      \n        // Bugfix (cf. http://code.google.com/p/oryx-editor/issues/detail?id=240)\n        // Deserialize the canvas' stencil set extensions properties first!\n        this.loadSSExtensions(model.ssextensions);\n\t\t\n\t\t// Load Meta Data Extension if available\n\t\t// #Signavio\n\t\tif (requestMeta === true) {\n\t\t\tvar metaDataExtension = this.getExtensionForMetaData();\n\t\t\tif (metaDataExtension) {\n\t\t\t\tthis.loadSSExtension(metaDataExtension);\n\t\t\t}\n\t\t}\n\t\t\n        var shapes = this.getCanvas().addShapeObjects(model.childShapes, this.handleEvents.bind(this));\n        \n        if(model.properties) {\n        \tfor(key in model.properties) {\n        \t\tvar value = model.properties[key];\n\t\t\t\tvar prop = this.getCanvas().getStencil().property(\"oryx-\"+key);\n        \t\tif (!(typeof value === \"string\") && (!prop || !prop.isList())) {\n        \t\t\tvalue = JSON.stringify(value);\n        \t\t}\n            \tthis.getCanvas().setProperty(\"oryx-\" + key, value);\n            }\n        }\n        \n        \n        this.getCanvas().updateSize();\n\t\t\n\t\t// Force to update the selection\n\t\tthis.selection = [null];\n\t\tthis.setSelection([]);\n\t\t\n        return shapes;\n    },\n\t\n\t/**\n\t * Return the namespace of the extension which\n\t * provided all the self defined meta data\n\t * @return {String} Returns null if no extension is defined, otherwise the namespace\n\t *\n\t */\n\tgetExtensionForMetaData: function(){\n\t\tif (!this.ss_extensions_def||!(this.ss_extensions_def.extensions instanceof Array)){\n\t\t\treturn null;\n\t\t}\n\t\t\n\t\tvar stencilsets = this.getStencilSets();\n\t\tvar extension = this.ss_extensions_def.extensions.find(function(ex){\n\t\t\t\treturn !!stencilsets[ex[\"extends\"]] && ex.namespace.endsWith(\"/meta#\");\n\t\t\t});\n\t\t\t\n\t\treturn extension ? extension.namespace || null : null;\t\t\n\t},\n    \n    /**\n     * Calls ORYX.Editor.prototype.ss_extension_namespace for each element\n     * @param {Array} ss_extension_namespaces An array of stencil set extension namespaces.\n     */\n    loadSSExtensions: function(ss_extension_namespaces){\n        if(!ss_extension_namespaces) return;\n\n        ss_extension_namespaces.each(function(ss_extension_namespace){\n            this.loadSSExtension(ss_extension_namespace);\n        }.bind(this));\n    },\n\t\n\t/**\n\t* Loads a stencil set extension.\n\t* The stencil set extensions definiton file must already\n\t* be loaded when the editor is initialized.\n\t*/\n\tloadSSExtension: function(ss_extension_namespace) {\t\t\t\t\n\t\t\n\t\tif (this.ss_extensions_def) {\n\t\t\tvar extension = this.ss_extensions_def.extensions.find(function(ex){\n\t\t\t\treturn (ex.namespace == ss_extension_namespace);\n\t\t\t});\n\t\t\t\n\t\t\tif (!extension) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\tvar stencilset = this.getStencilSets()[extension[\"extends\"]];\n\t\t\t\n\t\t\tif (!stencilset) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\t// Check if absolute or relative url\n\t\t\tif ((extension[\"definition\"]||\"\").startsWith(\"/\")){\n\t\t\t\tstencilset.addExtension(extension[\"definition\"])\n\t\t\t} else {\n\t\t\t\tstencilset.addExtension(ORYX.CONFIG.SS_EXTENSIONS_FOLDER + extension[\"definition\"])\n\t\t\t}\n\t\t\t\n\t\t\t//stencilset.addExtension(\"/oryx/build/stencilsets/extensions/\" + extension[\"definition\"])\n\t\t\tthis.getRules().initializeRules(stencilset);\n\t\t\t\n\t\t\tthis._getPluginFacade().raiseEvent({\n\t\t\t\ttype: ORYX.CONFIG.EVENT_STENCIL_SET_LOADED\n\t\t\t});\n\t\t}\n\t\t\n\t},\n\n\tdisableEvent: function(eventType){\n\t\tif(eventType == ORYX.CONFIG.EVENT_KEYDOWN) {\n\t\t\tthis._keydownEnabled = false;\n\t\t}\n\t\tif(eventType == ORYX.CONFIG.EVENT_KEYUP) {\n\t\t\tthis._keyupEnabled = false;\n\t\t}\n\t\tif(this.DOMEventListeners.keys().member(eventType)) {\n\t\t\tvar value = this.DOMEventListeners.remove(eventType);\n\t\t\tthis.DOMEventListeners['disable_' + eventType] = value;\n\t\t}\n\t},\n\n\tenableEvent: function(eventType){\n\t\tif(eventType == ORYX.CONFIG.EVENT_KEYDOWN) {\n\t\t\tthis._keydownEnabled = true;\n\t\t}\n\t\t\n\t\tif(eventType == ORYX.CONFIG.EVENT_KEYUP) {\n\t\t\tthis._keyupEnabled = true;\n\t\t}\n\t\t\n\t\tif(this.DOMEventListeners.keys().member(\"disable_\" + eventType)) {\n\t\t\tvar value = this.DOMEventListeners.remove(\"disable_\" + eventType);\n\t\t\tthis.DOMEventListeners[eventType] = value;\n\t\t}\n\t},\n\n\t/**\n\t *  Methods for the PluginFacade\n\t */\n\tregisterOnEvent: function(eventType, callback) {\n\t\tif(!(this.DOMEventListeners.keys().member(eventType))) {\n\t\t\tthis.DOMEventListeners[eventType] = [];\n\t\t}\n\n\t\tthis.DOMEventListeners[eventType].push(callback);\n\t},\n\n\tunregisterOnEvent: function(eventType, callback) {\n\t\tif(this.DOMEventListeners.keys().member(eventType)) {\n\t\t\tthis.DOMEventListeners[eventType] = this.DOMEventListeners[eventType].without(callback);\n\t\t} else {\n\t\t\t// Event is not supported\n\t\t\t// TODO: Error Handling\n\t\t}\n\t},\n\n\tgetSelection: function() {\n\t\treturn this.selection || [];\n\t},\n\n\tgetStencilSets: function() { \n\t\treturn ORYX.Core.StencilSet.stencilSets(this.id); \n\t},\n\t\n\tgetRules: function() {\n\t\treturn ORYX.Core.StencilSet.rules(this.id);\n\t},\n\t\n\tloadStencilSet: function(source) {\n\t\ttry {\n\t\t\tORYX.Core.StencilSet.loadStencilSet(source, this.modelMetaData, this.id);\n\t\t\tthis.handleEvents({type:ORYX.CONFIG.EVENT_STENCIL_SET_LOADED});\n\t\t} catch (e) {\n\t\t\tORYX.Log.warn(\"Requesting stencil set file failed. (\" + e + \")\");\n\t\t}\n\t},\n\n\toffer: function(pluginData) {\n\t\tif(!this.pluginsData.member(pluginData)){\n\t\t\tthis.pluginsData.push(pluginData);\n\t\t}\n\t},\n\t\n\t/**\n\t * It creates an new event or adds the callback, if already existing,\n\t * for the key combination that the plugin passes in keyCodes attribute\n\t * of the offer method.\n\t * \n\t * The new key down event fits the schema:\n\t * \t\tkey.event[.metactrl][.alt][.shift].'thekeyCode'\n\t */\n\tregisterPluginsOnKeyEvents: function() {\n\t\tthis.pluginsData.each(function(pluginData) {\n\t\t\t\n\t\t\tif(pluginData.keyCodes) {\n\t\t\t\t\n\t\t\t\tpluginData.keyCodes.each(function(keyComb) {\n\t\t\t\t\tvar eventName = \"key.event\";\n\t\t\t\t\t\n\t\t\t\t\t/* Include key action */\n\t\t\t\t\teventName += '.' + keyComb.keyAction;\n\t\t\t\t\t\n\t\t\t\t\tif(keyComb.metaKeys) {\n\t\t\t\t\t\t/* Register on ctrl or apple meta key as meta key */\n\t\t\t\t\t\tif(keyComb.metaKeys.\n\t\t\t\t\t\t\tindexOf(ORYX.CONFIG.META_KEY_META_CTRL) > -1) {\n\t\t\t\t\t\t\t\teventName += \".\" + ORYX.CONFIG.META_KEY_META_CTRL;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t/* Register on alt key as meta key */\n\t\t\t\t\t\tif(keyComb.metaKeys.\n\t\t\t\t\t\t\tindexOf(ORYX.CONFIG.META_KEY_ALT) > -1) {\n\t\t\t\t\t\t\t\teventName += '.' + ORYX.CONFIG.META_KEY_ALT;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\t/* Register on shift key as meta key */\n\t\t\t\t\t\tif(keyComb.metaKeys.\n\t\t\t\t\t\t\tindexOf(ORYX.CONFIG.META_KEY_SHIFT) > -1) {\n\t\t\t\t\t\t\t\teventName += '.' + ORYX.CONFIG.META_KEY_SHIFT;\n\t\t\t\t\t\t}\t\t\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t/* Register on the actual key */\n\t\t\t\t\tif(keyComb.keyCode)\t{\n\t\t\t\t\t\teventName += '.' + keyComb.keyCode;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t/* Register the event */\n\t\t\t\t\tORYX.Log.debug(\"Register Plugin on Key Event: %0\", eventName);\n\t\t\t\t\tif (pluginData.toggle === true && pluginData.buttonInstance) {\n\t\t\t\t\t\tthis.registerOnEvent(eventName, function(){\n\t\t\t\t\t\t\tpluginData.buttonInstance.toggle(!pluginData.buttonInstance.pressed); // Toggle \n\t\t\t\t\t\t\tpluginData.functionality.call(pluginData, pluginData.buttonInstance, pluginData.buttonInstance.pressed); // Call function\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.registerOnEvent(eventName, pluginData.functionality)\n\t\t\t\t\t}\n\t\t\t\t\n\t\t\t\t}.bind(this));\n\t\t\t}\n\t\t}.bind(this));\n\t},\n\t\n\tisEqual: function(a,b){\n\t\treturn a === b || (a.length === b.length && a.all(function(r){ return b.include(r) }))\n\t},\n\t\n\tisDirty: function(a){\n\t\treturn a.any(function(shape){ return shape.isPropertyChanged() })\n\t},\n\n\tsetSelection: function(elements, subSelectionElement, force) {\n\t\t\n\t\tif (!elements) { elements = []; }\n\t\tif (!(elements instanceof Array)) { elements = [elements]; }\n\t\t\n\t\telements = elements.findAll(function(n){ return n && n instanceof ORYX.Core.Shape });\n\t\t\n\t\tif (elements[0] instanceof ORYX.Core.Canvas) {\n\t\t\telements = [];\n\t\t}\n\t\t\n\t\tif (!force && this.isEqual(this.selection, elements) && !this.isDirty(elements)){\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tthis.selection = elements;\n\t\tthis._subSelection = subSelectionElement;\n\t\t\n\t\tthis.handleEvents({type:ORYX.CONFIG.EVENT_SELECTION_CHANGED, elements:elements, subSelection: subSelectionElement, force: !!force})\n\t},\n\t\n\tupdateSelection: function() {\n\t\tthis.setSelection(this.selection, this._subSelection, true);\n\t\t/*var s = this.selection;\n\t\tthis.setSelection();\n\t\tthis.setSelection(s);*/\n\t},\n\n\tgetCanvas: function() {\n\t\treturn this._canvas;\n\t},\n\t\n\n\t/**\n\t*\toption = {\n\t*\t\ttype: string,\n\t*\t\tposition: {x:int, y:int},\n\t*\t\tconnectingType:\tuiObj-Class\n\t*\t\tconnectedShape: uiObj\n\t*\t\tdraggin: bool\n\t*\t\tnamespace: url\n\t*       parent: ORYX.Core.AbstractShape\n\t*\t\ttemplate: a template shape that the newly created inherits properties from.\n\t*\t\t}\n\t*/\n\tcreateShape: function(option) {\n\n\t\tif(option && option.serialize && option.serialize instanceof Array){\n\t\t\n\t\t\tvar type = option.serialize.find(function(obj){return (obj.prefix+\"-\"+obj.name) == \"oryx-type\"});\n\t\t\tvar stencil = ORYX.Core.StencilSet.stencil(type.value);\n\t\t\t\n\t\t\tif(stencil.type() == 'node'){\n\t\t\t\tvar newShapeObject = new ORYX.Core.Node({'eventHandlerCallback':this.handleEvents.bind(this)}, stencil, this._getPluginFacade());\t\n\t\t\t} else {\n\t\t\t\tvar newShapeObject = new ORYX.Core.Edge({'eventHandlerCallback':this.handleEvents.bind(this)}, stencil, this._getPluginFacade());\t\n\t\t\t}\n\t\t\n\t\t\tthis.getCanvas().add(newShapeObject);\n\t\t\tnewShapeObject.deserialize(option.serialize);\n\t\t\n\t\t\treturn newShapeObject;\n\t\t}\n\n\t\t// If there is no argument, throw an exception\n\t\tif(!option || !option.type || !option.namespace) { throw \"To create a new shape you have to give an argument with type and namespace\";}\n\t\t\n\t\tvar canvas = this.getCanvas();\n\t\tvar newShapeObject;\n\n\t\t// Get the shape type\n\t\tvar shapetype = option.type;\n\n\t\t// Get the stencil set\n\t\tvar sset = ORYX.Core.StencilSet.stencilSet(option.namespace);\n\t\t// Create an New Shape, dependents on an Edge or a Node\n\t\tif(sset.stencil(shapetype).type() == \"node\") {\n\t\t\tnewShapeObject = new ORYX.Core.Node({'eventHandlerCallback':this.handleEvents.bind(this)}, sset.stencil(shapetype), this._getPluginFacade())\n\t\t} else {\n\t\t\tnewShapeObject = new ORYX.Core.Edge({'eventHandlerCallback':this.handleEvents.bind(this)}, sset.stencil(shapetype), this._getPluginFacade())\n\t\t}\n\t\t\n\t\t// when there is a template, inherit the properties.\n\t\tif(option.template) {\n\n\t\t\tnewShapeObject._jsonStencil.properties = option.template._jsonStencil.properties;\n\t\t\tnewShapeObject.postProcessProperties();\n\t\t}\n\n\t\t// Add to the canvas\n\t\tif(option.parent && newShapeObject instanceof ORYX.Core.Node) {\n\t\t\toption.parent.add(newShapeObject);\n\t\t} else {\n\t\t\tcanvas.add(newShapeObject);\n\t\t}\n\t\t\n\t\t\n\t\t// Set the position\n\t\tvar point = option.position ? option.position : {x:100, y:200};\n\t\n\t\t\n\t\tvar con;\n\t\t// If there is create a shape and in the argument there is given an ConnectingType and is instance of an edge\n\t\tif(option.connectingType && option.connectedShape && !(newShapeObject instanceof ORYX.Core.Edge)) {\n\n\t\t\t// there will be create a new Edge\n\t\t\tcon = new ORYX.Core.Edge({'eventHandlerCallback':this.handleEvents.bind(this)}, sset.stencil(option.connectingType));\n\t\t\t\n\t\t\t// And both endings dockers will be referenced to the both shapes\n\t\t\tcon.dockers.first().setDockedShape(option.connectedShape);\n\t\t\t\n\t\t\tvar magnet = option.connectedShape.getDefaultMagnet()\n\t\t\tvar cPoint = magnet ? magnet.bounds.center() : option.connectedShape.bounds.midPoint();\n\t\t\tcon.dockers.first().setReferencePoint( cPoint );\n\t\t\tcon.dockers.last().setDockedShape(newShapeObject);\n\t\t\tcon.dockers.last().setReferencePoint(newShapeObject.getDefaultMagnet().bounds.center());\t\t\n\t\t\t\n\t\t\t// The Edge will be added to the canvas and be updated\n\t\t\tcanvas.add(con);\t\n\t\t\t//con.update();\n\t\t\t\n\t\t} \n\t\t\n\t\t// Move the new Shape to the position\n\t\tif(newShapeObject instanceof ORYX.Core.Edge && option.connectedShape) {\n\n\t\t\tnewShapeObject.dockers.first().setDockedShape(option.connectedShape);\n\t\t\t\n\t\t\tif( option.connectedShape instanceof ORYX.Core.Node ){\n\t\t\t\tnewShapeObject.dockers.first().setReferencePoint(option.connectedShape.getDefaultMagnet().bounds.center());\t\t\t\t\t\n\t\t\t\tnewShapeObject.dockers.last().bounds.centerMoveTo(point);\t\t\t\n\t\t\t} else {\n\t\t\t\tnewShapeObject.dockers.first().setReferencePoint(option.connectedShape.bounds.midPoint());\t\t\t\t\t\t\t\t\n\t\t\t}\n\t\t\t\n\t\t\tvar start = newShapeObject.dockers.first();\n        \tvar end = newShapeObject.dockers.last();\n        \t\n        \tif(start.getDockedShape() && end.getDockedShape()) {\n        \t\tvar startPoint = start.getAbsoluteReferencePoint();\n        \t\tvar endPoint = end.getAbsoluteReferencePoint();\n        \t\t\n        \t\tvar docker = newShapeObject.createDocker();\n        \t\tdocker.bounds.centerMoveTo({\n        \t\t\tx: startPoint.x + (endPont.x - startPoint.x) / 2,\n        \t\t\ty: startPoint.y + (endPont.y - startPoint.y) / 2\n        \t\t});\n        \t}\n\n\t\t} else {\n\t\t\t\n\t\t\tvar b = newShapeObject.bounds\n\t\t\tif( newShapeObject instanceof ORYX.Core.Node && newShapeObject.dockers.length == 1){\n\t\t\t\tb = newShapeObject.dockers.first().bounds\n\t\t\t}\n\t\t\t\n\t\t\tb.centerMoveTo(point);\n\t\t\t\n\t\t\tvar upL = b.upperLeft();\n\t\t\tb.moveBy( -Math.min(upL.x, 0) , -Math.min(upL.y, 0) )\n\t\t\t\n\t\t\tvar lwR = b.lowerRight();\n\t\t\tb.moveBy( -Math.max(lwR.x-canvas.bounds.width(), 0) , -Math.max(lwR.y-canvas.bounds.height(), 0) )\n\t\t\t\n\t\t}\n\t\t\n\t\t// Update the shape\n\t\tif (newShapeObject instanceof ORYX.Core.Edge) {\n\t\t\tnewShapeObject._update(false);\n\t\t}\n\t\t\n\t\t// And refresh the selection\n\t\tif(!(newShapeObject instanceof ORYX.Core.Edge)&&!(option.dontUpdateSelection)) {\n\t\t\tthis.setSelection([newShapeObject]);\n\t\t}\n\t\t\n\t\tif(con && con.alignDockers) {\n\t\t\t//con.alignDockers();\n\t\t} \n\t\tif(newShapeObject.alignDockers) {\n\t\t\tnewShapeObject.alignDockers();\n\t\t}\n\n\t\treturn newShapeObject;\n\t},\n\t\n\tdeleteShape: function(shape) {\n\t\t\n\t\tif (!shape || !shape.parent){ return }\n\t\t\n\t\t//remove shape from parent\n\t\t// this also removes it from DOM\n\t\tshape.parent.remove(shape);\n\t\t\n\t\t//delete references to outgoing edges\n\t\tshape.getOutgoingShapes().each(function(os) {\n\t\t\tvar docker = os.getDockers().first();\n\t\t\tif(docker && docker.getDockedShape() == shape) {\n\t\t\t\tdocker.setDockedShape(undefined);\n\t\t\t}\n\t\t});\n\t\t\n\t\t//delete references to incoming edges\n\t\tshape.getIncomingShapes().each(function(is) {\n\t\t\tvar docker = is.getDockers().last();\n\t\t\tif(docker && docker.getDockedShape() == shape) {\n\t\t\t\tdocker.setDockedShape(undefined);\n\t\t\t}\n\t\t});\n\t\t\n\t\t//delete references of the shape's dockers\n\t\tshape.getDockers().each(function(docker) {\n\t\t\tdocker.setDockedShape(undefined);\n\t\t});\n\t},\n\t\n\t/**\n\t * Returns an object with meta data about the model.\n\t * Like name, description, ...\n\t * \n\t * Empty object with the current backend.\n\t * \n\t * @return {Object} Meta data about the model\n\t */\n\tgetModelMetaData: function() {\n\t\treturn this.modelMetaData;\n\t},\n\n\t/* Event-Handler Methods */\n\t\n\t/**\n\t* Helper method to execute an event immediately. The event is not\n\t* scheduled in the _eventsQueue. Needed to handle Layout-Callbacks.\n\t*/\n\t_executeEventImmediately: function(eventObj) {\n\t\tif(this.DOMEventListeners.keys().member(eventObj.event.type)) {\n\t\t\tthis.DOMEventListeners[eventObj.event.type].each((function(value) {\n\t\t\t\tvalue(eventObj.event, eventObj.arg);\t\t\n\t\t\t}).bind(this));\n\t\t}\n\t},\n\n\t_executeEvents: function() {\n\t\tthis._queueRunning = true;\n\t\twhile(this._eventsQueue.length > 0) {\n\t\t\tvar val = this._eventsQueue.shift();\n\t\t\tthis._executeEventImmediately(val);\n\t\t}\n\t\tthis._queueRunning = false;\n\t},\n\t\n\t/**\n\t * Leitet die Events an die Editor-Spezifischen Event-Methoden weiter\n\t * @param {Object} event Event , welches gefeuert wurde\n\t * @param {Object} uiObj Target-UiObj\n\t */\n\thandleEvents: function(event, uiObj) {\n\t\t\n\t\tORYX.Log.trace(\"Dispatching event type %0 on %1\", event.type, uiObj);\n\n\t\tswitch(event.type) {\n\t\t\tcase ORYX.CONFIG.EVENT_MOUSEDOWN:\n\t\t\t\tthis._handleMouseDown(event, uiObj);\n\t\t\t\tbreak;\n\t\t\tcase ORYX.CONFIG.EVENT_MOUSEMOVE:\n\t\t\t\tthis._handleMouseMove(event, uiObj);\n\t\t\t\tbreak;\n\t\t\tcase ORYX.CONFIG.EVENT_MOUSEUP:\n\t\t\t\tthis._handleMouseUp(event, uiObj);\n\t\t\t\tbreak;\n\t\t\tcase ORYX.CONFIG.EVENT_MOUSEOVER:\n\t\t\t\tthis._handleMouseHover(event, uiObj);\n\t\t\t\tbreak;\n\t\t\tcase ORYX.CONFIG.EVENT_MOUSEOUT:\n\t\t\t\tthis._handleMouseOut(event, uiObj);\n\t\t\t\tbreak;\n\t\t}\n\t\t/* Force execution if necessary. Used while handle Layout-Callbacks. */\n\t\tif(event.forceExecution) {\n\t\t\tthis._executeEventImmediately({event: event, arg: uiObj});\n\t\t} else {\n\t\t\tthis._eventsQueue.push({event: event, arg: uiObj});\n\t\t}\n\t\t\n\t\tif(!this._queueRunning) {\n\t\t\tthis._executeEvents();\n\t\t}\n\t\t\n\t\t// TODO: Make this return whether no listener returned false.\n\t\t// So that, when one considers bubbling undesireable, it won't happen.\n\t\treturn false;\n\t},\n\n\tisValidEvent: function(e){\n\t\ttry {\n\t\t\tvar isInput = [\"INPUT\", \"TEXTAREA\"].include(e.target.tagName.toUpperCase());\n\t\t\tvar gridHasFocus = e.target.className.include(\"x-grid3-focus\") && !e.target.className.include(\"x-grid3-focus-canvas\");\n\t\t\treturn !isInput && !gridHasFocus;\n\t\t} catch(e){\n\t\t\treturn false;\n\t\t}\n\t},\n\n\tcatchKeyUpEvents: function(event) {\n\t\tif(!this._keyupEnabled) {\n\t\t\treturn;\n\t\t}\n\t\t/* assure we have the current event. */\n        if (!event) \n            event = window.event;\n        \n\t\t// Checks if the event comes from some input field\n\t\tif (!this.isValidEvent(event)){\n\t\t\treturn;\n\t\t}\n\t\t\n\t\t/* Create key up event type */\n\t\tvar keyUpEvent = this.createKeyCombEvent(event,\tORYX.CONFIG.KEY_ACTION_UP);\n\t\t\n\t\tORYX.Log.debug(\"Key Event to handle: %0\", keyUpEvent);\n\n\t\t/* forward to dispatching. */\n\t\tthis.handleEvents({type: keyUpEvent, event:event});\n\t},\n\t\n\t/**\n\t * Catches all key down events and forward the appropriated event to \n\t * dispatching concerning to the pressed keys.\n\t * \n\t * @param {Event} \n\t * \t\tThe key down event to handle\n\t */\n\tcatchKeyDownEvents: function(event) {\n\t\tif(!this._keydownEnabled) {\n\t\t\treturn;\n\t\t}\n\t\t/* Assure we have the current event. */\n        if (!event) \n            event = window.event;\n        \n\t\t/* Fixed in FF3 */\n\t\t// This is a mac-specific fix. The mozilla event object has no knowledge\n\t\t// of meta key modifier on osx, however, it is needed for certain\n\t\t// shortcuts. This fix adds the metaKey field to the event object, so\n\t\t// that all listeners that registered per Oryx plugin facade profit from\n\t\t// this. The original bug is filed in\n\t\t// https://bugzilla.mozilla.org/show_bug.cgi?id=418334\n\t\t//if (this.__currentKey == ORYX.CONFIG.KEY_CODE_META) {\n\t\t//\tevent.appleMetaKey = true;\n\t\t//}\n\t\t//this.__currentKey = pressedKey;\n\t\t\n\t\t// Checks if the event comes from some input field\n\t\tif (!this.isValidEvent(event)){\n\t\t\treturn;\n\t\t}\n\t\t\n\t\t/* Create key up event type */\n\t\tvar keyDownEvent = this.createKeyCombEvent(event, ORYX.CONFIG.KEY_ACTION_DOWN);\n\t\t\n\t\tORYX.Log.debug(\"Key Event to handle: %0\", keyDownEvent);\n\t\t\n\t\t/* Forward to dispatching. */\n\t\tthis.handleEvents({type: keyDownEvent,event: event});\n\t},\n\t\n\t/**\n\t * Creates the event type name concerning to the pressed keys.\n\t * \n\t * @param {Event} keyDownEvent\n\t * \t\tThe source keyDownEvent to build up the event name\n\t */\n\tcreateKeyCombEvent: function(keyEvent, keyAction) {\n\n\t\t/* Get the currently pressed key code. */\n        var pressedKey = keyEvent.which || keyEvent.keyCode;\n\t\t//this.__currentKey = pressedKey;\n\t\t\n\t\t/* Event name */\n\t\tvar eventName = \"key.event\";\n\t\t\n\t\t/* Key action */\n\t\tif(keyAction) {\n\t\t\teventName += \".\" + keyAction;\n\t\t}\n\t\t\n\t\t/* Ctrl or apple meta key is pressed */\n\t\tif(keyEvent.ctrlKey || keyEvent.metaKey) {\n\t\t\teventName += \".\" + ORYX.CONFIG.META_KEY_META_CTRL;\n\t\t}\n\t\t\n\t\t/* Alt key is pressed */\n\t\tif(keyEvent.altKey) {\n\t\t\teventName += \".\" + ORYX.CONFIG.META_KEY_ALT;\n\t\t}\n\t\t\n\t\t/* Alt key is pressed */\n\t\tif(keyEvent.shiftKey) {\n\t\t\teventName += \".\" + ORYX.CONFIG.META_KEY_SHIFT;\n\t\t}\n\t\t\n\t\t/* Return the composed event name */\n\t\treturn  eventName + \".\" + pressedKey;\n\t},\n\n\t_handleMouseDown: function(event, uiObj) {\n\t\t\n\t\t// get canvas.\n\t\tvar canvas = this.getCanvas();\n\t\t// Try to get the focus\n\t\tcanvas.focus()\n\t\n\t\t// find the shape that is responsible for this element's id.\n\t\tvar element = event.currentTarget;\n\t\tvar elementController = uiObj;\n\n\t\t// gather information on selection.\n\t\tvar currentIsSelectable = (elementController !== null) &&\n\t\t\t(elementController !== undefined) && (elementController.isSelectable);\n\t\tvar currentIsMovable = (elementController !== null) &&\n\t\t\t(elementController !== undefined) && (elementController.isMovable);\n\t\tvar modifierKeyPressed = event.shiftKey || event.ctrlKey;\n\t\tvar noObjectsSelected = this.selection.length === 0;\n\t\tvar currentIsSelected = this.selection.member(elementController);\n\n\n\t\t// Rule #1: When there is nothing selected, select the clicked object.\n\t\tif(currentIsSelectable && noObjectsSelected) {\n\n\t\t\tthis.setSelection([elementController]);\n\n\t\t\tORYX.Log.trace(\"Rule #1 applied for mouse down on %0\", element.id);\n\n\t\t// Rule #3: When at least one element is selected, and there is no\n\t\t// control key pressed, and the clicked object is not selected, select\n\t\t// the clicked object.\n\t\t} else if(currentIsSelectable && !noObjectsSelected &&\n\t\t\t!modifierKeyPressed && !currentIsSelected) {\n\n\t\t\tthis.setSelection([elementController]);\n\n\t\t\t//var objectType = elementController.readAttributes();\n\t\t\t//alert(objectType[0] + \": \" + objectType[1]);\n\n\t\t\tORYX.Log.trace(\"Rule #3 applied for mouse down on %0\", element.id);\n\n\t\t// Rule #4: When the control key is pressed, and the current object is\n\t\t// not selected, add it to the selection.\n\t\t} else if(currentIsSelectable && modifierKeyPressed\n\t\t\t&& !currentIsSelected) {\n\t\t\t\t\n\t\t\tvar newSelection = this.selection.clone();\n\t\t\tnewSelection.push(elementController)\n\t\t\tthis.setSelection(newSelection)\n\n\t\t\tORYX.Log.trace(\"Rule #4 applied for mouse down on %0\", element.id);\n\n\t\t// Rule #6\n\t\t} else if(currentIsSelectable && currentIsSelected &&\n\t\t\tmodifierKeyPressed) {\n\n\t\t\tvar newSelection = this.selection.clone();\n\t\t\tthis.setSelection(newSelection.without(elementController))\n\n\t\t\tORYX.Log.trace(\"Rule #6 applied for mouse down on %0\", elementController.id);\n\n\t\t// Rule #5: When there is at least one object selected and no control\n\t\t// key pressed, we're dragging.\n\t\t/*} else if(currentIsSelectable && !noObjectsSelected\n\t\t\t&& !modifierKeyPressed) {\n\n\t\t\tif(this.log.isTraceEnabled())\n\t\t\t\tthis.log.trace(\"Rule #5 applied for mouse down on \"+element.id);\n*/\n\t\t// Rule #2: When clicked on something that is neither\n\t\t// selectable nor movable, clear the selection, and return.\n\t\t} else if (!currentIsSelectable && !currentIsMovable) {\n\t\t\t\n\t\t\tthis.setSelection([]);\n\t\t\t\n\t\t\tORYX.Log.trace(\"Rule #2 applied for mouse down on %0\", element.id);\n\n\t\t\treturn;\n\n\t\t// Rule #7: When the current object is not selectable but movable,\n\t\t// it is probably a control. Leave the selection unchanged but set\n\t\t// the movedObject to the current one and enable Drag. Dockers will\n\t\t// be processed in the dragDocker plugin.\n\t\t} else if(!currentIsSelectable && currentIsMovable && !(elementController instanceof ORYX.Core.Controls.Docker)) {\n\t\t\t\n\t\t\t// TODO: If there is any moveable elements, do this in a plugin\n\t\t\t//ORYX.Core.UIEnableDrag(event, elementController);\n\n\t\t\tORYX.Log.trace(\"Rule #7 applied for mouse down on %0\", element.id);\n\t\t\n\t\t// Rule #8: When the element is selectable and is currently selected and no \n\t\t// modifier key is pressed\n\t\t} else if(currentIsSelectable && currentIsSelected &&\n\t\t\t!modifierKeyPressed) {\n\t\t\t\n\t\t\tthis._subSelection = this._subSelection != elementController ? elementController : undefined;\n\t\t\t\t\t\t\n\t\t\tthis.setSelection(this.selection, this._subSelection);\n\t\t\t\n\t\t\tORYX.Log.trace(\"Rule #8 applied for mouse down on %0\", element.id);\n\t\t}\n\t\t\n\t\t\n\t\t// prevent event from bubbling, return.\n\t\t//Event.stop(event);\n\t\treturn;\n\t},\n\n\t_handleMouseMove: function(event, uiObj) {\n\t\treturn;\n\t},\n\n\t_handleMouseUp: function(event, uiObj) {\n\t\t// get canvas.\n\t\tvar canvas = this.getCanvas();\n\n\t\t// find the shape that is responsible for this elemement's id.\n\t\tvar elementController = uiObj;\n\n\t\t//get event position\n\t\tvar evPos = this.eventCoordinates(event);\n\n\t\t//Event.stop(event);\n\t},\n\n\t_handleMouseHover: function(event, uiObj) {\n\t\treturn;\n\t},\n\n\t_handleMouseOut: function(event, uiObj) {\n\t\treturn;\n\t},\n\n\t/**\n\t * Calculates the event coordinates to SVG document coordinates.\n\t * @param {Event} event\n\t * @return {SVGPoint} The event coordinates in the SVG document\n\t */\n\teventCoordinates: function(event) {\n\n\t\tvar canvas = this.getCanvas();\n\n\t\tvar svgPoint = canvas.node.ownerSVGElement.createSVGPoint();\n\t\tsvgPoint.x = event.clientX;\n\t\tsvgPoint.y = event.clientY;\n\t\t\n\t\tvar additionalIEZoom = 1;\n        if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) {\n            var ua = navigator.userAgent;\n            if (ua.indexOf('MSIE') >= 0) {\n                //IE 10 and below\n                var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100);\n                if (zoom !== 100) {\n                    additionalIEZoom = zoom / 100\n                }\n            }\n        }\n        \n        if (additionalIEZoom !== 1) {\n            svgPoint.x = svgPoint.x * additionalIEZoom;\n            svgPoint.y = svgPoint.y * additionalIEZoom;\n        }\n\t\t\n\t\tvar matrix = canvas.node.getScreenCTM();\n\t\treturn svgPoint.matrixTransform(matrix.inverse());\n\t},\n\t\n\teventCoordinatesXY: function(x, y) {\n\n\t\tvar canvas = this.getCanvas();\n\n\t\tvar svgPoint = canvas.node.ownerSVGElement.createSVGPoint();\n\t\tsvgPoint.x = x;\n\t\tsvgPoint.y = y;\n\t\t\n\t\tvar additionalIEZoom = 1;\n        if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) {\n            var ua = navigator.userAgent;\n            if (ua.indexOf('MSIE') >= 0) {\n                //IE 10 and below\n                var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100);\n                if (zoom !== 100) {\n                    additionalIEZoom = zoom / 100\n                }\n            }\n        }\n        \n        if (additionalIEZoom !== 1) {\n            svgPoint.x = svgPoint.x * additionalIEZoom;\n            svgPoint.y = svgPoint.y * additionalIEZoom;\n        }\n\t\t\n\t\tvar matrix = canvas.node.getScreenCTM();\n\t\treturn svgPoint.matrixTransform(matrix.inverse());\n\t}\n};\nORYX.Editor = Clazz.extend(ORYX.Editor);\n\n/**\n * Creates a new ORYX.Editor instance by fetching a model from given url and passing it to the constructur\n * @param {String} modelUrl The JSON URL of a model.\n * @param {Object} config Editor config passed to the constructur, merged with the response of the request to modelUrl\n */\nORYX.Editor.createByUrl = function(modelUrl){\n    new Ajax.Request(modelUrl, {\n      method: 'GET',\n      onSuccess: function(transport) {\n    \tvar editorConfig = JSON.parse(transport.responseText);\n        new ORYX.Editor(editorConfig);\n      }.bind(this)\n    });\n}\n\n// TODO Implement namespace awareness on attribute level.\n/**\n * graft() function\n * Originally by Sean M. Burke from interglacial.com, altered for usage with\n * SVG and namespace (xmlns) support. Be sure you understand xmlns before\n * using this funtion, as it creates all grafted elements in the xmlns\n * provided by you and all element's attribures in default xmlns. If you\n * need to graft elements in a certain xmlns and wish to assign attributes\n * in both that and another xmlns, you will need to do stepwise grafting,\n * adding non-default attributes yourself or you'll have to enhance this\n * function. Latter, I would appreciate: martin???apfelfabrik.de\n * @param {Object} namespace The namespace in which\n * \t\t\t\t\telements should be grafted.\n * @param {Object} parent The element that should contain the grafted\n * \t\t\t\t\tstructure after the function returned.\n * @param {Object} t the crafting structure.\n * @param {Object} doc the document in which grafting is performed.\n */\nORYX.Editor.graft = function(namespace, parent, t, doc) {\n\n    doc = (doc || (parent && parent.ownerDocument) || document);\n    var e;\n    if(t === undefined) {\n        throw \"Can't graft an undefined value\";\n    } else if(t.constructor == String) {\n        e = doc.createTextNode( t );\n    } else {\n        for(var i = 0; i < t.length; i++) {\n            if( i === 0 && t[i].constructor == String ) {\n                var snared;\n                snared = t[i].match( /^([a-z][a-z0-9]*)\\.([^\\s\\.]+)$/i );\n                if( snared ) {\n                    e = doc.createElementNS(namespace, snared[1] );\n                    e.setAttributeNS(null, 'class', snared[2] );\n                    continue;\n                }\n                snared = t[i].match( /^([a-z][a-z0-9]*)$/i );\n                if( snared ) {\n                    e = doc.createElementNS(namespace, snared[1] );  // but no class\n                    continue;\n                }\n\n                // Otherwise:\n                e = doc.createElementNS(namespace, \"span\" );\n                e.setAttribute(null, \"class\", \"namelessFromLOL\" );\n            }\n\n            if( t[i] === undefined ) {\n                throw \"Can't graft an undefined value in a list!\";\n            } else if( t[i].constructor == String || t[i].constructor == Array ) {\n                this.graft(namespace, e, t[i], doc );\n            } else if(  t[i].constructor == Number ) {\n                this.graft(namespace, e, t[i].toString(), doc );\n            } else if(  t[i].constructor == Object ) {\n                // hash's properties => element's attributes\n                for(var k in t[i]) { e.setAttributeNS(null, k, t[i][k] ); }\n            } else {\n\n\t\t\t}\n        }\n    }\n\tif(parent && parent.appendChild) {\n\t    parent.appendChild( e );\n\t} else {\n\n\t}\n    return e; // return the topmost created node\n};\n\nORYX.Editor.provideId = function() {\n\tvar res = [], hex = '0123456789ABCDEF';\n\n\tfor (var i = 0; i < 36; i++) res[i] = Math.floor(Math.random()*0x10);\n\n\tres[14] = 4;\n\tres[19] = (res[19] & 0x3) | 0x8;\n\n\tfor (var i = 0; i < 36; i++) res[i] = hex[res[i]];\n\n\tres[8] = res[13] = res[18] = res[23] = '-';\n\n\treturn \"oryx_\" + res.join('');\n};\n\n/**\n * When working with Ext, conditionally the window needs to be resized. To do\n * so, use this class method. Resize is deferred until 100ms, and all subsequent\n * resizeBugFix calls are ignored until the initially requested resize is\n * performed.\n */\nORYX.Editor.resizeFix = function() {\n\tif (!ORYX.Editor._resizeFixTimeout) {\n\t\tORYX.Editor._resizeFixTimeout = window.setTimeout(function() {\n\t\t\twindow.resizeBy(1,1);\n\t\t\twindow.resizeBy(-1,-1);\n\t\t\tORYX.Editor._resizefixTimeout = null;\n\t\t}, 100); \n\t}\n};\n\nORYX.Editor.Cookie = {\n\t\n\tcallbacks:[],\n\t\t\n\tonChange: function( callback, interval ){\n\t\n\t\tthis.callbacks.push(callback);\n\t\tthis.start( interval )\n\t\n\t},\n\t\n\tstart: function( interval ){\n\t\t\n\t\tif( this.pe ){\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tvar currentString = document.cookie;\n\t\t\n\t\tthis.pe = new PeriodicalExecuter( function(){\n\t\t\t\n\t\t\tif( currentString != document.cookie ){\n\t\t\t\tcurrentString = document.cookie;\n\t\t\t\tthis.callbacks.each(function(callback){ callback(this.getParams()) }.bind(this));\n\t\t\t}\n\t\t\t\n\t\t}.bind(this), ( interval || 10000 ) / 1000);\t\n\t},\n\t\n\tstop: function(){\n\n\t\tif( this.pe ){\n\t\t\tthis.pe.stop();\n\t\t\tthis.pe = null;\n\t\t}\n\t},\n\t\t\n\tgetParams: function(){\n\t\tvar res = {};\n\t\t\n\t\tvar p = document.cookie;\n\t\tp.split(\"; \").each(function(param){ res[param.split(\"=\")[0]] = param.split(\"=\")[1];});\n\t\t\n\t\treturn res;\n\t},\t\n\t\n\ttoString: function(){\n\t\treturn document.cookie;\n\t}\n};\n\n/**\n * Workaround for SAFARI/Webkit, because\n * when trying to check SVGSVGElement of instanceof there is \n * raising an error\n * \n */\nORYX.Editor.SVGClassElementsAreAvailable = true;\nORYX.Editor.setMissingClasses = function() {\n\t\n\ttry {\n\t\tSVGElement;\n\t} catch(e) {\n\t\tORYX.Editor.SVGClassElementsAreAvailable = false;\n\t\tSVGSVGElement \t\t= document.createElementNS('http://www.w3.org/2000/svg', 'svg').toString();\n\t\tSVGGElement \t\t= document.createElementNS('http://www.w3.org/2000/svg', 'g').toString();\n\t\tSVGPathElement \t\t= document.createElementNS('http://www.w3.org/2000/svg', 'path').toString();\n\t\tSVGTextElement \t\t= document.createElementNS('http://www.w3.org/2000/svg', 'text').toString();\n\t\t//SVGMarkerElement \t= document.createElementNS('http://www.w3.org/2000/svg', 'marker').toString();\n\t\tSVGRectElement \t\t= document.createElementNS('http://www.w3.org/2000/svg', 'rect').toString();\n\t\tSVGImageElement \t= document.createElementNS('http://www.w3.org/2000/svg', 'image').toString();\n\t\tSVGCircleElement \t= document.createElementNS('http://www.w3.org/2000/svg', 'circle').toString();\n\t\tSVGEllipseElement \t= document.createElementNS('http://www.w3.org/2000/svg', 'ellipse').toString();\n\t\tSVGLineElement\t \t= document.createElementNS('http://www.w3.org/2000/svg', 'line').toString();\n\t\tSVGPolylineElement \t= document.createElementNS('http://www.w3.org/2000/svg', 'polyline').toString();\n\t\tSVGPolygonElement \t= document.createElementNS('http://www.w3.org/2000/svg', 'polygon').toString();\n\t\t\n\t}\n\t\n}\nORYX.Editor.checkClassType = function( classInst, classType ) {\n\t\n\tif( ORYX.Editor.SVGClassElementsAreAvailable ){\n\t\treturn classInst instanceof classType\n\t} else {\n\t\treturn classInst == classType\n\t}\n};\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespaces\n */\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\n\n\nnew function(){\n\t\n\tORYX.Core.UIEnableDrag = function(event, uiObj, option) {\n\t\n\t\tthis.uiObj = uiObj;\n\t\tvar upL = uiObj.bounds.upperLeft();\n\t\n\t\tvar a = uiObj.node.getScreenCTM();\n\t\tthis.faktorXY= {x: a.a, y: a.d};\n\t\t\n\t\tthis.scrollNode = uiObj.node.ownerSVGElement.parentNode.parentNode;\n\t\t\n\t\tthis.offSetPosition =  {\n\t\t\tx: Event.pointerX(event) - (upL.x * this.faktorXY.x),\n\t\t\ty: Event.pointerY(event) - (upL.y * this.faktorXY.y)};\n\t\n\t\tthis.offsetScroll\t= {x:this.scrollNode.scrollLeft,y:this.scrollNode.scrollTop};\n\t\t\t\n\t\tthis.dragCallback = ORYX.Core.UIDragCallback.bind(this);\n\t\tthis.disableCallback = ORYX.Core.UIDisableDrag.bind(this);\n\t\n\t\tthis.movedCallback = option ? option.movedCallback : undefined;\n\t\tthis.upCallback = option ? option.upCallback : undefined;\n\t\t\n\t\tdocument.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEUP, this.disableCallback, true);\n\t\tdocument.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, \tthis.dragCallback , false);\n\t\n\t};\n\t\n\tORYX.Core.UIDragCallback = function(event) {\n\t\n\t\tvar position = {\n\t\t\tx: Event.pointerX(event) - this.offSetPosition.x,\n\t\t\ty: Event.pointerY(event) - this.offSetPosition.y}\n\t\n\t\tposition.x \t-= this.offsetScroll.x - this.scrollNode.scrollLeft; \n\t\tposition.y \t-= this.offsetScroll.y - this.scrollNode.scrollTop;\n\t\n\t\tposition.x /= this.faktorXY.x;\n\t\tposition.y /= this.faktorXY.y;\n\t\n\t\tthis.uiObj.bounds.moveTo(position);\n\t\t//this.uiObj.update();\n\t\n\t\tif(this.movedCallback)\n\t\t\tthis.movedCallback(event);\n\t\t\n\t\t//Event.stop(event);\n\t\n\t};\n\t\n\tORYX.Core.UIDisableDrag = function(event) {\n\t\tdocument.documentElement.removeEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, this.dragCallback, false);\n\t\tdocument.documentElement.removeEventListener(ORYX.CONFIG.EVENT_MOUSEUP, this.disableCallback, true);\n\t\t\n\t\tif(this.upCallback)\n\t\t\tthis.upCallback(event);\n\t\t\t\n\t\tthis.upCallback = undefined;\n\t\tthis.movedCallback = undefined;\t\t\n\t\t\n\t\tEvent.stop(event);\t\n\t};\n\n\n\n\t\n\t/**\n\t * Implements a command to move docker by an offset.\n\t * \n\t * @class ORYX.Core.MoveDockersCommand\n\t * @param {Object} object An object with the docker id as key and docker and offset as object value\n\t * \n\t */\t\n\tORYX.Core.MoveDockersCommand = ORYX.Core.Command.extend({\n\t\tconstruct: function(dockers){\n\t\t\tthis.dockers \t= $H(dockers);\n\t\t\tthis.edges \t\t= $H({});\n\t\t},\n\t\texecute: function(){\n\t\t\tif (this.changes) {\n\t\t\t\tthis.executeAgain();\n\t\t\t\treturn;\n\t\t\t} else {\n\t\t\t\tthis.changes = $H({});\n\t\t\t}\n\t\t\t\n\t\t\tthis.dockers.values().each(function(docker){\n\t\t\t\tvar edge = docker.docker.parent;\n\t\t\t\tif (!edge){ return }\n\t\t\t\t\n\t\t\t\tif (!this.changes[edge.getId()]) {\n\t\t\t\t\tthis.changes[edge.getId()] = {\n\t\t\t\t\t\tedge\t\t\t\t: edge,\n\t\t\t\t\t\toldDockerPositions\t: edge.dockers.map(function(r){ return r.bounds.center() })\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tdocker.docker.bounds.moveBy(docker.offset);\n\t\t\t\tthis.edges[edge.getId()] = edge;\n\t\t\t\tdocker.docker.update();\n\t\t\t}.bind(this));\n\t\t\tthis.edges.each(function(edge){\n\t\t\t\tthis.updateEdge(edge.value);\n\t\t\t\tif (this.changes[edge.value.getId()])\n\t\t\t\t\tthis.changes[edge.value.getId()].dockerPositions = edge.value.dockers.map(function(r){ return r.bounds.center() })\n\t\t\t}.bind(this));\n\t\t},\n\t\tupdateEdge: function(edge){\n\t\t\tedge._update(true);\n\t\t\t[edge.getOutgoingShapes(), edge.getIncomingShapes()].flatten().invoke(\"_update\", [true])\n\t\t},\n\t\texecuteAgain: function(){\n\t\t\tthis.changes.values().each(function(change){\n\t\t\t\t// Reset the dockers\n\t\t\t\tthis.removeAllDocker(change.edge);\n\t\t\t\tchange.dockerPositions.each(function(pos, i){\t\n\t\t\t\t\tif (i==0||i==change.dockerPositions.length-1){ return }\t\t\t\t\t\n\t\t\t\t\tvar docker = change.edge.createDocker(undefined, pos);\n\t\t\t\t\tdocker.bounds.centerMoveTo(pos);\n\t\t\t\t\tdocker.update();\n\t\t\t\t}.bind(this));\n\t\t\t\tthis.updateEdge(change.edge);\n\t\t\t}.bind(this));\n\t\t},\n\t\trollback: function(){\n\t\t\tthis.changes.values().each(function(change){\n\t\t\t\t// Reset the dockers\n\t\t\t\tthis.removeAllDocker(change.edge);\n\t\t\t\tchange.oldDockerPositions.each(function(pos, i){\t\n\t\t\t\t\tif (i==0||i==change.oldDockerPositions.length-1){ return }\t\t\t\t\t\n\t\t\t\t\tvar docker = change.edge.createDocker(undefined, pos);\n\t\t\t\t\tdocker.bounds.centerMoveTo(pos);\n\t\t\t\t\tdocker.update();\n\t\t\t\t}.bind(this));\n\t\t\t\tthis.updateEdge(change.edge);\n\t\t\t}.bind(this));\n\t\t},\n\t\tremoveAllDocker: function(edge){\n\t\t\tedge.dockers.slice(1, edge.dockers.length-1).each(function(docker){\n\t\t\t\tedge.removeDocker(docker);\n\t\t\t})\n\t\t}\n\t});\n\t\n}();\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespaces\n */\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\n\n/**\n * @classDescription Base class for Shapes.\n * @extends ORYX.Core.AbstractShape\n */\nORYX.Core.Shape = {\n\n\t/**\n\t * Constructor\n\t */\n\tconstruct: function(options, stencil, facade) {\n\t\t// call base class constructor\n\t\targuments.callee.$.construct.apply(this, arguments);\n\t\t\n\t\tthis.facade = facade;\n\t\tthis.dockers = [];\n\t\tthis.magnets = [];\n\t\t\n\t\tthis._defaultMagnet;\n\t\t\n\t\tthis.incoming = [];\n\t\tthis.outgoing = [];\n\t\t\n\t\tthis.nodes = [];\n\t\t\n\t\tthis._dockerChangedCallback = this._dockerChanged.bind(this);\n\t\t\n\t\t//Hash map for all labels. Labels are not treated as children of shapes.\n\t\tthis._labels = new Hash();\n\t\t\n\t\t// create SVG node\n\t\tthis.node = ORYX.Editor.graft(\"http://www.w3.org/2000/svg\",\n\t\t\tnull,\n\t\t\t['g', {id:\"svg-\" + this.resourceId},\n\t\t\t\t['g', {\"class\": \"stencils\"},\n\t\t\t\t\t['g', {\"class\": \"me\"}],\n\t\t\t\t\t['g', {\"class\": \"children\", style:\"overflow:hidden\"}],\n\t\t\t\t\t['g', {\"class\": \"edge\"}]\n\t\t\t\t],\n\t\t\t\t['g', {\"class\": \"controls\"},\n\t\t\t\t\t['g', {\"class\": \"dockers\"}],\n\t\t\t\t\t['g', {\"class\": \"magnets\"}]\t\t\t\t\n\t\t\t\t]\n\t\t\t]);\n\t},\n\n\t/**\n\t * If changed flag is set, refresh method is called.\n\t */\n\tupdate: function() {\n\t\t//if(this.isChanged) {\n\t\t\t//this.layout();\n\t\t//}\n\t},\n\t\n\t/**\n\t * !!!Not called from any sub class!!!\n\t */\n\t_update: function() {\n\n\t},\n\t\n\t/**\n\t * Calls the super class refresh method\n\t *  and updates the svg elements that are referenced by a property.\n\t */\n\trefresh: function() {\n\t\t//call base class refresh method\n\t\targuments.callee.$.refresh.apply(this, arguments);\n\t\t\n\t\tif(this.node.ownerDocument) {\n\t\t\t//adjust SVG to properties' values\n\t\t\tvar me = this;\n\t\t\tthis.propertiesChanged.each((function(propChanged) {\n\t\t\t\tif(propChanged.value) {\n\t\t\t\t\tvar prop = this.properties[propChanged.key];\n\t\t\t\t\tvar property = this.getStencil().property(propChanged.key);\n\t\t\t\t\tif (property != undefined) {\n\t\t\t\t\t\tthis.propertiesChanged[propChanged.key] = false;\n\t\n\t\t\t\t\t\t//handle choice properties\n\t\t\t\t\t\tif(property.type() == ORYX.CONFIG.TYPE_CHOICE) {\n\t\t\t\t\t\t\t//iterate all references to SVG elements\n\t\t\t\t\t\t\tproperty.refToView().each((function(ref) {\n\t\t\t\t\t\t\t\t//if property is referencing a label, update the label\n\t\t\t\t\t\t\t\tif(ref !== \"\") {\n\t\t\t\t\t\t\t\t\tvar label = this._labels[this.id + ref];\n\t\t\t\t\t\t\t\t\tif (label && property.item(prop)) {\n\t\t\t\t\t\t\t\t\t\tlabel.text(property.item(prop).title());\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}).bind(this));\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t//if the choice's items are referencing SVG elements\n\t\t\t\t\t\t\t// show the selected and hide all other referenced SVG\n\t\t\t\t\t\t\t// elements\n\t\t\t\t\t\t\tvar refreshedSvgElements = new Hash();\n\t\t\t\t\t\t\tproperty.items().each((function(item) {\n\t\t\t\t\t\t\t\titem.refToView().each((function(itemRef) {\n\t\t\t\t\t\t\t\t\tif(itemRef == \"\") { return; }\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tvar svgElem = this.node.ownerDocument.getElementById(this.id + itemRef);\n\t\t\n\t\t\t\t\t\t\t\t\tif(!svgElem) { return; }\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t/* Do not refresh the same svg element multiple times */\n\t\t\t\t\t\t\t\t\tif(!refreshedSvgElements[svgElem.id] || prop == item.value()) {\n\t\t\t\t\t\t\t\t\t\tsvgElem.setAttributeNS(null, 'display', ((prop == item.value()) ? 'inherit' : 'none'));\n\t\t\t\t\t\t\t\t\t\trefreshedSvgElements[svgElem.id] = svgElem;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t// Reload the href if there is an image-tag\n\t\t\t\t\t\t\t\t\tif(ORYX.Editor.checkClassType(svgElem, SVGImageElement)) {\n\t\t\t\t\t\t\t\t\t\tsvgElem.setAttributeNS('http://www.w3.org/1999/xlink', 'href', svgElem.getAttributeNS('http://www.w3.org/1999/xlink', 'href'));\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}).bind(this));\n\t\t\t\t\t\t\t}).bind(this));\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t} else { //handle properties that are not of type choice\n\t\t\t\t\t\t\t//iterate all references to SVG elements\n\t\t\t\t\t\t\tproperty.refToView().each((function(ref) {\n\t\t\t\t\t\t\t\t//if the property does not reference an SVG element,\n\t\t\t\t\t\t\t\t// do nothing\n\n\t\t\t\t\t\t\t\tif(ref === \"\") { return; }\n\n\t\t\t\t\t\t\t\tvar refId = this.id + ref;\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tif (property.type() === ORYX.CONFIG.TYPE_KISBPM_MULTIINSTANCE)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tif (ref === \"multiinstance\") {\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\tvar svgElemParallel = this.node.ownerDocument.getElementById(this.id + 'parallel');\n\t\t\t\t\t\t\t\t\t\tif(svgElemParallel) \n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tif (prop === 'Parallel')\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tsvgElemParallel.setAttributeNS(null, 'display', 'inherit');\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tsvgElemParallel.setAttributeNS(null, 'display', 'none');\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\t\n\t\t\t\t\t\t\t\t\t\tvar svgElemSequential = this.node.ownerDocument.getElementById(this.id + 'sequential');\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\tif(svgElemSequential) \n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tif (prop === 'Sequential')\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tsvgElemSequential.setAttributeNS(null, 'display', 'inherit');\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tsvgElemSequential.setAttributeNS(null, 'display', 'none');\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}\n\t\t\t\t\t\t\t\t\treturn;\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\telse if (property.type() === \"cancelactivity\")\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tvar svgElemFrame = this.node.ownerDocument.getElementById(this.id + 'frame');\n\t\t\t\t\t\t\t\t\tvar svgElemFrame2 = this.node.ownerDocument.getElementById(this.id + 'frame2');\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tif (prop === 'true')\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tsvgElemFrame.setAttributeNS(null, 'display', 'inherit');\n\t\t\t\t\t\t\t\t\t\tsvgElemFrame2.setAttributeNS(null, 'display', 'inherit');\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tsvgElemFrame.setAttributeNS(null, 'display', 'none');\n\t\t\t\t\t\t\t\t\t\tsvgElemFrame2.setAttributeNS(null, 'display', 'none');\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\n\t\t\t\t\t\t\t\t//get the SVG element\n\t\t\t\t\t\t\t\tvar svgElem = this.node.ownerDocument.getElementById(refId);\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t//if the SVG element can not be found\n\t\t\t\t\t\t\t\tif(!svgElem || !(svgElem.ownerSVGElement)) { \n\t\t\t\t\t\t\t\t\t//if the referenced SVG element is a SVGAElement, it cannot\n\t\t\t\t\t\t\t\t\t// be found with getElementById (Firefox bug).\n\t\t\t\t\t\t\t\t\t// this is a work around\n\t\t\t\t\t\t\t\t\tif(property.type() === ORYX.CONFIG.TYPE_URL || property.type() === ORYX.CONFIG.TYPE_DIAGRAM_LINK) {\n\t\t\t\t\t\t\t\t\t\tvar svgElems = this.node.ownerDocument.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'a');\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\tsvgElem = $A(svgElems).find(function(elem) {\n\t\t\t\t\t\t\t\t\t\t\treturn elem.getAttributeNS(null, 'id') === refId;\n\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\tif(!svgElem) { return; } \n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t//this.propertiesChanged[propChanged.key] = true;\n\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\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\n\t\t\t\t\t\t\t\tif (property.complexAttributeToView()) {\n\t\t\t\t\t\t\t\t\tvar label = this._labels[refId];\n\t\t\t\t\t\t\t\t\tif (label) {\n\t\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t    \tpropJson = prop.evalJSON();\n\t\t\t\t\t\t\t\t\t    \tvar value = propJson[property.complexAttributeToView()]\n\t\t\t\t\t\t\t\t\t    \tlabel.text(value ? value : prop);\n\t\t\t\t\t\t\t\t\t    } catch (e) {\n\t\t\t\t\t\t\t\t\t    \tlabel.text(prop);\n\t\t\t\t\t\t\t\t\t    }\n\t\t\t\t\t\t\t\t\t}\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\tswitch (property.type()) {\n\t\t\t\t\t\t\t\t\t\tcase ORYX.CONFIG.TYPE_BOOLEAN:\t\n\t\t\t\t\t\t\t\t\t\t    if (typeof prop == \"string\")\n\t\t\t\t\t\t\t\t\t\t\t\tprop = prop === \"true\"\n\t\t\n\t\t\t\t\t\t\t\t\t\t\tsvgElem.setAttributeNS(null, 'display', (!(prop === property.inverseBoolean())) ? 'inherit' : 'none');\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tcase ORYX.CONFIG.TYPE_COLOR:\n\t\t\t\t\t\t\t\t\t\t\tif(property.fill()) {\n\t\t\t\t\t\t\t\t\t\t\t\tif (svgElem.tagName.toLowerCase() === \"stop\"){\n\t\t\t\t\t\t\t\t\t\t\t\t\tif (prop){\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (property.lightness() &&  property.lightness() !== 1){\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tprop = ORYX.Utils.adjustLightness(prop, property.lightness());\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tsvgElem.setAttributeNS(null, \"stop-color\", prop);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Adjust stop color of the others\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (svgElem.parentNode.tagName.toLowerCase() === \"radialgradient\"){\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tORYX.Utils.adjustGradient(svgElem.parentNode, svgElem);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t// If there is no value, set opaque\n\t\t\t\t\t\t\t\t\t\t\t\t\tif (svgElem.parentNode.tagName.toLowerCase() === \"radialgradient\"){\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t$A(svgElem.parentNode.getElementsByTagName('stop')).each(function(stop){\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstop.setAttributeNS(null, \"stop-opacity\", prop ? stop.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'default-stop-opacity') || 1 : 0);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}.bind(this))\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\t\tsvgElem.setAttributeNS(null, 'fill', prop);\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tif(property.stroke()) {\n\t\t\t\t\t\t\t\t\t\t\t\tsvgElem.setAttributeNS(null, 'stroke', prop);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tcase ORYX.CONFIG.TYPE_STRING:\n\t\t\t\t\t\t\t\t\t\t\tvar label = this._labels[refId];\n\t\t\t\t\t\t\t\t\t\t\tif (label) {\n\t\t\t\t\t\t\t\t\t\t\t\tlabel.text(prop);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tcase ORYX.CONFIG.TYPE_EXPRESSION:\n\t\t\t\t\t\t\t\t\t\t\tvar label = this._labels[refId];\n\t\t\t\t\t\t\t\t\t\t\tif (label) {\n\t\t\t\t\t\t\t\t\t\t\t\tlabel.text(prop);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tcase ORYX.CONFIG.TYPE_DATASOURCE:\n\t\t\t\t\t\t\t\t\t\t\tvar label = this._labels[refId];\n\t\t\t\t\t\t\t\t\t\t\tif (label) {\n\t\t\t\t\t\t\t\t\t\t\t\tlabel.text(prop);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tbreak;\t\n\t\t\t\t\t\t\t\t\t\tcase ORYX.CONFIG.TYPE_INTEGER:\n\t\t\t\t\t\t\t\t\t\t\tvar label = this._labels[refId];\n\t\t\t\t\t\t\t\t\t\t\tif (label) {\n\t\t\t\t\t\t\t\t\t\t\t\tlabel.text(prop);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tcase ORYX.CONFIG.TYPE_FLOAT:\n\t\t\t\t\t\t\t\t\t\t\tif(property.fillOpacity()) {\n\t\t\t\t\t\t\t\t\t\t\t\tsvgElem.setAttributeNS(null, 'fill-opacity', prop);\n\t\t\t\t\t\t\t\t\t\t\t} \n\t\t\t\t\t\t\t\t\t\t\tif(property.strokeOpacity()) {\n\t\t\t\t\t\t\t\t\t\t\t\tsvgElem.setAttributeNS(null, 'stroke-opacity', prop);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tif(!property.fillOpacity() && !property.strokeOpacity()) {\n\t\t\t\t\t\t\t\t\t\t\t\tvar label = this._labels[refId];\n\t\t\t\t\t\t\t\t\t\t\t\tif (label) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tlabel.text(prop);\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\tcase ORYX.CONFIG.TYPE_FORM_LINK:\n\t  \t\t\t\t\t\t\t\t\t\tif (ref == \"pimg\") {\n\t  \t\t\t\t\t\t\t\t\t\t\tvar onclickAttr = svgElem.getAttributeNodeNS('', 'onclick');\n\t  \t\t\t\t\t\t\t\t\t\t\tif(onclickAttr) {\n\t  \t\t\t\t\t\t\t\t\t\t\t\tif(prop && (\"\" + prop).length > 0) {\n\t  \t\t\t\t\t\t\t\t\t\t\t\t\tonclickAttr.textContent = \"window.location = '../service/editor?id=\" + prop + \"_form'\";\n\t  \t\t\t\t\t\t\t    \t   \t\t\t} else {\n\t  \t\t\t\t\t\t\t    \t   \t\t\t\tnewFormFacade = this.facade;\n\t  \t\t\t\t\t\t\t    \t   \t\t\t\tonclickAttr.textContent = \"displayNewFormDialog('\" + this.resourceId + \"');\";\n\t  \t\t\t\t\t\t\t    \t\t        }\n\t  \t\t\t\t\t\t\t\t\t\t\t}\n\t  \t\t\t\t\t\t\t\t\t\t} else if (ref == \"linkIndicator\") {\n\t  \t\t\t\t\t\t\t\t\t\t\tif (prop && prop.length > 0) {\n\t  \t\t\t\t\t\t\t\t\t\t\t\tsvgElem.setAttributeNS(null, 'display', 'inherit');\n\t  \t\t\t\t\t\t\t\t\t\t\t} else {\n\t  \t\t\t\t\t\t\t\t\t\t\t\tsvgElem.setAttributeNS(null, 'display', 'none');\n\t  \t\t\t\t\t\t\t\t\t\t\t}\n\t  \t\t\t\t\t\t\t\t\t\t}\n\t  \t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tcase ORYX.CONFIG.TYPE_URL:\n\t\t\t\t\t\t\t\t\t\tcase ORYX.CONFIG.TYPE_DIAGRAM_LINK:\n\t\t\t\t\t\t\t\t\t\t\t//TODO what is the dafault path?\n\t\t\t\t\t\t\t\t\t\t\tvar hrefAttr = svgElem.getAttributeNodeNS('http://www.w3.org/1999/xlink', 'xlink:href');\n\t\t\t\t\t\t\t\t\t\t\tif(hrefAttr) {\n\t\t\t\t\t\t\t\t\t\t\t\threfAttr.textContent = prop;\n\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\tsvgElem.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', prop);\n\t\t\t\t\t\t\t\t\t\t\t}\t\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\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}).bind(this));\n\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\t\n\t\t\t\t}\n\t\t\t}).bind(this));\n\t\t\t\n\t\t\t//update labels\n\t\t\tthis._labels.values().each(function(label) {\n\t\t\t\tlabel.update();\n\t\t\t});\n\t\t}\n\t},\n\t\n\tlayout: function() {\n\t\t//this.getStencil().layout(this)\n\t\tvar layoutEvents = this.getStencil().layout()\n\t\tif (layoutEvents) {\n\t\t\tlayoutEvents.each(function(event) {\n\t\t\t\t\n\t\t\t\t// setup additional attributes\n\t\t\t\tevent.shape = this;\n\t\t\t\tevent.forceExecution = true;\n\t\t\t\t\n\t\t\t\t// do layouting\n\t\t\t\tthis._delegateEvent(event);\n\t\t\t}.bind(this))\n\t\t\t\n\t\t}\n\t},\n\t\n\t/**\n\t * Returns an array of Label objects.\n\t */\n\tgetLabels: function() {\n\t\treturn this._labels.values();\n\t},\n\t\n\t/**\n\t * Returns the label for a given ref\n\t * @return {ORYX.Core.Label} Returns null if there is no label\n\t */\n\tgetLabel: function(ref){\n\t\tif (!ref){\n\t\t\treturn null;\n\t\t}\n\t\treturn (this._labels.find(function(o){\n\t\t\t\treturn o.key.endsWith(ref);\n\t\t\t})||{}).value || null;\n\t},\n\t\n\t/**\n\t * Hides all related labels\n\t * \n\t */\n\thideLabels: function(){\n\t\tthis.getLabels().invoke(\"hide\");\n\t},\n\n\t/**\n\t * Shows all related labels\n\t * \n\t */\n\tshowLabels: function(){\n\t\tvar labels = this.getLabels();\n\t\tlabels.invoke(\"show\");\n\t\tlabels.each(function(label) {\n\t\t\t\tlabel.update();\n\t\t});\n\t},\n\t\n\tsetOpacity: function(value, animate){\n\t\t\n\t\tvalue = Math.max(Math.min((typeof value == \"number\" ? value : 1.0), 1.0), 0.0);\n\t\t\t\t\n\t\tif (value !== 1.0){\n\t\t\tvalue = String(value);\n\t\t\tthis.node.setAttributeNS(null, \"fill-opacity\", value)\n\t\t\tthis.node.setAttributeNS(null, \"stroke-opacity\", value)\n\t\t} else {\n\t\t\tthis.node.removeAttributeNS(null, \"fill-opacity\");\n\t\t\tthis.node.removeAttributeNS(null, \"stroke-opacity\");\n\t\t}\n\t},\n\t\n\t/**\n\t * Returns an array of dockers of this object.\n\t */\n\tgetDockers: function() {\n\t\treturn this.dockers;\n\t},\n\t\n\tgetMagnets: function() {\n\t\treturn this.magnets;\n\t},\n\t\n\tgetDefaultMagnet: function() {\n\t\tif(this._defaultMagnet) {\n\t\t\treturn this._defaultMagnet;\n\t\t} else if (this.magnets.length > 0) {\n\t\t\treturn this.magnets[0];\n\t\t} else {\n\t\t\treturn undefined;\n\t\t}\n\t},\n\n\tgetParentShape: function() {\n\t\treturn this.parent;\n\t},\n\t\n\tgetIncomingShapes: function(iterator) {\n\t\tif(iterator) {\n\t\t\tthis.incoming.each(iterator);\n\t\t}\n\t\treturn this.incoming;\n\t},\n\t\n\tgetIncomingNodes: function(iterator) {\n        return this.incoming.select(function(incoming){\n            var isNode = (incoming instanceof ORYX.Core.Node);\n            if(isNode && iterator) iterator(incoming);\n            return isNode;\n        });\n    },\n\t\n\t\n\tgetOutgoingShapes: function(iterator) {\n\t\tif(iterator) {\n\t\t\tthis.outgoing.each(iterator);\n\t\t}\n\t\treturn this.outgoing;\n\t},\n    \n    getOutgoingNodes: function(iterator) {\n        return this.outgoing.select(function(out){\n            var isNode = (out instanceof ORYX.Core.Node);\n            if(isNode && iterator) iterator(out);\n            return isNode;\n        });\n    },\n\t\n\tgetAllDockedShapes: function(iterator) {\n\t\tvar result = this.incoming.concat(this.outgoing);\n\t\tif(iterator) {\n\t\t\tresult.each(iterator);\n\t\t}\n\t\treturn result\n\t},\n\n\tgetCanvas: function() {\n\t\tif(this.parent instanceof ORYX.Core.Canvas) {\n\t\t\treturn this.parent;\n\t\t} else if(this.parent instanceof ORYX.Core.Shape) {\n\t\t\treturn this.parent.getCanvas();\n\t\t} else {\n\t\t\treturn undefined;\n\t\t}\n\t},\n\t\n\t/**\n\t * \n\t * @param {Object} deep\n\t * @param {Object} iterator\n\t */\n\tgetChildNodes: function(deep, iterator) {\n\t\tif(!deep && !iterator) {\n\t\t\treturn this.nodes.clone();\n\t\t} else {\n\t\t\tvar result = [];\n\t\t\tthis.nodes.each(function(uiObject) {\n\t\t\t\tif(!uiObject.isVisible){return}\n\t\t\t\tif(iterator) {\n\t\t\t\t\titerator(uiObject);\n\t\t\t\t}\n\t\t\t\tresult.push(uiObject);\n\t\t\t\t\n\t\t\t\tif(deep && uiObject instanceof ORYX.Core.Shape) {\n\t\t\t\t\tresult = result.concat(uiObject.getChildNodes(deep, iterator));\n\t\t\t\t}\n\t\t\t});\n\t\n\t\t\treturn result;\n\t\t}\n\t},\n\t\n\t/**\n\t * Overrides the UIObject.add method. Adds uiObject to the correct sub node.\n\t * @param {UIObject} uiObject\n\t * @param {Number} index\n\t */\n\tadd: function(uiObject, index, silent) {\n\t\t//parameter has to be an UIObject, but\n\t\t// must not be an Edge.\n\t\tif(uiObject instanceof ORYX.Core.UIObject \n\t\t\t&& !(uiObject instanceof ORYX.Core.Edge)) {\n\t\t\t\n\t\t\tif (!(this.children.member(uiObject))) {\n\t\t\t\t//if uiObject is child of another parent, remove it from that parent.\n\t\t\t\tif(uiObject.parent) {\n\t\t\t\t\tuiObject.parent.remove(uiObject, true);\n\t\t\t\t}\n\n\t\t\t\t//add uiObject to this Shape\n\t\t\t\tif(index != undefined)\n\t\t\t\t\tthis.children.splice(index, 0, uiObject);\n\t\t\t\telse\n\t\t\t\t\tthis.children.push(uiObject);\n\n\t\t\t\t//set parent reference\n\t\t\t\tuiObject.parent = this;\n\n\t\t\t\t//add uiObject.node to this.node depending on the type of uiObject\n\t\t\t\tvar parent;\n\t\t\t\tif(uiObject instanceof ORYX.Core.Node) {\n\t\t\t\t\tparent = this.node.childNodes[0].childNodes[1];\n\t\t\t\t\tthis.nodes.push(uiObject);\n\t\t\t\t} else if(uiObject instanceof ORYX.Core.Controls.Control) {\n\t\t\t\t\tvar ctrls = this.node.childNodes[1];\n\t\t\t\t\tif(uiObject instanceof ORYX.Core.Controls.Docker) {\n\t\t\t\t\t\tparent = ctrls.childNodes[0];\n\t\t\t\t\t\tif (this.dockers.length >= 2){\n\t\t\t\t\t\t\tthis.dockers.splice(index!==undefined?Math.min(index, this.dockers.length-1):this.dockers.length-1, 0, uiObject);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.dockers.push(uiObject);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if(uiObject instanceof ORYX.Core.Controls.Magnet) {\n\t\t\t\t\t\tparent = ctrls.childNodes[1];\n\t\t\t\t\t\tthis.magnets.push(uiObject);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tparent = ctrls;\n\t\t\t\t\t}\n\t\t\t\t} else {\t//UIObject\n\t\t\t\t\tparent = this.node;\n\t\t\t\t}\n\n\t\t\t\tif(index != undefined && index < parent.childNodes.length)\n\t\t\t\t\tuiObject.node = parent.insertBefore(uiObject.node, parent.childNodes[index]);\n\t\t\t\telse\n\t\t\t\t\tuiObject.node = parent.appendChild(uiObject.node);\n\t\t\t\t\t\n\t\t\t\tthis._changed();\n\t\t\t\t//uiObject.bounds.registerCallback(this._changedCallback);\n\t\t\t\t\n\t\t\t\t\n\t\t\t\tif(this.eventHandlerCallback && silent !== true)\n\t\t\t\t\tthis.eventHandlerCallback({type:ORYX.CONFIG.EVENT_SHAPEADDED,shape:uiObject})\n\t\t\t\t\t\n\t\t\t} else {\n\n\t\t\t\tORYX.Log.warn(\"add: ORYX.Core.UIObject is already a child of this object.\");\n\t\t\t}\n\t\t} else {\n\n\t\t\tORYX.Log.warn(\"add: Parameter is not of type ORYX.Core.UIObject.\");\n\t\t}\n\t},\n\n\t/**\n\t * Overrides the UIObject.remove method. Removes uiObject.\n\t * @param {UIObject} uiObject\n\t */\n\tremove: function(uiObject, silent) {\n\t\t//if uiObject is a child of this object, remove it.\n\t\tif (this.children.member(uiObject)) {\n\t\t\t//remove uiObject from children\n\t\t\tvar parent = uiObject.parent;\n\n\t\t\tthis.children = this.children.without(uiObject);\n\n\t\t\t//delete parent reference of uiObject\n\t\t\tuiObject.parent = undefined;\n\n\t\t\t//delete uiObject.node from this.node\n\t\t\tif(uiObject instanceof ORYX.Core.Shape) {\n\t\t\t\tif(uiObject instanceof ORYX.Core.Edge) {\n\t\t\t\t\tuiObject.removeMarkers();\n\t\t\t\t\tuiObject.node = this.node.childNodes[0].childNodes[2].removeChild(uiObject.node);\n\t\t\t\t} else {\n\t\t\t\t\tuiObject.node = this.node.childNodes[0].childNodes[1].removeChild(uiObject.node);\n\t\t\t\t\tthis.nodes = this.nodes.without(uiObject);\n\t\t\t\t}\n\t\t\t} else if(uiObject instanceof ORYX.Core.Controls.Control) {\n\t\t\t\tif (uiObject instanceof ORYX.Core.Controls.Docker) {\n\t\t\t\t\tuiObject.node = this.node.childNodes[1].childNodes[0].removeChild(uiObject.node);\n\t\t\t\t\tthis.dockers = this.dockers.without(uiObject);\n\t\t\t\t} else if (uiObject instanceof ORYX.Core.Controls.Magnet) {\n\t\t\t\t\tuiObject.node = this.node.childNodes[1].childNodes[1].removeChild(uiObject.node);\n\t\t\t\t\tthis.magnets = this.magnets.without(uiObject);\n\t\t\t\t} else {\n\t\t\t\t\tuiObject.node = this.node.childNodes[1].removeChild(uiObject.node);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif(this.eventHandlerCallback && silent !== true)\n\t\t\t\tthis.eventHandlerCallback({type: ORYX.CONFIG.EVENT_SHAPEREMOVED, shape: uiObject, parent: parent});\n\t\t\t\n\t\t\tthis._changed();\n\t\t\t//uiObject.bounds.unregisterCallback(this._changedCallback);\n\t\t} else {\n\n\t\t\tORYX.Log.warn(\"remove: ORYX.Core.UIObject is not a child of this object.\");\n\t\t}\n\t},\n\t\n\t/**\n\t * Calculate the Border Intersection Point between two points\n\t * @param {PointA}\n\t * @param {PointB}\n\t */\n\tgetIntersectionPoint: function() {\n\t\t\t\n\t\tvar pointAX, pointAY, pointBX, pointBY;\n\t\t\n\t\t// Get the the two Points\t\n\t\tswitch(arguments.length) {\n\t\t\tcase 2:\n\t\t\t\tpointAX = arguments[0].x;\n\t\t\t\tpointAY = arguments[0].y;\n\t\t\t\tpointBX = arguments[1].x;\n\t\t\t\tpointBY = arguments[1].y;\n\t\t\t\tbreak;\n\t\t\tcase 4:\n\t\t\t\tpointAX = arguments[0];\n\t\t\t\tpointAY = arguments[1];\n\t\t\t\tpointBX = arguments[2];\n\t\t\t\tpointBY = arguments[3];\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthrow \"getIntersectionPoints needs two or four arguments\";\n\t\t}\n\t\t\n\t\t\n\t\t\n\t\t// Defined an include and exclude point\n\t\tvar includePointX, includePointY, excludePointX, excludePointY;\n\n\t\tvar bounds = this.absoluteBounds();\n\t\t\n\t\tif(this.isPointIncluded(pointAX, pointAY, bounds)){\n\t\t\tincludePointX = pointAX;\n\t\t\tincludePointY = pointAY;\n\t\t} else {\n\t\t\texcludePointX = pointAX;\n\t\t\texcludePointY = pointAY;\n\t\t}\n\n\t\tif(this.isPointIncluded(pointBX, pointBY, bounds)){\n\t\t\tincludePointX = pointBX;\n\t\t\tincludePointY = pointBY;\n\t\t} else {\n\t\t\texcludePointX = pointBX;\n\t\t\texcludePointY = pointBY;\n\t\t}\n\t\t\t\t\n\t\t// If there is no inclue or exclude Shape, than return\n\t\tif(!includePointX || !includePointY || !excludePointX || !excludePointY) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tvar midPointX = 0;\n\t\tvar midPointY = 0;\t\t\n\t\t\n\t\tvar refPointX, refPointY;\n\t\t\n\t\tvar minDifferent = 1;\n\t\t// Get the UpperLeft and LowerRight\n\t\t//var ul = bounds.upperLeft();\n\t\t//var lr = bounds.lowerRight();\n\t\t\n\t\tvar i = 0;\n\t\t\n\t\twhile(true) {\n\t\t\t// Calculate the midpoint of the current to points\t\n\t\t\tvar midPointX = Math.min(includePointX, excludePointX) + ((Math.max(includePointX, excludePointX) - Math.min(includePointX, excludePointX)) / 2.0);\n\t\t\tvar midPointY = Math.min(includePointY, excludePointY) + ((Math.max(includePointY, excludePointY) - Math.min(includePointY, excludePointY)) / 2.0);\n\t\t\t\n\t\t\t\n\t\t\t// Set the new midpoint by the means of the include of the bounds\n\t\t\tif(this.isPointIncluded(midPointX, midPointY, bounds)){\n\t\t\t\tincludePointX = midPointX;\n\t\t\t\tincludePointY = midPointY;\n\t\t\t} else {\n\t\t\t\texcludePointX = midPointX;\n\t\t\t\texcludePointY = midPointY;\n\t\t\t}\t\t\t\n\t\t\t\n\t\t\t// Calc the length of the line\n\t\t\tvar length = Math.sqrt(Math.pow(includePointX - excludePointX, 2) + Math.pow(includePointY - excludePointY, 2))\n\t\t\t// Calc a point one step from the include point\n\t\t\trefPointX = includePointX + ((excludePointX - includePointX) / length),\n\t\t\trefPointY = includePointY + ((excludePointY - includePointY) / length)\n\t\t\t\t\t\n\t\t\t\n\t\t\t// If the reference point not in the bounds, break\n\t\t\tif(!this.isPointIncluded(refPointX, refPointY, bounds)) {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\n\t\t}\n\n\t\t// Return the last includepoint\n\t\treturn {x:refPointX , y:refPointY};\n\t},\n\n   \n    \n    /**\n     * Calculate if the point is inside the Shape\n     * @param {PointX}\n     * @param {PointY} \n     */\n    isPointIncluded: function(){\n\t\treturn  false\n\t},\n\n\t/**\n\t * Returns TRUE if the given node\n\t * is a child node of the shapes node\n\t * @param {Element} node\n\t * @return {Boolean}\n\t *\n\t */\n\tcontainsNode: function(node){\n\t\tvar me = this.node.firstChild.firstChild;\n\t\twhile(node){\n\t\t\tif (node == me){\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tnode = node.parentNode;\n\t\t}\n\t\treturn false\n\t},\n    \n    /**\n     * Calculate if the point is over an special offset area\n     * @param {Point}\n     */\n    isPointOverOffset: function(){\n\t\treturn  this.isPointIncluded.apply( this , arguments )\n\t},\n\t\t\n\t_dockerChanged: function() {\n\n\t},\n\t\t\n\t/**\n\t * Create a Docker for this Edge\n\t *\n\t */\n\tcreateDocker: function(index, position) {\n\t\tvar docker = new ORYX.Core.Controls.Docker({eventHandlerCallback: this.eventHandlerCallback});\n\t\tdocker.bounds.registerCallback(this._dockerChangedCallback);\n\t\tif (position) {\n\t\t\tdocker.bounds.centerMoveTo(position);\n\t\t}\n\t\tthis.add(docker, index);\n\t\t\n\t\treturn docker\n\t},\n\n\t/**\n\t * Get the serialized object\n\t * return Array with hash-entrees (prefix, name, value)\n\t * Following values will given:\n\t * \t\tBounds\n\t * \t\tOutgoing Shapes\n\t * \t\tParent\n\t */\n\tserialize: function() {\n\t\tvar serializedObject = arguments.callee.$.serialize.apply(this);\n\n\t\t// Add the bounds\n\t\tserializedObject.push({name: 'bounds', prefix:'oryx', value: this.bounds.serializeForERDF(), type: 'literal'});\n\n\t\t// Add the outgoing shapes\n\t\tthis.getOutgoingShapes().each((function(followingShape){\n\t\t\tserializedObject.push({name: 'outgoing', prefix:'raziel', value: '#'+ERDF.__stripHashes(followingShape.resourceId), type: 'resource'});\t\t\t\n\t\t}).bind(this));\n\n\t\t// Add the parent shape, if the parent not the canvas\n\t\t//if(this.parent instanceof ORYX.Core.Shape){\n\t\t\tserializedObject.push({name: 'parent', prefix:'raziel', value: '#'+ERDF.__stripHashes(this.parent.resourceId), type: 'resource'});\t\n\t\t//}\t\t\t\n\t\t\n\t\treturn serializedObject;\n\t},\n\t\t\n\t\t\n\tdeserialize: function(serialize, json){\n\t\targuments.callee.$.deserialize.apply(this, arguments);\n\t\t\n\t\t// Set the Bounds\n\t\tvar bounds = serialize.find(function(ser){ return 'oryx-bounds' === (ser.prefix+\"-\"+ser.name) });\n\t\tif (bounds) {\n\t\t\tvar b = bounds.value.replace(/,/g, \" \").split(\" \").without(\"\");\n\t\t\tif (this instanceof ORYX.Core.Edge) {\n\t\t\t\tif (!this.dockers.first().isChanged)\n\t\t\t\t\tthis.dockers.first().bounds.centerMoveTo(parseFloat(b[0]), parseFloat(b[1]));\n\t\t\t\tif (!this.dockers.last().isChanged)\n\t\t\t\t\tthis.dockers.last().bounds.centerMoveTo(parseFloat(b[2]), parseFloat(b[3]));\n\t\t\t} else {\n\t\t\t\tthis.bounds.set(parseFloat(b[0]), parseFloat(b[1]), parseFloat(b[2]), parseFloat(b[3]));\n\t\t\t}\n\t\t}\n\t\t\n\t\tif (json && json.labels instanceof Array){\n\t\t\tjson.labels.each(function(slabel){\n\t\t\t\tvar label = this.getLabel(slabel.ref);\n\t\t\t\tif (label){\n\t\t\t\t\tlabel.deserialize(slabel, this);\n\t\t\t\t}\n\t\t\t}.bind(this))\n\t\t}\n\t},\n\t\n\ttoJSON: function(){\n\t\tvar json = arguments.callee.$.toJSON.apply(this, arguments);\n\t\t\n\t\tvar labels = [], id = this.id;\n\t\tthis._labels.each(function(obj){\n\t\t\tvar slabel = obj.value.serialize();\n\t\t\tif (slabel){\n\t\t\t\tslabel.ref = obj.key.replace(id, '');\n\t\t\t\tlabels.push(slabel);\n\t\t\t}\n\t\t});\n\t\t\n\t\tif (labels.length > 0){\n\t\t\tjson.labels = labels;\n\t\t}\n\t\treturn json;\n\t},\n\n\t\t\n\t/**\n\t * Private methods.\n\t */\n\n\t/**\n\t * Child classes have to overwrite this method for initializing a loaded\n\t * SVG representation.\n\t * @param {SVGDocument} svgDocument\n\t */\n\t_init: function(svgDocument) {\n\t\t//adjust ids\n\t\tthis._adjustIds(svgDocument, 0);\n\t},\n\n\t_adjustIds: function(element, idIndex) {\n\t\tif(element instanceof Element) {\n\t\t\tvar eid = element.getAttributeNS(null, 'id');\n\t\t\tif(eid && eid !== \"\") {\n\t\t\t\telement.setAttributeNS(null, 'id', this.id + eid);\n\t\t\t} else {\n\t\t\t\telement.setAttributeNS(null, 'id', this.id + \"_\" + this.id + \"_\" + idIndex);\n\t\t\t\tidIndex++;\n\t\t\t}\n\t\t\t\n\t\t\t// Replace URL in fill attribute\n\t\t\tvar fill = element.getAttributeNS(null, 'fill');\n\t\t\tif (fill&&fill.include(\"url(#\")){\n\t\t\t\tfill = fill.replace(/url\\(#/g, 'url(#'+this.id);\n\t\t\t\telement.setAttributeNS(null, 'fill', fill);\n\t\t\t}\n\t\t\t\n\t\t\tif(element.hasChildNodes()) {\n\t\t\t\tfor(var i = 0; i < element.childNodes.length; i++) {\n\t\t\t\t\tidIndex = this._adjustIds(element.childNodes[i], idIndex);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn idIndex;\n\t},\n\n\ttoString: function() { return \"ORYX.Core.Shape \" + this.getId() }\n};\nORYX.Core.Shape = ORYX.Core.AbstractShape.extend(ORYX.Core.Shape);/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespaces\n */\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\nif(!ORYX.Core.Controls) {ORYX.Core.Controls = {};}\n\n\n/**\n * @classDescription Abstract base class for all Controls.\n */\nORYX.Core.Controls.Control = ORYX.Core.UIObject.extend({\n\t\n\ttoString: function() { return \"Control \" + this.id; }\n });/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespaces\n */\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\nif(!ORYX.Core.Controls) {ORYX.Core.Controls = {};}\n\n\n/**\n * @classDescription Represents a movable docker that can be bound to a shape. Dockers are used\n * for positioning shape objects.\n * @extends {Control}\n * \n * TODO absoluteXY und absoluteCenterXY von einem Docker liefern falsche Werte!!!\n */\nORYX.Core.Controls.Docker = ORYX.Core.Controls.Control.extend({\n\t/**\n\t * Constructor\n\t */\n\tconstruct: function() {\n\t\targuments.callee.$.construct.apply(this, arguments);\n\t\t\n\t\tthis.isMovable = true;\t\t\t\t// Enables movability\n\t\tthis.bounds.set(0, 0, 16, 16);\t\t// Set the bounds\n\t\tthis.referencePoint = undefined;\t\t// Refrenzpoint \n\t\tthis._dockedShapeBounds = undefined;\t\t\n\t\tthis._dockedShape = undefined;\n\t\tthis._oldRefPoint1 = undefined;\n\t\tthis._oldRefPoint2 = undefined;\n\t\t\n\t\t//this.anchors = [];\n\t\tthis.anchorLeft;\n\t\tthis.anchorRight;\n\t\tthis.anchorTop;\n\t\tthis.anchorBottom;\n\n\t\tthis.node = ORYX.Editor.graft(\"http://www.w3.org/2000/svg\",\n\t\t\tnull,\n\t\t\t['g']);\n\n\t\t// The DockerNode reprasentation\n\t\tthis._dockerNode = ORYX.Editor.graft(\"http://www.w3.org/2000/svg\",\n\t\t\tthis.node,\n\t\t\t['g', {\"pointer-events\":\"all\"},\n\t\t\t\t\t['circle', {cx:\"8\", cy:\"8\", r:\"8\", stroke:\"none\", fill:\"none\"}],\n\t\t\t\t\t['circle', {cx:\"8\", cy:\"8\", r:\"3\", stroke:\"black\", fill:\"red\", \"stroke-width\":\"1\"}]\n\t\t\t\t]);\n\t\t\t\n\t\t// The ReferenzNode reprasentation\t\n\t\tthis._referencePointNode = ORYX.Editor.graft(\"http://www.w3.org/2000/svg\",\n\t\t\tthis.node,\t\n\t\t\t['g', {\"pointer-events\":\"none\"},\n\t\t\t\t['circle', {cx: this.bounds.upperLeft().x, cy: this.bounds.upperLeft().y, r: 3, fill:\"red\", \"fill-opacity\":0.4}]]);\n\n\t\t// Hide the Docker\n\t\tthis.hide();\n\t\t\n\t\t//Add to the EventHandler\n\t\tthis.addEventHandlers(this._dockerNode);\n\n\t\t// Buffer the Update Callback for un-/register on Event-Handler \n\t\tthis._updateCallback = this._changed.bind(this);\n\t},\n\t\n\tupdate: function() {\n\t\t// If there have an DockedShape\t\n\t\tif(this._dockedShape) {\n\t\t\tif(this._dockedShapeBounds && this._dockedShape instanceof ORYX.Core.Node) {\n\t\t\t\t// Calc the delta of width and height of the lastBounds and the current Bounds\n\t\t\t\tvar dswidth = this._dockedShapeBounds.width();\n\t\t\t\tvar dsheight = this._dockedShapeBounds.height();\n\t\t\t\tif(!dswidth)\n\t\t\t\t\tdswidth = 1;\n\t\t\t\tif(!dsheight)\n\t\t\t\t\tdsheight = 1;\t\n\t\t\t\tvar widthDelta = \tthis._dockedShape.bounds.width() \t/ dswidth;\n\t\t\t\tvar heightDelta = \tthis._dockedShape.bounds.height() \t/ dsheight;\n\t\t\t\t\n\t\t\t\t// If there is an different\n\t\t\t\tif(widthDelta !== 1.0 || heightDelta !== 1.0) {\n\t\t\t\t\t// Set the delta\n\t\t\t\t\tthis.referencePoint.x *= widthDelta;\n\t\t\t\t\tthis.referencePoint.y *= heightDelta;\n\t\t\t\t}\n\t\n\t\t\t\t// Clone these bounds\n\t\t\t\tthis._dockedShapeBounds = this._dockedShape.bounds.clone();\t\t\t\t\n\t\t\t}\n\t\t\t\n\t\t\t// Get the first and the last Docker of the parent Shape\n\t\t\tvar dockerIndex = this.parent.dockers.indexOf(this)\n\t\t\tvar dock1 = this;\n\t\t\tvar dock2 = this.parent.dockers.length > 1 ? \n\t\t\t\t\t\t\t(dockerIndex === 0?\t\t\t\t\t\t\t// If there is the first element\n\t\t\t\t\t\t\t \tthis.parent.dockers[dockerIndex + 1]:\t// then take the next docker\n\t\t\t\t\t\t\t\tthis.parent.dockers[dockerIndex - 1]):  // if not, then take the docker before\n\t\t\t\t\t\t\tundefined;\n\t\t\t\n\t\t\t// Calculate the first absolute Refenzpoint \n\t\t\tvar absoluteReferenzPoint1 = dock1.getDockedShape() ? \n\t\t\t\tdock1.getAbsoluteReferencePoint() : \n\t\t\t\tdock1.bounds.center();\n\n\t\t\t// Calculate the last absolute Refenzpoint \n\t\t\tvar absoluteReferenzPoint2 = dock2 && dock2.getDockedShape() ? \n\t\t\t\tdock2.getAbsoluteReferencePoint() : \n\t\t\t\tdock2 ? \n\t\t\t\t\tdock2.bounds.center() :\n\t\t\t\t\tundefined;\n\n\t\t\t// If there is no last absolute Referenzpoint\t\t\n\t\t\tif(!absoluteReferenzPoint2) {\n\t\t\t\t// Calculate from the middle of the DockedShape\n\t\t\t\tvar center = this._dockedShape.absoluteCenterXY();\n\t\t\t\tvar minDimension = this._dockedShape.bounds.width() * this._dockedShape.bounds.height(); \n\t\t\t\tabsoluteReferenzPoint2 = {\n\t\t\t\t\tx: absoluteReferenzPoint1.x + (center.x - absoluteReferenzPoint1.x) * -minDimension,\n\t\t\t\t\ty: absoluteReferenzPoint1.y + (center.y - absoluteReferenzPoint1.y) * -minDimension\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tvar newPoint = undefined;\n\t\t\t\n\t\t\t/*if (!this._oldRefPoint1 || !this._oldRefPoint2 ||\n\t\t\t\tabsoluteReferenzPoint1.x !== this._oldRefPoint1.x ||\n\t\t\t\tabsoluteReferenzPoint1.y !== this._oldRefPoint1.y ||\n\t\t\t\tabsoluteReferenzPoint2.x !== this._oldRefPoint2.x ||\n\t\t\t\tabsoluteReferenzPoint2.y !== this._oldRefPoint2.y) {*/\n\t\t\t\t\n\t\t\t\t// Get the new point for the Docker, calucalted by the intersection point of the Shape and the two points\n\t\t\t\tnewPoint = this._dockedShape.getIntersectionPoint(absoluteReferenzPoint1, absoluteReferenzPoint2);\n\t\t\t\t\n\t\t\t\t// If there is new point, take the referencepoint as the new point\n\t\t\t\tif(!newPoint) {\n\t\t\t\t\tnewPoint = this.getAbsoluteReferencePoint();\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif(this.parent && this.parent.parent) {\n\t\t\t\t\tvar grandParentPos = this.parent.parent.absoluteXY();\n\t\t\t\t\tnewPoint.x -= grandParentPos.x;\n\t\t\t\t\tnewPoint.y -= grandParentPos.y;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// Set the bounds to the new point\n\t\t\t\tthis.bounds.centerMoveTo(newPoint)\n\t\t\t\n\t\t\t\tthis._oldRefPoint1 = absoluteReferenzPoint1;\n\t\t\t\tthis._oldRefPoint2 = absoluteReferenzPoint2;\n\t\t\t} \n\t\t\t/*else {\n\t\t\t\tnewPoint = this.bounds.center();\n\t\t\t}*/\n\t\t\t\n\t\t\t\n\t//\t}\n\t\t\n\t\t// Call the super class\n\t\targuments.callee.$.update.apply(this, arguments);\n\t},\n\n\t/**\n\t * Calls the super class refresh method and updates the view of the docker.\n\t */\n\trefresh: function() {\n\t\targuments.callee.$.refresh.apply(this, arguments);\n\t\t\n\t\t// Refresh the dockers node\n\t\tvar p = this.bounds.upperLeft();\n\t\tthis._dockerNode.setAttributeNS(null, 'transform','translate(' + p.x + ', ' + p.y + ')');\n\t\t\n\t\t// Refresh the referencepoints node\n\t\tp = Object.clone(this.referencePoint);\n\t\t\n\t\tif(p && this._dockedShape){\n\t\t\tvar upL \n\t\t\tif(this.parent instanceof ORYX.Core.Edge) {\n\t\t\t\tupL = this._dockedShape.absoluteXY();\n\t\t\t} else {\n\t\t\t\tupL = this._dockedShape.bounds.upperLeft();\n\t\t\t}\n\t\t\tp.x += upL.x;\n\t\t\tp.y += upL.y;\n\t\t} else {\n\t\t\tp = this.bounds.center();\n\t\t}\t\t\t\n\n\t\tthis._referencePointNode.setAttributeNS(null, 'transform','translate(' + p.x + ', ' + p.y + ')');\n\t},\n\n\t/**\n\t * Set the reference point\n\t * @param {Object} point\n\t */\t\n\tsetReferencePoint: function(point) {\n\t\t// Set the referencepoint\n\t\tif(this.referencePoint !== point &&\n\t\t\t(!this.referencePoint || \n\t\t\t!point ||\n\t\t\tthis.referencePoint.x !== point.x || \n\t\t\tthis.referencePoint.y !== point.y)) {\n\t\t\t\t\n\t\t\tthis.referencePoint = point;\n\t\t\tthis._changed();\t\t\t\n\t\t}\n\n\t\t\n\t\t// Update directly, because the referencepoint has no influence of the bounds\n\t\t//this.refresh();\n\t},\n\t\n\t/**\n\t * Get the absolute referencepoint\n\t */\n\tgetAbsoluteReferencePoint: function() {\n\t\tif(!this.referencePoint || !this._dockedShape) {\n\t\t\treturn undefined;\n\t\t} else {\n\t\t\tvar absUL = this._dockedShape.absoluteXY();\n\t\t\treturn {\t\n\t\t\t\t\t\tx: this.referencePoint.x + absUL.x,\n\t\t\t\t\t\ty: this.referencePoint.y + absUL.y\n\t\t\t\t\t}\n\t\t}\n\t},\t\n\t\n\t/**\n\t * Set the docked Shape from the docker\n\t * @param {Object} shape\n\t */\n\tsetDockedShape: function(shape) {\n\n\t\t// If there is an old docked Shape\n\t\tif(this._dockedShape) {\n\t\t\tthis._dockedShape.bounds.unregisterCallback(this._updateCallback)\n\t\t\t\n\t\t\t// Delete the Shapes from the incoming and outgoing array\n\t\t\t// If this Docker the incoming of the Shape\n\t\t\tif(this === this.parent.dockers.first()) {\n\t\t\t\t\n\t\t\t\tthis.parent.incoming = this.parent.incoming.without(this._dockedShape);\n\t\t\t\tthis._dockedShape.outgoing = this._dockedShape.outgoing.without(this.parent);\n\t\t\t\n\t\t\t// If this Docker the outgoing of the Shape\t\n\t\t\t} else if (this === this.parent.dockers.last()){\n\t\n\t\t\t\tthis.parent.outgoing = this.parent.outgoing.without(this._dockedShape);\n\t\t\t\tthis._dockedShape.incoming = this._dockedShape.incoming.without(this.parent);\n\t\t\t\t\t\t\t\n\t\t\t}\n\t\t\t\n\t\t}\n\n\t\t\n\t\t// Set the new Shape\n\t\tthis._dockedShape = shape;\n\t\tthis._dockedShapeBounds = undefined;\n\t\tvar referencePoint = undefined;\n\t\t\n\t\t// If there is an Shape, register the updateCallback if there are changes in the shape bounds\n\t\tif(this._dockedShape) {\n\t\t\t\n\t\t\t// Add the Shapes to the incoming and outgoing array\n\t\t\t// If this Docker the incoming of the Shape\n\t\t\tif(this === this.parent.dockers.first()) {\n\t\t\t\t\n\t\t\t\tthis.parent.incoming.push(shape);\n\t\t\t\tshape.outgoing.push(this.parent);\n\t\t\t\n\t\t\t// If this Docker the outgoing of the Shape\t\n\t\t\t} else if (this === this.parent.dockers.last()){\n\t\n\t\t\t\tthis.parent.outgoing.push(shape);\n\t\t\t\tshape.incoming.push(this.parent);\n\t\t\t\t\t\t\t\n\t\t\t}\n\t\t\t\n\t\t\t// Get the bounds and set the new referencepoint\n\t\t\tvar bounds = this.bounds;\n\t\t\tvar absUL = shape.absoluteXY();\n\t\t\t\n\t\t\t/*if(shape.parent){\n\t\t\t\tvar b = shape.parent.bounds.upperLeft();\n\t\t\t\tabsUL.x -= b.x;\n\t\t\t\tabsUL.y -= b.y;\n\t\t\t}*/\n\t\t\t\n\t\t\treferencePoint = {\n\t\t\t\tx: bounds.center().x - absUL.x,\n\t\t\t\ty: bounds.center().y - absUL.y\n\t\t\t}\t\n\t\t\t\t\t\t\n\t\t\tthis._dockedShapeBounds = this._dockedShape.bounds.clone();\n\t\t\t\n\t\t\tthis._dockedShape.bounds.registerCallback(this._updateCallback);\n\t\t\t\n\t\t\t// Set the color of the docker as docked\n\t\t\tthis.setDockerColor(ORYX.CONFIG.DOCKER_DOCKED_COLOR);\t\t\t\t\n\t\t} else {\n\t\t\t// Set the color of the docker as undocked\n\t\t\tthis.setDockerColor(ORYX.CONFIG.DOCKER_UNDOCKED_COLOR);\n\t\t}\n\n\t\t// Set the referencepoint\n\t\tthis.setReferencePoint(referencePoint);\n\t\tthis._changed();\n\t\t//this.update();\n\t},\n\t\n\t/**\n\t * Get the docked Shape\n\t */\n\tgetDockedShape: function() {\n\t\treturn this._dockedShape;\n\t},\n\n\t/**\n\t * Returns TRUE if the docker has a docked shape\n\t */\n\tisDocked: function() {\n\t\treturn !!this._dockedShape;\n\t},\n\t\t\n\t/**\n\t * Set the Color of the Docker\n\t * @param {Object} color\n\t */\n\tsetDockerColor: function(color) {\n\t\tthis._dockerNode.lastChild.setAttributeNS(null, \"fill\", color);\n\t},\n\t\n\tpreventHiding: function(prevent){\n\t\tthis._preventHiding = Math.max(0, (this._preventHiding||0) + (prevent ? 1 : -1));\n\t},\n\t\n\t/**\n\t * Hides this UIObject and all its children.\n\t */\n\thide: function() {\n\t\tif (this._preventHiding){\n\t\t\treturn false;\n\t\t}\n\t\t\n\t\t// Hide docker and reference point\n\t\tthis.node.setAttributeNS(null, 'visibility', 'hidden');\n\t\tthis._referencePointNode.setAttributeNS(null, 'visibility', 'hidden');\n\t\t\n\t\tthis.children.each(function(uiObj) {\n\t\t\tuiObj.hide();\t\n\t\t});\t\t\t\t\n\t},\n\t\n\t/**\n\t * Enables visibility of this UIObject and all its children.\n\t */\n\tshow: function() {\n\t\t// Show docker\n\t\tthis.node.setAttributeNS(null, 'visibility', 'visible');\n\t\t\n\t\t// Hide reference point if the connected shape is an edge\n\t\tif (this.getDockedShape() instanceof ORYX.Core.Edge){\n\t\t\tthis._referencePointNode.setAttributeNS(null, 'visibility', 'hidden');\n\t\t} else {\n\t\t\tthis._referencePointNode.setAttributeNS(null, 'visibility', 'visible');\n\t\t}\n\t\t\n\t\tthis.children.each(function(uiObj) {\n\t\t\tuiObj.show();\t\n\t\t});\t\t\n\t},\n\t\n\ttoString: function() { return \"Docker \" + this.id }\n});/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespaces\n */\nif(!ORYX) {var ORYX = {};}\nif(!ORYX.Core) {ORYX.Core = {};}\nif(!ORYX.Core.Controls) {ORYX.Core.Controls = {};}\n\n\n/**\n * @classDescription Represents a magnet that is part of another shape and can\n * be attached to dockers. Magnets are used for linking edge objects\n * to other Shape objects.\n * @extends {Control}\n */\nORYX.Core.Controls.Magnet = ORYX.Core.Controls.Control.extend({\n\t\t\n\t/**\n\t * Constructor\n\t */\n\tconstruct: function() {\n\t\targuments.callee.$.construct.apply(this, arguments);\n\t\t\n\t\t//this.anchors = [];\n\t\tthis.anchorLeft;\n\t\tthis.anchorRight;\n\t\tthis.anchorTop;\n\t\tthis.anchorBottom;\n\t\t\n\t\tthis.bounds.set(0, 0, 16, 16);\n\t\t\n\t\t//graft magnet's root node into owner's control group.\n\t\tthis.node = ORYX.Editor.graft(\"http://www.w3.org/2000/svg\",\n\t\t\tnull,\n\t\t\t['g', {\"pointer-events\":\"all\"},\n\t\t\t\t\t['circle', {cx:\"8\", cy:\"8\", r:\"4\", stroke:\"none\", fill:\"red\", \"fill-opacity\":\"0.3\"}],\n\t\t\t\t]);\n\t\t\t\n\t\tthis.hide();\n\t},\n\t\n\tupdate: function() {\n\t\targuments.callee.$.update.apply(this, arguments);\n\t\t\n\t\t//this.isChanged = true;\n\t},\n\t\n\t_update: function() {\t\t\n\t\targuments.callee.$.update.apply(this, arguments);\n\t\t\n\t\t//this.isChanged = true;\n\t},\n\t\n\trefresh: function() {\n\t\targuments.callee.$.refresh.apply(this, arguments);\n\n\t\tvar p = this.bounds.upperLeft();\n\t\t/*if(this.parent) {\n\t\t\tvar parentPos = this.parent.bounds.upperLeft();\n\t\t\tp.x += parentPos.x;\n\t\t\tp.y += parentPos.y;\n\t\t}*/\n\t\t\n\t\tthis.node.setAttributeNS(null, 'transform','translate(' + p.x + ', ' + p.y + ')');\n\t},\n\t\n\tshow: function() {\n\t\t//this.refresh();\n\t\targuments.callee.$.show.apply(this, arguments);\n\t},\n\t\n\ttoString: function() {\n\t\treturn \"Magnet \" + this.id;\n\t}\n});\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * Init namespaces\n */\nif (!ORYX) {\n    var ORYX = {};\n}\nif (!ORYX.Core) {\n    ORYX.Core = {};\n}\n\n/**\n * @classDescription Abstract base class for all Nodes.\n * @extends ORYX.Core.Shape\n */\nORYX.Core.Node = {\n\n    /**\n     * Constructor\n     * @param options {Object} A container for arguments.\n     * @param stencil {Stencil}\n     */\n    construct: function(options, stencil, facade){\n        arguments.callee.$.construct.apply(this, arguments);\n        \n        this.isSelectable = true;\n        this.isMovable = true;\n\t\tthis._dockerUpdated = false;\n\t\tthis.facade = facade;\n        \n        this._oldBounds = new ORYX.Core.Bounds(); //init bounds with undefined values\n        this._svgShapes = []; //array of all SVGShape objects of\n        // SVG representation\n        \n        //TODO vielleicht in shape verschieben?\n        this.minimumSize = undefined; // {width:..., height:...}\n        this.maximumSize = undefined;\n        \n        //TODO vielleicht in shape oder uiobject verschieben?\n        // vielleicht sogar isResizable ersetzen?\n        this.isHorizontallyResizable = false;\n        this.isVerticallyResizable = false;\n        \n        this.dataId = undefined;\n        \n        this._init(this._stencil.view());\n        this.forcedHeight = -1;\n    },\n        \n    /**\n     * This method checks whether the shape is resized correctly and calls the\n     * super class update method.\n     */\n    _update: function(){\n\t\t\n\t\tthis.dockers.invoke(\"update\");\n\t\tif (this.isChanged) {\n\n\t\t\tvar bounds = this.bounds;\n            var oldBounds = this._oldBounds;\n\t\t\t\t\t\t\n\t\t\tif (this.isResized) {\n\t\t\t\n\t\t\t\tvar widthDelta = bounds.width() / oldBounds.width();\n\t\t\t\tvar heightDelta = bounds.height() / oldBounds.height();\n\t\t\t\t\n\t\t\t\t//iterate over all relevant svg elements and resize them\n\t\t\t\tthis._svgShapes.each(function(svgShape){\n\t\t\t\t\t//adjust width\n\t\t\t\t\tif (svgShape.isHorizontallyResizable) {\n\t\t\t\t\t\tsvgShape.width = svgShape.oldWidth * widthDelta;\n\t\t\t\t\t}\n\t\t\t\t\t//adjust height\n\t\t\t\t\tif (svgShape.isVerticallyResizable) {\n\t\t\t\t\t\tsvgShape.height = svgShape.oldHeight * heightDelta;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t//check, if anchors are set\n\t\t\t\t\tvar anchorOffset;\n\t\t\t\t\tvar leftIncluded = svgShape.anchorLeft;\n\t\t\t\t\tvar rightIncluded = svgShape.anchorRight;\n\t\t\t\t\t\n\t\t\t\t\tif (rightIncluded) {\n\t\t\t\t\t\tanchorOffset = oldBounds.width() - (svgShape.oldX + svgShape.oldWidth);\n\t\t\t\t\t\tif (leftIncluded) {\n\t\t\t\t\t\t\tsvgShape.width = bounds.width() - svgShape.x - anchorOffset;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tsvgShape.x = bounds.width() - (anchorOffset + svgShape.width);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse \n\t\t\t\t\t\tif (!leftIncluded) {\n\t\t\t\t\t\t\tsvgShape.x = widthDelta * svgShape.oldX;\n\t\t\t\t\t\t\tif (!svgShape.isHorizontallyResizable) {\n\t\t\t\t\t\t\t\tsvgShape.x = svgShape.x + svgShape.width * widthDelta / 2 - svgShape.width / 2;\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\tvar topIncluded = svgShape.anchorTop;\n\t\t\t\t\tvar bottomIncluded = svgShape.anchorBottom;\n\t\t\t\t\t\n\t\t\t\t\tif (bottomIncluded) {\n\t\t\t\t\t\tanchorOffset = oldBounds.height() - (svgShape.oldY + svgShape.oldHeight);\n\t\t\t\t\t\tif (topIncluded) {\n\t\t\t\t\t\t\tsvgShape.height = bounds.height() - svgShape.y - anchorOffset;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t// Hack for choreography task layouting\n\t\t\t\t\t\t\tif (!svgShape._isYLocked) {\n\t\t\t\t\t\t\t\tsvgShape.y = bounds.height() - (anchorOffset + svgShape.height);\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\telse \n\t\t\t\t\t\tif (!topIncluded) {\n\t\t\t\t\t\t\tsvgShape.y = heightDelta * svgShape.oldY;\n\t\t\t\t\t\t\tif (!svgShape.isVerticallyResizable) {\n\t\t\t\t\t\t\t\tsvgShape.y = svgShape.y + svgShape.height * heightDelta / 2 - svgShape.height / 2;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\t//check, if the current bounds is unallowed horizontally or vertically resized\n\t\t\t\tvar p = {\n\t\t\t\t\tx: 0,\n\t\t\t\t\ty: 0\n\t\t\t\t};\n\t\t\t\tif (!this.isHorizontallyResizable && bounds.width() !== oldBounds.width()) {\n\t\t\t\t\tp.x = oldBounds.width() - bounds.width();\n\t\t\t\t}\n\t\t\t\tif (!this.isVerticallyResizable && bounds.height() !== oldBounds.height()) {\n\t\t\t\t\tp.y = oldBounds.height() - bounds.height();\n\t\t\t\t}\n\t\t\t\tif (p.x !== 0 || p.y !== 0) {\n\t\t\t\t\tbounds.extend(p);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t//check, if the current bounds are between maximum and minimum bounds\n\t\t\t\tp = {\n\t\t\t\t\tx: 0,\n\t\t\t\t\ty: 0\n\t\t\t\t};\n\t\t\t\tvar widthDifference, heightDifference;\n\t\t\t\tif (this.minimumSize) {\n\t\t\t\t\n\t\t\t\t\tORYX.Log.debug(\"Shape (%0)'s min size: (%1x%2)\", this, this.minimumSize.width, this.minimumSize.height);\n\t\t\t\t\twidthDifference = this.minimumSize.width - bounds.width();\n\t\t\t\t\tif (widthDifference > 0) {\n\t\t\t\t\t\tp.x += widthDifference;\n\t\t\t\t\t}\n\t\t\t\t\theightDifference = this.minimumSize.height - bounds.height();\n\t\t\t\t\tif (heightDifference > 0) {\n\t\t\t\t\t\tp.y += heightDifference;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (this.maximumSize) {\n\t\t\t\t\n\t\t\t\t\tORYX.Log.debug(\"Shape (%0)'s max size: (%1x%2)\", this, this.maximumSize.width, this.maximumSize.height);\n\t\t\t\t\twidthDifference = bounds.width() - this.maximumSize.width;\n\t\t\t\t\tif (widthDifference > 0) {\n\t\t\t\t\t\tp.x -= widthDifference;\n\t\t\t\t\t}\n\t\t\t\t\theightDifference = bounds.height() - this.maximumSize.height;\n\t\t\t\t\tif (heightDifference > 0) {\n\t\t\t\t\t\tp.y -= heightDifference;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (p.x !== 0 || p.y !== 0) {\n\t\t\t\t\tbounds.extend(p);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t//update magnets\n\t\t\t\t\n\t\t\t\tvar widthDelta = bounds.width() / oldBounds.width();\n\t\t\t\tvar heightDelta = bounds.height() / oldBounds.height();\n\t\t\t\t\n\t\t\t\tvar leftIncluded, rightIncluded, topIncluded, bottomIncluded, center, newX, newY;\n\t\t\t\t\n\t\t\t\tthis.magnets.each(function(magnet){\n\t\t\t\t\tleftIncluded = magnet.anchorLeft;\n\t\t\t\t\trightIncluded = magnet.anchorRight;\n\t\t\t\t\ttopIncluded = magnet.anchorTop;\n\t\t\t\t\tbottomIncluded = magnet.anchorBottom;\n\t\t\t\t\t\n\t\t\t\t\tcenter = magnet.bounds.center();\n\t\t\t\t\t\n\t\t\t\t\tif (leftIncluded) {\n\t\t\t\t\t\tnewX = center.x;\n\t\t\t\t\t}\n\t\t\t\t\telse \n\t\t\t\t\t\tif (rightIncluded) {\n\t\t\t\t\t\t\tnewX = bounds.width() - (oldBounds.width() - center.x)\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tnewX = center.x * widthDelta;\n\t\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif (topIncluded) {\n\t\t\t\t\t\tnewY = center.y;\n\t\t\t\t\t}\n\t\t\t\t\telse \n\t\t\t\t\t\tif (bottomIncluded) {\n\t\t\t\t\t\t\tnewY = bounds.height() - (oldBounds.height() - center.y);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tnewY = center.y * heightDelta;\n\t\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif (center.x !== newX || center.y !== newY) {\n\t\t\t\t\t\tmagnet.bounds.centerMoveTo(newX, newY);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\t//set new position of labels\n\t\t\t\tthis.getLabels().each(function(label){\n\t\t\t\t\t// Set the position dependings on it anchor\n\t\t\t\t\tif (!label.isAnchorLeft()) {\n\t\t\t\t\t\tif (label.isAnchorRight()) {\n\t\t\t\t\t\t\tlabel.setX(bounds.width() - (oldBounds.width() - label.oldX))\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlabel.setX((label.position?label.position.x:label.x) * widthDelta);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (!label.isAnchorTop()) {\n\t\t\t\t\t\tif (label.isAnchorBottom()) {\n\t\t\t\t\t\t\tlabel.setY(bounds.height() - (oldBounds.height() - label.oldY));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlabel.setY((label.position?label.position.y:label.y) * heightDelta);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t// If there is an position,\n\t\t\t\t\t// set the origin position as well\n\t\t\t\t\tif (label.position){\n\t\t\t\t\t\tif (!label.isOriginAnchorLeft()) {\n\t\t\t\t\t\t\tif (label.isOriginAnchorRight()) {\n\t\t\t\t\t\t\t\tlabel.setOriginX(bounds.width() - (oldBounds.width() - label.oldX))\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tlabel.setOriginX(label.x * widthDelta);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!label.isOriginAnchorTop()) {\n\t\t\t\t\t\t\tif (label.isOriginAnchorBottom()) {\n\t\t\t\t\t\t\t\tlabel.setOriginY(bounds.height() - (oldBounds.height() - label.oldY));\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tlabel.setOriginY(label.y * heightDelta);\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\t\n\t\t\t\t//update docker\n\t\t\t\tvar docker = this.dockers[0];\n\t\t\t\tif (docker) {\n\t\t\t\t\tdocker.bounds.unregisterCallback(this._dockerChangedCallback);\n\t\t\t\t\tif (!this._dockerUpdated) {\n\t\t\t\t\t\tdocker.bounds.centerMoveTo(this.bounds.center());\n\t\t\t\t\t\tthis._dockerUpdated = false;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tdocker.update();\n\t\t\t\t\tdocker.bounds.registerCallback(this._dockerChangedCallback);\n\t\t\t\t}\n\t\t\t\tthis.isResized = false;\n\t\t\t}\n            \n            this.refresh();\n\t\t\t\n\t\t\tthis.isChanged = false;\n\t\t\t\n\t\t\tthis._oldBounds = this.bounds.clone();\n        }\n\t\t\n\t\tthis.children.each(function(value) {\n\t\t\tif(!(value instanceof ORYX.Core.Controls.Docker)) {\n\t\t\t\tvalue._update();\n\t\t\t}\n\t\t});\n\t\t\n\t\tif (this.dockers.length > 0&&!this.dockers.first().getDockedShape()) {\n\t\t\tthis.dockers.each(function(docker){\n\t\t\t\tdocker.bounds.centerMoveTo(this.bounds.center())\n\t\t\t}.bind(this))\n\t\t}\n\t\t\n\t\t/*this.incoming.each((function(edge) {\n\t\t\tif(!(this.dockers[0] && this.dockers[0].getDockedShape() instanceof ORYX.Core.Node))\n\t\t\t\tedge._update(true);\n\t\t}).bind(this));\n\t\t\n\t\tthis.outgoing.each((function(edge) {\n\t\t\tif(!(this.dockers[0] && this.dockers[0].getDockedShape() instanceof ORYX.Core.Node))\n\t\t\t\tedge._update(true);\n\t\t}).bind(this)); */\n    },\n    \n    /**\n     * This method repositions and resizes the SVG representation\n     * of the shape.\n     */\n    refresh: function(){\n        arguments.callee.$.refresh.apply(this, arguments);\n        \n        /** Movement */\n        var x = this.bounds.upperLeft().x;\n        var y = this.bounds.upperLeft().y;\n        \n\t\t// Move owner element\n\t\tthis.node.firstChild.setAttributeNS(null, \"transform\", \"translate(\" + x + \", \" + y + \")\");\n\t\t// Move magnets\n\t\tthis.node.childNodes[1].childNodes[1].setAttributeNS(null, \"transform\", \"translate(\" + x + \", \" + y + \")\");\n        \n        /** Resize */\n        \n        //iterate over all relevant svg elements and update them\n        this._svgShapes.each(function(svgShape){\n            svgShape.update();\n        });\n    },\n    \n    _dockerChanged: function(){\n\t\tvar docker = this.dockers[0];\n        \n        //set the bounds of the the association\n        this.bounds.centerMoveTo(docker.bounds.center());\n        \n\t\tthis._dockerUpdated = true;\n        //this._update(true);\n    },\n    \n    /**\n     * This method traverses a tree of SVGElements and returns\n     * all SVGShape objects. For each basic shape or path element\n     * a SVGShape object is initialized.\n     *\n     * @param svgNode {SVGElement}\n     * @return {Array} Array of SVGShape objects\n     */\n    _initSVGShapes: function(svgNode){\n        var svgShapes = [];\n        try {\n            var svgShape = new ORYX.Core.SVG.SVGShape(svgNode);\n            svgShapes.push(svgShape);\n        } \n        catch (e) {\n            //do nothing\n        }\n        \n        if (svgNode.hasChildNodes()) {\n            for (var i = 0; i < svgNode.childNodes.length; i++) {\n                svgShapes = svgShapes.concat(this._initSVGShapes(svgNode.childNodes[i]));\n            }\n        }\n        \n        return svgShapes;\n    },\n    \n    /**\n     * Calculate if the point is inside the Shape\n     * @param {PointX}\n     * @param {PointY} \n     * @param {absoluteBounds} optional: for performance\n     */\n    isPointIncluded: function(pointX, pointY, absoluteBounds){\n        // If there is an arguments with the absoluteBounds\n        var absBounds = absoluteBounds && absoluteBounds instanceof ORYX.Core.Bounds ? absoluteBounds : this.absoluteBounds();\n        \n        if (!absBounds.isIncluded(pointX, pointY)) {\n\t\t\treturn false;\n\t\t} else {\n\t\t\t\n\t\t}\n\t\t\t\n        \n        //point = Object.clone(point);\n        var ul = absBounds.upperLeft();\n        var x = pointX - ul.x;\n        var y = pointY - ul.y;\t\t\n\t\n\t\tvar i=0;\n\t\tdo {\n\t\t\tvar isPointIncluded = this._svgShapes[i++].isPointIncluded( x, y );\n\t\t} while( !isPointIncluded && i < this._svgShapes.length)\n\t\t\n\t\treturn isPointIncluded;\n\n        /*return this._svgShapes.any(function(svgShape){\n            return svgShape.isPointIncluded(point);\n        });*/\n    },\n \n    \n    /**\n     * Calculate if the point is over an special offset area\n     * @param {Point}\n     */\n    isPointOverOffset: function( pointX, pointY ){       \n\t\tvar isOverEl = arguments.callee.$.isPointOverOffset.apply( this , arguments );\n\t\t\n\t\tif (isOverEl) {\n\t\t\t\t\t\t\n\t        // If there is an arguments with the absoluteBounds\n\t        var absBounds = this.absoluteBounds();\n\t        absBounds.widen( - ORYX.CONFIG.BORDER_OFFSET );\n\t\t\t\n\t        if ( !absBounds.isIncluded( pointX, pointY )) {\n\t            return true;\n\t        }\t\t\n\t\t}\n\t\t\n\t\treturn false;\n\t\t\n\t},\n\t   \n    serialize: function(){\n        var result = arguments.callee.$.serialize.apply(this);\n        \n        // Add the docker's bounds\n        // nodes only have at most one docker!\n        this.dockers.each((function(docker){\n\t\t\tif (docker.getDockedShape()) {\n\t\t\t\tvar center = docker.referencePoint;\n\t\t\t\tcenter = center ? center : docker.bounds.center();\n\t\t\t\tresult.push({\n\t\t\t\t\tname: 'docker',\n\t\t\t\t\tprefix: 'oryx',\n\t\t\t\t\tvalue: $H(center).values().join(','),\n\t\t\t\t\ttype: 'literal'\n\t\t\t\t});\n\t\t\t}\n        }).bind(this));\n        \n        // Get the spezific serialized object from the stencil\n        try {\n            //result = this.getStencil().serialize(this, result);\n\n\t\t\tvar serializeEvent = this.getStencil().serialize();\n\t\t\t\n\t\t\t/*\n\t\t\t * call serialize callback by reference, result should be found\n\t\t\t * in serializeEvent.result\n\t\t\t */\n\t\t\tif(serializeEvent.type) {\n\t\t\t\tserializeEvent.shape = this;\n\t\t\t\tserializeEvent.data = result;\n\t\t\t\tserializeEvent.result = undefined;\n\t\t\t\tserializeEvent.forceExecution = true;\n\t\t\t\t\n\t\t\t\tthis._delegateEvent(serializeEvent);\n\t\t\t\t\n\t\t\t\tif(serializeEvent.result) {\n\t\t\t\t\tresult = serializeEvent.result;\n\t\t\t\t}\n\t\t\t}\n        } \n        catch (e) {\n        }\n        return result;\n    },\n    \n    deserialize: function(data){\n    \targuments.callee.$.deserialize.apply(this, arguments);\n\t\t\n\t    try {\n            //data = this.getStencil().deserialize(this, data);\n\n\t\t\tvar deserializeEvent = this.getStencil().deserialize();\n\t\t\t\n\t\t\t/*\n\t\t\t * call serialize callback by reference, result should be found\n\t\t\t * in serializeEventInfo.result\n\t\t\t */\n\t\t\tif(deserializeEvent.type) {\n\t\t\t\tdeserializeEvent.shape = this;\n\t\t\t\tdeserializeEvent.data = data;\n\t\t\t\tdeserializeEvent.result = undefined;\n\t\t\t\tdeserializeEvent.forceExecution = true;\n\t\t\t\t\n\t\t\t\tthis._delegateEvent(deserializeEvent);\n\t\t\t\tif(deserializeEvent.result) {\n\t\t\t\t\tdata = deserializeEvent.result;\n\t\t\t\t}\n\t\t\t}\n        } \n        catch (e) {\n        }\n\t\t\n\t\t// Set the outgoing shapes\n\t\tvar outgoing = data.findAll(function(ser){ return (ser.prefix+\"-\"+ser.name) == 'raziel-outgoing'});\n\t\toutgoing.each((function(obj){\n\t\t\t// TODO: Look at Canvas\n\t\t\tif(!this.parent) {return};\n\t\t\t\t\t\t\t\t\n\t\t\t// Set outgoing Shape\n\t\t\tvar next = this.getCanvas().getChildShapeByResourceId(obj.value);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\tif(next){\n\t\t\t\tif(next instanceof ORYX.Core.Edge) {\n\t\t\t\t\t//Set the first docker of the next shape\n\t\t\t\t\tnext.dockers.first().setDockedShape(this);\n\t\t\t\t\tnext.dockers.first().setReferencePoint(next.dockers.first().bounds.center());\n\t\t\t\t} else if(next.dockers.length > 0) { //next is a node and next has a docker\n\t\t\t\t\tnext.dockers.first().setDockedShape(this);\n\t\t\t\t\t//next.dockers.first().setReferencePoint({x: this.bounds.width() / 2.0, y: this.bounds.height() / 2.0});\n\t\t\t\t}\n\t\t\t}\t\n\t\t\t\n\t\t}).bind(this));\n        \n        if (this.dockers.length === 1) {\n            var dockerPos;\n            dockerPos = data.find(function(entry){\n                return (entry.prefix + \"-\" + entry.name === \"oryx-dockers\");\n            });\n            \n            if (dockerPos) {\n                var points = dockerPos.value.replace(/,/g, \" \").split(\" \").without(\"\").without(\"#\");\n\t\t\t\tif (points.length === 2 && this.dockers[0].getDockedShape()) {\n                    this.dockers[0].setReferencePoint({\n                        x: parseFloat(points[0]),\n                        y: parseFloat(points[1])\n                    });\n                }\n                else {\n                    this.dockers[0].bounds.centerMoveTo(parseFloat(points[0]), parseFloat(points[1]));\n                }\n            }\n        }\n    },\n    \n    /**\n     * This method excepts the SVGDoucment that is the SVG representation\n     * of this shape.\n     * The bounds of the shape are calculated, the SVG representation's upper left point\n     * is moved to 0,0 and it the method sets if this shape is resizable.\n     *\n     * @param {SVGDocument} svgDocument\n     */\n    _init: function(svgDocument){\n        arguments.callee.$._init.apply(this, arguments);\n\t\t\n        var svgNode = svgDocument.getElementsByTagName(\"g\")[0]; //outer most g node\n        // set all required attributes\n        var attributeTitle = svgDocument.ownerDocument.createAttribute(\"title\");\n        attributeTitle.nodeValue = this.getStencil().title();\n        svgNode.setAttributeNode(attributeTitle);\n        \n        var attributeId = svgDocument.ownerDocument.createAttribute(\"id\");\n        attributeId.nodeValue = this.id;\n        svgNode.setAttributeNode(attributeId);\n        \n        // \n        var stencilTargetNode = this.node.childNodes[0].childNodes[0]; //<g class=me>\"\n        svgNode = stencilTargetNode.appendChild(svgNode);\n        \n        // Add to the EventHandler\n        this.addEventHandlers(svgNode.parentNode);\n        \n        /**set minimum and maximum size*/\n        var minSizeAttr = svgNode.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, \"minimumSize\");\n        if (minSizeAttr) {\n            minSizeAttr = minSizeAttr.replace(\"/,/g\", \" \");\n            var minSizeValues = minSizeAttr.split(\" \");\n            minSizeValues = minSizeValues.without(\"\");\n            \n            if (minSizeValues.length > 1) {\n                this.minimumSize = {\n                    width: parseFloat(minSizeValues[0]),\n                    height: parseFloat(minSizeValues[1])\n                };\n            }\n            else {\n                //set minimumSize to (1,1), so that width and height of the stencil can never be (0,0)\n                this.minimumSize = {\n                    width: 1,\n                    height: 1\n                };\n            }\n        }\n        \n        var maxSizeAttr = svgNode.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, \"maximumSize\");\n        if (maxSizeAttr) {\n            maxSizeAttr = maxSizeAttr.replace(\"/,/g\", \" \");\n            var maxSizeValues = maxSizeAttr.split(\" \");\n            maxSizeValues = maxSizeValues.without(\"\");\n            \n            if (maxSizeValues.length > 1) {\n                this.maximumSize = {\n                    width: parseFloat(maxSizeValues[0]),\n                    height: parseFloat(maxSizeValues[1])\n                };\n            }\n        }\n        \n        if (this.minimumSize && this.maximumSize &&\n        (this.minimumSize.width > this.maximumSize.width ||\n        this.minimumSize.height > this.maximumSize.height)) {\n        \n            //TODO wird verschluckt!!!\n            throw this + \": Minimum Size must be greater than maxiumSize.\";\n        }\n        \n        /**get current bounds and adjust it to upperLeft == (0,0)*/\n        //initialize all SVGShape objects\n        this._svgShapes = this._initSVGShapes(svgNode);\n        \n        //get upperLeft and lowerRight of stencil\n        var upperLeft = {\n            x: undefined,\n            y: undefined\n        };\n        var lowerRight = {\n            x: undefined,\n            y: undefined\n        };\n        var me = this;\n        this._svgShapes.each(function(svgShape){\n            upperLeft.x = (upperLeft.x !== undefined) ? Math.min(upperLeft.x, svgShape.x) : svgShape.x;\n            upperLeft.y = (upperLeft.y !== undefined) ? Math.min(upperLeft.y, svgShape.y) : svgShape.y;\n            lowerRight.x = (lowerRight.x !== undefined) ? Math.max(lowerRight.x, svgShape.x + svgShape.width) : svgShape.x + svgShape.width;\n            lowerRight.y = (lowerRight.y !== undefined) ? Math.max(lowerRight.y, svgShape.y + svgShape.height) : svgShape.y + svgShape.height;\n            \n            /** set if resizing is enabled */\n            //TODO isResizable durch die beiden anderen booleans ersetzen?\n            if (svgShape.isHorizontallyResizable) {\n                me.isHorizontallyResizable = true;\n                me.isResizable = true;\n            }\n            if (svgShape.isVerticallyResizable) {\n                me.isVerticallyResizable = true;\n                me.isResizable = true;\n            }\n            if (svgShape.anchorTop && svgShape.anchorBottom) {\n                me.isVerticallyResizable = true;\n                me.isResizable = true;\n            }\n            if (svgShape.anchorLeft && svgShape.anchorRight) {\n                me.isHorizontallyResizable = true;\n                me.isResizable = true;\n            }\n        });\n        \n        //move all SVGShapes by -upperLeft\n        this._svgShapes.each(function(svgShape){\n            svgShape.x -= upperLeft.x;\n            svgShape.y -= upperLeft.y;\n            svgShape.update();\n        });\n        \n        //set bounds of shape\n        //the offsets are also needed for positioning the magnets and the docker\n        var offsetX = upperLeft.x;\n        var offsetY = upperLeft.y;\n        \n        lowerRight.x -= offsetX;\n        lowerRight.y -= offsetY;\n        upperLeft.x = 0;\n        upperLeft.y = 0;\n        \n        //prevent that width or height of initial bounds is 0\n        if (lowerRight.x === 0) {\n            lowerRight.x = 1;\n        }\n        if (lowerRight.y === 0) {\n            lowerRight.y = 1;\n        }\n        \n        this._oldBounds.set(upperLeft, lowerRight);\n        this.bounds.set(upperLeft, lowerRight);\n        \n        /**initialize magnets */\n        \n        var magnets = svgDocument.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_ORYX, \"magnets\");\n        \n        if (magnets && magnets.length > 0) {\n        \n            magnets = $A(magnets[0].getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_ORYX, \"magnet\"));\n            \n            var me = this;\n            magnets.each(function(magnetElem){\n                var magnet = new ORYX.Core.Controls.Magnet({\n                    eventHandlerCallback: me.eventHandlerCallback\n                });\n                var cx = parseFloat(magnetElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, \"cx\"));\n                var cy = parseFloat(magnetElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, \"cy\"));\n                magnet.bounds.centerMoveTo({\n                    x: cx - offsetX,\n                    y: cy - offsetY\n                });\n                \n                //get anchors\n                var anchors = magnetElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, \"anchors\");\n                if (anchors) {\n                    anchors = anchors.replace(\"/,/g\", \" \");\n                    anchors = anchors.split(\" \").without(\"\");\n                    for(var i = 0; i < anchors.length; i++) {\n\t\t\t\t\t\tswitch(anchors[i].toLowerCase()) {\n\t\t\t\t\t\t\tcase \"left\":\n\t\t\t\t\t\t\t\tmagnet.anchorLeft = true;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase \"right\":\n\t\t\t\t\t\t\t\tmagnet.anchorRight = true;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase \"top\":\n\t\t\t\t\t\t\t\tmagnet.anchorTop = true;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase \"bottom\":\n\t\t\t\t\t\t\t\tmagnet.anchorBottom = true;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n                }\n                \n                me.add(magnet);\n                \n                //check, if magnet is default magnet\n                if (!this._defaultMagnet) {\n                    var defaultAttr = magnetElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, \"default\");\n                    if (defaultAttr && defaultAttr.toLowerCase() === \"yes\") {\n                        me._defaultMagnet = magnet;\n                    }\n                }\n            });\n        }\n        else {\n            // Add a Magnet in the Center of Shape\t\t\t\n            var magnet = new ORYX.Core.Controls.Magnet();\n            magnet.bounds.centerMoveTo(this.bounds.width() / 2, this.bounds.height() / 2);\n            this.add(magnet);\n        }\n        \n        /**initialize docker */\n        var dockerElem = svgDocument.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_ORYX, \"docker\");\n        \n        if (dockerElem && dockerElem.length > 0) {\n            dockerElem = dockerElem[0];\n            var docker = this.createDocker();\n            var cx = parseFloat(dockerElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, \"cx\"));\n            var cy = parseFloat(dockerElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, \"cy\"));\n            docker.bounds.centerMoveTo({\n                x: cx - offsetX,\n                y: cy - offsetY\n            });\n            \n            //get anchors\n            var anchors = dockerElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, \"anchors\");\n            if (anchors) {\n                anchors = anchors.replace(\"/,/g\", \" \");\n                anchors = anchors.split(\" \").without(\"\");\n                \n\t\t\t\tfor(var i = 0; i < anchors.length; i++) {\n\t\t\t\t\tswitch(anchors[i].toLowerCase()) {\n\t\t\t\t\t\tcase \"left\":\n\t\t\t\t\t\t\tdocker.anchorLeft = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"right\":\n\t\t\t\t\t\t\tdocker.anchorRight = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"top\":\n\t\t\t\t\t\t\tdocker.anchorTop = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"bottom\":\n\t\t\t\t\t\t\tdocker.anchorBottom = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n            }\n        }\n        \n        /**initialize labels*/\n        var textElems = svgNode.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'text');\n        $A(textElems).each((function(textElem){\n            var label = new ORYX.Core.SVG.Label({\n                textElement: textElem,\n\t\t\t\tshapeId: this.id\n            });\n            label.x -= offsetX;\n            label.y -= offsetY;\n            this._labels[label.id] = label;\n\t\t\t\n\t\t\tlabel.registerOnChange(this.layout.bind(this));\n\t\t\t\n\t\t\t// Only apply fitting on form-components\n\t\t\tif(this._stencil.id().indexOf(ORYX.CONFIG.FORM_ELEMENT_ID_PREFIX) == 0) {\n\t\t\t\tlabel.registerOnChange(this.fitToLabels.bind(this));\n\t\t\t}\n\t\t\t\n        }).bind(this));\n    },\n    \n    fitToLabels: function() {\n    \tvar y = 0;\n    \t\n    \tthis.getLabels().each(function(label){\n    \t\tvar lr = label.getY() + label.getHeight();\n    \t\tif(lr > y) {\n    \t\t\ty = lr;\n    \t\t}\n    \t});\n    \t\n    \tvar bounds = this.bounds;\n    \tvar boundsChanged = false;\n    \t\n    \tif(this.minimumSize) {\n    \t\t// Check if y-value exceeds the min-value. If not, stick to this value.\n    \t\tvar minHeight = this.minimumSize.height;\n    \t\tif(y < minHeight && bounds.height() > minHeight && minHeight > this.forcedHeight) {\n    \t\t\tbounds.set(bounds.upperLeft().x, bounds.upperLeft().y, bounds.lowerRight().x, bounds.upperLeft().y + minHeight);\n    \t\t\tboundsChanged = true;\n    \t\t} else if(y > minHeight && bounds.height() != y && y > this.forcedHeight){\n    \t\t\tbounds.set(bounds.upperLeft().x, bounds.upperLeft().y, bounds.lowerRight().x, bounds.upperLeft().y + y);\n    \t\t\tboundsChanged = true;\n    \t\t} else if(bounds.height() > this.forcedHeight && this.forcedHeight > 0) {\n    \t\t\tbounds.set(bounds.upperLeft().x, bounds.upperLeft().y, bounds.lowerRight().x, bounds.upperLeft().y + this.forcedHeight);\n    \t\t\tboundsChanged = true;\n    \t\t}\n    \t}\n    \t\n    \tif(boundsChanged) {\n    \t\t// Force facade to re-layout since bounds are changed AFTER layout has been performed\n    \t\tif(this.facade.getCanvas() != null) {\n\t\t\t\tthis.facade.getCanvas().update();\n\t\t\t}\n    \t\t\n    \t\t// Re-select if needed to force the select\n    \t\tif(this.facade.getSelection().member(this)) {\n    \t\t\tvar selectedNow = this.facade.getSelection();\n    \t\t\tthis.facade.setSelection([]);\n    \t\t\tthis.facade.setSelection(selectedNow);\n    \t\t}\n    \t}\n    },\n\t\n\t/**\n\t * Override the Method, that a docker is not shown\n\t *\n\t */\n\tcreateDocker: function() {\n\t\tvar docker = new ORYX.Core.Controls.Docker({eventHandlerCallback: this.eventHandlerCallback});\n\t\tdocker.bounds.registerCallback(this._dockerChangedCallback);\n\t\t\n\t\tthis.dockers.push( docker );\n\t\tdocker.parent = this;\n\t\tdocker.bounds.registerCallback(this._changedCallback);\t\t\n\t\t\n\t\treturn docker\t\t\n\t},\t\n    \n    toString: function(){\n        return this._stencil.title() + \" \" + this.id\n    }\n};\nORYX.Core.Node = ORYX.Core.Shape.extend(ORYX.Core.Node);\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nNAMESPACE_SVG = \"http://www.w3.org/2000/svg\";\nNAMESPACE_ORYX = \"http://www.b3mn.org/oryx\";\n\n\n/**\n * Init namespaces\n */\nif (!ORYX) {\n    var ORYX = {};\n}\nif (!ORYX.Core) {\n    ORYX.Core = {};\n}\n\n\n/**\n * @classDescription Abstract base class for all connections.\n * @extends {ORYX.Core.Shape}\n * @param options {Object}\n *\n * TODO da die verschiebung der Edge nicht ueber eine\n *  translation gemacht wird, die sich auch auf alle kind UIObjects auswirkt,\n *  muessen die kinder hier beim verschieben speziell betrachtet werden.\n *  Das sollte ueberarbeitet werden.\n *\n */\nORYX.Core.Edge = {\n    /**\n     * Constructor\n     * @param {Object} options\n     * @param {Stencil} stencil\n     */\n    construct: function(options, stencil, facade){\n        arguments.callee.$.construct.apply(this, arguments);\n        \n        this.isMovable = true;\n        this.isSelectable = true;\n\t\t\n\t\tthis._dockerUpdated = false;\n        \n        this._markers = new Hash(); //a hash map of SVGMarker objects where keys are the marker ids\n        this._paths = [];\n        this._interactionPaths = [];\n        this._dockersByPath = new Hash();\n        this._markersByPath = new Hash();\n\t\t\n\t\t/* Data structures to store positioning information of attached child nodes */ \n\t\tthis.attachedNodePositionData = new Hash();\n        \n        //TODO was muss hier initial erzeugt werden?\n        var stencilNode = this.node.childNodes[0].childNodes[0];\n        stencilNode = ORYX.Editor.graft(\"http://www.w3.org/2000/svg\", stencilNode, ['g', {\n            \"pointer-events\": \"painted\"\n        }]);\n        \n        //Add to the EventHandler\n        this.addEventHandlers(stencilNode.parentNode);\n        \n        \n        this._oldBounds = this.bounds.clone();\n        \n        //load stencil\n        this._init(this._stencil.view());\n        \n        if (stencil instanceof Array) {\n            this.deserialize(stencil);\n        }\n        \n    },\n    \n    _update: function(force){\n        if(this._dockerUpdated || this.isChanged || force) {\n\t\t  \n\t\t\tthis.dockers.invoke(\"update\");\n\t\t\t\n\t        if (false && (this.bounds.width() === 0 || this.bounds.height() === 0)) {\n\t\t\t\tvar width = this.bounds.width();\n\t\t\t\tvar height = this.bounds.height();\n\t            this.bounds.extend({\n\t                x: width === 0 ? 2 : 0,\n\t                y: height === 0 ? 2 : 0\n\t            });\n\t            this.bounds.moveBy({\n\t                x: width === 0 ? -1 : 0,\n\t                y: height === 0 ? -1 : 0\n\t            });\n            \n\t        }\n\t        \n\t        // TODO: Bounds muss abhaengig des Eltern-Shapes gesetzt werden\n\t        var upL = this.bounds.upperLeft();\n\t        var oldUpL = this._oldBounds.upperLeft();\n\t        var oldWidth = this._oldBounds.width() === 0 ? this.bounds.width() : this._oldBounds.width();\n\t        var oldHeight = this._oldBounds.height() === 0 ? this.bounds.height() : this._oldBounds.height();\n\t        var diffX = upL.x - oldUpL.x;\n\t        var diffY = upL.y - oldUpL.y;\n\t        var diffWidth = (this.bounds.width() / oldWidth) || 1;\n\t        var diffHeight = (this.bounds.height() / oldHeight) || 1;\n\t        \n\t        this.dockers.each((function(docker){\n\t            // Unregister on BoundsChangedCallback\n\t            docker.bounds.unregisterCallback(this._dockerChangedCallback);\n\t            \n\t            // If there is any changes at the edge and is there is not an DockersUpdate\n\t            // set the new bounds to the docker\n\t            if (!this._dockerUpdated) {\n\t                docker.bounds.moveBy(diffX, diffY);\n\t                \n\t                if (diffWidth !== 1 || diffHeight !== 1) {\n\t                    var relX = docker.bounds.upperLeft().x - upL.x;\n\t                    var relY = docker.bounds.upperLeft().y - upL.y;\n\t                    \n\t                    docker.bounds.moveTo(upL.x + relX * diffWidth, upL.y + relY * diffHeight);\n\t                }\n\t            }\n\t            // Do Docker update and register on DockersBoundChange\n\t            docker.update();\n\t            docker.bounds.registerCallback(this._dockerChangedCallback);\n\t            \n\t        }).bind(this));\n\t        \n\t        if (this._dockerUpdated) {\n\t            var a = this.dockers.first().bounds.center();\n\t            var b = this.dockers.first().bounds.center();\n\t            \n\t            this.dockers.each((function(docker){\n\t                var center = docker.bounds.center();\n\t                a.x = Math.min(a.x, center.x);\n\t                a.y = Math.min(a.y, center.y);\n\t                b.x = Math.max(b.x, center.x);\n\t                b.y = Math.max(b.y, center.y);\n\t            }).bind(this));\n\t            \n\t            //set the bounds of the the association\n\t            this.bounds.set(Object.clone(a), Object.clone(b));\n\t        }\n\t\t\t\n\t\t\tupL = this.bounds.upperLeft(); oldUpL = this._oldBounds.upperLeft();\n\t\t\tdiffWidth = (this.bounds.width() / (oldWidth||this.bounds.width())); diffHeight = (this.bounds.height() / (oldHeight||this.bounds.height())); \n\t        diffX = upL.x - oldUpL.x; diffY = upL.y - oldUpL.y;\n\t\t\t\t\t\n\t\t\t//reposition labels\n\t\t\tthis.getLabels().each(function(label) {\n\t\t\t\t\n\t\t\t\tif (label.getReferencePoint()){\n\t\t\t\t\tvar ref = label.getReferencePoint();\n\t\t\t\t\tvar from = ref.segment.from, to = ref.segment.to;\n\t\t\t\t\tif (!from || !from.parent || !to || !to.parent) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tvar fromPosition = from.bounds.center(), toPosition = to.bounds.center();\n\n\t\t\t\t\tif (fromPosition.x === ref.segment.fromPosition.x && fromPosition.y === ref.segment.fromPosition.y &&\n\t\t\t\t\t\ttoPosition.x === ref.segment.toPosition.x && toPosition.y === ref.segment.toPosition.y && !ref.dirty){\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif (!this.parent.initializingShapes) {\n\t\t\t\t\t\tvar oldDistance = ORYX.Core.Math.getDistanceBetweenTwoPoints(ref.segment.fromPosition, ref.segment.toPosition, ref.intersection);\n\t\t\t\t\t\tvar newIntersection = ORYX.Core.Math.getPointBetweenTwoPoints(fromPosition, toPosition, isNaN(oldDistance) ? 0.5 : oldDistance);\n\t\t\t\t\t\t\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * Set position\n\t\t\t\t\t\t */\n\t\t\t\t\t\t// Get the orthogonal identity vector of the current segment\n\t\t\t\t\t\tvar oiv = ORYX.Core.Math.getOrthogonalIdentityVector(fromPosition, toPosition);\n\t\t\t\t\t\tvar isHor = Math.abs(oiv.y)===1, isVer = Math.abs(oiv.x)===1;\n\t\t\t\t\t\toiv.x *= ref.distance; oiv.y *= ref.distance; \t\t\t\t// vector * distance\n\t\t\t\t\t\toiv.x += newIntersection.x; oiv.y += newIntersection.y; \t// vector + the intersection point\t\t\t\t\n\t\t\t\t\t\tvar mx = isHor && ref.orientation && (ref.iorientation||ref.orientation).endsWith(\"r\") ? -label.getWidth() : 0;\t\t\n\t\t\t\t\t\tvar my = isVer && ref.orientation && (ref.iorientation||ref.orientation).startsWith(\"l\") ? -label.getHeight()+2 : 0;\n\t\t\t\t\t\tlabel.setX(oiv.x+mx); label.setY(oiv.y+my);\n\t\t\t\t\t\t\n\t\t\t\t\t\t// Update the reference point\n\t\t\t\t\t\tthis.updateReferencePointOfLabel(label, newIntersection, from, to);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvar oiv = ORYX.Core.Math.getOrthogonalIdentityVector(fromPosition, toPosition);\n\t\t\t\t\t\toiv.x *= ref.distance; oiv.y *= ref.distance; // vector * distance\n\t\t\t\t\t\toiv.x += ref.intersection.x; oiv.y += ref.intersection.y; // vector + the intersection point\t\t\n\t\t\t\t\t\tlabel.setX(oiv.x); label.setY(oiv.y);\n\t\t\t\t\t\tref.segment.fromPosition = fromPosition; ref.segment.toPosition = toPosition;\t\t\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\treturn;\t\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// Update label position if no reference point is set\n\t\t\t\tif (label.position && !this.parent.initializingShapes){\n\t\t\t\t\tvar x = label.position.x + (diffX * (diffWidth||1));\n\t\t\t\t\tif (x > this.bounds.lowerRight().x){\n\t\t\t\t\t\tx += this.bounds.width()-(this.bounds.width()/(diffWidth||1));\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tvar y = label.position.y + (diffY * (diffHeight||1));\n\t\t\t\t\tif (y > this.bounds.lowerRight().y){\n\t\t\t\t\t\ty += this.bounds.height()-(this.bounds.height()/(diffHeight||1));\n\t\t\t\t\t}\n\t\t\t\t\tlabel.setX(x);label.setY(y);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tswitch (label.getEdgePosition()) {\n\t\t\t\t\tcase \"starttop\":\n\t\t\t\t\t\tvar angle = this._getAngle(this.dockers[0], this.dockers[1]);\n\t\t\t\t\t\tvar pos = this.dockers.first().bounds.center();\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (angle <= 90 || angle > 270) {\n\t\t\t\t\t\t\tlabel.horizontalAlign(\"left\");\n\t\t\t\t\t\t\tlabel.verticalAlign(\"bottom\");\n\t\t\t\t\t\t\tlabel.x = pos.x + label.getOffsetTop();\n\t\t\t\t\t\t\tlabel.y = pos.y - label.getOffsetTop();\n\t\t\t\t\t\t\tlabel.rotate(360 - angle, pos);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlabel.horizontalAlign(\"right\");\n\t\t\t\t\t\t\tlabel.verticalAlign(\"bottom\");\n\t\t\t\t\t\t\tlabel.x = pos.x - label.getOffsetTop();\n\t\t\t\t\t\t\tlabel.y = pos.y - label.getOffsetTop();\n\t\t\t\t\t\t\tlabel.rotate(180 - angle, pos);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase \"startmiddle\":\n\t\t\t\t\t\tvar angle = this._getAngle(this.dockers[0], this.dockers[1]);\n\t\t\t\t\t\tvar pos = this.dockers.first().bounds.center();\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (angle <= 90 || angle > 270) {\n\t\t\t\t\t\t\tlabel.horizontalAlign(\"left\");\n\t\t\t\t\t\t\tlabel.verticalAlign(\"bottom\");\n\t\t\t\t\t\t\tlabel.x = pos.x + 2;\n\t\t\t\t\t\t\tlabel.y = pos.y + 4;\n\t\t\t\t\t\t\tlabel.rotate(360 - angle, pos);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlabel.horizontalAlign(\"right\");\n\t\t\t\t\t\t\tlabel.verticalAlign(\"bottom\");\n\t\t\t\t\t\t\tlabel.x = pos.x + 1;\n\t\t\t\t\t\t\tlabel.y = pos.y + 4;\n\t\t\t\t\t\t\tlabel.rotate(180 - angle, pos);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\tcase \"startbottom\":\n\t\t\t\t\t\tvar angle = this._getAngle(this.dockers[0], this.dockers[1]);\n\t\t\t\t\t\tvar pos = this.dockers.first().bounds.center();\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (angle <= 90 || angle > 270) {\n\t\t\t\t\t\t\tlabel.horizontalAlign(\"left\");\n\t\t\t\t\t\t\tlabel.verticalAlign(\"top\");\n\t\t\t\t\t\t\tlabel.x = pos.x + label.getOffsetBottom();\n\t\t\t\t\t\t\tlabel.y = pos.y + label.getOffsetBottom();\n\t\t\t\t\t\t\tlabel.rotate(360 - angle, pos);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlabel.horizontalAlign(\"right\");\n\t\t\t\t\t\t\tlabel.verticalAlign(\"top\");\n\t\t\t\t\t\t\tlabel.x = pos.x - label.getOffsetBottom();\n\t\t\t\t\t\t\tlabel.y = pos.y + label.getOffsetBottom();\n\t\t\t\t\t\t\tlabel.rotate(180 - angle, pos);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"midtop\":\n\t\t\t\t\t\tvar numOfDockers = this.dockers.length;\n\t\t\t\t\t\tif(numOfDockers%2 == 0) {\n\t\t\t\t\t\t\tvar angle = this._getAngle(this.dockers[numOfDockers/2-1], this.dockers[numOfDockers/2])\n\t\t\t\t\t\t\tvar pos1 = this.dockers[numOfDockers/2-1].bounds.center();\n\t\t\t\t\t\t\tvar pos2 = this.dockers[numOfDockers/2].bounds.center();\n\t\t\t\t\t\t\tvar pos = {x:(pos1.x + pos2.x)/2.0, y:(pos1.y+pos2.y)/2.0};\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tlabel.horizontalAlign(\"center\");\n\t\t\t\t\t\t\tlabel.verticalAlign(\"bottom\");\n\t\t\t\t\t\t\tlabel.x = pos.x;\n\t\t\t\t\t\t\tlabel.y = pos.y - label.getOffsetTop();\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif (angle <= 90 || angle > 270) {\n\t\t\t\t\t\t\t\tlabel.rotate(360 - angle, pos);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tlabel.rotate(180 - angle, pos);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tvar index = parseInt(numOfDockers/2);\n\t\t\t\t\t\t\tvar angle = this._getAngle(this.dockers[index], this.dockers[index+1])\n\t\t\t\t\t\t\tvar pos = this.dockers[index].bounds.center();\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif (angle <= 90 || angle > 270) {\n\t\t\t\t\t\t\t\tlabel.horizontalAlign(\"left\");\n\t\t\t\t\t\t\t\tlabel.verticalAlign(\"bottom\");\n\t\t\t\t\t\t\t\tlabel.x = pos.x + label.getOffsetTop();\n\t\t\t\t\t\t\t\tlabel.y = pos.y - label.getOffsetTop();\n\t\t\t\t\t\t\t\tlabel.rotate(360 - angle, pos);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tlabel.horizontalAlign(\"right\");\n\t\t\t\t\t\t\t\tlabel.verticalAlign(\"bottom\");\n\t\t\t\t\t\t\t\tlabel.x = pos.x - label.getOffsetTop();\n\t\t\t\t\t\t\t\tlabel.y = pos.y - label.getOffsetTop();\n\t\t\t\t\t\t\t\tlabel.rotate(180 - angle, pos);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"midbottom\":\n\t\t\t\t\t\tvar numOfDockers = this.dockers.length;\n\t\t\t\t\t\tif(numOfDockers%2 == 0) {\n\t\t\t\t\t\t\tvar angle = this._getAngle(this.dockers[numOfDockers/2-1], this.dockers[numOfDockers/2])\n\t\t\t\t\t\t\tvar pos1 = this.dockers[numOfDockers/2-1].bounds.center();\n\t\t\t\t\t\t\tvar pos2 = this.dockers[numOfDockers/2].bounds.center();\n\t\t\t\t\t\t\tvar pos = {x:(pos1.x + pos2.x)/2.0, y:(pos1.y+pos2.y)/2.0};\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tlabel.horizontalAlign(\"center\");\n\t\t\t\t\t\t\tlabel.verticalAlign(\"top\");\n\t\t\t\t\t\t\tlabel.x = pos.x;\n\t\t\t\t\t\t\tlabel.y = pos.y + label.getOffsetTop();\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif (angle <= 90 || angle > 270) {\n\t\t\t\t\t\t\t\tlabel.rotate(360 - angle, pos);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tlabel.rotate(180 - angle, pos);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tvar index = parseInt(numOfDockers/2);\n\t\t\t\t\t\t\tvar angle = this._getAngle(this.dockers[index], this.dockers[index+1])\n\t\t\t\t\t\t\tvar pos = this.dockers[index].bounds.center();\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif (angle <= 90 || angle > 270) {\n\t\t\t\t\t\t\t\tlabel.horizontalAlign(\"left\");\n\t\t\t\t\t\t\t\tlabel.verticalAlign(\"top\");\n\t\t\t\t\t\t\t\tlabel.x = pos.x + label.getOffsetBottom();\n\t\t\t\t\t\t\t\tlabel.y = pos.y + label.getOffsetBottom();\n\t\t\t\t\t\t\t\tlabel.rotate(360 - angle, pos);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tlabel.horizontalAlign(\"right\");\n\t\t\t\t\t\t\t\tlabel.verticalAlign(\"top\");\n\t\t\t\t\t\t\t\tlabel.x = pos.x - label.getOffsetBottom();\n\t\t\t\t\t\t\t\tlabel.y = pos.y + label.getOffsetBottom();\n\t\t\t\t\t\t\t\tlabel.rotate(180 - angle, pos);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"endtop\":\n\t\t\t\t\t\tvar length = this.dockers.length;\n\t\t\t\t\t\tvar angle = this._getAngle(this.dockers[length-2], this.dockers[length-1]);\n\t\t\t\t\t\tvar pos = this.dockers.last().bounds.center();\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (angle <= 90 || angle > 270) {\n\t\t\t\t\t\t\tlabel.horizontalAlign(\"right\");\n\t\t\t\t\t\t\tlabel.verticalAlign(\"bottom\");\n\t\t\t\t\t\t\tlabel.x = pos.x - label.getOffsetTop();\n\t\t\t\t\t\t\tlabel.y = pos.y - label.getOffsetTop();\n\t\t\t\t\t\t\tlabel.rotate(360 - angle, pos);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlabel.horizontalAlign(\"left\");\n\t\t\t\t\t\t\tlabel.verticalAlign(\"bottom\");\n\t\t\t\t\t\t\tlabel.x = pos.x + label.getOffsetTop();\n\t\t\t\t\t\t\tlabel.y = pos.y - label.getOffsetTop();\n\t\t\t\t\t\t\tlabel.rotate(180 - angle, pos);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"endbottom\":\n\t\t\t\t\t\tvar length = this.dockers.length;\n\t\t\t\t\t\tvar angle = this._getAngle(this.dockers[length-2], this.dockers[length-1]);\n\t\t\t\t\t\tvar pos = this.dockers.last().bounds.center();\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (angle <= 90 || angle > 270) {\n\t\t\t\t\t\t\tlabel.horizontalAlign(\"right\");\n\t\t\t\t\t\t\tlabel.verticalAlign(\"top\");\n\t\t\t\t\t\t\tlabel.x = pos.x - label.getOffsetBottom();\n\t\t\t\t\t\t\tlabel.y = pos.y + label.getOffsetBottom();\n\t\t\t\t\t\t\tlabel.rotate(360 - angle, pos);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlabel.horizontalAlign(\"left\");\n\t\t\t\t\t\t\tlabel.verticalAlign(\"top\");\n\t\t\t\t\t\t\tlabel.x = pos.x + label.getOffsetBottom();\n\t\t\t\t\t\t\tlabel.y = pos.y + label.getOffsetBottom();\n\t\t\t\t\t\t\tlabel.rotate(180 - angle, pos);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}.bind(this));\n\t\t\t\n\t\t\tthis.children.each(function(value) {\n\t\t\t\tif(value instanceof ORYX.Core.Node) {\n\t\t\t\t\tthis.calculatePositionOfAttachedChildNode.call(this, value);\n\t\t\t\t}\n\t\t\t}.bind(this));\n\t\t\t\n\t\t\tthis.refreshAttachedNodes();\n\t\t\tthis.refresh();\n\t\t\t\n\t\t\tthis.isChanged = false;\n\t\t\tthis._dockerUpdated = false;\n\t\t\t\n\t\t\tthis._oldBounds = this.bounds.clone();\n        }\n\t\t\n\t\t\n  \t    // IE10 specific fix, start and end-markes get left behind when moving path\n\t\tvar userAgent = navigator.userAgent;\n\t\tif (navigator.appVersion.indexOf(\"MSIE 10\") !== -1 || (userAgent.indexOf('Trident') !== -1 && userAgent.indexOf('rv:11') !== -1)) \n\t\t{\n\t\t\tthis.node.parentNode.insertBefore(this.node, this.node);\n\t\t}\n    },\n\t\n\t/**\n\t *  Moves a point to the upperLeft of a node's bounds.\n\t *  \n\t *  @param {point} point\n\t *  \tThe point to move\n\t *  @param {ORYX.Core.Bounds} bounds\n\t *  \tThe Bounds of the related noe\n\t */\n\tmovePointToUpperLeftOfNode: function(point, bounds) {\n\t\tpoint.x -= bounds.width()/2;\n\t\tpoint.y -= bounds.height()/2;\n\t},\n\t\n\t/**\n\t * Refreshes the visual representation of edge's attached nodes.\n\t */\t\n\trefreshAttachedNodes: function() {\n\t\tthis.attachedNodePositionData.values().each(function(nodeData) {\n\t\t\tvar startPoint = nodeData.segment.docker1.bounds.center();\n\t\t\tvar endPoint = nodeData.segment.docker2.bounds.center();\n\t\t\tthis.relativizePoint(startPoint);\n\t\t\tthis.relativizePoint(endPoint);\n\t\t\t\n\t\t\tvar newNodePosition = new Object();\n\t\t\t\n\t\t\t/* Calculate new x-coordinate */\n\t\t\tnewNodePosition.x = startPoint.x \n\t\t\t\t\t\t\t\t+ nodeData.relativDistanceFromDocker1\n\t\t\t\t\t\t\t\t\t* (endPoint.x - startPoint.x);\n\t\t\t\n\t\t\t/* Calculate new y-coordinate */\n\t\t\tnewNodePosition.y = startPoint.y \n\t\t\t\t\t\t\t\t+ nodeData.relativDistanceFromDocker1\n\t\t\t\t\t\t\t\t\t* (endPoint.y - startPoint.y);\n\t\t\t\n\t\t\t/* Convert new position to the upper left of the node */\n\t\t\tthis.movePointToUpperLeftOfNode(newNodePosition, nodeData.node.bounds);\n\t\t\t\n\t\t\t/* Move node to its new position */\n\t\t\tnodeData.node.bounds.moveTo(newNodePosition);\n\t\t\tnodeData.node._update();\t\t\t\t\t\n\t\t\t\n\t\t}.bind(this));\n\t},\n\t\n\t/**\n\t * Calculates the position of an edge's child node. The node is placed on \n\t * the path of the edge.\n\t * \n\t * @param {node}\n\t * \t\tThe node to calculate the new position\n\t * @return {Point}\n\t * \t\tThe calculated upper left point of the node's shape.\n\t */\n\tcalculatePositionOfAttachedChildNode: function(node) {\n\t\t/* Initialize position */\n\t\tvar position = new Object();\n\t\tposition.x = 0;\n\t\tposition.y = 0;\n\t\t\n\t\t/* Case: Node was just added */\n\t\tif(!this.attachedNodePositionData[node.getId()]) {\n\t\t\tthis.attachedNodePositionData[node.getId()] = new Object();\n\t\t\tthis.attachedNodePositionData[node.getId()]\n\t\t\t\t\t.relativDistanceFromDocker1 = 0;\n\t\t\tthis.attachedNodePositionData[node.getId()].node = node;\n\t\t\tthis.attachedNodePositionData[node.getId()].segment = new Object();\n\t\t\tthis.findEdgeSegmentForNode(node);\n\t\t}else if(node.isChanged) {\n\t\t\tthis.findEdgeSegmentForNode(node);\n\t\t}\n\t\t\n\t\t\n\t\t\n\t},\n\t\n\t/**\n\t * Finds the appropriate edge segement for a node.\n\t * The segment is choosen, which has the smallest distance to the node.\n\t * \n\t * @param {ORYX.Core.Node} node\n\t * \t\tThe concerning node\n\t */\n\tfindEdgeSegmentForNode: function(node) {\n\t\tvar length = this.dockers.length;\n\t\tvar smallestDistance = undefined;\n\t\t\n\t\tfor(i=1;i<length;i++) {\n\t\t\tvar lineP1 = this.dockers[i-1].bounds.center();\n\t\t\tvar lineP2 = this.dockers[i].bounds.center();\n\t\t\tthis.relativizePoint(lineP1);\n\t\t\tthis.relativizePoint(lineP2);\n\t\t\t\n\t\t\tvar nodeCenterPoint = node.bounds.center();\n\t\t\tvar distance = ORYX.Core.Math.distancePointLinie(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tlineP1,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tlineP2, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnodeCenterPoint, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttrue);\n\t\t\t\n\t\t\tif((distance || distance == 0) && ((!smallestDistance && smallestDistance != 0) \n\t\t\t\t\t\t|| distance < smallestDistance)) {\n\t\t\t\t\n\t\t\t\tsmallestDistance = distance;\n\t\t\t\t\n\t\t\t\tthis.attachedNodePositionData[node.getId()].segment.docker1 = \n\t\t\t\t\t\t\t\t\t\t\t\t\tthis.dockers[i-1];\n\t\t\t\tthis.attachedNodePositionData[node.getId()].segment.docker2 = \n\t\t\t\t\t\t\t\t\t\t\t\t\tthis.dockers[i];\n\t\n\t\t\t}\n\t\t\t\n\t\t\t/* Either the distance does not match the segment or the distance\n\t\t\t * between docker1 and docker2 is 0\n\t\t\t * \n\t\t\t * In this case choose the nearest docker as attaching point.\n\t\t\t * \n\t\t\t */\n\t\t\tif(!distance && !smallestDistance && smallestDistance != 0) {\n\t\t\t\t(ORYX.Core.Math.getDistancePointToPoint(nodeCenterPoint, lineP1)\n\t\t\t\t\t< ORYX.Core.Math.getDistancePointToPoint(nodeCenterPoint, lineP2)) ?\n\t\t\t\t\tthis.attachedNodePositionData[node.getId()].relativDistanceFromDocker1 = 0 :\n\t\t\t\t\tthis.attachedNodePositionData[node.getId()].relativDistanceFromDocker1 = 1;\n\t\t\t\tthis.attachedNodePositionData[node.getId()].segment.docker1 = \n\t\t\t\t\t\t\t\t\t\t\t\t\tthis.dockers[i-1];\n\t\t\t\tthis.attachedNodePositionData[node.getId()].segment.docker2 = \n\t\t\t\t\t\t\t\t\t\t\t\t\tthis.dockers[i];\n\t\t\t}\n\t\t}\n\t\t\n\t\t/* Calculate position on edge segment for the node */\n\t\tif(smallestDistance || smallestDistance == 0) {\n\t\t\tthis.attachedNodePositionData[node.getId()].relativDistanceFromDocker1 =\n\t\t\tthis.getLineParameterForPosition(\n\t\t\t\t\tthis.attachedNodePositionData[node.getId()].segment.docker1,\n\t\t\t\t\tthis.attachedNodePositionData[node.getId()].segment.docker2,\n\t\t\t\t\tnode);\n\t\t}\n\t},\n\t\n\t\n\t/**\n\t *\n\t * @param {ORYX.Core.Node|Object} node or position\n\t * @return {Object} An object with the following attribute: {ORYX.Core.Docker} fromDocker, {ORYX.Core.Docker} toDocker, {X/Y} position, {int} distance\n\t */\n \tfindSegment: function(node){\n\t\t\n\t\tvar length = this.dockers.length;\n\t\tvar result;\n\t\t\n\t\tvar nodeCenterPoint = node instanceof ORYX.Core.UIObject ? node.bounds.center() : node;\n\t\t\t\n\t\tfor (i = 1; i < length; i++) {\n\t\t\tvar lineP1 = this.dockers[i - 1].bounds.center();\n\t\t\tvar lineP2 = this.dockers[i].bounds.center();\n\t\t\t\n\t\t\tvar distance = ORYX.Core.Math.distancePointLinie(lineP1, lineP2, nodeCenterPoint, true);\n\t\t\t\n\t\t\tif (typeof distance == \"number\" && (result === undefined || distance < result.distance)) {\n\t\t\t\tresult = {\n\t\t\t\t\tdistance: distance,\n\t\t\t\t\tfromDocker: this.dockers[i - 1],\n\t\t\t\t\ttoDocker: this.dockers[i]\n\t\t\t\t}\n\t\t\t\t\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t},\n\t\n\t/**\n\t * Returns the value of the scalar to determine the position of the node on \n\t * line defined by docker1 and docker2.\n\t * \n\t * @param {point} docker1\n\t * \t\tThe docker that defines the start of the line segment\n\t * @param {point} docker2\n\t * \t\tThe docker that defines the end of the line segment\n\t * @param {ORYX.Core.Node} node\n\t * \t\tThe concerning node\n\t * \n\t * @return {float} positionParameter\n\t * \t\tThe scalar value to determine the position on the line\n\t */\n\tgetLineParameterForPosition: function(docker1, docker2, node) {\n\t\tvar dockerPoint1 = docker1.bounds.center();\n\t\tvar dockerPoint2 = docker2.bounds.center();\n\t\tthis.relativizePoint(dockerPoint1);\n\t\tthis.relativizePoint(dockerPoint2);\n\t\t\n\t\tvar intersectionPoint = ORYX.Core.Math.getPointOfIntersectionPointLine(\n\t\t\t\t\t\t\t\t\tdockerPoint1,\n\t\t\t\t\t\t\t\t\tdockerPoint2,\n\t\t\t\t\t\t\t\t\tnode.bounds.center(), true);\n\t\tif(!intersectionPoint) {\n\t\t\treturn 0;\n\t\t}\n\t\t\n\t\tvar relativeDistance = \n\t\t\tORYX.Core.Math.getDistancePointToPoint(intersectionPoint, dockerPoint1) /\n\t\t\tORYX.Core.Math.getDistancePointToPoint(dockerPoint1, dockerPoint2);\n\t\t\n\t\treturn relativeDistance;\n\t},\n\t/**\n\t * Makes point relative to the upper left of the edge's bound.\n\t * \n\t * @param {point} point\n\t * \t\tThe point to relativize\n\t */\n\trelativizePoint: function(point) {\n\t\tpoint.x -= this.bounds.upperLeft().x;\n\t\tpoint.y -= this.bounds.upperLeft().y;\t\t\n\t},\n\t\n\t/**\n\t * Move the first and last docker and calls the refresh method.\n\t * Attention: This does not calculates intersection point between the\n\t * edge and the bounded nodes. This only works if only the nodes are\n\t * moves.\n\t *\n\t */\n\toptimizedUpdate: function(){\n\t\t\n\t\tvar updateDocker = function(docker){\n\t\t\tif (!docker._dockedShape || !docker._dockedShapeBounds)\n\t\t\t\treturn;\n\t\t\tvar off = {\n\t\t\t    x: docker._dockedShape.bounds.a.x - docker._dockedShapeBounds.a.x,\n\t\t\t    y: docker._dockedShape.bounds.a.y - docker._dockedShapeBounds.a.y\n\t\t\t};\n\t\t\tdocker.bounds.moveBy(off);\n\t\t\tdocker._dockedShapeBounds.moveBy(off);\n\t\t}\n\t\t\n\t\tupdateDocker(this.dockers.first());\n\t\tupdateDocker(this.dockers.last());\n\t\t\n\t\tthis.refresh();\n\t},\n    \n    refresh: function(){\n        //call base class refresh method\n        arguments.callee.$.refresh.apply(this, arguments);\n        \n        //TODO consider points for marker mids\n        var lastPoint;\n        this._paths.each((function(path, index){\n            var dockers = this._dockersByPath[path.id];\n            var c = undefined;\n\t\t\tvar d = undefined;\n            if (lastPoint) {\n                d = \"M\" + lastPoint.x + \" \" + lastPoint.y;\n            }\n            else {\n                c = dockers[0].bounds.center();\n                lastPoint = c;\n                \n                d = \"M\" + c.x + \" \" + c.y;\n            }\n            \n            for (var i = 1; i < dockers.length; i++) {\n                // for each docker, draw a line to the center\n                c = dockers[i].bounds.center();\n                d = d + \"L\" + c.x + \" \" + c.y + \" \";\n                lastPoint = c;\n            }\n            \n            path.setAttributeNS(null, \"d\", d);\n            this._interactionPaths[index].setAttributeNS(null, \"d\", d);\n            \n        }).bind(this));\n\t\t\n\t\t\n\t\t/* move child shapes of an edge */\n\t\tif(this.getChildNodes().length > 0) {\n\t        var x = this.bounds.upperLeft().x;\n\t        var y = this.bounds.upperLeft().y;\n\t        \n\t\t\tthis.node.firstChild.childNodes[1].setAttributeNS(null, \"transform\", \"translate(\" + x + \", \" + y + \")\");\n\t\t}\n\t\t\n    },\n    \n    /**\n     * Calculate the Border Intersection Point between two points\n     * @param {PointA}\n     * @param {PointB}\n     */\n    getIntersectionPoint: function(){\n    \n        var length = Math.floor(this.dockers.length / 2)\n        \n        return ORYX.Core.Math.midPoint(this.dockers[length - 1].bounds.center(), this.dockers[length].bounds.center())\n    },\n    \n\t/**\n     * Returns TRUE if the bounds is over the edge\n     * @param {Bounds}\n     *\n     */\n    isBoundsIncluded: function(bounds){\n\t\tvar dockers = this.dockers, size = dockers.length;\n\t\treturn dockers.any(function(docker, i){\n\t\t\tif (i == size-1){ return false; }\n\t\t\tvar a = docker.bounds.center();\n\t\t\tvar b = dockers[i+1].bounds.center();\n\t\t\t\n\t\t\treturn ORYX.Core.Math.isRectOverLine(a.x, a.y, b.x, b.y, bounds.a.x, bounds.a.y, bounds.b.x, bounds.b.y);\n\t\t});\n\t},\n    \n    /**\n     * Calculate if the point is inside the Shape\n     * @param {PointX}\n     * @param {PointY} \n     */\n    isPointIncluded: function(pointX, pointY){\n    \n        var isbetweenAB = this.absoluteBounds().isIncluded(pointX, pointY, \n\t\t\t\t\t\t\t\t\t\t\t\tORYX.CONFIG.OFFSET_EDGE_BOUNDS);\n        \n\t\tvar isPointIncluded = undefined;\n\t\t\n        if (isbetweenAB && this.dockers.length > 0) {\n\t\t\n\t\t\tvar i = 0;\n\t\t\tvar point1, point2;\n\t\t\t\n\t\t\t\n\t\t\tdo {\n\t\t\t\n\t\t\t\tpoint1 = this.dockers[i].bounds.center();\n\t\t\t\tpoint2 = this.dockers[++i].bounds.center();\n\t\t\t\t\n\t\t\t\tisPointIncluded = ORYX.Core.Math.isPointInLine(pointX, pointY, \n\t\t\t\t\t\t\t\t\t\t\tpoint1.x, point1.y, \n\t\t\t\t\t\t\t\t\t\t\tpoint2.x, point2.y, \n\t\t\t\t\t\t\t\t\t\t\tORYX.CONFIG.OFFSET_EDGE_BOUNDS);\n\t\t\t\t\n\t\t\t} while (!isPointIncluded && i < this.dockers.length - 1)\n\t\t\t\n\t\t}\n\t\t\n\t\treturn isPointIncluded;\n\n    },\n  \n    \n    /**\n     * Calculate if the point is over an special offset area\n     * @param {Point}\n     */\n    isPointOverOffset: function(){\n\t\treturn  false\n\t},\n\t\n\t/**\n\t * Returns TRUE if the given node\n\t * is a child node of the shapes node\n\t * @param {Element} node\n\t * @return {Boolean}\n\t *\n\t */\n\tcontainsNode: function(node){\n\t\tif (this._paths.include(node) || \n       \t\tthis._interactionPaths.include(node)){\n\t\t\treturn true;\t\t\n\t\t}\t\n\t\treturn false;\n\t},\n\t\n\t/**\n\t* Returns the angle of the line between two dockers\n\t* (0 - 359.99999999)\n\t*/\n\t_getAngle: function(docker1, docker2) {\n\t\tvar p1 = docker1 instanceof ORYX.Core.Controls.Docker ? docker1.absoluteCenterXY() : docker1;\n\t\tvar p2 = docker2 instanceof ORYX.Core.Controls.Docker ? docker2.absoluteCenterXY() : docker2;\n\t\t\n\t\treturn ORYX.Core.Math.getAngle(p1, p2);\n\t},\n\t    \n    alignDockers: function(){\n        this._update(true);\n        \n        var firstPoint = this.dockers.first().bounds.center();\n        var lastPoint = this.dockers.last().bounds.center();\n        \n        var deltaX = lastPoint.x - firstPoint.x;\n        var deltaY = lastPoint.y - firstPoint.y;\n        \n        var numOfDockers = this.dockers.length - 1;\n        \n        this.dockers.each((function(docker, index){\n            var part = index / numOfDockers;\n            docker.bounds.unregisterCallback(this._dockerChangedCallback);\n            docker.bounds.moveTo(firstPoint.x + part * deltaX, firstPoint.y + part * deltaY);\n            docker.bounds.registerCallback(this._dockerChangedCallback);\n        }).bind(this));\n        \n        this._dockerChanged();\n    },\n    \n\tadd: function(shape){\n        arguments.callee.$.add.apply(this, arguments);\n\t\t\n\t\t// If the new shape is a Docker which is not contained\n\t\tif (shape instanceof ORYX.Core.Controls.Docker && this.dockers.include(shape)){\n\t\t\t// Add it to the dockers list ordered by paths\t\t\n\t\t\tvar pathArray = this._dockersByPath.values()[0];\n\t\t\tif (pathArray) {\n\t\t\t\tpathArray.splice(this.dockers.indexOf(shape), 0, shape);\n\t\t\t}\n\t\t\t\n\t\t\t/* Perform nessary adjustments on the edge's child shapes */\n\t\t\tthis.handleChildShapesAfterAddDocker(shape);\n\t\t}\n\t},\n\t\n\t/**\n\t * Performs nessary adjustments on the edge's child shapes.\n\t * \n\t * @param {ORYX.Core.Controls.Docker} docker\n\t * \t\tThe added docker\n\t */\n\thandleChildShapesAfterAddDocker: function(docker) {\n\t\t/* Ensure type of Docker */\n\t\tif(!docker instanceof ORYX.Core.Controls.Docker) {return undefined;}\n\t\t\n\t\tvar index = this.dockers.indexOf(docker);\n\t\tif(!(0 < index && index < this.dockers.length - 1)) {\n\t\t/* Exception: Expect added docker between first and last node of the edge */\n\t\t\treturn undefined;\n\t\t} \n\t\t\t\n\t\t/* Get child nodes concerning the segment of the new docker */\n\t\tvar startDocker = this.dockers[index-1];\n\t\tvar endDocker = this.dockers[index+1];\n\t\t\n\t\t/* Adjust the position of edge's child nodes */\n\t\tvar segmentElements = \n\t\t\tthis.getAttachedNodePositionDataForSegment(startDocker, endDocker);\n\t\t\n\t\tvar lengthSegmentPart1 = ORYX.Core.Math.getDistancePointToPoint(\n\t\t\t\t\t\t\t\t\t\tstartDocker.bounds.center(),\n\t\t\t\t\t\t\t\t\t\tdocker.bounds.center());\n\t\tvar lengthSegmentPart2 = ORYX.Core.Math.getDistancePointToPoint(\n\t\t\t\t\t\t\t\t\t\tendDocker.bounds.center(),\n\t\t\t\t\t\t\t\t\t\tdocker.bounds.center());\n\t\t\t\t\t\t\t\t\t\t\n\t\tif(!(lengthSegmentPart1 + lengthSegmentPart2)) {return;}\n\t\t\n\t\tvar relativDockerPosition = lengthSegmentPart1 / (lengthSegmentPart1 + lengthSegmentPart2);\n\t\t\t\n\t\tsegmentElements.each(function(nodePositionData) {\n\t\t\t/* Assign child node to the new segment */\n\t\t\tif(nodePositionData.value.relativDistanceFromDocker1 < relativDockerPosition) {\n\t\t\t\t/* Case: before added Docker */\n\t\t\t\tnodePositionData.value.segment.docker2 = docker;\n\t\t\t\tnodePositionData.value.relativDistanceFromDocker1 = \n\t\t\t\t\tnodePositionData.value.relativDistanceFromDocker1 / relativDockerPosition;\n\t\t\t} else {\n\t\t\t\t/* Case: after added Docker */\n\t\t\t\tnodePositionData.value.segment.docker1 = docker;\n\t\t\t\tvar newFullDistance = 1 - relativDockerPosition;\n\t\t\t\tvar relativPartOfSegment = \n\t\t\t\t\t\t\tnodePositionData.value.relativDistanceFromDocker1\n\t\t\t\t\t\t\t- relativDockerPosition;\n\t\t\t\t\n\t\t\t\tnodePositionData.value.relativDistanceFromDocker1 = \n\t\t\t\t\t\t\t\t\t\trelativPartOfSegment / newFullDistance;\n\t\t\t\t\n\t\t\t}\n\t\t})\n\t\t\n\t\t\n\t\t// Update all labels reference points\n\t\tthis.getLabels().each(function(label){\n\n\t\t\tvar ref = label.getReferencePoint();\n\t\t\tif (!ref) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar index = this.dockers.indexOf(docker);\n\t\t\tif (index >= ref.segment.fromIndex && index <= ref.segment.toIndex){\n\t\t\t\t\n\t\t\t\tvar segment = this.findSegment(ref.intersection);\n\t\t\t\tif (!segment){ \n\t\t\t\t\t// Choose whether the first of the last segment\n\t\t\t\t\tsegment.fromDocker = ref.segment.fromIndex >= (this.dockers.length/2) ? this.dockers[0] : this.dockers[this.dockers.length-2]; \n\t\t\t\t\tsegment.toDocker = this.dockers[this.dockers.indexOf(from)+1]; // The next one if the to docker\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tvar fromPosition = segment.fromDocker.bounds.center(), toPosition = segment.toDocker.bounds.center();\n\t\t\t\n\t\t\t\tvar intersection = ORYX.Core.Math.getPointOfIntersectionPointLine(\n\t\t\t\t\t\t\t\t\t\tfromPosition, \t\t// P1 - Center of the first docker\n\t\t\t\t\t\t\t\t\t\ttoPosition, \t\t// P2 - Center of the second docker\n\t\t\t\t\t\t\t\t\t\tref.intersection, \t// P3 - Center of the label\n\t\t\t\t\t\t\t\t\t\ttrue);\n\t\t\t\t//var oldDistance = ORYX.Core.Math.getDistanceBetweenTwoPoints(ref.segment.fromPosition, ref.segment.toPosition, ref.intersection);\n\t\t\t\t//intersection = ORYX.Core.Math.getPointBetweenTwoPoints(fromPosition, toPosition, isNaN(oldDistance) ? 0.5 : (lengthOld*oldDistance)/lengthNew);\n\t\t\t\t\t\n\t\t\t\t// Update the reference point\n\t\t\t\tthis.updateReferencePointOfLabel(label, intersection, segment.fromDocker, segment.toDocker, true);\n\t\t\t}\n\t\t}.bind(this));\n\t\t\n\t\t/* Update attached nodes visual representation */\n\t\tthis.refreshAttachedNodes();\n\t},\n\t\n\t/**\n\t *\tReturns elements from {@link attachedNodePositiondata} that match the\n\t *  segement defined by startDocker and endDocker.\n\t *  \n\t *  @param {ORYX.Core.Controls.Docker} startDocker\n\t *  \tThe docker defining the begin of the segment.\n\t *  @param {ORYX.Core.Controls.Docker} endDocker\n\t *  \tThe docker defining the begin of the segment.\n\t *  \n\t *  @return {Hash} attachedNodePositionData\n\t *  \tChild elements matching the segment\n\t */\n\tgetAttachedNodePositionDataForSegment: function(startDocker, endDocker) {\n\t\t/* Ensure that the segment is defined correctly */\n\t\tif(!((startDocker instanceof ORYX.Core.Controls.Docker) \n\t\t\t&& (endDocker instanceof ORYX.Core.Controls.Docker))) {\n\t\t\t\treturn [];\n\t\t\t}\n\t\t\t\n\t\t/* Get elements of the segment */\n\t\tvar elementsOfSegment = \n\t\t\tthis.attachedNodePositionData.findAll(function(nodePositionData) {\n\t\t\t\treturn nodePositionData.value.segment.docker1 === startDocker &&\n\t\t\t\t\t\tnodePositionData.value.segment.docker2 === endDocker;\n\t\t\t});\n\t\t\n\t\t/* Return a Hash in each case */\n\t\tif(!elementsOfSegment) {return [];}\n\t\t\n\t\treturn elementsOfSegment;\n\t},\n\t\n\t/**\n\t * Removes an edge's child shape\n\t */\n\tremove: function(shape) {\n\t\targuments.callee.$.remove.apply(this, arguments);\n\t\t\n\t\tif(this.attachedNodePositionData[shape.getId()]) {\n\t\t\tdelete this.attachedNodePositionData[shape.getId()];\n\t\t}\n\t\t\n\t\t/* Adjust child shapes if neccessary */\n\t\tif(shape instanceof ORYX.Core.Controls.Docker) {\n\t\t\tthis.handleChildShapesAfterRemoveDocker(shape);\n\t\t}\n\t},\n\t\n\tupdateReferencePointOfLabel: function(label, intersection, from, to, dirty){\n\t\tif (!label.getReferencePoint() || !label.isVisible) {\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tvar ref = label.getReferencePoint();\n\t\t\n\t\t//\n\t\tif (ref.orientation && ref.orientation !== \"ce\"){\n\t\t\tvar angle = this._getAngle(from, to);\n\t\t\tif (ref.distance >= 0){\n\t\t\t\tif(angle == 0){\n\t\t\t\t\tlabel.horizontalAlign(\"left\");//ref.orientation == \"lr\" ? \"right\" : \"left\");\n\t\t\t\t\tlabel.verticalAlign(\"bottom\");\n\t\t\t\t} else if (angle > 0 && angle < 90){\n\t\t\t\t\tlabel.horizontalAlign(\"right\");\n\t\t\t\t\tlabel.verticalAlign(\"bottom\");\n\t\t\t\t} else if (angle == 90){\n\t\t\t\t\tlabel.horizontalAlign(\"right\");\n\t\t\t\t\tlabel.verticalAlign(\"top\");//ref.orientation == \"lr\" ? \"bottom\" : \"top\");\n\t\t\t\t} else if (angle > 90 && angle < 180){\n\t\t\t\t\tlabel.horizontalAlign(\"right\");\n\t\t\t\t\tlabel.verticalAlign(\"top\");\n\t\t\t\t} else if (angle == 180){\n\t\t\t\t\tlabel.horizontalAlign(\"left\");//ref.orientation == \"ur\" ? \"right\" : \"left\");\n\t\t\t\t\tlabel.verticalAlign(\"top\");\n\t\t\t\t} else if (angle > 180 && angle < 270){\n\t\t\t\t\tlabel.horizontalAlign(\"left\");\n\t\t\t\t\tlabel.verticalAlign(\"top\");\t\t\t\t\n\t\t\t\t} else if (angle == 270){\n\t\t\t\t\tlabel.horizontalAlign(\"left\");\n\t\t\t\t\tlabel.verticalAlign(\"top\");//ref.orientation == \"ll\" ? \"bottom\" : \"top\");\n\t\t\t\t} else if (angle > 270 && angle <= 360){\n\t\t\t\t\tlabel.horizontalAlign(\"left\");\n\t\t\t\t\tlabel.verticalAlign(\"bottom\");\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif(angle == 0){\n\t\t\t\t\tlabel.horizontalAlign(\"left\");//ref.orientation == \"ur\" ? \"right\" : \"left\");\n\t\t\t\t\tlabel.verticalAlign(\"top\");\n\t\t\t\t} else if (angle > 0 && angle < 90){\n\t\t\t\t\tlabel.horizontalAlign(\"left\");\n\t\t\t\t\tlabel.verticalAlign(\"top\");\n\t\t\t\t} else if (angle == 90){\n\t\t\t\t\tlabel.horizontalAlign(\"left\");\n\t\t\t\t\tlabel.verticalAlign(\"top\");//ref.orientation == \"ll\" ? \"bottom\" : \"top\");\n\t\t\t\t} else if (angle > 90 && angle < 180){\n\t\t\t\t\tlabel.horizontalAlign(\"left\");\n\t\t\t\t\tlabel.verticalAlign(\"bottom\");\n\t\t\t\t} else if (angle == 180){\n\t\t\t\t\tlabel.horizontalAlign(\"left\");//ref.orientation == \"lr\" ? \"right\" : \"left\");\n\t\t\t\t\tlabel.verticalAlign(\"bottom\");\n\t\t\t\t} else if (angle > 180 && angle < 270){\n\t\t\t\t\tlabel.horizontalAlign(\"right\");\n\t\t\t\t\tlabel.verticalAlign(\"bottom\");\n\t\t\t\t} else if (angle == 270){\n\t\t\t\t\tlabel.horizontalAlign(\"right\");\n\t\t\t\t\tlabel.verticalAlign(\"top\");//ref.orientation == \"lr\" ? \"bottom\" : \"top\");\n\t\t\t\t} else if (angle > 270 && angle <= 360){\n\t\t\t\t\tlabel.horizontalAlign(\"right\");\n\t\t\t\t\tlabel.verticalAlign(\"top\");\n\t\t\t\t}\t\t\t\n\t\t\t}\n\t\t\tref.iorientation = ref.iorientation || ref.orientation;\n\t\t\tref.orientation = (label.verticalAlign()==\"top\"?\"u\":\"l\") + (label.horizontalAlign()==\"left\"?\"l\":\"r\");\n\t\t}\n\t\n\t\tlabel.setReferencePoint(jQuery.extend({},{\n\t\t\t\tintersection: intersection,\n\t\t\t\tsegment: {\n\t\t\t\t\tfrom: from,\n\t\t\t\t\tfromIndex: this.dockers.indexOf(from),\n\t\t\t\t\tfromPosition: from.bounds.center(),\n\t\t\t\t\tto: to,\n\t\t\t\t\ttoIndex: this.dockers.indexOf(to),\n\t\t\t\t\ttoPosition: to.bounds.center()\n\t\t\t\t},\n\t\t\t\tdirty: dirty || false\n\t\t\t},ref))\n\t},\n\t/**\n\t * \tAdjusts the child shapes of an edges after a docker was removed.\n\t * \t\n\t *  @param{ORYX.Core.Controls.Docker} docker\n\t *  \tThe removed docker.\n\t */\n\thandleChildShapesAfterRemoveDocker: function(docker) {\n\t\t/* Ensure docker type */\n\t\tif(!(docker instanceof ORYX.Core.Controls.Docker)) {return;}\n\t\t\n\t\tthis.attachedNodePositionData.each(function(nodePositionData) {\n\t\t\tif(nodePositionData.value.segment.docker1 === docker) {\n\t\t\t\t/* The new start of the segment is the predecessor of docker2. */\n\t\t\t\tvar index = this.dockers.indexOf(nodePositionData.value.segment.docker2);\n\t\t\t\tif(index == -1) {return;}\n\t\t\t\tnodePositionData.value.segment.docker1 = this.dockers[index - 1];\n\t\t\t} \n\t\t\telse if(nodePositionData.value.segment.docker2 === docker) {\n\t\t\t\t/* The new end of the segment is the successor of docker1. */\n\t\t\t\tvar index = this.dockers.indexOf(nodePositionData.value.segment.docker1);\n\t\t\t\tif(index == -1) {return;}\n\t\t\t\tnodePositionData.value.segment.docker2 = this.dockers[index + 1];\n\t\t\t}\n\t\t}.bind(this));\n\t\t\n\t\t// Update all labels reference points\n\t\tthis.getLabels().each(function(label){\n\n\t\t\tvar ref = label.getReferencePoint();\n\t\t\tif (!ref) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar from = ref.segment.from;\n\t\t\tvar to = ref.segment.to;\n\t\t\t\n\t\t\tif (from !== docker && to !== docker){ \n\t\t\t\treturn; \n\t\t\t}\n\t\t\t\n\t\t\tvar segment = this.findSegment(ref.intersection);\n\t\t\tif (!segment){ \n\t\t\t\tfrom = segment.fromDocker;\n\t\t\t\tto = segment.toDocker;\n\t\t\t} else {\n\t\t\t\tfrom = from === docker ? this.dockers[this.dockers.indexOf(to)-1] : from;\n\t\t\t\tto = this.dockers[this.dockers.indexOf(from)+1];\n\t\t\t}\n\n\t\t\tvar intersection = ORYX.Core.Math.getPointOfIntersectionPointLine(from.bounds.center(), to.bounds.center(), ref.intersection, true);\t\t\t\n\t\t\t// Update the reference point\n\t\t\tthis.updateReferencePointOfLabel(label, intersection, from, to, true);\n\t\t}.bind(this));\n\t\t\n\t\t/* Update attached nodes visual representation */\n\t\tthis.refreshAttachedNodes();\n\t},\n\t\n\t/**\n     *@deprecated Use the .createDocker() Method and set the point via the bounds\n     */\n    addDocker: function(position, exDocker){\n        var lastDocker;\n\t\tvar result;\n        this._dockersByPath.any((function(pair){\n            return pair.value.any((function(docker, index){\n                if (!lastDocker) {\n                    lastDocker = docker;\n                    return false;\n                }\n                else {\n                    var point1 = lastDocker.bounds.center();\n                    var point2 = docker.bounds.center();\n                    \n                    var additionalIEZoom = 1;\n                    if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) {\n                        var ua = navigator.userAgent;\n                        if (ua.indexOf('MSIE') >= 0) {\n                            //IE 10 and below\n                            var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100);\n                            if (zoom !== 100) {\n                                additionalIEZoom = zoom / 100\n                            }\n                        }\n                    }\n                    \n                    if (additionalIEZoom !== 1) {\n                        position.x = position.x / additionalIEZoom;\n                        position.y = position.y / additionalIEZoom;\n                    }\n                    \n                    if (ORYX.Core.Math.isPointInLine(position.x, position.y, point1.x, point1.y, point2.x, point2.y, 10)) {\n                        var path = this._paths.find(function(path){\n                            return path.id === pair.key;\n                        });\n                        if (path) {\n                            var allowAttr = path.getAttributeNS(NAMESPACE_ORYX, 'allowDockers');\n                            if (allowAttr && allowAttr.toLowerCase() === \"no\") {\n                                return true;\n                            }\n                        }\n                        \n                        var newDocker = (exDocker) ? exDocker : this.createDocker(this.dockers.indexOf(lastDocker) + 1, position);\n\t\t\t\t\t\tnewDocker.bounds.centerMoveTo(position);\n                        if(exDocker)\n\t\t\t\t\t\t\tthis.add(newDocker, this.dockers.indexOf(lastDocker) + 1);\n\t\t\t\t\t\tresult = newDocker;\n                        return true;\n                    }\n                    else {\n                        lastDocker = docker;\n                        return false;\n                    }\n                }\n            }).bind(this));\n        }).bind(this));\n\t\treturn result;\n    },\n    \n    removeDocker: function(docker){\n        if (this.dockers.length > 2 && !(this.dockers.first() === docker)) {\n            this._dockersByPath.any((function(pair){\n                if (pair.value.member(docker)) {\n                    if (docker === pair.value.last()) {\n                        return true;\n                    }\n                    else {\n                        this.remove(docker);\n                        this._dockersByPath[pair.key] = pair.value.without(docker);\n                        this.isChanged = true;\n                        this._dockerChanged();\n                        return true;\n                    }\n                }\n                return false;\n            }).bind(this));\n        }\n    },\n\t\n\t/**\n\t * Removes all dockers from the edge which are on \n\t * the line between two dockers\n\t * @return {Object} Removed dockers in an indicied array \n\t * (key is the removed position of the docker, value is docker themselve)\n\t */\n\tremoveUnusedDockers:function(){\n\t\tvar marked = $H({});\n\t\t\n\t\tthis.dockers.each(function(docker, i){\n\t\t\tif (i==0||i==this.dockers.length-1){ return }\n\t\t\tvar previous = this.dockers[i-1];\n\t\t\t\n\t\t\t/* Do not consider already removed dockers */\n\t\t\tif(marked.values().indexOf(previous) != -1 && this.dockers[i-2]) {\n\t\t\t\tprevious = this.dockers[i-2];\n\t\t\t}\n\t\t\tvar next = this.dockers[i+1];\n\t\t\t\n\t\t\tvar cp = previous.getDockedShape() && previous.referencePoint ? previous.getAbsoluteReferencePoint() : previous.bounds.center();\n\t\t\tvar cn = next.getDockedShape() && next.referencePoint ? next.getAbsoluteReferencePoint() : next.bounds.center();\n\t\t\tvar cd = docker.bounds.center();\n\t\t\t\n\t\t\tif (ORYX.Core.Math.isPointInLine(cd.x, cd.y, cp.x, cp.y, cn.x, cn.y, 1)){\n\t\t\t\tmarked[i] = docker;\n\t\t\t}\n\t\t}.bind(this))\n\t\t\n\t\tmarked.each(function(docker){\n\t\t\tthis.removeDocker(docker.value);\n\t\t}.bind(this))\n\t\t\n\t\tif (marked.values().length > 0){\n\t\t\tthis._update(true);\n\t\t}\n\t\t\n\t\treturn marked;\n\t},\n    \n    /**\n     * Initializes the Edge after loading the SVG representation of the edge.\n     * @param {SVGDocument} svgDocument\n     */\n    _init: function(svgDocument){\n        arguments.callee.$._init.apply(this, arguments);\n        \n        var minPointX, minPointY, maxPointX, maxPointY;\n        \n        //init markers\n        var defs = svgDocument.getElementsByTagNameNS(NAMESPACE_SVG, \"defs\");\n        if (defs.length > 0) {\n            defs = defs[0];\n            var markerElements = $A(defs.getElementsByTagNameNS(NAMESPACE_SVG, \"marker\"));\n            var marker;\n            var me = this;\n            markerElements.each(function(markerElement){\n                try {\n                    marker = new ORYX.Core.SVG.SVGMarker(markerElement.cloneNode(true));\n                    me._markers[marker.id] = marker;\n                    var textElements = $A(marker.element.getElementsByTagNameNS(NAMESPACE_SVG, \"text\"));\n                    var label;\n                    textElements.each(function(textElement){\n                        label = new ORYX.Core.SVG.Label({\n                            textElement: textElement,\n\t\t\t\t\t\t\tshapeId: this.id\n                        });\n                        me._labels[label.id] = label;\n                    });\n                } \n                catch (e) {\n                }\n            });\n        }\n        \n        \n        var gs = svgDocument.getElementsByTagNameNS(NAMESPACE_SVG, \"g\");\n        if (gs.length <= 0) {\n            throw \"Edge: No g element found.\";\n        }\n        var g = gs[0];\n        \n        \n        g.setAttributeNS(null, \"id\", null);\n        \n        var isFirst = true;\n        \n        $A(g.childNodes).each((function(path, index){\n            if (ORYX.Editor.checkClassType(path, SVGPathElement)) {\n                path = path.cloneNode(false);\n                \n                var pathId = this.id + \"_\" + index;\n                path.setAttributeNS(null, \"id\", pathId);\n                this._paths.push(path);\n                \n                //check, if markers are set and update the id\n                var markersByThisPath = [];\n                var markerUrl = path.getAttributeNS(null, \"marker-start\");\n                \n                if (markerUrl && markerUrl !== \"\") {\n                    markerUrl = markerUrl.strip();\n                    markerUrl = markerUrl.replace(/^url\\(#/, '');\n                    \n                    var markerStartId = this.getValidMarkerId(markerUrl);\n                    path.setAttributeNS(null, \"marker-start\", \"url(#\" + markerStartId + \")\");\n                    \n                    markersByThisPath.push(this._markers[markerStartId]);\n                }\n                \n                markerUrl = path.getAttributeNS(null, \"marker-mid\");\n                \n                if (markerUrl && markerUrl !== \"\") {\n                    markerUrl = markerUrl.strip();\n                    markerUrl = markerUrl.replace(/^url\\(#/, '');\n                    var markerMidId = this.getValidMarkerId(markerUrl);\n                    path.setAttributeNS(null, \"marker-mid\", \"url(#\" + markerMidId + \")\");\n                    \n                    markersByThisPath.push(this._markers[markerMidId]);\n                }\n                \n                markerUrl = path.getAttributeNS(null, \"marker-end\");\n                \n                if (markerUrl && markerUrl !== \"\") {\n                    markerUrl = markerUrl.strip();\n                    \n                    var markerEndId = this.getValidMarkerId(markerUrl);\n                    path.setAttributeNS(null, \"marker-end\", \"url(#\" + markerEndId + \")\");\n                    \n                    markersByThisPath.push(this._markers[markerEndId]);\n                }\n                \n                this._markersByPath[pathId] = markersByThisPath;\n                \n                //init dockers\n                var parser = new PathParser();\n                var handler = new ORYX.Core.SVG.PointsPathHandler();\n                parser.setHandler(handler);\n                parser.parsePath(path);\n                \n                if (handler.points.length < 4) {\n                    throw \"Edge: Path has to have two or more points specified.\";\n                }\n                \n                this._dockersByPath[pathId] = [];\n                \n\t\t\t\tfor (var i = 0; i < handler.points.length; i += 2) {\n\t\t\t\t\t//handler.points.each((function(point, pIndex){\n\t\t\t\t\tvar x = handler.points[i];\n\t\t\t\t\tvar y = handler.points[i+1];\n\t\t\t\t\tif (isFirst || i > 0) {\n\t\t\t\t\t\tvar docker = new ORYX.Core.Controls.Docker({\n\t\t\t\t\t\t\teventHandlerCallback: this.eventHandlerCallback\n\t\t\t\t\t\t});\n\t\t\t\t\t\tdocker.bounds.centerMoveTo(x,y);\n\t\t\t\t\t\tdocker.bounds.registerCallback(this._dockerChangedCallback);\n\t\t\t\t\t\tthis.add(docker, this.dockers.length);\n\t\t\t\t\t\t\n\t\t\t\t\t\t//this._dockersByPath[pathId].push(docker);\n\t\t\t\t\t\t\n\t\t\t\t\t\t//calculate minPoint and maxPoint\n\t\t\t\t\t\tif (minPointX) {\n\t\t\t\t\t\t\tminPointX = Math.min(x, minPointX);\n\t\t\t\t\t\t\tminPointY = Math.min(y, minPointY);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tminPointX = x;\n\t\t\t\t\t\t\tminPointY = y;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (maxPointX) {\n\t\t\t\t\t\t\tmaxPointX = Math.max(x, maxPointX);\n\t\t\t\t\t\t\tmaxPointY = Math.max(y, maxPointY);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tmaxPointX = x;\n\t\t\t\t\t\t\tmaxPointY = y;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t//}).bind(this));\n\t\t\t\t}\n                isFirst = false;\n            }\n        }).bind(this));\n        \n        this.bounds.set(minPointX, minPointY, maxPointX, maxPointY);\n        \n        if (false&&(this.bounds.width() === 0 || this.bounds.height() === 0)) {\n\t\t\tvar width = this.bounds.width();\n\t\t\tvar height = this.bounds.height();\n\t\t\t\n            this.bounds.extend({\n                x: width === 0 ? 2 : 0,\n                y: height === 0 ? 2 : 0\n            });\n            \n            this.bounds.moveBy({\n                x: width === 0 ? -1 : 0,\n                y: height === 0 ? -1 : 0\n            });\n            \n        }\n        \n        this._oldBounds = this.bounds.clone();\n        \n        //add paths to this.node\n        this._paths.reverse();\n        var paths = [];\n        this._paths.each((function(path){\n            paths.push(this.node.childNodes[0].childNodes[0].childNodes[0].appendChild(path));\n        }).bind(this));\n        \n        this._paths = paths;\n        \n        //init interaction path\n        this._paths.each((function(path){\n            var iPath = path.cloneNode(false);\n\t\t\tiPath.setAttributeNS(null, \"id\", undefined);\n            iPath.setAttributeNS(null, \"stroke-width\", 10);\n            iPath.setAttributeNS(null, \"visibility\", \"hidden\");\n            iPath.setAttributeNS(null, \"stroke-dasharray\", null);\n            iPath.setAttributeNS(null, \"stroke\", \"black\");\n            iPath.setAttributeNS(null, \"fill\", \"none\");\n\t\t\tiPath.setAttributeNS(null, \"title\", this.getStencil().title());\n            this._interactionPaths.push(this.node.childNodes[0].childNodes[0].childNodes[0].appendChild(iPath));\n        }).bind(this));\n        \n        this._paths.reverse();\n        this._interactionPaths.reverse();\n\t\t\n\t\t/**initialize labels*/\n        var textElems = svgDocument.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'text');\n        \n\t\t$A(textElems).each((function(textElem){\n            var label = new ORYX.Core.SVG.Label({\n                textElement: textElem,\n\t\t\t\tshapeId: this.id\n            });\n            this.node.childNodes[0].childNodes[0].appendChild(label.node);\n            this._labels[label.id] = label;\n\t\t\t\n\t\t\tlabel.registerOnChange(this.layout.bind(this));\n        }).bind(this)); \n\t\t\n        \n        this.propertiesChanged.each(function(pair){\n            pair.value = true;\n        });\n        \n        \n        //if(this.dockers.length == 2) {\n        \t\n        \t\n        \t\n      //  }\n\t\t\n        //this._update(true);\n    },\n    \n    getValidMarkerId: function(markerUrl) {\n    \tif(markerUrl.indexOf(\"url(\\\"#\") >= 0) {\n            // Fix for IE9, additional quotes are added to the <id\n            var rawId = markerUrl.replace(/^url\\(\\\"#/, \"\").replace(/\\\"\\)$/, '');\n            return this.id + rawId;\n          } else {\n            markerUrl = markerUrl.replace(/^url\\(#/, '');\n            return this.id.concat(markerUrl.replace(/\\)$/, ''));\n          }\n    },\n    \n    /**\n     * Adds all necessary markers of this Edge to the SVG document.\n     * Has to be called, while this.node is part of DOM.\n     */\n    addMarkers: function(defs){\n        this._markers.each(function(marker){\n            if (!defs.ownerDocument.getElementById(marker.value.id)) {\n                marker.value.element = defs.appendChild(marker.value.element);\n            }\n        });\n    },\n    \n    /**\n     * Removes all necessary markers of this Edge from the SVG document.\n     * Has to be called, while this.node is part of DOM.\n     */\n    removeMarkers: function(){\n        var svgElement = this.node.ownerSVGElement;\n        if (svgElement) {\n            var defs = svgElement.getElementsByTagNameNS(NAMESPACE_SVG, \"defs\");\n            if (defs.length > 0) {\n                defs = defs[0];\n                this._markers.each(function(marker){\n                    var foundMarker = defs.ownerDocument.getElementById(marker.value.id);\n                    if (foundMarker) {\n                        marker.value.element = defs.removeChild(marker.value.element);\n                    }\n                });\n            }\n        }\n    },\n    \n    /**\n     * Calls when a docker has changed\n     */\n    _dockerChanged: function(){\n    \n        //this._update(true);\n\t\tthis._dockerUpdated = true;\n        \n    },\n    \n    serialize: function(){\n        var result = arguments.callee.$.serialize.apply(this);\n        \n        //add dockers triple\n        var value = \"\";\n        this._dockersByPath.each((function(pair){\n            pair.value.each(function(docker){\n                var position = docker.getDockedShape() && docker.referencePoint ? docker.referencePoint : docker.bounds.center();\n                value = value.concat(position.x + \" \" + position.y + \" \");\n            });\n            \n            value += \" # \";\n        }).bind(this));\n        result.push({\n            name: 'dockers',\n            prefix: 'oryx',\n            value: value,\n            type: 'literal'\n        });\n        \n        //add parent triple dependant on the dockedShapes\n        //TODO change this when canvas becomes a resource\n/*        var source = this.dockers.first().getDockedShape();\n        var target = this.dockers.last().getDockedShape();\n        var sharedParent;\n        if (source && target) {\n            //get shared parent\n            while (source.parent) {\n                source = source.parent;\n                if (source instanceof ORYX.Core.Canvas) {\n                    sharedParent = source;\n                    break;\n                }\n                else {\n                    var targetParent = target.parent;\n                    var found;\n                    while (targetParent) {\n                        if (source === targetParent) {\n                            sharedParent = source;\n                            found = true;\n                            break;\n                        }\n                        else {\n                            targetParent = targetParent.parent;\n                        }\n                    }\n                    if (found) {\n                        break;\n                    }\n                }\n            }\n        }\n        else \n            if (source) {\n                sharedParent = source.parent;\n            }\n            else \n                if (target) {\n                    sharedParent = target.parent;\n                }\n*/        \n        //if (sharedParent) {\n/*            result.push({\n                name: 'parent',\n                prefix: 'raziel',\n                //value: '#' + ERDF.__stripHashes(sharedParent.resourceId),\n                value: '#' + ERDF.__stripHashes(this.getCanvas().resourceId),\n                type: 'resource'\n            });*/\n        //}\n\t\t\n\t\t//serialize target and source\n\t\tvar lastDocker = this.dockers.last();\n\t\t\n\t\tvar target = lastDocker.getDockedShape();\n\t\t\n\t\tif(target) {\n\t\t\tresult.push({\n\t\t\t\tname: 'target',\n\t\t\t\tprefix: 'raziel',\n\t\t\t\tvalue: '#' + ERDF.__stripHashes(target.resourceId),\n\t\t\t\ttype: 'resource'\n\t\t\t});\n\t\t}\n        \n        try {\n            //result = this.getStencil().serialize(this, result);\n\t\t\tvar serializeEvent = this.getStencil().serialize();\n\t\t\t\n\t\t\t/*\n\t\t\t * call serialize callback by reference, result should be found\n\t\t\t * in serializeEvent.result\n\t\t\t */\n\t\t\tif(serializeEvent.type) {\n\t\t\t\tserializeEvent.shape = this;\n\t\t\t\tserializeEvent.data = result;\n\t\t\t\tserializeEvent.result = undefined;\n\t\t\t\tserializeEvent.forceExecution = true;\n\t\t\t\t\n\t\t\t\tthis._delegateEvent(serializeEvent);\n\t\t\t\t\n\t\t\t\tif(serializeEvent.result) {\n\t\t\t\t\tresult = serializeEvent.result;\n\t\t\t\t}\n\t\t\t}\n        } \n        catch (e) {\n        }\n        return result;\n    },\n    \n    deserialize: function(data){\n        try {\n            //data = this.getStencil().deserialize(this, data);\n\t\t\t\n\t\t\tvar deserializeEvent = this.getStencil().deserialize();\n\t\t\t\n\t\t\t/*\n\t\t\t * call serialize callback by reference, result should be found\n\t\t\t * in serializeEventInfo.result\n\t\t\t */\n\t\t\tif(deserializeEvent.type) {\n\t\t\t\tdeserializeEvent.shape = this;\n\t\t\t\tdeserializeEvent.data = data;\n\t\t\t\tdeserializeEvent.result = undefined;\n\t\t\t\tdeserializeEvent.forceExecution = true;\n\t\t\t\t\n\t\t\t\tthis._delegateEvent(deserializeEvent);\n\t\t\t\tif(deserializeEvent.result) {\n\t\t\t\t\tdata = deserializeEvent.result;\n\t\t\t\t}\n\t\t\t}\n        } \n        catch (e) {\n        }\n        \n\t\t// Set the outgoing shapes\n\t\tvar target = data.find(function(ser) {return (ser.prefix+\"-\"+ser.name) == 'raziel-target'});\n\t\tvar targetShape;\n\t\tif(target) {\n\t\t\ttargetShape = this.getCanvas().getChildShapeByResourceId(target.value);\n\t\t}\n\t\t\n\t\tvar outgoing = data.findAll(function(ser){ return (ser.prefix+\"-\"+ser.name) == 'raziel-outgoing'});\n\t\toutgoing.each((function(obj){\n\t\t\t// TODO: Look at Canvas\n\t\t\tif(!this.parent) {return};\n\t\t\t\t\t\t\t\t\n\t\t\t// Set outgoing Shape\n\t\t\tvar next = this.getCanvas().getChildShapeByResourceId(obj.value);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\tif(next){\n\t\t\t\tif(next == targetShape) {\n\t\t\t\t\t// If this is an edge, set the last docker to the next shape\n\t\t\t\t\tthis.dockers.last().setDockedShape(next);\n\t\t\t\t\tthis.dockers.last().setReferencePoint({x: next.bounds.width() / 2.0, y: next.bounds.height() / 2.0});\n\t\t\t\t} else if(next instanceof ORYX.Core.Edge) {\n\t\t\t\t\t//Set the first docker of the next shape\n\t\t\t\t\tnext.dockers.first().setDockedShape(this);\n\t\t\t\t\t//next.dockers.first().setReferencePoint({x: this.bounds.width() / 2.0, y: this.bounds.height() / 2.0});\n\t\t\t\t} /*else if(next.dockers.length > 0) { //next is a node and next has a docker\n\t\t\t\t\tnext.dockers.first().setDockedShape(this);\n\t\t\t\t\tnext.dockers.first().setReferencePoint({x: this.bounds.width() / 2.0, y: this.bounds.height() / 2.0});\n\t\t\t\t}*/\n\t\t\t}\t\n\t\t\t\n\t\t}).bind(this));\n\t\t\n        \n        var oryxDockers = data.find(function(obj){\n            return (obj.prefix === \"oryx\" &&\n            obj.name === \"dockers\");\n        });\n\t\t\n        if (oryxDockers) {\n            var dataByPath = oryxDockers.value.split(\"#\").without(\"\").without(\" \");\n            \n            dataByPath.each((function(data, index){\n                var values = data.replace(/,/g, \" \").split(\" \").without(\"\");\n                \n                //for each docker two values must be defined\n                if (values.length % 2 === 0) {\n                    var path = this._paths[index];\n                    \n                    if (path) {\n                        if (index === 0) {\n                            while (this._dockersByPath[path.id].length > 2) {\n                                this.removeDocker(this._dockersByPath[path.id][1]);\n                            }\n                        }\n                        else {\n                            while (this._dockersByPath[path.id].length > 1) {\n                                this.removeDocker(this._dockersByPath[path.id][0]);\n                            }\n                        }\n                        \n                        var dockersByPath = this._dockersByPath[path.id];\n                        \n                        if (index === 0) {\n                            //set position of first docker\n                            var x = parseFloat(values.shift());\n                            var y = parseFloat(values.shift());\n                            \n                            if (dockersByPath.first().getDockedShape()) {\n                                dockersByPath.first().setReferencePoint({\n                                    x: x,\n                                    y: y\n                                });\n                            }\n                            else {\n                                dockersByPath.first().bounds.centerMoveTo(x, y);\n                            }\n                        }\n                        \n                        //set position of last docker\n                        y = parseFloat(values.pop());\n                        x = parseFloat(values.pop());\n                        \n                        if (dockersByPath.last().getDockedShape()) {\n                            dockersByPath.last().setReferencePoint({\n                                x: x,\n                                y: y\n                            });\n                        } else {\n                            dockersByPath.last().bounds.centerMoveTo(x, y);\n                        }\n                        \n                        //add additional dockers\n                        for (var i = 0; i < values.length; i++) {\n                            x = parseFloat(values[i]);\n                            y = parseFloat(values[++i]);\n                            \n                            var newDocker = this.createDocker();\n                            newDocker.bounds.centerMoveTo(x, y);\n                            \n                            //this.dockers = this.dockers.without(newDocker);\n                            //this.dockers.splice(this.dockers.indexOf(dockersByPath.last()), 0, newDocker);\n                            //dockersByPath.splice(this.dockers.indexOf(dockersByPath.last()), 0, newDocker);\n\t\t\t\t\t\t}\n                    }\n                }\n            }).bind(this));\n        } else {\n            this.alignDockers();\n        }\n\t\t\n        arguments.callee.$.deserialize.apply(this, arguments);\n\t\t\n\t\tthis._changed();\n    },\n    \n    toString: function(){\n        return this.getStencil().title() + \" \" + this.id;\n    },\n    \n    /**\n     * @return {ORYX.Core.Shape} Returns last docked shape or null.\n     */\n    getTarget: function(){\n        return this.dockers.last() ? this.dockers.last().getDockedShape() : null;\n    },\n\t\n\t/**\n\t * @return {ORYX.Core.Shape} Returns the first docked shape or null\n\t */\n\tgetSource: function() {\n\t\treturn this.dockers.first() ? this.dockers.first().getDockedShape() : null;\n\t},\n\t\n\t/**\n\t * Checks whether the edge is at least docked to one shape.\n\t * \n\t * @return {boolean} True if edge is docked\n\t */\n\tisDocked: function() {\n\t\tvar isDocked = false;\n\t\tthis.dockers.each(function(docker) {\n\t\t\tif(docker.isDocked()) {\n\t\t\t\tisDocked = true;\n\t\t\t\tthrow $break;\n\t\t\t}\n\t\t});\n\t\treturn isDocked;\n\t},\n    \n    /**\n     * Calls {@link ORYX.Core.AbstractShape#toJSON} and add a some stencil set information.\n     */\n    toJSON: function() {\n        var json = arguments.callee.$.toJSON.apply(this, arguments);\n        \n        if(this.getTarget()) {\n            json.target = {\n                resourceId: this.getTarget().resourceId\n            };\n        }\n        \n        return json;\n    }\n};\nORYX.Core.Edge = ORYX.Core.Shape.extend(ORYX.Core.Edge);\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nif(!ORYX){ var ORYX = {} }\nif(!ORYX.Plugins){ ORYX.Plugins = {} }\n\n/**\n   This abstract plugin class can be used to build plugins on.\n   It provides some more basic functionality like registering events (on*-handlers)...\n   @example\n    ORYX.Plugins.MyPlugin = ORYX.Plugins.AbstractPlugin.extend({\n        construct: function() {\n            // Call super class constructor\n            arguments.callee.$.construct.apply(this, arguments);\n            \n            [...]\n        },\n        [...]\n    });\n   \n   @class ORYX.Plugins.AbstractPlugin\n   @constructor Creates a new instance\n   @author Willi Tscheschner\n*/\nORYX.Plugins.AbstractPlugin = Clazz.extend({\n    /** \n     * The facade which offer editor-specific functionality\n     * @type Facade\n     * @memberOf ORYX.Plugins.AbstractPlugin.prototype\n     */\n\tfacade: null,\n\t\n\tconstruct: function( facade ){\n\t\tthis.facade = facade;\n\t\t\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_LOADED, this.onLoaded.bind(this));\n\t},\n        \n    /**\n       Overwrite to handle load event. TODO: Document params!!!\n       @methodOf ORYX.Plugins.AbstractPlugin.prototype\n    */\n\tonLoaded: function(){},\n\t\n    /**\n       Overwrite to handle selection changed event. TODO: Document params!!!\n       @methodOf ORYX.Plugins.AbstractPlugin.prototype\n    */\n\tonSelectionChanged: function(){},\n\t\n    /**\n       Show overlay on given shape.\n       @methodOf ORYX.Plugins.AbstractPlugin.prototype\n       @example\n       showOverlay(\n           myShape,\n           { stroke: \"green\" },\n           ORYX.Editor.graft(\"http://www.w3.org/2000/svg\", null, ['path', {\n               \"title\": \"Click the element to execute it!\",\n               \"stroke-width\": 2.0,\n               \"stroke\": \"black\",\n               \"d\": \"M0,-5 L5,0 L0,5 Z\",\n               \"line-captions\": \"round\"\n           }])\n       )\n       @param {Oryx.XXX.Shape[]} shapes One shape or array of shapes the overlay should be put on\n       @param {Oryx.XXX.Attributes} attributes some attributes...\n       @param {Oryx.svg.node} svgNode The svg node which should be used as overlay\n       @param {String} [svgNode=\"NW\"] The svg node position where the overlay should be placed\n    */\n\tshowOverlay: function(shapes, attributes, svgNode, svgNodePosition ){\n\t\t\n\t\tif( !(shapes instanceof Array) ){\n\t\t\tshapes = [shapes]\n\t\t}\n\t\t\n\t\t// Define Shapes\n\t\tshapes = shapes.map(function(shape){\n\t\t\tvar el = shape;\n\t\t\tif( typeof shape == \"string\" ){\n\t\t\t\tel = this.facade.getCanvas().getChildShapeByResourceId( shape );\n\t\t\t\tel = el || this.facade.getCanvas().getChildById( shape, true );\n\t\t\t}\n\t\t\treturn el;\n\t\t}.bind(this)).compact();\n\t\t\n\t\t// Define unified id\n\t\tif( !this.overlayID ){\n\t\t\tthis.overlayID = this.type + ORYX.Editor.provideId();\n\t\t}\n\t\t\n\t\tthis.facade.raiseEvent({\n\t\t\ttype\t\t: ORYX.CONFIG.EVENT_OVERLAY_SHOW,\n\t\t\tid\t\t\t: this.overlayID,\n\t\t\tshapes\t\t: shapes,\n\t\t\tattributes \t: attributes,\n\t\t\tnode\t\t: svgNode,\n\t\t\tnodePosition: svgNodePosition || \"NW\"\n\t\t});\n\t\t\n\t},\n\t\n    /**\n       Hide current overlay.\n       @methodOf ORYX.Plugins.AbstractPlugin.prototype\n    */\n\thideOverlay: function(){\n\t\tthis.facade.raiseEvent({\n\t\t\ttype\t: ORYX.CONFIG.EVENT_OVERLAY_HIDE,\n\t\t\tid\t\t: this.overlayID\n\t\t});\t\t\n\t},\n\t\n    /**\n       Does a transformation with the given xslt stylesheet.\n       @methodOf ORYX.Plugins.AbstractPlugin.prototype\n       @param {String} data The data (e.g. eRDF) which should be transformed\n       @param {String} stylesheet URL of a stylesheet which should be used for transforming data.\n    */\n\tdoTransform: function( data, stylesheet ) {\t\t\n\t\t\n\t\tif( !stylesheet || !data ){\n\t\t\treturn \"\"\n\t\t}\n\n        var parser \t\t= new DOMParser();\n        var parsedData \t= parser.parseFromString(data, \"text/xml\");\n\t\tsource=stylesheet;\n\t\tnew Ajax.Request(source, {\n\t\t\tasynchronous: false,\n\t\t\tmethod: 'get',\n\t\t\tonSuccess: function(transport){\n\t\t\t\txsl = transport.responseText\n\t\t\t}.bind(this),\n\t\t\tonFailure: (function(transport){\n\t\t\t\tORYX.Log.error(\"XSL load failed\" + transport);\n\t\t\t}).bind(this)\n\t\t});\n        var xsltProcessor = new XSLTProcessor();\n\t\tvar domParser = new DOMParser();\n\t\tvar xslObject = domParser.parseFromString(xsl, \"text/xml\");\n        xsltProcessor.importStylesheet(xslObject);\n        \n        try {\n        \t\n            var newData \t\t= xsltProcessor.transformToFragment(parsedData, document);\n            var serializedData \t= (new XMLSerializer()).serializeToString(newData);\n            \n           \t/* Firefox 2 to 3 problem?! */\n            serializedData = !serializedData.startsWith(\"<?xml\") ? \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\"?>\" + serializedData : serializedData;\n            \n            return serializedData;\n            \n        }catch (error) {\n            return -1;\n        }\n        \n\t},\n\t\n\t/**\n\t * Opens a new window that shows the given XML content.\n\t * @methodOf ORYX.Plugins.AbstractPlugin.prototype\n\t * @param {Object} content The XML content to be shown.\n\t * @example\n\t * openDownloadWindow( \"my.xml\", \"<exampleXML />\" );\n\t */\n\topenXMLWindow: function(content) {\n\t\tvar win = window.open(\n\t\t   'data:application/xml,' + encodeURIComponent(\n\t\t     content\n\t\t   ),\n\t\t   '_blank', \"resizable=yes,width=600,height=600,toolbar=0,scrollbars=yes\"\n\t\t);\n\t},\n\t\n    /**\n     * Opens a download window for downloading the given content.\n     * @methodOf ORYX.Plugins.AbstractPlugin.prototype\n     * @param {String} filename The content's file name\n     * @param {String} content The content to download\n     */\n\topenDownloadWindow: function(filename, content) {\n\t\tvar win = window.open(\"\");\n\t\tif (win != null) {\n\t\t\twin.document.open();\n\t\t\twin.document.write(\"<html><body>\");\n\t\t\tvar submitForm = win.document.createElement(\"form\");\n\t\t\twin.document.body.appendChild(submitForm);\n\t\t\t\n\t\t\tvar createHiddenElement = function(name, value) {\n\t\t\t\tvar newElement = document.createElement(\"input\");\n\t\t\t\tnewElement.name=name;\n\t\t\t\tnewElement.type=\"hidden\";\n\t\t\t\tnewElement.value = value;\n\t\t\t\treturn newElement\n\t\t\t}\n\t\t\t\n\t\t\tsubmitForm.appendChild( createHiddenElement(\"download\", content) );\n\t\t\tsubmitForm.appendChild( createHiddenElement(\"file\", filename) );\n\t\t\t\n\t\t\t\n\t\t\tsubmitForm.method = \"POST\";\n\t\t\twin.document.write(\"</body></html>\");\n\t\t\twin.document.close();\n\t\t\tsubmitForm.action= ORYX.PATH + \"/download\";\n\t\t\tsubmitForm.submit();\n\t\t}\t\t\n\t},\n    \n    /**\n     * Serializes DOM.\n     * @methodOf ORYX.Plugins.AbstractPlugin.prototype\n     * @type {String} Serialized DOM\n     */\n    getSerializedDOM: function(){\n        // Force to set all resource IDs\n        var serializedDOM = DataManager.serializeDOM( this.facade );\n\n        //add namespaces\n        serializedDOM = '<?xml version=\"1.0\" encoding=\"utf-8\"?>' +\n        '<html xmlns=\"http://www.w3.org/1999/xhtml\" ' +\n        'xmlns:b3mn=\"http://b3mn.org/2007/b3mn\" ' +\n        'xmlns:ext=\"http://b3mn.org/2007/ext\" ' +\n        'xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\" ' +\n        'xmlns:atom=\"http://b3mn.org/2007/atom+xhtml\">' +\n        '<head profile=\"http://purl.org/NET/erdf/profile\">' +\n        '<link rel=\"schema.dc\" href=\"http://purl.org/dc/elements/1.1/\" />' +\n        '<link rel=\"schema.dcTerms\" href=\"http://purl.org/dc/terms/ \" />' +\n        '<link rel=\"schema.b3mn\" href=\"http://b3mn.org\" />' +\n        '<link rel=\"schema.oryx\" href=\"http://oryx-editor.org/\" />' +\n        '<link rel=\"schema.raziel\" href=\"http://raziel.org/\" />' +\n        '<base href=\"' +\n        location.href.split(\"?\")[0] +\n        '\" />' +\n        '</head><body>' +\n        serializedDOM +\n        '</body></html>';\n        \n        return serializedDOM;\n    },\n    \n    /**\n     * Sets the editor in read only mode: Edges/ dockers cannot be moved anymore,\n     * shapes cannot be selected anymore.\n     * @methodOf ORYX.Plugins.AbstractPlugin.prototype\n     */\n    enableReadOnlyMode: function(){\n        //Edges cannot be moved anymore\n        this.facade.disableEvent(ORYX.CONFIG.EVENT_MOUSEDOWN);\n        \n        // Stop the user from editing the diagram while the plugin is active\n        this._stopSelectionChange = function(){\n            if(this.facade.getSelection().length > 0) {\n                this.facade.setSelection([]);\n            }\n        };\n        this.facade.registerOnEvent(ORYX.CONFIG.EVENT_SELECTION_CHANGED, this._stopSelectionChange.bind(this));\n    },\n    /**\n     * Disables read only mode, see @see\n     * @methodOf ORYX.Plugins.AbstractPlugin.prototype\n     * @see ORYX.Plugins.AbstractPlugin.prototype.enableReadOnlyMode\n     */\n    disableReadOnlyMode: function(){\n        // Edges can be moved now again\n        this.facade.enableEvent(ORYX.CONFIG.EVENT_MOUSEDOWN);\n        \n        if (this._stopSelectionChange) {\n            this.facade.unregisterOnEvent(ORYX.CONFIG.EVENT_SELECTION_CHANGED, this._stopSelectionChange.bind(this));\n            this._stopSelectionChange = undefined;\n        }\n    },\n    \n    /**\n     * Extracts RDF from DOM.\n     * @methodOf ORYX.Plugins.AbstractPlugin.prototype\n     * @type {String} Extracted RFD. Null if there are transformation errors.\n     */\n    getRDFFromDOM: function(){\n        //convert to RDF\n\t\ttry {\n\t\t\tvar xsl = \"\";\n\t\t\tsource=ORYX.PATH + \"lib/extract-rdf.xsl\";\n\t\t\tnew Ajax.Request(source, {\n\t\t\t\tasynchronous: false,\n\t\t\t\tmethod: 'get',\n\t\t\t\tonSuccess: function(transport){\n\t\t\t\t\txsl = transport.responseText\n\t\t\t\t}.bind(this),\n\t\t\t\tonFailure: (function(transport){\n\t\t\t\t\tORYX.Log.error(\"XSL load failed\" + transport);\n\t\t\t\t}).bind(this)\n\t\t\t});\n\t\t\t\n\t\t\tvar domParser = new DOMParser();\n\t\t\tvar xmlObject = domParser.parseFromString(this.getSerializedDOM(), \"text/xml\");\n\t\t\tvar xslObject = domParser.parseFromString(xsl, \"text/xml\");\n\t\t\tvar xsltProcessor = new XSLTProcessor();\n\t\t\txsltProcessor.importStylesheet(xslObject);\n\t\t\tvar result = xsltProcessor.transformToFragment(xmlObject, document);\n\t\t\t\n\t\t\tvar serializer = new XMLSerializer();\n\t\t\t\n\t\t\treturn serializer.serializeToString(result);\n\t\t} catch(e){\n\t\t\tconsole.log(\"error serializing \" + e);\n\t\t\treturn \"\";\n\t\t}\n\n\t\t\n    },\n    \n    /**\n\t * Checks if a certain stencil set is loaded right now.\n\t * \n\t */\n\tisStencilSetExtensionLoaded: function(stencilSetExtensionNamespace) {\n\t\treturn this.facade.getStencilSets().values().any(\n\t\t\tfunction(ss){ \n\t\t\t\treturn ss.extensions().keys().any(\n\t\t\t\t\tfunction(extensionKey) {\n\t\t\t\t\t\treturn extensionKey == stencilSetExtensionNamespace;\n\t\t\t\t\t}.bind(this)\n\t\t\t\t);\n\t\t\t}.bind(this)\n\t\t);\n\t},\n\t\n\t/**\n\t * Raises an event so that registered layouters does\n\t * have the posiblility to layout the given shapes \n\t * For further reading, have a look into the AbstractLayouter\n\t * class\n\t * @param {Object} shapes\n\t */\n\tdoLayout: function(shapes){\n\t\t// Raises a do layout event\n\t\tif (this.facade.raiseEvent)\n\t\t{\n\t\t\tthis.facade.raiseEvent({\n\t\t\t\ttype\t\t: ORYX.CONFIG.EVENT_LAYOUT,\n\t\t\t\tshapes\t\t: shapes\n\t\t\t});\n\t\t}\n\t\telse\n\t\t{\n\t\t\tthis.facade.handleEvents({\n\t\t\t\ttype\t\t: ORYX.CONFIG.EVENT_LAYOUT,\n\t\t\t\tshapes\t\t: shapes\n\t\t\t});\n\t\t}\n\t},\n\t\n\t\n\t/**\n\t * Does a primitive layouting with the incoming/outgoing \n\t * edges (set the dockers to the right position) and if \n\t * necessary, it will be called the real layouting \n\t * @param {ORYX.Core.Node} node\n\t * @param {Array} edges\n\t */\n\tlayoutEdges : function(node, allEdges, offset){\t\t\n\n\t\tif (!this.facade.isExecutingCommands()){ return }\t\t\n\n\t\tvar Command = ORYX.Core.Command.extend({\n\t\t\tconstruct: function(edges, node, offset, plugin){\n\t\t\t\tthis.edges = edges;\n\t\t\t\tthis.node = node;\n\t\t\t\tthis.plugin = plugin;\n\t\t\t\tthis.offset = offset;\n\t\t\t\t\n\t\t\t\t// Get the new absolute center\n\t\t\t\tvar center = node.absoluteXY();\n\t\t\t\tthis.ulo = {x: center.x - offset.x, y:center.y - offset.y};\n\t\t\t\t\n\t\t\t\t\n\t\t\t},\n\t\t\texecute: function(){\n\t\t\t\t\n\t\t\t\tif (this.changes){\n\t\t\t\t\tthis.executeAgain();\n\t\t\t\t\treturn;\n\t\t\t\t} else {\n\t\t\t\t\tthis.changes = [];\n\t\t\t\t\tthis.edges.each(function(edge){\n\t\t\t\t\t\tthis.changes.push({\n\t\t\t\t\t\t\tedge: edge,\n\t\t\t\t\t\t\toldDockerPositions: edge.dockers.map(function(r){ return r.bounds.center() })\n\t\t\t\t\t\t})\n\t\t\t\t\t}.bind(this));\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// Find all edges, which are related to the node and\n\t\t\t\t// have more than two dockers\n\t\t\t\tthis.edges\n\t\t\t\t\t// Find all edges with more than two dockers\n\t\t\t\t\t.findAll(function(r){ return r.dockers.length > 2 }.bind(this))\n\t\t\t\t\t// For every edge, check second and one before last docker\n\t\t\t\t\t// if there are horizontal/vertical on the same level\n\t\t\t\t\t// and if so, align the the bounds \n\t\t\t\t\t.each(function(edge){\n\t\t\t\t\t\tif (edge.dockers.first().getDockedShape() === this.node){\n\t\t\t\t\t\t\tvar second = edge.dockers[1];\n\t\t\t\t\t\t\tif (this.align(second.bounds, edge.dockers.first())){ second.update(); }\n\t\t\t\t\t\t} else if (edge.dockers.last().getDockedShape() === this.node) {\n\t\t\t\t\t\t\tvar beforeLast = edge.dockers[edge.dockers.length-2];\n\t\t\t\t\t\t\tif (this.align(beforeLast.bounds, edge.dockers.last())){ beforeLast.update(); }\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t}\n\t\t\t\t\t\tedge._update(true);\n\t\t\t\t\t\tedge.removeUnusedDockers();\n\t\t\t\t\t\tif (this.isBendPointIncluded(edge)){\n\t\t\t\t\t\t\tthis.plugin.doLayout(edge);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t}.bind(this));\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t// Find all edges, which have only to dockers \n\t\t\t\t// and is located horizontal/vertical.\n\t\t\t\t// Do layout with those edges\n\t\t\t\tthis.edges\n\t\t\t\t\t// Find all edges with exactly two dockers\n\t\t\t\t\t.each(function(edge){\n\t\t\t\t\t\tif (edge.dockers.length == 2){\n\t\t\t\t\t\t\tvar p1 = edge.dockers.first().getAbsoluteReferencePoint() || edge.dockers.first().bounds.center();\n\t\t\t\t\t\t\tvar p2 = edge.dockers.last().getAbsoluteReferencePoint() || edge.dockers.first().bounds.center();\n\t\t\t\t\t\t\t// Find all horizontal/vertical edges\n\t\t\t\t\t\t\tif (Math.abs(-Math.abs(p1.x - p2.x) + Math.abs(this.offset.x)) < 2 || Math.abs(-Math.abs(p1.y - p2.y) + Math.abs(this.offset.y)) < 2){\n\t\t\t\t\t\t\t\tthis.plugin.doLayout(edge);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}.bind(this));\n\t\t\n\t\t\t\tthis.edges.each(function(edge, i){\n\t\t\t\t\tthis.changes[i].dockerPositions = edge.dockers.map(function(r){ return r.bounds.center() });\n\t\t\t\t}.bind(this));\n\t\t\t\t\n\t\t\t},\n\t\t\t/**\n\t\t\t * Align the bounds if the center is \n\t\t\t * the same than the old center\n\t\t\t * @params {Object} bounds\n\t\t\t * @params {Object} bounds2\n\t\t\t */\n\t\t\talign: function(bounds, refDocker){\n\t\t\t\t\n\t\t\t\tvar abRef = refDocker.getAbsoluteReferencePoint() || refDocker.bounds.center();\n\t\t\t\t\n\t\t\t\tvar xdif = bounds.center().x-abRef.x;\n\t\t\t\tvar ydif = bounds.center().y-abRef.y;\n\t\t\t\tif (Math.abs(-Math.abs(xdif) + Math.abs(this.offset.x)) < 3 && this.offset.xs === undefined){\n\t\t\t\t\tbounds.moveBy({x:-xdif, y:0})\n\t\t\t\t}\n\t\t\t\tif (Math.abs(-Math.abs(ydif) + Math.abs(this.offset.y)) < 3 && this.offset.ys === undefined){\n\t\t\t\t\tbounds.moveBy({y:-ydif, x:0})\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (this.offset.xs !== undefined || this.offset.ys !== undefined){\n\t\t\t\t\tvar absPXY = refDocker.getDockedShape().absoluteXY();\n\t\t\t\t\txdif = bounds.center().x-(absPXY.x+((abRef.x-absPXY.x)/this.offset.xs));\n\t\t\t\t\tydif = bounds.center().y-(absPXY.y+((abRef.y-absPXY.y)/this.offset.ys));\n\t\t\t\t\t\n\t\t\t\t\tif (Math.abs(-Math.abs(xdif) + Math.abs(this.offset.x)) < 3){\n\t\t\t\t\t\tbounds.moveBy({x:-(bounds.center().x-abRef.x), y:0})\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif (Math.abs(-Math.abs(ydif) + Math.abs(this.offset.y)) < 3){\n\t\t\t\t\t\tbounds.moveBy({y:-(bounds.center().y-abRef.y), x:0})\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\n\t\t\t/**\t\t\t\t\t\t\n\t\t\t * Returns a TRUE if there are bend point which overlay the shape\n\t\t\t */\n\t\t\tisBendPointIncluded: function(edge){\n\t\t\t\t// Get absolute bounds\n\t\t\t\tvar ab = edge.dockers.first().getDockedShape();\n\t\t\t\tvar bb = edge.dockers.last().getDockedShape();\n\t\t\t\t\n\t\t\t\tif (ab) {\n\t\t\t\t\tab = ab.absoluteBounds();\n\t\t\t\t\tab.widen(5);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (bb) {\n\t\t\t\t\tbb = bb.absoluteBounds();\n\t\t\t\t\tbb.widen(20); // Wide with 20 because of the arrow from the edge\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\treturn edge.dockers\n\t\t\t\t\t\t.any(function(docker, i){ \n\t\t\t\t\t\t\tvar c = docker.bounds.center();\n\t\t\t\t\t\t\t\t\t// Dont count first and last\n\t\t\t\t\t\t\treturn \ti != 0 && i != edge.dockers.length-1 && \n\t\t\t\t\t\t\t\t\t// Check if the point is included to the absolute bounds\n\t\t\t\t\t\t\t\t\t((ab && ab.isIncluded(c)) || (bb && bb.isIncluded(c)))\n\t\t\t\t\t\t})\n\t\t\t},\n\t\t\t\n\t\t\tremoveAllDocker: function(edge){\n\t\t\t\tedge.dockers.slice(1, edge.dockers.length-1).each(function(docker){\n\t\t\t\t\tedge.removeDocker(docker);\n\t\t\t\t})\n\t\t\t},\n\t\t\texecuteAgain: function(){\n\t\t\t\tthis.changes.each(function(change){\n\t\t\t\t\t// Reset the dockers\n\t\t\t\t\tthis.removeAllDocker(change.edge);\n\t\t\t\t\tchange.dockerPositions.each(function(pos, i){\t\n\t\t\t\t\t\tif (i==0||i==change.dockerPositions.length-1){ return }\t\t\t\t\t\n\t\t\t\t\t\tvar docker = change.edge.createDocker(undefined, pos);\n\t\t\t\t\t\tdocker.bounds.centerMoveTo(pos);\n\t\t\t\t\t\tdocker.update();\n\t\t\t\t\t}.bind(this));\n\t\t\t\t\tchange.edge._update(true);\n\t\t\t\t}.bind(this));\n\t\t\t},\n\t\t\trollback: function(){\t\t\t\t\t\n\t\t\t\tthis.changes.each(function(change){\n\t\t\t\t\t// Reset the dockers\n\t\t\t\t\tthis.removeAllDocker(change.edge);\n\t\t\t\t\tchange.oldDockerPositions.each(function(pos, i){\t\n\t\t\t\t\t\tif (i==0||i==change.oldDockerPositions.length-1){ return }\t\t\t\t\t\n\t\t\t\t\t\tvar docker = change.edge.createDocker(undefined, pos);\n\t\t\t\t\t\tdocker.bounds.centerMoveTo(pos);\n\t\t\t\t\t\tdocker.update();\n\t\t\t\t\t}.bind(this));\n\t\t\t\t\tchange.edge._update(true);\n\t\t\t\t}.bind(this));\n\t\t\t}\n\t\t});\n\t\t\n\t\tthis.facade.executeCommands([new Command(allEdges, node, offset, this)]);\n\n\t}\n});/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nif(!ORYX){ var ORYX = {} }\nif(!ORYX.Plugins){ ORYX.Plugins = {} }\n\n/**\n   This abstract plugin implements the core behaviour of layout\n   \n   @class ORYX.Plugins.AbstractLayouter\n   @constructor Creates a new instance\n   @author Willi Tscheschner\n*/\nORYX.Plugins.AbstractLayouter = ORYX.Plugins.AbstractPlugin.extend({\n\t\n\t/**\n\t * 'layouted' defined all types of shapes which will be layouted. \n\t * It can be one value or an array of values. The value\n\t * can be a Stencil ID (as String) or an class type of either \n\t * a ORYX.Core.Node or ORYX.Core.Edge\n     * @type Array|String|Object\n     * @memberOf ORYX.Plugins.AbstractLayouter.prototype\n\t */\n\tlayouted : [],\n\t\n\t/**\n\t * Constructor\n\t * @param {Object} facade\n\t * @memberOf ORYX.Plugins.AbstractLayouter.prototype\n\t */\n\tconstruct: function( facade ){\n\t\targuments.callee.$.construct.apply(this, arguments);\n\t\t\t\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_LAYOUT, this._initLayout.bind(this));\n\t},\n\t\n\t/**\n\t * Proofs if this shape should be layouted or not\n\t * @param {Object} shape\n     * @memberOf ORYX.Plugins.AbstractLayouter.prototype\n\t */\n\tisIncludedInLayout: function(shape){\n\t\tif (!(this.layouted instanceof Array)){\n\t\t\tthis.layouted = [this.layouted].compact();\n\t\t}\n\t\t\n\t\t// If there are no elements\n\t\tif (this.layouted.length <= 0) {\n\t\t\t// Return TRUE\n\t\t\treturn true;\n\t\t}\n\t\t\n\t\t// Return TRUE if there is any correlation between \n\t\t// the 'layouted' attribute and the shape themselve.\n\t\treturn this.layouted.any(function(s){\n\t\t\tif (typeof s == \"string\") {\n\t\t\t\treturn shape.getStencil().id().include(s);\n\t\t\t} else {\n\t\t\t\treturn shape instanceof s;\n\t\t\t}\n\t\t})\n\t},\n\t\n\t/**\n\t * Callback to start the layouting\n\t * @param {Object} event Layout event\n\t * @param {Object} shapes Given shapes\n     * @memberOf ORYX.Plugins.AbstractLayouter.prototype\n\t */\n\t_initLayout: function(event){\n\t\t\n\t\t// Get the shapes\n\t\tvar shapes = [event.shapes].flatten().compact();\n\t\t\n\t\t// Find all shapes which should be layouted\n\t\tvar toLayout = shapes.findAll(function(shape){\n\t\t\treturn this.isIncludedInLayout(shape) \n\t\t}.bind(this))\n\t\t\n\t\t// If there are shapes left \n\t\tif (toLayout.length > 0){\n\t\t\t// Do layout\n\t\t\tthis.layout(toLayout);\n\t\t}\n\t},\n\t\n\t/**\n\t * Implementation of layouting a set on shapes\n\t * @param {Object} shapes Given shapes\n     * @memberOf ORYX.Plugins.AbstractLayouter.prototype\n\t */\n\tlayout: function(shapes){\n\t\tthrow new Error(\"Layouter has to implement the layout function.\")\n\t}\n});/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nif (!ORYX.Plugins) \n    ORYX.Plugins = new Object();\n\nORYX.Plugins.Edit = Clazz.extend({\n    \n    construct: function(facade){\n    \n        this.facade = facade;\n        this.clipboard = new ORYX.Plugins.Edit.ClipBoard();\n        \n        //this.facade.registerOnEvent(ORYX.CONFIG.EVENT_KEYDOWN, this.keyHandler.bind(this));\n        \n        this.facade.offer({\n         name: ORYX.I18N.Edit.cut,\n         description: ORYX.I18N.Edit.cutDesc,\n         icon: ORYX.PATH + \"images/cut.png\",\n\t\t keyCodes: [{\n\t\t\t\tmetaKeys: [ORYX.CONFIG.META_KEY_META_CTRL],\n\t\t\t\tkeyCode: 88,\n\t\t\t\tkeyAction: ORYX.CONFIG.KEY_ACTION_DOWN\n\t\t\t}\n\t\t ],\n         functionality: this.callEdit.bind(this, this.editCut),\n         group: ORYX.I18N.Edit.group,\n         index: 1,\n         minShape: 1\n         });\n         \n        this.facade.offer({\n         name: ORYX.I18N.Edit.copy,\n         description: ORYX.I18N.Edit.copyDesc,\n         icon: ORYX.PATH + \"images/page_copy.png\",\n\t\t keyCodes: [{\n\t\t\t\tmetaKeys: [ORYX.CONFIG.META_KEY_META_CTRL],\n\t\t\t\tkeyCode: 67,\n\t\t\t\tkeyAction: ORYX.CONFIG.KEY_ACTION_DOWN\n\t\t\t}\n\t\t ],\n         functionality: this.callEdit.bind(this, this.editCopy, [true, false]),\n         group: ORYX.I18N.Edit.group,\n         index: 2,\n         minShape: 1\n         });\n         \n        this.facade.offer({\n         name: ORYX.I18N.Edit.paste,\n         description: ORYX.I18N.Edit.pasteDesc,\n         icon: ORYX.PATH + \"images/page_paste.png\",\n\t\t keyCodes: [{\n\t\t\t\tmetaKeys: [ORYX.CONFIG.META_KEY_META_CTRL],\n\t\t\t\tkeyCode: 86,\n\t\t\t\tkeyAction: ORYX.CONFIG.KEY_ACTION_DOWN\n\t\t\t}\n\t\t ],\n         functionality: this.callEdit.bind(this, this.editPaste),\n         isEnabled: this.clipboard.isOccupied.bind(this.clipboard),\n         group: ORYX.I18N.Edit.group,\n         index: 3,\n         minShape: 0,\n         maxShape: 0\n         });\n         \n        this.facade.offer({\n            name: ORYX.I18N.Edit.del,\n            description: ORYX.I18N.Edit.delDesc,\n            icon: ORYX.PATH + \"images/cross.png\",\n\t\t\tkeyCodes: [{\n\t\t\t\t\tmetaKeys: [ORYX.CONFIG.META_KEY_META_CTRL],\n\t\t\t\t\tkeyCode: 8,\n\t\t\t\t\tkeyAction: ORYX.CONFIG.KEY_ACTION_DOWN\n\t\t\t\t},\n\t\t\t\t{\t\n\t\t\t\t\tkeyCode: 46,\n\t\t\t\t\tkeyAction: ORYX.CONFIG.KEY_ACTION_DOWN\n\t\t\t\t}\n\t\t\t],\n            functionality: this.callEdit.bind(this, this.editDelete),\n            group: ORYX.I18N.Edit.group,\n            index: 4,\n            minShape: 1\n        });\n    },\n\t\n\tcallEdit: function(fn, args){\n\t\twindow.setTimeout(function(){\n\t\t\tfn.apply(this, (args instanceof Array ? args : []));\n\t\t}.bind(this), 1);\n\t},\n\t\n\t/**\n\t * Handles the mouse down event and starts the copy-move-paste action, if\n\t * control or meta key is pressed.\n\t */\n\thandleMouseDown: function(event) {\n\t\tif(this._controlPressed) {\n\t\t\tthis._controlPressed = false;\n\t\t\tthis.editCopy();\n//\t\t\tconsole.log(\"copiedEle: %0\",this.clipboard.shapesAsJson)\n//\t\t\tconsole.log(\"mousevent: %o\",event)\n\t\t\tthis.editPaste();\n\t\t\tevent.forceExecution = true;\n\t\t\tthis.facade.raiseEvent(event, this.clipboard.shapesAsJson);\n\t\t\t\n\t\t}\n\t},\n    \n    /**\n     * The key handler for this plugin. Every action from the set of cut, copy,\n     * paste and delete should be accessible trough simple keyboard shortcuts.\n     * This method checks whether any event triggers one of those actions.\n     *\n     * @param {Object} event The keyboard event that should be analysed for\n     *     triggering of this plugin.\n     */\n//    keyHandler: function(event){\n//        //TODO document what event.which is.\n//        \n//        ORYX.Log.debug(\"edit.js handles a keyEvent.\");\n//        \n//        // assure we have the current event.\n//        if (!event) \n//            event = window.event;\n//        \n//        \n//        // get the currently pressed key and state of control key.\n//        var pressedKey = event.which || event.keyCode;\n//        var ctrlPressed = event.ctrlKey;\n//        \n//        // if the object is to be deleted, do so, and return immediately.\n//        if ((pressedKey == ORYX.CONFIG.KEY_CODE_DELETE) ||\n//        ((pressedKey == ORYX.CONFIG.KEY_CODE_BACKSPACE) &&\n//        (event.metaKey || event.appleMetaKey))) {\n//        \n//            ORYX.Log.debug(\"edit.js deletes the shape.\");\n//            this.editDelete();\n//            return;\n//        }\n//        \n//         // if control key is not pressed, we're not interested anymore.\n//         if (!ctrlPressed)\n//         return;\n//         \n//         // when ctrl is pressed, switch trough the possibilities.\n//         switch (pressedKey) {\n//         \n//\t         // cut.\n//\t         case ORYX.CONFIG.KEY_CODE_X:\n//\t         this.editCut();\n//\t         break;\n//\t         \n//\t         // copy.\n//\t         case ORYX.CONFIG.KEY_CODE_C:\n//\t         this.editCopy();\n//\t         break;\n//\t         \n//\t         // paste.\n//\t         case ORYX.CONFIG.KEY_CODE_V:\n//\t         this.editPaste();\n//\t         break;\n//         }\n//    },\n\t\n    /**\n     * Returns a list of shapes which should be considered while copying.\n     * Besides the shapes of given ones, edges and attached nodes are added to the result set.\n     * If one of the given shape is a child of another given shape, it is not put into the result. \n     */\n    getAllShapesToConsider: function(shapes){\n        var shapesToConsider = []; // only top-level shapes\n        var childShapesToConsider = []; // all child shapes of top-level shapes\n        \n        shapes.each(function(shape){\n            //Throw away these shapes which have a parent in given shapes\n            isChildShapeOfAnother = shapes.any(function(s2){\n                return s2.hasChildShape(shape);\n            });\n            if(isChildShapeOfAnother) return;\n            \n            // This shape should be considered\n            shapesToConsider.push(shape);\n            // Consider attached nodes (e.g. intermediate events)\n            if (shape instanceof ORYX.Core.Node) {\n\t\t\t\tvar attached = shape.getOutgoingNodes();\n\t\t\t\tattached = attached.findAll(function(a){ return !shapes.include(a) });\n                shapesToConsider = shapesToConsider.concat(attached);\n            }\n            \n            childShapesToConsider = childShapesToConsider.concat(shape.getChildShapes(true));\n        }.bind(this));\n        \n        // All edges between considered child shapes should be considered\n        // Look for these edges having incoming and outgoing in childShapesToConsider\n        var edgesToConsider = this.facade.getCanvas().getChildEdges().select(function(edge){\n            // Ignore if already added\n            if(shapesToConsider.include(edge)) return false;\n            // Ignore if there are no docked shapes\n            if(edge.getAllDockedShapes().size() === 0) return false; \n            // True if all docked shapes are in considered child shapes\n            return edge.getAllDockedShapes().all(function(shape){\n                // Remember: Edges can have other edges on outgoing, that is why edges must not be included in childShapesToConsider\n                return shape instanceof ORYX.Core.Edge || childShapesToConsider.include(shape);\n            });\n        });\n        shapesToConsider = shapesToConsider.concat(edgesToConsider);\n        \n        return shapesToConsider;\n    },\n    \n    /**\n     * Performs the cut operation by first copy-ing and then deleting the\n     * current selection.\n     */\n    editCut: function(){\n        //TODO document why this returns false.\n        //TODO document what the magic boolean parameters are supposed to do.\n        \n        this.editCopy(false, true);\n        this.editDelete(true);\n        return false;\n    },\n    \n    /**\n     * Performs the copy operation.\n     * @param {Object} will_not_update ??\n     */\n    editCopy: function( will_update, useNoOffset ){\n        var selection = this.facade.getSelection();\n        \n        //if the selection is empty, do not remove the previously copied elements\n        if(selection.length == 0) return;\n        \n        this.clipboard.refresh(selection, this.getAllShapesToConsider(selection), this.facade.getCanvas().getStencil().stencilSet().namespace(), useNoOffset);\n\n        if( will_update ) this.facade.updateSelection();\n    },\n    \n    /**\n     * Performs the paste operation.\n     */\n    editPaste: function(){\n        // Create a new canvas with childShapes \n\t\t//and stencilset namespace to be JSON Import conform\n\t\tvar canvas = {\n            childShapes: this.clipboard.shapesAsJson,\n\t\t\tstencilset:{\n\t\t\t\tnamespace:this.clipboard.SSnamespace\n\t\t\t}\n        };\n        // Apply json helper to iterate over json object\n\t\tjQuery.extend(canvas, ORYX.Core.AbstractShape.JSONHelper);\n        \n        var childShapeResourceIds = canvas.getChildShapes(true).pluck(\"resourceId\");\n        var outgoings = {};\n        // Iterate over all shapes\n        canvas.eachChild(function(shape, parent){\n            // Throw away these references where referenced shape isn't copied\n            shape.outgoing = shape.outgoing.select(function(out){\n                return childShapeResourceIds.include(out.resourceId);\n            });\n\t\t\tshape.outgoing.each(function(out){\n\t\t\t\tif (!outgoings[out.resourceId]){ outgoings[out.resourceId] = []; }\n\t\t\t\toutgoings[out.resourceId].push(shape);\n\t\t\t});\n\t\t\t\n            return shape;\n        }.bind(this), true, true);\n        \n\n        // Iterate over all shapes\n        canvas.eachChild(function(shape, parent){\n            \n        \t// Check if there has a valid target\n            if(shape.target && !(childShapeResourceIds.include(shape.target.resourceId))){\n                shape.target = undefined;\n                shape.targetRemoved = true;\n            }\n    \t\t\n    \t\t// Check if the first docker is removed\n    \t\tif(\tshape.dockers && \n    \t\t\tshape.dockers.length >= 1 && \n    \t\t\tshape.dockers[0].getDocker &&\n    \t\t\t((shape.dockers[0].getDocker().getDockedShape() &&\n    \t\t\t!childShapeResourceIds.include(shape.dockers[0].getDocker().getDockedShape().resourceId)) || \n    \t\t\t!shape.getShape().dockers[0].getDockedShape()&&!outgoings[shape.resourceId])) {\n    \t\t\t\t\n    \t\t\tshape.sourceRemoved = true;\n    \t\t}\n\t\t\t\n            return shape;\n        }.bind(this), true, true);\n\n\t\t\n        // Iterate over top-level shapes\n        canvas.eachChild(function(shape, parent){\n            // All top-level shapes should get an offset in their bounds\n            // Move the shape occording to COPY_MOVE_OFFSET\n        \tif (this.clipboard.useOffset) {\n\t            shape.bounds = {\n\t                lowerRight: {\n\t                    x: shape.bounds.lowerRight.x + ORYX.CONFIG.COPY_MOVE_OFFSET,\n\t                    y: shape.bounds.lowerRight.y + ORYX.CONFIG.COPY_MOVE_OFFSET\n\t                },\n\t                upperLeft: {\n\t                    x: shape.bounds.upperLeft.x + ORYX.CONFIG.COPY_MOVE_OFFSET,\n\t                    y: shape.bounds.upperLeft.y + ORYX.CONFIG.COPY_MOVE_OFFSET\n\t                }\n\t            };\n        \t}\n            // Only apply offset to shapes with a target\n            if (shape.dockers){\n                shape.dockers = shape.dockers.map(function(docker, i){\n                    // If shape had a target but the copied does not have anyone anymore,\n                    // migrate the relative dockers to absolute ones.\n                    if( (shape.targetRemoved === true && i == shape.dockers.length - 1&&docker.getDocker) ||\n\t\t\t\t\t\t(shape.sourceRemoved === true && i == 0&&docker.getDocker)){\n\n                        docker = docker.getDocker().bounds.center();\n                    }\n\n\t\t\t\t\t// If it is the first docker and it has a docked shape, \n\t\t\t\t\t// just return the coordinates\n\t\t\t\t   \tif ((i == 0 && docker.getDocker instanceof Function && \n\t\t\t\t   \t\tshape.sourceRemoved !== true && (docker.getDocker().getDockedShape() || ((outgoings[shape.resourceId]||[]).length > 0 && (!(shape.getShape() instanceof ORYX.Core.Node) || outgoings[shape.resourceId][0].getShape() instanceof ORYX.Core.Node)))) || \n\t\t\t\t\t\t(i == shape.dockers.length - 1 && docker.getDocker instanceof Function && \n\t\t\t\t\t\tshape.targetRemoved !== true && (docker.getDocker().getDockedShape() || shape.target))){\n\t\t\t\t\t\t\t\n\t\t\t\t\t\treturn {\n                        \tx: docker.x, \n                        \ty: docker.y,\n                        \tgetDocker: docker.getDocker\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (this.clipboard.useOffset) {\n\t                    return {\n\t\t                        x: docker.x + ORYX.CONFIG.COPY_MOVE_OFFSET, \n\t\t                        y: docker.y + ORYX.CONFIG.COPY_MOVE_OFFSET,\n\t                        \tgetDocker: docker.getDocker\n\t\t                    };\n\t\t\t\t   \t} else {\n\t\t\t\t   \t\treturn {\n                        \tx: docker.x, \n                        \ty: docker.y,\n                        \tgetDocker: docker.getDocker\n\t\t\t\t\t\t};\n\t\t\t\t   \t}\n                }.bind(this));\n\n            } else if (shape.getShape() instanceof ORYX.Core.Node && shape.dockers && shape.dockers.length > 0 && (!shape.dockers.first().getDocker || shape.sourceRemoved === true || !(shape.dockers.first().getDocker().getDockedShape() || outgoings[shape.resourceId]))){\n            \t\n            \tshape.dockers = shape.dockers.map(function(docker, i){\n            \t\t\n                    if((shape.sourceRemoved === true && i == 0&&docker.getDocker)){\n                    \tdocker = docker.getDocker().bounds.center();\n                    }\n                    \n                    if (this.clipboard.useOffset) {\n\t            \t\treturn {\n\t                        x: docker.x + ORYX.CONFIG.COPY_MOVE_OFFSET, \n\t                        y: docker.y + ORYX.CONFIG.COPY_MOVE_OFFSET,\n\t                    \tgetDocker: docker.getDocker\n\t                    };\n                    } else {\n\t            \t\treturn {\n\t                        x: docker.x, \n\t                        y: docker.y,\n\t                    \tgetDocker: docker.getDocker\n\t                    };\n                    }\n            \t}.bind(this));\n            }\n            \n            return shape;\n        }.bind(this), false, true);\n\n        this.clipboard.useOffset = true;\n        this.facade.importJSON(canvas);\n    },\n    \n    /**\n     * Performs the delete operation. No more asking.\n     */\n    editDelete: function(){\n        var selection = this.facade.getSelection();\n        \n        var clipboard = new ORYX.Plugins.Edit.ClipBoard();\n        clipboard.refresh(selection, this.getAllShapesToConsider(selection));\n        \n\t\tvar command = new ORYX.Plugins.Edit.DeleteCommand(clipboard , this.facade);\n                                       \n\t\tthis.facade.executeCommands([command]);\n    }\n}); \n\nORYX.Plugins.Edit.ClipBoard = Clazz.extend({\n    construct: function(){\n        this.shapesAsJson = [];\n        this.selection = [];\n\t\tthis.SSnamespace=\"\";\n\t\tthis.useOffset=true;\n    },\n    isOccupied: function(){\n        return this.shapesAsJson.length > 0;\n    },\n    refresh: function(selection, shapes, namespace, useNoOffset){\n        this.selection = selection;\n        this.SSnamespace=namespace;\n        // Store outgoings, targets and parents to restore them later on\n        this.outgoings = {};\n        this.parents = {};\n        this.targets = {};\n        this.useOffset = useNoOffset !== true;\n        \n        this.shapesAsJson = shapes.map(function(shape){\n            var s = shape.toJSON();\n            s.parent = {resourceId : shape.getParentShape().resourceId};\n            s.parentIndex = shape.getParentShape().getChildShapes().indexOf(shape)\n            return s;\n        });\n    }\n});\n\nORYX.Plugins.Edit.DeleteCommand = ORYX.Core.Command.extend({\n    construct: function(clipboard, facade){\n        this.clipboard          = clipboard;\n        this.shapesAsJson       = clipboard.shapesAsJson;\n        this.facade             = facade;\n        \n        // Store dockers of deleted shapes to restore connections\n        this.dockers            = this.shapesAsJson.map(function(shapeAsJson) {\n            var shape = shapeAsJson.getShape();\n            var incomingDockers = shape.getIncomingShapes().map(function(s){return s.getDockers().last();});\n            var outgoingDockers = shape.getOutgoingShapes().map(function(s){return s.getDockers().first();});\n            var dockers = shape.getDockers().concat(incomingDockers, outgoingDockers).compact().map(function(docker){\n                return {\n                    object: docker,\n                    referencePoint: docker.referencePoint,\n                    dockedShape: docker.getDockedShape()\n                };\n            });\n            return dockers;\n        }).flatten();\n    },          \n    execute: function(){\n        this.shapesAsJson.each(function(shapeAsJson){\n            // Delete shape\n            this.facade.deleteShape(shapeAsJson.getShape());\n        }.bind(this));\n        \n        this.facade.setSelection([]);\n        this.facade.getCanvas().update();\t\t\n\t\tthis.facade.updateSelection();\n        \n    },\n    rollback: function(){\n        this.shapesAsJson.each(function(shapeAsJson) {\n            var shape = shapeAsJson.getShape();\n            var parent = this.facade.getCanvas().getChildShapeByResourceId(shapeAsJson.parent.resourceId) || this.facade.getCanvas();\n            parent.add(shape, shape.parentIndex);\n        }.bind(this));\n        \n        //reconnect shapes\n        this.dockers.each(function(d) {\n            d.object.setDockedShape(d.dockedShape);\n            d.object.setReferencePoint(d.referencePoint);\n        }.bind(this));\n        \n        this.facade.setSelection(this.selectedShapes);\n        this.facade.getCanvas().update();\t\n\t\tthis.facade.updateSelection();\n        \n    }\n});/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * @namespace Oryx name space for plugins\n * @name ORYX.Plugins\n*/\nif(!ORYX.Plugins)\n\tORYX.Plugins = new Object();\n\n/**\n * The view plugin offers all of zooming functionality accessible over the \n * tool bar. This are zoom in, zoom out, zoom to standard, zoom fit to model.\n * \n * @class ORYX.Plugins.View\n * @extends Clazz\n * @param {Object} facade The editor facade for plugins.\n*/\nORYX.Plugins.View = {\n\t/** @lends ORYX.Plugins.View.prototype */\n\tfacade: undefined,\n\n\tconstruct: function(facade, ownPluginData) {\n\t\tthis.facade = facade;\n\t\t//Standard Values\n\t\tthis.zoomLevel = 1.0;\n\t\tthis.maxFitToScreenLevel=1.5;\n\t\tthis.minZoomLevel = 0.1;\n\t\tthis.maxZoomLevel = 2.5;\n\t\tthis.diff=5; //difference between canvas and view port, s.th. like toolbar??\n\t\t\n\t\t//Read properties\n\t\tif (ownPluginData !== undefined && ownPluginData !== null) {\n\t\t\townPluginData.properties.each( function(property) {\t\t\t\n\t\t\t\tif (property.zoomLevel) {this.zoomLevel = Number(1.0);}\t\t\n\t\t\t\tif (property.maxFitToScreenLevel) {this.maxFitToScreenLevel=Number(property.maxFitToScreenLevel);}\n\t\t\t\tif (property.minZoomLevel) {this.minZoomLevel = Number(property.minZoomLevel);}\n\t\t\t\tif (property.maxZoomLevel) {this.maxZoomLevel = Number(property.maxZoomLevel);}\n\t\t\t}.bind(this));\n\t\t}\n\n\t\t\n\t\t/* Register zoom in */\n\t\tthis.facade.offer({\n\t\t\t'name':ORYX.I18N.View.zoomIn,\n\t\t\t'functionality': this.zoom.bind(this, [1.0 + ORYX.CONFIG.ZOOM_OFFSET]),\n\t\t\t'group': ORYX.I18N.View.group,\n\t\t\t'icon': ORYX.PATH + \"images/magnifier_zoom_in.png\",\n\t\t\t'description': ORYX.I18N.View.zoomInDesc,\n\t\t\t'index': 1,\n\t\t\t'minShape': 0,\n\t\t\t'maxShape': 0,\n\t\t\t'isEnabled': function(){return this.zoomLevel < this.maxZoomLevel }.bind(this)});\n\t\t\n\t\t/* Register zoom out */\n\t\tthis.facade.offer({\n\t\t\t'name':ORYX.I18N.View.zoomOut,\n\t\t\t'functionality': this.zoom.bind(this, [1.0 - ORYX.CONFIG.ZOOM_OFFSET]),\n\t\t\t'group': ORYX.I18N.View.group,\n\t\t\t'icon': ORYX.PATH + \"images/magnifier_zoom_out.png\",\n\t\t\t'description': ORYX.I18N.View.zoomOutDesc,\n\t\t\t'index': 2,\n\t\t\t'minShape': 0,\n\t\t\t'maxShape': 0,\n\t\t\t'isEnabled': function(){ return this._checkSize() }.bind(this)});\n\t\t\n\t\t/* Register zoom standard */\n\t\tthis.facade.offer({\n\t\t\t'name':ORYX.I18N.View.zoomStandard,\n\t\t\t'functionality': this.setAFixZoomLevel.bind(this, 1),\n\t\t\t'group': ORYX.I18N.View.group,\n\t\t\t'icon': ORYX.PATH + \"images/zoom_standard.png\",\n\t\t\t'cls' : 'icon-large',\n\t\t\t'description': ORYX.I18N.View.zoomStandardDesc,\n\t\t\t'index': 3,\n\t\t\t'minShape': 0,\n\t\t\t'maxShape': 0,\n\t\t\t'isEnabled': function(){return this.zoomLevel != 1}.bind(this)\n\t\t});\n\t\t\n\t\t/* Register zoom fit to model */\n\t\tthis.facade.offer({\n\t\t\t'name':ORYX.I18N.View.zoomFitToModel,\n\t\t\t'functionality': this.zoomFitToModel.bind(this),\n\t\t\t'group': ORYX.I18N.View.group,\n\t\t\t'icon': ORYX.PATH + \"images/image.png\",\n\t\t\t'description': ORYX.I18N.View.zoomFitToModelDesc,\n\t\t\t'index': 4,\n\t\t\t'minShape': 0,\n\t\t\t'maxShape': 0\n\t\t});\n\t},\n\t\n\t/**\n\t * It sets the zoom level to a fix value and call the zooming function.\n\t * \n\t * @param {Number} zoomLevel\n\t * \t\t\tthe zoom level\n\t */\n\tsetAFixZoomLevel : function(zoomLevel) {\n\t\tthis.zoomLevel = zoomLevel;\n\t\tthis._checkZoomLevelRange();\n\t\tthis.zoom(1);\n\t},\n\t\n\t/**\n\t * It does the actual zooming. It changes the viewable size of the canvas \n\t * and all to its child elements.\n\t * \n\t * @param {Number} factor\n\t * \t\tthe factor to adjust the zoom level\n\t */\n\tzoom: function(factor) {\n\t\t// TODO: Zoomen auf allen Objekten im SVG-DOM\n\t\t\n\t\tthis.zoomLevel *= factor;\n\t\tvar scrollNode \t= this.facade.getCanvas().getHTMLContainer().parentNode.parentNode;\n\t\tvar canvas \t\t= this.facade.getCanvas();\n\t\tvar newWidth \t= canvas.bounds.width()  * this.zoomLevel;\n\t\tvar newHeight \t= canvas.bounds.height() * this.zoomLevel;\n\t\t\n\t\t/* Set new top offset */\n\t\tvar offsetTop = (canvas.node.parentNode.parentNode.parentNode.offsetHeight - newHeight) / 2.0;\t\n\t\toffsetTop = offsetTop > 20 ? offsetTop - 20 : 0;\n\t\tcanvas.node.parentNode.parentNode.style.marginTop = offsetTop + \"px\";\n\t\toffsetTop += 5;\n\t\tcanvas.getHTMLContainer().style.top = offsetTop + \"px\";\n\t\t\n\t\t/*readjust scrollbar*/\n\t\tvar newScrollTop=\tscrollNode.scrollTop - Math.round((canvas.getHTMLContainer().parentNode.getHeight()-newHeight) / 2)+this.diff;\n\t\tvar newScrollLeft=\tscrollNode.scrollLeft - Math.round((canvas.getHTMLContainer().parentNode.getWidth()-newWidth) / 2)+this.diff;\n\t\t\n\t\t/* Set new Zoom-Level */\n\t\tcanvas.setSize({width: newWidth, height: newHeight}, true);\n\t\t\n\t\t/* Set Scale-Factor */\n\t\tcanvas.node.setAttributeNS(null, \"transform\", \"scale(\" +this.zoomLevel+ \")\");\t\n\n\t\t/* Refresh the Selection */\n\t\tthis.facade.updateSelection();\n\t\tscrollNode.scrollTop=newScrollTop;\n\t\tscrollNode.scrollLeft=newScrollLeft;\n\t\t\n\t\t/* Update the zoom-level*/\n\t\tcanvas.zoomLevel = this.zoomLevel;\n\t},\n\t\n\t\n\t/**\n\t * It calculates the zoom level to fit whole model into the visible area\n\t * of the canvas. Than the model gets zoomed and the position of the \n\t * scroll bars are adjusted.\n\t * \n\t */\n\tzoomFitToModel: function() {\n\t\t\n\t\t/* Get the size of the visible area of the canvas */\n\t\tvar scrollNode \t= this.facade.getCanvas().getHTMLContainer().parentNode.parentNode;\n\t\tvar visibleHeight = scrollNode.getHeight() - 30;\n\t\tvar visibleWidth = scrollNode.getWidth() - 30;\n\t\t\n\t\tvar nodes = this.facade.getCanvas().getChildShapes();\n\t\t\n\t\tif(!nodes || nodes.length < 1) {\n\t\t\treturn false;\t\t\t\n\t\t}\n\t\t\t\n\t\t/* Calculate size of canvas to fit the model */\n\t\tvar bounds = nodes[0].absoluteBounds().clone();\n\t\tnodes.each(function(node) {\n\t\t\tbounds.include(node.absoluteBounds().clone());\n\t\t});\n\t\t\n\t\t\n\t\t/* Set new Zoom Level */\n\t\tvar scaleFactorWidth =  visibleWidth / bounds.width();\n\t\tvar scaleFactorHeight = visibleHeight / bounds.height();\n\t\t\n\t\t/* Choose the smaller zoom level to fit the whole model */\n\t\tvar zoomFactor = scaleFactorHeight < scaleFactorWidth ? scaleFactorHeight : scaleFactorWidth;\n\t\t\n\t\t/*Test if maximum zoom is reached*/\n\t\tif(zoomFactor>this.maxFitToScreenLevel){zoomFactor=this.maxFitToScreenLevel}\n\t\t/* Do zooming */\n\t\tthis.setAFixZoomLevel(zoomFactor);\n\t\t\n\t\t/* Set scroll bar position */\n\t\tscrollNode.scrollTop = Math.round(bounds.upperLeft().y * this.zoomLevel) - 5;\n\t\tscrollNode.scrollLeft = Math.round(bounds.upperLeft().x * this.zoomLevel) - 5;\n\t\t\n\t},\n\t\n\t/**\n\t * It checks if the zoom level is less or equal to the level, which is required\n\t * to schow the whole canvas.\n\t * \n\t * @private\n\t */\n\t_checkSize:function(){\n\t\tvar canvasParent=this.facade.getCanvas().getHTMLContainer().parentNode;\n\t\tvar minForCanvas= Math.min((canvasParent.parentNode.getWidth()/canvasParent.getWidth()),(canvasParent.parentNode.getHeight()/canvasParent.getHeight()));\n\t\treturn 1.05 > minForCanvas;\n\t\t\n\t},\n\t/**\n\t * It checks if the zoom level is included in the definined zoom\n\t * level range.\n\t * \n\t * @private\n\t */\n\t_checkZoomLevelRange: function() {\n\t\t/*var canvasParent=this.facade.getCanvas().getHTMLContainer().parentNode;\n\t\tvar maxForCanvas= Math.max((canvasParent.parentNode.getWidth()/canvasParent.getWidth()),(canvasParent.parentNode.getHeight()/canvasParent.getHeight()));\n\t\tif(this.zoomLevel > maxForCanvas) {\n\t\t\tthis.zoomLevel = maxForCanvas;\t\t\t\n\t\t}*/\n\t\tif(this.zoomLevel < this.minZoomLevel) {\n\t\t\tthis.zoomLevel = this.minZoomLevel;\t\t\t\n\t\t}\n\t\t\n\t\tif(this.zoomLevel > this.maxZoomLevel) {\n\t\t\tthis.zoomLevel = this.maxZoomLevel;\t\t\t\n\t\t}\n\t}\n};\n\nORYX.Plugins.View = Clazz.extend(ORYX.Plugins.View);\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\nif(!Signavio){ var Signavio = {} };\n\tif (!Signavio.Core) { Signavio.Core = {} };\n\tSignavio.Core.Version = \"1.0\";\n\t\t\t/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nif (!Signavio) {\n\tvar Signavio = new Object();\n}\n\nif (!Signavio.Plugins) {\n\tSignavio.Plugins = new Object();\n}\n\nif (!Signavio.Plugins.Utils) {\n\tSignavio.Plugins.Utils = new Object();\n}\n\nif (!Signavio.Helper) {\n\tSignavio.Helper = new Object();\n}\n\n\nnew function() {\n\n\t/**\n\t * Provides an uniq id\n\t * @overwrite\n\t * @return {String}\n\t *\n\t */\n\tORYX.Editor.provideId = function() {\n\t\tvar res = [], hex = '0123456789ABCDEF';\n\t\n\t\tfor (var i = 0; i < 36; i++) res[i] = Math.floor(Math.random()*0x10);\n\t\n\t\tres[14] = 4;\n\t\tres[19] = (res[19] & 0x3) | 0x8;\n\t\n\t\tfor (var i = 0; i < 36; i++) res[i] = hex[res[i]];\n\t\n\t\tres[8] = res[13] = res[18] = res[23] = '-';\n\t\n\t\treturn \"sid-\" + res.join('');\n\t};\n\n\n}();\n\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nif (!ORYX.Plugins) {\n    ORYX.Plugins = new Object();\n}\n\n/**\n * This plugin is responsible for displaying loading indicators and to prevent\n * the user from accidently unloading the page by, e.g., pressing the backspace\n * button and returning to the previous site in history.\n * @param {Object} facade The editor plugin facade to register enhancements with.\n */\nORYX.Plugins.Loading = {\n\n    construct: function(facade){\n    \n        this.facade = facade;\n        \n        // The parent Node\n        this.node = ORYX.Editor.graft(\"http://www.w3.org/1999/xhtml\", this.facade.getCanvas().getHTMLContainer().parentNode, ['div', {\n            'class': 'LoadingIndicator'\n        }, '']);\n        \n        this.facade.registerOnEvent(ORYX.CONFIG.EVENT_LOADING_ENABLE, this.enableLoading.bind(this));\n        this.facade.registerOnEvent(ORYX.CONFIG.EVENT_LOADING_DISABLE, this.disableLoading.bind(this));\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_LOADING_STATUS, this.showStatus.bind(this));\n        \n        this.disableLoading();\n    },\n    \n    enableLoading: function(options){\n\t\tif(options.text) \n\t\t\tthis.node.innerHTML = options.text + \"...\";\n\t\telse\n\t\t\tthis.node.innerHTML = ORYX.I18N.Loading.waiting;\n\t\tthis.node.removeClassName('StatusIndicator');\n\t\tthis.node.addClassName('LoadingIndicator');\n        this.node.style.display = \"block\";\n\t\t\n\t\tvar pos = this.facade.getCanvas().rootNode.parentNode.parentNode.parentNode.parentNode;\n\n\t\tthis.node.style.top \t\t= pos.offsetTop + 'px';\n\t\tthis.node.style.left \t\t= pos.offsetLeft +'px';\n\t\t\t\t\t\n    },\n    \n    disableLoading: function(){\n        this.node.style.display = \"none\";\n    },\n\t\n\tshowStatus: function(options) {\n\t\tif(options.text) {\n\t\t\tthis.node.innerHTML = options.text;\n\t\t\tthis.node.addClassName('StatusIndicator');\n\t\t\tthis.node.removeClassName('LoadingIndicator');\n\t\t\tthis.node.style.display = 'block';\n\n\t\t\tvar pos = this.facade.getCanvas().rootNode.parentNode.parentNode.parentNode.parentNode;\n\n\t\t\tthis.node.style.top \t= pos.offsetTop + 'px';\n\t\t\tthis.node.style.left \t= pos.offsetLeft +'px';\n\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\tvar tout = options.timeout ? options.timeout : 2000;\n\t\t\t\n\t\t\twindow.setTimeout((function(){\n            \n                this.disableLoading();\n                \n            }).bind(this), tout);\n\t\t}\n\t\t\n\t}\n}\n\nORYX.Plugins.Loading = Clazz.extend(ORYX.Plugins.Loading);\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\nif (!ORYX.Plugins) {\n    ORYX.Plugins = new Object();\n}\n\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\n/**\n * This plugin is responsible for resizing the canvas.\n * @param {Object} facade The editor plugin facade to register enhancements with.\n */\nORYX.Plugins.CanvasResize = Clazz.extend({\n\n    construct: function(facade){\n\t\t\n        this.facade = facade;\n\t\tnew ORYX.Plugins.CanvasResizeButton( this.facade.getCanvas(), \"N\", this.resize.bind(this));\n\t\tnew ORYX.Plugins.CanvasResizeButton( this.facade.getCanvas(), \"W\", this.resize.bind(this));\n\t\tnew ORYX.Plugins.CanvasResizeButton( this.facade.getCanvas(), \"E\", this.resize.bind(this));\n\t\tnew ORYX.Plugins.CanvasResizeButton( this.facade.getCanvas(), \"S\", this.resize.bind(this));\n\t\t\n\t\twindow.setTimeout(function(){jQuery(window).trigger('resize');});\n\n    },\n    \n    resize: function( position, shrink ){\n    \t\n    \tresizeCanvas = function(position, extentionSize, facade) {\n        \tvar canvas \t\t= facade.getCanvas();\n    \t\tvar b \t\t\t= canvas.bounds;\n    \t\tvar scrollNode \t= facade.getCanvas().getHTMLContainer().parentNode.parentNode;\n    \t\t\n    \t\tif( position == \"E\" || position == \"W\"){\n    \t\t\tcanvas.setSize({width: (b.width() + extentionSize)*canvas.zoomLevel, height: (b.height())*canvas.zoomLevel})\n\n    \t\t} else if( position == \"S\" || position == \"N\"){\n    \t\t\tcanvas.setSize({width: (b.width())*canvas.zoomLevel, height: (b.height() + extentionSize)*canvas.zoomLevel})\n    \t\t}\n\n    \t\tif( position == \"N\" || position == \"W\"){\n    \t\t\t\n    \t\t\tvar move = position == \"N\" ? {x: 0, y: extentionSize}: {x: extentionSize, y: 0 };\n\n    \t\t\t// Move all children\n    \t\t\tcanvas.getChildNodes(false, function(shape){ shape.bounds.moveBy(move) })\n    \t\t\t// Move all dockers, when the edge has at least one docked shape\n    \t\t\tvar edges = canvas.getChildEdges().findAll(function(edge){ return edge.getAllDockedShapes().length > 0})\n    \t\t\tvar dockers = edges.collect(function(edge){ return edge.dockers.findAll(function(docker){ return !docker.getDockedShape() })}).flatten();\n    \t\t\tdockers.each(function(docker){ docker.bounds.moveBy(move)})\n    \t\t} else if( position == \"S\" ){\n    \t\t\tscrollNode.scrollTop += extentionSize;\n    \t\t} else if( position == \"E\" ){\n    \t\t\tscrollNode.scrollLeft += extentionSize;\n    \t\t}\n    \t\t\n    \t\tjQuery(window).trigger('resize');\n    \t\t\n    \t\tcanvas.update();\n    \t\tfacade.updateSelection();\n        }\n\t\t\n\t\tvar commandClass = ORYX.Core.Command.extend({\n\t\t\tconstruct: function(position, extentionSize, facade){\n\t\t\t\tthis.position = position;\n\t\t\t\tthis.extentionSize = extentionSize;\n\t\t\t\tthis.facade = facade;\n\t\t\t},\t\t\t\n\t\t\texecute: function(){\n\t\t\t\tresizeCanvas(this.position, this.extentionSize, this.facade);\n\t\t\t},\n\t\t\trollback: function(){\n\t\t\t\tresizeCanvas(this.position, -this.extentionSize, this.facade);\n\t\t\t},\n\t\t\tupdate:function(){\n\t\t\t}\n\t\t});\n\t\t\n\t\tvar extentionSize = ORYX.CONFIG.CANVAS_RESIZE_INTERVAL;\n\t\tif(shrink) extentionSize = -extentionSize;\n\t\tvar command = new commandClass(position, extentionSize, this.facade);\n\t\t\n\t\tthis.facade.executeCommands([command]);\n\t\t\t\n    }\n    \n});\n\n\nORYX.Plugins.CanvasResizeButton = Clazz.extend({\n\t\n\tconstruct: function(canvas, position, callback){\n\t\tthis.canvas = canvas;\n\t\tvar parentNode = canvas.getHTMLContainer().parentNode;\n\t\t\n\t\twindow.myParent=parentNode;\n\t\t\t\n\t\tvar actualScrollNode = jQuery('#canvasSection')[0];\n\t\tvar scrollNode \t= actualScrollNode;\n\t\tvar canvasNode = jQuery('#canvasSection').find(\".ORYX_Editor\")[0];\n\t\tvar svgRootNode = canvasNode.children[0];\n\t\t\n\t\tvar iconClass = 'glyphicon glyphicon-chevron-';\n\t\tvar iconClassShrink = 'glyphicon glyphicon-chevron-';\n\t\tif(position == 'N') {\n\t\t\ticonClass += 'up';\n\t\t\ticonClassShrink += 'down';\n\t\t} else if(position == 'S') {\n\t\t\ticonClass += 'down';\n\t\t\ticonClassShrink += 'up';\n\t\t} else if(position == 'E') {\n\t\t\ticonClass += 'right';\n\t\t\ticonClassShrink += 'left';\n\t\t} else if(position == 'W') {\n\t\t\ticonClass += 'left';\n\t\t\ticonClassShrink += 'right';\n\t\t}\n\t\t\n\t\t// The buttons\n\t\tvar idGrow = 'canvas-shrink-' + position;\n\t\tvar idShrink = 'canvas-grow-' + position;\n\t\t\n\t\tvar buttonGrow \t= ORYX.Editor.graft(\"http://www.w3.org/1999/xhtml\", parentNode, ['div', {'class': 'canvas_resize_indicator canvas_resize_indicator_grow' + ' ' + position, 'id': idGrow ,'title':ORYX.I18N.RESIZE.tipGrow+ORYX.I18N.RESIZE[position]},\n             ['i', {'class' : iconClass}]\n\t\t]);\n\t\tvar buttonShrink \t= ORYX.Editor.graft(\"http://www.w3.org/1999/xhtml\", parentNode, ['div', {'class': 'canvas_resize_indicator canvas_resize_indicator_shrink' + ' ' + position, 'id': idShrink ,'title':ORYX.I18N.RESIZE.tipGrow+ORYX.I18N.RESIZE[position]},\n             ['i', {'class' : iconClassShrink}]\n\t\t]);\n\t\t// Defines a callback which gives back\n\t\t// a boolean if the current mouse event \n\t\t// is over the particular button area\n\t\tvar offSetWidth = 60;\n\t\tvar isOverOffset = function(event) {\n\t\t\t\n\t\t\tvar isOverButton = event.target.id.indexOf(\"canvas-shrink\") != -1\n\t\t\t\t|| event.target.id.indexOf(\"canvas-grow\") != -1\n\t\t\t\t|| event.target.parentNode.id.indexOf(\"canvas-shrink\") != -1\n\t\t\t\t|| event.target.parentNode.id.indexOf(\"canvas-grow\") != -1;\n\t\t\tif(isOverButton) {\n\t\t\t\tif(event.target.id == idGrow || event.target.id == idShrink || \n\t\t\t\t\t\tevent.target.parentNode.id == idGrow || event.target.parentNode.id == idShrink ) {\n\t\t\t\t\treturn true;\n\t\t\t\t} else {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif(event.target!=parentNode && event.target!=scrollNode&& event.target!=scrollNode.firstChild&& event.target!=svgRootNode&& event.target!=scrollNode){ return false; }\n\t\t\t\n\t\t\t//if(inCanvas){offSetWidth=30}else{offSetWidth=30*2}\n\t\t\t//Safari work around\n\t\t\tvar X=event.offsetX !== undefined ? event.offsetX : event.layerX;\n\t\t\tvar Y=event.offsetY !== undefined ? event.offsetY : event.layerY;\n\t\t\t\n\t\t\tvar canvasOffset = 0;\n\t\t\tif(canvasNode.clientWidth < actualScrollNode.clientWidth) {\n              \tvar widthDiff = actualScrollNode.clientWidth -  canvasNode.clientWidth;\n              \tcanvasOffset = widthDiff / 2;\n            }\n\t\t\t\n\t\t\t\t// Adjust to relative location to the actual viewport\n\t\t\t\tY = Y - actualScrollNode.scrollTop;\n\t\t\t\tX = X - actualScrollNode.scrollLeft;\n\t\t\t\n\t\t\t\n\t\t\tif(position == \"N\"){\n\t\t\t\treturn  Y < offSetWidth;\n\t\t\t} else if(position == \"W\"){\n\t\t\t\treturn X < offSetWidth + canvasOffset;\n\t\t\t} else if(position == \"E\"){\n\t\t\t\treturn actualScrollNode.clientWidth - X < offSetWidth + canvasOffset;\n\t\t\t} else if(position == \"S\"){\n\t\t\t\treturn actualScrollNode.clientHeight - Y < offSetWidth;\n\t\t\t}\n\t\t\t\n\t\t\treturn false;\n\t\t};\n\t\t\n\t\tvar showButtons = (function() {\n\t\t\tbuttonGrow.show(); \n        \n\t\t\tvar w = canvas.bounds.width();\n\t\t\tvar h = canvas.bounds.height();\n        \n\t\t\tif(position==\"N\" && (h - ORYX.CONFIG.CANVAS_RESIZE_INTERVAL > ORYX.CONFIG.CANVAS_MIN_HEIGHT)) buttonShrink.show();\n\t\t\telse if(position==\"E\" && (w - ORYX.CONFIG.CANVAS_RESIZE_INTERVAL > ORYX.CONFIG.CANVAS_MIN_WIDTH)) buttonShrink.show();\n\t\t\telse if(position==\"S\" && (h - ORYX.CONFIG.CANVAS_RESIZE_INTERVAL > ORYX.CONFIG.CANVAS_MIN_HEIGHT)) buttonShrink.show();\n\t\t\telse if(position==\"W\" && (w - ORYX.CONFIG.CANVAS_RESIZE_INTERVAL > ORYX.CONFIG.CANVAS_MIN_WIDTH)) buttonShrink.show();\n\t\t\telse buttonShrink.hide();\n\t\t\t\n\n\t\t}).bind(this);\n        \n\t\tvar hideButtons = function() {\n\t\t\tbuttonGrow.hide(); \n\t\t\tbuttonShrink.hide();\n\t\t};\n        \n\t\t// If the mouse move is over the button area, show the button\n\t\tparentNode.parentNode.addEventListener(\tORYX.CONFIG.EVENT_MOUSEMOVE, \tfunction(event){ if( isOverOffset(event) ){showButtons();} else {hideButtons()}} , false );\n\t\t// If the mouse is over the button, show them\n\t\tbuttonGrow.addEventListener(\t\tORYX.CONFIG.EVENT_MOUSEOVER, \tfunction(event){showButtons();}, true );\n\t\tbuttonShrink.addEventListener(\t\tORYX.CONFIG.EVENT_MOUSEOVER, \tfunction(event){showButtons();}, true );\n\t\t// If the mouse is out, hide the button\n\t\t//scrollNode.addEventListener(\t\tORYX.CONFIG.EVENT_MOUSEOUT, \tfunction(event){button.hide()}, true )\n\t\tparentNode.parentNode.addEventListener(\tORYX.CONFIG.EVENT_MOUSEOUT, \tfunction(event){hideButtons()} , true );\n\t\t//svgRootNode.addEventListener(\tORYX.CONFIG.EVENT_MOUSEOUT, \tfunction(event){ inCanvas = false } , true );\n        \n\t\t// Hide the button initialy\n\t\thideButtons();\n\n\t\t// Add the callbacks\n\t    buttonGrow.addEventListener('click', function(){callback( position ); showButtons();}, true);\n\t    buttonShrink.addEventListener('click', function(){callback( position, true ); showButtons();}, true);\n\n\t}\n\t\n\n});\n\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nif (!ORYX.Plugins) \n    ORYX.Plugins = new Object();\n\nORYX.Plugins.RenameShapes = Clazz.extend({\n\n    facade: undefined,\n    \n    construct: function(facade){\n    \n        this.facade = facade;\n      \t\n        this.facade.registerOnEvent(ORYX.CONFIG.EVENT_CANVAS_SCROLL, this.hideField.bind(this)); \n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_DBLCLICK, this.actOnDBLClick.bind(this)); \n\t\tthis.facade.offer({\n\t\t keyCodes: [{\n\t\t\t\tkeyCode: 113, // F2-Key\n\t\t\t\tkeyAction: ORYX.CONFIG.KEY_ACTION_DOWN \n\t\t\t}\n\t\t ],\n         functionality: this.renamePerF2.bind(this)\n         });\n\t\t\n\t\t\n\t\tdocument.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEDOWN, this.hide.bind(this), true);\n    },\n\t\n\t/**\n\t * This method handles the \"F2\" key down event. The selected shape are looked\n\t * up and the editing of title/name of it gets started.\n\t */\n\trenamePerF2 : function() {\n\t\tvar selectedShapes = this.facade.getSelection();\n\t\tthis.actOnDBLClick(undefined, selectedShapes.first());\n\t},\n\t\n\tactOnDBLClick: function(evt, shape){\n\t\t\n\t\tif( !(shape instanceof ORYX.Core.Shape) ){ return; }\n\t\t\n\t\t// Destroys the old input, if there is one\n\t\tthis.destroy();\n\t\t\n\t\t// Get all properties which where at least one ref to view is set\n\t\tvar props = shape.getStencil().properties().findAll(function(item){ \n\t\t\treturn (item.refToView() \n\t\t\t\t\t&&  item.refToView().length > 0\n\t\t\t\t\t&&\titem.directlyEditable()); \n\t\t});\n\t\t// from these, get all properties where write access are and the type is String or Expression\n\t\tprops = props.findAll(function(item){ return !item.readonly() &&  (item.type() == ORYX.CONFIG.TYPE_STRING || item.type() == ORYX.CONFIG.TYPE_EXPRESSION || item.type() == ORYX.CONFIG.TYPE_DATASOURCE); });\n\t\t\n\t\t// Get all ref ids\n\t\tvar allRefToViews\t= props.collect(function(prop){ return prop.refToView(); }).flatten().compact();\n\t\t// Get all labels from the shape with the ref ids\n\t\tvar labels\t\t\t= shape.getLabels().findAll(function(label){ return allRefToViews.any(function(toView){ return label.id.endsWith(toView); }); });\n\t\t\n\t\t// If there are no referenced labels --> return\n\t\tif( labels.length == 0 ){ return; } \n\t\t\n\t\t// Define the nearest label\n\t\tvar nearestLabel \t= labels.length <= 1 ? labels[0] : null;\t\n\t\tif( !nearestLabel ){\n\t\t\tnearestLabel = labels.find(function(label){ return label.node == evt.target || label.node == evt.target.parentNode; });\n\t\t\tif( !nearestLabel ){\n\t\t\t\t\n\t\t\t\tvar evtCoord \t= this.facade.eventCoordinates(evt);\n\t\t\t\t\n\t\t\t\tvar additionalIEZoom = 1;\n                if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) {\n                    var ua = navigator.userAgent;\n                    if (ua.indexOf('MSIE') >= 0) {\n                        //IE 10 and below\n                        var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100);\n                        if (zoom !== 100) {\n                            additionalIEZoom = zoom / 100\n                        }\n                    }\n                }\n                \n                if (additionalIEZoom !== 1) {\n                     evtCoord.x = evtCoord.x / additionalIEZoom;\n                     evtCoord.y = evtCoord.y / additionalIEZoom;\n                }\n\n\t\t\t\tevtCoord.y += $(\"editor-header\").clientHeight - $(\"canvasSection\").scrollTop - 5;\n\t\t\t\tif (KISBPM.HEADER_CONFIG.showAppTitle == false)\n\t\t\t\t{\n\t\t\t\t\tevtCoord.y += 61;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tevtCoord.x -= $(\"canvasSection\").scrollLeft;\n\t\t\t\t\n\t\t\t\tvar trans\t\t= this.facade.getCanvas().rootNode.lastChild.getScreenCTM();\n\t\t\t\tevtCoord.x\t\t*= trans.a;\n\t\t\t\tevtCoord.y\t\t*= trans.d;\n\n\t\t\t\tvar diff = labels.collect(function(label){ \n\t\t\t\t\t\t\tvar center \t= this.getCenterPosition( label.node ); \n\t\t\t\t\t\t\tvar len \t= Math.sqrt( Math.pow(center.x - evtCoord.x, 2) + Math.pow(center.y - evtCoord.y, 2));\n\t\t\t\t\t\t\treturn {diff: len, label: label}; \n\t\t\t\t\t\t}.bind(this));\n\t\t\t\t\n\t\t\t\tdiff.sort(function(a, b){ return a.diff > b.diff; });\n\t\t\t\t\n\t\t\t\tnearestLabel = \tdiff[0].label;\n\n\t\t\t}\n\t\t}\n\t\t// Get the particular property for the label\n\t\tvar prop \t\t\t= props.find(function(item){ return item.refToView().any(function(toView){ return nearestLabel.id == shape.id + toView; });});\n\t\t\n\t\t// Get the center position from the nearest label\n\t\tvar width\t\t= Math.min(Math.max(100, shape.bounds.width()), 200);\n\t\tvar center \t\t= this.getCenterPosition( nearestLabel.node, shape );\n\t\tcenter.x\t\t-= (width/2);\n\t\tvar propId\t\t= prop.prefix() + \"-\" + prop.id();\n\t\tvar textInput = document.createElement(\"textarea\");\n\t\ttextInput.id = 'shapeTextInput';\n\t\ttextInput.style.position = 'absolute';\n\t\ttextInput.style.width = width + 'px';\n\t\ttextInput.style.left = (center.x < 10) ? 10 : center.x + 'px';\n\t\ttextInput.style.top = (center.y - 15) + 'px';\n\t\ttextInput.className = 'x-form-textarea x-form-field x_form_text_set_absolute';\n\t\ttextInput.value = shape.properties[propId];\n\t\tthis.oldValueText = shape.properties[propId];\n\t\tdocument.getElementById('canvasSection').appendChild(textInput);\n\t\tthis.shownTextField = textInput;\n\t\t\n\t\t\n\t\t// Value change listener needs to be defined now since we reference it in the text field\n\t\tthis.updateValueFunction = function(newValue, oldValue) {\n\t\t\tvar currentEl \t= shape;\n\t\t\tvar facade\t\t= this.facade;\n\t\t\t\n\t\t\tif (oldValue != newValue) {\n\t\t\t\t// Implement the specific command for property change\n\t\t\t\tvar commandClass = ORYX.Core.Command.extend({\n\t\t\t\t\tconstruct: function(){\n\t\t\t\t\t\tthis.el = currentEl;\n\t\t\t\t\t\tthis.propId = propId;\n\t\t\t\t\t\tthis.oldValue = oldValue;\n\t\t\t\t\t\tthis.newValue = newValue;\n\t\t\t\t\t\tthis.facade = facade;\n\t\t\t\t\t},\n\t\t\t\t\texecute: function(){\n\t\t\t\t\t\tthis.el.setProperty(this.propId, this.newValue);\n\t\t\t\t\t\t//this.el.update();\n\t\t\t\t\t\tthis.facade.setSelection([this.el]);\n\t\t\t\t\t\tthis.facade.getCanvas().update();\n\t\t\t\t\t\tthis.facade.updateSelection();\n\t\t\t\t\t},\n\t\t\t\t\trollback: function(){\n\t\t\t\t\t\tthis.el.setProperty(this.propId, this.oldValue);\n\t\t\t\t\t\t//this.el.update();\n\t\t\t\t\t\tthis.facade.setSelection([this.el]);\n\t\t\t\t\t\tthis.facade.getCanvas().update();\n\t\t\t\t\t\tthis.facade.updateSelection();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t// Instantiated the class\n\t\t\t\tvar command = new commandClass();\n\t\t\t\t\n\t\t\t\t// Execute the command\n\t\t\t\tthis.facade.executeCommands([command]);\n\t\t\t}\n\t\t}.bind(this);\n\t\t\t\n\t\tjQuery(\"#shapeTextInput\").focus();\n\t\t\n\t\tjQuery(\"#shapeTextInput\").autogrow();\n\t\t\t\n\t\t// Disable the keydown in the editor (that when hitting the delete button, the shapes not get deleted)\n\t\tthis.facade.disableEvent(ORYX.CONFIG.EVENT_KEYDOWN);\n\t\t\n\t},\n\t\n\tgetCenterPosition: function(svgNode, shape){\n\t\t\n\t\tif (!svgNode) { return {x:0, y:0}; }\n\t\t\n\t\tvar scale = this.facade.getCanvas().node.getScreenCTM();\n\t\tvar absoluteXY = shape.bounds.upperLeft();\n\t\t\n\t\tvar hasParent = true;\n\t\tvar searchShape = shape;\n\t\twhile (hasParent)\n\t\t{\n\t\t\tif (searchShape.getParentShape().getStencil().idWithoutNs() === 'BPMNDiagram')\n\t\t\t{\n\t\t\t\thasParent = false;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tvar parentXY = searchShape.getParentShape().bounds.upperLeft();\n\t\t\t\tabsoluteXY.x += parentXY.x;\n\t\t\t\tabsoluteXY.y += parentXY.y;\n\t\t\t\tsearchShape = searchShape.getParentShape();\n\t\t\t}\n\t\t}\n\t\t\n\t\tvar center = shape.bounds.midPoint();\n\t\tcenter.x += absoluteXY.x + scale.e;\n\t\tcenter.y += absoluteXY.y + scale.f;\n\t\t\n\t\tcenter.x *= scale.a;\n\t\tcenter.y *= scale.d;\n\t\t\n\t\tvar additionalIEZoom = 1;\n        if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) {\n            var ua = navigator.userAgent;\n            if (ua.indexOf('MSIE') >= 0) {\n                //IE 10 and below\n                var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100);\n                if (zoom !== 100) {\n                    additionalIEZoom = zoom / 100\n                }\n            }\n        }\n        \n        if (additionalIEZoom === 1) {\n             center.y = center.y - jQuery(\"#canvasSection\").offset().top + 5;\n             center.x -= jQuery(\"#canvasSection\").offset().left;\n        \n        } else {\n             var canvasOffsetLeft = jQuery(\"#canvasSection\").offset().left;\n             var canvasScrollLeft = jQuery(\"#canvasSection\").scrollLeft();\n             var canvasScrollTop = jQuery(\"#canvasSection\").scrollTop();\n             \n             var offset = scale.e - (canvasOffsetLeft * additionalIEZoom);\n             var additionaloffset = 0;\n             if (offset > 10) {\n                 additionaloffset = (offset / additionalIEZoom) - offset;\n             }\n             center.y = center.y - (jQuery(\"#canvasSection\").offset().top * additionalIEZoom) + 5 + ((canvasScrollTop * additionalIEZoom) - canvasScrollTop);\n             center.x = center.x - (canvasOffsetLeft * additionalIEZoom) + additionaloffset + ((canvasScrollLeft * additionalIEZoom) - canvasScrollLeft);\n        }\n\t\t\n\t\n\t\treturn center;\t\t\t\n\t},\n\t\n\thide: function(e){\n\t\tif (this.shownTextField && (!e || e.target !== this.shownTextField)) {\n\t\t\tvar newValue = this.shownTextField.value;\n\t\t\tif (newValue !== this.oldValueText)\n\t\t\t{\n\t\t\t\tthis.updateValueFunction(newValue, this.oldValueText);\n\t\t\t}\n\t\t\tthis.destroy();\n\t\t}\n\t},\n\t\n\thideField: function(e){\n\t\tif (this.shownTextField) {\n\t\t\tthis.destroy();\n\t\t}\n\t},\n\t\n\tdestroy: function(e){\n\t\tvar textInputComp = jQuery(\"#shapeTextInput\");\n\t\tif( textInputComp ){\n\t\t\ttextInputComp.remove(); \n\t\t\tdelete this.shownTextField; \n\t\t\t\n\t\t\tthis.facade.enableEvent(ORYX.CONFIG.EVENT_KEYDOWN);\n\t\t}\n\t}\n});\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nif(!ORYX.Plugins)\n\tORYX.Plugins = new Object();\n\n/**\n * Supports EPCs by offering a syntax check and export and import ability..\n * \n * \n */\nORYX.Plugins.ProcessLink = Clazz.extend({\n\n\tfacade: undefined,\n\n\t/**\n\t * Offers the plugin functionality:\n\t * \n\t */\n\tconstruct: function(facade) {\n\n\t\tthis.facade = facade;\n\t\t\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_PROPERTY_CHANGED, this.propertyChanged.bind(this) );\n\t\t\n\t},\n\n\n\t/**\n\t * \n\t * @param {Object} option\n\t */\n\tpropertyChanged: function( option, node){\n\n\t\tif( option.name !== \"oryx-refuri\" || !node instanceof ORYX.Core.Node ){ return }\n\t\t\n\t\t\n\t\tif( option.value && option.value.length > 0 && option.value != \"undefined\"){\n\t\t\t\n\t\t\tthis.show( node, option.value );\n\t\t\t\t\t\n\t\t} else {\n\n\t\t\tthis.hide( node );\n\n\t\t}\t\t\t\t\n\n\t},\n\t\n\t/**\n\t * Shows the Link for a particular shape with a specific url\n\t * \n\t * @param {Object} shape\n\t * @param {Object} url\n\t */\n\tshow: function( shape, url){\n\n\t\t\n\t\t// Generate the svg-representation of a link\n\t\tvar link  = ORYX.Editor.graft(\"http://www.w3.org/2000/svg\", null ,\n\t\t\t\t\t[ 'a',\n\t\t\t\t\t\t{'target': '_blank'},\n\t\t\t\t\t\t['path', \n\t\t\t\t\t\t\t{ \"stroke-width\": 1.0, \"stroke\":\"#00DD00\", \"fill\": \"#00AA00\", \"d\":  \"M3,3 l0,-2.5 l7.5,0 l0,-2.5 l7.5,4.5 l-7.5,3.5 l0,-2.5 l-8,0\", \"line-captions\": \"round\"}\n\t\t\t\t\t\t]\n\t\t\t\t\t]);\n\n\t\tvar link  = ORYX.Editor.graft(\"http://www.w3.org/2000/svg\", null ,\t\t\n\t\t\t\t\t\t[ 'a',\n\t\t\t\t\t\t\t{'target': '_blank'},\n\t\t\t\t\t\t\t['path', { \"style\": \"fill:#92BFFC;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.72\", \"d\": \"M0 1.44 L0 15.05 L11.91 15.05 L11.91 5.98 L7.37 1.44 L0 1.44 Z\"}],\n\t\t\t\t\t\t\t['path', { \"style\": \"stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.72;fill:none;\", \"transform\": \"translate(7.5, -8.5)\", \"d\": \"M0 10.51 L0 15.05 L4.54 15.05\"}],\n\t\t\t\t\t\t\t['path', { \"style\": \"fill:#f28226;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.72\", \"transform\": \"translate(-3, -1)\", \"d\": \"M0 8.81 L0 13.06 L5.95 13.06 L5.95 15.05 A50.2313 50.2313 -175.57 0 0 10.77 11.08 A49.9128 49.9128 -1.28 0 0 5.95 6.54 L5.95 8.81 L0 8.81 Z\"}],\n\t\t\t\t\t\t]);\n\n\t/*\n\t * \n\t * \t\t\t\t\t[ 'a',\n\t\t\t\t\t\t{'target': '_blank'},\n\t\t\t\t\t\t['path', { \"style\": \"fill:none;stroke-width:0.5px; stroke:#000000\", \"d\": \"M7,4 l0,2\"}],\n\t\t\t\t\t\t['path', { \"style\": \"fill:none;stroke-width:0.5px; stroke:#000000\", \"d\": \"M4,8 l-2,0 l0,6\"}],\n\t\t\t\t\t\t['path', { \"style\": \"fill:none;stroke-width:0.5px; stroke:#000000\", \"d\": \"M10,8 l2,0 l0,6\"}],\n\t\t\t\t\t\t['rect', { \"style\": \"fill:#96ff96;stroke:#000000;stroke-width:1\", \"width\": 6, \"height\": 4, \"x\": 4, \"y\": 0}],\n\t\t\t\t\t\t['rect', { \"style\": \"fill:#ffafff;stroke:#000000;stroke-width:1\", \"width\": 6, \"height\": 4, \"x\": 4, \"y\": 6}],\n\t\t\t\t\t\t['rect', { \"style\": \"fill:#96ff96;stroke:#000000;stroke-width:1\", \"width\": 6, \"height\": 4, \"x\": 0, \"y\": 12}],\n\t\t\t\t\t\t['rect', { \"style\": \"fill:#96ff96;stroke:#000000;stroke-width:1\", \"width\": 6, \"height\": 4, \"x\": 8, \"y\": 12}],\n\t\t\t\t\t\t['rect', { \"style\": \"fill:none;stroke:none;pointer-events:all\", \"width\": 14, \"height\": 16, \"x\": 0, \"y\": 0}]\n\t\t\t\t\t]);\n\t */\n\t\t\n\t\t// Set the link with the special namespace\n\t\tlink.setAttributeNS(\"http://www.w3.org/1999/xlink\", \"xlink:href\", url);\n\t\t\n\t\t\n\t\t// Shows the link in the overlay\t\t\t\t\t\n\t\tthis.facade.raiseEvent({\n\t\t\t\t\ttype: \t\t\tORYX.CONFIG.EVENT_OVERLAY_SHOW,\n\t\t\t\t\tid: \t\t\t\"arissupport.urlref_\" + shape.id,\n\t\t\t\t\tshapes: \t\t[shape],\n\t\t\t\t\tnode:\t\t\tlink,\n\t\t\t\t\tnodePosition:\t\"SE\"\n\t\t\t\t});\t\n\t\t\t\t\t\t\t\n\t},\t\n\n\t/**\n\t * Hides the Link for a particular shape\n\t * \n\t * @param {Object} shape\n\t */\n\thide: function( shape ){\n\n\t\tthis.facade.raiseEvent({\n\t\t\t\t\ttype: \t\t\tORYX.CONFIG.EVENT_OVERLAY_HIDE,\n\t\t\t\t\tid: \t\t\t\"arissupport.urlref_\" + shape.id\n\t\t\t\t});\t\n\t\t\t\t\t\t\t\n\t}\t\t\n});/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nArray.prototype.insertFrom = function(from, to){\n\tto \t\t\t= Math.max(0, to);\n\tfrom \t\t= Math.min( Math.max(0, from), this.length-1 );\n\t\t\n\tvar el \t\t= this[from];\n\tvar old \t= this.without(el);\n\tvar newA \t= old.slice(0, to);\n\tnewA.push(el);\n\tif(old.length > to ){\n\t\tnewA \t= newA.concat(old.slice(to))\n\t};\n\treturn newA;\n}\n\nif(!ORYX.Plugins)\n\tORYX.Plugins = new Object();\n\nORYX.Plugins.Arrangement = ORYX.Plugins.AbstractPlugin.extend({\n\n\tfacade: undefined,\n\n\tconstruct: function(facade) {\n\t\tthis.facade = facade;\n\n\t\t// Z-Ordering\n\t\t/** Hide for SIGNAVIO \n\t\t\n\t\tthis.facade.offer({\n\t\t\t'name':ORYX.I18N.Arrangement.btf,\n\t\t\t'functionality': this.setZLevel.bind(this, this.setToTop),\n\t\t\t'group': ORYX.I18N.Arrangement.groupZ,\n\t\t\t'icon': ORYX.PATH + \"images/shape_move_front.png\",\n\t\t\t'description': ORYX.I18N.Arrangement.btfDesc,\n\t\t\t'index': 1,\n\t\t\t'minShape': 1});\n\t\t\t\n\t\tthis.facade.offer({\n\t\t\t'name':ORYX.I18N.Arrangement.btb,\n\t\t\t'functionality': this.setZLevel.bind(this, this.setToBack),\n\t\t\t'group': ORYX.I18N.Arrangement.groupZ,\n\t\t\t'icon': ORYX.PATH + \"images/shape_move_back.png\",\n\t\t\t'description': ORYX.I18N.Arrangement.btbDesc,\n\t\t\t'index': 2,\n\t\t\t'minShape': 1});\n\n\t\tthis.facade.offer({\n\t\t\t'name':ORYX.I18N.Arrangement.bf,\n\t\t\t'functionality': this.setZLevel.bind(this, this.setForward),\n\t\t\t'group': ORYX.I18N.Arrangement.groupZ,\n\t\t\t'icon': ORYX.PATH + \"images/shape_move_forwards.png\",\n\t\t\t'description': ORYX.I18N.Arrangement.bfDesc,\n\t\t\t'index': 3,\n\t\t\t'minShape': 1});\n\n\t\tthis.facade.offer({\n\t\t\t'name':ORYX.I18N.Arrangement.bb,\n\t\t\t'functionality': this.setZLevel.bind(this, this.setBackward),\n\t\t\t'group': ORYX.I18N.Arrangement.groupZ,\n\t\t\t'icon': ORYX.PATH + \"images/shape_move_backwards.png\",\n\t\t\t'description': ORYX.I18N.Arrangement.bbDesc,\n\t\t\t'index': 4,\n\t\t\t'minShape': 1});\n\n\t\t// Aligment\n\t\tthis.facade.offer({\n\t\t\t'name':ORYX.I18N.Arrangement.ab,\n\t\t\t'functionality': this.alignShapes.bind(this, [ORYX.CONFIG.EDITOR_ALIGN_BOTTOM]),\n\t\t\t'group': ORYX.I18N.Arrangement.groupA,\n\t\t\t'icon': ORYX.PATH + \"images/shape_align_bottom.png\",\n\t\t\t'description': ORYX.I18N.Arrangement.abDesc,\n\t\t\t'index': 1,\n\t\t\t'minShape': 2});\n\n\n\n\t\tthis.facade.offer({\n\t\t\t'name':ORYX.I18N.Arrangement.at,\n\t\t\t'functionality': this.alignShapes.bind(this, [ORYX.CONFIG.EDITOR_ALIGN_TOP]),\n\t\t\t'group': ORYX.I18N.Arrangement.groupA,\n\t\t\t'icon': ORYX.PATH + \"images/shape_align_top.png\",\n\t\t\t'description': ORYX.I18N.Arrangement.atDesc,\n\t\t\t'index': 3,\n\t\t\t'minShape': 2});\n\n\t\tthis.facade.offer({\n\t\t\t'name':ORYX.I18N.Arrangement.al,\n\t\t\t'functionality': this.alignShapes.bind(this, [ORYX.CONFIG.EDITOR_ALIGN_LEFT]),\n\t\t\t'group': ORYX.I18N.Arrangement.groupA,\n\t\t\t'icon': ORYX.PATH + \"images/shape_align_left.png\",\n\t\t\t'description': ORYX.I18N.Arrangement.alDesc,\n\t\t\t'index': 4,\n\t\t\t'minShape': 2});\n\n\t\tthis.facade.offer({\n\t\t\t'name':ORYX.I18N.Arrangement.ar,\n\t\t\t'functionality': this.alignShapes.bind(this, [ORYX.CONFIG.EDITOR_ALIGN_RIGHT]),\n\t\t\t'group': ORYX.I18N.Arrangement.groupA,\n\t\t\t'icon': ORYX.PATH + \"images/shape_align_right.png\",\n\t\t\t'description': ORYX.I18N.Arrangement.arDesc,\n\t\t\t'index': 6,\n\t\t\t'minShape': 2});\n\n\t\t**/\n\t\t\n\t\tthis.facade.offer({\n\t\t\t'name':ORYX.I18N.Arrangement.am,\n\t\t\t'functionality': this.alignShapes.bind(this, [ORYX.CONFIG.EDITOR_ALIGN_MIDDLE]),\n\t\t\t'group': ORYX.I18N.Arrangement.groupA,\n\t\t\t'icon': ORYX.PATH + \"images/shape_align_middle.png\",\n\t\t\t'description': ORYX.I18N.Arrangement.amDesc,\n\t\t\t'index': 1,\n\t\t\t'minShape': 2});\n\t\t\t\n\t\tthis.facade.offer({\n\t\t\t'name':ORYX.I18N.Arrangement.ac,\n\t\t\t'functionality': this.alignShapes.bind(this, [ORYX.CONFIG.EDITOR_ALIGN_CENTER]),\n\t\t\t'group': ORYX.I18N.Arrangement.groupA,\n\t\t\t'icon': ORYX.PATH + \"images/shape_align_center.png\",\n\t\t\t'description': ORYX.I18N.Arrangement.acDesc,\n\t\t\t'index': 2,\n\t\t\t'minShape': 2});\n\n\t\t\t\n\t\tthis.facade.offer({\n\t\t\t'name':ORYX.I18N.Arrangement.as,\n\t\t\t'functionality': this.alignShapes.bind(this, [ORYX.CONFIG.EDITOR_ALIGN_SIZE]),\n\t\t\t'group': ORYX.I18N.Arrangement.groupA,\n\t\t\t'icon': ORYX.PATH + \"images/shape_align_size.png\",\n\t\t\t'description': ORYX.I18N.Arrangement.asDesc,\n\t\t\t'index': 3,\n\t\t\t'minShape': 2});\n\t\t\t\n\n\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_ARRANGEMENT_TOP, \tthis.setZLevel.bind(this, this.setToTop)\t);\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_ARRANGEMENT_BACK, \tthis.setZLevel.bind(this, this.setToBack)\t);\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_ARRANGEMENT_FORWARD, \tthis.setZLevel.bind(this, this.setForward)\t);\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_ARRANGEMENT_BACKWARD, \tthis.setZLevel.bind(this, this.setBackward)\t);\t\t\t\t\t\t\n\n\t\n\t},\n\t\n\tonSelectionChanged: function(elemnt){\n\t\tvar selection = this.facade.getSelection();\n\t\tif (selection.length === 1 && selection[0] instanceof ORYX.Core.Edge) {\n\t\t\tthis.setToTop(selection);\n\t\t}\n\t},\n\t\n\tsetZLevel:function(callback, event){\n\t\t\t\n\t\t//Command-Pattern for dragging one docker\n\t\tvar zLevelCommand = ORYX.Core.Command.extend({\n\t\t\tconstruct: function(callback, elements, facade){\n\t\t\t\tthis.callback \t= callback;\n\t\t\t\tthis.elements \t= elements;\n\t\t\t\t// For redo, the previous elements get stored\n\t\t\t\tthis.elAndIndex\t= elements.map(function(el){ return {el:el, previous:el.parent.children[el.parent.children.indexOf(el)-1]} })\n\t\t\t\tthis.facade\t\t= facade;\n\t\t\t},\t\t\t\n\t\t\texecute: function(){\n\t\t\t\t\n\t\t\t\t// Call the defined z-order callback with the elements\n\t\t\t\tthis.callback( this.elements )\t\t\t\n\t\t\t\tthis.facade.setSelection( this.elements )\n\t\t\t},\n\t\t\trollback: function(){\n\t\t\t\t\n\t\t\t\t// Sort all elements on the index of there containment\n\t\t\t\tvar sortedEl =\tthis.elAndIndex.sortBy( function( el ) {\n\t\t\t\t\t\t\t\t\tvar value \t= el.el;\n\t\t\t\t\t\t\t\t\tvar t \t\t= $A(value.node.parentNode.childNodes);\n\t\t\t\t\t\t\t\t\treturn t.indexOf(value.node);\n\t\t\t\t\t\t\t\t}); \n\t\t\t\t\n\t\t\t\t// Every element get setted back bevor the old previous element\n\t\t\t\tfor(var i=0; i<sortedEl.length; i++){\n\t\t\t\t\tvar el\t\t\t= sortedEl[i].el;\n\t\t\t\t\tvar p \t\t\t= el.parent;\t\t\t\n\t\t\t\t\tvar oldIndex \t= p.children.indexOf(el);\n\t\t\t\t\tvar newIndex \t= p.children.indexOf(sortedEl[i].previous);\n\t\t\t\t\tnewIndex\t\t= newIndex || 0\n\t\t\t\t\tp.children \t= p.children.insertFrom(oldIndex, newIndex)\t\t\t\n\t\t\t\t\tel.node.parentNode.insertBefore(el.node, el.node.parentNode.childNodes[newIndex+1]);\n\t\t\t\t}\n\n\t\t\t\t// Reset the selection\n\t\t\t\tthis.facade.setSelection( this.elements )\n\t\t\t}\n\t\t});\n\t\n\t\t// Instanziate the dockCommand\n\t\tvar command = new zLevelCommand(callback, this.facade.getSelection(), this.facade);\n\t\tif( event.excludeCommand ){\n\t\t\tcommand.execute();\n\t\t} else {\n\t\t\tthis.facade.executeCommands( [command] );\t\n\t\t}\n\t\t\n\t},\n\n\tsetToTop: function(elements) {\n\n\t\t// Sortieren des Arrays nach dem Index des SVGKnotens im Bezug auf dem Elternknoten.\n\t\tvar tmpElem =  elements.sortBy( function(value, index) {\n\t\t\tvar t = $A(value.node.parentNode.childNodes);\n\t\t\treturn t.indexOf(value.node);\n\t\t});\n\t\t// Sortiertes Array wird nach oben verschoben.\n\t\ttmpElem.each( function(value) {\n\t\t\tvar p = value.parent;\n\t\t\tif (p.children.last() === value){\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tp.children = p.children.without( value )\n\t\t\tp.children.push(value);\n\t\t\tvalue.node.parentNode.appendChild(value.node);\t\t\t\n\t\t});\n\t},\n\n\tsetToBack: function(elements) {\n\t\t// Sortieren des Arrays nach dem Index des SVGKnotens im Bezug auf dem Elternknoten.\n\t\tvar tmpElem =  elements.sortBy( function(value, index) {\n\t\t\tvar t = $A(value.node.parentNode.childNodes);\n\t\t\treturn t.indexOf(value.node);\n\t\t});\n\n\t\ttmpElem = tmpElem.reverse();\n\n\t\t// Sortiertes Array wird nach unten verschoben.\n\t\ttmpElem.each( function(value) {\n\t\t\tvar p = value.parent\n\t\t\tp.children = p.children.without( value )\n\t\t\tp.children.unshift( value );\n\t\t\tvalue.node.parentNode.insertBefore(value.node, value.node.parentNode.firstChild);\n\t\t});\n\t\t\n\t\t\n\t},\n\n\tsetBackward: function(elements) {\n\t\t// Sortieren des Arrays nach dem Index des SVGKnotens im Bezug auf dem Elternknoten.\n\t\tvar tmpElem =  elements.sortBy( function(value, index) {\n\t\t\tvar t = $A(value.node.parentNode.childNodes);\n\t\t\treturn t.indexOf(value.node);\n\t\t});\n\n\t\t// Reverse the elements\n\t\ttmpElem = tmpElem.reverse();\n\t\t\n\t\t// Delete all Nodes who are the next Node in the nodes-Array\n\t\tvar compactElem = tmpElem.findAll(function(el) {return !tmpElem.some(function(checkedEl){ return checkedEl.node == el.node.previousSibling})});\n\t\t\n\t\t// Sortiertes Array wird nach eine Ebene nach oben verschoben.\n\t\tcompactElem.each( function(el) {\n\t\t\tif(el.node.previousSibling === null) { return; }\n\t\t\tvar p \t\t= el.parent;\t\t\t\n\t\t\tvar index \t= p.children.indexOf(el);\n\t\t\tp.children \t= p.children.insertFrom(index, index-1)\t\t\t\n\t\t\tel.node.parentNode.insertBefore(el.node, el.node.previousSibling);\n\t\t});\n\t\t\n\t\t\n\t},\n\n\tsetForward: function(elements) {\n\t\t// Sortieren des Arrays nach dem Index des SVGKnotens im Bezug auf dem Elternknoten.\n\t\tvar tmpElem =  elements.sortBy( function(value, index) {\n\t\t\tvar t = $A(value.node.parentNode.childNodes);\n\t\t\treturn t.indexOf(value.node);\n\t\t});\n\n\n\t\t// Delete all Nodes who are the next Node in the nodes-Array\n\t\tvar compactElem = tmpElem.findAll(function(el) {return !tmpElem.some(function(checkedEl){ return checkedEl.node == el.node.nextSibling})});\n\t\n\t\t\t\n\t\t// Sortiertes Array wird eine Ebene nach unten verschoben.\n\t\tcompactElem.each( function(el) {\n\t\t\tvar nextNode = el.node.nextSibling\t\t\n\t\t\tif(nextNode === null) { return; }\n\t\t\tvar index \t= el.parent.children.indexOf(el);\n\t\t\tvar p \t\t= el.parent;\n\t\t\tp.children \t= p.children.insertFrom(index, index+1)\t\t\t\n\t\t\tel.node.parentNode.insertBefore(nextNode, el.node);\n\t\t});\n\t},\n\n\n\talignShapes: function(way) {\n\n\t\tvar elements = this.facade.getSelection();\n\n\t\t// Set the elements to all Top-Level elements\n\t\telements = this.facade.getCanvas().getShapesWithSharedParent(elements);\n\t\t// Get only nodes\n\t\telements = elements.findAll(function(value) {\n\t\t\treturn (value instanceof ORYX.Core.Node)\n\t\t});\n\t\t// Delete all attached intermediate events from the array\n\t\telements = elements.findAll(function(value) {\n\t\t\tvar d = value.getIncomingShapes()\n\t\t\treturn d.length == 0 || !elements.include(d[0])\n\t\t});\n\t\tif(elements.length < 2) { return; }\n\n\t\t// get bounds of all shapes.\n\t\tvar bounds = elements[0].absoluteBounds().clone();\n\t\telements.each(function(shape) {\n\t\t        bounds.include(shape.absoluteBounds().clone());\n\t\t});\n\t\t\n\t\t// get biggest width and heigth\n\t\tvar maxWidth = 0;\n\t\tvar maxHeight = 0;\n\t\telements.each(function(shape){\n\t\t\tmaxWidth = Math.max(shape.bounds.width(), maxWidth);\n\t\t\tmaxHeight = Math.max(shape.bounds.height(), maxHeight);\n\t\t});\n\n\t\tvar commandClass = ORYX.Core.Command.extend({\n\t\t\tconstruct: function(elements, bounds, maxHeight, maxWidth, way, plugin){\n\t\t\t\tthis.elements = elements;\n\t\t\t\tthis.bounds = bounds;\n\t\t\t\tthis.maxHeight = maxHeight;\n\t\t\t\tthis.maxWidth = maxWidth;\n\t\t\t\tthis.way = way;\n\t\t\t\tthis.facade = plugin.facade;\n\t\t\t\tthis.plugin = plugin;\n\t\t\t\tthis.orgPos = [];\n\t\t\t},\n\t\t\tsetBounds: function(shape, maxSize) {\n\t\t\t\tif(!maxSize)\n\t\t\t\t\tmaxSize = {width: ORYX.CONFIG.MAXIMUM_SIZE, height: ORYX.CONFIG.MAXIMUM_SIZE};\n\n\t\t\t\tif(!shape.bounds) { throw \"Bounds not definined.\" }\n\t\t\t\t\n\t\t\t\tvar newBounds = {\n                    a: {x: shape.bounds.upperLeft().x - (this.maxWidth - shape.bounds.width())/2,\n                        y: shape.bounds.upperLeft().y - (this.maxHeight - shape.bounds.height())/2},\n                    b: {x: shape.bounds.lowerRight().x + (this.maxWidth - shape.bounds.width())/2,\n                        y: shape.bounds.lowerRight().y + (this.maxHeight - shape.bounds.height())/2}\n\t            }\n\t\t\t\t\n\t\t\t\t/* If the new width of shape exceeds the maximum width, set width value to maximum. */\n\t\t\t\tif(this.maxWidth > maxSize.width) {\n\t\t\t\t\tnewBounds.a.x = shape.bounds.upperLeft().x - \n\t\t\t\t\t\t\t\t\t(maxSize.width - shape.bounds.width())/2;\n\t\t\t\t\t\n\t\t\t\t\tnewBounds.b.x =\tshape.bounds.lowerRight().x + (maxSize.width - shape.bounds.width())/2\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t/* If the new height of shape exceeds the maximum height, set height value to maximum. */\n\t\t\t\tif(this.maxHeight > maxSize.height) {\n\t\t\t\t\tnewBounds.a.y = shape.bounds.upperLeft().y - \n\t\t\t\t\t\t\t\t\t(maxSize.height - shape.bounds.height())/2;\n\t\t\t\t\t\n\t\t\t\t\tnewBounds.b.y =\tshape.bounds.lowerRight().y + (maxSize.height - shape.bounds.height())/2\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t/* set bounds of shape */\n\t\t\t\tshape.bounds.set(newBounds);\n\t\t\t\t\n\t\t\t},\t\t\t\n\t\t\texecute: function(){\n\t\t\t\t// align each shape according to the way that was specified.\n\t\t\t\tthis.elements.each(function(shape, index) {\n\t\t\t\t\tthis.orgPos[index] = shape.bounds.upperLeft();\n\t\t\t\t\t\n\t\t\t\t\tvar relBounds = this.bounds.clone();\n\t\t\t\t\tvar newCoordinates;\n\t\t\t\t\tif (shape.parent && !(shape.parent instanceof ORYX.Core.Canvas) ) {\n\t\t\t\t\t\tvar upL = shape.parent.absoluteBounds().upperLeft();\n\t\t\t\t\t\trelBounds.moveBy(-upL.x, -upL.y);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tswitch (this.way) {\n\t\t\t\t\t\t// align the shapes in the requested way.\n\t\t\t\t\t\tcase ORYX.CONFIG.EDITOR_ALIGN_BOTTOM:\n\t\t\t                newCoordinates = {\n\t\t\t\t\t\t\t\tx: shape.bounds.upperLeft().x,\n\t\t\t\t\t\t\t\ty: relBounds.b.y - shape.bounds.height()\n\t\t\t\t\t\t\t}; break;\n\t\t\n\t\t\t\t        case ORYX.CONFIG.EDITOR_ALIGN_MIDDLE:\n\t\t\t                newCoordinates = {\n\t\t\t\t\t\t\t\tx: shape.bounds.upperLeft().x,\n\t\t\t\t\t\t\t\ty: (relBounds.a.y + relBounds.b.y - shape.bounds.height()) / 2\n\t\t\t\t\t\t\t}; break;\n\t\t\n\t\t\t\t        case ORYX.CONFIG.EDITOR_ALIGN_TOP:\n\t\t\t                newCoordinates = {\n\t\t\t\t\t\t\t\tx: shape.bounds.upperLeft().x,\n\t\t\t\t\t\t\t\ty: relBounds.a.y\n\t\t\t\t\t\t\t}; break;\n\t\t\n\t\t\t\t        case ORYX.CONFIG.EDITOR_ALIGN_LEFT:\n\t\t\t                newCoordinates = {\n\t\t\t\t\t\t\t\tx: relBounds.a.x,\n\t\t\t\t\t\t\t\ty: shape.bounds.upperLeft().y\n\t\t\t\t\t\t\t}; break;\n\t\t\n\t\t\t\t        case ORYX.CONFIG.EDITOR_ALIGN_CENTER:\n\t\t\t                newCoordinates = {\n\t\t\t\t\t\t\t\tx: (relBounds.a.x + relBounds.b.x - shape.bounds.width()) / 2,\n\t\t\t\t\t\t\t\ty: shape.bounds.upperLeft().y\n\t\t\t\t\t\t\t}; break;\n\t\t\n\t\t\t\t        case ORYX.CONFIG.EDITOR_ALIGN_RIGHT:\n\t\t\t                newCoordinates = {\n\t\t\t\t\t\t\t\tx: relBounds.b.x - shape.bounds.width(),\n\t\t\t\t\t\t\t\ty: shape.bounds.upperLeft().y\n\t\t\t\t\t\t\t}; break;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\tcase ORYX.CONFIG.EDITOR_ALIGN_SIZE:\n\t\t\t\t\t\t\tif(shape.isResizable) {\n\t\t\t\t\t\t\t\tthis.orgPos[index] = {a: shape.bounds.upperLeft(), b: shape.bounds.lowerRight()};\n\t\t\t\t\t\t\t\tthis.setBounds(shape, shape.maximumSize);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif (newCoordinates){\n\t\t\t\t\t\tvar offset =  {\n\t\t\t\t\t\t\tx: shape.bounds.upperLeft().x - newCoordinates.x,\n\t\t\t\t\t\t\ty: shape.bounds.upperLeft().y - newCoordinates.y\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Set the new position\n\t\t\t\t\t\tshape.bounds.moveTo(newCoordinates);\n\t\t\t\t\t\tthis.plugin.layoutEdges(shape, shape.getAllDockedShapes(),offset);\n\t\t\t\t\t\t//shape.update()\n\t\t\t\t\t}\t\t\t\n\t\t\t\t}.bind(this));\n\t\t\n\t\t\t\t//this.facade.getCanvas().update();\n\t\t\t\t//this.facade.updateSelection();\n\t\t\t},\n\t\t\trollback: function(){\n\t\t\t\tthis.elements.each(function(shape, index) {\n\t\t\t\t\tif (this.way == ORYX.CONFIG.EDITOR_ALIGN_SIZE) {\n\t\t\t\t\t\tif(shape.isResizable) {shape.bounds.set(this.orgPos[index]);}\n\t\t\t\t\t} else {shape.bounds.moveTo(this.orgPos[index]);}\n\t\t\t\t}.bind(this));\n\t\t\t\t\n\t\t\t\t//this.facade.getCanvas().update();\n\t\t\t\t//this.facade.updateSelection();\n\t\t\t}\n\t\t})\n\t\t\n\t\tvar command = new commandClass(elements, bounds, maxHeight, maxWidth, parseInt(way), this);\n\t\t\n\t\tthis.facade.executeCommands([command]);\t\n\t}\n});/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nif (!ORYX.Plugins) \n    ORYX.Plugins = new Object();\n\nORYX.Plugins.Save = Clazz.extend({\n\t\n    facade: undefined,\n\t\n\tprocessURI: undefined,\n\t\n\tchangeSymbol : \"*\",\n\t\n    construct: function(facade){\n\t\tthis.facade = facade;\n\t\t\n\t\tdocument.addEventListener(\"keydown\", function(e){\n\t\t\tif (e.ctrlKey&&e.keyCode === 83){\n\t\t\t\tEvent.stop(e);\n\t\t\t}\n\t\t}, false);\n\t\t\n\t\twindow.onbeforeunload = this.onUnLoad.bind(this);\n\t\t\n\t\tthis.changeDifference = 0;\n\t\t\n\t\t// Register on event for executing commands --> store all commands in a stack\t\t \n\t\t// --> Execute\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_UNDO_EXECUTE, function(){ this.changeDifference++; this.updateTitle(); }.bind(this) );\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_EXECUTE_COMMANDS, function(){ this.changeDifference++; this.updateTitle(); }.bind(this) );\n\t\t// --> Saved from other places in the editor\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_SAVED, function(){ this.changeDifference = 0; this.updateTitle(); }.bind(this) );\n\t\t\n\t\t// --> Rollback\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_UNDO_ROLLBACK, function(){ this.changeDifference--; this.updateTitle(); }.bind(this) );\n\t\t\n\t\t//TODO very critical for load time performance!!!\n\t\t//this.serializedDOM = DataManager.__persistDOM(this.facade);\n\t\t\n\t\tthis.hasChanges = this._hasChanges.bind(this);\n\t},\n\t\n\tupdateTitle: function(){\n\t\t\n\t\tvar value = window.document.title || document.getElementsByTagName(\"title\")[0].childNodes[0].nodeValue;\n\t\t\n\t\tif (this.changeDifference === 0 && value.startsWith(this.changeSymbol)){\n\t\t\twindow.document.title = value.slice(1);\n\t\t} else if (this.changeDifference !== 0 && !value.startsWith(this.changeSymbol)){\n\t\t\twindow.document.title = this.changeSymbol + \"\" + value;\n\t\t}\n\t},\n\t\n\t_hasChanges: function() {\n\t  return this.changeDifference !== 0 || (this.facade.getModelMetaData()['new'] && this.facade.getCanvas().getChildShapes().size() > 0);\n\t},\n\t\n\tonUnLoad: function(){\n\t\tif(this._hasChanges()) {\n\t\t\treturn ORYX.I18N.Save.unsavedData;\n\t\t}\t\n\t}\n});\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nif(!ORYX.Plugins) \n\tORYX.Plugins = new Object();\n\nORYX.Plugins.DragDropResize = ORYX.Plugins.AbstractPlugin.extend({\n\n\t/**\n\t *\tConstructor\n\t *\t@param {Object} Facade: The Facade of the Editor\n\t */\n\tconstruct: function(facade) {\n\t\tthis.facade = facade;\n\n\t\t// Initialize variables\n\t\tthis.currentShapes \t\t= [];\t\t\t// Current selected Shapes\n\t\t//this.pluginsData \t\t= [];\t\t\t// Available Plugins\n\t\tthis.toMoveShapes \t\t= [];\t\t\t// Shapes there will be moved\n\t\tthis.distPoints \t\t= [];\t\t\t// Distance Points for Snap on Grid\n\t\tthis.isResizing \t\t= false;\t\t// Flag: If there was currently resized\n\t\tthis.dragEnable \t\t= false;\t\t// Flag: If Dragging is enabled\n\t\tthis.dragIntialized \t= false;\t\t// Flag: If the Dragging is initialized\n\t\tthis.edgesMovable\t\t= true;\t\t\t// Flag: If an edge is docked it is not movable\n\t\tthis.offSetPosition \t= {x: 0, y: 0};\t// Offset of the Dragging\n\t\tthis.faktorXY \t\t\t= {x: 1, y: 1};\t// The Current Zoom-Faktor\n\t\tthis.containmentParentNode;\t\t\t\t// the current future parent node for the dragged shapes\n\t\tthis.isAddingAllowed \t= false;\t\t// flag, if adding current selected shapes to containmentParentNode is allowed\n\t\tthis.isAttachingAllowed = false;\t\t// flag, if attaching to the current shape is allowed\n\t\t\n\t\tthis.callbackMouseMove\t= this.handleMouseMove.bind(this);\n\t\tthis.callbackMouseUp\t= this.handleMouseUp.bind(this);\n\t\t\n\t\t// Get the SVG-Containernode \n\t\tvar containerNode = this.facade.getCanvas().getSvgContainer();\n\t\t\n\t\t// Create the Selected Rectangle in the SVG\n\t\tthis.selectedRect = new ORYX.Plugins.SelectedRect(containerNode);\n\t\t\n\t\t// Show grid line if enabled\n\t\tif (ORYX.CONFIG.SHOW_GRIDLINE) {\n\t\t\tthis.vLine = new ORYX.Plugins.GridLine(containerNode, ORYX.Plugins.GridLine.DIR_VERTICAL);\n\t\t\tthis.hLine = new ORYX.Plugins.GridLine(containerNode, ORYX.Plugins.GridLine.DIR_HORIZONTAL);\n\t\t}\n\t\t\n\t\t// Get a HTML-ContainerNode\n\t\tcontainerNode = this.facade.getCanvas().getHTMLContainer();\n\t\t\n\t\tthis.scrollNode = this.facade.getCanvas().rootNode.parentNode.parentNode;\n\t\t\n\t\t// Create the southeastern button for resizing\n\t\tthis.resizerSE = new ORYX.Plugins.Resizer(containerNode, \"southeast\", this.facade);\n\t\tthis.resizerSE.registerOnResize(this.onResize.bind(this)); // register the resize callback\n\t\tthis.resizerSE.registerOnResizeEnd(this.onResizeEnd.bind(this)); // register the resize end callback\n\t\tthis.resizerSE.registerOnResizeStart(this.onResizeStart.bind(this)); // register the resize start callback\n\t\t\n\t\t// Create the northwestern button for resizing\n\t\tthis.resizerNW = new ORYX.Plugins.Resizer(containerNode, \"northwest\", this.facade);\n\t\tthis.resizerNW.registerOnResize(this.onResize.bind(this)); // register the resize callback\n\t\tthis.resizerNW.registerOnResizeEnd(this.onResizeEnd.bind(this)); // register the resize end callback\n\t\tthis.resizerNW.registerOnResizeStart(this.onResizeStart.bind(this)); // register the resize start callback\n\t\t\n\t\t// For the Drag and Drop\n\t\t// Register on MouseDown-Event on a Shape\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_MOUSEDOWN, this.handleMouseDown.bind(this));\n\t},\n\n\t/**\n\t * On Mouse Down\n\t *\n\t */\n\thandleMouseDown: function(event, uiObj) {\n\t\t// If the selection Bounds not intialized and the uiObj is not member of current selectio\n\t\t// then return\n\t\tif(!this.dragBounds || !this.currentShapes.member(uiObj) || !this.toMoveShapes.length) {return;};\n\t\t\n\t\t// Start Dragging\n\t\tthis.dragEnable = true;\n\t\tthis.dragIntialized = true;\n\t\tthis.edgesMovable = true;\n\n\t\t// Calculate the current zoom factor\n\t\tvar a = this.facade.getCanvas().node.getScreenCTM();\n\t\tthis.faktorXY.x = a.a;\n\t\tthis.faktorXY.y = a.d;\n\t\t\n\t\tvar eventX = Event.pointerX(event);\n\t\tvar eventY = Event.pointerY(event);\n\n\t\t// Set the offset position of dragging\n\t\tvar upL = this.dragBounds.upperLeft();\n\t\tthis.offSetPosition =  {\n\t\t\tx: eventX - (upL.x * this.faktorXY.x),\n\t\t\ty: eventY - (upL.y * this.faktorXY.y)};\n\t\t\n\t\tthis.offsetScroll\t= {x:this.scrollNode.scrollLeft,y:this.scrollNode.scrollTop};\n\t\t\t\n\t\t// Register on Global Mouse-MOVE Event\n\t\tdocument.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, this.callbackMouseMove, false);\t\n\t\t// Register on Global Mouse-UP Event\n\t\tdocument.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEUP, this.callbackMouseUp, true);\t\t\t\n\n\t\treturn;\n\t},\n\n\t/**\n\t * On Key Mouse Up\n\t *\n\t */\n\thandleMouseUp: function(event) {\n\t\t\n\t\t//disable containment highlighting\n\t\tthis.facade.raiseEvent({\n\t\t\t\t\t\t\t\t\ttype:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,\n\t\t\t\t\t\t\t\t\thighlightId:\"dragdropresize.contain\"\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\n\t\tthis.facade.raiseEvent({\n\t\t\t\t\t\t\t\t\ttype:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,\n\t\t\t\t\t\t\t\t\thighlightId:\"dragdropresize.attached\"\n\t\t\t\t\t\t\t\t});\n\n\t\t// If Dragging is finished\n\t\tif(this.dragEnable) {\n\t\t\n\t\t\t// and update the current selection\n\t\t\tif(!this.dragIntialized) {\n\t\t\t\t\n\t\t\t\t// Do Method after Dragging\n\t\t\t\tthis.afterDrag();\t\n\t\t\t\t\n\t\t\t\t// Check if the Shape is allowed to dock to the other Shape\t\t\t\t\t\t\n\t\t\t\tif ( \tthis.isAttachingAllowed &&\n\t\t\t\t\t\tthis.toMoveShapes.length == 1 && this.toMoveShapes[0] instanceof ORYX.Core.Node  &&\n\t\t\t\t\t\tthis.toMoveShapes[0].dockers.length > 0) {\n\t\t\t\t\t\n\t\t\t\t\t// Get the position and the docker\t\t\t\t\t\n\t\t\t\t\tvar position \t= this.facade.eventCoordinates( event );\t\n\t\t\t\t\tvar docker \t\t= this.toMoveShapes[0].dockers[0];\n\n\n\t\t\t\n\t\t\t\t\t//Command-Pattern for dragging several Shapes\n\t\t\t\t\tvar dockCommand = ORYX.Core.Command.extend({\n\t\t\t\t\t\tconstruct: function(docker, position, newDockedShape, facade){\n\t\t\t\t\t\t\tthis.docker \t\t= docker;\n\t\t\t\t\t\t\tthis.newPosition\t= position;\n\t\t\t\t\t\t\tthis.newDockedShape = newDockedShape;\n\t\t\t\t\t\t\tthis.newParent \t\t= newDockedShape.parent || facade.getCanvas();\n\t\t\t\t\t\t\tthis.oldPosition\t= docker.parent.bounds.center();\n\t\t\t\t\t\t\tthis.oldDockedShape\t= docker.getDockedShape();\n\t\t\t\t\t\t\tthis.oldParent \t\t= docker.parent.parent || facade.getCanvas();\n\t\t\t\t\t\t\tthis.facade\t\t\t= facade;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif( this.oldDockedShape ){\n\t\t\t\t\t\t\t\tthis.oldPosition = docker.parent.absoluteBounds().center();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t},\t\t\t\n\t\t\t\t\t\texecute: function(){\n\t\t\t\t\t\t\tthis.dock( this.newDockedShape, this.newParent,  this.newPosition );\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t// Raise Event for having the docked shape on top of the other shape\n\t\t\t\t\t\t\tthis.facade.raiseEvent({type:ORYX.CONFIG.EVENT_ARRANGEMENT_TOP, excludeCommand: true})\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t},\n\t\t\t\t\t\trollback: function(){\n\t\t\t\t\t\t\tthis.dock( this.oldDockedShape, this.oldParent, this.oldPosition );\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdock:function( toDockShape, parent, pos ){\n\t\t\t\t\t\t\t// Add to the same parent Shape\n\t\t\t\t\t\t\tparent.add( this.docker.parent )\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t// Set the Docker to the new Shape\n\t\t\t\t\t\t\tthis.docker.setDockedShape( undefined );\n\t\t\t\t\t\t\tthis.docker.bounds.centerMoveTo( pos )\t\t\t\t\n\t\t\t\t\t\t\tthis.docker.setDockedShape( toDockShape );\t\n\t\t\t\t\t\t\t//this.docker.update();\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tthis.facade.setSelection( [this.docker.parent] );\t\n\t\t\t\t\t\t\tthis.facade.getCanvas().update();\n\t\t\t\t\t\t\tthis.facade.updateSelection();\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\n\t\t\t\t\t// Instanziate the dockCommand\n\t\t\t\t\tvar commands = [new dockCommand(docker, position, this.containmentParentNode, this.facade)];\n\t\t\t\t\tthis.facade.executeCommands(commands);\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t// Check if adding is allowed to the other Shape\t\n\t\t\t\t} else if( this.isAddingAllowed ) {\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t// Refresh all Shapes --> Set the new Bounds\n\t\t\t\t\tthis.refreshSelectedShapes();\n\t\t\t\t\t\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tthis.facade.updateSelection();\n\t\t\t\t\t\t\t\n\t\t\t\t//this.currentShapes.each(function(shape) {shape.update()})\n\t\t\t\t// Raise Event: Dragging is finished\n\t\t\t\tthis.facade.raiseEvent({type:ORYX.CONFIG.EVENT_DRAGDROP_END});\n\t\t\t}\t\n\n\t\t\tif (this.vLine)\n\t\t\t\tthis.vLine.hide();\n\t\t\tif (this.hLine)\n\t\t\t\tthis.hLine.hide();\n\t\t}\n\n\t\t// Disable \n\t\tthis.dragEnable = false;\t\n\t\t\n\n\t\t// UnRegister on Global Mouse-UP/-Move Event\n\t\tdocument.documentElement.removeEventListener(ORYX.CONFIG.EVENT_MOUSEUP, this.callbackMouseUp, true);\t\n\t\tdocument.documentElement.removeEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, this.callbackMouseMove, false);\t\t\t\t\n\t\t\t\n\t\treturn;\n\t},\n\n\t/**\n\t* On Key Mouse Move\n\t*\n\t*/\n\thandleMouseMove: function(event) {\n\t\t// If dragging is not enabled, go return\n\t\tif(!this.dragEnable) { return };\n\t\t// If Dragging is initialized\n\t\tif(this.dragIntialized) {\n\t\t\t// Raise Event: Drag will be started\n\t\t\tthis.facade.raiseEvent({type:ORYX.CONFIG.EVENT_DRAGDROP_START});\n\t\t\tthis.dragIntialized = false;\n\t\t\t\n\t\t\t// And hide the resizers and the highlighting\n\t\t\tthis.resizerSE.hide();\n\t\t\tthis.resizerNW.hide();\n\t\t\t\n\t\t\t// if only edges are selected, containmentParentNode must be the canvas\n\t\t\tthis._onlyEdges = this.currentShapes.all(function(currentShape) {\n\t\t\t\treturn (currentShape instanceof ORYX.Core.Edge);\n\t\t\t});\n\t\t\t\n\t\t\t// Do method before Drag\n\t\t\tthis.beforeDrag();\n\t\t\t\n\t\t\tthis._currentUnderlyingNodes = [];\n\t\t\t\n\t\t}\n\n\t\t\t\n\t\t// Calculate the new position\n\t\tvar position = {\n\t\t\tx: Event.pointerX(event) - this.offSetPosition.x,\n\t\t\ty: Event.pointerY(event) - this.offSetPosition.y}\n\n\t\tposition.x \t-= this.offsetScroll.x - this.scrollNode.scrollLeft; \n\t\tposition.y \t-= this.offsetScroll.y - this.scrollNode.scrollTop;\n\t\t\n\t\t// If not the Control-Key are pressed\n\t\tvar modifierKeyPressed = event.shiftKey || event.ctrlKey;\n\t\tif(ORYX.CONFIG.GRID_ENABLED && !modifierKeyPressed) {\n\t\t\t// Snap the current position to the nearest Snap-Point\n\t\t\tposition = this.snapToGrid(position);\n\t\t} else {\n\t\t\tif (this.vLine)\n\t\t\t\tthis.vLine.hide();\n\t\t\tif (this.hLine)\n\t\t\t\tthis.hLine.hide();\n\t\t}\n\n\t\t// Adjust the point by the zoom faktor \n\t\tposition.x /= this.faktorXY.x;\n\t\tposition.y /= this.faktorXY.y;\n\n\t\t// Set that the position is not lower than zero\n\t\tposition.x = Math.max( 0 , position.x)\n\t\tposition.y = Math.max( 0 , position.y)\n\n\t\t// Set that the position is not bigger than the canvas\n\t\tvar c = this.facade.getCanvas();\n\t\tposition.x = Math.min( c.bounds.width() - this.dragBounds.width(), \t\tposition.x)\n\t\tposition.y = Math.min( c.bounds.height() - this.dragBounds.height(), \tposition.y)\t\n\t\t\t\t\t\t\n\n\t\t// Drag this bounds\n\t\tthis.dragBounds.moveTo(position);\n\n\t\t// Update all selected shapes and the selection rectangle\n\t\t//this.refreshSelectedShapes();\n\t\tthis.resizeRectangle(this.dragBounds);\n\n\t\tthis.isAttachingAllowed = false;\n\n\t\t//check, if a node can be added to the underlying node\n\t\tvar eventCoordinates = this.facade.eventCoordinates(event);\n\t\t\n\t\tvar additionalIEZoom = 1;\n        if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) {\n            var ua = navigator.userAgent;\n            if (ua.indexOf('MSIE') >= 0) {\n                //IE 10 and below\n                var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100);\n                if (zoom !== 100) {\n                    additionalIEZoom = zoom / 100\n                }\n            }\n        }\n        \n        if (additionalIEZoom !== 1) {\n             eventCoordinates.x = eventCoordinates.x / additionalIEZoom;\n             eventCoordinates.y = eventCoordinates.y / additionalIEZoom;\n        }\n\t\t\n\t\tvar underlyingNodes = $A(this.facade.getCanvas().getAbstractShapesAtPosition(eventCoordinates));\n\t\t\n\t\tvar checkIfAttachable = this.toMoveShapes.length == 1 && this.toMoveShapes[0] instanceof ORYX.Core.Node && this.toMoveShapes[0].dockers.length > 0\n\t\tcheckIfAttachable\t= checkIfAttachable && underlyingNodes.length != 1\n\t\t\n\t\t\t\n\t\tif (!checkIfAttachable &&\n\t\t\t\tunderlyingNodes.length === this._currentUnderlyingNodes.length  &&\n\t\t\t\tunderlyingNodes.all(function(node, index){return this._currentUnderlyingNodes[index] === node}.bind(this))) {\n\t\t\t\t\t\n\t\t\treturn\n\t\t\t\n\t\t} else if(this._onlyEdges) {\n\t\t\t\n\t\t\tthis.isAddingAllowed = true;\n\t\t\tthis.containmentParentNode = this.facade.getCanvas();\n\t\t\t\n\t\t} else {\n\t\t\n\t\t\t/* Check the containment and connection rules */\n\t\t\tvar options = {\n\t\t\t\tevent : event,\n\t\t\t\tunderlyingNodes : underlyingNodes,\n\t\t\t\tcheckIfAttachable : checkIfAttachable\n\t\t\t};\n\t\t\tthis.checkRules(options);\n\t\t\t\t\t\t\t\n\t\t}\n\t\t\n\t\tthis._currentUnderlyingNodes = underlyingNodes.reverse();\n\t\t\n\t\t//visualize the containment result\n\t\tif( this.isAttachingAllowed ) {\n\t\t\t\n\t\t\tthis.facade.raiseEvent({\n\t\t\t\t\t\t\t\t\ttype: \t\t\tORYX.CONFIG.EVENT_HIGHLIGHT_SHOW,\n\t\t\t\t\t\t\t\t\thighlightId: \t\"dragdropresize.attached\",\n\t\t\t\t\t\t\t\t\telements: \t\t[this.containmentParentNode],\n\t\t\t\t\t\t\t\t\tstyle: \t\t\tORYX.CONFIG.SELECTION_HIGHLIGHT_STYLE_RECTANGLE,\n\t\t\t\t\t\t\t\t\tcolor: \t\t\tORYX.CONFIG.SELECTION_VALID_COLOR\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\n\t\t} else {\n\t\t\t\n\t\t\tthis.facade.raiseEvent({\n\t\t\t\t\t\t\t\t\ttype:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,\n\t\t\t\t\t\t\t\t\thighlightId:\"dragdropresize.attached\"\n\t\t\t\t\t\t\t\t});\n\t\t}\n\t\t\n\t\tif( !this.isAttachingAllowed ){\n\t\t\tif( this.isAddingAllowed ) {\n\n\t\t\t\tthis.facade.raiseEvent({\n\t\t\t\t\t\t\t\t\t\ttype:ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW,\n\t\t\t\t\t\t\t\t\t\thighlightId:\"dragdropresize.contain\",\n\t\t\t\t\t\t\t\t\t\telements:[this.containmentParentNode],\n\t\t\t\t\t\t\t\t\t\tcolor: ORYX.CONFIG.SELECTION_VALID_COLOR\n\t\t\t\t\t\t\t\t\t});\n\n\t\t\t} else {\n\n\t\t\t\tthis.facade.raiseEvent({\n\t\t\t\t\t\t\t\t\t\ttype:ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW,\n\t\t\t\t\t\t\t\t\t\thighlightId:\"dragdropresize.contain\",\n\t\t\t\t\t\t\t\t\t\telements:[this.containmentParentNode],\n\t\t\t\t\t\t\t\t\t\tcolor: ORYX.CONFIG.SELECTION_INVALID_COLOR\n\t\t\t\t\t\t\t\t\t});\n\n\t\t\t}\n\t\t} else {\n\t\t\tthis.facade.raiseEvent({\n\t\t\t\t\t\t\t\t\ttype:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,\n\t\t\t\t\t\t\t\t\thighlightId:\"dragdropresize.contain\"\n\t\t\t\t\t\t\t\t});\t\t\t\n\t\t}\t\n\n\t\t// Stop the Event\n\t\t//Event.stop(event);\n\t\treturn;\n\t},\n\t\n//\t/**\n//\t * Rollbacks the docked shape of an edge, if the edge is not movable.\n//\t */\n//\tredockEdges: function() {\n//\t\tthis._undockedEdgesCommand.dockers.each(function(el){\n//\t\t\tel.docker.setDockedShape(el.dockedShape);\n//\t\t\tel.docker.setReferencePoint(el.refPoint);\n//\t\t})\n//\t},\n\t\n\t/**\n\t *  Checks the containment and connection rules for the selected shapes.\n\t */\n\tcheckRules : function(options) {\n\t\tvar event = options.event;\n\t\tvar underlyingNodes = options.underlyingNodes;\n\t\tvar checkIfAttachable = options.checkIfAttachable;\n\t\tvar noEdges = options.noEdges;\n\t\t\n\t\t//get underlying node that is not the same than one of the currently selected shapes or\n\t\t// a child of one of the selected shapes with the highest z Order.\n\t\t// The result is a shape or the canvas\n\t\tthis.containmentParentNode = underlyingNodes.reverse().find((function(node) {\n\t\t\treturn (node instanceof ORYX.Core.Canvas) || \n\t\t\t\t\t(((node instanceof ORYX.Core.Node) || ((node instanceof ORYX.Core.Edge) && !noEdges)) \n\t\t\t\t\t&& (!(this.currentShapes.member(node) || \n\t\t\t\t\t\t\tthis.currentShapes.any(function(shape) {\n\t\t\t\t\t\t\t\treturn (shape.children.length > 0 && shape.getChildNodes(true).member(node));\n\t\t\t\t\t\t\t}))));\n\t\t}).bind(this));\n\t\t\t\t\t\t\t\t\n\t\tif( checkIfAttachable ){\n\t\t\t\t\n\t\t\tthis.isAttachingAllowed\t= this.facade.getRules().canConnect({\n\t\t\t\t\t\t\t\t\t\t\t\tsourceShape:\tthis.containmentParentNode, \n\t\t\t\t\t\t\t\t\t\t\t\tedgeShape:\t\tthis.toMoveShapes[0], \n\t\t\t\t\t\t\t\t\t\t\t\ttargetShape:\tthis.toMoveShapes[0]\n\t\t\t\t\t\t\t\t\t\t\t\t});\t\t\t\t\t\t\n\t\t\t\n\t\t\tif ( this.isAttachingAllowed\t) {\n\t\t\t\tvar point = this.facade.eventCoordinates(event);\n\t\t\t\tthis.isAttachingAllowed\t= this.containmentParentNode.isPointOverOffset( point.x, point.y );\n\t\t\t}\t\t\t\t\t\t\n\t\t}\n\t\t\n\t\tif( !this.isAttachingAllowed ){\n\t\t\t//check all selected shapes, if they can be added to containmentParentNode\n\t\t\tthis.isAddingAllowed = this.toMoveShapes.all((function(currentShape) {\n\t\t\t\tif(currentShape instanceof ORYX.Core.Edge ||\n\t\t\t\t\tcurrentShape instanceof ORYX.Core.Controls.Docker ||\n\t\t\t\t\tthis.containmentParentNode === currentShape.parent) {\n\t\t\t\t\treturn true;\n\t\t\t\t} else if(this.containmentParentNode !== currentShape) {\n\t\t\t\t\t\n\t\t\t\t\tif(!(this.containmentParentNode instanceof ORYX.Core.Edge) || !noEdges) {\n\t\t\t\t\t\n\t\t\t\t\t\tif(this.facade.getRules().canContain({containingShape:this.containmentParentNode,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  containedShape:currentShape})) {\t  \t\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\treturn false;\n\t\t\t}).bind(this));\t\t\t\t\n\t\t}\n\t\t\n\t\tif(!this.isAttachingAllowed && !this.isAddingAllowed && \n\t\t\t\t(this.containmentParentNode instanceof ORYX.Core.Edge)) {\n\t\t\toptions.noEdges = true;\n\t\t\toptions.underlyingNodes.reverse();\n\t\t\tthis.checkRules(options);\t\t\t\n\t\t}\n\t},\n\t\n\t/**\n\t * Redraw the selected Shapes.\n\t *\n\t */\n\trefreshSelectedShapes: function() {\n\t\t// If the selection bounds not initialized, return\n\t\tif(!this.dragBounds) {return}\n\n\t\t// Calculate the offset between the bounds and the old bounds\n\t\tvar upL = this.dragBounds.upperLeft();\n\t\tvar oldUpL = this.oldDragBounds.upperLeft();\n\t\tvar offset = {\n\t\t\tx: upL.x - oldUpL.x,\n\t\t\ty: upL.y - oldUpL.y };\n\n\t\t// Instanciate the dragCommand\n\t\tvar commands = [new ORYX.Core.Command.Move(this.toMoveShapes, offset, this.containmentParentNode, this.currentShapes, this)];\n\t\t// If the undocked edges command is setted, add this command\n\t\tif( this._undockedEdgesCommand instanceof ORYX.Core.Command ){\n\t\t\tcommands.unshift( this._undockedEdgesCommand );\n\t\t}\n\t\t// Execute the commands\t\t\t\n\t\tthis.facade.executeCommands( commands );\t\n\n\t\t// copy the bounds to the old bounds\n\t\tif( this.dragBounds )\n\t\t\tthis.oldDragBounds = this.dragBounds.clone();\n\n\t},\n\t\n\t/**\n\t * Callback for Resize\n\t *\n\t */\n\tonResize: function(bounds) {\n\t\t// If the selection bounds not initialized, return\n\t\tif(!this.dragBounds) {return}\n\t\t\n\t\tthis.dragBounds = bounds;\n\t\tthis.isResizing = true;\n\n\t\t// Update the rectangle \n\t\tthis.resizeRectangle(this.dragBounds);\n\t},\n\t\n\tonResizeStart: function() {\n\t\tthis.facade.raiseEvent({type:ORYX.CONFIG.EVENT_RESIZE_START});\n\t},\n\n\tonResizeEnd: function() {\n\t\t\n\t\tif (!(this.currentShapes instanceof Array)||this.currentShapes.length<=0) {\n\t\t\treturn;\n\t\t}\n\t\t\n\t\t// If Resizing finished, the Shapes will be resize\n\t\tif(this.isResizing) {\n\t\t\t\n\t\t\tvar commandClass = ORYX.Core.Command.extend({\n\t\t\t\tconstruct: function(shape, newBounds, plugin){\n\t\t\t\t\tthis.shape = shape;\n\t\t\t\t\tthis.oldBounds = shape.bounds.clone();\n\t\t\t\t\tthis.newBounds = newBounds;\n\t\t\t\t\tthis.plugin = plugin;\n\t\t\t\t},\t\t\t\n\t\t\t\texecute: function(){\n\t\t\t\t\tthis.shape.bounds.set(this.newBounds.a, this.newBounds.b);\n\t\t\t\t\tthis.update(this.getOffset(this.oldBounds, this.newBounds));\n\t\t\t\t\t\n\t\t\t\t},\n\t\t\t\trollback: function(){\n\t\t\t\t\tthis.shape.bounds.set(this.oldBounds.a, this.oldBounds.b);\n\t\t\t\t\tthis.update(this.getOffset(this.newBounds, this.oldBounds))\n\t\t\t\t},\n\t\t\t\t\n\t\t\t\tgetOffset:function(b1, b2){\n\t\t\t\t\treturn {\n\t\t\t\t\t\tx: b2.a.x - b1.a.x,\n\t\t\t\t\t\ty: b2.a.y - b1.a.y,\n\t\t\t\t\t\txs: b2.width()/b1.width(),\n\t\t\t\t\t\tys: b2.height()/b1.height()\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tupdate:function(offset){\n\t\t\t\t\tthis.shape.getLabels().each(function(label) {\n\t\t\t\t\t\tlabel.changed();\n\t\t\t\t\t});\n\t\t\t\t\t\n\t\t\t\t\tvar allEdges = [].concat(this.shape.getIncomingShapes())\n\t\t\t\t\t\t.concat(this.shape.getOutgoingShapes())\n\t\t\t\t\t\t// Remove all edges which are included in the selection from the list\n\t\t\t\t\t\t.findAll(function(r){ return r instanceof ORYX.Core.Edge }.bind(this))\n\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\tthis.plugin.layoutEdges(this.shape, allEdges, offset);\n\n\t\t\t\t\tthis.plugin.facade.setSelection([this.shape]);\n\t\t\t\t\tthis.plugin.facade.getCanvas().update();\n\t\t\t\t\tthis.plugin.facade.updateSelection();\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t\tvar bounds = this.dragBounds.clone();\n\t\t\tvar shape = this.currentShapes[0];\n\t\t\t\n\t\t\tif(shape.parent) {\n\t\t\t\tvar parentPosition = shape.parent.absoluteXY();\n\t\t\t\tbounds.moveBy(-parentPosition.x, -parentPosition.y);\n\t\t\t}\n\t\t\t\t\n\t\t\tvar command = new commandClass(shape, bounds, this);\n\t\t\t\n\t\t\tthis.facade.executeCommands([command]);\n\t\t\t\n\t\t\tthis.isResizing = false;\n\t\t\t\n\t\t\tthis.facade.raiseEvent({type:ORYX.CONFIG.EVENT_RESIZE_END});\n\t\t}\n\t},\n\t\n\n\t/**\n\t * Prepare the Dragging\n\t *\n\t */\n\tbeforeDrag: function(){\n\n\t\tvar undockEdgeCommand = ORYX.Core.Command.extend({\n\t\t\tconstruct: function(moveShapes){\n\t\t\t\tthis.dockers = moveShapes.collect(function(shape){ return shape instanceof ORYX.Core.Controls.Docker ? {docker:shape, dockedShape:shape.getDockedShape(), refPoint:shape.referencePoint} : undefined }).compact();\n\t\t\t},\t\t\t\n\t\t\texecute: function(){\n\t\t\t\tthis.dockers.each(function(el){\n\t\t\t\t\tel.docker.setDockedShape(undefined);\n\t\t\t\t})\n\t\t\t},\n\t\t\trollback: function(){\n\t\t\t\tthis.dockers.each(function(el){\n\t\t\t\t\tel.docker.setDockedShape(el.dockedShape);\n\t\t\t\t\tel.docker.setReferencePoint(el.refPoint);\n\t\t\t\t\t//el.docker.update();\n\t\t\t\t})\n\t\t\t}\n\t\t});\n\t\t\n\t\tthis._undockedEdgesCommand = new undockEdgeCommand( this.toMoveShapes );\n\t\tthis._undockedEdgesCommand.execute();\t\n\t\t\n\t},\n\n\thideAllLabels: function(shape) {\n\t\t\t\n\t\t\t// Hide all labels from the shape\n\t\t\tshape.getLabels().each(function(label) {\n\t\t\t\tlabel.hide();\n\t\t\t});\n\t\t\t// Hide all labels from docked shapes\n\t\t\tshape.getAllDockedShapes().each(function(dockedShape) {\n\t\t\t\tvar labels = dockedShape.getLabels();\n\t\t\t\tif(labels.length > 0) {\n\t\t\t\t\tlabels.each(function(label) {\n\t\t\t\t\t\tlabel.hide();\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// Do this recursive for all child shapes\n\t\t\t// EXP-NICO use getShapes\n\t\t\tshape.getChildren().each((function(value) {\n\t\t\t\tif(value instanceof ORYX.Core.Shape)\n\t\t\t\t\tthis.hideAllLabels(value);\n\t\t\t}).bind(this));\n\t},\n\n\t/**\n\t * Finished the Dragging\n\t *\n\t */\n\tafterDrag: function(){\n\t\t\t\t\n\t},\n\n\t/**\n\t * Show all Labels at these shape\n\t * \n\t */\n\tshowAllLabels: function(shape) {\n\n\t\t\t// Show the label of these shape\n\t\t\t//shape.getLabels().each(function(label) {\n\t\t\tfor(var i=0; i<shape.length ;i++){\n\t\t\t\tvar label = shape[i];\n\t\t\t\tlabel.show();\n\t\t\t}//);\n\t\t\t// Show all labels at docked shapes\n\t\t\t//shape.getAllDockedShapes().each(function(dockedShape) {\n\t\t\tvar allDockedShapes = shape.getAllDockedShapes()\n\t\t\tfor(var i=0; i<allDockedShapes.length ;i++){\n\t\t\t\tvar dockedShape = allDockedShapes[i];\t\t\t\t\n\t\t\t\tvar labels = dockedShape.getLabels();\n\t\t\t\tif(labels.length > 0) {\n\t\t\t\t\tlabels.each(function(label) {\n\t\t\t\t\t\tlabel.show();\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}//);\n\n\t\t\t// Do this recursive\n\t\t\t//shape.children.each((function(value) {\n\t\t\tfor(var i=0; i<shape.children.length ;i++){\n\t\t\t\tvar value = shape.children[i];\t\n\t\t\t\tif(value instanceof ORYX.Core.Shape)\n\t\t\t\t\tthis.showAllLabels(value);\n\t\t\t}//).bind(this));\n\t},\n\n\t/**\n\t * Intialize Method, if there are new Plugins\n\t *\n\t */\n\t/*registryChanged: function(pluginsData) {\n\t\t// Save all new Plugin, sorted by group and index\n\t\tthis.pluginsData = pluginsData.sortBy( function(value) {\n\t\t\treturn (value.group + \"\" + value.index);\n\t\t});\n\t},*/\n\n\t/**\n\t * On the Selection-Changed\n\t *\n\t */\n\tonSelectionChanged: function(event) {\n\t\tvar elements = event.elements;\n\t\t\n\t\t// Reset the drag-variables\n\t\tthis.dragEnable = false;\n\t\tthis.dragIntialized = false;\n\t\tthis.resizerSE.hide();\n\t\tthis.resizerNW.hide();\n\n\t\t// If there is no elements\n\t\tif(!elements || elements.length == 0) {\n\t\t\t// Hide all things and reset all variables\n\t\t\tthis.selectedRect.hide();\n\t\t\tthis.currentShapes = [];\n\t\t\tthis.toMoveShapes = [];\n\t\t\tthis.dragBounds = undefined;\n\t\t\tthis.oldDragBounds = undefined;\n\t\t} else {\n\n\t\t\t// Set the current Shapes\n\t\t\tthis.currentShapes = elements;\n\n\t\t\t// Get all shapes with the highest parent in object hierarchy (canvas is the top most parent)\n\t\t\tvar topLevelElements = this.facade.getCanvas().getShapesWithSharedParent(elements);\n\t\t\tthis.toMoveShapes = topLevelElements;\n\t\t\t\n\t\t\tthis.toMoveShapes = this.toMoveShapes.findAll( function(shape) { return shape instanceof ORYX.Core.Node && \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t(shape.dockers.length === 0 || !elements.member(shape.dockers.first().getDockedShape()))});\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\telements.each((function(shape){\n\t\t\t\tif(!(shape instanceof ORYX.Core.Edge)) {return;}\n\t\t\t\t\n\t\t\t\tvar dks = shape.getDockers();\n\t\t\t\t\t\t\t\t\n\t\t\t\tvar hasF = elements.member(dks.first().getDockedShape());\n\t\t\t\tvar hasL = elements.member(dks.last().getDockedShape());\t\n\t\t\t\t\t\t\n//\t\t\t\tif(!hasL) {\n//\t\t\t\t\tthis.toMoveShapes.push(dks.last());\n//\t\t\t\t}\n//\t\t\t\tif(!hasF){\n//\t\t\t\t\tthis.toMoveShapes.push(dks.first())\n//\t\t\t\t} \n\t\t\t\t/* Enable movement of undocked edges */\n\t\t\t\tif(!hasF && !hasL) {\n\t\t\t\t\tvar isUndocked = !dks.first().getDockedShape() && !dks.last().getDockedShape();\n\t\t\t\t\tif(isUndocked) {\n\t\t\t\t\t\tthis.toMoveShapes = this.toMoveShapes.concat(dks);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif( shape.dockers.length > 2 && hasF && hasL){\n\t\t\t\t\tthis.toMoveShapes = this.toMoveShapes.concat(dks.findAll(function(el,index){ return index > 0 && index < dks.length-1}));\n\t\t\t\t}\n\t\t\t\t\n\t\t\t}).bind(this));\n\t\t\t\n\t\t\t// Calculate the new area-bounds of the selection\n\t\t\tvar newBounds = undefined;\n\t\t\tthis.toMoveShapes.each(function(value) {\n\t\t\t\tvar shape = value;\n\t\t\t\tif(value instanceof ORYX.Core.Controls.Docker) {\n\t\t\t\t\t/* Get the Shape */\n\t\t\t\t\tshape = value.parent;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif(!newBounds){\n\t\t\t\t\tnewBounds = shape.absoluteBounds();\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tnewBounds.include(shape.absoluteBounds());\n\t\t\t\t}\n\t\t\t}.bind(this));\n\t\t\t\n\t\t\tif(!newBounds){\n\t\t\t\telements.each(function(value){\n\t\t\t\t\tif(!newBounds) {\n\t\t\t\t\t\tnewBounds = value.absoluteBounds();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnewBounds.include(value.absoluteBounds());\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\t\n\t\t\t// Set the new bounds\n\t\t\tthis.dragBounds = newBounds;\n\t\t\tthis.oldDragBounds = newBounds.clone();\n\n\t\t\t// Update and show the rectangle\n\t\t\tthis.resizeRectangle(newBounds);\n\t\t\tthis.selectedRect.show();\n\t\t\t\n\t\t\t// Show the resize button, if there is only one element and this is resizeable\n\t\t\tif(elements.length == 1 && elements[0].isResizable) {\n\t\t\t\tvar aspectRatio = elements[0].getStencil().fixedAspectRatio() ? elements[0].bounds.width() / elements[0].bounds.height() : undefined;\n\t\t\t\tthis.resizerSE.setBounds(this.dragBounds, elements[0].minimumSize, elements[0].maximumSize, aspectRatio);\n\t\t\t\tthis.resizerSE.show();\n\t\t\t\tthis.resizerNW.setBounds(this.dragBounds, elements[0].minimumSize, elements[0].maximumSize, aspectRatio);\n\t\t\t\tthis.resizerNW.show();\n\t\t\t} else {\n\t\t\t\tthis.resizerSE.setBounds(undefined);\n\t\t\t\tthis.resizerNW.setBounds(undefined);\n\t\t\t}\n\n\t\t\t// If Snap-To-Grid is enabled, the Snap-Point will be calculate\n\t\t\tif(ORYX.CONFIG.GRID_ENABLED) {\n\n\t\t\t\t// Reset all points\n\t\t\t\tthis.distPoints = [];\n\n\t\t\t\tif (this.distPointTimeout)\n\t\t\t\t\twindow.clearTimeout(this.distPointTimeout)\n\t\t\t\t\n\t\t\t\tthis.distPointTimeout = window.setTimeout(function(){\n\t\t\t\t\t// Get all the shapes, there will consider at snapping\n\t\t\t\t\t// Consider only those elements who shares the same parent element\n\t\t\t\t\tvar distShapes = this.facade.getCanvas().getChildShapes(true).findAll(function(value){\n\t\t\t\t\t\tvar parentShape = value.parent;\n\t\t\t\t\t\twhile(parentShape){\n\t\t\t\t\t\t\tif(elements.member(parentShape)) return false;\n\t\t\t\t\t\t\tparentShape = parentShape.parent\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t})\n\t\t\t\t\t\n\t\t\t\t\t// The current selection will delete from this array\n\t\t\t\t\t//elements.each(function(shape) {\n\t\t\t\t\t//\tdistShapes = distShapes.without(shape);\n\t\t\t\t\t//});\n\n\t\t\t\t\t// For all these shapes\n\t\t\t\t\tdistShapes.each((function(value) {\n\t\t\t\t\t\tif(!(value instanceof ORYX.Core.Edge)) {\n\t\t\t\t\t\t\tvar ul = value.absoluteXY();\n\t\t\t\t\t\t\tvar width = value.bounds.width();\n\t\t\t\t\t\t\tvar height = value.bounds.height();\n\n\t\t\t\t\t\t\t// Add the upperLeft, center and lowerRight - Point to the distancePoints\n\t\t\t\t\t\t\tthis.distPoints.push({\n\t\t\t\t\t\t\t\tul: {\n\t\t\t\t\t\t\t\t\tx: ul.x,\n\t\t\t\t\t\t\t\t\ty: ul.y\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tc: {\n\t\t\t\t\t\t\t\t\tx: ul.x + (width / 2),\n\t\t\t\t\t\t\t\t\ty: ul.y + (height / 2)\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tlr: {\n\t\t\t\t\t\t\t\t\tx: ul.x + width,\n\t\t\t\t\t\t\t\t\ty: ul.y + height\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}).bind(this));\n\t\t\t\t\t\n\t\t\t\t}.bind(this), 10)\n\n\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Adjust an Point to the Snap Points\n\t *\n\t */\n\tsnapToGrid: function(position) {\n\n\t\t// Get the current Bounds\n\t\tvar bounds = this.dragBounds;\n\t\t\n\t\tvar point = {};\n\n\t\tvar ulThres = 6;\n\t\tvar cThres = 10;\n\t\tvar lrThres = 6;\n\n\t\tvar scale = this.vLine ? this.vLine.getScale() : 1;\n\t\t\n\t\tvar ul = { x: (position.x/scale), y: (position.y/scale)};\n\t\tvar c = { x: (position.x/scale) + (bounds.width()/2), y: (position.y/scale) + (bounds.height()/2)};\n\t\tvar lr = { x: (position.x/scale) + (bounds.width()), y: (position.y/scale) + (bounds.height())};\n\n\t\tvar offsetX, offsetY;\n\t\tvar gridX, gridY;\n\t\t\n\t\t// For each distant point\n\t\tthis.distPoints.each(function(value) {\n\n\t\t\tvar x, y, gx, gy;\n\t\t\tif (Math.abs(value.c.x-c.x) < cThres){\n\t\t\t\tx = value.c.x-c.x;\n\t\t\t\tgx = value.c.x;\n\t\t\t}/* else if (Math.abs(value.ul.x-ul.x) < ulThres){\n\t\t\t\tx = value.ul.x-ul.x;\n\t\t\t\tgx = value.ul.x;\n\t\t\t} else if (Math.abs(value.lr.x-lr.x) < lrThres){\n\t\t\t\tx = value.lr.x-lr.x;\n\t\t\t\tgx = value.lr.x;\n\t\t\t} */\n\t\t\t\n\n\t\t\tif (Math.abs(value.c.y-c.y) < cThres){\n\t\t\t\ty = value.c.y-c.y;\n\t\t\t\tgy = value.c.y;\n\t\t\t}/* else if (Math.abs(value.ul.y-ul.y) < ulThres){\n\t\t\t\ty = value.ul.y-ul.y;\n\t\t\t\tgy = value.ul.y;\n\t\t\t} else if (Math.abs(value.lr.y-lr.y) < lrThres){\n\t\t\t\ty = value.lr.y-lr.y;\n\t\t\t\tgy = value.lr.y;\n\t\t\t} */\n\n\t\t\tif (x !== undefined) {\n\t\t\t\toffsetX = offsetX === undefined ? x : (Math.abs(x) < Math.abs(offsetX) ? x : offsetX);\n\t\t\t\tif (offsetX === x)\n\t\t\t\t\tgridX = gx;\n\t\t\t}\n\n\t\t\tif (y !== undefined) {\n\t\t\t\toffsetY = offsetY === undefined ? y : (Math.abs(y) < Math.abs(offsetY) ? y : offsetY);\n\t\t\t\tif (offsetY === y)\n\t\t\t\t\tgridY = gy;\n\t\t\t}\n\t\t});\n\t\t\n\t\t\n\t\tif (offsetX !== undefined) {\n\t\t\tul.x += offsetX;\t\n\t\t\tul.x *= scale;\n\t\t\tif (this.vLine&&gridX)\n\t\t\t\tthis.vLine.update(gridX);\n\t\t} else {\n\t\t\tul.x = (position.x - (position.x % (ORYX.CONFIG.GRID_DISTANCE/2)));\n\t\t\tif (this.vLine)\n\t\t\t\tthis.vLine.hide()\n\t\t}\n\t\t\n\t\tif (offsetY !== undefined) {\t\n\t\t\tul.y += offsetY;\n\t\t\tul.y *= scale;\n\t\t\tif (this.hLine&&gridY)\n\t\t\t\tthis.hLine.update(gridY);\n\t\t} else {\n\t\t\tul.y = (position.y - (position.y % (ORYX.CONFIG.GRID_DISTANCE/2)));\n\t\t\tif (this.hLine)\n\t\t\t\tthis.hLine.hide();\n\t\t}\n\t\t\n\t\treturn ul;\n\t},\n\t\n\tshowGridLine: function(){\n\t\t\n\t},\n\n\n\t/**\n\t * Redraw of the Rectangle of the SelectedArea\n\t * @param {Object} bounds\n\t */\n\tresizeRectangle: function(bounds) {\n\t\t// Resize the Rectangle\n\t\tthis.selectedRect.resize(bounds);\n\t}\n\n});\n\n\nORYX.Plugins.SelectedRect = Clazz.extend({\n\n\tconstruct: function(parentId) {\n\n\t\tthis.parentId = parentId;\n\n\t\tthis.node = ORYX.Editor.graft(\"http://www.w3.org/2000/svg\", $(parentId),\n\t\t\t\t\t['g']);\n\n\t\tthis.dashedArea = ORYX.Editor.graft(\"http://www.w3.org/2000/svg\", this.node,\n\t\t\t['rect', {x: 0, y: 0,\n\t\t\t\t'stroke-width': 1, stroke: '#777777', fill: 'none',\n\t\t\t\t'stroke-dasharray': '2,2',\n\t\t\t\t'pointer-events': 'none'}]);\n\n\t\tthis.hide();\n\n\t},\n\n\thide: function() {\n\t\tthis.node.setAttributeNS(null, 'display', 'none');\n\t},\n\n\tshow: function() {\n\t\tthis.node.setAttributeNS(null, 'display', '');\n\t},\n\n\tresize: function(bounds) {\n\t\tvar upL = bounds.upperLeft();\n\n\t\tvar padding = ORYX.CONFIG.SELECTED_AREA_PADDING;\n\n\t\tthis.dashedArea.setAttributeNS(null, 'width', bounds.width() + 2*padding);\n\t\tthis.dashedArea.setAttributeNS(null, 'height', bounds.height() + 2*padding);\n\t\tthis.node.setAttributeNS(null, 'transform', \"translate(\"+ (upL.x - padding) +\", \"+ (upL.y - padding) +\")\");\n\t}\n\n\n});\n\n\n\nORYX.Plugins.GridLine = Clazz.extend({\n\t\n\tconstruct: function(parentId, direction) {\n\n\t\tif (ORYX.Plugins.GridLine.DIR_HORIZONTAL !== direction && ORYX.Plugins.GridLine.DIR_VERTICAL !== direction) {\n\t\t\tdirection = ORYX.Plugins.GridLine.DIR_HORIZONTAL\n\t\t}\n\t\t\n\t\n\t\tthis.parent = $(parentId);\n\t\tthis.direction = direction;\n\t\tthis.node = ORYX.Editor.graft(\"http://www.w3.org/2000/svg\", this.parent,\n\t\t\t\t\t['g']);\n\n\t\tthis.line = ORYX.Editor.graft(\"http://www.w3.org/2000/svg\", this.node,\n\t\t\t['path', {\n\t\t\t\t'stroke-width': 1, stroke: 'silver', fill: 'none',\n\t\t\t\t'stroke-dasharray': '5,5',\n\t\t\t\t'pointer-events': 'none'}]);\n\n\t\tthis.hide();\n\n\t},\n\n\thide: function() {\n\t\tthis.node.setAttributeNS(null, 'display', 'none');\n\t},\n\n\tshow: function() {\n\t\tthis.node.setAttributeNS(null, 'display', '');\n\t},\n\n\tgetScale: function(){\n\t\ttry {\n\t\t\treturn this.parent.parentNode.transform.baseVal.getItem(0).matrix.a;\n\t\t} catch(e) {\n\t\t\treturn 1;\n\t\t}\n\t},\n\t\n\tupdate: function(pos) {\n\t\t\n\t\tif (this.direction === ORYX.Plugins.GridLine.DIR_HORIZONTAL) {\n\t\t\tvar y = pos instanceof Object ? pos.y : pos; \n\t\t\tvar cWidth = this.parent.parentNode.parentNode.width.baseVal.value/this.getScale();\n\t\t\tthis.line.setAttributeNS(null, 'd', 'M 0 '+y+ ' L '+cWidth+' '+y);\n\t\t} else {\n\t\t\tvar x = pos instanceof Object ? pos.x : pos; \n\t\t\tvar cHeight = this.parent.parentNode.parentNode.height.baseVal.value/this.getScale();\n\t\t\tthis.line.setAttributeNS(null, 'd', 'M'+x+ ' 0 L '+x+' '+cHeight);\n\t\t}\n\t\t\n\t\tthis.show();\n\t}\n\n\n});\n\nORYX.Plugins.GridLine.DIR_HORIZONTAL = \"hor\";\nORYX.Plugins.GridLine.DIR_VERTICAL = \"ver\";\n\nORYX.Plugins.Resizer = Clazz.extend({\n\n\tconstruct: function(parentId, orientation, facade) {\n\n\t\tthis.parentId \t\t= parentId;\n\t\tthis.orientation\t= orientation;\n\t\tthis.facade\t\t\t= facade;\n\t\t\n\t\tthis.node = ORYX.Editor.graft(\"http://www.w3.org/1999/xhtml\", $('canvasSection'),\n\t\t\t['div', {'class': 'resizer_'+ this.orientation, style:'left:0px; top:0px;position:absolute;'}]);\n\n\t\tthis.node.addEventListener(ORYX.CONFIG.EVENT_MOUSEDOWN, this.handleMouseDown.bind(this), true);\n\t\tdocument.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEUP, \tthis.handleMouseUp.bind(this), \t\ttrue);\n\t\tdocument.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, \tthis.handleMouseMove.bind(this), \tfalse);\n\n\t\tthis.dragEnable = false;\n\t\tthis.offSetPosition = {x: 0, y: 0};\n\t\tthis.bounds = undefined;\n\n\t\tthis.canvasNode = this.facade.getCanvas().node;\n\n\t\tthis.minSize = undefined;\n\t\tthis.maxSize = undefined;\n\t\t\n\t\tthis.aspectRatio = undefined;\n\n\t\tthis.resizeCallbacks \t\t= [];\n\t\tthis.resizeStartCallbacks \t= [];\n\t\tthis.resizeEndCallbacks \t= [];\n\t\tthis.hide();\n\t\t\n\t\t// Calculate the Offset\n\t\tthis.scrollNode = this.node.parentNode.parentNode.parentNode;\n\n\t},\n\n\thandleMouseDown: function(event) {\n\t\tthis.dragEnable = true;\n\n\t\tthis.offsetScroll\t= {x:this.scrollNode.scrollLeft,y:this.scrollNode.scrollTop};\n\t\t\t\n\t\tthis.offSetPosition =  {\n\t\t\tx: Event.pointerX(event) - this.position.x,\n\t\t\ty: Event.pointerY(event) - this.position.y};\n\t\t\n\t\tthis.resizeStartCallbacks.each((function(value) {\n\t\t\tvalue(this.bounds);\n\t\t}).bind(this));\n\n\t},\n\n\thandleMouseUp: function(event) {\n\t\tthis.dragEnable = false;\n\t\tthis.containmentParentNode = null;\n\t\tthis.resizeEndCallbacks.each((function(value) {\n\t\t\tvalue(this.bounds);\n\t\t}).bind(this));\n\t\t\t\t\n\t},\n\n\thandleMouseMove: function(event) {\n\t\tif(!this.dragEnable) { return }\n\t\t\n\t\tif(event.shiftKey || event.ctrlKey) {\n\t\t\tthis.aspectRatio = this.bounds.width() / this.bounds.height();\n\t\t} else {\n\t\t\tthis.aspectRatio = undefined;\n\t\t}\n\n\t\tvar position = {\n\t\t\tx: Event.pointerX(event) - this.offSetPosition.x,\n\t\t\ty: Event.pointerY(event) - this.offSetPosition.y};\n\n\n\t\tposition.x \t-= this.offsetScroll.x - this.scrollNode.scrollLeft; \n\t\tposition.y \t-= this.offsetScroll.y - this.scrollNode.scrollTop;\n\t\t\n\t\tposition.x  = Math.min( position.x, this.facade.getCanvas().bounds.width());\n\t\tposition.y  = Math.min( position.y, this.facade.getCanvas().bounds.height());\n\t\t\n\t\tvar offset = {\n\t\t\tx: position.x - this.position.x,\n\t\t\ty: position.y - this.position.y\n\t\t};\n\t\t\n\t\tif(this.aspectRatio) {\n\t\t\t// fixed aspect ratio\n\t\t\tnewAspectRatio = (this.bounds.width()+offset.x) / (this.bounds.height()+offset.y);\n\t\t\tif(newAspectRatio>this.aspectRatio) {\n\t\t\t\toffset.x = this.aspectRatio * (this.bounds.height()+offset.y) - this.bounds.width();\n\t\t\t} else if(newAspectRatio<this.aspectRatio) {\n\t\t\t\toffset.y = (this.bounds.width()+offset.x) / this.aspectRatio - this.bounds.height();\n\t\t\t}\n\t\t}\n\t\t\n\t\t// respect minimum and maximum sizes of stencil\n\t\tif(this.orientation===\"northwest\") {\n\t\t\t\n\t\t\tif(this.bounds.width()-offset.x > this.maxSize.width) {\n\t\t\t\toffset.x = -(this.maxSize.width - this.bounds.width());\n\t\t\t\tif(this.aspectRatio)\n\t\t\t\t\toffset.y = this.aspectRatio * offset.x;\n\t\t\t}\n\t\t\tif(this.bounds.width()-offset.x < this.minSize.width) {\n\t\t\t\toffset.x = -(this.minSize.width - this.bounds.width());\n\t\t\t\tif(this.aspectRatio)\n\t\t\t\t\toffset.y = this.aspectRatio * offset.x;\n\t\t\t}\n\t\t\tif(this.bounds.height()-offset.y > this.maxSize.height) {\n\t\t\t\toffset.y = -(this.maxSize.height - this.bounds.height());\n\t\t\t\tif(this.aspectRatio)\n\t\t\t\t\toffset.x = offset.y / this.aspectRatio;\n\t\t\t}\n\t\t\tif(this.bounds.height()-offset.y < this.minSize.height) {\n\t\t\t\toffset.y = -(this.minSize.height - this.bounds.height());\n\t\t\t\tif(this.aspectRatio)\n\t\t\t\t\toffset.x = offset.y / this.aspectRatio;\n\t\t\t}\n\t\t\t\n\t\t} else { // defaults to southeast\n\t\t\tif(this.bounds.width()+offset.x > this.maxSize.width) {\n\t\t\t\toffset.x = this.maxSize.width - this.bounds.width();\n\t\t\t\tif(this.aspectRatio)\n\t\t\t\t\toffset.y = this.aspectRatio * offset.x;\n\t\t\t}\n\t\t\tif(this.bounds.width()+offset.x < this.minSize.width) {\n\t\t\t\toffset.x = this.minSize.width - this.bounds.width();\n\t\t\t\tif(this.aspectRatio)\n\t\t\t\t\toffset.y = this.aspectRatio * offset.x;\n\t\t\t}\n\t\t\tif(this.bounds.height()+offset.y > this.maxSize.height) {\n\t\t\t\toffset.y = this.maxSize.height - this.bounds.height();\n\t\t\t\tif(this.aspectRatio)\n\t\t\t\t\toffset.x = offset.y / this.aspectRatio;\n\t\t\t}\n\t\t\tif(this.bounds.height()+offset.y < this.minSize.height) {\n\t\t\t\toffset.y = this.minSize.height - this.bounds.height();\n\t\t\t\tif(this.aspectRatio)\n\t\t\t\t\toffset.x = offset.y / this.aspectRatio;\n\t\t\t}\n\t\t}\n\n\t\tif(this.orientation===\"northwest\") {\n\t\t\tthis.bounds.extend({x:-offset.x, y:-offset.y});\n\t\t\tthis.bounds.moveBy(offset);\n\t\t} else { // defaults to southeast\n\t\t\tthis.bounds.extend(offset);\n\t\t}\n\n\t\tthis.update();\n\n\t\tthis.resizeCallbacks.each((function(value) {\n\t\t\tvalue(this.bounds);\n\t\t}).bind(this));\n\n\t\tEvent.stop(event);\n\n\t},\n\t\n\tregisterOnResizeStart: function(callback) {\n\t\tif(!this.resizeStartCallbacks.member(callback)) {\n\t\t\tthis.resizeStartCallbacks.push(callback);\n\t\t}\n\t},\n\t\n\tunregisterOnResizeStart: function(callback) {\n\t\tif(this.resizeStartCallbacks.member(callback)) {\n\t\t\tthis.resizeStartCallbacks = this.resizeStartCallbacks.without(callback);\n\t\t}\n\t},\n\n\tregisterOnResizeEnd: function(callback) {\n\t\tif(!this.resizeEndCallbacks.member(callback)) {\n\t\t\tthis.resizeEndCallbacks.push(callback);\n\t\t}\n\t},\n\t\n\tunregisterOnResizeEnd: function(callback) {\n\t\tif(this.resizeEndCallbacks.member(callback)) {\n\t\t\tthis.resizeEndCallbacks = this.resizeEndCallbacks.without(callback);\n\t\t}\n\t},\n\t\t\n\tregisterOnResize: function(callback) {\n\t\tif(!this.resizeCallbacks.member(callback)) {\n\t\t\tthis.resizeCallbacks.push(callback);\n\t\t}\n\t},\n\n\tunregisterOnResize: function(callback) {\n\t\tif(this.resizeCallbacks.member(callback)) {\n\t\t\tthis.resizeCallbacks = this.resizeCallbacks.without(callback);\n\t\t}\n\t},\n\n\thide: function() {\n\t\tthis.node.style.display = \"none\";\n\t},\n\n\tshow: function() {\n\t\tif(this.bounds)\n\t\t\tthis.node.style.display = \"\";\n\t},\n\n\tsetBounds: function(bounds, min, max, aspectRatio) {\n\t\tthis.bounds = bounds;\n\n\t\tif(!min)\n\t\t\tmin = {width: ORYX.CONFIG.MINIMUM_SIZE, height: ORYX.CONFIG.MINIMUM_SIZE};\n\n\t\tif(!max)\n\t\t\tmax = {width: ORYX.CONFIG.MAXIMUM_SIZE, height: ORYX.CONFIG.MAXIMUM_SIZE};\n\n\t\tthis.minSize = min;\n\t\tthis.maxSize = max;\n\t\t\n\t\tthis.aspectRatio = aspectRatio;\n\n\t\tthis.update();\n\t},\n\n\tupdate: function() {\n\t\tif(!this.bounds) { return; }\n\n\t\tvar upL = this.bounds.upperLeft();\n\t\t\n\t\tif(this.bounds.width() < this.minSize.width)\t{ this.bounds.set(upL.x, upL.y, upL.x + this.minSize.width, upL.y + this.bounds.height());};\n\t\tif(this.bounds.height() < this.minSize.height)\t{ this.bounds.set(upL.x, upL.y, upL.x + this.bounds.width(), upL.y + this.minSize.height);};\n\t\tif(this.bounds.width() > this.maxSize.width)\t{ this.bounds.set(upL.x, upL.y, upL.x + this.maxSize.width, upL.y + this.bounds.height());};\n\t\tif(this.bounds.height() > this.maxSize.height)\t{ this.bounds.set(upL.x, upL.y, upL.x + this.bounds.width(), upL.y + this.maxSize.height);};\n\n\t\tvar a = this.canvasNode.getScreenCTM();\n\t    \n\t\tupL.x *= a.a;\n\t\tupL.y *= a.d;\n\t\t\n\t\tvar additionalIEZoom = 1;\n        if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) {\n            var ua = navigator.userAgent;\n            if (ua.indexOf('MSIE') >= 0) {\n                //IE 10 and below\n                var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100);\n                if (zoom !== 100) {\n                    additionalIEZoom = zoom / 100\n                }\n            }\n        }\n        \n        if (additionalIEZoom === 1) {\n             upL.y = upL.y - jQuery(\"#canvasSection\").offset().top + a.f;\n             upL.x = upL.x - jQuery(\"#canvasSection\").offset().left + a.e;\n        \n        } else {\n             var canvasOffsetLeft = jQuery(\"#canvasSection\").offset().left;\n             var canvasScrollLeft = jQuery(\"#canvasSection\").scrollLeft();\n             var canvasScrollTop = jQuery(\"#canvasSection\").scrollTop();\n             \n             var offset = a.e - (canvasOffsetLeft * additionalIEZoom);\n             var additionaloffset = 0;\n             if (offset > 10) {\n                 additionaloffset = (offset / additionalIEZoom) - offset;\n             }\n             upL.y = upL.y - (jQuery(\"#canvasSection\").offset().top * additionalIEZoom) + ((canvasScrollTop * additionalIEZoom) - canvasScrollTop) + a.f;\n             upL.x = upL.x - (canvasOffsetLeft * additionalIEZoom) + additionaloffset + ((canvasScrollLeft * additionalIEZoom) - canvasScrollLeft) + a.e;\n        }\n\t\t\n\t\tif(this.orientation===\"northwest\") {\n\t\t\tupL.x -= 13;\n\t\t\tupL.y -= 13;\n\t\t} else { // defaults to southeast\n\t\t\tupL.x +=  (a.a * this.bounds.width()) + 3 ;\n\t\t\tupL.y +=  (a.d * this.bounds.height())  + 3;\n\t\t}\n\t\t\n\t\tthis.position = upL;\n\n\t\tthis.node.style.left = this.position.x + \"px\";\n\t\tthis.node.style.top = this.position.y + \"px\";\n\t}\n});\n\n\n\n/**\n * Implements a Command to move shapes\n * \n */ \nORYX.Core.Command.Move = ORYX.Core.Command.extend({\n\tconstruct: function(moveShapes, offset, parent, selectedShapes, plugin){\n\t\tthis.moveShapes = moveShapes;\n\t\tthis.selectedShapes = selectedShapes;\n\t\tthis.offset \t= offset;\n\t\tthis.plugin\t\t= plugin;\n\t\t// Defines the old/new parents for the particular shape\n\t\tthis.newParents\t= moveShapes.collect(function(t){ return parent || t.parent });\n\t\tthis.oldParents\t= moveShapes.collect(function(shape){ return shape.parent });\n\t\tthis.dockedNodes= moveShapes.findAll(function(shape){ return shape instanceof ORYX.Core.Node && shape.dockers.length == 1}).collect(function(shape){ return {docker:shape.dockers[0], dockedShape:shape.dockers[0].getDockedShape(), refPoint:shape.dockers[0].referencePoint} });\n\t},\t\t\t\n\texecute: function(){\n\t\tthis.dockAllShapes()\t\t\t\t\n\t\t// Moves by the offset\n\t\tthis.move( this.offset);\n\t\t// Addes to the new parents\n\t\tthis.addShapeToParent( this.newParents ); \n\t\t// Set the selection to the current selection\n\t\tthis.selectCurrentShapes();\n\t\tthis.plugin.facade.getCanvas().update();\n\t\tthis.plugin.facade.updateSelection();\n\t},\n\trollback: function(){\n\t\t// Moves by the inverted offset\n\t\tvar offset = { x:-this.offset.x, y:-this.offset.y };\n\t\tthis.move( offset );\n\t\t// Addes to the old parents\n\t\tthis.addShapeToParent( this.oldParents ); \n\t\tthis.dockAllShapes(true)\t\n\t\t\n\t\t// Set the selection to the current selection\n\t\tthis.selectCurrentShapes();\n\t\tthis.plugin.facade.getCanvas().update();\n\t\tthis.plugin.facade.updateSelection();\n\t\t\n\t},\n\tmove:function(offset, doLayout){\n\t\t\n\t\t// Move all Shapes by these offset\n\t\tfor(var i=0; i<this.moveShapes.length ;i++){\n\t\t\tvar value = this.moveShapes[i];\t\t\t\t\t\n\t\t\tvalue.bounds.moveBy(offset);\n\t\t\t\n\t\t\tif (value instanceof ORYX.Core.Node) {\n\t\t\t\t\n\t\t\t\t(value.dockers||[]).each(function(d){\n\t\t\t\t\td.bounds.moveBy(offset);\n\t\t\t\t})\n\t\t\t\t\n\t\t\t\t// Update all Dockers of Child shapes\n\t\t\t\t/*var childShapesNodes = value.getChildShapes(true).findAll(function(shape){ return shape instanceof ORYX.Core.Node });\t\t\t\t\t\t\t\n\t\t\t\tvar childDockedShapes = childShapesNodes.collect(function(shape){ return shape.getAllDockedShapes() }).flatten().uniq();\t\t\t\t\t\t\t\n\t\t\t\tvar childDockedEdge = childDockedShapes.findAll(function(shape){ return shape instanceof ORYX.Core.Edge });\t\t\t\t\t\t\t\n\t\t\t\tchildDockedEdge = childDockedEdge.findAll(function(shape){ return shape.getAllDockedShapes().all(function(dsh){ return childShapesNodes.include(dsh) }) });\t\t\t\t\t\t\t\n\t\t\t\tvar childDockedDockers = childDockedEdge.collect(function(shape){ return shape.dockers }).flatten();\n\t\t\t\t\n\t\t\t\tfor (var j = 0; j < childDockedDockers.length; j++) {\n\t\t\t\t\tvar docker = childDockedDockers[j];\n\t\t\t\t\tif (!docker.getDockedShape() && !this.moveShapes.include(docker)) {\n\t\t\t\t\t\t//docker.bounds.moveBy(offset);\n\t\t\t\t\t\t//docker.update();\n\t\t\t\t\t}\n\t\t\t\t}*/\n\t\t\t\t\n\t\t\t\t\n\t\t\t\tvar allEdges = [].concat(value.getIncomingShapes())\n\t\t\t\t\t.concat(value.getOutgoingShapes())\n\t\t\t\t\t// Remove all edges which are included in the selection from the list\n\t\t\t\t\t.findAll(function(r){ return\tr instanceof ORYX.Core.Edge && !this.moveShapes.any(function(d){ return d == r || (d instanceof ORYX.Core.Controls.Docker && d.parent == r)}) }.bind(this))\n\t\t\t\t\t// Remove all edges which are between the node and a node contained in the selection from the list\n\t\t\t\t\t.findAll(function(r){ return \t(r.dockers.first().getDockedShape() == value || !this.moveShapes.include(r.dockers.first().getDockedShape())) &&  \n\t\t\t\t\t\t\t\t\t\t\t\t\t(r.dockers.last().getDockedShape() == value || !this.moveShapes.include(r.dockers.last().getDockedShape()))}.bind(this))\n\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t// Layout all outgoing/incoming edges\n\t\t\t\tthis.plugin.layoutEdges(value, allEdges, offset);\n\t\t\t\t\n\t\t\t\t\n\t\t\t\tvar allSameEdges = [].concat(value.getIncomingShapes())\n\t\t\t\t\t.concat(value.getOutgoingShapes())\n\t\t\t\t\t// Remove all edges which are included in the selection from the list\n\t\t\t\t\t.findAll(function(r){ return r instanceof ORYX.Core.Edge && r.dockers.first().isDocked() && r.dockers.last().isDocked() && !this.moveShapes.include(r) && !this.moveShapes.any(function(d){ return d == r || (d instanceof ORYX.Core.Controls.Docker && d.parent == r)}) }.bind(this))\n\t\t\t\t\t// Remove all edges which are included in the selection from the list\n\t\t\t\t\t.findAll(function(r){ return this.moveShapes.indexOf(r.dockers.first().getDockedShape()) > i ||  this.moveShapes.indexOf(r.dockers.last().getDockedShape()) > i}.bind(this))\n\n\t\t\t\tfor (var j = 0; j < allSameEdges.length; j++) {\n\t\t\t\t\tfor (var k = 1; k < allSameEdges[j].dockers.length-1; k++) {\n\t\t\t\t\t\tvar docker = allSameEdges[j].dockers[k];\n\t\t\t\t\t\tif (!docker.getDockedShape() && !this.moveShapes.include(docker)) {\n\t\t\t\t\t\t\tdocker.bounds.moveBy(offset);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\t\n\t\t\t\t\n\t\t\t\t/*var i=-1;\n\t\t\t\tvar nodes = value.getChildShapes(true);\n\t\t\t\tvar allEdges = [];\n\t\t\t\twhile(++i<nodes.length){\n\t\t\t\t\tvar edges = [].concat(nodes[i].getIncomingShapes())\n\t\t\t\t\t\t.concat(nodes[i].getOutgoingShapes())\n\t\t\t\t\t\t// Remove all edges which are included in the selection from the list\n\t\t\t\t\t\t.findAll(function(r){ return r instanceof ORYX.Core.Edge && !allEdges.include(r) && r.dockers.any(function(d){ return !value.bounds.isIncluded(d.bounds.center)})})\n\t\t\t\t\tallEdges = allEdges.concat(edges);\n\t\t\t\t\tif (edges.length <= 0){ continue }\n\t\t\t\t\t//this.plugin.layoutEdges(nodes[i], edges, offset);\n\t\t\t\t}*/\n\t\t\t}\n\t\t}\n\t\t\t\t\t\t\t\t\t\t\n\t},\n\tdockAllShapes: function(shouldDocked){\n\t\t// Undock all Nodes\n\t\tfor (var i = 0; i < this.dockedNodes.length; i++) {\n\t\t\tvar docker = this.dockedNodes[i].docker;\n\t\t\t\n\t\t\tdocker.setDockedShape( shouldDocked ? this.dockedNodes[i].dockedShape : undefined )\n\t\t\tif (docker.getDockedShape()) {\n\t\t\t\tdocker.setReferencePoint(this.dockedNodes[i].refPoint);\n\t\t\t\t//docker.update();\n\t\t\t}\n\t\t}\n\t},\n\t\n\taddShapeToParent:function( parents ){\n\t\t\n\t\t// For every Shape, add this and reset the position\t\t\n\t\tfor(var i=0; i<this.moveShapes.length ;i++){\n\t\t\tvar currentShape = this.moveShapes[i];\n\t\t\tif(currentShape instanceof ORYX.Core.Node &&\n\t\t\t   currentShape.parent !== parents[i]) {\n\t\t\t\t\n\t\t\t\t// Calc the new position\n\t\t\t\tvar unul = parents[i].absoluteXY();\n\t\t\t\tvar csul = currentShape.absoluteXY();\n\t\t\t\tvar x = csul.x - unul.x;\n\t\t\t\tvar y = csul.y - unul.y;\n\n\t\t\t\t// Add the shape to the new contained shape\n\t\t\t\tparents[i].add(currentShape);\n\t\t\t\t// Add all attached shapes as well\n\t\t\t\tcurrentShape.getOutgoingShapes((function(shape) {\n\t\t\t\t\tif(shape instanceof ORYX.Core.Node && !this.moveShapes.member(shape)) {\n\t\t\t\t\t\tparents[i].add(shape);\n\t\t\t\t\t}\n\t\t\t\t}).bind(this));\n\n\t\t\t\t// Set the new position\n\t\t\t\tif(currentShape instanceof ORYX.Core.Node && currentShape.dockers.length == 1){\n\t\t\t\t\tvar b = currentShape.bounds;\n\t\t\t\t\tx += b.width()/2;y += b.height()/2\n\t\t\t\t\tcurrentShape.dockers.first().bounds.centerMoveTo(x, y);\n\t\t\t\t} else {\n\t\t\t\t\tcurrentShape.bounds.moveTo(x, y);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t} \n\t\t\t\n\t\t\t// Update the shape\n\t\t\t//currentShape.update();\n\t\t\t\n\t\t}\n\t},\n\tselectCurrentShapes:function(){\n\t\tthis.plugin.facade.setSelection( this.selectedShapes );\n\t}\n});\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nif(!ORYX.Plugins)\n\tORYX.Plugins = new Object();\n\nORYX.Plugins.DragDocker = Clazz.extend({\n\n\t/**\n\t *\tConstructor\n\t *\t@param {Object} Facade: The Facade of the Editor\n\t */\n\tconstruct: function(facade) {\n\t\tthis.facade = facade;\n\t\t\n\t\t// Set the valid and invalid color\n\t\tthis.VALIDCOLOR \t= ORYX.CONFIG.SELECTION_VALID_COLOR;\n\t\tthis.INVALIDCOLOR \t= ORYX.CONFIG.SELECTION_INVALID_COLOR;\n\t\t\n\t\t// Define Variables \n\t\tthis.shapeSelection = undefined;\n\t\tthis.docker \t\t= undefined;\n\t\tthis.dockerParent   = undefined;\n\t\tthis.dockerSource \t= undefined;\n\t\tthis.dockerTarget \t= undefined;\n\t\tthis.lastUIObj \t\t= undefined;\n\t\tthis.isStartDocker \t= undefined;\n\t\tthis.isEndDocker \t= undefined;\n\t\tthis.undockTreshold\t= 10;\n\t\tthis.initialDockerPosition = undefined;\n\t\tthis.outerDockerNotMoved = undefined;\n\t\tthis.isValid \t\t= false;\n\t\t\n\t\t// For the Drag and Drop\n\t\t// Register on MouseDown-Event on a Docker\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_MOUSEDOWN, this.handleMouseDown.bind(this));\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_DOCKERDRAG, this.handleDockerDrag.bind(this));\n\n\t\t\n\t\t// Register on over/out to show / hide a docker\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_MOUSEOVER, this.handleMouseOver.bind(this));\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_MOUSEOUT, this.handleMouseOut.bind(this));\t\t\n\t\t\n\t\t\n\t},\n\t\n\t/**\n\t * MouseOut Handler\n\t *\n\t */\n\thandleMouseOut: function(event, uiObj) {\n\t\t// If there is a Docker, hide this\n\t\tif(!this.docker && uiObj instanceof ORYX.Core.Controls.Docker) {\n\t\t\tuiObj.hide();\n\t\t} else if(!this.docker && uiObj instanceof ORYX.Core.Edge) {\n\t\t\tuiObj.dockers.each(function(docker){\n\t\t\t\tdocker.hide();\n\t\t\t});\n\t\t}\n\t},\n\n\t/**\n\t * MouseOver Handler\n\t *\n\t */\n\thandleMouseOver: function(event, uiObj) {\n\t\t// If there is a Docker, show this\t\t\n\t\tif(!this.docker && uiObj instanceof ORYX.Core.Controls.Docker) {\n\t\t\tuiObj.show();\n\t\t} else if(!this.docker && uiObj instanceof ORYX.Core.Edge) {\n\t\t\tuiObj.dockers.each(function(docker){\n\t\t\t\tdocker.show();\n\t\t\t});\n\t\t}\n\t},\n\t/**\n\t * DockerDrag Handler\n\t * delegates the uiEvent of the drag event to the mouseDown function\n\t */\n\thandleDockerDrag: function(event, uiObj) {\n\t\tthis.handleMouseDown(event.uiEvent, uiObj);\n\t},\n\t\n\t/**\n\t * MouseDown Handler\n\t *\n\t */\t\n\thandleMouseDown: function(event, uiObj) {\n\t\t// If there is a Docker\n\t\tif(uiObj instanceof ORYX.Core.Controls.Docker && uiObj.isMovable) {\n\t\t\t\n\t\t\t/* Buffering shape selection and clear selection*/\n\t\t\tthis.shapeSelection = this.facade.getSelection();\n\t\t\tthis.facade.setSelection();\n\t\t\t\n\t\t\tthis.docker = uiObj;\n\t\t\tthis.initialDockerPosition = this.docker.bounds.center();\n\t\t\tthis.outerDockerNotMoved = false;\t\t\t\n\t\t\tthis.dockerParent = uiObj.parent;\n\t\t\t\n\t\t\t// Define command arguments\n\t\t\tthis._commandArg = {docker:uiObj, dockedShape:uiObj.getDockedShape(), refPoint:uiObj.referencePoint || uiObj.bounds.center()};\n\n\t\t\t// Show the Docker\n\t\t\tthis.docker.show();\n\t\t\t\n\t\t\t// If the Dockers Parent is an Edge, \n\t\t\t//  and the Docker is either the first or last Docker of the Edge\n\t\t\tif(uiObj.parent instanceof ORYX.Core.Edge && \n\t\t\t   \t(uiObj.parent.dockers.first() == uiObj || uiObj.parent.dockers.last() == uiObj)) {\n\t\t\t\t\n\t\t\t\t// Get the Edge Source or Target\n\t\t\t\tif(uiObj.parent.dockers.first() == uiObj && uiObj.parent.dockers.last().getDockedShape()) {\n\t\t\t\t\tthis.dockerTarget = uiObj.parent.dockers.last().getDockedShape();\n\t\t\t\t} else if(uiObj.parent.dockers.last() == uiObj && uiObj.parent.dockers.first().getDockedShape()) {\n\t\t\t\t\tthis.dockerSource = uiObj.parent.dockers.first().getDockedShape();\n\t\t\t\t}\n\t\t\t\t\n\t\t\t} else {\n\t\t\t\t// If there parent is not an Edge, undefined the Source and Target\n\t\t\t\tthis.dockerSource = undefined;\n\t\t\t\tthis.dockerTarget = undefined;\t\t\t\t\n\t\t\t}\n\t\t\n\t\t\tthis.isStartDocker = this.docker.parent.dockers.first() === this.docker;\n\t\t\tthis.isEndDocker = this.docker.parent.dockers.last() === this.docker;\n\t\t\t\t\t\n\t\t\t// add to canvas while dragging\n\t\t\tthis.facade.getCanvas().add(this.docker.parent);\n\t\t\t\n\t\t\t// Hide all Labels from Docker\n\t\t\tthis.docker.parent.getLabels().each(function(label) {\n\t\t\t\tlabel.hide();\n\t\t\t});\n\t\t\t\n\t\t\tvar eventCoordinates = this.facade.eventCoordinates(event);\n\t\t\tvar additionalIEZoom = 1;\n            if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) {\n                var ua = navigator.userAgent;\n                if (ua.indexOf('MSIE') >= 0) {\n                    //IE 10 and below\n                    var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100);\n                    if (zoom !== 100) {\n                        additionalIEZoom = zoom / 100\n                    }\n                }\n            }\n            \n            if (additionalIEZoom !== 1) {\n                eventCoordinates.x = eventCoordinates.x / additionalIEZoom;\n                eventCoordinates.y = eventCoordinates.y / additionalIEZoom;\n            }\n\t\t\t\n\t\t\t// Undocked the Docker from current Shape\n\t\t\tif ((!this.isStartDocker && !this.isEndDocker) || !this.docker.isDocked()) {\n\t\t\t\t\n\t\t\t\tthis.docker.setDockedShape(undefined);\n\t\t\t\t// Set the Docker to the center of the mouse pointer\n\t\t\t\tthis.docker.bounds.centerMoveTo(eventCoordinates);\n\t\t\t\tthis.dockerParent._update();\n\t\t\t} else {\n\t\t\t\tthis.outerDockerNotMoved = true;\n\t\t\t}\n\t\t\t\n\t\t\tvar option = {movedCallback: this.dockerMoved.bind(this), upCallback: this.dockerMovedFinished.bind(this)};\n\t\t\t\n\t\t\tthis.startEventPos = eventCoordinates;\n\t\t\t\n\t\t\t// Enable the Docker for Drag'n'Drop, give the mouseMove and mouseUp-Callback with\n\t\t\tORYX.Core.UIEnableDrag(event, uiObj, option);\n\t\t}\n\t},\n\t\n\t/**\n\t * Docker MouseMove Handler\n\t *\n\t */\n\tdockerMoved: function(event) {\n\t\tthis.outerDockerNotMoved = false;\n\t\tvar snapToMagnet = undefined;\n\t\t\n\t\tif (this.docker.parent) {\n\t\t\tif (this.isStartDocker || this.isEndDocker) {\n\t\t\t\n\t\t\t\t// Get the EventPosition and all Shapes on these point\n\t\t\t\tvar evPos = this.facade.eventCoordinates(event);\n\t\t\t\t\n\t\t\t\tvar additionalIEZoom = 1;\n\t            if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) {\n\t                var ua = navigator.userAgent;\n\t                if (ua.indexOf('MSIE') >= 0) {\n\t                    //IE 10 and below\n\t                    var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100);\n\t                    if (zoom !== 100) {\n\t                        additionalIEZoom = zoom / 100\n\t                    }\n\t                }\n\t            }\n\t            \n\t            if (additionalIEZoom !== 1) {\n\t            \tevPos.x = evPos.x / additionalIEZoom;\n\t            \tevPos.y = evPos.y / additionalIEZoom;\n\t            }\n\t\t\t\t\n\t\t\t\tif(this.docker.isDocked()) {\n\t\t\t\t\t/* Only consider start/end dockers if they are moved over a treshold */\n\t\t\t\t\tvar distanceDockerPointer = \n\t\t\t\t\t\tORYX.Core.Math.getDistancePointToPoint(evPos, this.initialDockerPosition);\n\t\t\t\t\tif(distanceDockerPointer < this.undockTreshold) {\n\t\t\t\t\t\tthis.outerDockerNotMoved = true;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t/* Undock the docker */\n\t\t\t\t\tthis.docker.setDockedShape(undefined);\n\t\t\t\t\t// Set the Docker to the center of the mouse pointer\n\t\t\t\t\t//this.docker.bounds.centerMoveTo(evPos);\n\t\t\t\t\tthis.dockerParent._update();\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tvar shapes = this.facade.getCanvas().getAbstractShapesAtPosition(evPos);\n\t\t\t\t\n\t\t\t\t// Get the top level Shape on these, but not the same as Dockers parent\n\t\t\t\tvar uiObj = shapes.pop();\n\t\t\t\tif (this.docker.parent === uiObj) {\n\t\t\t\t\tuiObj = shapes.pop();\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// If the top level Shape the same as the last Shape, then return\n\t\t\t\tif (this.lastUIObj == uiObj) {\n\t\t\t\t//return;\n\t\t\t\t\n\t\t\t\t// If the top level uiObj instance of Shape and this isn't the parent of the docker \n\t\t\t\t}\n\t\t\t\telse \n\t\t\t\t\tif (uiObj instanceof ORYX.Core.Shape) {\n\t\t\t\t\t\t\n\t\t\t\t\t\t// Ask by the StencilSet if the source, the edge and the target valid connections.\n\t\t\t\t\t\tif (this.docker.parent instanceof ORYX.Core.Edge) {\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tvar highestParent = this.getHighestParentBeforeCanvas(uiObj);\n\t\t\t\t\t\t\t/* Ensure that the shape to dock is not a child shape \n\t\t\t\t\t\t\t * of the same edge.\n\t\t\t\t\t\t\t */\n\t\t\t\t\t\t\tif (highestParent instanceof ORYX.Core.Edge && this.docker.parent === highestParent) \n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tthis.isValid = false;\n\t\t\t\t\t\t\t\tthis.dockerParent._update();\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tthis.isValid = false;\n\t\t\t\t\t\t\tvar curObj = uiObj, orgObj = uiObj;\n\t\t\t\t\t\t\twhile (!this.isValid && curObj && !(curObj instanceof ORYX.Core.Canvas))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tuiObj = curObj;\n\t\t\t\t\t\t\t\tthis.isValid = this.facade.getRules().canConnect({\n\t\t\t\t\t\t\t\t\t\t\tsourceShape: this.dockerSource ? // Is there a docked source \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tthis.dockerSource : // than set this\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t(this.isStartDocker ? // if not and if the Docker is the start docker\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tuiObj : // take the last uiObj\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tundefined), // if not set it to undefined;\n\t\t\t\t\t\t\t\t\t\t\tedgeShape: this.docker.parent,\n\t\t\t\t\t\t\t\t\t\t\ttargetShape: this.dockerTarget ? // Is there a docked target \n\t\t\t\t\t\t\t\t\t\t\tthis.dockerTarget : // than set this\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t(this.isEndDocker ? // if not and if the Docker is not the start docker\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tuiObj : // take the last uiObj\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tundefined) // if not set it to undefined;\n\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tcurObj = curObj.parent;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t// Reset uiObj if no \n\t\t\t\t\t\t\t// valid parent is found\n\t\t\t\t\t\t\tif (!this.isValid){\n\t\t\t\t\t\t\t\tuiObj = orgObj;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tthis.isValid = this.facade.getRules().canConnect({\n\t\t\t\t\t\t\t\tsourceShape: uiObj,\n\t\t\t\t\t\t\t\tedgeShape: this.docker.parent,\n\t\t\t\t\t\t\t\ttargetShape: this.docker.parent\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\t// If there is a lastUIObj, hide the magnets\n\t\t\t\t\t\tif (this.lastUIObj) {\n\t\t\t\t\t\t\tthis.hideMagnets(this.lastUIObj);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\t// If there is a valid connection, show the magnets\n\t\t\t\t\t\tif (this.isValid) {\n\t\t\t\t\t\t\tthis.showMagnets(uiObj);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\t// Set the Highlight Rectangle by these value\n\t\t\t\t\t\tthis.showHighlight(uiObj, this.isValid ? this.VALIDCOLOR : this.INVALIDCOLOR);\n\t\t\t\t\t\t\n\t\t\t\t\t\t// Buffer the current Shape\n\t\t\t\t\t\tthis.lastUIObj = uiObj;\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\t// If there is no top level Shape, then hide the highligting of the last Shape\n\t\t\t\t\t\tthis.hideHighlight();\n\t\t\t\t\t\tthis.lastUIObj ? this.hideMagnets(this.lastUIObj) : null;\n\t\t\t\t\t\tthis.lastUIObj = undefined;\n\t\t\t\t\t\tthis.isValid = false;\n\t\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// Snap to the nearest Magnet\n\t\t\t\tif (this.lastUIObj && this.isValid && !(event.shiftKey || event.ctrlKey)) {\n\t\t\t\t\tsnapToMagnet = this.lastUIObj.magnets.find(function(magnet){\n\t\t\t\t\t\treturn magnet.absoluteBounds().isIncluded(evPos);\n\t\t\t\t\t});\n\t\t\t\t\t\n\t\t\t\t\tif (snapToMagnet) {\n\t\t\t\t\t\tthis.docker.bounds.centerMoveTo(snapToMagnet.absoluteCenterXY());\n\t\t\t\t\t//this.docker.update()\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// Snap to on the nearest Docker of the same parent\n\t\tif(!(event.shiftKey || event.ctrlKey) && !snapToMagnet) {\n\t\t\tvar minOffset = ORYX.CONFIG.DOCKER_SNAP_OFFSET;\n\t\t\tvar nearestX = minOffset + 1;\n\t\t\tvar nearestY = minOffset + 1;\n\t\t\t\n\t\t\tvar dockerCenter = this.docker.bounds.center();\n\t\t\t\n\t\t\tif (this.docker.parent) {\n\t\t\t\t\n\t\t\t\tthis.docker.parent.dockers.each((function(docker){\n\t\t\t\t\tif (this.docker == docker) {\n\t\t\t\t\t\treturn\n\t\t\t\t\t};\n\t\t\t\t\t\n\t\t\t\t\tvar center = docker.referencePoint ? docker.getAbsoluteReferencePoint() : docker.bounds.center();\n\t\t\t\t\t\n\t\t\t\t\tnearestX = Math.abs(nearestX) > Math.abs(center.x - dockerCenter.x) ? center.x - dockerCenter.x : nearestX;\n\t\t\t\t\tnearestY = Math.abs(nearestY) > Math.abs(center.y - dockerCenter.y) ? center.y - dockerCenter.y : nearestY;\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t}).bind(this));\n\t\t\t\t\n\t\t\t\tif (Math.abs(nearestX) < minOffset || Math.abs(nearestY) < minOffset) {\n\t\t\t\t\tnearestX = Math.abs(nearestX) < minOffset ? nearestX : 0;\n\t\t\t\t\tnearestY = Math.abs(nearestY) < minOffset ? nearestY : 0;\n\t\t\t\t\t\n\t\t\t\t\tthis.docker.bounds.centerMoveTo(dockerCenter.x + nearestX, dockerCenter.y + nearestY);\n\t\t\t\t\t//this.docker.update()\n\t\t\t\t} else {\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\tvar previous = this.docker.parent.dockers[Math.max(this.docker.parent.dockers.indexOf(this.docker)-1, 0)];\n\t\t\t\t\tvar next = this.docker.parent.dockers[Math.min(this.docker.parent.dockers.indexOf(this.docker)+1, this.docker.parent.dockers.length-1)];\n\t\t\t\t\t\n\t\t\t\t\tif (previous && next && previous !== this.docker && next !== this.docker){\n\t\t\t\t\t\tvar cp = previous.bounds.center();\n\t\t\t\t\t\tvar cn = next.bounds.center();\n\t\t\t\t\t\tvar cd = this.docker.bounds.center();\n\t\t\t\t\t\t\n\t\t\t\t\t\t// Checks if the point is on the line between previous and next\n\t\t\t\t\t\tif (ORYX.Core.Math.isPointInLine(cd.x, cd.y, cp.x, cp.y, cn.x, cn.y, 10)) {\n\t\t\t\t\t\t\t// Get the rise\n\t\t\t\t\t\t\tvar raise = (Number(cn.y)-Number(cp.y))/(Number(cn.x)-Number(cp.x));\n\t\t\t\t\t\t\t// Calculate the intersection point\n\t\t\t\t\t\t\tvar intersecX = ((cp.y-(cp.x*raise))-(cd.y-(cd.x*(-Math.pow(raise,-1)))))/((-Math.pow(raise,-1))-raise);\n\t\t\t\t\t\t\tvar intersecY = (cp.y-(cp.x*raise))+(raise*intersecX);\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif(isNaN(intersecX) || isNaN(intersecY)) {return;}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tthis.docker.bounds.centerMoveTo(intersecX, intersecY);\n\t\t\t\t\t\t}\n\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\t//this.facade.getCanvas().update();\n\t\tthis.dockerParent._update();\n\t},\n\n\t/**\n\t * Docker MouseUp Handler\n\t *\n\t */\n\tdockerMovedFinished: function(event) {\n\t\t\n\t\t/* Reset to buffered shape selection */\n\t\tthis.facade.setSelection(this.shapeSelection);\n\t\t\n\t\t// Hide the border\n\t\tthis.hideHighlight();\n\t\t\n\t\t// Show all Labels from Docker\n\t\tthis.dockerParent.getLabels().each(function(label){\n\t\t\tlabel.show();\n\t\t\t//label.update();\n\t\t});\n\t\n\t\t// If there is a last top level Shape\n\t\tif(this.lastUIObj && (this.isStartDocker || this.isEndDocker)){\t\t\t\t\n\t\t\t// If there is a valid connection, the set as a docked Shape to them\n\t\t\tif(this.isValid) {\n\t\t\t\t\n\t\t\t\tthis.docker.setDockedShape(this.lastUIObj);\t\n\t\t\t\t\n\t\t\t\tthis.facade.raiseEvent({\n\t\t\t\t\ttype \t:ORYX.CONFIG.EVENT_DRAGDOCKER_DOCKED, \n\t\t\t\t\tdocker\t: this.docker,\n\t\t\t\t\tparent\t: this.docker.parent,\n\t\t\t\t\ttarget\t: this.lastUIObj\n\t\t\t\t});\n\t\t\t}\n\t\t\t\n\t\t\tthis.hideMagnets(this.lastUIObj);\n\t\t}\n\t\t\n\t\t// Hide the Docker\n\t\tthis.docker.hide();\n\t\t\n\t\tif(this.outerDockerNotMoved) {\n\t\t\t// Get the EventPosition and all Shapes on these point\n\t\t\tvar evPos = this.facade.eventCoordinates(event);\n\t\t\tvar shapes = this.facade.getCanvas().getAbstractShapesAtPosition(evPos);\n\t\t\t\n\t\t\t/* Remove edges from selection */\n\t\t\tvar shapeWithoutEdges = shapes.findAll(function(node) {\n\t\t\t\treturn node instanceof ORYX.Core.Node;\n\t\t\t});\n\t\t\tshapes = shapeWithoutEdges.length ? shapeWithoutEdges : shapes;\n\t\t\tthis.facade.setSelection(shapes);\n\t\t} else {\n\t\t\t//Command-Pattern for dragging one docker\n\t\t\tvar dragDockerCommand = ORYX.Core.Command.extend({\n\t\t\t\tconstruct: function(docker, newPos, oldPos, newDockedShape, oldDockedShape, facade){\n\t\t\t\t\tthis.docker \t\t= docker;\n\t\t\t\t\tthis.index\t\t\t= docker.parent.dockers.indexOf(docker);\n\t\t\t\t\tthis.newPosition\t= newPos;\n\t\t\t\t\tthis.newDockedShape = newDockedShape;\n\t\t\t\t\tthis.oldPosition\t= oldPos;\n\t\t\t\t\tthis.oldDockedShape\t= oldDockedShape;\n\t\t\t\t\tthis.facade\t\t\t= facade;\n\t\t\t\t\tthis.index\t\t\t= docker.parent.dockers.indexOf(docker);\n\t\t\t\t\tthis.shape\t\t\t= docker.parent;\n\t\t\t\t\t\n\t\t\t\t},\t\t\t\n\t\t\t\texecute: function(){\n\t\t\t\t\tif (!this.docker.parent){\n\t\t\t\t\t\tthis.docker = this.shape.dockers[this.index];\n\t\t\t\t\t}\n\t\t\t\t\tthis.dock( this.newDockedShape, this.newPosition );\n\t\t\t\t\tthis.removedDockers = this.shape.removeUnusedDockers();\n\t\t\t\t\tthis.facade.updateSelection();\n\t\t\t\t},\n\t\t\t\trollback: function(){\n\t\t\t\t\tthis.dock( this.oldDockedShape, this.oldPosition );\n\t\t\t\t\t(this.removedDockers||$H({})).each(function(d){\n\t\t\t\t\t\tthis.shape.add(d.value, Number(d.key));\n\t\t\t\t\t\tthis.shape._update(true);\n\t\t\t\t\t}.bind(this));\n\t\t\t\t\tthis.facade.updateSelection();\n\t\t\t\t},\n\t\t\t\tdock:function( toDockShape, pos ){\t\t\t\n\t\t\t\t\t// Set the Docker to the new Shape\n\t\t\t\t\tthis.docker.setDockedShape( undefined );\n\t\t\t\t\tif( toDockShape ){\t\t\t\n\t\t\t\t\t\tthis.docker.setDockedShape( toDockShape );\t\n\t\t\t\t\t\tthis.docker.setReferencePoint( pos );\n\t\t\t\t\t\t//this.docker.update();\t\n\t\t\t\t\t\t//this.docker.parent._update();\t\t\t\t\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.docker.bounds.centerMoveTo( pos );\n\t\t\t\t\t}\n\t\n\t\t\t\t\tthis.facade.getCanvas().update();\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t\t\n\t\t\tif (this.docker.parent){\n\t\t\t\t// Instanziate the dockCommand\n\t\t\t\tvar command = new dragDockerCommand(this.docker, this.docker.getDockedShape() ? this.docker.referencePoint : this.docker.bounds.center(), this._commandArg.refPoint, this.docker.getDockedShape(), this._commandArg.dockedShape, this.facade);\n\t\t\t\tthis.facade.executeCommands( [command] );\t\n\t\t\t}\n\t\t}\n\t\n\t\t// Update all Shapes\n\t\t//this.facade.updateSelection();\n\t\t\t\n\t\t// Undefined all variables\n\t\tthis.docker \t\t= undefined;\n\t\tthis.dockerParent   = undefined;\n\t\tthis.dockerSource \t= undefined;\n\t\tthis.dockerTarget \t= undefined;\t\n\t\tthis.lastUIObj \t\t= undefined;\t\t\n\t},\n\t\n\t/**\n\t * Hide the highlighting\n\t */\n\thideHighlight: function() {\n\t\tthis.facade.raiseEvent({type:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE, highlightId:'validDockedShape'});\n\t},\n\n\t/**\n\t * Show the highlighting\n\t *\n\t */\n\tshowHighlight: function(uiObj, color) {\n\t\t\n\t\tthis.facade.raiseEvent({\n\t\t\t\t\t\t\t\t\t\ttype:\t\tORYX.CONFIG.EVENT_HIGHLIGHT_SHOW, \n\t\t\t\t\t\t\t\t\t\thighlightId:'validDockedShape',\n\t\t\t\t\t\t\t\t\t\telements:\t[uiObj],\n\t\t\t\t\t\t\t\t\t\tcolor:\t\tcolor\n\t\t\t\t\t\t\t\t\t});\n\t},\n\t\n\tshowMagnets: function(uiObj){\n\t\tuiObj.magnets.each(function(magnet) {\n\t\t\tmagnet.show();\n\t\t});\n\t},\n\t\n\thideMagnets: function(uiObj){\n\t\tuiObj.magnets.each(function(magnet) {\n\t\t\tmagnet.hide();\n\t\t});\n\t},\n\t\n\tgetHighestParentBeforeCanvas: function(shape) {\n\t\tif(!(shape instanceof ORYX.Core.Shape)) {return undefined;}\n\t\t\n\t\tvar parent = shape.parent;\n\t\twhile(parent && !(parent.parent instanceof ORYX.Core.Canvas)) {\n\t\t\tparent = parent.parent;\n\t\t}\t\n\t\t\n\t\treturn parent;\t\t\n\t}\t\n\n});\n\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nif(!ORYX.Plugins)\n\tORYX.Plugins = new Object();\n\nORYX.Plugins.AddDocker = Clazz.extend({\n\n\t/**\n\t *\tConstructor\n\t *\t@param {Object} Facade: The Facade of the Editor\n\t */\n\tconstruct: function(facade) {\n\t\tthis.facade = facade;\n\t\tthis.enableAdd = false;\n\t\tthis.enableRemove = false;\n\t\t\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_MOUSEDOWN, this.handleMouseDown.bind(this));\n\t},\n\t\n\tsetEnableAdd: function(enable){\n\t\tthis.enableAdd = enable;\n\t\t\n\t\tif(this.enableAdd) {\n    \t\tjQuery(\"#add-bendpoint-button\").addClass('pressed');\n    \t} else {\n    \t\tjQuery(\"#add-bendpoint-button\").removeClass('pressed');\n    \t\tjQuery(\"#add-bendpoint-button\").blur();\n    \t}\n\t},\n\tsetEnableRemove: function(enable){\n\t\tthis.enableRemove = enable;\n\t\t\n\t\tif(this.enableRemove) {\n    \t\tjQuery(\"#remove-bendpoint-button\").addClass('pressed');\n    \t} else {\n    \t\tjQuery(\"#remove-bendpoint-button\").removeClass('pressed');\n    \t\tjQuery(\"#remove-bendpoint-button\").blur();\n    \t}\n\t},\n\t\n    enabledAdd: function(enable){\n        return this.enableAdd;\n    },\n    enabledRemove: function(){\n        return this.enableRemove;\n    },\n\t\n\t/**\n\t * MouseDown Handler\n\t *\n\t */\t\n\thandleMouseDown: function(event, uiObj) {\n\t\tif (this.enabledAdd() && uiObj instanceof ORYX.Core.Edge) {\n            this.newDockerCommand({\n                edge: uiObj,\n                position: this.facade.eventCoordinates(event)\n            });\n            this.setEnableAdd(false);\n            \n\t\t} else if (this.enabledRemove() &&\n\t\t\t\t   uiObj instanceof ORYX.Core.Controls.Docker &&\n\t\t\t\t   uiObj.parent instanceof ORYX.Core.Edge) {\n            this.newDockerCommand({\n                edge: uiObj.parent,\n                docker: uiObj\n            });\n            this.setEnableRemove(false);\n        }\n\t\tdocument.body.style.cursor = 'default';\n\t},\n    \n    // Options: edge (required), position (required if add), docker (required if delete)\n    newDockerCommand: function(options){\n        if(!options.edge)\n            return;\n\n        var commandClass = ORYX.Core.Command.extend({\n            construct: function(addEnabled, deleteEnabled, edge, docker, pos, facade){\n                this.addEnabled = addEnabled;\n                this.deleteEnabled = deleteEnabled;\n                this.edge = edge;\n                this.docker = docker;\n                this.pos = pos;\n                this.facade = facade;\n            },\n            execute: function(){\n                if (this.addEnabled) {\n\t\t\t\t\tif (!this.docker){\n                    \tthis.docker = this.edge.addDocker(this.pos);\n\t\t\t\t\t\tthis.index = this.edge.dockers.indexOf(this.docker);\n\t\t\t\t\t} else {\n                    \tthis.edge.add(this.docker, this.index);\n\t\t\t\t\t}\n                }\n                else if (this.deleteEnabled) {\n\t\t\t\t\tthis.index = this.edge.dockers.indexOf(this.docker);\n                    this.pos = this.docker.bounds.center();\n                    this.edge.removeDocker(this.docker);\n                }\n                this.edge.getLabels().invoke(\"show\");\n                this.facade.getCanvas().update();\n                this.facade.updateSelection();\n            },\n            rollback: function(){\n                if (this.addEnabled) {\n                    if (this.docker instanceof ORYX.Core.Controls.Docker) {\n                        this.edge.removeDocker(this.docker);\n                    }\n                }\n                else if (this.deleteEnabled) {\n                    this.edge.add(this.docker, this.index);\n                }\n                this.edge.getLabels().invoke(\"show\");\n                this.facade.getCanvas().update();\n                this.facade.updateSelection();\n            }\n        })\n        \n        var command = new commandClass(this.enabledAdd(), this.enabledRemove(), options.edge, options.docker, options.position, this.facade);\n        \n        this.facade.executeCommands([command]);\n    }\n});\n\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nif(!ORYX.Plugins)\n\tORYX.Plugins = new Object();\n\n ORYX.Plugins.SelectionFrame = Clazz.extend({\n\n\tconstruct: function(facade) {\n\t\tthis.facade = facade;\n\n\t\t// Register on MouseEvents\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_MOUSEDOWN, this.handleMouseDown.bind(this));\n\t\tdocument.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEUP, this.handleMouseUp.bind(this), true);\n\n\t\t// Some initiale variables\n\t\tthis.position \t\t= {x:0, y:0};\n\t\tthis.size \t\t\t= {width:0, height:0};\n\t\tthis.offsetPosition = {x: 0, y: 0};\n\n\t\t// (Un)Register Mouse-Move Event\n\t\tthis.moveCallback \t= undefined;\n\t\tthis.offsetScroll\t= {x:0,y:0};\n\t\t// HTML-Node of Selection-Frame\n\t\tthis.node = ORYX.Editor.graft(\"http://www.w3.org/1999/xhtml\", $('canvasSection'),\n\t\t\t['div', {'class':'Oryx_SelectionFrame'}]);\n\n\t\tthis.hide();\n\t},\n\n\thandleMouseDown: function(event, uiObj) {\n\t\t// If there is the Canvas\n\t\tif( uiObj instanceof ORYX.Core.Canvas ) {\n\t\t\t// Calculate the Offset\n\t\t\tvar scrollNode = uiObj.rootNode.parentNode.parentNode;\n\t\t\t\t\t\t\n\t\t\tvar a = this.facade.getCanvas().node.getScreenCTM();\n\t\t\tthis.offsetPosition = {\n\t\t\t\tx: a.e,\n\t\t\t\ty: a.f\n\t\t\t};\n\n\t\t\t// Set the new Position\n\t\t\tthis.setPos({\n\t\t\t    x: Event.pointerX(event) - jQuery(\"#canvasSection\").offset().left, \n\t\t\t\ty: Event.pointerY(event) - jQuery(\"#canvasSection\").offset().top + 5\n\t\t\t});\n\t\t\t\n\t\t\t// Reset the size\n\t\t\tthis.resize({width:0, height:0});\n\t\t\tthis.moveCallback = this.handleMouseMove.bind(this);\n\t\t\n\t\t\t// Register Mouse-Move Event\n\t\t\tdocument.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, this.moveCallback, false);\n\n\t\t\tthis.offsetScroll\t\t= {x:scrollNode.scrollLeft,y:scrollNode.scrollTop};\n\t\t\t\n\t\t\t// Show the Frame\n\t\t\tthis.show();\n\t\t}\n\n\t\tEvent.stop(event);\n\t},\n\n\thandleMouseUp: function(event) {\n\t\t// If there was an MouseMoving\n\t\tif(this.moveCallback) {\n\t\t\t// Hide the Frame\n\t\t\tthis.hide();\n\n\t\t\t// Unregister Mouse-Move\n\t\t\tdocument.documentElement.removeEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, this.moveCallback, false);\t\t\t\n\t\t\n\t\t\tthis.moveCallback = undefined;\n\n\t\t\tvar corrSVG = this.facade.getCanvas().node.getScreenCTM();\n\n\t\t\t// Calculate the positions of the Frame\n\t\t\tvar a = {\n\t\t\t\tx: this.size.width > 0 ? this.position.x : this.position.x + this.size.width,\n\t\t\t\ty: this.size.height > 0 ? this.position.y : this.position.y + this.size.height\n\t\t\t};\n\n\t\t\tvar b = {\n\t\t\t\tx: a.x + Math.abs(this.size.width),\n\t\t\t\ty: a.y + Math.abs(this.size.height)\n\t\t\t};\n\t\t\t\n\t\t\tvar additionalIEZoom = 1;\n            if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) {\n                var ua = navigator.userAgent;\n                if (ua.indexOf('MSIE') >= 0) {\n                    //IE 10 and below\n                    var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100);\n                    if (zoom !== 100) {\n                        additionalIEZoom = zoom / 100\n                    }\n                }\n            }\n            \n            if (additionalIEZoom === 1) {\n                a.x = a.x - (corrSVG.e - jQuery(\"#canvasSection\").offset().left);\n                a.y = a.y - (corrSVG.f - jQuery(\"#canvasSection\").offset().top);\n                b.x = b.x - (corrSVG.e - jQuery(\"#canvasSection\").offset().left);\n                b.y = b.y - (corrSVG.f - jQuery(\"#canvasSection\").offset().top);\n            \n            } else {\n                 var canvasOffsetLeft = jQuery(\"#canvasSection\").offset().left;\n                 var canvasScrollLeft = jQuery(\"#canvasSection\").scrollLeft();\n                 var canvasScrollTop = jQuery(\"#canvasSection\").scrollTop();\n                 \n                 var offset = a.e - (canvasOffsetLeft * additionalIEZoom);\n                 var additionaloffset = 0;\n                 if (offset > 10) {\n                     additionaloffset = (offset / additionalIEZoom) - offset;\n                 }\n                 \n                 a.x = a.x - (corrSVG.e - (canvasOffsetLeft * additionalIEZoom) + additionaloffset + ((canvasScrollLeft * additionalIEZoom) - canvasScrollLeft));\n                 a.y = a.y - (corrSVG.f - (jQuery(\"#canvasSection\").offset().top * additionalIEZoom) + ((canvasScrollTop * additionalIEZoom) - canvasScrollTop));\n                 b.x = b.x - (corrSVG.e - (canvasOffsetLeft * additionalIEZoom) + additionaloffset + ((canvasScrollLeft * additionalIEZoom) - canvasScrollLeft));\n                 b.y = b.y - (corrSVG.f - (jQuery(\"#canvasSection\").offset().top * additionalIEZoom) + ((canvasScrollTop * additionalIEZoom) - canvasScrollTop));\n            }\n\t\t\t\n\t\t\t\n\n\t\t\t// Fit to SVG-Coordinates\n\t\t\ta.x /= corrSVG.a; a.y /= corrSVG.d;\n\t\t\tb.x /= corrSVG.a; b.y /= corrSVG.d;\n\t\t\t\n\t\t\t// Calculate the elements from the childs of the canvas\n\t\t\tvar elements = this.facade.getCanvas().getChildShapes(true).findAll(function(value) {\n\t\t\t\tvar absBounds = value.absoluteBounds();\n\t\t\t\t\n\t\t\t\tvar bA = absBounds.upperLeft();\n\t\t\t\tvar bB = absBounds.lowerRight();\n\t\t\t\t\n\t\t\t\tif(bA.x > a.x && bA.y > a.y && bB.x < b.x && bB.y < b.y)\n\t\t\t\t\treturn true;\n\t\t\t\treturn false;\n\t\t\t});\n\n\t\t\t// Set the selection\n\t\t\tthis.facade.setSelection(elements);\n\t\t}\n\t},\n\n\thandleMouseMove: function(event) {\n\t\t// Calculate the size\n\t\tvar size = {\n\t\t\twidth\t: Event.pointerX(event) - this.position.x - jQuery(\"#canvasSection\").offset().left,\n\t\t\theight\t: Event.pointerY(event) - this.position.y - jQuery(\"#canvasSection\").offset().top + 5\n\t\t};\n\n\t\tvar scrollNode \t= this.facade.getCanvas().rootNode.parentNode.parentNode;\n\t\tsize.width \t\t-= this.offsetScroll.x - scrollNode.scrollLeft; \n\t\tsize.height \t-= this.offsetScroll.y - scrollNode.scrollTop;\n\t\t\t\t\t\t\n\t\t// Set the size\n\t\tthis.resize(size);\n\n\t\tEvent.stop(event);\n\t},\n\n\thide: function() {\n\t\tthis.node.style.display = \"none\";\n\t},\n\n\tshow: function() {\n\t\tthis.node.style.display = \"\";\n\t},\n\n\tsetPos: function(pos) {\n\t\t// Set the Position\n\t\tthis.node.style.top = pos.y + \"px\";\n\t\tthis.node.style.left = pos.x + \"px\";\n\t\tthis.position = pos;\n\t},\n\n\tresize: function(size) {\n\n\t\t// Calculate the negative offset\n\t\tthis.setPos(this.position);\n\t\tthis.size = Object.clone(size);\n\t\t\n\t\tif(size.width < 0) {\n\t\t\tthis.node.style.left = (this.position.x + size.width) + \"px\";\n\t\t\tsize.width = - size.width;\n\t\t}\n\t\tif(size.height < 0) {\n\t\t\tthis.node.style.top = (this.position.y + size.height) + \"px\";\n\t\t\tsize.height = - size.height;\n\t\t}\n\n\t\t// Set the size\n\t\tthis.node.style.width = size.width + \"px\";\n\t\tthis.node.style.height = size.height + \"px\";\n\t}\n\n});\n\n\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nif(!ORYX.Plugins)\n\tORYX.Plugins = new Object(); \n\nORYX.Plugins.ShapeHighlighting = Clazz.extend({\n\n\tconstruct: function(facade) {\n\t\t\n\t\tthis.parentNode = facade.getCanvas().getSvgContainer();\n\t\t\n\t\t// The parent Node\n\t\tthis.node = ORYX.Editor.graft(\"http://www.w3.org/2000/svg\", this.parentNode,\n\t\t\t\t\t['g']);\n\n\t\tthis.highlightNodes = {};\n\t\t\n\t\tfacade.registerOnEvent(ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW, this.setHighlight.bind(this));\n\t\tfacade.registerOnEvent(ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE, this.hideHighlight.bind(this));\t\t\n\n\t},\n\n\tsetHighlight: function(options) {\n\t\tif(options && options.highlightId){\n\t\t\tvar node = this.highlightNodes[options.highlightId];\n\t\t\t\n\t\t\tif(!node){\n\t\t\t\tnode= ORYX.Editor.graft(\"http://www.w3.org/2000/svg\", this.node,\n\t\t\t\t\t['path', {\n\t\t\t\t\t\t\"stroke-width\": 2.0, \"fill\":\"none\"\n\t\t\t\t\t\t}]);\t\n\t\t\t\n\t\t\t\tthis.highlightNodes[options.highlightId] = node;\n\t\t\t}\n\n\t\t\tif(options.elements && options.elements.length > 0) {\n\t\t\t\t\n\t\t\t\tthis.setAttributesByStyle( node, options );\n\t\t\t\tthis.show(node);\n\t\t\t\n\t\t\t} else {\n\t\t\t\n\t\t\t\tthis.hide(node);\t\t\t\n\t\t\t\n\t\t\t}\n\t\t\t\n\t\t}\n\t},\n\t\n\thideHighlight: function(options) {\n\t\tif(options && options.highlightId && this.highlightNodes[options.highlightId]){\n\t\t\tthis.hide(this.highlightNodes[options.highlightId]);\n\t\t}\t\t\n\t},\n\t\n\thide: function(node) {\n\t\tnode.setAttributeNS(null, 'display', 'none');\n\t},\n\n\tshow: function(node) {\n\t\tnode.setAttributeNS(null, 'display', '');\n\t},\n\t\n\tsetAttributesByStyle: function( node, options ){\n\t\t\n\t\t// If the style say, that it should look like a rectangle\n\t\tif( options.style && options.style == ORYX.CONFIG.SELECTION_HIGHLIGHT_STYLE_RECTANGLE ){\n\t\t\t\n\t\t\t// Set like this\n\t\t\tvar bo = options.elements[0].absoluteBounds();\n\t\t\t\n\t\t\tvar strWidth = options.strokewidth ? options.strokewidth \t: ORYX.CONFIG.BORDER_OFFSET\n\t\t\t\n\t\t\tnode.setAttributeNS(null, \"d\", this.getPathRectangle( bo.a, bo.b , strWidth ) );\n\t\t\tnode.setAttributeNS(null, \"stroke\", \t\toptions.color \t\t? options.color \t\t: ORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR);\n\t\t\tnode.setAttributeNS(null, \"stroke-opacity\", options.opacity \t? options.opacity \t\t: 0.2);\n\t\t\tnode.setAttributeNS(null, \"stroke-width\", \tstrWidth);\n\t\t\t\t\t\t\n\t\t} else if(options.elements.length == 1 \n\t\t\t\t\t&& options.elements[0] instanceof ORYX.Core.Edge &&\n\t\t\t\t\toptions.highlightId != \"selection\") {\n\t\t\t\n\t\t\t/* Highlight containment of edge's childs */\n\t\t\tvar path = this.getPathEdge(options.elements[0].dockers);\n\t\t\tif (path && path.length > 0)\n\t\t\t{\n\t\t\t\tnode.setAttributeNS(null, \"d\", path);\n\t\t\t}\n\t\t\tnode.setAttributeNS(null, \"stroke\", options.color ? options.color : ORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR);\n\t\t\tnode.setAttributeNS(null, \"stroke-opacity\", options.opacity ? options.opacity : 0.2);\n\t\t\tnode.setAttributeNS(null, \"stroke-width\", \tORYX.CONFIG.OFFSET_EDGE_BOUNDS);\n\t\t\t\n\t\t}else {\n\t\t\t// If not, set just the corners\n\t\t\tvar path = this.getPathByElements(options.elements);\n\t\t\tif (path && path.length > 0)\n\t\t\t{\n\t\t\t\tnode.setAttributeNS(null, \"d\", path);\n\t\t\t}\n\t\t\tnode.setAttributeNS(null, \"stroke\", options.color ? options.color : ORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR);\n\t\t\tnode.setAttributeNS(null, \"stroke-opacity\", options.opacity ? options.opacity : 1.0);\n\t\t\tnode.setAttributeNS(null, \"stroke-width\", \toptions.strokewidth ? options.strokewidth \t: 2.0);\n\t\t\t\t\t\t\n\t\t}\n\t},\n\t\n\tgetPathByElements: function(elements){\n\t\tif(!elements || elements.length <= 0) {return undefined}\n\t\t\n\t\t// Get the padding and the size\n\t\tvar padding = ORYX.CONFIG.SELECTED_AREA_PADDING;\n\t\t\n\t\tvar path = \"\"\n\t\t\n\t\t// Get thru all Elements\n\t\telements.each((function(element) {\n\t\t\tif(!element) {return}\n\t\t\t// Get the absolute Bounds and the two Points\n\t\t\tvar bounds = element.absoluteBounds();\n\t\t\tbounds.widen(padding)\n\t\t\tvar a = bounds.upperLeft();\n\t\t\tvar b = bounds.lowerRight();\n\t\t\t\n\t\t\tpath = path + this.getPath(a ,b);\n\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t}).bind(this));\n\n\t\treturn path;\n\t\t\n\t},\n\n\tgetPath: function(a, b){\n\t\t\t\t\n\t\treturn this.getPathCorners(a, b);\n\t\n\t},\n\t\t\t\n\tgetPathCorners: function(a, b){\n\n\t\tvar size = ORYX.CONFIG.SELECTION_HIGHLIGHT_SIZE;\n\t\t\t\t\n\t\tvar path = \"\"\n\n\t\t// Set: Upper left \n\t\tpath = path + \"M\" + a.x + \" \" + (a.y + size) + \" l0 -\" + size + \" l\" + size + \" 0 \";\n\t\t// Set: Lower left\n\t\tpath = path + \"M\" + a.x + \" \" + (b.y - size) + \" l0 \" + size + \" l\" + size + \" 0 \";\n\t\t// Set: Lower right\n\t\tpath = path + \"M\" + b.x + \" \" + (b.y - size) + \" l0 \" + size + \" l-\" + size + \" 0 \";\n\t\t// Set: Upper right\n\t\tpath = path + \"M\" + b.x + \" \" + (a.y + size) + \" l0 -\" + size + \" l-\" + size + \" 0 \";\n\t\t\n\t\treturn path;\n\t},\n\t\n\tgetPathRectangle: function(a, b, strokeWidth){\n\n\t\tvar size = ORYX.CONFIG.SELECTION_HIGHLIGHT_SIZE;\n\n\t\tvar path \t= \"\"\n\t\tvar offset \t= strokeWidth / 2.0;\n\t\t \n\t\t// Set: Upper left \n\t\tpath = path + \"M\" + (a.x + offset) + \" \" + (a.y);\n\t\tpath = path + \" L\" + (a.x + offset) + \" \" + (b.y - offset);\n\t\tpath = path + \" L\" + (b.x - offset) + \" \" + (b.y - offset);\n\t\tpath = path + \" L\" + (b.x - offset) + \" \" + (a.y + offset);\n\t\tpath = path + \" L\" + (a.x + offset) + \" \" + (a.y + offset);\n\n\t\treturn path;\n\t},\n\t\n\tgetPathEdge: function(edgeDockers) {\n\t\tvar length = edgeDockers.length;\n\t\tvar path = \"M\" + edgeDockers[0].bounds.center().x + \" \" \n\t\t\t\t\t+  edgeDockers[0].bounds.center().y;\n\t\t\n\t\tfor(i=1; i<length; i++) {\n\t\t\tvar dockerPoint = edgeDockers[i].bounds.center();\n\t\t\tpath = path + \" L\" + dockerPoint.x + \" \" +  dockerPoint.y;\n\t\t}\n\t\t\n\t\treturn path;\n\t}\n\t\n});\n\n \nORYX.Plugins.HighlightingSelectedShapes = Clazz.extend({\n\n\tconstruct: function(facade) {\n\t\tthis.facade = facade;\n\t\tthis.opacityFull = 0.9;\n\t\tthis.opacityLow = 0.4;\n\n\t\t// Register on Dragging-Events for show/hide of ShapeMenu\n\t\t//this.facade.registerOnEvent(ORYX.CONFIG.EVENT_DRAGDROP_START, this.hide.bind(this));\n\t\t//this.facade.registerOnEvent(ORYX.CONFIG.EVENT_DRAGDROP_END,  this.show.bind(this));\t\t\n\t},\n\n\t/**\n\t * On the Selection-Changed\n\t *\n\t */\n\tonSelectionChanged: function(event) {\n\t\tif(event.elements && event.elements.length > 1) {\n\t\t\tthis.facade.raiseEvent({\n\t\t\t\t\t\t\t\t\t\ttype:\t\tORYX.CONFIG.EVENT_HIGHLIGHT_SHOW, \n\t\t\t\t\t\t\t\t\t\thighlightId:'selection',\n\t\t\t\t\t\t\t\t\t\telements:\tevent.elements.without(event.subSelection),\n\t\t\t\t\t\t\t\t\t\tcolor:\t\tORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR,\n\t\t\t\t\t\t\t\t\t\topacity: \t!event.subSelection ? this.opacityFull : this.opacityLow\n\t\t\t\t\t\t\t\t\t});\n\n\t\t\tif(event.subSelection){\n\t\t\t\tthis.facade.raiseEvent({\n\t\t\t\t\t\t\t\t\t\t\ttype:\t\tORYX.CONFIG.EVENT_HIGHLIGHT_SHOW, \n\t\t\t\t\t\t\t\t\t\t\thighlightId:'subselection',\n\t\t\t\t\t\t\t\t\t\t\telements:\t[event.subSelection],\n\t\t\t\t\t\t\t\t\t\t\tcolor:\t\tORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR,\n\t\t\t\t\t\t\t\t\t\t\topacity: \tthis.opacityFull\n\t\t\t\t\t\t\t\t\t\t});\t\n\t\t\t} else {\n\t\t\t\tthis.facade.raiseEvent({type:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE, highlightId:'subselection'});\t\t\t\t\n\t\t\t}\t\t\t\t\t\t\n\t\t\t\n\t\t} else {\n\t\t\tthis.facade.raiseEvent({type:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE, highlightId:'selection'});\n\t\t\tthis.facade.raiseEvent({type:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE, highlightId:'subselection'});\n\t\t}\t\t\n\t}\n});/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nif (!ORYX.Plugins) \n    ORYX.Plugins = new Object();\n\nORYX.Plugins.Overlay = Clazz.extend({\n\n    facade: undefined,\n\t\n\tstyleNode: undefined,\n    \n    construct: function(facade){\n\t\t\n        this.facade = facade;\n\n\t\tthis.changes = [];\n\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_OVERLAY_SHOW, this.show.bind(this));\n\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_OVERLAY_HIDE, this.hide.bind(this));\t\n\n\t\tthis.styleNode = document.createElement('style')\n\t\tthis.styleNode.setAttributeNS(null, 'type', 'text/css')\n\t\t\n\t\tdocument.getElementsByTagName('head')[0].appendChild( this.styleNode )\n\n    },\n\t\n\t/**\n\t * Show the overlay for specific nodes\n\t * @param {Object} options\n\t * \n\t * \tString\t\t\t\toptions.id\t\t- MUST - Define the id of the overlay (is needed for the hiding of this overlay)\t\t\n\t *\tORYX.Core.Shape[] \toptions.shapes \t- MUST - Define the Shapes for the changes\n\t * \tattr-name:value\t\toptions.changes\t- Defines all the changes which should be shown\n\t * \n\t * \n\t */\n\tshow: function( options ){\n\t\t\n\t\t// Checks if all arguments are available\n\t\tif( \t!options || \n\t\t\t\t!options.shapes || !options.shapes instanceof Array ||\n\t\t\t\t!options.id\t|| !options.id instanceof String || options.id.length == 0) { \n\t\t\t\t\n\t\t\t\t\treturn\n\t\t\t\t\t\n\t\t}\n\t\t\n\t\t//if( this.changes[options.id]){\n\t\t//\tthis.hide( options )\n\t\t//}\n\t\t\t\n\n\t\t// Checked if attributes are setted\n\t\tif( options.attributes ){\n\t\t\t\n\t\t\t// FOR EACH - Shape\n\t\t\toptions.shapes.each(function(el){\n\t\t\t\t\n\t\t\t\t// Checks if the node is a Shape\n\t\t\t\tif( !el instanceof ORYX.Core.Shape){ return }\n\t\t\t\t\n\t\t\t\tthis.setAttributes( el.node , options.attributes )\n\t\t\t\t\n\t\t\t}.bind(this))\n\n\t\t}\t\n\t\t\n\t\tvar isSVG = true\n\t\ttry {\n\t\t\tisSVG = options.node && options.node instanceof SVGElement;\n\t\t} catch(e){}\n\t\t\n\t\t// Checks if node is setted and if this is an SVGElement\t\t\n\t\tif ( options.node && isSVG) {\n\t\t\t\n\t\t\toptions[\"_temps\"] = []\n\t\t\t\t\t\t\n\t\t\t// FOR EACH - Node\n\t\t\toptions.shapes.each(function(el, index){\n\t\t\t\t\n\t\t\t\t// Checks if the node is a Shape\n\t\t\t\tif( !el instanceof ORYX.Core.Shape){ return }\n\t\t\t\t\n\t\t\t\tvar _temp = {}\n\t\t\t\t_temp.svg = options.dontCloneNode ? options.node : options.node.cloneNode( true );\n\t\t\t\t\n\t\t\t\t// Add the svg node to the ORYX-Shape\n\t\t\t\tel.node.firstChild.appendChild( _temp.svg )\t\t\n\t\t\t\t\n\t\t\t\t// If\n\t\t\t\tif (el instanceof ORYX.Core.Edge && !options.nodePosition) {\n\t\t\t\t\toptions['nodePosition'] = \"START\"\n\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t// If the node position is setted, it has to be transformed\n\t\t\t\tif( options.nodePosition ){\n\t\t\t\t\t\n\t\t\t\t\tvar b = el.bounds;\n\t\t\t\t\tvar p = options.nodePosition.toUpperCase();\n\t\t\t\t\t\n\t\t\t\t\t// Check the values of START and END\n\t\t\t\t\tif( el instanceof ORYX.Core.Node && p == \"START\"){\n\t\t\t\t\t\tp = \"NW\";\n\t\t\t\t\t} else if(el instanceof ORYX.Core.Node && p == \"END\"){\n\t\t\t\t\t\tp = \"SE\";\n\t\t\t\t\t} else if(el instanceof ORYX.Core.Edge && p == \"START\"){\n\t\t\t\t\t\tb = el.getDockers().first().bounds\n\t\t\t\t\t} else if(el instanceof ORYX.Core.Edge && p == \"END\"){\n\t\t\t\t\t\tb = el.getDockers().last().bounds\n\t\t\t\t\t}\n\n\t\t\t\t\t// Create a callback for the changing the position \n\t\t\t\t\t// depending on the position string\n\t\t\t\t\t_temp.callback = function(){\n\t\t\t\t\t\t\n\t\t\t\t\t\tvar x = 0; var y = 0;\n\t\t\t\t\t\t\n\t\t\t\t\t\tif( p == \"NW\" ){\n\t\t\t\t\t\t\t// Do Nothing\n\t\t\t\t\t\t} else if( p == \"N\" ) {\n\t\t\t\t\t\t\tx = b.width() / 2;\n\t\t\t\t\t\t} else if( p == \"NE\" ) {\n\t\t\t\t\t\t\tx = b.width();\n\t\t\t\t\t\t} else if( p == \"E\" ) {\n\t\t\t\t\t\t\tx = b.width(); y = b.height() / 2;\n\t\t\t\t\t\t} else if( p == \"SE\" ) {\n\t\t\t\t\t\t\tx = b.width(); y = b.height();\n\t\t\t\t\t\t} else if( p == \"S\" ) {\n\t\t\t\t\t\t\tx = b.width() / 2; y = b.height();\n\t\t\t\t\t\t} else if( p == \"SW\" ) {\n\t\t\t\t\t\t\ty = b.height();\n\t\t\t\t\t\t} else if( p == \"W\" ) {\n\t\t\t\t\t\t\ty = b.height() / 2;\n\t\t\t\t\t\t} else if( p == \"START\" || p == \"END\") {\n\t\t\t\t\t\t\tx = b.width() / 2; y = b.height() / 2;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tif( el instanceof ORYX.Core.Edge){\n\t\t\t\t\t\t\tx  += b.upperLeft().x ; y  += b.upperLeft().y ;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\t_temp.svg.setAttributeNS(null, \"transform\", \"translate(\" + x + \", \" + y + \")\")\n\t\t\t\t\t\n\t\t\t\t\t}.bind(this)\n\t\t\t\t\t\n\t\t\t\t\t_temp.element = el;\n\t\t\t\t\t_temp.callback();\n\t\t\t\t\t\n\t\t\t\t\tb.registerCallback( _temp.callback );\n\t\t\t\t\t\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t\n\t\t\t\toptions._temps.push( _temp )\t\n\t\t\t\t\n\t\t\t}.bind(this))\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t}\t\t\n\t\n\n\t\t// Store the changes\n\t\tif( !this.changes[options.id] ){\n\t\t\tthis.changes[options.id] = [];\n\t\t}\n\t\t\n\t\tthis.changes[options.id].push( options );\n\t\t\t\t\n\t},\n\t\n\t/**\n\t * Hide the overlay with the spefic id\n\t * @param {Object} options\n\t */\n\thide: function( options ){\n\t\t\n\t\t// Checks if all arguments are available\n\t\tif( \t!options || \n\t\t\t\t!options.id\t|| !options.id instanceof String || options.id.length == 0 ||\n\t\t\t\t!this.changes[options.id]) { \n\t\t\t\t\n\t\t\t\t\treturn\n\t\t\t\t\t\n\t\t}\t\t\n\t\t\n\t\t\n\t\t// Delete all added attributes\n\t\t// FOR EACH - Shape\n\t\tthis.changes[options.id].each(function(option){\n\t\t\t\n\t\t\toption.shapes.each(function(el, index){\n\t\t\t\t\n\t\t\t\t// Checks if the node is a Shape\n\t\t\t\tif( !el instanceof ORYX.Core.Shape){ return }\n\t\t\t\t\n\t\t\t\tthis.deleteAttributes( el.node )\n\t\t\t\t\t\t\t\n\t\t\t}.bind(this));\n\n\t\n\t\t\tif( option._temps ){\n\t\t\t\t\n\t\t\t\toption._temps.each(function(tmp){\n\t\t\t\t\t// Delete the added Node, if there is one\n\t\t\t\t\tif( tmp.svg && tmp.svg.parentNode ){\n\t\t\t\t\t\ttmp.svg.parentNode.removeChild( tmp.svg )\n\t\t\t\t\t}\n\t\t\n\t\t\t\t\t// If \n\t\t\t\t\tif( tmp.callback && tmp.element){\n\t\t\t\t\t\t// It has to be unregistered from the edge\n\t\t\t\t\t\ttmp.element.bounds.unregisterCallback( tmp.callback )\n\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t}.bind(this))\n\t\t\t\t\n\t\t\t}\n\t\t\n\t\t\t\n\t\t}.bind(this));\n\n\t\t\n\t\tthis.changes[options.id] = null;\n\t\t\n\t\t\n\t},\n\t\n\t\n\t/**\n\t * Set the given css attributes to that node\n\t * @param {HTMLElement} node\n\t * @param {Object} attributes\n\t */\n\tsetAttributes: function( node, attributes ) {\n\t\t\n\t\t\n\t\t// Get all the childs from ME\n\t\tvar childs = this.getAllChilds( node.firstChild.firstChild )\n\t\t\n\t\tvar ids = []\n\t\t\n\t\t// Add all Attributes which have relation to another node in this document and concate the pure id out of it\n\t\t// This is for example important for the markers of a edge\n\t\tchilds.each(function(e){ ids.push( $A(e.attributes).findAll(function(attr){ return attr.nodeValue.startsWith('url(#')}) )})\n\t\tids = ids.flatten().compact();\n\t\tids = ids.collect(function(s){return s.nodeValue}).uniq();\n\t\tids = ids.collect(function(s){return s.slice(5, s.length-1)})\n\t\t\n\t\t// Add the node ID to the id\n\t\tids.unshift( node.id + ' .me')\n\t\t\n\t\tvar attr\t\t\t\t= $H(attributes);\n        var attrValue\t\t\t= attr.toJSON().gsub(',', ';').gsub('\"', '');\n        var attrMarkerValue\t\t= attributes.stroke ? attrValue.slice(0, attrValue.length-1) + \"; fill:\" + attributes.stroke + \";}\" : attrValue;\n        var attrTextValue;\n        if( attributes.fill ){\n            var copyAttr        = Object.clone(attributes);\n        \tcopyAttr.fill\t\t= \"black\";\n        \tattrTextValue\t\t= $H(copyAttr).toJSON().gsub(',', ';').gsub('\"', '');\n        }\n                \t\n        // Create the CSS-Tags Style out of the ids and the attributes\n        csstags = ids.collect(function(s, i){return \"#\" + s + \" * \" + (!i? attrValue : attrMarkerValue) + \"\" + (attrTextValue ? \" #\" + s + \" text * \" + attrTextValue : \"\") })\n\t\t\n\t\t// Join all the tags\n\t\tvar s = csstags.join(\" \") + \"\\n\" \n\t\t\n\t\t// And add to the end of the style tag\n\t\tthis.styleNode.appendChild(document.createTextNode(s));\n\t\t\n\t\t\n\t},\n\t\n\t/**\n\t * Deletes all attributes which are\n\t * added in a special style sheet for that node\n\t * @param {HTMLElement} node \n\t */\n\tdeleteAttributes: function( node ) {\n\t\t\t\t\n\t\t// Get all children which contains the node id\t\t\n\t\tvar delEl = $A(this.styleNode.childNodes)\n\t\t\t\t\t .findAll(function(e){ return e.textContent.include( '#' + node.id ) });\n\t\t\n\t\t// Remove all of them\n\t\tdelEl.each(function(el){\n\t\t\tel.parentNode.removeChild(el);\n\t\t});\t\t\n\t},\n\t\n\tgetAllChilds: function( node ){\n\t\t\n\t\tvar childs = $A(node.childNodes)\n\t\t\n\t\t$A(node.childNodes).each(function( e ){ \n\t\t        childs.push( this.getAllChilds( e ) )\n\t\t}.bind(this))\n\n    \treturn childs.flatten();\n\t}\n\n    \n});\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nif (!ORYX.Plugins) \n    ORYX.Plugins = new Object();\n\nORYX.Plugins.KeysMove = ORYX.Plugins.AbstractPlugin.extend({\n\n    facade: undefined,\n    \n    construct: function(facade){\n    \n        this.facade = facade;\n        this.copyElements = [];\n        \n        //this.facade.registerOnEvent(ORYX.CONFIG.EVENT_KEYDOWN, this.keyHandler.bind(this));\n\n\t\t// SELECT ALL\n\t\tthis.facade.offer({\n\t\tkeyCodes: [{\n\t\t \t\tmetaKeys: [ORYX.CONFIG.META_KEY_META_CTRL],\n\t\t\t\tkeyCode: 65,\n\t\t\t\tkeyAction: ORYX.CONFIG.KEY_ACTION_DOWN \n\t\t\t}\n\t\t ],\n         functionality: this.selectAll.bind(this)\n         });\n\t\t \n\t\t// MOVE LEFT SMALL\t\t\n\t\tthis.facade.offer({\n\t\tkeyCodes: [{\n\t\t \t\tmetaKeys: [ORYX.CONFIG.META_KEY_META_CTRL],\n\t\t\t\tkeyCode: ORYX.CONFIG.KEY_CODE_LEFT,\n\t\t\t\tkeyAction: ORYX.CONFIG.KEY_ACTION_DOWN \n\t\t\t}\n\t\t ],\n         functionality: this.move.bind(this, ORYX.CONFIG.KEY_CODE_LEFT, false)\n         });\n\t\t \n\t\t // MOVE LEFT\n\t\t this.facade.offer({\n\t\t keyCodes: [{\n\t\t\t\tkeyCode: ORYX.CONFIG.KEY_CODE_LEFT,\n\t\t\t\tkeyAction: ORYX.CONFIG.KEY_ACTION_DOWN \n\t\t\t}\n\t\t ],\n         functionality: this.move.bind(this, ORYX.CONFIG.KEY_CODE_LEFT, true)\n         });\n\t\t \n\t\t// MOVE RIGHT SMALL\t\n\t\t this.facade.offer({\n\t\t keyCodes: [{\n\t\t \t\tmetaKeys: [ORYX.CONFIG.META_KEY_META_CTRL],\n\t\t\t\tkeyCode: ORYX.CONFIG.KEY_CODE_RIGHT,\n\t\t\t\tkeyAction: ORYX.CONFIG.KEY_ACTION_DOWN \n\t\t\t}\n\t\t ],\n         functionality: this.move.bind(this, ORYX.CONFIG.KEY_CODE_RIGHT, false)\n         });\n\t\t \n\t\t// MOVE RIGHT\t\n\t\t this.facade.offer({\n\t\t keyCodes: [{\n\t\t\t\tkeyCode: ORYX.CONFIG.KEY_CODE_RIGHT,\n\t\t\t\tkeyAction: ORYX.CONFIG.KEY_ACTION_DOWN \n\t\t\t}\n\t\t ],\n         functionality: this.move.bind(this, ORYX.CONFIG.KEY_CODE_RIGHT, true)\n         });\n\t\t \n\t\t// MOVE UP SMALL\t\n\t\t this.facade.offer({\n\t\t keyCodes: [{\n\t\t \t\tmetaKeys: [ORYX.CONFIG.META_KEY_META_CTRL],\n\t\t\t\tkeyCode: ORYX.CONFIG.KEY_CODE_UP,\n\t\t\t\tkeyAction: ORYX.CONFIG.KEY_ACTION_DOWN \n\t\t\t}\n\t\t ],\n         functionality: this.move.bind(this, ORYX.CONFIG.KEY_CODE_UP, false)\n         });\n\t\t \n\t\t// MOVE UP\t\n\t\t this.facade.offer({\n\t\t keyCodes: [{\n\t\t\t\tkeyCode: ORYX.CONFIG.KEY_CODE_UP,\n\t\t\t\tkeyAction: ORYX.CONFIG.KEY_ACTION_DOWN \n\t\t\t}\n\t\t ],\n         functionality: this.move.bind(this, ORYX.CONFIG.KEY_CODE_UP, true)\n         });\n\t\t \n\t\t// MOVE DOWN SMALL\t\n\t\t this.facade.offer({\n\t\t keyCodes: [{\n\t\t \t\tmetaKeys: [ORYX.CONFIG.META_KEY_META_CTRL],\n\t\t\t\tkeyCode: ORYX.CONFIG.KEY_CODE_DOWN,\n\t\t\t\tkeyAction: ORYX.CONFIG.KEY_ACTION_DOWN \n\t\t\t}\n\t\t ],\n         functionality: this.move.bind(this, ORYX.CONFIG.KEY_CODE_DOWN, false)\n         });\n\t\t \n\t\t// MOVE DOWN\t\n\t\t this.facade.offer({\n\t\t keyCodes: [{\n\t\t\t\tkeyCode: ORYX.CONFIG.KEY_CODE_DOWN,\n\t\t\t\tkeyAction: ORYX.CONFIG.KEY_ACTION_DOWN \n\t\t\t}\n\t\t ],\n         functionality: this.move.bind(this, ORYX.CONFIG.KEY_CODE_DOWN, true)\n         });\n\t\t \n         \n    },\n    \n\t/**\n\t * Select all shapes in the editor\n\t *\n\t */\n\tselectAll: function(e){\n    \tEvent.stop(e.event);\n\t\tthis.facade.setSelection(this.facade.getCanvas().getChildShapes(true))\n\t},\n\t\n\tmove: function(key, far, e) {\n\t\t\n    \tEvent.stop(e.event);\n\n\t\t// calculate the distance to move the objects and get the selection.\n\t\tvar distance = far? 20 : 5;\n\t\tvar selection = this.facade.getSelection();\n\t\tvar currentSelection = this.facade.getSelection();\n\t\tvar p = {x: 0, y: 0};\n\t\t\n\t\t// switch on the key pressed and populate the point to move by.\n\t\tswitch(key) {\n\n\t\t\tcase ORYX.CONFIG.KEY_CODE_LEFT:\n\t\t\t\tp.x = -1*distance;\n\t\t\t\tbreak;\n\t\t\tcase ORYX.CONFIG.KEY_CODE_RIGHT:\n\t\t\t\tp.x = distance;\n\t\t\t\tbreak;\n\t\t\tcase ORYX.CONFIG.KEY_CODE_UP:\n\t\t\t\tp.y = -1*distance;\n\t\t\t\tbreak;\n\t\t\tcase ORYX.CONFIG.KEY_CODE_DOWN:\n\t\t\t\tp.y = distance;\n\t\t\t\tbreak;\n\t\t}\n\t\t\n\t\t// move each shape in the selection by the point calculated and update it.\n\t\tselection = selection.findAll(function(shape){ \n\t\t\t// Check if this shape is docked to an shape in the selection\t\t\t\n\t\t\tif(shape instanceof ORYX.Core.Node && shape.dockers.length == 1 && selection.include( shape.dockers.first().getDockedShape() )){ \n\t\t\t\treturn false \n\t\t\t} \n\t\t\t\n\t\t\t// Check if any of the parent shape is included in the selection\n\t\t\tvar s = shape.parent; \n\t\t\tdo{ \n\t\t\t\tif(selection.include(s)){ \n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t}while(s = s.parent); \n\t\t\t\n\t\t\t// Otherwise, return true\n\t\t\treturn true;\n\t\t\t\n\t\t});\n\t\t\n\t\t/* Edges must not be movable, if only edges are selected and at least \n\t\t * one of them is docked.\n\t\t */\n\t\tvar edgesMovable = true;\n\t\tvar onlyEdgesSelected = selection.all(function(shape) {\n\t\t\tif(shape instanceof ORYX.Core.Edge) {\n\t\t\t\tif(shape.isDocked()) {\n\t\t\t\t\tedgesMovable = false;\n\t\t\t\t}\n\t\t\t\treturn true;\t\n\t\t\t}\n\t\t\treturn false;\n\t\t});\n\t\t\n\t\tif(onlyEdgesSelected && !edgesMovable) {\n\t\t\t/* Abort moving shapes */\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tselection = selection.map(function(shape){ \n\t\t\tif( shape instanceof ORYX.Core.Node ){\n\t\t\t\t/*if( shape.dockers.length == 1 ){\n\t\t\t\t\treturn shape.dockers.first()\n\t\t\t\t} else {*/\n\t\t\t\t\treturn shape\n\t\t\t\t//}\n\t\t\t} else if( shape instanceof ORYX.Core.Edge ) {\n\t\t\t\t\n\t\t\t\tvar dockers = shape.dockers;\n\t\t\t\t\n\t\t\t\tif( selection.include( shape.dockers.first().getDockedShape() ) ){\n\t\t\t\t\tdockers = dockers.without( shape.dockers.first() )\n\t\t\t\t}\n\n\t\t\t\tif( selection.include( shape.dockers.last().getDockedShape() ) ){\n\t\t\t\t\tdockers = dockers.without( shape.dockers.last() )\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\treturn dockers\t\n\t\t\t\t\t\t\t\n\t\t\t} else {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\n\t\t}).flatten().compact();\n\t\t\n\t\tif (selection.size() > 0) {\n\t\t\t\n\t\t\t//Stop moving at canvas borders\n\t\t\tvar selectionBounds = [ this.facade.getCanvas().bounds.lowerRight().x,\n\t\t\t                        this.facade.getCanvas().bounds.lowerRight().y,\n\t\t\t                        0,\n\t\t\t                        0 ];\n\t\t\tselection.each(function(s) {\n\t\t\t\tselectionBounds[0] = Math.min(selectionBounds[0], s.bounds.upperLeft().x);\n\t\t\t\tselectionBounds[1] = Math.min(selectionBounds[1], s.bounds.upperLeft().y);\n\t\t\t\tselectionBounds[2] = Math.max(selectionBounds[2], s.bounds.lowerRight().x);\n\t\t\t\tselectionBounds[3] = Math.max(selectionBounds[3], s.bounds.lowerRight().y);\n\t\t\t});\n\t\t\tif(selectionBounds[0]+p.x < 0)\n\t\t\t\tp.x = -selectionBounds[0];\n\t\t\tif(selectionBounds[1]+p.y < 0)\n\t\t\t\tp.y = -selectionBounds[1];\n\t\t\tif(selectionBounds[2]+p.x > this.facade.getCanvas().bounds.lowerRight().x)\n\t\t\t\tp.x = this.facade.getCanvas().bounds.lowerRight().x - selectionBounds[2];\n\t\t\tif(selectionBounds[3]+p.y > this.facade.getCanvas().bounds.lowerRight().y)\n\t\t\t\tp.y = this.facade.getCanvas().bounds.lowerRight().y - selectionBounds[3];\n\t\t\t\n\t\t\tif(p.x!=0 || p.y!=0) {\n\t\t\t\t// Instantiate the moveCommand\n\t\t\t\tvar commands = [new ORYX.Core.Command.Move(selection, p, null, currentSelection, this)];\n\t\t\t\t// Execute the commands\t\t\t\n\t\t\t\tthis.facade.executeCommands(commands);\n\t\t\t}\n\t\t\t\n\t\t}\n\t},\n\t\n\tgetUndockedCommant: function(shapes){\n\n\t\tvar undockEdgeCommand = ORYX.Core.Command.extend({\n\t\t\tconstruct: function(moveShapes){\n\t\t\t\tthis.dockers = moveShapes.collect(function(shape){ return shape instanceof ORYX.Core.Controls.Docker ? {docker:shape, dockedShape:shape.getDockedShape(), refPoint:shape.referencePoint} : undefined }).compact();\n\t\t\t},\t\t\t\n\t\t\texecute: function(){\n\t\t\t\tthis.dockers.each(function(el){\n\t\t\t\t\tel.docker.setDockedShape(undefined);\n\t\t\t\t})\n\t\t\t},\n\t\t\trollback: function(){\n\t\t\t\tthis.dockers.each(function(el){\n\t\t\t\t\tel.docker.setDockedShape(el.dockedShape);\n\t\t\t\t\tel.docker.setReferencePoint(el.refPoint);\n\t\t\t\t\t//el.docker.update();\n\t\t\t\t})\n\t\t\t}\n\t\t});\n\t\t\n\t\tcommand = new undockEdgeCommand( shapes );\n\t\tcommand.execute();\t\n\t\treturn command;\n\t},\n\t\n//    /**\n//     * The key handler for this plugin. Every action from the set of cut, copy,\n//     * paste and delete should be accessible trough simple keyboard shortcuts.\n//     * This method checks whether any event triggers one of those actions.\n//     *\n//     * @param {Object} event The keyboard event that should be analysed for\n//     *     triggering of this plugin.\n//     */\n//    keyHandler: function(event){\n//        //TODO document what event.which is.\n//        \n//        ORYX.Log.debug(\"keysMove.js handles a keyEvent.\");\n//        \n//        // assure we have the current event.\n//        if (!event) \n//            event = window.event;\n//        \n//        // get the currently pressed key and state of control key.\n//        var pressedKey = event.which || event.keyCode;\n//        var ctrlPressed = event.ctrlKey;\n//\n//\t\t// if the key is one of the arrow keys, forward to move and return.\n//\t\tif ([ORYX.CONFIG.KEY_CODE_LEFT, ORYX.CONFIG.KEY_CODE_RIGHT,\n//\t\t\tORYX.CONFIG.KEY_CODE_UP, ORYX.CONFIG.KEY_CODE_DOWN].include(pressedKey)) {\n//\t\t\t\n//\t\t\tthis.move(pressedKey, !ctrlPressed);\n//\t\t\treturn;\n//\t\t}\n//\t\t\n//    }\n\t\n});\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nif(!ORYX.Plugins) { ORYX.Plugins = {} }\nif(!ORYX.Plugins.Layouter) { ORYX.Plugins.Layouter = {} }\n\nnew function(){\n\t\n\t/**\n\t * Edge layouter is an implementation to layout an edge\n\t * @class ORYX.Plugins.Layouter.EdgeLayouter\n\t * @author Willi Tscheschner\n\t */\n\tORYX.Plugins.Layouter.EdgeLayouter = ORYX.Plugins.AbstractLayouter.extend({\n\t\t\n\t\t/**\n\t\t * Layout only Edges\n\t\t */\n\t\tlayouted : [\t\"http://b3mn.org/stencilset/bpmn1.1#SequenceFlow\", \n\t\t\t\t\t\t\"http://b3mn.org/stencilset/bpmn1.1#MessageFlow\",\n\t\t\t\t\t\t\"http://b3mn.org/stencilset/timjpdl3#SequenceFlow\", \n\t\t\t\t\t\t\"http://b3mn.org/stencilset/jbpm4#SequenceFlow\", \n\t\t\t\t\t\t\"http://b3mn.org/stencilset/bpmn2.0#MessageFlow\",\n\t\t\t\t\t\t\"http://b3mn.org/stencilset/bpmn2.0#SequenceFlow\", \n\t\t\t\t\t\t\"http://b3mn.org/stencilset/bpmn2.0choreography#MessageFlow\",\n\t\t\t\t\t\t\"http://b3mn.org/stencilset/bpmn2.0choreography#SequenceFlow\", \n\t\t\t\t\t\t\"http://b3mn.org/stencilset/bpmn2.0conversation#ConversationLink\",\n\t\t\t\t\t\t\"http://b3mn.org/stencilset/epc#ControlFlow\",\n\t\t\t\t\t\t\"http://www.signavio.com/stencilsets/processmap#ProcessLink\",\n\t\t\t\t\t\t\"http://www.signavio.com/stencilsets/organigram#connection\"],\n\t\t\n\t\t/**\n\t\t * Layout a set on edges\n\t\t * @param {Object} edges\n\t\t */\n\t\tlayout: function(edges){\n\t\t\tedges.each(function(edge){\n\t\t\t\tthis.doLayout(edge)\n\t\t\t}.bind(this))\n\t\t},\n\t\t\n\t\t/**\n\t\t * Layout one edge\n\t\t * @param {Object} edge\n\t\t */\n\t\tdoLayout: function(edge){\n\t\t\t// Get from and to node\n\t\t\tvar from \t= edge.getIncomingNodes()[0]; \n\t\t\tvar to \t\t= edge.getOutgoingNodes()[0];\n\t\t\t\n\t\t\t// Return if one is null\n\t\t\tif (!from || !to) { return }\n\t\t\t\n\t\t\tvar positions = this.getPositions(from, to, edge);\n\t\t\n\t\t\tif (positions.length > 0){\n\t\t\t\tthis.setDockers(edge, positions[0].a, positions[0].b);\n\t\t\t}\n\t\t\t\t\n\t\t},\n\t\t\n\t\t/**\n\t\t * Returns a set on positions which are not containt either \n\t\t * in the bounds in from or to.\n\t\t * @param {Object} from Shape where the edge is come from\n\t\t * @param {Object} to Shape where the edge is leading to\n\t\t * @param {Object} edge Edge between from and to\n\t\t */\n\t\tgetPositions : function(from, to, edge){\n\t\t\t\n\t\t\t// Get absolute bounds\n\t\t\tvar ab = from.absoluteBounds();\n\t\t\tvar bb = to.absoluteBounds();\n\t\t\t\n\t\t\t// Get center from and to\n\t\t\tvar a = ab.center();\n\t\t\tvar b = bb.center();\n\t\t\t\n\t\t\tvar am = ab.midPoint();\n\t\t\tvar bm = bb.midPoint();\n\t\t\n\t\t\t// Get first and last reference point\n\t\t\tvar first = Object.clone(edge.dockers.first().referencePoint);\n\t\t\tvar last = Object.clone(edge.dockers.last().referencePoint);\n\t\t\t// Get the absolute one\n\t\t\tvar aFirst = edge.dockers.first().getAbsoluteReferencePoint();\n\t\t\tvar aLast = edge.dockers.last().getAbsoluteReferencePoint(); \n\t\t\t\n\t\t\t// IF ------>\n\t\t\t// or  |\n\t\t\t//     V\n\t\t\t// Do nothing\n\t\t\tif (Math.abs(aFirst.x-aLast.x) < 1 || Math.abs(aFirst.y-aLast.y) < 1) {\n\t\t\t\treturn []\n\t\t\t}\n\t\t\t\n\t\t\t// Calc center position, between a and b\n\t\t\t// depending on there weight\n\t\t\tvar m = {}\n\t\t\tm.x = a.x < b.x ? \n\t\t\t\t\t(((b.x - bb.width()/2) - (a.x + ab.width()/2))/2) + (a.x + ab.width()/2): \n\t\t\t\t\t(((a.x - ab.width()/2) - (b.x + bb.width()/2))/2) + (b.x + bb.width()/2);\n\n\t\t\tm.y = a.y < b.y ? \n\t\t\t\t\t(((b.y - bb.height()/2) - (a.y + ab.height()/2))/2) + (a.y + ab.height()/2): \n\t\t\t\t\t(((a.y - ab.height()/2) - (b.y + bb.height()/2))/2) + (b.y + bb.height()/2);\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t// Enlarge both bounds with 10\n\t\t\tab.widen(5); // Wide the from less than \n\t\t\tbb.widen(20);// the to because of the arrow from the edge\n\t\t\t\t\t\t\t\t\n\t\t\tvar positions = [];\n\t\t\tvar off = this.getOffset.bind(this);\n\t\t\t\n\t\t\t// Checks ----+\n\t\t\t//            |\n\t\t\t//            V\n\t\t\tif (!ab.isIncluded(b.x, a.y)&&!bb.isIncluded(b.x, a.y)) {\n\t\t\t\tpositions.push({\n\t\t\t\t\ta : {x:b.x+off(last,bm,\"x\"),y:a.y+off(first,am,\"y\")},\n\t\t\t\t\tz : this.getWeight(from, a.x < b.x ? \"r\" : \"l\", to, a.y < b.y ? \"t\" : \"b\", edge)\n\t\t\t\t});\n\t\t\t}\n\t\t\t\t\t\t\n\t\t\t// Checks | \n\t\t\t//        +--->\n\t\t\tif (!ab.isIncluded(a.x, b.y)&&!bb.isIncluded(a.x, b.y)) {\n\t\t\t\tpositions.push({\n\t\t\t\t\ta : {x:a.x+off(first,am,\"x\"),y:b.y+off(last,bm,\"y\")},\n\t\t\t\t\tz : this.getWeight(from, a.y < b.y ? \"b\" : \"t\", to, a.x < b.x ? \"l\" : \"r\", edge)\n\t\t\t\t});\n\t\t\t}\n\t\t\t\t\t\t\n\t\t\t// Checks  --+\n\t\t\t//           |\n\t\t\t//           +--->\n\t\t\tif (!ab.isIncluded(m.x, a.y)&&!bb.isIncluded(m.x, b.y)) {\n\t\t\t\tpositions.push({\n\t\t\t\t\ta : {x:m.x,y:a.y+off(first,am,\"y\")},\n\t\t\t\t\tb : {x:m.x,y:b.y+off(last,bm,\"y\")},\n\t\t\t\t\tz : this.getWeight(from, \"r\", to, \"l\", edge, a.x > b.x)\n\t\t\t\t});\n\t\t\t}\n\t\t\t\n\t\t\t// Checks | \n\t\t\t//        +---+\n\t\t\t//            |\n\t\t\t//            V\n\t\t\tif (!ab.isIncluded(a.x, m.y)&&!bb.isIncluded(b.x, m.y)) {\n\t\t\t\tpositions.push({\n\t\t\t\t\ta : {x:a.x+off(first,am,\"x\"),y:m.y},\n\t\t\t\t\tb : {x:b.x+off(last,bm,\"x\"),y:m.y},\n\t\t\t\t\tz : this.getWeight(from, \"b\", to, \"t\", edge, a.y > b.y)\n\t\t\t\t});\n\t\t\t}\t\n\t\t\t\n\t\t\t// Sort DESC of weights\n\t\t\treturn positions.sort(function(a,b){ return a.z < b.z ? 1 : (a.z == b.z ? -1 : -1)});\n\t\t},\n\t\t\n\t\t/**\n\t\t * Returns a offset for the pos to the center of the bounds\n\t\t * \n\t\t * @param {Object} val\n\t\t * @param {Object} pos2\n\t\t * @param {String} dir Direction x|y\n\t\t */\n\t\tgetOffset: function(pos, pos2, dir){\n\t\t\treturn pos[dir] - pos2[dir];\n\t\t},\n\t\t\n\t\t/**\n\t\t * Returns a value which shows the weight for this configuration\n\t\t * \n\t\t * @param {Object} from Shape which is coming from\n\t\t * @param {String} d1 Direction where is goes\n\t\t * @param {Object} to Shape which goes to\n\t\t * @param {String} d2 Direction where it comes to\n\t\t * @param {Object} edge Edge between from and to\n\t\t * @param {Boolean} reverse Reverse the direction (e.g. \"r\" -> \"l\")\n\t\t */\n\t\tgetWeight: function(from, d1, to, d2, edge, reverse){\n\t\t\t\n\t\t\td1 = (d1||\"\").toLowerCase();\n\t\t\td2 = (d2||\"\").toLowerCase();\n\t\t\t\n\t\t\tif (![\"t\",\"r\",\"b\",\"l\"].include(d1)){ d1 = \"r\"}\n\t\t\tif (![\"t\",\"r\",\"b\",\"l\"].include(d2)){ d1 = \"l\"}\n\t\t\t\n\t\t\t// If reverse is set\n\t\t\tif (reverse) {\n\t\t\t\t// Reverse d1 and d2\n\t\t\t\td1 = d1==\"t\"?\"b\":(d1==\"r\"?\"l\":(d1==\"b\"?\"t\":(d1==\"l\"?\"r\":\"r\")))\n\t\t\t\td2 = d2==\"t\"?\"b\":(d2==\"r\"?\"l\":(d2==\"b\"?\"t\":(d2==\"l\"?\"r\":\"r\")))\n\t\t\t}\n\t\t\t\n\t\t\t\t\t\n\t\t\tvar weight = 0;\n\t\t\t// Get rules for from \"out\" and to \"in\"\n\t\t\tvar dr1 = this.facade.getRules().getLayoutingRules(from, edge)[\"out\"];\n\t\t\tvar dr2 = this.facade.getRules().getLayoutingRules(to, edge)[\"in\"];\n\n\t\t\tvar fromWeight = dr1[d1];\n\t\t\tvar toWeight = dr2[d2];\n\n\n\t\t\t/**\n\t\t\t * Return a true if the center 1 is in the same direction than center 2\n\t\t\t * @param {Object} direction\n\t\t\t * @param {Object} center1\n\t\t\t * @param {Object} center2\n\t\t\t */\n\t\t\tvar sameDirection = function(direction, center1, center2){\n\t\t\t\tswitch(direction){\n\t\t\t\t\tcase \"t\": return Math.abs(center1.x - center2.x) < 2 && center1.y < center2.y\n\t\t\t\t\tcase \"r\": return center1.x > center2.x && Math.abs(center1.y - center2.y) < 2\n\t\t\t\t\tcase \"b\": return Math.abs(center1.x - center2.x) < 2 && center1.y > center2.y\n\t\t\t\t\tcase \"l\": return center1.x < center2.x && Math.abs(center1.y - center2.y) < 2\n\t\t\t\t\tdefault: return false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check if there are same incoming edges from 'from'\n\t\t\tvar sameIncomingFrom = from\n\t\t\t\t\t\t\t\t.getIncomingShapes()\n\t\t\t\t\t\t\t\t.findAll(function(a){ return a instanceof ORYX.Core.Edge})\n\t\t\t\t\t\t\t\t.any(function(e){ \n\t\t\t\t\t\t\t\t\treturn sameDirection(d1, e.dockers[e.dockers.length-2].bounds.center(), e.dockers.last().bounds.center());\n\t\t\t\t\t\t\t\t});\n\n\t\t\t// Check if there are same outgoing edges from 'to'\n\t\t\tvar sameOutgoingTo = to\n\t\t\t\t\t\t\t\t.getOutgoingShapes()\n\t\t\t\t\t\t\t\t.findAll(function(a){ return a instanceof ORYX.Core.Edge})\n\t\t\t\t\t\t\t\t.any(function(e){ \n\t\t\t\t\t\t\t\t\treturn sameDirection(d2, e.dockers[1].bounds.center(), e.dockers.first().bounds.center());\n\t\t\t\t\t\t\t\t});\n\t\t\t\n\t\t\t// If there are equivalent edges, set 0\n\t\t\t//fromWeight = sameIncomingFrom ? 0 : fromWeight;\n\t\t\t//toWeight = sameOutgoingTo ? 0 : toWeight;\n\t\t\t\n\t\t\t// Get the sum of \"out\" and the direction plus \"in\" and the direction \t\t\t\t\t\t\n\t\t\treturn (sameIncomingFrom||sameOutgoingTo?0:fromWeight+toWeight);\n\t\t},\n\t\t\n\t\t/**\n\t\t * Removes all current dockers from the node \n\t\t * (except the start and end) and adds two new\n\t\t * dockers, on the position a and b.\n\t\t * @param {Object} edge\n\t\t * @param {Object} a\n\t\t * @param {Object} b\n\t\t */\n\t\tsetDockers: function(edge, a, b){\n\t\t\tif (!edge){ return }\n\t\t\t\n\t\t\t// Remove all dockers (implicit,\n\t\t\t// start and end dockers will not removed)\n\t\t\tedge.dockers.each(function(r){\n\t\t\t\tedge.removeDocker(r);\n\t\t\t});\n\t\t\t\n\t\t\t// For a and b (if exists), create\n\t\t\t// a new docker and set position\n\t\t\t[a, b].compact().each(function(pos){\n\t\t\t\tvar docker = edge.createDocker(undefined, pos);\n\t\t\t\tdocker.bounds.centerMoveTo(pos);\n\t\t\t});\n\t\t\t\n\t\t\t// Update all dockers from the edge\n\t\t\tedge.dockers.each(function(docker){\n\t\t\t\tdocker.update()\n\t\t\t})\n\t\t\t\n\t\t\t// Update edge\n\t\t\t//edge.refresh();\n\t\t\tedge._update(true);\n\t\t\t\n\t\t}\n\t});\n\t\n\t\n}()\n/*\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * License rights for this program may be obtained from Alfresco Software, Ltd.\n * pursuant to a written agreement and any use of this program without such an\n * agreement is prohibited.\n */\n/*\n * All code Copyright 2013 KIS Consultancy all rights reserved\n */\n\nif(!ORYX.Plugins)\n\tORYX.Plugins = new Object();\n\nnew function(){\n\t\n\tORYX.Plugins.BPMN2_0 = {\n\t\n\t\t/**\n\t\t *\tConstructor\n\t\t *\t@param {Object} Facade: The Facade of the Editor\n\t\t */\n\t\tconstruct: function(facade){\n\t\t\tthis.facade = facade;\n\t\t\t\n\t\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_DRAGDOCKER_DOCKED, this.handleDockerDocked.bind(this));\n\t\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_PROPWINDOW_PROP_CHANGED, this.handlePropertyChanged.bind(this));\n\t\t\tthis.facade.registerOnEvent('layout.bpmn2_0.pool', this.handleLayoutPool.bind(this));\n\t\t\tthis.facade.registerOnEvent('layout.bpmn2_0.subprocess', this.handleSubProcess.bind(this));\n\t\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_SHAPEREMOVED, this.handleShapeRemove.bind(this));\n\t\t\t\n\t\t\tthis.facade.registerOnEvent(ORYX.CONFIG.EVENT_LOADED, this.afterLoad.bind(this));\n\t\t\t\n\n\t\t\tthis.namespace = undefined;\n\t\t},\n\t\t\n\t\t/**\n         * Force to update every pool\n         */\n        afterLoad: function(){\n                this.facade.getCanvas().getChildNodes().each(function(shape){\n                        if (shape.getStencil().id().endsWith(\"Pool\")) {\n                                this.handleLayoutPool({\n                                        shape: shape\n                                });\n                        }\n                }.bind(this))\n        },\n       \n        /**\n         * If a pool is selected and contains no lane,\n         * a lane is created automagically\n         */\n        onSelectionChanged: function(event) {\n                var selection = event.elements;\n               \n                if(selection && selection.length === 1) {\n                        var namespace = this.getNamespace();\n                        var shape = selection[0];\n                        if(shape.getStencil().idWithoutNs() === \"Pool\") {\n                                if(shape.getChildNodes().length === 0) {\n                                        // create a lane inside the selected pool\n                                        var option = {\n                                                        type:namespace + \"Lane\",\n                                                        position:{x:0,y:0},\n                                                        namespace:shape.getStencil().namespace(),\n                                                        parent:shape\n                                        };\n                                        this.facade.createShape(option);\n                                        this.facade.getCanvas().update();\n                                        this.facade.setSelection([shape]);\n                                }\n                        }\n                }\n               \n                // Preventing selection of all lanes but not the pool\n                if(selection.any(function(s){ return s instanceof ORYX.Core.Node && s.getStencil().id().endsWith(\"Lane\")})){\n                        var lanes = selection.findAll(function(s){\n                                return s instanceof ORYX.Core.Node && s.getStencil().id().endsWith(\"Lane\")\n                        });\n                       \n                        var pools = [];\n                        var unselectLanes = [];\n                        lanes.each(function(lane){\n                                pools.push(this.getParentPool(lane))\n                        }.bind(this));\n                       \n                        pools = pools.uniq().findAll(function(pool){\n                                var childLanes = this.getLanes(pool, true);\n                                if (childLanes.all(function(lane){ return lanes.include(lane)})){\n                                        unselectLanes = unselectLanes.concat(childLanes);\n                                        return true;\n                                } else if (selection.include(pool) && childLanes.any(function(lane){ return lanes.include(lane)})) {\n                                        unselectLanes = unselectLanes.concat(childLanes);\n                                        return true;\n                                } else {\n                                        return false;\n                                }\n                        }.bind(this))\n                       \n                        if (unselectLanes.length > 0 && pools.length > 0){\n                                selection = selection.without.apply(selection, unselectLanes);\n                                selection = selection.concat(pools);\n                                this.facade.setSelection(selection.uniq());\n                        }\n                }\n        },\n       \n        handleShapeRemove: function(option) {\n               \n                var sh                          = option.shape;\n                var parent                      = option.parent;\n                                       \n                if (sh instanceof ORYX.Core.Node && sh.getStencil().idWithoutNs() === \"Lane\" && this.facade.isExecutingCommands()) {\n               \n                        var pool = this.getParentPool(parent);\n                        if (pool&&pool.parent){        \n                       \n                                var isLeafFn = function(leaf){\n                                        return !leaf.getChildNodes().any(function(r){ return r.getStencil().idWithoutNs() === \"Lane\"});\n                                }\n                               \n                                var isLeaf = isLeafFn(sh);\n                                var parentHasMoreLanes = parent.getChildNodes().any(function(r){ return r.getStencil().idWithoutNs() === \"Lane\"});\n                               \n                                if (isLeaf && parentHasMoreLanes){\n                                       \n                                        var command = new ResizeLanesCommand(sh, parent, pool, this);\n                                        this.facade.executeCommands([command]);\n                                       \n                                } else if(      !isLeaf &&\n                                                        !this.facade.getSelection().any(function(select){ // Find one of the selection, which is a lane and child of \"sh\" and is a leaf lane\n                                                                        return  select instanceof ORYX.Core.Node && select.getStencil().idWithoutNs() === \"Lane\" &&\n                                                                                        select.isParent(sh) && isLeafFn(select);})) {\n                                                                                               \n                                        var Command = ORYX.Core.Command.extend({\n                                                construct: function(shape, facade) {\n                                                        this.children = shape.getChildNodes(true);\n                                                        this.facade = facade;\n                                                },\n                                                execute: function() {\n                                                        this.children.each(function(child){\n                                                                child.bounds.moveBy(30,0)\n                                                        });\n                                                        //this.facade.getCanvas().update();\n                                                },\n                                                rollback: function() {\n                                                        this.children.each(function(child){\n                                                                child.bounds.moveBy(-30,0)\n                                                        })\n                                                        //this.facade.getCanvas().update();\n                                                }\n                                        });\n                                        this.facade.executeCommands([new Command(sh, this.facade)]);\n                                       \n                                } else if (isLeaf&&!parentHasMoreLanes&&parent == pool){\n                                        parent.add(sh);\n                                }\n                        }\n               \n                }\n               \n        },\n\n\t\t\n\t\thashedSubProcesses: {},\n\t\t\n\t\thashChildShapes: function(shape){\n\t\t\tvar children = shape.getChildNodes();\n\t\t\tchildren.each(function(child){\n\t\t\t\tif (this.hashedSubProcesses[child.id]){\n\t\t\t\t\tthis.hashedSubProcesses[child.id] = child.absoluteXY();\n\t\t\t\t\tthis.hashedSubProcesses[child.id].width \t= child.bounds.width();\n\t\t\t\t\tthis.hashedSubProcesses[child.id].height \t= child.bounds.height();\n\t\t\t\t\tthis.hashChildShapes(child);\n\t\t\t\t}\n\t\t\t}.bind(this));\n\t\t},\n\t\n\t\t/**\n\t\t * Handle the layouting of a sub process.\n\t\t * Mainly to adjust the child dockers of a sub process. \n\t\t *\n\t\t */\n\t\thandleSubProcess : function(option) {\n\t\t\t\n\t\t\tvar sh = option.shape;\n\t\t\t\n\t\t\tif (!this.hashedSubProcesses[sh.id]) {\n\t\t\t\tthis.hashedSubProcesses[sh.id] = sh.absoluteXY();\n\t\t\t\tthis.hashedSubProcesses[sh.id].width \t= sh.bounds.width();\n\t\t\t\tthis.hashedSubProcesses[sh.id].height \t= sh.bounds.height();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\tvar offset = sh.absoluteXY();\n\t\t\toffset.x -= this.hashedSubProcesses[sh.id].x;\n\t\t\toffset.y -= this.hashedSubProcesses[sh.id].y;\n\t\t\t\n\t\t\tvar resized = this.hashedSubProcesses[sh.id].width !== sh.bounds.width() || this.hashedSubProcesses[sh.id].height !== sh.bounds.height();\n\t\t\t\n\t\t\tthis.hashedSubProcesses[sh.id] = sh.absoluteXY();\n\t\t\tthis.hashedSubProcesses[sh.id].width \t= sh.bounds.width();\n\t\t\tthis.hashedSubProcesses[sh.id].height \t= sh.bounds.height();\n\t\t\tthis.hashChildShapes(sh);\n\t\t\t\n\t\t\t\n\t\t\t// Move dockers only if currently is not resizing\n\t\t\tif (this.facade.isExecutingCommands()&&!resized) {\n\t\t\t\tthis.moveChildDockers(sh, offset);\n\t\t\t}\n\t\t},\n\t\t\n\t\tmoveChildDockers: function(shape, offset){\n\t\t\t\n\t\t\tif (!offset.x && !offset.y) {\n\t\t\t\treturn;\n\t\t\t} \n\t\t\t\n\t\t\tvar children = shape.getChildNodes(true);\n\t\t\t\n\t\t\t// Get all nodes\n\t\t\tvar dockers = children\n\t\t\t\t// Get all incoming and outgoing edges\n\t\t\t\t.map(function(node){\n\t\t\t\t\treturn [].concat(node.getIncomingShapes())\n\t\t\t\t\t\t\t.concat(node.getOutgoingShapes())\n\t\t\t\t})\n\t\t\t\t// Flatten all including arrays into one\n\t\t\t\t.flatten()\n\t\t\t\t// Get every edge only once\n\t\t\t\t.uniq()\n\t\t\t\t// Get all dockers\n\t\t\t\t.map(function(edge){\n\t\t\t\t\treturn edge.dockers.length > 2 ? \n\t\t\t\t\t\t\tedge.dockers.slice(1, edge.dockers.length-1) : \n\t\t\t\t\t\t\t[];\n\t\t\t\t})\n\t\t\t\t// Flatten the dockers lists\n\t\t\t\t.flatten();\n\t\n\t\t\tvar abs = shape.absoluteBounds();\n\t\t\tabs.moveBy(-offset.x, -offset.y)\n\t\t\tvar obj = {};\n\t\t\tdockers.each(function(docker){\n\t\t\t\t\n\t\t\t\tif (docker.isChanged){\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tvar off = Object.clone(offset);\n\t\t\t\t\n\t\t\t\tif (!abs.isIncluded(docker.bounds.center())){\n\t\t\t\t\tvar index \t= docker.parent.dockers.indexOf(docker);\n\t\t\t\t\tvar size\t= docker.parent.dockers.length;\n\t\t\t\t\tvar from \t= docker.parent.getSource();\n\t\t\t\t\tvar to \t\t= docker.parent.getTarget();\n\t\t\t\t\t\n\t\t\t\t\tvar bothAreIncluded = children.include(from) && children.include(to);\n\t\t\t\t\t\n\t\t\t\t\tif (!bothAreIncluded){\n\t\t\t\t\t\tvar previousIsOver = index !== 0 ? abs.isIncluded(docker.parent.dockers[index-1].bounds.center()) : false;\n\t\t\t\t\t\tvar nextIsOver = index !== size-1 ? abs.isIncluded(docker.parent.dockers[index+1].bounds.center()) : false;\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (!previousIsOver && !nextIsOver){ return; }\n\t\t\t\t\t\t\n\t\t\t\t\t\tvar ref = docker.parent.dockers[previousIsOver ? index-1 : index+1];\n\t\t\t\t\t\tif (Math.abs(-Math.abs(ref.bounds.center().x-docker.bounds.center().x)) < 2){\n\t\t\t\t\t\t\toff.y = 0;\n\t\t\t\t\t\t} else if(Math.abs(-Math.abs(ref.bounds.center().y-docker.bounds.center().y)) < 2){\n\t\t\t\t\t\t\toff.x = 0;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tobj[docker.getId()] = {\n\t\t\t\t\tdocker:docker,\n\t\t\t\t\toffset:off\n\t\t\t\t}\n\t\t\t})\n\t\t\t\n\t\t\t// Set dockers\n\t\t\tthis.facade.executeCommands([new ORYX.Core.MoveDockersCommand(obj)]);\n\t\t\t\t\n\t\t},\n\t\t\n\t\t/**\n\t\t * DragDocker.Docked Handler\n\t\t *\n\t\t */\t\n\t\thandleDockerDocked: function(options) {\n\t\t\tvar namespace = this.getNamespace();\n\t\t\t\n\t\t\tvar edge = options.parent;\n\t\t\tvar edgeSource = options.target;\n\t\t\t\n\t\t\tif(edge.getStencil().id() === namespace + \"SequenceFlow\") {\n\t\t\t\tvar isGateway = edgeSource.getStencil().groups().find(function(group) {\n\t\t\t\t\t\tif(group == \"Gateways\") \n\t\t\t\t\t\t\treturn group;\n\t\t\t\t\t});\n\t\t\t\tif(!isGateway && (edge.properties[\"oryx-conditiontype\"] == \"Expression\"))\n\t\t\t\t\t// show diamond on edge source\n\t\t\t\t\tedge.setProperty(\"oryx-showdiamondmarker\", true);\n\t\t\t\telse \n\t\t\t\t\t// do not show diamond on edge source\n\t\t\t\t\tedge.setProperty(\"oryx-showdiamondmarker\", false);\n\t\t\t\t\n\t\t\t\t// update edge rendering\n\t\t\t\t//edge.update();\n\t\t\t\t\n\t\t\t\tthis.facade.getCanvas().update();\n\t\t\t}\n\t\t},\n\t\t\n\t\t/**\n\t\t * PropertyWindow.PropertyChanged Handler\n\t\t */\n\t\thandlePropertyChanged: function(option) {\n\t\t\tvar namespace = this.getNamespace();\n\t\t\t\n\t\t\tvar shapes = option.elements;\n\t\t\tvar propertyKey = option.key;\n\t\t\tvar propertyValue = option.value;\n\t\t\t\n\t\t\tvar changed = false;\n\t\t\tshapes.each(function(shape){\n\t\t\t\tif((shape.getStencil().id() === namespace + \"SequenceFlow\") &&\n\t\t\t\t\t(propertyKey === \"oryx-conditiontype\")) {\n\t\t\t\t\t\n\t\t\t\t\tif(propertyValue != \"Expression\")\n\t\t\t\t\t\t// Do not show the Diamond\n\t\t\t\t\t\tshape.setProperty(\"oryx-showdiamondmarker\", false);\n\t\t\t\t\telse {\n\t\t\t\t\t\tvar incomingShapes = shape.getIncomingShapes();\n\t\t\t\t\t\t\n\t\t\t\t\t\tif(!incomingShapes) {\n\t\t\t\t\t\t\tshape.setProperty(\"oryx-showdiamondmarker\", true);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tvar incomingGateway = incomingShapes.find(function(aShape) {\n\t\t\t\t\t\t\tvar foundGateway = aShape.getStencil().groups().find(function(group) {\n\t\t\t\t\t\t\t\tif(group == \"Gateways\") \n\t\t\t\t\t\t\t\t\treturn group;\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif(foundGateway)\n\t\t\t\t\t\t\t\treturn foundGateway;\n\t\t\t\t\t\t});\n\t\t\t\t\t\t\n\t\t\t\t\t\tif(!incomingGateway) \n\t\t\t\t\t\t\t// show diamond on edge source\n\t\t\t\t\t\t\tshape.setProperty(\"oryx-showdiamondmarker\", true);\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\t// do not show diamond\n\t\t\t\t\t\t\tshape.setProperty(\"oryx-showdiamondmarker\", false);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tchanged = true;\n\t\t\t\t}\n\t\t\t}.bind(this));\n\t\t\t\n\t\t\tif(changed) {this.facade.getCanvas().update();}\n\t\t\t\n\t\t},\n\t\t\n\t\thashedPoolPositions : {},\n\t\thashedLaneDepth : {},\n\t\thashedBounds : {},\n\t\thashedPositions: {},\n\t\t\n\t\t/**\n         * Handler for layouting event 'layout.bpmn2_0.pool'\n         * @param {Object} event\n         */\n        handleLayoutPool: function(event){\n               \n               \n                var pool = event.shape;\n                var selection = this.facade.getSelection();\n                var currentShape = selection.include(pool) ? pool : selection.first();\n               \n                currentShape = currentShape || pool;\n               \n                this.currentPool = pool;\n               \n                // Check if it is a pool or a lane\n                if (!(currentShape.getStencil().id().endsWith(\"Pool\") || currentShape.getStencil().id().endsWith(\"Lane\"))) {\n                        return;\n                }\n               \n                // Check if the lane is within the pool and is not removed lately\n                if (currentShape !== pool && !currentShape.isParent(pool) && !this.hashedBounds[pool.id][currentShape.id]){\n                        return;\n                }\n               \n               \n                if (!this.hashedBounds[pool.id]) {\n                        this.hashedBounds[pool.id] = {};\n                }\n               \n                // Find all child lanes\n                var lanes = this.getLanes(pool);\n               \n                if (lanes.length <= 0) {\n                        return\n                }\n               \n                var allLanes = this.getLanes(pool, true), hp;\n                var considerForDockers = allLanes.clone();\n               \n                var hashedPositions = $H({});\n                allLanes.each(function(lane){\n                        hashedPositions[lane.id] = lane.bounds.upperLeft();\n                })\n               \n               \n               \n                // Show/hide caption regarding the number of lanes\n                if (lanes.length === 1 && this.getLanes(lanes.first()).length <= 0) {\n                        // TRUE if there is a caption\n                        lanes.first().setProperty(\"oryx-showcaption\", lanes.first().properties[\"oryx-name\"].trim().length > 0);\n                        var rect = lanes.first().node.getElementsByTagName(\"rect\");\n                        rect[0].setAttributeNS(null, \"display\", \"none\");\n                } else {\n                        allLanes.invoke(\"setProperty\", \"oryx-showcaption\", true);\n                        allLanes.each(function(lane){\n                                var rect = lane.node.getElementsByTagName(\"rect\");\n                                rect[0].removeAttributeNS(null, \"display\");\n                        })\n                }\n               \n                var deletedLanes = [];\n                var addedLanes = [];\n               \n                // Get all new lanes\n                var i=-1;\n                while (++i<allLanes.length) {\n                        if (!this.hashedBounds[pool.id][allLanes[i].id]){\n                                addedLanes.push(allLanes[i])\n                        }\n                }\n               \n                if (addedLanes.length > 0){\n                        currentShape = addedLanes.first();\n                }\n               \n               \n                // Get all deleted lanes\n                var resourceIds = $H(this.hashedBounds[pool.id]).keys();\n                var i=-1;\n                while (++i<resourceIds.length) {\n                        if (!allLanes.any(function(lane){ return lane.id == resourceIds[i]})){\n                                deletedLanes.push(this.hashedBounds[pool.id][resourceIds[i]]);\n                                selection = selection.without(function(r){ return r.id == resourceIds[i] });\n                        }\n                }              \n               \n                var height, width, x, y;\n               \n                if (deletedLanes.length > 0 || addedLanes.length > 0) {\n                       \n                        if (addedLanes.length === 1 && this.getLanes(addedLanes[0].parent).length === 1){\n                                // Set height from the pool\n                                height = this.adjustHeight(lanes, addedLanes[0].parent);\n                        } else {\n                                // Set height from the pool\n                                height = this.updateHeight(pool);\n                        }\n                        // Set width from the pool\n                        width = this.adjustWidth(lanes, pool.bounds.width());  \n                       \n                        pool.update();\n                }\n               \n                /**\n                 * Set width/height depending on the pool\n                 */\n                else if (pool == currentShape) {\n                       \n                        if (selection.length === 1 && this.isResized(pool, this.hashedPoolPositions[pool.id])) {\n                                var oldXY = this.hashedPoolPositions[pool.id].upperLeft();\n                                var xy = pool.bounds.upperLeft();\n                                var scale = 0;\n                                if (this.shouldScale(pool)){\n                                        var old = this.hashedPoolPositions[pool.id];\n                                        scale = old.height()/pool.bounds.height();\n                                }\n                       \n                                this.adjustLanes(pool, allLanes, oldXY.x - xy.x, oldXY.y - xy.y, scale);\n                        }\n                       \n                        // Set height from the pool\n                        height = this.adjustHeight(lanes, undefined, pool.bounds.height());\n                        // Set width from the pool\n                        width = this.adjustWidth(lanes, pool.bounds.width());          \n                }\n               \n                /**???\n                 * Set width/height depending on containing lanes\n                 */            \n                else {\n                       \n                        // Reposition the pool if one shape is selected and the upperleft has changed\n                        if (selection.length === 1 && this.isResized(currentShape, this.hashedBounds[pool.id][currentShape.id])){\n                                var oldXY = this.hashedBounds[pool.id][currentShape.id].upperLeft();\n                                var xy = currentShape.absoluteXY();\n                                x = oldXY.x - xy.x;\n                                y = oldXY.y - xy.y;\n                               \n                                // Adjust all other lanes beneath this lane\n                                if (x||y){\n                                        considerForDockers = considerForDockers.without(currentShape);\n                                        this.adjustLanes(pool, this.getAllExcludedLanes(pool, currentShape), x, 0);\n                                }\n                               \n                                // Adjust all child lanes\n                                var childLanes = this.getLanes(currentShape, true);\n                                if (childLanes.length > 0){\n                                        if (this.shouldScale(currentShape)){\n                                                var old = this.hashedBounds[pool.id][currentShape.id];\n                                                var scale = old.height()/currentShape.bounds.height();\n                                                this.adjustLanes(pool, childLanes, x, y, scale);\n                                        } else {\n                                                this.adjustLanes(pool, childLanes, x, y, 0);\n                                        }\n                                }\n                        }\n                       \n                        // Cache all bounds\n                        var changes = allLanes.map(function(lane){ return {\n                                shape: lane,\n                                bounds: lane.bounds.clone()\n                        } });\n                       \n                        // Get height and adjust child heights\n                        height = this.adjustHeight(lanes, currentShape);\n                        // Check if something has changed and maybe create a command\n                        this.checkForChanges(allLanes, changes);\n                       \n                        // Set width from the current shape\n                        width = this.adjustWidth(lanes, currentShape.bounds.width()+(this.getDepth(currentShape,pool)*30));\n                }\n               \n                this.setDimensions(pool, width, height, x, y);\n               \n               \n                if (this.facade.isExecutingCommands() && (deletedLanes.length === 0 || addedLanes.length !== 0)){\n                        // Update all dockers\n                        this.updateDockers(considerForDockers, pool);\n                       \n                        // Check if the order has changed\n                        if (this.hashedPositions[pool.id] && this.hashedPositions[pool.id].keys().any(function(key, i){\n                                        return (allLanes[i]||{}).id     !== key;\n                                })){\n                               \n                                var LanesHasBeenReordered = ORYX.Core.Command.extend({\n                                        construct: function(originPosition, newPosition, lanes, plugin, poolId) {\n                                                this.originPosition = Object.clone(originPosition);\n                                                this.newPosition = Object.clone(newPosition);\n                                                this.lanes = lanes;\n                                                this.plugin = plugin;\n                                                this.pool = poolId;\n                                        },\n                                        execute: function(){\n                                                if (!this.executed){\n                                                        this.executed = true;\n                                                        this.lanes.each(function(lane){\n                                                                if (this.newPosition[lane.id])\n                                                                        lane.bounds.moveTo(this.newPosition[lane.id])\n                                                        }.bind(this));\n                                                        this.plugin.hashedPositions[this.pool] = Object.clone(this.newPosition);\n                                                }\n                                        },\n                                        rollback: function(){\n                                                this.lanes.each(function(lane){\n                                                        if (this.originPosition[lane.id])\n                                                                lane.bounds.moveTo(this.originPosition[lane.id])\n                                                }.bind(this));\n                                                this.plugin.hashedPositions[this.pool] = Object.clone(this.originPosition);\n                                        }\n                                });\n                               \n                                var hp2 = $H({});\n                                allLanes.each(function(lane){\n                                        hp2[lane.id] = lane.bounds.upperLeft();\n                                })\n                       \n                                var command = new LanesHasBeenReordered(hashedPositions, hp2, allLanes, this, pool.id);\n                                this.facade.executeCommands([command]);\n                                       \n                        }\n                }\n               \n                this.hashedBounds[pool.id] = {};\n                this.hashedPositions[pool.id] = hashedPositions;\n               \n                var i=-1;\n                while (++i < allLanes.length) {\n                        // Cache positions\n                        this.hashedBounds[pool.id][allLanes[i].id] = allLanes[i].absoluteBounds();\n                       \n                        // Cache also the bounds of child shapes, mainly for child subprocesses\n                        this.hashChildShapes(allLanes[i]);\n               \n                        this.hashedLaneDepth[allLanes[i].id] = this.getDepth(allLanes[i], pool);\n                       \n                        this.forceToUpdateLane(allLanes[i]);\n                }\n               \n                this.hashedPoolPositions[pool.id] = pool.bounds.clone();\n               \n               \n                // Update selection\n                //this.facade.setSelection(selection);          \n        },\n       \n        shouldScale: function(element){\n                var childLanes = element.getChildNodes().findAll(function(shape){ return shape.getStencil().id().endsWith(\"Lane\") })\n                return childLanes.length > 1 || childLanes.any(function(lane){ return this.shouldScale(lane) }.bind(this))\n        },\n       \n        /**\n         * Lookup if some bounds has changed\n         * @param {Object} lanes\n         * @param {Object} changes\n         */\n        checkForChanges: function(lanes, changes){\n                // Check if something has changed\n                if (this.facade.isExecutingCommands() && changes.any(function(change){\n                        return change.shape.bounds.toString() !== change.bounds.toString();\n                })){\n                       \n                        var Command = ORYX.Core.Command.extend({\n                                                construct: function(changes) {\n                                                        this.oldState = changes;\n                                                        this.newState = changes.map(function(s){ return {shape:s.shape, bounds:s.bounds.clone()}});\n                                                },\n                                                execute: function(){\n                                                        if (this.executed){\n                                                                this.applyState(this.newState);\n                                                        }\n                                                        this.executed = true;\n                                                },\n                                                rollback: function(){\n                                                        this.applyState(this.oldState);\n                                                },\n                                                applyState: function(state){\n                                                        state.each(function(s){\n                                                                s.shape.bounds.set(s.bounds.upperLeft(), s.bounds.lowerRight());\n                                                        })\n                                                }\n                                        });\n                                       \n                        this.facade.executeCommands([new Command(changes)]);\n                }\n        },\n       \n        isResized: function(shape, bounds){\n               \n                if (!bounds||!shape){\n                        return false;\n                }\n               \n                var oldB = bounds;\n                //var oldXY = oldB.upperLeft();\n                //var xy = shape.absoluteXY();\n                return Math.round(oldB.width() - shape.bounds.width()) !== 0 || Math.round(oldB.height() - shape.bounds.height()) !== 0\n        },\n       \n        adjustLanes: function(pool, lanes, x, y, scale){\n               \n                scale = scale || 0;\n\n                // For every lane, adjust the child nodes with the offset\n                lanes.each(function(l){\n                        l.getChildNodes().each(function(child){\n                                if (!child.getStencil().id().endsWith(\"Lane\")){\n                                        var cy = scale ? child.bounds.center().y - (child.bounds.center().y/scale) : -y;\n                                        child.bounds.moveBy((x||0), -cy);\n                                       \n                                        if (scale&&child.getStencil().id().endsWith(\"Subprocess\")) {\n                                                this.moveChildDockers(child, {x:(0), y:-cy});\n                                        }\n                               \n                                }\n                        }.bind(this));\n                        this.hashedBounds[pool.id][l.id].moveBy(-(x||0), !scale?-y:0);\n                        if (scale) {\n                                l.isScaled = true;\n                        }\n                }.bind(this))\n               \n        },\n       \n        getAllExcludedLanes: function(parent, lane){\n                var lanes = [];\n                parent.getChildNodes().each(function(shape){\n                        if ((!lane || shape !== lane) && shape.getStencil().id().endsWith(\"Lane\")){\n                                lanes.push(shape);\n                                lanes = lanes.concat(this.getAllExcludedLanes(shape, lane));\n                        }\n                }.bind(this));\n                return lanes;\n        },\n       \n       \n        forceToUpdateLane: function(lane){\n               \n                if (lane.bounds.height() !== lane._svgShapes[0].height) {      \n                        lane.isChanged = true;\n                        lane.isResized = true;\n                        lane._update();\n                }\n        },\n       \n        getDepth: function(child, parent){\n               \n                var i=0;\n                while(child && child.parent && child !== parent){\n                        child = child.parent;\n                        ++i\n                }\n                return i;\n        },\n       \n        updateDepth: function(lane, fromDepth, toDepth){\n               \n                var xOffset = (fromDepth - toDepth) * 30;\n               \n                lane.getChildNodes().each(function(shape){\n                        shape.bounds.moveBy(xOffset, 0);\n                       \n                        [].concat(children[j].getIncomingShapes())\n                                        .concat(children[j].getOutgoingShapes())\n                                       \n                })\n               \n        },\n       \n        setDimensions: function(shape, width, height, x, y){\n                var isLane = shape.getStencil().id().endsWith(\"Lane\");\n                // Set the bounds\n                shape.bounds.set(\n                                isLane  ? 30 : (shape.bounds.a.x - (x || 0)),\n                                isLane  ? shape.bounds.a.y : (shape.bounds.a.y - (y || 0)),\n                                width   ? shape.bounds.a.x + width - (isLane?30:(x||0)) : shape.bounds.b.x,\n                                height  ? shape.bounds.a.y + height - (isLane?0:(y||0)) : shape.bounds.b.y\n                        );\n        },\n\n        setLanePosition: function(shape, y){\n               \n                shape.bounds.moveTo(30, y);\n       \n        },\n               \n        adjustWidth: function(lanes, width) {\n               \n                // Set width to each lane\n                (lanes||[]).each(function(lane){\n                        this.setDimensions(lane, width);\n                        this.adjustWidth(this.getLanes(lane), width-30);\n                }.bind(this));\n               \n                return width;\n        },\n       \n       \n        adjustHeight: function(lanes, changedLane, propagateHeight){\n               \n                var oldHeight = 0;\n                if (!changedLane && propagateHeight){\n                        var i=-1;\n                        while (++i<lanes.length){      \n                                oldHeight += lanes[i].bounds.height();          \n                        }\n                }\n               \n                var i=-1;\n                var height = 0;\n               \n                // Iterate trough every lane\n                while (++i<lanes.length){\n                       \n                        if (lanes[i] === changedLane) {\n                                // Propagate new height down to the children\n                                this.adjustHeight(this.getLanes(lanes[i]), undefined, lanes[i].bounds.height());\n                               \n                                lanes[i].bounds.set({x:30, y:height}, {x:lanes[i].bounds.width()+30, y:lanes[i].bounds.height()+height})\n                                                               \n                        } else if (!changedLane && propagateHeight) {\n                               \n                                var tempHeight = (lanes[i].bounds.height() * propagateHeight) / oldHeight;\n                                // Propagate height\n                                this.adjustHeight(this.getLanes(lanes[i]), undefined, tempHeight);\n                                // Set height propotional to the propagated and old height\n                                this.setDimensions(lanes[i], null, tempHeight);\n                                this.setLanePosition(lanes[i], height);\n                        } else {\n                                // Get height from children\n                                var tempHeight = this.adjustHeight(this.getLanes(lanes[i]), changedLane, propagateHeight);\n                                if (!tempHeight) {\n                                        tempHeight = lanes[i].bounds.height();\n                                }\n                                this.setDimensions(lanes[i], null, tempHeight);\n                                this.setLanePosition(lanes[i], height);\n                        }\n                       \n                        height += lanes[i].bounds.height();\n                }\n               \n                return height;\n               \n        },\n       \n       \n        updateHeight: function(root){\n               \n                var lanes = this.getLanes(root);\n               \n                if (lanes.length == 0){\n                        return root.bounds.height();\n                }\n               \n                var height = 0;\n                var i=-1;\n                while (++i < lanes.length) {\n                        this.setLanePosition(lanes[i], height);\n                        height += this.updateHeight(lanes[i]);\n                }\n               \n                this.setDimensions(root, null, height);\n               \n                return height;\n        },\n       \n        getOffset: function(lane, includePool, pool){\n               \n                var offset = {x:0,y:0};\n               \n               \n                /*var parent = lane;\n                 while(parent) {\n                                               \n                       \n                        var offParent = this.hashedBounds[pool.id][parent.id] ||(includePool === true ? this.hashedPoolPositions[parent.id] : undefined);\n                        if (offParent){\n                                var ul = parent.bounds.upperLeft();\n                                var ulo = offParent.upperLeft();\n                                offset.x += ul.x-ulo.x;\n                                offset.y += ul.y-ulo.y;\n                        }\n                       \n                        if (parent.getStencil().id().endsWith(\"Pool\")) {\n                                break;\n                        }\n                       \n                        parent = parent.parent;\n                }       */\n               \n                var offset = lane.absoluteXY();\n               \n                var hashed = this.hashedBounds[pool.id][lane.id] ||(includePool === true ? this.hashedPoolPositions[lane.id] : undefined);\n                if (hashed) {\n                        offset.x -= hashed.upperLeft().x;      \n                        offset.y -= hashed.upperLeft().y;              \n                } else {\n                        return {x:0,y:0}\n                }              \n                return offset;\n        },\n       \n        getNextLane: function(shape){\n                while(shape && !shape.getStencil().id().endsWith(\"Lane\")){\n                        if (shape instanceof ORYX.Core.Canvas) {\n                                return null;\n                        }\n                        shape = shape.parent;\n                }\n                return shape;\n        },\n       \n        getParentPool: function(shape){\n                while(shape && !shape.getStencil().id().endsWith(\"Pool\")){\n                        if (shape instanceof ORYX.Core.Canvas) {\n                                return null;\n                        }\n                        shape = shape.parent;\n                }\n                return shape;\n        },\n       \n        updateDockers: function(lanes, pool){\n               \n                var absPool = pool.absoluteBounds(), movedShapes = [];\n                var oldPool = (this.hashedPoolPositions[pool.id]||absPool).clone();\n               \n                var i=-1, j=-1, k=-1, l=-1, docker;\n                var dockers = {};\n               \n                while (++i < lanes.length) {\n                       \n                        if (!this.hashedBounds[pool.id][lanes[i].id]) {\n                                continue;\n                        }\n                       \n                        var isScaled = lanes[i].isScaled;\n                        delete lanes[i].isScaled;\n                        var children = lanes[i].getChildNodes();\n                        var absBounds = lanes[i].absoluteBounds();\n                        var oldBounds = (this.hashedBounds[pool.id][lanes[i].id]||absBounds);\n                        //oldBounds.moveBy((absBounds.upperLeft().x-lanes[i].bounds.upperLeft().x), (absBounds.upperLeft().y-lanes[i].bounds.upperLeft().y));\n                        var offset = this.getOffset(lanes[i], true, pool);\n                        var xOffsetDepth = 0;\n\n                        var depth = this.getDepth(lanes[i], pool);\n                        if ( this.hashedLaneDepth[lanes[i].id] !== undefined &&  this.hashedLaneDepth[lanes[i].id] !== depth) {\n                                xOffsetDepth = (this.hashedLaneDepth[lanes[i].id] - depth) * 30;\n                                offset.x += xOffsetDepth;\n                        }\n                       \n                        j=-1;\n                       \n                        while (++j < children.length) {\n                               \n                                if (xOffsetDepth && !children[j].getStencil().id().endsWith(\"Lane\")) {\n                                        movedShapes.push({xOffset:xOffsetDepth, shape: children[j]});\n                                        children[j].bounds.moveBy(xOffsetDepth, 0);\n                                }\n                               \n                                if (children[j].getStencil().id().endsWith(\"Subprocess\")) {\n                                        this.moveChildDockers(children[j], offset);\n                                }\n                               \n                                var edges = [].concat(children[j].getIncomingShapes())\n                                        .concat(children[j].getOutgoingShapes())\n                                        // Remove all edges which are included in the selection from the list\n                                        .findAll(function(r){ return r instanceof ORYX.Core.Edge })\n\n                                k=-1;\n                                while (++k < edges.length) {                    \n                                       \n                                        if (edges[k].getStencil().id().endsWith(\"MessageFlow\")) {\n                                                this.layoutEdges(children[j], [edges[k]], offset);\n                                                continue;\n                                        }\n                                       \n                                        l=-1;\n                                        while (++l < edges[k].dockers.length) {\n                                               \n                                                docker = edges[k].dockers[l];\n                                               \n                                                if (docker.getDockedShape()||docker.isChanged){\n                                                        continue;\n                                                }\n                                       \n                                       \n                                                pos = docker.bounds.center();\n                                               \n                                                // Check if the modified center included the new position\n                                                var isOverLane = oldBounds.isIncluded(pos);\n                                                // Check if the original center is over the pool\n                                                var isOutSidePool = !oldPool.isIncluded(pos);\n                                                var previousIsOverLane = l == 0 ? isOverLane : oldBounds.isIncluded(edges[k].dockers[l-1].bounds.center());\n                                                var nextIsOverLane = l == edges[k].dockers.length-1 ? isOverLane : oldBounds.isIncluded(edges[k].dockers[l+1].bounds.center());\n                                                var off = Object.clone(offset);\n                                               \n                                                // If the\n                                                if (isScaled && isOverLane && this.isResized(lanes[i], this.hashedBounds[pool.id][lanes[i].id])){\n                                                        var relY = (pos.y - absBounds.upperLeft().y + off.y);\n                                                        off.y -= (relY - (relY * (absBounds.height()/oldBounds.height())));\n                                                }\n                                               \n                                                // Check if the previous dockers docked shape is from this lane\n                                                // Otherwise, check if the docker is over the lane OR is outside the lane\n                                                // but the previous/next was over this lane\n                                                if (isOverLane){\n                                                        dockers[docker.id] = {docker: docker, offset:off};\n                                                }\n                                                /*else if (l == 1 && edges[k].dockers.length>2 && edges[k].dockers[l-1].isDocked()){\n                                                        var dockedLane = this.getNextLane(edges[k].dockers[l-1].getDockedShape());\n                                                        if (dockedLane != lanes[i])\n                                                                continue;\n                                                        dockers[docker.id] = {docker: docker, offset:offset};\n                                                }\n                                                // Check if the next dockers docked shape is from this lane\n                                                else if (l == edges[k].dockers.length-2 && edges[k].dockers.length>2 && edges[k].dockers[l+1].isDocked()){\n                                                        var dockedLane = this.getNextLane(edges[k].dockers[l+1].getDockedShape());\n                                                        if (dockedLane != lanes[i])\n                                                                continue;\n                                                        dockers[docker.id] = {docker: docker, offset:offset};\n                                                }\n                                                                                               \n                                                else if (isOutSidePool) {\n                                                        dockers[docker.id] = {docker: docker, offset:this.getOffset(lanes[i], true, pool)};\n                                                }*/\n                                               \n                                       \n                                        }\n                                }\n                                               \n                        }\n                }\n               \n                // Move the moved children\n                var MoveChildCommand = ORYX.Core.Command.extend({\n                        construct: function(state){\n                                this.state = state;\n                        },\n                        execute: function(){\n                                if (this.executed){\n                                        this.state.each(function(s){\n                                                s.shape.bounds.moveBy(s.xOffset, 0);\n                                        });\n                                }\n                                this.executed = true;\n                        },\n                        rollback: function(){\n                                this.state.each(function(s){\n                                        s.shape.bounds.moveBy(-s.xOffset, 0);\n                                });\n                        }\n                })\n               \n               \n                // Set dockers\n                this.facade.executeCommands([new ORYX.Core.MoveDockersCommand(dockers), new MoveChildCommand(movedShapes)]);\n\n        },\n       \n        moveBy: function(pos, offset){\n                pos.x += offset.x;\n                pos.y += offset.y;\n                return pos;\n        },\n       \n        getHashedBounds: function(shape){\n                return this.currentPool && this.hashedBounds[this.currentPool.id][shape.id] ? this.hashedBounds[this.currentPool.id][shape.id] : shape.absoluteBounds();\n        },\n       \n        /**\n         * Returns a set on all child lanes for the given Shape. If recursive is TRUE, also indirect children will be returned (default is FALSE)\n         * The set is sorted with first child the lowest y-coordinate and the last one the highest.\n         * @param {ORYX.Core.Shape} shape\n         * @param {boolean} recursive\n         */\n        getLanes: function(shape, recursive){\n                var namespace = this.getNamespace();\n            \n                // Get all the child lanes\n                var lanes = shape.getChildNodes(recursive||false).findAll(function(node) { return (node.getStencil().id() === namespace + \"Lane\"); });\n               \n                // Sort all lanes by there y coordinate\n                lanes = lanes.sort(function(a, b){\n                       \n                                        // Get y coordinates for upper left and lower right\n                                        var auy = Math.round(a.bounds.upperLeft().y);\n                                        var buy = Math.round(b.bounds.upperLeft().y);\n                                        var aly = Math.round(a.bounds.lowerRight().y);\n                                        var bly = Math.round(b.bounds.lowerRight().y);\n                                       \n                                        var ha  = this.getHashedBounds(a);\n                                        var hb  = this.getHashedBounds(b);\n                                       \n                                        // Get the old y coordinates\n                                        var oauy = Math.round(ha.upperLeft().y);\n                                        var obuy = Math.round(hb.upperLeft().y);\n                                        var oaly = Math.round(ha.lowerRight().y);\n                                        var obly = Math.round(hb.lowerRight().y);\n                                       \n                                        // If equal, than use the old one\n                                        if (auy == buy && aly == bly) {\n                                                auy = oauy; buy = obuy; aly = oaly; bly = obly;\n                                        }\n                                       \n                                        if (Math.round(a.bounds.height()-ha.height()) === 0 && Math.round(b.bounds.height()-hb.height()) === 0){\n                                                return auy < buy ? -1 : (auy > buy ? 1: 0);\n                                        }\n                                       \n                                        // Check if upper left and lower right is completely above/below\n                                        var above = auy < buy && aly < bly;\n                                        var below = auy > buy && aly > bly;\n                                        // Check if a is above b including the old values\n                                        var slightlyAboveBottom = auy < buy && aly >= bly && oaly < obly;\n                                        var slightlyAboveTop = auy >= buy && aly < bly && oauy < obuy;\n                                        // Check if a is below b including the old values\n                                        var slightlyBelowBottom = auy > buy && aly <= bly && oaly > obly;\n                                        var slightlyBelowTop = auy <= buy && aly > bly && oauy > obuy;\n                                       \n                                        // Return -1 if a is above b, 1 if b is above a, or 0 otherwise\n                                        return  (above || slightlyAboveBottom || slightlyAboveTop ? -1 : (below || slightlyBelowBottom || slightlyBelowTop ? 1 : 0))\n                                }.bind(this));\n                               \n                // Return lanes\n                return lanes;\n        },\n                       \n        getNamespace: function() {\n                if(!this.namespace) {\n                        var stencilsets = this.facade.getStencilSets();\n                        if(stencilsets.keys()) {\n                                this.namespace = stencilsets.keys()[0];\n                        } else {\n                                return undefined;\n                        }\n                }\n                return this.namespace;\n        }\n\t};\n\t\n\tvar ResizeLanesCommand = ORYX.Core.Command.extend({\n\n        construct: function(shape, parent, pool, plugin) {\n       \n                this.facade  = plugin.facade;\n                this.plugin  = plugin;\n                this.shape       = shape;\n                this.changes;\n               \n                this.pool       = pool;\n               \n                this.parent     = parent;\n               \n               \n                this.shapeChildren = [];\n               \n                /*\n                 * The Bounds have to be stored\n                 * separate because they would\n                 * otherwise also be influenced\n                 */\n                this.shape.getChildShapes().each(function(childShape) {\n                        this.shapeChildren.push({\n                                shape: childShape,\n                                bounds: {\n                                        a: {\n                                                x: childShape.bounds.a.x,\n                                                y: childShape.bounds.a.y\n                                        },\n                                        b: {\n                                                x: childShape.bounds.b.x,\n                                                y: childShape.bounds.b.y\n                                        }\n                                }\n                        });\n                }.bind(this));\n\n                this.shapeUpperLeft = this.shape.bounds.upperLeft();\n               \n                // If there is no parent,\n                // correct the abs position with the parents abs.\n                /*if (!this.shape.parent) {\n                        var pAbs = parent.absoluteXY();\n                        this.shapeUpperLeft.x += pAbs.x;\n                        this.shapeUpperLeft.y += pAbs.y;\n                }*/\n                this.parentHeight       = this.parent.bounds.height();\n\n        },\n       \n        getLeafLanes: function(lane){\n                var childLanes = this.plugin.getLanes(lane).map(function(child){\n                        return this.getLeafLanes(child);\n                }.bind(this)).flatten();\n                return childLanes.length > 0 ? childLanes : [lane];\n        },\n       \n        findNewLane: function(){\n               \n                var lanes = this.plugin.getLanes(this.parent);\n\n                var leafLanes = this.getLeafLanes(this.parent);\n                /*leafLanes = leafLanes.sort(function(a,b){\n                        var aupl = a.absoluteXY().y;\n                        var bupl = b.absoluteXY().y;\n                        return aupl < bupl ? -1 : (aupl > bupl ? 1 : 0)\n                })*/\n                this.lane = leafLanes.find(function(l){ return l.bounds.upperLeft().y >= this.shapeUpperLeft.y }.bind(this)) || leafLanes.last();\n                this.laneUpperLeft = this.lane.bounds.upperLeft();      \n        },\n       \n        execute: function() {\n               \n                if(this.changes) {\n                        this.executeAgain();\n                        return;\n                }\n\n                /*\n                 * Rescue all ChildShapes of the deleted\n                 * Shape into the lane that takes its\n                 * place\n                 */\n               \n                if (!this.lane){\n                        this.findNewLane();\n                }\n               \n                if(this.lane) {                \n                       \n                        var laUpL = this.laneUpperLeft;\n                        var shUpL = this.shapeUpperLeft;\n                       \n                        var depthChange = this.plugin.getDepth(this.lane, this.parent)-1;\n                                               \n                        this.changes = $H({});\n                       \n                        // Selected lane is BELOW the removed lane\n                        if (laUpL.y >= shUpL.y) {                              \n                                this.lane.getChildShapes().each(function(childShape) {\n                                       \n                                        /*\n                                         * Cache the changes for rollback\n                                         */\n                                        if(!this.changes[childShape.getId()]) {\n                                                this.changes[childShape.getId()] = this.computeChanges(childShape, this.lane, this.lane, this.shape.bounds.height());\n                                        }\n                                       \n                                        childShape.bounds.moveBy(0, this.shape.bounds.height());\n                                }.bind(this));\n                               \n                                this.plugin.hashChildShapes(this.lane);\n                               \n                                this.shapeChildren.each(function(shapeChild) {\n                                        shapeChild.shape.bounds.set(shapeChild.bounds);\n                                        shapeChild.shape.bounds.moveBy((shUpL.x-30)-(depthChange*30), 0);\n                                       \n                                        /*\n                                         * Cache the changes for rollback\n                                         */\n                                        if(!this.changes[shapeChild.shape.getId()]) {\n                                                this.changes[shapeChild.shape.getId()] = this.computeChanges(shapeChild.shape, this.shape, this.lane, 0);\n                                        }\n                                       \n                                        this.lane.add(shapeChild.shape);\n                                       \n                                }.bind(this));          \n                       \n                                this.lane.bounds.moveBy(0, shUpL.y-laUpL.y);\n                       \n                        // Selected lane is ABOVE the removed lane      \n                        } else if(shUpL.y > laUpL.y){\n                               \n                                this.shapeChildren.each(function(shapeChild) {\n                                        shapeChild.shape.bounds.set(shapeChild.bounds);        \n                                        shapeChild.shape.bounds.moveBy((shUpL.x-30)-(depthChange*30), this.lane.bounds.height());                      \n                                       \n                                        /*\n                                         * Cache the changes for rollback\n                                         */\n                                        if(!this.changes[shapeChild.shape.getId()]) {\n                                                this.changes[shapeChild.shape.getId()] = this.computeChanges(shapeChild.shape, this.shape, this.lane, 0);\n                                        }\n                                       \n                                        this.lane.add(shapeChild.shape);\n                                       \n                                }.bind(this));\n                        }\n                       \n                       \n\n                       \n                }\n                               \n                /*\n                 * Adjust the height of the lanes\n                 */\n                // Get the height values\n                var oldHeight   = this.lane.bounds.height();                            \n                var newHeight   = this.lane.length === 1 ? this.parentHeight : this.lane.bounds.height() + this.shape.bounds.height();\n\n                // Set height\n                this.setHeight(newHeight, oldHeight, this.parent, this.parentHeight, true);\n               \n                // Cache all sibling lanes\n                //this.changes[this.shape.getId()] = this.computeChanges(this.shape, this.parent, this.parent, 0);\n                this.plugin.getLanes(this.parent).each(function(childLane){\n                        if(!this.changes[childLane.getId()] && childLane !== this.lane && childLane !== this.shape) {\n                                this.changes[childLane.getId()] = this.computeChanges(childLane, this.parent, this.parent, 0);\n                        }\n                }.bind(this))\n                       \n                // Update\n                this.update();\n        },\n       \n        setHeight: function(newHeight, oldHeight, parent, parentHeight, store){\n               \n                // Set heigh of the lane\n                this.plugin.setDimensions(this.lane, this.lane.bounds.width(), newHeight);\n                this.plugin.hashedBounds[this.pool.id][this.lane.id] = this.lane.absoluteBounds();\n               \n                // Adjust child lanes\n                this.plugin.adjustHeight(this.plugin.getLanes(parent), this.lane);\n               \n                if (store === true){\n                        // Store changes\n                        this.changes[this.shape.getId()] = this.computeChanges(this.shape, parent, parent, 0, oldHeight, newHeight);    \n                }\n               \n                // Set parents height\n                this.plugin.setDimensions(parent, parent.bounds.width(), parentHeight);\n               \n                if (parent !== this.pool){\n                        this.plugin.setDimensions(this.pool, this.pool.bounds.width(), this.pool.bounds.height() + (newHeight-oldHeight));\n                }\n        },\n       \n        update: function(){\n               \n                // Hack to prevent the updating of the dockers\n                this.plugin.hashedBounds[this.pool.id][\"REMOVED\"] = true;\n                // Update\n                //this.facade.getCanvas().update();\n        },\n       \n        rollback: function() {\n               \n                var laUpL = this.laneUpperLeft;\n                var shUpL = this.shapeUpperLeft;\n                       \n                this.changes.each(function(pair) {\n                       \n                        var parent                      = pair.value.oldParent;\n                        var shape                       = pair.value.shape;\n                        var parentHeight        = pair.value.parentHeight;\n                        var oldHeight           = pair.value.oldHeight;\n                        var newHeight           = pair.value.newHeight;\n                       \n                        // Move siblings\n                        if (shape.getStencil().id().endsWith(\"Lane\")){\n                                shape.bounds.moveTo(pair.value.oldPosition);    \n                        }\n                       \n                        // If lane\n                        if(oldHeight) {                                \n                                this.setHeight(oldHeight, newHeight, parent, parent.bounds.height() + (oldHeight - newHeight));\n                                if (laUpL.y >= shUpL.y) {\n                                        this.lane.bounds.moveBy(0, this.shape.bounds.height()-1);\n                                }\n                        } else {\n                                parent.add(shape);\n                                shape.bounds.moveTo(pair.value.oldPosition);\n                               \n                        }\n\n                       \n                }.bind(this));\n               \n                // Update\n                //this.update();\n               \n        },\n       \n        executeAgain: function() {\n               \n                this.changes.each(function(pair) {\n                        var parent        = pair.value.newParent;\n                        var shape         = pair.value.shape;\n                        var newHeight = pair.value.newHeight;\n                        var oldHeight = pair.value.oldHeight;\n                       \n                        // If lane\n                        if(newHeight) {\n                                var laUpL = this.laneUpperLeft.y;\n                                var shUpL = this.shapeUpperLeft.y;\n                       \n                                if (laUpL >= shUpL) {\n                                        this.lane.bounds.moveBy(0, shUpL - laUpL);\n                                }\n                                this.setHeight(newHeight, oldHeight, parent, parent.bounds.height() + (newHeight-oldHeight));\n                        } else {\n                                parent.add(shape);\n                                shape.bounds.moveTo(pair.value.newPosition);\n                        }\n                       \n                }.bind(this));\n               \n                // Update\n                this.update();\n        },\n       \n        computeChanges: function(shape, oldParent, parent, yOffset, oldHeight, newHeight) {\n               \n                oldParent = this.changes[shape.getId()] ? this.changes[shape.getId()].oldParent : oldParent;\n                var oldPosition = this.changes[shape.getId()] ? this.changes[shape.getId()].oldPosition : shape.bounds.upperLeft();\n               \n                var sUl = shape.bounds.upperLeft();\n               \n                var pos = {x: sUl.x, y: sUl.y + yOffset};\n               \n                var changes = {\n                        shape           : shape,\n                        parentHeight: oldParent.bounds.height(),\n                        oldParent       : oldParent,\n                        oldPosition     : oldPosition,\n                        oldHeight       : oldHeight,\n                        newParent       : parent,\n                        newPosition : pos,\n                        newHeight       : newHeight\n                };\n                       \n                return changes;\n        }\n       \n\t});\n\n\t\t\n\tORYX.Plugins.BPMN2_0 = ORYX.Plugins.AbstractPlugin.extend(ORYX.Plugins.BPMN2_0);\n\t\n}()\t"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/editor/oryx.js",
    "content": "/**\n * Copyright (c) 2006\n * \n * Philipp Berger, Martin Czuchra, Gero Decker, Ole Eckermann, Lutz Gericke,\n * Alexander Hold, Alexander Koglin, Oliver Kopp, Stefan Krumnow, \n * Matthias Kunze, Philipp Maschke, Falko Menge, Christoph Neijenhuis, \n * Hagen Overdick, Zhen Peng, Nicolas Peters, Kerstin Pfitzner, Daniel Polak,\n * Steffen Ryll, Kai Schlichting, Jan-Felix Schwarz, Daniel Taschik, \n * Willi Tscheschner, Bj??rn Wagner, Sven Wagner-Boysen, Matthias Weidlich\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is 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\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n * \n **/\n if(!ORYX){var ORYX={}}ORYX.Utils={getParamFromUrl:function(b){b=b.replace(/[\\[]/,\"\\\\[\").replace(/[\\]]/,\"\\\\]\");var a=\"[\\\\?&]\"+b+\"=([^&#]*)\";var d=new RegExp(a);var c=d.exec(window.location.href);if(c==null){return null}else{return c[1]}},adjustLightness:function(){return arguments[0]},adjustGradient:function(c,a){if(ORYX.CONFIG.DISABLE_GRADIENT&&c){var b=a.getAttributeNS(null,\"stop-color\")||\"#ffffff\";$A(c.getElementsByTagName(\"stop\")).each(function(d){if(d==a){return}d.setAttributeNS(null,\"stop-color\",b)})}}};XMLNS={ATOM:\"http://www.w3.org/2005/Atom\",XHTML:\"http://www.w3.org/1999/xhtml\",ERDF:\"http://purl.org/NET/erdf/profile\",RDFS:\"http://www.w3.org/2000/01/rdf-schema#\",RDF:\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\",RAZIEL:\"http://b3mn.org/Raziel\",SCHEMA:\"\"};var Kickstart={started:false,callbacks:[],alreadyLoaded:[],PATH:\"\",load:function(){Kickstart.kick()},kick:function(){if(!Kickstart.started){Kickstart.started=true;Kickstart.callbacks.each(function(a){window.setTimeout(a,1)})}},register:function(callback){with(Kickstart){if(started){window.setTimeout(callback,1)}else{Kickstart.callbacks.push(callback)}}},require:function(a){if(Kickstart.alreadyLoaded.member(a)){return false}return Kickstart.include(a)},include:function(a){var b=document.getElementsByTagNameNS(XMLNS.XHTML,\"head\")[0];var c=document.createElementNS(XMLNS.XHTML,\"script\");c.setAttributeNS(XMLNS.XHTML,\"type\",\"text/javascript\");c.src=Kickstart.PATH+a;b.appendChild(c);Kickstart.alreadyLoaded.push(a);return true}};Event.observe(window,\"load\",Kickstart.load);var ERDF={LITERAL:1,RESOURCE:2,DELIMITERS:[\".\",\"-\"],HASH:\"#\",HYPHEN:\"-\",schemas:[],callback:undefined,log:undefined,init:function(a){ERDF.callback=a;ERDF.registerSchema(\"schema\",XMLNS.SCHEMA);ERDF.registerSchema(\"rdfs\",XMLNS.RDFS)},run:function(){return ERDF._checkProfile()&&ERDF.parse()},parse:function(){ERDF.__startTime=new Date();var b=document.getElementsByTagNameNS(XMLNS.XHTML,\"body\");var c={type:ERDF.RESOURCE,value:\"\"};var a=ERDF._parseDocumentMetadata()&&ERDF._parseFromTag(b[0],c);ERDF.__stopTime=new Date();var d=(ERDF.__stopTime-ERDF.__startTime)/1000;return a},_parseDocumentMetadata:function(){var b=document.getElementsByTagNameNS(XMLNS.XHTML,\"head\");var a=b[0].getElementsByTagNameNS(XMLNS.XHTML,\"link\");var c=b[0].getElementsByTagNameNS(XMLNS.XHTML,\"meta\");$A(a).each(function(e){var d=e.getAttribute(\"rel\");var g=e.getAttribute(\"rev\");var f=e.getAttribute(\"href\");ERDF._parseTriplesFrom(ERDF.RESOURCE,\"\",d,ERDF.RESOURCE,f);ERDF._parseTriplesFrom(ERDF.RESOURCE,f,g,ERDF.RESOURCE,\"\")});$A(c).each(function(f){var e=f.getAttribute(\"name\");var d=f.getAttribute(\"content\");ERDF._parseTriplesFrom(ERDF.RESOURCE,\"\",e,ERDF.LITERAL,d)});return true},_parseFromTag:function(c,k,d){if(!c||!c.namespaceURI||c.namespaceURI!=XMLNS.XHTML){return}if(!d){d=0}var a=c.getAttribute(\"id\");if(c.nodeName.endsWith(\":a\")||c.nodeName==\"a\"){var h=c.getAttribute(\"rel\");var e=c.getAttribute(\"rev\");var n=c.getAttribute(\"href\");var m=c.getAttribute(\"title\");var g=c.textContent;ERDF._parseTriplesFrom(k.type,k.value,h,ERDF.RESOURCE,n,function(p){var o=m?m:g;ERDF._parseTriplesFrom(p.object.type,p.object.value,\"rdfs.label\",ERDF.LITERAL,o)});ERDF._parseTriplesFrom(k.type,k.value,e,ERDF.RESOURCE,\"\");ERDF._parseTypeTriplesFrom(k.type,k.value,h)}else{if(c.nodeName.endsWith(\":img\")||c.nodeName==\"img\"){var h=c.getAttribute(\"class\");var n=c.getAttribute(\"src\");var f=c.getAttribute(\"alt\");ERDF._parseTriplesFrom(k.type,k.value,h,ERDF.RESOURCE,n,function(p){var o=f;ERDF._parseTriplesFrom(p.object.type,p.object.value,\"rdfs.label\",ERDF.LITERAL,o)})}}var h=c.getAttribute(\"class\");var m=c.getAttribute(\"title\");var g=c.textContent;var l=m?m:g;ERDF._parseTriplesFrom(k.type,k.value,h,ERDF.LITERAL,l);if(a){k={type:ERDF.RESOURCE,value:ERDF.HASH+a}}ERDF._parseTypeTriplesFrom(k.type,k.value,h);var b=c.childNodes;if(b){$A(b).each(function(o){if(o.nodeType==o.ELEMENT_NODE){ERDF._parseFromTag(o,k,d+1)}})}},_parseTriplesFrom:function(c,e,d,a,b,f){if(!d){return}d.toLowerCase().split(\" \").each(function(h){var g=ERDF.schemas.find(function(l){return false||ERDF.DELIMITERS.find(function(m){return h.startsWith(l.prefix+m)})});if(g&&b){h=h.substring(g.prefix.length+1,h.length);var k=ERDF.registerTriple(new ERDF.Resource(e),{prefix:g.prefix,name:h},(a==ERDF.RESOURCE)?new ERDF.Resource(b):new ERDF.Literal(b));if(f){f(k)}}})},_parseTypeTriplesFrom:function(a,c,b,d){if(!b){return}b.toLowerCase().split(\" \").each(function(f){var e=ERDF.schemas.find(function(h){return false||ERDF.DELIMITERS.find(function(k){return f.startsWith(ERDF.HYPHEN+h.prefix+k)})});if(e&&c){f=f.substring(e.prefix.length+2,f.length);var g=ERDF.registerTriple((a==ERDF.RESOURCE)?new ERDF.Resource(c):new ERDF.Literal(c),{prefix:\"rdf\",name:\"type\"},new ERDF.Resource(e.namespace+f));if(d){d(g)}}})},_checkProfile:function(){var b=document.getElementsByTagNameNS(XMLNS.XHTML,\"head\");var a=b[0].getAttribute(\"profile\");var c=false;if(a&&a.split(\" \").member(XMLNS.ERDF)){return true}else{return false}},__stripHashes:function(a){return(a&&(typeof a.substring==\"function\")&&a.substring(0,1)==\"#\")?a.substring(1,a.length):a},registerSchema:function(b,a){ERDF.schemas.push({prefix:b,namespace:a})},registerTriple:function(c,a,b){if(a.prefix.toLowerCase()==\"schema\"){this.registerSchema(a.name,b.value)}var d=new ERDF.Triple(c,a,b);ERDF.callback(d);return d},__enhanceObject:function(){this.isResource=function(){return this.type==ERDF.RESOURCE};this.isLocal=function(){return this.isResource()&&this.value.startsWith(\"#\")};this.isCurrentDocument=function(){return this.isResource()&&(this.value==\"\")};this.getId=function(){return this.isLocal()?ERDF.__stripHashes(this.value):false};this.isLiteral=function(){return this.type==ERDF.LIITERAL}},serialize:function(a){if(!a){return\"\"}else{if(a.constructor==String){return a}else{if(a.constructor==Boolean){return a?\"true\":\"false\"}else{return a.toString()}}}}};ERDF.Triple=function(c,a,b){this.subject=c;this.predicate=a;this.object=b;this.toString=function(){return\"[ERDF.Triple] \"+this.subject.toString()+\" \"+this.predicate.prefix+\":\"+this.predicate.name+\" \"+this.object.toString()}};ERDF.Resource=function(a){this.type=ERDF.RESOURCE;this.value=a;ERDF.__enhanceObject.apply(this);this.toString=function(){return\"&lt;\"+this.value+\"&gt;\"}};ERDF.Literal=function(a){this.type=ERDF.LITERAL;this.value=ERDF.serialize(a);ERDF.__enhanceObject.apply(this);this.toString=function(){return'\"'+this.value+'\"'}};var USE_ASYNCHRONOUS_REQUESTS=true;var DISCARD_UNUSED_TRIPLES=true;var PREFER_SPANS_OVER_DIVS=true;var PREFER_TITLE_OVER_TEXTNODE=false;var RESOURCE_ID_PREFIX=\"resource\";var SHOW_DEBUG_ALERTS_WHEN_SAVING=false;var SHOW_EXTENDED_DEBUG_INFORMATION=false;var USE_ARESS_WORKAROUNDS=true;var RESOURCE_CREATED=1;var RESOURCE_REMOVED=2;var RESOURCE_SAVED=4;var RESOURCE_RELOADED=8;var RESOURCE_SYNCHRONIZED=16;var TRIPLE_REMOVE=1;var TRIPLE_ADD=2;var TRIPLE_RELOAD=4;var TRIPLE_SAVE=8;var PROCESSDATA_REF=\"processdata\";var DataManager={init:function(){ERDF.init(DataManager._registerTriple);DataManager.__synclocal()},_triples:[],_registerTriple:function(a){DataManager._triples.push(a)},__synclocal:function(){DataManager._triples=[];ERDF.run()},__synchronizeShape:function(a){var c=ResourceManager.getResource(a.resourceId);var b=a.serialize();b.each(function(d){var f=(d.type==\"resource\");var e=new ERDF.Triple(new ERDF.Resource(a.resourceId),{prefix:d.prefix,name:d.name},f?new ERDF.Resource(d.value):new ERDF.Literal(d.value));DataManager.setObject(e)});return c},__storeShape:function(a){var b=DataManager.__synchronizeShape(a);b.save()},__forceExistance:function(a){if(!$(a.resourceId)){if(!$$(\".\"+PROCESSDATA_REF)[0]){DataManager.graft(XMLNS.XHTML,document.getElementsByTagNameNS(XMLNS.XHTML,\"body\").item(0),[\"div\",{\"class\":PROCESSDATA_REF,style:\"display:none;\"}])}DataManager.graft(XMLNS.XHTML,$$(\".\"+PROCESSDATA_REF)[0],[\"div\",{id:a.resourceId,\"class\":(a instanceof ORYX.Core.Canvas)?\"-oryx-canvas\":undefined}])}else{var c=$(a.resourceId);var b=$A(c.childNodes);b.each(function(d){c.removeChild(d)})}},__persistShape:function(b){var d=b.serialize();var a=[];var c=new ERDF.Resource(b.resourceId);DataManager.removeTriples(DataManager.query(c,undefined,undefined));d.each(function(f){var e=(f.type==\"resource\")?new ERDF.Resource(f.value):new ERDF.Literal(f.value);DataManager.addTriple(new ERDF.Triple(c,{prefix:f.prefix,name:f.name},e))})},__persistDOM:function(d){var c=d.getCanvas();var b=c.getChildShapes(true);var a=\"\";b.each(function(e){DataManager.__forceExistance(e)});DataManager.__renderCanvas(d);a+=DataManager.serialize($(ERDF.__stripHashes(d.getCanvas().resourceId)),true);b.each(function(e){DataManager.__persistShape(e);a+=DataManager.serialize($(ERDF.__stripHashes(e.resourceId)),true)});return a},__renderCanvas:function(e){var b=e.getCanvas();var d=e.getStencilSets();var a=b.getChildShapes(true);DataManager.__forceExistance(b);DataManager.__persistShape(b);var c=new ERDF.Resource(b.resourceId);DataManager.removeTriples(DataManager.query(c,undefined,undefined));DataManager.addTriple(new ERDF.Triple(c,{prefix:\"oryx\",name:\"mode\"},new ERDF.Literal(\"writable\")));DataManager.addTriple(new ERDF.Triple(c,{prefix:\"oryx\",name:\"mode\"},new ERDF.Literal(\"fullscreen\")));d.values().each(function(f){DataManager.addTriple(new ERDF.Triple(c,{prefix:\"oryx\",name:\"stencilset\"},new ERDF.Resource(f.source().replace(/&/g,\"%26\"))));DataManager.addTriple(new ERDF.Triple(c,{prefix:\"oryx\",name:\"ssnamespace\"},new ERDF.Resource(f.namespace())));f.extensions().keys().each(function(g){DataManager.addTriple(new ERDF.Triple(c,{prefix:\"oryx\",name:\"ssextension\"},new ERDF.Literal(g)))})});a.each(function(f){DataManager.addTriple(new ERDF.Triple(c,{prefix:\"oryx\",name:\"render\"},new ERDF.Resource(\"#\"+f.resourceId)))})},__counter:0,__provideId:function(){while($(RESOURCE_ID_PREFIX+DataManager.__counter)){DataManager.__counter++}return RESOURCE_ID_PREFIX+DataManager.__counter},serializeDOM:function(a){return DataManager.__persistDOM(a)},syncGlobal:function(a){return DataManager.__syncglobal(a)},__syncglobal:function(c){var b=c.getCanvas();var a=b.getChildShapes(true);a.select(function(d){return !($(d.resourceId))}).each(function(d){if(USE_ARESS_WORKAROUNDS){var e=d.properties[\"raziel-type\"];var g='<div xmlns=\"http://www.w3.org/1999/xhtml\"><span class=\"raziel-type\">'+e+\"</span></div>\";var f=ResourceManager.__createResource(g);d.resourceId=f.id()}else{var f=ResourceManager.__createResource();d.resourceId=f.id()}});a.each(function(d){DataManager.__storeShape(d)})},serialize:function(f,b){if(f.nodeType==f.ELEMENT_NODE){var e=$A(f.childNodes);var c=$A(f.attributes);var d=new String(f.getAttribute(\"class\"));var g=d.split(\" \").member(\"transient\");if(g){return\"\"}var a=\"<\"+f.nodeName;if(!b){a+=' xmlns=\"'+(f.namespaceURI?f.namespaceURI:XMLNS.XHTML)+'\" xmlns:oryx=\"http://oryx-editor.org\"'}c.each(function(h){a+=\" \"+h.nodeName+'=\"'+h.nodeValue+'\"'});if(e.length==0){a+=\"/>\"}else{a+=\">\";e.each(function(h){a+=DataManager.serialize(h,true)});a+=\"</\"+f.nodeName+\">\"}return a}else{if(f.nodeType==f.TEXT_NODE){return f.nodeValue}}},addTriple:function(c){if(!c.subject.type==ERDF.LITERAL){throw\"Cannot add the triple \"+c.toString()+\" because the subject is not a resource.\"}var a=ERDF.__stripHashes(c.subject.value);var b=$(a);if(!b){throw\"Cannot add the triple \"+c.toString()+' because the subject \"'+a+'\" is not in the document.'}if(c.object.type==ERDF.LITERAL){DataManager.graft(XMLNS.XHTML,b,[\"span\",{\"class\":(c.predicate.prefix+\"-\"+c.predicate.name)},c.object.value.escapeHTML()])}else{DataManager.graft(XMLNS.XHTML,b,[\"a\",{rel:(c.predicate.prefix+\"-\"+c.predicate.name),href:c.object.value}])}return true},removeTriples:function(b){var a=b.select(function(c){return DataManager.__removeTriple(c)});return a},removeTriple:function(b){var a=DataManager.__removeTriple(b);return a},__removeTriple:function(d){if(!d.subject.type==ERDF.LITERAL){throw\"Cannot remove the triple \"+d.toString()+\" because the subject is not a resource.\"}var b=ERDF.__stripHashes(d.subject.value);var c=$(b);if(!c){throw\"Cannot remove the triple \"+d.toString()+\" because the subject is not in the document.\"}if(d.object.type==ERDF.LITERAL){var a=DataManager.__removeTripleRecursively(d,c);return a}},__removeTripleRecursively:function(e,d){if(d.nodeType!=d.ELEMENT_NODE){return false}var b=new String(d.getAttribute(\"class\"));var a=$A(d.childNodes);if(b.include(e.predicate.prefix+\"-\"+e.predicate.name)){var c=d.textContent;if((e.object.type==ERDF.LITERAL)&&(e.object.value==c)){d.parentNode.removeChild(d)}return true}else{a.each(function(f){DataManager.__removeTripleRecursively(e,f)});return false}},graft:function(g,f,d,l){l=(l||(f&&f.ownerDocument)||document);var h;if(d===undefined){echo(\"Can't graft an undefined value\")}else{if(d.constructor==String){h=l.createTextNode(d)}else{for(var c=0;c<d.length;c++){if(c===0&&d[c].constructor==String){var a=d[c].match(/^([a-z][a-z0-9]*)\\.([^\\s\\.]+)$/i);if(a){h=l.createElementNS(g,a[1]);h.setAttributeNS(null,\"class\",a[2]);continue}a=d[c].match(/^([a-z][a-z0-9]*)$/i);if(a){h=l.createElementNS(g,a[1]);continue}h=l.createElementNS(g,\"span\");h.setAttribute(null,\"class\",\"namelessFromLOL\")}if(d[c]===undefined){echo(\"Can't graft an undefined value in a list!\")}else{if(d[c].constructor==String||d[c].constructor==Array){this.graft(g,h,d[c],l)}else{if(d[c].constructor==Number){this.graft(g,h,d[c].toString(),l)}else{if(d[c].constructor==Object){for(var b in d[c]){h.setAttributeNS(null,b,d[c][b])}}else{if(d[c].constructor==Boolean){this.graft(g,h,d[c]?\"true\":\"false\",l)}else{throw\"Object \"+d[c]+\" is inscrutable as an graft arglet.\"}}}}}}}}if(f){f.appendChild(h)}return Element.extend(h)},setObject:function(a){var b=DataManager.query(a.subject,a.predicate,undefined);DataManager.removeTriples(b);DataManager.addTriple(a);return true},query:function(c,a,b){return DataManager._triples.select(function(e){var d=((c)?(e.subject.type==c.type)&&(e.subject.value==c.value):true);if(a){d=d&&((a.prefix)?(e.predicate.prefix==a.prefix):true);d=d&&((a.name)?(e.predicate.name==a.name):true)}d=d&&((b)?(e.object.type==b.type)&&(e.object.value==b.value):true);return d})}};Kickstart.register(DataManager.init);function assert(b,a){if(!b){throw a}}function DMCommand(a,b){this.action=a;this.triple=b;this.toString=function(){return\"Command(\"+a+\", \"+b+\")\"}}function DMCommandHandler(a){this.__setNext=function(c){var b=this.__next;this.__next=a;return b?b:true};this.__setNext(a);this.__invokeNext=function(b){return this.__next?this.__next.handle(b):false};this.handle=function(b){return this.process(b)?true:this.__invokeNext(b)};this.process=function(b){return false}}function MetaTagHandler(next){DMCommandHandler.apply(this,[next]);this.process=function(command){with(command.triple){if(!((subject instanceof ERDF.Resource)&&(subject.isCurrentDocument())&&(object instanceof ERDF.Literal))){return false}}}}var chain=new MetaTagHandler();var command=new DMCommand(TRIPLE_ADD,new ERDF.Triple(new ERDF.Resource(\"\"),\"rdf:tool\",new ERDF.Literal(\"\")));ResourceManager={__corrupt:false,__latelyCreatedResource:undefined,__listeners:$H(),__token:1,addListener:function(d,b){if(!(d instanceof Function)){throw\"Resource event listener is not a function!\"}if(!(b)){throw\"Invalid mask for resource event listener registration.\"}var a={listener:d,mask:b};var c=ResourceManager.__token++;ResourceManager.__listeners[c]=a;return c},removeListener:function(a){return ResourceManager.__listners.remove(a)},__Event:function(a,b){this.action=a;this.resourceId=b},__dispatchEvent:function(a){ResourceManager.__listeners.values().each(function(b){if(a.action&b.mask){return b.listener(a)}})},getResource:function(c){c=ERDF.__stripHashes(c);var b=DataManager.query(new ERDF.Resource(\"#\"+c),{prefix:\"raziel\",name:\"entry\"},undefined);if((b.length==1)&&(b[0].object.isResource())){var a=b[0].object.value;return new ResourceManager.__Resource(c,a)}throw (\"Resource with id \"+c+\" not recognized as such. \"+((b.length>1)?\" There is more than one raziel:entry URL.\":\" There is no raziel:entry URL.\"));return false},__createResource:function(e){var d=DataManager.query(new ERDF.Resource(\"\"),{prefix:\"raziel\",name:\"collection\"},undefined);if((d.length==1)&&(d[0].object.isResource())){var b=d[0].object.value;var c=undefined;var a=e?e:'<div xmlns=\"http://www.w3.org/1999/xhtml\"></div>';ResourceManager.__request(\"POST\",b,a,function(){var f=(this.responseXML);var h=f.childNodes[0];var g=h.getAttribute(\"id\");if(!$$(\".\"+PROCESSDATA_REF)[0]){DataManager.graft(XMLNS.XHTML,document.getElementsByTagNameNS(XMLNS.XHTML,\"body\").item(0),[\"div\",{\"class\":PROCESSDATA_REF,style:\"display:none;\"}])}$$(\".\"+PROCESSDATA_REF)[0].appendChild(h.cloneNode(true));DataManager.__synclocal();c=new ResourceManager.getResource(g);ResourceManager.__resourceActionSucceeded(this,RESOURCE_CREATED,undefined)},function(){ResourceManager.__resourceActionFailed(this,RESOURCE_CREATED,undefined)},false);return c}throw\"Could not create resource! raziel:collection URL is missing!\";return false},__Resource:function(b,a){this.__id=b;this.__url=a;this.id=function(){return this.__id};this.url=function(){return this.__url};this.reload=function(){var d=this.__url;var c=this.__id;ResourceManager.__request(\"GET\",d,null,function(){ResourceManager.__resourceActionSucceeded(this,RESOURCE_RELOADED,c)},function(){ResourceManager.__resourceActionFailed(this,RESURCE_RELOADED,c)},USE_ASYNCHRONOUS_REQUESTS)};this.save=function(e){var d=this.__url;var c=this.__id;data=DataManager.serialize($(c));ResourceManager.__request(\"PUT\",d,data,function(){ResourceManager.__resourceActionSucceeded(this,e?RESOURCE_SAVED|RESOURCE_SYNCHRONIZED:RESOURCE_SAVED,c)},function(){ResourceManager.__resourceActionFailed(this,e?RESOURCE_SAVED|RESOURCE_SYNCHRONIZED:RESOURCE.SAVED,c)},USE_ASYNCHRONOUS_REQUESTS)};this.remove=function(){var d=this.__url;var c=this.__id;ResourceManager.__request(\"DELETE\",d,null,function(){ResourceManager.__resourceActionSucceeded(this,RESOURCE_REMOVED,c)},function(){ResourceManager.__resourceActionFailed(this,RESOURCE_REMOVED,c)},USE_ASYNCHRONOUS_REQUESTS)}},request:function(c,a){var b={method:\"get\",asynchronous:true,parameters:{}};Object.extend(b,a||{});var d=Hash.toQueryString(b.parameters);if(d){c+=(c.include(\"?\")?\"&\":\"?\")+d}return ResourceManager.__request(b.method,c,b.data,(b.onSuccess instanceof Function?function(){b.onSuccess(this)}:undefined),(b.onFailure instanceof Function?function(){b.onFailure(this)}:undefined),b.asynchronous&&USE_ASYNCHRONOUS_REQUESTS,b.headers)},__request:function(a,b,f,n,m,d,c){var g=Try.these(function(){return new XMLHttpRequest()},function(){return new ActiveXObject(\"Msxml2.XMLHTTP\")},function(){return new ActiveXObject(\"Microsoft.XMLHTTP\")});if(!g){if(!this.__corrupt){throw\"This browser does not provide any AJAX functionality. You will not be able to use the software provided with the page you are viewing. Please consider installing appropriate extensions.\"}this.__corrupt=true;return false}if(n instanceof Function){g.onload=n}if(m instanceof Function){g.onerror=m}var k=$H(c);k.keys().each(function(e){g.setRequestHeader(e,k[e])});try{if(SHOW_DEBUG_ALERTS_WHEN_SAVING){alert(a+\" \"+b+\"\\n\"+SHOW_EXTENDED_DEBUG_INFORMATION?f:\"\")}g.open(a,b,!d?false:true);g.send(f)}catch(l){return false}return true},__resourceActionSucceeded:function(g,c,f){var a=g.status;var b=g.responseText;if(SHOW_DEBUG_ALERTS_WHEN_SAVING){alert(a+\" \"+url+\"\\n\"+SHOW_EXTENDED_DEBUG_INFORMATION?data:\"\")}if(a>=300){throw\"The server responded with an error: \"+a+\"\\n\"+(SHOW_EXTENDED_DEBUG_INFORMATION?+data:\"If you need additional information here, including the data sent by the server, consider setting SHOW_EXTENDED_DEBUG_INFORMATION to true.\")}switch(c){case RESOURCE_REMOVED:var b=(g.responseXML);var e=b.childNodes[0];var f=e.getAttribute(\"id\");var d=document.getElementById(f);d.parentNode.removeChild(d);break;case RESOURCE_CREATED:break;case RESOURCE_SAVED|RESOURCE_SYNCHRONIZED:DataManager.__synclocal();case RESOURCE_SAVED:break;case RESOURCE_RELOADED:var b=(g.responseXML);var e=b.childNodes[0];var f=e.getAttribute(\"id\");var d=document.getElementById(f);d.parentNode.removeChild(d);if(!$$(PROCESSDATA_REF)[0]){DataManager.graft(XMLNS.XHTML,document.getElementsByTagNameNS(XMLNS.XHTML,\"body\").item(0),[\"div\",{\"class\":PROCESSDATA_REF,style:\"display:none;\"}])}$$(PROCESSDATA_REF)[0].appendChild(e.cloneNode(true));DataManager.__synclocal();break;default:DataManager.__synclocal()}ResourceManager.__dispatchEvent(new ResourceManager.__Event(c,f))},__resourceActionFailed:function(c,a,b){throw\"Fatal: Resource action failed. There is something horribly wrong with either the server, the transport protocol or your online status. Sure you're online?\"}};var Clazz=function(){};Clazz.prototype.construct=function(){};Clazz.extend=function(e){var a=function(){if(arguments[0]!==Clazz){this.construct.apply(this,arguments)}};var d=new this(Clazz);var b=this.prototype;for(var f in e){var c=e[f];if(c instanceof Function){c.$=b}d[f]=c}a.prototype=d;a.extend=this.extend;return a};if(!ORYX){var ORYX={}}if(!ORYX.CONFIG){ORYX.CONFIG={}}ORYX.CONFIG.ROOT_PATH=\"editor/\";ORYX.CONFIG.EXPLORER_PATH=\"explorer\";ORYX.CONFIG.LIBS_PATH=\"libs\";ORYX.CONFIG.SERVER_HANDLER_ROOT=\"service\";ORYX.CONFIG.SERVER_EDITOR_HANDLER=ORYX.CONFIG.SERVER_HANDLER_ROOT+\"/editor\";ORYX.CONFIG.SERVER_MODEL_HANDLER=ORYX.CONFIG.SERVER_HANDLER_ROOT+\"/model\";ORYX.CONFIG.STENCILSET_HANDLER=ORYX.CONFIG.SERVER_HANDLER_ROOT+\"/editor_stencilset?embedsvg=true&url=true&namespace=\";ORYX.CONFIG.STENCIL_SETS_URL=ORYX.CONFIG.SERVER_HANDLER_ROOT+\"/editor_stencilset\";ORYX.CONFIG.PLUGINS_CONFIG=\"editor-app/plugins.xml\";ORYX.CONFIG.SYNTAXCHECKER_URL=ORYX.CONFIG.SERVER_HANDLER_ROOT+\"/syntaxchecker\";ORYX.CONFIG.DEPLOY_URL=ORYX.CONFIG.SERVER_HANDLER_ROOT+\"/model/deploy\";ORYX.CONFIG.MODEL_LIST_URL=ORYX.CONFIG.SERVER_HANDLER_ROOT+\"/models\";ORYX.CONFIG.FORM_FLOW_LIST_URL=ORYX.CONFIG.SERVER_HANDLER_ROOT+\"/formflows\";ORYX.CONFIG.FORM_FLOW_IMAGE_URL=ORYX.CONFIG.SERVER_HANDLER_ROOT+\"/formflow\";ORYX.CONFIG.FORM_LIST_URL=ORYX.CONFIG.SERVER_HANDLER_ROOT+\"/forms\";ORYX.CONFIG.FORM_IMAGE_URL=ORYX.CONFIG.SERVER_HANDLER_ROOT+\"/form\";ORYX.CONFIG.SUB_PROCESS_LIST_URL=ORYX.CONFIG.SERVER_HANDLER_ROOT+\"/subprocesses\";ORYX.CONFIG.SUB_PROCESS_IMAGE_URL=ORYX.CONFIG.SERVER_HANDLER_ROOT+\"/subprocess\";ORYX.CONFIG.TEST_SERVICE_URL=ORYX.CONFIG.SERVER_HANDLER_ROOT+\"/service/\";ORYX.CONFIG.SERVICE_LIST_URL=ORYX.CONFIG.SERVER_HANDLER_ROOT+\"/services\";ORYX.CONFIG.CONDITION_ELEMENT_LIST_URL=ORYX.CONFIG.SERVER_HANDLER_ROOT+\"/conditionelements\";ORYX.CONFIG.VARIABLEDEF_ELEMENT_LIST_URL=ORYX.CONFIG.SERVER_HANDLER_ROOT+\"/variabledefinitionelements\";ORYX.CONFIG.VALIDATOR_LIST_URL=ORYX.CONFIG.SERVER_HANDLER_ROOT+\"/validators\";ORYX.CONFIG.SS_EXTENSIONS_FOLDER=ORYX.CONFIG.ROOT_PATH+\"stencilsets/extensions/\";ORYX.CONFIG.SS_EXTENSIONS_CONFIG=ORYX.CONFIG.SERVER_HANDLER_ROOT+\"/editor_ssextensions\";ORYX.CONFIG.ORYX_NEW_URL=\"/new\";ORYX.CONFIG.BPMN_LAYOUTER=ORYX.CONFIG.ROOT_PATH+\"bpmnlayouter\";ORYX.CONFIG.EXPRESSION_METADATA_URL=ORYX.CONFIG.SERVER_HANDLER_ROOT+\"/expression-metadata\";ORYX.CONFIG.DATASOURCE_METADATA_URL=ORYX.CONFIG.SERVER_HANDLER_ROOT+\"/datasource-metadata\";if(!ORYX){var ORYX={}}if(!ORYX.CONFIG){ORYX.CONFIG={}}ORYX.CONFIG.BACKEND_SWITCH=true;ORYX.CONFIG.PANEL_LEFT_WIDTH=250;ORYX.CONFIG.PANEL_RIGHT_COLLAPSED=true;ORYX.CONFIG.PANEL_RIGHT_WIDTH=300;ORYX.CONFIG.APPNAME=\"KISBPM\";ORYX.CONFIG.WEB_URL=\".\";ORYX.CONFIG.BLANK_IMAGE=ORYX.CONFIG.LIBS_PATH+\"/ext-2.0.2/resources/images/default/s.gif\";ORYX.CONFIG.OFFSET_HEADER=61;ORYX.CONFIG.SHOW_GRIDLINE=true;ORYX.CONFIG.MODE_READONLY=\"readonly\";ORYX.CONFIG.MODE_FULLSCREEN=\"fullscreen\";ORYX.CONFIG.WINDOW_HEIGHT=800;ORYX.CONFIG.PREVENT_LOADINGMASK_AT_READY=false;ORYX.CONFIG.PLUGINS_ENABLED=true;ORYX.CONFIG.PLUGINS_FOLDER=\"Plugins/\";ORYX.CONFIG.BPMN20_SCHEMA_VALIDATION_ON=true;ORYX.CONFIG.NAMESPACE_ORYX=\"http://www.b3mn.org/oryx\";ORYX.CONFIG.NAMESPACE_SVG=\"http://www.w3.org/2000/svg\";ORYX.CONFIG.CANVAS_WIDTH=1200;ORYX.CONFIG.CANVAS_HEIGHT=1050;ORYX.CONFIG.CANVAS_RESIZE_INTERVAL=100;ORYX.CONFIG.CANVAS_MIN_WIDTH=800;ORYX.CONFIG.CANVAS_MIN_HEIGHT=300;ORYX.CONFIG.SELECTED_AREA_PADDING=4;ORYX.CONFIG.CANVAS_BACKGROUND_COLOR=\"none\";ORYX.CONFIG.GRID_DISTANCE=30;ORYX.CONFIG.GRID_ENABLED=true;ORYX.CONFIG.ZOOM_OFFSET=0.1;ORYX.CONFIG.DEFAULT_SHAPE_MARGIN=60;ORYX.CONFIG.SCALERS_SIZE=7;ORYX.CONFIG.MINIMUM_SIZE=20;ORYX.CONFIG.MAXIMUM_SIZE=10000;ORYX.CONFIG.OFFSET_MAGNET=15;ORYX.CONFIG.OFFSET_EDGE_LABEL_TOP=8;ORYX.CONFIG.OFFSET_EDGE_LABEL_BOTTOM=8;ORYX.CONFIG.OFFSET_EDGE_BOUNDS=5;ORYX.CONFIG.COPY_MOVE_OFFSET=30;ORYX.CONFIG.BORDER_OFFSET=14;ORYX.CONFIG.MAX_NUM_SHAPES_NO_GROUP=20;ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET_CORNER=30;ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET=45;ORYX.CONFIG.SHAPEMENU_RIGHT=\"Oryx_Right\";ORYX.CONFIG.SHAPEMENU_BOTTOM=\"Oryx_Bottom\";ORYX.CONFIG.SHAPEMENU_LEFT=\"Oryx_Left\";ORYX.CONFIG.SHAPEMENU_TOP=\"Oryx_Top\";ORYX.CONFIG.MORPHITEM_DISABLED=\"Oryx_MorphItem_disabled\";ORYX.CONFIG.TYPE_STRING=\"string\";ORYX.CONFIG.TYPE_BOOLEAN=\"boolean\";ORYX.CONFIG.TYPE_INTEGER=\"integer\";ORYX.CONFIG.TYPE_FLOAT=\"float\";ORYX.CONFIG.TYPE_COLOR=\"color\";ORYX.CONFIG.TYPE_DATE=\"date\";ORYX.CONFIG.TYPE_CHOICE=\"choice\";ORYX.CONFIG.TYPE_URL=\"url\";ORYX.CONFIG.TYPE_DIAGRAM_LINK=\"diagramlink\";ORYX.CONFIG.TYPE_COMPLEX=\"complex\";ORYX.CONFIG.TYPE_MULTIPLECOMPLEX=\"multiplecomplex\";ORYX.CONFIG.TYPE_TEXT=\"text\";ORYX.CONFIG.TYPE_KISBPM_MULTIINSTANCE=\"kisbpm-multiinstance\";ORYX.CONFIG.TYPE_MODEL_LINK=\"modellink\";ORYX.CONFIG.TYPE_FORM_FLOW_LINK=\"formflowlink\";ORYX.CONFIG.TYPE_FORM_LINK=\"formlink\";ORYX.CONFIG.TYPE_SUB_PROCESS_LINK=\"subprocesslink\";ORYX.CONFIG.TYPE_SERVICE_LINK=\"servicelink\";ORYX.CONFIG.TYPE_CONDITIONS=\"conditions\";ORYX.CONFIG.TYPE_VARIABLES=\"variables\";ORYX.CONFIG.TYPE_LISTENER=\"listener\";ORYX.CONFIG.TYPE_EPC_FREQ=\"epcfrequency\";ORYX.CONFIG.TYPE_GLOSSARY_LINK=\"glossarylink\";ORYX.CONFIG.TYPE_EXPRESSION=\"expression\";ORYX.CONFIG.TYPE_DATASOURCE=\"datasource\";ORYX.CONFIG.TYPE_DATASOURCE_MINIMAL=\"datasource-minimal\";ORYX.CONFIG.TYPE_VALIDATORS=\"validators\";ORYX.CONFIG.LABEL_LINE_DISTANCE=2;ORYX.CONFIG.LABEL_DEFAULT_LINE_HEIGHT=12;ORYX.CONFIG.ENABLE_MORPHMENU_BY_HOVER=false;ORYX.CONFIG.EDITOR_ALIGN_BOTTOM=1;ORYX.CONFIG.EDITOR_ALIGN_MIDDLE=2;ORYX.CONFIG.EDITOR_ALIGN_TOP=4;ORYX.CONFIG.EDITOR_ALIGN_LEFT=8;ORYX.CONFIG.EDITOR_ALIGN_CENTER=16;ORYX.CONFIG.EDITOR_ALIGN_RIGHT=32;ORYX.CONFIG.EDITOR_ALIGN_SIZE=48;ORYX.CONFIG.EVENT_MOUSEDOWN=\"mousedown\";ORYX.CONFIG.EVENT_MOUSEUP=\"mouseup\";ORYX.CONFIG.EVENT_MOUSEOVER=\"mouseover\";ORYX.CONFIG.EVENT_MOUSEOUT=\"mouseout\";ORYX.CONFIG.EVENT_MOUSEMOVE=\"mousemove\";ORYX.CONFIG.EVENT_DBLCLICK=\"dblclick\";ORYX.CONFIG.EVENT_KEYDOWN=\"keydown\";ORYX.CONFIG.EVENT_KEYUP=\"keyup\";ORYX.CONFIG.EVENT_LOADED=\"editorloaded\";ORYX.CONFIG.EVENT_SAVED=\"editorSaved\";ORYX.CONFIG.EVENT_EXECUTE_COMMANDS=\"executeCommands\";ORYX.CONFIG.EVENT_STENCIL_SET_LOADED=\"stencilSetLoaded\";ORYX.CONFIG.EVENT_SELECTION_CHANGED=\"selectionchanged\";ORYX.CONFIG.EVENT_SHAPEADDED=\"shapeadded\";ORYX.CONFIG.EVENT_SHAPEREMOVED=\"shaperemoved\";ORYX.CONFIG.EVENT_PROPERTY_CHANGED=\"propertyChanged\";ORYX.CONFIG.EVENT_DRAGDROP_START=\"dragdrop.start\";ORYX.CONFIG.EVENT_SHAPE_MENU_CLOSE=\"shape.menu.close\";ORYX.CONFIG.EVENT_DRAGDROP_END=\"dragdrop.end\";ORYX.CONFIG.EVENT_RESIZE_START=\"resize.start\";ORYX.CONFIG.EVENT_RESIZE_END=\"resize.end\";ORYX.CONFIG.EVENT_DRAGDOCKER_DOCKED=\"dragDocker.docked\";ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW=\"highlight.showHighlight\";ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE=\"highlight.hideHighlight\";ORYX.CONFIG.EVENT_LOADING_ENABLE=\"loading.enable\";ORYX.CONFIG.EVENT_LOADING_DISABLE=\"loading.disable\";ORYX.CONFIG.EVENT_LOADING_STATUS=\"loading.status\";ORYX.CONFIG.EVENT_OVERLAY_SHOW=\"overlay.show\";ORYX.CONFIG.EVENT_OVERLAY_HIDE=\"overlay.hide\";ORYX.CONFIG.EVENT_ARRANGEMENT_TOP=\"arrangement.setToTop\";ORYX.CONFIG.EVENT_ARRANGEMENT_BACK=\"arrangement.setToBack\";ORYX.CONFIG.EVENT_ARRANGEMENT_FORWARD=\"arrangement.setForward\";ORYX.CONFIG.EVENT_ARRANGEMENT_BACKWARD=\"arrangement.setBackward\";ORYX.CONFIG.EVENT_PROPWINDOW_PROP_CHANGED=\"propertyWindow.propertyChanged\";ORYX.CONFIG.EVENT_LAYOUT_ROWS=\"layout.rows\";ORYX.CONFIG.EVENT_LAYOUT_BPEL=\"layout.BPEL\";ORYX.CONFIG.EVENT_LAYOUT_BPEL_VERTICAL=\"layout.BPEL.vertical\";ORYX.CONFIG.EVENT_LAYOUT_BPEL_HORIZONTAL=\"layout.BPEL.horizontal\";ORYX.CONFIG.EVENT_LAYOUT_BPEL_SINGLECHILD=\"layout.BPEL.singlechild\";ORYX.CONFIG.EVENT_LAYOUT_BPEL_AUTORESIZE=\"layout.BPEL.autoresize\";ORYX.CONFIG.EVENT_AUTOLAYOUT_LAYOUT=\"autolayout.layout\";ORYX.CONFIG.EVENT_UNDO_EXECUTE=\"undo.execute\";ORYX.CONFIG.EVENT_UNDO_ROLLBACK=\"undo.rollback\";ORYX.CONFIG.EVENT_BUTTON_UPDATE=\"toolbar.button.update\";ORYX.CONFIG.EVENT_LAYOUT=\"layout.dolayout\";ORYX.CONFIG.EVENT_GLOSSARY_LINK_EDIT=\"glossary.link.edit\";ORYX.CONFIG.EVENT_GLOSSARY_SHOW=\"glossary.show.info\";ORYX.CONFIG.EVENT_GLOSSARY_NEW=\"glossary.show.new\";ORYX.CONFIG.EVENT_DOCKERDRAG=\"dragTheDocker\";ORYX.CONFIG.EVENT_CANVAS_SCROLL=\"canvas.scroll\";ORYX.CONFIG.EVENT_SHOW_PROPERTYWINDOW=\"propertywindow.show\";ORYX.CONFIG.EVENT_ABOUT_TO_SAVE=\"file.aboutToSave\";ORYX.CONFIG.SELECTION_HIGHLIGHT_SIZE=5;ORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR=\"#4444FF\";ORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR2=\"#9999FF\";ORYX.CONFIG.SELECTION_HIGHLIGHT_STYLE_CORNER=\"corner\";ORYX.CONFIG.SELECTION_HIGHLIGHT_STYLE_RECTANGLE=\"rectangle\";ORYX.CONFIG.SELECTION_VALID_COLOR=\"#00FF00\";ORYX.CONFIG.SELECTION_INVALID_COLOR=\"#FF0000\";ORYX.CONFIG.DOCKER_DOCKED_COLOR=\"#00FF00\";ORYX.CONFIG.DOCKER_UNDOCKED_COLOR=\"#FF0000\";ORYX.CONFIG.DOCKER_SNAP_OFFSET=10;ORYX.CONFIG.EDIT_OFFSET_PASTE=10;ORYX.CONFIG.KEY_CODE_X=88;ORYX.CONFIG.KEY_CODE_C=67;ORYX.CONFIG.KEY_CODE_V=86;ORYX.CONFIG.KEY_CODE_DELETE=46;ORYX.CONFIG.KEY_CODE_META=224;ORYX.CONFIG.KEY_CODE_BACKSPACE=8;ORYX.CONFIG.KEY_CODE_LEFT=37;ORYX.CONFIG.KEY_CODE_RIGHT=39;ORYX.CONFIG.KEY_CODE_UP=38;ORYX.CONFIG.KEY_CODE_DOWN=40;ORYX.CONFIG.KEY_Code_enter=12;ORYX.CONFIG.KEY_Code_left=37;ORYX.CONFIG.KEY_Code_right=39;ORYX.CONFIG.KEY_Code_top=38;ORYX.CONFIG.KEY_Code_bottom=40;ORYX.CONFIG.META_KEY_META_CTRL=\"metactrl\";ORYX.CONFIG.META_KEY_ALT=\"alt\";ORYX.CONFIG.META_KEY_SHIFT=\"shift\";ORYX.CONFIG.KEY_ACTION_DOWN=\"down\";ORYX.CONFIG.KEY_ACTION_UP=\"up\";ORYX.CONFIG.FORM_ROW_WIDTH=350;ORYX.CONFIG.FORM_GROUP_MARGIN=5;ORYX.CONFIG.FORM_GROUP_EMPTY_HEIGHT=100;ORYX.CONFIG.FORM_ELEMENT_ID_PREFIX=\"http://b3mn.org/stencilset/xforms\";ORYX.CONFIG.FORM_ELEMENT_TYPE_ROOT=\"http://b3mn.org/stencilset/xforms#XForm\";ORYX.CONFIG.FORM_ELEMENT_TYPE_GROUP=\"http://b3mn.org/stencilset/xforms#Group\";ORYX.CONFIG.FORM_ELEMENT_TYPE_REPEATING_GROUP=\"http://b3mn.org/stencilset/xforms#RepeatingGroup\";ORYX.CONFIG.FORM_ELEMENT_TYPE_LABEL_FIELD=\"http://b3mn.org/stencilset/xforms#LabelField\";function printf(){var a=arguments[0];for(var b=1;b<arguments.length;b++){a=a.replace(\"%\"+(b-1),arguments[b])}return a}var ORYX_LOGLEVEL_TRACE=5;var ORYX_LOGLEVEL_DEBUG=4;var ORYX_LOGLEVEL_INFO=3;var ORYX_LOGLEVEL_WARN=2;var ORYX_LOGLEVEL_ERROR=1;var ORYX_LOGLEVEL_FATAL=0;var ORYX_LOGLEVEL=3;var ORYX_CONFIGURATION_DELAY=100;var ORYX_CONFIGURATION_WAIT_ATTEMPTS=10;if(!ORYX){var ORYX={}}ORYX=Object.extend(ORYX,{PATH:ORYX.CONFIG.ROOT_PATH,URLS:[],alreadyLoaded:[],configrationRetries:0,Version:\"0.1.1\",availablePlugins:[],Log:{__appenders:[{append:function(a){if(typeof(console)!==\"undefined\"&&console.log!==undefined){console.log(a)}}}],trace:function(){if(ORYX_LOGLEVEL>=ORYX_LOGLEVEL_TRACE){ORYX.Log.__log(\"TRACE\",arguments)}},debug:function(){if(ORYX_LOGLEVEL>=ORYX_LOGLEVEL_DEBUG){ORYX.Log.__log(\"DEBUG\",arguments)}},info:function(){if(ORYX_LOGLEVEL>=ORYX_LOGLEVEL_INFO){ORYX.Log.__log(\"INFO\",arguments)}},warn:function(){if(ORYX_LOGLEVEL>=ORYX_LOGLEVEL_WARN){ORYX.Log.__log(\"WARN\",arguments)}},error:function(){if(ORYX_LOGLEVEL>=ORYX_LOGLEVEL_ERROR){ORYX.Log.__log(\"ERROR\",arguments)}},fatal:function(){if(ORYX_LOGLEVEL>=ORYX_LOGLEVEL_FATAL){ORYX.Log.__log(\"FATAL\",arguments)}},__log:function(c,a){a[0]=(new Date()).getTime()+\" \"+c+\" \"+a[0];var b=printf.apply(null,a);ORYX.Log.__appenders.each(function(d){d.append(b)})},addAppender:function(a){ORYX.Log.__appenders.push(a)}},load:function(){ORYX.Log.debug(\"Oryx begins loading procedure.\");if((typeof Prototype==\"undefined\")||(typeof Element==\"undefined\")||(typeof Element.Methods==\"undefined\")||parseFloat(Prototype.Version.split(\".\")[0]+\".\"+Prototype.Version.split(\".\")[1])<1.5){throw (\"Application requires the Prototype JavaScript framework >= 1.5.3\")}ORYX.Log.debug(\"Prototype > 1.5 found.\");ORYX._load()},_load:function(){ORYX.loadPlugins()},loadPlugins:function(){if(ORYX.CONFIG.PLUGINS_ENABLED){ORYX._loadPlugins()}else{ORYX.Log.warn(\"Ignoring plugins, loading Core only.\")}init()},_loadPlugins:function(){var a=ORYX.CONFIG.PLUGINS_CONFIG;ORYX.Log.debug(\"Loading plugin configuration from '%0'.\",a);new Ajax.Request(a,{asynchronous:false,method:\"get\",onSuccess:function(c){ORYX.Log.info(\"Plugin configuration file loaded.\");var f=c.responseXML;var b=[];var d=$A(f.getElementsByTagName(\"properties\"));d.each(function(h){var g=$A(h.childNodes);g.each(function(m){var l=new Hash();var k=$A(m.attributes);k.each(function(n){l[n.nodeName]=n.nodeValue});if(k.length>0){b.push(l)}})});var e=f.getElementsByTagName(\"plugin\");$A(e).each(function(k){var p=new Hash();$A(k.attributes).each(function(r){p[r.nodeName]=r.nodeValue});if(!p.name){ORYX.Log.error(\"A plugin is not providing a name. Ingnoring this plugin.\");return}if(!p.source){ORYX.Log.error(\"Plugin with name '%0' doesn't provide a source attribute.\",p.name);return}var n=k.getElementsByTagName(\"property\");var o=[];$A(n).each(function(t){var s=new Hash();var r=$A(t.attributes);r.each(function(u){s[u.nodeName]=u.nodeValue});if(r.length>0){o.push(s)}});o=o.concat(b);p.properties=o;var l=k.getElementsByTagName(\"requires\");var q;$A(l).each(function(s){var r=$A(s.attributes).find(function(t){return t.name==\"namespace\"});if(r&&r.nodeValue){if(!q){q={namespaces:[]}}q.namespaces.push(r.nodeValue)}});if(q){p.requires=q}var m=k.getElementsByTagName(\"notUsesIn\");var h;$A(m).each(function(s){var r=$A(s.attributes).find(function(t){return t.name==\"namespace\"});if(r&&r.nodeValue){if(!h){h={namespaces:[]}}h.namespaces.push(r.nodeValue)}});if(h){p.notUsesIn=h}var g=ORYX.PATH+ORYX.CONFIG.PLUGINS_FOLDER+p.source;ORYX.Log.debug(\"Requireing '%0'\",g);ORYX.Log.info(\"Plugin '%0' successfully loaded.\",p.name);ORYX.availablePlugins.push(p)})},onFailure:this._loadPluginsOnFails})},_loadPluginsOnFails:function(a){ORYX.Log.error(\"Plugin configuration file not available.\")}});if(!ORYX){var ORYX={}}if(!ORYX.Core){ORYX.Core={}}if(!ORYX.Core.SVG){ORYX.Core.SVG={}}ORYX.Core.SVG.EditPathHandler=Clazz.extend({construct:function(){arguments.callee.$.construct.apply(this,arguments);this.x=0;this.y=0;this.oldX=0;this.oldY=0;this.deltaWidth=1;this.deltaHeight=1;this.d=\"\"},init:function(a,f,d,b,c,e){this.x=a;this.y=f;this.oldX=d;this.oldY=b;this.deltaWidth=c;this.deltaHeight=e;this.d=\"\"},editPointsAbs:function(c){if(c instanceof Array){var d=[];var a,e;for(var b=0;b<c.length;b++){a=(parseFloat(c[b])-this.oldX)*this.deltaWidth+this.x;b++;e=(parseFloat(c[b])-this.oldY)*this.deltaHeight+this.y;d.push(a);d.push(e)}return d}else{}},editPointsRel:function(c){if(c instanceof Array){var d=[];var a,e;for(var b=0;b<c.length;b++){a=parseFloat(c[b])*this.deltaWidth;b++;e=parseFloat(c[b])*this.deltaHeight;d.push(a);d.push(e)}return d}else{}},arcAbs:function(e,c,k,b,f,h,g){var d=this.editPointsAbs([h,g]);var a=this.editPointsRel([e,c]);this.d=this.d.concat(\" A\"+a[0]+\" \"+a[1]+\" \"+k+\" \"+b+\" \"+f+\" \"+d[0]+\" \"+d[1]+\" \")},arcRel:function(f,d,b,e,c,a,h){var g=this.editPointsRel([f,d,a,h]);this.d=this.d.concat(\" a\"+g[0]+\" \"+g[1]+\" \"+b+\" \"+e+\" \"+c+\" \"+g[2]+\" \"+g[3]+\" \")},curvetoCubicAbs:function(c,e,b,d,a,g){var f=this.editPointsAbs([c,e,b,d,a,g]);this.d=this.d.concat(\" C\"+f[0]+\" \"+f[1]+\" \"+f[2]+\" \"+f[3]+\" \"+f[4]+\" \"+f[5]+\" \")},curvetoCubicRel:function(c,e,b,d,a,g){var f=this.editPointsRel([c,e,b,d,a,g]);this.d=this.d.concat(\" c\"+f[0]+\" \"+f[1]+\" \"+f[2]+\" \"+f[3]+\" \"+f[4]+\" \"+f[5]+\" \")},linetoHorizontalAbs:function(a){var b=this.editPointsAbs([a,0]);this.d=this.d.concat(\" H\"+b[0]+\" \")},linetoHorizontalRel:function(a){var b=this.editPointsRel([a,0]);this.d=this.d.concat(\" h\"+b[0]+\" \")},linetoAbs:function(a,c){var b=this.editPointsAbs([a,c]);this.d=this.d.concat(\" L\"+b[0]+\" \"+b[1]+\" \")},linetoRel:function(a,c){var b=this.editPointsRel([a,c]);this.d=this.d.concat(\" l\"+b[0]+\" \"+b[1]+\" \")},movetoAbs:function(a,c){var b=this.editPointsAbs([a,c]);this.d=this.d.concat(\" M\"+b[0]+\" \"+b[1]+\" \")},movetoRel:function(a,c){var b;if(this.d===\"\"){b=this.editPointsAbs([a,c])}else{b=this.editPointsRel([a,c])}this.d=this.d.concat(\" m\"+b[0]+\" \"+b[1]+\" \")},curvetoQuadraticAbs:function(b,c,a,e){var d=this.editPointsAbs([b,c,a,e]);this.d=this.d.concat(\" Q\"+d[0]+\" \"+d[1]+\" \"+d[2]+\" \"+d[3]+\" \")},curvetoQuadraticRel:function(b,c,a,e){var d=this.editPointsRel([b,c,a,e]);this.d=this.d.concat(\" q\"+d[0]+\" \"+d[1]+\" \"+d[2]+\" \"+d[3]+\" \")},curvetoCubicSmoothAbs:function(b,c,a,e){var d=this.editPointsAbs([b,c,a,e]);this.d=this.d.concat(\" S\"+d[0]+\" \"+d[1]+\" \"+d[2]+\" \"+d[3]+\" \")},curvetoCubicSmoothRel:function(b,c,a,e){var d=this.editPointsRel([b,c,a,e]);this.d=this.d.concat(\" s\"+d[0]+\" \"+d[1]+\" \"+d[2]+\" \"+d[3]+\" \")},curvetoQuadraticSmoothAbs:function(a,c){var b=this.editPointsAbs([a,c]);this.d=this.d.concat(\" T\"+b[0]+\" \"+b[1]+\" \")},curvetoQuadraticSmoothRel:function(a,c){var b=this.editPointsRel([a,c]);this.d=this.d.concat(\" t\"+b[0]+\" \"+b[1]+\" \")},linetoVerticalAbs:function(b){var a=this.editPointsAbs([0,b]);this.d=this.d.concat(\" V\"+a[1]+\" \")},linetoVerticalRel:function(b){var a=this.editPointsRel([0,b]);this.d=this.d.concat(\" v\"+a[1]+\" \")},closePath:function(){this.d=this.d.concat(\" z\")}});if(!ORYX){var ORYX={}}if(!ORYX.Core){ORYX.Core={}}if(!ORYX.Core.SVG){ORYX.Core.SVG={}}ORYX.Core.SVG.MinMaxPathHandler=Clazz.extend({construct:function(){arguments.callee.$.construct.apply(this,arguments);this.minX=undefined;this.minY=undefined;this.maxX=undefined;this.maxY=undefined;this._lastAbsX=undefined;this._lastAbsY=undefined},calculateMinMax:function(c){if(c instanceof Array){var a,d;for(var b=0;b<c.length;b++){a=parseFloat(c[b]);b++;d=parseFloat(c[b]);this.minX=(this.minX!==undefined)?Math.min(this.minX,a):a;this.maxX=(this.maxX!==undefined)?Math.max(this.maxX,a):a;this.minY=(this.minY!==undefined)?Math.min(this.minY,d):d;this.maxY=(this.maxY!==undefined)?Math.max(this.maxY,d):d;this._lastAbsX=a;this._lastAbsY=d}}else{}},arcAbs:function(f,d,b,e,c,a,g){this.calculateMinMax([a,g])},arcRel:function(f,d,b,e,c,a,g){this.calculateMinMax([this._lastAbsX+a,this._lastAbsY+g])},curvetoCubicAbs:function(c,e,b,d,a,f){this.calculateMinMax([c,e,b,d,a,f])},curvetoCubicRel:function(c,e,b,d,a,f){this.calculateMinMax([this._lastAbsX+c,this._lastAbsY+e,this._lastAbsX+b,this._lastAbsY+d,this._lastAbsX+a,this._lastAbsY+f])},linetoHorizontalAbs:function(a){this.calculateMinMax([a,this._lastAbsY])},linetoHorizontalRel:function(a){this.calculateMinMax([this._lastAbsX+a,this._lastAbsY])},linetoAbs:function(a,b){this.calculateMinMax([a,b])},linetoRel:function(a,b){this.calculateMinMax([this._lastAbsX+a,this._lastAbsY+b])},movetoAbs:function(a,b){this.calculateMinMax([a,b])},movetoRel:function(a,b){if(this._lastAbsX&&this._lastAbsY){this.calculateMinMax([this._lastAbsX+a,this._lastAbsY+b])}else{this.calculateMinMax([a,b])}},curvetoQuadraticAbs:function(b,c,a,d){this.calculateMinMax([b,c,a,d])},curvetoQuadraticRel:function(b,c,a,d){this.calculateMinMax([this._lastAbsX+b,this._lastAbsY+c,this._lastAbsX+a,this._lastAbsY+d])},curvetoCubicSmoothAbs:function(b,c,a,d){this.calculateMinMax([b,c,a,d])},curvetoCubicSmoothRel:function(b,c,a,d){this.calculateMinMax([this._lastAbsX+b,this._lastAbsY+c,this._lastAbsX+a,this._lastAbsY+d])},curvetoQuadraticSmoothAbs:function(a,b){this.calculateMinMax([a,b])},curvetoQuadraticSmoothRel:function(a,b){this.calculateMinMax([this._lastAbsX+a,this._lastAbsY+b])},linetoVerticalAbs:function(a){this.calculateMinMax([this._lastAbsX,a])},linetoVerticalRel:function(a){this.calculateMinMax([this._lastAbsX,this._lastAbsY+a])},closePath:function(){return}});if(!ORYX){var ORYX={}}if(!ORYX.Core){ORYX.Core={}}if(!ORYX.Core.SVG){ORYX.Core.SVG={}}ORYX.Core.SVG.PointsPathHandler=Clazz.extend({construct:function(){arguments.callee.$.construct.apply(this,arguments);this.points=[];this._lastAbsX=undefined;this._lastAbsY=undefined},addPoints:function(c){if(c instanceof Array){var a,d;for(var b=0;b<c.length;b++){a=parseFloat(c[b]);b++;d=parseFloat(c[b]);this.points.push(a);this.points.push(d);this._lastAbsX=a;this._lastAbsY=d}}else{}},arcAbs:function(f,d,b,e,c,a,g){this.addPoints([a,g])},arcRel:function(f,d,b,e,c,a,g){this.addPoints([this._lastAbsX+a,this._lastAbsY+g])},curvetoCubicAbs:function(c,e,b,d,a,f){this.addPoints([a,f])},curvetoCubicRel:function(c,e,b,d,a,f){this.addPoints([this._lastAbsX+a,this._lastAbsY+f])},linetoHorizontalAbs:function(a){this.addPoints([a,this._lastAbsY])},linetoHorizontalRel:function(a){this.addPoints([this._lastAbsX+a,this._lastAbsY])},linetoAbs:function(a,b){this.addPoints([a,b])},linetoRel:function(a,b){this.addPoints([this._lastAbsX+a,this._lastAbsY+b])},movetoAbs:function(a,b){this.addPoints([a,b])},movetoRel:function(a,b){if(this._lastAbsX&&this._lastAbsY){this.addPoints([this._lastAbsX+a,this._lastAbsY+b])}else{this.addPoints([a,b])}},curvetoQuadraticAbs:function(b,c,a,d){this.addPoints([a,d])},curvetoQuadraticRel:function(b,c,a,d){this.addPoints([this._lastAbsX+a,this._lastAbsY+d])},curvetoCubicSmoothAbs:function(b,c,a,d){this.addPoints([a,d])},curvetoCubicSmoothRel:function(b,c,a,d){this.addPoints([this._lastAbsX+a,this._lastAbsY+d])},curvetoQuadraticSmoothAbs:function(a,b){this.addPoints([a,b])},curvetoQuadraticSmoothRel:function(a,b){this.addPoints([this._lastAbsX+a,this._lastAbsY+b])},linetoVerticalAbs:function(a){this.addPoints([this._lastAbsX,a])},linetoVerticalRel:function(a){this.addPoints([this._lastAbsX,this._lastAbsY+a])},closePath:function(){return}});NAMESPACE_ORYX=\"http://www.b3mn.org/oryx\";NAMESPACE_SVG=\"http://www.w3.org/2000/svg/\";if(!ORYX){var ORYX={}}if(!ORYX.Core){ORYX.Core={}}if(!ORYX.Core.SVG){ORYX.Core.SVG={}}ORYX.Core.SVG.SVGMarker=Clazz.extend({construct:function(a){arguments.callee.$.construct.apply(this,arguments);this.id=undefined;this.element=a;this.refX=undefined;this.refY=undefined;this.markerWidth=undefined;this.markerHeight=undefined;this.oldRefX=undefined;this.oldRefY=undefined;this.oldMarkerWidth=undefined;this.oldMarkerHeight=undefined;this.optional=false;this.enabled=true;this.minimumLength=undefined;this.resize=false;this.svgShapes=[];this._init()},_init:function(){if(!(this.element==\"[object SVGMarkerElement]\")){throw\"SVGMarker: Argument is not an instance of SVGMarkerElement.\"}this.id=this.element.getAttributeNS(null,\"id\");var a=this.element.getAttributeNS(null,\"refX\");if(a){this.refX=parseFloat(a)}else{this.refX=0}var h=this.element.getAttributeNS(null,\"refY\");if(h){this.refY=parseFloat(h)}else{this.refY=0}var f=this.element.getAttributeNS(null,\"markerWidth\");if(f){this.markerWidth=parseFloat(f)}else{this.markerWidth=3}var c=this.element.getAttributeNS(null,\"markerHeight\");if(c){this.markerHeight=parseFloat(c)}else{this.markerHeight=3}this.oldRefX=this.refX;this.oldRefY=this.refY;this.oldMarkerWidth=this.markerWidth;this.oldMarkerHeight=this.markerHeight;var g=this.element.getAttributeNS(NAMESPACE_ORYX,\"optional\");if(g){g=g.strip();this.optional=(g.toLowerCase()===\"yes\")}else{this.optional=false}var e=this.element.getAttributeNS(NAMESPACE_ORYX,\"enabled\");if(e){e=e.strip();this.enabled=!(e.toLowerCase()===\"no\")}else{this.enabled=true}var d=this.element.getAttributeNS(NAMESPACE_ORYX,\"minimumLength\");if(d){this.minimumLength=parseFloat(d)}var b=this.element.getAttributeNS(NAMESPACE_ORYX,\"resize\");if(b){b=b.strip();this.resize=(b.toLowerCase()===\"yes\")}else{this.resize=false}},_getSVGShapes:function(c){if(c.hasChildNodes){var a=[];var b=this;$A(c.childNodes).each(function(d){try{var g=new ORYX.Core.SVG.SVGShape(d);a.push(g)}catch(f){a=a.concat(b._getSVGShapes(d))}});return a}},update:function(){this.oldRefX=this.refX;this.oldRefY=this.refY;this.oldMarkerWidth=this.markerWidth;this.oldMarkerHeight=this.markerHeight},toString:function(){return(this.element)?\"SVGMarker \"+this.element.id:\"SVGMarker \"+this.element}});NAMESPACE_ORYX=\"http://www.b3mn.org/oryx\";NAMESPACE_SVG=\"http://www.w3.org/2000/svg/\";if(!ORYX){var ORYX={}}if(!ORYX.Core){ORYX.Core={}}if(!ORYX.Core.SVG){ORYX.Core.SVG={}}ORYX.Core.SVG.SVGShape=Clazz.extend({construct:function(a){arguments.callee.$.construct.apply(this,arguments);this.type;this.element=a;this.x=undefined;this.y=undefined;this.width=undefined;this.height=undefined;this.oldX=undefined;this.oldY=undefined;this.oldWidth=undefined;this.oldHeight=undefined;this.radiusX=undefined;this.radiusY=undefined;this.isHorizontallyResizable=false;this.isVerticallyResizable=false;this.anchorLeft=false;this.anchorRight=false;this.anchorTop=false;this.anchorBottom=false;this.allowDockers=true;this.resizeMarkerMid=false;this.editPathParser;this.editPathHandler;this.init()},init:function(){if(ORYX.Editor.checkClassType(this.element,SVGRectElement)||ORYX.Editor.checkClassType(this.element,SVGImageElement)){this.type=\"Rect\";var I=this.element.getAttributeNS(null,\"x\");if(I){this.oldX=parseFloat(I)}else{throw\"Missing attribute in element \"+this.element}var p=this.element.getAttributeNS(null,\"y\");if(p){this.oldY=parseFloat(p)}else{throw\"Missing attribute in element \"+this.element}var r=this.element.getAttributeNS(null,\"width\");if(r){this.oldWidth=parseFloat(r)}else{throw\"Missing attribute in element \"+this.element}var u=this.element.getAttributeNS(null,\"height\");if(u){this.oldHeight=parseFloat(u)}else{throw\"Missing attribute in element \"+this.element}}else{if(ORYX.Editor.checkClassType(this.element,SVGCircleElement)){this.type=\"Circle\";var h=undefined;var e=undefined;var a=this.element.getAttributeNS(null,\"cx\");if(a){h=parseFloat(a)}else{throw\"Missing attribute in element \"+this.element}var w=this.element.getAttributeNS(null,\"cy\");if(w){e=parseFloat(w)}else{throw\"Missing attribute in element \"+this.element}var k=this.element.getAttributeNS(null,\"r\");if(k){this.radiusX=parseFloat(k)}else{throw\"Missing attribute in element \"+this.element}this.oldX=h-this.radiusX;this.oldY=e-this.radiusX;this.oldWidth=2*this.radiusX;this.oldHeight=2*this.radiusX}else{if(ORYX.Editor.checkClassType(this.element,SVGEllipseElement)){this.type=\"Ellipse\";var h=undefined;var e=undefined;var a=this.element.getAttributeNS(null,\"cx\");if(a){h=parseFloat(a)}else{throw\"Missing attribute in element \"+this.element}var w=this.element.getAttributeNS(null,\"cy\");if(w){e=parseFloat(w)}else{throw\"Missing attribute in element \"+this.element}var J=this.element.getAttributeNS(null,\"rx\");if(J){this.radiusX=parseFloat(J)}else{throw\"Missing attribute in element \"+this.element}var q=this.element.getAttributeNS(null,\"ry\");if(q){this.radiusY=parseFloat(q)}else{throw\"Missing attribute in element \"+this.element}this.oldX=h-this.radiusX;this.oldY=e-this.radiusY;this.oldWidth=2*this.radiusX;this.oldHeight=2*this.radiusY}else{if(ORYX.Editor.checkClassType(this.element,SVGLineElement)){this.type=\"Line\";var C=undefined;var g=undefined;var A=undefined;var d=undefined;var H=this.element.getAttributeNS(null,\"x1\");if(H){C=parseFloat(H)}else{throw\"Missing attribute in element \"+this.element}var b=this.element.getAttributeNS(null,\"y1\");if(b){g=parseFloat(b)}else{throw\"Missing attribute in element \"+this.element}var m=this.element.getAttributeNS(null,\"x2\");if(m){A=parseFloat(m)}else{throw\"Missing attribute in element \"+this.element}var v=this.element.getAttributeNS(null,\"y2\");if(v){d=parseFloat(v)}else{throw\"Missing attribute in element \"+this.element}this.oldX=Math.min(C,A);this.oldY=Math.min(g,d);this.oldWidth=Math.abs(C-A);this.oldHeight=Math.abs(g-d)}else{if(ORYX.Editor.checkClassType(this.element,SVGPolylineElement)||ORYX.Editor.checkClassType(this.element,SVGPolygonElement)){this.type=\"Polyline\";var n=[];if(this.element.points&&this.element.points.numberOfItems){for(var z=0,s=this.element.points.numberOfItems;z<s;z++){n.push(this.element.points.getItem(z).x);n.push(this.element.points.getItem(z).y)}}else{var y=this.element.getAttributeNS(null,\"points\");if(y){y=y.replace(/,/g,\" \");n=y.split(\" \");n=n.without(\"\")}else{throw\"Missing attribute in element \"+this.element}}if(n&&n.length&&n.length>1){var G=parseFloat(n[0]);var F=parseFloat(n[1]);var E=parseFloat(n[0]);var D=parseFloat(n[1]);for(var z=0;z<n.length;z++){G=Math.min(G,parseFloat(n[z]));E=Math.max(E,parseFloat(n[z]));z++;F=Math.min(F,parseFloat(n[z]));D=Math.max(D,parseFloat(n[z]))}this.oldX=G;this.oldY=F;this.oldWidth=E-G;this.oldHeight=D-F}else{throw\"Missing attribute in element \"+this.element}}else{if(ORYX.Editor.checkClassType(this.element,SVGPathElement)){this.type=\"Path\";this.editPathParser=new PathParser();this.editPathHandler=new ORYX.Core.SVG.EditPathHandler();this.editPathParser.setHandler(this.editPathHandler);var f=new PathParser();var c=new ORYX.Core.SVG.MinMaxPathHandler();f.setHandler(c);f.parsePath(this.element);this.oldX=c.minX;this.oldY=c.minY;this.oldWidth=c.maxX-c.minX;this.oldHeight=c.maxY-c.minY;delete f;delete c}else{throw\"Element is not a shape.\"}}}}}}var t=this.element.getAttributeNS(NAMESPACE_ORYX,\"resize\");if(t){t=t.toLowerCase();if(t.match(/horizontal/)){this.isHorizontallyResizable=true}else{this.isHorizontallyResizable=false}if(t.match(/vertical/)){this.isVerticallyResizable=true}else{this.isVerticallyResizable=false}}else{this.isHorizontallyResizable=false;this.isVerticallyResizable=false}var x=this.element.getAttributeNS(NAMESPACE_ORYX,\"anchors\");if(x){x=x.replace(\"/,/g\",\" \");var o=x.split(\" \").without(\"\");for(var z=0;z<o.length;z++){switch(o[z].toLowerCase()){case\"left\":this.anchorLeft=true;break;case\"right\":this.anchorRight=true;break;case\"top\":this.anchorTop=true;break;case\"bottom\":this.anchorBottom=true;break}}}if(ORYX.Editor.checkClassType(this.element,SVGPathElement)){var l=this.element.getAttributeNS(NAMESPACE_ORYX,\"allowDockers\");if(l){if(l.toLowerCase()===\"no\"){this.allowDockers=false}else{this.allowDockers=true}}var B=this.element.getAttributeNS(NAMESPACE_ORYX,\"resizeMarker-mid\");if(B){if(B.toLowerCase()===\"yes\"){this.resizeMarkerMid=true}else{this.resizeMarkerMid=false}}}this.x=this.oldX;this.y=this.oldY;this.width=this.oldWidth;this.height=this.oldHeight},update:function(){if(this.x!==this.oldX||this.y!==this.oldY||this.width!==this.oldWidth||this.height!==this.oldHeight){switch(this.type){case\"Rect\":if(this.x!==this.oldX){this.element.setAttributeNS(null,\"x\",this.x)}if(this.y!==this.oldY){this.element.setAttributeNS(null,\"y\",this.y)}if(this.width!==this.oldWidth){this.element.setAttributeNS(null,\"width\",this.width)}if(this.height!==this.oldHeight){this.element.setAttributeNS(null,\"height\",this.height)}break;case\"Circle\":this.radiusX=((this.width<this.height)?this.width:this.height)/2;this.element.setAttributeNS(null,\"cx\",this.x+this.width/2);this.element.setAttributeNS(null,\"cy\",this.y+this.height/2);this.element.setAttributeNS(null,\"r\",this.radiusX);break;case\"Ellipse\":this.radiusX=this.width/2;this.radiusY=this.height/2;this.element.setAttributeNS(null,\"cx\",this.x+this.radiusX);this.element.setAttributeNS(null,\"cy\",this.y+this.radiusY);this.element.setAttributeNS(null,\"rx\",this.radiusX);this.element.setAttributeNS(null,\"ry\",this.radiusY);break;case\"Line\":if(this.x!==this.oldX){this.element.setAttributeNS(null,\"x1\",this.x)}if(this.y!==this.oldY){this.element.setAttributeNS(null,\"y1\",this.y)}if(this.x!==this.oldX||this.width!==this.oldWidth){this.element.setAttributeNS(null,\"x2\",this.x+this.width)}if(this.y!==this.oldY||this.height!==this.oldHeight){this.element.setAttributeNS(null,\"y2\",this.y+this.height)}break;case\"Polyline\":var d=this.element.getAttributeNS(null,\"points\");if(d){d=d.replace(/,/g,\" \").split(\" \").without(\"\");if(d&&d.length&&d.length>1){var g=(this.oldWidth===0)?0:this.width/this.oldWidth;var e=(this.oldHeight===0)?0:this.height/this.oldHeight;var b=\"\";for(var c=0;c<d.length;c++){var a=(parseFloat(d[c])-this.oldX)*g+this.x;c++;var f=(parseFloat(d[c])-this.oldY)*e+this.y;b+=a+\" \"+f+\" \"}this.element.setAttributeNS(null,\"points\",b)}else{}}else{}break;case\"Path\":var g=(this.oldWidth===0)?0:this.width/this.oldWidth;var e=(this.oldHeight===0)?0:this.height/this.oldHeight;this.editPathHandler.init(this.x,this.y,this.oldX,this.oldY,g,e);this.editPathParser.parsePath(this.element);this.element.setAttributeNS(null,\"d\",this.editPathHandler.d);break}this.oldX=this.x;this.oldY=this.y;this.oldWidth=this.width;this.oldHeight=this.height}delete this.visible;delete this.handler},isPointIncluded:function(d,b){if(!d||!b||!this.isVisible()){return false}switch(this.type){case\"Rect\":return(d>=this.x&&d<=this.x+this.width&&b>=this.y&&b<=this.y+this.height);break;case\"Circle\":return ORYX.Core.Math.isPointInEllipse(d,b,this.x+this.width/2,this.y+this.height/2,this.radiusX,this.radiusX);break;case\"Ellipse\":return ORYX.Core.Math.isPointInEllipse(d,b,this.x+this.radiusX,this.y+this.radiusY,this.radiusX,this.radiusY);break;case\"Line\":return ORYX.Core.Math.isPointInLine(d,b,this.x,this.y,this.x+this.width,this.y+this.height);break;case\"Polyline\":var a=this.element.getAttributeNS(null,\"points\");if(a){a=a.replace(/,/g,\" \").split(\" \").without(\"\");a=a.collect(function(e){return parseFloat(e)});return ORYX.Core.Math.isPointInPolygone(d,b,a)}else{return false}break;case\"Path\":if(!this.handler){var c=new PathParser();this.handler=new ORYX.Core.SVG.PointsPathHandler();c.setHandler(this.handler);c.parsePath(this.element)}return ORYX.Core.Math.isPointInPolygone(d,b,this.handler.points);break;default:return false}},isVisible:function(c){if(this.visible!==undefined){return this.visible}if(!c){c=this.element}var b=false;try{b=!!c.ownerSVGElement}catch(g){}if(b){if(ORYX.Editor.checkClassType(c,SVGGElement)){if(c.className&&c.className.baseVal==\"me\"){this.visible=true;return this.visible}}var f=c.getAttributeNS(null,\"fill\");var d=c.getAttributeNS(null,\"stroke\");if(f&&f==\"none\"&&d&&d==\"none\"){this.visible=false}else{var a=c.getAttributeNS(null,\"display\");if(!a){this.visible=this.isVisible(c.parentNode)}else{if(a==\"none\"){this.visible=false}else{this.visible=true}}}}else{this.visible=true}return this.visible},toString:function(){return(this.element)?\"SVGShape \"+this.element.id:\"SVGShape \"+this.element}});if(!ORYX){var ORYX={}}if(!ORYX.Core){ORYX.Core={}}if(!ORYX.Core.SVG){ORYX.Core.SVG={}}ORYX.Core.SVG.Label=Clazz.extend({_characterSets:[\"%W\",\"@\",\"m\",\"wDGMOQ?????#+=<>~^\",\"ABCHKNRSUVXZ??????????&\",\"bdghnopqux???????????ETY1234567890?????_????${}*????`???????????\",\"aeksvyz?????FLP????????????????\",\"c-\",'rtJ\"/()[]:;!|\\\\',\"fjI., \",\"'\",\"il\"],_characterSetValues:[15,14,13,11,10,9,8,7,6,5,4,3],construct:function(m){arguments.callee.$.construct.apply(this,arguments);if(!m.textElement){throw\"Label: No parameter textElement.\"}else{if(!ORYX.Editor.checkClassType(m.textElement,SVGTextElement)){throw\"Label: Parameter textElement is not an SVGTextElement.\"}}this.invisibleRenderPoint=-5000;this.node=m.textElement;this.node.setAttributeNS(null,\"stroke-width\",\"0pt\");this.node.setAttributeNS(null,\"letter-spacing\",\"-0.01px\");this.shapeId=m.shapeId;this.id;this.fitToElemId;this.edgePosition;this.x;this.y;this.oldX;this.oldY;this.isVisible=true;this._text;this._verticalAlign;this._horizontalAlign;this._rotate;this._rotationPoint;this.anchorLeft;this.anchorRight;this.anchorTop;this.anchorBottom;this._isChanged=true;var k=this.node.getAttributeNS(null,\"id\");if(k){this.id=k}this.fitToElemId=this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX,\"fittoelem\");if(this.fitToElemId){this.fitToElemId=this.shapeId+this.fitToElemId}var f=this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX,\"align\");if(f){f=f.replace(/,/g,\" \");f=f.split(\" \");f=f.without(\"\");f.each((function(e){switch(e){case\"top\":case\"middle\":case\"bottom\":if(!this._verticalAlign){this._originVerticalAlign=this._verticalAlign=e}break;case\"left\":case\"center\":case\"right\":if(!this._horizontalAlign){this._originHorizontalAlign=this._horizontalAlign=e}break}}).bind(this))}this.edgePosition=this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX,\"edgePosition\");if(this.edgePosition){this.originEdgePosition=this.edgePosition=this.edgePosition.toLowerCase()}this.offsetTop=this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX,\"offsetTop\")||ORYX.CONFIG.OFFSET_EDGE_LABEL_TOP;if(this.offsetTop){this.offsetTop=parseInt(this.offsetTop)}this.offsetBottom=this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX,\"offsetBottom\")||ORYX.CONFIG.OFFSET_EDGE_LABEL_BOTTOM;if(this.offsetBottom){this.offsetBottom=parseInt(this.offsetBottom)}var l=this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX,\"rotate\");if(l){try{this._rotate=parseFloat(l)}catch(g){this._rotate=0}}else{this._rotate=0}var b=this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX,\"anchors\");if(b){b=b.replace(\"/,/g\",\" \");var a=b.split(\" \").without(\"\");for(var d=0;d<a.length;d++){switch(a[d].toLowerCase()){case\"left\":this.originAnchorLeft=this.anchorLeft=true;break;case\"right\":this.originAnchorRight=this.anchorRight=true;break;case\"top\":this.originAnchorTop=this.anchorTop=true;break;case\"bottom\":this.originAnchorBottom=this.anchorBottom=true;break}}}if(!this._verticalAlign){this._verticalAlign=\"bottom\"}if(!this._horizontalAlign){this._horizontalAlign=\"left\"}var c=this.node.getAttributeNS(null,\"x\");if(c){this.oldX=this.x=parseFloat(c)}else{}var h=this.node.getAttributeNS(null,\"y\");if(h){this.oldY=this.y=parseFloat(h)}else{}this.text(this.node.textContent)},resetAnchorPosition:function(){this.anchorLeft=this.originAnchorLeft||false;this.anchorRight=this.originAnchorRight||false;this.anchorTop=this.originAnchorTop||false;this.anchorBottom=this.originAnchorBottom||false},isOriginAnchorLeft:function(){return this.originAnchorLeft||false},isOriginAnchorRight:function(){return this.originAnchorRight||false},isOriginAnchorTop:function(){return this.originAnchorTop||false},isOriginAnchorBottom:function(){return this.originAnchorBottom||false},isAnchorLeft:function(){return this.anchorLeft||false},isAnchorRight:function(){return this.anchorRight||false},isAnchorTop:function(){return this.anchorTop||false},isAnchorBottom:function(){return this.anchorBottom||false},getX:function(){try{var a=this.node.x.baseVal.getItem(0).value;switch(this.horizontalAlign()){case\"left\":return a;case\"center\":return a-(this.getWidth()/2);case\"right\":return a-this.getWidth()}return this.node.getBBox().x}catch(b){return this.x}},setX:function(a){if(this.position){this.position.x=a}else{this.setOriginX(a)}},getY:function(){try{return this.node.getBBox().y}catch(a){return this.y}},setY:function(a){if(this.position){this.position.y=a}else{this.setOriginY(a)}},setOriginX:function(a){this.x=a},setOriginY:function(a){this.y=a},getWidth:function(){try{try{var f,h=this.node.childNodes;if(h.length==0){f=this.node.getBBox().width}else{for(var d=0,c=h.length;d<c;++d){var b=h[d].getComputedTextLength();if(\"undefined\"==typeof f||f<b){f=b}}}return f+(f%2==0?0:1)}catch(a){return this.node.getBBox().width}}catch(g){return 0}},getOriginUpperLeft:function(){var a=this.x,b=this.y;switch(this._horizontalAlign){case\"center\":a-=this.getWidth()/2;break;case\"right\":a-=this.getWidth();break}switch(this._verticalAlign){case\"middle\":b-=this.getHeight()/2;break;case\"bottom\":b-=this.getHeight();break}return{x:a,y:b}},getHeight:function(){try{return this.node.getBBox().height}catch(a){return 0}},getCenter:function(){var a={x:this.getX(),y:this.getY()};a.x+=this.getWidth()/2;a.y+=this.getHeight()/2;return a},setPosition:function(a){if(!a||a.x===undefined||a.y===undefined){delete this.position}else{this.position=a}if(this.position){delete this._referencePoint;delete this.edgePosition}this._isChanged=true;this.update()},getPosition:function(){return this.position},setReferencePoint:function(a){if(a){this._referencePoint=a}else{delete this._referencePoint}if(this._referencePoint){delete this.position}},getReferencePoint:function(){return this._referencePoint||undefined},changed:function(){this._isChanged=true},registerOnChange:function(a){if(!this.changeCallbacks){this.changeCallbacks=[]}if(a instanceof Function&&!this.changeCallbacks.include(a)){this.changeCallbacks.push(a)}},unregisterOnChange:function(a){if(this.changeCallbacks&&a instanceof Function&&this.changeCallbacks.include(a)){this.changeCallbacks=this.changeCallbacks.without(a)}},isUpdating:function(){return !!this._isUpdating},getOriginEdgePosition:function(){return this.originEdgePosition},getEdgePosition:function(){return this.edgePosition||null},setEdgePosition:function(a){if([\"starttop\",\"startmiddle\",\"startbottom\",\"midtop\",\"midbottom\",\"endtop\",\"endbottom\"].include(a)){this.edgePosition=a;delete this.position;delete this._referencePoint}else{delete this.edgePosition}},update:function(c){var a=this.x,d=this.y;if(this.position){a=this.position.x;d=this.position.y}a=Math.floor(a);d=Math.floor(d);if(this._isChanged||a!==this.oldX||d!==this.oldY||c===true){if(this.isVisible){this._isChanged=false;this._isUpdating=true;this.node.setAttributeNS(null,\"x\",a);this.node.setAttributeNS(null,\"y\",d);this.node.removeAttributeNS(null,\"fill-opacity\");this.oldX=a;this.oldY=d;if(!this.position&&!this.getReferencePoint()){if(this._rotate!==undefined){if(this._rotationPoint){this.node.setAttributeNS(null,\"transform\",\"rotate(\"+this._rotate+\" \"+Math.floor(this._rotationPoint.x)+\" \"+Math.floor(this._rotationPoint.y)+\")\")}else{this.node.setAttributeNS(null,\"transform\",\"rotate(\"+this._rotate+\" \"+Math.floor(a)+\" \"+Math.floor(d)+\")\")}}}else{this.node.removeAttributeNS(null,\"transform\")}var b=this._text.split(\"\\n\");while(b.last()==\"\"){b.pop()}if(this.node.ownerDocument){if(this.fitToElemId||this._textHasChanged){this.node.textContent=\"\";b.each((function(f,e){var g=this.node.ownerDocument.createElementNS(ORYX.CONFIG.NAMESPACE_SVG,\"tspan\");g.textContent=f.trim();if(this.fitToElemId){g.setAttributeNS(null,\"x\",this.invisibleRenderPoint);g.setAttributeNS(null,\"y\",this.invisibleRenderPoint)}if(g.textContent===\"\"){g.textContent=\" \"}this.node.appendChild(g)}).bind(this));delete this._textHasChanged;delete this.indices}if(this.isVisible&&this.fitToElemId){this.node.setAttributeNS(null,\"visibility\",\"hidden\")}if(this.fitToElemId){window.setTimeout(this._checkFittingToReferencedElem.bind(this),0)}else{window.setTimeout(this._positionText.bind(this),0)}}}else{this.node.textContent=\"\"}}},_checkFittingToReferencedElem:function(){try{var b=$A(this.node.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG,\"tspan\"));var d=[];var l=this.node.ownerDocument.getElementById(this.fitToElemId);if(l){var k=l.getBBox();var s=this.getFontSize();for(var f=0;f<b.length;f++){var p=b[f];var t=this._getRenderedTextLength(p,undefined,undefined,s);var h=(this._rotate!=0&&this._rotate%180!=0&&this._rotate%90==0?k.height:k.width);if(t>h){var q=0;var n=0;var o=this.getTrimmedTextLength(p.textContent);for(var g=0;g<o;g++){var r=this._getRenderedTextLength(p,q,g-q,s);if(r>h-2){var c=this.node.ownerDocument.createElementNS(ORYX.CONFIG.NAMESPACE_SVG,\"tspan\");if(n<=q){n=(g==0)?g:g-1;c.textContent=p.textContent.slice(q,n).trim()}else{c.textContent=p.textContent.slice(q,++n).trim()}c.setAttributeNS(null,\"x\",this.invisibleRenderPoint);c.setAttributeNS(null,\"y\",this.invisibleRenderPoint);d.push(c);q=n}else{var a=p.textContent.charAt(g);if(a==\" \"||a==\"-\"||a==\".\"||a==\",\"||a==\";\"||a==\":\"){n=g}}}p.textContent=p.textContent.slice(q).trim()}d.push(p)}while(this.node.hasChildNodes()){this.node.removeChild(this.node.childNodes[0])}while(d.length>0){this.node.appendChild(d.shift())}}}catch(m){ORYX.Log.fatal(\"Error \"+m)}window.setTimeout(this._positionText.bind(this),0)},_positionText:function(){try{var d=this.node.childNodes;var m=this.getFontSize(this.node);var b=[];var l=this.x,k=this.y;if(this.position){l=this.position.x;k=this.position.y}l=Math.floor(l);k=Math.floor(k);var f=0,a=[];var g=(this.indices||$R(0,d.length-1).toArray());var c=g.length;g.each((function(n){if(\"undefined\"==typeof n){return}var o=d[f++];if(o.textContent.trim()===\"\"){b.push(o)}else{var e=0;switch(this._verticalAlign){case\"bottom\":e=-(c-n-1)*(m);break;case\"middle\":e=-(c/2-n-1)*(m);e-=ORYX.CONFIG.LABEL_LINE_DISTANCE/2;break;case\"top\":e=n*(m);e+=m;break}o.setAttributeNS(null,\"dy\",Math.floor(e));o.setAttributeNS(null,\"x\",l);o.setAttributeNS(null,\"y\",k);a.push(n)}}).bind(this));a.length=d.length;this.indices=this.indices||a;b.each(function(e){this.node.removeChild(e)}.bind(this));switch(this._horizontalAlign){case\"left\":this.node.setAttributeNS(null,\"text-anchor\",\"start\");break;case\"center\":this.node.setAttributeNS(null,\"text-anchor\",\"middle\");break;case\"right\":this.node.setAttributeNS(null,\"text-anchor\",\"end\");break}}catch(h){this._isChanged=true}if(this.isVisible){this.node.removeAttributeNS(null,\"visibility\")}delete this._isUpdating;(this.changeCallbacks||[]).each(function(e){e.apply(e)})},_getRenderedTextLength:function(c,d,b,a){if(d===undefined){return c.getComputedTextLength()}else{return c.getSubStringLength(d,b)}},_estimateTextWidth:function(d,c){var b=0;for(var a=0;a<d.length;a++){b+=this._estimateCharacterWidth(d.charAt(a))}return b*(c/14)},_estimateCharacterWidth:function(b){for(var a=0;a<this._characterSets.length;a++){if(this._characterSets[a].indexOf(b)>=0){return this._characterSetValues[a]}}return 9},getReferencedElementWidth:function(){var a=this.node.ownerDocument.getElementById(this.fitToElemId);if(a){var b=a.getBBox();if(b){return(this._rotate!=0&&this._rotate%180!=0&&this._rotate%90==0?b.height:b.width)}}return undefined},text:function(){switch(arguments.length){case 0:return this._text;break;case 1:var a=this._text;if(arguments[0]){this._text=arguments[0].toString();if(this._text!=null&&this._text!=undefined){this._text=this._text.replace(/ {2,}/g,\" \")}}else{this._text=\"\"}if(a!==this._text){this._isChanged=true;this._textHasChanged=true}break;default:break}},getOriginVerticalAlign:function(){return this._originVerticalAlign},verticalAlign:function(){switch(arguments.length){case 0:return this._verticalAlign;case 1:if([\"top\",\"middle\",\"bottom\"].member(arguments[0])){var a=this._verticalAlign;this._verticalAlign=arguments[0];if(this._verticalAlign!==a){this._isChanged=true}}break;default:break}},getOriginHorizontalAlign:function(){return this._originHorizontalAlign},horizontalAlign:function(){switch(arguments.length){case 0:return this._horizontalAlign;case 1:if([\"left\",\"center\",\"right\"].member(arguments[0])){var a=this._horizontalAlign;this._horizontalAlign=arguments[0];if(this._horizontalAlign!==a){this._isChanged=true}}break;default:break}},rotate:function(){switch(arguments.length){case 0:return this._rotate;case 1:if(this._rotate!=arguments[0]){this._rotate=arguments[0];this._rotationPoint=undefined;this._isChanged=true}case 2:if(this._rotate!=arguments[0]||!this._rotationPoint||this._rotationPoint.x!=arguments[1].x||this._rotationPoint.y!=arguments[1].y){this._rotate=arguments[0];this._rotationPoint=arguments[1];this._isChanged=true}}},hide:function(){if(this.isVisible){this.isVisible=false;this._isChanged=true}},show:function(){if(!this.isVisible){this.isVisible=true;this._isChanged=true;this._textHasChanged=true}},getInheritedFontSize:function(b){if(!b||!b.getAttributeNS){return}var a=b.getAttributeNS(null,\"font-size\");if(a){return parseFloat(a)}else{if(!ORYX.Editor.checkClassType(b,SVGSVGElement)){return this.getInheritedFontSize(b.parentNode)}}},getFontSize:function(b){var a=this.node.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG,\"tspan\");var c=this.getInheritedFontSize(this.node);if(!c){if(a[0]&&/Firefox[\\/\\s](\\d+\\.\\d+)/.test(navigator.userAgent)&&new Number(RegExp.$1)>=3){c=a[0].getExtentOfChar(0).height}else{c=ORYX.CONFIG.LABEL_DEFAULT_LINE_HEIGHT}if(c<=0){c=ORYX.CONFIG.LABEL_DEFAULT_LINE_HEIGHT}}if(c){this.node.setAttribute(\"oryx:fontSize\",c)}return c},getTrimmedTextLength:function(b){b=b.strip().gsub(\"  \",\" \");var a;do{a=b.length;b=b.gsub(\"  \",\" \")}while(a>b.length);return b.length},getOffsetBottom:function(){return this.offsetBottom},getOffsetTop:function(){return this.offsetTop},deserialize:function(b,a){if(b&&\"undefined\"!=typeof b.x&&\"undefined\"!=typeof b.y){this.setPosition({x:b.x,y:b.y});if(\"undefined\"!=typeof b.distance){var d=a.dockers[b.from];var c=a.dockers[b.to];if(d&&c){this.setReferencePoint({dirty:true,distance:b.distance,intersection:{x:b.x,y:b.y},orientation:b.orientation,segment:{from:d,fromIndex:b.from,fromPosition:d.bounds.center(),to:c,toIndex:b.to,toPosition:c.bounds.center()}})}}if(b.left){this.anchorLeft=true}if(b.right){this.anchorRight=true}if(b.top){this.anchorTop=true}if(b.bottom){this.anchorBottom=true}if(b.valign){this.verticalAlign(b.valign)}if(b.align){this.horizontalAlign(b.align)}}else{if(b&&\"undefined\"!=typeof b.edge){this.setEdgePosition(b.edge)}}},serialize:function(){if(this.getEdgePosition()){if(this.getOriginEdgePosition()!==this.getEdgePosition()){return{edge:this.getEdgePosition()}}else{return null}}if(this.position){var b={x:this.position.x,y:this.position.y};if(this.isAnchorLeft()&&this.isAnchorLeft()!==this.isOriginAnchorLeft()){b.left=true}if(this.isAnchorRight()&&this.isAnchorRight()!==this.isOriginAnchorRight()){b.right=true}if(this.isAnchorTop()&&this.isAnchorTop()!==this.isOriginAnchorTop()){b.top=true}if(this.isAnchorBottom()&&this.isAnchorBottom()!==this.isOriginAnchorBottom()){b.bottom=true}if(this.getOriginVerticalAlign()!==this.verticalAlign()){b.valign=this.verticalAlign()}if(this.getOriginHorizontalAlign()!==this.horizontalAlign()){b.align=this.horizontalAlign()}return b}if(this.getReferencePoint()){var a=this.getReferencePoint();return{distance:a.distance,x:a.intersection.x,y:a.intersection.y,from:a.segment.fromIndex,to:a.segment.toIndex,orientation:a.orientation,valign:this.verticalAlign(),align:this.horizontalAlign()}}return null},toString:function(){return\"Label \"+this.id}});if(!ORYX){var ORYX={}}if(!ORYX.Core){ORYX.Core={}}if(!ORYX.Core.Math){ORYX.Core.Math={}}ORYX.Core.Math.midPoint=function(b,a){return{x:(b.x+a.x)/2,y:(b.y+a.y)/2}};ORYX.Core.Math.isPointInLine=function(h,f,g,e,b,a,d){d=d?Math.abs(d):1;if(Math.abs(g-b)<=d&&Math.abs(h-g)<=d&&f-Math.max(e,a)<=d&&Math.min(e,a)-f<=d){return true}if(Math.abs(e-a)<=d&&Math.abs(f-e)<=d&&h-Math.max(g,b)<=d&&Math.min(g,b)-h<=d){return true}if(h>Math.max(g,b)||h<Math.min(g,b)){return false}if(f>Math.max(e,a)||f<Math.min(e,a)){return false}var c=(e-a)/(g-b);return Math.abs(f-((c*h)+e-c*g))<d};ORYX.Core.Math.isPointInEllipse=function(h,f,b,g,e,d){if(b===undefined||g===undefined||e===undefined||d===undefined){throw\"ORYX.Core.Math.isPointInEllipse needs a ellipse with these properties: x, y, radiusX, radiusY\"}var c=(h-b)/e;var a=(f-g)/d;return c*c+a*a<1};ORYX.Core.Math.isPointInPolygone=function(a,n,e){if(arguments.length<3){throw\"ORYX.Core.Math.isPointInPolygone needs two arguments\"}var g=e.length-1;if(e[0]!==e[g-1]||e[1]!==e[g]){e.push(e[0]);e.push(e[1])}var h=0;var c,m,b,l,k;for(var f=0;f<e.length-3;){c=e[f];m=e[++f];b=e[++f];l=e[f+1];k=(n-m)*(b-c)-(a-c)*(l-m);if((m>=n)!=(l>=n)){h+=l-m>=0?k>=0:k<=0}if(!k&&Math.min(c,b)<=a&&a<=Math.max(c,b)&&Math.min(m,l)<=n&&n<=Math.max(m,l)){return true}}return(h%2)?true:false};ORYX.Core.Math.distancePointLinie=function(e,d,a,b){var c=ORYX.Core.Math.getPointOfIntersectionPointLine(e,d,a,b);if(!c){return null}return ORYX.Core.Math.getDistancePointToPoint(a,c)};ORYX.Core.Math.getDistancePointToPoint=function(b,a){return Math.sqrt(Math.pow(b.x-a.x,2)+Math.pow(b.y-a.y,2))};ORYX.Core.Math.getDistanceBetweenTwoPoints=function(c,b,a){return ORYX.Core.Math.getDistancePointToPoint(a,c)/ORYX.Core.Math.getDistancePointToPoint(c,b)};ORYX.Core.Math.pointIsLeftOfLine=function(e,d,a){var c=ORYX.Core.Math.getVector(e,d);var b=ORYX.Core.Math.getVector(e,a);return((c.x*b.y)-(b.x*c.y))>0};ORYX.Core.Math.getPointBetweenTwoPoints=function(b,a,c){c=Math.max(Math.min(c||0,1),0);if(c===0){return b}else{if(c===1){return a}}return{x:b.x+((a.x-b.x)*c),y:b.y+((a.y-b.y)*c)}};ORYX.Core.Math.getVector=function(b,a){return{x:a.x-b.x,y:a.y-b.y}};ORYX.Core.Math.getIdentityVector=function(a){if(arguments.length==2){a=ORYX.Core.Math.getVector(arguments[0],arguments[1])}var b=Math.sqrt((a.x*a.x)+(a.y*a.y));return{x:a.x/(b||1),y:a.y/(b||1)}};ORYX.Core.Math.getOrthogonalIdentityVector=function(c,b){var a=arguments.length==1?c:ORYX.Core.Math.getIdentityVector(c,b);return{x:a.y,y:-a.x}};ORYX.Core.Math.getPointOfIntersectionPointLine=function(f,c,a,e){var d=Math.pow(c.x-f.x,2)+Math.pow(c.y-f.y,2);if(d==0){return undefined}var b=((a.x-f.x)*(c.x-f.x)+(a.y-f.y)*(c.y-f.y))/d;if(e){if(!(0<=b&&b<=1)){return undefined}}pointOfIntersection=new Object();pointOfIntersection.x=f.x+b*(c.x-f.x);pointOfIntersection.y=f.y+b*(c.y-f.y);return pointOfIntersection};ORYX.Core.Math.getTranslatedPoint=function(b,c){var a=c.a*b.x+c.c*b.y+c.e*1;var d=c.b*b.x+c.d*b.y+c.f*1;return{x:a,y:d}};ORYX.Core.Math.getInverseMatrix=function(b){var c=ORYX.Core.Math.getDeterminant(b),a=b;return{a:c*((a.d*1)-(a.f*0)),b:c*((a.f*0)-(a.b*1)),c:c*((a.e*0)-(a.c*1)),d:c*((a.a*1)-(a.e*0)),e:c*((a.c*a.f)-(a.e*a.d)),f:c*((a.e*a.b)-(a.a*a.f))}};ORYX.Core.Math.getDeterminant=function(a){return(a.a*a.d*1)+(a.c*a.f*0)+(a.e*a.b*0)-(a.e*a.d*0)-(a.c*a.b*1)-(a.a*a.f*0)};ORYX.Core.Math.getTranslatedBoundingBox=function(a){var h=a.getCTM();var f=a.getBBox();var e=ORYX.Core.Math.getTranslatedPoint({x:f.x,y:f.y},h);var g=ORYX.Core.Math.getTranslatedPoint({x:f.x,y:f.y+f.height},h);var b=ORYX.Core.Math.getTranslatedPoint({x:f.x+f.width,y:f.y},h);var c=ORYX.Core.Math.getTranslatedPoint({x:f.x+f.width,y:f.y+f.height},h);var k={x:Math.min(e.x,g.x,b.x,c.x),y:Math.min(e.y,g.y,b.y,c.y)};var d={x:Math.max(e.x,g.x,b.x,c.x),y:Math.max(e.y,g.y,b.y,c.y)};return{x:k.x,y:k.y,width:d.x-k.x,height:d.y-k.y}};ORYX.Core.Math.getAngle=function(c,a){if(c.x==a.x&&c.y==a.y){return 0}var b=Math.asin(Math.sqrt(Math.pow(c.y-a.y,2))/(Math.sqrt(Math.pow(a.x-c.x,2)+Math.pow(c.y-a.y,2))))*180/Math.PI;if(a.x>=c.x&&a.y<=c.y){return b}else{if(a.x<c.x&&a.y<=c.y){return 180-b}else{if(a.x<c.x&&a.y>c.y){return 180+b}else{return 360-b}}}};new function(){var b=2,c=8,e=4,a=1;function d(g,n,m,k,h,f){var l=0;if(n>f){l|=c}else{if(n<k){l|=e}}if(g>h){l|=b}else{if(g<m){l|=a}}return l}ORYX.Core.Math.isRectOverLine=function(k,n,g,m,o,l,h,f){return !!ORYX.Core.Math.clipLineOnRect.apply(ORYX.Core.Math,arguments)};ORYX.Core.Math.clipLineOnRect=function(h,u,g,s,f,v,q,l){var m,k,p,w=0;var n=false,o=false;m=d(h,u,f,v,q,l);k=d(g,s,f,v,q,l);do{if((m|k)==0){n=true;o=true}else{if((m&k)>0){o=true}else{var t=0,r=0;p=m!=0?m:k;if((p&c)>0){t=h+(g-h)*(l-u)/(s-u);r=l}else{if((p&e)>0){t=h+(g-h)*(v-u)/(s-u);r=v}else{if((p&b)>0){r=u+(s-u)*(q-h)/(g-h);t=q}else{if((p&a)>0){r=u+(s-u)*(f-h)/(g-h);t=f}}}}if(p==m){h=t;u=r;m=d(h,u,f,v,q,l)}else{g=t;s=r;k=d(g,s,f,v,q,l)}}}w++}while(o!=true&&w<5000);if(n){return{a:{x:h,y:u},b:{x:g,y:s}}}return null}}();if(!ORYX){var ORYX={}}if(!ORYX.Core){ORYX.Core={}}if(!ORYX.Core.StencilSet){ORYX.Core.StencilSet={}}ORYX.Core.StencilSet.Stencil={construct:function(d,e,a,k,h,g){arguments.callee.$.construct.apply(this,arguments);if(!d){throw\"Stencilset seems corrupt.\"}if(!e){throw\"Stencil does not provide namespace.\"}if(!a){throw\"Stencil does not provide SVG source.\"}if(!k){throw\"Fatal internal error loading stencilset.\"}this._source=a;this._jsonStencil=d;this._stencilSet=k;this._namespace=e;this._propertyPackages=h;if(g&&!this._jsonStencil.position){this._jsonStencil.position=g}this._view;this._properties=new Hash();if(!this._jsonStencil.type||!(this._jsonStencil.type===\"edge\"||this._jsonStencil.type===\"node\")){throw\"ORYX.Core.StencilSet.Stencil(construct): Type is not defined.\"}if(!this._jsonStencil.id||this._jsonStencil.id===\"\"){throw\"ORYX.Core.StencilSet.Stencil(construct): Id is not defined.\"}if(!this._jsonStencil.title||this._jsonStencil.title===\"\"){throw\"ORYX.Core.StencilSet.Stencil(construct): Title is not defined.\"}if(!this._jsonStencil.description){this._jsonStencil.description=\"\"}if(!this._jsonStencil.groups){this._jsonStencil.groups=[]}if(!this._jsonStencil.roles){this._jsonStencil.roles=[]}this._jsonStencil.roles.push(this._jsonStencil.id);this._jsonStencil.roles.each((function(m,l){this._jsonStencil.roles[l]=e+m}).bind(this));this._jsonStencil.roles=this._jsonStencil.roles.uniq();this._jsonStencil.id=e+this._jsonStencil.id;this.postProcessProperties();if(!this._jsonStencil.serialize){this._jsonStencil.serialize={}}if(!this._jsonStencil.deserialize){this._jsonStencil.deserialize={}}if(!this._jsonStencil.layout){this._jsonStencil.layout=[]}var c=a+\"view/\"+d.view;if(this._jsonStencil.view.trim().match(/</)){var b=new DOMParser();var f=b.parseFromString(this._jsonStencil.view,\"text/xml\");if(ORYX.Editor.checkClassType(f.documentElement,SVGSVGElement)){this._view=f.documentElement}else{throw\"ORYX.Core.StencilSet.Stencil(_loadSVGOnSuccess): The response is not a SVG document.\"}}else{new Ajax.Request(c,{asynchronous:false,method:\"get\",onSuccess:this._loadSVGOnSuccess.bind(this),onFailure:this._loadSVGOnFailure.bind(this)})}},postProcessProperties:function(){if(this._jsonStencil.propertyPackages&&this._jsonStencil.propertyPackages instanceof Array){this._jsonStencil.propertyPackages.each((function(b){var a=this._propertyPackages[b];if(a){a.each((function(d){var c=new ORYX.Core.StencilSet.Property(d,this._namespace,this);this._properties[c.prefix()+\"-\"+c.id()]=c}).bind(this))}}).bind(this))}if(this._jsonStencil.properties&&this._jsonStencil.properties instanceof Array){this._jsonStencil.properties.each((function(b){var a=new ORYX.Core.StencilSet.Property(b,this._namespace,this);this._properties[a.prefix()+\"-\"+a.id()]=a}).bind(this))}},equals:function(a){return(this.id()===a.id())},stencilSet:function(){return this._stencilSet},type:function(){return this._jsonStencil.type},namespace:function(){return this._namespace},id:function(){return this._jsonStencil.id},idWithoutNs:function(){return this.id().replace(this.namespace(),\"\")},title:function(){return ORYX.Core.StencilSet.getTranslation(this._jsonStencil,\"title\")},description:function(){return ORYX.Core.StencilSet.getTranslation(this._jsonStencil,\"description\")},groups:function(){return ORYX.Core.StencilSet.getTranslation(this._jsonStencil,\"groups\")},position:function(){return(isNaN(this._jsonStencil.position)?0:this._jsonStencil.position)},view:function(){return this._view.cloneNode(true)||this._view},icon:function(){return this._jsonStencil.icon},fixedAspectRatio:function(){return this._jsonStencil.fixedAspectRatio===true},hasMultipleRepositoryEntries:function(){return(this.getRepositoryEntries().length>0)},getRepositoryEntries:function(){return(this._jsonStencil.repositoryEntries)?$A(this._jsonStencil.repositoryEntries):$A([])},properties:function(){return this._properties.values()},property:function(a){return this._properties[a]},roles:function(){return this._jsonStencil.roles},defaultAlign:function(){if(!this._jsonStencil.defaultAlign){return\"east\"}return this._jsonStencil.defaultAlign},serialize:function(a,b){return this._jsonStencil.serialize},deserialize:function(a,b){return this._jsonStencil.deserialize},layout:function(a){return this._jsonStencil.layout},addProperty:function(c,b){if(c&&b){var a=new ORYX.Core.StencilSet.Property(c,b,this);this._properties[a.prefix()+\"-\"+a.id()]=a}},removeProperty:function(b){if(b){var a=this._properties.values().find(function(c){return(b==c.id())});if(a){delete this._properties[a.prefix()+\"-\"+a.id()]}}},_loadSVGOnSuccess:function(a){var b=null;b=a.responseXML;if(ORYX.Editor.checkClassType(b.documentElement,SVGSVGElement)){this._view=b.documentElement}else{throw\"ORYX.Core.StencilSet.Stencil(_loadSVGOnSuccess): The response is not a SVG document.\"}},_loadSVGOnFailure:function(a){throw\"ORYX.Core.StencilSet.Stencil(_loadSVGOnFailure): Loading SVG document failed.\"},toString:function(){return\"Stencil \"+this.title()+\" (\"+this.id()+\")\"}};ORYX.Core.StencilSet.Stencil=Clazz.extend(ORYX.Core.StencilSet.Stencil);function _evenMoreEvilHack(c,e){if(window.ActiveXObject){var b=new ActiveXObject(\"MSXML.DomDocument\");b.loadXML(c);return b}else{if(window.XMLHttpRequest){var a=new XMLHttpRequest;a.open(\"GET\",\"data:\"+(e||\"application/xml\")+\";charset=utf-8,\"+encodeURIComponent(c),false);if(a.overrideMimeType){a.overrideMimeType(e)}a.send(null);return a.responseXML}}}function _evilSafariHack(d){var b=d;var a=\"data:text/xml;charset=utf-8,\"+encodeURIComponent(b);var e=null;var c=new XMLHttpRequest();c.open(\"GET\",a);c.onload=function(){e=c.responseXML};c.send(null);return e}if(!ORYX){var ORYX={}}if(!ORYX.Core){ORYX.Core={}}if(!ORYX.Core.StencilSet){ORYX.Core.StencilSet={}}ORYX.Core.StencilSet.Property=Clazz.extend({construct:function(d,b,c){arguments.callee.$.construct.apply(this,arguments);this._jsonProp=d||ORYX.Log.error(\"Parameter jsonProp is not defined.\");this._namespace=b||ORYX.Log.error(\"Parameter namespace is not defined.\");this._stencil=c||ORYX.Log.error(\"Parameter stencil is not defined.\");this._items={};this._complexItems={};this._hidden=false;d.id=d.id||ORYX.Log.error(\"ORYX.Core.StencilSet.Property(construct): Id is not defined.\");d.id=d.id.toLowerCase();if(!d.type){ORYX.Log.info(\"Type is not defined for stencil '%0', id '%1'. Falling back to 'String'.\",c,d.id);d.type=\"string\"}else{d.type=d.type.toLowerCase()}d.prefix=d.prefix||\"oryx\";d.title=d.title||\"\";d.value=d.value||\"\";d.description=d.description||\"\";d.readonly=d.readonly||false;d.optional=d.optional!==false;if(this._jsonProp.refToView){if(!(this._jsonProp.refToView instanceof Array)){this._jsonProp.refToView=[this._jsonProp.refToView]}}else{this._jsonProp.refToView=[]}var a=this.getMinForType(d.type);if(d.min===undefined||d.min===null){d.min=a}else{if(d.min<a){d.min=a}}var e=this.getMaxForType(d.type);if(d.max===undefined||d.max===null){d.max=e}else{if(d.max>e){d.min=e}}if(!d.fillOpacity){d.fillOpacity=false}if(\"number\"!=typeof d.lightness){d.lightness=1}else{d.lightness=Math.max(0,Math.min(1,d.lightness))}if(!d.strokeOpacity){d.strokeOpacity=false}if(d.length===undefined||d.length===null){d.length=Number.MAX_VALUE}if(!d.wrapLines){d.wrapLines=false}if(!d.dateFormat){d.dateFormat=ORYX.I18N.PropertyWindow.dateFormat||\"m/d/y\"}if(!d.fill){d.fill=false}if(!d.stroke){d.stroke=false}if(!d.inverseBoolean){d.inverseBoolean=false}if(!d.directlyEditable&&d.directlyEditable!=false){d.directlyEditable=true}if(d.visible!==false){d.visible=true}if(d.isList!==true){d.isList=false;if(!d.list||!(d.list instanceof Array)){d.list=[]}}if(!d.category){if(d.popular){d.category=\"popular\"}else{d.category=\"others\"}}if(!d.alwaysAppearInMultiselect){d.alwaysAppearInMultiselect=false}if(d.type===ORYX.CONFIG.TYPE_CHOICE){if(d.items&&d.items instanceof Array){d.items.each((function(f){this._items[f.value.toLowerCase()]=new ORYX.Core.StencilSet.PropertyItem(f,b,this)}).bind(this))}else{throw\"ORYX.Core.StencilSet.Property(construct): No property items defined.\"}}else{if(d.type===ORYX.CONFIG.TYPE_COMPLEX||d.type==ORYX.CONFIG.TYPE_MULTIPLECOMPLEX){if(d.complexItems&&d.complexItems instanceof Array){d.complexItems.each((function(f){this._complexItems[f.id.toLowerCase()]=new ORYX.Core.StencilSet.ComplexPropertyItem(f,b,this)}).bind(this))}}}},getMinForType:function(a){if(a.toLowerCase()==ORYX.CONFIG.TYPE_INTEGER){return -Math.pow(2,31)}else{return -Number.MAX_VALUE+1}},getMaxForType:function(a){if(a.toLowerCase()==ORYX.CONFIG.TYPE_INTEGER){return Math.pow(2,31)-1}else{return Number.MAX_VALUE}},equals:function(a){return(this._namespace===a.namespace()&&this.id()===a.id())?true:false},namespace:function(){return this._namespace},stencil:function(){return this._stencil},id:function(){return this._jsonProp.id},prefix:function(){return this._jsonProp.prefix},type:function(){return this._jsonProp.type},inverseBoolean:function(){return this._jsonProp.inverseBoolean},category:function(){return this._jsonProp.category},setCategory:function(a){this._jsonProp.category=a},directlyEditable:function(){return this._jsonProp.directlyEditable},visible:function(){return this._jsonProp.visible},title:function(){return ORYX.Core.StencilSet.getTranslation(this._jsonProp,\"title\")},value:function(){return this._jsonProp.value},readonly:function(){return this._jsonProp.readonly},optional:function(){return this._jsonProp.optional},description:function(){return ORYX.Core.StencilSet.getTranslation(this._jsonProp,\"description\")},refToView:function(){return this._jsonProp.refToView},min:function(){return this._jsonProp.min},max:function(){return this._jsonProp.max},fillOpacity:function(){return this._jsonProp.fillOpacity},strokeOpacity:function(){return this._jsonProp.strokeOpacity},length:function(){return this._jsonProp.length?this._jsonProp.length:Number.MAX_VALUE},wrapLines:function(){return this._jsonProp.wrapLines},dateFormat:function(){return this._jsonProp.dateFormat},fill:function(){return this._jsonProp.fill},lightness:function(){return this._jsonProp.lightness},stroke:function(){return this._jsonProp.stroke},items:function(){return $H(this._items).values()},item:function(a){if(a){return this._items[a.toLowerCase()]}else{return null}},toString:function(){return\"Property \"+this.title()+\" (\"+this.id()+\")\"},complexItems:function(){return $H(this._complexItems).values()},complexItem:function(a){if(a){return this._complexItems[a.toLowerCase()]}else{return null}},complexAttributeToView:function(){return this._jsonProp.complexAttributeToView||\"\"},isList:function(){return !!this._jsonProp.isList},getListItems:function(){return this._jsonProp.list},linkableType:function(){return this._jsonProp.linkableType||\"\"},alwaysAppearInMultiselect:function(){return this._jsonProp.alwaysAppearInMultiselect},popular:function(){return this._jsonProp.popular||false},setPopular:function(){this._jsonProp.popular=true},hide:function(){this._hidden=true},isHidden:function(){return this._hidden}});if(!ORYX){var ORYX={}}if(!ORYX.Core){ORYX.Core={}}if(!ORYX.Core.StencilSet){ORYX.Core.StencilSet={}}ORYX.Core.StencilSet.PropertyItem=Clazz.extend({construct:function(a,b,c){arguments.callee.$.construct.apply(this,arguments);if(!a){throw\"ORYX.Core.StencilSet.PropertyItem(construct): Parameter jsonItem is not defined.\"}if(!b){throw\"ORYX.Core.StencilSet.PropertyItem(construct): Parameter namespace is not defined.\"}if(!c){throw\"ORYX.Core.StencilSet.PropertyItem(construct): Parameter property is not defined.\"}this._jsonItem=a;this._namespace=b;this._property=c;if(!a.value){throw\"ORYX.Core.StencilSet.PropertyItem(construct): Value is not defined.\"}if(this._jsonItem.refToView){if(!(this._jsonItem.refToView instanceof Array)){this._jsonItem.refToView=[this._jsonItem.refToView]}}else{this._jsonItem.refToView=[]}},equals:function(a){return(this.property().equals(a.property())&&this.value()===a.value())},namespace:function(){return this._namespace},property:function(){return this._property},value:function(){return this._jsonItem.value},title:function(){return ORYX.Core.StencilSet.getTranslation(this._jsonItem,\"title\")},refToView:function(){return this._jsonItem.refToView},icon:function(){return(this._jsonItem.icon)?this.property().stencil()._source+\"icons/\"+this._jsonItem.icon:\"\"},toString:function(){return\"PropertyItem \"+this.property()+\" (\"+this.value()+\")\"}});if(!ORYX){var ORYX={}}if(!ORYX.Core){ORYX.Core={}}if(!ORYX.Core.StencilSet){ORYX.Core.StencilSet={}}ORYX.Core.StencilSet.ComplexPropertyItem=Clazz.extend({construct:function(a,b,c){arguments.callee.$.construct.apply(this,arguments);if(!a){throw\"ORYX.Core.StencilSet.ComplexPropertyItem(construct): Parameter jsonItem is not defined.\"}if(!b){throw\"ORYX.Core.StencilSet.ComplexPropertyItem(construct): Parameter namespace is not defined.\"}if(!c){throw\"ORYX.Core.StencilSet.ComplexPropertyItem(construct): Parameter property is not defined.\"}this._jsonItem=a;this._namespace=b;this._property=c;this._items=new Hash();this._complexItems=new Hash();if(!a.name){throw\"ORYX.Core.StencilSet.ComplexPropertyItem(construct): Name is not defined.\"}if(!a.type){throw\"ORYX.Core.StencilSet.ComplexPropertyItem(construct): Type is not defined.\"}else{a.type=a.type.toLowerCase()}if(a.type===ORYX.CONFIG.TYPE_CHOICE){if(a.items&&a.items instanceof Array){a.items.each((function(d){this._items[d.value]=new ORYX.Core.StencilSet.PropertyItem(d,b,this)}).bind(this))}else{throw\"ORYX.Core.StencilSet.Property(construct): No property items defined.\"}}else{if(a.type===ORYX.CONFIG.TYPE_COMPLEX){if(a.complexItems&&a.complexItems instanceof Array){a.complexItems.each((function(d){this._complexItems[d.id]=new ORYX.Core.StencilSet.ComplexPropertyItem(d,b,this)}).bind(this))}else{throw\"ORYX.Core.StencilSet.Property(construct): No property items defined.\"}}}},equals:function(a){return(this.property().equals(a.property())&&this.name()===a.name())},namespace:function(){return this._namespace},property:function(){return this._property},name:function(){return ORYX.Core.StencilSet.getTranslation(this._jsonItem,\"name\")},id:function(){return this._jsonItem.id},type:function(){return this._jsonItem.type},optional:function(){return this._jsonItem.optional},width:function(){return this._jsonItem.width},value:function(){return this._jsonItem.value},items:function(){return this._items.values()},complexItems:function(){return this._complexItems.values()},disable:function(){return this._jsonItem.disable}});if(!ORYX){var ORYX={}}if(!ORYX.Core){ORYX.Core={}}if(!ORYX.Core.StencilSet){ORYX.Core.StencilSet={}}ORYX.Core.StencilSet.Rules={construct:function(){arguments.callee.$.construct.apply(this,arguments);this._stencilSets=[];this._stencils=[];this._containerStencils=[];this._cachedConnectSET=new Hash();this._cachedConnectSE=new Hash();this._cachedConnectTE=new Hash();this._cachedCardSE=new Hash();this._cachedCardTE=new Hash();this._cachedContainPC=new Hash();this._cachedMorphRS=new Hash();this._connectionRules=new Hash();this._cardinalityRules=new Hash();this._containmentRules=new Hash();this._morphingRules=new Hash();this._layoutRules=new Hash()},initializeRules:function(l){var k=this._stencilSets.find(function(o){return(o.namespace()==l.namespace())});if(k){var f=this._stencilSets.clone();f=f.without(k);f.push(l);this._stencilSets=[];this._stencils=[];this._containerStencils=[];this._cachedConnectSET=new Hash();this._cachedConnectSE=new Hash();this._cachedConnectTE=new Hash();this._cachedCardSE=new Hash();this._cachedCardTE=new Hash();this._cachedContainPC=new Hash();this._cachedMorphRS=new Hash();this._connectionRules=new Hash();this._cardinalityRules=new Hash();this._containmentRules=new Hash();this._morphingRules=new Hash();this._layoutRules=new Hash();f.each(function(o){this.initializeRules(o)}.bind(this));return}else{this._stencilSets.push(l);var m=new Hash(l.jsonRules());var e=l.namespace();var b=l.stencils();l.extensions().values().each(function(o){if(o.rules){if(o.rules.connectionRules){m.connectionRules=m.connectionRules.concat(o.rules.connectionRules)}if(o.rules.cardinalityRules){m.cardinalityRules=m.cardinalityRules.concat(o.rules.cardinalityRules)}if(o.rules.containmentRules){m.containmentRules=m.containmentRules.concat(o.rules.containmentRules)}if(o.rules.morphingRules){m.morphingRules=m.morphingRules.concat(o.rules.morphingRules)}}if(o.stencils){b=b.concat(o.stencils)}});this._stencils=this._stencils.concat(l.stencils());var g=this._connectionRules;if(m.connectionRules){m.connectionRules.each((function(o){if(this._isRoleOfOtherNamespace(o.role)){if(!g[o.role]){g[o.role]=new Hash()}}else{if(!g[e+o.role]){g[e+o.role]=new Hash()}}o.connects.each((function(p){var s=[];if(p.to){if(!(p.to instanceof Array)){p.to=[p.to]}p.to.each((function(t){if(this._isRoleOfOtherNamespace(t)){s.push(t)}else{s.push(e+t)}}).bind(this))}var r,q;if(this._isRoleOfOtherNamespace(o.role)){r=o.role}else{r=e+o.role}if(this._isRoleOfOtherNamespace(p.from)){q=p.from}else{q=e+p.from}if(!g[r][q]){g[r][q]=s}else{g[r][q]=g[r][q].concat(s)}}).bind(this))}).bind(this))}var c=this._cardinalityRules;if(m.cardinalityRules){m.cardinalityRules.each((function(q){var o;if(this._isRoleOfOtherNamespace(q.role)){o=q.role}else{o=e+q.role}if(!c[o]){c[o]={};for(i in q){c[o][i]=q[i]}}var r=new Hash();if(q.outgoingEdges){q.outgoingEdges.each((function(s){if(this._isRoleOfOtherNamespace(s.role)){r[s.role]=s}else{r[e+s.role]=s}}).bind(this))}c[o].outgoingEdges=r;var p=new Hash();if(q.incomingEdges){q.incomingEdges.each((function(s){if(this._isRoleOfOtherNamespace(s.role)){p[s.role]=s}else{p[e+s.role]=s}}).bind(this))}c[o].incomingEdges=p}).bind(this))}var a=this._containmentRules;if(m.containmentRules){m.containmentRules.each((function(p){var o;if(this._isRoleOfOtherNamespace(p.role)){o=p.role}else{this._containerStencils.push(e+p.role);o=e+p.role}if(!a[o]){a[o]=[]}(p.contains||[]).each((function(q){if(this._isRoleOfOtherNamespace(q)){a[o].push(q)}else{a[o].push(e+q)}}).bind(this))}).bind(this))}var d=this._morphingRules;if(m.morphingRules){m.morphingRules.each((function(p){var o;if(this._isRoleOfOtherNamespace(p.role)){o=p.role}else{o=e+p.role}if(!d[o]){d[o]=[]}if(!p.preserveBounds){p.preserveBounds=false}p.baseMorphs.each((function(r){var q=this._getStencilById(e+r);if(q){d[o].push(q)}}).bind(this))}).bind(this))}var h=this._layoutRules;if(m.layoutRules){var n=function(p){return{edgeRole:p.edgeRole||undefined,t:p.t||1,r:p.r||1,b:p.b||1,l:p.l||1}};m.layoutRules.each(function(p){var o;if(this._isRoleOfOtherNamespace(p.role)){o=p.role}else{o=e+p.role}if(!h[o]){h[o]={}}if(p[\"in\"]){h[o][\"in\"]=n(p[\"in\"])}if(p.ins){h[o][\"ins\"]=(p.ins||[]).map(function(q){return n(q)})}if(p.out){h[o][\"out\"]=n(p.out)}if(p.outs){h[o][\"outs\"]=(p.outs||[]).map(function(q){return n(q)})}}.bind(this))}}},_getStencilById:function(a){return this._stencils.find(function(b){return b.id()==a})},_cacheConnect:function(a){result=this._canConnect(a);if(a.sourceStencil&&a.targetStencil){var c=this._cachedConnectSET[a.sourceStencil.id()];if(!c){c=new Hash();this._cachedConnectSET[a.sourceStencil.id()]=c}var b=c[a.edgeStencil.id()];if(!b){b=new Hash();c[a.edgeStencil.id()]=b}b[a.targetStencil.id()]=result}else{if(a.sourceStencil){var c=this._cachedConnectSE[a.sourceStencil.id()];if(!c){c=new Hash();this._cachedConnectSE[a.sourceStencil.id()]=c}c[a.edgeStencil.id()]=result}else{var d=this._cachedConnectTE[a.targetStencil.id()];if(!d){d=new Hash();this._cachedConnectTE[a.targetStencil.id()]=d}d[a.edgeStencil.id()]=result}}return result},_cacheCard:function(b){if(b.sourceStencil){var c=this._cachedCardSE[b.sourceStencil.id()];if(!c){c=new Hash();this._cachedCardSE[b.sourceStencil.id()]=c}var a=this._getMaximumNumberOfOutgoingEdge(b);if(a==undefined){a=-1}c[b.edgeStencil.id()]=a}if(b.targetStencil){var d=this._cachedCardTE[b.targetStencil.id()];if(!d){d=new Hash();this._cachedCardTE[b.targetStencil.id()]=d}var a=this._getMaximumNumberOfIncomingEdge(b);if(a==undefined){a=-1}d[b.edgeStencil.id()]=a}},_cacheContain:function(b){var a=[this._canContain(b),this._getMaximumOccurrence(b.containingStencil,b.containedStencil)];if(a[1]==undefined){a[1]=-1}var c=this._cachedContainPC[b.containingStencil.id()];if(!c){c=new Hash();this._cachedContainPC[b.containingStencil.id()]=c}c[b.containedStencil.id()]=a;return a},_cacheMorph:function(b){var a=this._cachedMorphRS[b];if(!a){a=[];if(this._morphingRules.keys().include(b)){a=this._stencils.select(function(c){return c.roles().include(b)})}this._cachedMorphRS[b]=a}return a},outgoingEdgeStencils:function(a){if(!a.sourceShape&&!a.sourceStencil){return[]}if(a.sourceShape){a.sourceStencil=a.sourceShape.getStencil()}var b=[];this._stencils.each((function(d){if(d.type()===\"edge\"){var c=Object.clone(a);c.edgeStencil=d;if(this.canConnect(c)){b.push(d)}}}).bind(this));return b},incomingEdgeStencils:function(a){if(!a.targetShape&&!a.targetStencil){return[]}if(a.targetShape){a.targetStencil=a.targetShape.getStencil()}var b=[];this._stencils.each((function(d){if(d.type()===\"edge\"){var c=Object.clone(a);c.edgeStencil=d;if(this.canConnect(c)){b.push(d)}}}).bind(this));return b},sourceStencils:function(b){if(!b||!b.edgeShape&&!b.edgeStencil){return[]}if(b.targetShape){b.targetStencil=b.targetShape.getStencil()}if(b.edgeShape){b.edgeStencil=b.edgeShape.getStencil()}var a=[];this._stencils.each((function(d){var c=Object.clone(b);c.sourceStencil=d;if(this.canConnect(c)){a.push(d)}}).bind(this));return a},targetStencils:function(a){if(!a||!a.edgeShape&&!a.edgeStencil){return[]}if(a.sourceShape){a.sourceStencil=a.sourceShape.getStencil()}if(a.edgeShape){a.edgeStencil=a.edgeShape.getStencil()}var b=[];this._stencils.each((function(d){var c=Object.clone(a);c.targetStencil=d;if(this.canConnect(c)){b.push(d)}}).bind(this));return b},canConnect:function(c){if(!c||(!c.sourceShape&&!c.sourceStencil&&!c.targetShape&&!c.targetStencil)||!c.edgeShape&&!c.edgeStencil){return false}if(c.sourceShape){c.sourceStencil=c.sourceShape.getStencil()}if(c.targetShape){c.targetStencil=c.targetShape.getStencil()}if(c.edgeShape){c.edgeStencil=c.edgeShape.getStencil()}var b;if(c.sourceStencil&&c.targetStencil){var e=this._cachedConnectSET[c.sourceStencil.id()];if(!e){b=this._cacheConnect(c)}else{var d=e[c.edgeStencil.id()];if(!d){b=this._cacheConnect(c)}else{var f=d[c.targetStencil.id()];if(f==undefined){b=this._cacheConnect(c)}else{b=f}}}}else{if(c.sourceStencil){var e=this._cachedConnectSE[c.sourceStencil.id()];if(!e){b=this._cacheConnect(c)}else{var d=e[c.edgeStencil.id()];if(d==undefined){b=this._cacheConnect(c)}else{b=d}}}else{var f=this._cachedConnectTE[c.targetStencil.id()];if(!f){b=this._cacheConnect(c)}else{var d=f[c.edgeStencil.id()];if(d==undefined){b=this._cacheConnect(c)}else{b=d}}}}if(b){if(c.sourceShape){var e=this._cachedCardSE[c.sourceStencil.id()];if(!e){this._cacheCard(c);e=this._cachedCardSE[c.sourceStencil.id()]}var a=e[c.edgeStencil.id()];if(a==undefined){this._cacheCard(c)}a=e[c.edgeStencil.id()];if(a!=-1){b=c.sourceShape.getOutgoingShapes().all(function(g){if((g.getStencil().id()===c.edgeStencil.id())&&((c.edgeShape)?g!==c.edgeShape:true)){a--;return(a>0)?true:false}else{return true}})}}if(c.targetShape){var f=this._cachedCardTE[c.targetStencil.id()];if(!f){this._cacheCard(c);f=this._cachedCardTE[c.targetStencil.id()]}var a=f[c.edgeStencil.id()];if(a==undefined){this._cacheCard(c)}a=f[c.edgeStencil.id()];if(a!=-1){b=c.targetShape.getIncomingShapes().all(function(g){if((g.getStencil().id()===c.edgeStencil.id())&&((c.edgeShape)?g!==c.edgeShape:true)){a--;return(a>0)?true:false}else{return true}})}}}return b},_canConnect:function(b){if(!b||(!b.sourceShape&&!b.sourceStencil&&!b.targetShape&&!b.targetStencil)||!b.edgeShape&&!b.edgeStencil){return false}if(b.sourceShape){b.sourceStencil=b.sourceShape.getStencil()}if(b.targetShape){b.targetStencil=b.targetShape.getStencil()}if(b.edgeShape){b.edgeStencil=b.edgeShape.getStencil()}var c;var a=this._getConnectionRulesOfEdgeStencil(b.edgeStencil);if(a.keys().length===0){c=false}else{if(b.sourceStencil){c=b.sourceStencil.roles().any(function(e){var d=a[e];if(!d){return false}if(b.targetStencil){return(d.any(function(f){return b.targetStencil.roles().member(f)}))}else{return true}})}else{c=a.values().any(function(d){return b.targetStencil.roles().any(function(e){return d.member(e)})})}}return c},isContainer:function(a){return this._containerStencils.member(a.getStencil().id())},canContain:function(c){if(!c||!c.containingStencil&&!c.containingShape||!c.containedStencil&&!c.containedShape){return false}if(c.containedShape){c.containedStencil=c.containedShape.getStencil()}if(c.containingShape){c.containingStencil=c.containingShape.getStencil()}if(c.containedStencil.type()==\"edge\"){return false}var b;var d=this._cachedContainPC[c.containingStencil.id()];if(!d){b=this._cacheContain(c)}else{b=d[c.containedStencil.id()];if(!b){b=this._cacheContain(c)}}if(!b[0]){return false}else{if(b[1]==-1){return true}else{if(c.containingShape){var a=b[1];return c.containingShape.getChildShapes(false).all(function(e){if(e.getStencil().id()===c.containedStencil.id()){a--;return(a>0)?true:false}else{return true}})}else{return true}}}},_canContain:function(b){if(!b||!b.containingStencil&&!b.containingShape||!b.containedStencil&&!b.containedShape){return false}if(b.containedShape){b.containedStencil=b.containedShape.getStencil()}if(b.containingShape){b.containingStencil=b.containingShape.getStencil()}var a;a=b.containingStencil.roles().any((function(d){var c=this._containmentRules[d];if(c){return c.any(function(e){return b.containedStencil.roles().member(e)})}else{return false}}).bind(this));return a},morphStencils:function(b){if(!b.stencil&&!b.shape){return[]}if(b.shape){b.stencil=b.shape.getStencil()}var a=[];b.stencil.roles().each(function(d){this._cacheMorph(d).each(function(e){a.push(e)})}.bind(this));var c=this.baseMorphs();a=a.uniq().sort(function(e,d){return c.include(e)&&!c.include(d)?-1:(c.include(d)&&!c.include(e)?1:0)});return a},baseMorphs:function(){var a=[];this._morphingRules.each(function(b){b.value.each(function(c){a.push(c)})});return a},containsMorphingRules:function(){return this._stencilSets.any(function(a){return !!a.jsonRules().morphingRules})},connectMorph:function(e){if(!e||(!e.sourceShape&&!e.sourceStencil&&!e.targetShape&&!e.targetStencil)){return false}if(e.sourceShape){e.sourceStencil=e.sourceShape.getStencil()}if(e.targetShape){e.targetStencil=e.targetShape.getStencil()}var a=this.incomingEdgeStencils(e);var d=this.outgoingEdgeStencils(e);var c=a.select(function(f){return d.member(f)});var b=this.baseMorphs().select(function(f){return c.member(f)});if(b.size()>0){return b[0]}else{if(c.size()>0){return c[0]}}return null},showInShapeMenu:function(a){return this._stencilSets.any(function(b){return b.jsonRules().morphingRules.any(function(c){return a.roles().include(b.namespace()+c.role)&&c.showInShapeMenu!==false})})},preserveBounds:function(a){return this._stencilSets.any(function(b){return b.jsonRules().morphingRules.any(function(c){return a.roles().include(b.namespace()+c.role)&&c.preserveBounds})})},getLayoutingRules:function(b,d){if(!b||!(b instanceof ORYX.Core.Shape)){return}var c={\"in\":{},out:{}};var a=function(f,e){if(f&&f[e]){[\"t\",\"r\",\"b\",\"l\"].each(function(g){c[e][g]=Math.max(f[e][g],c[e][g]||0)})}if(f&&f[e+\"s\"] instanceof Array){[\"t\",\"r\",\"b\",\"l\"].each(function(k){var g=f[e+\"s\"].find(function(l){return !l.edgeRole});var h;if(d instanceof ORYX.Core.Edge){h=f[e+\"s\"].find(function(l){return this._hasRole(d,l.edgeRole)}.bind(this))}c[e][k]=Math.max(h?h[k]:g[k],c[e][k]||0)}.bind(this))}}.bind(this);b.getStencil().roles().each(function(e){if(this._layoutRules[e]){a(this._layoutRules[e],\"in\");a(this._layoutRules[e],\"out\")}}.bind(this));[\"in\",\"out\"].each(function(e){[\"t\",\"r\",\"b\",\"l\"].each(function(f){c[e][f]=c[e][f]!==undefined?c[e][f]:1})});return c},_hasRole:function(b,c){if(!(b instanceof ORYX.Core.Shape)||!c){return}var a=b.getStencil().roles().any(function(d){return d==c});return a||b.getStencil().id()==(b.getStencil().namespace()+c)},_stencilsWithRole:function(a){return this._stencils.findAll(function(b){return(b.roles().member(a))?true:false})},_edgesWithRole:function(a){return this._stencils.findAll(function(b){return(b.roles().member(a)&&b.type()===\"edge\")?true:false})},_nodesWithRole:function(a){return this._stencils.findAll(function(b){return(b.roles().member(a)&&b.type()===\"node\")?true:false})},_getMaximumOccurrence:function(b,c){var a;c.roles().each((function(e){var d=this._cardinalityRules[e];if(d&&d.maximumOccurrence){if(a){a=Math.min(a,d.maximumOccurrence)}else{a=d.maximumOccurrence}}}).bind(this));return a},_getMaximumNumberOfOutgoingEdge:function(b){if(!b||!b.sourceStencil||!b.edgeStencil){return false}var a;b.sourceStencil.roles().each((function(d){var c=this._cardinalityRules[d];if(c&&c.outgoingEdges){b.edgeStencil.roles().each(function(e){var f=c.outgoingEdges[e];if(f&&f.maximum){if(a){a=Math.min(a,f.maximum)}else{a=f.maximum}}})}}).bind(this));return a},_getMaximumNumberOfIncomingEdge:function(b){if(!b||!b.targetStencil||!b.edgeStencil){return false}var a;b.targetStencil.roles().each((function(d){var c=this._cardinalityRules[d];if(c&&c.incomingEdges){b.edgeStencil.roles().each(function(e){var f=c.incomingEdges[e];if(f&&f.maximum){if(a){a=Math.min(a,f.maximum)}else{a=f.maximum}}})}}).bind(this));return a},_getConnectionRulesOfEdgeStencil:function(b){var a=new Hash();b.roles().each((function(c){if(this._connectionRules[c]){this._connectionRules[c].each(function(d){if(a[d.key]){a[d.key]=a[d.key].concat(d.value)}else{a[d.key]=d.value}})}}).bind(this));return a},_isRoleOfOtherNamespace:function(a){return(a.indexOf(\"#\")>0)},toString:function(){return\"Rules\"}};ORYX.Core.StencilSet.Rules=Clazz.extend(ORYX.Core.StencilSet.Rules);if(!ORYX){var ORYX={}}if(!ORYX.Core){ORYX.Core={}}if(!ORYX.Core.StencilSet){ORYX.Core.StencilSet={}}ORYX.Core.StencilSet.StencilSet=Clazz.extend({construct:function(c,b,a){arguments.callee.$.construct.apply(this,arguments);if(!c){throw\"ORYX.Core.StencilSet.StencilSet(construct): Parameter 'source' is not defined.\"}if(c.endsWith(\"/\")){c=c.substr(0,c.length-1)}this._extensions=new Hash();this._source=c;this._baseUrl=c.substring(0,c.lastIndexOf(\"/\")+1);this._jsonObject={};this._stencils=new Hash();this._availableStencils=new Hash();if(ORYX.CONFIG.BACKEND_SWITCH){this._baseUrl=\"editor/stencilsets/bpmn2.0/\";this._source=\"stencilsets/bpmn2.0/bpmn2.0.json\";new Ajax.Request(ACTIVITI.CONFIG.contextRoot+\"/editor/stencilset?version=\"+Date.now(),{asynchronous:false,method:\"get\",onSuccess:this._init.bind(this),onFailure:this._cancelInit.bind(this)})}else{new Ajax.Request(c,{asynchronous:false,method:\"get\",onSuccess:this._init.bind(this),onFailure:this._cancelInit.bind(this)})}if(this.errornous){throw\"Loading stencil set \"+c+\" failed.\"}},findRootStencilName:function(){var a=this._stencils.values().find(function(b){return b._jsonStencil.mayBeRoot});if(!a){ORYX.Log.warn(\"Did not find any stencil that may be root. Taking a guess.\");a=this._stencils.values()[0]}return a.id()},equals:function(a){return(this.namespace()===a.namespace())},stencils:function(k,l,h){if(k&&l){var a=this._availableStencils.values();var e=[k];var d=[];var m=[];while(e.size()>0){var b=e.pop();d.push(b);var c=a.findAll(function(o){var n={containingStencil:b,containedStencil:o};return l.canContain(n)});for(var g=0;g<c.size();g++){if(!d.member(c[g])){e.push(c[g])}}m=m.concat(c).uniq()}m=m.sortBy(function(n){return a.indexOf(n)});if(h){m=m.sortBy(function(n){return n.groups().first()})}var f=a.findAll(function(n){return n.type()==\"edge\"});m=m.concat(f);return m}else{if(h){return this._availableStencils.values().sortBy(function(n){return n.groups().first()})}else{return this._availableStencils.values()}}},nodes:function(){return this._availableStencils.values().findAll(function(a){return(a.type()===\"node\")})},edges:function(){return this._availableStencils.values().findAll(function(a){return(a.type()===\"edge\")})},stencil:function(a){return this._stencils[a]},title:function(){return ORYX.Core.StencilSet.getTranslation(this._jsonObject,\"title\")},description:function(){return ORYX.Core.StencilSet.getTranslation(this._jsonObject,\"description\")},namespace:function(){return this._jsonObject?this._jsonObject.namespace:null},jsonRules:function(){return this._jsonObject?this._jsonObject.rules:null},source:function(){return this._source},extensions:function(){return this._extensions},addExtension:function(a){new Ajax.Request(a,{method:\"GET\",asynchronous:false,onSuccess:(function(b){this.addExtensionDirectly(b.responseText)}).bind(this),onFailure:(function(b){ORYX.Log.debug(\"Loading stencil set extension file failed. The request returned an error.\"+b)}).bind(this),onException:(function(b){ORYX.Log.debug(\"Loading stencil set extension file failed. The request returned an error.\"+b)}).bind(this)})},addExtensionDirectly:function(str){try{eval(\"var jsonExtension = \"+str);if(!(jsonExtension[\"extends\"].endsWith(\"#\"))){jsonExtension[\"extends\"]+=\"#\"}if(jsonExtension[\"extends\"]==this.namespace()){this._extensions[jsonExtension.namespace]=jsonExtension;var defaultPosition=this._stencils.keys().size();if(jsonExtension.stencils){$A(jsonExtension.stencils).each(function(stencil){defaultPosition++;var oStencil=new ORYX.Core.StencilSet.Stencil(stencil,this.namespace(),this._baseUrl,this,undefined,defaultPosition);this._stencils[oStencil.id()]=oStencil;this._availableStencils[oStencil.id()]=oStencil}.bind(this))}if(jsonExtension.properties){var stencils=this._stencils.values();stencils.each(function(stencil){var roles=stencil.roles();jsonExtension.properties.each(function(prop){prop.roles.any(function(role){role=jsonExtension[\"extends\"]+role;if(roles.member(role)){prop.properties.each(function(property){stencil.addProperty(property,jsonExtension.namespace)});return true}else{return false}})})}.bind(this))}if(jsonExtension.removeproperties){jsonExtension.removeproperties.each(function(remprop){var stencil=this.stencil(jsonExtension[\"extends\"]+remprop.stencil);if(stencil){remprop.properties.each(function(propId){stencil.removeProperty(propId)})}}.bind(this))}if(jsonExtension.removestencils){$A(jsonExtension.removestencils).each(function(remstencil){delete this._availableStencils[jsonExtension[\"extends\"]+remstencil]}.bind(this))}}}catch(e){ORYX.Log.debug(\"StencilSet.addExtension: Something went wrong when initialising the stencil set extension. \"+e)}},removeExtension:function(a){var b=this._extensions[a];if(b){if(b.stencils){$A(b.stencils).each(function(e){var d=new ORYX.Core.StencilSet.Stencil(e,this.namespace(),this._baseUrl,this);delete this._stencils[d.id()];delete this._availableStencils[d.id()]}.bind(this))}if(b.properties){var c=this._stencils.values();c.each(function(e){var d=e.roles();b.properties.each(function(f){f.roles.any(function(g){g=b[\"extends\"]+g;if(d.member(g)){f.properties.each(function(h){e.removeProperty(h.id)});return true}else{return false}})})}.bind(this))}if(b.removeproperties){b.removeproperties.each(function(f){var e=this.stencil(b[\"extends\"]+f.stencil);if(e){var d=$A(this._jsonObject.stencils).find(function(g){return g.id==e.id()});f.properties.each(function(h){var g=$A(d.properties).find(function(k){return k.id==h});e.addProperty(g,this.namespace())}.bind(this))}}.bind(this))}if(b.removestencils){$A(b.removestencils).each(function(d){var e=b[\"extends\"]+d;this._availableStencils[e]=this._stencils[e]}.bind(this))}}delete this._extensions[a]},__handleStencilset:function(response){try{eval(\"this._jsonObject =\"+response.responseText)}catch(e){throw\"Stenciset corrupt: \"+e}if(!this._jsonObject){throw\"Error evaluating stencilset. It may be corrupt.\"}with(this._jsonObject){if(!namespace||namespace===\"\"){throw\"Namespace definition missing in stencilset.\"}if(!(stencils instanceof Array)){throw\"Stencilset corrupt.\"}if(!namespace.endsWith(\"#\")){namespace=namespace+\"#\"}if(!title){title=\"\"}if(!description){description=\"\"}}},_init:function(c){this.__handleStencilset(c);var b=new Hash();if(this._jsonObject.propertyPackages){$A(this._jsonObject.propertyPackages).each((function(d){b[d.name]=d.properties}).bind(this))}var a=0;$A(this._jsonObject.stencils).each((function(e){a++;var d=new ORYX.Core.StencilSet.Stencil(e,this.namespace(),this._baseUrl,this,b,a);this._stencils[d.id()]=d;this._availableStencils[d.id()]=d}).bind(this))},_cancelInit:function(a){this.errornous=true},toString:function(){return\"StencilSet \"+this.title()+\" (\"+this.namespace()+\")\"}});if(!ORYX){var ORYX={}}if(!ORYX.Core){ORYX.Core={}}if(!ORYX.Core.StencilSet){ORYX.Core.StencilSet={}}ORYX.Core.StencilSet._stencilSetsByNamespace=new Hash();ORYX.Core.StencilSet._stencilSetsByUrl=new Hash();ORYX.Core.StencilSet._StencilSetNSByEditorInstance=new Hash();ORYX.Core.StencilSet._rulesByEditorInstance=new Hash();ORYX.Core.StencilSet.stencilSets=function(b){var c=ORYX.Core.StencilSet._StencilSetNSByEditorInstance[b];var a=new Hash();if(c){c.each(function(e){var d=ORYX.Core.StencilSet.stencilSet(e);a[d.namespace()]=d})}return a};ORYX.Core.StencilSet.stencilSet=function(a){ORYX.Log.trace(\"Getting stencil set %0\",a);var b=a.split(\"#\",1);if(b.length===1){ORYX.Log.trace(\"Getting stencil set %0\",b[0]);return ORYX.Core.StencilSet._stencilSetsByNamespace[b[0]+\"#\"]}else{return undefined}};ORYX.Core.StencilSet.stencil=function(b){ORYX.Log.trace(\"Getting stencil for %0\",b);var a=ORYX.Core.StencilSet.stencilSet(b);if(a){return a.stencil(b)}else{ORYX.Log.trace(\"Cannot fild stencil for %0\",b);return undefined}};ORYX.Core.StencilSet.rules=function(a){if(!ORYX.Core.StencilSet._rulesByEditorInstance[a]){ORYX.Core.StencilSet._rulesByEditorInstance[a]=new ORYX.Core.StencilSet.Rules()}return ORYX.Core.StencilSet._rulesByEditorInstance[a]};ORYX.Core.StencilSet.loadStencilSet=function(a,d,c){stencilSet=new ORYX.Core.StencilSet.StencilSet(a,d,c);ORYX.Core.StencilSet._stencilSetsByNamespace[stencilSet.namespace()]=stencilSet;ORYX.Core.StencilSet._stencilSetsByUrl[a]=stencilSet;var b=stencilSet.namespace();if(ORYX.Core.StencilSet._StencilSetNSByEditorInstance[c]){ORYX.Core.StencilSet._StencilSetNSByEditorInstance[c].push(b)}else{ORYX.Core.StencilSet._StencilSetNSByEditorInstance[c]=[b]}if(ORYX.Core.StencilSet._rulesByEditorInstance[c]){ORYX.Core.StencilSet._rulesByEditorInstance[c].initializeRules(stencilSet)}else{var e=new ORYX.Core.StencilSet.Rules();e.initializeRules(stencilSet);ORYX.Core.StencilSet._rulesByEditorInstance[c]=e}};ORYX.Core.StencilSet.getTranslation=function(c,b){var d=ORYX.I18N.Language.toLowerCase();var a=c[b+\"_\"+d];if(a){return a}a=c[b+\"_\"+d.substr(0,2)];if(a){return a}return c[b]};if(!ORYX){var ORYX={}}if(!ORYX.Core){ORYX.Core={}}ORYX.Core.Command=Clazz.extend({construct:function(){},execute:function(){throw\"Command.execute() has to be implemented!\"},rollback:function(){throw\"Command.rollback() has to be implemented!\"}});if(!ORYX){var ORYX={}}if(!ORYX.Core){ORYX.Core={}}ORYX.Core.Bounds={construct:function(){this._changedCallbacks=[];this.a={};this.b={};this.set.apply(this,arguments);this.suspendChange=false;this.changedWhileSuspend=false},_changed:function(a){if(!this.suspendChange){this._changedCallbacks.each(function(b){b(this,a)}.bind(this));this.changedWhileSuspend=false}else{this.changedWhileSuspend=true}},registerCallback:function(a){if(!this._changedCallbacks.member(a)){this._changedCallbacks.push(a)}},unregisterCallback:function(a){this._changedCallbacks=this._changedCallbacks.without(a)},set:function(){var e=false;switch(arguments.length){case 1:if(this.a.x!==arguments[0].a.x){e=true;this.a.x=arguments[0].a.x}if(this.a.y!==arguments[0].a.y){e=true;this.a.y=arguments[0].a.y}if(this.b.x!==arguments[0].b.x){e=true;this.b.x=arguments[0].b.x}if(this.b.y!==arguments[0].b.y){e=true;this.b.y=arguments[0].b.y}break;case 2:var b=Math.min(arguments[0].x,arguments[1].x);var a=Math.min(arguments[0].y,arguments[1].y);var d=Math.max(arguments[0].x,arguments[1].x);var c=Math.max(arguments[0].y,arguments[1].y);if(this.a.x!==b){e=true;this.a.x=b}if(this.a.y!==a){e=true;this.a.y=a}if(this.b.x!==d){e=true;this.b.x=d}if(this.b.y!==c){e=true;this.b.y=c}break;case 4:var b=Math.min(arguments[0],arguments[2]);var a=Math.min(arguments[1],arguments[3]);var d=Math.max(arguments[0],arguments[2]);var c=Math.max(arguments[1],arguments[3]);if(this.a.x!==b){e=true;this.a.x=b}if(this.a.y!==a){e=true;this.a.y=a}if(this.b.x!==d){e=true;this.b.x=d}if(this.b.y!==c){e=true;this.b.y=c}break}if(e){this._changed(true)}},moveTo:function(){var a=this.upperLeft();switch(arguments.length){case 1:this.moveBy({x:arguments[0].x-a.x,y:arguments[0].y-a.y});break;case 2:this.moveBy({x:arguments[0]-a.x,y:arguments[1]-a.y});break;default:}},moveBy:function(){var c=false;switch(arguments.length){case 1:var b=arguments[0];if(b.x!==0||b.y!==0){c=true;this.a.x+=b.x;this.b.x+=b.x;this.a.y+=b.y;this.b.y+=b.y}break;case 2:var a=arguments[0];var d=arguments[1];if(a!==0||d!==0){c=true;this.a.x+=a;this.b.x+=a;this.a.y+=d;this.b.y+=d}break;default:}if(c){this._changed()}},include:function(c){if((this.a.x===undefined)&&(this.a.y===undefined)&&(this.b.x===undefined)&&(this.b.y===undefined)){return c}var a=Math.min(this.a.x,c.a.x);var f=Math.min(this.a.y,c.a.y);var e=Math.max(this.b.x,c.b.x);var d=Math.max(this.b.y,c.b.y);this.set(a,f,e,d)},extend:function(a){if(a.x!==0||a.y!==0){this.b.x+=a.x;this.b.y+=a.y;this._changed(true)}},widen:function(a){if(a!==0){this.suspendChange=true;this.moveBy({x:-a,y:-a});this.extend({x:2*a,y:2*a});this.suspendChange=false;if(this.changedWhileSuspend){this._changed(true)}}},upperLeft:function(){var a={};a.x=this.a.x;a.y=this.a.y;return a},lowerRight:function(){var a={};a.x=this.b.x;a.y=this.b.y;return a},width:function(){return this.b.x-this.a.x},height:function(){return this.b.y-this.a.y},center:function(){var a={};a.x=(this.a.x+this.b.x)/2;a.y=(this.a.y+this.b.y)/2;return a},midPoint:function(){var a={};a.x=(this.b.x-this.a.x)/2;a.y=(this.b.y-this.a.y)/2;return a},centerMoveTo:function(){var a=this.center();switch(arguments.length){case 1:this.moveBy(arguments[0].x-a.x,arguments[0].y-a.y);break;case 2:this.moveBy(arguments[0]-a.x,arguments[1]-a.y);break}},isIncluded:function(a,e){var f,d,e;switch(arguments.length){case 1:f=arguments[0].x;d=arguments[0].y;e=0;break;case 2:if(arguments[0].x&&arguments[0].y){f=arguments[0].x;d=arguments[0].y;e=Math.abs(arguments[1])}else{f=arguments[0];d=arguments[1];e=0}break;case 3:f=arguments[0];d=arguments[1];e=Math.abs(arguments[2]);break;default:throw\"isIncluded needs one, two or three arguments\"}var c=this.upperLeft();var b=this.lowerRight();if(f>=c.x-e&&f<=b.x+e&&d>=c.y-e&&d<=b.y+e){return true}else{return false}},clone:function(){return new ORYX.Core.Bounds(this)},toString:function(){return\"( \"+this.a.x+\" | \"+this.a.y+\" )/( \"+this.b.x+\" | \"+this.b.y+\" )\"},serializeForERDF:function(){return this.a.x+\",\"+this.a.y+\",\"+this.b.x+\",\"+this.b.y}};ORYX.Core.Bounds=Clazz.extend(ORYX.Core.Bounds);if(!ORYX){var ORYX={}}if(!ORYX.Core){ORYX.Core={}}ORYX.Core.UIObject={construct:function(a){this.isChanged=true;this.isResized=true;this.isVisible=true;this.isSelectable=false;this.isResizable=false;this.isMovable=false;this.id=ORYX.Editor.provideId();this.parent=undefined;this.node=undefined;this.children=[];this.bounds=new ORYX.Core.Bounds();this._changedCallback=this._changed.bind(this);this.bounds.registerCallback(this._changedCallback);if(a&&a.eventHandlerCallback){this.eventHandlerCallback=a.eventHandlerCallback}},_changed:function(b,a){this.isChanged=true;if(this.bounds==b){this.isResized=a||this.isResized}},update:function(){if(this.isChanged){this.refresh();this.isChanged=false;this.children.each(function(a){a.update()})}},refresh:function(){},getChildren:function(){return this.children.clone()},getParents:function(){var a=[];var b=this.parent;while(b){a.push(b);b=b.parent}return a},isParent:function(a){var b=this;while(b){if(b===a){return true}b=b.parent}return false},getId:function(){return this.id},getChildById:function(b,a){return this.children.find(function(c){if(c.getId()===b){return c}else{if(a){var d=c.getChildById(b,a);if(d){return d}}}})},add:function(a){if(!(this.children.member(a))){if(a.parent){a.remove(a)}this.children.push(a);a.parent=this;a.node=this.node.appendChild(a.node);a.bounds.registerCallback(this._changedCallback)}else{ORYX.Log.info(\"add: ORYX.Core.UIObject is already a child of this object.\")}},remove:function(a){if(this.children.member(a)){this.children=this._uiObjects.without(a);a.parent=undefined;a.node=this.node.removeChild(a.node);a.bounds.unregisterCallback(this._changedCallback)}else{ORYX.Log.info(\"remove: ORYX.Core.UIObject is not a child of this object.\")}},absoluteBounds:function(){if(this.parent){var a=this.absoluteXY();return new ORYX.Core.Bounds(a.x,a.y,a.x+this.bounds.width(),a.y+this.bounds.height())}else{return this.bounds.clone()}},absoluteXY:function(){if(this.parent){var b=this.parent.absoluteXY();var a={};a.x=b.x+this.bounds.upperLeft().x;a.y=b.y+this.bounds.upperLeft().y;return a}else{var a={};a.x=this.bounds.upperLeft().x;a.y=this.bounds.upperLeft().y;return a}},absoluteCenterXY:function(){if(this.parent){var b=this.parent.absoluteXY();var a={};a.x=b.x+this.bounds.center().x;a.y=b.y+this.bounds.center().y;return a}else{var a={};a.x=this.bounds.center().x;a.y=this.bounds.center().y;return a}},hide:function(){this.node.setAttributeNS(null,\"display\",\"none\");this.isVisible=false;this.children.each(function(a){a.hide()})},show:function(){this.node.setAttributeNS(null,\"display\",\"inherit\");this.isVisible=true;this.children.each(function(a){a.show()})},addEventHandlers:function(a){a.addEventListener(ORYX.CONFIG.EVENT_MOUSEDOWN,this._delegateEvent.bind(this),false);a.addEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE,this._delegateEvent.bind(this),false);a.addEventListener(ORYX.CONFIG.EVENT_MOUSEUP,this._delegateEvent.bind(this),false);a.addEventListener(ORYX.CONFIG.EVENT_MOUSEOVER,this._delegateEvent.bind(this),false);a.addEventListener(ORYX.CONFIG.EVENT_MOUSEOUT,this._delegateEvent.bind(this),false);a.addEventListener(\"click\",this._delegateEvent.bind(this),false);a.addEventListener(ORYX.CONFIG.EVENT_DBLCLICK,this._delegateEvent.bind(this),false)},_delegateEvent:function(a){if(this.eventHandlerCallback){this.eventHandlerCallback(a,this)}},toString:function(){return\"UIObject \"+this.id}};ORYX.Core.UIObject=Clazz.extend(ORYX.Core.UIObject);if(!ORYX){var ORYX={}}if(!ORYX.Core){ORYX.Core={}}ORYX.Core.AbstractShape=ORYX.Core.UIObject.extend({construct:function(a,c,b){arguments.callee.$.construct.apply(this,arguments);this.resourceId=ORYX.Editor.provideId();this._stencil=c;if(this._stencil._jsonStencil.superId){stencilId=this._stencil.id();superStencilId=stencilId.substring(0,stencilId.indexOf(\"#\")+1)+c._jsonStencil.superId;stencilSet=this._stencil.stencilSet();this._stencil=stencilSet.stencil(superStencilId)}this.properties=new Hash();this.propertiesChanged=new Hash();this.hiddenProperties=new Hash();this._stencil.properties().each((function(e){var d=e.prefix()+\"-\"+e.id();this.properties[d]=e.value();this.propertiesChanged[d]=true}).bind(this));if(c._jsonStencil.superId){c.properties().each((function(g){var e=g.prefix()+\"-\"+g.id();var f=g.value();var d=this.properties[e];this.properties[e]=f;this.propertiesChanged[e]=true;this._delegateEvent({type:ORYX.CONFIG.EVENT_PROPERTY_CHANGED,name:e,value:f,oldValue:d})}).bind(this))}},layout:function(){},getStencil:function(){return this._stencil},getChildShapeByResourceId:function(a){a=ERDF.__stripHashes(a);return this.getChildShapes(true).find(function(b){return b.resourceId==a})},getChildShapes:function(b,c){var a=[];this.children.each(function(d){if(d instanceof ORYX.Core.Shape&&d.isVisible){if(c){c(d)}a.push(d);if(b){a=a.concat(d.getChildShapes(b,c))}}});return a},hasChildShape:function(a){return this.getChildShapes().any(function(b){return(b===a)||b.hasChildShape(a)})},getChildNodes:function(b,c){var a=[];this.children.each(function(d){if(d instanceof ORYX.Core.Node&&d.isVisible){if(c){c(d)}a.push(d)}if(d instanceof ORYX.Core.Shape){if(b){a=a.concat(d.getChildNodes(b,c))}}});return a},getChildEdges:function(b,c){var a=[];this.children.each(function(d){if(d instanceof ORYX.Core.Edge&&d.isVisible){if(c){c(d)}a.push(d)}if(d instanceof ORYX.Core.Shape){if(b){a=a.concat(d.getChildEdges(b,c))}}});return a},getAbstractShapesAtPosition:function(){var b,e;switch(arguments.length){case 1:b=arguments[0].x;e=arguments[0].y;break;case 2:b=arguments[0];e=arguments[1];break;default:throw\"getAbstractShapesAtPosition needs 1 or 2 arguments!\"}if(this.isPointIncluded(b,e)){var a=[];a.push(this);var d=this.getChildNodes();var c=this.getChildEdges();[d,c].each(function(f){var g=new Hash();f.each(function(h){if(!h.isVisible){return}var l=h.getAbstractShapesAtPosition(b,e);if(l.length>0){var k=$A(h.node.parentNode.childNodes);var m=k.indexOf(h.node);g[m]=l}});g.keys().sort().each(function(h){a=a.concat(g[h])})});return a}else{return[]}},setProperty:function(b,d,c){var a=this.properties[b];if(a!==d||c===true){this.properties[b]=d;this.propertiesChanged[b]=true;this._changed();if(!this._isInSetProperty){this._isInSetProperty=true;this._delegateEvent({type:ORYX.CONFIG.EVENT_PROPERTY_CHANGED,elements:[this],name:b,value:d,oldValue:a});delete this._isInSetProperty}}},isPropertyChanged:function(){return this.propertiesChanged.any(function(a){return a.value})},setHiddenProperty:function(b,c){if(c===undefined){delete this.hiddenProperties[b];return}var a=this.hiddenProperties[b];if(a!==c){this.hiddenProperties[b]=c}},isPointIncluded:function(d,c,b){var a=b?b:this.absoluteBounds();return a.isIncluded(d,c)},serialize:function(){var a=[];a.push({name:\"type\",prefix:\"oryx\",value:this.getStencil().id(),type:\"literal\"});this.hiddenProperties.each(function(b){a.push({name:b.key.replace(\"oryx-\",\"\"),prefix:\"oryx\",value:b.value,type:\"literal\"})}.bind(this));this.getStencil().properties().each((function(d){var c=d.prefix();var b=d.id();a.push({name:b,prefix:c,value:this.properties[c+\"-\"+b],type:\"literal\"})}).bind(this));return a},deserialize:function(b){var a=0;b=b.sort(function(d,c){d=Number(this.properties.keys().member(d.prefix+\"-\"+d.name));c=Number(this.properties.keys().member(c.prefix+\"-\"+c.name));return d>c?1:(d<c?-1:0)}.bind(this));b.each((function(g){var c=g.name;var f=g.prefix;var e=g.value;if(Object.prototype.toString.call(e)===\"Object\"){e=JSON.stringify(e)}switch(f+\"-\"+c){case\"raziel-parent\":if(!this.parent){break}var d=this.getCanvas().getChildShapeByResourceId(e);if(d){d.add(this)}break;default:var h=this.getStencil().property(f+\"-\"+c);if(h&&h.isList()&&typeof e===\"string\"){if((e||\"\").strip()&&!e.startsWith(\"[\")&&!e.startsWith(\"]\")){e='[\"'+e.strip()+'\"]'}e=((e||\"\").strip()||\"[]\").evalJSON()}if(this.properties.keys().member(f+\"-\"+c)){this.setProperty(f+\"-\"+c,e)}else{if(!(c===\"bounds\"||c===\"parent\"||c===\"target\"||c===\"dockers\"||c===\"docker\"||c===\"outgoing\"||c===\"incoming\")){this.setHiddenProperty(f+\"-\"+c,e)}}}}).bind(this))},toString:function(){return\"ORYX.Core.AbstractShape \"+this.id},toJSON:function(){var a={resourceId:this.resourceId,properties:jQuery.extend({},this.properties,this.hiddenProperties).inject({},function(d,h){var c=h[0];var f=h[1];if(this.getStencil().property(c)&&this.getStencil().property(c).type()===ORYX.CONFIG.TYPE_COMPLEX&&Object.prototype.toString.call(f)===\"String\"){try{f=JSON.parse(f)}catch(b){}}else{if(f instanceof Date&&this.getStencil().property(c)){try{f=f.format(this.getStencil().property(c).dateFormat())}catch(g){}}}c=c.replace(/^[\\w_]+-/,\"\");d[c]=f;return d}.bind(this)),stencil:{id:this.getStencil().idWithoutNs()},childShapes:this.getChildShapes().map(function(b){return b.toJSON()})};if(this.getOutgoingShapes){a.outgoing=this.getOutgoingShapes().map(function(b){return{resourceId:b.resourceId}})}if(this.bounds){a.bounds={lowerRight:this.bounds.lowerRight(),upperLeft:this.bounds.upperLeft()}}if(this.dockers){a.dockers=this.dockers.map(function(b){var c=b.getDockedShape()&&b.referencePoint?b.referencePoint:b.bounds.center();c.getDocker=function(){return b};return c})}jQuery.extend(a,ORYX.Core.AbstractShape.JSONHelper);a.getShape=function(){return this}.bind(this);return a}});ORYX.Core.AbstractShape.JSONHelper={eachChild:function(c,b,d){if(!this.childShapes){return}var a=[];this.childShapes.each(function(e){if(!(e.eachChild instanceof Function)){jQuery.extend(e,ORYX.Core.AbstractShape.JSONHelper)}var f=c(e,this);if(f){a.push(f)}if(b){e.eachChild(c,b,d)}}.bind(this));if(d){this.childShapes=a}},getShape:function(){return null},getChildShapes:function(a){var b=this.childShapes;if(a){this.eachChild(function(c){if(!(c.getChildShapes instanceof Function)){jQuery.extend(c,ORYX.Core.AbstractShape.JSONHelper)}b=b.concat(c.getChildShapes(a))},true)}return b},serialize:function(){return JSON.stringify(this)}};if(!ORYX){var ORYX={}}if(!ORYX.Core){ORYX.Core={}}ORYX.Core.Canvas=ORYX.Core.AbstractShape.extend({zoomLevel:1,construct:function(a,c,b){arguments.callee.$.construct.apply(this,arguments);if(!(a&&a.width&&a.height)){ORYX.Log.fatal(\"Canvas is missing mandatory parameters options.width and options.height.\");return}this.facade=b;this.resourceId=a.id;this.nodes=[];this.edges=[];this.colHighlightState=0;this.colHighlightEnabled=false;this.rootNode=ORYX.Editor.graft(\"http://www.w3.org/2000/svg\",a.parentNode,[\"svg\",{id:this.id,width:a.width,height:a.height},[\"defs\",{}]]);this.rootNode.setAttribute(\"xmlns:xlink\",\"http://www.w3.org/1999/xlink\");this.rootNode.setAttribute(\"xmlns:svg\",\"http://www.w3.org/2000/svg\");this._htmlContainer=ORYX.Editor.graft(\"http://www.w3.org/1999/xhtml\",a.parentNode,[\"div\",{id:\"oryx_canvas_htmlContainer\",style:\"position:absolute; top:5px\"}]);this.underlayNode=ORYX.Editor.graft(\"http://www.w3.org/2000/svg\",this.rootNode,[\"svg\",{id:\"underlay-container\"}]);this.columnHightlight1=ORYX.Editor.graft(\"http://www.w3.org/2000/svg\",this.underlayNode,[\"rect\",{x:0,width:ORYX.CONFIG.FORM_ROW_WIDTH+35,height:\"100%\",style:\"fill: #fff6d5\",visibility:\"hidden\"}]);this.columnHightlight2=ORYX.Editor.graft(\"http://www.w3.org/2000/svg\",this.underlayNode,[\"rect\",{x:ORYX.CONFIG.FORM_ROW_WIDTH+35,width:ORYX.CONFIG.FORM_ROW_WIDTH+25,height:\"100%\",style:\"fill: #fff6d5\",visibility:\"hidden\"}]);this.node=ORYX.Editor.graft(\"http://www.w3.org/2000/svg\",this.rootNode,[\"g\",{},[\"g\",{\"class\":\"stencils\"},[\"g\",{\"class\":\"me\"}],[\"g\",{\"class\":\"children\"}],[\"g\",{\"class\":\"edge\"}]],[\"g\",{\"class\":\"svgcontainer\"}]]);this.node.setAttributeNS(null,\"stroke\",\"none\");this.node.setAttributeNS(null,\"font-family\",\"Verdana, sans-serif\");this.node.setAttributeNS(null,\"font-size-adjust\",\"none\");this.node.setAttributeNS(null,\"font-style\",\"normal\");this.node.setAttributeNS(null,\"font-variant\",\"normal\");this.node.setAttributeNS(null,\"font-weight\",\"normal\");this.node.setAttributeNS(null,\"line-heigth\",\"normal\");this.node.setAttributeNS(null,\"font-size\",ORYX.CONFIG.LABEL_DEFAULT_LINE_HEIGHT);this.bounds.set(0,0,a.width,a.height);this.addEventHandlers(this.rootNode.parentNode);this.rootNode.oncontextmenu=function(){return false}},focus:function(){try{if(!this.focusEl){this.focusEl=jQuery(\"body\").append(jQuery('<a href=\"#\" class=\"x-grid3-focus x-grid3-focus-canvas\"/>'));this.focusEl.swallowEvent(\"click\",true)}this.focusEl.focus.defer(1,this.focusEl);this.focusEl.blur.defer(3,this.focusEl)}catch(a){}},setHightlightState:function(a){if(this.colHighlightEnabled&&this.colHighlightState!=a){if(a==0){this.columnHightlight1.setAttribute(\"visibility\",\"hidden\");this.columnHightlight2.setAttribute(\"visibility\",\"hidden\")}else{if(a==1){this.columnHightlight1.setAttribute(\"visibility\",\"visible\");this.columnHightlight2.setAttribute(\"visibility\",\"hidden\")}else{if(a==2){this.columnHightlight1.setAttribute(\"visibility\",\"hidden\");this.columnHightlight2.setAttribute(\"visibility\",\"visible\")}else{if(a==3){this.columnHightlight1.setAttribute(\"visibility\",\"visible\");this.columnHightlight2.setAttribute(\"visibility\",\"visible\")}}}}this.colHighlightState=a}},setHightlightStateBasedOnX:function(a){if(a>ORYX.CONFIG.FORM_ROW_WIDTH+30){this.setHightlightState(2)}else{this.setHightlightState(1)}},update:function(){this.nodes.each(function(b){this._traverseForUpdate(b)}.bind(this));var a=this.getStencil().layout();if(a){a.each(function(b){b.shape=this;b.forceExecution=true;b.target=this.rootNode;this._delegateEvent(b)}.bind(this))}this.nodes.invoke(\"_update\");this.edges.invoke(\"_update\",true)},_traverseForUpdate:function(a){var b=a.isChanged;a.getChildNodes(false,function(c){if(this._traverseForUpdate(c)){b=true}}.bind(this));if(b){a.layout();return true}else{return false}},layout:function(){},getChildNodes:function(b,c){if(!b&&!c){return this.nodes.clone()}else{var a=[];this.nodes.each(function(d){if(c){c(d)}a.push(d);if(b&&d instanceof ORYX.Core.Shape){a=a.concat(d.getChildNodes(b,c))}});return a}},add:function(a,c,b){if(a instanceof ORYX.Core.UIObject){if(!(this.children.member(a))){if(a.parent){a.parent.remove(a,true)}if(c!=undefined){this.children.splice(c,0,a)}else{this.children.push(a)}a.parent=this;if(a instanceof ORYX.Core.Shape){if(a instanceof ORYX.Core.Edge){a.addMarkers(this.rootNode.getElementsByTagNameNS(NAMESPACE_SVG,\"defs\")[0]);a.node=this.node.childNodes[0].childNodes[2].appendChild(a.node);this.edges.push(a)}else{a.node=this.node.childNodes[0].childNodes[1].appendChild(a.node);this.nodes.push(a)}}else{a.node=this.node.appendChild(a.node)}a.bounds.registerCallback(this._changedCallback);if(this.eventHandlerCallback&&b!==true){this.eventHandlerCallback({type:ORYX.CONFIG.EVENT_SHAPEADDED,shape:a})}}else{ORYX.Log.warn(\"add: ORYX.Core.UIObject is already a child of this object.\")}}else{ORYX.Log.fatal(\"add: Parameter is not of type ORYX.Core.UIObject.\")}},remove:function(a,b){if(this.children.member(a)){var c=a.parent;this.children=this.children.without(a);a.parent=undefined;if(a instanceof ORYX.Core.Shape){if(a instanceof ORYX.Core.Edge){a.removeMarkers();a.node=this.node.childNodes[0].childNodes[2].removeChild(a.node);this.edges=this.edges.without(a)}else{a.node=this.node.childNodes[0].childNodes[1].removeChild(a.node);this.nodes=this.nodes.without(a)}}else{a.node=this.node.removeChild(a.node)}if(this.eventHandlerCallback&&b!==true){this.eventHandlerCallback({type:ORYX.CONFIG.EVENT_SHAPEREMOVED,shape:a,parent:c})}a.bounds.unregisterCallback(this._changedCallback)}else{ORYX.Log.warn(\"remove: ORYX.Core.UIObject is not a child of this object.\")}},addShapeObjects:function(d,c){if(!d){return}this.initializingShapes=true;var b=function(f,k){var l=ORYX.Core.StencilSet.stencil(this.getStencil().namespace()+f.stencil.id);var h=(l.type()==\"node\")?ORYX.Core.Node:ORYX.Core.Edge;var g=new h({eventHandlerCallback:c},l,this.facade);g.resourceId=f.resourceId;g.node.id=\"svg-\"+f.resourceId;f.parent=\"#\"+((f.parent&&f.parent.resourceId)||k.resourceId);this.add(g);return{json:f,object:g}}.bind(this);var e=function(f){var g=[];if(f.childShapes&&f.childShapes.constructor==String){f.childShapes=JSON.parse(f.childShapes)}f.childShapes.each(function(h){g.push(b(h,f));g=g.concat(e(h))});return g}.bind(this);var a=e({childShapes:d,resourceId:this.resourceId});a.each(function(f){var g=[];for(field in f.json.properties){g.push({prefix:\"oryx\",name:field,value:f.json.properties[field]})}f.json.outgoing.each(function(k){g.push({prefix:\"raziel\",name:\"outgoing\",value:\"#\"+k.resourceId})});if(f.object instanceof ORYX.Core.Edge){var h=f.json.target||f.json.outgoing[0];if(h){g.push({prefix:\"raziel\",name:\"target\",value:\"#\"+h.resourceId})}}if(f.json.bounds){g.push({prefix:\"oryx\",name:\"bounds\",value:f.json.bounds.upperLeft.x+\",\"+f.json.bounds.upperLeft.y+\",\"+f.json.bounds.lowerRight.x+\",\"+f.json.bounds.lowerRight.y})}if(f.json.dockers){g.push({prefix:\"oryx\",name:\"dockers\",value:f.json.dockers.inject(\"\",function(l,k){return l+k.x+\" \"+k.y+\" \"})+\" #\"})}g.push({prefix:\"raziel\",name:\"parent\",value:f.json.parent});f.__properties=g}.bind(this));a.each(function(f){if(f.object instanceof ORYX.Core.Node){f.object.deserialize(f.__properties,f.json)}});a.each(function(f){if(f.object instanceof ORYX.Core.Edge){f.object.deserialize(f.__properties,f.json);f.object._oldBounds=f.object.bounds.clone();f.object._update()}});delete this.initializingShapes;return a.pluck(\"object\")},updateSize:function(){var b=0;var a=0;var c=100;this.getChildShapes(true,function(e){var d=e.bounds;b=Math.max(b,d.lowerRight().x+c);a=Math.max(a,d.lowerRight().y+c)});if(this.bounds.width()<b||this.bounds.height()<a){this.setSize({width:Math.max(this.bounds.width(),b),height:Math.max(this.bounds.height(),a)})}},getRootNode:function(){return this.rootNode},getUnderlayNode:function(){return this.underlayNode},getSvgContainer:function(){return this.node.childNodes[1]},getHTMLContainer:function(){return this._htmlContainer},getShapesWithSharedParent:function(a){if(!a||a.length<1){return[]}if(a.length==1){return a}return a.findAll(function(c){var b=c.parent;while(b){if(a.member(b)){return false}b=b.parent}return true})},setSize:function(b,a){if(!b||!b.width||!b.height){return}if(this.rootNode.parentNode){this.rootNode.parentNode.style.width=b.width+\"px\";this.rootNode.parentNode.style.height=b.height+\"px\"}this.rootNode.setAttributeNS(null,\"width\",b.width);this.rootNode.setAttributeNS(null,\"height\",b.height);if(!a){this.bounds.set({a:{x:0,y:0},b:{x:b.width/this.zoomLevel,y:b.height/this.zoomLevel}})}},getSVGRepresentation:function(o){var k=this.getRootNode().cloneNode(true);this._removeInvisibleElements(k);var d,n,b,m;this.getChildShapes(true).each(function(q){var s=q.absoluteBounds();var r=s.upperLeft();var e=s.lowerRight();if(d==undefined){d=r.x;n=r.y;b=e.x;m=e.y}else{d=Math.min(d,r.x);n=Math.min(n,r.y);b=Math.max(b,e.x);m=Math.max(m,e.y)}});var f=50;var c,p,h,g;if(d==undefined){c=0;p=0;h=0;g=0}else{c=b;p=m;h=-d+f/2;g=-n+f/2}k.setAttributeNS(null,\"width\",c+f);k.setAttributeNS(null,\"height\",p+f);k.childNodes[1].removeAttributeNS(null,\"transform\");try{var a=k.childNodes[1].childNodes[1];a.parentNode.removeChild(a)}catch(l){}if(o){$A(k.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG,\"tspan\")).each(function(e){e.textContent=e.textContent.escapeHTML()});$A(k.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG,\"text\")).each(function(e){if(e.childNodes.length==0){e.textContent=e.textContent.escapeHTML()}})}$A(k.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG,\"image\")).each(function(q){var e=q.getAttributeNS(\"http://www.w3.org/1999/xlink\",\"href\");if(!e.match(\"^(http|https)://\")){e=window.location.protocol+\"//\"+window.location.host+e;q.setAttributeNS(\"http://www.w3.org/1999/xlink\",\"href\",e)}});$A(k.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG,\"a\")).each(function(e){e.setAttributeNS(\"http://www.w3.org/1999/xlink\",\"xlink:href\",(e.getAttributeNS(\"http://www.w3.org/1999/xlink\",\"href\")||\"\").escapeHTML())});return k},_removeInvisibleElements:function(b){var a=0;while(a<b.childNodes.length){var c=b.childNodes[a];if(c.getAttributeNS&&c.getAttributeNS(null,\"visibility\")===\"hidden\"){b.removeChild(c)}else{this._removeInvisibleElements(c);a++}}},_delegateEvent:function(a){if(this.eventHandlerCallback&&(a.target==this.rootNode||a.target==this.rootNode.parentNode)){this.eventHandlerCallback(a,this)}},toString:function(){return\"Canvas \"+this.id},toJSON:function(){var a=arguments.callee.$.toJSON.apply(this,arguments);a.stencilset={url:this.getStencil().stencilSet().source(),namespace:this.getStencil().stencilSet().namespace()};return a}});var idCounter=0;var ID_PREFIX=\"resource\";function init(){ORYX.Log.debug(\"Querying editor instances\");ORYX.Editor.setMissingClasses();if(window.onOryxResourcesLoaded){window.onOryxResourcesLoaded()}else{var b=window.location.search.substring(4);var a=\"./service/model/\"+b+\"/json\";ORYX.Editor.createByUrl(a)}}if(!ORYX){var ORYX={}}ORYX.Editor={DOMEventListeners:new Hash(),selection:[],zoomLevel:1,construct:function(d){this._eventsQueue=[];this.loadedPlugins=[];this.pluginsData=[];this.modelMetaData=d;var c=d;this.id=c.modelId;if(d.model){c=d.model}if(!this.id){this.id=c.id;if(!this.id){this.id=ORYX.Editor.provideId()}}this.fullscreen=d.fullscreen!==false;this._initEventListener();if(ORYX.CONFIG.BACKEND_SWITCH){var b=(c.stencilset.namespace||c.stencilset.url).replace(\"#\",\"%23\");ORYX.Core.StencilSet.loadStencilSet(b,this.modelMetaData,this.id)}else{var b=c.stencilset.url;ORYX.Core.StencilSet.loadStencilSet(b,this.modelMetaData,this.id)}this._createCanvas(c.stencil?c.stencil.id:null,c.properties);this._generateGUI();var f=false;var e=false;var a=function(){if(!f||!e){return}this._finishedLoading()}.bind(this);window.setTimeout(function(){this.loadPlugins();f=true;a()}.bind(this),100);window.setTimeout(function(){this.loadSerialized(c,true);this.getCanvas().update();e=true;a()}.bind(this),200)},_finishedLoading:function(){this.handleEvents({type:ORYX.CONFIG.EVENT_LOADED})},_initEventListener:function(){document.documentElement.addEventListener(ORYX.CONFIG.EVENT_KEYDOWN,this.catchKeyDownEvents.bind(this),false);document.documentElement.addEventListener(ORYX.CONFIG.EVENT_KEYUP,this.catchKeyUpEvents.bind(this),false);this._keydownEnabled=true;this._keyupEnabled=true;this.DOMEventListeners[ORYX.CONFIG.EVENT_MOUSEDOWN]=[];this.DOMEventListeners[ORYX.CONFIG.EVENT_MOUSEUP]=[];this.DOMEventListeners[ORYX.CONFIG.EVENT_MOUSEOVER]=[];this.DOMEventListeners[ORYX.CONFIG.EVENT_MOUSEOUT]=[];this.DOMEventListeners[ORYX.CONFIG.EVENT_SELECTION_CHANGED]=[];this.DOMEventListeners[ORYX.CONFIG.EVENT_MOUSEMOVE]=[]},_generateGUI:function(){var a=ORYX.CONFIG.WINDOW_HEIGHT;var b=this.getCanvas().rootNode.parentNode;jQuery(\"#canvasSection\").append(b);b.parentNode.setAttributeNS(null,\"align\",\"center\");b.setAttributeNS(null,\"align\",\"left\");this.getCanvas().setSize({width:ORYX.CONFIG.CANVAS_WIDTH,height:ORYX.CONFIG.CANVAS_HEIGHT})},getAvailablePlugins:function(){var a=ORYX.availablePlugins.clone();a.each(function(b){if(this.loadedPlugins.find(function(c){return c.type==this.name}.bind(b))){b.engaged=true}else{b.engaged=false}}.bind(this));return a},loadScript:function(b,c){var a=document.createElement(\"script\");a.type=\"text/javascript\";if(a.readyState){a.onreadystatechange=function(){if(a.readyState==\"loaded\"||a.readyState==\"complete\"){a.onreadystatechange=null;c()}}}else{a.onload=function(){c()}}a.src=b;document.getElementsByTagName(\"head\")[0].appendChild(a)},activatePluginByName:function(name,callback,loadTry){var match=this.getAvailablePlugins().find(function(value){return value.name==name});if(match&&(!match.engaged||(match.engaged===\"false\"))){var loadedStencilSetsNamespaces=this.getStencilSets().keys();var facade=this._getPluginFacade();var newPlugin;var me=this;ORYX.Log.debug(\"Initializing plugin '%0'\",match.name);if(!match.requires||!match.requires.namespaces||match.requires.namespaces.any(function(req){return loadedStencilSetsNamespaces.indexOf(req)>=0})){if(!match.notUsesIn||!match.notUsesIn.namespaces||!match.notUsesIn.namespaces.any(function(req){return loadedStencilSetsNamespaces.indexOf(req)>=0})){try{var className=eval(match.name);var newPlugin=new className(facade,match);newPlugin.type=match.name;if(newPlugin.registryChanged){newPlugin.registryChanged(me.pluginsData)}if(newPlugin.onSelectionChanged){me.registerOnEvent(ORYX.CONFIG.EVENT_SELECTION_CHANGED,newPlugin.onSelectionChanged.bind(newPlugin))}this.loadedPlugins.push(newPlugin);this.loadedPlugins.each(function(loaded){if(loaded.registryChanged){loaded.registryChanged(this.pluginsData)}}.bind(me));callback(true)}catch(e){ORYX.Log.warn(\"Plugin %0 is not available\",match.name);if(!!loadTry){callback(false,\"INITFAILED\");return}this.loadScript(\"plugins/scripts/\"+match.source,this.activatePluginByName.bind(this,match.name,callback,true))}}else{callback(false,\"NOTUSEINSTENCILSET\");ORYX.Log.info(\"Plugin need a stencilset which is not loaded'\",match.name)}}else{callback(false,\"REQUIRESTENCILSET\");ORYX.Log.info(\"Plugin need a stencilset which is not loaded'\",match.name)}}else{callback(false,match?\"NOTFOUND\":\"YETACTIVATED\")}},loadPlugins:function(){var me=this;var newPlugins=[];var loadedStencilSetsNamespaces=this.getStencilSets().keys();var facade=this._getPluginFacade();if(ORYX.MashupAPI&&ORYX.MashupAPI.loadablePlugins&&ORYX.MashupAPI.loadablePlugins instanceof Array){ORYX.availablePlugins=$A(ORYX.availablePlugins).findAll(function(value){return ORYX.MashupAPI.loadablePlugins.include(value.name)});ORYX.MashupAPI.loadablePlugins.each(function(className){if(!(ORYX.availablePlugins.find(function(val){return val.name==className}))){ORYX.availablePlugins.push({name:className})}})}ORYX.availablePlugins.each(function(value){ORYX.Log.debug(\"Initializing plugin '%0'\",value.name);if((!value.requires||!value.requires.namespaces||value.requires.namespaces.any(function(req){return loadedStencilSetsNamespaces.indexOf(req)>=0}))&&(!value.notUsesIn||!value.notUsesIn.namespaces||!value.notUsesIn.namespaces.any(function(req){return loadedStencilSetsNamespaces.indexOf(req)>=0}))&&(value.engaged||(value.engaged===undefined))){try{var className=eval(value.name);if(className){var plugin=new className(facade,value);plugin.type=value.name;newPlugins.push(plugin);plugin.engaged=true}}catch(e){ORYX.Log.warn(\"Plugin %0 is not available %1\",value.name,e)}}else{ORYX.Log.info(\"Plugin need a stencilset which is not loaded'\",value.name)}});newPlugins.each(function(value){if(value.registryChanged){value.registryChanged(me.pluginsData)}if(value.onSelectionChanged){me.registerOnEvent(ORYX.CONFIG.EVENT_SELECTION_CHANGED,value.onSelectionChanged.bind(value))}});this.loadedPlugins=newPlugins;this.registerPluginsOnKeyEvents();this.setSelection()},_createCanvas:function(c,d){if(c){if(c.search(/^http/)===-1){c=this.getStencilSets().values()[0].namespace()+c}}else{c=this.getStencilSets().values()[0].findRootStencilName()}var a=ORYX.Core.StencilSet.stencil(c);if(!a){ORYX.Log.fatal(\"Initialisation failed, because the stencil with the type %0 is not part of one of the loaded stencil sets.\",c)}var e=ORYX.Editor.graft(\"http://www.w3.org/1999/xhtml\",null,[\"div\"]);e.addClassName(\"ORYX_Editor\");this._canvas=new ORYX.Core.Canvas({width:ORYX.CONFIG.CANVAS_WIDTH,height:ORYX.CONFIG.CANVAS_HEIGHT,eventHandlerCallback:this.handleEvents.bind(this),id:this.id,parentNode:e},a,this._getPluginFacade());if(d){var b=[];for(field in d){b.push({prefix:\"oryx\",name:field,value:d[field]})}this._canvas.deserialize(b)}},_getPluginFacade:function(){if(!(this._pluginFacade)){this._pluginFacade={activatePluginByName:this.activatePluginByName.bind(this),getAvailablePlugins:this.getAvailablePlugins.bind(this),offer:this.offer.bind(this),getStencilSets:this.getStencilSets.bind(this),getStencilSetExtensionDefinition:function(){return Object.clone(this.ss_extensions_def||{})}.bind(this),getRules:this.getRules.bind(this),loadStencilSet:this.loadStencilSet.bind(this),createShape:this.createShape.bind(this),deleteShape:this.deleteShape.bind(this),getSelection:this.getSelection.bind(this),setSelection:this.setSelection.bind(this),updateSelection:this.updateSelection.bind(this),getCanvas:this.getCanvas.bind(this),importJSON:this.importJSON.bind(this),getJSON:this.getJSON.bind(this),getSerializedJSON:this.getSerializedJSON.bind(this),executeCommands:this.executeCommands.bind(this),isExecutingCommands:this.isExecutingCommands.bind(this),registerOnEvent:this.registerOnEvent.bind(this),unregisterOnEvent:this.unregisterOnEvent.bind(this),raiseEvent:this.handleEvents.bind(this),enableEvent:this.enableEvent.bind(this),disableEvent:this.disableEvent.bind(this),eventCoordinates:this.eventCoordinates.bind(this),eventCoordinatesXY:this.eventCoordinatesXY.bind(this),getModelMetaData:this.getModelMetaData.bind(this)}}return this._pluginFacade},isExecutingCommands:function(){return !!this.commandExecuting},executeCommands:function(a){if(!this.commandStack){this.commandStack=[]}if(!this.commandStackExecuted){this.commandStackExecuted=[]}this.commandStack=[].concat(this.commandStack).concat(a);if(this.commandExecuting){return}this.commandExecuting=true;while(this.commandStack.length>0){var b=this.commandStack.shift();b.execute();this.commandStackExecuted.push(b)}this.handleEvents({type:ORYX.CONFIG.EVENT_EXECUTE_COMMANDS,commands:this.commandStackExecuted});delete this.commandStack;delete this.commandStackExecuted;delete this.commandExecuting;this.updateSelection()},getJSON:function(){delete Array.prototype.toJSON;var a=this.getCanvas().toJSON();a.ssextensions=this.getStencilSets().values()[0].extensions().keys().findAll(function(b){return !b.endsWith(\"/meta#\")});return a},getSerializedJSON:function(){return JSON.stringify(this.getJSON())},importJSON:function(d,c){try{d=this.renewResourceIds(d)}catch(b){throw b}if(d.stencilset.namespace&&d.stencilset.namespace!==this.getCanvas().getStencil().stencilSet().namespace()){alert(String.format(ORYX.I18N.JSONImport.wrongSS,d.stencilset.namespace,this.getCanvas().getStencil().stencilSet().namespace()));return null}else{var a=ORYX.Core.Command.extend({construct:function(g,k,f,h){this.jsonObject=g;this.noSelection=f;this.facade=h;this.shapes;this.connections=[];this.parents=new Hash();this.selection=this.facade.getSelection();this.loadSerialized=k},execute:function(){if(!this.shapes){this.shapes=this.loadSerialized(this.jsonObject);this.shapes.each(function(g){if(g.getDockers){var f=g.getDockers();if(f){if(f.length>0){this.connections.push([f.first(),f.first().getDockedShape(),f.first().referencePoint])}if(f.length>1){this.connections.push([f.last(),f.last().getDockedShape(),f.last().referencePoint])}}}this.parents[g.id]=g.parent}.bind(this))}else{this.shapes.each(function(f){this.parents[f.id].add(f)}.bind(this));this.connections.each(function(f){f[0].setDockedShape(f[1]);f[0].setReferencePoint(f[2]);f[0].update()})}this.facade.getCanvas().update();if(!this.noSelection){this.facade.setSelection(this.shapes)}else{this.facade.updateSelection()}this.facade.getCanvas().updateSize()},rollback:function(){var f=this.facade.getSelection();this.shapes.each(function(g){f=f.without(g);this.facade.deleteShape(g)}.bind(this));this.facade.getCanvas().update();this.facade.setSelection(f)}});var e=new a(d,this.loadSerialized.bind(this),c,this._getPluginFacade());this.executeCommands([e]);return e.shapes.clone()}},renewResourceIds:function(b){if(Object.prototype.toString.call(b)===\"String\"){try{var d=b;b=JSON.parse(b)}catch(a){throw new SyntaxError(a.message)}}else{var d=JSON.stringify(b)}var e=function(f){if(!f){return[]}return f.map(function(g){return e(g.childShapes).concat(g.resourceId)}).flatten()};var c=e(b.childShapes);c.each(function(f){var g=ORYX.Editor.provideId();d=d.replace(new RegExp(f,\"g\"),g)});return JSON.parse(d)},loadSerialized:function(d,e){var c=this.getCanvas();this.loadSSExtensions(d.ssextensions);if(e===true){var b=this.getExtensionForMetaData();if(b){this.loadSSExtension(b)}}var a=this.getCanvas().addShapeObjects(d.childShapes,this.handleEvents.bind(this));if(d.properties){for(key in d.properties){var f=d.properties[key];var g=this.getCanvas().getStencil().property(\"oryx-\"+key);if(!(typeof f===\"string\")&&(!g||!g.isList())){f=JSON.stringify(f)}this.getCanvas().setProperty(\"oryx-\"+key,f)}}this.getCanvas().updateSize();this.selection=[null];this.setSelection([]);return a},getExtensionForMetaData:function(){if(!this.ss_extensions_def||!(this.ss_extensions_def.extensions instanceof Array)){return null}var a=this.getStencilSets();var b=this.ss_extensions_def.extensions.find(function(c){return !!a[c[\"extends\"]]&&c.namespace.endsWith(\"/meta#\")});return b?b.namespace||null:null},loadSSExtensions:function(a){if(!a){return}a.each(function(b){this.loadSSExtension(b)}.bind(this))},loadSSExtension:function(b){if(this.ss_extensions_def){var c=this.ss_extensions_def.extensions.find(function(d){return(d.namespace==b)});if(!c){return}var a=this.getStencilSets()[c[\"extends\"]];if(!a){return}if((c.definition||\"\").startsWith(\"/\")){a.addExtension(c.definition)}else{a.addExtension(ORYX.CONFIG.SS_EXTENSIONS_FOLDER+c.definition)}this.getRules().initializeRules(a);this._getPluginFacade().raiseEvent({type:ORYX.CONFIG.EVENT_STENCIL_SET_LOADED})}},disableEvent:function(a){if(a==ORYX.CONFIG.EVENT_KEYDOWN){this._keydownEnabled=false}if(a==ORYX.CONFIG.EVENT_KEYUP){this._keyupEnabled=false}if(this.DOMEventListeners.keys().member(a)){var b=this.DOMEventListeners.remove(a);this.DOMEventListeners[\"disable_\"+a]=b}},enableEvent:function(a){if(a==ORYX.CONFIG.EVENT_KEYDOWN){this._keydownEnabled=true}if(a==ORYX.CONFIG.EVENT_KEYUP){this._keyupEnabled=true}if(this.DOMEventListeners.keys().member(\"disable_\"+a)){var b=this.DOMEventListeners.remove(\"disable_\"+a);this.DOMEventListeners[a]=b}},registerOnEvent:function(a,b){if(!(this.DOMEventListeners.keys().member(a))){this.DOMEventListeners[a]=[]}this.DOMEventListeners[a].push(b)},unregisterOnEvent:function(a,b){if(this.DOMEventListeners.keys().member(a)){this.DOMEventListeners[a]=this.DOMEventListeners[a].without(b)}else{}},getSelection:function(){return this.selection||[]},getStencilSets:function(){return ORYX.Core.StencilSet.stencilSets(this.id)},getRules:function(){return ORYX.Core.StencilSet.rules(this.id)},loadStencilSet:function(a){try{ORYX.Core.StencilSet.loadStencilSet(a,this.modelMetaData,this.id);this.handleEvents({type:ORYX.CONFIG.EVENT_STENCIL_SET_LOADED})}catch(b){ORYX.Log.warn(\"Requesting stencil set file failed. (\"+b+\")\")}},offer:function(a){if(!this.pluginsData.member(a)){this.pluginsData.push(a)}},registerPluginsOnKeyEvents:function(){this.pluginsData.each(function(a){if(a.keyCodes){a.keyCodes.each(function(c){var b=\"key.event\";b+=\".\"+c.keyAction;if(c.metaKeys){if(c.metaKeys.indexOf(ORYX.CONFIG.META_KEY_META_CTRL)>-1){b+=\".\"+ORYX.CONFIG.META_KEY_META_CTRL}if(c.metaKeys.indexOf(ORYX.CONFIG.META_KEY_ALT)>-1){b+=\".\"+ORYX.CONFIG.META_KEY_ALT}if(c.metaKeys.indexOf(ORYX.CONFIG.META_KEY_SHIFT)>-1){b+=\".\"+ORYX.CONFIG.META_KEY_SHIFT}}if(c.keyCode){b+=\".\"+c.keyCode}ORYX.Log.debug(\"Register Plugin on Key Event: %0\",b);if(a.toggle===true&&a.buttonInstance){this.registerOnEvent(b,function(){a.buttonInstance.toggle(!a.buttonInstance.pressed);a.functionality.call(a,a.buttonInstance,a.buttonInstance.pressed)})}else{this.registerOnEvent(b,a.functionality)}}.bind(this))}}.bind(this))},isEqual:function(d,c){return d===c||(d.length===c.length&&d.all(function(a){return c.include(a)}))},isDirty:function(b){return b.any(function(a){return a.isPropertyChanged()})},setSelection:function(c,a,b){if(!c){c=[]}if(!(c instanceof Array)){c=[c]}c=c.findAll(function(d){return d&&d instanceof ORYX.Core.Shape});if(c[0] instanceof ORYX.Core.Canvas){c=[]}if(!b&&this.isEqual(this.selection,c)&&!this.isDirty(c)){return}this.selection=c;this._subSelection=a;this.handleEvents({type:ORYX.CONFIG.EVENT_SELECTION_CHANGED,elements:c,subSelection:a,force:!!b})},updateSelection:function(){this.setSelection(this.selection,this._subSelection,true)},getCanvas:function(){return this._canvas},createShape:function(o){if(o&&o.serialize&&o.serialize instanceof Array){var d=o.serialize.find(function(b){return(b.prefix+\"-\"+b.name)==\"oryx-type\"});var t=ORYX.Core.StencilSet.stencil(d.value);if(t.type()==\"node\"){var f=new ORYX.Core.Node({eventHandlerCallback:this.handleEvents.bind(this)},t,this._getPluginFacade())}else{var f=new ORYX.Core.Edge({eventHandlerCallback:this.handleEvents.bind(this)},t,this._getPluginFacade())}this.getCanvas().add(f);f.deserialize(o.serialize);return f}if(!o||!o.type||!o.namespace){throw\"To create a new shape you have to give an argument with type and namespace\"}var c=this.getCanvas();var f;var u=o.type;var r=ORYX.Core.StencilSet.stencilSet(o.namespace);if(r.stencil(u).type()==\"node\"){f=new ORYX.Core.Node({eventHandlerCallback:this.handleEvents.bind(this)},r.stencil(u),this._getPluginFacade())}else{f=new ORYX.Core.Edge({eventHandlerCallback:this.handleEvents.bind(this)},r.stencil(u),this._getPluginFacade())}if(o.template){f._jsonStencil.properties=o.template._jsonStencil.properties;f.postProcessProperties()}if(o.parent&&f instanceof ORYX.Core.Node){o.parent.add(f)}else{c.add(f)}var s=o.position?o.position:{x:100,y:200};var g;if(o.connectingType&&o.connectedShape&&!(f instanceof ORYX.Core.Edge)){g=new ORYX.Core.Edge({eventHandlerCallback:this.handleEvents.bind(this)},r.stencil(o.connectingType));g.dockers.first().setDockedShape(o.connectedShape);var l=o.connectedShape.getDefaultMagnet();var a=l?l.bounds.center():o.connectedShape.bounds.midPoint();g.dockers.first().setReferencePoint(a);g.dockers.last().setDockedShape(f);g.dockers.last().setReferencePoint(f.getDefaultMagnet().bounds.center());c.add(g)}if(f instanceof ORYX.Core.Edge&&o.connectedShape){f.dockers.first().setDockedShape(o.connectedShape);if(o.connectedShape instanceof ORYX.Core.Node){f.dockers.first().setReferencePoint(o.connectedShape.getDefaultMagnet().bounds.center());f.dockers.last().bounds.centerMoveTo(s)}else{f.dockers.first().setReferencePoint(o.connectedShape.bounds.midPoint())}var k=f.dockers.first();var e=f.dockers.last();if(k.getDockedShape()&&e.getDockedShape()){var q=k.getAbsoluteReferencePoint();var n=e.getAbsoluteReferencePoint();var p=f.createDocker();p.bounds.centerMoveTo({x:q.x+(endPont.x-q.x)/2,y:q.y+(endPont.y-q.y)/2})}}else{var v=f.bounds;if(f instanceof ORYX.Core.Node&&f.dockers.length==1){v=f.dockers.first().bounds}v.centerMoveTo(s);var h=v.upperLeft();v.moveBy(-Math.min(h.x,0),-Math.min(h.y,0));var m=v.lowerRight();v.moveBy(-Math.max(m.x-c.bounds.width(),0),-Math.max(m.y-c.bounds.height(),0))}if(f instanceof ORYX.Core.Edge){f._update(false)}if(!(f instanceof ORYX.Core.Edge)&&!(o.dontUpdateSelection)){this.setSelection([f])}if(g&&g.alignDockers){}if(f.alignDockers){f.alignDockers()}return f},deleteShape:function(a){if(!a||!a.parent){return}a.parent.remove(a);a.getOutgoingShapes().each(function(c){var b=c.getDockers().first();if(b&&b.getDockedShape()==a){b.setDockedShape(undefined)}});a.getIncomingShapes().each(function(b){var c=b.getDockers().last();if(c&&c.getDockedShape()==a){c.setDockedShape(undefined)}});a.getDockers().each(function(b){b.setDockedShape(undefined)})},getModelMetaData:function(){return this.modelMetaData},_executeEventImmediately:function(a){if(this.DOMEventListeners.keys().member(a.event.type)){this.DOMEventListeners[a.event.type].each((function(b){b(a.event,a.arg)}).bind(this))}},_executeEvents:function(){this._queueRunning=true;while(this._eventsQueue.length>0){var a=this._eventsQueue.shift();this._executeEventImmediately(a)}this._queueRunning=false},handleEvents:function(b,a){ORYX.Log.trace(\"Dispatching event type %0 on %1\",b.type,a);switch(b.type){case ORYX.CONFIG.EVENT_MOUSEDOWN:this._handleMouseDown(b,a);break;case ORYX.CONFIG.EVENT_MOUSEMOVE:this._handleMouseMove(b,a);break;case ORYX.CONFIG.EVENT_MOUSEUP:this._handleMouseUp(b,a);break;case ORYX.CONFIG.EVENT_MOUSEOVER:this._handleMouseHover(b,a);break;case ORYX.CONFIG.EVENT_MOUSEOUT:this._handleMouseOut(b,a);break}if(b.forceExecution){this._executeEventImmediately({event:b,arg:a})}else{this._eventsQueue.push({event:b,arg:a})}if(!this._queueRunning){this._executeEvents()}return false},isValidEvent:function(c){try{var a=[\"INPUT\",\"TEXTAREA\"].include(c.target.tagName.toUpperCase());var b=c.target.className.include(\"x-grid3-focus\")&&!c.target.className.include(\"x-grid3-focus-canvas\");return !a&&!b}catch(c){return false}},catchKeyUpEvents:function(b){if(!this._keyupEnabled){return}if(!b){b=window.event}if(!this.isValidEvent(b)){return}var a=this.createKeyCombEvent(b,ORYX.CONFIG.KEY_ACTION_UP);ORYX.Log.debug(\"Key Event to handle: %0\",a);this.handleEvents({type:a,event:b})},catchKeyDownEvents:function(b){if(!this._keydownEnabled){return}if(!b){b=window.event}if(!this.isValidEvent(b)){return}var a=this.createKeyCombEvent(b,ORYX.CONFIG.KEY_ACTION_DOWN);ORYX.Log.debug(\"Key Event to handle: %0\",a);this.handleEvents({type:a,event:b})},createKeyCombEvent:function(c,b){var d=c.which||c.keyCode;var a=\"key.event\";if(b){a+=\".\"+b}if(c.ctrlKey||c.metaKey){a+=\".\"+ORYX.CONFIG.META_KEY_META_CTRL}if(c.altKey){a+=\".\"+ORYX.CONFIG.META_KEY_ALT}if(c.shiftKey){a+=\".\"+ORYX.CONFIG.META_KEY_SHIFT}return a+\".\"+d},_handleMouseDown:function(a,l){var b=this.getCanvas();b.focus();var d=a.currentTarget;var c=l;var g=(c!==null)&&(c!==undefined)&&(c.isSelectable);var m=(c!==null)&&(c!==undefined)&&(c.isMovable);var k=a.shiftKey||a.ctrlKey;var h=this.selection.length===0;var e=this.selection.member(c);if(g&&h){this.setSelection([c]);ORYX.Log.trace(\"Rule #1 applied for mouse down on %0\",d.id)}else{if(g&&!h&&!k&&!e){this.setSelection([c]);ORYX.Log.trace(\"Rule #3 applied for mouse down on %0\",d.id)}else{if(g&&k&&!e){var f=this.selection.clone();f.push(c);this.setSelection(f);ORYX.Log.trace(\"Rule #4 applied for mouse down on %0\",d.id)}else{if(g&&e&&k){var f=this.selection.clone();this.setSelection(f.without(c));ORYX.Log.trace(\"Rule #6 applied for mouse down on %0\",c.id)}else{if(!g&&!m){this.setSelection([]);ORYX.Log.trace(\"Rule #2 applied for mouse down on %0\",d.id);return}else{if(!g&&m&&!(c instanceof ORYX.Core.Controls.Docker)){ORYX.Log.trace(\"Rule #7 applied for mouse down on %0\",d.id)}else{if(g&&e&&!k){this._subSelection=this._subSelection!=c?c:undefined;this.setSelection(this.selection,this._subSelection);ORYX.Log.trace(\"Rule #8 applied for mouse down on %0\",d.id)}}}}}}}return},_handleMouseMove:function(b,a){return},_handleMouseUp:function(d,c){var a=this.getCanvas();var e=c;var b=this.eventCoordinates(d)},_handleMouseHover:function(b,a){return},_handleMouseOut:function(b,a){return},eventCoordinates:function(f){var b=this.getCanvas();var g=b.node.ownerSVGElement.createSVGPoint();g.x=f.clientX;g.y=f.clientY;var e=1;if(!isNaN(screen.logicalXDPI)&&!isNaN(screen.systemXDPI)){var c=navigator.userAgent;if(c.indexOf(\"MSIE\")>=0){var d=Math.round((screen.deviceXDPI/screen.logicalXDPI)*100);if(d!==100){e=d/100}}}if(e!==1){g.x=g.x*e;g.y=g.y*e}var a=b.node.getScreenCTM();return g.matrixTransform(a.inverse())},eventCoordinatesXY:function(a,h){var c=this.getCanvas();var g=c.node.ownerSVGElement.createSVGPoint();g.x=a;g.y=h;var f=1;if(!isNaN(screen.logicalXDPI)&&!isNaN(screen.systemXDPI)){var d=navigator.userAgent;if(d.indexOf(\"MSIE\")>=0){var e=Math.round((screen.deviceXDPI/screen.logicalXDPI)*100);if(e!==100){f=e/100}}}if(f!==1){g.x=g.x*f;g.y=g.y*f}var b=c.node.getScreenCTM();return g.matrixTransform(b.inverse())}};ORYX.Editor=Clazz.extend(ORYX.Editor);ORYX.Editor.createByUrl=function(a){new Ajax.Request(a,{method:\"GET\",onSuccess:function(c){var b=JSON.parse(c.responseText);new ORYX.Editor(b)}.bind(this)})};ORYX.Editor.graft=function(g,f,d,l){l=(l||(f&&f.ownerDocument)||document);var h;if(d===undefined){throw\"Can't graft an undefined value\"}else{if(d.constructor==String){h=l.createTextNode(d)}else{for(var c=0;c<d.length;c++){if(c===0&&d[c].constructor==String){var a;a=d[c].match(/^([a-z][a-z0-9]*)\\.([^\\s\\.]+)$/i);if(a){h=l.createElementNS(g,a[1]);h.setAttributeNS(null,\"class\",a[2]);continue}a=d[c].match(/^([a-z][a-z0-9]*)$/i);if(a){h=l.createElementNS(g,a[1]);continue}h=l.createElementNS(g,\"span\");h.setAttribute(null,\"class\",\"namelessFromLOL\")}if(d[c]===undefined){throw\"Can't graft an undefined value in a list!\"}else{if(d[c].constructor==String||d[c].constructor==Array){this.graft(g,h,d[c],l)}else{if(d[c].constructor==Number){this.graft(g,h,d[c].toString(),l)}else{if(d[c].constructor==Object){for(var b in d[c]){h.setAttributeNS(null,b,d[c][b])}}else{}}}}}}}if(f&&f.appendChild){f.appendChild(h)}else{}return h};ORYX.Editor.provideId=function(){var b=[],c=\"0123456789ABCDEF\";for(var a=0;a<36;a++){b[a]=Math.floor(Math.random()*16)}b[14]=4;b[19]=(b[19]&3)|8;for(var a=0;a<36;a++){b[a]=c[b[a]]}b[8]=b[13]=b[18]=b[23]=\"-\";return\"oryx_\"+b.join(\"\")};ORYX.Editor.resizeFix=function(){if(!ORYX.Editor._resizeFixTimeout){ORYX.Editor._resizeFixTimeout=window.setTimeout(function(){window.resizeBy(1,1);window.resizeBy(-1,-1);ORYX.Editor._resizefixTimeout=null},100)}};ORYX.Editor.Cookie={callbacks:[],onChange:function(b,a){this.callbacks.push(b);this.start(a)},start:function(a){if(this.pe){return}var b=document.cookie;this.pe=new PeriodicalExecuter(function(){if(b!=document.cookie){b=document.cookie;this.callbacks.each(function(c){c(this.getParams())}.bind(this))}}.bind(this),(a||10000)/1000)},stop:function(){if(this.pe){this.pe.stop();this.pe=null}},getParams:function(){var a={};var b=document.cookie;b.split(\"; \").each(function(c){a[c.split(\"=\")[0]]=c.split(\"=\")[1]});return a},toString:function(){return document.cookie}};ORYX.Editor.SVGClassElementsAreAvailable=true;ORYX.Editor.setMissingClasses=function(){try{SVGElement}catch(a){ORYX.Editor.SVGClassElementsAreAvailable=false;SVGSVGElement=document.createElementNS(\"http://www.w3.org/2000/svg\",\"svg\").toString();SVGGElement=document.createElementNS(\"http://www.w3.org/2000/svg\",\"g\").toString();SVGPathElement=document.createElementNS(\"http://www.w3.org/2000/svg\",\"path\").toString();SVGTextElement=document.createElementNS(\"http://www.w3.org/2000/svg\",\"text\").toString();SVGRectElement=document.createElementNS(\"http://www.w3.org/2000/svg\",\"rect\").toString();SVGImageElement=document.createElementNS(\"http://www.w3.org/2000/svg\",\"image\").toString();SVGCircleElement=document.createElementNS(\"http://www.w3.org/2000/svg\",\"circle\").toString();SVGEllipseElement=document.createElementNS(\"http://www.w3.org/2000/svg\",\"ellipse\").toString();SVGLineElement=document.createElementNS(\"http://www.w3.org/2000/svg\",\"line\").toString();SVGPolylineElement=document.createElementNS(\"http://www.w3.org/2000/svg\",\"polyline\").toString();SVGPolygonElement=document.createElementNS(\"http://www.w3.org/2000/svg\",\"polygon\").toString()}};ORYX.Editor.checkClassType=function(b,a){if(ORYX.Editor.SVGClassElementsAreAvailable){return b instanceof a}else{return b==a}};if(!ORYX){var ORYX={}}if(!ORYX.Core){ORYX.Core={}}new function(){ORYX.Core.UIEnableDrag=function(e,d,c){this.uiObj=d;var f=d.bounds.upperLeft();var b=d.node.getScreenCTM();this.faktorXY={x:b.a,y:b.d};this.scrollNode=d.node.ownerSVGElement.parentNode.parentNode;this.offSetPosition={x:Event.pointerX(e)-(f.x*this.faktorXY.x),y:Event.pointerY(e)-(f.y*this.faktorXY.y)};this.offsetScroll={x:this.scrollNode.scrollLeft,y:this.scrollNode.scrollTop};this.dragCallback=ORYX.Core.UIDragCallback.bind(this);this.disableCallback=ORYX.Core.UIDisableDrag.bind(this);this.movedCallback=c?c.movedCallback:undefined;this.upCallback=c?c.upCallback:undefined;document.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEUP,this.disableCallback,true);document.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE,this.dragCallback,false)};ORYX.Core.UIDragCallback=function(b){var a={x:Event.pointerX(b)-this.offSetPosition.x,y:Event.pointerY(b)-this.offSetPosition.y};a.x-=this.offsetScroll.x-this.scrollNode.scrollLeft;a.y-=this.offsetScroll.y-this.scrollNode.scrollTop;a.x/=this.faktorXY.x;a.y/=this.faktorXY.y;this.uiObj.bounds.moveTo(a);if(this.movedCallback){this.movedCallback(b)}};ORYX.Core.UIDisableDrag=function(a){document.documentElement.removeEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE,this.dragCallback,false);document.documentElement.removeEventListener(ORYX.CONFIG.EVENT_MOUSEUP,this.disableCallback,true);if(this.upCallback){this.upCallback(a)}this.upCallback=undefined;this.movedCallback=undefined;Event.stop(a)};ORYX.Core.MoveDockersCommand=ORYX.Core.Command.extend({construct:function(a){this.dockers=$H(a);this.edges=$H({})},execute:function(){if(this.changes){this.executeAgain();return}else{this.changes=$H({})}this.dockers.values().each(function(b){var a=b.docker.parent;if(!a){return}if(!this.changes[a.getId()]){this.changes[a.getId()]={edge:a,oldDockerPositions:a.dockers.map(function(c){return c.bounds.center()})}}b.docker.bounds.moveBy(b.offset);this.edges[a.getId()]=a;b.docker.update()}.bind(this));this.edges.each(function(a){this.updateEdge(a.value);if(this.changes[a.value.getId()]){this.changes[a.value.getId()].dockerPositions=a.value.dockers.map(function(b){return b.bounds.center()})}}.bind(this))},updateEdge:function(a){a._update(true);[a.getOutgoingShapes(),a.getIncomingShapes()].flatten().invoke(\"_update\",[true])},executeAgain:function(){this.changes.values().each(function(a){this.removeAllDocker(a.edge);a.dockerPositions.each(function(d,b){if(b==0||b==a.dockerPositions.length-1){return}var c=a.edge.createDocker(undefined,d);c.bounds.centerMoveTo(d);c.update()}.bind(this));this.updateEdge(a.edge)}.bind(this))},rollback:function(){this.changes.values().each(function(a){this.removeAllDocker(a.edge);a.oldDockerPositions.each(function(d,b){if(b==0||b==a.oldDockerPositions.length-1){return}var c=a.edge.createDocker(undefined,d);c.bounds.centerMoveTo(d);c.update()}.bind(this));this.updateEdge(a.edge)}.bind(this))},removeAllDocker:function(a){a.dockers.slice(1,a.dockers.length-1).each(function(b){a.removeDocker(b)})}})}();if(!ORYX){var ORYX={}}if(!ORYX.Core){ORYX.Core={}}ORYX.Core.Shape={construct:function(a,c,b){arguments.callee.$.construct.apply(this,arguments);this.facade=b;this.dockers=[];this.magnets=[];this._defaultMagnet;this.incoming=[];this.outgoing=[];this.nodes=[];this._dockerChangedCallback=this._dockerChanged.bind(this);this._labels=new Hash();this.node=ORYX.Editor.graft(\"http://www.w3.org/2000/svg\",null,[\"g\",{id:\"svg-\"+this.resourceId},[\"g\",{\"class\":\"stencils\"},[\"g\",{\"class\":\"me\"}],[\"g\",{\"class\":\"children\",style:\"overflow:hidden\"}],[\"g\",{\"class\":\"edge\"}]],[\"g\",{\"class\":\"controls\"},[\"g\",{\"class\":\"dockers\"}],[\"g\",{\"class\":\"magnets\"}]]])},update:function(){},_update:function(){},refresh:function(){arguments.callee.$.refresh.apply(this,arguments);if(this.node.ownerDocument){var a=this;this.propertiesChanged.each((function(b){if(b.value){var e=this.properties[b.key];var d=this.getStencil().property(b.key);if(d!=undefined){this.propertiesChanged[b.key]=false;if(d.type()==ORYX.CONFIG.TYPE_CHOICE){d.refToView().each((function(g){if(g!==\"\"){var f=this._labels[this.id+g];if(f&&d.item(e)){f.text(d.item(e).title())}}}).bind(this));var c=new Hash();d.items().each((function(f){f.refToView().each((function(g){if(g==\"\"){return}var h=this.node.ownerDocument.getElementById(this.id+g);if(!h){return}if(!c[h.id]||e==f.value()){h.setAttributeNS(null,\"display\",((e==f.value())?\"inherit\":\"none\"));c[h.id]=h}if(ORYX.Editor.checkClassType(h,SVGImageElement)){h.setAttributeNS(\"http://www.w3.org/1999/xlink\",\"href\",h.getAttributeNS(\"http://www.w3.org/1999/xlink\",\"href\"))}}).bind(this))}).bind(this))}else{d.refToView().each((function(h){if(h===\"\"){return}var g=this.id+h;if(d.type()===ORYX.CONFIG.TYPE_KISBPM_MULTIINSTANCE){if(h===\"multiinstance\"){var l=this.node.ownerDocument.getElementById(this.id+\"parallel\");if(l){if(e===\"Parallel\"){l.setAttributeNS(null,\"display\",\"inherit\")}else{l.setAttributeNS(null,\"display\",\"none\")}}var o=this.node.ownerDocument.getElementById(this.id+\"sequential\");if(o){if(e===\"Sequential\"){o.setAttributeNS(null,\"display\",\"inherit\")}else{o.setAttributeNS(null,\"display\",\"none\")}}}return}else{if(d.type()===\"cancelactivity\"){var s=this.node.ownerDocument.getElementById(this.id+\"frame\");var t=this.node.ownerDocument.getElementById(this.id+\"frame2\");if(e===\"true\"){s.setAttributeNS(null,\"display\",\"inherit\");t.setAttributeNS(null,\"display\",\"inherit\")}else{s.setAttributeNS(null,\"display\",\"none\");t.setAttributeNS(null,\"display\",\"none\")}}}var k=this.node.ownerDocument.getElementById(g);if(!k||!(k.ownerSVGElement)){if(d.type()===ORYX.CONFIG.TYPE_URL||d.type()===ORYX.CONFIG.TYPE_DIAGRAM_LINK){var r=this.node.ownerDocument.getElementsByTagNameNS(\"http://www.w3.org/2000/svg\",\"a\");k=$A(r).find(function(u){return u.getAttributeNS(null,\"id\")===g});if(!k){return}}else{return}}if(d.complexAttributeToView()){var p=this._labels[g];if(p){try{propJson=e.evalJSON();var q=propJson[d.complexAttributeToView()];p.text(q?q:e)}catch(m){p.text(e)}}}else{switch(d.type()){case ORYX.CONFIG.TYPE_BOOLEAN:if(typeof e==\"string\"){e=e===\"true\"}k.setAttributeNS(null,\"display\",(!(e===d.inverseBoolean()))?\"inherit\":\"none\");break;case ORYX.CONFIG.TYPE_COLOR:if(d.fill()){if(k.tagName.toLowerCase()===\"stop\"){if(e){if(d.lightness()&&d.lightness()!==1){e=ORYX.Utils.adjustLightness(e,d.lightness())}k.setAttributeNS(null,\"stop-color\",e);if(k.parentNode.tagName.toLowerCase()===\"radialgradient\"){ORYX.Utils.adjustGradient(k.parentNode,k)}}if(k.parentNode.tagName.toLowerCase()===\"radialgradient\"){$A(k.parentNode.getElementsByTagName(\"stop\")).each(function(u){u.setAttributeNS(null,\"stop-opacity\",e?u.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX,\"default-stop-opacity\")||1:0)}.bind(this))}}else{k.setAttributeNS(null,\"fill\",e)}}if(d.stroke()){k.setAttributeNS(null,\"stroke\",e)}break;case ORYX.CONFIG.TYPE_STRING:var p=this._labels[g];if(p){p.text(e)}break;case ORYX.CONFIG.TYPE_EXPRESSION:var p=this._labels[g];if(p){p.text(e)}break;case ORYX.CONFIG.TYPE_DATASOURCE:var p=this._labels[g];if(p){p.text(e)}break;case ORYX.CONFIG.TYPE_INTEGER:var p=this._labels[g];if(p){p.text(e)}break;case ORYX.CONFIG.TYPE_FLOAT:if(d.fillOpacity()){k.setAttributeNS(null,\"fill-opacity\",e)}if(d.strokeOpacity()){k.setAttributeNS(null,\"stroke-opacity\",e)}if(!d.fillOpacity()&&!d.strokeOpacity()){var p=this._labels[g];if(p){p.text(e)}}break;case ORYX.CONFIG.TYPE_FORM_LINK:if(h==\"pimg\"){var n=k.getAttributeNodeNS(\"\",\"onclick\");if(n){if(e&&(\"\"+e).length>0){n.textContent=\"window.location = '../service/editor?id=\"+e+\"_form'\"}else{newFormFacade=this.facade;n.textContent=\"displayNewFormDialog('\"+this.resourceId+\"');\"}}}else{if(h==\"linkIndicator\"){if(e&&e.length>0){k.setAttributeNS(null,\"display\",\"inherit\")}else{k.setAttributeNS(null,\"display\",\"none\")}}}break;case ORYX.CONFIG.TYPE_URL:case ORYX.CONFIG.TYPE_DIAGRAM_LINK:var f=k.getAttributeNodeNS(\"http://www.w3.org/1999/xlink\",\"xlink:href\");if(f){f.textContent=e}else{k.setAttributeNS(\"http://www.w3.org/1999/xlink\",\"xlink:href\",e)}break}}}).bind(this))}}}}).bind(this));this._labels.values().each(function(b){b.update()})}},layout:function(){var a=this.getStencil().layout();if(a){a.each(function(b){b.shape=this;b.forceExecution=true;this._delegateEvent(b)}.bind(this))}},getLabels:function(){return this._labels.values()},getLabel:function(a){if(!a){return null}return(this._labels.find(function(b){return b.key.endsWith(a)})||{}).value||null},hideLabels:function(){this.getLabels().invoke(\"hide\")},showLabels:function(){var a=this.getLabels();a.invoke(\"show\");a.each(function(b){b.update()})},setOpacity:function(b,a){b=Math.max(Math.min((typeof b==\"number\"?b:1),1),0);if(b!==1){b=String(b);this.node.setAttributeNS(null,\"fill-opacity\",b);this.node.setAttributeNS(null,\"stroke-opacity\",b)}else{this.node.removeAttributeNS(null,\"fill-opacity\");this.node.removeAttributeNS(null,\"stroke-opacity\")}},getDockers:function(){return this.dockers},getMagnets:function(){return this.magnets},getDefaultMagnet:function(){if(this._defaultMagnet){return this._defaultMagnet}else{if(this.magnets.length>0){return this.magnets[0]}else{return undefined}}},getParentShape:function(){return this.parent},getIncomingShapes:function(a){if(a){this.incoming.each(a)}return this.incoming},getIncomingNodes:function(a){return this.incoming.select(function(b){var c=(b instanceof ORYX.Core.Node);if(c&&a){a(b)}return c})},getOutgoingShapes:function(a){if(a){this.outgoing.each(a)}return this.outgoing},getOutgoingNodes:function(a){return this.outgoing.select(function(b){var c=(b instanceof ORYX.Core.Node);if(c&&a){a(b)}return c})},getAllDockedShapes:function(b){var a=this.incoming.concat(this.outgoing);if(b){a.each(b)}return a},getCanvas:function(){if(this.parent instanceof ORYX.Core.Canvas){return this.parent}else{if(this.parent instanceof ORYX.Core.Shape){return this.parent.getCanvas()}else{return undefined}}},getChildNodes:function(b,c){if(!b&&!c){return this.nodes.clone()}else{var a=[];this.nodes.each(function(d){if(!d.isVisible){return}if(c){c(d)}a.push(d);if(b&&d instanceof ORYX.Core.Shape){a=a.concat(d.getChildNodes(b,c))}});return a}},add:function(b,d,c){if(b instanceof ORYX.Core.UIObject&&!(b instanceof ORYX.Core.Edge)){if(!(this.children.member(b))){if(b.parent){b.parent.remove(b,true)}if(d!=undefined){this.children.splice(d,0,b)}else{this.children.push(b)}b.parent=this;var e;if(b instanceof ORYX.Core.Node){e=this.node.childNodes[0].childNodes[1];this.nodes.push(b)}else{if(b instanceof ORYX.Core.Controls.Control){var a=this.node.childNodes[1];if(b instanceof ORYX.Core.Controls.Docker){e=a.childNodes[0];if(this.dockers.length>=2){this.dockers.splice(d!==undefined?Math.min(d,this.dockers.length-1):this.dockers.length-1,0,b)}else{this.dockers.push(b)}}else{if(b instanceof ORYX.Core.Controls.Magnet){e=a.childNodes[1];this.magnets.push(b)}else{e=a}}}else{e=this.node}}if(d!=undefined&&d<e.childNodes.length){b.node=e.insertBefore(b.node,e.childNodes[d])}else{b.node=e.appendChild(b.node)}this._changed();if(this.eventHandlerCallback&&c!==true){this.eventHandlerCallback({type:ORYX.CONFIG.EVENT_SHAPEADDED,shape:b})}}else{ORYX.Log.warn(\"add: ORYX.Core.UIObject is already a child of this object.\")}}else{ORYX.Log.warn(\"add: Parameter is not of type ORYX.Core.UIObject.\")}},remove:function(a,b){if(this.children.member(a)){var c=a.parent;this.children=this.children.without(a);a.parent=undefined;if(a instanceof ORYX.Core.Shape){if(a instanceof ORYX.Core.Edge){a.removeMarkers();a.node=this.node.childNodes[0].childNodes[2].removeChild(a.node)}else{a.node=this.node.childNodes[0].childNodes[1].removeChild(a.node);this.nodes=this.nodes.without(a)}}else{if(a instanceof ORYX.Core.Controls.Control){if(a instanceof ORYX.Core.Controls.Docker){a.node=this.node.childNodes[1].childNodes[0].removeChild(a.node);this.dockers=this.dockers.without(a)}else{if(a instanceof ORYX.Core.Controls.Magnet){a.node=this.node.childNodes[1].childNodes[1].removeChild(a.node);this.magnets=this.magnets.without(a)}else{a.node=this.node.childNodes[1].removeChild(a.node)}}}}if(this.eventHandlerCallback&&b!==true){this.eventHandlerCallback({type:ORYX.CONFIG.EVENT_SHAPEREMOVED,shape:a,parent:c})}this._changed()}else{ORYX.Log.warn(\"remove: ORYX.Core.UIObject is not a child of this object.\")}},getIntersectionPoint:function(){var p,o,h,g;switch(arguments.length){case 2:p=arguments[0].x;o=arguments[0].y;h=arguments[1].x;g=arguments[1].y;break;case 4:p=arguments[0];o=arguments[1];h=arguments[2];g=arguments[3];break;default:throw\"getIntersectionPoints needs two or four arguments\"}var d,b,e,c;var a=this.absoluteBounds();if(this.isPointIncluded(p,o,a)){d=p;b=o}else{e=p;c=o}if(this.isPointIncluded(h,g,a)){d=h;b=g}else{e=h;c=g}if(!d||!b||!e||!c){return undefined}var n=0;var m=0;var r,q;var l=1;var k=0;while(true){var n=Math.min(d,e)+((Math.max(d,e)-Math.min(d,e))/2);var m=Math.min(b,c)+((Math.max(b,c)-Math.min(b,c))/2);if(this.isPointIncluded(n,m,a)){d=n;b=m}else{e=n;c=m}var f=Math.sqrt(Math.pow(d-e,2)+Math.pow(b-c,2));r=d+((e-d)/f),q=b+((c-b)/f);if(!this.isPointIncluded(r,q,a)){break}}return{x:r,y:q}},isPointIncluded:function(){return false},containsNode:function(b){var a=this.node.firstChild.firstChild;while(b){if(b==a){return true}b=b.parentNode}return false},isPointOverOffset:function(){return this.isPointIncluded.apply(this,arguments)},_dockerChanged:function(){},createDocker:function(b,a){var c=new ORYX.Core.Controls.Docker({eventHandlerCallback:this.eventHandlerCallback});c.bounds.registerCallback(this._dockerChangedCallback);if(a){c.bounds.centerMoveTo(a)}this.add(c,b);return c},serialize:function(){var a=arguments.callee.$.serialize.apply(this);a.push({name:\"bounds\",prefix:\"oryx\",value:this.bounds.serializeForERDF(),type:\"literal\"});this.getOutgoingShapes().each((function(b){a.push({name:\"outgoing\",prefix:\"raziel\",value:\"#\"+ERDF.__stripHashes(b.resourceId),type:\"resource\"})}).bind(this));a.push({name:\"parent\",prefix:\"raziel\",value:\"#\"+ERDF.__stripHashes(this.parent.resourceId),type:\"resource\"});return a},deserialize:function(d,c){arguments.callee.$.deserialize.apply(this,arguments);var e=d.find(function(b){return\"oryx-bounds\"===(b.prefix+\"-\"+b.name)});if(e){var a=e.value.replace(/,/g,\" \").split(\" \").without(\"\");if(this instanceof ORYX.Core.Edge){if(!this.dockers.first().isChanged){this.dockers.first().bounds.centerMoveTo(parseFloat(a[0]),parseFloat(a[1]))}if(!this.dockers.last().isChanged){this.dockers.last().bounds.centerMoveTo(parseFloat(a[2]),parseFloat(a[3]))}}else{this.bounds.set(parseFloat(a[0]),parseFloat(a[1]),parseFloat(a[2]),parseFloat(a[3]))}}if(c&&c.labels instanceof Array){c.labels.each(function(b){var f=this.getLabel(b.ref);if(f){f.deserialize(b,this)}}.bind(this))}},toJSON:function(){var a=arguments.callee.$.toJSON.apply(this,arguments);var c=[],b=this.id;this._labels.each(function(e){var d=e.value.serialize();if(d){d.ref=e.key.replace(b,\"\");c.push(d)}});if(c.length>0){a.labels=c}return a},_init:function(a){this._adjustIds(a,0)},_adjustIds:function(c,e){if(c instanceof Element){var a=c.getAttributeNS(null,\"id\");if(a&&a!==\"\"){c.setAttributeNS(null,\"id\",this.id+a)}else{c.setAttributeNS(null,\"id\",this.id+\"_\"+this.id+\"_\"+e);e++}var d=c.getAttributeNS(null,\"fill\");if(d&&d.include(\"url(#\")){d=d.replace(/url\\(#/g,\"url(#\"+this.id);c.setAttributeNS(null,\"fill\",d)}if(c.hasChildNodes()){for(var b=0;b<c.childNodes.length;b++){e=this._adjustIds(c.childNodes[b],e)}}}return e},toString:function(){return\"ORYX.Core.Shape \"+this.getId()}};ORYX.Core.Shape=ORYX.Core.AbstractShape.extend(ORYX.Core.Shape);if(!ORYX){var ORYX={}}if(!ORYX.Core){ORYX.Core={}}if(!ORYX.Core.Controls){ORYX.Core.Controls={}}ORYX.Core.Controls.Control=ORYX.Core.UIObject.extend({toString:function(){return\"Control \"+this.id}});if(!ORYX){var ORYX={}}if(!ORYX.Core){ORYX.Core={}}if(!ORYX.Core.Controls){ORYX.Core.Controls={}}ORYX.Core.Controls.Docker=ORYX.Core.Controls.Control.extend({construct:function(){arguments.callee.$.construct.apply(this,arguments);this.isMovable=true;this.bounds.set(0,0,16,16);this.referencePoint=undefined;this._dockedShapeBounds=undefined;this._dockedShape=undefined;this._oldRefPoint1=undefined;this._oldRefPoint2=undefined;this.anchorLeft;this.anchorRight;this.anchorTop;this.anchorBottom;this.node=ORYX.Editor.graft(\"http://www.w3.org/2000/svg\",null,[\"g\"]);this._dockerNode=ORYX.Editor.graft(\"http://www.w3.org/2000/svg\",this.node,[\"g\",{\"pointer-events\":\"all\"},[\"circle\",{cx:\"8\",cy:\"8\",r:\"8\",stroke:\"none\",fill:\"none\"}],[\"circle\",{cx:\"8\",cy:\"8\",r:\"3\",stroke:\"black\",fill:\"red\",\"stroke-width\":\"1\"}]]);this._referencePointNode=ORYX.Editor.graft(\"http://www.w3.org/2000/svg\",this.node,[\"g\",{\"pointer-events\":\"none\"},[\"circle\",{cx:this.bounds.upperLeft().x,cy:this.bounds.upperLeft().y,r:3,fill:\"red\",\"fill-opacity\":0.4}]]);this.hide();this.addEventHandlers(this._dockerNode);this._updateCallback=this._changed.bind(this)},update:function(){if(this._dockedShape){if(this._dockedShapeBounds&&this._dockedShape instanceof ORYX.Core.Node){var g=this._dockedShapeBounds.width();var d=this._dockedShapeBounds.height();if(!g){g=1}if(!d){d=1}var o=this._dockedShape.bounds.width()/g;var m=this._dockedShape.bounds.height()/d;if(o!==1||m!==1){this.referencePoint.x*=o;this.referencePoint.y*=m}this._dockedShapeBounds=this._dockedShape.bounds.clone()}var b=this.parent.dockers.indexOf(this);var f=this;var e=this.parent.dockers.length>1?(b===0?this.parent.dockers[b+1]:this.parent.dockers[b-1]):undefined;var n=f.getDockedShape()?f.getAbsoluteReferencePoint():f.bounds.center();var k=e&&e.getDockedShape()?e.getAbsoluteReferencePoint():e?e.bounds.center():undefined;if(!k){var a=this._dockedShape.absoluteCenterXY();var l=this._dockedShape.bounds.width()*this._dockedShape.bounds.height();k={x:n.x+(a.x-n.x)*-l,y:n.y+(a.y-n.y)*-l}}var c=undefined;c=this._dockedShape.getIntersectionPoint(n,k);if(!c){c=this.getAbsoluteReferencePoint()}if(this.parent&&this.parent.parent){var h=this.parent.parent.absoluteXY();c.x-=h.x;c.y-=h.y}this.bounds.centerMoveTo(c);this._oldRefPoint1=n;this._oldRefPoint2=k}arguments.callee.$.update.apply(this,arguments)},refresh:function(){arguments.callee.$.refresh.apply(this,arguments);var a=this.bounds.upperLeft();this._dockerNode.setAttributeNS(null,\"transform\",\"translate(\"+a.x+\", \"+a.y+\")\");a=Object.clone(this.referencePoint);if(a&&this._dockedShape){var b;if(this.parent instanceof ORYX.Core.Edge){b=this._dockedShape.absoluteXY()}else{b=this._dockedShape.bounds.upperLeft()}a.x+=b.x;a.y+=b.y}else{a=this.bounds.center()}this._referencePointNode.setAttributeNS(null,\"transform\",\"translate(\"+a.x+\", \"+a.y+\")\")},setReferencePoint:function(a){if(this.referencePoint!==a&&(!this.referencePoint||!a||this.referencePoint.x!==a.x||this.referencePoint.y!==a.y)){this.referencePoint=a;this._changed()}},getAbsoluteReferencePoint:function(){if(!this.referencePoint||!this._dockedShape){return undefined}else{var a=this._dockedShape.absoluteXY();return{x:this.referencePoint.x+a.x,y:this.referencePoint.y+a.y}}},setDockedShape:function(b){if(this._dockedShape){this._dockedShape.bounds.unregisterCallback(this._updateCallback);if(this===this.parent.dockers.first()){this.parent.incoming=this.parent.incoming.without(this._dockedShape);this._dockedShape.outgoing=this._dockedShape.outgoing.without(this.parent)}else{if(this===this.parent.dockers.last()){this.parent.outgoing=this.parent.outgoing.without(this._dockedShape);this._dockedShape.incoming=this._dockedShape.incoming.without(this.parent)}}}this._dockedShape=b;this._dockedShapeBounds=undefined;var a=undefined;if(this._dockedShape){if(this===this.parent.dockers.first()){this.parent.incoming.push(b);b.outgoing.push(this.parent)}else{if(this===this.parent.dockers.last()){this.parent.outgoing.push(b);b.incoming.push(this.parent)}}var c=this.bounds;var d=b.absoluteXY();a={x:c.center().x-d.x,y:c.center().y-d.y};this._dockedShapeBounds=this._dockedShape.bounds.clone();this._dockedShape.bounds.registerCallback(this._updateCallback);this.setDockerColor(ORYX.CONFIG.DOCKER_DOCKED_COLOR)}else{this.setDockerColor(ORYX.CONFIG.DOCKER_UNDOCKED_COLOR)}this.setReferencePoint(a);this._changed()},getDockedShape:function(){return this._dockedShape},isDocked:function(){return !!this._dockedShape},setDockerColor:function(a){this._dockerNode.lastChild.setAttributeNS(null,\"fill\",a)},preventHiding:function(a){this._preventHiding=Math.max(0,(this._preventHiding||0)+(a?1:-1))},hide:function(){if(this._preventHiding){return false}this.node.setAttributeNS(null,\"visibility\",\"hidden\");this._referencePointNode.setAttributeNS(null,\"visibility\",\"hidden\");this.children.each(function(a){a.hide()})},show:function(){this.node.setAttributeNS(null,\"visibility\",\"visible\");if(this.getDockedShape() instanceof ORYX.Core.Edge){this._referencePointNode.setAttributeNS(null,\"visibility\",\"hidden\")}else{this._referencePointNode.setAttributeNS(null,\"visibility\",\"visible\")}this.children.each(function(a){a.show()})},toString:function(){return\"Docker \"+this.id}});if(!ORYX){var ORYX={}}if(!ORYX.Core){ORYX.Core={}}if(!ORYX.Core.Controls){ORYX.Core.Controls={}}ORYX.Core.Controls.Magnet=ORYX.Core.Controls.Control.extend({construct:function(){arguments.callee.$.construct.apply(this,arguments);this.anchorLeft;this.anchorRight;this.anchorTop;this.anchorBottom;this.bounds.set(0,0,16,16);this.node=ORYX.Editor.graft(\"http://www.w3.org/2000/svg\",null,[\"g\",{\"pointer-events\":\"all\"},[\"circle\",{cx:\"8\",cy:\"8\",r:\"4\",stroke:\"none\",fill:\"red\",\"fill-opacity\":\"0.3\"}],]);this.hide()},update:function(){arguments.callee.$.update.apply(this,arguments)},_update:function(){arguments.callee.$.update.apply(this,arguments)},refresh:function(){arguments.callee.$.refresh.apply(this,arguments);var a=this.bounds.upperLeft();this.node.setAttributeNS(null,\"transform\",\"translate(\"+a.x+\", \"+a.y+\")\")},show:function(){arguments.callee.$.show.apply(this,arguments)},toString:function(){return\"Magnet \"+this.id}});if(!ORYX){var ORYX={}}if(!ORYX.Core){ORYX.Core={}}ORYX.Core.Node={construct:function(a,c,b){arguments.callee.$.construct.apply(this,arguments);this.isSelectable=true;this.isMovable=true;this._dockerUpdated=false;this.facade=b;this._oldBounds=new ORYX.Core.Bounds();this._svgShapes=[];this.minimumSize=undefined;this.maximumSize=undefined;this.isHorizontallyResizable=false;this.isVerticallyResizable=false;this.dataId=undefined;this._init(this._stencil.view());this.forcedHeight=-1},_update:function(){this.dockers.invoke(\"update\");if(this.isChanged){var c=this.bounds;var d=this._oldBounds;if(this.isResized){var o=c.width()/d.width();var n=c.height()/d.height();this._svgShapes.each(function(w){if(w.isHorizontallyResizable){w.width=w.oldWidth*o}if(w.isVerticallyResizable){w.height=w.oldHeight*n}var v;var s=w.anchorLeft;var u=w.anchorRight;if(u){v=d.width()-(w.oldX+w.oldWidth);if(s){w.width=c.width()-w.x-v}else{w.x=c.width()-(v+w.width)}}else{if(!s){w.x=o*w.oldX;if(!w.isHorizontallyResizable){w.x=w.x+w.width*o/2-w.width/2}}}var p=w.anchorTop;var t=w.anchorBottom;if(t){v=d.height()-(w.oldY+w.oldHeight);if(p){w.height=c.height()-w.y-v}else{if(!w._isYLocked){w.y=c.height()-(v+w.height)}}}else{if(!p){w.y=n*w.oldY;if(!w.isVerticallyResizable){w.y=w.y+w.height*n/2-w.height/2}}}});var g={x:0,y:0};if(!this.isHorizontallyResizable&&c.width()!==d.width()){g.x=d.width()-c.width()}if(!this.isVerticallyResizable&&c.height()!==d.height()){g.y=d.height()-c.height()}if(g.x!==0||g.y!==0){c.extend(g)}g={x:0,y:0};var e,k;if(this.minimumSize){ORYX.Log.debug(\"Shape (%0)'s min size: (%1x%2)\",this,this.minimumSize.width,this.minimumSize.height);e=this.minimumSize.width-c.width();if(e>0){g.x+=e}k=this.minimumSize.height-c.height();if(k>0){g.y+=k}}if(this.maximumSize){ORYX.Log.debug(\"Shape (%0)'s max size: (%1x%2)\",this,this.maximumSize.width,this.maximumSize.height);e=c.width()-this.maximumSize.width;if(e>0){g.x-=e}k=c.height()-this.maximumSize.height;if(k>0){g.y-=k}}if(g.x!==0||g.y!==0){c.extend(g)}var o=c.width()/d.width();var n=c.height()/d.height();var m,l,q,f,b,a,r;this.magnets.each(function(p){m=p.anchorLeft;l=p.anchorRight;q=p.anchorTop;f=p.anchorBottom;b=p.bounds.center();if(m){a=b.x}else{if(l){a=c.width()-(d.width()-b.x)}else{a=b.x*o}}if(q){r=b.y}else{if(f){r=c.height()-(d.height()-b.y)}else{r=b.y*n}}if(b.x!==a||b.y!==r){p.bounds.centerMoveTo(a,r)}});this.getLabels().each(function(p){if(!p.isAnchorLeft()){if(p.isAnchorRight()){p.setX(c.width()-(d.width()-p.oldX))}else{p.setX((p.position?p.position.x:p.x)*o)}}if(!p.isAnchorTop()){if(p.isAnchorBottom()){p.setY(c.height()-(d.height()-p.oldY))}else{p.setY((p.position?p.position.y:p.y)*n)}}if(p.position){if(!p.isOriginAnchorLeft()){if(p.isOriginAnchorRight()){p.setOriginX(c.width()-(d.width()-p.oldX))}else{p.setOriginX(p.x*o)}}if(!p.isOriginAnchorTop()){if(p.isOriginAnchorBottom()){p.setOriginY(c.height()-(d.height()-p.oldY))}else{p.setOriginY(p.y*n)}}}});var h=this.dockers[0];if(h){h.bounds.unregisterCallback(this._dockerChangedCallback);if(!this._dockerUpdated){h.bounds.centerMoveTo(this.bounds.center());this._dockerUpdated=false}h.update();h.bounds.registerCallback(this._dockerChangedCallback)}this.isResized=false}this.refresh();this.isChanged=false;this._oldBounds=this.bounds.clone()}this.children.each(function(p){if(!(p instanceof ORYX.Core.Controls.Docker)){p._update()}});if(this.dockers.length>0&&!this.dockers.first().getDockedShape()){this.dockers.each(function(p){p.bounds.centerMoveTo(this.bounds.center())}.bind(this))}},refresh:function(){arguments.callee.$.refresh.apply(this,arguments);var a=this.bounds.upperLeft().x;var b=this.bounds.upperLeft().y;this.node.firstChild.setAttributeNS(null,\"transform\",\"translate(\"+a+\", \"+b+\")\");this.node.childNodes[1].childNodes[1].setAttributeNS(null,\"transform\",\"translate(\"+a+\", \"+b+\")\");this._svgShapes.each(function(c){c.update()})},_dockerChanged:function(){var a=this.dockers[0];this.bounds.centerMoveTo(a.bounds.center());this._dockerUpdated=true},_initSVGShapes:function(c){var a=[];try{var f=new ORYX.Core.SVG.SVGShape(c);a.push(f)}catch(d){}if(c.hasChildNodes()){for(var b=0;b<c.childNodes.length;b++){a=a.concat(this._initSVGShapes(c.childNodes[b]))}}return a},isPointIncluded:function(a,k,c){var h=c&&c instanceof ORYX.Core.Bounds?c:this.absoluteBounds();if(!h.isIncluded(a,k)){return false}else{}var e=h.upperLeft();var g=a-e.x;var f=k-e.y;var d=0;do{var b=this._svgShapes[d++].isPointIncluded(g,f)}while(!b&&d<this._svgShapes.length);return b},isPointOverOffset:function(d,c){var b=arguments.callee.$.isPointOverOffset.apply(this,arguments);if(b){var a=this.absoluteBounds();a.widen(-ORYX.CONFIG.BORDER_OFFSET);if(!a.isIncluded(d,c)){return true}}return false},serialize:function(){var a=arguments.callee.$.serialize.apply(this);this.dockers.each((function(e){if(e.getDockedShape()){var d=e.referencePoint;d=d?d:e.bounds.center();a.push({name:\"docker\",prefix:\"oryx\",value:$H(d).values().join(\",\"),type:\"literal\"})}}).bind(this));try{var b=this.getStencil().serialize();if(b.type){b.shape=this;b.data=a;b.result=undefined;b.forceExecution=true;this._delegateEvent(b);if(b.result){a=b.result}}}catch(c){}return a},deserialize:function(f){arguments.callee.$.deserialize.apply(this,arguments);try{var a=this.getStencil().deserialize();if(a.type){a.shape=this;a.data=f;a.result=undefined;a.forceExecution=true;this._delegateEvent(a);if(a.result){f=a.result}}}catch(g){}var b=f.findAll(function(e){return(e.prefix+\"-\"+e.name)==\"raziel-outgoing\"});b.each((function(h){if(!this.parent){return}var e=this.getCanvas().getChildShapeByResourceId(h.value);if(e){if(e instanceof ORYX.Core.Edge){e.dockers.first().setDockedShape(this);e.dockers.first().setReferencePoint(e.dockers.first().bounds.center())}else{if(e.dockers.length>0){e.dockers.first().setDockedShape(this)}}}}).bind(this));if(this.dockers.length===1){var d;d=f.find(function(e){return(e.prefix+\"-\"+e.name===\"oryx-dockers\")});if(d){var c=d.value.replace(/,/g,\" \").split(\" \").without(\"\").without(\"#\");if(c.length===2&&this.dockers[0].getDockedShape()){this.dockers[0].setReferencePoint({x:parseFloat(c[0]),y:parseFloat(c[1])})}else{this.dockers[0].bounds.centerMoveTo(parseFloat(c[0]),parseFloat(c[1]))}}}},_init:function(n){arguments.callee.$._init.apply(this,arguments);var o=n.getElementsByTagName(\"g\")[0];var r=n.ownerDocument.createAttribute(\"title\");r.nodeValue=this.getStencil().title();o.setAttributeNode(r);var u=n.ownerDocument.createAttribute(\"id\");u.nodeValue=this.id;o.setAttributeNode(u);var b=this.node.childNodes[0].childNodes[0];o=b.appendChild(o);this.addEventHandlers(o.parentNode);var t=o.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX,\"minimumSize\");if(t){t=t.replace(\"/,/g\",\" \");var k=t.split(\" \");k=k.without(\"\");if(k.length>1){this.minimumSize={width:parseFloat(k[0]),height:parseFloat(k[1])}}else{this.minimumSize={width:1,height:1}}}var g=o.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX,\"maximumSize\");if(g){g=g.replace(\"/,/g\",\" \");var l=g.split(\" \");l=l.without(\"\");if(l.length>1){this.maximumSize={width:parseFloat(l[0]),height:parseFloat(l[1])}}}if(this.minimumSize&&this.maximumSize&&(this.minimumSize.width>this.maximumSize.width||this.minimumSize.height>this.maximumSize.height)){throw this+\": Minimum Size must be greater than maxiumSize.\"}this._svgShapes=this._initSVGShapes(o);var a={x:undefined,y:undefined};var d={x:undefined,y:undefined};var y=this;this._svgShapes.each(function(z){a.x=(a.x!==undefined)?Math.min(a.x,z.x):z.x;a.y=(a.y!==undefined)?Math.min(a.y,z.y):z.y;d.x=(d.x!==undefined)?Math.max(d.x,z.x+z.width):z.x+z.width;d.y=(d.y!==undefined)?Math.max(d.y,z.y+z.height):z.y+z.height;if(z.isHorizontallyResizable){y.isHorizontallyResizable=true;y.isResizable=true}if(z.isVerticallyResizable){y.isVerticallyResizable=true;y.isResizable=true}if(z.anchorTop&&z.anchorBottom){y.isVerticallyResizable=true;y.isResizable=true}if(z.anchorLeft&&z.anchorRight){y.isHorizontallyResizable=true;y.isResizable=true}});this._svgShapes.each(function(z){z.x-=a.x;z.y-=a.y;z.update()});var x=a.x;var w=a.y;d.x-=x;d.y-=w;a.x=0;a.y=0;if(d.x===0){d.x=1}if(d.y===0){d.y=1}this._oldBounds.set(a,d);this.bounds.set(a,d);var f=n.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_ORYX,\"magnets\");if(f&&f.length>0){f=$A(f[0].getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_ORYX,\"magnet\"));var y=this;f.each(function(A){var E=new ORYX.Core.Controls.Magnet({eventHandlerCallback:y.eventHandlerCallback});var z=parseFloat(A.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX,\"cx\"));var F=parseFloat(A.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX,\"cy\"));E.bounds.centerMoveTo({x:z-x,y:F-w});var D=A.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX,\"anchors\");if(D){D=D.replace(\"/,/g\",\" \");D=D.split(\" \").without(\"\");for(var B=0;B<D.length;B++){switch(D[B].toLowerCase()){case\"left\":E.anchorLeft=true;break;case\"right\":E.anchorRight=true;break;case\"top\":E.anchorTop=true;break;case\"bottom\":E.anchorBottom=true;break}}}y.add(E);if(!this._defaultMagnet){var C=A.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX,\"default\");if(C&&C.toLowerCase()===\"yes\"){y._defaultMagnet=E}}})}else{var h=new ORYX.Core.Controls.Magnet();h.bounds.centerMoveTo(this.bounds.width()/2,this.bounds.height()/2);this.add(h)}var s=n.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_ORYX,\"docker\");if(s&&s.length>0){s=s[0];var q=this.createDocker();var e=parseFloat(s.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX,\"cx\"));var c=parseFloat(s.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX,\"cy\"));q.bounds.centerMoveTo({x:e-x,y:c-w});var p=s.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX,\"anchors\");if(p){p=p.replace(\"/,/g\",\" \");p=p.split(\" \").without(\"\");for(var v=0;v<p.length;v++){switch(p[v].toLowerCase()){case\"left\":q.anchorLeft=true;break;case\"right\":q.anchorRight=true;break;case\"top\":q.anchorTop=true;break;case\"bottom\":q.anchorBottom=true;break}}}}var m=o.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG,\"text\");$A(m).each((function(A){var z=new ORYX.Core.SVG.Label({textElement:A,shapeId:this.id});z.x-=x;z.y-=w;this._labels[z.id]=z;z.registerOnChange(this.layout.bind(this));if(this._stencil.id().indexOf(ORYX.CONFIG.FORM_ELEMENT_ID_PREFIX)==0){z.registerOnChange(this.fitToLabels.bind(this))}}).bind(this))},fitToLabels:function(){var e=0;this.getLabels().each(function(g){var f=g.getY()+g.getHeight();if(f>e){e=f}});var c=this.bounds;var b=false;if(this.minimumSize){var d=this.minimumSize.height;if(e<d&&c.height()>d&&d>this.forcedHeight){c.set(c.upperLeft().x,c.upperLeft().y,c.lowerRight().x,c.upperLeft().y+d);b=true}else{if(e>d&&c.height()!=e&&e>this.forcedHeight){c.set(c.upperLeft().x,c.upperLeft().y,c.lowerRight().x,c.upperLeft().y+e);b=true}else{if(c.height()>this.forcedHeight&&this.forcedHeight>0){c.set(c.upperLeft().x,c.upperLeft().y,c.lowerRight().x,c.upperLeft().y+this.forcedHeight);b=true}}}}if(b){if(this.facade.getCanvas()!=null){this.facade.getCanvas().update()}if(this.facade.getSelection().member(this)){var a=this.facade.getSelection();this.facade.setSelection([]);this.facade.setSelection(a)}}},createDocker:function(){var a=new ORYX.Core.Controls.Docker({eventHandlerCallback:this.eventHandlerCallback});a.bounds.registerCallback(this._dockerChangedCallback);this.dockers.push(a);a.parent=this;a.bounds.registerCallback(this._changedCallback);return a},toString:function(){return this._stencil.title()+\" \"+this.id}};ORYX.Core.Node=ORYX.Core.Shape.extend(ORYX.Core.Node);NAMESPACE_SVG=\"http://www.w3.org/2000/svg\";NAMESPACE_ORYX=\"http://www.b3mn.org/oryx\";if(!ORYX){var ORYX={}}if(!ORYX.Core){ORYX.Core={}}ORYX.Core.Edge={construct:function(a,d,b){arguments.callee.$.construct.apply(this,arguments);this.isMovable=true;this.isSelectable=true;this._dockerUpdated=false;this._markers=new Hash();this._paths=[];this._interactionPaths=[];this._dockersByPath=new Hash();this._markersByPath=new Hash();this.attachedNodePositionData=new Hash();var c=this.node.childNodes[0].childNodes[0];c=ORYX.Editor.graft(\"http://www.w3.org/2000/svg\",c,[\"g\",{\"pointer-events\":\"painted\"}]);this.addEventHandlers(c.parentNode);this._oldBounds=this.bounds.clone();this._init(this._stencil.view());if(d instanceof Array){this.deserialize(d)}},_update:function(c){if(this._dockerUpdated||this.isChanged||c){this.dockers.invoke(\"update\");if(false&&(this.bounds.width()===0||this.bounds.height()===0)){var d=this.bounds.width();var q=this.bounds.height();this.bounds.extend({x:d===0?2:0,y:q===0?2:0});this.bounds.moveBy({x:d===0?-1:0,y:q===0?-1:0})}var e=this.bounds.upperLeft();var n=this._oldBounds.upperLeft();var f=this._oldBounds.width()===0?this.bounds.width():this._oldBounds.width();var p=this._oldBounds.height()===0?this.bounds.height():this._oldBounds.height();var m=e.x-n.x;var k=e.y-n.y;var o=(this.bounds.width()/f)||1;var g=(this.bounds.height()/p)||1;this.dockers.each((function(b){b.bounds.unregisterCallback(this._dockerChangedCallback);if(!this._dockerUpdated){b.bounds.moveBy(m,k);if(o!==1||g!==1){var s=b.bounds.upperLeft().x-e.x;var a=b.bounds.upperLeft().y-e.y;b.bounds.moveTo(e.x+s*o,e.y+a*g)}}b.update();b.bounds.registerCallback(this._dockerChangedCallback)}).bind(this));if(this._dockerUpdated){var l=this.dockers.first().bounds.center();var h=this.dockers.first().bounds.center();this.dockers.each((function(b){var a=b.bounds.center();l.x=Math.min(l.x,a.x);l.y=Math.min(l.y,a.y);h.x=Math.max(h.x,a.x);h.y=Math.max(h.y,a.y)}).bind(this));this.bounds.set(Object.clone(l),Object.clone(h))}e=this.bounds.upperLeft();n=this._oldBounds.upperLeft();o=(this.bounds.width()/(f||this.bounds.width()));g=(this.bounds.height()/(p||this.bounds.height()));m=e.x-n.x;k=e.y-n.y;this.getLabels().each(function(C){if(C.getReferencePoint()){var w=C.getReferencePoint();var K=w.segment.from,b=w.segment.to;if(!K||!K.parent||!b||!b.parent){return}var J=K.bounds.center(),B=b.bounds.center();if(J.x===w.segment.fromPosition.x&&J.y===w.segment.fromPosition.y&&B.x===w.segment.toPosition.x&&B.y===w.segment.toPosition.y&&!w.dirty){return}if(!this.parent.initializingShapes){var L=ORYX.Core.Math.getDistanceBetweenTwoPoints(w.segment.fromPosition,w.segment.toPosition,w.intersection);var M=ORYX.Core.Math.getPointBetweenTwoPoints(J,B,isNaN(L)?0.5:L);var I=ORYX.Core.Math.getOrthogonalIdentityVector(J,B);var a=Math.abs(I.y)===1,F=Math.abs(I.x)===1;I.x*=w.distance;I.y*=w.distance;I.x+=M.x;I.y+=M.y;var H=a&&w.orientation&&(w.iorientation||w.orientation).endsWith(\"r\")?-C.getWidth():0;var G=F&&w.orientation&&(w.iorientation||w.orientation).startsWith(\"l\")?-C.getHeight()+2:0;C.setX(I.x+H);C.setY(I.y+G);this.updateReferencePointOfLabel(C,M,K,b)}else{var I=ORYX.Core.Math.getOrthogonalIdentityVector(J,B);I.x*=w.distance;I.y*=w.distance;I.x+=w.intersection.x;I.y+=w.intersection.y;C.setX(I.x);C.setY(I.y);w.segment.fromPosition=J;w.segment.toPosition=B}return}if(C.position&&!this.parent.initializingShapes){var E=C.position.x+(m*(o||1));if(E>this.bounds.lowerRight().x){E+=this.bounds.width()-(this.bounds.width()/(o||1))}var D=C.position.y+(k*(g||1));if(D>this.bounds.lowerRight().y){D+=this.bounds.height()-(this.bounds.height()/(g||1))}C.setX(E);C.setY(D);return}switch(C.getEdgePosition()){case\"starttop\":var N=this._getAngle(this.dockers[0],this.dockers[1]);var z=this.dockers.first().bounds.center();if(N<=90||N>270){C.horizontalAlign(\"left\");C.verticalAlign(\"bottom\");C.x=z.x+C.getOffsetTop();C.y=z.y-C.getOffsetTop();C.rotate(360-N,z)}else{C.horizontalAlign(\"right\");C.verticalAlign(\"bottom\");C.x=z.x-C.getOffsetTop();C.y=z.y-C.getOffsetTop();C.rotate(180-N,z)}break;case\"startmiddle\":var N=this._getAngle(this.dockers[0],this.dockers[1]);var z=this.dockers.first().bounds.center();if(N<=90||N>270){C.horizontalAlign(\"left\");C.verticalAlign(\"bottom\");C.x=z.x+2;C.y=z.y+4;C.rotate(360-N,z)}else{C.horizontalAlign(\"right\");C.verticalAlign(\"bottom\");C.x=z.x+1;C.y=z.y+4;C.rotate(180-N,z)}break;case\"startbottom\":var N=this._getAngle(this.dockers[0],this.dockers[1]);var z=this.dockers.first().bounds.center();if(N<=90||N>270){C.horizontalAlign(\"left\");C.verticalAlign(\"top\");C.x=z.x+C.getOffsetBottom();C.y=z.y+C.getOffsetBottom();C.rotate(360-N,z)}else{C.horizontalAlign(\"right\");C.verticalAlign(\"top\");C.x=z.x-C.getOffsetBottom();C.y=z.y+C.getOffsetBottom();C.rotate(180-N,z)}break;case\"midtop\":var v=this.dockers.length;if(v%2==0){var N=this._getAngle(this.dockers[v/2-1],this.dockers[v/2]);var u=this.dockers[v/2-1].bounds.center();var s=this.dockers[v/2].bounds.center();var z={x:(u.x+s.x)/2,y:(u.y+s.y)/2};C.horizontalAlign(\"center\");C.verticalAlign(\"bottom\");C.x=z.x;C.y=z.y-C.getOffsetTop();if(N<=90||N>270){C.rotate(360-N,z)}else{C.rotate(180-N,z)}}else{var A=parseInt(v/2);var N=this._getAngle(this.dockers[A],this.dockers[A+1]);var z=this.dockers[A].bounds.center();if(N<=90||N>270){C.horizontalAlign(\"left\");C.verticalAlign(\"bottom\");C.x=z.x+C.getOffsetTop();C.y=z.y-C.getOffsetTop();C.rotate(360-N,z)}else{C.horizontalAlign(\"right\");C.verticalAlign(\"bottom\");C.x=z.x-C.getOffsetTop();C.y=z.y-C.getOffsetTop();C.rotate(180-N,z)}}break;case\"midbottom\":var v=this.dockers.length;if(v%2==0){var N=this._getAngle(this.dockers[v/2-1],this.dockers[v/2]);var u=this.dockers[v/2-1].bounds.center();var s=this.dockers[v/2].bounds.center();var z={x:(u.x+s.x)/2,y:(u.y+s.y)/2};C.horizontalAlign(\"center\");C.verticalAlign(\"top\");C.x=z.x;C.y=z.y+C.getOffsetTop();if(N<=90||N>270){C.rotate(360-N,z)}else{C.rotate(180-N,z)}}else{var A=parseInt(v/2);var N=this._getAngle(this.dockers[A],this.dockers[A+1]);var z=this.dockers[A].bounds.center();if(N<=90||N>270){C.horizontalAlign(\"left\");C.verticalAlign(\"top\");C.x=z.x+C.getOffsetBottom();C.y=z.y+C.getOffsetBottom();C.rotate(360-N,z)}else{C.horizontalAlign(\"right\");C.verticalAlign(\"top\");C.x=z.x-C.getOffsetBottom();C.y=z.y+C.getOffsetBottom();C.rotate(180-N,z)}}break;case\"endtop\":var t=this.dockers.length;var N=this._getAngle(this.dockers[t-2],this.dockers[t-1]);var z=this.dockers.last().bounds.center();if(N<=90||N>270){C.horizontalAlign(\"right\");C.verticalAlign(\"bottom\");C.x=z.x-C.getOffsetTop();C.y=z.y-C.getOffsetTop();C.rotate(360-N,z)}else{C.horizontalAlign(\"left\");C.verticalAlign(\"bottom\");C.x=z.x+C.getOffsetTop();C.y=z.y-C.getOffsetTop();C.rotate(180-N,z)}break;case\"endbottom\":var t=this.dockers.length;var N=this._getAngle(this.dockers[t-2],this.dockers[t-1]);var z=this.dockers.last().bounds.center();if(N<=90||N>270){C.horizontalAlign(\"right\");C.verticalAlign(\"top\");C.x=z.x-C.getOffsetBottom();C.y=z.y+C.getOffsetBottom();C.rotate(360-N,z)}else{C.horizontalAlign(\"left\");C.verticalAlign(\"top\");C.x=z.x+C.getOffsetBottom();C.y=z.y+C.getOffsetBottom();C.rotate(180-N,z)}break}}.bind(this));this.children.each(function(a){if(a instanceof ORYX.Core.Node){this.calculatePositionOfAttachedChildNode.call(this,a)}}.bind(this));this.refreshAttachedNodes();this.refresh();this.isChanged=false;this._dockerUpdated=false;this._oldBounds=this.bounds.clone()}var r=navigator.userAgent;if(navigator.appVersion.indexOf(\"MSIE 10\")!==-1||(r.indexOf(\"Trident\")!==-1&&r.indexOf(\"rv:11\")!==-1)){this.node.parentNode.insertBefore(this.node,this.node)}},movePointToUpperLeftOfNode:function(a,b){a.x-=b.width()/2;a.y-=b.height()/2},refreshAttachedNodes:function(){this.attachedNodePositionData.values().each(function(a){var d=a.segment.docker1.bounds.center();var b=a.segment.docker2.bounds.center();this.relativizePoint(d);this.relativizePoint(b);var c=new Object();c.x=d.x+a.relativDistanceFromDocker1*(b.x-d.x);c.y=d.y+a.relativDistanceFromDocker1*(b.y-d.y);this.movePointToUpperLeftOfNode(c,a.node.bounds);a.node.bounds.moveTo(c);a.node._update()}.bind(this))},calculatePositionOfAttachedChildNode:function(b){var a=new Object();a.x=0;a.y=0;if(!this.attachedNodePositionData[b.getId()]){this.attachedNodePositionData[b.getId()]=new Object();this.attachedNodePositionData[b.getId()].relativDistanceFromDocker1=0;this.attachedNodePositionData[b.getId()].node=b;this.attachedNodePositionData[b.getId()].segment=new Object();this.findEdgeSegmentForNode(b)}else{if(b.isChanged){this.findEdgeSegmentForNode(b)}}},findEdgeSegmentForNode:function(c){var b=this.dockers.length;var a=undefined;for(i=1;i<b;i++){var g=this.dockers[i-1].bounds.center();var e=this.dockers[i].bounds.center();this.relativizePoint(g);this.relativizePoint(e);var d=c.bounds.center();var f=ORYX.Core.Math.distancePointLinie(g,e,d,true);if((f||f==0)&&((!a&&a!=0)||f<a)){a=f;this.attachedNodePositionData[c.getId()].segment.docker1=this.dockers[i-1];this.attachedNodePositionData[c.getId()].segment.docker2=this.dockers[i]}if(!f&&!a&&a!=0){(ORYX.Core.Math.getDistancePointToPoint(d,g)<ORYX.Core.Math.getDistancePointToPoint(d,e))?this.attachedNodePositionData[c.getId()].relativDistanceFromDocker1=0:this.attachedNodePositionData[c.getId()].relativDistanceFromDocker1=1;this.attachedNodePositionData[c.getId()].segment.docker1=this.dockers[i-1];this.attachedNodePositionData[c.getId()].segment.docker2=this.dockers[i]}}if(a||a==0){this.attachedNodePositionData[c.getId()].relativDistanceFromDocker1=this.getLineParameterForPosition(this.attachedNodePositionData[c.getId()].segment.docker1,this.attachedNodePositionData[c.getId()].segment.docker2,c)}},findSegment:function(c){var b=this.dockers.length;var a;var d=c instanceof ORYX.Core.UIObject?c.bounds.center():c;for(i=1;i<b;i++){var g=this.dockers[i-1].bounds.center();var e=this.dockers[i].bounds.center();var f=ORYX.Core.Math.distancePointLinie(g,e,d,true);if(typeof f==\"number\"&&(a===undefined||f<a.distance)){a={distance:f,fromDocker:this.dockers[i-1],toDocker:this.dockers[i]}}}return a},getLineParameterForPosition:function(b,g,d){var f=b.bounds.center();var e=g.bounds.center();this.relativizePoint(f);this.relativizePoint(e);var c=ORYX.Core.Math.getPointOfIntersectionPointLine(f,e,d.bounds.center(),true);if(!c){return 0}var a=ORYX.Core.Math.getDistancePointToPoint(c,f)/ORYX.Core.Math.getDistancePointToPoint(f,e);return a},relativizePoint:function(a){a.x-=this.bounds.upperLeft().x;a.y-=this.bounds.upperLeft().y},optimizedUpdate:function(){var a=function(b){if(!b._dockedShape||!b._dockedShapeBounds){return}var c={x:b._dockedShape.bounds.a.x-b._dockedShapeBounds.a.x,y:b._dockedShape.bounds.a.y-b._dockedShapeBounds.a.y};b.bounds.moveBy(c);b._dockedShapeBounds.moveBy(c)};a(this.dockers.first());a(this.dockers.last());this.refresh()},refresh:function(){arguments.callee.$.refresh.apply(this,arguments);var b;this._paths.each((function(h,f){var e=this._dockersByPath[h.id];var l=undefined;var k=undefined;if(b){k=\"M\"+b.x+\" \"+b.y}else{l=e[0].bounds.center();b=l;k=\"M\"+l.x+\" \"+l.y}for(var g=1;g<e.length;g++){l=e[g].bounds.center();k=k+\"L\"+l.x+\" \"+l.y+\" \";b=l}h.setAttributeNS(null,\"d\",k);this._interactionPaths[f].setAttributeNS(null,\"d\",k)}).bind(this));if(this.getChildNodes().length>0){var a=this.bounds.upperLeft().x;var c=this.bounds.upperLeft().y;this.node.firstChild.childNodes[1].setAttributeNS(null,\"transform\",\"translate(\"+a+\", \"+c+\")\")}},getIntersectionPoint:function(){var a=Math.floor(this.dockers.length/2);return ORYX.Core.Math.midPoint(this.dockers[a-1].bounds.center(),this.dockers[a].bounds.center())},isBoundsIncluded:function(c){var a=this.dockers,b=a.length;return a.any(function(g,f){if(f==b-1){return false}var e=g.bounds.center();var d=a[f+1].bounds.center();return ORYX.Core.Math.isRectOverLine(e.x,e.y,d.x,d.y,c.a.x,c.a.y,c.b.x,c.b.y)})},isPointIncluded:function(g,f){var a=this.absoluteBounds().isIncluded(g,f,ORYX.CONFIG.OFFSET_EDGE_BOUNDS);var e=undefined;if(a&&this.dockers.length>0){var c=0;var d,b;do{d=this.dockers[c].bounds.center();b=this.dockers[++c].bounds.center();e=ORYX.Core.Math.isPointInLine(g,f,d.x,d.y,b.x,b.y,ORYX.CONFIG.OFFSET_EDGE_BOUNDS)}while(!e&&c<this.dockers.length-1)}return e},isPointOverOffset:function(){return false},containsNode:function(a){if(this._paths.include(a)||this._interactionPaths.include(a)){return true}return false},_getAngle:function(a,d){var c=a instanceof ORYX.Core.Controls.Docker?a.absoluteCenterXY():a;var b=d instanceof ORYX.Core.Controls.Docker?d.absoluteCenterXY():d;return ORYX.Core.Math.getAngle(c,b)},alignDockers:function(){this._update(true);var e=this.dockers.first().bounds.center();var d=this.dockers.last().bounds.center();var c=d.x-e.x;var a=d.y-e.y;var b=this.dockers.length-1;this.dockers.each((function(h,g){var f=g/b;h.bounds.unregisterCallback(this._dockerChangedCallback);h.bounds.moveTo(e.x+f*c,e.y+f*a);h.bounds.registerCallback(this._dockerChangedCallback)}).bind(this));this._dockerChanged()},add:function(a){arguments.callee.$.add.apply(this,arguments);if(a instanceof ORYX.Core.Controls.Docker&&this.dockers.include(a)){var b=this._dockersByPath.values()[0];if(b){b.splice(this.dockers.indexOf(a),0,a)}this.handleChildShapesAfterAddDocker(a)}},handleChildShapesAfterAddDocker:function(f){if(!f instanceof ORYX.Core.Controls.Docker){return undefined}var d=this.dockers.indexOf(f);if(!(0<d&&d<this.dockers.length-1)){return undefined}var e=this.dockers[d-1];var b=this.dockers[d+1];var c=this.getAttachedNodePositionDataForSegment(e,b);var a=ORYX.Core.Math.getDistancePointToPoint(e.bounds.center(),f.bounds.center());var h=ORYX.Core.Math.getDistancePointToPoint(b.bounds.center(),f.bounds.center());if(!(a+h)){return}var g=a/(a+h);c.each(function(m){if(m.value.relativDistanceFromDocker1<g){m.value.segment.docker2=f;m.value.relativDistanceFromDocker1=m.value.relativDistanceFromDocker1/g}else{m.value.segment.docker1=f;var l=1-g;var k=m.value.relativDistanceFromDocker1-g;m.value.relativDistanceFromDocker1=k/l}});this.getLabels().each(function(m){var o=m.getReferencePoint();if(!o){return}var l=this.dockers.indexOf(f);if(l>=o.segment.fromIndex&&l<=o.segment.toIndex){var n=this.findSegment(o.intersection);if(!n){n.fromDocker=o.segment.fromIndex>=(this.dockers.length/2)?this.dockers[0]:this.dockers[this.dockers.length-2];n.toDocker=this.dockers[this.dockers.indexOf(from)+1]}var k=n.fromDocker.bounds.center(),p=n.toDocker.bounds.center();var q=ORYX.Core.Math.getPointOfIntersectionPointLine(k,p,o.intersection,true);this.updateReferencePointOfLabel(m,q,n.fromDocker,n.toDocker,true)}}.bind(this));this.refreshAttachedNodes()},getAttachedNodePositionDataForSegment:function(c,a){if(!((c instanceof ORYX.Core.Controls.Docker)&&(a instanceof ORYX.Core.Controls.Docker))){return[]}var b=this.attachedNodePositionData.findAll(function(d){return d.value.segment.docker1===c&&d.value.segment.docker2===a});if(!b){return[]}return b},remove:function(a){arguments.callee.$.remove.apply(this,arguments);if(this.attachedNodePositionData[a.getId()]){delete this.attachedNodePositionData[a.getId()]}if(a instanceof ORYX.Core.Controls.Docker){this.handleChildShapesAfterRemoveDocker(a)}},updateReferencePointOfLabel:function(a,g,f,e,b){if(!a.getReferencePoint()||!a.isVisible){return}var c=a.getReferencePoint();if(c.orientation&&c.orientation!==\"ce\"){var d=this._getAngle(f,e);if(c.distance>=0){if(d==0){a.horizontalAlign(\"left\");a.verticalAlign(\"bottom\")}else{if(d>0&&d<90){a.horizontalAlign(\"right\");a.verticalAlign(\"bottom\")}else{if(d==90){a.horizontalAlign(\"right\");a.verticalAlign(\"top\")}else{if(d>90&&d<180){a.horizontalAlign(\"right\");a.verticalAlign(\"top\")}else{if(d==180){a.horizontalAlign(\"left\");a.verticalAlign(\"top\")}else{if(d>180&&d<270){a.horizontalAlign(\"left\");a.verticalAlign(\"top\")}else{if(d==270){a.horizontalAlign(\"left\");a.verticalAlign(\"top\")}else{if(d>270&&d<=360){a.horizontalAlign(\"left\");a.verticalAlign(\"bottom\")}}}}}}}}}else{if(d==0){a.horizontalAlign(\"left\");a.verticalAlign(\"top\")}else{if(d>0&&d<90){a.horizontalAlign(\"left\");a.verticalAlign(\"top\")}else{if(d==90){a.horizontalAlign(\"left\");a.verticalAlign(\"top\")}else{if(d>90&&d<180){a.horizontalAlign(\"left\");a.verticalAlign(\"bottom\")}else{if(d==180){a.horizontalAlign(\"left\");a.verticalAlign(\"bottom\")}else{if(d>180&&d<270){a.horizontalAlign(\"right\");a.verticalAlign(\"bottom\")}else{if(d==270){a.horizontalAlign(\"right\");a.verticalAlign(\"top\")}else{if(d>270&&d<=360){a.horizontalAlign(\"right\");a.verticalAlign(\"top\")}}}}}}}}}c.iorientation=c.iorientation||c.orientation;c.orientation=(a.verticalAlign()==\"top\"?\"u\":\"l\")+(a.horizontalAlign()==\"left\"?\"l\":\"r\")}a.setReferencePoint(jQuery.extend({},{intersection:g,segment:{from:f,fromIndex:this.dockers.indexOf(f),fromPosition:f.bounds.center(),to:e,toIndex:this.dockers.indexOf(e),toPosition:e.bounds.center()},dirty:b||false},c))},handleChildShapesAfterRemoveDocker:function(a){if(!(a instanceof ORYX.Core.Controls.Docker)){return}this.attachedNodePositionData.each(function(c){if(c.value.segment.docker1===a){var b=this.dockers.indexOf(c.value.segment.docker2);if(b==-1){return}c.value.segment.docker1=this.dockers[b-1]}else{if(c.value.segment.docker2===a){var b=this.dockers.indexOf(c.value.segment.docker1);if(b==-1){return}c.value.segment.docker2=this.dockers[b+1]}}}.bind(this));this.getLabels().each(function(b){var d=b.getReferencePoint();if(!d){return}var g=d.segment.from;var f=d.segment.to;if(g!==a&&f!==a){return}var c=this.findSegment(d.intersection);if(!c){g=c.fromDocker;f=c.toDocker}else{g=g===a?this.dockers[this.dockers.indexOf(f)-1]:g;f=this.dockers[this.dockers.indexOf(g)+1]}var e=ORYX.Core.Math.getPointOfIntersectionPointLine(g.bounds.center(),f.bounds.center(),d.intersection,true);this.updateReferencePointOfLabel(b,e,g,f,true)}.bind(this));this.refreshAttachedNodes()},addDocker:function(b,d){var c;var a;this._dockersByPath.any((function(e){return e.value.any((function(h,l){if(!c){c=h;return false}else{var n=c.bounds.center();var m=h.bounds.center();var f=1;if(!isNaN(screen.logicalXDPI)&&!isNaN(screen.systemXDPI)){var g=navigator.userAgent;if(g.indexOf(\"MSIE\")>=0){var p=Math.round((screen.deviceXDPI/screen.logicalXDPI)*100);if(p!==100){f=p/100}}}if(f!==1){b.x=b.x/f;b.y=b.y/f}if(ORYX.Core.Math.isPointInLine(b.x,b.y,n.x,n.y,m.x,m.y,10)){var q=this._paths.find(function(r){return r.id===e.key});if(q){var o=q.getAttributeNS(NAMESPACE_ORYX,\"allowDockers\");if(o&&o.toLowerCase()===\"no\"){return true}}var k=(d)?d:this.createDocker(this.dockers.indexOf(c)+1,b);k.bounds.centerMoveTo(b);if(d){this.add(k,this.dockers.indexOf(c)+1)}a=k;return true}else{c=h;return false}}}).bind(this))}).bind(this));return a},removeDocker:function(a){if(this.dockers.length>2&&!(this.dockers.first()===a)){this._dockersByPath.any((function(b){if(b.value.member(a)){if(a===b.value.last()){return true}else{this.remove(a);this._dockersByPath[b.key]=b.value.without(a);this.isChanged=true;this._dockerChanged();return true}}return false}).bind(this))}},removeUnusedDockers:function(){var a=$H({});this.dockers.each(function(e,b){if(b==0||b==this.dockers.length-1){return}var d=this.dockers[b-1];if(a.values().indexOf(d)!=-1&&this.dockers[b-2]){d=this.dockers[b-2]}var c=this.dockers[b+1];var f=d.getDockedShape()&&d.referencePoint?d.getAbsoluteReferencePoint():d.bounds.center();var h=c.getDockedShape()&&c.referencePoint?c.getAbsoluteReferencePoint():c.bounds.center();var g=e.bounds.center();if(ORYX.Core.Math.isPointInLine(g.x,g.y,f.x,f.y,h.x,h.y,1)){a[b]=e}}.bind(this));a.each(function(b){this.removeDocker(b.value)}.bind(this));if(a.values().length>0){this._update(true)}return a},_init:function(f){arguments.callee.$._init.apply(this,arguments);var e,c,s,q;var k=f.getElementsByTagNameNS(NAMESPACE_SVG,\"defs\");if(k.length>0){k=k[0];var d=$A(k.getElementsByTagNameNS(NAMESPACE_SVG,\"marker\"));var l;var o=this;d.each(function(t){try{l=new ORYX.Core.SVG.SVGMarker(t.cloneNode(true));o._markers[l.id]=l;var u=$A(l.element.getElementsByTagNameNS(NAMESPACE_SVG,\"text\"));var g;u.each(function(w){g=new ORYX.Core.SVG.Label({textElement:w,shapeId:this.id});o._labels[g.id]=g})}catch(v){}})}var b=f.getElementsByTagNameNS(NAMESPACE_SVG,\"g\");if(b.length<=0){throw\"Edge: No g element found.\"}var m=b[0];m.setAttributeNS(null,\"id\",null);var h=true;$A(m.childNodes).each((function(G,A){if(ORYX.Editor.checkClassType(G,SVGPathElement)){G=G.cloneNode(false);var z=this.id+\"_\"+A;G.setAttributeNS(null,\"id\",z);this._paths.push(G);var C=[];var H=G.getAttributeNS(null,\"marker-start\");if(H&&H!==\"\"){H=H.strip();H=H.replace(/^url\\(#/,\"\");var w=this.getValidMarkerId(H);G.setAttributeNS(null,\"marker-start\",\"url(#\"+w+\")\");C.push(this._markers[w])}H=G.getAttributeNS(null,\"marker-mid\");if(H&&H!==\"\"){H=H.strip();H=H.replace(/^url\\(#/,\"\");var t=this.getValidMarkerId(H);G.setAttributeNS(null,\"marker-mid\",\"url(#\"+t+\")\");C.push(this._markers[t])}H=G.getAttributeNS(null,\"marker-end\");if(H&&H!==\"\"){H=H.strip();var B=this.getValidMarkerId(H);G.setAttributeNS(null,\"marker-end\",\"url(#\"+B+\")\");C.push(this._markers[B])}this._markersByPath[z]=C;var g=new PathParser();var F=new ORYX.Core.SVG.PointsPathHandler();g.setHandler(F);g.parsePath(G);if(F.points.length<4){throw\"Edge: Path has to have two or more points specified.\"}this._dockersByPath[z]=[];for(var v=0;v<F.points.length;v+=2){var E=F.points[v];var D=F.points[v+1];if(h||v>0){var u=new ORYX.Core.Controls.Docker({eventHandlerCallback:this.eventHandlerCallback});u.bounds.centerMoveTo(E,D);u.bounds.registerCallback(this._dockerChangedCallback);this.add(u,this.dockers.length);if(e){e=Math.min(E,e);c=Math.min(D,c)}else{e=E;c=D}if(s){s=Math.max(E,s);q=Math.max(D,q)}else{s=E;q=D}}}h=false}}).bind(this));this.bounds.set(e,c,s,q);if(false&&(this.bounds.width()===0||this.bounds.height()===0)){var a=this.bounds.width();var p=this.bounds.height();this.bounds.extend({x:a===0?2:0,y:p===0?2:0});this.bounds.moveBy({x:a===0?-1:0,y:p===0?-1:0})}this._oldBounds=this.bounds.clone();this._paths.reverse();var r=[];this._paths.each((function(g){r.push(this.node.childNodes[0].childNodes[0].childNodes[0].appendChild(g))}).bind(this));this._paths=r;this._paths.each((function(t){var g=t.cloneNode(false);g.setAttributeNS(null,\"id\",undefined);g.setAttributeNS(null,\"stroke-width\",10);g.setAttributeNS(null,\"visibility\",\"hidden\");g.setAttributeNS(null,\"stroke-dasharray\",null);g.setAttributeNS(null,\"stroke\",\"black\");g.setAttributeNS(null,\"fill\",\"none\");g.setAttributeNS(null,\"title\",this.getStencil().title());this._interactionPaths.push(this.node.childNodes[0].childNodes[0].childNodes[0].appendChild(g))}).bind(this));this._paths.reverse();this._interactionPaths.reverse();var n=f.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG,\"text\");$A(n).each((function(t){var g=new ORYX.Core.SVG.Label({textElement:t,shapeId:this.id});this.node.childNodes[0].childNodes[0].appendChild(g.node);this._labels[g.id]=g;g.registerOnChange(this.layout.bind(this))}).bind(this));this.propertiesChanged.each(function(g){g.value=true})},getValidMarkerId:function(b){if(b.indexOf('url(\"#')>=0){var a=b.replace(/^url\\(\\\"#/,\"\").replace(/\\\"\\)$/,\"\");return this.id+a}else{b=b.replace(/^url\\(#/,\"\");return this.id.concat(b.replace(/\\)$/,\"\"))}},addMarkers:function(a){this._markers.each(function(b){if(!a.ownerDocument.getElementById(b.value.id)){b.value.element=a.appendChild(b.value.element)}})},removeMarkers:function(){var b=this.node.ownerSVGElement;if(b){var a=b.getElementsByTagNameNS(NAMESPACE_SVG,\"defs\");if(a.length>0){a=a[0];this._markers.each(function(c){var d=a.ownerDocument.getElementById(c.value.id);if(d){c.value.element=a.removeChild(c.value.element)}})}}},_dockerChanged:function(){this._dockerUpdated=true},serialize:function(){var a=arguments.callee.$.serialize.apply(this);var d=\"\";this._dockersByPath.each((function(e){e.value.each(function(k){var h=k.getDockedShape()&&k.referencePoint?k.referencePoint:k.bounds.center();d=d.concat(h.x+\" \"+h.y+\" \")});d+=\" # \"}).bind(this));a.push({name:\"dockers\",prefix:\"oryx\",value:d,type:\"literal\"});var b=this.dockers.last();var g=b.getDockedShape();if(g){a.push({name:\"target\",prefix:\"raziel\",value:\"#\"+ERDF.__stripHashes(g.resourceId),type:\"resource\"})}try{var c=this.getStencil().serialize();if(c.type){c.shape=this;c.data=a;c.result=undefined;c.forceExecution=true;this._delegateEvent(c);if(c.result){a=c.result}}}catch(f){}return a},deserialize:function(f){try{var c=this.getStencil().deserialize();if(c.type){c.shape=this;c.data=f;c.result=undefined;c.forceExecution=true;this._delegateEvent(c);if(c.result){f=c.result}}}catch(h){}var g=f.find(function(e){return(e.prefix+\"-\"+e.name)==\"raziel-target\"});var a;if(g){a=this.getCanvas().getChildShapeByResourceId(g.value)}var d=f.findAll(function(e){return(e.prefix+\"-\"+e.name)==\"raziel-outgoing\"});d.each((function(l){if(!this.parent){return}var e=this.getCanvas().getChildShapeByResourceId(l.value);if(e){if(e==a){this.dockers.last().setDockedShape(e);this.dockers.last().setReferencePoint({x:e.bounds.width()/2,y:e.bounds.height()/2})}else{if(e instanceof ORYX.Core.Edge){e.dockers.first().setDockedShape(this)}}}}).bind(this));var b=f.find(function(e){return(e.prefix===\"oryx\"&&e.name===\"dockers\")});if(b){var k=b.value.split(\"#\").without(\"\").without(\" \");k.each((function(l,o){var r=l.replace(/,/g,\" \").split(\" \").without(\"\");if(r.length%2===0){var s=this._paths[o];if(s){if(o===0){while(this._dockersByPath[s.id].length>2){this.removeDocker(this._dockersByPath[s.id][1])}}else{while(this._dockersByPath[s.id].length>1){this.removeDocker(this._dockersByPath[s.id][0])}}var e=this._dockersByPath[s.id];if(o===0){var q=parseFloat(r.shift());var p=parseFloat(r.shift());if(e.first().getDockedShape()){e.first().setReferencePoint({x:q,y:p})}else{e.first().bounds.centerMoveTo(q,p)}}p=parseFloat(r.pop());q=parseFloat(r.pop());if(e.last().getDockedShape()){e.last().setReferencePoint({x:q,y:p})}else{e.last().bounds.centerMoveTo(q,p)}for(var m=0;m<r.length;m++){q=parseFloat(r[m]);p=parseFloat(r[++m]);var n=this.createDocker();n.bounds.centerMoveTo(q,p)}}}}).bind(this))}else{this.alignDockers()}arguments.callee.$.deserialize.apply(this,arguments);this._changed()},toString:function(){return this.getStencil().title()+\" \"+this.id},getTarget:function(){return this.dockers.last()?this.dockers.last().getDockedShape():null},getSource:function(){return this.dockers.first()?this.dockers.first().getDockedShape():null},isDocked:function(){var a=false;this.dockers.each(function(b){if(b.isDocked()){a=true;throw $break}});return a},toJSON:function(){var a=arguments.callee.$.toJSON.apply(this,arguments);if(this.getTarget()){a.target={resourceId:this.getTarget().resourceId}}return a}};ORYX.Core.Edge=ORYX.Core.Shape.extend(ORYX.Core.Edge);if(!ORYX){var ORYX={}}if(!ORYX.Plugins){ORYX.Plugins={}}ORYX.Plugins.AbstractPlugin=Clazz.extend({facade:null,construct:function(a){this.facade=a;this.facade.registerOnEvent(ORYX.CONFIG.EVENT_LOADED,this.onLoaded.bind(this))},onLoaded:function(){},onSelectionChanged:function(){},showOverlay:function(a,b,d,c){if(!(a instanceof Array)){a=[a]}a=a.map(function(e){var f=e;if(typeof e==\"string\"){f=this.facade.getCanvas().getChildShapeByResourceId(e);f=f||this.facade.getCanvas().getChildById(e,true)}return f}.bind(this)).compact();if(!this.overlayID){this.overlayID=this.type+ORYX.Editor.provideId()}this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_OVERLAY_SHOW,id:this.overlayID,shapes:a,attributes:b,node:d,nodePosition:c||\"NW\"})},hideOverlay:function(){this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_OVERLAY_HIDE,id:this.overlayID})},doTransform:function(d,a){if(!a||!d){return\"\"}var c=new DOMParser();var k=c.parseFromString(d,\"text/xml\");source=a;new Ajax.Request(source,{asynchronous:false,method:\"get\",onSuccess:function(m){xsl=m.responseText}.bind(this),onFailure:(function(m){ORYX.Log.error(\"XSL load failed\"+m)}).bind(this)});var f=new XSLTProcessor();var h=new DOMParser();var e=h.parseFromString(xsl,\"text/xml\");f.importStylesheet(e);try{var l=f.transformToFragment(k,document);var b=(new XMLSerializer()).serializeToString(l);b=!b.startsWith(\"<?xml\")?'<?xml version=\"1.0\" encoding=\"UTF-8\"?>'+b:b;return b}catch(g){return -1}},openXMLWindow:function(a){var b=window.open(\"data:application/xml,\"+encodeURIComponent(a),\"_blank\",\"resizable=yes,width=600,height=600,toolbar=0,scrollbars=yes\")},openDownloadWindow:function(b,c){var d=window.open(\"\");if(d!=null){d.document.open();d.document.write(\"<html><body>\");var a=d.document.createElement(\"form\");d.document.body.appendChild(a);var e=function(f,g){var h=document.createElement(\"input\");h.name=f;h.type=\"hidden\";h.value=g;return h};a.appendChild(e(\"download\",c));a.appendChild(e(\"file\",b));a.method=\"POST\";d.document.write(\"</body></html>\");d.document.close();a.action=ORYX.PATH+\"/download\";a.submit()}},getSerializedDOM:function(){var a=DataManager.serializeDOM(this.facade);a='<?xml version=\"1.0\" encoding=\"utf-8\"?><html xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:b3mn=\"http://b3mn.org/2007/b3mn\" xmlns:ext=\"http://b3mn.org/2007/ext\" xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\" xmlns:atom=\"http://b3mn.org/2007/atom+xhtml\"><head profile=\"http://purl.org/NET/erdf/profile\"><link rel=\"schema.dc\" href=\"http://purl.org/dc/elements/1.1/\" /><link rel=\"schema.dcTerms\" href=\"http://purl.org/dc/terms/ \" /><link rel=\"schema.b3mn\" href=\"http://b3mn.org\" /><link rel=\"schema.oryx\" href=\"http://oryx-editor.org/\" /><link rel=\"schema.raziel\" href=\"http://raziel.org/\" /><base href=\"'+location.href.split(\"?\")[0]+'\" /></head><body>'+a+\"</body></html>\";return a},enableReadOnlyMode:function(){this.facade.disableEvent(ORYX.CONFIG.EVENT_MOUSEDOWN);this._stopSelectionChange=function(){if(this.facade.getSelection().length>0){this.facade.setSelection([])}};this.facade.registerOnEvent(ORYX.CONFIG.EVENT_SELECTION_CHANGED,this._stopSelectionChange.bind(this))},disableReadOnlyMode:function(){this.facade.enableEvent(ORYX.CONFIG.EVENT_MOUSEDOWN);if(this._stopSelectionChange){this.facade.unregisterOnEvent(ORYX.CONFIG.EVENT_SELECTION_CHANGED,this._stopSelectionChange.bind(this));this._stopSelectionChange=undefined}},getRDFFromDOM:function(){try{var c=\"\";source=ORYX.PATH+\"lib/extract-rdf.xsl\";new Ajax.Request(source,{asynchronous:false,method:\"get\",onSuccess:function(e){c=e.responseText}.bind(this),onFailure:(function(e){ORYX.Log.error(\"XSL load failed\"+e)}).bind(this)});var k=new DOMParser();var h=k.parseFromString(this.getSerializedDOM(),\"text/xml\");var f=k.parseFromString(c,\"text/xml\");var b=new XSLTProcessor();b.importStylesheet(f);var a=b.transformToFragment(h,document);var d=new XMLSerializer();return d.serializeToString(a)}catch(g){console.log(\"error serializing \"+g);return\"\"}},isStencilSetExtensionLoaded:function(a){return this.facade.getStencilSets().values().any(function(b){return b.extensions().keys().any(function(c){return c==a}.bind(this))}.bind(this))},doLayout:function(a){if(this.facade.raiseEvent){this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_LAYOUT,shapes:a})}else{this.facade.handleEvents({type:ORYX.CONFIG.EVENT_LAYOUT,shapes:a})}},layoutEdges:function(b,a,d){if(!this.facade.isExecutingCommands()){return}var c=ORYX.Core.Command.extend({construct:function(f,h,k,g){this.edges=f;this.node=h;this.plugin=g;this.offset=k;var e=h.absoluteXY();this.ulo={x:e.x-k.x,y:e.y-k.y}},execute:function(){if(this.changes){this.executeAgain();return}else{this.changes=[];this.edges.each(function(e){this.changes.push({edge:e,oldDockerPositions:e.dockers.map(function(f){return f.bounds.center()})})}.bind(this))}this.edges.findAll(function(e){return e.dockers.length>2}.bind(this)).each(function(g){if(g.dockers.first().getDockedShape()===this.node){var f=g.dockers[1];if(this.align(f.bounds,g.dockers.first())){f.update()}}else{if(g.dockers.last().getDockedShape()===this.node){var e=g.dockers[g.dockers.length-2];if(this.align(e.bounds,g.dockers.last())){e.update()}}}g._update(true);g.removeUnusedDockers();if(this.isBendPointIncluded(g)){this.plugin.doLayout(g);return}}.bind(this));this.edges.each(function(e){if(e.dockers.length==2){var g=e.dockers.first().getAbsoluteReferencePoint()||e.dockers.first().bounds.center();var f=e.dockers.last().getAbsoluteReferencePoint()||e.dockers.first().bounds.center();if(Math.abs(-Math.abs(g.x-f.x)+Math.abs(this.offset.x))<2||Math.abs(-Math.abs(g.y-f.y)+Math.abs(this.offset.y))<2){this.plugin.doLayout(e)}}}.bind(this));this.edges.each(function(f,e){this.changes[e].dockerPositions=f.dockers.map(function(g){return g.bounds.center()})}.bind(this))},align:function(k,f){var h=f.getAbsoluteReferencePoint()||f.bounds.center();var l=k.center().x-h.x;var g=k.center().y-h.y;if(Math.abs(-Math.abs(l)+Math.abs(this.offset.x))<3&&this.offset.xs===undefined){k.moveBy({x:-l,y:0})}if(Math.abs(-Math.abs(g)+Math.abs(this.offset.y))<3&&this.offset.ys===undefined){k.moveBy({y:-g,x:0})}if(this.offset.xs!==undefined||this.offset.ys!==undefined){var e=f.getDockedShape().absoluteXY();l=k.center().x-(e.x+((h.x-e.x)/this.offset.xs));g=k.center().y-(e.y+((h.y-e.y)/this.offset.ys));if(Math.abs(-Math.abs(l)+Math.abs(this.offset.x))<3){k.moveBy({x:-(k.center().x-h.x),y:0})}if(Math.abs(-Math.abs(g)+Math.abs(this.offset.y))<3){k.moveBy({y:-(k.center().y-h.y),x:0})}}},isBendPointIncluded:function(e){var f=e.dockers.first().getDockedShape();var g=e.dockers.last().getDockedShape();if(f){f=f.absoluteBounds();f.widen(5)}if(g){g=g.absoluteBounds();g.widen(20)}return e.dockers.any(function(k,h){var l=k.bounds.center();return h!=0&&h!=e.dockers.length-1&&((f&&f.isIncluded(l))||(g&&g.isIncluded(l)))})},removeAllDocker:function(e){e.dockers.slice(1,e.dockers.length-1).each(function(f){e.removeDocker(f)})},executeAgain:function(){this.changes.each(function(e){this.removeAllDocker(e.edge);e.dockerPositions.each(function(h,f){if(f==0||f==e.dockerPositions.length-1){return}var g=e.edge.createDocker(undefined,h);g.bounds.centerMoveTo(h);g.update()}.bind(this));e.edge._update(true)}.bind(this))},rollback:function(){this.changes.each(function(e){this.removeAllDocker(e.edge);e.oldDockerPositions.each(function(h,f){if(f==0||f==e.oldDockerPositions.length-1){return}var g=e.edge.createDocker(undefined,h);g.bounds.centerMoveTo(h);g.update()}.bind(this));e.edge._update(true)}.bind(this))}});this.facade.executeCommands([new c(a,b,d,this)])}});if(!ORYX){var ORYX={}}if(!ORYX.Plugins){ORYX.Plugins={}}ORYX.Plugins.AbstractLayouter=ORYX.Plugins.AbstractPlugin.extend({layouted:[],construct:function(a){arguments.callee.$.construct.apply(this,arguments);this.facade.registerOnEvent(ORYX.CONFIG.EVENT_LAYOUT,this._initLayout.bind(this))},isIncludedInLayout:function(a){if(!(this.layouted instanceof Array)){this.layouted=[this.layouted].compact()}if(this.layouted.length<=0){return true}return this.layouted.any(function(b){if(typeof b==\"string\"){return a.getStencil().id().include(b)}else{return a instanceof b}})},_initLayout:function(c){var b=[c.shapes].flatten().compact();var a=b.findAll(function(d){return this.isIncludedInLayout(d)}.bind(this));if(a.length>0){this.layout(a)}},layout:function(a){throw new Error(\"Layouter has to implement the layout function.\")}});if(!ORYX.Plugins){ORYX.Plugins=new Object()}ORYX.Plugins.Edit=Clazz.extend({construct:function(a){this.facade=a;this.clipboard=new ORYX.Plugins.Edit.ClipBoard();this.facade.offer({name:ORYX.I18N.Edit.cut,description:ORYX.I18N.Edit.cutDesc,icon:ORYX.PATH+\"images/cut.png\",keyCodes:[{metaKeys:[ORYX.CONFIG.META_KEY_META_CTRL],keyCode:88,keyAction:ORYX.CONFIG.KEY_ACTION_DOWN}],functionality:this.callEdit.bind(this,this.editCut),group:ORYX.I18N.Edit.group,index:1,minShape:1});this.facade.offer({name:ORYX.I18N.Edit.copy,description:ORYX.I18N.Edit.copyDesc,icon:ORYX.PATH+\"images/page_copy.png\",keyCodes:[{metaKeys:[ORYX.CONFIG.META_KEY_META_CTRL],keyCode:67,keyAction:ORYX.CONFIG.KEY_ACTION_DOWN}],functionality:this.callEdit.bind(this,this.editCopy,[true,false]),group:ORYX.I18N.Edit.group,index:2,minShape:1});this.facade.offer({name:ORYX.I18N.Edit.paste,description:ORYX.I18N.Edit.pasteDesc,icon:ORYX.PATH+\"images/page_paste.png\",keyCodes:[{metaKeys:[ORYX.CONFIG.META_KEY_META_CTRL],keyCode:86,keyAction:ORYX.CONFIG.KEY_ACTION_DOWN}],functionality:this.callEdit.bind(this,this.editPaste),isEnabled:this.clipboard.isOccupied.bind(this.clipboard),group:ORYX.I18N.Edit.group,index:3,minShape:0,maxShape:0});this.facade.offer({name:ORYX.I18N.Edit.del,description:ORYX.I18N.Edit.delDesc,icon:ORYX.PATH+\"images/cross.png\",keyCodes:[{metaKeys:[ORYX.CONFIG.META_KEY_META_CTRL],keyCode:8,keyAction:ORYX.CONFIG.KEY_ACTION_DOWN},{keyCode:46,keyAction:ORYX.CONFIG.KEY_ACTION_DOWN}],functionality:this.callEdit.bind(this,this.editDelete),group:ORYX.I18N.Edit.group,index:4,minShape:1})},callEdit:function(b,a){window.setTimeout(function(){b.apply(this,(a instanceof Array?a:[]))}.bind(this),1)},handleMouseDown:function(a){if(this._controlPressed){this._controlPressed=false;this.editCopy();this.editPaste();a.forceExecution=true;this.facade.raiseEvent(a,this.clipboard.shapesAsJson)}},getAllShapesToConsider:function(b){var a=[];var c=[];b.each(function(e){isChildShapeOfAnother=b.any(function(g){return g.hasChildShape(e)});if(isChildShapeOfAnother){return}a.push(e);if(e instanceof ORYX.Core.Node){var f=e.getOutgoingNodes();f=f.findAll(function(g){return !b.include(g)});a=a.concat(f)}c=c.concat(e.getChildShapes(true))}.bind(this));var d=this.facade.getCanvas().getChildEdges().select(function(e){if(a.include(e)){return false}if(e.getAllDockedShapes().size()===0){return false}return e.getAllDockedShapes().all(function(f){return f instanceof ORYX.Core.Edge||c.include(f)})});a=a.concat(d);return a},editCut:function(){this.editCopy(false,true);this.editDelete(true);return false},editCopy:function(c,a){var b=this.facade.getSelection();if(b.length==0){return}this.clipboard.refresh(b,this.getAllShapesToConsider(b),this.facade.getCanvas().getStencil().stencilSet().namespace(),a);if(c){this.facade.updateSelection()}},editPaste:function(){var b={childShapes:this.clipboard.shapesAsJson,stencilset:{namespace:this.clipboard.SSnamespace}};jQuery.extend(b,ORYX.Core.AbstractShape.JSONHelper);var a=b.getChildShapes(true).pluck(\"resourceId\");var c={};b.eachChild(function(d,e){d.outgoing=d.outgoing.select(function(f){return a.include(f.resourceId)});d.outgoing.each(function(f){if(!c[f.resourceId]){c[f.resourceId]=[]}c[f.resourceId].push(d)});return d}.bind(this),true,true);b.eachChild(function(d,e){if(d.target&&!(a.include(d.target.resourceId))){d.target=undefined;d.targetRemoved=true}if(d.dockers&&d.dockers.length>=1&&d.dockers[0].getDocker&&((d.dockers[0].getDocker().getDockedShape()&&!a.include(d.dockers[0].getDocker().getDockedShape().resourceId))||!d.getShape().dockers[0].getDockedShape()&&!c[d.resourceId])){d.sourceRemoved=true}return d}.bind(this),true,true);b.eachChild(function(d,e){if(this.clipboard.useOffset){d.bounds={lowerRight:{x:d.bounds.lowerRight.x+ORYX.CONFIG.COPY_MOVE_OFFSET,y:d.bounds.lowerRight.y+ORYX.CONFIG.COPY_MOVE_OFFSET},upperLeft:{x:d.bounds.upperLeft.x+ORYX.CONFIG.COPY_MOVE_OFFSET,y:d.bounds.upperLeft.y+ORYX.CONFIG.COPY_MOVE_OFFSET}}}if(d.dockers){d.dockers=d.dockers.map(function(g,f){if((d.targetRemoved===true&&f==d.dockers.length-1&&g.getDocker)||(d.sourceRemoved===true&&f==0&&g.getDocker)){g=g.getDocker().bounds.center()}if((f==0&&g.getDocker instanceof Function&&d.sourceRemoved!==true&&(g.getDocker().getDockedShape()||((c[d.resourceId]||[]).length>0&&(!(d.getShape() instanceof ORYX.Core.Node)||c[d.resourceId][0].getShape() instanceof ORYX.Core.Node))))||(f==d.dockers.length-1&&g.getDocker instanceof Function&&d.targetRemoved!==true&&(g.getDocker().getDockedShape()||d.target))){return{x:g.x,y:g.y,getDocker:g.getDocker}}else{if(this.clipboard.useOffset){return{x:g.x+ORYX.CONFIG.COPY_MOVE_OFFSET,y:g.y+ORYX.CONFIG.COPY_MOVE_OFFSET,getDocker:g.getDocker}}else{return{x:g.x,y:g.y,getDocker:g.getDocker}}}}.bind(this))}else{if(d.getShape() instanceof ORYX.Core.Node&&d.dockers&&d.dockers.length>0&&(!d.dockers.first().getDocker||d.sourceRemoved===true||!(d.dockers.first().getDocker().getDockedShape()||c[d.resourceId]))){d.dockers=d.dockers.map(function(g,f){if((d.sourceRemoved===true&&f==0&&g.getDocker)){g=g.getDocker().bounds.center()}if(this.clipboard.useOffset){return{x:g.x+ORYX.CONFIG.COPY_MOVE_OFFSET,y:g.y+ORYX.CONFIG.COPY_MOVE_OFFSET,getDocker:g.getDocker}}else{return{x:g.x,y:g.y,getDocker:g.getDocker}}}.bind(this))}}return d}.bind(this),false,true);this.clipboard.useOffset=true;this.facade.importJSON(b)},editDelete:function(){var a=this.facade.getSelection();var b=new ORYX.Plugins.Edit.ClipBoard();b.refresh(a,this.getAllShapesToConsider(a));var c=new ORYX.Plugins.Edit.DeleteCommand(b,this.facade);this.facade.executeCommands([c])}});ORYX.Plugins.Edit.ClipBoard=Clazz.extend({construct:function(){this.shapesAsJson=[];this.selection=[];this.SSnamespace=\"\";this.useOffset=true},isOccupied:function(){return this.shapesAsJson.length>0},refresh:function(d,b,c,a){this.selection=d;this.SSnamespace=c;this.outgoings={};this.parents={};this.targets={};this.useOffset=a!==true;this.shapesAsJson=b.map(function(e){var f=e.toJSON();f.parent={resourceId:e.getParentShape().resourceId};f.parentIndex=e.getParentShape().getChildShapes().indexOf(e);return f})}});ORYX.Plugins.Edit.DeleteCommand=ORYX.Core.Command.extend({construct:function(b,a){this.clipboard=b;this.shapesAsJson=b.shapesAsJson;this.facade=a;this.dockers=this.shapesAsJson.map(function(g){var e=g.getShape();var f=e.getIncomingShapes().map(function(h){return h.getDockers().last()});var d=e.getOutgoingShapes().map(function(h){return h.getDockers().first()});var c=e.getDockers().concat(f,d).compact().map(function(h){return{object:h,referencePoint:h.referencePoint,dockedShape:h.getDockedShape()}});return c}).flatten()},execute:function(){this.shapesAsJson.each(function(a){this.facade.deleteShape(a.getShape())}.bind(this));this.facade.setSelection([]);this.facade.getCanvas().update();this.facade.updateSelection()},rollback:function(){this.shapesAsJson.each(function(c){var a=c.getShape();var b=this.facade.getCanvas().getChildShapeByResourceId(c.parent.resourceId)||this.facade.getCanvas();b.add(a,a.parentIndex)}.bind(this));this.dockers.each(function(a){a.object.setDockedShape(a.dockedShape);a.object.setReferencePoint(a.referencePoint)}.bind(this));this.facade.setSelection(this.selectedShapes);this.facade.getCanvas().update();this.facade.updateSelection()}});if(!ORYX.Plugins){ORYX.Plugins=new Object()}ORYX.Plugins.View={facade:undefined,construct:function(b,a){this.facade=b;this.zoomLevel=1;this.maxFitToScreenLevel=1.5;this.minZoomLevel=0.1;this.maxZoomLevel=2.5;this.diff=5;if(a!==undefined&&a!==null){a.properties.each(function(c){if(c.zoomLevel){this.zoomLevel=Number(1)}if(c.maxFitToScreenLevel){this.maxFitToScreenLevel=Number(c.maxFitToScreenLevel)}if(c.minZoomLevel){this.minZoomLevel=Number(c.minZoomLevel)}if(c.maxZoomLevel){this.maxZoomLevel=Number(c.maxZoomLevel)}}.bind(this))}this.facade.offer({name:ORYX.I18N.View.zoomIn,functionality:this.zoom.bind(this,[1+ORYX.CONFIG.ZOOM_OFFSET]),group:ORYX.I18N.View.group,icon:ORYX.PATH+\"images/magnifier_zoom_in.png\",description:ORYX.I18N.View.zoomInDesc,index:1,minShape:0,maxShape:0,isEnabled:function(){return this.zoomLevel<this.maxZoomLevel}.bind(this)});this.facade.offer({name:ORYX.I18N.View.zoomOut,functionality:this.zoom.bind(this,[1-ORYX.CONFIG.ZOOM_OFFSET]),group:ORYX.I18N.View.group,icon:ORYX.PATH+\"images/magnifier_zoom_out.png\",description:ORYX.I18N.View.zoomOutDesc,index:2,minShape:0,maxShape:0,isEnabled:function(){return this._checkSize()}.bind(this)});this.facade.offer({name:ORYX.I18N.View.zoomStandard,functionality:this.setAFixZoomLevel.bind(this,1),group:ORYX.I18N.View.group,icon:ORYX.PATH+\"images/zoom_standard.png\",cls:\"icon-large\",description:ORYX.I18N.View.zoomStandardDesc,index:3,minShape:0,maxShape:0,isEnabled:function(){return this.zoomLevel!=1}.bind(this)});this.facade.offer({name:ORYX.I18N.View.zoomFitToModel,functionality:this.zoomFitToModel.bind(this),group:ORYX.I18N.View.group,icon:ORYX.PATH+\"images/image.png\",description:ORYX.I18N.View.zoomFitToModelDesc,index:4,minShape:0,maxShape:0})},setAFixZoomLevel:function(a){this.zoomLevel=a;this._checkZoomLevelRange();this.zoom(1)},zoom:function(d){this.zoomLevel*=d;var h=this.facade.getCanvas().getHTMLContainer().parentNode.parentNode;var c=this.facade.getCanvas();var g=c.bounds.width()*this.zoomLevel;var a=c.bounds.height()*this.zoomLevel;var f=(c.node.parentNode.parentNode.parentNode.offsetHeight-a)/2;f=f>20?f-20:0;c.node.parentNode.parentNode.style.marginTop=f+\"px\";f+=5;c.getHTMLContainer().style.top=f+\"px\";var b=h.scrollTop-Math.round((c.getHTMLContainer().parentNode.getHeight()-a)/2)+this.diff;var e=h.scrollLeft-Math.round((c.getHTMLContainer().parentNode.getWidth()-g)/2)+this.diff;c.setSize({width:g,height:a},true);c.node.setAttributeNS(null,\"transform\",\"scale(\"+this.zoomLevel+\")\");this.facade.updateSelection();h.scrollTop=b;h.scrollLeft=e;c.zoomLevel=this.zoomLevel},zoomFitToModel:function(){var h=this.facade.getCanvas().getHTMLContainer().parentNode.parentNode;var b=h.getHeight()-30;var d=h.getWidth()-30;var c=this.facade.getCanvas().getChildShapes();if(!c||c.length<1){return false}var g=c[0].absoluteBounds().clone();c.each(function(k){g.include(k.absoluteBounds().clone())});var f=d/g.width();var a=b/g.height();var e=a<f?a:f;if(e>this.maxFitToScreenLevel){e=this.maxFitToScreenLevel}this.setAFixZoomLevel(e);h.scrollTop=Math.round(g.upperLeft().y*this.zoomLevel)-5;h.scrollLeft=Math.round(g.upperLeft().x*this.zoomLevel)-5},_checkSize:function(){var a=this.facade.getCanvas().getHTMLContainer().parentNode;var b=Math.min((a.parentNode.getWidth()/a.getWidth()),(a.parentNode.getHeight()/a.getHeight()));return 1.05>b},_checkZoomLevelRange:function(){if(this.zoomLevel<this.minZoomLevel){this.zoomLevel=this.minZoomLevel}if(this.zoomLevel>this.maxZoomLevel){this.zoomLevel=this.maxZoomLevel}}};ORYX.Plugins.View=Clazz.extend(ORYX.Plugins.View);if(!Signavio){var Signavio={}}if(!Signavio.Core){Signavio.Core={}}Signavio.Core.Version=\"1.0\";if(!Signavio){var Signavio=new Object()}if(!Signavio.Plugins){Signavio.Plugins=new Object()}if(!Signavio.Plugins.Utils){Signavio.Plugins.Utils=new Object()}if(!Signavio.Helper){Signavio.Helper=new Object()}new function(){ORYX.Editor.provideId=function(){var b=[],c=\"0123456789ABCDEF\";for(var a=0;a<36;a++){b[a]=Math.floor(Math.random()*16)}b[14]=4;b[19]=(b[19]&3)|8;for(var a=0;a<36;a++){b[a]=c[b[a]]}b[8]=b[13]=b[18]=b[23]=\"-\";return\"sid-\"+b.join(\"\")}}();if(!ORYX.Plugins){ORYX.Plugins=new Object()}ORYX.Plugins.Loading={construct:function(a){this.facade=a;this.node=ORYX.Editor.graft(\"http://www.w3.org/1999/xhtml\",this.facade.getCanvas().getHTMLContainer().parentNode,[\"div\",{\"class\":\"LoadingIndicator\"},\"\"]);this.facade.registerOnEvent(ORYX.CONFIG.EVENT_LOADING_ENABLE,this.enableLoading.bind(this));this.facade.registerOnEvent(ORYX.CONFIG.EVENT_LOADING_DISABLE,this.disableLoading.bind(this));this.facade.registerOnEvent(ORYX.CONFIG.EVENT_LOADING_STATUS,this.showStatus.bind(this));this.disableLoading()},enableLoading:function(a){if(a.text){this.node.innerHTML=a.text+\"...\"}else{this.node.innerHTML=ORYX.I18N.Loading.waiting}this.node.removeClassName(\"StatusIndicator\");this.node.addClassName(\"LoadingIndicator\");this.node.style.display=\"block\";var b=this.facade.getCanvas().rootNode.parentNode.parentNode.parentNode.parentNode;this.node.style.top=b.offsetTop+\"px\";this.node.style.left=b.offsetLeft+\"px\"},disableLoading:function(){this.node.style.display=\"none\"},showStatus:function(a){if(a.text){this.node.innerHTML=a.text;this.node.addClassName(\"StatusIndicator\");this.node.removeClassName(\"LoadingIndicator\");this.node.style.display=\"block\";var c=this.facade.getCanvas().rootNode.parentNode.parentNode.parentNode.parentNode;this.node.style.top=c.offsetTop+\"px\";this.node.style.left=c.offsetLeft+\"px\";var b=a.timeout?a.timeout:2000;window.setTimeout((function(){this.disableLoading()}).bind(this),b)}}};ORYX.Plugins.Loading=Clazz.extend(ORYX.Plugins.Loading);if(!ORYX.Plugins){ORYX.Plugins=new Object()}ORYX.Plugins.CanvasResize=Clazz.extend({construct:function(a){this.facade=a;new ORYX.Plugins.CanvasResizeButton(this.facade.getCanvas(),\"N\",this.resize.bind(this));new ORYX.Plugins.CanvasResizeButton(this.facade.getCanvas(),\"W\",this.resize.bind(this));new ORYX.Plugins.CanvasResizeButton(this.facade.getCanvas(),\"E\",this.resize.bind(this));new ORYX.Plugins.CanvasResizeButton(this.facade.getCanvas(),\"S\",this.resize.bind(this));window.setTimeout(function(){jQuery(window).trigger(\"resize\")})},resize:function(a,c){resizeCanvas=function(l,m,o){var f=o.getCanvas();var n=f.bounds;var h=o.getCanvas().getHTMLContainer().parentNode.parentNode;if(l==\"E\"||l==\"W\"){f.setSize({width:(n.width()+m)*f.zoomLevel,height:(n.height())*f.zoomLevel})}else{if(l==\"S\"||l==\"N\"){f.setSize({width:(n.width())*f.zoomLevel,height:(n.height()+m)*f.zoomLevel})}}if(l==\"N\"||l==\"W\"){var g=l==\"N\"?{x:0,y:m}:{x:m,y:0};f.getChildNodes(false,function(q){q.bounds.moveBy(g)});var k=f.getChildEdges().findAll(function(q){return q.getAllDockedShapes().length>0});var p=k.collect(function(q){return q.dockers.findAll(function(r){return !r.getDockedShape()})}).flatten();p.each(function(q){q.bounds.moveBy(g)})}else{if(l==\"S\"){h.scrollTop+=m}else{if(l==\"E\"){h.scrollLeft+=m}}}jQuery(window).trigger(\"resize\");f.update();o.updateSelection()};var b=ORYX.Core.Command.extend({construct:function(f,h,g){this.position=f;this.extentionSize=h;this.facade=g},execute:function(){resizeCanvas(this.position,this.extentionSize,this.facade)},rollback:function(){resizeCanvas(this.position,-this.extentionSize,this.facade)},update:function(){}});var d=ORYX.CONFIG.CANVAS_RESIZE_INTERVAL;if(c){d=-d}var e=new b(a,d,this.facade);this.facade.executeCommands([e])}});ORYX.Plugins.CanvasResizeButton=Clazz.extend({construct:function(b,t,g){this.canvas=b;var k=b.getHTMLContainer().parentNode;window.myParent=k;var s=jQuery(\"#canvasSection\")[0];var d=s;var e=jQuery(\"#canvasSection\").find(\".ORYX_Editor\")[0];var f=e.children[0];var a=\"glyphicon glyphicon-chevron-\";var p=\"glyphicon glyphicon-chevron-\";if(t==\"N\"){a+=\"up\";p+=\"down\"}else{if(t==\"S\"){a+=\"down\";p+=\"up\"}else{if(t==\"E\"){a+=\"right\";p+=\"left\"}else{if(t==\"W\"){a+=\"left\";p+=\"right\"}}}}var l=\"canvas-shrink-\"+t;var r=\"canvas-grow-\"+t;var c=ORYX.Editor.graft(\"http://www.w3.org/1999/xhtml\",k,[\"div\",{\"class\":\"canvas_resize_indicator canvas_resize_indicator_grow \"+t,id:l,title:ORYX.I18N.RESIZE.tipGrow+ORYX.I18N.RESIZE[t]},[\"i\",{\"class\":a}]]);var h=ORYX.Editor.graft(\"http://www.w3.org/1999/xhtml\",k,[\"div\",{\"class\":\"canvas_resize_indicator canvas_resize_indicator_shrink \"+t,id:r,title:ORYX.I18N.RESIZE.tipGrow+ORYX.I18N.RESIZE[t]},[\"i\",{\"class\":p}]]);var m=60;var q=function(w){var x=w.target.id.indexOf(\"canvas-shrink\")!=-1||w.target.id.indexOf(\"canvas-grow\")!=-1||w.target.parentNode.id.indexOf(\"canvas-shrink\")!=-1||w.target.parentNode.id.indexOf(\"canvas-grow\")!=-1;if(x){if(w.target.id==l||w.target.id==r||w.target.parentNode.id==l||w.target.parentNode.id==r){return true}else{return false}}if(w.target!=k&&w.target!=d&&w.target!=d.firstChild&&w.target!=f&&w.target!=d){return false}var z=w.offsetX!==undefined?w.offsetX:w.layerX;var y=w.offsetY!==undefined?w.offsetY:w.layerY;var u=0;if(e.clientWidth<s.clientWidth){var v=s.clientWidth-e.clientWidth;u=v/2}y=y-s.scrollTop;z=z-s.scrollLeft;if(t==\"N\"){return y<m}else{if(t==\"W\"){return z<m+u}else{if(t==\"E\"){return s.clientWidth-z<m+u}else{if(t==\"S\"){return s.clientHeight-y<m}}}}return false};var n=(function(){c.show();var u=b.bounds.width();var v=b.bounds.height();if(t==\"N\"&&(v-ORYX.CONFIG.CANVAS_RESIZE_INTERVAL>ORYX.CONFIG.CANVAS_MIN_HEIGHT)){h.show()}else{if(t==\"E\"&&(u-ORYX.CONFIG.CANVAS_RESIZE_INTERVAL>ORYX.CONFIG.CANVAS_MIN_WIDTH)){h.show()}else{if(t==\"S\"&&(v-ORYX.CONFIG.CANVAS_RESIZE_INTERVAL>ORYX.CONFIG.CANVAS_MIN_HEIGHT)){h.show()}else{if(t==\"W\"&&(u-ORYX.CONFIG.CANVAS_RESIZE_INTERVAL>ORYX.CONFIG.CANVAS_MIN_WIDTH)){h.show()}else{h.hide()}}}}}).bind(this);var o=function(){c.hide();h.hide()};k.parentNode.addEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE,function(u){if(q(u)){n()}else{o()}},false);c.addEventListener(ORYX.CONFIG.EVENT_MOUSEOVER,function(u){n()},true);h.addEventListener(ORYX.CONFIG.EVENT_MOUSEOVER,function(u){n()},true);k.parentNode.addEventListener(ORYX.CONFIG.EVENT_MOUSEOUT,function(u){o()},true);o();c.addEventListener(\"click\",function(){g(t);n()},true);h.addEventListener(\"click\",function(){g(t,true);n()},true)}});if(!ORYX.Plugins){ORYX.Plugins=new Object()}ORYX.Plugins.RenameShapes=Clazz.extend({facade:undefined,construct:function(a){this.facade=a;this.facade.registerOnEvent(ORYX.CONFIG.EVENT_CANVAS_SCROLL,this.hideField.bind(this));this.facade.registerOnEvent(ORYX.CONFIG.EVENT_DBLCLICK,this.actOnDBLClick.bind(this));this.facade.offer({keyCodes:[{keyCode:113,keyAction:ORYX.CONFIG.KEY_ACTION_DOWN}],functionality:this.renamePerF2.bind(this)});document.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEDOWN,this.hide.bind(this),true)},renamePerF2:function(){var a=this.facade.getSelection();this.actOnDBLClick(undefined,a.first())},actOnDBLClick:function(p,l){if(!(l instanceof ORYX.Core.Shape)){return}this.destroy();var m=l.getStencil().properties().findAll(function(t){return(t.refToView()&&t.refToView().length>0&&t.directlyEditable())});m=m.findAll(function(t){return !t.readonly()&&(t.type()==ORYX.CONFIG.TYPE_STRING||t.type()==ORYX.CONFIG.TYPE_EXPRESSION||t.type()==ORYX.CONFIG.TYPE_DATASOURCE)});var n=m.collect(function(t){return t.refToView()}).flatten().compact();var h=l.getLabels().findAll(function(t){return n.any(function(u){return t.id.endsWith(u)})});if(h.length==0){return}var k=h.length<=1?h[0]:null;if(!k){k=h.find(function(t){return t.node==p.target||t.node==p.target.parentNode});if(!k){var q=this.facade.eventCoordinates(p);var b=1;if(!isNaN(screen.logicalXDPI)&&!isNaN(screen.systemXDPI)){var e=navigator.userAgent;if(e.indexOf(\"MSIE\")>=0){var r=Math.round((screen.deviceXDPI/screen.logicalXDPI)*100);if(r!==100){b=r/100}}}if(b!==1){q.x=q.x/b;q.y=q.y/b}q.y+=$(\"editor-header\").clientHeight-$(\"canvasSection\").scrollTop-5;if(KISBPM.HEADER_CONFIG.showAppTitle==false){q.y+=61}q.x-=$(\"canvasSection\").scrollLeft;var s=this.facade.getCanvas().rootNode.lastChild.getScreenCTM();q.x*=s.a;q.y*=s.d;var o=h.collect(function(v){var u=this.getCenterPosition(v.node);var t=Math.sqrt(Math.pow(u.x-q.x,2)+Math.pow(u.y-q.y,2));return{diff:t,label:v}}.bind(this));o.sort(function(u,t){return u.diff>t.diff});k=o[0].label}}var d=m.find(function(t){return t.refToView().any(function(u){return k.id==l.id+u})});var f=Math.min(Math.max(100,l.bounds.width()),200);var a=this.getCenterPosition(k.node,l);a.x-=(f/2);var c=d.prefix()+\"-\"+d.id();var g=document.createElement(\"textarea\");g.id=\"shapeTextInput\";g.style.position=\"absolute\";g.style.width=f+\"px\";g.style.left=(a.x<10)?10:a.x+\"px\";g.style.top=(a.y-15)+\"px\";g.className=\"x-form-textarea x-form-field x_form_text_set_absolute\";g.value=l.properties[c];this.oldValueText=l.properties[c];document.getElementById(\"canvasSection\").appendChild(g);this.shownTextField=g;this.updateValueFunction=function(x,u){var w=l;var v=this.facade;if(u!=x){var t=ORYX.Core.Command.extend({construct:function(){this.el=w;this.propId=c;this.oldValue=u;this.newValue=x;this.facade=v},execute:function(){this.el.setProperty(this.propId,this.newValue);this.facade.setSelection([this.el]);this.facade.getCanvas().update();this.facade.updateSelection()},rollback:function(){this.el.setProperty(this.propId,this.oldValue);this.facade.setSelection([this.el]);this.facade.getCanvas().update();this.facade.updateSelection()}});var y=new t();this.facade.executeCommands([y])}}.bind(this);jQuery(\"#shapeTextInput\").focus();jQuery(\"#shapeTextInput\").autogrow();this.facade.disableEvent(ORYX.CONFIG.EVENT_KEYDOWN)},getCenterPosition:function(f,h){if(!f){return{x:0,y:0}}var e=this.facade.getCanvas().node.getScreenCTM();var b=h.bounds.upperLeft();var p=true;var n=h;while(p){if(n.getParentShape().getStencil().idWithoutNs()===\"BPMNDiagram\"){p=false}else{var l=n.getParentShape().bounds.upperLeft();b.x+=l.x;b.y+=l.y;n=n.getParentShape()}}var c=h.bounds.midPoint();c.x+=b.x+e.e;c.y+=b.y+e.f;c.x*=e.a;c.y*=e.d;var a=1;if(!isNaN(screen.logicalXDPI)&&!isNaN(screen.systemXDPI)){var d=navigator.userAgent;if(d.indexOf(\"MSIE\")>=0){var r=Math.round((screen.deviceXDPI/screen.logicalXDPI)*100);if(r!==100){a=r/100}}}if(a===1){c.y=c.y-jQuery(\"#canvasSection\").offset().top+5;c.x-=jQuery(\"#canvasSection\").offset().left}else{var m=jQuery(\"#canvasSection\").offset().left;var o=jQuery(\"#canvasSection\").scrollLeft();var k=jQuery(\"#canvasSection\").scrollTop();var g=e.e-(m*a);var q=0;if(g>10){q=(g/a)-g}c.y=c.y-(jQuery(\"#canvasSection\").offset().top*a)+5+((k*a)-k);c.x=c.x-(m*a)+q+((o*a)-o)}return c},hide:function(b){if(this.shownTextField&&(!b||b.target!==this.shownTextField)){var a=this.shownTextField.value;if(a!==this.oldValueText){this.updateValueFunction(a,this.oldValueText)}this.destroy()}},hideField:function(a){if(this.shownTextField){this.destroy()}},destroy:function(a){var b=jQuery(\"#shapeTextInput\");if(b){b.remove();delete this.shownTextField;this.facade.enableEvent(ORYX.CONFIG.EVENT_KEYDOWN)}}});if(!ORYX.Plugins){ORYX.Plugins=new Object()}ORYX.Plugins.ProcessLink=Clazz.extend({facade:undefined,construct:function(a){this.facade=a;this.facade.registerOnEvent(ORYX.CONFIG.EVENT_PROPERTY_CHANGED,this.propertyChanged.bind(this))},propertyChanged:function(a,b){if(a.name!==\"oryx-refuri\"||!b instanceof ORYX.Core.Node){return}if(a.value&&a.value.length>0&&a.value!=\"undefined\"){this.show(b,a.value)}else{this.hide(b)}},show:function(a,b){var c=ORYX.Editor.graft(\"http://www.w3.org/2000/svg\",null,[\"a\",{target:\"_blank\"},[\"path\",{\"stroke-width\":1,stroke:\"#00DD00\",fill:\"#00AA00\",d:\"M3,3 l0,-2.5 l7.5,0 l0,-2.5 l7.5,4.5 l-7.5,3.5 l0,-2.5 l-8,0\",\"line-captions\":\"round\"}]]);var c=ORYX.Editor.graft(\"http://www.w3.org/2000/svg\",null,[\"a\",{target:\"_blank\"},[\"path\",{style:\"fill:#92BFFC;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.72\",d:\"M0 1.44 L0 15.05 L11.91 15.05 L11.91 5.98 L7.37 1.44 L0 1.44 Z\"}],[\"path\",{style:\"stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.72;fill:none;\",transform:\"translate(7.5, -8.5)\",d:\"M0 10.51 L0 15.05 L4.54 15.05\"}],[\"path\",{style:\"fill:#f28226;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.72\",transform:\"translate(-3, -1)\",d:\"M0 8.81 L0 13.06 L5.95 13.06 L5.95 15.05 A50.2313 50.2313 -175.57 0 0 10.77 11.08 A49.9128 49.9128 -1.28 0 0 5.95 6.54 L5.95 8.81 L0 8.81 Z\"}],]);c.setAttributeNS(\"http://www.w3.org/1999/xlink\",\"xlink:href\",b);this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_OVERLAY_SHOW,id:\"arissupport.urlref_\"+a.id,shapes:[a],node:c,nodePosition:\"SE\"})},hide:function(a){this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_OVERLAY_HIDE,id:\"arissupport.urlref_\"+a.id})}});Array.prototype.insertFrom=function(e,d){d=Math.max(0,d);e=Math.min(Math.max(0,e),this.length-1);var b=this[e];var a=this.without(b);var c=a.slice(0,d);c.push(b);if(a.length>d){c=c.concat(a.slice(d))}return c};if(!ORYX.Plugins){ORYX.Plugins=new Object()}ORYX.Plugins.Arrangement=ORYX.Plugins.AbstractPlugin.extend({facade:undefined,construct:function(a){this.facade=a;this.facade.offer({name:ORYX.I18N.Arrangement.am,functionality:this.alignShapes.bind(this,[ORYX.CONFIG.EDITOR_ALIGN_MIDDLE]),group:ORYX.I18N.Arrangement.groupA,icon:ORYX.PATH+\"images/shape_align_middle.png\",description:ORYX.I18N.Arrangement.amDesc,index:1,minShape:2});this.facade.offer({name:ORYX.I18N.Arrangement.ac,functionality:this.alignShapes.bind(this,[ORYX.CONFIG.EDITOR_ALIGN_CENTER]),group:ORYX.I18N.Arrangement.groupA,icon:ORYX.PATH+\"images/shape_align_center.png\",description:ORYX.I18N.Arrangement.acDesc,index:2,minShape:2});this.facade.offer({name:ORYX.I18N.Arrangement.as,functionality:this.alignShapes.bind(this,[ORYX.CONFIG.EDITOR_ALIGN_SIZE]),group:ORYX.I18N.Arrangement.groupA,icon:ORYX.PATH+\"images/shape_align_size.png\",description:ORYX.I18N.Arrangement.asDesc,index:3,minShape:2});this.facade.registerOnEvent(ORYX.CONFIG.EVENT_ARRANGEMENT_TOP,this.setZLevel.bind(this,this.setToTop));this.facade.registerOnEvent(ORYX.CONFIG.EVENT_ARRANGEMENT_BACK,this.setZLevel.bind(this,this.setToBack));this.facade.registerOnEvent(ORYX.CONFIG.EVENT_ARRANGEMENT_FORWARD,this.setZLevel.bind(this,this.setForward));this.facade.registerOnEvent(ORYX.CONFIG.EVENT_ARRANGEMENT_BACKWARD,this.setZLevel.bind(this,this.setBackward))},onSelectionChanged:function(a){var b=this.facade.getSelection();if(b.length===1&&b[0] instanceof ORYX.Core.Edge){this.setToTop(b)}},setZLevel:function(d,b){var a=ORYX.Core.Command.extend({construct:function(g,f,e){this.callback=g;this.elements=f;this.elAndIndex=f.map(function(h){return{el:h,previous:h.parent.children[h.parent.children.indexOf(h)-1]}});this.facade=e},execute:function(){this.callback(this.elements);this.facade.setSelection(this.elements)},rollback:function(){var g=this.elAndIndex.sortBy(function(n){var o=n.el;var m=$A(o.node.parentNode.childNodes);return m.indexOf(o.node)});for(var f=0;f<g.length;f++){var h=g[f].el;var k=h.parent;var l=k.children.indexOf(h);var e=k.children.indexOf(g[f].previous);e=e||0;k.children=k.children.insertFrom(l,e);h.node.parentNode.insertBefore(h.node,h.node.parentNode.childNodes[e+1])}this.facade.setSelection(this.elements)}});var c=new a(d,this.facade.getSelection(),this.facade);if(b.excludeCommand){c.execute()}else{this.facade.executeCommands([c])}},setToTop:function(b){var a=b.sortBy(function(e,c){var d=$A(e.node.parentNode.childNodes);return d.indexOf(e.node)});a.each(function(c){var d=c.parent;if(d.children.last()===c){return}d.children=d.children.without(c);d.children.push(c);c.node.parentNode.appendChild(c.node)})},setToBack:function(b){var a=b.sortBy(function(e,c){var d=$A(e.node.parentNode.childNodes);return d.indexOf(e.node)});a=a.reverse();a.each(function(c){var d=c.parent;d.children=d.children.without(c);d.children.unshift(c);c.node.parentNode.insertBefore(c.node,c.node.parentNode.firstChild)})},setBackward:function(c){var b=c.sortBy(function(f,d){var e=$A(f.node.parentNode.childNodes);return e.indexOf(f.node)});b=b.reverse();var a=b.findAll(function(d){return !b.some(function(e){return e.node==d.node.previousSibling})});a.each(function(e){if(e.node.previousSibling===null){return}var f=e.parent;var d=f.children.indexOf(e);f.children=f.children.insertFrom(d,d-1);e.node.parentNode.insertBefore(e.node,e.node.previousSibling)})},setForward:function(c){var b=c.sortBy(function(f,d){var e=$A(f.node.parentNode.childNodes);return e.indexOf(f.node)});var a=b.findAll(function(d){return !b.some(function(e){return e.node==d.node.nextSibling})});a.each(function(f){var d=f.node.nextSibling;if(d===null){return}var e=f.parent.children.indexOf(f);var g=f.parent;g.children=g.children.insertFrom(e,e+1);f.node.parentNode.insertBefore(d,f.node)})},alignShapes:function(b){var f=this.facade.getSelection();f=this.facade.getCanvas().getShapesWithSharedParent(f);f=f.findAll(function(h){return(h instanceof ORYX.Core.Node)});f=f.findAll(function(h){var k=h.getIncomingShapes();return k.length==0||!f.include(k[0])});if(f.length<2){return}var e=f[0].absoluteBounds().clone();f.each(function(h){e.include(h.absoluteBounds().clone())});var d=0;var c=0;f.each(function(h){d=Math.max(h.bounds.width(),d);c=Math.max(h.bounds.height(),c)});var a=ORYX.Core.Command.extend({construct:function(o,n,m,l,h,k){this.elements=o;this.bounds=n;this.maxHeight=m;this.maxWidth=l;this.way=h;this.facade=k.facade;this.plugin=k;this.orgPos=[]},setBounds:function(h,l){if(!l){l={width:ORYX.CONFIG.MAXIMUM_SIZE,height:ORYX.CONFIG.MAXIMUM_SIZE}}if(!h.bounds){throw\"Bounds not definined.\"}var k={a:{x:h.bounds.upperLeft().x-(this.maxWidth-h.bounds.width())/2,y:h.bounds.upperLeft().y-(this.maxHeight-h.bounds.height())/2},b:{x:h.bounds.lowerRight().x+(this.maxWidth-h.bounds.width())/2,y:h.bounds.lowerRight().y+(this.maxHeight-h.bounds.height())/2}};if(this.maxWidth>l.width){k.a.x=h.bounds.upperLeft().x-(l.width-h.bounds.width())/2;k.b.x=h.bounds.lowerRight().x+(l.width-h.bounds.width())/2}if(this.maxHeight>l.height){k.a.y=h.bounds.upperLeft().y-(l.height-h.bounds.height())/2;k.b.y=h.bounds.lowerRight().y+(l.height-h.bounds.height())/2}h.bounds.set(k)},execute:function(){this.elements.each(function(h,k){this.orgPos[k]=h.bounds.upperLeft();var l=this.bounds.clone();var o;if(h.parent&&!(h.parent instanceof ORYX.Core.Canvas)){var n=h.parent.absoluteBounds().upperLeft();l.moveBy(-n.x,-n.y)}switch(this.way){case ORYX.CONFIG.EDITOR_ALIGN_BOTTOM:o={x:h.bounds.upperLeft().x,y:l.b.y-h.bounds.height()};break;case ORYX.CONFIG.EDITOR_ALIGN_MIDDLE:o={x:h.bounds.upperLeft().x,y:(l.a.y+l.b.y-h.bounds.height())/2};break;case ORYX.CONFIG.EDITOR_ALIGN_TOP:o={x:h.bounds.upperLeft().x,y:l.a.y};break;case ORYX.CONFIG.EDITOR_ALIGN_LEFT:o={x:l.a.x,y:h.bounds.upperLeft().y};break;case ORYX.CONFIG.EDITOR_ALIGN_CENTER:o={x:(l.a.x+l.b.x-h.bounds.width())/2,y:h.bounds.upperLeft().y};break;case ORYX.CONFIG.EDITOR_ALIGN_RIGHT:o={x:l.b.x-h.bounds.width(),y:h.bounds.upperLeft().y};break;case ORYX.CONFIG.EDITOR_ALIGN_SIZE:if(h.isResizable){this.orgPos[k]={a:h.bounds.upperLeft(),b:h.bounds.lowerRight()};this.setBounds(h,h.maximumSize)}break}if(o){var m={x:h.bounds.upperLeft().x-o.x,y:h.bounds.upperLeft().y-o.y};h.bounds.moveTo(o);this.plugin.layoutEdges(h,h.getAllDockedShapes(),m)}}.bind(this))},rollback:function(){this.elements.each(function(h,k){if(this.way==ORYX.CONFIG.EDITOR_ALIGN_SIZE){if(h.isResizable){h.bounds.set(this.orgPos[k])}}else{h.bounds.moveTo(this.orgPos[k])}}.bind(this))}});var g=new a(f,e,c,d,parseInt(b),this);this.facade.executeCommands([g])}});if(!ORYX.Plugins){ORYX.Plugins=new Object()}ORYX.Plugins.Save=Clazz.extend({facade:undefined,processURI:undefined,changeSymbol:\"*\",construct:function(a){this.facade=a;document.addEventListener(\"keydown\",function(b){if(b.ctrlKey&&b.keyCode===83){Event.stop(b)}},false);window.onbeforeunload=this.onUnLoad.bind(this);this.changeDifference=0;this.facade.registerOnEvent(ORYX.CONFIG.EVENT_UNDO_EXECUTE,function(){this.changeDifference++;this.updateTitle()}.bind(this));this.facade.registerOnEvent(ORYX.CONFIG.EVENT_EXECUTE_COMMANDS,function(){this.changeDifference++;this.updateTitle()}.bind(this));this.facade.registerOnEvent(ORYX.CONFIG.EVENT_SAVED,function(){this.changeDifference=0;this.updateTitle()}.bind(this));this.facade.registerOnEvent(ORYX.CONFIG.EVENT_UNDO_ROLLBACK,function(){this.changeDifference--;this.updateTitle()}.bind(this));this.hasChanges=this._hasChanges.bind(this)},updateTitle:function(){var a=window.document.title||document.getElementsByTagName(\"title\")[0].childNodes[0].nodeValue;if(this.changeDifference===0&&a.startsWith(this.changeSymbol)){window.document.title=a.slice(1)}else{if(this.changeDifference!==0&&!a.startsWith(this.changeSymbol)){window.document.title=this.changeSymbol+\"\"+a}}},_hasChanges:function(){return this.changeDifference!==0||(this.facade.getModelMetaData()[\"new\"]&&this.facade.getCanvas().getChildShapes().size()>0)},onUnLoad:function(){if(this._hasChanges()){return ORYX.I18N.Save.unsavedData}}});if(!ORYX.Plugins){ORYX.Plugins=new Object()}ORYX.Plugins.DragDropResize=ORYX.Plugins.AbstractPlugin.extend({construct:function(b){this.facade=b;this.currentShapes=[];this.toMoveShapes=[];this.distPoints=[];this.isResizing=false;this.dragEnable=false;this.dragIntialized=false;this.edgesMovable=true;this.offSetPosition={x:0,y:0};this.faktorXY={x:1,y:1};this.containmentParentNode;this.isAddingAllowed=false;this.isAttachingAllowed=false;this.callbackMouseMove=this.handleMouseMove.bind(this);this.callbackMouseUp=this.handleMouseUp.bind(this);var a=this.facade.getCanvas().getSvgContainer();this.selectedRect=new ORYX.Plugins.SelectedRect(a);if(ORYX.CONFIG.SHOW_GRIDLINE){this.vLine=new ORYX.Plugins.GridLine(a,ORYX.Plugins.GridLine.DIR_VERTICAL);this.hLine=new ORYX.Plugins.GridLine(a,ORYX.Plugins.GridLine.DIR_HORIZONTAL)}a=this.facade.getCanvas().getHTMLContainer();this.scrollNode=this.facade.getCanvas().rootNode.parentNode.parentNode;this.resizerSE=new ORYX.Plugins.Resizer(a,\"southeast\",this.facade);this.resizerSE.registerOnResize(this.onResize.bind(this));this.resizerSE.registerOnResizeEnd(this.onResizeEnd.bind(this));this.resizerSE.registerOnResizeStart(this.onResizeStart.bind(this));this.resizerNW=new ORYX.Plugins.Resizer(a,\"northwest\",this.facade);this.resizerNW.registerOnResize(this.onResize.bind(this));this.resizerNW.registerOnResizeEnd(this.onResizeEnd.bind(this));this.resizerNW.registerOnResizeStart(this.onResizeStart.bind(this));this.facade.registerOnEvent(ORYX.CONFIG.EVENT_MOUSEDOWN,this.handleMouseDown.bind(this))},handleMouseDown:function(d,c){if(!this.dragBounds||!this.currentShapes.member(c)||!this.toMoveShapes.length){return}this.dragEnable=true;this.dragIntialized=true;this.edgesMovable=true;var b=this.facade.getCanvas().node.getScreenCTM();this.faktorXY.x=b.a;this.faktorXY.y=b.d;var g=Event.pointerX(d);var e=Event.pointerY(d);var f=this.dragBounds.upperLeft();this.offSetPosition={x:g-(f.x*this.faktorXY.x),y:e-(f.y*this.faktorXY.y)};this.offsetScroll={x:this.scrollNode.scrollLeft,y:this.scrollNode.scrollTop};document.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE,this.callbackMouseMove,false);document.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEUP,this.callbackMouseUp,true);return},handleMouseUp:function(d){this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,highlightId:\"dragdropresize.contain\"});this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,highlightId:\"dragdropresize.attached\"});if(this.dragEnable){if(!this.dragIntialized){this.afterDrag();if(this.isAttachingAllowed&&this.toMoveShapes.length==1&&this.toMoveShapes[0] instanceof ORYX.Core.Node&&this.toMoveShapes[0].dockers.length>0){var b=this.facade.eventCoordinates(d);var e=this.toMoveShapes[0].dockers[0];var c=ORYX.Core.Command.extend({construct:function(k,f,h,g){this.docker=k;this.newPosition=f;this.newDockedShape=h;this.newParent=h.parent||g.getCanvas();this.oldPosition=k.parent.bounds.center();this.oldDockedShape=k.getDockedShape();this.oldParent=k.parent.parent||g.getCanvas();this.facade=g;if(this.oldDockedShape){this.oldPosition=k.parent.absoluteBounds().center()}},execute:function(){this.dock(this.newDockedShape,this.newParent,this.newPosition);this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_ARRANGEMENT_TOP,excludeCommand:true})},rollback:function(){this.dock(this.oldDockedShape,this.oldParent,this.oldPosition)},dock:function(f,g,h){g.add(this.docker.parent);this.docker.setDockedShape(undefined);this.docker.bounds.centerMoveTo(h);this.docker.setDockedShape(f);this.facade.setSelection([this.docker.parent]);this.facade.getCanvas().update();this.facade.updateSelection()}});var a=[new c(e,b,this.containmentParentNode,this.facade)];this.facade.executeCommands(a)}else{if(this.isAddingAllowed){this.refreshSelectedShapes()}}this.facade.updateSelection();this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_DRAGDROP_END})}if(this.vLine){this.vLine.hide()}if(this.hLine){this.hLine.hide()}}this.dragEnable=false;document.documentElement.removeEventListener(ORYX.CONFIG.EVENT_MOUSEUP,this.callbackMouseUp,true);document.documentElement.removeEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE,this.callbackMouseMove,false);return},handleMouseMove:function(b){if(!this.dragEnable){return}if(this.dragIntialized){this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_DRAGDROP_START});this.dragIntialized=false;this.resizerSE.hide();this.resizerNW.hide();this._onlyEdges=this.currentShapes.all(function(c){return(c instanceof ORYX.Core.Edge)});this.beforeDrag();this._currentUnderlyingNodes=[]}var e={x:Event.pointerX(b)-this.offSetPosition.x,y:Event.pointerY(b)-this.offSetPosition.y};e.x-=this.offsetScroll.x-this.scrollNode.scrollLeft;e.y-=this.offsetScroll.y-this.scrollNode.scrollTop;var k=b.shiftKey||b.ctrlKey;if(ORYX.CONFIG.GRID_ENABLED&&!k){e=this.snapToGrid(e)}else{if(this.vLine){this.vLine.hide()}if(this.hLine){this.hLine.hide()}}e.x/=this.faktorXY.x;e.y/=this.faktorXY.y;e.x=Math.max(0,e.x);e.y=Math.max(0,e.y);var g=this.facade.getCanvas();e.x=Math.min(g.bounds.width()-this.dragBounds.width(),e.x);e.y=Math.min(g.bounds.height()-this.dragBounds.height(),e.y);this.dragBounds.moveTo(e);this.resizeRectangle(this.dragBounds);this.isAttachingAllowed=false;var f=this.facade.eventCoordinates(b);var a=1;if(!isNaN(screen.logicalXDPI)&&!isNaN(screen.systemXDPI)){var d=navigator.userAgent;if(d.indexOf(\"MSIE\")>=0){var m=Math.round((screen.deviceXDPI/screen.logicalXDPI)*100);if(m!==100){a=m/100}}}if(a!==1){f.x=f.x/a;f.y=f.y/a}var l=$A(this.facade.getCanvas().getAbstractShapesAtPosition(f));var h=this.toMoveShapes.length==1&&this.toMoveShapes[0] instanceof ORYX.Core.Node&&this.toMoveShapes[0].dockers.length>0;h=h&&l.length!=1;if(!h&&l.length===this._currentUnderlyingNodes.length&&l.all(function(o,c){return this._currentUnderlyingNodes[c]===o}.bind(this))){return}else{if(this._onlyEdges){this.isAddingAllowed=true;this.containmentParentNode=this.facade.getCanvas()}else{var n={event:b,underlyingNodes:l,checkIfAttachable:h};this.checkRules(n)}}this._currentUnderlyingNodes=l.reverse();if(this.isAttachingAllowed){this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW,highlightId:\"dragdropresize.attached\",elements:[this.containmentParentNode],style:ORYX.CONFIG.SELECTION_HIGHLIGHT_STYLE_RECTANGLE,color:ORYX.CONFIG.SELECTION_VALID_COLOR})}else{this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,highlightId:\"dragdropresize.attached\"})}if(!this.isAttachingAllowed){if(this.isAddingAllowed){this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW,highlightId:\"dragdropresize.contain\",elements:[this.containmentParentNode],color:ORYX.CONFIG.SELECTION_VALID_COLOR})}else{this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW,highlightId:\"dragdropresize.contain\",elements:[this.containmentParentNode],color:ORYX.CONFIG.SELECTION_INVALID_COLOR})}}else{this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,highlightId:\"dragdropresize.contain\"})}return},checkRules:function(d){var f=d.event;var c=d.underlyingNodes;var e=d.checkIfAttachable;var b=d.noEdges;this.containmentParentNode=c.reverse().find((function(g){return(g instanceof ORYX.Core.Canvas)||(((g instanceof ORYX.Core.Node)||((g instanceof ORYX.Core.Edge)&&!b))&&(!(this.currentShapes.member(g)||this.currentShapes.any(function(h){return(h.children.length>0&&h.getChildNodes(true).member(g))}))))}).bind(this));if(e){this.isAttachingAllowed=this.facade.getRules().canConnect({sourceShape:this.containmentParentNode,edgeShape:this.toMoveShapes[0],targetShape:this.toMoveShapes[0]});if(this.isAttachingAllowed){var a=this.facade.eventCoordinates(f);this.isAttachingAllowed=this.containmentParentNode.isPointOverOffset(a.x,a.y)}}if(!this.isAttachingAllowed){this.isAddingAllowed=this.toMoveShapes.all((function(g){if(g instanceof ORYX.Core.Edge||g instanceof ORYX.Core.Controls.Docker||this.containmentParentNode===g.parent){return true}else{if(this.containmentParentNode!==g){if(!(this.containmentParentNode instanceof ORYX.Core.Edge)||!b){if(this.facade.getRules().canContain({containingShape:this.containmentParentNode,containedShape:g})){return true}}}}return false}).bind(this))}if(!this.isAttachingAllowed&&!this.isAddingAllowed&&(this.containmentParentNode instanceof ORYX.Core.Edge)){d.noEdges=true;d.underlyingNodes.reverse();this.checkRules(d)}},refreshSelectedShapes:function(){if(!this.dragBounds){return}var d=this.dragBounds.upperLeft();var b=this.oldDragBounds.upperLeft();var c={x:d.x-b.x,y:d.y-b.y};var a=[new ORYX.Core.Command.Move(this.toMoveShapes,c,this.containmentParentNode,this.currentShapes,this)];if(this._undockedEdgesCommand instanceof ORYX.Core.Command){a.unshift(this._undockedEdgesCommand)}this.facade.executeCommands(a);if(this.dragBounds){this.oldDragBounds=this.dragBounds.clone()}},onResize:function(a){if(!this.dragBounds){return}this.dragBounds=a;this.isResizing=true;this.resizeRectangle(this.dragBounds)},onResizeStart:function(){this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_RESIZE_START})},onResizeEnd:function(){if(!(this.currentShapes instanceof Array)||this.currentShapes.length<=0){return}if(this.isResizing){var a=ORYX.Core.Command.extend({construct:function(f,h,g){this.shape=f;this.oldBounds=f.bounds.clone();this.newBounds=h;this.plugin=g},execute:function(){this.shape.bounds.set(this.newBounds.a,this.newBounds.b);this.update(this.getOffset(this.oldBounds,this.newBounds))},rollback:function(){this.shape.bounds.set(this.oldBounds.a,this.oldBounds.b);this.update(this.getOffset(this.newBounds,this.oldBounds))},getOffset:function(g,f){return{x:f.a.x-g.a.x,y:f.a.y-g.a.y,xs:f.width()/g.width(),ys:f.height()/g.height()}},update:function(g){this.shape.getLabels().each(function(h){h.changed()});var f=[].concat(this.shape.getIncomingShapes()).concat(this.shape.getOutgoingShapes()).findAll(function(h){return h instanceof ORYX.Core.Edge}.bind(this));this.plugin.layoutEdges(this.shape,f,g);this.plugin.facade.setSelection([this.shape]);this.plugin.facade.getCanvas().update();this.plugin.facade.updateSelection()}});var c=this.dragBounds.clone();var b=this.currentShapes[0];if(b.parent){var e=b.parent.absoluteXY();c.moveBy(-e.x,-e.y)}var d=new a(b,c,this);this.facade.executeCommands([d]);this.isResizing=false;this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_RESIZE_END})}},beforeDrag:function(){var a=ORYX.Core.Command.extend({construct:function(b){this.dockers=b.collect(function(c){return c instanceof ORYX.Core.Controls.Docker?{docker:c,dockedShape:c.getDockedShape(),refPoint:c.referencePoint}:undefined}).compact()},execute:function(){this.dockers.each(function(b){b.docker.setDockedShape(undefined)})},rollback:function(){this.dockers.each(function(b){b.docker.setDockedShape(b.dockedShape);b.docker.setReferencePoint(b.refPoint)})}});this._undockedEdgesCommand=new a(this.toMoveShapes);this._undockedEdgesCommand.execute()},hideAllLabels:function(a){a.getLabels().each(function(b){b.hide()});a.getAllDockedShapes().each(function(b){var c=b.getLabels();if(c.length>0){c.each(function(d){d.hide()})}});a.getChildren().each((function(b){if(b instanceof ORYX.Core.Shape){this.hideAllLabels(b)}}).bind(this))},afterDrag:function(){},showAllLabels:function(a){for(var d=0;d<a.length;d++){var b=a[d];b.show()}var f=a.getAllDockedShapes();for(var d=0;d<f.length;d++){var c=f[d];var g=c.getLabels();if(g.length>0){g.each(function(h){h.show()})}}for(var d=0;d<a.children.length;d++){var e=a.children[d];if(e instanceof ORYX.Core.Shape){this.showAllLabels(e)}}},onSelectionChanged:function(b){var d=b.elements;this.dragEnable=false;this.dragIntialized=false;this.resizerSE.hide();this.resizerNW.hide();if(!d||d.length==0){this.selectedRect.hide();this.currentShapes=[];this.toMoveShapes=[];this.dragBounds=undefined;this.oldDragBounds=undefined}else{this.currentShapes=d;var e=this.facade.getCanvas().getShapesWithSharedParent(d);this.toMoveShapes=e;this.toMoveShapes=this.toMoveShapes.findAll(function(f){return f instanceof ORYX.Core.Node&&(f.dockers.length===0||!d.member(f.dockers.first().getDockedShape()))});d.each((function(f){if(!(f instanceof ORYX.Core.Edge)){return}var h=f.getDockers();var k=d.member(h.first().getDockedShape());var g=d.member(h.last().getDockedShape());if(!k&&!g){var l=!h.first().getDockedShape()&&!h.last().getDockedShape();if(l){this.toMoveShapes=this.toMoveShapes.concat(h)}}if(f.dockers.length>2&&k&&g){this.toMoveShapes=this.toMoveShapes.concat(h.findAll(function(n,m){return m>0&&m<h.length-1}))}}).bind(this));var c=undefined;this.toMoveShapes.each(function(g){var f=g;if(g instanceof ORYX.Core.Controls.Docker){f=g.parent}if(!c){c=f.absoluteBounds()}else{c.include(f.absoluteBounds())}}.bind(this));if(!c){d.each(function(f){if(!c){c=f.absoluteBounds()}else{c.include(f.absoluteBounds())}})}this.dragBounds=c;this.oldDragBounds=c.clone();this.resizeRectangle(c);this.selectedRect.show();if(d.length==1&&d[0].isResizable){var a=d[0].getStencil().fixedAspectRatio()?d[0].bounds.width()/d[0].bounds.height():undefined;this.resizerSE.setBounds(this.dragBounds,d[0].minimumSize,d[0].maximumSize,a);this.resizerSE.show();this.resizerNW.setBounds(this.dragBounds,d[0].minimumSize,d[0].maximumSize,a);this.resizerNW.show()}else{this.resizerSE.setBounds(undefined);this.resizerNW.setBounds(undefined)}if(ORYX.CONFIG.GRID_ENABLED){this.distPoints=[];if(this.distPointTimeout){window.clearTimeout(this.distPointTimeout)}this.distPointTimeout=window.setTimeout(function(){var f=this.facade.getCanvas().getChildShapes(true).findAll(function(h){var g=h.parent;while(g){if(d.member(g)){return false}g=g.parent}return true});f.each((function(l){if(!(l instanceof ORYX.Core.Edge)){var h=l.absoluteXY();var k=l.bounds.width();var g=l.bounds.height();this.distPoints.push({ul:{x:h.x,y:h.y},c:{x:h.x+(k/2),y:h.y+(g/2)},lr:{x:h.x+k,y:h.y+g}})}}).bind(this))}.bind(this),10)}}},snapToGrid:function(h){var a=this.dragBounds;var p={};var o=6;var m=10;var q=6;var b=this.vLine?this.vLine.getScale():1;var l={x:(h.x/b),y:(h.y/b)};var n={x:(h.x/b)+(a.width()/2),y:(h.y/b)+(a.height()/2)};var g={x:(h.x/b)+(a.width()),y:(h.y/b)+(a.height())};var f,d;var k,e;this.distPoints.each(function(s){var c,u,t,r;if(Math.abs(s.c.x-n.x)<m){c=s.c.x-n.x;t=s.c.x}if(Math.abs(s.c.y-n.y)<m){u=s.c.y-n.y;r=s.c.y}if(c!==undefined){f=f===undefined?c:(Math.abs(c)<Math.abs(f)?c:f);if(f===c){k=t}}if(u!==undefined){d=d===undefined?u:(Math.abs(u)<Math.abs(d)?u:d);if(d===u){e=r}}});if(f!==undefined){l.x+=f;l.x*=b;if(this.vLine&&k){this.vLine.update(k)}}else{l.x=(h.x-(h.x%(ORYX.CONFIG.GRID_DISTANCE/2)));if(this.vLine){this.vLine.hide()}}if(d!==undefined){l.y+=d;l.y*=b;if(this.hLine&&e){this.hLine.update(e)}}else{l.y=(h.y-(h.y%(ORYX.CONFIG.GRID_DISTANCE/2)));if(this.hLine){this.hLine.hide()}}return l},showGridLine:function(){},resizeRectangle:function(a){this.selectedRect.resize(a)}});ORYX.Plugins.SelectedRect=Clazz.extend({construct:function(a){this.parentId=a;this.node=ORYX.Editor.graft(\"http://www.w3.org/2000/svg\",$(a),[\"g\"]);this.dashedArea=ORYX.Editor.graft(\"http://www.w3.org/2000/svg\",this.node,[\"rect\",{x:0,y:0,\"stroke-width\":1,stroke:\"#777777\",fill:\"none\",\"stroke-dasharray\":\"2,2\",\"pointer-events\":\"none\"}]);this.hide()},hide:function(){this.node.setAttributeNS(null,\"display\",\"none\")},show:function(){this.node.setAttributeNS(null,\"display\",\"\")},resize:function(a){var c=a.upperLeft();var b=ORYX.CONFIG.SELECTED_AREA_PADDING;this.dashedArea.setAttributeNS(null,\"width\",a.width()+2*b);this.dashedArea.setAttributeNS(null,\"height\",a.height()+2*b);this.node.setAttributeNS(null,\"transform\",\"translate(\"+(c.x-b)+\", \"+(c.y-b)+\")\")}});ORYX.Plugins.GridLine=Clazz.extend({construct:function(b,a){if(ORYX.Plugins.GridLine.DIR_HORIZONTAL!==a&&ORYX.Plugins.GridLine.DIR_VERTICAL!==a){a=ORYX.Plugins.GridLine.DIR_HORIZONTAL}this.parent=$(b);this.direction=a;this.node=ORYX.Editor.graft(\"http://www.w3.org/2000/svg\",this.parent,[\"g\"]);this.line=ORYX.Editor.graft(\"http://www.w3.org/2000/svg\",this.node,[\"path\",{\"stroke-width\":1,stroke:\"silver\",fill:\"none\",\"stroke-dasharray\":\"5,5\",\"pointer-events\":\"none\"}]);this.hide()},hide:function(){this.node.setAttributeNS(null,\"display\",\"none\")},show:function(){this.node.setAttributeNS(null,\"display\",\"\")},getScale:function(){try{return this.parent.parentNode.transform.baseVal.getItem(0).matrix.a}catch(a){return 1}},update:function(e){if(this.direction===ORYX.Plugins.GridLine.DIR_HORIZONTAL){var d=e instanceof Object?e.y:e;var c=this.parent.parentNode.parentNode.width.baseVal.value/this.getScale();this.line.setAttributeNS(null,\"d\",\"M 0 \"+d+\" L \"+c+\" \"+d)}else{var a=e instanceof Object?e.x:e;var b=this.parent.parentNode.parentNode.height.baseVal.value/this.getScale();this.line.setAttributeNS(null,\"d\",\"M\"+a+\" 0 L \"+a+\" \"+b)}this.show()}});ORYX.Plugins.GridLine.DIR_HORIZONTAL=\"hor\";ORYX.Plugins.GridLine.DIR_VERTICAL=\"ver\";ORYX.Plugins.Resizer=Clazz.extend({construct:function(c,a,b){this.parentId=c;this.orientation=a;this.facade=b;this.node=ORYX.Editor.graft(\"http://www.w3.org/1999/xhtml\",$(\"canvasSection\"),[\"div\",{\"class\":\"resizer_\"+this.orientation,style:\"left:0px; top:0px;position:absolute;\"}]);this.node.addEventListener(ORYX.CONFIG.EVENT_MOUSEDOWN,this.handleMouseDown.bind(this),true);document.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEUP,this.handleMouseUp.bind(this),true);document.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE,this.handleMouseMove.bind(this),false);this.dragEnable=false;this.offSetPosition={x:0,y:0};this.bounds=undefined;this.canvasNode=this.facade.getCanvas().node;this.minSize=undefined;this.maxSize=undefined;this.aspectRatio=undefined;this.resizeCallbacks=[];this.resizeStartCallbacks=[];this.resizeEndCallbacks=[];this.hide();this.scrollNode=this.node.parentNode.parentNode.parentNode},handleMouseDown:function(a){this.dragEnable=true;this.offsetScroll={x:this.scrollNode.scrollLeft,y:this.scrollNode.scrollTop};this.offSetPosition={x:Event.pointerX(a)-this.position.x,y:Event.pointerY(a)-this.position.y};this.resizeStartCallbacks.each((function(b){b(this.bounds)}).bind(this))},handleMouseUp:function(a){this.dragEnable=false;this.containmentParentNode=null;this.resizeEndCallbacks.each((function(b){b(this.bounds)}).bind(this))},handleMouseMove:function(b){if(!this.dragEnable){return}if(b.shiftKey||b.ctrlKey){this.aspectRatio=this.bounds.width()/this.bounds.height()}else{this.aspectRatio=undefined}var a={x:Event.pointerX(b)-this.offSetPosition.x,y:Event.pointerY(b)-this.offSetPosition.y};a.x-=this.offsetScroll.x-this.scrollNode.scrollLeft;a.y-=this.offsetScroll.y-this.scrollNode.scrollTop;a.x=Math.min(a.x,this.facade.getCanvas().bounds.width());a.y=Math.min(a.y,this.facade.getCanvas().bounds.height());var c={x:a.x-this.position.x,y:a.y-this.position.y};if(this.aspectRatio){newAspectRatio=(this.bounds.width()+c.x)/(this.bounds.height()+c.y);if(newAspectRatio>this.aspectRatio){c.x=this.aspectRatio*(this.bounds.height()+c.y)-this.bounds.width()}else{if(newAspectRatio<this.aspectRatio){c.y=(this.bounds.width()+c.x)/this.aspectRatio-this.bounds.height()}}}if(this.orientation===\"northwest\"){if(this.bounds.width()-c.x>this.maxSize.width){c.x=-(this.maxSize.width-this.bounds.width());if(this.aspectRatio){c.y=this.aspectRatio*c.x}}if(this.bounds.width()-c.x<this.minSize.width){c.x=-(this.minSize.width-this.bounds.width());if(this.aspectRatio){c.y=this.aspectRatio*c.x}}if(this.bounds.height()-c.y>this.maxSize.height){c.y=-(this.maxSize.height-this.bounds.height());if(this.aspectRatio){c.x=c.y/this.aspectRatio}}if(this.bounds.height()-c.y<this.minSize.height){c.y=-(this.minSize.height-this.bounds.height());if(this.aspectRatio){c.x=c.y/this.aspectRatio}}}else{if(this.bounds.width()+c.x>this.maxSize.width){c.x=this.maxSize.width-this.bounds.width();if(this.aspectRatio){c.y=this.aspectRatio*c.x}}if(this.bounds.width()+c.x<this.minSize.width){c.x=this.minSize.width-this.bounds.width();if(this.aspectRatio){c.y=this.aspectRatio*c.x}}if(this.bounds.height()+c.y>this.maxSize.height){c.y=this.maxSize.height-this.bounds.height();if(this.aspectRatio){c.x=c.y/this.aspectRatio}}if(this.bounds.height()+c.y<this.minSize.height){c.y=this.minSize.height-this.bounds.height();if(this.aspectRatio){c.x=c.y/this.aspectRatio}}}if(this.orientation===\"northwest\"){this.bounds.extend({x:-c.x,y:-c.y});this.bounds.moveBy(c)}else{this.bounds.extend(c)}this.update();this.resizeCallbacks.each((function(d){d(this.bounds)}).bind(this));Event.stop(b)},registerOnResizeStart:function(a){if(!this.resizeStartCallbacks.member(a)){this.resizeStartCallbacks.push(a)}},unregisterOnResizeStart:function(a){if(this.resizeStartCallbacks.member(a)){this.resizeStartCallbacks=this.resizeStartCallbacks.without(a)}},registerOnResizeEnd:function(a){if(!this.resizeEndCallbacks.member(a)){this.resizeEndCallbacks.push(a)}},unregisterOnResizeEnd:function(a){if(this.resizeEndCallbacks.member(a)){this.resizeEndCallbacks=this.resizeEndCallbacks.without(a)}},registerOnResize:function(a){if(!this.resizeCallbacks.member(a)){this.resizeCallbacks.push(a)}},unregisterOnResize:function(a){if(this.resizeCallbacks.member(a)){this.resizeCallbacks=this.resizeCallbacks.without(a)}},hide:function(){this.node.style.display=\"none\"},show:function(){if(this.bounds){this.node.style.display=\"\"}},setBounds:function(d,b,a,c){this.bounds=d;if(!b){b={width:ORYX.CONFIG.MINIMUM_SIZE,height:ORYX.CONFIG.MINIMUM_SIZE}}if(!a){a={width:ORYX.CONFIG.MAXIMUM_SIZE,height:ORYX.CONFIG.MAXIMUM_SIZE}}this.minSize=b;this.maxSize=a;this.aspectRatio=c;this.update()},update:function(){if(!this.bounds){return}var d=this.bounds.upperLeft();if(this.bounds.width()<this.minSize.width){this.bounds.set(d.x,d.y,d.x+this.minSize.width,d.y+this.bounds.height())}if(this.bounds.height()<this.minSize.height){this.bounds.set(d.x,d.y,d.x+this.bounds.width(),d.y+this.minSize.height)}if(this.bounds.width()>this.maxSize.width){this.bounds.set(d.x,d.y,d.x+this.maxSize.width,d.y+this.bounds.height())}if(this.bounds.height()>this.maxSize.height){this.bounds.set(d.x,d.y,d.x+this.bounds.width(),d.y+this.maxSize.height)}var g=this.canvasNode.getScreenCTM();d.x*=g.a;d.y*=g.d;var b=1;if(!isNaN(screen.logicalXDPI)&&!isNaN(screen.systemXDPI)){var c=navigator.userAgent;if(c.indexOf(\"MSIE\")>=0){var m=Math.round((screen.deviceXDPI/screen.logicalXDPI)*100);if(m!==100){b=m/100}}}if(b===1){d.y=d.y-jQuery(\"#canvasSection\").offset().top+g.f;d.x=d.x-jQuery(\"#canvasSection\").offset().left+g.e}else{var h=jQuery(\"#canvasSection\").offset().left;var k=jQuery(\"#canvasSection\").scrollLeft();var f=jQuery(\"#canvasSection\").scrollTop();var e=g.e-(h*b);var l=0;if(e>10){l=(e/b)-e}d.y=d.y-(jQuery(\"#canvasSection\").offset().top*b)+((f*b)-f)+g.f;d.x=d.x-(h*b)+l+((k*b)-k)+g.e}if(this.orientation===\"northwest\"){d.x-=13;d.y-=13}else{d.x+=(g.a*this.bounds.width())+3;d.y+=(g.d*this.bounds.height())+3}this.position=d;this.node.style.left=this.position.x+\"px\";this.node.style.top=this.position.y+\"px\"}});ORYX.Core.Command.Move=ORYX.Core.Command.extend({construct:function(b,e,c,a,d){this.moveShapes=b;this.selectedShapes=a;this.offset=e;this.plugin=d;this.newParents=b.collect(function(f){return c||f.parent});this.oldParents=b.collect(function(f){return f.parent});this.dockedNodes=b.findAll(function(f){return f instanceof ORYX.Core.Node&&f.dockers.length==1}).collect(function(f){return{docker:f.dockers[0],dockedShape:f.dockers[0].getDockedShape(),refPoint:f.dockers[0].referencePoint}})},execute:function(){this.dockAllShapes();this.move(this.offset);this.addShapeToParent(this.newParents);this.selectCurrentShapes();this.plugin.facade.getCanvas().update();this.plugin.facade.updateSelection()},rollback:function(){var a={x:-this.offset.x,y:-this.offset.y};this.move(a);this.addShapeToParent(this.oldParents);this.dockAllShapes(true);this.selectCurrentShapes();this.plugin.facade.getCanvas().update();this.plugin.facade.updateSelection()},move:function(d,a){for(var g=0;g<this.moveShapes.length;g++){var l=this.moveShapes[g];l.bounds.moveBy(d);if(l instanceof ORYX.Core.Node){(l.dockers||[]).each(function(k){k.bounds.moveBy(d)});var e=[].concat(l.getIncomingShapes()).concat(l.getOutgoingShapes()).findAll(function(k){return k instanceof ORYX.Core.Edge&&!this.moveShapes.any(function(m){return m==k||(m instanceof ORYX.Core.Controls.Docker&&m.parent==k)})}.bind(this)).findAll(function(k){return(k.dockers.first().getDockedShape()==l||!this.moveShapes.include(k.dockers.first().getDockedShape()))&&(k.dockers.last().getDockedShape()==l||!this.moveShapes.include(k.dockers.last().getDockedShape()))}.bind(this));this.plugin.layoutEdges(l,e,d);var h=[].concat(l.getIncomingShapes()).concat(l.getOutgoingShapes()).findAll(function(k){return k instanceof ORYX.Core.Edge&&k.dockers.first().isDocked()&&k.dockers.last().isDocked()&&!this.moveShapes.include(k)&&!this.moveShapes.any(function(m){return m==k||(m instanceof ORYX.Core.Controls.Docker&&m.parent==k)})}.bind(this)).findAll(function(k){return this.moveShapes.indexOf(k.dockers.first().getDockedShape())>g||this.moveShapes.indexOf(k.dockers.last().getDockedShape())>g}.bind(this));for(var f=0;f<h.length;f++){for(var b=1;b<h[f].dockers.length-1;b++){var c=h[f].dockers[b];if(!c.getDockedShape()&&!this.moveShapes.include(c)){c.bounds.moveBy(d)}}}}}},dockAllShapes:function(a){for(var b=0;b<this.dockedNodes.length;b++){var c=this.dockedNodes[b].docker;c.setDockedShape(a?this.dockedNodes[b].dockedShape:undefined);if(c.getDockedShape()){c.setReferencePoint(this.dockedNodes[b].refPoint)}}},addShapeToParent:function(e){for(var f=0;f<this.moveShapes.length;f++){var d=this.moveShapes[f];if(d instanceof ORYX.Core.Node&&d.parent!==e[f]){var g=e[f].absoluteXY();var h=d.absoluteXY();var c=h.x-g.x;var k=h.y-g.y;e[f].add(d);d.getOutgoingShapes((function(b){if(b instanceof ORYX.Core.Node&&!this.moveShapes.member(b)){e[f].add(b)}}).bind(this));if(d instanceof ORYX.Core.Node&&d.dockers.length==1){var a=d.bounds;c+=a.width()/2;k+=a.height()/2;d.dockers.first().bounds.centerMoveTo(c,k)}else{d.bounds.moveTo(c,k)}}}},selectCurrentShapes:function(){this.plugin.facade.setSelection(this.selectedShapes)}});if(!ORYX.Plugins){ORYX.Plugins=new Object()}ORYX.Plugins.DragDocker=Clazz.extend({construct:function(a){this.facade=a;this.VALIDCOLOR=ORYX.CONFIG.SELECTION_VALID_COLOR;this.INVALIDCOLOR=ORYX.CONFIG.SELECTION_INVALID_COLOR;this.shapeSelection=undefined;this.docker=undefined;this.dockerParent=undefined;this.dockerSource=undefined;this.dockerTarget=undefined;this.lastUIObj=undefined;this.isStartDocker=undefined;this.isEndDocker=undefined;this.undockTreshold=10;this.initialDockerPosition=undefined;this.outerDockerNotMoved=undefined;this.isValid=false;this.facade.registerOnEvent(ORYX.CONFIG.EVENT_MOUSEDOWN,this.handleMouseDown.bind(this));this.facade.registerOnEvent(ORYX.CONFIG.EVENT_DOCKERDRAG,this.handleDockerDrag.bind(this));this.facade.registerOnEvent(ORYX.CONFIG.EVENT_MOUSEOVER,this.handleMouseOver.bind(this));this.facade.registerOnEvent(ORYX.CONFIG.EVENT_MOUSEOUT,this.handleMouseOut.bind(this))},handleMouseOut:function(b,a){if(!this.docker&&a instanceof ORYX.Core.Controls.Docker){a.hide()}else{if(!this.docker&&a instanceof ORYX.Core.Edge){a.dockers.each(function(c){c.hide()})}}},handleMouseOver:function(b,a){if(!this.docker&&a instanceof ORYX.Core.Controls.Docker){a.show()}else{if(!this.docker&&a instanceof ORYX.Core.Edge){a.dockers.each(function(c){c.show()})}}},handleDockerDrag:function(b,a){this.handleMouseDown(b.uiEvent,a)},handleMouseDown:function(g,f){if(f instanceof ORYX.Core.Controls.Docker&&f.isMovable){this.shapeSelection=this.facade.getSelection();this.facade.setSelection();this.docker=f;this.initialDockerPosition=this.docker.bounds.center();this.outerDockerNotMoved=false;this.dockerParent=f.parent;this._commandArg={docker:f,dockedShape:f.getDockedShape(),refPoint:f.referencePoint||f.bounds.center()};this.docker.show();if(f.parent instanceof ORYX.Core.Edge&&(f.parent.dockers.first()==f||f.parent.dockers.last()==f)){if(f.parent.dockers.first()==f&&f.parent.dockers.last().getDockedShape()){this.dockerTarget=f.parent.dockers.last().getDockedShape()}else{if(f.parent.dockers.last()==f&&f.parent.dockers.first().getDockedShape()){this.dockerSource=f.parent.dockers.first().getDockedShape()}}}else{this.dockerSource=undefined;this.dockerTarget=undefined}this.isStartDocker=this.docker.parent.dockers.first()===this.docker;this.isEndDocker=this.docker.parent.dockers.last()===this.docker;this.facade.getCanvas().add(this.docker.parent);this.docker.parent.getLabels().each(function(h){h.hide()});var c=this.facade.eventCoordinates(g);var e=1;if(!isNaN(screen.logicalXDPI)&&!isNaN(screen.systemXDPI)){var a=navigator.userAgent;if(a.indexOf(\"MSIE\")>=0){var d=Math.round((screen.deviceXDPI/screen.logicalXDPI)*100);if(d!==100){e=d/100}}}if(e!==1){c.x=c.x/e;c.y=c.y/e}if((!this.isStartDocker&&!this.isEndDocker)||!this.docker.isDocked()){this.docker.setDockedShape(undefined);this.docker.bounds.centerMoveTo(c);this.dockerParent._update()}else{this.outerDockerNotMoved=true}var b={movedCallback:this.dockerMoved.bind(this),upCallback:this.dockerMovedFinished.bind(this)};this.startEventPos=c;ORYX.Core.UIEnableDrag(g,f,b)}},dockerMoved:function(u){this.outerDockerNotMoved=false;var m=undefined;if(this.docker.parent){if(this.isStartDocker||this.isEndDocker){var p=this.facade.eventCoordinates(u);var x=1;if(!isNaN(screen.logicalXDPI)&&!isNaN(screen.systemXDPI)){var w=navigator.userAgent;if(w.indexOf(\"MSIE\")>=0){var a=Math.round((screen.deviceXDPI/screen.logicalXDPI)*100);if(a!==100){x=a/100}}}if(x!==1){p.x=p.x/x;p.y=p.y/x}if(this.docker.isDocked()){var c=ORYX.Core.Math.getDistancePointToPoint(p,this.initialDockerPosition);if(c<this.undockTreshold){this.outerDockerNotMoved=true;return}this.docker.setDockedShape(undefined);this.dockerParent._update()}var t=this.facade.getCanvas().getAbstractShapesAtPosition(p);var s=t.pop();if(this.docker.parent===s){s=t.pop()}if(this.lastUIObj==s){}else{if(s instanceof ORYX.Core.Shape){if(this.docker.parent instanceof ORYX.Core.Edge){var v=this.getHighestParentBeforeCanvas(s);if(v instanceof ORYX.Core.Edge&&this.docker.parent===v){this.isValid=false;this.dockerParent._update();return}this.isValid=false;var b=s,d=s;while(!this.isValid&&b&&!(b instanceof ORYX.Core.Canvas)){s=b;this.isValid=this.facade.getRules().canConnect({sourceShape:this.dockerSource?this.dockerSource:(this.isStartDocker?s:undefined),edgeShape:this.docker.parent,targetShape:this.dockerTarget?this.dockerTarget:(this.isEndDocker?s:undefined)});b=b.parent}if(!this.isValid){s=d}}else{this.isValid=this.facade.getRules().canConnect({sourceShape:s,edgeShape:this.docker.parent,targetShape:this.docker.parent})}if(this.lastUIObj){this.hideMagnets(this.lastUIObj)}if(this.isValid){this.showMagnets(s)}this.showHighlight(s,this.isValid?this.VALIDCOLOR:this.INVALIDCOLOR);this.lastUIObj=s}else{this.hideHighlight();this.lastUIObj?this.hideMagnets(this.lastUIObj):null;this.lastUIObj=undefined;this.isValid=false}}if(this.lastUIObj&&this.isValid&&!(u.shiftKey||u.ctrlKey)){m=this.lastUIObj.magnets.find(function(A){return A.absoluteBounds().isIncluded(p)});if(m){this.docker.bounds.centerMoveTo(m.absoluteCenterXY())}}}}if(!(u.shiftKey||u.ctrlKey)&&!m){var o=ORYX.CONFIG.DOCKER_SNAP_OFFSET;var k=o+1;var g=o+1;var z=this.docker.bounds.center();if(this.docker.parent){this.docker.parent.dockers.each((function(B){if(this.docker==B){return}var A=B.referencePoint?B.getAbsoluteReferencePoint():B.bounds.center();k=Math.abs(k)>Math.abs(A.x-z.x)?A.x-z.x:k;g=Math.abs(g)>Math.abs(A.y-z.y)?A.y-z.y:g}).bind(this));if(Math.abs(k)<o||Math.abs(g)<o){k=Math.abs(k)<o?k:0;g=Math.abs(g)<o?g:0;this.docker.bounds.centerMoveTo(z.x+k,z.y+g)}else{var e=this.docker.parent.dockers[Math.max(this.docker.parent.dockers.indexOf(this.docker)-1,0)];var r=this.docker.parent.dockers[Math.min(this.docker.parent.dockers.indexOf(this.docker)+1,this.docker.parent.dockers.length-1)];if(e&&r&&e!==this.docker&&r!==this.docker){var f=e.bounds.center();var h=r.bounds.center();var q=this.docker.bounds.center();if(ORYX.Core.Math.isPointInLine(q.x,q.y,f.x,f.y,h.x,h.y,10)){var y=(Number(h.y)-Number(f.y))/(Number(h.x)-Number(f.x));var n=((f.y-(f.x*y))-(q.y-(q.x*(-Math.pow(y,-1)))))/((-Math.pow(y,-1))-y);var l=(f.y-(f.x*y))+(y*n);if(isNaN(n)||isNaN(l)){return}this.docker.bounds.centerMoveTo(n,l)}}}}}this.dockerParent._update()},dockerMovedFinished:function(e){this.facade.setSelection(this.shapeSelection);this.hideHighlight();this.dockerParent.getLabels().each(function(g){g.show()});if(this.lastUIObj&&(this.isStartDocker||this.isEndDocker)){if(this.isValid){this.docker.setDockedShape(this.lastUIObj);this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_DRAGDOCKER_DOCKED,docker:this.docker,parent:this.docker.parent,target:this.lastUIObj})}this.hideMagnets(this.lastUIObj)}this.docker.hide();if(this.outerDockerNotMoved){var d=this.facade.eventCoordinates(e);var a=this.facade.getCanvas().getAbstractShapesAtPosition(d);var b=a.findAll(function(g){return g instanceof ORYX.Core.Node});a=b.length?b:a;this.facade.setSelection(a)}else{var c=ORYX.Core.Command.extend({construct:function(n,h,g,m,l,k){this.docker=n;this.index=n.parent.dockers.indexOf(n);this.newPosition=h;this.newDockedShape=m;this.oldPosition=g;this.oldDockedShape=l;this.facade=k;this.index=n.parent.dockers.indexOf(n);this.shape=n.parent},execute:function(){if(!this.docker.parent){this.docker=this.shape.dockers[this.index]}this.dock(this.newDockedShape,this.newPosition);this.removedDockers=this.shape.removeUnusedDockers();this.facade.updateSelection()},rollback:function(){this.dock(this.oldDockedShape,this.oldPosition);(this.removedDockers||$H({})).each(function(g){this.shape.add(g.value,Number(g.key));this.shape._update(true)}.bind(this));this.facade.updateSelection()},dock:function(g,h){this.docker.setDockedShape(undefined);if(g){this.docker.setDockedShape(g);this.docker.setReferencePoint(h)}else{this.docker.bounds.centerMoveTo(h)}this.facade.getCanvas().update()}});if(this.docker.parent){var f=new c(this.docker,this.docker.getDockedShape()?this.docker.referencePoint:this.docker.bounds.center(),this._commandArg.refPoint,this.docker.getDockedShape(),this._commandArg.dockedShape,this.facade);this.facade.executeCommands([f])}}this.docker=undefined;this.dockerParent=undefined;this.dockerSource=undefined;this.dockerTarget=undefined;this.lastUIObj=undefined},hideHighlight:function(){this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,highlightId:\"validDockedShape\"})},showHighlight:function(b,a){this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW,highlightId:\"validDockedShape\",elements:[b],color:a})},showMagnets:function(a){a.magnets.each(function(b){b.show()})},hideMagnets:function(a){a.magnets.each(function(b){b.hide()})},getHighestParentBeforeCanvas:function(a){if(!(a instanceof ORYX.Core.Shape)){return undefined}var b=a.parent;while(b&&!(b.parent instanceof ORYX.Core.Canvas)){b=b.parent}return b}});if(!ORYX.Plugins){ORYX.Plugins=new Object()}ORYX.Plugins.AddDocker=Clazz.extend({construct:function(a){this.facade=a;this.enableAdd=false;this.enableRemove=false;this.facade.registerOnEvent(ORYX.CONFIG.EVENT_MOUSEDOWN,this.handleMouseDown.bind(this))},setEnableAdd:function(a){this.enableAdd=a;if(this.enableAdd){jQuery(\"#add-bendpoint-button\").addClass(\"pressed\")}else{jQuery(\"#add-bendpoint-button\").removeClass(\"pressed\");jQuery(\"#add-bendpoint-button\").blur()}},setEnableRemove:function(a){this.enableRemove=a;if(this.enableRemove){jQuery(\"#remove-bendpoint-button\").addClass(\"pressed\")}else{jQuery(\"#remove-bendpoint-button\").removeClass(\"pressed\");jQuery(\"#remove-bendpoint-button\").blur()}},enabledAdd:function(a){return this.enableAdd},enabledRemove:function(){return this.enableRemove},handleMouseDown:function(b,a){if(this.enabledAdd()&&a instanceof ORYX.Core.Edge){this.newDockerCommand({edge:a,position:this.facade.eventCoordinates(b)});this.setEnableAdd(false)}else{if(this.enabledRemove()&&a instanceof ORYX.Core.Controls.Docker&&a.parent instanceof ORYX.Core.Edge){this.newDockerCommand({edge:a.parent,docker:a});this.setEnableRemove(false)}}document.body.style.cursor=\"default\"},newDockerCommand:function(b){if(!b.edge){return}var a=ORYX.Core.Command.extend({construct:function(h,f,e,g,k,d){this.addEnabled=h;this.deleteEnabled=f;this.edge=e;this.docker=g;this.pos=k;this.facade=d},execute:function(){if(this.addEnabled){if(!this.docker){this.docker=this.edge.addDocker(this.pos);this.index=this.edge.dockers.indexOf(this.docker)}else{this.edge.add(this.docker,this.index)}}else{if(this.deleteEnabled){this.index=this.edge.dockers.indexOf(this.docker);this.pos=this.docker.bounds.center();this.edge.removeDocker(this.docker)}}this.edge.getLabels().invoke(\"show\");this.facade.getCanvas().update();this.facade.updateSelection()},rollback:function(){if(this.addEnabled){if(this.docker instanceof ORYX.Core.Controls.Docker){this.edge.removeDocker(this.docker)}}else{if(this.deleteEnabled){this.edge.add(this.docker,this.index)}}this.edge.getLabels().invoke(\"show\");this.facade.getCanvas().update();this.facade.updateSelection()}});var c=new a(this.enabledAdd(),this.enabledRemove(),b.edge,b.docker,b.position,this.facade);this.facade.executeCommands([c])}});if(!ORYX.Plugins){ORYX.Plugins=new Object()}ORYX.Plugins.SelectionFrame=Clazz.extend({construct:function(a){this.facade=a;this.facade.registerOnEvent(ORYX.CONFIG.EVENT_MOUSEDOWN,this.handleMouseDown.bind(this));document.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEUP,this.handleMouseUp.bind(this),true);this.position={x:0,y:0};this.size={width:0,height:0};this.offsetPosition={x:0,y:0};this.moveCallback=undefined;this.offsetScroll={x:0,y:0};this.node=ORYX.Editor.graft(\"http://www.w3.org/1999/xhtml\",$(\"canvasSection\"),[\"div\",{\"class\":\"Oryx_SelectionFrame\"}]);this.hide()},handleMouseDown:function(d,c){if(c instanceof ORYX.Core.Canvas){var e=c.rootNode.parentNode.parentNode;var b=this.facade.getCanvas().node.getScreenCTM();this.offsetPosition={x:b.e,y:b.f};this.setPos({x:Event.pointerX(d)-jQuery(\"#canvasSection\").offset().left,y:Event.pointerY(d)-jQuery(\"#canvasSection\").offset().top+5});this.resize({width:0,height:0});this.moveCallback=this.handleMouseMove.bind(this);document.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE,this.moveCallback,false);this.offsetScroll={x:e.scrollLeft,y:e.scrollTop};this.show()}Event.stop(d)},handleMouseUp:function(e){if(this.moveCallback){this.hide();document.documentElement.removeEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE,this.moveCallback,false);this.moveCallback=undefined;var g=this.facade.getCanvas().node.getScreenCTM();var m={x:this.size.width>0?this.position.x:this.position.x+this.size.width,y:this.size.height>0?this.position.y:this.position.y+this.size.height};var l={x:m.x+Math.abs(this.size.width),y:m.y+Math.abs(this.size.height)};var d=1;if(!isNaN(screen.logicalXDPI)&&!isNaN(screen.systemXDPI)){var f=navigator.userAgent;if(f.indexOf(\"MSIE\")>=0){var q=Math.round((screen.deviceXDPI/screen.logicalXDPI)*100);if(q!==100){d=q/100}}}if(d===1){m.x=m.x-(g.e-jQuery(\"#canvasSection\").offset().left);m.y=m.y-(g.f-jQuery(\"#canvasSection\").offset().top);l.x=l.x-(g.e-jQuery(\"#canvasSection\").offset().left);l.y=l.y-(g.f-jQuery(\"#canvasSection\").offset().top)}else{var n=jQuery(\"#canvasSection\").offset().left;var o=jQuery(\"#canvasSection\").scrollLeft();var k=jQuery(\"#canvasSection\").scrollTop();var h=m.e-(n*d);var p=0;if(h>10){p=(h/d)-h}m.x=m.x-(g.e-(n*d)+p+((o*d)-o));m.y=m.y-(g.f-(jQuery(\"#canvasSection\").offset().top*d)+((k*d)-k));l.x=l.x-(g.e-(n*d)+p+((o*d)-o));l.y=l.y-(g.f-(jQuery(\"#canvasSection\").offset().top*d)+((k*d)-k))}m.x/=g.a;m.y/=g.d;l.x/=g.a;l.y/=g.d;var c=this.facade.getCanvas().getChildShapes(true).findAll(function(b){var a=b.absoluteBounds();var s=a.upperLeft();var r=a.lowerRight();if(s.x>m.x&&s.y>m.y&&r.x<l.x&&r.y<l.y){return true}return false});this.facade.setSelection(c)}},handleMouseMove:function(b){var a={width:Event.pointerX(b)-this.position.x-jQuery(\"#canvasSection\").offset().left,height:Event.pointerY(b)-this.position.y-jQuery(\"#canvasSection\").offset().top+5};var c=this.facade.getCanvas().rootNode.parentNode.parentNode;a.width-=this.offsetScroll.x-c.scrollLeft;a.height-=this.offsetScroll.y-c.scrollTop;this.resize(a);Event.stop(b)},hide:function(){this.node.style.display=\"none\"},show:function(){this.node.style.display=\"\"},setPos:function(a){this.node.style.top=a.y+\"px\";this.node.style.left=a.x+\"px\";this.position=a},resize:function(a){this.setPos(this.position);this.size=Object.clone(a);if(a.width<0){this.node.style.left=(this.position.x+a.width)+\"px\";a.width=-a.width}if(a.height<0){this.node.style.top=(this.position.y+a.height)+\"px\";a.height=-a.height}this.node.style.width=a.width+\"px\";this.node.style.height=a.height+\"px\"}});if(!ORYX.Plugins){ORYX.Plugins=new Object()}ORYX.Plugins.ShapeHighlighting=Clazz.extend({construct:function(a){this.parentNode=a.getCanvas().getSvgContainer();this.node=ORYX.Editor.graft(\"http://www.w3.org/2000/svg\",this.parentNode,[\"g\"]);this.highlightNodes={};a.registerOnEvent(ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW,this.setHighlight.bind(this));a.registerOnEvent(ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,this.hideHighlight.bind(this))},setHighlight:function(a){if(a&&a.highlightId){var b=this.highlightNodes[a.highlightId];if(!b){b=ORYX.Editor.graft(\"http://www.w3.org/2000/svg\",this.node,[\"path\",{\"stroke-width\":2,fill:\"none\"}]);this.highlightNodes[a.highlightId]=b}if(a.elements&&a.elements.length>0){this.setAttributesByStyle(b,a);this.show(b)}else{this.hide(b)}}},hideHighlight:function(a){if(a&&a.highlightId&&this.highlightNodes[a.highlightId]){this.hide(this.highlightNodes[a.highlightId])}},hide:function(a){a.setAttributeNS(null,\"display\",\"none\")},show:function(a){a.setAttributeNS(null,\"display\",\"\")},setAttributesByStyle:function(b,a){if(a.style&&a.style==ORYX.CONFIG.SELECTION_HIGHLIGHT_STYLE_RECTANGLE){var d=a.elements[0].absoluteBounds();var c=a.strokewidth?a.strokewidth:ORYX.CONFIG.BORDER_OFFSET;b.setAttributeNS(null,\"d\",this.getPathRectangle(d.a,d.b,c));b.setAttributeNS(null,\"stroke\",a.color?a.color:ORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR);b.setAttributeNS(null,\"stroke-opacity\",a.opacity?a.opacity:0.2);b.setAttributeNS(null,\"stroke-width\",c)}else{if(a.elements.length==1&&a.elements[0] instanceof ORYX.Core.Edge&&a.highlightId!=\"selection\"){var e=this.getPathEdge(a.elements[0].dockers);if(e&&e.length>0){b.setAttributeNS(null,\"d\",e)}b.setAttributeNS(null,\"stroke\",a.color?a.color:ORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR);b.setAttributeNS(null,\"stroke-opacity\",a.opacity?a.opacity:0.2);b.setAttributeNS(null,\"stroke-width\",ORYX.CONFIG.OFFSET_EDGE_BOUNDS)}else{var e=this.getPathByElements(a.elements);if(e&&e.length>0){b.setAttributeNS(null,\"d\",e)}b.setAttributeNS(null,\"stroke\",a.color?a.color:ORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR);b.setAttributeNS(null,\"stroke-opacity\",a.opacity?a.opacity:1);b.setAttributeNS(null,\"stroke-width\",a.strokewidth?a.strokewidth:2)}}},getPathByElements:function(a){if(!a||a.length<=0){return undefined}var c=ORYX.CONFIG.SELECTED_AREA_PADDING;var b=\"\";a.each((function(f){if(!f){return}var g=f.absoluteBounds();g.widen(c);var e=g.upperLeft();var d=g.lowerRight();b=b+this.getPath(e,d)}).bind(this));return b},getPath:function(d,c){return this.getPathCorners(d,c)},getPathCorners:function(d,c){var e=ORYX.CONFIG.SELECTION_HIGHLIGHT_SIZE;var f=\"\";f=f+\"M\"+d.x+\" \"+(d.y+e)+\" l0 -\"+e+\" l\"+e+\" 0 \";f=f+\"M\"+d.x+\" \"+(c.y-e)+\" l0 \"+e+\" l\"+e+\" 0 \";f=f+\"M\"+c.x+\" \"+(c.y-e)+\" l0 \"+e+\" l-\"+e+\" 0 \";f=f+\"M\"+c.x+\" \"+(d.y+e)+\" l0 -\"+e+\" l-\"+e+\" 0 \";return f},getPathRectangle:function(d,c,h){var e=ORYX.CONFIG.SELECTION_HIGHLIGHT_SIZE;var f=\"\";var g=h/2;f=f+\"M\"+(d.x+g)+\" \"+(d.y);f=f+\" L\"+(d.x+g)+\" \"+(c.y-g);f=f+\" L\"+(c.x-g)+\" \"+(c.y-g);f=f+\" L\"+(c.x-g)+\" \"+(d.y+g);f=f+\" L\"+(d.x+g)+\" \"+(d.y+g);return f},getPathEdge:function(a){var b=a.length;var c=\"M\"+a[0].bounds.center().x+\" \"+a[0].bounds.center().y;for(i=1;i<b;i++){var d=a[i].bounds.center();c=c+\" L\"+d.x+\" \"+d.y}return c}});ORYX.Plugins.HighlightingSelectedShapes=Clazz.extend({construct:function(a){this.facade=a;this.opacityFull=0.9;this.opacityLow=0.4},onSelectionChanged:function(a){if(a.elements&&a.elements.length>1){this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW,highlightId:\"selection\",elements:a.elements.without(a.subSelection),color:ORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR,opacity:!a.subSelection?this.opacityFull:this.opacityLow});if(a.subSelection){this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW,highlightId:\"subselection\",elements:[a.subSelection],color:ORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR,opacity:this.opacityFull})}else{this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,highlightId:\"subselection\"})}}else{this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,highlightId:\"selection\"});this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,highlightId:\"subselection\"})}}});if(!ORYX.Plugins){ORYX.Plugins=new Object()}ORYX.Plugins.Overlay=Clazz.extend({facade:undefined,styleNode:undefined,construct:function(a){this.facade=a;this.changes=[];this.facade.registerOnEvent(ORYX.CONFIG.EVENT_OVERLAY_SHOW,this.show.bind(this));this.facade.registerOnEvent(ORYX.CONFIG.EVENT_OVERLAY_HIDE,this.hide.bind(this));this.styleNode=document.createElement(\"style\");this.styleNode.setAttributeNS(null,\"type\",\"text/css\");document.getElementsByTagName(\"head\")[0].appendChild(this.styleNode)},show:function(a){if(!a||!a.shapes||!a.shapes instanceof Array||!a.id||!a.id instanceof String||a.id.length==0){return}if(a.attributes){a.shapes.each(function(d){if(!d instanceof ORYX.Core.Shape){return}this.setAttributes(d.node,a.attributes)}.bind(this))}var c=true;try{c=a.node&&a.node instanceof SVGElement}catch(b){}if(a.node&&c){a._temps=[];a.shapes.each(function(g,f){if(!g instanceof ORYX.Core.Shape){return}var e={};e.svg=a.dontCloneNode?a.node:a.node.cloneNode(true);g.node.firstChild.appendChild(e.svg);if(g instanceof ORYX.Core.Edge&&!a.nodePosition){a.nodePosition=\"START\"}if(a.nodePosition){var d=g.bounds;var h=a.nodePosition.toUpperCase();if(g instanceof ORYX.Core.Node&&h==\"START\"){h=\"NW\"}else{if(g instanceof ORYX.Core.Node&&h==\"END\"){h=\"SE\"}else{if(g instanceof ORYX.Core.Edge&&h==\"START\"){d=g.getDockers().first().bounds}else{if(g instanceof ORYX.Core.Edge&&h==\"END\"){d=g.getDockers().last().bounds}}}}e.callback=function(){var k=0;var l=0;if(h==\"NW\"){}else{if(h==\"N\"){k=d.width()/2}else{if(h==\"NE\"){k=d.width()}else{if(h==\"E\"){k=d.width();l=d.height()/2}else{if(h==\"SE\"){k=d.width();l=d.height()}else{if(h==\"S\"){k=d.width()/2;l=d.height()}else{if(h==\"SW\"){l=d.height()}else{if(h==\"W\"){l=d.height()/2}else{if(h==\"START\"||h==\"END\"){k=d.width()/2;l=d.height()/2}else{return}}}}}}}}}if(g instanceof ORYX.Core.Edge){k+=d.upperLeft().x;l+=d.upperLeft().y}e.svg.setAttributeNS(null,\"transform\",\"translate(\"+k+\", \"+l+\")\")}.bind(this);e.element=g;e.callback();d.registerCallback(e.callback)}a._temps.push(e)}.bind(this))}if(!this.changes[a.id]){this.changes[a.id]=[]}this.changes[a.id].push(a)},hide:function(a){if(!a||!a.id||!a.id instanceof String||a.id.length==0||!this.changes[a.id]){return}this.changes[a.id].each(function(b){b.shapes.each(function(d,c){if(!d instanceof ORYX.Core.Shape){return}this.deleteAttributes(d.node)}.bind(this));if(b._temps){b._temps.each(function(c){if(c.svg&&c.svg.parentNode){c.svg.parentNode.removeChild(c.svg)}if(c.callback&&c.element){c.element.bounds.unregisterCallback(c.callback)}}.bind(this))}}.bind(this));this.changes[a.id]=null},setAttributes:function(c,d){var h=this.getAllChilds(c.firstChild.firstChild);var a=[];h.each(function(m){a.push($A(m.attributes).findAll(function(n){return n.nodeValue.startsWith(\"url(#\")}))});a=a.flatten().compact();a=a.collect(function(m){return m.nodeValue}).uniq();a=a.collect(function(m){return m.slice(5,m.length-1)});a.unshift(c.id+\" .me\");var g=$H(d);var e=g.toJSON().gsub(\",\",\";\").gsub('\"',\"\");var k=d.stroke?e.slice(0,e.length-1)+\"; fill:\"+d.stroke+\";}\":e;var f;if(d.fill){var b=Object.clone(d);b.fill=\"black\";f=$H(b).toJSON().gsub(\",\",\";\").gsub('\"',\"\")}csstags=a.collect(function(n,m){return\"#\"+n+\" * \"+(!m?e:k)+\"\"+(f?\" #\"+n+\" text * \"+f:\"\")});var l=csstags.join(\" \")+\"\\n\";this.styleNode.appendChild(document.createTextNode(l))},deleteAttributes:function(b){var a=$A(this.styleNode.childNodes).findAll(function(c){return c.textContent.include(\"#\"+b.id)});a.each(function(c){c.parentNode.removeChild(c)})},getAllChilds:function(a){var b=$A(a.childNodes);$A(a.childNodes).each(function(c){b.push(this.getAllChilds(c))}.bind(this));return b.flatten()}});if(!ORYX.Plugins){ORYX.Plugins=new Object()}ORYX.Plugins.KeysMove=ORYX.Plugins.AbstractPlugin.extend({facade:undefined,construct:function(a){this.facade=a;this.copyElements=[];this.facade.offer({keyCodes:[{metaKeys:[ORYX.CONFIG.META_KEY_META_CTRL],keyCode:65,keyAction:ORYX.CONFIG.KEY_ACTION_DOWN}],functionality:this.selectAll.bind(this)});this.facade.offer({keyCodes:[{metaKeys:[ORYX.CONFIG.META_KEY_META_CTRL],keyCode:ORYX.CONFIG.KEY_CODE_LEFT,keyAction:ORYX.CONFIG.KEY_ACTION_DOWN}],functionality:this.move.bind(this,ORYX.CONFIG.KEY_CODE_LEFT,false)});this.facade.offer({keyCodes:[{keyCode:ORYX.CONFIG.KEY_CODE_LEFT,keyAction:ORYX.CONFIG.KEY_ACTION_DOWN}],functionality:this.move.bind(this,ORYX.CONFIG.KEY_CODE_LEFT,true)});this.facade.offer({keyCodes:[{metaKeys:[ORYX.CONFIG.META_KEY_META_CTRL],keyCode:ORYX.CONFIG.KEY_CODE_RIGHT,keyAction:ORYX.CONFIG.KEY_ACTION_DOWN}],functionality:this.move.bind(this,ORYX.CONFIG.KEY_CODE_RIGHT,false)});this.facade.offer({keyCodes:[{keyCode:ORYX.CONFIG.KEY_CODE_RIGHT,keyAction:ORYX.CONFIG.KEY_ACTION_DOWN}],functionality:this.move.bind(this,ORYX.CONFIG.KEY_CODE_RIGHT,true)});this.facade.offer({keyCodes:[{metaKeys:[ORYX.CONFIG.META_KEY_META_CTRL],keyCode:ORYX.CONFIG.KEY_CODE_UP,keyAction:ORYX.CONFIG.KEY_ACTION_DOWN}],functionality:this.move.bind(this,ORYX.CONFIG.KEY_CODE_UP,false)});this.facade.offer({keyCodes:[{keyCode:ORYX.CONFIG.KEY_CODE_UP,keyAction:ORYX.CONFIG.KEY_ACTION_DOWN}],functionality:this.move.bind(this,ORYX.CONFIG.KEY_CODE_UP,true)});this.facade.offer({keyCodes:[{metaKeys:[ORYX.CONFIG.META_KEY_META_CTRL],keyCode:ORYX.CONFIG.KEY_CODE_DOWN,keyAction:ORYX.CONFIG.KEY_ACTION_DOWN}],functionality:this.move.bind(this,ORYX.CONFIG.KEY_CODE_DOWN,false)});this.facade.offer({keyCodes:[{keyCode:ORYX.CONFIG.KEY_CODE_DOWN,keyAction:ORYX.CONFIG.KEY_ACTION_DOWN}],functionality:this.move.bind(this,ORYX.CONFIG.KEY_CODE_DOWN,true)})},selectAll:function(a){Event.stop(a.event);this.facade.setSelection(this.facade.getCanvas().getChildShapes(true))},move:function(n,k,l){Event.stop(l.event);var b=k?20:5;var m=this.facade.getSelection();var g=this.facade.getSelection();var c={x:0,y:0};switch(n){case ORYX.CONFIG.KEY_CODE_LEFT:c.x=-1*b;break;case ORYX.CONFIG.KEY_CODE_RIGHT:c.x=b;break;case ORYX.CONFIG.KEY_CODE_UP:c.y=-1*b;break;case ORYX.CONFIG.KEY_CODE_DOWN:c.y=b;break}m=m.findAll(function(e){if(e instanceof ORYX.Core.Node&&e.dockers.length==1&&m.include(e.dockers.first().getDockedShape())){return false}var o=e.parent;do{if(m.include(o)){return false}}while(o=o.parent);return true});var f=true;var h=m.all(function(e){if(e instanceof ORYX.Core.Edge){if(e.isDocked()){f=false}return true}return false});if(h&&!f){return}m=m.map(function(o){if(o instanceof ORYX.Core.Node){return o}else{if(o instanceof ORYX.Core.Edge){var e=o.dockers;if(m.include(o.dockers.first().getDockedShape())){e=e.without(o.dockers.first())}if(m.include(o.dockers.last().getDockedShape())){e=e.without(o.dockers.last())}return e}else{return null}}}).flatten().compact();if(m.size()>0){var a=[this.facade.getCanvas().bounds.lowerRight().x,this.facade.getCanvas().bounds.lowerRight().y,0,0];m.each(function(e){a[0]=Math.min(a[0],e.bounds.upperLeft().x);a[1]=Math.min(a[1],e.bounds.upperLeft().y);a[2]=Math.max(a[2],e.bounds.lowerRight().x);a[3]=Math.max(a[3],e.bounds.lowerRight().y)});if(a[0]+c.x<0){c.x=-a[0]}if(a[1]+c.y<0){c.y=-a[1]}if(a[2]+c.x>this.facade.getCanvas().bounds.lowerRight().x){c.x=this.facade.getCanvas().bounds.lowerRight().x-a[2]}if(a[3]+c.y>this.facade.getCanvas().bounds.lowerRight().y){c.y=this.facade.getCanvas().bounds.lowerRight().y-a[3]}if(c.x!=0||c.y!=0){var d=[new ORYX.Core.Command.Move(m,c,null,g,this)];this.facade.executeCommands(d)}}},getUndockedCommant:function(b){var a=ORYX.Core.Command.extend({construct:function(c){this.dockers=c.collect(function(d){return d instanceof ORYX.Core.Controls.Docker?{docker:d,dockedShape:d.getDockedShape(),refPoint:d.referencePoint}:undefined}).compact()},execute:function(){this.dockers.each(function(c){c.docker.setDockedShape(undefined)})},rollback:function(){this.dockers.each(function(c){c.docker.setDockedShape(c.dockedShape);c.docker.setReferencePoint(c.refPoint)})}});command=new a(b);command.execute();return command},});if(!ORYX.Plugins){ORYX.Plugins={}}if(!ORYX.Plugins.Layouter){ORYX.Plugins.Layouter={}}new function(){ORYX.Plugins.Layouter.EdgeLayouter=ORYX.Plugins.AbstractLayouter.extend({layouted:[\"http://b3mn.org/stencilset/bpmn1.1#SequenceFlow\",\"http://b3mn.org/stencilset/bpmn1.1#MessageFlow\",\"http://b3mn.org/stencilset/timjpdl3#SequenceFlow\",\"http://b3mn.org/stencilset/jbpm4#SequenceFlow\",\"http://b3mn.org/stencilset/bpmn2.0#MessageFlow\",\"http://b3mn.org/stencilset/bpmn2.0#SequenceFlow\",\"http://b3mn.org/stencilset/bpmn2.0choreography#MessageFlow\",\"http://b3mn.org/stencilset/bpmn2.0choreography#SequenceFlow\",\"http://b3mn.org/stencilset/bpmn2.0conversation#ConversationLink\",\"http://b3mn.org/stencilset/epc#ControlFlow\",\"http://www.signavio.com/stencilsets/processmap#ProcessLink\",\"http://www.signavio.com/stencilsets/organigram#connection\"],layout:function(a){a.each(function(b){this.doLayout(b)}.bind(this))},doLayout:function(b){var d=b.getIncomingNodes()[0];var c=b.getOutgoingNodes()[0];if(!d||!c){return}var a=this.getPositions(d,c,b);if(a.length>0){this.setDockers(b,a[0].a,a[0].b)}},getPositions:function(r,s,e){var u=r.absoluteBounds();var n=s.absoluteBounds();var q=u.center();var o=n.center();var l=u.midPoint();var d=n.midPoint();var k=Object.clone(e.dockers.first().referencePoint);var t=Object.clone(e.dockers.last().referencePoint);var c=e.dockers.first().getAbsoluteReferencePoint();var p=e.dockers.last().getAbsoluteReferencePoint();if(Math.abs(c.x-p.x)<1||Math.abs(c.y-p.y)<1){return[]}var g={};g.x=q.x<o.x?(((o.x-n.width()/2)-(q.x+u.width()/2))/2)+(q.x+u.width()/2):(((q.x-u.width()/2)-(o.x+n.width()/2))/2)+(o.x+n.width()/2);g.y=q.y<o.y?(((o.y-n.height()/2)-(q.y+u.height()/2))/2)+(q.y+u.height()/2):(((q.y-u.height()/2)-(o.y+n.height()/2))/2)+(o.y+n.height()/2);u.widen(5);n.widen(20);var h=[];var f=this.getOffset.bind(this);if(!u.isIncluded(o.x,q.y)&&!n.isIncluded(o.x,q.y)){h.push({a:{x:o.x+f(t,d,\"x\"),y:q.y+f(k,l,\"y\")},z:this.getWeight(r,q.x<o.x?\"r\":\"l\",s,q.y<o.y?\"t\":\"b\",e)})}if(!u.isIncluded(q.x,o.y)&&!n.isIncluded(q.x,o.y)){h.push({a:{x:q.x+f(k,l,\"x\"),y:o.y+f(t,d,\"y\")},z:this.getWeight(r,q.y<o.y?\"b\":\"t\",s,q.x<o.x?\"l\":\"r\",e)})}if(!u.isIncluded(g.x,q.y)&&!n.isIncluded(g.x,o.y)){h.push({a:{x:g.x,y:q.y+f(k,l,\"y\")},b:{x:g.x,y:o.y+f(t,d,\"y\")},z:this.getWeight(r,\"r\",s,\"l\",e,q.x>o.x)})}if(!u.isIncluded(q.x,g.y)&&!n.isIncluded(o.x,g.y)){h.push({a:{x:q.x+f(k,l,\"x\"),y:g.y},b:{x:o.x+f(t,d,\"x\"),y:g.y},z:this.getWeight(r,\"b\",s,\"t\",e,q.y>o.y)})}return h.sort(function(v,m){return v.z<m.z?1:(v.z==m.z?-1:-1)})},getOffset:function(c,b,a){return c[a]-b[a]},getWeight:function(m,b,n,a,d,g){b=(b||\"\").toLowerCase();a=(a||\"\").toLowerCase();if(![\"t\",\"r\",\"b\",\"l\"].include(b)){b=\"r\"}if(![\"t\",\"r\",\"b\",\"l\"].include(a)){b=\"l\"}if(g){b=b==\"t\"?\"b\":(b==\"r\"?\"l\":(b==\"b\"?\"t\":(b==\"l\"?\"r\":\"r\")));a=a==\"t\"?\"b\":(a==\"r\"?\"l\":(a==\"b\"?\"t\":(a==\"l\"?\"r\":\"r\")))}var f=0;var p=this.facade.getRules().getLayoutingRules(m,d)[\"out\"];var o=this.facade.getRules().getLayoutingRules(n,d)[\"in\"];var e=p[b];var c=o[a];var l=function(s,r,q){switch(s){case\"t\":return Math.abs(r.x-q.x)<2&&r.y<q.y;case\"r\":return r.x>q.x&&Math.abs(r.y-q.y)<2;case\"b\":return Math.abs(r.x-q.x)<2&&r.y>q.y;case\"l\":return r.x<q.x&&Math.abs(r.y-q.y)<2;default:return false}};var k=m.getIncomingShapes().findAll(function(q){return q instanceof ORYX.Core.Edge}).any(function(q){return l(b,q.dockers[q.dockers.length-2].bounds.center(),q.dockers.last().bounds.center())});var h=n.getOutgoingShapes().findAll(function(q){return q instanceof ORYX.Core.Edge}).any(function(q){return l(a,q.dockers[1].bounds.center(),q.dockers.first().bounds.center())});return(k||h?0:e+c)},setDockers:function(e,d,c){if(!e){return}e.dockers.each(function(a){e.removeDocker(a)});[d,c].compact().each(function(b){var a=e.createDocker(undefined,b);a.bounds.centerMoveTo(b)});e.dockers.each(function(a){a.update()});e._update(true)}})}();if(!ORYX.Plugins){ORYX.Plugins=new Object()}new function(){ORYX.Plugins.BPMN2_0={construct:function(b){this.facade=b;this.facade.registerOnEvent(ORYX.CONFIG.EVENT_DRAGDOCKER_DOCKED,this.handleDockerDocked.bind(this));this.facade.registerOnEvent(ORYX.CONFIG.EVENT_PROPWINDOW_PROP_CHANGED,this.handlePropertyChanged.bind(this));this.facade.registerOnEvent(\"layout.bpmn2_0.pool\",this.handleLayoutPool.bind(this));this.facade.registerOnEvent(\"layout.bpmn2_0.subprocess\",this.handleSubProcess.bind(this));this.facade.registerOnEvent(ORYX.CONFIG.EVENT_SHAPEREMOVED,this.handleShapeRemove.bind(this));this.facade.registerOnEvent(ORYX.CONFIG.EVENT_LOADED,this.afterLoad.bind(this));this.namespace=undefined},afterLoad:function(){this.facade.getCanvas().getChildNodes().each(function(b){if(b.getStencil().id().endsWith(\"Pool\")){this.handleLayoutPool({shape:b})}}.bind(this))},onSelectionChanged:function(h){var f=h.elements;if(f&&f.length===1){var e=this.getNamespace();var b=f[0];if(b.getStencil().idWithoutNs()===\"Pool\"){if(b.getChildNodes().length===0){var d={type:e+\"Lane\",position:{x:0,y:0},namespace:b.getStencil().namespace(),parent:b};this.facade.createShape(d);this.facade.getCanvas().update();this.facade.setSelection([b])}}}if(f.any(function(l){return l instanceof ORYX.Core.Node&&l.getStencil().id().endsWith(\"Lane\")})){var c=f.findAll(function(l){return l instanceof ORYX.Core.Node&&l.getStencil().id().endsWith(\"Lane\")});var g=[];var k=[];c.each(function(l){g.push(this.getParentPool(l))}.bind(this));g=g.uniq().findAll(function(l){var m=this.getLanes(l,true);if(m.all(function(n){return c.include(n)})){k=k.concat(m);return true}else{if(f.include(l)&&m.any(function(n){return c.include(n)})){k=k.concat(m);return true}else{return false}}}.bind(this));if(k.length>0&&g.length>0){f=f.without.apply(f,k);f=f.concat(g);this.facade.setSelection(f.uniq())}}},handleShapeRemove:function(e){var f=e.shape;var l=e.parent;if(f instanceof ORYX.Core.Node&&f.getStencil().idWithoutNs()===\"Lane\"&&this.facade.isExecutingCommands()){var g=this.getParentPool(l);if(g&&g.parent){var h=function(m){return !m.getChildNodes().any(function(n){return n.getStencil().idWithoutNs()===\"Lane\"})};var c=h(f);var k=l.getChildNodes().any(function(m){return m.getStencil().idWithoutNs()===\"Lane\"});if(c&&k){var d=new a(f,l,g,this);this.facade.executeCommands([d])}else{if(!c&&!this.facade.getSelection().any(function(m){return m instanceof ORYX.Core.Node&&m.getStencil().idWithoutNs()===\"Lane\"&&m.isParent(f)&&h(m)})){var b=ORYX.Core.Command.extend({construct:function(m,n){this.children=m.getChildNodes(true);this.facade=n},execute:function(){this.children.each(function(m){m.bounds.moveBy(30,0)})},rollback:function(){this.children.each(function(m){m.bounds.moveBy(-30,0)})}});this.facade.executeCommands([new b(f,this.facade)])}else{if(c&&!k&&l==g){l.add(f)}}}}}},hashedSubProcesses:{},hashChildShapes:function(b){var c=b.getChildNodes();c.each(function(d){if(this.hashedSubProcesses[d.id]){this.hashedSubProcesses[d.id]=d.absoluteXY();this.hashedSubProcesses[d.id].width=d.bounds.width();this.hashedSubProcesses[d.id].height=d.bounds.height();this.hashChildShapes(d)}}.bind(this))},handleSubProcess:function(d){var c=d.shape;if(!this.hashedSubProcesses[c.id]){this.hashedSubProcesses[c.id]=c.absoluteXY();this.hashedSubProcesses[c.id].width=c.bounds.width();this.hashedSubProcesses[c.id].height=c.bounds.height();return}var e=c.absoluteXY();e.x-=this.hashedSubProcesses[c.id].x;e.y-=this.hashedSubProcesses[c.id].y;var b=this.hashedSubProcesses[c.id].width!==c.bounds.width()||this.hashedSubProcesses[c.id].height!==c.bounds.height();this.hashedSubProcesses[c.id]=c.absoluteXY();this.hashedSubProcesses[c.id].width=c.bounds.width();this.hashedSubProcesses[c.id].height=c.bounds.height();this.hashChildShapes(c);if(this.facade.isExecutingCommands()&&!b){this.moveChildDockers(c,e)}},moveChildDockers:function(d,g){if(!g.x&&!g.y){return}var e=d.getChildNodes(true);var c=e.map(function(h){return[].concat(h.getIncomingShapes()).concat(h.getOutgoingShapes())}).flatten().uniq().map(function(h){return h.dockers.length>2?h.dockers.slice(1,h.dockers.length-1):[]}).flatten();var b=d.absoluteBounds();b.moveBy(-g.x,-g.y);var f={};c.each(function(m){if(m.isChanged){return}var k=Object.clone(g);if(!b.isIncluded(m.bounds.center())){var o=m.parent.dockers.indexOf(m);var s=m.parent.dockers.length;var q=m.parent.getSource();var r=m.parent.getTarget();var l=e.include(q)&&e.include(r);if(!l){var n=o!==0?b.isIncluded(m.parent.dockers[o-1].bounds.center()):false;var p=o!==s-1?b.isIncluded(m.parent.dockers[o+1].bounds.center()):false;if(!n&&!p){return}var h=m.parent.dockers[n?o-1:o+1];if(Math.abs(-Math.abs(h.bounds.center().x-m.bounds.center().x))<2){k.y=0}else{if(Math.abs(-Math.abs(h.bounds.center().y-m.bounds.center().y))<2){k.x=0}else{return}}}}f[m.getId()]={docker:m,offset:k}});this.facade.executeCommands([new ORYX.Core.MoveDockersCommand(f)])},handleDockerDocked:function(d){var e=this.getNamespace();var f=d.parent;var c=d.target;if(f.getStencil().id()===e+\"SequenceFlow\"){var b=c.getStencil().groups().find(function(g){if(g==\"Gateways\"){return g}});if(!b&&(f.properties[\"oryx-conditiontype\"]==\"Expression\")){f.setProperty(\"oryx-showdiamondmarker\",true)}else{f.setProperty(\"oryx-showdiamondmarker\",false)}this.facade.getCanvas().update()}},handlePropertyChanged:function(e){var d=this.getNamespace();var c=e.elements;var f=e.key;var b=e.value;var g=false;c.each(function(k){if((k.getStencil().id()===d+\"SequenceFlow\")&&(f===\"oryx-conditiontype\")){if(b!=\"Expression\"){k.setProperty(\"oryx-showdiamondmarker\",false)}else{var l=k.getIncomingShapes();if(!l){k.setProperty(\"oryx-showdiamondmarker\",true)}var h=l.find(function(m){var n=m.getStencil().groups().find(function(o){if(o==\"Gateways\"){return o}});if(n){return n}});if(!h){k.setProperty(\"oryx-showdiamondmarker\",true)}else{k.setProperty(\"oryx-showdiamondmarker\",false)}}g=true}}.bind(this));if(g){this.facade.getCanvas().update()}},hashedPoolPositions:{},hashedLaneDepth:{},hashedBounds:{},hashedPositions:{},handleLayoutPool:function(u){var o=u.shape;var F=this.facade.getSelection();var w=F.include(o)?o:F.first();w=w||o;this.currentPool=o;if(!(w.getStencil().id().endsWith(\"Pool\")||w.getStencil().id().endsWith(\"Lane\"))){return}if(w!==o&&!w.isParent(o)&&!this.hashedBounds[o.id][w.id]){return}if(!this.hashedBounds[o.id]){this.hashedBounds[o.id]={}}var A=this.getLanes(o);if(A.length<=0){return}var z=this.getLanes(o,true),b;var g=z.clone();var k=$H({});z.each(function(x){k[x.id]=x.bounds.upperLeft()});if(A.length===1&&this.getLanes(A.first()).length<=0){A.first().setProperty(\"oryx-showcaption\",A.first().properties[\"oryx-name\"].trim().length>0);var d=A.first().node.getElementsByTagName(\"rect\");d[0].setAttributeNS(null,\"display\",\"none\")}else{z.invoke(\"setProperty\",\"oryx-showcaption\",true);z.each(function(x){var y=x.node.getElementsByTagName(\"rect\");y[0].removeAttributeNS(null,\"display\")})}var t=[];var n=[];var v=-1;while(++v<z.length){if(!this.hashedBounds[o.id][z[v].id]){n.push(z[v])}}if(n.length>0){w=n.first()}var C=$H(this.hashedBounds[o.id]).keys();var v=-1;while(++v<C.length){if(!z.any(function(x){return x.id==C[v]})){t.push(this.hashedBounds[o.id][C[v]]);F=F.without(function(x){return x.id==C[v]})}}var q,s,m,l;if(t.length>0||n.length>0){if(n.length===1&&this.getLanes(n[0].parent).length===1){q=this.adjustHeight(A,n[0].parent)}else{q=this.updateHeight(o)}s=this.adjustWidth(A,o.bounds.width());o.update()}else{if(o==w){if(F.length===1&&this.isResized(o,this.hashedPoolPositions[o.id])){var B=this.hashedPoolPositions[o.id].upperLeft();var f=o.bounds.upperLeft();var E=0;if(this.shouldScale(o)){var c=this.hashedPoolPositions[o.id];E=c.height()/o.bounds.height()}this.adjustLanes(o,z,B.x-f.x,B.y-f.y,E)}q=this.adjustHeight(A,undefined,o.bounds.height());s=this.adjustWidth(A,o.bounds.width())}else{if(F.length===1&&this.isResized(w,this.hashedBounds[o.id][w.id])){var B=this.hashedBounds[o.id][w.id].upperLeft();var f=w.absoluteXY();m=B.x-f.x;l=B.y-f.y;if(m||l){g=g.without(w);this.adjustLanes(o,this.getAllExcludedLanes(o,w),m,0)}var h=this.getLanes(w,true);if(h.length>0){if(this.shouldScale(w)){var c=this.hashedBounds[o.id][w.id];var E=c.height()/w.bounds.height();this.adjustLanes(o,h,m,l,E)}else{this.adjustLanes(o,h,m,l,0)}}}var D=z.map(function(x){return{shape:x,bounds:x.bounds.clone()}});q=this.adjustHeight(A,w);this.checkForChanges(z,D);s=this.adjustWidth(A,w.bounds.width()+(this.getDepth(w,o)*30))}}this.setDimensions(o,s,q,m,l);if(this.facade.isExecutingCommands()&&(t.length===0||n.length!==0)){this.updateDockers(g,o);if(this.hashedPositions[o.id]&&this.hashedPositions[o.id].keys().any(function(y,x){return(z[x]||{}).id!==y})){var r=ORYX.Core.Command.extend({construct:function(H,G,y,I,x){this.originPosition=Object.clone(H);this.newPosition=Object.clone(G);this.lanes=y;this.plugin=I;this.pool=x},execute:function(){if(!this.executed){this.executed=true;this.lanes.each(function(x){if(this.newPosition[x.id]){x.bounds.moveTo(this.newPosition[x.id])}}.bind(this));this.plugin.hashedPositions[this.pool]=Object.clone(this.newPosition)}},rollback:function(){this.lanes.each(function(x){if(this.originPosition[x.id]){x.bounds.moveTo(this.originPosition[x.id])}}.bind(this));this.plugin.hashedPositions[this.pool]=Object.clone(this.originPosition)}});var p=$H({});z.each(function(x){p[x.id]=x.bounds.upperLeft()});var e=new r(k,p,z,this,o.id);this.facade.executeCommands([e])}}this.hashedBounds[o.id]={};this.hashedPositions[o.id]=k;var v=-1;while(++v<z.length){this.hashedBounds[o.id][z[v].id]=z[v].absoluteBounds();this.hashChildShapes(z[v]);this.hashedLaneDepth[z[v].id]=this.getDepth(z[v],o);this.forceToUpdateLane(z[v])}this.hashedPoolPositions[o.id]=o.bounds.clone()},shouldScale:function(b){var c=b.getChildNodes().findAll(function(d){return d.getStencil().id().endsWith(\"Lane\")});return c.length>1||c.any(function(d){return this.shouldScale(d)}.bind(this))},checkForChanges:function(b,c){if(this.facade.isExecutingCommands()&&c.any(function(e){return e.shape.bounds.toString()!==e.bounds.toString()})){var d=ORYX.Core.Command.extend({construct:function(e){this.oldState=e;this.newState=e.map(function(f){return{shape:f.shape,bounds:f.bounds.clone()}})},execute:function(){if(this.executed){this.applyState(this.newState)}this.executed=true},rollback:function(){this.applyState(this.oldState)},applyState:function(e){e.each(function(f){f.shape.bounds.set(f.bounds.upperLeft(),f.bounds.lowerRight())})}});this.facade.executeCommands([new d(c)])}},isResized:function(b,d){if(!d||!b){return false}var c=d;return Math.round(c.width()-b.bounds.width())!==0||Math.round(c.height()-b.bounds.height())!==0},adjustLanes:function(d,c,b,f,e){e=e||0;c.each(function(g){g.getChildNodes().each(function(k){if(!k.getStencil().id().endsWith(\"Lane\")){var h=e?k.bounds.center().y-(k.bounds.center().y/e):-f;k.bounds.moveBy((b||0),-h);if(e&&k.getStencil().id().endsWith(\"Subprocess\")){this.moveChildDockers(k,{x:(0),y:-h})}}}.bind(this));this.hashedBounds[d.id][g.id].moveBy(-(b||0),!e?-f:0);if(e){g.isScaled=true}}.bind(this))},getAllExcludedLanes:function(d,b){var c=[];d.getChildNodes().each(function(e){if((!b||e!==b)&&e.getStencil().id().endsWith(\"Lane\")){c.push(e);c=c.concat(this.getAllExcludedLanes(e,b))}}.bind(this));return c},forceToUpdateLane:function(b){if(b.bounds.height()!==b._svgShapes[0].height){b.isChanged=true;b.isResized=true;b._update()}},getDepth:function(d,c){var b=0;while(d&&d.parent&&d!==c){d=d.parent;++b}return b},updateDepth:function(c,b,d){var e=(b-d)*30;c.getChildNodes().each(function(f){f.bounds.moveBy(e,0);[].concat(children[j].getIncomingShapes()).concat(children[j].getOutgoingShapes())})},setDimensions:function(e,f,c,b,g){var d=e.getStencil().id().endsWith(\"Lane\");e.bounds.set(d?30:(e.bounds.a.x-(b||0)),d?e.bounds.a.y:(e.bounds.a.y-(g||0)),f?e.bounds.a.x+f-(d?30:(b||0)):e.bounds.b.x,c?e.bounds.a.y+c-(d?0:(g||0)):e.bounds.b.y)},setLanePosition:function(b,c){b.bounds.moveTo(30,c)},adjustWidth:function(b,c){(b||[]).each(function(d){this.setDimensions(d,c);this.adjustWidth(this.getLanes(d),c-30)}.bind(this));return c},adjustHeight:function(e,g,c){var h=0;if(!g&&c){var f=-1;while(++f<e.length){h+=e[f].bounds.height()}}var f=-1;var b=0;while(++f<e.length){if(e[f]===g){this.adjustHeight(this.getLanes(e[f]),undefined,e[f].bounds.height());e[f].bounds.set({x:30,y:b},{x:e[f].bounds.width()+30,y:e[f].bounds.height()+b})}else{if(!g&&c){var d=(e[f].bounds.height()*c)/h;this.adjustHeight(this.getLanes(e[f]),undefined,d);this.setDimensions(e[f],null,d);this.setLanePosition(e[f],b)}else{var d=this.adjustHeight(this.getLanes(e[f]),g,c);if(!d){d=e[f].bounds.height()}this.setDimensions(e[f],null,d);this.setLanePosition(e[f],b)}}b+=e[f].bounds.height()}return b},updateHeight:function(c){var d=this.getLanes(c);if(d.length==0){return c.bounds.height()}var b=0;var e=-1;while(++e<d.length){this.setLanePosition(d[e],b);b+=this.updateHeight(d[e])}this.setDimensions(c,null,b);return b},getOffset:function(b,d,c){var f={x:0,y:0};var f=b.absoluteXY();var e=this.hashedBounds[c.id][b.id]||(d===true?this.hashedPoolPositions[b.id]:undefined);if(e){f.x-=e.upperLeft().x;f.y-=e.upperLeft().y}else{return{x:0,y:0}}return f},getNextLane:function(b){while(b&&!b.getStencil().id().endsWith(\"Lane\")){if(b instanceof ORYX.Core.Canvas){return null}b=b.parent}return b},getParentPool:function(b){while(b&&!b.getStencil().id().endsWith(\"Pool\")){if(b instanceof ORYX.Core.Canvas){return null}b=b.parent}return b},updateDockers:function(B,t){var r=t.absoluteBounds(),v=[];var s=(this.hashedPoolPositions[t.id]||r).clone();var A=-1,z=-1,y=-1,w=-1,u;var C={};while(++A<B.length){if(!this.hashedBounds[t.id][B[A].id]){continue}var d=B[A].isScaled;delete B[A].isScaled;var h=B[A].getChildNodes();var p=B[A].absoluteBounds();var e=(this.hashedBounds[t.id][B[A].id]||p);var m=this.getOffset(B[A],true,t);var f=0;var E=this.getDepth(B[A],t);if(this.hashedLaneDepth[B[A].id]!==undefined&&this.hashedLaneDepth[B[A].id]!==E){f=(this.hashedLaneDepth[B[A].id]-E)*30;m.x+=f}z=-1;while(++z<h.length){if(f&&!h[z].getStencil().id().endsWith(\"Lane\")){v.push({xOffset:f,shape:h[z]});h[z].bounds.moveBy(f,0)}if(h[z].getStencil().id().endsWith(\"Subprocess\")){this.moveChildDockers(h[z],m)}var c=[].concat(h[z].getIncomingShapes()).concat(h[z].getOutgoingShapes()).findAll(function(k){return k instanceof ORYX.Core.Edge});y=-1;while(++y<c.length){if(c[y].getStencil().id().endsWith(\"MessageFlow\")){this.layoutEdges(h[z],[c[y]],m);continue}w=-1;while(++w<c[y].dockers.length){u=c[y].dockers[w];if(u.getDockedShape()||u.isChanged){continue}pos=u.bounds.center();var b=e.isIncluded(pos);var q=!s.isIncluded(pos);var g=w==0?b:e.isIncluded(c[y].dockers[w-1].bounds.center());var n=w==c[y].dockers.length-1?b:e.isIncluded(c[y].dockers[w+1].bounds.center());var D=Object.clone(m);if(d&&b&&this.isResized(B[A],this.hashedBounds[t.id][B[A].id])){var x=(pos.y-p.upperLeft().y+D.y);D.y-=(x-(x*(p.height()/e.height())))}if(b){C[u.id]={docker:u,offset:D}}}}}}var o=ORYX.Core.Command.extend({construct:function(k){this.state=k},execute:function(){if(this.executed){this.state.each(function(k){k.shape.bounds.moveBy(k.xOffset,0)})}this.executed=true},rollback:function(){this.state.each(function(k){k.shape.bounds.moveBy(-k.xOffset,0)})}});this.facade.executeCommands([new ORYX.Core.MoveDockersCommand(C),new o(v)])},moveBy:function(c,b){c.x+=b.x;c.y+=b.y;return c},getHashedBounds:function(b){return this.currentPool&&this.hashedBounds[this.currentPool.id][b.id]?this.hashedBounds[this.currentPool.id][b.id]:b.absoluteBounds()},getLanes:function(b,d){var e=this.getNamespace();var c=b.getChildNodes(d||false).findAll(function(f){return(f.getStencil().id()===e+\"Lane\")});c=c.sort(function(w,u){var v=Math.round(w.bounds.upperLeft().y);var p=Math.round(u.bounds.upperLeft().y);var s=Math.round(w.bounds.lowerRight().y);var m=Math.round(u.bounds.lowerRight().y);var h=this.getHashedBounds(w);var g=this.getHashedBounds(u);var o=Math.round(h.upperLeft().y);var y=Math.round(g.upperLeft().y);var l=Math.round(h.lowerRight().y);var x=Math.round(g.lowerRight().y);if(v==p&&s==m){v=o;p=y;s=l;m=x}if(Math.round(w.bounds.height()-h.height())===0&&Math.round(u.bounds.height()-g.height())===0){return v<p?-1:(v>p?1:0)}var t=v<p&&s<m;var q=v>p&&s>m;var k=v<p&&s>=m&&l<x;var n=v>=p&&s<m&&o<y;var r=v>p&&s<=m&&l>x;var f=v<=p&&s>m&&o>y;return(t||k||n?-1:(q||r||f?1:0))}.bind(this));return c},getNamespace:function(){if(!this.namespace){var b=this.facade.getStencilSets();if(b.keys()){this.namespace=b.keys()[0]}else{return undefined}}return this.namespace}};var a=ORYX.Core.Command.extend({construct:function(b,d,c,e){this.facade=e.facade;this.plugin=e;this.shape=b;this.changes;this.pool=c;this.parent=d;this.shapeChildren=[];this.shape.getChildShapes().each(function(f){this.shapeChildren.push({shape:f,bounds:{a:{x:f.bounds.a.x,y:f.bounds.a.y},b:{x:f.bounds.b.x,y:f.bounds.b.y}}})}.bind(this));this.shapeUpperLeft=this.shape.bounds.upperLeft();this.parentHeight=this.parent.bounds.height()},getLeafLanes:function(b){var c=this.plugin.getLanes(b).map(function(d){return this.getLeafLanes(d)}.bind(this)).flatten();return c.length>0?c:[b]},findNewLane:function(){var b=this.plugin.getLanes(this.parent);var c=this.getLeafLanes(this.parent);this.lane=c.find(function(d){return d.bounds.upperLeft().y>=this.shapeUpperLeft.y}.bind(this))||c.last();this.laneUpperLeft=this.lane.bounds.upperLeft()},execute:function(){if(this.changes){this.executeAgain();return}if(!this.lane){this.findNewLane()}if(this.lane){var f=this.laneUpperLeft;var d=this.shapeUpperLeft;var c=this.plugin.getDepth(this.lane,this.parent)-1;this.changes=$H({});if(f.y>=d.y){this.lane.getChildShapes().each(function(g){if(!this.changes[g.getId()]){this.changes[g.getId()]=this.computeChanges(g,this.lane,this.lane,this.shape.bounds.height())}g.bounds.moveBy(0,this.shape.bounds.height())}.bind(this));this.plugin.hashChildShapes(this.lane);this.shapeChildren.each(function(g){g.shape.bounds.set(g.bounds);g.shape.bounds.moveBy((d.x-30)-(c*30),0);if(!this.changes[g.shape.getId()]){this.changes[g.shape.getId()]=this.computeChanges(g.shape,this.shape,this.lane,0)}this.lane.add(g.shape)}.bind(this));this.lane.bounds.moveBy(0,d.y-f.y)}else{if(d.y>f.y){this.shapeChildren.each(function(g){g.shape.bounds.set(g.bounds);g.shape.bounds.moveBy((d.x-30)-(c*30),this.lane.bounds.height());if(!this.changes[g.shape.getId()]){this.changes[g.shape.getId()]=this.computeChanges(g.shape,this.shape,this.lane,0)}this.lane.add(g.shape)}.bind(this))}}}var e=this.lane.bounds.height();var b=this.lane.length===1?this.parentHeight:this.lane.bounds.height()+this.shape.bounds.height();this.setHeight(b,e,this.parent,this.parentHeight,true);this.plugin.getLanes(this.parent).each(function(g){if(!this.changes[g.getId()]&&g!==this.lane&&g!==this.shape){this.changes[g.getId()]=this.computeChanges(g,this.parent,this.parent,0)}}.bind(this));this.update()},setHeight:function(b,f,e,d,c){this.plugin.setDimensions(this.lane,this.lane.bounds.width(),b);this.plugin.hashedBounds[this.pool.id][this.lane.id]=this.lane.absoluteBounds();this.plugin.adjustHeight(this.plugin.getLanes(e),this.lane);if(c===true){this.changes[this.shape.getId()]=this.computeChanges(this.shape,e,e,0,f,b)}this.plugin.setDimensions(e,e.bounds.width(),d);if(e!==this.pool){this.plugin.setDimensions(this.pool,this.pool.bounds.width(),this.pool.bounds.height()+(b-f))}},update:function(){this.plugin.hashedBounds[this.pool.id][\"REMOVED\"]=true},rollback:function(){var c=this.laneUpperLeft;var b=this.shapeUpperLeft;this.changes.each(function(h){var g=h.value.oldParent;var e=h.value.shape;var f=h.value.parentHeight;var k=h.value.oldHeight;var d=h.value.newHeight;if(e.getStencil().id().endsWith(\"Lane\")){e.bounds.moveTo(h.value.oldPosition)}if(k){this.setHeight(k,d,g,g.bounds.height()+(k-d));if(c.y>=b.y){this.lane.bounds.moveBy(0,this.shape.bounds.height()-1)}}else{g.add(e);e.bounds.moveTo(h.value.oldPosition)}}.bind(this))},executeAgain:function(){this.changes.each(function(f){var d=f.value.newParent;var c=f.value.shape;var b=f.value.newHeight;var h=f.value.oldHeight;if(b){var g=this.laneUpperLeft.y;var e=this.shapeUpperLeft.y;if(g>=e){this.lane.bounds.moveBy(0,e-g)}this.setHeight(b,h,d,d.bounds.height()+(b-h))}else{d.add(c);c.bounds.moveTo(f.value.newPosition)}}.bind(this));this.update()},computeChanges:function(d,l,k,c,m,b){l=this.changes[d.getId()]?this.changes[d.getId()].oldParent:l;var h=this.changes[d.getId()]?this.changes[d.getId()].oldPosition:d.bounds.upperLeft();var f=d.bounds.upperLeft();var e={x:f.x,y:f.y+c};var g={shape:d,parentHeight:l.bounds.height(),oldParent:l,oldPosition:h,oldHeight:m,newParent:k,newPosition:e,newHeight:b};return g}});ORYX.Plugins.BPMN2_0=ORYX.Plugins.AbstractPlugin.extend(ORYX.Plugins.BPMN2_0)}();"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/editor-config.js",
    "content": "/*\n * Activiti Modeler component part of the Activiti project\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * \n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n */\n'use strict';\n\nvar KISBPM = KISBPM || {};\n\nKISBPM.CONFIG = {\n\t\t'showRemovedProperties' : false\n};\n\nKISBPM.HEADER_CONFIG = {\n\t\t'showAppTitle' : true,\n\t\t'showHeaderMenu' : true,\n\t\t'showMainNavigation' : true,\n\t\t'showPageHeader' : true\n};"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/editor-controller.js",
    "content": "/*\n * Activiti Modeler component part of the Activiti project\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * \n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n */\n'use strict';\n\nangular.module('activitiModeler')\n.controller('EditorUnsavedChangesPopupCrtl', ['$rootScope', '$scope', '$http', '$location', '$window', function ($rootScope, $scope, $http, $location, $window) {\n   \n\t$scope.ok = function () {\n\t\tif ($scope.handleResponseFunction) {\n\t\t\t$scope.handleResponseFunction(true);\n\n            // Also clear any 'onbeforeunload', added by oryx\n            $window.onbeforeunload = undefined;\n\t\t}\n\t\t$scope.$hide();\n\t};\n\n\t$scope.cancel = function () {\n\t\tif ($scope.handleResponseFunction) {\n\t\t\t$scope.handleResponseFunction(false);\n\t\t}\n        $scope.$hide();\n\t};\n}]);\n\nactivitiModule\n.directive('autoFocus', ['$timeout', '$parse', function($timeout, $parse) {\n    return {\n        restrict: 'AC',\n        compile: function($element, attr) {\n\n            return function(_scope, _element, _attrs) {\n                var firstChild = (_attrs.focusFirstChild !== undefined);\n                $timeout(function () {\n                    if (firstChild) {\n                        // look for first input-element in child-tree and focus that\n                        var inputs = _element.find('input');\n                        if (inputs && inputs.length > 0) {\n                            inputs[0].focus();\n                        }\n                    } else {\n                        // Focus element where the directive is put on\n                        _element[0].focus();\n                    }\n                }, 100);\n            }\n        }\n    };\n}]);\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/editor-utils.js",
    "content": "/*\n * Activiti Modeler component part of the Activiti project\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * \n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n */\n\n/**\n * Utility methods are grouped together here.\n */\nvar EDITOR = EDITOR || {};\n\nEDITOR.UTIL = {\n\n    getParameterByName: function (name) {\n        name = name.replace(/[\\[]/, \"\\\\[\").replace(/[\\]]/, \"\\\\]\");\n        var regex = new RegExp(\"[\\\\?&]\" + name + \"=([^&#]*)\"),\n            results = regex.exec(location.search);\n        return results == null ? \"\" : decodeURIComponent(results[1].replace(/\\+/g, \" \"));\n    },\n\n    /**\n     * Starts at the provided start element, and walks all preceding elements in the graph.\n     * Each element is tested to have a certain property and, if it has, adds this property value\n     * to the return result list.\n     */\n    collectPropertiesFromPrecedingElements: function (startElement, propertyType) {\n        var visitedElements = [];\n        var collectedProperties = [];\n        EDITOR.UTIL._visitElementAndCollectProperty(startElement, propertyType, visitedElements, collectedProperties);\n        return collectedProperties;\n    },\n\n    /**\n     * Starts at the provided start element, and walks all preceding elements in the graph.\n     * Each element is tested to be a specific stencil id and, if it has, adds the element\n     * to the return result list.\n     */\n    collectElementsFromPrecedingElements: function (startElement, stencilId) {\n        var visitedElements = [];\n        var collectedElements = [];\n\n        var incomingShapesIterator = startElement.getIncomingShapes();\n        if (incomingShapesIterator) {\n            for (var i = 0; i < incomingShapesIterator.length; i++) {\n                var incomingShape = incomingShapesIterator[i];\n                if (visitedElements.indexOf(incomingShape.id) < 0) {\n                    EDITOR.UTIL._visitElementAndCollectElement(incomingShape, stencilId, visitedElements, collectedElements);\n                }\n            }\n        }\n\n        return collectedElements;\n    },\n\n    _visitElementAndCollectProperty: function (element, propertyType, visitedElementsArray, collectedProperties) {\n\n        visitedElementsArray.push(element.id);\n\n        var property = element.properties[propertyType]\n        if (property) {\n            collectedProperties.push(property);\n        }\n\n        var incomingShapesIterator = element.getIncomingShapes();\n        if (incomingShapesIterator) {\n            for (var i = 0; i < incomingShapesIterator.length; i++) {\n                var incomingShape = incomingShapesIterator[i];\n                if (visitedElementsArray.indexOf(incomingShape.id) < 0) {\n                    EDITOR.UTIL._visitElementAndCollectProperty(incomingShape, propertyType, visitedElementsArray, collectedProperties);\n                }\n            }\n        }\n    },\n\n    _visitElementAndCollectElement: function (element, stencilId, visitedElementsArray, collectedElements) {\n\n        visitedElementsArray.push(element.id);\n\n        var elementStencilId = element.getStencil().id();\n        if (elementStencilId && elementStencilId.indexOf(stencilId) >= 0) {\n            collectedElements.push(element);\n        }\n\n        var incomingShapesIterator = element.getIncomingShapes();\n        if (incomingShapesIterator) {\n            for (var i = 0; i < incomingShapesIterator.length; i++) {\n                var incomingShape = incomingShapesIterator[i];\n                if (visitedElementsArray.indexOf(incomingShape.id) < 0) {\n                    EDITOR.UTIL._visitElementAndCollectElement(incomingShape, stencilId, visitedElementsArray, collectedElements);\n                }\n            }\n        }\n    },\n\n    /**\n     * Goes up the chain of parents of the provided element.\n     * When the property is encountered, its value is immediately returned.\n     * If the chain of parents is completely walked through, undefined is returned.\n     */\n    getPropertyFromParent: function (element, propertyType) {\n        if (element.parent) {\n            return EDITOR.UTIL._getPropertyFromParent(element.parent, propertyType);\n        } else {\n            return undefined;\n        }\n\n    },\n\n    _getPropertyFromParent: function (parentElement, propertyType) {\n        var property = parentElement.properties[propertyType];\n        if (property) {\n            return property;\n        }\n\n        if (parentElement.parent) {\n            return EDITOR.UTIL._getPropertyFromParent(parentElement.parent, propertyType);\n        } else {\n            return undefined;\n        }\n    }\n\n};"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/editor.html",
    "content": "<div ng-controller=\"StencilController\">\n  <div class=\"subheader editor-toolbar\" id=\"editor-header\">\n  \t<div class=\"btn-group\">\n\t    <div class=\"btn-toolbar pull-left\" ng-controller=\"ToolbarController\" ng-cloak>\n        \t<button id=\"{{item.id}}\"\n                    title=\"{{item.title | translate}}\"\n                    ng-repeat=\"item in items\"\n                    ng-switch on=\"item.type\"\n                    class=\"btn btn-inverse\" ng-class=\"{'separator': item.type == 'separator'}\"\n                    ng-disabled=\"item.type == 'separator' || item.enabled == false\"\n                    ng-click=\"toolbarButtonClicked($index)\">\n        \t\t<i ng-switch-when=\"button\" ng-class=\"item.cssClass\" class=\"toolbar-button\" data-toggle=\"tooltip\" title=\"{{item.title | translate}}\"></i>\n\t            <div ng-switch-when=\"separator\" ng-class=\"item.cssClass\"></div>\n        \t</button>\n  \t\t  </div>\n        </div>\n        <div class=\"btn-group pull-right\" ng-show=\"!secondaryItems.length\">\n\t        <div class=\"btn-toolbar pull-right\" ng-controller=\"ToolbarController\">\n        \t<button title=\"{{item.title | translate}}\" ng-repeat=\"item in secondaryItems\" ng-switch on=\"item.type\" class=\"btn btn-inverse\" ng-class=\"{'separator': item.type == 'separator'}\"\n                ng-disabled=\"item.type == 'separator'\" ng-click=\"toolbarSecondaryButtonClicked($index)\" id=\"{{item.id}}\">\n        \t\t<i ng-switch-when=\"button\" ng-class=\"item.cssClass\" class=\"toolbar-button\" data-toggle=\"tooltip\" title=\"{{item.title | translate}}\"></i>\n\t            <div ng-switch-when=\"separator\" ng-class=\"item.cssClass\"></div>\n        \t</button>\n  \t\t  </div>\n        </div>\n  </div>\n  <div class=\"full\">\n      <div class=\"row row-no-gutter\">\n\t      <div id=\"paletteHelpWrapper\" class=\"col-xs-3\">\n\t      \t<div class=\"stencils\" id=\"paletteSection\">\n\t\t\t    <div ng-if=\"stencilItemGroups.length > 1\">\n                    <div ng-repeat=\"group in stencilItemGroups\">\n\n                        <ul ng-if=\"group.visible && group.items\" class=\"stencil-group\"  ng-class=\"{collapsed: !group.expanded, 'first': $first}\">\n                            <li ng-include=\"'editor-app/partials/stencil-item-template.html?version=4'\"></li>\n                        </ul>\n\n                        <div ng-if=\"!group.items\" ng-include=\"'editor-app/partials/root-stencil-item-template.html?version=4'\"></div>\n\n                    </div>\n\t\t\t    </div>\n\t\t\t    <div ng-if=\"stencilItemGroups.length == 1\">\n\t                <ul class=\"stencil-group\">\n\t                    <li ng-repeat=\"item in stencilItemGroups[0].paletteItems\" class=\"stencil-item\"\n\t                         id=\"{{item.id}}\"\n\t                         title=\"{{item.description}}\"\n\t                         ng-model=\"draggedElement\"\n\t                         data-drag=\"true\"\n\t                         jqyoui-draggable=\"{onStart:'startDragCallback', onDrag:'dragCallback'}\"\n\t                         data-jqyoui-options=\"{revert: 'invalid', helper: 'clone', opacity : 0.5}\">\n\t                         \n\t                        <img ng-src=\"editor-app/stencilsets/bpmn2.0/icons/{{item.icon}}\" width=\"16px;\" height=\"16px;\"/>\n\t                        {{item.name}}\n\t                    </li>\n                    </ul>\n\t\t\t     </div>\n\t\t      </div>\n\t      </div>\n\t      <div id=\"canvasHelpWrapper\" class=\"col-xs-9\">\n\t      \t<div class=\"canvas-wrapper\" id=\"canvasSection\" \n\t      \t\tng-model=\"droppedElement\"\n                  ng-model=\"droppedElement\"\n                  data-drop=\"true\"\n                  data-jqyoui-options\n                  jqyoui-droppable=\"{onDrop:'dropCallback',onOver: 'overCallback', onOut: 'outCallback'}\"> \n            \t<div class=\"canvas-message\" id=\"model-modified-date\"></div>\n            \t<div class=\"Oryx_button\" \n            \t     id=\"delete-button\" \n            \t     title=\"{{'BUTTON.ACTION.DELETE.TOOLTIP' | translate}}\"\n            \t     ng-click=\"deleteShape()\"\n            \t     style=\"display:none\">\n            \t    <img src=\"editor-app/images/delete.png\"/>\n            \t</div>\n            \t<div class=\"Oryx_button\" \n            \t     id=\"morph-button\"\n            \t     title=\"{{'BUTTON.ACTION.MORPH.TOOLTIP' | translate}}\"\n            \t     ng-click=\"morphShape()\"\n            \t     style=\"display:none\">\n            \t    <img src=\"editor-app/images/wrench.png\"/>\n            \t</div>\n            \t<div class=\"Oryx_button\"\n            \t\t ng-repeat=\"item in quickMenuItems\"\n\t                 id=\"{{item.id}}\"\n\t                 title=\"{{item.description}}\"\n\t                 ng-click=\"quickAddItem(item.id)\"\n            \t     ng-model=\"draggedElement\"\n\t                 data-drag=\"true\"\n\t                 jqyoui-draggable=\"{onStart:'startDragCallbackQuickMenu', onDrag:'dragCallbackQuickMenu'}\"\n\t                 data-jqyoui-options=\"{revert: 'invalid', helper: 'clone', opacity : 0.5}\"\n\t                 style=\"display:none\">\n\t             \t<img ng-src=\"editor-app/stencilsets/bpmn2.0/icons/{{item.icon}}\"/>\n\t             </div>\n\t         </div>\n           </div>\n           <div id=\"propertiesHelpWrapper\" class=\"col-xs-9\">\n            \t<div class=\"propertySection\" id=\"propertySection\"\n                \tng-class=\"{collapsed: propertyWindowState.collapsed}\">\n\t                <div class=\"selected-item-section\">\n\t                \t<div class=\"clearfix\">\n\t\t                    <div class=\"pull-right\" ng-if=\"selectedItem.auditData.createDate\">\n\t\t                        <strong>{{'ELEMENT.DATE_CREATED' | translate}}: </strong> {{selectedItem.auditData.createDate}}\n\t\t                    </div>\n\t\t                    <div class=\"pull-right\" ng-if=\"selectedItem.auditData.author\">\n\t\t                        <strong>{{'ELEMENT.AUTHOR' | translate}}: </strong> {{selectedItem.auditData.author}}\n\t\t                    </div>\n\t\t                    <div class=\"selected-item-title\">\n\t\t                        <a ng-click=\"propertyWindowState.toggle()\"> \n\t\t                            <i class=\"glyphicon\" ng-class=\"{'glyphicon-chevron-right': propertyWindowState.collapsed, 'glyphicon-chevron-down': !propertyWindowState.collapsed}\"></i>\n\t\t                            <span ng-show=\"selectedItem.title != undefined && selectedItem.title != null && selectedItem.title.length > 0\">{{selectedItem.title}}</span> \n\t\t                            <span ng-show=\"!selectedItem || selectedItem.title == undefined || selectedItem.title == null || selectedItem.title.length == 0\">{{modelData.name}}</span>\n\t\t                        </a>\n\t\t                    </div>\n\t\t                </div>\n                    \t<div class=\"selected-item-body\">\n\t                        <div>\n\t                             <div class=\"property-row\" ng-repeat=\"property in selectedItem.properties\"\n\t                                ng-click=\"propertyClicked($index)\" ng-class=\"{'clear' : $index%2 == 0}\">\n\t                                <span class=\"title\" ng-if=\"!property.hidden\">{{ property.title }}&nbsp;:</span>\n\t                                <span class=\"title-removed\" ng-if=\"property.hidden\"><i>{{ property.title }}&nbsp;({{'PROPERTY.REMOVED' | translate}})&nbsp;:</i></span>\n\t                                <span class=\"value\"> \n\t                                    <ng-include\n\t                                        src=\"getPropertyTemplateUrl($index)\" ng-if=\"!property.hasReadWriteMode\"></ng-include>\n\t                                    <ng-include src=\"getPropertyReadModeTemplateUrl($index)\"\n\t                                        ng-if=\"property.hasReadWriteMode && property.mode == 'read'\"></ng-include>\n\t                                    <ng-include src=\"getPropertyWriteModeTemplateUrl($index)\"\n\t                                        ng-if=\"property.hasReadWriteMode && property.mode == 'write'\"></ng-include>\n\t                                </span>\n\t                            </div>\n\t                        </div>\n\t                    </div>\n\t    \t\t\t</div>     \n    \t\t\t</div>            \n            </div>\n         </div>\n    </div>\n</div>\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/eventbus.js",
    "content": "/*\n * Activiti Modeler component part of the Activiti project\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * \n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n */\nvar KISBPM = KISBPM || {};\n\n/** Inspired by https://github.com/krasimir/EventBus/blob/master/src/EventBus.js */\nKISBPM.eventBus = {\n\n    /** Event fired when the editor is loaded and ready */\n    EVENT_TYPE_EDITOR_READY: 'event-type-editor-ready',\n\n    /** Event fired when a selection is made on the canvas. */\n    EVENT_TYPE_SELECTION_CHANGE: 'event-type-selection-change',\n\n    /** Event fired when a toolbar button has been clicked. */\n    EVENT_TYPE_TOOLBAR_BUTTON_CLICKED: 'event-type-toolbar-button-clicked',\n\n    /** Event fired when a stencil item is dropped on the canvas. */\n    EVENT_TYPE_ITEM_DROPPED: 'event-type-item-dropped',\n\n    /** Event fired when a property value is changed. */\n    EVENT_TYPE_PROPERTY_VALUE_CHANGED: 'event-type-property-value-changed',\n\n    /** Event fired on double click in canvas. */\n    EVENT_TYPE_DOUBLE_CLICK: 'event-type-double-click',\n\n    /** Event fired on a mouse out */\n    EVENT_TYPE_MOUSE_OUT: 'event-type-mouse-out',\n\n    /** Event fired on a mouse over */\n    EVENT_TYPE_MOUSE_OVER: 'event-type-mouse-over',\n\n    /** Event fired when a model is saved. */\n    EVENT_TYPE_MODEL_SAVED: 'event-type-model-saved',\n    \n    /** Event fired when the quick menu buttons should be hidden. */\n    EVENT_TYPE_HIDE_SHAPE_BUTTONS: 'event-type-hide-shape-buttons',\n\n    /** A mapping for storing the listeners*/\n    listeners: {},\n\n    /** The Oryx editor, which is stored locally to send events to */\n    editor: null,\n\n    /**\n     * Add an event listener to the event bus, listening to the event with the provided type.\n     * Type and callback are mandatory parameters.\n     *\n     * Provide scope parameter if it is important that the callback is executed\n     * within a specific scope.\n     */\n    addListener: function (type, callback, scope) {\n\n        // Add to the listeners map\n        if (typeof this.listeners[type] !== \"undefined\") {\n            this.listeners[type].push({scope: scope, callback: callback});\n        } else {\n            this.listeners[type] = [\n                {scope: scope, callback: callback}\n            ];\n        }\n    },\n\n    /**\n     * Removes the provided event listener.\n     */\n    removeListener: function (type, callback, scope) {\n        if (typeof this.listeners[type] != \"undefined\") {\n            var numOfCallbacks = this.listeners[type].length;\n            var newArray = [];\n            for (var i = 0; i < numOfCallbacks; i++) {\n                var listener = this.listeners[type][i];\n                if (listener.scope === scope && listener.callback === callback) {\n                    // Do nothing, this is the listener and doesn't need to survive\n                } else {\n                    newArray.push(listener);\n                }\n            }\n            this.listeners[type] = newArray;\n        }\n    },\n\n    hasListener:function(type, callback, scope) {\n        if(typeof this.listeners[type] != \"undefined\") {\n            var numOfCallbacks = this.listeners[type].length;\n            if(callback === undefined && scope === undefined){\n                return numOfCallbacks > 0;\n            }\n            for(var i=0; i<numOfCallbacks; i++) {\n                var listener = this.listeners[type][i];\n                if(listener.scope == scope && listener.callback == callback) {\n                    return true;\n                }\n            }\n        }\n        return false;\n    },\n\n    /**\n     * Dispatch an event to all event listeners registered to that specific type.\n     */\n    dispatch:function(type, event) {\n        if(typeof this.listeners[type] != \"undefined\") {\n            var numOfCallbacks = this.listeners[type].length;\n            for(var i=0; i<numOfCallbacks; i++) {\n                var listener = this.listeners[type][i];\n                if(listener && listener.callback) {\n                    listener.callback.apply(listener.scope, [event]);\n                }\n            }\n        }\n    },\n\n    dispatchOryxEvent: function(event, uiObject) {\n        KISBPM.eventBus.editor.handleEvents(event, uiObject);\n    }\n\n};"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/header-controller.js",
    "content": "/*\n * Activiti Modeler component part of the Activiti project\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * \n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n */\n'use strict';\n\nangular.module('activitiModeler')\n    .controller('HeaderController', ['$rootScope', '$scope', '$http', '$timeout', function ($rootScope, $scope, $http, $timeout) {\n    \t\n    \t// Add reference to global header-config\n    \t$scope.headerConfig = KISBPM.HEADER_CONFIG;\n    \t\n    \t// TODO: generate setting-menu items\n    \t\n    \t// TODO: generate user-menu items\n\n}]);"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/i18n/en.json",
    "content": "{\n    \"HEADER.BRAND\" : \"Activiti编辑\",\n    \"HEADER.BRAND_TAGLINE\" : \"powered by Alfresco\",\n    \"PAGE.HEADER\" : \"Orchestration Details\",\n\n    \"ACTION.OK\" : \"确认\",\n    \"ACTION.SAVE\" : \"保存\",\n    \"ACTION.SAVE-AND-CLOSE\" : \"保存并关闭\",\n    \"ACTION.SEND\" : \"发送\",\n    \"ACTION.CANCEL\" : \"取消\",\n    \"ACTION.SELECT\" : \"选择\",\n    \"ACTION.ADD\" : \"添加\",\n    \"ACTION.REMOVE\" : \"清除\",\n    \"ACTION.MOVE.UP\" : \"上移\",\n    \"ACTION.MOVE.DOWN\" : \"下移\",\n\n    \"MAIN_NAVIGATION_ORCHESTRATIONS\" : \"业务流程\",\n    \"MAIN_NAVIGATION_DISPATCH_RULES\" : \"调度规则\",\n    \"MAIN_NAVIGATION_ASSET_GROUPS\" : \"审批组\",\n    \"MAIN_NAVIGATION_SOLUTIONS\" : \"解决\",\n\n    \"TOOLBAR.ACTION.CLOSE\" : \"Close the editor and go back to the overview page\",\n    \"TOOLBAR.ACTION.SAVE\" : \"保存\",\n    \"TOOLBAR.ACTION.VALIDATE\": \"校验\",\n    \"TOOLBAR.ACTION.CUT\" : \"剪切\",\n    \"TOOLBAR.ACTION.COPY\" : \"复制\",\n    \"TOOLBAR.ACTION.PASTE\" : \"粘贴\",\n    \"TOOLBAR.ACTION.DELETE\" : \"删除\",\n    \"TOOLBAR.ACTION.UNDO\" : \"撤销\",\n    \"TOOLBAR.ACTION.REDO\" : \"重复\",\n    \"TOOLBAR.ACTION.ZOOMIN\" : \"放大\",\n    \"TOOLBAR.ACTION.ZOOMOUT\" : \"缩小\",\n    \"TOOLBAR.ACTION.ZOOMACTUAL\" : \"实际大小 \",\n    \"TOOLBAR.ACTION.ZOOMFIT\" : \"适应屏幕\",\n    \"TOOLBAR.ACTION.MOVE\" : \"移动\",\n    \"TOOLBAR.ACTION.IMPORT\" : \"导入\",\n    \"TOOLBAR.ACTION.EXPORT\" : \"导出\",\n    \"TOOLBAR.ACTION.BENDPOINT.ADD\" : \"为选定的流程连线添加弯曲点\",\n    \"TOOLBAR.ACTION.BENDPOINT.REMOVE\" : \"为选定的流程连线删除弯曲点\",\n    \"TOOLBAR.ACTION.ALIGNHORIZONTAL\" : \"水平对齐\",\n    \"TOOLBAR.ACTION.ALIGNVERTICAL\" : \"垂直对齐\",\n    \"TOOLBAR.ACTION.SAMESIZE\" : \"Same size\",\n    \"TOOLBAR.ACTION.HELP\": \"Start the guided tour\",\n    \"TOOLBAR.ACTION.FEEDBACK\": \"Provide feedback\",\n\n    \"KICKSTART.PROCESS_TOOLBAR.ACTION.SAVE\" : \"保存\",\n    \"KICKSTART.PROCESS_TOOLBAR.ACTION.VALIDATE\": \"校验模型\",\n    \"KICKSTART.PROCESS_TOOLBAR.ACTION.HELP\": \"预览\",\n    \"KICKSTART.PROCESS_TOOLBAR.ACTION.FEEDBACK\": \"反馈\",\n\n    \"FORM_TOOLBAR.ACTION.SAVE\" : \"保存\",\n    \"FORM_TOOLBAR.ACTION.VALIDATE\": \"校验模型\",\n    \"FORM_TOOLBAR.ACTION.HELP\": \"预览\",\n    \"FORM_TOOLBAR.ACTION.FEEDBACK\": \"反馈\",\n\n    \"APP_DEFINITION_TOOLBAR.ACTION.SAVE\" : \"保存\",\n    \"APP_DEFINITION_TOOLBAR.ACTION.VALIDATE\" : \"校验模型\",\n    \"APP_DEFINITION_TOOLBAR.ACTION.HELP\" : \"预览\",\n    \"APP_DEFINITION_TOOLBAR.ACTION.FEEDBACK\" : \"反馈\",\n\n    \"BUTTON.ACTION.DELETE.TOOLTIP\": \"从模型中删除元素\",\n    \"BUTTON.ACTION.MORPH.TOOLTIP\": \"更改元素类型\",\n\n    \"ELEMENT.AUTHOR\" : \"作者\",\n    \"ELEMENT.DATE_CREATED\" : \"创建日期\",\n    \"ELEMENT.SELECTED_EMPTY_TITLE\" : \"(输入名称)\",\n\n    \"PROPERTY.REMOVED\" : \"清除\",\n    \"PROPERTY.EMPTY\" : \"\",\n    \"PROPERTY.PROPERTY.EDIT.TITLE\" : \"修改 \\\"{{title}}\\\"\",\n\n    \"PROPERTY.FEEDBACK.TITLE\" : \"请填写您的反馈意见\",\n\n    \"PROPERTY.ASSIGNMENT.TITLE\" : \"指派\",\n    \"PROPERTY.ASSIGNMENT.TYPE\" : \"类型\",\n    \"PROPERTY.ASSIGNMENT.TYPE.IDENTITYSTORE\" : \"Identity store\",\n    \"PROPERTY.ASSIGNMENT.TYPE.STATIC\" : \"静态值\",\n    \"PROPERTY.ASSIGNMENT.ASSIGNEE\" : \"代理人\",\n    \"PROPERTY.ASSIGNMENT.MATCHING\" : \"使用上下方向键选择并按回车键确认或使用鼠标\",\n    \"PROPERTY.ASSIGNMENT.ASSIGNEE_PLACEHOLDER\" : \"请输入代理人\",\n    \"PROPERTY.ASSIGNMENT.EMPTY\" : \"无代理人\",\n    \"PROPERTY.ASSIGNMENT.ASSIGNEE_DISPLAY\" : \"代理人 {{assignee}}\",\n    \"PROPERTY.ASSIGNMENT.CANDIDATE_USERS_DISPLAY\" : \"{{length}}候选人\",\n    \"PROPERTY.ASSIGNMENT.CANDIDATE_USERS\" : \"候选人\",\n    \"PROPERTY.ASSIGNMENT.CANDIDATE_GROUPS_DISPLAY\" :  \"{{length}}候选组\",\n    \"PROPERTY.ASSIGNMENT.CANDIDATE_GROUPS\" :  \"候选组\",\n    \"PROPERTY.ASSIGNMENT.USER_IDM_DISPLAY\": \"用户{{firstName}} {{lastName}}\",\n    \"PROPERTY.ASSIGNMENT.USER_IDM_EMAIL_DISPLAY\": \"用户{{email}}\",\n    \"PROPERTY.ASSIGNMENT.IDM_EMPTY\" : \"发起人\",\n    \"PROPERTY.ASSIGNMENT.IDM.TYPE\" : \"任务\",\n    \"PROPERTY.ASSIGNMENT.IDM.NO_CANDIDATE_USERS\" : \"没有选择候选人...\",\n    \"PROPERTY.ASSIGNMENT.IDM.NO_CANDIDATE_GROUPS\" : \"没有选择候选组...\",\n    \"PROPERTY.ASSIGNMENT.IDM.DROPDOWN.INITIATOR\" : \"分派给发起人\",\n    \"PROPERTY.ASSIGNMENT.IDM.DROPDOWN.USER\" : \"分派给一个用户\",\n    \"PROPERTY.ASSIGNMENT.IDM.DROPDOWN.USERS\" : \"候选人s\",\n    \"PROPERTY.ASSIGNMENT.IDM.DROPDOWN.GROUPS\" : \"候选组\",\n    \"PROPERTY.ASSIGNMENT.EMAIL.HELP\" : \"键入一个电子邮件地址，然后按回车键继续 \",\n\n    \"PROPERTY.EXECUTIONLISTENERS.DISPLAY\" : \"{{length}}执行监听\",\n    \"PROPERTY.EXECUTIONLISTENERS.EMPTY\" : \"没有配置执行监听\",\n    \"PROPERTY.EXECUTIONLISTENERS.EVENT\" : \"事件\",\n    \"PROPERTY.EXECUTIONLISTENERS.CLASS\" : \"类\",\n    \"PROPERTY.EXECUTIONLISTENERS.CLASS.PLACEHOLDER\" : \"输入类名\",\n    \"PROPERTY.EXECUTIONLISTENERS.EXPRESSION\" : \"表达式\",\n    \"PROPERTY.EXECUTIONLISTENERS.EXPRESSION.PLACEHOLDER\" : \"输入表达式\",\n    \"PROPERTY.EXECUTIONLISTENERS.DELEGATEEXPRESSION\" : \"委托表达式\",\n    \"PROPERTY.EXECUTIONLISTENERS.DELEGATEEXPRESSION.PLACEHOLDER\" : \"输入委托表达式\",\n    \"PROPERTY.EXECUTIONLISTENERS.UNSELECTED\" : \"没有配置执行监听\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.NAME\" : \"名称\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.NAME.PLACEHOLDER\" : \"输入名称\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.EXPRESSION\" : \"表达式\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.EXPRESSION.PLACEHOLDER\" : \"输入表达式\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.STRINGVALUE\" : \"字符串\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.STRINGVALUE.PLACEHOLDER\" : \"输入字符串\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.STRING\" : \"字符串\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.STRING.PLACEHOLDER\" : \"输入字符串\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.IMPLEMENTATION\" : \"实现类\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.EMPTY\" : \"没有选择字段\",\n\n    \"PROPERTY.FIELDS\" : \"{{length}}字段\",\n    \"PROPERTY.FIELDS.EMPTY\" : \"没有选择字段\",\n    \"PROPERTY.FIELDS.NAME\" : \"名称\",\n    \"PROPERTY.FIELDS.NAME.PLACEHOLDER\" : \"输入名称\",\n    \"PROPERTY.FIELDS.EXPRESSION\" : \"表达式\",\n    \"PROPERTY.FIELDS.EXPRESSION.PLACEHOLDER\" : \"输入表达式\",\n    \"PROPERTY.FIELDS.STRINGVALUE\" : \"字符串\",\n    \"PROPERTY.FIELDS.STRINGVALUE.PLACEHOLDER\" : \"输入字符串\",\n    \"PROPERTY.FIELDS.STRING\" : \"字符串\",\n    \"PROPERTY.FIELDS.STRING.PLACEHOLDER\" : \"输入字符串\",\n    \"PROPERTY.FIELDS.IMPLEMENTATION\" : \"实现类\",\n    \"PROPERTY.FIELDS.UNSELECTED\" : \"没有选择字段\",\n\n    \"PROPERTY.FORMPROPERTIES.VALUE\" : \"{{length}}表单属性\",\n    \"PROPERTY.FORMPROPERTIES.EMPTY\" : \"没有配置表单\",\n    \"PROPERTY.FORMPROPERTIES.ID\" : \"活动编号\",\n    \"PROPERTY.FORMPROPERTIES.ID.PLACEHOLDER\" : \"输入活动编号\",\n    \"PROPERTY.FORMPROPERTIES.NAME\" : \"名称\",\n    \"PROPERTY.FORMPROPERTIES.NAME.PLACEHOLDER\" : \"输入名称\",\n    \"PROPERTY.FORMPROPERTIES.TYPE\" : \"类型\",\n    \"PROPERTY.FORMPROPERTIES.DATEPATTERN\" : \"时间选择框\",\n    \"PROPERTY.FORMPROPERTIES.DATEPATTERN.PLACEHOLDER\" : \"输入日期\",\n    \"PROPERTY.FORMPROPERTIES.VALUES\" : \"值\",\n    \"PROPERTY.FORMPROPERTIES.EXPRESSION\" : \"表达式\",\n    \"PROPERTY.FORMPROPERTIES.EXPRESSION.PLACEHOLDER\" : \"输入表达式\",\n    \"PROPERTY.FORMPROPERTIES.VARIABLE\" : \"变量\",\n    \"PROPERTY.FORMPROPERTIES.VARIABLE.PLACEHOLDER\" : \"输入变量\",\n    \"PROPERTY.FORMPROPERTIES.REQUIRED\" : \"必输\",\n    \"PROPERTY.FORMPROPERTIES.READABLE\" : \"可读\",\n    \"PROPERTY.FORMPROPERTIES.WRITABLE\" : \"可写\",\n\n    \"PROPERTY.INPARAMETERS.VALUE\" : \"{{length}}输入参数\",\n    \"PROPERTY.INPARAMETERS.EMPTY\" : \"没有配置输入参数\",\n\n    \"PROPERTY.OUTPARAMETERS.VALUE\" : \"{{length}}返回参数\",\n    \"PROPERTY.OUTPARAMETERS.EMPTY\" : \"没有配置返回参数\",\n\n    \"PROPERTY.PARAMETER.SOURCE\" : \"源\",\n    \"PROPERTY.PARAMETER.SOURCE.PLACEHOLDER\" : \"输入源\",\n    \"PROPERTY.PARAMETER.SOURCEEXPRESSION\" : \"源表达式\",\n    \"PROPERTY.PARAMETER.SOURCEEXPRESSION.PLACEHOLDER\" : \"输入源表达式\",\n    \"PROPERTY.PARAMETER.TARGET\" : \"目标\",\n    \"PROPERTY.PARAMETER.TARGET.PLACEHOLDER\" : \"输入目标\",\n    \"PROPERTY.PARAMETER.EMPTY\" : \"没有选择参数\",\n\n    \"PROPERTY.SUBPROCESSREFERENCE.EMPTY\" : \"没有引用子流程\",\n    \"PROPERTY.SUBPROCESSREFERENCE.TITLE\" : \"引用错误的子流程\",\n    \"PROPERTY.SUBPROCESSREFERENCE.ERROR.SUBPROCESS\" : \"子流程加载错误.请稍后再试\",\n    \"PROPERTY.SUBPROCESSREFERENCE.FOLDER.ROOT\" : \"文件夹\",\n    \"PROPERTY.SUBPROCESSREFERENCE.FOLDER.LOADING\" : \"文件夹加载中...\",\n    \"PROPERTY.SUBPROCESSREFERENCE.FOLDER.EMPTY\" : \"文件夹未包含子文件夹\",\n    \"PROPERTY.SUBPROCESSREFERENCE.SUBPROCESS.LOADING\" : \"子流程加载中...\",\n    \"PROPERTY.SUBPROCESSREFERENCE.SUBPROCESS.EMPTY\" : \"文件夹包含子文件夹\",\n\n    \"PROPERTY.FORMREFERENCE.EMPTY\" : \"没有引用表单\",\n    \"PROPERTY.FORMREFERENCE.TITLE\" : \"表单引用\",\n    \"PROPERTY.FORMREFERENCE.ERROR.FORM\" : \"表单加载错误.请稍后再试!\",\n    \"PROPERTY.FORMREFERENCE.FOLDER.ROOT\" : \"文件夹\",\n    \"PROPERTY.FORMREFERENCE.FOLDER.LOADING\" : \"文件夹加载中...\",\n    \"PROPERTY.FORMREFERENCE.FOLDER.EMPTY\" : \"文件夹未包含子文件夹\",\n    \"PROPERTY.FORMREFERENCE.FORM.LOADING\" : \"表单加载中...\",\n    \"PROPERTY.FORMREFERENCE.FORM.EMPTY\" : \"文件夹包含子文件夹\",\n\n    \"PROPERTY.TASKLISTENERS.VALUE\" : \"{{length}}任务监听\",\n    \"PROPERTY.TASKLISTENERS.EMPTY\" : \"未配置任务监听\",\n    \"PROPERTY.TASKLISTENERS.EVENT\" : \"事件\",\n    \"PROPERTY.TASKLISTENERS.CLASS\" : \"类\",\n    \"PROPERTY.TASKLISTENERS.CLASS.PLACEHOLDER\" : \"输入类名\",\n    \"PROPERTY.TASKLISTENERS.EXPRESSION\" : \"表达式\",\n    \"PROPERTY.TASKLISTENERS.EXPRESSION.PLACEHOLDER\" : \"请输入表达式\",\n    \"PROPERTY.TASKLISTENERS.DELEGATEEXPRESSION\" : \"委托表达式\",\n    \"PROPERTY.TASKLISTENERS.DELEGATEEXPRESSION.PLACEHOLDER\" : \"请输入委托表达式\",\n    \"PROPERTY.TASKLISTENERS.UNSELECTED\" : \"没有选择任务监听\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.NAME\" : \"名称\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.NAME.PLACEHOLDER\" : \"请输入名称\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.EXPRESSION\" : \"表达式\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.EXPRESSION.PLACEHOLDER\" : \"请输入表达式\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.STRINGVALUE\" : \"字符串\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.STRINGVALUE.PLACEHOLDER\" : \"请输入字符串\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.STRING\" : \"字符串\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.STRING.PLACEHOLDER\" : \"请输入字符串\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.IMPLEMENTATION\" : \"执行\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.EMPTY\" : \"未选择字段\",\n\n    \"PROPERTY.EVENTLISTENERS.DISPLAY\" : \"{{length}}事件监听\",\n    \"PROPERTY.EVENTLISTENERS.EMPTY\" : \"未配置事件监听\",\n    \"PROPERTY.EVENTLISTENERS.EVENTS\": \"事件\",\n    \"PROPERTY.EVENTLISTENERS.RETHROW\": \"抛出事件?\",\n    \"PROPERTY.EVENTLISTENERS.CLASS\" : \"类\",\n    \"PROPERTY.EVENTLISTENERS.CLASS.PLACEHOLDER\" : \"输入类名\",\n    \"PROPERTY.EVENTLISTENERS.DELEGATEEXPRESSION\" : \"委托表达式\",\n    \"PROPERTY.EVENTLISTENERS.DELEGATEEXPRESSION.PLACEHOLDER\" : \"请输入委托表达式\",\n    \"PROPERTY.EVENTLISTENERS.ENTITYTYPE\" : \"类型\",\n    \"PROPERTY.EVENTLISTENERS.ENTITYTYPE.PLACEHOLDER\" : \"请输入类型\",\n    \"PROPERTY.EVENTLISTENERS.RETHROWTYPE\": \"抛出事件类型\",\n    \"PROPERTY.EVENTLISTENERS.ERRORCODE\" : \"错误代码\",\n    \"PROPERTY.EVENTLISTENERS.ERRORCODE.PLACEHOLDER\" : \"请输入错误代码\",\n    \"PROPERTY.EVENTLISTENERS.MESSAGENAME\" : \"消息名称\",\n    \"PROPERTY.EVENTLISTENERS.MESSAGENAME.PLACEHOLDER\" : \"请输入消息名称\",\n    \"PROPERTY.EVENTLISTENERS.SIGNALNAME\" : \"信号名称\",\n    \"PROPERTY.EVENTLISTENERS.SIGNALNAME.PLACEHOLDER\" : \"请输入信号名称\",\n    \"PROPERTY.EVENTLISTENERS.UNSELECTED\" : \"没有选择事件监听\",\n\n    \"PROPERTY.SIGNALDEFINITIONS.DISPLAY\" : \"{{length}}信号定义\",\n    \"PROPERTY.SIGNALDEFINITIONS.EMPTY\" : \"没有配置信号定义\",\n    \"PROPERTY.SIGNALDEFINITIONS.SCOPE-GLOBAL\": \"全局\",\n    \"PROPERTY.SIGNALDEFINITIONS.SCOPE-PROCESSINSTANCE\": \"流程初始化\",\n    \"PROPERTY.SIGNALDEFINITIONS.ID\" : \"编号\",\n    \"PROPERTY.SIGNALDEFINITIONS.NAME\" : \"名称\",\n    \"PROPERTY.SIGNALDEFINITIONS.SCOPE\" : \"Scope\",\n\n    \"PROPERTY.MESSAGEDEFINITIONS.DISPLAY\" : \"{{length}}消息定义\",\n    \"PROPERTY.MESSAGEDEFINITIONS.EMPTY\" : \"没有配置消息定义\",\n    \"PROPERTY.MESSAGEDEFINITIONS.ID\" : \"编号\",\n    \"PROPERTY.MESSAGEDEFINITIONS.NAME\" : \"名称\",\n\n    \"PROPERTY.SEQUENCEFLOW.ORDER.EMPTY\" : \"没有确定顺序流排序\",\n    \"PROPERTY.SEQUENCEFLOW.ORDER.NOT.EMPTY\" : \"顺序流排序\",\n    \"PROPERTY.SEQUENCEFLOW.ORDER.NO.OUTGOING.SEQUENCEFLOW.FOUND\" : \"没有输出顺序流.\",\n    \"PROPERTY.SEQUENCEFLOW.ORDER.DESCRIPTION\" : \"不能设置已经被使用的编号:\",\n    \"PROPERTY.SEQUENCEFLOW.ORDER.SEQUENCEFLOW.VALUE\" : \"顺序流{{targetType}} {{targetTitle}}\",\n\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.TITLE\" : \"条件\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.TYPE.TITLE\" : \"条件类型\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.TYPE.VARIABLE\" : \"选择的变量\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.TYPE.STATIC\" : \"静态值\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.STATIC\" : \"条件表达式\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.STATIC_PLACEHOLDER\" : \"输入表达式值\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.TYPE\" : \"变量类型\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.NO-CONDITION\" : \"没有条件\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.FORM-FIELD\" : \"表单字段\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.FORM-OUTCOME\" : \"表单输出\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.SELECT-FIELD\" : \"选择的字段\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.NO-FIELDS-AVAILABLE\" : \"没有字段变量\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.SELECT-FORM\" : \"选择表单\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.NO-FORMS-AVAILABLE\" : \"没有表单变量\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.SELECT-OPERATOR\" : \"选择操作\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.EQUALS\" : \"等于\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.NOTEQUALS\" : \"不等于\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.LESSTHAN\" : \"小于\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.GREATERTHAN\" : \"大于\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.SELECT-OUTCOME\" : \"选择输出\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.NO-OUTCOMES-AVAILABLE\" : \"没有输出变量\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.NO-CONDITION-DISPLAY\" : \"没有条件\",\n\n    \"MODEL.SAVE.TITLE\" : \"保存模型\",\n    \"MODEL.NAME\" : \"名称\",\n    \"MODEL.DESCRIPTION\" : \"描述\",\n    \"MODEL.SAVE.NEWVERSION\" : \"保存为新版本? 这样你可以随时回到以前的版本\",\n    \"MODEL.SAVE.COMMENT\" : \"注释\",\n    \"MODEL.SAVE.SAVING\" : \"保存\",\n    \"MODEL.LASTMODIFIEDDATE\" : \"上次保存时间\",\n    \"MODEL.SAVE.ERROR\": \"未知错误:保存失败!\",\n\n    \"EVENT_TYPE.ACTIVITY.COMPENSATE.TOOLTIP\": \"一个活动被另外一个活动替代执行\",\n    \"EVENT_TYPE.ACTIVITY.COMPLETED.TOOLTIP\": \"一个活动被成功的执行\",\n    \"EVENT_TYPE.ACTIVITY.ERROR.RECEIVED.TOOLTIP\": \"在收到活动错误之前,活动已收到错误事件\",\n    \"EVENT_TYPE.MEMBERSHIP.CREATED.TOOLTIP\": \"一个唯一的成员被创建\",\n    \"EVENT_TYPE.MEMBERSHIP.DELETED.TOOLTIP\": \"一个唯一的成员被删除\",\n    \"EVENT_TYPE.MEMBERSHIPS.DELETED.TOOLTIP\": \"所有成员都被删除.可能是由于没有事件被分配\",\n    \"EVENT_TYPE.TASK.ASSIGNED.TOOLTIP\": \"在ENTITY_UPDATED事件抛出时，任务已经被分配\",\n    \"EVENT_TYPE.TASK.COMPLETED.TOOLTIP\": \"在任务实体删除前任务已经被完成\",\n    \"EVENT_TYPE.UNCAUGHT.BPMNERROR.TOOLTIP\": \"一个BPMN被抛出,但没有捕获\",\n    \"EVENT_TYPE.VARIABLE.CREATED.TOOLTIP\": \"一个变量被创建\",\n    \"EVENT_TYPE.VARIABLE.DELETED.TOOLTIP\": \"一个变量被删除\",\n    \"EVENT_TYPE.VARIABLE.UPDATED.TOOLTIP\": \"一个变量被更新\"\n}"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/i18n/en.json_bak",
    "content": "{    \n    \"HEADER.BRAND\" : \"Activiti Editor\",\n    \"HEADER.BRAND_TAGLINE\" : \"powered by Alfresco\",\n    \"PAGE.HEADER\" : \"Orchestration Details\",\n\n    \"ACTION.OK\" : \"Ok\",\n    \"ACTION.SAVE\" : \"Save\",\n    \"ACTION.SAVE-AND-CLOSE\" : \"Save and close editor\",\n    \"ACTION.SEND\" : \"Send\",\n    \"ACTION.CANCEL\" : \"Cancel\",\n    \"ACTION.SELECT\" : \"Select\",\n    \"ACTION.ADD\" : \"Add\",\n    \"ACTION.REMOVE\" : \"Remove\",\n    \"ACTION.MOVE.UP\" : \"Move entry up\",\n    \"ACTION.MOVE.DOWN\" : \"Move entry down\",\n    \n    \"MAIN_NAVIGATION_ORCHESTRATIONS\" : \"Orchestrations\",\n    \"MAIN_NAVIGATION_DISPATCH_RULES\" : \"Dispatch Rules\",\n    \"MAIN_NAVIGATION_ASSET_GROUPS\" : \"Assert Groups\",\n    \"MAIN_NAVIGATION_SOLUTIONS\" : \"Solutions\",\n    \n    \"TOOLBAR.ACTION.CLOSE\" : \"Close the editor and go back to the overview page\",\n    \"TOOLBAR.ACTION.SAVE\" : \"Save the model\",\n    \"TOOLBAR.ACTION.VALIDATE\": \"Validate the model\",\n    \"TOOLBAR.ACTION.CUT\" : \"Cut (select one or more elements in your business process)\",\n    \"TOOLBAR.ACTION.COPY\" : \"Copy (select one or more elements in your business process)\",\n    \"TOOLBAR.ACTION.PASTE\" : \"Paste\",\n    \"TOOLBAR.ACTION.DELETE\" : \"Delete the selected element\",\n    \"TOOLBAR.ACTION.UNDO\" : \"Undo\",\n    \"TOOLBAR.ACTION.REDO\" : \"Redo\",\n    \"TOOLBAR.ACTION.ZOOMIN\" : \"Zoom in\",\n    \"TOOLBAR.ACTION.ZOOMOUT\" : \"Zoom out\",\n    \"TOOLBAR.ACTION.ZOOMACTUAL\" : \"Zoom to actual size\",\n    \"TOOLBAR.ACTION.ZOOMFIT\" : \"Zoom to fit\",\n    \"TOOLBAR.ACTION.MOVE\" : \"Move\",\n    \"TOOLBAR.ACTION.IMPORT\" : \"Import\",\n    \"TOOLBAR.ACTION.EXPORT\" : \"Export\",\n    \"TOOLBAR.ACTION.BENDPOINT.ADD\" : \"Add bend-point to the selected sequence flow\",\n    \"TOOLBAR.ACTION.BENDPOINT.REMOVE\" : \"Remove bend-point from the selected sequence flow\",\n    \"TOOLBAR.ACTION.ALIGNHORIZONTAL\" : \"Align model horizontal\",\n    \"TOOLBAR.ACTION.ALIGNVERTICAL\" : \"Align model vertical\",\n    \"TOOLBAR.ACTION.SAMESIZE\" : \"Same size\",\n    \"TOOLBAR.ACTION.HELP\": \"Start the guided tour\",\n    \"TOOLBAR.ACTION.FEEDBACK\": \"Provide feedback\",\n    \n    \"KICKSTART.PROCESS_TOOLBAR.ACTION.SAVE\" : \"Save the model\",\n    \"KICKSTART.PROCESS_TOOLBAR.ACTION.VALIDATE\": \"Validate the model\",\n    \"KICKSTART.PROCESS_TOOLBAR.ACTION.HELP\": \"Start the guided tour\",\n    \"KICKSTART.PROCESS_TOOLBAR.ACTION.FEEDBACK\": \"Provide feedback\",\n    \n    \"FORM_TOOLBAR.ACTION.SAVE\" : \"Save the model\",\n    \"FORM_TOOLBAR.ACTION.VALIDATE\": \"Validate the model\",\n    \"FORM_TOOLBAR.ACTION.HELP\": \"Start the guided tour\",\n    \"FORM_TOOLBAR.ACTION.FEEDBACK\": \"Provide feedback\",\n    \n    \"APP_DEFINITION_TOOLBAR.ACTION.SAVE\" : \"Save the app definition\",\n    \"APP_DEFINITION_TOOLBAR.ACTION.VALIDATE\" : \"Validate the app definition\",\n    \"APP_DEFINITION_TOOLBAR.ACTION.HELP\" : \"Start the guided tour\",\n    \"APP_DEFINITION_TOOLBAR.ACTION.FEEDBACK\" : \"Provide feedback\",\n    \n    \"BUTTON.ACTION.DELETE.TOOLTIP\": \"Delete the element from the model\",\n    \"BUTTON.ACTION.MORPH.TOOLTIP\": \"Change the element type\",\n    \n    \"ELEMENT.AUTHOR\" : \"Author\",\n    \"ELEMENT.DATE_CREATED\" : \"Date created\",\n    \"ELEMENT.SELECTED_EMPTY_TITLE\" : \"(No name)\",\n    \n    \"PROPERTY.REMOVED\" : \"removed\",\n    \"PROPERTY.EMPTY\" : \"No value\",\n    \"PROPERTY.PROPERTY.EDIT.TITLE\" : \"Change value for \\\"{{title}}\\\"\",\n    \n    \"PROPERTY.FEEDBACK.TITLE\" : \"Please fill-in your feedback\",\n    \n    \"PROPERTY.ASSIGNMENT.TITLE\" : \"Assignment\",\n    \"PROPERTY.ASSIGNMENT.TYPE\" : \"Type\",\n    \"PROPERTY.ASSIGNMENT.TYPE.IDENTITYSTORE\" : \"Identity store\",\n    \"PROPERTY.ASSIGNMENT.TYPE.STATIC\" : \"Static values\",\n    \"PROPERTY.ASSIGNMENT.ASSIGNEE\" : \"Assignee\",\n    \"PROPERTY.ASSIGNMENT.MATCHING\" : \"Use &uparrow; and &downarrow; to select and press Enter to confirm or use the mouse\",\n    \"PROPERTY.ASSIGNMENT.ASSIGNEE_PLACEHOLDER\" : \"Enter an assignee\",\n    \"PROPERTY.ASSIGNMENT.EMPTY\" : \"No assignment selected\",\n    \"PROPERTY.ASSIGNMENT.ASSIGNEE_DISPLAY\" : \"Assignee {{assignee}}\",\n    \"PROPERTY.ASSIGNMENT.CANDIDATE_USERS_DISPLAY\" : \"{{length}} Candidate users\",\n    \"PROPERTY.ASSIGNMENT.CANDIDATE_USERS\" : \"Candidate users\",\n    \"PROPERTY.ASSIGNMENT.CANDIDATE_GROUPS_DISPLAY\" :  \"{{length}} Candidate groups\",\n    \"PROPERTY.ASSIGNMENT.CANDIDATE_GROUPS\" :  \"Candidate groups\",\n    \"PROPERTY.ASSIGNMENT.USER_IDM_DISPLAY\": \"User {{firstName}} {{lastName}}\",\n    \"PROPERTY.ASSIGNMENT.USER_IDM_EMAIL_DISPLAY\": \"User {{email}}\",\n    \"PROPERTY.ASSIGNMENT.IDM_EMPTY\" : \"Process initiator\",\n    \"PROPERTY.ASSIGNMENT.IDM.TYPE\" : \"Assignment\",\n    \"PROPERTY.ASSIGNMENT.IDM.NO_CANDIDATE_USERS\" : \"No candidate users selected...\",\n    \"PROPERTY.ASSIGNMENT.IDM.NO_CANDIDATE_GROUPS\" : \"No candidate groups selected...\",\n    \"PROPERTY.ASSIGNMENT.IDM.DROPDOWN.INITIATOR\" : \"Assigned to process initiator\",\n    \"PROPERTY.ASSIGNMENT.IDM.DROPDOWN.USER\" : \"Assigned to single user\",\n    \"PROPERTY.ASSIGNMENT.IDM.DROPDOWN.USERS\" : \"Candidate users\",\n    \"PROPERTY.ASSIGNMENT.IDM.DROPDOWN.GROUPS\" : \"Candidate groups\",\n    \"PROPERTY.ASSIGNMENT.EMAIL.HELP\" : \"Type an email address and press Enter to continue\",\n    \n    \"PROPERTY.EXECUTIONLISTENERS.DISPLAY\" : \"{{length}} execution listeners\",\n    \"PROPERTY.EXECUTIONLISTENERS.EMPTY\" : \"No execution listeners configured\",\n    \"PROPERTY.EXECUTIONLISTENERS.EVENT\" : \"Event\",\n    \"PROPERTY.EXECUTIONLISTENERS.CLASS\" : \"Class\",\n    \"PROPERTY.EXECUTIONLISTENERS.CLASS.PLACEHOLDER\" : \"Enter a classname\",\n    \"PROPERTY.EXECUTIONLISTENERS.EXPRESSION\" : \"Expression\",\n    \"PROPERTY.EXECUTIONLISTENERS.EXPRESSION.PLACEHOLDER\" : \"Enter an expression\",\n    \"PROPERTY.EXECUTIONLISTENERS.DELEGATEEXPRESSION\" : \"Delegate expression\",\n    \"PROPERTY.EXECUTIONLISTENERS.DELEGATEEXPRESSION.PLACEHOLDER\" : \"Enter a delegate expression\",\n    \"PROPERTY.EXECUTIONLISTENERS.UNSELECTED\" : \"No execution listener selected\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.NAME\" : \"Name\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.NAME.PLACEHOLDER\" : \"Enter a name\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.EXPRESSION\" : \"Expression\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.EXPRESSION.PLACEHOLDER\" : \"Enter an expression\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.STRINGVALUE\" : \"String value\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.STRINGVALUE.PLACEHOLDER\" : \"Enter a string value\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.STRING\" : \"String\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.STRING.PLACEHOLDER\" : \"Enter a string\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.IMPLEMENTATION\" : \"Implementation\",\n    \"PROPERTY.EXECUTIONLISTENERS.FIELDS.EMPTY\" : \"No Field selected\",\n    \n    \"PROPERTY.FIELDS\" : \"{{length}} fields\",\n    \"PROPERTY.FIELDS.EMPTY\" : \"No fields selected\",\n    \"PROPERTY.FIELDS.NAME\" : \"Name\",\n    \"PROPERTY.FIELDS.NAME.PLACEHOLDER\" : \"Enter a name\",\n    \"PROPERTY.FIELDS.EXPRESSION\" : \"Expression\",\n    \"PROPERTY.FIELDS.EXPRESSION.PLACEHOLDER\" : \"Enter an expression\",\n    \"PROPERTY.FIELDS.STRINGVALUE\" : \"String value\",\n    \"PROPERTY.FIELDS.STRINGVALUE.PLACEHOLDER\" : \"Enter a string value\",\n    \"PROPERTY.FIELDS.STRING\" : \"String\",\n    \"PROPERTY.FIELDS.STRING.PLACEHOLDER\" : \"Enter a string\",\n    \"PROPERTY.FIELDS.IMPLEMENTATION\" : \"Implementation\",\n    \"PROPERTY.FIELDS.UNSELECTED\" : \"No Field selected\",\n    \n    \"PROPERTY.FORMPROPERTIES.VALUE\" : \"{{length}} form properties\",\n    \"PROPERTY.FORMPROPERTIES.EMPTY\" : \"No form properties selected\",\n    \"PROPERTY.FORMPROPERTIES.ID\" : \"Id\",\n    \"PROPERTY.FORMPROPERTIES.ID.PLACEHOLDER\" : \"Enter an id\",\n    \"PROPERTY.FORMPROPERTIES.NAME\" : \"Name\",\n    \"PROPERTY.FORMPROPERTIES.NAME.PLACEHOLDER\" : \"Enter a name\",\n    \"PROPERTY.FORMPROPERTIES.TYPE\" : \"Type\",\n    \"PROPERTY.FORMPROPERTIES.DATEPATTERN\" : \"Date pattern\",\n    \"PROPERTY.FORMPROPERTIES.DATEPATTERN.PLACEHOLDER\" : \"Enter date pattern\",\n    \"PROPERTY.FORMPROPERTIES.VALUES\" : \"Values\",\n    \"PROPERTY.FORMPROPERTIES.ENUMVALUES.EMPTY\" : \"No enum value selected\",\n    \"PROPERTY.FORMPROPERTIES.VALUES.ID\" : \"Id\",\n    \"PROPERTY.FORMPROPERTIES.VALUES.NAME\" : \"Name\",\n    \"PROPERTY.FORMPROPERTIES.VALUES.ID.PLACEHOLDER\" : \"Enter id of a value\",\n\t\"PROPERTY.FORMPROPERTIES.VALUES.NAME.PLACEHOLDER\" : \"Enter name of a value\",\n    \"PROPERTY.FORMPROPERTIES.EXPRESSION\" : \"Expression\",\n    \"PROPERTY.FORMPROPERTIES.EXPRESSION.PLACEHOLDER\" : \"Enter an expression\",\n    \"PROPERTY.FORMPROPERTIES.VARIABLE\" : \"Variable\",\n    \"PROPERTY.FORMPROPERTIES.VARIABLE.PLACEHOLDER\" : \"Enter a variable\",\n    \"PROPERTY.FORMPROPERTIES.REQUIRED\" : \"Required\",\n    \"PROPERTY.FORMPROPERTIES.READABLE\" : \"Readable\",\n    \"PROPERTY.FORMPROPERTIES.WRITABLE\" : \"Writable\",\n    \n    \"PROPERTY.INPARAMETERS.VALUE\" : \"{{length}} in-parameters\",\n    \"PROPERTY.INPARAMETERS.EMPTY\" : \"No in-parameters configured\",\n    \n    \"PROPERTY.OUTPARAMETERS.VALUE\" : \"{{length}} out-parameters\",\n    \"PROPERTY.OUTPARAMETERS.EMPTY\" : \"No out-parameters configured\",\n    \n    \"PROPERTY.PARAMETER.SOURCE\" : \"Source\",\n    \"PROPERTY.PARAMETER.SOURCE.PLACEHOLDER\" : \"Enter a source\",\n    \"PROPERTY.PARAMETER.SOURCEEXPRESSION\" : \"Source expression\",\n    \"PROPERTY.PARAMETER.SOURCEEXPRESSION.PLACEHOLDER\" : \"Enter a source expression\",\n    \"PROPERTY.PARAMETER.TARGET\" : \"Target\",\n    \"PROPERTY.PARAMETER.TARGET.PLACEHOLDER\" : \"Enter a target\",\n    \"PROPERTY.PARAMETER.EMPTY\" : \"No parameter selected\",\n    \n    \"PROPERTY.SUBPROCESSREFERENCE.EMPTY\" : \"No reference selected\",\n    \"PROPERTY.SUBPROCESSREFERENCE.TITLE\" : \"Collapsed subprocess reference\",\n    \"PROPERTY.SUBPROCESSREFERENCE.ERROR.SUBPROCESS\" : \"There was an error loading the subprocesses. Try again later\",\n    \"PROPERTY.SUBPROCESSREFERENCE.FOLDER.ROOT\" : \"Folders\",\n    \"PROPERTY.SUBPROCESSREFERENCE.FOLDER.LOADING\" : \"Loading folders...\",\n    \"PROPERTY.SUBPROCESSREFERENCE.FOLDER.EMPTY\" : \"This folder contains no sub-folders\",\n    \"PROPERTY.SUBPROCESSREFERENCE.SUBPROCESS.LOADING\" : \"Loading subprocesses...\",\n    \"PROPERTY.SUBPROCESSREFERENCE.SUBPROCESS.EMPTY\" : \"This folder contains no subprocesses\",\n    \n    \"PROPERTY.FORMREFERENCE.EMPTY\" : \"No reference selected\",\n    \"PROPERTY.FORMREFERENCE.TITLE\" : \"Form reference\",\n    \"PROPERTY.FORMREFERENCE.ERROR.FORM\" : \"There was an error loading the forms. Try again later\",\n    \"PROPERTY.FORMREFERENCE.FOLDER.ROOT\" : \"Folders\",\n    \"PROPERTY.FORMREFERENCE.FOLDER.LOADING\" : \"Loading folders...\",\n    \"PROPERTY.FORMREFERENCE.FOLDER.EMPTY\" : \"This folder contains no sub-folders\",\n    \"PROPERTY.FORMREFERENCE.FORM.LOADING\" : \"Loading forms...\",\n    \"PROPERTY.FORMREFERENCE.FORM.EMPTY\" : \"This folder contains no forms\",\n    \n    \"PROPERTY.TASKLISTENERS.VALUE\" : \"{{length}} task listeners\",\n    \"PROPERTY.TASKLISTENERS.EMPTY\" : \"No task listeners configured\",\n    \"PROPERTY.TASKLISTENERS.EVENT\" : \"Event\",\n    \"PROPERTY.TASKLISTENERS.CLASS\" : \"Class\",\n    \"PROPERTY.TASKLISTENERS.CLASS.PLACEHOLDER\" : \"Enter a classname\",\n    \"PROPERTY.TASKLISTENERS.EXPRESSION\" : \"Expression\",\n    \"PROPERTY.TASKLISTENERS.EXPRESSION.PLACEHOLDER\" : \"Enter an expression\",\n    \"PROPERTY.TASKLISTENERS.DELEGATEEXPRESSION\" : \"Delegate expression\",\n    \"PROPERTY.TASKLISTENERS.DELEGATEEXPRESSION.PLACEHOLDER\" : \"Enter a delegate expression\",\n    \"PROPERTY.TASKLISTENERS.UNSELECTED\" : \"No task listener selected\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.NAME\" : \"Name\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.NAME.PLACEHOLDER\" : \"Enter a name\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.EXPRESSION\" : \"Expression\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.EXPRESSION.PLACEHOLDER\" : \"Enter an expression\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.STRINGVALUE\" : \"String value\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.STRINGVALUE.PLACEHOLDER\" : \"Enter a string value\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.STRING\" : \"String\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.STRING.PLACEHOLDER\" : \"Enter a string\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.IMPLEMENTATION\" : \"Implementation\",\n    \"PROPERTY.TASKLISTENERS.FIELDS.EMPTY\" : \"No Field selected\",\n    \n    \"PROPERTY.EVENTLISTENERS.DISPLAY\" : \"{{length}} event listeners\",\n    \"PROPERTY.EVENTLISTENERS.EMPTY\" : \"No event listeners configured\",\n    \"PROPERTY.EVENTLISTENERS.EVENTS\": \"Events\",\n    \"PROPERTY.EVENTLISTENERS.RETHROW\": \"Rethrow event?\",\n    \"PROPERTY.EVENTLISTENERS.CLASS\" : \"Class\",\n    \"PROPERTY.EVENTLISTENERS.CLASS.PLACEHOLDER\" : \"Enter a classname\",\n    \"PROPERTY.EVENTLISTENERS.DELEGATEEXPRESSION\" : \"Delegate expression\",\n    \"PROPERTY.EVENTLISTENERS.DELEGATEEXPRESSION.PLACEHOLDER\" : \"Enter a delegate expression\",\n    \"PROPERTY.EVENTLISTENERS.ENTITYTYPE\" : \"Entity type\",\n    \"PROPERTY.EVENTLISTENERS.ENTITYTYPE.PLACEHOLDER\" : \"Enter an entity type\",\n    \"PROPERTY.EVENTLISTENERS.RETHROWTYPE\": \"Rethrow event type\",\n    \"PROPERTY.EVENTLISTENERS.ERRORCODE\" : \"Error code\",\n    \"PROPERTY.EVENTLISTENERS.ERRORCODE.PLACEHOLDER\" : \"Enter an error code\",\n    \"PROPERTY.EVENTLISTENERS.MESSAGENAME\" : \"Message name\",\n    \"PROPERTY.EVENTLISTENERS.MESSAGENAME.PLACEHOLDER\" : \"Enter a message name\",\n    \"PROPERTY.EVENTLISTENERS.SIGNALNAME\" : \"Signal name\",\n    \"PROPERTY.EVENTLISTENERS.SIGNALNAME.PLACEHOLDER\" : \"Enter a signal name\",\n    \"PROPERTY.EVENTLISTENERS.UNSELECTED\" : \"No event listener selected\",\n    \n    \"PROPERTY.SIGNALDEFINITIONS.DISPLAY\" : \"{{length}} signal definitions\",\n    \"PROPERTY.SIGNALDEFINITIONS.EMPTY\" : \"No signal definitions configured\",\n    \"PROPERTY.SIGNALDEFINITIONS.SCOPE-GLOBAL\": \"Global\",\n    \"PROPERTY.SIGNALDEFINITIONS.SCOPE-PROCESSINSTANCE\": \"Process Instance\",\n    \"PROPERTY.SIGNALDEFINITIONS.ID\" : \"Id\",\n    \"PROPERTY.SIGNALDEFINITIONS.NAME\" : \"Name\",\n    \"PROPERTY.SIGNALDEFINITIONS.SCOPE\" : \"Scope\", \n  \n    \"PROPERTY.MESSAGEDEFINITIONS.DISPLAY\" : \"{{length}} message definitions\",\n    \"PROPERTY.MESSAGEDEFINITIONS.EMPTY\" : \"No message definitions configured\",\n    \"PROPERTY.MESSAGEDEFINITIONS.ID\" : \"Id\",\n    \"PROPERTY.MESSAGEDEFINITIONS.NAME\" : \"Name\",\n\n    \"PROPERTY.SEQUENCEFLOW.ORDER.EMPTY\" : \"No sequence flow order determined\",\n    \"PROPERTY.SEQUENCEFLOW.ORDER.NOT.EMPTY\" : \"Sequence flow order set\",\n    \"PROPERTY.SEQUENCEFLOW.ORDER.NO.OUTGOING.SEQUENCEFLOW.FOUND\" : \"No outgoing sequence flow found.\",\n    \"PROPERTY.SEQUENCEFLOW.ORDER.DESCRIPTION\" : \"Set the order in which the sequence flow need to be evaluated:\",\n    \"PROPERTY.SEQUENCEFLOW.ORDER.SEQUENCEFLOW.VALUE\" : \"Sequence flow to {{targetType}} {{targetTitle}}\",\n    \n    \"PROPERTY.SEQUENCEFLOW.CONDITION.TITLE\" : \"Sequence flow condition\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.TYPE.TITLE\" : \"Condition type\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.TYPE.VARIABLE\" : \"Select variables\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.TYPE.STATIC\" : \"Static value\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.STATIC\" : \"Condition expression\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.STATIC_PLACEHOLDER\" : \"Fill-in expression value\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.TYPE\" : \"Variable type\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.NO-CONDITION\" : \"No condition\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.FORM-FIELD\" : \"Form field\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.FORM-OUTCOME\" : \"Form outcome\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.SELECT-FIELD\" : \"Select field\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.NO-FIELDS-AVAILABLE\" : \"No fields available\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.SELECT-FORM\" : \"Select form\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.NO-FORMS-AVAILABLE\" : \"No forms available\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.SELECT-OPERATOR\" : \"Select operator\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.EQUALS\" : \"Equals\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.NOTEQUALS\" : \"Not equals\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.LESSTHAN\" : \"Less than\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.GREATERTHAN\" : \"Greater than\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.SELECT-OUTCOME\" : \"Select outcome\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.NO-OUTCOMES-AVAILABLE\" : \"No outcomes available\",\n    \"PROPERTY.SEQUENCEFLOW.CONDITION.NO-CONDITION-DISPLAY\" : \"No condition\",\n    \n    \"MODEL.SAVE.TITLE\" : \"Save model\",\n    \"MODEL.NAME\" : \"Name\",\n    \"MODEL.DESCRIPTION\" : \"Description\",\n    \"MODEL.SAVE.NEWVERSION\" : \"Save this as a new version?  This means you can always go back to a previous version\",\n    \"MODEL.SAVE.COMMENT\" : \"Comment\",\n    \"MODEL.SAVE.SAVING\" : \"Saving model\",\n    \"MODEL.LASTMODIFIEDDATE\" : \"Last saved\",\n    \"MODEL.SAVE.ERROR\": \"Unexpected error: could not save model\",\n    \n    \"EVENT_TYPE.ACTIVITY.COMPENSATE.TOOLTIP\": \"An activity is about to be executed as a compensation for another activity. The event targets the activity that is about to be executed for compensation\",\n    \"EVENT_TYPE.ACTIVITY.COMPLETED.TOOLTIP\": \"An activity has been completed successfully\",\n    \"EVENT_TYPE.ACTIVITY.ERROR.RECEIVED.TOOLTIP\": \"An activity has received an error event. Dispatched before the actual error has been received by the activity\",\n    \"EVENT_TYPE.MEMBERSHIP.CREATED.TOOLTIP\": \"A new membership has been created\",\n    \"EVENT_TYPE.MEMBERSHIP.DELETED.TOOLTIP\": \"A single membership has been deleted\",\n    \"EVENT_TYPE.MEMBERSHIPS.DELETED.TOOLTIP\": \"All memberships in the related group have been deleted. No individual events will be dispatched due to possible performance reasons\",\n    \"EVENT_TYPE.TASK.ASSIGNED.TOOLTIP\": \"A task as been assigned. This is thrown alongside with an ENTITY_UPDATED event\",\n    \"EVENT_TYPE.TASK.COMPLETED.TOOLTIP\": \"A task has been completed. Dispatched before the task entity is deleted\",\n    \"EVENT_TYPE.UNCAUGHT.BPMNERROR.TOOLTIP\": \"When a BPMN Error was thrown, but was not caught within in the process\",\n    \"EVENT_TYPE.VARIABLE.CREATED.TOOLTIP\": \"A new variable has been created\",\n    \"EVENT_TYPE.VARIABLE.DELETED.TOOLTIP\": \"An existing variable has been deleted\",\n    \"EVENT_TYPE.VARIABLE.UPDATED.TOOLTIP\": \"An existing variable has been updated\"\n}"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/angular-dragdrop.min-1.0.3.js",
    "content": "/**\n * Implementing Drag and Drop functionality in AngularJS is easier than ever.\n * Demo: http://codef0rmer.github.com/angular-dragdrop/\n * \n * @version 1.0.3\n *\n * (c) 2013 Amit Gharat a.k.a codef0rmer <amit.2006.it@gmail.com> - amitgharat.wordpress.com\n */\nvar jqyoui=angular.module(\"ngDragDrop\",[]).service(\"ngDragDropService\",[\"$timeout\",\"$parse\",function($timeout,$parse){this.callEventCallback=function(scope,callbackName,event,ui){if(!callbackName){return}var args=[event,ui];var match=callbackName.match(/^(.+)\\((.+)\\)$/);if(match!==null){callbackName=match[1];values=eval(\"[\"+match[0].replace(/^(.+)\\(/,\"\").replace(/\\)/,\"\")+\"]\");args.push.apply(args,values)}scope[callbackName].apply(scope,args)};this.invokeDrop=function(e,t,n,r){var i=\"\",s=\"\",o={},u={},a=null,f={},l={},c,h,p=null,d=t.scope(),v=e.scope();i=e.attr(\"ng-model\");s=t.attr(\"ng-model\");c=v.$eval(i);h=d.$eval(s);p=t.find(\"[jqyoui-draggable]:last\");u=d.$eval(t.attr(\"jqyoui-droppable\"))||[];o=v.$eval(e.attr(\"jqyoui-draggable\"))||[];o.index=this.fixIndex(v,o,c);u.index=this.fixIndex(d,u,h);a=angular.isArray(c)?o.index:null;f=angular.isArray(c)?c[a]:c;if(angular.isArray(h)&&u&&u.index!==undefined){l=h[u.index]}else if(!angular.isArray(h)){l=h}else{l={}}if(o.animate===true){this.move(e,p.length>0?p:t,null,\"fast\",u,null);this.move(p.length>0&&!u.multiple?p:[],e.parent(\"[jqyoui-droppable]\"),jqyoui.startXY,\"fast\",u,function(){$timeout(function(){e.css({position:\"relative\",left:\"\",top:\"\"});p.css({position:\"relative\",left:\"\",top:\"\"});this.mutateDraggable(v,u,o,i,s,l,e);this.mutateDroppable(d,u,o,s,f,a);this.callEventCallback(d,u.onDrop,n,r)}.bind(this))}.bind(this))}else{$timeout(function(){this.mutateDraggable(v,u,o,i,s,l,e);this.mutateDroppable(d,u,o,s,f,a);this.callEventCallback(d,u.onDrop,n,r)}.bind(this))}};this.move=function(e,t,n,r,i,s){if(e.length===0){if(s){window.setTimeout(function(){s()},300)}return false}var o=9999,u=e.offset(),a=t&&t.is(\":visible\");if(n===null&&t.length>0){if(t.attr(\"jqyoui-draggable\")!==undefined&&t.attr(\"ng-model\")!==undefined&&t.is(\":visible\")&&i&&i.multiple){n=t.offset();if(i.stack===false){n.left+=t.outerWidth(true)}else{n.top+=t.outerHeight(true)}}else{n=t.css({visibility:\"hidden\",display:\"block\"}).offset();t.css({visibility:\"\",display:a?\"\":\"none\"})}}e.css({position:\"absolute\",\"z-index\":o}).css(u).animate(n,r,function(){if(s)s()})};this.mutateDroppable=function(e,t,n,r,i,s){var o=e.$eval(r);e.__dragItem=i;if(angular.isArray(o)){if(t&&t.index>=0){o[t.index]=i}else{o.push(i)}if(n&&n.placeholder===true){o[o.length-1][\"jqyoui_pos\"]=s}}else{$parse(r+\" = __dragItem\")(e);if(n&&n.placeholder===true){o[\"jqyoui_pos\"]=s}}};this.mutateDraggable=function(e,t,n,r,i,s,o){var u=angular.equals(angular.copy(s),{}),a=e.$eval(r);e.__dropItem=s;if(n&&n.placeholder){if(n.placeholder!=\"keep\"){if(angular.isArray(a)&&n.index!==undefined){a[n.index]=s}else{$parse(r+\" = __dropItem\")(e)}}}else{if(angular.isArray(a)){if(u){if(n&&n.placeholder!==true&&n.placeholder!==\"keep\"){a.splice(n.index,1)}}else{a[n.index]=s}}else{$parse(r+\" = __dropItem\")(e);if(e.$parent){$parse(r+\" = __dropItem\")(e.$parent)}}}o.css({\"z-index\":\"\",left:\"\",top:\"\"})};this.fixIndex=function(e,t,n){if(t.applyFilter&&angular.isArray(n)&&n.length>0){var r=e[t.applyFilter](),i=r[t.index],s=undefined;n.forEach(function(e,t){if(angular.equals(e,i)){s=t}});return s}return t.index}}]).directive(\"jqyouiDraggable\",[\"ngDragDropService\",function(e){return{require:\"?jqyouiDroppable\",restrict:\"A\",link:function(t,n,r){var i,s;var o=function(o,u){if(o){i=t.$eval(n.attr(\"jqyoui-draggable\"))||[];n.draggable({disabled:false}).draggable(t.$eval(r.jqyouiOptions)||{}).draggable({start:function(n,r){s=angular.element(this).css(\"z-index\");angular.element(this).css(\"z-index\",99999);jqyoui.startXY=angular.element(this).offset();e.callEventCallback(t,i.onStart,n,r)},stop:function(n,r){angular.element(this).css(\"z-index\",s);e.callEventCallback(t,i.onStop,n,r)},drag:function(n,r){e.callEventCallback(t,i.onDrag,n,r)}})}else{n.draggable({disabled:true})}};t.$watch(function(){return t.$eval(r.drag)},o);o()}}}]).directive(\"jqyouiDroppable\",[\"ngDragDropService\",function(e){return{restrict:\"A\",priority:1,link:function(t,n,r){var i=function(i,s){if(i){n.droppable({disabled:false}).droppable(t.$eval(r.jqyouiOptions)||{}).droppable({over:function(n,r){var i=t.$eval(angular.element(this).attr(\"jqyoui-droppable\"))||[];e.callEventCallback(t,i.onOver,n,r)},out:function(n,r){var i=t.$eval(angular.element(this).attr(\"jqyoui-droppable\"))||[];e.callEventCallback(t,i.onOut,n,r)},drop:function(t,n){e.invokeDrop(angular.element(n.draggable),angular.element(this),t,n)}})}else{n.droppable({disabled:true})}};t.$watch(function(){return t.$eval(r.drop)},i);i()}}}])\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/angular-mocks_1.2.13/angular-mocks.js",
    "content": "/**\n * @license AngularJS v1.2.13\n * (c) 2010-2014 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {\n\n'use strict';\n\n/**\n * @ngdoc overview\n * @name angular.mock\n * @description\n *\n * Namespace from 'angular-mocks.js' which contains testing related code.\n */\nangular.mock = {};\n\n/**\n * ! This is a private undocumented service !\n *\n * @name ngMock.$browser\n *\n * @description\n * This service is a mock implementation of {@link ng.$browser}. It provides fake\n * implementation for commonly used browser apis that are hard to test, e.g. setTimeout, xhr,\n * cookies, etc...\n *\n * The api of this service is the same as that of the real {@link ng.$browser $browser}, except\n * that there are several helper methods available which can be used in tests.\n */\nangular.mock.$BrowserProvider = function() {\n  this.$get = function() {\n    return new angular.mock.$Browser();\n  };\n};\n\nangular.mock.$Browser = function() {\n  var self = this;\n\n  this.isMock = true;\n  self.$$url = \"http://server/\";\n  self.$$lastUrl = self.$$url; // used by url polling fn\n  self.pollFns = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = angular.noop;\n  self.$$incOutstandingRequestCount = angular.noop;\n\n\n  // register url polling fn\n\n  self.onUrlChange = function(listener) {\n    self.pollFns.push(\n      function() {\n        if (self.$$lastUrl != self.$$url) {\n          self.$$lastUrl = self.$$url;\n          listener(self.$$url);\n        }\n      }\n    );\n\n    return listener;\n  };\n\n  self.cookieHash = {};\n  self.lastCookieHash = {};\n  self.deferredFns = [];\n  self.deferredNextId = 0;\n\n  self.defer = function(fn, delay) {\n    delay = delay || 0;\n    self.deferredFns.push({time:(self.defer.now + delay), fn:fn, id: self.deferredNextId});\n    self.deferredFns.sort(function(a,b){ return a.time - b.time;});\n    return self.deferredNextId++;\n  };\n\n\n  /**\n   * @name ngMock.$browser#defer.now\n   * @propertyOf ngMock.$browser\n   *\n   * @description\n   * Current milliseconds mock time.\n   */\n  self.defer.now = 0;\n\n\n  self.defer.cancel = function(deferId) {\n    var fnIndex;\n\n    angular.forEach(self.deferredFns, function(fn, index) {\n      if (fn.id === deferId) fnIndex = index;\n    });\n\n    if (fnIndex !== undefined) {\n      self.deferredFns.splice(fnIndex, 1);\n      return true;\n    }\n\n    return false;\n  };\n\n\n  /**\n   * @name ngMock.$browser#defer.flush\n   * @methodOf ngMock.$browser\n   *\n   * @description\n   * Flushes all pending requests and executes the defer callbacks.\n   *\n   * @param {number=} number of milliseconds to flush. See {@link #defer.now}\n   */\n  self.defer.flush = function(delay) {\n    if (angular.isDefined(delay)) {\n      self.defer.now += delay;\n    } else {\n      if (self.deferredFns.length) {\n        self.defer.now = self.deferredFns[self.deferredFns.length-1].time;\n      } else {\n        throw new Error('No deferred tasks to be flushed');\n      }\n    }\n\n    while (self.deferredFns.length && self.deferredFns[0].time <= self.defer.now) {\n      self.deferredFns.shift().fn();\n    }\n  };\n\n  self.$$baseHref = '';\n  self.baseHref = function() {\n    return this.$$baseHref;\n  };\n};\nangular.mock.$Browser.prototype = {\n\n/**\n  * @name ngMock.$browser#poll\n  * @methodOf ngMock.$browser\n  *\n  * @description\n  * run all fns in pollFns\n  */\n  poll: function poll() {\n    angular.forEach(this.pollFns, function(pollFn){\n      pollFn();\n    });\n  },\n\n  addPollFn: function(pollFn) {\n    this.pollFns.push(pollFn);\n    return pollFn;\n  },\n\n  url: function(url, replace) {\n    if (url) {\n      this.$$url = url;\n      return this;\n    }\n\n    return this.$$url;\n  },\n\n  cookies:  function(name, value) {\n    if (name) {\n      if (angular.isUndefined(value)) {\n        delete this.cookieHash[name];\n      } else {\n        if (angular.isString(value) &&       //strings only\n            value.length <= 4096) {          //strict cookie storage limits\n          this.cookieHash[name] = value;\n        }\n      }\n    } else {\n      if (!angular.equals(this.cookieHash, this.lastCookieHash)) {\n        this.lastCookieHash = angular.copy(this.cookieHash);\n        this.cookieHash = angular.copy(this.cookieHash);\n      }\n      return this.cookieHash;\n    }\n  },\n\n  notifyWhenNoOutstandingRequests: function(fn) {\n    fn();\n  }\n};\n\n\n/**\n * @ngdoc object\n * @name ngMock.$exceptionHandlerProvider\n *\n * @description\n * Configures the mock implementation of {@link ng.$exceptionHandler} to rethrow or to log errors\n * passed into the `$exceptionHandler`.\n */\n\n/**\n * @ngdoc object\n * @name ngMock.$exceptionHandler\n *\n * @description\n * Mock implementation of {@link ng.$exceptionHandler} that rethrows or logs errors passed\n * into it. See {@link ngMock.$exceptionHandlerProvider $exceptionHandlerProvider} for configuration\n * information.\n *\n *\n * <pre>\n *   describe('$exceptionHandlerProvider', function() {\n *\n *     it('should capture log messages and exceptions', function() {\n *\n *       module(function($exceptionHandlerProvider) {\n *         $exceptionHandlerProvider.mode('log');\n *       });\n *\n *       inject(function($log, $exceptionHandler, $timeout) {\n *         $timeout(function() { $log.log(1); });\n *         $timeout(function() { $log.log(2); throw 'banana peel'; });\n *         $timeout(function() { $log.log(3); });\n *         expect($exceptionHandler.errors).toEqual([]);\n *         expect($log.assertEmpty());\n *         $timeout.flush();\n *         expect($exceptionHandler.errors).toEqual(['banana peel']);\n *         expect($log.log.logs).toEqual([[1], [2], [3]]);\n *       });\n *     });\n *   });\n * </pre>\n */\n\nangular.mock.$ExceptionHandlerProvider = function() {\n  var handler;\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$exceptionHandlerProvider#mode\n   * @methodOf ngMock.$exceptionHandlerProvider\n   *\n   * @description\n   * Sets the logging mode.\n   *\n   * @param {string} mode Mode of operation, defaults to `rethrow`.\n   *\n   *   - `rethrow`: If any errors are passed into the handler in tests, it typically\n   *                means that there is a bug in the application or test, so this mock will\n   *                make these tests fail.\n   *   - `log`: Sometimes it is desirable to test that an error is thrown, for this case the `log`\n   *            mode stores an array of errors in `$exceptionHandler.errors`, to allow later\n   *            assertion of them. See {@link ngMock.$log#assertEmpty assertEmpty()} and\n   *            {@link ngMock.$log#reset reset()}\n   */\n  this.mode = function(mode) {\n    switch(mode) {\n      case 'rethrow':\n        handler = function(e) {\n          throw e;\n        };\n        break;\n      case 'log':\n        var errors = [];\n\n        handler = function(e) {\n          if (arguments.length == 1) {\n            errors.push(e);\n          } else {\n            errors.push([].slice.call(arguments, 0));\n          }\n        };\n\n        handler.errors = errors;\n        break;\n      default:\n        throw new Error(\"Unknown mode '\" + mode + \"', only 'log'/'rethrow' modes are allowed!\");\n    }\n  };\n\n  this.$get = function() {\n    return handler;\n  };\n\n  this.mode('rethrow');\n};\n\n\n/**\n * @ngdoc service\n * @name ngMock.$log\n *\n * @description\n * Mock implementation of {@link ng.$log} that gathers all logged messages in arrays\n * (one array per logging level). These arrays are exposed as `logs` property of each of the\n * level-specific log function, e.g. for level `error` the array is exposed as `$log.error.logs`.\n *\n */\nangular.mock.$LogProvider = function() {\n  var debug = true;\n\n  function concat(array1, array2, index) {\n    return array1.concat(Array.prototype.slice.call(array2, index));\n  }\n\n  this.debugEnabled = function(flag) {\n    if (angular.isDefined(flag)) {\n      debug = flag;\n      return this;\n    } else {\n      return debug;\n    }\n  };\n\n  this.$get = function () {\n    var $log = {\n      log: function() { $log.log.logs.push(concat([], arguments, 0)); },\n      warn: function() { $log.warn.logs.push(concat([], arguments, 0)); },\n      info: function() { $log.info.logs.push(concat([], arguments, 0)); },\n      error: function() { $log.error.logs.push(concat([], arguments, 0)); },\n      debug: function() {\n        if (debug) {\n          $log.debug.logs.push(concat([], arguments, 0));\n        }\n      }\n    };\n\n    /**\n     * @ngdoc method\n     * @name ngMock.$log#reset\n     * @methodOf ngMock.$log\n     *\n     * @description\n     * Reset all of the logging arrays to empty.\n     */\n    $log.reset = function () {\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#log.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of messages logged using {@link ngMock.$log#log}.\n       *\n       * @example\n       * <pre>\n       * $log.log('Some Log');\n       * var first = $log.log.logs.unshift();\n       * </pre>\n       */\n      $log.log.logs = [];\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#info.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of messages logged using {@link ngMock.$log#info}.\n       *\n       * @example\n       * <pre>\n       * $log.info('Some Info');\n       * var first = $log.info.logs.unshift();\n       * </pre>\n       */\n      $log.info.logs = [];\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#warn.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of messages logged using {@link ngMock.$log#warn}.\n       *\n       * @example\n       * <pre>\n       * $log.warn('Some Warning');\n       * var first = $log.warn.logs.unshift();\n       * </pre>\n       */\n      $log.warn.logs = [];\n      /**\n       * @ngdoc property\n       * @name ngMock.$log#error.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of messages logged using {@link ngMock.$log#error}.\n       *\n       * @example\n       * <pre>\n       * $log.error('Some Error');\n       * var first = $log.error.logs.unshift();\n       * </pre>\n       */\n      $log.error.logs = [];\n        /**\n       * @ngdoc property\n       * @name ngMock.$log#debug.logs\n       * @propertyOf ngMock.$log\n       *\n       * @description\n       * Array of messages logged using {@link ngMock.$log#debug}.\n       *\n       * @example\n       * <pre>\n       * $log.debug('Some Error');\n       * var first = $log.debug.logs.unshift();\n       * </pre>\n       */\n      $log.debug.logs = [];\n    };\n\n    /**\n     * @ngdoc method\n     * @name ngMock.$log#assertEmpty\n     * @methodOf ngMock.$log\n     *\n     * @description\n     * Assert that the all of the logging methods have no logged messages. If messages present, an\n     * exception is thrown.\n     */\n    $log.assertEmpty = function() {\n      var errors = [];\n      angular.forEach(['error', 'warn', 'info', 'log', 'debug'], function(logLevel) {\n        angular.forEach($log[logLevel].logs, function(log) {\n          angular.forEach(log, function (logItem) {\n            errors.push('MOCK $log (' + logLevel + '): ' + String(logItem) + '\\n' +\n                        (logItem.stack || ''));\n          });\n        });\n      });\n      if (errors.length) {\n        errors.unshift(\"Expected $log to be empty! Either a message was logged unexpectedly, or \"+\n          \"an expected log message was not checked and removed:\");\n        errors.push('');\n        throw new Error(errors.join('\\n---------\\n'));\n      }\n    };\n\n    $log.reset();\n    return $log;\n  };\n};\n\n\n/**\n * @ngdoc service\n * @name ngMock.$interval\n *\n * @description\n * Mock implementation of the $interval service.\n *\n * Use {@link ngMock.$interval#methods_flush `$interval.flush(millis)`} to\n * move forward by `millis` milliseconds and trigger any functions scheduled to run in that\n * time.\n *\n * @param {function()} fn A function that should be called repeatedly.\n * @param {number} delay Number of milliseconds between each function call.\n * @param {number=} [count=0] Number of times to repeat. If not set, or 0, will repeat\n *   indefinitely.\n * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise\n *   will invoke `fn` within the {@link ng.$rootScope.Scope#methods_$apply $apply} block.\n * @returns {promise} A promise which will be notified on each iteration.\n */\nangular.mock.$IntervalProvider = function() {\n  this.$get = ['$rootScope', '$q',\n       function($rootScope,   $q) {\n    var repeatFns = [],\n        nextRepeatId = 0,\n        now = 0;\n\n    var $interval = function(fn, delay, count, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          iteration = 0,\n          skipApply = (angular.isDefined(invokeApply) && !invokeApply);\n\n      count = (angular.isDefined(count)) ? count : 0,\n      promise.then(null, null, fn);\n\n      promise.$$intervalId = nextRepeatId;\n\n      function tick() {\n        deferred.notify(iteration++);\n\n        if (count > 0 && iteration >= count) {\n          var fnIndex;\n          deferred.resolve(iteration);\n\n          angular.forEach(repeatFns, function(fn, index) {\n            if (fn.id === promise.$$intervalId) fnIndex = index;\n          });\n\n          if (fnIndex !== undefined) {\n            repeatFns.splice(fnIndex, 1);\n          }\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }\n\n      repeatFns.push({\n        nextTime:(now + delay),\n        delay: delay,\n        fn: tick,\n        id: nextRepeatId,\n        deferred: deferred\n      });\n      repeatFns.sort(function(a,b){ return a.nextTime - b.nextTime;});\n\n      nextRepeatId++;\n      return promise;\n    };\n\n    $interval.cancel = function(promise) {\n      if(!promise) return false;\n      var fnIndex;\n\n      angular.forEach(repeatFns, function(fn, index) {\n        if (fn.id === promise.$$intervalId) fnIndex = index;\n      });\n\n      if (fnIndex !== undefined) {\n        repeatFns[fnIndex].deferred.reject('canceled');\n        repeatFns.splice(fnIndex, 1);\n        return true;\n      }\n\n      return false;\n    };\n\n    /**\n     * @ngdoc method\n     * @name ngMock.$interval#flush\n     * @methodOf ngMock.$interval\n     * @description\n     *\n     * Runs interval tasks scheduled to be run in the next `millis` milliseconds.\n     *\n     * @param {number=} millis maximum timeout amount to flush up until.\n     *\n     * @return {number} The amount of time moved forward.\n     */\n    $interval.flush = function(millis) {\n      now += millis;\n      while (repeatFns.length && repeatFns[0].nextTime <= now) {\n        var task = repeatFns[0];\n        task.fn();\n        task.nextTime += task.delay;\n        repeatFns.sort(function(a,b){ return a.nextTime - b.nextTime;});\n      }\n      return millis;\n    };\n\n    return $interval;\n  }];\n};\n\n\n/* jshint -W101 */\n/* The R_ISO8061_STR regex is never going to fit into the 100 char limit!\n * This directive should go inside the anonymous function but a bug in JSHint means that it would\n * not be enacted early enough to prevent the warning.\n */\nvar R_ISO8061_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?:\\:?(\\d\\d)(?:\\:?(\\d\\d)(?:\\.(\\d{3}))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d)))?$/;\n\nfunction jsonStringToDate(string) {\n  var match;\n  if (match = string.match(R_ISO8061_STR)) {\n    var date = new Date(0),\n        tzHour = 0,\n        tzMin  = 0;\n    if (match[9]) {\n      tzHour = int(match[9] + match[10]);\n      tzMin = int(match[9] + match[11]);\n    }\n    date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));\n    date.setUTCHours(int(match[4]||0) - tzHour,\n                     int(match[5]||0) - tzMin,\n                     int(match[6]||0),\n                     int(match[7]||0));\n    return date;\n  }\n  return string;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\n/**\n * @ngdoc object\n * @name angular.mock.TzDate\n * @description\n *\n * *NOTE*: this is not an injectable instance, just a globally available mock class of `Date`.\n *\n * Mock of the Date type which has its timezone specified via constructor arg.\n *\n * The main purpose is to create Date-like instances with timezone fixed to the specified timezone\n * offset, so that we can test code that depends on local timezone settings without dependency on\n * the time zone settings of the machine where the code is running.\n *\n * @param {number} offset Offset of the *desired* timezone in hours (fractions will be honored)\n * @param {(number|string)} timestamp Timestamp representing the desired time in *UTC*\n *\n * @example\n * !!!! WARNING !!!!!\n * This is not a complete Date object so only methods that were implemented can be called safely.\n * To make matters worse, TzDate instances inherit stuff from Date via a prototype.\n *\n * We do our best to intercept calls to \"unimplemented\" methods, but since the list of methods is\n * incomplete we might be missing some non-standard methods. This can result in errors like:\n * \"Date.prototype.foo called on incompatible Object\".\n *\n * <pre>\n * var newYearInBratislava = new TzDate(-1, '2009-12-31T23:00:00Z');\n * newYearInBratislava.getTimezoneOffset() => -60;\n * newYearInBratislava.getFullYear() => 2010;\n * newYearInBratislava.getMonth() => 0;\n * newYearInBratislava.getDate() => 1;\n * newYearInBratislava.getHours() => 0;\n * newYearInBratislava.getMinutes() => 0;\n * newYearInBratislava.getSeconds() => 0;\n * </pre>\n *\n */\nangular.mock.TzDate = function (offset, timestamp) {\n  var self = new Date(0);\n  if (angular.isString(timestamp)) {\n    var tsStr = timestamp;\n\n    self.origDate = jsonStringToDate(timestamp);\n\n    timestamp = self.origDate.getTime();\n    if (isNaN(timestamp))\n      throw {\n        name: \"Illegal Argument\",\n        message: \"Arg '\" + tsStr + \"' passed into TzDate constructor is not a valid date string\"\n      };\n  } else {\n    self.origDate = new Date(timestamp);\n  }\n\n  var localOffset = new Date(timestamp).getTimezoneOffset();\n  self.offsetDiff = localOffset*60*1000 - offset*1000*60*60;\n  self.date = new Date(timestamp + self.offsetDiff);\n\n  self.getTime = function() {\n    return self.date.getTime() - self.offsetDiff;\n  };\n\n  self.toLocaleDateString = function() {\n    return self.date.toLocaleDateString();\n  };\n\n  self.getFullYear = function() {\n    return self.date.getFullYear();\n  };\n\n  self.getMonth = function() {\n    return self.date.getMonth();\n  };\n\n  self.getDate = function() {\n    return self.date.getDate();\n  };\n\n  self.getHours = function() {\n    return self.date.getHours();\n  };\n\n  self.getMinutes = function() {\n    return self.date.getMinutes();\n  };\n\n  self.getSeconds = function() {\n    return self.date.getSeconds();\n  };\n\n  self.getMilliseconds = function() {\n    return self.date.getMilliseconds();\n  };\n\n  self.getTimezoneOffset = function() {\n    return offset * 60;\n  };\n\n  self.getUTCFullYear = function() {\n    return self.origDate.getUTCFullYear();\n  };\n\n  self.getUTCMonth = function() {\n    return self.origDate.getUTCMonth();\n  };\n\n  self.getUTCDate = function() {\n    return self.origDate.getUTCDate();\n  };\n\n  self.getUTCHours = function() {\n    return self.origDate.getUTCHours();\n  };\n\n  self.getUTCMinutes = function() {\n    return self.origDate.getUTCMinutes();\n  };\n\n  self.getUTCSeconds = function() {\n    return self.origDate.getUTCSeconds();\n  };\n\n  self.getUTCMilliseconds = function() {\n    return self.origDate.getUTCMilliseconds();\n  };\n\n  self.getDay = function() {\n    return self.date.getDay();\n  };\n\n  // provide this method only on browsers that already have it\n  if (self.toISOString) {\n    self.toISOString = function() {\n      return padNumber(self.origDate.getUTCFullYear(), 4) + '-' +\n            padNumber(self.origDate.getUTCMonth() + 1, 2) + '-' +\n            padNumber(self.origDate.getUTCDate(), 2) + 'T' +\n            padNumber(self.origDate.getUTCHours(), 2) + ':' +\n            padNumber(self.origDate.getUTCMinutes(), 2) + ':' +\n            padNumber(self.origDate.getUTCSeconds(), 2) + '.' +\n            padNumber(self.origDate.getUTCMilliseconds(), 3) + 'Z';\n    };\n  }\n\n  //hide all methods not implemented in this mock that the Date prototype exposes\n  var unimplementedMethods = ['getUTCDay',\n      'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds',\n      'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear',\n      'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds',\n      'setYear', 'toDateString', 'toGMTString', 'toJSON', 'toLocaleFormat', 'toLocaleString',\n      'toLocaleTimeString', 'toSource', 'toString', 'toTimeString', 'toUTCString', 'valueOf'];\n\n  angular.forEach(unimplementedMethods, function(methodName) {\n    self[methodName] = function() {\n      throw new Error(\"Method '\" + methodName + \"' is not implemented in the TzDate mock\");\n    };\n  });\n\n  return self;\n};\n\n//make \"tzDateInstance instanceof Date\" return true\nangular.mock.TzDate.prototype = Date.prototype;\n/* jshint +W101 */\n\nangular.mock.animate = angular.module('ngAnimateMock', ['ng'])\n\n  .config(['$provide', function($provide) {\n    var reflowQueue = [];\n\n    $provide.value('$$animateReflow', function(fn) {\n      reflowQueue.push(fn);\n      return angular.noop;\n    });\n\n    $provide.decorator('$animate', function($delegate) {\n      var animate = {\n        queue : [],\n        enabled : $delegate.enabled,\n        triggerReflow : function() {\n          if(reflowQueue.length === 0) {\n            throw new Error('No animation reflows present');\n          }\n          angular.forEach(reflowQueue, function(fn) {\n            fn();\n          });\n          reflowQueue = [];\n        }\n      };\n\n      angular.forEach(\n        ['enter','leave','move','addClass','removeClass','setClass'], function(method) {\n        animate[method] = function() {\n          animate.queue.push({\n            event : method,\n            element : arguments[0],\n            args : arguments\n          });\n          $delegate[method].apply($delegate, arguments);\n        };\n      });\n\n      return animate;\n    });\n\n  }]);\n\n\n/**\n * @ngdoc function\n * @name angular.mock.dump\n * @description\n *\n * *NOTE*: this is not an injectable instance, just a globally available function.\n *\n * Method for serializing util angular objects (scope, elements, etc..) into strings, useful for\n * debugging.\n *\n * This method is also available on window, where it can be used to display objects on debug\n * console.\n *\n * @param {*} object - any object to turn into string.\n * @return {string} a serialized string of the argument\n */\nangular.mock.dump = function(object) {\n  return serialize(object);\n\n  function serialize(object) {\n    var out;\n\n    if (angular.isElement(object)) {\n      object = angular.element(object);\n      out = angular.element('<div></div>');\n      angular.forEach(object, function(element) {\n        out.append(angular.element(element).clone());\n      });\n      out = out.html();\n    } else if (angular.isArray(object)) {\n      out = [];\n      angular.forEach(object, function(o) {\n        out.push(serialize(o));\n      });\n      out = '[ ' + out.join(', ') + ' ]';\n    } else if (angular.isObject(object)) {\n      if (angular.isFunction(object.$eval) && angular.isFunction(object.$apply)) {\n        out = serializeScope(object);\n      } else if (object instanceof Error) {\n        out = object.stack || ('' + object.name + ': ' + object.message);\n      } else {\n        // TODO(i): this prevents methods being logged,\n        // we should have a better way to serialize objects\n        out = angular.toJson(object, true);\n      }\n    } else {\n      out = String(object);\n    }\n\n    return out;\n  }\n\n  function serializeScope(scope, offset) {\n    offset = offset ||  '  ';\n    var log = [offset + 'Scope(' + scope.$id + '): {'];\n    for ( var key in scope ) {\n      if (Object.prototype.hasOwnProperty.call(scope, key) && !key.match(/^(\\$|this)/)) {\n        log.push('  ' + key + ': ' + angular.toJson(scope[key]));\n      }\n    }\n    var child = scope.$$childHead;\n    while(child) {\n      log.push(serializeScope(child, offset + '  '));\n      child = child.$$nextSibling;\n    }\n    log.push('}');\n    return log.join('\\n' + offset);\n  }\n};\n\n/**\n * @ngdoc object\n * @name ngMock.$httpBackend\n * @description\n * Fake HTTP backend implementation suitable for unit testing applications that use the\n * {@link ng.$http $http service}.\n *\n * *Note*: For fake HTTP backend implementation suitable for end-to-end testing or backend-less\n * development please see {@link ngMockE2E.$httpBackend e2e $httpBackend mock}.\n *\n * During unit testing, we want our unit tests to run quickly and have no external dependencies so\n * we don’t want to send {@link https://developer.mozilla.org/en/xmlhttprequest XHR} or\n * {@link http://en.wikipedia.org/wiki/JSONP JSONP} requests to a real server. All we really need is\n * to verify whether a certain request has been sent or not, or alternatively just let the\n * application make requests, respond with pre-trained responses and assert that the end result is\n * what we expect it to be.\n *\n * This mock implementation can be used to respond with static or dynamic responses via the\n * `expect` and `when` apis and their shortcuts (`expectGET`, `whenPOST`, etc).\n *\n * When an Angular application needs some data from a server, it calls the $http service, which\n * sends the request to a real server using $httpBackend service. With dependency injection, it is\n * easy to inject $httpBackend mock (which has the same API as $httpBackend) and use it to verify\n * the requests and respond with some testing data without sending a request to real server.\n *\n * There are two ways to specify what test data should be returned as http responses by the mock\n * backend when the code under test makes http requests:\n *\n * - `$httpBackend.expect` - specifies a request expectation\n * - `$httpBackend.when` - specifies a backend definition\n *\n *\n * # Request Expectations vs Backend Definitions\n *\n * Request expectations provide a way to make assertions about requests made by the application and\n * to define responses for those requests. The test will fail if the expected requests are not made\n * or they are made in the wrong order.\n *\n * Backend definitions allow you to define a fake backend for your application which doesn't assert\n * if a particular request was made or not, it just returns a trained response if a request is made.\n * The test will pass whether or not the request gets made during testing.\n *\n *\n * <table class=\"table\">\n *   <tr><th width=\"220px\"></th><th>Request expectations</th><th>Backend definitions</th></tr>\n *   <tr>\n *     <th>Syntax</th>\n *     <td>.expect(...).respond(...)</td>\n *     <td>.when(...).respond(...)</td>\n *   </tr>\n *   <tr>\n *     <th>Typical usage</th>\n *     <td>strict unit tests</td>\n *     <td>loose (black-box) unit testing</td>\n *   </tr>\n *   <tr>\n *     <th>Fulfills multiple requests</th>\n *     <td>NO</td>\n *     <td>YES</td>\n *   </tr>\n *   <tr>\n *     <th>Order of requests matters</th>\n *     <td>YES</td>\n *     <td>NO</td>\n *   </tr>\n *   <tr>\n *     <th>Request required</th>\n *     <td>YES</td>\n *     <td>NO</td>\n *   </tr>\n *   <tr>\n *     <th>Response required</th>\n *     <td>optional (see below)</td>\n *     <td>YES</td>\n *   </tr>\n * </table>\n *\n * In cases where both backend definitions and request expectations are specified during unit\n * testing, the request expectations are evaluated first.\n *\n * If a request expectation has no response specified, the algorithm will search your backend\n * definitions for an appropriate response.\n *\n * If a request didn't match any expectation or if the expectation doesn't have the response\n * defined, the backend definitions are evaluated in sequential order to see if any of them match\n * the request. The response from the first matched definition is returned.\n *\n *\n * # Flushing HTTP requests\n *\n * The $httpBackend used in production always responds to requests with responses asynchronously.\n * If we preserved this behavior in unit testing we'd have to create async unit tests, which are\n * hard to write, understand, and maintain. However, the testing mock can't respond\n * synchronously because that would change the execution of the code under test. For this reason the\n * mock $httpBackend has a `flush()` method, which allows the test to explicitly flush pending\n * requests and thus preserve the async api of the backend while allowing the test to execute\n * synchronously.\n *\n *\n * # Unit testing with mock $httpBackend\n * The following code shows how to setup and use the mock backend when unit testing a controller.\n * First we create the controller under test:\n *\n  <pre>\n  // The controller code\n  function MyController($scope, $http) {\n    var authToken;\n\n    $http.get('/auth.py').success(function(data, status, headers) {\n      authToken = headers('A-Token');\n      $scope.user = data;\n    });\n\n    $scope.saveMessage = function(message) {\n      var headers = { 'Authorization': authToken };\n      $scope.status = 'Saving...';\n\n      $http.post('/add-msg.py', message, { headers: headers } ).success(function(response) {\n        $scope.status = '';\n      }).error(function() {\n        $scope.status = 'ERROR!';\n      });\n    };\n  }\n  </pre>\n *\n * Now we setup the mock backend and create the test specs:\n *\n  <pre>\n    // testing controller\n    describe('MyController', function() {\n       var $httpBackend, $rootScope, createController;\n\n       beforeEach(inject(function($injector) {\n         // Set up the mock http service responses\n         $httpBackend = $injector.get('$httpBackend');\n         // backend definition util for all tests\n         $httpBackend.when('GET', '/auth.py').respond({userId: 'userX'}, {'A-Token': 'xxx'});\n\n         // Get hold of a scope (i.e. the root scope)\n         $rootScope = $injector.get('$rootScope');\n         // The $controller service is used to create instances of controllers\n         var $controller = $injector.get('$controller');\n\n         createController = function() {\n           return $controller('MyController', {'$scope' : $rootScope });\n         };\n       }));\n\n\n       afterEach(function() {\n         $httpBackend.verifyNoOutstandingExpectation();\n         $httpBackend.verifyNoOutstandingRequest();\n       });\n\n\n       it('should fetch authentication token', function() {\n         $httpBackend.expectGET('/auth.py');\n         var controller = createController();\n         $httpBackend.flush();\n       });\n\n\n       it('should send msg to server', function() {\n         var controller = createController();\n         $httpBackend.flush();\n\n         // now you don’t care about the authentication, but\n         // the controller will still send the request and\n         // $httpBackend will respond without you having to\n         // specify the expectation and response for this request\n\n         $httpBackend.expectPOST('/add-msg.py', 'message content').respond(201, '');\n         $rootScope.saveMessage('message content');\n         expect($rootScope.status).toBe('Saving...');\n         $httpBackend.flush();\n         expect($rootScope.status).toBe('');\n       });\n\n\n       it('should send auth header', function() {\n         var controller = createController();\n         $httpBackend.flush();\n\n         $httpBackend.expectPOST('/add-msg.py', undefined, function(headers) {\n           // check if the header was send, if it wasn't the expectation won't\n           // match the request and the test will fail\n           return headers['Authorization'] == 'xxx';\n         }).respond(201, '');\n\n         $rootScope.saveMessage('whatever');\n         $httpBackend.flush();\n       });\n    });\n   </pre>\n */\nangular.mock.$HttpBackendProvider = function() {\n  this.$get = ['$rootScope', createHttpBackendMock];\n};\n\n/**\n * General factory function for $httpBackend mock.\n * Returns instance for unit testing (when no arguments specified):\n *   - passing through is disabled\n *   - auto flushing is disabled\n *\n * Returns instance for e2e testing (when `$delegate` and `$browser` specified):\n *   - passing through (delegating request to real backend) is enabled\n *   - auto flushing is enabled\n *\n * @param {Object=} $delegate Real $httpBackend instance (allow passing through if specified)\n * @param {Object=} $browser Auto-flushing enabled if specified\n * @return {Object} Instance of $httpBackend mock\n */\nfunction createHttpBackendMock($rootScope, $delegate, $browser) {\n  var definitions = [],\n      expectations = [],\n      responses = [],\n      responsesPush = angular.bind(responses, responses.push),\n      copy = angular.copy;\n\n  function createResponse(status, data, headers) {\n    if (angular.isFunction(status)) return status;\n\n    return function() {\n      return angular.isNumber(status)\n          ? [status, data, headers]\n          : [200, status, data];\n    };\n  }\n\n  // TODO(vojta): change params to: method, url, data, headers, callback\n  function $httpBackend(method, url, data, callback, headers, timeout, withCredentials) {\n    var xhr = new MockXhr(),\n        expectation = expectations[0],\n        wasExpected = false;\n\n    function prettyPrint(data) {\n      return (angular.isString(data) || angular.isFunction(data) || data instanceof RegExp)\n          ? data\n          : angular.toJson(data);\n    }\n\n    function wrapResponse(wrapped) {\n      if (!$browser && timeout && timeout.then) timeout.then(handleTimeout);\n\n      return handleResponse;\n\n      function handleResponse() {\n        var response = wrapped.response(method, url, data, headers);\n        xhr.$$respHeaders = response[2];\n        callback(copy(response[0]), copy(response[1]), xhr.getAllResponseHeaders());\n      }\n\n      function handleTimeout() {\n        for (var i = 0, ii = responses.length; i < ii; i++) {\n          if (responses[i] === handleResponse) {\n            responses.splice(i, 1);\n            callback(-1, undefined, '');\n            break;\n          }\n        }\n      }\n    }\n\n    if (expectation && expectation.match(method, url)) {\n      if (!expectation.matchData(data))\n        throw new Error('Expected ' + expectation + ' with different data\\n' +\n            'EXPECTED: ' + prettyPrint(expectation.data) + '\\nGOT:      ' + data);\n\n      if (!expectation.matchHeaders(headers))\n        throw new Error('Expected ' + expectation + ' with different headers\\n' +\n                        'EXPECTED: ' + prettyPrint(expectation.headers) + '\\nGOT:      ' +\n                        prettyPrint(headers));\n\n      expectations.shift();\n\n      if (expectation.response) {\n        responses.push(wrapResponse(expectation));\n        return;\n      }\n      wasExpected = true;\n    }\n\n    var i = -1, definition;\n    while ((definition = definitions[++i])) {\n      if (definition.match(method, url, data, headers || {})) {\n        if (definition.response) {\n          // if $browser specified, we do auto flush all requests\n          ($browser ? $browser.defer : responsesPush)(wrapResponse(definition));\n        } else if (definition.passThrough) {\n          $delegate(method, url, data, callback, headers, timeout, withCredentials);\n        } else throw new Error('No response defined !');\n        return;\n      }\n    }\n    throw wasExpected ?\n        new Error('No response defined !') :\n        new Error('Unexpected request: ' + method + ' ' + url + '\\n' +\n                  (expectation ? 'Expected ' + expectation : 'No more request expected'));\n  }\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#when\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition.\n   *\n   * @param {string} method HTTP method.\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives\n   *   data string and returns true if the data is as expected.\n   * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header\n   *   object and returns true if the headers match the current definition.\n   * @returns {requestHandler} Returns an object with `respond` method that controls how a matched\n   *   request is handled.\n   *\n   *  - respond –\n   *      `{function([status,] data[, headers])|function(function(method, url, data, headers)}`\n   *    – The respond method takes a set of static data to be returned or a function that can return\n   *    an array containing response status (number), response data (string) and response headers\n   *    (Object).\n   */\n  $httpBackend.when = function(method, url, data, headers) {\n    var definition = new MockHttpExpectation(method, url, data, headers),\n        chain = {\n          respond: function(status, data, headers) {\n            definition.response = createResponse(status, data, headers);\n          }\n        };\n\n    if ($browser) {\n      chain.passThrough = function() {\n        definition.passThrough = true;\n      };\n    }\n\n    definitions.push(definition);\n    return chain;\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenGET\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for GET requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenHEAD\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for HEAD requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenDELETE\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for DELETE requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenPOST\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for POST requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives\n   *   data string and returns true if the data is as expected.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenPUT\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for PUT requests.  For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives\n   *   data string and returns true if the data is as expected.\n   * @param {(Object|function(Object))=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#whenJSONP\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new backend definition for JSONP requests. For more info see `when()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled.\n   */\n  createShortMethods('when');\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expect\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation.\n   *\n   * @param {string} method HTTP method.\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that\n   *  receives data string and returns true if the data is as expected, or Object if request body\n   *  is in JSON format.\n   * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header\n   *   object and returns true if the headers match the current expectation.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *  request is handled.\n   *\n   *  - respond –\n   *    `{function([status,] data[, headers])|function(function(method, url, data, headers)}`\n   *    – The respond method takes a set of static data to be returned or a function that can return\n   *    an array containing response status (number), response data (string) and response headers\n   *    (Object).\n   */\n  $httpBackend.expect = function(method, url, data, headers) {\n    var expectation = new MockHttpExpectation(method, url, data, headers);\n    expectations.push(expectation);\n    return {\n      respond: function(status, data, headers) {\n        expectation.response = createResponse(status, data, headers);\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectGET\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for GET requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   * request is handled. See #expect for more info.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectHEAD\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for HEAD requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectDELETE\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for DELETE requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectPOST\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for POST requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that\n   *  receives data string and returns true if the data is as expected, or Object if request body\n   *  is in JSON format.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectPUT\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for PUT requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that\n   *  receives data string and returns true if the data is as expected, or Object if request body\n   *  is in JSON format.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectPATCH\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for PATCH requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that\n   *  receives data string and returns true if the data is as expected, or Object if request body\n   *  is in JSON format.\n   * @param {Object=} headers HTTP headers.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#expectJSONP\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Creates a new request expectation for JSONP requests. For more info see `expect()`.\n   *\n   * @param {string|RegExp} url HTTP url.\n   * @returns {requestHandler} Returns an object with `respond` method that control how a matched\n   *   request is handled.\n   */\n  createShortMethods('expect');\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#flush\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Flushes all pending requests using the trained responses.\n   *\n   * @param {number=} count Number of responses to flush (in the order they arrived). If undefined,\n   *   all pending requests will be flushed. If there are no pending requests when the flush method\n   *   is called an exception is thrown (as this typically a sign of programming error).\n   */\n  $httpBackend.flush = function(count) {\n    $rootScope.$digest();\n    if (!responses.length) throw new Error('No pending request to flush !');\n\n    if (angular.isDefined(count)) {\n      while (count--) {\n        if (!responses.length) throw new Error('No more pending request to flush !');\n        responses.shift()();\n      }\n    } else {\n      while (responses.length) {\n        responses.shift()();\n      }\n    }\n    $httpBackend.verifyNoOutstandingExpectation();\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#verifyNoOutstandingExpectation\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Verifies that all of the requests defined via the `expect` api were made. If any of the\n   * requests were not made, verifyNoOutstandingExpectation throws an exception.\n   *\n   * Typically, you would call this method following each test case that asserts requests using an\n   * \"afterEach\" clause.\n   *\n   * <pre>\n   *   afterEach($httpBackend.verifyNoOutstandingExpectation);\n   * </pre>\n   */\n  $httpBackend.verifyNoOutstandingExpectation = function() {\n    $rootScope.$digest();\n    if (expectations.length) {\n      throw new Error('Unsatisfied requests: ' + expectations.join(', '));\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#verifyNoOutstandingRequest\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Verifies that there are no outstanding requests that need to be flushed.\n   *\n   * Typically, you would call this method following each test case that asserts requests using an\n   * \"afterEach\" clause.\n   *\n   * <pre>\n   *   afterEach($httpBackend.verifyNoOutstandingRequest);\n   * </pre>\n   */\n  $httpBackend.verifyNoOutstandingRequest = function() {\n    if (responses.length) {\n      throw new Error('Unflushed requests: ' + responses.length);\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$httpBackend#resetExpectations\n   * @methodOf ngMock.$httpBackend\n   * @description\n   * Resets all request expectations, but preserves all backend definitions. Typically, you would\n   * call resetExpectations during a multiple-phase test when you want to reuse the same instance of\n   * $httpBackend mock.\n   */\n  $httpBackend.resetExpectations = function() {\n    expectations.length = 0;\n    responses.length = 0;\n  };\n\n  return $httpBackend;\n\n\n  function createShortMethods(prefix) {\n    angular.forEach(['GET', 'DELETE', 'JSONP'], function(method) {\n     $httpBackend[prefix + method] = function(url, headers) {\n       return $httpBackend[prefix](method, url, undefined, headers);\n     };\n    });\n\n    angular.forEach(['PUT', 'POST', 'PATCH'], function(method) {\n      $httpBackend[prefix + method] = function(url, data, headers) {\n        return $httpBackend[prefix](method, url, data, headers);\n      };\n    });\n  }\n}\n\nfunction MockHttpExpectation(method, url, data, headers) {\n\n  this.data = data;\n  this.headers = headers;\n\n  this.match = function(m, u, d, h) {\n    if (method != m) return false;\n    if (!this.matchUrl(u)) return false;\n    if (angular.isDefined(d) && !this.matchData(d)) return false;\n    if (angular.isDefined(h) && !this.matchHeaders(h)) return false;\n    return true;\n  };\n\n  this.matchUrl = function(u) {\n    if (!url) return true;\n    if (angular.isFunction(url.test)) return url.test(u);\n    return url == u;\n  };\n\n  this.matchHeaders = function(h) {\n    if (angular.isUndefined(headers)) return true;\n    if (angular.isFunction(headers)) return headers(h);\n    return angular.equals(headers, h);\n  };\n\n  this.matchData = function(d) {\n    if (angular.isUndefined(data)) return true;\n    if (data && angular.isFunction(data.test)) return data.test(d);\n    if (data && angular.isFunction(data)) return data(d);\n    if (data && !angular.isString(data)) return angular.equals(data, angular.fromJson(d));\n    return data == d;\n  };\n\n  this.toString = function() {\n    return method + ' ' + url;\n  };\n}\n\nfunction createMockXhr() {\n  return new MockXhr();\n}\n\nfunction MockXhr() {\n\n  // hack for testing $http, $httpBackend\n  MockXhr.$$lastInstance = this;\n\n  this.open = function(method, url, async) {\n    this.$$method = method;\n    this.$$url = url;\n    this.$$async = async;\n    this.$$reqHeaders = {};\n    this.$$respHeaders = {};\n  };\n\n  this.send = function(data) {\n    this.$$data = data;\n  };\n\n  this.setRequestHeader = function(key, value) {\n    this.$$reqHeaders[key] = value;\n  };\n\n  this.getResponseHeader = function(name) {\n    // the lookup must be case insensitive,\n    // that's why we try two quick lookups first and full scan last\n    var header = this.$$respHeaders[name];\n    if (header) return header;\n\n    name = angular.lowercase(name);\n    header = this.$$respHeaders[name];\n    if (header) return header;\n\n    header = undefined;\n    angular.forEach(this.$$respHeaders, function(headerVal, headerName) {\n      if (!header && angular.lowercase(headerName) == name) header = headerVal;\n    });\n    return header;\n  };\n\n  this.getAllResponseHeaders = function() {\n    var lines = [];\n\n    angular.forEach(this.$$respHeaders, function(value, key) {\n      lines.push(key + ': ' + value);\n    });\n    return lines.join('\\n');\n  };\n\n  this.abort = angular.noop;\n}\n\n\n/**\n * @ngdoc function\n * @name ngMock.$timeout\n * @description\n *\n * This service is just a simple decorator for {@link ng.$timeout $timeout} service\n * that adds a \"flush\" and \"verifyNoPendingTasks\" methods.\n */\n\nangular.mock.$TimeoutDecorator = function($delegate, $browser) {\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$timeout#flush\n   * @methodOf ngMock.$timeout\n   * @description\n   *\n   * Flushes the queue of pending tasks.\n   *\n   * @param {number=} delay maximum timeout amount to flush up until\n   */\n  $delegate.flush = function(delay) {\n    $browser.defer.flush(delay);\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngMock.$timeout#verifyNoPendingTasks\n   * @methodOf ngMock.$timeout\n   * @description\n   *\n   * Verifies that there are no pending tasks that need to be flushed.\n   */\n  $delegate.verifyNoPendingTasks = function() {\n    if ($browser.deferredFns.length) {\n      throw new Error('Deferred tasks to flush (' + $browser.deferredFns.length + '): ' +\n          formatPendingTasksAsString($browser.deferredFns));\n    }\n  };\n\n  function formatPendingTasksAsString(tasks) {\n    var result = [];\n    angular.forEach(tasks, function(task) {\n      result.push('{id: ' + task.id + ', ' + 'time: ' + task.time + '}');\n    });\n\n    return result.join(', ');\n  }\n\n  return $delegate;\n};\n\n/**\n *\n */\nangular.mock.$RootElementProvider = function() {\n  this.$get = function() {\n    return angular.element('<div ng-app></div>');\n  };\n};\n\n/**\n * @ngdoc overview\n * @name ngMock\n * @description\n *\n * # ngMock\n *\n * The `ngMock` module providers support to inject and mock Angular services into unit tests.\n * In addition, ngMock also extends various core ng services such that they can be\n * inspected and controlled in a synchronous manner within test code.\n *\n * {@installModule mock}\n *\n * <div doc-module-components=\"ngMock\"></div>\n *\n */\nangular.module('ngMock', ['ng']).provider({\n  $browser: angular.mock.$BrowserProvider,\n  $exceptionHandler: angular.mock.$ExceptionHandlerProvider,\n  $log: angular.mock.$LogProvider,\n  $interval: angular.mock.$IntervalProvider,\n  $httpBackend: angular.mock.$HttpBackendProvider,\n  $rootElement: angular.mock.$RootElementProvider\n}).config(['$provide', function($provide) {\n  $provide.decorator('$timeout', angular.mock.$TimeoutDecorator);\n}]);\n\n/**\n * @ngdoc overview\n * @name ngMockE2E\n * @description\n *\n * The `ngMockE2E` is an angular module which contains mocks suitable for end-to-end testing.\n * Currently there is only one mock present in this module -\n * the {@link ngMockE2E.$httpBackend e2e $httpBackend} mock.\n */\nangular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {\n  $provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator);\n}]);\n\n/**\n * @ngdoc object\n * @name ngMockE2E.$httpBackend\n * @description\n * Fake HTTP backend implementation suitable for end-to-end testing or backend-less development of\n * applications that use the {@link ng.$http $http service}.\n *\n * *Note*: For fake http backend implementation suitable for unit testing please see\n * {@link ngMock.$httpBackend unit-testing $httpBackend mock}.\n *\n * This implementation can be used to respond with static or dynamic responses via the `when` api\n * and its shortcuts (`whenGET`, `whenPOST`, etc) and optionally pass through requests to the\n * real $httpBackend for specific requests (e.g. to interact with certain remote apis or to fetch\n * templates from a webserver).\n *\n * As opposed to unit-testing, in an end-to-end testing scenario or in scenario when an application\n * is being developed with the real backend api replaced with a mock, it is often desirable for\n * certain category of requests to bypass the mock and issue a real http request (e.g. to fetch\n * templates or static files from the webserver). To configure the backend with this behavior\n * use the `passThrough` request handler of `when` instead of `respond`.\n *\n * Additionally, we don't want to manually have to flush mocked out requests like we do during unit\n * testing. For this reason the e2e $httpBackend automatically flushes mocked out requests\n * automatically, closely simulating the behavior of the XMLHttpRequest object.\n *\n * To setup the application to run with this http backend, you have to create a module that depends\n * on the `ngMockE2E` and your application modules and defines the fake backend:\n *\n * <pre>\n *   myAppDev = angular.module('myAppDev', ['myApp', 'ngMockE2E']);\n *   myAppDev.run(function($httpBackend) {\n *     phones = [{name: 'phone1'}, {name: 'phone2'}];\n *\n *     // returns the current list of phones\n *     $httpBackend.whenGET('/phones').respond(phones);\n *\n *     // adds a new phone to the phones array\n *     $httpBackend.whenPOST('/phones').respond(function(method, url, data) {\n *       phones.push(angular.fromJson(data));\n *     });\n *     $httpBackend.whenGET(/^\\/templates\\//).passThrough();\n *     //...\n *   });\n * </pre>\n *\n * Afterwards, bootstrap your app with this new module.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#when\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition.\n *\n * @param {string} method HTTP method.\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header\n *   object and returns true if the headers match the current definition.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n *\n *  - respond –\n *    `{function([status,] data[, headers])|function(function(method, url, data, headers)}`\n *    – The respond method takes a set of static data to be returned or a function that can return\n *    an array containing response status (number), response data (string) and response headers\n *    (Object).\n *  - passThrough – `{function()}` – Any request matching a backend definition with `passThrough`\n *    handler, will be pass through to the real backend (an XHR request will be made to the\n *    server.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenGET\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for GET requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenHEAD\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for HEAD requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenDELETE\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for DELETE requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenPOST\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for POST requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenPUT\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for PUT requests.  For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenPATCH\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for PATCH requests.  For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @param {(string|RegExp)=} data HTTP request body.\n * @param {(Object|function(Object))=} headers HTTP headers.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\n\n/**\n * @ngdoc method\n * @name ngMockE2E.$httpBackend#whenJSONP\n * @methodOf ngMockE2E.$httpBackend\n * @description\n * Creates a new backend definition for JSONP requests. For more info see `when()`.\n *\n * @param {string|RegExp} url HTTP url.\n * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that\n *   control how a matched request is handled.\n */\nangular.mock.e2e = {};\nangular.mock.e2e.$httpBackendDecorator =\n  ['$rootScope', '$delegate', '$browser', createHttpBackendMock];\n\n\nangular.mock.clearDataCache = function() {\n  var key,\n      cache = angular.element.cache;\n\n  for(key in cache) {\n    if (Object.prototype.hasOwnProperty.call(cache,key)) {\n      var handle = cache[key].handle;\n\n      handle && angular.element(handle.elem).off();\n      delete cache[key];\n    }\n  }\n};\n\n\nif(window.jasmine || window.mocha) {\n\n  var currentSpec = null,\n      isSpecRunning = function() {\n        return !!currentSpec;\n      };\n\n\n  beforeEach(function() {\n    currentSpec = this;\n  });\n\n  afterEach(function() {\n    var injector = currentSpec.$injector;\n\n    currentSpec.$injector = null;\n    currentSpec.$modules = null;\n    currentSpec = null;\n\n    if (injector) {\n      injector.get('$rootElement').off();\n      injector.get('$browser').pollFns.length = 0;\n    }\n\n    angular.mock.clearDataCache();\n\n    // clean up jquery's fragment cache\n    angular.forEach(angular.element.fragments, function(val, key) {\n      delete angular.element.fragments[key];\n    });\n\n    MockXhr.$$lastInstance = null;\n\n    angular.forEach(angular.callbacks, function(val, key) {\n      delete angular.callbacks[key];\n    });\n    angular.callbacks.counter = 0;\n  });\n\n  /**\n   * @ngdoc function\n   * @name angular.mock.module\n   * @description\n   *\n   * *NOTE*: This function is also published on window for easy access.<br>\n   *\n   * This function registers a module configuration code. It collects the configuration information\n   * which will be used when the injector is created by {@link angular.mock.inject inject}.\n   *\n   * See {@link angular.mock.inject inject} for usage example\n   *\n   * @param {...(string|Function|Object)} fns any number of modules which are represented as string\n   *        aliases or as anonymous module initialization functions. The modules are used to\n   *        configure the injector. The 'ng' and 'ngMock' modules are automatically loaded. If an\n   *        object literal is passed they will be register as values in the module, the key being\n   *        the module name and the value being what is returned.\n   */\n  window.module = angular.mock.module = function() {\n    var moduleFns = Array.prototype.slice.call(arguments, 0);\n    return isSpecRunning() ? workFn() : workFn;\n    /////////////////////\n    function workFn() {\n      if (currentSpec.$injector) {\n        throw new Error('Injector already created, can not register a module!');\n      } else {\n        var modules = currentSpec.$modules || (currentSpec.$modules = []);\n        angular.forEach(moduleFns, function(module) {\n          if (angular.isObject(module) && !angular.isArray(module)) {\n            modules.push(function($provide) {\n              angular.forEach(module, function(value, key) {\n                $provide.value(key, value);\n              });\n            });\n          } else {\n            modules.push(module);\n          }\n        });\n      }\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name angular.mock.inject\n   * @description\n   *\n   * *NOTE*: This function is also published on window for easy access.<br>\n   *\n   * The inject function wraps a function into an injectable function. The inject() creates new\n   * instance of {@link AUTO.$injector $injector} per test, which is then used for\n   * resolving references.\n   *\n   *\n   * ## Resolving References (Underscore Wrapping)\n   * Often, we would like to inject a reference once, in a `beforeEach()` block and reuse this\n   * in multiple `it()` clauses. To be able to do this we must assign the reference to a variable\n   * that is declared in the scope of the `describe()` block. Since we would, most likely, want\n   * the variable to have the same name of the reference we have a problem, since the parameter\n   * to the `inject()` function would hide the outer variable.\n   *\n   * To help with this, the injected parameters can, optionally, be enclosed with underscores.\n   * These are ignored by the injector when the reference name is resolved.\n   *\n   * For example, the parameter `_myService_` would be resolved as the reference `myService`.\n   * Since it is available in the function body as _myService_, we can then assign it to a variable\n   * defined in an outer scope.\n   *\n   * ```\n   * // Defined out reference variable outside\n   * var myService;\n   *\n   * // Wrap the parameter in underscores\n   * beforeEach( inject( function(_myService_){\n   *   myService = _myService_;\n   * }));\n   *\n   * // Use myService in a series of tests.\n   * it('makes use of myService', function() {\n   *   myService.doStuff();\n   * });\n   *\n   * ```\n   *\n   * See also {@link angular.mock.module angular.mock.module}\n   *\n   * ## Example\n   * Example of what a typical jasmine tests looks like with the inject method.\n   * <pre>\n   *\n   *   angular.module('myApplicationModule', [])\n   *       .value('mode', 'app')\n   *       .value('version', 'v1.0.1');\n   *\n   *\n   *   describe('MyApp', function() {\n   *\n   *     // You need to load modules that you want to test,\n   *     // it loads only the \"ng\" module by default.\n   *     beforeEach(module('myApplicationModule'));\n   *\n   *\n   *     // inject() is used to inject arguments of all given functions\n   *     it('should provide a version', inject(function(mode, version) {\n   *       expect(version).toEqual('v1.0.1');\n   *       expect(mode).toEqual('app');\n   *     }));\n   *\n   *\n   *     // The inject and module method can also be used inside of the it or beforeEach\n   *     it('should override a version and test the new version is injected', function() {\n   *       // module() takes functions or strings (module aliases)\n   *       module(function($provide) {\n   *         $provide.value('version', 'overridden'); // override version here\n   *       });\n   *\n   *       inject(function(version) {\n   *         expect(version).toEqual('overridden');\n   *       });\n   *     });\n   *   });\n   *\n   * </pre>\n   *\n   * @param {...Function} fns any number of functions which will be injected using the injector.\n   */\n\n\n\n  var ErrorAddingDeclarationLocationStack = function(e, errorForStack) {\n    this.message = e.message;\n    this.name = e.name;\n    if (e.line) this.line = e.line;\n    if (e.sourceId) this.sourceId = e.sourceId;\n    if (e.stack && errorForStack)\n      this.stack = e.stack + '\\n' + errorForStack.stack;\n    if (e.stackArray) this.stackArray = e.stackArray;\n  };\n  ErrorAddingDeclarationLocationStack.prototype.toString = Error.prototype.toString;\n\n  window.inject = angular.mock.inject = function() {\n    var blockFns = Array.prototype.slice.call(arguments, 0);\n    var errorForStack = new Error('Declaration Location');\n    return isSpecRunning() ? workFn.call(currentSpec) : workFn;\n    /////////////////////\n    function workFn() {\n      var modules = currentSpec.$modules || [];\n\n      modules.unshift('ngMock');\n      modules.unshift('ng');\n      var injector = currentSpec.$injector;\n      if (!injector) {\n        injector = currentSpec.$injector = angular.injector(modules);\n      }\n      for(var i = 0, ii = blockFns.length; i < ii; i++) {\n        try {\n          /* jshint -W040 *//* Jasmine explicitly provides a `this` object when calling functions */\n          injector.invoke(blockFns[i] || angular.noop, this);\n          /* jshint +W040 */\n        } catch (e) {\n          if (e.stack && errorForStack) {\n            throw new ErrorAddingDeclarationLocationStack(e, errorForStack);\n          }\n          throw e;\n        } finally {\n          errorForStack = null;\n        }\n      }\n    }\n  };\n}\n\n\n})(window, window.angular);"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/angular-resource_1.2.13/angular-resource.js",
    "content": "/**\n * @license AngularJS v1.2.13\n * (c) 2010-2014 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {'use strict';\n\nvar $resourceMinErr = angular.$$minErr('$resource');\n\n// Helper functions and regex to lookup a dotted path on an object\n// stopping at undefined/null.  The path must be composed of ASCII\n// identifiers (just like $parse)\nvar MEMBER_NAME_REGEX = /^(\\.[a-zA-Z_$][0-9a-zA-Z_$]*)+$/;\n\nfunction isValidDottedPath(path) {\n  return (path != null && path !== '' && path !== 'hasOwnProperty' &&\n      MEMBER_NAME_REGEX.test('.' + path));\n}\n\nfunction lookupDottedPath(obj, path) {\n  if (!isValidDottedPath(path)) {\n    throw $resourceMinErr('badmember', 'Dotted member path \"@{0}\" is invalid.', path);\n  }\n  var keys = path.split('.');\n  for (var i = 0, ii = keys.length; i < ii && obj !== undefined; i++) {\n    var key = keys[i];\n    obj = (obj !== null) ? obj[key] : undefined;\n  }\n  return obj;\n}\n\n/**\n * Create a shallow copy of an object and clear other fields from the destination\n */\nfunction shallowClearAndCopy(src, dst) {\n  dst = dst || {};\n\n  angular.forEach(dst, function(value, key){\n    delete dst[key];\n  });\n\n  for (var key in src) {\n    if (src.hasOwnProperty(key) && !(key.charAt(0) === '$' && key.charAt(1) === '$')) {\n      dst[key] = src[key];\n    }\n  }\n\n  return dst;\n}\n\n/**\n * @ngdoc overview\n * @name ngResource\n * @description\n *\n * # ngResource\n *\n * The `ngResource` module provides interaction support with RESTful services\n * via the $resource service.\n *\n * {@installModule resource}\n *\n * <div doc-module-components=\"ngResource\"></div>\n *\n * See {@link ngResource.$resource `$resource`} for usage.\n */\n\n/**\n * @ngdoc object\n * @name ngResource.$resource\n * @requires $http\n *\n * @description\n * A factory which creates a resource object that lets you interact with\n * [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) server-side data sources.\n *\n * The returned resource object has action methods which provide high-level behaviors without\n * the need to interact with the low level {@link ng.$http $http} service.\n *\n * Requires the {@link ngResource `ngResource`} module to be installed.\n *\n * @param {string} url A parametrized URL template with parameters prefixed by `:` as in\n *   `/user/:username`. If you are using a URL with a port number (e.g.\n *   `http://example.com:8080/api`), it will be respected.\n *\n *   If you are using a url with a suffix, just add the suffix, like this:\n *   `$resource('http://example.com/resource.json')` or `$resource('http://example.com/:id.json')`\n *   or even `$resource('http://example.com/resource/:resource_id.:format')`\n *   If the parameter before the suffix is empty, :resource_id in this case, then the `/.` will be\n *   collapsed down to a single `.`.  If you need this sequence to appear and not collapse then you\n *   can escape it with `/\\.`.\n *\n * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in\n *   `actions` methods. If any of the parameter value is a function, it will be executed every time\n *   when a param value needs to be obtained for a request (unless the param was overridden).\n *\n *   Each key value in the parameter object is first bound to url template if present and then any\n *   excess keys are appended to the url search query after the `?`.\n *\n *   Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in\n *   URL `/path/greet?salutation=Hello`.\n *\n *   If the parameter value is prefixed with `@` then the value of that parameter is extracted from\n *   the data object (useful for non-GET operations).\n *\n * @param {Object.<Object>=} actions Hash with declaration of custom action that should extend the\n *   default set of resource actions. The declaration should be created in the format of {@link\n *   ng.$http#usage_parameters $http.config}:\n *\n *       {action1: {method:?, params:?, isArray:?, headers:?, ...},\n *        action2: {method:?, params:?, isArray:?, headers:?, ...},\n *        ...}\n *\n *   Where:\n *\n *   - **`action`** – {string} – The name of action. This name becomes the name of the method on\n *     your resource object.\n *   - **`method`** – {string} – HTTP request method. Valid methods are: `GET`, `POST`, `PUT`,\n *     `DELETE`, and `JSONP`.\n *   - **`params`** – {Object=} – Optional set of pre-bound parameters for this action. If any of\n *     the parameter value is a function, it will be executed every time when a param value needs to\n *     be obtained for a request (unless the param was overridden).\n *   - **`url`** – {string} – action specific `url` override. The url templating is supported just\n *     like for the resource-level urls.\n *   - **`isArray`** – {boolean=} – If true then the returned object for this action is an array,\n *     see `returns` section.\n *   - **`transformRequest`** –\n *     `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n *     transform function or an array of such functions. The transform function takes the http\n *     request body and headers and returns its transformed (typically serialized) version.\n *   - **`transformResponse`** –\n *     `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n *     transform function or an array of such functions. The transform function takes the http\n *     response body and headers and returns its transformed (typically deserialized) version.\n *   - **`cache`** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n *     GET request, otherwise if a cache instance built with\n *     {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n *     caching.\n *   - **`timeout`** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise} that\n *     should abort the request when resolved.\n *   - **`withCredentials`** - `{boolean}` - whether to set the `withCredentials` flag on the\n *     XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5\n *     requests with credentials} for more information.\n *   - **`responseType`** - `{string}` - see {@link\n *     https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType requestType}.\n *   - **`interceptor`** - `{Object=}` - The interceptor object has two optional methods -\n *     `response` and `responseError`. Both `response` and `responseError` interceptors get called\n *     with `http response` object. See {@link ng.$http $http interceptors}.\n *\n * @returns {Object} A resource \"class\" object with methods for the default set of resource actions\n *   optionally extended with custom `actions`. The default set contains these actions:\n *\n *       { 'get':    {method:'GET'},\n *         'save':   {method:'POST'},\n *         'query':  {method:'GET', isArray:true},\n *         'remove': {method:'DELETE'},\n *         'delete': {method:'DELETE'} };\n *\n *   Calling these methods invoke an {@link ng.$http} with the specified http method,\n *   destination and parameters. When the data is returned from the server then the object is an\n *   instance of the resource class. The actions `save`, `remove` and `delete` are available on it\n *   as  methods with the `$` prefix. This allows you to easily perform CRUD operations (create,\n *   read, update, delete) on server-side data like this:\n *   <pre>\n        var User = $resource('/user/:userId', {userId:'@id'});\n        var user = User.get({userId:123}, function() {\n          user.abc = true;\n          user.$save();\n        });\n     </pre>\n *\n *   It is important to realize that invoking a $resource object method immediately returns an\n *   empty reference (object or array depending on `isArray`). Once the data is returned from the\n *   server the existing reference is populated with the actual data. This is a useful trick since\n *   usually the resource is assigned to a model which is then rendered by the view. Having an empty\n *   object results in no rendering, once the data arrives from the server then the object is\n *   populated with the data and the view automatically re-renders itself showing the new data. This\n *   means that in most cases one never has to write a callback function for the action methods.\n *\n *   The action methods on the class object or instance object can be invoked with the following\n *   parameters:\n *\n *   - HTTP GET \"class\" actions: `Resource.action([parameters], [success], [error])`\n *   - non-GET \"class\" actions: `Resource.action([parameters], postData, [success], [error])`\n *   - non-GET instance actions:  `instance.$action([parameters], [success], [error])`\n *\n *   Success callback is called with (value, responseHeaders) arguments. Error callback is called\n *   with (httpResponse) argument.\n *\n *   Class actions return empty instance (with additional properties below).\n *   Instance actions return promise of the action.\n *\n *   The Resource instances and collection have these additional properties:\n *\n *   - `$promise`: the {@link ng.$q promise} of the original server interaction that created this\n *     instance or collection.\n *\n *     On success, the promise is resolved with the same resource instance or collection object,\n *     updated with data from server. This makes it easy to use in\n *     {@link ngRoute.$routeProvider resolve section of $routeProvider.when()} to defer view\n *     rendering until the resource(s) are loaded.\n *\n *     On failure, the promise is resolved with the {@link ng.$http http response} object, without\n *     the `resource` property.\n *\n *   - `$resolved`: `true` after first server interaction is completed (either with success or\n *      rejection), `false` before that. Knowing if the Resource has been resolved is useful in\n *      data-binding.\n *\n * @example\n *\n * # Credit card resource\n *\n * <pre>\n     // Define CreditCard class\n     var CreditCard = $resource('/user/:userId/card/:cardId',\n      {userId:123, cardId:'@id'}, {\n       charge: {method:'POST', params:{charge:true}}\n      });\n\n     // We can retrieve a collection from the server\n     var cards = CreditCard.query(function() {\n       // GET: /user/123/card\n       // server returns: [ {id:456, number:'1234', name:'Smith'} ];\n\n       var card = cards[0];\n       // each item is an instance of CreditCard\n       expect(card instanceof CreditCard).toEqual(true);\n       card.name = \"J. Smith\";\n       // non GET methods are mapped onto the instances\n       card.$save();\n       // POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'}\n       // server returns: {id:456, number:'1234', name: 'J. Smith'};\n\n       // our custom method is mapped as well.\n       card.$charge({amount:9.99});\n       // POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'}\n     });\n\n     // we can create an instance as well\n     var newCard = new CreditCard({number:'0123'});\n     newCard.name = \"Mike Smith\";\n     newCard.$save();\n     // POST: /user/123/card {number:'0123', name:'Mike Smith'}\n     // server returns: {id:789, number:'0123', name: 'Mike Smith'};\n     expect(newCard.id).toEqual(789);\n * </pre>\n *\n * The object returned from this function execution is a resource \"class\" which has \"static\" method\n * for each action in the definition.\n *\n * Calling these methods invoke `$http` on the `url` template with the given `method`, `params` and\n * `headers`.\n * When the data is returned from the server then the object is an instance of the resource type and\n * all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD\n * operations (create, read, update, delete) on server-side data.\n\n   <pre>\n     var User = $resource('/user/:userId', {userId:'@id'});\n     var user = User.get({userId:123}, function() {\n       user.abc = true;\n       user.$save();\n     });\n   </pre>\n *\n * It's worth noting that the success callback for `get`, `query` and other methods gets passed\n * in the response that came from the server as well as $http header getter function, so one\n * could rewrite the above example and get access to http headers as:\n *\n   <pre>\n     var User = $resource('/user/:userId', {userId:'@id'});\n     User.get({userId:123}, function(u, getResponseHeaders){\n       u.abc = true;\n       u.$save(function(u, putResponseHeaders) {\n         //u => saved user object\n         //putResponseHeaders => $http header getter\n       });\n     });\n   </pre>\n\n * # Creating a custom 'PUT' request\n * In this example we create a custom method on our resource to make a PUT request\n * <pre>\n *\t\tvar app = angular.module('app', ['ngResource', 'ngRoute']);\n *\n *\t\t// Some APIs expect a PUT request in the format URL/object/ID\n *\t\t// Here we are creating an 'update' method \n *\t\tapp.factory('Notes', ['$resource', function($resource) {\n *    return $resource('/notes/:id', null,\n *        {\n *            'update': { method:'PUT' }\n *        });\n *\t\t}]);\n *\n *\t\t// In our controller we get the ID from the URL using ngRoute and $routeParams\n *\t\t// We pass in $routeParams and our Notes factory along with $scope\n *\t\tapp.controller('NotesCtrl', ['$scope', '$routeParams', 'Notes',\n                                      function($scope, $routeParams, Notes) {\n *    // First get a note object from the factory\n *    var note = Notes.get({ id:$routeParams.id });\n *    $id = note.id;\n *\n *    // Now call update passing in the ID first then the object you are updating\n *    Notes.update({ id:$id }, note);\n *\n *    // This will PUT /notes/ID with the note object in the request payload\n *\t\t}]);\n * </pre>\n */\nangular.module('ngResource', ['ng']).\n  factory('$resource', ['$http', '$q', function($http, $q) {\n\n    var DEFAULT_ACTIONS = {\n      'get':    {method:'GET'},\n      'save':   {method:'POST'},\n      'query':  {method:'GET', isArray:true},\n      'remove': {method:'DELETE'},\n      'delete': {method:'DELETE'}\n    };\n    var noop = angular.noop,\n        forEach = angular.forEach,\n        extend = angular.extend,\n        copy = angular.copy,\n        isFunction = angular.isFunction;\n\n    /**\n     * We need our custom method because encodeURIComponent is too aggressive and doesn't follow\n     * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n     * segments:\n     *    segment       = *pchar\n     *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n     *    pct-encoded   = \"%\" HEXDIG HEXDIG\n     *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n     *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n     *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n     */\n    function encodeUriSegment(val) {\n      return encodeUriQuery(val, true).\n        replace(/%26/gi, '&').\n        replace(/%3D/gi, '=').\n        replace(/%2B/gi, '+');\n    }\n\n\n    /**\n     * This method is intended for encoding *key* or *value* parts of query component. We need a\n     * custom method because encodeURIComponent is too aggressive and encodes stuff that doesn't\n     * have to be encoded per http://tools.ietf.org/html/rfc3986:\n     *    query       = *( pchar / \"/\" / \"?\" )\n     *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n     *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n     *    pct-encoded   = \"%\" HEXDIG HEXDIG\n     *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n     *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n     */\n    function encodeUriQuery(val, pctEncodeSpaces) {\n      return encodeURIComponent(val).\n        replace(/%40/gi, '@').\n        replace(/%3A/gi, ':').\n        replace(/%24/g, '$').\n        replace(/%2C/gi, ',').\n        replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));\n    }\n\n    function Route(template, defaults) {\n      this.template = template;\n      this.defaults = defaults || {};\n      this.urlParams = {};\n    }\n\n    Route.prototype = {\n      setUrlParams: function(config, params, actionUrl) {\n        var self = this,\n            url = actionUrl || self.template,\n            val,\n            encodedVal;\n\n        var urlParams = self.urlParams = {};\n        forEach(url.split(/\\W/), function(param){\n          if (param === 'hasOwnProperty') {\n            throw $resourceMinErr('badname', \"hasOwnProperty is not a valid parameter name.\");\n          }\n          if (!(new RegExp(\"^\\\\d+$\").test(param)) && param &&\n               (new RegExp(\"(^|[^\\\\\\\\]):\" + param + \"(\\\\W|$)\").test(url))) {\n            urlParams[param] = true;\n          }\n        });\n        url = url.replace(/\\\\:/g, ':');\n\n        params = params || {};\n        forEach(self.urlParams, function(_, urlParam){\n          val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam];\n          if (angular.isDefined(val) && val !== null) {\n            encodedVal = encodeUriSegment(val);\n            url = url.replace(new RegExp(\":\" + urlParam + \"(\\\\W|$)\", \"g\"), function(match, p1) {\n              return encodedVal + p1;\n            });\n          } else {\n            url = url.replace(new RegExp(\"(\\/?):\" + urlParam + \"(\\\\W|$)\", \"g\"), function(match,\n                leadingSlashes, tail) {\n              if (tail.charAt(0) == '/') {\n                return tail;\n              } else {\n                return leadingSlashes + tail;\n              }\n            });\n          }\n        });\n\n        // strip trailing slashes and set the url\n        url = url.replace(/\\/+$/, '') || '/';\n        // then replace collapse `/.` if found in the last URL path segment before the query\n        // E.g. `http://url.com/id./format?q=x` becomes `http://url.com/id.format?q=x`\n        url = url.replace(/\\/\\.(?=\\w+($|\\?))/, '.');\n        // replace escaped `/\\.` with `/.`\n        config.url = url.replace(/\\/\\\\\\./, '/.');\n\n\n        // set params - delegate param encoding to $http\n        forEach(params, function(value, key){\n          if (!self.urlParams[key]) {\n            config.params = config.params || {};\n            config.params[key] = value;\n          }\n        });\n      }\n    };\n\n\n    function resourceFactory(url, paramDefaults, actions) {\n      var route = new Route(url);\n\n      actions = extend({}, DEFAULT_ACTIONS, actions);\n\n      function extractParams(data, actionParams){\n        var ids = {};\n        actionParams = extend({}, paramDefaults, actionParams);\n        forEach(actionParams, function(value, key){\n          if (isFunction(value)) { value = value(); }\n          ids[key] = value && value.charAt && value.charAt(0) == '@' ?\n            lookupDottedPath(data, value.substr(1)) : value;\n        });\n        return ids;\n      }\n\n      function defaultResponseInterceptor(response) {\n        return response.resource;\n      }\n\n      function Resource(value){\n        shallowClearAndCopy(value || {}, this);\n      }\n\n      forEach(actions, function(action, name) {\n        var hasBody = /^(POST|PUT|PATCH)$/i.test(action.method);\n\n        Resource[name] = function(a1, a2, a3, a4) {\n          var params = {}, data, success, error;\n\n          /* jshint -W086 */ /* (purposefully fall through case statements) */\n          switch(arguments.length) {\n          case 4:\n            error = a4;\n            success = a3;\n            //fallthrough\n          case 3:\n          case 2:\n            if (isFunction(a2)) {\n              if (isFunction(a1)) {\n                success = a1;\n                error = a2;\n                break;\n              }\n\n              success = a2;\n              error = a3;\n              //fallthrough\n            } else {\n              params = a1;\n              data = a2;\n              success = a3;\n              break;\n            }\n          case 1:\n            if (isFunction(a1)) success = a1;\n            else if (hasBody) data = a1;\n            else params = a1;\n            break;\n          case 0: break;\n          default:\n            throw $resourceMinErr('badargs',\n              \"Expected up to 4 arguments [params, data, success, error], got {0} arguments\",\n              arguments.length);\n          }\n          /* jshint +W086 */ /* (purposefully fall through case statements) */\n\n          var isInstanceCall = this instanceof Resource;\n          var value = isInstanceCall ? data : (action.isArray ? [] : new Resource(data));\n          var httpConfig = {};\n          var responseInterceptor = action.interceptor && action.interceptor.response ||\n                                    defaultResponseInterceptor;\n          var responseErrorInterceptor = action.interceptor && action.interceptor.responseError ||\n                                    undefined;\n\n          forEach(action, function(value, key) {\n            if (key != 'params' && key != 'isArray' && key != 'interceptor') {\n              httpConfig[key] = copy(value);\n            }\n          });\n\n          if (hasBody) httpConfig.data = data;\n          route.setUrlParams(httpConfig,\n                             extend({}, extractParams(data, action.params || {}), params),\n                             action.url);\n\n          var promise = $http(httpConfig).then(function(response) {\n            var data = response.data,\n                promise = value.$promise;\n\n            if (data) {\n              // Need to convert action.isArray to boolean in case it is undefined\n              // jshint -W018\n              if (angular.isArray(data) !== (!!action.isArray)) {\n                throw $resourceMinErr('badcfg', 'Error in resource configuration. Expected ' +\n                  'response to contain an {0} but got an {1}',\n                  action.isArray?'array':'object', angular.isArray(data)?'array':'object');\n              }\n              // jshint +W018\n              if (action.isArray) {\n                value.length = 0;\n                forEach(data, function(item) {\n                  value.push(new Resource(item));\n                });\n              } else {\n                shallowClearAndCopy(data, value);\n                value.$promise = promise;\n              }\n            }\n\n            value.$resolved = true;\n\n            response.resource = value;\n\n            return response;\n          }, function(response) {\n            value.$resolved = true;\n\n            (error||noop)(response);\n\n            return $q.reject(response);\n          });\n\n          promise = promise.then(\n              function(response) {\n                var value = responseInterceptor(response);\n                (success||noop)(value, response.headers);\n                return value;\n              },\n              responseErrorInterceptor);\n\n          if (!isInstanceCall) {\n            // we are creating instance / collection\n            // - set the initial promise\n            // - return the instance / collection\n            value.$promise = promise;\n            value.$resolved = false;\n\n            return value;\n          }\n\n          // instance call\n          return promise;\n        };\n\n\n        Resource.prototype['$' + name] = function(params, success, error) {\n          if (isFunction(params)) {\n            error = success; success = params; params = {};\n          }\n          var result = Resource[name].call(this, params, this, success, error);\n          return result.$promise || result;\n        };\n      });\n\n      Resource.bind = function(additionalParamDefaults){\n        return resourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions);\n      };\n\n      return Resource;\n    }\n\n    return resourceFactory;\n  }]);\n\n\n})(window, window.angular);\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/angular-route_1.2.13/angular-route.js",
    "content": "/**\n * @license AngularJS v1.2.13\n * (c) 2010-2014 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {'use strict';\n\n/**\n * @ngdoc overview\n * @name ngRoute\n * @description\n *\n * # ngRoute\n *\n * The `ngRoute` module provides routing and deeplinking services and directives for angular apps.\n *\n * ## Example\n * See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`.\n * \n * {@installModule route}\n *\n * <div doc-module-components=\"ngRoute\"></div>\n */\n /* global -ngRouteModule */\nvar ngRouteModule = angular.module('ngRoute', ['ng']).\n                        provider('$route', $RouteProvider);\n\n/**\n * @ngdoc object\n * @name ngRoute.$routeProvider\n * @function\n *\n * @description\n *\n * Used for configuring routes.\n * \n * ## Example\n * See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`.\n *\n * ## Dependencies\n * Requires the {@link ngRoute `ngRoute`} module to be installed.\n */\nfunction $RouteProvider(){\n  function inherit(parent, extra) {\n    return angular.extend(new (angular.extend(function() {}, {prototype:parent}))(), extra);\n  }\n\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name ngRoute.$routeProvider#when\n   * @methodOf ngRoute.$routeProvider\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *      * `path` can contain named groups starting with a colon: e.g. `:name`. All characters up\n   *        to the next slash are matched and stored in `$routeParams` under the given `name`\n   *        when the route matches.\n   *      * `path` can contain named groups starting with a colon and ending with a star:\n   *        e.g.`:name*`. All characters are eagerly stored in `$routeParams` under the given `name`\n   *        when the route matches.\n   *      * `path` can contain optional named groups with a question mark: e.g.`:name?`.\n   *\n   *    For example, routes like `/color/:color/largecode/:largecode*\\/edit` will match\n   *    `/color/brown/largecode/code/with/slashs/edit` and extract:\n   *\n   *      * `color: brown`\n   *      * `largecode: code/with/slashs`.\n   *\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|function()=}` – Controller fn that should be associated with\n   *      newly created scope or the name of a {@link angular.Module#controller registered\n   *      controller} if passed as a string.\n   *    - `controllerAs` – `{string=}` – A controller alias name. If present the controller will be\n   *      published to scope under the `controllerAs` name.\n   *    - `template` – `{string=|function()=}` – html template as a string or a function that\n   *      returns an html template as a string which should be used by {@link\n   *      ngRoute.directive:ngView ngView} or {@link ng.directive:ngInclude ngInclude} directives.\n   *      This property takes precedence over `templateUrl`.\n   *\n   *      If `template` is a function, it will be called with the following parameters:\n   *\n   *      - `{Array.<Object>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route\n   *\n   *    - `templateUrl` – `{string=|function()=}` – path or function that returns a path to an html\n   *      template that should be used by {@link ngRoute.directive:ngView ngView}.\n   *\n   *      If `templateUrl` is a function, it will be called with the following parameters:\n   *\n   *      - `{Array.<Object>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route\n   *\n   *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, the router\n   *      will wait for them all to be resolved or one to be rejected before the controller is\n   *      instantiated.\n   *      If all the promises are resolved successfully, the values of the resolved promises are\n   *      injected and {@link ngRoute.$route#$routeChangeSuccess $routeChangeSuccess} event is\n   *      fired. If any of the promises are rejected the\n   *      {@link ngRoute.$route#$routeChangeError $routeChangeError} event is fired. The map object\n   *      is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is\n   *        resolved before its value is injected into the controller. Be aware that\n   *        `ngRoute.$routeParams` will still refer to the previous route within these resolve\n   *        functions.  Use `$route.current.params` to access the new route parameters, instead.\n   *\n   *    - `redirectTo` – {(string|function())=} – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.path()` and `$location.search()`.\n   *\n   *    - `[reloadOnSearch=true]` - {boolean=} - reload route when only `$location.search()`\n   *      or `$location.hash()` changes.\n   *\n   *      If the option is set to `false` and url in the browser changes, then\n   *      `$routeUpdate` event is broadcasted on the root scope.\n   *\n   *    - `[caseInsensitiveMatch=false]` - {boolean=} - match routes without being case sensitive\n   *\n   *      If the option is set to `true`, then the particular route can be matched without being\n   *      case sensitive\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    routes[path] = angular.extend(\n      {reloadOnSearch: true},\n      route,\n      path && pathRegExp(path, route)\n    );\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length-1] == '/')\n            ? path.substr(0, path.length-1)\n            : path +'/';\n\n      routes[redirectPath] = angular.extend(\n        {redirectTo: path},\n        pathRegExp(redirectPath, route)\n      );\n    }\n\n    return this;\n  };\n\n   /**\n    * @param path {string} path\n    * @param opts {Object} options\n    * @return {?Object}\n    *\n    * @description\n    * Normalizes the given path, returning a regular expression\n    * and the original path.\n    *\n    * Inspired by pathRexp in visionmedia/express/lib/utils.js.\n    */\n  function pathRegExp(path, opts) {\n    var insensitive = opts.caseInsensitiveMatch,\n        ret = {\n          originalPath: path,\n          regexp: path\n        },\n        keys = ret.keys = [];\n\n    path = path\n      .replace(/([().])/g, '\\\\$1')\n      .replace(/(\\/)?:(\\w+)([\\?\\*])?/g, function(_, slash, key, option){\n        var optional = option === '?' ? option : null;\n        var star = option === '*' ? option : null;\n        keys.push({ name: key, optional: !!optional });\n        slash = slash || '';\n        return ''\n          + (optional ? '' : slash)\n          + '(?:'\n          + (optional ? slash : '')\n          + (star && '(.+?)' || '([^/]+)')\n          + (optional || '')\n          + ')'\n          + (optional || '');\n      })\n      .replace(/([\\/$\\*])/g, '\\\\$1');\n\n    ret.regexp = new RegExp('^' + path + '$', insensitive ? 'i' : '');\n    return ret;\n  }\n\n  /**\n   * @ngdoc method\n   * @name ngRoute.$routeProvider#otherwise\n   * @methodOf ngRoute.$routeProvider\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object} params Mapping information to be assigned to `$route.current`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    this.when(null, params);\n    return this;\n  };\n\n\n  this.$get = ['$rootScope',\n               '$location',\n               '$routeParams',\n               '$q',\n               '$injector',\n               '$http',\n               '$templateCache',\n               '$sce',\n      function($rootScope, $location, $routeParams, $q, $injector, $http, $templateCache, $sce) {\n\n    /**\n     * @ngdoc object\n     * @name ngRoute.$route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as define in route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     * @property {Array.<Object>} routes Array of all configured routes.\n     *\n     * @description\n     * `$route` is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * Requires the {@link ngRoute `ngRoute`} module to be installed.\n     *\n     * You can define routes through {@link ngRoute.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with the\n     * {@link ngRoute.directive:ngView `ngView`} directive and the\n     * {@link ngRoute.$routeParams `$routeParams`} service.\n     *\n     * @example\n       This example shows how changing the URL hash causes the `$route` to match a route against the\n       URL, and the `ngView` pulls in the partial.\n\n       Note that this example is using {@link ng.directive:script inlined templates}\n       to get it working on jsfiddle as well.\n\n     <example module=\"ngViewExample\" deps=\"angular-route.js\">\n       <file name=\"index.html\">\n         <div ng-controller=\"MainCntl\">\n           Choose:\n           <a href=\"Book/Moby\">Moby</a> |\n           <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n           <a href=\"Book/Gatsby\">Gatsby</a> |\n           <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n           <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n           <div ng-view></div>\n           <hr />\n\n           <pre>$location.path() = {{$location.path()}}</pre>\n           <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n           <pre>$route.current.params = {{$route.current.params}}</pre>\n           <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n           <pre>$routeParams = {{$routeParams}}</pre>\n         </div>\n       </file>\n\n       <file name=\"book.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n       </file>\n\n       <file name=\"chapter.html\">\n         controller: {{name}}<br />\n         Book Id: {{params.bookId}}<br />\n         Chapter Id: {{params.chapterId}}\n       </file>\n\n       <file name=\"script.js\">\n         angular.module('ngViewExample', ['ngRoute'])\n\n         .config(function($routeProvider, $locationProvider) {\n           $routeProvider.when('/Book/:bookId', {\n             templateUrl: 'book.html',\n             controller: BookCntl,\n             resolve: {\n               // I will cause a 1 second delay\n               delay: function($q, $timeout) {\n                 var delay = $q.defer();\n                 $timeout(delay.resolve, 1000);\n                 return delay.promise;\n               }\n             }\n           });\n           $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n             templateUrl: 'chapter.html',\n             controller: ChapterCntl\n           });\n\n           // configure html5 to get links working on jsfiddle\n           $locationProvider.html5Mode(true);\n         });\n\n         function MainCntl($scope, $route, $routeParams, $location) {\n           $scope.$route = $route;\n           $scope.$location = $location;\n           $scope.$routeParams = $routeParams;\n         }\n\n         function BookCntl($scope, $routeParams) {\n           $scope.name = \"BookCntl\";\n           $scope.params = $routeParams;\n         }\n\n         function ChapterCntl($scope, $routeParams) {\n           $scope.name = \"ChapterCntl\";\n           $scope.params = $routeParams;\n         }\n       </file>\n\n       <file name=\"protractorTest.js\">\n         it('should load and compile correct template', function() {\n           element(by.linkText('Moby: Ch1')).click();\n           var content = element(by.css('.doc-example-live [ng-view]')).getText();\n           expect(content).toMatch(/controller\\: ChapterCntl/);\n           expect(content).toMatch(/Book Id\\: Moby/);\n           expect(content).toMatch(/Chapter Id\\: 1/);\n\n           element(by.partialLinkText('Scarlet')).click();\n\n           content = element(by.css('.doc-example-live [ng-view]')).getText();\n           expect(content).toMatch(/controller\\: BookCntl/);\n           expect(content).toMatch(/Book Id\\: Scarlet/);\n         });\n       </file>\n     </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name ngRoute.$route#$routeChangeStart\n     * @eventOf ngRoute.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occur.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * @param {Object} angularEvent Synthetic event object.\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ngRoute.$route#$routeChangeSuccess\n     * @eventOf ngRoute.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route dependencies are resolved.\n     * {@link ngRoute.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Object} angularEvent Synthetic event object.\n     * @param {Route} current Current route information.\n     * @param {Route|Undefined} previous Previous route information, or undefined if current is\n     * first route entered.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ngRoute.$route#$routeChangeError\n     * @eventOf ngRoute.$route\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if any of the resolve promises are rejected.\n     *\n     * @param {Object} angularEvent Synthetic event object\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n     */\n\n    /**\n     * @ngdoc event\n     * @name ngRoute.$route#$routeUpdate\n     * @eventOf ngRoute.$route\n     * @eventType broadcast on root scope\n     * @description\n     *\n     * The `reloadOnSearch` property has been set to false, and we are reusing the same\n     * instance of the Controller.\n     */\n\n    var forceReload = false,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name ngRoute.$route#reload\n           * @methodOf ngRoute.$route\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ngRoute.directive:ngView ngView}\n           * creates new scope, reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n            $rootScope.$evalAsync(updateRoute);\n          }\n        };\n\n    $rootScope.$on('$locationChangeSuccess', updateRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param route {Object} route regexp to match the url against\n     * @return {?Object}\n     *\n     * @description\n     * Check if the route matches the current url.\n     *\n     * Inspired by match in\n     * visionmedia/express/lib/router/router.js.\n     */\n    function switchRouteMatcher(on, route) {\n      var keys = route.keys,\n          params = {};\n\n      if (!route.regexp) return null;\n\n      var m = route.regexp.exec(on);\n      if (!m) return null;\n\n      for (var i = 1, len = m.length; i < len; ++i) {\n        var key = keys[i - 1];\n\n        var val = 'string' == typeof m[i]\n              ? decodeURIComponent(m[i])\n              : m[i];\n\n        if (key && val) {\n          params[key.name] = val;\n        }\n      }\n      return params;\n    }\n\n    function updateRoute() {\n      var next = parseRoute(),\n          last = $route.current;\n\n      if (next && last && next.$$route === last.$$route\n          && angular.equals(next.pathParams, last.pathParams)\n          && !next.reloadOnSearch && !forceReload) {\n        last.params = next.params;\n        angular.copy(last.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', last);\n      } else if (next || last) {\n        forceReload = false;\n        $rootScope.$broadcast('$routeChangeStart', next, last);\n        $route.current = next;\n        if (next) {\n          if (next.redirectTo) {\n            if (angular.isString(next.redirectTo)) {\n              $location.path(interpolate(next.redirectTo, next.params)).search(next.params)\n                       .replace();\n            } else {\n              $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))\n                       .replace();\n            }\n          }\n        }\n\n        $q.when(next).\n          then(function() {\n            if (next) {\n              var locals = angular.extend({}, next.resolve),\n                  template, templateUrl;\n\n              angular.forEach(locals, function(value, key) {\n                locals[key] = angular.isString(value) ?\n                    $injector.get(value) : $injector.invoke(value);\n              });\n\n              if (angular.isDefined(template = next.template)) {\n                if (angular.isFunction(template)) {\n                  template = template(next.params);\n                }\n              } else if (angular.isDefined(templateUrl = next.templateUrl)) {\n                if (angular.isFunction(templateUrl)) {\n                  templateUrl = templateUrl(next.params);\n                }\n                templateUrl = $sce.getTrustedResourceUrl(templateUrl);\n                if (angular.isDefined(templateUrl)) {\n                  next.loadedTemplateUrl = templateUrl;\n                  template = $http.get(templateUrl, {cache: $templateCache}).\n                      then(function(response) { return response.data; });\n                }\n              }\n              if (angular.isDefined(template)) {\n                locals['$template'] = template;\n              }\n              return $q.all(locals);\n            }\n          }).\n          // after route change\n          then(function(locals) {\n            if (next == $route.current) {\n              if (next) {\n                next.locals = locals;\n                angular.copy(next.params, $routeParams);\n              }\n              $rootScope.$broadcast('$routeChangeSuccess', next, last);\n            }\n          }, function(error) {\n            if (next == $route.current) {\n              $rootScope.$broadcast('$routeChangeError', next, last, error);\n            }\n          });\n      }\n    }\n\n\n    /**\n     * @returns the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      angular.forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), route))) {\n          match = inherit(route, {\n            params: angular.extend({}, $location.search(), params),\n            pathParams: params});\n          match.$$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @returns interpolation of the redirect path with the parameters\n     */\n    function interpolate(string, params) {\n      var result = [];\n      angular.forEach((string||'').split(':'), function(segment, i) {\n        if (i === 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\nngRouteModule.provider('$routeParams', $RouteParamsProvider);\n\n\n/**\n * @ngdoc object\n * @name ngRoute.$routeParams\n * @requires $route\n *\n * @description\n * The `$routeParams` service allows you to retrieve the current set of route parameters.\n *\n * Requires the {@link ngRoute `ngRoute`} module to be installed.\n *\n * The route parameters are a combination of {@link ng.$location `$location`}'s\n * {@link ng.$location#methods_search `search()`} and {@link ng.$location#methods_path `path()`}.\n * The `path` parameters are extracted when the {@link ngRoute.$route `$route`} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * Note that the `$routeParams` are only updated *after* a route change completes successfully.\n * This means that you cannot rely on `$routeParams` being correct in route resolve functions.\n * Instead you can use `$route.current.params` to access the new route's parameters.\n *\n * @example\n * <pre>\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}\n * </pre>\n */\nfunction $RouteParamsProvider() {\n  this.$get = function() { return {}; };\n}\n\nngRouteModule.directive('ngView', ngViewFactory);\nngRouteModule.directive('ngView', ngViewFillContentFactory);\n\n\n/**\n * @ngdoc directive\n * @name ngRoute.directive:ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ngRoute.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * Requires the {@link ngRoute `ngRoute`} module to be installed.\n *\n * @animations\n * enter - animation is used to bring new content into the browser.\n * leave - animation is used to animate existing content away.\n *\n * The enter and leave animation occur concurrently.\n *\n * @scope\n * @priority 400\n * @param {string=} onload Expression to evaluate whenever the view updates.\n *\n * @param {string=} autoscroll Whether `ngView` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the view is updated.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the `autoscroll` attribute value evaluated\n *                    as an expression yields a truthy value.\n * @example\n    <example module=\"ngViewExample\" deps=\"angular-route.js\" animations=\"true\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCntl as main\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div class=\"view-animate-container\">\n            <div ng-view class=\"view-animate\"></div>\n          </div>\n          <hr />\n\n          <pre>$location.path() = {{main.$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{main.$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{main.$route.current.params}}</pre>\n          <pre>$route.current.scope.name = {{main.$route.current.scope.name}}</pre>\n          <pre>$routeParams = {{main.$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        <div>\n          controller: {{book.name}}<br />\n          Book Id: {{book.params.bookId}}<br />\n        </div>\n      </file>\n\n      <file name=\"chapter.html\">\n        <div>\n          controller: {{chapter.name}}<br />\n          Book Id: {{chapter.params.bookId}}<br />\n          Chapter Id: {{chapter.params.chapterId}}\n        </div>\n      </file>\n\n      <file name=\"animations.css\">\n        .view-animate-container {\n          position:relative;\n          height:100px!important;\n          position:relative;\n          background:white;\n          border:1px solid black;\n          height:40px;\n          overflow:hidden;\n        }\n\n        .view-animate {\n          padding:10px;\n        }\n\n        .view-animate.ng-enter, .view-animate.ng-leave {\n          -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;\n          transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;\n\n          display:block;\n          width:100%;\n          border-left:1px solid black;\n\n          position:absolute;\n          top:0;\n          left:0;\n          right:0;\n          bottom:0;\n          padding:10px;\n        }\n\n        .view-animate.ng-enter {\n          left:100%;\n        }\n        .view-animate.ng-enter.ng-enter-active {\n          left:0;\n        }\n        .view-animate.ng-leave.ng-leave-active {\n          left:-100%;\n        }\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngViewExample', ['ngRoute', 'ngAnimate'],\n          function($routeProvider, $locationProvider) {\n            $routeProvider.when('/Book/:bookId', {\n              templateUrl: 'book.html',\n              controller: BookCntl,\n              controllerAs: 'book'\n            });\n            $routeProvider.when('/Book/:bookId/ch/:chapterId', {\n              templateUrl: 'chapter.html',\n              controller: ChapterCntl,\n              controllerAs: 'chapter'\n            });\n\n            // configure html5 to get links working on jsfiddle\n            $locationProvider.html5Mode(true);\n        });\n\n        function MainCntl($route, $routeParams, $location) {\n          this.$route = $route;\n          this.$location = $location;\n          this.$routeParams = $routeParams;\n        }\n\n        function BookCntl($routeParams) {\n          this.name = \"BookCntl\";\n          this.params = $routeParams;\n        }\n\n        function ChapterCntl($routeParams) {\n          this.name = \"ChapterCntl\";\n          this.params = $routeParams;\n        }\n      </file>\n\n      <file name=\"protractorTest.js\">\n        it('should load and compile correct template', function() {\n          element(by.linkText('Moby: Ch1')).click();\n          var content = element(by.css('.doc-example-live [ng-view]')).getText();\n          expect(content).toMatch(/controller\\: ChapterCntl/);\n          expect(content).toMatch(/Book Id\\: Moby/);\n          expect(content).toMatch(/Chapter Id\\: 1/);\n\n          element(by.partialLinkText('Scarlet')).click();\n\n          content = element(by.css('.doc-example-live [ng-view]')).getText();\n          expect(content).toMatch(/controller\\: BookCntl/);\n          expect(content).toMatch(/Book Id\\: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ngRoute.directive:ngView#$viewContentLoaded\n * @eventOf ngRoute.directive:ngView\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nngViewFactory.$inject = ['$route', '$anchorScroll', '$animate'];\nfunction ngViewFactory(   $route,   $anchorScroll,   $animate) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    priority: 400,\n    transclude: 'element',\n    link: function(scope, $element, attr, ctrl, $transclude) {\n        var currentScope,\n            currentElement,\n            autoScrollExp = attr.autoscroll,\n            onloadExp = attr.onload || '';\n\n        scope.$on('$routeChangeSuccess', update);\n        update();\n\n        function cleanupLastView() {\n          if (currentScope) {\n            currentScope.$destroy();\n            currentScope = null;\n          }\n          if(currentElement) {\n            $animate.leave(currentElement);\n            currentElement = null;\n          }\n        }\n\n        function update() {\n          var locals = $route.current && $route.current.locals,\n              template = locals && locals.$template;\n\n          if (angular.isDefined(template)) {\n            var newScope = scope.$new();\n            var current = $route.current;\n\n            // Note: This will also link all children of ng-view that were contained in the original\n            // html. If that content contains controllers, ... they could pollute/change the scope.\n            // However, using ng-view on an element with additional content does not make sense...\n            // Note: We can't remove them in the cloneAttchFn of $transclude as that\n            // function is called before linking the content, which would apply child\n            // directives to non existing elements.\n            var clone = $transclude(newScope, function(clone) {\n              $animate.enter(clone, null, currentElement || $element, function onNgViewEnter () {\n                if (angular.isDefined(autoScrollExp)\n                  && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                  $anchorScroll();\n                }\n              });\n              cleanupLastView();\n            });\n\n            currentElement = clone;\n            currentScope = current.scope = newScope;\n            currentScope.$emit('$viewContentLoaded');\n            currentScope.$eval(onloadExp);\n          } else {\n            cleanupLastView();\n          }\n        }\n    }\n  };\n}\n\n// This directive is called during the $transclude call of the first `ngView` directive.\n// It will replace and compile the content of the element with the loaded template.\n// We need this directive so that the element content is already filled when\n// the link function of another directive on the same element as ngView\n// is called.\nngViewFillContentFactory.$inject = ['$compile', '$controller', '$route'];\nfunction ngViewFillContentFactory($compile, $controller, $route) {\n  return {\n    restrict: 'ECA',\n    priority: -400,\n    link: function(scope, $element) {\n      var current = $route.current,\n          locals = current.locals;\n\n      $element.html(locals.$template);\n\n      var link = $compile($element.contents());\n\n      if (current.controller) {\n        locals.$scope = scope;\n        var controller = $controller(current.controller, locals);\n        if (current.controllerAs) {\n          scope[current.controllerAs] = controller;\n        }\n        $element.data('$ngControllerController', controller);\n        $element.children().data('$ngControllerController', controller);\n      }\n\n      link(scope);\n    }\n  };\n}\n\n\n})(window, window.angular);\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/angular-sanitize_1.2.13/angular-sanitize.js",
    "content": "/**\n * @license AngularJS v1.2.13\n * (c) 2010-2014 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {'use strict';\n\nvar $sanitizeMinErr = angular.$$minErr('$sanitize');\n\n/**\n * @ngdoc overview\n * @name ngSanitize\n * @description\n *\n * # ngSanitize\n *\n * The `ngSanitize` module provides functionality to sanitize HTML.\n *\n * {@installModule sanitize}\n *\n * <div doc-module-components=\"ngSanitize\"></div>\n *\n * See {@link ngSanitize.$sanitize `$sanitize`} for usage.\n */\n\n/*\n * HTML Parser By Misko Hevery (misko@hevery.com)\n * based on:  HTML Parser By John Resig (ejohn.org)\n * Original code by Erik Arvidsson, Mozilla Public License\n * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js\n *\n * // Use like so:\n * htmlParser(htmlString, {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * });\n *\n */\n\n\n/**\n * @ngdoc service\n * @name ngSanitize.$sanitize\n * @function\n *\n * @description\n *   The input is sanitized by parsing the html into tokens. All safe tokens (from a whitelist) are\n *   then serialized back to properly escaped html string. This means that no unsafe input can make\n *   it into the returned string, however, since our parser is more strict than a typical browser\n *   parser, it's possible that some obscure input, which would be recognized as valid HTML by a\n *   browser, won't make it through the sanitizer.\n *   The whitelist is configured using the functions `aHrefSanitizationWhitelist` and\n *   `imgSrcSanitizationWhitelist` of {@link ng.$compileProvider `$compileProvider`}.\n *\n * @param {string} html Html input.\n * @returns {string} Sanitized html.\n *\n * @example\n   <doc:example module=\"ngSanitize\">\n   <doc:source>\n     <script>\n       function Ctrl($scope, $sce) {\n         $scope.snippet =\n           '<p style=\"color:blue\">an html\\n' +\n           '<em onmouseover=\"this.textContent=\\'PWN3D!\\'\">click here</em>\\n' +\n           'snippet</p>';\n         $scope.deliberatelyTrustDangerousSnippet = function() {\n           return $sce.trustAsHtml($scope.snippet);\n         };\n       }\n     </script>\n     <div ng-controller=\"Ctrl\">\n        Snippet: <textarea ng-model=\"snippet\" cols=\"60\" rows=\"3\"></textarea>\n       <table>\n         <tr>\n           <td>Directive</td>\n           <td>How</td>\n           <td>Source</td>\n           <td>Rendered</td>\n         </tr>\n         <tr id=\"bind-html-with-sanitize\">\n           <td>ng-bind-html</td>\n           <td>Automatically uses $sanitize</td>\n           <td><pre>&lt;div ng-bind-html=\"snippet\"&gt;<br/>&lt;/div&gt;</pre></td>\n           <td><div ng-bind-html=\"snippet\"></div></td>\n         </tr>\n         <tr id=\"bind-html-with-trust\">\n           <td>ng-bind-html</td>\n           <td>Bypass $sanitize by explicitly trusting the dangerous value</td>\n           <td>\n           <pre>&lt;div ng-bind-html=\"deliberatelyTrustDangerousSnippet()\"&gt;\n&lt;/div&gt;</pre>\n           </td>\n           <td><div ng-bind-html=\"deliberatelyTrustDangerousSnippet()\"></div></td>\n         </tr>\n         <tr id=\"bind-default\">\n           <td>ng-bind</td>\n           <td>Automatically escapes</td>\n           <td><pre>&lt;div ng-bind=\"snippet\"&gt;<br/>&lt;/div&gt;</pre></td>\n           <td><div ng-bind=\"snippet\"></div></td>\n         </tr>\n       </table>\n       </div>\n   </doc:source>\n   <doc:protractor>\n     it('should sanitize the html snippet by default', function() {\n       expect(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()).\n         toBe('<p>an html\\n<em>click here</em>\\nsnippet</p>');\n     });\n\n     it('should inline raw snippet if bound to a trusted value', function() {\n       expect(element(by.css('#bind-html-with-trust div')).getInnerHtml()).\n         toBe(\"<p style=\\\"color:blue\\\">an html\\n\" +\n              \"<em onmouseover=\\\"this.textContent='PWN3D!'\\\">click here</em>\\n\" +\n              \"snippet</p>\");\n     });\n\n     it('should escape snippet without any filter', function() {\n       expect(element(by.css('#bind-default div')).getInnerHtml()).\n         toBe(\"&lt;p style=\\\"color:blue\\\"&gt;an html\\n\" +\n              \"&lt;em onmouseover=\\\"this.textContent='PWN3D!'\\\"&gt;click here&lt;/em&gt;\\n\" +\n              \"snippet&lt;/p&gt;\");\n     });\n\n     it('should update', function() {\n       element(by.model('snippet')).clear();\n       element(by.model('snippet')).sendKeys('new <b onclick=\"alert(1)\">text</b>');\n       expect(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()).\n         toBe('new <b>text</b>');\n       expect(element(by.css('#bind-html-with-trust div')).getInnerHtml()).toBe(\n         'new <b onclick=\"alert(1)\">text</b>');\n       expect(element(by.css('#bind-default div')).getInnerHtml()).toBe(\n         \"new &lt;b onclick=\\\"alert(1)\\\"&gt;text&lt;/b&gt;\");\n     });\n   </doc:protractor>\n   </doc:example>\n */\nfunction $SanitizeProvider() {\n  this.$get = ['$$sanitizeUri', function($$sanitizeUri) {\n    return function(html) {\n      var buf = [];\n      htmlParser(html, htmlSanitizeWriter(buf, function(uri, isImage) {\n        return !/^unsafe/.test($$sanitizeUri(uri, isImage));\n      }));\n      return buf.join('');\n    };\n  }];\n}\n\nfunction sanitizeText(chars) {\n  var buf = [];\n  var writer = htmlSanitizeWriter(buf, angular.noop);\n  writer.chars(chars);\n  return buf.join('');\n}\n\n\n// Regular Expressions for parsing tags and attributes\nvar START_TAG_REGEXP =\n       /^<\\s*([\\w:-]+)((?:\\s+[\\w:-]+(?:\\s*=\\s*(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>\\s]+))?)*)\\s*(\\/?)\\s*>/,\n  END_TAG_REGEXP = /^<\\s*\\/\\s*([\\w:-]+)[^>]*>/,\n  ATTR_REGEXP = /([\\w:-]+)(?:\\s*=\\s*(?:(?:\"((?:[^\"])*)\")|(?:'((?:[^'])*)')|([^>\\s]+)))?/g,\n  BEGIN_TAG_REGEXP = /^</,\n  BEGING_END_TAGE_REGEXP = /^<\\s*\\//,\n  COMMENT_REGEXP = /<!--(.*?)-->/g,\n  DOCTYPE_REGEXP = /<!DOCTYPE([^>]*?)>/i,\n  CDATA_REGEXP = /<!\\[CDATA\\[(.*?)]]>/g,\n  // Match everything outside of normal chars and \" (quote character)\n  NON_ALPHANUMERIC_REGEXP = /([^\\#-~| |!])/g;\n\n\n// Good source of info about elements and attributes\n// http://dev.w3.org/html5/spec/Overview.html#semantics\n// http://simon.html5.org/html-elements\n\n// Safe Void Elements - HTML5\n// http://dev.w3.org/html5/spec/Overview.html#void-elements\nvar voidElements = makeMap(\"area,br,col,hr,img,wbr\");\n\n// Elements that you can, intentionally, leave open (and which close themselves)\n// http://dev.w3.org/html5/spec/Overview.html#optional-tags\nvar optionalEndTagBlockElements = makeMap(\"colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr\"),\n    optionalEndTagInlineElements = makeMap(\"rp,rt\"),\n    optionalEndTagElements = angular.extend({},\n                                            optionalEndTagInlineElements,\n                                            optionalEndTagBlockElements);\n\n// Safe Block Elements - HTML5\nvar blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap(\"address,article,\" +\n        \"aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,\" +\n        \"h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul\"));\n\n// Inline Elements - HTML5\nvar inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap(\"a,abbr,acronym,b,\" +\n        \"bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,\" +\n        \"samp,small,span,strike,strong,sub,sup,time,tt,u,var\"));\n\n\n// Special Elements (can contain anything)\nvar specialElements = makeMap(\"script,style\");\n\nvar validElements = angular.extend({},\n                                   voidElements,\n                                   blockElements,\n                                   inlineElements,\n                                   optionalEndTagElements);\n\n//Attributes that have href and hence need to be sanitized\nvar uriAttrs = makeMap(\"background,cite,href,longdesc,src,usemap\");\nvar validAttrs = angular.extend({}, uriAttrs, makeMap(\n    'abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'+\n    'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,'+\n    'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,'+\n    'scope,scrolling,shape,size,span,start,summary,target,title,type,'+\n    'valign,value,vspace,width'));\n\nfunction makeMap(str) {\n  var obj = {}, items = str.split(','), i;\n  for (i = 0; i < items.length; i++) obj[items[i]] = true;\n  return obj;\n}\n\n\n/**\n * @example\n * htmlParser(htmlString, {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * });\n *\n * @param {string} html string\n * @param {object} handler\n */\nfunction htmlParser( html, handler ) {\n  var index, chars, match, stack = [], last = html;\n  stack.last = function() { return stack[ stack.length - 1 ]; };\n\n  while ( html ) {\n    chars = true;\n\n    // Make sure we're not in a script or style element\n    if ( !stack.last() || !specialElements[ stack.last() ] ) {\n\n      // Comment\n      if ( html.indexOf(\"<!--\") === 0 ) {\n        // comments containing -- are not allowed unless they terminate the comment\n        index = html.indexOf(\"--\", 4);\n\n        if ( index >= 0 && html.lastIndexOf(\"-->\", index) === index) {\n          if (handler.comment) handler.comment( html.substring( 4, index ) );\n          html = html.substring( index + 3 );\n          chars = false;\n        }\n      // DOCTYPE\n      } else if ( DOCTYPE_REGEXP.test(html) ) {\n        match = html.match( DOCTYPE_REGEXP );\n\n        if ( match ) {\n          html = html.replace( match[0] , '');\n          chars = false;\n        }\n      // end tag\n      } else if ( BEGING_END_TAGE_REGEXP.test(html) ) {\n        match = html.match( END_TAG_REGEXP );\n\n        if ( match ) {\n          html = html.substring( match[0].length );\n          match[0].replace( END_TAG_REGEXP, parseEndTag );\n          chars = false;\n        }\n\n      // start tag\n      } else if ( BEGIN_TAG_REGEXP.test(html) ) {\n        match = html.match( START_TAG_REGEXP );\n\n        if ( match ) {\n          html = html.substring( match[0].length );\n          match[0].replace( START_TAG_REGEXP, parseStartTag );\n          chars = false;\n        }\n      }\n\n      if ( chars ) {\n        index = html.indexOf(\"<\");\n\n        var text = index < 0 ? html : html.substring( 0, index );\n        html = index < 0 ? \"\" : html.substring( index );\n\n        if (handler.chars) handler.chars( decodeEntities(text) );\n      }\n\n    } else {\n      html = html.replace(new RegExp(\"(.*)<\\\\s*\\\\/\\\\s*\" + stack.last() + \"[^>]*>\", 'i'),\n        function(all, text){\n          text = text.replace(COMMENT_REGEXP, \"$1\").replace(CDATA_REGEXP, \"$1\");\n\n          if (handler.chars) handler.chars( decodeEntities(text) );\n\n          return \"\";\n      });\n\n      parseEndTag( \"\", stack.last() );\n    }\n\n    if ( html == last ) {\n      throw $sanitizeMinErr('badparse', \"The sanitizer was unable to parse the following block \" +\n                                        \"of html: {0}\", html);\n    }\n    last = html;\n  }\n\n  // Clean up any remaining tags\n  parseEndTag();\n\n  function parseStartTag( tag, tagName, rest, unary ) {\n    tagName = angular.lowercase(tagName);\n    if ( blockElements[ tagName ] ) {\n      while ( stack.last() && inlineElements[ stack.last() ] ) {\n        parseEndTag( \"\", stack.last() );\n      }\n    }\n\n    if ( optionalEndTagElements[ tagName ] && stack.last() == tagName ) {\n      parseEndTag( \"\", tagName );\n    }\n\n    unary = voidElements[ tagName ] || !!unary;\n\n    if ( !unary )\n      stack.push( tagName );\n\n    var attrs = {};\n\n    rest.replace(ATTR_REGEXP,\n      function(match, name, doubleQuotedValue, singleQuotedValue, unquotedValue) {\n        var value = doubleQuotedValue\n          || singleQuotedValue\n          || unquotedValue\n          || '';\n\n        attrs[name] = decodeEntities(value);\n    });\n    if (handler.start) handler.start( tagName, attrs, unary );\n  }\n\n  function parseEndTag( tag, tagName ) {\n    var pos = 0, i;\n    tagName = angular.lowercase(tagName);\n    if ( tagName )\n      // Find the closest opened tag of the same type\n      for ( pos = stack.length - 1; pos >= 0; pos-- )\n        if ( stack[ pos ] == tagName )\n          break;\n\n    if ( pos >= 0 ) {\n      // Close all the open elements, up the stack\n      for ( i = stack.length - 1; i >= pos; i-- )\n        if (handler.end) handler.end( stack[ i ] );\n\n      // Remove the open elements from the stack\n      stack.length = pos;\n    }\n  }\n}\n\nvar hiddenPre=document.createElement(\"pre\");\nvar spaceRe = /^(\\s*)([\\s\\S]*?)(\\s*)$/;\n/**\n * decodes all entities into regular string\n * @param value\n * @returns {string} A string with decoded entities.\n */\nfunction decodeEntities(value) {\n  if (!value) { return ''; }\n\n  // Note: IE8 does not preserve spaces at the start/end of innerHTML\n  // so we must capture them and reattach them afterward\n  var parts = spaceRe.exec(value);\n  var spaceBefore = parts[1];\n  var spaceAfter = parts[3];\n  var content = parts[2];\n  if (content) {\n    hiddenPre.innerHTML=content.replace(/</g,\"&lt;\");\n    // innerText depends on styling as it doesn't display hidden elements.\n    // Therefore, it's better to use textContent not to cause unnecessary\n    // reflows. However, IE<9 don't support textContent so the innerText\n    // fallback is necessary.\n    content = 'textContent' in hiddenPre ?\n      hiddenPre.textContent : hiddenPre.innerText;\n  }\n  return spaceBefore + content + spaceAfter;\n}\n\n/**\n * Escapes all potentially dangerous characters, so that the\n * resulting string can be safely inserted into attribute or\n * element text.\n * @param value\n * @returns escaped text\n */\nfunction encodeEntities(value) {\n  return value.\n    replace(/&/g, '&amp;').\n    replace(NON_ALPHANUMERIC_REGEXP, function(value){\n      return '&#' + value.charCodeAt(0) + ';';\n    }).\n    replace(/</g, '&lt;').\n    replace(/>/g, '&gt;');\n}\n\n/**\n * create an HTML/XML writer which writes to buffer\n * @param {Array} buf use buf.jain('') to get out sanitized html string\n * @returns {object} in the form of {\n *     start: function(tag, attrs, unary) {},\n *     end: function(tag) {},\n *     chars: function(text) {},\n *     comment: function(text) {}\n * }\n */\nfunction htmlSanitizeWriter(buf, uriValidator){\n  var ignore = false;\n  var out = angular.bind(buf, buf.push);\n  return {\n    start: function(tag, attrs, unary){\n      tag = angular.lowercase(tag);\n      if (!ignore && specialElements[tag]) {\n        ignore = tag;\n      }\n      if (!ignore && validElements[tag] === true) {\n        out('<');\n        out(tag);\n        angular.forEach(attrs, function(value, key){\n          var lkey=angular.lowercase(key);\n          var isImage = (tag === 'img' && lkey === 'src') || (lkey === 'background');\n          if (validAttrs[lkey] === true &&\n            (uriAttrs[lkey] !== true || uriValidator(value, isImage))) {\n            out(' ');\n            out(key);\n            out('=\"');\n            out(encodeEntities(value));\n            out('\"');\n          }\n        });\n        out(unary ? '/>' : '>');\n      }\n    },\n    end: function(tag){\n        tag = angular.lowercase(tag);\n        if (!ignore && validElements[tag] === true) {\n          out('</');\n          out(tag);\n          out('>');\n        }\n        if (tag == ignore) {\n          ignore = false;\n        }\n      },\n    chars: function(chars){\n        if (!ignore) {\n          out(encodeEntities(chars));\n        }\n      }\n  };\n}\n\n\n// define ngSanitize module and register $sanitize service\nangular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider);\n\n/* global sanitizeText: false */\n\n/**\n * @ngdoc filter\n * @name ngSanitize.filter:linky\n * @function\n *\n * @description\n * Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and\n * plain email address links.\n *\n * Requires the {@link ngSanitize `ngSanitize`} module to be installed.\n *\n * @param {string} text Input text.\n * @param {string} target Window (_blank|_self|_parent|_top) or named frame to open links in.\n * @returns {string} Html-linkified text.\n *\n * @usage\n   <span ng-bind-html=\"linky_expression | linky\"></span>\n *\n * @example\n   <doc:example module=\"ngSanitize\">\n     <doc:source>\n       <script>\n         function Ctrl($scope) {\n           $scope.snippet =\n             'Pretty text with some links:\\n'+\n             'http://angularjs.org/,\\n'+\n             'mailto:us@somewhere.org,\\n'+\n             'another@somewhere.org,\\n'+\n             'and one more: ftp://127.0.0.1/.';\n           $scope.snippetWithTarget = 'http://angularjs.org/';\n         }\n       </script>\n       <div ng-controller=\"Ctrl\">\n       Snippet: <textarea ng-model=\"snippet\" cols=\"60\" rows=\"3\"></textarea>\n       <table>\n         <tr>\n           <td>Filter</td>\n           <td>Source</td>\n           <td>Rendered</td>\n         </tr>\n         <tr id=\"linky-filter\">\n           <td>linky filter</td>\n           <td>\n             <pre>&lt;div ng-bind-html=\"snippet | linky\"&gt;<br>&lt;/div&gt;</pre>\n           </td>\n           <td>\n             <div ng-bind-html=\"snippet | linky\"></div>\n           </td>\n         </tr>\n         <tr id=\"linky-target\">\n          <td>linky target</td>\n          <td>\n            <pre>&lt;div ng-bind-html=\"snippetWithTarget | linky:'_blank'\"&gt;<br>&lt;/div&gt;</pre>\n          </td>\n          <td>\n            <div ng-bind-html=\"snippetWithTarget | linky:'_blank'\"></div>\n          </td>\n         </tr>\n         <tr id=\"escaped-html\">\n           <td>no filter</td>\n           <td><pre>&lt;div ng-bind=\"snippet\"&gt;<br>&lt;/div&gt;</pre></td>\n           <td><div ng-bind=\"snippet\"></div></td>\n         </tr>\n       </table>\n     </doc:source>\n     <doc:protractor>\n       it('should linkify the snippet with urls', function() {\n         expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()).\n             toBe('Pretty text with some links: http://angularjs.org/, us@somewhere.org, ' +\n                  'another@somewhere.org, and one more: ftp://127.0.0.1/.');\n         expect(element.all(by.css('#linky-filter a')).count()).toEqual(4);\n       });\n\n       it('should not linkify snippet without the linky filter', function() {\n         expect(element(by.id('escaped-html')).element(by.binding('snippet')).getText()).\n             toBe('Pretty text with some links: http://angularjs.org/, mailto:us@somewhere.org, ' +\n                  'another@somewhere.org, and one more: ftp://127.0.0.1/.');\n         expect(element.all(by.css('#escaped-html a')).count()).toEqual(0);\n       });\n\n       it('should update', function() {\n         element(by.model('snippet')).clear();\n         element(by.model('snippet')).sendKeys('new http://link.');\n         expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()).\n             toBe('new http://link.');\n         expect(element.all(by.css('#linky-filter a')).count()).toEqual(1);\n         expect(element(by.id('escaped-html')).element(by.binding('snippet')).getText())\n             .toBe('new http://link.');\n       });\n\n       it('should work with the target property', function() {\n        expect(element(by.id('linky-target')).\n            element(by.binding(\"snippetWithTarget | linky:'_blank'\")).getText()).\n            toBe('http://angularjs.org/');\n        expect(element(by.css('#linky-target a')).getAttribute('target')).toEqual('_blank');\n       });\n     </doc:protractor>\n   </doc:example>\n */\nangular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) {\n  var LINKY_URL_REGEXP =\n        /((ftp|https?):\\/\\/|(mailto:)?[A-Za-z0-9._%+-]+@)\\S*[^\\s.;,(){}<>]/,\n      MAILTO_REGEXP = /^mailto:/;\n\n  return function(text, target) {\n    if (!text) return text;\n    var match;\n    var raw = text;\n    var html = [];\n    var url;\n    var i;\n    while ((match = raw.match(LINKY_URL_REGEXP))) {\n      // We can not end in these as they are sometimes found at the end of the sentence\n      url = match[0];\n      // if we did not match ftp/http/mailto then assume mailto\n      if (match[2] == match[3]) url = 'mailto:' + url;\n      i = match.index;\n      addText(raw.substr(0, i));\n      addLink(url, match[0].replace(MAILTO_REGEXP, ''));\n      raw = raw.substring(i + match[0].length);\n    }\n    addText(raw);\n    return $sanitize(html.join(''));\n\n    function addText(text) {\n      if (!text) {\n        return;\n      }\n      html.push(sanitizeText(text));\n    }\n\n    function addLink(url, text) {\n      html.push('<a ');\n      if (angular.isDefined(target)) {\n        html.push('target=\"');\n        html.push(target);\n        html.push('\" ');\n      }\n      html.push('href=\"');\n      html.push(url);\n      html.push('\">');\n      addText(text);\n      html.push('</a>');\n    }\n  };\n}]);\n\n\n})(window, window.angular);\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/angular-translate-loader-static-files/.bower.json",
    "content": "{\n  \"name\": \"angular-translate-loader-static-files\",\n  \"version\": \"0.1.6\",\n  \"main\": \"./angular-translate-loader-static-files.js\",\n  \"dependencies\": {\n    \"angular\": \"1.0.8\",\n    \"angular-translate\": \"~1.1.1\"\n  },\n  \"homepage\": \"https://github.com/PascalPrecht/bower-angular-translate-loader-static-files\",\n  \"_release\": \"0.1.6\",\n  \"_resolution\": {\n    \"type\": \"version\",\n    \"tag\": \"0.1.6\",\n    \"commit\": \"eaac546d29d6cde45873e6bad9d18cdff071d983\"\n  },\n  \"_source\": \"git://github.com/PascalPrecht/bower-angular-translate-loader-static-files.git\",\n  \"_target\": \"0.1.6\",\n  \"_originalSource\": \"angular-translate-loader-static-files\"\n}"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/angular-translate-loader-static-files/angular-translate-loader-static-files.js",
    "content": "/*!\n * angular-translate - v2.4.2 - 2014-10-21\n * http://github.com/angular-translate/angular-translate\n * Copyright (c) 2014 ; Licensed MIT\n */\nangular.module('pascalprecht.translate').factory('$translateStaticFilesLoader', [\n  '$q',\n  '$http',\n  function ($q, $http) {\n    return function (options) {\n      if (!options || (!angular.isString(options.prefix) || !angular.isString(options.suffix))) {\n        throw new Error('Couldn\\'t load static files, no prefix or suffix specified!');\n      }\n      var deferred = $q.defer();\n      $http(angular.extend({\n        url: [\n          options.prefix,\n          options.key,\n          options.suffix\n        ].join(''),\n        method: 'GET',\n        params: ''\n      }, options.$http)).success(function (data) {\n        deferred.resolve(data);\n      }).error(function (data) {\n        deferred.reject(options.key);\n      });\n      return deferred.promise;\n    };\n  }\n]);"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/angular-translate-storage-cookie/.bower.json",
    "content": "{\n  \"name\": \"angular-translate-storage-cookie\",\n  \"version\": \"0.1.6\",\n  \"main\": \"./angular-translate-storage-cookie.js\",\n  \"dependencies\": {\n    \"angular\": \"1.0.8\",\n    \"angular-cookies\": \"1.0.8\",\n    \"angular-translate\": \"~1.1.1\"\n  },\n  \"homepage\": \"https://github.com/PascalPrecht/bower-angular-translate-storage-cookie\",\n  \"_release\": \"0.1.6\",\n  \"_resolution\": {\n    \"type\": \"version\",\n    \"tag\": \"0.1.6\",\n    \"commit\": \"fc9ea3275f0f9bf0a60ca073b58488d934a348ac\"\n  },\n  \"_source\": \"git://github.com/PascalPrecht/bower-angular-translate-storage-cookie.git\",\n  \"_target\": \"0.1.6\",\n  \"_originalSource\": \"angular-translate-storage-cookie\"\n}"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/angular-translate-storage-cookie/angular-translate-storage-cookie.js",
    "content": "/*!\n * angular-translate - v2.4.2 - 2014-10-21\n * http://github.com/angular-translate/angular-translate\n * Copyright (c) 2014 ; Licensed MIT\n */\nangular.module('pascalprecht.translate').factory('$translateCookieStorage', [\n  '$cookieStore',\n  function ($cookieStore) {\n    var $translateCookieStorage = {\n        get: function (name) {\n          return $cookieStore.get(name);\n        },\n        set: function (name, value) {\n          $cookieStore.put(name, value);\n        }\n      };\n    return $translateCookieStorage;\n  }\n]);"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/angular-translate_2.4.2/angular-translate.js",
    "content": "/*!\n * angular-translate - v2.4.2 - 2014-10-21\n * http://github.com/angular-translate/angular-translate\n * Copyright (c) 2014 ; Licensed MIT\n */\nangular.module('pascalprecht.translate', ['ng']).run([\n  '$translate',\n  function ($translate) {\n    var key = $translate.storageKey(), storage = $translate.storage();\n    if (storage) {\n      if (!storage.get(key)) {\n        if (angular.isString($translate.preferredLanguage())) {\n          $translate.use($translate.preferredLanguage());\n        } else {\n          storage.set(key, $translate.use());\n        }\n      } else {\n        $translate.use(storage.get(key));\n      }\n    } else if (angular.isString($translate.preferredLanguage())) {\n      $translate.use($translate.preferredLanguage());\n    }\n  }\n]);\nangular.module('pascalprecht.translate').provider('$translate', [\n  '$STORAGE_KEY',\n  function ($STORAGE_KEY) {\n    var $translationTable = {}, $preferredLanguage, $availableLanguageKeys = [], $languageKeyAliases, $fallbackLanguage, $fallbackWasString, $uses, $nextLang, $storageFactory, $storageKey = $STORAGE_KEY, $storagePrefix, $missingTranslationHandlerFactory, $interpolationFactory, $interpolatorFactories = [], $interpolationSanitizationStrategy = false, $loaderFactory, $cloakClassName = 'translate-cloak', $loaderOptions, $notFoundIndicatorLeft, $notFoundIndicatorRight, $postCompilingEnabled = false, NESTED_OBJECT_DELIMITER = '.', loaderCache;\n    var version = '2.4.2';\n    var getLocale = function () {\n      var nav = window.navigator;\n      return ((angular.isArray(nav.languages) ? nav.languages[0] : nav.language || nav.browserLanguage || nav.systemLanguage || nav.userLanguage) || '').split('-').join('_');\n    };\n    var indexOf = function (array, searchElement) {\n      for (var i = 0, len = array.length; i < len; i++) {\n        if (array[i] === searchElement) {\n          return i;\n        }\n      }\n      return -1;\n    };\n    var trim = function () {\n      return this.replace(/^\\s+|\\s+$/g, '');\n    };\n    var negotiateLocale = function (preferred) {\n      var avail = [], locale = angular.lowercase(preferred), i = 0, n = $availableLanguageKeys.length;\n      for (; i < n; i++) {\n        avail.push(angular.lowercase($availableLanguageKeys[i]));\n      }\n      if (indexOf(avail, locale) > -1) {\n        return preferred;\n      }\n      if ($languageKeyAliases) {\n        var alias;\n        for (var langKeyAlias in $languageKeyAliases) {\n          var hasWildcardKey = false;\n          var hasExactKey = Object.prototype.hasOwnProperty.call($languageKeyAliases, langKeyAlias) && angular.lowercase(langKeyAlias) === angular.lowercase(preferred);\n          if (langKeyAlias.slice(-1) === '*') {\n            hasWildcardKey = langKeyAlias.slice(0, -1) === preferred.slice(0, langKeyAlias.length - 1);\n          }\n          if (hasExactKey || hasWildcardKey) {\n            alias = $languageKeyAliases[langKeyAlias];\n            if (indexOf(avail, angular.lowercase(alias)) > -1) {\n              return alias;\n            }\n          }\n        }\n      }\n      var parts = preferred.split('_');\n      if (parts.length > 1 && indexOf(avail, angular.lowercase(parts[0])) > -1) {\n        return parts[0];\n      }\n      return preferred;\n    };\n    var translations = function (langKey, translationTable) {\n      if (!langKey && !translationTable) {\n        return $translationTable;\n      }\n      if (langKey && !translationTable) {\n        if (angular.isString(langKey)) {\n          return $translationTable[langKey];\n        }\n      } else {\n        if (!angular.isObject($translationTable[langKey])) {\n          $translationTable[langKey] = {};\n        }\n        angular.extend($translationTable[langKey], flatObject(translationTable));\n      }\n      return this;\n    };\n    this.translations = translations;\n    this.cloakClassName = function (name) {\n      if (!name) {\n        return $cloakClassName;\n      }\n      $cloakClassName = name;\n      return this;\n    };\n    var flatObject = function (data, path, result, prevKey) {\n      var key, keyWithPath, keyWithShortPath, val;\n      if (!path) {\n        path = [];\n      }\n      if (!result) {\n        result = {};\n      }\n      for (key in data) {\n        if (!Object.prototype.hasOwnProperty.call(data, key)) {\n          continue;\n        }\n        val = data[key];\n        if (angular.isObject(val)) {\n          flatObject(val, path.concat(key), result, key);\n        } else {\n          keyWithPath = path.length ? '' + path.join(NESTED_OBJECT_DELIMITER) + NESTED_OBJECT_DELIMITER + key : key;\n          if (path.length && key === prevKey) {\n            keyWithShortPath = '' + path.join(NESTED_OBJECT_DELIMITER);\n            result[keyWithShortPath] = '@:' + keyWithPath;\n          }\n          result[keyWithPath] = val;\n        }\n      }\n      return result;\n    };\n    this.addInterpolation = function (factory) {\n      $interpolatorFactories.push(factory);\n      return this;\n    };\n    this.useMessageFormatInterpolation = function () {\n      return this.useInterpolation('$translateMessageFormatInterpolation');\n    };\n    this.useInterpolation = function (factory) {\n      $interpolationFactory = factory;\n      return this;\n    };\n    this.useSanitizeValueStrategy = function (value) {\n      $interpolationSanitizationStrategy = value;\n      return this;\n    };\n    this.preferredLanguage = function (langKey) {\n      setupPreferredLanguage(langKey);\n      return this;\n    };\n    var setupPreferredLanguage = function (langKey) {\n      if (langKey) {\n        $preferredLanguage = langKey;\n      }\n      return $preferredLanguage;\n    };\n    this.translationNotFoundIndicator = function (indicator) {\n      this.translationNotFoundIndicatorLeft(indicator);\n      this.translationNotFoundIndicatorRight(indicator);\n      return this;\n    };\n    this.translationNotFoundIndicatorLeft = function (indicator) {\n      if (!indicator) {\n        return $notFoundIndicatorLeft;\n      }\n      $notFoundIndicatorLeft = indicator;\n      return this;\n    };\n    this.translationNotFoundIndicatorRight = function (indicator) {\n      if (!indicator) {\n        return $notFoundIndicatorRight;\n      }\n      $notFoundIndicatorRight = indicator;\n      return this;\n    };\n    this.fallbackLanguage = function (langKey) {\n      fallbackStack(langKey);\n      return this;\n    };\n    var fallbackStack = function (langKey) {\n      if (langKey) {\n        if (angular.isString(langKey)) {\n          $fallbackWasString = true;\n          $fallbackLanguage = [langKey];\n        } else if (angular.isArray(langKey)) {\n          $fallbackWasString = false;\n          $fallbackLanguage = langKey;\n        }\n        if (angular.isString($preferredLanguage) && indexOf($fallbackLanguage, $preferredLanguage) < 0) {\n          $fallbackLanguage.push($preferredLanguage);\n        }\n        return this;\n      } else {\n        if ($fallbackWasString) {\n          return $fallbackLanguage[0];\n        } else {\n          return $fallbackLanguage;\n        }\n      }\n    };\n    this.use = function (langKey) {\n      if (langKey) {\n        if (!$translationTable[langKey] && !$loaderFactory) {\n          throw new Error('$translateProvider couldn\\'t find translationTable for langKey: \\'' + langKey + '\\'');\n        }\n        $uses = langKey;\n        return this;\n      }\n      return $uses;\n    };\n    var storageKey = function (key) {\n      if (!key) {\n        if ($storagePrefix) {\n          return $storagePrefix + $storageKey;\n        }\n        return $storageKey;\n      }\n      $storageKey = key;\n    };\n    this.storageKey = storageKey;\n    this.useUrlLoader = function (url, options) {\n      return this.useLoader('$translateUrlLoader', angular.extend({ url: url }, options));\n    };\n    this.useStaticFilesLoader = function (options) {\n      return this.useLoader('$translateStaticFilesLoader', options);\n    };\n    this.useLoader = function (loaderFactory, options) {\n      $loaderFactory = loaderFactory;\n      $loaderOptions = options || {};\n      return this;\n    };\n    this.useLocalStorage = function () {\n      return this.useStorage('$translateLocalStorage');\n    };\n    this.useCookieStorage = function () {\n      return this.useStorage('$translateCookieStorage');\n    };\n    this.useStorage = function (storageFactory) {\n      $storageFactory = storageFactory;\n      return this;\n    };\n    this.storagePrefix = function (prefix) {\n      if (!prefix) {\n        return prefix;\n      }\n      $storagePrefix = prefix;\n      return this;\n    };\n    this.useMissingTranslationHandlerLog = function () {\n      return this.useMissingTranslationHandler('$translateMissingTranslationHandlerLog');\n    };\n    this.useMissingTranslationHandler = function (factory) {\n      $missingTranslationHandlerFactory = factory;\n      return this;\n    };\n    this.usePostCompiling = function (value) {\n      $postCompilingEnabled = !!value;\n      return this;\n    };\n    this.determinePreferredLanguage = function (fn) {\n      var locale = fn && angular.isFunction(fn) ? fn() : getLocale();\n      if (!$availableLanguageKeys.length) {\n        $preferredLanguage = locale;\n      } else {\n        $preferredLanguage = negotiateLocale(locale);\n      }\n      return this;\n    };\n    this.registerAvailableLanguageKeys = function (languageKeys, aliases) {\n      if (languageKeys) {\n        $availableLanguageKeys = languageKeys;\n        if (aliases) {\n          $languageKeyAliases = aliases;\n        }\n        return this;\n      }\n      return $availableLanguageKeys;\n    };\n    this.useLoaderCache = function (cache) {\n      if (cache === false) {\n        loaderCache = undefined;\n      } else if (cache === true) {\n        loaderCache = true;\n      } else if (typeof cache === 'undefined') {\n        loaderCache = '$translationCache';\n      } else if (cache) {\n        loaderCache = cache;\n      }\n      return this;\n    };\n    this.$get = [\n      '$log',\n      '$injector',\n      '$rootScope',\n      '$q',\n      function ($log, $injector, $rootScope, $q) {\n        var Storage, defaultInterpolator = $injector.get($interpolationFactory || '$translateDefaultInterpolation'), pendingLoader = false, interpolatorHashMap = {}, langPromises = {}, fallbackIndex, startFallbackIteration;\n        var $translate = function (translationId, interpolateParams, interpolationId) {\n          if (angular.isArray(translationId)) {\n            var translateAll = function (translationIds) {\n              var results = {};\n              var promises = [];\n              var translate = function (translationId) {\n                var deferred = $q.defer();\n                var regardless = function (value) {\n                  results[translationId] = value;\n                  deferred.resolve([\n                    translationId,\n                    value\n                  ]);\n                };\n                $translate(translationId, interpolateParams, interpolationId).then(regardless, regardless);\n                return deferred.promise;\n              };\n              for (var i = 0, c = translationIds.length; i < c; i++) {\n                promises.push(translate(translationIds[i]));\n              }\n              return $q.all(promises).then(function () {\n                return results;\n              });\n            };\n            return translateAll(translationId);\n          }\n          var deferred = $q.defer();\n          if (translationId) {\n            translationId = trim.apply(translationId);\n          }\n          var promiseToWaitFor = function () {\n              var promise = $preferredLanguage ? langPromises[$preferredLanguage] : langPromises[$uses];\n              fallbackIndex = 0;\n              if ($storageFactory && !promise) {\n                var langKey = Storage.get($storageKey);\n                promise = langPromises[langKey];\n                if ($fallbackLanguage && $fallbackLanguage.length) {\n                  var index = indexOf($fallbackLanguage, langKey);\n                  fallbackIndex = index === 0 ? 1 : 0;\n                  if (indexOf($fallbackLanguage, $preferredLanguage) < 0) {\n                    $fallbackLanguage.push($preferredLanguage);\n                  }\n                }\n              }\n              return promise;\n            }();\n          if (!promiseToWaitFor) {\n            determineTranslation(translationId, interpolateParams, interpolationId).then(deferred.resolve, deferred.reject);\n          } else {\n            promiseToWaitFor.then(function () {\n              determineTranslation(translationId, interpolateParams, interpolationId).then(deferred.resolve, deferred.reject);\n            }, deferred.reject);\n          }\n          return deferred.promise;\n        };\n        var applyNotFoundIndicators = function (translationId) {\n          if ($notFoundIndicatorLeft) {\n            translationId = [\n              $notFoundIndicatorLeft,\n              translationId\n            ].join(' ');\n          }\n          if ($notFoundIndicatorRight) {\n            translationId = [\n              translationId,\n              $notFoundIndicatorRight\n            ].join(' ');\n          }\n          return translationId;\n        };\n        var useLanguage = function (key) {\n          $uses = key;\n          $rootScope.$emit('$translateChangeSuccess', { language: key });\n          if ($storageFactory) {\n            Storage.set($translate.storageKey(), $uses);\n          }\n          defaultInterpolator.setLocale($uses);\n          angular.forEach(interpolatorHashMap, function (interpolator, id) {\n            interpolatorHashMap[id].setLocale($uses);\n          });\n          $rootScope.$emit('$translateChangeEnd', { language: key });\n        };\n        var loadAsync = function (key) {\n          if (!key) {\n            throw 'No language key specified for loading.';\n          }\n          var deferred = $q.defer();\n          $rootScope.$emit('$translateLoadingStart', { language: key });\n          pendingLoader = true;\n          var cache = loaderCache;\n          if (typeof cache === 'string') {\n            cache = $injector.get(cache);\n          }\n          var loaderOptions = angular.extend({}, $loaderOptions, {\n              key: key,\n              $http: angular.extend({}, { cache: cache }, $loaderOptions.$http)\n            });\n          $injector.get($loaderFactory)(loaderOptions).then(function (data) {\n            var translationTable = {};\n            $rootScope.$emit('$translateLoadingSuccess', { language: key });\n            if (angular.isArray(data)) {\n              angular.forEach(data, function (table) {\n                angular.extend(translationTable, flatObject(table));\n              });\n            } else {\n              angular.extend(translationTable, flatObject(data));\n            }\n            pendingLoader = false;\n            deferred.resolve({\n              key: key,\n              table: translationTable\n            });\n            $rootScope.$emit('$translateLoadingEnd', { language: key });\n          }, function (key) {\n            $rootScope.$emit('$translateLoadingError', { language: key });\n            deferred.reject(key);\n            $rootScope.$emit('$translateLoadingEnd', { language: key });\n          });\n          return deferred.promise;\n        };\n        if ($storageFactory) {\n          Storage = $injector.get($storageFactory);\n          if (!Storage.get || !Storage.set) {\n            throw new Error('Couldn\\'t use storage \\'' + $storageFactory + '\\', missing get() or set() method!');\n          }\n        }\n        if (angular.isFunction(defaultInterpolator.useSanitizeValueStrategy)) {\n          defaultInterpolator.useSanitizeValueStrategy($interpolationSanitizationStrategy);\n        }\n        if ($interpolatorFactories.length) {\n          angular.forEach($interpolatorFactories, function (interpolatorFactory) {\n            var interpolator = $injector.get(interpolatorFactory);\n            interpolator.setLocale($preferredLanguage || $uses);\n            if (angular.isFunction(interpolator.useSanitizeValueStrategy)) {\n              interpolator.useSanitizeValueStrategy($interpolationSanitizationStrategy);\n            }\n            interpolatorHashMap[interpolator.getInterpolationIdentifier()] = interpolator;\n          });\n        }\n        var getTranslationTable = function (langKey) {\n          var deferred = $q.defer();\n          if (Object.prototype.hasOwnProperty.call($translationTable, langKey)) {\n            deferred.resolve($translationTable[langKey]);\n          } else if (langPromises[langKey]) {\n            langPromises[langKey].then(function (data) {\n              translations(data.key, data.table);\n              deferred.resolve(data.table);\n            }, deferred.reject);\n          } else {\n            deferred.reject();\n          }\n          return deferred.promise;\n        };\n        var getFallbackTranslation = function (langKey, translationId, interpolateParams, Interpolator) {\n          var deferred = $q.defer();\n          getTranslationTable(langKey).then(function (translationTable) {\n            if (Object.prototype.hasOwnProperty.call(translationTable, translationId)) {\n              Interpolator.setLocale(langKey);\n              deferred.resolve(Interpolator.interpolate(translationTable[translationId], interpolateParams));\n              Interpolator.setLocale($uses);\n            } else {\n              deferred.reject();\n            }\n          }, deferred.reject);\n          return deferred.promise;\n        };\n        var getFallbackTranslationInstant = function (langKey, translationId, interpolateParams, Interpolator) {\n          var result, translationTable = $translationTable[langKey];\n          if (Object.prototype.hasOwnProperty.call(translationTable, translationId)) {\n            Interpolator.setLocale(langKey);\n            result = Interpolator.interpolate(translationTable[translationId], interpolateParams);\n            Interpolator.setLocale($uses);\n          }\n          return result;\n        };\n        var translateByHandler = function (translationId) {\n          if ($missingTranslationHandlerFactory) {\n            var resultString = $injector.get($missingTranslationHandlerFactory)(translationId, $uses);\n            if (resultString !== undefined) {\n              return resultString;\n            } else {\n              return translationId;\n            }\n          } else {\n            return translationId;\n          }\n        };\n        var resolveForFallbackLanguage = function (fallbackLanguageIndex, translationId, interpolateParams, Interpolator) {\n          var deferred = $q.defer();\n          if (fallbackLanguageIndex < $fallbackLanguage.length) {\n            var langKey = $fallbackLanguage[fallbackLanguageIndex];\n            getFallbackTranslation(langKey, translationId, interpolateParams, Interpolator).then(deferred.resolve, function () {\n              resolveForFallbackLanguage(fallbackLanguageIndex + 1, translationId, interpolateParams, Interpolator).then(deferred.resolve);\n            });\n          } else {\n            deferred.resolve(translateByHandler(translationId));\n          }\n          return deferred.promise;\n        };\n        var resolveForFallbackLanguageInstant = function (fallbackLanguageIndex, translationId, interpolateParams, Interpolator) {\n          var result;\n          if (fallbackLanguageIndex < $fallbackLanguage.length) {\n            var langKey = $fallbackLanguage[fallbackLanguageIndex];\n            result = getFallbackTranslationInstant(langKey, translationId, interpolateParams, Interpolator);\n            if (!result) {\n              result = resolveForFallbackLanguageInstant(fallbackLanguageIndex + 1, translationId, interpolateParams, Interpolator);\n            }\n          }\n          return result;\n        };\n        var fallbackTranslation = function (translationId, interpolateParams, Interpolator) {\n          return resolveForFallbackLanguage(startFallbackIteration > 0 ? startFallbackIteration : fallbackIndex, translationId, interpolateParams, Interpolator);\n        };\n        var fallbackTranslationInstant = function (translationId, interpolateParams, Interpolator) {\n          return resolveForFallbackLanguageInstant(startFallbackIteration > 0 ? startFallbackIteration : fallbackIndex, translationId, interpolateParams, Interpolator);\n        };\n        var determineTranslation = function (translationId, interpolateParams, interpolationId) {\n          var deferred = $q.defer();\n          var table = $uses ? $translationTable[$uses] : $translationTable, Interpolator = interpolationId ? interpolatorHashMap[interpolationId] : defaultInterpolator;\n          if (table && Object.prototype.hasOwnProperty.call(table, translationId)) {\n            var translation = table[translationId];\n            if (translation.substr(0, 2) === '@:') {\n              $translate(translation.substr(2), interpolateParams, interpolationId).then(deferred.resolve, deferred.reject);\n            } else {\n              deferred.resolve(Interpolator.interpolate(translation, interpolateParams));\n            }\n          } else {\n            var missingTranslationHandlerTranslation;\n            if ($missingTranslationHandlerFactory && !pendingLoader) {\n              missingTranslationHandlerTranslation = translateByHandler(translationId);\n            }\n            if ($uses && $fallbackLanguage && $fallbackLanguage.length) {\n              fallbackTranslation(translationId, interpolateParams, Interpolator).then(function (translation) {\n                deferred.resolve(translation);\n              }, function (_translationId) {\n                deferred.reject(applyNotFoundIndicators(_translationId));\n              });\n            } else if ($missingTranslationHandlerFactory && !pendingLoader && missingTranslationHandlerTranslation) {\n              deferred.resolve(missingTranslationHandlerTranslation);\n            } else {\n              deferred.reject(applyNotFoundIndicators(translationId));\n            }\n          }\n          return deferred.promise;\n        };\n        var determineTranslationInstant = function (translationId, interpolateParams, interpolationId) {\n          var result, table = $uses ? $translationTable[$uses] : $translationTable, Interpolator = interpolationId ? interpolatorHashMap[interpolationId] : defaultInterpolator;\n          if (table && Object.prototype.hasOwnProperty.call(table, translationId)) {\n            var translation = table[translationId];\n            if (translation.substr(0, 2) === '@:') {\n              result = determineTranslationInstant(translation.substr(2), interpolateParams, interpolationId);\n            } else {\n              result = Interpolator.interpolate(translation, interpolateParams);\n            }\n          } else {\n            var missingTranslationHandlerTranslation;\n            if ($missingTranslationHandlerFactory && !pendingLoader) {\n              missingTranslationHandlerTranslation = translateByHandler(translationId);\n            }\n            if ($uses && $fallbackLanguage && $fallbackLanguage.length) {\n              fallbackIndex = 0;\n              result = fallbackTranslationInstant(translationId, interpolateParams, Interpolator);\n            } else if ($missingTranslationHandlerFactory && !pendingLoader && missingTranslationHandlerTranslation) {\n              result = missingTranslationHandlerTranslation;\n            } else {\n              result = applyNotFoundIndicators(translationId);\n            }\n          }\n          return result;\n        };\n        $translate.preferredLanguage = function (langKey) {\n          if (langKey) {\n            setupPreferredLanguage(langKey);\n          }\n          return $preferredLanguage;\n        };\n        $translate.cloakClassName = function () {\n          return $cloakClassName;\n        };\n        $translate.fallbackLanguage = function (langKey) {\n          if (langKey !== undefined && langKey !== null) {\n            fallbackStack(langKey);\n            if ($loaderFactory) {\n              if ($fallbackLanguage && $fallbackLanguage.length) {\n                for (var i = 0, len = $fallbackLanguage.length; i < len; i++) {\n                  if (!langPromises[$fallbackLanguage[i]]) {\n                    langPromises[$fallbackLanguage[i]] = loadAsync($fallbackLanguage[i]);\n                  }\n                }\n              }\n            }\n            $translate.use($translate.use());\n          }\n          if ($fallbackWasString) {\n            return $fallbackLanguage[0];\n          } else {\n            return $fallbackLanguage;\n          }\n        };\n        $translate.useFallbackLanguage = function (langKey) {\n          if (langKey !== undefined && langKey !== null) {\n            if (!langKey) {\n              startFallbackIteration = 0;\n            } else {\n              var langKeyPosition = indexOf($fallbackLanguage, langKey);\n              if (langKeyPosition > -1) {\n                startFallbackIteration = langKeyPosition;\n              }\n            }\n          }\n        };\n        $translate.proposedLanguage = function () {\n          return $nextLang;\n        };\n        $translate.storage = function () {\n          return Storage;\n        };\n        $translate.use = function (key) {\n          if (!key) {\n            return $uses;\n          }\n          var deferred = $q.defer();\n          $rootScope.$emit('$translateChangeStart', { language: key });\n          var aliasedKey = negotiateLocale(key);\n          if (aliasedKey) {\n            key = aliasedKey;\n          }\n          if (!$translationTable[key] && $loaderFactory && !langPromises[key]) {\n            $nextLang = key;\n            langPromises[key] = loadAsync(key).then(function (translation) {\n              translations(translation.key, translation.table);\n              deferred.resolve(translation.key);\n              useLanguage(translation.key);\n              if ($nextLang === key) {\n                $nextLang = undefined;\n              }\n            }, function (key) {\n              if ($nextLang === key) {\n                $nextLang = undefined;\n              }\n              $rootScope.$emit('$translateChangeError', { language: key });\n              deferred.reject(key);\n              $rootScope.$emit('$translateChangeEnd', { language: key });\n            });\n          } else {\n            deferred.resolve(key);\n            useLanguage(key);\n          }\n          return deferred.promise;\n        };\n        $translate.storageKey = function () {\n          return storageKey();\n        };\n        $translate.isPostCompilingEnabled = function () {\n          return $postCompilingEnabled;\n        };\n        $translate.refresh = function (langKey) {\n          if (!$loaderFactory) {\n            throw new Error('Couldn\\'t refresh translation table, no loader registered!');\n          }\n          var deferred = $q.defer();\n          function resolve() {\n            deferred.resolve();\n            $rootScope.$emit('$translateRefreshEnd', { language: langKey });\n          }\n          function reject() {\n            deferred.reject();\n            $rootScope.$emit('$translateRefreshEnd', { language: langKey });\n          }\n          $rootScope.$emit('$translateRefreshStart', { language: langKey });\n          if (!langKey) {\n            var tables = [], loadingKeys = {};\n            if ($fallbackLanguage && $fallbackLanguage.length) {\n              for (var i = 0, len = $fallbackLanguage.length; i < len; i++) {\n                tables.push(loadAsync($fallbackLanguage[i]));\n                loadingKeys[$fallbackLanguage[i]] = true;\n              }\n            }\n            if ($uses && !loadingKeys[$uses]) {\n              tables.push(loadAsync($uses));\n            }\n            $q.all(tables).then(function (tableData) {\n              angular.forEach(tableData, function (data) {\n                if ($translationTable[data.key]) {\n                  delete $translationTable[data.key];\n                }\n                translations(data.key, data.table);\n              });\n              if ($uses) {\n                useLanguage($uses);\n              }\n              resolve();\n            });\n          } else if ($translationTable[langKey]) {\n            loadAsync(langKey).then(function (data) {\n              translations(data.key, data.table);\n              if (langKey === $uses) {\n                useLanguage($uses);\n              }\n              resolve();\n            }, reject);\n          } else {\n            reject();\n          }\n          return deferred.promise;\n        };\n        $translate.instant = function (translationId, interpolateParams, interpolationId) {\n          if (translationId === null || angular.isUndefined(translationId)) {\n            return translationId;\n          }\n          if (angular.isArray(translationId)) {\n            var results = {};\n            for (var i = 0, c = translationId.length; i < c; i++) {\n              results[translationId[i]] = $translate.instant(translationId[i], interpolateParams, interpolationId);\n            }\n            return results;\n          }\n          if (angular.isString(translationId) && translationId.length < 1) {\n            return translationId;\n          }\n          if (translationId) {\n            translationId = trim.apply(translationId);\n          }\n          var result, possibleLangKeys = [];\n          if ($preferredLanguage) {\n            possibleLangKeys.push($preferredLanguage);\n          }\n          if ($uses) {\n            possibleLangKeys.push($uses);\n          }\n          if ($fallbackLanguage && $fallbackLanguage.length) {\n            possibleLangKeys = possibleLangKeys.concat($fallbackLanguage);\n          }\n          for (var j = 0, d = possibleLangKeys.length; j < d; j++) {\n            var possibleLangKey = possibleLangKeys[j];\n            if ($translationTable[possibleLangKey]) {\n              if (typeof $translationTable[possibleLangKey][translationId] !== 'undefined') {\n                result = determineTranslationInstant(translationId, interpolateParams, interpolationId);\n              }\n            }\n            if (typeof result !== 'undefined') {\n              break;\n            }\n          }\n          if (!result && result !== '') {\n            result = defaultInterpolator.interpolate(translationId, interpolateParams);\n            if ($missingTranslationHandlerFactory && !pendingLoader) {\n              result = translateByHandler(translationId);\n            }\n          }\n          return result;\n        };\n        $translate.versionInfo = function () {\n          return version;\n        };\n        $translate.loaderCache = function () {\n          return loaderCache;\n        };\n        if ($loaderFactory) {\n          if (angular.equals($translationTable, {})) {\n            $translate.use($translate.use());\n          }\n          if ($fallbackLanguage && $fallbackLanguage.length) {\n            var processAsyncResult = function (translation) {\n              translations(translation.key, translation.table);\n              $rootScope.$emit('$translateChangeEnd', { language: translation.key });\n            };\n            for (var i = 0, len = $fallbackLanguage.length; i < len; i++) {\n              langPromises[$fallbackLanguage[i]] = loadAsync($fallbackLanguage[i]).then(processAsyncResult);\n            }\n          }\n        }\n        return $translate;\n      }\n    ];\n  }\n]);\nangular.module('pascalprecht.translate').factory('$translateDefaultInterpolation', [\n  '$interpolate',\n  function ($interpolate) {\n    var $translateInterpolator = {}, $locale, $identifier = 'default', $sanitizeValueStrategy = null, sanitizeValueStrategies = {\n        escaped: function (params) {\n          var result = {};\n          for (var key in params) {\n            if (Object.prototype.hasOwnProperty.call(params, key)) {\n              result[key] = angular.element('<div></div>').text(params[key]).html();\n            }\n          }\n          return result;\n        }\n      };\n    var sanitizeParams = function (params) {\n      var result;\n      if (angular.isFunction(sanitizeValueStrategies[$sanitizeValueStrategy])) {\n        result = sanitizeValueStrategies[$sanitizeValueStrategy](params);\n      } else {\n        result = params;\n      }\n      return result;\n    };\n    $translateInterpolator.setLocale = function (locale) {\n      $locale = locale;\n    };\n    $translateInterpolator.getInterpolationIdentifier = function () {\n      return $identifier;\n    };\n    $translateInterpolator.useSanitizeValueStrategy = function (value) {\n      $sanitizeValueStrategy = value;\n      return this;\n    };\n    $translateInterpolator.interpolate = function (string, interpolateParams) {\n      if ($sanitizeValueStrategy) {\n        interpolateParams = sanitizeParams(interpolateParams);\n      }\n      return $interpolate(string)(interpolateParams || {});\n    };\n    return $translateInterpolator;\n  }\n]);\nangular.module('pascalprecht.translate').constant('$STORAGE_KEY', 'NG_TRANSLATE_LANG_KEY');\nangular.module('pascalprecht.translate').directive('translate', [\n  '$translate',\n  '$q',\n  '$interpolate',\n  '$compile',\n  '$parse',\n  '$rootScope',\n  function ($translate, $q, $interpolate, $compile, $parse, $rootScope) {\n    return {\n      restrict: 'AE',\n      scope: true,\n      compile: function (tElement, tAttr) {\n        var translateValuesExist = tAttr.translateValues ? tAttr.translateValues : undefined;\n        var translateInterpolation = tAttr.translateInterpolation ? tAttr.translateInterpolation : undefined;\n        var translateValueExist = tElement[0].outerHTML.match(/translate-value-+/i);\n        var interpolateRegExp = '^(.*)(' + $interpolate.startSymbol() + '.*' + $interpolate.endSymbol() + ')(.*)';\n        return function linkFn(scope, iElement, iAttr) {\n          scope.interpolateParams = {};\n          scope.preText = '';\n          scope.postText = '';\n          iAttr.$observe('translate', function (translationId) {\n            if (angular.equals(translationId, '') || !angular.isDefined(translationId)) {\n              var interpolateMatches = iElement.text().match(interpolateRegExp);\n              if (angular.isArray(interpolateMatches)) {\n                scope.preText = interpolateMatches[1];\n                scope.postText = interpolateMatches[3];\n                scope.translationId = $interpolate(interpolateMatches[2])(scope.$parent);\n              } else {\n                scope.translationId = iElement.text().replace(/^\\s+|\\s+$/g, '');\n              }\n            } else {\n              scope.translationId = translationId;\n            }\n          });\n          iAttr.$observe('translateDefault', function (value) {\n            scope.defaultText = value;\n          });\n          if (translateValuesExist) {\n            iAttr.$observe('translateValues', function (interpolateParams) {\n              if (interpolateParams) {\n                scope.$parent.$watch(function () {\n                  angular.extend(scope.interpolateParams, $parse(interpolateParams)(scope.$parent));\n                });\n              }\n            });\n          }\n          if (translateValueExist) {\n            var fn = function (attrName) {\n              iAttr.$observe(attrName, function (value) {\n                scope.interpolateParams[angular.lowercase(attrName.substr(14, 1)) + attrName.substr(15)] = value;\n              });\n            };\n            for (var attr in iAttr) {\n              if (Object.prototype.hasOwnProperty.call(iAttr, attr) && attr.substr(0, 14) === 'translateValue' && attr !== 'translateValues') {\n                fn(attr);\n              }\n            }\n          }\n          var applyElementContent = function (value, scope, successful) {\n            if (!successful && typeof scope.defaultText !== 'undefined') {\n              value = scope.defaultText;\n            }\n            iElement.html(scope.preText + value + scope.postText);\n            var globallyEnabled = $translate.isPostCompilingEnabled();\n            var locallyDefined = typeof tAttr.translateCompile !== 'undefined';\n            var locallyEnabled = locallyDefined && tAttr.translateCompile !== 'false';\n            if (globallyEnabled && !locallyDefined || locallyEnabled) {\n              $compile(iElement.contents())(scope);\n            }\n          };\n          var updateTranslationFn = function () {\n              if (!translateValuesExist && !translateValueExist) {\n                return function () {\n                  var unwatch = scope.$watch('translationId', function (value) {\n                      if (scope.translationId && value) {\n                        $translate(value, {}, translateInterpolation).then(function (translation) {\n                          applyElementContent(translation, scope, true);\n                          unwatch();\n                        }, function (translationId) {\n                          applyElementContent(translationId, scope, false);\n                          unwatch();\n                        });\n                      }\n                    }, true);\n                };\n              } else {\n                return function () {\n                  var updateTranslations = function () {\n                    if (scope.translationId && scope.interpolateParams) {\n                      $translate(scope.translationId, scope.interpolateParams, translateInterpolation).then(function (translation) {\n                        applyElementContent(translation, scope, true);\n                      }, function (translationId) {\n                        applyElementContent(translationId, scope, false);\n                      });\n                    }\n                  };\n                  scope.$watch('interpolateParams', updateTranslations, true);\n                  scope.$watch('translationId', updateTranslations);\n                };\n              }\n            }();\n          var unbind = $rootScope.$on('$translateChangeSuccess', updateTranslationFn);\n          updateTranslationFn();\n          scope.$on('$destroy', unbind);\n        };\n      }\n    };\n  }\n]);\nangular.module('pascalprecht.translate').directive('translateCloak', [\n  '$rootScope',\n  '$translate',\n  function ($rootScope, $translate) {\n    return {\n      compile: function (tElement) {\n        var applyCloak = function () {\n            tElement.addClass($translate.cloakClassName());\n          }, removeCloak = function () {\n            tElement.removeClass($translate.cloakClassName());\n          }, removeListener = $rootScope.$on('$translateChangeEnd', function () {\n            removeCloak();\n            removeListener();\n            removeListener = null;\n          });\n        applyCloak();\n        return function linkFn(scope, iElement, iAttr) {\n          if (iAttr.translateCloak && iAttr.translateCloak.length) {\n            iAttr.$observe('translateCloak', function (translationId) {\n              $translate(translationId).then(removeCloak, applyCloak);\n            });\n          }\n        };\n      }\n    };\n  }\n]);\nangular.module('pascalprecht.translate').filter('translate', [\n  '$parse',\n  '$translate',\n  function ($parse, $translate) {\n    var translateFilter = function (translationId, interpolateParams, interpolation) {\n      if (!angular.isObject(interpolateParams)) {\n        interpolateParams = $parse(interpolateParams)(this);\n      }\n      return $translate.instant(translationId, interpolateParams, interpolation);\n    };\n    translateFilter.$stateful = true;\n    return translateFilter;\n  }\n]);"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/bootstrap-daterangepicker_1.3.7/daterangepicker-bs3.css",
    "content": "/*!\n * Stylesheet for the Date Range Picker, for use with Bootstrap 3.x\n *\n * Copyright 2013 Dan Grossman ( http://www.dangrossman.info )\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Built for http://www.improvely.com\n */\n\n.daterangepicker.dropdown-menu {\n    max-width: none;\n    z-index: 3000;\n}\n\n.daterangepicker.opensleft .ranges, .daterangepicker.opensleft .calendar {\n    float: left;\n    margin: 4px;\n}\n\n.daterangepicker.opensright .ranges, .daterangepicker.opensright .calendar {\n    float: right;\n    margin: 4px;\n}\n\n.daterangepicker .ranges {\n    width: 160px;\n    text-align: left;\n}\n\n.daterangepicker .ranges .range_inputs>div {\n    float: left;\n}\n\n.daterangepicker .ranges .range_inputs>div:nth-child(2) {\n    padding-left: 11px;\n}\n\n.daterangepicker .calendar {\n    display: none;\n    max-width: 270px;\n}\n\n.daterangepicker.show-calendar .calendar {\n    display: block;\n}\n\n.daterangepicker .calendar.single .calendar-date {\n    border: none;\n}\n\n.daterangepicker .calendar th, .daterangepicker .calendar td {\n    font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;\n    white-space: nowrap;\n    text-align: center;\n    min-width: 32px;\n}\n\n.daterangepicker .daterangepicker_start_input label,\n.daterangepicker .daterangepicker_end_input label {\n    color: #333;\n    display: block;\n    font-size: 11px;\n    font-weight: normal;\n    height: 20px;\n    line-height: 20px;\n    margin-bottom: 2px;\n    text-shadow: #fff 1px 1px 0px;\n    text-transform: uppercase;\n    width: 74px;\n}\n\n.daterangepicker .ranges input {\n    font-size: 11px;\n}\n\n.daterangepicker .ranges .input-mini {\n    background-color: #eee;\n    border: 1px solid #ccc;\n    border-radius: 4px;\n    color: #555;\n    display: block;\n    font-size: 11px;\n    height: 30px;\n    line-height: 30px;\n    vertical-align: middle;\n    margin: 0 0 10px 0;\n    padding: 0 6px;\n    width: 74px;\n}\n\n.daterangepicker .ranges ul {\n    list-style: none;\n    margin: 0;\n    padding: 0;\n}\n\n.daterangepicker .ranges li {\n    font-size: 13px;\n    background: #f5f5f5;\n    border: 1px solid #f5f5f5;\n    color: #08c;\n    padding: 3px 12px;\n    margin-bottom: 8px;\n    -webkit-border-radius: 5px;\n    -moz-border-radius: 5px;\n    border-radius: 5px;\n    cursor: pointer;\n}\n\n.daterangepicker .ranges li.active, .daterangepicker .ranges li:hover {\n    background: #08c;\n    border: 1px solid #08c;\n    color: #fff;\n}\n\n.daterangepicker .calendar-date {\n    border: 1px solid #ddd;\n    padding: 4px;\n    border-radius: 4px;\n    background: #fff;\n}\n\n.daterangepicker .calendar-time {\n    text-align: center;\n    margin: 8px auto 0 auto;\n    line-height: 30px;\n}\n\n.daterangepicker {\n    position: absolute;\n    background: #fff;\n    top: 100px;\n    left: 20px;\n    padding: 4px;\n    margin-top: 1px;\n    -webkit-border-radius: 4px;\n    -moz-border-radius: 4px;\n    border-radius: 4px;\n}\n\n.daterangepicker.opensleft:before {\n    position: absolute;\n    top: -7px;\n    right: 9px;\n    display: inline-block;\n    border-right: 7px solid transparent;\n    border-bottom: 7px solid #ccc;\n    border-left: 7px solid transparent;\n    border-bottom-color: rgba(0, 0, 0, 0.2);\n    content: '';\n}\n\n.daterangepicker.opensleft:after {\n    position: absolute;\n    top: -6px;\n    right: 10px;\n    display: inline-block;\n    border-right: 6px solid transparent;\n    border-bottom: 6px solid #fff;\n    border-left: 6px solid transparent;\n    content: '';\n}\n\n.daterangepicker.opensright:before {\n    position: absolute;\n    top: -7px;\n    left: 9px;\n    display: inline-block;\n    border-right: 7px solid transparent;\n    border-bottom: 7px solid #ccc;\n    border-left: 7px solid transparent;\n    border-bottom-color: rgba(0, 0, 0, 0.2);\n    content: '';\n}\n\n.daterangepicker.opensright:after {\n    position: absolute;\n    top: -6px;\n    left: 10px;\n    display: inline-block;\n    border-right: 6px solid transparent;\n    border-bottom: 6px solid #fff;\n    border-left: 6px solid transparent;\n    content: '';\n}\n\n.daterangepicker table {\n    width: 100%;\n    margin: 0;\n}\n\n.daterangepicker td, .daterangepicker th {\n    text-align: center;\n    width: 20px;\n    height: 20px;\n    -webkit-border-radius: 4px;\n    -moz-border-radius: 4px;\n    border-radius: 4px;\n    cursor: pointer;\n    white-space: nowrap;\n}\n\n.daterangepicker td.off {\n    color: #999;\n}\n\n.daterangepicker td.disabled {\n    color: #999;\n}\n\n.daterangepicker td.available:hover, .daterangepicker th.available:hover {\n    background: #eee;\n}\n\n.daterangepicker td.in-range {\n    background: #ebf4f8;\n    -webkit-border-radius: 0;\n    -moz-border-radius: 0;\n    border-radius: 0;\n}\n\n.daterangepicker td.active, .daterangepicker td.active:hover {\n    background-color: #357ebd;\n    border-color: #3071a9;\n    color: #fff;\n}\n\n.daterangepicker td.week, .daterangepicker th.week {\n    font-size: 80%;\n    color: #ccc;\n}\n\n.daterangepicker select.monthselect, .daterangepicker select.yearselect {\n    font-size: 12px;\n    padding: 1px;\n    height: auto;\n    margin: 0;\n    cursor: default;\n}\n\n.daterangepicker select.monthselect {\n    margin-right: 2%;\n    width: 56%;\n}\n\n.daterangepicker select.yearselect {\n    width: 40%;\n}\n\n.daterangepicker select.hourselect, .daterangepicker select.minuteselect, .daterangepicker select.ampmselect {\n    width: 50px;\n    margin-bottom: 0;\n}\n\n.daterangepicker_start_input {\n    float: left;\n}\n\n.daterangepicker_end_input {\n    float: left;\n    padding-left: 11px\n}\n\n.daterangepicker th.month {\n    width: auto;\n}"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/bootstrap-daterangepicker_1.3.7/daterangepicker.js",
    "content": "/**\n * @version: 1.3.7\n * @author: Dan Grossman http://www.dangrossman.info/\n * @date: 2014-04-29\n * @copyright: Copyright (c) 2012-2014 Dan Grossman. All rights reserved.\n * @license: Licensed under Apache License v2.0. See http://www.apache.org/licenses/LICENSE-2.0\n * @website: http://www.improvely.com/\n */\n!function ($, moment) {\n\n    var DateRangePicker = function (element, options, cb) {\n\n        // by default, the daterangepicker element is placed at the bottom of HTML body\n        this.parentEl = 'body';\n\n        //element that triggered the date range picker\n        this.element = $(element);\n\n        //create the picker HTML object\n        var DRPTemplate = '<div class=\"daterangepicker dropdown-menu\">' +\n            '<div class=\"calendar left\"></div>' +\n            '<div class=\"calendar right\"></div>' +\n            '<div class=\"ranges\">' +\n            '<div class=\"range_inputs\">' +\n            '<div class=\"daterangepicker_start_input\">' +\n            '<label for=\"daterangepicker_start\"></label>' +\n            '<input class=\"input-mini\" type=\"text\" name=\"daterangepicker_start\" value=\"\" disabled=\"disabled\" />' +\n            '</div>' +\n            '<div class=\"daterangepicker_end_input\">' +\n            '<label for=\"daterangepicker_end\"></label>' +\n            '<input class=\"input-mini\" type=\"text\" name=\"daterangepicker_end\" value=\"\" disabled=\"disabled\" />' +\n            '</div>' +\n            '<button class=\"applyBtn\" disabled=\"disabled\"></button>&nbsp;' +\n            '<button class=\"cancelBtn\"></button>' +\n            '</div>' +\n            '</div>' +\n            '</div>';\n\n        //custom options\n        if (typeof options !== 'object' || options === null)\n            options = {};\n\n        this.parentEl = (typeof options === 'object' && options.parentEl && $(options.parentEl).length) ? $(options.parentEl) : $(this.parentEl);\n        this.container = $(DRPTemplate).appendTo(this.parentEl);\n\n        this.setOptions(options, cb);\n\n        //apply CSS classes and labels to buttons\n        var c = this.container;\n        $.each(this.buttonClasses, function (idx, val) {\n            c.find('button').addClass(val);\n        });\n        this.container.find('.daterangepicker_start_input label').html(this.locale.fromLabel);\n        this.container.find('.daterangepicker_end_input label').html(this.locale.toLabel);\n        if (this.applyClass.length)\n            this.container.find('.applyBtn').addClass(this.applyClass);\n        if (this.cancelClass.length)\n            this.container.find('.cancelBtn').addClass(this.cancelClass);\n        this.container.find('.applyBtn').html(this.locale.applyLabel);\n        this.container.find('.cancelBtn').html(this.locale.cancelLabel);\n\n        //event listeners\n\n        this.container.find('.calendar')\n            .on('click.daterangepicker', '.prev', $.proxy(this.clickPrev, this))\n            .on('click.daterangepicker', '.next', $.proxy(this.clickNext, this))\n            .on('click.daterangepicker', 'td.available', $.proxy(this.clickDate, this))\n            .on('mouseenter.daterangepicker', 'td.available', $.proxy(this.enterDate, this))\n            .on('mouseleave.daterangepicker', 'td.available', $.proxy(this.updateFormInputs, this))\n            .on('change.daterangepicker', 'select.yearselect', $.proxy(this.updateMonthYear, this))\n            .on('change.daterangepicker', 'select.monthselect', $.proxy(this.updateMonthYear, this))\n            .on('change.daterangepicker', 'select.hourselect,select.minuteselect,select.ampmselect', $.proxy(this.updateTime, this));\n\n        this.container.find('.ranges')\n            .on('click.daterangepicker', 'button.applyBtn', $.proxy(this.clickApply, this))\n            .on('click.daterangepicker', 'button.cancelBtn', $.proxy(this.clickCancel, this))\n            .on('click.daterangepicker', '.daterangepicker_start_input,.daterangepicker_end_input', $.proxy(this.showCalendars, this))\n            .on('click.daterangepicker', 'li', $.proxy(this.clickRange, this))\n            .on('mouseenter.daterangepicker', 'li', $.proxy(this.enterRange, this))\n            .on('mouseleave.daterangepicker', 'li', $.proxy(this.updateFormInputs, this));\n\n        if (this.element.is('input')) {\n            this.element.on({\n                'click.daterangepicker': $.proxy(this.show, this),\n                'focus.daterangepicker': $.proxy(this.show, this),\n                'keyup.daterangepicker': $.proxy(this.updateFromControl, this)\n            });\n        } else {\n            this.element.on('click.daterangepicker', $.proxy(this.toggle, this));\n        }\n\n    };\n\n    DateRangePicker.prototype = {\n\n        constructor: DateRangePicker,\n\n        setOptions: function(options, callback) {\n\n            this.startDate = moment().startOf('day');\n            this.endDate = moment().endOf('day');\n            this.minDate = false;\n            this.maxDate = false;\n            this.dateLimit = false;\n\n            this.showDropdowns = false;\n            this.showWeekNumbers = false;\n            this.timePicker = false;\n            this.timePickerIncrement = 30;\n            this.timePicker12Hour = true;\n            this.singleDatePicker = false;\n            this.ranges = {};\n\n            this.opens = 'right';\n            if (this.element.hasClass('pull-right'))\n                this.opens = 'left';\n\n            this.buttonClasses = ['btn', 'btn-small'];\n            this.applyClass = 'btn-success';\n            this.cancelClass = 'btn-default';\n\n            this.format = 'MM/DD/YYYY';\n            this.separator = ' - ';\n\n            this.locale = {\n                applyLabel: 'Apply',\n                cancelLabel: 'Cancel',\n                fromLabel: 'From',\n                toLabel: 'To',\n                weekLabel: 'W',\n                customRangeLabel: 'Custom Range',\n                daysOfWeek: moment()._lang._weekdaysMin.slice(),\n                monthNames: moment()._lang._monthsShort.slice(),\n                firstDay: 0\n            };\n\n            this.cb = function () { };\n\n            if (typeof options.format === 'string')\n                this.format = options.format;\n\n            if (typeof options.separator === 'string')\n                this.separator = options.separator;\n\n            if (typeof options.startDate === 'string')\n                this.startDate = moment(options.startDate, this.format);\n\n            if (typeof options.endDate === 'string')\n                this.endDate = moment(options.endDate, this.format);\n\n            if (typeof options.minDate === 'string')\n                this.minDate = moment(options.minDate, this.format);\n\n            if (typeof options.maxDate === 'string')\n                this.maxDate = moment(options.maxDate, this.format);\n\n            if (typeof options.startDate === 'object')\n                this.startDate = moment(options.startDate);\n\n            if (typeof options.endDate === 'object')\n                this.endDate = moment(options.endDate);\n\n            if (typeof options.minDate === 'object')\n                this.minDate = moment(options.minDate);\n\n            if (typeof options.maxDate === 'object')\n                this.maxDate = moment(options.maxDate);\n\n            if (typeof options.applyClass === 'string')\n                this.applyClass = options.applyClass;\n\n            if (typeof options.cancelClass === 'string')\n                this.cancelClass = options.cancelClass;\n\n            if (typeof options.dateLimit === 'object')\n                this.dateLimit = options.dateLimit;\n\n            // update day names order to firstDay\n            if (typeof options.locale === 'object') {\n\n                if (typeof options.locale.daysOfWeek === 'object') {\n                    // Create a copy of daysOfWeek to avoid modification of original\n                    // options object for reusability in multiple daterangepicker instances\n                    this.locale.daysOfWeek = options.locale.daysOfWeek.slice();\n                }\n\n                if (typeof options.locale.monthNames === 'object') {\n                    this.locale.monthNames = options.locale.monthNames.slice();\n                }\n\n                if (typeof options.locale.firstDay === 'number') {\n                    this.locale.firstDay = options.locale.firstDay;\n                    var iterator = options.locale.firstDay;\n                    while (iterator > 0) {\n                        this.locale.daysOfWeek.push(this.locale.daysOfWeek.shift());\n                        iterator--;\n                    }\n                }\n\n                if (typeof options.locale.applyLabel === 'string') {\n                    this.locale.applyLabel = options.locale.applyLabel;\n                }\n\n                if (typeof options.locale.cancelLabel === 'string') {\n                    this.locale.cancelLabel = options.locale.cancelLabel;\n                }\n\n                if (typeof options.locale.fromLabel === 'string') {\n                    this.locale.fromLabel = options.locale.fromLabel;\n                }\n\n                if (typeof options.locale.toLabel === 'string') {\n                    this.locale.toLabel = options.locale.toLabel;\n                }\n\n                if (typeof options.locale.weekLabel === 'string') {\n                    this.locale.weekLabel = options.locale.weekLabel;\n                }\n\n                if (typeof options.locale.customRangeLabel === 'string') {\n                    this.locale.customRangeLabel = options.locale.customRangeLabel;\n                }\n            }\n\n            if (typeof options.opens === 'string')\n                this.opens = options.opens;\n\n            if (typeof options.showWeekNumbers === 'boolean') {\n                this.showWeekNumbers = options.showWeekNumbers;\n            }\n\n            if (typeof options.buttonClasses === 'string') {\n                this.buttonClasses = [options.buttonClasses];\n            }\n\n            if (typeof options.buttonClasses === 'object') {\n                this.buttonClasses = options.buttonClasses;\n            }\n\n            if (typeof options.showDropdowns === 'boolean') {\n                this.showDropdowns = options.showDropdowns;\n            }\n\n            if (typeof options.singleDatePicker === 'boolean') {\n                this.singleDatePicker = options.singleDatePicker;\n            }\n\n            if (typeof options.timePicker === 'boolean') {\n                this.timePicker = options.timePicker;\n            }\n\n            if (typeof options.timePickerIncrement === 'number') {\n                this.timePickerIncrement = options.timePickerIncrement;\n            }\n\n            if (typeof options.timePicker12Hour === 'boolean') {\n                this.timePicker12Hour = options.timePicker12Hour;\n            }\n\n            var start, end, range;\n\n            //if no start/end dates set, check if an input element contains initial values\n            if (typeof options.startDate === 'undefined' && typeof options.endDate === 'undefined') {\n                if ($(this.element).is('input[type=text]')) {\n                    var val = $(this.element).val();\n                    var split = val.split(this.separator);\n                    start = end = null;\n                    if (split.length == 2) {\n                        start = moment(split[0], this.format);\n                        end = moment(split[1], this.format);\n                    } else if (this.singleDatePicker) {\n                        start = moment(val, this.format);\n                        end = moment(val, this.format);\n                    }\n                    if (start !== null && end !== null) {\n                        this.startDate = start;\n                        this.endDate = end;\n                    }\n                }\n            }\n\n            if (typeof options.ranges === 'object') {\n                for (range in options.ranges) {\n\n                    start = moment(options.ranges[range][0]);\n                    end = moment(options.ranges[range][1]);\n\n                    // If we have a min/max date set, bound this range\n                    // to it, but only if it would otherwise fall\n                    // outside of the min/max.\n                    if (this.minDate && start.isBefore(this.minDate))\n                        start = moment(this.minDate);\n\n                    if (this.maxDate && end.isAfter(this.maxDate))\n                        end = moment(this.maxDate);\n\n                    // If the end of the range is before the minimum (if min is set) OR\n                    // the start of the range is after the max (also if set) don't display this\n                    // range option.\n                    if ((this.minDate && end.isBefore(this.minDate)) || (this.maxDate && start.isAfter(this.maxDate))) {\n                        continue;\n                    }\n\n                    this.ranges[range] = [start, end];\n                }\n\n                var list = '<ul>';\n                for (range in this.ranges) {\n                    list += '<li>' + range + '</li>';\n                }\n                list += '<li>' + this.locale.customRangeLabel + '</li>';\n                list += '</ul>';\n                this.container.find('.ranges ul').remove();\n                this.container.find('.ranges').prepend(list);\n            }\n\n            if (typeof callback === 'function') {\n                this.cb = callback;\n            }\n\n            if (!this.timePicker) {\n                this.startDate = this.startDate.startOf('day');\n                this.endDate = this.endDate.endOf('day');\n            }\n\n            if (this.singleDatePicker) {\n                this.opens = 'right';\n                this.container.find('.calendar.right').show();\n                this.container.find('.calendar.left').hide();\n                this.container.find('.ranges').hide();\n                if (!this.container.find('.calendar.right').hasClass('single'))\n                    this.container.find('.calendar.right').addClass('single');\n            } else {\n                this.container.find('.calendar.right').removeClass('single');\n                this.container.find('.ranges').show();\n            }\n\n            this.oldStartDate = this.startDate.clone();\n            this.oldEndDate = this.endDate.clone();\n            this.oldChosenLabel = this.chosenLabel;\n\n            this.leftCalendar = {\n                month: moment([this.startDate.year(), this.startDate.month(), 1, this.startDate.hour(), this.startDate.minute()]),\n                calendar: []\n            };\n\n            this.rightCalendar = {\n                month: moment([this.endDate.year(), this.endDate.month(), 1, this.endDate.hour(), this.endDate.minute()]),\n                calendar: []\n            };\n\n            if (this.opens == 'right') {\n                //swap calendar positions\n                var left = this.container.find('.calendar.left');\n                var right = this.container.find('.calendar.right');\n                left.removeClass('left').addClass('right');\n                right.removeClass('right').addClass('left');\n            }\n\n            if (typeof options.ranges === 'undefined' && !this.singleDatePicker) {\n                this.container.addClass('show-calendar');\n            }\n\n            this.container.addClass('opens' + this.opens);\n\n            this.updateView();\n            this.updateCalendars();\n\n        },\n\n        setStartDate: function(startDate) {\n            if (typeof startDate === 'string')\n                this.startDate = moment(startDate, this.format);\n\n            if (typeof startDate === 'object')\n                this.startDate = moment(startDate);\n\n            if (!this.timePicker)\n                this.startDate = this.startDate.startOf('day');\n\n            this.oldStartDate = this.startDate.clone();\n\n            this.updateView();\n            this.updateCalendars();\n        },\n\n        setEndDate: function(endDate) {\n            if (typeof endDate === 'string')\n                this.endDate = moment(endDate, this.format);\n\n            if (typeof endDate === 'object')\n                this.endDate = moment(endDate);\n\n            if (!this.timePicker)\n                this.endDate = this.endDate.endOf('day');\n\n            this.oldEndDate = this.endDate.clone();\n\n            this.updateView();\n            this.updateCalendars();\n        },\n\n        updateView: function () {\n            this.leftCalendar.month.month(this.startDate.month()).year(this.startDate.year());\n            this.rightCalendar.month.month(this.endDate.month()).year(this.endDate.year());\n            this.updateFormInputs();\n        },\n\n        updateFormInputs: function () {\n            this.container.find('input[name=daterangepicker_start]').val(this.startDate.format(this.format));\n            this.container.find('input[name=daterangepicker_end]').val(this.endDate.format(this.format));\n\n            if (this.startDate.isSame(this.endDate) || this.startDate.isBefore(this.endDate)) {\n                this.container.find('button.applyBtn').removeAttr('disabled');\n            } else {\n                this.container.find('button.applyBtn').attr('disabled', 'disabled');\n            }\n        },\n\n        updateFromControl: function () {\n            if (!this.element.is('input')) return;\n            if (!this.element.val().length) return;\n\n            var dateString = this.element.val().split(this.separator),\n                start = null,\n                end = null;\n\n            if(dateString.length === 2) {\n                start = moment(dateString[0], this.format);\n                end = moment(dateString[1], this.format);\n            }\n\n            if (this.singleDatePicker || start === null || end === null) {\n                start = moment(this.element.val(), this.format);\n                end = start;\n            }\n\n            if (end.isBefore(start)) return;\n\n            this.oldStartDate = this.startDate.clone();\n            this.oldEndDate = this.endDate.clone();\n\n            this.startDate = start;\n            this.endDate = end;\n\n            if (!this.startDate.isSame(this.oldStartDate) || !this.endDate.isSame(this.oldEndDate))\n                this.notify();\n\n            this.updateCalendars();\n        },\n\n        notify: function () {\n            this.updateView();\n            this.cb(this.startDate, this.endDate, this.chosenLabel);\n        },\n\n        move: function () {\n            var parentOffset = { top: 0, left: 0 };\n            if (!this.parentEl.is('body')) {\n                parentOffset = {\n                    top: this.parentEl.offset().top - this.parentEl.scrollTop(),\n                    left: this.parentEl.offset().left - this.parentEl.scrollLeft()\n                };\n            }\n\n            if (this.opens == 'left') {\n                this.container.css({\n                    top: this.element.offset().top + this.element.outerHeight() - parentOffset.top,\n                    right: $(window).width() - this.element.offset().left - this.element.outerWidth() - parentOffset.left,\n                    left: 'auto'\n                });\n                if (this.container.offset().left < 0) {\n                    this.container.css({\n                        right: 'auto',\n                        left: 9\n                    });\n                }\n            } else {\n                this.container.css({\n                    top: this.element.offset().top + this.element.outerHeight() - parentOffset.top,\n                    left: this.element.offset().left - parentOffset.left,\n                    right: 'auto'\n                });\n                if (this.container.offset().left + this.container.outerWidth() > $(window).width()) {\n                    this.container.css({\n                        left: 'auto',\n                        right: 0\n                    });\n                }\n            }\n        },\n\n        toggle: function (e) {\n            if (this.element.hasClass('active')) {\n                this.hide();\n            } else {\n                this.show();\n            }\n        },\n\n        show: function (e) {\n            this.element.addClass('active');\n            this.container.show();\n            this.move();\n\n            // Create a click proxy that is private to this instance of datepicker, for unbinding\n            this._outsideClickProxy = $.proxy(function (e) { this.outsideClick(e); }, this);\n            // Bind global datepicker mousedown for hiding and\n            $(document)\n                .on('mousedown.daterangepicker', this._outsideClickProxy)\n                // also explicitly play nice with Bootstrap dropdowns, which stopPropagation when clicking them\n                .on('click.daterangepicker', '[data-toggle=dropdown]', this._outsideClickProxy)\n                // and also close when focus changes to outside the picker (eg. tabbing between controls)\n                .on('focusin.daterangepicker', this._outsideClickProxy);\n\n            this.element.trigger('show.daterangepicker', this);\n        },\n\n        outsideClick: function (e) {\n            var target = $(e.target);\n            // if the page is clicked anywhere except within the daterangerpicker/button\n            // itself then call this.hide()\n            if (\n                target.closest(this.element).length ||\n                target.closest(this.container).length ||\n                target.closest('.calendar-date').length\n                ) return;\n            this.hide();\n        },\n\n        hide: function (e) {\n            $(document)\n                .off('mousedown.daterangepicker', this._outsideClickProxy)\n                .off('click.daterangepicker', this._outsideClickProxy)\n                .off('focusin.daterangepicker', this._outsideClickProxy);\n\n            this.element.removeClass('active');\n            this.container.hide();\n\n            if (!this.startDate.isSame(this.oldStartDate) || !this.endDate.isSame(this.oldEndDate))\n                this.notify();\n\n            this.oldStartDate = this.startDate.clone();\n            this.oldEndDate = this.endDate.clone();\n\n            this.element.trigger('hide.daterangepicker', this);\n        },\n\n        enterRange: function (e) {\n            // mouse pointer has entered a range label\n            var label = e.target.innerHTML;\n            if (label == this.locale.customRangeLabel) {\n                this.updateView();\n            } else {\n                var dates = this.ranges[label];\n                this.container.find('input[name=daterangepicker_start]').val(dates[0].format(this.format));\n                this.container.find('input[name=daterangepicker_end]').val(dates[1].format(this.format));\n            }\n        },\n\n        showCalendars: function() {\n            this.container.addClass('show-calendar');\n            this.move();\n        },\n\n        hideCalendars: function() {\n            this.container.removeClass('show-calendar');\n        },\n\n        updateInputText: function() {\n            if (this.element.is('input') && !this.singleDatePicker) {\n                this.element.val(this.startDate.format(this.format) + this.separator + this.endDate.format(this.format));\n            } else if (this.element.is('input')) {\n                this.element.val(this.startDate.format(this.format));\n            }\n        },\n\n        clickRange: function (e) {\n            var label = e.target.innerHTML;\n            this.chosenLabel = label;\n            if (label == this.locale.customRangeLabel) {\n                this.showCalendars();\n            } else {\n                var dates = this.ranges[label];\n\n                this.startDate = dates[0];\n                this.endDate = dates[1];\n\n                if (!this.timePicker) {\n                    this.startDate.startOf('day');\n                    this.endDate.endOf('day');\n                }\n\n                this.leftCalendar.month.month(this.startDate.month()).year(this.startDate.year()).hour(this.startDate.hour()).minute(this.startDate.minute());\n                this.rightCalendar.month.month(this.endDate.month()).year(this.endDate.year()).hour(this.endDate.hour()).minute(this.endDate.minute());\n                this.updateCalendars();\n\n                this.updateInputText();\n\n                this.hideCalendars();\n                this.hide();\n                this.element.trigger('apply.daterangepicker', this);\n            }\n        },\n\n        clickPrev: function (e) {\n            var cal = $(e.target).parents('.calendar');\n            if (cal.hasClass('left')) {\n                this.leftCalendar.month.subtract('month', 1);\n            } else {\n                this.rightCalendar.month.subtract('month', 1);\n            }\n            this.updateCalendars();\n        },\n\n        clickNext: function (e) {\n            var cal = $(e.target).parents('.calendar');\n            if (cal.hasClass('left')) {\n                this.leftCalendar.month.add('month', 1);\n            } else {\n                this.rightCalendar.month.add('month', 1);\n            }\n            this.updateCalendars();\n        },\n\n        enterDate: function (e) {\n\n            var title = $(e.target).attr('data-title');\n            var row = title.substr(1, 1);\n            var col = title.substr(3, 1);\n            var cal = $(e.target).parents('.calendar');\n\n            if (cal.hasClass('left')) {\n                this.container.find('input[name=daterangepicker_start]').val(this.leftCalendar.calendar[row][col].format(this.format));\n            } else {\n                this.container.find('input[name=daterangepicker_end]').val(this.rightCalendar.calendar[row][col].format(this.format));\n            }\n\n        },\n\n        clickDate: function (e) {\n            var title = $(e.target).attr('data-title');\n            var row = title.substr(1, 1);\n            var col = title.substr(3, 1);\n            var cal = $(e.target).parents('.calendar');\n\n            var startDate, endDate;\n            if (cal.hasClass('left')) {\n                startDate = this.leftCalendar.calendar[row][col];\n                endDate = this.endDate;\n                if (typeof this.dateLimit === 'object') {\n                    var maxDate = moment(startDate).add(this.dateLimit).startOf('day');\n                    if (endDate.isAfter(maxDate)) {\n                        endDate = maxDate;\n                    }\n                }\n            } else {\n                startDate = this.startDate;\n                endDate = this.rightCalendar.calendar[row][col];\n                if (typeof this.dateLimit === 'object') {\n                    var minDate = moment(endDate).subtract(this.dateLimit).startOf('day');\n                    if (startDate.isBefore(minDate)) {\n                        startDate = minDate;\n                    }\n                }\n            }\n\n            if (this.singleDatePicker && cal.hasClass('left')) {\n                endDate = startDate.clone();\n            } else if (this.singleDatePicker && cal.hasClass('right')) {\n                startDate = endDate.clone();\n            }\n\n            cal.find('td').removeClass('active');\n\n            if (startDate.isSame(endDate) || startDate.isBefore(endDate)) {\n                $(e.target).addClass('active');\n                this.startDate = startDate;\n                this.endDate = endDate;\n                this.chosenLabel = this.locale.customRangeLabel;\n            } else if (startDate.isAfter(endDate)) {\n                $(e.target).addClass('active');\n                var difference = this.endDate.diff(this.startDate);\n                this.startDate = startDate;\n                this.endDate = moment(startDate).add('ms', difference);\n                this.chosenLabel = this.locale.customRangeLabel;\n            }\n\n            this.leftCalendar.month.month(this.startDate.month()).year(this.startDate.year());\n            this.rightCalendar.month.month(this.endDate.month()).year(this.endDate.year());\n            this.updateCalendars();\n\n            if (!this.timePicker)\n                endDate.endOf('day');\n\n            if (this.singleDatePicker)\n                this.clickApply();\n        },\n\n        clickApply: function (e) {\n            this.updateInputText();\n            this.hide();\n            this.element.trigger('apply.daterangepicker', this);\n        },\n\n        clickCancel: function (e) {\n            this.startDate = this.oldStartDate;\n            this.endDate = this.oldEndDate;\n            this.chosenLabel = this.oldChosenLabel;\n            this.updateView();\n            this.updateCalendars();\n            this.hide();\n            this.element.trigger('cancel.daterangepicker', this);\n        },\n\n        updateMonthYear: function (e) {\n            var isLeft = $(e.target).closest('.calendar').hasClass('left'),\n                leftOrRight = isLeft ? 'left' : 'right',\n                cal = this.container.find('.calendar.'+leftOrRight);\n\n            // Month must be Number for new moment versions\n            var month = parseInt(cal.find('.monthselect').val(), 10);\n            var year = cal.find('.yearselect').val();\n\n            this[leftOrRight+'Calendar'].month.month(month).year(year);\n            this.updateCalendars();\n        },\n\n        updateTime: function(e) {\n\n            var cal = $(e.target).closest('.calendar'),\n                isLeft = cal.hasClass('left');\n\n            var hour = parseInt(cal.find('.hourselect').val(), 10);\n            var minute = parseInt(cal.find('.minuteselect').val(), 10);\n\n            if (this.timePicker12Hour) {\n                var ampm = cal.find('.ampmselect').val();\n                if (ampm === 'PM' && hour < 12)\n                    hour += 12;\n                if (ampm === 'AM' && hour === 12)\n                    hour = 0;\n            }\n\n            if (isLeft) {\n                var start = this.startDate.clone();\n                start.hour(hour);\n                start.minute(minute);\n                this.startDate = start;\n                this.leftCalendar.month.hour(hour).minute(minute);\n            } else {\n                var end = this.endDate.clone();\n                end.hour(hour);\n                end.minute(minute);\n                this.endDate = end;\n                this.rightCalendar.month.hour(hour).minute(minute);\n            }\n\n            this.updateCalendars();\n        },\n\n        updateCalendars: function () {\n            this.leftCalendar.calendar = this.buildCalendar(this.leftCalendar.month.month(), this.leftCalendar.month.year(), this.leftCalendar.month.hour(), this.leftCalendar.month.minute(), 'left');\n            this.rightCalendar.calendar = this.buildCalendar(this.rightCalendar.month.month(), this.rightCalendar.month.year(), this.rightCalendar.month.hour(), this.rightCalendar.month.minute(), 'right');\n            this.container.find('.calendar.left').empty().html(this.renderCalendar(this.leftCalendar.calendar, this.startDate, this.minDate, this.maxDate));\n            this.container.find('.calendar.right').empty().html(this.renderCalendar(this.rightCalendar.calendar, this.endDate, this.startDate, this.maxDate));\n\n            this.container.find('.ranges li').removeClass('active');\n            var customRange = true;\n            var i = 0;\n            for (var range in this.ranges) {\n                if (this.timePicker) {\n                    if (this.startDate.isSame(this.ranges[range][0]) && this.endDate.isSame(this.ranges[range][1])) {\n                        customRange = false;\n                        this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')')\n                            .addClass('active').html();\n                    }\n                } else {\n                    //ignore times when comparing dates if time picker is not enabled\n                    if (this.startDate.format('YYYY-MM-DD') == this.ranges[range][0].format('YYYY-MM-DD') && this.endDate.format('YYYY-MM-DD') == this.ranges[range][1].format('YYYY-MM-DD')) {\n                        customRange = false;\n                        this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')')\n                            .addClass('active').html();\n                    }\n                }\n                i++;\n            }\n            if (customRange) {\n                this.chosenLabel = this.container.find('.ranges li:last')\n                    .addClass('active').html();\n            }\n        },\n\n        buildCalendar: function (month, year, hour, minute, side) {\n            var firstDay = moment([year, month, 1]);\n            var lastMonth = moment(firstDay).subtract('month', 1).month();\n            var lastYear = moment(firstDay).subtract('month', 1).year();\n\n            var daysInLastMonth = moment([lastYear, lastMonth]).daysInMonth();\n\n            var dayOfWeek = firstDay.day();\n\n            var i;\n\n            //initialize a 6 rows x 7 columns array for the calendar\n            var calendar = [];\n            for (i = 0; i < 6; i++) {\n                calendar[i] = [];\n            }\n\n            //populate the calendar with date objects\n            var startDay = daysInLastMonth - dayOfWeek + this.locale.firstDay + 1;\n            if (startDay > daysInLastMonth)\n                startDay -= 7;\n\n            if (dayOfWeek == this.locale.firstDay)\n                startDay = daysInLastMonth - 6;\n\n            var curDate = moment([lastYear, lastMonth, startDay, 12, minute]);\n            var col, row;\n            for (i = 0, col = 0, row = 0; i < 42; i++, col++, curDate = moment(curDate).add('hour', 24)) {\n                if (i > 0 && col % 7 === 0) {\n                    col = 0;\n                    row++;\n                }\n                calendar[row][col] = curDate.clone().hour(hour);\n                curDate.hour(12);\n            }\n\n            return calendar;\n        },\n\n        renderDropdowns: function (selected, minDate, maxDate) {\n            var currentMonth = selected.month();\n            var monthHtml = '<select class=\"monthselect\">';\n            var inMinYear = false;\n            var inMaxYear = false;\n\n            for (var m = 0; m < 12; m++) {\n                if ((!inMinYear || m >= minDate.month()) && (!inMaxYear || m <= maxDate.month())) {\n                    monthHtml += \"<option value='\" + m + \"'\" +\n                        (m === currentMonth ? \" selected='selected'\" : \"\") +\n                        \">\" + this.locale.monthNames[m] + \"</option>\";\n                }\n            }\n            monthHtml += \"</select>\";\n\n            var currentYear = selected.year();\n            var maxYear = (maxDate && maxDate.year()) || (currentYear + 5);\n            var minYear = (minDate && minDate.year()) || (currentYear - 50);\n            var yearHtml = '<select class=\"yearselect\">';\n\n            for (var y = minYear; y <= maxYear; y++) {\n                yearHtml += '<option value=\"' + y + '\"' +\n                    (y === currentYear ? ' selected=\"selected\"' : '') +\n                    '>' + y + '</option>';\n            }\n\n            yearHtml += '</select>';\n\n            return monthHtml + yearHtml;\n        },\n\n        renderCalendar: function (calendar, selected, minDate, maxDate) {\n\n            var html = '<div class=\"calendar-date\">';\n            html += '<table class=\"table-condensed\">';\n            html += '<thead>';\n            html += '<tr>';\n\n            // add empty cell for week number\n            if (this.showWeekNumbers)\n                html += '<th></th>';\n\n            if (!minDate || minDate.isBefore(calendar[1][1])) {\n                html += '<th class=\"prev available\"><i class=\"fa fa-arrow-left icon-arrow-left glyphicon glyphicon-arrow-left\"></i></th>';\n            } else {\n                html += '<th></th>';\n            }\n\n            var dateHtml = this.locale.monthNames[calendar[1][1].month()] + calendar[1][1].format(\" YYYY\");\n\n            if (this.showDropdowns) {\n                dateHtml = this.renderDropdowns(calendar[1][1], minDate, maxDate);\n            }\n\n            html += '<th colspan=\"5\" class=\"month\">' + dateHtml + '</th>';\n            if (!maxDate || maxDate.isAfter(calendar[1][1])) {\n                html += '<th class=\"next available\"><i class=\"fa fa-arrow-right icon-arrow-right glyphicon glyphicon-arrow-right\"></i></th>';\n            } else {\n                html += '<th></th>';\n            }\n\n            html += '</tr>';\n            html += '<tr>';\n\n            // add week number label\n            if (this.showWeekNumbers)\n                html += '<th class=\"week\">' + this.locale.weekLabel + '</th>';\n\n            $.each(this.locale.daysOfWeek, function (index, dayOfWeek) {\n                html += '<th>' + dayOfWeek + '</th>';\n            });\n\n            html += '</tr>';\n            html += '</thead>';\n            html += '<tbody>';\n\n            for (var row = 0; row < 6; row++) {\n                html += '<tr>';\n\n                // add week number\n                if (this.showWeekNumbers)\n                    html += '<td class=\"week\">' + calendar[row][0].week() + '</td>';\n\n                for (var col = 0; col < 7; col++) {\n                    var cname = 'available ';\n                    cname += (calendar[row][col].month() == calendar[1][1].month()) ? '' : 'off';\n\n                    if ((minDate && calendar[row][col].isBefore(minDate, 'day')) || (maxDate && calendar[row][col].isAfter(maxDate, 'day'))) {\n                        cname = ' off disabled ';\n                    } else if (calendar[row][col].format('YYYY-MM-DD') == selected.format('YYYY-MM-DD')) {\n                        cname += ' active ';\n                        if (calendar[row][col].format('YYYY-MM-DD') == this.startDate.format('YYYY-MM-DD')) {\n                            cname += ' start-date ';\n                        }\n                        if (calendar[row][col].format('YYYY-MM-DD') == this.endDate.format('YYYY-MM-DD')) {\n                            cname += ' end-date ';\n                        }\n                    } else if (calendar[row][col] >= this.startDate && calendar[row][col] <= this.endDate) {\n                        cname += ' in-range ';\n                        if (calendar[row][col].isSame(this.startDate)) { cname += ' start-date '; }\n                        if (calendar[row][col].isSame(this.endDate)) { cname += ' end-date '; }\n                    }\n\n                    var title = 'r' + row + 'c' + col;\n                    html += '<td class=\"' + cname.replace(/\\s+/g, ' ').replace(/^\\s?(.*?)\\s?$/, '$1') + '\" data-title=\"' + title + '\">' + calendar[row][col].date() + '</td>';\n                }\n                html += '</tr>';\n            }\n\n            html += '</tbody>';\n            html += '</table>';\n            html += '</div>';\n\n            var i;\n            if (this.timePicker) {\n\n                html += '<div class=\"calendar-time\">';\n                html += '<select class=\"hourselect\">';\n                var start = 0;\n                var end = 23;\n                var selected_hour = selected.hour();\n                if (this.timePicker12Hour) {\n                    start = 1;\n                    end = 12;\n                    if (selected_hour >= 12)\n                        selected_hour -= 12;\n                    if (selected_hour === 0)\n                        selected_hour = 12;\n                }\n\n                for (i = start; i <= end; i++) {\n                    if (i == selected_hour) {\n                        html += '<option value=\"' + i + '\" selected=\"selected\">' + i + '</option>';\n                    } else {\n                        html += '<option value=\"' + i + '\">' + i + '</option>';\n                    }\n                }\n\n                html += '</select> : ';\n\n                html += '<select class=\"minuteselect\">';\n\n                for (i = 0; i < 60; i += this.timePickerIncrement) {\n                    var num = i;\n                    if (num < 10)\n                        num = '0' + num;\n                    if (i == selected.minute()) {\n                        html += '<option value=\"' + i + '\" selected=\"selected\">' + num + '</option>';\n                    } else {\n                        html += '<option value=\"' + i + '\">' + num + '</option>';\n                    }\n                }\n\n                html += '</select> ';\n\n                if (this.timePicker12Hour) {\n                    html += '<select class=\"ampmselect\">';\n                    if (selected.hour() >= 12) {\n                        html += '<option value=\"AM\">AM</option><option value=\"PM\" selected=\"selected\">PM</option>';\n                    } else {\n                        html += '<option value=\"AM\" selected=\"selected\">AM</option><option value=\"PM\">PM</option>';\n                    }\n                    html += '</select>';\n                }\n\n                html += '</div>';\n\n            }\n\n            return html;\n\n        },\n\n        remove: function() {\n\n            this.container.remove();\n            this.element.off('.daterangepicker');\n            this.element.removeData('daterangepicker');\n\n        }\n\n    };\n\n    $.fn.daterangepicker = function (options, cb) {\n        this.each(function () {\n            var el = $(this);\n            if (el.data('daterangepicker'))\n                el.data('daterangepicker').remove();\n            el.data('daterangepicker', new DateRangePicker(el, options, cb));\n        });\n        return this;\n    };\n\n}(window.jQuery, window.moment);"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/bootstrap_3.1.1/css/bootstrap-theme.css",
    "content": "/*!\n * Bootstrap v3.1.1 (http://getbootstrap.com)\n * Copyright 2011-2014 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, .2);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);\n}\n.btn-default:active,\n.btn-primary:active,\n.btn-success:active,\n.btn-info:active,\n.btn-warning:active,\n.btn-danger:active,\n.btn-default.active,\n.btn-primary.active,\n.btn-success.active,\n.btn-info.active,\n.btn-warning.active,\n.btn-danger.active {\n  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);\n          box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);\n}\n.btn:active,\n.btn.active {\n  background-image: none;\n}\n.btn-default {\n  text-shadow: 0 1px 0 #fff;\n  background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%);\n  background-image:         linear-gradient(to bottom, #fff 0%, #e0e0e0 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n  background-repeat: repeat-x;\n  border-color: #dbdbdb;\n  border-color: #ccc;\n}\n.btn-default:hover,\n.btn-default:focus {\n  background-color: #e0e0e0;\n  background-position: 0 -15px;\n}\n.btn-default:active,\n.btn-default.active {\n  background-color: #e0e0e0;\n  border-color: #dbdbdb;\n}\n.btn-primary {\n  background-image: -webkit-linear-gradient(top, #428bca 0%, #2d6ca2 100%);\n  background-image:         linear-gradient(to bottom, #428bca 0%, #2d6ca2 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n  background-repeat: repeat-x;\n  border-color: #2b669a;\n}\n.btn-primary:hover,\n.btn-primary:focus {\n  background-color: #2d6ca2;\n  background-position: 0 -15px;\n}\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #2d6ca2;\n  border-color: #2b669a;\n}\n.btn-success {\n  background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);\n  background-image:         linear-gradient(to bottom, #5cb85c 0%, #419641 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n  background-repeat: repeat-x;\n  border-color: #3e8f3e;\n}\n.btn-success:hover,\n.btn-success:focus {\n  background-color: #419641;\n  background-position: 0 -15px;\n}\n.btn-success:active,\n.btn-success.active {\n  background-color: #419641;\n  border-color: #3e8f3e;\n}\n.btn-info {\n  background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);\n  background-image:         linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n  background-repeat: repeat-x;\n  border-color: #28a4c9;\n}\n.btn-info:hover,\n.btn-info:focus {\n  background-color: #2aabd2;\n  background-position: 0 -15px;\n}\n.btn-info:active,\n.btn-info.active {\n  background-color: #2aabd2;\n  border-color: #28a4c9;\n}\n.btn-warning {\n  background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);\n  background-image:         linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n  background-repeat: repeat-x;\n  border-color: #e38d13;\n}\n.btn-warning:hover,\n.btn-warning:focus {\n  background-color: #eb9316;\n  background-position: 0 -15px;\n}\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #eb9316;\n  border-color: #e38d13;\n}\n.btn-danger {\n  background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);\n  background-image:         linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n  background-repeat: repeat-x;\n  border-color: #b92c28;\n}\n.btn-danger:hover,\n.btn-danger:focus {\n  background-color: #c12e2a;\n  background-position: 0 -15px;\n}\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #c12e2a;\n  border-color: #b92c28;\n}\n.thumbnail,\n.img-thumbnail {\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, .075);\n}\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n  background-color: #e8e8e8;\n  background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n  background-image:         linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);\n  background-repeat: repeat-x;\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n  background-color: #357ebd;\n  background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%);\n  background-image:         linear-gradient(to bottom, #428bca 0%, #357ebd 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);\n  background-repeat: repeat-x;\n}\n.navbar-default {\n  background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%);\n  background-image:         linear-gradient(to bottom, #fff 0%, #f8f8f8 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n  background-repeat: repeat-x;\n  border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);\n}\n.navbar-default .navbar-nav > .active > a {\n  background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f3f3f3 100%);\n  background-image:         linear-gradient(to bottom, #ebebeb 0%, #f3f3f3 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0);\n  background-repeat: repeat-x;\n  -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);\n          box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);\n}\n.navbar-brand,\n.navbar-nav > li > a {\n  text-shadow: 0 1px 0 rgba(255, 255, 255, .25);\n}\n.navbar-inverse {\n  background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%);\n  background-image:         linear-gradient(to bottom, #3c3c3c 0%, #222 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n  background-repeat: repeat-x;\n}\n.navbar-inverse .navbar-nav > .active > a {\n  background-image: -webkit-linear-gradient(top, #222 0%, #282828 100%);\n  background-image:         linear-gradient(to bottom, #222 0%, #282828 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0);\n  background-repeat: repeat-x;\n  -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);\n          box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);\n}\n.navbar-inverse .navbar-brand,\n.navbar-inverse .navbar-nav > li > a {\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, .25);\n}\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  border-radius: 0;\n}\n.alert {\n  text-shadow: 0 1px 0 rgba(255, 255, 255, .2);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);\n}\n.alert-success {\n  background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);\n  background-image:         linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);\n  background-repeat: repeat-x;\n  border-color: #b2dba1;\n}\n.alert-info {\n  background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);\n  background-image:         linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);\n  background-repeat: repeat-x;\n  border-color: #9acfea;\n}\n.alert-warning {\n  background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);\n  background-image:         linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);\n  background-repeat: repeat-x;\n  border-color: #f5e79e;\n}\n.alert-danger {\n  background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);\n  background-image:         linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);\n  background-repeat: repeat-x;\n  border-color: #dca7a7;\n}\n.progress {\n  background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);\n  background-image:         linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);\n  background-repeat: repeat-x;\n}\n.progress-bar {\n  background-image: -webkit-linear-gradient(top, #428bca 0%, #3071a9 100%);\n  background-image:         linear-gradient(to bottom, #428bca 0%, #3071a9 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0);\n  background-repeat: repeat-x;\n}\n.progress-bar-success {\n  background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);\n  background-image:         linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);\n  background-repeat: repeat-x;\n}\n.progress-bar-info {\n  background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);\n  background-image:         linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);\n  background-repeat: repeat-x;\n}\n.progress-bar-warning {\n  background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);\n  background-image:         linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);\n  background-repeat: repeat-x;\n}\n.progress-bar-danger {\n  background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);\n  background-image:         linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);\n  background-repeat: repeat-x;\n}\n.list-group {\n  border-radius: 4px;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, .075);\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n  text-shadow: 0 -1px 0 #3071a9;\n  background-image: -webkit-linear-gradient(top, #428bca 0%, #3278b3 100%);\n  background-image:         linear-gradient(to bottom, #428bca 0%, #3278b3 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0);\n  background-repeat: repeat-x;\n  border-color: #3278b3;\n}\n.panel {\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, .05);\n}\n.panel-default > .panel-heading {\n  background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n  background-image:         linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);\n  background-repeat: repeat-x;\n}\n.panel-primary > .panel-heading {\n  background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%);\n  background-image:         linear-gradient(to bottom, #428bca 0%, #357ebd 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);\n  background-repeat: repeat-x;\n}\n.panel-success > .panel-heading {\n  background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);\n  background-image:         linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);\n  background-repeat: repeat-x;\n}\n.panel-info > .panel-heading {\n  background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);\n  background-image:         linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);\n  background-repeat: repeat-x;\n}\n.panel-warning > .panel-heading {\n  background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);\n  background-image:         linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);\n  background-repeat: repeat-x;\n}\n.panel-danger > .panel-heading {\n  background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);\n  background-image:         linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);\n  background-repeat: repeat-x;\n}\n.well {\n  background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);\n  background-image:         linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);\n  background-repeat: repeat-x;\n  border-color: #dcdcdc;\n  -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);\n          box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);\n}\n/*# sourceMappingURL=bootstrap-theme.css.map */\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/bootstrap_3.1.1/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v3.1.1 (http://getbootstrap.com)\n * Copyright 2011-2014 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n\n/*! normalize.css v3.0.0 | MIT License | git.io/normalize */\nhtml {\n  font-family: sans-serif;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\nbody {\n  margin: 0;\n}\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nnav,\nsection,\nsummary {\n  display: block;\n}\naudio,\ncanvas,\nprogress,\nvideo {\n  display: inline-block;\n  vertical-align: baseline;\n}\naudio:not([controls]) {\n  display: none;\n  height: 0;\n}\n[hidden],\ntemplate {\n  display: none;\n}\na {\n  background: transparent;\n}\na:active,\na:hover {\n  outline: 0;\n}\nabbr[title] {\n  border-bottom: 1px dotted;\n}\nb,\nstrong {\n  font-weight: bold;\n}\ndfn {\n  font-style: italic;\n}\nh1 {\n  margin: .67em 0;\n  font-size: 2em;\n}\nmark {\n  color: #000;\n  background: #ff0;\n}\nsmall {\n  font-size: 80%;\n}\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\nsup {\n  top: -.5em;\n}\nsub {\n  bottom: -.25em;\n}\nimg {\n  border: 0;\n}\nsvg:not(:root) {\n  overflow: hidden;\n}\nfigure {\n  margin: 1em 40px;\n}\nhr {\n  height: 0;\n  -moz-box-sizing: content-box;\n       box-sizing: content-box;\n}\npre {\n  overflow: auto;\n}\ncode,\nkbd,\npre,\nsamp {\n  font-family: monospace, monospace;\n  font-size: 1em;\n}\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n  margin: 0;\n  font: inherit;\n  color: inherit;\n}\nbutton {\n  overflow: visible;\n}\nbutton,\nselect {\n  text-transform: none;\n}\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  -webkit-appearance: button;\n  cursor: pointer;\n}\nbutton[disabled],\nhtml input[disabled] {\n  cursor: default;\n}\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\ninput {\n  line-height: normal;\n}\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n  box-sizing: border-box;\n  padding: 0;\n}\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n  height: auto;\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}\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n  -webkit-appearance: none;\n}\nfieldset {\n  padding: .35em .625em .75em;\n  margin: 0 2px;\n  border: 1px solid #c0c0c0;\n}\nlegend {\n  padding: 0;\n  border: 0;\n}\ntextarea {\n  overflow: auto;\n}\noptgroup {\n  font-weight: bold;\n}\ntable {\n  border-spacing: 0;\n  border-collapse: collapse;\n}\ntd,\nth {\n  padding: 0;\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\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  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  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n*:before,\n*:after {\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\nhtml {\n  font-size: 62.5%;\n\n  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\nbody {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 1.42857143;\n  color: #333;\n  background-color: #fff;\n}\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: inherit;\n  font-size: inherit;\n  line-height: inherit;\n}\na {\n  color: #428bca;\n  text-decoration: none;\n}\na:hover,\na:focus {\n  color: #2a6496;\n  text-decoration: underline;\n}\na:focus {\n  outline: thin dotted;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\nfigure {\n  margin: 0;\n}\nimg {\n  vertical-align: middle;\n}\n.img-responsive,\n.thumbnail > img,\n.thumbnail a > img,\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n  display: block;\n  max-width: 100%;\n  height: auto;\n}\n.img-rounded {\n  border-radius: 6px;\n}\n.img-thumbnail {\n  display: inline-block;\n  max-width: 100%;\n  height: auto;\n  padding: 4px;\n  line-height: 1.42857143;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  border-radius: 4px;\n  -webkit-transition: all .2s ease-in-out;\n          transition: all .2s ease-in-out;\n}\n.img-circle {\n  border-radius: 50%;\n}\nhr {\n  margin-top: 20px;\n  margin-bottom: 20px;\n  border: 0;\n  border-top: 1px solid #eee;\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}\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\n.h1,\n.h2,\n.h3,\n.h4,\n.h5,\n.h6 {\n  font-family: inherit;\n  font-weight: 500;\n  line-height: 1.1;\n  color: inherit;\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: #999;\n}\nh1,\n.h1,\nh2,\n.h2,\nh3,\n.h3 {\n  margin-top: 20px;\n  margin-bottom: 10px;\n}\nh1 small,\n.h1 small,\nh2 small,\n.h2 small,\nh3 small,\n.h3 small,\nh1 .small,\n.h1 .small,\nh2 .small,\n.h2 .small,\nh3 .small,\n.h3 .small {\n  font-size: 65%;\n}\nh4,\n.h4,\nh5,\n.h5,\nh6,\n.h6 {\n  margin-top: 10px;\n  margin-bottom: 10px;\n}\nh4 small,\n.h4 small,\nh5 small,\n.h5 small,\nh6 small,\n.h6 small,\nh4 .small,\n.h4 .small,\nh5 .small,\n.h5 .small,\nh6 .small,\n.h6 .small {\n  font-size: 75%;\n}\nh1,\n.h1 {\n  font-size: 36px;\n}\nh2,\n.h2 {\n  font-size: 30px;\n}\nh3,\n.h3 {\n  font-size: 24px;\n}\nh4,\n.h4 {\n  font-size: 18px;\n}\nh5,\n.h5 {\n  font-size: 14px;\n}\nh6,\n.h6 {\n  font-size: 12px;\n}\np {\n  margin: 0 0 10px;\n}\n.lead {\n  margin-bottom: 20px;\n  font-size: 16px;\n  font-weight: 200;\n  line-height: 1.4;\n}\n@media (min-width: 768px) {\n  .lead {\n    font-size: 21px;\n  }\n}\nsmall,\n.small {\n  font-size: 85%;\n}\ncite {\n  font-style: normal;\n}\n.text-left {\n  text-align: left;\n}\n.text-right {\n  text-align: right;\n}\n.text-center {\n  text-align: center;\n}\n.text-justify {\n  text-align: justify;\n}\n.text-muted {\n  color: #999;\n}\n.text-primary {\n  color: #428bca;\n}\na.text-primary:hover {\n  color: #3071a9;\n}\n.text-success {\n  color: #3c763d;\n}\na.text-success:hover {\n  color: #2b542c;\n}\n.text-info {\n  color: #31708f;\n}\na.text-info:hover {\n  color: #245269;\n}\n.text-warning {\n  color: #8a6d3b;\n}\na.text-warning:hover {\n  color: #66512c;\n}\n.text-danger {\n  color: #a94442;\n}\na.text-danger:hover {\n  color: #843534;\n}\n.bg-primary {\n  color: #fff;\n  background-color: #428bca;\n}\na.bg-primary:hover {\n  background-color: #3071a9;\n}\n.bg-success {\n  background-color: #dff0d8;\n}\na.bg-success:hover {\n  background-color: #c1e2b3;\n}\n.bg-info {\n  background-color: #d9edf7;\n}\na.bg-info:hover {\n  background-color: #afd9ee;\n}\n.bg-warning {\n  background-color: #fcf8e3;\n}\na.bg-warning:hover {\n  background-color: #f7ecb5;\n}\n.bg-danger {\n  background-color: #f2dede;\n}\na.bg-danger:hover {\n  background-color: #e4b9b9;\n}\n.page-header {\n  padding-bottom: 9px;\n  margin: 40px 0 20px;\n  border-bottom: 1px solid #eee;\n}\nul,\nol {\n  margin-top: 0;\n  margin-bottom: 10px;\n}\nul ul,\nol ul,\nul ol,\nol ol {\n  margin-bottom: 0;\n}\n.list-unstyled {\n  padding-left: 0;\n  list-style: none;\n}\n.list-inline {\n  padding-left: 0;\n  margin-left: -5px;\n  list-style: none;\n}\n.list-inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\ndl {\n  margin-top: 0;\n  margin-bottom: 20px;\n}\ndt,\ndd {\n  line-height: 1.42857143;\n}\ndt {\n  font-weight: bold;\n}\ndd {\n  margin-left: 0;\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}\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999;\n}\n.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\nblockquote {\n  padding: 10px 20px;\n  margin: 0 0 20px;\n  font-size: 17.5px;\n  border-left: 5px solid #eee;\n}\nblockquote p:last-child,\nblockquote ul:last-child,\nblockquote ol:last-child {\n  margin-bottom: 0;\n}\nblockquote footer,\nblockquote small,\nblockquote .small {\n  display: block;\n  font-size: 80%;\n  line-height: 1.42857143;\n  color: #999;\n}\nblockquote footer:before,\nblockquote small:before,\nblockquote .small:before {\n  content: '\\2014 \\00A0';\n}\n.blockquote-reverse,\nblockquote.pull-right {\n  padding-right: 15px;\n  padding-left: 0;\n  text-align: right;\n  border-right: 5px solid #eee;\n  border-left: 0;\n}\n.blockquote-reverse footer:before,\nblockquote.pull-right footer:before,\n.blockquote-reverse small:before,\nblockquote.pull-right small:before,\n.blockquote-reverse .small:before,\nblockquote.pull-right .small:before {\n  content: '';\n}\n.blockquote-reverse footer:after,\nblockquote.pull-right footer:after,\n.blockquote-reverse small:after,\nblockquote.pull-right small:after,\n.blockquote-reverse .small:after,\nblockquote.pull-right .small:after {\n  content: '\\00A0 \\2014';\n}\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\naddress {\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 1.42857143;\n}\ncode,\nkbd,\npre,\nsamp {\n  font-family: Menlo, Monaco, Consolas, \"Courier New\", monospace;\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}\nkbd {\n  padding: 2px 4px;\n  font-size: 90%;\n  color: #fff;\n  background-color: #333;\n  border-radius: 3px;\n  box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25);\n}\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 1.42857143;\n  color: #333;\n  word-break: break-all;\n  word-wrap: break-word;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border-radius: 4px;\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.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n.container {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-right: auto;\n  margin-left: auto;\n}\n@media (min-width: 768px) {\n  .container {\n    width: 750px;\n  }\n}\n@media (min-width: 992px) {\n  .container {\n    width: 970px;\n  }\n}\n@media (min-width: 1200px) {\n  .container {\n    width: 1170px;\n  }\n}\n.container-fluid {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-right: auto;\n  margin-left: auto;\n}\n.row {\n  margin-right: -15px;\n  margin-left: -15px;\n}\n.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 {\n  position: relative;\n  min-height: 1px;\n  padding-right: 15px;\n  padding-left: 15px;\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 {\n  float: left;\n}\n.col-xs-12 {\n  width: 100%;\n}\n.col-xs-11 {\n  width: 91.66666667%;\n}\n.col-xs-10 {\n  width: 83.33333333%;\n}\n.col-xs-9 {\n  width: 75%;\n}\n.col-xs-8 {\n  width: 66.66666667%;\n}\n.col-xs-7 {\n  width: 58.33333333%;\n}\n.col-xs-6 {\n  width: 50%;\n}\n.col-xs-5 {\n  width: 41.66666667%;\n}\n.col-xs-4 {\n  width: 33.33333333%;\n}\n.col-xs-3 {\n  width: 25%;\n}\n.col-xs-2 {\n  width: 16.66666667%;\n}\n.col-xs-1 {\n  width: 8.33333333%;\n}\n.col-xs-pull-12 {\n  right: 100%;\n}\n.col-xs-pull-11 {\n  right: 91.66666667%;\n}\n.col-xs-pull-10 {\n  right: 83.33333333%;\n}\n.col-xs-pull-9 {\n  right: 75%;\n}\n.col-xs-pull-8 {\n  right: 66.66666667%;\n}\n.col-xs-pull-7 {\n  right: 58.33333333%;\n}\n.col-xs-pull-6 {\n  right: 50%;\n}\n.col-xs-pull-5 {\n  right: 41.66666667%;\n}\n.col-xs-pull-4 {\n  right: 33.33333333%;\n}\n.col-xs-pull-3 {\n  right: 25%;\n}\n.col-xs-pull-2 {\n  right: 16.66666667%;\n}\n.col-xs-pull-1 {\n  right: 8.33333333%;\n}\n.col-xs-pull-0 {\n  right: 0;\n}\n.col-xs-push-12 {\n  left: 100%;\n}\n.col-xs-push-11 {\n  left: 91.66666667%;\n}\n.col-xs-push-10 {\n  left: 83.33333333%;\n}\n.col-xs-push-9 {\n  left: 75%;\n}\n.col-xs-push-8 {\n  left: 66.66666667%;\n}\n.col-xs-push-7 {\n  left: 58.33333333%;\n}\n.col-xs-push-6 {\n  left: 50%;\n}\n.col-xs-push-5 {\n  left: 41.66666667%;\n}\n.col-xs-push-4 {\n  left: 33.33333333%;\n}\n.col-xs-push-3 {\n  left: 25%;\n}\n.col-xs-push-2 {\n  left: 16.66666667%;\n}\n.col-xs-push-1 {\n  left: 8.33333333%;\n}\n.col-xs-push-0 {\n  left: 0;\n}\n.col-xs-offset-12 {\n  margin-left: 100%;\n}\n.col-xs-offset-11 {\n  margin-left: 91.66666667%;\n}\n.col-xs-offset-10 {\n  margin-left: 83.33333333%;\n}\n.col-xs-offset-9 {\n  margin-left: 75%;\n}\n.col-xs-offset-8 {\n  margin-left: 66.66666667%;\n}\n.col-xs-offset-7 {\n  margin-left: 58.33333333%;\n}\n.col-xs-offset-6 {\n  margin-left: 50%;\n}\n.col-xs-offset-5 {\n  margin-left: 41.66666667%;\n}\n.col-xs-offset-4 {\n  margin-left: 33.33333333%;\n}\n.col-xs-offset-3 {\n  margin-left: 25%;\n}\n.col-xs-offset-2 {\n  margin-left: 16.66666667%;\n}\n.col-xs-offset-1 {\n  margin-left: 8.33333333%;\n}\n.col-xs-offset-0 {\n  margin-left: 0;\n}\n@media (min-width: 768px) {\n  .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 {\n    float: left;\n  }\n  .col-sm-12 {\n    width: 100%;\n  }\n  .col-sm-11 {\n    width: 91.66666667%;\n  }\n  .col-sm-10 {\n    width: 83.33333333%;\n  }\n  .col-sm-9 {\n    width: 75%;\n  }\n  .col-sm-8 {\n    width: 66.66666667%;\n  }\n  .col-sm-7 {\n    width: 58.33333333%;\n  }\n  .col-sm-6 {\n    width: 50%;\n  }\n  .col-sm-5 {\n    width: 41.66666667%;\n  }\n  .col-sm-4 {\n    width: 33.33333333%;\n  }\n  .col-sm-3 {\n    width: 25%;\n  }\n  .col-sm-2 {\n    width: 16.66666667%;\n  }\n  .col-sm-1 {\n    width: 8.33333333%;\n  }\n  .col-sm-pull-12 {\n    right: 100%;\n  }\n  .col-sm-pull-11 {\n    right: 91.66666667%;\n  }\n  .col-sm-pull-10 {\n    right: 83.33333333%;\n  }\n  .col-sm-pull-9 {\n    right: 75%;\n  }\n  .col-sm-pull-8 {\n    right: 66.66666667%;\n  }\n  .col-sm-pull-7 {\n    right: 58.33333333%;\n  }\n  .col-sm-pull-6 {\n    right: 50%;\n  }\n  .col-sm-pull-5 {\n    right: 41.66666667%;\n  }\n  .col-sm-pull-4 {\n    right: 33.33333333%;\n  }\n  .col-sm-pull-3 {\n    right: 25%;\n  }\n  .col-sm-pull-2 {\n    right: 16.66666667%;\n  }\n  .col-sm-pull-1 {\n    right: 8.33333333%;\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.66666667%;\n  }\n  .col-sm-push-10 {\n    left: 83.33333333%;\n  }\n  .col-sm-push-9 {\n    left: 75%;\n  }\n  .col-sm-push-8 {\n    left: 66.66666667%;\n  }\n  .col-sm-push-7 {\n    left: 58.33333333%;\n  }\n  .col-sm-push-6 {\n    left: 50%;\n  }\n  .col-sm-push-5 {\n    left: 41.66666667%;\n  }\n  .col-sm-push-4 {\n    left: 33.33333333%;\n  }\n  .col-sm-push-3 {\n    left: 25%;\n  }\n  .col-sm-push-2 {\n    left: 16.66666667%;\n  }\n  .col-sm-push-1 {\n    left: 8.33333333%;\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.66666667%;\n  }\n  .col-sm-offset-10 {\n    margin-left: 83.33333333%;\n  }\n  .col-sm-offset-9 {\n    margin-left: 75%;\n  }\n  .col-sm-offset-8 {\n    margin-left: 66.66666667%;\n  }\n  .col-sm-offset-7 {\n    margin-left: 58.33333333%;\n  }\n  .col-sm-offset-6 {\n    margin-left: 50%;\n  }\n  .col-sm-offset-5 {\n    margin-left: 41.66666667%;\n  }\n  .col-sm-offset-4 {\n    margin-left: 33.33333333%;\n  }\n  .col-sm-offset-3 {\n    margin-left: 25%;\n  }\n  .col-sm-offset-2 {\n    margin-left: 16.66666667%;\n  }\n  .col-sm-offset-1 {\n    margin-left: 8.33333333%;\n  }\n  .col-sm-offset-0 {\n    margin-left: 0;\n  }\n}\n@media (min-width: 992px) {\n  .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 {\n    float: left;\n  }\n  .col-md-12 {\n    width: 100%;\n  }\n  .col-md-11 {\n    width: 91.66666667%;\n  }\n  .col-md-10 {\n    width: 83.33333333%;\n  }\n  .col-md-9 {\n    width: 75%;\n  }\n  .col-md-8 {\n    width: 66.66666667%;\n  }\n  .col-md-7 {\n    width: 58.33333333%;\n  }\n  .col-md-6 {\n    width: 50%;\n  }\n  .col-md-5 {\n    width: 41.66666667%;\n  }\n  .col-md-4 {\n    width: 33.33333333%;\n  }\n  .col-md-3 {\n    width: 25%;\n  }\n  .col-md-2 {\n    width: 16.66666667%;\n  }\n  .col-md-1 {\n    width: 8.33333333%;\n  }\n  .col-md-pull-12 {\n    right: 100%;\n  }\n  .col-md-pull-11 {\n    right: 91.66666667%;\n  }\n  .col-md-pull-10 {\n    right: 83.33333333%;\n  }\n  .col-md-pull-9 {\n    right: 75%;\n  }\n  .col-md-pull-8 {\n    right: 66.66666667%;\n  }\n  .col-md-pull-7 {\n    right: 58.33333333%;\n  }\n  .col-md-pull-6 {\n    right: 50%;\n  }\n  .col-md-pull-5 {\n    right: 41.66666667%;\n  }\n  .col-md-pull-4 {\n    right: 33.33333333%;\n  }\n  .col-md-pull-3 {\n    right: 25%;\n  }\n  .col-md-pull-2 {\n    right: 16.66666667%;\n  }\n  .col-md-pull-1 {\n    right: 8.33333333%;\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.66666667%;\n  }\n  .col-md-push-10 {\n    left: 83.33333333%;\n  }\n  .col-md-push-9 {\n    left: 75%;\n  }\n  .col-md-push-8 {\n    left: 66.66666667%;\n  }\n  .col-md-push-7 {\n    left: 58.33333333%;\n  }\n  .col-md-push-6 {\n    left: 50%;\n  }\n  .col-md-push-5 {\n    left: 41.66666667%;\n  }\n  .col-md-push-4 {\n    left: 33.33333333%;\n  }\n  .col-md-push-3 {\n    left: 25%;\n  }\n  .col-md-push-2 {\n    left: 16.66666667%;\n  }\n  .col-md-push-1 {\n    left: 8.33333333%;\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.66666667%;\n  }\n  .col-md-offset-10 {\n    margin-left: 83.33333333%;\n  }\n  .col-md-offset-9 {\n    margin-left: 75%;\n  }\n  .col-md-offset-8 {\n    margin-left: 66.66666667%;\n  }\n  .col-md-offset-7 {\n    margin-left: 58.33333333%;\n  }\n  .col-md-offset-6 {\n    margin-left: 50%;\n  }\n  .col-md-offset-5 {\n    margin-left: 41.66666667%;\n  }\n  .col-md-offset-4 {\n    margin-left: 33.33333333%;\n  }\n  .col-md-offset-3 {\n    margin-left: 25%;\n  }\n  .col-md-offset-2 {\n    margin-left: 16.66666667%;\n  }\n  .col-md-offset-1 {\n    margin-left: 8.33333333%;\n  }\n  .col-md-offset-0 {\n    margin-left: 0;\n  }\n}\n@media (min-width: 1200px) {\n  .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 {\n    float: left;\n  }\n  .col-lg-12 {\n    width: 100%;\n  }\n  .col-lg-11 {\n    width: 91.66666667%;\n  }\n  .col-lg-10 {\n    width: 83.33333333%;\n  }\n  .col-lg-9 {\n    width: 75%;\n  }\n  .col-lg-8 {\n    width: 66.66666667%;\n  }\n  .col-lg-7 {\n    width: 58.33333333%;\n  }\n  .col-lg-6 {\n    width: 50%;\n  }\n  .col-lg-5 {\n    width: 41.66666667%;\n  }\n  .col-lg-4 {\n    width: 33.33333333%;\n  }\n  .col-lg-3 {\n    width: 25%;\n  }\n  .col-lg-2 {\n    width: 16.66666667%;\n  }\n  .col-lg-1 {\n    width: 8.33333333%;\n  }\n  .col-lg-pull-12 {\n    right: 100%;\n  }\n  .col-lg-pull-11 {\n    right: 91.66666667%;\n  }\n  .col-lg-pull-10 {\n    right: 83.33333333%;\n  }\n  .col-lg-pull-9 {\n    right: 75%;\n  }\n  .col-lg-pull-8 {\n    right: 66.66666667%;\n  }\n  .col-lg-pull-7 {\n    right: 58.33333333%;\n  }\n  .col-lg-pull-6 {\n    right: 50%;\n  }\n  .col-lg-pull-5 {\n    right: 41.66666667%;\n  }\n  .col-lg-pull-4 {\n    right: 33.33333333%;\n  }\n  .col-lg-pull-3 {\n    right: 25%;\n  }\n  .col-lg-pull-2 {\n    right: 16.66666667%;\n  }\n  .col-lg-pull-1 {\n    right: 8.33333333%;\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.66666667%;\n  }\n  .col-lg-push-10 {\n    left: 83.33333333%;\n  }\n  .col-lg-push-9 {\n    left: 75%;\n  }\n  .col-lg-push-8 {\n    left: 66.66666667%;\n  }\n  .col-lg-push-7 {\n    left: 58.33333333%;\n  }\n  .col-lg-push-6 {\n    left: 50%;\n  }\n  .col-lg-push-5 {\n    left: 41.66666667%;\n  }\n  .col-lg-push-4 {\n    left: 33.33333333%;\n  }\n  .col-lg-push-3 {\n    left: 25%;\n  }\n  .col-lg-push-2 {\n    left: 16.66666667%;\n  }\n  .col-lg-push-1 {\n    left: 8.33333333%;\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.66666667%;\n  }\n  .col-lg-offset-10 {\n    margin-left: 83.33333333%;\n  }\n  .col-lg-offset-9 {\n    margin-left: 75%;\n  }\n  .col-lg-offset-8 {\n    margin-left: 66.66666667%;\n  }\n  .col-lg-offset-7 {\n    margin-left: 58.33333333%;\n  }\n  .col-lg-offset-6 {\n    margin-left: 50%;\n  }\n  .col-lg-offset-5 {\n    margin-left: 41.66666667%;\n  }\n  .col-lg-offset-4 {\n    margin-left: 33.33333333%;\n  }\n  .col-lg-offset-3 {\n    margin-left: 25%;\n  }\n  .col-lg-offset-2 {\n    margin-left: 16.66666667%;\n  }\n  .col-lg-offset-1 {\n    margin-left: 8.33333333%;\n  }\n  .col-lg-offset-0 {\n    margin-left: 0;\n  }\n}\ntable {\n  max-width: 100%;\n  background-color: transparent;\n}\nth {\n  text-align: left;\n}\n.table {\n  width: 100%;\n  margin-bottom: 20px;\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.42857143;\n  vertical-align: top;\n  border-top: 1px solid #ddd;\n}\n.table > thead > tr > th {\n  vertical-align: bottom;\n  border-bottom: 2px solid #ddd;\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.table > tbody + tbody {\n  border-top: 2px solid #ddd;\n}\n.table .table {\n  background-color: #fff;\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.table-bordered {\n  border: 1px solid #ddd;\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 #ddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > thead > tr > td {\n  border-bottom-width: 2px;\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.table-hover > tbody > tr:hover > td,\n.table-hover > tbody > tr:hover > th {\n  background-color: #f5f5f5;\n}\ntable col[class*=\"col-\"] {\n  position: static;\n  display: table-column;\n  float: none;\n}\ntable td[class*=\"col-\"],\ntable th[class*=\"col-\"] {\n  position: static;\n  display: table-cell;\n  float: none;\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.table-hover > tbody > tr > td.active:hover,\n.table-hover > tbody > tr > th.active:hover,\n.table-hover > tbody > tr.active:hover > td,\n.table-hover > tbody > tr.active:hover > th {\n  background-color: #e8e8e8;\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.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.table > thead > tr > td.info,\n.table > tbody > tr > td.info,\n.table > tfoot > tr > td.info,\n.table > thead > tr > th.info,\n.table > tbody > tr > th.info,\n.table > tfoot > tr > th.info,\n.table > thead > tr.info > td,\n.table > tbody > tr.info > td,\n.table > tfoot > tr.info > td,\n.table > thead > tr.info > th,\n.table > tbody > tr.info > th,\n.table > tfoot > tr.info > th {\n  background-color: #d9edf7;\n}\n.table-hover > tbody > tr > td.info:hover,\n.table-hover > tbody > tr > th.info:hover,\n.table-hover > tbody > tr.info:hover > td,\n.table-hover > tbody > tr.info:hover > th {\n  background-color: #c4e3f3;\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.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.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.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@media (max-width: 767px) {\n  .table-responsive {\n    width: 100%;\n    margin-bottom: 15px;\n    overflow-x: scroll;\n    overflow-y: hidden;\n    -webkit-overflow-scrolling: touch;\n    -ms-overflow-style: -ms-autohiding-scrollbar;\n    border: 1px solid #ddd;\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}\nfieldset {\n  min-width: 0;\n  padding: 0;\n  margin: 0;\n  border: 0;\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: #333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\nlabel {\n  display: inline-block;\n  margin-bottom: 5px;\n  font-weight: bold;\n}\ninput[type=\"search\"] {\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  /* IE8-9 */\n  line-height: normal;\n}\ninput[type=\"file\"] {\n  display: block;\n}\ninput[type=\"range\"] {\n  display: block;\n  width: 100%;\n}\nselect[multiple],\nselect[size] {\n  height: auto;\n}\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\noutput {\n  display: block;\n  padding-top: 7px;\n  font-size: 14px;\n  line-height: 1.42857143;\n  color: #555;\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.42857143;\n  color: #555;\n  background-color: #fff;\n  background-image: none;\n  border: 1px solid #ccc;\n  border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n  -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n          transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n}\n.form-control:focus {\n  border-color: #66afe9;\n  outline: 0;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6);\n          box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6);\n}\n.form-control::-moz-placeholder {\n  color: #999;\n  opacity: 1;\n}\n.form-control:-ms-input-placeholder {\n  color: #999;\n}\n.form-control::-webkit-input-placeholder {\n  color: #999;\n}\n.form-control[disabled],\n.form-control[readonly],\nfieldset[disabled] .form-control {\n  cursor: not-allowed;\n  background-color: #eee;\n  opacity: 1;\n}\ntextarea.form-control {\n  height: auto;\n}\ninput[type=\"search\"] {\n  -webkit-appearance: none;\n}\ninput[type=\"date\"] {\n  line-height: 34px;\n}\n.form-group {\n  margin-bottom: 15px;\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}\n.radio label,\n.checkbox label {\n  display: inline;\n  font-weight: normal;\n  cursor: pointer;\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.radio + .radio,\n.checkbox + .checkbox {\n  margin-top: -5px;\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.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n  margin-top: 0;\n  margin-left: 10px;\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.input-sm {\n  height: 30px;\n  padding: 5px 10px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n}\nselect.input-sm {\n  height: 30px;\n  line-height: 30px;\n}\ntextarea.input-sm,\nselect[multiple].input-sm {\n  height: auto;\n}\n.input-lg {\n  height: 46px;\n  padding: 10px 16px;\n  font-size: 18px;\n  line-height: 1.33;\n  border-radius: 6px;\n}\nselect.input-lg {\n  height: 46px;\n  line-height: 46px;\n}\ntextarea.input-lg,\nselect[multiple].input-lg {\n  height: auto;\n}\n.has-feedback {\n  position: relative;\n}\n.has-feedback .form-control {\n  padding-right: 42.5px;\n}\n.has-feedback .form-control-feedback {\n  position: absolute;\n  top: 25px;\n  right: 0;\n  display: block;\n  width: 34px;\n  height: 34px;\n  line-height: 34px;\n  text-align: center;\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: #3c763d;\n}\n.has-success .form-control {\n  border-color: #3c763d;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n}\n.has-success .form-control:focus {\n  border-color: #2b542c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168;\n}\n.has-success .input-group-addon {\n  color: #3c763d;\n  background-color: #dff0d8;\n  border-color: #3c763d;\n}\n.has-success .form-control-feedback {\n  color: #3c763d;\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: #8a6d3b;\n}\n.has-warning .form-control {\n  border-color: #8a6d3b;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n}\n.has-warning .form-control:focus {\n  border-color: #66512c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b;\n}\n.has-warning .input-group-addon {\n  color: #8a6d3b;\n  background-color: #fcf8e3;\n  border-color: #8a6d3b;\n}\n.has-warning .form-control-feedback {\n  color: #8a6d3b;\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: #a94442;\n}\n.has-error .form-control {\n  border-color: #a94442;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n}\n.has-error .form-control:focus {\n  border-color: #843534;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483;\n}\n.has-error .input-group-addon {\n  color: #a94442;\n  background-color: #f2dede;\n  border-color: #a94442;\n}\n.has-error .form-control-feedback {\n  color: #a94442;\n}\n.form-control-static {\n  margin-bottom: 0;\n}\n.help-block {\n  display: block;\n  margin-top: 5px;\n  margin-bottom: 10px;\n  color: #737373;\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    width: auto;\n    vertical-align: middle;\n  }\n  .form-inline .input-group > .form-control {\n    width: 100%;\n  }\n  .form-inline .control-label {\n    margin-bottom: 0;\n    vertical-align: middle;\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    vertical-align: middle;\n  }\n  .form-inline .radio input[type=\"radio\"],\n  .form-inline .checkbox input[type=\"checkbox\"] {\n    float: none;\n    margin-left: 0;\n  }\n  .form-inline .has-feedback .form-control-feedback {\n    top: 0;\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.form-horizontal .radio,\n.form-horizontal .checkbox {\n  min-height: 27px;\n}\n.form-horizontal .form-group {\n  margin-right: -15px;\n  margin-left: -15px;\n}\n.form-horizontal .form-control-static {\n  padding-top: 7px;\n}\n@media (min-width: 768px) {\n  .form-horizontal .control-label {\n    text-align: right;\n  }\n}\n.form-horizontal .has-feedback .form-control-feedback {\n  top: 0;\n  right: 15px;\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.42857143;\n  text-align: center;\n  white-space: nowrap;\n  vertical-align: middle;\n  cursor: pointer;\n  -webkit-user-select: none;\n     -moz-user-select: none;\n      -ms-user-select: none;\n          user-select: none;\n  background-image: none;\n  border: 1px solid transparent;\n  border-radius: 4px;\n}\n.btn:focus,\n.btn:active:focus,\n.btn.active:focus {\n  outline: thin dotted;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n.btn:hover,\n.btn:focus {\n  color: #333;\n  text-decoration: none;\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, .125);\n          box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);\n}\n.btn.disabled,\n.btn[disabled],\nfieldset[disabled] .btn {\n  pointer-events: none;\n  cursor: not-allowed;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n          box-shadow: none;\n  opacity: .65;\n}\n.btn-default {\n  color: #333;\n  background-color: #fff;\n  border-color: #ccc;\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: #333;\n  background-color: #ebebeb;\n  border-color: #adadad;\n}\n.btn-default:active,\n.btn-default.active,\n.open .dropdown-toggle.btn-default {\n  background-image: none;\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: #fff;\n  border-color: #ccc;\n}\n.btn-default .badge {\n  color: #fff;\n  background-color: #333;\n}\n.btn-primary {\n  color: #fff;\n  background-color: #428bca;\n  border-color: #357ebd;\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: #fff;\n  background-color: #3276b1;\n  border-color: #285e8e;\n}\n.btn-primary:active,\n.btn-primary.active,\n.open .dropdown-toggle.btn-primary {\n  background-image: none;\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.btn-primary .badge {\n  color: #428bca;\n  background-color: #fff;\n}\n.btn-success {\n  color: #fff;\n  background-color: #5cb85c;\n  border-color: #4cae4c;\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: #fff;\n  background-color: #47a447;\n  border-color: #398439;\n}\n.btn-success:active,\n.btn-success.active,\n.open .dropdown-toggle.btn-success {\n  background-image: none;\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.btn-success .badge {\n  color: #5cb85c;\n  background-color: #fff;\n}\n.btn-info {\n  color: #fff;\n  background-color: #5bc0de;\n  border-color: #46b8da;\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: #fff;\n  background-color: #39b3d7;\n  border-color: #269abc;\n}\n.btn-info:active,\n.btn-info.active,\n.open .dropdown-toggle.btn-info {\n  background-image: none;\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.btn-info .badge {\n  color: #5bc0de;\n  background-color: #fff;\n}\n.btn-warning {\n  color: #fff;\n  background-color: #f0ad4e;\n  border-color: #eea236;\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: #fff;\n  background-color: #ed9c28;\n  border-color: #d58512;\n}\n.btn-warning:active,\n.btn-warning.active,\n.open .dropdown-toggle.btn-warning {\n  background-image: none;\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.btn-warning .badge {\n  color: #f0ad4e;\n  background-color: #fff;\n}\n.btn-danger {\n  color: #fff;\n  background-color: #d9534f;\n  border-color: #d43f3a;\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: #fff;\n  background-color: #d2322d;\n  border-color: #ac2925;\n}\n.btn-danger:active,\n.btn-danger.active,\n.open .dropdown-toggle.btn-danger {\n  background-image: none;\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.btn-danger .badge {\n  color: #d9534f;\n  background-color: #fff;\n}\n.btn-link {\n  font-weight: normal;\n  color: #428bca;\n  cursor: pointer;\n  border-radius: 0;\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.btn-link,\n.btn-link:hover,\n.btn-link:focus,\n.btn-link:active {\n  border-color: transparent;\n}\n.btn-link:hover,\n.btn-link:focus {\n  color: #2a6496;\n  text-decoration: underline;\n  background-color: transparent;\n}\n.btn-link[disabled]:hover,\nfieldset[disabled] .btn-link:hover,\n.btn-link[disabled]:focus,\nfieldset[disabled] .btn-link:focus {\n  color: #999;\n  text-decoration: none;\n}\n.btn-lg,\n.btn-group-lg > .btn {\n  padding: 10px 16px;\n  font-size: 18px;\n  line-height: 1.33;\n  border-radius: 6px;\n}\n.btn-sm,\n.btn-group-sm > .btn {\n  padding: 5px 10px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n}\n.btn-xs,\n.btn-group-xs > .btn {\n  padding: 1px 5px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n}\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n}\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity .15s linear;\n          transition: opacity .15s linear;\n}\n.fade.in {\n  opacity: 1;\n}\n.collapse {\n  display: none;\n}\n.collapse.in {\n  display: block;\n}\n.collapsing {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height .35s ease;\n          transition: height .35s ease;\n}\n@font-face {\n  font-family: 'Glyphicons Halflings';\n\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.glyphicon {\n  position: relative;\n  top: 1px;\n  display: inline-block;\n  font-family: 'Glyphicons Halflings';\n  font-style: normal;\n  font-weight: normal;\n  line-height: 1;\n\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n.glyphicon-asterisk:before {\n  content: \"\\2a\";\n}\n.glyphicon-plus:before {\n  content: \"\\2b\";\n}\n.glyphicon-euro:before {\n  content: \"\\20ac\";\n}\n.glyphicon-minus:before {\n  content: \"\\2212\";\n}\n.glyphicon-cloud:before {\n  content: \"\\2601\";\n}\n.glyphicon-envelope:before {\n  content: \"\\2709\";\n}\n.glyphicon-pencil:before {\n  content: \"\\270f\";\n}\n.glyphicon-glass:before {\n  content: \"\\e001\";\n}\n.glyphicon-music:before {\n  content: \"\\e002\";\n}\n.glyphicon-search:before {\n  content: \"\\e003\";\n}\n.glyphicon-heart:before {\n  content: \"\\e005\";\n}\n.glyphicon-star:before {\n  content: \"\\e006\";\n}\n.glyphicon-star-empty:before {\n  content: \"\\e007\";\n}\n.glyphicon-user:before {\n  content: \"\\e008\";\n}\n.glyphicon-film:before {\n  content: \"\\e009\";\n}\n.glyphicon-th-large:before {\n  content: \"\\e010\";\n}\n.glyphicon-th:before {\n  content: \"\\e011\";\n}\n.glyphicon-th-list:before {\n  content: \"\\e012\";\n}\n.glyphicon-ok:before {\n  content: \"\\e013\";\n}\n.glyphicon-remove:before {\n  content: \"\\e014\";\n}\n.glyphicon-zoom-in:before {\n  content: \"\\e015\";\n}\n.glyphicon-zoom-out:before {\n  content: \"\\e016\";\n}\n.glyphicon-off:before {\n  content: \"\\e017\";\n}\n.glyphicon-signal:before {\n  content: \"\\e018\";\n}\n.glyphicon-cog:before {\n  content: \"\\e019\";\n}\n.glyphicon-trash:before {\n  content: \"\\e020\";\n}\n.glyphicon-home:before {\n  content: \"\\e021\";\n}\n.glyphicon-file:before {\n  content: \"\\e022\";\n}\n.glyphicon-time:before {\n  content: \"\\e023\";\n}\n.glyphicon-road:before {\n  content: \"\\e024\";\n}\n.glyphicon-download-alt:before {\n  content: \"\\e025\";\n}\n.glyphicon-download:before {\n  content: \"\\e026\";\n}\n.glyphicon-upload:before {\n  content: \"\\e027\";\n}\n.glyphicon-inbox:before {\n  content: \"\\e028\";\n}\n.glyphicon-play-circle:before {\n  content: \"\\e029\";\n}\n.glyphicon-repeat:before {\n  content: \"\\e030\";\n}\n.glyphicon-refresh:before {\n  content: \"\\e031\";\n}\n.glyphicon-list-alt:before {\n  content: \"\\e032\";\n}\n.glyphicon-lock:before {\n  content: \"\\e033\";\n}\n.glyphicon-flag:before {\n  content: \"\\e034\";\n}\n.glyphicon-headphones:before {\n  content: \"\\e035\";\n}\n.glyphicon-volume-off:before {\n  content: \"\\e036\";\n}\n.glyphicon-volume-down:before {\n  content: \"\\e037\";\n}\n.glyphicon-volume-up:before {\n  content: \"\\e038\";\n}\n.glyphicon-qrcode:before {\n  content: \"\\e039\";\n}\n.glyphicon-barcode:before {\n  content: \"\\e040\";\n}\n.glyphicon-tag:before {\n  content: \"\\e041\";\n}\n.glyphicon-tags:before {\n  content: \"\\e042\";\n}\n.glyphicon-book:before {\n  content: \"\\e043\";\n}\n.glyphicon-bookmark:before {\n  content: \"\\e044\";\n}\n.glyphicon-print:before {\n  content: \"\\e045\";\n}\n.glyphicon-camera:before {\n  content: \"\\e046\";\n}\n.glyphicon-font:before {\n  content: \"\\e047\";\n}\n.glyphicon-bold:before {\n  content: \"\\e048\";\n}\n.glyphicon-italic:before {\n  content: \"\\e049\";\n}\n.glyphicon-text-height:before {\n  content: \"\\e050\";\n}\n.glyphicon-text-width:before {\n  content: \"\\e051\";\n}\n.glyphicon-align-left:before {\n  content: \"\\e052\";\n}\n.glyphicon-align-center:before {\n  content: \"\\e053\";\n}\n.glyphicon-align-right:before {\n  content: \"\\e054\";\n}\n.glyphicon-align-justify:before {\n  content: \"\\e055\";\n}\n.glyphicon-list:before {\n  content: \"\\e056\";\n}\n.glyphicon-indent-left:before {\n  content: \"\\e057\";\n}\n.glyphicon-indent-right:before {\n  content: \"\\e058\";\n}\n.glyphicon-facetime-video:before {\n  content: \"\\e059\";\n}\n.glyphicon-picture:before {\n  content: \"\\e060\";\n}\n.glyphicon-map-marker:before {\n  content: \"\\e062\";\n}\n.glyphicon-adjust:before {\n  content: \"\\e063\";\n}\n.glyphicon-tint:before {\n  content: \"\\e064\";\n}\n.glyphicon-edit:before {\n  content: \"\\e065\";\n}\n.glyphicon-share:before {\n  content: \"\\e066\";\n}\n.glyphicon-check:before {\n  content: \"\\e067\";\n}\n.glyphicon-move:before {\n  content: \"\\e068\";\n}\n.glyphicon-step-backward:before {\n  content: \"\\e069\";\n}\n.glyphicon-fast-backward:before {\n  content: \"\\e070\";\n}\n.glyphicon-backward:before {\n  content: \"\\e071\";\n}\n.glyphicon-play:before {\n  content: \"\\e072\";\n}\n.glyphicon-pause:before {\n  content: \"\\e073\";\n}\n.glyphicon-stop:before {\n  content: \"\\e074\";\n}\n.glyphicon-forward:before {\n  content: \"\\e075\";\n}\n.glyphicon-fast-forward:before {\n  content: \"\\e076\";\n}\n.glyphicon-step-forward:before {\n  content: \"\\e077\";\n}\n.glyphicon-eject:before {\n  content: \"\\e078\";\n}\n.glyphicon-chevron-left:before {\n  content: \"\\e079\";\n}\n.glyphicon-chevron-right:before {\n  content: \"\\e080\";\n}\n.glyphicon-plus-sign:before {\n  content: \"\\e081\";\n}\n.glyphicon-minus-sign:before {\n  content: \"\\e082\";\n}\n.glyphicon-remove-sign:before {\n  content: \"\\e083\";\n}\n.glyphicon-ok-sign:before {\n  content: \"\\e084\";\n}\n.glyphicon-question-sign:before {\n  content: \"\\e085\";\n}\n.glyphicon-info-sign:before {\n  content: \"\\e086\";\n}\n.glyphicon-screenshot:before {\n  content: \"\\e087\";\n}\n.glyphicon-remove-circle:before {\n  content: \"\\e088\";\n}\n.glyphicon-ok-circle:before {\n  content: \"\\e089\";\n}\n.glyphicon-ban-circle:before {\n  content: \"\\e090\";\n}\n.glyphicon-arrow-left:before {\n  content: \"\\e091\";\n}\n.glyphicon-arrow-right:before {\n  content: \"\\e092\";\n}\n.glyphicon-arrow-up:before {\n  content: \"\\e093\";\n}\n.glyphicon-arrow-down:before {\n  content: \"\\e094\";\n}\n.glyphicon-share-alt:before {\n  content: \"\\e095\";\n}\n.glyphicon-resize-full:before {\n  content: \"\\e096\";\n}\n.glyphicon-resize-small:before {\n  content: \"\\e097\";\n}\n.glyphicon-exclamation-sign:before {\n  content: \"\\e101\";\n}\n.glyphicon-gift:before {\n  content: \"\\e102\";\n}\n.glyphicon-leaf:before {\n  content: \"\\e103\";\n}\n.glyphicon-fire:before {\n  content: \"\\e104\";\n}\n.glyphicon-eye-open:before {\n  content: \"\\e105\";\n}\n.glyphicon-eye-close:before {\n  content: \"\\e106\";\n}\n.glyphicon-warning-sign:before {\n  content: \"\\e107\";\n}\n.glyphicon-plane:before {\n  content: \"\\e108\";\n}\n.glyphicon-calendar:before {\n  content: \"\\e109\";\n}\n.glyphicon-random:before {\n  content: \"\\e110\";\n}\n.glyphicon-comment:before {\n  content: \"\\e111\";\n}\n.glyphicon-magnet:before {\n  content: \"\\e112\";\n}\n.glyphicon-chevron-up:before {\n  content: \"\\e113\";\n}\n.glyphicon-chevron-down:before {\n  content: \"\\e114\";\n}\n.glyphicon-retweet:before {\n  content: \"\\e115\";\n}\n.glyphicon-shopping-cart:before {\n  content: \"\\e116\";\n}\n.glyphicon-folder-close:before {\n  content: \"\\e117\";\n}\n.glyphicon-folder-open:before {\n  content: \"\\e118\";\n}\n.glyphicon-resize-vertical:before {\n  content: \"\\e119\";\n}\n.glyphicon-resize-horizontal:before {\n  content: \"\\e120\";\n}\n.glyphicon-hdd:before {\n  content: \"\\e121\";\n}\n.glyphicon-bullhorn:before {\n  content: \"\\e122\";\n}\n.glyphicon-bell:before {\n  content: \"\\e123\";\n}\n.glyphicon-certificate:before {\n  content: \"\\e124\";\n}\n.glyphicon-thumbs-up:before {\n  content: \"\\e125\";\n}\n.glyphicon-thumbs-down:before {\n  content: \"\\e126\";\n}\n.glyphicon-hand-right:before {\n  content: \"\\e127\";\n}\n.glyphicon-hand-left:before {\n  content: \"\\e128\";\n}\n.glyphicon-hand-up:before {\n  content: \"\\e129\";\n}\n.glyphicon-hand-down:before {\n  content: \"\\e130\";\n}\n.glyphicon-circle-arrow-right:before {\n  content: \"\\e131\";\n}\n.glyphicon-circle-arrow-left:before {\n  content: \"\\e132\";\n}\n.glyphicon-circle-arrow-up:before {\n  content: \"\\e133\";\n}\n.glyphicon-circle-arrow-down:before {\n  content: \"\\e134\";\n}\n.glyphicon-globe:before {\n  content: \"\\e135\";\n}\n.glyphicon-wrench:before {\n  content: \"\\e136\";\n}\n.glyphicon-tasks:before {\n  content: \"\\e137\";\n}\n.glyphicon-filter:before {\n  content: \"\\e138\";\n}\n.glyphicon-briefcase:before {\n  content: \"\\e139\";\n}\n.glyphicon-fullscreen:before {\n  content: \"\\e140\";\n}\n.glyphicon-dashboard:before {\n  content: \"\\e141\";\n}\n.glyphicon-paperclip:before {\n  content: \"\\e142\";\n}\n.glyphicon-heart-empty:before {\n  content: \"\\e143\";\n}\n.glyphicon-link:before {\n  content: \"\\e144\";\n}\n.glyphicon-phone:before {\n  content: \"\\e145\";\n}\n.glyphicon-pushpin:before {\n  content: \"\\e146\";\n}\n.glyphicon-usd:before {\n  content: \"\\e148\";\n}\n.glyphicon-gbp:before {\n  content: \"\\e149\";\n}\n.glyphicon-sort:before {\n  content: \"\\e150\";\n}\n.glyphicon-sort-by-alphabet:before {\n  content: \"\\e151\";\n}\n.glyphicon-sort-by-alphabet-alt:before {\n  content: \"\\e152\";\n}\n.glyphicon-sort-by-order:before {\n  content: \"\\e153\";\n}\n.glyphicon-sort-by-order-alt:before {\n  content: \"\\e154\";\n}\n.glyphicon-sort-by-attributes:before {\n  content: \"\\e155\";\n}\n.glyphicon-sort-by-attributes-alt:before {\n  content: \"\\e156\";\n}\n.glyphicon-unchecked:before {\n  content: \"\\e157\";\n}\n.glyphicon-expand:before {\n  content: \"\\e158\";\n}\n.glyphicon-collapse-down:before {\n  content: \"\\e159\";\n}\n.glyphicon-collapse-up:before {\n  content: \"\\e160\";\n}\n.glyphicon-log-in:before {\n  content: \"\\e161\";\n}\n.glyphicon-flash:before {\n  content: \"\\e162\";\n}\n.glyphicon-log-out:before {\n  content: \"\\e163\";\n}\n.glyphicon-new-window:before {\n  content: \"\\e164\";\n}\n.glyphicon-record:before {\n  content: \"\\e165\";\n}\n.glyphicon-save:before {\n  content: \"\\e166\";\n}\n.glyphicon-open:before {\n  content: \"\\e167\";\n}\n.glyphicon-saved:before {\n  content: \"\\e168\";\n}\n.glyphicon-import:before {\n  content: \"\\e169\";\n}\n.glyphicon-export:before {\n  content: \"\\e170\";\n}\n.glyphicon-send:before {\n  content: \"\\e171\";\n}\n.glyphicon-floppy-disk:before {\n  content: \"\\e172\";\n}\n.glyphicon-floppy-saved:before {\n  content: \"\\e173\";\n}\n.glyphicon-floppy-remove:before {\n  content: \"\\e174\";\n}\n.glyphicon-floppy-save:before {\n  content: \"\\e175\";\n}\n.glyphicon-floppy-open:before {\n  content: \"\\e176\";\n}\n.glyphicon-credit-card:before {\n  content: \"\\e177\";\n}\n.glyphicon-transfer:before {\n  content: \"\\e178\";\n}\n.glyphicon-cutlery:before {\n  content: \"\\e179\";\n}\n.glyphicon-header:before {\n  content: \"\\e180\";\n}\n.glyphicon-compressed:before {\n  content: \"\\e181\";\n}\n.glyphicon-earphone:before {\n  content: \"\\e182\";\n}\n.glyphicon-phone-alt:before {\n  content: \"\\e183\";\n}\n.glyphicon-tower:before {\n  content: \"\\e184\";\n}\n.glyphicon-stats:before {\n  content: \"\\e185\";\n}\n.glyphicon-sd-video:before {\n  content: \"\\e186\";\n}\n.glyphicon-hd-video:before {\n  content: \"\\e187\";\n}\n.glyphicon-subtitles:before {\n  content: \"\\e188\";\n}\n.glyphicon-sound-stereo:before {\n  content: \"\\e189\";\n}\n.glyphicon-sound-dolby:before {\n  content: \"\\e190\";\n}\n.glyphicon-sound-5-1:before {\n  content: \"\\e191\";\n}\n.glyphicon-sound-6-1:before {\n  content: \"\\e192\";\n}\n.glyphicon-sound-7-1:before {\n  content: \"\\e193\";\n}\n.glyphicon-copyright-mark:before {\n  content: \"\\e194\";\n}\n.glyphicon-registration-mark:before {\n  content: \"\\e195\";\n}\n.glyphicon-cloud-download:before {\n  content: \"\\e197\";\n}\n.glyphicon-cloud-upload:before {\n  content: \"\\e198\";\n}\n.glyphicon-tree-conifer:before {\n  content: \"\\e199\";\n}\n.glyphicon-tree-deciduous:before {\n  content: \"\\e200\";\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;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n}\n.dropdown {\n  position: relative;\n}\n.dropdown-toggle:focus {\n  outline: 0;\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: #fff;\n  background-clip: padding-box;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, .15);\n  border-radius: 4px;\n  -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175);\n          box-shadow: 0 6px 12px rgba(0, 0, 0, .175);\n}\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n.dropdown-menu .divider {\n  height: 1px;\n  margin: 9px 0;\n  overflow: hidden;\n  background-color: #e5e5e5;\n}\n.dropdown-menu > li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 1.42857143;\n  color: #333;\n  white-space: nowrap;\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.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n  color: #fff;\n  text-decoration: none;\n  background-color: #428bca;\n  outline: 0;\n}\n.dropdown-menu > .disabled > a,\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n  color: #999;\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.open > .dropdown-menu {\n  display: block;\n}\n.open > a {\n  outline: 0;\n}\n.dropdown-menu-right {\n  right: 0;\n  left: auto;\n}\n.dropdown-menu-left {\n  right: auto;\n  left: 0;\n}\n.dropdown-header {\n  display: block;\n  padding: 3px 20px;\n  font-size: 12px;\n  line-height: 1.42857143;\n  color: #999;\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.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  content: \"\";\n  border-top: 0;\n  border-bottom: 4px solid;\n}\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n@media (min-width: 768px) {\n  .navbar-right .dropdown-menu {\n    right: 0;\n    left: auto;\n  }\n  .navbar-right .dropdown-menu-left {\n    right: auto;\n    left: 0;\n  }\n}\n.btn-group,\n.btn-group-vertical {\n  position: relative;\n  display: inline-block;\n  vertical-align: middle;\n}\n.btn-group > .btn,\n.btn-group-vertical > .btn {\n  position: relative;\n  float: left;\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.btn-group > .btn:focus,\n.btn-group-vertical > .btn:focus {\n  outline: none;\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.btn-toolbar {\n  margin-left: -5px;\n}\n.btn-toolbar .btn-group,\n.btn-toolbar .input-group {\n  float: left;\n}\n.btn-toolbar > .btn,\n.btn-toolbar > .btn-group,\n.btn-toolbar > .input-group {\n  margin-left: 5px;\n}\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n  border-radius: 0;\n}\n.btn-group > .btn:first-child {\n  margin-left: 0;\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.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n  border-top-left-radius: 0;\n  border-bottom-left-radius: 0;\n}\n.btn-group > .btn-group {\n  float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n  border-radius: 0;\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.btn-group > .btn-group:last-child > .btn:first-child {\n  border-top-left-radius: 0;\n  border-bottom-left-radius: 0;\n}\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n.btn-group > .btn + .dropdown-toggle {\n  padding-right: 8px;\n  padding-left: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n  padding-right: 12px;\n  padding-left: 12px;\n}\n.btn-group.open .dropdown-toggle {\n  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);\n          box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);\n}\n.btn-group.open .dropdown-toggle.btn-link {\n  -webkit-box-shadow: none;\n          box-shadow: none;\n}\n.btn .caret {\n  margin-left: 0;\n}\n.btn-lg .caret {\n  border-width: 5px 5px 0;\n  border-bottom-width: 0;\n}\n.dropup .btn-lg .caret {\n  border-width: 0 5px 5px;\n}\n.btn-group-vertical > .btn,\n.btn-group-vertical > .btn-group,\n.btn-group-vertical > .btn-group > .btn {\n  display: block;\n  float: none;\n  width: 100%;\n  max-width: 100%;\n}\n.btn-group-vertical > .btn-group > .btn {\n  float: none;\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.btn-group-vertical > .btn:not(:first-child):not(:last-child) {\n  border-radius: 0;\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.btn-group-vertical > .btn:last-child:not(:first-child) {\n  border-top-left-radius: 0;\n  border-top-right-radius: 0;\n  border-bottom-left-radius: 4px;\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n  border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n  border-top-left-radius: 0;\n  border-top-right-radius: 0;\n}\n.btn-group-justified {\n  display: table;\n  width: 100%;\n  table-layout: fixed;\n  border-collapse: separate;\n}\n.btn-group-justified > .btn,\n.btn-group-justified > .btn-group {\n  display: table-cell;\n  float: none;\n  width: 1%;\n}\n.btn-group-justified > .btn-group .btn {\n  width: 100%;\n}\n[data-toggle=\"buttons\"] > .btn > input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn > input[type=\"checkbox\"] {\n  display: none;\n}\n.input-group {\n  position: relative;\n  display: table;\n  border-collapse: separate;\n}\n.input-group[class*=\"col-\"] {\n  float: none;\n  padding-right: 0;\n  padding-left: 0;\n}\n.input-group .form-control {\n  position: relative;\n  z-index: 2;\n  float: left;\n  width: 100%;\n  margin-bottom: 0;\n}\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n  height: 46px;\n  padding: 10px 16px;\n  font-size: 18px;\n  line-height: 1.33;\n  border-radius: 6px;\n}\nselect.input-group-lg > .form-control,\nselect.input-group-lg > .input-group-addon,\nselect.input-group-lg > .input-group-btn > .btn {\n  height: 46px;\n  line-height: 46px;\n}\ntextarea.input-group-lg > .form-control,\ntextarea.input-group-lg > .input-group-addon,\ntextarea.input-group-lg > .input-group-btn > .btn,\nselect[multiple].input-group-lg > .form-control,\nselect[multiple].input-group-lg > .input-group-addon,\nselect[multiple].input-group-lg > .input-group-btn > .btn {\n  height: auto;\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}\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}\ntextarea.input-group-sm > .form-control,\ntextarea.input-group-sm > .input-group-addon,\ntextarea.input-group-sm > .input-group-btn > .btn,\nselect[multiple].input-group-sm > .form-control,\nselect[multiple].input-group-sm > .input-group-addon,\nselect[multiple].input-group-sm > .input-group-btn > .btn {\n  height: auto;\n}\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n  display: table-cell;\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.input-group-addon,\n.input-group-btn {\n  width: 1%;\n  white-space: nowrap;\n  vertical-align: middle;\n}\n.input-group-addon {\n  padding: 6px 12px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 1;\n  color: #555;\n  text-align: center;\n  background-color: #eee;\n  border: 1px solid #ccc;\n  border-radius: 4px;\n}\n.input-group-addon.input-sm {\n  padding: 5px 10px;\n  font-size: 12px;\n  border-radius: 3px;\n}\n.input-group-addon.input-lg {\n  padding: 10px 16px;\n  font-size: 18px;\n  border-radius: 6px;\n}\n.input-group-addon input[type=\"radio\"],\n.input-group-addon input[type=\"checkbox\"] {\n  margin-top: 0;\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 > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n  border-top-right-radius: 0;\n  border-bottom-right-radius: 0;\n}\n.input-group-addon:first-child {\n  border-right: 0;\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 > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n  border-top-left-radius: 0;\n  border-bottom-left-radius: 0;\n}\n.input-group-addon:last-child {\n  border-left: 0;\n}\n.input-group-btn {\n  position: relative;\n  font-size: 0;\n  white-space: nowrap;\n}\n.input-group-btn > .btn {\n  position: relative;\n}\n.input-group-btn > .btn + .btn {\n  margin-left: -1px;\n}\n.input-group-btn > .btn:hover,\n.input-group-btn > .btn:focus,\n.input-group-btn > .btn:active {\n  z-index: 2;\n}\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group {\n  margin-right: -1px;\n}\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group {\n  margin-left: -1px;\n}\n.nav {\n  padding-left: 0;\n  margin-bottom: 0;\n  list-style: none;\n}\n.nav > li {\n  position: relative;\n  display: block;\n}\n.nav > li > a {\n  position: relative;\n  display: block;\n  padding: 10px 15px;\n}\n.nav > li > a:hover,\n.nav > li > a:focus {\n  text-decoration: none;\n  background-color: #eee;\n}\n.nav > li.disabled > a {\n  color: #999;\n}\n.nav > li.disabled > a:hover,\n.nav > li.disabled > a:focus {\n  color: #999;\n  text-decoration: none;\n  cursor: not-allowed;\n  background-color: transparent;\n}\n.nav .open > a,\n.nav .open > a:hover,\n.nav .open > a:focus {\n  background-color: #eee;\n  border-color: #428bca;\n}\n.nav .nav-divider {\n  height: 1px;\n  margin: 9px 0;\n  overflow: hidden;\n  background-color: #e5e5e5;\n}\n.nav > li > a > img {\n  max-width: none;\n}\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n.nav-tabs > li {\n  float: left;\n  margin-bottom: -1px;\n}\n.nav-tabs > li > a {\n  margin-right: 2px;\n  line-height: 1.42857143;\n  border: 1px solid transparent;\n  border-radius: 4px 4px 0 0;\n}\n.nav-tabs > li > a:hover {\n  border-color: #eee #eee #ddd;\n}\n.nav-tabs > li.active > a,\n.nav-tabs > li.active > a:hover,\n.nav-tabs > li.active > a:focus {\n  color: #555;\n  cursor: default;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n.nav-tabs.nav-justified {\n  width: 100%;\n  border-bottom: 0;\n}\n.nav-tabs.nav-justified > li {\n  float: none;\n}\n.nav-tabs.nav-justified > li > a {\n  margin-bottom: 5px;\n  text-align: center;\n}\n.nav-tabs.nav-justified > .dropdown .dropdown-menu {\n  top: auto;\n  left: auto;\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.nav-tabs.nav-justified > li > a {\n  margin-right: 0;\n  border-radius: 4px;\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 #ddd;\n}\n@media (min-width: 768px) {\n  .nav-tabs.nav-justified > li > a {\n    border-bottom: 1px solid #ddd;\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: #fff;\n  }\n}\n.nav-pills > li {\n  float: left;\n}\n.nav-pills > li > a {\n  border-radius: 4px;\n}\n.nav-pills > li + li {\n  margin-left: 2px;\n}\n.nav-pills > li.active > a,\n.nav-pills > li.active > a:hover,\n.nav-pills > li.active > a:focus {\n  color: #fff;\n  background-color: #428bca;\n}\n.nav-stacked > li {\n  float: none;\n}\n.nav-stacked > li + li {\n  margin-top: 2px;\n  margin-left: 0;\n}\n.nav-justified {\n  width: 100%;\n}\n.nav-justified > li {\n  float: none;\n}\n.nav-justified > li > a {\n  margin-bottom: 5px;\n  text-align: center;\n}\n.nav-justified > .dropdown .dropdown-menu {\n  top: auto;\n  left: auto;\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.nav-tabs-justified {\n  border-bottom: 0;\n}\n.nav-tabs-justified > li > a {\n  margin-right: 0;\n  border-radius: 4px;\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 #ddd;\n}\n@media (min-width: 768px) {\n  .nav-tabs-justified > li > a {\n    border-bottom: 1px solid #ddd;\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: #fff;\n  }\n}\n.tab-content > .tab-pane {\n  display: none;\n}\n.tab-content > .active {\n  display: block;\n}\n.nav-tabs .dropdown-menu {\n  margin-top: -1px;\n  border-top-left-radius: 0;\n  border-top-right-radius: 0;\n}\n.navbar {\n  position: relative;\n  min-height: 50px;\n  margin-bottom: 20px;\n  border: 1px solid transparent;\n}\n@media (min-width: 768px) {\n  .navbar {\n    border-radius: 4px;\n  }\n}\n@media (min-width: 768px) {\n  .navbar-header {\n    float: left;\n  }\n}\n.navbar-collapse {\n  max-height: 340px;\n  padding-right: 15px;\n  padding-left: 15px;\n  overflow-x: visible;\n  -webkit-overflow-scrolling: touch;\n  border-top: 1px solid transparent;\n  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1);\n}\n.navbar-collapse.in {\n  overflow-y: auto;\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: visible;\n  }\n  .navbar-fixed-top .navbar-collapse,\n  .navbar-static-top .navbar-collapse,\n  .navbar-fixed-bottom .navbar-collapse {\n    padding-right: 0;\n    padding-left: 0;\n  }\n}\n.container > .navbar-header,\n.container-fluid > .navbar-header,\n.container > .navbar-collapse,\n.container-fluid > .navbar-collapse {\n  margin-right: -15px;\n  margin-left: -15px;\n}\n@media (min-width: 768px) {\n  .container > .navbar-header,\n  .container-fluid > .navbar-header,\n  .container > .navbar-collapse,\n  .container-fluid > .navbar-collapse {\n    margin-right: 0;\n    margin-left: 0;\n  }\n}\n.navbar-static-top {\n  z-index: 1000;\n  border-width: 0 0 1px;\n}\n@media (min-width: 768px) {\n  .navbar-static-top {\n    border-radius: 0;\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@media (min-width: 768px) {\n  .navbar-fixed-top,\n  .navbar-fixed-bottom {\n    border-radius: 0;\n  }\n}\n.navbar-fixed-top {\n  top: 0;\n  border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n  bottom: 0;\n  margin-bottom: 0;\n  border-width: 1px 0 0;\n}\n.navbar-brand {\n  float: left;\n  height: 50px;\n  padding: 15px 15px;\n  font-size: 18px;\n  line-height: 20px;\n}\n.navbar-brand:hover,\n.navbar-brand:focus {\n  text-decoration: none;\n}\n@media (min-width: 768px) {\n  .navbar > .container .navbar-brand,\n  .navbar > .container-fluid .navbar-brand {\n    margin-left: -15px;\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  background-image: none;\n  border: 1px solid transparent;\n  border-radius: 4px;\n}\n.navbar-toggle:focus {\n  outline: none;\n}\n.navbar-toggle .icon-bar {\n  display: block;\n  width: 22px;\n  height: 2px;\n  border-radius: 1px;\n}\n.navbar-toggle .icon-bar + .icon-bar {\n  margin-top: 4px;\n}\n@media (min-width: 768px) {\n  .navbar-toggle {\n    display: none;\n  }\n}\n.navbar-nav {\n  margin: 7.5px -15px;\n}\n.navbar-nav > li > a {\n  padding-top: 10px;\n  padding-bottom: 10px;\n  line-height: 20px;\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@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  .navbar-nav.navbar-right:last-child {\n    margin-right: -15px;\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.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, .1), 0 1px 0 rgba(255, 255, 255, .1);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1);\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    width: auto;\n    vertical-align: middle;\n  }\n  .navbar-form .input-group > .form-control {\n    width: 100%;\n  }\n  .navbar-form .control-label {\n    margin-bottom: 0;\n    vertical-align: middle;\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    vertical-align: middle;\n  }\n  .navbar-form .radio input[type=\"radio\"],\n  .navbar-form .checkbox input[type=\"checkbox\"] {\n    float: none;\n    margin-left: 0;\n  }\n  .navbar-form .has-feedback .form-control-feedback {\n    top: 0;\n  }\n}\n@media (max-width: 767px) {\n  .navbar-form .form-group {\n    margin-bottom: 5px;\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  .navbar-form.navbar-right:last-child {\n    margin-right: -15px;\n  }\n}\n.navbar-nav > li > .dropdown-menu {\n  margin-top: 0;\n  border-top-left-radius: 0;\n  border-top-right-radius: 0;\n}\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n.navbar-btn {\n  margin-top: 8px;\n  margin-bottom: 8px;\n}\n.navbar-btn.btn-sm {\n  margin-top: 10px;\n  margin-bottom: 10px;\n}\n.navbar-btn.btn-xs {\n  margin-top: 14px;\n  margin-bottom: 14px;\n}\n.navbar-text {\n  margin-top: 15px;\n  margin-bottom: 15px;\n}\n@media (min-width: 768px) {\n  .navbar-text {\n    float: left;\n    margin-right: 15px;\n    margin-left: 15px;\n  }\n  .navbar-text.navbar-right:last-child {\n    margin-right: 0;\n  }\n}\n.navbar-default {\n  background-color: #f8f8f8;\n  border-color: #e7e7e7;\n}\n.navbar-default .navbar-brand {\n  color: #777;\n}\n.navbar-default .navbar-brand:hover,\n.navbar-default .navbar-brand:focus {\n  color: #5e5e5e;\n  background-color: transparent;\n}\n.navbar-default .navbar-text {\n  color: #777;\n}\n.navbar-default .navbar-nav > li > a {\n  color: #777;\n}\n.navbar-default .navbar-nav > li > a:hover,\n.navbar-default .navbar-nav > li > a:focus {\n  color: #333;\n  background-color: transparent;\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: #555;\n  background-color: #e7e7e7;\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: #ccc;\n  background-color: transparent;\n}\n.navbar-default .navbar-toggle {\n  border-color: #ddd;\n}\n.navbar-default .navbar-toggle:hover,\n.navbar-default .navbar-toggle:focus {\n  background-color: #ddd;\n}\n.navbar-default .navbar-toggle .icon-bar {\n  background-color: #888;\n}\n.navbar-default .navbar-collapse,\n.navbar-default .navbar-form {\n  border-color: #e7e7e7;\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: #555;\n  background-color: #e7e7e7;\n}\n@media (max-width: 767px) {\n  .navbar-default .navbar-nav .open .dropdown-menu > li > a {\n    color: #777;\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: #333;\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: #555;\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: #ccc;\n    background-color: transparent;\n  }\n}\n.navbar-default .navbar-link {\n  color: #777;\n}\n.navbar-default .navbar-link:hover {\n  color: #333;\n}\n.navbar-inverse {\n  background-color: #222;\n  border-color: #080808;\n}\n.navbar-inverse .navbar-brand {\n  color: #999;\n}\n.navbar-inverse .navbar-brand:hover,\n.navbar-inverse .navbar-brand:focus {\n  color: #fff;\n  background-color: transparent;\n}\n.navbar-inverse .navbar-text {\n  color: #999;\n}\n.navbar-inverse .navbar-nav > li > a {\n  color: #999;\n}\n.navbar-inverse .navbar-nav > li > a:hover,\n.navbar-inverse .navbar-nav > li > a:focus {\n  color: #fff;\n  background-color: transparent;\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: #fff;\n  background-color: #080808;\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: #444;\n  background-color: transparent;\n}\n.navbar-inverse .navbar-toggle {\n  border-color: #333;\n}\n.navbar-inverse .navbar-toggle:hover,\n.navbar-inverse .navbar-toggle:focus {\n  background-color: #333;\n}\n.navbar-inverse .navbar-toggle .icon-bar {\n  background-color: #fff;\n}\n.navbar-inverse .navbar-collapse,\n.navbar-inverse .navbar-form {\n  border-color: #101010;\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: #fff;\n  background-color: #080808;\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 .divider {\n    background-color: #080808;\n  }\n  .navbar-inverse .navbar-nav .open .dropdown-menu > li > a {\n    color: #999;\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: #fff;\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: #fff;\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: #444;\n    background-color: transparent;\n  }\n}\n.navbar-inverse .navbar-link {\n  color: #999;\n}\n.navbar-inverse .navbar-link:hover {\n  color: #fff;\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.breadcrumb > li {\n  display: inline-block;\n}\n.breadcrumb > li + li:before {\n  padding: 0 5px;\n  color: #ccc;\n  content: \"/\\00a0\";\n}\n.breadcrumb > .active {\n  color: #999;\n}\n.pagination {\n  display: inline-block;\n  padding-left: 0;\n  margin: 20px 0;\n  border-radius: 4px;\n}\n.pagination > li {\n  display: inline;\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.42857143;\n  color: #428bca;\n  text-decoration: none;\n  background-color: #fff;\n  border: 1px solid #ddd;\n}\n.pagination > li:first-child > a,\n.pagination > li:first-child > span {\n  margin-left: 0;\n  border-top-left-radius: 4px;\n  border-bottom-left-radius: 4px;\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.pagination > li > a:hover,\n.pagination > li > span:hover,\n.pagination > li > a:focus,\n.pagination > li > span:focus {\n  color: #2a6496;\n  background-color: #eee;\n  border-color: #ddd;\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: #fff;\n  cursor: default;\n  background-color: #428bca;\n  border-color: #428bca;\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: #999;\n  cursor: not-allowed;\n  background-color: #fff;\n  border-color: #ddd;\n}\n.pagination-lg > li > a,\n.pagination-lg > li > span {\n  padding: 10px 16px;\n  font-size: 18px;\n}\n.pagination-lg > li:first-child > a,\n.pagination-lg > li:first-child > span {\n  border-top-left-radius: 6px;\n  border-bottom-left-radius: 6px;\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.pagination-sm > li > a,\n.pagination-sm > li > span {\n  padding: 5px 10px;\n  font-size: 12px;\n}\n.pagination-sm > li:first-child > a,\n.pagination-sm > li:first-child > span {\n  border-top-left-radius: 3px;\n  border-bottom-left-radius: 3px;\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.pager {\n  padding-left: 0;\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n}\n.pager li {\n  display: inline;\n}\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  border-radius: 15px;\n}\n.pager li > a:hover,\n.pager li > a:focus {\n  text-decoration: none;\n  background-color: #eee;\n}\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > a:focus,\n.pager .disabled > span {\n  color: #999;\n  cursor: not-allowed;\n  background-color: #fff;\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: #fff;\n  text-align: center;\n  white-space: nowrap;\n  vertical-align: baseline;\n  border-radius: .25em;\n}\n.label[href]:hover,\n.label[href]:focus {\n  color: #fff;\n  text-decoration: none;\n  cursor: pointer;\n}\n.label:empty {\n  display: none;\n}\n.btn .label {\n  position: relative;\n  top: -1px;\n}\n.label-default {\n  background-color: #999;\n}\n.label-default[href]:hover,\n.label-default[href]:focus {\n  background-color: #808080;\n}\n.label-primary {\n  background-color: #428bca;\n}\n.label-primary[href]:hover,\n.label-primary[href]:focus {\n  background-color: #3071a9;\n}\n.label-success {\n  background-color: #5cb85c;\n}\n.label-success[href]:hover,\n.label-success[href]:focus {\n  background-color: #449d44;\n}\n.label-info {\n  background-color: #5bc0de;\n}\n.label-info[href]:hover,\n.label-info[href]:focus {\n  background-color: #31b0d5;\n}\n.label-warning {\n  background-color: #f0ad4e;\n}\n.label-warning[href]:hover,\n.label-warning[href]:focus {\n  background-color: #ec971f;\n}\n.label-danger {\n  background-color: #d9534f;\n}\n.label-danger[href]:hover,\n.label-danger[href]:focus {\n  background-color: #c9302c;\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: #fff;\n  text-align: center;\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999;\n  border-radius: 10px;\n}\n.badge:empty {\n  display: none;\n}\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n.btn-xs .badge {\n  top: 0;\n  padding: 1px 5px;\n}\na.badge:hover,\na.badge:focus {\n  color: #fff;\n  text-decoration: none;\n  cursor: pointer;\n}\na.list-group-item.active > .badge,\n.nav-pills > .active > a > .badge {\n  color: #428bca;\n  background-color: #fff;\n}\n.nav-pills > li > a > .badge {\n  margin-left: 3px;\n}\n.jumbotron {\n  padding: 30px;\n  margin-bottom: 30px;\n  color: inherit;\n  background-color: #eee;\n}\n.jumbotron h1,\n.jumbotron .h1 {\n  color: inherit;\n}\n.jumbotron p {\n  margin-bottom: 15px;\n  font-size: 21px;\n  font-weight: 200;\n}\n.container .jumbotron {\n  border-radius: 6px;\n}\n.jumbotron .container {\n  max-width: 100%;\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  .jumbotron .h1 {\n    font-size: 63px;\n  }\n}\n.thumbnail {\n  display: block;\n  padding: 4px;\n  margin-bottom: 20px;\n  line-height: 1.42857143;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  border-radius: 4px;\n  -webkit-transition: all .2s ease-in-out;\n          transition: all .2s ease-in-out;\n}\n.thumbnail > img,\n.thumbnail a > img {\n  margin-right: auto;\n  margin-left: auto;\n}\na.thumbnail:hover,\na.thumbnail:focus,\na.thumbnail.active {\n  border-color: #428bca;\n}\n.thumbnail .caption {\n  padding: 9px;\n  color: #333;\n}\n.alert {\n  padding: 15px;\n  margin-bottom: 20px;\n  border: 1px solid transparent;\n  border-radius: 4px;\n}\n.alert h4 {\n  margin-top: 0;\n  color: inherit;\n}\n.alert .alert-link {\n  font-weight: bold;\n}\n.alert > p,\n.alert > ul {\n  margin-bottom: 0;\n}\n.alert > p + p {\n  margin-top: 5px;\n}\n.alert-dismissable {\n  padding-right: 35px;\n}\n.alert-dismissable .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  color: inherit;\n}\n.alert-success {\n  color: #3c763d;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n.alert-success hr {\n  border-top-color: #c9e2b3;\n}\n.alert-success .alert-link {\n  color: #2b542c;\n}\n.alert-info {\n  color: #31708f;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n.alert-info hr {\n  border-top-color: #a6e1ec;\n}\n.alert-info .alert-link {\n  color: #245269;\n}\n.alert-warning {\n  color: #8a6d3b;\n  background-color: #fcf8e3;\n  border-color: #faebcc;\n}\n.alert-warning hr {\n  border-top-color: #f7e1b5;\n}\n.alert-warning .alert-link {\n  color: #66512c;\n}\n.alert-danger {\n  color: #a94442;\n  background-color: #f2dede;\n  border-color: #ebccd1;\n}\n.alert-danger hr {\n  border-top-color: #e4b9c0;\n}\n.alert-danger .alert-link {\n  color: #843534;\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@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\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, .1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1);\n}\n.progress-bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  line-height: 20px;\n  color: #fff;\n  text-align: center;\n  background-color: #428bca;\n  -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          transition: width .6s ease;\n}\n.progress-striped .progress-bar {\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n  background-image:         linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n  background-size: 40px 40px;\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.progress-bar-success {\n  background-color: #5cb85c;\n}\n.progress-striped .progress-bar-success {\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n  background-image:         linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n}\n.progress-bar-info {\n  background-color: #5bc0de;\n}\n.progress-striped .progress-bar-info {\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n  background-image:         linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n}\n.progress-bar-warning {\n  background-color: #f0ad4e;\n}\n.progress-striped .progress-bar-warning {\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n  background-image:         linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n}\n.progress-bar-danger {\n  background-color: #d9534f;\n}\n.progress-striped .progress-bar-danger {\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n  background-image:         linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n}\n.media,\n.media-body {\n  overflow: hidden;\n  zoom: 1;\n}\n.media,\n.media .media {\n  margin-top: 15px;\n}\n.media:first-child {\n  margin-top: 0;\n}\n.media-object {\n  display: block;\n}\n.media-heading {\n  margin: 0 0 5px;\n}\n.media > .pull-left {\n  margin-right: 10px;\n}\n.media > .pull-right {\n  margin-left: 10px;\n}\n.media-list {\n  padding-left: 0;\n  list-style: none;\n}\n.list-group {\n  padding-left: 0;\n  margin-bottom: 20px;\n}\n.list-group-item {\n  position: relative;\n  display: block;\n  padding: 10px 15px;\n  margin-bottom: -1px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n}\n.list-group-item:first-child {\n  border-top-left-radius: 4px;\n  border-top-right-radius: 4px;\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.list-group-item > .badge {\n  float: right;\n}\n.list-group-item > .badge + .badge {\n  margin-right: 5px;\n}\na.list-group-item {\n  color: #555;\n}\na.list-group-item .list-group-item-heading {\n  color: #333;\n}\na.list-group-item:hover,\na.list-group-item:focus {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\na.list-group-item.active,\na.list-group-item.active:hover,\na.list-group-item.active:focus {\n  z-index: 2;\n  color: #fff;\n  background-color: #428bca;\n  border-color: #428bca;\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}\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.list-group-item-success {\n  color: #3c763d;\n  background-color: #dff0d8;\n}\na.list-group-item-success {\n  color: #3c763d;\n}\na.list-group-item-success .list-group-item-heading {\n  color: inherit;\n}\na.list-group-item-success:hover,\na.list-group-item-success:focus {\n  color: #3c763d;\n  background-color: #d0e9c6;\n}\na.list-group-item-success.active,\na.list-group-item-success.active:hover,\na.list-group-item-success.active:focus {\n  color: #fff;\n  background-color: #3c763d;\n  border-color: #3c763d;\n}\n.list-group-item-info {\n  color: #31708f;\n  background-color: #d9edf7;\n}\na.list-group-item-info {\n  color: #31708f;\n}\na.list-group-item-info .list-group-item-heading {\n  color: inherit;\n}\na.list-group-item-info:hover,\na.list-group-item-info:focus {\n  color: #31708f;\n  background-color: #c4e3f3;\n}\na.list-group-item-info.active,\na.list-group-item-info.active:hover,\na.list-group-item-info.active:focus {\n  color: #fff;\n  background-color: #31708f;\n  border-color: #31708f;\n}\n.list-group-item-warning {\n  color: #8a6d3b;\n  background-color: #fcf8e3;\n}\na.list-group-item-warning {\n  color: #8a6d3b;\n}\na.list-group-item-warning .list-group-item-heading {\n  color: inherit;\n}\na.list-group-item-warning:hover,\na.list-group-item-warning:focus {\n  color: #8a6d3b;\n  background-color: #faf2cc;\n}\na.list-group-item-warning.active,\na.list-group-item-warning.active:hover,\na.list-group-item-warning.active:focus {\n  color: #fff;\n  background-color: #8a6d3b;\n  border-color: #8a6d3b;\n}\n.list-group-item-danger {\n  color: #a94442;\n  background-color: #f2dede;\n}\na.list-group-item-danger {\n  color: #a94442;\n}\na.list-group-item-danger .list-group-item-heading {\n  color: inherit;\n}\na.list-group-item-danger:hover,\na.list-group-item-danger:focus {\n  color: #a94442;\n  background-color: #ebcccc;\n}\na.list-group-item-danger.active,\na.list-group-item-danger.active:hover,\na.list-group-item-danger.active:focus {\n  color: #fff;\n  background-color: #a94442;\n  border-color: #a94442;\n}\n.list-group-item-heading {\n  margin-top: 0;\n  margin-bottom: 5px;\n}\n.list-group-item-text {\n  margin-bottom: 0;\n  line-height: 1.3;\n}\n.panel {\n  margin-bottom: 20px;\n  background-color: #fff;\n  border: 1px solid transparent;\n  border-radius: 4px;\n  -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05);\n          box-shadow: 0 1px 1px rgba(0, 0, 0, .05);\n}\n.panel-body {\n  padding: 15px;\n}\n.panel-heading {\n  padding: 10px 15px;\n  border-bottom: 1px solid transparent;\n  border-top-left-radius: 3px;\n  border-top-right-radius: 3px;\n}\n.panel-heading > .dropdown .dropdown-toggle {\n  color: inherit;\n}\n.panel-title {\n  margin-top: 0;\n  margin-bottom: 0;\n  font-size: 16px;\n  color: inherit;\n}\n.panel-title > a {\n  color: inherit;\n}\n.panel-footer {\n  padding: 10px 15px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  border-bottom-right-radius: 3px;\n  border-bottom-left-radius: 3px;\n}\n.panel > .list-group {\n  margin-bottom: 0;\n}\n.panel > .list-group .list-group-item {\n  border-width: 1px 0;\n  border-radius: 0;\n}\n.panel > .list-group:first-child .list-group-item:first-child {\n  border-top: 0;\n  border-top-left-radius: 3px;\n  border-top-right-radius: 3px;\n}\n.panel > .list-group:last-child .list-group-item:last-child {\n  border-bottom: 0;\n  border-bottom-right-radius: 3px;\n  border-bottom-left-radius: 3px;\n}\n.panel-heading + .list-group .list-group-item:first-child {\n  border-top-width: 0;\n}\n.panel > .table,\n.panel > .table-responsive > .table {\n  margin-bottom: 0;\n}\n.panel > .table:first-child,\n.panel > .table-responsive:first-child > .table:first-child {\n  border-top-left-radius: 3px;\n  border-top-right-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child {\n  border-top-left-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child {\n  border-top-right-radius: 3px;\n}\n.panel > .table:last-child,\n.panel > .table-responsive:last-child > .table:last-child {\n  border-bottom-right-radius: 3px;\n  border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child {\n  border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child {\n  border-bottom-right-radius: 3px;\n}\n.panel > .panel-body + .table,\n.panel > .panel-body + .table-responsive {\n  border-top: 1px solid #ddd;\n}\n.panel > .table > tbody:first-child > tr:first-child th,\n.panel > .table > tbody:first-child > tr:first-child td {\n  border-top: 0;\n}\n.panel > .table-bordered,\n.panel > .table-responsive > .table-bordered {\n  border: 0;\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.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.panel > .table-bordered > thead > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > td,\n.panel > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-bordered > thead > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > th,\n.panel > .table-bordered > tbody > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th {\n  border-bottom: 0;\n}\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.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  border-bottom: 0;\n}\n.panel > .table-responsive {\n  margin-bottom: 0;\n  border: 0;\n}\n.panel-group {\n  margin-bottom: 20px;\n}\n.panel-group .panel {\n  margin-bottom: 0;\n  overflow: hidden;\n  border-radius: 4px;\n}\n.panel-group .panel + .panel {\n  margin-top: 5px;\n}\n.panel-group .panel-heading {\n  border-bottom: 0;\n}\n.panel-group .panel-heading + .panel-collapse .panel-body {\n  border-top: 1px solid #ddd;\n}\n.panel-group .panel-footer {\n  border-top: 0;\n}\n.panel-group .panel-footer + .panel-collapse .panel-body {\n  border-bottom: 1px solid #ddd;\n}\n.panel-default {\n  border-color: #ddd;\n}\n.panel-default > .panel-heading {\n  color: #333;\n  background-color: #f5f5f5;\n  border-color: #ddd;\n}\n.panel-default > .panel-heading + .panel-collapse .panel-body {\n  border-top-color: #ddd;\n}\n.panel-default > .panel-footer + .panel-collapse .panel-body {\n  border-bottom-color: #ddd;\n}\n.panel-primary {\n  border-color: #428bca;\n}\n.panel-primary > .panel-heading {\n  color: #fff;\n  background-color: #428bca;\n  border-color: #428bca;\n}\n.panel-primary > .panel-heading + .panel-collapse .panel-body {\n  border-top-color: #428bca;\n}\n.panel-primary > .panel-footer + .panel-collapse .panel-body {\n  border-bottom-color: #428bca;\n}\n.panel-success {\n  border-color: #d6e9c6;\n}\n.panel-success > .panel-heading {\n  color: #3c763d;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n.panel-success > .panel-heading + .panel-collapse .panel-body {\n  border-top-color: #d6e9c6;\n}\n.panel-success > .panel-footer + .panel-collapse .panel-body {\n  border-bottom-color: #d6e9c6;\n}\n.panel-info {\n  border-color: #bce8f1;\n}\n.panel-info > .panel-heading {\n  color: #31708f;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n.panel-info > .panel-heading + .panel-collapse .panel-body {\n  border-top-color: #bce8f1;\n}\n.panel-info > .panel-footer + .panel-collapse .panel-body {\n  border-bottom-color: #bce8f1;\n}\n.panel-warning {\n  border-color: #faebcc;\n}\n.panel-warning > .panel-heading {\n  color: #8a6d3b;\n  background-color: #fcf8e3;\n  border-color: #faebcc;\n}\n.panel-warning > .panel-heading + .panel-collapse .panel-body {\n  border-top-color: #faebcc;\n}\n.panel-warning > .panel-footer + .panel-collapse .panel-body {\n  border-bottom-color: #faebcc;\n}\n.panel-danger {\n  border-color: #ebccd1;\n}\n.panel-danger > .panel-heading {\n  color: #a94442;\n  background-color: #f2dede;\n  border-color: #ebccd1;\n}\n.panel-danger > .panel-heading + .panel-collapse .panel-body {\n  border-top-color: #ebccd1;\n}\n.panel-danger > .panel-footer + .panel-collapse .panel-body {\n  border-bottom-color: #ebccd1;\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, .05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05);\n}\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, .15);\n}\n.well-lg {\n  padding: 24px;\n  border-radius: 6px;\n}\n.well-sm {\n  padding: 9px;\n  border-radius: 3px;\n}\n.close {\n  float: right;\n  font-size: 21px;\n  font-weight: bold;\n  line-height: 1;\n  color: #000;\n  text-shadow: 0 1px 0 #fff;\n  filter: alpha(opacity=20);\n  opacity: .2;\n}\n.close:hover,\n.close:focus {\n  color: #000;\n  text-decoration: none;\n  cursor: pointer;\n  filter: alpha(opacity=50);\n  opacity: .5;\n}\nbutton.close {\n  -webkit-appearance: none;\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n}\n.modal-open {\n  overflow: hidden;\n}\n.modal {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1050;\n  display: none;\n  overflow: auto;\n  overflow-y: scroll;\n  -webkit-overflow-scrolling: touch;\n  outline: 0;\n}\n.modal.fade .modal-dialog {\n  -webkit-transition: -webkit-transform .3s ease-out;\n     -moz-transition:    -moz-transform .3s ease-out;\n       -o-transition:      -o-transform .3s ease-out;\n          transition:         transform .3s ease-out;\n  -webkit-transform: translate(0, -25%);\n      -ms-transform: translate(0, -25%);\n          transform: translate(0, -25%);\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.modal-dialog {\n  position: relative;\n  width: auto;\n  margin: 10px;\n}\n.modal-content {\n  position: relative;\n  background-color: #fff;\n  background-clip: padding-box;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, .2);\n  border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5);\n          box-shadow: 0 3px 9px rgba(0, 0, 0, .5);\n}\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000;\n}\n.modal-backdrop.fade {\n  filter: alpha(opacity=0);\n  opacity: 0;\n}\n.modal-backdrop.in {\n  filter: alpha(opacity=50);\n  opacity: .5;\n}\n.modal-header {\n  min-height: 16.42857143px;\n  padding: 15px;\n  border-bottom: 1px solid #e5e5e5;\n}\n.modal-header .close {\n  margin-top: -2px;\n}\n.modal-title {\n  margin: 0;\n  line-height: 1.42857143;\n}\n.modal-body {\n  position: relative;\n  padding: 20px;\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.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n@media (min-width: 768px) {\n  .modal-dialog {\n    width: 600px;\n    margin: 30px auto;\n  }\n  .modal-content {\n    -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5);\n            box-shadow: 0 5px 15px rgba(0, 0, 0, .5);\n  }\n  .modal-sm {\n    width: 300px;\n  }\n}\n@media (min-width: 992px) {\n  .modal-lg {\n    width: 900px;\n  }\n}\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  font-size: 12px;\n  line-height: 1.4;\n  visibility: visible;\n  filter: alpha(opacity=0);\n  opacity: 0;\n}\n.tooltip.in {\n  filter: alpha(opacity=90);\n  opacity: .9;\n}\n.tooltip.top {\n  padding: 5px 0;\n  margin-top: -3px;\n}\n.tooltip.right {\n  padding: 0 5px;\n  margin-left: 3px;\n}\n.tooltip.bottom {\n  padding: 5px 0;\n  margin-top: 3px;\n}\n.tooltip.left {\n  padding: 0 5px;\n  margin-left: -3px;\n}\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #fff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000;\n  border-radius: 4px;\n}\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-width: 5px 5px 0;\n  border-top-color: #000;\n}\n.tooltip.top-left .tooltip-arrow {\n  bottom: 0;\n  left: 5px;\n  border-width: 5px 5px 0;\n  border-top-color: #000;\n}\n.tooltip.top-right .tooltip-arrow {\n  right: 5px;\n  bottom: 0;\n  border-width: 5px 5px 0;\n  border-top-color: #000;\n}\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-width: 5px 5px 5px 0;\n  border-right-color: #000;\n}\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-width: 5px 0 5px 5px;\n  border-left-color: #000;\n}\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-width: 0 5px 5px;\n  border-bottom-color: #000;\n}\n.tooltip.bottom-left .tooltip-arrow {\n  top: 0;\n  left: 5px;\n  border-width: 0 5px 5px;\n  border-bottom-color: #000;\n}\n.tooltip.bottom-right .tooltip-arrow {\n  top: 0;\n  right: 5px;\n  border-width: 0 5px 5px;\n  border-bottom-color: #000;\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: #fff;\n  background-clip: padding-box;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, .2);\n  border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, .2);\n}\n.popover.top {\n  margin-top: -10px;\n}\n.popover.right {\n  margin-left: 10px;\n}\n.popover.bottom {\n  margin-top: 10px;\n}\n.popover.left {\n  margin-left: -10px;\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.popover-content {\n  padding: 9px 14px;\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.popover > .arrow {\n  border-width: 11px;\n}\n.popover > .arrow:after {\n  content: \"\";\n  border-width: 10px;\n}\n.popover.top > .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, .25);\n  border-bottom-width: 0;\n}\n.popover.top > .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  content: \" \";\n  border-top-color: #fff;\n  border-bottom-width: 0;\n}\n.popover.right > .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, .25);\n  border-left-width: 0;\n}\n.popover.right > .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  content: \" \";\n  border-right-color: #fff;\n  border-left-width: 0;\n}\n.popover.bottom > .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-width: 0;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, .25);\n}\n.popover.bottom > .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  content: \" \";\n  border-top-width: 0;\n  border-bottom-color: #fff;\n}\n.popover.left > .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-right-width: 0;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, .25);\n}\n.popover.left > .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  content: \" \";\n  border-right-width: 0;\n  border-left-color: #fff;\n}\n.carousel {\n  position: relative;\n}\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: .6s ease-in-out left;\n          transition: .6s ease-in-out left;\n}\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n  line-height: 1;\n}\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n.carousel-inner > .active {\n  left: 0;\n}\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n.carousel-inner > .next {\n  left: 100%;\n}\n.carousel-inner > .prev {\n  left: -100%;\n}\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n.carousel-inner > .active.left {\n  left: -100%;\n}\n.carousel-inner > .active.right {\n  left: 100%;\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: #fff;\n  text-align: center;\n  text-shadow: 0 1px 2px rgba(0, 0, 0, .6);\n  filter: alpha(opacity=50);\n  opacity: .5;\n}\n.carousel-control.left {\n  background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, .5) 0%), color-stop(rgba(0, 0, 0, .0001) 100%));\n  background-image:         linear-gradient(to right, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);\n  background-repeat: repeat-x;\n}\n.carousel-control.right {\n  right: 0;\n  left: auto;\n  background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, .0001) 0%), color-stop(rgba(0, 0, 0, .5) 100%));\n  background-image:         linear-gradient(to right, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);\n  background-repeat: repeat-x;\n}\n.carousel-control:hover,\n.carousel-control:focus {\n  color: #fff;\n  text-decoration: none;\n  filter: alpha(opacity=90);\n  outline: none;\n  opacity: .9;\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.carousel-control .icon-prev,\n.carousel-control .glyphicon-chevron-left {\n  left: 50%;\n}\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-right {\n  right: 50%;\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.carousel-control .icon-prev:before {\n  content: '\\2039';\n}\n.carousel-control .icon-next:before {\n  content: '\\203a';\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.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 #fff;\n  border-radius: 10px;\n}\n.carousel-indicators .active {\n  width: 12px;\n  height: 12px;\n  margin: 0;\n  background-color: #fff;\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: #fff;\n  text-align: center;\n  text-shadow: 0 1px 2px rgba(0, 0, 0, .6);\n}\n.carousel-caption .btn {\n  text-shadow: none;\n}\n@media screen and (min-width: 768px) {\n  .carousel-control .glyphicon-chevron-left,\n  .carousel-control .glyphicon-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.clearfix:before,\n.clearfix:after,\n.container:before,\n.container:after,\n.container-fluid:before,\n.container-fluid:after,\n.row:before,\n.row:after,\n.form-horizontal .form-group:before,\n.form-horizontal .form-group:after,\n.btn-toolbar:before,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:before,\n.btn-group-vertical > .btn-group:after,\n.nav:before,\n.nav:after,\n.navbar:before,\n.navbar:after,\n.navbar-header:before,\n.navbar-header:after,\n.navbar-collapse:before,\n.navbar-collapse:after,\n.pager:before,\n.pager:after,\n.panel-body:before,\n.panel-body:after,\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  content: \" \";\n}\n.clearfix:after,\n.container:after,\n.container-fluid:after,\n.row:after,\n.form-horizontal .form-group:after,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:after,\n.nav:after,\n.navbar:after,\n.navbar-header:after,\n.navbar-collapse:after,\n.pager:after,\n.panel-body:after,\n.modal-footer:after {\n  clear: both;\n}\n.center-block {\n  display: block;\n  margin-right: auto;\n  margin-left: auto;\n}\n.pull-right {\n  float: right !important;\n}\n.pull-left {\n  float: left !important;\n}\n.hide {\n  display: none !important;\n}\n.show {\n  display: block !important;\n}\n.invisible {\n  visibility: hidden;\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.hidden {\n  display: none !important;\n  visibility: hidden !important;\n}\n.affix {\n  position: fixed;\n}\n@-ms-viewport {\n  width: device-width;\n}\n.visible-xs,\n.visible-sm,\n.visible-md,\n.visible-lg {\n  display: none !important;\n}\n@media (max-width: 767px) {\n  .visible-xs {\n    display: block !important;\n  }\n  table.visible-xs {\n    display: table;\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@media (min-width: 768px) and (max-width: 991px) {\n  .visible-sm {\n    display: block !important;\n  }\n  table.visible-sm {\n    display: table;\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@media (min-width: 992px) and (max-width: 1199px) {\n  .visible-md {\n    display: block !important;\n  }\n  table.visible-md {\n    display: table;\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@media (min-width: 1200px) {\n  .visible-lg {\n    display: block !important;\n  }\n  table.visible-lg {\n    display: table;\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@media (max-width: 767px) {\n  .hidden-xs {\n    display: none !important;\n  }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n  .hidden-sm {\n    display: none !important;\n  }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n  .hidden-md {\n    display: none !important;\n  }\n}\n@media (min-width: 1200px) {\n  .hidden-lg {\n    display: none !important;\n  }\n}\n.visible-print {\n  display: none !important;\n}\n@media print {\n  .visible-print {\n    display: block !important;\n  }\n  table.visible-print {\n    display: table;\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}\n@media print {\n  .hidden-print {\n    display: none !important;\n  }\n}\n/*# sourceMappingURL=bootstrap.css.map */\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/bootstrap_3.1.1/js/bootstrap.js",
    "content": "/*!\n * Bootstrap v3.1.1 (http://getbootstrap.com)\n * Copyright 2011-2014 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n\nif (typeof jQuery === 'undefined') { throw new Error('Bootstrap\\'s JavaScript requires jQuery') }\n\n/* ========================================================================\n * Bootstrap: transition.js v3.1.1\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\n\n+function ($) {\n  '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    return false // explicit for ie8 (  ._.)\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.1.1\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\n\n+function ($) {\n  '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.1.1\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\n\n+function ($) {\n  '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    this.isLoading = false\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($.proxy(function () {\n      if (state == 'loadingText') {\n        this.isLoading = true\n        $el.addClass(d).attr(d, d)\n      } else if (this.isLoading) {\n        this.isLoading = false\n        $el.removeClass(d).removeAttr(d)\n      }\n    }, this), 0)\n  }\n\n  Button.prototype.toggle = function () {\n    var changed = true\n    var $parent = this.$element.closest('[data-toggle=\"buttons\"]')\n\n    if ($parent.length) {\n      var $input = this.$element.find('input')\n      if ($input.prop('type') == 'radio') {\n        if ($input.prop('checked') && this.$element.hasClass('active')) changed = false\n        else $parent.find('.active').removeClass('active')\n      }\n      if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change')\n    }\n\n    if (changed) 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.1.1\n * http://getbootstrap.com/javascript/#carousel\n * ========================================================================\n * Copyright 2011-2014 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * ======================================================================== */\n\n\n+function ($) {\n  '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.bs.carousel', 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) {\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    if ($next.hasClass('active')) return this.sliding = false\n\n    var e = $.Event('slide.bs.carousel', { relatedTarget: $next[0], direction: direction })\n    this.$element.trigger(e)\n    if (e.isDefaultPrevented()) return\n\n    this.sliding = true\n\n    isCycling && this.pause()\n\n    if (this.$indicators.length) {\n      this.$indicators.find('.active').removeClass('active')\n      this.$element.one('slid.bs.carousel', 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      $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.bs.carousel') }, 0)\n        })\n        .emulateTransitionEnd($active.css('transition-duration').slice(0, -1) * 1000)\n    } else {\n      $active.removeClass('active')\n      $next.addClass('active')\n      this.sliding = false\n      this.$element.trigger('slid.bs.carousel')\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.1.1\n * http://getbootstrap.com/javascript/#collapse\n * ========================================================================\n * Copyright 2011-2014 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * ======================================================================== */\n\n\n+function ($) {\n  '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('collapse 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 && options.toggle && option == 'show') option = !option\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.1.1\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\n\n+function ($) {\n  '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    $(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 use a backdrop because click events don't delegate\n        $('<div class=\"dropdown-backdrop\"/>').insertAfter($(this)).on('click', clearMenus)\n      }\n\n      var relatedTarget = { relatedTarget: this }\n      $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))\n\n      if (e.isDefaultPrevented()) return\n\n      $parent\n        .toggleClass('open')\n        .trigger('shown.bs.dropdown', relatedTarget)\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 desc = ' li:not(.divider):visible a'\n    var $items = $parent.find('[role=menu]' + desc + ', [role=listbox]' + desc)\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(e) {\n    $(backdrop).remove()\n    $(toggle).each(function () {\n      var $parent = getParent($(this))\n      var relatedTarget = { relatedTarget: this }\n      if (!$parent.hasClass('open')) return\n      $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))\n      if (e.isDefaultPrevented()) return\n      $parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)\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 && /#[A-Za-z]/.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('bs.dropdown')\n\n      if (!data) $this.data('bs.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], [role=listbox]', Dropdown.prototype.keydown)\n\n}(jQuery);\n\n/* ========================================================================\n * Bootstrap: modal.js v3.1.1\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\n\n+function ($) {\n  '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) {\n      this.$element\n        .find('.modal-content')\n        .load(this.options.remote, $.proxy(function () {\n          this.$element.trigger('loaded.bs.modal')\n        }, this))\n    }\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.bs.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\n        .show()\n        .scrollTop(0)\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.bs.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 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.bs.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('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())\n\n    if ($this.is('a')) 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.1.1\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\n\n+function ($) {\n  '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' : 'focusin'\n        var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'\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      var that = this;\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.hoverState = null\n\n      var complete = function() {\n        that.$element.trigger('shown.bs.' + that.type)\n      }\n\n      $.support.transition && this.$tip.hasClass('fade') ?\n        $tip\n          .one($.support.transition.end, complete)\n          .emulateTransitionEnd(150) :\n        complete()\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    // $.fn.offset doesn't round pixel values\n    // so we use setOffset directly with our own function B-0\n    $.offset.setOffset($tip[0], $.extend({\n      using: function (props) {\n        $tip.css({\n          top: Math.round(props.top),\n          left: Math.round(props.left)\n        })\n      }\n    }, offset), 0)\n\n    $tip.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      that.$element.trigger('hidden.bs.' + that.type)\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.hoverState = null\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    clearTimeout(this.timeout)\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 && option == 'destroy') return\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.1.1\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\n\n+function ($) {\n  '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')[ // we use append for html objects to maintain js events\n      this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'\n    ](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 && option == 'destroy') return\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.1.1\n * http://getbootstrap.com/javascript/#scrollspy\n * ========================================================================\n * Copyright 2011-2014 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * ======================================================================== */\n\n\n+function ($) {\n  '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 = /^#./.test(href) && $(href)\n\n        return ($href\n          && $href.length\n          && $href.is(':visible')\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    if (activeTarget && scrollTop <= offsets[0]) {\n      return activeTarget != (i = targets[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      .parentsUntil(this.options.target, '.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.bs.scrollspy')\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.1.1\n * http://getbootstrap.com/javascript/#tabs\n * ========================================================================\n * Copyright 2011-2014 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * ======================================================================== */\n\n\n+function ($) {\n  '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.1.1\n * http://getbootstrap.com/javascript/#affix\n * ========================================================================\n * Copyright 2011-2014 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * ======================================================================== */\n\n\n+function ($) {\n  '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        =\n    this.pinnedOffset = 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.getPinnedOffset = function () {\n    if (this.pinnedOffset) return this.pinnedOffset\n    this.$element.removeClass(Affix.RESET).addClass('affix')\n    var scrollTop = this.$window.scrollTop()\n    var position  = this.$element.offset()\n    return (this.pinnedOffset = position.top - scrollTop)\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 (this.affixed == 'top') position.top += scrollTop\n\n    if (typeof offset != 'object')         offsetBottom = offsetTop = offset\n    if (typeof offsetTop == 'function')    offsetTop    = offset.top(this.$element)\n    if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)\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    var affixType = 'affix' + (affix ? '-' + affix : '')\n    var e         = $.Event(affixType + '.bs.affix')\n\n    this.$element.trigger(e)\n\n    if (e.isDefaultPrevented()) return\n\n    this.affixed = affix\n    this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null\n\n    this.$element\n      .removeClass(Affix.RESET)\n      .addClass(affixType)\n      .trigger($.Event(affixType.replace('affix', 'affixed')))\n\n    if (affix == 'bottom') {\n      this.$element.offset({ top: scrollHeight - 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": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/es5-shim-15.3.4.5/.bower.json",
    "content": "{\n  \"name\": \"es5-shim\",\n  \"homepage\": \"https://github.com/es-shims/es5-shim\",\n  \"version\": \"2.1.0\",\n  \"_release\": \"2.1.0\",\n  \"_resolution\": {\n    \"type\": \"version\",\n    \"tag\": \"v2.1.0\",\n    \"commit\": \"07da727ff7db2a3a25d6bc25d13e374b3bbc99c2\"\n  },\n  \"_source\": \"git://github.com/es-shims/es5-shim.git\",\n  \"_target\": \"~2.1.0\",\n  \"_originalSource\": \"es5-shim\"\n}"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/es5-shim-15.3.4.5/.gitignore",
    "content": "node_modules\n.DS_Store\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/es5-shim-15.3.4.5/CHANGES",
    "content": "\n2.0.0\n - Separate reliable shims from dubious shims (shams).\n\n1.2.10\n - Group-effort Style Cleanup\n - Took a stab at fixing Object.defineProperty on IE8 without\n   bad side-effects. (@hax)\n - Object.isExtensible no longer fakes it. (@xavierm)\n - Date.prototype.toISOString no longer deals with partial\n   ISO dates, per spec (@kitcambridge)\n - More (mostly from @bryanforbes)\n\n1.2.9\n - Corrections to toISOString by @kitcambridge\n - Fixed three bugs in array methods revealed by Jasmine tests.\n - Cleaned up Function.prototype.bind with more fixes and tests from\n   @bryanforbes.\n\n1.2.8\n - Actually fixed problems with Function.prototype.bind, and regressions\n   from 1.2.7 (@bryanforbes, @jdalton #36)\n\n1.2.7 - REGRESSED\n - Fixed problems with Function.prototype.bind when called as a constructor.\n   (@jdalton #36)\n\n1.2.6\n - Revised Date.parse to match ES 5.1 (kitcambridge)\n\n1.2.5\n - Fixed a bug for padding it Date..toISOString (tadfisher issue #33)\n\n1.2.4\n - Fixed a descriptor bug in Object.defineProperty (raynos)\n\n1.2.3\n - Cleaned up RequireJS and <script> boilerplate\n\n1.2.2\n - Changed reduce to follow the letter of the spec with regard to having and\n   owning properties.\n - Fixed a bug where RegExps pass as Functions in some engines in reduce.\n\n1.2.1\n - Adding few fixes to make jshint happy.\n - Fix for issue #12, function expressions can cause scoping issues in IE.\n - NPM will minify on install or when `npm run-script install` is executed.\n - Adding .gitignore to avoid publishing dev dependencies.\n\n1.2.0\n - Making script loadable as AMD module.\n - Adding `indexOf` to the list of safe shims.\n\n1.1.0\n - Added support for accessor properties where possible (which is all browsers\n   except IE).\n - Stop exposing bound function's (that are returned by\n   `Function.prototype.bind`) internal properties (`bound, boundTo, boundArgs`)\n   as in some cases (when using facade objects for example) capabilities of the\n   enclosed functions will be leaked.\n - `Object.create` now explicitly sets `__proto__` property to guarantee\n   correct behavior of `Object.getPrototypeOf`'s on all objects created using\n   `Object.create`.\n - Switched to `===` from `==` where possible as it's slightly faster on older\n   browsers that are target of this lib.\n - Added names to all anonymous functions to have a better stack traces.\n\n1.0.0\n - fixed Date.toISODate, using UTC accessors, as in\n   http://code.google.com/p/v8/source/browse/trunk/src/date.js?r=6120#986\n   (arian)\n\n0.0.4\n - Revised Object.getPrototypeOf to work in more cases\n   in response to http://ejohn.org/blog/objectgetprototypeof/\n   [issue #2] (fschaefer)\n\n0.0.3\n - Fixed typos in Object.keys (samsonjs)\n\n0.0.2\n   Per kangax's recommendations:\n - faster Object.create(null)\n - fixed a function-scope function declaration statement in Object.create\n\n0.0.1\n - fixed Object.create(null), in so far as that's possible\n - reworked Rhino Object.freeze(Function) bug detector and patcher\n\n0.0.0\n - forked from narwhal-lib\n\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/es5-shim-15.3.4.5/CONTRIBUTORS.md",
    "content": "\n-   kriskowal Kris Kowal Copyright (C) 2009-2011 MIT License\n-   tlrobinson Tom Robinson Copyright (C) 2009-2010 MIT License (Narwhal\n    Project)\n-   dantman Daniel Friesen Copyright (C) 2010 XXX TODO License or CLA\n-   fschaefer Florian Schäfer Copyright (C) 2010 MIT License\n-   Gozala Irakli Gozalishvili Copyright (C) 2010 MIT License\n-   kitcambridge Kit Cambridge Copyright (C) 2011 MIT License\n-   kossnocorp Sasha Koss XXX TODO License or CLA\n-   bryanforbes Bryan Forbes XXX TODO License or CLA\n-   killdream Quildreen Motta Copyright (C) 2011 MIT Licence\n-   michaelficarra Michael Ficarra Copyright (C) 2011 3-clause BSD\n    License\n-   sharkbrainguy Gerard Paapu Copyright (C) 2011 MIT License\n-   bbqsrc Brendan Molloy (C) 2011 Creative Commons Zero (public domain)\n-   iwyg XXX TODO License or CLA\n-   DomenicDenicola Domenic Denicola Copyright (C) 2011 MIT License\n-   xavierm02 Montillet Xavier Copyright (C) 2011 MIT License\n-   Raynos Jake Verbaten Copyright (C) 2011 MIT Licence\n-   samsonjs Sami Samhuri Copyright (C) 2010 MIT License\n-   rwldrn Rick Waldron Copyright (C) 2011 MIT License\n-   lexer Alexey Zakharov XXX TODO License or CLA\n-   280 North Inc. (Now Motorola LLC, a subsidiary of Google Inc.)\n    Copyright (C) 2009 MIT License\n-   Steven Levithan Copyright (C) 2012 MIT License\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/es5-shim-15.3.4.5/LICENSE",
    "content": "\nCopyright 2009, 2010 Kristopher Michael Kowal. All rights reserved.\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to\ndeal in the Software without restriction, including without limitation the\nrights to use, copy, modify, merge, publish, distribute, sublicense, and/or\nsell copies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\nIN THE SOFTWARE.\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/es5-shim-15.3.4.5/README.md",
    "content": "\n`es5-shim.js` and `es5-shim.min.js` monkey-patch a JavaScript context to\ncontain all EcmaScript 5 methods that can be faithfully emulated with a\nlegacy JavaScript engine.\n\n`es5-sham.js` and `es5-sham.min.js` monkey-patch other ES5 methods as\nclosely as possible.  For these methods, as closely as possible to ES5\nis not very close.  Many of these shams are intended only to allow code\nto be written to ES5 without causing run-time errors in older engines.\nIn many cases, this means that these shams cause many ES5 methods to\nsilently fail.  Decide carefully whether this is what you want.\n\n\n## Tests\n\nThe tests are written with the Jasmine BDD test framework.\nTo run the tests, navigate to <root-folder>/tests/. \n\nIn order to run against the shim-code, the tests attempt to kill the current \nimplementation of the missing methods. This happens in <root-folder>/tests/helpers/h-kill.js.\nSo in order to run the tests against the built-in methods, invalidate that file somehow\n(comment-out, delete the file, delete the script-tag, etc.).\n\n## Shims\n\n### Complete tests ###\n\n* Array.prototype.every\n* Array.prototype.filter\n* Array.prototype.forEach\n* Array.prototype.indexOf\n* Array.prototype.lastIndexOf\n* Array.prototype.map\n* Array.prototype.some\n* Array.prototype.reduce\n* Array.prototype.reduceRight\n* Array.isArray\n* Date.now\n* Date.prototype.toJSON\n* Function.prototype.bind\n    * /!\\ Caveat: the bound function's length is always 0.\n    * /!\\ Caveat: the bound function has a prototype property.\n    * /!\\ Caveat: bound functions do not try too hard to keep you\n      from manipulating their ``arguments`` and ``caller`` properties.\n    * /!\\ Caveat: bound functions don't have checks in ``call`` and\n      ``apply`` to avoid executing as a constructor.\n* Object.keys\n* String.prototype.trim\n\n### Untested ###\n\n* Date.parse (for ISO parsing)\n* Date.prototype.toISOString\n\n## Shams\n\n* /?\\ Object.create\n\n    For the case of simply \"begetting\" an object that\n    inherits prototypically from another, this should work\n    fine across legacy engines.\n\n    /!\\ Object.create(null) will work only in browsers that\n    support prototype assignment.  This creates an object\n    that does not have any properties inherited from\n    Object.prototype.  It will silently fail otherwise.\n\n    /!\\ The second argument is passed to\n    Object.defineProperties which will probably fail\n    silently.\n\n* /?\\ Object.getPrototypeOf\n\n    This will return \"undefined\" in some cases.  It uses\n    __proto__ if it's available.  Failing that, it uses\n    constructor.prototype, which depends on the constructor\n    property of the object's prototype having not been\n    replaced.  If your object was created like this, it\n    won't work:\n\n        function Foo() {\n        }\n        Foo.prototype = {};\n\n    Because the prototype reassignment destroys the\n    constructor property.\n\n    This will work for all objects that were created using\n    `Object.create` implemented with this library.\n\n* /!\\ Object.getOwnPropertyNames\n\n    This method uses Object.keys, so it will not be accurate\n    on legacy engines.\n\n* Object.isSealed\n\n    Returns \"false\" in all legacy engines for all objects,\n    which is conveniently guaranteed to be accurate.\n\n* Object.isFrozen\n\n    Returns \"false\" in all legacy engines for all objects,\n    which is conveniently guaranteed to be accurate.\n\n* Object.isExtensible\n\n    Works like a charm, by trying very hard to extend the\n    object then redacting the extension.\n\n### Fail silently\n\n* /!\\ Object.getOwnPropertyDescriptor\n    \n    The behavior of this shim does not conform to ES5.  It\n    should probably not be used at this time, until its\n    behavior has been reviewed and been confirmed to be\n    useful in legacy engines.\n\n* /!\\ Object.defineProperty\n\n    This method will silently fail to set \"writable\",\n    \"enumerable\", and \"configurable\" properties.\n    \n    Providing a getter or setter with \"get\" or \"set\" on a\n    descriptor will silently fail on engines that lack\n    \"__defineGetter__\" and \"__defineSetter__\", which include\n    all versions of IE up to version 8 so far.\n\n    IE 8 provides a version of this method but it only works\n    on DOM objects.  Thus, the shim will not get installed\n    and attempts to set \"value\" properties will fail\n    silently on non-DOM objects.\n\n    https://github.com/kriskowal/es5-shim/issues#issue/5\n\n* /!\\ Object.defineProperties\n\n    This uses the Object.defineProperty shim\n\n* Object.seal\n\n    Silently fails on all legacy engines.  This should be\n    fine unless you are depending on the safety and security\n    provisions of this method, which you cannot possibly\n    obtain in legacy engines.\n\n* Object.freeze\n\n    Silently fails on all legacy engines.  This should be\n    fine unless you are depending on the safety and security\n    provisions of this method, which you cannot possibly\n    obtain in legacy engines.\n\n* Object.preventExtensions\n\n    Silently fails on all legacy engines.  This should be\n    fine unless you are depending on the safety and security\n    provisions of this method, which you cannot possibly\n    obtain in legacy engines.\n\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/es5-shim-15.3.4.5/es5-sham.js",
    "content": "// Copyright 2009-2012 by contributors, MIT License\n// vim: ts=4 sts=4 sw=4 expandtab\n\n// Module systems magic dance\n(function (definition) {\n    // RequireJS\n    if (typeof define == \"function\") {\n        define(definition);\n    // YUI3\n    } else if (typeof YUI == \"function\") {\n        YUI.add(\"es5-sham\", definition);\n    // CommonJS and <script>\n    } else {\n        definition();\n    }\n})(function () {\n\n\nvar call = Function.prototype.call;\nvar prototypeOfObject = Object.prototype;\nvar owns = call.bind(prototypeOfObject.hasOwnProperty);\n\n// If JS engine supports accessors creating shortcuts.\nvar defineGetter;\nvar defineSetter;\nvar lookupGetter;\nvar lookupSetter;\nvar supportsAccessors;\nif ((supportsAccessors = owns(prototypeOfObject, \"__defineGetter__\"))) {\n    defineGetter = call.bind(prototypeOfObject.__defineGetter__);\n    defineSetter = call.bind(prototypeOfObject.__defineSetter__);\n    lookupGetter = call.bind(prototypeOfObject.__lookupGetter__);\n    lookupSetter = call.bind(prototypeOfObject.__lookupSetter__);\n}\n\n// ES5 15.2.3.2\n// http://es5.github.com/#x15.2.3.2\nif (!Object.getPrototypeOf) {\n    // https://github.com/kriskowal/es5-shim/issues#issue/2\n    // http://ejohn.org/blog/objectgetprototypeof/\n    // recommended by fschaefer on github\n    Object.getPrototypeOf = function getPrototypeOf(object) {\n        return object.__proto__ || (\n            object.constructor\n                ? object.constructor.prototype\n                : prototypeOfObject\n        );\n    };\n}\n\n//ES5 15.2.3.3\n//http://es5.github.com/#x15.2.3.3\n\nfunction doesGetOwnPropertyDescriptorWork(object) {\n    try {\n        object.sentinel = 0;\n        return Object.getOwnPropertyDescriptor(\n                object,\n                \"sentinel\"\n        ).value === 0;\n    } catch (exception) {\n        // returns falsy\n    }\n}\n\n//check whether getOwnPropertyDescriptor works if it's given. Otherwise,\n//shim partially.\nif (Object.defineProperty) {\n    var getOwnPropertyDescriptorWorksOnObject = \n        doesGetOwnPropertyDescriptorWork({});\n    var getOwnPropertyDescriptorWorksOnDom = typeof document == \"undefined\" ||\n    doesGetOwnPropertyDescriptorWork(document.createElement(\"div\"));\n    if (!getOwnPropertyDescriptorWorksOnDom || \n            !getOwnPropertyDescriptorWorksOnObject\n    ) {\n        var getOwnPropertyDescriptorFallback = Object.getOwnPropertyDescriptor;\n    }\n}\n\nif (!Object.getOwnPropertyDescriptor || getOwnPropertyDescriptorFallback) {\n    var ERR_NON_OBJECT = \"Object.getOwnPropertyDescriptor called on a non-object: \";\n\n    Object.getOwnPropertyDescriptor = function getOwnPropertyDescriptor(object, property) {\n        if ((typeof object != \"object\" && typeof object != \"function\") || object === null) {\n            throw new TypeError(ERR_NON_OBJECT + object);\n        }\n\n        // make a valiant attempt to use the real getOwnPropertyDescriptor\n        // for I8's DOM elements.\n        if (getOwnPropertyDescriptorFallback) {\n            try {\n                return getOwnPropertyDescriptorFallback.call(Object, object, property);\n            } catch (exception) {\n                // try the shim if the real one doesn't work\n            }\n        }\n\n        // If object does not owns property return undefined immediately.\n        if (!owns(object, property)) {\n            return;\n        }\n\n        // If object has a property then it's for sure both `enumerable` and\n        // `configurable`.\n        var descriptor =  { enumerable: true, configurable: true };\n\n        // If JS engine supports accessor properties then property may be a\n        // getter or setter.\n        if (supportsAccessors) {\n            // Unfortunately `__lookupGetter__` will return a getter even\n            // if object has own non getter property along with a same named\n            // inherited getter. To avoid misbehavior we temporary remove\n            // `__proto__` so that `__lookupGetter__` will return getter only\n            // if it's owned by an object.\n            var prototype = object.__proto__;\n            object.__proto__ = prototypeOfObject;\n\n            var getter = lookupGetter(object, property);\n            var setter = lookupSetter(object, property);\n\n            // Once we have getter and setter we can put values back.\n            object.__proto__ = prototype;\n\n            if (getter || setter) {\n                if (getter) {\n                    descriptor.get = getter;\n                }\n                if (setter) {\n                    descriptor.set = setter;\n                }\n                // If it was accessor property we're done and return here\n                // in order to avoid adding `value` to the descriptor.\n                return descriptor;\n            }\n        }\n\n        // If we got this far we know that object has an own property that is\n        // not an accessor so we set it as a value and return descriptor.\n        descriptor.value = object[property];\n        descriptor.writable = true;\n        return descriptor;\n    };\n}\n\n// ES5 15.2.3.4\n// http://es5.github.com/#x15.2.3.4\nif (!Object.getOwnPropertyNames) {\n    Object.getOwnPropertyNames = function getOwnPropertyNames(object) {\n        return Object.keys(object);\n    };\n}\n\n// ES5 15.2.3.5\n// http://es5.github.com/#x15.2.3.5\nif (!Object.create) {\n\n    // Contributed by Brandon Benvie, October, 2012\n    var createEmpty;\n    var supportsProto = Object.prototype.__proto__ === null;\n    if (supportsProto || typeof document == 'undefined') {\n        createEmpty = function () {\n            return { \"__proto__\": null };\n        };\n    } else {\n        // In old IE __proto__ can't be used to manually set `null`, nor does\n        // any other method exist to make an object that inherits from nothing,\n        // aside from Object.prototype itself. Instead, create a new global\n        // object and *steal* its Object.prototype and strip it bare. This is\n        // used as the prototype to create nullary objects.\n        createEmpty = function () {\n            var iframe = document.createElement('iframe');\n            var parent = document.body || document.documentElement;\n            iframe.style.display = 'none';\n            parent.appendChild(iframe);\n            iframe.src = 'javascript:';\n            var empty = iframe.contentWindow.Object.prototype;\n            parent.removeChild(iframe);\n            iframe = null;\n            delete empty.constructor;\n            delete empty.hasOwnProperty;\n            delete empty.propertyIsEnumerable;\n            delete empty.isPrototypeOf;\n            delete empty.toLocaleString;\n            delete empty.toString;\n            delete empty.valueOf;\n            empty.__proto__ = null;\n\n            function Empty() {}\n            Empty.prototype = empty;\n            // short-circuit future calls\n            createEmpty = function () {\n                return new Empty();\n            };\n            return new Empty();\n        };\n    }\n\n    Object.create = function create(prototype, properties) {\n\n        var object;\n        function Type() {}  // An empty constructor.\n\n        if (prototype === null) {\n            object = createEmpty();\n        } else {\n            if (typeof prototype !== \"object\" && typeof prototype !== \"function\") {\n                // In the native implementation `parent` can be `null`\n                // OR *any* `instanceof Object`  (Object|Function|Array|RegExp|etc)\n                // Use `typeof` tho, b/c in old IE, DOM elements are not `instanceof Object`\n                // like they are in modern browsers. Using `Object.create` on DOM elements\n                // is...err...probably inappropriate, but the native version allows for it.\n                throw new TypeError(\"Object prototype may only be an Object or null\"); // same msg as Chrome\n            }\n            Type.prototype = prototype;\n            object = new Type();\n            // IE has no built-in implementation of `Object.getPrototypeOf`\n            // neither `__proto__`, but this manually setting `__proto__` will\n            // guarantee that `Object.getPrototypeOf` will work as expected with\n            // objects created using `Object.create`\n            object.__proto__ = prototype;\n        }\n\n        if (properties !== void 0) {\n            Object.defineProperties(object, properties);\n        }\n\n        return object;\n    };\n}\n\n// ES5 15.2.3.6\n// http://es5.github.com/#x15.2.3.6\n\n// Patch for WebKit and IE8 standard mode\n// Designed by hax <hax.github.com>\n// related issue: https://github.com/kriskowal/es5-shim/issues#issue/5\n// IE8 Reference:\n//     http://msdn.microsoft.com/en-us/library/dd282900.aspx\n//     http://msdn.microsoft.com/en-us/library/dd229916.aspx\n// WebKit Bugs:\n//     https://bugs.webkit.org/show_bug.cgi?id=36423\n\nfunction doesDefinePropertyWork(object) {\n    try {\n        Object.defineProperty(object, \"sentinel\", {});\n        return \"sentinel\" in object;\n    } catch (exception) {\n        // returns falsy\n    }\n}\n\n// check whether defineProperty works if it's given. Otherwise,\n// shim partially.\nif (Object.defineProperty) {\n    var definePropertyWorksOnObject = doesDefinePropertyWork({});\n    var definePropertyWorksOnDom = typeof document == \"undefined\" ||\n        doesDefinePropertyWork(document.createElement(\"div\"));\n    if (!definePropertyWorksOnObject || !definePropertyWorksOnDom) {\n        var definePropertyFallback = Object.defineProperty,\n            definePropertiesFallback = Object.defineProperties;\n    }\n}\n\nif (!Object.defineProperty || definePropertyFallback) {\n    var ERR_NON_OBJECT_DESCRIPTOR = \"Property description must be an object: \";\n    var ERR_NON_OBJECT_TARGET = \"Object.defineProperty called on non-object: \"\n    var ERR_ACCESSORS_NOT_SUPPORTED = \"getters & setters can not be defined \" +\n                                      \"on this javascript engine\";\n\n    Object.defineProperty = function defineProperty(object, property, descriptor) {\n        if ((typeof object != \"object\" && typeof object != \"function\") || object === null) {\n            throw new TypeError(ERR_NON_OBJECT_TARGET + object);\n        }\n        if ((typeof descriptor != \"object\" && typeof descriptor != \"function\") || descriptor === null) {\n            throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR + descriptor);\n        }\n        // make a valiant attempt to use the real defineProperty\n        // for I8's DOM elements.\n        if (definePropertyFallback) {\n            try {\n                return definePropertyFallback.call(Object, object, property, descriptor);\n            } catch (exception) {\n                // try the shim if the real one doesn't work\n            }\n        }\n\n        // If it's a data property.\n        if (owns(descriptor, \"value\")) {\n            // fail silently if \"writable\", \"enumerable\", or \"configurable\"\n            // are requested but not supported\n            /*\n            // alternate approach:\n            if ( // can't implement these features; allow false but not true\n                !(owns(descriptor, \"writable\") ? descriptor.writable : true) ||\n                !(owns(descriptor, \"enumerable\") ? descriptor.enumerable : true) ||\n                !(owns(descriptor, \"configurable\") ? descriptor.configurable : true)\n            )\n                throw new RangeError(\n                    \"This implementation of Object.defineProperty does not \" +\n                    \"support configurable, enumerable, or writable.\"\n                );\n            */\n\n            if (supportsAccessors && (lookupGetter(object, property) ||\n                                      lookupSetter(object, property)))\n            {\n                // As accessors are supported only on engines implementing\n                // `__proto__` we can safely override `__proto__` while defining\n                // a property to make sure that we don't hit an inherited\n                // accessor.\n                var prototype = object.__proto__;\n                object.__proto__ = prototypeOfObject;\n                // Deleting a property anyway since getter / setter may be\n                // defined on object itself.\n                delete object[property];\n                object[property] = descriptor.value;\n                // Setting original `__proto__` back now.\n                object.__proto__ = prototype;\n            } else {\n                object[property] = descriptor.value;\n            }\n        } else {\n            if (!supportsAccessors) {\n                throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED);\n            }\n            // If we got that far then getters and setters can be defined !!\n            if (owns(descriptor, \"get\")) {\n                defineGetter(object, property, descriptor.get);\n            }\n            if (owns(descriptor, \"set\")) {\n                defineSetter(object, property, descriptor.set);\n            }\n        }\n        return object;\n    };\n}\n\n// ES5 15.2.3.7\n// http://es5.github.com/#x15.2.3.7\nif (!Object.defineProperties || definePropertiesFallback) {\n    Object.defineProperties = function defineProperties(object, properties) {\n        // make a valiant attempt to use the real defineProperties\n        if (definePropertiesFallback) {\n            try {\n                return definePropertiesFallback.call(Object, object, properties);\n            } catch (exception) {\n                // try the shim if the real one doesn't work\n            }\n        }\n\n        for (var property in properties) {\n            if (owns(properties, property) && property != \"__proto__\") {\n                Object.defineProperty(object, property, properties[property]);\n            }\n        }\n        return object;\n    };\n}\n\n// ES5 15.2.3.8\n// http://es5.github.com/#x15.2.3.8\nif (!Object.seal) {\n    Object.seal = function seal(object) {\n        // this is misleading and breaks feature-detection, but\n        // allows \"securable\" code to \"gracefully\" degrade to working\n        // but insecure code.\n        return object;\n    };\n}\n\n// ES5 15.2.3.9\n// http://es5.github.com/#x15.2.3.9\nif (!Object.freeze) {\n    Object.freeze = function freeze(object) {\n        // this is misleading and breaks feature-detection, but\n        // allows \"securable\" code to \"gracefully\" degrade to working\n        // but insecure code.\n        return object;\n    };\n}\n\n// detect a Rhino bug and patch it\ntry {\n    Object.freeze(function () {});\n} catch (exception) {\n    Object.freeze = (function freeze(freezeObject) {\n        return function freeze(object) {\n            if (typeof object == \"function\") {\n                return object;\n            } else {\n                return freezeObject(object);\n            }\n        };\n    })(Object.freeze);\n}\n\n// ES5 15.2.3.10\n// http://es5.github.com/#x15.2.3.10\nif (!Object.preventExtensions) {\n    Object.preventExtensions = function preventExtensions(object) {\n        // this is misleading and breaks feature-detection, but\n        // allows \"securable\" code to \"gracefully\" degrade to working\n        // but insecure code.\n        return object;\n    };\n}\n\n// ES5 15.2.3.11\n// http://es5.github.com/#x15.2.3.11\nif (!Object.isSealed) {\n    Object.isSealed = function isSealed(object) {\n        return false;\n    };\n}\n\n// ES5 15.2.3.12\n// http://es5.github.com/#x15.2.3.12\nif (!Object.isFrozen) {\n    Object.isFrozen = function isFrozen(object) {\n        return false;\n    };\n}\n\n// ES5 15.2.3.13\n// http://es5.github.com/#x15.2.3.13\nif (!Object.isExtensible) {\n    Object.isExtensible = function isExtensible(object) {\n        // 1. If Type(O) is not Object throw a TypeError exception.\n        if (Object(object) !== object) {\n            throw new TypeError(); // TODO message\n        }\n        // 2. Return the Boolean value of the [[Extensible]] internal property of O.\n        var name = '';\n        while (owns(object, name)) {\n            name += '?';\n        }\n        object[name] = true;\n        var returnValue = owns(object, name);\n        delete object[name];\n        return returnValue;\n    };\n}\n\n});\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/es5-shim-15.3.4.5/es5-shim.js",
    "content": "// Copyright 2009-2012 by contributors, MIT License\n// vim: ts=4 sts=4 sw=4 expandtab\n\n// Module systems magic dance\n(function (definition) {\n    // RequireJS\n    if (typeof define == \"function\") {\n        define(definition);\n    // YUI3\n    } else if (typeof YUI == \"function\") {\n        YUI.add(\"es5\", definition);\n    // CommonJS and <script>\n    } else {\n        definition();\n    }\n})(function () {\n\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//\n// Function\n// ========\n//\n\n// ES-5 15.3.4.5\n// http://es5.github.com/#x15.3.4.5\n\nfunction Empty() {}\n\nif (!Function.prototype.bind) {\n    Function.prototype.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 (typeof target != \"function\") {\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 = 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 = target.apply(\n                    this,\n                    args.concat(_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 target.apply(\n                    that,\n                    args.concat(_Array_slice_.call(arguments))\n                );\n\n            }\n\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        // XXX bound.length is never writable, so don't even try\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        // 17. Set the attributes of the length own property of F to the values\n        //   specified in 15.3.5.1.\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// Shortcut to an often accessed properties, in order to avoid multiple\n// dereference that costs universally.\n// _Please note: Shortcuts are defined after `Function.prototype.bind` as we\n// us it in defining shortcuts.\nvar call = Function.prototype.call;\nvar prototypeOfArray = Array.prototype;\nvar prototypeOfObject = Object.prototype;\nvar _Array_slice_ = prototypeOfArray.slice;\n// Having a toString local variable name breaks in Opera so use _toString.\nvar _toString = call.bind(prototypeOfObject.toString);\nvar owns = call.bind(prototypeOfObject.hasOwnProperty);\n\n// If JS engine supports accessors creating shortcuts.\nvar defineGetter;\nvar defineSetter;\nvar lookupGetter;\nvar lookupSetter;\nvar supportsAccessors;\nif ((supportsAccessors = owns(prototypeOfObject, \"__defineGetter__\"))) {\n    defineGetter = call.bind(prototypeOfObject.__defineGetter__);\n    defineSetter = call.bind(prototypeOfObject.__defineSetter__);\n    lookupGetter = call.bind(prototypeOfObject.__lookupGetter__);\n    lookupSetter = call.bind(prototypeOfObject.__lookupSetter__);\n}\n\n//\n// Array\n// =====\n//\n\n// ES5 15.4.4.12\n// http://es5.github.com/#x15.4.4.12\n// Default value for second param\n// [bugfix, ielt9, old browsers]\n// IE < 9 bug: [1,2].splice(0).join(\"\") == \"\" but should be \"12\"\nif ([1,2].splice(0).length != 2) {\n    var array_splice = Array.prototype.splice;\n\n    if(function() { // test IE < 9 to splice bug - see issue #138\n        function makeArray(l) {\n            var a = [];\n            while (l--) {\n                a.unshift(l)\n            }\n            return a\n        }\n\n        var array = []\n            , lengthBefore\n        ;\n\n        array.splice.bind(array, 0, 0).apply(null, makeArray(20));\n        array.splice.bind(array, 0, 0).apply(null, makeArray(26));\n\n        lengthBefore = array.length; //20\n        array.splice(5, 0, \"XXX\"); // add one element\n\n        if(lengthBefore + 1 == array.length) {\n            return true;// has right splice implementation without bugs\n        }\n        // else {\n        //    IE8 bug\n        // }\n    }()) {//IE 6/7\n        Array.prototype.splice = function(start, deleteCount) {\n            if (!arguments.length) {\n                return [];\n            } else {\n                return array_splice.apply(this, [\n                    start === void 0 ? 0 : start,\n                    deleteCount === void 0 ? (this.length - start) : deleteCount\n                ].concat(_Array_slice_.call(arguments, 2)))\n            }\n        };\n    }\n    else {//IE8\n        Array.prototype.splice = function(start, deleteCount) {\n            var result\n                , args = _Array_slice_.call(arguments, 2)\n                , addElementsCount = args.length\n            ;\n\n            if(!arguments.length) {\n                return [];\n            }\n\n            if(start === void 0) { // default\n                start = 0;\n            }\n            if(deleteCount === void 0) { // default\n                deleteCount = this.length - start;\n            }\n\n            if(addElementsCount > 0) {\n                if(deleteCount <= 0) {\n                    if(start == this.length) { // tiny optimisation #1\n                        this.push.apply(this, args);\n                        return [];\n                    }\n\n                    if(start == 0) { // tiny optimisation #2\n                        this.unshift.apply(this, args);\n                        return [];\n                    }\n                }\n\n                // Array.prototype.splice implementation\n                result = _Array_slice_.call(this, start, start + deleteCount);// delete part\n                args.push.apply(args, _Array_slice_.call(this, start + deleteCount, this.length));// right part\n                args.unshift.apply(args, _Array_slice_.call(this, 0, start));// left part\n\n                // delete all items from this array and replace it to 'left part' + _Array_slice_.call(arguments, 2) + 'right part'\n                args.unshift(0, this.length);\n\n                array_splice.apply(this, args);\n\n                return result;\n            }\n\n            return array_splice.call(this, start, deleteCount);\n        }\n\n    }\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\"\nif ([].unshift(0) != 1) {\n    var array_unshift = Array.prototype.unshift;\n    Array.prototype.unshift = function() {\n        array_unshift.apply(this, arguments);\n        return this.length;\n    };\n}\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\nif (!Array.isArray) {\n    Array.isArray = function isArray(obj) {\n        return _toString(obj) == \"[object Array]\";\n    };\n}\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 util 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)\nvar boxedString = Object(\"a\"),\n    splitString = boxedString[0] != \"a\" || !(0 in boxedString);\n\nif (!Array.prototype.forEach) {\n    Array.prototype.forEach = function forEach(fun /*, thisp*/) {\n        var object = toObject(this),\n            self = splitString && _toString(this) == \"[object String]\" ?\n                this.split(\"\") :\n                object,\n            thisp = arguments[1],\n            i = -1,\n            length = self.length >>> 0;\n\n        // If no callback function or if callback is not a callable function\n        if (_toString(fun) != \"[object Function]\") {\n            throw new TypeError(); // TODO message\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                // context\n                fun.call(thisp, self[i], i, object);\n            }\n        }\n    };\n}\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\nif (!Array.prototype.map) {\n    Array.prototype.map = function map(fun /*, thisp*/) {\n        var object = toObject(this),\n            self = splitString && _toString(this) == \"[object String]\" ?\n                this.split(\"\") :\n                object,\n            length = self.length >>> 0,\n            result = Array(length),\n            thisp = arguments[1];\n\n        // If no callback function or if callback is not a callable function\n        if (_toString(fun) != \"[object Function]\") {\n            throw new TypeError(fun + \" is not a function\");\n        }\n\n        for (var i = 0; i < length; i++) {\n            if (i in self)\n                result[i] = fun.call(thisp, self[i], i, object);\n        }\n        return result;\n    };\n}\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\nif (!Array.prototype.filter) {\n    Array.prototype.filter = function filter(fun /*, thisp */) {\n        var object = toObject(this),\n            self = splitString && _toString(this) == \"[object String]\" ?\n                this.split(\"\") :\n                    object,\n            length = self.length >>> 0,\n            result = [],\n            value,\n            thisp = arguments[1];\n\n        // If no callback function or if callback is not a callable function\n        if (_toString(fun) != \"[object Function]\") {\n            throw new TypeError(fun + \" is not a function\");\n        }\n\n        for (var i = 0; i < length; i++) {\n            if (i in self) {\n                value = self[i];\n                if (fun.call(thisp, value, i, object)) {\n                    result.push(value);\n                }\n            }\n        }\n        return result;\n    };\n}\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\nif (!Array.prototype.every) {\n    Array.prototype.every = function every(fun /*, thisp */) {\n        var object = toObject(this),\n            self = splitString && _toString(this) == \"[object String]\" ?\n                this.split(\"\") :\n                object,\n            length = self.length >>> 0,\n            thisp = arguments[1];\n\n        // If no callback function or if callback is not a callable function\n        if (_toString(fun) != \"[object Function]\") {\n            throw new TypeError(fun + \" is not a function\");\n        }\n\n        for (var i = 0; i < length; i++) {\n            if (i in self && !fun.call(thisp, self[i], i, object)) {\n                return false;\n            }\n        }\n        return true;\n    };\n}\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\nif (!Array.prototype.some) {\n    Array.prototype.some = function some(fun /*, thisp */) {\n        var object = toObject(this),\n            self = splitString && _toString(this) == \"[object String]\" ?\n                this.split(\"\") :\n                object,\n            length = self.length >>> 0,\n            thisp = arguments[1];\n\n        // If no callback function or if callback is not a callable function\n        if (_toString(fun) != \"[object Function]\") {\n            throw new TypeError(fun + \" is not a function\");\n        }\n\n        for (var i = 0; i < length; i++) {\n            if (i in self && fun.call(thisp, self[i], i, object)) {\n                return true;\n            }\n        }\n        return false;\n    };\n}\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\nif (!Array.prototype.reduce) {\n    Array.prototype.reduce = function reduce(fun /*, initial*/) {\n        var object = toObject(this),\n            self = splitString && _toString(this) == \"[object String]\" ?\n                this.split(\"\") :\n                object,\n            length = self.length >>> 0;\n\n        // If no callback function or if callback is not a callable function\n        if (_toString(fun) != \"[object Function]\") {\n            throw new TypeError(fun + \" is not a function\");\n        }\n\n        // no value to return if no initial value and an empty array\n        if (!length && 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 = fun.call(void 0, result, self[i], i, object);\n            }\n        }\n\n        return result;\n    };\n}\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\nif (!Array.prototype.reduceRight) {\n    Array.prototype.reduceRight = function reduceRight(fun /*, initial*/) {\n        var object = toObject(this),\n            self = splitString && _toString(this) == \"[object String]\" ?\n                this.split(\"\") :\n                object,\n            length = self.length >>> 0;\n\n        // If no callback function or if callback is not a callable function\n        if (_toString(fun) != \"[object Function]\") {\n            throw new TypeError(fun + \" is not a function\");\n        }\n\n        // no value to return if no initial value, empty array\n        if (!length && arguments.length == 1) {\n            throw new TypeError(\"reduceRight of empty array with no initial value\");\n        }\n\n        var result, 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 this) {\n                result = fun.call(void 0, result, self[i], i, object);\n            }\n        } while (i--);\n\n        return result;\n    };\n}\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\nif (!Array.prototype.indexOf || ([0, 1].indexOf(1, 2) != -1)) {\n    Array.prototype.indexOf = function indexOf(sought /*, fromIndex */ ) {\n        var self = splitString && _toString(this) == \"[object String]\" ?\n                this.split(\"\") :\n                toObject(this),\n            length = self.length >>> 0;\n\n        if (!length) {\n            return -1;\n        }\n\n        var i = 0;\n        if (arguments.length > 1) {\n            i = toInteger(arguments[1]);\n        }\n\n        // handle negative indices\n        i = i >= 0 ? i : Math.max(0, length + i);\n        for (; i < length; i++) {\n            if (i in self && self[i] === sought) {\n                return i;\n            }\n        }\n        return -1;\n    };\n}\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\nif (!Array.prototype.lastIndexOf || ([0, 1].lastIndexOf(0, -3) != -1)) {\n    Array.prototype.lastIndexOf = function lastIndexOf(sought /*, fromIndex */) {\n        var self = splitString && _toString(this) == \"[object String]\" ?\n                this.split(\"\") :\n                toObject(this),\n            length = self.length >>> 0;\n\n        if (!length) {\n            return -1;\n        }\n        var i = length - 1;\n        if (arguments.length > 1) {\n            i = Math.min(i, 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 && sought === self[i]) {\n                return i;\n            }\n        }\n        return -1;\n    };\n}\n\n//\n// Object\n// ======\n//\n\n// ES5 15.2.3.14\n// http://es5.github.com/#x15.2.3.14\nif (!Object.keys) {\n    // http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation\n    var hasDontEnumBug = true,\n        dontEnums = [\n            \"toString\",\n            \"toLocaleString\",\n            \"valueOf\",\n            \"hasOwnProperty\",\n            \"isPrototypeOf\",\n            \"propertyIsEnumerable\",\n            \"constructor\"\n        ],\n        dontEnumsLength = dontEnums.length;\n\n    for (var key in {\"toString\": null}) {\n        hasDontEnumBug = false;\n    }\n\n    Object.keys = function keys(object) {\n\n        if (\n            (typeof object != \"object\" && typeof object != \"function\") ||\n            object === null\n        ) {\n            throw new TypeError(\"Object.keys called on a non-object\");\n        }\n\n        var keys = [];\n        for (var name in object) {\n            if (owns(object, name)) {\n                keys.push(name);\n            }\n        }\n\n        if (hasDontEnumBug) {\n            for (var i = 0, ii = dontEnumsLength; i < ii; i++) {\n                var dontEnum = dontEnums[i];\n                if (owns(object, dontEnum)) {\n                    keys.push(dontEnum);\n                }\n            }\n        }\n        return keys;\n    };\n\n}\n\n//\n// Date\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.\nvar negativeDate = -62198755200000,\n    negativeYearString = \"-000001\";\nif (\n    !Date.prototype.toISOString ||\n    (new Date(negativeDate).toISOString().indexOf(negativeYearString) === -1)\n) {\n    Date.prototype.toISOString = function toISOString() {\n        var result, length, value, year, month;\n        if (!isFinite(this)) {\n            throw new RangeError(\"Date.prototype.toISOString called on non-finite value.\");\n        }\n\n        year = this.getUTCFullYear();\n\n        month = this.getUTCMonth();\n        // see https://github.com/kriskowal/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        result = [month + 1, this.getUTCDate(),\n            this.getUTCHours(), this.getUTCMinutes(), this.getUTCSeconds()];\n        year = (\n            (year < 0 ? \"-\" : (year > 9999 ? \"+\" : \"\")) +\n            (\"00000\" + Math.abs(year))\n            .slice(0 <= year && year <= 9999 ? -4 : -6)\n        );\n\n        length = result.length;\n        while (length--) {\n            value = result[length];\n            // pad months, days, hours, minutes, and seconds to have two\n            // digits.\n            if (value < 10) {\n                result[length] = \"0\" + value;\n            }\n        }\n        // pad milliseconds to have three digits.\n        return (\n            year + \"-\" + result.slice(0, 2).join(\"-\") +\n            \"T\" + result.slice(2).join(\":\") + \".\" +\n            (\"000\" + this.getUTCMilliseconds()).slice(-3) + \"Z\"\n        );\n    };\n}\n\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).\nvar dateToJSONIsSupported = false;\ntry {\n    dateToJSONIsSupported = (\n        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 () {\n                return true;\n            }\n        })\n    );\n} catch (e) {\n}\nif (!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 toPrimitive(O, hint Number).\n        var o = Object(this),\n            tv = toPrimitive(o),\n            toISO;\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        toISO = o.toISOString;\n        // 5. If IsCallable(toISO) is false, throw a TypeError exception.\n        if (typeof toISO != \"function\") {\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\nif (!Date.parse || \"Date.parse is buggy\") {\n    // XXX global assignment won't work in embeddings that use\n    // an alternate object for the context.\n    Date = (function(NativeDate) {\n\n        // Date.length === 7\n        function Date(Y, M, D, h, m, s, ms) {\n            var length = arguments.length;\n            if (this instanceof NativeDate) {\n                var date = length == 1 && String(Y) === Y ? // isString(Y)\n                    // We explicitly pass it through parse:\n                    new NativeDate(Date.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, s, ms) :\n                    length >= 6 ? new NativeDate(Y, M, D, h, m, s) :\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) :\n                                  new NativeDate();\n                // Prevent mixups with unfixed Date object\n                date.constructor = Date;\n                return date;\n            }\n            return NativeDate.apply(this, arguments);\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 = [\n            0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365\n        ];\n\n        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        // Copy any custom methods a 3rd party library may have added\n        for (var key in NativeDate) {\n            Date[key] = NativeDate[key];\n        }\n\n        // Copy \"native\" methods explicitly; they may be non-enumerable\n        Date.now = NativeDate.now;\n        Date.UTC = NativeDate.UTC;\n        Date.prototype = NativeDate.prototype;\n        Date.prototype.constructor = Date;\n\n        // Upgrade Date.parse to handle simplified ISO 8601 strings\n        Date.parse = 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                    offset = !match[4] || match[8] ?\n                        0 : Number(new NativeDate(1970, 0)),\n                    signOffset = match[9] === \"-\" ? 1 : -1,\n                    hourOffset = Number(match[10] || 0),\n                    minuteOffset = Number(match[11] || 0),\n                    result;\n                if (\n                    hour < (\n                        minute > 0 || second > 0 || millisecond > 0 ?\n                        24 : 25\n                    ) &&\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 < (\n                        dayFromMonth(year, month + 1) -\n                        dayFromMonth(year, month)\n                    )\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 + offset;\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\n        return Date;\n    })(Date);\n}\n\n// ES5 15.9.4.4\n// http://es5.github.com/#x15.9.4.4\nif (!Date.now) {\n    Date.now = function now() {\n        return new Date().getTime();\n    };\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\nif (!Number.prototype.toFixed || (0.00008).toFixed(3) !== '0.000' || (0.9).toFixed(0) === '0' || (1.255).toFixed(2) !== '1.25' || (1000000000000000128).toFixed(0) !== \"1000000000000000128\") {\n    // Hide these variables and functions\n    (function () {\n        var base, size, data, i;\n\n        base = 1e7;\n        size = 6;\n        data = [0, 0, 0, 0, 0, 0];\n\n        function multiply(n, c) {\n            var i = -1;\n            while (++i < size) {\n                c += n * data[i];\n                data[i] = c % base;\n                c = Math.floor(c / base);\n            }\n        }\n\n        function divide(n) {\n            var i = size, c = 0;\n            while (--i >= 0) {\n                c += data[i];\n                data[i] = Math.floor(c / n);\n                c = (c % n) * base;\n            }\n        }\n\n        function toString() {\n            var i = size;\n            var s = '';\n            while (--i >= 0) {\n                if (s !== '' || i === 0 || data[i] !== 0) {\n                    var t = String(data[i]);\n                    if (s === '') {\n                        s = t;\n                    } else {\n                        s += '0000000'.slice(0, 7 - t.length) + t;\n                    }\n                }\n            }\n            return s;\n        }\n\n        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\n        function log(x) {\n            var n = 0;\n            while (x >= 4096) {\n                n += 12;\n                x /= 4096;\n            }\n            while (x >= 2) {\n                n += 1;\n                x /= 2;\n            }\n            return n;\n        }\n\n        Number.prototype.toFixed = function (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 = f !== 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            // Test for NaN\n            if (x !== 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 = log(x * pow(2, 69, 1)) - 69;\n                z = (e < 0 ? x * pow(2, -e, 1) : x / 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                    multiply(0, z);\n                    j = f;\n\n                    while (j >= 7) {\n                        multiply(1e7, 0);\n                        j -= 7;\n                    }\n\n                    multiply(pow(10, j, 1), 0);\n                    j = e - 1;\n\n                    while (j >= 23) {\n                        divide(1 << 23);\n                        j -= 23;\n                    }\n\n                    divide(1 << j);\n                    multiply(1, 1);\n                    divide(2);\n                    m = toString();\n                } else {\n                    multiply(0, z);\n                    multiply(1 << (-e), 0);\n                    m = toString() + '0.00000000000000000000'.slice(2, 2 + f);\n                }\n            }\n\n            if (f > 0) {\n                k = m.length;\n\n                if (k <= f) {\n                    m = s + '0.0000000000000000000'.slice(0, f - k + 2) + m;\n                } else {\n                    m = s + m.slice(0, k - f) + '.' + m.slice(k - f);\n                }\n            } else {\n                m = s + m;\n            }\n\n            return m;\n        }\n    }());\n}\n\n\n//\n// String\n// ======\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\nvar string_split = String.prototype.split;\nif (\n    'ab'.split(/(?:ab)*/).length !== 2 ||\n    '.'.split(/(.?)(.?)/).length !== 4 ||\n    'tesst'.split(/(s)*/)[1] === \"t\" ||\n    ''.split(/.?/).length === 0 ||\n    '.'.split(/()()/).length > 1\n) {\n    (function () {\n        var compliantExecNpcg = /()??/.exec(\"\")[1] === void 0; // NPCG: nonparticipating capturing group\n\n        String.prototype.split = function (separator, limit) {\n            var string = this;\n            if (separator === void 0 && limit === 0)\n                return [];\n\n            // If `separator` is not a regex, use native split\n            if (Object.prototype.toString.call(separator) !== \"[object RegExp]\") {\n                return string_split.apply(this, arguments);\n            }\n\n            var output = [],\n                flags = (separator.ignoreCase ? \"i\" : \"\") +\n                        (separator.multiline  ? \"m\" : \"\") +\n                        (separator.extended   ? \"x\" : \"\") + // Proposed for ES6\n                        (separator.sticky     ? \"y\" : \"\"), // Firefox 3+\n                lastLastIndex = 0,\n                // Make `global` and avoid `lastIndex` issues by working with a copy\n                separator = new RegExp(separator.source, flags + \"g\"),\n                separator2, match, lastIndex, lastLength;\n            string += \"\"; // Type-convert\n            if (!compliantExecNpcg) {\n                // Doesn't need flags gy, but they don't hurt\n                separator2 = new RegExp(\"^\" + separator.source + \"$(?!\\\\s)\", flags);\n            }\n            /* Values for `limit`, per the spec:\n             * If undefined: 4294967295 // Math.pow(2, 32) - 1\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            limit = limit === void 0 ?\n                -1 >>> 0 : // Math.pow(2, 32) - 1\n                limit >>> 0; // ToUint32(limit)\n            while (match = separator.exec(string)) {\n                // `separator.lastIndex` is not reliable cross-browser\n                lastIndex = match.index + match[0].length;\n                if (lastIndex > lastLastIndex) {\n                    output.push(string.slice(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                        match[0].replace(separator2, function () {\n                            for (var i = 1; i < arguments.length - 2; i++) {\n                                if (arguments[i] === void 0) {\n                                    match[i] = void 0;\n                                }\n                            }\n                        });\n                    }\n                    if (match.length > 1 && match.index < string.length) {\n                        Array.prototype.push.apply(output, match.slice(1));\n                    }\n                    lastLength = match[0].length;\n                    lastLastIndex = lastIndex;\n                    if (output.length >= limit) {\n                        break;\n                    }\n                }\n                if (separator.lastIndex === match.index) {\n                    separator.lastIndex++; // Avoid an infinite loop\n                }\n            }\n            if (lastLastIndex === string.length) {\n                if (lastLength || !separator.test(\"\")) {\n                    output.push(\"\");\n                }\n            } else {\n                output.push(string.slice(lastLastIndex));\n            }\n            return output.length > limit ? output.slice(0, limit) : 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    String.prototype.split = function(separator, limit) {\n        if (separator === void 0 && limit === 0) return [];\n        return string_split.apply(this, arguments);\n    }\n}\n\n\n// ECMA-262, 3rd B.2.3\n// Note an ECMAScript standart, 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\nif(\"\".substr && \"0b\".substr(-1) !== \"b\") {\n    var string_substr = String.prototype.substr;\n    /**\n     *  Get the substring of a string\n     *  @param  {integer}  start   where to start the substring\n     *  @param  {integer}  length  how many characters to return\n     *  @return {string}\n     */\n    String.prototype.substr = function(start, length) {\n        return string_substr.call(\n            this,\n            start < 0 ? ((start = this.length + start) < 0 ? 0 : start) : start,\n            length\n        );\n    }\n}\n\n// ES5 15.5.4.20\n// http://es5.github.com/#x15.5.4.20\nvar 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\";\nif (!String.prototype.trim || ws.trim()) {\n    // http://blog.stevenlevithan.com/archives/faster-trim-javascript\n    // http://perfectionkills.com/whitespace-deviations/\n    ws = \"[\" + ws + \"]\";\n    var trimBeginRegexp = new RegExp(\"^\" + ws + ws + \"*\"),\n        trimEndRegexp = new RegExp(ws + ws + \"*$\");\n    String.prototype.trim = function trim() {\n        if (this === void 0 || this === null) {\n            throw new TypeError(\"can't convert \"+this+\" to object\");\n        }\n        return String(this)\n            .replace(trimBeginRegexp, \"\")\n            .replace(trimEndRegexp, \"\");\n    };\n}\n\n//\n// Util\n// ======\n//\n\n// ES5 9.4\n// http://es5.github.com/#x9.4\n// http://jsperf.com/to-integer\n\nfunction toInteger(n) {\n    n = +n;\n    if (n !== n) { // isNaN\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\nfunction isPrimitive(input) {\n    var type = typeof input;\n    return (\n        input === null ||\n        type === \"undefined\" ||\n        type === \"boolean\" ||\n        type === \"number\" ||\n        type === \"string\"\n    );\n}\n\nfunction toPrimitive(input) {\n    var val, valueOf, toString;\n    if (isPrimitive(input)) {\n        return input;\n    }\n    valueOf = input.valueOf;\n    if (typeof valueOf === \"function\") {\n        val = valueOf.call(input);\n        if (isPrimitive(val)) {\n            return val;\n        }\n    }\n    toString = input.toString;\n    if (typeof toString === \"function\") {\n        val = toString.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\nvar 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});\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/es5-shim-15.3.4.5/package.json",
    "content": "{\n  \"name\": \"es5-shim\",\n  \"version\": \"2.1.0\",\n  \"description\": \"ES5 as implementable on previous engines\",\n  \"homepage\": \"http://github.com/kriskowal/es5-shim/\",\n  \"contributors\": [\n    \"Kris Kowal <kris@cixar.com> (http://github.com/kriskowal/)\",\n    \"Sami Samhuri <sami.samhuri@gmail.com> (http://samhuri.net/)\",\n    \"Florian Schäfer <florian.schaefer@gmail.com> (http://github.com/fschaefer)\",\n    \"Irakli Gozalishvili <rfobic@gmail.com> (http://jeditoolkit.com)\",\n    \"Kit Cambridge <kitcambridge@gmail.com> (http://kitcambridge.github.com)\"\n  ],\n  \"bugs\": {\n    \"mail\": \"kris@cixar.com\",\n    \"url\": \"http://github.com/kriskowal/es5-shim/issues\"\n  },\n  \"licenses\": [\n    {\n      \"type\": \"MIT\",\n      \"url\": \"http://github.com/kriskowal/es5-shim/raw/master/LICENSE\"\n    }\n  ],\n  \"main\": \"es5-shim.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"http://github.com/kriskowal/es5-shim.git\"\n  },\n  \"scripts\": {\n    \"minify\": \"uglifyjs es5-shim.js --source-map=es5-shim.map -b ascii_only=true,beautify=false > es5-shim.min.js; uglifyjs es5-sham.js --source-map=es5-sham.map -b ascii_only=true,beautify=false > es5-sham.min.js\"\n  },\n  \"engines\": {\n    \"node\": \">=0.2.0\"\n  }\n}\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/es5-shim-15.3.4.5/tests/helpers/h-kill.js",
    "content": "// This methods allows the killing of built-in functions,\n// so the shim can take over with that implementation\nvar HLP = (function() {\n    \"use strict\";\n    var kill;\n\n    kill = function(_class, methods) {\n        /*if(!Array.isArray(methods))\n            return;*/\n        if(!_class.originals)\n            _class.originals = {};\n\n        for (var i = 0, len = methods.length; i < len; i++) {\n            var obj = methods[i];\n            _class.originals[obj] = _class[obj];\n            delete _class[obj];\n            if (obj in _class) {\n                // try something more aggressive since V8 at least\n                // appears to ignore the delete.\n                _class[obj] = null;\n                if (_class[obj]) {\n                    console.log(\"Couln't overwrite\", obj, \"of\", _class);\n                }\n            }\n        }\n    };\n    return { kill: kill };\n}());\n\nHLP.kill(Function.prototype, [\n    'bind'\n]);\n\nHLP.kill(Array, [\n    'isArray'\n]);\n\nHLP.kill(String.prototype, [\n    \"trim\"\n]);\n\nHLP.kill(Object, [\n    'keys'\n]);\n\nHLP.kill(Number.prototype, [\n    'toFixed'\n]);\n\nHLP.kill(Date, [\n    'now', 'parse'\n]);\n\nHLP.kill(Date.prototype, [\n    \"toJSON\", \"toISOString\"\n]);\n\nHLP.kill(Array.prototype, [\n    'forEach', 'some', 'every',\n    'indexOf', 'lastIndexOf',\n    'map', 'filter',\n    'reduce', 'reduceRight'\n]);\n\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/es5-shim-15.3.4.5/tests/helpers/h-matchers.js",
    "content": "beforeEach(function() {\n    this.addMatchers({\n        toExactlyMatch: function(expected) {\n            var a1, a2,\n                l, i,\n                key,\n                actual = this.actual;\n            \n            var getKeys = function(o) {\n                var a = [];\n                for(key in o) {\n                    if(o.hasOwnProperty(key)) {\n                        a.push(key);\n                    }\n                }\n                return a;\n            }\n            a1 = getKeys(actual);\n            a2 = getKeys(expected);\n            \n            l = a1.length;\n            if(l !== a2.length) {\n                return false;\n            }\n            for(i = 0; i < l; i++) {\n                key = a1[i];\n                expect(key).toEqual(a2[i]);\n                expect(actual[key]).toEqual(expected[key]);\n            }\n            \n            return true;\n        }\n    })\n});\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/es5-shim-15.3.4.5/tests/helpers/h.js",
    "content": "function implement() {\n    throw 'Not implemented';\n}"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/es5-shim-15.3.4.5/tests/index.html",
    "content": "<!DOCTYPE HTML>\n<html>\n<head>\n\t<title>Jasmine Spec Runner</title>\n\n\t<link rel=\"shortcut icon\" type=\"image/png\" href=\"lib/jasmine_favicon.png\">\n\n\t<link rel=\"stylesheet\" type=\"text/css\" href=\"lib/jasmine.css\">\n\t<script type=\"text/javascript\" src=\"lib/jasmine.js\"></script>\n\t<script type=\"text/javascript\" src=\"lib/jasmine-html.js\"></script>\n\t<script type=\"text/javascript\" src=\"lib/json2.js\"></script>\n\n\t<!-- include helper files here... -->\n\t<script src=\"helpers/h.js\"></script>\n\t<script src=\"helpers/h-kill.js\"></script>\n\t<script src=\"helpers/h-matchers.js\"></script>\n\n\t<!-- include source files here... -->\n\t<script src=\"../es5-shim.js\"></script>\n    <script src=\"../es5-sham.js\"></script>\n\n\t<!-- include spec files here... -->\n\t<script src=\"spec/s-array.js\"></script>\n\t<script src=\"spec/s-function.js\"></script>\n\t<script src=\"spec/s-string.js\"></script>\n\t<script src=\"spec/s-object.js\"></script>\n\t<script src=\"spec/s-number.js\"></script>\n\t<script src=\"spec/s-date.js\"></script>\n\n\n\t<script type=\"text/javascript\">\n\t\t(function() {\n\t\t\tvar jasmineEnv = jasmine.getEnv();\n\t\t\tjasmineEnv.updateInterval = 1000;\n\n\t\t\tvar trivialReporter = new jasmine.TrivialReporter();\n\n\t\t\tjasmineEnv.addReporter(trivialReporter);\n\n\t\t\tjasmineEnv.specFilter = function(spec) {\n\t\t\t\treturn trivialReporter.specFilter(spec);\n\t\t\t};\n\n\t\t\tvar currentWindowOnload = window.onload;\n\n\t\t\twindow.onload = function() {\n\t\t\t\tif (currentWindowOnload) {\n\t\t\t\t\tcurrentWindowOnload();\n\t\t\t\t}\n\t\t\t\texecJasmine();\n\t\t\t};\n\n\t\t\tfunction execJasmine() {\n\t\t\t\tjasmineEnv.execute();\n\t\t\t}\n\n\t\t})();\n\t</script>\n\n</head>\n\n<body>\n</body>\n</html>\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/es5-shim-15.3.4.5/tests/index.min.html",
    "content": "<!DOCTYPE HTML>\n<html>\n<head>\n\t<title>Jasmine Spec Runner</title>\n\n\t<link rel=\"shortcut icon\" type=\"image/png\" href=\"lib/jasmine_favicon.png\">\n\n\t<link rel=\"stylesheet\" type=\"text/css\" href=\"lib/jasmine.css\">\n\t<script type=\"text/javascript\" src=\"lib/jasmine.js\"></script>\n\t<script type=\"text/javascript\" src=\"lib/jasmine-html.js\"></script>\n\t<script type=\"text/javascript\" src=\"lib/json2.js\"></script>\n\n\t<!-- include helper files here... -->\n\t<script src=\"helpers/h.js\"></script>\n\t<script src=\"helpers/h-kill.js\"></script>\n\t<script src=\"helpers/h-matchers.js\"></script>\n\n\t<!-- include source files here... -->\n\t<script src=\"../es5-shim.min.js\"></script>\n\n\t<!-- include spec files here... -->\n\t<script src=\"spec/s-array.js\"></script>\n\t<script src=\"spec/s-function.js\"></script>\n\t<script src=\"spec/s-string.js\"></script>\n\t<script src=\"spec/s-object.js\"></script>\n\t<script src=\"spec/s-number.js\"></script>\n\t<script src=\"spec/s-date.js\"></script>\n\n\n\t<script type=\"text/javascript\">\n\t\t(function() {\n\t\t\tvar jasmineEnv = jasmine.getEnv();\n\t\t\tjasmineEnv.updateInterval = 1000;\n\n\t\t\tvar trivialReporter = new jasmine.TrivialReporter();\n\n\t\t\tjasmineEnv.addReporter(trivialReporter);\n\n\t\t\tjasmineEnv.specFilter = function(spec) {\n\t\t\t\treturn trivialReporter.specFilter(spec);\n\t\t\t};\n\n\t\t\tvar currentWindowOnload = window.onload;\n\n\t\t\twindow.onload = function() {\n\t\t\t\tif (currentWindowOnload) {\n\t\t\t\t\tcurrentWindowOnload();\n\t\t\t\t}\n\t\t\t\texecJasmine();\n\t\t\t};\n\n\t\t\tfunction execJasmine() {\n\t\t\t\tjasmineEnv.execute();\n\t\t\t}\n\n\t\t})();\n\t</script>\n\n</head>\n\n<body>\n</body>\n</html>\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/es5-shim-15.3.4.5/tests/lib/jasmine-html.js",
    "content": "jasmine.TrivialReporter = function(doc) {\n  this.document = doc || document;\n  this.suiteDivs = {};\n  this.logRunningSpecs = false;\n};\n\njasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) {\n  var el = document.createElement(type);\n\n  for (var i = 2; i < arguments.length; i++) {\n    var child = arguments[i];\n\n    if (typeof child === 'string') {\n      el.appendChild(document.createTextNode(child));\n    } else {\n      if (child) { el.appendChild(child); }\n    }\n  }\n\n  for (var attr in attrs) {\n    if (attr == \"className\") {\n      el[attr] = attrs[attr];\n    } else {\n      el.setAttribute(attr, attrs[attr]);\n    }\n  }\n\n  return el;\n};\n\njasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) {\n  var showPassed, showSkipped;\n\n  this.outerDiv = this.createDom('div', { className: 'jasmine_reporter' },\n      this.createDom('div', { className: 'banner' },\n        this.createDom('div', { className: 'logo' },\n            this.createDom('span', { className: 'title' }, \"Jasmine\"),\n            this.createDom('span', { className: 'version' }, runner.env.versionString())),\n        this.createDom('div', { className: 'options' },\n            \"Show \",\n            showPassed = this.createDom('input', { id: \"__jasmine_TrivialReporter_showPassed__\", type: 'checkbox' }),\n            this.createDom('label', { \"for\": \"__jasmine_TrivialReporter_showPassed__\" }, \" passed \"),\n            showSkipped = this.createDom('input', { id: \"__jasmine_TrivialReporter_showSkipped__\", type: 'checkbox' }),\n            this.createDom('label', { \"for\": \"__jasmine_TrivialReporter_showSkipped__\" }, \" skipped\")\n            )\n          ),\n\n      this.runnerDiv = this.createDom('div', { className: 'runner running' },\n          this.createDom('a', { className: 'run_spec', href: '?' }, \"run all\"),\n          this.runnerMessageSpan = this.createDom('span', {}, \"Running...\"),\n          this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, \"\"))\n      );\n\n  this.document.body.appendChild(this.outerDiv);\n\n  var suites = runner.suites();\n  for (var i = 0; i < suites.length; i++) {\n    var suite = suites[i];\n    var suiteDiv = this.createDom('div', { className: 'suite' },\n        this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, \"run\"),\n        this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description));\n    this.suiteDivs[suite.id] = suiteDiv;\n    var parentDiv = this.outerDiv;\n    if (suite.parentSuite) {\n      parentDiv = this.suiteDivs[suite.parentSuite.id];\n    }\n    parentDiv.appendChild(suiteDiv);\n  }\n\n  this.startedAt = new Date();\n\n  var self = this;\n  showPassed.onclick = function(evt) {\n    if (showPassed.checked) {\n      self.outerDiv.className += ' show-passed';\n    } else {\n      self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, '');\n    }\n  };\n\n  showSkipped.onclick = function(evt) {\n    if (showSkipped.checked) {\n      self.outerDiv.className += ' show-skipped';\n    } else {\n      self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, '');\n    }\n  };\n};\n\njasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) {\n  var results = runner.results();\n  var className = (results.failedCount > 0) ? \"runner failed\" : \"runner passed\";\n  this.runnerDiv.setAttribute(\"class\", className);\n  //do it twice for IE\n  this.runnerDiv.setAttribute(\"className\", className);\n  var specs = runner.specs();\n  var specCount = 0;\n  for (var i = 0; i < specs.length; i++) {\n    if (this.specFilter(specs[i])) {\n      specCount++;\n    }\n  }\n  var message = \"\" + specCount + \" spec\" + (specCount == 1 ? \"\" : \"s\" ) + \", \" + results.failedCount + \" failure\" + ((results.failedCount == 1) ? \"\" : \"s\");\n  message += \" in \" + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + \"s\";\n  this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild);\n\n  this.finishedAtSpan.appendChild(document.createTextNode(\"Finished at \" + new Date().toString()));\n};\n\njasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) {\n  var results = suite.results();\n  var status = results.passed() ? 'passed' : 'failed';\n  if (results.totalCount === 0) { // todo: change this to check results.skipped\n    status = 'skipped';\n  }\n  this.suiteDivs[suite.id].className += \" \" + status;\n};\n\njasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) {\n  if (this.logRunningSpecs) {\n    this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');\n  }\n};\n\njasmine.TrivialReporter.prototype.reportSpecResults = function(spec) {\n  var results = spec.results();\n  var status = results.passed() ? 'passed' : 'failed';\n  if (results.skipped) {\n    status = 'skipped';\n  }\n  var specDiv = this.createDom('div', { className: 'spec '  + status },\n      this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, \"run\"),\n      this.createDom('a', {\n        className: 'description',\n        href: '?spec=' + encodeURIComponent(spec.getFullName()),\n        title: spec.getFullName()\n      }, spec.description));\n\n\n  var resultItems = results.getItems();\n  var messagesDiv = this.createDom('div', { className: 'messages' });\n  for (var i = 0; i < resultItems.length; i++) {\n    var result = resultItems[i];\n\n    if (result.type == 'log') {\n      messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString()));\n    } else if (result.type == 'expect' && result.passed && !result.passed()) {\n      messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message));\n\n      if (result.trace.stack) {\n        messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack));\n      }\n    }\n  }\n\n  if (messagesDiv.childNodes.length > 0) {\n    specDiv.appendChild(messagesDiv);\n  }\n\n  this.suiteDivs[spec.suite.id].appendChild(specDiv);\n};\n\njasmine.TrivialReporter.prototype.log = function() {\n  var console = jasmine.getGlobal().console;\n  if (console && console.log) {\n    if (console.log.apply) {\n      console.log.apply(console, arguments);\n    } else {\n      console.log(arguments); // ie fix: console.log.apply doesn't exist on ie\n    }\n  }\n};\n\njasmine.TrivialReporter.prototype.getLocation = function() {\n  return this.document.location;\n};\n\njasmine.TrivialReporter.prototype.specFilter = function(spec) {\n  var paramMap = {};\n  var params = this.getLocation().search.substring(1).split('&');\n  for (var i = 0; i < params.length; i++) {\n    var p = params[i].split('=');\n    paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);\n  }\n\n  if (!paramMap.spec) {\n    return true;\n  }\n  return spec.getFullName().indexOf(paramMap.spec) === 0;\n};\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/es5-shim-15.3.4.5/tests/lib/jasmine.css",
    "content": "body {\n  font-family: \"Helvetica Neue Light\", \"Lucida Grande\", \"Calibri\", \"Arial\", sans-serif;\n}\n\n\n.jasmine_reporter a:visited, .jasmine_reporter a {\n  color: #303; \n}\n\n.jasmine_reporter a:hover, .jasmine_reporter a:active {\n  color: blue; \n}\n\n.run_spec {\n  float:right;\n  padding-right: 5px;\n  font-size: .8em;\n  text-decoration: none;\n}\n\n.jasmine_reporter {\n  margin: 0 5px;\n}\n\n.banner {\n  color: #303;\n  background-color: #fef;\n  padding: 5px;\n}\n\n.logo {\n  float: left;\n  font-size: 1.1em;\n  padding-left: 5px;\n}\n\n.logo .version {\n  font-size: .6em;\n  padding-left: 1em;\n}\n\n.runner.running {\n  background-color: yellow;\n}\n\n\n.options {\n  text-align: right;\n  font-size: .8em;\n}\n\n\n\n\n.suite {\n  border: 1px outset gray;\n  margin: 5px 0;\n  padding-left: 1em;\n}\n\n.suite .suite {\n  margin: 5px; \n}\n\n.suite.passed {\n  background-color: #dfd;\n}\n\n.suite.failed {\n  background-color: #fdd;\n}\n\n.spec {\n  margin: 5px;\n  padding-left: 1em;\n  clear: both;\n}\n\n.spec.failed, .spec.passed, .spec.skipped {\n  padding-bottom: 5px;\n  border: 1px solid gray;\n}\n\n.spec.failed {\n  background-color: #fbb;\n  border-color: red;\n}\n\n.spec.passed {\n  background-color: #bfb;\n  border-color: green;\n}\n\n.spec.skipped {\n  background-color: #bbb;\n}\n\n.messages {\n  border-left: 1px dashed gray;\n  padding-left: 1em;\n  padding-right: 1em;\n}\n\n.passed {\n  background-color: #cfc;\n  display: none;\n}\n\n.failed {\n  background-color: #fbb;\n}\n\n.skipped {\n  color: #777;\n  background-color: #eee;\n  display: none;\n}\n\n\n/*.resultMessage {*/\n  /*white-space: pre;*/\n/*}*/\n\n.resultMessage span.result {\n  display: block;\n  line-height: 2em;\n  color: black;\n}\n\n.resultMessage .mismatch {\n  color: black;\n}\n\n.stackTrace {\n  white-space: pre;\n  font-size: .8em;\n  margin-left: 10px;\n  max-height: 5em;\n  overflow: auto;\n  border: 1px inset red;\n  padding: 1em;\n  background: #eef;\n}\n\n.finished-at {\n  padding-left: 1em;\n  font-size: .6em;\n}\n\n.show-passed .passed,\n.show-skipped .skipped {\n  display: block;\n}\n\n\n#jasmine_content {\n  position:fixed;\n  right: 100%;\n}\n\n.runner {\n  border: 1px solid gray;\n  display: block;\n  margin: 5px 0;\n  padding: 2px 0 2px 10px;\n}\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/es5-shim-15.3.4.5/tests/lib/jasmine.js",
    "content": "var isCommonJS = typeof window == \"undefined\";\n\n/**\n * Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework.\n *\n * @namespace\n */\nvar jasmine = {};\nif (isCommonJS) exports.jasmine = jasmine;\n/**\n * @private\n */\njasmine.unimplementedMethod_ = function() {\n  throw new Error(\"unimplemented method\");\n};\n\n/**\n * Use <code>jasmine.undefined</code> instead of <code>undefined</code>, since <code>undefined</code> is just\n * a plain old variable and may be redefined by somebody else.\n *\n * @private\n */\njasmine.undefined = jasmine.___undefined___;\n\n/**\n * Show diagnostic messages in the console if set to true\n *\n */\njasmine.VERBOSE = false;\n\n/**\n * Default interval in milliseconds for event loop yields (e.g. to allow network activity or to refresh the screen with the HTML-based runner). Small values here may result in slow test running. Zero means no updates until all tests have completed.\n *\n */\njasmine.DEFAULT_UPDATE_INTERVAL = 250;\n\n/**\n * Default timeout interval in milliseconds for waitsFor() blocks.\n */\njasmine.DEFAULT_TIMEOUT_INTERVAL = 5000;\n\njasmine.getGlobal = function() {\n  function getGlobal() {\n    return this;\n  }\n\n  return getGlobal();\n};\n\n/**\n * Allows for bound functions to be compared.  Internal use only.\n *\n * @ignore\n * @private\n * @param base {Object} bound 'this' for the function\n * @param name {Function} function to find\n */\njasmine.bindOriginal_ = function(base, name) {\n  var original = base[name];\n  if (original.apply) {\n    return function() {\n      return original.apply(base, arguments);\n    };\n  } else {\n    // IE support\n    return jasmine.getGlobal()[name];\n  }\n};\n\njasmine.setTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'setTimeout');\njasmine.clearTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearTimeout');\njasmine.setInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'setInterval');\njasmine.clearInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearInterval');\n\njasmine.MessageResult = function(values) {\n  this.type = 'log';\n  this.values = values;\n  this.trace = new Error(); // todo: test better\n};\n\njasmine.MessageResult.prototype.toString = function() {\n  var text = \"\";\n  for (var i = 0; i < this.values.length; i++) {\n    if (i > 0) text += \" \";\n    if (jasmine.isString_(this.values[i])) {\n      text += this.values[i];\n    } else {\n      text += jasmine.pp(this.values[i]);\n    }\n  }\n  return text;\n};\n\njasmine.ExpectationResult = function(params) {\n  this.type = 'expect';\n  this.matcherName = params.matcherName;\n  this.passed_ = params.passed;\n  this.expected = params.expected;\n  this.actual = params.actual;\n  this.message = this.passed_ ? 'Passed.' : params.message;\n\n  var trace = (params.trace || new Error(this.message));\n  this.trace = this.passed_ ? '' : trace;\n};\n\njasmine.ExpectationResult.prototype.toString = function () {\n  return this.message;\n};\n\njasmine.ExpectationResult.prototype.passed = function () {\n  return this.passed_;\n};\n\n/**\n * Getter for the Jasmine environment. Ensures one gets created\n */\njasmine.getEnv = function() {\n  var env = jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env();\n  return env;\n};\n\n/**\n * @ignore\n * @private\n * @param value\n * @returns {Boolean}\n */\njasmine.isArray_ = function(value) {\n  return jasmine.isA_(\"Array\", value);\n};\n\n/**\n * @ignore\n * @private\n * @param value\n * @returns {Boolean}\n */\njasmine.isString_ = function(value) {\n  return jasmine.isA_(\"String\", value);\n};\n\n/**\n * @ignore\n * @private\n * @param value\n * @returns {Boolean}\n */\njasmine.isNumber_ = function(value) {\n  return jasmine.isA_(\"Number\", value);\n};\n\n/**\n * @ignore\n * @private\n * @param {String} typeName\n * @param value\n * @returns {Boolean}\n */\njasmine.isA_ = function(typeName, value) {\n  return Object.prototype.toString.apply(value) === '[object ' + typeName + ']';\n};\n\n/**\n * Pretty printer for expecations.  Takes any object and turns it into a human-readable string.\n *\n * @param value {Object} an object to be outputted\n * @returns {String}\n */\njasmine.pp = function(value) {\n  var stringPrettyPrinter = new jasmine.StringPrettyPrinter();\n  stringPrettyPrinter.format(value);\n  return stringPrettyPrinter.string;\n};\n\n/**\n * Returns true if the object is a DOM Node.\n *\n * @param {Object} obj object to check\n * @returns {Boolean}\n */\njasmine.isDomNode = function(obj) {\n  return obj.nodeType > 0;\n};\n\n/**\n * Returns a matchable 'generic' object of the class type.  For use in expecations of type when values don't matter.\n *\n * @example\n * // don't care about which function is passed in, as long as it's a function\n * expect(mySpy).toHaveBeenCalledWith(jasmine.any(Function));\n *\n * @param {Class} clazz\n * @returns matchable object of the type clazz\n */\njasmine.any = function(clazz) {\n  return new jasmine.Matchers.Any(clazz);\n};\n\n/**\n * Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks.\n *\n * Spies should be created in test setup, before expectations.  They can then be checked, using the standard Jasmine\n * expectation syntax. Spies can be checked if they were called or not and what the calling params were.\n *\n * A Spy has the following fields: wasCalled, callCount, mostRecentCall, and argsForCall (see docs).\n *\n * Spies are torn down at the end of every spec.\n *\n * Note: Do <b>not</b> call new jasmine.Spy() directly - a spy must be created using spyOn, jasmine.createSpy or jasmine.createSpyObj.\n *\n * @example\n * // a stub\n * var myStub = jasmine.createSpy('myStub');  // can be used anywhere\n *\n * // spy example\n * var foo = {\n *   not: function(bool) { return !bool; }\n * }\n *\n * // actual foo.not will not be called, execution stops\n * spyOn(foo, 'not');\n\n // foo.not spied upon, execution will continue to implementation\n * spyOn(foo, 'not').andCallThrough();\n *\n * // fake example\n * var foo = {\n *   not: function(bool) { return !bool; }\n * }\n *\n * // foo.not(val) will return val\n * spyOn(foo, 'not').andCallFake(function(value) {return value;});\n *\n * // mock example\n * foo.not(7 == 7);\n * expect(foo.not).toHaveBeenCalled();\n * expect(foo.not).toHaveBeenCalledWith(true);\n *\n * @constructor\n * @see spyOn, jasmine.createSpy, jasmine.createSpyObj\n * @param {String} name\n */\njasmine.Spy = function(name) {\n  /**\n   * The name of the spy, if provided.\n   */\n  this.identity = name || 'unknown';\n  /**\n   *  Is this Object a spy?\n   */\n  this.isSpy = true;\n  /**\n   * The actual function this spy stubs.\n   */\n  this.plan = function() {\n  };\n  /**\n   * Tracking of the most recent call to the spy.\n   * @example\n   * var mySpy = jasmine.createSpy('foo');\n   * mySpy(1, 2);\n   * mySpy.mostRecentCall.args = [1, 2];\n   */\n  this.mostRecentCall = {};\n\n  /**\n   * Holds arguments for each call to the spy, indexed by call count\n   * @example\n   * var mySpy = jasmine.createSpy('foo');\n   * mySpy(1, 2);\n   * mySpy(7, 8);\n   * mySpy.mostRecentCall.args = [7, 8];\n   * mySpy.argsForCall[0] = [1, 2];\n   * mySpy.argsForCall[1] = [7, 8];\n   */\n  this.argsForCall = [];\n  this.calls = [];\n};\n\n/**\n * Tells a spy to call through to the actual implemenatation.\n *\n * @example\n * var foo = {\n *   bar: function() { // do some stuff }\n * }\n *\n * // defining a spy on an existing property: foo.bar\n * spyOn(foo, 'bar').andCallThrough();\n */\njasmine.Spy.prototype.andCallThrough = function() {\n  this.plan = this.originalValue;\n  return this;\n};\n\n/**\n * For setting the return value of a spy.\n *\n * @example\n * // defining a spy from scratch: foo() returns 'baz'\n * var foo = jasmine.createSpy('spy on foo').andReturn('baz');\n *\n * // defining a spy on an existing property: foo.bar() returns 'baz'\n * spyOn(foo, 'bar').andReturn('baz');\n *\n * @param {Object} value\n */\njasmine.Spy.prototype.andReturn = function(value) {\n  this.plan = function() {\n    return value;\n  };\n  return this;\n};\n\n/**\n * For throwing an exception when a spy is called.\n *\n * @example\n * // defining a spy from scratch: foo() throws an exception w/ message 'ouch'\n * var foo = jasmine.createSpy('spy on foo').andThrow('baz');\n *\n * // defining a spy on an existing property: foo.bar() throws an exception w/ message 'ouch'\n * spyOn(foo, 'bar').andThrow('baz');\n *\n * @param {String} exceptionMsg\n */\njasmine.Spy.prototype.andThrow = function(exceptionMsg) {\n  this.plan = function() {\n    throw exceptionMsg;\n  };\n  return this;\n};\n\n/**\n * Calls an alternate implementation when a spy is called.\n *\n * @example\n * var baz = function() {\n *   // do some stuff, return something\n * }\n * // defining a spy from scratch: foo() calls the function baz\n * var foo = jasmine.createSpy('spy on foo').andCall(baz);\n *\n * // defining a spy on an existing property: foo.bar() calls an anonymnous function\n * spyOn(foo, 'bar').andCall(function() { return 'baz';} );\n *\n * @param {Function} fakeFunc\n */\njasmine.Spy.prototype.andCallFake = function(fakeFunc) {\n  this.plan = fakeFunc;\n  return this;\n};\n\n/**\n * Resets all of a spy's the tracking variables so that it can be used again.\n *\n * @example\n * spyOn(foo, 'bar');\n *\n * foo.bar();\n *\n * expect(foo.bar.callCount).toEqual(1);\n *\n * foo.bar.reset();\n *\n * expect(foo.bar.callCount).toEqual(0);\n */\njasmine.Spy.prototype.reset = function() {\n  this.wasCalled = false;\n  this.callCount = 0;\n  this.argsForCall = [];\n  this.calls = [];\n  this.mostRecentCall = {};\n};\n\njasmine.createSpy = function(name) {\n\n  var spyObj = function() {\n    spyObj.wasCalled = true;\n    spyObj.callCount++;\n    var args = jasmine.util.argsToArray(arguments);\n    spyObj.mostRecentCall.object = this;\n    spyObj.mostRecentCall.args = args;\n    spyObj.argsForCall.push(args);\n    spyObj.calls.push({object: this, args: args});\n    return spyObj.plan.apply(this, arguments);\n  };\n\n  var spy = new jasmine.Spy(name);\n\n  for (var prop in spy) {\n    spyObj[prop] = spy[prop];\n  }\n\n  spyObj.reset();\n\n  return spyObj;\n};\n\n/**\n * Determines whether an object is a spy.\n *\n * @param {jasmine.Spy|Object} putativeSpy\n * @returns {Boolean}\n */\njasmine.isSpy = function(putativeSpy) {\n  return putativeSpy && putativeSpy.isSpy;\n};\n\n/**\n * Creates a more complicated spy: an Object that has every property a function that is a spy.  Used for stubbing something\n * large in one call.\n *\n * @param {String} baseName name of spy class\n * @param {Array} methodNames array of names of methods to make spies\n */\njasmine.createSpyObj = function(baseName, methodNames) {\n  if (!jasmine.isArray_(methodNames) || methodNames.length === 0) {\n    throw new Error('createSpyObj requires a non-empty array of method names to create spies for');\n  }\n  var obj = {};\n  for (var i = 0; i < methodNames.length; i++) {\n    obj[methodNames[i]] = jasmine.createSpy(baseName + '.' + methodNames[i]);\n  }\n  return obj;\n};\n\n/**\n * All parameters are pretty-printed and concatenated together, then written to the current spec's output.\n *\n * Be careful not to leave calls to <code>jasmine.log</code> in production code.\n */\njasmine.log = function() {\n  var spec = jasmine.getEnv().currentSpec;\n  spec.log.apply(spec, arguments);\n};\n\n/**\n * Function that installs a spy on an existing object's method name.  Used within a Spec to create a spy.\n *\n * @example\n * // spy example\n * var foo = {\n *   not: function(bool) { return !bool; }\n * }\n * spyOn(foo, 'not'); // actual foo.not will not be called, execution stops\n *\n * @see jasmine.createSpy\n * @param obj\n * @param methodName\n * @returns a Jasmine spy that can be chained with all spy methods\n */\nvar spyOn = function(obj, methodName) {\n  return jasmine.getEnv().currentSpec.spyOn(obj, methodName);\n};\nif (isCommonJS) exports.spyOn = spyOn;\n\n/**\n * Creates a Jasmine spec that will be added to the current suite.\n *\n * // TODO: pending tests\n *\n * @example\n * it('should be true', function() {\n *   expect(true).toEqual(true);\n * });\n *\n * @param {String} desc description of this specification\n * @param {Function} func defines the preconditions and expectations of the spec\n */\nvar it = function(desc, func) {\n  return jasmine.getEnv().it(desc, func);\n};\nif (isCommonJS) exports.it = it;\n\n/**\n * Creates a <em>disabled</em> Jasmine spec.\n *\n * A convenience method that allows existing specs to be disabled temporarily during development.\n *\n * @param {String} desc description of this specification\n * @param {Function} func defines the preconditions and expectations of the spec\n */\nvar xit = function(desc, func) {\n  return jasmine.getEnv().xit(desc, func);\n};\nif (isCommonJS) exports.xit = xit;\n\n/**\n * Starts a chain for a Jasmine expectation.\n *\n * It is passed an Object that is the actual value and should chain to one of the many\n * jasmine.Matchers functions.\n *\n * @param {Object} actual Actual value to test against and expected value\n */\nvar expect = function(actual) {\n  return jasmine.getEnv().currentSpec.expect(actual);\n};\nif (isCommonJS) exports.expect = expect;\n\n/**\n * Defines part of a jasmine spec.  Used in cominbination with waits or waitsFor in asynchrnous specs.\n *\n * @param {Function} func Function that defines part of a jasmine spec.\n */\nvar runs = function(func) {\n  jasmine.getEnv().currentSpec.runs(func);\n};\nif (isCommonJS) exports.runs = runs;\n\n/**\n * Waits a fixed time period before moving to the next block.\n *\n * @deprecated Use waitsFor() instead\n * @param {Number} timeout milliseconds to wait\n */\nvar waits = function(timeout) {\n  jasmine.getEnv().currentSpec.waits(timeout);\n};\nif (isCommonJS) exports.waits = waits;\n\n/**\n * Waits for the latchFunction to return true before proceeding to the next block.\n *\n * @param {Function} latchFunction\n * @param {String} optional_timeoutMessage\n * @param {Number} optional_timeout\n */\nvar waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) {\n  jasmine.getEnv().currentSpec.waitsFor.apply(jasmine.getEnv().currentSpec, arguments);\n};\nif (isCommonJS) exports.waitsFor = waitsFor;\n\n/**\n * A function that is called before each spec in a suite.\n *\n * Used for spec setup, including validating assumptions.\n *\n * @param {Function} beforeEachFunction\n */\nvar beforeEach = function(beforeEachFunction) {\n  jasmine.getEnv().beforeEach(beforeEachFunction);\n};\nif (isCommonJS) exports.beforeEach = beforeEach;\n\n/**\n * A function that is called after each spec in a suite.\n *\n * Used for restoring any state that is hijacked during spec execution.\n *\n * @param {Function} afterEachFunction\n */\nvar afterEach = function(afterEachFunction) {\n  jasmine.getEnv().afterEach(afterEachFunction);\n};\nif (isCommonJS) exports.afterEach = afterEach;\n\n/**\n * Defines a suite of specifications.\n *\n * Stores the description and all defined specs in the Jasmine environment as one suite of specs. Variables declared\n * are accessible by calls to beforeEach, it, and afterEach. Describe blocks can be nested, allowing for specialization\n * of setup in some tests.\n *\n * @example\n * // TODO: a simple suite\n *\n * // TODO: a simple suite with a nested describe block\n *\n * @param {String} description A string, usually the class under test.\n * @param {Function} specDefinitions function that defines several specs.\n */\nvar describe = function(description, specDefinitions) {\n  return jasmine.getEnv().describe(description, specDefinitions);\n};\nif (isCommonJS) exports.describe = describe;\n\n/**\n * Disables a suite of specifications.  Used to disable some suites in a file, or files, temporarily during development.\n *\n * @param {String} description A string, usually the class under test.\n * @param {Function} specDefinitions function that defines several specs.\n */\nvar xdescribe = function(description, specDefinitions) {\n  return jasmine.getEnv().xdescribe(description, specDefinitions);\n};\nif (isCommonJS) exports.xdescribe = xdescribe;\n\n\n// Provide the XMLHttpRequest class for IE 5.x-6.x:\njasmine.XmlHttpRequest = (typeof XMLHttpRequest == \"undefined\") ? function() {\n  function tryIt(f) {\n    try {\n      return f();\n    } catch(e) {\n    }\n    return null;\n  }\n\n  var xhr = tryIt(function() {\n    return new ActiveXObject(\"Msxml2.XMLHTTP.6.0\");\n  }) ||\n    tryIt(function() {\n      return new ActiveXObject(\"Msxml2.XMLHTTP.3.0\");\n    }) ||\n    tryIt(function() {\n      return new ActiveXObject(\"Msxml2.XMLHTTP\");\n    }) ||\n    tryIt(function() {\n      return new ActiveXObject(\"Microsoft.XMLHTTP\");\n    });\n\n  if (!xhr) throw new Error(\"This browser does not support XMLHttpRequest.\");\n\n  return xhr;\n} : XMLHttpRequest;\n/**\n * @namespace\n */\njasmine.util = {};\n\n/**\n * Declare that a child class inherit it's prototype from the parent class.\n *\n * @private\n * @param {Function} childClass\n * @param {Function} parentClass\n */\njasmine.util.inherit = function(childClass, parentClass) {\n  /**\n   * @private\n   */\n  var subclass = function() {\n  };\n  subclass.prototype = parentClass.prototype;\n  childClass.prototype = new subclass();\n};\n\njasmine.util.formatException = function(e) {\n  var lineNumber;\n  if (e.line) {\n    lineNumber = e.line;\n  }\n  else if (e.lineNumber) {\n    lineNumber = e.lineNumber;\n  }\n\n  var file;\n\n  if (e.sourceURL) {\n    file = e.sourceURL;\n  }\n  else if (e.fileName) {\n    file = e.fileName;\n  }\n\n  var message = (e.name && e.message) ? (e.name + ': ' + e.message) : e.toString();\n\n  if (file && lineNumber) {\n    message += ' in ' + file + ' (line ' + lineNumber + ')';\n  }\n\n  return message;\n};\n\njasmine.util.htmlEscape = function(str) {\n  if (!str) return str;\n  return str.replace(/&/g, '&amp;')\n    .replace(/</g, '&lt;')\n    .replace(/>/g, '&gt;');\n};\n\njasmine.util.argsToArray = function(args) {\n  var arrayOfArgs = [];\n  for (var i = 0; i < args.length; i++) arrayOfArgs.push(args[i]);\n  return arrayOfArgs;\n};\n\njasmine.util.extend = function(destination, source) {\n  for (var property in source) destination[property] = source[property];\n  return destination;\n};\n\n/**\n * Environment for Jasmine\n *\n * @constructor\n */\njasmine.Env = function() {\n  this.currentSpec = null;\n  this.currentSuite = null;\n  this.currentRunner_ = new jasmine.Runner(this);\n\n  this.reporter = new jasmine.MultiReporter();\n\n  this.updateInterval = jasmine.DEFAULT_UPDATE_INTERVAL;\n  this.defaultTimeoutInterval = jasmine.DEFAULT_TIMEOUT_INTERVAL;\n  this.lastUpdate = 0;\n  this.specFilter = function() {\n    return true;\n  };\n\n  this.nextSpecId_ = 0;\n  this.nextSuiteId_ = 0;\n  this.equalityTesters_ = [];\n\n  // wrap matchers\n  this.matchersClass = function() {\n    jasmine.Matchers.apply(this, arguments);\n  };\n  jasmine.util.inherit(this.matchersClass, jasmine.Matchers);\n\n  jasmine.Matchers.wrapInto_(jasmine.Matchers.prototype, this.matchersClass);\n};\n\n\njasmine.Env.prototype.setTimeout = jasmine.setTimeout;\njasmine.Env.prototype.clearTimeout = jasmine.clearTimeout;\njasmine.Env.prototype.setInterval = jasmine.setInterval;\njasmine.Env.prototype.clearInterval = jasmine.clearInterval;\n\n/**\n * @returns an object containing jasmine version build info, if set.\n */\njasmine.Env.prototype.version = function () {\n  if (jasmine.version_) {\n    return jasmine.version_;\n  } else {\n    throw new Error('Version not set');\n  }\n};\n\n/**\n * @returns string containing jasmine version build info, if set.\n */\njasmine.Env.prototype.versionString = function() {\n  if (!jasmine.version_) {\n    return \"version unknown\";\n  }\n\n  var version = this.version();\n  var versionString = version.major + \".\" + version.minor + \".\" + version.build;\n  if (version.release_candidate) {\n    versionString += \".rc\" + version.release_candidate\n  }\n  versionString += \" revision \" + version.revision;\n  return versionString;\n};\n\n/**\n * @returns a sequential integer starting at 0\n */\njasmine.Env.prototype.nextSpecId = function () {\n  return this.nextSpecId_++;\n};\n\n/**\n * @returns a sequential integer starting at 0\n */\njasmine.Env.prototype.nextSuiteId = function () {\n  return this.nextSuiteId_++;\n};\n\n/**\n * Register a reporter to receive status updates from Jasmine.\n * @param {jasmine.Reporter} reporter An object which will receive status updates.\n */\njasmine.Env.prototype.addReporter = function(reporter) {\n  this.reporter.addReporter(reporter);\n};\n\njasmine.Env.prototype.execute = function() {\n  this.currentRunner_.execute();\n};\n\njasmine.Env.prototype.describe = function(description, specDefinitions) {\n  var suite = new jasmine.Suite(this, description, specDefinitions, this.currentSuite);\n\n  var parentSuite = this.currentSuite;\n  if (parentSuite) {\n    parentSuite.add(suite);\n  } else {\n    this.currentRunner_.add(suite);\n  }\n\n  this.currentSuite = suite;\n\n  var declarationError = null;\n  try {\n    specDefinitions.call(suite);\n  } catch(e) {\n    declarationError = e;\n  }\n\n  if (declarationError) {\n    this.it(\"encountered a declaration exception\", function() {\n      throw declarationError;\n    });\n  }\n\n  this.currentSuite = parentSuite;\n\n  return suite;\n};\n\njasmine.Env.prototype.beforeEach = function(beforeEachFunction) {\n  if (this.currentSuite) {\n    this.currentSuite.beforeEach(beforeEachFunction);\n  } else {\n    this.currentRunner_.beforeEach(beforeEachFunction);\n  }\n};\n\njasmine.Env.prototype.currentRunner = function () {\n  return this.currentRunner_;\n};\n\njasmine.Env.prototype.afterEach = function(afterEachFunction) {\n  if (this.currentSuite) {\n    this.currentSuite.afterEach(afterEachFunction);\n  } else {\n    this.currentRunner_.afterEach(afterEachFunction);\n  }\n\n};\n\njasmine.Env.prototype.xdescribe = function(desc, specDefinitions) {\n  return {\n    execute: function() {\n    }\n  };\n};\n\njasmine.Env.prototype.it = function(description, func) {\n  var spec = new jasmine.Spec(this, this.currentSuite, description);\n  this.currentSuite.add(spec);\n  this.currentSpec = spec;\n\n  if (func) {\n    spec.runs(func);\n  }\n\n  return spec;\n};\n\njasmine.Env.prototype.xit = function(desc, func) {\n  return {\n    id: this.nextSpecId(),\n    runs: function() {\n    }\n  };\n};\n\njasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchValues) {\n  if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a) {\n    return true;\n  }\n\n  a.__Jasmine_been_here_before__ = b;\n  b.__Jasmine_been_here_before__ = a;\n\n  var hasKey = function(obj, keyName) {\n    return obj !== null && obj[keyName] !== jasmine.undefined;\n  };\n\n  for (var property in b) {\n    if (!hasKey(a, property) && hasKey(b, property)) {\n      mismatchKeys.push(\"expected has key '\" + property + \"', but missing from actual.\");\n    }\n  }\n  for (property in a) {\n    if (!hasKey(b, property) && hasKey(a, property)) {\n      mismatchKeys.push(\"expected missing key '\" + property + \"', but present in actual.\");\n    }\n  }\n  for (property in b) {\n    if (property == '__Jasmine_been_here_before__') continue;\n    if (!this.equals_(a[property], b[property], mismatchKeys, mismatchValues)) {\n      mismatchValues.push(\"'\" + property + \"' was '\" + (b[property] ? jasmine.util.htmlEscape(b[property].toString()) : b[property]) + \"' in expected, but was '\" + (a[property] ? jasmine.util.htmlEscape(a[property].toString()) : a[property]) + \"' in actual.\");\n    }\n  }\n\n  if (jasmine.isArray_(a) && jasmine.isArray_(b) && a.length != b.length) {\n    mismatchValues.push(\"arrays were not the same length\");\n  }\n\n  delete a.__Jasmine_been_here_before__;\n  delete b.__Jasmine_been_here_before__;\n  return (mismatchKeys.length === 0 && mismatchValues.length === 0);\n};\n\njasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) {\n  mismatchKeys = mismatchKeys || [];\n  mismatchValues = mismatchValues || [];\n\n  for (var i = 0; i < this.equalityTesters_.length; i++) {\n    var equalityTester = this.equalityTesters_[i];\n    var result = equalityTester(a, b, this, mismatchKeys, mismatchValues);\n    if (result !== jasmine.undefined) return result;\n  }\n\n  if (a === b) return true;\n\n  if (a === jasmine.undefined || a === null || b === jasmine.undefined || b === null) {\n    return (a == jasmine.undefined && b == jasmine.undefined);\n  }\n\n  if (jasmine.isDomNode(a) && jasmine.isDomNode(b)) {\n    return a === b;\n  }\n\n  if (a instanceof Date && b instanceof Date) {\n    return a.getTime() == b.getTime();\n  }\n\n  if (a instanceof jasmine.Matchers.Any) {\n    return a.matches(b);\n  }\n\n  if (b instanceof jasmine.Matchers.Any) {\n    return b.matches(a);\n  }\n\n  if (jasmine.isString_(a) && jasmine.isString_(b)) {\n    return (a == b);\n  }\n\n  if (jasmine.isNumber_(a) && jasmine.isNumber_(b)) {\n    return (a == b);\n  }\n\n  if (typeof a === \"object\" && typeof b === \"object\") {\n    return this.compareObjects_(a, b, mismatchKeys, mismatchValues);\n  }\n\n  //Straight check\n  return (a === b);\n};\n\njasmine.Env.prototype.contains_ = function(haystack, needle) {\n  if (jasmine.isArray_(haystack)) {\n    for (var i = 0; i < haystack.length; i++) {\n      if (this.equals_(haystack[i], needle)) return true;\n    }\n    return false;\n  }\n  return haystack.indexOf(needle) >= 0;\n};\n\njasmine.Env.prototype.addEqualityTester = function(equalityTester) {\n  this.equalityTesters_.push(equalityTester);\n};\n/** No-op base class for Jasmine reporters.\n *\n * @constructor\n */\njasmine.Reporter = function() {\n};\n\n//noinspection JSUnusedLocalSymbols\njasmine.Reporter.prototype.reportRunnerStarting = function(runner) {\n};\n\n//noinspection JSUnusedLocalSymbols\njasmine.Reporter.prototype.reportRunnerResults = function(runner) {\n};\n\n//noinspection JSUnusedLocalSymbols\njasmine.Reporter.prototype.reportSuiteResults = function(suite) {\n};\n\n//noinspection JSUnusedLocalSymbols\njasmine.Reporter.prototype.reportSpecStarting = function(spec) {\n};\n\n//noinspection JSUnusedLocalSymbols\njasmine.Reporter.prototype.reportSpecResults = function(spec) {\n};\n\n//noinspection JSUnusedLocalSymbols\njasmine.Reporter.prototype.log = function(str) {\n};\n\n/**\n * Blocks are functions with executable code that make up a spec.\n *\n * @constructor\n * @param {jasmine.Env} env\n * @param {Function} func\n * @param {jasmine.Spec} spec\n */\njasmine.Block = function(env, func, spec) {\n  this.env = env;\n  this.func = func;\n  this.spec = spec;\n};\n\njasmine.Block.prototype.execute = function(onComplete) {  \n  try {\n    this.func.apply(this.spec);\n  } catch (e) {\n    this.spec.fail(e);\n  }\n  onComplete();\n};\n/** JavaScript API reporter.\n *\n * @constructor\n */\njasmine.JsApiReporter = function() {\n  this.started = false;\n  this.finished = false;\n  this.suites_ = [];\n  this.results_ = {};\n};\n\njasmine.JsApiReporter.prototype.reportRunnerStarting = function(runner) {\n  this.started = true;\n  var suites = runner.topLevelSuites();\n  for (var i = 0; i < suites.length; i++) {\n    var suite = suites[i];\n    this.suites_.push(this.summarize_(suite));\n  }\n};\n\njasmine.JsApiReporter.prototype.suites = function() {\n  return this.suites_;\n};\n\njasmine.JsApiReporter.prototype.summarize_ = function(suiteOrSpec) {\n  var isSuite = suiteOrSpec instanceof jasmine.Suite;\n  var summary = {\n    id: suiteOrSpec.id,\n    name: suiteOrSpec.description,\n    type: isSuite ? 'suite' : 'spec',\n    children: []\n  };\n  \n  if (isSuite) {\n    var children = suiteOrSpec.children();\n    for (var i = 0; i < children.length; i++) {\n      summary.children.push(this.summarize_(children[i]));\n    }\n  }\n  return summary;\n};\n\njasmine.JsApiReporter.prototype.results = function() {\n  return this.results_;\n};\n\njasmine.JsApiReporter.prototype.resultsForSpec = function(specId) {\n  return this.results_[specId];\n};\n\n//noinspection JSUnusedLocalSymbols\njasmine.JsApiReporter.prototype.reportRunnerResults = function(runner) {\n  this.finished = true;\n};\n\n//noinspection JSUnusedLocalSymbols\njasmine.JsApiReporter.prototype.reportSuiteResults = function(suite) {\n};\n\n//noinspection JSUnusedLocalSymbols\njasmine.JsApiReporter.prototype.reportSpecResults = function(spec) {\n  this.results_[spec.id] = {\n    messages: spec.results().getItems(),\n    result: spec.results().failedCount > 0 ? \"failed\" : \"passed\"\n  };\n};\n\n//noinspection JSUnusedLocalSymbols\njasmine.JsApiReporter.prototype.log = function(str) {\n};\n\njasmine.JsApiReporter.prototype.resultsForSpecs = function(specIds){\n  var results = {};\n  for (var i = 0; i < specIds.length; i++) {\n    var specId = specIds[i];\n    results[specId] = this.summarizeResult_(this.results_[specId]);\n  }\n  return results;\n};\n\njasmine.JsApiReporter.prototype.summarizeResult_ = function(result){\n  var summaryMessages = [];\n  var messagesLength = result.messages.length;\n  for (var messageIndex = 0; messageIndex < messagesLength; messageIndex++) {\n    var resultMessage = result.messages[messageIndex];\n    summaryMessages.push({\n      text: resultMessage.type == 'log' ? resultMessage.toString() : jasmine.undefined,\n      passed: resultMessage.passed ? resultMessage.passed() : true,\n      type: resultMessage.type,\n      message: resultMessage.message,\n      trace: {\n        stack: resultMessage.passed && !resultMessage.passed() ? resultMessage.trace.stack : jasmine.undefined\n      }\n    });\n  }\n\n  return {\n    result : result.result,\n    messages : summaryMessages\n  };\n};\n\n/**\n * @constructor\n * @param {jasmine.Env} env\n * @param actual\n * @param {jasmine.Spec} spec\n */\njasmine.Matchers = function(env, actual, spec, opt_isNot) {\n  this.env = env;\n  this.actual = actual;\n  this.spec = spec;\n  this.isNot = opt_isNot || false;\n  this.reportWasCalled_ = false;\n};\n\n// todo: @deprecated as of Jasmine 0.11, remove soon [xw]\njasmine.Matchers.pp = function(str) {\n  throw new Error(\"jasmine.Matchers.pp() is no longer supported, please use jasmine.pp() instead!\");\n};\n\n// todo: @deprecated Deprecated as of Jasmine 0.10. Rewrite your custom matchers to return true or false. [xw]\njasmine.Matchers.prototype.report = function(result, failing_message, details) {\n  throw new Error(\"As of jasmine 0.11, custom matchers must be implemented differently -- please see jasmine docs\");\n};\n\njasmine.Matchers.wrapInto_ = function(prototype, matchersClass) {\n  for (var methodName in prototype) {\n    if (methodName == 'report') continue;\n    var orig = prototype[methodName];\n    matchersClass.prototype[methodName] = jasmine.Matchers.matcherFn_(methodName, orig);\n  }\n};\n\njasmine.Matchers.matcherFn_ = function(matcherName, matcherFunction) {\n  return function() {\n    var matcherArgs = jasmine.util.argsToArray(arguments);\n    var result = matcherFunction.apply(this, arguments);\n\n    if (this.isNot) {\n      result = !result;\n    }\n\n    if (this.reportWasCalled_) return result;\n\n    var message;\n    if (!result) {\n      if (this.message) {\n        message = this.message.apply(this, arguments);\n        if (jasmine.isArray_(message)) {\n          message = message[this.isNot ? 1 : 0];\n        }\n      } else {\n        var englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); });\n        message = \"Expected \" + jasmine.pp(this.actual) + (this.isNot ? \" not \" : \" \") + englishyPredicate;\n        if (matcherArgs.length > 0) {\n          for (var i = 0; i < matcherArgs.length; i++) {\n            if (i > 0) message += \",\";\n            message += \" \" + jasmine.pp(matcherArgs[i]);\n          }\n        }\n        message += \".\";\n      }\n    }\n    var expectationResult = new jasmine.ExpectationResult({\n      matcherName: matcherName,\n      passed: result,\n      expected: matcherArgs.length > 1 ? matcherArgs : matcherArgs[0],\n      actual: this.actual,\n      message: message\n    });\n    this.spec.addMatcherResult(expectationResult);\n    return jasmine.undefined;\n  };\n};\n\n\n\n\n/**\n * toBe: compares the actual to the expected using ===\n * @param expected\n */\njasmine.Matchers.prototype.toBe = function(expected) {\n  return this.actual === expected;\n};\n\n/**\n * toNotBe: compares the actual to the expected using !==\n * @param expected\n * @deprecated as of 1.0. Use not.toBe() instead.\n */\njasmine.Matchers.prototype.toNotBe = function(expected) {\n  return this.actual !== expected;\n};\n\n/**\n * toEqual: compares the actual to the expected using util sense equality. Handles Objects, Arrays, etc.\n *\n * @param expected\n */\njasmine.Matchers.prototype.toEqual = function(expected) {\n  return this.env.equals_(this.actual, expected);\n};\n\n/**\n * toNotEqual: compares the actual to the expected using the ! of jasmine.Matchers.toEqual\n * @param expected\n * @deprecated as of 1.0. Use not.toNotEqual() instead.\n */\njasmine.Matchers.prototype.toNotEqual = function(expected) {\n  return !this.env.equals_(this.actual, expected);\n};\n\n/**\n * Matcher that compares the actual to the expected using a regular expression.  Constructs a RegExp, so takes\n * a pattern or a String.\n *\n * @param expected\n */\njasmine.Matchers.prototype.toMatch = function(expected) {\n  return new RegExp(expected).test(this.actual);\n};\n\n/**\n * Matcher that compares the actual to the expected using the boolean inverse of jasmine.Matchers.toMatch\n * @param expected\n * @deprecated as of 1.0. Use not.toMatch() instead.\n */\njasmine.Matchers.prototype.toNotMatch = function(expected) {\n  return !(new RegExp(expected).test(this.actual));\n};\n\n/**\n * Matcher that compares the actual to jasmine.undefined.\n */\njasmine.Matchers.prototype.toBeDefined = function() {\n  return (this.actual !== jasmine.undefined);\n};\n\n/**\n * Matcher that compares the actual to jasmine.undefined.\n */\njasmine.Matchers.prototype.toBeUndefined = function() {\n  return (this.actual === jasmine.undefined);\n};\n\n/**\n * Matcher that compares the actual to null.\n */\njasmine.Matchers.prototype.toBeNull = function() {\n  return (this.actual === null);\n};\n\n/**\n * Matcher that boolean not-nots the actual.\n */\njasmine.Matchers.prototype.toBeTruthy = function() {\n  return !!this.actual;\n};\n\n\n/**\n * Matcher that boolean nots the actual.\n */\njasmine.Matchers.prototype.toBeFalsy = function() {\n  return !this.actual;\n};\n\n\n/**\n * Matcher that checks to see if the actual, a Jasmine spy, was called.\n */\njasmine.Matchers.prototype.toHaveBeenCalled = function() {\n  if (arguments.length > 0) {\n    throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith');\n  }\n\n  if (!jasmine.isSpy(this.actual)) {\n    throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');\n  }\n\n  this.message = function() {\n    return [\n      \"Expected spy \" + this.actual.identity + \" to have been called.\",\n      \"Expected spy \" + this.actual.identity + \" not to have been called.\"\n    ];\n  };\n\n  return this.actual.wasCalled;\n};\n\n/** @deprecated Use expect(xxx).toHaveBeenCalled() instead */\njasmine.Matchers.prototype.wasCalled = jasmine.Matchers.prototype.toHaveBeenCalled;\n\n/**\n * Matcher that checks to see if the actual, a Jasmine spy, was not called.\n *\n * @deprecated Use expect(xxx).not.toHaveBeenCalled() instead\n */\njasmine.Matchers.prototype.wasNotCalled = function() {\n  if (arguments.length > 0) {\n    throw new Error('wasNotCalled does not take arguments');\n  }\n\n  if (!jasmine.isSpy(this.actual)) {\n    throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');\n  }\n\n  this.message = function() {\n    return [\n      \"Expected spy \" + this.actual.identity + \" to not have been called.\",\n      \"Expected spy \" + this.actual.identity + \" to have been called.\"\n    ];\n  };\n\n  return !this.actual.wasCalled;\n};\n\n/**\n * Matcher that checks to see if the actual, a Jasmine spy, was called with a set of parameters.\n *\n * @example\n *\n */\njasmine.Matchers.prototype.toHaveBeenCalledWith = function() {\n  var expectedArgs = jasmine.util.argsToArray(arguments);\n  if (!jasmine.isSpy(this.actual)) {\n    throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');\n  }\n  this.message = function() {\n    if (this.actual.callCount === 0) {\n      // todo: what should the failure message for .not.toHaveBeenCalledWith() be? is this right? test better. [xw]\n      return [\n        \"Expected spy \" + this.actual.identity + \" to have been called with \" + jasmine.pp(expectedArgs) + \" but it was never called.\",\n        \"Expected spy \" + this.actual.identity + \" not to have been called with \" + jasmine.pp(expectedArgs) + \" but it was.\"\n      ];\n    } else {\n      return [\n        \"Expected spy \" + this.actual.identity + \" to have been called with \" + jasmine.pp(expectedArgs) + \" but was called with \" + jasmine.pp(this.actual.argsForCall),\n        \"Expected spy \" + this.actual.identity + \" not to have been called with \" + jasmine.pp(expectedArgs) + \" but was called with \" + jasmine.pp(this.actual.argsForCall)\n      ];\n    }\n  };\n\n  return this.env.contains_(this.actual.argsForCall, expectedArgs);\n};\n\n/** @deprecated Use expect(xxx).toHaveBeenCalledWith() instead */\njasmine.Matchers.prototype.wasCalledWith = jasmine.Matchers.prototype.toHaveBeenCalledWith;\n\n/** @deprecated Use expect(xxx).not.toHaveBeenCalledWith() instead */\njasmine.Matchers.prototype.wasNotCalledWith = function() {\n  var expectedArgs = jasmine.util.argsToArray(arguments);\n  if (!jasmine.isSpy(this.actual)) {\n    throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');\n  }\n\n  this.message = function() {\n    return [\n      \"Expected spy not to have been called with \" + jasmine.pp(expectedArgs) + \" but it was\",\n      \"Expected spy to have been called with \" + jasmine.pp(expectedArgs) + \" but it was\"\n    ];\n  };\n\n  return !this.env.contains_(this.actual.argsForCall, expectedArgs);\n};\n\n/**\n * Matcher that checks that the expected item is an element in the actual Array.\n *\n * @param {Object} expected\n */\njasmine.Matchers.prototype.toContain = function(expected) {\n  return this.env.contains_(this.actual, expected);\n};\n\n/**\n * Matcher that checks that the expected item is NOT an element in the actual Array.\n *\n * @param {Object} expected\n * @deprecated as of 1.0. Use not.toNotContain() instead.\n */\njasmine.Matchers.prototype.toNotContain = function(expected) {\n  return !this.env.contains_(this.actual, expected);\n};\n\njasmine.Matchers.prototype.toBeLessThan = function(expected) {\n  return this.actual < expected;\n};\n\njasmine.Matchers.prototype.toBeGreaterThan = function(expected) {\n  return this.actual > expected;\n};\n\n/**\n * Matcher that checks that the expected item is equal to the actual item\n * up to a given level of decimal precision (default 2).\n *\n * @param {Number} expected\n * @param {Number} precision\n */\njasmine.Matchers.prototype.toBeCloseTo = function(expected, precision) {\n  if (!(precision === 0)) {\n    precision = precision || 2;\n  }\n  var multiplier = Math.pow(10, precision);\n  var actual = Math.round(this.actual * multiplier);\n  expected = Math.round(expected * multiplier);\n  return expected == actual;\n};\n\n/**\n * Matcher that checks that the expected exception was thrown by the actual.\n *\n * @param {String} expected\n */\njasmine.Matchers.prototype.toThrow = function(expected) {\n  var result = false;\n  var exception;\n  if (typeof this.actual != 'function') {\n    throw new Error('Actual is not a function');\n  }\n  try {\n    this.actual();\n  } catch (e) {\n    exception = e;\n  }\n  if (exception) {\n    result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected));\n  }\n\n  var not = this.isNot ? \"not \" : \"\";\n\n  this.message = function() {\n    if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) {\n      return [\"Expected function \" + not + \"to throw\", expected ? expected.message || expected : \"an exception\", \", but it threw\", exception.message || exception].join(' ');\n    } else {\n      return \"Expected function to throw an exception.\";\n    }\n  };\n\n  return result;\n};\n\njasmine.Matchers.Any = function(expectedClass) {\n  this.expectedClass = expectedClass;\n};\n\njasmine.Matchers.Any.prototype.matches = function(other) {\n  if (this.expectedClass == String) {\n    return typeof other == 'string' || other instanceof String;\n  }\n\n  if (this.expectedClass == Number) {\n    return typeof other == 'number' || other instanceof Number;\n  }\n\n  if (this.expectedClass == Function) {\n    return typeof other == 'function' || other instanceof Function;\n  }\n\n  if (this.expectedClass == Object) {\n    return typeof other == 'object';\n  }\n\n  return other instanceof this.expectedClass;\n};\n\njasmine.Matchers.Any.prototype.toString = function() {\n  return '<jasmine.any(' + this.expectedClass + ')>';\n};\n\n/**\n * @constructor\n */\njasmine.MultiReporter = function() {\n  this.subReporters_ = [];\n};\njasmine.util.inherit(jasmine.MultiReporter, jasmine.Reporter);\n\njasmine.MultiReporter.prototype.addReporter = function(reporter) {\n  this.subReporters_.push(reporter);\n};\n\n(function() {\n  var functionNames = [\n    \"reportRunnerStarting\",\n    \"reportRunnerResults\",\n    \"reportSuiteResults\",\n    \"reportSpecStarting\",\n    \"reportSpecResults\",\n    \"log\"\n  ];\n  for (var i = 0; i < functionNames.length; i++) {\n    var functionName = functionNames[i];\n    jasmine.MultiReporter.prototype[functionName] = (function(functionName) {\n      return function() {\n        for (var j = 0; j < this.subReporters_.length; j++) {\n          var subReporter = this.subReporters_[j];\n          if (subReporter[functionName]) {\n            subReporter[functionName].apply(subReporter, arguments);\n          }\n        }\n      };\n    })(functionName);\n  }\n})();\n/**\n * Holds results for a set of Jasmine spec. Allows for the results array to hold another jasmine.NestedResults\n *\n * @constructor\n */\njasmine.NestedResults = function() {\n  /**\n   * The total count of results\n   */\n  this.totalCount = 0;\n  /**\n   * Number of passed results\n   */\n  this.passedCount = 0;\n  /**\n   * Number of failed results\n   */\n  this.failedCount = 0;\n  /**\n   * Was this suite/spec skipped?\n   */\n  this.skipped = false;\n  /**\n   * @ignore\n   */\n  this.items_ = [];\n};\n\n/**\n * Roll up the result counts.\n *\n * @param result\n */\njasmine.NestedResults.prototype.rollupCounts = function(result) {\n  this.totalCount += result.totalCount;\n  this.passedCount += result.passedCount;\n  this.failedCount += result.failedCount;\n};\n\n/**\n * Adds a log message.\n * @param values Array of message parts which will be concatenated later.\n */\njasmine.NestedResults.prototype.log = function(values) {\n  this.items_.push(new jasmine.MessageResult(values));\n};\n\n/**\n * Getter for the results: message & results.\n */\njasmine.NestedResults.prototype.getItems = function() {\n  return this.items_;\n};\n\n/**\n * Adds a result, tracking counts (total, passed, & failed)\n * @param {jasmine.ExpectationResult|jasmine.NestedResults} result\n */\njasmine.NestedResults.prototype.addResult = function(result) {\n  if (result.type != 'log') {\n    if (result.items_) {\n      this.rollupCounts(result);\n    } else {\n      this.totalCount++;\n      if (result.passed()) {\n        this.passedCount++;\n      } else {\n        this.failedCount++;\n      }\n    }\n  }\n  this.items_.push(result);\n};\n\n/**\n * @returns {Boolean} True if <b>everything</b> below passed\n */\njasmine.NestedResults.prototype.passed = function() {\n  return this.passedCount === this.totalCount;\n};\n/**\n * Base class for pretty printing for expectation results.\n */\njasmine.PrettyPrinter = function() {\n  this.ppNestLevel_ = 0;\n};\n\n/**\n * Formats a value in a nice, human-readable string.\n *\n * @param value\n */\njasmine.PrettyPrinter.prototype.format = function(value) {\n  if (this.ppNestLevel_ > 40) {\n    throw new Error('jasmine.PrettyPrinter: format() nested too deeply!');\n  }\n\n  this.ppNestLevel_++;\n  try {\n    if (value === jasmine.undefined) {\n      this.emitScalar('undefined');\n    } else if (value === null) {\n      this.emitScalar('null');\n    } else if (value === jasmine.getGlobal()) {\n      this.emitScalar('<global>');\n    } else if (value instanceof jasmine.Matchers.Any) {\n      this.emitScalar(value.toString());\n    } else if (typeof value === 'string') {\n      this.emitString(value);\n    } else if (jasmine.isSpy(value)) {\n      this.emitScalar(\"spy on \" + value.identity);\n    } else if (value instanceof RegExp) {\n      this.emitScalar(value.toString());\n    } else if (typeof value === 'function') {\n      this.emitScalar('Function');\n    } else if (typeof value.nodeType === 'number') {\n      this.emitScalar('HTMLNode');\n    } else if (value instanceof Date) {\n      this.emitScalar('Date(' + value + ')');\n    } else if (value.__Jasmine_been_here_before__) {\n      this.emitScalar('<circular reference: ' + (jasmine.isArray_(value) ? 'Array' : 'Object') + '>');\n    } else if (jasmine.isArray_(value) || typeof value == 'object') {\n      value.__Jasmine_been_here_before__ = true;\n      if (jasmine.isArray_(value)) {\n        this.emitArray(value);\n      } else {\n        this.emitObject(value);\n      }\n      delete value.__Jasmine_been_here_before__;\n    } else {\n      this.emitScalar(value.toString());\n    }\n  } finally {\n    this.ppNestLevel_--;\n  }\n};\n\njasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) {\n  for (var property in obj) {\n    if (property == '__Jasmine_been_here_before__') continue;\n    fn(property, obj.__lookupGetter__ ? (obj.__lookupGetter__(property) !== jasmine.undefined && \n                                         obj.__lookupGetter__(property) !== null) : false);\n  }\n};\n\njasmine.PrettyPrinter.prototype.emitArray = jasmine.unimplementedMethod_;\njasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_;\njasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_;\njasmine.PrettyPrinter.prototype.emitString = jasmine.unimplementedMethod_;\n\njasmine.StringPrettyPrinter = function() {\n  jasmine.PrettyPrinter.call(this);\n\n  this.string = '';\n};\njasmine.util.inherit(jasmine.StringPrettyPrinter, jasmine.PrettyPrinter);\n\njasmine.StringPrettyPrinter.prototype.emitScalar = function(value) {\n  this.append(value);\n};\n\njasmine.StringPrettyPrinter.prototype.emitString = function(value) {\n  this.append(\"'\" + value + \"'\");\n};\n\njasmine.StringPrettyPrinter.prototype.emitArray = function(array) {\n  this.append('[ ');\n  for (var i = 0; i < array.length; i++) {\n    if (i > 0) {\n      this.append(', ');\n    }\n    this.format(array[i]);\n  }\n  this.append(' ]');\n};\n\njasmine.StringPrettyPrinter.prototype.emitObject = function(obj) {\n  var self = this;\n  this.append('{ ');\n  var first = true;\n\n  this.iterateObject(obj, function(property, isGetter) {\n    if (first) {\n      first = false;\n    } else {\n      self.append(', ');\n    }\n\n    self.append(property);\n    self.append(' : ');\n    if (isGetter) {\n      self.append('<getter>');\n    } else {\n      self.format(obj[property]);\n    }\n  });\n\n  this.append(' }');\n};\n\njasmine.StringPrettyPrinter.prototype.append = function(value) {\n  this.string += value;\n};\njasmine.Queue = function(env) {\n  this.env = env;\n  this.blocks = [];\n  this.running = false;\n  this.index = 0;\n  this.offset = 0;\n  this.abort = false;\n};\n\njasmine.Queue.prototype.addBefore = function(block) {\n  this.blocks.unshift(block);\n};\n\njasmine.Queue.prototype.add = function(block) {\n  this.blocks.push(block);\n};\n\njasmine.Queue.prototype.insertNext = function(block) {\n  this.blocks.splice((this.index + this.offset + 1), 0, block);\n  this.offset++;\n};\n\njasmine.Queue.prototype.start = function(onComplete) {\n  this.running = true;\n  this.onComplete = onComplete;\n  this.next_();\n};\n\njasmine.Queue.prototype.isRunning = function() {\n  return this.running;\n};\n\njasmine.Queue.LOOP_DONT_RECURSE = true;\n\njasmine.Queue.prototype.next_ = function() {\n  var self = this;\n  var goAgain = true;\n\n  while (goAgain) {\n    goAgain = false;\n    \n    if (self.index < self.blocks.length && !this.abort) {\n      var calledSynchronously = true;\n      var completedSynchronously = false;\n\n      var onComplete = function () {\n        if (jasmine.Queue.LOOP_DONT_RECURSE && calledSynchronously) {\n          completedSynchronously = true;\n          return;\n        }\n\n        if (self.blocks[self.index].abort) {\n          self.abort = true;\n        }\n\n        self.offset = 0;\n        self.index++;\n\n        var now = new Date().getTime();\n        if (self.env.updateInterval && now - self.env.lastUpdate > self.env.updateInterval) {\n          self.env.lastUpdate = now;\n          self.env.setTimeout(function() {\n            self.next_();\n          }, 0);\n        } else {\n          if (jasmine.Queue.LOOP_DONT_RECURSE && completedSynchronously) {\n            goAgain = true;\n          } else {\n            self.next_();\n          }\n        }\n      };\n      self.blocks[self.index].execute(onComplete);\n\n      calledSynchronously = false;\n      if (completedSynchronously) {\n        onComplete();\n      }\n      \n    } else {\n      self.running = false;\n      if (self.onComplete) {\n        self.onComplete();\n      }\n    }\n  }\n};\n\njasmine.Queue.prototype.results = function() {\n  var results = new jasmine.NestedResults();\n  for (var i = 0; i < this.blocks.length; i++) {\n    if (this.blocks[i].results) {\n      results.addResult(this.blocks[i].results());\n    }\n  }\n  return results;\n};\n\n\n/**\n * Runner\n *\n * @constructor\n * @param {jasmine.Env} env\n */\njasmine.Runner = function(env) {\n  var self = this;\n  self.env = env;\n  self.queue = new jasmine.Queue(env);\n  self.before_ = [];\n  self.after_ = [];\n  self.suites_ = [];\n};\n\njasmine.Runner.prototype.execute = function() {\n  var self = this;\n  if (self.env.reporter.reportRunnerStarting) {\n    self.env.reporter.reportRunnerStarting(this);\n  }\n  self.queue.start(function () {\n    self.finishCallback();\n  });\n};\n\njasmine.Runner.prototype.beforeEach = function(beforeEachFunction) {\n  beforeEachFunction.typeName = 'beforeEach';\n  this.before_.splice(0,0,beforeEachFunction);\n};\n\njasmine.Runner.prototype.afterEach = function(afterEachFunction) {\n  afterEachFunction.typeName = 'afterEach';\n  this.after_.splice(0,0,afterEachFunction);\n};\n\n\njasmine.Runner.prototype.finishCallback = function() {\n  this.env.reporter.reportRunnerResults(this);\n};\n\njasmine.Runner.prototype.addSuite = function(suite) {\n  this.suites_.push(suite);\n};\n\njasmine.Runner.prototype.add = function(block) {\n  if (block instanceof jasmine.Suite) {\n    this.addSuite(block);\n  }\n  this.queue.add(block);\n};\n\njasmine.Runner.prototype.specs = function () {\n  var suites = this.suites();\n  var specs = [];\n  for (var i = 0; i < suites.length; i++) {\n    specs = specs.concat(suites[i].specs());\n  }\n  return specs;\n};\n\njasmine.Runner.prototype.suites = function() {\n  return this.suites_;\n};\n\njasmine.Runner.prototype.topLevelSuites = function() {\n  var topLevelSuites = [];\n  for (var i = 0; i < this.suites_.length; i++) {\n    if (!this.suites_[i].parentSuite) {\n      topLevelSuites.push(this.suites_[i]);\n    }\n  }\n  return topLevelSuites;\n};\n\njasmine.Runner.prototype.results = function() {\n  return this.queue.results();\n};\n/**\n * Internal representation of a Jasmine specification, or test.\n *\n * @constructor\n * @param {jasmine.Env} env\n * @param {jasmine.Suite} suite\n * @param {String} description\n */\njasmine.Spec = function(env, suite, description) {\n  if (!env) {\n    throw new Error('jasmine.Env() required');\n  }\n  if (!suite) {\n    throw new Error('jasmine.Suite() required');\n  }\n  var spec = this;\n  spec.id = env.nextSpecId ? env.nextSpecId() : null;\n  spec.env = env;\n  spec.suite = suite;\n  spec.description = description;\n  spec.queue = new jasmine.Queue(env);\n\n  spec.afterCallbacks = [];\n  spec.spies_ = [];\n\n  spec.results_ = new jasmine.NestedResults();\n  spec.results_.description = description;\n  spec.matchersClass = null;\n};\n\njasmine.Spec.prototype.getFullName = function() {\n  return this.suite.getFullName() + ' ' + this.description + '.';\n};\n\n\njasmine.Spec.prototype.results = function() {\n  return this.results_;\n};\n\n/**\n * All parameters are pretty-printed and concatenated together, then written to the spec's output.\n *\n * Be careful not to leave calls to <code>jasmine.log</code> in production code.\n */\njasmine.Spec.prototype.log = function() {\n  return this.results_.log(arguments);\n};\n\njasmine.Spec.prototype.runs = function (func) {\n  var block = new jasmine.Block(this.env, func, this);\n  this.addToQueue(block);\n  return this;\n};\n\njasmine.Spec.prototype.addToQueue = function (block) {\n  if (this.queue.isRunning()) {\n    this.queue.insertNext(block);\n  } else {\n    this.queue.add(block);\n  }\n};\n\n/**\n * @param {jasmine.ExpectationResult} result\n */\njasmine.Spec.prototype.addMatcherResult = function(result) {\n  this.results_.addResult(result);\n};\n\njasmine.Spec.prototype.expect = function(actual) {\n  var positive = new (this.getMatchersClass_())(this.env, actual, this);\n  positive.not = new (this.getMatchersClass_())(this.env, actual, this, true);\n  return positive;\n};\n\n/**\n * Waits a fixed time period before moving to the next block.\n *\n * @deprecated Use waitsFor() instead\n * @param {Number} timeout milliseconds to wait\n */\njasmine.Spec.prototype.waits = function(timeout) {\n  var waitsFunc = new jasmine.WaitsBlock(this.env, timeout, this);\n  this.addToQueue(waitsFunc);\n  return this;\n};\n\n/**\n * Waits for the latchFunction to return true before proceeding to the next block.\n *\n * @param {Function} latchFunction\n * @param {String} optional_timeoutMessage\n * @param {Number} optional_timeout\n */\njasmine.Spec.prototype.waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) {\n  var latchFunction_ = null;\n  var optional_timeoutMessage_ = null;\n  var optional_timeout_ = null;\n\n  for (var i = 0; i < arguments.length; i++) {\n    var arg = arguments[i];\n    switch (typeof arg) {\n      case 'function':\n        latchFunction_ = arg;\n        break;\n      case 'string':\n        optional_timeoutMessage_ = arg;\n        break;\n      case 'number':\n        optional_timeout_ = arg;\n        break;\n    }\n  }\n\n  var waitsForFunc = new jasmine.WaitsForBlock(this.env, optional_timeout_, latchFunction_, optional_timeoutMessage_, this);\n  this.addToQueue(waitsForFunc);\n  return this;\n};\n\njasmine.Spec.prototype.fail = function (e) {\n  var expectationResult = new jasmine.ExpectationResult({\n    passed: false,\n    message: e ? jasmine.util.formatException(e) : 'Exception',\n    trace: { stack: e.stack }\n  });\n  this.results_.addResult(expectationResult);\n};\n\njasmine.Spec.prototype.getMatchersClass_ = function() {\n  return this.matchersClass || this.env.matchersClass;\n};\n\njasmine.Spec.prototype.addMatchers = function(matchersPrototype) {\n  var parent = this.getMatchersClass_();\n  var newMatchersClass = function() {\n    parent.apply(this, arguments);\n  };\n  jasmine.util.inherit(newMatchersClass, parent);\n  jasmine.Matchers.wrapInto_(matchersPrototype, newMatchersClass);\n  this.matchersClass = newMatchersClass;\n};\n\njasmine.Spec.prototype.finishCallback = function() {\n  this.env.reporter.reportSpecResults(this);\n};\n\njasmine.Spec.prototype.finish = function(onComplete) {\n  this.removeAllSpies();\n  this.finishCallback();\n  if (onComplete) {\n    onComplete();\n  }\n};\n\njasmine.Spec.prototype.after = function(doAfter) {\n  if (this.queue.isRunning()) {\n    this.queue.add(new jasmine.Block(this.env, doAfter, this));\n  } else {\n    this.afterCallbacks.unshift(doAfter);\n  }\n};\n\njasmine.Spec.prototype.execute = function(onComplete) {\n  var spec = this;\n  if (!spec.env.specFilter(spec)) {\n    spec.results_.skipped = true;\n    spec.finish(onComplete);\n    return;\n  }\n\n  this.env.reporter.reportSpecStarting(this);\n\n  spec.env.currentSpec = spec;\n\n  spec.addBeforesAndAftersToQueue();\n\n  spec.queue.start(function () {\n    spec.finish(onComplete);\n  });\n};\n\njasmine.Spec.prototype.addBeforesAndAftersToQueue = function() {\n  var runner = this.env.currentRunner();\n  var i;\n\n  for (var suite = this.suite; suite; suite = suite.parentSuite) {\n    for (i = 0; i < suite.before_.length; i++) {\n      this.queue.addBefore(new jasmine.Block(this.env, suite.before_[i], this));\n    }\n  }\n  for (i = 0; i < runner.before_.length; i++) {\n    this.queue.addBefore(new jasmine.Block(this.env, runner.before_[i], this));\n  }\n  for (i = 0; i < this.afterCallbacks.length; i++) {\n    this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this));\n  }\n  for (suite = this.suite; suite; suite = suite.parentSuite) {\n    for (i = 0; i < suite.after_.length; i++) {\n      this.queue.add(new jasmine.Block(this.env, suite.after_[i], this));\n    }\n  }\n  for (i = 0; i < runner.after_.length; i++) {\n    this.queue.add(new jasmine.Block(this.env, runner.after_[i], this));\n  }\n};\n\njasmine.Spec.prototype.explodes = function() {\n  throw 'explodes function should not have been called';\n};\n\njasmine.Spec.prototype.spyOn = function(obj, methodName, ignoreMethodDoesntExist) {\n  if (obj == jasmine.undefined) {\n    throw \"spyOn could not find an object to spy upon for \" + methodName + \"()\";\n  }\n\n  if (!ignoreMethodDoesntExist && obj[methodName] === jasmine.undefined) {\n    throw methodName + '() method does not exist';\n  }\n\n  if (!ignoreMethodDoesntExist && obj[methodName] && obj[methodName].isSpy) {\n    throw new Error(methodName + ' has already been spied upon');\n  }\n\n  var spyObj = jasmine.createSpy(methodName);\n\n  this.spies_.push(spyObj);\n  spyObj.baseObj = obj;\n  spyObj.methodName = methodName;\n  spyObj.originalValue = obj[methodName];\n\n  obj[methodName] = spyObj;\n\n  return spyObj;\n};\n\njasmine.Spec.prototype.removeAllSpies = function() {\n  for (var i = 0; i < this.spies_.length; i++) {\n    var spy = this.spies_[i];\n    spy.baseObj[spy.methodName] = spy.originalValue;\n  }\n  this.spies_ = [];\n};\n\n/**\n * Internal representation of a Jasmine suite.\n *\n * @constructor\n * @param {jasmine.Env} env\n * @param {String} description\n * @param {Function} specDefinitions\n * @param {jasmine.Suite} parentSuite\n */\njasmine.Suite = function(env, description, specDefinitions, parentSuite) {\n  var self = this;\n  self.id = env.nextSuiteId ? env.nextSuiteId() : null;\n  self.description = description;\n  self.queue = new jasmine.Queue(env);\n  self.parentSuite = parentSuite;\n  self.env = env;\n  self.before_ = [];\n  self.after_ = [];\n  self.children_ = [];\n  self.suites_ = [];\n  self.specs_ = [];\n};\n\njasmine.Suite.prototype.getFullName = function() {\n  var fullName = this.description;\n  for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) {\n    fullName = parentSuite.description + ' ' + fullName;\n  }\n  return fullName;\n};\n\njasmine.Suite.prototype.finish = function(onComplete) {\n  this.env.reporter.reportSuiteResults(this);\n  this.finished = true;\n  if (typeof(onComplete) == 'function') {\n    onComplete();\n  }\n};\n\njasmine.Suite.prototype.beforeEach = function(beforeEachFunction) {\n  beforeEachFunction.typeName = 'beforeEach';\n  this.before_.unshift(beforeEachFunction);\n};\n\njasmine.Suite.prototype.afterEach = function(afterEachFunction) {\n  afterEachFunction.typeName = 'afterEach';\n  this.after_.unshift(afterEachFunction);\n};\n\njasmine.Suite.prototype.results = function() {\n  return this.queue.results();\n};\n\njasmine.Suite.prototype.add = function(suiteOrSpec) {\n  this.children_.push(suiteOrSpec);\n  if (suiteOrSpec instanceof jasmine.Suite) {\n    this.suites_.push(suiteOrSpec);\n    this.env.currentRunner().addSuite(suiteOrSpec);\n  } else {\n    this.specs_.push(suiteOrSpec);\n  }\n  this.queue.add(suiteOrSpec);\n};\n\njasmine.Suite.prototype.specs = function() {\n  return this.specs_;\n};\n\njasmine.Suite.prototype.suites = function() {\n  return this.suites_;\n};\n\njasmine.Suite.prototype.children = function() {\n  return this.children_;\n};\n\njasmine.Suite.prototype.execute = function(onComplete) {\n  var self = this;\n  this.queue.start(function () {\n    self.finish(onComplete);\n  });\n};\njasmine.WaitsBlock = function(env, timeout, spec) {\n  this.timeout = timeout;\n  jasmine.Block.call(this, env, null, spec);\n};\n\njasmine.util.inherit(jasmine.WaitsBlock, jasmine.Block);\n\njasmine.WaitsBlock.prototype.execute = function (onComplete) {\n  if (jasmine.VERBOSE) {\n    this.env.reporter.log('>> Jasmine waiting for ' + this.timeout + ' ms...');\n  }\n  this.env.setTimeout(function () {\n    onComplete();\n  }, this.timeout);\n};\n/**\n * A block which waits for some condition to become true, with timeout.\n *\n * @constructor\n * @extends jasmine.Block\n * @param {jasmine.Env} env The Jasmine environment.\n * @param {Number} timeout The maximum time in milliseconds to wait for the condition to become true.\n * @param {Function} latchFunction A function which returns true when the desired condition has been met.\n * @param {String} message The message to display if the desired condition hasn't been met within the given time period.\n * @param {jasmine.Spec} spec The Jasmine spec.\n */\njasmine.WaitsForBlock = function(env, timeout, latchFunction, message, spec) {\n  this.timeout = timeout || env.defaultTimeoutInterval;\n  this.latchFunction = latchFunction;\n  this.message = message;\n  this.totalTimeSpentWaitingForLatch = 0;\n  jasmine.Block.call(this, env, null, spec);\n};\njasmine.util.inherit(jasmine.WaitsForBlock, jasmine.Block);\n\njasmine.WaitsForBlock.TIMEOUT_INCREMENT = 10;\n\njasmine.WaitsForBlock.prototype.execute = function(onComplete) {\n  if (jasmine.VERBOSE) {\n    this.env.reporter.log('>> Jasmine waiting for ' + (this.message || 'something to happen'));\n  }\n  var latchFunctionResult;\n  try {\n    latchFunctionResult = this.latchFunction.apply(this.spec);\n  } catch (e) {\n    this.spec.fail(e);\n    onComplete();\n    return;\n  }\n\n  if (latchFunctionResult) {\n    onComplete();\n  } else if (this.totalTimeSpentWaitingForLatch >= this.timeout) {\n    var message = 'timed out after ' + this.timeout + ' msec waiting for ' + (this.message || 'something to happen');\n    this.spec.fail({\n      name: 'timeout',\n      message: message\n    });\n\n    this.abort = true;\n    onComplete();\n  } else {\n    this.totalTimeSpentWaitingForLatch += jasmine.WaitsForBlock.TIMEOUT_INCREMENT;\n    var self = this;\n    this.env.setTimeout(function() {\n      self.execute(onComplete);\n    }, jasmine.WaitsForBlock.TIMEOUT_INCREMENT);\n  }\n};\n// Mock setTimeout, clearTimeout\n// Contributed by Pivotal Computer Systems, www.pivotalsf.com\n\njasmine.FakeTimer = function() {\n  this.reset();\n\n  var self = this;\n  self.setTimeout = function(funcToCall, millis) {\n    self.timeoutsMade++;\n    self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false);\n    return self.timeoutsMade;\n  };\n\n  self.setInterval = function(funcToCall, millis) {\n    self.timeoutsMade++;\n    self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true);\n    return self.timeoutsMade;\n  };\n\n  self.clearTimeout = function(timeoutKey) {\n    self.scheduledFunctions[timeoutKey] = jasmine.undefined;\n  };\n\n  self.clearInterval = function(timeoutKey) {\n    self.scheduledFunctions[timeoutKey] = jasmine.undefined;\n  };\n\n};\n\njasmine.FakeTimer.prototype.reset = function() {\n  this.timeoutsMade = 0;\n  this.scheduledFunctions = {};\n  this.nowMillis = 0;\n};\n\njasmine.FakeTimer.prototype.tick = function(millis) {\n  var oldMillis = this.nowMillis;\n  var newMillis = oldMillis + millis;\n  this.runFunctionsWithinRange(oldMillis, newMillis);\n  this.nowMillis = newMillis;\n};\n\njasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) {\n  var scheduledFunc;\n  var funcsToRun = [];\n  for (var timeoutKey in this.scheduledFunctions) {\n    scheduledFunc = this.scheduledFunctions[timeoutKey];\n    if (scheduledFunc != jasmine.undefined &&\n        scheduledFunc.runAtMillis >= oldMillis &&\n        scheduledFunc.runAtMillis <= nowMillis) {\n      funcsToRun.push(scheduledFunc);\n      this.scheduledFunctions[timeoutKey] = jasmine.undefined;\n    }\n  }\n\n  if (funcsToRun.length > 0) {\n    funcsToRun.sort(function(a, b) {\n      return a.runAtMillis - b.runAtMillis;\n    });\n    for (var i = 0; i < funcsToRun.length; ++i) {\n      try {\n        var funcToRun = funcsToRun[i];\n        this.nowMillis = funcToRun.runAtMillis;\n        funcToRun.funcToCall();\n        if (funcToRun.recurring) {\n          this.scheduleFunction(funcToRun.timeoutKey,\n              funcToRun.funcToCall,\n              funcToRun.millis,\n              true);\n        }\n      } catch(e) {\n      }\n    }\n    this.runFunctionsWithinRange(oldMillis, nowMillis);\n  }\n};\n\njasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) {\n  this.scheduledFunctions[timeoutKey] = {\n    runAtMillis: this.nowMillis + millis,\n    funcToCall: funcToCall,\n    recurring: recurring,\n    timeoutKey: timeoutKey,\n    millis: millis\n  };\n};\n\n/**\n * @namespace\n */\njasmine.Clock = {\n  defaultFakeTimer: new jasmine.FakeTimer(),\n\n  reset: function() {\n    jasmine.Clock.assertInstalled();\n    jasmine.Clock.defaultFakeTimer.reset();\n  },\n\n  tick: function(millis) {\n    jasmine.Clock.assertInstalled();\n    jasmine.Clock.defaultFakeTimer.tick(millis);\n  },\n\n  runFunctionsWithinRange: function(oldMillis, nowMillis) {\n    jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis);\n  },\n\n  scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) {\n    jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring);\n  },\n\n  useMock: function() {\n    if (!jasmine.Clock.isInstalled()) {\n      var spec = jasmine.getEnv().currentSpec;\n      spec.after(jasmine.Clock.uninstallMock);\n\n      jasmine.Clock.installMock();\n    }\n  },\n\n  installMock: function() {\n    jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer;\n  },\n\n  uninstallMock: function() {\n    jasmine.Clock.assertInstalled();\n    jasmine.Clock.installed = jasmine.Clock.real;\n  },\n\n  real: {\n    setTimeout: jasmine.getGlobal().setTimeout,\n    clearTimeout: jasmine.getGlobal().clearTimeout,\n    setInterval: jasmine.getGlobal().setInterval,\n    clearInterval: jasmine.getGlobal().clearInterval\n  },\n\n  assertInstalled: function() {\n    if (!jasmine.Clock.isInstalled()) {\n      throw new Error(\"Mock clock is not installed, use jasmine.Clock.useMock()\");\n    }\n  },\n\n  isInstalled: function() {\n    return jasmine.Clock.installed == jasmine.Clock.defaultFakeTimer;\n  },\n\n  installed: null\n};\njasmine.Clock.installed = jasmine.Clock.real;\n\n//else for IE support\njasmine.getGlobal().setTimeout = function(funcToCall, millis) {\n  if (jasmine.Clock.installed.setTimeout.apply) {\n    return jasmine.Clock.installed.setTimeout.apply(this, arguments);\n  } else {\n    return jasmine.Clock.installed.setTimeout(funcToCall, millis);\n  }\n};\n\njasmine.getGlobal().setInterval = function(funcToCall, millis) {\n  if (jasmine.Clock.installed.setInterval.apply) {\n    return jasmine.Clock.installed.setInterval.apply(this, arguments);\n  } else {\n    return jasmine.Clock.installed.setInterval(funcToCall, millis);\n  }\n};\n\njasmine.getGlobal().clearTimeout = function(timeoutKey) {\n  if (jasmine.Clock.installed.clearTimeout.apply) {\n    return jasmine.Clock.installed.clearTimeout.apply(this, arguments);\n  } else {\n    return jasmine.Clock.installed.clearTimeout(timeoutKey);\n  }\n};\n\njasmine.getGlobal().clearInterval = function(timeoutKey) {\n  if (jasmine.Clock.installed.clearTimeout.apply) {\n    return jasmine.Clock.installed.clearInterval.apply(this, arguments);\n  } else {\n    return jasmine.Clock.installed.clearInterval(timeoutKey);\n  }\n};\n\njasmine.version_= {\n  \"major\": 1,\n  \"minor\": 1,\n  \"build\": 0,\n  \"revision\": 1308618948,\n  \"release_candidate\": 1\n};\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/es5-shim-15.3.4.5/tests/lib/json2.js",
    "content": "/*\n    http://www.JSON.org/json2.js\n    2009-08-17\n\n    Public Domain.\n\n    NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.\n\n    See http://www.JSON.org/js.html\n\n    This file creates a global JSON object containing two methods: stringify\n    and parse.\n\n        JSON.stringify(value, replacer, space)\n            value       any JavaScript value, usually an object or array.\n\n            replacer    an optional parameter that determines how object\n                        values are stringified for objects. It can be a\n                        function or an array of strings.\n\n            space       an optional parameter that specifies the indentation\n                        of nested structures. If it is omitted, the text will\n                        be packed without extra whitespace. If it is a number,\n                        it will specify the number of spaces to indent at each\n                        level. If it is a string (such as '\\t' or '&nbsp;'),\n                        it contains the characters used to indent at each level.\n\n            This method produces a JSON text from a JavaScript value.\n\n            When an object value is found, if the object contains a toJSON\n            method, its toJSON method will be called and the result will be\n            stringified. A toJSON method does not serialize: it returns the\n            value represented by the name/value pair that should be serialized,\n            or undefined if nothing should be serialized. The toJSON method\n            will be passed the key associated with the value, and this will be\n            bound to the value\n\n            For example, this would serialize Dates as ISO strings.\n\n                Date.prototype.toJSON = function (key) {\n                    function f(n) {\n                        // Format integers to have at least two digits.\n                        return n < 10 ? '0' + n : n;\n                    }\n\n                    return this.getUTCFullYear()   + '-' +\n                         f(this.getUTCMonth() + 1) + '-' +\n                         f(this.getUTCDate())      + 'T' +\n                         f(this.getUTCHours())     + ':' +\n                         f(this.getUTCMinutes())   + ':' +\n                         f(this.getUTCSeconds())   + 'Z';\n                };\n\n            You can provide an optional replacer method. It will be passed the\n            key and value of each member, with this bound to the containing\n            object. The value that is returned from your method will be\n            serialized. If your method returns undefined, then the member will\n            be excluded from the serialization.\n\n            If the replacer parameter is an array of strings, then it will be\n            used to select the members to be serialized. It filters the results\n            such that only members with keys listed in the replacer array are\n            stringified.\n\n            Values that do not have JSON representations, such as undefined or\n            functions, will not be serialized. Such values in objects will be\n            dropped; in arrays they will be replaced with null. You can use\n            a replacer function to replace those with JSON values.\n            JSON.stringify(undefined) returns undefined.\n\n            The optional space parameter produces a stringification of the\n            value that is filled with line breaks and indentation to make it\n            easier to read.\n\n            If the space parameter is a non-empty string, then that string will\n            be used for indentation. If the space parameter is a number, then\n            the indentation will be that many spaces.\n\n            Example:\n\n            text = JSON.stringify(['e', {pluribus: 'unum'}]);\n            // text is '[\"e\",{\"pluribus\":\"unum\"}]'\n\n\n            text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\\t');\n            // text is '[\\n\\t\"e\",\\n\\t{\\n\\t\\t\"pluribus\": \"unum\"\\n\\t}\\n]'\n\n            text = JSON.stringify([new Date()], function (key, value) {\n                return this[key] instanceof Date ?\n                    'Date(' + this[key] + ')' : value;\n            });\n            // text is '[\"Date(---current time---)\"]'\n\n\n        JSON.parse(text, reviver)\n            This method parses a JSON text to produce an object or array.\n            It can throw a SyntaxError exception.\n\n            The optional reviver parameter is a function that can filter and\n            transform the results. It receives each of the keys and values,\n            and its return value is used instead of the original value.\n            If it returns what it received, then the structure is not modified.\n            If it returns undefined then the member is deleted.\n\n            Example:\n\n            // Parse the text. Values that look like ISO date strings will\n            // be converted to Date objects.\n\n            myData = JSON.parse(text, function (key, value) {\n                var a;\n                if (typeof value === 'string') {\n                    a =\n/^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2}(?:\\.\\d*)?)Z$/.exec(value);\n                    if (a) {\n                        return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],\n                            +a[5], +a[6]));\n                    }\n                }\n                return value;\n            });\n\n            myData = JSON.parse('[\"Date(09/09/2001)\"]', function (key, value) {\n                var d;\n                if (typeof value === 'string' &&\n                        value.slice(0, 5) === 'Date(' &&\n                        value.slice(-1) === ')') {\n                    d = new Date(value.slice(5, -1));\n                    if (d) {\n                        return d;\n                    }\n                }\n                return value;\n            });\n\n\n    This is a reference implementation. You are free to copy, modify, or\n    redistribute.\n\n    This code should be minified before deployment.\n    See http://javascript.crockford.com/jsmin.html\n\n    USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO\n    NOT CONTROL.\n*/\n\n/*jslint evil: true */\n\n/*members \"\", \"\\b\", \"\\t\", \"\\n\", \"\\f\", \"\\r\", \"\\\"\", JSON, \"\\\\\", apply,\n    call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,\n    getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,\n    lastIndex, length, parse, prototype, push, replace, slice, stringify,\n    test, toJSON, toString, valueOf\n*/\n\n\"use strict\";\n\n// Create a JSON object only if one does not already exist. We create the\n// methods in a closure to avoid creating global variables.\n\nif (!this.JSON) {\n    this.JSON = {};\n}\n\n(function () {\n\n    function f(n) {\n        // Format integers to have at least two digits.\n        return n < 10 ? '0' + n : n;\n    }\n\n    if (typeof Date.prototype.toJSON !== 'function') {\n\n        Date.prototype.toJSON = function (key) {\n\n            return isFinite(this.valueOf()) ?\n                   this.getUTCFullYear()   + '-' +\n                 f(this.getUTCMonth() + 1) + '-' +\n                 f(this.getUTCDate())      + 'T' +\n                 f(this.getUTCHours())     + ':' +\n                 f(this.getUTCMinutes())   + ':' +\n                 f(this.getUTCSeconds())   + 'Z' : null;\n        };\n\n        String.prototype.toJSON =\n        Number.prototype.toJSON =\n        Boolean.prototype.toJSON = function (key) {\n            return this.valueOf();\n        };\n    }\n\n    var cx = /[\\u0000\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/g,\n        escapable = /[\\\\\\\"\\x00-\\x1f\\x7f-\\x9f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/g,\n        gap,\n        indent,\n        meta = {    // table of character substitutions\n            '\\b': '\\\\b',\n            '\\t': '\\\\t',\n            '\\n': '\\\\n',\n            '\\f': '\\\\f',\n            '\\r': '\\\\r',\n            '\"' : '\\\\\"',\n            '\\\\': '\\\\\\\\'\n        },\n        rep;\n\n\n    function quote(string) {\n\n// If the string contains no control characters, no quote characters, and no\n// backslash characters, then we can safely slap some quotes around it.\n// Otherwise we must also replace the offending characters with safe escape\n// sequences.\n\n        escapable.lastIndex = 0;\n        return escapable.test(string) ?\n            '\"' + string.replace(escapable, function (a) {\n                var c = meta[a];\n                return typeof c === 'string' ? c :\n                    '\\\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);\n            }) + '\"' :\n            '\"' + string + '\"';\n    }\n\n\n    function str(key, holder) {\n// Produce a string from holder[key].\n\n        var i,          // The loop counter.\n            k,          // The member key.\n            v,          // The member value.\n            length,\n            mind = gap,\n            partial,\n            value = holder[key];\n\n// If the value has a toJSON method, call it to obtain a replacement value.\n\n        if (value && typeof value === 'object' &&\n                typeof value.toJSON === 'function') {\n            value = value.toJSON(key);\n        }\n\n// If we were called with a replacer function, then call the replacer to\n// obtain a replacement value.\n\n        if (typeof rep === 'function') {\n            value = rep.call(holder, key, value);\n        }\n\n// What happens next depends on the value's type.\n\n        switch (typeof value) {\n        case 'string':\n            return quote(value);\n\n        case 'number':\n\n// JSON numbers must be finite. Encode non-finite numbers as null.\n\n            return isFinite(value) ? String(value) : 'null';\n\n        case 'boolean':\n        case 'null':\n\n// If the value is a boolean or null, convert it to a string. Note:\n// typeof null does not produce 'null'. The case is included here in\n// the remote chance that this gets fixed someday.\n\n            return String(value);\n\n// If the type is 'object', we might be dealing with an object or an array or\n// null.\n\n        case 'object':\n\n// Due to a specification blunder in ECMAScript, typeof null is 'object',\n// so watch out for that case.\n\n            if (!value) {\n                return 'null';\n            }\n\n// Make an array to hold the partial results of stringifying this object value.\n\n            gap += indent;\n            partial = [];\n\n// Is the value an array?\n\n            if (Object.prototype.toString.apply(value) === '[object Array]') {\n\n// The value is an array. Stringify every element. Use null as a placeholder\n// for non-JSON values.\n\n                length = value.length;\n                for (i = 0; i < length; i += 1) {\n                    partial[i] = str(i, value) || 'null';\n                }\n\n// Join all of the elements together, separated with commas, and wrap them in\n// brackets.\n\n                v = partial.length === 0 ? '[]' :\n                    gap ? '[\\n' + gap +\n                            partial.join(',\\n' + gap) + '\\n' +\n                                mind + ']' :\n                          '[' + partial.join(',') + ']';\n                gap = mind;\n                return v;\n            }\n\n// If the replacer is an array, use it to select the members to be stringified.\n\n            if (rep && typeof rep === 'object') {\n                length = rep.length;\n                for (i = 0; i < length; i += 1) {\n                    k = rep[i];\n                    if (typeof k === 'string') {\n                        v = str(k, value);\n                        if (v) {\n                            partial.push(quote(k) + (gap ? ': ' : ':') + v);\n                        }\n                    }\n                }\n            } else {\n\n// Otherwise, iterate through all of the keys in the object.\n\n                for (k in value) {\n                    if (Object.hasOwnProperty.call(value, k)) {\n                        v = str(k, value);\n                        if (v) {\n                            partial.push(quote(k) + (gap ? ': ' : ':') + v);\n                        }\n                    }\n                }\n            }\n\n// Join all of the member texts together, separated with commas,\n// and wrap them in braces.\n\n            v = partial.length === 0 ? '{}' :\n                gap ? '{\\n' + gap + partial.join(',\\n' + gap) + '\\n' +\n                        mind + '}' : '{' + partial.join(',') + '}';\n            gap = mind;\n            return v;\n        }\n    }\n\n// If the JSON object does not yet have a stringify method, give it one.\n\n    if (typeof JSON.stringify !== 'function') {\n        JSON.stringify = function (value, replacer, space) {\n// The stringify method takes a value and an optional replacer, and an optional\n// space parameter, and returns a JSON text. The replacer can be a function\n// that can replace values, or an array of strings that will select the keys.\n// A default replacer method can be provided. Use of the space parameter can\n// produce text that is more easily readable.\n\n            var i;\n            gap = '';\n            indent = '';\n\n// If the space parameter is a number, make an indent string containing that\n// many spaces.\n\n            if (typeof space === 'number') {\n                for (i = 0; i < space; i += 1) {\n                    indent += ' ';\n                }\n\n// If the space parameter is a string, it will be used as the indent string.\n\n            } else if (typeof space === 'string') {\n                indent = space;\n            }\n\n// If there is a replacer, it must be a function or an array.\n// Otherwise, throw an error.\n\n            rep = replacer;\n            if (replacer && typeof replacer !== 'function' &&\n                    (typeof replacer !== 'object' ||\n                     typeof replacer.length !== 'number')) {\n                throw new Error('JSON.stringify');\n            }\n\n// Make a fake root object containing our value under the key of ''.\n// Return the result of stringifying the value.\n\n            return str('', {'': value});\n        };\n    }\n\n\n// If the JSON object does not yet have a parse method, give it one.\n\n    if (typeof JSON.parse !== 'function') {\n        JSON.parse = function (text, reviver) {\n\n// The parse method takes a text and an optional reviver function, and returns\n// a JavaScript value if the text is a valid JSON text.\n\n            var j;\n\n            function walk(holder, key) {\n\n// The walk method is used to recursively walk the resulting structure so\n// that modifications can be made.\n\n                var k, v, value = holder[key];\n                if (value && typeof value === 'object') {\n                    for (k in value) {\n                        if (Object.hasOwnProperty.call(value, k)) {\n                            v = walk(value, k);\n                            if (v !== undefined) {\n                                value[k] = v;\n                            } else {\n                                delete value[k];\n                            }\n                        }\n                    }\n                }\n                return reviver.call(holder, key, value);\n            }\n\n\n// Parsing happens in four stages. In the first stage, we replace certain\n// Unicode characters with escape sequences. JavaScript handles many characters\n// incorrectly, either silently deleting them, or treating them as line endings.\n\n            cx.lastIndex = 0;\n            if (cx.test(text)) {\n                text = text.replace(cx, function (a) {\n                    return '\\\\u' +\n                        ('0000' + a.charCodeAt(0).toString(16)).slice(-4);\n                });\n            }\n\n// In the second stage, we run the text against regular expressions that look\n// for non-JSON patterns. We are especially concerned with '()' and 'new'\n// because they can cause invocation, and '=' because it can cause mutation.\n// But just to be safe, we want to reject all unexpected forms.\n\n// We split the second stage into 4 regexp operations in order to work around\n// crippling inefficiencies in IE's and Safari's regexp engines. First we\n// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we\n// replace all simple value tokens with ']' characters. Third, we delete all\n// open brackets that follow a colon or comma or that begin the text. Finally,\n// we look to see that the remaining characters are only whitespace or ']' or\n// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.\n\n            if (/^[\\],:{}\\s]*$/.\ntest(text.replace(/\\\\(?:[\"\\\\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').\nreplace(/\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g, ']').\nreplace(/(?:^|:|,)(?:\\s*\\[)+/g, ''))) {\n\n// In the third stage we use the eval function to compile the text into a\n// JavaScript structure. The '{' operator is subject to a syntactic ambiguity\n// in JavaScript: it can begin a block or an object literal. We wrap the text\n// in parens to eliminate the ambiguity.\n\n                j = eval('(' + text + ')');\n\n// In the optional fourth stage, we recursively walk the new structure, passing\n// each name/value pair to a reviver function for possible transformation.\n\n                return typeof reviver === 'function' ?\n                    walk({'': j}, '') : j;\n            }\n\n// If the text is not JSON parseable, then a SyntaxError is thrown.\n\n            throw new SyntaxError('JSON.parse');\n        };\n    }\n}());\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/es5-shim-15.3.4.5/tests/spec/s-array.js",
    "content": "describe('Array', function() {\n    var testSubject;\n    beforeEach(function() {\n        testSubject = [2, 3, undefined, true, 'hej', null, false, 0];\n        delete testSubject[1];\n    });\n    function createArrayLikeFromArray(arr) {\n        var o = {};\n        Array.prototype.forEach.call(arr, function(e, i) {\n            o[i]=e;\n        });\n        o.length = arr.length;\n        return o;\n    };\n\n    describe('forEach', function() {\n        \"use strict\";\n        var expected, actual;\n\n        beforeEach(function() {\n            expected = {0:2, 2: undefined, 3:true, 4: 'hej', 5:null, 6:false, 7:0 };\n            actual = {};\n        });\n        it('should pass the right parameters', function() {\n            var callback = jasmine.createSpy('callback'),\n                array = ['1'];\n            array.forEach(callback);\n            expect(callback).toHaveBeenCalledWith('1', 0, array);\n        });\n        it('should not affect elements added to the array after it has begun', function() {\n            var arr = [1,2,3],\n                i = 0;\n            arr.forEach(function(a) {\n                i++;\n                arr.push(a+3);\n            });\n            expect(arr).toEqual([1,2,3,4,5,6]);\n            expect(i).toBe(3);\n        });\n\n        it('should set the right context when given none', function() {\n            var context;\n            [1].forEach(function() {context = this;});\n            expect(context).toBe(function() {return this}.call());\n        });\n        it('should iterate all', function() {\n            testSubject.forEach(function(obj, index) {\n                actual[index] = obj;\n            });\n            expect(actual).toExactlyMatch(expected);\n        });\n        it('should iterate all using a context', function() {\n            var o = { a: actual };\n\n            testSubject.forEach(function(obj, index) {\n                this.a[index] = obj;\n            }, o);\n            expect(actual).toExactlyMatch(expected);\n        });\n\n        it('should iterate all in an array-like object', function() {\n            var ts = createArrayLikeFromArray(testSubject);\n            Array.prototype.forEach.call(ts, function(obj, index) {\n                actual[index] = obj;\n            });\n            expect(actual).toExactlyMatch(expected);\n        });\n        it('should iterate all in an array-like object using a context', function() {\n            var ts = createArrayLikeFromArray(testSubject),\n                o = { a: actual };\n\n            Array.prototype.forEach.call(ts, function(obj, index) {\n                this.a[index] = obj;\n            }, o);\n            expect(actual).toExactlyMatch(expected);\n        });\n\n        describe('strings', function() {\n            var str = 'Hello, World!',\n                toString = Object.prototype.toString;\n            it('should iterate all in a string', function() {\n                actual = [];\n                Array.prototype.forEach.call(str, function(item, index) {\n                    actual[index] = item;\n                });\n                expect(actual).toExactlyMatch(str.split(''));\n            });\n            it('should iterate all in a string using a context', function() {\n                actual = [];\n                var o = { a: actual };\n                Array.prototype.forEach.call(str, function(item, index) {\n                    this.a[index] = item;\n                }, o);\n                expect(actual).toExactlyMatch(str.split(''));\n            });\n            it('should have String object for third argument of callback', function() {\n                Array.prototype.forEach.call(str, function(item, index, obj) {\n                    actual = obj;\n                });\n                expect(typeof actual).toBe(\"object\");\n                expect(toString.call(actual)).toBe(\"[object String]\");\n            });\n        });\n    });\n    describe('some', function() {\n        var actual, expected, numberOfRuns;\n\n        beforeEach(function() {\n            expected = {0:2, 2: undefined, 3:true };\n            actual = {};\n            numberOfRuns = 0;\n        });\n\n        it('should pass the correct values along to the callback', function() {\n            var callback = jasmine.createSpy('callback');\n            var array = ['1'];\n            array.some(callback);\n            expect(callback).toHaveBeenCalledWith('1', 0, array);\n        });\n        it('should not affect elements added to the array after it has begun', function() {\n            var arr = [1,2,3],\n                i = 0;\n            arr.some(function(a) {\n                i++;\n                arr.push(a+3);\n                return i > 3;\n            });\n            expect(arr).toEqual([1,2,3,4,5,6]);\n            expect(i).toBe(3);\n        });\n        it('should set the right context when given none', function() {\n            var context;\n            [1].some(function() {context = this;});\n            expect(context).toBe(function() {return this}.call());\n        });\n\n        it('should return false if it runs to the end', function() {\n            actual = testSubject.some(function() {});\n            expect(actual).toBeFalsy();\n        });\n        it('should return true if it is stopped somewhere', function() {\n            actual = testSubject.some(function() { return true; });\n            expect(actual).toBeTruthy();\n        });\n        it('should return false if there are no elements', function() {\n            actual = [].some(function() { return true; });\n            expect(actual).toBeFalsy();\n        });\n\n        it('should stop after 3 elements', function() {\n            testSubject.some(function(obj, index) {\n                actual[index] = obj;\n                numberOfRuns += 1;\n                if(numberOfRuns == 3) {\n                    return true;\n                }\n                return false;\n            });\n            expect(actual).toExactlyMatch(expected);\n        });\n        it('should stop after 3 elements using a context', function() {\n            var o = { a: actual };\n            testSubject.some(function(obj, index) {\n                this.a[index] = obj;\n                numberOfRuns += 1;\n                if(numberOfRuns == 3) {\n                    return true;\n                }\n                return false;\n            }, o);\n            expect(actual).toExactlyMatch(expected);\n        });\n\n        it('should stop after 3 elements in an array-like object', function() {\n            var ts = createArrayLikeFromArray(testSubject);\n            Array.prototype.some.call(ts, function(obj, index) {\n                actual[index] = obj;\n                numberOfRuns += 1;\n                if(numberOfRuns == 3) {\n                    return true;\n                }\n                return false;\n            });\n            expect(actual).toExactlyMatch(expected);\n        });\n        it('should stop after 3 elements in an array-like object using a context', function() {\n            var ts = createArrayLikeFromArray(testSubject);\n            var o = { a: actual };\n            Array.prototype.some.call(ts, function(obj, index) {\n                this.a[index] = obj;\n                numberOfRuns += 1;\n                if(numberOfRuns == 3) {\n                    return true;\n                }\n                return false;\n            }, o);\n            expect(actual).toExactlyMatch(expected);\n        });\n    });\n    describe('every', function() {\n        var actual, expected, numberOfRuns;\n\n        beforeEach(function() {\n            expected = {0:2, 2: undefined, 3:true };\n            actual = {};\n            numberOfRuns = 0;\n        });\n\n        it('should pass the correct values along to the callback', function() {\n            var callback = jasmine.createSpy('callback');\n            var array = ['1'];\n            array.every(callback);\n            expect(callback).toHaveBeenCalledWith('1', 0, array);\n        });\n        it('should not affect elements added to the array after it has begun', function() {\n            var arr = [1,2,3],\n                i = 0;\n            arr.every(function(a) {\n                i++;\n                arr.push(a+3);\n                return i <= 3;\n            });\n            expect(arr).toEqual([1,2,3,4,5,6]);\n            expect(i).toBe(3);\n        });\n        it('should set the right context when given none', function() {\n            var context;\n            [1].every(function() {context = this;});\n            expect(context).toBe(function() {return this}.call());\n        });\n\n        it('should return true if the array is empty', function() {\n            actual = [].every(function() { return true; });\n            expect(actual).toBeTruthy();\n\n            actual = [].every(function() { return false; });\n            expect(actual).toBeTruthy();\n        });\n        it('should return true if it runs to the end', function() {\n            actual = [1,2,3].every(function() { return true; });\n            expect(actual).toBeTruthy();\n        });\n        it('should return false if it is stopped before the end', function() {\n            actual = [1,2,3].every(function() { return false; });\n            expect(actual).toBeFalsy();\n        });\n\n        it('should return after 3 elements', function() {\n            testSubject.every(function(obj, index) {\n                actual[index] = obj;\n                numberOfRuns += 1;\n                if(numberOfRuns == 3) {\n                    return false;\n                }\n                return true;\n            });\n            expect(actual).toExactlyMatch(expected);\n        });\n        it('should stop after 3 elements using a context', function() {\n            var o = { a: actual };\n            testSubject.every(function(obj, index) {\n                this.a[index] = obj;\n                numberOfRuns += 1;\n                if(numberOfRuns == 3) {\n                    return false;\n                }\n                return true;\n            }, o);\n            expect(actual).toExactlyMatch(expected);\n        });\n\n        it('should stop after 3 elements in an array-like object', function() {\n            var ts = createArrayLikeFromArray(testSubject);\n            Array.prototype.every.call(ts, function(obj, index) {\n                actual[index] = obj;\n                numberOfRuns += 1;\n                if(numberOfRuns == 3) {\n                    return false;\n                }\n                return true;\n            });\n            expect(actual).toExactlyMatch(expected);\n        });\n        it('should stop after 3 elements in an array-like object using a context', function() {\n            var ts = createArrayLikeFromArray(testSubject);\n            var o = { a: actual };\n            Array.prototype.every.call(ts, function(obj, index) {\n                this.a[index] = obj;\n                numberOfRuns += 1;\n                if(numberOfRuns == 3) {\n                    return false;\n                }\n                return true;\n            }, o);\n            expect(actual).toExactlyMatch(expected);\n        });\n    });\n\n    describe('indexOf', function() {\n        \"use strict\";\n        var actual, expected, testSubject;\n\n        beforeEach(function() {\n            testSubject = [2, 3, undefined, true, 'hej', null, 2, false, 0];\n            delete testSubject[1];\n\n        });\n\n        it('should find the element', function() {\n            expected = 4;\n            actual = testSubject.indexOf('hej');\n            expect(actual).toEqual(expected);\n        });\n        it('should not find the element', function() {\n            expected = -1;\n            actual = testSubject.indexOf('mus');\n            expect(actual).toEqual(expected);\n        });\n        it('should find undefined as well', function() {\n            expected = -1;\n            actual = testSubject.indexOf(undefined);\n            expect(actual).not.toEqual(expected);\n        });\n        it('should skip unset indexes', function() {\n            expected = 2;\n            actual = testSubject.indexOf(undefined);\n            expect(actual).toEqual(expected);\n        });\n        it('should use a strict test', function() {\n            actual = testSubject.indexOf(null);\n            expect(actual).toEqual(5);\n\n            actual = testSubject.indexOf('2');\n            expect(actual).toEqual(-1);\n        });\n        it('should skip the first if fromIndex is set', function() {\n            expect(testSubject.indexOf(2, 2)).toEqual(6);\n            expect(testSubject.indexOf(2, 0)).toEqual(0);\n            expect(testSubject.indexOf(2, 6)).toEqual(6);\n        });\n        it('should work with negative fromIndex', function() {\n            expect(testSubject.indexOf(2, -3)).toEqual(6);\n            expect(testSubject.indexOf(2, -9)).toEqual(0);\n        });\n        it('should work with fromIndex being greater than the length', function() {\n            expect(testSubject.indexOf(0, 20)).toEqual(-1);\n        });\n        it('should work with fromIndex being negative and greater than the length', function() {\n            expect(testSubject.indexOf('hej', -20)).toEqual(4);\n        });\n\n        describe('Array-like', function ArrayLike() {\n            var indexOf = Array.prototype.indexOf,\n                testAL;\n            beforeEach(function beforeEach() {\n                testAL = {};\n                testSubject = [2, 3, undefined, true, 'hej', null, 2, false, 0];\n                testSubject.forEach(function (o,i) {\n                    testAL[i] = o;\n                });\n                testAL.length = testSubject.length;\n            });\n            it('should find the element (array-like)', function() {\n                expected = 4;\n                actual = indexOf.call(testAL, 'hej');\n                expect(actual).toEqual(expected);\n            });\n            it('should not find the element (array-like)', function() {\n                expected = -1;\n                actual = indexOf.call(testAL, 'mus');\n                expect(actual).toEqual(expected);\n            });\n            it('should find undefined as well (array-like)', function() {\n                expected = -1;\n                actual = indexOf.call(testAL, undefined);\n                expect(actual).not.toEqual(expected);\n            });\n            it('should skip unset indexes (array-like)', function() {\n                expected = 2;\n                actual = indexOf.call(testAL, undefined);\n                expect(actual).toEqual(expected);\n            });\n            it('should use a strict test (array-like)', function() {\n                actual = Array.prototype.indexOf.call(testAL, null);\n                expect(actual).toEqual(5);\n\n                actual = Array.prototype.indexOf.call(testAL, '2');\n                expect(actual).toEqual(-1);\n            });\n            it('should skip the first if fromIndex is set (array-like)', function() {\n                expect(indexOf.call(testAL, 2, 2)).toEqual(6);\n                expect(indexOf.call(testAL, 2, 0)).toEqual(0);\n                expect(indexOf.call(testAL, 2, 6)).toEqual(6);\n            });\n            it('should work with negative fromIndex (array-like)', function() {\n                expect(indexOf.call(testAL, 2, -3)).toEqual(6);\n                expect(indexOf.call(testAL, 2, -9)).toEqual(0);\n            });\n            it('should work with fromIndex being greater than the length (array-like)', function() {\n                expect(indexOf.call(testAL, 0, 20)).toEqual(-1);\n            });\n            it('should work with fromIndex being negative and greater than the length (array-like)', function() {\n                expect(indexOf.call(testAL, 'hej', -20)).toEqual(4);\n            });\n        });\n    });\n    describe('lastIndexOf', function() {\n        \"use strict\";\n        var actual, expected, testSubject, testAL;\n\n        beforeEach(function() {\n            testSubject = [2, 3, undefined, true, 'hej', null, 2, 3, false, 0];\n            delete testSubject[1];\n            delete testSubject[7];\n        });\n        describe('Array', function() {\n            it('should find the element', function() {\n                expected = 4;\n                actual = testSubject.lastIndexOf('hej');\n                expect(actual).toEqual(expected);\n            });\n            it('should not find the element', function() {\n                expected = -1;\n                actual = testSubject.lastIndexOf('mus');\n                expect(actual).toEqual(expected);\n            });\n            it('should find undefined as well', function() {\n                expected = -1;\n                actual = testSubject.lastIndexOf(undefined);\n                expect(actual).not.toEqual(expected);\n            });\n            it('should skip unset indexes', function() {\n                expected = 2;\n                actual = testSubject.lastIndexOf(undefined);\n                expect(actual).toEqual(expected);\n            });\n            it('should use a strict test', function() {\n                actual = testSubject.lastIndexOf(null);\n                expect(actual).toEqual(5);\n\n                actual = testSubject.lastIndexOf('2');\n                expect(actual).toEqual(-1);\n            });\n            it('should skip the first if fromIndex is set', function() {\n                expect(testSubject.lastIndexOf(2, 2)).toEqual(0);\n                expect(testSubject.lastIndexOf(2, 0)).toEqual(0);\n                expect(testSubject.lastIndexOf(2, 6)).toEqual(6);\n            });\n            it('should work with negative fromIndex', function() {\n                expect(testSubject.lastIndexOf(2, -3)).toEqual(6);\n                expect(testSubject.lastIndexOf(2, -9)).toEqual(0);\n            });\n            it('should work with fromIndex being greater than the length', function() {\n                expect(testSubject.lastIndexOf(2, 20)).toEqual(6);\n            });\n            it('should work with fromIndex being negative and greater than the length', function() {\n                expect(testSubject.lastIndexOf(2, -20)).toEqual(-1);\n            });\n        });\n\n        describe('Array like', function() {\n            var lastIndexOf = Array.prototype.lastIndexOf,\n                testAL;\n            beforeEach(function() {\n                testAL = {};\n                testSubject.forEach(function (o,i) {\n                    testAL[i] = o;\n                });\n                testAL.length = testSubject.length;\n            });\n            it('should find the element (array-like)', function() {\n                expected = 4;\n                actual = lastIndexOf.call(testAL, 'hej');\n                expect(actual).toEqual(expected);\n            });\n            it('should not find the element (array-like)', function() {\n                expected = -1;\n                actual = lastIndexOf.call(testAL, 'mus');\n                expect(actual).toEqual(expected);\n            });\n            it('should find undefined as well (array-like)', function() {\n                expected = -1;\n                actual = lastIndexOf.call(testAL, undefined);\n                expect(actual).not.toEqual(expected);\n            });\n            it('should skip unset indexes (array-like)', function() {\n                expected = 2;\n                actual = lastIndexOf.call(testAL, undefined);\n                expect(actual).toEqual(expected);\n            });\n            it('should use a strict test (array-like)', function() {\n                actual = lastIndexOf.call(testAL, null);\n                expect(actual).toEqual(5);\n\n                actual = lastIndexOf.call(testAL, '2');\n                expect(actual).toEqual(-1);\n            });\n            it('should skip the first if fromIndex is set', function() {\n                expect(lastIndexOf.call(testAL, 2, 2)).toEqual(0);\n                expect(lastIndexOf.call(testAL, 2, 0)).toEqual(0);\n                expect(lastIndexOf.call(testAL, 2, 6)).toEqual(6);\n            });\n            it('should work with negative fromIndex', function() {\n                expect(lastIndexOf.call(testAL, 2, -3)).toEqual(6);\n                expect(lastIndexOf.call(testAL, 2, -9)).toEqual(0);\n            });\n            it('should work with fromIndex being greater than the length', function() {\n                expect(lastIndexOf.call(testAL, 2, 20)).toEqual(6);\n            });\n            it('should work with fromIndex being negative and greater than the length', function() {\n                expect(lastIndexOf.call(testAL, 2, -20)).toEqual(-1);\n            });\n        });\n    });\n\n    describe('filter', function() {\n        var filteredArray,\n            callback = function callback(o, i, arr) {\n                return (\n                    i != 3 && i != 5\n                );\n            };\n\n        beforeEach(function() {\n            testSubject = [2, 3, undefined, true, 'hej', 3, null, false, 0];\n            delete testSubject[1];\n            filteredArray = [2, undefined, 'hej', null, false, 0];\n        });\n        describe('Array object', function() {\n\n            it('should call the callback with the proper arguments', function() {\n                var callback = jasmine.createSpy('callback'),\n                    arr = ['1'];\n                arr.filter(callback);\n                expect(callback).toHaveBeenCalledWith('1', 0, arr);\n            });\n            it('should not affect elements added to the array after it has begun', function() {\n                var arr = [1,2,3],\n                    i = 0;\n                arr.filter(function(a) {\n                    i++;\n                    if(i <= 4) {\n                        arr.push(a+3);\n                    }\n                    return true;\n                });\n                expect(arr).toEqual([1,2,3,4,5,6]);\n                expect(i).toBe(3);\n            });\n            it('should skip non-set values', function() {\n                var passedValues = {};\n                testSubject = [1,2,3,4];\n                delete testSubject[1];\n                testSubject.filter(function(o, i) {\n                    passedValues[i] = o;\n                    return true;\n                });\n                expect(passedValues).toExactlyMatch(testSubject);\n            });\n            it('should pass the right context to the filter', function() {\n                var passedValues = {};\n                testSubject = [1,2,3,4];\n                delete testSubject[1];\n                testSubject.filter(function(o, i) {\n                    this[i] = o;\n                    return true;\n                }, passedValues);\n                expect(passedValues).toExactlyMatch(testSubject);\n            });\n            it('should set the right context when given none', function() {\n                var context;\n                [1].filter(function() {context = this;});\n                expect(context).toBe(function() {return this}.call());\n            });\n            it('should remove only the values for which the callback returns false', function() {\n                var result = testSubject.filter(callback);\n                expect(result).toExactlyMatch(filteredArray);\n            });\n            it('should leave the original array untouched', function() {\n                var copy = testSubject.slice();\n                testSubject.filter(callback);\n                expect(testSubject).toExactlyMatch(copy);\n            });\n            it('should not be affected by same-index mutation', function () {\n                var results = [1, 2, 3]\n                .filter(function (value, index, array) {\n                    array[index] = 'a';\n                    return true;\n                });\n                expect(results).toEqual([1, 2, 3]);\n            });\n        });\n        describe('Array like', function() {\n            beforeEach(function() {\n                testSubject = createArrayLikeFromArray(testSubject);\n            });\n            it('should call the callback with the proper arguments', function() {\n                var callback = jasmine.createSpy('callback'),\n                    arr = createArrayLikeFromArray(['1']);\n                Array.prototype.filter.call(arr, callback);\n                expect(callback).toHaveBeenCalledWith('1', 0, arr);\n            });\n            it('should not affect elements added to the array after it has begun', function() {\n                var arr = createArrayLikeFromArray([1,2,3]),\n                    i = 0;\n                Array.prototype.filter.call(arr, function(a) {\n                    i++;\n                    if(i <= 4) {\n                        arr[i+2] = a+3;\n                    }\n                    return true;\n                });\n                delete arr.length;\n                expect(arr).toExactlyMatch([1,2,3,4,5,6]);\n                expect(i).toBe(3);\n            });\n            it('should skip non-set values', function() {\n                var passedValues = {};\n                testSubject = createArrayLikeFromArray([1,2,3,4]);\n                delete testSubject[1];\n                Array.prototype.filter.call(testSubject, function(o, i) {\n                    passedValues[i] = o;\n                    return true;\n                });\n                delete testSubject.length;\n                expect(passedValues).toExactlyMatch(testSubject);\n            });\n            it('should set the right context when given none', function() {\n                var context;\n                Array.prototype.filter.call(createArrayLikeFromArray([1]), function() {context = this;}, undefined);\n                expect(context).toBe(function() {return this}.call());\n            });\n            it('should pass the right context to the filter', function() {\n                var passedValues = {};\n                testSubject = createArrayLikeFromArray([1,2,3,4]);\n                delete testSubject[1];\n                Array.prototype.filter.call(testSubject, function(o, i) {\n                    this[i] = o;\n                    return true;\n                }, passedValues);\n                delete testSubject.length;\n                expect(passedValues).toExactlyMatch(testSubject);\n            });\n            it('should remove only the values for which the callback returns false', function() {\n                var result = Array.prototype.filter.call(testSubject, callback);\n                expect(result).toExactlyMatch(filteredArray);\n            });\n            it('should leave the original array untouched', function() {\n                var copy = createArrayLikeFromArray(testSubject);\n                Array.prototype.filter.call(testSubject, callback);\n                expect(testSubject).toExactlyMatch(copy);\n            });\n        });\n    });\n    describe('map', function() {\n        var callback;\n        beforeEach(function() {\n            var i = 0;\n            callback = function() {\n                return i++;\n            };\n        });\n        describe('Array object', function() {\n            it('should call callback with the right parameters', function() {\n                var callback = jasmine.createSpy('callback'),\n                    array = [1];\n                array.map(callback);\n                expect(callback).toHaveBeenCalledWith(1, 0, array);\n            });\n            it('should set the context correctly', function() {\n                var context = {};\n                testSubject.map(function(o,i) {\n                    this[i] = o;\n                }, context);\n                expect(context).toExactlyMatch(testSubject);\n            });\n            it('should set the right context when given none', function() {\n                var context;\n                [1].map(function() {context = this;});\n                expect(context).toBe(function() {return this}.call());\n            });\n            it('should not change the array it is called on', function() {\n                var copy = testSubject.slice();\n                testSubject.map(callback);\n                expect(testSubject).toExactlyMatch(copy);\n            });\n            it('should only run for the number of objects in the array when it started', function() {\n                var arr = [1,2,3],\n                    i = 0;\n                arr.map(function(o) {\n                    arr.push(o+3);\n                    i++;\n                    return o;\n                });\n                expect(arr).toExactlyMatch([1,2,3,4,5,6]);\n                expect(i).toBe(3);\n            });\n            it('should properly translate the values as according to the callback', function() {\n                var result = testSubject.map(callback),\n                    expected = [0,0,1,2,3,4,5,6];\n                delete expected[1];\n                expect(result).toExactlyMatch(expected);\n            });\n            it('should skip non-existing values', function() {\n                var array = [1,2,3,4],\n                    i = 0;\n                delete array[2];\n                array.map(function() {\n                    i++;\n                });\n                expect(i).toBe(3);\n            });\n        });\n        describe('Array-like', function() {\n            beforeEach(function() {\n                testSubject = createArrayLikeFromArray(testSubject);\n            });\n            it('should call callback with the right parameters', function() {\n                var callback = jasmine.createSpy('callback'),\n                    array = createArrayLikeFromArray([1]);\n                Array.prototype.map.call(array, callback);\n                expect(callback).toHaveBeenCalledWith(1, 0, array);\n            });\n            it('should set the context correctly', function() {\n                var context = {};\n                Array.prototype.map.call(testSubject, function(o,i) {\n                    this[i] = o;\n                }, context);\n                delete testSubject.length;\n                expect(context).toExactlyMatch(testSubject);\n            });\n            it('should set the right context when given none', function() {\n                var context;\n                Array.prototype.map.call(createArrayLikeFromArray([1]), function() {context = this;});\n                expect(context).toBe(function() {return this}.call());\n            });\n            it('should not change the array it is called on', function() {\n                var copy = createArrayLikeFromArray(testSubject);\n                Array.prototype.map.call(testSubject, callback);\n                expect(testSubject).toExactlyMatch(copy);\n            });\n            it('should only run for the number of objects in the array when it started', function() {\n                var arr = createArrayLikeFromArray([1,2,3]),\n                    i = 0;\n                Array.prototype.map.call(arr, function(o) {\n                    Array.prototype.push.call(arr, o+3);\n                    i++;\n                    return o;\n                });\n                delete arr.length;\n                expect(arr).toExactlyMatch([1,2,3,4,5,6]);\n                expect(i).toBe(3);\n            });\n            it('should properly translate the values as according to the callback', function() {\n                var result = Array.prototype.map.call(testSubject, callback),\n                    expected = [0,0,1,2,3,4,5,6];\n                delete expected[1];\n                expect(result).toExactlyMatch(expected);\n            });\n            it('should skip non-existing values', function() {\n                var array = createArrayLikeFromArray([1,2,3,4]),\n                    i = 0;\n                delete array[2];\n                Array.prototype.map.call(array, function() {\n                    i++;\n                });\n                expect(i).toBe(3);\n            });\n        });\n    });\n\n    describe('reduce', function() {\n        beforeEach(function() {\n            testSubject = [1,2,3];\n        });\n\n        describe('Array', function() {\n            it('should pass the correct arguments to the callback', function() {\n                var spy = jasmine.createSpy().andReturn(0);\n                testSubject.reduce(spy);\n                expect(spy.calls[0].args).toExactlyMatch([1, 2, 1, testSubject]);\n            });\n            it('should start with the right initialValue', function() {\n                var spy = jasmine.createSpy().andReturn(0);\n                testSubject.reduce(spy, 0);\n                expect(spy.calls[0].args).toExactlyMatch([0, 1, 0, testSubject]);\n            });\n            it('should not affect elements added to the array after it has begun', function() {\n                var arr = [1,2,3],\n                    i = 0;\n                arr.reduce(function(a, b) {\n                    i++;\n                    if(i <= 4) {\n                        arr.push(a+3);\n                    };\n                    return b;\n                });\n                expect(arr).toEqual([1,2,3,4,5]);\n                expect(i).toBe(2);\n            });\n            it('should work as expected for empty arrays', function() {\n                var spy = jasmine.createSpy();\n                expect(function() {\n                    [].reduce(spy);\n                }).toThrow();\n                expect(spy).not.toHaveBeenCalled();\n            });\n            it('should throw correctly if no callback is given', function() {\n                expect(function() {\n                    testSubject.reduce();\n                }).toThrow();\n            });\n            it('should return the expected result', function() {\n                expect(testSubject.reduce(function(a,b) {\n                    return (a||'').toString()+(b||'').toString();\n                })).toEqual(testSubject.join(''));\n            });\n            it('should not directly affect the passed array', function() {\n                var copy = testSubject.slice();\n                testSubject.reduce(function(a,b) {\n                    return a+b;\n                });\n                expect(testSubject).toEqual(copy);\n            });\n            it('should skip non-set values', function() {\n                delete testSubject[1];\n                var visited = {};\n                testSubject.reduce(function(a,b) {\n                    if(a)\n                        visited[a] = true;\n                    if(b)\n                        visited[b] = true;\n                    return 0;\n                });\n\n                expect(visited).toEqual({ '1': true, '3': true });\n            });\n            it('should have the right length', function() {\n                expect(testSubject.reduce.length).toBe(1);\n            });\n        });\n        describe('Array-like objects', function() {\n            beforeEach(function() {\n                testSubject = createArrayLikeFromArray(testSubject);\n                testSubject.reduce = Array.prototype.reduce;\n            });\n            it('should pass the correct arguments to the callback', function() {\n                var spy = jasmine.createSpy().andReturn(0);\n                testSubject.reduce(spy);\n                expect(spy.calls[0].args).toExactlyMatch([1, 2, 1, testSubject]);\n            });\n            it('should start with the right initialValue', function() {\n                var spy = jasmine.createSpy().andReturn(0);\n                testSubject.reduce(spy, 0);\n                expect(spy.calls[0].args).toExactlyMatch([0, 1, 0, testSubject]);\n            });\n            it('should not affect elements added to the array after it has begun', function() {\n                var arr = createArrayLikeFromArray([1,2,3]),\n                    i = 0;\n                Array.prototype.reduce.call(arr, function(a, b) {\n                    i++;\n                    if(i <= 4) {\n                        arr[i+2] = a+3;\n                    };\n                    return b;\n                });\n                expect(arr).toEqual({\n                    0: 1,\n                    1: 2,\n                    2: 3,\n                    3: 4,\n                    4: 5,\n                    length: 3\n                });\n                expect(i).toBe(2);\n            });\n            it('should work as expected for empty arrays', function() {\n                var spy = jasmine.createSpy();\n                expect(function() {\n                    Array.prototype.reduce.call({length: 0}, spy);\n                }).toThrow();\n                expect(spy).not.toHaveBeenCalled();\n            });\n            it('should throw correctly if no callback is given', function() {\n                expect(function() {\n                    testSubject.reduce();\n                }).toThrow();\n            });\n            it('should return the expected result', function() {\n                expect(testSubject.reduce(function(a,b) {\n                    return (a||'').toString()+(b||'').toString();\n                })).toEqual('123');\n            });\n            it('should not directly affect the passed array', function() {\n                var copy = createArrayLikeFromArray(testSubject);\n                testSubject.reduce(function(a,b) {\n                    return a+b;\n                });\n                delete(testSubject.reduce);\n                expect(testSubject).toEqual(copy);\n            });\n            it('should skip non-set values', function() {\n                delete testSubject[1];\n                var visited = {};\n                testSubject.reduce(function(a,b) {\n                    if(a)\n                        visited[a] = true;\n                    if(b)\n                        visited[b] = true;\n                    return 0;\n                });\n\n                expect(visited).toEqual({ '1': true, '3': true });\n            });\n            it('should have the right length', function() {\n                expect(testSubject.reduce.length).toBe(1);\n            });\n        });\n    });\n    describe('reduceRight', function() {\n        beforeEach(function() {\n            testSubject = [1,2,3];\n        });\n\n        describe('Array', function() {\n            it('should pass the correct arguments to the callback', function() {\n                var spy = jasmine.createSpy().andReturn(0);\n                testSubject.reduceRight(spy);\n                expect(spy.calls[0].args).toExactlyMatch([3, 2, 1, testSubject]);\n            });\n            it('should start with the right initialValue', function() {\n                var spy = jasmine.createSpy().andReturn(0);\n                testSubject.reduceRight(spy, 0);\n                expect(spy.calls[0].args).toExactlyMatch([0, 3, 2, testSubject]);\n            });\n            it('should not affect elements added to the array after it has begun', function() {\n                var arr = [1,2,3],\n                    i = 0;\n                arr.reduceRight(function(a, b) {\n                    i++;\n                    if(i <= 4) {\n                        arr.push(a+3);\n                    };\n                    return b;\n                });\n                expect(arr).toEqual([1,2,3,6,5]);\n                expect(i).toBe(2);\n            });\n            it('should work as expected for empty arrays', function() {\n                var spy = jasmine.createSpy();\n                expect(function() {\n                    [].reduceRight(spy);\n                }).toThrow();\n                expect(spy).not.toHaveBeenCalled();\n            });\n            it('should work as expected for empty arrays with an initial value', function() {\n                var spy = jasmine.createSpy(),\n                    result;\n\n                result = [].reduceRight(spy, '');\n                expect(spy).not.toHaveBeenCalled();\n                expect(result).toBe('');\n            });\n            it('should throw correctly if no callback is given', function() {\n                expect(function() {\n                    testSubject.reduceRight();\n                }).toThrow();\n            });\n            it('should return the expected result', function() {\n                expect(testSubject.reduceRight(function(a,b) {\n                    return (a||'').toString()+(b||'').toString();\n                })).toEqual('321');\n            });\n            it('should not directly affect the passed array', function() {\n                var copy = testSubject.slice();\n                testSubject.reduceRight(function(a,b) {\n                    return a+b;\n                });\n                expect(testSubject).toEqual(copy);\n            });\n            it('should skip non-set values', function() {\n                delete testSubject[1];\n                var visited = {};\n                testSubject.reduceRight(function(a,b) {\n                    if(a)\n                        visited[a] = true;\n                    if(b)\n                        visited[b] = true;\n                    return 0;\n                });\n\n                expect(visited).toEqual({ '1': true, '3': true });\n            });\n            it('should have the right length', function() {\n                expect(testSubject.reduceRight.length).toBe(1);\n            });\n        });\n        describe('Array-like objects', function() {\n            beforeEach(function() {\n                testSubject = createArrayLikeFromArray(testSubject);\n                testSubject.reduceRight = Array.prototype.reduceRight;\n            });\n            it('should pass the correct arguments to the callback', function() {\n                var spy = jasmine.createSpy().andReturn(0);\n                testSubject.reduceRight(spy);\n                expect(spy.calls[0].args).toExactlyMatch([3, 2, 1, testSubject]);\n            });\n            it('should start with the right initialValue', function() {\n                var spy = jasmine.createSpy().andReturn(0);\n                testSubject.reduceRight(spy, 0);\n                expect(spy.calls[0].args).toExactlyMatch([0, 3, 2, testSubject]);\n            });\n            it('should not affect elements added to the array after it has begun', function() {\n                var arr = createArrayLikeFromArray([1,2,3]),\n                    i = 0;\n                Array.prototype.reduceRight.call(arr, function(a, b) {\n                    i++;\n                    if(i <= 4) {\n                        arr[i+2] = a+3;\n                    };\n                    return b;\n                });\n                expect(arr).toEqual({\n                    0: 1,\n                    1: 2,\n                    2: 3,\n                    3: 6,\n                    4: 5,\n                    length: 3 // does not get updated on property assignment\n                });\n                expect(i).toBe(2);\n            });\n            it('should work as expected for empty arrays', function() {\n                var spy = jasmine.createSpy();\n                expect(function() {\n                    Array.prototype.reduceRight.call({length:0}, spy);\n                }).toThrow();\n                expect(spy).not.toHaveBeenCalled();\n            });\n            it('should throw correctly if no callback is given', function() {\n                expect(function() {\n                    testSubject.reduceRight();\n                }).toThrow();\n            });\n            it('should return the expected result', function() {\n                expect(testSubject.reduceRight(function(a,b) {\n                    return (a||'').toString()+(b||'').toString();\n                })).toEqual('321');\n            });\n            it('should not directly affect the passed array', function() {\n                var copy = createArrayLikeFromArray(testSubject);\n                testSubject.reduceRight(function(a,b) {\n                    return a+b;\n                });\n                delete(testSubject.reduceRight);\n                expect(testSubject).toEqual(copy);\n            });\n            it('should skip non-set values', function() {\n                delete testSubject[1];\n                var visited = {};\n                testSubject.reduceRight(function(a,b) {\n                    if(a)\n                        visited[a] = true;\n                    if(b)\n                        visited[b] = true;\n                    return 0;\n                });\n\n                expect(visited).toEqual({ '1': true, '3': true });\n            });\n            it('should have the right length', function() {\n                expect(testSubject.reduceRight.length).toBe(1);\n            });\n        });\n    });\n\n    describe('isArray', function () {\n        it('should work for Array', function () {\n            var ret = Array.isArray([]);\n\n            expect(ret).toBe(true);\n        });\n\n        it('should fail for other objects', function () {\n            var objects = [\n                \"someString\",\n                true,\n                false,\n                42,\n                0,\n                {},\n                Object.create && Object.create(null) || null,\n                /foo/,\n                arguments,\n                document.getElementsByTagName(\"div\")\n            ];\n\n            objects.forEach(function (v) {\n                expect(Array.isArray(v)).toBe(false);\n            });\n        });\n    });\n\n    describe('unshift', function () {\n        it('should return length', function () {\n            expect([].unshift(0)).toEqual(1);\n        });\n    });\n\n    describe('splice', function () {\n        var b = [\"b\"],\n            a = [1, \"a\", b],\n            test;\n\n        var makeArray = function(l, prefix) {\n            prefix = prefix || \"\";\n            var a = [];\n            while (l--) {\n                a.unshift(prefix + Array(l + 1).join(\" \") + l)\n            }\n            return a\n        };\n\n        beforeEach(function() {\n            test = a.slice(0);\n        });\n\n        it('basic implementation test 1', function () {\n            expect(test.splice(0)).toEqual(a);\n        });\n        it('basic implementation test 2', function () {\n            test.splice(0, 2);\n            expect(test).toEqual([b]);\n        });\n\n        it('should return right result 1', function () {\n            expect((function() {\n                var array = [];\n\n                array.splice(0, 0, 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20);\n                array.splice(1, 0, \"F1\", \"F2\", \"F3\", \"F4\", \"F5\", \"F6\", \"F7\", \"F8\", \"F9\", \"F10\", \"F11\", \"F12\", \"F13\", \"F14\", \"F15\", \"F16\", \"F17\", \"F18\", \"F19\", \"F20\", \"F21\",\"F22\", \"F23\", \"F24\", \"F25\", \"F26\");\n                array.splice(5, 0, \"XXX\");\n\n                return array.join(\"|\");\n            }())).toBe(\"1|F1|F2|F3|F4|XXX|F5|F6|F7|F8|F9|F10|F11|F12|F13|F14|F15|F16|F17|F18|F19|F20|F21|F22|F23|F24|F25|F26|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20\");\n        });\n\n        it('should return right result 2', function () {\n            expect((function() {\n                var array = makeArray(6);\n\n                array.splice(array.length - 1, 1, \"\");\n                array.splice(0, 1, 1,2,3,4);\n                array.splice(0, 0, 1,2,3,4,5,6,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,45);\n\n                array.splice(4, 0, \"99999999999999\");\n                return array.join(\"|\");\n            }())).toBe(\"1|2|3|4|99999999999999|5|6|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|45|1|2|3|4| 1|  2|   3|    4|\");\n        });\n\n        it('should return right result 3', function () {\n            expect((function() {\n                var array = [1,2,3];\n\n                array.splice(0);\n                array.splice(0, 1, 1,2,3,4,5,6,7,8,9,10);\n                array.splice(1, 1, \"F1\", \"F2\", \"F3\", \"F4\", \"F5\", \"F6\", \"F7\", \"F8\", \"F9\", \"F10\", \"F11\", \"F12\", \"F13\", \"F14\", \"F15\", \"F16\", \"F17\", \"F18\", \"F19\", \"F20\", \"F21\",\"F22\", \"F23\", \"F24\", \"F25\", \"F26\");\n                array.splice(5, 1, \"YYY\", \"XXX\");\n                array.splice(0, 1);\n                array.splice(0, 2);\n                array.pop();\n                array.push.apply(array, makeArray(10, \"-\"));\n                array.splice(array.length - 2, 10);\n                array.splice();\n                array.splice(1, 1, 1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9);\n                array.splice(1, 1, \"F1\", \"F2\", \"F3\", \"F4\", \"F5\", \"F6\", \"F7\", \"F8\", \"F9\", \"F10\", \"F11\", \"F12\", \"F13\", \"F14\", \"F15\", \"F16\", \"F17\", \"F18\", \"F19\", \"F20\", \"F21\",\"F22\", \"F23\", \"F24\", \"F25\", \"F26\",1,23,4,5,6,7,8);\n                array.splice(30, 10);\n                array.splice(30, 1);\n                array.splice(30, 0);\n                array.splice(2, 5, 1,2,3,\"P\", \"LLL\", \"CCC\", \"YYY\", \"XXX\");\n                array.push(1,2,3,4,5,6);\n                array.splice(1, 6, 1,2,3,4,5,6,7,8,9,4,5,6,7,8,9);\n                array.splice(3, 7);\n                array.unshift(7,8,9,10,11);\n                array.pop();\n                array.splice(5, 2);\n                array.pop();\n                array.unshift.apply(array, makeArray(8, \"~\"));\n                array.pop();\n                array.splice(3, 1, \"F1\", \"F2\", \"F3\", \"F4\", \"F5\", \"F6\", \"F7\", \"F8\", \"F9\", \"F10\", \"F11\", \"F12\", \"F13\", \"F14\", \"F15\", \"F16\", \"F17\", \"F18\", \"F19\", \"F20\", \"F21\",\"F22\", \"F23\", \"F24\", \"F25\", \"F26\",1,23,4,5,6,7,8);\n                array.splice(4, 5, \"P\", \"LLL\", \"CCC\", \"YYY\", \"XXX\");\n\n                return array.join(\"|\");\n            }())).toBe(\"~0|~ 1|~  2|F1|P|LLL|CCC|YYY|XXX|F7|F8|F9|F10|F11|F12|F13|F14|F15|F16|F17|F18|F19|F20|F21|F22|F23|F24|F25|F26|1|23|4|5|6|7|8|~    4|~     5|~      6|~       7|7|8|9|10|11|2|4|5|6|7|8|9|CCC|YYY|XXX|F7|F8|F9|F10|F11|F12|F13|F14|F15|F16|F17|F18|F19|F20|F21|F22|F23|F24|F25|F26|1|23|4|9|10|1|2|3|4|5|6|7|8|9|YYY|XXX|F6|F7|F8|F9|F10|F11|F12|F13|F14|F15|F16|F17|F18|F19|F20|F21|F22|F23|F24|F25|F26|3|4|5|6|7|8|9|-0|- 1|-  2|-   3|-    4|-     5|-      6|-       7|1|2|3\");\n        });\n\n\n        it('should do nothing if method called with no arguments', function () {\n            expect(test.splice()).toEqual([]);\n            expect(test).toEqual(a);\n        });\n        //TODO:: Is this realy TRUE behavior?\n        it('should set first argument to 0 if first argument is set but undefined', function () {\n            var test2 = test.slice(0);\n            expect(test.splice(void 0, 2)).toEqual(test2.splice(0, 2));\n            expect(test).toEqual(test2);\n        });\n\n        it('should deleted and return all items after \"start\" when second argument is undefined', function () {\n            expect(test.splice(0)).toEqual(a);\n            expect(test).toEqual([]);\n        });\n        it('should deleted and return all items after \"start\" when second argument is undefined', function () {\n            expect(test.splice(2)).toEqual([b]);\n            expect(test).toEqual([1, \"a\"]);\n        });\n        it('runshould have the right length', function () {\n            expect(test.splice.length).toBe(2);\n        });\n    });\n\n\n});\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/es5-shim-15.3.4.5/tests/spec/s-date.js",
    "content": "describe('Date', function () {\n    \n    describe('now', function () {\n        it('should be the current time', function () {\n            expect(Date.now() === new Date().getTime()).toBe(true);\n        });\n    });\n\n    describe(\"parse\", function () {\n        // TODO: Write the rest of the test.\n\n        it('should support extended years', function () {\n\n            expect(Date.parse('0001-01-01T00:00:00Z')).toBe(-62135596800000);\n            expect(Date.parse('+275760-09-13T00:00:00.000Z')).toBe(8.64e15);\n            expect(Date.parse('+033658-09-27T01:46:40.000Z')).toBe(1e15);\n            expect(Date.parse('-000001-01-01T00:00:00Z')).toBe(-62198755200000);\n            expect(Date.parse('+002009-12-15T00:00:00Z')).toBe(1260835200000);\n\n        });\n\n        it('should work', function () {\n                                                                                  //Chrome 19     Opera 12      Firefox 11    IE 9          Safari 5.1.1\n            expect(Date.parse(\"2012-11-31T23:59:59.000Z\")).toBeFalsy();           //1354406399000 NaN           NaN           1354406399000 NaN\n            expect(Date.parse(\"2012-12-31T23:59:59.000Z\")).toBe(1356998399000);   //1356998399000 1356998399000 1356998399000 1356998399000 1356998399000\n            expect(Date.parse(\"2012-12-31T23:59:60.000Z\")).toBeFalsy();           //NaN           NaN           NaN           NaN           1356998400000\n            expect(Date.parse(\"2012-04-04T05:02:02.170Z\")).toBe(1333515722170);   //1333515722170 1333515722170 1333515722170 1333515722170 1333515722170\n            expect(Date.parse(\"2012-04-04T05:02:02.170999Z\")).toBe(1333515722170);   //1333515722170 1333515722170 1333515722170 1333515722170 1333515722170\n            expect(Date.parse(\"2012-04-04T05:02:02.17Z\")).toBe(1333515722170);    //1333515722170 1333515722170 1333515722170 1333515722170 1333515722170\n            expect(Date.parse(\"2012-04-04T05:02:02.1Z\")).toBe(1333515722100);     //1333515722170 1333515722170 1333515722170 1333515722170 1333515722170\n            expect(Date.parse(\"2012-04-04T24:00:00.000Z\")).toBe(1333584000000);   //NaN           1333584000000 1333584000000 1333584000000 1333584000000\n            expect(Date.parse(\"2012-04-04T24:00:00.500Z\")).toBeFalsy();           //NaN           NaN           1333584000500 1333584000500 NaN\n            expect(Date.parse(\"2012-12-31T10:08:60.000Z\")).toBeFalsy();           //NaN           NaN           NaN           NaN           1356948540000\n            expect(Date.parse(\"2012-13-01T12:00:00.000Z\")).toBeFalsy();           //NaN           NaN           NaN           NaN           NaN\n            expect(Date.parse(\"2012-12-32T12:00:00.000Z\")).toBeFalsy();           //NaN           NaN           NaN           NaN           NaN\n            expect(Date.parse(\"2012-12-31T25:00:00.000Z\")).toBeFalsy();           //NaN           NaN           NaN           NaN           NaN\n            expect(Date.parse(\"2012-12-31T24:01:00.000Z\")).toBeFalsy();           //NaN           NaN           NaN           1356998460000 NaN\n            expect(Date.parse(\"2012-12-31T12:60:00.000Z\")).toBeFalsy();           //NaN           NaN           NaN           NaN           NaN\n            expect(Date.parse(\"2012-12-31T12:00:60.000Z\")).toBeFalsy();           //NaN           NaN           NaN           NaN           1356955260000\n            expect(Date.parse(\"2012-00-31T23:59:59.000Z\")).toBeFalsy();           //NaN           NaN           NaN           NaN           NaN\n            expect(Date.parse(\"2012-12-00T23:59:59.000Z\")).toBeFalsy();           //NaN           NaN           NaN           NaN           NaN\n            expect(Date.parse(\"2012-02-29T12:00:00.000Z\")).toBe(1330516800000);   //1330516800000 1330516800000 1330516800000 1330516800000 1330516800000\n            expect(Date.parse(\"2011-02-29T12:00:00.000Z\")).toBeFalsy();           //1298980800000 NaN           NaN           1298980800000 NaN\n            expect(Date.parse(\"2011-03-01T12:00:00.000Z\")).toBe(1298980800000);   //1298980800000 1298980800000 1298980800000 1298980800000 1298980800000\n\n            // extended years:\n            expect(Date.parse(\"0000-01-01T00:00:00.000Z\")).toBe(-621672192e5);    //-621672192e5  -621672192e5  -621672192e5  -621672192e5  -621672192e5\n            expect(Date.parse(\"+275760-09-13T00:00:00.000Z\")).toBe(8.64e15);      //8.64e15       NaN           8.64e15       8.64e15       8.64e15\n            expect(Date.parse(\"-271821-04-20T00:00:00.000Z\")).toBe(-8.64e15);     //-8.64e15      NaN           -8.64e15      -8.64e15      -8.6400000864e15\n            expect(Date.parse(\"+275760-09-13T00:00:00.001Z\")).toBeFalsy();        //NaN           NaN           NaN           8.64e15 + 1   8.64e15 + 1\n            expect(Date.parse(\"-271821-04-19T23:59:59.999Z\")).toBeFalsy();        //NaN           NaN           NaN           -8.64e15 - 1  -8.6400000864e15 - 1\n\n            // https://github.com/kriskowal/es5-shim/issues/80 Safari bug with leap day\n            expect(Date.parse(\"2034-03-01T00:00:00.000Z\") -\n                        Date.parse(\"2034-02-27T23:59:59.999Z\")).toBe(86400001);   //86400001      86400001       86400001       86400001      1\n\n            // Time Zone Offset\n            expect(Date.parse(\"2012-01-29T12:00:00.000+01:00\")).toBe(132783480e4);//132783480e4 132783480e4  132783480e4  132783480e4     132783480e4\n            expect(Date.parse(\"2012-01-29T12:00:00.000-00:00\")).toBe(132783840e4);//132783840e4 132783840e4  132783840e4  132783840e4     132783840e4\n            expect(Date.parse(\"2012-01-29T12:00:00.000+00:00\")).toBe(132783840e4);//132783840e4 132783840e4  132783840e4  132783840e4     132783840e4\n            expect(Date.parse(\"2012-01-29T12:00:00.000+23:59\")).toBe(132775206e4);//132775206e4 132775206e4  132775206e4  132775206e4     132775206e4\n            expect(Date.parse(\"2012-01-29T12:00:00.000-23:59\")).toBe(132792474e4);//132792474e4 132792474e4  132792474e4  132792474e4     132792474e4\n            expect(Date.parse(\"2012-01-29T12:00:00.000+24:00\")).toBeFalsy();      //NaN         1327752e6    NaN          1327752000000   1327752000000\n            expect(Date.parse(\"2012-01-29T12:00:00.000+24:01\")).toBeFalsy();      //NaN         NaN          NaN          1327751940000   1327751940000\n            expect(Date.parse(\"2012-01-29T12:00:00.000+24:59\")).toBeFalsy();      //NaN         NaN          NaN          1327748460000   1327748460000\n            expect(Date.parse(\"2012-01-29T12:00:00.000+25:00\")).toBeFalsy();      //NaN         NaN          NaN          NaN             NaN\n            expect(Date.parse(\"2012-01-29T12:00:00.000+00:60\")).toBeFalsy();      //NaN         NaN          NaN          NaN             NaN\n            expect(Date.parse(\"-271821-04-20T00:00:00.000+00:01\")).toBeFalsy();   //NaN         NaN          NaN          -864000000006e4 -864000008646e4\n            expect(Date.parse(\"-271821-04-20T00:01:00.000+00:01\")).toBe(-8.64e15);//-8.64e15    NaN          -8.64e15     -8.64e15        -864000008640e4\n\n            // When time zone is missed, local offset should be used (ES 5.1 bug)\n            // see https://bugs.ecmascript.org/show_bug.cgi?id=112\n            var tzOffset = Number(new Date(1970, 0));\n            // same as (new Date().getTimezoneOffset() * 60000)\n            expect(Date.parse('1970-01-01T00:00:00')).toBe(tzOffset);             //tzOffset    0            0            0               NaN\n        });\n\n        it(\"should be able to coerce to a number\", function(){\n            var actual = Number(new Date(1970, 0));\n            var expected = parseInt(actual, 10);\n            expect(actual).toBeDefined();\n            expect(actual).toEqual(expected);\n            expect(isNaN(actual)).toBeFalsy();\n        });\n\n    });\n\n    describe(\"toString\", function(){\n        var actual = (new Date(1970, 0)).toString();\n        beforeEach(function(){\n            actual = (new Date(1970, 0)).toString();\n        });\n        it(\"should show correct date info for \"+actual, function(){\n            expect(actual).toMatch(/1970/);\n            expect(actual).toMatch(/jan/i);\n            expect(actual).toMatch(/thu/i);\n            expect(actual).toMatch(/00:00:00/);\n        });\n    });\n\n    describe(\"valueOf\", function(){\n        var actual = (new Date(1970, 0));\n        beforeEach(function(){\n            actual = (new Date(1970, 0)).valueOf();\n        });\n        it(\"should give an int value\", function(){\n            expect(parseInt(actual, 10)).toBeTruthy();\n        });\n    });\n\n    describe(\"toISOString\", function () {\n        // TODO: write the rest of the test.\n       \n        it('should support extended years', function () {\n            expect(new Date(-62198755200000).toISOString().indexOf('-000001-01-01')).toBe(0);\n            expect(new Date(8.64e15).toISOString().indexOf('+275760-09-13')).toBe(0);\n        });\n\n        it('should return correct dates', function () {\n            expect(new Date(-1).toISOString()).toBe('1969-12-31T23:59:59.999Z');// Safari 5.1.5 \"1969-12-31T23:59:59.-01Z\"\n            expect(new Date(-3509827334573292).toISOString()).toBe('-109252-01-01T10:37:06.708Z'); // Opera 11.61/Opera 12 bug with Date#getUTCMonth\n        });\n\n    });\n\n    describe(\"toJSON\", function () {\n\n        // Opera 11.6x/12 bug\n        it('should call toISOString', function () {\n          var date = new Date(0);\n          date.toISOString = function () {\n            return 1;\n          };\n          expect(date.toJSON()).toBe(1);\n        });\n\n        it('should return null for not finite dates', function () {\n          var date = new Date(NaN),\n              json;\n          try {\n            json = date.toJSON();\n          } catch (e) {}\n          expect(json).toBe(null);\n        });\n\n        it('should return the isoString when stringified', function () {\n            var date = new Date();\n            expect(JSON.stringify(date.toISOString())).toBe(JSON.stringify(date));\n        }) \n    });\n\n});"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/es5-shim-15.3.4.5/tests/spec/s-function.js",
    "content": "\ndescribe('Function', function() {\n    \"use strict\";\n    describe('bind', function() {\n        var actual, expected,\n            testSubject;\n        \n        testSubject = {\n            push: function(o) {\n                this.a.push(o);\n            }\n        };\n        \n        function func() {\n            Array.prototype.forEach.call(arguments, function(a) {\n                this.push(a);\n            }, this);\n            return this;\n        };\n        \n        beforeEach(function() {\n            actual = [];\n            testSubject.a = [];\n        });\n        \n        it('binds properly without a context', function() {\n            var context;\n            testSubject.func = function() {\n                context = this;\n            }.bind();\n            testSubject.func();\n            expect(context).toBe(function() {return this}.call());\n        });\n        it('binds properly without a context, and still supplies bound arguments', function() {\n            var a, context;\n            testSubject.func = function() {\n                a = Array.prototype.slice.call(arguments);\n                context = this;\n            }.bind(undefined, 1,2,3);\n            testSubject.func(1,2,3);\n            expect(a).toEqual([1,2,3,1,2,3]);\n            expect(context).toBe(function() {return this}.call());\n        });\n        it('binds a context properly', function() {\n            testSubject.func = func.bind(actual);\n            testSubject.func(1,2,3);\n            expect(actual).toEqual([1,2,3]);\n            expect(testSubject.a).toEqual([]);\n        });\n        it('binds a context and supplies bound arguments', function() {\n            testSubject.func = func.bind(actual, 1,2,3);\n            testSubject.func(4,5,6);\n            expect(actual).toEqual([1,2,3,4,5,6]);\n            expect(testSubject.a).toEqual([]);\n        });\n        \n        it('returns properly without binding a context', function() {\n            testSubject.func = function() {\n                return this;\n            }.bind();\n            var context = testSubject.func();\n            expect(context).toBe(function() {return this}.call());\n        });\n        it('returns properly without binding a context, and still supplies bound arguments', function() {\n            var context;\n            testSubject.func = function() {\n                context = this;\n                return Array.prototype.slice.call(arguments);\n            }.bind(undefined, 1,2,3);\n            actual = testSubject.func(1,2,3);\n            expect(context).toBe(function() {return this}.call());\n            expect(actual).toEqual([1,2,3,1,2,3]);\n        });\n        it('returns properly while binding a context properly', function() {\n            var ret;\n            testSubject.func = func.bind(actual);\n            ret = testSubject.func(1,2,3);\n            expect(ret).toBe(actual);\n            expect(ret).not.toBe(testSubject);\n        });\n        it('returns properly while binding a context and supplies bound arguments', function() {\n            var ret;\n            testSubject.func = func.bind(actual, 1,2,3);\n            ret = testSubject.func(4,5,6);\n            expect(ret).toBe(actual);\n            expect(ret).not.toBe(testSubject);\n        });\n        it('passes the correct arguments as a constructor', function() {\n            var ret, expected = { name: \"Correct\" };\n            testSubject.func = function(arg) {\n                return arg;\n            }.bind({ name: \"Incorrect\" });\n            ret = new testSubject.func(expected);\n            expect(ret).toBe(expected);\n        });\n        it('returns the return value of the bound function when called as a constructor', function () {\n            var oracle = [1, 2, 3];\n            var subject = function () {\n                return oracle;\n            }.bind(null);\n            var result = new subject;\n            expect(result).toBe(oracle);\n        });\n        it('returns the correct value if constructor returns primitive', function() {\n            var oracle = [1, 2, 3];\n            var subject = function () {\n                return oracle;\n            }.bind(null);\n            var result = new subject;\n            expect(result).toBe(oracle);\n\n            oracle = {};\n            result = new subject;\n            expect(result).toBe(oracle);\n\n            oracle = function(){};\n            result = new subject;\n            expect(result).toBe(oracle);\n\n            oracle = \"asdf\";\n            result = new subject;\n            expect(result).not.toBe(oracle);\n\n            oracle = null;\n            result = new subject;\n            expect(result).not.toBe(oracle);\n\n            oracle = true;\n            result = new subject;\n            expect(result).not.toBe(oracle);\n\n            oracle = 1;\n            result = new subject;\n            expect(result).not.toBe(oracle);\n        });\n        it('returns the value that instance of original \"class\" when called as a constructor', function() {\n            var classA = function(x) {\n                this.name = x || \"A\";\n            }\n            var classB = classA.bind(null, \"B\");\n            \n            var result = new classB;\n            expect(result instanceof classA).toBe(true);\n            expect(result instanceof classB).toBe(true);\n        });\n    });\n});\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/es5-shim-15.3.4.5/tests/spec/s-number.js",
    "content": "describe('Number', function () {\n    'use strict';\n    \n    describe('toFixed', function () {\n        it('should convert numbers correctly', function () {\n            expect((0.00008).toFixed(3)).toBe('0.000');\n            expect((0.9).toFixed(0)).toBe('1');\n            expect((1.255).toFixed(2)).toBe('1.25');\n            expect((1843654265.0774949).toFixed(5)).toBe('1843654265.07749');\n            expect((1000000000000000128).toFixed(0)).toBe('1000000000000000128');\n        });\n    });\n\n});\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/es5-shim-15.3.4.5/tests/spec/s-object.js",
    "content": "describe('Object', function () {\n    \"use strict\";\n\n    describe(\"Object.keys\", function () {\n        var obj = {\n            \"str\": \"boz\",\n            \"obj\": { },\n            \"arr\": [],\n            \"bool\": true,\n            \"num\": 42,\n            \"null\": null,\n            \"undefined\": undefined\n        };\n\n        var loopedValues = [];\n        for (var k in obj) {\n            loopedValues.push(k);\n        }\n\n        var keys = Object.keys(obj);\n        it('should have correct length', function () {\n            expect(keys.length).toBe(7);\n        });\n\n        it('should return an Array', function () {\n            expect(Array.isArray(keys)).toBe(true);\n        });\n\n        it('should return names which are own properties', function () {\n            keys.forEach(function (name) {\n                expect(obj.hasOwnProperty(name)).toBe(true);\n            });\n        });\n\n        it('should return names which are enumerable', function () {\n            keys.forEach(function (name) {\n                expect(loopedValues.indexOf(name)).toNotBe(-1);\n            })\n        });\n\n        it('should throw error for non object', function () {\n            var e = {};\n            expect(function () {\n                try {\n                    Object.keys(42)\n                } catch (err) {\n                    throw e;\n                }\n            }).toThrow(e);\n        });\n    });\n\n\tdescribe(\"Object.isExtensible\", function () {\n        var obj = { };\n\n        it('should return true if object is extensible', function () {\n            expect(Object.isExtensible(obj)).toBe(true);\n        });\n\n        it('should return false if object is not extensible', function () {\n            expect(Object.isExtensible(Object.preventExtensions(obj))).toBe(false);\n        });\n\n        it('should return false if object is seal', function () {\n            expect(Object.isExtensible(Object.seal(obj))).toBe(false);\n        });\n\n        it('should return false if object is freeze', function () {\n            expect(Object.isExtensible(Object.freeze(obj))).toBe(false);\n        });\n\n        it('should throw error for non object', function () {\n            var e1 = {};\n            expect(function () {\n                try {\n                    Object.isExtensible(42)\n                } catch (err) {\n                    throw e1;\n                }\n            }).toThrow(e1);\n        });\n    });\n\n\tdescribe(\"Object.defineProperty\", function () {\n        var obj;\n\n        beforeEach(function() {\n           obj = {};\n\n           Object.defineProperty(obj, 'name', {\n               value : 'Testing',\n               configurable: true,\n               enumerable: true,\n               writable: true\n           });\n        });\n\n        it('should return the initial value', function () {\n            expect(obj.hasOwnProperty('name')).toBeTruthy();\n            expect(obj.name).toBe('Testing');\n        });\n\n        it('should be setable', function () {\n            obj.name = 'Other';\n            expect(obj.name).toBe('Other');\n        });\n\n        it('should return the parent initial value', function () {\n            var child = Object.create(obj, {});\n\n            expect(child.name).toBe('Testing');\n            expect(child.hasOwnProperty('name')).toBeFalsy();\n        });\n\n        it('should not override the parent value', function () {\n            var child = Object.create(obj, {});\n\n            Object.defineProperty(child, 'name', {\n                value : 'Other'\n            });\n\n            expect(obj.name).toBe('Testing');\n            expect(child.name).toBe('Other');\n        });\n\n        it('should throw error for non object', function () {\n            expect(function () {\n                Object.defineProperty(42, 'name', {});\n            }).toThrow();\n        });\n    });\n\n\tdescribe(\"Object.getOwnPropertyDescriptor\", function () {\n        it('should return undefined because the object does not own the property', function () {\n            var descr = Object.getOwnPropertyDescriptor({}, 'name');\n\n            expect(descr).toBeUndefined()\n        });\n\n        it('should return a data descriptor', function () {\n            var descr = Object.getOwnPropertyDescriptor({name: 'Testing'}, 'name');\n\n            expect(descr).not.toBeUndefined();\n            expect(descr.value).toBe('Testing');\n            expect(descr.writable).toBe(true);\n            expect(descr.enumerable).toBe(true);\n            expect(descr.configurable).toBe(true);\n        });\n\n        it('should return undefined because the object does not own the property', function () {\n            var descr = Object.getOwnPropertyDescriptor(Object.create({name: 'Testing'}, {}), 'name');\n\n            expect(descr).toBeUndefined()\n        });\n\n        it('should return a data descriptor', function () {\n            var obj = Object.create({}, {\n                name: {\n                    value : 'Testing',\n                    configurable: true,\n                    enumerable: true,\n                    writable: true\n                }\n            });\n\n            var descr = Object.getOwnPropertyDescriptor(obj, 'name');\n\n            expect(descr).not.toBeUndefined();\n            expect(descr.value).toBe('Testing');\n            expect(descr.writable).toBe(true);\n            expect(descr.enumerable).toBe(true);\n            expect(descr.configurable).toBe(true);\n        });\n\n    \tit('should throw error for non object', function () {\n            expect(function () {\n                Object.getOwnPropertyDescriptor(42, 'name');\n            }).toThrow();\n        });\n    });\n});\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/es5-shim-15.3.4.5/tests/spec/s-string.js",
    "content": "describe('String', function() {\n    \"use strict\";\n    describe(\"trim\", function() {\n        var test = \"\\x09\\x0A\\x0B\\x0C\\x0D\\x20\\xA0\\u1680\\u180E\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200A\\u202F\\u205F\\u3000\\u2028\\u2029\\uFEFFHello, World!\\x09\\x0A\\x0B\\x0C\\x0D\\x20\\xA0\\u1680\\u180E\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200A\\u202F\\u205F\\u3000\\u2028\\u2029\\uFEFF\";\n\n        it('trims all ES5 whitespace', function() {\n            expect(test.trim()).toEqual(\"Hello, World!\");\n            expect(test.trim().length).toEqual(13);\n        });\n    });\n\n    describe(\"split\", function() {\n        var test = \"ab\";\n\n        it('If \"separator\" is undefined must return Array with one String - \"this\" string', function() {\n            expect(test.split()).toEqual([test]);\n            expect(test.split(void 0)).toEqual([test]);\n        });\n\n        it('If \"separator\" is undefined and \"limit\" set to 0 must return Array[]', function() {\n            expect(test.split(void 0, 0)).toEqual([]);\n        });\n\n        describe('Tests from Steven Levithan', function () {\n            it(\"''.split() results in ['']\", function () {\n                expect(''.split()).toEqual(['']);\n            });\n            it(\"''.split(/./) results in ['']\", function () {\n                expect(''.split(/./)).toEqual(['']);\n            });\n            it(\"''.split(/.?/) results in []\", function () {\n                expect(''.split(/.?/)).toEqual([]);\n            });\n            it(\"''.split(/.??/) results in []\", function () {\n                expect(''.split(/.??/)).toEqual([]);\n            });\n            it(\"'ab'.split(/a*/) results in ['', 'b']\", function () {\n                expect('ab'.split(/a*/)).toEqual(['', 'b']);\n            });\n            it(\"'ab'.split(/a*?/) results in ['a', 'b']\", function () {\n                expect('ab'.split(/a*?/)).toEqual(['a', 'b']);\n            });\n            it(\"'ab'.split(/(?:ab)/) results in ['', '']\", function () {\n                expect('ab'.split(/(?:ab)/)).toEqual(['', '']);\n            });\n            it(\"'ab'.split(/(?:ab)*/) results in ['', '']\", function () {\n                expect('ab'.split(/(?:ab)*/)).toEqual(['', '']);\n            });\n            it(\"'ab'.split(/(?:ab)*?/) results in ['a', 'b']\", function () {\n                expect('ab'.split(/(?:ab)*?/)).toEqual(['a', 'b']);\n            });\n            it(\"'test'.split('') results in ['t', 'e', 's', 't']\", function () {\n                expect('test'.split('')).toEqual(['t', 'e', 's', 't']);\n            });\n            it(\"'test'.split() results in ['test']\", function () {\n                expect('test'.split()).toEqual(['test']);\n            });\n            it(\"'111'.split(1) results in ['', '', '', '']\", function () {\n                expect('111'.split(1)).toEqual(['', '', '', '']);\n            });\n            it(\"'test'.split(/(?:)/, 2) results in ['t', 'e']\", function () {\n                expect('test'.split(/(?:)/, 2)).toEqual(['t', 'e']);\n            });\n            it(\"'test'.split(/(?:)/, -1) results in ['t', 'e', 's', 't']\", function () {\n                expect('test'.split(/(?:)/, -1)).toEqual(['t', 'e', 's', 't']);\n            });\n            it(\"'test'.split(/(?:)/, undefined) results in ['t', 'e', 's', 't']\", function () {\n                expect('test'.split(/(?:)/, undefined)).toEqual(['t', 'e', 's', 't']);\n            });\n            it(\"'test'.split(/(?:)/, null) results in []\", function () {\n                expect('test'.split(/(?:)/, null)).toEqual([]);\n            });\n            it(\"'test'.split(/(?:)/, NaN) results in []\", function () {\n                expect('test'.split(/(?:)/, NaN)).toEqual([]);\n            });\n            it(\"'test'.split(/(?:)/, true) results in ['t']\", function () {\n                expect('test'.split(/(?:)/, true)).toEqual(['t']);\n            });\n            it(\"'test'.split(/(?:)/, '2') results in ['t', 'e']\", function () {\n                expect('test'.split(/(?:)/, '2')).toEqual(['t', 'e']);\n            });\n            it(\"'test'.split(/(?:)/, 'two') results in []\", function () {\n                expect('test'.split(/(?:)/, 'two')).toEqual([]);\n            });\n            it(\"'a'.split(/-/) results in ['a']\", function () {\n                expect('a'.split(/-/)).toEqual(['a']);\n            });\n            it(\"'a'.split(/-?/) results in ['a']\", function () {\n                expect('a'.split(/-?/)).toEqual(['a']);\n            });\n            it(\"'a'.split(/-??/) results in ['a']\", function () {\n                expect('a'.split(/-??/)).toEqual(['a']);\n            });\n            it(\"'a'.split(/a/) results in ['', '']\", function () {\n                expect('a'.split(/a/)).toEqual(['', '']);\n            });\n            it(\"'a'.split(/a?/) results in ['', '']\", function () {\n                expect('a'.split(/a?/)).toEqual(['', '']);\n            });\n            it(\"'a'.split(/a??/) results in ['a']\", function () {\n                expect('a'.split(/a??/)).toEqual(['a']);\n            });\n            it(\"'ab'.split(/-/) results in ['ab']\", function () {\n                expect('ab'.split(/-/)).toEqual(['ab']);\n            });\n            it(\"'ab'.split(/-?/) results in ['a', 'b']\", function () {\n                expect('ab'.split(/-?/)).toEqual(['a', 'b']);\n            });\n            it(\"'ab'.split(/-??/) results in ['a', 'b']\", function () {\n                expect('ab'.split(/-??/)).toEqual(['a', 'b']);\n            });\n            it(\"'a-b'.split(/-/) results in ['a', 'b']\", function () {\n                expect('a-b'.split(/-/)).toEqual(['a', 'b']);\n            });\n            it(\"'a-b'.split(/-?/) results in ['a', 'b']\", function () {\n                expect('a-b'.split(/-?/)).toEqual(['a', 'b']);\n            });\n            it(\"'a-b'.split(/-??/) results in ['a', '-', 'b']\", function () {\n                expect('a-b'.split(/-??/)).toEqual(['a', '-', 'b']);\n            });\n            it(\"'a--b'.split(/-/) results in ['a', '', 'b']\", function () {\n                expect('a--b'.split(/-/)).toEqual(['a', '', 'b']);\n            });\n            it(\"'a--b'.split(/-?/) results in ['a', '', 'b']\", function () {\n                expect('a--b'.split(/-?/)).toEqual(['a', '', 'b']);\n            });\n            it(\"'a--b'.split(/-??/) results in ['a', '-', '-', 'b']\", function () {\n                expect('a--b'.split(/-??/)).toEqual(['a', '-', '-', 'b']);\n            });\n            it(\"''.split(/()()/) results in []\", function () {\n                expect(''.split(/()()/)).toEqual([]);\n            });\n            it(\"'.'.split(/()()/) results in ['.']\", function () {\n                expect('.'.split(/()()/)).toEqual(['.']);\n            });\n            it(\"'.'.split(/(.?)(.?)/) results in ['', '.', '', '']\", function () {\n                expect('.'.split(/(.?)(.?)/)).toEqual(['', '.', '', '']);\n            });\n            it(\"'.'.split(/(.??)(.??)/) results in ['.']\", function () {\n                expect('.'.split(/(.??)(.??)/)).toEqual(['.']);\n            });\n            it(\"'.'.split(/(.)?(.)?/) results in ['', '.', undefined, '']\", function () {\n                expect('.'.split(/(.)?(.)?/)).toEqual(['', '.', undefined, '']);\n            });\n            it(\"'A<B>bold</B>and<CODE>coded</CODE>'.split(/<(\\\\/)?([^<>]+)>/) results in ['A', undefined, 'B', 'bold', '/', 'B', 'and', undefined, 'CODE', 'coded', '/', 'CODE', '']\", function () {\n                expect('A<B>bold</B>and<CODE>coded</CODE>'.split(/<(\\/)?([^<>]+)>/)).toEqual(['A', undefined, 'B', 'bold', '/', 'B', 'and', undefined, 'CODE', 'coded', '/', 'CODE', '']);\n            });\n            it(\"'tesst'.split(/(s)*/) results in ['t', undefined, 'e', 's', 't']\", function () {\n                expect('tesst'.split(/(s)*/)).toEqual(['t', undefined, 'e', 's', 't']);\n            });\n            it(\"'tesst'.split(/(s)*?/) results in ['t', undefined, 'e', undefined, 's', undefined, 's', undefined, 't']\", function () {\n                expect('tesst'.split(/(s)*?/)).toEqual(['t', undefined, 'e', undefined, 's', undefined, 's', undefined, 't']);\n            });\n            it(\"'tesst'.split(/(s*)/) results in ['t', '', 'e', 'ss', 't']\", function () {\n                expect('tesst'.split(/(s*)/)).toEqual(['t', '', 'e', 'ss', 't']);\n            });\n            it(\"'tesst'.split(/(s*?)/) results in ['t', '', 'e', '', 's', '', 's', '', 't']\", function () {\n                expect('tesst'.split(/(s*?)/)).toEqual(['t', '', 'e', '', 's', '', 's', '', 't']);\n            });\n            it(\"'tesst'.split(/(?:s)*/) results in ['t', 'e', 't']\", function () {\n                expect('tesst'.split(/(?:s)*/)).toEqual(['t', 'e', 't']);\n            });\n            it(\"'tesst'.split(/(?=s+)/) results in ['te', 's', 'st']\", function () {\n                expect('tesst'.split(/(?=s+)/)).toEqual(['te', 's', 'st']);\n            });\n            it(\"'test'.split('t') results in ['', 'es', '']\", function () {\n                expect('test'.split('t')).toEqual(['', 'es', '']);\n            });\n            it(\"'test'.split('es') results in ['t', 't']\", function () {\n                expect('test'.split('es')).toEqual(['t', 't']);\n            });\n            it(\"'test'.split(/t/) results in ['', 'es', '']\", function () {\n                expect('test'.split(/t/)).toEqual(['', 'es', '']);\n            });\n            it(\"'test'.split(/es/) results in ['t', 't']\", function () {\n                expect('test'.split(/es/)).toEqual(['t', 't']);\n            });\n            it(\"'test'.split(/(t)/) results in ['', 't', 'es', 't', '']\", function () {\n                expect('test'.split(/(t)/)).toEqual(['', 't', 'es', 't', '']);\n            });\n            it(\"'test'.split(/(es)/) results in ['t', 'es', 't']\", function () {\n                expect('test'.split(/(es)/)).toEqual(['t', 'es', 't']);\n            });\n            it(\"'test'.split(/(t)(e)(s)(t)/) results in ['', 't', 'e', 's', 't', '']\", function () {\n                expect('test'.split(/(t)(e)(s)(t)/)).toEqual(['', 't', 'e', 's', 't', '']);\n            });\n            it(\"'.'.split(/(((.((.??)))))/) results in ['', '.', '.', '.', '', '', '']\", function () {\n                expect('.'.split(/(((.((.??)))))/)).toEqual(['', '.', '.', '.', '', '', '']);\n            });\n            it(\"'.'.split(/(((((.??)))))/) results in ['.']\", function () {\n                expect('.'.split(/(((((.??)))))/)).toEqual(['.']);\n            });\n            it(\"'a b c d'.split(/ /, -(Math.pow(2, 32) - 1)) results in ['a']\", function () {\n                expect('a b c d'.split(/ /, -(Math.pow(2, 32) - 1))).toEqual(['a']);\n            });\n            it(\"'a b c d'.split(/ /, Math.pow(2, 32) + 1) results in ['a']\", function () {\n                expect('a b c d'.split(/ /, Math.pow(2, 32) + 1)).toEqual(['a']);\n            });\n            it(\"'a b c d'.split(/ /, Infinity) results in []\", function () {\n                expect('a b c d'.split(/ /, Infinity)).toEqual([]);\n            });\n        });\n    });\n});\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/jquery.autogrow-textarea.js",
    "content": "(function($)\n{\n    /**\n     * Auto-growing textareas; technique ripped from Facebook\n     *\n     * http://github.com/jaz303/jquery-grab-bag/tree/master/javascripts/jquery.autogrow-textarea.js\n     */\n    $.fn.autogrow = function(options)\n    {\n        return this.filter('textarea').each(function()\n        {\n            var self         = this;\n            var $self        = $(self);\n            var minHeight    = $self.height();\n            var noFlickerPad = $self.hasClass('autogrow-short') ? 0 : parseInt($self.css('lineHeight')) || 0;\n\n            var shadow = $('<div></div>').css({\n                position:    'absolute',\n                top:         -10000,\n                left:        -10000,\n                width:       $self.width(),\n                fontSize:    $self.css('fontSize'),\n                fontFamily:  $self.css('fontFamily'),\n                fontWeight:  $self.css('fontWeight'),\n                lineHeight:  $self.css('lineHeight'),\n                resize:      'none',\n                            'word-wrap': 'break-word'\n            }).appendTo(document.body);\n\n            var update = function(event)\n            {\n                var times = function(string, number)\n                {\n                    for (var i=0, r=''; i<number; i++) r += string;\n                    return r;\n                };\n\n                var val = self.value.replace(/</g, '&lt;')\n                                    .replace(/>/g, '&gt;')\n                                    .replace(/&/g, '&amp;')\n                                    .replace(/\\n$/, '<br/>&nbsp;')\n                                    .replace(/\\n/g, '<br/>')\n                                    .replace(/ {2,}/g, function(space){ return times('&nbsp;', space.length - 1) + ' ' });\n\n                                // Did enter get pressed?  Resize in this keydown event so that the flicker doesn't occur.\n                                if (event && event.data && event.data.event === 'keydown' && event.keyCode === 13) {\n                                        val += '<br />';\n                                }\n\n                shadow.css('width', $self.width());\n                shadow.html(val + (noFlickerPad === 0 ? '...' : '')); // Append '...' to resize pre-emptively.\n                $self.height(Math.max(shadow.height() + noFlickerPad, minHeight));\n            }\n\n            $self.change(update).keyup(update).keydown({event:'keydown'},update);\n            $(window).resize(update);\n\n            update();\n        });\n    };\n})(jQuery);"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/jquery_1.11.0/jquery.js",
    "content": "/*!\n * jQuery JavaScript Library v1.10.2\n * http://jquery.com/\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n *\n * Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors\n * Released under the MIT license\n * http://jquery.org/license\n *\n * Date: 2013-07-03T13:48Z\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<10\n\t// For `typeof xmlNode.method` instead of `xmlNode.method !== undefined`\n\tcore_strundefined = typeof undefined,\n\n\t// Use the correct document accordingly with window argument (sandbox)\n\tlocation = window.location,\n\tdocument = window.document,\n\tdocElem = document.documentElement,\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.10.2\",\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 = /^(?:\\s*(<[\\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\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\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\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\t/* jshint eqeqeq: false */\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\tvar key;\n\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// Support: IE<9\n\t\t// Handle iteration over inherited properties before own properties.\n\t\tif ( jQuery.support.ownLast ) {\n\t\t\tfor ( key in obj ) {\n\t\t\t\treturn core_hasOwn.call( obj, key );\n\t\t\t}\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\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 util 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\t// A method for quickly swapping in/out CSS properties to get correct calculations.\n\t// Note: this method belongs to the css module but it's needed here for the support module.\n\t// If support gets modularized, this method should be moved back to the css module.\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\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/*!\n * Sizzle CSS Selector Engine v1.10.2\n * http://sizzlejs.com/\n *\n * Copyright 2013 jQuery Foundation, Inc. and other contributors\n * Released under the MIT license\n * http://jquery.org/license\n *\n * Date: 2013-07-03\n */\n(function( window, undefined ) {\n\nvar i,\n\tsupport,\n\tcachedruns,\n\tExpr,\n\tgetText,\n\tisXML,\n\tcompile,\n\toutermostContext,\n\tsortInput,\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\" + -(new Date()),\n\tpreferredDoc = window.document,\n\tdirruns = 0,\n\tdone = 0,\n\tclassCache = createCache(),\n\ttokenCache = createCache(),\n\tcompilerCache = createCache(),\n\thasDuplicate = false,\n\tsortOrder = function( a, b ) {\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\t\treturn 0;\n\t},\n\n\t// General-purpose constants\n\tstrundefined = typeof undefined,\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 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\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// Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors\n\tattributes = \"\\\\[\" + whitespace + \"*(\" + characterEncoding + \")\" + whitespace +\n\t\t\"*(?:([*^$|!~]?=)\" + 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 + \"*([>+~]|\" + whitespace + \")\" + whitespace + \"*\" ),\n\n\trsibling = new RegExp( whitespace + \"*[+~]\" ),\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\trnative = /^[^{]+\\{\\s*\\[native \\w/,\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\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\n\t\t// Workaround erroneous numeric interpretation of +\"0x\"\n\t\treturn high !== high || escapedWhitespace ?\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// 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\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 ( documentIsHTML && !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, 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 && context.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 === 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,\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 * 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// Expose support vars for convenience\nsupport = Sizzle.support = {};\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\t\tparent = doc.defaultView;\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\tdocumentIsHTML = !isXML( doc );\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.attachEvent && parent !== parent.top ) {\n\t\tparent.attachEvent( \"onbeforeunload\", function() {\n\t\t\tsetDocument();\n\t\t});\n\t}\n\n\t/* Attributes\n\t---------------------------------------------------------------------- */\n\n\t// Support: IE<8\n\t// Verify that getAttribute really returns attributes and not properties (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// Check if getElementsByClassName can be trusted\n\tsupport.getElementsByClassName = assert(function( div ) {\n\t\tdiv.innerHTML = \"<div class='a'></div><div class='a i'></div>\";\n\n\t\t// Support: Safari<4\n\t\t// Catch class over-caching\n\t\tdiv.firstChild.className = \"i\";\n\t\t// Support: Opera<10\n\t\t// Catch gEBCN failure to find non-leading classes\n\t\treturn div.getElementsByClassName(\"i\").length === 2;\n\t});\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 !== strundefined && 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 !== 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.getElementsByTagName ?\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// Class\n\tExpr.find[\"CLASS\"] = support.getElementsByClassName && function( className, context ) {\n\t\tif ( typeof context.getElementsByClassName !== strundefined && 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\tdiv.innerHTML = \"<select><option selected=''></option></select>\";\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// 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// Support: Opera 10-12/IE8\n\t\t\t// ^= $= *= and empty values\n\t\t\t// Should not select anything\n\t\t\t// Support: Windows 8 Native Apps\n\t\t\t// The type attribute is 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( \"t\", \"\" );\n\n\t\t\tif ( div.querySelectorAll(\"[t^='']\").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 = rnative.test( (matches = docElem.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\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 = rnative.test( 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/* Sorting\n\t---------------------------------------------------------------------- */\n\n\t// Document order sorting\n\tsortOrder = docElem.compareDocumentPosition ?\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\tvar compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b );\n\n\t\tif ( compare ) {\n\t\t\t// Disconnected nodes\n\t\t\tif ( compare & 1 ||\n\t\t\t\t(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {\n\n\t\t\t\t// Choose the first element that is related to our preferred document\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\n\t\t\t\t// Maintain original order\n\t\t\t\treturn sortInput ?\n\t\t\t\t\t( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :\n\t\t\t\t\t0;\n\t\t\t}\n\n\t\t\treturn compare & 4 ? -1 : 1;\n\t\t}\n\n\t\t// Not directly comparable, sort on existence of method\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\tsortInput ?\n\t\t\t\t( indexOf.call( sortInput, a ) - indexOf.call( 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 util 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\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\t\tval;\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\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\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\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[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[3] && match[4] !== undefined ) {\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( 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 !== 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 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 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\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\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(\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\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\tsupport.getById && context.nodeType === 9 && documentIsHTML &&\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\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, seed );\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\t!documentIsHTML,\n\t\tresults,\n\t\trsibling.test( selector )\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\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 (val = elem.getAttributeNode( name )) && val.specified ?\n\t\t\t\tval.value :\n\t\t\t\telem[ name ] === true ? name.toLowerCase() : null;\n\t\t}\n\t});\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})( window );\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\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};\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( support ) {\n\n\tvar all, a, input, select, fragment, opt, 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// Finish early in limited (non-browser) environments\n\tall = div.getElementsByTagName(\"*\") || [];\n\ta = div.getElementsByTagName(\"a\")[ 0 ];\n\tif ( !a || !a.style || !all.length ) {\n\t\treturn support;\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\n\t// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)\n\tsupport.getSetAttribute = div.className !== \"t\";\n\n\t// IE strips leading whitespace when .innerHTML is used\n\tsupport.leadingWhitespace = div.firstChild.nodeType === 3;\n\n\t// Make sure that tbody elements aren't automatically inserted\n\t// IE will insert them into empty tables\n\tsupport.tbody = !div.getElementsByTagName(\"tbody\").length;\n\n\t// Make sure that link elements get serialized correctly by innerHTML\n\t// This requires a wrapper element in IE\n\tsupport.htmlSerialize = !!div.getElementsByTagName(\"link\").length;\n\n\t// Get the style information from getAttribute\n\t// (IE uses .cssText instead)\n\tsupport.style = /top/.test( a.getAttribute(\"style\") );\n\n\t// Make sure that URLs aren't manipulated\n\t// (IE normalizes it by default)\n\tsupport.hrefNormalized = a.getAttribute(\"href\") === \"/a\";\n\n\t// Make sure that element opacity exists\n\t// (IE uses filter instead)\n\t// Use a regex to work around a WebKit issue. See #5145\n\tsupport.opacity = /^0.5/.test( a.style.opacity );\n\n\t// Verify style float existence\n\t// (IE uses styleFloat instead of cssFloat)\n\tsupport.cssFloat = !!a.style.cssFloat;\n\n\t// Check the default checkbox/radio value (\"\" on WebKit; \"on\" elsewhere)\n\tsupport.checkOn = !!input.value;\n\n\t// Make sure that a selected-by-default option has a working selected property.\n\t// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)\n\tsupport.optSelected = opt.selected;\n\n\t// Tests for enctype support on a form (#6743)\n\tsupport.enctype = !!document.createElement(\"form\").enctype;\n\n\t// Makes sure cloning an html5 element does not cause problems\n\t// Where outerHTML is undefined, this still works\n\tsupport.html5Clone = document.createElement(\"nav\").cloneNode( true ).outerHTML !== \"<:nav></:nav>\";\n\n\t// Will be defined later\n\tsupport.inlineBlockNeedsLayout = false;\n\tsupport.shrinkWrapBlocks = false;\n\tsupport.pixelPosition = false;\n\tsupport.deleteExpando = true;\n\tsupport.noCloneEvent = true;\n\tsupport.reliableMarginRight = true;\n\tsupport.boxSizingReliable = true;\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)\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// Support: IE<9\n\t// Iteration over object's inherited properties before its own.\n\tfor ( i in jQuery( support ) ) {\n\t\tbreak;\n\t}\n\tsupport.ownLast = i !== \"0\";\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\n\t\t// Workaround failing boxSizing test due to offsetWidth returning wrong value\n\t\t// with some non-1 values of body zoom, ticket #13543\n\t\tjQuery.swap( body, body.style.zoom != null ? { zoom: 1 } : {}, function() {\n\t\t\tsupport.boxSizing = div.offsetWidth === 4;\n\t\t});\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 ret, thisCache,\n\t\tinternalKey = jQuery.expando,\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)) && data === undefined && typeof name === \"string\" ) {\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\tid = elem[ internalKey ] = 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\t// Avoid exposing jQuery metadata on plain JS objects when the object\n\t\t// is serialized using JSON.stringify\n\t\tcache[ id ] = isNode ? {} : { toJSON: jQuery.noop };\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 ( typeof name === \"string\" ) {\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 thisCache, i,\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\ti = name.length;\n\t\t\twhile ( 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(thisCache) : !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/* jshint eqeqeq: false */\n\t} else if ( jQuery.support.deleteExpando || cache != cache.window ) {\n\t\t/* jshint eqeqeq: true */\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// The following elements throw uncatchable exceptions if you\n\t// attempt to add expando properties to them.\n\tnoData: {\n\t\t\"applet\": true,\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},\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\tdata = null,\n\t\t\ti = 0,\n\t\t\telem = this[0];\n\n\t\t// Special expections of .data basically thwart jQuery.access,\n\t\t// so implement the relevant behavior ourselves\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-\") === 0 ) {\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 arguments.length > 1 ?\n\n\t\t\t// Sets one value\n\t\t\tthis.each(function() {\n\t\t\t\tjQuery.data( this, key, value );\n\t\t\t}) :\n\n\t\t\t// Gets one value\n\t\t\t// Try to fetch any internally stored data first\n\t\t\telem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : null;\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\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\\f]/g,\n\trreturn = /\\r/g,\n\trfocusable = /^(?:input|select|textarea|button|object)$/i,\n\trclickable = /^(?:a|area)$/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\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( 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\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 === 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 util 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\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// Use proper attribute retrieval(#6932, #12072)\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\telem.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 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( jQuery(option).val(), 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\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 === core_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( 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 ( jQuery.expr.match.bool.test( name ) ) {\n\t\t\t\t\t// Set corresponding property to false\n\t\t\t\t\tif ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {\n\t\t\t\t\t\telem[ propName ] = false;\n\t\t\t\t\t// Support: IE<9\n\t\t\t\t\t// Also clear defaultChecked/defaultSelected (if appropriate)\n\t\t\t\t\t} else {\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}\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\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\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\t// Use proper attribute retrieval(#12072)\n\t\t\t\tvar tabindex = jQuery.find.attr( elem, \"tabindex\" );\n\n\t\t\t\treturn tabindex ?\n\t\t\t\t\tparseInt( tabindex, 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\t-1;\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 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};\njQuery.each( jQuery.expr.match.bool.source.match( /\\w+/g ), function( i, name ) {\n\tvar getter = jQuery.expr.attrHandle[ name ] || jQuery.find.attr;\n\n\tjQuery.expr.attrHandle[ name ] = getSetInput && getSetAttribute || !ruseDefault.test( name ) ?\n\t\tfunction( elem, name, isXML ) {\n\t\t\tvar fn = jQuery.expr.attrHandle[ name ],\n\t\t\t\tret = isXML ?\n\t\t\t\t\tundefined :\n\t\t\t\t\t/* jshint eqeqeq: false */\n\t\t\t\t\t(jQuery.expr.attrHandle[ name ] = undefined) !=\n\t\t\t\t\t\tgetter( elem, name, isXML ) ?\n\n\t\t\t\t\t\tname.toLowerCase() :\n\t\t\t\t\t\tnull;\n\t\t\tjQuery.expr.attrHandle[ name ] = fn;\n\t\t\treturn ret;\n\t\t} :\n\t\tfunction( elem, name, isXML ) {\n\t\t\treturn isXML ?\n\t\t\t\tundefined :\n\t\t\t\telem[ jQuery.camelCase( \"default-\" + name ) ] ?\n\t\t\t\t\tname.toLowerCase() :\n\t\t\t\t\tnull;\n\t\t};\n});\n\n// fix oldIE attroperties\nif ( !getSetInput || !getSetAttribute ) {\n\tjQuery.attrHooks.value = {\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 = {\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\tjQuery.expr.attrHandle.id = jQuery.expr.attrHandle.name = jQuery.expr.attrHandle.coords =\n\t\t// Some attributes are constructed with empty-string values when not defined\n\t\tfunction( elem, name, isXML ) {\n\t\t\tvar ret;\n\t\t\treturn isXML ?\n\t\t\t\tundefined :\n\t\t\t\t(ret = elem.getAttributeNode( name )) && ret.value !== \"\" ?\n\t\t\t\t\tret.value :\n\t\t\t\t\tnull;\n\t\t};\n\tjQuery.valHooks.button = {\n\t\tget: function( elem, name ) {\n\t\t\tvar ret = elem.getAttributeNode( name );\n\t\t\treturn ret && ret.specified ?\n\t\t\t\tret.value :\n\t\t\t\tundefined;\n\t\t},\n\t\tset: nodeHook.set\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\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 ] = {\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\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 = {\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\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// IE6/7 call enctype encoding\nif ( !jQuery.support.enctype ) {\n\tjQuery.propFix.enctype = \"encoding\";\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 ( !jQuery.support.checkOn ) {\n\t\tjQuery.valHooks[ this ].get = function( elem ) {\n\t\t\t// Support: Webkit\n\t\t\t// \"\" is returned instead of \"on\" if a value isn't specified\n\t\t\treturn elem.getAttribute(\"value\") === null ? \"on\" : elem.value;\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\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\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\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// 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/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\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 = ( 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( 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// 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\t/* jshint eqeqeq: false */\n\t\t\tfor ( ; cur != this; cur = cur.parentNode || this ) {\n\t\t\t\t/* jshint eqeqeq: true */\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\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\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 === 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 ( 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\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// 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{\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 = 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\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});\nvar isSimple = /^.[^:#\\[\\.,]*$/,\n\trparentsprev = /^(?:parents|prev(?:Until|All))/,\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,\n\t\t\tret = [],\n\t\t\tself = this,\n\t\t\tlen = self.length;\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\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 || [], true) );\n\t},\n\n\tfilter: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector || [], false) );\n\t},\n\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\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\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\tcur = ret.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( 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\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 ( name.slice( -5 ) !== \"Until\" ) {\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\tif ( this.length > 1 ) {\n\t\t\t// Remove duplicates\n\t\t\tif ( !guaranteedUnique[ name ] ) {\n\t\t\t\tret = jQuery.unique( ret );\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\tret = ret.reverse();\n\t\t\t}\n\t\t}\n\n\t\treturn this.pushStack( ret );\n\t};\n});\n\njQuery.extend({\n\tfilter: function( expr, elems, not ) {\n\t\tvar elem = elems[ 0 ];\n\n\t\tif ( not ) {\n\t\t\texpr = \":not(\" + expr + \")\";\n\t\t}\n\n\t\treturn elems.length === 1 && elem.nodeType === 1 ?\n\t\t\tjQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :\n\t\t\tjQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {\n\t\t\t\treturn elem.nodeType === 1;\n\t\t\t}));\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, 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 ( isSimple.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 ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not;\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\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\t// keepData is for internal use only--do not document\n\tremove: function( selector, keepData ) {\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\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\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() {\n\t\tvar\n\t\t\t// Snapshot the DOM in case .domManip sweeps something relevant into its fragment\n\t\t\targs = jQuery.map( this, function( elem ) {\n\t\t\t\treturn [ elem.nextSibling, elem.parentNode ];\n\t\t\t}),\n\t\t\ti = 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\tvar next = args[ i++ ],\n\t\t\t\tparent = args[ i++ ];\n\n\t\t\tif ( parent ) {\n\t\t\t\t// Don't use the snapshot next if it has moved (#13810)\n\t\t\t\tif ( next && next.parentNode !== parent ) {\n\t\t\t\t\tnext = this.nextSibling;\n\t\t\t\t}\n\t\t\t\tjQuery( this ).remove();\n\t\t\t\tparent.insertBefore( elem, next );\n\t\t\t}\n\t\t// Allow new content to include elements from the context set\n\t\t}, true );\n\n\t\t// Force removal if there was no new content (e.g., from empty arguments)\n\t\treturn i ? 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, allowIntersection ) {\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, self.html() );\n\t\t\t\t}\n\t\t\t\tself.domManip( args, callback, allowIntersection );\n\t\t\t});\n\t\t}\n\n\t\tif ( l ) {\n\t\t\tfragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, !allowIntersection && 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\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!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._evalUrl( node.src );\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\n// Support: IE<8\n// Manipulating tables requires a tbody\nfunction manipulationTarget( elem, content ) {\n\treturn jQuery.nodeName( elem, \"table\" ) &&\n\t\tjQuery.nodeName( content.nodeType === 1 ? 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 = (jQuery.find.attr( elem, \"type\" ) !== null) + \"/\" + 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\n\t_evalUrl: function( url ) {\n\t\treturn jQuery.ajax({\n\t\t\turl: url,\n\t\t\ttype: \"GET\",\n\t\t\tdataType: \"script\",\n\t\t\tasync: false,\n\t\t\tglobal: false,\n\t\t\t\"throws\": true\n\t\t});\n\t}\n});\njQuery.fn.extend({\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});\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\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\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// 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\"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// 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\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.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});\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 util 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.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 // 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// 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// 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\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/* 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\tvar firstDataType, ct, finalDataType, type,\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\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// 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 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 a string for doubling factor 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// And breaking 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\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 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\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\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 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, value, toggle, tween, hooks, oldfire,\n\t\tanim = this,\n\t\torig = {},\n\t\tstyle = elem.style,\n\t\thidden = elem.nodeType && isHidden( elem ),\n\t\tdataShow = jQuery._data( 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// 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 ( 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\t\t\t\tcontinue;\n\t\t\t}\n\t\t\torig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );\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 = jQuery._data( 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\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 ( 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\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// Support: IE <=9\n// Panic based approach 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\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.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\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 || docElem;\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 || docElem;\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// 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// })();\nif ( typeof module === \"object\" && module && typeof module.exports === \"object\" ) {\n\t// Expose jQuery as module.exports in loaders that implement the Node\n\t// module pattern (including browserify). Do not create the global, since\n\t// the user will be storing it themselves locally, and globals are frowned\n\t// upon in the Node module world.\n\tmodule.exports = jQuery;\n} else {\n\t// Otherwise expose jQuery to the global object as usual\n\twindow.jQuery = window.$ = jQuery;\n\n\t// Register as a named AMD module, since jQuery can be concatenated with other\n\t// files that may use define, but not via a proper concatenation script that\n\t// understands anonymous AMD modules. A named AMD is safest and most robust\n\t// way to register. Lowercase jquery is used because AMD module names are\n\t// derived from file names, and jQuery is normally delivered in a lowercase\n\t// file name. Do this after creating the global so that if an AMD module wants\n\t// to call noConflict to hide this version of jQuery, it will work.\n\tif ( typeof define === \"function\" && define.amd ) {\n\t\tdefine( \"jquery\", [], function () { return jQuery; } );\n\t}\n}\n\n})( window );\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/json3_3.2.6/LICENSE",
    "content": "Copyright (c) 2012-2013 Kit Cambridge.\nhttp://kitcambridge.be/\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\nof the Software, and to permit persons to whom the Software is furnished to do\nso, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE."
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/json3_3.2.6/lib/json3.js",
    "content": "/*! JSON v3.2.6 | http://bestiejs.github.io/json3 | Copyright 2012-2013, Kit Cambridge | http://kit.mit-license.org */\n;(function (window) {\n  // Convenience aliases.\n  var getClass = {}.toString, isProperty, forEach, undef;\n\n  // Detect the `define` function exposed by asynchronous module loaders. The\n  // strict `define` check is necessary for compatibility with `r.js`.\n  var isLoader = typeof define === \"function\" && define.amd;\n\n  // Detect native implementations.\n  var nativeJSON = typeof JSON == \"object\" && JSON;\n\n  // Set up the JSON 3 namespace, preferring the CommonJS `exports` object if\n  // available.\n  var JSON3 = typeof exports == \"object\" && exports && !exports.nodeType && exports;\n\n  if (JSON3 && nativeJSON) {\n    // Explicitly delegate to the native `stringify` and `parse`\n    // implementations in CommonJS environments.\n    JSON3.stringify = nativeJSON.stringify;\n    JSON3.parse = nativeJSON.parse;\n  } else {\n    // Export for web browsers, JavaScript engines, and asynchronous module\n    // loaders, using the global `JSON` object if available.\n    JSON3 = window.JSON = nativeJSON || {};\n  }\n\n  // Test the `Date#getUTC*` methods. Based on work by @Yaffle.\n  var isExtended = new Date(-3509827334573292);\n  try {\n    // The `getUTCFullYear`, `Month`, and `Date` methods return nonsensical\n    // results for certain dates in Opera >= 10.53.\n    isExtended = isExtended.getUTCFullYear() == -109252 && isExtended.getUTCMonth() === 0 && isExtended.getUTCDate() === 1 &&\n      // Safari < 2.0.2 stores the internal millisecond time value correctly,\n      // but clips the values returned by the date methods to the range of\n      // signed 32-bit integers ([-2 ** 31, 2 ** 31 - 1]).\n      isExtended.getUTCHours() == 10 && isExtended.getUTCMinutes() == 37 && isExtended.getUTCSeconds() == 6 && isExtended.getUTCMilliseconds() == 708;\n  } catch (exception) {}\n\n  // Internal: Determines whether the native `JSON.stringify` and `parse`\n  // implementations are spec-compliant. Based on work by Ken Snyder.\n  function has(name) {\n    if (has[name] !== undef) {\n      // Return cached feature test result.\n      return has[name];\n    }\n\n    var isSupported;\n    if (name == \"bug-string-char-index\") {\n      // IE <= 7 doesn't support accessing string characters using square\n      // bracket notation. IE 8 only supports this for primitives.\n      isSupported = \"a\"[0] != \"a\";\n    } else if (name == \"json\") {\n      // Indicates whether both `JSON.stringify` and `JSON.parse` are\n      // supported.\n      isSupported = has(\"json-stringify\") && has(\"json-parse\");\n    } else {\n      var value, serialized = '{\"a\":[1,true,false,null,\"\\\\u0000\\\\b\\\\n\\\\f\\\\r\\\\t\"]}';\n      // Test `JSON.stringify`.\n      if (name == \"json-stringify\") {\n        var stringify = JSON3.stringify, stringifySupported = typeof stringify == \"function\" && isExtended;\n        if (stringifySupported) {\n          // A test function object with a custom `toJSON` method.\n          (value = function () {\n            return 1;\n          }).toJSON = value;\n          try {\n            stringifySupported =\n              // Firefox 3.1b1 and b2 serialize string, number, and boolean\n              // primitives as object literals.\n              stringify(0) === \"0\" &&\n              // FF 3.1b1, b2, and JSON 2 serialize wrapped primitives as object\n              // literals.\n              stringify(new Number()) === \"0\" &&\n              stringify(new String()) == '\"\"' &&\n              // FF 3.1b1, 2 throw an error if the value is `null`, `undefined`, or\n              // does not define a canonical JSON representation (this applies to\n              // objects with `toJSON` properties as well, *unless* they are nested\n              // within an object or array).\n              stringify(getClass) === undef &&\n              // IE 8 serializes `undefined` as `\"undefined\"`. Safari <= 5.1.7 and\n              // FF 3.1b3 pass this test.\n              stringify(undef) === undef &&\n              // Safari <= 5.1.7 and FF 3.1b3 throw `Error`s and `TypeError`s,\n              // respectively, if the value is omitted entirely.\n              stringify() === undef &&\n              // FF 3.1b1, 2 throw an error if the given value is not a number,\n              // string, array, object, Boolean, or `null` literal. This applies to\n              // objects with custom `toJSON` methods as well, unless they are nested\n              // inside object or array literals. YUI 3.0.0b1 ignores custom `toJSON`\n              // methods entirely.\n              stringify(value) === \"1\" &&\n              stringify([value]) == \"[1]\" &&\n              // Prototype <= 1.6.1 serializes `[undefined]` as `\"[]\"` instead of\n              // `\"[null]\"`.\n              stringify([undef]) == \"[null]\" &&\n              // YUI 3.0.0b1 fails to serialize `null` literals.\n              stringify(null) == \"null\" &&\n              // FF 3.1b1, 2 halts serialization if an array contains a function:\n              // `[1, true, getClass, 1]` serializes as \"[1,true,],\". FF 3.1b3\n              // elides non-JSON values from objects and arrays, unless they\n              // define custom `toJSON` methods.\n              stringify([undef, getClass, null]) == \"[null,null,null]\" &&\n              // Simple serialization test. FF 3.1b1 uses Unicode escape sequences\n              // where character escape codes are expected (e.g., `\\b` => `\\u0008`).\n              stringify({ \"a\": [value, true, false, null, \"\\x00\\b\\n\\f\\r\\t\"] }) == serialized &&\n              // FF 3.1b1 and b2 ignore the `filter` and `width` arguments.\n              stringify(null, value) === \"1\" &&\n              stringify([1, 2], null, 1) == \"[\\n 1,\\n 2\\n]\" &&\n              // JSON 2, Prototype <= 1.7, and older WebKit builds incorrectly\n              // serialize extended years.\n              stringify(new Date(-8.64e15)) == '\"-271821-04-20T00:00:00.000Z\"' &&\n              // The milliseconds are optional in ES 5, but required in 5.1.\n              stringify(new Date(8.64e15)) == '\"+275760-09-13T00:00:00.000Z\"' &&\n              // Firefox <= 11.0 incorrectly serializes years prior to 0 as negative\n              // four-digit years instead of six-digit years. Credits: @Yaffle.\n              stringify(new Date(-621987552e5)) == '\"-000001-01-01T00:00:00.000Z\"' &&\n              // Safari <= 5.1.5 and Opera >= 10.53 incorrectly serialize millisecond\n              // values less than 1000. Credits: @Yaffle.\n              stringify(new Date(-1)) == '\"1969-12-31T23:59:59.999Z\"';\n          } catch (exception) {\n            stringifySupported = false;\n          }\n        }\n        isSupported = stringifySupported;\n      }\n      // Test `JSON.parse`.\n      if (name == \"json-parse\") {\n        var parse = JSON3.parse;\n        if (typeof parse == \"function\") {\n          try {\n            // FF 3.1b1, b2 will throw an exception if a bare literal is provided.\n            // Conforming implementations should also coerce the initial argument to\n            // a string prior to parsing.\n            if (parse(\"0\") === 0 && !parse(false)) {\n              // Simple parsing test.\n              value = parse(serialized);\n              var parseSupported = value[\"a\"].length == 5 && value[\"a\"][0] === 1;\n              if (parseSupported) {\n                try {\n                  // Safari <= 5.1.2 and FF 3.1b1 allow unescaped tabs in strings.\n                  parseSupported = !parse('\"\\t\"');\n                } catch (exception) {}\n                if (parseSupported) {\n                  try {\n                    // FF 4.0 and 4.0.1 allow leading `+` signs and leading\n                    // decimal points. FF 4.0, 4.0.1, and IE 9-10 also allow\n                    // certain octal literals.\n                    parseSupported = parse(\"01\") !== 1;\n                  } catch (exception) {}\n                }\n                if (parseSupported) {\n                  try {\n                    // FF 4.0, 4.0.1, and Rhino 1.7R3-R4 allow trailing decimal\n                    // points. These environments, along with FF 3.1b1 and 2,\n                    // also allow trailing commas in JSON objects and arrays.\n                    parseSupported = parse(\"1.\") !== 1;\n                  } catch (exception) {}\n                }\n              }\n            }\n          } catch (exception) {\n            parseSupported = false;\n          }\n        }\n        isSupported = parseSupported;\n      }\n    }\n    return has[name] = !!isSupported;\n  }\n\n  if (!has(\"json\")) {\n    // Common `[[Class]]` name aliases.\n    var functionClass = \"[object Function]\";\n    var dateClass = \"[object Date]\";\n    var numberClass = \"[object Number]\";\n    var stringClass = \"[object String]\";\n    var arrayClass = \"[object Array]\";\n    var booleanClass = \"[object Boolean]\";\n\n    // Detect incomplete support for accessing string characters by index.\n    var charIndexBuggy = has(\"bug-string-char-index\");\n\n    // Define additional utility methods if the `Date` methods are buggy.\n    if (!isExtended) {\n      var floor = Math.floor;\n      // A mapping between the months of the year and the number of days between\n      // January 1st and the first of the respective month.\n      var Months = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];\n      // Internal: Calculates the number of days between the Unix epoch and the\n      // first day of the given month.\n      var getDay = function (year, month) {\n        return Months[month] + 365 * (year - 1970) + floor((year - 1969 + (month = +(month > 1))) / 4) - floor((year - 1901 + month) / 100) + floor((year - 1601 + month) / 400);\n      };\n    }\n\n    // Internal: Determines if a property is a direct property of the given\n    // object. Delegates to the native `Object#hasOwnProperty` method.\n    if (!(isProperty = {}.hasOwnProperty)) {\n      isProperty = function (property) {\n        var members = {}, constructor;\n        if ((members.__proto__ = null, members.__proto__ = {\n          // The *proto* property cannot be set multiple times in recent\n          // versions of Firefox and SeaMonkey.\n          \"toString\": 1\n        }, members).toString != getClass) {\n          // Safari <= 2.0.3 doesn't implement `Object#hasOwnProperty`, but\n          // supports the mutable *proto* property.\n          isProperty = function (property) {\n            // Capture and break the object's prototype chain (see section 8.6.2\n            // of the ES 5.1 spec). The parenthesized expression prevents an\n            // unsafe transformation by the Closure Compiler.\n            var original = this.__proto__, result = property in (this.__proto__ = null, this);\n            // Restore the original prototype chain.\n            this.__proto__ = original;\n            return result;\n          };\n        } else {\n          // Capture a reference to the top-level `Object` constructor.\n          constructor = members.constructor;\n          // Use the `constructor` property to simulate `Object#hasOwnProperty` in\n          // other environments.\n          isProperty = function (property) {\n            var parent = (this.constructor || constructor).prototype;\n            return property in this && !(property in parent && this[property] === parent[property]);\n          };\n        }\n        members = null;\n        return isProperty.call(this, property);\n      };\n    }\n\n    // Internal: A set of primitive types used by `isHostType`.\n    var PrimitiveTypes = {\n      'boolean': 1,\n      'number': 1,\n      'string': 1,\n      'undefined': 1\n    };\n\n    // Internal: Determines if the given object `property` value is a\n    // non-primitive.\n    var isHostType = function (object, property) {\n      var type = typeof object[property];\n      return type == 'object' ? !!object[property] : !PrimitiveTypes[type];\n    };\n\n    // Internal: Normalizes the `for...in` iteration algorithm across\n    // environments. Each enumerated key is yielded to a `callback` function.\n    forEach = function (object, callback) {\n      var size = 0, Properties, members, property;\n\n      // Tests for bugs in the current environment's `for...in` algorithm. The\n      // `valueOf` property inherits the non-enumerable flag from\n      // `Object.prototype` in older versions of IE, Netscape, and Mozilla.\n      (Properties = function () {\n        this.valueOf = 0;\n      }).prototype.valueOf = 0;\n\n      // Iterate over a new instance of the `Properties` class.\n      members = new Properties();\n      for (property in members) {\n        // Ignore all properties inherited from `Object.prototype`.\n        if (isProperty.call(members, property)) {\n          size++;\n        }\n      }\n      Properties = members = null;\n\n      // Normalize the iteration algorithm.\n      if (!size) {\n        // A list of non-enumerable properties inherited from `Object.prototype`.\n        members = [\"valueOf\", \"toString\", \"toLocaleString\", \"propertyIsEnumerable\", \"isPrototypeOf\", \"hasOwnProperty\", \"constructor\"];\n        // IE <= 8, Mozilla 1.0, and Netscape 6.2 ignore shadowed non-enumerable\n        // properties.\n        forEach = function (object, callback) {\n          var isFunction = getClass.call(object) == functionClass, property, length;\n          var hasProperty = !isFunction && typeof object.constructor != 'function' && isHostType(object, 'hasOwnProperty') ? object.hasOwnProperty : isProperty;\n          for (property in object) {\n            // Gecko <= 1.0 enumerates the `prototype` property of functions under\n            // certain conditions; IE does not.\n            if (!(isFunction && property == \"prototype\") && hasProperty.call(object, property)) {\n              callback(property);\n            }\n          }\n          // Manually invoke the callback for each non-enumerable property.\n          for (length = members.length; property = members[--length]; hasProperty.call(object, property) && callback(property));\n        };\n      } else if (size == 2) {\n        // Safari <= 2.0.4 enumerates shadowed properties twice.\n        forEach = function (object, callback) {\n          // Create a set of iterated properties.\n          var members = {}, isFunction = getClass.call(object) == functionClass, property;\n          for (property in object) {\n            // Store each property name to prevent double enumeration. The\n            // `prototype` property of functions is not enumerated due to cross-\n            // environment inconsistencies.\n            if (!(isFunction && property == \"prototype\") && !isProperty.call(members, property) && (members[property] = 1) && isProperty.call(object, property)) {\n              callback(property);\n            }\n          }\n        };\n      } else {\n        // No bugs detected; use the standard `for...in` algorithm.\n        forEach = function (object, callback) {\n          var isFunction = getClass.call(object) == functionClass, property, isConstructor;\n          for (property in object) {\n            if (!(isFunction && property == \"prototype\") && isProperty.call(object, property) && !(isConstructor = property === \"constructor\")) {\n              callback(property);\n            }\n          }\n          // Manually invoke the callback for the `constructor` property due to\n          // cross-environment inconsistencies.\n          if (isConstructor || isProperty.call(object, (property = \"constructor\"))) {\n            callback(property);\n          }\n        };\n      }\n      return forEach(object, callback);\n    };\n\n    // Public: Serializes a JavaScript `value` as a JSON string. The optional\n    // `filter` argument may specify either a function that alters how object and\n    // array members are serialized, or an array of strings and numbers that\n    // indicates which properties should be serialized. The optional `width`\n    // argument may be either a string or number that specifies the indentation\n    // level of the output.\n    if (!has(\"json-stringify\")) {\n      // Internal: A map of control characters and their escaped equivalents.\n      var Escapes = {\n        92: \"\\\\\\\\\",\n        34: '\\\\\"',\n        8: \"\\\\b\",\n        12: \"\\\\f\",\n        10: \"\\\\n\",\n        13: \"\\\\r\",\n        9: \"\\\\t\"\n      };\n\n      // Internal: Converts `value` into a zero-padded string such that its\n      // length is at least equal to `width`. The `width` must be <= 6.\n      var leadingZeroes = \"000000\";\n      var toPaddedString = function (width, value) {\n        // The `|| 0` expression is necessary to work around a bug in\n        // Opera <= 7.54u2 where `0 == -0`, but `String(-0) !== \"0\"`.\n        return (leadingZeroes + (value || 0)).slice(-width);\n      };\n\n      // Internal: Double-quotes a string `value`, replacing all ASCII control\n      // characters (characters with code unit values between 0 and 31) with\n      // their escaped equivalents. This is an implementation of the\n      // `Quote(value)` operation defined in ES 5.1 section 15.12.3.\n      var unicodePrefix = \"\\\\u00\";\n      var quote = function (value) {\n        var result = '\"', index = 0, length = value.length, isLarge = length > 10 && charIndexBuggy, symbols;\n        if (isLarge) {\n          symbols = value.split(\"\");\n        }\n        for (; index < length; index++) {\n          var charCode = value.charCodeAt(index);\n          // If the character is a control character, append its Unicode or\n          // shorthand escape sequence; otherwise, append the character as-is.\n          switch (charCode) {\n            case 8: case 9: case 10: case 12: case 13: case 34: case 92:\n              result += Escapes[charCode];\n              break;\n            default:\n              if (charCode < 32) {\n                result += unicodePrefix + toPaddedString(2, charCode.toString(16));\n                break;\n              }\n              result += isLarge ? symbols[index] : charIndexBuggy ? value.charAt(index) : value[index];\n          }\n        }\n        return result + '\"';\n      };\n\n      // Internal: Recursively serializes an object. Implements the\n      // `Str(key, holder)`, `JO(value)`, and `JA(value)` operations.\n      var serialize = function (property, object, callback, properties, whitespace, indentation, stack) {\n        var value, className, year, month, date, time, hours, minutes, seconds, milliseconds, results, element, index, length, prefix, result;\n        try {\n          // Necessary for host object support.\n          value = object[property];\n        } catch (exception) {}\n        if (typeof value == \"object\" && value) {\n          className = getClass.call(value);\n          if (className == dateClass && !isProperty.call(value, \"toJSON\")) {\n            if (value > -1 / 0 && value < 1 / 0) {\n              // Dates are serialized according to the `Date#toJSON` method\n              // specified in ES 5.1 section 15.9.5.44. See section 15.9.1.15\n              // for the ISO 8601 date time string format.\n              if (getDay) {\n                // Manually compute the year, month, date, hours, minutes,\n                // seconds, and milliseconds if the `getUTC*` methods are\n                // buggy. Adapted from @Yaffle's `date-shim` project.\n                date = floor(value / 864e5);\n                for (year = floor(date / 365.2425) + 1970 - 1; getDay(year + 1, 0) <= date; year++);\n                for (month = floor((date - getDay(year, 0)) / 30.42); getDay(year, month + 1) <= date; month++);\n                date = 1 + date - getDay(year, month);\n                // The `time` value specifies the time within the day (see ES\n                // 5.1 section 15.9.1.2). The formula `(A % B + B) % B` is used\n                // to compute `A modulo B`, as the `%` operator does not\n                // correspond to the `modulo` operation for negative numbers.\n                time = (value % 864e5 + 864e5) % 864e5;\n                // The hours, minutes, seconds, and milliseconds are obtained by\n                // decomposing the time within the day. See section 15.9.1.10.\n                hours = floor(time / 36e5) % 24;\n                minutes = floor(time / 6e4) % 60;\n                seconds = floor(time / 1e3) % 60;\n                milliseconds = time % 1e3;\n              } else {\n                year = value.getUTCFullYear();\n                month = value.getUTCMonth();\n                date = value.getUTCDate();\n                hours = value.getUTCHours();\n                minutes = value.getUTCMinutes();\n                seconds = value.getUTCSeconds();\n                milliseconds = value.getUTCMilliseconds();\n              }\n              // Serialize extended years correctly.\n              value = (year <= 0 || year >= 1e4 ? (year < 0 ? \"-\" : \"+\") + toPaddedString(6, year < 0 ? -year : year) : toPaddedString(4, year)) +\n                \"-\" + toPaddedString(2, month + 1) + \"-\" + toPaddedString(2, date) +\n                // Months, dates, hours, minutes, and seconds should have two\n                // digits; milliseconds should have three.\n                \"T\" + toPaddedString(2, hours) + \":\" + toPaddedString(2, minutes) + \":\" + toPaddedString(2, seconds) +\n                // Milliseconds are optional in ES 5.0, but required in 5.1.\n                \".\" + toPaddedString(3, milliseconds) + \"Z\";\n            } else {\n              value = null;\n            }\n          } else if (typeof value.toJSON == \"function\" && ((className != numberClass && className != stringClass && className != arrayClass) || isProperty.call(value, \"toJSON\"))) {\n            // Prototype <= 1.6.1 adds non-standard `toJSON` methods to the\n            // `Number`, `String`, `Date`, and `Array` prototypes. JSON 3\n            // ignores all `toJSON` methods on these objects unless they are\n            // defined directly on an instance.\n            value = value.toJSON(property);\n          }\n        }\n        if (callback) {\n          // If a replacement function was provided, call it to obtain the value\n          // for serialization.\n          value = callback.call(object, property, value);\n        }\n        if (value === null) {\n          return \"null\";\n        }\n        className = getClass.call(value);\n        if (className == booleanClass) {\n          // Booleans are represented literally.\n          return \"\" + value;\n        } else if (className == numberClass) {\n          // JSON numbers must be finite. `Infinity` and `NaN` are serialized as\n          // `\"null\"`.\n          return value > -1 / 0 && value < 1 / 0 ? \"\" + value : \"null\";\n        } else if (className == stringClass) {\n          // Strings are double-quoted and escaped.\n          return quote(\"\" + value);\n        }\n        // Recursively serialize objects and arrays.\n        if (typeof value == \"object\") {\n          // Check for cyclic structures. This is a linear search; performance\n          // is inversely proportional to the number of unique nested objects.\n          for (length = stack.length; length--;) {\n            if (stack[length] === value) {\n              // Cyclic structures cannot be serialized by `JSON.stringify`.\n              throw TypeError();\n            }\n          }\n          // Add the object to the stack of traversed objects.\n          stack.push(value);\n          results = [];\n          // Save the current indentation level and indent one additional level.\n          prefix = indentation;\n          indentation += whitespace;\n          if (className == arrayClass) {\n            // Recursively serialize array elements.\n            for (index = 0, length = value.length; index < length; index++) {\n              element = serialize(index, value, callback, properties, whitespace, indentation, stack);\n              results.push(element === undef ? \"null\" : element);\n            }\n            result = results.length ? (whitespace ? \"[\\n\" + indentation + results.join(\",\\n\" + indentation) + \"\\n\" + prefix + \"]\" : (\"[\" + results.join(\",\") + \"]\")) : \"[]\";\n          } else {\n            // Recursively serialize object members. Members are selected from\n            // either a user-specified list of property names, or the object\n            // itself.\n            forEach(properties || value, function (property) {\n              var element = serialize(property, value, callback, properties, whitespace, indentation, stack);\n              if (element !== undef) {\n                // According to ES 5.1 section 15.12.3: \"If `gap` {whitespace}\n                // is not the empty string, let `member` {quote(property) + \":\"}\n                // be the concatenation of `member` and the `space` character.\"\n                // The \"`space` character\" refers to the literal space\n                // character, not the `space` {width} argument provided to\n                // `JSON.stringify`.\n                results.push(quote(property) + \":\" + (whitespace ? \" \" : \"\") + element);\n              }\n            });\n            result = results.length ? (whitespace ? \"{\\n\" + indentation + results.join(\",\\n\" + indentation) + \"\\n\" + prefix + \"}\" : (\"{\" + results.join(\",\") + \"}\")) : \"{}\";\n          }\n          // Remove the object from the traversed object stack.\n          stack.pop();\n          return result;\n        }\n      };\n\n      // Public: `JSON.stringify`. See ES 5.1 section 15.12.3.\n      JSON3.stringify = function (source, filter, width) {\n        var whitespace, callback, properties, className;\n        if (typeof filter == \"function\" || typeof filter == \"object\" && filter) {\n          if ((className = getClass.call(filter)) == functionClass) {\n            callback = filter;\n          } else if (className == arrayClass) {\n            // Convert the property names array into a makeshift set.\n            properties = {};\n            for (var index = 0, length = filter.length, value; index < length; value = filter[index++], ((className = getClass.call(value)), className == stringClass || className == numberClass) && (properties[value] = 1));\n          }\n        }\n        if (width) {\n          if ((className = getClass.call(width)) == numberClass) {\n            // Convert the `width` to an integer and create a string containing\n            // `width` number of space characters.\n            if ((width -= width % 1) > 0) {\n              for (whitespace = \"\", width > 10 && (width = 10); whitespace.length < width; whitespace += \" \");\n            }\n          } else if (className == stringClass) {\n            whitespace = width.length <= 10 ? width : width.slice(0, 10);\n          }\n        }\n        // Opera <= 7.54u2 discards the values associated with empty string keys\n        // (`\"\"`) only if they are used directly within an object member list\n        // (e.g., `!(\"\" in { \"\": 1})`).\n        return serialize(\"\", (value = {}, value[\"\"] = source, value), callback, properties, whitespace, \"\", []);\n      };\n    }\n\n    // Public: Parses a JSON source string.\n    if (!has(\"json-parse\")) {\n      var fromCharCode = String.fromCharCode;\n\n      // Internal: A map of escaped control characters and their unescaped\n      // equivalents.\n      var Unescapes = {\n        92: \"\\\\\",\n        34: '\"',\n        47: \"/\",\n        98: \"\\b\",\n        116: \"\\t\",\n        110: \"\\n\",\n        102: \"\\f\",\n        114: \"\\r\"\n      };\n\n      // Internal: Stores the parser state.\n      var Index, Source;\n\n      // Internal: Resets the parser state and throws a `SyntaxError`.\n      var abort = function() {\n        Index = Source = null;\n        throw SyntaxError();\n      };\n\n      // Internal: Returns the next token, or `\"$\"` if the parser has reached\n      // the end of the source string. A token may be a string, number, `null`\n      // literal, or Boolean literal.\n      var lex = function () {\n        var source = Source, length = source.length, value, begin, position, isSigned, charCode;\n        while (Index < length) {\n          charCode = source.charCodeAt(Index);\n          switch (charCode) {\n            case 9: case 10: case 13: case 32:\n              // Skip whitespace tokens, including tabs, carriage returns, line\n              // feeds, and space characters.\n              Index++;\n              break;\n            case 123: case 125: case 91: case 93: case 58: case 44:\n              // Parse a punctuator token (`{`, `}`, `[`, `]`, `:`, or `,`) at\n              // the current position.\n              value = charIndexBuggy ? source.charAt(Index) : source[Index];\n              Index++;\n              return value;\n            case 34:\n              // `\"` delimits a JSON string; advance to the next character and\n              // begin parsing the string. String tokens are prefixed with the\n              // sentinel `@` character to distinguish them from punctuators and\n              // end-of-string tokens.\n              for (value = \"@\", Index++; Index < length;) {\n                charCode = source.charCodeAt(Index);\n                if (charCode < 32) {\n                  // Unescaped ASCII control characters (those with a code unit\n                  // less than the space character) are not permitted.\n                  abort();\n                } else if (charCode == 92) {\n                  // A reverse solidus (`\\`) marks the beginning of an escaped\n                  // control character (including `\"`, `\\`, and `/`) or Unicode\n                  // escape sequence.\n                  charCode = source.charCodeAt(++Index);\n                  switch (charCode) {\n                    case 92: case 34: case 47: case 98: case 116: case 110: case 102: case 114:\n                      // Revive escaped control characters.\n                      value += Unescapes[charCode];\n                      Index++;\n                      break;\n                    case 117:\n                      // `\\u` marks the beginning of a Unicode escape sequence.\n                      // Advance to the first character and validate the\n                      // four-digit code point.\n                      begin = ++Index;\n                      for (position = Index + 4; Index < position; Index++) {\n                        charCode = source.charCodeAt(Index);\n                        // A valid sequence comprises four hexdigits (case-\n                        // insensitive) that form a single hexadecimal value.\n                        if (!(charCode >= 48 && charCode <= 57 || charCode >= 97 && charCode <= 102 || charCode >= 65 && charCode <= 70)) {\n                          // Invalid Unicode escape sequence.\n                          abort();\n                        }\n                      }\n                      // Revive the escaped character.\n                      value += fromCharCode(\"0x\" + source.slice(begin, Index));\n                      break;\n                    default:\n                      // Invalid escape sequence.\n                      abort();\n                  }\n                } else {\n                  if (charCode == 34) {\n                    // An unescaped double-quote character marks the end of the\n                    // string.\n                    break;\n                  }\n                  charCode = source.charCodeAt(Index);\n                  begin = Index;\n                  // Optimize for the util case where a string is valid.\n                  while (charCode >= 32 && charCode != 92 && charCode != 34) {\n                    charCode = source.charCodeAt(++Index);\n                  }\n                  // Append the string as-is.\n                  value += source.slice(begin, Index);\n                }\n              }\n              if (source.charCodeAt(Index) == 34) {\n                // Advance to the next character and return the revived string.\n                Index++;\n                return value;\n              }\n              // Unterminated string.\n              abort();\n            default:\n              // Parse numbers and literals.\n              begin = Index;\n              // Advance past the negative sign, if one is specified.\n              if (charCode == 45) {\n                isSigned = true;\n                charCode = source.charCodeAt(++Index);\n              }\n              // Parse an integer or floating-point value.\n              if (charCode >= 48 && charCode <= 57) {\n                // Leading zeroes are interpreted as octal literals.\n                if (charCode == 48 && ((charCode = source.charCodeAt(Index + 1)), charCode >= 48 && charCode <= 57)) {\n                  // Illegal octal literal.\n                  abort();\n                }\n                isSigned = false;\n                // Parse the integer component.\n                for (; Index < length && ((charCode = source.charCodeAt(Index)), charCode >= 48 && charCode <= 57); Index++);\n                // Floats cannot contain a leading decimal point; however, this\n                // case is already accounted for by the parser.\n                if (source.charCodeAt(Index) == 46) {\n                  position = ++Index;\n                  // Parse the decimal component.\n                  for (; position < length && ((charCode = source.charCodeAt(position)), charCode >= 48 && charCode <= 57); position++);\n                  if (position == Index) {\n                    // Illegal trailing decimal.\n                    abort();\n                  }\n                  Index = position;\n                }\n                // Parse exponents. The `e` denoting the exponent is\n                // case-insensitive.\n                charCode = source.charCodeAt(Index);\n                if (charCode == 101 || charCode == 69) {\n                  charCode = source.charCodeAt(++Index);\n                  // Skip past the sign following the exponent, if one is\n                  // specified.\n                  if (charCode == 43 || charCode == 45) {\n                    Index++;\n                  }\n                  // Parse the exponential component.\n                  for (position = Index; position < length && ((charCode = source.charCodeAt(position)), charCode >= 48 && charCode <= 57); position++);\n                  if (position == Index) {\n                    // Illegal empty exponent.\n                    abort();\n                  }\n                  Index = position;\n                }\n                // Coerce the parsed value to a JavaScript number.\n                return +source.slice(begin, Index);\n              }\n              // A negative sign may only precede numbers.\n              if (isSigned) {\n                abort();\n              }\n              // `true`, `false`, and `null` literals.\n              if (source.slice(Index, Index + 4) == \"true\") {\n                Index += 4;\n                return true;\n              } else if (source.slice(Index, Index + 5) == \"false\") {\n                Index += 5;\n                return false;\n              } else if (source.slice(Index, Index + 4) == \"null\") {\n                Index += 4;\n                return null;\n              }\n              // Unrecognized token.\n              abort();\n          }\n        }\n        // Return the sentinel `$` character if the parser has reached the end\n        // of the source string.\n        return \"$\";\n      };\n\n      // Internal: Parses a JSON `value` token.\n      var get = function (value) {\n        var results, hasMembers;\n        if (value == \"$\") {\n          // Unexpected end of input.\n          abort();\n        }\n        if (typeof value == \"string\") {\n          if ((charIndexBuggy ? value.charAt(0) : value[0]) == \"@\") {\n            // Remove the sentinel `@` character.\n            return value.slice(1);\n          }\n          // Parse object and array literals.\n          if (value == \"[\") {\n            // Parses a JSON array, returning a new JavaScript array.\n            results = [];\n            for (;; hasMembers || (hasMembers = true)) {\n              value = lex();\n              // A closing square bracket marks the end of the array literal.\n              if (value == \"]\") {\n                break;\n              }\n              // If the array literal contains elements, the current token\n              // should be a comma separating the previous element from the\n              // next.\n              if (hasMembers) {\n                if (value == \",\") {\n                  value = lex();\n                  if (value == \"]\") {\n                    // Unexpected trailing `,` in array literal.\n                    abort();\n                  }\n                } else {\n                  // A `,` must separate each array element.\n                  abort();\n                }\n              }\n              // Elisions and leading commas are not permitted.\n              if (value == \",\") {\n                abort();\n              }\n              results.push(get(value));\n            }\n            return results;\n          } else if (value == \"{\") {\n            // Parses a JSON object, returning a new JavaScript object.\n            results = {};\n            for (;; hasMembers || (hasMembers = true)) {\n              value = lex();\n              // A closing curly brace marks the end of the object literal.\n              if (value == \"}\") {\n                break;\n              }\n              // If the object literal contains members, the current token\n              // should be a comma separator.\n              if (hasMembers) {\n                if (value == \",\") {\n                  value = lex();\n                  if (value == \"}\") {\n                    // Unexpected trailing `,` in object literal.\n                    abort();\n                  }\n                } else {\n                  // A `,` must separate each object member.\n                  abort();\n                }\n              }\n              // Leading commas are not permitted, object property names must be\n              // double-quoted strings, and a `:` must separate each property\n              // name and value.\n              if (value == \",\" || typeof value != \"string\" || (charIndexBuggy ? value.charAt(0) : value[0]) != \"@\" || lex() != \":\") {\n                abort();\n              }\n              results[value.slice(1)] = get(lex());\n            }\n            return results;\n          }\n          // Unexpected token encountered.\n          abort();\n        }\n        return value;\n      };\n\n      // Internal: Updates a traversed object member.\n      var update = function(source, property, callback) {\n        var element = walk(source, property, callback);\n        if (element === undef) {\n          delete source[property];\n        } else {\n          source[property] = element;\n        }\n      };\n\n      // Internal: Recursively traverses a parsed JSON object, invoking the\n      // `callback` function for each value. This is an implementation of the\n      // `Walk(holder, name)` operation defined in ES 5.1 section 15.12.2.\n      var walk = function (source, property, callback) {\n        var value = source[property], length;\n        if (typeof value == \"object\" && value) {\n          // `forEach` can't be used to traverse an array in Opera <= 8.54\n          // because its `Object#hasOwnProperty` implementation returns `false`\n          // for array indices (e.g., `![1, 2, 3].hasOwnProperty(\"0\")`).\n          if (getClass.call(value) == arrayClass) {\n            for (length = value.length; length--;) {\n              update(value, length, callback);\n            }\n          } else {\n            forEach(value, function (property) {\n              update(value, property, callback);\n            });\n          }\n        }\n        return callback.call(source, property, value);\n      };\n\n      // Public: `JSON.parse`. See ES 5.1 section 15.12.2.\n      JSON3.parse = function (source, callback) {\n        var result, value;\n        Index = 0;\n        Source = \"\" + source;\n        result = get(lex());\n        // If a JSON string contains multiple tokens, it is invalid.\n        if (lex() != \"$\") {\n          abort();\n        }\n        // Reset the parser state.\n        Index = Source = null;\n        return callback && getClass.call(callback) == functionClass ? walk((value = {}, value[\"\"] = result, value), \"\", callback) : result;\n      };\n    }\n  }\n\n  // Export for asynchronous module loaders.\n  if (isLoader) {\n    define(function () {\n      return JSON3;\n    });\n  }\n}(this));\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/ng-grid-2.0.7-min.js",
    "content": "(function(e,t){\"use strict\";var n=6,o=4,i=\"asc\",r=\"desc\",l=\"_ng_field_\",a=\"_ng_depth_\",s=\"_ng_hidden_\",c=\"_ng_column_\",g=/CUSTOM_FILTERS/g,d=/COL_FIELD/g,u=/DISPLAY_CELL_TEMPLATE/g,f=/EDITABLE_CELL_TEMPLATE/g,h=/<.+>/;e.ngGrid={},e.ngGrid.i18n={},angular.module(\"ngGrid.services\",[]);var p=angular.module(\"ngGrid.directives\",[]),m=angular.module(\"ngGrid.filters\",[]);angular.module(\"ngGrid\",[\"ngGrid.services\",\"ngGrid.directives\",\"ngGrid.filters\"]);var v=function(e,t,o,i){if(void 0===e.selectionProvider.selectedItems)return!0;var r,l=o.which||o.keyCode,a=!1,s=!1,c=void 0===e.selectionProvider.lastClickedRow?1:e.selectionProvider.lastClickedRow.rowIndex,g=e.columns.filter(function(e){return e.visible}),d=e.columns.filter(function(e){return e.pinned});if(e.col&&(r=g.indexOf(e.col)),37!==l&&38!==l&&39!==l&&40!==l&&9!==l&&13!==l)return!0;if(e.enableCellSelection){9===l&&o.preventDefault();var u=e.showSelectionCheckbox?1===e.col.index:0===e.col.index,f=1===e.$index||0===e.$index,h=e.$index===e.renderedColumns.length-1||e.$index===e.renderedColumns.length-2,p=g.indexOf(e.col)===g.length-1,m=d.indexOf(e.col)===d.length-1;if(37===l||9===l&&o.shiftKey){var v=0;u||(r-=1),f?u&&9===l&&o.shiftKey?(v=i.$canvas.width(),r=g.length-1,s=!0):v=i.$viewport.scrollLeft()-e.col.width:d.length>0&&(v=i.$viewport.scrollLeft()-g[r].width),i.$viewport.scrollLeft(v)}else(39===l||9===l&&!o.shiftKey)&&(h?p&&9===l&&!o.shiftKey?(i.$viewport.scrollLeft(0),r=e.showSelectionCheckbox?1:0,a=!0):i.$viewport.scrollLeft(i.$viewport.scrollLeft()+e.col.width):m&&i.$viewport.scrollLeft(0),p||(r+=1))}var w;w=e.configGroups.length>0?i.rowFactory.parsedData.filter(function(e){return!e.isAggRow}):i.filteredRows;var C=0;if(0!==c&&(38===l||13===l&&o.shiftKey||9===l&&o.shiftKey&&s)?C=-1:c!==w.length-1&&(40===l||13===l&&!o.shiftKey||9===l&&a)&&(C=1),C){var b=w[c+C];b.beforeSelectionChange(b,o)&&(b.continueSelection(o),e.$emit(\"ngGridEventDigestGridParent\"),e.selectionProvider.lastClickedRow.renderedRowIndex>=e.renderedRows.length-n-2?i.$viewport.scrollTop(i.$viewport.scrollTop()+e.rowHeight):n+2>=e.selectionProvider.lastClickedRow.renderedRowIndex&&i.$viewport.scrollTop(i.$viewport.scrollTop()-e.rowHeight))}return e.enableCellSelection&&setTimeout(function(){e.domAccessProvider.focusCellElement(e,e.renderedColumns.indexOf(g[r]))},3),!1};String.prototype.trim||(String.prototype.trim=function(){return this.replace(/^\\s+|\\s+$/g,\"\")}),Array.prototype.indexOf||(Array.prototype.indexOf=function(e){var t=this.length>>>0,n=Number(arguments[1])||0;for(n=0>n?Math.ceil(n):Math.floor(n),0>n&&(n+=t);t>n;n++)if(n in this&&this[n]===e)return n;return-1}),Array.prototype.filter||(Array.prototype.filter=function(e){var t=Object(this),n=t.length>>>0;if(\"function\"!=typeof e)throw new TypeError;for(var o=[],i=arguments[1],r=0;n>r;r++)if(r in t){var l=t[r];e.call(i,l,r,t)&&o.push(l)}return o}),m.filter(\"checkmark\",function(){return function(e){return e?\"✔\":\"✘\"}}),m.filter(\"ngColumns\",function(){return function(e){return e.filter(function(e){return!e.isAggCol})}}),angular.module(\"ngGrid.services\").factory(\"$domUtilityService\",[\"$utilityService\",function(e){var n={},o={},i=function(){var e=t(\"<div></div>\");e.appendTo(\"body\"),e.height(100).width(100).css(\"position\",\"absolute\").css(\"overflow\",\"scroll\"),e.append('<div style=\"height: 400px; width: 400px;\"></div>'),n.ScrollH=e.height()-e[0].clientHeight,n.ScrollW=e.width()-e[0].clientWidth,e.empty(),e.attr(\"style\",\"\"),e.append('<span style=\"font-family: Verdana, Helvetica, Sans-Serif; font-size: 14px;\"><strong>M</strong></span>'),n.LetterW=e.children().first().width(),e.remove()};return n.eventStorage={},n.AssignGridContainers=function(e,o,i){i.$root=t(o),i.$topPanel=i.$root.find(\".ngTopPanel\"),i.$groupPanel=i.$root.find(\".ngGroupPanel\"),i.$headerContainer=i.$topPanel.find(\".ngHeaderContainer\"),e.$headerContainer=i.$headerContainer,i.$headerScroller=i.$topPanel.find(\".ngHeaderScroller\"),i.$headers=i.$headerScroller.children(),i.$viewport=i.$root.find(\".ngViewport\"),i.$canvas=i.$viewport.find(\".ngCanvas\"),i.$footerPanel=i.$root.find(\".ngFooterPanel\"),e.$watch(function(){return i.$viewport.scrollLeft()},function(e){return i.$headerContainer.scrollLeft(e)}),n.UpdateGridLayout(e,i)},n.getRealWidth=function(e){var n=0,o={visibility:\"hidden\",display:\"block\"},i=e.parents().andSelf().not(\":visible\");return t.swap(i[0],o,function(){n=e.outerWidth()}),n},n.UpdateGridLayout=function(e,t){var o=t.$viewport.scrollTop();t.elementDims.rootMaxW=t.$root.width(),t.$root.is(\":hidden\")&&(t.elementDims.rootMaxW=n.getRealWidth(t.$root)),t.elementDims.rootMaxH=t.$root.height(),t.refreshDomSizes(),e.adjustScrollTop(o,!0)},n.numberOfGrids=0,n.BuildStyles=function(o,i,r){var l,a=i.config.rowHeight,s=i.$styleSheet,c=i.gridId,g=o.columns,d=0;s||(s=t(\"#\"+c),s[0]||(s=t(\"<style id='\"+c+\"' type='text/css' rel='stylesheet' />\").appendTo(i.$root))),s.empty();var u=o.totalRowWidth();l=\".\"+c+\" .ngCanvas { width: \"+u+\"px; }\"+\".\"+c+\" .ngRow { width: \"+u+\"px; }\"+\".\"+c+\" .ngCanvas { width: \"+u+\"px; }\"+\".\"+c+\" .ngHeaderScroller { width: \"+(u+n.ScrollH)+\"px}\";for(var f=0;g.length>f;f++){var h=g[f];h.visible!==!1&&(l+=\".\"+c+\" .col\"+f+\" { width: \"+h.width+\"px; left: \"+d+\"px; height: \"+a+\"px }\"+\".\"+c+\" .colt\"+f+\" { width: \"+h.width+\"px; }\",d+=h.width)}e.isIe?s[0].styleSheet.cssText=l:s[0].appendChild(document.createTextNode(l)),i.$styleSheet=s,o.adjustScrollLeft(i.$viewport.scrollLeft()),r&&n.digest(o)},n.setColLeft=function(t,n,i){if(i.$styleSheet){var r=o[t.index];r||(r=o[t.index]=RegExp(\".col\"+t.index+\" { width: [0-9]+px; left: [0-9]+px\"));var l=i.$styleSheet.html(),a=l.replace(r,\".col\"+t.index+\" { width: \"+t.width+\"px; left: \"+n+\"px\");e.isIe?setTimeout(function(){i.$styleSheet.html(a)}):i.$styleSheet.html(a)}},n.setColLeft.immediate=1,n.RebuildGrid=function(e,t){n.UpdateGridLayout(e,t),(null==t.config.maintainColumnRatios||t.config.maintainColumnRatios)&&t.configureColumnWidths(),e.adjustScrollLeft(t.$viewport.scrollLeft()),n.BuildStyles(e,t,!0)},n.digest=function(e){e.$root.$$phase||e.$digest()},n.ScrollH=17,n.ScrollW=17,n.LetterW=10,i(),n}]),angular.module(\"ngGrid.services\").factory(\"$sortService\",[\"$parse\",function(e){var t={};return t.colSortFnCache={},t.guessSortFn=function(e){var n=typeof e;switch(n){case\"number\":return t.sortNumber;case\"boolean\":return t.sortBool;case\"string\":return e.match(/^[-+]?[£$¤]?[\\d,.]+%?$/)?t.sortNumberStr:t.sortAlpha;default:return\"[object Date]\"===Object.prototype.toString.call(e)?t.sortDate:t.basicSort}},t.basicSort=function(e,t){return e===t?0:t>e?-1:1},t.sortNumber=function(e,t){return e-t},t.sortNumberStr=function(e,t){var n,o,i=!1,r=!1;return n=parseFloat(e.replace(/[^0-9.-]/g,\"\")),isNaN(n)&&(i=!0),o=parseFloat(t.replace(/[^0-9.-]/g,\"\")),isNaN(o)&&(r=!0),i&&r?0:i?1:r?-1:n-o},t.sortAlpha=function(e,t){var n=e.toLowerCase(),o=t.toLowerCase();return n===o?0:o>n?-1:1},t.sortDate=function(e,t){var n=e.getTime(),o=t.getTime();return n===o?0:o>n?-1:1},t.sortBool=function(e,t){return e&&t?0:e||t?e?1:-1:0},t.sortData=function(n,o){if(o&&n){var r,l,a=n.fields.length,s=n.fields,c=o.slice(0);o.sort(function(o,g){for(var d,u=0,f=0;0===u&&a>f;){r=n.columns[f],l=n.directions[f],d=t.getSortFn(r,c);var h=e(s[f])(o),p=e(s[f])(g);!h&&0!==h||!p&&0!==p?p||h?h?p||(u=-1):u=1:u=0:u=d(h,p),f++}return l===i?u:0-u})}},t.Sort=function(e,n){t.isSorting||(t.isSorting=!0,t.sortData(e,n),t.isSorting=!1)},t.getSortFn=function(n,o){var i,r;if(t.colSortFnCache[n.field])i=t.colSortFnCache[n.field];else if(void 0!==n.sortingAlgorithm)i=n.sortingAlgorithm,t.colSortFnCache[n.field]=n.sortingAlgorithm;else{if(r=o[0],!r)return i;i=t.guessSortFn(e(n.field)(r)),i?t.colSortFnCache[n.field]=i:i=t.sortAlpha}return i},t}]),angular.module(\"ngGrid.services\").factory(\"$utilityService\",[\"$parse\",function(n){var o=/function (.{1,})\\(/,i={visualLength:function(e){var n=document.getElementById(\"testDataLength\");return n||(n=document.createElement(\"SPAN\"),n.id=\"testDataLength\",n.style.visibility=\"hidden\",document.body.appendChild(n)),t(n).css(\"font\",t(e).css(\"font\")),t(n).css(\"font-size\",t(e).css(\"font-size\")),t(n).css(\"font-family\",t(e).css(\"font-family\")),n.innerHTML=t(e).text(),n.offsetWidth},forIn:function(e,t){for(var n in e)e.hasOwnProperty(n)&&t(e[n],n)},evalProperty:function(e,t){return n(t)(e)},endsWith:function(e,t){return e&&t&&\"string\"==typeof e?-1!==e.indexOf(t,e.length-t.length):!1},isNullOrUndefined:function(e){return void 0===e||null===e?!0:!1},getElementsByClassName:function(e){for(var t=[],n=RegExp(\"\\\\b\"+e+\"\\\\b\"),o=document.getElementsByTagName(\"*\"),i=0;o.length>i;i++){var r=o[i].className;n.test(r)&&t.push(o[i])}return t},newId:function(){var e=(new Date).getTime();return function(){return e+=1}}(),seti18n:function(t,n){var o=e.ngGrid.i18n[n];for(var i in o)t.i18n[i]=o[i]},getInstanceType:function(e){var t=o.exec(\"\"+e.constructor);if(t&&t.length>1){var n=t[1].replace(/^\\s+|\\s+$/g,\"\");return n}return\"\"},ieVersion:function(){var e=3,t=document.createElement(\"div\"),n=t.getElementsByTagName(\"i\");do t.innerHTML=\"<!--[if gt IE \"+ ++e+\"]><i></i><![endif]-->\";while(n[0]);return e>4?e:void 0}()};return t.extend(i,{isIe:function(){return void 0!==i.ieVersion}()}),i}]);var w=function(e,t,n,o){this.rowIndex=0,this.offsetTop=this.rowIndex*n,this.entity=e,this.label=e.gLabel,this.field=e.gField,this.depth=e.gDepth,this.parent=e.parent,this.children=e.children,this.aggChildren=e.aggChildren,this.aggIndex=e.aggIndex,this.collapsed=o,this.groupInitState=o,this.rowFactory=t,this.rowHeight=n,this.isAggRow=!0,this.offsetLeft=25*e.gDepth,this.aggLabelFilter=e.aggLabelFilter};w.prototype.toggleExpand=function(){this.collapsed=this.collapsed?!1:!0,this.orig&&(this.orig.collapsed=this.collapsed),this.notifyChildren()},w.prototype.setExpand=function(e){this.collapsed=e,this.notifyChildren()},w.prototype.notifyChildren=function(){for(var e=Math.max(this.rowFactory.aggCache.length,this.children.length),t=0;e>t;t++)if(this.aggChildren[t]&&(this.aggChildren[t].entity[s]=this.collapsed,this.collapsed&&this.aggChildren[t].setExpand(this.collapsed)),this.children[t]&&(this.children[t][s]=this.collapsed),t>this.aggIndex&&this.rowFactory.aggCache[t]){var n=this.rowFactory.aggCache[t],o=30*this.children.length;n.offsetTop=this.collapsed?n.offsetTop-o:n.offsetTop+o}this.rowFactory.renderedChange()},w.prototype.aggClass=function(){return this.collapsed?\"ngAggArrowCollapsed\":\"ngAggArrowExpanded\"},w.prototype.totalChildren=function(){if(this.aggChildren.length>0){var e=0,t=function(n){n.aggChildren.length>0?angular.forEach(n.aggChildren,function(e){t(e)}):e+=n.children.length};return t(this),e}return this.children.length},w.prototype.copy=function(){var e=new w(this.entity,this.rowFactory,this.rowHeight,this.groupInitState);return e.orig=this,e};var C=function(e,n,o,l,a,s){var c=this,d=e.colDef,u=500,f=0,p=null;c.colDef=e.colDef,c.width=d.width,c.groupIndex=0,c.isGroupedBy=!1,c.minWidth=d.minWidth?d.minWidth:50,c.maxWidth=d.maxWidth?d.maxWidth:9e3,c.enableCellEdit=void 0!==d.enableCellEdit?d.enableCellEdit:e.enableCellEdit||e.enableCellEditOnFocus,c.headerRowHeight=e.headerRowHeight,c.displayName=void 0===d.displayName?d.field:d.displayName,c.index=e.index,c.isAggCol=e.isAggCol,c.cellClass=d.cellClass,c.sortPriority=void 0,c.cellFilter=d.cellFilter?d.cellFilter:\"\",c.field=d.field,c.aggLabelFilter=d.cellFilter||d.aggLabelFilter,c.visible=s.isNullOrUndefined(d.visible)||d.visible,c.sortable=!1,c.resizable=!1,c.pinnable=!1,c.pinned=e.enablePinning&&d.pinned,c.originalIndex=null==e.originalIndex?c.index:e.originalIndex,c.groupable=s.isNullOrUndefined(d.groupable)||d.groupable,e.enableSort&&(c.sortable=s.isNullOrUndefined(d.sortable)||d.sortable),e.enableResize&&(c.resizable=s.isNullOrUndefined(d.resizable)||d.resizable),e.enablePinning&&(c.pinnable=s.isNullOrUndefined(d.pinnable)||d.pinnable),c.sortDirection=void 0,c.sortingAlgorithm=d.sortFn,c.headerClass=d.headerClass,c.cursor=c.sortable?\"pointer\":\"default\",c.headerCellTemplate=d.headerCellTemplate||a.get(\"headerCellTemplate.html\"),c.cellTemplate=d.cellTemplate||a.get(\"cellTemplate.html\").replace(g,c.cellFilter?\"|\"+c.cellFilter:\"\"),c.enableCellEdit&&(c.cellEditTemplate=a.get(\"cellEditTemplate.html\"),c.editableCellTemplate=d.editableCellTemplate||a.get(\"editableCellTemplate.html\")),d.cellTemplate&&!h.test(d.cellTemplate)&&(c.cellTemplate=t.ajax({type:\"GET\",url:d.cellTemplate,async:!1}).responseText),c.enableCellEdit&&d.editableCellTemplate&&!h.test(d.editableCellTemplate)&&(c.editableCellTemplate=t.ajax({type:\"GET\",url:d.editableCellTemplate,async:!1}).responseText),d.headerCellTemplate&&!h.test(d.headerCellTemplate)&&(c.headerCellTemplate=t.ajax({type:\"GET\",url:d.headerCellTemplate,async:!1}).responseText),c.colIndex=function(){var e=c.pinned?\"pinned \":\"\";return e+=\"col\"+c.index+\" colt\"+c.index,c.cellClass&&(e+=\" \"+c.cellClass),e},c.groupedByClass=function(){return c.isGroupedBy?\"ngGroupedByIcon\":\"ngGroupIcon\"},c.toggleVisible=function(){c.visible=!c.visible},c.showSortButtonUp=function(){return c.sortable?c.sortDirection===r:c.sortable},c.showSortButtonDown=function(){return c.sortable?c.sortDirection===i:c.sortable},c.noSortVisible=function(){return!c.sortDirection},c.sort=function(t){if(!c.sortable)return!0;var n=c.sortDirection===i?r:i;return c.sortDirection=n,e.sortCallback(c,t),!1},c.gripClick=function(){f++,1===f?p=setTimeout(function(){f=0},u):(clearTimeout(p),e.resizeOnDataCallback(c),f=0)},c.gripOnMouseDown=function(e){return n.isColumnResizing=!0,e.ctrlKey&&!c.pinned?(c.toggleVisible(),l.BuildStyles(n,o),!0):(e.target.parentElement.style.cursor=\"col-resize\",c.startMousePosition=e.clientX,c.origWidth=c.width,t(document).mousemove(c.onMouseMove),t(document).mouseup(c.gripOnMouseUp),!1)},c.onMouseMove=function(e){var t=e.clientX-c.startMousePosition,i=t+c.origWidth;return c.width=c.minWidth>i?c.minWidth:i>c.maxWidth?c.maxWidth:i,n.hasUserChangedGridColumnWidths=!0,l.BuildStyles(n,o),!1},c.gripOnMouseUp=function(e){return t(document).off(\"mousemove\",c.onMouseMove),t(document).off(\"mouseup\",c.gripOnMouseUp),e.target.parentElement.style.cursor=\"default\",l.digest(n),n.isColumnResizing=!1,!1},c.copy=function(){var t=new C(e,n,o,l,a);return t.isClone=!0,t.orig=c,t},c.setVars=function(e){c.orig=e,c.width=e.width,c.groupIndex=e.groupIndex,c.isGroupedBy=e.isGroupedBy,c.displayName=e.displayName,c.index=e.index,c.isAggCol=e.isAggCol,c.cellClass=e.cellClass,c.cellFilter=e.cellFilter,c.field=e.field,c.aggLabelFilter=e.aggLabelFilter,c.visible=e.visible,c.sortable=e.sortable,c.resizable=e.resizable,c.pinnable=e.pinnable,c.pinned=e.pinned,c.originalIndex=e.originalIndex,c.sortDirection=e.sortDirection,c.sortingAlgorithm=e.sortingAlgorithm,c.headerClass=e.headerClass,c.headerCellTemplate=e.headerCellTemplate,c.cellTemplate=e.cellTemplate,c.cellEditTemplate=e.cellEditTemplate}},b=function(e){this.outerHeight=null,this.outerWidth=null,t.extend(this,e)},S=function(e){this.previousColumn=null,this.grid=e};S.prototype.changeUserSelect=function(e,t){e.css({\"-webkit-touch-callout\":t,\"-webkit-user-select\":t,\"-khtml-user-select\":t,\"-moz-user-select\":\"none\"===t?\"-moz-none\":t,\"-ms-user-select\":t,\"user-select\":t})},S.prototype.focusCellElement=function(e,t){if(e.selectionProvider.lastClickedRow){var n=void 0!==t?t:this.previousColumn,o=e.selectionProvider.lastClickedRow.clone?e.selectionProvider.lastClickedRow.clone.elm:e.selectionProvider.lastClickedRow.elm;if(void 0!==n&&o){var i=angular.element(o[0].children).filter(function(){return 8!==this.nodeType}),r=Math.max(Math.min(e.renderedColumns.length-1,n),0);this.grid.config.showSelectionCheckbox&&angular.element(i[r]).scope()&&0===angular.element(i[r]).scope().col.index&&(r=1),i[r]&&i[r].children[1].children[0].focus(),this.previousColumn=n}}},S.prototype.selectionHandlers=function(e,t){var n=!1,o=this;t.bind(\"keydown\",function(i){if(16===i.keyCode)return o.changeUserSelect(t,\"none\",i),!0;if(!n){n=!0;var r=v(e,t,i,o.grid);return n=!1,r}return!0}),t.bind(\"keyup\",function(e){return 16===e.keyCode&&o.changeUserSelect(t,\"text\",e),!0})};var x=function(n,o,i,r){var l=this;l.colToMove=void 0,l.groupToMove=void 0,l.assignEvents=function(){n.config.jqueryUIDraggable&&!n.config.enablePinning?n.$groupPanel.droppable({addClasses:!1,drop:function(e){l.onGroupDrop(e)}}):(n.$groupPanel.on(\"mousedown\",l.onGroupMouseDown).on(\"dragover\",l.dragOver).on(\"drop\",l.onGroupDrop),n.$headerScroller.on(\"mousedown\",l.onHeaderMouseDown).on(\"dragover\",l.dragOver),n.config.enableColumnReordering&&!n.config.enablePinning&&n.$headerScroller.on(\"drop\",l.onHeaderDrop)),o.$watch(\"renderedColumns\",function(){r(l.setDraggables)})},l.dragStart=function(e){e.dataTransfer.setData(\"text\",\"\")},l.dragOver=function(e){e.preventDefault()},l.setDraggables=function(){if(n.config.jqueryUIDraggable)n.$root.find(\".ngHeaderSortColumn\").draggable({helper:\"clone\",appendTo:\"body\",stack:\"div\",addClasses:!1,start:function(e){l.onHeaderMouseDown(e)}}).droppable({drop:function(e){l.onHeaderDrop(e)}});else{var e=n.$root.find(\".ngHeaderSortColumn\");angular.forEach(e,function(e){e.className&&-1!==e.className.indexOf(\"ngHeaderSortColumn\")&&(e.setAttribute(\"draggable\",\"true\"),e.addEventListener&&e.addEventListener(\"dragstart\",l.dragStart))}),-1!==navigator.userAgent.indexOf(\"MSIE\")&&n.$root.find(\".ngHeaderSortColumn\").bind(\"selectstart\",function(){return this.dragDrop(),!1})}},l.onGroupMouseDown=function(e){var o=t(e.target);if(\"ngRemoveGroup\"!==o[0].className){var i=angular.element(o).scope();i&&(n.config.jqueryUIDraggable||(o.attr(\"draggable\",\"true\"),this.addEventListener&&this.addEventListener(\"dragstart\",l.dragStart),-1!==navigator.userAgent.indexOf(\"MSIE\")&&o.bind(\"selectstart\",function(){return this.dragDrop(),!1})),l.groupToMove={header:o,groupName:i.group,index:i.$index})}else l.groupToMove=void 0},l.onGroupDrop=function(e){e.stopPropagation();var i,r;l.groupToMove?(i=t(e.target).closest(\".ngGroupElement\"),\"ngGroupPanel\"===i.context.className?(o.configGroups.splice(l.groupToMove.index,1),o.configGroups.push(l.groupToMove.groupName)):(r=angular.element(i).scope(),r&&l.groupToMove.index!==r.$index&&(o.configGroups.splice(l.groupToMove.index,1),o.configGroups.splice(r.$index,0,l.groupToMove.groupName))),l.groupToMove=void 0,n.fixGroupIndexes()):l.colToMove&&(-1===o.configGroups.indexOf(l.colToMove.col)&&(i=t(e.target).closest(\".ngGroupElement\"),\"ngGroupPanel\"===i.context.className||\"ngGroupPanelDescription ng-binding\"===i.context.className?o.groupBy(l.colToMove.col):(r=angular.element(i).scope(),r&&o.removeGroup(r.$index))),l.colToMove=void 0),o.$$phase||o.$apply()},l.onHeaderMouseDown=function(e){var n=t(e.target).closest(\".ngHeaderSortColumn\"),o=angular.element(n).scope();o&&(l.colToMove={header:n,col:o.col})},l.onHeaderDrop=function(e){if(l.colToMove&&!l.colToMove.col.pinned){var r=t(e.target).closest(\".ngHeaderSortColumn\"),a=angular.element(r).scope();if(a){if(l.colToMove.col===a.col)return;o.columns.splice(l.colToMove.col.index,1),o.columns.splice(a.col.index,0,l.colToMove.col),n.fixColumnIndexes(),l.colToMove=void 0,i.digest(o)}}},l.assignGridEventHandlers=function(){-1===n.config.tabIndex?(n.$viewport.attr(\"tabIndex\",i.numberOfGrids),i.numberOfGrids++):n.$viewport.attr(\"tabIndex\",n.config.tabIndex);var r;t(e).resize(function(){clearTimeout(r),r=setTimeout(function(){i.RebuildGrid(o,n)},100)});var l;t(n.$root.parent()).on(\"resize\",function(){clearTimeout(l),l=setTimeout(function(){i.RebuildGrid(o,n)},100)})},l.assignGridEventHandlers(),l.assignEvents()},y=function(e,t){e.maxRows=function(){var n=Math.max(e.totalServerItems,t.data.length);return n},e.multiSelect=t.config.enableRowSelection&&t.config.multiSelect,e.selectedItemCount=t.selectedItemCount,e.maxPages=function(){return Math.ceil(e.maxRows()/e.pagingOptions.pageSize)},e.pageForward=function(){var t=e.pagingOptions.currentPage;e.totalServerItems>0?e.pagingOptions.currentPage=Math.min(t+1,e.maxPages()):e.pagingOptions.currentPage++},e.pageBackward=function(){var t=e.pagingOptions.currentPage;e.pagingOptions.currentPage=Math.max(t-1,1)},e.pageToFirst=function(){e.pagingOptions.currentPage=1},e.pageToLast=function(){var t=e.maxPages();e.pagingOptions.currentPage=t},e.cantPageForward=function(){var n=e.pagingOptions.currentPage,o=e.maxPages();return e.totalServerItems>0?n>=o:1>t.data.length},e.cantPageToLast=function(){return e.totalServerItems>0?e.cantPageForward():!0},e.cantPageBackward=function(){var t=e.pagingOptions.currentPage;return 1>=t}},T=function(i,r,l,a,c,g,d,u,f,p,m){var v={aggregateTemplate:void 0,afterSelectionChange:function(){},beforeSelectionChange:function(){return!0},checkboxCellTemplate:void 0,checkboxHeaderTemplate:void 0,columnDefs:void 0,data:[],dataUpdated:function(){},enableCellEdit:!1,enableCellEditOnFocus:!1,enableCellSelection:!1,enableColumnResize:!1,enableColumnReordering:!1,enableColumnHeavyVirt:!1,enablePaging:!1,enablePinning:!1,enableRowSelection:!0,enableSorting:!0,enableHighlighting:!1,excludeProperties:[],filterOptions:{filterText:\"\",useExternalFilter:!1},footerRowHeight:55,footerTemplate:void 0,groups:[],groupsCollapsedByDefault:!0,headerRowHeight:30,headerRowTemplate:void 0,jqueryUIDraggable:!1,jqueryUITheme:!1,keepLastSelected:!0,maintainColumnRatios:void 0,menuTemplate:void 0,multiSelect:!0,pagingOptions:{pageSizes:[250,500,1e3],pageSize:250,currentPage:1},pinSelectionCheckbox:!1,plugins:[],primaryKey:void 0,rowHeight:30,rowTemplate:void 0,selectedItems:[],selectWithCheckboxOnly:!1,showColumnMenu:!1,showFilter:!1,showFooter:!1,showGroupPanel:!1,showSelectionCheckbox:!1,sortInfo:{fields:[],columns:[],directions:[]},tabIndex:-1,totalServerItems:0,useExternalSorting:!1,i18n:\"en\",virtualizationThreshold:50},w=this;w.maxCanvasHt=0,w.config=t.extend(v,e.ngGrid.config,r),w.config.showSelectionCheckbox=w.config.showSelectionCheckbox&&w.config.enableColumnHeavyVirt===!1,w.config.enablePinning=w.config.enablePinning&&w.config.enableColumnHeavyVirt===!1,w.config.selectWithCheckboxOnly=w.config.selectWithCheckboxOnly&&w.config.showSelectionCheckbox!==!1,w.config.pinSelectionCheckbox=w.config.enablePinning,\"string\"==typeof r.columnDefs&&(w.config.columnDefs=i.$eval(r.columnDefs)),w.rowCache=[],w.rowMap=[],w.gridId=\"ng\"+d.newId(),w.$root=null,w.$groupPanel=null,w.$topPanel=null,w.$headerContainer=null,w.$headerScroller=null,w.$headers=null,w.$viewport=null,w.$canvas=null,w.rootDim=w.config.gridDim,w.data=[],w.lateBindColumns=!1,w.filteredRows=[],w.initTemplates=function(){var e=[\"rowTemplate\",\"aggregateTemplate\",\"headerRowTemplate\",\"checkboxCellTemplate\",\"checkboxHeaderTemplate\",\"menuTemplate\",\"footerTemplate\"],t=[];return angular.forEach(e,function(e){t.push(w.getTemplate(e))}),m.all(t)},w.getTemplate=function(e){var t=w.config[e],n=w.gridId+e+\".html\",o=m.defer();if(t&&!h.test(t))p.get(t,{cache:g}).success(function(e){g.put(n,e),o.resolve()}).error(function(){o.reject(\"Could not load template: \"+t)});else if(t)g.put(n,t),o.resolve();else{var i=e+\".html\";g.put(n,g.get(i)),o.resolve()}return o.promise},\"object\"==typeof w.config.data&&(w.data=w.config.data),w.calcMaxCanvasHeight=function(){var e;return e=w.config.groups.length>0?w.rowFactory.parsedData.filter(function(e){return!e[s]}).length*w.config.rowHeight:w.filteredRows.length*w.config.rowHeight},w.elementDims={scrollW:0,scrollH:0,rowIndexCellW:25,rowSelectedCellW:25,rootMaxW:0,rootMaxH:0},w.setRenderedRows=function(e){i.renderedRows.length=e.length;for(var t=0;e.length>t;t++)!i.renderedRows[t]||e[t].isAggRow||i.renderedRows[t].isAggRow?(i.renderedRows[t]=e[t].copy(),i.renderedRows[t].collapsed=e[t].collapsed,e[t].isAggRow||i.renderedRows[t].setVars(e[t])):i.renderedRows[t].setVars(e[t]),i.renderedRows[t].rowIndex=e[t].rowIndex,i.renderedRows[t].offsetTop=e[t].offsetTop,i.renderedRows[t].selected=e[t].selected,e[t].renderedRowIndex=t;w.refreshDomSizes(),i.$emit(\"ngGridEventRows\",e)},w.minRowsToRender=function(){var e=i.viewportDimHeight()||1;return Math.floor(e/w.config.rowHeight)},w.refreshDomSizes=function(){var e=new b;e.outerWidth=w.elementDims.rootMaxW,e.outerHeight=w.elementDims.rootMaxH,w.rootDim=e,w.maxCanvasHt=w.calcMaxCanvasHeight()},w.buildColumnDefsFromData=function(){w.config.columnDefs=[];var e=w.data[0];return e?(d.forIn(e,function(e,t){-1===w.config.excludeProperties.indexOf(t)&&w.config.columnDefs.push({field:t})}),void 0):(w.lateBoundColumns=!0,void 0)},w.buildColumns=function(){var e=w.config.columnDefs,t=[];if(e||(w.buildColumnDefsFromData(),e=w.config.columnDefs),w.config.showSelectionCheckbox&&t.push(new C({colDef:{field:\"✔\",width:w.elementDims.rowSelectedCellW,sortable:!1,resizable:!1,groupable:!1,headerCellTemplate:g.get(i.gridId+\"checkboxHeaderTemplate.html\"),cellTemplate:g.get(i.gridId+\"checkboxCellTemplate.html\"),pinned:w.config.pinSelectionCheckbox},index:0,headerRowHeight:w.config.headerRowHeight,sortCallback:w.sortData,resizeOnDataCallback:w.resizeOnData,enableResize:w.config.enableColumnResize,enableSort:w.config.enableSorting,enablePinning:w.config.enablePinning},i,w,a,g,d)),e.length>0){var n=w.config.showSelectionCheckbox?1:0,o=i.configGroups.length;i.configGroups.length=0,angular.forEach(e,function(e,r){r+=n;var l=new C({colDef:e,index:r+o,originalIndex:r,headerRowHeight:w.config.headerRowHeight,sortCallback:w.sortData,resizeOnDataCallback:w.resizeOnData,enableResize:w.config.enableColumnResize,enableSort:w.config.enableSorting,enablePinning:w.config.enablePinning,enableCellEdit:w.config.enableCellEdit||w.config.enableCellEditOnFocus},i,w,a,g,d),s=w.config.groups.indexOf(e.field);-1!==s&&(l.isGroupedBy=!0,i.configGroups.splice(s,0,l),l.groupIndex=i.configGroups.length),t.push(l)}),i.columns=t,w.config.groups.length>0&&w.rowFactory.getGrouping(w.config.groups)}},w.configureColumnWidths=function(){var e=[],t=[],n=0,o=0,r={};if(angular.forEach(i.columns,function(e,t){if(!d.isNullOrUndefined(e.originalIndex)){var n=e.originalIndex;w.config.showSelectionCheckbox&&(0===e.originalIndex&&e.visible&&(o+=25),n--),r[n]=t}}),angular.forEach(w.config.columnDefs,function(l,a){var s=i.columns[r[a]];l.index=a;var c,g=!1;if(d.isNullOrUndefined(l.width)?l.width=\"*\":(g=isNaN(l.width)?d.endsWith(l.width,\"%\"):!1,c=g?l.width:parseInt(l.width,10)),isNaN(c)&&!i.hasUserChangedGridColumnWidths){if(c=l.width,\"auto\"===c){s.width=s.minWidth,o+=s.width;var u=s;return i.$on(\"ngGridEventData\",function(){w.resizeOnData(u)}),void 0}if(-1!==c.indexOf(\"*\"))return s.visible!==!1&&(n+=c.length),e.push(l),void 0;if(g)return t.push(l),void 0;throw'unable to parse column width, use percentage (\"10%\",\"20%\", etc...) or \"*\" to use remaining width of grid'}s.visible!==!1&&(o+=s.width=parseInt(s.width,10))}),t.length>0){w.config.maintainColumnRatios=w.config.maintainColumnRatios!==!1;var l=0,s=0;angular.forEach(t,function(e){var t=i.columns[r[e.index]],n=e.width,o=parseInt(n.slice(0,-1),10)/100;l+=o,t.visible||(s+=o)});var c=l-s;angular.forEach(t,function(e){var t=i.columns[r[e.index]],n=e.width,a=parseInt(n.slice(0,-1),10)/100;a/=s>0?c:l;var g=w.rootDim.outerWidth*l;t.width=Math.floor(g*a),o+=t.width})}if(e.length>0){w.config.maintainColumnRatios=w.config.maintainColumnRatios!==!1;var g=w.rootDim.outerWidth-o;w.maxCanvasHt>i.viewportDimHeight()&&(g-=a.ScrollW);var u=Math.floor(g/n);angular.forEach(e,function(t,n){var l=i.columns[r[t.index]];l.width=u*t.width.length,l.visible!==!1&&(o+=l.width);var s=n===e.length-1;if(s&&w.rootDim.outerWidth>o){var c=w.rootDim.outerWidth-o;w.maxCanvasHt>i.viewportDimHeight()&&(c-=a.ScrollW),l.width+=c}})}},w.init=function(){return w.initTemplates().then(function(){i.selectionProvider=new D(w,i,f),i.domAccessProvider=new S(w),w.rowFactory=new R(w,i,a,g,d),w.searchProvider=new $(i,w,c),w.styleProvider=new L(i,w),i.$watch(\"configGroups\",function(e){var t=[];angular.forEach(e,function(e){t.push(e.field||e)}),w.config.groups=t,w.rowFactory.filteredRowsChanged(),i.$emit(\"ngGridEventGroups\",e)},!0),i.$watch(\"columns\",function(e){i.isColumnResizing||a.RebuildGrid(i,w),i.$emit(\"ngGridEventColumns\",e)},!0),i.$watch(function(){return r.i18n},function(e){d.seti18n(i,e)}),w.maxCanvasHt=w.calcMaxCanvasHeight(),w.config.sortInfo.fields&&w.config.sortInfo.fields.length>0&&i.$watch(function(){return w.config.sortInfo},function(){l.isSorting||(w.sortColumnsInit(),i.$emit(\"ngGridEventSorted\",w.config.sortInfo))},!0)})},w.resizeOnData=function(e){var n=e.minWidth,o=d.getElementsByClassName(\"col\"+e.index);angular.forEach(o,function(e,o){var i;if(0===o){var r=t(e).find(\".ngHeaderText\");i=d.visualLength(r)+10}else{var l=t(e).find(\".ngCellText\");i=d.visualLength(l)+10}i>n&&(n=i)}),e.width=e.longest=Math.min(e.maxWidth,n+7),a.BuildStyles(i,w,!0)},w.lastSortedColumns=[],w.sortData=function(e,n){if(n&&n.shiftKey&&w.config.sortInfo){var o=w.config.sortInfo.columns.indexOf(e);-1===o?(1===w.config.sortInfo.columns.length&&(w.config.sortInfo.columns[0].sortPriority=1),w.config.sortInfo.columns.push(e),e.sortPriority=w.config.sortInfo.columns.length,w.config.sortInfo.fields.push(e.field),w.config.sortInfo.directions.push(e.sortDirection),w.lastSortedColumns.push(e)):w.config.sortInfo.directions[o]=e.sortDirection}else{var r=t.isArray(e);w.config.sortInfo.columns.length=0,w.config.sortInfo.fields.length=0,w.config.sortInfo.directions.length=0;var l=function(e){w.config.sortInfo.columns.push(e),w.config.sortInfo.fields.push(e.field),w.config.sortInfo.directions.push(e.sortDirection),w.lastSortedColumns.push(e)};r?(w.clearSortingData(),angular.forEach(e,function(e,t){e.sortPriority=t+1,l(e)})):(w.clearSortingData(e),e.sortPriority=void 0,l(e))}w.sortActual(),w.searchProvider.evalFilter(),i.$emit(\"ngGridEventSorted\",w.config.sortInfo)},w.sortColumnsInit=function(){w.config.sortInfo.columns?w.config.sortInfo.columns.length=0:w.config.sortInfo.columns=[],angular.forEach(i.columns,function(e){var t=w.config.sortInfo.fields.indexOf(e.field);-1!==t&&(e.sortDirection=w.config.sortInfo.directions[t]||\"asc\",w.config.sortInfo.columns[t]=e)}),angular.forEach(w.config.sortInfo.columns,function(e){w.sortData(e)})},w.sortActual=function(){if(!w.config.useExternalSorting){var e=w.data.slice(0);angular.forEach(e,function(e,t){var n=w.rowMap[t];if(void 0!==n){var o=w.rowCache[n];void 0!==o&&(e.preSortSelected=o.selected,e.preSortIndex=t)}}),l.Sort(w.config.sortInfo,e),angular.forEach(e,function(e,t){w.rowCache[t].entity=e,w.rowCache[t].selected=e.preSortSelected,w.rowMap[e.preSortIndex]=t,delete e.preSortSelected,delete e.preSortIndex})}},w.clearSortingData=function(e){e?(angular.forEach(w.lastSortedColumns,function(t){e.index!==t.index&&(t.sortDirection=\"\",t.sortPriority=null)}),w.lastSortedColumns[0]=e,w.lastSortedColumns.length=1):(angular.forEach(w.lastSortedColumns,function(e){e.sortDirection=\"\",e.sortPriority=null}),w.lastSortedColumns=[])},w.fixColumnIndexes=function(){for(var e=0;i.columns.length>e;e++)i.columns[e].index=e},w.fixGroupIndexes=function(){angular.forEach(i.configGroups,function(e,t){e.groupIndex=t+1})},i.elementsNeedMeasuring=!0,i.columns=[],i.renderedRows=[],i.renderedColumns=[],i.headerRow=null,i.rowHeight=w.config.rowHeight,i.jqueryUITheme=w.config.jqueryUITheme,i.showSelectionCheckbox=w.config.showSelectionCheckbox,i.enableCellSelection=w.config.enableCellSelection,i.enableCellEditOnFocus=w.config.enableCellEditOnFocus,i.footer=null,i.selectedItems=w.config.selectedItems,i.multiSelect=w.config.multiSelect,i.showFooter=w.config.showFooter,i.footerRowHeight=i.showFooter?w.config.footerRowHeight:0,i.showColumnMenu=w.config.showColumnMenu,i.showMenu=!1,i.configGroups=[],i.gridId=w.gridId,i.enablePaging=w.config.enablePaging,i.pagingOptions=w.config.pagingOptions,i.i18n={},d.seti18n(i,w.config.i18n),i.adjustScrollLeft=function(e){for(var t=0,n=0,o=i.columns.length,r=[],l=!w.config.enableColumnHeavyVirt,s=0,c=function(e){l?r.push(e):i.renderedColumns[s]?i.renderedColumns[s].setVars(e):i.renderedColumns[s]=e.copy(),s++},g=0;o>g;g++){var d=i.columns[g];if(d.visible!==!1){var u=d.width+t;if(d.pinned){c(d);var f=g>0?e+n:e;a.setColLeft(d,f,w),n+=d.width}else u>=e&&e+w.rootDim.outerWidth>=t&&c(d);t+=d.width}}l&&(i.renderedColumns=r)},w.prevScrollTop=0,w.prevScrollIndex=0,i.adjustScrollTop=function(e,t){if(w.prevScrollTop!==e||t){e>0&&w.$viewport[0].scrollHeight-e<=w.$viewport.outerHeight()&&i.$emit(\"ngGridEventScroll\");\n    var r,l=Math.floor(e/w.config.rowHeight);if(w.filteredRows.length>w.config.virtualizationThreshold){if(e>w.prevScrollTop&&w.prevScrollIndex+o>l)return;if(w.prevScrollTop>e&&l>w.prevScrollIndex-o)return;r=new P(Math.max(0,l-n),l+w.minRowsToRender()+n)}else{var a=i.configGroups.length>0?w.rowFactory.parsedData.length:w.data.length;r=new P(0,Math.max(a,w.minRowsToRender()+n))}w.prevScrollTop=e,w.rowFactory.UpdateViewableRange(r),w.prevScrollIndex=l}},i.toggleShowMenu=function(){i.showMenu=!i.showMenu},i.toggleSelectAll=function(e,t){i.selectionProvider.toggleSelectAll(e,!1,t)},i.totalFilteredItemsLength=function(){return w.filteredRows.length},i.showGroupPanel=function(){return w.config.showGroupPanel},i.topPanelHeight=function(){return w.config.showGroupPanel===!0?w.config.headerRowHeight+32:w.config.headerRowHeight},i.viewportDimHeight=function(){return Math.max(0,w.rootDim.outerHeight-i.topPanelHeight()-i.footerRowHeight-2)},i.groupBy=function(e){if(!(1>w.data.length)&&e.groupable&&e.field){e.sortDirection||e.sort({shiftKey:i.configGroups.length>0?!0:!1});var t=i.configGroups.indexOf(e);-1===t?(e.isGroupedBy=!0,i.configGroups.push(e),e.groupIndex=i.configGroups.length):i.removeGroup(t),w.$viewport.scrollTop(0),a.digest(i)}},i.removeGroup=function(e){var t=i.columns.filter(function(t){return t.groupIndex===e+1})[0];t.isGroupedBy=!1,t.groupIndex=0,i.columns[e].isAggCol&&(i.columns.splice(e,1),i.configGroups.splice(e,1),w.fixGroupIndexes()),0===i.configGroups.length&&(w.fixColumnIndexes(),a.digest(i)),i.adjustScrollLeft(0)},i.togglePin=function(e){for(var t=e.index,n=0,o=0;i.columns.length>o&&i.columns[o].pinned;o++)n++;e.pinned&&(n=Math.max(e.originalIndex,n-1)),e.pinned=!e.pinned,i.columns.splice(t,1),i.columns.splice(n,0,e),w.fixColumnIndexes(),a.BuildStyles(i,w,!0),w.$viewport.scrollLeft(w.$viewport.scrollLeft()-e.width)},i.totalRowWidth=function(){for(var e=0,t=i.columns,n=0;t.length>n;n++)t[n].visible!==!1&&(e+=t[n].width);return e},i.headerScrollerDim=function(){var e=i.viewportDimHeight(),t=w.maxCanvasHt,n=t>e,o=new b;return o.autoFitHeight=!0,o.outerWidth=i.totalRowWidth(),n?o.outerWidth+=w.elementDims.scrollW:w.elementDims.scrollH>=t-e&&(o.outerWidth+=w.elementDims.scrollW),o}},P=function(e,t){this.topRow=e,this.bottomRow=t},I=function(e,t,n,o,i){this.entity=e,this.config=t,this.selectionProvider=n,this.rowIndex=o,this.utils=i,this.selected=n.getSelection(e),this.cursor=this.config.enableRowSelection?\"pointer\":\"default\",this.beforeSelectionChange=t.beforeSelectionChangeCallback,this.afterSelectionChange=t.afterSelectionChangeCallback,this.offsetTop=this.rowIndex*t.rowHeight,this.rowDisplayIndex=0};I.prototype.setSelection=function(e){this.selectionProvider.setSelection(this,e),this.selectionProvider.lastClickedRow=this},I.prototype.continueSelection=function(e){this.selectionProvider.ChangeSelection(this,e)},I.prototype.ensureEntity=function(e){this.entity!==e&&(this.entity=e,this.selected=this.selectionProvider.getSelection(this.entity))},I.prototype.toggleSelected=function(e){if(!this.config.enableRowSelection&&!this.config.enableCellSelection)return!0;var t=e.target||e;return\"checkbox\"===t.type&&\"ngSelectionCell ng-scope\"!==t.parentElement.className?!0:this.config.selectWithCheckboxOnly&&\"checkbox\"!==t.type?(this.selectionProvider.lastClickedRow=this,!0):(this.beforeSelectionChange(this,e)&&this.continueSelection(e),!1)},I.prototype.alternatingRowClass=function(){var e=0===this.rowIndex%2,t={ngRow:!0,selected:this.selected,even:e,odd:!e,\"ui-state-default\":this.config.jqueryUITheme&&e,\"ui-state-active\":this.config.jqueryUITheme&&!e};return t},I.prototype.getProperty=function(e){return this.utils.evalProperty(this.entity,e)},I.prototype.copy=function(){return this.clone=new I(this.entity,this.config,this.selectionProvider,this.rowIndex,this.utils),this.clone.isClone=!0,this.clone.elm=this.elm,this.clone.orig=this,this.clone},I.prototype.setVars=function(e){e.clone=this,this.entity=e.entity,this.selected=e.selected,this.orig=e};var R=function(e,t,o,i,r){var g=this;g.aggCache={},g.parentCache=[],g.dataChanged=!0,g.parsedData=[],g.rowConfig={},g.selectionProvider=t.selectionProvider,g.rowHeight=30,g.numberOfAggregates=0,g.groupedData=void 0,g.rowHeight=e.config.rowHeight,g.rowConfig={enableRowSelection:e.config.enableRowSelection,rowClasses:e.config.rowClasses,selectedItems:t.selectedItems,selectWithCheckboxOnly:e.config.selectWithCheckboxOnly,beforeSelectionChangeCallback:e.config.beforeSelectionChange,afterSelectionChangeCallback:e.config.afterSelectionChange,jqueryUITheme:e.config.jqueryUITheme,enableCellSelection:e.config.enableCellSelection,rowHeight:e.config.rowHeight},g.renderedRange=new P(0,e.minRowsToRender()+n),g.buildEntityRow=function(e,t){return new I(e,g.rowConfig,g.selectionProvider,t,r)},g.buildAggregateRow=function(t,n){var o=g.aggCache[t.aggIndex];return o||(o=new w(t,g,g.rowConfig.rowHeight,e.config.groupsCollapsedByDefault),g.aggCache[t.aggIndex]=o),o.rowIndex=n,o.offsetTop=n*g.rowConfig.rowHeight,o},g.UpdateViewableRange=function(e){g.renderedRange=e,g.renderedChange()},g.filteredRowsChanged=function(){e.lateBoundColumns&&e.filteredRows.length>0&&(e.config.columnDefs=void 0,e.buildColumns(),e.lateBoundColumns=!1,t.$evalAsync(function(){t.adjustScrollLeft(0)})),g.dataChanged=!0,e.config.groups.length>0&&g.getGrouping(e.config.groups),g.UpdateViewableRange(g.renderedRange)},g.renderedChange=function(){if(!g.groupedData||1>e.config.groups.length)return g.renderedChangeNoGroups(),e.refreshDomSizes(),void 0;g.wasGrouped=!0,g.parentCache=[];var t=0,n=g.parsedData.filter(function(e){return e.isAggRow?e.parent&&e.parent.collapsed?!1:!0:(e[s]||(e.rowIndex=t++),!e[s])});g.totalRows=n.length;for(var o=[],i=g.renderedRange.topRow;g.renderedRange.bottomRow>i;i++)n[i]&&(n[i].offsetTop=i*e.config.rowHeight,o.push(n[i]));e.setRenderedRows(o)},g.renderedChangeNoGroups=function(){for(var t=[],n=g.renderedRange.topRow;g.renderedRange.bottomRow>n;n++)e.filteredRows[n]&&(e.filteredRows[n].rowIndex=n,e.filteredRows[n].offsetTop=n*e.config.rowHeight,t.push(e.filteredRows[n]));e.setRenderedRows(t)},g.fixRowCache=function(){var t=e.data.length,n=t-e.rowCache.length;if(0>n)e.rowCache.length=e.rowMap.length=t;else for(var o=e.rowCache.length;t>o;o++)e.rowCache[o]=e.rowFactory.buildEntityRow(e.data[o],o)},g.parseGroupData=function(e){if(e.values)for(var t=0;e.values.length>t;t++)g.parentCache[g.parentCache.length-1].children.push(e.values[t]),g.parsedData.push(e.values[t]);else for(var n in e)if(n!==l&&n!==a&&n!==c&&e.hasOwnProperty(n)){var o=g.buildAggregateRow({gField:e[l],gLabel:n,gDepth:e[a],isAggRow:!0,_ng_hidden_:!1,children:[],aggChildren:[],aggIndex:g.numberOfAggregates,aggLabelFilter:e[c].aggLabelFilter},0);g.numberOfAggregates++,o.parent=g.parentCache[o.depth-1],o.parent&&(o.parent.collapsed=!1,o.parent.aggChildren.push(o)),g.parsedData.push(o),g.parentCache[o.depth]=o,g.parseGroupData(e[n])}},g.getGrouping=function(n){function d(e,t){return e.filter(function(e){return e.field===t})}g.aggCache=[],g.numberOfAggregates=0,g.groupedData={};for(var u=e.filteredRows,f=n.length,h=t.columns,p=0;u.length>p;p++){var m=u[p].entity;if(!m)return;u[p][s]=e.config.groupsCollapsedByDefault;for(var v=g.groupedData,w=0;n.length>w;w++){var b=n[w],S=d(h,b)[0],x=r.evalProperty(m,b);x=x?\"\"+x:\"null\",v[x]||(v[x]={}),v[l]||(v[l]=b),v[a]||(v[a]=w),v[c]||(v[c]=S),v=v[x]}v.values||(v.values=[]),v.values.push(u[p])}if(h.length>0)for(var y=0;n.length>y;y++)!h[y].isAggCol&&f>=y&&h.splice(0,0,new C({colDef:{field:\"\",width:25,sortable:!1,resizable:!1,headerCellTemplate:'<div class=\"ngAggHeader\"></div>',pinned:e.config.pinSelectionCheckbox},enablePinning:e.config.enablePinning,isAggCol:!0,headerRowHeight:e.config.headerRowHeight},t,e,o,i,r));e.fixColumnIndexes(),t.adjustScrollLeft(0),g.parsedData.length=0,g.parseGroupData(g.groupedData),g.fixRowCache()},e.config.groups.length>0&&e.filteredRows.length>0&&g.getGrouping(e.config.groups)},$=function(e,n,o){var i=this,r=[];i.extFilter=n.config.filterOptions.useExternalFilter,e.showFilter=n.config.showFilter,e.filterText=\"\",i.fieldMap={};var l=function(e,t,n){var i;for(var r in t)if(t.hasOwnProperty(r)){var a=n[r.toLowerCase()];if(!a)continue;var s=t[r];if(\"object\"==typeof s)return l(e,s,a);var c=null,g=null;if(a&&a.cellFilter&&(g=a.cellFilter.split(\":\"),c=o(g[0])),null!==s&&void 0!==s){if(\"function\"==typeof c){var d=\"\"+c(s,g[1]);i=e.regex.test(d)}else i=e.regex.test(\"\"+s);if(i)return!0}}return!1},a=function(e,t){var n,r=i.fieldMap[e.columnDisplay];if(!r)return!1;var l=r.cellFilter.split(\":\"),a=r.cellFilter?o(l[0]):null,s=t[e.column]||t[r.field.split(\".\")[0]];if(null===s||void 0===s)return!1;if(\"function\"==typeof a){var g=\"\"+a(\"object\"==typeof s?c(s,r.field):s,l[1]);n=e.regex.test(g)}else n=e.regex.test(\"object\"==typeof s?\"\"+c(s,r.field):\"\"+s);return n?!0:!1},s=function(e){for(var t=0,n=r.length;n>t;t++){var o,s=r[t];if(o=s.column?a(s,e):l(s,e,i.fieldMap),!o)return!1}return!0};i.evalFilter=function(){n.filteredRows=0===r.length?n.rowCache:n.rowCache.filter(function(e){return s(e.entity)});for(var e=0;n.filteredRows.length>e;e++)n.filteredRows[e].rowIndex=e;n.rowFactory.filteredRowsChanged()};var c=function(e,t){if(\"object\"!=typeof e||\"string\"!=typeof t)return e;var n=t.split(\".\"),o=e;if(n.length>1){for(var i=1,r=n.length;r>i;i++)if(o=o[n[i]],!o)return e;return o}return e},g=function(e,t){try{return RegExp(e,t)}catch(n){return RegExp(e.replace(/(\\^|\\$|\\(|\\)|<|>|\\[|\\]|\\{|\\}|\\\\|\\||\\.|\\*|\\+|\\?)/g,\"\\\\$1\"))}},d=function(e){r=[];var n;if(n=t.trim(e))for(var o=n.split(\";\"),i=0;o.length>i;i++){var l=o[i].split(\":\");if(l.length>1){var a=t.trim(l[0]),s=t.trim(l[1]);a&&s&&r.push({column:a,columnDisplay:a.replace(/\\s+/g,\"\").toLowerCase(),regex:g(s,\"i\")})}else{var c=t.trim(l[0]);c&&r.push({column:\"\",regex:g(c,\"i\")})}}};i.extFilter||e.$watch(\"columns\",function(e){for(var t=0;e.length>t;t++){var n=e[t];if(n.field)if(n.field.match(/\\./g)){for(var o=n.field.split(\".\"),r=i.fieldMap,l=0;o.length-1>l;l++)r[o[l]]=r[o[l]]||{},r=r[o[l]];r[o[o.length-1]]=n}else i.fieldMap[n.field.toLowerCase()]=n;n.displayName&&(i.fieldMap[n.displayName.toLowerCase().replace(/\\s+/g,\"\")]=n)}}),e.$watch(function(){return n.config.filterOptions.filterText},function(t){e.filterText=t}),e.$watch(\"filterText\",function(t){i.extFilter||(e.$emit(\"ngGridEventFilter\",t),d(t),i.evalFilter())})},D=function(e,t,n){var o=this;o.multi=e.config.multiSelect,o.selectedItems=e.config.selectedItems,o.selectedIndex=e.config.selectedIndex,o.lastClickedRow=void 0,o.ignoreSelectedItemChanges=!1,o.pKeyParser=n(e.config.primaryKey),o.ChangeSelection=function(n,i){var r=i.which||i.keyCode,l=40===r||38===r;if(i&&i.shiftKey&&!i.keyCode&&o.multi&&e.config.enableRowSelection){if(o.lastClickedRow){var a;a=t.configGroups.length>0?e.rowFactory.parsedData.filter(function(e){return!e.isAggRow}):e.filteredRows;var s=n.rowIndex,c=o.lastClickedRowIndex;if(s===c)return!1;c>s?(s^=c,c=s^c,s^=c,s--):c++;for(var g=[];s>=c;c++)g.push(a[c]);if(g[g.length-1].beforeSelectionChange(g,i)){for(var d=0;g.length>d;d++){var u=g[d],f=u.selected;u.selected=!f,u.clone&&(u.clone.selected=u.selected);var h=o.selectedItems.indexOf(u.entity);-1===h?o.selectedItems.push(u.entity):o.selectedItems.splice(h,1)}g[g.length-1].afterSelectionChange(g,i)}return o.lastClickedRow=n,o.lastClickedRowIndex=n.rowIndex,!0}}else o.multi?(!i.keyCode||l&&!e.config.selectWithCheckboxOnly)&&o.setSelection(n,!n.selected):o.lastClickedRow===n?o.setSelection(o.lastClickedRow,e.config.keepLastSelected?!0:!n.selected):(o.lastClickedRow&&o.setSelection(o.lastClickedRow,!1),o.setSelection(n,!n.selected));return o.lastClickedRow=n,o.lastClickedRowIndex=n.rowIndex,!0},o.getSelection=function(t){var n=!1;if(e.config.primaryKey){var i=o.pKeyParser(t);angular.forEach(o.selectedItems,function(e){i===o.pKeyParser(e)&&(n=!0)})}else n=-1!==o.selectedItems.indexOf(t);return n},o.setSelection=function(t,n){if(e.config.enableRowSelection){if(n)-1===o.selectedItems.indexOf(t.entity)&&(!o.multi&&o.selectedItems.length>0&&o.toggleSelectAll(!1,!0),o.selectedItems.push(t.entity));else{var i=o.selectedItems.indexOf(t.entity);-1!==i&&o.selectedItems.splice(i,1)}t.selected=n,t.orig&&(t.orig.selected=n),t.clone&&(t.clone.selected=n),t.afterSelectionChange(t)}},o.toggleSelectAll=function(t,n,i){var r=i?e.filteredRows:e.rowCache;if(n||e.config.beforeSelectionChange(r,t)){var l=o.selectedItems.length;l>0&&(o.selectedItems.length=0);for(var a=0;r.length>a;a++)r[a].selected=t,r[a].clone&&(r[a].clone.selected=t),t&&o.selectedItems.push(r[a].entity);n||e.config.afterSelectionChange(r,t)}}},L=function(e,t){e.headerCellStyle=function(e){return{height:e.headerRowHeight+\"px\"}},e.rowStyle=function(t){var n={top:t.offsetTop+\"px\",height:e.rowHeight+\"px\"};return t.isAggRow&&(n.left=t.offsetLeft),n},e.canvasStyle=function(){return{height:t.maxCanvasHt+\"px\"}},e.headerScrollerStyle=function(){return{height:t.config.headerRowHeight+\"px\"}},e.topPanelStyle=function(){return{width:t.rootDim.outerWidth+\"px\",height:e.topPanelHeight()+\"px\"}},e.headerStyle=function(){return{width:t.rootDim.outerWidth+\"px\",height:t.config.headerRowHeight+\"px\"}},e.groupPanelStyle=function(){return{width:t.rootDim.outerWidth+\"px\",height:\"32px\"}},e.viewportStyle=function(){return{width:t.rootDim.outerWidth+\"px\",height:e.viewportDimHeight()+\"px\"}},e.footerStyle=function(){return{width:t.rootDim.outerWidth+\"px\",height:e.footerRowHeight+\"px\"}}};p.directive(\"ngCellHasFocus\",[\"$domUtilityService\",function(e){var t=function(t){t.isFocused=!0,e.digest(t),t.$broadcast(\"ngGridEventStartCellEdit\"),t.$on(\"ngGridEventEndCellEdit\",function(){t.isFocused=!1,e.digest(t)})};return function(e,n){var o=!1,i=!1;e.editCell=function(){e.enableCellEditOnFocus||setTimeout(function(){t(e,n)},0)},n.bind(\"mousedown\",function(){return e.enableCellEditOnFocus?i=!0:n.focus(),!0}),n.bind(\"click\",function(o){e.enableCellEditOnFocus&&(o.preventDefault(),i=!1,t(e,n))}),n.bind(\"focus\",function(){return o=!0,e.enableCellEditOnFocus&&!i&&t(e,n),!0}),n.bind(\"blur\",function(){return o=!1,!0}),n.bind(\"keydown\",function(i){return e.enableCellEditOnFocus||(o&&37!==i.keyCode&&38!==i.keyCode&&39!==i.keyCode&&40!==i.keyCode&&9!==i.keyCode&&!i.shiftKey&&13!==i.keyCode&&t(e,n),o&&i.shiftKey&&i.keyCode>=65&&90>=i.keyCode&&t(e,n),27===i.keyCode&&n.focus()),!0})}}]),p.directive(\"ngCellText\",function(){return function(e,t){t.bind(\"mouseover\",function(e){e.preventDefault(),t.css({cursor:\"text\"})}),t.bind(\"mouseleave\",function(e){e.preventDefault(),t.css({cursor:\"default\"})})}}),p.directive(\"ngCell\",[\"$compile\",\"$domUtilityService\",function(e,t){var n={scope:!1,compile:function(){return{pre:function(t,n){var o,i=t.col.cellTemplate.replace(d,\"row.entity.\"+t.col.field);t.col.enableCellEdit?(o=t.col.cellEditTemplate,o=o.replace(u,i),o=o.replace(f,t.col.editableCellTemplate.replace(d,\"row.entity.\"+t.col.field))):o=i;var r=e(o)(t);t.enableCellSelection&&-1===r[0].className.indexOf(\"ngSelectionCell\")&&(r[0].setAttribute(\"tabindex\",0),r.addClass(\"ngCellElement\")),n.append(r)},post:function(e,n){e.enableCellSelection&&e.domAccessProvider.selectionHandlers(e,n),e.$on(\"ngGridEventDigestCell\",function(){t.digest(e)})}}}};return n}]),p.directive(\"ngEditCellIf\",[function(){return{transclude:\"element\",priority:1e3,terminal:!0,restrict:\"A\",compile:function(e,t,n){return function(e,t,o){var i,r;e.$watch(o.ngEditCellIf,function(o){i&&(i.remove(),i=void 0),r&&(r.$destroy(),r=void 0),o&&(r=e.$new(),n(r,function(e){i=e,t.after(e)}))})}}}}]),p.directive(\"ngGridFooter\",[\"$compile\",\"$templateCache\",function(e,t){var n={scope:!1,compile:function(){return{pre:function(n,o){0===o.children().length&&o.append(e(t.get(n.gridId+\"footerTemplate.html\"))(n))}}}};return n}]),p.directive(\"ngGridMenu\",[\"$compile\",\"$templateCache\",function(e,t){var n={scope:!1,compile:function(){return{pre:function(n,o){0===o.children().length&&o.append(e(t.get(n.gridId+\"menuTemplate.html\"))(n))}}}};return n}]),p.directive(\"ngGrid\",[\"$compile\",\"$filter\",\"$templateCache\",\"$sortService\",\"$domUtilityService\",\"$utilityService\",\"$timeout\",\"$parse\",\"$http\",\"$q\",function(e,n,o,i,r,l,a,s,c,g){var d={scope:!0,compile:function(){return{pre:function(d,u,f){var h=t(u),p=d.$eval(f.ngGrid);p.gridDim=new b({outerHeight:t(h).height(),outerWidth:t(h).width()});var m=new T(d,p,i,r,n,o,l,a,s,c,g);return m.init().then(function(){if(\"string\"==typeof p.columnDefs?d.$parent.$watch(p.columnDefs,function(e){return e?(m.lateBoundColumns=!1,d.columns=[],m.config.columnDefs=e,m.buildColumns(),m.eventProvider.assignEvents(),r.RebuildGrid(d,m),void 0):(m.refreshDomSizes(),m.buildColumns(),void 0)},!0):m.buildColumns(),\"string\"==typeof p.totalServerItems?d.$parent.$watch(p.totalServerItems,function(e){d.totalServerItems=angular.isDefined(e)?e:0}):d.totalServerItems=0,\"string\"==typeof p.data){var n=function(e){m.data=t.extend([],e),m.rowFactory.fixRowCache(),angular.forEach(m.data,function(e,t){var n=m.rowMap[t]||t;m.rowCache[n]&&m.rowCache[n].ensureEntity(e),m.rowMap[n]=t}),m.searchProvider.evalFilter(),m.configureColumnWidths(),m.refreshDomSizes(),m.config.sortInfo.fields.length>0&&(m.sortColumnsInit(),d.$emit(\"ngGridEventSorted\",m.config.sortInfo)),d.$emit(\"ngGridEventData\",m.gridId)};d.$parent.$watch(p.data,n),d.$parent.$watch(p.data+\".length\",function(){n(d.$eval(p.data))})}return m.footerController=new y(d,m),u.addClass(\"ngGrid\").addClass(\"\"+m.gridId),p.enableHighlighting||u.addClass(\"unselectable\"),p.jqueryUITheme&&u.addClass(\"ui-widget\"),u.append(e(o.get(\"gridTemplate.html\"))(d)),r.AssignGridContainers(d,u,m),m.eventProvider=new x(m,d,r,a),p.selectRow=function(e,t){m.rowCache[e]&&(m.rowCache[e].clone&&m.rowCache[e].clone.setSelection(t?!0:!1),m.rowCache[e].setSelection(t?!0:!1))},p.selectItem=function(e,t){p.selectRow(m.rowMap[e],t)},p.selectAll=function(e){d.toggleSelectAll(e)},p.selectVisible=function(e){d.toggleSelectAll(e,!0)},p.groupBy=function(e){if(e)d.groupBy(d.columns.filter(function(t){return t.field===e})[0]);else{var n=t.extend(!0,[],d.configGroups);angular.forEach(n,d.groupBy)}},p.sortBy=function(e){var t=d.columns.filter(function(t){return t.field===e})[0];t&&t.sort()},p.gridId=m.gridId,p.ngGrid=m,p.$gridScope=d,p.$gridServices={SortService:i,DomUtilityService:r,UtilityService:l},d.$on(\"ngGridEventDigestGrid\",function(){r.digest(d.$parent)}),d.$on(\"ngGridEventDigestGridParent\",function(){r.digest(d.$parent)}),d.$evalAsync(function(){d.adjustScrollLeft(0)}),angular.forEach(p.plugins,function(e){\"function\"==typeof e&&(e=new e),e.init(d.$new(),m,p.$gridServices),p.plugins[l.getInstanceType(e)]=e}),\"function\"==typeof p.init&&p.init(m,d),null})}}}};return d}]),p.directive(\"ngHeaderCell\",[\"$compile\",function(e){var t={scope:!1,compile:function(){return{pre:function(t,n){n.append(e(t.col.headerCellTemplate)(t))}}}};return t}]),p.directive(\"ngInput\",[function(){return{require:\"ngModel\",link:function(e,t,n,o){var i,r=e.$watch(\"ngModel\",function(){i=o.$modelValue,r()});t.bind(\"keydown\",function(n){switch(n.keyCode){case 37:case 38:case 39:case 40:n.stopPropagation();break;case 27:e.$$phase||e.$apply(function(){o.$setViewValue(i),t.blur()});break;case 13:(e.enableCellEditOnFocus&&e.totalFilteredItemsLength()-1>e.row.rowIndex&&e.row.rowIndex>0||e.enableCellEdit)&&t.blur()}return!0}),t.bind(\"click\",function(e){e.stopPropagation()}),t.bind(\"mousedown\",function(e){e.stopPropagation()}),e.$on(\"ngGridEventStartCellEdit\",function(){t.focus(),t.select()}),angular.element(t).bind(\"blur\",function(){e.$emit(\"ngGridEventEndCellEdit\")})}}}]),p.directive(\"ngRow\",[\"$compile\",\"$domUtilityService\",\"$templateCache\",function(e,t,n){var o={scope:!1,compile:function(){return{pre:function(o,i){if(o.row.elm=i,o.row.clone&&(o.row.clone.elm=i),o.row.isAggRow){var r=n.get(o.gridId+\"aggregateTemplate.html\");r=o.row.aggLabelFilter?r.replace(g,\"| \"+o.row.aggLabelFilter):r.replace(g,\"\"),i.append(e(r)(o))}else i.append(e(n.get(o.gridId+\"rowTemplate.html\"))(o));o.$on(\"ngGridEventDigestRow\",function(){t.digest(o)})}}}};return o}]),p.directive(\"ngViewport\",[function(){return function(e,t){var n,o,i=0;t.bind(\"scroll\",function(t){var r=t.target.scrollLeft,l=t.target.scrollTop;return e.$headerContainer&&e.$headerContainer.scrollLeft(r),e.adjustScrollLeft(r),e.adjustScrollTop(l),e.$root.$$phase||e.$digest(),o=r,i=l,n=!1,!0}),t.bind(\"mousewheel DOMMouseScroll\",function(){return n=!0,t.focus&&t.focus(),!0}),e.enableCellSelection||e.domAccessProvider.selectionHandlers(e,t)}}]),e.ngGrid.i18n.da={ngAggregateLabel:\"artikler\",ngGroupPanelDescription:\"Grupér rækker udfra en kolonne ved at trække dens overskift hertil.\",ngSearchPlaceHolder:\"Søg...\",ngMenuText:\"Vælg kolonner:\",ngShowingItemsLabel:\"Viste rækker:\",ngTotalItemsLabel:\"Rækker totalt:\",ngSelectedItemsLabel:\"Valgte rækker:\",ngPageSizeLabel:\"Side størrelse:\",ngPagerFirstTitle:\"Første side\",ngPagerNextTitle:\"Næste side\",ngPagerPrevTitle:\"Forrige side\",ngPagerLastTitle:\"Sidste side\"},e.ngGrid.i18n.de={ngAggregateLabel:\"artikel\",ngGroupPanelDescription:\"Ziehen Sie eine Spaltenüberschrift hier und legen Sie es der Gruppe nach dieser Spalte.\",ngSearchPlaceHolder:\"Suche...\",ngMenuText:\"Spalten auswählen:\",ngShowingItemsLabel:\"Zeige Artikel:\",ngTotalItemsLabel:\"Meiste Artikel:\",ngSelectedItemsLabel:\"Ausgewählte Artikel:\",ngPageSizeLabel:\"Größe Seite:\",ngPagerFirstTitle:\"Erste Page\",ngPagerNextTitle:\"Nächste Page\",ngPagerPrevTitle:\"Vorherige Page\",ngPagerLastTitle:\"Letzte Page\"},e.ngGrid.i18n.en={ngAggregateLabel:\"items\",ngGroupPanelDescription:\"Drag a column header here and drop it to group by that column.\",ngSearchPlaceHolder:\"Search...\",ngMenuText:\"Choose Columns:\",ngShowingItemsLabel:\"Showing Items:\",ngTotalItemsLabel:\"Total Items:\",ngSelectedItemsLabel:\"Selected Items:\",ngPageSizeLabel:\"Page Size:\",ngPagerFirstTitle:\"First Page\",ngPagerNextTitle:\"Next Page\",ngPagerPrevTitle:\"Previous Page\",ngPagerLastTitle:\"Last Page\"},e.ngGrid.i18n.es={ngAggregateLabel:\"Artículos\",ngGroupPanelDescription:\"Arrastre un encabezado de columna aquí y soltarlo para agrupar por esa columna.\",ngSearchPlaceHolder:\"Buscar...\",ngMenuText:\"Elegir columnas:\",ngShowingItemsLabel:\"Artículos Mostrando:\",ngTotalItemsLabel:\"Artículos Totales:\",ngSelectedItemsLabel:\"Artículos Seleccionados:\",ngPageSizeLabel:\"Tamaño de Página:\",ngPagerFirstTitle:\"Primera Página\",ngPagerNextTitle:\"Página Siguiente\",ngPagerPrevTitle:\"Página Anterior\",ngPagerLastTitle:\"Última Página\"},e.ngGrid.i18n.fr={ngAggregateLabel:\"articles\",ngGroupPanelDescription:\"Faites glisser un en-tête de colonne ici et déposez-le vers un groupe par cette colonne.\",ngSearchPlaceHolder:\"Recherche...\",ngMenuText:\"Choisir des colonnes:\",ngShowingItemsLabel:\"Articles Affichage des:\",ngTotalItemsLabel:\"Nombre total d'articles:\",ngSelectedItemsLabel:\"Éléments Articles:\",ngPageSizeLabel:\"Taille de page:\",ngPagerFirstTitle:\"Première page\",ngPagerNextTitle:\"Page Suivante\",ngPagerPrevTitle:\"Page précédente\",ngPagerLastTitle:\"Dernière page\"},e.ngGrid.i18n[\"pt-br\"]={ngAggregateLabel:\"items\",ngGroupPanelDescription:\"Arraste e solte uma coluna aqui para agrupar por essa coluna\",ngSearchPlaceHolder:\"Procurar...\",ngMenuText:\"Selecione as colunas:\",ngShowingItemsLabel:\"Mostrando os Items:\",ngTotalItemsLabel:\"Total de Items:\",ngSelectedItemsLabel:\"Items Selecionados:\",ngPageSizeLabel:\"Tamanho da Página:\",ngPagerFirstTitle:\"Primeira Página\",ngPagerNextTitle:\"Próxima Página\",ngPagerPrevTitle:\"Página Anterior\",ngPagerLastTitle:\"Última Página\"},e.ngGrid.i18n[\"zh-cn\"]={ngAggregateLabel:\"条目\",ngGroupPanelDescription:\"拖曳表头到此处以进行分组\",ngSearchPlaceHolder:\"搜索...\",ngMenuText:\"数据分组与选择列：\",ngShowingItemsLabel:\"当前显示条目：\",ngTotalItemsLabel:\"条目总数：\",ngSelectedItemsLabel:\"选中条目：\",ngPageSizeLabel:\"每页显示数：\",ngPagerFirstTitle:\"回到首页\",ngPagerNextTitle:\"下一页\",ngPagerPrevTitle:\"上一页\",ngPagerLastTitle:\"前往尾页\"},e.ngGrid.i18n[\"zh-tw\"]={ngAggregateLabel:\"筆\",ngGroupPanelDescription:\"拖拉表頭到此處以進行分組\",ngSearchPlaceHolder:\"搜尋...\",ngMenuText:\"選擇欄位：\",ngShowingItemsLabel:\"目前顯示筆數：\",ngTotalItemsLabel:\"總筆數：\",ngSelectedItemsLabel:\"選取筆數：\",ngPageSizeLabel:\"每頁顯示：\",ngPagerFirstTitle:\"第一頁\",ngPagerNextTitle:\"下一頁\",ngPagerPrevTitle:\"上一頁\",ngPagerLastTitle:\"最後頁\"},angular.module(\"ngGrid\").run([\"$templateCache\",function(e){e.put(\"aggregateTemplate.html\",'<div ng-click=\"row.toggleExpand()\" ng-style=\"rowStyle(row)\" class=\"ngAggregate\">    <span class=\"ngAggregateText\">{{row.label CUSTOM_FILTERS}} ({{row.totalChildren()}} {{AggItemsLabel}})</span>    <div class=\"{{row.aggClass()}}\"></div></div>'),e.put(\"cellEditTemplate.html\",'<div ng-cell-has-focus ng-dblclick=\"editCell()\">\t<div ng-edit-cell-if=\"!isFocused\">\t\t\tDISPLAY_CELL_TEMPLATE\t</div>\t<div ng-edit-cell-if=\"isFocused\">\t\tEDITABLE_CELL_TEMPLATE\t</div></div>'),e.put(\"cellTemplate.html\",'<div class=\"ngCellText\" ng-class=\"col.colIndex()\"><span ng-cell-text>{{COL_FIELD CUSTOM_FILTERS}}</span></div>'),e.put(\"checkboxCellTemplate.html\",'<div class=\"ngSelectionCell\"><input tabindex=\"-1\" class=\"ngSelectionCheckbox\" type=\"checkbox\" ng-checked=\"row.selected\" /></div>'),e.put(\"checkboxHeaderTemplate.html\",'<input class=\"ngSelectionHeader\" type=\"checkbox\" ng-show=\"multiSelect\" ng-model=\"allSelected\" ng-change=\"toggleSelectAll(allSelected, true)\"/>'),e.put(\"editableCellTemplate.html\",'<input ng-class=\"\\'colt\\' + col.index\" ng-input=\"COL_FIELD\" ng-model=\"COL_FIELD\" />'),e.put(\"footerTemplate.html\",'<div ng-show=\"showFooter\" class=\"ngFooterPanel\" ng-class=\"{\\'ui-widget-content\\': jqueryUITheme, \\'ui-corner-bottom\\': jqueryUITheme}\" ng-style=\"footerStyle()\">    <div class=\"ngTotalSelectContainer\" >        <div class=\"ngFooterTotalItems\" ng-class=\"{\\'ngNoMultiSelect\\': !multiSelect}\" >            <span class=\"ngLabel\">{{i18n.ngTotalItemsLabel}} {{maxRows()}}</span><span ng-show=\"filterText.length > 0\" class=\"ngLabel\">({{i18n.ngShowingItemsLabel}} {{totalFilteredItemsLength()}})</span>        </div>        <div class=\"ngFooterSelectedItems\" ng-show=\"multiSelect\">            <span class=\"ngLabel\">{{i18n.ngSelectedItemsLabel}} {{selectedItems.length}}</span>        </div>    </div>    <div class=\"ngPagerContainer\" style=\"float: right; margin-top: 10px;\" ng-show=\"enablePaging\" ng-class=\"{\\'ngNoMultiSelect\\': !multiSelect}\">        <div style=\"float:left; margin-right: 10px;\" class=\"ngRowCountPicker\">            <span style=\"float: left; margin-top: 3px;\" class=\"ngLabel\">{{i18n.ngPageSizeLabel}}</span>            <select style=\"float: left;height: 27px; width: 100px\" ng-model=\"pagingOptions.pageSize\" >                <option ng-repeat=\"size in pagingOptions.pageSizes\">{{size}}</option>            </select>        </div>        <div style=\"float:left; margin-right: 10px; line-height:25px;\" class=\"ngPagerControl\" style=\"float: left; min-width: 135px;\">            <button class=\"ngPagerButton\" ng-click=\"pageToFirst()\" ng-disabled=\"cantPageBackward()\" title=\"{{i18n.ngPagerFirstTitle}}\"><div class=\"ngPagerFirstTriangle\"><div class=\"ngPagerFirstBar\"></div></div></button>            <button class=\"ngPagerButton\" ng-click=\"pageBackward()\" ng-disabled=\"cantPageBackward()\" title=\"{{i18n.ngPagerPrevTitle}}\"><div class=\"ngPagerFirstTriangle ngPagerPrevTriangle\"></div></button>            <input class=\"ngPagerCurrent\" min=\"1\" max=\"{{maxPages()}}\" type=\"number\" style=\"width:50px; height: 24px; margin-top: 1px; padding: 0 4px;\" ng-model=\"pagingOptions.currentPage\"/>            <button class=\"ngPagerButton\" ng-click=\"pageForward()\" ng-disabled=\"cantPageForward()\" title=\"{{i18n.ngPagerNextTitle}}\"><div class=\"ngPagerLastTriangle ngPagerNextTriangle\"></div></button>            <button class=\"ngPagerButton\" ng-click=\"pageToLast()\" ng-disabled=\"cantPageToLast()\" title=\"{{i18n.ngPagerLastTitle}}\"><div class=\"ngPagerLastTriangle\"><div class=\"ngPagerLastBar\"></div></div></button>        </div>    </div></div>'),e.put(\"gridTemplate.html\",'<div class=\"ngTopPanel\" ng-class=\"{\\'ui-widget-header\\':jqueryUITheme, \\'ui-corner-top\\': jqueryUITheme}\" ng-style=\"topPanelStyle()\">    <div class=\"ngGroupPanel\" ng-show=\"showGroupPanel()\" ng-style=\"groupPanelStyle()\">        <div class=\"ngGroupPanelDescription\" ng-show=\"configGroups.length == 0\">{{i18n.ngGroupPanelDescription}}</div>        <ul ng-show=\"configGroups.length > 0\" class=\"ngGroupList\">            <li class=\"ngGroupItem\" ng-repeat=\"group in configGroups\">                <span class=\"ngGroupElement\">                    <span class=\"ngGroupName\">{{group.displayName}}                        <span ng-click=\"removeGroup($index)\" class=\"ngRemoveGroup\">x</span>                    </span>                    <span ng-hide=\"$last\" class=\"ngGroupArrow\"></span>                </span>            </li>        </ul>    </div>    <div class=\"ngHeaderContainer\" ng-style=\"headerStyle()\">        <div class=\"ngHeaderScroller\" ng-style=\"headerScrollerStyle()\" ng-include=\"gridId + \\'headerRowTemplate.html\\'\"></div>    </div>    <div ng-grid-menu></div></div><div class=\"ngViewport\" unselectable=\"on\" ng-viewport ng-class=\"{\\'ui-widget-content\\': jqueryUITheme}\" ng-style=\"viewportStyle()\">    <div class=\"ngCanvas\" ng-style=\"canvasStyle()\">        <div ng-style=\"rowStyle(row)\" ng-repeat=\"row in renderedRows\" ng-click=\"row.toggleSelected($event)\" ng-class=\"row.alternatingRowClass()\" ng-row></div>    </div></div><div ng-grid-footer></div>'),e.put(\"headerCellTemplate.html\",'<div class=\"ngHeaderSortColumn {{col.headerClass}}\" ng-style=\"{\\'cursor\\': col.cursor}\" ng-class=\"{ \\'ngSorted\\': !noSortVisible }\">    <div ng-click=\"col.sort($event)\" ng-class=\"\\'colt\\' + col.index\" class=\"ngHeaderText\">{{col.displayName}}</div>    <div class=\"ngSortButtonDown\" ng-show=\"col.showSortButtonDown()\"></div>    <div class=\"ngSortButtonUp\" ng-show=\"col.showSortButtonUp()\"></div>    <div class=\"ngSortPriority\">{{col.sortPriority}}</div>    <div ng-class=\"{ ngPinnedIcon: col.pinned, ngUnPinnedIcon: !col.pinned }\" ng-click=\"togglePin(col)\" ng-show=\"col.pinnable\"></div></div><div ng-show=\"col.resizable\" class=\"ngHeaderGrip\" ng-click=\"col.gripClick($event)\" ng-mousedown=\"col.gripOnMouseDown($event)\"></div>'),e.put(\"headerRowTemplate.html\",'<div ng-style=\"{ height: col.headerRowHeight }\" ng-repeat=\"col in renderedColumns\" ng-class=\"col.colIndex()\" class=\"ngHeaderCell\">\t<div class=\"ngVerticalBar\" ng-style=\"{height: col.headerRowHeight}\" ng-class=\"{ ngVerticalBarVisible: !$last }\">&nbsp;</div>\t<div ng-header-cell></div></div>'),e.put(\"menuTemplate.html\",'<div ng-show=\"showColumnMenu || showFilter\"  class=\"ngHeaderButton\" ng-click=\"toggleShowMenu()\">    <div class=\"ngHeaderButtonArrow\"></div></div><div ng-show=\"showMenu\" class=\"ngColMenu\">    <div ng-show=\"showFilter\">        <input placeholder=\"{{i18n.ngSearchPlaceHolder}}\" type=\"text\" ng-model=\"filterText\"/>    </div>    <div ng-show=\"showColumnMenu\">        <span class=\"ngMenuText\">{{i18n.ngMenuText}}</span>        <ul class=\"ngColList\">            <li class=\"ngColListItem\" ng-repeat=\"col in columns | ngColumns\">                <label><input ng-disabled=\"col.pinned\" type=\"checkbox\" class=\"ngColListCheckbox\" ng-model=\"col.visible\"/>{{col.displayName}}</label>\t\t\t\t<a title=\"Group By\" ng-class=\"col.groupedByClass()\" ng-show=\"col.groupable && col.visible\" ng-click=\"groupBy(col)\"></a>\t\t\t\t<span class=\"ngGroupingNumber\" ng-show=\"col.groupIndex > 0\">{{col.groupIndex}}</span>                      </li>        </ul>    </div></div>'),e.put(\"rowTemplate.html\",'<div ng-style=\"{ \\'cursor\\': row.cursor }\" ng-repeat=\"col in renderedColumns\" ng-class=\"col.colIndex()\" class=\"ngCell {{col.cellClass}}\">\t<div class=\"ngVerticalBar\" ng-style=\"{height: rowHeight}\" ng-class=\"{ ngVerticalBarVisible: !$last }\">&nbsp;</div>\t<div ng-cell></div></div>')}])})(window,jQuery);"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/path_parser.js",
    "content": "/*****\n*\n*   The contents of this file were written by Kevin Lindsey\n*   copyright 2002-2003 Kevin Lindsey\n*\n*   This file was compacted by jscompact\n*   A Perl utility written by Kevin Lindsey (kevin@kevlindev.com)\n*\n*****/\n\nSvg.VERSION=1.0;\nSvg.NAMESPACE=\"http://www.w3.org/2000/svg\";\nfunction Svg(){}\nPathParser.PARAMCOUNT={A:7,C:6,H:1,L:2,M:2,Q:4,S:4,T:2,V:1,Z:0};\nPathParser.METHODNAME={A:\"arcAbs\",a:\"arcRel\",C:\"curvetoCubicAbs\",c:\"curvetoCubicRel\",H:\"linetoHorizontalAbs\",h:\"linetoHorizontalRel\",L:\"linetoAbs\",l:\"linetoRel\",M:\"movetoAbs\",m:\"movetoRel\",Q:\"curvetoQuadraticAbs\",q:\"curvetoQuadraticRel\",S:\"curvetoCubicSmoothAbs\",s:\"curvetoCubicSmoothRel\",T:\"curvetoQuadraticSmoothAbs\",t:\"curvetoQuadraticSmoothRel\",V:\"linetoVerticalAbs\",v:\"linetoVerticalRel\",Z:\"closePath\",z:\"closePath\"}\nfunction PathParser(){this._lexer=new PathLexer();this._handler=null;}\nPathParser.prototype.parsePath=function(path){if(path==null||path.namespaceURI!=Svg.NAMESPACE||path.localName!=\"path\")throw new Error(\"PathParser.parsePath: The first parameter must be an SVG path element\");this.parseData(path.getAttributeNS(null,\"d\"));};\nPathParser.prototype.parseData=function(pathData){if(typeof(pathData)!=\"string\")throw new Error(\"PathParser.parseData: The first parameter must be a string\");if(this._handler!=null&&this._handler.beginParse!=null)this._handler.beginParse();var lexer=this._lexer;lexer.setPathData(pathData);var mode=\"BOP\";var token=lexer.getNextToken();while(!token.typeis(PathToken.EOD)){var param_count;var params=new Array();switch(token.type){case PathToken.COMMAND:if(mode==\"BOP\"&&token.text!=\"M\"&&token.text!=\"m\")throw new Error(\"PathParser.parseData: a path must begin with a moveto command\");mode=token.text;param_count=PathParser.PARAMCOUNT[token.text.toUpperCase()];token=lexer.getNextToken();break;case PathToken.NUMBER:break;default:throw new Error(\"PathParser.parseData: unrecognized token type: \"+token.type);}for(var i=0;i<param_count;i++){switch(token.type){case PathToken.COMMAND:throw new Error(\"PathParser.parseData: parameter must be a number: \"+token.text);case PathToken.NUMBER:params[i]=token.text-0;break;default:throw new Errot(\"PathParser.parseData: unrecognized token type: \"+token.type);}token=lexer.getNextToken();}if(this._handler!=null){var handler=this._handler;var method=PathParser.METHODNAME[mode];if(handler[method]!=null)handler[method].apply(handler,params);}if(mode==\"M\")mode=\"L\";if(mode==\"m\")mode=\"l\";}};\nPathParser.prototype.setHandler=function(handler){this._handler=handler;};\nPathLexer.VERSION=1.0;\nfunction PathLexer(pathData){if(pathData==null)pathData=\"\";this.setPathData(pathData);}\nPathLexer.prototype.setPathData=function(pathData){if(typeof(pathData)!=\"string\")throw new Error(\"PathLexer.setPathData: The first parameter must be a string\");this._pathData=pathData;};\nPathLexer.prototype.getNextToken=function(){var result=null;var d=this._pathData;while(result==null){if(d==null||d==\"\"){result=new PathToken(PathToken.EOD,\"\");}else if(d.match(/^([ \\t\\r\\n,]+)/)){d=d.substr(RegExp.$1.length);}else if(d.match(/^([AaCcHhLlMmQqSsTtVvZz])/)){result=new PathToken(PathToken.COMMAND,RegExp.$1);d=d.substr(RegExp.$1.length);}else if(d.match(/^(([-+]?[0-9]+(\\.[0-9]*)?|[-+]?\\.[0-9]+)([eE][-+]?[0-9]+)?)/)){result=new PathToken(PathToken.NUMBER,parseFloat(RegExp.$1));d=d.substr(RegExp.$1.length);}else{throw new Error(\"PathLexer.getNextToken: unrecognized path data \"+d);}}this._pathData=d;return result;};\nPathToken.UNDEFINED=0;\nPathToken.COMMAND=1;\nPathToken.NUMBER=2;\nPathToken.EOD=3;\nfunction PathToken(type,text){if(arguments.length>0){this.init(type,text);}}\nPathToken.prototype.init=function(type,text){this.type=type;this.text=text;};\nPathToken.prototype.typeis=function(type){return this.type==type;}"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/prototype-1.5.1.js",
    "content": "/*  Prototype JavaScript framework, version 1.5.1\n *  (c) 2005-2007 Sam Stephenson\n *\n *  Prototype is freely distributable under the terms of an MIT-style license.\n *  For details, see the Prototype web site: http://www.prototypejs.org/\n *\n/*--------------------------------------------------------------------------*/\n\nvar Prototype = {\n  Version: '1.5.1',\n\n  Browser: {\n    IE:     !!(window.attachEvent && !window.opera),\n    Opera:  !!window.opera,\n    WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,\n    Gecko:  navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1\n  },\n\n  BrowserFeatures: {\n    XPath: !!document.evaluate,\n    ElementExtensions: !!window.HTMLElement,\n    SpecificElementExtensions:\n      (document.createElement('div').__proto__ !==\n       document.createElement('form').__proto__)\n  },\n\n  ScriptFragment: '<script[^>]*>([\\u0001-\\uFFFF]*?)</script>',\n  JSONFilter: /^\\/\\*-secure-\\s*(.*)\\s*\\*\\/\\s*$/,\n\n  emptyFunction: function() { },\n  K: function(x) { return x }\n}\n\nvar Class = {\n  create: function() {\n    return function() {\n      this.initialize.apply(this, arguments);\n    }\n  }\n}\n\nvar Abstract = new Object();\n\nObject.extend = function(destination, source) {\n  for (var property in source) {\n    destination[property] = source[property];\n  }\n  return destination;\n}\n\nObject.extend(Object, {\n  inspect: function(object) {\n    try {\n      if (object === undefined) return 'undefined';\n      if (object === null) return 'null';\n      return object.inspect ? object.inspect() : object.toString();\n    } catch (e) {\n      if (e instanceof RangeError) return '...';\n      throw e;\n    }\n  },\n\n  toJSON: function(object) {\n    var type = typeof object;\n    switch(type) {\n      case 'undefined':\n      case 'function':\n      case 'unknown': return;\n      case 'boolean': return object.toString();\n    }\n    if (object === null) return 'null';\n    if (object.toJSON) return object.toJSON();\n    if (object.ownerDocument === document) return;\n    var results = [];\n    for (var property in object) {\n      var value = Object.toJSON(object[property]);\n      if (value !== undefined)\n        results.push(property.toJSON() + ': ' + value);\n    }\n    return '{' + results.join(', ') + '}';\n  },\n\n  keys: function(object) {\n    var keys = [];\n    for (var property in object)\n      keys.push(property);\n    return keys;\n  },\n\n  values: function(object) {\n    var values = [];\n    for (var property in object)\n      values.push(object[property]);\n    return values;\n  },\n\n  clone: function(object) {\n    return Object.extend({}, object);\n  }\n});\n\nFunction.prototype.bind = function() {\n  var __method = this, args = $A(arguments), object = args.shift();\n  return function() {\n    return __method.apply(object, args.concat($A(arguments)));\n  }\n}\n\nFunction.prototype.bindAsEventListener = function(object) {\n  var __method = this, args = $A(arguments), object = args.shift();\n  return function(event) {\n    return __method.apply(object, [event || window.event].concat(args));\n  }\n}\n\nObject.extend(Number.prototype, {\n  toColorPart: function() {\n    return this.toPaddedString(2, 16);\n  },\n\n  succ: function() {\n    return this + 1;\n  },\n\n  times: function(iterator) {\n    $R(0, this, true).each(iterator);\n    return this;\n  },\n\n  toPaddedString: function(length, radix) {\n    var string = this.toString(radix || 10);\n    return '0'.times(length - string.length) + string;\n  },\n\n  toJSON: function() {\n    return isFinite(this) ? this.toString() : 'null';\n  }\n});\n\nDate.prototype.toJSON = function() {\n  return '\"' + this.getFullYear() + '-' +\n    (this.getMonth() + 1).toPaddedString(2) + '-' +\n    this.getDate().toPaddedString(2) + 'T' +\n    this.getHours().toPaddedString(2) + ':' +\n    this.getMinutes().toPaddedString(2) + ':' +\n    this.getSeconds().toPaddedString(2) + '\"';\n};\n\nvar Try = {\n  these: function() {\n    var returnValue;\n\n    for (var i = 0, length = arguments.length; i < length; i++) {\n      var lambda = arguments[i];\n      try {\n        returnValue = lambda();\n        break;\n      } catch (e) {}\n    }\n\n    return returnValue;\n  }\n}\n\n/*--------------------------------------------------------------------------*/\n\nvar PeriodicalExecuter = Class.create();\nPeriodicalExecuter.prototype = {\n  initialize: function(callback, frequency) {\n    this.callback = callback;\n    this.frequency = frequency;\n    this.currentlyExecuting = false;\n\n    this.registerCallback();\n  },\n\n  registerCallback: function() {\n    this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);\n  },\n\n  stop: function() {\n    if (!this.timer) return;\n    clearInterval(this.timer);\n    this.timer = null;\n  },\n\n  onTimerEvent: function() {\n    if (!this.currentlyExecuting) {\n      try {\n        this.currentlyExecuting = true;\n        this.callback(this);\n      } finally {\n        this.currentlyExecuting = false;\n      }\n    }\n  }\n}\nObject.extend(String, {\n  interpret: function(value) {\n    return value == null ? '' : String(value);\n  },\n  specialChar: {\n    '\\b': '\\\\b',\n    '\\t': '\\\\t',\n    '\\n': '\\\\n',\n    '\\f': '\\\\f',\n    '\\r': '\\\\r',\n    '\\\\': '\\\\\\\\'\n  }\n});\n\nObject.extend(String.prototype, {\n  gsub: function(pattern, replacement) {\n    var result = '', source = this, match;\n    replacement = arguments.callee.prepareReplacement(replacement);\n\n    while (source.length > 0) {\n      if (match = source.match(pattern)) {\n        result += source.slice(0, match.index);\n        result += String.interpret(replacement(match));\n        source  = source.slice(match.index + match[0].length);\n      } else {\n        result += source, source = '';\n      }\n    }\n    return result;\n  },\n\n  sub: function(pattern, replacement, count) {\n    replacement = this.gsub.prepareReplacement(replacement);\n    count = count === undefined ? 1 : count;\n\n    return this.gsub(pattern, function(match) {\n      if (--count < 0) return match[0];\n      return replacement(match);\n    });\n  },\n\n  scan: function(pattern, iterator) {\n    this.gsub(pattern, iterator);\n    return this;\n  },\n\n  truncate: function(length, truncation) {\n    length = length || 30;\n    truncation = truncation === undefined ? '...' : truncation;\n    return this.length > length ?\n      this.slice(0, length - truncation.length) + truncation : this;\n  },\n\n  strip: function() {\n    return this.replace(/^\\s+/, '').replace(/\\s+$/, '');\n  },\n\n  stripTags: function() {\n    return this.replace(/<\\/?[^>]+>/gi, '');\n  },\n\n  stripScripts: function() {\n    return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');\n  },\n\n  extractScripts: function() {\n    var matchAll = new RegExp(Prototype.ScriptFragment, 'img');\n    var matchOne = new RegExp(Prototype.ScriptFragment, 'im');\n    return (this.match(matchAll) || []).map(function(scriptTag) {\n      return (scriptTag.match(matchOne) || ['', ''])[1];\n    });\n  },\n\n  evalScripts: function() {\n    return this.extractScripts().map(function(script) { return eval(script) });\n  },\n\n  escapeHTML: function() {\n    var self = arguments.callee;\n    self.text.data = this;\n    return self.div.innerHTML;\n  },\n\n  unescapeHTML: function() {\n    var div = document.createElement('div');\n    div.innerHTML = this.stripTags();\n    return div.childNodes[0] ? (div.childNodes.length > 1 ?\n      $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :\n      div.childNodes[0].nodeValue) : '';\n  },\n\n  toQueryParams: function(separator) {\n    var match = this.strip().match(/([^?#]*)(#.*)?$/);\n    if (!match) return {};\n\n    return match[1].split(separator || '&').inject({}, function(hash, pair) {\n      if ((pair = pair.split('='))[0]) {\n        var key = decodeURIComponent(pair.shift());\n        var value = pair.length > 1 ? pair.join('=') : pair[0];\n        if (value != undefined) value = decodeURIComponent(value);\n\n        if (key in hash) {\n          if (hash[key].constructor != Array) hash[key] = [hash[key]];\n          hash[key].push(value);\n        }\n        else hash[key] = value;\n      }\n      return hash;\n    });\n  },\n\n  toArray: function() {\n    return this.split('');\n  },\n\n  succ: function() {\n    return this.slice(0, this.length - 1) +\n      String.fromCharCode(this.charCodeAt(this.length - 1) + 1);\n  },\n\n  times: function(count) {\n    var result = '';\n    for (var i = 0; i < count; i++) result += this;\n    return result;\n  },\n\n  camelize: function() {\n    var parts = this.split('-'), len = parts.length;\n    if (len == 1) return parts[0];\n\n    var camelized = this.charAt(0) == '-'\n      ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)\n      : parts[0];\n\n    for (var i = 1; i < len; i++)\n      camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);\n\n    return camelized;\n  },\n\n  capitalize: function() {\n    return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();\n  },\n\n  underscore: function() {\n    return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();\n  },\n\n  dasherize: function() {\n    return this.gsub(/_/,'-');\n  },\n\n  inspect: function(useDoubleQuotes) {\n    var escapedString = this.gsub(/[\\x00-\\x1f\\\\]/, function(match) {\n      var character = String.specialChar[match[0]];\n      return character ? character : '\\\\u00' + match[0].charCodeAt().toPaddedString(2, 16);\n    });\n    if (useDoubleQuotes) return '\"' + escapedString.replace(/\"/g, '\\\\\"') + '\"';\n    return \"'\" + escapedString.replace(/'/g, '\\\\\\'') + \"'\";\n  },\n\n  toJSON: function() {\n    return this.inspect(true);\n  },\n\n  unfilterJSON: function(filter) {\n    return this.sub(filter || Prototype.JSONFilter, '#{1}');\n  },\n\n  evalJSON: function(sanitize) {\n    var json = this.unfilterJSON();\n    try {\n      if (!sanitize || (/^(\"(\\\\.|[^\"\\\\\\n\\r])*?\"|[,:{}\\[\\]0-9.\\-+Eaeflnr-u \\n\\r\\t])+?$/.test(json)))\n        return eval('(' + json + ')');\n    } catch (e) { }\n    throw new SyntaxError('Badly formed JSON string: ' + this.inspect());\n  },\n\n  include: function(pattern) {\n    return this.indexOf(pattern) > -1;\n  },\n\n  startsWith: function(pattern) {\n    return this.indexOf(pattern) === 0;\n  },\n\n  endsWith: function(pattern) {\n    var d = this.length - pattern.length;\n    return d >= 0 && this.lastIndexOf(pattern) === d;\n  },\n\n  empty: function() {\n    return this == '';\n  },\n\n  blank: function() {\n    return /^\\s*$/.test(this);\n  }\n});\n\nif (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {\n  escapeHTML: function() {\n    return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');\n  },\n  unescapeHTML: function() {\n    return this.replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>');\n  }\n});\n\nString.prototype.gsub.prepareReplacement = function(replacement) {\n  if (typeof replacement == 'function') return replacement;\n  var template = new Template(replacement);\n  return function(match) { return template.evaluate(match) };\n}\n\nString.prototype.parseQuery = String.prototype.toQueryParams;\n\nObject.extend(String.prototype.escapeHTML, {\n  div:  document.createElement('div'),\n  text: document.createTextNode('')\n});\n\nwith (String.prototype.escapeHTML) div.appendChild(text);\n\nvar Template = Class.create();\nTemplate.Pattern = /(^|.|\\r|\\n)(#\\{(.*?)\\})/;\nTemplate.prototype = {\n  initialize: function(template, pattern) {\n    this.template = template.toString();\n    this.pattern  = pattern || Template.Pattern;\n  },\n\n  evaluate: function(object) {\n    return this.template.gsub(this.pattern, function(match) {\n      var before = match[1];\n      if (before == '\\\\') return match[2];\n      return before + String.interpret(object[match[3]]);\n    });\n  }\n}\n\nvar $break = {}, $continue = new Error('\"throw $continue\" is deprecated, use \"return\" instead');\n\nvar Enumerable = {\n  each: function(iterator) {\n    var index = 0;\n    try {\n      this._each(function(value) {\n        iterator(value, index++);\n      });\n    } catch (e) {\n      if (e != $break) \n    \t  throw e;\n    }\n    return this;\n  },\n\n  eachSlice: function(number, iterator) {\n    var index = -number, slices = [], array = this.toArray();\n    while ((index += number) < array.length)\n      slices.push(array.slice(index, index+number));\n    return slices.map(iterator);\n  },\n\n  all: function(iterator) {\n    var result = true;\n    this.each(function(value, index) {\n      result = result && !!(iterator || Prototype.K)(value, index);\n      if (!result) throw $break;\n    });\n    return result;\n  },\n\n  any: function(iterator) {\n    var result = false;\n    this.each(function(value, index) {\n      if (result = !!(iterator || Prototype.K)(value, index))\n        throw $break;\n    });\n    return result;\n  },\n\n  collect: function(iterator) {\n    var results = [];\n    this.each(function(value, index) {\n      results.push((iterator || Prototype.K)(value, index));\n    });\n    return results;\n  },\n\n  detect: function(iterator) {\n    var result;\n    this.each(function(value, index) {\n      if (iterator(value, index)) {\n        result = value;\n        throw $break;\n      }\n    });\n    return result;\n  },\n\n  findAll: function(iterator) {\n    var results = [];\n    this.each(function(value, index) {\n      if (iterator(value, index))\n        results.push(value);\n    });\n    return results;\n  },\n\n  grep: function(pattern, iterator) {\n    var results = [];\n    this.each(function(value, index) {\n      var stringValue = value.toString();\n      if (stringValue.match(pattern))\n        results.push((iterator || Prototype.K)(value, index));\n    })\n    return results;\n  },\n\n  include: function(object) {\n    var found = false;\n    this.each(function(value) {\n      if (value == object) {\n        found = true;\n        throw $break;\n      }\n    });\n    return found;\n  },\n\n  inGroupsOf: function(number, fillWith) {\n    fillWith = fillWith === undefined ? null : fillWith;\n    return this.eachSlice(number, function(slice) {\n      while(slice.length < number) slice.push(fillWith);\n      return slice;\n    });\n  },\n\n  inject: function(memo, iterator) {\n    this.each(function(value, index) {\n      memo = iterator(memo, value, index);\n    });\n    return memo;\n  },\n\n  invoke: function(method) {\n    var args = $A(arguments).slice(1);\n    return this.map(function(value) {\n      return value[method].apply(value, args);\n    });\n  },\n\n  max: function(iterator) {\n    var result;\n    this.each(function(value, index) {\n      value = (iterator || Prototype.K)(value, index);\n      if (result == undefined || value >= result)\n        result = value;\n    });\n    return result;\n  },\n\n  min: function(iterator) {\n    var result;\n    this.each(function(value, index) {\n      value = (iterator || Prototype.K)(value, index);\n      if (result == undefined || value < result)\n        result = value;\n    });\n    return result;\n  },\n\n  partition: function(iterator) {\n    var trues = [], falses = [];\n    this.each(function(value, index) {\n      ((iterator || Prototype.K)(value, index) ?\n        trues : falses).push(value);\n    });\n    return [trues, falses];\n  },\n\n  pluck: function(property) {\n    var results = [];\n    this.each(function(value, index) {\n      results.push(value[property]);\n    });\n    return results;\n  },\n\n  reject: function(iterator) {\n    var results = [];\n    this.each(function(value, index) {\n      if (!iterator(value, index))\n        results.push(value);\n    });\n    return results;\n  },\n\n  sortBy: function(iterator) {\n    return this.map(function(value, index) {\n      return {value: value, criteria: iterator(value, index)};\n    }).sort(function(left, right) {\n      var a = left.criteria, b = right.criteria;\n      return a < b ? -1 : a > b ? 1 : 0;\n    }).pluck('value');\n  },\n\n  toArray: function() {\n    return this.map();\n  },\n\n  zip: function() {\n    var iterator = Prototype.K, args = $A(arguments);\n    if (typeof args.last() == 'function')\n      iterator = args.pop();\n\n    var collections = [this].concat(args).map($A);\n    return this.map(function(value, index) {\n      return iterator(collections.pluck(index));\n    });\n  },\n\n  size: function() {\n    return this.toArray().length;\n  },\n\n  inspect: function() {\n    return '#<Enumerable:' + this.toArray().inspect() + '>';\n  }\n}\n\nObject.extend(Enumerable, {\n  map:     Enumerable.collect,\n  find:    Enumerable.detect,\n  select:  Enumerable.findAll,\n  member:  Enumerable.include,\n  entries: Enumerable.toArray\n});\nvar $A = Array.from = function(iterable) {\n  if (!iterable) return [];\n  if (iterable.toArray) {\n    return iterable.toArray();\n  } else {\n    var results = [];\n    for (var i = 0, length = iterable.length; i < length; i++)\n      results.push(iterable[i]);\n    return results;\n  }\n}\n\nif (Prototype.Browser.WebKit) {\n  $A = Array.from = function(iterable) {\n    if (!iterable) return [];\n    if (!(typeof iterable == 'function' && iterable == '[object NodeList]') &&\n      iterable.toArray) {\n      return iterable.toArray();\n    } else {\n      var results = [];\n      for (var i = 0, length = iterable.length; i < length; i++)\n        results.push(iterable[i]);\n      return results;\n    }\n  }\n}\n\nObject.extend(Array.prototype, Enumerable);\n\nif (!Array.prototype._reverse)\n  Array.prototype._reverse = Array.prototype.reverse;\n\nObject.extend(Array.prototype, {\n  _each: function(iterator) {\n    for (var i = 0, length = this.length; i < length; i++)\n      iterator(this[i]);\n  },\n\n  clear: function() {\n    this.length = 0;\n    return this;\n  },\n\n  first: function() {\n    return this[0];\n  },\n\n  last: function() {\n    return this[this.length - 1];\n  },\n\n  compact: function() {\n    return this.select(function(value) {\n      return value != null;\n    });\n  },\n\n  flatten: function() {\n    return this.inject([], function(array, value) {\n      return array.concat(value && value.constructor == Array ?\n        value.flatten() : [value]);\n    });\n  },\n\n  without: function() {\n    var values = $A(arguments);\n    return this.select(function(value) {\n      return !values.include(value);\n    });\n  },\n\n  indexOf: function(object) {\n    for (var i = 0, length = this.length; i < length; i++)\n      if (this[i] == object) return i;\n    return -1;\n  },\n\n  reverse: function(inline) {\n    return (inline !== false ? this : this.toArray())._reverse();\n  },\n\n  reduce: function() {\n    return this.length > 1 ? this : this[0];\n  },\n\n  uniq: function(sorted) {\n    return this.inject([], function(array, value, index) {\n      if (0 == index || (sorted ? array.last() != value : !array.include(value)))\n        array.push(value);\n      return array;\n    });\n  },\n\n  clone: function() {\n    return [].concat(this);\n  },\n\n  size: function() {\n    return this.length;\n  },\n\n  inspect: function() {\n    return '[' + this.map(Object.inspect).join(', ') + ']';\n  },\n\n  toJSON: function() {\n    var results = [];\n    this.each(function(object) {\n      var value = Object.toJSON(object);\n      if (value !== undefined) results.push(value);\n    });\n    return '[' + results.join(', ') + ']';\n  }\n});\n\nArray.prototype.toArray = Array.prototype.clone;\n\nfunction $w(string) {\n  string = string.strip();\n  return string ? string.split(/\\s+/) : [];\n}\n\nif (Prototype.Browser.Opera){\n  Array.prototype.concat = function() {\n    var array = [];\n    for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);\n    for (var i = 0, length = arguments.length; i < length; i++) {\n      if (arguments[i].constructor == Array) {\n        for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)\n          array.push(arguments[i][j]);\n      } else {\n        array.push(arguments[i]);\n      }\n    }\n    return array;\n  }\n}\nvar Hash = function(object) {\n  if (object instanceof Hash) this.merge(object);\n  else Object.extend(this, object || {});\n};\n\nObject.extend(Hash, {\n  toQueryString: function(obj) {\n    var parts = [];\n    parts.add = arguments.callee.addPair;\n\n    this.prototype._each.call(obj, function(pair) {\n      if (!pair.key) return;\n      var value = pair.value;\n\n      if (value && typeof value == 'object') {\n        if (value.constructor == Array) value.each(function(value) {\n          parts.add(pair.key, value);\n        });\n        return;\n      }\n      parts.add(pair.key, value);\n    });\n\n    return parts.join('&');\n  },\n\n  toJSON: function(object) {\n    var results = [];\n    this.prototype._each.call(object, function(pair) {\n      var value = Object.toJSON(pair.value);\n      if (value !== undefined) results.push(pair.key.toJSON() + ': ' + value);\n    });\n    return '{' + results.join(', ') + '}';\n  }\n});\n\nHash.toQueryString.addPair = function(key, value, prefix) {\n  key = encodeURIComponent(key);\n  if (value === undefined) this.push(key);\n  else this.push(key + '=' + (value == null ? '' : encodeURIComponent(value)));\n}\n\nObject.extend(Hash.prototype, Enumerable);\nObject.extend(Hash.prototype, {\n  _each: function(iterator) {\n    for (var key in this) {\n      var value = this[key];\n      if (value && value == Hash.prototype[key]) continue;\n\n      var pair = [key, value];\n      pair.key = key;\n      pair.value = value;\n      iterator(pair);\n    }\n  },\n\n  keys: function() {\n    return this.pluck('key');\n  },\n\n  values: function() {\n    return this.pluck('value');\n  },\n\n  merge: function(hash) {\n    return $H(hash).inject(this, function(mergedHash, pair) {\n      mergedHash[pair.key] = pair.value;\n      return mergedHash;\n    });\n  },\n\n  remove: function() {\n    var result;\n    for(var i = 0, length = arguments.length; i < length; i++) {\n      var value = this[arguments[i]];\n      if (value !== undefined){\n        if (result === undefined) result = value;\n        else {\n          if (result.constructor != Array) result = [result];\n          result.push(value)\n        }\n      }\n      delete this[arguments[i]];\n    }\n    return result;\n  },\n\n  toQueryString: function() {\n    return Hash.toQueryString(this);\n  },\n\n  inspect: function() {\n    return '#<Hash:{' + this.map(function(pair) {\n      return pair.map(Object.inspect).join(': ');\n    }).join(', ') + '}>';\n  },\n\n  toJSON: function() {\n    return Hash.toJSON(this);\n  }\n});\n\nfunction $H(object) {\n  if (object instanceof Hash) return object;\n  return new Hash(object);\n};\n\n// Safari iterates over shadowed properties\nif (function() {\n  var i = 0, Test = function(value) { this.key = value };\n  Test.prototype.key = 'foo';\n  for (var property in new Test('bar')) i++;\n  return i > 1;\n}()) Hash.prototype._each = function(iterator) {\n  var cache = [];\n  for (var key in this) {\n    var value = this[key];\n    if ((value && value == Hash.prototype[key]) || cache.include(key)) continue;\n    cache.push(key);\n    var pair = [key, value];\n    pair.key = key;\n    pair.value = value;\n    iterator(pair);\n  }\n};\nObjectRange = Class.create();\nObject.extend(ObjectRange.prototype, Enumerable);\nObject.extend(ObjectRange.prototype, {\n  initialize: function(start, end, exclusive) {\n    this.start = start;\n    this.end = end;\n    this.exclusive = exclusive;\n  },\n\n  _each: function(iterator) {\n    var value = this.start;\n    while (this.include(value)) {\n      iterator(value);\n      value = value.succ();\n    }\n  },\n\n  include: function(value) {\n    if (value < this.start)\n      return false;\n    if (this.exclusive)\n      return value < this.end;\n    return value <= this.end;\n  }\n});\n\nvar $R = function(start, end, exclusive) {\n  return new ObjectRange(start, end, exclusive);\n}\n\nvar Ajax = {\n  getTransport: function() {\n    return Try.these(\n      function() {return new XMLHttpRequest()},\n      function() {return new ActiveXObject('Msxml2.XMLHTTP')},\n      function() {return new ActiveXObject('Microsoft.XMLHTTP')}\n    ) || false;\n  },\n\n  activeRequestCount: 0\n}\n\nAjax.Responders = {\n  responders: [],\n\n  _each: function(iterator) {\n    this.responders._each(iterator);\n  },\n\n  register: function(responder) {\n    if (!this.include(responder))\n      this.responders.push(responder);\n  },\n\n  unregister: function(responder) {\n    this.responders = this.responders.without(responder);\n  },\n\n  dispatch: function(callback, request, transport, json) {\n    this.each(function(responder) {\n      if (typeof responder[callback] == 'function') {\n        try {\n          responder[callback].apply(responder, [request, transport, json]);\n        } catch (e) {}\n      }\n    });\n  }\n};\n\nObject.extend(Ajax.Responders, Enumerable);\n\nAjax.Responders.register({\n  onCreate: function() {\n    Ajax.activeRequestCount++;\n  },\n  onComplete: function() {\n    Ajax.activeRequestCount--;\n  }\n});\n\nAjax.Base = function() {};\nAjax.Base.prototype = {\n  setOptions: function(options) {\n    this.options = {\n      method:       'post',\n      asynchronous: true,\n      contentType:  'application/x-www-form-urlencoded',\n      encoding:     'UTF-8',\n      parameters:   ''\n    }\n    Object.extend(this.options, options || {});\n\n    this.options.method = this.options.method.toLowerCase();\n    if (typeof this.options.parameters == 'string')\n      this.options.parameters = this.options.parameters.toQueryParams();\n  }\n}\n\nAjax.Request = Class.create();\nAjax.Request.Events =\n  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];\n\nAjax.Request.prototype = Object.extend(new Ajax.Base(), {\n  _complete: false,\n\n  initialize: function(url, options) {\n    this.transport = Ajax.getTransport();\n    this.setOptions(options);\n    this.request(url);\n  },\n\n  request: function(url) {\n    this.url = url;\n    this.method = this.options.method;\n    var params = Object.clone(this.options.parameters);\n\n    if (!['get', 'post'].include(this.method)) {\n      // simulate other verbs over post\n      params['_method'] = this.method;\n      this.method = 'post';\n    }\n\n    this.parameters = params;\n\n    if (params = Hash.toQueryString(params)) {\n      // when GET, append parameters to URL\n      if (this.method == 'get' || this.options.postBody)\n        this.url += (this.url.include('?') ? '&' : '?') + params;\n      else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))\n        params += '&_=';\n    }\n\n    try {\n      if (this.options.onCreate) this.options.onCreate(this.transport);\n      Ajax.Responders.dispatch('onCreate', this, this.transport);\n\n      this.transport.open(this.method.toUpperCase(), this.url,\n        this.options.asynchronous);\n\n      if (this.options.asynchronous)\n        setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10);\n\n      this.transport.onreadystatechange = this.onStateChange.bind(this);\n      this.setRequestHeaders();\n\n      this.body = this.method == 'post' ? (this.options.postBody || params) : null;\n      this.transport.send(this.body);\n\n      /* Force Firefox to handle ready state 4 for synchronous requests */\n      if (!this.options.asynchronous && this.transport.overrideMimeType)\n        this.onStateChange();\n\n    }\n    catch (e) {\n      this.dispatchException(e);\n    }\n  },\n\n  onStateChange: function() {\n    var readyState = this.transport.readyState;\n    if (readyState > 1 && !((readyState == 4) && this._complete))\n      this.respondToReadyState(this.transport.readyState);\n  },\n\n  setRequestHeaders: function() {\n    var headers = {\n      'X-Requested-With': 'XMLHttpRequest',\n      'X-Prototype-Version': Prototype.Version,\n      'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'\n    };\n\n    if (this.method == 'post') {\n      headers['Content-type'] = this.options.contentType +\n        (this.options.encoding ? '; charset=' + this.options.encoding : '');\n\n      /* Force \"Connection: close\" for older Mozilla browsers to work\n       * around a bug where XMLHttpRequest sends an incorrect\n       * Content-length header. See Mozilla Bugzilla #246651.\n       */\n      if (this.transport.overrideMimeType &&\n          (navigator.userAgent.match(/Gecko\\/(\\d{4})/) || [0,2005])[1] < 2005)\n            headers['Connection'] = 'close';\n    }\n\n    // user-defined headers\n    if (typeof this.options.requestHeaders == 'object') {\n      var extras = this.options.requestHeaders;\n\n      if (typeof extras.push == 'function')\n        for (var i = 0, length = extras.length; i < length; i += 2)\n          headers[extras[i]] = extras[i+1];\n      else\n        $H(extras).each(function(pair) { headers[pair.key] = pair.value });\n    }\n\n    for (var name in headers)\n      this.transport.setRequestHeader(name, headers[name]);\n  },\n\n  success: function() {\n    return !this.transport.status\n        || (this.transport.status >= 200 && this.transport.status < 300);\n  },\n\n  respondToReadyState: function(readyState) {\n    var state = Ajax.Request.Events[readyState];\n    var transport = this.transport, json = this.evalJSON();\n\n    if (state == 'Complete') {\n      try {\n        this._complete = true;\n        (this.options['on' + this.transport.status]\n         || this.options['on' + (this.success() ? 'Success' : 'Failure')]\n         || Prototype.emptyFunction)(transport, json);\n      } catch (e) {\n        this.dispatchException(e);\n      }\n\n      var contentType = this.getHeader('Content-type');\n      if (contentType && contentType.strip().\n        match(/^(text|application)\\/(x-)?(java|ecma)script(;.*)?$/i))\n          this.evalResponse();\n    }\n\n    try {\n      (this.options['on' + state] || Prototype.emptyFunction)(transport, json);\n      Ajax.Responders.dispatch('on' + state, this, transport, json);\n    } catch (e) {\n      this.dispatchException(e);\n    }\n\n    if (state == 'Complete') {\n      // avoid memory leak in MSIE: clean up\n      this.transport.onreadystatechange = Prototype.emptyFunction;\n    }\n  },\n\n  getHeader: function(name) {\n    try {\n      return this.transport.getResponseHeader(name);\n    } catch (e) { return null }\n  },\n\n  evalJSON: function() {\n    try {\n      var json = this.getHeader('X-JSON');\n      return json ? json.evalJSON() : null;\n    } catch (e) { return null }\n  },\n\n  evalResponse: function() {\n    try {\n      return eval((this.transport.responseText || '').unfilterJSON());\n    } catch (e) {\n      this.dispatchException(e);\n    }\n  },\n\n  dispatchException: function(exception) {\n    (this.options.onException || Prototype.emptyFunction)(this, exception);\n    Ajax.Responders.dispatch('onException', this, exception);\n  }\n});\n\nAjax.Updater = Class.create();\n\nObject.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {\n  initialize: function(container, url, options) {\n    this.container = {\n      success: (container.success || container),\n      failure: (container.failure || (container.success ? null : container))\n    }\n\n    this.transport = Ajax.getTransport();\n    this.setOptions(options);\n\n    var onComplete = this.options.onComplete || Prototype.emptyFunction;\n    this.options.onComplete = (function(transport, param) {\n      this.updateContent();\n      onComplete(transport, param);\n    }).bind(this);\n\n    this.request(url);\n  },\n\n  updateContent: function() {\n    var receiver = this.container[this.success() ? 'success' : 'failure'];\n    var response = this.transport.responseText;\n\n    if (!this.options.evalScripts) response = response.stripScripts();\n\n    if (receiver = $(receiver)) {\n      if (this.options.insertion)\n        new this.options.insertion(receiver, response);\n      else\n        receiver.update(response);\n    }\n\n    if (this.success()) {\n      if (this.onComplete)\n        setTimeout(this.onComplete.bind(this), 10);\n    }\n  }\n});\n\nAjax.PeriodicalUpdater = Class.create();\nAjax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {\n  initialize: function(container, url, options) {\n    this.setOptions(options);\n    this.onComplete = this.options.onComplete;\n\n    this.frequency = (this.options.frequency || 2);\n    this.decay = (this.options.decay || 1);\n\n    this.updater = {};\n    this.container = container;\n    this.url = url;\n\n    this.start();\n  },\n\n  start: function() {\n    this.options.onComplete = this.updateComplete.bind(this);\n    this.onTimerEvent();\n  },\n\n  stop: function() {\n    this.updater.options.onComplete = undefined;\n    clearTimeout(this.timer);\n    (this.onComplete || Prototype.emptyFunction).apply(this, arguments);\n  },\n\n  updateComplete: function(request) {\n    if (this.options.decay) {\n      this.decay = (request.responseText == this.lastText ?\n        this.decay * this.options.decay : 1);\n\n      this.lastText = request.responseText;\n    }\n    this.timer = setTimeout(this.onTimerEvent.bind(this),\n      this.decay * this.frequency * 1000);\n  },\n\n  onTimerEvent: function() {\n    this.updater = new Ajax.Updater(this.container, this.url, this.options);\n  }\n});\nfunction $(element) {\n  if (arguments.length > 1) {\n    for (var i = 0, elements = [], length = arguments.length; i < length; i++)\n      elements.push($(arguments[i]));\n    return elements;\n  }\n  if (typeof element == 'string')\n    element = document.getElementById(element);\n  return Element.extend(element);\n}\n\nif (Prototype.BrowserFeatures.XPath) {\n  document._getElementsByXPath = function(expression, parentElement) {\n    var results = [];\n    var query = document.evaluate(expression, $(parentElement) || document,\n      null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);\n    for (var i = 0, length = query.snapshotLength; i < length; i++)\n      results.push(query.snapshotItem(i));\n    return results;\n  };\n\n  document.getElementsByClassName = function(className, parentElement) {\n    var q = \".//*[contains(concat(' ', @class, ' '), ' \" + className + \" ')]\";\n    return document._getElementsByXPath(q, parentElement);\n  }\n\n} else document.getElementsByClassName = function(className, parentElement) {\n  var children = ($(parentElement) || document.body).getElementsByTagName('*');\n  var elements = [], child;\n  for (var i = 0, length = children.length; i < length; i++) {\n    child = children[i];\n    if (Element.hasClassName(child, className))\n      elements.push(Element.extend(child));\n  }\n  return elements;\n};\n\n/*--------------------------------------------------------------------------*/\n\nif (!window.Element) var Element = {};\n\nElement.extend = function(element) {\n  var F = Prototype.BrowserFeatures;\n  if (!element || !element.tagName || element.nodeType == 3 ||\n   element._extended || F.SpecificElementExtensions || element == window)\n    return element;\n\n  var methods = {}, tagName = element.tagName, cache = Element.extend.cache,\n   T = Element.Methods.ByTag;\n\n  // extend methods for all tags (Safari doesn't need this)\n  if (!F.ElementExtensions) {\n    Object.extend(methods, Element.Methods),\n    Object.extend(methods, Element.Methods.Simulated);\n  }\n\n  // extend methods for specific tags\n  if (T[tagName]) Object.extend(methods, T[tagName]);\n\n  for (var property in methods) {\n    var value = methods[property];\n    if (typeof value == 'function' && !(property in element))\n      element[property] = cache.findOrStore(value);\n  }\n\n  element._extended = Prototype.emptyFunction;\n  return element;\n};\n\nElement.extend.cache = {\n  findOrStore: function(value) {\n    return this[value] = this[value] || function() {\n      return value.apply(null, [this].concat($A(arguments)));\n    }\n  }\n};\n\nElement.Methods = {\n  visible: function(element) {\n    return $(element).style.display != 'none';\n  },\n\n  toggle: function(element) {\n    element = $(element);\n    Element[Element.visible(element) ? 'hide' : 'show'](element);\n    return element;\n  },\n\n  hide: function(element) {\n    $(element).style.display = 'none';\n    return element;\n  },\n\n  show: function(element) {\n    $(element).style.display = '';\n    return element;\n  },\n\n  remove: function(element) {\n    element = $(element);\n    element.parentNode.removeChild(element);\n    return element;\n  },\n\n  update: function(element, html) {\n    html = typeof html == 'undefined' ? '' : html.toString();\n    $(element).innerHTML = html.stripScripts();\n    setTimeout(function() {html.evalScripts()}, 10);\n    return element;\n  },\n\n  replace: function(element, html) {\n    element = $(element);\n    html = typeof html == 'undefined' ? '' : html.toString();\n    if (element.outerHTML) {\n      element.outerHTML = html.stripScripts();\n    } else {\n      var range = element.ownerDocument.createRange();\n      range.selectNodeContents(element);\n      element.parentNode.replaceChild(\n        range.createContextualFragment(html.stripScripts()), element);\n    }\n    setTimeout(function() {html.evalScripts()}, 10);\n    return element;\n  },\n\n  inspect: function(element) {\n    element = $(element);\n    var result = '<' + element.tagName.toLowerCase();\n    $H({'id': 'id', 'className': 'class'}).each(function(pair) {\n      var property = pair.first(), attribute = pair.last();\n      var value = (element[property] || '').toString();\n      if (value) result += ' ' + attribute + '=' + value.inspect(true);\n    });\n    return result + '>';\n  },\n\n  recursivelyCollect: function(element, property) {\n    element = $(element);\n    var elements = [];\n    while (element = element[property])\n      if (element.nodeType == 1)\n        elements.push(Element.extend(element));\n    return elements;\n  },\n\n  ancestors: function(element) {\n    return $(element).recursivelyCollect('parentNode');\n  },\n\n  descendants: function(element) {\n    return $A($(element).getElementsByTagName('*')).each(Element.extend);\n  },\n\n  firstDescendant: function(element) {\n    element = $(element).firstChild;\n    while (element && element.nodeType != 1) element = element.nextSibling;\n    return $(element);\n  },\n\n  immediateDescendants: function(element) {\n    if (!(element = $(element).firstChild)) return [];\n    while (element && element.nodeType != 1) element = element.nextSibling;\n    if (element) return [element].concat($(element).nextSiblings());\n    return [];\n  },\n\n  previousSiblings: function(element) {\n    return $(element).recursivelyCollect('previousSibling');\n  },\n\n  nextSiblings: function(element) {\n    return $(element).recursivelyCollect('nextSibling');\n  },\n\n  siblings: function(element) {\n    element = $(element);\n    return element.previousSiblings().reverse().concat(element.nextSiblings());\n  },\n\n  match: function(element, selector) {\n    if (typeof selector == 'string')\n      selector = new Selector(selector);\n    return selector.match($(element));\n  },\n\n  up: function(element, expression, index) {\n    element = $(element);\n    if (arguments.length == 1) return $(element.parentNode);\n    var ancestors = element.ancestors();\n    return expression ? Selector.findElement(ancestors, expression, index) :\n      ancestors[index || 0];\n  },\n\n  down: function(element, expression, index) {\n    element = $(element);\n    if (arguments.length == 1) return element.firstDescendant();\n    var descendants = element.descendants();\n    return expression ? Selector.findElement(descendants, expression, index) :\n      descendants[index || 0];\n  },\n\n  previous: function(element, expression, index) {\n    element = $(element);\n    if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));\n    var previousSiblings = element.previousSiblings();\n    return expression ? Selector.findElement(previousSiblings, expression, index) :\n      previousSiblings[index || 0];\n  },\n\n  next: function(element, expression, index) {\n    element = $(element);\n    if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));\n    var nextSiblings = element.nextSiblings();\n    return expression ? Selector.findElement(nextSiblings, expression, index) :\n      nextSiblings[index || 0];\n  },\n\n  getElementsBySelector: function() {\n    var args = $A(arguments), element = $(args.shift());\n    return Selector.findChildElements(element, args);\n  },\n\n  getElementsByClassName: function(element, className) {\n    return document.getElementsByClassName(className, element);\n  },\n\n  readAttribute: function(element, name) {\n    element = $(element);\n    if (Prototype.Browser.IE) {\n      if (!element.attributes) return null;\n      var t = Element._attributeTranslations;\n      if (t.values[name]) return t.values[name](element, name);\n      if (t.names[name])  name = t.names[name];\n      var attribute = element.attributes[name];\n      return attribute ? attribute.nodeValue : null;\n    }\n    return element.getAttribute(name);\n  },\n\n  getHeight: function(element) {\n    return $(element).getDimensions().height;\n  },\n\n  getWidth: function(element) {\n    return $(element).getDimensions().width;\n  },\n\n  classNames: function(element) {\n    return new Element.ClassNames(element);\n  },\n\n  hasClassName: function(element, className) {\n    if (!(element = $(element))) return;\n    var elementClassName = element.className;\n    if (elementClassName.length == 0) return false;\n    if (elementClassName == className ||\n    \t\t(typeof(elementClassName.match) === 'function' && elementClassName.match(new RegExp(\"(^|\\\\s)\" + className + \"(\\\\s|$)\"))))\n      return true;\n    return false;\n  },\n\n  addClassName: function(element, className) {\n    if (!(element = $(element))) return;\n    Element.classNames(element).add(className);\n    return element;\n  },\n\n  removeClassName: function(element, className) {\n    if (!(element = $(element))) return;\n    Element.classNames(element).remove(className);\n    return element;\n  },\n\n  toggleClassName: function(element, className) {\n    if (!(element = $(element))) return;\n    Element.classNames(element)[element.hasClassName(className) ? 'remove' : 'add'](className);\n    return element;\n  },\n\n  observe: function() {\n    Event.observe.apply(Event, arguments);\n    return $A(arguments).first();\n  },\n\n  stopObserving: function() {\n    Event.stopObserving.apply(Event, arguments);\n    return $A(arguments).first();\n  },\n\n  // removes whitespace-only text node children\n  cleanWhitespace: function(element) {\n    element = $(element);\n    var node = element.firstChild;\n    while (node) {\n      var nextNode = node.nextSibling;\n      if (node.nodeType == 3 && !/\\S/.test(node.nodeValue))\n        element.removeChild(node);\n      node = nextNode;\n    }\n    return element;\n  },\n\n  empty: function(element) {\n    return $(element).innerHTML.blank();\n  },\n\n  descendantOf: function(element, ancestor) {\n    element = $(element), ancestor = $(ancestor);\n    while (element = element.parentNode)\n      if (element == ancestor) return true;\n    return false;\n  },\n\n  scrollTo: function(element) {\n    element = $(element);\n    var pos = Position.cumulativeOffset(element);\n    window.scrollTo(pos[0], pos[1]);\n    return element;\n  },\n\n  getStyle: function(element, style) {\n    element = $(element);\n    style = style == 'float' ? 'cssFloat' : style.camelize();\n    var value = element.style[style];\n    if (!value) {\n      var css = document.defaultView.getComputedStyle(element, null);\n      value = css ? css[style] : null;\n    }\n    if (style == 'opacity') return value ? parseFloat(value) : 1.0;\n    return value == 'auto' ? null : value;\n  },\n\n  getOpacity: function(element) {\n    return $(element).getStyle('opacity');\n  },\n\n  setStyle: function(element, styles, camelized) {\n    element = $(element);\n    var elementStyle = element.style;\n\n    for (var property in styles)\n      if (property == 'opacity') element.setOpacity(styles[property])\n      else\n        elementStyle[(property == 'float' || property == 'cssFloat') ?\n          (elementStyle.styleFloat === undefined ? 'cssFloat' : 'styleFloat') :\n          (camelized ? property : property.camelize())] = styles[property];\n\n    return element;\n  },\n\n  setOpacity: function(element, value) {\n    element = $(element);\n    element.style.opacity = (value == 1 || value === '') ? '' :\n      (value < 0.00001) ? 0 : value;\n    return element;\n  },\n\n  getDimensions: function(element) {\n    element = $(element);\n    var display = $(element).getStyle('display');\n    if (display != 'none' && display != null) // Safari bug\n      return {width: element.offsetWidth, height: element.offsetHeight};\n\n    // All *Width and *Height properties give 0 on elements with display none,\n    // so enable the element temporarily\n    var els = element.style;\n    var originalVisibility = els.visibility;\n    var originalPosition = els.position;\n    var originalDisplay = els.display;\n    els.visibility = 'hidden';\n    els.position = 'absolute';\n    els.display = 'block';\n    var originalWidth = element.clientWidth;\n    var originalHeight = element.clientHeight;\n    els.display = originalDisplay;\n    els.position = originalPosition;\n    els.visibility = originalVisibility;\n    return {width: originalWidth, height: originalHeight};\n  },\n\n  makePositioned: function(element) {\n    element = $(element);\n    var pos = Element.getStyle(element, 'position');\n    if (pos == 'static' || !pos) {\n      element._madePositioned = true;\n      element.style.position = 'relative';\n      // Opera returns the offset relative to the positioning context, when an\n      // element is position relative but top and left have not been defined\n      if (window.opera) {\n        element.style.top = 0;\n        element.style.left = 0;\n      }\n    }\n    return element;\n  },\n\n  undoPositioned: function(element) {\n    element = $(element);\n    if (element._madePositioned) {\n      element._madePositioned = undefined;\n      element.style.position =\n        element.style.top =\n        element.style.left =\n        element.style.bottom =\n        element.style.right = '';\n    }\n    return element;\n  },\n\n  makeClipping: function(element) {\n    element = $(element);\n    if (element._overflow) return element;\n    element._overflow = element.style.overflow || 'auto';\n    if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')\n      element.style.overflow = 'hidden';\n    return element;\n  },\n\n  undoClipping: function(element) {\n    element = $(element);\n    if (!element._overflow) return element;\n    element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;\n    element._overflow = null;\n    return element;\n  }\n};\n\nObject.extend(Element.Methods, {\n  childOf: Element.Methods.descendantOf,\n  childElements: Element.Methods.immediateDescendants\n});\n\nif (Prototype.Browser.Opera) {\n  Element.Methods._getStyle = Element.Methods.getStyle;\n  Element.Methods.getStyle = function(element, style) {\n    switch(style) {\n      case 'left':\n      case 'top':\n      case 'right':\n      case 'bottom':\n        if (Element._getStyle(element, 'position') == 'static') return null;\n      default: return Element._getStyle(element, style);\n    }\n  };\n}\nelse if (Prototype.Browser.IE) {\n  Element.Methods.getStyle = function(element, style) {\n    element = $(element);\n    style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();\n    var value = element.style[style];\n    if (!value && element.currentStyle) value = element.currentStyle[style];\n\n    if (style == 'opacity') {\n      if (value = (element.getStyle('filter') || '').match(/alpha\\(opacity=(.*)\\)/))\n        if (value[1]) return parseFloat(value[1]) / 100;\n      return 1.0;\n    }\n\n    if (value == 'auto') {\n      if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))\n        return element['offset'+style.capitalize()] + 'px';\n      return null;\n    }\n    return value;\n  };\n\n  Element.Methods.setOpacity = function(element, value) {\n    element = $(element);\n    var filter = element.getStyle('filter'), style = element.style;\n    if (value == 1 || value === '') {\n      style.filter = filter.replace(/alpha\\([^\\)]*\\)/gi,'');\n      return element;\n    } else if (value < 0.00001) value = 0;\n    style.filter = filter.replace(/alpha\\([^\\)]*\\)/gi, '') +\n      'alpha(opacity=' + (value * 100) + ')';\n    return element;\n  };\n\n  // IE is missing .innerHTML support for TABLE-related elements\n  Element.Methods.update = function(element, html) {\n    element = $(element);\n    html = typeof html == 'undefined' ? '' : html.toString();\n    var tagName = element.tagName.toUpperCase();\n    if (['THEAD','TBODY','TR','TD'].include(tagName)) {\n      var div = document.createElement('div');\n      switch (tagName) {\n        case 'THEAD':\n        case 'TBODY':\n          div.innerHTML = '<table><tbody>' +  html.stripScripts() + '</tbody></table>';\n          depth = 2;\n          break;\n        case 'TR':\n          div.innerHTML = '<table><tbody><tr>' +  html.stripScripts() + '</tr></tbody></table>';\n          depth = 3;\n          break;\n        case 'TD':\n          div.innerHTML = '<table><tbody><tr><td>' +  html.stripScripts() + '</td></tr></tbody></table>';\n          depth = 4;\n      }\n      $A(element.childNodes).each(function(node) { element.removeChild(node) });\n      depth.times(function() { div = div.firstChild });\n      $A(div.childNodes).each(function(node) { element.appendChild(node) });\n    } else {\n      element.innerHTML = html.stripScripts();\n    }\n    setTimeout(function() { html.evalScripts() }, 10);\n    return element;\n  }\n}\nelse if (Prototype.Browser.Gecko) {\n  Element.Methods.setOpacity = function(element, value) {\n    element = $(element);\n    element.style.opacity = (value == 1) ? 0.999999 :\n      (value === '') ? '' : (value < 0.00001) ? 0 : value;\n    return element;\n  };\n}\n\nElement._attributeTranslations = {\n  names: {\n    colspan:   \"colSpan\",\n    rowspan:   \"rowSpan\",\n    valign:    \"vAlign\",\n    datetime:  \"dateTime\",\n    accesskey: \"accessKey\",\n    tabindex:  \"tabIndex\",\n    enctype:   \"encType\",\n    maxlength: \"maxLength\",\n    readonly:  \"readOnly\",\n    longdesc:  \"longDesc\"\n  },\n  values: {\n    _getAttr: function(element, attribute) {\n      return element.getAttribute(attribute, 2);\n    },\n    _flag: function(element, attribute) {\n      return $(element).hasAttribute(attribute) ? attribute : null;\n    },\n    style: function(element) {\n      return element.style.cssText.toLowerCase();\n    },\n    title: function(element) {\n      var node = element.getAttributeNode('title');\n      return node.specified ? node.nodeValue : null;\n    }\n  }\n};\n\n(function() {\n  Object.extend(this, {\n    href: this._getAttr,\n    src:  this._getAttr,\n    type: this._getAttr,\n    disabled: this._flag,\n    checked:  this._flag,\n    readonly: this._flag,\n    multiple: this._flag\n  });\n}).call(Element._attributeTranslations.values);\n\nElement.Methods.Simulated = {\n  hasAttribute: function(element, attribute) {\n    var t = Element._attributeTranslations, node;\n    attribute = t.names[attribute] || attribute;\n    node = $(element).getAttributeNode(attribute);\n    return node && node.specified;\n  }\n};\n\nElement.Methods.ByTag = {};\n\nObject.extend(Element, Element.Methods);\n\nif (!Prototype.BrowserFeatures.ElementExtensions &&\n document.createElement('div').__proto__) {\n  window.HTMLElement = {};\n  window.HTMLElement.prototype = document.createElement('div').__proto__;\n  Prototype.BrowserFeatures.ElementExtensions = true;\n}\n\nElement.hasAttribute = function(element, attribute) {\n  if (element.hasAttribute) return element.hasAttribute(attribute);\n  return Element.Methods.Simulated.hasAttribute(element, attribute);\n};\n\nElement.addMethods = function(methods) {\n  var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;\n\n  if (!methods) {\n    Object.extend(Form, Form.Methods);\n    Object.extend(Form.Element, Form.Element.Methods);\n    Object.extend(Element.Methods.ByTag, {\n      \"FORM\":     Object.clone(Form.Methods),\n      \"INPUT\":    Object.clone(Form.Element.Methods),\n      \"SELECT\":   Object.clone(Form.Element.Methods),\n      \"TEXTAREA\": Object.clone(Form.Element.Methods)\n    });\n  }\n\n  if (arguments.length == 2) {\n    var tagName = methods;\n    methods = arguments[1];\n  }\n\n  if (!tagName) Object.extend(Element.Methods, methods || {});\n  else {\n    if (tagName.constructor == Array) tagName.each(extend);\n    else extend(tagName);\n  }\n\n  function extend(tagName) {\n    tagName = tagName.toUpperCase();\n    if (!Element.Methods.ByTag[tagName])\n      Element.Methods.ByTag[tagName] = {};\n    Object.extend(Element.Methods.ByTag[tagName], methods);\n  }\n\n  function copy(methods, destination, onlyIfAbsent) {\n    onlyIfAbsent = onlyIfAbsent || false;\n    var cache = Element.extend.cache;\n    for (var property in methods) {\n      var value = methods[property];\n      if (!onlyIfAbsent || !(property in destination))\n        destination[property] = cache.findOrStore(value);\n    }\n  }\n\n  function findDOMClass(tagName) {\n    var klass;\n    var trans = {\n      \"OPTGROUP\": \"OptGroup\", \"TEXTAREA\": \"TextArea\", \"P\": \"Paragraph\",\n      \"FIELDSET\": \"FieldSet\", \"UL\": \"UList\", \"OL\": \"OList\", \"DL\": \"DList\",\n      \"DIR\": \"Directory\", \"H1\": \"Heading\", \"H2\": \"Heading\", \"H3\": \"Heading\",\n      \"H4\": \"Heading\", \"H5\": \"Heading\", \"H6\": \"Heading\", \"Q\": \"Quote\",\n      \"INS\": \"Mod\", \"DEL\": \"Mod\", \"A\": \"Anchor\", \"IMG\": \"Image\", \"CAPTION\":\n      \"TableCaption\", \"COL\": \"TableCol\", \"COLGROUP\": \"TableCol\", \"THEAD\":\n      \"TableSection\", \"TFOOT\": \"TableSection\", \"TBODY\": \"TableSection\", \"TR\":\n      \"TableRow\", \"TH\": \"TableCell\", \"TD\": \"TableCell\", \"FRAMESET\":\n      \"FrameSet\", \"IFRAME\": \"IFrame\"\n    };\n    if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';\n    if (window[klass]) return window[klass];\n    klass = 'HTML' + tagName + 'Element';\n    if (window[klass]) return window[klass];\n    klass = 'HTML' + tagName.capitalize() + 'Element';\n    if (window[klass]) return window[klass];\n\n    window[klass] = {};\n    window[klass].prototype = document.createElement(tagName).__proto__;\n    return window[klass];\n  }\n\n  if (F.ElementExtensions) {\n    copy(Element.Methods, HTMLElement.prototype);\n    copy(Element.Methods.Simulated, HTMLElement.prototype, true);\n  }\n\n  if (F.SpecificElementExtensions) {\n    for (var tag in Element.Methods.ByTag) {\n      var klass = findDOMClass(tag);\n      if (typeof klass == \"undefined\") continue;\n      copy(T[tag], klass.prototype);\n    }\n  }\n\n  Object.extend(Element, Element.Methods);\n  delete Element.ByTag;\n};\n\nvar Toggle = { display: Element.toggle };\n\n/*--------------------------------------------------------------------------*/\n\nAbstract.Insertion = function(adjacency) {\n  this.adjacency = adjacency;\n}\n\nAbstract.Insertion.prototype = {\n  initialize: function(element, content) {\n    this.element = $(element);\n    this.content = content.stripScripts();\n\n    if (this.adjacency && this.element.insertAdjacentHTML) {\n      try {\n        this.element.insertAdjacentHTML(this.adjacency, this.content);\n      } catch (e) {\n        var tagName = this.element.tagName.toUpperCase();\n        if (['TBODY', 'TR'].include(tagName)) {\n          this.insertContent(this.contentFromAnonymousTable());\n        } else {\n          throw e;\n        }\n      }\n    } else {\n      this.range = this.element.ownerDocument.createRange();\n      if (this.initializeRange) this.initializeRange();\n      this.insertContent([this.range.createContextualFragment(this.content)]);\n    }\n\n    setTimeout(function() {content.evalScripts()}, 10);\n  },\n\n  contentFromAnonymousTable: function() {\n    var div = document.createElement('div');\n    div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>';\n    return $A(div.childNodes[0].childNodes[0].childNodes);\n  }\n}\n\nvar Insertion = new Object();\n\nInsertion.Before = Class.create();\nInsertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {\n  initializeRange: function() {\n    this.range.setStartBefore(this.element);\n  },\n\n  insertContent: function(fragments) {\n    fragments.each((function(fragment) {\n      this.element.parentNode.insertBefore(fragment, this.element);\n    }).bind(this));\n  }\n});\n\nInsertion.Top = Class.create();\nInsertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {\n  initializeRange: function() {\n    this.range.selectNodeContents(this.element);\n    this.range.collapse(true);\n  },\n\n  insertContent: function(fragments) {\n    fragments.reverse(false).each((function(fragment) {\n      this.element.insertBefore(fragment, this.element.firstChild);\n    }).bind(this));\n  }\n});\n\nInsertion.Bottom = Class.create();\nInsertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {\n  initializeRange: function() {\n    this.range.selectNodeContents(this.element);\n    this.range.collapse(this.element);\n  },\n\n  insertContent: function(fragments) {\n    fragments.each((function(fragment) {\n      this.element.appendChild(fragment);\n    }).bind(this));\n  }\n});\n\nInsertion.After = Class.create();\nInsertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {\n  initializeRange: function() {\n    this.range.setStartAfter(this.element);\n  },\n\n  insertContent: function(fragments) {\n    fragments.each((function(fragment) {\n      this.element.parentNode.insertBefore(fragment,\n        this.element.nextSibling);\n    }).bind(this));\n  }\n});\n\n/*--------------------------------------------------------------------------*/\n\nElement.ClassNames = Class.create();\nElement.ClassNames.prototype = {\n  initialize: function(element) {\n    this.element = $(element);\n  },\n\n  _each: function(iterator) {\n    this.element.className.split(/\\s+/).select(function(name) {\n      return name.length > 0;\n    })._each(iterator);\n  },\n\n  set: function(className) {\n    this.element.className = className;\n  },\n\n  add: function(classNameToAdd) {\n    if (this.include(classNameToAdd)) return;\n    this.set($A(this).concat(classNameToAdd).join(' '));\n  },\n\n  remove: function(classNameToRemove) {\n    if (!this.include(classNameToRemove)) return;\n    this.set($A(this).without(classNameToRemove).join(' '));\n  },\n\n  toString: function() {\n    return $A(this).join(' ');\n  }\n};\n\nObject.extend(Element.ClassNames.prototype, Enumerable);\n/* Portions of the Selector class are derived from Jack Slocum�۪s DomQuery,\n * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style\n * license.  Please see http://www.yui-ext.com/ for more information. */\n\nvar Selector = Class.create();\n\nSelector.prototype = {\n  initialize: function(expression) {\n    this.expression = expression.strip();\n    this.compileMatcher();\n  },\n\n  compileMatcher: function() {\n    // Selectors with namespaced attributes can't use the XPath version\n    if (Prototype.BrowserFeatures.XPath && !(/\\[[\\w-]*?:/).test(this.expression))\n      return this.compileXPathMatcher();\n\n    var e = this.expression, ps = Selector.patterns, h = Selector.handlers,\n        c = Selector.criteria, le, p, m;\n\n    if (Selector._cache[e]) {\n      this.matcher = Selector._cache[e]; return;\n    }\n    this.matcher = [\"this.matcher = function(root) {\",\n                    \"var r = root, h = Selector.handlers, c = false, n;\"];\n\n    while (e && le != e && (/\\S/).test(e)) {\n      le = e;\n      for (var i in ps) {\n        p = ps[i];\n        if (m = e.match(p)) {\n          this.matcher.push(typeof c[i] == 'function' ? c[i](m) :\n    \t      new Template(c[i]).evaluate(m));\n          e = e.replace(m[0], '');\n          break;\n        }\n      }\n    }\n\n    this.matcher.push(\"return h.unique(n);\\n}\");\n    eval(this.matcher.join('\\n'));\n    Selector._cache[this.expression] = this.matcher;\n  },\n\n  compileXPathMatcher: function() {\n    var e = this.expression, ps = Selector.patterns,\n        x = Selector.xpath, le,  m;\n\n    if (Selector._cache[e]) {\n      this.xpath = Selector._cache[e]; return;\n    }\n\n    this.matcher = ['.//*'];\n    while (e && le != e && (/\\S/).test(e)) {\n      le = e;\n      for (var i in ps) {\n        if (m = e.match(ps[i])) {\n          this.matcher.push(typeof x[i] == 'function' ? x[i](m) :\n            new Template(x[i]).evaluate(m));\n          e = e.replace(m[0], '');\n          break;\n        }\n      }\n    }\n\n    this.xpath = this.matcher.join('');\n    Selector._cache[this.expression] = this.xpath;\n  },\n\n  findElements: function(root) {\n    root = root || document;\n    if (this.xpath) return document._getElementsByXPath(this.xpath, root);\n    return this.matcher(root);\n  },\n\n  match: function(element) {\n    return this.findElements(document).include(element);\n  },\n\n  toString: function() {\n    return this.expression;\n  },\n\n  inspect: function() {\n    return \"#<Selector:\" + this.expression.inspect() + \">\";\n  }\n};\n\nObject.extend(Selector, {\n  _cache: {},\n\n  xpath: {\n    descendant:   \"//*\",\n    child:        \"/*\",\n    adjacent:     \"/following-sibling::*[1]\",\n    laterSibling: '/following-sibling::*',\n    tagName:      function(m) {\n      if (m[1] == '*') return '';\n      return \"[local-name()='\" + m[1].toLowerCase() +\n             \"' or local-name()='\" + m[1].toUpperCase() + \"']\";\n    },\n    className:    \"[contains(concat(' ', @class, ' '), ' #{1} ')]\",\n    id:           \"[@id='#{1}']\",\n    attrPresence: \"[@#{1}]\",\n    attr: function(m) {\n      m[3] = m[5] || m[6];\n      return new Template(Selector.xpath.operators[m[2]]).evaluate(m);\n    },\n    pseudo: function(m) {\n      var h = Selector.xpath.pseudos[m[1]];\n      if (!h) return '';\n      if (typeof h === 'function') return h(m);\n      return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);\n    },\n    operators: {\n      '=':  \"[@#{1}='#{3}']\",\n      '!=': \"[@#{1}!='#{3}']\",\n      '^=': \"[starts-with(@#{1}, '#{3}')]\",\n      '$=': \"[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']\",\n      '*=': \"[contains(@#{1}, '#{3}')]\",\n      '~=': \"[contains(concat(' ', @#{1}, ' '), ' #{3} ')]\",\n      '|=': \"[contains(concat('-', @#{1}, '-'), '-#{3}-')]\"\n    },\n    pseudos: {\n      'first-child': '[not(preceding-sibling::*)]',\n      'last-child':  '[not(following-sibling::*)]',\n      'only-child':  '[not(preceding-sibling::* or following-sibling::*)]',\n      'empty':       \"[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \\t\\r\\n', '') = '')]\",\n      'checked':     \"[@checked]\",\n      'disabled':    \"[@disabled]\",\n      'enabled':     \"[not(@disabled)]\",\n      'not': function(m) {\n        var e = m[6], p = Selector.patterns,\n            x = Selector.xpath, le, m, v;\n\n        var exclusion = [];\n        while (e && le != e && (/\\S/).test(e)) {\n          le = e;\n          for (var i in p) {\n            if (m = e.match(p[i])) {\n              v = typeof x[i] == 'function' ? x[i](m) : new Template(x[i]).evaluate(m);\n              exclusion.push(\"(\" + v.substring(1, v.length - 1) + \")\");\n              e = e.replace(m[0], '');\n              break;\n            }\n          }\n        }\n        return \"[not(\" + exclusion.join(\" and \") + \")]\";\n      },\n      'nth-child':      function(m) {\n        return Selector.xpath.pseudos.nth(\"(count(./preceding-sibling::*) + 1) \", m);\n      },\n      'nth-last-child': function(m) {\n        return Selector.xpath.pseudos.nth(\"(count(./following-sibling::*) + 1) \", m);\n      },\n      'nth-of-type':    function(m) {\n        return Selector.xpath.pseudos.nth(\"position() \", m);\n      },\n      'nth-last-of-type': function(m) {\n        return Selector.xpath.pseudos.nth(\"(last() + 1 - position()) \", m);\n      },\n      'first-of-type':  function(m) {\n        m[6] = \"1\"; return Selector.xpath.pseudos['nth-of-type'](m);\n      },\n      'last-of-type':   function(m) {\n        m[6] = \"1\"; return Selector.xpath.pseudos['nth-last-of-type'](m);\n      },\n      'only-of-type':   function(m) {\n        var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m);\n      },\n      nth: function(fragment, m) {\n        var mm, formula = m[6], predicate;\n        if (formula == 'even') formula = '2n+0';\n        if (formula == 'odd')  formula = '2n+1';\n        if (mm = formula.match(/^(\\d+)$/)) // digit only\n          return '[' + fragment + \"= \" + mm[1] + ']';\n        if (mm = formula.match(/^(-?\\d*)?n(([+-])(\\d+))?/)) { // an+b\n          if (mm[1] == \"-\") mm[1] = -1;\n          var a = mm[1] ? Number(mm[1]) : 1;\n          var b = mm[2] ? Number(mm[2]) : 0;\n          predicate = \"[((#{fragment} - #{b}) mod #{a} = 0) and \" +\n          \"((#{fragment} - #{b}) div #{a} >= 0)]\";\n          return new Template(predicate).evaluate({\n            fragment: fragment, a: a, b: b });\n        }\n      }\n    }\n  },\n\n  criteria: {\n    tagName:      'n = h.tagName(n, r, \"#{1}\", c);   c = false;',\n    className:    'n = h.className(n, r, \"#{1}\", c); c = false;',\n    id:           'n = h.id(n, r, \"#{1}\", c);        c = false;',\n    attrPresence: 'n = h.attrPresence(n, r, \"#{1}\"); c = false;',\n    attr: function(m) {\n      m[3] = (m[5] || m[6]);\n      return new Template('n = h.attr(n, r, \"#{1}\", \"#{3}\", \"#{2}\"); c = false;').evaluate(m);\n    },\n    pseudo:       function(m) {\n      if (m[6]) m[6] = m[6].replace(/\"/g, '\\\\\"');\n      return new Template('n = h.pseudo(n, \"#{1}\", \"#{6}\", r, c); c = false;').evaluate(m);\n    },\n    descendant:   'c = \"descendant\";',\n    child:        'c = \"child\";',\n    adjacent:     'c = \"adjacent\";',\n    laterSibling: 'c = \"laterSibling\";'\n  },\n\n  patterns: {\n    // combinators must be listed first\n    // (and descendant needs to be last combinator)\n    laterSibling: /^\\s*~\\s*/,\n    child:        /^\\s*>\\s*/,\n    adjacent:     /^\\s*\\+\\s*/,\n    descendant:   /^\\s/,\n\n    // selectors follow\n    tagName:      /^\\s*(\\*|[\\w\\-]+)(\\b|$)?/,\n    id:           /^#([\\w\\-\\*]+)(\\b|$)/,\n    className:    /^\\.([\\w\\-\\*]+)(\\b|$)/,\n    pseudo:       /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\\((.*?)\\))?(\\b|$|\\s|(?=:))/,\n    attrPresence: /^\\[([\\w]+)\\]/,\n    attr:         /\\[((?:[\\w-]*:)?[\\w-]+)\\s*(?:([!^$*~|]?=)\\s*((['\"])([^\\]]*?)\\4|([^'\"][^\\]]*?)))?\\]/\n  },\n\n  handlers: {\n    // UTILITY FUNCTIONS\n    // joins two collections\n    concat: function(a, b) {\n      for (var i = 0, node; node = b[i]; i++)\n        a.push(node);\n      return a;\n    },\n\n    // marks an array of nodes for counting\n    mark: function(nodes) {\n      for (var i = 0, node; node = nodes[i]; i++)\n        node._counted = true;\n      return nodes;\n    },\n\n    unmark: function(nodes) {\n      for (var i = 0, node; node = nodes[i]; i++)\n        node._counted = undefined;\n      return nodes;\n    },\n\n    // mark each child node with its position (for nth calls)\n    // \"ofType\" flag indicates whether we're indexing for nth-of-type\n    // rather than nth-child\n    index: function(parentNode, reverse, ofType) {\n      parentNode._counted = true;\n      if (reverse) {\n        for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {\n          node = nodes[i];\n          if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++;\n        }\n      } else {\n        for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)\n          if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++;\n      }\n    },\n\n    // filters out duplicates and extends all nodes\n    unique: function(nodes) {\n      if (nodes.length == 0) return nodes;\n      var results = [], n;\n      for (var i = 0, l = nodes.length; i < l; i++)\n        if (!(n = nodes[i])._counted) {\n          n._counted = true;\n          results.push(Element.extend(n));\n        }\n      return Selector.handlers.unmark(results);\n    },\n\n    // COMBINATOR FUNCTIONS\n    descendant: function(nodes) {\n      var h = Selector.handlers;\n      for (var i = 0, results = [], node; node = nodes[i]; i++)\n        h.concat(results, node.getElementsByTagName('*'));\n      return results;\n    },\n\n    child: function(nodes) {\n      var h = Selector.handlers;\n      for (var i = 0, results = [], node; node = nodes[i]; i++) {\n        for (var j = 0, children = [], child; child = node.childNodes[j]; j++)\n          if (child.nodeType == 1 && child.tagName != '!') results.push(child);\n      }\n      return results;\n    },\n\n    adjacent: function(nodes) {\n      for (var i = 0, results = [], node; node = nodes[i]; i++) {\n        var next = this.nextElementSibling(node);\n        if (next) results.push(next);\n      }\n      return results;\n    },\n\n    laterSibling: function(nodes) {\n      var h = Selector.handlers;\n      for (var i = 0, results = [], node; node = nodes[i]; i++)\n        h.concat(results, Element.nextSiblings(node));\n      return results;\n    },\n\n    nextElementSibling: function(node) {\n      while (node = node.nextSibling)\n\t      if (node.nodeType == 1) return node;\n      return null;\n    },\n\n    previousElementSibling: function(node) {\n      while (node = node.previousSibling)\n        if (node.nodeType == 1) return node;\n      return null;\n    },\n\n    // TOKEN FUNCTIONS\n    tagName: function(nodes, root, tagName, combinator) {\n      tagName = tagName.toUpperCase();\n      var results = [], h = Selector.handlers;\n      if (nodes) {\n        if (combinator) {\n          // fastlane for ordinary descendant combinators\n          if (combinator == \"descendant\") {\n            for (var i = 0, node; node = nodes[i]; i++)\n              h.concat(results, node.getElementsByTagName(tagName));\n            return results;\n          } else nodes = this[combinator](nodes);\n          if (tagName == \"*\") return nodes;\n        }\n        for (var i = 0, node; node = nodes[i]; i++)\n          if (node.tagName.toUpperCase() == tagName) results.push(node);\n        return results;\n      } else return root.getElementsByTagName(tagName);\n    },\n\n    id: function(nodes, root, id, combinator) {\n      var targetNode = $(id), h = Selector.handlers;\n      if (!nodes && root == document) return targetNode ? [targetNode] : [];\n      if (nodes) {\n        if (combinator) {\n          if (combinator == 'child') {\n            for (var i = 0, node; node = nodes[i]; i++)\n              if (targetNode.parentNode == node) return [targetNode];\n          } else if (combinator == 'descendant') {\n            for (var i = 0, node; node = nodes[i]; i++)\n              if (Element.descendantOf(targetNode, node)) return [targetNode];\n          } else if (combinator == 'adjacent') {\n            for (var i = 0, node; node = nodes[i]; i++)\n              if (Selector.handlers.previousElementSibling(targetNode) == node)\n                return [targetNode];\n          } else nodes = h[combinator](nodes);\n        }\n        for (var i = 0, node; node = nodes[i]; i++)\n          if (node == targetNode) return [targetNode];\n        return [];\n      }\n      return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];\n    },\n\n    className: function(nodes, root, className, combinator) {\n      if (nodes && combinator) nodes = this[combinator](nodes);\n      return Selector.handlers.byClassName(nodes, root, className);\n    },\n\n    byClassName: function(nodes, root, className) {\n      if (!nodes) nodes = Selector.handlers.descendant([root]);\n      var needle = ' ' + className + ' ';\n      for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {\n        nodeClassName = node.className;\n        if (nodeClassName.length == 0) continue;\n        if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle))\n          results.push(node);\n      }\n      return results;\n    },\n\n    attrPresence: function(nodes, root, attr) {\n      var results = [];\n      for (var i = 0, node; node = nodes[i]; i++)\n        if (Element.hasAttribute(node, attr)) results.push(node);\n      return results;\n    },\n\n    attr: function(nodes, root, attr, value, operator) {\n      if (!nodes) nodes = root.getElementsByTagName(\"*\");\n      var handler = Selector.operators[operator], results = [];\n      for (var i = 0, node; node = nodes[i]; i++) {\n        var nodeValue = Element.readAttribute(node, attr);\n        if (nodeValue === null) continue;\n        if (handler(nodeValue, value)) results.push(node);\n      }\n      return results;\n    },\n\n    pseudo: function(nodes, name, value, root, combinator) {\n      if (nodes && combinator) nodes = this[combinator](nodes);\n      if (!nodes) nodes = root.getElementsByTagName(\"*\");\n      return Selector.pseudos[name](nodes, value, root);\n    }\n  },\n\n  pseudos: {\n    'first-child': function(nodes, value, root) {\n      for (var i = 0, results = [], node; node = nodes[i]; i++) {\n        if (Selector.handlers.previousElementSibling(node)) continue;\n          results.push(node);\n      }\n      return results;\n    },\n    'last-child': function(nodes, value, root) {\n      for (var i = 0, results = [], node; node = nodes[i]; i++) {\n        if (Selector.handlers.nextElementSibling(node)) continue;\n          results.push(node);\n      }\n      return results;\n    },\n    'only-child': function(nodes, value, root) {\n      var h = Selector.handlers;\n      for (var i = 0, results = [], node; node = nodes[i]; i++)\n        if (!h.previousElementSibling(node) && !h.nextElementSibling(node))\n          results.push(node);\n      return results;\n    },\n    'nth-child':        function(nodes, formula, root) {\n      return Selector.pseudos.nth(nodes, formula, root);\n    },\n    'nth-last-child':   function(nodes, formula, root) {\n      return Selector.pseudos.nth(nodes, formula, root, true);\n    },\n    'nth-of-type':      function(nodes, formula, root) {\n      return Selector.pseudos.nth(nodes, formula, root, false, true);\n    },\n    'nth-last-of-type': function(nodes, formula, root) {\n      return Selector.pseudos.nth(nodes, formula, root, true, true);\n    },\n    'first-of-type':    function(nodes, formula, root) {\n      return Selector.pseudos.nth(nodes, \"1\", root, false, true);\n    },\n    'last-of-type':     function(nodes, formula, root) {\n      return Selector.pseudos.nth(nodes, \"1\", root, true, true);\n    },\n    'only-of-type':     function(nodes, formula, root) {\n      var p = Selector.pseudos;\n      return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);\n    },\n\n    // handles the an+b logic\n    getIndices: function(a, b, total) {\n      if (a == 0) return b > 0 ? [b] : [];\n      return $R(1, total).inject([], function(memo, i) {\n        if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);\n        return memo;\n      });\n    },\n\n    // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type\n    nth: function(nodes, formula, root, reverse, ofType) {\n      if (nodes.length == 0) return [];\n      if (formula == 'even') formula = '2n+0';\n      if (formula == 'odd')  formula = '2n+1';\n      var h = Selector.handlers, results = [], indexed = [], m;\n      h.mark(nodes);\n      for (var i = 0, node; node = nodes[i]; i++) {\n        if (!node.parentNode._counted) {\n          h.index(node.parentNode, reverse, ofType);\n          indexed.push(node.parentNode);\n        }\n      }\n      if (formula.match(/^\\d+$/)) { // just a number\n        formula = Number(formula);\n        for (var i = 0, node; node = nodes[i]; i++)\n          if (node.nodeIndex == formula) results.push(node);\n      } else if (m = formula.match(/^(-?\\d*)?n(([+-])(\\d+))?/)) { // an+b\n        if (m[1] == \"-\") m[1] = -1;\n        var a = m[1] ? Number(m[1]) : 1;\n        var b = m[2] ? Number(m[2]) : 0;\n        var indices = Selector.pseudos.getIndices(a, b, nodes.length);\n        for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {\n          for (var j = 0; j < l; j++)\n            if (node.nodeIndex == indices[j]) results.push(node);\n        }\n      }\n      h.unmark(nodes);\n      h.unmark(indexed);\n      return results;\n    },\n\n    'empty': function(nodes, value, root) {\n      for (var i = 0, results = [], node; node = nodes[i]; i++) {\n        // IE treats comments as element nodes\n        if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\\s*$/))) continue;\n        results.push(node);\n      }\n      return results;\n    },\n\n    'not': function(nodes, selector, root) {\n      var h = Selector.handlers, selectorType, m;\n      var exclusions = new Selector(selector).findElements(root);\n      h.mark(exclusions);\n      for (var i = 0, results = [], node; node = nodes[i]; i++)\n        if (!node._counted) results.push(node);\n      h.unmark(exclusions);\n      return results;\n    },\n\n    'enabled': function(nodes, value, root) {\n      for (var i = 0, results = [], node; node = nodes[i]; i++)\n        if (!node.disabled) results.push(node);\n      return results;\n    },\n\n    'disabled': function(nodes, value, root) {\n      for (var i = 0, results = [], node; node = nodes[i]; i++)\n        if (node.disabled) results.push(node);\n      return results;\n    },\n\n    'checked': function(nodes, value, root) {\n      for (var i = 0, results = [], node; node = nodes[i]; i++)\n        if (node.checked) results.push(node);\n      return results;\n    }\n  },\n\n  operators: {\n    '=':  function(nv, v) { return nv == v; },\n    '!=': function(nv, v) { return nv != v; },\n    '^=': function(nv, v) { return nv.startsWith(v); },\n    '$=': function(nv, v) { return nv.endsWith(v); },\n    '*=': function(nv, v) { return nv.include(v); },\n    '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },\n    '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); }\n  },\n\n  matchElements: function(elements, expression) {\n    var matches = new Selector(expression).findElements(), h = Selector.handlers;\n    h.mark(matches);\n    for (var i = 0, results = [], element; element = elements[i]; i++)\n      if (element._counted) results.push(element);\n    h.unmark(matches);\n    return results;\n  },\n\n  findElement: function(elements, expression, index) {\n    if (typeof expression == 'number') {\n      index = expression; expression = false;\n    }\n    return Selector.matchElements(elements, expression || '*')[index || 0];\n  },\n\n  findChildElements: function(element, expressions) {\n    var exprs = expressions.join(','), expressions = [];\n    exprs.scan(/(([\\w#:.~>+()\\s-]+|\\*|\\[.*?\\])+)\\s*(,|$)/, function(m) {\n      expressions.push(m[1].strip());\n    });\n    var results = [], h = Selector.handlers;\n    for (var i = 0, l = expressions.length, selector; i < l; i++) {\n      selector = new Selector(expressions[i].strip());\n      h.concat(results, selector.findElements(element));\n    }\n    return (l > 1) ? h.unique(results) : results;\n  }\n});\n\nfunction $$() {\n  return Selector.findChildElements(document, $A(arguments));\n}\nvar Form = {\n  reset: function(form) {\n    $(form).reset();\n    return form;\n  },\n\n  serializeElements: function(elements, getHash) {\n    var data = elements.inject({}, function(result, element) {\n      if (!element.disabled && element.name) {\n        var key = element.name, value = $(element).getValue();\n        if (value != null) {\n         \tif (key in result) {\n            if (result[key].constructor != Array) result[key] = [result[key]];\n            result[key].push(value);\n          }\n          else result[key] = value;\n        }\n      }\n      return result;\n    });\n\n    return getHash ? data : Hash.toQueryString(data);\n  }\n};\n\nForm.Methods = {\n  serialize: function(form, getHash) {\n    return Form.serializeElements(Form.getElements(form), getHash);\n  },\n\n  getElements: function(form) {\n    return $A($(form).getElementsByTagName('*')).inject([],\n      function(elements, child) {\n        if (Form.Element.Serializers[child.tagName.toLowerCase()])\n          elements.push(Element.extend(child));\n        return elements;\n      }\n    );\n  },\n\n  getInputs: function(form, typeName, name) {\n    form = $(form);\n    var inputs = form.getElementsByTagName('input');\n\n    if (!typeName && !name) return $A(inputs).map(Element.extend);\n\n    for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {\n      var input = inputs[i];\n      if ((typeName && input.type != typeName) || (name && input.name != name))\n        continue;\n      matchingInputs.push(Element.extend(input));\n    }\n\n    return matchingInputs;\n  },\n\n  disable: function(form) {\n    form = $(form);\n    Form.getElements(form).invoke('disable');\n    return form;\n  },\n\n  enable: function(form) {\n    form = $(form);\n    Form.getElements(form).invoke('enable');\n    return form;\n  },\n\n  findFirstElement: function(form) {\n    return $(form).getElements().find(function(element) {\n      return element.type != 'hidden' && !element.disabled &&\n        ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());\n    });\n  },\n\n  focusFirstElement: function(form) {\n    form = $(form);\n    form.findFirstElement().activate();\n    return form;\n  },\n\n  request: function(form, options) {\n    form = $(form), options = Object.clone(options || {});\n\n    var params = options.parameters;\n    options.parameters = form.serialize(true);\n\n    if (params) {\n      if (typeof params == 'string') params = params.toQueryParams();\n      Object.extend(options.parameters, params);\n    }\n\n    if (form.hasAttribute('method') && !options.method)\n      options.method = form.method;\n\n    return new Ajax.Request(form.readAttribute('action'), options);\n  }\n}\n\n/*--------------------------------------------------------------------------*/\n\nForm.Element = {\n  focus: function(element) {\n    $(element).focus();\n    return element;\n  },\n\n  select: function(element) {\n    $(element).select();\n    return element;\n  }\n}\n\nForm.Element.Methods = {\n  serialize: function(element) {\n    element = $(element);\n    if (!element.disabled && element.name) {\n      var value = element.getValue();\n      if (value != undefined) {\n        var pair = {};\n        pair[element.name] = value;\n        return Hash.toQueryString(pair);\n      }\n    }\n    return '';\n  },\n\n  getValue: function(element) {\n    element = $(element);\n    var method = element.tagName.toLowerCase();\n    return Form.Element.Serializers[method](element);\n  },\n\n  clear: function(element) {\n    $(element).value = '';\n    return element;\n  },\n\n  present: function(element) {\n    return $(element).value != '';\n  },\n\n  activate: function(element) {\n    element = $(element);\n    try {\n      element.focus();\n      if (element.select && (element.tagName.toLowerCase() != 'input' ||\n        !['button', 'reset', 'submit'].include(element.type)))\n        element.select();\n    } catch (e) {}\n    return element;\n  },\n\n  disable: function(element) {\n    element = $(element);\n    element.blur();\n    element.disabled = true;\n    return element;\n  },\n\n  enable: function(element) {\n    element = $(element);\n    element.disabled = false;\n    return element;\n  }\n}\n\n/*--------------------------------------------------------------------------*/\n\nvar Field = Form.Element;\nvar $F = Form.Element.Methods.getValue;\n\n/*--------------------------------------------------------------------------*/\n\nForm.Element.Serializers = {\n  input: function(element) {\n    switch (element.type.toLowerCase()) {\n      case 'checkbox':\n      case 'radio':\n        return Form.Element.Serializers.inputSelector(element);\n      default:\n        return Form.Element.Serializers.textarea(element);\n    }\n  },\n\n  inputSelector: function(element) {\n    return element.checked ? element.value : null;\n  },\n\n  textarea: function(element) {\n    return element.value;\n  },\n\n  select: function(element) {\n    return this[element.type == 'select-one' ?\n      'selectOne' : 'selectMany'](element);\n  },\n\n  selectOne: function(element) {\n    var index = element.selectedIndex;\n    return index >= 0 ? this.optionValue(element.options[index]) : null;\n  },\n\n  selectMany: function(element) {\n    var values, length = element.length;\n    if (!length) return null;\n\n    for (var i = 0, values = []; i < length; i++) {\n      var opt = element.options[i];\n      if (opt.selected) values.push(this.optionValue(opt));\n    }\n    return values;\n  },\n\n  optionValue: function(opt) {\n    // extend element because hasAttribute may not be native\n    return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;\n  }\n}\n\n/*--------------------------------------------------------------------------*/\n\nAbstract.TimedObserver = function() {}\nAbstract.TimedObserver.prototype = {\n  initialize: function(element, frequency, callback) {\n    this.frequency = frequency;\n    this.element   = $(element);\n    this.callback  = callback;\n\n    this.lastValue = this.getValue();\n    this.registerCallback();\n  },\n\n  registerCallback: function() {\n    setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);\n  },\n\n  onTimerEvent: function() {\n    var value = this.getValue();\n    var changed = ('string' == typeof this.lastValue && 'string' == typeof value\n      ? this.lastValue != value : String(this.lastValue) != String(value));\n    if (changed) {\n      this.callback(this.element, value);\n      this.lastValue = value;\n    }\n  }\n}\n\nForm.Element.Observer = Class.create();\nForm.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {\n  getValue: function() {\n    return Form.Element.getValue(this.element);\n  }\n});\n\nForm.Observer = Class.create();\nForm.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {\n  getValue: function() {\n    return Form.serialize(this.element);\n  }\n});\n\n/*--------------------------------------------------------------------------*/\n\nAbstract.EventObserver = function() {}\nAbstract.EventObserver.prototype = {\n  initialize: function(element, callback) {\n    this.element  = $(element);\n    this.callback = callback;\n\n    this.lastValue = this.getValue();\n    if (this.element.tagName.toLowerCase() == 'form')\n      this.registerFormCallbacks();\n    else\n      this.registerCallback(this.element);\n  },\n\n  onElementEvent: function() {\n    var value = this.getValue();\n    if (this.lastValue != value) {\n      this.callback(this.element, value);\n      this.lastValue = value;\n    }\n  },\n\n  registerFormCallbacks: function() {\n    Form.getElements(this.element).each(this.registerCallback.bind(this));\n  },\n\n  registerCallback: function(element) {\n    if (element.type) {\n      switch (element.type.toLowerCase()) {\n        case 'checkbox':\n        case 'radio':\n          Event.observe(element, 'click', this.onElementEvent.bind(this));\n          break;\n        default:\n          Event.observe(element, 'change', this.onElementEvent.bind(this));\n          break;\n      }\n    }\n  }\n}\n\nForm.Element.EventObserver = Class.create();\nForm.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {\n  getValue: function() {\n    return Form.Element.getValue(this.element);\n  }\n});\n\nForm.EventObserver = Class.create();\nForm.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {\n  getValue: function() {\n    return Form.serialize(this.element);\n  }\n});\nif (!window.Event) {\n  var Event = new Object();\n}\n\nObject.extend(Event, {\n  KEY_BACKSPACE: 8,\n  KEY_TAB:       9,\n  KEY_RETURN:   13,\n  KEY_ESC:      27,\n  KEY_LEFT:     37,\n  KEY_UP:       38,\n  KEY_RIGHT:    39,\n  KEY_DOWN:     40,\n  KEY_DELETE:   46,\n  KEY_HOME:     36,\n  KEY_END:      35,\n  KEY_PAGEUP:   33,\n  KEY_PAGEDOWN: 34,\n\n  element: function(event) {\n    return $(event.target || event.srcElement);\n  },\n\n  isLeftClick: function(event) {\n    return (((event.which) && (event.which == 1)) ||\n            ((event.button) && (event.button == 1)));\n  },\n\n  pointerX: function(event) {\n    return event.pageX || (event.clientX +\n      (document.documentElement.scrollLeft || document.body.scrollLeft));\n  },\n\n  pointerY: function(event) {\n    return event.pageY || (event.clientY +\n      (document.documentElement.scrollTop || document.body.scrollTop));\n  },\n\n  stop: function(event) {\n    if (event.preventDefault) {\n      event.preventDefault();\n      event.stopPropagation();\n    } else {\n      event.returnValue = false;\n      event.cancelBubble = true;\n    }\n  },\n\n  // find the first node with the given tagName, starting from the\n  // node the event was triggered on; traverses the DOM upwards\n  findElement: function(event, tagName) {\n    var element = Event.element(event);\n    while (element.parentNode && (!element.tagName ||\n        (element.tagName.toUpperCase() != tagName.toUpperCase())))\n      element = element.parentNode;\n    return element;\n  },\n\n  observers: false,\n\n  _observeAndCache: function(element, name, observer, useCapture) {\n    if (!this.observers) this.observers = [];\n    if (element.addEventListener) {\n      this.observers.push([element, name, observer, useCapture]);\n      element.addEventListener(name, observer, useCapture);\n    } else if (element.attachEvent) {\n      this.observers.push([element, name, observer, useCapture]);\n      element.attachEvent('on' + name, observer);\n    }\n  },\n\n  unloadCache: function() {\n    if (!Event.observers) return;\n    for (var i = 0, length = Event.observers.length; i < length; i++) {\n      Event.stopObserving.apply(this, Event.observers[i]);\n      Event.observers[i][0] = null;\n    }\n    Event.observers = false;\n  },\n\n  observe: function(element, name, observer, useCapture) {\n    element = $(element);\n    useCapture = useCapture || false;\n\n    if (name == 'keypress' &&\n      (Prototype.Browser.WebKit || element.attachEvent))\n      name = 'keydown';\n\n    Event._observeAndCache(element, name, observer, useCapture);\n  },\n\n  stopObserving: function(element, name, observer, useCapture) {\n    element = $(element);\n    useCapture = useCapture || false;\n\n    if (name == 'keypress' &&\n        (Prototype.Browser.WebKit || element.attachEvent))\n      name = 'keydown';\n\n    if (element.removeEventListener) {\n      element.removeEventListener(name, observer, useCapture);\n    } else if (element.detachEvent) {\n      try {\n        element.detachEvent('on' + name, observer);\n      } catch (e) {}\n    }\n  }\n});\n\n/* prevent memory leaks in IE */\nif (Prototype.Browser.IE)\n  Event.observe(window, 'unload', Event.unloadCache, false);\nvar Position = {\n  // set to true if needed, warning: firefox performance problems\n  // NOT neeeded for page scrolling, only if draggable contained in\n  // scrollable elements\n  includeScrollOffsets: false,\n\n  // must be called before calling withinIncludingScrolloffset, every time the\n  // page is scrolled\n  prepare: function() {\n    this.deltaX =  window.pageXOffset\n                || document.documentElement.scrollLeft\n                || document.body.scrollLeft\n                || 0;\n    this.deltaY =  window.pageYOffset\n                || document.documentElement.scrollTop\n                || document.body.scrollTop\n                || 0;\n  },\n\n  realOffset: function(element) {\n    var valueT = 0, valueL = 0;\n    do {\n      valueT += element.scrollTop  || 0;\n      valueL += element.scrollLeft || 0;\n      element = element.parentNode;\n    } while (element);\n    return [valueL, valueT];\n  },\n\n  cumulativeOffset: function(element) {\n    var valueT = 0, valueL = 0;\n    do {\n      valueT += element.offsetTop  || 0;\n      valueL += element.offsetLeft || 0;\n      element = element.offsetParent;\n    } while (element);\n    return [valueL, valueT];\n  },\n\n  positionedOffset: function(element) {\n    var valueT = 0, valueL = 0;\n    do {\n      valueT += element.offsetTop  || 0;\n      valueL += element.offsetLeft || 0;\n      element = element.offsetParent;\n      if (element) {\n        if(element.tagName=='BODY') break;\n        var p = Element.getStyle(element, 'position');\n        if (p == 'relative' || p == 'absolute') break;\n      }\n    } while (element);\n    return [valueL, valueT];\n  },\n\n  offsetParent: function(element) {\n    if (element.offsetParent) return element.offsetParent;\n    if (element == document.body) return element;\n\n    while ((element = element.parentNode) && element != document.body)\n      if (Element.getStyle(element, 'position') != 'static')\n        return element;\n\n    return document.body;\n  },\n\n  // caches x/y coordinate pair to use with overlap\n  within: function(element, x, y) {\n    if (this.includeScrollOffsets)\n      return this.withinIncludingScrolloffsets(element, x, y);\n    this.xcomp = x;\n    this.ycomp = y;\n    this.offset = this.cumulativeOffset(element);\n\n    return (y >= this.offset[1] &&\n            y <  this.offset[1] + element.offsetHeight &&\n            x >= this.offset[0] &&\n            x <  this.offset[0] + element.offsetWidth);\n  },\n\n  withinIncludingScrolloffsets: function(element, x, y) {\n    var offsetcache = this.realOffset(element);\n\n    this.xcomp = x + offsetcache[0] - this.deltaX;\n    this.ycomp = y + offsetcache[1] - this.deltaY;\n    this.offset = this.cumulativeOffset(element);\n\n    return (this.ycomp >= this.offset[1] &&\n            this.ycomp <  this.offset[1] + element.offsetHeight &&\n            this.xcomp >= this.offset[0] &&\n            this.xcomp <  this.offset[0] + element.offsetWidth);\n  },\n\n  // within must be called directly before\n  overlap: function(mode, element) {\n    if (!mode) return 0;\n    if (mode == 'vertical')\n      return ((this.offset[1] + element.offsetHeight) - this.ycomp) /\n        element.offsetHeight;\n    if (mode == 'horizontal')\n      return ((this.offset[0] + element.offsetWidth) - this.xcomp) /\n        element.offsetWidth;\n  },\n\n  page: function(forElement) {\n    var valueT = 0, valueL = 0;\n\n    var element = forElement;\n    do {\n      valueT += element.offsetTop  || 0;\n      valueL += element.offsetLeft || 0;\n\n      // Safari fix\n      if (element.offsetParent == document.body)\n        if (Element.getStyle(element,'position')=='absolute') break;\n\n    } while (element = element.offsetParent);\n\n    element = forElement;\n    do {\n      if (!window.opera || element.tagName=='BODY') {\n        valueT -= element.scrollTop  || 0;\n        valueL -= element.scrollLeft || 0;\n      }\n    } while (element = element.parentNode);\n\n    return [valueL, valueT];\n  },\n\n  clone: function(source, target) {\n    var options = Object.extend({\n      setLeft:    true,\n      setTop:     true,\n      setWidth:   true,\n      setHeight:  true,\n      offsetTop:  0,\n      offsetLeft: 0\n    }, arguments[2] || {})\n\n    // find page position of source\n    source = $(source);\n    var p = Position.page(source);\n\n    // find coordinate system to use\n    target = $(target);\n    var delta = [0, 0];\n    var parent = null;\n    // delta [0,0] will do fine with position: fixed elements,\n    // position:absolute needs offsetParent deltas\n    if (Element.getStyle(target,'position') == 'absolute') {\n      parent = Position.offsetParent(target);\n      delta = Position.page(parent);\n    }\n\n    // correct by body offsets (fixes Safari)\n    if (parent == document.body) {\n      delta[0] -= document.body.offsetLeft;\n      delta[1] -= document.body.offsetTop;\n    }\n\n    // set position\n    if(options.setLeft)   target.style.left  = (p[0] - delta[0] + options.offsetLeft) + 'px';\n    if(options.setTop)    target.style.top   = (p[1] - delta[1] + options.offsetTop) + 'px';\n    if(options.setWidth)  target.style.width = source.offsetWidth + 'px';\n    if(options.setHeight) target.style.height = source.offsetHeight + 'px';\n  },\n\n  absolutize: function(element) {\n    element = $(element);\n    if (element.style.position == 'absolute') return;\n    Position.prepare();\n\n    var offsets = Position.positionedOffset(element);\n    var top     = offsets[1];\n    var left    = offsets[0];\n    var width   = element.clientWidth;\n    var height  = element.clientHeight;\n\n    element._originalLeft   = left - parseFloat(element.style.left  || 0);\n    element._originalTop    = top  - parseFloat(element.style.top || 0);\n    element._originalWidth  = element.style.width;\n    element._originalHeight = element.style.height;\n\n    element.style.position = 'absolute';\n    element.style.top    = top + 'px';\n    element.style.left   = left + 'px';\n    element.style.width  = width + 'px';\n    element.style.height = height + 'px';\n  },\n\n  relativize: function(element) {\n    element = $(element);\n    if (element.style.position == 'relative') return;\n    Position.prepare();\n\n    element.style.position = 'relative';\n    var top  = parseFloat(element.style.top  || 0) - (element._originalTop || 0);\n    var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);\n\n    element.style.top    = top + 'px';\n    element.style.left   = left + 'px';\n    element.style.height = element._originalHeight;\n    element.style.width  = element._originalWidth;\n  }\n}\n\n// Safari returns margins on body which is incorrect if the child is absolutely\n// positioned.  For performance reasons, redefine Position.cumulativeOffset for\n// KHTML/WebKit only.\nif (Prototype.Browser.WebKit) {\n  Position.cumulativeOffset = function(element) {\n    var valueT = 0, valueL = 0;\n    do {\n      valueT += element.offsetTop  || 0;\n      valueL += element.offsetLeft || 0;\n      if (element.offsetParent == document.body)\n        if (Element.getStyle(element, 'position') == 'absolute') break;\n\n      element = element.offsetParent;\n    } while (element);\n\n    return [valueL, valueT];\n  }\n}\n\nElement.addMethods();"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/ui-utils.min-0.0.4.js",
    "content": "/**\n * angular-ui-utils - Swiss-Army-Knife of AngularJS tools (with no external dependencies!)\n * @version v0.0.4 - 2013-08-28\n * @link http://angular-ui.github.com\n * @license MIT License, http://www.opensource.org/licenses/MIT\n */\nangular.module(\"ui.event\",[]).directive(\"uiEvent\",[\"$parse\",function(a){return function(b,c,d){var e=b.$eval(d.uiEvent);angular.forEach(e,function(d,e){var f=a(d);c.bind(e,function(a){var c=Array.prototype.slice.call(arguments);c=c.splice(1),f(b,{$event:a,$params:c}),b.$$phase||b.$apply()})})}}]),angular.module(\"ui.format\",[]).filter(\"format\",function(){return function(a,b){var c=a;if(angular.isString(c)&&void 0!==b)if(angular.isArray(b)||angular.isObject(b)||(b=[b]),angular.isArray(b)){var d=b.length,e=function(a,c){return c=parseInt(c,10),c>=0&&d>c?b[c]:a};c=c.replace(/\\$([0-9]+)/g,e)}else angular.forEach(b,function(a,b){c=c.split(\":\"+b).join(a)});return c}}),angular.module(\"ui.highlight\",[]).filter(\"highlight\",function(){return function(a,b,c){return b||angular.isNumber(b)?(a=a.toString(),b=b.toString(),c?a.split(b).join('<span class=\"ui-match\">'+b+\"</span>\"):a.replace(new RegExp(b,\"gi\"),'<span class=\"ui-match\">$&</span>')):a}}),angular.module(\"ui.include\",[]).directive(\"uiInclude\",[\"$http\",\"$templateCache\",\"$anchorScroll\",\"$compile\",function(a,b,c,d){return{restrict:\"ECA\",terminal:!0,compile:function(e,f){var g=f.uiInclude||f.src,h=f.fragment||\"\",i=f.onload||\"\",j=f.autoscroll;return function(e,f){function k(){var k=++m,o=e.$eval(g),p=e.$eval(h);o?a.get(o,{cache:b}).success(function(a){if(k===m){l&&l.$destroy(),l=e.$new();var b;b=p?angular.element(\"<div/>\").html(a).find(p):angular.element(\"<div/>\").html(a).contents(),f.html(b),d(b)(l),!angular.isDefined(j)||j&&!e.$eval(j)||c(),l.$emit(\"$includeContentLoaded\"),e.$eval(i)}}).error(function(){k===m&&n()}):n()}var l,m=0,n=function(){l&&(l.$destroy(),l=null),f.html(\"\")};e.$watch(h,k),e.$watch(g,k)}}}}]),angular.module(\"ui.indeterminate\",[]).directive(\"uiIndeterminate\",[function(){return{compile:function(a,b){return b.type&&\"checkbox\"===b.type.toLowerCase()?function(a,b,c){a.$watch(c.uiIndeterminate,function(a){b[0].indeterminate=!!a})}:angular.noop}}}]),angular.module(\"ui.inflector\",[]).filter(\"inflector\",function(){function a(a){return a.replace(/^([a-z])|\\s+([a-z])/g,function(a){return a.toUpperCase()})}function b(a,b){return a.replace(/[A-Z]/g,function(a){return b+a})}var c={humanize:function(c){return a(b(c,\" \").split(\"_\").join(\" \"))},underscore:function(a){return a.substr(0,1).toLowerCase()+b(a.substr(1),\"_\").toLowerCase().split(\" \").join(\"_\")},variable:function(b){return b=b.substr(0,1).toLowerCase()+a(b.split(\"_\").join(\" \")).substr(1).split(\" \").join(\"\")}};return function(a,b){return b!==!1&&angular.isString(a)?(b=b||\"humanize\",c[b](a)):a}}),angular.module(\"ui.jq\",[]).value(\"uiJqConfig\",{}).directive(\"uiJq\",[\"uiJqConfig\",\"$timeout\",function(a,b){return{restrict:\"A\",compile:function(c,d){if(!angular.isFunction(c[d.uiJq]))throw new Error('ui-jq: The \"'+d.uiJq+'\" function does not exist');var e=a&&a[d.uiJq];return function(a,c,d){function f(){b(function(){c[d.uiJq].apply(c,g)},0,!1)}var g=[];d.uiOptions?(g=a.$eval(\"[\"+d.uiOptions+\"]\"),angular.isObject(e)&&angular.isObject(g[0])&&(g[0]=angular.extend({},e,g[0]))):e&&(g=[e]),d.ngModel&&c.is(\"select,input,textarea\")&&c.bind(\"change\",function(){c.trigger(\"input\")}),d.uiRefresh&&a.$watch(d.uiRefresh,function(){f()}),f()}}}}]),angular.module(\"ui.keypress\",[]).factory(\"keypressHelper\",[\"$parse\",function(a){var b={8:\"backspace\",9:\"tab\",13:\"enter\",27:\"esc\",32:\"space\",33:\"pageup\",34:\"pagedown\",35:\"end\",36:\"home\",37:\"left\",38:\"up\",39:\"right\",40:\"down\",45:\"insert\",46:\"delete\"},c=function(a){return a.charAt(0).toUpperCase()+a.slice(1)};return function(d,e,f,g){var h,i=[];h=e.$eval(g[\"ui\"+c(d)]),angular.forEach(h,function(b,c){var d,e;e=a(b),angular.forEach(c.split(\" \"),function(a){d={expression:e,keys:{}},angular.forEach(a.split(\"-\"),function(a){d.keys[a]=!0}),i.push(d)})}),f.bind(d,function(a){var c=!(!a.metaKey||a.ctrlKey),f=!!a.altKey,g=!!a.ctrlKey,h=!!a.shiftKey,j=a.keyCode;\"keypress\"===d&&!h&&j>=97&&122>=j&&(j-=32),angular.forEach(i,function(d){var i=d.keys[b[j]]||d.keys[j.toString()],k=!!d.keys.meta,l=!!d.keys.alt,m=!!d.keys.ctrl,n=!!d.keys.shift;i&&k===c&&l===f&&m===g&&n===h&&e.$apply(function(){d.expression(e,{$event:a})})})})}}]),angular.module(\"ui.keypress\").directive(\"uiKeydown\",[\"keypressHelper\",function(a){return{link:function(b,c,d){a(\"keydown\",b,c,d)}}}]),angular.module(\"ui.keypress\").directive(\"uiKeypress\",[\"keypressHelper\",function(a){return{link:function(b,c,d){a(\"keypress\",b,c,d)}}}]),angular.module(\"ui.keypress\").directive(\"uiKeyup\",[\"keypressHelper\",function(a){return{link:function(b,c,d){a(\"keyup\",b,c,d)}}}]),angular.module(\"ui.mask\",[]).value(\"uiMaskConfig\",{maskDefinitions:{9:/\\d/,A:/[a-zA-Z]/,\"*\":/[a-zA-Z0-9]/}}).directive(\"uiMask\",[\"uiMaskConfig\",function(a){return{priority:100,require:\"ngModel\",restrict:\"A\",compile:function(){var b=a;return function(a,c,d,e){function f(a){return angular.isDefined(a)?(s(a),N?(k(),l(),!0):j()):j()}function g(a){angular.isDefined(a)&&(D=a,N&&w())}function h(a){return N?(G=o(a||\"\"),I=n(G),e.$setValidity(\"mask\",I),I&&G.length?p(G):void 0):a}function i(a){return N?(G=o(a||\"\"),I=n(G),e.$viewValue=G.length?p(G):\"\",e.$setValidity(\"mask\",I),\"\"===G&&void 0!==e.$error.required&&e.$setValidity(\"required\",!1),I?G:void 0):a}function j(){return N=!1,m(),angular.isDefined(P)?c.attr(\"placeholder\",P):c.removeAttr(\"placeholder\"),angular.isDefined(Q)?c.attr(\"maxlength\",Q):c.removeAttr(\"maxlength\"),c.val(e.$modelValue),e.$viewValue=e.$modelValue,!1}function k(){G=K=o(e.$modelValue||\"\"),H=J=p(G),I=n(G);var a=I&&G.length?H:\"\";d.maxlength&&c.attr(\"maxlength\",2*B[B.length-1]),c.attr(\"placeholder\",D),c.val(a),e.$viewValue=a}function l(){O||(c.bind(\"blur\",t),c.bind(\"mousedown mouseup\",u),c.bind(\"input keyup click focus\",w),O=!0)}function m(){O&&(c.unbind(\"blur\",t),c.unbind(\"mousedown\",u),c.unbind(\"mouseup\",u),c.unbind(\"input\",w),c.unbind(\"keyup\",w),c.unbind(\"click\",w),c.unbind(\"focus\",w),O=!1)}function n(a){return a.length?a.length>=F:!0}function o(a){var b=\"\",c=C.slice();return a=a.toString(),angular.forEach(E,function(b){a=a.replace(b,\"\")}),angular.forEach(a.split(\"\"),function(a){c.length&&c[0].test(a)&&(b+=a,c.shift())}),b}function p(a){var b=\"\",c=B.slice();return angular.forEach(D.split(\"\"),function(d,e){a.length&&e===c[0]?(b+=a.charAt(0)||\"_\",a=a.substr(1),c.shift()):b+=d}),b}function q(a){var b=d.placeholder;return\"undefined\"!=typeof b&&b[a]?b[a]:\"_\"}function r(){return D.replace(/[_]+/g,\"_\").replace(/([^_]+)([a-zA-Z0-9])([^_])/g,\"$1$2_$3\").split(\"_\")}function s(a){var b=0;if(B=[],C=[],D=\"\",\"string\"==typeof a){F=0;var c=!1,d=a.split(\"\");angular.forEach(d,function(a,d){R.maskDefinitions[a]?(B.push(b),D+=q(d),C.push(R.maskDefinitions[a]),b++,c||F++):\"?\"===a?c=!0:(D+=a,b++)})}B.push(B.slice().pop()+1),E=r(),N=B.length>1?!0:!1}function t(){L=0,M=0,I&&0!==G.length||(H=\"\",c.val(\"\"),a.$apply(function(){e.$setViewValue(\"\")}))}function u(a){\"mousedown\"===a.type?c.bind(\"mouseout\",v):c.unbind(\"mouseout\",v)}function v(){M=A(this),c.unbind(\"mouseout\",v)}function w(b){b=b||{};var d=b.which,f=b.type;if(16!==d&&91!==d){var g,h=c.val(),i=J,j=o(h),k=K,l=!1,m=y(this)||0,n=L||0,q=m-n,r=B[0],s=B[j.length]||B.slice().shift(),t=M||0,u=A(this)>0,v=t>0,w=h.length>i.length||t&&h.length>i.length-t,C=h.length<i.length||t&&h.length===i.length-t,D=d>=37&&40>=d&&b.shiftKey,E=37===d,F=8===d||\"keyup\"!==f&&C&&-1===q,G=46===d||\"keyup\"!==f&&C&&0===q&&!v,H=(E||F||\"click\"===f)&&m>r;if(M=A(this),!D&&(!u||\"click\"!==f&&\"keyup\"!==f)){if(\"input\"===f&&C&&!v&&j===k){for(;F&&m>r&&!x(m);)m--;for(;G&&s>m&&-1===B.indexOf(m);)m++;var I=B.indexOf(m);j=j.substring(0,I)+j.substring(I+1),l=!0}for(g=p(j),J=g,K=j,c.val(g),l&&a.$apply(function(){e.$setViewValue(j)}),w&&r>=m&&(m=r+1),H&&m--,m=m>s?s:r>m?r:m;!x(m)&&m>r&&s>m;)m+=H?-1:1;(H&&s>m||w&&!x(n))&&m++,L=m,z(this,m)}}}function x(a){return B.indexOf(a)>-1}function y(a){if(void 0!==a.selectionStart)return a.selectionStart;if(document.selection){a.focus();var b=document.selection.createRange();return b.moveStart(\"character\",-a.value.length),b.text.length}return 0}function z(a,b){if(0!==a.offsetWidth&&0!==a.offsetHeight)if(a.setSelectionRange)a.focus(),a.setSelectionRange(b,b);else if(a.createTextRange){var c=a.createTextRange();c.collapse(!0),c.moveEnd(\"character\",b),c.moveStart(\"character\",b),c.select()}}function A(a){return void 0!==a.selectionStart?a.selectionEnd-a.selectionStart:document.selection?document.selection.createRange().text.length:0}var B,C,D,E,F,G,H,I,J,K,L,M,N=!1,O=!1,P=d.placeholder,Q=d.maxlength,R={};d.uiOptions?(R=a.$eval(\"[\"+d.uiOptions+\"]\"),angular.isObject(R[0])&&(R=function(a,b){for(var c in a)Object.prototype.hasOwnProperty.call(a,c)&&(b[c]?angular.extend(b[c],a[c]):b[c]=angular.copy(a[c]));return b}(b,R[0]))):R=b,d.$observe(\"uiMask\",f),d.$observe(\"placeholder\",g),e.$formatters.push(h),e.$parsers.push(i),c.bind(\"mousedown mouseup\",u),Array.prototype.indexOf||(Array.prototype.indexOf=function(a){\"use strict\";if(null===this)throw new TypeError;var b=Object(this),c=b.length>>>0;if(0===c)return-1;var d=0;if(arguments.length>1&&(d=Number(arguments[1]),d!==d?d=0:0!==d&&1/0!==d&&d!==-1/0&&(d=(d>0||-1)*Math.floor(Math.abs(d)))),d>=c)return-1;for(var e=d>=0?d:Math.max(c-Math.abs(d),0);c>e;e++)if(e in b&&b[e]===a)return e;return-1})}}}}]),angular.module(\"ui.reset\",[]).value(\"uiResetConfig\",null).directive(\"uiReset\",[\"uiResetConfig\",function(a){var b=null;return void 0!==a&&(b=a),{require:\"ngModel\",link:function(a,c,d,e){var f;f=angular.element('<a class=\"ui-reset\" />'),c.wrap('<span class=\"ui-resetwrap\" />').after(f),f.bind(\"click\",function(c){c.preventDefault(),a.$apply(function(){d.uiReset?e.$setViewValue(a.$eval(d.uiReset)):e.$setViewValue(b),e.$render()})})}}}]),angular.module(\"ui.route\",[]).directive(\"uiRoute\",[\"$location\",\"$parse\",function(a,b){return{restrict:\"AC\",scope:!0,compile:function(c,d){var e;if(d.uiRoute)e=\"uiRoute\";else if(d.ngHref)e=\"ngHref\";else{if(!d.href)throw new Error(\"uiRoute missing a route or href property on \"+c[0]);e=\"href\"}return function(c,d,f){function g(b){(hash=b.indexOf(\"#\"))>-1&&(b=b.substr(hash+1)),j=function(){i(c,a.path().indexOf(b)>-1)},j()}function h(b){(hash=b.indexOf(\"#\"))>-1&&(b=b.substr(hash+1)),j=function(){var d=new RegExp(\"^\"+b+\"$\",[\"i\"]);i(c,d.test(a.path()))},j()}var i=b(f.ngModel||f.routeModel||\"$uiRoute\").assign,j=angular.noop;switch(e){case\"uiRoute\":f.uiRoute?h(f.uiRoute):f.$observe(\"uiRoute\",h);break;case\"ngHref\":f.ngHref?g(f.ngHref):f.$observe(\"ngHref\",g);break;case\"href\":g(f.href)}c.$on(\"$routeChangeSuccess\",function(){j()}),c.$on(\"$stateChangeSuccess\",function(){j()})}}}}]),angular.module(\"ui.scrollfix\",[]).directive(\"uiScrollfix\",[\"$window\",function(a){\"use strict\";return{require:\"^?uiScrollfixTarget\",link:function(b,c,d,e){var f=c[0].offsetTop,g=e&&e.$element||angular.element(a);d.uiScrollfix?\"string\"==typeof d.uiScrollfix&&(\"-\"===d.uiScrollfix.charAt(0)?d.uiScrollfix=f-parseFloat(d.uiScrollfix.substr(1)):\"+\"===d.uiScrollfix.charAt(0)&&(d.uiScrollfix=f+parseFloat(d.uiScrollfix.substr(1)))):d.uiScrollfix=f,g.bind(\"scroll\",function(){var b;if(angular.isDefined(a.pageYOffset))b=a.pageYOffset;else{var e=document.compatMode&&\"BackCompat\"!==document.compatMode?document.documentElement:document.body;b=e.scrollTop}!c.hasClass(\"ui-scrollfix\")&&b>d.uiScrollfix?c.addClass(\"ui-scrollfix\"):c.hasClass(\"ui-scrollfix\")&&b<d.uiScrollfix&&c.removeClass(\"ui-scrollfix\")})}}}]).directive(\"uiScrollfixTarget\",[function(){\"use strict\";return{controller:function(a){this.$element=a}}}]),angular.module(\"ui.showhide\",[]).directive(\"uiShow\",[function(){return function(a,b,c){a.$watch(c.uiShow,function(a){a?b.addClass(\"ui-show\"):b.removeClass(\"ui-show\")})}}]).directive(\"uiHide\",[function(){return function(a,b,c){a.$watch(c.uiHide,function(a){a?b.addClass(\"ui-hide\"):b.removeClass(\"ui-hide\")})}}]).directive(\"uiToggle\",[function(){return function(a,b,c){a.$watch(c.uiToggle,function(a){a?b.removeClass(\"ui-hide\").addClass(\"ui-show\"):b.removeClass(\"ui-show\").addClass(\"ui-hide\")})}}]),angular.module(\"ui.unique\",[]).filter(\"unique\",[\"$parse\",function(a){return function(b,c){if(c===!1)return b;if((c||angular.isUndefined(c))&&angular.isArray(b)){var d=[],e=angular.isString(c)?a(c):function(a){return a},f=function(a){return angular.isObject(a)?e(a):a};angular.forEach(b,function(a){for(var b=!1,c=0;c<d.length;c++)if(angular.equals(f(d[c]),f(a))){b=!0;break}b||d.push(a)}),b=d}return b}}]),angular.module(\"ui.validate\",[]).directive(\"uiValidate\",function(){return{restrict:\"A\",require:\"ngModel\",link:function(a,b,c,d){function e(b){return angular.isString(b)?(a.$watch(b,function(){angular.forEach(g,function(a){a(d.$modelValue)})}),void 0):angular.isArray(b)?(angular.forEach(b,function(b){a.$watch(b,function(){angular.forEach(g,function(a){a(d.$modelValue)})})}),void 0):(angular.isObject(b)&&angular.forEach(b,function(b,c){angular.isString(b)&&a.$watch(b,function(){g[c](d.$modelValue)}),angular.isArray(b)&&angular.forEach(b,function(b){a.$watch(b,function(){g[c](d.$modelValue)})})}),void 0)}var f,g={},h=a.$eval(c.uiValidate);h&&(angular.isString(h)&&(h={validator:h}),angular.forEach(h,function(b,c){f=function(e){var f=a.$eval(b,{$value:e});return angular.isObject(f)&&angular.isFunction(f.then)?(f.then(function(){d.$setValidity(c,!0)},function(){d.$setValidity(c,!1)}),e):f?(d.$setValidity(c,!0),e):(d.$setValidity(c,!1),void 0)},g[c]=f,d.$formatters.push(f),d.$parsers.push(f)}),c.uiValidateWatch&&e(a.$eval(c.uiValidateWatch)))}}}),angular.module(\"ui.utils\",[\"ui.event\",\"ui.format\",\"ui.highlight\",\"ui.include\",\"ui.indeterminate\",\"ui.inflector\",\"ui.jq\",\"ui.keypress\",\"ui.mask\",\"ui.reset\",\"ui.route\",\"ui.scrollfix\",\"ui.showhide\",\"ui.unique\",\"ui.validate\"]);"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/partials/root-stencil-item-template.html",
    "content": "<span class=\"stencil-item root-stencil-item\"\n      id=\"{{group.id}}\"\n      title=\"{{group.description}}\"\n      ng-model=\"draggedElement\"\n      data-drag=\"true\"\n      jqyoui-draggable=\"{onStart:'startDragCallback', onDrag:'dragCallback'}\"\n      data-jqyoui-options=\"{revert: 'invalid', helper: 'clone', opacity : 0.5}\">\n        \n        <img ng-src=\"editor-app/stencilsets/bpmn2.0/icons/{{group.icon}}\" width=\"16px;\" height=\"16px;\"/>\n        {{group.name}}\n</span>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/partials/stencil-item-template.html",
    "content": "<span ng-click=\"group.expanded = !group.expanded\">\n        <i class=\"glyphicon\"\n           ng-class=\"{'glyphicon-chevron-right': !group.expanded, 'glyphicon-chevron-down': group.expanded}\"></i>\n        {{group.name}}\n    </span>\n\n<!-- Child groups -->\n<ul ng-repeat=\"group in group.groups\"\n    class=\"stencil-group stencil-group-non-root\"\n    ng-class=\"{collapsed: !group.expanded, 'first': $first}\"\n    ng-include=\"'editor-app/partials/stencil-item-template.html?version=4'\">\n</ul>\n\n<!-- Group items -->\n<ul>\n    <li ng-repeat=\"item in group.paletteItems\" class=\"stencil-item\"\n        id=\"{{item.id}}\"\n        title=\"{{item.description}}\"\n        ng-model=\"draggedElement\"\n        data-drag=\"true\"\n        jqyoui-draggable=\"{onStart:'startDragCallback', onDrag:'dragCallback'}\"\n        data-jqyoui-options=\"{revert: 'invalid', helper: 'clone', opacity : 0.5}\">\n        \n        <img ng-src=\"editor-app/stencilsets/bpmn2.0/icons/{{item.icon}}\" width=\"16px;\" height=\"16px;\"/>\n        {{item.name}}\n    </li>\n</ul>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/plugins.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<config>\n\n  <plugins>\n    <plugin source=\"version.js\" name=\"\" />\n    <plugin source=\"signavio.js\" name=\"Signavio.Plugins.Loading\" />\n\n    <plugin source=\"loading.js\" name=\"ORYX.Plugins.Loading\" />\n    <plugin source=\"canvasResize.js\" name=\"ORYX.Plugins.CanvasResize\">\n      <notUsesIn namespace=\"http://b3mn.org/stencilset/xforms#\"/>\n    </plugin>\n    \n    <plugin source=\"renameShapes.js\" name=\"ORYX.Plugins.RenameShapes\" />\n    <plugin source=\"processLink.js\" name=\"ORYX.Plugins.ProcessLink\">\n      <requires namespace=\"http://b3mn.org/stencilset/bpmn1.1#\"/> \n    </plugin>\n      \n    <!-- following plugins don't require Ext -->\n    <plugin source=\"arrangement.js\" name=\"ORYX.Plugins.Arrangement\">\n      <notUsesIn namespace=\"http://b3mn.org/stencilset/xforms#\"/>\n    </plugin>\n    <plugin source=\"file.js\" name=\"ORYX.Plugins.Save\"/>\n    <plugin source=\"view.js\" name=\"ORYX.Plugins.View\" />\n    <plugin source=\"dragdropresize.js\" name=\"ORYX.Plugins.DragDropResize\" />\n    <plugin source=\"shapeHighlighting.js\" name=\"ORYX.Plugins.HighlightingSelectedShapes\" />\n    <plugin source=\"dragDocker.js\" name=\"ORYX.Plugins.DragDocker\">\n      <notUsesIn namespace=\"http://b3mn.org/stencilset/xforms#\" />\n    </plugin>   \n    <plugin source=\"addDocker.js\" name=\"ORYX.Plugins.AddDocker\">\n      <notUsesIn namespace=\"http://b3mn.org/stencilset/xforms#\" />\n    </plugin>\n    <plugin source=\"selectionframe.js\" name=\"ORYX.Plugins.SelectionFrame\">\n      <notUsesIn namespace=\"http://b3mn.org/stencilset/xforms#\" />\n    </plugin>\n    <plugin source=\"shapeHighlighting.js\" name=\"ORYX.Plugins.ShapeHighlighting\" />\n    <plugin source=\"overlay.js\" name=\"ORYX.Plugins.Overlay\" />    \n    <plugin source=\"keysMove.js\" name=\"ORYX.Plugins.KeysMove\" />\n    <plugin source=\"Layouter/edgeLayouter.js\" name=\"ORYX.Plugins.Layouter.EdgeLayouter\" />\n    \n    <!-- Begin: BPMN2.0 specific plugins -->\n    <plugin source=\"bpmn2.0/bpmn2.0.js\" name=\"ORYX.Plugins.BPMN2_0\">\n      <requires namespace=\"http://b3mn.org/stencilset/bpmn2.0#\" />\n    </plugin> \n    \n    <!-- End: BPMN2.0 specific plugins -->\n  </plugins>\n  \n  <properties>\n    <property group=\"File\" index=\"1\" />\n    <property group=\"Edit\" index=\"2\" /> \n    <property group=\"Undo\" index=\"3\" />\n    <property group=\"Alignment\" index=\"4\" />\n    <property group=\"Group\" index=\"5\" />\n    <property group=\"Z-Order\" index=\"6\" />\n    <property group=\"Docker\" index=\"7\" />\n    <property group=\"Zoom\" index=\"8\" /> \n  </properties>\n</config>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/popups/icon-template.html",
    "content": "<div class=\"ui-grid-cell-contents\">\n    <img ng-src=\"editor-app/stencilsets/bpmn2.0/icons/{{row.entity.icon}}\" />\n</div>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/popups/save-model.html",
    "content": "\n<div class=\"modal\" ng-controller=\"SaveModelCtrl\">\n    <div class=\"modal-dialog\">\n        <div class=\"modal-content\">\n        <div class=\"modal-header\">\n            <h2>{{'MODEL.SAVE.TITLE' | translate}}</h2>\n        </div>\n        <div class=\"modal-body\">\n\n        \t<div class=\"form-group\">\n           \t\t<label for=\"nameField\">{{'MODEL.NAME' | translate}}</label>\n        \t\t<input type=\"text\"\n                       ng-disabled=\"status.loading\"\n                       id=\"nameField\"\n                       class=\"form-control\"\n                       ng-model=\"saveDialog.name\"\n                       ui-keypress=\"{13:'save()'}\"\n                       auto-focus />\n        \t</div>\n        \t<div class=\"form-group\">\n           \t\t<label for=\"docTextArea\">{{'MODEL.DESCRIPTION' | translate}}</label>\n           \t\t<textarea id=\"docTextArea\" ng-disabled=\"status.loading\" class=\"form-control\" ng-model=\"saveDialog.description\"></textarea>\n        \t</div>\n        </div>\n        <div class=\"modal-footer\">\n        \n        \t<div class=\"pull-right\">\n            \t<button type=\"button\" class=\"btn\" ng-click=\"close()\" ng-disabled=\"status.loading\" translate>ACTION.CANCEL</button>\n            \t<button class=\"btn btn-primary\" ng-click=\"saveAndClose()\" ng-disabled=\"status.loading\" ng-show=\"!error\" translate>ACTION.SAVE-AND-CLOSE</button>\n            \t<button class=\"btn btn-primary\" ng-click=\"save()\" ng-disabled=\"status.loading\" ng-show=\"!error\" translate>ACTION.SAVE</button>\n            </div>\n        \n            <div class=\"pull-right popup-error\" ng-if=\"error && !error.isConflict\">\n                <span>{{'MODEL.SAVE.ERROR' | translate}}</span>\n            </div>\n        \n        \t<loading></loading>\n        \n        </div>\n    </div>\n</div>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/popups/select-shape.html",
    "content": "\n<div class=\"modal\" ng-controller=\"KisBpmShapeSelectionCtrl\">\n    <div class=\"modal-dialog\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header\">\n                <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\" ng-click=\"close()\">&times;</button>\n                <h2>Change shape to:</h2>\n            </div>\n            <div class=\"modal-body\">\n            \n                   <div class=\"kis-listener-grid\" ng-grid=\"gridOptions\"></div>\n            \n            </div>\n            <div class=\"modal-footer\">\n                <button ng-click=\"cancel()\" class=\"btn btn-primary\" translate>ACTION.CANCEL</button>\n                <button ng-click=\"select()\" class=\"btn btn-primary\" translate>ACTION.SELECT</button>\n            </div>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/popups/unsaved-changes.html",
    "content": "\n<div class=\"modal\" ng-controller=\"EditorUnsavedChangesPopupCrtl\">\n    <div class=\"modal-dialog\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header\">\n                <h2 translate=\"EDITOR.POPUP.UNSAVED-CHANGES.TITLE\"></h2>\n            </div>\n            <div class=\"modal-body\">\n            \t<p translate=\"EDITOR.POPUP.UNSAVED-CHANGES.DESCRIPTION\"></p>\n            </div>\n            <div class=\"modal-footer\">\n            \t<div class=\"pull-right\">\n                \t<button class=\"btn btn-danger\" ng-click=\"ok()\" translate=\"EDITOR.POPUP.UNSAVED-CHANGES.ACTION.DISCARD\"></button>\n                \t<button class=\"btn btn-default\" ng-click=\"cancel()\" translate=\"EDITOR.POPUP.UNSAVED-CHANGES.ACTION.CONTINUE\"></button>\n                </div>\n            \t<div class=\"loading pull-right\" ng-show=\"loading\">\n            \t\t<div class=\"l1\"></div><div class=\"l2\"></div><div class=\"l2\"></div>\n            \t</div>\n            </div>\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/select-shape-controller.js",
    "content": "/*\n * Activiti Modeler component part of the Activiti project\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * \n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n */\n\n/*\n * Controller for morph shape selection\n */\n\nvar KisBpmShapeSelectionCtrl = [ '$rootScope', '$scope', '$timeout', '$translate', function($rootScope, $scope, $timeout, $translate) {\n\n    $scope.selectedMorphShapes = [];\n    \n    $scope.availableMorphShapes = [];\n\n    for (var i = 0; i < $scope.morphShapes.length; i++)\n    {\n    \tif ($scope.morphShapes[i].id != $scope.currentSelectedShape.getStencil().idWithoutNs())\n    \t{\n    \t\t$scope.availableMorphShapes.push($scope.morphShapes[i]);\n    \t}\n    }\n    \t\n    // Config for grid\n    $scope.gridOptions = {\n        data: 'availableMorphShapes',\n        enableRowReordering: true,\n        headerRowHeight: 28,\n        multiSelect: false,\n        keepLastSelected : false,\n        selectedItems: $scope.selectedMorphShapes,\n        columnDefs: [{ field: 'objectId', displayName: 'Icon', width: 50, cellTemplate: 'editor-app/popups/icon-template.html?version=' + Date.now() },\n            { field: 'name', displayName: 'Name'}]\n    };\n\n    // Click handler for save button\n    $scope.select = function() {\n\n        if ($scope.selectedMorphShapes.length > 0) \n        {\n        \tvar MorphTo = ORYX.Core.Command.extend({\n    \t\t\tconstruct: function(shape, stencil, facade){\n    \t\t\t\tthis.shape = shape;\n    \t\t\t\tthis.stencil = stencil;\n    \t\t\t\tthis.facade = facade;\n    \t\t\t},\n    \t\t\texecute: function(){\n    \t\t\t\t\n    \t\t\t\tvar shape = this.shape;\n    \t\t\t\tvar stencil = this.stencil;\n    \t\t\t\tvar resourceId = shape.resourceId;\n    \t\t\t\t\n    \t\t\t\t// Serialize all attributes\n    \t\t\t\tvar serialized = shape.serialize();\n    \t\t\t\tstencil.properties().each((function(prop) {\n    \t\t\t\t\tif(prop.readonly()) {\n    \t\t\t\t\t\tserialized = serialized.reject(function(serProp) {\n    \t\t\t\t\t\t\treturn serProp.name==prop.id();\n    \t\t\t\t\t\t});\n    \t\t\t\t\t}\n    \t\t\t\t}).bind(this));\n    \t\t\n    \t\t\t\t// Get shape if already created, otherwise create a new shape\n    \t\t\t\tif (this.newShape){\n    \t\t\t\t\tnewShape = this.newShape;\n    \t\t\t\t\tthis.facade.getCanvas().add(newShape);\n    \t\t\t\t} else {\n    \t\t\t\t\tnewShape = this.facade.createShape({\n    \t\t\t\t\t\t\t\t\ttype: stencil.id(),\n    \t\t\t\t\t\t\t\t\tnamespace: stencil.namespace(),\n    \t\t\t\t\t\t\t\t\tresourceId: resourceId\n    \t\t\t\t\t\t\t\t});\n    \t\t\t\t}\n    \t\t\t\t\n    \t\t\t\t// calculate new bounds using old shape's upperLeft and new shape's width/height\n    \t\t\t\tvar boundsObj = serialized.find(function(serProp){\n    \t\t\t\t\treturn (serProp.prefix === \"oryx\" && serProp.name === \"bounds\");\n    \t\t\t\t});\n    \t\t\t\t\n    \t\t\t\tvar changedBounds = null;\n    \t\t\t\t\n    \t\t\t\tif (!this.facade.getRules().preserveBounds(shape.getStencil())) {\n    \t\t\t\t\t\n    \t\t\t\t\tvar bounds = boundsObj.value.split(\",\");\n    \t\t\t\t\tif (parseInt(bounds[0], 10) > parseInt(bounds[2], 10)) { // if lowerRight comes first, swap array items\n    \t\t\t\t\t\tvar tmp = bounds[0];\n    \t\t\t\t\t\tbounds[0] = bounds[2];\n    \t\t\t\t\t\tbounds[2] = tmp;\n    \t\t\t\t\t\ttmp = bounds[1];\n    \t\t\t\t\t\tbounds[1] = bounds[3];\n    \t\t\t\t\t\tbounds[3] = tmp;\n    \t\t\t\t\t}\n    \t\t\t\t\tbounds[2] = parseInt(bounds[0], 10) + newShape.bounds.width();\n    \t\t\t\t\tbounds[3] = parseInt(bounds[1], 10) + newShape.bounds.height();\n    \t\t\t\t\tboundsObj.value = bounds.join(\",\");\n    \t\t\t\t\t\n    \t\t\t\t}  else {\n    \t\t\t\t\t\n    \t\t\t\t\tvar height = shape.bounds.height();\n    \t\t\t\t\tvar width  = shape.bounds.width();\n    \t\t\t\t\t\n    \t\t\t\t\t// consider the minimum and maximum size of\n    \t\t\t\t\t// the new shape\n    \t\t\t\t\t\n    \t\t\t\t\tif (newShape.minimumSize) {\n    \t\t\t\t\t\tif (shape.bounds.height() < newShape.minimumSize.height) {\n    \t\t\t\t\t\t\theight = newShape.minimumSize.height;\n    \t\t\t\t\t\t}\n    \t\t\t\t\t\t\n    \t\t\t\t\t\t\n    \t\t\t\t\t\tif (shape.bounds.width() < newShape.minimumSize.width) {\n    \t\t\t\t\t\t\twidth = newShape.minimumSize.width;\n    \t\t\t\t\t\t}\n    \t\t\t\t\t}\n    \t\t\t\t\t\n    \t\t\t\t\tif(newShape.maximumSize) {\n    \t\t\t\t\t\tif(shape.bounds.height() > newShape.maximumSize.height) {\n    \t\t\t\t\t\t\theight = newShape.maximumSize.height;\n    \t\t\t\t\t\t}\t\n    \t\t\t\t\t\t\n    \t\t\t\t\t\tif(shape.bounds.width() > newShape.maximumSize.width) {\n    \t\t\t\t\t\t\twidth = newShape.maximumSize.width;\n    \t\t\t\t\t\t}\n    \t\t\t\t\t}\n    \t\t\t\t\t\n    \t\t\t\t\tchangedBounds = {\n    \t\t\t\t\t\ta : {\n    \t\t\t\t\t\t\tx: shape.bounds.a.x,\n    \t\t\t\t\t\t\ty: shape.bounds.a.y\n    \t\t\t\t\t\t},\n    \t\t\t\t\t\tb : {\n    \t\t\t\t\t\t\tx: shape.bounds.a.x + width,\n    \t\t\t\t\t\t\ty: shape.bounds.a.y + height\n    \t\t\t\t\t\t}\t\t\t\t\t\t\n    \t\t\t\t\t};\n    \t\t\t\t\t\n    \t\t\t\t}\n    \t\t\t\t\n    \t\t\t\tvar oPos = shape.bounds.center();\n    \t\t\t\tif(changedBounds !== null) {\n    \t\t\t\t\tnewShape.bounds.set(changedBounds);\n    \t\t\t\t}\n    \t\t\t\t\n    \t\t\t\t// Set all related dockers\n    \t\t\t\tthis.setRelatedDockers(shape, newShape);\n    \t\t\t\t\n    \t\t\t\t// store DOM position of old shape\n    \t\t\t\tvar parentNode = shape.node.parentNode;\n    \t\t\t\tvar nextSibling = shape.node.nextSibling;\n    \t\t\t\t\n    \t\t\t\t// Delete the old shape\n    \t\t\t\tthis.facade.deleteShape(shape);\n    \t\t\t\t\n    \t\t\t\t// Deserialize the new shape - Set all attributes\n    \t\t\t\tnewShape.deserialize(serialized);\n    \t\t\t\t/*\n    \t\t\t\t * Change color to default if unchanged\n    \t\t\t\t * 23.04.2010\n    \t\t\t\t */\n    \t\t\t\tif(shape.getStencil().property(\"oryx-bgcolor\") \n    \t\t\t\t\t\t&& shape.properties[\"oryx-bgcolor\"]\n    \t\t\t\t\t\t&& shape.getStencil().property(\"oryx-bgcolor\").value().toUpperCase()== shape.properties[\"oryx-bgcolor\"].toUpperCase()){\n    \t\t\t\t\t\tif(newShape.getStencil().property(\"oryx-bgcolor\")){\n    \t\t\t\t\t\t\tnewShape.setProperty(\"oryx-bgcolor\", newShape.getStencil().property(\"oryx-bgcolor\").value());\n    \t\t\t\t\t\t}\n    \t\t\t\t}\t\n    \t\t\t\tif(changedBounds !== null) {\n    \t\t\t\t\tnewShape.bounds.set(changedBounds);\n    \t\t\t\t}\n    \t\t\t\t\n    \t\t\t\tif(newShape.getStencil().type()===\"edge\" || (newShape.dockers.length==0 || !newShape.dockers[0].getDockedShape())) {\n    \t\t\t\t\tnewShape.bounds.centerMoveTo(oPos);\n    \t\t\t\t} \n    \t\t\t\t\n    \t\t\t\tif(newShape.getStencil().type()===\"node\" && (newShape.dockers.length==0 || !newShape.dockers[0].getDockedShape())) {\n    \t\t\t\t\tthis.setRelatedDockers(newShape, newShape);\n    \t\t\t\t\t\n    \t\t\t\t}\n    \t\t\t\t\n    \t\t\t\t// place at the DOM position of the old shape\n    \t\t\t\tif(nextSibling) parentNode.insertBefore(newShape.node, nextSibling);\n    \t\t\t\telse parentNode.appendChild(newShape.node);\n    \t\t\t\t\n    \t\t\t\t// Set selection\n    \t\t\t\tthis.facade.setSelection([newShape]);\n    \t\t\t\tthis.facade.getCanvas().update();\n    \t\t\t\tthis.facade.updateSelection();\n    \t\t\t\tthis.newShape = newShape;\n    \t\t\t\t\n    \t\t\t},\n    \t\t\trollback: function(){\n    \t\t\t\t\n    \t\t\t\tif (!this.shape || !this.newShape || !this.newShape.parent) {return;}\n    \t\t\t\t\n    \t\t\t\t// Append shape to the parent\n    \t\t\t\tthis.newShape.parent.add(this.shape);\n    \t\t\t\t// Set dockers\n    \t\t\t\tthis.setRelatedDockers(this.newShape, this.shape);\n    \t\t\t\t// Delete new shape\n    \t\t\t\tthis.facade.deleteShape(this.newShape);\n    \t\t\t\t// Set selection\n    \t\t\t\tthis.facade.setSelection([this.shape]);\n    \t\t\t\t// Update\n    \t\t\t\tthis.facade.getCanvas().update();\n    \t\t\t\tthis.facade.updateSelection();\n    \t\t\t},\n    \t\t\t\n    \t\t\t/**\n    \t\t\t * Set all incoming and outgoing edges from the shape to the new shape\n    \t\t\t * @param {Shape} shape\n    \t\t\t * @param {Shape} newShape\n    \t\t\t */\n    \t\t\tsetRelatedDockers: function(shape, newShape){\n    \t\t\t\t\n    \t\t\t\tif(shape.getStencil().type()===\"node\") {\n    \t\t\t\t\t\n    \t\t\t\t\t(shape.incoming||[]).concat(shape.outgoing||[])\n    \t\t\t\t\t\t.each(function(i) { \n    \t\t\t\t\t\t\ti.dockers.each(function(docker) {\n    \t\t\t\t\t\t\t\tif (docker.getDockedShape() == shape) {\n    \t\t\t\t\t\t\t\t\tvar rPoint = Object.clone(docker.referencePoint);\n    \t\t\t\t\t\t\t\t\t// Move reference point per percent\n\n    \t\t\t\t\t\t\t\t\tvar rPointNew = {\n    \t\t\t\t\t\t\t\t\t\tx: rPoint.x*newShape.bounds.width()/shape.bounds.width(),\n    \t\t\t\t\t\t\t\t\t\ty: rPoint.y*newShape.bounds.height()/shape.bounds.height()\n    \t\t\t\t\t\t\t\t\t};\n\n    \t\t\t\t\t\t\t\t\tdocker.setDockedShape(newShape);\n    \t\t\t\t\t\t\t\t\t// Set reference point and center to new position\n    \t\t\t\t\t\t\t\t\tdocker.setReferencePoint(rPointNew);\n    \t\t\t\t\t\t\t\t\tif(i instanceof ORYX.Core.Edge) {\n    \t\t\t\t\t\t\t\t\t\tdocker.bounds.centerMoveTo(rPointNew);\n    \t\t\t\t\t\t\t\t\t} else {\n    \t\t\t\t\t\t\t\t\t\tvar absXY = shape.absoluteXY();\n    \t\t\t\t\t\t\t\t\t\tdocker.bounds.centerMoveTo({x:rPointNew.x+absXY.x, y:rPointNew.y+absXY.y});\n    \t\t\t\t\t\t\t\t\t\t//docker.bounds.moveBy({x:rPointNew.x-rPoint.x, y:rPointNew.y-rPoint.y});\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\n    \t\t\t\t\t\t});\n    \t\t\t\t\t\n    \t\t\t\t\t// for attached events\n    \t\t\t\t\tif(shape.dockers.length>0&&shape.dockers.first().getDockedShape()) {\n    \t\t\t\t\t\tnewShape.dockers.first().setDockedShape(shape.dockers.first().getDockedShape());\n    \t\t\t\t\t\tnewShape.dockers.first().setReferencePoint(Object.clone(shape.dockers.first().referencePoint));\n    \t\t\t\t\t}\n    \t\t\t\t\n    \t\t\t\t} else { // is edge\n    \t\t\t\t\tnewShape.dockers.first().setDockedShape(shape.dockers.first().getDockedShape());\n    \t\t\t\t\tnewShape.dockers.first().setReferencePoint(shape.dockers.first().referencePoint);\n    \t\t\t\t\tnewShape.dockers.last().setDockedShape(shape.dockers.last().getDockedShape());\n    \t\t\t\t\tnewShape.dockers.last().setReferencePoint(shape.dockers.last().referencePoint);\n    \t\t\t\t}\n    \t\t\t}\n    \t\t});\n    \t\t\n        \tvar stencil = undefined;\n        \tvar stencilSets = $scope.editor.getStencilSets().values();\n        \t\n        \tvar stencilId = $scope.selectedMorphShapes[0].id;\n        \tif ($scope.selectedMorphShapes[0].genericTaskId)\n        \t{\n        \t\tstencilId = $scope.selectedMorphShapes[0].genericTaskId;\n        \t}\n        \t\n        \tfor (var i = 0; i < stencilSets.length; i++)\n        \t{\n        \t\tvar stencilSet = stencilSets[i];\n    \t\t\tvar nodes = stencilSet.nodes();\n    \t\t\tfor (var j = 0; j < nodes.length; j++)\n            \t{\n    \t\t\t\tif (nodes[j].idWithoutNs() === stencilId)\n    \t\t\t\t{\n    \t\t\t\t\tstencil = nodes[j];\n    \t\t\t\t\tbreak;\n    \t\t\t\t}\n            \t}\n        \t}\n        \t\n        \tif (!stencil) return;\n        \t\n    \t\t// Create and execute command (for undo/redo)\t\t\t\n    \t\tvar command = new MorphTo($scope.currentSelectedShape, stencil, $scope.editor);\n    \t\t$scope.editor.executeCommands([command]);\n        }\n\n        $scope.close();\n    };\n\n    $scope.cancel = function() {\n    \t$scope.$hide();\n    };\n\n    // Close button handler\n    $scope.close = function() {\n    \t$scope.$hide();\n    };\n\n}];"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/stencil-controller.js",
    "content": "/*\n * Activiti Modeler component part of the Activiti project\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * \n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n */\n'use strict';\n\nangular.module('activitiModeler')\n    .controller('StencilController', ['$rootScope', '$scope', '$http', '$modal', '$timeout', function ($rootScope, $scope, $http, $modal, $timeout) {\n\n        // Property window toggle state\n        $scope.propertyWindowState = {'collapsed': false};\n\n        // Add reference to global header-config\n        $scope.headerConfig = KISBPM.HEADER_CONFIG;\n\n        $scope.propertyWindowState.toggle = function () {\n            $scope.propertyWindowState.collapsed = !$scope.propertyWindowState.collapsed;\n            $timeout(function () {\n                jQuery(window).trigger('resize');\n            });\n        };\n        \n        // Code that is dependent on an initialised Editor is wrapped in a promise for the editor\n        $scope.editorFactory.promise.then(function () {\n        \t\n            /* Build stencil item list */\n\n            // Build simple json representation of stencil set\n            var stencilItemGroups = [];\n\n            // Helper method: find a group in an array\n            var findGroup = function (name, groupArray) {\n                for (var index = 0; index < groupArray.length; index++) {\n                    if (groupArray[index].name === name) {\n                        return groupArray[index];\n                    }\n                }\n                return null;\n            };\n\n            // Helper method: add a new group to an array of groups\n            var addGroup = function (groupName, groupArray) {\n                var group = { name: groupName, items: [], paletteItems: [], groups: [], visible: true };\n                groupArray.push(group);\n                return group;\n            };\n\n            /*\n             StencilSet items\n             */\n            $http({method: 'GET', url: KISBPM.URL.getStencilSet()}).success(function (data, status, headers, config) {\n\n            \tvar quickMenuDefinition = ['UserTask', 'EndNoneEvent', 'ExclusiveGateway', \n            \t                           'CatchTimerEvent', 'ThrowNoneEvent', 'TextAnnotation',\n            \t                           'SequenceFlow', 'Association'];\n            \tvar ignoreForPaletteDefinition = ['SequenceFlow', 'MessageFlow', 'Association', 'DataAssociation', 'DataStore', 'SendTask'];\n            \tvar quickMenuItems = [];\n            \t\n            \tvar morphRoles = [];\n                for (var i = 0; i < data.rules.morphingRules.length; i++) \n                {\n                    var role = data.rules.morphingRules[i].role;\n                    var roleItem = {'role': role, 'morphOptions': []};\n                    morphRoles.push(roleItem);\n                }\n            \t\n                // Check all received items\n                for (var stencilIndex = 0; stencilIndex < data.stencils.length; stencilIndex++) \n                {\n                \t// Check if the root group is the 'diagram' group. If so, this item should not be shown.\n                    var currentGroupName = data.stencils[stencilIndex].groups[0];\n                    if (currentGroupName === 'Diagram' || currentGroupName === 'Form') {\n                        continue;  // go to next item\n                    }\n                    \n                    var removed = false;\n                    if (data.stencils[stencilIndex].removed) {\n                        removed = true;\n                    }\n\n                    var currentGroup = undefined;\n                    if (!removed) {\n                        // Check if this group already exists. If not, we create a new one\n\n                        if (currentGroupName !== null && currentGroupName !== undefined && currentGroupName.length > 0) {\n\n                            currentGroup = findGroup(currentGroupName, stencilItemGroups); // Find group in root groups array\n                            if (currentGroup === null) {\n                                currentGroup = addGroup(currentGroupName, stencilItemGroups);\n                            }\n\n                            // Add all child groups (if any)\n                            for (var groupIndex = 1; groupIndex < data.stencils[stencilIndex].groups.length; groupIndex++) {\n                                var childGroupName = data.stencils[stencilIndex].groups[groupIndex];\n                                var childGroup = findGroup(childGroupName, currentGroup.groups);\n                                if (childGroup === null) {\n                                    childGroup = addGroup(childGroupName, currentGroup.groups);\n                                }\n\n                                // The current group variable holds the parent of the next group (if any),\n                                // and is basically the last element in the array of groups defined in the stencil item\n                                currentGroup = childGroup;\n\n                            }\n\n                        }\n                    }\n                    \n                    // Construct the stencil item\n                    var stencilItem = {'id': data.stencils[stencilIndex].id,\n                        'name': data.stencils[stencilIndex].title,\n                        'description': data.stencils[stencilIndex].description,\n                        'icon': data.stencils[stencilIndex].icon,\n                        'type': data.stencils[stencilIndex].type,\n                        'roles': data.stencils[stencilIndex].roles,\n                        'removed': removed,\n                        'customIcon': false,\n                        'canConnect': false,\n                        'canConnectTo': false,\n                        'canConnectAssociation': false};\n                    \n                    if (data.stencils[stencilIndex].customIconId && data.stencils[stencilIndex].customIconId > 0) {\n                        stencilItem.customIcon = true;\n                        stencilItem.icon = data.stencils[stencilIndex].customIconId;\n                    }\n                    \n                    if (!removed) {\n                        if (quickMenuDefinition.indexOf(stencilItem.id) >= 0) {\n                        \tquickMenuItems[quickMenuDefinition.indexOf(stencilItem.id)] = stencilItem;\n                        }\n                    }\n                    \n                    if (stencilItem.id === 'TextAnnotation' || stencilItem.id === 'BoundaryCompensationEvent') {\n                    \tstencilItem.canConnectAssociation = true;\n                    }\n                    \n                    for (var i = 0; i < data.stencils[stencilIndex].roles.length; i++) {\n                    \tvar stencilRole = data.stencils[stencilIndex].roles[i];\n                    \tif (stencilRole === 'sequence_start') {\n                    \t\tstencilItem.canConnect = true;\n                    \t} else if (stencilRole === 'sequence_end') {\n                    \t\tstencilItem.canConnectTo = true;\n                    \t}\n                    \t\n                    \tfor (var j = 0; j < morphRoles.length; j++) {\n                    \t\tif (stencilRole === morphRoles[j].role) {\n                    \t\t    if (!removed) {\n                    \t\t\t     morphRoles[j].morphOptions.push(stencilItem);\n                    \t\t\t}\n                    \t\t\tstencilItem.morphRole = morphRoles[j].role;\n                    \t\t\tbreak;\n                    \t\t}\n                    \t}\n                    }\n\n                    if (currentGroup) {\n\t                    // Add the stencil item to the correct group\n\t                    currentGroup.items.push(stencilItem);\n\t                    if (ignoreForPaletteDefinition.indexOf(stencilItem.id) < 0) {\n\t                    \tcurrentGroup.paletteItems.push(stencilItem);\n\t                    }\n\n                    } else {\n                        // It's a root stencil element\n                        if (!removed) {\n                            stencilItemGroups.push(stencilItem);\n                        }\n                    }\n                }\n                \n                for (var i = 0; i < stencilItemGroups.length; i++) \n                {\n                \tif (stencilItemGroups[i].paletteItems && stencilItemGroups[i].paletteItems.length == 0)\n                \t{\n                \t\tstencilItemGroups[i].visible = false;\n                \t}\n                }\n                \n                $scope.stencilItemGroups = stencilItemGroups;\n\n                var containmentRules = [];\n                for (var i = 0; i < data.rules.containmentRules.length; i++) \n                {\n                    var rule = data.rules.containmentRules[i];\n                    containmentRules.push(rule);\n                }\n                $scope.containmentRules = containmentRules;\n                \n                // remove quick menu items which are not available anymore due to custom pallette\n                var availableQuickMenuItems = [];\n                for (var i = 0; i < quickMenuItems.length; i++) \n                {\n                    if (quickMenuItems[i]) {\n                        availableQuickMenuItems[availableQuickMenuItems.length] = quickMenuItems[i];\n                    }\n                }\n                \n                $scope.quickMenuItems = availableQuickMenuItems;\n                $scope.morphRoles = morphRoles;\n            }).\n            \n            error(function (data, status, headers, config) {\n                console.log('Something went wrong when fetching stencil items:' + JSON.stringify(data));\n            });\n\n            /*\n             * Listen to selection change events: show properties\n             */\n            $scope.editor.registerOnEvent(ORYX.CONFIG.EVENT_SELECTION_CHANGED, function (event) {\n                var shapes = event.elements;\n                var canvasSelected = false;\n                if (shapes && shapes.length == 0) {\n                    shapes = [$scope.editor.getCanvas()];\n                    canvasSelected = true;\n                }\n                if (shapes && shapes.length > 0) {\n\n                    var selectedShape = shapes.first();\n                    var stencil = selectedShape.getStencil();\n                    \n                    if ($rootScope.selectedElementBeforeScrolling && stencil.id().indexOf('BPMNDiagram') !== -1)\n                    {\n                    \t// ignore canvas event because of empty selection when scrolling stops\n                    \treturn;\n                    }\n                    \n                    if ($rootScope.selectedElementBeforeScrolling && $rootScope.selectedElementBeforeScrolling.getId() === selectedShape.getId())\n                    {\n                    \t$rootScope.selectedElementBeforeScrolling = null;\n                    \treturn;\n                    }\n\n                    // Store previous selection\n                    $scope.previousSelectedShape = $scope.selectedShape;\n                    \n                    // Only do something if another element is selected (Oryx fires this event multiple times)\n                    if ($scope.selectedShape !== undefined && $scope.selectedShape.getId() === selectedShape.getId()) {\n                        if ($rootScope.forceSelectionRefresh) {\n                            // Switch the flag again, this run will force refresh\n                            $rootScope.forceSelectionRefresh = false;\n                        } else {\n                            // Selected the same element again, no need to update anything\n                            return;\n                        }\n                    }\n\n                    var selectedItem = {'title': '', 'properties': []};\n\n                    if (canvasSelected) {\n                        selectedItem.auditData = {\n                            'author': $scope.modelData.createdByUser,\n                            'createDate': $scope.modelData.createDate\n                        };\n                    }\n\n                    // Gather properties of selected item\n                    var properties = stencil.properties();\n                    for (var i = 0; i < properties.length; i++) {\n                        var property = properties[i];\n                        if (property.popular() == false) continue;\n                        var key = property.prefix() + \"-\" + property.id();\n\n                        if (key === 'oryx-name') {\n                            selectedItem.title = selectedShape.properties[key];\n                        }\n\n                        // First we check if there is a config for 'key-type' and then for 'type' alone\n                        var propertyConfig = KISBPM.PROPERTY_CONFIG[key + '-' + property.type()];\n                        if (propertyConfig === undefined || propertyConfig === null) {\n                            propertyConfig = KISBPM.PROPERTY_CONFIG[property.type()];\n                        }\n\n                        if (propertyConfig === undefined || propertyConfig === null) {\n                            console.log('WARNING: no property configuration defined for ' + key + ' of type ' + property.type());\n                        } else {\n\n                            if (selectedShape.properties[key] === 'true') {\n                                selectedShape.properties[key] = true;\n                            }\n                            \n                            if (KISBPM.CONFIG.showRemovedProperties == false && property.isHidden())\n                            {\n                            \tcontinue;\n                            }\n\n                            var currentProperty = {\n                                'key': key,\n                                'title': property.title(),\n                                'type': property.type(),\n                                'mode': 'read',\n                                'hidden': property.isHidden(),\n                                'value': selectedShape.properties[key]\n                            };\n                            \n                            if ((currentProperty.type === 'complex' || currentProperty.type === 'multiplecomplex') && currentProperty.value && currentProperty.value.length > 0) {\n                                try {\n                                    currentProperty.value = JSON.parse(currentProperty.value);\n                                } catch (err) {\n                                    // ignore\n                                }\n                            }\n\n                            if (propertyConfig.readModeTemplateUrl !== undefined && propertyConfig.readModeTemplateUrl !== null) {\n                                currentProperty.readModeTemplateUrl = propertyConfig.readModeTemplateUrl + '?version=' + $rootScope.staticIncludeVersion;\n                            }\n                            if (propertyConfig.writeModeTemplateUrl !== null && propertyConfig.writeModeTemplateUrl !== null) {\n                            \tcurrentProperty.writeModeTemplateUrl = propertyConfig.writeModeTemplateUrl + '?version=' + $rootScope.staticIncludeVersion;\n                            }\n\n                            if (propertyConfig.templateUrl !== undefined && propertyConfig.templateUrl !== null) {\n                                currentProperty.templateUrl = propertyConfig.templateUrl + '?version=' + $rootScope.staticIncludeVersion;\n                                currentProperty.hasReadWriteMode = false;\n                            }\n                            else {\n                                currentProperty.hasReadWriteMode = true;\n                            }\n\n                            if (currentProperty.value === undefined\n                                || currentProperty.value === null\n                                || currentProperty.value.length == 0) {\n                                currentProperty.noValue = true;\n                            }\n\n                            selectedItem.properties.push(currentProperty);\n                        }\n                    }\n\n                    // Need to wrap this in an $apply block, see http://jimhoskins.com/2012/12/17/angularjs-and-apply.html\n                    $scope.safeApply(function () {\n                        $scope.selectedItem = selectedItem;\n                        $scope.selectedShape = selectedShape;\n                    });\n\n                } else {\n                    $scope.safeApply(function () {\n                        $scope.selectedItem = {};\n                        $scope.selectedShape = null;\n                    });\n                }\n            });\n            \n            $scope.editor.registerOnEvent(ORYX.CONFIG.EVENT_SELECTION_CHANGED, function (event) {\n            \t\n            \tKISBPM.eventBus.dispatch(KISBPM.eventBus.EVENT_TYPE_HIDE_SHAPE_BUTTONS);\n            \tvar shapes = event.elements;\n                \n                if (shapes && shapes.length == 1) {\n\n                    var selectedShape = shapes.first();\n            \t\n                    var a = $scope.editor.getCanvas().node.getScreenCTM();\n        \t\t\t\n        \t\t\tvar absoluteXY = selectedShape.absoluteXY();\n        \t\t\t\n        \t\t\tabsoluteXY.x *= a.a;\n        \t\t\tabsoluteXY.y *= a.d;\n        \t\t\t\n        \t\t\tvar additionalIEZoom = 1;\n        \t\t\tif (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) {\n                        var ua = navigator.userAgent;\n                        if (ua.indexOf('MSIE') >= 0) {\n                            //IE 10 and below\n                            var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100);\n                            if (zoom !== 100) {\n                                additionalIEZoom = zoom / 100\n                            }\n                        }\n                    }\n                    \n        \t\t\tif (additionalIEZoom === 1) {\n        \t\t\t     absoluteXY.y = absoluteXY.y - jQuery(\"#canvasSection\").offset().top + 5;\n                         absoluteXY.x = absoluteXY.x - jQuery(\"#canvasSection\").offset().left;\n        \t\t\t\n        \t\t\t} else {\n        \t\t\t     var canvasOffsetLeft = jQuery(\"#canvasSection\").offset().left;\n        \t\t\t     var canvasScrollLeft = jQuery(\"#canvasSection\").scrollLeft();\n        \t\t\t     var canvasScrollTop = jQuery(\"#canvasSection\").scrollTop();\n        \t\t\t     \n        \t\t\t     var offset = a.e - (canvasOffsetLeft * additionalIEZoom);\n        \t\t\t     var additionaloffset = 0;\n        \t\t\t     if (offset > 10) {\n        \t\t\t         additionaloffset = (offset / additionalIEZoom) - offset;\n        \t\t\t     }\n        \t\t\t     absoluteXY.y = absoluteXY.y - (jQuery(\"#canvasSection\").offset().top * additionalIEZoom) + 5 + ((canvasScrollTop * additionalIEZoom) - canvasScrollTop);\n                         absoluteXY.x = absoluteXY.x - (canvasOffsetLeft * additionalIEZoom) + additionaloffset + ((canvasScrollLeft * additionalIEZoom) - canvasScrollLeft);\n                    }\n        \t\t\t\n        \t\t\tvar bounds = new ORYX.Core.Bounds(a.e + absoluteXY.x, a.f + absoluteXY.y, a.e + absoluteXY.x + a.a*selectedShape.bounds.width(), a.f + absoluteXY.y + a.d*selectedShape.bounds.height());\n        \t\t\tvar shapeXY = bounds.upperLeft();\n        \t\t\t\n        \t\t\tvar stencilItem = $scope.getStencilItemById(selectedShape.getStencil().idWithoutNs());\n        \t\t\tvar morphShapes = [];\n        \t\t\tif (stencilItem && stencilItem.morphRole)\n        \t\t\t{\n            \t\t\tfor (var i = 0; i < $scope.morphRoles.length; i++)\n            \t\t\t{\n            \t\t\t\tif ($scope.morphRoles[i].role === stencilItem.morphRole)\n        \t\t\t\t\t{\n        \t\t\t\t\t\tmorphShapes = $scope.morphRoles[i].morphOptions;\n        \t\t\t\t\t}\n            \t\t\t}\n            \t    }\n        \t\t\t\n        \t\t\tvar x = shapeXY.x;\n    \t\t\t\tif (bounds.width() < 48) {\n    \t\t\t\t\tx -= 24;\n    \t\t\t\t}\n        \t\t\t\n        \t\t\tif (morphShapes && morphShapes.length > 0) {\n        \t\t\t\t// In case the element is not wide enough, start the 2 bottom-buttons more to the left\n        \t\t\t\t// to prevent overflow in the right-menu\n\t        \t\t\tvar morphButton = document.getElementById('morph-button');\n\t        \t\t\tmorphButton.style.display = \"block\";\n\t        \t\t\tmorphButton.style.left = x + 24 +'px';\n\t        \t\t\tmorphButton.style.top = (shapeXY.y+bounds.height() + 2) + 'px';\n        \t\t\t}\n        \t\t\t\n        \t\t\tvar deleteButton = document.getElementById('delete-button');\n        \t\t\tdeleteButton.style.display = \"block\";\n        \t\t\tdeleteButton.style.left = x + 'px';\n        \t\t\tdeleteButton.style.top = (shapeXY.y+bounds.height() + 2) + 'px';\n        \t\t\t\n        \t\t\tif (stencilItem && (stencilItem.canConnect || stencilItem.canConnectAssociation)) {\n\t        \t\t\tvar quickButtonCounter = 0;\n\t        \t\t\tvar quickButtonX = shapeXY.x+bounds.width() + 5;\n\t        \t\t\tvar quickButtonY = shapeXY.y;\n\t        \t\t\tjQuery('.Oryx_button').each(function(i, obj) {\n\t        \t\t\t\tif (obj.id !== 'morph-button' && obj.id != 'delete-button') {\n\t        \t\t\t\t\tquickButtonCounter++;\n\t        \t\t\t\t\tif (quickButtonCounter > 3) {\n\t        \t\t\t\t\t\tquickButtonX = shapeXY.x+bounds.width() + 5;\n\t        \t\t\t\t\t\tquickButtonY += 24;\n\t        \t\t\t\t\t\tquickButtonCounter = 1;\n\t        \t\t\t\t\t\t\n\t        \t\t\t\t\t} else if (quickButtonCounter > 1) {\n\t        \t\t\t\t\t\tquickButtonX += 24;\n\t        \t\t\t\t\t}\n\t        \t\t\t\t\tobj.style.display = \"block\";\n\t        \t\t\t\t\tobj.style.left = quickButtonX + 'px';\n\t        \t\t\t\t\tobj.style.top = quickButtonY + 'px';\n\t        \t\t\t\t}\n\t        \t\t\t});\n        \t\t\t}\n                }\n            });\n\t        \n            if (!$rootScope.stencilInitialized) {\n\t            KISBPM.eventBus.addListener(KISBPM.eventBus.EVENT_TYPE_HIDE_SHAPE_BUTTONS, function (event) {\n\t\t            jQuery('.Oryx_button').each(function(i, obj) {\n\t\t            \tobj.style.display = \"none\";\n      \t\t\t\t});\n\t            });\n\n\t            /*\n\t             * Listen to property updates and act upon them\n\t             */\n\t            KISBPM.eventBus.addListener(KISBPM.eventBus.EVENT_TYPE_PROPERTY_VALUE_CHANGED, function (event) {\n\t                if (event.property && event.property.key) {\n\t                    // If the name property is been updated, we also need to change the title of the currently selected item\n\t                    if (event.property.key === 'oryx-name' && $scope.selectedItem !== undefined && $scope.selectedItem !== null) {\n\t                        $scope.selectedItem.title = event.newValue;\n\t                    }\n\n\t                    // Update \"no value\" flag\n\t                    event.property.noValue = (event.property.value === undefined\n\t                        || event.property.value === null\n\t                        || event.property.value.length == 0);\n\t                }\n\t            });\n\t            \n\t            $rootScope.stencilInitialized = true;\n            }\n            \n            $scope.morphShape = function() {\n            \t$scope.safeApply(function () {\n            \t\t\n            \t\tvar shapes = $rootScope.editor.getSelection();\n            \t\tif (shapes && shapes.length == 1)\n            \t\t{\n            \t\t\t$rootScope.currentSelectedShape = shapes.first();\n            \t\t\tvar stencilItem = $scope.getStencilItemById($rootScope.currentSelectedShape.getStencil().idWithoutNs());\n            \t\t\tvar morphShapes = [];\n            \t\t\tfor (var i = 0; i < $scope.morphRoles.length; i++)\n            \t\t\t{\n            \t\t\t\tif ($scope.morphRoles[i].role === stencilItem.morphRole)\n        \t\t\t\t\t{\n        \t\t\t\t\t\tmorphShapes = $scope.morphRoles[i].morphOptions.slice();\n        \t\t\t\t\t}\n            \t\t\t}\n\n            \t\t\t// Method to open shape select dialog (used later on)\n                        var showSelectShapeDialog = function()\n                        {\n                            $rootScope.morphShapes = morphShapes;\n                            $modal({\n                                backdrop: false,\n                                keyboard: true,\n                                template: 'editor-app/popups/select-shape.html?version=' + Date.now()\n                            });\n                        };\n\n                        showSelectShapeDialog();\n            \t\t}\n            \t});\n            };\n            \n            $scope.deleteShape = function() {\n              KISBPM.TOOLBAR.ACTIONS.deleteItem({'$scope': $scope});\n            };\n            \n            $scope.quickAddItem = function(newItemId) {\n            \t$scope.safeApply(function () {\n            \t\t\n            \t\tvar shapes = $rootScope.editor.getSelection();\n            \t\tif (shapes && shapes.length == 1)\n            \t\t{\n            \t\t\t$rootScope.currentSelectedShape = shapes.first();\n            \t\t\t\n            \t\t\tvar containedStencil = undefined;\n                    \tvar stencilSets = $scope.editor.getStencilSets().values();\n                    \tfor (var i = 0; i < stencilSets.length; i++)\n                    \t{\n                    \t\tvar stencilSet = stencilSets[i];\n                \t\t\tvar nodes = stencilSet.nodes();\n                \t\t\tfor (var j = 0; j < nodes.length; j++)\n                        \t{\n                \t\t\t\tif (nodes[j].idWithoutNs() === newItemId)\n                \t\t\t\t{\n                \t\t\t\t\tcontainedStencil = nodes[j];\n                \t\t\t\t\tbreak;\n                \t\t\t\t}\n                        \t}\n                    \t}\n                    \t\n                    \tif (!containedStencil) return;\n            \t\t\t\n            \t\t\tvar option = {type: $scope.currentSelectedShape.getStencil().namespace() + newItemId, namespace: $scope.currentSelectedShape.getStencil().namespace()};\n            \t\t\toption['connectedShape'] = $rootScope.currentSelectedShape;\n            \t\t\toption['parent'] = $rootScope.currentSelectedShape.parent;\n            \t\t\toption['containedStencil'] = containedStencil;\n            \t\t\n            \t\t\tvar args = { sourceShape: $rootScope.currentSelectedShape, targetStencil: containedStencil };\n            \t\t\tvar targetStencil = $scope.editor.getRules().connectMorph(args);\n            \t\t\tif (!targetStencil){ return; }// Check if there can be a target shape\n            \t\t\toption['connectingType'] = targetStencil.id();\n\n            \t\t\tvar command = new KISBPM.CreateCommand(option, undefined, undefined, $scope.editor);\n            \t\t\n            \t\t\t$scope.editor.executeCommands([command]);\n            \t\t}\n            \t});\n            };\n\n        }); // end of $scope.editorFactory.promise block\n\n        /* Click handler for clicking a property */\n        $scope.propertyClicked = function (index) {\n            if (!$scope.selectedItem.properties[index].hidden) {\n                $scope.selectedItem.properties[index].mode = \"write\";\n            }\n        };\n\n        /* Helper method to retrieve the template url for a property */\n        $scope.getPropertyTemplateUrl = function (index) {\n            return $scope.selectedItem.properties[index].templateUrl;\n        };\n        $scope.getPropertyReadModeTemplateUrl = function (index) {\n            return $scope.selectedItem.properties[index].readModeTemplateUrl;\n        };\n        $scope.getPropertyWriteModeTemplateUrl = function (index) {\n            return $scope.selectedItem.properties[index].writeModeTemplateUrl;\n        };\n\n        /* Method available to all sub controllers (for property controllers) to update the internal Oryx model */\n        $scope.updatePropertyInModel = function (property, shapeId) {\n\n            var shape = $scope.selectedShape;\n            // Some updates may happen when selected shape is already changed, so when an additional\n            // shapeId is supplied, we need to make sure the correct shape is updated (current or previous)\n            if (shapeId) {\n                if (shape.id != shapeId && $scope.previousSelectedShape && $scope.previousSelectedShape.id == shapeId) {\n                    shape = $scope.previousSelectedShape;\n                } else {\n                    shape = null;\n                }\n            }\n\n            if (!shape) {\n                // When no shape is selected, or no shape is found for the alternative\n                // shape ID, do nothing\n                return;\n            }\n            var key = property.key;\n            var newValue = property.value;\n            var oldValue = shape.properties[key];\n\n            if (newValue != oldValue) {\n                var commandClass = ORYX.Core.Command.extend({\n                    construct: function () {\n                        this.key = key;\n                        this.oldValue = oldValue;\n                        this.newValue = newValue;\n                        this.shape = shape;\n                        this.facade = $scope.editor;\n                    },\n                    execute: function () {\n                        this.shape.setProperty(this.key, this.newValue);\n                        this.facade.getCanvas().update();\n                        this.facade.updateSelection();\n                    },\n                    rollback: function () {\n                        this.shape.setProperty(this.key, this.oldValue);\n                        this.facade.getCanvas().update();\n                        this.facade.updateSelection();\n                    }\n                });\n                // Instantiate the class\n                var command = new commandClass();\n\n                // Execute the command\n                $scope.editor.executeCommands([command]);\n                $scope.editor.handleEvents({\n                    type: ORYX.CONFIG.EVENT_PROPWINDOW_PROP_CHANGED,\n                    elements: [shape],\n                    key: key\n                });\n\n                // Switch the property back to read mode, now the update is done\n                property.mode = 'read';\n\n                // Fire event to all who is interested\n                // Fire event to all who want to know about this\n                var event = {\n                    type: KISBPM.eventBus.EVENT_TYPE_PROPERTY_VALUE_CHANGED,\n                    property: property,\n                    oldValue: oldValue,\n                    newValue: newValue\n                };\n                KISBPM.eventBus.dispatch(event.type, event);\n            } else {\n                // Switch the property back to read mode, no update was needed\n                property.mode = 'read';\n            }\n\n        };\n\n        /**\n         * Helper method that searches a group for an item with the given id.\n         * If not found, will return undefined.\n         */\n        $scope.findStencilItemInGroup = function (stencilItemId, group) {\n\n            var item;\n\n            // Check all items directly in this group\n            for (var j = 0; j < group.items.length; j++) {\n                item = group.items[j];\n                if (item.id === stencilItemId) {\n                    return item;\n                }\n            }\n\n            // Check the child groups\n            if (group.groups && group.groups.length > 0) {\n                for (var k = 0; k < group.groups.length; k++) {\n                    item = $scope.findStencilItemInGroup(stencilItemId, group.groups[k]);\n                    if (item) {\n                        return item;\n                    }\n                }\n            }\n\n            return undefined;\n        };\n\n        /**\n         * Helper method to find a stencil item.\n         */\n        $scope.getStencilItemById = function (stencilItemId) {\n            for (var i = 0; i < $scope.stencilItemGroups.length; i++) {\n                var element = $scope.stencilItemGroups[i];\n\n                // Real group\n                if (element.items !== null && element.items !== undefined) {\n                    var item = $scope.findStencilItemInGroup(stencilItemId, element);\n                    if (item) {\n                        return item;\n                    }\n                } else { // Root stencil item\n                    if (element.id === stencilItemId) {\n                        return element;\n                    }\n                }\n            }\n            return undefined;\n        };\n\n        /*\n         * DRAG AND DROP FUNCTIONALITY\n         */\n\n        $scope.dropCallback = function (event, ui) {\n        \t\n            $scope.editor.handleEvents({\n                type: ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,\n                highlightId: \"shapeRepo.attached\"\n            });\n            $scope.editor.handleEvents({\n                type: ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,\n                highlightId: \"shapeRepo.added\"\n            });\n            \n            $scope.editor.handleEvents({\n                type: ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,\n                highlightId: \"shapeMenu\"\n            });\n            \n            KISBPM.eventBus.dispatch(KISBPM.eventBus.EVENT_TYPE_HIDE_SHAPE_BUTTONS);\n\n            if ($scope.dragCanContain) {\n\n            \tvar item = $scope.getStencilItemById(ui.draggable[0].id);\n            \t\n            \tvar pos = {x: event.pageX, y: event.pageY};\n            \t\n            \tvar additionalIEZoom = 1;\n                if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) {\n                    var ua = navigator.userAgent;\n                    if (ua.indexOf('MSIE') >= 0) {\n                        //IE 10 and below\n                        var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100);\n                        if (zoom !== 100) {\n                            additionalIEZoom = zoom / 100;\n                        }\n                    }\n                }\n            \t\n                var screenCTM = $scope.editor.getCanvas().node.getScreenCTM();\n\n                // Correcting the UpperLeft-Offset\n                pos.x -= (screenCTM.e / additionalIEZoom);\n                pos.y -= (screenCTM.f / additionalIEZoom);\n                // Correcting the Zoom-Factor\n                pos.x /= screenCTM.a;\n                pos.y /= screenCTM.d;\n                \n                // Correcting the ScrollOffset\n                pos.x -= document.documentElement.scrollLeft;\n                pos.y -= document.documentElement.scrollTop;\n                \n                var parentAbs = $scope.dragCurrentParent.absoluteXY();\n                pos.x -= parentAbs.x;\n                pos.y -= parentAbs.y;\n\n                var containedStencil = undefined;\n                var stencilSets = $scope.editor.getStencilSets().values();\n                for (var i = 0; i < stencilSets.length; i++)\n                {\n                    var stencilSet = stencilSets[i];\n                    var nodes = stencilSet.nodes();\n                    for (var j = 0; j < nodes.length; j++)\n                    {\n                        if (nodes[j].idWithoutNs() === ui.draggable[0].id)\n                        {\n                            containedStencil = nodes[j];\n                            break;\n                        }\n                    }\n\n                    if (!containedStencil)\n                    {\n                        var edges = stencilSet.edges();\n                        for (var j = 0; j < edges.length; j++)\n                        {\n                            if (edges[j].idWithoutNs() === ui.draggable[0].id)\n                            {\n                                containedStencil = edges[j];\n                                break;\n                            }\n                        }\n                    }\n                }\n\n                if (!containedStencil) return;\n\n            \tif ($scope.quickMenu)\n            \t{\n            \t\tvar shapes = $scope.editor.getSelection();\n            \t\tif (shapes && shapes.length == 1)\n            \t\t{\n            \t\t\tvar currentSelectedShape = shapes.first();\n\n\t        \t\t\tvar option = {};\n\t        \t\t\toption.type = currentSelectedShape.getStencil().namespace() + ui.draggable[0].id;\n\t        \t\t\toption.namespace = currentSelectedShape.getStencil().namespace();\n\t        \t\t\toption.connectedShape = currentSelectedShape;\n\t        \t\t\toption.parent = $scope.dragCurrentParent;\n\t        \t\t\toption.containedStencil = containedStencil;\n\t        \t\t\t\n\t        \t\t\t// If the ctrl key is not pressed, \n\t        \t\t\t// snapp the new shape to the center \n\t        \t\t\t// if it is near to the center of the other shape\n\t        \t\t\tif (!event.ctrlKey){\n\t        \t\t\t\t// Get the center of the shape\n\t        \t\t\t\tvar cShape = currentSelectedShape.bounds.center();\n\t        \t\t\t\t// Snapp +-20 Pixel horizontal to the center \n\t        \t\t\t\tif (20 > Math.abs(cShape.x - pos.x)){\n\t        \t\t\t\t\tpos.x = cShape.x;\n\t        \t\t\t\t}\n\t        \t\t\t\t// Snapp +-20 Pixel vertical to the center \n\t        \t\t\t\tif (20 > Math.abs(cShape.y - pos.y)){\n\t        \t\t\t\t\tpos.y = cShape.y;\n\t        \t\t\t\t}\n\t        \t\t\t}\n\t        \t\t\t\n\t        \t\t\toption.position = pos;\n\t        \t\t\n\t        \t\t\tif (containedStencil.idWithoutNs() !== 'SequenceFlow' && containedStencil.idWithoutNs() !== 'Association' && \n\t        \t\t\t        containedStencil.idWithoutNs() !== 'MessageFlow' && containedStencil.idWithoutNs() !== 'DataAssociation')\n\t        \t\t\t{\n\t\t        \t\t\tvar args = { sourceShape: currentSelectedShape, targetStencil: containedStencil };\n\t\t        \t\t\tvar targetStencil = $scope.editor.getRules().connectMorph(args);\n\t\t        \t\t\tif (!targetStencil){ return; }// Check if there can be a target shape\n\t\t        \t\t\toption.connectingType = targetStencil.id();\n\t        \t\t\t}\n\t\n\t        \t\t\tvar command = new KISBPM.CreateCommand(option, $scope.dropTargetElement, pos, $scope.editor);\n\t        \t\t\n\t        \t\t\t$scope.editor.executeCommands([command]);\n            \t\t}\n            \t}\n            \telse\n            \t{\n                    var canAttach = false;\n                    if (containedStencil.idWithoutNs() === 'BoundaryErrorEvent' || containedStencil.idWithoutNs() === 'BoundaryTimerEvent' ||\n                        containedStencil.idWithoutNs() === 'BoundarySignalEvent' || containedStencil.idWithoutNs() === 'BoundaryMessageEvent' ||\n                        containedStencil.idWithoutNs() === 'BoundaryCancelEvent' || containedStencil.idWithoutNs() === 'BoundaryCompensationEvent') {\n                        // Modify position, otherwise boundary event will get position related to left corner of the canvas instead of the container\n                        pos = $scope.editor.eventCoordinates( event );\n                        canAttach = true;\n                    }\n\n                    var option = {};\n                    option['type'] = $scope.modelData.model.stencilset.namespace + item.id;\n                    option['namespace'] = $scope.modelData.model.stencilset.namespace;\n                    option['position'] = pos;\n                    option['parent'] = $scope.dragCurrentParent;\n\n                    var commandClass = ORYX.Core.Command.extend({\n                        construct: function(option, dockedShape, canAttach, position, facade){\n                            this.option = option;\n                            this.docker = null;\n                            this.dockedShape = dockedShape;\n                            this.dockedShapeParent = dockedShape.parent || facade.getCanvas();\n                            this.position = position;\n                            this.facade\t= facade;\n                            this.selection = this.facade.getSelection();\n                            this.shape = null;\n                            this.parent = null;\n                            this.canAttach = canAttach;\n                        },\n                        execute: function(){\n                            if (!this.shape) {\n                                this.shape = this.facade.createShape(option);\n                                this.parent = this.shape.parent;\n                            } else if (this.parent) {\n                                this.parent.add(this.shape);\n                            }\n\n                            if (this.canAttach && this.shape.dockers && this.shape.dockers.length) {\n                                this.docker = this.shape.dockers[0];\n\n                                this.dockedShapeParent.add(this.docker.parent);\n\n                                // Set the Docker to the new Shape\n                                this.docker.setDockedShape(undefined);\n                                this.docker.bounds.centerMoveTo(this.position);\n                                if (this.dockedShape !== this.facade.getCanvas()) {\n                                    this.docker.setDockedShape(this.dockedShape);\n                                }\n                                this.facade.setSelection( [this.docker.parent] );\n                            }\n\n                            this.facade.getCanvas().update();\n                            this.facade.updateSelection();\n\n                        },\n                        rollback: function(){\n                            if (this.shape) {\n                                this.facade.setSelection(this.selection.without(this.shape));\n                                this.facade.deleteShape(this.shape);\n                            }\n                            if (this.canAttach && this.docker) {\n                                this.docker.setDockedShape(undefined);\n                            }\n                            this.facade.getCanvas().update();\n                            this.facade.updateSelection();\n\n                        }\n                    });\n\n                    // Update canvas\n                    var command = new commandClass(option, $scope.dragCurrentParent, canAttach, pos, $scope.editor);\n                    $scope.editor.executeCommands([command]);\n\n                    // Fire event to all who want to know about this\n                    var dropEvent = {\n                        type: KISBPM.eventBus.EVENT_TYPE_ITEM_DROPPED,\n                        droppedItem: item,\n                        position: pos\n                    };\n                    KISBPM.eventBus.dispatch(dropEvent.type, dropEvent);\n                }\n            }\n\n            $scope.dragCurrentParent = undefined;\n            $scope.dragCurrentParentId = undefined;\n            $scope.dragCurrentParentStencil = undefined;\n            $scope.dragCanContain = undefined;\n            $scope.quickMenu = undefined;\n            $scope.dropTargetElement = undefined;\n        };\n\n\n        $scope.overCallback = function (event, ui) {\n            $scope.dragModeOver = true;\n        };\n\n        $scope.outCallback = function (event, ui) {\n            $scope.dragModeOver = false;\n        };\n\n        $scope.startDragCallback = function (event, ui) {\n            $scope.dragModeOver = false;\n            $scope.quickMenu = false;\n            if (!ui.helper.hasClass('stencil-item-dragged')) {\n                ui.helper.addClass('stencil-item-dragged');\n            }\n        };\n        \n        $scope.startDragCallbackQuickMenu = function (event, ui) {\n            $scope.dragModeOver = false;\n            $scope.quickMenu = true;\n        };\n        \n        $scope.dragCallback = function (event, ui) {\n        \t\n            if ($scope.dragModeOver != false) {\n            \t\n                var coord = $scope.editor.eventCoordinatesXY(event.pageX, event.pageY);\n                \n                var additionalIEZoom = 1;\n                if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) {\n                    var ua = navigator.userAgent;\n                    if (ua.indexOf('MSIE') >= 0) {\n                        //IE 10 and below\n                        var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100);\n                        if (zoom !== 100) {\n                            additionalIEZoom = zoom / 100\n                        }\n                    }\n                }\n                \n                if (additionalIEZoom !== 1) {\n                     coord.x = coord.x / additionalIEZoom;\n                     coord.y = coord.y / additionalIEZoom;\n                }\n                \n                var aShapes = $scope.editor.getCanvas().getAbstractShapesAtPosition(coord);\n                \n                if (aShapes.length <= 0) {\n                    if (event.helper) {\n                        $scope.dragCanContain = false;\n                        return false;\n                    }\n                }\n\n                if (aShapes[0] instanceof ORYX.Core.Canvas) {\n                    $scope.editor.getCanvas().setHightlightStateBasedOnX(coord.x);\n                }\n\n                if (aShapes.length == 1 && aShapes[0] instanceof ORYX.Core.Canvas)\n                {\n                    var parentCandidate = aShapes[0];\n\n                    $scope.dragCanContain = true;\n                    $scope.dragCurrentParent = parentCandidate;\n                    $scope.dragCurrentParentId = parentCandidate.id;\n\n                    $scope.editor.handleEvents({\n                        type: ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,\n                        highlightId: \"shapeRepo.attached\"\n                    });\n                    $scope.editor.handleEvents({\n                        type: ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,\n                        highlightId: \"shapeRepo.added\"\n                    });\n                    return false;\n                }\n                else \n                {\n                    var item = $scope.getStencilItemById(event.target.id);\n                    \n                    var parentCandidate = aShapes.reverse().find(function (candidate) {\n                        return (candidate instanceof ORYX.Core.Canvas\n                            || candidate instanceof ORYX.Core.Node\n                            || candidate instanceof ORYX.Core.Edge);\n                    });\n                    \n                    if (!parentCandidate) {\n                        $scope.dragCanContain = false;\n                        return false;\n                    }\n                    \n                    if (item.type === \"node\") {\n                        \n                        // check if the draggable is a boundary event and the parent an Activity\n                        var _canContain = false;\n                        var parentStencilId = parentCandidate.getStencil().id();\n\n                        if ($scope.dragCurrentParentId && $scope.dragCurrentParentId === parentCandidate.id) {\n                            return false;\n                        }\n\n                        var parentItem = $scope.getStencilItemById(parentCandidate.getStencil().idWithoutNs());\n                        if (parentItem.roles.indexOf(\"Activity\") > -1) {\n                            if (item.roles.indexOf(\"IntermediateEventOnActivityBoundary\") > -1) {\n                                _canContain = true;\n                            }\n                        }\n                        else if (parentCandidate.getStencil().idWithoutNs() === 'Pool')\n                        {\n                        \tif (item.id === 'Lane')\n                        \t{\n                        \t\t_canContain = true;\n                        \t}\n                        }\n                        \n                        if (_canContain)\n                        {\n                        \t$scope.editor.handleEvents({\n                                type: ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW,\n                                highlightId: \"shapeRepo.attached\",\n                                elements: [parentCandidate],\n                                style: ORYX.CONFIG.SELECTION_HIGHLIGHT_STYLE_RECTANGLE,\n                                color: ORYX.CONFIG.SELECTION_VALID_COLOR\n                            });\n\n                            $scope.editor.handleEvents({\n                                type: ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,\n                                highlightId: \"shapeRepo.added\"\n                            });\n                        }\n                        else\n                        {\n                            for (var i = 0; i < $scope.containmentRules.length; i++) {\n                                var rule = $scope.containmentRules[i];\n                                if (rule.role === parentItem.id) {\n                                    for (var j = 0; j < rule.contains.length; j++) {\n                                        if (item.roles.indexOf(rule.contains[j]) > -1) {\n                                            _canContain = true;\n                                            break;\n                                        }\n                                    }\n\n                                    if (_canContain) {\n                                        break;\n                                    }\n                                }\n                            }\n\n                            // Show Highlight\n                            $scope.editor.handleEvents({\n                                type: ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW,\n                                highlightId: 'shapeRepo.added',\n                                elements: [parentCandidate],\n                                color: _canContain ? ORYX.CONFIG.SELECTION_VALID_COLOR : ORYX.CONFIG.SELECTION_INVALID_COLOR\n                            });\n\n                            $scope.editor.handleEvents({\n                                type: ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,\n                                highlightId: \"shapeRepo.attached\"\n                            });\n                        }\n\n                        $scope.dragCurrentParent = parentCandidate;\n                        $scope.dragCurrentParentId = parentCandidate.id;\n                        $scope.dragCurrentParentStencil = parentStencilId;\n                        $scope.dragCanContain = _canContain;\n                        \n                    } else  { \n                    \tvar canvasCandidate = $scope.editor.getCanvas();\n                    \tvar canConnect = false;\n                    \t\n                    \tvar targetStencil = $scope.getStencilItemById(parentCandidate.getStencil().idWithoutNs());\n            \t\t\tif (targetStencil) {\n            \t\t\t\tvar associationConnect = false;\n            \t\t\t\tif (stencil.idWithoutNs() === 'Association' && (curCan.getStencil().idWithoutNs() === 'TextAnnotation' || curCan.getStencil().idWithoutNs() === 'BoundaryCompensationEvent')) {\n            \t\t\t\t    associationConnect = true;\n            \t\t\t\t} else if (stencil.idWithoutNs() === 'DataAssociation' && curCan.getStencil().idWithoutNs() === 'DataStore') {\n                                associationConnect = true;\n                            }\n            \t\t\t\t\n            \t\t\t\tif (targetStencil.canConnectTo || associationConnect) {\n            \t\t\t\t\tcanConnect = true;\n            \t\t\t\t}\n            \t\t\t}\n                    \t\n                    \t//Edge\n                    \t$scope.dragCurrentParent = canvasCandidate;\n                    \t$scope.dragCurrentParentId = canvasCandidate.id;\n                        $scope.dragCurrentParentStencil = canvasCandidate.getStencil().id();\n                        $scope.dragCanContain = canConnect;\n                        \n                    \t// Show Highlight\n                        $scope.editor.handleEvents({\n                            type: ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW,\n                            highlightId: 'shapeRepo.added',\n                            elements: [canvasCandidate],\n                            color: ORYX.CONFIG.SELECTION_VALID_COLOR\n                        });\n\n                        $scope.editor.handleEvents({\n                            type: ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,\n                            highlightId: \"shapeRepo.attached\"\n                        });\n        \t\t\t}\n                }\n            }\n        };\n        \n        $scope.dragCallbackQuickMenu = function (event, ui) {\n        \t\n            if ($scope.dragModeOver != false) {\n                var coord = $scope.editor.eventCoordinatesXY(event.pageX, event.pageY);\n                \n                var additionalIEZoom = 1;\n                if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) {\n                    var ua = navigator.userAgent;\n                    if (ua.indexOf('MSIE') >= 0) {\n                        //IE 10 and below\n                        var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100);\n                        if (zoom !== 100) {\n                            additionalIEZoom = zoom / 100\n                        }\n                    }\n                }\n                \n                if (additionalIEZoom !== 1) {\n                     coord.x = coord.x / additionalIEZoom;\n                     coord.y = coord.y / additionalIEZoom;\n                }\n                \n                var aShapes = $scope.editor.getCanvas().getAbstractShapesAtPosition(coord);\n               \n                if (aShapes.length <= 0) {\n                    if (event.helper) {\n                        $scope.dragCanContain = false;\n                        return false;\n                    }\n                }\n\n                if (aShapes[0] instanceof ORYX.Core.Canvas) {\n                    $scope.editor.getCanvas().setHightlightStateBasedOnX(coord.x);\n                }\n                \n        \t\tvar stencil = undefined;\n            \tvar stencilSets = $scope.editor.getStencilSets().values();\n            \tfor (var i = 0; i < stencilSets.length; i++)\n            \t{\n            \t\tvar stencilSet = stencilSets[i];\n        \t\t\tvar nodes = stencilSet.nodes();\n        \t\t\tfor (var j = 0; j < nodes.length; j++)\n                \t{\n        \t\t\t\tif (nodes[j].idWithoutNs() === event.target.id)\n        \t\t\t\t{\n        \t\t\t\t\tstencil = nodes[j];\n        \t\t\t\t\tbreak;\n        \t\t\t\t}\n                \t}\n        \t\t\t\n        \t\t\tif (!stencil)\n        \t\t\t{\n        \t\t\t\tvar edges = stencilSet.edges();\n            \t\t\tfor (var j = 0; j < edges.length; j++)\n                    \t{\n            \t\t\t\tif (edges[j].idWithoutNs() === event.target.id)\n            \t\t\t\t{\n            \t\t\t\t\tstencil = edges[j];\n            \t\t\t\t\tbreak;\n            \t\t\t\t}\n                    \t}\n        \t\t\t}\n            \t}\n        \t\t\n                var candidate = aShapes.last();\n                \n                var isValid = false;\n                if (stencil.type() === \"node\") \n                {\n    \t\t\t\t//check containment rules\n    \t\t\t\tvar canContain = $scope.editor.getRules().canContain({containingShape:candidate, containedStencil:stencil});\n    \t\t\t\t\n    \t\t\t\tvar parentCandidate = aShapes.reverse().find(function (candidate) {\n                        return (candidate instanceof ORYX.Core.Canvas\n                            || candidate instanceof ORYX.Core.Node\n                            || candidate instanceof ORYX.Core.Edge);\n                    });\n\n                    if (!parentCandidate) {\n                        $scope.dragCanContain = false;\n                        return false;\n                    }\n    \t\t\t\t\n    \t\t\t\t$scope.dragCurrentParent = parentCandidate;\n                    $scope.dragCurrentParentId = parentCandidate.id;\n                    $scope.dragCurrentParentStencil = parentCandidate.getStencil().id();\n                    $scope.dragCanContain = canContain;\n                    $scope.dropTargetElement = parentCandidate;\n                    isValid = canContain;\n    \t\n    \t\t\t} else { //Edge\n    \t\t\t\n    \t\t\t\tvar shapes = $scope.editor.getSelection();\n            \t\tif (shapes && shapes.length == 1)\n            \t\t{\n            \t\t\tvar currentSelectedShape = shapes.first();\n            \t\t\tvar curCan = candidate;\n            \t\t\tvar canConnect = false;\n            \t\t\t\n            \t\t\tvar targetStencil = $scope.getStencilItemById(curCan.getStencil().idWithoutNs());\n            \t\t\tif (targetStencil)\n            \t\t\t{\n            \t\t\t\tvar associationConnect = false;\n            \t\t\t\tif (stencil.idWithoutNs() === 'Association' && (curCan.getStencil().idWithoutNs() === 'TextAnnotation' || curCan.getStencil().idWithoutNs() === 'BoundaryCompensationEvent'))  \n            \t\t\t\t{\n            \t\t\t\t\tassociationConnect = true;\n            \t\t\t\t}\n            \t\t\t\telse if (stencil.idWithoutNs() === 'DataAssociation' && curCan.getStencil().idWithoutNs() === 'DataStore')\n            \t\t\t\t{\n            \t\t\t\t    associationConnect = true;\n            \t\t\t\t}\n            \t\t\t\t\n            \t\t\t\tif (targetStencil.canConnectTo || associationConnect)\n\t            \t\t\t{\n\t\t        \t\t\t\twhile (!canConnect && curCan && !(curCan instanceof ORYX.Core.Canvas))\n\t\t        \t\t\t\t{\n\t\t        \t\t\t\t\tcandidate = curCan;\n\t\t        \t\t\t\t\t//check connection rules\n\t\t        \t\t\t\t\tcanConnect = $scope.editor.getRules().canConnect({\n\t\t        \t\t\t\t\t\t\t\t\t\t\tsourceShape: currentSelectedShape, \n\t\t        \t\t\t\t\t\t\t\t\t\t\tedgeStencil: stencil, \n\t\t        \t\t\t\t\t\t\t\t\t\t\ttargetShape: curCan\n\t\t        \t\t\t\t\t\t\t\t\t\t\t});\t\n\t\t        \t\t\t\t\tcurCan = curCan.parent;\n\t\t        \t\t\t\t}\n\t            \t\t\t}\n            \t\t\t}\n            \t\t\tvar parentCandidate = $scope.editor.getCanvas();\n        \t\t\t\t\n        \t\t\t\tisValid = canConnect;\n        \t\t\t\t$scope.dragCurrentParent = parentCandidate;\n                        $scope.dragCurrentParentId = parentCandidate.id;\n                        $scope.dragCurrentParentStencil = parentCandidate.getStencil().id();\n        \t\t\t\t$scope.dragCanContain = canConnect;\n        \t\t\t\t$scope.dropTargetElement = candidate;\n            \t\t}\t\t\n    \t\t\t\t\n    \t\t\t}\t\n\n                $scope.editor.handleEvents({\n\t\t\t\t\ttype:\t\tORYX.CONFIG.EVENT_HIGHLIGHT_SHOW, \n\t\t\t\t\thighlightId:'shapeMenu',\n\t\t\t\t\telements:\t[candidate],\n\t\t\t\t\tcolor:\t\tisValid ? ORYX.CONFIG.SELECTION_VALID_COLOR : ORYX.CONFIG.SELECTION_INVALID_COLOR\n\t\t\t\t});\n            }\n        };\n\n    }]);\n\nvar KISBPM = KISBPM || {};\n//create command for undo/redo\nKISBPM.CreateCommand = ORYX.Core.Command.extend({\n\tconstruct: function(option, currentReference, position, facade){\n\t\tthis.option = option;\n\t\tthis.currentReference = currentReference;\n\t\tthis.position = position;\n\t\tthis.facade = facade;\n\t\tthis.shape;\n\t\tthis.edge;\n\t\tthis.targetRefPos;\n\t\tthis.sourceRefPos;\n\t\t/*\n\t\t * clone options parameters\n\t\t */\n        this.connectedShape = option.connectedShape;\n        this.connectingType = option.connectingType;\n        this.namespace = option.namespace;\n        this.type = option.type;\n        this.containedStencil = option.containedStencil;\n        this.parent = option.parent;\n        this.currentReference = currentReference;\n        this.shapeOptions = option.shapeOptions;\n\t},\t\t\t\n\texecute: function(){\n\t\t\n\t\tif (this.shape) {\n\t\t\tif (this.shape instanceof ORYX.Core.Node) {\n\t\t\t\tthis.parent.add(this.shape);\n\t\t\t\tif (this.edge) {\n\t\t\t\t\tthis.facade.getCanvas().add(this.edge);\n\t\t\t\t\tthis.edge.dockers.first().setDockedShape(this.connectedShape);\n\t\t\t\t\tthis.edge.dockers.first().setReferencePoint(this.sourceRefPos);\n\t\t\t\t\tthis.edge.dockers.last().setDockedShape(this.shape);\n\t\t\t\t\tthis.edge.dockers.last().setReferencePoint(this.targetRefPos);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tthis.facade.setSelection([this.shape]);\n\t\t\t\t\n\t\t\t} else if (this.shape instanceof ORYX.Core.Edge) {\n\t\t\t\tthis.facade.getCanvas().add(this.shape);\n\t\t\t\tthis.shape.dockers.first().setDockedShape(this.connectedShape);\n\t\t\t\tthis.shape.dockers.first().setReferencePoint(this.sourceRefPos);\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tthis.shape = this.facade.createShape(this.option);\n\t\t\tthis.edge = (!(this.shape instanceof ORYX.Core.Edge)) ? this.shape.getIncomingShapes().first() : undefined;\n\t\t}\n\t\t\n\t\tif (this.currentReference && this.position) {\n\t\t\t\n\t\t\tif (this.shape instanceof ORYX.Core.Edge) {\n\t\t\t\n\t\t\t\tif (!(this.currentReference instanceof ORYX.Core.Canvas)) {\n\t\t\t\t\tthis.shape.dockers.last().setDockedShape(this.currentReference);\n\t\t\t\t\t\n\t\t\t\t\tif (this.currentReference.getStencil().idWithoutNs() === 'TextAnnotation')\n\t\t\t\t\t{\n\t\t\t\t\t\tvar midpoint = {};\n\t\t\t\t\t\tmidpoint.x = 0;\n\t\t\t\t\t\tmidpoint.y = this.currentReference.bounds.height() / 2;\n\t\t\t\t\t\tthis.shape.dockers.last().setReferencePoint(midpoint);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tthis.shape.dockers.last().setReferencePoint(this.currentReference.bounds.midPoint());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tthis.shape.dockers.last().bounds.centerMoveTo(this.position);\n\t\t\t\t}\n\t\t\t\tthis.sourceRefPos = this.shape.dockers.first().referencePoint;\n\t\t\t\tthis.targetRefPos = this.shape.dockers.last().referencePoint;\n\t\t\t\t\n\t\t\t} else if (this.edge){\n\t\t\t\tthis.sourceRefPos = this.edge.dockers.first().referencePoint;\n\t\t\t\tthis.targetRefPos = this.edge.dockers.last().referencePoint;\n\t\t\t}\n\t\t} else {\n\t\t\tvar containedStencil = this.containedStencil;\n\t\t\tvar connectedShape = this.connectedShape;\n\t\t\tvar bc = connectedShape.bounds;\n\t\t\tvar bs = this.shape.bounds;\n\t\t\t\n\t\t\tvar pos = bc.center();\n\t\t\tif(containedStencil.defaultAlign()===\"north\") {\n\t\t\t\tpos.y -= (bc.height() / 2) + ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET + (bs.height()/2);\n\t\t\t} else if(containedStencil.defaultAlign()===\"northeast\") {\n\t\t\t\tpos.x += (bc.width() / 2) + ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET_CORNER + (bs.width()/2);\n\t\t\t\tpos.y -= (bc.height() / 2) + ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET_CORNER + (bs.height()/2);\n\t\t\t} else if(containedStencil.defaultAlign()===\"southeast\") {\n\t\t\t\tpos.x += (bc.width() / 2) + ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET_CORNER + (bs.width()/2);\n\t\t\t\tpos.y += (bc.height() / 2) + ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET_CORNER + (bs.height()/2);\n\t\t\t} else if(containedStencil.defaultAlign()===\"south\") {\n\t\t\t\tpos.y += (bc.height() / 2) + ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET + (bs.height()/2);\n\t\t\t} else if(containedStencil.defaultAlign()===\"southwest\") {\n\t\t\t\tpos.x -= (bc.width() / 2) + ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET_CORNER + (bs.width()/2);\n\t\t\t\tpos.y += (bc.height() / 2) + ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET_CORNER + (bs.height()/2);\n\t\t\t} else if(containedStencil.defaultAlign()===\"west\") {\n\t\t\t\tpos.x -= (bc.width() / 2) + ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET + (bs.width()/2);\n\t\t\t} else if(containedStencil.defaultAlign()===\"northwest\") {\n\t\t\t\tpos.x -= (bc.width() / 2) + ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET_CORNER + (bs.width()/2);\n\t\t\t\tpos.y -= (bc.height() / 2) + ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET_CORNER + (bs.height()/2);\n\t\t\t} else {\n\t\t\t\tpos.x += (bc.width() / 2) + ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET + (bs.width()/2);\n\t\t\t}\n\t\t\t\n\t\t\t// Move shape to the new position\n\t\t\tthis.shape.bounds.centerMoveTo(pos);\n\t\t\t\n\t\t\t// Move all dockers of a node to the position\n\t\t\tif (this.shape instanceof ORYX.Core.Node){\n\t\t\t\t(this.shape.dockers||[]).each(function(docker){\n\t\t\t\t\tdocker.bounds.centerMoveTo(pos);\n\t\t\t\t});\n\t\t\t}\n\t\t\t\n\t\t\t//this.shape.update();\n\t\t\tthis.position = pos;\n\t\t\t\n\t\t\tif (this.edge){\n\t\t\t\tthis.sourceRefPos = this.edge.dockers.first().referencePoint;\n\t\t\t\tthis.targetRefPos = this.edge.dockers.last().referencePoint;\n\t\t\t}\n\t\t}\n\t\t\n\t\tthis.facade.getCanvas().update();\n\t\tthis.facade.updateSelection();\n\n\t},\n\trollback: function(){\n\t\tthis.facade.deleteShape(this.shape);\n\t\tif(this.edge) {\n\t\t\tthis.facade.deleteShape(this.edge);\n\t\t}\n\t\t//this.currentParent.update();\n\t\tthis.facade.setSelection(this.facade.getSelection().without(this.shape, this.edge));\n\t}\n});\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/editor-app/toolbar-controller.js",
    "content": "/*\n * Activiti Modeler component part of the Activiti project\n * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.\n * \n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n */\n'use strict';\n\nangular.module('activitiModeler')\n    .controller('ToolbarController', ['$scope', '$http', '$modal', '$q', '$rootScope', '$translate', '$location', function ($scope, $http, $modal, $q, $rootScope, $translate, $location) {\n\n    \t$scope.editorFactory.promise.then(function () {\n    \t\t$scope.items = KISBPM.TOOLBAR_CONFIG.items;\n    \t});\n        \n        $scope.secondaryItems = KISBPM.TOOLBAR_CONFIG.secondaryItems;\n\n        // Call configurable click handler (From http://stackoverflow.com/questions/359788/how-to-execute-a-javascript-function-when-i-have-its-name-as-a-string)\n        var executeFunctionByName = function(functionName, context /*, args */) {\n            var args = Array.prototype.slice.call(arguments).splice(2);\n            var namespaces = functionName.split(\".\");\n            var func = namespaces.pop();\n            for(var i = 0; i < namespaces.length; i++) {\n                context = context[namespaces[i]];\n            }\n            return context[func].apply(this, args);\n        };\n\n        // Click handler for toolbar buttons\n        $scope.toolbarButtonClicked = function(buttonIndex) {\n\n            // Default behaviour\n            var buttonClicked = $scope.items[buttonIndex];\n            var services = { '$scope' : $scope, '$rootScope' : $rootScope, '$http' : $http, '$modal' : $modal, '$q' : $q, '$translate' : $translate};\n            executeFunctionByName(buttonClicked.action, window, services);\n\n            // Other events\n            var event = {\n                type : KISBPM.eventBus.EVENT_TYPE_TOOLBAR_BUTTON_CLICKED,\n                toolbarItem : buttonClicked\n            };\n            KISBPM.eventBus.dispatch(event.type, event);\n        };\n        \n        // Click handler for secondary toolbar buttons\n        $scope.toolbarSecondaryButtonClicked = function(buttonIndex) {\n            var buttonClicked = $scope.secondaryItems[buttonIndex];\n            var services = { '$scope' : $scope, '$http' : $http, '$modal' : $modal, '$q' : $q, '$translate' : $translate, '$location': $location};\n            executeFunctionByName(buttonClicked.action, window, services);\n        };\n        \n        /* Key bindings */\n        Mousetrap.bind(['command+z', 'ctrl+z'], function(e) {\n        \tvar services = { '$scope' : $scope, '$rootScope' : $rootScope, '$http' : $http, '$modal' : $modal, '$q' : $q, '$translate' : $translate};\n        \tKISBPM.TOOLBAR.ACTIONS.undo(services);\n            return false;\n        });\n        \n        Mousetrap.bind(['command+y', 'ctrl+y'], function(e) {\n        \tvar services = { '$scope' : $scope, '$rootScope' : $rootScope, '$http' : $http, '$modal' : $modal, '$q' : $q, '$translate' : $translate};\n        \tKISBPM.TOOLBAR.ACTIONS.redo(services);\n            return false;\n        });\n        \n        Mousetrap.bind(['command+c', 'ctrl+c'], function(e) {\n        \tvar services = { '$scope' : $scope, '$rootScope' : $rootScope, '$http' : $http, '$modal' : $modal, '$q' : $q, '$translate' : $translate};\n        \tKISBPM.TOOLBAR.ACTIONS.copy(services);\n            return false;\n        });\n        \n        Mousetrap.bind(['command+v', 'ctrl+v'], function(e) {\n        \tvar services = { '$scope' : $scope, '$rootScope' : $rootScope, '$http' : $http, '$modal' : $modal, '$q' : $q, '$translate' : $translate};\n        \tKISBPM.TOOLBAR.ACTIONS.paste(services);\n            return false;\n        });\n        \n        Mousetrap.bind(['del'], function(e) {\n        \tvar services = { '$scope' : $scope, '$rootScope' : $rootScope, '$http' : $http, '$modal' : $modal, '$q' : $q, '$translate' : $translate};\n        \tKISBPM.TOOLBAR.ACTIONS.deleteItem(services);\n            return false;\n        });\n\n        /* Undo logic */\n\n        $scope.undoStack = [];\n        $scope.redoStack = [];\n\n        $scope.editorFactory.promise.then(function() {\n\n            // Catch all command that are executed and store them on the respective stacks\n            $scope.editor.registerOnEvent(ORYX.CONFIG.EVENT_EXECUTE_COMMANDS, function( evt ){\n\n                // If the event has commands\n                if( !evt.commands ){ return; }\n\n                $scope.undoStack.push( evt.commands );\n                $scope.redoStack = [];\n                \n                for(var i = 0; i < $scope.items.length; i++) \n        \t\t{\n                    var item = $scope.items[i];\n                    if (item.action === 'KISBPM.TOOLBAR.ACTIONS.undo')\n                    {\n                    \titem.enabled = true;\n                    }\n                    else if (item.action === 'KISBPM.TOOLBAR.ACTIONS.redo')\n                    {\n                    \titem.enabled = false;\n                    }\n        \t\t}\n\n                // Update\n                $scope.editor.getCanvas().update();\n                $scope.editor.updateSelection();\n\n            });\n\n        });\n        \n        // Handle enable/disable toolbar buttons \n        $scope.editorFactory.promise.then(function() {\n        \t$scope.editor.registerOnEvent(ORYX.CONFIG.EVENT_SELECTION_CHANGED, function( evt ){\n        \t\tvar elements = evt.elements;\n        \t\t\n        \t\tfor(var i = 0; i < $scope.items.length; i++) \n        \t\t{\n                    var item = $scope.items[i];\n                    if (item.enabledAction && item.enabledAction === 'element')\n                    {\n                    \tvar minLength = 1;\n                    \tif(item.minSelectionCount) {\n                    \t\tminLength = item.minSelectionCount;\n                    \t}\n                    \tif (elements.length >= minLength && !item.enabled) {\n                    \t\t$scope.safeApply(function () {\n                    \t\t\titem.enabled = true;\n                            });\n                    \t}\n                    \telse if (elements.length == 0 && item.enabled) {\n                    \t\t$scope.safeApply(function () {\n                    \t\t\titem.enabled = false;\n                            });\n                    \t}\n                    }\n                }\n        \t});\n        \t\n        });\n\n    }]);"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/activiti/modeler.html",
    "content": "<!doctype html>\n<!--[if lt IE 7]>\n<html class=\"no-js lt-ie9 lt-ie8 lt-ie7\"> <![endif]-->\n<!--[if IE 7]>\n<html class=\"no-js lt-ie9 lt-ie8\"> <![endif]-->\n<!--[if IE 8]>\n<html class=\"no-js lt-ie9\"> <![endif]-->\n<!--[if gt IE 8]><!-->\n<html class=\"no-js\"> <!--<![endif]-->\n<head>\n    <meta charset=\"utf-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n    <title>Activiti Editor</title>\n    <meta name=\"description\" content=\"\">\n    <meta name=\"viewport\"\n          content=\"initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, width=device-width\">\n    <!-- Place favicon.ico and apple-touch-icon.png in the root directory -->\n\n    <link rel=\"Stylesheet\" media=\"screen\" href=\"editor-app/libs/ng-grid-2.0.7.min.css\" type=\"text/css\"/>\n    <link rel=\"stylesheet\" href=\"editor-app/libs/bootstrap_3.1.1/css/bootstrap.min.css\"/>\n\n    <link rel=\"Stylesheet\" media=\"screen\" href=\"editor-app/editor/css/editor.css\" type=\"text/css\"/>\n    <link rel=\"stylesheet\" href=\"editor-app/css/style.css\" type=\"text/css\"/>\n\n\t<link rel=\"stylesheet\" href=\"editor-app/css/style-common.css\">\n    <link rel=\"stylesheet\" href=\"editor-app/css/style-editor.css\">\n\n</head>\n<body style=\"background-color: #FFFFFF;overflow:hidden\">\n\n\t<div class=\"navbar navbar-fixed-top navbar-inverse\" role=\"navigation\" id=\"main-header\">\n\t    <div class=\"navbar-header\">\n            <a href=\"\" ng-click=\"backToLanding()\" class=\"navbar-brand\"\n               title=\"{{'GENERAL.MAIN-TITLE' | translate}}\"><span\n                    class=\"sr-only\">{{'GENERAL.MAIN-TITLE' | translate}}</span></a>\n        </div>\n\t</div>\n\t\n\t<!--[if lt IE 9]>\n\t<div class=\"unsupported-browser\">\n\t    <p class=\"alert error\">You are using an unsupported browser. Please upgrade your browser in order to use the\n\t        editor.</p>\n\t</div>\n\t<![endif]-->\n\t\n\t<div class=\"alert-wrapper\" ng-cloak>\n\t    <div class=\"alert fadein {{alerts.current.type}}\" ng-show=\"alerts.current\" ng-click=\"dismissAlert()\">\n\t        <i class=\"glyphicon\"\n\t           ng-class=\"{'glyphicon-ok': alerts.current.type == 'info', 'glyphicon-remove': alerts.current.type == 'error'}\"></i>\n\t        <span>{{alerts.current.message}}</span>\n\t\n\t        <div class=\"pull-right\" ng-show=\"alerts.queue.length > 0\">\n\t            <span class=\"badge\">{{alerts.queue.length + 1}}</span>\n\t        </div>\n\t    </div>\n\t</div>\n\t\n\t<div id=\"main\" class=\"wrapper full clearfix\" ng-style=\"{height: window.height + 'px'}\" ng-app=\"activitiModeler\" ng-include=\"'editor-app/editor.html'\">\n\t</div>\n\n\t<!--[if lt IE 9]>\n\t<script src=\"editor-app/libs/es5-shim-15.3.4.5/es5-shim.js\"></script>\n\t<script src=\"editor-app/libs/json3_3.2.6/lib/json3.min.js\"></script>\n\t<![endif]-->\n\t\n\t<script src=\"editor-app/libs/jquery_1.11.0/jquery.min.js\"></script>\n\t<script src=\"editor-app/libs/jquery-ui-1.10.3.custom.min.js\"></script>\n\t\n\t<script src=\"editor-app/libs/angular_1.2.13/angular.min.js\"></script>\n\t<script src=\"editor-app/libs/angular_1.2.13/angular-animate.min.js\"></script>\n\t<script src=\"editor-app/libs/bootstrap_3.1.1/js/bootstrap.min.js\"></script>\n\t<script src=\"editor-app/libs/angular-resource_1.2.13/angular-resource.min.js\"></script>\n\t<script src=\"editor-app/libs/angular-cookies_1.2.13/angular-cookies.min.js\"></script>\n\t<script src=\"editor-app/libs/angular-sanitize_1.2.13/angular-sanitize.min.js\"></script>\n\t<script src=\"editor-app/libs/angular-route_1.2.13/angular-route.min.js\"></script>\n\t<script src=\"editor-app/libs/angular-translate_2.4.2/angular-translate.min.js\"></script>\n\t<script src=\"editor-app/libs/angular-translate-storage-cookie/angular-translate-storage-cookie.js\"></script>\n\t<script src=\"editor-app/libs/angular-translate-loader-static-files/angular-translate-loader-static-files.js\"></script>\n\t<script src=\"editor-app/libs/angular-strap_2.0.5/angular-strap.min.js\"></script>\n\t<script src=\"editor-app/libs/angular-strap_2.0.5/angular-strap.tpl.min.js\"></script>\n\t<script src=\"editor-app/libs/momentjs_2.5.1/momentjs.min.js\"></script>\n\t\n\t<script src=\"editor-app/libs/ui-utils.min-0.0.4.js\" type=\"text/javascript\"></script>\n\t<script src=\"editor-app/libs/ng-grid-2.0.7-min.js\" type=\"text/javascript\"></script>\n\t<script src=\"editor-app/libs/angular-dragdrop.min-1.0.3.js\" type=\"text/javascript\"></script>\n\t<script src=\"editor-app/libs/mousetrap-1.4.5.min.js\" type=\"text/javascript\"></script>\n\t<script src=\"editor-app/libs/jquery.autogrow-textarea.js\" type=\"text/javascript\"></script>\n\t\n\t<script src=\"editor-app/libs/prototype-1.5.1.js\" type=\"text/javascript\"></script>\n\t<script src=\"editor-app/libs/path_parser.js\" type=\"text/javascript\"></script>\n\t\n\t<script src=\"editor-app/libs/angular-scroll_0.5.7/angular-scroll.min.js\" type=\"text/javascript\"></script>\n\t\n\t<!-- Configuration -->\n\t<script src=\"editor-app/app-cfg.js?v=1\"></script>\n\t<script src=\"editor-app/editor-config.js\" type=\"text/javascript\"></script>\n\t<script src=\"editor-app/configuration/url-config.js\" type=\"text/javascript\"></script>\n\t\n\t<script src=\"editor-app/editor/i18n/translation_en_us.js\" type=\"text/javascript\"></script>\n\t<script src=\"editor-app/editor/i18n/translation_signavio_en_us.js\" type=\"text/javascript\"></script>\n\t<script src=\"editor-app/editor/oryx.debug.js\" type=\"text/javascript\"></script>\n\t\n\t<script src=\"editor-app/app.js\"></script>\n\t\n\t<script src=\"editor-app/eventbus.js\" type=\"text/javascript\"></script>\n\t\n\t<script src=\"editor-app/editor-controller.js\" type=\"text/javascript\"></script>\n\t<script src=\"editor-app/stencil-controller.js\" type=\"text/javascript\"></script>\n\t<script src=\"editor-app/toolbar-controller.js\" type=\"text/javascript\"></script>\n\t<script src=\"editor-app/header-controller.js\" type=\"text/javascript\"></script>\n\t<script src=\"editor-app/select-shape-controller.js\" type=\"text/javascript\"></script>\n\t\n\t<script src=\"editor-app/editor-utils.js\" type=\"text/javascript\"></script>\n\t<script src=\"editor-app/configuration/toolbar-default-actions.js\" type=\"text/javascript\"></script>\n\t\n\t<script src=\"editor-app/configuration/properties-default-controllers.js\" type=\"text/javascript\"></script>\n\t<script src=\"editor-app/configuration/properties-execution-listeners-controller.js\" type=\"text/javascript\"></script>\n\t<script src=\"editor-app/configuration/properties-event-listeners-controller.js\" type=\"text/javascript\"></script>\n\t<script src=\"editor-app/configuration/properties-assignment-controller.js\" type=\"text/javascript\"></script>\n\t<script src=\"editor-app/configuration/properties-fields-controller.js\" type=\"text/javascript\"></script>\n\t<script src=\"editor-app/configuration/properties-form-properties-controller.js\" type=\"text/javascript\"></script>\n\t<script src=\"editor-app/configuration/properties-in-parameters-controller.js\" type=\"text/javascript\"></script>\n\t<script src=\"editor-app/configuration/properties-multiinstance-controller.js\" type=\"text/javascript\"></script>\n\t<script src=\"editor-app/configuration/properties-out-parameters-controller.js\" type=\"text/javascript\"></script>\n\t<script src=\"editor-app/configuration/properties-task-listeners-controller.js\" type=\"text/javascript\"></script>\n\t<script src=\"editor-app/configuration/properties-sequenceflow-order-controller.js\" type=\"text/javascript\"></script>\n\t<script src=\"editor-app/configuration/properties-condition-expression-controller.js\" type=\"text/javascript\"></script>\n\t<script src=\"editor-app/configuration/properties-signal-definitions-controller.js\" type=\"text/javascript\"></script>\n\t<script src=\"editor-app/configuration/properties-signal-scope-controller.js\" type=\"text/javascript\"></script>\n\t<script src=\"editor-app/configuration/properties-message-definitions-controller.js\" type=\"text/javascript\"></script>\n\t<script src=\"editor-app/configuration/properties-message-scope-controller.js\" type=\"text/javascript\"></script>\n\t\n\t<script src=\"editor-app/configuration/toolbar.js\" type=\"text/javascript\"></script>\n\t<script src=\"editor-app/configuration/toolbar-custom-actions.js\" type=\"text/javascript\"></script>\n\t\n\t<script src=\"editor-app/configuration/properties.js\" type=\"text/javascript\"></script>\n\t<script src=\"editor-app/configuration/properties-custom-controllers.js\" type=\"text/javascript\"></script>\n\n</body>\n</html>\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/client/addClient.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en-us\" id=\"extr-page\">\n<head>\n<meta charset=\"UTF-8\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/bootstrap.min.css\">\n <!--layui and necessary plugins-->\n<link rel=\"stylesheet\" type=\"text/css\" href=\"/lib/layui/css/layui.css\"></link>\n\n<link rel=\"stylesheet\" href=\"/css/ztree/metroStyle/metroStyle.css\" type=\"text/css\">\n</head>\n<body>\n<div class=\"col-xs-12 col-sm-12 col-md-12 col-lg-12\">\n\t<form class=\"form-horizontal\" onsubmit=\"return false\" id=\"form\">\n\t\t<fieldset>\n\t\t\t<input type=\"hidden\" id=\"id\" name=\"id\">\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">应用标识</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<input class=\"form-control\" placeholder=\"应用标识\" type=\"text\" name=\"clientId\" id=\"clientId\"\n\t\t\t\t\t\tdata-bv-notempty=\"true\"\n\t\t\t\t\t\tdata-bv-notempty-message=\"应用标识不能为空\">\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">应用密钥</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<textarea class=\"form-control\" placeholder=\"应用密钥\" name=\"clientSecret\"  id=\"clientSecret\"></textarea>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">回调地址</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<textarea class=\"form-control\" placeholder=\"回调地址\" name=\"webServerRedirectUri\"  id=\"webServerRedirectUri\"></textarea>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">权限</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<ul id=\"treeDemo\" class=\"ztree\"></ul>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"form-actions\">\n\t\t\t\t<div class=\"row\" align=\"center\">\n\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t<button class=\"layui-btn layui-btn-sm\" onclick=\"location.href='clientList.html'\">返回</button>\n\t\t\t\t\t\t<button class=\"layui-btn layui-btn-sm\" type=\"submit\" onclick=\"add()\">\n\t\t\t\t\t\t\t<i class=\"fa fa-save\"></i> 保存\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t</fieldset>\n\t</form>\n</div>\n\n\t<script type=\"text/javascript\" src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/plugin/bootstrapvalidator/bootstrapValidator.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/common.js\"></script>\n\t<script type=\"text/javascript\" src=\"/lib/layui/layui.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/libs/jquery.ztree.all-3.5.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/my/ztree-service.js\"></script>\n\t<script type=\"text/javascript\">\n\tlayui.use('layer', function(){\n\t    var layer = layui.layer;\n\t});\n\t\n\t\t$.fn.zTree.init($(\"#treeDemo\"), getSettting(), getMenuTree());\n\t\tinitData();\n\t\n\t\tfunction initData(){\n\t\t\tvar id = getUrlParam(\"id\");\n\t\t\tif(id != \"\"){\n\t\t\t\t$.ajax({\n\t\t\t\t\ttype : 'get',\n\t\t\t\t\turl : '/clients/'+id,\n\t\t\t\t\tasync : false,\n\t\t\t\t\tsuccess : function(data) {\n\t\t\t\t\t\t$(\"#id\").val(data.id);\n\t\t\t\t\t\t$(\"#clientId\").val(data.clientId);\n\t\t\t\t\t\t//不可编辑clientId\n\t\t\t\t\t\t$(\"#clientId\").attr(\"disabled\", \"disabled\");\n\t\t\t\t\t\t$(\"#clientSecret\").val(data.clientSecret);\n\t\t\t\t\t\t$(\"#webServerRedirectUri\").val(data.webServerRedirectUri);\n\t\t\t\t\t\t$(\"#webServerRedirectUri\").attr(\"disabled\", \"disabled\");\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\tinitMenuDatas(id);\n\t\t\t}\n\t\t}\n\t\t\n\t\t\n\t\t$('#form').bootstrapValidator();\n\t\t\n\t\tfunction add() {\n\t\t\tvar bootstrapValidator = $(\"#form\").data('bootstrapValidator');\n\t\t\tbootstrapValidator.validate();\n\t\t    if(!bootstrapValidator.isValid()){\n\t\t\t   return;\n\t\t    }\n\t\t    \n\t\t    var formdata = $(\"#form\").serializeObject();\n\t\t    formdata.permissionIds = getCheckedMenuIds();\n\n\t\t\t$.ajax({\n\t\t\t\ttype : 'post',\n\t\t\t\turl : '/clients',\n\t\t\t\tcontentType: \"application/json; charset=utf-8\",  \n\t\t\t\tdata : JSON.stringify(formdata),\n\t\t\t\tsuccess : function(data) {\n\t\t\t\t\tlayer.msg(\"成功\", {shift: -1, time: 1000}, function(){\n                        location.href = \"clientList.html\";\n                    });\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\t\n\t</script>\n</body>\n</html>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/client/clientList.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<title>Insert title here</title>\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/bootstrap.min.css\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/dataTables.bootstrap.min.css\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/lib/layui/css/layui.css\">\n</head>\n<body>\n    <div>\n        <div class=\"col-xs-12 col-sm-12 col-md-12 col-lg-12\">\n                <header style=\"height: 100%\">\n                    <div align=\"left\">\n\t                    <table style=\"width: 100%\">\n\t                   \t\t<tr>\n\t                   \t\t\t<td>\n\t\t                   \t\t\t<form class=\"form-inline\" onsubmit=\"return false\">\n\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t应用标识：\n\t\t\t\t\t\t\t\t\t\t\t<input id=\"clientId\" type=\"text\" class=\"form-control\" placeholder=\"应用标识\">\n\t\t\t\t\t\t\t\t\t\t\t<button id=\"searchBt\" class=\"layui-btn layui-btn-sm\" permission=\"sys:role:query\"><i class=\"layui-icon\">&#xe615;</i>搜索</button>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</form>\n\t                   \t\t\t</td>\n\t                   \t\t\t<td align=\"right\">\n\t                   \t\t\t\t<button class=\"layui-btn layui-btn-sm\" onclick=\"location.href='addClient.html'\" permission=\"sys:role:add\">\n                                      <i class=\"layui-icon\">&#xe608;</i> 添加\n                                    </button>\n\t                   \t\t\t</td>\n\t                   \t\t</tr> \n\t                    </table>\n\t\t\t\t\t</div>\n                </header>\n                \n                <div>\n                    <div class=\"widget-body no-padding\">\n                        <table id=\"dt-table\" class=\"table table-striped table-bordered table-hover\" style=\"width:100%\">\n                            <thead>\n                                <tr>\n                                </tr>                       \n                                <tr>\n                                    <th style=\"width: 20%\">应用标识</th>\n\t\t\t\t\t\t\t\t\t<th>应用密钥</th>\n\t\t\t\t\t\t\t\t\t<th style=\"width: 20%\">回调地址</th>\n\t\t\t\t\t\t\t\t\t<th style=\"width: 10%\">操作</th>\n                                </tr>\n                            </thead>\n                            <tbody>\n                            </tbody>\n                        </table>\n                    </div>\n                </div>\n        </div>\n    </div>\n</body>\n</html>\n\n<script type=\"text/javascript\" src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n<script type=\"text/javascript\" src=\"/js/plugin/datatables/jquery.dataTables.min.js\"></script>\n<script type=\"text/javascript\" src=\"/js/plugin/datatables/dataTables.bootstrap.min.js\"></script>\n<script type=\"text/javascript\" src=\"/lib/layui/layui.js\"></script>\n<script type=\"text/javascript\" src=\"/js/my/permission.js\"></script>\n<script type=\"text/javascript\">\nvar pers = checkPermission();\n\nvar example;\nfunction init(){\n\texample = \n    \t$('#dt-table').DataTable({\n        \t\"searching\": false,\n        \t\"processing\": false,\n        \t\"serverSide\" : true,\n        \t\"language\": {\n                \"url\": \"/js/plugin/datatables/Chinese.lang\"\n            },\n        \t\"ajax\": {\n        \t\t\"url\" : \"/clients\",\n        \t\t\"type\":\"get\",\n        \t\t\"data\":function(d){\n    \t\t\t\td.clientId = $('#clientId').val();\n        \t\t},\n    \t\t\t\"error\":function(xhr, textStatus, errorThrown){\n    \t\t\t\tvar msg = xhr.responseText;\n    \t\t\t\tconsole.log(msg);\n    \t\t\t\tvar response = JSON.parse(msg);\n    \t\t\t\tvar code = response.code;\n    \t\t\t\tvar message = response.message;\n    \t\t\t\tif (code == 400) {\n    \t\t\t\t\tlayer.msg(message);\n    \t\t\t\t} else if (code == 401) {\n    \t\t\t\t\tlocalStorage.removeItem(\"token\");\n    \t\t\t\t\tlayer.msg(\"token过期，请先登录\", {shift: -1, time: 1000}, function(){\n    \t\t\t\t\t\tlocation.href = '/login.html';\n                        });\n    \t\t\t\t} else if (code == 403) {\n    \t\t\t\t\tconsole.log(\"未授权:\" + message);\n    \t\t\t\t\tlayer.msg('未授权');\n    \t\t\t\t} else if (code == 500) {\n    \t\t\t\t\tlayer.msg('系统错误：' + message);\n    \t\t\t\t}\n    \t\t\t}\n        \t},\n        \t\"dom\": \"<'dt-toolbar'r>t<'dt-toolbar-footer'<'col-sm-10 col-xs-12 hidden-xs'i><'col-xs-12 col-sm-10' p v>>\",\t\n            \"columns\": [\n                { \"data\": \"clientId\", \"defaultContent\": \"\"},\n                { \"data\": \"clientSecret\", \"defaultContent\": \"\"},\n                { \"data\": \"webServerRedirectUri\", \"defaultContent\": \"\"},\n                { \n                \t\"data\": \"\", \n                \t\"defaultContent\": \"\",\n                \t\"orderable\":false,\n                \t\"render\": function (data, type, row) {\n                \t\tvar id = row['id'];\n                \t\tvar href = \"addClient.html?id=\" + id;\n                        var edit = buttonEdit(href, \"sys:role:add\", pers);\n                \t\tvar del = buttonDel(id, \"sys:role:del\", pers);\n                        return edit + del;\n                  \t}\n                },\n            ],\n            \"order\": [[ 1, \"desc\" ]]\n        } );\n}\n\nlayui.use('layer', function(){\n    var layer = layui.layer;\n});\n\nfunction del(id){\n    layer.confirm('确定要删除吗？', {\n        btn : [ '确定', '取消' ]\n    }, function() {\n        $.ajax({\n            type : 'delete',\n            url : '/clients/'+id,\n            success : function(data) {\n                example.ajax.reload();\n                layer.msg(\"删除成功\");\n            }\n        });\n        \n        layer.close(1);\n    });\n}\n\n$(\"#searchBt\").click(function(){\n\texample.ajax.reload();\n});\n\ninit();\n</script>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/dashboard.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<title></title>\n<link rel=\"stylesheet\" href=\"/lib/layui/css/layui.css\" media=\"all\" />\n<link rel=\"stylesheet\" href=\"/lib/layui/css/global.css\" media=\"all\" />\n</head>\n\n<body>\n\t<div class=\"admin-main\">\n\t\t<blockquote class=\"layui-elem-quote\" style=\"background-color: #FFFFFF\">\n\t\t\t<fieldset class=\"layui-elem-field\">\n\t\t\t\t<legend>说明：</legend>\n\t\t\t\t<div class=\"layui-field-box\">\n\t\t\t\t\t<p>\n\t\t\t\t\t\t<span class=\"layui-badge-dot\"></span>spring security jwt token 无状态后台管理\n\t\t\t\t\t</p>\n\t\t\t\t\t<p>\n\t\t\t\t\t\t<span class=\"layui-badge-dot\"></span>动态配置权限，角色和资源，权限控制到按钮粒度\n\t\t\t\t\t</p>\n\t\t\t\t\t<p>\n\t\t\t\t\t\t<span class=\"layui-badge-dot\"></span>采用token进行权限校验，禁用session，未登录返回401，权限不足返回403\n\t\t\t\t\t</p>\n\t\t\t\t\t<p>\n\t\t\t\t\t\t<span class=\"layui-badge-dot\"></span>采用redis存储token及权限信息\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\t\t\t</fieldset>\n\t\t</blockquote>\n\t\t<blockquote class=\"layui-elem-quote\" style=\"background-color: #FFFFFF\">\n\t\t\t<fieldset class=\"layui-elem-field\">\n\t\t\t\t<legend>内置功能：</legend>\n\t\t\t\t<div class=\"layui-field-box\">\n\t\t\t\t\t<p>\n\t\t\t\t\t\t<span class=\"layui-badge-dot\"></span>用户管理：用户查询、添加用户、修改用户、给用户分配角色\n\t\t\t\t\t</p>\n\t\t\t\t\t<p>\n\t\t\t\t\t\t<span class=\"layui-badge-dot\"></span>菜单管理：菜单列表、添加菜单、修改菜单、删除菜单、权限配置、菜单图标设置、菜单排序\n\t\t\t\t\t</p>\n\t\t\t\t\t<p>\n\t\t\t\t\t\t<span class=\"layui-badge-dot\"></span>角色管理：角色查询、添加角色、修改角色、删除角色\n\t\t\t\t\t</p>\n\t\t\t\t\t<p>\n\t\t\t\t\t\t<span class=\"layui-badge-dot\"></span>注册中心\n\t\t\t\t\t</p>\n\t\t\t\t\t<p>\n\t\t\t\t\t\t<span class=\"layui-badge-dot\"></span>携程配置中心\n\t\t\t\t\t</p>\n\t\t\t\t\t<p>\n\t\t\t\t\t\t<span class=\"layui-badge-dot\"></span>代码生成：根据表名生成bean、controller、dao、Mapper.xml、列表页、搜索、分页、新增页、修改页\n\t\t\t\t\t</p>\n\t\t\t\t\t<p>\n\t\t\t\t\t\t<span class=\"layui-badge-dot\"></span>数据源监控：druid\n\t\t\t\t\t</p>\n\t\t\t\t\t<p>\n\t\t\t\t\t\t<span class=\"layui-badge-dot\"></span>接口swagger文档\n\t\t\t\t\t</p>\n\t\t\t\t\t<p>\n\t\t\t\t\t\t<span class=\"layui-badge-dot\"></span>日志查询\n\t\t\t\t\t</p>\n\n\t\t\t\t</div>\n\t\t\t</fieldset>\n\t\t</blockquote>\n\t\t \n\t</div>\n</body>\n\n</html>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/dict/addDict.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/bootstrap.min.css\">\n</head>\n<body>\n<div class=\"col-xs-12 col-sm-12 col-md-12 col-lg-12\">\n\t<form class=\"form-horizontal\" onsubmit=\"return false\" id=\"form\">\n\t\t<fieldset>\n\t\t\t<div class='form-group'>\n\t\t\t\t<label class='col-md-2 control-label'>type</label>\n\t\t\t\t<div class='col-md-10'>\n\t\t\t\t\t<input class='form-control' placeholder='type' type='text' name='type' id='type' data-bv-notempty='true' data-bv-notempty-message='type 不能为空'>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class='form-group'>\n\t\t\t\t<label class='col-md-2 control-label'>k</label>\n\t\t\t\t<div class='col-md-10'>\n\t\t\t\t\t<input class='form-control' placeholder='k' type='text' name='k' id='k' data-bv-notempty='true' data-bv-notempty-message='k 不能为空'>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class='form-group'>\n\t\t\t\t<label class='col-md-2 control-label'>val</label>\n\t\t\t\t<div class='col-md-10'>\n\t\t\t\t\t<input class='form-control' placeholder='val' type='text' name='val' id='val' data-bv-notempty='true' data-bv-notempty-message='val 不能为空'>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"form-actions\">\n\t\t\t\t<div class=\"row\" align=\"center\">\n\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t    <button class=\"btn btn-primary\" onclick=\"location.href='dictList.html'\">返回</button>\n\t\t\t\t\t\t<button class=\"btn btn-primary\" type=\"submit\" onclick=\"add()\">\n\t\t\t\t\t\t\t<i class=\"fa fa-save\"></i> 保存\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t</fieldset>\n\t</form>\n</div>\n\t<script type=\"text/javascript\" src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/plugin/bootstrapvalidator/bootstrapValidator.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/common.js\"></script>\n\t<script type=\"text/javascript\" src=\"/lib/layui/layui.js\"></script>\n\t<script type=\"text/javascript\">\n\t\tlayui.use(['layer','laydate'], function(){\n\t\t    var layer = layui.layer;\n\t\t});\n\t\t\n\t\tfunction add() {\n\t\t\t$('#form').bootstrapValidator();\n\t\t\tvar bootstrapValidator = $(\"#form\").data('bootstrapValidator');\n\t\t\tbootstrapValidator.validate();\n\t\t    if(!bootstrapValidator.isValid()){\n\t\t\t   return;\n\t\t    }\n\t\t    \n\t\t    var formdata = $(\"#form\").serializeObject();\n\n\t\t\t$.ajax({\n\t\t\t\ttype : 'post',\n\t\t\t\turl : '/dicts',\n\t\t\t\tcontentType: \"application/json; charset=utf-8\",  \n\t\t\t\tdata : JSON.stringify(formdata),\n\t\t\t\tsuccess : function(data) {\n\t\t\t\t\tlayer.msg(\"添加成功\", {shift: -1, time: 1000}, function(){\n                        location.href = \"dictList.html\";\n                    });\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\t\n\t</script>\n</body>\n</html>\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/dict/dictList.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<title>Insert title here</title>\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/bootstrap.min.css\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/dataTables.bootstrap.min.css\">\n<link rel=\"stylesheet\" href=\"/lib/layui/css/layui.css\" media=\"all\" />\n</head>\n<body>\n    <div>\n        <div class=\"col-xs-12 col-sm-12 col-md-12 col-lg-12\">\n            <div>\n                <header style=\"height: 100%\">\n                    <div align=\"left\">\n\t                    <table style=\"width: 100%\">\n\t                   \t\t<tr>\n\t                   \t\t\t<td>\n\t\t                   \t\t\t<form class=\"form-inline\" onsubmit=\"return false\">\n\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\ttype：\n\t\t\t\t\t\t\t\t\t\t\t<input id=\"type\" type=\"text\" class=\"form-control\" placeholder=\"type\">\n\t\t\t\t\t\t\t\t\t\t\t<button id=\"searchBt\" class=\"layui-btn layui-btn-sm\" permission=\"dict:query\"><i class=\"layui-icon\">&#xe615;</i>搜索</button>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</form>\n\t                   \t\t\t</td>\n\t                   \t\t\t<td align=\"right\">\n\t                   \t\t\t\t<button class=\"layui-btn layui-btn-sm\" onclick=\"location.href='addDict.html'\" permission=\"dict:add\">\n                                      <i class=\"layui-icon\">&#xe608;</i> 添加\n                                    </button>\n\t                   \t\t\t</td>\n\t                   \t\t</tr> \n\t                    </table>\n\t\t\t\t\t</div>\n                </header>\n                \n                <div>\n                    <div class=\"widget-body no-padding\">\n                        <table id=\"dt-table\" class=\"table table-striped table-bordered table-hover\" style=\"width:100%\">\n                            <thead>\n                                <tr>\n                                </tr>                       \n                                <tr>\n\t\t\t\t\t\t\t\t\t<th>id</th>\n\t\t\t\t\t\t\t\t\t<th>type</th>\n\t\t\t\t\t\t\t\t\t<th>k</th>\n\t\t\t\t\t\t\t\t\t<th>val</th>\n\t\t\t\t\t\t\t\t\t<th>createTime</th>\n\t\t\t\t\t\t\t\t\t<th>updateTime</th>\n\t\t\t\t\t\t\t\t\t<th>操作</th>\n                                </tr>\n                            </thead>\n                            <tbody>\n                            </tbody>\n                        </table>\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>\n</body>\n</html>\n\n<script type=\"text/javascript\" src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n<script type=\"text/javascript\" src=\"/js/plugin/datatables/jquery.dataTables.min.js\"></script>\n<script type=\"text/javascript\" src=\"/js/plugin/datatables/dataTables.bootstrap.min.js\"></script>\n<script type=\"text/javascript\" src=\"/lib/layui/layui.js\"></script>\n<script type=\"text/javascript\" src=\"/js/my/permission.js\"></script>\n<script type=\"text/javascript\">\nvar pers = checkPermission();\n\nvar example;\nfunction init(){\n\texample = \n    \t$('#dt-table').DataTable({\n        \t\"searching\": false,\n        \t\"processing\": false,\n        \t\"serverSide\" : true,\n        \t\"ajax\": {\n        \t\t\"url\" : \"/dicts\",\n        \t\t\"type\":\"get\",\n        \t\t\"data\":function(d){\n    \t\t\t\td.type = $(\"#type\").val();\n    \t\t\t},\n    \t\t\t\"error\":function(xhr, textStatus, errorThrown){\n    \t\t\t\tvar msg = xhr.responseText;\n    \t\t\t\tconsole.log(msg);\n    \t\t\t\tvar response = JSON.parse(msg);\n    \t\t\t\tvar code = response.code;\n    \t\t\t\tvar message = response.message;\n    \t\t\t\tif (code == 400) {\n    \t\t\t\t\tlayer.msg(message);\n    \t\t\t\t} else if (code == 401) {\n    \t\t\t\t\tlocalStorage.removeItem(\"token\");\n    \t\t\t\t\tlayer.msg(\"token过期，请先登录\", {shift: -1, time: 1000}, function(){\n    \t\t\t\t\t\tlocation.href = '/login.html';\n                        });\n    \t\t\t\t} else if (code == 403) {\n    \t\t\t\t\tconsole.log(\"未授权:\" + message);\n    \t\t\t\t\tlayer.msg('未授权');\n    \t\t\t\t} else if (code == 500) {\n    \t\t\t\t\tlayer.msg('系统错误：' + message);\n    \t\t\t\t}\n    \t\t\t}\n        \t},\n        \t\"dom\": \"<'dt-toolbar'r>t<'dt-toolbar-footer'<'col-sm-10 col-xs-12 hidden-xs'i><'col-xs-12 col-sm-10' p v>>\",\t\n            \"columns\": [\n\t\t\t\t{\"data\" : \"id\", \"defaultContent\" : \"\"},\n\t\t\t\t{\"data\" : \"type\", \"defaultContent\" : \"\"},\n\t\t\t\t{\"data\" : \"k\", \"defaultContent\" : \"\"},\n\t\t\t\t{\"data\" : \"val\", \"defaultContent\" : \"\"},\n\t\t\t\t{\"data\" : \"createTime\", \"defaultContent\" : \"\"},\n\t\t\t\t{\"data\" : \"updateTime\", \"defaultContent\" : \"\"},\n\t\t\t\t{ \n\t\t\t\t\t\"data\": \"\", \n\t\t\t\t\t\"defaultContent\": \"\",\n\t\t\t\t\t\"orderable\":false,\n\t\t\t        \"render\": function (data, type, row) {\n             \t\t           var id = row['id'];\n             \t\t           var href = \"updateDict.html?id=\" + id;\n                                var edit = buttonEdit(href, \"dict:add\", pers);\n             \t\t            var del = buttonDel(id, \"dict:del\", pers);\n                                return edit + del;\n               \t            }\t\t\n\t\t\t\t},\n                \n            ],\n           \"order\": [[ 0, \"asc\" ]]\n        } );\n}\n\nlayui.use('layer', function(){\n    var layer = layui.layer;\n});\n\nfunction del(id){\n\tlayer.confirm('确定要删除吗？', {\n        btn : [ '确定', '取消' ]\n    }, function() {\n    \t$.ajax({\n            type : 'delete',\n            url : '/dicts/'+id,\n            success : function(data) {\n                example.ajax.reload();\n                layer.msg(\"删除成功\");\n            }\n        });\n        \n        layer.close(1);\n    });\n}\n\n$(\"#searchBt\").click(function(){\n\texample.ajax.reload();\n});\n\ninit();\n</script>\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/dict/updateDict.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/bootstrap.min.css\">\n</head>\n<body>\n<div class=\"col-xs-12 col-sm-12 col-md-12 col-lg-12\">\n\t<form class=\"form-horizontal\" onsubmit=\"return false\" id=\"form\">\n\t\t<fieldset>\n\t\t\t<input type=\"hidden\" id=\"id\" name=\"id\">\n\t\t\t<div class='form-group'>\n\t\t\t\t<label class='col-md-2 control-label'>type</label>\n\t\t\t\t<div class='col-md-10'>\n\t\t\t\t\t<input class='form-control' placeholder='type' type='text' name='type' id='type' readonly=\"readonly\">\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class='form-group'>\n\t\t\t\t<label class='col-md-2 control-label'>k</label>\n\t\t\t\t<div class='col-md-10'>\n\t\t\t\t\t<input class='form-control' placeholder='k' type='text' name='k' id='k' readonly=\"readonly\">\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class='form-group'>\n\t\t\t\t<label class='col-md-2 control-label'>val</label>\n\t\t\t\t<div class='col-md-10'>\n\t\t\t\t\t<input class='form-control' placeholder='val' type='text' name='val' id='val' data-bv-notempty='true' data-bv-notempty-message='val 不能为空'>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"form-actions\">\n\t\t\t\t<div class=\"row\" align=\"center\">\n\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t    <button class=\"btn btn-primary\" onclick=\"location.href='dictList.html'\">返回</button>\n\t\t\t\t\t\t<button class=\"btn btn-primary\" type=\"submit\" onclick=\"update()\">\n\t\t\t\t\t\t\t<i class=\"fa fa-save\"></i> 保存\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t</fieldset>\n\t</form>\n</div>\n\t<script type=\"text/javascript\" src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/plugin/bootstrapvalidator/bootstrapValidator.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/common.js\"></script>\n\t<script type=\"text/javascript\" src=\"/lib/layui/layui.js\"></script>\n\t<script type=\"text/javascript\">\n\t\tlayui.use(['layer','laydate'], function(){\n\t\t    var layer = layui.layer;\n\t\t});\n\t\t\n\t\tinitData();\n\t\t\n\t\tfunction initData(){\n\t\t\tvar id = getUrlParam(\"id\");\n\t\t\tif(id != \"\"){\n\t\t\t\t$.ajax({\n\t\t\t\t\ttype : 'get',\n\t\t\t\t\turl : '/dicts/'+id,\n\t\t\t\t\tasync : false,\n\t\t\t\t\tsuccess : function(data) {\n\t\t\t\t\t\t$('#id').val(data.id);\n\t\t\t\t\t\t$('#type').val(data.type);\n\t\t\t\t\t\t$('#k').val(data.k);\n\t\t\t\t\t\t$('#val').val(data.val);\n\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tfunction update() {\n\t\t\t$('#form').bootstrapValidator();\n\t\t\tvar bootstrapValidator = $(\"#form\").data('bootstrapValidator');\n\t\t\tbootstrapValidator.validate();\n\t\t    if(!bootstrapValidator.isValid()){\n\t\t\t   return;\n\t\t    }\n\t\t    \n\t\t    var formdata = $(\"#form\").serializeObject();\n\n\t\t\t$.ajax({\n\t\t\t\ttype : 'put',\n\t\t\t\turl : '/dicts',\n\t\t\t\tcontentType: \"application/json; charset=utf-8\",  \n\t\t\t\tdata : JSON.stringify(formdata),\n\t\t\t\tsuccess : function(data) {\n\t\t\t\t\tlayer.msg(\"修改成功\", {shift: -1, time: 1000}, function(){\n                        location.href = \"dictList.html\";\n                    });\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\t\n\t</script>\n</body>\n</html>\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/euraka/euraka.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<title>Insert title here</title>\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\"\n\thref=\"/css/bootstrap.min.css\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\"\n\thref=\"/css/dataTables.bootstrap.min.css\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\"\n\thref=\"/lib/layui/css/layui.css\">\n</head>\n<body>\n\t\n\t<div class=\"main-content-inner\">\n\t\t<!-- 左边服务列表 -->\n\t\t<div class=\"col-sm-4\">\n\t\t\t<div class=\"table-header\">\n\t\t\t\t服务列表&nbsp;&nbsp; <a class=\"green\" href=\"#\"> <i\n\t\t\t\t\tclass=\"ace-icon fa fa-plus-circle orange bigger-130 dept-add\"></i>\n\t\t\t\t</a>\n\t\t\t</div>\n\t\t\t<div>\n\t\t\t \n\t\t\t\t<div class=\"widget-body no-padding\">\n\t\t\t\t\t<table id=\"dt-service-table\"\n\t\t\t\t\t\tclass=\"table table-striped table-bordered table-hover\"\n\t\t\t\t\t\tstyle=\"width: 100%\">\n\t\t\t\t\t\t<thead>\n\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t<th>服务名称</th>\n\t\t\t\t\t\t\t\t<th>实例</th>\n\t\t\t\t\t\t\t\t<th>操作</th>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t</thead>\n\t\t\t\t\t\t<tbody>\n\t\t\t\t\t\t</tbody>\n\t\t\t\t\t</table>\n\t\t\t\t</div>\n\t\t\t \n\t\t\t</div>\n\t\t</div>\n\t\t<!-- 右边用户列表 -->\n\t\t<div class=\"col-sm-8\">\n\t\t\t<div class=\"col-xs-12\">\n\t\t\t\t<div class=\"table-header\">\n\t\t\t\t\t实例列表&nbsp;&nbsp; <a class=\"green\" href=\"#\"> <i\n\t\t\t\t\t\tclass=\"ace-icon fa fa-plus-circle orange bigger-130 user-add\"></i>\n\t\t\t\t\t</a>\n\t\t\t\t</div>\n\t\t\t\t<div>\n\t\t\t\t\t<div id=\"dynamic-table_wrapper\"\n\t\t\t\t\t\tclass=\"dataTables_wrapper form-inline no-footer\">\n\t\t\t\t\t\t  <div class=\"widget-body no-padding\">\n\t\t\t\t\t\t\t\t<table id=\"dt-instance-table\"\n\t\t\t\t\t\t\t\t\tclass=\"table table-striped table-bordered table-hover\"\n\t\t\t\t\t\t\t\t\tstyle=\"width: 100%\">\n\t\t\t\t\t\t\t\t\t<thead>\n\t\t\t\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t\t\t\t<th>服务名称</th>\n\t\t\t\t\t\t\t\t\t\t\t<th>实例标识</th>\n\t\t\t\t\t\t\t\t\t\t\t<th>IP地址</th>\n\t\t\t\t\t\t\t\t\t\t\t<th>端口</th>\n\t\t\t\t\t\t\t\t\t\t\t<th>状态</th>\n\t\t\t\t\t\t\t\t\t\t\t<th>操作</th>\n\t\t\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t\t\t</thead>\n\t\t\t\t\t\t\t\t\t<tbody>\n\t\t\t\t\t\t\t\t\t</tbody>\n\t\t\t\t\t\t\t\t</table>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\n\t \n</body>\n</html>\n\n\n<script type=\"text/javascript\" src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n<script type=\"text/javascript\"\n\tsrc=\"/js/plugin/datatables/jquery.dataTables.min.js\"></script>\n<script type=\"text/javascript\"\n\tsrc=\"/js/plugin/datatables/dataTables.bootstrap.min.js\"></script>\n<script type=\"text/javascript\" src=\"/lib/layui/layui.js\"></script>\n<script type=\"text/javascript\" src=\"/js/my/permission.js\"></script>\n<script type=\"text/javascript\">\nvar pers = checkPermission();\nvar service  ;\nvar instance  ;\nfunction init(){\n\tservice = \n    \t$('#dt-service-table').DataTable({\n        \t\"searching\": false,\n        \t\"processing\": false,\n        \t\"serverSide\" : true,\n        \t \"bFilter\": false,    //去掉搜索框方法三：这种方法可以\n             \"bLengthChange\": false,   //去掉每页显示多少条数据方法\n             \"bInfo\": false,\n             \"bPaginate\": false,\n        \t\"language\": {\n                \"url\": \"/js/plugin/datatables/Chinese.lang\"\n            },\n            \n            \n            \"ajax\": function (data, callback, settings) {  \n\t            \t //封装请求参数  \n\t            \t var param = {};  \n\t            \t param.limit =data.length;//页面显示记录条数，在页面显示每页显示多少项的时候  \n\t            \t param.start = data.start;//开始的记录序号  \n\t            \t param.page = (data.start / data.length)+1;//当前页码  \n\t            \t //ajax请求数据  \n\t            \t $.ajax({  \n\t\t            \t  type: \"GET\",  \n\t\t            \t  url: \"/eureka/apps\",  \n\t\t            \t  cache: false, //禁用缓存  \n\t\t            \t  data: param, //传入组装的参数  \n\t\t            \t  dataType: \"json\",  \n\t            \t  \"success\": function (result) {  \n\t\t            \t  //封装返回数据  \n\t\t            \t  var returnData = {};  \n\t\t            \t   returnData.data = result.applications.application;//返回的数据列表  \n\t\t            \t   \n\t\t            \t  //console.log(returnData);  \n\t\t            \t  //调用DataTables提供的callback方法，代表数据已封装完成并传回DataTables进行渲染  \n\t\t            \t  //此时的数据需确保正确无误，异常判断应在执行此回调前自行处理完毕  \n\t\t            \t  callback(returnData);  \n\t\t            \t  \n\t            \t  }  ,\n\t            \t  \"error\":function(xhr, textStatus, errorThrown){\n\t      \t\t\t\tvar msg = xhr.responseText;\n\t      \t\t\t\tconsole.log(msg);\n\t      \t\t\t\tvar response = JSON.parse(msg);\n\t      \t\t\t\tvar code = response.code;\n\t      \t\t\t\tvar message = response.message;\n\t      \t\t\t\tif (code == 400) {\n\t      \t\t\t\t\tlayer.msg(message);\n\t      \t\t\t\t} else if (code == 401) {\n\t      \t\t\t\t\tlocalStorage.removeItem(\"token\");\n\t      \t\t\t\t\tlayer.msg(\"token过期，请先登录\", {shift: -1, time: 1000}, function(){\n\t      \t\t\t\t\t\tlocation.href = '/login.html';\n\t                          });\n\t      \t\t\t\t} else if (code == 403) {\n\t      \t\t\t\t\tconsole.log(\"未授权:\" + message);\n\t      \t\t\t\t\tlayer.msg('未授权');\n\t      \t\t\t\t} else if (code == 500) {\n\t      \t\t\t\t\tlayer.msg('系统错误：' + message);\n\t      \t\t\t\t}\n\t      \t\t\t}\n            \t\t });  \n            \t },  \n        \t\"dom\": \"<'dt-toolbar'r>t<'dt-toolbar-footer'<'col-sm-10 col-xs-12 hidden-xs'i><'col-xs-12 col-sm-10' p v>>\",\t\n            \"columns\": [\n                { \"data\": \"name\", \"defaultContent\": \"\"} , \n                { \"data\": \"instance.length\", \"defaultContent\": \"\"}  ,\n                { \n                \t\"data\": \"\", \n                \t\"defaultContent\": \"\",\n                \t\"orderable\":false,\n                \t\"render\": function (data, type, row) {\n                \t\tvar isSysJob = row['isSysJob'];\n                \t\tif(!isSysJob) {\n                \t\t\tvar id = row['name'];\n                    \t\tvar href = \"/eureka/apps?name=\" + id;\n                            //var edit = buttonInfo(href, \"job:add\", pers); \n                            var edit = buttonInfo(id, \"job:add\", pers);\n                            return edit    ;\n                \t\t} else {\n                \t\t\treturn \"<span style='color:red'>系统任务无操作</span>\";\n                \t\t}\n                  \t}\n                }\n            ],\n        } );\n}\n \nfunction info(id){\n\t\n\t\n\t $(\"#dt-instance-table\").DataTable().clear();\n\t $(\"#dt-instance-table\").DataTable().destroy();\n\t \n\tinstance = \n    \t$('#dt-instance-table').DataTable({\n        \t\"searching\": false,\n        \t\"processing\": false,\n        \t\"serverSide\" : true,\n        \t \"bFilter\": false,    //去掉搜索框方法三：这种方法可以\n             \"bLengthChange\": false,   //去掉每页显示多少条数据方法\n             \"bInfo\": false,\n             \"bPaginate\": false,\n        \t\"language\": {\n                \"url\": \"/js/plugin/datatables/Chinese.lang\"\n            },\n            \n            \n            \"ajax\": function (data, callback, settings) {  \n\t            \t //封装请求参数  \n\t            \t var param = {};  \n\t            \t param.limit =data.length;//页面显示记录条数，在页面显示每页显示多少项的时候  \n\t            \t param.start = data.start;//开始的记录序号  \n\t            \t param.page = (data.start / data.length)+1;//当前页码  \n\t            \t //ajax请求数据  \n\t            \t $.ajax({  \n\t\t            \t  type: \"POST\",  \n\t\t            \t  url: '/eureka/appsmd?name='+id,\n\t\t            \t  cache: false, //禁用缓存  \n\t\t            \t  data: param, //传入组装的参数  \n\t\t            \t  dataType: \"json\",  \n\t            \t  \"success\": function (result) {  \n\t\t            \t  //封装返回数据  \n\t\t            \t  var returnData = {};  \n\t\t            \t   returnData.data = result.application.instance;//返回的数据列表  \n\t\t            \t   \n\t\t            \t  //console.log(returnData);  \n\t\t            \t  //调用DataTables提供的callback方法，代表数据已封装完成并传回DataTables进行渲染  \n\t\t            \t  //此时的数据需确保正确无误，异常判断应在执行此回调前自行处理完毕  \n\t\t            \t  callback(returnData);  \n\t\t            \t  \n\t            \t  }  ,\n\t            \t  \"error\":function(xhr, textStatus, errorThrown){\n\t      \t\t\t\tvar msg = xhr.responseText;\n\t      \t\t\t\tconsole.log(msg);\n\t      \t\t\t\tvar response = JSON.parse(msg);\n\t      \t\t\t\tvar code = response.code;\n\t      \t\t\t\tvar message = response.message;\n\t      \t\t\t\tif (code == 400) {\n\t      \t\t\t\t\tlayer.msg(message);\n\t      \t\t\t\t} else if (code == 401) {\n\t      \t\t\t\t\tlocalStorage.removeItem(\"token\");\n\t      \t\t\t\t\tlayer.msg(\"token过期，请先登录\", {shift: -1, time: 1000}, function(){\n\t      \t\t\t\t\t\tlocation.href = '/login.html';\n\t                          });\n\t      \t\t\t\t} else if (code == 403) {\n\t      \t\t\t\t\tconsole.log(\"未授权:\" + message);\n\t      \t\t\t\t\tlayer.msg('未授权');\n\t      \t\t\t\t} else if (code == 500) {\n\t      \t\t\t\t\tlayer.msg('系统错误：' + message);\n\t      \t\t\t\t}\n\t      \t\t\t}\n            \t\t });  \n            \t },  \n        \t\"dom\": \"<'dt-toolbar'r>t<'dt-toolbar-footer'<'col-sm-10 col-xs-12 hidden-xs'i><'col-xs-12 col-sm-10' p v>>\",\t\n            \"columns\": [\n                { \"data\": \"app\", \"defaultContent\": \"\"} ,\n                { \"data\": \"instanceId\", \"defaultContent\": \"\"} ,\n                { \"data\": \"ipAddr\", \"defaultContent\": \"\"}  ,\n                { \"data\": \"port.$\", \"defaultContent\": \"\"}  ,\n                { \"data\": \"status\", \"defaultContent\": \"\"}  ,\n                { \n                \t\"data\": \"\", \n                \t\"defaultContent\": \"\",\n                \t\"orderable\":false,\n                \t\"render\": function (data, type, row) {\n                \t\tvar isSysJob = row['ipAddr'];\n                \t\tif(isSysJob) {\n                            //var edit = buttonInfo(href, \"job:add\", pers); \n                            \n                            var ipAddr = row['ipAddr'];\n                            var port = row['port'].$;\n                            var status =row['status'];\n                            var req ={} ;\n                            req.ip = ipAddr;\n                            req.port = port;\n                            req.status = status;\n                            req.app = row['app'];\n                            req.instanceId = row['instanceId'];\n                            var ops = buttonOps(req, \"job:add\", pers);\n                            var refresh = buttonRefresh(req, \"job:add\", pers);\n                            return ops  + refresh  ;\n                \t\t} else {\n                \t\t\treturn \"<span style='color:red'>系统任务无操作</span>\";\n                \t\t}\n                  \t}\n                }\n            ],\n        } );\n\t\n     \n}\n\nlayui.use('layer', function(){\n    var layer = layui.layer;\n});\n\nfunction del(id){\n    layer.confirm('确定要取消吗？', {\n        btn : [ '确定', '取消' ]\n    }, function() {\n        $.ajax({\n            type : 'delete',\n            url : '/jobs/'+id,\n            success : function(data) {\n            \tservice.ajax.reload();\n                layer.msg(\"取消成功\");\n            }\n        });\n        \n        layer.close(1);\n    });\n}\n\n\n\nfunction ops(app ,instanceId , ip,port,ops){\n\t\n\tvar req = {} ;\n\treq.ip = ip ;\n\treq.port = port ;\n\treq.operate = ops ;\n\treq.app=app ;\n\treq.instanceId= instanceId;\n\tvar str ;\n\tif(ops==1){\n\t\tstr=\"暂停\";\n\t}else if(ops==3){\n\t\tstr=\"恢复\";\n\t}else if(ops==4){\n\t\tstr=\"刷新\";\n\t}\n\t\n    layer.confirm('确定要'+str+'吗？', {\n        btn : [ '确定', '取消' ]\n    }, function() {\n        $.ajax({\n            type : 'post',\n            url : '/eureka/operate',\n            data: JSON.stringify(req),\n            dataType:\"html\",\n            contentType: \"application/json\",\n            success : function(data) {\n            \tservice.ajax.reload();\n                layer.msg(\"操作成功\");\n            }\n        });\n        layer.close(1);\n    });\n}\n \n\ninit();\n</script>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/excel/sql.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/bootstrap.min.css\">\n<link rel=\"stylesheet\" href=\"/lib/layui/css/layui.css\" media=\"all\" />\n</head>\n<body>\n\t<div class=\"col-xs-12 col-sm-12 col-md-12 col-lg-12\">\n\t\t<form class=\"form-horizontal\" id=\"form\" method=\"post\" action=\"/excels\" onsubmit=\"return false\" enctype=\"multipart/form-data\">\n\t\t\t<fieldset>\n\t\t\t\t<input id=\"token\" name=\"token\" hidden=\"true\">\n\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t<label class=\"col-md-2 control-label\">sql</label>\n\t\t\t\t\t<div class=\"col-md-10 form-inline\">\n\t\t\t\t\t\t<textarea rows=\"8\" cols=\"120\" name=\"sql\" id=\"sql\">\nSELECT \n\tid, \n\tusername '用户名', \n\tnickname '昵称' \nFROM \n\tsys_user t \n\t\t\t\t\t\t</textarea>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\n\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t<label class=\"col-md-2 control-label\">导出文件名</label>\n\t\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t\t<input class=\"form-control\" placeholder=\"文件名\" type=\"text\"\n\t\t\t\t\t\t\tmaxlength=\"200\" name=\"fileName\" id=\"fileName\">\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\n\t\t\t\t<div class=\"form-actions\">\n\t\t\t\t\t<div class=\"row\" align=\"center\">\n\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t<button class='btn btn-primary' permission=\"excel:down\" type=\"submit\" onclick=\"download()\">\n\t\t\t\t\t\t\t\t<i class='layui-icon'>&#xe601;</i>导出\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t<button class='btn btn-primary' permission=\"excel:show:datas\" type=\"submit\" onclick=\"showDatas()\">\n\t\t\t\t\t\t\t\t<i class='layui-icon'>&#xe62d;</i>页面显示数据\n\t\t\t\t\t\t\t</button>\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\n\t\t\t\t<div id=\"datas\">\n\t\t\t\t\t<table class=\"table\">\n\t\t\t\t\t</table>\n\t\t\t\t</div>\n\n\t\t\t</fieldset>\n\t\t</form>\n\t</div>\n\t<script type=\"text/javascript\" src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/common.js\"></script>\n\t<script type=\"text/javascript\" src=\"/lib/layui/layui.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/my/permission.js\"></script>\n\t<script type=\"text/javascript\">\n\t\tvar pers = checkPermission();\n\t\tlayui.use([ 'layer' ], function() {\n\t\t\tvar layer = layui.layer;\n\t\t});\n\t\t$(\"#datas\").hide();\n\t\t\n\t\tfunction checkSql() {\n\t\t\tvar sql = $(\"#sql\").val();\n\t\t\tvar flag = false;\n\t\t\tif (sql.trim() == \"\") {\n\t\t\t\tlayer.msg(\"sql不能为空\", {\n\t\t\t\t\tshift : -1,\n\t\t\t\t\ttime : 1000\n\t\t\t\t}, function() {\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\t$.ajax({\n\t\t\t\t\ttype : 'post',\n\t\t\t\t\tasync:false,\n\t\t\t\t\turl : '/excels/sql-count?sql='+sql,\n\t\t\t\t\tcontentType: \"application/json; charset=utf-8\",  \n\t\t\t\t\tsuccess : function(data) {\n\t\t\t\t\t\tif(data == 0){\n\t\t\t\t\t\t\tlayer.msg(\"0条数据，请检查sql\", {shift: -1, time: 1000}, function(){});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tflag = true;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn flag;\n\t\t}\n\n\t\tfunction download() {\n\t\t\tif(!checkSql()){\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\t$(\"#token\").val(localStorage.getItem(\"token\"));\n\t\t\t$(\"#form\").attr(\"onsubmit\", \"return true\");\n\t\t\t$(\"#form\").submit();\n\t\t\t$(\"#form\").attr(\"onsubmit\", \"return false\");\n\t\t}\n\t\t\n\t\tfunction showDatas(){\n\t\t\tif(!checkSql()){\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\t$.ajax({\n\t\t\t\ttype : 'post',\n\t\t\t\tasync:false,\n\t\t\t\turl : '/excels/show-datas?sql='+$(\"#sql\").val(),\n\t\t\t\tcontentType: \"application/json; charset=utf-8\",  \n\t\t\t\tsuccess : function(data) {\n\t\t\t\t\tvar size = data.length;\n\t\t\t\t\tif(size == 0){\n\t\t\t\t\t\tlayer.msg(\"0条数据\", {shift: -1, time: 1000}, function(){});\n\t\t\t\t\t}else{\n\t\t\t\t\t\t$(\"#datas\").show();\n\t\t\t\t\t\tvar table = $(\"#datas table\");\n\t\t\t\t\t\ttable.empty();\n\t\t\t\t\t\tfor(var i=0;i<size;i++){\n\t\t\t\t\t\t\tvar tr = $(\"<tr></tr>\");\n\t\t\t\t\t\t\tvar ds = data[i];\n\t\t\t\t\t\t\tfor(var t=0;t<ds.length;t++){\n\t\t\t\t\t\t\t\tvar d = ds[t];\n\t\t\t\t\t\t\t\tif(d == null){\n\t\t\t\t\t\t\t\t\td = \"\";\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\ttr.append(\"<td>\"+d+\"</td>\")\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\ttable.append(tr);\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</script>\n</body>\n</html>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/file/fileList.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<title>Insert title here</title>\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/bootstrap.min.css\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/dataTables.bootstrap.min.css\">\n<link rel=\"stylesheet\" href=\"/lib/layui/css/layui.css\" media=\"all\" />\n</head>\n<body>\n    <div>\n        <div class=\"col-xs-12 col-sm-12 col-md-12 col-lg-12\">\n            <div>\n                <header style=\"height: 100%\">\n\t\t\t\t\t <div align=\"left\">\n                        <table style=\"width: 100%\">\n                            <tr>\n                                <td>\n                                    <button type=\"button\" class=\"layui-btn\" id=\"test1\">\n\t\t\t\t\t\t\t\t\t  <i class=\"layui-icon\">&#xe67c;</i>上传文件\n\t\t\t\t\t\t\t\t\t</button>\n                                </td>\n                                <td align=\"right\">\n                                    <form class=\"form-inline\" onsubmit=\"return false\">\n                                        <div class=\"form-group\">\n                                           <button id=\"searchBt\" class=\"layui-btn layui-btn-sm\" permission=\"sys:file:query\"><i class=\"layui-icon\">&#xe615;</i>搜索</button>\n                                        </div>\n                                    </form>\n                                </td>\n                            </tr> \n                        </table>\n                    </div>\n                </header>\n                \n                <div>\n                    <div class=\"widget-body no-padding\">\n                        <table id=\"dt-table\" class=\"table table-striped table-bordered table-hover\" style=\"width:100%\">\n                            <thead>\n                                <tr>\n                                </tr>                       \n                                <tr>\n                                    <th>url</th>\n                                    <th>path</th>\n                                    <th>contentType</th>\n                                    <th>修改时间</th>\n                                    <th>管理</th>\n                                </tr>\n                            </thead>\n                            <tbody>\n                            </tbody>\n                        </table>\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>\n</body>\n</html>\n\n<script type=\"text/javascript\" src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n<script type=\"text/javascript\" src=\"/lib/layui/layui.js\"></script>\n<script type=\"text/javascript\" src=\"/js/plugin/datatables/jquery.dataTables.min.js\"></script>\n<script type=\"text/javascript\" src=\"/js/plugin/datatables/dataTables.bootstrap.min.js\"></script>\n<script type=\"text/javascript\" src=\"/js/my/permission.js\"></script>\n<script type=\"text/javascript\">\nvar pers = checkPermission();\n\nvar pro = window.location.protocol;\nvar host = window.location.host;\nvar domain = pro + \"//\" + host;\n\nvar example;\nfunction init(){\n\texample = \n    \t$('#dt-table').DataTable({\n        \t\"searching\": false,\n        \t\"processing\": false,\n        \t\"serverSide\" : true,\n        \t\"language\": {\n                \"url\": \"/js/plugin/datatables/Chinese.lang\"\n            },\n        \t\"ajax\": {\n        \t\t\"url\" : \"/files\",\n        \t\t\"type\":\"get\",\n        \t\t\"data\":function(d){\n    \t\t\t\n        \t\t},\n    \t\t\t\"error\":function(xhr, textStatus, errorThrown){\n    \t\t\t\tvar msg = xhr.responseText;\n    \t\t\t\tconsole.log(msg);\n    \t\t\t\tvar response = JSON.parse(msg);\n    \t\t\t\tvar code = response.code;\n    \t\t\t\tvar message = response.message;\n    \t\t\t\tif (code == 400) {\n    \t\t\t\t\tlayer.msg(message);\n    \t\t\t\t} else if (code == 401) {\n    \t\t\t\t\tlocalStorage.removeItem(\"token\");\n    \t\t\t\t\tlayer.msg(\"token过期，请先登录\", {shift: -1, time: 1000}, function(){\n    \t\t\t\t\t\tlocation.href = '/login.html';\n                        });\n    \t\t\t\t} else if (code == 403) {\n    \t\t\t\t\tconsole.log(\"未授权:\" + message);\n    \t\t\t\t\tlayer.msg('未授权');\n    \t\t\t\t} else if (code == 500) {\n    \t\t\t\t\tlayer.msg('系统错误：' + message);\n    \t\t\t\t}\n    \t\t\t}\n        \t},\n        \t\"dom\": \"<'dt-toolbar'r>t<'dt-toolbar-footer'<'col-sm-10 col-xs-12 hidden-xs'i><'col-xs-12 col-sm-10' p v>>\",\t\n            \"columns\": [\n                { \n                \t\"data\": \"url\", \n                \t\"defaultContent\": \"\",\n                \t\"render\": function (data, type, row) {\n                \t\tvar url = row['url'];\n                \t\tvar type = row['type'];\n                \t\tvar u = \"\";\n                \t\tif(type == 1) {\n                \t\t\tvar src = domain + \"/statics\" + url;\n                \t\t\tu = \"<a target='_blank' href='\" + src +\"'><img width='30' src='\" + src + \"'></img></a>\";\n                \t\t} else {\n                \t\t\tu = url;\n                \t\t}\n                    \treturn u;\n                  \t}\n                },\n                { \"data\": \"path\", \"defaultContent\": \"\"},\n                { \"data\": \"contentType\", \"defaultContent\": \"\"},\n                { \"data\": \"updateTime\", \"defaultContent\": \"\"},\n                { \n                \t\"data\": \"\", \n                \t\"defaultContent\": \"\",\n                \t\"orderable\":false,\n                \t\"render\": function (data, type, row) {\n                \t\tvar id = row['id'];\n                        var del = buttonDel(id, \"sys:file:del\", pers);\n                        return del;\n                  \t}\n                },\n                \n            ],\n           \"order\": [[ 3, \"desc\" ]]\n        } );\n}\n\nfunction del(id){\n\tlayer.confirm('确定要删除吗？', {\n        btn : [ '确定', '取消' ]\n    }, function() {\n    \t$.ajax({\n            type : 'delete',\n            url : '/files/'+id,\n            success : function(data) {\n                example.ajax.reload();\n                layer.msg(\"删除成功\");\n            }\n        });\n        \n        layer.close(1);\n    });\n}\n\n$(\"#searchBt\").click(function(){\n\texample.ajax.reload();\n});\n\nlayui.use('upload', function(){\n\tvar upload = layui.upload;\n\tupload.render({\n\t    elem: '#test1' //绑定元素\n\t    ,accept: 'file' //允许上传的文件类型\n\t    ,url: '/files' //上传接口\n\t    ,done: function(res, index, upload){\n\t    \tlayer.msg(\"上传成功\");\n\t\t \texample.ajax.reload();\n\t    }\n\t  });\n});\n\ninit();\n</script>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/generate/edit.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"../../css/bootstrap.min.css\">\n</head>\n<body>\n<div class=\"col-xs-12 col-sm-12 col-md-12 col-lg-12\">\n    <form class=\"form-horizontal\" onsubmit=\"return false\" id=\"form\">\n        <fieldset>\n            <div class=\"form-group\">\n                <label class=\"col-md-2 control-label\">表名</label>\n                <div class=\"col-md-10\">\n                    <input class=\"form-control\" placeholder=\"表名\" type=\"text\" name=\"tableName\" id=\"tableName\" value=\"sys_user\"\n                        data-bv-notempty=\"true\"\n                        data-bv-notempty-message=\"表名 不能为空\">\n                    <button id=\"showInfo\" class=\"btn btn-primary\">预览代码</button>\n                    <button id=\"save\" class=\"btn btn-primary\">保存代码</button>\n                </div>\n            </div>\n        </fieldset>\n        <div id=\"detail\">\n\t        <fieldset>\n\t           <table class=\"table\">\n                  <caption>基本配置</caption>\n                  <tbody>\n                    <tr>\n                      <td width=\"10%\">路径</td>\n                      <td>\n                        <input class=\"form-control\" placeholder=\"路径\" type=\"text\" name=\"path\" id=\"path\" value=\"d:/generate\"\n                                data-bv-notempty=\"true\"\n                                data-bv-notempty-message=\"路径 不能为空\">\n                      </td>\n                      <td width=\"10%\"></td>\n                      <td width=\"15%\"></td>\n                      <td width=\"5%\"></td>\n                      <td></td>\n                      <td width=\"5%\"></td>\n                      <td width=\"15%\"></td>\n                    </tr>\n                    <tr>\n                      <td>bean包名</td>\n                      <td>\n                        <input class=\"form-control\" placeholder=\"bean包名\" type=\"text\" name=\"beanPackageName\" id=\"beanPackageName\" value=\"com.open.capacity.security.model\"\n                                data-bv-notempty=\"true\"\n                                data-bv-notempty-message=\"bean包名 不能为空\">\n                      </td>\n                      <td>bean类名</td>\n                      <td>\n                        <input class=\"form-control\" placeholder=\"bean类名\" type=\"text\" name=\"beanName\" id=\"beanName\" value=\"BeanTest\"\n                                data-bv-notempty=\"true\"\n                                data-bv-notempty-message=\"bean类名 不能为空\">\n                      </td>\n                      <td>dao包名</td>\n                      <td>\n                        <input class=\"form-control\" placeholder=\"dao包名\" type=\"text\" name=\"daoPackageName\" id=\"daoPackageName\" value=\"com.open.capacity.security.dao\"\n                                data-bv-notempty=\"true\"\n                                data-bv-notempty-message=\"dao包名 不能为空\">\n                      </td>\n                      <td>dao类名</td>\n                      <td>\n                        <input class=\"form-control\" placeholder=\"dao类名\" type=\"text\" name=\"daoName\" id=\"daoName\" value=\"BeanTestDao\"\n                                data-bv-notempty=\"true\"\n                                data-bv-notempty-message=\"dao类名 不能为空\">\n                      </td>\n                    </tr>\n                    <tr>\n                        <td>controller包名</td>\n\t                    <td>\n\t                        <input class=\"form-control\" placeholder=\"controller包名\" type=\"text\" name=\"controllerPkgName\" id=\"controllerPkgName\" value=\"com.open.capacity.security.controller\"\n\t                                data-bv-notempty=\"true\"\n\t                                data-bv-notempty-message=\"bean包名 不能为空\">\n\t                    </td>\n                        <td>controller类名</td>\n                        <td>\n                         <input class=\"form-control\" placeholder=\"controller类名\" type=\"text\" name=\"controllerName\" id=\"controllerName\" value=\"ControllerTest\"\n                                data-bv-notempty=\"true\"\n                                data-bv-notempty-message=\"bean类名 不能为空\">\n                        </td>\n                    </tr>\n                  </tbody>\n                </table>\n\t        </fieldset>\n            <table class=\"table\">\n                <caption>字段详情</caption>\n                <thead>\n                    <tr>\n                        <th>表字段名</th>\n                        <th>表类型</th>\n                        <th>字段描述</th>\n                        <th>java字段名</th>\n                        <th>java字段类型</th>\n                        <th>默认值</th>\n                    </tr>\n                </thead>\n                <tbody id=\"beanFields\">\n                </tbody>\n            </table>\n        </div>\n    </form>\n</div>\n\n    <script type=\"text/javascript\" src=\"../../js/libs/jquery-2.1.1.min.js\"></script>\n    <script type=\"text/javascript\" src=\"../../js/jq.js\"></script>\n    <script type=\"text/javascript\" src=\"../../lib/layui/layui.js\"></script>\n\t<script type=\"text/javascript\" src=\"../../js/plugin/bootstrapvalidator/bootstrapValidator.min.js\"></script>\n    <script type=\"text/javascript\" src=\"../../js/common.js\"></script>\n    <script type=\"text/javascript\">\n    layui.use('layer', function(){\n\t    var layer = layui.layer;\n\t});\n    \n    $('#form').bootstrapValidator();\n    $(\"#detail\").hide();\n    $(\"#save\").hide();\n    \n    $(\"#showInfo\").click(function(){\n        var bootstrapValidator = $(\"#form\").data('bootstrapValidator');\n        bootstrapValidator.validate();\n        if(!bootstrapValidator.isValid()){\n           return;\n        }\n        var beanFields = $(\"#beanFields\");\n        beanFields.html(\"\");\n        $.ajax({\n            type : 'get',\n            url : '/generate',\n            data : \"tableName=\" + $(\"#tableName\").val(),\n            success : function(data) {\n                $(\"#detail\").show();\n                $(\"#save\").show();\n                \n                var beanName = data.beanName;\n                $(\"#beanName\").val(beanName);\n                $(\"#daoName\").val(beanName + \"Dao\");\n                $(\"#controllerName\").val(beanName + \"Controller\");\n                var fields = data.fields;\n                var length = fields.length;\n                \n                for(var i=0;i<length;i++){\n                    var f = fields[i];\n                    var tr = $(\"<tr></tr>\");\n                    \n                    var columnName = f['columnName'];\n                    var columnNameInput = \"<input type='hidden' name='columnNames' value='\" + columnName +\"'>\"\n                    \n                    tr.append(\"<td>\" + columnNameInput + columnName + \"</td>\");\n                    tr.append(\"<td>\" + f['columnType'] + \"</td>\");\n                    tr.append(\"<td>\" + f['columnComment'] + \"</td>\");\n                    var name = f['name'];\n                    var nameInput = \"<input name='beanFieldName' class='form-control' value='\" + name +\"'>\";\n                    tr.append(\"<td>\" + nameInput + \"</td>\");\n                    \n                    var type = f['type'];\n                    var typeInput = \"<input name='beanFieldType' class='form-control' value='\" + type +\"'>\"\n                    tr.append(\"<td>\" + typeInput + \"</td>\");\n                    \n                    var val = f['columnDefault'];\n                    var valInput = \"<input name='beanFieldValue' class='form-control' value='\" + val +\"'>\"\n                    tr.append(\"<td>\" + valInput + \"</td>\");\n                    \n                    beanFields.append(tr);\n                }\n            }\n        });\n    });\n    \n    $(\"#save\").click(function(){\n        var bootstrapValidator = $(\"#form\").data('bootstrapValidator');\n        bootstrapValidator.validate();\n        if(!bootstrapValidator.isValid()){\n           return;\n        }\n        if($(\"#detail\").is(':hidden')) {\n           return;\n        }\n        \n        var formdata = $(\"#form\").serializeObject();\n        $.ajax({\n            type : 'post',\n            url : '/generate',\n            contentType: \"application/json; charset=utf-8\",  \n            data : JSON.stringify(formdata),\n            success : function(data) {\n                $(\"#detail\").hide();\n                $(\"#save\").hide();\n                layer.msg(\"生成成功\");\n            }\n        });\n    });\n\n    \n    </script>\n</body>\n</html>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/job/addJob.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/bootstrap.min.css\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/bootstrap-select.min.css\">\n</head>\n<body>\n<div class=\"col-xs-12 col-sm-12 col-md-12 col-lg-12\">\n\t<form class=\"form-horizontal\" onsubmit=\"return false\" id=\"form\">\n\t\t<fieldset>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">job名</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<input class=\"form-control\" placeholder=\"job名\" type=\"text\" maxlength=\"60\" name=\"jobName\"\n\t\t\t\t\t\tdata-bv-notempty=\"true\"\n\t\t\t\t\t\tdata-bv-notempty-message=\"job名 不能为空\">\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">cron表达式</label>\n\t\t\t\t<div class=\"col-md-10 form-inline\">\n\t\t\t\t\t<input class=\"form-control\" placeholder=\"cron表达式\" type=\"text\" name=\"cron\" id=\"cron\"\n\t\t\t\t\t\tdata-bv-notempty=\"true\"\n\t\t\t\t\t\tdata-bv-notempty-message=\"cron表达式 不能为空\"><button class=\"btn btn-primary\" onclick=\"checkCron()\">检查</button>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">job描述</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<input class=\"form-control\" placeholder=\"job描述\" type=\"text\" maxlength=\"200\" name=\"description\">\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">springBeanName</label>\n\t\t\t\t<div class=\"col-md-10 form-inline\">\n\t\t\t\t\t<select class=\"selectpicker show-tick form-control\" data-live-search=\"true\" name=\"springBeanName\" id=\"springBeanName\" onchange=\"showMethods()\"></select>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">方法名<span style=\"color: red\">（目前仅支持无参方法）</span></label>\n\t\t\t\t<div class=\"col-md-10 form-inline\">\n\t\t\t\t\t<select class=\"form-control\" name=\"methodName\" id=\"methodName\" \n\t\t\t\t\t\tdata-bv-notempty=\"true\"\n\t\t\t\t\t\tdata-bv-notempty-message=\"方法名 不能为空\"></select>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"form-actions\">\n\t\t\t\t<div class=\"row\" align=\"center\">\n\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t    <button class=\"btn btn-primary\" onclick=\"location.href='jobList.html'\">返回</button>\n\t\t\t\t\t\t<button class=\"btn btn-primary\" type=\"submit\" onclick=\"add()\">\n\t\t\t\t\t\t\t<i class=\"fa fa-save\"></i> 保存\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t</fieldset>\n\t</form>\n</div>\n\t<script type=\"text/javascript\" src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/bootstrap/bootstrap.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/bootstrap/bootstrap-select.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/plugin/bootstrapvalidator/bootstrapValidator.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/common.js\"></script>\n\t<script type=\"text/javascript\" src=\"/lib/layui/layui.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/my/job.js\"></script>\n\t<script type=\"text/javascript\">\n\t\tlayui.use(['layer'], function(){\n\t\t    var layer = layui.layer;\n\t\t});\n\t\t\n\t\tinitBeanNames();\n\t\tshowMethods();\n\t\t\n\t\tfunction add() {\n\t\t\t$('#form').bootstrapValidator();\n\t\t\tvar bootstrapValidator = $(\"#form\").data('bootstrapValidator');\n\t\t\tbootstrapValidator.validate();\n\t\t    if(!bootstrapValidator.isValid()){\n\t\t\t   return;\n\t\t    }\n\t\t    \n\t\t    var formdata = $(\"#form\").serializeObject();\n\n\t\t\t$.ajax({\n\t\t\t\ttype : 'post',\n\t\t\t\turl : '/jobs',\n\t\t\t\tcontentType: \"application/json; charset=utf-8\",  \n\t\t\t\tdata : JSON.stringify(formdata),\n\t\t\t\tsuccess : function(data) {\n\t\t\t\t\tlayer.msg(\"添加成功\", {shift: -1, time: 1000}, function(){\n                        location.href = \"jobList.html\";\n                    });\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\t\n\t</script>\n</body>\n</html>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/job/jobList.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<title>Insert title here</title>\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/bootstrap.min.css\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/dataTables.bootstrap.min.css\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/lib/layui/css/layui.css\">\n</head>\n<body>\n    <div>\n        <div class=\"col-xs-12 col-sm-12 col-md-12 col-lg-12\">\n                <header style=\"height: 100%\">\n                    <div align=\"left\">\n\t                    <table style=\"width: 100%\">\n\t                   \t\t<tr>\n\t                   \t\t\t<td>\n\t\t                   \t\t\t<form class=\"form-inline\" onsubmit=\"return false\">\n\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t描述：\n\t\t\t\t\t\t\t\t\t\t\t<input id=\"description\" type=\"text\" class=\"form-control\" placeholder=\"描述\">\n\t\t\t\t\t\t\t\t\t\t\t<select class=\"form-control input-sm\" id=\"status\">\n\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"\">全部</option>\n\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"1\">正常</option>\n\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"0\">取消</option>\n\t\t\t\t\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\t\t\t\t\t<button id=\"searchBt\" class=\"layui-btn layui-btn-sm\" permission=\"job:query\"><i class=\"layui-icon\">&#xe615;</i>搜索</button>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</form>\n\t                   \t\t\t</td>\n\t                   \t\t\t<td align=\"right\">\n\t                   \t\t\t\t<button class=\"layui-btn layui-btn-sm\" onclick=\"location.href='addJob.html'\" permission=\"job:add\">\n                                      <i class=\"layui-icon\">&#xe608;</i> 添加\n                                    </button>\n\t                   \t\t\t</td>\n\t                   \t\t</tr> \n\t                    </table>\n\t\t\t\t\t</div>\n                </header>\n                \n                <div>\n                    <div class=\"widget-body no-padding\">\n                        <table id=\"dt-table\" class=\"table table-striped table-bordered table-hover\" style=\"width:100%\">\n                            <thead>\n                                <tr>\n                                </tr>                       \n                                <tr>\n                                    <th>id</th>\n                                    <th>job名</th>\n                                    <th>cron表达式</th>\n                                    <th>bean名</th>\n                                    <th>方法名</th>\n\t\t\t\t\t\t\t\t\t<th>描述</th>\n\t\t\t\t\t\t\t\t\t<th>状态</th>\n\t\t\t\t\t\t\t\t\t<th>修改时间</th>\n\t\t\t\t\t\t\t\t\t<th>操作</th>\n                                </tr>\n                            </thead>\n                            <tbody>\n                            </tbody>\n                        </table>\n                    </div>\n                </div>\n        </div>\n    </div>\n</body>\n</html>\n\n<script type=\"text/javascript\" src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n<script type=\"text/javascript\" src=\"/js/plugin/datatables/jquery.dataTables.min.js\"></script>\n<script type=\"text/javascript\" src=\"/js/plugin/datatables/dataTables.bootstrap.min.js\"></script>\n<script type=\"text/javascript\" src=\"/lib/layui/layui.js\"></script>\n<script type=\"text/javascript\" src=\"/js/my/permission.js\"></script>\n<script type=\"text/javascript\">\nvar pers = checkPermission();\n\nvar example;\nfunction init(){\n\texample = \n    \t$('#dt-table').DataTable({\n        \t\"searching\": false,\n        \t\"processing\": false,\n        \t\"serverSide\" : true,\n        \t\"language\": {\n                \"url\": \"/js/plugin/datatables/Chinese.lang\"\n            },\n        \t\"ajax\": {\n        \t\t\"url\" : \"/jobs\",\n        \t\t\"type\":\"get\",\n        \t\t\"data\":function(d){\n    \t\t\t\td.description = $('#description').val();\n    \t\t\t\td.status = $('#status').val();\n        \t\t},\n    \t\t\t\"error\":function(xhr, textStatus, errorThrown){\n    \t\t\t\tvar msg = xhr.responseText;\n    \t\t\t\tconsole.log(msg);\n    \t\t\t\tvar response = JSON.parse(msg);\n    \t\t\t\tvar code = response.code;\n    \t\t\t\tvar message = response.message;\n    \t\t\t\tif (code == 400) {\n    \t\t\t\t\tlayer.msg(message);\n    \t\t\t\t} else if (code == 401) {\n    \t\t\t\t\tlocalStorage.removeItem(\"token\");\n    \t\t\t\t\tlayer.msg(\"token过期，请先登录\", {shift: -1, time: 1000}, function(){\n    \t\t\t\t\t\tlocation.href = '/login.html';\n                        });\n    \t\t\t\t} else if (code == 403) {\n    \t\t\t\t\tconsole.log(\"未授权:\" + message);\n    \t\t\t\t\tlayer.msg('未授权');\n    \t\t\t\t} else if (code == 500) {\n    \t\t\t\t\tlayer.msg('系统错误：' + message);\n    \t\t\t\t}\n    \t\t\t}\n        \t},\n        \t\"dom\": \"<'dt-toolbar'r>t<'dt-toolbar-footer'<'col-sm-10 col-xs-12 hidden-xs'i><'col-xs-12 col-sm-10' p v>>\",\t\n            \"columns\": [\n                { \"data\": \"id\", \"defaultContent\": \"\"},\n                { \"data\": \"jobName\", \"defaultContent\": \"\"},\n                { \"data\": \"cron\", \"defaultContent\": \"\"},\n                { \"data\": \"springBeanName\", \"defaultContent\": \"\"},\n                { \"data\": \"methodName\", \"defaultContent\": \"\"},\n                { \"data\": \"description\", \"defaultContent\": \"\"},\n                { \n                \t\"data\": \"status\", \n                \t\"defaultContent\": \"\",\n                \t\"render\": function (data, type, row) {\n                \t\tvar status = row['status'];\n                \t\tvar a = \"\";\n                \t\tif(status == 1){\n                \t\t\ta = \"正常\";\n                \t\t} else {\n                \t\t\ta = \"<span style='color:red'>取消</span>\";\n                \t\t}\n                    \treturn a;\n                  \t}\n                },\n                { \"data\": \"updateTime\", \"defaultContent\": \"\"},\n                { \n                \t\"data\": \"\", \n                \t\"defaultContent\": \"\",\n                \t\"orderable\":false,\n                \t\"render\": function (data, type, row) {\n                \t\tvar isSysJob = row['isSysJob'];\n                \t\tif(!isSysJob) {\n                \t\t\tvar id = row['id'];\n                    \t\tvar href = \"updateJob.html?id=\" + id;\n                            var edit = buttonEdit(href, \"job:add\", pers);\n                    \t\tvar del = buttonDel(id, \"job:del\", pers);\n                            return edit + del;\n                \t\t} else {\n                \t\t\treturn \"<span style='color:red'>系统任务无操作</span>\";\n                \t\t}\n                  \t}\n                },\n            ],\n            \"order\": [[6, \"desc\"],[ 7, \"desc\" ]]\n        } );\n}\n\nlayui.use('layer', function(){\n    var layer = layui.layer;\n});\n\nfunction del(id){\n    layer.confirm('确定要取消吗？', {\n        btn : [ '确定', '取消' ]\n    }, function() {\n        $.ajax({\n            type : 'delete',\n            url : '/jobs/'+id,\n            success : function(data) {\n                example.ajax.reload();\n                layer.msg(\"取消成功\");\n            }\n        });\n        \n        layer.close(1);\n    });\n}\n\n$(\"#searchBt\").click(function(){\n\texample.ajax.reload();\n});\n\ninit();\n</script>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/job/updateJob.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/bootstrap.min.css\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/bootstrap-select.min.css\">\n</head>\n<body>\n<div class=\"col-xs-12 col-sm-12 col-md-12 col-lg-12\">\n\t<form class=\"form-horizontal\" onsubmit=\"return false\" id=\"form\">\n\t\t<fieldset>\n\t\t\t<input type=\"hidden\" id=\"id\" name=\"id\">\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">job名</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<input class=\"form-control\" placeholder=\"job名\" type=\"text\" maxlength=\"60\" name=\"jobName\" id=\"jobName\" readonly=\"readonly\">\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">cron表达式</label>\n\t\t\t\t<div class=\"col-md-10 form-inline\">\n\t\t\t\t\t<input class=\"form-control\" placeholder=\"cron表达式\" type=\"text\" name=\"cron\" id=\"cron\"\n\t\t\t\t\t\tdata-bv-notempty=\"true\"\n\t\t\t\t\t\tdata-bv-notempty-message=\"cron表达式 不能为空\"><button class=\"btn btn-primary\" onclick=\"checkCron()\">检查</button>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">job描述</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<input class=\"form-control\" placeholder=\"job描述\" type=\"text\" maxlength=\"200\" name=\"description\" id=\"description\">\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">springBeanName</label>\n\t\t\t\t<div class=\"col-md-10 form-inline\">\n\t\t\t\t\t<select class=\"selectpicker show-tick form-control\" data-live-search=\"true\" name=\"springBeanName\" id=\"springBeanName\" onchange=\"showMethods()\"></select>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">方法名<span style=\"color: red\">（目前仅支持无参方法）</span></label>\n\t\t\t\t<div class=\"col-md-10 form-inline\">\n\t\t\t\t\t<select class=\"form-control\" name=\"methodName\" id=\"methodName\" \n\t\t\t\t\t\tdata-bv-notempty=\"true\"\n\t\t\t\t\t\tdata-bv-notempty-message=\"方法名 不能为空\"></select>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"form-actions\">\n\t\t\t\t<div class=\"row\" align=\"center\">\n\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t    <button class=\"btn btn-primary\" onclick=\"location.href='jobList.html'\">返回</button>\n\t\t\t\t\t\t<button class=\"btn btn-primary\" type=\"submit\" onclick=\"update()\">\n\t\t\t\t\t\t\t<i class=\"fa fa-save\"></i> 保存\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t</fieldset>\n\t</form>\n</div>\n\t<script type=\"text/javascript\" src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/bootstrap/bootstrap.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/bootstrap/bootstrap-select.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/plugin/bootstrapvalidator/bootstrapValidator.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/common.js\"></script>\n\t<script type=\"text/javascript\" src=\"/lib/layui/layui.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/my/job.js\"></script>\n\t<script type=\"text/javascript\">\n\t\tlayui.use(['layer','laydate'], function(){\n\t\t    var layer = layui.layer;\n\t\t});\n\t\t\n\t\tinitBeanNames();\n\t\tinitData();\n\t\t\n\t\tfunction initData(){\n\t\t\tvar id = getUrlParam(\"id\");\n\t\t\tif(id != \"\"){\n\t\t\t\t$.ajax({\n\t\t\t\t\ttype : 'get',\n\t\t\t\t\turl : '/jobs/'+id,\n\t\t\t\t\tasync : false,\n\t\t\t\t\tsuccess : function(data) {\n\t\t\t\t\t\t$(\"#id\").val(data.id);\n\t\t\t\t\t\t$(\"#jobName\").val(data.jobName);\n\t\t\t\t\t\t$(\"#cron\").val(data.cron);\n\t\t\t\t\t\t$(\"#description\").val(data.description);\n\t\t\t\t\t//\t$(\"#springBeanName\").val(data.springBeanName);\n\t\t\t\t\t\t$('.selectpicker').selectpicker('val', data.springBeanName);\n\t\t\t\t\t\tshowMethods();\n\t\t\t\t\t\t$(\"#methodName\").val(data.methodName);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tfunction update() {\n\t\t\t$('#form').bootstrapValidator();\n\t\t\tvar bootstrapValidator = $(\"#form\").data('bootstrapValidator');\n\t\t\tbootstrapValidator.validate();\n\t\t    if(!bootstrapValidator.isValid()){\n\t\t\t   return;\n\t\t    }\n\t\t    \n\t\t    var formdata = $(\"#form\").serializeObject();\n\n\t\t\t$.ajax({\n\t\t\t\ttype : 'put',\n\t\t\t\turl : '/jobs',\n\t\t\t\tcontentType: \"application/json; charset=utf-8\",  \n\t\t\t\tdata : JSON.stringify(formdata),\n\t\t\t\tsuccess : function(data) {\n\t\t\t\t\tlayer.msg(\"修改成功\", {shift: -1, time: 1000}, function(){\n                        location.href = \"jobList.html\";\n                    });\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\t\n\t</script>\n</body>\n</html>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/log/logList.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<title>Insert title here</title>\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/bootstrap.min.css\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/dataTables.bootstrap.min.css\">\n<link rel=\"stylesheet\" href=\"/lib/layui/css/layui.css\" media=\"all\" />\n</head>\n<body>\n    <div>\n        <div class=\"col-xs-12 col-sm-12 col-md-12 col-lg-12\">\n            <div>\n                <header style=\"height: 100%\">\n\t\t\t\t\t <div align=\"left\">\n                        <table style=\"width: 100%\">\n                            <tr>\n                                <td>\n\t\t\t\t\t\t\t\t\t<form class=\"form-inline\" onsubmit=\"return false\">\n\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t昵称：\n\t\t\t\t\t\t\t\t\t\t\t<input id=\"nickname\" type=\"text\" class=\"form-control\" placeholder=\"昵称\">\n\t\t\t\t\t\t\t\t\t\t\t时间：\n\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" class=\"form-control\" placeholder=\"开始时间\" id=\"beginTime\">\n\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" class=\"form-control\" placeholder=\"结束时间\" id=\"endTime\">\n\t\t\t\t\t\t\t\t\t\t\t状态：\n\t\t\t\t\t\t\t\t\t\t\t<select class=\"form-control input-sm\" id=\"flag\">\n\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"\">全部</option>\n\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"1\">成功</option>\n\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"0\">失败</option>\n\t\t\t\t\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\t\t\t\t\t<button id=\"searchBt\" class=\"layui-btn layui-btn-sm\" permission=\"sys:log:query\"><i class=\"layui-icon\">&#xe615;</i>搜索</button>\n\t\t\t\t\t\t\t\t\t\t\t<input name=\"logids\" type=\"hidden\">\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</form>\n\t\t\t\t\t\t\t\t</td>\n                            </tr> \n                        </table>\n                    </div>\n                </header>\n                \n                <div>\n                    <div class=\"widget-body no-padding\">\n                        <table id=\"dt-table\" class=\"table table-bordered table-condensed table-hover\" style=\"width:100%\">\n                            <thead>\n                                <tr>\n                                </tr>                       \n                                <tr>\n                                \t<th><input type=\"checkbox\" name=\"allChecked\" /></th>\n\t\t\t\t\t\t\t\t\t<th width=\"5%\">id</th>\n\t\t\t\t\t\t\t\t\t<th width=\"15%\">昵称</th>\n\t\t\t\t\t\t\t\t\t<th width=\"20%\">模块</th>\n\t\t\t\t\t\t\t\t\t<th width=\"5%\">状态</th>\n\t\t\t\t\t\t\t\t\t<th>备注</th>\n\t\t\t\t\t\t\t\t\t<th width=\"15%\">时间</th>\n                                </tr>\n                            </thead>\n                             <tbody>\n                            </tbody>\n                        </table>\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>\n</body>\n</html>\n\n<script type=\"text/javascript\" src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n<script type=\"text/javascript\" src=\"/lib/layui/layui.js\"></script>\n<script type=\"text/javascript\" src=\"/js/plugin/datatables/jquery.dataTables.min.js\"></script>\n<script type=\"text/javascript\" src=\"/js/plugin/datatables/dataTables.bootstrap.min.js\"></script>\n<script type=\"text/javascript\" src=\"/js/my/permission.js\"></script>\n<script type=\"text/javascript\">\nvar pers = checkPermission();\nlayui.use(['layer','laydate'], function(){\n    var layer = layui.layer;\n    var laydate = layui.laydate;\n    laydate.render({\n       elem: '#beginTime'\n    });\n    laydate.render({\n       elem: '#endTime'\n    });\n});\n\nvar example;\nfunction init(){\n\texample = \n    \t$('#dt-table').DataTable({\n        \t\"searching\": false,\n        \t\"processing\": false,\n        \t\"serverSide\" : true,\n        \t\"language\": {\n                \"url\": \"/js/plugin/datatables/Chinese.lang\"\n            },\n        \t\"ajax\": {\n        \t\t\"url\" : \"/logs\",\n        \t\t\"type\":\"get\",\n        \t\t\"data\":function(d){\n        \t\t\td.flag = $('#flag').val();\n        \t\t\td.nickname = $('#nickname').val();\n        \t\t\td.beginTime = $('#beginTime').val();\n    \t\t\t\td.endTime = $('#endTime').val();\n        \t\t},\n    \t\t\t\"error\":function(xhr, textStatus, errorThrown){\n    \t\t\t\tvar msg = xhr.responseText;\n    \t\t\t\tconsole.log(msg);\n    \t\t\t\tvar response = JSON.parse(msg);\n    \t\t\t\tvar code = response.code;\n    \t\t\t\tvar message = response.message;\n    \t\t\t\tif (code == 400) {\n    \t\t\t\t\tlayer.msg(message);\n    \t\t\t\t} else if (code == 401) {\n    \t\t\t\t\tlocalStorage.removeItem(\"token\");\n    \t\t\t\t\tlayer.msg(\"token过期，请先登录\", {shift: -1, time: 1000}, function(){\n    \t\t\t\t\t\tlocation.href = '/login.html';\n                        });\n    \t\t\t\t} else if (code == 403) {\n    \t\t\t\t\tconsole.log(\"未授权:\" + message);\n    \t\t\t\t\tlayer.msg('未授权');\n    \t\t\t\t} else if (code == 500) {\n    \t\t\t\t\tlayer.msg('系统错误：' + message);\n    \t\t\t\t}\n    \t\t\t}\n        \t},\n        \t\"dom\": \"<'dt-toolbar'r>t<'dt-toolbar-footer'<'col-sm-10 col-xs-12 hidden-xs'i><'col-xs-12 col-sm-10' p v>>\",\t\n            \"columns\": [\n            \t{\n\t\t\t\t\t\"data\" : \"id\", \n\t\t\t\t\t\"defaultContent\" : \"\",\n\t\t\t\t\t\"orderable\":false,\n\t\t\t\t\t\"render\" : function(data, type, full, meta) {\n\t\t\t\t\t\treturn '<input type=\"checkbox\" value=\"'+ data + '\" name=\"id\"/>';\n\t\t\t\t\t}\n\t\t\t\t} ,\n\t\t\t\t{\"data\" : \"id\", \"defaultContent\" : \"\"},\n\t\t\t\t{\n\t\t\t\t\t\"data\" : \"user\", \n\t\t\t\t\t\"defaultContent\" : \"\",\n\t\t\t\t\t\"orderable\":false,\n\t\t\t\t\t\"render\": function (data, type, row) {\n                \t\tvar user = row['user'];\n                        return user['nickname'];\n                  \t}\n\t\t\t\t},\n\t\t\t\t{\"data\" : \"module\", \"defaultContent\" : \"\"},\n\t\t\t\t{\n\t\t\t\t\t\"data\" : \"flag\", \n\t\t\t\t\t\"defaultContent\" : \"\",\n\t\t\t\t\t\"render\": function (data, type, row) {\n                \t\tvar flag = row['flag'];\n                        return flag ? \"成功\":\"失败\";\n                  \t}\n\t\t\t\t},\n\t\t\t\t{\"data\" : \"remark\", \"defaultContent\" : \"\"},\n\t\t\t\t{\"data\" : \"createTime\", \"defaultContent\" : \"\"},\n\n                \n            ],\n           \"order\": [[ 5, \"desc\" ]]\n        } );\n}\n\n$(\"#searchBt\").click(function(){\n\texample.ajax.reload();\n});\n\n/**\n * 多选选中和取消选中,同时选中第一个单元格单选框,并联动全选单选框\n */\n$('#dt-table tbody').on('click', 'tr', function(event) {\n\tvar allChecked=$('input[name=allChecked]')[0];//关联全选单选框\n\t$($(this).children()[0]).children().each(function(){\n\t\tif(this.type==\"checkbox\" && (!$(event.target).is(\":checkbox\") && $(\":checkbox\",this).trigger(\"click\"))){\n\t\t\tif(!this.checked){\n\t\t\t\tthis.checked = true;\n\t\t\t\taddValue(this);\n\t\t\t\tvar selected=example.rows('.selected').data().length;//被选中的行数\n\t\t\t\t//全选单选框的状态处理\n\t\t\t\tvar recordsDisplay=example.page.info().recordsDisplay;//搜索条件过滤后的总行数\n\t\t\t\tvar iDisplayStart=example.page.info().start;// 起始行数\n\t\t\t\tif(selected === example.page.len()||selected === recordsDisplay||selected === (recordsDisplay - iDisplayStart)){\n\t\t\t\t\tallChecked.checked = true;\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\tthis.checked = false;\n\t\t\t\tcancelValue(this);\n\t\t\t\tallChecked.checked = false;\n\t\t\t}\n\t\t}\n\t});\n\t$(this).toggleClass('selected');//放在最后处理，以便给checkbox做检测\n});\n\n\n/**\n * 单选框被选中时将它的value放入隐藏域\n */\nfunction addValue(para) {\n\tvar userIds = $(\"input[name=logids]\");\n\tif(userIds.val() === \"\"){\n\t\tuserIds.val($(para).val());\n\t}else{\n\t\tuserIds.val(userIds.val()+\",\"+$(para).val());\n\t}\n}\n\n/**\n * 单选框取消选中时将它的value移除隐藏域\n */\nfunction cancelValue(para){\n\t//取消选中checkbox要做的操作\n\tvar userIds = $(\"input[name=logids]\");\n\tvar array = userIds.val().split(\",\");\n\tuserIds.val(\"\");\n\tfor (var i = 0; i < array.length; i++) {\n\t\tif (array[i] === $(para).val()) {\n\t\t\tcontinue;\n\t\t}\n\t\tif (userIds.val() === \"\") {\n\t\t\tuserIds.val(array[i]);\n\t\t} else {\n\t\t\tuserIds.val(userIds.val() + \",\" + array[i]);\n\t\t}\n\t}\n}\n\n\n\n/**\n * 全选按钮被点击事件\n */\n$('input[name=allChecked]').click(function(){\n\tif(this.checked){\n\t\t$('#dt-table tbody tr').each(function(){\n\t\t\tif(!$(this).hasClass('selected')){\n\t\t\t\t$(this).click();\n\t\t\t}\n\t\t});\n\t}else{\n\t\t$('#dt-table tbody tr').click();\n\t}\n});\n\n\ninit();\n</script>\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/mail/addMail.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/bootstrap.min.css\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/lib/layui/css/layui.css\">\n</head>\n<body>\n\t<div class=\"col-xs-12 col-sm-12 col-md-12 col-lg-12\">\n\t\t<fieldset>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">标题</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<input class=\"form-control\" placeholder=\"标题\" type=\"text\" name=\"subject\" id=\"subject\">\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">收件人</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<input class=\"form-control\" placeholder=\"收件人\" type=\"text\" name=\"toUsers\" id=\"toUsers\">\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">内容</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<textarea class=\"layui-textarea\" id=\"demo\" style=\"display: none\">  \n\t\t\t\t\t</textarea>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"form-actions\">\n\t\t\t\t<div class=\"row\" align=\"center\">\n\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t    <button class=\"btn btn-primary\" onclick=\"location.href='mailList.html'\">返回</button>\n\t\t\t\t\t\t<button class=\"btn btn-primary\" type=\"submit\" onclick=\"add(this)\">\n\t\t\t\t\t\t\t<i class=\"fa fa-save\"></i> 发送\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t</fieldset>\n\t</div>\n\t\n\t<script type=\"text/javascript\" src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n\t<script type=\"text/javascript\" src=\"/lib/layui/layui.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/common.js\"></script>\n\t<script type=\"text/javascript\">\n\t\tvar pro = window.location.protocol;\n\t\tvar host = window.location.host;\n\t\tvar domain = pro + \"//\" + host;\n\t\t\n\t\tvar layedit, index;\n\t\tlayui.use(['layedit','upload'], function(){\n\t\t  layedit = layui.layedit;\n\t\t  layedit.set({\n              uploadImage: {\n            \t  url: '/files/layui?domain=' + domain+\"&token=\"+localStorage.getItem(\"token\"),\n                type: 'post'\n              }\n            });\n\t\t  index = layedit.build('demo');\n\t\t});\n\t\n\t\tfunction add(obj) {\n\t\t\tvar subject = $(\"#subject\").val();\n\t\t\tvar toUsers = $(\"#toUsers\").val();\n\t\t    if(subject.trim() == \"\"){\n\t\t       layer.msg(\"标题不能为空\")\n\t\t\t   return;\n\t\t    }\n\t\t    if(toUsers.trim() == \"\"){\n\t\t       layer.msg(\"收件人不能为空\")\n\t\t\t   return;\n\t\t    }\n\t\t    $(obj).attr(\"disabled\",true);\n\t\t    \n\t\t    var formdata = $(\"#form\").serializeObject();\n\t\t    formdata.subject = subject;\n\t\t    formdata.toUsers = toUsers;\n\t\t    formdata.content = layedit.getContent(index);\n\n\t\t\t$.ajax({\n\t\t\t\ttype : 'post',\n\t\t\t\turl : '/mails',\n\t\t\t\tcontentType: \"application/json; charset=utf-8\",  \n\t\t\t\tdata : JSON.stringify(formdata),\n\t\t\t\tsuccess : function(data) {\n\t\t\t\t\tlayer.msg(\"发送成功\", {shift: -1, time: 1000}, function(){\n\t\t\t\t\t\tlocation.href = \"mailList.html\";\n                    });\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\t\n\t</script>\n</body>\n</html>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/mail/mailDetail.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/bootstrap.min.css\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/lib/layui/css/layui.css\">\n</head>\n<body>\n\t<div class=\"col-xs-12 col-sm-12 col-md-12 col-lg-12\">\n\t\t<fieldset>\n\t\t\t<input type=\"hidden\" id=\"id\" name=\"id\">\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">标题</label>\n\t\t\t\t<div class=\"col-md-10\" id=\"subject\" align=\"left\">\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</fieldset>\n\t\t<fieldset>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\"></label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<table class=\"table\">\n\t\t\t\t\t\t<thead>\n\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t<th>收件人</th>\n\t\t\t\t\t\t\t\t<th>投递状态</th>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t</thead>\n\t\t\t\t\t\t<tbody id=\"toUsers\">\n\t\t\t\t\t\t\n\t\t\t\t\t\t</tbody>\n\t\t\t\t\t</table>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</fieldset>\n\t\t<fieldset>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">内容</label>\n\t\t\t\t<div class=\"col-md-10\" id=\"content\">\n\t\t\t\t\t\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"form-actions\">\n\t\t\t\t<div class=\"row\" align=\"center\">\n\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t    <button class=\"btn btn-primary\" onclick=\"location.href='mailList.html'\">返回</button>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t</fieldset>\n\t</div>\n\n\t<script type=\"text/javascript\" src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n\t<script type=\"text/javascript\" src=\"/lib/layui/layui.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/common.js\"></script>\n\t<script type=\"text/javascript\">\n\t\n\tinitData();\n\t\n\tfunction initData(){\n\t\tvar id = getUrlParam(\"id\");\n\t\tif(id != \"\"){\n\t\t\t$.ajax({\n\t\t\t\ttype : 'get',\n\t\t\t\turl : '/mails/'+id,\n\t\t\t\tsuccess : function(data) {\n\t\t\t\t\t$(\"#subject\").html(data.subject);\n\t\t\t\t\t$(\"#content\").html(data.content);\n\t\t\t\t\t\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t\t$.ajax({\n\t\t\t\ttype : 'get',\n\t\t\t\turl : '/mails/'+id+\"/to\",\n\t\t\t\tsuccess : function(data) {\n\t\t\t\t\tvar length = data.length;\n\t\t\t\t\tfor(var i=0;i<length;i++){\n\t\t\t\t\t\tvar tr = $(\"<tr></tr>\");\n\t\t\t\t\t\ttr.append(\"<td>\" + data[i]['toUser'] + \"</td>\");\n\t\t\t\t\t\t\n\t\t\t\t\t\tvar status = data[i]['status'];\n\t\t\t\t\t\ttr.append(\"<td>\" + (status ? \"投递成功\":\"<span style='color:red'>投递失败</span>\") + \"</td>\");\n\t\t\t\t\t\t$(\"#toUsers\").append(tr);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t}\n\t}\n\t\n\t</script>\n</body>\n</html>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/mail/mailList.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<title>Insert title here</title>\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/bootstrap.min.css\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/dataTables.bootstrap.min.css\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/lib/layui/css/layui.css\">\n</head>\n<body>\n    <div>\n        <div class=\"col-xs-12 col-sm-12 col-md-12 col-lg-12\">\n                <header style=\"height: 100%\">\n                    <div align=\"left\">\n\t                    <table style=\"width: 100%\">\n\t                   \t\t<tr>\n\t                   \t\t\t<td>\n\t\t\t\t\t\t\t\t\t<form class=\"form-inline\" onsubmit=\"return false\">\n\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t标题：\n\t\t\t\t\t\t\t\t\t\t\t<input id=\"subject\" type=\"text\" class=\"form-control\" placeholder=\"标题\">\n\t\t\t\t\t\t\t\t\t\t\t时间：\n\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" class=\"form-control\" placeholder=\"开始时间\" id=\"beginTime\">\n\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" class=\"form-control\" placeholder=\"结束时间\" id=\"endTime\">\n\t\t\t\t\t\t\t\t\t\t\t<button id=\"searchBt\" class=\"layui-btn layui-btn-sm\" permission=\"mail:all:query\"><i class=\"layui-icon\">&#xe615;</i>搜索</button>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</form>\n\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t<td align=\"right\">\n\t\t\t\t\t\t\t\t\t<button class=\"layui-btn layui-btn-sm\" onclick=\"location.href='addMail.html'\" permission=\"mail:send\">\n\t\t\t\t\t\t\t\t\t  <i class=\"layui-icon\">&#xe608;</i> 添加\n\t\t\t\t\t\t\t\t\t</button>\n\t                   \t\t\t</td>\n\t                   \t\t</tr> \n\t                    </table>\n\t\t\t\t\t</div>\n                </header>\n                \n                <div>\n                    <div class=\"widget-body no-padding\">\n                        <table id=\"dt-table\" class=\"table table-striped table-bordered table-hover\" style=\"width:100%\">\n                            <thead>\n                                <tr>\n                                </tr>                       \n                                <tr>\n                                    <th style=\"width: 10%\">id</th>\n                                    <th style=\"width: 30%\">标题</th>\n                                    <th>内容</th>\n\t\t\t\t\t\t\t\t\t<th style=\"width: 20%\">时间</th>     \n\t\t\t\t\t\t\t\t\t<th style=\"width: 10%\">操作</th>     \n                                </tr>\n                            </thead>\n                            <tbody>\n                            </tbody>\n                        </table>\n                    </div>\n                </div>\n        </div>\n    </div>\n</body>\n</html>\n\n<script type=\"text/javascript\" src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n<script type=\"text/javascript\" src=\"/lib/layui/layui.js\"></script>\n<script type=\"text/javascript\" src=\"/js/plugin/datatables/jquery.dataTables.min.js\"></script>\n<script type=\"text/javascript\" src=\"/js/plugin/datatables/dataTables.bootstrap.min.js\"></script>\n<script type=\"text/javascript\" src=\"/js/my/permission.js\"></script>\n<script type=\"text/javascript\">\nvar pers = checkPermission();\nlayui.use(['layer','laydate'], function(){\n    var layer = layui.layer;\n    var laydate = layui.laydate;\n    laydate.render({\n       elem: '#beginTime'\n    });\n    laydate.render({\n       elem: '#endTime'\n    });\n});\n\nvar example;\nfunction init(){\n\texample = \n    \t$('#dt-table').DataTable({\n        \t\"searching\": false,\n        \t\"processing\": false,\n        \t\"serverSide\" : true,\n        \t\"language\": {\n                \"url\": \"/js/plugin/datatables/Chinese.lang\"\n            },\n        \t\"ajax\": {\n        \t\t\"url\" : \"/mails\",\n        \t\t\"type\":\"get\",\n        \t\t\"data\":function(d){\n    \t\t\t\td.subject = $('#subject').val();\n    \t\t\t\td.beginTime = $('#beginTime').val();\n    \t\t\t\td.endTime = $('#endTime').val();\n        \t\t},\n    \t\t\t\"error\":function(xhr, textStatus, errorThrown){\n    \t\t\t\tvar msg = xhr.responseText;\n    \t\t\t\tconsole.log(msg);\n    \t\t\t\tvar response = JSON.parse(msg);\n    \t\t\t\tvar code = response.code;\n    \t\t\t\tvar message = response.message;\n    \t\t\t\tif (code == 400) {\n    \t\t\t\t\tlayer.msg(message);\n    \t\t\t\t} else if (code == 401) {\n    \t\t\t\t\tlocalStorage.removeItem(\"token\");\n    \t\t\t\t\tlayer.msg(\"token过期，请先登录\", {shift: -1, time: 1000}, function(){\n    \t\t\t\t\t\tlocation.href = '/login.html';\n                        });\n    \t\t\t\t} else if (code == 403) {\n    \t\t\t\t\tconsole.log(\"未授权:\" + message);\n    \t\t\t\t\tlayer.msg('未授权');\n    \t\t\t\t} else if (code == 500) {\n    \t\t\t\t\tlayer.msg('系统错误：' + message);\n    \t\t\t\t}\n    \t\t\t}\n        \t},\n        \t\"dom\": \"<'dt-toolbar'r>t<'dt-toolbar-footer'<'col-sm-10 col-xs-12 hidden-xs'i><'col-xs-12 col-sm-10' p v>>\",\t\n            \"columns\": [\n                { \"data\": \"id\", \"defaultContent\": \"\"},\n                { \"data\": \"subject\", \"defaultContent\": \"\"},\n                { \n                \t\"data\": \"content\", \n                \t\"defaultContent\": \"\",\n                \t\"render\": function (data, type, row) {\n                \t\tvar content = row['content'];\n                \t\tvar c = removeHTMLTag(content);\n                        return c;\n                  \t}\n                },\n                { \"data\": \"createTime\", \"defaultContent\": \"\"},\n                { \n                \t\"data\": \"content\", \n                \t\"defaultContent\": \"\",\n                \t\"orderable\":false,\n                \t\"render\": function (data, type, row) {\n                \t\tvar id = row['id'];\n                \t\tvar href = \"mailDetail.html?id=\" + id;\n                        return \"<button class='layui-btn layui-btn-xs' title='编辑' onclick='window.location=\\\"\" + href +\"\\\"'>详情</button>\";\n                    }\n                },\n            ],\n            \"order\": [[ 3, \"desc\" ]]\n        } );\n}\n\nfunction removeHTMLTag(str) {  \n\tvar content = str;\n    str = str.replace(/<\\/?[^>]*>/g,''); //去除HTML tag  \n    str = str.replace(/[ | ]*\\n/g,'\\n'); //去除行尾空白  \n    str = str.replace(/\\n[\\s| | ]*\\r/g,'\\n'); //去除多余空行  \n    str=str.replace(/ /ig,'');//去掉   \n    \n    if(str.length>60){\n    \tstr = str.substr(0,60) +\"...\";\n    }\n    return str;  \n}  \n\n$(\"#searchBt\").click(function(){\n\texample.ajax.reload();\n});\n\ninit();\n</script>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/menu/addMenu.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/bootstrap.min.css\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/font-awesome/css/font-awesome.css\">\n</head>\n<body>\n<div class=\"col-xs-12 col-sm-12 col-md-12 col-lg-12\">\n\t<form class=\"form-horizontal\" onsubmit=\"return false\" id=\"form\">\n\t\t<fieldset>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">上级菜单</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<select id=\"parentId\" name=\"parentId\" class=\"form-control input-sm\"></select>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">名称</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<input class=\"form-control\" placeholder=\"名称\" type=\"text\" name=\"name\" id=\"name\"\n\t\t\t\t\t\tdata-bv-notempty=\"true\"\n\t\t\t\t\t\tdata-bv-notempty-message=\"名称 不能为空\">\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">样式</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<button onclick=\"selectCss()\" class=\"btn btn-primary\">选择</button>\n\t\t\t\t\t<input type=\"hidden\"  name=\"css\" id=\"css\" /><i id=\"cssImg\" class=\"fa\"></i>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">链接</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<input class=\"form-control\" placeholder=\"链接\" name=\"href\" id=\"href\"/>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">类型</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<select name=\"type\" class=\"form-control input-sm\">\n\t\t\t\t\t   <option value=\"1\">菜单</option>\n\t\t\t\t\t   <option value=\"2\">按钮</option>\n\t\t\t\t\t</select>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">权限</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<input class=\"form-control\" placeholder=\"权限\" name=\"permission\" id=\"permission\" />\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"form-group\">\n                <label class=\"col-md-2 control-label\">排序</label>\n                <div class=\"col-md-10\">\n                    <input class=\"form-control\" placeholder=\"排序\" name=\"sort\" id=\"sort\" type=\"number\" value=\"100\"\n                        data-bv-notempty=\"true\"\n                        data-bv-notempty-message=\"排序 不能为空\">\n                </div>\n            </div>\n\n\t\t\t<div class=\"form-actions\">\n\t\t\t\t<div class=\"row\" align=\"center\">\n\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t<button class=\"btn btn-primary\" onclick=\"location.href='menuList.html'\">返回</button>\n\t\t\t\t\t\t<button class=\"btn btn-primary\" type=\"submit\" onclick=\"add()\">\n\t\t\t\t\t\t\t<i class=\"fa fa-save\"></i> 保存\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t</fieldset>\n\t</form>\n</div>\n\n\t<script type=\"text/javascript\" src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/plugin/bootstrapvalidator/bootstrapValidator.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/common.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/my/ztree-menu.js\"></script>\n\t<script type=\"text/javascript\" src=\"/lib/layui/layui.js\"></script>\n\t<script type=\"text/javascript\">\n\t\tlayui.use('layer', function(){\n\t\t    var layer = layui.layer;\n\t\t});\n\n\n\t\tinitParentMenuSelect();\n\t\t\n\t\tfunction add() {\n\t\t\t$('#form').bootstrapValidator();\n\t\t\tvar bootstrapValidator = $(\"#form\").data('bootstrapValidator');\n\t\t\tbootstrapValidator.validate();\n\t\t    if(!bootstrapValidator.isValid()){\n\t\t\t   return;\n\t\t    }\n\t\t    \n\t\t    var formdata = $(\"#form\").serializeObject();\n\n\t\t\t$.ajax({\n\t\t\t\ttype : 'post',\n\t\t\t\turl : '/permissions',\n\t\t\t\tcontentType: \"application/json; charset=utf-8\",  \n\t\t\t\tdata : JSON.stringify(formdata),\n\t\t\t\tsuccess : function(data) {\n\t\t\t\t\tlayer.msg(\"添加成功\", {shift: -1, time: 1000}, function(){\n                        location.href = \"menuList.html\";\n                    });\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\t\n\t\tfunction selectCss(){\n\t\t\tlayer.open({\n\t\t\t\t  type: 2,\n\t\t\t\t  title: \"样式\",\n\t\t\t\t  area: ['800px', '400px'],\n\t\t\t\t  maxmin: true,\n\t\t\t\t  shadeClose: true,\n\t\t\t\t  content: ['icon.html']\n\t\t\t\t});\n\t\t}\n\t</script>\n</body>\n</html>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/menu/icon.html",
    "content": "<!DOCTYPE section PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n<html lang=\"en-us\">\t\n\t<head>\n\t\t<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/bootstrap.min.css\">\n\t\t<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/font-awesome/css/font-awesome.css\">\n\t\t<style type=\"text/css\">\n\t\t\tdiv.demo-icon-font{ cursor:pointer;}\n\t\t</style>\n\t\t\n\t</head>\n<body>\n\t\t\t<div class=\"col-xs-12 col-sm-12 col-md-12 col-lg-12\">\n\t\t\t\t<div align=\"left\">\n\t\t\t\t\t\t\t<div class=\"row\">\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-automobile\"></i> fa-automobile <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-bank\"></i> fa-bank <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-behance\"></i> fa-behance\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-behance-square\"></i> fa-behance-square\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-bomb\"></i> fa-bomb\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-building\"></i> fa-building\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-cab\"></i> fa-cab <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-car\"></i> fa-car\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-child\"></i> fa-child\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-circle-o-notch\"></i> fa-circle-o-notch\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-circle-thin\"></i> fa-circle-thin\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-codepen\"></i> fa-codepen\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-cube\"></i> fa-cube\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-cubes\"></i> fa-cubes\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-database\"></i> fa-database\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-delicious\"></i> fa-delicious\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-deviantart\"></i> fa-deviantart\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-digg\"></i> fa-digg\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-drupal\"></i> fa-drupal\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-empire\"></i> fa-empire\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-envelope-square\"></i> fa-envelope-square\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-fax\"></i> fa-fax\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-file-archive-o\"></i> fa-file-archive-o\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-file-audio-o\"></i> fa-file-audio-o\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-file-code-o\"></i> fa-file-code-o\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-file-excel-o\"></i> fa-file-excel-o\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-file-image-o\"></i> fa-file-image-o\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-file-movie-o\"></i> fa-file-movie-o <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-file-pdf-o\"></i> fa-file-pdf-o\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-file-photo-o\"></i> fa-file-photo-o <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-file-picture-o\"></i> fa-file-picture-o <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-file-powerpoint-o\"></i> fa-file-powerpoint-o\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-file-sound-o\"></i> fa-file-sound-o <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-file-video-o\"></i> fa-file-video-o\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-file-word-o\"></i> fa-file-word-o\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-file-zip-o\"></i> fa-file-zip-o <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-ge\"></i> fa-ge <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-git\"></i> fa-git\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-git-square\"></i> fa-git-square\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-google\"></i> fa-google\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-graduation-cap\"></i> fa-graduation-cap\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-hacker-news\"></i> fa-hacker-news\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-header\"></i> fa-header\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-history\"></i> fa-history\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-institution\"></i> fa-institution <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-joomla\"></i> fa-joomla\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-jsfiddle\"></i> fa-jsfiddle\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-language\"></i> fa-language\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-life-bouy\"></i> fa-life-bouy <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-life-ring\"></i> fa-life-ring\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-life-saver\"></i> fa-life-saver <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-mortar-board\"></i> fa-mortar-board <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-openid\"></i> fa-openid\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-paper-plane\"></i> fa-paper-plane\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-paper-plane-o\"></i> fa-paper-plane-o\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-paragraph\"></i> fa-paragraph\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-paw\"></i> fa-paw\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-pied-piper\"></i> fa-pied-piper\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-pied-piper-alt\"></i> fa-pied-piper-alt\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-pied-piper-square\"></i> fa-pied-piper-square <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-qq\"></i> fa-qq\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-ra\"></i> fa-ra <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-rebel\"></i> fa-rebel\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-recycle\"></i> fa-recycle\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-reddit\"></i> fa-reddit\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-reddit-square\"></i> fa-reddit-square\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-send\"></i> fa-send <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-send-o\"></i> fa-send-o <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-share-alt\"></i> fa-share-alt\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-share-alt-square\"></i> fa-share-alt-square\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-slack\"></i> fa-slack\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-sliders\"></i> fa-sliders\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-soundcloud\"></i> fa-soundcloud\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-space-shuttle\"></i> fa-space-shuttle\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-spoon\"></i> fa-spoon\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-spotify\"></i> fa-spotify\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-steam\"></i> fa-steam\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-steam-square\"></i> fa-steam-square\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-stumbleupon\"></i> fa-stumbleupon\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-stumbleupon-circle\"></i> fa-stumbleupon-circle\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-support\"></i> fa-support <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-taxi\"></i> fa-taxi\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-tencent-weibo\"></i> fa-tencent-weibo\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-tree\"></i> fa-tree\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-university\"></i> fa-university\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-vine\"></i> fa-vine\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-wechat\"></i> fa-wechat <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-weixin\"></i> fa-weixin\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-wordpress\"></i> fa-wordpress\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-yahoo\"></i> fa-yahoo\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t</div>\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t<!-- new sets -->\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t<h2>Web Application Icons</h2>\n\n\t\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-adjust\"></i> fa-adjust\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-anchor\"></i> fa-anchor\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-archive\"></i> fa-archive\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-asterisk\"></i> fa-asterisk\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-ban\"></i> fa-ban\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-bar-chart-o\"></i> fa-bar-chart-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-barcode\"></i> fa-barcode\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-beer\"></i> fa-beer\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-bell\"></i> fa-bell\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-bell-o\"></i> fa-bell-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-bolt\"></i> fa-bolt\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-book\"></i> fa-book\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-bookmark\"></i> fa-bookmark\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-bookmark-o\"></i> fa-bookmark-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-briefcase\"></i> fa-briefcase\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-bug\"></i> fa-bug\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-building\"></i> fa-building\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-bullhorn\"></i> fa-bullhorn\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-bullseye\"></i> fa-bullseye\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-calendar\"></i> fa-calendar\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-calendar-o\"></i> fa-calendar-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-camera\"></i> fa-camera\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-camera-retro\"></i> fa-camera-retro\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-caret-square-o-down\"></i> fa-caret-square-o-down\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-caret-square-o-left\"></i> fa-caret-square-o-left\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-caret-square-o-right\"></i> fa-caret-square-o-right\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-caret-square-o-up\"></i> fa-caret-square-o-up\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-certificate\"></i> fa-certificate\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-check\"></i> fa-check\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-check-circle\"></i> fa-check-circle\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-check-circle-o\"></i> fa-check-circle-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-check-square\"></i> fa-check-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-check-square-o\"></i> fa-check-square-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-circle\"></i> fa-circle\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-circle-o\"></i> fa-circle-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-clock-o\"></i> fa-clock-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-cloud\"></i> fa-cloud\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-cloud-download\"></i> fa-cloud-download\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-cloud-upload\"></i> fa-cloud-upload\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-code\"></i> fa-code\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-code-fork\"></i> fa-code-fork\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-coffee\"></i> fa-coffee\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-cog\"></i> fa-cog\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-cogs\"></i> fa-cogs\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-plus-square-o\"></i> fa-plus-square-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-comment\"></i> fa-comment\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-comment-o\"></i> fa-comment-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-comments\"></i> fa-comments\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-comments-o\"></i> fa-comments-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-compass\"></i> fa-compass\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-credit-card\"></i> fa-credit-card\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-crop\"></i> fa-crop\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-crosshairs\"></i> fa-crosshairs\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-cutlery\"></i> fa-cutlery\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-dashboard\"></i> fa-dashboard <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-desktop\"></i> fa-desktop\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-dot-circle-o\"></i> fa-dot-circle-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-download\"></i> fa-download\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-edit\"></i> fa-edit <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-ellipsis-horizontal\"></i> fa-ellipsis-horizontal\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-ellipsis-vertical\"></i> fa-ellipsis-vertical\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-envelope\"></i> fa-envelope\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-envelope-o\"></i> fa-envelope-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-eraser\"></i> fa-eraser\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-exchange\"></i> fa-exchange\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-exclamation\"></i> fa-exclamation\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-exclamation-circle\"></i> fa-exclamation-circle\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-exclamation-triangle\"></i> fa-exclamation-triangle\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-minus-square-o\"></i> fa-minus-square-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-external-link\"></i> fa-external-link\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-external-link-square\"></i> fa-external-link-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-eye\"></i> fa-eye\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-eye-slash\"></i> fa-eye-slash\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-female\"></i> fa-female\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-fighter-jet\"></i> fa-fighter-jet\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-film\"></i> fa-film\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-filter\"></i> fa-filter\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-fire\"></i> fa-fire\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-fire-extinguisher\"></i> fa-fire-extinguisher\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-flag\"></i> fa-flag\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-flag-checkered\"></i> fa-flag-checkered\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-flag-o\"></i> fa-flag-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-flash\"></i> fa-flash <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-flask\"></i> fa-flask\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-folder\"></i> fa-folder\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-folder-o\"></i> fa-folder-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-folder-open\"></i> fa-folder-open\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-folder-open-o\"></i> fa-folder-open-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-frown-o\"></i> fa-frown-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-gamepad\"></i> fa-gamepad\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-gavel\"></i> fa-gavel\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-gear\"></i> fa-gear <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-gears\"></i> fa-gears <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-gift\"></i> fa-gift\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-glass\"></i> fa-glass\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-globe\"></i> fa-globe\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-group\"></i> fa-group\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-hdd-o\"></i> fa-hdd-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-headphones\"></i> fa-headphones\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-heart\"></i> fa-heart\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-heart-o\"></i> fa-heart-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-home\"></i> fa-home\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-inbox\"></i> fa-inbox\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-info\"></i> fa-info\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-info-circle\"></i> fa-info-circle\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-key\"></i> fa-key\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-keyboard-o\"></i> fa-keyboard-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-laptop\"></i> fa-laptop\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-leaf\"></i> fa-leaf\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-legal\"></i> fa-legal <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-lemon-o\"></i> fa-lemon-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-level-down\"></i> fa-level-down\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-level-up\"></i> fa-level-up\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-lightbulb-o\"></i> fa-lightbulb-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-location-arrow\"></i> fa-location-arrow\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-lock\"></i> fa-lock\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-magic\"></i> fa-magic\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-magnet\"></i> fa-magnet\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-mail-forward\"></i> fa-mail-forward <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-mail-reply\"></i> fa-mail-reply <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-mail-reply-all\"></i> fa-mail-reply-all\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-male\"></i> fa-male\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-map-marker\"></i> fa-map-marker\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-meh-o\"></i> fa-meh-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-microphone\"></i> fa-microphone\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-microphone-slash\"></i> fa-microphone-slash\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-minus\"></i> fa-minus\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-minus-circle\"></i> fa-minus-circle\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-minus-square\"></i> fa-minus-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-minus-square-o\"></i> fa-minus-square-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-mobile\"></i> fa-mobile\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-mobile-phone\"></i> fa-mobile-phone <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-money\"></i> fa-money\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-moon-o\"></i> fa-moon-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-move\"></i> fa-move\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-music\"></i> fa-music\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-pencil\"></i> fa-pencil\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-pencil-square\"></i> fa-pencil-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-pencil-square-o\"></i> fa-pencil-square-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-phone\"></i> fa-phone\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-phone-square\"></i> fa-phone-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-picture-o\"></i> fa-picture-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-plane\"></i> fa-plane\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-plus\"></i> fa-plus\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-plus-circle\"></i> fa-plus-circle\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-plus-square\"></i> fa-plus-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-power-off\"></i> fa-power-off\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-print\"></i> fa-print\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-puzzle-piece\"></i> fa-puzzle-piece\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-qrcode\"></i> fa-qrcode\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-question\"></i> fa-question\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-question-circle\"></i> fa-question-circle\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-quote-left\"></i> fa-quote-left\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-quote-right\"></i> fa-quote-right\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-random\"></i> fa-random\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-refresh\"></i> fa-refresh\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-reorder\"></i> fa-reorder\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-reply\"></i> fa-reply\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-reply-all\"></i> fa-reply-all\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-resize-horizontal\"></i> fa-resize-horizontal\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-resize-vertical\"></i> fa-resize-vertical\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-retweet\"></i> fa-retweet\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-road\"></i> fa-road\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-rocket\"></i> fa-rocket\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-rss\"></i> fa-rss\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-rss-square\"></i> fa-rss-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-search\"></i> fa-search\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-search-minus\"></i> fa-search-minus\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-search-plus\"></i> fa-search-plus\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-share\"></i> fa-share\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-share-square\"></i> fa-share-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-share-square-o\"></i> fa-share-square-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-shield\"></i> fa-shield\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-shopping-cart\"></i> fa-shopping-cart\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-sign-in\"></i> fa-sign-in\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-sign-out\"></i> fa-sign-out\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-signal\"></i> fa-signal\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-sitemap\"></i> fa-sitemap\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-smile-o\"></i> fa-smile-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-sort\"></i> fa-sort\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-sort-alpha-asc\"></i> fa-sort-alpha-asc\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-sort-alpha-desc\"></i> fa-sort-alpha-desc\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-sort-amount-asc\"></i> fa-sort-amount-asc\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-sort-amount-desc\"></i> fa-sort-amount-desc\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-sort-asc\"></i> fa-sort-asc\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-sort-desc\"></i> fa-sort-desc\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-sort-down\"></i> fa-sort-down <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-sort-numeric-asc\"></i> fa-sort-numeric-asc\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-sort-numeric-desc\"></i> fa-sort-numeric-desc\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-sort-up\"></i> fa-sort-up <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-spinner\"></i> fa-spinner\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-square\"></i> fa-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-square-o\"></i> fa-square-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-star\"></i> fa-star\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-star-half\"></i> fa-star-half\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-star-half-empty\"></i> fa-star-half-empty <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-star-half-full\"></i> fa-star-half-full <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-star-half-o\"></i> fa-star-half-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-star-o\"></i> fa-star-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-subscript\"></i> fa-subscript\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-suitcase\"></i> fa-suitcase\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-sun-o\"></i> fa-sun-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-superscript\"></i> fa-superscript\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-tablet\"></i> fa-tablet\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-tachometer\"></i> fa-tachometer\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-tag\"></i> fa-tag\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-tags\"></i> fa-tags\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-tasks\"></i> fa-tasks\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-terminal\"></i> fa-terminal\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-thumb-tack\"></i> fa-thumb-tack\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-thumbs-down\"></i> fa-thumbs-down\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-thumbs-o-down\"></i> fa-thumbs-o-down\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-thumbs-o-up\"></i> fa-thumbs-o-up\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-thumbs-up\"></i> fa-thumbs-up\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-ticket\"></i> fa-ticket\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-times\"></i> fa-times\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-times-circle\"></i> fa-times-circle\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-times-circle-o\"></i> fa-times-circle-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-tint\"></i> fa-tint\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-toggle-down\"></i> fa-toggle-down <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-toggle-left\"></i> fa-toggle-left <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-toggle-right\"></i> fa-toggle-right <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-toggle-up\"></i> fa-toggle-up <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-trash-o\"></i> fa-trash-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-trophy\"></i> fa-trophy\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-truck\"></i> fa-truck\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-umbrella\"></i> fa-umbrella\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-unlock\"></i> fa-unlock\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-unlock-alt\"></i> fa-unlock-alt\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-unsorted\"></i> fa-unsorted <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-upload\"></i> fa-upload\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-user\"></i> fa-user\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-video-camera\"></i> fa-video-camera\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-volume-down\"></i> fa-volume-down\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-volume-off\"></i> fa-volume-off\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-volume-up\"></i> fa-volume-up\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-warning\"></i> fa-warning <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-wheelchair\"></i> fa-wheelchair\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-wrench\"></i> fa-wrench\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t<!-- new sets -->\n\t\t\t\t\t\n\t\t\t\t\t\t\t<h2>Form Control Icons</h2>\n\n\t\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-check-square\"></i> fa-check-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-check-square-o\"></i> fa-check-square-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-circle\"></i> fa-circle\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-circle-o\"></i> fa-circle-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-dot-circle-o\"></i> fa-dot-circle-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-minus-square\"></i> fa-minus-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-minus-square-o\"></i> fa-minus-square-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-square\"></i> fa-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-square-o\"></i> fa-square-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t<!-- new sets -->\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t<h2>Currency Icons</h2>\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-bitcoin\"></i> fa-bitcoin <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-btc\"></i> fa-btc\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-cny\"></i> fa-cny <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-dollar\"></i> fa-dollar <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-eur\"></i> fa-eur\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-euro\"></i> fa-euro <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-gbp\"></i> fa-gbp\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-inr\"></i> fa-inr\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-jpy\"></i> fa-jpy\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-krw\"></i> fa-krw\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-money\"></i> fa-money\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-rmb\"></i> fa-rmb <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-rouble\"></i> fa-rouble <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-rub\"></i> fa-rub\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-ruble\"></i> fa-ruble <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-rupee\"></i> fa-rupee <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-try\"></i> fa-try\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-turkish-lira\"></i> fa-turkish-lira <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-usd\"></i> fa-usd\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-won\"></i> fa-won <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-yen\"></i> fa-yen <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t<!-- new sets -->\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t<h2>Text Editor Icons</h2>\n\n\t\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-align-center\"></i> fa-align-center\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-align-justify\"></i> fa-align-justify\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-align-left\"></i> fa-align-left\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-align-right\"></i> fa-align-right\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-bold\"></i> fa-bold\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-chain\"></i> fa-chain <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-chain-broken\"></i> fa-chain-broken\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-clipboard\"></i> fa-clipboard\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-columns\"></i> fa-columns\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-copy\"></i> fa-copy <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-cut\"></i> fa-cut <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-dedent\"></i> fa-dedent <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-eraser\"></i> fa-eraser\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-file\"></i> fa-file\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-file-o\"></i> fa-file-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-file-text\"></i> fa-file-text\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-file-text-o\"></i> fa-file-text-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-files-o\"></i> fa-files-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-floppy-o\"></i> fa-floppy-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-font\"></i> fa-font\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-indent\"></i> fa-indent\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-italic\"></i> fa-italic\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-link\"></i> fa-link\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-list\"></i> fa-list\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-list-alt\"></i> fa-list-alt\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-list-ol\"></i> fa-list-ol\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-list-ul\"></i> fa-list-ul\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-outdent\"></i> fa-outdent\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-paperclip\"></i> fa-paperclip\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-paste\"></i> fa-paste <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-repeat\"></i> fa-repeat\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-rotate-left\"></i> fa-rotate-left <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-rotate-right\"></i> fa-rotate-right <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-save\"></i> fa-save <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-scissors\"></i> fa-scissors\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-strikethrough\"></i> fa-strikethrough\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-table\"></i> fa-table\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-text-height\"></i> fa-text-height\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-text-width\"></i> fa-text-width\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-th\"></i> fa-th\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-th-large\"></i> fa-th-large\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-th-list\"></i> fa-th-list\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-underline\"></i> fa-underline\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-undo\"></i> fa-undo\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-unlink\"></i> fa-unlink <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t<!-- new sets -->\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t<h2>Directional Icons</h2>\n\n\t\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-double-down\"></i> fa-angle-double-down\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-double-left\"></i> fa-angle-double-left\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-double-right\"></i> fa-angle-double-right\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-double-up\"></i> fa-angle-double-up\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-down\"></i> fa-angle-down\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-left\"></i> fa-angle-left\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right\"></i> fa-angle-right\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-up\"></i> fa-angle-up\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-arrow-circle-down\"></i> fa-arrow-circle-down\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-arrow-circle-left\"></i> fa-arrow-circle-left\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-arrow-circle-o-down\"></i> fa-arrow-circle-o-down\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-arrow-circle-o-left\"></i> fa-arrow-circle-o-left\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-arrow-circle-o-right\"></i> fa-arrow-circle-o-right\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-arrow-circle-o-up\"></i> fa-arrow-circle-o-up\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-arrow-circle-right\"></i> fa-arrow-circle-right\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-arrow-circle-up\"></i> fa-arrow-circle-up\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-arrow-down\"></i> fa-arrow-down\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-arrow-left\"></i> fa-arrow-left\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-arrow-right\"></i> fa-arrow-right\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-arrow-up\"></i> fa-arrow-up\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-caret-down\"></i> fa-caret-down\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-caret-left\"></i> fa-caret-left\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-caret-right\"></i> fa-caret-right\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-caret-square-o-down\"></i> fa-caret-square-o-down\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-caret-square-o-left\"></i> fa-caret-square-o-left\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-caret-square-o-right\"></i> fa-caret-square-o-right\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-caret-square-o-up\"></i> fa-caret-square-o-up\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-caret-up\"></i> fa-caret-up\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-chevron-circle-down\"></i> fa-chevron-circle-down\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-chevron-circle-left\"></i> fa-chevron-circle-left\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-chevron-circle-right\"></i> fa-chevron-circle-right\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-chevron-circle-up\"></i> fa-chevron-circle-up\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-chevron-down\"></i> fa-chevron-down\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-chevron-left\"></i> fa-chevron-left\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-chevron-right\"></i> fa-chevron-right\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-chevron-up\"></i> fa-chevron-up\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-hand-o-down\"></i> fa-hand-o-down\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-hand-o-left\"></i> fa-hand-o-left\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-hand-o-right\"></i> fa-hand-o-right\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-hand-o-up\"></i> fa-hand-o-up\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-long-arrow-down\"></i> fa-long-arrow-down\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-long-arrow-left\"></i> fa-long-arrow-left\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-long-arrow-right\"></i> fa-long-arrow-right\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-long-arrow-up\"></i> fa-long-arrow-up\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-toggle-down\"></i> fa-toggle-down <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-toggle-left\"></i> fa-toggle-left <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-toggle-right\"></i> fa-toggle-right <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-toggle-up\"></i> fa-toggle-up <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t<!-- new sets -->\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t<h2>Video Player Icons</h2>\n\n\t\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-backward\"></i> fa-backward\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-eject\"></i> fa-eject\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-fast-backward\"></i> fa-fast-backward\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-fast-forward\"></i> fa-fast-forward\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-forward\"></i> fa-forward\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-arrows-alt\"></i> fa-arrows-alt\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-pause\"></i> fa-pause\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-play\"></i> fa-play\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-play-circle\"></i> fa-play-circle\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-play-circle-o\"></i> fa-play-circle-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-expand\"></i> fa-expand\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-compress\"></i> fa-compress\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-step-backward\"></i> fa-step-backward\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-step-forward\"></i> fa-step-forward\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-stop\"></i> fa-stop\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-youtube-play\"></i> fa-youtube-play\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t<!-- new sets -->\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t<h2>Brand Icons</h2>\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-adn\"></i> fa-adn\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-android\"></i> fa-android\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-apple\"></i> fa-apple\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-bitbucket\"></i> fa-bitbucket\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-bitbucket-square\"></i> fa-bitbucket-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-bitcoin\"></i> fa-bitcoin <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-btc\"></i> fa-btc\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-css3\"></i> fa-css3\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-dribbble\"></i> fa-dribbble\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-dropbox\"></i> fa-dropbox\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-facebook\"></i> fa-facebook\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-facebook-square\"></i> fa-facebook-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-flickr\"></i> fa-flickr\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-foursquare\"></i> fa-foursquare\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-github\"></i> fa-github\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-github-alt\"></i> fa-github-alt\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-github-square\"></i> fa-github-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-gittip\"></i> fa-gittip\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-google-plus\"></i> fa-google-plus\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-google-plus-square\"></i> fa-google-plus-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-html5\"></i> fa-html5\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-instagram\"></i> fa-instagram\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-linkedin\"></i> fa-linkedin\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-linkedin-square\"></i> fa-linkedin-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-linux\"></i> fa-linux\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-maxcdn\"></i> fa-maxcdn\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-pagelines\"></i> fa-pagelines\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-pinterest\"></i> fa-pinterest\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-pinterest-square\"></i> fa-pinterest-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-renren\"></i> fa-renren\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-skype\"></i> fa-skype\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-stack-exchange\"></i> fa-stack-exchange\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-stack-overflow\"></i> fa-stack-overflow\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-trello\"></i> fa-trello\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-tumblr\"></i> fa-tumblr\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-tumblr-square\"></i> fa-tumblr-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-twitter\"></i> fa-twitter\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-twitter-square\"></i> fa-twitter-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-vimeo-square\"></i> fa-vimeo-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-vk\"></i> fa-vk\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-weibo\"></i> fa-weibo\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-windows\"></i> fa-windows\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-xing\"></i> fa-xing\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-xing-square\"></i> fa-xing-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-youtube\"></i> fa-youtube\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-youtube-play\"></i> fa-youtube-play\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-youtube-square\"></i> fa-youtube-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t<!-- new sets -->\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t<h2>Medical Icons</h2>\n\n\t\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-ambulance\"></i> fa-ambulance\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-h-square\"></i> fa-h-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-hospital-o\"></i> fa-hospital-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-medkit\"></i> fa-medkit\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-plus-square\"></i> fa-plus-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-stethoscope\"></i> fa-stethoscope\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-user-md\"></i> fa-user-md\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-wheelchair\"></i> fa-wheelchair\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n</body>\n</html>\n<script src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n<script type=\"text/javascript\">\n$(\".demo-icon-font\").click(function(){\n\tvar cla = $(this).children(\"i:first\").attr(\"class\").split(\" \");\n\tvar l = cla.length;\n\tparent.$(\"#css\").val(cla[l-1]);console.log(cla[l-1])\n\tparent.$(\"#cssImg\").removeClass();\n\tparent.$(\"#cssImg\").addClass(\"fa\");\n\tparent.$(\"#cssImg\").addClass(cla[l-1]);\n\tvar index = parent.layer.getFrameIndex(window.name); //获取窗口索引\n\tparent.layer.close(index);\n});\n\n</script>\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/menu/menuList.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<title>Insert title here</title>\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/bootstrap.min.css\">\n<link rel=\"stylesheet\" href=\"/css/treetable/jquery.treetable.css\" />\n<link rel=\"stylesheet\" href=\"/css/treetable/jquery.treetable.theme.default.css\" />\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/lib/layui/css/layui.css\">\n</head>\n<body>\n    <div>\n        <div class=\"col-xs-12 col-sm-12 col-md-12 col-lg-12\">\n                <header style=\"height: 100%\">\n                    <div align=\"left\">\n\t                    <table style=\"width: 100%\">\n\t                   \t\t<tr>\n\t                   \t\t\t<td>\n\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t<td align=\"right\">\n\t                   \t\t\t\t<button class=\"layui-btn layui-btn-sm\" onclick=\"location.href='addMenu.html'\" permission=\"sys:menu:add\">\n                                      <i class=\"layui-icon\">&#xe608;</i> 添加\n                                    </button>\n\t                   \t\t\t</td>\n\t                   \t\t</tr> \n\t                    </table>\n\t\t\t\t\t</div>\n                </header>\n                \n                <div>\n                    <div class=\"widget-body no-padding\">\n                        <table id=\"dt-table\" class=\"table table-striped table-bordered table-hover\" style=\"width:100%\">\n                             <tr>\n                                 <th width=\"20%\">名称</th>\n                                 <th width=\"5%\">id</th>\n\t\t\t\t\t\t\t\t <th>href</th>     \n\t\t\t\t\t\t\t\t <th width=\"15%\">permission</th>     \n\t\t\t\t\t\t\t\t <th width=\"5%\">sort</th>     \n\t\t\t\t\t\t\t\t <th>操作</th>\n                             </tr>\n                        </table>\n                    </div>\n                </div>\n        </div>\n    </div>\n\n</body>\n</html>\n\n<script type=\"text/javascript\" src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n<script type=\"text/javascript\" src=\"/lib/layui/layui.js\"></script>\n<script type=\"text/javascript\" src=\"/js/my/permission.js\"></script>\n<script type=\"text/javascript\" src=\"/js/libs/jquery.treetable.js\"></script>\n<script type=\"text/javascript\">\nvar pers = checkPermission();\ninitMenuList();\n\nfunction initMenuList(){\n\t$.ajax({\n\t\ttype : 'get',\n\t\turl : '/permissions',\n\t\tcontentType: \"application/json; charset=utf-8\",  \n\t\tasync:false,\n\t\tsuccess : function(data) {\n\t\t\tvar length = data.length;\n\t\t\tfor(var i=0; i<length; i++){\n\t\t\t\tvar d = data[i];\n\t\t\t\tvar tr = \"<tr data-tt-id='\" + d['id'] + \"' data-tt-parent-id='\" + d['parentId'] + \"'>\";\n\t\t\t\tvar td1 = \"<td>\" + d['name'] +\"</td>\";\n\t\t\t\ttr += td1;\n\t\t\t\tvar id = \"<td>\" + d['id'] +\"</td>\";\n\t\t\t\ttr += id;\n\t\t\t\tvar href = \"\";\n\t\t\t\tif(d['href'] != null){\n\t\t\t\t\thref = d['href'];\n\t\t\t\t}\n\t\t\t\tvar td2 = \"<td>\" + href +\"</td>\";\n\t\t\t\ttr += td2;\n\t\t\t\t\n\t\t\t\tvar permission = d['permission'];\n\t\t\t\tif(permission == null){\n\t\t\t\t\tpermission = \"\";\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tvar td3 = \"<td>\" + permission +\"</td>\";\n\t\t\t\ttr += td3;\n\t\t\t\t\n\t\t\t\tvar sort = d['sort'];\n\t\t\t\tif(sort == 0){\n\t\t\t\t\tsort = \"\";\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tvar td4 = \"<td>\" + sort +\"</td>\";\n\t\t\t\ttr += td4;\n\t\t\t\t\n\t\t\t\tvar id = d['id'];\n\t\t\t\tvar href = \"updateMenu.html?id=\" + id;\n\t\t\t\tvar edit = buttonEdit(href, \"sys:menu:add\", pers);\n\t\t\t\tvar del = buttonDel(id, \"sys:menu:del\", pers);\n                tr += \"<td>\"+edit + del+\"</td>\";\n\t\t\t\ttr += \"</tr>\"\n\t\t\t\t$(\"#dt-table\").append(tr);\n\t\t\t}\n\t\t}\n\t});\n}\n\nlayui.use('layer', function(){\n    var layer = layui.layer;\n});\n\nfunction del(id){\n\tlayer.confirm('确定要删除吗？', {\n        btn : [ '确定', '取消' ]\n    }, function() {\n        $.ajax({\n            type : 'delete',\n            url : '/permissions/' + id,\n            success : function(data) {\n                location.reload();\n            }\n        });\n    });\n}\n\n\tvar option = {\n\t\texpandable : true,\n\t\tclickableNodeNames : true,\n\t\tonNodeExpand : function() {\n\t\t\tvar d = this;\n\t\t\tconsole.log(d['id']);\n\t\t\tconsole.log(d['parentId']);\n\t\t},\n\t\tonNodeCollapse : function() {\n\t\t\tvar d = this;\n\t\t\tconsole.log(d['id'] + \"Collapse\");\n\t\t\tconsole.log(d['parentId'] + \"Collapse\");\n\t\t}\n\n\t};\n\n\t$(\"#dt-table\").treetable(option);\n</script>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/menu/updateMenu.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/bootstrap.min.css\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/font-awesome/css/font-awesome.css\">\n</head>\n<body>\n<div class=\"col-xs-12 col-sm-12 col-md-12 col-lg-12\">\n\t<form class=\"form-horizontal\" onsubmit=\"return false\" id=\"form\">\n\t\t<fieldset>\n\t\t\t<input type=\"hidden\" id=\"id\" name=\"id\">\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">上级菜单</label>\n\t\t\t\t<div class=\"col-md-10\">\n                    <select id=\"parentId\" name=\"parentId\" class=\"form-control input-sm\"></select>\n                </div>\n\t\t\t</div>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">名称</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<input class=\"form-control\" placeholder=\"名称\" type=\"text\" name=\"name\" id=\"name\"\n\t\t\t\t\t\tdata-bv-notempty=\"true\"\n\t\t\t\t\t\tdata-bv-notempty-message=\"名称 不能为空\">\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">样式</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<button onclick=\"selectCss()\" class=\"btn btn-primary\">选择</button>\n\t\t\t\t\t<input type=\"hidden\"  name=\"css\" id=\"css\" /><i id=\"cssImg\" class=\"fa\"></i>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">链接</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<input class=\"form-control\" placeholder=\"链接\" name=\"href\" id=\"href\"/>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">类型</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<select name=\"type\" class=\"form-control input-sm\" id=\"type\">\n\t\t\t\t\t   <option value=\"1\">菜单</option>\n\t\t\t\t\t   <option value=\"2\">按钮</option>\n\t\t\t\t\t</select>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">权限</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<input class=\"form-control\" placeholder=\"权限\" name=\"permission\" id=\"permission\" />\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"form-group\">\n                <label class=\"col-md-2 control-label\">排序</label>\n                <div class=\"col-md-10\">\n                    <input class=\"form-control\" placeholder=\"排序\" name=\"sort\" id=\"sort\" type=\"number\" \n                        data-bv-notempty=\"true\"\n                        data-bv-notempty-message=\"排序 不能为空\">\n                </div>\n            </div>\n\n\t\t\t<div class=\"form-actions\">\n\t\t\t\t<div class=\"row\" align=\"center\">\n\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t<button class=\"btn btn-primary\" onclick=\"location.href='menuList.html'\">返回</button>\n\t\t\t\t\t\t<button class=\"btn btn-primary\" type=\"submit\" onclick=\"update()\">\n\t\t\t\t\t\t\t<i class=\"fa fa-save\"></i> 保存\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t</fieldset>\n\t</form>\n</div>\n\n\t<script type=\"text/javascript\" src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/plugin/bootstrapvalidator/bootstrapValidator.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/common.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/my/ztree-menu.js\"></script>\n\t<script type=\"text/javascript\" src=\"/lib/layui/layui.js\"></script>\n\t<script type=\"text/javascript\">\n\tlayui.use('layer', function(){\n\t    var layer = layui.layer;\n\t});\n\n\tinitParentMenuSelect();\n\tinitData();\n\t\n\tfunction initData(){\n\t\tvar id = getUrlParam(\"id\");\n\t\tif(id != \"\"){\n\t\t\t$.ajax({\n\t\t\t\ttype : 'get',\n\t\t\t\turl : '/permissions/'+id,\n\t\t\t\tasync : false,\n\t\t\t\tsuccess : function(data) {\n\t\t\t\t\t$(\"#id\").val(data.id);\n\t\t\t\t\t$(\"#parentId\").val(data.parentId);\n\t\t\t\t\t$(\"#name\").val(data.name);\n\t\t\t\t\tvar css = data.css;\n\t\t\t\t\t$(\"#css\").val(css);\n\t\t\t\t\t$(\"#href\").val(data.href);\n\t\t\t\t\t$(\"#type\").val(data.type);\n\t\t\t\t\t$(\"#permission\").val(data.permission);\n\t\t\t\t\t$(\"#sort\").val(data.sort);\n\t\t\t\t\t\n\t\t\t\t\tif(css != \"\"){\n\t\t\t\t\t\t$(\"#cssImg\").addClass(\"fa\");\n\t\t\t\t\t\t$(\"#cssImg\").addClass(css);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t}\n\t}\n\t\n\tfunction selectCss(){\n\t\tlayer.open({\n\t\t\t  type: 2,\n\t\t\t  title: \"样式\",\n\t\t\t  area: ['800px', '400px'],\n\t\t\t  maxmin: true,\n\t\t\t  shadeClose: true,\n\t\t\t  content: ['icon.html']\n\t\t\t});\n\t}\n\t\n\t\tfunction update() {\n\t\t\t$('#form').bootstrapValidator();\n\t\t\tvar bootstrapValidator = $(\"#form\").data('bootstrapValidator');\n\t\t\tbootstrapValidator.validate();\n\t\t    if(!bootstrapValidator.isValid()){\n\t\t\t   return;\n\t\t    }\n\t\t    \n\t\t    var formdata = $(\"#form\").serializeObject();\n\n\t\t\t$.ajax({\n\t\t\t\ttype : 'put',\n\t\t\t\turl : '/permissions/',\n\t\t\t\tcontentType: \"application/json; charset=utf-8\",  \n\t\t\t\tdata : JSON.stringify(formdata),\n\t\t\t\tsuccess : function(data) {\n\t\t\t\t\tlayer.msg(\"修改成功\", {shift: -1, time: 1000}, function(){\n                        location.href = \"menuList.html\";\n                    });\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\t\n\t</script>\n</body>\n</html>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/notice/addNotice.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/bootstrap.min.css\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/lib/layui/css/layui.css\">\n</head>\n<body>\n\t<div class=\"col-xs-12 col-sm-12 col-md-12 col-lg-12\">\n\t\t<fieldset>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">title</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<input class=\"form-control\" placeholder=\"title\" type=\"text\" name=\"title\" id=\"title\">\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">内容</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<textarea class=\"layui-textarea\" id=\"demo\" style=\"display: none\">  \n\t\t\t\t\t</textarea>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">状态</label>\n\t\t\t\t<div class=\"col-md-10\" style=\"width: 100px\">\n\t\t\t\t\t<select class=\"form-control input-sm\" name=\"status\" id=\"status\">\n\t\t\t\t\t</select>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"form-actions\">\n\t\t\t\t<div class=\"row\" align=\"center\">\n\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t    <button class=\"btn btn-primary\" onclick=\"location.href='noticeList.html'\">返回</button>\n\t\t\t\t\t\t<button class=\"btn btn-primary\" type=\"submit\" onclick=\"add(this)\">\n\t\t\t\t\t\t\t<i class=\"fa fa-save\"></i> 保存\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t</fieldset>\n\t</div>\n\t\n\t<script type=\"text/javascript\" src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n\t<script type=\"text/javascript\" src=\"/lib/layui/layui.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/common.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/dict.js\"></script>\n\t<script type=\"text/javascript\">\n\tshowDictSelect(\"status\", \"noticeStatus\");\n\t\n\t\tvar pro = window.location.protocol;\n\t\tvar host = window.location.host;\n\t\tvar domain = pro + \"//\" + host;\n\t\t\n\t\tvar layedit, index;\n\t\tlayui.use(['layedit','upload'], function(){\n\t\t  layedit = layui.layedit;\n\t\t  layedit.set({\n              uploadImage: {\n                url: '/files/layui?domain=' + domain+\"&token=\"+localStorage.getItem(\"token\"),\n                type: 'post'\n              }\n            });\n\t\t  index = layedit.build('demo');\n\t\t});\n\t\n\t\tfunction add(obj) {\n\t\t\tvar title = $(\"#title\").val();\n\t\t\tvar status = $(\"#status\").val();\n\t\t    if(title.trim() == \"\"){\n\t\t       layer.msg(\"title不能为空\")\n\t\t\t   return;\n\t\t    }\n\t\t    if(status.trim() == \"\"){\n\t\t       layer.msg(\"状态不能为空\")\n\t\t\t   return;\n\t\t    }\n\t\t    $(obj).attr(\"disabled\",true);\n\t\t    \n\t\t    var formdata = $(\"#form\").serializeObject();\n\t\t    formdata.title = title;\n\t\t    formdata.status = status;\n\t\t    formdata.content = layedit.getContent(index);\n\n\t\t\t$.ajax({\n\t\t\t\ttype : 'post',\n\t\t\t\turl : '/notices',\n\t\t\t\tcontentType: \"application/json; charset=utf-8\",  \n\t\t\t\tdata : JSON.stringify(formdata),\n\t\t\t\tsuccess : function(data) {\n\t\t\t\t\tlayer.msg(\"添加成功\", {shift: -1, time: 1000}, function(){\n\t\t\t\t\t\tlocation.href = \"noticeList.html\";\n                    });\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\t\n\t</script>\n</body>\n</html>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/notice/detail.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/bootstrap.min.css\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/lib/layui/css/layui.css\">\n</head>\n<body>\n\t<div class=\"col-xs-12 col-sm-12 col-md-12 col-lg-12\">\n\t\t<fieldset>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">title</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<p id=\"title\"></p>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">内容</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<textarea class=\"layui-textarea\" id=\"demo\" style=\"display: none\">  \n\t\t\t\t\t</textarea>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">时间</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<span id=\"updateTime\"></span>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">已读人员</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t<ul class=\"layui-tab-title\" id=\"users\"></ul>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t</fieldset>\n\t</div>\n\n\t<script type=\"text/javascript\" src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/lib/layui/layui.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/common.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n\t<script type=\"text/javascript\">\n\t\n\tinitData();\n\t\n\tfunction initData(){\n\t\tvar id = getUrlParam(\"id\");\n\t\tif(id != \"\"){\n\t\t\t$.ajax({\n\t\t\t\ttype : 'get',\n\t\t\t\turl : '/notices?id='+id,\n\t\t\t\tasync : false,\n\t\t\t\tsuccess : function(data) {\n\t\t\t\t\tvar notice = data.notice;\n\t\t\t\t\tif(notice != null){\n\t\t\t\t\t\t$(\"#title\").text(notice.title);\n\t\t\t\t\t\t$(\"#status\").val(notice.status);\n\t\t\t\t\t\t$(\"#demo\").text(notice.content);\n\t\t\t\t\t\t$(\"#updateTime\").text(notice.updateTime);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tvar users = data.users;\n\t\t\t\t\tif(users != null){\n\t\t\t\t\t\tfor(var i=0;i<users.length;i++){\n\t\t\t\t\t\t\tvar u = users[i];\n\t\t\t\t\t\t\t$(\"#users\").append(\"<li>\"+u.nickname+\"</li>\");\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\n\t\t}\n\t}\n\t\n\t\tvar layedit, index;\n\t\tlayui.use('layedit', function(){\n\t\t  layedit = layui.layedit;\n\t\t  index = layedit.build('demo', {\n\t\t\t  tool: ['strong']\n\t\t  });\n\t\t});\n\t\t\n\t</script>\n</body>\n</html>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/notice/noticeList.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<title>Insert title here</title>\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/bootstrap.min.css\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/dataTables.bootstrap.min.css\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/lib/layui/css/layui.css\">\n</head>\n<body>\n    <div>\n        <div class=\"col-xs-12 col-sm-12 col-md-12 col-lg-12\">\n                <header style=\"height: 100%\">\n                    <div align=\"left\">\n\t                    <table style=\"width: 100%\">\n\t                   \t\t<tr>\n\t                   \t\t\t<td>\n\t\t\t\t\t\t\t\t\t<form class=\"form-inline\" onsubmit=\"return false\">\n\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\ttitle：\n\t\t\t\t\t\t\t\t\t\t\t<input id=\"title\" type=\"text\" class=\"form-control\" placeholder=\"title\">\n\t\t\t\t\t\t\t\t\t\t\t时间：\n\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" class=\"form-control\" placeholder=\"开始时间\" id=\"beginTime\">\n\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" class=\"form-control\" placeholder=\"结束时间\" id=\"endTime\">\n\t\t\t\t\t\t\t\t\t\t\t状态：\n\t\t\t\t\t\t\t\t\t\t\t<select class=\"form-control input-sm\" id=\"status\">\n\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"\">全部</option>\n\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"0\">草稿</option>\n\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"1\">发布</option>\n\t\t\t\t\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\t\t\t\t\t<button id=\"searchBt\" class=\"layui-btn layui-btn-sm\" permission=\"notice:query\"><i class=\"layui-icon\">&#xe615;</i>搜索</button>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</form>\n\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t<td align=\"right\">\n\t\t\t\t\t\t\t\t\t<button class=\"layui-btn layui-btn-sm\" onclick=\"location.href='addNotice.html'\" permission=\"notice:add\">\n\t\t\t\t\t\t\t\t\t  <i class=\"layui-icon\">&#xe608;</i> 添加\n\t\t\t\t\t\t\t\t\t</button>\n\t                   \t\t\t</td>\n\t                   \t\t</tr> \n\t                    </table>\n\t\t\t\t\t</div>\n                </header>\n                \n                <div>\n                    <div class=\"widget-body no-padding\">\n                        <table id=\"dt-table\" class=\"table table-striped table-bordered table-hover\" style=\"width:100%\">\n                            <thead>\n                                <tr>\n                                </tr>                       \n                                <tr>\n                                    <th style=\"width: 10%\">id</th>\n                                    <th>title</th>\n                                    <th style=\"width: 20%\">修改时间</th>\n\t\t\t\t\t\t\t\t\t<th style=\"width: 10%\">状态</th>     \n\t\t\t\t\t\t\t\t\t<th>操作</th>\n                                </tr>\n                            </thead>\n                            <tbody>\n                            </tbody>\n                        </table>\n                    </div>\n                </div>\n        </div>\n    </div>\n</body>\n</html>\n\n<script type=\"text/javascript\" src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n<script type=\"text/javascript\" src=\"/lib/layui/layui.js\"></script>\n<script type=\"text/javascript\" src=\"/js/plugin/datatables/jquery.dataTables.min.js\"></script>\n<script type=\"text/javascript\" src=\"/js/plugin/datatables/dataTables.bootstrap.min.js\"></script>\n<script type=\"text/javascript\" src=\"/js/my/permission.js\"></script>\n<script type=\"text/javascript\" src=\"/js/dict.js\"></script>\n<script type=\"text/javascript\">\nvar pers = checkPermission();\nlayui.use(['layer','laydate'], function(){\n    var layer = layui.layer;\n    var laydate = layui.laydate;\n    laydate.render({\n       elem: '#beginTime'\n    });\n    laydate.render({\n       elem: '#endTime'\n    });\n});\n\nvar noticeStatus = showDictSelect(\"status\", \"noticeStatus\", true);\n\nvar example;\nfunction init(){\n\texample = \n    \t$('#dt-table').DataTable({\n        \t\"searching\": false,\n        \t\"processing\": false,\n        \t\"serverSide\" : true,\n        \t\"language\": {\n                \"url\": \"/js/plugin/datatables/Chinese.lang\"\n            },\n        \t\"ajax\": {\n        \t\t\"url\" : \"/notices\",\n        \t\t\"type\":\"get\",\n        \t\t\"data\":function(d){\n    \t\t\t\td.title = $('#title').val();\n    \t\t\t\td.status = $('#status').val();\n    \t\t\t\td.beginTime = $('#beginTime').val();\n    \t\t\t\td.endTime = $('#endTime').val();\n        \t\t},\n    \t\t\t\"error\":function(xhr, textStatus, errorThrown){\n    \t\t\t\tvar msg = xhr.responseText;\n    \t\t\t\tconsole.log(msg);\n    \t\t\t\tvar response = JSON.parse(msg);\n    \t\t\t\tvar code = response.code;\n    \t\t\t\tvar message = response.message;\n    \t\t\t\tif (code == 400) {\n    \t\t\t\t\tlayer.msg(message);\n    \t\t\t\t} else if (code == 401) {\n    \t\t\t\t\tlocalStorage.removeItem(\"token\");\n    \t\t\t\t\tlayer.msg(\"token过期，请先登录\", {shift: -1, time: 1000}, function(){\n    \t\t\t\t\t\tlocation.href = '/login.html';\n                        });\n    \t\t\t\t} else if (code == 403) {\n    \t\t\t\t\tconsole.log(\"未授权:\" + message);\n    \t\t\t\t\tlayer.msg('未授权');\n    \t\t\t\t} else if (code == 500) {\n    \t\t\t\t\tlayer.msg('系统错误：' + message);\n    \t\t\t\t}\n    \t\t\t}\n        \t},\n        \t\"dom\": \"<'dt-toolbar'r>t<'dt-toolbar-footer'<'col-sm-10 col-xs-12 hidden-xs'i><'col-xs-12 col-sm-10' p v>>\",\t\n            \"columns\": [\n                { \"data\": \"id\", \"defaultContent\": \"\"},\n                { \"data\": \"title\", \"defaultContent\": \"\"},\n                { \"data\": \"updateTime\", \"defaultContent\": \"\"},\n                { \n                \t\"data\": \"status\", \n                \t\"defaultContent\": \"\",\n                \t\"render\": function (data, type, row) {\n                    \treturn noticeStatus[data];\n                  \t}\n                },\n                { \n                \t\"data\": \"\", \n                \t\"defaultContent\": \"\",\n                \t\"orderable\":false,\n                \t\"render\": function (data, type, row) {\n                \t\tvar id = row['id'];\n                \t\tvar status = row['status'];\n                \t\tvar href = \"updateNotice.html?id=\" + id;\n                \t\tvar edit = buttonEdit(href, \"notice:add\", pers);\n                \t\tif(status == 1){\n                \t\t\tedit = \"<button class='layui-btn layui-btn-xs' style='background-color:#c2c2c2;' title='不可编辑'><i class='layui-icon' style='color: #F0F0F0;'>&#xe642;</i></button>\";\n                \t\t}\n                        var del = buttonDel(id, \"notice:del\", pers);\n                        return edit + del + \"<button class='layui-btn layui-btn-xs' title='详情' onclick='showDetail(\\\"\" + id +\"\\\")'><i class='layui-icon'>&#xe65f;</i></button>\";\n                     }\n                },\n            ],\n            \"order\": [[ 2, \"desc\" ],[1, \"desc\"]]\n        } );\n}\n\nfunction showDetail(id){\n\tlayer.open({\n\t\t  type: 2,\n\t\t  title: false,\n\t\t  area: ['800px', '400px'],\n\t\t  shadeClose: true,\n\t\t  content: ['detail.html?id='+id]\n\t\t});\n}\n\nfunction del(id){\n    layer.confirm('确定要删除吗？', {\n        btn : [ '确定', '取消' ]\n    }, function() {\n        $.ajax({\n            type : 'delete',\n            url : '/notices/'+id,\n            success : function(data) {\n                example.ajax.reload();\n                layer.msg(\"删除成功\");\n            }\n        });\n        \n        layer.close(1);\n    });\n}\n\n$(\"#searchBt\").click(function(){\n\texample.ajax.reload();\n});\n\ninit();\n</script>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/notice/noticePubList.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<title>Insert title here</title>\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/bootstrap.min.css\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/dataTables.bootstrap.min.css\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/lib/layui/css/layui.css\">\n</head>\n<body>\n    <div>\n        <div class=\"col-xs-12 col-sm-12 col-md-12 col-lg-12\">\n                <header style=\"height: 100%\">\n                    <div align=\"left\">\n\t                    <table style=\"width: 100%\">\n\t                   \t\t<tr>\n\t                   \t\t\t<td>\n\t\t\t\t\t\t\t\t\t<form class=\"form-inline\" onsubmit=\"return false\">\n\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\ttitle：\n\t\t\t\t\t\t\t\t\t\t\t<input id=\"title\" type=\"text\" class=\"form-control\" placeholder=\"title\">\n\t\t\t\t\t\t\t\t\t\t\t时间：\n\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" class=\"form-control\" placeholder=\"开始时间\" id=\"beginTime\">\n\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" class=\"form-control\" placeholder=\"结束时间\" id=\"endTime\">\n\t\t\t\t\t\t\t\t\t\t\t状态：\n\t\t\t\t\t\t\t\t\t\t\t<select class=\"form-control input-sm\" id=\"isRead\">\n\t\t\t\t\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\t\t\t\t\t<button id=\"searchBt\" class=\"layui-btn layui-btn-sm\"><i class=\"layui-icon\">&#xe615;</i>搜索</button>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</form>\n\t\t\t\t\t\t\t\t</td>\n\t                   \t\t</tr> \n\t                    </table>\n\t\t\t\t\t</div>\n                </header>\n                \n                <div>\n                    <div class=\"widget-body no-padding\">\n                        <table id=\"dt-table\" class=\"table table-striped table-bordered table-hover\" style=\"width:100%\">\n                            <thead>\n                                <tr>\n                                </tr>                       \n                                <tr>\n                                    <th>title</th>\n                                    <th>发布时间</th>\n                                    <th>状态</th>\n                                    <th>阅读时间</th>\n                                    <th>操作</th>\n                                </tr>\n                            </thead>\n                            <tbody>\n                            </tbody>\n                        </table>\n                    </div>\n                </div>\n        </div>\n    </div>\n</body>\n</html>\n\n<script type=\"text/javascript\" src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n<script type=\"text/javascript\" src=\"/lib/layui/layui.js\"></script>\n<script type=\"text/javascript\" src=\"/js/plugin/datatables/jquery.dataTables.min.js\"></script>\n<script type=\"text/javascript\" src=\"/js/plugin/datatables/dataTables.bootstrap.min.js\"></script>\n<script type=\"text/javascript\" src=\"/js/dict.js\"></script>\n<script type=\"text/javascript\">\nlayui.use(['layer','laydate'], function(){\n    var layer = layui.layer;\n    var laydate = layui.laydate;\n    laydate.render({\n       elem: '#beginTime'\n    });\n    laydate.render({\n       elem: '#endTime'\n    });\n});\n\nvar isRead = showDictSelect(\"isRead\", \"isRead\", true);\n\nvar example;\nfunction init(){\n\texample = \n    \t$('#dt-table').DataTable({\n        \t\"searching\": false,\n        \t\"processing\": false,\n        \t\"serverSide\" : true,\n        \t\"language\": {\n                \"url\": \"/js/plugin/datatables/Chinese.lang\"\n            },\n        \t\"ajax\": {\n        \t\t\"url\" : \"/notices/published\",\n        \t\t\"type\":\"get\",\n        \t\t\"data\":function(d){\n    \t\t\t\td.title = $('#title').val();\n    \t\t\t\td.beginTime = $('#beginTime').val();\n    \t\t\t\td.endTime = $('#endTime').val();\n    \t\t\t\td.isRead = $('#isRead').val();\n    \t\t\t}\n        \t},\n        \t\"dom\": \"<'dt-toolbar'r>t<'dt-toolbar-footer'<'col-sm-10 col-xs-12 hidden-xs'i><'col-xs-12 col-sm-10' p v>>\",\t\n            \"columns\": [\n                { \"data\": \"title\", \"defaultContent\": \"\"},\n                { \"data\": \"updateTime\", \"defaultContent\": \"\"},\n                { \n                \t\"data\": \"\", \n                \t\"defaultContent\": \"\",\n                \t\"render\": function (data, type, row) {\n                \t\tvar isRead = row['isRead'];\n                \t\tif(isRead){\n                \t\t\treturn \"已读\";\n                \t\t}\n                        return \"<span style='color:red'>未读</span>\";\n                     }\n                },\n                { \"data\": \"readTime\", \"defaultContent\": \"\"},\n                { \n                \t\"data\": \"\", \n                \t\"defaultContent\": \"\",\n                \t\"orderable\":false,\n                \t\"render\": function (data, type, row) {\n                \t\tvar id = row['id'];\n                \t\treturn \"<button class='layui-btn layui-btn-xs' title='详情' onclick='showDetail(this,\\\"\" + id +\"\\\")'><i class='layui-icon'>&#xe65f;</i></button>\";\n                    }\n                },\n            ],\n            \"order\": [[ 2, \"asc\" ],[1, \"desc\"]]\n        } );\n}\n\nfunction showDetail(obj,id){\n\tvar tr = $(obj).parents(\"tr\")[0];\n\tvar td = $(tr).find(\"td\").eq(2);\n\tvar v = $(td).text();\n\tvar isRead = (v == \"已读\");\n\tif(!isRead){\n\t\t$(td).text(\"已读\");\n\t}\n\t\n\tlayer.open({\n\t\t  type: 2,\n\t\t  title: false,\n\t\t  area: ['800px', '400px'],\n\t\t  shadeClose: true,\n\t\t  content: ['detail.html?id='+id]\n\t\t});\n\n\tif(!isRead) {\n\t\tparent.$(\"[unreadNotice]\").each(function(){\n\t\t\tvar n = $(this).text();\n\t\t\tif(!isNaN(n) && n>0) {\n\t\t\t\tn = n-1;\n\t\t\t\tif(n>0){\n\t\t\t\t\t$(this).html(\"<span class='layui-badge'>\"+n+\"</span>\");\n\t\t\t\t}else{\n\t\t\t\t\t$(this).html(\"\");\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n}\n\nfunction del(id){\n    layer.confirm('确定要删除吗？', {\n        btn : [ '确定', '取消' ]\n    }, function() {\n        $.ajax({\n            type : 'delete',\n            url : '/notices/'+id,\n            success : function(data) {\n                example.ajax.reload();\n                layer.msg(\"删除成功\");\n            }\n        });\n        \n        layer.close(1);\n    });\n}\n\n$(\"#searchBt\").click(function(){\n\texample.ajax.reload();\n});\n\ninit();\n</script>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/notice/updateNotice.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/bootstrap.min.css\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/lib/layui/css/layui.css\">\n</head>\n<body>\n\t<div class=\"col-xs-12 col-sm-12 col-md-12 col-lg-12\">\n\t\t<fieldset>\n\t\t\t<input type=\"hidden\" id=\"id\" name=\"id\">\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">title</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<input class=\"form-control\" placeholder=\"title\" type=\"text\" name=\"title\" id=\"title\">\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">内容</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<textarea class=\"layui-textarea\" id=\"demo\" style=\"display: none\">  \n\t\t\t\t\t</textarea>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">状态</label>\n\t\t\t\t<div class=\"col-md-10\" style=\"width: 100px\">\n\t\t\t\t\t<select class=\"form-control input-sm\" name=\"status\" id=\"status\">\n\t\t\t\t\t</select>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"form-actions\">\n\t\t\t\t<div class=\"row\" align=\"center\">\n\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t    <button class=\"btn btn-primary\" onclick=\"location.href='noticeList.html'\">返回</button>\n\t\t\t\t\t\t<button class=\"btn btn-primary\" type=\"submit\" onclick=\"update(this)\">\n\t\t\t\t\t\t\t<i class=\"fa fa-save\"></i> 保存\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t</fieldset>\n\t</div>\n\n\t<script type=\"text/javascript\" src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n\t<script type=\"text/javascript\" src=\"/lib/layui/layui.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/common.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/dict.js\"></script>\n\t<script type=\"text/javascript\">\n\tshowDictSelect(\"status\", \"noticeStatus\");\n\tinitData();\n\t\n\tfunction initData(){\n\t\tvar id = getUrlParam(\"id\");\n\t\tif(id != \"\"){\n\t\t\t$.ajax({\n\t\t\t\ttype : 'get',\n\t\t\t\turl : '/notices/'+id,\n\t\t\t\tasync : false,\n\t\t\t\tsuccess : function(data) {\n\t\t\t\t\t$(\"#id\").val(data.id);\n\t\t\t\t\t$(\"#title\").val(data.title);\n\t\t\t\t\t$(\"#status\").val(data.status);\n\t\t\t\t\t$(\"#demo\").text(data.content);\n\t\t\t\t\t\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t}\n\t}\n\t\n\t\tvar pro = window.location.protocol;\n\t\tvar host = window.location.host;\n\t\tvar domain = pro + \"//\" + host;\n\t\t\n\t\tvar layedit, index;\n\t\tlayui.use('layedit', function(){\n\t\t  layedit = layui.layedit;\n\t\t  layedit.set({\n              uploadImage: {\n            \t  url: '/files/layui?domain=' + domain+\"&token=\"+localStorage.getItem(\"token\"),\n                type: 'post'\n              }\n            });\n\t\t  index = layedit.build('demo');\n\t\t});\n\t\t\n\t\t\n\t\t\n\t\tfunction update(obj) {\n\t\t\tvar title = $(\"#title\").val();\n\t\t\tvar status = $(\"#status\").val();\n\t\t    if(title.trim() == \"\"){\n\t\t       layer.msg(\"title不能为空\")\n\t\t\t   return;\n\t\t    }\n\t\t    if(status.trim() == \"\"){\n\t\t       layer.msg(\"状态不能为空\")\n\t\t\t   return;\n\t\t    }\n\t\t    $(obj).attr(\"disabled\",true);\n\t\t    \n\t\t    var formdata = $(\"#form\").serializeObject();\n\t\t    formdata.id = $(\"#id\").val();\n\t\t    formdata.title = title;\n\t\t    formdata.status = status;\n\t\t    formdata.content = layedit.getContent(index);\n\n\t\t\t$.ajax({\n\t\t\t\ttype : 'put',\n\t\t\t\turl : '/notices',\n\t\t\t\tcontentType: \"application/json; charset=utf-8\",  \n\t\t\t\tdata : JSON.stringify(formdata),\n\t\t\t\tsuccess : function(data) {\n\t\t\t\t\tlayer.msg(\"修改成功\", {shift: -1, time: 1000}, function(){\n                        location.href = \"noticeList.html\";\n                    });\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\t\n\t</script>\n</body>\n</html>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/role/addRole.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en-us\" id=\"extr-page\">\n<head>\n<meta charset=\"UTF-8\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/bootstrap.min.css\">\n <!--layui and necessary plugins-->\n<link rel=\"stylesheet\" type=\"text/css\" href=\"/lib/layui/css/layui.css\"></link>\n\n<link rel=\"stylesheet\" href=\"/css/ztree/metroStyle/metroStyle.css\" type=\"text/css\">\n</head>\n<body>\n<div class=\"col-xs-12 col-sm-12 col-md-12 col-lg-12\">\n\t<form class=\"form-horizontal\" onsubmit=\"return false\" id=\"form\">\n\t\t<fieldset>\n\t\t\t<input type=\"hidden\" id=\"id\" name=\"id\">\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">角色</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<input class=\"form-control\" placeholder=\"角色\" type=\"text\" name=\"name\" id=\"name\"\n\t\t\t\t\t\tdata-bv-notempty=\"true\"\n\t\t\t\t\t\tdata-bv-notempty-message=\"角色 不能为空\">\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">描述</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<textarea class=\"form-control\" placeholder=\"描述\" name=\"description\"  id=\"description\"></textarea>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">权限</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<ul id=\"treeDemo\" class=\"ztree\"></ul>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"form-actions\">\n\t\t\t\t<div class=\"row\" align=\"center\">\n\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t<button class=\"layui-btn layui-btn-sm\" onclick=\"location.href='roleList.html'\">返回</button>\n\t\t\t\t\t\t<button class=\"layui-btn layui-btn-sm\" type=\"submit\" onclick=\"add()\">\n\t\t\t\t\t\t\t<i class=\"fa fa-save\"></i> 保存\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t</fieldset>\n\t</form>\n</div>\n\n\t<script type=\"text/javascript\" src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/plugin/bootstrapvalidator/bootstrapValidator.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/common.js\"></script>\n\t<script type=\"text/javascript\" src=\"/lib/layui/layui.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/libs/jquery.ztree.all-3.5.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/my/ztree-menu.js\"></script>\n\t<script type=\"text/javascript\">\n\tlayui.use('layer', function(){\n\t    var layer = layui.layer;\n\t});\n\t\n\t\t$.fn.zTree.init($(\"#treeDemo\"), getSettting(), getMenuTree());\n\t\tinitData();\n\t\n\t\tfunction initData(){\n\t\t\tvar id = getUrlParam(\"id\");\n\t\t\tif(id != \"\"){\n\t\t\t\t$.ajax({\n\t\t\t\t\ttype : 'get',\n\t\t\t\t\turl : '/roles/'+id,\n\t\t\t\t\tasync : false,\n\t\t\t\t\tsuccess : function(data) {\n\t\t\t\t\t\t$(\"#id\").val(data.id);\n\t\t\t\t\t\t$(\"#name\").val(data.name);\n\t\t\t\t\t\t$(\"#description\").val(data.description);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\tinitMenuDatas(id);\n\t\t\t}\n\t\t}\n\t\t\n\t\t\n\t\t$('#form').bootstrapValidator();\n\t\t\n\t\tfunction add() {\n\t\t\tvar bootstrapValidator = $(\"#form\").data('bootstrapValidator');\n\t\t\tbootstrapValidator.validate();\n\t\t    if(!bootstrapValidator.isValid()){\n\t\t\t   return;\n\t\t    }\n\t\t    \n\t\t    var formdata = $(\"#form\").serializeObject();\n\t\t    formdata.permissionIds = getCheckedMenuIds();\n\n\t\t\t$.ajax({\n\t\t\t\ttype : 'post',\n\t\t\t\turl : '/roles',\n\t\t\t\tcontentType: \"application/json; charset=utf-8\",  \n\t\t\t\tdata : JSON.stringify(formdata),\n\t\t\t\tsuccess : function(data) {\n\t\t\t\t\tlayer.msg(\"成功\", {shift: -1, time: 1000}, function(){\n                        location.href = \"roleList.html\";\n                    });\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\t\n\t</script>\n</body>\n</html>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/role/roleList.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<title>Insert title here</title>\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/bootstrap.min.css\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/dataTables.bootstrap.min.css\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/lib/layui/css/layui.css\">\n</head>\n<body>\n    <div>\n        <div class=\"col-xs-12 col-sm-12 col-md-12 col-lg-12\">\n                <header style=\"height: 100%\">\n                    <div align=\"left\">\n\t                    <table style=\"width: 100%\">\n\t                   \t\t<tr>\n\t                   \t\t\t<td>\n\t\t                   \t\t\t<form class=\"form-inline\" onsubmit=\"return false\">\n\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t角色：\n\t\t\t\t\t\t\t\t\t\t\t<input id=\"name\" type=\"text\" class=\"form-control\" placeholder=\"角色\">\n\t\t\t\t\t\t\t\t\t\t\t<button id=\"searchBt\" class=\"layui-btn layui-btn-sm\" permission=\"sys:role:query\"><i class=\"layui-icon\">&#xe615;</i>搜索</button>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</form>\n\t                   \t\t\t</td>\n\t                   \t\t\t<td align=\"right\">\n\t                   \t\t\t\t<button class=\"layui-btn layui-btn-sm\" onclick=\"location.href='addRole.html'\" permission=\"sys:role:add\">\n                                      <i class=\"layui-icon\">&#xe608;</i> 添加\n                                    </button>\n\t                   \t\t\t</td>\n\t                   \t\t</tr> \n\t                    </table>\n\t\t\t\t\t</div>\n                </header>\n                \n                <div>\n                    <div class=\"widget-body no-padding\">\n                        <table id=\"dt-table\" class=\"table table-striped table-bordered table-hover\" style=\"width:100%\">\n                            <thead>\n                                <tr>\n                                </tr>                       \n                                <tr>\n                                    <th style=\"width: 20%\">角色</th>\n\t\t\t\t\t\t\t\t\t<th>描述</th>\n\t\t\t\t\t\t\t\t\t<th style=\"width: 20%\">修改时间</th>\n\t\t\t\t\t\t\t\t\t<th style=\"width: 10%\">操作</th>\n                                </tr>\n                            </thead>\n                            <tbody>\n                            </tbody>\n                        </table>\n                    </div>\n                </div>\n        </div>\n    </div>\n</body>\n</html>\n\n<script type=\"text/javascript\" src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n<script type=\"text/javascript\" src=\"/js/plugin/datatables/jquery.dataTables.min.js\"></script>\n<script type=\"text/javascript\" src=\"/js/plugin/datatables/dataTables.bootstrap.min.js\"></script>\n<script type=\"text/javascript\" src=\"/lib/layui/layui.js\"></script>\n<script type=\"text/javascript\" src=\"/js/my/permission.js\"></script>\n<script type=\"text/javascript\">\nvar pers = checkPermission();\n\nvar example;\nfunction init(){\n\texample = \n    \t$('#dt-table').DataTable({\n        \t\"searching\": false,\n        \t\"processing\": false,\n        \t\"serverSide\" : true,\n        \t\"language\": {\n                \"url\": \"/js/plugin/datatables/Chinese.lang\"\n            },\n        \t\"ajax\": {\n        \t\t\"url\" : \"/roles\",\n        \t\t\"type\":\"get\",\n        \t\t\"data\":function(d){\n    \t\t\t\td.name = $('#name').val();\n        \t\t},\n    \t\t\t\"error\":function(xhr, textStatus, errorThrown){\n    \t\t\t\tvar msg = xhr.responseText;\n    \t\t\t\tconsole.log(msg);\n    \t\t\t\tvar response = JSON.parse(msg);\n    \t\t\t\tvar code = response.code;\n    \t\t\t\tvar message = response.message;\n    \t\t\t\tif (code == 400) {\n    \t\t\t\t\tlayer.msg(message);\n    \t\t\t\t} else if (code == 401) {\n    \t\t\t\t\tlocalStorage.removeItem(\"token\");\n    \t\t\t\t\tlayer.msg(\"token过期，请先登录\", {shift: -1, time: 1000}, function(){\n    \t\t\t\t\t\tlocation.href = '/login.html';\n                        });\n    \t\t\t\t} else if (code == 403) {\n    \t\t\t\t\tconsole.log(\"未授权:\" + message);\n    \t\t\t\t\tlayer.msg('未授权');\n    \t\t\t\t} else if (code == 500) {\n    \t\t\t\t\tlayer.msg('系统错误：' + message);\n    \t\t\t\t}\n    \t\t\t}\n        \t},\n        \t\"dom\": \"<'dt-toolbar'r>t<'dt-toolbar-footer'<'col-sm-10 col-xs-12 hidden-xs'i><'col-xs-12 col-sm-10' p v>>\",\t\n            \"columns\": [\n                { \"data\": \"name\", \"defaultContent\": \"\"},\n                { \"data\": \"description\", \"defaultContent\": \"\"},\n                { \"data\": \"updateTime\", \"defaultContent\": \"\"},\n                { \n                \t\"data\": \"\", \n                \t\"defaultContent\": \"\",\n                \t\"orderable\":false,\n                \t\"render\": function (data, type, row) {\n                \t\tvar id = row['id'];\n                \t\tvar href = \"addRole.html?id=\" + id;\n                        var edit = buttonEdit(href, \"sys:role:add\", pers);\n                \t\tvar del = buttonDel(id, \"sys:role:del\", pers);\n                        return edit + del;\n                  \t}\n                },\n            ],\n            \"order\": [[ 2, \"desc\" ]]\n        } );\n}\n\nlayui.use('layer', function(){\n    var layer = layui.layer;\n});\n\nfunction del(id){\n    layer.confirm('确定要删除吗？', {\n        btn : [ '确定', '取消' ]\n    }, function() {\n        $.ajax({\n            type : 'delete',\n            url : '/roles/'+id,\n            success : function(data) {\n                example.ajax.reload();\n                layer.msg(\"删除成功\");\n            }\n        });\n        \n        layer.close(1);\n    });\n}\n\n$(\"#searchBt\").click(function(){\n\texample.ajax.reload();\n});\n\ninit();\n</script>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/service/addService.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/bootstrap.min.css\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/font-awesome/css/font-awesome.css\">\n</head>\n<body>\n<div class=\"col-xs-12 col-sm-12 col-md-12 col-lg-12\">\n\t<form class=\"form-horizontal\" onsubmit=\"return false\" id=\"form\">\n\t\t<fieldset>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">上级菜单</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<select id=\"parentId\" name=\"parentId\" class=\"form-control input-sm\"></select>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">名称</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<input class=\"form-control\" placeholder=\"名称\" type=\"text\" name=\"name\" id=\"name\"\n\t\t\t\t\t\tdata-bv-notempty=\"true\"\n\t\t\t\t\t\tdata-bv-notempty-message=\"名称 不能为空\">\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">样式</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<button onclick=\"selectCss()\" class=\"btn btn-primary\">选择</button>\n\t\t\t\t\t<input type=\"hidden\"  name=\"css\" id=\"css\" /><i id=\"cssImg\" class=\"fa\"></i>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">链接</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<input class=\"form-control\" placeholder=\"链接\" name=\"href\" id=\"href\"/>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">类型</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<select name=\"type\" class=\"form-control input-sm\">\n\t\t\t\t\t   <option value=\"1\">菜单</option>\n\t\t\t\t\t   <option value=\"2\">按钮</option>\n\t\t\t\t\t</select>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">权限</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<input class=\"form-control\" placeholder=\"权限\" name=\"permission\" id=\"permission\" />\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"form-group\">\n                <label class=\"col-md-2 control-label\">排序</label>\n                <div class=\"col-md-10\">\n                    <input class=\"form-control\" placeholder=\"排序\" name=\"sort\" id=\"sort\" type=\"number\" value=\"100\"\n                        data-bv-notempty=\"true\"\n                        data-bv-notempty-message=\"排序 不能为空\">\n                </div>\n            </div>\n\n\t\t\t<div class=\"form-actions\">\n\t\t\t\t<div class=\"row\" align=\"center\">\n\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t<button class=\"btn btn-primary\" onclick=\"location.href='serviceList.html'\">返回</button>\n\t\t\t\t\t\t<button class=\"btn btn-primary\" type=\"submit\" onclick=\"add()\">\n\t\t\t\t\t\t\t<i class=\"fa fa-save\"></i> 保存\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t</fieldset>\n\t</form>\n</div>\n\n\t<script type=\"text/javascript\" src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/plugin/bootstrapvalidator/bootstrapValidator.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/common.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/my/ztree-service.js\"></script>\n\t<script type=\"text/javascript\" src=\"/lib/layui/layui.js\"></script>\n\t<script type=\"text/javascript\">\n\t\tlayui.use('layer', function(){\n\t\t    var layer = layui.layer;\n\t\t});\n\n\n\t\tinitParentMenuSelect();\n\t\t\n\t\tfunction add() {\n\t\t\t$('#form').bootstrapValidator();\n\t\t\tvar bootstrapValidator = $(\"#form\").data('bootstrapValidator');\n\t\t\tbootstrapValidator.validate();\n\t\t    if(!bootstrapValidator.isValid()){\n\t\t\t   return;\n\t\t    }\n\t\t    \n\t\t    var formdata = $(\"#form\").serializeObject();\n\n\t\t\t$.ajax({\n\t\t\t\ttype : 'post',\n\t\t\t\turl : '/services',\n\t\t\t\tcontentType: \"application/json; charset=utf-8\",  \n\t\t\t\tdata : JSON.stringify(formdata),\n\t\t\t\tsuccess : function(data) {\n\t\t\t\t\tlayer.msg(\"添加成功\", {shift: -1, time: 1000}, function(){\n                        location.href = \"serviceList.html\";\n                    });\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\t\n\t\tfunction selectCss(){\n\t\t\tlayer.open({\n\t\t\t\t  type: 2,\n\t\t\t\t  title: \"样式\",\n\t\t\t\t  area: ['800px', '400px'],\n\t\t\t\t  maxmin: true,\n\t\t\t\t  shadeClose: true,\n\t\t\t\t  content: ['icon.html']\n\t\t\t\t});\n\t\t}\n\t</script>\n</body>\n</html>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/service/icon.html",
    "content": "<!DOCTYPE section PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n<html lang=\"en-us\">\t\n\t<head>\n\t\t<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/bootstrap.min.css\">\n\t\t<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/font-awesome/css/font-awesome.css\">\n\t\t<style type=\"text/css\">\n\t\t\tdiv.demo-icon-font{ cursor:pointer;}\n\t\t</style>\n\t\t\n\t</head>\n<body>\n\t\t\t<div class=\"col-xs-12 col-sm-12 col-md-12 col-lg-12\">\n\t\t\t\t<div align=\"left\">\n\t\t\t\t\t\t\t<div class=\"row\">\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-automobile\"></i> fa-automobile <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-bank\"></i> fa-bank <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-behance\"></i> fa-behance\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-behance-square\"></i> fa-behance-square\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-bomb\"></i> fa-bomb\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-building\"></i> fa-building\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-cab\"></i> fa-cab <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-car\"></i> fa-car\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-child\"></i> fa-child\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-circle-o-notch\"></i> fa-circle-o-notch\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-circle-thin\"></i> fa-circle-thin\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-codepen\"></i> fa-codepen\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-cube\"></i> fa-cube\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-cubes\"></i> fa-cubes\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-database\"></i> fa-database\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-delicious\"></i> fa-delicious\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-deviantart\"></i> fa-deviantart\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-digg\"></i> fa-digg\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-drupal\"></i> fa-drupal\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-empire\"></i> fa-empire\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-envelope-square\"></i> fa-envelope-square\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-fax\"></i> fa-fax\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-file-archive-o\"></i> fa-file-archive-o\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-file-audio-o\"></i> fa-file-audio-o\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-file-code-o\"></i> fa-file-code-o\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-file-excel-o\"></i> fa-file-excel-o\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-file-image-o\"></i> fa-file-image-o\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-file-movie-o\"></i> fa-file-movie-o <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-file-pdf-o\"></i> fa-file-pdf-o\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-file-photo-o\"></i> fa-file-photo-o <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-file-picture-o\"></i> fa-file-picture-o <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-file-powerpoint-o\"></i> fa-file-powerpoint-o\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-file-sound-o\"></i> fa-file-sound-o <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-file-video-o\"></i> fa-file-video-o\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-file-word-o\"></i> fa-file-word-o\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-file-zip-o\"></i> fa-file-zip-o <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-ge\"></i> fa-ge <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-git\"></i> fa-git\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-git-square\"></i> fa-git-square\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-google\"></i> fa-google\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-graduation-cap\"></i> fa-graduation-cap\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-hacker-news\"></i> fa-hacker-news\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-header\"></i> fa-header\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-history\"></i> fa-history\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-institution\"></i> fa-institution <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-joomla\"></i> fa-joomla\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-jsfiddle\"></i> fa-jsfiddle\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-language\"></i> fa-language\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-life-bouy\"></i> fa-life-bouy <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-life-ring\"></i> fa-life-ring\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-life-saver\"></i> fa-life-saver <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-mortar-board\"></i> fa-mortar-board <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-openid\"></i> fa-openid\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-paper-plane\"></i> fa-paper-plane\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-paper-plane-o\"></i> fa-paper-plane-o\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-paragraph\"></i> fa-paragraph\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-paw\"></i> fa-paw\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-pied-piper\"></i> fa-pied-piper\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-pied-piper-alt\"></i> fa-pied-piper-alt\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-pied-piper-square\"></i> fa-pied-piper-square <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-qq\"></i> fa-qq\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-ra\"></i> fa-ra <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-rebel\"></i> fa-rebel\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-recycle\"></i> fa-recycle\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-reddit\"></i> fa-reddit\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-reddit-square\"></i> fa-reddit-square\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-send\"></i> fa-send <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-send-o\"></i> fa-send-o <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-share-alt\"></i> fa-share-alt\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-share-alt-square\"></i> fa-share-alt-square\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-slack\"></i> fa-slack\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-sliders\"></i> fa-sliders\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-soundcloud\"></i> fa-soundcloud\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-space-shuttle\"></i> fa-space-shuttle\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-spoon\"></i> fa-spoon\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-spotify\"></i> fa-spotify\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-steam\"></i> fa-steam\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-steam-square\"></i> fa-steam-square\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-stumbleupon\"></i> fa-stumbleupon\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-stumbleupon-circle\"></i> fa-stumbleupon-circle\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-support\"></i> fa-support <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-taxi\"></i> fa-taxi\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-tencent-weibo\"></i> fa-tencent-weibo\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-tree\"></i> fa-tree\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-university\"></i> fa-university\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-vine\"></i> fa-vine\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-wechat\"></i> fa-wechat <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-weixin\"></i> fa-weixin\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-wordpress\"></i> fa-wordpress\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-yahoo\"></i> fa-yahoo\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t</div>\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t<!-- new sets -->\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t<h2>Web Application Icons</h2>\n\n\t\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-adjust\"></i> fa-adjust\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-anchor\"></i> fa-anchor\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-archive\"></i> fa-archive\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-asterisk\"></i> fa-asterisk\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-ban\"></i> fa-ban\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-bar-chart-o\"></i> fa-bar-chart-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-barcode\"></i> fa-barcode\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-beer\"></i> fa-beer\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-bell\"></i> fa-bell\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-bell-o\"></i> fa-bell-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-bolt\"></i> fa-bolt\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-book\"></i> fa-book\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-bookmark\"></i> fa-bookmark\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-bookmark-o\"></i> fa-bookmark-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-briefcase\"></i> fa-briefcase\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-bug\"></i> fa-bug\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-building\"></i> fa-building\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-bullhorn\"></i> fa-bullhorn\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-bullseye\"></i> fa-bullseye\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-calendar\"></i> fa-calendar\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-calendar-o\"></i> fa-calendar-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-camera\"></i> fa-camera\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-camera-retro\"></i> fa-camera-retro\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-caret-square-o-down\"></i> fa-caret-square-o-down\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-caret-square-o-left\"></i> fa-caret-square-o-left\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-caret-square-o-right\"></i> fa-caret-square-o-right\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-caret-square-o-up\"></i> fa-caret-square-o-up\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-certificate\"></i> fa-certificate\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-check\"></i> fa-check\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-check-circle\"></i> fa-check-circle\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-check-circle-o\"></i> fa-check-circle-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-check-square\"></i> fa-check-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-check-square-o\"></i> fa-check-square-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-circle\"></i> fa-circle\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-circle-o\"></i> fa-circle-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-clock-o\"></i> fa-clock-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-cloud\"></i> fa-cloud\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-cloud-download\"></i> fa-cloud-download\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-cloud-upload\"></i> fa-cloud-upload\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-code\"></i> fa-code\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-code-fork\"></i> fa-code-fork\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-coffee\"></i> fa-coffee\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-cog\"></i> fa-cog\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-cogs\"></i> fa-cogs\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-plus-square-o\"></i> fa-plus-square-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-comment\"></i> fa-comment\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-comment-o\"></i> fa-comment-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-comments\"></i> fa-comments\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-comments-o\"></i> fa-comments-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-compass\"></i> fa-compass\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-credit-card\"></i> fa-credit-card\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-crop\"></i> fa-crop\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-crosshairs\"></i> fa-crosshairs\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-cutlery\"></i> fa-cutlery\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-dashboard\"></i> fa-dashboard <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-desktop\"></i> fa-desktop\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-dot-circle-o\"></i> fa-dot-circle-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-download\"></i> fa-download\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-edit\"></i> fa-edit <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-ellipsis-horizontal\"></i> fa-ellipsis-horizontal\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-ellipsis-vertical\"></i> fa-ellipsis-vertical\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-envelope\"></i> fa-envelope\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-envelope-o\"></i> fa-envelope-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-eraser\"></i> fa-eraser\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-exchange\"></i> fa-exchange\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-exclamation\"></i> fa-exclamation\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-exclamation-circle\"></i> fa-exclamation-circle\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-exclamation-triangle\"></i> fa-exclamation-triangle\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-minus-square-o\"></i> fa-minus-square-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-external-link\"></i> fa-external-link\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-external-link-square\"></i> fa-external-link-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-eye\"></i> fa-eye\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-eye-slash\"></i> fa-eye-slash\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-female\"></i> fa-female\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-fighter-jet\"></i> fa-fighter-jet\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-film\"></i> fa-film\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-filter\"></i> fa-filter\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-fire\"></i> fa-fire\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-fire-extinguisher\"></i> fa-fire-extinguisher\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-flag\"></i> fa-flag\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-flag-checkered\"></i> fa-flag-checkered\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-flag-o\"></i> fa-flag-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-flash\"></i> fa-flash <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-flask\"></i> fa-flask\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-folder\"></i> fa-folder\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-folder-o\"></i> fa-folder-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-folder-open\"></i> fa-folder-open\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-folder-open-o\"></i> fa-folder-open-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-frown-o\"></i> fa-frown-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-gamepad\"></i> fa-gamepad\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-gavel\"></i> fa-gavel\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-gear\"></i> fa-gear <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-gears\"></i> fa-gears <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-gift\"></i> fa-gift\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-glass\"></i> fa-glass\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-globe\"></i> fa-globe\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-group\"></i> fa-group\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-hdd-o\"></i> fa-hdd-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-headphones\"></i> fa-headphones\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-heart\"></i> fa-heart\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-heart-o\"></i> fa-heart-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-home\"></i> fa-home\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-inbox\"></i> fa-inbox\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-info\"></i> fa-info\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-info-circle\"></i> fa-info-circle\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-key\"></i> fa-key\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-keyboard-o\"></i> fa-keyboard-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-laptop\"></i> fa-laptop\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-leaf\"></i> fa-leaf\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-legal\"></i> fa-legal <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-lemon-o\"></i> fa-lemon-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-level-down\"></i> fa-level-down\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-level-up\"></i> fa-level-up\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-lightbulb-o\"></i> fa-lightbulb-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-location-arrow\"></i> fa-location-arrow\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-lock\"></i> fa-lock\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-magic\"></i> fa-magic\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-magnet\"></i> fa-magnet\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-mail-forward\"></i> fa-mail-forward <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-mail-reply\"></i> fa-mail-reply <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-mail-reply-all\"></i> fa-mail-reply-all\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-male\"></i> fa-male\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-map-marker\"></i> fa-map-marker\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-meh-o\"></i> fa-meh-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-microphone\"></i> fa-microphone\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-microphone-slash\"></i> fa-microphone-slash\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-minus\"></i> fa-minus\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-minus-circle\"></i> fa-minus-circle\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-minus-square\"></i> fa-minus-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-minus-square-o\"></i> fa-minus-square-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-mobile\"></i> fa-mobile\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-mobile-phone\"></i> fa-mobile-phone <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-money\"></i> fa-money\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-moon-o\"></i> fa-moon-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-move\"></i> fa-move\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-music\"></i> fa-music\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-pencil\"></i> fa-pencil\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-pencil-square\"></i> fa-pencil-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-pencil-square-o\"></i> fa-pencil-square-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-phone\"></i> fa-phone\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-phone-square\"></i> fa-phone-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-picture-o\"></i> fa-picture-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-plane\"></i> fa-plane\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-plus\"></i> fa-plus\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-plus-circle\"></i> fa-plus-circle\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-plus-square\"></i> fa-plus-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-power-off\"></i> fa-power-off\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-print\"></i> fa-print\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-puzzle-piece\"></i> fa-puzzle-piece\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-qrcode\"></i> fa-qrcode\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-question\"></i> fa-question\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-question-circle\"></i> fa-question-circle\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-quote-left\"></i> fa-quote-left\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-quote-right\"></i> fa-quote-right\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-random\"></i> fa-random\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-refresh\"></i> fa-refresh\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-reorder\"></i> fa-reorder\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-reply\"></i> fa-reply\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-reply-all\"></i> fa-reply-all\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-resize-horizontal\"></i> fa-resize-horizontal\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-resize-vertical\"></i> fa-resize-vertical\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-retweet\"></i> fa-retweet\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-road\"></i> fa-road\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-rocket\"></i> fa-rocket\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-rss\"></i> fa-rss\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-rss-square\"></i> fa-rss-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-search\"></i> fa-search\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-search-minus\"></i> fa-search-minus\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-search-plus\"></i> fa-search-plus\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-share\"></i> fa-share\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-share-square\"></i> fa-share-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-share-square-o\"></i> fa-share-square-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-shield\"></i> fa-shield\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-shopping-cart\"></i> fa-shopping-cart\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-sign-in\"></i> fa-sign-in\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-sign-out\"></i> fa-sign-out\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-signal\"></i> fa-signal\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-sitemap\"></i> fa-sitemap\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-smile-o\"></i> fa-smile-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-sort\"></i> fa-sort\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-sort-alpha-asc\"></i> fa-sort-alpha-asc\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-sort-alpha-desc\"></i> fa-sort-alpha-desc\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-sort-amount-asc\"></i> fa-sort-amount-asc\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-sort-amount-desc\"></i> fa-sort-amount-desc\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-sort-asc\"></i> fa-sort-asc\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-sort-desc\"></i> fa-sort-desc\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-sort-down\"></i> fa-sort-down <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-sort-numeric-asc\"></i> fa-sort-numeric-asc\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-sort-numeric-desc\"></i> fa-sort-numeric-desc\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-sort-up\"></i> fa-sort-up <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-spinner\"></i> fa-spinner\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-square\"></i> fa-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-square-o\"></i> fa-square-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-star\"></i> fa-star\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-star-half\"></i> fa-star-half\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-star-half-empty\"></i> fa-star-half-empty <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-star-half-full\"></i> fa-star-half-full <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-star-half-o\"></i> fa-star-half-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-star-o\"></i> fa-star-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-subscript\"></i> fa-subscript\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-suitcase\"></i> fa-suitcase\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-sun-o\"></i> fa-sun-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-superscript\"></i> fa-superscript\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-tablet\"></i> fa-tablet\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-tachometer\"></i> fa-tachometer\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-tag\"></i> fa-tag\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-tags\"></i> fa-tags\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-tasks\"></i> fa-tasks\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-terminal\"></i> fa-terminal\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-thumb-tack\"></i> fa-thumb-tack\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-thumbs-down\"></i> fa-thumbs-down\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-thumbs-o-down\"></i> fa-thumbs-o-down\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-thumbs-o-up\"></i> fa-thumbs-o-up\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-thumbs-up\"></i> fa-thumbs-up\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-ticket\"></i> fa-ticket\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-times\"></i> fa-times\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-times-circle\"></i> fa-times-circle\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-times-circle-o\"></i> fa-times-circle-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-tint\"></i> fa-tint\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-toggle-down\"></i> fa-toggle-down <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-toggle-left\"></i> fa-toggle-left <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-toggle-right\"></i> fa-toggle-right <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-toggle-up\"></i> fa-toggle-up <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-trash-o\"></i> fa-trash-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-trophy\"></i> fa-trophy\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-truck\"></i> fa-truck\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-umbrella\"></i> fa-umbrella\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-unlock\"></i> fa-unlock\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-unlock-alt\"></i> fa-unlock-alt\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-unsorted\"></i> fa-unsorted <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-upload\"></i> fa-upload\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-user\"></i> fa-user\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-video-camera\"></i> fa-video-camera\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-volume-down\"></i> fa-volume-down\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-volume-off\"></i> fa-volume-off\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-volume-up\"></i> fa-volume-up\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-warning\"></i> fa-warning <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-wheelchair\"></i> fa-wheelchair\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-wrench\"></i> fa-wrench\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t<!-- new sets -->\n\t\t\t\t\t\n\t\t\t\t\t\t\t<h2>Form Control Icons</h2>\n\n\t\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-check-square\"></i> fa-check-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-check-square-o\"></i> fa-check-square-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-circle\"></i> fa-circle\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-circle-o\"></i> fa-circle-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-dot-circle-o\"></i> fa-dot-circle-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-minus-square\"></i> fa-minus-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-minus-square-o\"></i> fa-minus-square-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-square\"></i> fa-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-square-o\"></i> fa-square-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t<!-- new sets -->\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t<h2>Currency Icons</h2>\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-bitcoin\"></i> fa-bitcoin <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-btc\"></i> fa-btc\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-cny\"></i> fa-cny <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-dollar\"></i> fa-dollar <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-eur\"></i> fa-eur\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-euro\"></i> fa-euro <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-gbp\"></i> fa-gbp\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-inr\"></i> fa-inr\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-jpy\"></i> fa-jpy\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-krw\"></i> fa-krw\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-money\"></i> fa-money\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-rmb\"></i> fa-rmb <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-rouble\"></i> fa-rouble <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-rub\"></i> fa-rub\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-ruble\"></i> fa-ruble <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-rupee\"></i> fa-rupee <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-try\"></i> fa-try\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-turkish-lira\"></i> fa-turkish-lira <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-usd\"></i> fa-usd\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-won\"></i> fa-won <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-yen\"></i> fa-yen <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t<!-- new sets -->\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t<h2>Text Editor Icons</h2>\n\n\t\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-align-center\"></i> fa-align-center\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-align-justify\"></i> fa-align-justify\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-align-left\"></i> fa-align-left\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-align-right\"></i> fa-align-right\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-bold\"></i> fa-bold\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-chain\"></i> fa-chain <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-chain-broken\"></i> fa-chain-broken\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-clipboard\"></i> fa-clipboard\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-columns\"></i> fa-columns\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-copy\"></i> fa-copy <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-cut\"></i> fa-cut <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-dedent\"></i> fa-dedent <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-eraser\"></i> fa-eraser\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-file\"></i> fa-file\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-file-o\"></i> fa-file-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-file-text\"></i> fa-file-text\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-file-text-o\"></i> fa-file-text-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-files-o\"></i> fa-files-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-floppy-o\"></i> fa-floppy-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-font\"></i> fa-font\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-indent\"></i> fa-indent\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-italic\"></i> fa-italic\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-link\"></i> fa-link\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-list\"></i> fa-list\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-list-alt\"></i> fa-list-alt\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-list-ol\"></i> fa-list-ol\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-list-ul\"></i> fa-list-ul\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-outdent\"></i> fa-outdent\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-paperclip\"></i> fa-paperclip\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-paste\"></i> fa-paste <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-repeat\"></i> fa-repeat\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-rotate-left\"></i> fa-rotate-left <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-rotate-right\"></i> fa-rotate-right <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-save\"></i> fa-save <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-scissors\"></i> fa-scissors\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-strikethrough\"></i> fa-strikethrough\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-table\"></i> fa-table\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-text-height\"></i> fa-text-height\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-text-width\"></i> fa-text-width\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-th\"></i> fa-th\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-th-large\"></i> fa-th-large\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-th-list\"></i> fa-th-list\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-underline\"></i> fa-underline\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-undo\"></i> fa-undo\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-unlink\"></i> fa-unlink <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t<!-- new sets -->\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t<h2>Directional Icons</h2>\n\n\t\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-double-down\"></i> fa-angle-double-down\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-double-left\"></i> fa-angle-double-left\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-double-right\"></i> fa-angle-double-right\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-double-up\"></i> fa-angle-double-up\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-down\"></i> fa-angle-down\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-left\"></i> fa-angle-left\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right\"></i> fa-angle-right\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-up\"></i> fa-angle-up\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-arrow-circle-down\"></i> fa-arrow-circle-down\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-arrow-circle-left\"></i> fa-arrow-circle-left\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-arrow-circle-o-down\"></i> fa-arrow-circle-o-down\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-arrow-circle-o-left\"></i> fa-arrow-circle-o-left\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-arrow-circle-o-right\"></i> fa-arrow-circle-o-right\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-arrow-circle-o-up\"></i> fa-arrow-circle-o-up\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-arrow-circle-right\"></i> fa-arrow-circle-right\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-arrow-circle-up\"></i> fa-arrow-circle-up\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-arrow-down\"></i> fa-arrow-down\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-arrow-left\"></i> fa-arrow-left\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-arrow-right\"></i> fa-arrow-right\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-arrow-up\"></i> fa-arrow-up\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-caret-down\"></i> fa-caret-down\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-caret-left\"></i> fa-caret-left\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-caret-right\"></i> fa-caret-right\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-caret-square-o-down\"></i> fa-caret-square-o-down\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-caret-square-o-left\"></i> fa-caret-square-o-left\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-caret-square-o-right\"></i> fa-caret-square-o-right\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-caret-square-o-up\"></i> fa-caret-square-o-up\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-caret-up\"></i> fa-caret-up\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-chevron-circle-down\"></i> fa-chevron-circle-down\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-chevron-circle-left\"></i> fa-chevron-circle-left\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-chevron-circle-right\"></i> fa-chevron-circle-right\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-chevron-circle-up\"></i> fa-chevron-circle-up\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-chevron-down\"></i> fa-chevron-down\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-chevron-left\"></i> fa-chevron-left\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-chevron-right\"></i> fa-chevron-right\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-chevron-up\"></i> fa-chevron-up\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-hand-o-down\"></i> fa-hand-o-down\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-hand-o-left\"></i> fa-hand-o-left\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-hand-o-right\"></i> fa-hand-o-right\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-hand-o-up\"></i> fa-hand-o-up\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-long-arrow-down\"></i> fa-long-arrow-down\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-long-arrow-left\"></i> fa-long-arrow-left\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-long-arrow-right\"></i> fa-long-arrow-right\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-long-arrow-up\"></i> fa-long-arrow-up\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-toggle-down\"></i> fa-toggle-down <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-toggle-left\"></i> fa-toggle-left <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-toggle-right\"></i> fa-toggle-right <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-toggle-up\"></i> fa-toggle-up <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t<!-- new sets -->\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t<h2>Video Player Icons</h2>\n\n\t\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-backward\"></i> fa-backward\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-eject\"></i> fa-eject\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-fast-backward\"></i> fa-fast-backward\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-fast-forward\"></i> fa-fast-forward\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-forward\"></i> fa-forward\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-arrows-alt\"></i> fa-arrows-alt\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-pause\"></i> fa-pause\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-play\"></i> fa-play\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-play-circle\"></i> fa-play-circle\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-play-circle-o\"></i> fa-play-circle-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-expand\"></i> fa-expand\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-compress\"></i> fa-compress\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-step-backward\"></i> fa-step-backward\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-step-forward\"></i> fa-step-forward\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-stop\"></i> fa-stop\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-youtube-play\"></i> fa-youtube-play\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t<!-- new sets -->\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t<h2>Brand Icons</h2>\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-adn\"></i> fa-adn\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-android\"></i> fa-android\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-apple\"></i> fa-apple\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-bitbucket\"></i> fa-bitbucket\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-bitbucket-square\"></i> fa-bitbucket-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-bitcoin\"></i> fa-bitcoin <span class=\"text-muted\">(alias)</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-btc\"></i> fa-btc\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-css3\"></i> fa-css3\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-dribbble\"></i> fa-dribbble\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-dropbox\"></i> fa-dropbox\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-facebook\"></i> fa-facebook\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-facebook-square\"></i> fa-facebook-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-flickr\"></i> fa-flickr\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-foursquare\"></i> fa-foursquare\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-github\"></i> fa-github\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-github-alt\"></i> fa-github-alt\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-github-square\"></i> fa-github-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-gittip\"></i> fa-gittip\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-google-plus\"></i> fa-google-plus\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-google-plus-square\"></i> fa-google-plus-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-html5\"></i> fa-html5\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-instagram\"></i> fa-instagram\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-linkedin\"></i> fa-linkedin\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-linkedin-square\"></i> fa-linkedin-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-linux\"></i> fa-linux\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-maxcdn\"></i> fa-maxcdn\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-pagelines\"></i> fa-pagelines\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-pinterest\"></i> fa-pinterest\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-pinterest-square\"></i> fa-pinterest-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-renren\"></i> fa-renren\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-skype\"></i> fa-skype\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-stack-exchange\"></i> fa-stack-exchange\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-stack-overflow\"></i> fa-stack-overflow\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-trello\"></i> fa-trello\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-tumblr\"></i> fa-tumblr\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-tumblr-square\"></i> fa-tumblr-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-twitter\"></i> fa-twitter\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-twitter-square\"></i> fa-twitter-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-vimeo-square\"></i> fa-vimeo-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-vk\"></i> fa-vk\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-weibo\"></i> fa-weibo\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-windows\"></i> fa-windows\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-xing\"></i> fa-xing\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-xing-square\"></i> fa-xing-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-youtube\"></i> fa-youtube\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-youtube-play\"></i> fa-youtube-play\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-youtube-square\"></i> fa-youtube-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t<!-- new sets -->\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t<h2>Medical Icons</h2>\n\n\t\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-ambulance\"></i> fa-ambulance\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-h-square\"></i> fa-h-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-hospital-o\"></i> fa-hospital-o\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-medkit\"></i> fa-medkit\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-plus-square\"></i> fa-plus-square\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-stethoscope\"></i> fa-stethoscope\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-user-md\"></i> fa-user-md\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"col-xs-6 col-md-3 col-sm-4 demo-icon-font\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-wheelchair\"></i> fa-wheelchair\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n</body>\n</html>\n<script src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n<script type=\"text/javascript\">\n$(\".demo-icon-font\").click(function(){\n\tvar cla = $(this).children(\"i:first\").attr(\"class\").split(\" \");\n\tvar l = cla.length;\n\tparent.$(\"#css\").val(cla[l-1]);console.log(cla[l-1])\n\tparent.$(\"#cssImg\").removeClass();\n\tparent.$(\"#cssImg\").addClass(\"fa\");\n\tparent.$(\"#cssImg\").addClass(cla[l-1]);\n\tvar index = parent.layer.getFrameIndex(window.name); //获取窗口索引\n\tparent.layer.close(index);\n});\n\n</script>\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/service/serviceList.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<title>Insert title here</title>\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/bootstrap.min.css\">\n<link rel=\"stylesheet\" href=\"/css/treetable/jquery.treetable.css\" />\n<link rel=\"stylesheet\" href=\"/css/treetable/jquery.treetable.theme.default.css\" />\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/lib/layui/css/layui.css\">\n</head>\n<body>\n    <div>\n        <div class=\"col-xs-12 col-sm-12 col-md-12 col-lg-12\">\n                <header style=\"height: 100%\">\n                    <div align=\"left\">\n\t                    <table style=\"width: 100%\">\n\t                   \t\t<tr>\n\t                   \t\t\t<td>\n\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t<td align=\"right\">\n\t                   \t\t\t\t<button class=\"layui-btn layui-btn-sm\" onclick=\"location.href='addService.html'\" permission=\"sys:menu:add\">\n                                      <i class=\"layui-icon\">&#xe608;</i> 添加\n                                    </button>\n\t                   \t\t\t</td>\n\t                   \t\t</tr> \n\t                    </table>\n\t\t\t\t\t</div>\n                </header>\n                \n                <div>\n                    <div class=\"widget-body no-padding\">\n                        <table id=\"dt-table\" class=\"table table-striped table-bordered table-hover\" style=\"width:100%\">\n                             <tr>\n                                 <th width=\"20%\">名称</th>\n                                 <th width=\"5%\">id</th>\n\t\t\t\t\t\t\t\t <th>href</th>     \n\t\t\t\t\t\t\t\t <th width=\"15%\">permission</th>     \n\t\t\t\t\t\t\t\t <th width=\"5%\">sort</th>     \n\t\t\t\t\t\t\t\t <th>操作</th>\n                             </tr>\n                        </table>\n                    </div>\n                </div>\n        </div>\n    </div>\n\n</body>\n</html>\n\n<script type=\"text/javascript\" src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n<script type=\"text/javascript\" src=\"/lib/layui/layui.js\"></script>\n<script type=\"text/javascript\" src=\"/js/my/permission.js\"></script>\n<script type=\"text/javascript\" src=\"/js/libs/jquery.treetable.js\"></script>\n<script type=\"text/javascript\">\nvar pers = checkPermission();\ninitMenuList();\n\nfunction initMenuList(){\n\t$.ajax({\n\t\ttype : 'get',\n\t\turl : '/services',\n\t\tcontentType: \"application/json; charset=utf-8\",  \n\t\tasync:false,\n\t\tsuccess : function(data) {\n\t\t\tvar length = data.length;\n\t\t\tfor(var i=0; i<length; i++){\n\t\t\t\tvar d = data[i];\n\t\t\t\tvar tr = \"<tr data-tt-id='\" + d['id'] + \"' data-tt-parent-id='\" + d['parentId'] + \"'>\";\n\t\t\t\tvar td1 = \"<td>\" + d['name'] +\"</td>\";\n\t\t\t\ttr += td1;\n\t\t\t\tvar id = \"<td>\" + d['id'] +\"</td>\";\n\t\t\t\ttr += id;\n\t\t\t\tvar href = \"\";\n\t\t\t\tif(d['href'] != null){\n\t\t\t\t\thref = d['href'];\n\t\t\t\t}\n\t\t\t\tvar td2 = \"<td>\" + href +\"</td>\";\n\t\t\t\ttr += td2;\n\t\t\t\t\n\t\t\t\tvar permission = d['permission'];\n\t\t\t\tif(permission == null){\n\t\t\t\t\tpermission = \"\";\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tvar td3 = \"<td>\" + permission +\"</td>\";\n\t\t\t\ttr += td3;\n\t\t\t\t\n\t\t\t\tvar sort = d['sort'];\n\t\t\t\tif(sort == 0){\n\t\t\t\t\tsort = \"\";\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tvar td4 = \"<td>\" + sort +\"</td>\";\n\t\t\t\ttr += td4;\n\t\t\t\t\n\t\t\t\tvar id = d['id'];\n\t\t\t\tvar href = \"updateService.html?id=\" + id;\n\t\t\t\tvar edit = buttonEdit(href, \"sys:menu:add\", pers);\n\t\t\t\tvar del = buttonDel(id, \"sys:menu:del\", pers);\n                tr += \"<td>\"+edit + del+\"</td>\";\n\t\t\t\ttr += \"</tr>\"\n\t\t\t\t$(\"#dt-table\").append(tr);\n\t\t\t}\n\t\t}\n\t});\n}\n\nlayui.use('layer', function(){\n    var layer = layui.layer;\n});\n\nfunction del(id){\n\tlayer.confirm('确定要删除吗？', {\n        btn : [ '确定', '取消' ]\n    }, function() {\n        $.ajax({\n            type : 'delete',\n            url : '/services/' + id,\n            success : function(data) {\n                location.reload();\n            }\n        });\n    });\n}\n\n\tvar option = {\n\t\texpandable : true,\n\t\tclickableNodeNames : true,\n\t\tonNodeExpand : function() {\n\t\t\tvar d = this;\n\t\t\tconsole.log(d['id']);\n\t\t\tconsole.log(d['parentId']);\n\t\t},\n\t\tonNodeCollapse : function() {\n\t\t\tvar d = this;\n\t\t\tconsole.log(d['id'] + \"Collapse\");\n\t\t\tconsole.log(d['parentId'] + \"Collapse\");\n\t\t}\n\n\t};\n\n\t$(\"#dt-table\").treetable(option);\n</script>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/service/updateService.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/bootstrap.min.css\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/font-awesome/css/font-awesome.css\">\n</head>\n<body>\n<div class=\"col-xs-12 col-sm-12 col-md-12 col-lg-12\">\n\t<form class=\"form-horizontal\" onsubmit=\"return false\" id=\"form\">\n\t\t<fieldset>\n\t\t\t<input type=\"hidden\" id=\"id\" name=\"id\">\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">上级菜单</label>\n\t\t\t\t<div class=\"col-md-10\">\n                    <select id=\"parentId\" name=\"parentId\" class=\"form-control input-sm\"></select>\n                </div>\n\t\t\t</div>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">名称</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<input class=\"form-control\" placeholder=\"名称\" type=\"text\" name=\"name\" id=\"name\"\n\t\t\t\t\t\tdata-bv-notempty=\"true\"\n\t\t\t\t\t\tdata-bv-notempty-message=\"名称 不能为空\">\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">样式</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<button onclick=\"selectCss()\" class=\"btn btn-primary\">选择</button>\n\t\t\t\t\t<input type=\"hidden\"  name=\"css\" id=\"css\" /><i id=\"cssImg\" class=\"fa\"></i>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">链接</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<input class=\"form-control\" placeholder=\"链接\" name=\"href\" id=\"href\"/>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">类型</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<select name=\"type\" class=\"form-control input-sm\" id=\"type\">\n\t\t\t\t\t   <option value=\"1\">菜单</option>\n\t\t\t\t\t   <option value=\"2\">按钮</option>\n\t\t\t\t\t</select>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">权限</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<input class=\"form-control\" placeholder=\"权限\" name=\"permission\" id=\"permission\" />\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"form-group\">\n                <label class=\"col-md-2 control-label\">排序</label>\n                <div class=\"col-md-10\">\n                    <input class=\"form-control\" placeholder=\"排序\" name=\"sort\" id=\"sort\" type=\"number\" \n                        data-bv-notempty=\"true\"\n                        data-bv-notempty-message=\"排序 不能为空\">\n                </div>\n            </div>\n\n\t\t\t<div class=\"form-actions\">\n\t\t\t\t<div class=\"row\" align=\"center\">\n\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t<button class=\"btn btn-primary\" onclick=\"location.href='serviceList.html'\">返回</button>\n\t\t\t\t\t\t<button class=\"btn btn-primary\" type=\"submit\" onclick=\"update()\">\n\t\t\t\t\t\t\t<i class=\"fa fa-save\"></i> 保存\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t</fieldset>\n\t</form>\n</div>\n\n\t<script type=\"text/javascript\" src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/plugin/bootstrapvalidator/bootstrapValidator.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/common.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/my/ztree-service.js\"></script>\n\t<script type=\"text/javascript\" src=\"/lib/layui/layui.js\"></script>\n\t<script type=\"text/javascript\">\n\tlayui.use('layer', function(){\n\t    var layer = layui.layer;\n\t});\n\n\tinitParentMenuSelect();\n\tinitData();\n\t\n\tfunction initData(){\n\t\tvar id = getUrlParam(\"id\");\n\t\tif(id != \"\"){\n\t\t\t$.ajax({\n\t\t\t\ttype : 'get',\n\t\t\t\turl : '/services/'+id,\n\t\t\t\tasync : false,\n\t\t\t\tsuccess : function(data) {\n\t\t\t\t\t$(\"#id\").val(data.id);\n\t\t\t\t\t$(\"#parentId\").val(data.parentId);\n\t\t\t\t\t$(\"#name\").val(data.name);\n\t\t\t\t\tvar css = data.css;\n\t\t\t\t\t$(\"#css\").val(css);\n\t\t\t\t\t$(\"#href\").val(data.href);\n\t\t\t\t\t$(\"#type\").val(data.type);\n\t\t\t\t\t$(\"#permission\").val(data.permission);\n\t\t\t\t\t$(\"#sort\").val(data.sort);\n\t\t\t\t\t\n\t\t\t\t\tif(css != \"\"){\n\t\t\t\t\t\t$(\"#cssImg\").addClass(\"fa\");\n\t\t\t\t\t\t$(\"#cssImg\").addClass(css);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t}\n\t}\n\t\n\tfunction selectCss(){\n\t\tlayer.open({\n\t\t\t  type: 2,\n\t\t\t  title: \"样式\",\n\t\t\t  area: ['800px', '400px'],\n\t\t\t  maxmin: true,\n\t\t\t  shadeClose: true,\n\t\t\t  content: ['icon.html']\n\t\t\t});\n\t}\n\t\n\t\tfunction update() {\n\t\t\t$('#form').bootstrapValidator();\n\t\t\tvar bootstrapValidator = $(\"#form\").data('bootstrapValidator');\n\t\t\tbootstrapValidator.validate();\n\t\t    if(!bootstrapValidator.isValid()){\n\t\t\t   return;\n\t\t    }\n\t\t    \n\t\t    var formdata = $(\"#form\").serializeObject();\n\n\t\t\t$.ajax({\n\t\t\t\ttype : 'put',\n\t\t\t\turl : '/services/',\n\t\t\t\tcontentType: \"application/json; charset=utf-8\",  \n\t\t\t\tdata : JSON.stringify(formdata),\n\t\t\t\tsuccess : function(data) {\n\t\t\t\t\tlayer.msg(\"修改成功\", {shift: -1, time: 1000}, function(){\n                        location.href = \"serviceList.html\";\n                    });\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\t\n\t</script>\n</body>\n</html>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/user/addUser.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/bootstrap.min.css\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/lib/layui/css/layui.css\">\n</head>\n<body>\n<div class=\"col-xs-12 col-sm-12 col-md-12 col-lg-12\">\n\t<form class=\"form-horizontal\" onsubmit=\"return false\" id=\"form\">\n\t\t<fieldset>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">用户名</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<input class=\"form-control\" placeholder=\"用户名\" type=\"text\" name=\"username\"\n\t\t\t\t\t\tdata-bv-notempty=\"true\"\n\t\t\t\t\t\tdata-bv-notempty-message=\"用户名 不能为空\">\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">密码</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<input class=\"form-control\" placeholder=\"密码\" type=\"text\" value=\"88888888\" name=\"password\"\n\t\t\t\t\t\tdata-bv-notempty=\"true\"\n\t\t\t\t\t\tdata-bv-notempty-message=\"密码 不能为空\">\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">昵称</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<input class=\"form-control\" placeholder=\"昵称\" type=\"text\" name=\"nickname\">\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">手机号</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<input class=\"form-control\" placeholder=\"手机号\" type=\"text\" maxlength=\"11\" name=\"phone\">\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">电话</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<input class=\"form-control\" placeholder=\"电话\" type=\"text\" maxlength=\"20\" name=\"telephone\">\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">邮箱</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<input class=\"form-control\" placeholder=\"邮箱\" type=\"text\" maxlength=\"50\" name=\"email\">\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">生日</label>\n\t\t\t\t<div class=\"col-xs-2\">\n\t\t\t\t  <input type=\"text\" class=\"form-control\" placeholder=\"生日\" id=\"birthday\" name='birthday'>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">性别</label>\n\t\t\t\t<div class=\"col-md-10\" style=\"width: 100px\">\n\t\t\t\t\t<select class=\"form-control input-sm\" name=\"sex\" id=\"sex\">\n\t\t\t\t\t</select>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">角色</label>\n\t\t\t\t<div class=\"checkbox\" id=\"roles\">\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"form-actions\">\n\t\t\t\t<div class=\"row\" align=\"center\">\n\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t    <button class=\"btn btn-primary\" onclick=\"location.href='userList.html'\">返回</button>\n\t\t\t\t\t\t<button class=\"btn btn-primary\" type=\"submit\" onclick=\"add()\">\n\t\t\t\t\t\t\t<i class=\"fa fa-save\"></i> 保存\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t</fieldset>\n\t</form>\n</div>\n\t<script type=\"text/javascript\" src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/plugin/bootstrapvalidator/bootstrapValidator.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/common.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/my/roles/role.js\"></script>\n\t<script type=\"text/javascript\" src=\"/lib/layui/layui.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/dict.js\"></script>\n\t<script type=\"text/javascript\">\n\t\tlayui.use(['layer','laydate'], function(){\n\t\t    var layer = layui.layer;\n\t\t    var laydate = layui.laydate;\n\t\t    laydate.render({\n\t           elem: '#birthday'\n\t        });\n\t\t});\n\n\t\tshowDictSelect(\"sex\", \"sex\");\n\t\tinitRoles();\n\t\n\t\t$('#form').bootstrapValidator();\n\t\t\n\t\tfunction add() {\n\t\t\tvar bootstrapValidator = $(\"#form\").data('bootstrapValidator');\n\t\t\tbootstrapValidator.validate();\n\t\t    if(!bootstrapValidator.isValid()){\n\t\t\t   return;\n\t\t    }\n\t\t    \n\t\t    var formdata = $(\"#form\").serializeObject();\n\t\t    formdata.roleIds = getCheckedRoleIds();\n\n\t\t\t$.ajax({\n\t\t\t\ttype : 'post',\n\t\t\t\turl : '/users',\n\t\t\t\tcontentType: \"application/json; charset=utf-8\",  \n\t\t\t\tdata : JSON.stringify(formdata),\n\t\t\t\tsuccess : function(data) {\n\t\t\t\t\tlayer.msg(\"添加成功\", {shift: -1, time: 1000}, function(){\n                        location.href = \"userList.html\";\n                    });\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\t\n\t</script>\n</body>\n</html>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/user/changePassword.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/bootstrap.min.css\">\n</head>\n<body>\n<div class=\"col-xs-12 col-sm-12 col-md-12 col-lg-12\">\n\t<form class=\"form-horizontal\" onsubmit=\"return false\" id=\"form\">\n\t\t<fieldset>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">用户名</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<input class=\"form-control\" placeholder=\"用户名\" type=\"text\" id=\"username\" readonly=\"readonly\" name=\"username\"\n\t\t\t\t\t\tdata-bv-notempty=\"true\"\n\t\t\t\t\t\tdata-bv-notempty-message=\"用户名 不能为空\">\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">旧密码</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<input class=\"form-control\" placeholder=\"旧密码\" type=\"text\" name=\"oldPassword\"\n\t\t\t\t\t\tdata-bv-notempty=\"true\"\n\t\t\t\t\t\tdata-bv-notempty-message=\"旧密码 不能为空\">\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">新密码</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<input class=\"form-control\" placeholder=\"新密码\" type=\"text\" name=\"newPassword\" id=\"newPassword\"\n\t\t\t\t\t\tdata-bv-notempty=\"true\"\n\t\t\t\t\t\tdata-bv-notempty-message=\"新密码 不能为空\"\n\t\t\t\t\t\t\n\t\t\t\t\t\tdata-bv-identical=\"true\"\n\t\t\t\t\t\tdata-bv-identical-field=\"newPassword2\"\n\t\t\t\t\t\tdata-bv-identical-message=\"两次密码不一致\">\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">再次输入新密码</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<input class=\"form-control\" placeholder=\"再次输入新密码\" type=\"text\" name=\"newPassword2\" id=\"newPassword2\"\n\t\t\t\t\t\tdata-bv-notempty=\"true\"\n\t\t\t\t\t\tdata-bv-notempty-message=\"再次输入新密码\"\n\t\t\t\t\t\tdata-bv-identical=\"true\"\n\t\t\t\t\t\tdata-bv-identical-field=\"newPassword\"\n\t\t\t\t\t\tdata-bv-identical-message=\"两次密码不一致\">\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"form-actions\">\n\t\t\t\t<div class=\"row\" align=\"center\">\n\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t<button class=\"btn btn-primary\" type=\"submit\" onclick=\"update()\">\n\t\t\t\t\t\t\t<i class=\"fa fa-save\"></i> 保存\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t</fieldset>\n\t</form>\n</div>\n\t<script type=\"text/javascript\" src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n\t<script type=\"text/javascript\" src=\"/lib/layui/layui.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/plugin/bootstrapvalidator/bootstrapValidator.min.js\"></script>\n\t<script type=\"text/javascript\">\n\tlayui.use('layer', function(){\n\t    var layer = layui.layer;\n\t});\n\t\tfunction init(){\n\t\t\t$.ajax({\n\t\t\t\ttype : 'get',\n\t\t\t\turl : '/users/current',\n\t\t\t\tasync : false,\n\t\t\t\tdata : $(\"#form\").serialize(),\n\t\t\t\tsuccess : function(data) {\n\t\t\t\t\t$(\"#username\").val(data.username);\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t}\n\t\t\n\t\tinit();\n\t\n\t\tfunction update() {\n\t\t\t$('#form').bootstrapValidator();\n\t\t\tvar bootstrapValidator = $(\"#form\").data('bootstrapValidator');\n\t\t\tbootstrapValidator.validate();\n\t\t    if(!bootstrapValidator.isValid()){\n\t\t\t   return;\n\t\t    }\n\t\t    \n\t\t\t$.ajax({\n\t\t\t\ttype : 'put',\n\t\t\t\turl : '/users/'+$(\"#username\").val(),\n\t\t\t\tdata : $(\"#form\").serialize(),\n\t\t\t\tsuccess : function(data) {\n\t\t\t\t\tlayer.msg(\"修改成功\", {shift: -1, time: 1000}, function(){\n\t\t\t            deleteCurrentTab();\n\t\t\t        });\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\t\n\t</script>\n</body>\n</html>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/user/updateHeadImg.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/layui/css/layui.css\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/bootstrap.min.css\">\n</head>\n<body style=\"background-color: #FFFFFF;overflow:hidden\">\n\t<button type=\"button\" class=\"layui-btn\" id=\"test1\">\n\t  <i class=\"layui-icon\">&#xe67c;</i>上传头像\n\t</button>\n    <div id=\"headImgDiv\">\n    </div>\n\n\t<script type=\"text/javascript\" src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n\t<script type=\"text/javascript\" src=\"/lib/layui/layui.js\"></script>\n\t<script type=\"text/javascript\">\n\tvar pro = window.location.protocol;\n    var host = window.location.host;\n    var domain = pro + \"//\" + host;\n    \n\tinitData();\n\t\n\tfunction initData(){\n\t\t$.ajax({\n\t\t\ttype : 'get',\n\t\t\turl : '/users/current',\n\t\t\tasync : false,\n\t\t\tsuccess : function(data) {\n\t\t\t\tvar url = data.headImgUrl;\n\t\t\t\tif(url!=null && url!=\"\"){\n\t\t\t\t\tvar src = domain + \"/statics\" + url;\n                    var a = \"<a target='_blank' href='\" + src +\"'><img height='200' width='200' src='\" + src + \"'></img></a>\";\n\t\t\t\t\t$(\"#headImgDiv\").html(a);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\t\n\tlayui.use(['upload','layer'], function(){\n\t  var layer = layui.layer;\n\t  var upload = layui.upload;\n\t  upload.render({\n\t    elem: '#test1' //绑定元素\n\t    ,accept: 'images' //允许上传的文件类型\n\t    ,url: '/files' //上传接口\n\t    ,done: function(res, index, upload){\n\t    \tvar url = res.url;\n\t\t\t  $.ajax({\n\t\t            type : 'put',\n\t\t            url : '/users?headImgUrl='+url,\n\t\t            async : false,\n\t\t            success : function(data) {\n\t\t            \t layer.msg(\"上传成功\");\n\t\t                 var src = domain + \"/statics\" + url;\n\t\t                 var a = \"<a target='_blank' href='\" + src +\"'><img src='\" + src + \"'></img></a>\";\n\t\t                 $(\"#headImgDiv\").html(a);\n\t\t                 \n\t\t                 var img = parent.$(\".admin-header-user img\");\n\t\t     \t\t\t img.attr(\"src\", src);\n\t\t            }\n\t\t        });\n\t    }\n\t  });\n\t});\n\t\n\t</script>\n</body>\n</html>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/user/updateMyself.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/lib/layui/css/layui.css\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/bootstrap.min.css\">\n</head>\n<body>\n<div class=\"col-xs-12 col-sm-12 col-md-12 col-lg-12\">\n\t<form class=\"form-horizontal\" onsubmit=\"return false\" id=\"form\">\n\t\t<fieldset>\n\t\t\t<input type=\"hidden\" id=\"id\" name=\"id\">\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">用户名</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<input class=\"form-control\" placeholder=\"用户名\" type=\"text\" name=\"username\" id=\"username\" readonly=\"readonly\">\n\t\t\t\t</div>\n\t\t\t</div>\n            <div class=\"form-group\">\n                <label class=\"col-md-2 control-label\">昵称</label>\n                <div class=\"col-md-10\">\n                    <input class=\"form-control\" placeholder=\"昵称\" type=\"text\" name=\"nickname\" id=\"nickname\"\n\t\t\t\t\t\tdata-bv-notempty=\"true\"\n\t\t\t\t\t\tdata-bv-notempty-message=\"昵称 不能为空\">\n                </div>\n            </div>\n            <div class=\"form-group\">\n                <label class=\"col-md-2 control-label\">手机号</label>\n                <div class=\"col-md-10\">\n                    <input class=\"form-control\" placeholder=\"手机号\" type=\"text\" maxlength=\"11\" name=\"phone\" id=\"phone\">\n                </div>\n            </div>\n            <div class=\"form-group\">\n                <label class=\"col-md-2 control-label\">电话</label>\n                <div class=\"col-md-10\">\n                    <input class=\"form-control\" placeholder=\"电话\" type=\"text\" maxlength=\"20\" name=\"telephone\" id=\"telephone\">\n                </div>\n            </div>\n            <div class=\"form-group\">\n                <label class=\"col-md-2 control-label\">邮箱</label>\n                <div class=\"col-md-10\">\n                    <input class=\"form-control\" placeholder=\"邮箱\" type=\"text\" maxlength=\"50\" name=\"email\" id=\"email\">\n                </div>\n            </div>\n            <div class=\"form-group\">\n                <label class=\"col-md-2 control-label\">生日</label>\n                <div class=\"col-xs-2\">\n                  <input type=\"text\" class=\"form-control\" placeholder=\"生日\" id=\"birthday\" name='birthday'>\n                </div>\n            </div>\n            <div class=\"form-group\">\n                <label class=\"col-md-2 control-label\">性别</label>\n                <div class=\"col-md-10\" style=\"width: 100px\">\n                    <select class=\"form-control input-sm\" name=\"sex\" id=\"sex\">\n                    </select>\n                </div>\n            </div>\n\n\t\t\t<div class=\"form-actions\">\n\t\t\t\t<div class=\"row\" align=\"center\">\n\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t<button class=\"btn btn-primary\" type=\"submit\" onclick=\"update()\">\n\t\t\t\t\t\t\t<i class=\"fa fa-save\"></i> 保存\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t</fieldset>\n\t</form>\n</div>\n\n\t<script type=\"text/javascript\" src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n\t<script type=\"text/javascript\" src=\"/lib/layui/layui.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/plugin/bootstrapvalidator/bootstrapValidator.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/common.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/dict.js\"></script>\n\t<script type=\"text/javascript\">\n\tshowDictSelect(\"sex\", \"sex\");\n\tinitData();\n\t\n\tfunction initData(){\n\t\t$.ajax({\n\t\t\ttype : 'get',\n\t\t\turl : '/users/current',\n\t\t\tasync : false,\n\t\t\tsuccess : function(data) {\n\t\t\t\t$(\"#id\").val(data.id);\n\t\t\t\t$(\"#username\").val(data.username);\n\t\t\t\t$(\"#nickname\").val(data.nickname);\n\t\t\t\t$(\"#phone\").val(data.phone);\n\t\t\t\t$(\"#telephone\").val(data.telephone);\n\t\t\t\t$(\"#email\").val(data.email);\n\t\t\t\t$(\"#birthday\").val(data.birthday);\n\t\t\t\t$(\"#sex\").val(data.sex);\n\t\t\t}\n\t\t});\n\t}\n\t\n\t\t$('#form').bootstrapValidator();\n\t\t\n\t\tlayui.use(['layer','laydate'], function(){\n            var layer = layui.layer;\n            var laydate = layui.laydate;\n            laydate.render({\n              elem: '#birthday'\n            });\n        });\n\t\t\n\t\tfunction update() {\n\t\t\tvar bootstrapValidator = $(\"#form\").data('bootstrapValidator');\n\t\t\tbootstrapValidator.validate();\n\t\t    if(!bootstrapValidator.isValid()){\n\t\t\t   return;\n\t\t    }\n\t\t    \n\t\t    var formdata = $(\"#form\").serializeObject();\n\n\t\t\t$.ajax({\n\t\t\t\ttype : 'put',\n\t\t\t\turl : '/users',\n\t\t\t\tcontentType: \"application/json; charset=utf-8\",  \n\t\t\t\tdata : JSON.stringify(formdata),\n\t\t\t\tsuccess : function(data) {\n\t\t\t\t\tlayer.msg(\"修改成功\", {shift: -1, time: 1000}, function(){\n                        deleteCurrentTab();\n                    });\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\t\n\t</script>\n</body>\n</html>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/user/updateUser.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/bootstrap.min.css\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/lib/layui/css/layui.css\">\n</head>\n<body>\n<div class=\"col-xs-12 col-sm-12 col-md-12 col-lg-12\">\n\t<form class=\"form-horizontal\" onsubmit=\"return false\" id=\"form\">\n\t\t<fieldset>\n\t\t\t<input type=\"hidden\" id=\"id\" name=\"id\">\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">用户名</label>\n\t\t\t\t<div class=\"col-md-10\">\n\t\t\t\t\t<input class=\"form-control\" placeholder=\"用户名\" type=\"text\" name=\"username\" id=\"username\" readonly=\"readonly\">\n\t\t\t\t</div>\n\t\t\t</div>\n            <div class=\"form-group\">\n                <label class=\"col-md-2 control-label\">昵称</label>\n                <div class=\"col-md-10\">\n                    <input class=\"form-control\" placeholder=\"昵称\" type=\"text\" name=\"nickname\" id=\"nickname\">\n                </div>\n            </div>\n            <div class=\"form-group\">\n                <label class=\"col-md-2 control-label\">手机号</label>\n                <div class=\"col-md-10\">\n                    <input class=\"form-control\" placeholder=\"手机号\" type=\"text\" maxlength=\"11\" name=\"phone\" id=\"phone\">\n                </div>\n            </div>\n            <div class=\"form-group\">\n                <label class=\"col-md-2 control-label\">电话</label>\n                <div class=\"col-md-10\">\n                    <input class=\"form-control\" placeholder=\"电话\" type=\"text\" maxlength=\"20\" name=\"telephone\" id=\"telephone\">\n                </div>\n            </div>\n            <div class=\"form-group\">\n                <label class=\"col-md-2 control-label\">邮箱</label>\n                <div class=\"col-md-10\">\n                    <input class=\"form-control\" placeholder=\"邮箱\" type=\"text\" maxlength=\"50\" name=\"email\" id=\"email\">\n                </div>\n            </div>\n            <div class=\"form-group\">\n                <label class=\"col-md-2 control-label\">生日</label>\n                <div class=\"col-xs-2\">\n                  <input type=\"text\" class=\"form-control\" placeholder=\"生日\" id=\"birthday\" name='birthday'>\n                </div>\n            </div>\n            <div class=\"form-group\">\n                <label class=\"col-md-2 control-label\">性别</label>\n                <div class=\"col-md-10\" style=\"width: 100px\">\n                    <select class=\"form-control input-sm\" name=\"sex\" id=\"sex\">\n                    </select>\n                </div>\n            </div>\n            <div class=\"form-group\">\n                <label class=\"col-md-2 control-label\">状态</label>\n                <div class=\"col-md-10\" style=\"width: 100px\">\n                    <select class=\"form-control input-sm\" name=\"status\" id=\"status\">\n                    </select>\n                </div>\n            </div>\n\t\t\t<div class=\"form-group\">\n\t\t\t\t<label class=\"col-md-2 control-label\">角色</label>\n\t\t\t\t<div class=\"checkbox\" id=\"roles\">\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"form-actions\">\n\t\t\t\t<div class=\"row\" align=\"center\">\n\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t<button class=\"btn btn-primary\" onclick=\"location.href='userList.html'\">返回</button>\n\t\t\t\t\t\t<button class=\"btn btn-primary\" type=\"submit\" onclick=\"update()\">\n\t\t\t\t\t\t\t<i class=\"fa fa-save\"></i> 保存\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t</fieldset>\n\t</form>\n</div>\t\n\t<script type=\"text/javascript\" src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/plugin/bootstrapvalidator/bootstrapValidator.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/common.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/my/roles/role.js\"></script>\n\t<script type=\"text/javascript\" src=\"/lib/layui/layui.js\"></script>\n\t<script type=\"text/javascript\" src=\"/js/dict.js\"></script>\n\t<script type=\"text/javascript\">\n\tlayui.use(['layer','laydate'], function(){\n\t    var layer = layui.layer;\n\t    var laydate = layui.laydate;\n\t    laydate.render({\n           elem: '#birthday'\n        });\n\t});\n\t\n\tshowDictSelect(\"sex\", \"sex\");\n\tshowDictSelect(\"status\", \"userStatus\");\n\t\n\tinitRoles();\n\t\n\tinitData();\n\t\n\tfunction initData(){\n\t\tvar id = getUrlParam(\"id\");\n\t\tif(id != \"\"){\n\t\t\t$.ajax({\n\t\t\t\ttype : 'get',\n\t\t\t\turl : '/users/'+id,\n\t\t\t\tasync : false,\n\t\t\t\tsuccess : function(data) {\n\t\t\t\t\t$(\"#id\").val(data.id);\n\t\t\t\t\t$(\"#username\").val(data.username);\n\t\t\t\t\t$(\"#nickname\").val(data.nickname);\n\t\t\t\t\t$(\"#phone\").val(data.phone);\n\t\t\t\t\t$(\"#telephone\").val(data.telephone);\n\t\t\t\t\t$(\"#email\").val(data.email);\n\t\t\t\t\t$(\"#birthday\").val(data.birthday);\n\t\t\t\t\t$(\"#sex\").val(data.sex);\n\t\t\t\t\t$(\"#status\").val(data.status);\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t\tinitRoleDatas(id);\n\t\t}\n\t}\n\t\n\t\t$('#form').bootstrapValidator();\n\t\t\n\t\tfunction update() {\n\t\t\tvar bootstrapValidator = $(\"#form\").data('bootstrapValidator');\n\t\t\tbootstrapValidator.validate();\n\t\t    if(!bootstrapValidator.isValid()){\n\t\t\t   return;\n\t\t    }\n\t\t    \n\t\t    var formdata = $(\"#form\").serializeObject();\n\t\t    formdata.roleIds = getCheckedRoleIds();\n\n\t\t\t$.ajax({\n\t\t\t\ttype : 'put',\n\t\t\t\turl : '/users',\n\t\t\t\tcontentType: \"application/json; charset=utf-8\",  \n\t\t\t\tdata : JSON.stringify(formdata),\n\t\t\t\tsuccess : function(data) {\n\t\t\t\t\tlayer.msg(\"修改成功\", {shift: -1, time: 1000}, function(){\n                        location.href = \"userList.html\";\n                    });\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\t\n\t</script>\n</body>\n</html>"
  },
  {
    "path": "open-layui-web/src/main/view/static/pages/user/userList.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<title>Insert title here</title>\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/bootstrap.min.css\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/css/dataTables.bootstrap.min.css\">\n<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/lib/layui/css/layui.css\">\n</head>\n<body>\n    <div>\n        <div class=\"col-xs-12 col-sm-12 col-md-12 col-lg-12\">\n                <header style=\"height: 100%\">\n                    <div align=\"left\">\n\t                    <table style=\"width: 100%\">\n\t                   \t\t<tr>\n\t                   \t\t\t<td>\n\t\t\t\t\t\t\t\t\t<form class=\"form-inline\" onsubmit=\"return false\">\n\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t用户名：\n\t\t\t\t\t\t\t\t\t\t\t<input id=\"username\" type=\"text\" class=\"form-control\" placeholder=\"用户名\">\n\t\t\t\t\t\t\t\t\t\t\t昵称：\n\t\t\t\t\t\t\t\t\t\t\t<input id=\"nickname\" type=\"text\" class=\"form-control\" placeholder=\"昵称\">\n\t\t\t\t\t\t\t\t\t\t\t状态：\n\t\t\t\t\t\t\t\t\t\t\t<select class=\"form-control input-sm\" id=\"status\">\n\t\t\t\t\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\t\t\t\t\t<button id=\"searchBt\" class=\"layui-btn layui-btn-sm\" permission=\"sys:user:query\"><i class=\"layui-icon\">&#xe615;</i>搜索</button>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</form>\n\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t<td align=\"right\">\n\t                   \t\t\t\t<button class=\"layui-btn layui-btn-sm\" onclick=\"location.href='addUser.html'\" permission=\"sys:user:add\">\n                                      <i class=\"layui-icon\">&#xe608;</i> 添加\n                                    </button>\n\t                   \t\t\t</td>\n\t                   \t\t</tr> \n\t                    </table>\n\t\t\t\t\t</div>\n                </header>\n                \n                <div>\n                    <div class=\"widget-body no-padding\">\n                        <table id=\"dt-table\" class=\"table table-striped table-bordered table-hover\" style=\"width:100%\">\n                            <thead>\n                                <tr>\n                                </tr>                       \n                                <tr>\n                                    <th>用户名</th>\n                                    <th>昵称</th>\n                                    <th>手机号</th>\n                                    <th>邮箱</th>\n\t\t\t\t\t\t\t\t\t<th>状态</th>     \n\t\t\t\t\t\t\t\t\t<th>操作</th>\n                                </tr>\n                            </thead>\n                            <tbody>\n                            </tbody>\n                        </table>\n                    </div>\n                </div>\n        </div>\n    </div>\n</body>\n</html>\n\n<script type=\"text/javascript\" src=\"/js/libs/jquery-2.1.1.min.js\"></script>\n<script type=\"text/javascript\" src=\"/js/jq.js\"></script>\n<script type=\"text/javascript\" src=\"/js/plugin/datatables/jquery.dataTables.min.js\"></script>\n<script type=\"text/javascript\" src=\"/js/plugin/datatables/dataTables.bootstrap.min.js\"></script>\n<script type=\"text/javascript\" src=\"/js/my/permission.js\"></script>\n<script type=\"text/javascript\" src=\"/lib/layui/layui.js\"></script>\n<script type=\"text/javascript\" src=\"/js/dict.js\"></script>\n<script type=\"text/javascript\">\nlayui.use([ 'layer' ], function() {\n\tvar layer = layui.layer;\n});\nvar userStatus = showDictSelect(\"status\", \"userStatus\", true);\n\nvar pers = checkPermission();\n\nvar example;\nfunction init(){\n\texample = \n    \t$('#dt-table').DataTable({\n        \t\"searching\": false,\n        \t\"processing\": false,\n        \t\"serverSide\" : true,\n        \t\"language\": {\n                \"url\": \"/js/plugin/datatables/Chinese.lang\"\n            },\n        \t\"ajax\": {\n        \t\t\"url\" : \"/users\",\n        \t\t\"type\":\"get\",\n        \t\t\"data\":function(d){\n    \t\t\t\td.username = $('#username').val();\n    \t\t\t\td.nickname = $('#nickname').val();\n    \t\t\t\td.status = $('#status').val();\n        \t\t},\n    \t\t\t\"error\":function(xhr, textStatus, errorThrown){\n    \t\t\t\tvar msg = xhr.responseText;\n    \t\t\t\tconsole.log(msg);\n    \t\t\t\tvar response = JSON.parse(msg);\n    \t\t\t\tvar code = response.code;\n    \t\t\t\tvar message = response.message;\n    \t\t\t\tif (code == 400) {\n    \t\t\t\t\tlayer.msg(message);\n    \t\t\t\t} else if (code == 401) {\n    \t\t\t\t\tlocalStorage.removeItem(\"token\");\n    \t\t\t\t\tlayer.msg(\"token过期，请先登录\", {shift: -1, time: 1000}, function(){\n    \t\t\t\t\t\tlocation.href = '/login.html';\n                        });\n    \t\t\t\t} else if (code == 403) {\n    \t\t\t\t\tconsole.log(\"未授权:\" + message);\n    \t\t\t\t\tlayer.msg('未授权');\n    \t\t\t\t} else if (code == 500) {\n    \t\t\t\t\tlayer.msg('系统错误：' + message);\n    \t\t\t\t}\n    \t\t\t}\n        \t},\n        \t\"dom\": \"<'dt-toolbar'r>t<'dt-toolbar-footer'<'col-sm-10 col-xs-12 hidden-xs'i><'col-xs-12 col-sm-10' p v>>\",\t\n            \"columns\": [\n                { \"data\": \"username\", \"defaultContent\": \"\"},\n                { \"data\": \"nickname\", \"defaultContent\": \"\"},\n                { \"data\": \"phone\", \"defaultContent\": \"\"},\n                { \"data\": \"email\", \"defaultContent\": \"\"},\n                { \n                \t\"data\": \"status\", \n                \t\"defaultContent\": \"\",\n                \t\"render\": function (data, type, row) {\n                    \treturn userStatus[data];\n                  \t}\n                },\n                { \n                \t\"data\": \"\", \n                \t\"defaultContent\": \"\",\n                \t\"orderable\":false,\n                \t\"render\": function (data, type, row) {\n                \t\tvar id = row['id'];\n                \t\tvar href = \"updateUser.html?id=\" + id;\n                \t\tvar edit = buttonEdit(href, \"sys:user:add\", pers);\n                        return edit;\n                  }\n                },\n                \n            ],\n            \"order\": [[ 0, \"desc\" ],[1, \"asc\"]]\n        } );\n}\n\n$(\"#searchBt\").click(function(){\n\texample.ajax.reload();\n});\n\ninit();\n</script>"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/css/index1.css",
    "content": "@charset \"utf-8\";\n/*\n* Copyright https://github.com/larryqin/larrycms\n*/\n/* 头部 */\n.header{height: 65px; border-bottom: 1px solid #404553;  background-color: #393D49; color: #fff;}\n.logo{display:block;position: absolute; left: 10px; top: 10px;}\n.logo img{width: 150px; height: 35px;}\n\n.header .layui-nav{position: absolute; right: 0; top: 0; padding: 0; background: none;}\n.header .layui-nav .layui-nav-item{margin: 0 20px; line-height: 66px;}\n\n.body{display: block;}\n.layui-layout-admin .header-demo{border-bottom-color: #1AA094;}\n.header-demo .logo{font-family: \"Helvetica Neue\",Helvetica,Arial,sans-serif;left: 10px;top: 8px;font-size: 24px;font-weight:bold; color:#fff;height: 50px;line-height: 50px;text-align: center;}\n.header-demo .layui-nav{top: 0;}\n.header-demo .layui-nav .layui-nav-item{margin: 0 10px; line-height: 70px;}\n.header-demo .layui-nav .layui-nav-item a{\n\tcolor: #999;\n\tpadding-left: 15px;\n\tpadding-right: 15px;\n\tposition: relative;\n}\n.header-demo .layui-nav .layui-nav-item:hover{\n\tborder-bottom-color: #000;\n}\n.header-demo .layui-nav .layui-this{background-color: #000;/* #5FB878 */}\n.header-demo .layui-nav .layui-nav-item a:hover, \n.header-demo .layui-nav .layui-this a{color: #ffffff;}\n.header-demo .layui-nav .layui-nav-item span.layui-nav-more{\n\ttop: 32px;\n}\n.header-demo .layui-nav .layui-nav-item span.layui-nav-mored{\n\ttop: 26px;\n}\n.header-demo .layui-nav .layui-this:after, \n.header-demo .layui-nav-bar{background-color: #393D49;}\n.header-demo .layui-nav .layui-this a{padding: 0 15px;}\n.header{\n\tbackground: #393D49;\n}\n.admin-logo-box{\n\twidth: 185px; height: 70px; position: relative;\n}\n.larry-side-menu{\n\tposition: absolute; \n\tcursor: pointer;\n    z-index: 19940201;\n    left: 200px;\n    color: white;\n    text-align: center;\n    width: 30px;\n    height: 30px;\n    background-color: #1AA094;\n    line-height: 30px;\n    top: 23%;\n}\n.larry-side-menu:hover{\n\tbackground-color: #5FB878;\n}\n/* 头部左侧 */\n.layui-larry-menu{\n\twidth: auto;\n\theight: 70px;\n\tposition: absolute;\n\tleft: 245px;\n\ttop: 0px;\n}\n.layui-larry-menu ul.layui-nav{\n\theight: 70px;\n\tposition:static;\n}\n.layui-larry-menu ul.layui-nav li.layui-nav-item{\n\tmargin: 0px;\n}\n.layui-larry-menu ul.layui-nav li.layui-nav-item a{\n\tcolor: #F5F5F5;\n\tfont-size: 14px;\n\tline-height: 60px;\n\tpadding-left: 10px;\n\tpadding-right: 10px;\n}\n.layui-larry-menu ul.layui-nav li.layui-nav-item a i{\n\tpadding-right: 5px;\n\tline-height: 70px;\n}\n.layui-larry-menu ul.layui-nav .layui-this{\n\tbackground: #2B2E37;\n\n}\n.layui-larry-menu ul.layui-nav .layui-this::after{\n\t/* background: #2B2E37; */\n\tbackground: #1AA094;\n}\n/* 头部右侧 */\n.header ul.larry-header-item{\n\theight: 70px;\n}\n.header ul.larry-header-item li.layui-nav-item{\n\tmargin-left: 0px;\n\tmargin-right: 0px;\n}\n.header ul.larry-header-item .userimg{\n\twidth: 40px;\n\tborder-radius: 50%;\n\t-webkit-border-radius: 50%;\n\t-moz-border-radius: 50%;\n\tborder: 4px solid #44576b;\n\tmargin-top: -6px;\n}\n.header ul.larry-header-item .layui-this{\n\tbackground: #393D49;\n\tborder-bottom: none;\n}\n.header ul.larry-header-item .layui-this::after{\n\tbackground: transparent;\n}\n/* ======================= */\n/* 左侧区域 */\n.layui-side-bg{\n\tbackground: #393D49;\n}\n.layui-larry-side{\n\tpadding: 0px;\n}\n.layui-larry-side .user-photo{\n\twidth: 200px;\n\theight: 120px;\n\tpadding-top: 15px;\n\tpadding-bottom: 5px;\n}\n.layui-larry-side  .user-photo a.img{\n    display: block;\n    width: 76px;\n    height: 76px;\n    margin: 0 auto;\n    margin-bottom: 15px;\n}\n.layui-larry-side  .user-photo a.img img{\n\tdisplay: block;\n\tborder: none;\n\twidth: 100%;\n\theight: 100%;\n\tborder-radius: 50%;\n\t-webkit-border-radius: 50%;\n\t-moz-border-radius: 50%;\n\tborder: 4px solid #44576b;\n}\n.layui-larry-side  .user-photo p{\n\tdisplay: block;\n\twidth: 100%;\n\theight: 25px;\n\tcolor: #ffffff;\n\ttext-align: center;\n\tfont-size: 12px;\n\twhite-space: nowrap;\n\tline-height: 25px;\n\toverflow: hidden;\n}\n.layui-nav-tree li.layui-nav-item a{\n\tpadding-right: 10px;\n}\n.layui-nav-tree li.layui-nav-item a i{\n\tpadding-right: 3px;\n}\n.layui-nav-tree li.layui-nav-item .layui-nav-child dd a{\n\tpadding-left: 40px !important;\n\tpadding-right: 0px;\n}\n.layui-nav-tree li.layui-nav-item .layui-nav-child dd a i{\n\tpadding-right: 3px;\n}\n/* 右侧主体区域 */\n.layui-body{\n\tbottom: 0;\n\tborder-left: solid 2px #1AA094;\n}\n.layui-tab-content{\n\tmin-height: 150px; \n\t/* padding: 5px 0 0 0; */\n}\n /* tab选项卡 */\n.layui-body{\n \tpadding-left: 0px;\n }\n .layui-layout-admin .layui-body {\n    top: 58px;\n}\n\n.larry-tab-menu{\n\twidth: 200px;\n\theight: 40px;\n\tdisplay: none;\n}\n.larry-tab-box .layui-tab-title li em{\n   padding-left: 5px;\n   font-style: normal;\n}\n#admin-home i.layui-icon{\n\tdisplay: none;\n}\n.larry-tab-box{\n\tbox-shadow:none;\n}\n/* layui-tab-title start */\n.layui-tab-title .larry-tab-menu{\n\tdisplay: inline-block;\n\tfloat: right;border: 1px solid red;\n\tposition: relative;\n\tfont-size: 14px;\n}\n.larry-test{\n\t\n\theight: 40px;\n\tcolor: #000;\n\tposition: absolute;\n\ttop: 0px;\n\tleft: 0px;\n\tfont-size: 16px;\n\tcolor: #ffffff;\n}\n.refresh_iframe{\n\tdisplay: none;\n\tposition: absolute;\n\ttop: 10px;\n\tright: 1px;\n\theight: 41px;\n\tbackground: #33AB9F;\n\tcolor: #FFFFFF;\n}\n\n/* layui-tab-title end */\n.layui-tab-content{\n\tpadding: 0px;\n\tmargin: 0px;\n}\n.layui-tab-item{\n\tpadding: 10px 0 0 10px;\n\tmargin: 0px;\n\n}\n.layui-tab-content .layui-tab-item iframe{\n\twidth: 100%;\n\tborder: 0;\n\theight: 100%;\n}\n.larry-tab-box>.layui-tab-title{\n\tborder-bottom: 1px solid #1AA094;\n}\n.larry-tab-box .layui-tab-title cite{\n\tfont-style: normal;\n\tpadding-left: 5px;\n}\n.larry-tab-box>.layui-tab-title .layui-this{\n\tcolor: white;\n    background-color: #1AA094;\n}\n.larry-tab-box>.layui-tab-title .layui-this:after{\n\tborder-bottom: 0;\n}\n\n#time{\n\twidth:100%;\n\tcolor:#fff;\n\tfont-size:60px;\n\tmargin-bottom:80px;\n\tdisplay:inline-block;\n\ttext-align:center;\n}\n.form-group {\n    margin-bottom: 15px;\n}\n.col-lg-12{\n\tposition: relative;\n    min-height: 1px;\n    padding-right: 15px;\n    padding-left: 15px;\n}\n\n::selection{background:#FF6C60;color:#fff;}\n.form-control {\n    height: 30px;\n}\n@media (min-width: 1200px){\n\t.col-lg-12 {\n\t    width: 100%;\n\t    float: left;\n\t}\n}\n\nbody .layui-layout-admin .layui-larry-foot{\n    height: 30px;\n    padding-left:10px;\n    line-height: 30px;\n    background-color: #eee;\n    color: #666;\n    font-weight: 300;\n    border-left: 2px solid #1AA094;\n    z-index: 998;\n}\nbody .layui-layout-admin .layui-larry-foot a{\n    padding: 0 5px;\n\n}\n\n.layui-form-item .layui-input-inline {\n    float: left;\n    width: 350px;\n    margin-right: 10px;\n}\n\n.laber-account{\n\tpadding:3px 6px;margin-top:8px;width:auto;border-radius:5px;text-align: left;background-color:#009688; color: #fff;\n}\n\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/css/main.css",
    "content": "html { overflow-x:hidden; }\n.content-header {\n\tposition: relative;\n\tpadding: 0 0 3px 8px\n}\n\n.content-header>.breadcrumb {\n    position: relative;\n    top: 0;\n    right: 0;\n    float: none;\n    margin-top: 0px;\n    padding-left: 10px;\n    background: #ecf0f5;\n}\n\n.main-footer {\n    padding: 7px;\n    color: #444;\n    border-top: 1px solid #eee;\n}\n\n[v-cloak] {\n  display: none;\n}\n\n.grid-btn{\n\tmargin-bottom:12px;\n}\n.grid-btn .btn{\n\tmargin-right:10px;\n}\n.pointer{cursor: pointer;}\n\n.ml-10 { margin-left:0 !important; }\n@media (min-width: 768px) {\n\t.ml-10 { margin-left:10px !important; }\n\t.col-sm-10 {width: 70%;padding-left: 0px;}\n\t.col-sm-2 {width: 24%;}\n}\ntbody > tr > th {font-weight: normal; }\n.panel .table { margin:0 0; }\n.panel .pagination { margin:0; }\n.panel-default>.panel-heading {background-color: #f5f5f5;}\n.row{\n\tborder-top: 1px solid #ddd;\n\tmargin:0;\n\tpadding:20px 2px 0px 2px;\n}\n.col-xs-6{padding-left: 0px;padding-right: 0px;}\n.form-horizontal .form-group {margin-left:0px;margin-right:0px;}\n.form-horizontal{\n\twidth:550px;padding-top:20px;\n}"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/js/common.js",
    "content": "//jqGrid的配置信息\n$.jgrid.defaults.width = 1000;\n$.jgrid.defaults.responsive = true;\n$.jgrid.defaults.styleUI = 'Bootstrap';\n\n//工具集合Tools\nwindow.T = {};\n\n// 获取请求参数\n// 使用示例\n// location.href = http://localhost:8080/index.html?id=123\n// T.p('id') --> 123;\nvar url = function(name) {\n\tvar reg = new RegExp(\"(^|&)\"+ name +\"=([^&]*)(&|$)\");\n\tvar r = window.location.search.substr(1).match(reg);\n\tif(r!=null)return  unescape(r[2]); return null;\n};\nT.p = url;\n\n//全局配置\n$.ajaxSetup({\n\tdataType: \"json\",\n\tcontentType: \"application/json\",\n\tcache: false\n});\n\nfunction hasPermission(permission) {\n    if (window.parent.permissions.indexOf(permission) > -1) {\n        return true;\n    } else {\n        return false;\n    }\n}\n\n//重写alert\nwindow.alert = function(msg, callback){\n\tparent.layer.alert(msg, function(index){\n\t\tparent.layer.close(index);\n\t\tif(typeof(callback) === \"function\"){\n\t\t\tcallback(\"ok\");\n\t\t}\n\t});\n}\n\n//重写confirm式样框\nwindow.confirm = function(msg, callback){\n\tparent.layer.confirm(msg, {btn: ['确定','取消']},\n\tfunction(){//确定事件\n\t\tif(typeof(callback) === \"function\"){\n\t\t\tcallback(\"ok\");\n\t\t}\n\t});\n}\n\n//选择一条记录\nfunction getSelectedRow() {\n    var grid = $(\"#jqGrid\");\n    var rowKey = grid.getGridParam(\"selrow\");\n    if(!rowKey){\n    \talert(\"请选择一条记录\");\n    \treturn ;\n    }\n    \n    var selectedIDs = grid.getGridParam(\"selarrrow\");\n    if(selectedIDs.length > 1){\n    \talert(\"只能选择一条记录\");\n    \treturn ;\n    }\n    \n    return selectedIDs[0];\n}\n\n//选择多条记录\nfunction getSelectedRows() {\n    var grid = $(\"#jqGrid\");\n    var rowKey = grid.getGridParam(\"selrow\");\n    if(!rowKey){\n    \talert(\"请选择一条记录\");\n    \treturn ;\n    }\n    \n    return grid.getGridParam(\"selarrrow\");\n}"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/js/index.js",
    "content": "//生成菜单\nvar menuItem = Vue.extend({\n\tname: 'menu-item',\n\tprops:{item:{}},\n\ttemplate:[\n\t          '<li>',\n\t          '<a v-if=\"item.type === 0\" href=\"javascript:;\">',\n\t          '<i v-if=\"item.icon != null\" :class=\"item.icon\"></i>',\n\t          '<span>{{item.name}}</span>',\n\t          '<i class=\"fa fa-angle-left pull-right\"></i>',\n\t          '</a>',\n\t          '<ul v-if=\"item.type === 0\" class=\"treeview-menu\">',\n\t          '<menu-item :item=\"item\" v-for=\"item in item.list\"></menu-item>',\n\t          '</ul>',\n\t          '<a v-if=\"item.type === 1\" :href=\"\\'#\\'+item.url\"><i v-if=\"item.icon != null\" :class=\"item.icon\"></i><i v-else class=\"fa fa-circle-o\"></i> {{item.name}}</a>',\n\t          '</li>'\n\t].join('')\n});\n\n//iframe自适应\n$(window).on('resize', function() {\n\tvar $content = $('.content');\n\t$content.height($(this).height() - 120);\n\t$content.find('iframe').each(function() {\n\t\t$(this).height($content.height());\n\t});\n}).resize();\n\n//注册菜单组件\nVue.component('menuItem',menuItem);\n\nvar vm = new Vue({\n\tel:'#rrapp',\n\tdata:{\n\t\tuser:{},\n\t\tmenuList:{},\n\t\tmain:\"sys/main.html\",\n\t\tpassword:'',\n\t\tnewPassword:'',\n        navTitle:\"控制台\"\n\t},\n\tmethods: {\n\t\tgetMenuList: function (event) {\n\t\t\t$.getJSON(\"sys/menu/user?_\"+$.now(), function(r){\n\t\t\t\tvm.menuList = r.menuList;\n                window.permissions = r.permissions;\n\t\t\t});\n\t\t},\n\t\tgetUser: function(){\n\t\t\t$.getJSON(\"sys/user/info?_\"+$.now(), function(r){\n\t\t\t\tvm.user = r.user;\n\t\t\t});\n\t\t},\n\t\tupdatePassword: function(){\n\t\t\tlayer.open({\n\t\t\t\ttype: 1,\n\t\t\t\tskin: 'layui-layer-molv',\n\t\t\t\ttitle: \"修改密码\",\n\t\t\t\tarea: ['550px', '270px'],\n\t\t\t\tshadeClose: false,\n\t\t\t\tcontent: jQuery(\"#passwordLayer\"),\n\t\t\t\tbtn: ['修改','取消'],\n\t\t\t\tbtn1: function (index) {\n\t\t\t\t\tvar data = \"password=\"+vm.password+\"&newPassword=\"+vm.newPassword;\n\t\t\t\t\t$.ajax({\n\t\t\t\t\t\ttype: \"POST\",\n\t\t\t\t\t    url: \"sys/user/password\",\n\t\t\t\t\t    data: data,\n\t\t\t\t\t    dataType: \"json\",\n\t\t\t\t\t    success: function(result){\n\t\t\t\t\t\t\tif(result.code == 0){\n\t\t\t\t\t\t\t\tlayer.close(index);\n\t\t\t\t\t\t\t\tlayer.alert('修改成功', function(index){\n\t\t\t\t\t\t\t\t\tlocation.reload();\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\tlayer.alert(result.msg);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t            }\n\t\t\t});\n\t\t}\n\t},\n\tcreated: function(){\n\t\tthis.getMenuList();\n\t\tthis.getUser();\n\t},\n\tupdated: function(){\n\t\t//路由\n\t\tvar router = new Router();\n\t\trouterList(router, vm.menuList);\n\t\trouter.start();\n\t}\n});\n\n\n\nfunction routerList(router, menuList){\n\tfor(var key in menuList){\n\t\tvar menu = menuList[key];\n\t\tif(menu.type == 0){\n\t\t\trouterList(router, menu.list);\n\t\t}else if(menu.type == 1){\n\t\t\trouter.add('#'+menu.url, function() {\n\t\t\t\tvar url = window.location.hash;\n\t\t\t\t\n\t\t\t\t//替换iframe的url\n\t\t\t    vm.main = url.replace('#', '');\n\t\t\t    \n\t\t\t    //导航菜单展开\n\t\t\t    $(\".treeview-menu li\").removeClass(\"active\");\n\t\t\t    $(\"a[href='\"+url+\"']\").parents(\"li\").addClass(\"active\");\n\t\t\t    \n\t\t\t    vm.navTitle = $(\"a[href='\"+url+\"']\").text();\n\t\t\t});\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/js/navtab.js",
    "content": "layui.define(['element'], function(exports){\n   var  element = layui.element(),\n        $ = layui.jquery,\n\t\tlayer = parent.layer === undefined ? layui.layer : parent.layer,\n\t\tmodule_name = 'navtab',\n\tglobalTabIdIndex = 0,\n\tLarryTab = function(){\n          this.config ={\n          \t  elem: undefined,\n\t\t\t  closed: true \n          };\n\t};\n    var ELEM = {};\n    /**\n     * [参数设置 options]\n     */\n    LarryTab.prototype.set = function(options){\n          var _this = this;\n          $.extend(true, _this.config, options);\n          return _this;\n    };\n    /**\n     * [init 对象初始化]\n     * @return {[type]} [返回对象初始化结果]\n     */\n    LarryTab.prototype.init  = function(){\n         var _this = this;\n         var _config = _this.config;\n         if(typeof(_config.elem) !== 'string' && typeof(_config.elem) !== 'object') {\n\t\t       layer.alert('Tab选项卡错误提示: elem参数未定义或设置出错，具体设置格式请参考文档API.');\n\t     }\n\t     var $container;\n\t     if(typeof(_config.elem) === 'string') {\n\t\t     $container = $('' + _config.elem + '');\n\t\t     //console.log($container);\n\t     }\n\t     if(typeof(_config.elem) === 'object') {\n\t\t     $container = _config.elem;\n\t     }\n\t     if($container.length === 0) {\n\t\t     layer.alert('Tab选项卡错误提示:找不到elem参数配置的容器，请检查.');\n\t     }\n\t     var filter = $container.attr('lay-filter');\n\t     if(filter === undefined || filter === '') {\n\t\t      layer.alert('Tab选项卡错误提示:请为elem容器设置一个lay-filter过滤器');\n\t     }\n\t     _config.elem = $container;\n\t     ELEM.titleBox = $container.children('ul.layui-tab-title');\n\t     ELEM.contentBox = $container.children('div.layui-tab-content');\n\t     ELEM.tabFilter = filter;\n\t     return _this;\n    };\n    /**\n     * [exists 在layui-tab中检查对应layui-tab-title是否存在，如果存在则返回索引值，不存在返回-1]\n     * @param  {[type]} title [description]\n     * @return {[type]}       [description]\n     */\n    LarryTab.prototype.exists = function(title){\n        var _this = ELEM.titleBox === undefined ? this.init() : this,\n\t\t    tabIndex = -1;\n\t\tELEM.titleBox.find('li').each(function(i, e) {\n\t\t    var $em = $(this).children('em');\n\t\t    if($em.text() === title) {\n\t\t\t      tabIndex = i;\n\t\t    };\n\t    });\n\t    return tabIndex;\n    };\n    /**\n     * [tabAdd 增加选项卡，如果已存在则增加this样式]\n     * @param  {[type]} data [description]\n     * @return {[type]}      [description]\n     */\n    LarryTab.prototype.tabAdd = function(data){\n        var _this = this;\n\t    var tabIndex = _this.exists(data.title);\n\t    // 若不存在\n\t    if(tabIndex === -1){\n\t    \tglobalTabIdIndex++;\n\t    \tvar content = '<iframe src=\"' + data.href + '\" data-id=\"' + globalTabIdIndex + '\" class=\"larry-iframe\"></iframe>';\n\t\t    var title = '';\n\t\t    // 若icon有定义\n\t\t    if(data.icon !== undefined){\n                if(data.icon.indexOf('fa-') !== -1) {\n\t\t\t\t    title += '<i class=\"' + data.icon + '\"></i>';\n\t\t\t    } else {\n\t\t\t    \ttitle += '<i class=\"layui-icon \">' + data.icon + '</i>';\n\t\t\t    }\n\t\t    }\n\t\t    title += '<em>' + data.title + '</em>';\n\t\t    if(_this.config.closed) {\n\t\t\t    title += '<i class=\"layui-icon layui-unselect layui-tab-close\" data-id=\"' + globalTabIdIndex + '\">&#x1006;</i>';\n\t\t    }\n\t\t    //添加tab\n\t\t    element.tabAdd(ELEM.tabFilter, {\n\t\t\t    title: title,\n\t\t\t    content: content\n\t\t    });\n\t\t    //iframe 自适应\n\t\t    ELEM.contentBox.find('iframe[data-id=' + globalTabIdIndex + ']').each(function() {\n\t\t    \t$(this).height(ELEM.contentBox.height());\n\t\t    });\n\t\t    if(_this.config.closed) {\n\t\t\t//监听关闭事件\n\t\t\t    ELEM.titleBox.find('li').children('i.layui-tab-close[data-id=' + globalTabIdIndex + ']').on('click', function() {\n\t\t\t    \telement.tabDelete(ELEM.tabFilter, $(this).parent('li').index()).init();\n\t\t\t    });\n\t\t    };\n\t\t    //切换到当前打开的选项卡\n\t\t    element.tabChange(ELEM.tabFilter, ELEM.titleBox.find('li').length - 1);\n\t\t    }else {\n\t\t\t    element.tabChange(ELEM.tabFilter, tabIndex);\n\t\t    }\n        };\n    var navtab = new LarryTab();\n    exports(module_name, function(options) {\n\t\treturn navtab.set(options);\n\t});\n});"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/js/sys/config.js",
    "content": "$(function () {\n    $(\"#jqGrid\").jqGrid({\n        url: '../sys/config/list',\n        datatype: \"json\",\n        colModel: [\t\t\t\n\t\t\t{ label: 'ID', name: 'id', width: 30, key: true },\n\t\t\t{ label: '参数名', name: 'key', width: 60 },\n\t\t\t{ label: '参数值', name: 'value', width: 100 },\n\t\t\t{ label: '备注', name: 'remark', width: 80 }\n        ],\n\t\tviewrecords: true,\n        height: 385,\n        rowNum: 10,\n\t\trowList : [10,30,50],\n        rownumbers: true, \n        rownumWidth: 25, \n        autowidth:true,\n        multiselect: true,\n        pager: \"#jqGridPager\",\n        jsonReader : {\n            root: \"page.list\",\n            page: \"page.currPage\",\n            total: \"page.totalPage\",\n            records: \"page.totalCount\"\n        },\n        prmNames : {\n            page:\"page\", \n            rows:\"limit\", \n            order: \"order\"\n        },\n        gridComplete:function(){\n        \t//隐藏grid底部滚动条\n        \t$(\"#jqGrid\").closest(\".ui-jqgrid-bdiv\").css({ \"overflow-x\" : \"hidden\" }); \n        }\n    });\n});\n\nvar vm = new Vue({\n\tel:'#rrapp',\n\tdata:{\n\t\tq:{\n\t\t\tkey: null\n\t\t},\n\t\tshowList: true,\n\t\ttitle: null,\n\t\tconfig: {}\n\t},\n\tmethods: {\n\t\tquery: function () {\n\t\t\tvm.reload();\n\t\t},\n\t\tadd: function(){\n\t\t\tvm.showList = false;\n\t\t\tvm.title = \"新增\";\n\t\t\tvm.config = {};\n\t\t},\n\t\tupdate: function () {\n\t\t\tvar id = getSelectedRow();\n\t\t\tif(id == null){\n\t\t\t\treturn ;\n\t\t\t}\n\t\t\t\n\t\t\t$.get(\"../sys/config/info/\"+id, function(r){\n                vm.showList = false;\n                vm.title = \"修改\";\n                vm.config = r.config;\n            });\n\t\t},\n\t\tdel: function (event) {\n\t\t\tvar ids = getSelectedRows();\n\t\t\tif(ids == null){\n\t\t\t\treturn ;\n\t\t\t}\n\t\t\t\n\t\t\tconfirm('确定要删除选中的记录？', function(){\n\t\t\t\t$.ajax({\n\t\t\t\t\ttype: \"POST\",\n\t\t\t\t    url: \"../sys/config/delete\",\n\t\t\t\t    data: JSON.stringify(ids),\n\t\t\t\t    success: function(r){\n\t\t\t\t\t\tif(r.code == 0){\n\t\t\t\t\t\t\talert('操作成功', function(index){\n\t\t\t\t\t\t\t\tvm.reload();\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\talert(r.msg);\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\tsaveOrUpdate: function (event) {\n\t\t\tvar url = vm.config.id == null ? \"../sys/config/save\" : \"../sys/config/update\";\n\t\t\t$.ajax({\n\t\t\t\ttype: \"POST\",\n\t\t\t    url: url,\n\t\t\t    data: JSON.stringify(vm.config),\n\t\t\t    success: function(r){\n\t\t\t    \tif(r.code === 0){\n\t\t\t\t\t\talert('操作成功', function(index){\n\t\t\t\t\t\t\tvm.reload();\n\t\t\t\t\t\t});\n\t\t\t\t\t}else{\n\t\t\t\t\t\talert(r.msg);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\t\treload: function (event) {\n\t\t\tvm.showList = true;\n\t\t\tvar page = $(\"#jqGrid\").jqGrid('getGridParam','page');\n\t\t\t$(\"#jqGrid\").jqGrid('setGridParam',{ \n                postData:{'key': vm.q.key},\n                page:page\n            }).trigger(\"reloadGrid\");\n\t\t}\n\t}\n});"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/js/sys/generator.js",
    "content": "$(function () {\n    $(\"#jqGrid\").jqGrid({\n        url: '../sys/generator/list',\n        datatype: \"json\",\n        colModel: [\t\t\t\n\t\t\t{ label: '表名', name: 'tableName', width: 100, key: true },\n\t\t\t{ label: 'Engine', name: 'engine', width: 70},\n\t\t\t{ label: '表备注', name: 'tableComment', width: 100 },\n\t\t\t{ label: '创建时间', name: 'createTime', width: 100 }\n        ],\n\t\tviewrecords: true,\n        height: 385,\n        rowNum: 10,\n\t\trowList : [10,30,50,100,200],\n        rownumbers: true, \n        rownumWidth: 25, \n        autowidth:true,\n        multiselect: true,\n        pager: \"#jqGridPager\",\n        jsonReader : {\n            root: \"page.list\",\n            page: \"page.currPage\",\n            total: \"page.totalPage\",\n            records: \"page.totalCount\"\n        },\n        prmNames : {\n            page:\"page\", \n            rows:\"limit\", \n            order: \"order\"\n        },\n        gridComplete:function(){\n        \t//隐藏grid底部滚动条\n        \t$(\"#jqGrid\").closest(\".ui-jqgrid-bdiv\").css({ \"overflow-x\" : \"hidden\" }); \n        }\n    });\n});\n\nvar vm = new Vue({\n\tel:'#rrapp',\n\tdata:{\n\t\tq:{\n\t\t\ttableName: null\n\t\t}\n\t},\n\tmethods: {\n\t\tquery: function () {\n\t\t\t$(\"#jqGrid\").jqGrid('setGridParam',{ \n                postData:{'tableName': vm.q.tableName},\n                page:1 \n            }).trigger(\"reloadGrid\");\n\t\t},\n\t\tgenerator: function() {\n\t\t\tvar tableNames = getSelectedRows();\n\t\t\tif(tableNames == null){\n\t\t\t\treturn ;\n\t\t\t}\n\t\t\tlocation.href = \"../sys/generator/code?tables=\" + JSON.stringify(tableNames);\n\t\t}\n\t}\n});\n\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/js/sys/log.js",
    "content": "$(function () {\n    $(\"#jqGrid\").jqGrid({\n        url: '../sys/log/list',\n        datatype: \"json\",\n        colModel: [\t\t\t\n\t\t\t{ label: 'id', name: 'id', width: 30, key: true },\n\t\t\t{ label: '用户名', name: 'username', width: 50 }, \t\t\t\n\t\t\t{ label: '用户操作', name: 'operation', width: 70 }, \t\t\t\n\t\t\t{ label: '请求方法', name: 'method', width: 150 }, \t\t\t\n\t\t\t{ label: '请求参数', name: 'params', width: 80 }, \t\t\t\n\t\t\t{ label: 'IP地址', name: 'ip', width: 70 }, \t\t\t\n\t\t\t{ label: '创建时间', name: 'createDate', width: 90 }\t\t\t\n        ],\n\t\tviewrecords: true,\n        height: 385,\n        rowNum: 10,\n\t\trowList : [10,30,50],\n        rownumbers: true, \n        rownumWidth: 25, \n        autowidth:true,\n        multiselect: false,\n        pager: \"#jqGridPager\",\n        jsonReader : {\n            root: \"page.list\",\n            page: \"page.currPage\",\n            total: \"page.totalPage\",\n            records: \"page.totalCount\"\n        },\n        prmNames : {\n            page:\"page\", \n            rows:\"limit\", \n            order: \"order\"\n        },\n        gridComplete:function(){\n        \t//隐藏grid底部滚动条\n        \t$(\"#jqGrid\").closest(\".ui-jqgrid-bdiv\").css({ \"overflow-x\" : \"hidden\" }); \n        }\n    });\n});\n\nvar vm = new Vue({\n\tel:'#rrapp',\n\tdata:{\n\t\tq:{\n\t\t\tkey: null\n\t\t},\n\t},\n\tmethods: {\n\t\tquery: function () {\n\t\t\tvm.reload();\n\t\t},\n\t\treload: function (event) {\n\t\t\tvar page = $(\"#jqGrid\").jqGrid('getGridParam','page');\n\t\t\t$(\"#jqGrid\").jqGrid('setGridParam',{ \n\t\t\t\tpostData:{'key': vm.q.key},\n                page:page\n            }).trigger(\"reloadGrid\");\n\t\t}\n\t}\n});"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/js/sys/menu.js",
    "content": "$(function () {\n    $(\"#jqGrid\").jqGrid({\n        url: '../sys/menu/list',\n        datatype: \"json\",\n        colModel: [\t\t\t\n\t\t\t{ label: '菜单ID', name: 'menuId', index: \"menu_id\", width: 40, key: true },\n\t\t\t{ label: '菜单名称', name: 'name', width: 60 },\n\t\t\t{ label: '上级菜单', name: 'parentName', sortable: false, width: 60 },\n\t\t\t{ label: '菜单图标', name: 'icon', sortable: false, width: 50, formatter: function(value, options, row){\n\t\t\t\treturn value == null ? '' : '<i class=\"'+value+' fa-lg\"></i>';\n\t\t\t}},\n\t\t\t{ label: '菜单URL', name: 'url', width: 100 },\n\t\t\t{ label: '授权标识', name: 'perms', width: 100 },\n\t\t\t{ label: '类型', name: 'type', width: 50, formatter: function(value, options, row){\n\t\t\t\tif(value === 0){\n\t\t\t\t\treturn '<span class=\"label label-primary\">目录</span>';\n\t\t\t\t}\n\t\t\t\tif(value === 1){\n\t\t\t\t\treturn '<span class=\"label label-success\">菜单</span>';\n\t\t\t\t}\n\t\t\t\tif(value === 2){\n\t\t\t\t\treturn '<span class=\"label label-warning\">按钮</span>';\n\t\t\t\t}\n\t\t\t}},\n\t\t\t{ label: '排序号', name: 'orderNum', index: \"order_num\", width: 50}\n        ],\n\t\tviewrecords: true,\n        height: 385,\n        rowNum: 10,\n\t\trowList : [10,30,50],\n        rownumbers: true, \n        rownumWidth: 25, \n        autowidth:true,\n        multiselect: true,\n        pager: \"#jqGridPager\",\n        jsonReader : {\n            root: \"page.list\",\n            page: \"page.currPage\",\n            total: \"page.totalPage\",\n            records: \"page.totalCount\"\n        },\n        prmNames : {\n            page:\"page\", \n            rows:\"limit\", \n            order: \"order\"\n        },\n        gridComplete:function(){\n        \t//隐藏grid底部滚动条\n        \t$(\"#jqGrid\").closest(\".ui-jqgrid-bdiv\").css({ \"overflow-x\" : \"hidden\" }); \n        }\n    });\n});\n\nvar setting = {\n\tdata: {\n\t\tsimpleData: {\n\t\t\tenable: true,\n\t\t\tidKey: \"menuId\",\n\t\t\tpIdKey: \"parentId\",\n\t\t\trootPId: -1\n\t\t},\n\t\tkey: {\n\t\t\turl:\"nourl\"\n\t\t}\n\t}\n};\nvar ztree;\n\nvar vm = new Vue({\n\tel:'#rrapp',\n\tdata:{\n\t\tshowList: true,\n\t\ttitle: null,\n\t\tmenu:{\n\t\t\tparentName:null,\n\t\t\tparentId:0,\n\t\t\ttype:1,\n\t\t\torderNum:0\n\t\t}\n\t},\n\tmethods: {\n\t\tgetMenu: function(menuId){\n\t\t\t//加载菜单树\n\t\t\t$.get(\"../sys/menu/select\", function(r){\n\t\t\t\tztree = $.fn.zTree.init($(\"#menuTree\"), setting, r.menuList);\n\t\t\t\tvar node = ztree.getNodeByParam(\"menuId\", vm.menu.parentId);\n\t\t\t\tztree.selectNode(node);\n\t\t\t\t\n\t\t\t\tvm.menu.parentName = node.name;\n\t\t\t})\n\t\t},\n\t\tadd: function(){\n\t\t\tvm.showList = false;\n\t\t\tvm.title = \"新增\";\n\t\t\tvm.menu = {parentName:null,parentId:0,type:1,orderNum:0};\n\t\t\tvm.getMenu();\n\t\t},\n\t\tupdate: function (event) {\n\t\t\tvar menuId = getSelectedRow();\n\t\t\tif(menuId == null){\n\t\t\t\treturn ;\n\t\t\t}\n\t\t\t\n\t\t\t$.get(\"../sys/menu/info/\"+menuId, function(r){\n\t\t\t\tvm.showList = false;\n                vm.title = \"修改\";\n                vm.menu = r.menu;\n                \n                vm.getMenu();\n            });\n\t\t},\n\t\tdel: function (event) {\n\t\t\tvar menuIds = getSelectedRows();\n\t\t\tif(menuIds == null){\n\t\t\t\treturn ;\n\t\t\t}\n\t\t\t\n\t\t\tconfirm('确定要删除选中的记录？', function(){\n\t\t\t\t$.ajax({\n\t\t\t\t\ttype: \"POST\",\n\t\t\t\t    url: \"../sys/menu/delete\",\n\t\t\t\t    data: JSON.stringify(menuIds),\n\t\t\t\t    success: function(r){\n\t\t\t\t    \tif(r.code === 0){\n\t\t\t\t\t\t\talert('操作成功', function(index){\n\t\t\t\t\t\t\t\tvm.reload();\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\talert(r.msg);\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\tsaveOrUpdate: function (event) {\n\t\t\tvar url = vm.menu.menuId == null ? \"../sys/menu/save\" : \"../sys/menu/update\";\n\t\t\t$.ajax({\n\t\t\t\ttype: \"POST\",\n\t\t\t    url: url,\n\t\t\t    data: JSON.stringify(vm.menu),\n\t\t\t    success: function(r){\n\t\t\t    \tif(r.code === 0){\n\t\t\t\t\t\talert('操作成功', function(index){\n\t\t\t\t\t\t\tvm.reload();\n\t\t\t\t\t\t});\n\t\t\t\t\t}else{\n\t\t\t\t\t\talert(r.msg);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\t\tmenuTree: function(){\n\t\t\tlayer.open({\n\t\t\t\ttype: 1,\n\t\t\t\toffset: '50px',\n\t\t\t\tskin: 'layui-layer-molv',\n\t\t\t\ttitle: \"选择菜单\",\n\t\t\t\tarea: ['300px', '450px'],\n\t\t\t\tshade: 0,\n\t\t\t\tshadeClose: false,\n\t\t\t\tcontent: jQuery(\"#menuLayer\"),\n\t\t\t\tbtn: ['确定', '取消'],\n\t\t\t\tbtn1: function (index) {\n\t\t\t\t\tvar node = ztree.getSelectedNodes();\n\t\t\t\t\t//选择上级菜单\n\t\t\t\t\tvm.menu.parentId = node[0].menuId;\n\t\t\t\t\tvm.menu.parentName = node[0].name;\n\t\t\t\t\t\n\t\t\t\t\tlayer.close(index);\n\t            }\n\t\t\t});\n\t\t},\n\t\treload: function (event) {\n\t\t\tvm.showList = true;\n\t\t\tvar page = $(\"#jqGrid\").jqGrid('getGridParam','page');\n\t\t\t$(\"#jqGrid\").jqGrid('setGridParam',{ \n                page:page\n            }).trigger(\"reloadGrid\");\n\t\t}\n\t}\n});"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/js/sys/role.js",
    "content": "$(function () {\n    $(\"#jqGrid\").jqGrid({\n        url: '../sys/role/list',\n        datatype: \"json\",\n        colModel: [\t\t\t\n\t\t\t{ label: '角色ID', name: 'roleId', index: \"role_id\", width: 45, key: true },\n\t\t\t{ label: '角色名称', name: 'roleName', index: \"role_name\", width: 75 },\n\t\t\t{ label: '备注', name: 'remark', width: 100 },\n\t\t\t{ label: '创建时间', name: 'createTime', index: \"create_time\", width: 80}\n        ],\n\t\tviewrecords: true,\n        height: 385,\n        rowNum: 10,\n\t\trowList : [10,30,50],\n        rownumbers: true, \n        rownumWidth: 25, \n        autowidth:true,\n        multiselect: true,\n        pager: \"#jqGridPager\",\n        jsonReader : {\n            root: \"page.list\",\n            page: \"page.currPage\",\n            total: \"page.totalPage\",\n            records: \"page.totalCount\"\n        },\n        prmNames : {\n            page:\"page\", \n            rows:\"limit\", \n            order: \"order\"\n        },\n        gridComplete:function(){\n        \t//隐藏grid底部滚动条\n        \t$(\"#jqGrid\").closest(\".ui-jqgrid-bdiv\").css({ \"overflow-x\" : \"hidden\" }); \n        }\n    });\n});\n\nvar setting = {\n\tdata: {\n\t\tsimpleData: {\n\t\t\tenable: true,\n\t\t\tidKey: \"menuId\",\n\t\t\tpIdKey: \"parentId\",\n\t\t\trootPId: -1\n\t\t},\n\t\tkey: {\n\t\t\turl:\"nourl\"\n\t\t}\n\t},\n\tcheck:{\n\t\tenable:true,\n\t\tnocheckInherit:true\n\t}\n};\nvar ztree;\n\t\nvar vm = new Vue({\n\tel:'#rrapp',\n\tdata:{\n\t\tq:{\n\t\t\troleName: null\n\t\t},\n\t\tshowList: true,\n\t\ttitle:null,\n\t\trole:{}\n\t},\n\tmethods: {\n\t\tquery: function () {\n\t\t\tvm.reload();\n\t\t},\n\t\tadd: function(){\n\t\t\tvm.showList = false;\n\t\t\tvm.title = \"新增\";\n\t\t\tvm.role = {};\n\t\t\tvm.getMenuTree(null);\n\t\t},\n\t\tupdate: function () {\n\t\t\tvar roleId = getSelectedRow();\n\t\t\tif(roleId == null){\n\t\t\t\treturn ;\n\t\t\t}\n\t\t\t\n\t\t\tvm.showList = false;\n            vm.title = \"修改\";\n            vm.getMenuTree(roleId);\n\t\t},\n\t\tdel: function (event) {\n\t\t\tvar roleIds = getSelectedRows();\n\t\t\tif(roleIds == null){\n\t\t\t\treturn ;\n\t\t\t}\n\t\t\t\n\t\t\tconfirm('确定要删除选中的记录？', function(){\n\t\t\t\t$.ajax({\n\t\t\t\t\ttype: \"POST\",\n\t\t\t\t    url: \"../sys/role/delete\",\n\t\t\t\t    data: JSON.stringify(roleIds),\n\t\t\t\t    success: function(r){\n\t\t\t\t\t\tif(r.code == 0){\n\t\t\t\t\t\t\talert('操作成功', function(index){\n\t\t\t\t\t\t\t\tvm.reload();\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\talert(r.msg);\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\tgetRole: function(roleId){\n            $.get(\"../sys/role/info/\"+roleId, function(r){\n            \tvm.role = r.role;\n                \n                //勾选角色所拥有的菜单\n    \t\t\tvar menuIds = vm.role.menuIdList;\n    \t\t\tfor(var i=0; i<menuIds.length; i++) {\n    \t\t\t\tvar node = ztree.getNodeByParam(\"menuId\", menuIds[i]);\n    \t\t\t\tztree.checkNode(node, true, false);\n    \t\t\t}\n    \t\t});\n\t\t},\n\t\tsaveOrUpdate: function (event) {\n\t\t\t//获取选择的菜单\n\t\t\tvar nodes = ztree.getCheckedNodes(true);\n\t\t\tvar menuIdList = new Array();\n\t\t\tfor(var i=0; i<nodes.length; i++) {\n\t\t\t\tmenuIdList.push(nodes[i].menuId);\n\t\t\t}\n\t\t\tvm.role.menuIdList = menuIdList;\n\t\t\t\n\t\t\tvar url = vm.role.roleId == null ? \"../sys/role/save\" : \"../sys/role/update\";\n\t\t\t$.ajax({\n\t\t\t\ttype: \"POST\",\n\t\t\t    url: url,\n\t\t\t    data: JSON.stringify(vm.role),\n\t\t\t    success: function(r){\n\t\t\t    \tif(r.code === 0){\n\t\t\t\t\t\talert('操作成功', function(index){\n\t\t\t\t\t\t\tvm.reload();\n\t\t\t\t\t\t});\n\t\t\t\t\t}else{\n\t\t\t\t\t\talert(r.msg);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\t\tgetMenuTree: function(roleId) {\n\t\t\t//加载菜单树\n\t\t\t$.get(\"../sys/menu/perms\", function(r){\n\t\t\t\tztree = $.fn.zTree.init($(\"#menuTree\"), setting, r.menuList);\n\t\t\t\t//展开所有节点\n\t\t\t\tztree.expandAll(true);\n\t\t\t\t\n\t\t\t\tif(roleId != null){\n\t\t\t\t\tvm.getRole(roleId);\n\t\t\t\t}\n\t\t\t});\n\t    },\n\t    reload: function (event) {\n\t    \tvm.showList = true;\n\t\t\tvar page = $(\"#jqGrid\").jqGrid('getGridParam','page');\n\t\t\t$(\"#jqGrid\").jqGrid('setGridParam',{ \n                postData:{'roleName': vm.q.roleName},\n                page:page\n            }).trigger(\"reloadGrid\");\n\t\t}\n\t}\n});"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/js/sys/schedule.js",
    "content": "$(function () {\n    $(\"#jqGrid\").jqGrid({\n        url: '../sys/schedule/list',\n        datatype: \"json\",\n        colModel: [\t\t\t\n\t\t\t{ label: '任务ID', name: 'jobId', width: 60, key: true },\n\t\t\t{ label: 'bean名称', name: 'beanName', width: 100 },\n\t\t\t{ label: '方法名称', name: 'methodName', width: 100 },\n\t\t\t{ label: '参数', name: 'params', width: 100 },\n\t\t\t{ label: 'cron表达式 ', name: 'cronExpression', width: 100 },\n\t\t\t{ label: '备注 ', name: 'remark', width: 100 },\n\t\t\t{ label: '状态', name: 'status', width: 60, formatter: function(value, options, row){\n\t\t\t\treturn value === 0 ? \n\t\t\t\t\t'<span class=\"label label-success\">正常</span>' : \n\t\t\t\t\t'<span class=\"label label-danger\">暂停</span>';\n\t\t\t}}\n        ],\n\t\tviewrecords: true,\n        height: 385,\n        rowNum: 10,\n\t\trowList : [10,30,50],\n        rownumbers: true, \n        rownumWidth: 25, \n        autowidth:true,\n        multiselect: true,\n        pager: \"#jqGridPager\",\n        jsonReader : {\n            root: \"page.list\",\n            page: \"page.currPage\",\n            total: \"page.totalPage\",\n            records: \"page.totalCount\"\n        },\n        prmNames : {\n            page:\"page\", \n            rows:\"limit\", \n            order: \"order\"\n        },\n        gridComplete:function(){\n        \t//隐藏grid底部滚动条\n        \t$(\"#jqGrid\").closest(\".ui-jqgrid-bdiv\").css({ \"overflow-x\" : \"hidden\" }); \n        }\n    });\n});\n\nvar vm = new Vue({\n\tel:'#rrapp',\n\tdata:{\n\t\tq:{\n\t\t\tbeanName: null\n\t\t},\n\t\tshowList: true,\n\t\ttitle: null,\n\t\tschedule: {}\n\t},\n\tmethods: {\n\t\tquery: function () {\n\t\t\tvm.reload();\n\t\t},\n\t\tadd: function(){\n\t\t\tvm.showList = false;\n\t\t\tvm.title = \"新增\";\n\t\t\tvm.schedule = {};\n\t\t},\n\t\tupdate: function () {\n\t\t\tvar jobId = getSelectedRow();\n\t\t\tif(jobId == null){\n\t\t\t\treturn ;\n\t\t\t}\n\t\t\t\n\t\t\t$.get(\"../sys/schedule/info/\"+jobId, function(r){\n\t\t\t\tvm.showList = false;\n                vm.title = \"修改\";\n\t\t\t\tvm.schedule = r.schedule;\n\t\t\t});\n\t\t},\n\t\tsaveOrUpdate: function (event) {\n\t\t\tvar url = vm.schedule.jobId == null ? \"../sys/schedule/save\" : \"../sys/schedule/update\";\n\t\t\t$.ajax({\n\t\t\t\ttype: \"POST\",\n\t\t\t    url: url,\n\t\t\t    data: JSON.stringify(vm.schedule),\n\t\t\t    success: function(r){\n\t\t\t    \tif(r.code === 0){\n\t\t\t\t\t\talert('操作成功', function(index){\n\t\t\t\t\t\t\tvm.reload();\n\t\t\t\t\t\t});\n\t\t\t\t\t}else{\n\t\t\t\t\t\talert(r.msg);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\t\tdel: function (event) {\n\t\t\tvar jobIds = getSelectedRows();\n\t\t\tif(jobIds == null){\n\t\t\t\treturn ;\n\t\t\t}\n\t\t\t\n\t\t\tconfirm('确定要删除选中的记录？', function(){\n\t\t\t\t$.ajax({\n\t\t\t\t\ttype: \"POST\",\n\t\t\t\t    url: \"../sys/schedule/delete\",\n\t\t\t\t    data: JSON.stringify(jobIds),\n\t\t\t\t    success: function(r){\n\t\t\t\t\t\tif(r.code == 0){\n\t\t\t\t\t\t\talert('操作成功', function(index){\n\t\t\t\t\t\t\t\tvm.reload();\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\talert(r.msg);\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\tpause: function (event) {\n\t\t\tvar jobIds = getSelectedRows();\n\t\t\tif(jobIds == null){\n\t\t\t\treturn ;\n\t\t\t}\n\t\t\t\n\t\t\tconfirm('确定要暂停选中的记录？', function(){\n\t\t\t\t$.ajax({\n\t\t\t\t\ttype: \"POST\",\n\t\t\t\t    url: \"../sys/schedule/pause\",\n\t\t\t\t    data: JSON.stringify(jobIds),\n\t\t\t\t    success: function(r){\n\t\t\t\t\t\tif(r.code == 0){\n\t\t\t\t\t\t\talert('操作成功', function(index){\n\t\t\t\t\t\t\t\tvm.reload();\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\talert(r.msg);\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\tresume: function (event) {\n\t\t\tvar jobIds = getSelectedRows();\n\t\t\tif(jobIds == null){\n\t\t\t\treturn ;\n\t\t\t}\n\t\t\t\n\t\t\tconfirm('确定要恢复选中的记录？', function(){\n\t\t\t\t$.ajax({\n\t\t\t\t\ttype: \"POST\",\n\t\t\t\t    url: \"../sys/schedule/resume\",\n\t\t\t\t    data: JSON.stringify(jobIds),\n\t\t\t\t    success: function(r){\n\t\t\t\t\t\tif(r.code == 0){\n\t\t\t\t\t\t\talert('操作成功', function(index){\n\t\t\t\t\t\t\t\tvm.reload();\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\talert(r.msg);\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\trunOnce: function (event) {\n\t\t\tvar jobIds = getSelectedRows();\n\t\t\tif(jobIds == null){\n\t\t\t\treturn ;\n\t\t\t}\n\t\t\t\n\t\t\tconfirm('确定要立即执行选中的记录？', function(){\n\t\t\t\t$.ajax({\n\t\t\t\t\ttype: \"POST\",\n\t\t\t\t    url: \"../sys/schedule/run\",\n\t\t\t\t    data: JSON.stringify(jobIds),\n\t\t\t\t    success: function(r){\n\t\t\t\t\t\tif(r.code == 0){\n\t\t\t\t\t\t\talert('操作成功', function(index){\n\t\t\t\t\t\t\t\tvm.reload();\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\talert(r.msg);\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\treload: function (event) {\n\t\t\tvm.showList = true;\n\t\t\tvar page = $(\"#jqGrid\").jqGrid('getGridParam','page');\n\t\t\t$(\"#jqGrid\").jqGrid('setGridParam',{ \n                postData:{'beanName': vm.q.beanName},\n                page:page \n            }).trigger(\"reloadGrid\");\n\t\t}\n\t}\n});"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/js/sys/schedule_log.js",
    "content": "$(function () {\n    $(\"#jqGrid\").jqGrid({\n        url: '../sys/scheduleLog/list',\n        datatype: \"json\",\n        colModel: [\t\t\t\n            { label: '日志ID', name: 'logId', width: 50, key: true },\n\t\t\t{ label: '任务ID', name: 'jobId', width: 50},\n\t\t\t{ label: 'bean名称', name: 'beanName', width: 60 },\n\t\t\t{ label: '方法名称', name: 'methodName', width: 60 },\n\t\t\t{ label: '参数', name: 'params', width: 60 },\n\t\t\t{ label: '状态', name: 'status', width: 50, formatter: function(value, options, row){\n\t\t\t\treturn value === 0 ? \n\t\t\t\t\t'<span class=\"label label-success\">成功</span>' :\n\t\t\t\t\t'<span class=\"label label-danger pointer\" onclick=\"vm.showError('+row.logId+')\">失败</span>';\n\t\t\t}},\n\t\t\t{ label: '耗时(单位：毫秒)', name: 'times', width: 70 },\n\t\t\t{ label: '执行时间', name: 'createTime', width: 80 }\n        ],\n\t\tviewrecords: true,\n        height: 385,\n        rowNum: 10,\n\t\trowList : [10,30,50,100,200],\n        rownumbers: true, \n        rownumWidth: 25, \n        autowidth:true,\n        multiselect: false,\n        pager: \"#jqGridPager\",\n        jsonReader : {\n            root: \"page.list\",\n            page: \"page.currPage\",\n            total: \"page.totalPage\",\n            records: \"page.totalCount\"\n        },\n        prmNames : {\n            page:\"page\", \n            rows:\"limit\", \n            order: \"order\"\n        },\n        gridComplete:function(){\n        \t//隐藏grid底部滚动条\n        \t$(\"#jqGrid\").closest(\".ui-jqgrid-bdiv\").css({ \"overflow-x\" : \"hidden\" }); \n        }\n    });\n});\n\nvar vm = new Vue({\n\tel:'#rrapp',\n\tdata:{\n\t\tq:{\n\t\t\tjobId: null\n\t\t}\n\t},\n\tmethods: {\n\t\tquery: function () {\n\t\t\t$(\"#jqGrid\").jqGrid('setGridParam',{ \n                postData:{'jobId': vm.q.jobId},\n                page:1 \n            }).trigger(\"reloadGrid\");\n\t\t},\n\t\tshowError: function(logId) {\n\t\t\t$.get(\"../sys/scheduleLog/info/\"+logId, function(r){\n\t\t\t\tparent.layer.open({\n\t\t\t\t  title:'失败信息',\n\t\t\t\t  closeBtn:0,\n\t\t\t\t  content: r.log.error\n\t\t\t\t});\n\t\t\t});\n\t\t},\n\t\tback: function (event) {\n\t\t\thistory.go(-1);\n\t\t}\n\t}\n});\n\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/js/sys/user.js",
    "content": "$(function () {\n    $(\"#jqGrid\").jqGrid({\n        url: '../sys/user/list',\n        datatype: \"json\",\n        colModel: [\t\t\t\n\t\t\t{ label: '用户ID', name: 'userId', index: \"user_id\", width: 45, key: true },\n\t\t\t{ label: '用户名', name: 'username', width: 75 },\n\t\t\t{ label: '邮箱', name: 'email', width: 90 },\n\t\t\t{ label: '手机号', name: 'mobile', width: 100 },\n\t\t\t{ label: '状态', name: 'status', width: 80, formatter: function(value, options, row){\n\t\t\t\treturn value === 0 ? \n\t\t\t\t\t'<span class=\"label label-danger\">禁用</span>' : \n\t\t\t\t\t'<span class=\"label label-success\">正常</span>';\n\t\t\t}},\n\t\t\t{ label: '创建时间', name: 'createTime', index: \"create_time\", width: 80}\n        ],\n\t\tviewrecords: true,\n        height: 385,\n        rowNum: 10,\n\t\trowList : [10,30,50],\n        rownumbers: true, \n        rownumWidth: 25, \n        autowidth:true,\n        multiselect: true,\n        pager: \"#jqGridPager\",\n        jsonReader : {\n            root: \"page.list\",\n            page: \"page.currPage\",\n            total: \"page.totalPage\",\n            records: \"page.totalCount\"\n        },\n        prmNames : {\n            page:\"page\", \n            rows:\"limit\", \n            order: \"order\"\n        },\n        gridComplete:function(){\n        \t//隐藏grid底部滚动条\n        \t$(\"#jqGrid\").closest(\".ui-jqgrid-bdiv\").css({ \"overflow-x\" : \"hidden\" }); \n        }\n    });\n});\n\nvar vm = new Vue({\n\tel:'#rrapp',\n\tdata:{\n\t\tq:{\n\t\t\tusername: null\n\t\t},\n\t\tshowList: true,\n\t\ttitle:null,\n\t\troleList:{},\n\t\tuser:{\n\t\t\tstatus:1,\n\t\t\troleIdList:[]\n\t\t}\n\t},\n\tmethods: {\n\t\tquery: function () {\n\t\t\tvm.reload();\n\t\t},\n\t\tadd: function(){\n\t\t\tvm.showList = false;\n\t\t\tvm.title = \"新增\";\n\t\t\tvm.roleList = {};\n\t\t\tvm.user = {status:1,roleIdList:[]};\n\t\t\t\n\t\t\t//获取角色信息\n\t\t\tthis.getRoleList();\n\t\t},\n\t\tupdate: function () {\n\t\t\tvar userId = getSelectedRow();\n\t\t\tif(userId == null){\n\t\t\t\treturn ;\n\t\t\t}\n\t\t\t\n\t\t\tvm.showList = false;\n            vm.title = \"修改\";\n\t\t\t\n\t\t\tvm.getUser(userId);\n\t\t\t//获取角色信息\n\t\t\tthis.getRoleList();\n\t\t},\n\t\tdel: function () {\n\t\t\tvar userIds = getSelectedRows();\n\t\t\tif(userIds == null){\n\t\t\t\treturn ;\n\t\t\t}\n\t\t\t\n\t\t\tconfirm('确定要删除选中的记录？', function(){\n\t\t\t\t$.ajax({\n\t\t\t\t\ttype: \"POST\",\n\t\t\t\t    url: \"../sys/user/delete\",\n\t\t\t\t    data: JSON.stringify(userIds),\n\t\t\t\t    success: function(r){\n\t\t\t\t\t\tif(r.code == 0){\n\t\t\t\t\t\t\talert('操作成功', function(index){\n                                vm.reload();\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\talert(r.msg);\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\tsaveOrUpdate: function (event) {\n\t\t\tvar url = vm.user.userId == null ? \"../sys/user/save\" : \"../sys/user/update\";\n\t\t\t$.ajax({\n\t\t\t\ttype: \"POST\",\n\t\t\t    url: url,\n\t\t\t    data: JSON.stringify(vm.user),\n\t\t\t    success: function(r){\n\t\t\t    \tif(r.code === 0){\n\t\t\t\t\t\talert('操作成功', function(index){\n\t\t\t\t\t\t\tvm.reload();\n\t\t\t\t\t\t});\n\t\t\t\t\t}else{\n\t\t\t\t\t\talert(r.msg);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\t\tgetUser: function(userId){\n\t\t\t$.get(\"../sys/user/info/\"+userId, function(r){\n\t\t\t\tvm.user = r.user;\n\t\t\t});\n\t\t},\n\t\tgetRoleList: function(){\n\t\t\t$.get(\"../sys/role/select\", function(r){\n\t\t\t\tvm.roleList = r.list;\n\t\t\t});\n\t\t},\n\t\treload: function (event) {\n\t\t\tvm.showList = true;\n\t\t\tvar page = $(\"#jqGrid\").jqGrid('getGridParam','page');\n\t\t\t$(\"#jqGrid\").jqGrid('setGridParam',{ \n                postData:{'username': vm.q.username},\n                page:page\n            }).trigger(\"reloadGrid\");\n\t\t}\n\t}\n});"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/libs/ajaxupload.js",
    "content": "/**\n * AJAX Upload ( http://valums.com/ajax-upload/ ) \n * Copyright (c) Andris Valums\n * Licensed under the MIT license ( http://valums.com/mit-license/ )\n * Thanks to Gary Haran, David Mark, Corey Burns and others for contributions \n */\n(function () {\n    /* global window */\n    /* jslint browser: true, devel: true, undef: true, nomen: true, bitwise: true, regexp: true, newcap: true, immed: true */\n    \n    /**\n     * Wrapper for FireBug's console.log\n     */\n    function log(){\n        if (typeof(console) != 'undefined' && typeof(console.log) == 'function'){            \n            Array.prototype.unshift.call(arguments, '[Ajax Upload]');\n            console.log( Array.prototype.join.call(arguments, ' '));\n        }\n    } \n\n    /**\n     * Attaches event to a dom element.\n     * @param {Element} el\n     * @param type event name\n     * @param fn callback This refers to the passed element\n     */\n    function addEvent(el, type, fn){\n        if (el.addEventListener) {\n            el.addEventListener(type, fn, false);\n        } else if (el.attachEvent) {\n            el.attachEvent('on' + type, function(){\n                fn.call(el);\n\t        });\n\t    } else {\n            throw new Error('not supported or DOM not loaded');\n        }\n    }   \n    \n    /**\n     * Attaches resize event to a window, limiting\n     * number of event fired. Fires only when encounteres\n     * delay of 100 after series of events.\n     * \n     * Some browsers fire event multiple times when resizing\n     * http://www.quirksmode.org/dom/events/resize.html\n     * \n     * @param fn callback This refers to the passed element\n     */\n    function addResizeEvent(fn){\n        var timeout;\n               \n\t    addEvent(window, 'resize', function(){\n            if (timeout){\n                clearTimeout(timeout);\n            }\n            timeout = setTimeout(fn, 100);                        \n        });\n    }    \n    \n    // Needs more testing, will be rewriten for next version        \n    // getOffset function copied from jQuery lib (http://jquery.com/)\n    if (document.documentElement.getBoundingClientRect){\n        // Get Offset using getBoundingClientRect\n        // http://ejohn.org/blog/getboundingclientrect-is-awesome/\n        var getOffset = function(el){\n            var box = el.getBoundingClientRect();\n            var doc = el.ownerDocument;\n            var body = doc.body;\n            var docElem = doc.documentElement; // for ie \n            var clientTop = docElem.clientTop || body.clientTop || 0;\n            var clientLeft = docElem.clientLeft || body.clientLeft || 0;\n             \n            // In Internet Explorer 7 getBoundingClientRect property is treated as physical,\n            // while others are logical. Make all logical, like in IE8.\t\n            var zoom = 1;            \n            if (body.getBoundingClientRect) {\n                var bound = body.getBoundingClientRect();\n                zoom = (bound.right - bound.left) / body.clientWidth;\n            }\n            \n            if (zoom > 1) {\n                clientTop = 0;\n                clientLeft = 0;\n            }\n            \n            var top = box.top / zoom + (window.pageYOffset || docElem && docElem.scrollTop / zoom || body.scrollTop / zoom) - clientTop, left = box.left / zoom + (window.pageXOffset || docElem && docElem.scrollLeft / zoom || body.scrollLeft / zoom) - clientLeft;\n            \n            return {\n                top: top,\n                left: left\n            };\n        };        \n    } else {\n        // Get offset adding all offsets \n        var getOffset = function(el){\n            var top = 0, left = 0;\n            do {\n                top += el.offsetTop || 0;\n                left += el.offsetLeft || 0;\n                el = el.offsetParent;\n            } while (el);\n            \n            return {\n                left: left,\n                top: top\n            };\n        };\n    }\n    \n    /**\n     * Returns left, top, right and bottom properties describing the border-box,\n     * in pixels, with the top-left relative to the body\n     * @param {Element} el\n     * @return {Object} Contains left, top, right,bottom\n     */\n    function getBox(el){\n        var left, right, top, bottom;\n        var offset = getOffset(el);\n        left = offset.left;\n        top = offset.top;\n        \n        right = left + el.offsetWidth;\n        bottom = top + el.offsetHeight;\n        \n        return {\n            left: left,\n            right: right,\n            top: top,\n            bottom: bottom\n        };\n    }\n    \n    /**\n     * Helper that takes object literal\n     * and add all properties to element.style\n     * @param {Element} el\n     * @param {Object} styles\n     */\n    function addStyles(el, styles){\n        for (var name in styles) {\n            if (styles.hasOwnProperty(name)) {\n                el.style[name] = styles[name];\n            }\n        }\n    }\n        \n    /**\n     * Function places an absolutely positioned\n     * element on top of the specified element\n     * copying position and dimentions.\n     * @param {Element} from\n     * @param {Element} to\n     */    \n    function copyLayout(from, to){\n\t    var box = getBox(from);\n        \n        addStyles(to, {\n\t        position: 'absolute',                    \n\t        left : box.left + 'px',\n\t        top : box.top + 'px',\n\t        width : from.offsetWidth + 'px',\n\t        height : from.offsetHeight + 'px'\n\t    });        \n    }\n\n    /**\n    * Creates and returns element from html chunk\n    * Uses innerHTML to create an element\n    */\n    var toElement = (function(){\n        var div = document.createElement('div');\n        return function(html){\n            div.innerHTML = html;\n            var el = div.firstChild;\n            return div.removeChild(el);\n        };\n    })();\n            \n    /**\n     * Function generates unique id\n     * @return unique id \n     */\n    var getUID = (function(){\n        var id = 0;\n        return function(){\n            return 'ValumsAjaxUpload' + id++;\n        };\n    })();        \n \n    /**\n     * Get file name from path\n     * @param {String} file path to file\n     * @return filename\n     */  \n    function fileFromPath(file){\n        return file.replace(/.*(\\/|\\\\)/, \"\");\n    }\n    \n    /**\n     * Get file extension lowercase\n     * @param {String} file name\n     * @return file extenstion\n     */    \n    function getExt(file){\n        return (-1 !== file.indexOf('.')) ? file.replace(/.*[.]/, '') : '';\n    }\n\n    function hasClass(el, name){        \n        var re = new RegExp('\\\\b' + name + '\\\\b');        \n        return re.test(el.className);\n    }    \n    function addClass(el, name){\n        if ( ! hasClass(el, name)){   \n            el.className += ' ' + name;\n        }\n    }    \n    function removeClass(el, name){\n        var re = new RegExp('\\\\b' + name + '\\\\b');                \n        el.className = el.className.replace(re, '');        \n    }\n    \n    function removeNode(el){\n        el.parentNode.removeChild(el);\n    }\n\n    /**\n     * Easy styling and uploading\n     * @constructor\n     * @param button An element you want convert to \n     * upload button. Tested dimentions up to 500x500px\n     * @param {Object} options See defaults below.\n     */\n    window.AjaxUpload = function(button, options){\n        this._settings = {\n            // Location of the server-side upload script\n            action: 'upload.php',\n            // File upload name\n            name: 'userfile',\n            // Additional data to send\n            data: {},\n            // Submit file as soon as it's selected\n            autoSubmit: true,\n            // The type of data that you're expecting back from the server.\n            // html and xml are detected automatically.\n            // Only useful when you are using json data as a response.\n            // Set to \"json\" in that case. \n            responseType: false,\n            // Class applied to button when mouse is hovered\n            hoverClass: 'hover',\n            // Class applied to button when AU is disabled\n            disabledClass: 'disabled',            \n            // When user selects a file, useful with autoSubmit disabled\n            // You can return false to cancel upload\t\t\t\n            onChange: function(file, extension){\n            },\n            // Callback to fire before file is uploaded\n            // You can return false to cancel upload\n            onSubmit: function(file, extension){\n            },\n            // Fired when file upload is completed\n            // WARNING! DO NOT USE \"FALSE\" STRING AS A RESPONSE!\n            onComplete: function(file, response){\n            }\n        };\n                        \n        // Merge the users options with our defaults\n        for (var i in options) {\n            if (options.hasOwnProperty(i)){\n                this._settings[i] = options[i];\n            }\n        }\n                \n        // button isn't necessary a dom element\n        if (button.jquery){\n            // jQuery object was passed\n            button = button[0];\n        } else if (typeof button == \"string\") {\n            if (/^#.*/.test(button)){\n                // If jQuery user passes #elementId don't break it\t\t\t\t\t\n                button = button.slice(1);                \n            }\n            \n            button = document.getElementById(button);\n        }\n        \n        if ( ! button || button.nodeType !== 1){\n            throw new Error(\"Please make sure that you're passing a valid element\"); \n        }\n                \n        if ( button.nodeName.toUpperCase() == 'A'){\n            // disable link                       \n            addEvent(button, 'click', function(e){\n                if (e && e.preventDefault){\n                    e.preventDefault();\n                } else if (window.event){\n                    window.event.returnValue = false;\n                }\n            });\n        }\n                    \n        // DOM element\n        this._button = button;        \n        // DOM element                 \n        this._input = null;\n        // If disabled clicking on button won't do anything\n        this._disabled = false;\n        \n        // if the button was disabled before refresh if will remain\n        // disabled in FireFox, let's fix it\n        this.enable();        \n        \n        this._rerouteClicks();\n    };\n    \n    // assigning methods to our class\n    AjaxUpload.prototype = {\n        setData: function(data){\n            this._settings.data = data;\n        },\n        disable: function(){            \n            addClass(this._button, this._settings.disabledClass);\n            this._disabled = true;\n            \n            var nodeName = this._button.nodeName.toUpperCase();            \n            if (nodeName == 'INPUT' || nodeName == 'BUTTON'){\n                this._button.setAttribute('disabled', 'disabled');\n            }            \n            \n            // hide input\n            if (this._input){\n                // We use visibility instead of display to fix problem with Safari 4\n                // The problem is that the value of input doesn't change if it \n                // has display none when user selects a file           \n                this._input.parentNode.style.visibility = 'hidden';\n            }\n        },\n        enable: function(){\n            removeClass(this._button, this._settings.disabledClass);\n            this._button.removeAttribute('disabled');\n            this._disabled = false;\n            \n        },\n        /**\n         * Creates invisible file input \n         * that will hover above the button\n         * <div><input type='file' /></div>\n         */\n        _createInput: function(){ \n            var self = this;\n                        \n            var input = document.createElement(\"input\");\n            input.setAttribute('type', 'file');\n            input.setAttribute('name', this._settings.name);\n            \n            addStyles(input, {\n                'position' : 'absolute',\n                // in Opera only 'browse' button\n                // is clickable and it is located at\n                // the right side of the input\n                'right' : 0,\n                'margin' : 0,\n                'padding' : 0,\n                'fontSize' : '480px',                \n                'cursor' : 'pointer'\n            });            \n\n            var div = document.createElement(\"div\");                        \n            addStyles(div, {\n                'display' : 'block',\n                'position' : 'absolute',\n                'overflow' : 'hidden',\n                'margin' : 0,\n                'padding' : 0,                \n                'opacity' : 0,\n                // Make sure browse button is in the right side\n                // in Internet Explorer\n                'direction' : 'ltr',\n                //Max zIndex supported by Opera 9.0-9.2\n                'zIndex': 2147483583\n            });\n            \n            // Make sure that element opacity exists.\n            // Otherwise use IE filter            \n            if ( div.style.opacity !== \"0\") {\n                if (typeof(div.filters) == 'undefined'){\n                    throw new Error('Opacity not supported by the browser');\n                }\n                div.style.filter = \"alpha(opacity=0)\";\n            }            \n            \n            addEvent(input, 'change', function(){\n                 \n                if ( ! input || input.value === ''){                \n                    return;                \n                }\n                            \n                // Get filename from input, required                \n                // as some browsers have path instead of it          \n                var file = fileFromPath(input.value);\n                                \n                if (false === self._settings.onChange.call(self, file, getExt(file))){\n                    self._clearInput();                \n                    return;\n                }\n                \n                // Submit form when value is changed\n                if (self._settings.autoSubmit) {\n                    self.submit();\n                }\n            });            \n\n            addEvent(input, 'mouseover', function(){\n                addClass(self._button, self._settings.hoverClass);\n            });\n            \n            addEvent(input, 'mouseout', function(){\n                removeClass(self._button, self._settings.hoverClass);\n                \n                // We use visibility instead of display to fix problem with Safari 4\n                // The problem is that the value of input doesn't change if it \n                // has display none when user selects a file           \n                input.parentNode.style.visibility = 'hidden';\n\n            });   \n                        \n\t        div.appendChild(input);\n            document.body.appendChild(div);\n              \n            this._input = input;\n        },\n        _clearInput : function(){\n            if (!this._input){\n                return;\n            }            \n                             \n            // this._input.value = ''; Doesn't work in IE6                               \n            removeNode(this._input.parentNode);\n            this._input = null;                                                                   \n            this._createInput();\n            \n            removeClass(this._button, this._settings.hoverClass);\n        },\n        /**\n         * Function makes sure that when user clicks upload button,\n         * the this._input is clicked instead\n         */\n        _rerouteClicks: function(){\n            var self = this;\n            \n            // IE will later display 'access denied' error\n            // if you use using self._input.click()\n            // other browsers just ignore click()\n\n            addEvent(self._button, 'mouseover', function(){\n                if (self._disabled){\n                    return;\n                }\n                                \n                if ( ! self._input){\n\t                self._createInput();\n                }\n                \n                var div = self._input.parentNode;                            \n                copyLayout(self._button, div);\n                div.style.visibility = 'visible';\n                                \n            });\n            \n            \n            // commented because we now hide input on mouseleave\n            /**\n             * When the window is resized the elements \n             * can be misaligned if button position depends\n             * on window size\n             */\n            //addResizeEvent(function(){\n            //    if (self._input){\n            //        copyLayout(self._button, self._input.parentNode);\n            //    }\n            //});            \n                                         \n        },\n        /**\n         * Creates iframe with unique name\n         * @return {Element} iframe\n         */\n        _createIframe: function(){\n            // We can't use getTime, because it sometimes return\n            // same value in safari :(\n            var id = getUID();            \n             \n            // We can't use following code as the name attribute\n            // won't be properly registered in IE6, and new window\n            // on form submit will open\n            // var iframe = document.createElement('iframe');\n            // iframe.setAttribute('name', id);                        \n \n            var iframe = toElement('<iframe src=\"javascript:false;\" name=\"' + id + '\" />');\n            // src=\"javascript:false; was added\n            // because it possibly removes ie6 prompt \n            // \"This page contains both secure and nonsecure items\"\n            // Anyway, it doesn't do any harm.            \n            iframe.setAttribute('id', id);\n            \n            iframe.style.display = 'none';\n            document.body.appendChild(iframe);\n            \n            return iframe;\n        },\n        /**\n         * Creates form, that will be submitted to iframe\n         * @param {Element} iframe Where to submit\n         * @return {Element} form\n         */\n        _createForm: function(iframe){\n            var settings = this._settings;\n                        \n            // We can't use the following code in IE6\n            // var form = document.createElement('form');\n            // form.setAttribute('method', 'post');\n            // form.setAttribute('enctype', 'multipart/form-data');\n            // Because in this case file won't be attached to request                    \n            var form = toElement('<form method=\"post\" enctype=\"multipart/form-data\"></form>');\n                        \n            form.setAttribute('action', settings.action);\n            form.setAttribute('target', iframe.name);                                   \n            form.style.display = 'none';\n            document.body.appendChild(form);\n            \n            // Create hidden input element for each data key\n            for (var prop in settings.data) {\n                if (settings.data.hasOwnProperty(prop)){\n                    var el = document.createElement(\"input\");\n                    el.setAttribute('type', 'hidden');\n                    el.setAttribute('name', prop);\n                    el.setAttribute('value', settings.data[prop]);\n                    form.appendChild(el);\n                }\n            }\n            return form;\n        },\n        /**\n         * Gets response from iframe and fires onComplete event when ready\n         * @param iframe\n         * @param file Filename to use in onComplete callback \n         */\n        _getResponse : function(iframe, file){            \n            // getting response\n            var toDeleteFlag = false, self = this, settings = this._settings;   \n               \n            addEvent(iframe, 'load', function(){                \n                \n                if (// For Safari \n                    iframe.src == \"javascript:'%3Chtml%3E%3C/html%3E';\" ||\n                    // For FF, IE\n                    iframe.src == \"javascript:'<html></html>';\"){                                                                        \n                        // First time around, do not delete.\n                        // We reload to blank page, so that reloading main page\n                        // does not re-submit the post.\n                        \n                        if (toDeleteFlag) {\n                            // Fix busy state in FF3\n                            setTimeout(function(){\n                                removeNode(iframe);\n                            }, 0);\n                        }\n                                                \n                        return;\n                }\n                \n                var doc = iframe.contentDocument ? iframe.contentDocument : window.frames[iframe.id].document;\n                \n                // fixing Opera 9.26,10.00\n                if (doc.readyState && doc.readyState != 'complete') {\n                   // Opera fires load event multiple times\n                   // Even when the DOM is not ready yet\n                   // this fix should not affect other browsers\n                   return;\n                }\n                \n                // fixing Opera 9.64\n                if (doc.body && doc.body.innerHTML == \"false\") {\n                    // In Opera 9.64 event was fired second time\n                    // when body.innerHTML changed from false \n                    // to server response approx. after 1 sec\n                    return;\n                }\n                \n                var response;\n                \n                if (doc.XMLDocument) {\n                    // response is a xml document Internet Explorer property\n                    response = doc.XMLDocument;\n                } else if (doc.body){\n                    // response is html document or plain text\n                    response = doc.body.innerHTML;\n                    \n                    if (settings.responseType && settings.responseType.toLowerCase() == 'json') {\n                        // If the document was sent as 'application/javascript' or\n                        // 'text/javascript', then the browser wraps the text in a <pre>\n                        // tag and performs html encoding on the contents.  In this case,\n                        // we need to pull the original text content from the text node's\n                        // nodeValue property to retrieve the unmangled content.\n                        // Note that IE6 only understands text/html\n                        if (doc.body.firstChild && doc.body.firstChild.nodeName.toUpperCase() == 'PRE') {\n                            response = doc.body.firstChild.firstChild.nodeValue;\n                        }\n                        \n                        if (response) {\n                            response = eval(\"(\" + response + \")\");\n                        } else {\n                            response = {};\n                        }\n                    }\n                } else {\n                    // response is a xml document\n                    response = doc;\n                }\n                \n                settings.onComplete.call(self, file, response);\n                \n                // Reload blank page, so that reloading main page\n                // does not re-submit the post. Also, remember to\n                // delete the frame\n                toDeleteFlag = true;\n                \n                // Fix IE mixed content issue\n                iframe.src = \"javascript:'<html></html>';\";\n            });            \n        },        \n        /**\n         * Upload file contained in this._input\n         */\n        submit: function(){                        \n            var self = this, settings = this._settings;\n            \n            if ( ! this._input || this._input.value === ''){                \n                return;                \n            }\n                                    \n            var file = fileFromPath(this._input.value);\n            \n            // user returned false to cancel upload\n            if (false === settings.onSubmit.call(this, file, getExt(file))){\n                this._clearInput();                \n                return;\n            }\n            \n            // sending request    \n            var iframe = this._createIframe();\n            var form = this._createForm(iframe);\n            \n            // assuming following structure\n            // div -> input type='file'\n            removeNode(this._input.parentNode);            \n            removeClass(self._button, self._settings.hoverClass);\n                        \n            form.appendChild(this._input);\n                        \n            form.submit();\n\n            // request set, clean up                \n            removeNode(form); form = null;                          \n            removeNode(this._input); this._input = null;\n            \n            // Get response from iframe and fire onComplete event when ready\n            this._getResponse(iframe, file);            \n\n            // get ready for next request            \n            this._createInput();\n        }\n    };\n})(); \n"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/libs/app.js",
    "content": "/*! AdminLTE app.js\n * ================\n * Main JS application file for AdminLTE v2. This file\n * should be included in all pages. It controls some layout\n * options and implements exclusive AdminLTE plugins.\n *\n * @Author  Almsaeed Studio\n * @Support <http://www.almsaeedstudio.com>\n * @Email   <abdullah@almsaeedstudio.com>\n * @version 2.3.8\n * @license MIT <http://opensource.org/licenses/MIT>\n */\n\n//Make sure jQuery has been loaded before app.js\nif (typeof jQuery === \"undefined\") {\n  throw new Error(\"AdminLTE requires jQuery\");\n}\n\n/* AdminLTE\n *\n * @type Object\n * @description $.AdminLTE is the main object for the template's app.\n *              It's used for implementing functions and options related\n *              to the template. Keeping everything wrapped in an object\n *              prevents conflict with other plugins and is a better\n *              way to organize our code.\n */\n$.AdminLTE = {};\n\n/* --------------------\n * - AdminLTE Options -\n * --------------------\n * Modify these options to suit your implementation\n */\n$.AdminLTE.options = {\n  //Add slimscroll to navbar menus\n  //This requires you to load the slimscroll plugin\n  //in every page before app.js\n  navbarMenuSlimscroll: true,\n  navbarMenuSlimscrollWidth: \"3px\", //The width of the scroll bar\n  navbarMenuHeight: \"200px\", //The height of the inner menu\n  //General animation speed for JS animated elements such as box collapse/expand and\n  //sidebar treeview slide up/down. This options accepts an integer as milliseconds,\n  //'fast', 'normal', or 'slow'\n  animationSpeed: 'fast',\n  //Sidebar push menu toggle button selector\n  sidebarToggleSelector: \"[data-toggle='offcanvas']\",\n  //Activate sidebar push menu\n  sidebarPushMenu: true,\n  //Activate sidebar slimscroll if the fixed layout is set (requires SlimScroll Plugin)\n  sidebarSlimScroll: true,\n  //Enable sidebar expand on hover effect for sidebar mini\n  //This option is forced to true if both the fixed layout and sidebar mini\n  //are used together\n  sidebarExpandOnHover: false,\n  //BoxRefresh Plugin\n  enableBoxRefresh: true,\n  //Bootstrap.js tooltip\n  enableBSToppltip: true,\n  BSTooltipSelector: \"[data-toggle='tooltip']\",\n  //Enable Fast Click. Fastclick.js creates a more\n  //native touch experience with touch devices. If you\n  //choose to enable the plugin, make sure you load the script\n  //before AdminLTE's app.js\n  enableFastclick: false,\n  //Control Sidebar Tree views\n  enableControlTreeView: true,\n  //Control Sidebar Options\n  enableControlSidebar: true,\n  controlSidebarOptions: {\n    //Which button should trigger the open/close event\n    toggleBtnSelector: \"[data-toggle='control-sidebar']\",\n    //The sidebar selector\n    selector: \".control-sidebar\",\n    //Enable slide over content\n    slide: true\n  },\n  //Box Widget Plugin. Enable this plugin\n  //to allow boxes to be collapsed and/or removed\n  enableBoxWidget: true,\n  //Box Widget plugin options\n  boxWidgetOptions: {\n    boxWidgetIcons: {\n      //Collapse icon\n      collapse: 'fa-minus',\n      //Open icon\n      open: 'fa-plus',\n      //Remove icon\n      remove: 'fa-times'\n    },\n    boxWidgetSelectors: {\n      //Remove button selector\n      remove: '[data-widget=\"remove\"]',\n      //Collapse button selector\n      collapse: '[data-widget=\"collapse\"]'\n    }\n  },\n  //Direct Chat plugin options\n  directChat: {\n    //Enable direct chat by default\n    enable: true,\n    //The button to open and close the chat contacts pane\n    contactToggleSelector: '[data-widget=\"chat-pane-toggle\"]'\n  },\n  //Define the set of colors to use globally around the website\n  colors: {\n    lightBlue: \"#3c8dbc\",\n    red: \"#f56954\",\n    green: \"#00a65a\",\n    aqua: \"#00c0ef\",\n    yellow: \"#f39c12\",\n    blue: \"#0073b7\",\n    navy: \"#001F3F\",\n    teal: \"#39CCCC\",\n    olive: \"#3D9970\",\n    lime: \"#01FF70\",\n    orange: \"#FF851B\",\n    fuchsia: \"#F012BE\",\n    purple: \"#8E24AA\",\n    maroon: \"#D81B60\",\n    black: \"#222222\",\n    gray: \"#d2d6de\"\n  },\n  //The standard screen sizes that bootstrap uses.\n  //If you change these in the variables.less file, change\n  //them here too.\n  screenSizes: {\n    xs: 480,\n    sm: 768,\n    md: 992,\n    lg: 1200\n  }\n};\n\n/* ------------------\n * - Implementation -\n * ------------------\n * The next block of code implements AdminLTE's\n * functions and plugins as specified by the\n * options above.\n */\n$(function () {\n  \"use strict\";\n\n  //Fix for IE page transitions\n  $(\"body\").removeClass(\"hold-transition\");\n\n  //Extend options if external options exist\n  if (typeof AdminLTEOptions !== \"undefined\") {\n    $.extend(true,\n      $.AdminLTE.options,\n      AdminLTEOptions);\n  }\n\n  //Easy access to options\n  var o = $.AdminLTE.options;\n\n  //Set up the object\n  _init();\n\n  //Activate the layout maker\n  $.AdminLTE.layout.activate();\n\n  //Enable sidebar tree view controls\n  if (o.enableControlTreeView) {\n    $.AdminLTE.tree('.sidebar');\n  }\n\n  //Enable control sidebar\n  if (o.enableControlSidebar) {\n    $.AdminLTE.controlSidebar.activate();\n  }\n\n  //Add slimscroll to navbar dropdown\n  if (o.navbarMenuSlimscroll && typeof $.fn.slimscroll != 'undefined') {\n    $(\".navbar .menu\").slimscroll({\n      height: o.navbarMenuHeight,\n      alwaysVisible: false,\n      size: o.navbarMenuSlimscrollWidth\n    }).css(\"width\", \"100%\");\n  }\n\n  //Activate sidebar push menu\n  if (o.sidebarPushMenu) {\n    $.AdminLTE.pushMenu.activate(o.sidebarToggleSelector);\n  }\n\n  //Activate Bootstrap tooltip\n  if (o.enableBSToppltip) {\n    $('body').tooltip({\n      selector: o.BSTooltipSelector,\n      container: 'body'\n    });\n  }\n\n  //Activate box widget\n  if (o.enableBoxWidget) {\n    $.AdminLTE.boxWidget.activate();\n  }\n\n  //Activate fast click\n  if (o.enableFastclick && typeof FastClick != 'undefined') {\n    FastClick.attach(document.body);\n  }\n\n  //Activate direct chat widget\n  if (o.directChat.enable) {\n    $(document).on('click', o.directChat.contactToggleSelector, function () {\n      var box = $(this).parents('.direct-chat').first();\n      box.toggleClass('direct-chat-contacts-open');\n    });\n  }\n\n  /*\n   * INITIALIZE BUTTON TOGGLE\n   * ------------------------\n   */\n  $('.btn-group[data-toggle=\"btn-toggle\"]').each(function () {\n    var group = $(this);\n    $(this).find(\".btn\").on('click', function (e) {\n      group.find(\".btn.active\").removeClass(\"active\");\n      $(this).addClass(\"active\");\n      e.preventDefault();\n    });\n\n  });\n});\n\n/* ----------------------------------\n * - Initialize the AdminLTE Object -\n * ----------------------------------\n * All AdminLTE functions are implemented below.\n */\nfunction _init() {\n  'use strict';\n  /* Layout\n   * ======\n   * Fixes the layout height in case min-height fails.\n   *\n   * @type Object\n   * @usage $.AdminLTE.layout.activate()\n   *        $.AdminLTE.layout.fix()\n   *        $.AdminLTE.layout.fixSidebar()\n   */\n  $.AdminLTE.layout = {\n    activate: function () {\n      var _this = this;\n      _this.fix();\n      _this.fixSidebar();\n      $('body, html, .wrapper').css('height', 'auto');\n      $(window, \".wrapper\").resize(function () {\n        _this.fix();\n        _this.fixSidebar();\n      });\n    },\n    fix: function () {\n      // Remove overflow from .wrapper if layout-boxed exists\n      $(\".layout-boxed > .wrapper\").css('overflow', 'hidden');\n      //Get window height and the wrapper height\n      var footer_height = $('.main-footer').outerHeight() || 0;\n      var neg = $('.main-header').outerHeight() + footer_height;\n      var window_height = $(window).height();\n      var sidebar_height = $(\".sidebar\").height() || 0;\n      //Set the min-height of the content and sidebar based on the\n      //the height of the document.\n      if ($(\"body\").hasClass(\"fixed\")) {\n        $(\".content-wrapper, .right-side\").css('min-height', window_height - footer_height);\n      } else {\n        var postSetWidth;\n        if (window_height >= sidebar_height) {\n          $(\".content-wrapper, .right-side\").css('min-height', window_height - neg);\n          postSetWidth = window_height - neg;\n        } else {\n          $(\".content-wrapper, .right-side\").css('min-height', sidebar_height);\n          postSetWidth = sidebar_height;\n        }\n\n        //Fix for the control sidebar height\n        var controlSidebar = $($.AdminLTE.options.controlSidebarOptions.selector);\n        if (typeof controlSidebar !== \"undefined\") {\n          if (controlSidebar.height() > postSetWidth)\n            $(\".content-wrapper, .right-side\").css('min-height', controlSidebar.height());\n        }\n\n      }\n    },\n    fixSidebar: function () {\n      //Make sure the body tag has the .fixed class\n      if (!$(\"body\").hasClass(\"fixed\")) {\n        if (typeof $.fn.slimScroll != 'undefined') {\n          $(\".sidebar\").slimScroll({destroy: true}).height(\"auto\");\n        }\n        return;\n      } else if (typeof $.fn.slimScroll == 'undefined' && window.console) {\n        window.console.error(\"Error: the fixed layout requires the slimscroll plugin!\");\n      }\n      //Enable slimscroll for fixed layout\n      if ($.AdminLTE.options.sidebarSlimScroll) {\n        if (typeof $.fn.slimScroll != 'undefined') {\n          //Destroy if it exists\n          $(\".sidebar\").slimScroll({destroy: true}).height(\"auto\");\n          //Add slimscroll\n          $(\".sidebar\").slimScroll({\n            height: ($(window).height() - $(\".main-header\").height()) + \"px\",\n            color: \"rgba(0,0,0,0.2)\",\n            size: \"3px\"\n          });\n        }\n      }\n    }\n  };\n\n  /* PushMenu()\n   * ==========\n   * Adds the push menu functionality to the sidebar.\n   *\n   * @type Function\n   * @usage: $.AdminLTE.pushMenu(\"[data-toggle='offcanvas']\")\n   */\n  $.AdminLTE.pushMenu = {\n    activate: function (toggleBtn) {\n      //Get the screen sizes\n      var screenSizes = $.AdminLTE.options.screenSizes;\n\n      //Enable sidebar toggle\n      $(document).on('click', toggleBtn, function (e) {\n        e.preventDefault();\n\n        //Enable sidebar push menu\n        if ($(window).width() > (screenSizes.sm - 1)) {\n          if ($(\"body\").hasClass('sidebar-collapse')) {\n            $(\"body\").removeClass('sidebar-collapse').trigger('expanded.pushMenu');\n          } else {\n            $(\"body\").addClass('sidebar-collapse').trigger('collapsed.pushMenu');\n          }\n        }\n        //Handle sidebar push menu for small screens\n        else {\n          if ($(\"body\").hasClass('sidebar-open')) {\n            $(\"body\").removeClass('sidebar-open').removeClass('sidebar-collapse').trigger('collapsed.pushMenu');\n          } else {\n            $(\"body\").addClass('sidebar-open').trigger('expanded.pushMenu');\n          }\n        }\n      });\n\n      $(\".content-wrapper\").click(function () {\n        //Enable hide menu when clicking on the content-wrapper on small screens\n        if ($(window).width() <= (screenSizes.sm - 1) && $(\"body\").hasClass(\"sidebar-open\")) {\n          $(\"body\").removeClass('sidebar-open');\n        }\n      });\n\n      //Enable expand on hover for sidebar mini\n      if ($.AdminLTE.options.sidebarExpandOnHover\n        || ($('body').hasClass('fixed')\n        && $('body').hasClass('sidebar-mini'))) {\n        this.expandOnHover();\n      }\n    },\n    expandOnHover: function () {\n      var _this = this;\n      var screenWidth = $.AdminLTE.options.screenSizes.sm - 1;\n      //Expand sidebar on hover\n      $('.main-sidebar').hover(function () {\n        if ($('body').hasClass('sidebar-mini')\n          && $(\"body\").hasClass('sidebar-collapse')\n          && $(window).width() > screenWidth) {\n          _this.expand();\n        }\n      }, function () {\n        if ($('body').hasClass('sidebar-mini')\n          && $('body').hasClass('sidebar-expanded-on-hover')\n          && $(window).width() > screenWidth) {\n          _this.collapse();\n        }\n      });\n    },\n    expand: function () {\n      $(\"body\").removeClass('sidebar-collapse').addClass('sidebar-expanded-on-hover');\n    },\n    collapse: function () {\n      if ($('body').hasClass('sidebar-expanded-on-hover')) {\n        $('body').removeClass('sidebar-expanded-on-hover').addClass('sidebar-collapse');\n      }\n    }\n  };\n\n  /* Tree()\n   * ======\n   * Converts the sidebar into a multilevel\n   * tree view menu.\n   *\n   * @type Function\n   * @Usage: $.AdminLTE.tree('.sidebar')\n   */\n  $.AdminLTE.tree = function (menu) {\n    var _this = this;\n    var animationSpeed = $.AdminLTE.options.animationSpeed;\n    $(document).off('click', menu + ' li a')\n      .on('click', menu + ' li a', function (e) {\n        //Get the clicked link and the next element\n        var $this = $(this);\n        var checkElement = $this.next();\n\n        //Check if the next element is a menu and is visible\n        if ((checkElement.is('.treeview-menu')) && (checkElement.is(':visible')) && (!$('body').hasClass('sidebar-collapse'))) {\n          //Close the menu\n          checkElement.slideUp(animationSpeed, function () {\n            checkElement.removeClass('menu-open');\n            //Fix the layout in case the sidebar stretches over the height of the window\n            //_this.layout.fix();\n          });\n          checkElement.parent(\"li\").removeClass(\"active\");\n        }\n        //If the menu is not visible\n        else if ((checkElement.is('.treeview-menu')) && (!checkElement.is(':visible'))) {\n          //Get the parent menu\n          var parent = $this.parents('ul').first();\n          //Close all open menus within the parent\n          var ul = parent.find('ul:visible').slideUp(animationSpeed);\n          //Remove the menu-open class from the parent\n          ul.removeClass('menu-open');\n          //Get the parent li\n          var parent_li = $this.parent(\"li\");\n\n          //Open the target menu and add the menu-open class\n          checkElement.slideDown(animationSpeed, function () {\n            //Add the class active to the parent li\n            checkElement.addClass('menu-open');\n            parent.find('li.active').removeClass('active');\n            parent_li.addClass('active');\n            //Fix the layout in case the sidebar stretches over the height of the window\n            _this.layout.fix();\n          });\n        }\n        //if this isn't a link, prevent the page from being redirected\n        if (checkElement.is('.treeview-menu')) {\n          e.preventDefault();\n        }\n      });\n  };\n\n  /* ControlSidebar\n   * ==============\n   * Adds functionality to the right sidebar\n   *\n   * @type Object\n   * @usage $.AdminLTE.controlSidebar.activate(options)\n   */\n  $.AdminLTE.controlSidebar = {\n    //instantiate the object\n    activate: function () {\n      //Get the object\n      var _this = this;\n      //Update options\n      var o = $.AdminLTE.options.controlSidebarOptions;\n      //Get the sidebar\n      var sidebar = $(o.selector);\n      //The toggle button\n      var btn = $(o.toggleBtnSelector);\n\n      //Listen to the click event\n      btn.on('click', function (e) {\n        e.preventDefault();\n        //If the sidebar is not open\n        if (!sidebar.hasClass('control-sidebar-open')\n          && !$('body').hasClass('control-sidebar-open')) {\n          //Open the sidebar\n          _this.open(sidebar, o.slide);\n        } else {\n          _this.close(sidebar, o.slide);\n        }\n      });\n\n      //If the body has a boxed layout, fix the sidebar bg position\n      var bg = $(\".control-sidebar-bg\");\n      _this._fix(bg);\n\n      //If the body has a fixed layout, make the control sidebar fixed\n      if ($('body').hasClass('fixed')) {\n        _this._fixForFixed(sidebar);\n      } else {\n        //If the content height is less than the sidebar's height, force max height\n        if ($('.content-wrapper, .right-side').height() < sidebar.height()) {\n          _this._fixForContent(sidebar);\n        }\n      }\n    },\n    //Open the control sidebar\n    open: function (sidebar, slide) {\n      //Slide over content\n      if (slide) {\n        sidebar.addClass('control-sidebar-open');\n      } else {\n        //Push the content by adding the open class to the body instead\n        //of the sidebar itself\n        $('body').addClass('control-sidebar-open');\n      }\n    },\n    //Close the control sidebar\n    close: function (sidebar, slide) {\n      if (slide) {\n        sidebar.removeClass('control-sidebar-open');\n      } else {\n        $('body').removeClass('control-sidebar-open');\n      }\n    },\n    _fix: function (sidebar) {\n      var _this = this;\n      if ($(\"body\").hasClass('layout-boxed')) {\n        sidebar.css('position', 'absolute');\n        sidebar.height($(\".wrapper\").height());\n        if (_this.hasBindedResize) {\n          return;\n        }\n        $(window).resize(function () {\n          _this._fix(sidebar);\n        });\n        _this.hasBindedResize = true;\n      } else {\n        sidebar.css({\n          'position': 'fixed',\n          'height': 'auto'\n        });\n      }\n    },\n    _fixForFixed: function (sidebar) {\n      sidebar.css({\n        'position': 'fixed',\n        'max-height': '100%',\n        'overflow': 'auto',\n        'padding-bottom': '50px'\n      });\n    },\n    _fixForContent: function (sidebar) {\n      $(\".content-wrapper, .right-side\").css('min-height', sidebar.height());\n    }\n  };\n\n  /* BoxWidget\n   * =========\n   * BoxWidget is a plugin to handle collapsing and\n   * removing boxes from the screen.\n   *\n   * @type Object\n   * @usage $.AdminLTE.boxWidget.activate()\n   *        Set all your options in the main $.AdminLTE.options object\n   */\n  $.AdminLTE.boxWidget = {\n    selectors: $.AdminLTE.options.boxWidgetOptions.boxWidgetSelectors,\n    icons: $.AdminLTE.options.boxWidgetOptions.boxWidgetIcons,\n    animationSpeed: $.AdminLTE.options.animationSpeed,\n    activate: function (_box) {\n      var _this = this;\n      if (!_box) {\n        _box = document; // activate all boxes per default\n      }\n      //Listen for collapse event triggers\n      $(_box).on('click', _this.selectors.collapse, function (e) {\n        e.preventDefault();\n        _this.collapse($(this));\n      });\n\n      //Listen for remove event triggers\n      $(_box).on('click', _this.selectors.remove, function (e) {\n        e.preventDefault();\n        _this.remove($(this));\n      });\n    },\n    collapse: function (element) {\n      var _this = this;\n      //Find the box parent\n      var box = element.parents(\".box\").first();\n      //Find the body and the footer\n      var box_content = box.find(\"> .box-body, > .box-footer, > form  >.box-body, > form > .box-footer\");\n      if (!box.hasClass(\"collapsed-box\")) {\n        //Convert minus into plus\n        element.children(\":first\")\n          .removeClass(_this.icons.collapse)\n          .addClass(_this.icons.open);\n        //Hide the content\n        box_content.slideUp(_this.animationSpeed, function () {\n          box.addClass(\"collapsed-box\");\n        });\n      } else {\n        //Convert plus into minus\n        element.children(\":first\")\n          .removeClass(_this.icons.open)\n          .addClass(_this.icons.collapse);\n        //Show the content\n        box_content.slideDown(_this.animationSpeed, function () {\n          box.removeClass(\"collapsed-box\");\n        });\n      }\n    },\n    remove: function (element) {\n      //Find the box parent\n      var box = element.parents(\".box\").first();\n      box.slideUp(this.animationSpeed);\n    }\n  };\n}\n\n/* ------------------\n * - Custom Plugins -\n * ------------------\n * All custom plugins are defined below.\n */\n\n/*\n * BOX REFRESH BUTTON\n * ------------------\n * This is a custom plugin to use with the component BOX. It allows you to add\n * a refresh button to the box. It converts the box's state to a loading state.\n *\n * @type plugin\n * @usage $(\"#box-widget\").boxRefresh( options );\n */\n(function ($) {\n\n  \"use strict\";\n\n  $.fn.boxRefresh = function (options) {\n\n    // Render options\n    var settings = $.extend({\n      //Refresh button selector\n      trigger: \".refresh-btn\",\n      //File source to be loaded (e.g: ajax/src.php)\n      source: \"\",\n      //Callbacks\n      onLoadStart: function (box) {\n        return box;\n      }, //Right after the button has been clicked\n      onLoadDone: function (box) {\n        return box;\n      } //When the source has been loaded\n\n    }, options);\n\n    //The overlay\n    var overlay = $('<div class=\"overlay\"><div class=\"fa fa-refresh fa-spin\"></div></div>');\n\n    return this.each(function () {\n      //if a source is specified\n      if (settings.source === \"\") {\n        if (window.console) {\n          window.console.log(\"Please specify a source first - boxRefresh()\");\n        }\n        return;\n      }\n      //the box\n      var box = $(this);\n      //the button\n      var rBtn = box.find(settings.trigger).first();\n\n      //On trigger click\n      rBtn.on('click', function (e) {\n        e.preventDefault();\n        //Add loading overlay\n        start(box);\n\n        //Perform ajax call\n        box.find(\".box-body\").load(settings.source, function () {\n          done(box);\n        });\n      });\n    });\n\n    function start(box) {\n      //Add overlay and loading img\n      box.append(overlay);\n\n      settings.onLoadStart.call(box);\n    }\n\n    function done(box) {\n      //Remove overlay and loading img\n      box.find(overlay).remove();\n\n      settings.onLoadDone.call(box);\n    }\n\n  };\n\n})(jQuery);\n\n/*\n * EXPLICIT BOX CONTROLS\n * -----------------------\n * This is a custom plugin to use with the component BOX. It allows you to activate\n * a box inserted in the DOM after the app.js was loaded, toggle and remove box.\n *\n * @type plugin\n * @usage $(\"#box-widget\").activateBox();\n * @usage $(\"#box-widget\").toggleBox();\n * @usage $(\"#box-widget\").removeBox();\n */\n(function ($) {\n\n  'use strict';\n\n  $.fn.activateBox = function () {\n    $.AdminLTE.boxWidget.activate(this);\n  };\n\n  $.fn.toggleBox = function () {\n    var button = $($.AdminLTE.boxWidget.selectors.collapse, this);\n    $.AdminLTE.boxWidget.collapse(button);\n  };\n\n  $.fn.removeBox = function () {\n    var button = $($.AdminLTE.boxWidget.selectors.remove, this);\n    $.AdminLTE.boxWidget.remove(button);\n  };\n\n})(jQuery);\n\n/*\n * TODO LIST CUSTOM PLUGIN\n * -----------------------\n * This plugin depends on iCheck plugin for checkbox and radio inputs\n *\n * @type plugin\n * @usage $(\"#todo-widget\").todolist( options );\n */\n(function ($) {\n\n  'use strict';\n\n  $.fn.todolist = function (options) {\n    // Render options\n    var settings = $.extend({\n      //When the user checks the input\n      onCheck: function (ele) {\n        return ele;\n      },\n      //When the user unchecks the input\n      onUncheck: function (ele) {\n        return ele;\n      }\n    }, options);\n\n    return this.each(function () {\n\n      if (typeof $.fn.iCheck != 'undefined') {\n        $('input', this).on('ifChecked', function () {\n          var ele = $(this).parents(\"li\").first();\n          ele.toggleClass(\"done\");\n          settings.onCheck.call(ele);\n        });\n\n        $('input', this).on('ifUnchecked', function () {\n          var ele = $(this).parents(\"li\").first();\n          ele.toggleClass(\"done\");\n          settings.onUncheck.call(ele);\n        });\n      } else {\n        $('input', this).on('change', function () {\n          var ele = $(this).parents(\"li\").first();\n          ele.toggleClass(\"done\");\n          if ($('input', ele).is(\":checked\")) {\n            settings.onCheck.call(ele);\n          } else {\n            settings.onUncheck.call(ele);\n          }\n        });\n      }\n    });\n  };\n}(jQuery));\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/libs/router.js",
    "content": "(function() {\n\twindow.Router = function() {\n\t\tvar self = this;\n\n\t\tself.hashList = {}; /* 路由表 */\n\t\tself.index = null;\n\t\tself.key = '!';\n\n\t\twindow.onhashchange = function() {\n\t\t\tself.reload();\n\t\t};\n\t};\n\n\t/**\n\t * 添加路由,如果路由已经存在则会覆盖\n\t * @param addr: 地址\n\t * @param callback: 回调函数，调用回调函数的时候同时也会传入相应参数\n\t */\n\tRouter.prototype.add = function(addr, callback) {\n\t\tvar self = this;\n\n\t\tself.hashList[addr] = callback;\n\t};\n\n\t/**\n\t * 删除路由\n\t * @param addr: 地址\n\t */\n\tRouter.prototype.remove = function(addr) {\n\t\tvar self = this;\n\n\t\tdelete self.hashList[addr];\n\t};\n\n\t/**\n\t * 设置主页地址\n\t * @param index: 主页地址\n\t */\n\tRouter.prototype.setIndex = function(index) {\n\t\tvar self = this;\n\n\t\tself.index = index;\n\t};\n\n\n\t/**\n\t * 跳转到指定地址\n\t * @param addr: 地址值\n\t */\n\tRouter.prototype.go = function(addr) {\n\t\tvar self = this;\n\n\t\twindow.location.hash = '#' + self.key + addr;\n\t};\n\n\t/**\n\t * 重载页面\n\t */\n\tRouter.prototype.reload = function() {\n\t\tvar self = this;\n\n\t\tvar hash = window.location.hash.replace('#' + self.key, '');\n\t\t//var addr = hash.split('/')[0];\n\t\tvar addr = hash;\n\t\tvar cb = getCb(addr, self.hashList);\n\t\tif(cb != false) {\n\t\t\tvar arr = hash.split('/');\n\t\t\tarr.shift();\n\t\t\tcb.apply(self, arr);\n\t\t}\n\t\telse {\n\t\t\tself.index && self.go(self.index);\t\n\t\t}\n\t};\n\n\t/**\n\t * 开始路由，实际上只是为了当直接访问路由路由地址的时候能够及时调用回调\n\t */\n\tRouter.prototype.start = function() {\n\t\tvar self = this;\n\n\t\tself.reload();\n\t}\n\n\t/**\n\t * 获取callback\n\t * @return false or callback\n\t */\n\tfunction getCb(addr, hashList) {\n\t\tfor(var key in hashList) {\n\t\t\tif(key == addr) {\n\t\t\t\treturn hashList[key]\t\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n})();"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/plugins/jqgrid/grid.locale-cn.js",
    "content": "/**\n * jqGrid Chinese Translation\n * 咖啡兔 yanhonglei@gmail.com\n * http://www.kafeitu.me \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/*global jQuery, define */\n(function( factory ) {\n\t\"use strict\";\n\tif ( typeof define === \"function\" && define.amd ) {\n\t\t// AMD. Register as an anonymous module.\n\t\tdefine([\n\t\t\t\"jquery\",\n\t\t\t\"../grid.base\"\n\t\t], factory );\n\t} else {\n\t\t// Browser globals\n\t\tfactory( jQuery );\n\t}\n}(function( $ ) {\n\n$.jgrid = $.jgrid || {};\nif(!$.jgrid.hasOwnProperty(\"regional\")) {\n\t$.jgrid.regional = [];\n}\n$.jgrid.regional[\"cn\"] = {\n    defaults : {\n        recordtext: \"{0} - {1}\\u3000共 {2} 条\", // 共字前是全角空格\n        emptyrecords: \"无数据显示\",\n        loadtext: \"读取中...\",\n\t\tsavetext: \"Saving...\",\n        pgtext : \" {0} 共 {1} 页\",\n\t\tpgfirst : \"First Page\",\n\t\tpglast : \"Last Page\",\n\t\tpgnext : \"Next Page\",\n\t\tpgprev : \"Previous Page\",\n\t\tpgrecs : \"Records per Page\",\n\t\tshowhide: \"Toggle Expand Collapse Grid\",\n\t\t// mobile\n\t\tpagerCaption : \"Grid::Page Settings\",\n\t\tpageText : \"Page:\",\n\t\trecordPage : \"Records per Page\",\n\t\tnomorerecs : \"No more records...\",\n\t\tscrollPullup: \"Pull up to load more...\",\n\t\tscrollPulldown : \"Pull down to refresh...\",\n\t\tscrollRefresh : \"Release to refresh...\"\n    },\n    search : {\n        caption: \"搜索...\",\n        Find: \"查找\",\n        Reset: \"重置\",\n        odata: [{ oper:'eq', text:'等于\\u3000\\u3000'},{ oper:'ne', text:'不等\\u3000\\u3000'},{ oper:'lt', text:'小于\\u3000\\u3000'},{ oper:'le', text:'小于等于'},{ oper:'gt', text:'大于\\u3000\\u3000'},{ oper:'ge', text:'大于等于'},{ oper:'bw', text:'开始于'},{ oper:'bn', text:'不开始于'},{ oper:'in', text:'属于\\u3000\\u3000'},{ oper:'ni', text:'不属于'},{ oper:'ew', text:'结束于'},{ oper:'en', text:'不结束于'},{ oper:'cn', text:'包含\\u3000\\u3000'},{ oper:'nc', text:'不包含'},{ oper:'nu', text:'不存在'},{ oper:'nn', text:'存在'}, {oper:'bt', text:'between'}],\n        groupOps: [ { op: \"AND\", text: \"所有\" },    { op: \"OR\",  text: \"任一\" } ],\n\t\toperandTitle : \"Click to select search operation.\",\n\t\tresetTitle : \"Reset Search Value\"\n    },\n    edit : {\n        addCaption: \"添加记录\",\n        editCaption: \"编辑记录\",\n        bSubmit: \"提交\",\n        bCancel: \"取消\",\n        bClose: \"关闭\",\n        saveData: \"数据已改变，是否保存？\",\n        bYes : \"是\",\n        bNo : \"否\",\n        bExit : \"取消\",\n        msg: {\n            required:\"此字段必需\",\n            number:\"请输入有效数字\",\n            minValue:\"输值必须大于等于 \",\n            maxValue:\"输值必须小于等于 \",\n            email: \"这不是有效的e-mail地址\",\n            integer: \"请输入有效整数\",\n            date: \"请输入有效时间\",\n            url: \"无效网址。前缀必须为 ('http://' 或 'https://')\",\n            nodefined : \" 未定义！\",\n            novalue : \" 需要返回值！\",\n            customarray : \"自定义函数需要返回数组！\",\n            customfcheck : \"必须有自定义函数!\"\n        }\n    },\n    view : {\n        caption: \"查看记录\",\n        bClose: \"关闭\"\n    },\n    del : {\n        caption: \"删除\",\n        msg: \"删除所选记录？\",\n        bSubmit: \"删除\",\n        bCancel: \"取消\"\n    },\n    nav : {\n        edittext: \"\",\n        edittitle: \"编辑所选记录\",\n        addtext:\"\",\n        addtitle: \"添加新记录\",\n        deltext: \"\",\n        deltitle: \"删除所选记录\",\n        searchtext: \"\",\n        searchtitle: \"查找\",\n        refreshtext: \"\",\n        refreshtitle: \"刷新表格\",\n        alertcap: \"注意\",\n        alerttext: \"请选择记录\",\n        viewtext: \"\",\n        viewtitle: \"查看所选记录\",\n\t\tsavetext: \"\",\n\t\tsavetitle: \"Save row\",\n\t\tcanceltext: \"\",\n\t\tcanceltitle : \"Cancel row editing\",\n\t\tselectcaption : \"Actions...\"\n    },\n    col : {\n        caption: \"选择列\",\n        bSubmit: \"确定\",\n        bCancel: \"取消\"\n    },\n    errors : {\n        errcap : \"错误\",\n        nourl : \"没有设置url\",\n        norecords: \"没有要处理的记录\",\n        model : \"colNames 和 colModel 长度不等！\"\n    },\n    formatter : {\n        integer : {thousandsSeparator: \",\", defaultValue: '0'},\n        number : {decimalSeparator:\".\", thousandsSeparator: \",\", decimalPlaces: 2, defaultValue: '0.00'},\n        currency : {decimalSeparator:\".\", thousandsSeparator: \",\", decimalPlaces: 2, prefix: \"\", suffix:\"\", defaultValue: '0.00'},\n        date : {\n            dayNames:   [\n                \"日\", \"一\", \"二\", \"三\", \"四\", \"五\", \"六\",\n                \"星期日\", \"星期一\", \"星期二\", \"星期三\", \"星期四\", \"星期五\", \"星期六\",\n            ],\n            monthNames: [\n                \"一\", \"二\", \"三\", \"四\", \"五\", \"六\", \"七\", \"八\", \"九\", \"十\", \"十一\", \"十二\",\n                \"一月\", \"二月\", \"三月\", \"四月\", \"五月\", \"六月\", \"七月\", \"八月\", \"九月\", \"十月\", \"十一月\", \"十二月\"\n            ],\n            AmPm : [\"am\",\"pm\",\"上午\",\"下午\"],\n            S: function (j) {return j < 11 || j > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((j - 1) % 10, 3)] : 'th';},\n            srcformat: 'Y-m-d',\n            newformat: 'Y-m-d',\n            parseRe : /[#%\\\\\\/:_;.,\\t\\s-]/,\n            masks : {\n                // see http://php.net/manual/en/function.date.php for PHP format used in jqGrid\n                // and see http://docs.jquery.com/UI/Datepicker/formatDate\n                // and https://github.com/jquery/globalize#dates for alternative formats used frequently\n                // one can find on https://github.com/jquery/globalize/tree/master/lib/cultures many\n                // information about date, time, numbers and currency formats used in different countries\n                // one should just convert the information in PHP format\n                ISO8601Long:\"Y-m-d H:i:s\",\n                ISO8601Short:\"Y-m-d\",\n                // short date:\n                //    n - Numeric representation of a month, without leading zeros\n                //    j - Day of the month without leading zeros\n                //    Y - A full numeric representation of a year, 4 digits\n                // example: 3/1/2012 which means 1 March 2012\n                ShortDate: \"n/j/Y\", // in jQuery UI Datepicker: \"M/d/yyyy\"\n                // long date:\n                //    l - A full textual representation of the day of the week\n                //    F - A full textual representation of a month\n                //    d - Day of the month, 2 digits with leading zeros\n                //    Y - A full numeric representation of a year, 4 digits\n                LongDate: \"l, F d, Y\", // in jQuery UI Datepicker: \"dddd, MMMM dd, yyyy\"\n                // long date with long time:\n                //    l - A full textual representation of the day of the week\n                //    F - A full textual representation of a month\n                //    d - Day of the month, 2 digits with leading zeros\n                //    Y - A full numeric representation of a year, 4 digits\n                //    g - 12-hour format of an hour without leading zeros\n                //    i - Minutes with leading zeros\n                //    s - Seconds, with leading zeros\n                //    A - Uppercase Ante meridiem and Post meridiem (AM or PM)\n                FullDateTime: \"l, F d, Y g:i:s A\", // in jQuery UI Datepicker: \"dddd, MMMM dd, yyyy h:mm:ss tt\"\n                // month day:\n                //    F - A full textual representation of a month\n                //    d - Day of the month, 2 digits with leading zeros\n                MonthDay: \"F d\", // in jQuery UI Datepicker: \"MMMM dd\"\n                // short time (without seconds)\n                //    g - 12-hour format of an hour without leading zeros\n                //    i - Minutes with leading zeros\n                //    A - Uppercase Ante meridiem and Post meridiem (AM or PM)\n                ShortTime: \"g:i A\", // in jQuery UI Datepicker: \"h:mm tt\"\n                // long time (with seconds)\n                //    g - 12-hour format of an hour without leading zeros\n                //    i - Minutes with leading zeros\n                //    s - Seconds, with leading zeros\n                //    A - Uppercase Ante meridiem and Post meridiem (AM or PM)\n                LongTime: \"g:i:s A\", // in jQuery UI Datepicker: \"h:mm:ss tt\"\n                SortableDateTime: \"Y-m-d\\\\TH:i:s\",\n                UniversalSortableDateTime: \"Y-m-d H:i:sO\",\n                // month with year\n                //    Y - A full numeric representation of a year, 4 digits\n                //    F - A full textual representation of a month\n                YearMonth: \"F, Y\" // in jQuery UI Datepicker: \"MMMM, yyyy\"\n            },\n            reformatAfterEdit : false,\n\t\t\tuserLocalTime : false\n        },\n        baseLinkUrl: '',\n        showAction: '',\n        target: '',\n        checkbox : {disabled:true},\n        idName : 'id'\n    },\n\tcolmenu : {\n\t\tsortasc : \"Sort Ascending\",\n\t\tsortdesc : \"Sort Descending\",\n\t\tcolumns : \"Columns\",\n\t\tfilter : \"Filter\",\n\t\tgrouping : \"Group By\",\n\t\tungrouping : \"Ungroup\",\n\t\tsearchTitle : \"Get items with value that:\",\n\t\tfreeze : \"Freeze\",\n\t\tunfreeze : \"Unfreeze\",\n\t\treorder : \"Move to reorder\"\n\t}\n};\n}));\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/plugins/jqgrid/ui.jqgrid-bootstrap-ui.css",
    "content": "/*\nTo change this license header, choose License Headers in Project Properties.\nTo change this template file, choose Tools | Templates\nand open the template in the editor.\n*/\n/* \n    Created on : Mar 16, 2015, 10:24:01 AM\n    Author     : tony\n*/\n\n.ui-jqgrid tr.jqgrow td { height: 26px;}\n.ui-jqgrid .ui-pg-input,.ui-jqgrid .ui-jqgrid-toppager .ui-pg-input { height:20px }\n.ui-state-hover\n{\n    border: .15em solid;\n\tborder-color: inherit;\n\n}\n.ui-jqdialog .ui-jqdialog-titlebar  {\n\theight:29px;\n\tborder-color: inherit;\n}\n\n.ui-jqdialog-content input.FormElement {\n    padding: 0.25em;\n}\n\n.fm-button {\n    height:30px;\n}\n#nData, #pData { height:20px; width:18px; }"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/plugins/jqgrid/ui.jqgrid-bootstrap.css",
    "content": "/*Grid*/\n.ui-jqgrid {\n\tposition: relative; \n\tborder: 1px solid #ddd;      /*default*/\n\t-webkit-border-radius: 3px;\n\t-moz-border-radius: 3px;\n\tborder-radius: 3px;\n}\n.ui-jqgrid .ui-jqgrid-view {\n\tposition: relative;\n\tleft:0; \n\ttop: 0; \n\tpadding: 0;\n}\n.ui-jqgrid .ui-common-table {}\n\n/* Caption*/\n.ui-jqgrid .ui-jqgrid-titlebar {\n\tfont-weight: normal;\n\tmin-height:37px; \n\tpadding: 4px 8px; \n\tposition: relative; \n\tmargin-right: 2px;\n\tborder-bottom: 1px solid #ddd; /*default*/\n\n}\n.ui-jqgrid .ui-jqgrid-caption {\n\ttext-align: left;\n}\n.ui-jqgrid .ui-jqgrid-title { \n\tpadding-top: 5px; \n\tvertical-align: middle;\n}\n.ui-jqgrid .ui-jqgrid-titlebar-close { \n\tcolor: inherit; \n\tposition: absolute;\n\ttop: 50%; \n\tmargin: -10px 7px 0 0; \n\tpadding: 1px; \n\tcursor:pointer;\n}\n.ui-jqgrid .ui-jqgrid-titlebar-close span { \n\tdisplay: block; \n\tmargin: 1px; \n}\n.ui-jqgrid .ui-jqgrid-titlebar-close:hover {  }\n\n/* Header*/\n.ui-jqgrid .ui-jqgrid-hdiv {\n\tposition: relative; \n\tmargin: 0;\n\tpadding: 0; \n\toverflow: hidden;\n}\n.ui-jqgrid .ui-jqgrid-hbox {\n\tfloat: left; \n\tpadding-right: 20px;\n}\n.ui-jqgrid .ui-jqgrid-htable { \n\tmargin-bottom: 0; \n\ttable-layout: fixed; \n\tborder-top:none;\n}\n.ui-jqgrid .ui-jqgrid-htable thead th {\n\toverflow : hidden; \n\tborder-bottom : none;\n\tpadding-right: 2px;\n}\n.ui-jqgrid .ui-jqgrid-htable thead th div {\n\toverflow: hidden; \n\tposition:relative;\n}\n.ui-th-column, .ui-jqgrid .ui-jqgrid-htable th.ui-th-column {\n\toverflow: hidden;\n\twhite-space: nowrap;\n}\n.ui-th-column-header, \n.ui-jqgrid .ui-jqgrid-htable th.ui-th-column-header {\n\toverflow: hidden;\n\twhite-space: nowrap;\n}\n.ui-th-ltr, .ui-jqgrid .ui-jqgrid-htable th.ui-th-ltr {}\n.ui-th-rtl, .ui-jqgrid .ui-jqgrid-htable th.ui-th-rtl {text-align: center; }\n.ui-first-th-ltr { }\n.ui-first-th-rtl { }\n.ui-jqgrid tr.jqg-first-row-header th {\n\theight:auto; \n\tborder-top:none; \n\tpadding-bottom: 0;\n\tpadding-top: 0;\n\tborder-bottom: none; \n\tpadding-right: 2px;\n\ttext-align: center;\n}\n.ui-jqgrid tr.jqg-second-row-header th,\n.ui-jqgrid tr.jqg-third--row-header th\n{\n\tborder-top:none;\n\ttext-align: center;\n}\n\n.ui-jqgrid .ui-th-div-ie {\n\twhite-space: nowrap; \n\tzoom :1; \n\theight:17px;\n}\n.ui-jqgrid .ui-jqgrid-resize {\n\theight:20px !important;\n\tposition: relative; \n\tcursor :e-resize;\n\tdisplay: inline;\n\toverflow: hidden;\n}\n.ui-jqgrid .ui-grid-ico-sort { \n\tmargin-left:5px; \n\toverflow:hidden;\n\tposition:absolute;\n\tright: auto;\n\tfont-size:12px;\n}\n.ui-jqgrid .ui-icon-asc {\n\tmargin-top:-3px;\n}\n.ui-jqgrid .ui-icon-desc {\n\tmargin-top:4px;\n}\n.ui-jqgrid .ui-i-asc {\n\tmargin-top:0;\n}\n.ui-jqgrid .ui-i-desc {\n\tmargin-top:0;\n\tmargin-right:13px;\n}\n.ui-jqgrid .ui-single-sort-asc {\n\tmargin-top:0;\n}\n.ui-jqgrid .ui-single-sort-desc {}\n.ui-jqgrid .ui-jqgrid-sortable {\n\tcursor:pointer;\n}\n.ui-jqgrid tr.ui-search-toolbar th { }\n.ui-jqgrid .ui-search-table td.ui-search-clear { }\n.ui-jqgrid tr.ui-search-toolbar td > input { }\n.ui-jqgrid tr.ui-search-toolbar select {}\n\n/* Body */ \n.ui-jqgrid .table-bordered,\n.ui-jqgrid .table-bordered td,\n.ui-jqgrid .table-bordered th.ui-th-ltr\n{\n\tborder-left:0px none !important;\n}\n.ui-jqgrid .table-bordered th.ui-th-rtl\n{\n\tborder-right:0px none !important;\n}\n.ui-jqgrid .table-bordered tr.ui-row-rtl td\n{\n\tborder-right:0px none !important;\n\tborder-left: 1px solid #ddd !important;\n}\ndiv.tablediv > .table-bordered {\n\tborder-left : 1px solid #ddd !important;\n}\n.ui-jqgrid  .ui-jqgrid-bdiv table.table-bordered td {\n\tborder-top: 0px none;\n}\n.ui-jqgrid .ui-jqgrid-bdiv {\n\tposition: relative; \n\tmargin: 0; \n\tpadding:0; \n\toverflow: auto; \n\ttext-align:left; \n}\n.ui-jqgrid .ui-jqgrid-btable {\n\ttable-layout: fixed; \n\tborder-left:none ; \n\tborder-top:none; \n\tmargin-bottom: 0px\n}\n.ui-jqgrid tr.jqgrow {  \n\toutline-style: none; \n}\n.ui-jqgrid tr.jqgroup {  \n\toutline-style: none; \n}\n.ui-jqgrid .ui-jqgrid-btable tbody tr.jqgrow td { \n\toverflow: hidden; \n\twhite-space: pre; \n\tpadding-right: 2px;\n}\n.ui-jqgrid tr.jqgfirstrow  td {\n\theight:auto; \n\tborder-top:none; \n\tpadding-bottom: 0;\n\tpadding-top: 0;\n\tborder-bottom: none; \n\tpadding-right: 2px;\n}\n.ui-jqgrid tr.jqgroup td { \n\twhite-space: nowrap;\n}\n.ui-jqgrid tr.jqfoot td {\n\twhite-space: nowrap;\n}\n.ui-jqgrid tr.ui-row-ltr td {}\n.ui-jqgrid tr.ui-row-rtl td {}\n.ui-jqgrid td.jqgrid-rownum { }\n.ui-jqgrid .ui-jqgrid-resize-mark { \n\twidth:2px; \n\tleft:0; \n\tbackground-color:#777; \n\tcursor: e-resize; \n\tcursor: col-resize; \n\tposition:absolute; \n\ttop:0; \n\theight:100px; \n\toverflow:hidden; \n\tdisplay:none; \n\tborder:0 none; \n\tz-index: 99999;\n\n}\n/* Footer */\n.ui-jqgrid .ui-jqgrid-sdiv {\n\tposition: relative; \n\tmargin: 0;\n\tpadding: 0; \n\toverflow: hidden; \n\tborder-left: 0 none !important; \n\tborder-top : 0 none !important; \n\tborder-right : 0 none !important;\n}\n.ui-jqgrid .ui-jqgrid-ftable {\n\ttable-layout:fixed;\n\tmargin-bottom:0;\n}\n\n.ui-jqgrid tr.footrow td {\n\tfont-weight: bold; \n\toverflow: hidden; \n\twhite-space:nowrap; \n\tpadding-right: 2px;\n\tborder-bottom: 0px none;\n}\n.ui-jqgrid tr.footrow-ltr td {\n\ttext-align:left;\n}\n.ui-jqgrid tr.footrow-rtl td {\n\ttext-align:right;\n}\n\n/* Pager*/\n.ui-jqgrid .ui-jqgrid-pager,\n.ui-jqgrid .ui-jqgrid-toppager\n{ \n\tborder-left-width: 0px;\n\tborder-top: 1px solid #ddd;  \n\t/*padding : 4px 0px;*/\n\tposition: relative; \n\t/*height: auto; */\n\twhite-space: nowrap;\n\toverflow: hidden;\n}\n.ui-jqgrid .ui-jqgrid-toppager {\n\tborder-top-width :0;\n\tborder-bottom : 1px solid #ddd;\n}\n.ui-jqgrid .ui-jqgrid-toppager .ui-pager-control, \n.ui-jqgrid .ui-jqgrid-pager .ui-pager-control {\n\tposition: relative;\n\tborder-left: 0;\n\tborder-bottom: 0;\n\tborder-top: 0; \n\t/*height: 30px;*/\n}\n.ui-jqgrid .ui-pg-table {\n\tposition: relative; \n\tpadding: 1px 0; \n\twidth:auto; \n\tmargin: 0;\n}\n.ui-jqgrid .ui-pg-table td {\n\tfont-weight:normal; \n\tvertical-align:middle; \n\t/*padding:0px 6px;*/\n}\n.ui-jqgrid .ui-pager-control .ui-pager-table td {\n\tborder-top : 0px none !important;\n\tmin-height : 20px !important;\n}\n.ui-jqgrid .ui-pg-button  { \n\theight:auto; \n}\n.ui-jqgrid  .ui-paging-pager td {\n\tpadding : 0 5px;\n}\n.ui-jqgrid .ui-pg-button span { \n\tdisplay: block; \n\tmargin: 0px 2px; \n\tfloat:left;\n}\n.ui-jqgrid .ui-pg-button:hover {  }\n.ui-jqgrid .ui-disabled:hover {}\n.ui-jqgrid .ui-pg-input,\n.ui-jqgrid .ui-jqgrid-toppager .ui-pg-input { \n\tdisplay: inline-block;\n\theight:auto;\n\twidth: auto;\n\tfont-size:.9em; \n\tmargin:0;\n\tline-height: inherit;\n\tborder: none; \n\tpadding: 0px 3px\n}\n.ui-jqgrid .ui-pg-selbox, \n.ui-jqgrid .ui-jqgrid-toppager .ui-pg-selbox {\n\tfont-size:.9em; \n\tline-height:inherit; \n\tdisplay:block; \n\theight:22px; \n\tmargin: 0; \n\tpadding: 3px 0px 3px 3px; \n\tborder:none;\n}\n.ui-jqgrid .ui-separator {\n\theight: 18px; \n\tborder : none;\n\tborder-left: 2px solid #ccc ; /*default*/\n\t\n}\n.ui-separator-li {\n\theight: 2px; \n\tborder : none;\n\tborder-top: 2px solid #ccc ;  /*default*/\n\tmargin: 0; padding: 0; width:100%\n}\n.ui-jqgrid .ui-jqgrid-pager .ui-pg-div,\n.ui-jqgrid .ui-jqgrid-toppager .ui-pg-div\n{\n\tfloat:left;\n\tposition:relative; \n}\n.ui-jqgrid .ui-jqgrid-pager .ui-pg-button,\n.ui-jqgrid .ui-jqgrid-toppager .ui-pg-button\n{ \n\tcursor:pointer; \n}\n.ui-jqgrid .ui-jqgrid-pager .ui-pg-div  span,\n.ui-jqgrid .ui-jqgrid-toppager .ui-pg-div  span\n{\n\tfloat:left;\n}\n.ui-jqgrid td input, \n.ui-jqgrid td select, \n.ui-jqgrid td textarea { \n\tmargin: 0;\n}\n.ui-jqgrid td textarea {\n\twidth:auto;\n\theight:auto;\n}\n.ui-jqgrid .ui-jqgrid-pager .ui-pager-table,\n.ui-jqgrid .ui-jqgrid-toppager .ui-pager-table\n{\n\twidth:100%;\n\ttable-layout:fixed;\n\theight:100%;\n}\n.ui-jqgrid .ui-jqgrid-pager .ui-paging-info,\n.ui-jqgrid .ui-jqgrid-toppager .ui-paging-info\n{ \n\tfont-weight: normal;\n\theight:auto; \n\tmargin-top:3px;\n\tmargin-right:4px;\n\tdisplay: inline;\n}\n.ui-jqgrid .ui-jqgrid-pager .ui-paging-pager,\n.ui-jqgrid .ui-jqgrid-toppager .ui-paging-pager\n{\n\ttable-layout:auto;\n\theight:100%;\n}\n.ui-jqgrid .ui-jqgrid-pager .navtable,\n.ui-jqgrid .ui-jqgrid-toppager .navtable\n{\n\tfloat:left;\n\ttable-layout:auto;\n\theight:100%;\n}\n.ui-jqgrid .ui-jqgrid-pager .navtable td,\n.ui-jqgrid .ui-jqgrid-toppager .navtable td \n{ \n\tpadding : 0 5px;\n}\n\n/*Subgrid*/\n\n.ui-jqgrid .ui-jqgrid-btable .ui-sgcollapsed span {\n\tdisplay: block;\n}\n.ui-jqgrid .ui-subgrid {\n\tmargin:0;\n\tpadding:0; \n\twidth:100%;\n}\n.ui-jqgrid .ui-subgrid table {\n\ttable-layout: fixed;\n}\n.ui-jqgrid .ui-subgrid tr.ui-subtblcell td {}\n.ui-jqgrid .ui-subgrid td.subgrid-data {\n\tborder-top:  0 none !important;\n}\n.ui-jqgrid .ui-subgrid td.subgrid-cell { \n\tvertical-align: middle\n}\n.ui-jqgrid a.ui-sghref {\n\ttext-decoration: none;\n\tcolor : #010101; /*default*/\n}\n.ui-jqgrid .ui-th-subgrid {height:20px;}\n.tablediv > .row { margin: 0 0}\n/* loading */\n.ui-jqgrid .loading {\n\tposition: absolute; \n\ttop: 45%;\n\tleft: 45%;\n\twidth: auto;\n\tz-index:101;\n\tpadding: 6px; \n\tmargin: 5px;\n\ttext-align: center;\n\tdisplay: none;\n\tborder: 1px solid #ddd;  /*default*/\n\tfont-size: 14px;\n\tbackground-color: #d9edf7;\n}\n.ui-jqgrid .jqgrid-overlay { \n\tdisplay:none;\n\tz-index:100;\n}\n/* IE * html .jqgrid-overlay {width: expression(this.parentNode.offsetWidth+'px');height: expression(this.parentNode.offsetHeight+'px');} */\n* .jqgrid-overlay iframe {\n\tposition:absolute;\n\ttop:0;\n\tleft:0;\n\tz-index:-1;\n}\n/* IE width: expression(this.parentNode.offsetWidth+'px');height: expression(this.parentNode.offsetHeight+'px');}*/\n/* end loading div */\n\n/* Toolbar */\n.ui-jqgrid .ui-userdata {\n\tpadding: 4px 0px; \n\toverflow: hidden; \n\tmin-height: 32px; \n}\n.ui-jqgrid .ui-userdata-top {\n\tborder-left-width: 0px;    /*default*/\n\tborder-bottom: 1px solid #ddd;\t\n}\n.ui-jqgrid .ui-userdata-bottom {\n\tborder-left-width: 0px;    /*default*/\n\tborder-top: 1px solid #ddd;\t\n}\n/*Modal Window */\n.ui-jqdialog { }\n.ui-jqdialog { \n\tdisplay: none; \n\twidth: 500px; \n\tposition: absolute; \n\t/*padding: 5px; */\n\toverflow:visible;\n}\n.ui-jqdialog .ui-jqdialog-titlebar {\n\tpadding: .1em .1em; \n\tmin-height: 35px; \n}\n.ui-jqdialog .ui-jqdialog-title { \n\tmargin: .3em 0 .2em;  \n\tfont-weight: bold;\n\tpadding-left :6px;\n\tpadding-right:6px;\n} \n.ui-jqdialog .ui-jqdialog-titlebar-close { \n\tposition: absolute;  \n\ttop: 0%; \n\tmargin: 3px 5px 0 0; \n\tpadding: 8px;  \n\tcursor:pointer;\n}\n\n.ui-jqdialog .ui-jqdialog-titlebar-close span {  }\n.ui-jqdialog .ui-jqdialog-titlebar-close:hover, \n.ui-jqdialog .ui-jqdialog-titlebar-close:focus { \n\tpadding: 8px; \n}\n.ui-jqdialog-content, .ui-jqdialog .ui-jqdialog-content { \n\tborder: 0; \n\tpadding: .3em .2em; \n\tbackground: none; \n\theight:auto;\n}\n.ui-jqdialog .ui-jqconfirm {\n\tpadding: .4em 1em; \n\tborder-width:3px;\n\tposition:absolute;\n\tbottom:10px;\n\tright:10px;\n\toverflow:visible;\n\tdisplay:none;\n\theight:120px;\n\twidth:220px;\n\ttext-align:center;\n\tbackground-color: #fff;\n\tborder-radius: 4px;\n\t-webkit-border-radius: 4px;\n\t-moz-border-radius: 4px;\n}\n.ui-jqdialog>.ui-resizable-se { }\n.ui-jqgrid>.ui-resizable-se { }\n/* end Modal window*/\n/* Form edit */\n.ui-jqdialog-content .FormGrid { \n\tmargin: 0 8px 0 8px; \n\toverflow:auto;\n\tposition:relative;\n}\n.ui-jqdialog-content .EditTable { \n\twidth: 100%; \n\tmargin-bottom:0; \n}\n.ui-jqdialog-content .DelTable { \n\twidth: 100%; \n\tmargin-bottom:0;\n}\n.EditTable td input, \n.EditTable td select, \n.EditTable td textarea { \n\twidth: 98%; \n\tdisplay: inline-block;\n}\n.EditTable td textarea { \n\twidth:auto; \n\theight:auto;\n}\n.EditTable .FormData td { \n\theight:37px !important;\n}\n.ui-jqdialog-content td.EditButton {\n\ttext-align: right; \n\tpadding: 5px 5px 5px 0;\n}\n.ui-jqdialog-content td.navButton {\n\ttext-align: center; \n\tborder-left: 0 none;\n\tborder-top: 0 none;\n\tborder-right: 0 none; \n\tpadding-bottom:5px; \n\tpadding-top:5px;\n}\n.ui-jqdialog-content input.FormElement {\n\tpadding: .5em .3em; \n\tmargin-bottom: 5px\n}\n.ui-jqdialog-content select.FormElement {\n\tpadding:.3em; \n\tmargin-bottom: 3px;\n}\n.ui-jqdialog-content .data-line {\n\tpadding-top:.1em;\n\tborder: 0 none;\n}\n\n.ui-jqdialog-content .CaptionTD {\n\tvertical-align: middle;\n\tborder: 0 none; \n\tpadding: 2px;\n\twhite-space: nowrap;\n}\n.ui-jqdialog-content .DataTD {\n\tpadding: 2px; \n\tborder: 0 none; \n\tvertical-align: top;\n}\n.ui-jqdialog-content .form-view-data {\n\twhite-space:pre\n}\n.fm-button {  }\n.fm-button-icon-left { \n\tmargin-left: 4px; \n\tmargin-right: 4px;  \n}\n.fm-button-icon-right { \n\tmargin-left: 4px; \n\tmargin-right: 4px; \n}\n.fm-button-icon-left  {  }\n.fm-button-icon-right  { }\n#nData, #pData { \n\tmargin-left: 4px; \n\tmargin-right: 4px; \n}\n#sData span, #cData span { \n\tmargin-left: 5px;\n}\n/* End Eorm edit */\n/*.ui-jqgrid .edit-cell {}*/\n.ui-jqgrid .selected-row, \ndiv.ui-jqgrid .selected-row td {\n\tfont-style : normal;\n}\n/* inline edit actions button*/\n.ui-inline-del, .ui-inline-cancel {\n    margin-left: 14px;\n}\n.ui-jqgrid .inline-edit-cell {}\n/* Tree Grid */\n.ui-jqgrid .tree-wrap {\n\tfloat: left; \n\tposition: relative;\n\theight: 18px;\n\twhite-space: nowrap;\n\toverflow: hidden;\n}\n.ui-jqgrid .tree-minus {\n\tposition: absolute; \n\theight: 18px; \n\twidth: 18px; \n\toverflow: hidden;\n}\n.ui-jqgrid .tree-plus {\n\tposition: absolute;\t\n\theight: 18px; \n\twidth: 18px;\t\n\toverflow: hidden;\n}\n.ui-jqgrid .tree-leaf {\n\tposition: absolute;\t\n\theight: 18px; \n\twidth: 18px;\n\toverflow: hidden;\n}\n.ui-jqgrid .treeclick {\n\tcursor: pointer;\n}\n/* moda dialog */\n* iframe.jqm {\n\tposition:absolute;\n\ttop:0;\n\tleft:0;\n\tz-index:-1;\n}\n/*\t width: expression(this.parentNode.offsetWidth+'px');height: expression(this.parentNode.offsetHeight+'px');}*/\n.ui-jqgrid-dnd tr td {\n\tborder-right-width: 1px;\n\tborder-right-color: inherit;\n\tborder-right-style: solid; \n\theight:20px\n}\n/* RTL Support */\n.ui-jqgrid .ui-jqgrid-caption-rtl {\n\ttext-align: right;\n}\n.ui-jqgrid .ui-jqgrid-hbox-rtl {\n\tfloat: right; \n\t/*padding-left: 20px;*/\n}\n.ui-jqgrid .ui-jqgrid-resize-ltr {\n\tfloat: right;\n\tmargin: -2px -2px -2px 0;\n\theight:100%;\n}\n.ui-jqgrid .ui-jqgrid-resize-rtl {\n\tfloat: left;\n\tmargin: -2px -2px -2px -0px;\n}\n.ui-jqgrid .ui-sort-rtl {\n\t\n}\n.ui-jqgrid .tree-wrap-ltr {\n\tfloat: left;\n}\n.ui-jqgrid .tree-wrap-rtl {\n\tfloat: right;\n}\n.ui-jqgrid .ui-ellipsis {\n\t-moz-text-overflow:ellipsis;\n\ttext-overflow:ellipsis;\n}\n/* Toolbar Search Menu. Nav menu */\n.ui-search-menu, \n.ui-nav-menu {\n\tposition: absolute; \n\tpadding: 2px 5px; \n\tz-index:99999;\n}\n.ui-search-menu.ui-menu .ui-menu-item,\n.ui-nav-menu.ui-menu .ui-menu-item\n{ \n\tlist-style-image: none; \n\tpadding-right: 0; \n\tpadding-left: 0; \n}\n.ui-search-menu.ui-menu .ui-menu-item a, \n.ui-nav-menu.ui-menu .ui-menu-item a \n{ \n\tdisplay: block; \n}\n.ui-search-menu.ui-menu .ui-menu-item a.g-menu-item:hover,\n.ui-nav-menu.ui-menu .ui-menu-item a.g-menu-item:hover \n{ \n\tmargin: -1px; \n\tfont-weight: normal; \n}\n.ui-jqgrid .ui-search-table { \n\tpadding: 0; \n\tborder: 0 none; \n\theight:20px; \n\twidth:100%;\n}\n.ui-jqgrid .ui-search-table .ui-search-oper { \n\twidth:20px; \n}\na.g-menu-item, a.soptclass, a.clearsearchclass { \n\tcursor: pointer; \n} \n.ui-jqgrid .ui-jqgrid-view input,\n.ui-jqgrid .ui-jqgrid-view select,\n.ui-jqgrid .ui-jqgrid-view textarea,\n.ui-jqgrid .ui-jqgrid-view button {\n    /*font-size: 11px*/\n}\n.ui-jqgrid .ui-scroll-popup {\n\twidth: 100px;\n}\n.ui-search-table select,\n.ui-search-table input \n{\n\tpadding: 4px 3px;\n}\n\t\n.ui-disabled {\n\topacity: .35;\n\tfilter:Alpha(Opacity=35); /* support: IE8 */\n\tbackground-image: none;\n}\n.ui-overlay {\n\tposition: fixed;\n\ttop: 0;\n\tleft: 0;\n\twidth: 100%;\n\theight: 100%;\n\tbackground-color: rgba(0,0,0,0.5);\n\topacity: .3;\n\tfilter: Alpha(Opacity=30); /* support: IE8 */\n}\n \n.ui-jqgrid-pager .ui-pg-table .ui-pg-button:hover,\n.ui-jqgrid-toppager .ui-pg-table .ui-pg-button:hover\n{\n\tbackground-color: #ddd;\n}\n.ui-jqgrid-corner  {\n\t border-radius: 5px\n}\n.ui-resizable-handle {\n\t/*position: absolute;*/\n\tdisplay: block;\n\tleft :97%;\n}\n.ui-jqdialog .ui-resizable-se {\n\twidth: 12px;\n\theight: 12px;\n\tright: -5px;\n\tbottom: -5px;\n\tbackground-position: 16px 16px;\n}\n.ui-resizable-se {\n\tcursor: se-resize;\n\twidth: 12px;\n\theight: 12px;\n\tright: 1px;\n\tbottom: 1px;\n}\n.ui-top-corner {\n\tborder-top-left-radius: 5px;\n\tborder-top-right-radius: 5px;\n}\n.ui-bottom-corner {\n\tborder-bottom-left-radius: 5px;\n\tborder-bottom-right-radius: 5px;\n}\n\n.ui-search-table {\n\tmargin-bottom: 0;\n}\n.ui-search-table .columns, .ui-search-table .operators {\n\tpadding-right: 5px;\n}\n.opsel {\n\tfloat :left;\n\twidth : 100px;\n\tmargin-right : 5px;\n}\n.add-group, .add-rule, .delete-group {\n\twidth: 14%;\t\n\tmargin-right : 5px;\n}\n.delete-rule {\n\twidth : 15px;\n}\nul.ui-search-menu, ul.ui-nav-menu {\n\t list-style-type:  none;\n}\nul.ui-search-menu li a, \nul.ui-nav-menu li a,\n.soptclass, \n.clearsearchclass {\n\ttext-decoration: none;\n\tcolor : #010101;\n}\nul.ui-search-menu li a:hover, ul.ui-nav-menu li a:hover, a.soptclass:hover, a.clearsearchclass:hover {\n\tbackground-color: #ddd;\n\tpadding: 1px 1px;\n\ttext-decoration: none;\n}\nul.ui-search-menu li, ul.ui-nav-menu li {\n\tpadding : 5px 5px;\n}\n.ui-menu-item hr {\n\tmargin-bottom: 0px;\n\tmargin-top:0px;\n}\n\n.searchFilter .ui-search-table td,\n.searchFilter .ui-search-table th\n{\n\tborder-top: 0px none !important;\n}\n\n.searchFilter .queryresult {\n\tmargin-bottom: 5px;\n}\n.searchFilter .queryresult tr td{\n\tborder-top: 0px none;\n}\n.ui-search-label { \n\tpadding-left: 5px;\n}\n\n.frozen-div, .frozen-bdiv {\n\tbackground-color: #fff;\n}\n/*\n.ui-jqgrid .ui-jqgrid-caption,\n.ui-jqgrid .ui-jqgrid-pager,\n.ui-jqgrid .ui-jqgrid-toppager,\n.ui-jqgrid .ui-jqgrid-htable thead th,\n.ui-jqgrid .ui-userdata-top,\n.ui-jqgrid .ui-userdata-bottom,\n.ui-jqgrid .ui-jqgrid-hdiv,\n.ui-jqdialog .ui-jqdialog-titlebar\n{\n    background-image: none, linear-gradient(to bottom, #fff 0px, #e0e0e0 100%);\n    background-repeat: repeat-x;\n    border-color: #ccc;\n    text-shadow: 0 1px 0 #fff;\n}\n*/\n/* Column menu */\n.ui-jqgrid .ui-jqgrid-htable .colmenu {\n\tposition:absolute;\n\tright:1px;\n\theight:100%;\n\tcolor : black;\n}\n.ui-jqgrid .ui-jqgrid-htable .colmenu-rtl {\n\tright: auto;\n\tleft : 1px;\n}\n.ui-jqgrid .ui-jqgrid-htable .colmenuspan {\n\tdisplay:inline-block;\n}\n\n.ui-jqgrid .ui-jqgrid-htable .ui-th-div {\n\theight:17px;\n\tmargin-top:5px;\n\tdisplay:inine-block;\n}\n.column-menu, .ui-search-menu {\n\tpadding: 10px 15px;\n}\n.column-menu .divider {\n\tbackground-color: #e5e5e5; \n\theight: 1px;\n\tpadding:0 0;\n\tmargin: 5px 0;  \n\toverflow: hidden;\n}\n.ui-menu-item .ui-common-table .menu_icon {\n\tpadding-right: 8px;\n\tpadding-left: 8px;\n}\ntd.menu_text {\n\twidth: auto;\n\tpadding-left: 1px;\n\twhite-space: nowrap;\n}\n#search_menu .ui-menu-item div {\n\tpadding: 3px 0;\n\twhite-space: nowrap;\n}\n\n#search_menu  .search_buttons {\n\tdisplay:inline-block;\n\twidth:50%;\n\tpadding: 3px 3px;\n}\n.search_buttons .btn-default:hover {\n\tpadding-bottom: 6px;\n\tpadding-top: 6px;\n}\n.search_buttons #bs_reset {\n\tmargin-right: 3px;\n}\n.search_buttons #bs_search {\n\tmargin-left: 3px;\n}"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/plugins/jqgrid/ui.jqgrid.css",
    "content": "/*Grid*/\n.ui-jqgrid {\n\tposition: relative;\n\t-moz-box-sizing: content-box; \n\t-webkit-box-sizing: content-box; \n\tbox-sizing: content-box;\n}\n.ui-jqgrid .ui-jqgrid-view {position: relative;left:0; top: 0; padding: 0; font-size:11px; z-index:100;}\n.ui-jqgrid .ui-common-table {border-width: 0px; border-style: none; border-spacing: 0px; padding: 0;}\n/* caption*/\n.ui-jqgrid .ui-jqgrid-titlebar {height:19px; padding: .3em .2em .2em .3em; position: relative; font-size: 12px; border-left: 0 none;border-right: 0 none; border-top: 0 none;}\n.ui-jqgrid .ui-jqgrid-caption {text-align: left;}\n.ui-jqgrid .ui-jqgrid-title { margin: .1em 0 .2em; }\n.ui-jqgrid .ui-jqgrid-titlebar-close { position: absolute;top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height:18px; cursor:pointer;}\n.ui-jqgrid .ui-jqgrid-titlebar-close span { display: block; margin: 1px; }\n.ui-jqgrid .ui-jqgrid-titlebar-close:hover { padding: 0; }\n/* header*/\n.ui-jqgrid .ui-jqgrid-hdiv {position: relative; margin: 0;padding: 0; overflow: hidden; border-left: 0 none !important; border-top : 0 none !important; border-right : 0 none !important;}\n.ui-jqgrid .ui-jqgrid-hbox {float: left; padding-right: 20px;}\n.ui-jqgrid .ui-jqgrid-htable {table-layout:fixed;margin:0;border-collapse: separate;}\n.ui-jqgrid .ui-jqgrid-htable th { height: 27px; padding: 0 2px 0 2px;}\n.ui-jqgrid .ui-jqgrid-htable th div {overflow: hidden; position:relative;margin: .1em 0em .1em 0em;}\n.ui-th-column, .ui-jqgrid .ui-jqgrid-htable th.ui-th-column {overflow: hidden;white-space: nowrap;text-align:center;border-top : 0 none;border-bottom : 0 none;}\n.ui-th-column-header, .ui-jqgrid .ui-jqgrid-htable th.ui-th-column-header {overflow: hidden;white-space: nowrap;text-align:center;border-top : 0 none; height: 26px;}\n.ui-th-ltr, .ui-jqgrid .ui-jqgrid-htable th.ui-th-ltr {border-left : 0 none;}\n.ui-th-rtl, .ui-jqgrid .ui-jqgrid-htable th.ui-th-rtl {border-right : 0 none;}\n.ui-first-th-ltr {border-right: 1px solid; }\n.ui-first-th-rtl {border-left: 1px solid; }\n.ui-jqgrid .ui-th-div-ie {white-space: nowrap; zoom :1; height:17px;}\n.ui-jqgrid .ui-jqgrid-resize {height:20px !important;position: relative; cursor :e-resize;display: inline;overflow: hidden;}\n.ui-jqgrid .ui-grid-ico-sort {overflow:hidden;position:absolute;display:inline; cursor: pointer !important;}\n.ui-jqgrid .ui-icon-asc {margin-top:-3px; height:12px;}\n.ui-jqgrid .ui-icon-desc {margin-top:3px;margin-left:-1px;height:12px;}\n.ui-jqgrid .ui-i-asc {margin-top:0;height:18px;}\n.ui-jqgrid .ui-i-desc {margin-top:0;margin-left:12px;height:18px;}\n.ui-jqgrid .ui-single-sort-asc {margin-top:0;height:18px;}\n.ui-jqgrid .ui-single-sort-desc {margin-top:-1px;height:18px;}\n.ui-jqgrid .ui-jqgrid-sortable {cursor:pointer;height:14px}\n.ui-jqgrid tr.ui-search-toolbar th { }\n.ui-jqgrid .ui-search-table td.ui-search-clear { width:25px;}\n.ui-jqgrid tr.ui-search-toolbar td > input { padding-right: 0px; width: 95%;}\n.ui-jqgrid tr.ui-search-toolbar select {}\n/* body */ \n.ui-jqgrid .ui-jqgrid-bdiv {position: relative; margin: 0; padding:0; overflow: auto; text-align:left;z-index: 101;}\n.ui-jqgrid .ui-jqgrid-btable {table-layout:fixed; margin:0; outline-style: none; border-collapse: separate;}\n.ui-jqgrid tr.jqgrow { outline-style: none; }\n.ui-jqgrid tr.jqgroup { outline-style: none; }\n.ui-jqgrid tr.jqgrow td {font-weight: normal; overflow: hidden; white-space: pre; height: 23px;padding: 1px 2px 1px 2px;border-bottom-width: 1px; border-bottom-color: inherit; border-bottom-style: solid;}\n.ui-jqgrid tr.jqgfirstrow td {padding: 0 2px 0 2px;border-right-width: 1px; border-right-style: solid; height:auto;}\n.ui-jqgrid tr.jqgroup td {font-weight: normal; overflow: hidden; white-space: pre; height: 22px;padding: 0 2px 0 2px;border-bottom-width: 1px; border-bottom-color: inherit; border-bottom-style: solid;}\n.ui-jqgrid tr.jqfoot td {font-weight: bold; overflow: hidden; white-space: pre; height: 22px;padding: 0 2px 0 2px;border-bottom-width: 1px; border-bottom-color: inherit; border-bottom-style: solid;}\n.ui-jqgrid tr.ui-row-ltr td {text-align:left;border-right-width: 1px; border-right-color: inherit; border-right-style: solid;}\n.ui-jqgrid tr.ui-row-rtl td {text-align:right;border-left-width: 1px; border-left-color: inherit; border-left-style: solid;}\n.ui-jqgrid td.jqgrid-rownum { padding: 0 2px 0 2px; margin: 0; border: 0 none;}\n.ui-jqgrid .ui-jqgrid-resize-mark { width:2px; left:0; background-color:#777; cursor: e-resize; cursor: col-resize; position:absolute; top:0; height:100px; overflow:hidden; display:none; border:0 none; z-index: 99999;}\n/* footer */\n.ui-jqgrid .ui-jqgrid-sdiv {position: relative; margin: 0;padding: 0; overflow: hidden; border-left: 0 none !important; border-top : 0 none !important; border-right : 0 none !important;}\n.ui-jqgrid .ui-jqgrid-ftable {table-layout:fixed; margin-bottom:0;border-collapse: separate;}\n.ui-jqgrid tr.footrow td {font-weight: bold; overflow: hidden; white-space:nowrap; height: 20px;padding: 0 2px 0 2px;border-top-width: 1px; border-top-color: inherit; border-top-style: solid;border-bottom-width: 1px; border-bottom-color: inherit; border-bottom-style: solid;}\n.ui-jqgrid tr.footrow-ltr td {text-align:left;border-right-width: 1px; border-right-color: inherit; border-right-style: solid;}\n.ui-jqgrid tr.footrow-rtl td {text-align:right;border-left-width: 1px; border-left-color: inherit; border-left-style: solid;}\n/* Pager*/\n.ui-jqgrid .ui-jqgrid-pager { border-left: 0 none !important;border-right: 0 none !important; border-bottom: 0 none !important; border-top: 0 none; margin: 0 !important; padding: 0 !important; position: relative; height: auto; min-height: 28px; white-space: nowrap;overflow: hidden;font-size:11px; z-index:101}\n.ui-jqgrid .ui-jqgrid-toppager .ui-pager-control, .ui-jqgrid .ui-jqgrid-pager .ui-pager-control {position: relative;border-left: 0;border-bottom: 0;border-top: 0; height: 28px;}\n.ui-jqgrid .ui-pg-table {position: relative; padding: 1px 0; width:auto; margin: 0;}\n.ui-jqgrid .ui-pg-table td {font-weight:normal; vertical-align:middle; padding:0px 1px;}\n.ui-jqgrid .ui-pg-button  { height:auto}\n.ui-jqgrid .ui-pg-button span { display: block; margin: 2px; float:left;}\n.ui-jqgrid .ui-pg-button:hover { padding: 0;}\n.ui-jqgrid .ui-state-disabled:hover {padding:0px;}\n.ui-jqgrid .ui-pg-input,.ui-jqgrid .ui-jqgrid-toppager .ui-pg-input { height:14px;width: auto;font-size:.9em; margin:0;line-height: inherit;border: none; padding: 3px 2px}\n.ui-jqgrid .ui-pg-selbox, .ui-jqgrid .ui-jqgrid-toppager .ui-pg-selbox {font-size:.9em; line-height:inherit; display:block; height:19px; margin: 0; padding: 3px 0px; border:none;}\n.ui-jqgrid .ui-separator {height: 18px; border-left: 2px solid #ccc ;}\n.ui-separator-li {height: 2px; border : none;border-top: 2px solid #ccc ; margin: 0; padding: 0; width:100%}\n.ui-jqgrid  .dropdownmenu {\n\tpadding: 3px 0 3px 0;\n\tmargin-left: 4px;\n}\n.ui-jqgrid .ui-jqgrid-pager .ui-pg-div,\n.ui-jqgrid .ui-jqgrid-toppager .ui-pg-div\n{padding:1px 0;float:left;position:relative; line-height: 20px;}\n.ui-jqgrid .ui-jqgrid-pager .ui-pg-button,\n.ui-jqgrid .ui-jqgrid-toppager .ui-pg-button\n{ cursor:pointer; }\n.ui-jqgrid .ui-jqgrid-pager .ui-pg-div  span.ui-icon,\n.ui-jqgrid .ui-jqgrid-toppager .ui-pg-div  span.ui-icon\n{float:left;margin: 2px; width:18px;}\n.ui-jqgrid td input, .ui-jqgrid td select, .ui-jqgrid td textarea { margin: 0; padding-top:5px;padding-bottom: 5px;}\n.ui-jqgrid td textarea {width:auto;height:auto;}\n.ui-jqgrid .ui-jqgrid-toppager {border-left: 0 none !important;border-right: 0 none !important; border-top: 0 none !important; margin: 0 !important; padding: 0 !important; position: relative;white-space: nowrap;overflow: hidden;}\n.ui-jqgrid .ui-jqgrid-pager .ui-pager-table,\n.ui-jqgrid .ui-jqgrid-toppager .ui-pager-table \n{\n\twidth:100%;\n\ttable-layout:fixed;\n\theight:100%;\n}\n.ui-jqgrid .ui-jqgrid-pager .ui-paging-info,\n.ui-jqgrid .ui-jqgrid-toppager .ui-paging-info\n{ \n\tfont-weight: normal;\n\theight:auto; \n\tmargin-top:3px;\n\tmargin-right:4px;\n\tdisplay: inline;\n}\n.ui-jqgrid .ui-jqgrid-pager .ui-paging-pager,\n.ui-jqgrid .ui-jqgrid-toppager .ui-paging-pager\n{\n\ttable-layout:auto;\n\theight:100%;\n}\n.ui-jqgrid .ui-jqgrid-pager .navtable,\n.ui-jqgrid .ui-jqgrid-toppager .navtable\n{\n\tfloat:left;\n\ttable-layout:auto;\n\theight:100%;\n}\n\n/*.ui-jqgrid .ui-jqgrid-toppager .ui-pg-div {padding:1px 0;float:left;position:relative; line-height: 20px; margin-right:3px;}\n.ui-jqgrid .ui-jqgrid-toppager .ui-pg-button { cursor:pointer; }\n.ui-jqgrid .ui-jqgrid-toppager .ui-pg-div  span.ui-icon {float:left;margin: 2px; width:18px;}\n*/\n\n/*subgrid*/\n.ui-jqgrid .ui-jqgrid-btable .ui-sgcollapsed span {display: block;}\n.ui-jqgrid .ui-subgrid {margin:0;padding:0; width:100%;}\n.ui-jqgrid .ui-subgrid table {table-layout: fixed;}\n.ui-jqgrid .ui-subgrid tr.ui-subtblcell td {height:18px;border-right-width: 1px; border-right-color: inherit; border-right-style: solid;border-bottom-width: 1px; border-bottom-color: inherit; border-bottom-style: solid;}\n.ui-jqgrid .ui-subgrid td.subgrid-data {border-top:  0 none !important; border-left: 0 none !important;}\n.ui-jqgrid .ui-subgrid td.subgrid-cell {border-width: 0 1px 1px 0;}\n.ui-jqgrid .ui-th-subgrid {height:20px;}\n/* loading */\n.ui-jqgrid .loading {position: absolute; top: 45%;left: 45%;width: auto;z-index:101;padding: 6px; margin: 5px;text-align: center;font-weight: bold;display: none;border-width: 2px !important; font-size:11px;}\n.ui-jqgrid .jqgrid-overlay {display:none;z-index:100;}\n/* IE * html .jqgrid-overlay {width: expression(this.parentNode.offsetWidth+'px');height: expression(this.parentNode.offsetHeight+'px');} */\n* .jqgrid-overlay iframe {position:absolute;top:0;left:0;z-index:-1;}\n/* IE width: expression(this.parentNode.offsetWidth+'px');height: expression(this.parentNode.offsetHeight+'px');}*/\n/* end loading div */\n/* toolbar */\n.ui-jqgrid .ui-userdata {border-left: 0 none;    border-right: 0 none;\theight : 27px;overflow: hidden;\t}\n/*Modal Window */\n.ui-jqdialog { font-size:11px !important; }\n.ui-jqdialog { display: none; width: 300px; position: absolute; padding: .2em; font-size:11px; overflow:visible;}\n.ui-jqdialog .ui-jqdialog-titlebar { padding: .3em .2em; position: relative; height:20px;}\n.ui-jqdialog .ui-jqdialog-title { margin: .3em .2em .2em .2em;} \n.ui-jqdialog .ui-jqdialog-titlebar-close { position: absolute;  top: 50%; width: 19px; margin: -12px 0 0 0; padding: 1px; height: 18px; cursor:pointer;}\n\n.ui-jqdialog .ui-jqdialog-titlebar-close span { display: block; margin: 1px; }\n.ui-jqdialog .ui-jqdialog-titlebar-close:hover, .ui-jqdialog .ui-jqdialog-titlebar-close:focus { padding: 0; }\n.ui-jqdialog-content, .ui-jqdialog .ui-jqdialog-content { border: 0; padding: .3em .2em; background: none; height:auto;}\n.ui-jqdialog .ui-jqconfirm {padding: .4em 1em; border-width:3px;position:absolute;bottom:10px;right:10px;overflow:visible;display:none;height:80px;width:220px;text-align:center;}\n.ui-jqdialog>.ui-resizable-se { bottom: -3px; right: -3px}\n.ui-jqgrid>.ui-resizable-se { bottom: -3px; right: -3px }\n/* end Modal window*/\n/* Form edit */\n.ui-jqdialog-content .FormGrid {margin: 0; overflow:auto;position:relative;}\n.ui-jqdialog-content .EditTable { width: 100%; margin-bottom:0;}\n.ui-jqdialog-content .DelTable { width: 100%; margin-bottom:0;}\n.EditTable td input, .EditTable td select, .EditTable td textarea {margin: 0;}\n.EditTable td textarea { width:auto; height:auto;}\n.ui-jqdialog-content td.EditButton {text-align: right;border-top: 0 none;border-left: 0 none;border-right: 0 none; padding-bottom:5px; padding-top:5px;}\n.ui-jqdialog-content td.navButton {text-align: center; border-left: 0 none;border-top: 0 none;border-right: 0 none; padding-bottom:5px; padding-top:5px;}\n.ui-jqdialog-content input.FormElement {padding: .5em .3em; margin-bottom: 3px}\n.ui-jqdialog-content select.FormElement {padding:.3em; margin-bottom: 3px;}\n.ui-jqdialog-content .data-line {padding-top:.1em;border: 0 none;}\n\n.ui-jqdialog-content .CaptionTD {vertical-align: middle;border: 0 none; padding: 2px;white-space: nowrap;}\n.ui-jqdialog-content .DataTD {padding: 2px; border: 0 none; vertical-align: top;}\n.ui-jqdialog-content .form-view-data {white-space:pre}\n.fm-button { height: 18px; display: inline-block; margin:2px 4px 0 0; padding: .6em .5em .2em .5em; text-decoration:none !important; cursor:pointer; position: relative; text-align: center; zoom: 1; }\n.fm-button-icon-left { padding-left: 1.9em; }\n.fm-button-icon-right { padding-right: 1.9em; }\n.fm-button-icon-left .ui-icon { right: auto; left: .2em; margin-left: 0; position: absolute; top: 50%; margin-top: -8px; }\n.fm-button-icon-right .ui-icon { left: auto; right: .2em; margin-left: 0; position: absolute; top: 50%; margin-top: -8px;}\n#nData, #pData { float: left; margin:3px;padding: 0; width: 15px; }\n.ViewTable {\n\tborder-width: 0; \n\tborder-style: none; \n\tborder-spacing: 1px;\n\tpadding: 4px;\n\ttable-layout: fixed;\n}\n.ViewTable .CaptionTD, .ViewTable .DataTD {padding : 4px;} \n/* End Eorm edit */\n/*cell edit*/\n.ui-jqgrid .edit-cell {\n\tpadding: 4px 0px 4px 4px;\n}\n.ui-jqgrid .selected-row, div.ui-jqgrid .selected-row td {font-style : normal;border-left: 0 none;}\n/* inline edit actions button*/\n.ui-inline-del.ui-state-hover span, .ui-inline-edit.ui-state-hover span,\n.ui-inline-save.ui-state-hover span, .ui-inline-cancel.ui-state-hover span {\n    margin: -1px;\n}\n.ui-inline-del, .ui-inline-cancel {\n    margin-left: 8px;\n}\n\n.ui-jqgrid .inline-edit-cell {\n\tpadding: 4px 0px 4px 4px;\n}\n/* Tree Grid */\n.ui-jqgrid .tree-wrap {float: left; position: relative;height: 18px;white-space: nowrap;overflow: hidden;}\n.ui-jqgrid .tree-minus {position: absolute; height: 18px; width: 18px; overflow: hidden;}\n.ui-jqgrid .tree-plus {position: absolute;\theight: 18px; width: 18px;\toverflow: hidden;}\n.ui-jqgrid .tree-leaf {position: absolute;\theight: 18px; width: 18px;overflow: hidden;}\n.ui-jqgrid .treeclick {cursor: pointer;}\n/* moda dialog */\n* iframe.jqm {position:absolute;top:0;left:0;z-index:-1;}\n/*\t width: expression(this.parentNode.offsetWidth+'px');height: expression(this.parentNode.offsetHeight+'px');}*/\n.ui-jqgrid-dnd tr td {border-right-width: 1px; border-right-color: inherit; border-right-style: solid; height:20px}\n/* RTL Support */\n.ui-jqgrid .ui-jqgrid-caption-rtl {text-align: right;}\n.ui-jqgrid .ui-jqgrid-hbox-rtl {float: right;}\n.ui-jqgrid .ui-jqgrid-resize-ltr {float: right;margin: -2px -2px -2px 0;}\n.ui-jqgrid .ui-jqgrid-resize-rtl {float: left;margin: -2px 0 -1px -3px;}\n.ui-jqgrid .ui-sort-rtl {left:0;}\n.ui-jqgrid .tree-wrap-ltr {float: left;}\n.ui-jqgrid .tree-wrap-rtl {float: right;}\n.ui-jqgrid .ui-ellipsis {-moz-text-overflow:ellipsis;text-overflow:ellipsis;}\n\n/* Toolbar Search Menu , Nav menu*/\n.ui-search-menu, \n.ui-nav-menu {\n\tposition: absolute; \n\tpadding: 2px 5px; \n\tz-index:99999;\n\t-webkit-box-shadow: 7px 7px 5px 0px rgba(50, 50, 50, 0.75);\n\t-moz-box-shadow:    7px 7px 5px 0px rgba(50, 50, 50, 0.75);\n\tbox-shadow:         7px 7px 5px 0px rgba(50, 50, 50, 0.75);\n}\n.ui-search-menu.ui-menu .ui-menu-item,\n.ui-nav-menu.ui-menu .ui-menu-item\n{ \n\tlist-style-image: none; \n\tpadding-right: 0; \n\tpadding-left: 0; \n}\n.ui-search-menu.ui-menu .ui-menu-item a, \n.ui-nav-menu.ui-menu .ui-menu-item a \n{ \n\tdisplay: block; \n}\n.ui-search-menu.ui-menu .ui-menu-item a.g-menu-item:hover,\n.ui-nav-menu.ui-menu .ui-menu-item a.g-menu-item:hover \n{ \n\tmargin: -1px; \n\tfont-weight: normal; \n}\n.ui-jqgrid .ui-search-table { padding: 0; border: 0 none; height:20px; width:100%;}\n.ui-jqgrid .ui-search-table .ui-search-oper { width:20px; }\na.g-menu-item, a.soptclass, a.clearsearchclass { cursor: pointer; } \n.ui-jqgrid .ui-jqgrid-view input,\n.ui-jqgrid .ui-jqgrid-view select,\n.ui-jqgrid .ui-jqgrid-view textarea,\n.ui-jqgrid .ui-jqgrid-view button {\n    font-size: 11px;\n}\n.ui-jqgrid .ui-scroll-popup {width: 95px;}\n.ui-search-table select,\n.ui-search-table input \n{\n\tpadding: 4px 3px;\n}\n\n.ui-jqgrid .ui-pg-table .ui-pg-button.ui-state-disabled:hover > .ui-separator {\n\tmargin-left: 3px;\n\tmargin-right: 3px;\n}\n\n.ui-jqgrid .ui-pg-table .ui-pg-button.ui-state-disabled:hover > .ui-pg-div > .ui-icon {\n\tmargin-left: 3px;\n\tmargin-right: 3px;\n}\n/* Column menu */\n.ui-jqgrid .ui-jqgrid-htable .colmenu {\n\tposition:absolute;\n\tright:1px;\n\theight:100%;\n\tcolor : black;\n}\n.ui-jqgrid .ui-jqgrid-htable .colmenu-rtl {\n\tright:auto;\n\tleft : 1px;\n}\n.ui-jqgrid .ui-jqgrid-htable .colmenuspan {\n\tdisplay:inline-block;\n}\n\n.ui-jqgrid .ui-jqgrid-htable .ui-th-div {\n\theight:17px;\n\tmargin-top:5px;\n\tdisplay:inine-block;\n}\n.column-menu, .ui-search-menu {\n\tpadding: 10px 10px;\n}\n.column-menu .divider {\n\tbackground-color: #e5e5e5; \n\theight: 1px;\n\tpadding:0 0;\n\tmargin: 5px 0;  \n\toverflow: hidden;\n}\n.ui-menu-item .ui-common-table .menu_icon {\n\twhite-space: pre;\n\tpadding-right: 4px;\n\tpadding-left: 4px;\n\twidth : auto;\n}\n.ui-menu-item .ui-common-table .menu_icon .ui-icon {\n\tdisplay : inline-block;\n\tposition: relative;\n}\ntd.menu_text {\n\twidth: auto;\n\twhite-space: nowrap;\n}\n.ui-search-menu .ui-menu-item {\n\tpadding : 0 0;\n}\n.ui-col-menu .ui-menu-item td.menu_text{\n\tpadding-top: 0;\n\tpadding-bottom: 0;\n\tpadding-left : 1px;\n}\n.ui-col-menu .ui-menu-item td.menu_icon{\n\tpadding-top: 0;\n\tpadding-bottom: 0;\n\tvertical-align: middle;\n}\n.ui-col-menu .ui-menu-item td.menu_icon input{\n\tmargin: 2px 0;\n\t\n}\n#search_menu .ui-menu-item div {\n\tmargin: 3px 0;\n\twhite-space: nowrap;\n}\n\n#search_menu .ui-menu-item div input,\n#search_menu .ui-menu-item div select\n{\n\tpadding: 3px 2px;\n}\n#search_menu  .search_buttons {\n\tdisplay:inline-block;\n\twidth:50%;\n}\n#column_menu.ui-menu .ui-menu-item {\n\tposition :static;\n}"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/plugins/layer/layer.js",
    "content": "/*! layer-v3.0.1 Web弹层组件 MIT License  http://layer.layui.com/  By 贤心 */\n ;!function(e,t){\"use strict\";var i,n,a=e.layui&&layui.define,o={getPath:function(){var e=document.scripts,t=e[e.length-1],i=t.src;if(!t.getAttribute(\"merge\"))return i.substring(0,i.lastIndexOf(\"/\")+1)}(),config:{},end:{},minIndex:0,minLeft:[],btn:[\"&#x786E;&#x5B9A;\",\"&#x53D6;&#x6D88;\"],type:[\"dialog\",\"page\",\"iframe\",\"loading\",\"tips\"]},r={v:\"3.0.1\",ie:function(){var t=navigator.userAgent.toLowerCase();return!!(e.ActiveXObject||\"ActiveXObject\"in e)&&((t.match(/msie\\s(\\d+)/)||[])[1]||\"11\")}(),index:e.layer&&e.layer.v?1e5:0,path:o.getPath,config:function(e,t){return e=e||{},r.cache=o.config=i.extend({},o.config,e),r.path=o.config.path||r.path,\"string\"==typeof e.extend&&(e.extend=[e.extend]),o.config.path&&r.ready(),e.extend?(a?layui.addcss(\"modules/layer/\"+e.extend):r.link(\"skin/\"+e.extend),this):this},link:function(t,n,a){if(r.path){var o=i(\"head\")[0],l=document.createElement(\"link\");\"string\"==typeof n&&(a=n);var s=(a||t).replace(/\\.|\\//g,\"\"),f=\"layuicss-\"+s,c=0;l.rel=\"stylesheet\",l.href=r.path+t,l.id=f,i(\"#\"+f)[0]||o.appendChild(l),\"function\"==typeof n&&!function d(){return++c>80?e.console&&console.error(\"layer.css: Invalid\"):void(1989===parseInt(i(\"#\"+f).css(\"width\"))?n():setTimeout(d,100))}()}},ready:function(e){var t=\"skinlayercss\",i=\"1110\";return a?layui.addcss(\"modules/layer/default/layer.css?v=\"+r.v+i,e,t):r.link(\"skin/default/layer.css?v=\"+r.v+i,e,t),this},alert:function(e,t,n){var a=\"function\"==typeof t;return a&&(n=t),r.open(i.extend({content:e,yes:n},a?{}:t))},confirm:function(e,t,n,a){var l=\"function\"==typeof t;return l&&(a=n,n=t),r.open(i.extend({content:e,btn:o.btn,yes:n,btn2:a},l?{}:t))},msg:function(e,n,a){var l=\"function\"==typeof n,f=o.config.skin,c=(f?f+\" \"+f+\"-msg\":\"\")||\"layui-layer-msg\",d=s.anim.length-1;return l&&(a=n),r.open(i.extend({content:e,time:3e3,shade:!1,skin:c,title:!1,closeBtn:!1,btn:!1,resize:!1,end:a},l&&!o.config.skin?{skin:c+\" layui-layer-hui\",anim:d}:function(){return n=n||{},(n.icon===-1||n.icon===t&&!o.config.skin)&&(n.skin=c+\" \"+(n.skin||\"layui-layer-hui\")),n}()))},load:function(e,t){return r.open(i.extend({type:3,icon:e||0,resize:!1,shade:.01},t))},tips:function(e,t,n){return r.open(i.extend({type:4,content:[e,t],closeBtn:!1,time:3e3,shade:!1,resize:!1,fixed:!1,maxWidth:210},n))}},l=function(e){var t=this;t.index=++r.index,t.config=i.extend({},t.config,o.config,e),document.body?t.creat():setTimeout(function(){t.creat()},50)};l.pt=l.prototype;var s=[\"layui-layer\",\".layui-layer-title\",\".layui-layer-main\",\".layui-layer-dialog\",\"layui-layer-iframe\",\"layui-layer-content\",\"layui-layer-btn\",\"layui-layer-close\"];s.anim=[\"layer-anim\",\"layer-anim-01\",\"layer-anim-02\",\"layer-anim-03\",\"layer-anim-04\",\"layer-anim-05\",\"layer-anim-06\"],l.pt.config={type:0,shade:.3,fixed:!0,move:s[1],title:\"&#x4FE1;&#x606F;\",offset:\"auto\",area:\"auto\",closeBtn:1,time:0,zIndex:19891014,maxWidth:360,anim:0,icon:-1,moveType:1,resize:!0,scrollbar:!0,tips:2},l.pt.vessel=function(e,t){var n=this,a=n.index,r=n.config,l=r.zIndex+a,f=\"object\"==typeof r.title,c=r.maxmin&&(1===r.type||2===r.type),d=r.title?'<div class=\"layui-layer-title\" style=\"'+(f?r.title[1]:\"\")+'\">'+(f?r.title[0]:r.title)+\"</div>\":\"\";return r.zIndex=l,t([r.shade?'<div class=\"layui-layer-shade\" id=\"layui-layer-shade'+a+'\" times=\"'+a+'\" style=\"'+(\"z-index:\"+(l-1)+\"; background-color:\"+(r.shade[1]||\"#000\")+\"; opacity:\"+(r.shade[0]||r.shade)+\"; filter:alpha(opacity=\"+(100*r.shade[0]||100*r.shade)+\");\")+'\"></div>':\"\",'<div class=\"'+s[0]+(\" layui-layer-\"+o.type[r.type])+(0!=r.type&&2!=r.type||r.shade?\"\":\" layui-layer-border\")+\" \"+(r.skin||\"\")+'\" id=\"'+s[0]+a+'\" type=\"'+o.type[r.type]+'\" times=\"'+a+'\" showtime=\"'+r.time+'\" conType=\"'+(e?\"object\":\"string\")+'\" style=\"z-index: '+l+\"; width:\"+r.area[0]+\";height:\"+r.area[1]+(r.fixed?\"\":\";position:absolute;\")+'\">'+(e&&2!=r.type?\"\":d)+'<div id=\"'+(r.id||\"\")+'\" class=\"layui-layer-content'+(0==r.type&&r.icon!==-1?\" layui-layer-padding\":\"\")+(3==r.type?\" layui-layer-loading\"+r.icon:\"\")+'\">'+(0==r.type&&r.icon!==-1?'<i class=\"layui-layer-ico layui-layer-ico'+r.icon+'\"></i>':\"\")+(1==r.type&&e?\"\":r.content||\"\")+'</div><span class=\"layui-layer-setwin\">'+function(){var e=c?'<a class=\"layui-layer-min\" href=\"javascript:;\"><cite></cite></a><a class=\"layui-layer-ico layui-layer-max\" href=\"javascript:;\"></a>':\"\";return r.closeBtn&&(e+='<a class=\"layui-layer-ico '+s[7]+\" \"+s[7]+(r.title?r.closeBtn:4==r.type?\"1\":\"2\")+'\" href=\"javascript:;\"></a>'),e}()+\"</span>\"+(r.btn?function(){var e=\"\";\"string\"==typeof r.btn&&(r.btn=[r.btn]);for(var t=0,i=r.btn.length;t<i;t++)e+='<a class=\"'+s[6]+t+'\">'+r.btn[t]+\"</a>\";return'<div class=\"'+s[6]+\" layui-layer-btn-\"+(r.btnAlign||\"\")+'\">'+e+\"</div>\"}():\"\")+(r.resize?'<span class=\"layui-layer-resize\"></span>':\"\")+\"</div>\"],d,i('<div class=\"layui-layer-move\"></div>')),n},l.pt.creat=function(){var e=this,t=e.config,a=e.index,l=t.content,f=\"object\"==typeof l,c=i(\"body\");if(!i(\"#\"+t.id)[0]){switch(\"string\"==typeof t.area&&(t.area=\"auto\"===t.area?[\"\",\"\"]:[t.area,\"\"]),t.shift&&(t.anim=t.shift),6==r.ie&&(t.fixed=!1),t.type){case 0:t.btn=\"btn\"in t?t.btn:o.btn[0],r.closeAll(\"dialog\");break;case 2:var l=t.content=f?t.content:[t.content||\"http://layer.layui.com\",\"auto\"];t.content='<iframe scrolling=\"'+(t.content[1]||\"auto\")+'\" allowtransparency=\"true\" id=\"'+s[4]+a+'\" name=\"'+s[4]+a+'\" onload=\"this.className=\\'\\';\" class=\"layui-layer-load\" frameborder=\"0\" src=\"'+t.content[0]+'\"></iframe>';break;case 3:delete t.title,delete t.closeBtn,t.icon===-1&&0===t.icon,r.closeAll(\"loading\");break;case 4:f||(t.content=[t.content,\"body\"]),t.follow=t.content[1],t.content=t.content[0]+'<i class=\"layui-layer-TipsG\"></i>',delete t.title,t.tips=\"object\"==typeof t.tips?t.tips:[t.tips,!0],t.tipsMore||r.closeAll(\"tips\")}e.vessel(f,function(n,r,d){c.append(n[0]),f?function(){2==t.type||4==t.type?function(){i(\"body\").append(n[1])}():function(){l.parents(\".\"+s[0])[0]||(l.data(\"display\",l.css(\"display\")).show().addClass(\"layui-layer-wrap\").wrap(n[1]),i(\"#\"+s[0]+a).find(\".\"+s[5]).before(r))}()}():c.append(n[1]),i(\".layui-layer-move\")[0]||c.append(o.moveElem=d),e.layero=i(\"#\"+s[0]+a),t.scrollbar||s.html.css(\"overflow\",\"hidden\").attr(\"layer-full\",a)}).auto(a),2==t.type&&6==r.ie&&e.layero.find(\"iframe\").attr(\"src\",l[0]),4==t.type?e.tips():e.offset(),t.fixed&&n.on(\"resize\",function(){e.offset(),(/^\\d+%$/.test(t.area[0])||/^\\d+%$/.test(t.area[1]))&&e.auto(a),4==t.type&&e.tips()}),t.time<=0||setTimeout(function(){r.close(e.index)},t.time),e.move().callback(),s.anim[t.anim]&&e.layero.addClass(s.anim[t.anim]).data(\"anim\",!0)}},l.pt.auto=function(e){function t(e){e=l.find(e),e.height(f[1]-c-d-2*(0|parseFloat(e.css(\"padding\"))))}var a=this,o=a.config,l=i(\"#\"+s[0]+e);\"\"===o.area[0]&&o.maxWidth>0&&(r.ie&&r.ie<8&&o.btn&&l.width(l.innerWidth()),l.outerWidth()>o.maxWidth&&l.width(o.maxWidth));var f=[l.innerWidth(),l.innerHeight()],c=l.find(s[1]).outerHeight()||0,d=l.find(\".\"+s[6]).outerHeight()||0;switch(o.type){case 2:t(\"iframe\");break;default:\"\"===o.area[1]?o.fixed&&f[1]>=n.height()&&(f[1]=n.height(),t(\".\"+s[5])):t(\".\"+s[5])}return a},l.pt.offset=function(){var e=this,t=e.config,i=e.layero,a=[i.outerWidth(),i.outerHeight()],o=\"object\"==typeof t.offset;e.offsetTop=(n.height()-a[1])/2,e.offsetLeft=(n.width()-a[0])/2,o?(e.offsetTop=t.offset[0],e.offsetLeft=t.offset[1]||e.offsetLeft):\"auto\"!==t.offset&&(\"t\"===t.offset?e.offsetTop=0:\"r\"===t.offset?e.offsetLeft=n.width()-a[0]:\"b\"===t.offset?e.offsetTop=n.height()-a[1]:\"l\"===t.offset?e.offsetLeft=0:\"lt\"===t.offset?(e.offsetTop=0,e.offsetLeft=0):\"lb\"===t.offset?(e.offsetTop=n.height()-a[1],e.offsetLeft=0):\"rt\"===t.offset?(e.offsetTop=0,e.offsetLeft=n.width()-a[0]):\"rb\"===t.offset?(e.offsetTop=n.height()-a[1],e.offsetLeft=n.width()-a[0]):e.offsetTop=t.offset),t.fixed||(e.offsetTop=/%$/.test(e.offsetTop)?n.height()*parseFloat(e.offsetTop)/100:parseFloat(e.offsetTop),e.offsetLeft=/%$/.test(e.offsetLeft)?n.width()*parseFloat(e.offsetLeft)/100:parseFloat(e.offsetLeft),e.offsetTop+=n.scrollTop(),e.offsetLeft+=n.scrollLeft()),i.attr(\"minLeft\")&&(e.offsetTop=n.height()-(i.find(s[1]).outerHeight()||0),e.offsetLeft=i.css(\"left\")),i.css({top:e.offsetTop,left:e.offsetLeft})},l.pt.tips=function(){var e=this,t=e.config,a=e.layero,o=[a.outerWidth(),a.outerHeight()],r=i(t.follow);r[0]||(r=i(\"body\"));var l={width:r.outerWidth(),height:r.outerHeight(),top:r.offset().top,left:r.offset().left},f=a.find(\".layui-layer-TipsG\"),c=t.tips[0];t.tips[1]||f.remove(),l.autoLeft=function(){l.left+o[0]-n.width()>0?(l.tipLeft=l.left+l.width-o[0],f.css({right:12,left:\"auto\"})):l.tipLeft=l.left},l.where=[function(){l.autoLeft(),l.tipTop=l.top-o[1]-10,f.removeClass(\"layui-layer-TipsB\").addClass(\"layui-layer-TipsT\").css(\"border-right-color\",t.tips[1])},function(){l.tipLeft=l.left+l.width+10,l.tipTop=l.top,f.removeClass(\"layui-layer-TipsL\").addClass(\"layui-layer-TipsR\").css(\"border-bottom-color\",t.tips[1])},function(){l.autoLeft(),l.tipTop=l.top+l.height+10,f.removeClass(\"layui-layer-TipsT\").addClass(\"layui-layer-TipsB\").css(\"border-right-color\",t.tips[1])},function(){l.tipLeft=l.left-o[0]-10,l.tipTop=l.top,f.removeClass(\"layui-layer-TipsR\").addClass(\"layui-layer-TipsL\").css(\"border-bottom-color\",t.tips[1])}],l.where[c-1](),1===c?l.top-(n.scrollTop()+o[1]+16)<0&&l.where[2]():2===c?n.width()-(l.left+l.width+o[0]+16)>0||l.where[3]():3===c?l.top-n.scrollTop()+l.height+o[1]+16-n.height()>0&&l.where[0]():4===c&&o[0]+16-l.left>0&&l.where[1](),a.find(\".\"+s[5]).css({\"background-color\":t.tips[1],\"padding-right\":t.closeBtn?\"30px\":\"\"}),a.css({left:l.tipLeft-(t.fixed?n.scrollLeft():0),top:l.tipTop-(t.fixed?n.scrollTop():0)})},l.pt.move=function(){var e=this,t=e.config,a=i(document),l=e.layero,s=l.find(t.move),f=l.find(\".layui-layer-resize\"),c={};return t.move&&s.css(\"cursor\",\"move\"),s.on(\"mousedown\",function(e){e.preventDefault(),t.move&&(c.moveStart=!0,c.offset=[e.clientX-parseFloat(l.css(\"left\")),e.clientY-parseFloat(l.css(\"top\"))],o.moveElem.css(\"cursor\",\"move\").show())}),f.on(\"mousedown\",function(e){e.preventDefault(),c.resizeStart=!0,c.offset=[e.clientX,e.clientY],c.area=[l.outerWidth(),l.outerHeight()],o.moveElem.css(\"cursor\",\"se-resize\").show()}),a.on(\"mousemove\",function(i){if(c.moveStart){var a=i.clientX-c.offset[0],o=i.clientY-c.offset[1],s=\"fixed\"===l.css(\"position\");if(i.preventDefault(),c.stX=s?0:n.scrollLeft(),c.stY=s?0:n.scrollTop(),!t.moveOut){var f=n.width()-l.outerWidth()+c.stX,d=n.height()-l.outerHeight()+c.stY;a<c.stX&&(a=c.stX),a>f&&(a=f),o<c.stY&&(o=c.stY),o>d&&(o=d)}l.css({left:a,top:o})}if(t.resize&&c.resizeStart){var a=i.clientX-c.offset[0],o=i.clientY-c.offset[1];i.preventDefault(),r.style(e.index,{width:c.area[0]+a,height:c.area[1]+o}),c.isResize=!0}}).on(\"mouseup\",function(e){c.moveStart&&(delete c.moveStart,o.moveElem.hide(),t.moveEnd&&t.moveEnd()),c.resizeStart&&(delete c.resizeStart,o.moveElem.hide())}),e},l.pt.callback=function(){function e(){var e=a.cancel&&a.cancel(t.index,n);e===!1||r.close(t.index)}var t=this,n=t.layero,a=t.config;t.openLayer(),a.success&&(2==a.type?n.find(\"iframe\").on(\"load\",function(){a.success(n,t.index)}):a.success(n,t.index)),6==r.ie&&t.IE6(n),n.find(\".\"+s[6]).children(\"a\").on(\"click\",function(){var e=i(this).index();if(0===e)a.yes?a.yes(t.index,n):a.btn1?a.btn1(t.index,n):r.close(t.index);else{var o=a[\"btn\"+(e+1)]&&a[\"btn\"+(e+1)](t.index,n);o===!1||r.close(t.index)}}),n.find(\".\"+s[7]).on(\"click\",e),a.shadeClose&&i(\"#layui-layer-shade\"+t.index).on(\"click\",function(){r.close(t.index)}),n.find(\".layui-layer-min\").on(\"click\",function(){var e=a.min&&a.min(n);e===!1||r.min(t.index,a)}),n.find(\".layui-layer-max\").on(\"click\",function(){i(this).hasClass(\"layui-layer-maxmin\")?(r.restore(t.index),a.restore&&a.restore(n)):(r.full(t.index,a),setTimeout(function(){a.full&&a.full(n)},100))}),a.end&&(o.end[t.index]=a.end)},o.reselect=function(){i.each(i(\"select\"),function(e,t){var n=i(this);n.parents(\".\"+s[0])[0]||1==n.attr(\"layer\")&&i(\".\"+s[0]).length<1&&n.removeAttr(\"layer\").show(),n=null})},l.pt.IE6=function(e){i(\"select\").each(function(e,t){var n=i(this);n.parents(\".\"+s[0])[0]||\"none\"===n.css(\"display\")||n.attr({layer:\"1\"}).hide(),n=null})},l.pt.openLayer=function(){var e=this;r.zIndex=e.config.zIndex,r.setTop=function(e){var t=function(){r.zIndex++,e.css(\"z-index\",r.zIndex+1)};return r.zIndex=parseInt(e[0].style.zIndex),e.on(\"mousedown\",t),r.zIndex}},o.record=function(e){var t=[e.width(),e.height(),e.position().top,e.position().left+parseFloat(e.css(\"margin-left\"))];e.find(\".layui-layer-max\").addClass(\"layui-layer-maxmin\"),e.attr({area:t})},o.rescollbar=function(e){s.html.attr(\"layer-full\")==e&&(s.html[0].style.removeProperty?s.html[0].style.removeProperty(\"overflow\"):s.html[0].style.removeAttribute(\"overflow\"),s.html.removeAttr(\"layer-full\"))},e.layer=r,r.getChildFrame=function(e,t){return t=t||i(\".\"+s[4]).attr(\"times\"),i(\"#\"+s[0]+t).find(\"iframe\").contents().find(e)},r.getFrameIndex=function(e){return i(\"#\"+e).parents(\".\"+s[4]).attr(\"times\")},r.iframeAuto=function(e){if(e){var t=r.getChildFrame(\"html\",e).outerHeight(),n=i(\"#\"+s[0]+e),a=n.find(s[1]).outerHeight()||0,o=n.find(\".\"+s[6]).outerHeight()||0;n.css({height:t+a+o}),n.find(\"iframe\").css({height:t})}},r.iframeSrc=function(e,t){i(\"#\"+s[0]+e).find(\"iframe\").attr(\"src\",t)},r.style=function(e,t,n){var a=i(\"#\"+s[0]+e),r=a.find(\".layui-layer-content\"),l=a.attr(\"type\"),f=a.find(s[1]).outerHeight()||0,c=a.find(\".\"+s[6]).outerHeight()||0;a.attr(\"minLeft\");l!==o.type[3]&&l!==o.type[4]&&(n||(parseFloat(t.width)<=260&&(t.width=260),parseFloat(t.height)-f-c<=64&&(t.height=64+f+c)),a.css(t),c=a.find(\".\"+s[6]).outerHeight(),l===o.type[2]?a.find(\"iframe\").css({height:parseFloat(t.height)-f-c}):r.css({height:parseFloat(t.height)-f-c-parseFloat(r.css(\"padding-top\"))-parseFloat(r.css(\"padding-bottom\"))}))},r.min=function(e,t){var a=i(\"#\"+s[0]+e),l=a.find(s[1]).outerHeight()||0,f=a.attr(\"minLeft\")||181*o.minIndex+\"px\",c=a.css(\"position\");o.record(a),o.minLeft[0]&&(f=o.minLeft[0],o.minLeft.shift()),a.attr(\"position\",c),r.style(e,{width:180,height:l,left:f,top:n.height()-l,position:\"fixed\",overflow:\"hidden\"},!0),a.find(\".layui-layer-min\").hide(),\"page\"===a.attr(\"type\")&&a.find(s[4]).hide(),o.rescollbar(e),a.attr(\"minLeft\")||o.minIndex++,a.attr(\"minLeft\",f)},r.restore=function(e){var t=i(\"#\"+s[0]+e),n=t.attr(\"area\").split(\",\");t.attr(\"type\");r.style(e,{width:parseFloat(n[0]),height:parseFloat(n[1]),top:parseFloat(n[2]),left:parseFloat(n[3]),position:t.attr(\"position\"),overflow:\"visible\"},!0),t.find(\".layui-layer-max\").removeClass(\"layui-layer-maxmin\"),t.find(\".layui-layer-min\").show(),\"page\"===t.attr(\"type\")&&t.find(s[4]).show(),o.rescollbar(e)},r.full=function(e){var t,a=i(\"#\"+s[0]+e);o.record(a),s.html.attr(\"layer-full\")||s.html.css(\"overflow\",\"hidden\").attr(\"layer-full\",e),clearTimeout(t),t=setTimeout(function(){var t=\"fixed\"===a.css(\"position\");r.style(e,{top:t?0:n.scrollTop(),left:t?0:n.scrollLeft(),width:n.width(),height:n.height()},!0),a.find(\".layui-layer-min\").hide()},100)},r.title=function(e,t){var n=i(\"#\"+s[0]+(t||r.index)).find(s[1]);n.html(e)},r.close=function(e){var t=i(\"#\"+s[0]+e),n=t.attr(\"type\"),a=\"layer-anim-close\";if(t[0]){var l=\"layui-layer-wrap\",f=function(){if(n===o.type[1]&&\"object\"===t.attr(\"conType\")){t.children(\":not(.\"+s[5]+\")\").remove();for(var a=t.find(\".\"+l),r=0;r<2;r++)a.unwrap();a.css(\"display\",a.data(\"display\")).removeClass(l)}else{if(n===o.type[2])try{var f=i(\"#\"+s[4]+e)[0];f.contentWindow.document.write(\"\"),f.contentWindow.close(),t.find(\".\"+s[5])[0].removeChild(f)}catch(c){}t[0].innerHTML=\"\",t.remove()}};t.data(\"anim\")&&t.addClass(a),i(\"#layui-layer-moves, #layui-layer-shade\"+e).remove(),6==r.ie&&o.reselect(),o.rescollbar(e),\"function\"==typeof o.end[e]&&o.end[e](),delete o.end[e],t.attr(\"minLeft\")&&(o.minIndex--,o.minLeft.push(t.attr(\"minLeft\"))),setTimeout(function(){f()},r.ie&&r.ie<10||!t.data(\"anim\")?0:200)}},r.closeAll=function(e){i.each(i(\".\"+s[0]),function(){var t=i(this),n=e?t.attr(\"type\")===e:1;n&&r.close(t.attr(\"times\")),n=null})};var f=r.cache||{},c=function(e){return f.skin?\" \"+f.skin+\" \"+f.skin+\"-\"+e:\"\"};r.prompt=function(e,t){var a=\"\";if(e=e||{},\"function\"==typeof e&&(t=e),e.area){var o=e.area;a='style=\"width: '+o[0]+\"; height: \"+o[1]+';\"',delete e.area}var l,s=2==e.formType?'<textarea class=\"layui-layer-input\"'+a+\">\"+(e.value||\"\")+\"</textarea>\":function(){return'<input type=\"'+(1==e.formType?\"password\":\"text\")+'\" class=\"layui-layer-input\" value=\"'+(e.value||\"\")+'\">'}();return r.open(i.extend({type:1,btn:[\"&#x786E;&#x5B9A;\",\"&#x53D6;&#x6D88;\"],content:s,skin:\"layui-layer-prompt\"+c(\"prompt\"),maxWidth:n.width(),success:function(e){l=e.find(\".layui-layer-input\"),l.focus()},resize:!1,yes:function(i){var n=l.val();\"\"===n?l.focus():n.length>(e.maxlength||500)?r.tips(\"&#x6700;&#x591A;&#x8F93;&#x5165;\"+(e.maxlength||500)+\"&#x4E2A;&#x5B57;&#x6570;\",l,{tips:1}):t&&t(n,i,l)}},e))},r.tab=function(e){e=e||{};var t=e.tab||{};return r.open(i.extend({type:1,skin:\"layui-layer-tab\"+c(\"tab\"),resize:!1,title:function(){var e=t.length,i=1,n=\"\";if(e>0)for(n='<span class=\"layui-layer-tabnow\">'+t[0].title+\"</span>\";i<e;i++)n+=\"<span>\"+t[i].title+\"</span>\";return n}(),content:'<ul class=\"layui-layer-tabmain\">'+function(){var e=t.length,i=1,n=\"\";if(e>0)for(n='<li class=\"layui-layer-tabli xubox_tab_layer\">'+(t[0].content||\"no content\")+\"</li>\";i<e;i++)n+='<li class=\"layui-layer-tabli\">'+(t[i].content||\"no  content\")+\"</li>\";return n}()+\"</ul>\",success:function(t){var n=t.find(\".layui-layer-title\").children(),a=t.find(\".layui-layer-tabmain\").children();n.on(\"mousedown\",function(t){t.stopPropagation?t.stopPropagation():t.cancelBubble=!0;var n=i(this),o=n.index();n.addClass(\"layui-layer-tabnow\").siblings().removeClass(\"layui-layer-tabnow\"),a.eq(o).show().siblings().hide(),\"function\"==typeof e.change&&e.change(o)})}},e))},r.photos=function(t,n,a){function o(e,t,i){var n=new Image;return n.src=e,n.complete?t(n):(n.onload=function(){n.onload=null,t(n)},void(n.onerror=function(e){n.onerror=null,i(e)}))}var l={};if(t=t||{},t.photos){var s=t.photos.constructor===Object,f=s?t.photos:{},d=f.data||[],u=f.start||0;if(l.imgIndex=(0|u)+1,t.img=t.img||\"img\",s){if(0===d.length)return r.msg(\"&#x6CA1;&#x6709;&#x56FE;&#x7247;\")}else{var y=i(t.photos),p=function(){d=[],y.find(t.img).each(function(e){var t=i(this);t.attr(\"layer-index\",e),d.push({alt:t.attr(\"alt\"),pid:t.attr(\"layer-pid\"),src:t.attr(\"layer-src\")||t.attr(\"src\"),thumb:t.attr(\"src\")})})};if(p(),0===d.length)return;if(n||y.on(\"click\",t.img,function(){var e=i(this),n=e.attr(\"layer-index\");r.photos(i.extend(t,{photos:{start:n,data:d,tab:t.tab},full:t.full}),!0),p()}),!n)return}l.imgprev=function(e){l.imgIndex--,l.imgIndex<1&&(l.imgIndex=d.length),l.tabimg(e)},l.imgnext=function(e,t){l.imgIndex++,l.imgIndex>d.length&&(l.imgIndex=1,t)||l.tabimg(e)},l.keyup=function(e){if(!l.end){var t=e.keyCode;e.preventDefault(),37===t?l.imgprev(!0):39===t?l.imgnext(!0):27===t&&r.close(l.index)}},l.tabimg=function(e){d.length<=1||(f.start=l.imgIndex-1,r.close(l.index),r.photos(t,!0,e))},l.event=function(){l.bigimg.hover(function(){l.imgsee.show()},function(){l.imgsee.hide()}),l.bigimg.find(\".layui-layer-imgprev\").on(\"click\",function(e){e.preventDefault(),l.imgprev()}),l.bigimg.find(\".layui-layer-imgnext\").on(\"click\",function(e){e.preventDefault(),l.imgnext()}),i(document).on(\"keyup\",l.keyup)},l.loadi=r.load(1,{shade:!(\"shade\"in t)&&.9,scrollbar:!1}),o(d[u].src,function(n){r.close(l.loadi),l.index=r.open(i.extend({type:1,area:function(){var a=[n.width,n.height],o=[i(e).width()-100,i(e).height()-100];if(!t.full&&(a[0]>o[0]||a[1]>o[1])){var r=[a[0]/o[0],a[1]/o[1]];r[0]>r[1]?(a[0]=a[0]/r[0],a[1]=a[1]/r[0]):r[0]<r[1]&&(a[0]=a[0]/r[1],a[1]=a[1]/r[1])}return[a[0]+\"px\",a[1]+\"px\"]}(),title:!1,shade:.9,shadeClose:!0,closeBtn:!1,move:\".layui-layer-phimg img\",moveType:1,scrollbar:!1,moveOut:!0,anim:5*Math.random()|0,skin:\"layui-layer-photos\"+c(\"photos\"),content:'<div class=\"layui-layer-phimg\"><img src=\"'+d[u].src+'\" alt=\"'+(d[u].alt||\"\")+'\" layer-pid=\"'+d[u].pid+'\"><div class=\"layui-layer-imgsee\">'+(d.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:'+(a?\"block\":\"\")+'\"><span class=\"layui-layer-imgtit\"><a href=\"javascript:;\">'+(d[u].alt||\"\")+\"</a><em>\"+l.imgIndex+\"/\"+d.length+\"</em></span></div></div></div>\",success:function(e,i){l.bigimg=e.find(\".layui-layer-phimg\"),l.imgsee=e.find(\".layui-layer-imguide,.layui-layer-imgbar\"),l.event(e),t.tab&&t.tab(d[u],e)},end:function(){l.end=!0,i(document).off(\"keyup\",l.keyup)}},t))},function(){r.close(l.loadi),r.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(){d.length>1&&l.imgnext(!0,!0)}})})}},o.run=function(t){i=t,n=i(e),s.html=i(\"html\"),r.open=function(e){var t=new l(e);return t.index}},e.layui&&layui.define?(r.ready(),layui.define(\"jquery\",function(t){r.path=layui.cache.dir,o.run(layui.jquery),e.layer=r,t(\"layer\",r)})):\"function\"==typeof define?define([\"jquery\"],function(){return o.run(e.jQuery),r}):function(){o.run(e.jQuery),r.ready()}()}(window);"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/plugins/layer/mobile/layer.js",
    "content": "/*! layer mobile-v2.0.0 Web弹层组件 MIT License  http://layer.layui.com/mobile  By 贤心 */\n ;!function(e){\"use strict\";var t=document,n=\"querySelectorAll\",i=\"getElementsByClassName\",a=function(e){return t[n](e)},s={type:0,shade:!0,shadeClose:!0,fixed:!0,anim:\"scale\"},l={extend:function(e){var t=JSON.parse(JSON.stringify(s));for(var n in e)t[n]=e[n];return t},timer:{},end:{}};l.touch=function(e,t){e.addEventListener(\"click\",function(e){t.call(this,e)},!1)};var r=0,o=[\"layui-m-layer\"],c=function(e){var t=this;t.config=l.extend(e),t.view()};c.prototype.view=function(){var e=this,n=e.config,s=t.createElement(\"div\");e.id=s.id=o[0]+r,s.setAttribute(\"class\",o[0]+\" \"+o[0]+(n.type||0)),s.setAttribute(\"index\",r);var l=function(){var e=\"object\"==typeof n.title;return n.title?'<h3 style=\"'+(e?n.title[1]:\"\")+'\">'+(e?n.title[0]:n.title)+\"</h3>\":\"\"}(),c=function(){\"string\"==typeof n.btn&&(n.btn=[n.btn]);var e,t=(n.btn||[]).length;return 0!==t&&n.btn?(e='<span yes type=\"1\">'+n.btn[0]+\"</span>\",2===t&&(e='<span no type=\"0\">'+n.btn[1]+\"</span>\"+e),'<div class=\"layui-m-layerbtn\">'+e+\"</div>\"):\"\"}();if(n.fixed||(n.top=n.hasOwnProperty(\"top\")?n.top:100,n.style=n.style||\"\",n.style+=\" top:\"+(t.body.scrollTop+n.top)+\"px\"),2===n.type&&(n.content='<i></i><i class=\"layui-m-layerload\"></i><i></i><p>'+(n.content||\"\")+\"</p>\"),n.skin&&(n.anim=\"up\"),\"msg\"===n.skin&&(n.shade=!1),s.innerHTML=(n.shade?\"<div \"+(\"string\"==typeof n.shade?'style=\"'+n.shade+'\"':\"\")+' class=\"layui-m-layershade\"></div>':\"\")+'<div class=\"layui-m-layermain\" '+(n.fixed?\"\":'style=\"position:static;\"')+'><div class=\"layui-m-layersection\"><div class=\"layui-m-layerchild '+(n.skin?\"layui-m-layer-\"+n.skin+\" \":\"\")+(n.className?n.className:\"\")+\" \"+(n.anim?\"layui-m-anim-\"+n.anim:\"\")+'\" '+(n.style?'style=\"'+n.style+'\"':\"\")+\">\"+l+'<div class=\"layui-m-layercont\">'+n.content+\"</div>\"+c+\"</div></div></div>\",!n.type||2===n.type){var d=t[i](o[0]+n.type),y=d.length;y>=1&&layer.close(d[0].getAttribute(\"index\"))}document.body.appendChild(s);var u=e.elem=a(\"#\"+e.id)[0];n.success&&n.success(u),e.index=r++,e.action(n,u)},c.prototype.action=function(e,t){var n=this;e.time&&(l.timer[n.index]=setTimeout(function(){layer.close(n.index)},1e3*e.time));var a=function(){var t=this.getAttribute(\"type\");0==t?(e.no&&e.no(),layer.close(n.index)):e.yes?e.yes(n.index):layer.close(n.index)};if(e.btn)for(var s=t[i](\"layui-m-layerbtn\")[0].children,r=s.length,o=0;o<r;o++)l.touch(s[o],a);if(e.shade&&e.shadeClose){var c=t[i](\"layui-m-layershade\")[0];l.touch(c,function(){layer.close(n.index,e.end)})}e.end&&(l.end[n.index]=e.end)},e.layer={v:\"2.0\",index:r,open:function(e){var t=new c(e||{});return t.index},close:function(e){var n=a(\"#\"+o[0]+e)[0];n&&(n.innerHTML=\"\",t.body.removeChild(n),clearTimeout(l.timer[e]),delete l.timer[e],\"function\"==typeof l.end[e]&&l.end[e](),delete l.end[e])},closeAll:function(){for(var e=t[i](o[0]),n=0,a=e.length;n<a;n++)layer.close(0|e[0].getAttribute(\"index\"))}},\"function\"==typeof define?define(function(){return layer}):function(){var e=document.scripts,n=e[e.length-1],i=n.src,a=i.substring(0,i.lastIndexOf(\"/\")+1);n.getAttribute(\"merge\")||document.head.appendChild(function(){var e=t.createElement(\"link\");return e.href=a+\"need/layer.css?2.0\",e.type=\"text/css\",e.rel=\"styleSheet\",e.id=\"layermcss\",e}())}()}(window);"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/plugins/layer/mobile/need/layer.css",
    "content": ".layui-m-layer{position:relative;z-index:19891014}.layui-m-layer *{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.layui-m-layermain,.layui-m-layershade{position:fixed;left:0;top:0;width:100%;height:100%}.layui-m-layershade{background-color:rgba(0,0,0,.7);pointer-events:auto}.layui-m-layermain{display:table;font-family:Helvetica,arial,sans-serif;pointer-events:none}.layui-m-layermain .layui-m-layersection{display:table-cell;vertical-align:middle;text-align:center}.layui-m-layerchild{position:relative;display:inline-block;text-align:left;background-color:#fff;font-size:14px;border-radius:5px;box-shadow:0 0 8px rgba(0,0,0,.1);pointer-events:auto;-webkit-overflow-scrolling:touch;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:.2s;animation-duration:.2s}@-webkit-keyframes layui-m-anim-scale{0%{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}@keyframes layui-m-anim-scale{0%{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}.layui-m-anim-scale{animation-name:layui-m-anim-scale;-webkit-animation-name:layui-m-anim-scale}@-webkit-keyframes layui-m-anim-up{0%{opacity:0;-webkit-transform:translateY(800px);transform:translateY(800px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes layui-m-anim-up{0%{opacity:0;-webkit-transform:translateY(800px);transform:translateY(800px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}.layui-m-anim-up{-webkit-animation-name:layui-m-anim-up;animation-name:layui-m-anim-up}.layui-m-layer0 .layui-m-layerchild{width:90%;max-width:640px}.layui-m-layer1 .layui-m-layerchild{border:none;border-radius:0}.layui-m-layer2 .layui-m-layerchild{width:auto;max-width:260px;min-width:40px;border:none;background:0 0;box-shadow:none;color:#fff}.layui-m-layerchild h3{padding:0 10px;height:60px;line-height:60px;font-size:16px;font-weight:400;border-radius:5px 5px 0 0;text-align:center}.layui-m-layerbtn span,.layui-m-layerchild h3{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-m-layercont{padding:50px 30px;line-height:22px;text-align:center}.layui-m-layer1 .layui-m-layercont{padding:0;text-align:left}.layui-m-layer2 .layui-m-layercont{text-align:center;padding:0;line-height:0}.layui-m-layer2 .layui-m-layercont i{width:25px;height:25px;margin-left:8px;display:inline-block;background-color:#fff;border-radius:100%;-webkit-animation:layui-m-anim-loading 1.4s infinite ease-in-out;animation:layui-m-anim-loading 1.4s infinite ease-in-out;-webkit-animation-fill-mode:both;animation-fill-mode:both}.layui-m-layerbtn,.layui-m-layerbtn span{position:relative;text-align:center;border-radius:0 0 5px 5px}.layui-m-layer2 .layui-m-layercont p{margin-top:20px}@-webkit-keyframes layui-m-anim-loading{0%,100%,80%{transform:scale(0);-webkit-transform:scale(0)}40%{transform:scale(1);-webkit-transform:scale(1)}}@keyframes layui-m-anim-loading{0%,100%,80%{transform:scale(0);-webkit-transform:scale(0)}40%{transform:scale(1);-webkit-transform:scale(1)}}.layui-m-layer2 .layui-m-layercont i:first-child{margin-left:0;-webkit-animation-delay:-.32s;animation-delay:-.32s}.layui-m-layer2 .layui-m-layercont i.layui-m-layerload{-webkit-animation-delay:-.16s;animation-delay:-.16s}.layui-m-layer2 .layui-m-layercont>div{line-height:22px;padding-top:7px;margin-bottom:20px;font-size:14px}.layui-m-layerbtn{display:box;display:-moz-box;display:-webkit-box;width:100%;height:50px;line-height:50px;font-size:0;border-top:1px solid #D0D0D0;background-color:#F2F2F2}.layui-m-layerbtn span{display:block;-moz-box-flex:1;box-flex:1;-webkit-box-flex:1;font-size:14px;cursor:pointer}.layui-m-layerbtn span[yes]{color:#40AFFE}.layui-m-layerbtn span[no]{border-right:1px solid #D0D0D0;border-radius:0 0 0 5px}.layui-m-layerbtn span:active{background-color:#F6F6F6}.layui-m-layerend{position:absolute;right:7px;top:10px;width:30px;height:30px;border:0;font-weight:400;background:0 0;cursor:pointer;-webkit-appearance:none;font-size:30px}.layui-m-layerend::after,.layui-m-layerend::before{position:absolute;left:5px;top:15px;content:'';width:18px;height:1px;background-color:#999;transform:rotate(45deg);-webkit-transform:rotate(45deg);border-radius:3px}.layui-m-layerend::after{transform:rotate(-45deg);-webkit-transform:rotate(-45deg)}body .layui-m-layer .layui-m-layer-footer{position:fixed;width:95%;max-width:100%;margin:0 auto;left:0;right:0;bottom:10px;background:0 0}.layui-m-layer-footer .layui-m-layercont{padding:20px;border-radius:5px 5px 0 0;background-color:rgba(255,255,255,.8)}.layui-m-layer-footer .layui-m-layerbtn{display:block;height:auto;background:0 0;border-top:none}.layui-m-layer-footer .layui-m-layerbtn span{background-color:rgba(255,255,255,.8)}.layui-m-layer-footer .layui-m-layerbtn span[no]{color:#FD482C;border-top:1px solid #c2c2c2;border-radius:0 0 5px 5px}.layui-m-layer-footer .layui-m-layerbtn span[yes]{margin-top:10px;border-radius:5px}body .layui-m-layer .layui-m-layer-msg{width:auto;max-width:90%;margin:0 auto;bottom:-150px;background-color:rgba(0,0,0,.7);color:#fff}.layui-m-layer-msg .layui-m-layercont{padding:10px 20px}"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/plugins/layer/skin/default/layer.css",
    "content": ".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 #layuicss-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)}.layui-layer-close{position:absolute}.layui-layer-content{position:relative}.layui-layer-border{border:1px solid #B2B2B2;border:1px solid rgba(0,0,0,.1);box-shadow:1px 1px 5px rgba(0,0,0,.2)}.layui-layer-load{background:url(loading-1.gif) center center no-repeat #eee}.layui-layer-ico{background:url(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}.layui-layer-move{display:none;position:fixed;*position:absolute;left:0;top:0;width:100%;height:100%;cursor:move;opacity:0;filter:alpha(opacity=0);background-color:#fff;z-index:2147483647}.layui-layer-resize{position:absolute;width:15px;height:15px;right:0;bottom:0;cursor:se-resize}.layui-layer{border-radius:2px;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:.3s;animation-duration:.3s}@-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 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}}@-webkit-keyframes bounceOut{100%{opacity:0;-webkit-transform:scale(.7);transform:scale(.7)}30%{-webkit-transform:scale(1.05);transform:scale(1.05)}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.05);-ms-transform:scale(1.05);transform:scale(1.05)}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}.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;user-select:none;-webkit-user-select:none}.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:.8}.layui-layer-btn .layui-layer-btn0{border-color:#4898d5;background-color:#2e8ded;color:#fff}.layui-layer-btn-l{text-align:left}.layui-layer-btn-c{text-align:center}.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 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(loading-0.gif) no-repeat}.layui-layer-loading .layui-layer-loading1{width:37px;height:37px;background:url(loading-1.gif) no-repeat}.layui-layer-ico16,.layui-layer-loading .layui-layer-loading2{width:32px;height:32px;background:url(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:2px;box-shadow:1px 1px 3px rgba(0,0,0,.2);background-color:#000;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:#000}.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:#000}.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(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-prompt .layui-layer-content{padding:20px}.layui-layer-prompt .layui-layer-btn{padding-top:0}.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}@media screen and (max-width:1100px){.layui-layer-iframe{overflow-y:auto;-webkit-overflow-scrolling:touch}}"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/plugins/layer/skin/moon/style.css",
    "content": "html #layui_layer_skinmoonstylecss{display:none;position:absolute;width:1989px}body .layer-ext-moon[type=dialog]{min-width:320px}body .layer-ext-moon-msg[type=dialog]{min-width:200px}body .layer-ext-moon .layui-layer-title{background:#f6f6f6;color:#212a31;font-size:16px;font-weight:700;height:46px;line-height:46px;border-bottom:1px solid #D5D5D5}body .layer-ext-moon .layui-layer-content .layui-layer-ico{height:32px;width:32px;top:18.5px}body .layer-ext-moon .layui-layer-ico0{background:url(default.png) -96px 0 no-repeat}body .layer-ext-moon .layui-layer-ico1{background:url(default.png) -224px 0 no-repeat}body .layer-ext-moon .layui-layer-ico2{background:url(default.png) -192px 0 no-repeat}body .layer-ext-moon .layui-layer-ico3{background:url(default.png) -160px 0 no-repeat}body .layer-ext-moon .layui-layer-ico4{background:url(default.png) -320px 0 no-repeat}body .layer-ext-moon .layui-layer-ico5{background:url(default.png) -288px 0 no-repeat}body .layer-ext-moon .layui-layer-ico6{background:url(default.png) -256px 0}body .layer-ext-moon .layui-layer-ico7{background:url(default.png) -128px 0 no-repeat}body .layer-ext-moon .layui-layer-setwin{top:15px;right:15px}body .layer-ext-moon .layui-layer-setwin a{width:16px;height:16px}body .layer-ext-moon .layui-layer-setwin .layui-layer-min cite:hover{background-color:#56abe4}body .layer-ext-moon .layui-layer-setwin .layui-layer-max{background:url(default.png) -80px 0 no-repeat}body .layer-ext-moon .layui-layer-setwin .layui-layer-max:hover{background:url(default.png) -64px 0 no-repeat}body .layer-ext-moon .layui-layer-setwin .layui-layer-maxmin{background:url(default.png) -32px 0 no-repeat}body .layer-ext-moon .layui-layer-setwin .layui-layer-maxmin:hover{background:url(default.png) -16px 0 no-repeat}body .layer-ext-moon .layui-layer-setwin .layui-layer-close1,body .layer-ext-moon .layui-layer-setwin .layui-layer-close2{background:url(default.png)}body .layer-ext-moon .layui-layer-setwin .layui-layer-close1:hover,body .layer-ext-moon .layui-layer-setwin .layui-layer-close2:hover{background:url(default.png) -48px 0}body .layer-ext-moon .layui-layer-padding{padding-top:24px}body .layer-ext-moon .layui-layer-btn{text-align:center;padding-top:15px;padding-bottom:15px;background:#f0f4f7;border-top:1px #c7c7c7 solid}body .layer-ext-moon .layui-layer-btn a{font-size:12px;font-weight:400;margin:0 7px;padding:6px 20px;color:#fff;border:1px solid #0064b6;background:no-repeat #0071ce;border-radius:3px;display:inline-block;height:20px;line-height:20px;text-align:center;vertical-align:middle;text-decoration:none;outline:0}body .layer-ext-moon .layui-layer-btn .layui-layer-btn0{background:#0071ce}body .layer-ext-moon .layui-layer-btn .layui-layer-btn1{background:#fff;color:#404a58;border:1px solid #c0c4cd;border-radius:3px}body .layer-ext-moon .layui-layer-btn .layui-layer-btn2{background:#f60;color:#fff;border:1px solid #f60;border-radius:3px}body .layer-ext-moon .layui-layer-btn .layui-layer-btn3{background:red;color:#fff;border:1px solid red;border-radius:3px}body .layer-ext-moon .layui-layer-title span.layui-layer-tabnow{height:47px}"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/plugins/layui/css/layui.css",
    "content": "/** layui-v1.0.7 LGPL License By http://www.layui.com */\n .layui-btn,.layui-inline,img{vertical-align:middle}.layui-btn,.layui-unselect{-webkit-user-select:none;-ms-user-select:none;-moz-user-select:none}.layui-laypage a,a{text-decoration:none}.layui-btn,.layui-tree li i,.layui-unselect{-moz-user-select:none}.layui-form-select dl,.layui-nav-child{min-width:100%;box-shadow:0 2px 4px rgba(0,0,0,.12)}blockquote,body,button,dd,div,dl,dt,form,h1,h2,h3,h4,h5,h6,input,li,ol,p,pre,td,textarea,th,ul{margin:0;padding:0;-webkit-tap-highlight-color:rgba(0,0,0,0)}a:active,a:hover{outline:0}img{display:inline-block;border:none}li{list-style:none}table{border-collapse:collapse;border-spacing:0}h1,h2,h3{font-size:14px;font-weight:400}h4,h5,h6{font-size:100%;font-weight:400}button,input,optgroup,option,select,textarea{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;outline:0}pre{white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word}::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar-button:vertical{display:none}::-webkit-scrollbar-corner,::-webkit-scrollbar-track{background-color:#e2e2e2}::-webkit-scrollbar-thumb{border-radius:0;background-color:rgba(0,0,0,.3)}::-webkit-scrollbar-thumb:vertical:hover{background-color:rgba(0,0,0,.35)}::-webkit-scrollbar-thumb:vertical:active{background-color:rgba(0,0,0,.38)}@font-face{font-family:layui-icon;src:url(../font/iconfont.eot);src:url(../font/iconfont.eot?#iefix) format('embedded-opentype'),url(../font/iconfont.woff) format('woff'),url(../font/iconfont.ttf) format('truetype'),url(../font/iconfont.svg#iconfont) format('svg')}.layui-icon{font-family:layui-icon!important;font-size:16px;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body{line-height:24px;font:14px Helvetica Neue,Helvetica,PingFang SC,\\5FAE\\8F6F\\96C5\\9ED1,Tahoma,Arial,sans-serif}.layui-flow-more a cite,.layui-laypage em,.layui-tree li a cite,a cite{font-style:normal}hr{height:1px;margin:10px 0;border:0;background-color:#e2e2e2;clear:both}a{color:#333}a:hover{color:#777}a cite{*cursor:pointer}.layui-box,.layui-box *{-webkit-box-sizing:content-box!important;-moz-box-sizing:content-box!important;box-sizing:content-box!important}.layui-border-box,.layui-border-box *{-webkit-box-sizing:border-box!important;-moz-box-sizing:border-box!important;box-sizing:border-box!important}.layui-clear{clear:both;*zoom:1}.layui-clear:after{content:'\\20';clear:both;*zoom:1;display:block;height:0}.layui-inline{position:relative;display:inline-block;*display:inline;*zoom:1}.layui-edge{position:absolute;width:0;height:0;border-style:dashed;border-color:transparent;overflow:hidden}.layui-elip{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-disabled,.layui-disabled:hover{color:#d2d2d2!important;cursor:not-allowed!important}.layui-circle{border-radius:100%}.layui-show{display:block!important}.layui-hide{display:none!important}.layui-main{position:relative;width:1140px;margin:0 auto}.layui-header{position:relative;z-index:1000;height:65px}.layui-header a:hover{transition:all .5s;-webkit-transition:all .5s}.layui-side{position:fixed;top:0;bottom:0;z-index:999;width:200px;overflow-x:hidden}.layui-side-scroll{width:220px;height:100%;overflow-x:hidden}.layui-body{position:absolute;left:200px;right:0;top:0;bottom:0;z-index:998;width:auto;overflow:hidden;overflow-y:auto;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.layui-layout-admin .layui-header{border-bottom:5px solid #1AA094}.layui-layout-admin .layui-side{top:70px;width:200px;overflow-x:hidden}.layui-layout-admin .layui-body{top:70px;bottom:44px}.layui-layout-admin .layui-main{width:auto;margin:0 15px}.layui-layout-admin .layui-footer{position:fixed;left:200px;right:0;bottom:0;height:44px;background-color:#eee}.layui-btn,.layui-input,.layui-select,.layui-textarea,.layui-upload-button{outline:0;-webkit-transition:border-color .3s cubic-bezier(.65,.05,.35,.5);transition:border-color .3s cubic-bezier(.65,.05,.35,.5);-webkit-box-sizing:border-box!important;-moz-box-sizing:border-box!important;box-sizing:border-box!important}.layui-elem-quote{margin-bottom:10px;padding:15px;line-height:22px;border-left:5px solid #009688;border-radius:0 2px 2px 0;background-color:#f2f2f2}.layui-quote-nm{border-color:#e2e2e2;border-style:solid;border-width:1px 1px 1px 5px;background:0 0}.layui-elem-field{margin-bottom:10px;padding:0;border:1px solid #e2e2e2}.layui-elem-field legend{margin-left:20px;padding:0 10px;font-size:20px;font-weight:300}.layui-field-title{margin:10px 0 20px;border:none;border-top:1px solid #e2e2e2}.layui-field-box{padding:10px 15px}.layui-field-title .layui-field-box{padding:10px 0}.layui-bg-black{background-color:#393D49;color:#c2c2c2}.layui-bg-black a{color:#c2c2c2}.layui-bg-black a:hover{color:#fff}.layui-bg-gray{background-color:#eee;color:#333}.layui-bg-green{background-color:#009688;color:#D7EEE8}.layui-bg-blue{background-color:#1E9FFF;color:#D7EEE8}.layui-word-aux{font-size:12px;color:#999;padding:0 5px}.layui-btn{display:inline-block;height:38px;line-height:38px;padding:0 18px;background-color:#009688;color:#fff;white-space:nowrap;text-align:center;border:none;border-radius:2px;cursor:pointer;opacity:.9;filter:alpha(opacity=90)}.layui-btn:hover{opacity:.8;filter:alpha(opacity=80);color:#fff}.layui-btn:active{opacity:1;filter:alpha(opacity=100)}.layui-btn+.layui-btn{margin-left:10px}.layui-btn-radius{border-radius:100px}.layui-btn .layui-icon{font-size:18px;vertical-align:bottom}.layui-btn-primary{border:1px solid #C9C9C9;background-color:#fff;color:#555}.layui-btn-primary:hover{border-color:#009688;color:#333}.layui-btn-normal{background-color:#1E9FFF}.layui-btn-warm{background-color:#F7B824}.layui-btn-danger{background-color:#FF5722}.layui-btn-disabled,.layui-btn-disabled:active,.layui-btn-disabled:hover{border:1px solid #e6e6e6;background-color:#FBFBFB;color:#C9C9C9;cursor:not-allowed;opacity:1}.layui-btn-big{height:44px;line-height:44px;padding:0 25px;font-size:16px}.layui-btn-small{height:30px;line-height:30px;padding:0 10px;font-size:12px}.layui-btn-small i{font-size:16px!important}.layui-btn-mini{height:22px;line-height:22px;padding:0 5px;font-size:12px}.layui-btn-mini i{font-size:14px!important}.layui-input,.layui-select,.layui-textarea{height:38px;line-height:38px;line-height:36px\\9;border:1px solid #e6e6e6;background-color:#fff;border-radius:2px}.layui-form-label,.layui-form-mid,.layui-textarea{line-height:20px;position:relative}.layui-input,.layui-textarea{display:block;width:100%;padding-left:10px}.layui-input:hover,.layui-textarea:hover{border-color:#D2D2D2!important}.layui-input:focus,.layui-textarea:focus{border-color:#C9C9C9!important}.layui-textarea{min-height:100px;height:auto;padding:6px 10px;resize:vertical}.layui-select{padding:0 10px}.layui-form input[type=checkbox],.layui-form input[type=radio],.layui-form select{display:none}.layui-form-item{margin-bottom:15px;clear:both;*zoom:1}.layui-form-item:after{content:'\\20';clear:both;*zoom:1;display:block;height:0}.layui-form-label{float:left;display:block;padding:9px 15px;width:80px;font-weight:400;text-align:right}.layui-form-item .layui-inline{margin-bottom:5px;margin-right:10px}.layui-input-block,.layui-input-inline{position:relative}.layui-input-block{margin-left:110px;min-height:36px}.layui-input-inline{display:inline-block;vertical-align:middle}.layui-form-item .layui-input-inline{float:left;width:190px;margin-right:10px}.layui-form-text .layui-input-inline{width:auto}.layui-form-mid{float:left;display:block;padding:8px 0;margin-right:10px}.layui-form-danger+.layui-form-select .layui-input,.layui-form-danger:focus{border:1px solid #FF5722!important}.layui-form-select{position:relative}.layui-form-select .layui-input{padding-right:30px;cursor:pointer}.layui-form-select .layui-edge{position:absolute;right:10px;top:50%;margin-top:-3px;cursor:pointer;border-width:6px;border-top-color:#c2c2c2;border-top-style:solid;transition:all .3s;-webkit-transition:all .3s}.layui-form-checkbox,.layui-form-switch{-webkit-transition:.1s linear;cursor:pointer}.layui-form-select dl{display:none;position:absolute;left:0;top:42px;padding:5px 0;z-index:999;border:1px solid #d2d2d2;max-height:300px;overflow-y:auto;background-color:#fff;border-radius:2px;box-sizing:border-box}.layui-form-select dl dd,.layui-form-select dl dt{padding:0 10px;line-height:36px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.layui-form-select dl dt{font-size:12px;color:#999}.layui-form-select dl dd{cursor:pointer}.layui-form-select dl dd:hover{background-color:#f2f2f2}.layui-form-select .layui-select-group dd{padding-left:20px}.layui-form-select dl dd.layui-this{background-color:#5FB878;color:#fff}.layui-form-checkbox,.layui-form-select dl dd.layui-disabled{background-color:#fff}.layui-form-selected dl{display:block}.layui-form-checkbox,.layui-form-checkbox *,.layui-form-radio,.layui-form-radio *,.layui-form-switch{display:inline-block;vertical-align:middle}.layui-form-selected .layui-edge{margin-top:-9px;-webkit-transform:rotate(180deg);transform:rotate(180deg);margin-top:-3px\\9}:root .layui-form-selected .layui-edge{margin-top:-9px\\0/IE9}.layui-select-disabled .layui-disabled{border-color:#eee!important}.layui-select-disabled .layui-edge{border-top-color:#d2d2d2}.layui-form-checkbox{position:relative;height:30px;line-height:28px;margin:4px 10px 0 0;padding-right:30px;border:1px solid #d2d2d2;font-size:0;border-radius:2px;transition:.1s linear;box-sizing:border-box!important}.layui-form-checkbox:hover{border:1px solid #c2c2c2}.layui-form-checkbox span{padding:0 10px;font-size:14px;background-color:#d2d2d2;color:#fff;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.layui-form-checkbox:hover span{background-color:#c2c2c2}.layui-form-checkbox i{position:absolute;right:0;width:37px;color:#fff;font-size:20px}.layui-form-checkbox:hover i{color:#c2c2c2}.layui-form-checked,.layui-form-checked:hover{border:1px solid #5FB878}.layui-form-checked span,.layui-form-checked:hover span{background-color:#5FB878}.layui-form-checked i,.layui-form-checked:hover i{color:#5FB878}.layui-form-switch{position:relative;height:22px;line-height:22px;width:40px;padding:0 5px;margin-top:8px;border:1px solid #d2d2d2;border-radius:20px;background-color:#fff;transition:.1s linear}.layui-form-switch i{position:absolute;left:5px;top:3px;width:16px;height:16px;border-radius:20px;background-color:#d2d2d2;-webkit-transition:.1s linear;transition:.1s linear}.layui-form-onswitch{border-color:#5FB878;background-color:#5FB878}.layui-form-onswitch:before{content:'ON';color:#fff}.layui-form-onswitch i{left:30px;background-color:#fff}.layui-checkbox-disbaled{border-color:#e2e2e2!important}.layui-checkbox-disbaled span{background-color:#e2e2e2!important}.layui-checkbox-disbaled:hover i{color:#fff!important}.layui-form-radio{line-height:28px;margin:6px 10px 0 0;padding-right:10px;cursor:pointer;font-size:0}.layui-form-radio i{margin-right:8px;font-size:22px;color:#c2c2c2}.layui-form-radio span{font-size:14px}.layui-form-radio i:hover,.layui-form-radioed i{color:#5FB878}.layui-radio-disbaled i{color:#e2e2e2!important}.layui-form-pane .layui-form-label{width:80px;padding:8px 15px;line-height:20px;border:1px solid #e6e6e6;border-radius:2px 0 0 2px;text-align:center;background-color:#FBFBFB;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.layui-form-pane .layui-input-inline{margin-left:-1px}.layui-form-pane .layui-input-block{margin-left:112px;left:-1px}.layui-form-pane .layui-input{border-radius:0 2px 2px 0}.layui-form-pane .layui-form-text .layui-form-label{float:none;width:100%;border-right:1px solid #e6e6e6;border-radius:2px;box-sizing:border-box!important;text-align:left}.layui-laypage button,.layui-laypage input,.layui-nav{-webkit-box-sizing:border-box!important;-moz-box-sizing:border-box!important}.layui-form-pane .layui-form-text .layui-input-inline{display:block;margin:0;top:-1px;clear:both}.layui-form-pane .layui-form-text .layui-input-block{margin:0;left:0;top:-1px}.layui-form-pane .layui-form-text .layui-textarea{min-height:100px;border-radius:0 0 2px 2px}.layui-form-pane .layui-input:hover,.layui-form-pane .layui-textarea:hover{border-color:#e6e6e6!important}.layui-form-pane .layui-input:focus,.layui-form-pane .layui-textarea:focus{border-color:#e6e6e6!important}.layui-form-pane .layui-form-checkbox{margin:0 0 10px 10px}.layui-form-pane .layui-form-radio,.layui-form-pane .layui-form-switch{margin-left:10px}.layui-layedit{border:1px solid #d2d2d2;border-radius:2px}.layui-layedit-tool{padding:3px 5px;border-bottom:1px solid #e2e2e2;font-size:0}.layedit-tool-fixed{position:fixed;top:0;border-top:1px solid #e2e2e2}.layui-layedit-tool .layedit-tool-mid,.layui-layedit-tool .layui-icon{display:inline-block;vertical-align:middle;text-align:center;font-size:14px}.layui-layedit-tool .layui-icon{position:relative;width:32px;height:30px;line-height:30px;margin:3px 5px;color:#777;cursor:pointer;border-radius:2px}.layui-layedit-tool .layui-icon:hover{color:#393D49}.layui-layedit-tool .layui-icon:active{color:#000}.layui-layedit-tool .layedit-tool-active{background-color:#e2e2e2;color:#000}.layui-layedit-tool .layui-disabled,.layui-layedit-tool .layui-disabled:hover{color:#d2d2d2;cursor:not-allowed}.layui-layedit-tool .layedit-tool-mid{width:1px;height:18px;margin:0 10px;background-color:#d2d2d2}.layedit-tool-html{width:50px!important;font-size:30px!important}.layedit-tool-b,.layedit-tool-code,.layedit-tool-help{font-size:16px!important}.layedit-tool-d,.layedit-tool-face,.layedit-tool-image,.layedit-tool-unlink{font-size:18px!important}.layedit-tool-image input{position:absolute;font-size:0;left:0;top:0;width:100%;height:100%;opacity:.01;filter:Alpha(opacity=1);cursor:pointer}.layui-layedit-iframe iframe{display:block;width:100%}#LAY_layedit_code{overflow:hidden}.layui-table{width:100%;margin:10px 0;background-color:#fff}.layui-table tr{transition:all .3s;-webkit-transition:all .3s}.layui-table thead tr{background-color:#f2f2f2}.layui-table th{text-align:left}.layui-table td,.layui-table th{padding:9px 15px;min-height:20px;line-height:20px;border:1px solid #e2e2e2;font-size:14px}.layui-table tr:hover,.layui-table[lay-even] tr:nth-child(even){background-color:#f8f8f8}.layui-table[lay-skin=line],.layui-table[lay-skin=row]{border:1px solid #e2e2e2}.layui-table[lay-skin=line] td,.layui-table[lay-skin=line] th{border:none;border-bottom:1px solid #e2e2e2}.layui-table[lay-skin=row] td,.layui-table[lay-skin=row] th{border:none;border-right:1px solid #e2e2e2}.layui-table[lay-skin=nob] td,.layui-table[lay-skin=nob] th{border:none}.layui-upload-button{position:relative;display:inline-block;vertical-align:middle;min-width:60px;height:38px;line-height:38px;border:1px solid #DFDFDF;border-radius:2px;overflow:hidden;background-color:#fff;color:#666}.layui-upload-button:hover{border:1px solid #aaa;color:#333}.layui-upload-button:active{border:1px solid #4CAF50;color:#000}.layui-upload-button input,.layui-upload-file{opacity:.01;filter:Alpha(opacity=1);cursor:pointer}.layui-upload-button input{position:absolute;left:0;top:0;z-index:10;font-size:100px;width:100%;height:100%}.layui-upload-icon{display:block;margin:0 15px;text-align:center}.layui-upload-icon i{margin-right:5px;vertical-align:top;font-size:20px;color:#5FB878}.layui-upload-iframe{position:absolute;width:0;height:0;border:0;visibility:hidden}.layui-upload-enter{border:1px solid #009E94;background-color:#009E94;color:#fff;-webkit-transform:scale(1.1);transform:scale(1.1)}.layui-upload-enter .layui-upload-icon,.layui-upload-enter .layui-upload-icon i{color:#fff}.layui-flow-more{margin:10px 0;text-align:center;color:#999;font-size:14px}.layui-flow-more a{height:32px;line-height:32px}.layui-flow-more a *{display:inline-block;vertical-align:top}.layui-flow-more a cite{padding:0 20px;border-radius:3px;background-color:#eee;color:#333}.layui-flow-more a cite:hover{opacity:.8}.layui-flow-more a i{font-size:30px;color:#737383}.layui-laypage{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;margin:10px 0;font-size:0}.layui-laypage>:first-child,.layui-laypage>:first-child em{border-radius:2px 0 0 2px}.layui-laypage>:last-child,.layui-laypage>:last-child em{border-radius:0 2px 2px 0}.layui-laypage a,.layui-laypage span{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;padding:0 15px;border:1px solid #e2e2e2;height:28px;line-height:28px;margin:0 -1px 5px 0;background-color:#fff;color:#333;font-size:12px}.layui-laypage span{color:#999;font-weight:700}.layui-laypage .layui-laypage-curr{position:relative}.layui-laypage .layui-laypage-curr em{position:relative;color:#fff;font-weight:400}.layui-laypage .layui-laypage-curr .layui-laypage-em{position:absolute;left:-1px;top:-1px;padding:1px;width:100%;height:100%;background-color:#009688}.layui-laypage-em{border-radius:2px}.layui-laypage-next em,.layui-laypage-prev em{font-family:Sim sun;font-size:16px}.layui-laypage .layui-laypage-total{height:30px;line-height:30px;margin-left:1px;border:none;font-weight:400}.layui-laypage button,.layui-laypage input{height:30px;line-height:30px;border:1px solid #e2e2e2;border-radius:2px;vertical-align:top;background-color:#fff;box-sizing:border-box!important}.layui-laypage input{width:50px;margin:0 5px;text-align:center}.layui-laypage button{margin-left:5px;padding:0 15px;cursor:pointer}.layui-code{position:relative;margin:10px 0;padding:15px;line-height:20px;border:1px solid #ddd;border-left-width:6px;background-color:#F2F2F2;color:#333;font-family:Courier New;font-size:12px}.layui-tree{line-height:26px}.layui-tree li{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-tree li .layui-tree-spread,.layui-tree li a{display:inline-block;vertical-align:top;height:26px;*display:inline;*zoom:1;cursor:pointer}.layui-tree li a{font-size:0}.layui-tree li a i{font-size:16px}.layui-tree li a cite{padding:0 6px;font-size:14px}.layui-tree li i{padding-left:6px;color:#333}.layui-tree li .layui-tree-check{font-size:13px}.layui-tree li .layui-tree-check:hover{color:#009E94}.layui-tree li ul{display:none;margin-left:20px}.layui-tree li .layui-tree-enter{line-height:24px;border:1px dotted #000}.layui-tree-drag{display:none;position:absolute;left:-666px;top:-666px;background-color:#f2f2f2;padding:5px 10px;border:1px dotted #000;white-space:nowrap}.layui-nav .layui-nav-item,.layui-tab-title li{display:inline-block;*zoom:1;vertical-align:middle}.layui-tree-drag i{padding-right:5px}.layui-nav{position:relative;padding:0 20px;background-color:#393D49;color:#c2c2c2;border-radius:2px;font-size:0;box-sizing:border-box!important}.layui-nav *{font-size:14px}.layui-nav .layui-nav-item{position:relative;*display:inline;line-height:60px}.layui-nav .layui-nav-item a{display:block;padding:0 20px;color:#c2c2c2;transition:all .3s;-webkit-transition:all .3s}.layui-nav .layui-this:after,.layui-nav-bar,.layui-nav-tree .layui-nav-itemed:after{position:absolute;left:0;top:0;width:0;height:5px;background-color:#5FB878;transition:all .2s;-webkit-transition:all .2s}.layui-nav-bar{z-index:1000}.layui-nav .layui-nav-item a:hover,.layui-nav .layui-this a{color:#fff}.layui-nav .layui-this:after{content:'';top:auto;bottom:0;width:100%}.layui-nav .layui-nav-more{content:'';width:0;height:0;border-style:solid dashed dashed;border-color:#c2c2c2 transparent transparent;overflow:hidden;cursor:pointer;transition:all .2s;-webkit-transition:all .2s;position:absolute;top:28px;right:3px;border-width:6px}.layui-nav .layui-nav-mored,.layui-nav-itemed .layui-nav-more{top:22px;border-style:dashed dashed solid;border-color:transparent transparent #c2c2c2}.layui-nav-child{display:none;position:absolute;left:0;top:65px;line-height:36px;padding:5px 0;border:1px solid #d2d2d2;background-color:#fff;z-index:100;border-radius:2px;white-space:nowrap}.layui-nav .layui-nav-child a{color:#333}.layui-nav .layui-nav-child a:hover{background-color:#f2f2f2;color:#333}.layui-nav-child dd{position:relative}.layui-nav-child dd.layui-this{background-color:#5FB878;color:#fff}.layui-nav-child dd.layui-this a{color:#fff}.layui-nav-child dd.layui-this:after{display:none}.layui-nav-tree{width:200px;padding:0}.layui-nav-tree .layui-nav-item{display:block;width:100%;line-height:45px}.layui-nav-tree .layui-nav-item a{height:45px;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-nav-tree .layui-nav-item a:hover{background-color:#4E5465}.layui-nav-tree .layui-nav-child dd.layui-this,.layui-nav-tree .layui-this,.layui-nav-tree .layui-this>a,.layui-nav-tree .layui-this>a:hover{background-color:#009688;color:#fff}.layui-nav-tree .layui-this:after{display:none}.layui-nav-itemed>a,.layui-nav-tree .layui-nav-title a,.layui-nav-tree .layui-nav-title a:hover{background-color:#2B2E37!important;color:#fff!important}.layui-nav-tree .layui-nav-bar{width:5px;height:0;background-color:#009688}.layui-nav-tree .layui-nav-child{position:relative;z-index:0;top:0;border:none;box-shadow:none}.layui-nav-tree .layui-nav-child a{height:40px;line-height:40px;color:#c2c2c2}.layui-nav-tree .layui-nav-child,.layui-nav-tree .layui-nav-child a:hover{background:0 0;color:#fff}.layui-nav-tree .layui-nav-more{top:20px;right:10px}.layui-nav-itemed .layui-nav-more{top:14px}.layui-nav-itemed .layui-nav-child{display:block;padding:0}.layui-nav-side{position:fixed;top:0;bottom:0;left:0;overflow-x:hidden;z-index:999}.layui-breadcrumb{visibility:hidden;font-size:0}.layui-breadcrumb a{padding-right:8px;line-height:22px;font-size:14px;color:#333!important}.layui-breadcrumb a:hover{color:#01AAED!important}.layui-breadcrumb a cite,.layui-breadcrumb a span{color:#666;cursor:text;font-style:normal}.layui-breadcrumb a span{padding-left:8px;font-family:Sim sun}.layui-tab{margin:10px 0;overflow:hidden;text-align:left!important}.layui-fixbar li,.layui-tab-bar,.layui-tab-title li,.layui-util-face ul li{cursor:pointer;text-align:center}.layui-tab-title{position:relative;left:0;height:40px;white-space:nowrap;font-size:0;border-bottom:1px solid #e2e2e2;transition:all .2s;-webkit-transition:all .2s}.layui-tab-title li{*display:inline;font-size:14px;transition:all .3s;-webkit-transition:all .3s;position:relative;line-height:40px;min-width:65px;padding:0 10px}.layui-tab-title .layui-this{color:#000}.layui-tab-title .layui-this:after{position:absolute;left:0;top:0;content:'';width:100%;height:41px;border:1px solid #e2e2e2;border-bottom-color:#fff;border-radius:2px 2px 0 0;-webkit-box-sizing:border-box!important;-moz-box-sizing:border-box!important;box-sizing:border-box!important;pointer-events:none}.layui-tab-bar{position:absolute;right:0;top:0;width:30px;height:39px;line-height:39px;border:1px solid #e2e2e2;border-radius:2px;background-color:#fff}.layui-tab-bar .layui-icon{position:relative;display:inline-block;top:3px;transition:all .3s;-webkit-transition:all .3s}.layui-tab-item,.layui-util-face .layui-layer-TipsG{display:none}.layui-tab-more{padding-right:30px;height:auto;white-space:normal}.layui-tab-more li.layui-this:after{border-bottom-color:#e2e2e2;border-radius:2px}.layui-tab-more .layui-tab-bar .layui-icon{top:-2px;top:3px\\9;-webkit-transform:rotate(180deg);transform:rotate(180deg)}:root .layui-tab-more .layui-tab-bar .layui-icon{top:-2px\\0/IE9}.layui-tab-content{padding:10px}.layui-tab-title li .layui-tab-close{position:relative;margin-left:8px;top:1px;color:#c2c2c2}.layui-tab-title li .layui-tab-close:hover{border-radius:10px;background-color:#FF5722;color:#fff}.layui-tab-brief>.layui-tab-title .layui-this{color:#009688}.layui-tab-brief>.layui-tab-more li.layui-this:after,.layui-tab-brief>.layui-tab-title .layui-this:after{border:none;border-radius:0;border-bottom:3px solid #5FB878}.layui-tab-card{border:1px solid #e2e2e2;border-radius:2px;box-shadow:0 2px 5px 0 rgba(0,0,0,.1)}.layui-tab-card>.layui-tab-title{background-color:#f2f2f2}.layui-tab-card>.layui-tab-title li{margin-right:-1px;margin-left:-1px}.layui-tab-card>.layui-tab-title .layui-this{background-color:#fff}.layui-tab-card>.layui-tab-title .layui-this:after{border-top:none;border-width:1px;border-bottom-color:#fff}.layui-tab-card>.layui-tab-title .layui-tab-bar{height:40px;line-height:40px;border-radius:0;border-top:none;border-right:none}.layui-tab-card>.layui-tab-more .layui-this{background:0 0;color:#5FB878}.layui-tab-card>.layui-tab-more .layui-this:after{border:none}.layui-fixbar{position:fixed;right:15px;bottom:15px;z-index:9999}.layui-fixbar li{width:50px;height:50px;line-height:50px;margin-bottom:1px;font-size:30px;background-color:#9F9F9F;color:#fff;border-radius:2px;opacity:.95}.layui-fixbar li:hover{opacity:.85}.layui-fixbar li:active{opacity:1}.layui-fixbar .layui-fixbar-top{display:none;font-size:40px}body .layui-util-face{border:none;background:0 0}body .layui-util-face .layui-layer-content{padding:0;background-color:#fff;color:#666;box-shadow:none}.layui-util-face ul{position:relative;width:372px;padding:10px;border:1px solid #D9D9D9;background-color:#fff;box-shadow:0 0 20px rgba(0,0,0,.2)}.layui-util-face ul li{float:left;border:1px solid #e8e8e8;height:22px;width:26px;overflow:hidden;margin:-1px 0 0 -1px;padding:4px 2px}.layui-util-face ul li:hover{position:relative;z-index:2;border:1px solid #eb7350;background:#fff9ec}.layui-anim{-webkit-animation-duration:.3s;animation-duration:.3s;-webkit-animation-fill-mode:both;animation-fill-mode:both}.layui-anim-loop{-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}@-webkit-keyframes layui-rotate{from{-webkit-transform:rotate(0)}to{-webkit-transform:rotate(360deg)}}@keyframes layui-rotate{from{transform:rotate(0)}to{transform:rotate(360deg)}}.layui-anim-rotate{-webkit-animation-name:layui-rotate;animation-name:layui-rotate;-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-timing-function:linear;animation-timing-function:linear}@-webkit-keyframes layui-up{from{-webkit-transform:translate3d(0,100%,0);opacity:.3}to{-webkit-transform:translate3d(0,0,0);opacity:1}}@keyframes layui-up{from{transform:translate3d(0,100%,0);opacity:.3}to{transform:translate3d(0,0,0);opacity:1}}.layui-anim-up{-webkit-animation-name:layui-up;animation-name:layui-up}@-webkit-keyframes layui-upbit{from{-webkit-transform:translate3d(0,30px,0);opacity:.3}to{-webkit-transform:translate3d(0,0,0);opacity:1}}@keyframes layui-upbit{from{transform:translate3d(0,30px,0);opacity:.3}to{transform:translate3d(0,0,0);opacity:1}}.layui-anim-upbit{-webkit-animation-name:layui-upbit;animation-name:layui-upbit}@-webkit-keyframes layui-scale{0%{opacity:.3;-webkit-transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1)}}@keyframes layui-scale{0%{opacity:.3;-ms-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-ms-transform:scale(1);transform:scale(1)}}.layui-anim-scale{-webkit-animation-name:layui-scale;animation-name:layui-scale}@-webkit-keyframes layui-scale-spring{0%{opacity:.5;-webkit-transform:scale(.5)}80%{opacity:.8;-webkit-transform:scale(1.1)}100%{opacity:1;-webkit-transform:scale(1)}}@keyframes layui-scale-spring{0%{opacity:.5;-ms-transform:scale(.5);transform:scale(.5)}80%{opacity:.8;-ms-transform:scale(1.1);transform:scale(1.1)}100%{opacity:1;-ms-transform:scale(1);transform:scale(1)}}.layui-anim-scaleSpring{-webkit-animation-name:layui-scale-spring;animation-name:layui-scale-spring}@media screen and (max-width:450px){.layui-form-item .layui-form-label{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-form-item .layui-inline{display:block;margin-right:0;margin-bottom:20px;clear:both}.layui-form-item .layui-inline:after{content:'\\20';clear:both;display:block;height:0}.layui-form-item .layui-input-inline{display:block;float:none;left:-1px;width:auto;margin:0 0 10px 112px}.layui-form-item .layui-input-inline+.layui-form-mid{margin-left:110px;top:-5px;padding:0}.layui-form-item .layui-form-checkbox{margin-right:5px;margin-bottom:5px}}"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/code.css",
    "content": "/** layui-v1.0.7 LGPL License By http://www.layui.com */\n html #layuicss-skincodecss{display:none;position:absolute;width:1989px}.layui-code-h3,.layui-code-view{position:relative;font-size:12px}.layui-code-view{display:block;margin:10px 0;padding:0;border:1px solid #ddd;border-left-width:6px;background-color:#F2F2F2;color:#333;font-family:Courier New}.layui-code-h3{padding:0 10px;height:30px;line-height:30px;border-bottom:1px solid #ddd}.layui-code-h3 a{position:absolute;right:10px;top:0;color:#999}.layui-code-view .layui-code-ol{position:relative;overflow:auto}.layui-code-view .layui-code-ol li{position:relative;margin-left:45px;line-height:20px;padding:0 5px;border-left:1px solid #ddd;list-style-type:decimal-leading-zero;*list-style-type:decimal;background-color:#fff}.layui-code-view pre{margin:0}.layui-code-notepad{border:1px solid #0C0C0C;border-left-color:#3F3F3F;background-color:#0C0C0C;color:#C2BE9E}.layui-code-notepad .layui-code-h3{border-bottom:none}.layui-code-notepad .layui-code-ol li{background-color:#3F3F3F;border-left:none}"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/icheck/icheck.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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/icheck/minimal/_all.css",
    "content": "/* iCheck plugin Minimal skin\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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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}\n\n/* 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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/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/* HiDPI support */\n@media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {\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": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/laydate/laydate.css",
    "content": "/** layui-v1.0.7 LGPL License By http://www.layui.com */\n #layuicss-laydatecss{display:none;position:absolute;width:1989px}.laydate_body .laydate_box,.laydate_body .laydate_box *{margin:0;padding:0;box-sizing:content-box}.laydate-icon,.laydate-icon-dahong,.laydate-icon-danlan,.laydate-icon-default,.laydate-icon-molv{height:22px;line-height:22px;padding-right:20px;border:1px solid #C6C6C6;background-repeat:no-repeat;background-position:right center;background-color:#fff;outline:0}.laydate-icon-default{background-image:url(../skins/default/icon.png)}.laydate-icon-danlan{border:1px solid #B1D2EC;background-image:url(../skins/danlan/icon.png)}.laydate-icon-dahong{background-image:url(../skins/dahong/icon.png)}.laydate-icon-molv{background-image:url(../skins/molv/icon.png)}.laydate_body .laydate_box{width:240px;font:12px '\\5B8B\\4F53';z-index:99999999;*overflow:hidden;_margin:0;_position:absolute!important}.laydate_body .laydate_box li{list-style:none}.laydate_body .laydate_box .laydate_void{cursor:text!important}.laydate_body .laydate_box cite,.laydate_body .laydate_box label{position:absolute;width:0;height:0;border-width:5px;border-style:dashed;border-color:transparent;overflow:hidden;cursor:pointer}.laydate_body .laydate_box .laydate_time,.laydate_body .laydate_box .laydate_yms{display:none}.laydate_body .laydate_box .laydate_show{display:block}.laydate_body .laydate_box input{outline:0;font-size:14px;background-color:#fff;color:#333}.laydate_body .laydate_top{position:relative;height:26px;padding:5px;*width:100%;z-index:99}.laydate_body .laydate_ym{position:relative;float:left;height:24px;cursor:pointer}.laydate_body .laydate_ym input{float:left;height:24px;line-height:24px;text-align:center;border:none;cursor:pointer}.laydate_body .laydate_ym .laydate_yms{position:absolute;left:-1px;top:24px;height:181px}.laydate_body .laydate_y{width:121px;margin-right:6px}.laydate_body .laydate_y input{width:64px;margin-right:15px}.laydate_body .laydate_y .laydate_yms{width:121px;text-align:center}.laydate_body .laydate_y .laydate_yms a{position:relative;display:block;height:20px}.laydate_body .laydate_y .laydate_yms ul{height:139px;padding:0;*overflow:hidden}.laydate_body .laydate_y .laydate_yms ul li{float:left;width:60px;height:20px;line-height:20px;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.laydate_body .laydate_m{width:99px}.laydate_body .laydate_m .laydate_yms{width:99px;padding:0}.laydate_body .laydate_m input{width:42px;margin-right:15px}.laydate_body .laydate_m .laydate_yms span{display:block;float:left;width:42px;margin:5px 0 0 5px;line-height:24px;text-align:center;_display:inline}.laydate_body .laydate_choose{display:block;float:left;position:relative;width:20px;height:24px}.laydate_body .laydate_choose cite,.laydate_body .laydate_tab cite{left:50%;top:50%}.laydate_body .laydate_chtop cite{margin:-7px 0 0 -5px;border-bottom-style:solid}.laydate_body .laydate_chdown cite,.laydate_body .laydate_ym label{top:50%;margin:-2px 0 0 -5px;border-top-style:solid}.laydate_body .laydate_chprev cite{margin:-5px 0 0 -7px}.laydate_body .laydate_chnext cite{margin:-5px 0 0 -2px}.laydate_body .laydate_ym label{right:28px}.laydate_body .laydate_table{width:230px;margin:0 5px;border-collapse:collapse;border-spacing:0}.laydate_body .laydate_table td{width:31px;text-align:center;cursor:pointer;font-size:12px}.laydate_body .laydate_table thead th{font-weight:400;font-size:12px;text-align:center}.laydate_body .laydate_bottom{position:relative;height:22px;line-height:20px;padding:5px;font-size:12px}.laydate_body .laydate_bottom #laydate_hms{position:relative;z-index:1;float:left}.laydate_body .laydate_time{position:absolute;left:5px;bottom:26px;width:129px;height:125px;*overflow:hidden}.laydate_body .laydate_time .laydate_hmsno{padding:5px 0 0 5px}.laydate_body .laydate_time .laydate_hmsno span{display:block;float:left;width:24px;height:19px;line-height:19px;text-align:center;cursor:pointer;*margin-bottom:-5px}.laydate_body .laydate_time1{width:228px;height:154px}.laydate_body .laydate_time1 .laydate_hmsno{padding:6px 0 0 8px}.laydate_body .laydate_time1 .laydate_hmsno span{width:21px;height:20px;line-height:20px}.laydate_body .laydate_msg{left:49px;bottom:67px;width:141px;height:auto;overflow:hidden}.laydate_body .laydate_msg p{padding:5px 10px}.laydate_body .laydate_bottom li{float:left;height:20px;line-height:20px;border-right:none;font-weight:900}.laydate_body .laydate_bottom .laydate_sj{width:33px;text-align:center;font-weight:400}.laydate_body .laydate_bottom input{float:left;width:21px;height:20px;line-height:20px;border:none;text-align:center;cursor:pointer;font-size:12px;font-weight:400}.laydate_body .laydate_bottom .laydte_hsmtex{height:20px;line-height:20px;text-align:center}.laydate_body .laydate_bottom .laydte_hsmtex span{position:absolute;width:20px;top:0;right:0;cursor:pointer}.laydate_body .laydate_bottom .laydte_hsmtex span:hover{font-size:14px}.laydate_body .laydate_bottom .laydate_btn{position:absolute;right:5px;top:5px}.laydate_body .laydate_bottom .laydate_btn a{float:left;height:20px;padding:0 6px;_padding:0 5px}.laydate_body .laydate_table td,.laydate_body .laydate_table thead{height:21px!important;line-height:21px!important}.laydate-icon{border:1px solid #C6C6C6;background-image:url(icon.png)}.laydate_body .laydate_bottom #laydate_hms,.laydate_body .laydate_bottom .laydate_btn a,.laydate_body .laydate_box,.laydate_body .laydate_table,.laydate_body .laydate_table td,.laydate_body .laydate_time,.laydate_body .laydate_ym,.laydate_body .laydate_ym .laydate_yms{border:1px solid #ccc}.laydate_body .laydate_bottom .laydte_hsmtex,.laydate_body .laydate_choose,.laydate_body .laydate_table thead,.laydate_body .laydate_y .laydate_yms a{background-color:#F6F6F6}.laydate_body .laydate_box,.laydate_body .laydate_time,.laydate_body .laydate_ym .laydate_yms{box-shadow:2px 2px 5px rgba(0,0,0,.1)}.laydate_body .laydate_box{border-top:none;border-bottom:none;background-color:#fff;color:#333}.laydate_body .laydate_box .laydate_void{color:#ccc!important}.laydate_body .laydate_box .laydate_void:hover{background-color:#fff!important}.laydate_body .laydate_box a,.laydate_body .laydate_box a:hover{text-decoration:none;blr:expression(this.onFocus=this.blur());cursor:pointer;color:#333}.laydate_body .laydate_box a:hover{text-decoration:none;color:#666}.laydate_body .laydate_click{background-color:#eee!important}.laydate_body .laydate_bottom #laydate_hms,.laydate_body .laydate_choose:hover,.laydate_body .laydate_table td,.laydate_body .laydate_time,.laydate_body .laydate_y .laydate_yms a:hover{background-color:#fff}.laydate_body .laydate_top{border-top:1px solid #C6C6C6}.laydate_body .laydate_ym .laydate_yms{border:1px solid #C6C6C6;background-color:#fff}.laydate_body .laydate_y .laydate_yms a{border-bottom:1px solid #C6C6C6}.laydate_body .laydate_y .laydate_yms .laydate_chdown{border-top:1px solid #C6C6C6;border-bottom:none}.laydate_body .laydate_choose{border-left:1px solid #C6C6C6}.laydate_body .laydate_chprev{border-left:none;border-right:1px solid #C6C6C6}.laydate_body .laydate_chtop cite{border-bottom-color:#666}.laydate_body .laydate_chdown cite,.laydate_body .laydate_ym label{border-top-color:#666}.laydate_body .laydate_chprev cite{border-right-style:solid;border-right-color:#666}.laydate_body .laydate_chnext cite{border-left-style:solid;border-left-color:#666}.laydate_body .laydate_table td{border:none}.laydate_body .laydate_table .laydate_nothis{color:#999}.laydate_body .laydate_table thead th{border-bottom:1px solid #ccc}.laydate_body .laydate_bottom,.laydate_body .laydate_bottom .laydte_hsmtex{border-bottom:1px solid #C6C6C6}.laydate_body .laydate_bottom .laydate_sj{border-right:1px solid #C6C6C6;background-color:#F6F6F6}.laydate_body .laydate_bottom input{background-color:#fff}.laydate_body .laydate_bottom .laydate_btn{border-right:1px solid #C6C6C6}.laydate_body .laydate_bottom .laydate_v{position:absolute;left:10px;top:6px;font-family:Courier;z-index:0;color:#999}.laydate_body .laydate_bottom .laydate_btn a{border-right:none;background-color:#F6F6F6}.laydate_body .laydate_bottom .laydate_btn a:hover{color:#000;background-color:#fff}.laydate_body .laydate_m .laydate_yms span:hover,.laydate_body .laydate_table td:hover,.laydate_body .laydate_time .laydate_hmsno span:hover,.laydate_body .laydate_y .laydate_yms ul li:hover{background-color:#F3F3F3}"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/plugins/layui/css/modules/layer/default/layer.css",
    "content": "/** layui-v1.0.7 LGPL License By http://www.layui.com */\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 #layuicss-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)}.layui-layer-close{position:absolute}.layui-layer-content{position:relative}.layui-layer-border{border:1px solid #B2B2B2;border:1px solid rgba(0,0,0,.1);box-shadow:1px 1px 5px rgba(0,0,0,.2)}.layui-layer-load{background:url(loading-1.gif) center center no-repeat #eee}.layui-layer-ico{background:url(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}.layui-layer-move{display:none;position:fixed;*position:absolute;left:0;top:0;width:100%;height:100%;cursor:move;opacity:0;filter:alpha(opacity=0);background-color:#fff;z-index:2147483647}.layui-layer-resize{position:absolute;width:15px;height:15px;right:0;bottom:0;cursor:se-resize}.layui-layer{border-radius:2px;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:.3s;animation-duration:.3s}@-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 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}}@-webkit-keyframes bounceOut{100%{opacity:0;-webkit-transform:scale(.7);transform:scale(.7)}30%{-webkit-transform:scale(1.05);transform:scale(1.05)}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.05);-ms-transform:scale(1.05);transform:scale(1.05)}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}.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;user-select:none;-webkit-user-select:none}.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:.8}.layui-layer-btn .layui-layer-btn0{border-color:#4898d5;background-color:#2e8ded;color:#fff}.layui-layer-btn-l{text-align:left}.layui-layer-btn-c{text-align:center}.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 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(loading-0.gif) no-repeat}.layui-layer-loading .layui-layer-loading1{width:37px;height:37px;background:url(loading-1.gif) no-repeat}.layui-layer-ico16,.layui-layer-loading .layui-layer-loading2{width:32px;height:32px;background:url(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:2px;box-shadow:1px 1px 3px rgba(0,0,0,.2);background-color:#000;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:#000}.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:#000}.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(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-prompt .layui-layer-content{padding:20px}.layui-layer-prompt .layui-layer-btn{padding-top:0}.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}@media screen and (max-width:1100px){.layui-layer-iframe{overflow-y:auto;-webkit-overflow-scrolling:touch}}"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/plugins/layui/lay/dest/layui.all.js",
    "content": "/** layui-v1.0.7 LGPL License By http://www.layui.com */\n ;!function(e){\"use strict\";var t=function(){this.v=\"1.0.7\"};t.fn=t.prototype;var n=document,o=t.fn.cache={},i=function(){var e=n.scripts,t=e[e.length-1].src;return t.substring(0,t.lastIndexOf(\"/\")+1)}(),r=function(t){e.console&&console.error&&console.error(\"Layui hint: \"+t)},u=\"undefined\"!=typeof opera&&\"[object Opera]\"===opera.toString(),l={layer:\"modules/layer\",laydate:\"modules/laydate\",laypage:\"modules/laypage\",laytpl:\"modules/laytpl\",layim:\"modules/layim\",layedit:\"modules/layedit\",form:\"modules/form\",upload:\"modules/upload\",tree:\"modules/tree\",slide:\"modules/slide\",table:\"modules/table\",element:\"modules/element\",util:\"modules/util\",flow:\"modules/flow\",code:\"modules/code\",single:\"modules/single\",mobile:\"modules/mobile\",jquery:\"lib/jquery\",\"layui.mod\":\"dest/layui.mod\"};o.modules={},o.status={},o.timeout=10,o.event={},t.fn.define=function(e,t){var n=this,i=\"function\"==typeof e,r=function(){return\"function\"==typeof t&&t(function(e,t){layui[e]=t,o.status[e]=!0}),this};return i&&(t=e,e=[]),layui[\"layui.all\"]?r.call(n):(n.use(e,r),n)},t.fn.use=function(e,t,a){function s(e,t){var n=\"PLaySTATION 3\"===navigator.platform?/^complete$/:/^(complete|loaded)$/;(\"load\"===e.type||n.test((e.currentTarget||e.srcElement).readyState))&&(o.modules[m]=t,y.removeChild(v),function i(){return++p>1e3*o.timeout/4?r(m+\" is not a valid module\"):void(o.status[m]?c():setTimeout(i,4))}())}function c(){a.push(layui[m]),e.length>1?f.use(e.slice(1),t,a):\"function\"==typeof t&&t.apply(layui,a)}var f=this,d=o.dir=o.dir?o.dir:i,y=n.getElementsByTagName(\"head\")[0];e=\"string\"==typeof e?[e]:e,window.jQuery&&jQuery.fn.on&&(f.each(e,function(t,n){\"jquery\"===n&&e.splice(t,1)}),layui.jquery=jQuery);var m=e[0],p=0;if(a=a||[],o.host=o.host||(d.match(/\\/\\/([\\s\\S]+?)\\//)||[\"//\"+location.host+\"/\"])[0],0===e.length||layui[\"layui.all\"]&&l[m])return\"function\"==typeof t&&t.apply(layui,a),f;var v=n.createElement(\"script\"),h=(l[m]?d+\"lay/\":o.base||\"\")+(f.modules[m]||m)+\".js\";return v.async=!0,v.charset=\"utf-8\",v.src=h+function(){var e=o.version===!0?o.v||(new Date).getTime():o.version||\"\";return e?\"?v=\"+e:\"\"}(),o.modules[m]?!function g(){return++p>1e3*o.timeout/4?r(m+\" is not a valid module\"):void(\"string\"==typeof o.modules[m]&&o.status[m]?c():setTimeout(g,4))}():(y.appendChild(v),!v.attachEvent||v.attachEvent.toString&&v.attachEvent.toString().indexOf(\"[native code\")<0||u?v.addEventListener(\"load\",function(e){s(e,h)},!1):v.attachEvent(\"onreadystatechange\",function(e){s(e,h)})),o.modules[m]=h,f},t.fn.getStyle=function(t,n){var o=t.currentStyle?t.currentStyle:e.getComputedStyle(t,null);return o[o.getPropertyValue?\"getPropertyValue\":\"getAttribute\"](n)},t.fn.link=function(e,t,i){var u=this,l=n.createElement(\"link\"),a=n.getElementsByTagName(\"head\")[0];\"string\"==typeof t&&(i=t);var s=(i||e).replace(/\\.|\\//g,\"\"),c=l.id=\"layuicss-\"+s,f=0;l.rel=\"stylesheet\",l.href=e+(o.debug?\"?v=\"+(new Date).getTime():\"\"),l.media=\"all\",n.getElementById(c)||a.appendChild(l),\"function\"==typeof t&&!function d(){return++f>1e3*o.timeout/100?r(e+\" timeout\"):void(1989===parseInt(u.getStyle(n.getElementById(c),\"width\"))?function(){t()}():setTimeout(d,100))}()},t.fn.addcss=function(e,t,n){layui.link(o.dir+\"css/\"+e,t,n)},t.fn.img=function(e,t,n){var o=new Image;return o.src=e,o.complete?t(o):(o.onload=function(){o.onload=null,t(o)},void(o.onerror=function(e){o.onerror=null,n(e)}))},t.fn.config=function(e){e=e||{};for(var t in e)o[t]=e[t];return this},t.fn.modules=function(){var e={};for(var t in l)e[t]=l[t];return e}(),t.fn.extend=function(e){var t=this;e=e||{};for(var n in e)t[n]||t.modules[n]?r(\"模块名 \"+n+\" 已被占用\"):t.modules[n]=e[n];return t},t.fn.router=function(e){for(var t,n=(e||location.hash).replace(/^#/,\"\").split(\"/\")||[],o={dir:[]},i=0;i<n.length;i++)t=n[i].split(\"=\"),/^\\w+=/.test(n[i])?function(){\"dir\"!==t[0]&&(o[t[0]]=t[1])}():o.dir.push(n[i]),t=null;return o},t.fn.data=function(t,n){if(t=t||\"layui\",e.JSON&&e.JSON.parse){if(null===n)return delete localStorage[t];n=\"object\"==typeof n?n:{key:n};try{var o=JSON.parse(localStorage[t])}catch(i){var o={}}return n.value&&(o[n.key]=n.value),n.remove&&delete o[n.key],localStorage[t]=JSON.stringify(o),n.key?o[n.key]:o}},t.fn.device=function(t){var n=navigator.userAgent.toLowerCase(),o=function(e){var t=new RegExp(e+\"/([^\\\\s\\\\_\\\\-]+)\");return e=(n.match(t)||[])[1],e||!1},i={os:function(){return/windows/.test(n)?\"windows\":/linux/.test(n)?\"linux\":/iphone|ipod|ipad|ios/.test(n)?\"ios\":void 0}(),ie:function(){return!!(e.ActiveXObject||\"ActiveXObject\"in e)&&((n.match(/msie\\s(\\d+)/)||[])[1]||\"11\")}(),weixin:o(\"micromessenger\")};return t&&!i[t]&&(i[t]=o(t)),i.android=/android/.test(n),i.ios=\"ios\"===i.os,i},t.fn.hint=function(){return{error:r}},t.fn.each=function(e,t){var n,o=this;if(\"function\"!=typeof t)return o;if(e=e||[],e.constructor===Object){for(n in e)if(t.call(e[n],n,e[n]))break}else for(n=0;n<e.length&&!t.call(e[n],n,e[n]);n++);return o},t.fn.stope=function(t){t=t||e.event,t.stopPropagation?t.stopPropagation():t.cancelBubble=!0},t.fn.onevent=function(e,t,n){return\"string\"!=typeof e||\"function\"!=typeof n?this:(o.event[e+\".\"+t]=[n],this)},t.fn.event=function(e,t,n){var i=this,r=null,u=t.match(/\\(.*\\)$/)||[],l=(t=e+\".\"+t).replace(u,\"\"),a=function(e,t){var o=t&&t.call(i,n);o===!1&&null===r&&(r=!1)};return layui.each(o.event[l],a),u[0]&&layui.each(o.event[t],a),r},e.layui=new t}(window);layui.define(function(a){var i=layui.cache;layui.config({dir:i.dir.replace(/lay\\/dest\\/$/,\"\")}),a(\"layui.all\",layui.v)});layui.define(function(e){\"use strict\";var r={open:\"{{\",close:\"}}\"},n={exp:function(e){return new RegExp(e,\"g\")},query:function(e,n,t){var o=[\"#([\\\\s\\\\S])+?\",\"([^{#}])*?\"][e||0];return c((n||\"\")+r.open+o+r.close+(t||\"\"))},escape:function(e){return String(e||\"\").replace(/&(?!#?[a-zA-Z0-9]+;)/g,\"&amp;\").replace(/</g,\"&lt;\").replace(/>/g,\"&gt;\").replace(/'/g,\"&#39;\").replace(/\"/g,\"&quot;\")},error:function(e,r){var n=\"Laytpl Error：\";return\"object\"==typeof console&&console.error(n+e+\"\\n\"+(r||\"\")),n+e}},c=n.exp,t=function(e){this.tpl=e};t.pt=t.prototype,window.errors=0,t.pt.parse=function(e,t){var o=this,p=e,a=c(\"^\"+r.open+\"#\",\"\"),l=c(r.close+\"$\",\"\");e=e.replace(/\\s+|\\r|\\t|\\n/g,\" \").replace(c(r.open+\"#\"),r.open+\"# \").replace(c(r.close+\"}\"),\"} \"+r.close).replace(/\\\\/g,\"\\\\\\\\\").replace(/(?=\"|')/g,\"\\\\\").replace(n.query(),function(e){return e=e.replace(a,\"\").replace(l,\"\"),'\";'+e.replace(/\\\\/g,\"\")+';view+=\"'}).replace(n.query(1),function(e){var n='\"+(';return e.replace(/\\s/g,\"\")===r.open+r.close?\"\":(e=e.replace(c(r.open+\"|\"+r.close),\"\"),/^=/.test(e)&&(e=e.replace(/^=/,\"\"),n='\"+_escape_('),n+e.replace(/\\\\/g,\"\")+')+\"')}),e='\"use strict\";var view = \"'+e+'\";return view;';try{return o.cache=e=new Function(\"d, _escape_\",e),e(t,n.escape)}catch(u){return delete o.cache,n.error(u,p)}},t.pt.render=function(e,r){var c,t=this;return e?(c=t.cache?t.cache(e,n.escape):t.parse(t.tpl,e),r?void r(c):c):n.error(\"no data\")};var o=function(e){return\"string\"!=typeof e?n.error(\"Template not found\"):new t(e)};o.config=function(e){e=e||{};for(var n in e)r[n]=e[n]},o.v=\"1.2.0\",e(\"laytpl\",o)});layui.define(function(a){\"use strict\";function t(a){new p(a)}var e=document,r=\"getElementById\",n=\"getElementsByTagName\",s=0,p=function(a){var t=this,e=t.config=a||{};e.item=s++,t.render(!0)};p.on=function(a,t,e){return a.attachEvent?a.attachEvent(\"on\"+t,function(){e.call(a,window.even)}):a.addEventListener(t,e,!1),p},p.prototype.type=function(){var a=this.config;if(\"object\"==typeof a.cont)return void 0===a.cont.length?2:3},p.prototype.view=function(){var a=this,t=a.config,e=[],r={};if(t.pages=0|t.pages,t.curr=0|t.curr||1,t.groups=\"groups\"in t?0|t.groups:5,t.first=\"first\"in t?t.first:\"&#x9996;&#x9875;\",t.last=\"last\"in t?t.last:\"&#x672B;&#x9875;\",t.prev=\"prev\"in t?t.prev:\"&#x4E0A;&#x4E00;&#x9875;\",t.next=\"next\"in t?t.next:\"&#x4E0B;&#x4E00;&#x9875;\",t.pages<=1)return\"\";for(t.groups>t.pages&&(t.groups=t.pages),r.index=Math.ceil((t.curr+(t.groups>1&&t.groups!==t.pages?1:0))/(0===t.groups?1:t.groups)),t.curr>1&&t.prev&&e.push('<a href=\"javascript:;\" class=\"layui-laypage-prev\" data-page=\"'+(t.curr-1)+'\">'+t.prev+\"</a>\"),r.index>1&&t.first&&0!==t.groups&&e.push('<a href=\"javascript:;\" class=\"laypage_first\" data-page=\"1\"  title=\"&#x9996;&#x9875;\">'+t.first+\"</a><span>&#x2026;</span>\"),r.poor=Math.floor((t.groups-1)/2),r.start=r.index>1?t.curr-r.poor:1,r.end=r.index>1?function(){var a=t.curr+(t.groups-r.poor-1);return a>t.pages?t.pages:a}():t.groups,r.end-r.start<t.groups-1&&(r.start=r.end-t.groups+1);r.start<=r.end;r.start++)r.start===t.curr?e.push('<span class=\"layui-laypage-curr\"><em class=\"layui-laypage-em\" '+(/^#/.test(t.skin)?'style=\"background-color:'+t.skin+';\"':\"\")+\"></em><em>\"+r.start+\"</em></span>\"):e.push('<a href=\"javascript:;\" data-page=\"'+r.start+'\">'+r.start+\"</a>\");return t.pages>t.groups&&r.end<t.pages&&t.last&&0!==t.groups&&e.push('<span>&#x2026;</span><a href=\"javascript:;\" class=\"layui-laypage-last\" title=\"&#x5C3E;&#x9875;\"  data-page=\"'+t.pages+'\">'+t.last+\"</a>\"),r.flow=!t.prev&&0===t.groups,(t.curr!==t.pages&&t.next||r.flow)&&e.push(function(){return r.flow&&t.curr===t.pages?'<span class=\"layui-laypage-nomore\" title=\"&#x5DF2;&#x6CA1;&#x6709;&#x66F4;&#x591A;\">'+t.next+\"</span>\":'<a href=\"javascript:;\" class=\"layui-laypage-next\" data-page=\"'+(t.curr+1)+'\">'+t.next+\"</a>\"}()),'<div class=\"layui-box layui-laypage layui-laypage-'+(t.skin?function(a){return/^#/.test(a)?\"molv\":a}(t.skin):\"default\")+'\" id=\"layui-laypage-'+a.config.item+'\">'+e.join(\"\")+function(){return t.skip?'<span class=\"layui-laypage-total\">&#x5230;&#x7B2C; <input type=\"number\" min=\"1\" onkeyup=\"this.value=this.value.replace(/\\\\D/, \\'\\');\" value=\"'+t.curr+'\" class=\"layui-laypage-skip\"> &#x9875; <button type=\"button\" class=\"layui-laypage-btn\">&#x786e;&#x5b9a;</button></span>':\"\"}()+\"</div>\"},p.prototype.jump=function(a){if(a){for(var t=this,e=t.config,r=a.children,s=a[n](\"button\")[0],i=a[n](\"input\")[0],u=0,o=r.length;u<o;u++)\"a\"===r[u].nodeName.toLowerCase()&&p.on(r[u],\"click\",function(){var a=0|this.getAttribute(\"data-page\");e.curr=a,t.render()});s&&p.on(s,\"click\",function(){var a=0|i.value.replace(/\\s|\\D/g,\"\");a&&a<=e.pages&&(e.curr=a,t.render())})}},p.prototype.render=function(a){var t=this,n=t.config,s=t.type(),p=t.view();2===s?n.cont.innerHTML=p:3===s?n.cont.html(p):e[r](n.cont).innerHTML=p,n.jump&&n.jump(n,a),t.jump(e[r](\"layui-laypage-\"+n.item)),n.hash&&!a&&(location.hash=\"!\"+n.hash+\"=\"+n.curr)},a(\"laypage\",t)});layui.define(function(e){\"use strict\";var t=window,a={path:\"\",skin:\"default\",format:\"YYYY-MM-DD\",min:\"1900-01-01 00:00:00\",max:\"2099-12-31 23:59:59\",isv:!1,init:!0},n={},s=document,i=\"createElement\",o=\"getElementById\",l=\"getElementsByTagName\",d=[\"laydate_box\",\"laydate_void\",\"laydate_click\",\"LayDateSkin\",\"skins/\",\"/laydate.css\"];t.laydate=function(e){return e=e||{},n.run(e),laydate},laydate.v=\"1.1\",n.trim=function(e){return e=e||\"\",e.replace(/^\\s|\\s$/g,\"\").replace(/\\s+/g,\" \")},n.digit=function(e){return e<10?\"0\"+(0|e):e},n.stopmp=function(e){return e=e||t.event,e.stopPropagation?e.stopPropagation():e.cancelBubble=!0,this},n.each=function(e,t){for(var a=0,n=e.length;a<n&&t(a,e[a])!==!1;a++);},n.hasClass=function(e,t){return e=e||{},new RegExp(\"\\\\b\"+t+\"\\\\b\").test(e.className)},n.addClass=function(e,t){return e=e||{},n.hasClass(e,t)||(e.className+=\" \"+t),e.className=n.trim(e.className),this},n.removeClass=function(e,t){if(e=e||{},n.hasClass(e,t)){var a=new RegExp(\"\\\\b\"+t+\"\\\\b\");e.className=e.className.replace(a,\"\")}return this},n.removeCssAttr=function(e,t){var a=e.style;a.removeProperty?a.removeProperty(t):a.removeAttribute(t)},n.shde=function(e,t){e.style.display=t?\"none\":\"block\"},n.query=function(e){if(e&&1===e.nodeType){if(\"input\"!==e.tagName.toLowerCase())throw new Error(\"选择器elem错误\");return e}var t,e=n.trim(e).split(\" \"),a=s[o](e[0].substr(1));if(a){if(e[1]){if(/^\\./.test(e[1])){var i,d=e[1].substr(1),r=new RegExp(\"\\\\b\"+d+\"\\\\b\");return t=[],i=s.getElementsByClassName?a.getElementsByClassName(d):a[l](\"*\"),n.each(i,function(e,a){r.test(a.className)&&t.push(a)}),t[0]?t:\"\"}return t=a[l](e[1]),t[0]?a[l](e[1]):\"\"}return a}},n.on=function(e,a,s){return e.attachEvent?e.attachEvent(\"on\"+a,function(){s.call(e,t.even)}):e.addEventListener(a,s,!1),n},n.stopMosup=function(e,t){\"mouseup\"!==e&&n.on(t,\"mouseup\",function(e){n.stopmp(e)})},n.run=function(e){var t=(n.query,e.elem);t&&(d.elemv=/textarea|input/.test(t.tagName.toLocaleLowerCase())?\"value\":\"innerHTML\",(\"init\"in e?e.init:a.init)&&!t[d.elemv]&&(t[d.elemv]=laydate.now(null,e.format||a.format)),n.view(t,e),n.reshow())},n.scroll=function(e){return e=e?\"scrollLeft\":\"scrollTop\",s.body[e]|s.documentElement[e]},n.winarea=function(e){return document.documentElement[e?\"clientWidth\":\"clientHeight\"]},n.isleap=function(e){return e%4===0&&e%100!==0||e%400===0},n.checkVoid=function(e,t,a){var s=[];return e=0|e,t=0|t,a=0|a,e<n.mins[0]?s=[\"y\"]:e>n.maxs[0]?s=[\"y\",1]:e>=n.mins[0]&&e<=n.maxs[0]&&(e==n.mins[0]&&(t<n.mins[1]?s=[\"m\"]:t==n.mins[1]&&a<n.mins[2]&&(s=[\"d\"])),e==n.maxs[0]&&(t>n.maxs[1]?s=[\"m\",1]:t==n.maxs[1]&&a>n.maxs[2]&&(s=[\"d\",1]))),s},n.timeVoid=function(e,t){if(n.ymd[1]+1==n.mins[1]&&n.ymd[2]==n.mins[2]){if(0===t&&e<n.mins[3])return 1;if(1===t&&e<n.mins[4])return 1;if(2===t&&e<n.mins[5])return 1}else if(n.ymd[1]+1==n.maxs[1]&&n.ymd[2]==n.maxs[2]){if(0===t&&e>n.maxs[3])return 1;if(1===t&&e>n.maxs[4])return 1;if(2===t&&e>n.maxs[5])return 1}if(e>(t?59:23))return 1},n.check=function(){var e=n.options.format.replace(/YYYY|MM|DD|hh|mm|ss/g,\"\\\\d+\\\\\").replace(/\\\\$/g,\"\"),t=new RegExp(e),a=n.elem[d.elemv],s=a.match(/\\d+/g)||[],i=n.checkVoid(s[0],s[1],s[2]);if(\"\"!==a.replace(/\\s/g,\"\")){if(!t.test(a))return n.elem[d.elemv]=\"\",n.msg(\"日期不符合格式，请重新选择。\"),1;if(i[0])return n.elem[d.elemv]=\"\",n.msg(\"日期不在有效期内，请重新选择。\"),1;i.value=n.elem[d.elemv].match(t).join(),s=i.value.match(/\\d+/g),s[1]<1?(s[1]=1,i.auto=1):s[1]>12?(s[1]=12,i.auto=1):s[1].length<2&&(i.auto=1),s[2]<1?(s[2]=1,i.auto=1):s[2]>n.months[(0|s[1])-1]?(s[2]=31,i.auto=1):s[2].length<2&&(i.auto=1),s.length>3&&(n.timeVoid(s[3],0)&&(i.auto=1),n.timeVoid(s[4],1)&&(i.auto=1),n.timeVoid(s[5],2)&&(i.auto=1)),i.auto?n.creation([s[0],0|s[1],0|s[2]],1):i.value!==n.elem[d.elemv]&&(n.elem[d.elemv]=i.value)}},n.months=[31,null,31,30,31,30,31,31,30,31,30,31],n.viewDate=function(e,t,a){var s=(n.query,{}),i=new Date;e<(0|n.mins[0])&&(e=0|n.mins[0]),e>(0|n.maxs[0])&&(e=0|n.maxs[0]),i.setFullYear(e,t,a),s.ymd=[i.getFullYear(),i.getMonth(),i.getDate()],n.months[1]=n.isleap(s.ymd[0])?29:28,i.setFullYear(s.ymd[0],s.ymd[1],1),s.FDay=i.getDay(),s.PDay=n.months[0===t?11:t-1]-s.FDay+1,s.NDay=1,n.each(d.tds,function(e,t){var a,i=s.ymd[0],o=s.ymd[1]+1;t.className=\"\",e<s.FDay?(t.innerHTML=a=e+s.PDay,n.addClass(t,\"laydate_nothis\"),1===o&&(i-=1),o=1===o?12:o-1):e>=s.FDay&&e<s.FDay+n.months[s.ymd[1]]?(t.innerHTML=a=e-s.FDay+1,e-s.FDay+1===s.ymd[2]&&(n.addClass(t,d[2]),s.thisDay=t)):(t.innerHTML=a=s.NDay++,n.addClass(t,\"laydate_nothis\"),12===o&&(i+=1),o=12===o?1:o+1),n.checkVoid(i,o,a)[0]&&n.addClass(t,d[1]),n.options.festival&&n.festival(t,o+\".\"+a),t.setAttribute(\"y\",i),t.setAttribute(\"m\",o),t.setAttribute(\"d\",a),i=o=a=null}),n.valid=!n.hasClass(s.thisDay,d[1]),n.ymd=s.ymd,d.year.value=n.ymd[0]+\"年\",d.month.value=n.digit(n.ymd[1]+1)+\"月\",n.each(d.mms,function(e,t){var a=n.checkVoid(n.ymd[0],(0|t.getAttribute(\"m\"))+1);\"y\"===a[0]||\"m\"===a[0]?n.addClass(t,d[1]):n.removeClass(t,d[1]),n.removeClass(t,d[2]),a=null}),n.addClass(d.mms[n.ymd[1]],d[2]),s.times=[0|n.inymd[3]||0,0|n.inymd[4]||0,0|n.inymd[5]||0],n.each(new Array(3),function(e){n.hmsin[e].value=n.digit(n.timeVoid(s.times[e],e)?0|n.mins[e+3]:0|s.times[e])}),n[n.valid?\"removeClass\":\"addClass\"](d.ok,d[1])},n.festival=function(e,t){var a;switch(t){case\"1.1\":a=\"元旦\";break;case\"3.8\":a=\"妇女\";break;case\"4.5\":a=\"清明\";break;case\"5.1\":a=\"劳动\";break;case\"6.1\":a=\"儿童\";break;case\"9.10\":a=\"教师\";break;case\"10.1\":a=\"国庆\"}a&&(e.innerHTML=a),a=null},n.viewYears=function(e){var t=n.query,a=\"\";n.each(new Array(14),function(t){a+=7===t?\"<li \"+(parseInt(d.year.value)===e?'class=\"'+d[2]+'\"':\"\")+' y=\"'+e+'\">'+e+\"年</li>\":'<li y=\"'+(e-7+t)+'\">'+(e-7+t)+\"年</li>\"}),t(\"#laydate_ys\").innerHTML=a,n.each(t(\"#laydate_ys li\"),function(e,t){\"y\"===n.checkVoid(t.getAttribute(\"y\"))[0]?n.addClass(t,d[1]):n.on(t,\"click\",function(e){n.stopmp(e).reshow(),n.viewDate(0|this.getAttribute(\"y\"),n.ymd[1],n.ymd[2])})})},n.initDate=function(){var e=(n.query,new Date),t=n.elem[d.elemv].match(/\\d+/g)||[];t.length<3&&(t=n.options.start.match(/\\d+/g)||[],t.length<3&&(t=[e.getFullYear(),e.getMonth()+1,e.getDate()])),n.inymd=t,n.viewDate(t[0],t[1]-1,t[2])},n.iswrite=function(){var e=n.query,t={time:e(\"#laydate_hms\")};n.shde(t.time,!n.options.istime),n.shde(d.oclear,!(\"isclear\"in n.options?n.options.isclear:1)),n.shde(d.otoday,!(\"istoday\"in n.options?n.options.istoday:1)),n.shde(d.ok,!(\"issure\"in n.options?n.options.issure:1))},n.orien=function(e,t){var a,s=n.elem.getBoundingClientRect();e.style.left=s.left+(t?0:n.scroll(1))+\"px\",a=s.bottom+e.offsetHeight/1.5<=n.winarea()?s.bottom-1:s.top>e.offsetHeight/1.5?s.top-e.offsetHeight+1:n.winarea()-e.offsetHeight,e.style.top=Math.max(a+(t?0:n.scroll()),1)+\"px\"},n.follow=function(e){n.options.fixed?(e.style.position=\"fixed\",n.orien(e,1)):(e.style.position=\"absolute\",n.orien(e))},n.viewtb=function(){var e,t=[],a=[\"日\",\"一\",\"二\",\"三\",\"四\",\"五\",\"六\"],o={},d=s[i](\"table\"),r=s[i](\"thead\");return r.appendChild(s[i](\"tr\")),o.creath=function(e){var t=s[i](\"th\");t.innerHTML=a[e],r[l](\"tr\")[0].appendChild(t),t=null},n.each(new Array(6),function(a){t.push([]),e=d.insertRow(0),n.each(new Array(7),function(n){t[a][n]=0,0===a&&o.creath(n),e.insertCell(n)})}),d.insertBefore(r,d.children[0]),d.id=d.className=\"laydate_table\",e=t=null,d.outerHTML.toLowerCase()}(),n.view=function(e,t){var o,l=n.query,r={};t=t||e,n.elem=e,n.options=t,n.options.format||(n.options.format=a.format),n.options.start=n.options.start||\"\",n.mm=r.mm=[n.options.min||a.min,n.options.max||a.max],n.mins=r.mm[0].match(/\\d+/g),n.maxs=r.mm[1].match(/\\d+/g),n.box?n.shde(n.box):(o=s[i](\"div\"),o.id=d[0],o.className=d[0],o.style.cssText=\"position: absolute;\",o.setAttribute(\"name\",\"laydate-v\"+laydate.v),o.innerHTML=r.html='<div class=\"laydate_top\"><div class=\"laydate_ym laydate_y\" id=\"laydate_YY\"><a class=\"laydate_choose laydate_chprev laydate_tab\"><cite></cite></a><input id=\"laydate_y\" readonly><label></label><a class=\"laydate_choose laydate_chnext laydate_tab\"><cite></cite></a><div class=\"laydate_yms\"><a class=\"laydate_tab laydate_chtop\"><cite></cite></a><ul id=\"laydate_ys\"></ul><a class=\"laydate_tab laydate_chdown\"><cite></cite></a></div></div><div class=\"laydate_ym laydate_m\" id=\"laydate_MM\"><a class=\"laydate_choose laydate_chprev laydate_tab\"><cite></cite></a><input id=\"laydate_m\" readonly><label></label><a class=\"laydate_choose laydate_chnext laydate_tab\"><cite></cite></a><div class=\"laydate_yms\" id=\"laydate_ms\">'+function(){var e=\"\";return n.each(new Array(12),function(t){e+='<span m=\"'+t+'\">'+n.digit(t+1)+\"月</span>\"}),e}()+\"</div></div></div>\"+n.viewtb+'<div class=\"laydate_bottom\"><ul id=\"laydate_hms\"><li class=\"laydate_sj\">时间</li><li><input readonly>:</li><li><input readonly>:</li><li><input readonly></li></ul><div class=\"laydate_time\" id=\"laydate_time\"></div><div class=\"laydate_btn\"><a id=\"laydate_clear\">清空</a><a id=\"laydate_today\">今天</a><a id=\"laydate_ok\">确认</a></div>'+(a.isv?'<a href=\"http://sentsin.com/layui/laydate/\" class=\"laydate_v\" target=\"_blank\">laydate-v'+laydate.v+\"</a>\":\"\")+\"</div>\",s.body.appendChild(o),n.box=l(\"#\"+d[0]),n.events(),o=null),n.follow(n.box),t.zIndex?n.box.style.zIndex=t.zIndex:n.removeCssAttr(n.box,\"z-index\"),n.stopMosup(\"click\",n.box),n.initDate(),n.iswrite(),n.check()},n.reshow=function(){return n.each(n.query(\"#\"+d[0]+\" .laydate_show\"),function(e,t){n.removeClass(t,\"laydate_show\")}),this},n.close=function(){n.reshow(),n.shde(n.query(\"#\"+d[0]),1),n.elem=null},n.parse=function(e,t,s){return e=e.concat(t),s=s||(n.options?n.options.format:a.format),s.replace(/YYYY|MM|DD|hh|mm|ss/g,function(t,a){return e.index=0|++e.index,n.digit(e[e.index])})},n.creation=function(e,t){var a=(n.query,n.hmsin),s=n.parse(e,[a[0].value,a[1].value,a[2].value]);n.elem[d.elemv]=s,t||(n.close(),\"function\"==typeof n.options.choose&&n.options.choose(s))},n.events=function(){var e=n.query,a={box:\"#\"+d[0]};n.addClass(s.body,\"laydate_body\"),d.tds=e(\"#laydate_table td\"),d.mms=e(\"#laydate_ms span\"),d.year=e(\"#laydate_y\"),d.month=e(\"#laydate_m\"),n.each(e(a.box+\" .laydate_ym\"),function(e,t){n.on(t,\"click\",function(t){n.stopmp(t).reshow(),n.addClass(this[l](\"div\")[0],\"laydate_show\"),e||(a.YY=parseInt(d.year.value),n.viewYears(a.YY))})}),n.on(e(a.box),\"click\",function(){n.reshow()}),a.tabYear=function(e){0===e?n.ymd[0]--:1===e?n.ymd[0]++:2===e?a.YY-=14:a.YY+=14,e<2?(n.viewDate(n.ymd[0],n.ymd[1],n.ymd[2]),n.reshow()):n.viewYears(a.YY)},n.each(e(\"#laydate_YY .laydate_tab\"),function(e,t){n.on(t,\"click\",function(t){n.stopmp(t),a.tabYear(e)})}),a.tabMonth=function(e){e?(n.ymd[1]++,12===n.ymd[1]&&(n.ymd[0]++,n.ymd[1]=0)):(n.ymd[1]--,n.ymd[1]===-1&&(n.ymd[0]--,n.ymd[1]=11)),n.viewDate(n.ymd[0],n.ymd[1],n.ymd[2])},n.each(e(\"#laydate_MM .laydate_tab\"),function(e,t){n.on(t,\"click\",function(t){n.stopmp(t).reshow(),a.tabMonth(e)})}),n.each(e(\"#laydate_ms span\"),function(e,t){n.on(t,\"click\",function(e){n.stopmp(e).reshow(),n.hasClass(this,d[1])||n.viewDate(n.ymd[0],0|this.getAttribute(\"m\"),n.ymd[2])})}),n.each(e(\"#laydate_table td\"),function(e,t){n.on(t,\"click\",function(e){n.hasClass(this,d[1])||(n.stopmp(e),n.creation([0|this.getAttribute(\"y\"),0|this.getAttribute(\"m\"),0|this.getAttribute(\"d\")]))})}),d.oclear=e(\"#laydate_clear\"),n.on(d.oclear,\"click\",function(){n.elem[d.elemv]=\"\",n.close()}),d.otoday=e(\"#laydate_today\"),n.on(d.otoday,\"click\",function(){var e=new Date;n.creation([e.getFullYear(),e.getMonth()+1,e.getDate()])}),d.ok=e(\"#laydate_ok\"),n.on(d.ok,\"click\",function(){n.valid&&n.creation([n.ymd[0],n.ymd[1]+1,n.ymd[2]])}),a.times=e(\"#laydate_time\"),n.hmsin=a.hmsin=e(\"#laydate_hms input\"),a.hmss=[\"小时\",\"分钟\",\"秒数\"],a.hmsarr=[],n.msg=function(t,s){var i='<div class=\"laydte_hsmtex\">'+(s||\"提示\")+\"<span>×</span></div>\";\"string\"==typeof t?(i+=\"<p>\"+t+\"</p>\",n.shde(e(\"#\"+d[0])),n.removeClass(a.times,\"laydate_time1\").addClass(a.times,\"laydate_msg\")):(a.hmsarr[t]?i=a.hmsarr[t]:(i+='<div id=\"laydate_hmsno\" class=\"laydate_hmsno\">',n.each(new Array(0===t?24:60),function(e){i+=\"<span>\"+e+\"</span>\"}),i+=\"</div>\",a.hmsarr[t]=i),n.removeClass(a.times,\"laydate_msg\"),n[0===t?\"removeClass\":\"addClass\"](a.times,\"laydate_time1\")),n.addClass(a.times,\"laydate_show\"),a.times.innerHTML=i},a.hmson=function(t,a){var s=e(\"#laydate_hmsno span\"),i=n.valid?null:1;n.each(s,function(e,s){i?n.addClass(s,d[1]):n.timeVoid(e,a)?n.addClass(s,d[1]):n.on(s,\"click\",function(e){n.hasClass(this,d[1])||(t.value=n.digit(0|this.innerHTML))})}),n.addClass(s[0|t.value],\"laydate_click\")},n.each(a.hmsin,function(e,t){n.on(t,\"click\",function(t){n.stopmp(t).reshow(),n.msg(e,a.hmss[e]),a.hmson(this,e)})}),n.on(s,\"mouseup\",function(){var t=e(\"#\"+d[0]);t&&\"none\"!==t.style.display&&(n.check()||n.close())}).on(s,\"keydown\",function(e){e=e||t.event;var a=e.keyCode;13===a&&n.elem&&n.creation([n.ymd[0],n.ymd[1]+1,n.ymd[2]])})},laydate.reset=function(){n.box&&n.elem&&n.follow(n.box)},laydate.now=function(e,t){var a=new Date(0|e?function(e){return e<864e5?+new Date+864e5*e:e}(parseInt(e)):+new Date);return n.parse([a.getFullYear(),a.getMonth()+1,a.getDate()],[a.getHours(),a.getMinutes(),a.getSeconds()],t)},layui.addcss(\"modules/laydate/laydate.css\",function(){},\"laydatecss\"),e(\"laydate\",laydate)});!function(e,t){\"object\"==typeof module&&\"object\"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error(\"jQuery requires a window with a document\");return t(e)}:t(e)}(\"undefined\"!=typeof window?window:this,function(e,t){function n(e){var t=!!e&&\"length\"in e&&e.length,n=pe.type(e);return\"function\"!==n&&!pe.isWindow(e)&&(\"array\"===n||0===t||\"number\"==typeof t&&t>0&&t-1 in e)}function r(e,t,n){if(pe.isFunction(t))return pe.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return pe.grep(e,function(e){return e===t!==n});if(\"string\"==typeof t){if(Ce.test(t))return pe.filter(t,e,n);t=pe.filter(t,e)}return pe.grep(e,function(e){return pe.inArray(e,t)>-1!==n})}function i(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}function o(e){var t={};return pe.each(e.match(De)||[],function(e,n){t[n]=!0}),t}function a(){re.addEventListener?(re.removeEventListener(\"DOMContentLoaded\",s),e.removeEventListener(\"load\",s)):(re.detachEvent(\"onreadystatechange\",s),e.detachEvent(\"onload\",s))}function s(){(re.addEventListener||\"load\"===e.event.type||\"complete\"===re.readyState)&&(a(),pe.ready())}function u(e,t,n){if(void 0===n&&1===e.nodeType){var r=\"data-\"+t.replace(_e,\"-$1\").toLowerCase();if(n=e.getAttribute(r),\"string\"==typeof n){try{n=\"true\"===n||\"false\"!==n&&(\"null\"===n?null:+n+\"\"===n?+n:qe.test(n)?pe.parseJSON(n):n)}catch(i){}pe.data(e,t,n)}else n=void 0}return n}function l(e){var t;for(t in e)if((\"data\"!==t||!pe.isEmptyObject(e[t]))&&\"toJSON\"!==t)return!1;return!0}function c(e,t,n,r){if(He(e)){var i,o,a=pe.expando,s=e.nodeType,u=s?pe.cache:e,l=s?e[a]:e[a]&&a;if(l&&u[l]&&(r||u[l].data)||void 0!==n||\"string\"!=typeof t)return l||(l=s?e[a]=ne.pop()||pe.guid++:a),u[l]||(u[l]=s?{}:{toJSON:pe.noop}),\"object\"!=typeof t&&\"function\"!=typeof t||(r?u[l]=pe.extend(u[l],t):u[l].data=pe.extend(u[l].data,t)),o=u[l],r||(o.data||(o.data={}),o=o.data),void 0!==n&&(o[pe.camelCase(t)]=n),\"string\"==typeof t?(i=o[t],null==i&&(i=o[pe.camelCase(t)])):i=o,i}}function f(e,t,n){if(He(e)){var r,i,o=e.nodeType,a=o?pe.cache:e,s=o?e[pe.expando]:pe.expando;if(a[s]){if(t&&(r=n?a[s]:a[s].data)){pe.isArray(t)?t=t.concat(pe.map(t,pe.camelCase)):t in r?t=[t]:(t=pe.camelCase(t),t=t in r?[t]:t.split(\" \")),i=t.length;for(;i--;)delete r[t[i]];if(n?!l(r):!pe.isEmptyObject(r))return}(n||(delete a[s].data,l(a[s])))&&(o?pe.cleanData([e],!0):fe.deleteExpando||a!=a.window?delete a[s]:a[s]=void 0)}}}function d(e,t,n,r){var i,o=1,a=20,s=r?function(){return r.cur()}:function(){return pe.css(e,t,\"\")},u=s(),l=n&&n[3]||(pe.cssNumber[t]?\"\":\"px\"),c=(pe.cssNumber[t]||\"px\"!==l&&+u)&&Me.exec(pe.css(e,t));if(c&&c[3]!==l){l=l||c[3],n=n||[],c=+u||1;do o=o||\".5\",c/=o,pe.style(e,t,c+l);while(o!==(o=s()/u)&&1!==o&&--a)}return n&&(c=+c||+u||0,i=n[1]?c+(n[1]+1)*n[2]:+n[2],r&&(r.unit=l,r.start=c,r.end=i)),i}function p(e){var t=ze.split(\"|\"),n=e.createDocumentFragment();if(n.createElement)for(;t.length;)n.createElement(t.pop());return n}function h(e,t){var n,r,i=0,o=\"undefined\"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||\"*\"):\"undefined\"!=typeof e.querySelectorAll?e.querySelectorAll(t||\"*\"):void 0;if(!o)for(o=[],n=e.childNodes||e;null!=(r=n[i]);i++)!t||pe.nodeName(r,t)?o.push(r):pe.merge(o,h(r,t));return void 0===t||t&&pe.nodeName(e,t)?pe.merge([e],o):o}function g(e,t){for(var n,r=0;null!=(n=e[r]);r++)pe._data(n,\"globalEval\",!t||pe._data(t[r],\"globalEval\"))}function m(e){Be.test(e.type)&&(e.defaultChecked=e.checked)}function y(e,t,n,r,i){for(var o,a,s,u,l,c,f,d=e.length,y=p(t),v=[],x=0;x<d;x++)if(a=e[x],a||0===a)if(\"object\"===pe.type(a))pe.merge(v,a.nodeType?[a]:a);else if(Ue.test(a)){for(u=u||y.appendChild(t.createElement(\"div\")),l=(We.exec(a)||[\"\",\"\"])[1].toLowerCase(),f=Xe[l]||Xe._default,u.innerHTML=f[1]+pe.htmlPrefilter(a)+f[2],o=f[0];o--;)u=u.lastChild;if(!fe.leadingWhitespace&&$e.test(a)&&v.push(t.createTextNode($e.exec(a)[0])),!fe.tbody)for(a=\"table\"!==l||Ve.test(a)?\"<table>\"!==f[1]||Ve.test(a)?0:u:u.firstChild,o=a&&a.childNodes.length;o--;)pe.nodeName(c=a.childNodes[o],\"tbody\")&&!c.childNodes.length&&a.removeChild(c);for(pe.merge(v,u.childNodes),u.textContent=\"\";u.firstChild;)u.removeChild(u.firstChild);u=y.lastChild}else v.push(t.createTextNode(a));for(u&&y.removeChild(u),fe.appendChecked||pe.grep(h(v,\"input\"),m),x=0;a=v[x++];)if(r&&pe.inArray(a,r)>-1)i&&i.push(a);else if(s=pe.contains(a.ownerDocument,a),u=h(y.appendChild(a),\"script\"),s&&g(u),n)for(o=0;a=u[o++];)Ie.test(a.type||\"\")&&n.push(a);return u=null,y}function v(){return!0}function x(){return!1}function b(){try{return re.activeElement}catch(e){}}function w(e,t,n,r,i,o){var a,s;if(\"object\"==typeof t){\"string\"!=typeof n&&(r=r||n,n=void 0);for(s in t)w(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&(\"string\"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),i===!1)i=x;else if(!i)return e;return 1===o&&(a=i,i=function(e){return pe().off(e),a.apply(this,arguments)},i.guid=a.guid||(a.guid=pe.guid++)),e.each(function(){pe.event.add(this,t,i,r,n)})}function T(e,t){return pe.nodeName(e,\"table\")&&pe.nodeName(11!==t.nodeType?t:t.firstChild,\"tr\")?e.getElementsByTagName(\"tbody\")[0]||e.appendChild(e.ownerDocument.createElement(\"tbody\")):e}function C(e){return e.type=(null!==pe.find.attr(e,\"type\"))+\"/\"+e.type,e}function E(e){var t=it.exec(e.type);return t?e.type=t[1]:e.removeAttribute(\"type\"),e}function N(e,t){if(1===t.nodeType&&pe.hasData(e)){var n,r,i,o=pe._data(e),a=pe._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;r<i;r++)pe.event.add(t,n,s[n][r])}a.data&&(a.data=pe.extend({},a.data))}}function k(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!fe.noCloneEvent&&t[pe.expando]){i=pe._data(t);for(r in i.events)pe.removeEvent(t,r,i.handle);t.removeAttribute(pe.expando)}\"script\"===n&&t.text!==e.text?(C(t).text=e.text,E(t)):\"object\"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),fe.html5Clone&&e.innerHTML&&!pe.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):\"input\"===n&&Be.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)}}function S(e,t,n,r){t=oe.apply([],t);var i,o,a,s,u,l,c=0,f=e.length,d=f-1,p=t[0],g=pe.isFunction(p);if(g||f>1&&\"string\"==typeof p&&!fe.checkClone&&rt.test(p))return e.each(function(i){var o=e.eq(i);g&&(t[0]=p.call(this,i,o.html())),S(o,t,n,r)});if(f&&(l=y(t,e[0].ownerDocument,!1,e,r),i=l.firstChild,1===l.childNodes.length&&(l=i),i||r)){for(s=pe.map(h(l,\"script\"),C),a=s.length;c<f;c++)o=l,c!==d&&(o=pe.clone(o,!0,!0),a&&pe.merge(s,h(o,\"script\"))),n.call(e[c],o,c);if(a)for(u=s[s.length-1].ownerDocument,pe.map(s,E),c=0;c<a;c++)o=s[c],Ie.test(o.type||\"\")&&!pe._data(o,\"globalEval\")&&pe.contains(u,o)&&(o.src?pe._evalUrl&&pe._evalUrl(o.src):pe.globalEval((o.text||o.textContent||o.innerHTML||\"\").replace(ot,\"\")));l=i=null}return e}function A(e,t,n){for(var r,i=t?pe.filter(t,e):e,o=0;null!=(r=i[o]);o++)n||1!==r.nodeType||pe.cleanData(h(r)),r.parentNode&&(n&&pe.contains(r.ownerDocument,r)&&g(h(r,\"script\")),r.parentNode.removeChild(r));return e}function D(e,t){var n=pe(t.createElement(e)).appendTo(t.body),r=pe.css(n[0],\"display\");return n.detach(),r}function j(e){var t=re,n=lt[e];return n||(n=D(e,t),\"none\"!==n&&n||(ut=(ut||pe(\"<iframe frameborder='0' width='0' height='0'/>\")).appendTo(t.documentElement),t=(ut[0].contentWindow||ut[0].contentDocument).document,t.write(),t.close(),n=D(e,t),ut.detach()),lt[e]=n),n}function L(e,t){return{get:function(){return e()?void delete this.get:(this.get=t).apply(this,arguments)}}}function H(e){if(e in Et)return e;for(var t=e.charAt(0).toUpperCase()+e.slice(1),n=Ct.length;n--;)if(e=Ct[n]+t,e in Et)return e}function q(e,t){for(var n,r,i,o=[],a=0,s=e.length;a<s;a++)r=e[a],r.style&&(o[a]=pe._data(r,\"olddisplay\"),n=r.style.display,t?(o[a]||\"none\"!==n||(r.style.display=\"\"),\"\"===r.style.display&&Re(r)&&(o[a]=pe._data(r,\"olddisplay\",j(r.nodeName)))):(i=Re(r),(n&&\"none\"!==n||!i)&&pe._data(r,\"olddisplay\",i?n:pe.css(r,\"display\"))));for(a=0;a<s;a++)r=e[a],r.style&&(t&&\"none\"!==r.style.display&&\"\"!==r.style.display||(r.style.display=t?o[a]||\"\":\"none\"));return e}function _(e,t,n){var r=bt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||\"px\"):t}function F(e,t,n,r,i){for(var o=n===(r?\"border\":\"content\")?4:\"width\"===t?1:0,a=0;o<4;o+=2)\"margin\"===n&&(a+=pe.css(e,n+Oe[o],!0,i)),r?(\"content\"===n&&(a-=pe.css(e,\"padding\"+Oe[o],!0,i)),\"margin\"!==n&&(a-=pe.css(e,\"border\"+Oe[o]+\"Width\",!0,i))):(a+=pe.css(e,\"padding\"+Oe[o],!0,i),\"padding\"!==n&&(a+=pe.css(e,\"border\"+Oe[o]+\"Width\",!0,i)));return a}function M(t,n,r){var i=!0,o=\"width\"===n?t.offsetWidth:t.offsetHeight,a=ht(t),s=fe.boxSizing&&\"border-box\"===pe.css(t,\"boxSizing\",!1,a);if(re.msFullscreenElement&&e.top!==e&&t.getClientRects().length&&(o=Math.round(100*t.getBoundingClientRect()[n])),o<=0||null==o){if(o=gt(t,n,a),(o<0||null==o)&&(o=t.style[n]),ft.test(o))return o;i=s&&(fe.boxSizingReliable()||o===t.style[n]),o=parseFloat(o)||0}return o+F(t,n,r||(s?\"border\":\"content\"),i,a)+\"px\"}function O(e,t,n,r,i){return new O.prototype.init(e,t,n,r,i)}function R(){return e.setTimeout(function(){Nt=void 0}),Nt=pe.now()}function P(e,t){var n,r={height:e},i=0;for(t=t?1:0;i<4;i+=2-t)n=Oe[i],r[\"margin\"+n]=r[\"padding\"+n]=e;return t&&(r.opacity=r.width=e),r}function B(e,t,n){for(var r,i=($.tweeners[t]||[]).concat($.tweeners[\"*\"]),o=0,a=i.length;o<a;o++)if(r=i[o].call(n,t,e))return r}function W(e,t,n){var r,i,o,a,s,u,l,c,f=this,d={},p=e.style,h=e.nodeType&&Re(e),g=pe._data(e,\"fxshow\");n.queue||(s=pe._queueHooks(e,\"fx\"),null==s.unqueued&&(s.unqueued=0,u=s.empty.fire,s.empty.fire=function(){s.unqueued||u()}),s.unqueued++,f.always(function(){f.always(function(){s.unqueued--,pe.queue(e,\"fx\").length||s.empty.fire()})})),1===e.nodeType&&(\"height\"in t||\"width\"in t)&&(n.overflow=[p.overflow,p.overflowX,p.overflowY],l=pe.css(e,\"display\"),c=\"none\"===l?pe._data(e,\"olddisplay\")||j(e.nodeName):l,\"inline\"===c&&\"none\"===pe.css(e,\"float\")&&(fe.inlineBlockNeedsLayout&&\"inline\"!==j(e.nodeName)?p.zoom=1:p.display=\"inline-block\")),n.overflow&&(p.overflow=\"hidden\",fe.shrinkWrapBlocks()||f.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],St.exec(i)){if(delete t[r],o=o||\"toggle\"===i,i===(h?\"hide\":\"show\")){if(\"show\"!==i||!g||void 0===g[r])continue;h=!0}d[r]=g&&g[r]||pe.style(e,r)}else l=void 0;if(pe.isEmptyObject(d))\"inline\"===(\"none\"===l?j(e.nodeName):l)&&(p.display=l);else{g?\"hidden\"in g&&(h=g.hidden):g=pe._data(e,\"fxshow\",{}),o&&(g.hidden=!h),h?pe(e).show():f.done(function(){pe(e).hide()}),f.done(function(){var t;pe._removeData(e,\"fxshow\");for(t in d)pe.style(e,t,d[t])});for(r in d)a=B(h?g[r]:0,r,f),r in g||(g[r]=a.start,h&&(a.end=a.start,a.start=\"width\"===r||\"height\"===r?1:0))}}function I(e,t){var n,r,i,o,a;for(n in e)if(r=pe.camelCase(n),i=t[r],o=e[n],pe.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),a=pe.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}function $(e,t,n){var r,i,o=0,a=$.prefilters.length,s=pe.Deferred().always(function(){delete u.elem}),u=function(){if(i)return!1;for(var t=Nt||R(),n=Math.max(0,l.startTime+l.duration-t),r=n/l.duration||0,o=1-r,a=0,u=l.tweens.length;a<u;a++)l.tweens[a].run(o);return s.notifyWith(e,[l,o,n]),o<1&&u?n:(s.resolveWith(e,[l]),!1)},l=s.promise({elem:e,props:pe.extend({},t),opts:pe.extend(!0,{specialEasing:{},easing:pe.easing._default},n),originalProperties:t,originalOptions:n,startTime:Nt||R(),duration:n.duration,tweens:[],createTween:function(t,n){var r=pe.Tween(e,l.opts,t,n,l.opts.specialEasing[t]||l.opts.easing);return l.tweens.push(r),r},stop:function(t){var n=0,r=t?l.tweens.length:0;if(i)return this;for(i=!0;n<r;n++)l.tweens[n].run(1);return t?(s.notifyWith(e,[l,1,0]),s.resolveWith(e,[l,t])):s.rejectWith(e,[l,t]),this}}),c=l.props;for(I(c,l.opts.specialEasing);o<a;o++)if(r=$.prefilters[o].call(l,e,c,l.opts))return pe.isFunction(r.stop)&&(pe._queueHooks(l.elem,l.opts.queue).stop=pe.proxy(r.stop,r)),r;return pe.map(c,B,l),pe.isFunction(l.opts.start)&&l.opts.start.call(e,l),pe.fx.timer(pe.extend(u,{elem:e,anim:l,queue:l.opts.queue})),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always)}function z(e){return pe.attr(e,\"class\")||\"\"}function X(e){return function(t,n){\"string\"!=typeof t&&(n=t,t=\"*\");var r,i=0,o=t.toLowerCase().match(De)||[];if(pe.isFunction(n))for(;r=o[i++];)\"+\"===r.charAt(0)?(r=r.slice(1)||\"*\",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function U(e,t,n,r){function i(s){var u;return o[s]=!0,pe.each(e[s]||[],function(e,s){var l=s(t,n,r);return\"string\"!=typeof l||a||o[l]?a?!(u=l):void 0:(t.dataTypes.unshift(l),i(l),!1)}),u}var o={},a=e===Qt;return i(t.dataTypes[0])||!o[\"*\"]&&i(\"*\")}function V(e,t){var n,r,i=pe.ajaxSettings.flatOptions||{};for(r in t)void 0!==t[r]&&((i[r]?e:n||(n={}))[r]=t[r]);return n&&pe.extend(!0,e,n),e}function Y(e,t,n){for(var r,i,o,a,s=e.contents,u=e.dataTypes;\"*\"===u[0];)u.shift(),void 0===i&&(i=e.mimeType||t.getResponseHeader(\"Content-Type\"));if(i)for(a in s)if(s[a]&&s[a].test(i)){u.unshift(a);break}if(u[0]in n)o=u[0];else{for(a in n){if(!u[0]||e.converters[a+\" \"+u[0]]){o=a;break}r||(r=a)}o=o||r}if(o)return o!==u[0]&&u.unshift(o),n[o]}function J(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];for(o=c.shift();o;)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if(\"*\"===o)o=u;else if(\"*\"!==u&&u!==o){if(a=l[u+\" \"+o]||l[\"* \"+o],!a)for(i in l)if(s=i.split(\" \"),s[1]===o&&(a=l[u+\" \"+s[0]]||l[\"* \"+s[0]])){a===!0?a=l[i]:l[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(f){return{state:\"parsererror\",error:a?f:\"No conversion from \"+u+\" to \"+o}}}return{state:\"success\",data:t}}function G(e){return e.style&&e.style.display||pe.css(e,\"display\")}function K(e){for(;e&&1===e.nodeType;){if(\"none\"===G(e)||\"hidden\"===e.type)return!0;e=e.parentNode}return!1}function Q(e,t,n,r){var i;if(pe.isArray(t))pe.each(t,function(t,i){n||rn.test(e)?r(e,i):Q(e+\"[\"+(\"object\"==typeof i&&null!=i?t:\"\")+\"]\",i,n,r)});else if(n||\"object\"!==pe.type(t))r(e,t);else for(i in t)Q(e+\"[\"+i+\"]\",t[i],n,r)}function Z(){try{return new e.XMLHttpRequest}catch(t){}}function ee(){try{return new e.ActiveXObject(\"Microsoft.XMLHTTP\")}catch(t){}}function te(e){return pe.isWindow(e)?e:9===e.nodeType&&(e.defaultView||e.parentWindow)}var ne=[],re=e.document,ie=ne.slice,oe=ne.concat,ae=ne.push,se=ne.indexOf,ue={},le=ue.toString,ce=ue.hasOwnProperty,fe={},de=\"1.12.3\",pe=function(e,t){return new pe.fn.init(e,t)},he=/^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g,ge=/^-ms-/,me=/-([\\da-z])/gi,ye=function(e,t){return t.toUpperCase()};pe.fn=pe.prototype={jquery:de,constructor:pe,selector:\"\",length:0,toArray:function(){return ie.call(this)},get:function(e){return null!=e?e<0?this[e+this.length]:this[e]:ie.call(this)},pushStack:function(e){var t=pe.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e){return pe.each(this,e)},map:function(e){return this.pushStack(pe.map(this,function(t,n){return e.call(t,n,t)}))},slice:function(){return this.pushStack(ie.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(n>=0&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:ae,sort:ne.sort,splice:ne.splice},pe.extend=pe.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for(\"boolean\"==typeof a&&(l=a,a=arguments[s]||{},s++),\"object\"==typeof a||pe.isFunction(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(i=arguments[s]))for(r in i)e=a[r],n=i[r],a!==n&&(l&&n&&(pe.isPlainObject(n)||(t=pe.isArray(n)))?(t?(t=!1,o=e&&pe.isArray(e)?e:[]):o=e&&pe.isPlainObject(e)?e:{},a[r]=pe.extend(l,o,n)):void 0!==n&&(a[r]=n));return a},pe.extend({expando:\"jQuery\"+(de+Math.random()).replace(/\\D/g,\"\"),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isFunction:function(e){return\"function\"===pe.type(e)},isArray:Array.isArray||function(e){return\"array\"===pe.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){var t=e&&e.toString();return!pe.isArray(e)&&t-parseFloat(t)+1>=0},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},isPlainObject:function(e){var t;if(!e||\"object\"!==pe.type(e)||e.nodeType||pe.isWindow(e))return!1;try{if(e.constructor&&!ce.call(e,\"constructor\")&&!ce.call(e.constructor.prototype,\"isPrototypeOf\"))return!1}catch(n){return!1}if(!fe.ownFirst)for(t in e)return ce.call(e,t);for(t in e);return void 0===t||ce.call(e,t)},type:function(e){return null==e?e+\"\":\"object\"==typeof e||\"function\"==typeof e?ue[le.call(e)]||\"object\":typeof e},globalEval:function(t){t&&pe.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(ge,\"ms-\").replace(me,ye)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t){var r,i=0;if(n(e))for(r=e.length;i<r&&t.call(e[i],i,e[i])!==!1;i++);else for(i in e)if(t.call(e[i],i,e[i])===!1)break;return e},trim:function(e){return null==e?\"\":(e+\"\").replace(he,\"\")},makeArray:function(e,t){var r=t||[];return null!=e&&(n(Object(e))?pe.merge(r,\"string\"==typeof e?[e]:e):ae.call(r,e)),r},inArray:function(e,t,n){var r;if(t){if(se)return se.call(t,e,n);for(r=t.length,n=n?n<0?Math.max(0,r+n):n:0;n<r;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;)e[i++]=t[r++];if(n!==n)for(;void 0!==t[r];)e[i++]=t[r++];return e.length=i,e},grep:function(e,t,n){for(var r,i=[],o=0,a=e.length,s=!n;o<a;o++)r=!t(e[o],o),r!==s&&i.push(e[o]);return i},map:function(e,t,r){var i,o,a=0,s=[];if(n(e))for(i=e.length;a<i;a++)o=t(e[a],a,r),null!=o&&s.push(o);else for(a in e)o=t(e[a],a,r),null!=o&&s.push(o);return oe.apply([],s)},guid:1,proxy:function(e,t){var n,r,i;if(\"string\"==typeof t&&(i=e[t],t=e,e=i),pe.isFunction(e))return n=ie.call(arguments,2),r=function(){return e.apply(t||this,n.concat(ie.call(arguments)))},r.guid=e.guid=e.guid||pe.guid++,r},now:function(){return+new Date},support:fe}),\"function\"==typeof Symbol&&(pe.fn[Symbol.iterator]=ne[Symbol.iterator]),pe.each(\"Boolean Number String Function Array Date RegExp Object Error Symbol\".split(\" \"),function(e,t){ue[\"[object \"+t+\"]\"]=t.toLowerCase()});var ve=function(e){function t(e,t,n,r){var i,o,a,s,u,l,f,p,h=t&&t.ownerDocument,g=t?t.nodeType:9;if(n=n||[],\"string\"!=typeof e||!e||1!==g&&9!==g&&11!==g)return n;if(!r&&((t?t.ownerDocument||t:B)!==H&&L(t),t=t||H,_)){if(11!==g&&(l=ye.exec(e)))if(i=l[1]){if(9===g){if(!(a=t.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(h&&(a=h.getElementById(i))&&R(t,a)&&a.id===i)return n.push(a),n}else{if(l[2])return Q.apply(n,t.getElementsByTagName(e)),n;if((i=l[3])&&w.getElementsByClassName&&t.getElementsByClassName)return Q.apply(n,t.getElementsByClassName(i)),n}if(w.qsa&&!X[e+\" \"]&&(!F||!F.test(e))){if(1!==g)h=t,p=e;else if(\"object\"!==t.nodeName.toLowerCase()){for((s=t.getAttribute(\"id\"))?s=s.replace(xe,\"\\\\$&\"):t.setAttribute(\"id\",s=P),f=N(e),o=f.length,u=de.test(s)?\"#\"+s:\"[id='\"+s+\"']\";o--;)f[o]=u+\" \"+d(f[o]);p=f.join(\",\"),h=ve.test(e)&&c(t.parentNode)||t}if(p)try{return Q.apply(n,h.querySelectorAll(p)),n}catch(m){}finally{s===P&&t.removeAttribute(\"id\")}}}return S(e.replace(se,\"$1\"),t,n,r)}function n(){function e(n,r){return t.push(n+\" \")>T.cacheLength&&delete e[t.shift()],e[n+\" \"]=r}var t=[];return e}function r(e){return e[P]=!0,e}function i(e){var t=H.createElement(\"div\");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function o(e,t){for(var n=e.split(\"|\"),r=n.length;r--;)T.attrHandle[n[r]]=t}function a(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||V)-(~e.sourceIndex||V);if(r)return r;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function s(e){return function(t){var n=t.nodeName.toLowerCase();return\"input\"===n&&t.type===e}}function u(e){return function(t){var n=t.nodeName.toLowerCase();return(\"input\"===n||\"button\"===n)&&t.type===e}}function l(e){return r(function(t){return t=+t,r(function(n,r){for(var i,o=e([],n.length,t),a=o.length;a--;)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}function c(e){return e&&\"undefined\"!=typeof e.getElementsByTagName&&e}function f(){}function d(e){for(var t=0,n=e.length,r=\"\";t<n;t++)r+=e[t].value;return r}function p(e,t,n){var r=t.dir,i=n&&\"parentNode\"===r,o=I++;return t.first?function(t,n,o){for(;t=t[r];)if(1===t.nodeType||i)return e(t,n,o)}:function(t,n,a){var s,u,l,c=[W,o];if(a){for(;t=t[r];)if((1===t.nodeType||i)&&e(t,n,a))return!0}else for(;t=t[r];)if(1===t.nodeType||i){if(l=t[P]||(t[P]={}),u=l[t.uniqueID]||(l[t.uniqueID]={}),(s=u[r])&&s[0]===W&&s[1]===o)return c[2]=s[2];if(u[r]=c,c[2]=e(t,n,a))return!0}}}function h(e){return e.length>1?function(t,n,r){for(var i=e.length;i--;)if(!e[i](t,n,r))return!1;return!0}:e[0]}function g(e,n,r){for(var i=0,o=n.length;i<o;i++)t(e,n[i],r);return r}function m(e,t,n,r,i){for(var o,a=[],s=0,u=e.length,l=null!=t;s<u;s++)(o=e[s])&&(n&&!n(o,r,i)||(a.push(o),l&&t.push(s)));return a}function y(e,t,n,i,o,a){return i&&!i[P]&&(i=y(i)),o&&!o[P]&&(o=y(o,a)),r(function(r,a,s,u){var l,c,f,d=[],p=[],h=a.length,y=r||g(t||\"*\",s.nodeType?[s]:s,[]),v=!e||!r&&t?y:m(y,d,e,s,u),x=n?o||(r?e:h||i)?[]:a:v;if(n&&n(v,x,s,u),i)for(l=m(x,p),i(l,[],s,u),c=l.length;c--;)(f=l[c])&&(x[p[c]]=!(v[p[c]]=f));if(r){if(o||e){if(o){for(l=[],c=x.length;c--;)(f=x[c])&&l.push(v[c]=f);o(null,x=[],l,u)}for(c=x.length;c--;)(f=x[c])&&(l=o?ee(r,f):d[c])>-1&&(r[l]=!(a[l]=f))}}else x=m(x===a?x.splice(h,x.length):x),o?o(null,a,x,u):Q.apply(a,x)})}function v(e){for(var t,n,r,i=e.length,o=T.relative[e[0].type],a=o||T.relative[\" \"],s=o?1:0,u=p(function(e){return e===t},a,!0),l=p(function(e){return ee(t,e)>-1},a,!0),c=[function(e,n,r){var i=!o&&(r||n!==A)||((t=n).nodeType?u(e,n,r):l(e,n,r));return t=null,i}];s<i;s++)if(n=T.relative[e[s].type])c=[p(h(c),n)];else{if(n=T.filter[e[s].type].apply(null,e[s].matches),n[P]){for(r=++s;r<i&&!T.relative[e[r].type];r++);return y(s>1&&h(c),s>1&&d(e.slice(0,s-1).concat({value:\" \"===e[s-2].type?\"*\":\"\"})).replace(se,\"$1\"),n,s<r&&v(e.slice(s,r)),r<i&&v(e=e.slice(r)),r<i&&d(e))}c.push(n)}return h(c)}function x(e,n){var i=n.length>0,o=e.length>0,a=function(r,a,s,u,l){var c,f,d,p=0,h=\"0\",g=r&&[],y=[],v=A,x=r||o&&T.find.TAG(\"*\",l),b=W+=null==v?1:Math.random()||.1,w=x.length;for(l&&(A=a===H||a||l);h!==w&&null!=(c=x[h]);h++){if(o&&c){for(f=0,a||c.ownerDocument===H||(L(c),s=!_);d=e[f++];)if(d(c,a||H,s)){u.push(c);break}l&&(W=b)}i&&((c=!d&&c)&&p--,r&&g.push(c))}if(p+=h,i&&h!==p){for(f=0;d=n[f++];)d(g,y,a,s);if(r){if(p>0)for(;h--;)g[h]||y[h]||(y[h]=G.call(u));y=m(y)}Q.apply(u,y),l&&!r&&y.length>0&&p+n.length>1&&t.uniqueSort(u)}return l&&(W=b,A=v),g};return i?r(a):a}var b,w,T,C,E,N,k,S,A,D,j,L,H,q,_,F,M,O,R,P=\"sizzle\"+1*new Date,B=e.document,W=0,I=0,$=n(),z=n(),X=n(),U=function(e,t){return e===t&&(j=!0),0},V=1<<31,Y={}.hasOwnProperty,J=[],G=J.pop,K=J.push,Q=J.push,Z=J.slice,ee=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},te=\"checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped\",ne=\"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",re=\"(?:\\\\\\\\.|[\\\\w-]|[^\\\\x00-\\\\xa0])+\",ie=\"\\\\[\"+ne+\"*(\"+re+\")(?:\"+ne+\"*([*^$|!~]?=)\"+ne+\"*(?:'((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\"|(\"+re+\"))|)\"+ne+\"*\\\\]\",oe=\":(\"+re+\")(?:\\\\((('((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\")|((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\"+ie+\")*)|.*)\\\\)|)\",ae=new RegExp(ne+\"+\",\"g\"),se=new RegExp(\"^\"+ne+\"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\"+ne+\"+$\",\"g\"),ue=new RegExp(\"^\"+ne+\"*,\"+ne+\"*\"),le=new RegExp(\"^\"+ne+\"*([>+~]|\"+ne+\")\"+ne+\"*\"),ce=new RegExp(\"=\"+ne+\"*([^\\\\]'\\\"]*?)\"+ne+\"*\\\\]\",\"g\"),fe=new RegExp(oe),de=new RegExp(\"^\"+re+\"$\"),pe={ID:new RegExp(\"^#(\"+re+\")\"),CLASS:new RegExp(\"^\\\\.(\"+re+\")\"),TAG:new RegExp(\"^(\"+re+\"|[*])\"),ATTR:new RegExp(\"^\"+ie),PSEUDO:new RegExp(\"^\"+oe),CHILD:new RegExp(\"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\"+ne+\"*(even|odd|(([+-]|)(\\\\d*)n|)\"+ne+\"*(?:([+-]|)\"+ne+\"*(\\\\d+)|))\"+ne+\"*\\\\)|)\",\"i\"),bool:new RegExp(\"^(?:\"+te+\")$\",\"i\"),needsContext:new RegExp(\"^\"+ne+\"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\"+ne+\"*((?:-\\\\d)?\\\\d*)\"+ne+\"*\\\\)|)(?=[^-]|$)\",\"i\")},he=/^(?:input|select|textarea|button)$/i,ge=/^h\\d$/i,me=/^[^{]+\\{\\s*\\[native \\w/,ye=/^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,ve=/[+~]/,xe=/'|\\\\/g,be=new RegExp(\"\\\\\\\\([\\\\da-f]{1,6}\"+ne+\"?|(\"+ne+\")|.)\",\"ig\"),we=function(e,t,n){var r=\"0x\"+t-65536;return r!==r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},Te=function(){L()};try{Q.apply(J=Z.call(B.childNodes),B.childNodes),J[B.childNodes.length].nodeType}catch(Ce){Q={apply:J.length?function(e,t){K.apply(e,Z.call(t))}:function(e,t){for(var n=e.length,r=0;e[n++]=t[r++];);e.length=n-1}}}w=t.support={},E=t.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return!!t&&\"HTML\"!==t.nodeName},L=t.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:B;return r!==H&&9===r.nodeType&&r.documentElement?(H=r,q=H.documentElement,_=!E(H),(n=H.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener(\"unload\",Te,!1):n.attachEvent&&n.attachEvent(\"onunload\",Te)),w.attributes=i(function(e){return e.className=\"i\",!e.getAttribute(\"className\")}),w.getElementsByTagName=i(function(e){return e.appendChild(H.createComment(\"\")),!e.getElementsByTagName(\"*\").length}),w.getElementsByClassName=me.test(H.getElementsByClassName),w.getById=i(function(e){return q.appendChild(e).id=P,!H.getElementsByName||!H.getElementsByName(P).length}),w.getById?(T.find.ID=function(e,t){if(\"undefined\"!=typeof t.getElementById&&_){var n=t.getElementById(e);return n?[n]:[]}},T.filter.ID=function(e){var t=e.replace(be,we);return function(e){return e.getAttribute(\"id\")===t}}):(delete T.find.ID,T.filter.ID=function(e){var t=e.replace(be,we);return function(e){var n=\"undefined\"!=typeof e.getAttributeNode&&e.getAttributeNode(\"id\");return n&&n.value===t}}),T.find.TAG=w.getElementsByTagName?function(e,t){return\"undefined\"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):w.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if(\"*\"===e){for(;n=o[i++];)1===n.nodeType&&r.push(n);return r}return o},T.find.CLASS=w.getElementsByClassName&&function(e,t){if(\"undefined\"!=typeof t.getElementsByClassName&&_)return t.getElementsByClassName(e)},M=[],F=[],(w.qsa=me.test(H.querySelectorAll))&&(i(function(e){q.appendChild(e).innerHTML=\"<a id='\"+P+\"'></a><select id='\"+P+\"-\\r\\\\' msallowcapture=''><option selected=''></option></select>\",e.querySelectorAll(\"[msallowcapture^='']\").length&&F.push(\"[*^$]=\"+ne+\"*(?:''|\\\"\\\")\"),e.querySelectorAll(\"[selected]\").length||F.push(\"\\\\[\"+ne+\"*(?:value|\"+te+\")\"),e.querySelectorAll(\"[id~=\"+P+\"-]\").length||F.push(\"~=\"),e.querySelectorAll(\":checked\").length||F.push(\":checked\"),e.querySelectorAll(\"a#\"+P+\"+*\").length||F.push(\".#.+[+~]\")}),i(function(e){var t=H.createElement(\"input\");t.setAttribute(\"type\",\"hidden\"),e.appendChild(t).setAttribute(\"name\",\"D\"),e.querySelectorAll(\"[name=d]\").length&&F.push(\"name\"+ne+\"*[*^$|!~]?=\"),e.querySelectorAll(\":enabled\").length||F.push(\":enabled\",\":disabled\"),e.querySelectorAll(\"*,:x\"),F.push(\",.*:\")})),(w.matchesSelector=me.test(O=q.matches||q.webkitMatchesSelector||q.mozMatchesSelector||q.oMatchesSelector||q.msMatchesSelector))&&i(function(e){w.disconnectedMatch=O.call(e,\"div\"),O.call(e,\"[s!='']:x\"),M.push(\"!=\",oe)}),F=F.length&&new RegExp(F.join(\"|\")),M=M.length&&new RegExp(M.join(\"|\")),t=me.test(q.compareDocumentPosition),R=t||me.test(q.contains)?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)for(;t=t.parentNode;)if(t===e)return!0;return!1},U=t?function(e,t){if(e===t)return j=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n?n:(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1,1&n||!w.sortDetached&&t.compareDocumentPosition(e)===n?e===H||e.ownerDocument===B&&R(B,e)?-1:t===H||t.ownerDocument===B&&R(B,t)?1:D?ee(D,e)-ee(D,t):0:4&n?-1:1)}:function(e,t){if(e===t)return j=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,s=[e],u=[t];if(!i||!o)return e===H?-1:t===H?1:i?-1:o?1:D?ee(D,e)-ee(D,t):0;if(i===o)return a(e,t);for(n=e;n=n.parentNode;)s.unshift(n);for(n=t;n=n.parentNode;)u.unshift(n);for(;s[r]===u[r];)r++;return r?a(s[r],u[r]):s[r]===B?-1:u[r]===B?1:0},H):H},t.matches=function(e,n){return t(e,null,null,n)},t.matchesSelector=function(e,n){if((e.ownerDocument||e)!==H&&L(e),n=n.replace(ce,\"='$1']\"),w.matchesSelector&&_&&!X[n+\" \"]&&(!M||!M.test(n))&&(!F||!F.test(n)))try{var r=O.call(e,n);if(r||w.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(i){}return t(n,H,null,[e]).length>0},t.contains=function(e,t){return(e.ownerDocument||e)!==H&&L(e),R(e,t)},t.attr=function(e,t){(e.ownerDocument||e)!==H&&L(e);var n=T.attrHandle[t.toLowerCase()],r=n&&Y.call(T.attrHandle,t.toLowerCase())?n(e,t,!_):void 0;return void 0!==r?r:w.attributes||!_?e.getAttribute(t):(r=e.getAttributeNode(t))&&r.specified?r.value:null},t.error=function(e){throw new Error(\"Syntax error, unrecognized expression: \"+e)},t.uniqueSort=function(e){var t,n=[],r=0,i=0;if(j=!w.detectDuplicates,D=!w.sortStable&&e.slice(0),e.sort(U),j){for(;t=e[i++];)t===e[i]&&(r=n.push(i));for(;r--;)e.splice(n[r],1)}return D=null,e},C=t.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+=C(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r++];)n+=C(t);return n},T=t.selectors={cacheLength:50,createPseudo:r,match:pe,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(be,we),e[3]=(e[3]||e[4]||e[5]||\"\").replace(be,we),\"~=\"===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]||t.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]&&t.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return pe.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||\"\":n&&fe.test(n)&&(t=N(n,!0))&&(t=n.indexOf(\")\",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(be,we).toLowerCase();return\"*\"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=$[e+\" \"];return t||(t=new RegExp(\"(^|\"+ne+\")\"+e+\"(\"+ne+\"|$)\"))&&$(e,function(e){return t.test(\"string\"==typeof e.className&&e.className||\"undefined\"!=typeof e.getAttribute&&e.getAttribute(\"class\")||\"\")})},ATTR:function(e,n,r){return function(i){var o=t.attr(i,e);return null==o?\"!=\"===n:!n||(o+=\"\",\"=\"===n?o===r:\"!=\"===n?o!==r:\"^=\"===n?r&&0===o.indexOf(r):\"*=\"===n?r&&o.indexOf(r)>-1:\"$=\"===n?r&&o.slice(-r.length)===r:\"~=\"===n?(\" \"+o.replace(ae,\" \")+\" \").indexOf(r)>-1:\"|=\"===n&&(o===r||o.slice(0,r.length+1)===r+\"-\"))}},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,u){var l,c,f,d,p,h,g=o!==a?\"nextSibling\":\"previousSibling\",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!u&&!s,x=!1;if(m){if(o){for(;g;){for(d=t;d=d[g];)if(s?d.nodeName.toLowerCase()===y:1===d.nodeType)return!1;h=g=\"only\"===e&&!h&&\"nextSibling\"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){for(d=m,f=d[P]||(d[P]={}),c=f[d.uniqueID]||(f[d.uniqueID]={}),\nl=c[e]||[],p=l[0]===W&&l[1],x=p&&l[2],d=p&&m.childNodes[p];d=++p&&d&&d[g]||(x=p=0)||h.pop();)if(1===d.nodeType&&++x&&d===t){c[e]=[W,p,x];break}}else if(v&&(d=t,f=d[P]||(d[P]={}),c=f[d.uniqueID]||(f[d.uniqueID]={}),l=c[e]||[],p=l[0]===W&&l[1],x=p),x===!1)for(;(d=++p&&d&&d[g]||(x=p=0)||h.pop())&&((s?d.nodeName.toLowerCase()!==y:1!==d.nodeType)||!++x||(v&&(f=d[P]||(d[P]={}),c=f[d.uniqueID]||(f[d.uniqueID]={}),c[e]=[W,x]),d!==t)););return x-=i,x===r||x%r===0&&x/r>=0}}},PSEUDO:function(e,n){var i,o=T.pseudos[e]||T.setFilters[e.toLowerCase()]||t.error(\"unsupported pseudo: \"+e);return o[P]?o(n):o.length>1?(i=[e,e,\"\",n],T.setFilters.hasOwnProperty(e.toLowerCase())?r(function(e,t){for(var r,i=o(e,n),a=i.length;a--;)r=ee(e,i[a]),e[r]=!(t[r]=i[a])}):function(e){return o(e,0,i)}):o}},pseudos:{not:r(function(e){var t=[],n=[],i=k(e.replace(se,\"$1\"));return i[P]?r(function(e,t,n,r){for(var o,a=i(e,null,r,[]),s=e.length;s--;)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,r,o){return t[0]=e,i(t,null,o,n),t[0]=null,!n.pop()}}),has:r(function(e){return function(n){return t(e,n).length>0}}),contains:r(function(e){return e=e.replace(be,we),function(t){return(t.textContent||t.innerText||C(t)).indexOf(e)>-1}}),lang:r(function(e){return de.test(e||\"\")||t.error(\"unsupported lang: \"+e),e=e.replace(be,we).toLowerCase(),function(t){var n;do if(n=_?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===q},focus:function(e){return e===H.activeElement&&(!H.hasFocus||H.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.nodeType<6)return!1;return!0},parent:function(e){return!T.pseudos.empty(e)},header:function(e){return ge.test(e.nodeName)},input:function(e){return he.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\"))||\"text\"===t.toLowerCase())},first:l(function(){return[0]}),last:l(function(e,t){return[t-1]}),eq:l(function(e,t,n){return[n<0?n+t:n]}),even:l(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:l(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:l(function(e,t,n){for(var r=n<0?n+t:n;--r>=0;)e.push(r);return e}),gt:l(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}},T.pseudos.nth=T.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})T.pseudos[b]=s(b);for(b in{submit:!0,reset:!0})T.pseudos[b]=u(b);return f.prototype=T.filters=T.pseudos,T.setFilters=new f,N=t.tokenize=function(e,n){var r,i,o,a,s,u,l,c=z[e+\" \"];if(c)return n?0:c.slice(0);for(s=e,u=[],l=T.preFilter;s;){r&&!(i=ue.exec(s))||(i&&(s=s.slice(i[0].length)||s),u.push(o=[])),r=!1,(i=le.exec(s))&&(r=i.shift(),o.push({value:r,type:i[0].replace(se,\" \")}),s=s.slice(r.length));for(a in T.filter)!(i=pe[a].exec(s))||l[a]&&!(i=l[a](i))||(r=i.shift(),o.push({value:r,type:a,matches:i}),s=s.slice(r.length));if(!r)break}return n?s.length:s?t.error(e):z(e,u).slice(0)},k=t.compile=function(e,t){var n,r=[],i=[],o=X[e+\" \"];if(!o){for(t||(t=N(e)),n=t.length;n--;)o=v(t[n]),o[P]?r.push(o):i.push(o);o=X(e,x(i,r)),o.selector=e}return o},S=t.select=function(e,t,n,r){var i,o,a,s,u,l=\"function\"==typeof e&&e,f=!r&&N(e=l.selector||e);if(n=n||[],1===f.length){if(o=f[0]=f[0].slice(0),o.length>2&&\"ID\"===(a=o[0]).type&&w.getById&&9===t.nodeType&&_&&T.relative[o[1].type]){if(t=(T.find.ID(a.matches[0].replace(be,we),t)||[])[0],!t)return n;l&&(t=t.parentNode),e=e.slice(o.shift().value.length)}for(i=pe.needsContext.test(e)?0:o.length;i--&&(a=o[i],!T.relative[s=a.type]);)if((u=T.find[s])&&(r=u(a.matches[0].replace(be,we),ve.test(o[0].type)&&c(t.parentNode)||t))){if(o.splice(i,1),e=r.length&&d(o),!e)return Q.apply(n,r),n;break}}return(l||k(e,f))(r,t,!_,n,!t||ve.test(e)&&c(t.parentNode)||t),n},w.sortStable=P.split(\"\").sort(U).join(\"\")===P,w.detectDuplicates=!!j,L(),w.sortDetached=i(function(e){return 1&e.compareDocumentPosition(H.createElement(\"div\"))}),i(function(e){return e.innerHTML=\"<a href='#'></a>\",\"#\"===e.firstChild.getAttribute(\"href\")})||o(\"type|href|height|width\",function(e,t,n){if(!n)return e.getAttribute(t,\"type\"===t.toLowerCase()?1:2)}),w.attributes&&i(function(e){return e.innerHTML=\"<input/>\",e.firstChild.setAttribute(\"value\",\"\"),\"\"===e.firstChild.getAttribute(\"value\")})||o(\"value\",function(e,t,n){if(!n&&\"input\"===e.nodeName.toLowerCase())return e.defaultValue}),i(function(e){return null==e.getAttribute(\"disabled\")})||o(te,function(e,t,n){var r;if(!n)return e[t]===!0?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),t}(e);pe.find=ve,pe.expr=ve.selectors,pe.expr[\":\"]=pe.expr.pseudos,pe.uniqueSort=pe.unique=ve.uniqueSort,pe.text=ve.getText,pe.isXMLDoc=ve.isXML,pe.contains=ve.contains;var xe=function(e,t,n){for(var r=[],i=void 0!==n;(e=e[t])&&9!==e.nodeType;)if(1===e.nodeType){if(i&&pe(e).is(n))break;r.push(e)}return r},be=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},we=pe.expr.match.needsContext,Te=/^<([\\w-]+)\\s*\\/?>(?:<\\/\\1>|)$/,Ce=/^.[^:#\\[\\.,]*$/;pe.filter=function(e,t,n){var r=t[0];return n&&(e=\":not(\"+e+\")\"),1===t.length&&1===r.nodeType?pe.find.matchesSelector(r,e)?[r]:[]:pe.find.matches(e,pe.grep(t,function(e){return 1===e.nodeType}))},pe.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if(\"string\"!=typeof e)return this.pushStack(pe(e).filter(function(){for(t=0;t<i;t++)if(pe.contains(r[t],this))return!0}));for(t=0;t<i;t++)pe.find(e,r[t],n);return n=this.pushStack(i>1?pe.unique(n):n),n.selector=this.selector?this.selector+\" \"+e:e,n},filter:function(e){return this.pushStack(r(this,e||[],!1))},not:function(e){return this.pushStack(r(this,e||[],!0))},is:function(e){return!!r(this,\"string\"==typeof e&&we.test(e)?pe(e):e||[],!1).length}});var Ee,Ne=/^(?:\\s*(<[\\w\\W]+>)[^>]*|#([\\w-]*))$/,ke=pe.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||Ee,\"string\"==typeof e){if(r=\"<\"===e.charAt(0)&&\">\"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:Ne.exec(e),!r||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof pe?t[0]:t,pe.merge(this,pe.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:re,!0)),Te.test(r[1])&&pe.isPlainObject(t))for(r in t)pe.isFunction(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}if(i=re.getElementById(r[2]),i&&i.parentNode){if(i.id!==r[2])return Ee.find(e);this.length=1,this[0]=i}return this.context=re,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):pe.isFunction(e)?\"undefined\"!=typeof n.ready?n.ready(e):e(pe):(void 0!==e.selector&&(this.selector=e.selector,this.context=e.context),pe.makeArray(e,this))};ke.prototype=pe.fn,Ee=pe(re);var Se=/^(?:parents|prev(?:Until|All))/,Ae={children:!0,contents:!0,next:!0,prev:!0};pe.fn.extend({has:function(e){var t,n=pe(e,this),r=n.length;return this.filter(function(){for(t=0;t<r;t++)if(pe.contains(this,n[t]))return!0})},closest:function(e,t){for(var n,r=0,i=this.length,o=[],a=we.test(e)||\"string\"!=typeof e?pe(e,t||this.context):0;r<i;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(n.nodeType<11&&(a?a.index(n)>-1:1===n.nodeType&&pe.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(o.length>1?pe.uniqueSort(o):o)},index:function(e){return e?\"string\"==typeof e?pe.inArray(this[0],pe(e)):pe.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(pe.uniqueSort(pe.merge(this.get(),pe(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),pe.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return xe(e,\"parentNode\")},parentsUntil:function(e,t,n){return xe(e,\"parentNode\",n)},next:function(e){return i(e,\"nextSibling\")},prev:function(e){return i(e,\"previousSibling\")},nextAll:function(e){return xe(e,\"nextSibling\")},prevAll:function(e){return xe(e,\"previousSibling\")},nextUntil:function(e,t,n){return xe(e,\"nextSibling\",n)},prevUntil:function(e,t,n){return xe(e,\"previousSibling\",n)},siblings:function(e){return be((e.parentNode||{}).firstChild,e)},children:function(e){return be(e.firstChild)},contents:function(e){return pe.nodeName(e,\"iframe\")?e.contentDocument||e.contentWindow.document:pe.merge([],e.childNodes)}},function(e,t){pe.fn[e]=function(n,r){var i=pe.map(this,t,n);return\"Until\"!==e.slice(-5)&&(r=n),r&&\"string\"==typeof r&&(i=pe.filter(r,i)),this.length>1&&(Ae[e]||(i=pe.uniqueSort(i)),Se.test(e)&&(i=i.reverse())),this.pushStack(i)}});var De=/\\S+/g;pe.Callbacks=function(e){e=\"string\"==typeof e?o(e):pe.extend({},e);var t,n,r,i,a=[],s=[],u=-1,l=function(){for(i=e.once,r=t=!0;s.length;u=-1)for(n=s.shift();++u<a.length;)a[u].apply(n[0],n[1])===!1&&e.stopOnFalse&&(u=a.length,n=!1);e.memory||(n=!1),t=!1,i&&(a=n?[]:\"\")},c={add:function(){return a&&(n&&!t&&(u=a.length-1,s.push(n)),function r(t){pe.each(t,function(t,n){pe.isFunction(n)?e.unique&&c.has(n)||a.push(n):n&&n.length&&\"string\"!==pe.type(n)&&r(n)})}(arguments),n&&!t&&l()),this},remove:function(){return pe.each(arguments,function(e,t){for(var n;(n=pe.inArray(t,a,n))>-1;)a.splice(n,1),n<=u&&u--}),this},has:function(e){return e?pe.inArray(e,a)>-1:a.length>0},empty:function(){return a&&(a=[]),this},disable:function(){return i=s=[],a=n=\"\",this},disabled:function(){return!a},lock:function(){return i=!0,n||c.disable(),this},locked:function(){return!!i},fireWith:function(e,n){return i||(n=n||[],n=[e,n.slice?n.slice():n],s.push(n),t||l()),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!r}};return c},pe.extend({Deferred:function(e){var t=[[\"resolve\",\"done\",pe.Callbacks(\"once memory\"),\"resolved\"],[\"reject\",\"fail\",pe.Callbacks(\"once memory\"),\"rejected\"],[\"notify\",\"progress\",pe.Callbacks(\"memory\")]],n=\"pending\",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return pe.Deferred(function(n){pe.each(t,function(t,o){var a=pe.isFunction(e[t])&&e[t];i[o[1]](function(){var e=a&&a.apply(this,arguments);e&&pe.isFunction(e.promise)?e.promise().progress(n.notify).done(n.resolve).fail(n.reject):n[o[0]+\"With\"](this===r?n.promise():this,a?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?pe.extend(e,r):r}},i={};return r.pipe=r.then,pe.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,n,r,i=0,o=ie.call(arguments),a=o.length,s=1!==a||e&&pe.isFunction(e.promise)?a:0,u=1===s?e:pe.Deferred(),l=function(e,n,r){return function(i){n[e]=this,r[e]=arguments.length>1?ie.call(arguments):i,r===t?u.notifyWith(n,r):--s||u.resolveWith(n,r)}};if(a>1)for(t=new Array(a),n=new Array(a),r=new Array(a);i<a;i++)o[i]&&pe.isFunction(o[i].promise)?o[i].promise().progress(l(i,n,t)).done(l(i,r,o)).fail(u.reject):--s;return s||u.resolveWith(r,o),u.promise()}});var je;pe.fn.ready=function(e){return pe.ready.promise().done(e),this},pe.extend({isReady:!1,readyWait:1,holdReady:function(e){e?pe.readyWait++:pe.ready(!0)},ready:function(e){(e===!0?--pe.readyWait:pe.isReady)||(pe.isReady=!0,e!==!0&&--pe.readyWait>0||(je.resolveWith(re,[pe]),pe.fn.triggerHandler&&(pe(re).triggerHandler(\"ready\"),pe(re).off(\"ready\"))))}}),pe.ready.promise=function(t){if(!je)if(je=pe.Deferred(),\"complete\"===re.readyState||\"loading\"!==re.readyState&&!re.documentElement.doScroll)e.setTimeout(pe.ready);else if(re.addEventListener)re.addEventListener(\"DOMContentLoaded\",s),e.addEventListener(\"load\",s);else{re.attachEvent(\"onreadystatechange\",s),e.attachEvent(\"onload\",s);var n=!1;try{n=null==e.frameElement&&re.documentElement}catch(r){}n&&n.doScroll&&!function i(){if(!pe.isReady){try{n.doScroll(\"left\")}catch(t){return e.setTimeout(i,50)}a(),pe.ready()}}()}return je.promise(t)},pe.ready.promise();var Le;for(Le in pe(fe))break;fe.ownFirst=\"0\"===Le,fe.inlineBlockNeedsLayout=!1,pe(function(){var e,t,n,r;n=re.getElementsByTagName(\"body\")[0],n&&n.style&&(t=re.createElement(\"div\"),r=re.createElement(\"div\"),r.style.cssText=\"position:absolute;border:0;width:0;height:0;top:0;left:-9999px\",n.appendChild(r).appendChild(t),\"undefined\"!=typeof t.style.zoom&&(t.style.cssText=\"display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1\",fe.inlineBlockNeedsLayout=e=3===t.offsetWidth,e&&(n.style.zoom=1)),n.removeChild(r))}),function(){var e=re.createElement(\"div\");fe.deleteExpando=!0;try{delete e.test}catch(t){fe.deleteExpando=!1}e=null}();var He=function(e){var t=pe.noData[(e.nodeName+\" \").toLowerCase()],n=+e.nodeType||1;return(1===n||9===n)&&(!t||t!==!0&&e.getAttribute(\"classid\")===t)},qe=/^(?:\\{[\\w\\W]*\\}|\\[[\\w\\W]*\\])$/,_e=/([A-Z])/g;pe.extend({cache:{},noData:{\"applet \":!0,\"embed \":!0,\"object \":\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"},hasData:function(e){return e=e.nodeType?pe.cache[e[pe.expando]]:e[pe.expando],!!e&&!l(e)},data:function(e,t,n){return c(e,t,n)},removeData:function(e,t){return f(e,t)},_data:function(e,t,n){return c(e,t,n,!0)},_removeData:function(e,t){return f(e,t,!0)}}),pe.fn.extend({data:function(e,t){var n,r,i,o=this[0],a=o&&o.attributes;if(void 0===e){if(this.length&&(i=pe.data(o),1===o.nodeType&&!pe._data(o,\"parsedAttrs\"))){for(n=a.length;n--;)a[n]&&(r=a[n].name,0===r.indexOf(\"data-\")&&(r=pe.camelCase(r.slice(5)),u(o,r,i[r])));pe._data(o,\"parsedAttrs\",!0)}return i}return\"object\"==typeof e?this.each(function(){pe.data(this,e)}):arguments.length>1?this.each(function(){pe.data(this,e,t)}):o?u(o,e,pe.data(o,e)):void 0},removeData:function(e){return this.each(function(){pe.removeData(this,e)})}}),pe.extend({queue:function(e,t,n){var r;if(e)return t=(t||\"fx\")+\"queue\",r=pe._data(e,t),n&&(!r||pe.isArray(n)?r=pe._data(e,t,pe.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||\"fx\";var n=pe.queue(e,t),r=n.length,i=n.shift(),o=pe._queueHooks(e,t),a=function(){pe.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 pe._data(e,n)||pe._data(e,n,{empty:pe.Callbacks(\"once memory\").add(function(){pe._removeData(e,t+\"queue\"),pe._removeData(e,n)})})}}),pe.fn.extend({queue:function(e,t){var n=2;return\"string\"!=typeof e&&(t=e,e=\"fx\",n--),arguments.length<n?pe.queue(this[0],e):void 0===t?this:this.each(function(){var n=pe.queue(this,e,t);pe._queueHooks(this,e),\"fx\"===e&&\"inprogress\"!==n[0]&&pe.dequeue(this,e)})},dequeue:function(e){return this.each(function(){pe.dequeue(this,e)})},clearQueue:function(e){return this.queue(e||\"fx\",[])},promise:function(e,t){var n,r=1,i=pe.Deferred(),o=this,a=this.length,s=function(){--r||i.resolveWith(o,[o])};for(\"string\"!=typeof e&&(t=e,e=void 0),e=e||\"fx\";a--;)n=pe._data(o[a],e+\"queueHooks\"),n&&n.empty&&(r++,n.empty.add(s));return s(),i.promise(t)}}),function(){var e;fe.shrinkWrapBlocks=function(){if(null!=e)return e;e=!1;var t,n,r;return n=re.getElementsByTagName(\"body\")[0],n&&n.style?(t=re.createElement(\"div\"),r=re.createElement(\"div\"),r.style.cssText=\"position:absolute;border:0;width:0;height:0;top:0;left:-9999px\",n.appendChild(r).appendChild(t),\"undefined\"!=typeof t.style.zoom&&(t.style.cssText=\"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:1px;width:1px;zoom:1\",t.appendChild(re.createElement(\"div\")).style.width=\"5px\",e=3!==t.offsetWidth),n.removeChild(r),e):void 0}}();var Fe=/[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/.source,Me=new RegExp(\"^(?:([+-])=|)(\"+Fe+\")([a-z%]*)$\",\"i\"),Oe=[\"Top\",\"Right\",\"Bottom\",\"Left\"],Re=function(e,t){return e=t||e,\"none\"===pe.css(e,\"display\")||!pe.contains(e.ownerDocument,e)},Pe=function(e,t,n,r,i,o,a){var s=0,u=e.length,l=null==n;if(\"object\"===pe.type(n)){i=!0;for(s in n)Pe(e,t,s,n[s],!0,o,a)}else if(void 0!==r&&(i=!0,pe.isFunction(r)||(a=!0),l&&(a?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(pe(e),n)})),t))for(;s<u;s++)t(e[s],n,a?r:r.call(e[s],s,t(e[s],n)));return i?e:l?t.call(e):u?t(e[0],n):o},Be=/^(?:checkbox|radio)$/i,We=/<([\\w:-]+)/,Ie=/^$|\\/(?:java|ecma)script/i,$e=/^\\s+/,ze=\"abbr|article|aside|audio|bdi|canvas|data|datalist|details|dialog|figcaption|figure|footer|header|hgroup|main|mark|meter|nav|output|picture|progress|section|summary|template|time|video\";!function(){var e=re.createElement(\"div\"),t=re.createDocumentFragment(),n=re.createElement(\"input\");e.innerHTML=\"  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>\",fe.leadingWhitespace=3===e.firstChild.nodeType,fe.tbody=!e.getElementsByTagName(\"tbody\").length,fe.htmlSerialize=!!e.getElementsByTagName(\"link\").length,fe.html5Clone=\"<:nav></:nav>\"!==re.createElement(\"nav\").cloneNode(!0).outerHTML,n.type=\"checkbox\",n.checked=!0,t.appendChild(n),fe.appendChecked=n.checked,e.innerHTML=\"<textarea>x</textarea>\",fe.noCloneChecked=!!e.cloneNode(!0).lastChild.defaultValue,t.appendChild(e),n=re.createElement(\"input\"),n.setAttribute(\"type\",\"radio\"),n.setAttribute(\"checked\",\"checked\"),n.setAttribute(\"name\",\"t\"),e.appendChild(n),fe.checkClone=e.cloneNode(!0).cloneNode(!0).lastChild.checked,fe.noCloneEvent=!!e.addEventListener,e[pe.expando]=1,fe.attributes=!e.getAttribute(pe.expando)}();var Xe={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:fe.htmlSerialize?[0,\"\",\"\"]:[1,\"X<div>\",\"</div>\"]};Xe.optgroup=Xe.option,Xe.tbody=Xe.tfoot=Xe.colgroup=Xe.caption=Xe.thead,Xe.th=Xe.td;var Ue=/<|&#?\\w+;/,Ve=/<tbody/i;!function(){var t,n,r=re.createElement(\"div\");for(t in{submit:!0,change:!0,focusin:!0})n=\"on\"+t,(fe[t]=n in e)||(r.setAttribute(n,\"t\"),fe[t]=r.attributes[n].expando===!1);r=null}();var Ye=/^(?:input|select|textarea)$/i,Je=/^key/,Ge=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ke=/^(?:focusinfocus|focusoutblur)$/,Qe=/^([^.]*)(?:\\.(.+)|)/;pe.event={global:{},add:function(e,t,n,r,i){var o,a,s,u,l,c,f,d,p,h,g,m=pe._data(e);if(m){for(n.handler&&(u=n,n=u.handler,i=u.selector),n.guid||(n.guid=pe.guid++),(a=m.events)||(a=m.events={}),(c=m.handle)||(c=m.handle=function(e){return\"undefined\"==typeof pe||e&&pe.event.triggered===e.type?void 0:pe.event.dispatch.apply(c.elem,arguments)},c.elem=e),t=(t||\"\").match(De)||[\"\"],s=t.length;s--;)o=Qe.exec(t[s])||[],p=g=o[1],h=(o[2]||\"\").split(\".\").sort(),p&&(l=pe.event.special[p]||{},p=(i?l.delegateType:l.bindType)||p,l=pe.event.special[p]||{},f=pe.extend({type:p,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&pe.expr.match.needsContext.test(i),namespace:h.join(\".\")},u),(d=a[p])||(d=a[p]=[],d.delegateCount=0,l.setup&&l.setup.call(e,r,h,c)!==!1||(e.addEventListener?e.addEventListener(p,c,!1):e.attachEvent&&e.attachEvent(\"on\"+p,c))),l.add&&(l.add.call(e,f),f.handler.guid||(f.handler.guid=n.guid)),i?d.splice(d.delegateCount++,0,f):d.push(f),pe.event.global[p]=!0);e=null}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,d,p,h,g,m=pe.hasData(e)&&pe._data(e);if(m&&(c=m.events)){for(t=(t||\"\").match(De)||[\"\"],l=t.length;l--;)if(s=Qe.exec(t[l])||[],p=g=s[1],h=(s[2]||\"\").split(\".\").sort(),p){for(f=pe.event.special[p]||{},p=(r?f.delegateType:f.bindType)||p,d=c[p]||[],s=s[2]&&new RegExp(\"(^|\\\\.)\"+h.join(\"\\\\.(?:.*\\\\.|)\")+\"(\\\\.|$)\"),u=o=d.length;o--;)a=d[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&(\"**\"!==r||!a.selector)||(d.splice(o,1),a.selector&&d.delegateCount--,f.remove&&f.remove.call(e,a));u&&!d.length&&(f.teardown&&f.teardown.call(e,h,m.handle)!==!1||pe.removeEvent(e,p,m.handle),delete c[p])}else for(p in c)pe.event.remove(e,p+t[l],n,r,!0);pe.isEmptyObject(c)&&(delete m.handle,pe._removeData(e,\"events\"))}},trigger:function(t,n,r,i){var o,a,s,u,l,c,f,d=[r||re],p=ce.call(t,\"type\")?t.type:t,h=ce.call(t,\"namespace\")?t.namespace.split(\".\"):[];if(s=c=r=r||re,3!==r.nodeType&&8!==r.nodeType&&!Ke.test(p+pe.event.triggered)&&(p.indexOf(\".\")>-1&&(h=p.split(\".\"),p=h.shift(),h.sort()),a=p.indexOf(\":\")<0&&\"on\"+p,t=t[pe.expando]?t:new pe.Event(p,\"object\"==typeof t&&t),t.isTrigger=i?2:3,t.namespace=h.join(\".\"),t.rnamespace=t.namespace?new RegExp(\"(^|\\\\.)\"+h.join(\"\\\\.(?:.*\\\\.|)\")+\"(\\\\.|$)\"):null,t.result=void 0,t.target||(t.target=r),n=null==n?[t]:pe.makeArray(n,[t]),l=pe.event.special[p]||{},i||!l.trigger||l.trigger.apply(r,n)!==!1)){if(!i&&!l.noBubble&&!pe.isWindow(r)){for(u=l.delegateType||p,Ke.test(u+p)||(s=s.parentNode);s;s=s.parentNode)d.push(s),c=s;c===(r.ownerDocument||re)&&d.push(c.defaultView||c.parentWindow||e)}for(f=0;(s=d[f++])&&!t.isPropagationStopped();)t.type=f>1?u:l.bindType||p,o=(pe._data(s,\"events\")||{})[t.type]&&pe._data(s,\"handle\"),o&&o.apply(s,n),o=a&&s[a],o&&o.apply&&He(s)&&(t.result=o.apply(s,n),t.result===!1&&t.preventDefault());if(t.type=p,!i&&!t.isDefaultPrevented()&&(!l._default||l._default.apply(d.pop(),n)===!1)&&He(r)&&a&&r[p]&&!pe.isWindow(r)){c=r[a],c&&(r[a]=null),pe.event.triggered=p;try{r[p]()}catch(g){}pe.event.triggered=void 0,c&&(r[a]=c)}return t.result}},dispatch:function(e){e=pe.event.fix(e);var t,n,r,i,o,a=[],s=ie.call(arguments),u=(pe._data(this,\"events\")||{})[e.type]||[],l=pe.event.special[e.type]||{};if(s[0]=e,e.delegateTarget=this,!l.preDispatch||l.preDispatch.call(this,e)!==!1){for(a=pe.event.handlers.call(this,e,u),t=0;(i=a[t++])&&!e.isPropagationStopped();)for(e.currentTarget=i.elem,n=0;(o=i.handlers[n++])&&!e.isImmediatePropagationStopped();)e.rnamespace&&!e.rnamespace.test(o.namespace)||(e.handleObj=o,e.data=o.data,r=((pe.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,s),void 0!==r&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()));return l.postDispatch&&l.postDispatch.call(this,e),e.result}},handlers:function(e,t){var n,r,i,o,a=[],s=t.delegateCount,u=e.target;if(s&&u.nodeType&&(\"click\"!==e.type||isNaN(e.button)||e.button<1))for(;u!=this;u=u.parentNode||this)if(1===u.nodeType&&(u.disabled!==!0||\"click\"!==e.type)){for(r=[],n=0;n<s;n++)o=t[n],i=o.selector+\" \",void 0===r[i]&&(r[i]=o.needsContext?pe(i,this).index(u)>-1:pe.find(i,this,null,[u]).length),r[i]&&r.push(o);r.length&&a.push({elem:u,handlers:r})}return s<t.length&&a.push({elem:this,handlers:t.slice(s)}),a},fix:function(e){if(e[pe.expando])return e;var t,n,r,i=e.type,o=e,a=this.fixHooks[i];for(a||(this.fixHooks[i]=a=Ge.test(i)?this.mouseHooks:Je.test(i)?this.keyHooks:{}),r=a.props?this.props.concat(a.props):this.props,e=new pe.Event(o),t=r.length;t--;)n=r[t],e[n]=o[n];return e.target||(e.target=o.srcElement||re),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,a.filter?a.filter(e,o):e},props:\"altKey bubbles cancelable ctrlKey currentTarget detail 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,t){var n,r,i,o=t.button,a=t.fromElement;return null==e.pageX&&null!=t.clientX&&(r=e.target.ownerDocument||re,i=r.documentElement,n=r.body,e.pageX=t.clientX+(i&&i.scrollLeft||n&&n.scrollLeft||0)-(i&&i.clientLeft||n&&n.clientLeft||0),e.pageY=t.clientY+(i&&i.scrollTop||n&&n.scrollTop||0)-(i&&i.clientTop||n&&n.clientTop||0)),!e.relatedTarget&&a&&(e.relatedTarget=a===e.target?t.toElement:a),e.which||void 0===o||(e.which=1&o?1:2&o?3:4&o?2:0),e}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==b()&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:\"focusin\"},blur:{trigger:function(){if(this===b()&&this.blur)return this.blur(),!1},delegateType:\"focusout\"},click:{trigger:function(){if(pe.nodeName(this,\"input\")&&\"checkbox\"===this.type&&this.click)return this.click(),!1},_default:function(e){return pe.nodeName(e.target,\"a\")}},beforeunload:{postDispatch:function(e){void 0!==e.result&&e.originalEvent&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n){var r=pe.extend(new pe.Event,n,{type:e,isSimulated:!0});pe.event.trigger(r,null,t),r.isDefaultPrevented()&&n.preventDefault()}},pe.removeEvent=re.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n)}:function(e,t,n){var r=\"on\"+t;e.detachEvent&&(\"undefined\"==typeof e[r]&&(e[r]=null),e.detachEvent(r,n))},pe.Event=function(e,t){return this instanceof pe.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||void 0===e.defaultPrevented&&e.returnValue===!1?v:x):this.type=e,t&&pe.extend(this,t),this.timeStamp=e&&e.timeStamp||pe.now(),void(this[pe.expando]=!0)):new pe.Event(e,t)},pe.Event.prototype={constructor:pe.Event,isDefaultPrevented:x,isPropagationStopped:x,isImmediatePropagationStopped:x,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=v,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=v,e&&!this.isSimulated&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){var e=this.originalEvent;this.isImmediatePropagationStopped=v,e&&e.stopImmediatePropagation&&e.stopImmediatePropagation(),this.stopPropagation()}},pe.each({mouseenter:\"mouseover\",mouseleave:\"mouseout\",pointerenter:\"pointerover\",pointerleave:\"pointerout\"},function(e,t){pe.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return i&&(i===r||pe.contains(r,i))||(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),fe.submit||(pe.event.special.submit={setup:function(){return!pe.nodeName(this,\"form\")&&void pe.event.add(this,\"click._submit keypress._submit\",function(e){var t=e.target,n=pe.nodeName(t,\"input\")||pe.nodeName(t,\"button\")?pe.prop(t,\"form\"):void 0;n&&!pe._data(n,\"submit\")&&(pe.event.add(n,\"submit._submit\",function(e){e._submitBubble=!0}),pe._data(n,\"submit\",!0))})},postDispatch:function(e){e._submitBubble&&(delete e._submitBubble,this.parentNode&&!e.isTrigger&&pe.event.simulate(\"submit\",this.parentNode,e))},teardown:function(){return!pe.nodeName(this,\"form\")&&void pe.event.remove(this,\"._submit\")}}),fe.change||(pe.event.special.change={setup:function(){return Ye.test(this.nodeName)?(\"checkbox\"!==this.type&&\"radio\"!==this.type||(pe.event.add(this,\"propertychange._change\",function(e){\"checked\"===e.originalEvent.propertyName&&(this._justChanged=!0)}),pe.event.add(this,\"click._change\",function(e){this._justChanged&&!e.isTrigger&&(this._justChanged=!1),pe.event.simulate(\"change\",this,e)})),!1):void pe.event.add(this,\"beforeactivate._change\",function(e){var t=e.target;Ye.test(t.nodeName)&&!pe._data(t,\"change\")&&(pe.event.add(t,\"change._change\",function(e){!this.parentNode||e.isSimulated||e.isTrigger||pe.event.simulate(\"change\",this.parentNode,e)}),pe._data(t,\"change\",!0))})},handle:function(e){var t=e.target;if(this!==t||e.isSimulated||e.isTrigger||\"radio\"!==t.type&&\"checkbox\"!==t.type)return e.handleObj.handler.apply(this,arguments)},teardown:function(){return pe.event.remove(this,\"._change\"),!Ye.test(this.nodeName)}}),fe.focusin||pe.each({focus:\"focusin\",blur:\"focusout\"},function(e,t){var n=function(e){pe.event.simulate(t,e.target,pe.event.fix(e))};pe.event.special[t]={setup:function(){var r=this.ownerDocument||this,i=pe._data(r,t);i||r.addEventListener(e,n,!0),pe._data(r,t,(i||0)+1)},teardown:function(){var r=this.ownerDocument||this,i=pe._data(r,t)-1;i?pe._data(r,t,i):(r.removeEventListener(e,n,!0),pe._removeData(r,t))}}}),pe.fn.extend({on:function(e,t,n,r){return w(this,e,t,n,r)},one:function(e,t,n,r){return w(this,e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,pe(e.delegateTarget).off(r.namespace?r.origType+\".\"+r.namespace:r.origType,r.selector,r.handler),this;if(\"object\"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return t!==!1&&\"function\"!=typeof t||(n=t,t=void 0),n===!1&&(n=x),this.each(function(){pe.event.remove(this,e,n,t)})},trigger:function(e,t){return this.each(function(){pe.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return pe.event.trigger(e,t,n,!0)}});var Ze=/ jQuery\\d+=\"(?:null|\\d+)\"/g,et=new RegExp(\"<(?:\"+ze+\")[\\\\s/>]\",\"i\"),tt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:-]+)[^>]*)\\/>/gi,nt=/<script|<style|<link/i,rt=/checked\\s*(?:[^=]|=\\s*.checked.)/i,it=/^true\\/(.*)/,ot=/^\\s*<!(?:\\[CDATA\\[|--)|(?:\\]\\]|--)>\\s*$/g,at=p(re),st=at.appendChild(re.createElement(\"div\"));pe.extend({htmlPrefilter:function(e){return e.replace(tt,\"<$1></$2>\")},clone:function(e,t,n){var r,i,o,a,s,u=pe.contains(e.ownerDocument,e);if(fe.html5Clone||pe.isXMLDoc(e)||!et.test(\"<\"+e.nodeName+\">\")?o=e.cloneNode(!0):(st.innerHTML=e.outerHTML,st.removeChild(o=st.firstChild)),!(fe.noCloneEvent&&fe.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||pe.isXMLDoc(e)))for(r=h(o),s=h(e),a=0;null!=(i=s[a]);++a)r[a]&&k(i,r[a]);if(t)if(n)for(s=s||h(e),r=r||h(o),a=0;null!=(i=s[a]);a++)N(i,r[a]);else N(e,o);return r=h(o,\"script\"),r.length>0&&g(r,!u&&h(e,\"script\")),r=s=i=null,o},cleanData:function(e,t){for(var n,r,i,o,a=0,s=pe.expando,u=pe.cache,l=fe.attributes,c=pe.event.special;null!=(n=e[a]);a++)if((t||He(n))&&(i=n[s],o=i&&u[i])){if(o.events)for(r in o.events)c[r]?pe.event.remove(n,r):pe.removeEvent(n,r,o.handle);u[i]&&(delete u[i],l||\"undefined\"==typeof n.removeAttribute?n[s]=void 0:n.removeAttribute(s),ne.push(i))}}}),pe.fn.extend({domManip:S,detach:function(e){return A(this,e,!0)},remove:function(e){return A(this,e)},text:function(e){return Pe(this,function(e){return void 0===e?pe.text(this):this.empty().append((this[0]&&this[0].ownerDocument||re).createTextNode(e))},null,e,arguments.length)},append:function(){return S(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=T(this,e);t.appendChild(e)}})},prepend:function(){return S(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=T(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return S(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return S(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++){for(1===e.nodeType&&pe.cleanData(h(e,!1));e.firstChild;)e.removeChild(e.firstChild);e.options&&pe.nodeName(e,\"select\")&&(e.options.length=0)}return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return pe.clone(this,e,t)})},html:function(e){return Pe(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e)return 1===t.nodeType?t.innerHTML.replace(Ze,\"\"):void 0;if(\"string\"==typeof e&&!nt.test(e)&&(fe.htmlSerialize||!et.test(e))&&(fe.leadingWhitespace||!$e.test(e))&&!Xe[(We.exec(e)||[\"\",\"\"])[1].toLowerCase()]){e=pe.htmlPrefilter(e);try{for(;n<r;n++)t=this[n]||{},1===t.nodeType&&(pe.cleanData(h(t,!1)),t.innerHTML=e);t=0}catch(i){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=[];return S(this,arguments,function(t){var n=this.parentNode;pe.inArray(this,e)<0&&(pe.cleanData(h(this)),\nn&&n.replaceChild(t,this))},e)}}),pe.each({appendTo:\"append\",prependTo:\"prepend\",insertBefore:\"before\",insertAfter:\"after\",replaceAll:\"replaceWith\"},function(e,t){pe.fn[e]=function(e){for(var n,r=0,i=[],o=pe(e),a=o.length-1;r<=a;r++)n=r===a?this:this.clone(!0),pe(o[r])[t](n),ae.apply(i,n.get());return this.pushStack(i)}});var ut,lt={HTML:\"block\",BODY:\"block\"},ct=/^margin/,ft=new RegExp(\"^(\"+Fe+\")(?!px)[a-z%]+$\",\"i\"),dt=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},pt=re.documentElement;!function(){function t(){var t,c,f=re.documentElement;f.appendChild(u),l.style.cssText=\"-webkit-box-sizing:border-box;box-sizing:border-box;position:relative;display:block;margin:auto;border:1px;padding:1px;top:1%;width:50%\",n=i=s=!1,r=a=!0,e.getComputedStyle&&(c=e.getComputedStyle(l),n=\"1%\"!==(c||{}).top,s=\"2px\"===(c||{}).marginLeft,i=\"4px\"===(c||{width:\"4px\"}).width,l.style.marginRight=\"50%\",r=\"4px\"===(c||{marginRight:\"4px\"}).marginRight,t=l.appendChild(re.createElement(\"div\")),t.style.cssText=l.style.cssText=\"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0\",t.style.marginRight=t.style.width=\"0\",l.style.width=\"1px\",a=!parseFloat((e.getComputedStyle(t)||{}).marginRight),l.removeChild(t)),l.style.display=\"none\",o=0===l.getClientRects().length,o&&(l.style.display=\"\",l.innerHTML=\"<table><tr><td></td><td>t</td></tr></table>\",t=l.getElementsByTagName(\"td\"),t[0].style.cssText=\"margin:0;border:0;padding:0;display:none\",o=0===t[0].offsetHeight,o&&(t[0].style.display=\"\",t[1].style.display=\"none\",o=0===t[0].offsetHeight)),f.removeChild(u)}var n,r,i,o,a,s,u=re.createElement(\"div\"),l=re.createElement(\"div\");l.style&&(l.style.cssText=\"float:left;opacity:.5\",fe.opacity=\"0.5\"===l.style.opacity,fe.cssFloat=!!l.style.cssFloat,l.style.backgroundClip=\"content-box\",l.cloneNode(!0).style.backgroundClip=\"\",fe.clearCloneStyle=\"content-box\"===l.style.backgroundClip,u=re.createElement(\"div\"),u.style.cssText=\"border:0;width:8px;height:0;top:0;left:-9999px;padding:0;margin-top:1px;position:absolute\",l.innerHTML=\"\",u.appendChild(l),fe.boxSizing=\"\"===l.style.boxSizing||\"\"===l.style.MozBoxSizing||\"\"===l.style.WebkitBoxSizing,pe.extend(fe,{reliableHiddenOffsets:function(){return null==n&&t(),o},boxSizingReliable:function(){return null==n&&t(),i},pixelMarginRight:function(){return null==n&&t(),r},pixelPosition:function(){return null==n&&t(),n},reliableMarginRight:function(){return null==n&&t(),a},reliableMarginLeft:function(){return null==n&&t(),s}}))}();var ht,gt,mt=/^(top|right|bottom|left)$/;e.getComputedStyle?(ht=function(t){var n=t.ownerDocument.defaultView;return n&&n.opener||(n=e),n.getComputedStyle(t)},gt=function(e,t,n){var r,i,o,a,s=e.style;return n=n||ht(e),a=n?n.getPropertyValue(t)||n[t]:void 0,\"\"!==a&&void 0!==a||pe.contains(e.ownerDocument,e)||(a=pe.style(e,t)),n&&!fe.pixelMarginRight()&&ft.test(a)&&ct.test(t)&&(r=s.width,i=s.minWidth,o=s.maxWidth,s.minWidth=s.maxWidth=s.width=a,a=n.width,s.width=r,s.minWidth=i,s.maxWidth=o),void 0===a?a:a+\"\"}):pt.currentStyle&&(ht=function(e){return e.currentStyle},gt=function(e,t,n){var r,i,o,a,s=e.style;return n=n||ht(e),a=n?n[t]:void 0,null==a&&s&&s[t]&&(a=s[t]),ft.test(a)&&!mt.test(t)&&(r=s.left,i=e.runtimeStyle,o=i&&i.left,o&&(i.left=e.currentStyle.left),s.left=\"fontSize\"===t?\"1em\":a,a=s.pixelLeft+\"px\",s.left=r,o&&(i.left=o)),void 0===a?a:a+\"\"||\"auto\"});var yt=/alpha\\([^)]*\\)/i,vt=/opacity\\s*=\\s*([^)]*)/i,xt=/^(none|table(?!-c[ea]).+)/,bt=new RegExp(\"^(\"+Fe+\")(.*)$\",\"i\"),wt={position:\"absolute\",visibility:\"hidden\",display:\"block\"},Tt={letterSpacing:\"0\",fontWeight:\"400\"},Ct=[\"Webkit\",\"O\",\"Moz\",\"ms\"],Et=re.createElement(\"div\").style;pe.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=gt(e,\"opacity\");return\"\"===n?\"1\":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{\"float\":fe.cssFloat?\"cssFloat\":\"styleFloat\"},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=pe.camelCase(t),u=e.style;if(t=pe.cssProps[s]||(pe.cssProps[s]=H(s)||s),a=pe.cssHooks[t]||pe.cssHooks[s],void 0===n)return a&&\"get\"in a&&void 0!==(i=a.get(e,!1,r))?i:u[t];if(o=typeof n,\"string\"===o&&(i=Me.exec(n))&&i[1]&&(n=d(e,t,i),o=\"number\"),null!=n&&n===n&&(\"number\"===o&&(n+=i&&i[3]||(pe.cssNumber[s]?\"\":\"px\")),fe.clearCloneStyle||\"\"!==n||0!==t.indexOf(\"background\")||(u[t]=\"inherit\"),!(a&&\"set\"in a&&void 0===(n=a.set(e,n,r)))))try{u[t]=n}catch(l){}}},css:function(e,t,n,r){var i,o,a,s=pe.camelCase(t);return t=pe.cssProps[s]||(pe.cssProps[s]=H(s)||s),a=pe.cssHooks[t]||pe.cssHooks[s],a&&\"get\"in a&&(o=a.get(e,!0,n)),void 0===o&&(o=gt(e,t,r)),\"normal\"===o&&t in Tt&&(o=Tt[t]),\"\"===n||n?(i=parseFloat(o),n===!0||isFinite(i)?i||0:o):o}}),pe.each([\"height\",\"width\"],function(e,t){pe.cssHooks[t]={get:function(e,n,r){if(n)return xt.test(pe.css(e,\"display\"))&&0===e.offsetWidth?dt(e,wt,function(){return M(e,t,r)}):M(e,t,r)},set:function(e,n,r){var i=r&&ht(e);return _(e,n,r?F(e,t,r,fe.boxSizing&&\"border-box\"===pe.css(e,\"boxSizing\",!1,i),i):0)}}}),fe.opacity||(pe.cssHooks.opacity={get:function(e,t){return vt.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=pe.isNumeric(t)?\"alpha(opacity=\"+100*t+\")\":\"\",o=r&&r.filter||n.filter||\"\";n.zoom=1,(t>=1||\"\"===t)&&\"\"===pe.trim(o.replace(yt,\"\"))&&n.removeAttribute&&(n.removeAttribute(\"filter\"),\"\"===t||r&&!r.filter)||(n.filter=yt.test(o)?o.replace(yt,i):o+\" \"+i)}}),pe.cssHooks.marginRight=L(fe.reliableMarginRight,function(e,t){if(t)return dt(e,{display:\"inline-block\"},gt,[e,\"marginRight\"])}),pe.cssHooks.marginLeft=L(fe.reliableMarginLeft,function(e,t){if(t)return(parseFloat(gt(e,\"marginLeft\"))||(pe.contains(e.ownerDocument,e)?e.getBoundingClientRect().left-dt(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}):0))+\"px\"}),pe.each({margin:\"\",padding:\"\",border:\"Width\"},function(e,t){pe.cssHooks[e+t]={expand:function(n){for(var r=0,i={},o=\"string\"==typeof n?n.split(\" \"):[n];r<4;r++)i[e+Oe[r]+t]=o[r]||o[r-2]||o[0];return i}},ct.test(e)||(pe.cssHooks[e+t].set=_)}),pe.fn.extend({css:function(e,t){return Pe(this,function(e,t,n){var r,i,o={},a=0;if(pe.isArray(t)){for(r=ht(e),i=t.length;a<i;a++)o[t[a]]=pe.css(e,t[a],!1,r);return o}return void 0!==n?pe.style(e,t,n):pe.css(e,t)},e,t,arguments.length>1)},show:function(){return q(this,!0)},hide:function(){return q(this)},toggle:function(e){return\"boolean\"==typeof e?e?this.show():this.hide():this.each(function(){Re(this)?pe(this).show():pe(this).hide()})}}),pe.Tween=O,O.prototype={constructor:O,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||pe.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(pe.cssNumber[n]?\"\":\"px\")},cur:function(){var e=O.propHooks[this.prop];return e&&e.get?e.get(this):O.propHooks._default.get(this)},run:function(e){var t,n=O.propHooks[this.prop];return this.options.duration?this.pos=t=pe.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=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):O.propHooks._default.set(this),this}},O.prototype.init.prototype=O.prototype,O.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=pe.css(e.elem,e.prop,\"\"),t&&\"auto\"!==t?t:0)},set:function(e){pe.fx.step[e.prop]?pe.fx.step[e.prop](e):1!==e.elem.nodeType||null==e.elem.style[pe.cssProps[e.prop]]&&!pe.cssHooks[e.prop]?e.elem[e.prop]=e.now:pe.style(e.elem,e.prop,e.now+e.unit)}}},O.propHooks.scrollTop=O.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},pe.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:\"swing\"},pe.fx=O.prototype.init,pe.fx.step={};var Nt,kt,St=/^(?:toggle|show|hide)$/,At=/queueHooks$/;pe.Animation=pe.extend($,{tweeners:{\"*\":[function(e,t){var n=this.createTween(e,t);return d(n.elem,e,Me.exec(t),n),n}]},tweener:function(e,t){pe.isFunction(e)?(t=e,e=[\"*\"]):e=e.match(De);for(var n,r=0,i=e.length;r<i;r++)n=e[r],$.tweeners[n]=$.tweeners[n]||[],$.tweeners[n].unshift(t)},prefilters:[W],prefilter:function(e,t){t?$.prefilters.unshift(e):$.prefilters.push(e)}}),pe.speed=function(e,t,n){var r=e&&\"object\"==typeof e?pe.extend({},e):{complete:n||!n&&t||pe.isFunction(e)&&e,duration:e,easing:n&&t||t&&!pe.isFunction(t)&&t};return r.duration=pe.fx.off?0:\"number\"==typeof r.duration?r.duration:r.duration in pe.fx.speeds?pe.fx.speeds[r.duration]:pe.fx.speeds._default,null!=r.queue&&r.queue!==!0||(r.queue=\"fx\"),r.old=r.complete,r.complete=function(){pe.isFunction(r.old)&&r.old.call(this),r.queue&&pe.dequeue(this,r.queue)},r},pe.fn.extend({fadeTo:function(e,t,n,r){return this.filter(Re).css(\"opacity\",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=pe.isEmptyObject(e),o=pe.speed(t,n,r),a=function(){var t=$(this,pe.extend({},e),o);(i||pe._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,t,n){var r=function(e){var t=e.stop;delete e.stop,t(n)};return\"string\"!=typeof e&&(n=t,t=e,e=void 0),t&&e!==!1&&this.queue(e||\"fx\",[]),this.each(function(){var t=!0,i=null!=e&&e+\"queueHooks\",o=pe.timers,a=pe._data(this);if(i)a[i]&&a[i].stop&&r(a[i]);else for(i in a)a[i]&&a[i].stop&&At.test(i)&&r(a[i]);for(i=o.length;i--;)o[i].elem!==this||null!=e&&o[i].queue!==e||(o[i].anim.stop(n),t=!1,o.splice(i,1));!t&&n||pe.dequeue(this,e)})},finish:function(e){return e!==!1&&(e=e||\"fx\"),this.each(function(){var t,n=pe._data(this),r=n[e+\"queue\"],i=n[e+\"queueHooks\"],o=pe.timers,a=r?r.length:0;for(n.finish=!0,pe.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;t<a;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}}),pe.each([\"toggle\",\"show\",\"hide\"],function(e,t){var n=pe.fn[t];pe.fn[t]=function(e,r,i){return null==e||\"boolean\"==typeof e?n.apply(this,arguments):this.animate(P(t,!0),e,r,i)}}),pe.each({slideDown:P(\"show\"),slideUp:P(\"hide\"),slideToggle:P(\"toggle\"),fadeIn:{opacity:\"show\"},fadeOut:{opacity:\"hide\"},fadeToggle:{opacity:\"toggle\"}},function(e,t){pe.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),pe.timers=[],pe.fx.tick=function(){var e,t=pe.timers,n=0;for(Nt=pe.now();n<t.length;n++)e=t[n],e()||t[n]!==e||t.splice(n--,1);t.length||pe.fx.stop(),Nt=void 0},pe.fx.timer=function(e){pe.timers.push(e),e()?pe.fx.start():pe.timers.pop()},pe.fx.interval=13,pe.fx.start=function(){kt||(kt=e.setInterval(pe.fx.tick,pe.fx.interval))},pe.fx.stop=function(){e.clearInterval(kt),kt=null},pe.fx.speeds={slow:600,fast:200,_default:400},pe.fn.delay=function(t,n){return t=pe.fx?pe.fx.speeds[t]||t:t,n=n||\"fx\",this.queue(n,function(n,r){var i=e.setTimeout(n,t);r.stop=function(){e.clearTimeout(i)}})},function(){var e,t=re.createElement(\"input\"),n=re.createElement(\"div\"),r=re.createElement(\"select\"),i=r.appendChild(re.createElement(\"option\"));n=re.createElement(\"div\"),n.setAttribute(\"className\",\"t\"),n.innerHTML=\"  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>\",e=n.getElementsByTagName(\"a\")[0],t.setAttribute(\"type\",\"checkbox\"),n.appendChild(t),e=n.getElementsByTagName(\"a\")[0],e.style.cssText=\"top:1px\",fe.getSetAttribute=\"t\"!==n.className,fe.style=/top/.test(e.getAttribute(\"style\")),fe.hrefNormalized=\"/a\"===e.getAttribute(\"href\"),fe.checkOn=!!t.value,fe.optSelected=i.selected,fe.enctype=!!re.createElement(\"form\").enctype,r.disabled=!0,fe.optDisabled=!i.disabled,t=re.createElement(\"input\"),t.setAttribute(\"value\",\"\"),fe.input=\"\"===t.getAttribute(\"value\"),t.value=\"t\",t.setAttribute(\"type\",\"radio\"),fe.radioValue=\"t\"===t.value}();var Dt=/\\r/g,jt=/[\\x20\\t\\r\\n\\f]+/g;pe.fn.extend({val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=pe.isFunction(e),this.each(function(n){var i;1===this.nodeType&&(i=r?e.call(this,n,pe(this).val()):e,null==i?i=\"\":\"number\"==typeof i?i+=\"\":pe.isArray(i)&&(i=pe.map(i,function(e){return null==e?\"\":e+\"\"})),t=pe.valHooks[this.type]||pe.valHooks[this.nodeName.toLowerCase()],t&&\"set\"in t&&void 0!==t.set(this,i,\"value\")||(this.value=i))});if(i)return t=pe.valHooks[i.type]||pe.valHooks[i.nodeName.toLowerCase()],t&&\"get\"in t&&void 0!==(n=t.get(i,\"value\"))?n:(n=i.value,\"string\"==typeof n?n.replace(Dt,\"\"):null==n?\"\":n)}}}),pe.extend({valHooks:{option:{get:function(e){var t=pe.find.attr(e,\"value\");return null!=t?t:pe.trim(pe.text(e)).replace(jt,\" \")}},select:{get:function(e){for(var t,n,r=e.options,i=e.selectedIndex,o=\"select-one\"===e.type||i<0,a=o?null:[],s=o?i+1:r.length,u=i<0?s:o?i:0;u<s;u++)if(n=r[u],(n.selected||u===i)&&(fe.optDisabled?!n.disabled:null===n.getAttribute(\"disabled\"))&&(!n.parentNode.disabled||!pe.nodeName(n.parentNode,\"optgroup\"))){if(t=pe(n).val(),o)return t;a.push(t)}return a},set:function(e,t){for(var n,r,i=e.options,o=pe.makeArray(t),a=i.length;a--;)if(r=i[a],pe.inArray(pe.valHooks.option.get(r),o)>-1)try{r.selected=n=!0}catch(s){r.scrollHeight}else r.selected=!1;return n||(e.selectedIndex=-1),i}}}}),pe.each([\"radio\",\"checkbox\"],function(){pe.valHooks[this]={set:function(e,t){if(pe.isArray(t))return e.checked=pe.inArray(pe(e).val(),t)>-1}},fe.checkOn||(pe.valHooks[this].get=function(e){return null===e.getAttribute(\"value\")?\"on\":e.value})});var Lt,Ht,qt=pe.expr.attrHandle,_t=/^(?:checked|selected)$/i,Ft=fe.getSetAttribute,Mt=fe.input;pe.fn.extend({attr:function(e,t){return Pe(this,pe.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){pe.removeAttr(this,e)})}}),pe.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return\"undefined\"==typeof e.getAttribute?pe.prop(e,t,n):(1===o&&pe.isXMLDoc(e)||(t=t.toLowerCase(),i=pe.attrHooks[t]||(pe.expr.match.bool.test(t)?Ht:Lt)),void 0!==n?null===n?void pe.removeAttr(e,t):i&&\"set\"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+\"\"),n):i&&\"get\"in i&&null!==(r=i.get(e,t))?r:(r=pe.find.attr(e,t),null==r?void 0:r))},attrHooks:{type:{set:function(e,t){if(!fe.radioValue&&\"radio\"===t&&pe.nodeName(e,\"input\")){var n=e.value;return e.setAttribute(\"type\",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(De);if(o&&1===e.nodeType)for(;n=o[i++];)r=pe.propFix[n]||n,pe.expr.match.bool.test(n)?Mt&&Ft||!_t.test(n)?e[r]=!1:e[pe.camelCase(\"default-\"+n)]=e[r]=!1:pe.attr(e,n,\"\"),e.removeAttribute(Ft?n:r)}}),Ht={set:function(e,t,n){return t===!1?pe.removeAttr(e,n):Mt&&Ft||!_t.test(n)?e.setAttribute(!Ft&&pe.propFix[n]||n,n):e[pe.camelCase(\"default-\"+n)]=e[n]=!0,n}},pe.each(pe.expr.match.bool.source.match(/\\w+/g),function(e,t){var n=qt[t]||pe.find.attr;Mt&&Ft||!_t.test(t)?qt[t]=function(e,t,r){var i,o;return r||(o=qt[t],qt[t]=i,i=null!=n(e,t,r)?t.toLowerCase():null,qt[t]=o),i}:qt[t]=function(e,t,n){if(!n)return e[pe.camelCase(\"default-\"+t)]?t.toLowerCase():null}}),Mt&&Ft||(pe.attrHooks.value={set:function(e,t,n){return pe.nodeName(e,\"input\")?void(e.defaultValue=t):Lt&&Lt.set(e,t,n)}}),Ft||(Lt={set:function(e,t,n){var r=e.getAttributeNode(n);if(r||e.setAttributeNode(r=e.ownerDocument.createAttribute(n)),r.value=t+=\"\",\"value\"===n||t===e.getAttribute(n))return t}},qt.id=qt.name=qt.coords=function(e,t,n){var r;if(!n)return(r=e.getAttributeNode(t))&&\"\"!==r.value?r.value:null},pe.valHooks.button={get:function(e,t){var n=e.getAttributeNode(t);if(n&&n.specified)return n.value},set:Lt.set},pe.attrHooks.contenteditable={set:function(e,t,n){Lt.set(e,\"\"!==t&&t,n)}},pe.each([\"width\",\"height\"],function(e,t){pe.attrHooks[t]={set:function(e,n){if(\"\"===n)return e.setAttribute(t,\"auto\"),n}}})),fe.style||(pe.attrHooks.style={get:function(e){return e.style.cssText||void 0},set:function(e,t){return e.style.cssText=t+\"\"}});var Ot=/^(?:input|select|textarea|button|object)$/i,Rt=/^(?:a|area)$/i;pe.fn.extend({prop:function(e,t){return Pe(this,pe.prop,e,t,arguments.length>1)},removeProp:function(e){return e=pe.propFix[e]||e,this.each(function(){try{this[e]=void 0,delete this[e]}catch(t){}})}}),pe.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&pe.isXMLDoc(e)||(t=pe.propFix[t]||t,i=pe.propHooks[t]),void 0!==n?i&&\"set\"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&\"get\"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=pe.find.attr(e,\"tabindex\");return t?parseInt(t,10):Ot.test(e.nodeName)||Rt.test(e.nodeName)&&e.href?0:-1}}},propFix:{\"for\":\"htmlFor\",\"class\":\"className\"}}),fe.hrefNormalized||pe.each([\"href\",\"src\"],function(e,t){pe.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}}),fe.optSelected||(pe.propHooks.selected={get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),pe.each([\"tabIndex\",\"readOnly\",\"maxLength\",\"cellSpacing\",\"cellPadding\",\"rowSpan\",\"colSpan\",\"useMap\",\"frameBorder\",\"contentEditable\"],function(){pe.propFix[this.toLowerCase()]=this}),fe.enctype||(pe.propFix.enctype=\"encoding\");var Pt=/[\\t\\r\\n\\f]/g;pe.fn.extend({addClass:function(e){var t,n,r,i,o,a,s,u=0;if(pe.isFunction(e))return this.each(function(t){pe(this).addClass(e.call(this,t,z(this)))});if(\"string\"==typeof e&&e)for(t=e.match(De)||[];n=this[u++];)if(i=z(n),r=1===n.nodeType&&(\" \"+i+\" \").replace(Pt,\" \")){for(a=0;o=t[a++];)r.indexOf(\" \"+o+\" \")<0&&(r+=o+\" \");s=pe.trim(r),i!==s&&pe.attr(n,\"class\",s)}return this},removeClass:function(e){var t,n,r,i,o,a,s,u=0;if(pe.isFunction(e))return this.each(function(t){pe(this).removeClass(e.call(this,t,z(this)))});if(!arguments.length)return this.attr(\"class\",\"\");if(\"string\"==typeof e&&e)for(t=e.match(De)||[];n=this[u++];)if(i=z(n),r=1===n.nodeType&&(\" \"+i+\" \").replace(Pt,\" \")){for(a=0;o=t[a++];)for(;r.indexOf(\" \"+o+\" \")>-1;)r=r.replace(\" \"+o+\" \",\" \");s=pe.trim(r),i!==s&&pe.attr(n,\"class\",s)}return this},toggleClass:function(e,t){var n=typeof e;return\"boolean\"==typeof t&&\"string\"===n?t?this.addClass(e):this.removeClass(e):pe.isFunction(e)?this.each(function(n){pe(this).toggleClass(e.call(this,n,z(this),t),t)}):this.each(function(){var t,r,i,o;if(\"string\"===n)for(r=0,i=pe(this),o=e.match(De)||[];t=o[r++];)i.hasClass(t)?i.removeClass(t):i.addClass(t);else void 0!==e&&\"boolean\"!==n||(t=z(this),t&&pe._data(this,\"__className__\",t),pe.attr(this,\"class\",t||e===!1?\"\":pe._data(this,\"__className__\")||\"\"))})},hasClass:function(e){var t,n,r=0;for(t=\" \"+e+\" \";n=this[r++];)if(1===n.nodeType&&(\" \"+z(n)+\" \").replace(Pt,\" \").indexOf(t)>-1)return!0;return!1}}),pe.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){pe.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),pe.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}});var Bt=e.location,Wt=pe.now(),It=/\\?/,$t=/(,)|(\\[|{)|(}|])|\"(?:[^\"\\\\\\r\\n]|\\\\[\"\\\\\\/bfnrt]|\\\\u[\\da-fA-F]{4})*\"\\s*:?|true|false|null|-?(?!0\\d)\\d+(?:\\.\\d+|)(?:[eE][+-]?\\d+|)/g;pe.parseJSON=function(t){if(e.JSON&&e.JSON.parse)return e.JSON.parse(t+\"\");var n,r=null,i=pe.trim(t+\"\");return i&&!pe.trim(i.replace($t,function(e,t,i,o){return n&&t&&(r=0),0===r?e:(n=i||t,r+=!o-!i,\"\")}))?Function(\"return \"+i)():pe.error(\"Invalid JSON: \"+t)},pe.parseXML=function(t){var n,r;if(!t||\"string\"!=typeof t)return null;try{e.DOMParser?(r=new e.DOMParser,n=r.parseFromString(t,\"text/xml\")):(n=new e.ActiveXObject(\"Microsoft.XMLDOM\"),n.async=\"false\",n.loadXML(t))}catch(i){n=void 0}return n&&n.documentElement&&!n.getElementsByTagName(\"parsererror\").length||pe.error(\"Invalid XML: \"+t),n};var zt=/#.*$/,Xt=/([?&])_=[^&]*/,Ut=/^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/gm,Vt=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Yt=/^(?:GET|HEAD)$/,Jt=/^\\/\\//,Gt=/^([\\w.+-]+:)(?:\\/\\/(?:[^\\/?#]*@|)([^\\/?#:]*)(?::(\\d+)|)|)/,Kt={},Qt={},Zt=\"*/\".concat(\"*\"),en=Bt.href,tn=Gt.exec(en.toLowerCase())||[];pe.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:en,type:\"GET\",isLocal:Vt.test(tn[1]),global:!0,processData:!0,async:!0,contentType:\"application/x-www-form-urlencoded; charset=UTF-8\",accepts:{\"*\":Zt,text:\"text/plain\",html:\"text/html\",xml:\"application/xml, text/xml\",json:\"application/json, text/javascript\"},contents:{xml:/\\bxml\\b/,html:/\\bhtml/,json:/\\bjson\\b/},responseFields:{xml:\"responseXML\",text:\"responseText\",json:\"responseJSON\"},converters:{\"* text\":String,\"text html\":!0,\"text json\":pe.parseJSON,\"text xml\":pe.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?V(V(e,pe.ajaxSettings),t):V(pe.ajaxSettings,e)},ajaxPrefilter:X(Kt),ajaxTransport:X(Qt),ajax:function(t,n){function r(t,n,r,i){var o,f,v,x,w,C=n;2!==b&&(b=2,u&&e.clearTimeout(u),c=void 0,s=i||\"\",T.readyState=t>0?4:0,o=t>=200&&t<300||304===t,r&&(x=Y(d,T,r)),x=J(d,x,T,o),o?(d.ifModified&&(w=T.getResponseHeader(\"Last-Modified\"),w&&(pe.lastModified[a]=w),w=T.getResponseHeader(\"etag\"),w&&(pe.etag[a]=w)),204===t||\"HEAD\"===d.type?C=\"nocontent\":304===t?C=\"notmodified\":(C=x.state,f=x.data,v=x.error,o=!v)):(v=C,!t&&C||(C=\"error\",t<0&&(t=0))),T.status=t,T.statusText=(n||C)+\"\",o?g.resolveWith(p,[f,C,T]):g.rejectWith(p,[T,C,v]),T.statusCode(y),y=void 0,l&&h.trigger(o?\"ajaxSuccess\":\"ajaxError\",[T,d,o?f:v]),m.fireWith(p,[T,C]),l&&(h.trigger(\"ajaxComplete\",[T,d]),--pe.active||pe.event.trigger(\"ajaxStop\")))}\"object\"==typeof t&&(n=t,t=void 0),n=n||{};var i,o,a,s,u,l,c,f,d=pe.ajaxSetup({},n),p=d.context||d,h=d.context&&(p.nodeType||p.jquery)?pe(p):pe.event,g=pe.Deferred(),m=pe.Callbacks(\"once memory\"),y=d.statusCode||{},v={},x={},b=0,w=\"canceled\",T={readyState:0,getResponseHeader:function(e){var t;if(2===b){if(!f)for(f={};t=Ut.exec(s);)f[t[1].toLowerCase()]=t[2];t=f[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===b?s:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return b||(e=x[n]=x[n]||e,v[e]=t),this},overrideMimeType:function(e){return b||(d.mimeType=e),this},statusCode:function(e){var t;if(e)if(b<2)for(t in e)y[t]=[y[t],e[t]];else T.always(e[T.status]);return this},abort:function(e){var t=e||w;return c&&c.abort(t),r(0,t),this}};if(g.promise(T).complete=m.add,T.success=T.done,T.error=T.fail,d.url=((t||d.url||en)+\"\").replace(zt,\"\").replace(Jt,tn[1]+\"//\"),d.type=n.method||n.type||d.method||d.type,d.dataTypes=pe.trim(d.dataType||\"*\").toLowerCase().match(De)||[\"\"],null==d.crossDomain&&(i=Gt.exec(d.url.toLowerCase()),d.crossDomain=!(!i||i[1]===tn[1]&&i[2]===tn[2]&&(i[3]||(\"http:\"===i[1]?\"80\":\"443\"))===(tn[3]||(\"http:\"===tn[1]?\"80\":\"443\")))),d.data&&d.processData&&\"string\"!=typeof d.data&&(d.data=pe.param(d.data,d.traditional)),U(Kt,d,n,T),2===b)return T;l=pe.event&&d.global,l&&0===pe.active++&&pe.event.trigger(\"ajaxStart\"),d.type=d.type.toUpperCase(),d.hasContent=!Yt.test(d.type),a=d.url,d.hasContent||(d.data&&(a=d.url+=(It.test(a)?\"&\":\"?\")+d.data,delete d.data),d.cache===!1&&(d.url=Xt.test(a)?a.replace(Xt,\"$1_=\"+Wt++):a+(It.test(a)?\"&\":\"?\")+\"_=\"+Wt++)),d.ifModified&&(pe.lastModified[a]&&T.setRequestHeader(\"If-Modified-Since\",pe.lastModified[a]),pe.etag[a]&&T.setRequestHeader(\"If-None-Match\",pe.etag[a])),(d.data&&d.hasContent&&d.contentType!==!1||n.contentType)&&T.setRequestHeader(\"Content-Type\",d.contentType),T.setRequestHeader(\"Accept\",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(\"*\"!==d.dataTypes[0]?\", \"+Zt+\"; q=0.01\":\"\"):d.accepts[\"*\"]);for(o in d.headers)T.setRequestHeader(o,d.headers[o]);if(d.beforeSend&&(d.beforeSend.call(p,T,d)===!1||2===b))return T.abort();w=\"abort\";for(o in{success:1,error:1,complete:1})T[o](d[o]);if(c=U(Qt,d,n,T)){if(T.readyState=1,l&&h.trigger(\"ajaxSend\",[T,d]),2===b)return T;d.async&&d.timeout>0&&(u=e.setTimeout(function(){T.abort(\"timeout\")},d.timeout));try{b=1,c.send(v,r)}catch(C){if(!(b<2))throw C;r(-1,C)}}else r(-1,\"No Transport\");return T},getJSON:function(e,t,n){return pe.get(e,t,n,\"json\")},getScript:function(e,t){return pe.get(e,void 0,t,\"script\")}}),pe.each([\"get\",\"post\"],function(e,t){pe[t]=function(e,n,r,i){return pe.isFunction(n)&&(i=i||r,r=n,n=void 0),pe.ajax(pe.extend({url:e,type:t,dataType:i,data:n,success:r},pe.isPlainObject(e)&&e))}}),pe._evalUrl=function(e){return pe.ajax({url:e,type:\"GET\",dataType:\"script\",cache:!0,async:!1,global:!1,\"throws\":!0})},pe.fn.extend({wrapAll:function(e){if(pe.isFunction(e))return this.each(function(t){pe(this).wrapAll(e.call(this,t))});if(this[0]){var t=pe(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){for(var e=this;e.firstChild&&1===e.firstChild.nodeType;)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return pe.isFunction(e)?this.each(function(t){pe(this).wrapInner(e.call(this,t))}):this.each(function(){var t=pe(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=pe.isFunction(e);return this.each(function(n){pe(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){pe.nodeName(this,\"body\")||pe(this).replaceWith(this.childNodes)}).end()}}),pe.expr.filters.hidden=function(e){return fe.reliableHiddenOffsets()?e.offsetWidth<=0&&e.offsetHeight<=0&&!e.getClientRects().length:K(e)},pe.expr.filters.visible=function(e){return!pe.expr.filters.hidden(e)};var nn=/%20/g,rn=/\\[\\]$/,on=/\\r?\\n/g,an=/^(?:submit|button|image|reset|file)$/i,sn=/^(?:input|select|textarea|keygen)/i;pe.param=function(e,t){var n,r=[],i=function(e,t){t=pe.isFunction(t)?t():null==t?\"\":t,r[r.length]=encodeURIComponent(e)+\"=\"+encodeURIComponent(t)};if(void 0===t&&(t=pe.ajaxSettings&&pe.ajaxSettings.traditional),pe.isArray(e)||e.jquery&&!pe.isPlainObject(e))pe.each(e,function(){i(this.name,this.value)});else for(n in e)Q(n,e[n],t,i);return r.join(\"&\").replace(nn,\"+\")},pe.fn.extend({serialize:function(){return pe.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=pe.prop(this,\"elements\");return e?pe.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!pe(this).is(\":disabled\")&&sn.test(this.nodeName)&&!an.test(e)&&(this.checked||!Be.test(e))}).map(function(e,t){var n=pe(this).val();return null==n?null:pe.isArray(n)?pe.map(n,function(e){return{name:t.name,value:e.replace(on,\"\\r\\n\")}}):{name:t.name,value:n.replace(on,\"\\r\\n\")}}).get()}}),pe.ajaxSettings.xhr=void 0!==e.ActiveXObject?function(){return this.isLocal?ee():re.documentMode>8?Z():/^(get|post|head|put|delete|options)$/i.test(this.type)&&Z()||ee()}:Z;var un=0,ln={},cn=pe.ajaxSettings.xhr();e.attachEvent&&e.attachEvent(\"onunload\",function(){for(var e in ln)ln[e](void 0,!0)}),fe.cors=!!cn&&\"withCredentials\"in cn,cn=fe.ajax=!!cn,cn&&pe.ajaxTransport(function(t){if(!t.crossDomain||fe.cors){var n;return{send:function(r,i){var o,a=t.xhr(),s=++un;if(a.open(t.type,t.url,t.async,t.username,t.password),t.xhrFields)for(o in t.xhrFields)a[o]=t.xhrFields[o];t.mimeType&&a.overrideMimeType&&a.overrideMimeType(t.mimeType),t.crossDomain||r[\"X-Requested-With\"]||(r[\"X-Requested-With\"]=\"XMLHttpRequest\");for(o in r)void 0!==r[o]&&a.setRequestHeader(o,r[o]+\"\");a.send(t.hasContent&&t.data||null),n=function(e,r){var o,u,l;if(n&&(r||4===a.readyState))if(delete ln[s],n=void 0,a.onreadystatechange=pe.noop,r)4!==a.readyState&&a.abort();else{l={},o=a.status,\"string\"==typeof a.responseText&&(l.text=a.responseText);try{u=a.statusText}catch(c){u=\"\"}o||!t.isLocal||t.crossDomain?1223===o&&(o=204):o=l.text?200:404}l&&i(o,u,l,a.getAllResponseHeaders())},t.async?4===a.readyState?e.setTimeout(n):a.onreadystatechange=ln[s]=n:n()},abort:function(){n&&n(void 0,!0)}}}}),pe.ajaxSetup({accepts:{script:\"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"},contents:{script:/\\b(?:java|ecma)script\\b/},converters:{\"text script\":function(e){return pe.globalEval(e),e}}}),pe.ajaxPrefilter(\"script\",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type=\"GET\",e.global=!1)}),pe.ajaxTransport(\"script\",function(e){if(e.crossDomain){var t,n=re.head||pe(\"head\")[0]||re.documentElement;return{send:function(r,i){t=re.createElement(\"script\"),t.async=!0,e.scriptCharset&&(t.charset=e.scriptCharset),t.src=e.url,t.onload=t.onreadystatechange=function(e,n){(n||!t.readyState||/loaded|complete/.test(t.readyState))&&(t.onload=t.onreadystatechange=null,t.parentNode&&t.parentNode.removeChild(t),t=null,n||i(200,\"success\"))},n.insertBefore(t,n.firstChild)},abort:function(){t&&t.onload(void 0,!0)}}}});var fn=[],dn=/(=)\\?(?=&|$)|\\?\\?/;pe.ajaxSetup({jsonp:\"callback\",jsonpCallback:function(){var e=fn.pop()||pe.expando+\"_\"+Wt++;return this[e]=!0,e}}),pe.ajaxPrefilter(\"json jsonp\",function(t,n,r){var i,o,a,s=t.jsonp!==!1&&(dn.test(t.url)?\"url\":\"string\"==typeof t.data&&0===(t.contentType||\"\").indexOf(\"application/x-www-form-urlencoded\")&&dn.test(t.data)&&\"data\");if(s||\"jsonp\"===t.dataTypes[0])return i=t.jsonpCallback=pe.isFunction(t.jsonpCallback)?t.jsonpCallback():t.jsonpCallback,s?t[s]=t[s].replace(dn,\"$1\"+i):t.jsonp!==!1&&(t.url+=(It.test(t.url)?\"&\":\"?\")+t.jsonp+\"=\"+i),t.converters[\"script json\"]=function(){return a||pe.error(i+\" was not called\"),a[0]},t.dataTypes[0]=\"json\",o=e[i],e[i]=function(){a=arguments},r.always(function(){void 0===o?pe(e).removeProp(i):e[i]=o,t[i]&&(t.jsonpCallback=n.jsonpCallback,fn.push(i)),a&&pe.isFunction(o)&&o(a[0]),a=o=void 0}),\"script\"}),pe.parseHTML=function(e,t,n){if(!e||\"string\"!=typeof e)return null;\"boolean\"==typeof t&&(n=t,t=!1),t=t||re;var r=Te.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=y([e],t,i),i&&i.length&&pe(i).remove(),pe.merge([],r.childNodes))};var pn=pe.fn.load;return pe.fn.load=function(e,t,n){if(\"string\"!=typeof e&&pn)return pn.apply(this,arguments);var r,i,o,a=this,s=e.indexOf(\" \");return s>-1&&(r=pe.trim(e.slice(s,e.length)),e=e.slice(0,s)),pe.isFunction(t)?(n=t,t=void 0):t&&\"object\"==typeof t&&(i=\"POST\"),a.length>0&&pe.ajax({url:e,type:i||\"GET\",dataType:\"html\",data:t}).done(function(e){o=arguments,a.html(r?pe(\"<div>\").append(pe.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},pe.each([\"ajaxStart\",\"ajaxStop\",\"ajaxComplete\",\"ajaxError\",\"ajaxSuccess\",\"ajaxSend\"],function(e,t){pe.fn[t]=function(e){return this.on(t,e)}}),pe.expr.filters.animated=function(e){return pe.grep(pe.timers,function(t){return e===t.elem}).length},pe.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l,c=pe.css(e,\"position\"),f=pe(e),d={};\"static\"===c&&(e.style.position=\"relative\"),s=f.offset(),o=pe.css(e,\"top\"),u=pe.css(e,\"left\"),l=(\"absolute\"===c||\"fixed\"===c)&&pe.inArray(\"auto\",[o,u])>-1,l?(r=f.position(),a=r.top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),pe.isFunction(t)&&(t=t.call(e,n,pe.extend({},s))),null!=t.top&&(d.top=t.top-s.top+a),null!=t.left&&(d.left=t.left-s.left+i),\"using\"in t?t.using.call(e,d):f.css(d)}},pe.fn.extend({offset:function(e){if(arguments.length)return void 0===e?this:this.each(function(t){pe.offset.setOffset(this,e,t)});var t,n,r={top:0,left:0},i=this[0],o=i&&i.ownerDocument;if(o)return t=o.documentElement,pe.contains(t,i)?(\"undefined\"!=typeof i.getBoundingClientRect&&(r=i.getBoundingClientRect()),n=te(o),{top:r.top+(n.pageYOffset||t.scrollTop)-(t.clientTop||0),left:r.left+(n.pageXOffset||t.scrollLeft)-(t.clientLeft||0)}):r},position:function(){if(this[0]){var e,t,n={top:0,left:0},r=this[0];return\"fixed\"===pe.css(r,\"position\")?t=r.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),pe.nodeName(e[0],\"html\")||(n=e.offset()),n.top+=pe.css(e[0],\"borderTopWidth\",!0),n.left+=pe.css(e[0],\"borderLeftWidth\",!0)),{top:t.top-n.top-pe.css(r,\"marginTop\",!0),left:t.left-n.left-pe.css(r,\"marginLeft\",!0)}}},offsetParent:function(){return this.map(function(){\nfor(var e=this.offsetParent;e&&!pe.nodeName(e,\"html\")&&\"static\"===pe.css(e,\"position\");)e=e.offsetParent;return e||pt})}}),pe.each({scrollLeft:\"pageXOffset\",scrollTop:\"pageYOffset\"},function(e,t){var n=/Y/.test(t);pe.fn[e]=function(r){return Pe(this,function(e,r,i){var o=te(e);return void 0===i?o?t in o?o[t]:o.document.documentElement[r]:e[r]:void(o?o.scrollTo(n?pe(o).scrollLeft():i,n?i:pe(o).scrollTop()):e[r]=i)},e,r,arguments.length,null)}}),pe.each([\"top\",\"left\"],function(e,t){pe.cssHooks[t]=L(fe.pixelPosition,function(e,n){if(n)return n=gt(e,t),ft.test(n)?pe(e).position()[t]+\"px\":n})}),pe.each({Height:\"height\",Width:\"width\"},function(e,t){pe.each({padding:\"inner\"+e,content:t,\"\":\"outer\"+e},function(n,r){pe.fn[r]=function(r,i){var o=arguments.length&&(n||\"boolean\"!=typeof r),a=n||(r===!0||i===!0?\"margin\":\"border\");return Pe(this,function(t,n,r){var i;return pe.isWindow(t)?t.document.documentElement[\"client\"+e]:9===t.nodeType?(i=t.documentElement,Math.max(t.body[\"scroll\"+e],i[\"scroll\"+e],t.body[\"offset\"+e],i[\"offset\"+e],i[\"client\"+e])):void 0===r?pe.css(t,n,a):pe.style(t,n,r,a)},t,o?r:void 0,o,null)}})}),pe.fn.extend({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)}}),pe.fn.size=function(){return this.length},pe.fn.andSelf=pe.fn.addBack,layui.define(function(e){e(\"jquery\",pe)}),pe});!function(e,t){\"use strict\";var i,n,a=e.layui&&layui.define,o={getPath:function(){var e=document.scripts,t=e[e.length-1],i=t.src;if(!t.getAttribute(\"merge\"))return i.substring(0,i.lastIndexOf(\"/\")+1)}(),config:{},end:{},minIndex:0,minLeft:[],btn:[\"&#x786E;&#x5B9A;\",\"&#x53D6;&#x6D88;\"],type:[\"dialog\",\"page\",\"iframe\",\"loading\",\"tips\"]},r={v:\"3.0.1\",ie:function(){var t=navigator.userAgent.toLowerCase();return!!(e.ActiveXObject||\"ActiveXObject\"in e)&&((t.match(/msie\\s(\\d+)/)||[])[1]||\"11\")}(),index:e.layer&&e.layer.v?1e5:0,path:o.getPath,config:function(e,t){return e=e||{},r.cache=o.config=i.extend({},o.config,e),r.path=o.config.path||r.path,\"string\"==typeof e.extend&&(e.extend=[e.extend]),o.config.path&&r.ready(),e.extend?(a?layui.addcss(\"modules/layer/\"+e.extend):r.link(\"skin/\"+e.extend),this):this},link:function(t,n,a){if(r.path){var o=i(\"head\")[0],l=document.createElement(\"link\");\"string\"==typeof n&&(a=n);var s=(a||t).replace(/\\.|\\//g,\"\"),f=\"layuicss-\"+s,c=0;l.rel=\"stylesheet\",l.href=r.path+t,l.id=f,i(\"#\"+f)[0]||o.appendChild(l),\"function\"==typeof n&&!function d(){return++c>80?e.console&&console.error(\"layer.css: Invalid\"):void(1989===parseInt(i(\"#\"+f).css(\"width\"))?n():setTimeout(d,100))}()}},ready:function(e){var t=\"skinlayercss\",i=\"1110\";return a?layui.addcss(\"modules/layer/default/layer.css?v=\"+r.v+i,e,t):r.link(\"skin/default/layer.css?v=\"+r.v+i,e,t),this},alert:function(e,t,n){var a=\"function\"==typeof t;return a&&(n=t),r.open(i.extend({content:e,yes:n},a?{}:t))},confirm:function(e,t,n,a){var l=\"function\"==typeof t;return l&&(a=n,n=t),r.open(i.extend({content:e,btn:o.btn,yes:n,btn2:a},l?{}:t))},msg:function(e,n,a){var l=\"function\"==typeof n,f=o.config.skin,c=(f?f+\" \"+f+\"-msg\":\"\")||\"layui-layer-msg\",d=s.anim.length-1;return l&&(a=n),r.open(i.extend({content:e,time:3e3,shade:!1,skin:c,title:!1,closeBtn:!1,btn:!1,resize:!1,end:a},l&&!o.config.skin?{skin:c+\" layui-layer-hui\",anim:d}:function(){return n=n||{},(n.icon===-1||n.icon===t&&!o.config.skin)&&(n.skin=c+\" \"+(n.skin||\"layui-layer-hui\")),n}()))},load:function(e,t){return r.open(i.extend({type:3,icon:e||0,resize:!1,shade:.01},t))},tips:function(e,t,n){return r.open(i.extend({type:4,content:[e,t],closeBtn:!1,time:3e3,shade:!1,resize:!1,fixed:!1,maxWidth:210},n))}},l=function(e){var t=this;t.index=++r.index,t.config=i.extend({},t.config,o.config,e),document.body?t.creat():setTimeout(function(){t.creat()},50)};l.pt=l.prototype;var s=[\"layui-layer\",\".layui-layer-title\",\".layui-layer-main\",\".layui-layer-dialog\",\"layui-layer-iframe\",\"layui-layer-content\",\"layui-layer-btn\",\"layui-layer-close\"];s.anim=[\"layer-anim\",\"layer-anim-01\",\"layer-anim-02\",\"layer-anim-03\",\"layer-anim-04\",\"layer-anim-05\",\"layer-anim-06\"],l.pt.config={type:0,shade:.3,fixed:!0,move:s[1],title:\"&#x4FE1;&#x606F;\",offset:\"auto\",area:\"auto\",closeBtn:1,time:0,zIndex:19891014,maxWidth:360,anim:0,icon:-1,moveType:1,resize:!0,scrollbar:!0,tips:2},l.pt.vessel=function(e,t){var n=this,a=n.index,r=n.config,l=r.zIndex+a,f=\"object\"==typeof r.title,c=r.maxmin&&(1===r.type||2===r.type),d=r.title?'<div class=\"layui-layer-title\" style=\"'+(f?r.title[1]:\"\")+'\">'+(f?r.title[0]:r.title)+\"</div>\":\"\";return r.zIndex=l,t([r.shade?'<div class=\"layui-layer-shade\" id=\"layui-layer-shade'+a+'\" times=\"'+a+'\" style=\"'+(\"z-index:\"+(l-1)+\"; background-color:\"+(r.shade[1]||\"#000\")+\"; opacity:\"+(r.shade[0]||r.shade)+\"; filter:alpha(opacity=\"+(100*r.shade[0]||100*r.shade)+\");\")+'\"></div>':\"\",'<div class=\"'+s[0]+(\" layui-layer-\"+o.type[r.type])+(0!=r.type&&2!=r.type||r.shade?\"\":\" layui-layer-border\")+\" \"+(r.skin||\"\")+'\" id=\"'+s[0]+a+'\" type=\"'+o.type[r.type]+'\" times=\"'+a+'\" showtime=\"'+r.time+'\" conType=\"'+(e?\"object\":\"string\")+'\" style=\"z-index: '+l+\"; width:\"+r.area[0]+\";height:\"+r.area[1]+(r.fixed?\"\":\";position:absolute;\")+'\">'+(e&&2!=r.type?\"\":d)+'<div id=\"'+(r.id||\"\")+'\" class=\"layui-layer-content'+(0==r.type&&r.icon!==-1?\" layui-layer-padding\":\"\")+(3==r.type?\" layui-layer-loading\"+r.icon:\"\")+'\">'+(0==r.type&&r.icon!==-1?'<i class=\"layui-layer-ico layui-layer-ico'+r.icon+'\"></i>':\"\")+(1==r.type&&e?\"\":r.content||\"\")+'</div><span class=\"layui-layer-setwin\">'+function(){var e=c?'<a class=\"layui-layer-min\" href=\"javascript:;\"><cite></cite></a><a class=\"layui-layer-ico layui-layer-max\" href=\"javascript:;\"></a>':\"\";return r.closeBtn&&(e+='<a class=\"layui-layer-ico '+s[7]+\" \"+s[7]+(r.title?r.closeBtn:4==r.type?\"1\":\"2\")+'\" href=\"javascript:;\"></a>'),e}()+\"</span>\"+(r.btn?function(){var e=\"\";\"string\"==typeof r.btn&&(r.btn=[r.btn]);for(var t=0,i=r.btn.length;t<i;t++)e+='<a class=\"'+s[6]+t+'\">'+r.btn[t]+\"</a>\";return'<div class=\"'+s[6]+\" layui-layer-btn-\"+(r.btnAlign||\"\")+'\">'+e+\"</div>\"}():\"\")+(r.resize?'<span class=\"layui-layer-resize\"></span>':\"\")+\"</div>\"],d,i('<div class=\"layui-layer-move\"></div>')),n},l.pt.creat=function(){var e=this,t=e.config,a=e.index,l=t.content,f=\"object\"==typeof l,c=i(\"body\");if(!i(\"#\"+t.id)[0]){switch(\"string\"==typeof t.area&&(t.area=\"auto\"===t.area?[\"\",\"\"]:[t.area,\"\"]),t.shift&&(t.anim=t.shift),6==r.ie&&(t.fixed=!1),t.type){case 0:t.btn=\"btn\"in t?t.btn:o.btn[0],r.closeAll(\"dialog\");break;case 2:var l=t.content=f?t.content:[t.content||\"http://layer.layui.com\",\"auto\"];t.content='<iframe scrolling=\"'+(t.content[1]||\"auto\")+'\" allowtransparency=\"true\" id=\"'+s[4]+a+'\" name=\"'+s[4]+a+'\" onload=\"this.className=\\'\\';\" class=\"layui-layer-load\" frameborder=\"0\" src=\"'+t.content[0]+'\"></iframe>';break;case 3:delete t.title,delete t.closeBtn,t.icon===-1&&0===t.icon,r.closeAll(\"loading\");break;case 4:f||(t.content=[t.content,\"body\"]),t.follow=t.content[1],t.content=t.content[0]+'<i class=\"layui-layer-TipsG\"></i>',delete t.title,t.tips=\"object\"==typeof t.tips?t.tips:[t.tips,!0],t.tipsMore||r.closeAll(\"tips\")}e.vessel(f,function(n,r,d){c.append(n[0]),f?function(){2==t.type||4==t.type?function(){i(\"body\").append(n[1])}():function(){l.parents(\".\"+s[0])[0]||(l.data(\"display\",l.css(\"display\")).show().addClass(\"layui-layer-wrap\").wrap(n[1]),i(\"#\"+s[0]+a).find(\".\"+s[5]).before(r))}()}():c.append(n[1]),i(\".layui-layer-move\")[0]||c.append(o.moveElem=d),e.layero=i(\"#\"+s[0]+a),t.scrollbar||s.html.css(\"overflow\",\"hidden\").attr(\"layer-full\",a)}).auto(a),2==t.type&&6==r.ie&&e.layero.find(\"iframe\").attr(\"src\",l[0]),4==t.type?e.tips():e.offset(),t.fixed&&n.on(\"resize\",function(){e.offset(),(/^\\d+%$/.test(t.area[0])||/^\\d+%$/.test(t.area[1]))&&e.auto(a),4==t.type&&e.tips()}),t.time<=0||setTimeout(function(){r.close(e.index)},t.time),e.move().callback(),s.anim[t.anim]&&e.layero.addClass(s.anim[t.anim]).data(\"anim\",!0)}},l.pt.auto=function(e){function t(e){e=l.find(e),e.height(f[1]-c-d-2*(0|parseFloat(e.css(\"padding\"))))}var a=this,o=a.config,l=i(\"#\"+s[0]+e);\"\"===o.area[0]&&o.maxWidth>0&&(r.ie&&r.ie<8&&o.btn&&l.width(l.innerWidth()),l.outerWidth()>o.maxWidth&&l.width(o.maxWidth));var f=[l.innerWidth(),l.innerHeight()],c=l.find(s[1]).outerHeight()||0,d=l.find(\".\"+s[6]).outerHeight()||0;switch(o.type){case 2:t(\"iframe\");break;default:\"\"===o.area[1]?o.fixed&&f[1]>=n.height()&&(f[1]=n.height(),t(\".\"+s[5])):t(\".\"+s[5])}return a},l.pt.offset=function(){var e=this,t=e.config,i=e.layero,a=[i.outerWidth(),i.outerHeight()],o=\"object\"==typeof t.offset;e.offsetTop=(n.height()-a[1])/2,e.offsetLeft=(n.width()-a[0])/2,o?(e.offsetTop=t.offset[0],e.offsetLeft=t.offset[1]||e.offsetLeft):\"auto\"!==t.offset&&(\"t\"===t.offset?e.offsetTop=0:\"r\"===t.offset?e.offsetLeft=n.width()-a[0]:\"b\"===t.offset?e.offsetTop=n.height()-a[1]:\"l\"===t.offset?e.offsetLeft=0:\"lt\"===t.offset?(e.offsetTop=0,e.offsetLeft=0):\"lb\"===t.offset?(e.offsetTop=n.height()-a[1],e.offsetLeft=0):\"rt\"===t.offset?(e.offsetTop=0,e.offsetLeft=n.width()-a[0]):\"rb\"===t.offset?(e.offsetTop=n.height()-a[1],e.offsetLeft=n.width()-a[0]):e.offsetTop=t.offset),t.fixed||(e.offsetTop=/%$/.test(e.offsetTop)?n.height()*parseFloat(e.offsetTop)/100:parseFloat(e.offsetTop),e.offsetLeft=/%$/.test(e.offsetLeft)?n.width()*parseFloat(e.offsetLeft)/100:parseFloat(e.offsetLeft),e.offsetTop+=n.scrollTop(),e.offsetLeft+=n.scrollLeft()),i.attr(\"minLeft\")&&(e.offsetTop=n.height()-(i.find(s[1]).outerHeight()||0),e.offsetLeft=i.css(\"left\")),i.css({top:e.offsetTop,left:e.offsetLeft})},l.pt.tips=function(){var e=this,t=e.config,a=e.layero,o=[a.outerWidth(),a.outerHeight()],r=i(t.follow);r[0]||(r=i(\"body\"));var l={width:r.outerWidth(),height:r.outerHeight(),top:r.offset().top,left:r.offset().left},f=a.find(\".layui-layer-TipsG\"),c=t.tips[0];t.tips[1]||f.remove(),l.autoLeft=function(){l.left+o[0]-n.width()>0?(l.tipLeft=l.left+l.width-o[0],f.css({right:12,left:\"auto\"})):l.tipLeft=l.left},l.where=[function(){l.autoLeft(),l.tipTop=l.top-o[1]-10,f.removeClass(\"layui-layer-TipsB\").addClass(\"layui-layer-TipsT\").css(\"border-right-color\",t.tips[1])},function(){l.tipLeft=l.left+l.width+10,l.tipTop=l.top,f.removeClass(\"layui-layer-TipsL\").addClass(\"layui-layer-TipsR\").css(\"border-bottom-color\",t.tips[1])},function(){l.autoLeft(),l.tipTop=l.top+l.height+10,f.removeClass(\"layui-layer-TipsT\").addClass(\"layui-layer-TipsB\").css(\"border-right-color\",t.tips[1])},function(){l.tipLeft=l.left-o[0]-10,l.tipTop=l.top,f.removeClass(\"layui-layer-TipsR\").addClass(\"layui-layer-TipsL\").css(\"border-bottom-color\",t.tips[1])}],l.where[c-1](),1===c?l.top-(n.scrollTop()+o[1]+16)<0&&l.where[2]():2===c?n.width()-(l.left+l.width+o[0]+16)>0||l.where[3]():3===c?l.top-n.scrollTop()+l.height+o[1]+16-n.height()>0&&l.where[0]():4===c&&o[0]+16-l.left>0&&l.where[1](),a.find(\".\"+s[5]).css({\"background-color\":t.tips[1],\"padding-right\":t.closeBtn?\"30px\":\"\"}),a.css({left:l.tipLeft-(t.fixed?n.scrollLeft():0),top:l.tipTop-(t.fixed?n.scrollTop():0)})},l.pt.move=function(){var e=this,t=e.config,a=i(document),l=e.layero,s=l.find(t.move),f=l.find(\".layui-layer-resize\"),c={};return t.move&&s.css(\"cursor\",\"move\"),s.on(\"mousedown\",function(e){e.preventDefault(),t.move&&(c.moveStart=!0,c.offset=[e.clientX-parseFloat(l.css(\"left\")),e.clientY-parseFloat(l.css(\"top\"))],o.moveElem.css(\"cursor\",\"move\").show())}),f.on(\"mousedown\",function(e){e.preventDefault(),c.resizeStart=!0,c.offset=[e.clientX,e.clientY],c.area=[l.outerWidth(),l.outerHeight()],o.moveElem.css(\"cursor\",\"se-resize\").show()}),a.on(\"mousemove\",function(i){if(c.moveStart){var a=i.clientX-c.offset[0],o=i.clientY-c.offset[1],s=\"fixed\"===l.css(\"position\");if(i.preventDefault(),c.stX=s?0:n.scrollLeft(),c.stY=s?0:n.scrollTop(),!t.moveOut){var f=n.width()-l.outerWidth()+c.stX,d=n.height()-l.outerHeight()+c.stY;a<c.stX&&(a=c.stX),a>f&&(a=f),o<c.stY&&(o=c.stY),o>d&&(o=d)}l.css({left:a,top:o})}if(t.resize&&c.resizeStart){var a=i.clientX-c.offset[0],o=i.clientY-c.offset[1];i.preventDefault(),r.style(e.index,{width:c.area[0]+a,height:c.area[1]+o}),c.isResize=!0}}).on(\"mouseup\",function(e){c.moveStart&&(delete c.moveStart,o.moveElem.hide(),t.moveEnd&&t.moveEnd()),c.resizeStart&&(delete c.resizeStart,o.moveElem.hide())}),e},l.pt.callback=function(){function e(){var e=a.cancel&&a.cancel(t.index,n);e===!1||r.close(t.index)}var t=this,n=t.layero,a=t.config;t.openLayer(),a.success&&(2==a.type?n.find(\"iframe\").on(\"load\",function(){a.success(n,t.index)}):a.success(n,t.index)),6==r.ie&&t.IE6(n),n.find(\".\"+s[6]).children(\"a\").on(\"click\",function(){var e=i(this).index();if(0===e)a.yes?a.yes(t.index,n):a.btn1?a.btn1(t.index,n):r.close(t.index);else{var o=a[\"btn\"+(e+1)]&&a[\"btn\"+(e+1)](t.index,n);o===!1||r.close(t.index)}}),n.find(\".\"+s[7]).on(\"click\",e),a.shadeClose&&i(\"#layui-layer-shade\"+t.index).on(\"click\",function(){r.close(t.index)}),n.find(\".layui-layer-min\").on(\"click\",function(){var e=a.min&&a.min(n);e===!1||r.min(t.index,a)}),n.find(\".layui-layer-max\").on(\"click\",function(){i(this).hasClass(\"layui-layer-maxmin\")?(r.restore(t.index),a.restore&&a.restore(n)):(r.full(t.index,a),setTimeout(function(){a.full&&a.full(n)},100))}),a.end&&(o.end[t.index]=a.end)},o.reselect=function(){i.each(i(\"select\"),function(e,t){var n=i(this);n.parents(\".\"+s[0])[0]||1==n.attr(\"layer\")&&i(\".\"+s[0]).length<1&&n.removeAttr(\"layer\").show(),n=null})},l.pt.IE6=function(e){i(\"select\").each(function(e,t){var n=i(this);n.parents(\".\"+s[0])[0]||\"none\"===n.css(\"display\")||n.attr({layer:\"1\"}).hide(),n=null})},l.pt.openLayer=function(){var e=this;r.zIndex=e.config.zIndex,r.setTop=function(e){var t=function(){r.zIndex++,e.css(\"z-index\",r.zIndex+1)};return r.zIndex=parseInt(e[0].style.zIndex),e.on(\"mousedown\",t),r.zIndex}},o.record=function(e){var t=[e.width(),e.height(),e.position().top,e.position().left+parseFloat(e.css(\"margin-left\"))];e.find(\".layui-layer-max\").addClass(\"layui-layer-maxmin\"),e.attr({area:t})},o.rescollbar=function(e){s.html.attr(\"layer-full\")==e&&(s.html[0].style.removeProperty?s.html[0].style.removeProperty(\"overflow\"):s.html[0].style.removeAttribute(\"overflow\"),s.html.removeAttr(\"layer-full\"))},e.layer=r,r.getChildFrame=function(e,t){return t=t||i(\".\"+s[4]).attr(\"times\"),i(\"#\"+s[0]+t).find(\"iframe\").contents().find(e)},r.getFrameIndex=function(e){return i(\"#\"+e).parents(\".\"+s[4]).attr(\"times\")},r.iframeAuto=function(e){if(e){var t=r.getChildFrame(\"html\",e).outerHeight(),n=i(\"#\"+s[0]+e),a=n.find(s[1]).outerHeight()||0,o=n.find(\".\"+s[6]).outerHeight()||0;n.css({height:t+a+o}),n.find(\"iframe\").css({height:t})}},r.iframeSrc=function(e,t){i(\"#\"+s[0]+e).find(\"iframe\").attr(\"src\",t)},r.style=function(e,t,n){var a=i(\"#\"+s[0]+e),r=a.find(\".layui-layer-content\"),l=a.attr(\"type\"),f=a.find(s[1]).outerHeight()||0,c=a.find(\".\"+s[6]).outerHeight()||0;a.attr(\"minLeft\");l!==o.type[3]&&l!==o.type[4]&&(n||(parseFloat(t.width)<=260&&(t.width=260),parseFloat(t.height)-f-c<=64&&(t.height=64+f+c)),a.css(t),c=a.find(\".\"+s[6]).outerHeight(),l===o.type[2]?a.find(\"iframe\").css({height:parseFloat(t.height)-f-c}):r.css({height:parseFloat(t.height)-f-c-parseFloat(r.css(\"padding-top\"))-parseFloat(r.css(\"padding-bottom\"))}))},r.min=function(e,t){var a=i(\"#\"+s[0]+e),l=a.find(s[1]).outerHeight()||0,f=a.attr(\"minLeft\")||181*o.minIndex+\"px\",c=a.css(\"position\");o.record(a),o.minLeft[0]&&(f=o.minLeft[0],o.minLeft.shift()),a.attr(\"position\",c),r.style(e,{width:180,height:l,left:f,top:n.height()-l,position:\"fixed\",overflow:\"hidden\"},!0),a.find(\".layui-layer-min\").hide(),\"page\"===a.attr(\"type\")&&a.find(s[4]).hide(),o.rescollbar(e),a.attr(\"minLeft\")||o.minIndex++,a.attr(\"minLeft\",f)},r.restore=function(e){var t=i(\"#\"+s[0]+e),n=t.attr(\"area\").split(\",\");t.attr(\"type\");r.style(e,{width:parseFloat(n[0]),height:parseFloat(n[1]),top:parseFloat(n[2]),left:parseFloat(n[3]),position:t.attr(\"position\"),overflow:\"visible\"},!0),t.find(\".layui-layer-max\").removeClass(\"layui-layer-maxmin\"),t.find(\".layui-layer-min\").show(),\"page\"===t.attr(\"type\")&&t.find(s[4]).show(),o.rescollbar(e)},r.full=function(e){var t,a=i(\"#\"+s[0]+e);o.record(a),s.html.attr(\"layer-full\")||s.html.css(\"overflow\",\"hidden\").attr(\"layer-full\",e),clearTimeout(t),t=setTimeout(function(){var t=\"fixed\"===a.css(\"position\");r.style(e,{top:t?0:n.scrollTop(),left:t?0:n.scrollLeft(),width:n.width(),height:n.height()},!0),a.find(\".layui-layer-min\").hide()},100)},r.title=function(e,t){var n=i(\"#\"+s[0]+(t||r.index)).find(s[1]);n.html(e)},r.close=function(e){var t=i(\"#\"+s[0]+e),n=t.attr(\"type\"),a=\"layer-anim-close\";if(t[0]){var l=\"layui-layer-wrap\",f=function(){if(n===o.type[1]&&\"object\"===t.attr(\"conType\")){t.children(\":not(.\"+s[5]+\")\").remove();for(var a=t.find(\".\"+l),r=0;r<2;r++)a.unwrap();a.css(\"display\",a.data(\"display\")).removeClass(l)}else{if(n===o.type[2])try{var f=i(\"#\"+s[4]+e)[0];f.contentWindow.document.write(\"\"),f.contentWindow.close(),t.find(\".\"+s[5])[0].removeChild(f)}catch(c){}t[0].innerHTML=\"\",t.remove()}\"function\"==typeof o.end[e]&&o.end[e](),delete o.end[e]};t.data(\"anim\")&&t.addClass(a),i(\"#layui-layer-moves, #layui-layer-shade\"+e).remove(),6==r.ie&&o.reselect(),o.rescollbar(e),t.attr(\"minLeft\")&&(o.minIndex--,o.minLeft.push(t.attr(\"minLeft\"))),setTimeout(function(){f()},r.ie&&r.ie<10||!t.data(\"anim\")?0:200)}},r.closeAll=function(e){i.each(i(\".\"+s[0]),function(){var t=i(this),n=e?t.attr(\"type\")===e:1;n&&r.close(t.attr(\"times\")),n=null})};var f=r.cache||{},c=function(e){return f.skin?\" \"+f.skin+\" \"+f.skin+\"-\"+e:\"\"};r.prompt=function(e,t){var a=\"\";if(e=e||{},\"function\"==typeof e&&(t=e),e.area){var o=e.area;a='style=\"width: '+o[0]+\"; height: \"+o[1]+';\"',delete e.area}var l,s=2==e.formType?'<textarea class=\"layui-layer-input\"'+a+\">\"+(e.value||\"\")+\"</textarea>\":function(){return'<input type=\"'+(1==e.formType?\"password\":\"text\")+'\" class=\"layui-layer-input\" value=\"'+(e.value||\"\")+'\">'}();return r.open(i.extend({type:1,btn:[\"&#x786E;&#x5B9A;\",\"&#x53D6;&#x6D88;\"],content:s,skin:\"layui-layer-prompt\"+c(\"prompt\"),maxWidth:n.width(),success:function(e){l=e.find(\".layui-layer-input\"),l.focus()},resize:!1,yes:function(i){var n=l.val();\"\"===n?l.focus():n.length>(e.maxlength||500)?r.tips(\"&#x6700;&#x591A;&#x8F93;&#x5165;\"+(e.maxlength||500)+\"&#x4E2A;&#x5B57;&#x6570;\",l,{tips:1}):t&&t(n,i,l)}},e))},r.tab=function(e){e=e||{};var t=e.tab||{};return r.open(i.extend({type:1,skin:\"layui-layer-tab\"+c(\"tab\"),resize:!1,title:function(){var e=t.length,i=1,n=\"\";if(e>0)for(n='<span class=\"layui-layer-tabnow\">'+t[0].title+\"</span>\";i<e;i++)n+=\"<span>\"+t[i].title+\"</span>\";return n}(),content:'<ul class=\"layui-layer-tabmain\">'+function(){var e=t.length,i=1,n=\"\";if(e>0)for(n='<li class=\"layui-layer-tabli xubox_tab_layer\">'+(t[0].content||\"no content\")+\"</li>\";i<e;i++)n+='<li class=\"layui-layer-tabli\">'+(t[i].content||\"no  content\")+\"</li>\";return n}()+\"</ul>\",success:function(t){var n=t.find(\".layui-layer-title\").children(),a=t.find(\".layui-layer-tabmain\").children();n.on(\"mousedown\",function(t){t.stopPropagation?t.stopPropagation():t.cancelBubble=!0;var n=i(this),o=n.index();n.addClass(\"layui-layer-tabnow\").siblings().removeClass(\"layui-layer-tabnow\"),a.eq(o).show().siblings().hide(),\"function\"==typeof e.change&&e.change(o)})}},e))},r.photos=function(t,n,a){function o(e,t,i){var n=new Image;return n.src=e,n.complete?t(n):(n.onload=function(){n.onload=null,t(n)},void(n.onerror=function(e){n.onerror=null,i(e)}))}var l={};if(t=t||{},t.photos){var s=t.photos.constructor===Object,f=s?t.photos:{},d=f.data||[],u=f.start||0;if(l.imgIndex=(0|u)+1,t.img=t.img||\"img\",s){if(0===d.length)return r.msg(\"&#x6CA1;&#x6709;&#x56FE;&#x7247;\")}else{var y=i(t.photos),p=function(){d=[],y.find(t.img).each(function(e){var t=i(this);t.attr(\"layer-index\",e),d.push({alt:t.attr(\"alt\"),pid:t.attr(\"layer-pid\"),src:t.attr(\"layer-src\")||t.attr(\"src\"),thumb:t.attr(\"src\")})})};if(p(),0===d.length)return;if(n||y.on(\"click\",t.img,function(){var e=i(this),n=e.attr(\"layer-index\");r.photos(i.extend(t,{photos:{start:n,data:d,tab:t.tab},full:t.full}),!0),p()}),!n)return}l.imgprev=function(e){l.imgIndex--,l.imgIndex<1&&(l.imgIndex=d.length),l.tabimg(e)},l.imgnext=function(e,t){l.imgIndex++,l.imgIndex>d.length&&(l.imgIndex=1,t)||l.tabimg(e)},l.keyup=function(e){if(!l.end){var t=e.keyCode;e.preventDefault(),37===t?l.imgprev(!0):39===t?l.imgnext(!0):27===t&&r.close(l.index)}},l.tabimg=function(e){d.length<=1||(f.start=l.imgIndex-1,r.close(l.index),r.photos(t,!0,e))},l.event=function(){l.bigimg.hover(function(){l.imgsee.show()},function(){l.imgsee.hide()}),l.bigimg.find(\".layui-layer-imgprev\").on(\"click\",function(e){e.preventDefault(),l.imgprev()}),l.bigimg.find(\".layui-layer-imgnext\").on(\"click\",function(e){e.preventDefault(),l.imgnext()}),i(document).on(\"keyup\",l.keyup)},l.loadi=r.load(1,{shade:!(\"shade\"in t)&&.9,scrollbar:!1}),o(d[u].src,function(n){r.close(l.loadi),l.index=r.open(i.extend({type:1,area:function(){var a=[n.width,n.height],o=[i(e).width()-100,i(e).height()-100];if(!t.full&&(a[0]>o[0]||a[1]>o[1])){var r=[a[0]/o[0],a[1]/o[1]];r[0]>r[1]?(a[0]=a[0]/r[0],a[1]=a[1]/r[0]):r[0]<r[1]&&(a[0]=a[0]/r[1],a[1]=a[1]/r[1])}return[a[0]+\"px\",a[1]+\"px\"]}(),title:!1,shade:.9,shadeClose:!0,closeBtn:!1,move:\".layui-layer-phimg img\",moveType:1,scrollbar:!1,moveOut:!0,anim:5*Math.random()|0,skin:\"layui-layer-photos\"+c(\"photos\"),content:'<div class=\"layui-layer-phimg\"><img src=\"'+d[u].src+'\" alt=\"'+(d[u].alt||\"\")+'\" layer-pid=\"'+d[u].pid+'\"><div class=\"layui-layer-imgsee\">'+(d.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:'+(a?\"block\":\"\")+'\"><span class=\"layui-layer-imgtit\"><a href=\"javascript:;\">'+(d[u].alt||\"\")+\"</a><em>\"+l.imgIndex+\"/\"+d.length+\"</em></span></div></div></div>\",success:function(e,i){l.bigimg=e.find(\".layui-layer-phimg\"),l.imgsee=e.find(\".layui-layer-imguide,.layui-layer-imgbar\"),l.event(e),t.tab&&t.tab(d[u],e)},end:function(){l.end=!0,i(document).off(\"keyup\",l.keyup)}},t))},function(){r.close(l.loadi),r.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(){d.length>1&&l.imgnext(!0,!0)}})})}},o.run=function(t){i=t,n=i(e),s.html=i(\"html\"),r.open=function(e){var t=new l(e);return t.index}},e.layui&&layui.define?(r.ready(),layui.define(\"jquery\",function(t){r.path=layui.cache.dir,o.run(layui.jquery),e.layer=r,t(\"layer\",r)})):\"function\"==typeof define?define([\"jquery\"],function(){return o.run(e.jQuery),r}):function(){o.run(e.jQuery),r.ready()}()}(window);layui.define(\"jquery\",function(i){\"use strict\";var t=layui.jquery,a=(layui.hint(),layui.device()),e=\"element\",l=\"layui-this\",n=\"layui-show\",s=function(){this.config={}};s.prototype.set=function(i){var a=this;return t.extend(!0,a.config,i),a},s.prototype.on=function(i,t){return layui.onevent(e,i,t)},s.prototype.tabAdd=function(i,a){var e=t(\".layui-tab[lay-filter=\"+i+\"]\"),l=e.children(\".layui-tab-title\"),n=e.children(\".layui-tab-content\");return l.append(\"<li>\"+(a.title||\"unnaming\")+\"</li>\"),n.append('<div class=\"layui-tab-item\">'+(a.content||\"\")+\"</div>\"),y.tabAuto(),this},s.prototype.tabDelete=function(i,a){var e=t(\".layui-tab[lay-filter=\"+i+\"]\"),l=e.children(\".layui-tab-title\").find(\">li\").eq(a);return y.tabDelete(null,l),this},s.prototype.tabChange=function(i,a){var e=t(\".layui-tab[lay-filter=\"+i+\"]\"),l=e.children(\".layui-tab-title\").find(\">li\").eq(a);return y.tabClick(null,a,l),this};var o=\".layui-nav\",c=\"layui-nav-item\",r=\"layui-nav-bar\",u=\"layui-nav-tree\",d=\"layui-nav-child\",h=\"layui-nav-more\",f=\"layui-anim layui-anim-upbit\",y={tabClick:function(i,a,s){var o=s||t(this),a=a||o.index(),c=o.parents(\".layui-tab\"),r=c.children(\".layui-tab-content\").children(\".layui-tab-item\"),u=c.attr(\"lay-filter\");o.addClass(l).siblings().removeClass(l),r.eq(a).addClass(n).siblings().removeClass(n),layui.event.call(this,e,\"tab(\"+u+\")\",{elem:c,index:a})},tabDelete:function(i,a){var e=a||t(this).parent(),n=e.index(),s=e.parents(\".layui-tab\"),o=s.children(\".layui-tab-content\").children(\".layui-tab-item\");e.hasClass(l)&&(e.next()[0]?y.tabClick.call(e.next()[0],null,n+1):e.prev()[0]&&y.tabClick.call(e.prev()[0],null,n-1)),e.remove(),o.eq(n).remove()},tabAuto:function(){var i=\"layui-tab-more\",e=\"layui-tab-bar\",l=\"layui-tab-close\",n=this;t(\".layui-tab\").each(function(){var s=t(this),o=s.children(\".layui-tab-title\"),c=(s.children(\".layui-tab-content\").children(\".layui-tab-item\"),'lay-stope=\"tabmore\"'),r=t('<span class=\"layui-unselect layui-tab-bar\" '+c+\"><i \"+c+' class=\"layui-icon\">&#xe61a;</i></span>');if(n===window&&8!=a.ie&&y.hideTabMore(!0),s.attr(\"lay-allowClose\")&&o.find(\"li\").each(function(){var i=t(this);if(!i.find(\".\"+l)[0]){var a=t('<i class=\"layui-icon layui-unselect '+l+'\">&#x1006;</i>');a.on(\"click\",y.tabDelete),i.append(a)}}),o.prop(\"scrollWidth\")>o.outerWidth()+1){if(o.find(\".\"+e)[0])return;o.append(r),r.on(\"click\",function(t){o[this.title?\"removeClass\":\"addClass\"](i),this.title=this.title?\"\":\"收缩\"})}else o.find(\".\"+e).remove()})},hideTabMore:function(i){var a=t(\".layui-tab-title\");i!==!0&&\"tabmore\"===t(i.target).attr(\"lay-stope\")||(a.removeClass(\"layui-tab-more\"),a.find(\".layui-tab-bar\").attr(\"title\",\"\"))},clickThis:function(){var i=t(this),a=i.parents(o),n=a.attr(\"lay-filter\");i.find(\".\"+d)[0]||(a.find(\".\"+l).removeClass(l),i.addClass(l),layui.event.call(this,e,\"nav(\"+n+\")\",i))},clickChild:function(){var i=t(this),a=i.parents(o),n=a.attr(\"lay-filter\");a.find(\".\"+l).removeClass(l),i.addClass(l),layui.event.call(this,e,\"nav(\"+n+\")\",i)},showChild:function(){var i=t(this),a=i.parents(o),e=i.parent(),l=i.siblings(\".\"+d);a.hasClass(u)&&(l.removeClass(f),e[\"none\"===l.css(\"display\")?\"addClass\":\"removeClass\"](c+\"ed\"))}};s.prototype.init=function(i){var e={tab:function(){y.tabAuto.call({})},nav:function(){var i,e,l,s=200,p=function(o,c){var r=t(this),y=r.find(\".\"+d);c.hasClass(u)?o.css({top:r.position().top,height:r.children(\"a\").height(),opacity:1}):(y.addClass(f),o.css({left:r.position().left+parseFloat(r.css(\"marginLeft\")),top:r.position().top+r.height()-5}),i=setTimeout(function(){o.css({width:r.width(),opacity:1})},a.ie&&a.ie<10?0:s),clearTimeout(l),\"block\"===y.css(\"display\")&&clearTimeout(e),e=setTimeout(function(){y.addClass(n),r.find(\".\"+h).addClass(h+\"d\")},300))};t(o).each(function(){var a=t(this),o=t('<span class=\"'+r+'\"></span>'),f=a.find(\".\"+c);a.find(\".\"+r)[0]||(a.append(o),f.on(\"mouseenter\",function(){p.call(this,o,a)}).on(\"mouseleave\",function(){a.hasClass(u)||(clearTimeout(e),e=setTimeout(function(){a.find(\".\"+d).removeClass(n),a.find(\".\"+h).removeClass(h+\"d\")},300))}),a.on(\"mouseleave\",function(){clearTimeout(i),l=setTimeout(function(){a.hasClass(u)?o.css({height:0,top:o.position().top+o.height()/2,opacity:0}):o.css({width:0,left:o.position().left+o.width()/2,opacity:0})},s)})),f.each(function(){var i=t(this),a=i.find(\".\"+d);if(a[0]&&!i.find(\".\"+h)[0]){var e=i.children(\"a\");e.append('<span class=\"'+h+'\"></span>')}i.off(\"click\",y.clickThis).on(\"click\",y.clickThis),i.children(\"a\").off(\"click\",y.showChild).on(\"click\",y.showChild),a.children(\"dd\").off(\"click\",y.clickChild).on(\"click\",y.clickChild)})})},breadcrumb:function(){var i=\".layui-breadcrumb\";t(i).each(function(){var i=t(this),a=i.attr(\"lay-separator\")||\">\",e=i.find(\"a\");e.find(\".layui-box\")[0]||(e.each(function(i){i!==e.length-1&&t(this).append('<span class=\"layui-box\">'+a+\"</span>\")}),i.css(\"visibility\",\"visible\"))})}};return layui.each(e,function(i,t){t()})};var p=new s,b=t(document);p.init();var v=\".layui-tab-title li\";b.on(\"click\",v,y.tabClick),b.on(\"click\",y.hideTabMore),t(window).on(\"resize\",y.tabAuto),i(e,function(i){return p.set(i)})});layui.define(\"layer\",function(e){\"use strict\";var a=layui.jquery,t=layui.layer,i=(layui.device(),\"layui-upload-enter\"),n=\"layui-upload-iframe\",r={icon:2,shift:6},o={file:\"文件\",video:\"视频\",audio:\"音频\"},s=function(e){this.options=e};s.prototype.init=function(){var e=this,t=e.options,r=a(\"body\"),s=a(t.elem||\".layui-upload-file\"),u=a('<iframe id=\"'+n+'\" class=\"'+n+'\" name=\"'+n+'\"></iframe>');return a(\"#\"+n)[0]||r.append(u),s.each(function(r,s){s=a(s);var u='<form target=\"'+n+'\" method=\"'+(t.method||\"post\")+'\" key=\"set-mine\" enctype=\"multipart/form-data\" action=\"'+(t.url||\"\")+'\"></form>',l=s.attr(\"lay-type\")||t.type;t.unwrap||(u='<div class=\"layui-box layui-upload-button\">'+u+'<span class=\"layui-upload-icon\"><i class=\"layui-icon\">&#xe608;</i>'+(s.attr(\"lay-title\")||t.title||\"上传\"+(o[l]||\"图片\"))+\"</span></div>\"),u=a(u),t.unwrap||u.on(\"dragover\",function(e){e.preventDefault(),a(this).addClass(i)}).on(\"dragleave\",function(){a(this).removeClass(i)}).on(\"drop\",function(){a(this).removeClass(i)}),s.parent(\"form\").attr(\"target\")===n&&(t.unwrap?s.unwrap():(s.parent().next().remove(),s.unwrap().unwrap())),s.wrap(u),s.off(\"change\").on(\"change\",function(){e.action(this,l)})})},s.prototype.action=function(e,i){var o=this,s=o.options,u=e.value,l=a(e),p=l.attr(\"lay-ext\")||s.ext||\"\";if(u){switch(i){case\"file\":if(p&&!RegExp(\"\\\\w\\\\.(\"+p+\")$\",\"i\").test(escape(u)))return t.msg(\"不支持该文件格式\",r),e.value=\"\";break;case\"video\":if(!RegExp(\"\\\\w\\\\.(\"+(p||\"avi|mp4|wma|rmvb|rm|flash|3gp|flv\")+\")$\",\"i\").test(escape(u)))return t.msg(\"不支持该视频格式\",r),e.value=\"\";break;case\"audio\":if(!RegExp(\"\\\\w\\\\.(\"+(p||\"mp3|wav|mid\")+\")$\",\"i\").test(escape(u)))return t.msg(\"不支持该音频格式\",r),e.value=\"\";break;default:if(!RegExp(\"\\\\w\\\\.(\"+(p||\"jpg|png|gif|bmp|jpeg\")+\")$\",\"i\").test(escape(u)))return t.msg(\"不支持该图片格式\",r),e.value=\"\"}s.before&&s.before(e),l.parent().submit();var c=a(\"#\"+n),f=setInterval(function(){var a;try{a=c.contents().find(\"body\").text()}catch(i){t.msg(\"上传接口存在跨域\",r),clearInterval(f)}if(a){clearInterval(f),c.contents().find(\"body\").html(\"\");try{a=JSON.parse(a)}catch(i){return a={},t.msg(\"请对上传接口返回JSON字符\",r)}\"function\"==typeof s.success&&s.success(a,e)}},30);e.value=\"\"}},e(\"upload\",function(e){var a=new s(e=e||{});a.init()})});layui.define(\"layer\",function(e){\"use strict\";var i=layui.jquery,a=layui.layer,t=layui.hint(),n=layui.device(),l=\"form\",s=\".layui-form\",c=\"layui-this\",r=\"layui-disabled\",u=function(){this.config={verify:{required:[/[\\S]+/,\"必填项不能为空\"],phone:[/^1\\d{10}$/,\"请输入正确的手机号\"],email:[/^([a-zA-Z0-9_\\.\\-])+\\@(([a-zA-Z0-9\\-])+\\.)+([a-zA-Z0-9]{2,4})+$/,\"邮箱格式不正确\"],url:[/(^#)|(^http(s*):\\/\\/[^\\s]+\\.[^\\s]+)/,\"链接格式不正确\"],number:[/^\\d+$/,\"只能填写数字\"],date:[/^(\\d{4})[-\\/](\\d{1}|0\\d{1}|1[0-2])([-\\/](\\d{1}|0\\d{1}|[1-2][0-9]|3[0-1]))*$/,\"日期格式不正确\"],identity:[/(^\\d{15}$)|(^\\d{17}(x|X|\\d)$)/,\"请输入正确的身份证号\"]}}};u.prototype.set=function(e){var a=this;return i.extend(!0,a.config,e),a},u.prototype.verify=function(e){var a=this;return i.extend(!0,a.config.verify,e),a},u.prototype.on=function(e,i){return layui.onevent(l,e,i)},u.prototype.render=function(e){var a=this,n={select:function(){var e=\"请选择\",a=\"layui-form-select\",t=\"layui-select-title\",n=i(s).find(\"select\"),u=function(e,n){i(e.target).parent().hasClass(t)&&!n||i(\".\"+a).removeClass(a+\"ed\")},o=function(e,n){var s=i(this),o=e.find(\".\"+t);n||(o.on(\"click\",function(i){e.hasClass(a+\"ed\")?e.removeClass(a+\"ed\"):(u(i,!0),e.addClass(a+\"ed\"))}),e.find(\"dl>dd\").on(\"click\",function(){var e=i(this),a=e.attr(\"lay-value\"),t=s.attr(\"lay-filter\");return!e.hasClass(r)&&(s.val(a).removeClass(\"layui-form-danger\"),o.find(\"input\").val(e.text()),e.addClass(c).siblings().removeClass(c),void layui.event(l,\"select(\"+t+\")\",{elem:s[0],value:a}))}),e.find(\"dl>dt\").on(\"click\",function(e){return!1}),i(document).off(\"click\",u).on(\"click\",u))};n.each(function(n,l){var s=i(this),u=s.next(\".\"+a),d=this.disabled,f=l.value,y=i(l.options[l.selectedIndex]),v=i(['<div class=\"layui-unselect '+a+(d?\" layui-select-disabled\":\"\")+'\">','<div class=\"'+t+'\"><input type=\"text\" placeholder=\"'+(l.options[0].innerHTML?l.options[0].innerHTML:e)+'\" value=\"'+(f?y.html():\"\")+'\" readonly class=\"layui-input layui-unselect'+(d?\" \"+r:\"\")+'\">','<i class=\"layui-edge\"></i></div>','<dl class=\"layui-anim layui-anim-upbit'+(s.find(\"optgroup\")[0]?\" layui-select-group\":\"\")+'\">'+function(e){var i=[];return layui.each(e,function(e,a){(0!==e||a.value)&&(\"optgroup\"===a.tagName.toLowerCase()?i.push(\"<dt>\"+a.label+\"</dt>\"):i.push('<dd lay-value=\"'+a.value+'\" class=\"'+(f===a.value?c:\"\")+(a.disabled?\" \"+r:\"\")+'\">'+a.innerHTML+\"</dd>\"))}),i.join(\"\")}(s.find(\"*\"))+\"</dl>\",\"</div>\"].join(\"\"));u[0]&&u.remove(),s.after(v),o.call(this,v,d)})},checkbox:function(){var e={checkbox:[\"layui-form-checkbox\",\"layui-form-checked\",\"checkbox\"],_switch:[\"layui-form-switch\",\"layui-form-onswitch\",\"switch\"]},a=i(s).find(\"input[type=checkbox]\"),t=function(e,a){var t=i(this);e.on(\"click\",function(){var i=t.attr(\"lay-filter\");t[0].disabled||(t[0].checked?(t[0].checked=!1,e.removeClass(a[1])):(t[0].checked=!0,e.addClass(a[1])),layui.event(l,a[2]+\"(\"+i+\")\",{elem:t[0],value:t[0].value}))})};a.each(function(a,n){var l=i(this),s=l.attr(\"lay-skin\"),c=this.disabled;\"switch\"===s&&(s=\"_\"+s);var u=e[s]||e.checkbox,o=l.next(\".\"+u[0]),d=i(['<div class=\"layui-unselect '+u[0]+(n.checked?\" \"+u[1]:\"\")+(c?\" layui-checkbox-disbaled \"+r:\"\")+'\">',{_switch:\"<i></i>\"}[s]||\"<span>\"+(n.title||\"勾选\")+'</span><i class=\"layui-icon\">&#xe618;</i>',\"</div>\"].join(\"\"));o[0]&&o.remove(),l.after(d),t.call(this,d,u)})},radio:function(){var e=\"layui-form-radio\",a=[\"&#xe643;\",\"&#xe63f;\"],t=i(s).find(\"input[type=radio]\"),n=function(t){var n=i(this),c=\"layui-anim-scaleSpring\";t.on(\"click\",function(){var r=n[0].name,u=n.parents(s),o=n.attr(\"lay-filter\"),d=u.find(\"input[name=\"+r.replace(/(\\.|#|\\[|\\])/g,\"\\\\$1\")+\"]\");n[0].disabled||(layui.each(d,function(){var t=i(this).next(\".\"+e);this.checked=!1,t.removeClass(e+\"ed\"),t.find(\".layui-icon\").removeClass(c).html(a[1])}),n[0].checked=!0,t.addClass(e+\"ed\"),t.find(\".layui-icon\").addClass(c).html(a[0]),layui.event(l,\"radio(\"+o+\")\",{elem:n[0],value:n[0].value}))})};t.each(function(t,l){var s=i(this),c=s.next(\".\"+e),u=this.disabled,o=i(['<div class=\"layui-unselect '+e+(l.checked?\" \"+e+\"ed\":\"\")+(u?\" layui-radio-disbaled \"+r:\"\")+'\">','<i class=\"layui-anim layui-icon\">'+a[l.checked?0:1]+\"</i>\",\"<span>\"+(l.title||\"未命名\")+\"</span>\",\"</div>\"].join(\"\"));c[0]&&c.remove(),s.after(o),n.call(this,o)})}};return e?n[e]?n[e]():t.error(\"不支持的\"+e+\"表单渲染\"):layui.each(n,function(e,i){i()}),a};var o=function(){var e=i(this),t=d.config.verify,c=null,r=\"layui-form-danger\",u={},o=e.parents(s),f=o.find(\"*[lay-verify]\"),y=e.parents(\"form\")[0],v=o.find(\"input,select,textarea\"),h=e.attr(\"lay-filter\");return layui.each(f,function(e,l){var s=i(this),u=s.attr(\"lay-verify\"),o=\"\",d=s.val(),f=\"function\"==typeof t[u];if(s.removeClass(r),t[u]&&(f?o=t[u](d,l):!t[u][0].test(d)))return a.msg(o||t[u][1],{icon:5,shift:6}),n.android||n.ios||l.focus(),s.addClass(r),c=!0}),!c&&(layui.each(v,function(e,i){i.name&&(/^checkbox|radio$/.test(i.type)&&!i.checked||(u[i.name]=i.value))}),layui.event.call(this,l,\"submit(\"+h+\")\",{elem:this,form:y,field:u}))},d=new u,f=i(document);d.render(),f.on(\"reset\",s,function(){setTimeout(function(){d.render()},50)}),f.on(\"submit\",s,o).on(\"click\",\"*[lay-submit]\",o),e(l,function(e){return d.set(e)})});layui.define(\"jquery\",function(e){\"use strict\";var o=layui.jquery,a=layui.hint(),r=\"layui-tree-enter\",i=function(e){this.options=e},t={arrow:[\"&#xe623;\",\"&#xe625;\"],checkbox:[\"&#xe626;\",\"&#xe627;\"],radio:[\"&#xe62b;\",\"&#xe62a;\"],branch:[\"&#xe622;\",\"&#xe624;\"],leaf:\"&#xe621;\"};i.prototype.init=function(e){var o=this;e.addClass(\"layui-box layui-tree\"),o.options.skin&&e.addClass(\"layui-tree-skin-\"+o.options.skin),o.tree(e),o.on(e)},i.prototype.tree=function(e,a){var r=this,i=r.options,n=a||i.nodes;layui.each(n,function(a,n){var l=n.children&&n.children.length>0,c=o('<ul class=\"'+(n.spread?\"layui-show\":\"\")+'\"></ul>'),s=o([\"<li \"+(n.spread?'data-spread=\"'+n.spread+'\"':\"\")+\">\",function(){return l?'<i class=\"layui-icon layui-tree-spread\">'+(n.spread?t.arrow[1]:t.arrow[0])+\"</i>\":\"\"}(),function(){return i.check?'<i class=\"layui-icon layui-tree-check\">'+(\"checkbox\"===i.check?t.checkbox[0]:\"radio\"===i.check?t.radio[0]:\"\")+\"</i>\":\"\"}(),function(){return'<a href=\"'+(n.href||\"javascript:;\")+'\" '+(i.target&&n.href?'target=\"'+i.target+'\"':\"\")+\">\"+('<i class=\"layui-icon layui-tree-'+(l?\"branch\":\"leaf\")+'\">'+(l?n.spread?t.branch[1]:t.branch[0]:t.leaf)+\"</i>\")+(\"<cite>\"+(n.name||\"未命名\")+\"</cite></a>\")}(),\"</li>\"].join(\"\"));l&&(s.append(c),r.tree(c,n.children)),e.append(s),\"function\"==typeof i.click&&r.click(s,n),r.spread(s,n),i.drag&&r.drag(s,n)})},i.prototype.click=function(e,o){var a=this,r=a.options;e.children(\"a\").on(\"click\",function(e){layui.stope(e),r.click(o)})},i.prototype.spread=function(e,o){var a=this,r=(a.options,e.children(\".layui-tree-spread\")),i=e.children(\"ul\"),n=e.children(\"a\"),l=function(){e.data(\"spread\")?(e.data(\"spread\",null),i.removeClass(\"layui-show\"),r.html(t.arrow[0]),n.find(\".layui-icon\").html(t.branch[0])):(e.data(\"spread\",!0),i.addClass(\"layui-show\"),r.html(t.arrow[1]),n.find(\".layui-icon\").html(t.branch[1]))};i[0]&&(r.on(\"click\",l),n.on(\"dblclick\",l))},i.prototype.on=function(e){var a=this,i=a.options,t=\"layui-tree-drag\";e.find(\"i\").on(\"selectstart\",function(e){return!1}),i.drag&&o(document).on(\"mousemove\",function(e){var r=a.move;if(r.from){var i=(r.to,o('<div class=\"layui-box '+t+'\"></div>'));e.preventDefault(),o(\".\"+t)[0]||o(\"body\").append(i);var n=o(\".\"+t)[0]?o(\".\"+t):i;n.addClass(\"layui-show\").html(r.from.elem.children(\"a\").html()),n.css({left:e.pageX+10,top:e.pageY+10})}}).on(\"mouseup\",function(){var e=a.move;e.from&&(e.from.elem.children(\"a\").removeClass(r),e.to&&e.to.elem.children(\"a\").removeClass(r),a.move={},o(\".\"+t).remove())})},i.prototype.move={},i.prototype.drag=function(e,a){var i=this,t=(i.options,e.children(\"a\")),n=function(){var t=o(this),n=i.move;n.from&&(n.to={item:a,elem:e},t.addClass(r))};t.on(\"mousedown\",function(){var o=i.move;o.from={item:a,elem:e}}),t.on(\"mouseenter\",n).on(\"mousemove\",n).on(\"mouseleave\",function(){var e=o(this),a=i.move;a.from&&(delete a.to,e.removeClass(r))})},e(\"tree\",function(e){var r=new i(e=e||{}),t=o(e.elem);return t[0]?void r.init(t):a.error(\"layui.tree 没有找到\"+e.elem+\"元素\")})});layui.define(\"jquery\",function(l){\"use strict\";var o=layui.jquery,i={fixbar:function(l){l=l||{},l.bgcolor=l.bgcolor?\"background-color:\"+l.bgcolor:\"\";var i,a,c=\"layui-fixbar-top\",t=[l.bar1===!0?\"&#xe606;\":l.bar1,l.bar2===!0?\"&#xe607;\":l.bar2,\"&#xe604;\"],r=o(['<ul class=\"layui-fixbar\">',l.bar1?'<li class=\"layui-icon\" lay-type=\"bar1\" style=\"'+l.bgcolor+'\">'+t[0]+\"</li>\":\"\",l.bar2?'<li class=\"layui-icon\" lay-type=\"bar2\" style=\"'+l.bgcolor+'\">'+t[1]+\"</li>\":\"\",'<li class=\"layui-icon '+c+'\" lay-type=\"top\" style=\"'+l.bgcolor+'\">'+t[2]+\"</li>\",\"</ul>\"].join(\"\")),e=r.find(\".\"+c),s=function(){var i=o(document).scrollTop();i>=(l.showHeight||200)?a||(e.show(),a=1):a&&(e.hide(),a=0)};o(\".layui-fixbar\")[0]||(\"object\"==typeof l.css&&r.css(l.css),o(\"body\").append(r),s(),r.find(\"li\").on(\"click\",function(){var i=o(this),a=i.attr(\"lay-type\");\"top\"===a&&o(\"html,body\").animate({scrollTop:0},200),l.click&&l.click.call(this,a)}),o(document).on(\"scroll\",function(){i&&clearTimeout(i),i=setTimeout(function(){s()},100)}))}};l(\"util\",i)});layui.define(\"jquery\",function(e){\"use strict\";var l=layui.jquery,o=function(e){},t='<i class=\"layui-anim layui-anim-rotate layui-anim-loop layui-icon \">&#xe63e;</i>';o.prototype.load=function(e){var o,i,n,r,a=this,c=0;e=e||{};var u=l(e.elem);if(u[0]){var f=l(e.scrollElem||document),m=e.mb||50,s=!(\"isAuto\"in e)||e.isAuto,y=e.end||\"没有更多了\",v=e.scrollElem&&e.scrollElem!==document,d=\"<cite>加载更多</cite>\",h=l('<div class=\"layui-flow-more\"><a href=\"javascript:;\">'+d+\"</a></div>\");u.find(\".layui-flow-more\")[0]||u.append(h);var p=function(e,t){e=l(e),h.before(e),t=0==t||null,t?h.html(y):h.find(\"a\").html(d),i=t,o=null,n&&n()},g=function(){o=!0,h.find(\"a\").html(t),\"function\"==typeof e.done&&e.done(++c,p)};if(g(),h.find(\"a\").on(\"click\",function(){l(this);i||o||g()}),e.isLazyimg)var n=a.lazyimg({elem:e.elem+\" img\",scrollElem:e.scrollElem});return s?(f.on(\"scroll\",function(){var e=l(this),t=e.scrollTop();r&&clearTimeout(r),i||(r=setTimeout(function(){var i=v?e.height():l(window).height(),n=v?e.prop(\"scrollHeight\"):document.documentElement.scrollHeight;n-t-i<=m&&(o||g())},100))}),a):a}},o.prototype.lazyimg=function(e){var o,t=this,i=0;e=e||{};var n=l(e.scrollElem||document),r=e.elem||\"img\",a=e.scrollElem&&e.scrollElem!==document,c=function(e,l){var o=n.scrollTop(),r=o+l,c=a?function(){return e.offset().top-n.offset().top+o}():e.offset().top;if(c>=o&&c<=r&&!e.attr(\"src\")){var f=e.attr(\"lay-src\");layui.img(f,function(){var l=t.lazyimg.elem.eq(i);e.attr(\"src\",f).removeAttr(\"lay-src\"),l[0]&&u(l),i++})}},u=function(e,o){var u=a?(o||n).height():l(window).height(),f=n.scrollTop(),m=f+u;if(t.lazyimg.elem=l(r),e)c(e,u);else for(var s=0;s<t.lazyimg.elem.length;s++){var y=t.lazyimg.elem.eq(s),v=a?function(){return y.offset().top-n.offset().top+f}():y.offset().top;if(c(y,u),i=s,v>m)break}};if(u(),!o){var f;n.on(\"scroll\",function(){var e=l(this);f&&clearTimeout(f),f=setTimeout(function(){u(null,e)},50)}),o=!0}return u},e(\"flow\",new o)});layui.define([\"layer\",\"form\"],function(t){\"use strict\";var e=layui.jquery,i=layui.layer,a=layui.form(),l=(layui.hint(),layui.device()),n=\"layedit\",o=\"layui-show\",r=\"layui-disabled\",s=function(){var t=this;t.index=0,t.config={tool:[\"strong\",\"italic\",\"underline\",\"del\",\"|\",\"left\",\"center\",\"right\",\"|\",\"link\",\"unlink\",\"face\",\"image\"],hideTool:[],height:280}};s.prototype.set=function(t){var i=this;return e.extend(!0,i.config,t),i},s.prototype.on=function(t,e){return layui.onevent(n,t,e)},s.prototype.build=function(t,i){i=i||{};var a=this,n=a.config,r=\"layui-layedit\",s=e(\"#\"+t),u=\"LAY_layedit_\"+ ++a.index,d=s.next(\".\"+r),y=e.extend({},n,i),f=function(){var t=[],e={};return layui.each(y.hideTool,function(t,i){e[i]=!0}),layui.each(y.tool,function(i,a){C[a]&&!e[a]&&t.push(C[a])}),t.join(\"\")}(),m=e(['<div class=\"'+r+'\">','<div class=\"layui-unselect layui-layedit-tool\">'+f+\"</div>\",'<div class=\"layui-layedit-iframe\">','<iframe id=\"'+u+'\" name=\"'+u+'\" textarea=\"'+t+'\" frameborder=\"0\"></iframe>',\"</div>\",\"</div>\"].join(\"\"));return l.ie&&l.ie<8?s.removeClass(\"layui-hide\").addClass(o):(d[0]&&d.remove(),c.call(a,m,s[0],y),s.addClass(\"layui-hide\").after(m),a.index)},s.prototype.getContent=function(t){var e=u(t);if(e[0])return d(e[0].document.body.innerHTML)},s.prototype.getText=function(t){var i=u(t);if(i[0])return e(i[0].document.body).text()},s.prototype.sync=function(t){var i=u(t);if(i[0]){var a=e(\"#\"+i[1].attr(\"textarea\"));a.val(d(i[0].document.body.innerHTML))}},s.prototype.getSelection=function(t){var e=u(t);if(e[0]){var i=m(e[0].document);return document.selection?i.text:i.toString()}};var c=function(t,i,a){var l=this,n=t.find(\"iframe\");n.css({height:a.height}).on(\"load\",function(){var o=n.contents(),r=n.prop(\"contentWindow\"),s=o.find(\"head\"),c=e([\"<style>\",\"*{margin: 0; padding: 0;}\",\"body{padding: 10px; line-height: 20px; overflow-x: hidden; word-wrap: break-word; font: 14px Helvetica Neue,Helvetica,PingFang SC,Microsoft YaHei,Tahoma,Arial,sans-serif; -webkit-box-sizing: border-box !important; -moz-box-sizing: border-box !important; box-sizing: border-box !important;}\",\"a{color:#01AAED; text-decoration:none;}a:hover{color:#c00}\",\"p{margin-bottom: 10px;}\",\"img{display: inline-block; border: none; vertical-align: middle;}\",\"pre{margin: 10px 0; padding: 10px; line-height: 20px; border: 1px solid #ddd; border-left-width: 6px; background-color: #F2F2F2; color: #333; font-family: Courier New; font-size: 12px;}\",\"</style>\"].join(\"\")),u=o.find(\"body\");s.append(c),u.attr(\"contenteditable\",\"true\").css({\"min-height\":a.height}).html(i.value||\"\"),y.apply(l,[r,n,i,a]),g.call(l,r,t,a)})},u=function(t){var i=e(\"#LAY_layedit_\"+t),a=i.prop(\"contentWindow\");return[a,i]},d=function(t){return 8==l.ie&&(t=t.replace(/<.+>/g,function(t){return t.toLowerCase()})),t},y=function(t,a,n,o){var r=t.document,s=e(r.body);s.on(\"keydown\",function(t){var e=t.keyCode;if(13===e){var a=m(r),l=p(a),n=l.parentNode;if(\"pre\"===n.tagName.toLowerCase()){if(t.shiftKey)return;return i.msg(\"请暂时用shift+enter\"),!1}r.execCommand(\"formatBlock\",!1,\"<p>\")}}),e(n).parents(\"form\").on(\"submit\",function(){var t=s.html();8==l.ie&&(t=t.replace(/<.+>/g,function(t){return t.toLowerCase()})),n.value=t}),s.on(\"paste\",function(e){r.execCommand(\"formatBlock\",!1,\"<p>\"),setTimeout(function(){f.call(t,s),n.value=s.html()},100)})},f=function(t){var i=this;i.document;t.find(\"*[style]\").each(function(){var t=this.style.textAlign;this.removeAttribute(\"style\"),e(this).css({\"text-align\":t||\"\"})}),t.find(\"table\").addClass(\"layui-table\"),t.find(\"script,link\").remove()},m=function(t){return t.selection?t.selection.createRange():t.getSelection().getRangeAt(0)},p=function(t){return t.endContainer||t.parentElement().childNodes[0]},v=function(t,i,a){var l=this.document,n=document.createElement(t);for(var o in i)n.setAttribute(o,i[o]);if(n.removeAttribute(\"text\"),l.selection){var r=a.text||i.text;if(\"a\"===t&&!r)return;r&&(n.innerHTML=r),a.pasteHTML(e(n).prop(\"outerHTML\")),a.select()}else{var r=a.toString()||i.text;if(\"a\"===t&&!r)return;r&&(n.innerHTML=r),a.deleteContents(),a.insertNode(n)}},h=function(t,i){var a=this.document,l=\"layedit-tool-active\",n=p(m(a)),o=function(e){return t.find(\".layedit-tool-\"+e)};i&&i[i.hasClass(l)?\"removeClass\":\"addClass\"](l),t.find(\">i\").removeClass(l),o(\"unlink\").addClass(r),e(n).parents().each(function(){var t=this.tagName.toLowerCase(),e=this.style.textAlign;\"b\"!==t&&\"strong\"!==t||o(\"b\").addClass(l),\"i\"!==t&&\"em\"!==t||o(\"i\").addClass(l),\"u\"===t&&o(\"u\").addClass(l),\"strike\"===t&&o(\"d\").addClass(l),\"p\"===t&&(\"center\"===e?o(\"center\").addClass(l):\"right\"===e?o(\"right\").addClass(l):o(\"left\").addClass(l)),\"a\"===t&&(o(\"link\").addClass(l),o(\"unlink\").removeClass(r))})},g=function(t,a,l){var n=t.document,o=e(n.body),s={link:function(i){var a=p(i),l=e(a).parent();b.call(o,{href:l.attr(\"href\"),target:l.attr(\"target\")},function(e){var a=l[0];\"A\"===a.tagName?a.href=e.url:v.call(t,\"a\",{target:e.target,href:e.url,text:e.url},i)})},unlink:function(t){n.execCommand(\"unlink\")},face:function(e){x.call(this,function(i){v.call(t,\"img\",{src:i.src,alt:i.alt},e)})},image:function(a){var n=this;layui.use(\"upload\",function(o){var r=l.uploadImage||{};o({url:r.url,method:r.type,elem:e(n).find(\"input\")[0],unwrap:!0,success:function(e){0==e.code?(e.data=e.data||{},v.call(t,\"img\",{src:e.data.src,alt:e.data.title},a)):i.msg(e.msg||\"上传失败\")}})})},code:function(e){k.call(o,function(i){v.call(t,\"pre\",{text:i.code,\"lay-lang\":i.lang},e)})},help:function(){i.open({type:2,title:\"帮助\",area:[\"600px\",\"380px\"],shadeClose:!0,shade:.1,skin:\"layui-layer-msg\",content:[\"http://www.layui.com/about/layedit/help.html\",\"no\"]})}},c=a.find(\".layui-layedit-tool\"),u=function(){var i=e(this),a=i.attr(\"layedit-event\"),l=i.attr(\"lay-command\");if(!i.hasClass(r)){o.focus();var u=m(n);u.commonAncestorContainer;l?(n.execCommand(l),/justifyLeft|justifyCenter|justifyRight/.test(l)&&n.execCommand(\"formatBlock\",!1,\"<p>\"),setTimeout(function(){o.focus()},10)):s[a]&&s[a].call(this,u),h.call(t,c,i)}},d=/image/;c.find(\">i\").on(\"mousedown\",function(){var t=e(this),i=t.attr(\"layedit-event\");d.test(i)||u.call(this)}).on(\"click\",function(){var t=e(this),i=t.attr(\"layedit-event\");d.test(i)&&u.call(this)}),o.on(\"click\",function(){h.call(t,c),i.close(x.index)})},b=function(t,e){var l=this,n=i.open({type:1,id:\"LAY_layedit_link\",area:\"350px\",shade:.05,shadeClose:!0,moveType:1,title:\"超链接\",skin:\"layui-layer-msg\",content:['<ul class=\"layui-form\" style=\"margin: 15px;\">','<li class=\"layui-form-item\">','<label class=\"layui-form-label\" style=\"width: 60px;\">URL</label>','<div class=\"layui-input-block\" style=\"margin-left: 90px\">','<input name=\"url\" lay-verify=\"url\" value=\"'+(t.href||\"\")+'\" autofocus=\"true\" autocomplete=\"off\" class=\"layui-input\">',\"</div>\",\"</li>\",'<li class=\"layui-form-item\">','<label class=\"layui-form-label\" style=\"width: 60px;\">打开方式</label>','<div class=\"layui-input-block\" style=\"margin-left: 90px\">','<input type=\"radio\" name=\"target\" value=\"_self\" class=\"layui-input\" title=\"当前窗口\"'+(\"_self\"!==t.target&&t.target?\"\":\"checked\")+\">\",'<input type=\"radio\" name=\"target\" value=\"_blank\" class=\"layui-input\" title=\"新窗口\" '+(\"_blank\"===t.target?\"checked\":\"\")+\">\",\"</div>\",\"</li>\",'<li class=\"layui-form-item\" style=\"text-align: center;\">','<button type=\"button\" lay-submit lay-filter=\"layedit-link-yes\" class=\"layui-btn\"> 确定 </button>','<button style=\"margin-left: 20px;\" type=\"button\" class=\"layui-btn layui-btn-primary\"> 取消 </button>',\"</li>\",\"</ul>\"].join(\"\"),success:function(t,n){var o=\"submit(layedit-link-yes)\";a.render(\"radio\"),t.find(\".layui-btn-primary\").on(\"click\",function(){i.close(n),l.focus()}),a.on(o,function(t){i.close(b.index),e&&e(t.field)})}});b.index=n},x=function(t){var a=function(){var t=[\"[微笑]\",\"[嘻嘻]\",\"[哈哈]\",\"[可爱]\",\"[可怜]\",\"[挖鼻]\",\"[吃惊]\",\"[害羞]\",\"[挤眼]\",\"[闭嘴]\",\"[鄙视]\",\"[爱你]\",\"[泪]\",\"[偷笑]\",\"[亲亲]\",\"[生病]\",\"[太开心]\",\"[白眼]\",\"[右哼哼]\",\"[左哼哼]\",\"[嘘]\",\"[衰]\",\"[委屈]\",\"[吐]\",\"[哈欠]\",\"[抱抱]\",\"[怒]\",\"[疑问]\",\"[馋嘴]\",\"[拜拜]\",\"[思考]\",\"[汗]\",\"[困]\",\"[睡]\",\"[钱]\",\"[失望]\",\"[酷]\",\"[色]\",\"[哼]\",\"[鼓掌]\",\"[晕]\",\"[悲伤]\",\"[抓狂]\",\"[黑线]\",\"[阴险]\",\"[怒骂]\",\"[互粉]\",\"[心]\",\"[伤心]\",\"[猪头]\",\"[熊猫]\",\"[兔子]\",\"[ok]\",\"[耶]\",\"[good]\",\"[NO]\",\"[赞]\",\"[来]\",\"[弱]\",\"[草泥马]\",\"[神马]\",\"[囧]\",\"[浮云]\",\"[给力]\",\"[围观]\",\"[威武]\",\"[奥特曼]\",\"[礼物]\",\"[钟]\",\"[话筒]\",\"[蜡烛]\",\"[蛋糕]\"],e={};return layui.each(t,function(t,i){e[i]=layui.cache.dir+\"images/face/\"+t+\".gif\"}),e}();return x.hide=x.hide||function(t){\"face\"!==e(t.target).attr(\"layedit-event\")&&i.close(x.index)},x.index=i.tips(function(){var t=[];return layui.each(a,function(e,i){t.push('<li title=\"'+e+'\"><img src=\"'+i+'\" alt=\"'+e+'\"></li>')}),'<ul class=\"layui-clear\">'+t.join(\"\")+\"</ul>\"}(),this,{tips:1,time:0,skin:\"layui-box layui-util-face\",maxWidth:500,success:function(l,n){l.css({marginTop:-4,marginLeft:-10}).find(\".layui-clear>li\").on(\"click\",function(){t&&t({src:a[this.title],alt:this.title}),i.close(n)}),e(document).off(\"click\",x.hide).on(\"click\",x.hide)}})},k=function(t){var e=this,l=i.open({type:1,id:\"LAY_layedit_code\",area:\"550px\",shade:.05,shadeClose:!0,moveType:1,title:\"插入代码\",skin:\"layui-layer-msg\",content:['<ul class=\"layui-form layui-form-pane\" style=\"margin: 15px;\">','<li class=\"layui-form-item\">','<label class=\"layui-form-label\">请选择语言</label>','<div class=\"layui-input-block\">','<select name=\"lang\">','<option value=\"JavaScript\">JavaScript</option>','<option value=\"HTML\">HTML</option>','<option value=\"CSS\">CSS</option>','<option value=\"Java\">Java</option>','<option value=\"PHP\">PHP</option>','<option value=\"C#\">C#</option>','<option value=\"Python\">Python</option>','<option value=\"Ruby\">Ruby</option>','<option value=\"Go\">Go</option>',\"</select>\",\"</div>\",\"</li>\",'<li class=\"layui-form-item layui-form-text\">','<label class=\"layui-form-label\">代码</label>','<div class=\"layui-input-block\">','<textarea name=\"code\" lay-verify=\"required\" autofocus=\"true\" class=\"layui-textarea\" style=\"height: 200px;\"></textarea>',\"</div>\",\"</li>\",'<li class=\"layui-form-item\" style=\"text-align: center;\">','<button type=\"button\" lay-submit lay-filter=\"layedit-code-yes\" class=\"layui-btn\"> 确定 </button>','<button style=\"margin-left: 20px;\" type=\"button\" class=\"layui-btn layui-btn-primary\"> 取消 </button>',\"</li>\",\"</ul>\"].join(\"\"),success:function(l,n){var o=\"submit(layedit-code-yes)\";a.render(\"select\"),l.find(\".layui-btn-primary\").on(\"click\",function(){i.close(n),e.focus()}),a.on(o,function(e){i.close(k.index),t&&t(e.field)})}});k.index=l},C={html:'<i class=\"layui-icon layedit-tool-html\" title=\"HTML源代码\" lay-command=\"html\" layedit-event=\"html\"\">&#xe64b;</i><span class=\"layedit-tool-mid\"></span>',strong:'<i class=\"layui-icon layedit-tool-b\" title=\"加粗\" lay-command=\"Bold\" layedit-event=\"b\"\">&#xe62b;</i>',italic:'<i class=\"layui-icon layedit-tool-i\" title=\"斜体\" lay-command=\"italic\" layedit-event=\"i\"\">&#xe644;</i>',underline:'<i class=\"layui-icon layedit-tool-u\" title=\"下划线\" lay-command=\"underline\" layedit-event=\"u\"\">&#xe646;</i>',del:'<i class=\"layui-icon layedit-tool-d\" title=\"删除线\" lay-command=\"strikeThrough\" layedit-event=\"d\"\">&#xe64f;</i>',\"|\":'<span class=\"layedit-tool-mid\"></span>',left:'<i class=\"layui-icon layedit-tool-left\" title=\"左对齐\" lay-command=\"justifyLeft\" layedit-event=\"left\"\">&#xe649;</i>',center:'<i class=\"layui-icon layedit-tool-center\" title=\"居中对齐\" lay-command=\"justifyCenter\" layedit-event=\"center\"\">&#xe647;</i>',right:'<i class=\"layui-icon layedit-tool-right\" title=\"右对齐\" lay-command=\"justifyRight\" layedit-event=\"right\"\">&#xe648;</i>',link:'<i class=\"layui-icon layedit-tool-link\" title=\"插入链接\" layedit-event=\"link\"\">&#xe64c;</i>',unlink:'<i class=\"layui-icon layedit-tool-unlink layui-disabled\" title=\"清除链接\" lay-command=\"unlink\" layedit-event=\"unlink\"\">&#xe64d;</i>',face:'<i class=\"layui-icon layedit-tool-face\" title=\"表情\" layedit-event=\"face\"\">&#xe650;</i>',image:'<i class=\"layui-icon layedit-tool-image\" title=\"图片\" layedit-event=\"image\">&#xe64a;<input type=\"file\" name=\"file\"></i>',code:'<i class=\"layui-icon layedit-tool-code\" title=\"插入代码\" layedit-event=\"code\">&#xe64e;</i>',help:'<i class=\"layui-icon layedit-tool-help\" title=\"帮助\" layedit-event=\"help\">&#xe607;</i>'},w=new s;t(n,w)});layui.define(\"jquery\",function(e){\"use strict\";var a=layui.jquery,l=\"http://www.layui.com/doc/modules/code.html\";e(\"code\",function(e){var t=[];e=e||{},e.elem=a(e.elem||\".layui-code\"),e.about=!(\"about\"in e)||e.about,e.elem.each(function(){t.push(this)}),layui.each(t.reverse(),function(t,i){var c=a(i),o=c.html();(c.attr(\"lay-encode\")||e.encode)&&(o=o.replace(/&(?!#?[a-zA-Z0-9]+;)/g,\"&amp;\").replace(/</g,\"&lt;\").replace(/>/g,\"&gt;\").replace(/'/g,\"&#39;\").replace(/\"/g,\"&quot;\")),c.html('<ol class=\"layui-code-ol\"><li>'+o.replace(/[\\r\\t\\n]+/g,\"</li><li>\")+\"</li></ol>\"),c.find(\">.layui-code-h3\")[0]||c.prepend('<h3 class=\"layui-code-h3\">'+(c.attr(\"lay-title\")||e.title||\"code\")+(e.about?'<a href=\"'+l+'\" target=\"_blank\">layui.code</a>':\"\")+\"</h3>\");var d=c.find(\">.layui-code-ol\");c.addClass(\"layui-box layui-code-view\"),(c.attr(\"lay-skin\")||e.skin)&&c.addClass(\"layui-code-\"+(c.attr(\"lay-skin\")||e.skin)),(d.find(\"li\").length/100|0)>0&&d.css(\"margin-left\",(d.find(\"li\").length/100|0)+\"px\"),(c.attr(\"lay-height\")||e.height)&&d.css(\"max-height\",c.attr(\"lay-height\")||e.height)})})}).addcss(\"modules/code.css\",\"skincodecss\");"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/plugins/layui/lay/dest/layui.mod.js",
    "content": "/** layui-v1.0.5(All Modules) LGPL-2.1 license By http://www.layui.com */\n ;layui.define(function(i){i(\"layui.mod\",layui.v)});layui.define(function(e){\"use strict\";var r={open:\"{{\",close:\"}}\"},n={exp:function(e){return new RegExp(e,\"g\")},query:function(e,n,t){var o=[\"#([\\\\s\\\\S])+?\",\"([^{#}])*?\"][e||0];return c((n||\"\")+r.open+o+r.close+(t||\"\"))},escape:function(e){return String(e||\"\").replace(/&(?!#?[a-zA-Z0-9]+;)/g,\"&amp;\").replace(/</g,\"&lt;\").replace(/>/g,\"&gt;\").replace(/'/g,\"&#39;\").replace(/\"/g,\"&quot;\")},error:function(e,r){var n=\"Laytpl Error：\";return\"object\"==typeof console&&console.error(n+e+\"\\n\"+(r||\"\")),n+e}},c=n.exp,t=function(e){this.tpl=e};t.pt=t.prototype,window.errors=0,t.pt.parse=function(e,t){var o=this,p=e,a=c(\"^\"+r.open+\"#\",\"\"),l=c(r.close+\"$\",\"\");e=e.replace(/\\s+|\\r|\\t|\\n/g,\" \").replace(c(r.open+\"#\"),r.open+\"# \").replace(c(r.close+\"}\"),\"} \"+r.close).replace(/\\\\/g,\"\\\\\\\\\").replace(/(?=\"|')/g,\"\\\\\").replace(n.query(),function(e){return e=e.replace(a,\"\").replace(l,\"\"),'\";'+e.replace(/\\\\/g,\"\")+';view+=\"'}).replace(n.query(1),function(e){var n='\"+(';return e.replace(/\\s/g,\"\")===r.open+r.close?\"\":(e=e.replace(c(r.open+\"|\"+r.close),\"\"),/^=/.test(e)&&(e=e.replace(/^=/,\"\"),n='\"+_escape_('),n+e.replace(/\\\\/g,\"\")+')+\"')}),e='\"use strict\";var view = \"'+e+'\";return view;';try{return o.cache=e=new Function(\"d, _escape_\",e),e(t,n.escape)}catch(u){return delete o.cache,n.error(u,p)}},t.pt.render=function(e,r){var c,t=this;return e?(c=t.cache?t.cache(e,n.escape):t.parse(t.tpl,e),r?void r(c):c):n.error(\"no data\")};var o=function(e){return\"string\"!=typeof e?n.error(\"Template not found\"):new t(e)};o.config=function(e){e=e||{};for(var n in e)r[n]=e[n]},o.v=\"1.2.0\",e(\"laytpl\",o)});layui.define(function(a){\"use strict\";function t(a){new p(a)}var e=document,r=\"getElementById\",n=\"getElementsByTagName\",s=0,p=function(a){var t=this,e=t.config=a||{};e.item=s++,t.render(!0)};p.on=function(a,t,e){return a.attachEvent?a.attachEvent(\"on\"+t,function(){e.call(a,window.even)}):a.addEventListener(t,e,!1),p},p.prototype.type=function(){var a=this.config;if(\"object\"==typeof a.cont)return void 0===a.cont.length?2:3},p.prototype.view=function(){var a=this,t=a.config,e=[],r={};if(t.pages=0|t.pages,t.curr=0|t.curr||1,t.groups=\"groups\"in t?0|t.groups:5,t.first=\"first\"in t?t.first:\"&#x9996;&#x9875;\",t.last=\"last\"in t?t.last:\"&#x672B;&#x9875;\",t.prev=\"prev\"in t?t.prev:\"&#x4E0A;&#x4E00;&#x9875;\",t.next=\"next\"in t?t.next:\"&#x4E0B;&#x4E00;&#x9875;\",t.pages<=1)return\"\";for(t.groups>t.pages&&(t.groups=t.pages),r.index=Math.ceil((t.curr+(t.groups>1&&t.groups!==t.pages?1:0))/(0===t.groups?1:t.groups)),t.curr>1&&t.prev&&e.push('<a href=\"javascript:;\" class=\"layui-laypage-prev\" data-page=\"'+(t.curr-1)+'\">'+t.prev+\"</a>\"),r.index>1&&t.first&&0!==t.groups&&e.push('<a href=\"javascript:;\" class=\"laypage_first\" data-page=\"1\"  title=\"&#x9996;&#x9875;\">'+t.first+\"</a><span>&#x2026;</span>\"),r.poor=Math.floor((t.groups-1)/2),r.start=r.index>1?t.curr-r.poor:1,r.end=r.index>1?function(){var a=t.curr+(t.groups-r.poor-1);return a>t.pages?t.pages:a}():t.groups,r.end-r.start<t.groups-1&&(r.start=r.end-t.groups+1);r.start<=r.end;r.start++)r.start===t.curr?e.push('<span class=\"layui-laypage-curr\"><em class=\"layui-laypage-em\" '+(/^#/.test(t.skin)?'style=\"background-color:'+t.skin+';\"':\"\")+\"></em><em>\"+r.start+\"</em></span>\"):e.push('<a href=\"javascript:;\" data-page=\"'+r.start+'\">'+r.start+\"</a>\");return t.pages>t.groups&&r.end<t.pages&&t.last&&0!==t.groups&&e.push('<span>&#x2026;</span><a href=\"javascript:;\" class=\"layui-laypage-last\" title=\"&#x5C3E;&#x9875;\"  data-page=\"'+t.pages+'\">'+t.last+\"</a>\"),r.flow=!t.prev&&0===t.groups,(t.curr!==t.pages&&t.next||r.flow)&&e.push(function(){return r.flow&&t.curr===t.pages?'<span class=\"layui-laypage-nomore\" title=\"&#x5DF2;&#x6CA1;&#x6709;&#x66F4;&#x591A;\">'+t.next+\"</span>\":'<a href=\"javascript:;\" class=\"layui-laypage-next\" data-page=\"'+(t.curr+1)+'\">'+t.next+\"</a>\"}()),'<div class=\"layui-box layui-laypage layui-laypage-'+(t.skin?function(a){return/^#/.test(a)?\"molv\":a}(t.skin):\"default\")+'\" id=\"layui-laypage-'+a.config.item+'\">'+e.join(\"\")+function(){return t.skip?'<span class=\"layui-laypage-total\">&#x5230;&#x7B2C; <input type=\"number\" min=\"1\" onkeyup=\"this.value=this.value.replace(/\\\\D/, \\'\\');\" value=\"'+t.curr+'\" class=\"layui-laypage-skip\"> &#x9875; <button type=\"button\" class=\"layui-laypage-btn\">&#x786e;&#x5b9a;</button></span>':\"\"}()+\"</div>\"},p.prototype.jump=function(a){if(a){for(var t=this,e=t.config,r=a.children,s=a[n](\"button\")[0],i=a[n](\"input\")[0],u=0,o=r.length;u<o;u++)\"a\"===r[u].nodeName.toLowerCase()&&p.on(r[u],\"click\",function(){var a=0|this.getAttribute(\"data-page\");e.curr=a,t.render()});s&&p.on(s,\"click\",function(){var a=0|i.value.replace(/\\s|\\D/g,\"\");a&&a<=e.pages&&(e.curr=a,t.render())})}},p.prototype.render=function(a){var t=this,n=t.config,s=t.type(),p=t.view();2===s?n.cont.innerHTML=p:3===s?n.cont.html(p):e[r](n.cont).innerHTML=p,n.jump&&n.jump(n,a),t.jump(e[r](\"layui-laypage-\"+n.item)),n.hash&&!a&&(location.hash=\"!\"+n.hash+\"=\"+n.curr)},a(\"laypage\",t)});layui.define(function(e){\"use strict\";var t=window,a={path:\"\",skin:\"default\",format:\"YYYY-MM-DD\",min:\"1900-01-01 00:00:00\",max:\"2099-12-31 23:59:59\",isv:!1,init:!0},n={},s=document,i=\"createElement\",o=\"getElementById\",l=\"getElementsByTagName\",d=[\"laydate_box\",\"laydate_void\",\"laydate_click\",\"LayDateSkin\",\"skins/\",\"/laydate.css\"];t.laydate=function(e){return e=e||{},n.run(e),laydate},laydate.v=\"1.1\",n.trim=function(e){return e=e||\"\",e.replace(/^\\s|\\s$/g,\"\").replace(/\\s+/g,\" \")},n.digit=function(e){return e<10?\"0\"+(0|e):e},n.stopmp=function(e){return e=e||t.event,e.stopPropagation?e.stopPropagation():e.cancelBubble=!0,this},n.each=function(e,t){for(var a=0,n=e.length;a<n&&t(a,e[a])!==!1;a++);},n.hasClass=function(e,t){return e=e||{},new RegExp(\"\\\\b\"+t+\"\\\\b\").test(e.className)},n.addClass=function(e,t){return e=e||{},n.hasClass(e,t)||(e.className+=\" \"+t),e.className=n.trim(e.className),this},n.removeClass=function(e,t){if(e=e||{},n.hasClass(e,t)){var a=new RegExp(\"\\\\b\"+t+\"\\\\b\");e.className=e.className.replace(a,\"\")}return this},n.removeCssAttr=function(e,t){var a=e.style;a.removeProperty?a.removeProperty(t):a.removeAttribute(t)},n.shde=function(e,t){e.style.display=t?\"none\":\"block\"},n.query=function(e){if(e&&1===e.nodeType){if(\"input\"!==e.tagName.toLowerCase())throw new Error(\"选择器elem错误\");return e}var t,e=n.trim(e).split(\" \"),a=s[o](e[0].substr(1));if(a){if(e[1]){if(/^\\./.test(e[1])){var i,d=e[1].substr(1),r=new RegExp(\"\\\\b\"+d+\"\\\\b\");return t=[],i=s.getElementsByClassName?a.getElementsByClassName(d):a[l](\"*\"),n.each(i,function(e,a){r.test(a.className)&&t.push(a)}),t[0]?t:\"\"}return t=a[l](e[1]),t[0]?a[l](e[1]):\"\"}return a}},n.on=function(e,a,s){return e.attachEvent?e.attachEvent(\"on\"+a,function(){s.call(e,t.even)}):e.addEventListener(a,s,!1),n},n.stopMosup=function(e,t){\"mouseup\"!==e&&n.on(t,\"mouseup\",function(e){n.stopmp(e)})},n.run=function(e){var t=(n.query,e.elem);t&&(d.elemv=/textarea|input/.test(t.tagName.toLocaleLowerCase())?\"value\":\"innerHTML\",(\"init\"in e?e.init:a.init)&&!t[d.elemv]&&(t[d.elemv]=laydate.now(null,e.format||a.format)),n.view(t,e),n.reshow())},n.scroll=function(e){return e=e?\"scrollLeft\":\"scrollTop\",s.body[e]|s.documentElement[e]},n.winarea=function(e){return document.documentElement[e?\"clientWidth\":\"clientHeight\"]},n.isleap=function(e){return e%4===0&&e%100!==0||e%400===0},n.checkVoid=function(e,t,a){var s=[];return e=0|e,t=0|t,a=0|a,e<n.mins[0]?s=[\"y\"]:e>n.maxs[0]?s=[\"y\",1]:e>=n.mins[0]&&e<=n.maxs[0]&&(e==n.mins[0]&&(t<n.mins[1]?s=[\"m\"]:t==n.mins[1]&&a<n.mins[2]&&(s=[\"d\"])),e==n.maxs[0]&&(t>n.maxs[1]?s=[\"m\",1]:t==n.maxs[1]&&a>n.maxs[2]&&(s=[\"d\",1]))),s},n.timeVoid=function(e,t){if(n.ymd[1]+1==n.mins[1]&&n.ymd[2]==n.mins[2]){if(0===t&&e<n.mins[3])return 1;if(1===t&&e<n.mins[4])return 1;if(2===t&&e<n.mins[5])return 1}else if(n.ymd[1]+1==n.maxs[1]&&n.ymd[2]==n.maxs[2]){if(0===t&&e>n.maxs[3])return 1;if(1===t&&e>n.maxs[4])return 1;if(2===t&&e>n.maxs[5])return 1}if(e>(t?59:23))return 1},n.check=function(){var e=n.options.format.replace(/YYYY|MM|DD|hh|mm|ss/g,\"\\\\d+\\\\\").replace(/\\\\$/g,\"\"),t=new RegExp(e),a=n.elem[d.elemv],s=a.match(/\\d+/g)||[],i=n.checkVoid(s[0],s[1],s[2]);if(\"\"!==a.replace(/\\s/g,\"\")){if(!t.test(a))return n.elem[d.elemv]=\"\",n.msg(\"日期不符合格式，请重新选择。\"),1;if(i[0])return n.elem[d.elemv]=\"\",n.msg(\"日期不在有效期内，请重新选择。\"),1;i.value=n.elem[d.elemv].match(t).join(),s=i.value.match(/\\d+/g),s[1]<1?(s[1]=1,i.auto=1):s[1]>12?(s[1]=12,i.auto=1):s[1].length<2&&(i.auto=1),s[2]<1?(s[2]=1,i.auto=1):s[2]>n.months[(0|s[1])-1]?(s[2]=31,i.auto=1):s[2].length<2&&(i.auto=1),s.length>3&&(n.timeVoid(s[3],0)&&(i.auto=1),n.timeVoid(s[4],1)&&(i.auto=1),n.timeVoid(s[5],2)&&(i.auto=1)),i.auto?n.creation([s[0],0|s[1],0|s[2]],1):i.value!==n.elem[d.elemv]&&(n.elem[d.elemv]=i.value)}},n.months=[31,null,31,30,31,30,31,31,30,31,30,31],n.viewDate=function(e,t,a){var s=(n.query,{}),i=new Date;e<(0|n.mins[0])&&(e=0|n.mins[0]),e>(0|n.maxs[0])&&(e=0|n.maxs[0]),i.setFullYear(e,t,a),s.ymd=[i.getFullYear(),i.getMonth(),i.getDate()],n.months[1]=n.isleap(s.ymd[0])?29:28,i.setFullYear(s.ymd[0],s.ymd[1],1),s.FDay=i.getDay(),s.PDay=n.months[0===t?11:t-1]-s.FDay+1,s.NDay=1,n.each(d.tds,function(e,t){var a,i=s.ymd[0],o=s.ymd[1]+1;t.className=\"\",e<s.FDay?(t.innerHTML=a=e+s.PDay,n.addClass(t,\"laydate_nothis\"),1===o&&(i-=1),o=1===o?12:o-1):e>=s.FDay&&e<s.FDay+n.months[s.ymd[1]]?(t.innerHTML=a=e-s.FDay+1,e-s.FDay+1===s.ymd[2]&&(n.addClass(t,d[2]),s.thisDay=t)):(t.innerHTML=a=s.NDay++,n.addClass(t,\"laydate_nothis\"),12===o&&(i+=1),o=12===o?1:o+1),n.checkVoid(i,o,a)[0]&&n.addClass(t,d[1]),n.options.festival&&n.festival(t,o+\".\"+a),t.setAttribute(\"y\",i),t.setAttribute(\"m\",o),t.setAttribute(\"d\",a),i=o=a=null}),n.valid=!n.hasClass(s.thisDay,d[1]),n.ymd=s.ymd,d.year.value=n.ymd[0]+\"年\",d.month.value=n.digit(n.ymd[1]+1)+\"月\",n.each(d.mms,function(e,t){var a=n.checkVoid(n.ymd[0],(0|t.getAttribute(\"m\"))+1);\"y\"===a[0]||\"m\"===a[0]?n.addClass(t,d[1]):n.removeClass(t,d[1]),n.removeClass(t,d[2]),a=null}),n.addClass(d.mms[n.ymd[1]],d[2]),s.times=[0|n.inymd[3]||0,0|n.inymd[4]||0,0|n.inymd[5]||0],n.each(new Array(3),function(e){n.hmsin[e].value=n.digit(n.timeVoid(s.times[e],e)?0|n.mins[e+3]:0|s.times[e])}),n[n.valid?\"removeClass\":\"addClass\"](d.ok,d[1])},n.festival=function(e,t){var a;switch(t){case\"1.1\":a=\"元旦\";break;case\"3.8\":a=\"妇女\";break;case\"4.5\":a=\"清明\";break;case\"5.1\":a=\"劳动\";break;case\"6.1\":a=\"儿童\";break;case\"9.10\":a=\"教师\";break;case\"10.1\":a=\"国庆\"}a&&(e.innerHTML=a),a=null},n.viewYears=function(e){var t=n.query,a=\"\";n.each(new Array(14),function(t){a+=7===t?\"<li \"+(parseInt(d.year.value)===e?'class=\"'+d[2]+'\"':\"\")+' y=\"'+e+'\">'+e+\"年</li>\":'<li y=\"'+(e-7+t)+'\">'+(e-7+t)+\"年</li>\"}),t(\"#laydate_ys\").innerHTML=a,n.each(t(\"#laydate_ys li\"),function(e,t){\"y\"===n.checkVoid(t.getAttribute(\"y\"))[0]?n.addClass(t,d[1]):n.on(t,\"click\",function(e){n.stopmp(e).reshow(),n.viewDate(0|this.getAttribute(\"y\"),n.ymd[1],n.ymd[2])})})},n.initDate=function(){var e=(n.query,new Date),t=n.elem[d.elemv].match(/\\d+/g)||[];t.length<3&&(t=n.options.start.match(/\\d+/g)||[],t.length<3&&(t=[e.getFullYear(),e.getMonth()+1,e.getDate()])),n.inymd=t,n.viewDate(t[0],t[1]-1,t[2])},n.iswrite=function(){var e=n.query,t={time:e(\"#laydate_hms\")};n.shde(t.time,!n.options.istime),n.shde(d.oclear,!(\"isclear\"in n.options?n.options.isclear:1)),n.shde(d.otoday,!(\"istoday\"in n.options?n.options.istoday:1)),n.shde(d.ok,!(\"issure\"in n.options?n.options.issure:1))},n.orien=function(e,t){var a,s=n.elem.getBoundingClientRect();e.style.left=s.left+(t?0:n.scroll(1))+\"px\",a=s.bottom+e.offsetHeight/1.5<=n.winarea()?s.bottom-1:s.top>e.offsetHeight/1.5?s.top-e.offsetHeight+1:n.winarea()-e.offsetHeight,e.style.top=Math.max(a+(t?0:n.scroll()),1)+\"px\"},n.follow=function(e){n.options.fixed?(e.style.position=\"fixed\",n.orien(e,1)):(e.style.position=\"absolute\",n.orien(e))},n.viewtb=function(){var e,t=[],a=[\"日\",\"一\",\"二\",\"三\",\"四\",\"五\",\"六\"],o={},d=s[i](\"table\"),r=s[i](\"thead\");return r.appendChild(s[i](\"tr\")),o.creath=function(e){var t=s[i](\"th\");t.innerHTML=a[e],r[l](\"tr\")[0].appendChild(t),t=null},n.each(new Array(6),function(a){t.push([]),e=d.insertRow(0),n.each(new Array(7),function(n){t[a][n]=0,0===a&&o.creath(n),e.insertCell(n)})}),d.insertBefore(r,d.children[0]),d.id=d.className=\"laydate_table\",e=t=null,d.outerHTML.toLowerCase()}(),n.view=function(e,t){var o,l=n.query,r={};t=t||e,n.elem=e,n.options=t,n.options.format||(n.options.format=a.format),n.options.start=n.options.start||\"\",n.mm=r.mm=[n.options.min||a.min,n.options.max||a.max],n.mins=r.mm[0].match(/\\d+/g),n.maxs=r.mm[1].match(/\\d+/g),n.box?n.shde(n.box):(o=s[i](\"div\"),o.id=d[0],o.className=d[0],o.style.cssText=\"position: absolute;\",o.setAttribute(\"name\",\"laydate-v\"+laydate.v),o.innerHTML=r.html='<div class=\"laydate_top\"><div class=\"laydate_ym laydate_y\" id=\"laydate_YY\"><a class=\"laydate_choose laydate_chprev laydate_tab\"><cite></cite></a><input id=\"laydate_y\" readonly><label></label><a class=\"laydate_choose laydate_chnext laydate_tab\"><cite></cite></a><div class=\"laydate_yms\"><a class=\"laydate_tab laydate_chtop\"><cite></cite></a><ul id=\"laydate_ys\"></ul><a class=\"laydate_tab laydate_chdown\"><cite></cite></a></div></div><div class=\"laydate_ym laydate_m\" id=\"laydate_MM\"><a class=\"laydate_choose laydate_chprev laydate_tab\"><cite></cite></a><input id=\"laydate_m\" readonly><label></label><a class=\"laydate_choose laydate_chnext laydate_tab\"><cite></cite></a><div class=\"laydate_yms\" id=\"laydate_ms\">'+function(){var e=\"\";return n.each(new Array(12),function(t){e+='<span m=\"'+t+'\">'+n.digit(t+1)+\"月</span>\"}),e}()+\"</div></div></div>\"+n.viewtb+'<div class=\"laydate_bottom\"><ul id=\"laydate_hms\"><li class=\"laydate_sj\">时间</li><li><input readonly>:</li><li><input readonly>:</li><li><input readonly></li></ul><div class=\"laydate_time\" id=\"laydate_time\"></div><div class=\"laydate_btn\"><a id=\"laydate_clear\">清空</a><a id=\"laydate_today\">今天</a><a id=\"laydate_ok\">确认</a></div>'+(a.isv?'<a href=\"http://sentsin.com/layui/laydate/\" class=\"laydate_v\" target=\"_blank\">laydate-v'+laydate.v+\"</a>\":\"\")+\"</div>\",s.body.appendChild(o),n.box=l(\"#\"+d[0]),n.events(),o=null),n.follow(n.box),t.zIndex?n.box.style.zIndex=t.zIndex:n.removeCssAttr(n.box,\"z-index\"),n.stopMosup(\"click\",n.box),n.initDate(),n.iswrite(),n.check()},n.reshow=function(){return n.each(n.query(\"#\"+d[0]+\" .laydate_show\"),function(e,t){n.removeClass(t,\"laydate_show\")}),this},n.close=function(){n.reshow(),n.shde(n.query(\"#\"+d[0]),1),n.elem=null},n.parse=function(e,t,s){return e=e.concat(t),s=s||(n.options?n.options.format:a.format),s.replace(/YYYY|MM|DD|hh|mm|ss/g,function(t,a){return e.index=0|++e.index,n.digit(e[e.index])})},n.creation=function(e,t){var a=(n.query,n.hmsin),s=n.parse(e,[a[0].value,a[1].value,a[2].value]);n.elem[d.elemv]=s,t||(n.close(),\"function\"==typeof n.options.choose&&n.options.choose(s))},n.events=function(){var e=n.query,a={box:\"#\"+d[0]};n.addClass(s.body,\"laydate_body\"),d.tds=e(\"#laydate_table td\"),d.mms=e(\"#laydate_ms span\"),d.year=e(\"#laydate_y\"),d.month=e(\"#laydate_m\"),n.each(e(a.box+\" .laydate_ym\"),function(e,t){n.on(t,\"click\",function(t){n.stopmp(t).reshow(),n.addClass(this[l](\"div\")[0],\"laydate_show\"),e||(a.YY=parseInt(d.year.value),n.viewYears(a.YY))})}),n.on(e(a.box),\"click\",function(){n.reshow()}),a.tabYear=function(e){0===e?n.ymd[0]--:1===e?n.ymd[0]++:2===e?a.YY-=14:a.YY+=14,e<2?(n.viewDate(n.ymd[0],n.ymd[1],n.ymd[2]),n.reshow()):n.viewYears(a.YY)},n.each(e(\"#laydate_YY .laydate_tab\"),function(e,t){n.on(t,\"click\",function(t){n.stopmp(t),a.tabYear(e)})}),a.tabMonth=function(e){e?(n.ymd[1]++,12===n.ymd[1]&&(n.ymd[0]++,n.ymd[1]=0)):(n.ymd[1]--,n.ymd[1]===-1&&(n.ymd[0]--,n.ymd[1]=11)),n.viewDate(n.ymd[0],n.ymd[1],n.ymd[2])},n.each(e(\"#laydate_MM .laydate_tab\"),function(e,t){n.on(t,\"click\",function(t){n.stopmp(t).reshow(),a.tabMonth(e)})}),n.each(e(\"#laydate_ms span\"),function(e,t){n.on(t,\"click\",function(e){n.stopmp(e).reshow(),n.hasClass(this,d[1])||n.viewDate(n.ymd[0],0|this.getAttribute(\"m\"),n.ymd[2])})}),n.each(e(\"#laydate_table td\"),function(e,t){n.on(t,\"click\",function(e){n.hasClass(this,d[1])||(n.stopmp(e),n.creation([0|this.getAttribute(\"y\"),0|this.getAttribute(\"m\"),0|this.getAttribute(\"d\")]))})}),d.oclear=e(\"#laydate_clear\"),n.on(d.oclear,\"click\",function(){n.elem[d.elemv]=\"\",n.close()}),d.otoday=e(\"#laydate_today\"),n.on(d.otoday,\"click\",function(){var e=new Date;n.creation([e.getFullYear(),e.getMonth()+1,e.getDate()])}),d.ok=e(\"#laydate_ok\"),n.on(d.ok,\"click\",function(){n.valid&&n.creation([n.ymd[0],n.ymd[1]+1,n.ymd[2]])}),a.times=e(\"#laydate_time\"),n.hmsin=a.hmsin=e(\"#laydate_hms input\"),a.hmss=[\"小时\",\"分钟\",\"秒数\"],a.hmsarr=[],n.msg=function(t,s){var i='<div class=\"laydte_hsmtex\">'+(s||\"提示\")+\"<span>×</span></div>\";\"string\"==typeof t?(i+=\"<p>\"+t+\"</p>\",n.shde(e(\"#\"+d[0])),n.removeClass(a.times,\"laydate_time1\").addClass(a.times,\"laydate_msg\")):(a.hmsarr[t]?i=a.hmsarr[t]:(i+='<div id=\"laydate_hmsno\" class=\"laydate_hmsno\">',n.each(new Array(0===t?24:60),function(e){i+=\"<span>\"+e+\"</span>\"}),i+=\"</div>\",a.hmsarr[t]=i),n.removeClass(a.times,\"laydate_msg\"),n[0===t?\"removeClass\":\"addClass\"](a.times,\"laydate_time1\")),n.addClass(a.times,\"laydate_show\"),a.times.innerHTML=i},a.hmson=function(t,a){var s=e(\"#laydate_hmsno span\"),i=n.valid?null:1;n.each(s,function(e,s){i?n.addClass(s,d[1]):n.timeVoid(e,a)?n.addClass(s,d[1]):n.on(s,\"click\",function(e){n.hasClass(this,d[1])||(t.value=n.digit(0|this.innerHTML))})}),n.addClass(s[0|t.value],\"laydate_click\")},n.each(a.hmsin,function(e,t){n.on(t,\"click\",function(t){n.stopmp(t).reshow(),n.msg(e,a.hmss[e]),a.hmson(this,e)})}),n.on(s,\"mouseup\",function(){var t=e(\"#\"+d[0]);t&&\"none\"!==t.style.display&&(n.check()||n.close())}).on(s,\"keydown\",function(e){e=e||t.event;var a=e.keyCode;13===a&&n.elem&&n.creation([n.ymd[0],n.ymd[1]+1,n.ymd[2]])})},laydate.reset=function(){n.box&&n.elem&&n.follow(n.box)},laydate.now=function(e,t){var a=new Date(0|e?function(e){return e<864e5?+new Date+864e5*e:e}(parseInt(e)):+new Date);return n.parse([a.getFullYear(),a.getMonth()+1,a.getDate()],[a.getHours(),a.getMinutes(),a.getSeconds()],t)},layui.addcss(\"modules/laydate/laydate.css\",function(){},\"laydatecss\"),e(\"laydate\",laydate)});!function(e,t){\"object\"==typeof module&&\"object\"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error(\"jQuery requires a window with a document\");return t(e)}:t(e)}(\"undefined\"!=typeof window?window:this,function(e,t){function n(e){var t=!!e&&\"length\"in e&&e.length,n=pe.type(e);return\"function\"!==n&&!pe.isWindow(e)&&(\"array\"===n||0===t||\"number\"==typeof t&&t>0&&t-1 in e)}function r(e,t,n){if(pe.isFunction(t))return pe.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return pe.grep(e,function(e){return e===t!==n});if(\"string\"==typeof t){if(Ce.test(t))return pe.filter(t,e,n);t=pe.filter(t,e)}return pe.grep(e,function(e){return pe.inArray(e,t)>-1!==n})}function i(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}function o(e){var t={};return pe.each(e.match(De)||[],function(e,n){t[n]=!0}),t}function a(){re.addEventListener?(re.removeEventListener(\"DOMContentLoaded\",s),e.removeEventListener(\"load\",s)):(re.detachEvent(\"onreadystatechange\",s),e.detachEvent(\"onload\",s))}function s(){(re.addEventListener||\"load\"===e.event.type||\"complete\"===re.readyState)&&(a(),pe.ready())}function u(e,t,n){if(void 0===n&&1===e.nodeType){var r=\"data-\"+t.replace(_e,\"-$1\").toLowerCase();if(n=e.getAttribute(r),\"string\"==typeof n){try{n=\"true\"===n||\"false\"!==n&&(\"null\"===n?null:+n+\"\"===n?+n:qe.test(n)?pe.parseJSON(n):n)}catch(i){}pe.data(e,t,n)}else n=void 0}return n}function l(e){var t;for(t in e)if((\"data\"!==t||!pe.isEmptyObject(e[t]))&&\"toJSON\"!==t)return!1;return!0}function c(e,t,n,r){if(He(e)){var i,o,a=pe.expando,s=e.nodeType,u=s?pe.cache:e,l=s?e[a]:e[a]&&a;if(l&&u[l]&&(r||u[l].data)||void 0!==n||\"string\"!=typeof t)return l||(l=s?e[a]=ne.pop()||pe.guid++:a),u[l]||(u[l]=s?{}:{toJSON:pe.noop}),\"object\"!=typeof t&&\"function\"!=typeof t||(r?u[l]=pe.extend(u[l],t):u[l].data=pe.extend(u[l].data,t)),o=u[l],r||(o.data||(o.data={}),o=o.data),void 0!==n&&(o[pe.camelCase(t)]=n),\"string\"==typeof t?(i=o[t],null==i&&(i=o[pe.camelCase(t)])):i=o,i}}function f(e,t,n){if(He(e)){var r,i,o=e.nodeType,a=o?pe.cache:e,s=o?e[pe.expando]:pe.expando;if(a[s]){if(t&&(r=n?a[s]:a[s].data)){pe.isArray(t)?t=t.concat(pe.map(t,pe.camelCase)):t in r?t=[t]:(t=pe.camelCase(t),t=t in r?[t]:t.split(\" \")),i=t.length;for(;i--;)delete r[t[i]];if(n?!l(r):!pe.isEmptyObject(r))return}(n||(delete a[s].data,l(a[s])))&&(o?pe.cleanData([e],!0):fe.deleteExpando||a!=a.window?delete a[s]:a[s]=void 0)}}}function d(e,t,n,r){var i,o=1,a=20,s=r?function(){return r.cur()}:function(){return pe.css(e,t,\"\")},u=s(),l=n&&n[3]||(pe.cssNumber[t]?\"\":\"px\"),c=(pe.cssNumber[t]||\"px\"!==l&&+u)&&Me.exec(pe.css(e,t));if(c&&c[3]!==l){l=l||c[3],n=n||[],c=+u||1;do o=o||\".5\",c/=o,pe.style(e,t,c+l);while(o!==(o=s()/u)&&1!==o&&--a)}return n&&(c=+c||+u||0,i=n[1]?c+(n[1]+1)*n[2]:+n[2],r&&(r.unit=l,r.start=c,r.end=i)),i}function p(e){var t=ze.split(\"|\"),n=e.createDocumentFragment();if(n.createElement)for(;t.length;)n.createElement(t.pop());return n}function h(e,t){var n,r,i=0,o=\"undefined\"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||\"*\"):\"undefined\"!=typeof e.querySelectorAll?e.querySelectorAll(t||\"*\"):void 0;if(!o)for(o=[],n=e.childNodes||e;null!=(r=n[i]);i++)!t||pe.nodeName(r,t)?o.push(r):pe.merge(o,h(r,t));return void 0===t||t&&pe.nodeName(e,t)?pe.merge([e],o):o}function g(e,t){for(var n,r=0;null!=(n=e[r]);r++)pe._data(n,\"globalEval\",!t||pe._data(t[r],\"globalEval\"))}function m(e){Be.test(e.type)&&(e.defaultChecked=e.checked)}function y(e,t,n,r,i){for(var o,a,s,u,l,c,f,d=e.length,y=p(t),v=[],x=0;x<d;x++)if(a=e[x],a||0===a)if(\"object\"===pe.type(a))pe.merge(v,a.nodeType?[a]:a);else if(Ue.test(a)){for(u=u||y.appendChild(t.createElement(\"div\")),l=(We.exec(a)||[\"\",\"\"])[1].toLowerCase(),f=Xe[l]||Xe._default,u.innerHTML=f[1]+pe.htmlPrefilter(a)+f[2],o=f[0];o--;)u=u.lastChild;if(!fe.leadingWhitespace&&$e.test(a)&&v.push(t.createTextNode($e.exec(a)[0])),!fe.tbody)for(a=\"table\"!==l||Ve.test(a)?\"<table>\"!==f[1]||Ve.test(a)?0:u:u.firstChild,o=a&&a.childNodes.length;o--;)pe.nodeName(c=a.childNodes[o],\"tbody\")&&!c.childNodes.length&&a.removeChild(c);for(pe.merge(v,u.childNodes),u.textContent=\"\";u.firstChild;)u.removeChild(u.firstChild);u=y.lastChild}else v.push(t.createTextNode(a));for(u&&y.removeChild(u),fe.appendChecked||pe.grep(h(v,\"input\"),m),x=0;a=v[x++];)if(r&&pe.inArray(a,r)>-1)i&&i.push(a);else if(s=pe.contains(a.ownerDocument,a),u=h(y.appendChild(a),\"script\"),s&&g(u),n)for(o=0;a=u[o++];)Ie.test(a.type||\"\")&&n.push(a);return u=null,y}function v(){return!0}function x(){return!1}function b(){try{return re.activeElement}catch(e){}}function w(e,t,n,r,i,o){var a,s;if(\"object\"==typeof t){\"string\"!=typeof n&&(r=r||n,n=void 0);for(s in t)w(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&(\"string\"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),i===!1)i=x;else if(!i)return e;return 1===o&&(a=i,i=function(e){return pe().off(e),a.apply(this,arguments)},i.guid=a.guid||(a.guid=pe.guid++)),e.each(function(){pe.event.add(this,t,i,r,n)})}function T(e,t){return pe.nodeName(e,\"table\")&&pe.nodeName(11!==t.nodeType?t:t.firstChild,\"tr\")?e.getElementsByTagName(\"tbody\")[0]||e.appendChild(e.ownerDocument.createElement(\"tbody\")):e}function C(e){return e.type=(null!==pe.find.attr(e,\"type\"))+\"/\"+e.type,e}function E(e){var t=it.exec(e.type);return t?e.type=t[1]:e.removeAttribute(\"type\"),e}function N(e,t){if(1===t.nodeType&&pe.hasData(e)){var n,r,i,o=pe._data(e),a=pe._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;r<i;r++)pe.event.add(t,n,s[n][r])}a.data&&(a.data=pe.extend({},a.data))}}function k(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!fe.noCloneEvent&&t[pe.expando]){i=pe._data(t);for(r in i.events)pe.removeEvent(t,r,i.handle);t.removeAttribute(pe.expando)}\"script\"===n&&t.text!==e.text?(C(t).text=e.text,E(t)):\"object\"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),fe.html5Clone&&e.innerHTML&&!pe.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):\"input\"===n&&Be.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)}}function S(e,t,n,r){t=oe.apply([],t);var i,o,a,s,u,l,c=0,f=e.length,d=f-1,p=t[0],g=pe.isFunction(p);if(g||f>1&&\"string\"==typeof p&&!fe.checkClone&&rt.test(p))return e.each(function(i){var o=e.eq(i);g&&(t[0]=p.call(this,i,o.html())),S(o,t,n,r)});if(f&&(l=y(t,e[0].ownerDocument,!1,e,r),i=l.firstChild,1===l.childNodes.length&&(l=i),i||r)){for(s=pe.map(h(l,\"script\"),C),a=s.length;c<f;c++)o=l,c!==d&&(o=pe.clone(o,!0,!0),a&&pe.merge(s,h(o,\"script\"))),n.call(e[c],o,c);if(a)for(u=s[s.length-1].ownerDocument,pe.map(s,E),c=0;c<a;c++)o=s[c],Ie.test(o.type||\"\")&&!pe._data(o,\"globalEval\")&&pe.contains(u,o)&&(o.src?pe._evalUrl&&pe._evalUrl(o.src):pe.globalEval((o.text||o.textContent||o.innerHTML||\"\").replace(ot,\"\")));l=i=null}return e}function A(e,t,n){for(var r,i=t?pe.filter(t,e):e,o=0;null!=(r=i[o]);o++)n||1!==r.nodeType||pe.cleanData(h(r)),r.parentNode&&(n&&pe.contains(r.ownerDocument,r)&&g(h(r,\"script\")),r.parentNode.removeChild(r));return e}function D(e,t){var n=pe(t.createElement(e)).appendTo(t.body),r=pe.css(n[0],\"display\");return n.detach(),r}function j(e){var t=re,n=lt[e];return n||(n=D(e,t),\"none\"!==n&&n||(ut=(ut||pe(\"<iframe frameborder='0' width='0' height='0'/>\")).appendTo(t.documentElement),t=(ut[0].contentWindow||ut[0].contentDocument).document,t.write(),t.close(),n=D(e,t),ut.detach()),lt[e]=n),n}function L(e,t){return{get:function(){return e()?void delete this.get:(this.get=t).apply(this,arguments)}}}function H(e){if(e in Et)return e;for(var t=e.charAt(0).toUpperCase()+e.slice(1),n=Ct.length;n--;)if(e=Ct[n]+t,e in Et)return e}function q(e,t){for(var n,r,i,o=[],a=0,s=e.length;a<s;a++)r=e[a],r.style&&(o[a]=pe._data(r,\"olddisplay\"),n=r.style.display,t?(o[a]||\"none\"!==n||(r.style.display=\"\"),\"\"===r.style.display&&Re(r)&&(o[a]=pe._data(r,\"olddisplay\",j(r.nodeName)))):(i=Re(r),(n&&\"none\"!==n||!i)&&pe._data(r,\"olddisplay\",i?n:pe.css(r,\"display\"))));for(a=0;a<s;a++)r=e[a],r.style&&(t&&\"none\"!==r.style.display&&\"\"!==r.style.display||(r.style.display=t?o[a]||\"\":\"none\"));return e}function _(e,t,n){var r=bt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||\"px\"):t}function F(e,t,n,r,i){for(var o=n===(r?\"border\":\"content\")?4:\"width\"===t?1:0,a=0;o<4;o+=2)\"margin\"===n&&(a+=pe.css(e,n+Oe[o],!0,i)),r?(\"content\"===n&&(a-=pe.css(e,\"padding\"+Oe[o],!0,i)),\"margin\"!==n&&(a-=pe.css(e,\"border\"+Oe[o]+\"Width\",!0,i))):(a+=pe.css(e,\"padding\"+Oe[o],!0,i),\"padding\"!==n&&(a+=pe.css(e,\"border\"+Oe[o]+\"Width\",!0,i)));return a}function M(t,n,r){var i=!0,o=\"width\"===n?t.offsetWidth:t.offsetHeight,a=ht(t),s=fe.boxSizing&&\"border-box\"===pe.css(t,\"boxSizing\",!1,a);if(re.msFullscreenElement&&e.top!==e&&t.getClientRects().length&&(o=Math.round(100*t.getBoundingClientRect()[n])),o<=0||null==o){if(o=gt(t,n,a),(o<0||null==o)&&(o=t.style[n]),ft.test(o))return o;i=s&&(fe.boxSizingReliable()||o===t.style[n]),o=parseFloat(o)||0}return o+F(t,n,r||(s?\"border\":\"content\"),i,a)+\"px\"}function O(e,t,n,r,i){return new O.prototype.init(e,t,n,r,i)}function R(){return e.setTimeout(function(){Nt=void 0}),Nt=pe.now()}function P(e,t){var n,r={height:e},i=0;for(t=t?1:0;i<4;i+=2-t)n=Oe[i],r[\"margin\"+n]=r[\"padding\"+n]=e;return t&&(r.opacity=r.width=e),r}function B(e,t,n){for(var r,i=($.tweeners[t]||[]).concat($.tweeners[\"*\"]),o=0,a=i.length;o<a;o++)if(r=i[o].call(n,t,e))return r}function W(e,t,n){var r,i,o,a,s,u,l,c,f=this,d={},p=e.style,h=e.nodeType&&Re(e),g=pe._data(e,\"fxshow\");n.queue||(s=pe._queueHooks(e,\"fx\"),null==s.unqueued&&(s.unqueued=0,u=s.empty.fire,s.empty.fire=function(){s.unqueued||u()}),s.unqueued++,f.always(function(){f.always(function(){s.unqueued--,pe.queue(e,\"fx\").length||s.empty.fire()})})),1===e.nodeType&&(\"height\"in t||\"width\"in t)&&(n.overflow=[p.overflow,p.overflowX,p.overflowY],l=pe.css(e,\"display\"),c=\"none\"===l?pe._data(e,\"olddisplay\")||j(e.nodeName):l,\"inline\"===c&&\"none\"===pe.css(e,\"float\")&&(fe.inlineBlockNeedsLayout&&\"inline\"!==j(e.nodeName)?p.zoom=1:p.display=\"inline-block\")),n.overflow&&(p.overflow=\"hidden\",fe.shrinkWrapBlocks()||f.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],St.exec(i)){if(delete t[r],o=o||\"toggle\"===i,i===(h?\"hide\":\"show\")){if(\"show\"!==i||!g||void 0===g[r])continue;h=!0}d[r]=g&&g[r]||pe.style(e,r)}else l=void 0;if(pe.isEmptyObject(d))\"inline\"===(\"none\"===l?j(e.nodeName):l)&&(p.display=l);else{g?\"hidden\"in g&&(h=g.hidden):g=pe._data(e,\"fxshow\",{}),o&&(g.hidden=!h),h?pe(e).show():f.done(function(){pe(e).hide()}),f.done(function(){var t;pe._removeData(e,\"fxshow\");for(t in d)pe.style(e,t,d[t])});for(r in d)a=B(h?g[r]:0,r,f),r in g||(g[r]=a.start,h&&(a.end=a.start,a.start=\"width\"===r||\"height\"===r?1:0))}}function I(e,t){var n,r,i,o,a;for(n in e)if(r=pe.camelCase(n),i=t[r],o=e[n],pe.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),a=pe.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}function $(e,t,n){var r,i,o=0,a=$.prefilters.length,s=pe.Deferred().always(function(){delete u.elem}),u=function(){if(i)return!1;for(var t=Nt||R(),n=Math.max(0,l.startTime+l.duration-t),r=n/l.duration||0,o=1-r,a=0,u=l.tweens.length;a<u;a++)l.tweens[a].run(o);return s.notifyWith(e,[l,o,n]),o<1&&u?n:(s.resolveWith(e,[l]),!1)},l=s.promise({elem:e,props:pe.extend({},t),opts:pe.extend(!0,{specialEasing:{},easing:pe.easing._default},n),originalProperties:t,originalOptions:n,startTime:Nt||R(),duration:n.duration,tweens:[],createTween:function(t,n){var r=pe.Tween(e,l.opts,t,n,l.opts.specialEasing[t]||l.opts.easing);return l.tweens.push(r),r},stop:function(t){var n=0,r=t?l.tweens.length:0;if(i)return this;for(i=!0;n<r;n++)l.tweens[n].run(1);return t?(s.notifyWith(e,[l,1,0]),s.resolveWith(e,[l,t])):s.rejectWith(e,[l,t]),this}}),c=l.props;for(I(c,l.opts.specialEasing);o<a;o++)if(r=$.prefilters[o].call(l,e,c,l.opts))return pe.isFunction(r.stop)&&(pe._queueHooks(l.elem,l.opts.queue).stop=pe.proxy(r.stop,r)),r;return pe.map(c,B,l),pe.isFunction(l.opts.start)&&l.opts.start.call(e,l),pe.fx.timer(pe.extend(u,{elem:e,anim:l,queue:l.opts.queue})),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always)}function z(e){return pe.attr(e,\"class\")||\"\"}function X(e){return function(t,n){\"string\"!=typeof t&&(n=t,t=\"*\");var r,i=0,o=t.toLowerCase().match(De)||[];if(pe.isFunction(n))for(;r=o[i++];)\"+\"===r.charAt(0)?(r=r.slice(1)||\"*\",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function U(e,t,n,r){function i(s){var u;return o[s]=!0,pe.each(e[s]||[],function(e,s){var l=s(t,n,r);return\"string\"!=typeof l||a||o[l]?a?!(u=l):void 0:(t.dataTypes.unshift(l),i(l),!1)}),u}var o={},a=e===Qt;return i(t.dataTypes[0])||!o[\"*\"]&&i(\"*\")}function V(e,t){var n,r,i=pe.ajaxSettings.flatOptions||{};for(r in t)void 0!==t[r]&&((i[r]?e:n||(n={}))[r]=t[r]);return n&&pe.extend(!0,e,n),e}function Y(e,t,n){for(var r,i,o,a,s=e.contents,u=e.dataTypes;\"*\"===u[0];)u.shift(),void 0===i&&(i=e.mimeType||t.getResponseHeader(\"Content-Type\"));if(i)for(a in s)if(s[a]&&s[a].test(i)){u.unshift(a);break}if(u[0]in n)o=u[0];else{for(a in n){if(!u[0]||e.converters[a+\" \"+u[0]]){o=a;break}r||(r=a)}o=o||r}if(o)return o!==u[0]&&u.unshift(o),n[o]}function J(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];for(o=c.shift();o;)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if(\"*\"===o)o=u;else if(\"*\"!==u&&u!==o){if(a=l[u+\" \"+o]||l[\"* \"+o],!a)for(i in l)if(s=i.split(\" \"),s[1]===o&&(a=l[u+\" \"+s[0]]||l[\"* \"+s[0]])){a===!0?a=l[i]:l[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(f){return{state:\"parsererror\",error:a?f:\"No conversion from \"+u+\" to \"+o}}}return{state:\"success\",data:t}}function G(e){return e.style&&e.style.display||pe.css(e,\"display\")}function K(e){for(;e&&1===e.nodeType;){if(\"none\"===G(e)||\"hidden\"===e.type)return!0;e=e.parentNode}return!1}function Q(e,t,n,r){var i;if(pe.isArray(t))pe.each(t,function(t,i){n||rn.test(e)?r(e,i):Q(e+\"[\"+(\"object\"==typeof i&&null!=i?t:\"\")+\"]\",i,n,r)});else if(n||\"object\"!==pe.type(t))r(e,t);else for(i in t)Q(e+\"[\"+i+\"]\",t[i],n,r)}function Z(){try{return new e.XMLHttpRequest}catch(t){}}function ee(){try{return new e.ActiveXObject(\"Microsoft.XMLHTTP\")}catch(t){}}function te(e){return pe.isWindow(e)?e:9===e.nodeType&&(e.defaultView||e.parentWindow)}var ne=[],re=e.document,ie=ne.slice,oe=ne.concat,ae=ne.push,se=ne.indexOf,ue={},le=ue.toString,ce=ue.hasOwnProperty,fe={},de=\"1.12.3\",pe=function(e,t){return new pe.fn.init(e,t)},he=/^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g,ge=/^-ms-/,me=/-([\\da-z])/gi,ye=function(e,t){return t.toUpperCase()};pe.fn=pe.prototype={jquery:de,constructor:pe,selector:\"\",length:0,toArray:function(){return ie.call(this)},get:function(e){return null!=e?e<0?this[e+this.length]:this[e]:ie.call(this)},pushStack:function(e){var t=pe.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e){return pe.each(this,e)},map:function(e){return this.pushStack(pe.map(this,function(t,n){return e.call(t,n,t)}))},slice:function(){return this.pushStack(ie.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(n>=0&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:ae,sort:ne.sort,splice:ne.splice},pe.extend=pe.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for(\"boolean\"==typeof a&&(l=a,a=arguments[s]||{},s++),\"object\"==typeof a||pe.isFunction(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(i=arguments[s]))for(r in i)e=a[r],n=i[r],a!==n&&(l&&n&&(pe.isPlainObject(n)||(t=pe.isArray(n)))?(t?(t=!1,o=e&&pe.isArray(e)?e:[]):o=e&&pe.isPlainObject(e)?e:{},a[r]=pe.extend(l,o,n)):void 0!==n&&(a[r]=n));return a},pe.extend({expando:\"jQuery\"+(de+Math.random()).replace(/\\D/g,\"\"),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isFunction:function(e){return\"function\"===pe.type(e)},isArray:Array.isArray||function(e){return\"array\"===pe.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){var t=e&&e.toString();return!pe.isArray(e)&&t-parseFloat(t)+1>=0},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},isPlainObject:function(e){var t;if(!e||\"object\"!==pe.type(e)||e.nodeType||pe.isWindow(e))return!1;try{if(e.constructor&&!ce.call(e,\"constructor\")&&!ce.call(e.constructor.prototype,\"isPrototypeOf\"))return!1}catch(n){return!1}if(!fe.ownFirst)for(t in e)return ce.call(e,t);for(t in e);return void 0===t||ce.call(e,t)},type:function(e){return null==e?e+\"\":\"object\"==typeof e||\"function\"==typeof e?ue[le.call(e)]||\"object\":typeof e},globalEval:function(t){t&&pe.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(ge,\"ms-\").replace(me,ye)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t){var r,i=0;if(n(e))for(r=e.length;i<r&&t.call(e[i],i,e[i])!==!1;i++);else for(i in e)if(t.call(e[i],i,e[i])===!1)break;return e},trim:function(e){return null==e?\"\":(e+\"\").replace(he,\"\")},makeArray:function(e,t){var r=t||[];return null!=e&&(n(Object(e))?pe.merge(r,\"string\"==typeof e?[e]:e):ae.call(r,e)),r},inArray:function(e,t,n){var r;if(t){if(se)return se.call(t,e,n);for(r=t.length,n=n?n<0?Math.max(0,r+n):n:0;n<r;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;)e[i++]=t[r++];if(n!==n)for(;void 0!==t[r];)e[i++]=t[r++];return e.length=i,e},grep:function(e,t,n){for(var r,i=[],o=0,a=e.length,s=!n;o<a;o++)r=!t(e[o],o),r!==s&&i.push(e[o]);return i},map:function(e,t,r){var i,o,a=0,s=[];if(n(e))for(i=e.length;a<i;a++)o=t(e[a],a,r),null!=o&&s.push(o);else for(a in e)o=t(e[a],a,r),null!=o&&s.push(o);return oe.apply([],s)},guid:1,proxy:function(e,t){var n,r,i;if(\"string\"==typeof t&&(i=e[t],t=e,e=i),pe.isFunction(e))return n=ie.call(arguments,2),r=function(){return e.apply(t||this,n.concat(ie.call(arguments)))},r.guid=e.guid=e.guid||pe.guid++,r},now:function(){return+new Date},support:fe}),\"function\"==typeof Symbol&&(pe.fn[Symbol.iterator]=ne[Symbol.iterator]),pe.each(\"Boolean Number String Function Array Date RegExp Object Error Symbol\".split(\" \"),function(e,t){ue[\"[object \"+t+\"]\"]=t.toLowerCase()});var ve=function(e){function t(e,t,n,r){var i,o,a,s,u,l,f,p,h=t&&t.ownerDocument,g=t?t.nodeType:9;if(n=n||[],\"string\"!=typeof e||!e||1!==g&&9!==g&&11!==g)return n;if(!r&&((t?t.ownerDocument||t:B)!==H&&L(t),t=t||H,_)){if(11!==g&&(l=ye.exec(e)))if(i=l[1]){if(9===g){if(!(a=t.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(h&&(a=h.getElementById(i))&&R(t,a)&&a.id===i)return n.push(a),n}else{if(l[2])return Q.apply(n,t.getElementsByTagName(e)),n;if((i=l[3])&&w.getElementsByClassName&&t.getElementsByClassName)return Q.apply(n,t.getElementsByClassName(i)),n}if(w.qsa&&!X[e+\" \"]&&(!F||!F.test(e))){if(1!==g)h=t,p=e;else if(\"object\"!==t.nodeName.toLowerCase()){for((s=t.getAttribute(\"id\"))?s=s.replace(xe,\"\\\\$&\"):t.setAttribute(\"id\",s=P),f=N(e),o=f.length,u=de.test(s)?\"#\"+s:\"[id='\"+s+\"']\";o--;)f[o]=u+\" \"+d(f[o]);p=f.join(\",\"),h=ve.test(e)&&c(t.parentNode)||t}if(p)try{return Q.apply(n,h.querySelectorAll(p)),n}catch(m){}finally{s===P&&t.removeAttribute(\"id\")}}}return S(e.replace(se,\"$1\"),t,n,r)}function n(){function e(n,r){return t.push(n+\" \")>T.cacheLength&&delete e[t.shift()],e[n+\" \"]=r}var t=[];return e}function r(e){return e[P]=!0,e}function i(e){var t=H.createElement(\"div\");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function o(e,t){for(var n=e.split(\"|\"),r=n.length;r--;)T.attrHandle[n[r]]=t}function a(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||V)-(~e.sourceIndex||V);if(r)return r;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function s(e){return function(t){var n=t.nodeName.toLowerCase();return\"input\"===n&&t.type===e}}function u(e){return function(t){var n=t.nodeName.toLowerCase();return(\"input\"===n||\"button\"===n)&&t.type===e}}function l(e){return r(function(t){return t=+t,r(function(n,r){for(var i,o=e([],n.length,t),a=o.length;a--;)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}function c(e){return e&&\"undefined\"!=typeof e.getElementsByTagName&&e}function f(){}function d(e){for(var t=0,n=e.length,r=\"\";t<n;t++)r+=e[t].value;return r}function p(e,t,n){var r=t.dir,i=n&&\"parentNode\"===r,o=I++;return t.first?function(t,n,o){for(;t=t[r];)if(1===t.nodeType||i)return e(t,n,o)}:function(t,n,a){var s,u,l,c=[W,o];if(a){for(;t=t[r];)if((1===t.nodeType||i)&&e(t,n,a))return!0}else for(;t=t[r];)if(1===t.nodeType||i){if(l=t[P]||(t[P]={}),u=l[t.uniqueID]||(l[t.uniqueID]={}),(s=u[r])&&s[0]===W&&s[1]===o)return c[2]=s[2];if(u[r]=c,c[2]=e(t,n,a))return!0}}}function h(e){return e.length>1?function(t,n,r){for(var i=e.length;i--;)if(!e[i](t,n,r))return!1;return!0}:e[0]}function g(e,n,r){for(var i=0,o=n.length;i<o;i++)t(e,n[i],r);return r}function m(e,t,n,r,i){for(var o,a=[],s=0,u=e.length,l=null!=t;s<u;s++)(o=e[s])&&(n&&!n(o,r,i)||(a.push(o),l&&t.push(s)));return a}function y(e,t,n,i,o,a){return i&&!i[P]&&(i=y(i)),o&&!o[P]&&(o=y(o,a)),r(function(r,a,s,u){var l,c,f,d=[],p=[],h=a.length,y=r||g(t||\"*\",s.nodeType?[s]:s,[]),v=!e||!r&&t?y:m(y,d,e,s,u),x=n?o||(r?e:h||i)?[]:a:v;if(n&&n(v,x,s,u),i)for(l=m(x,p),i(l,[],s,u),c=l.length;c--;)(f=l[c])&&(x[p[c]]=!(v[p[c]]=f));if(r){if(o||e){if(o){for(l=[],c=x.length;c--;)(f=x[c])&&l.push(v[c]=f);o(null,x=[],l,u)}for(c=x.length;c--;)(f=x[c])&&(l=o?ee(r,f):d[c])>-1&&(r[l]=!(a[l]=f))}}else x=m(x===a?x.splice(h,x.length):x),o?o(null,a,x,u):Q.apply(a,x)})}function v(e){for(var t,n,r,i=e.length,o=T.relative[e[0].type],a=o||T.relative[\" \"],s=o?1:0,u=p(function(e){return e===t},a,!0),l=p(function(e){return ee(t,e)>-1},a,!0),c=[function(e,n,r){var i=!o&&(r||n!==A)||((t=n).nodeType?u(e,n,r):l(e,n,r));return t=null,i}];s<i;s++)if(n=T.relative[e[s].type])c=[p(h(c),n)];else{if(n=T.filter[e[s].type].apply(null,e[s].matches),n[P]){for(r=++s;r<i&&!T.relative[e[r].type];r++);return y(s>1&&h(c),s>1&&d(e.slice(0,s-1).concat({value:\" \"===e[s-2].type?\"*\":\"\"})).replace(se,\"$1\"),n,s<r&&v(e.slice(s,r)),r<i&&v(e=e.slice(r)),r<i&&d(e))}c.push(n)}return h(c)}function x(e,n){var i=n.length>0,o=e.length>0,a=function(r,a,s,u,l){var c,f,d,p=0,h=\"0\",g=r&&[],y=[],v=A,x=r||o&&T.find.TAG(\"*\",l),b=W+=null==v?1:Math.random()||.1,w=x.length;for(l&&(A=a===H||a||l);h!==w&&null!=(c=x[h]);h++){if(o&&c){for(f=0,a||c.ownerDocument===H||(L(c),s=!_);d=e[f++];)if(d(c,a||H,s)){u.push(c);break}l&&(W=b)}i&&((c=!d&&c)&&p--,r&&g.push(c))}if(p+=h,i&&h!==p){for(f=0;d=n[f++];)d(g,y,a,s);if(r){if(p>0)for(;h--;)g[h]||y[h]||(y[h]=G.call(u));y=m(y)}Q.apply(u,y),l&&!r&&y.length>0&&p+n.length>1&&t.uniqueSort(u)}return l&&(W=b,A=v),g};return i?r(a):a}var b,w,T,C,E,N,k,S,A,D,j,L,H,q,_,F,M,O,R,P=\"sizzle\"+1*new Date,B=e.document,W=0,I=0,$=n(),z=n(),X=n(),U=function(e,t){return e===t&&(j=!0),0},V=1<<31,Y={}.hasOwnProperty,J=[],G=J.pop,K=J.push,Q=J.push,Z=J.slice,ee=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},te=\"checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped\",ne=\"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",re=\"(?:\\\\\\\\.|[\\\\w-]|[^\\\\x00-\\\\xa0])+\",ie=\"\\\\[\"+ne+\"*(\"+re+\")(?:\"+ne+\"*([*^$|!~]?=)\"+ne+\"*(?:'((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\"|(\"+re+\"))|)\"+ne+\"*\\\\]\",oe=\":(\"+re+\")(?:\\\\((('((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\")|((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\"+ie+\")*)|.*)\\\\)|)\",ae=new RegExp(ne+\"+\",\"g\"),se=new RegExp(\"^\"+ne+\"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\"+ne+\"+$\",\"g\"),ue=new RegExp(\"^\"+ne+\"*,\"+ne+\"*\"),le=new RegExp(\"^\"+ne+\"*([>+~]|\"+ne+\")\"+ne+\"*\"),ce=new RegExp(\"=\"+ne+\"*([^\\\\]'\\\"]*?)\"+ne+\"*\\\\]\",\"g\"),fe=new RegExp(oe),de=new RegExp(\"^\"+re+\"$\"),pe={ID:new RegExp(\"^#(\"+re+\")\"),CLASS:new RegExp(\"^\\\\.(\"+re+\")\"),TAG:new RegExp(\"^(\"+re+\"|[*])\"),ATTR:new RegExp(\"^\"+ie),PSEUDO:new RegExp(\"^\"+oe),CHILD:new RegExp(\"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\"+ne+\"*(even|odd|(([+-]|)(\\\\d*)n|)\"+ne+\"*(?:([+-]|)\"+ne+\"*(\\\\d+)|))\"+ne+\"*\\\\)|)\",\"i\"),bool:new RegExp(\"^(?:\"+te+\")$\",\"i\"),needsContext:new RegExp(\"^\"+ne+\"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\"+ne+\"*((?:-\\\\d)?\\\\d*)\"+ne+\"*\\\\)|)(?=[^-]|$)\",\"i\")},he=/^(?:input|select|textarea|button)$/i,ge=/^h\\d$/i,me=/^[^{]+\\{\\s*\\[native \\w/,ye=/^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,ve=/[+~]/,xe=/'|\\\\/g,be=new RegExp(\"\\\\\\\\([\\\\da-f]{1,6}\"+ne+\"?|(\"+ne+\")|.)\",\"ig\"),we=function(e,t,n){var r=\"0x\"+t-65536;return r!==r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},Te=function(){L()};try{Q.apply(J=Z.call(B.childNodes),B.childNodes),J[B.childNodes.length].nodeType}catch(Ce){Q={apply:J.length?function(e,t){K.apply(e,Z.call(t))}:function(e,t){for(var n=e.length,r=0;e[n++]=t[r++];);e.length=n-1}}}w=t.support={},E=t.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return!!t&&\"HTML\"!==t.nodeName},L=t.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:B;return r!==H&&9===r.nodeType&&r.documentElement?(H=r,q=H.documentElement,_=!E(H),(n=H.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener(\"unload\",Te,!1):n.attachEvent&&n.attachEvent(\"onunload\",Te)),w.attributes=i(function(e){return e.className=\"i\",!e.getAttribute(\"className\")}),w.getElementsByTagName=i(function(e){return e.appendChild(H.createComment(\"\")),!e.getElementsByTagName(\"*\").length}),w.getElementsByClassName=me.test(H.getElementsByClassName),w.getById=i(function(e){return q.appendChild(e).id=P,!H.getElementsByName||!H.getElementsByName(P).length}),w.getById?(T.find.ID=function(e,t){if(\"undefined\"!=typeof t.getElementById&&_){var n=t.getElementById(e);return n?[n]:[]}},T.filter.ID=function(e){var t=e.replace(be,we);return function(e){return e.getAttribute(\"id\")===t}}):(delete T.find.ID,T.filter.ID=function(e){var t=e.replace(be,we);return function(e){var n=\"undefined\"!=typeof e.getAttributeNode&&e.getAttributeNode(\"id\");return n&&n.value===t}}),T.find.TAG=w.getElementsByTagName?function(e,t){return\"undefined\"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):w.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if(\"*\"===e){for(;n=o[i++];)1===n.nodeType&&r.push(n);return r}return o},T.find.CLASS=w.getElementsByClassName&&function(e,t){if(\"undefined\"!=typeof t.getElementsByClassName&&_)return t.getElementsByClassName(e)},M=[],F=[],(w.qsa=me.test(H.querySelectorAll))&&(i(function(e){q.appendChild(e).innerHTML=\"<a id='\"+P+\"'></a><select id='\"+P+\"-\\r\\\\' msallowcapture=''><option selected=''></option></select>\",e.querySelectorAll(\"[msallowcapture^='']\").length&&F.push(\"[*^$]=\"+ne+\"*(?:''|\\\"\\\")\"),e.querySelectorAll(\"[selected]\").length||F.push(\"\\\\[\"+ne+\"*(?:value|\"+te+\")\"),e.querySelectorAll(\"[id~=\"+P+\"-]\").length||F.push(\"~=\"),e.querySelectorAll(\":checked\").length||F.push(\":checked\"),e.querySelectorAll(\"a#\"+P+\"+*\").length||F.push(\".#.+[+~]\")}),i(function(e){var t=H.createElement(\"input\");t.setAttribute(\"type\",\"hidden\"),e.appendChild(t).setAttribute(\"name\",\"D\"),e.querySelectorAll(\"[name=d]\").length&&F.push(\"name\"+ne+\"*[*^$|!~]?=\"),e.querySelectorAll(\":enabled\").length||F.push(\":enabled\",\":disabled\"),e.querySelectorAll(\"*,:x\"),F.push(\",.*:\")})),(w.matchesSelector=me.test(O=q.matches||q.webkitMatchesSelector||q.mozMatchesSelector||q.oMatchesSelector||q.msMatchesSelector))&&i(function(e){w.disconnectedMatch=O.call(e,\"div\"),O.call(e,\"[s!='']:x\"),M.push(\"!=\",oe)}),F=F.length&&new RegExp(F.join(\"|\")),M=M.length&&new RegExp(M.join(\"|\")),t=me.test(q.compareDocumentPosition),R=t||me.test(q.contains)?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)for(;t=t.parentNode;)if(t===e)return!0;return!1},U=t?function(e,t){if(e===t)return j=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n?n:(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1,1&n||!w.sortDetached&&t.compareDocumentPosition(e)===n?e===H||e.ownerDocument===B&&R(B,e)?-1:t===H||t.ownerDocument===B&&R(B,t)?1:D?ee(D,e)-ee(D,t):0:4&n?-1:1)}:function(e,t){if(e===t)return j=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,s=[e],u=[t];if(!i||!o)return e===H?-1:t===H?1:i?-1:o?1:D?ee(D,e)-ee(D,t):0;if(i===o)return a(e,t);for(n=e;n=n.parentNode;)s.unshift(n);for(n=t;n=n.parentNode;)u.unshift(n);for(;s[r]===u[r];)r++;return r?a(s[r],u[r]):s[r]===B?-1:u[r]===B?1:0},H):H},t.matches=function(e,n){return t(e,null,null,n)},t.matchesSelector=function(e,n){if((e.ownerDocument||e)!==H&&L(e),n=n.replace(ce,\"='$1']\"),w.matchesSelector&&_&&!X[n+\" \"]&&(!M||!M.test(n))&&(!F||!F.test(n)))try{var r=O.call(e,n);if(r||w.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(i){}return t(n,H,null,[e]).length>0},t.contains=function(e,t){return(e.ownerDocument||e)!==H&&L(e),R(e,t)},t.attr=function(e,t){(e.ownerDocument||e)!==H&&L(e);var n=T.attrHandle[t.toLowerCase()],r=n&&Y.call(T.attrHandle,t.toLowerCase())?n(e,t,!_):void 0;return void 0!==r?r:w.attributes||!_?e.getAttribute(t):(r=e.getAttributeNode(t))&&r.specified?r.value:null},t.error=function(e){throw new Error(\"Syntax error, unrecognized expression: \"+e)},t.uniqueSort=function(e){var t,n=[],r=0,i=0;if(j=!w.detectDuplicates,D=!w.sortStable&&e.slice(0),e.sort(U),j){for(;t=e[i++];)t===e[i]&&(r=n.push(i));for(;r--;)e.splice(n[r],1)}return D=null,e},C=t.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+=C(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r++];)n+=C(t);return n},T=t.selectors={cacheLength:50,createPseudo:r,match:pe,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(be,we),e[3]=(e[3]||e[4]||e[5]||\"\").replace(be,we),\"~=\"===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]||t.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]&&t.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return pe.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||\"\":n&&fe.test(n)&&(t=N(n,!0))&&(t=n.indexOf(\")\",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(be,we).toLowerCase();return\"*\"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=$[e+\" \"];return t||(t=new RegExp(\"(^|\"+ne+\")\"+e+\"(\"+ne+\"|$)\"))&&$(e,function(e){return t.test(\"string\"==typeof e.className&&e.className||\"undefined\"!=typeof e.getAttribute&&e.getAttribute(\"class\")||\"\")})},ATTR:function(e,n,r){return function(i){var o=t.attr(i,e);return null==o?\"!=\"===n:!n||(o+=\"\",\"=\"===n?o===r:\"!=\"===n?o!==r:\"^=\"===n?r&&0===o.indexOf(r):\"*=\"===n?r&&o.indexOf(r)>-1:\"$=\"===n?r&&o.slice(-r.length)===r:\"~=\"===n?(\" \"+o.replace(ae,\" \")+\" \").indexOf(r)>-1:\"|=\"===n&&(o===r||o.slice(0,r.length+1)===r+\"-\"))}},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,u){var l,c,f,d,p,h,g=o!==a?\"nextSibling\":\"previousSibling\",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!u&&!s,x=!1;if(m){if(o){for(;g;){for(d=t;d=d[g];)if(s?d.nodeName.toLowerCase()===y:1===d.nodeType)return!1;h=g=\"only\"===e&&!h&&\"nextSibling\"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){for(d=m,f=d[P]||(d[P]={}),c=f[d.uniqueID]||(f[d.uniqueID]={}),\nl=c[e]||[],p=l[0]===W&&l[1],x=p&&l[2],d=p&&m.childNodes[p];d=++p&&d&&d[g]||(x=p=0)||h.pop();)if(1===d.nodeType&&++x&&d===t){c[e]=[W,p,x];break}}else if(v&&(d=t,f=d[P]||(d[P]={}),c=f[d.uniqueID]||(f[d.uniqueID]={}),l=c[e]||[],p=l[0]===W&&l[1],x=p),x===!1)for(;(d=++p&&d&&d[g]||(x=p=0)||h.pop())&&((s?d.nodeName.toLowerCase()!==y:1!==d.nodeType)||!++x||(v&&(f=d[P]||(d[P]={}),c=f[d.uniqueID]||(f[d.uniqueID]={}),c[e]=[W,x]),d!==t)););return x-=i,x===r||x%r===0&&x/r>=0}}},PSEUDO:function(e,n){var i,o=T.pseudos[e]||T.setFilters[e.toLowerCase()]||t.error(\"unsupported pseudo: \"+e);return o[P]?o(n):o.length>1?(i=[e,e,\"\",n],T.setFilters.hasOwnProperty(e.toLowerCase())?r(function(e,t){for(var r,i=o(e,n),a=i.length;a--;)r=ee(e,i[a]),e[r]=!(t[r]=i[a])}):function(e){return o(e,0,i)}):o}},pseudos:{not:r(function(e){var t=[],n=[],i=k(e.replace(se,\"$1\"));return i[P]?r(function(e,t,n,r){for(var o,a=i(e,null,r,[]),s=e.length;s--;)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,r,o){return t[0]=e,i(t,null,o,n),t[0]=null,!n.pop()}}),has:r(function(e){return function(n){return t(e,n).length>0}}),contains:r(function(e){return e=e.replace(be,we),function(t){return(t.textContent||t.innerText||C(t)).indexOf(e)>-1}}),lang:r(function(e){return de.test(e||\"\")||t.error(\"unsupported lang: \"+e),e=e.replace(be,we).toLowerCase(),function(t){var n;do if(n=_?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===q},focus:function(e){return e===H.activeElement&&(!H.hasFocus||H.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.nodeType<6)return!1;return!0},parent:function(e){return!T.pseudos.empty(e)},header:function(e){return ge.test(e.nodeName)},input:function(e){return he.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\"))||\"text\"===t.toLowerCase())},first:l(function(){return[0]}),last:l(function(e,t){return[t-1]}),eq:l(function(e,t,n){return[n<0?n+t:n]}),even:l(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:l(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:l(function(e,t,n){for(var r=n<0?n+t:n;--r>=0;)e.push(r);return e}),gt:l(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}},T.pseudos.nth=T.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})T.pseudos[b]=s(b);for(b in{submit:!0,reset:!0})T.pseudos[b]=u(b);return f.prototype=T.filters=T.pseudos,T.setFilters=new f,N=t.tokenize=function(e,n){var r,i,o,a,s,u,l,c=z[e+\" \"];if(c)return n?0:c.slice(0);for(s=e,u=[],l=T.preFilter;s;){r&&!(i=ue.exec(s))||(i&&(s=s.slice(i[0].length)||s),u.push(o=[])),r=!1,(i=le.exec(s))&&(r=i.shift(),o.push({value:r,type:i[0].replace(se,\" \")}),s=s.slice(r.length));for(a in T.filter)!(i=pe[a].exec(s))||l[a]&&!(i=l[a](i))||(r=i.shift(),o.push({value:r,type:a,matches:i}),s=s.slice(r.length));if(!r)break}return n?s.length:s?t.error(e):z(e,u).slice(0)},k=t.compile=function(e,t){var n,r=[],i=[],o=X[e+\" \"];if(!o){for(t||(t=N(e)),n=t.length;n--;)o=v(t[n]),o[P]?r.push(o):i.push(o);o=X(e,x(i,r)),o.selector=e}return o},S=t.select=function(e,t,n,r){var i,o,a,s,u,l=\"function\"==typeof e&&e,f=!r&&N(e=l.selector||e);if(n=n||[],1===f.length){if(o=f[0]=f[0].slice(0),o.length>2&&\"ID\"===(a=o[0]).type&&w.getById&&9===t.nodeType&&_&&T.relative[o[1].type]){if(t=(T.find.ID(a.matches[0].replace(be,we),t)||[])[0],!t)return n;l&&(t=t.parentNode),e=e.slice(o.shift().value.length)}for(i=pe.needsContext.test(e)?0:o.length;i--&&(a=o[i],!T.relative[s=a.type]);)if((u=T.find[s])&&(r=u(a.matches[0].replace(be,we),ve.test(o[0].type)&&c(t.parentNode)||t))){if(o.splice(i,1),e=r.length&&d(o),!e)return Q.apply(n,r),n;break}}return(l||k(e,f))(r,t,!_,n,!t||ve.test(e)&&c(t.parentNode)||t),n},w.sortStable=P.split(\"\").sort(U).join(\"\")===P,w.detectDuplicates=!!j,L(),w.sortDetached=i(function(e){return 1&e.compareDocumentPosition(H.createElement(\"div\"))}),i(function(e){return e.innerHTML=\"<a href='#'></a>\",\"#\"===e.firstChild.getAttribute(\"href\")})||o(\"type|href|height|width\",function(e,t,n){if(!n)return e.getAttribute(t,\"type\"===t.toLowerCase()?1:2)}),w.attributes&&i(function(e){return e.innerHTML=\"<input/>\",e.firstChild.setAttribute(\"value\",\"\"),\"\"===e.firstChild.getAttribute(\"value\")})||o(\"value\",function(e,t,n){if(!n&&\"input\"===e.nodeName.toLowerCase())return e.defaultValue}),i(function(e){return null==e.getAttribute(\"disabled\")})||o(te,function(e,t,n){var r;if(!n)return e[t]===!0?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),t}(e);pe.find=ve,pe.expr=ve.selectors,pe.expr[\":\"]=pe.expr.pseudos,pe.uniqueSort=pe.unique=ve.uniqueSort,pe.text=ve.getText,pe.isXMLDoc=ve.isXML,pe.contains=ve.contains;var xe=function(e,t,n){for(var r=[],i=void 0!==n;(e=e[t])&&9!==e.nodeType;)if(1===e.nodeType){if(i&&pe(e).is(n))break;r.push(e)}return r},be=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},we=pe.expr.match.needsContext,Te=/^<([\\w-]+)\\s*\\/?>(?:<\\/\\1>|)$/,Ce=/^.[^:#\\[\\.,]*$/;pe.filter=function(e,t,n){var r=t[0];return n&&(e=\":not(\"+e+\")\"),1===t.length&&1===r.nodeType?pe.find.matchesSelector(r,e)?[r]:[]:pe.find.matches(e,pe.grep(t,function(e){return 1===e.nodeType}))},pe.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if(\"string\"!=typeof e)return this.pushStack(pe(e).filter(function(){for(t=0;t<i;t++)if(pe.contains(r[t],this))return!0}));for(t=0;t<i;t++)pe.find(e,r[t],n);return n=this.pushStack(i>1?pe.unique(n):n),n.selector=this.selector?this.selector+\" \"+e:e,n},filter:function(e){return this.pushStack(r(this,e||[],!1))},not:function(e){return this.pushStack(r(this,e||[],!0))},is:function(e){return!!r(this,\"string\"==typeof e&&we.test(e)?pe(e):e||[],!1).length}});var Ee,Ne=/^(?:\\s*(<[\\w\\W]+>)[^>]*|#([\\w-]*))$/,ke=pe.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||Ee,\"string\"==typeof e){if(r=\"<\"===e.charAt(0)&&\">\"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:Ne.exec(e),!r||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof pe?t[0]:t,pe.merge(this,pe.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:re,!0)),Te.test(r[1])&&pe.isPlainObject(t))for(r in t)pe.isFunction(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}if(i=re.getElementById(r[2]),i&&i.parentNode){if(i.id!==r[2])return Ee.find(e);this.length=1,this[0]=i}return this.context=re,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):pe.isFunction(e)?\"undefined\"!=typeof n.ready?n.ready(e):e(pe):(void 0!==e.selector&&(this.selector=e.selector,this.context=e.context),pe.makeArray(e,this))};ke.prototype=pe.fn,Ee=pe(re);var Se=/^(?:parents|prev(?:Until|All))/,Ae={children:!0,contents:!0,next:!0,prev:!0};pe.fn.extend({has:function(e){var t,n=pe(e,this),r=n.length;return this.filter(function(){for(t=0;t<r;t++)if(pe.contains(this,n[t]))return!0})},closest:function(e,t){for(var n,r=0,i=this.length,o=[],a=we.test(e)||\"string\"!=typeof e?pe(e,t||this.context):0;r<i;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(n.nodeType<11&&(a?a.index(n)>-1:1===n.nodeType&&pe.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(o.length>1?pe.uniqueSort(o):o)},index:function(e){return e?\"string\"==typeof e?pe.inArray(this[0],pe(e)):pe.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(pe.uniqueSort(pe.merge(this.get(),pe(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),pe.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return xe(e,\"parentNode\")},parentsUntil:function(e,t,n){return xe(e,\"parentNode\",n)},next:function(e){return i(e,\"nextSibling\")},prev:function(e){return i(e,\"previousSibling\")},nextAll:function(e){return xe(e,\"nextSibling\")},prevAll:function(e){return xe(e,\"previousSibling\")},nextUntil:function(e,t,n){return xe(e,\"nextSibling\",n)},prevUntil:function(e,t,n){return xe(e,\"previousSibling\",n)},siblings:function(e){return be((e.parentNode||{}).firstChild,e)},children:function(e){return be(e.firstChild)},contents:function(e){return pe.nodeName(e,\"iframe\")?e.contentDocument||e.contentWindow.document:pe.merge([],e.childNodes)}},function(e,t){pe.fn[e]=function(n,r){var i=pe.map(this,t,n);return\"Until\"!==e.slice(-5)&&(r=n),r&&\"string\"==typeof r&&(i=pe.filter(r,i)),this.length>1&&(Ae[e]||(i=pe.uniqueSort(i)),Se.test(e)&&(i=i.reverse())),this.pushStack(i)}});var De=/\\S+/g;pe.Callbacks=function(e){e=\"string\"==typeof e?o(e):pe.extend({},e);var t,n,r,i,a=[],s=[],u=-1,l=function(){for(i=e.once,r=t=!0;s.length;u=-1)for(n=s.shift();++u<a.length;)a[u].apply(n[0],n[1])===!1&&e.stopOnFalse&&(u=a.length,n=!1);e.memory||(n=!1),t=!1,i&&(a=n?[]:\"\")},c={add:function(){return a&&(n&&!t&&(u=a.length-1,s.push(n)),function r(t){pe.each(t,function(t,n){pe.isFunction(n)?e.unique&&c.has(n)||a.push(n):n&&n.length&&\"string\"!==pe.type(n)&&r(n)})}(arguments),n&&!t&&l()),this},remove:function(){return pe.each(arguments,function(e,t){for(var n;(n=pe.inArray(t,a,n))>-1;)a.splice(n,1),n<=u&&u--}),this},has:function(e){return e?pe.inArray(e,a)>-1:a.length>0},empty:function(){return a&&(a=[]),this},disable:function(){return i=s=[],a=n=\"\",this},disabled:function(){return!a},lock:function(){return i=!0,n||c.disable(),this},locked:function(){return!!i},fireWith:function(e,n){return i||(n=n||[],n=[e,n.slice?n.slice():n],s.push(n),t||l()),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!r}};return c},pe.extend({Deferred:function(e){var t=[[\"resolve\",\"done\",pe.Callbacks(\"once memory\"),\"resolved\"],[\"reject\",\"fail\",pe.Callbacks(\"once memory\"),\"rejected\"],[\"notify\",\"progress\",pe.Callbacks(\"memory\")]],n=\"pending\",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return pe.Deferred(function(n){pe.each(t,function(t,o){var a=pe.isFunction(e[t])&&e[t];i[o[1]](function(){var e=a&&a.apply(this,arguments);e&&pe.isFunction(e.promise)?e.promise().progress(n.notify).done(n.resolve).fail(n.reject):n[o[0]+\"With\"](this===r?n.promise():this,a?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?pe.extend(e,r):r}},i={};return r.pipe=r.then,pe.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,n,r,i=0,o=ie.call(arguments),a=o.length,s=1!==a||e&&pe.isFunction(e.promise)?a:0,u=1===s?e:pe.Deferred(),l=function(e,n,r){return function(i){n[e]=this,r[e]=arguments.length>1?ie.call(arguments):i,r===t?u.notifyWith(n,r):--s||u.resolveWith(n,r)}};if(a>1)for(t=new Array(a),n=new Array(a),r=new Array(a);i<a;i++)o[i]&&pe.isFunction(o[i].promise)?o[i].promise().progress(l(i,n,t)).done(l(i,r,o)).fail(u.reject):--s;return s||u.resolveWith(r,o),u.promise()}});var je;pe.fn.ready=function(e){return pe.ready.promise().done(e),this},pe.extend({isReady:!1,readyWait:1,holdReady:function(e){e?pe.readyWait++:pe.ready(!0)},ready:function(e){(e===!0?--pe.readyWait:pe.isReady)||(pe.isReady=!0,e!==!0&&--pe.readyWait>0||(je.resolveWith(re,[pe]),pe.fn.triggerHandler&&(pe(re).triggerHandler(\"ready\"),pe(re).off(\"ready\"))))}}),pe.ready.promise=function(t){if(!je)if(je=pe.Deferred(),\"complete\"===re.readyState||\"loading\"!==re.readyState&&!re.documentElement.doScroll)e.setTimeout(pe.ready);else if(re.addEventListener)re.addEventListener(\"DOMContentLoaded\",s),e.addEventListener(\"load\",s);else{re.attachEvent(\"onreadystatechange\",s),e.attachEvent(\"onload\",s);var n=!1;try{n=null==e.frameElement&&re.documentElement}catch(r){}n&&n.doScroll&&!function i(){if(!pe.isReady){try{n.doScroll(\"left\")}catch(t){return e.setTimeout(i,50)}a(),pe.ready()}}()}return je.promise(t)},pe.ready.promise();var Le;for(Le in pe(fe))break;fe.ownFirst=\"0\"===Le,fe.inlineBlockNeedsLayout=!1,pe(function(){var e,t,n,r;n=re.getElementsByTagName(\"body\")[0],n&&n.style&&(t=re.createElement(\"div\"),r=re.createElement(\"div\"),r.style.cssText=\"position:absolute;border:0;width:0;height:0;top:0;left:-9999px\",n.appendChild(r).appendChild(t),\"undefined\"!=typeof t.style.zoom&&(t.style.cssText=\"display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1\",fe.inlineBlockNeedsLayout=e=3===t.offsetWidth,e&&(n.style.zoom=1)),n.removeChild(r))}),function(){var e=re.createElement(\"div\");fe.deleteExpando=!0;try{delete e.test}catch(t){fe.deleteExpando=!1}e=null}();var He=function(e){var t=pe.noData[(e.nodeName+\" \").toLowerCase()],n=+e.nodeType||1;return(1===n||9===n)&&(!t||t!==!0&&e.getAttribute(\"classid\")===t)},qe=/^(?:\\{[\\w\\W]*\\}|\\[[\\w\\W]*\\])$/,_e=/([A-Z])/g;pe.extend({cache:{},noData:{\"applet \":!0,\"embed \":!0,\"object \":\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"},hasData:function(e){return e=e.nodeType?pe.cache[e[pe.expando]]:e[pe.expando],!!e&&!l(e)},data:function(e,t,n){return c(e,t,n)},removeData:function(e,t){return f(e,t)},_data:function(e,t,n){return c(e,t,n,!0)},_removeData:function(e,t){return f(e,t,!0)}}),pe.fn.extend({data:function(e,t){var n,r,i,o=this[0],a=o&&o.attributes;if(void 0===e){if(this.length&&(i=pe.data(o),1===o.nodeType&&!pe._data(o,\"parsedAttrs\"))){for(n=a.length;n--;)a[n]&&(r=a[n].name,0===r.indexOf(\"data-\")&&(r=pe.camelCase(r.slice(5)),u(o,r,i[r])));pe._data(o,\"parsedAttrs\",!0)}return i}return\"object\"==typeof e?this.each(function(){pe.data(this,e)}):arguments.length>1?this.each(function(){pe.data(this,e,t)}):o?u(o,e,pe.data(o,e)):void 0},removeData:function(e){return this.each(function(){pe.removeData(this,e)})}}),pe.extend({queue:function(e,t,n){var r;if(e)return t=(t||\"fx\")+\"queue\",r=pe._data(e,t),n&&(!r||pe.isArray(n)?r=pe._data(e,t,pe.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||\"fx\";var n=pe.queue(e,t),r=n.length,i=n.shift(),o=pe._queueHooks(e,t),a=function(){pe.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 pe._data(e,n)||pe._data(e,n,{empty:pe.Callbacks(\"once memory\").add(function(){pe._removeData(e,t+\"queue\"),pe._removeData(e,n)})})}}),pe.fn.extend({queue:function(e,t){var n=2;return\"string\"!=typeof e&&(t=e,e=\"fx\",n--),arguments.length<n?pe.queue(this[0],e):void 0===t?this:this.each(function(){var n=pe.queue(this,e,t);pe._queueHooks(this,e),\"fx\"===e&&\"inprogress\"!==n[0]&&pe.dequeue(this,e)})},dequeue:function(e){return this.each(function(){pe.dequeue(this,e)})},clearQueue:function(e){return this.queue(e||\"fx\",[])},promise:function(e,t){var n,r=1,i=pe.Deferred(),o=this,a=this.length,s=function(){--r||i.resolveWith(o,[o])};for(\"string\"!=typeof e&&(t=e,e=void 0),e=e||\"fx\";a--;)n=pe._data(o[a],e+\"queueHooks\"),n&&n.empty&&(r++,n.empty.add(s));return s(),i.promise(t)}}),function(){var e;fe.shrinkWrapBlocks=function(){if(null!=e)return e;e=!1;var t,n,r;return n=re.getElementsByTagName(\"body\")[0],n&&n.style?(t=re.createElement(\"div\"),r=re.createElement(\"div\"),r.style.cssText=\"position:absolute;border:0;width:0;height:0;top:0;left:-9999px\",n.appendChild(r).appendChild(t),\"undefined\"!=typeof t.style.zoom&&(t.style.cssText=\"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:1px;width:1px;zoom:1\",t.appendChild(re.createElement(\"div\")).style.width=\"5px\",e=3!==t.offsetWidth),n.removeChild(r),e):void 0}}();var Fe=/[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/.source,Me=new RegExp(\"^(?:([+-])=|)(\"+Fe+\")([a-z%]*)$\",\"i\"),Oe=[\"Top\",\"Right\",\"Bottom\",\"Left\"],Re=function(e,t){return e=t||e,\"none\"===pe.css(e,\"display\")||!pe.contains(e.ownerDocument,e)},Pe=function(e,t,n,r,i,o,a){var s=0,u=e.length,l=null==n;if(\"object\"===pe.type(n)){i=!0;for(s in n)Pe(e,t,s,n[s],!0,o,a)}else if(void 0!==r&&(i=!0,pe.isFunction(r)||(a=!0),l&&(a?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(pe(e),n)})),t))for(;s<u;s++)t(e[s],n,a?r:r.call(e[s],s,t(e[s],n)));return i?e:l?t.call(e):u?t(e[0],n):o},Be=/^(?:checkbox|radio)$/i,We=/<([\\w:-]+)/,Ie=/^$|\\/(?:java|ecma)script/i,$e=/^\\s+/,ze=\"abbr|article|aside|audio|bdi|canvas|data|datalist|details|dialog|figcaption|figure|footer|header|hgroup|main|mark|meter|nav|output|picture|progress|section|summary|template|time|video\";!function(){var e=re.createElement(\"div\"),t=re.createDocumentFragment(),n=re.createElement(\"input\");e.innerHTML=\"  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>\",fe.leadingWhitespace=3===e.firstChild.nodeType,fe.tbody=!e.getElementsByTagName(\"tbody\").length,fe.htmlSerialize=!!e.getElementsByTagName(\"link\").length,fe.html5Clone=\"<:nav></:nav>\"!==re.createElement(\"nav\").cloneNode(!0).outerHTML,n.type=\"checkbox\",n.checked=!0,t.appendChild(n),fe.appendChecked=n.checked,e.innerHTML=\"<textarea>x</textarea>\",fe.noCloneChecked=!!e.cloneNode(!0).lastChild.defaultValue,t.appendChild(e),n=re.createElement(\"input\"),n.setAttribute(\"type\",\"radio\"),n.setAttribute(\"checked\",\"checked\"),n.setAttribute(\"name\",\"t\"),e.appendChild(n),fe.checkClone=e.cloneNode(!0).cloneNode(!0).lastChild.checked,fe.noCloneEvent=!!e.addEventListener,e[pe.expando]=1,fe.attributes=!e.getAttribute(pe.expando)}();var Xe={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:fe.htmlSerialize?[0,\"\",\"\"]:[1,\"X<div>\",\"</div>\"]};Xe.optgroup=Xe.option,Xe.tbody=Xe.tfoot=Xe.colgroup=Xe.caption=Xe.thead,Xe.th=Xe.td;var Ue=/<|&#?\\w+;/,Ve=/<tbody/i;!function(){var t,n,r=re.createElement(\"div\");for(t in{submit:!0,change:!0,focusin:!0})n=\"on\"+t,(fe[t]=n in e)||(r.setAttribute(n,\"t\"),fe[t]=r.attributes[n].expando===!1);r=null}();var Ye=/^(?:input|select|textarea)$/i,Je=/^key/,Ge=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ke=/^(?:focusinfocus|focusoutblur)$/,Qe=/^([^.]*)(?:\\.(.+)|)/;pe.event={global:{},add:function(e,t,n,r,i){var o,a,s,u,l,c,f,d,p,h,g,m=pe._data(e);if(m){for(n.handler&&(u=n,n=u.handler,i=u.selector),n.guid||(n.guid=pe.guid++),(a=m.events)||(a=m.events={}),(c=m.handle)||(c=m.handle=function(e){return\"undefined\"==typeof pe||e&&pe.event.triggered===e.type?void 0:pe.event.dispatch.apply(c.elem,arguments)},c.elem=e),t=(t||\"\").match(De)||[\"\"],s=t.length;s--;)o=Qe.exec(t[s])||[],p=g=o[1],h=(o[2]||\"\").split(\".\").sort(),p&&(l=pe.event.special[p]||{},p=(i?l.delegateType:l.bindType)||p,l=pe.event.special[p]||{},f=pe.extend({type:p,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&pe.expr.match.needsContext.test(i),namespace:h.join(\".\")},u),(d=a[p])||(d=a[p]=[],d.delegateCount=0,l.setup&&l.setup.call(e,r,h,c)!==!1||(e.addEventListener?e.addEventListener(p,c,!1):e.attachEvent&&e.attachEvent(\"on\"+p,c))),l.add&&(l.add.call(e,f),f.handler.guid||(f.handler.guid=n.guid)),i?d.splice(d.delegateCount++,0,f):d.push(f),pe.event.global[p]=!0);e=null}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,d,p,h,g,m=pe.hasData(e)&&pe._data(e);if(m&&(c=m.events)){for(t=(t||\"\").match(De)||[\"\"],l=t.length;l--;)if(s=Qe.exec(t[l])||[],p=g=s[1],h=(s[2]||\"\").split(\".\").sort(),p){for(f=pe.event.special[p]||{},p=(r?f.delegateType:f.bindType)||p,d=c[p]||[],s=s[2]&&new RegExp(\"(^|\\\\.)\"+h.join(\"\\\\.(?:.*\\\\.|)\")+\"(\\\\.|$)\"),u=o=d.length;o--;)a=d[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&(\"**\"!==r||!a.selector)||(d.splice(o,1),a.selector&&d.delegateCount--,f.remove&&f.remove.call(e,a));u&&!d.length&&(f.teardown&&f.teardown.call(e,h,m.handle)!==!1||pe.removeEvent(e,p,m.handle),delete c[p])}else for(p in c)pe.event.remove(e,p+t[l],n,r,!0);pe.isEmptyObject(c)&&(delete m.handle,pe._removeData(e,\"events\"))}},trigger:function(t,n,r,i){var o,a,s,u,l,c,f,d=[r||re],p=ce.call(t,\"type\")?t.type:t,h=ce.call(t,\"namespace\")?t.namespace.split(\".\"):[];if(s=c=r=r||re,3!==r.nodeType&&8!==r.nodeType&&!Ke.test(p+pe.event.triggered)&&(p.indexOf(\".\")>-1&&(h=p.split(\".\"),p=h.shift(),h.sort()),a=p.indexOf(\":\")<0&&\"on\"+p,t=t[pe.expando]?t:new pe.Event(p,\"object\"==typeof t&&t),t.isTrigger=i?2:3,t.namespace=h.join(\".\"),t.rnamespace=t.namespace?new RegExp(\"(^|\\\\.)\"+h.join(\"\\\\.(?:.*\\\\.|)\")+\"(\\\\.|$)\"):null,t.result=void 0,t.target||(t.target=r),n=null==n?[t]:pe.makeArray(n,[t]),l=pe.event.special[p]||{},i||!l.trigger||l.trigger.apply(r,n)!==!1)){if(!i&&!l.noBubble&&!pe.isWindow(r)){for(u=l.delegateType||p,Ke.test(u+p)||(s=s.parentNode);s;s=s.parentNode)d.push(s),c=s;c===(r.ownerDocument||re)&&d.push(c.defaultView||c.parentWindow||e)}for(f=0;(s=d[f++])&&!t.isPropagationStopped();)t.type=f>1?u:l.bindType||p,o=(pe._data(s,\"events\")||{})[t.type]&&pe._data(s,\"handle\"),o&&o.apply(s,n),o=a&&s[a],o&&o.apply&&He(s)&&(t.result=o.apply(s,n),t.result===!1&&t.preventDefault());if(t.type=p,!i&&!t.isDefaultPrevented()&&(!l._default||l._default.apply(d.pop(),n)===!1)&&He(r)&&a&&r[p]&&!pe.isWindow(r)){c=r[a],c&&(r[a]=null),pe.event.triggered=p;try{r[p]()}catch(g){}pe.event.triggered=void 0,c&&(r[a]=c)}return t.result}},dispatch:function(e){e=pe.event.fix(e);var t,n,r,i,o,a=[],s=ie.call(arguments),u=(pe._data(this,\"events\")||{})[e.type]||[],l=pe.event.special[e.type]||{};if(s[0]=e,e.delegateTarget=this,!l.preDispatch||l.preDispatch.call(this,e)!==!1){for(a=pe.event.handlers.call(this,e,u),t=0;(i=a[t++])&&!e.isPropagationStopped();)for(e.currentTarget=i.elem,n=0;(o=i.handlers[n++])&&!e.isImmediatePropagationStopped();)e.rnamespace&&!e.rnamespace.test(o.namespace)||(e.handleObj=o,e.data=o.data,r=((pe.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,s),void 0!==r&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()));return l.postDispatch&&l.postDispatch.call(this,e),e.result}},handlers:function(e,t){var n,r,i,o,a=[],s=t.delegateCount,u=e.target;if(s&&u.nodeType&&(\"click\"!==e.type||isNaN(e.button)||e.button<1))for(;u!=this;u=u.parentNode||this)if(1===u.nodeType&&(u.disabled!==!0||\"click\"!==e.type)){for(r=[],n=0;n<s;n++)o=t[n],i=o.selector+\" \",void 0===r[i]&&(r[i]=o.needsContext?pe(i,this).index(u)>-1:pe.find(i,this,null,[u]).length),r[i]&&r.push(o);r.length&&a.push({elem:u,handlers:r})}return s<t.length&&a.push({elem:this,handlers:t.slice(s)}),a},fix:function(e){if(e[pe.expando])return e;var t,n,r,i=e.type,o=e,a=this.fixHooks[i];for(a||(this.fixHooks[i]=a=Ge.test(i)?this.mouseHooks:Je.test(i)?this.keyHooks:{}),r=a.props?this.props.concat(a.props):this.props,e=new pe.Event(o),t=r.length;t--;)n=r[t],e[n]=o[n];return e.target||(e.target=o.srcElement||re),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,a.filter?a.filter(e,o):e},props:\"altKey bubbles cancelable ctrlKey currentTarget detail 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,t){var n,r,i,o=t.button,a=t.fromElement;return null==e.pageX&&null!=t.clientX&&(r=e.target.ownerDocument||re,i=r.documentElement,n=r.body,e.pageX=t.clientX+(i&&i.scrollLeft||n&&n.scrollLeft||0)-(i&&i.clientLeft||n&&n.clientLeft||0),e.pageY=t.clientY+(i&&i.scrollTop||n&&n.scrollTop||0)-(i&&i.clientTop||n&&n.clientTop||0)),!e.relatedTarget&&a&&(e.relatedTarget=a===e.target?t.toElement:a),e.which||void 0===o||(e.which=1&o?1:2&o?3:4&o?2:0),e}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==b()&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:\"focusin\"},blur:{trigger:function(){if(this===b()&&this.blur)return this.blur(),!1},delegateType:\"focusout\"},click:{trigger:function(){if(pe.nodeName(this,\"input\")&&\"checkbox\"===this.type&&this.click)return this.click(),!1},_default:function(e){return pe.nodeName(e.target,\"a\")}},beforeunload:{postDispatch:function(e){void 0!==e.result&&e.originalEvent&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n){var r=pe.extend(new pe.Event,n,{type:e,isSimulated:!0});pe.event.trigger(r,null,t),r.isDefaultPrevented()&&n.preventDefault()}},pe.removeEvent=re.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n)}:function(e,t,n){var r=\"on\"+t;e.detachEvent&&(\"undefined\"==typeof e[r]&&(e[r]=null),e.detachEvent(r,n))},pe.Event=function(e,t){return this instanceof pe.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||void 0===e.defaultPrevented&&e.returnValue===!1?v:x):this.type=e,t&&pe.extend(this,t),this.timeStamp=e&&e.timeStamp||pe.now(),void(this[pe.expando]=!0)):new pe.Event(e,t)},pe.Event.prototype={constructor:pe.Event,isDefaultPrevented:x,isPropagationStopped:x,isImmediatePropagationStopped:x,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=v,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=v,e&&!this.isSimulated&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){var e=this.originalEvent;this.isImmediatePropagationStopped=v,e&&e.stopImmediatePropagation&&e.stopImmediatePropagation(),this.stopPropagation()}},pe.each({mouseenter:\"mouseover\",mouseleave:\"mouseout\",pointerenter:\"pointerover\",pointerleave:\"pointerout\"},function(e,t){pe.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return i&&(i===r||pe.contains(r,i))||(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),fe.submit||(pe.event.special.submit={setup:function(){return!pe.nodeName(this,\"form\")&&void pe.event.add(this,\"click._submit keypress._submit\",function(e){var t=e.target,n=pe.nodeName(t,\"input\")||pe.nodeName(t,\"button\")?pe.prop(t,\"form\"):void 0;n&&!pe._data(n,\"submit\")&&(pe.event.add(n,\"submit._submit\",function(e){e._submitBubble=!0}),pe._data(n,\"submit\",!0))})},postDispatch:function(e){e._submitBubble&&(delete e._submitBubble,this.parentNode&&!e.isTrigger&&pe.event.simulate(\"submit\",this.parentNode,e))},teardown:function(){return!pe.nodeName(this,\"form\")&&void pe.event.remove(this,\"._submit\")}}),fe.change||(pe.event.special.change={setup:function(){return Ye.test(this.nodeName)?(\"checkbox\"!==this.type&&\"radio\"!==this.type||(pe.event.add(this,\"propertychange._change\",function(e){\"checked\"===e.originalEvent.propertyName&&(this._justChanged=!0)}),pe.event.add(this,\"click._change\",function(e){this._justChanged&&!e.isTrigger&&(this._justChanged=!1),pe.event.simulate(\"change\",this,e)})),!1):void pe.event.add(this,\"beforeactivate._change\",function(e){var t=e.target;Ye.test(t.nodeName)&&!pe._data(t,\"change\")&&(pe.event.add(t,\"change._change\",function(e){!this.parentNode||e.isSimulated||e.isTrigger||pe.event.simulate(\"change\",this.parentNode,e)}),pe._data(t,\"change\",!0))})},handle:function(e){var t=e.target;if(this!==t||e.isSimulated||e.isTrigger||\"radio\"!==t.type&&\"checkbox\"!==t.type)return e.handleObj.handler.apply(this,arguments)},teardown:function(){return pe.event.remove(this,\"._change\"),!Ye.test(this.nodeName)}}),fe.focusin||pe.each({focus:\"focusin\",blur:\"focusout\"},function(e,t){var n=function(e){pe.event.simulate(t,e.target,pe.event.fix(e))};pe.event.special[t]={setup:function(){var r=this.ownerDocument||this,i=pe._data(r,t);i||r.addEventListener(e,n,!0),pe._data(r,t,(i||0)+1)},teardown:function(){var r=this.ownerDocument||this,i=pe._data(r,t)-1;i?pe._data(r,t,i):(r.removeEventListener(e,n,!0),pe._removeData(r,t))}}}),pe.fn.extend({on:function(e,t,n,r){return w(this,e,t,n,r)},one:function(e,t,n,r){return w(this,e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,pe(e.delegateTarget).off(r.namespace?r.origType+\".\"+r.namespace:r.origType,r.selector,r.handler),this;if(\"object\"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return t!==!1&&\"function\"!=typeof t||(n=t,t=void 0),n===!1&&(n=x),this.each(function(){pe.event.remove(this,e,n,t)})},trigger:function(e,t){return this.each(function(){pe.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return pe.event.trigger(e,t,n,!0)}});var Ze=/ jQuery\\d+=\"(?:null|\\d+)\"/g,et=new RegExp(\"<(?:\"+ze+\")[\\\\s/>]\",\"i\"),tt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:-]+)[^>]*)\\/>/gi,nt=/<script|<style|<link/i,rt=/checked\\s*(?:[^=]|=\\s*.checked.)/i,it=/^true\\/(.*)/,ot=/^\\s*<!(?:\\[CDATA\\[|--)|(?:\\]\\]|--)>\\s*$/g,at=p(re),st=at.appendChild(re.createElement(\"div\"));pe.extend({htmlPrefilter:function(e){return e.replace(tt,\"<$1></$2>\")},clone:function(e,t,n){var r,i,o,a,s,u=pe.contains(e.ownerDocument,e);if(fe.html5Clone||pe.isXMLDoc(e)||!et.test(\"<\"+e.nodeName+\">\")?o=e.cloneNode(!0):(st.innerHTML=e.outerHTML,st.removeChild(o=st.firstChild)),!(fe.noCloneEvent&&fe.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||pe.isXMLDoc(e)))for(r=h(o),s=h(e),a=0;null!=(i=s[a]);++a)r[a]&&k(i,r[a]);if(t)if(n)for(s=s||h(e),r=r||h(o),a=0;null!=(i=s[a]);a++)N(i,r[a]);else N(e,o);return r=h(o,\"script\"),r.length>0&&g(r,!u&&h(e,\"script\")),r=s=i=null,o},cleanData:function(e,t){for(var n,r,i,o,a=0,s=pe.expando,u=pe.cache,l=fe.attributes,c=pe.event.special;null!=(n=e[a]);a++)if((t||He(n))&&(i=n[s],o=i&&u[i])){if(o.events)for(r in o.events)c[r]?pe.event.remove(n,r):pe.removeEvent(n,r,o.handle);u[i]&&(delete u[i],l||\"undefined\"==typeof n.removeAttribute?n[s]=void 0:n.removeAttribute(s),ne.push(i))}}}),pe.fn.extend({domManip:S,detach:function(e){return A(this,e,!0)},remove:function(e){return A(this,e)},text:function(e){return Pe(this,function(e){return void 0===e?pe.text(this):this.empty().append((this[0]&&this[0].ownerDocument||re).createTextNode(e))},null,e,arguments.length)},append:function(){return S(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=T(this,e);t.appendChild(e)}})},prepend:function(){return S(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=T(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return S(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return S(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++){for(1===e.nodeType&&pe.cleanData(h(e,!1));e.firstChild;)e.removeChild(e.firstChild);e.options&&pe.nodeName(e,\"select\")&&(e.options.length=0)}return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return pe.clone(this,e,t)})},html:function(e){return Pe(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e)return 1===t.nodeType?t.innerHTML.replace(Ze,\"\"):void 0;if(\"string\"==typeof e&&!nt.test(e)&&(fe.htmlSerialize||!et.test(e))&&(fe.leadingWhitespace||!$e.test(e))&&!Xe[(We.exec(e)||[\"\",\"\"])[1].toLowerCase()]){e=pe.htmlPrefilter(e);try{for(;n<r;n++)t=this[n]||{},1===t.nodeType&&(pe.cleanData(h(t,!1)),t.innerHTML=e);t=0}catch(i){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=[];return S(this,arguments,function(t){var n=this.parentNode;pe.inArray(this,e)<0&&(pe.cleanData(h(this)),\nn&&n.replaceChild(t,this))},e)}}),pe.each({appendTo:\"append\",prependTo:\"prepend\",insertBefore:\"before\",insertAfter:\"after\",replaceAll:\"replaceWith\"},function(e,t){pe.fn[e]=function(e){for(var n,r=0,i=[],o=pe(e),a=o.length-1;r<=a;r++)n=r===a?this:this.clone(!0),pe(o[r])[t](n),ae.apply(i,n.get());return this.pushStack(i)}});var ut,lt={HTML:\"block\",BODY:\"block\"},ct=/^margin/,ft=new RegExp(\"^(\"+Fe+\")(?!px)[a-z%]+$\",\"i\"),dt=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},pt=re.documentElement;!function(){function t(){var t,c,f=re.documentElement;f.appendChild(u),l.style.cssText=\"-webkit-box-sizing:border-box;box-sizing:border-box;position:relative;display:block;margin:auto;border:1px;padding:1px;top:1%;width:50%\",n=i=s=!1,r=a=!0,e.getComputedStyle&&(c=e.getComputedStyle(l),n=\"1%\"!==(c||{}).top,s=\"2px\"===(c||{}).marginLeft,i=\"4px\"===(c||{width:\"4px\"}).width,l.style.marginRight=\"50%\",r=\"4px\"===(c||{marginRight:\"4px\"}).marginRight,t=l.appendChild(re.createElement(\"div\")),t.style.cssText=l.style.cssText=\"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0\",t.style.marginRight=t.style.width=\"0\",l.style.width=\"1px\",a=!parseFloat((e.getComputedStyle(t)||{}).marginRight),l.removeChild(t)),l.style.display=\"none\",o=0===l.getClientRects().length,o&&(l.style.display=\"\",l.innerHTML=\"<table><tr><td></td><td>t</td></tr></table>\",t=l.getElementsByTagName(\"td\"),t[0].style.cssText=\"margin:0;border:0;padding:0;display:none\",o=0===t[0].offsetHeight,o&&(t[0].style.display=\"\",t[1].style.display=\"none\",o=0===t[0].offsetHeight)),f.removeChild(u)}var n,r,i,o,a,s,u=re.createElement(\"div\"),l=re.createElement(\"div\");l.style&&(l.style.cssText=\"float:left;opacity:.5\",fe.opacity=\"0.5\"===l.style.opacity,fe.cssFloat=!!l.style.cssFloat,l.style.backgroundClip=\"content-box\",l.cloneNode(!0).style.backgroundClip=\"\",fe.clearCloneStyle=\"content-box\"===l.style.backgroundClip,u=re.createElement(\"div\"),u.style.cssText=\"border:0;width:8px;height:0;top:0;left:-9999px;padding:0;margin-top:1px;position:absolute\",l.innerHTML=\"\",u.appendChild(l),fe.boxSizing=\"\"===l.style.boxSizing||\"\"===l.style.MozBoxSizing||\"\"===l.style.WebkitBoxSizing,pe.extend(fe,{reliableHiddenOffsets:function(){return null==n&&t(),o},boxSizingReliable:function(){return null==n&&t(),i},pixelMarginRight:function(){return null==n&&t(),r},pixelPosition:function(){return null==n&&t(),n},reliableMarginRight:function(){return null==n&&t(),a},reliableMarginLeft:function(){return null==n&&t(),s}}))}();var ht,gt,mt=/^(top|right|bottom|left)$/;e.getComputedStyle?(ht=function(t){var n=t.ownerDocument.defaultView;return n&&n.opener||(n=e),n.getComputedStyle(t)},gt=function(e,t,n){var r,i,o,a,s=e.style;return n=n||ht(e),a=n?n.getPropertyValue(t)||n[t]:void 0,\"\"!==a&&void 0!==a||pe.contains(e.ownerDocument,e)||(a=pe.style(e,t)),n&&!fe.pixelMarginRight()&&ft.test(a)&&ct.test(t)&&(r=s.width,i=s.minWidth,o=s.maxWidth,s.minWidth=s.maxWidth=s.width=a,a=n.width,s.width=r,s.minWidth=i,s.maxWidth=o),void 0===a?a:a+\"\"}):pt.currentStyle&&(ht=function(e){return e.currentStyle},gt=function(e,t,n){var r,i,o,a,s=e.style;return n=n||ht(e),a=n?n[t]:void 0,null==a&&s&&s[t]&&(a=s[t]),ft.test(a)&&!mt.test(t)&&(r=s.left,i=e.runtimeStyle,o=i&&i.left,o&&(i.left=e.currentStyle.left),s.left=\"fontSize\"===t?\"1em\":a,a=s.pixelLeft+\"px\",s.left=r,o&&(i.left=o)),void 0===a?a:a+\"\"||\"auto\"});var yt=/alpha\\([^)]*\\)/i,vt=/opacity\\s*=\\s*([^)]*)/i,xt=/^(none|table(?!-c[ea]).+)/,bt=new RegExp(\"^(\"+Fe+\")(.*)$\",\"i\"),wt={position:\"absolute\",visibility:\"hidden\",display:\"block\"},Tt={letterSpacing:\"0\",fontWeight:\"400\"},Ct=[\"Webkit\",\"O\",\"Moz\",\"ms\"],Et=re.createElement(\"div\").style;pe.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=gt(e,\"opacity\");return\"\"===n?\"1\":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{\"float\":fe.cssFloat?\"cssFloat\":\"styleFloat\"},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=pe.camelCase(t),u=e.style;if(t=pe.cssProps[s]||(pe.cssProps[s]=H(s)||s),a=pe.cssHooks[t]||pe.cssHooks[s],void 0===n)return a&&\"get\"in a&&void 0!==(i=a.get(e,!1,r))?i:u[t];if(o=typeof n,\"string\"===o&&(i=Me.exec(n))&&i[1]&&(n=d(e,t,i),o=\"number\"),null!=n&&n===n&&(\"number\"===o&&(n+=i&&i[3]||(pe.cssNumber[s]?\"\":\"px\")),fe.clearCloneStyle||\"\"!==n||0!==t.indexOf(\"background\")||(u[t]=\"inherit\"),!(a&&\"set\"in a&&void 0===(n=a.set(e,n,r)))))try{u[t]=n}catch(l){}}},css:function(e,t,n,r){var i,o,a,s=pe.camelCase(t);return t=pe.cssProps[s]||(pe.cssProps[s]=H(s)||s),a=pe.cssHooks[t]||pe.cssHooks[s],a&&\"get\"in a&&(o=a.get(e,!0,n)),void 0===o&&(o=gt(e,t,r)),\"normal\"===o&&t in Tt&&(o=Tt[t]),\"\"===n||n?(i=parseFloat(o),n===!0||isFinite(i)?i||0:o):o}}),pe.each([\"height\",\"width\"],function(e,t){pe.cssHooks[t]={get:function(e,n,r){if(n)return xt.test(pe.css(e,\"display\"))&&0===e.offsetWidth?dt(e,wt,function(){return M(e,t,r)}):M(e,t,r)},set:function(e,n,r){var i=r&&ht(e);return _(e,n,r?F(e,t,r,fe.boxSizing&&\"border-box\"===pe.css(e,\"boxSizing\",!1,i),i):0)}}}),fe.opacity||(pe.cssHooks.opacity={get:function(e,t){return vt.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=pe.isNumeric(t)?\"alpha(opacity=\"+100*t+\")\":\"\",o=r&&r.filter||n.filter||\"\";n.zoom=1,(t>=1||\"\"===t)&&\"\"===pe.trim(o.replace(yt,\"\"))&&n.removeAttribute&&(n.removeAttribute(\"filter\"),\"\"===t||r&&!r.filter)||(n.filter=yt.test(o)?o.replace(yt,i):o+\" \"+i)}}),pe.cssHooks.marginRight=L(fe.reliableMarginRight,function(e,t){if(t)return dt(e,{display:\"inline-block\"},gt,[e,\"marginRight\"])}),pe.cssHooks.marginLeft=L(fe.reliableMarginLeft,function(e,t){if(t)return(parseFloat(gt(e,\"marginLeft\"))||(pe.contains(e.ownerDocument,e)?e.getBoundingClientRect().left-dt(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}):0))+\"px\"}),pe.each({margin:\"\",padding:\"\",border:\"Width\"},function(e,t){pe.cssHooks[e+t]={expand:function(n){for(var r=0,i={},o=\"string\"==typeof n?n.split(\" \"):[n];r<4;r++)i[e+Oe[r]+t]=o[r]||o[r-2]||o[0];return i}},ct.test(e)||(pe.cssHooks[e+t].set=_)}),pe.fn.extend({css:function(e,t){return Pe(this,function(e,t,n){var r,i,o={},a=0;if(pe.isArray(t)){for(r=ht(e),i=t.length;a<i;a++)o[t[a]]=pe.css(e,t[a],!1,r);return o}return void 0!==n?pe.style(e,t,n):pe.css(e,t)},e,t,arguments.length>1)},show:function(){return q(this,!0)},hide:function(){return q(this)},toggle:function(e){return\"boolean\"==typeof e?e?this.show():this.hide():this.each(function(){Re(this)?pe(this).show():pe(this).hide()})}}),pe.Tween=O,O.prototype={constructor:O,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||pe.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(pe.cssNumber[n]?\"\":\"px\")},cur:function(){var e=O.propHooks[this.prop];return e&&e.get?e.get(this):O.propHooks._default.get(this)},run:function(e){var t,n=O.propHooks[this.prop];return this.options.duration?this.pos=t=pe.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=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):O.propHooks._default.set(this),this}},O.prototype.init.prototype=O.prototype,O.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=pe.css(e.elem,e.prop,\"\"),t&&\"auto\"!==t?t:0)},set:function(e){pe.fx.step[e.prop]?pe.fx.step[e.prop](e):1!==e.elem.nodeType||null==e.elem.style[pe.cssProps[e.prop]]&&!pe.cssHooks[e.prop]?e.elem[e.prop]=e.now:pe.style(e.elem,e.prop,e.now+e.unit)}}},O.propHooks.scrollTop=O.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},pe.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:\"swing\"},pe.fx=O.prototype.init,pe.fx.step={};var Nt,kt,St=/^(?:toggle|show|hide)$/,At=/queueHooks$/;pe.Animation=pe.extend($,{tweeners:{\"*\":[function(e,t){var n=this.createTween(e,t);return d(n.elem,e,Me.exec(t),n),n}]},tweener:function(e,t){pe.isFunction(e)?(t=e,e=[\"*\"]):e=e.match(De);for(var n,r=0,i=e.length;r<i;r++)n=e[r],$.tweeners[n]=$.tweeners[n]||[],$.tweeners[n].unshift(t)},prefilters:[W],prefilter:function(e,t){t?$.prefilters.unshift(e):$.prefilters.push(e)}}),pe.speed=function(e,t,n){var r=e&&\"object\"==typeof e?pe.extend({},e):{complete:n||!n&&t||pe.isFunction(e)&&e,duration:e,easing:n&&t||t&&!pe.isFunction(t)&&t};return r.duration=pe.fx.off?0:\"number\"==typeof r.duration?r.duration:r.duration in pe.fx.speeds?pe.fx.speeds[r.duration]:pe.fx.speeds._default,null!=r.queue&&r.queue!==!0||(r.queue=\"fx\"),r.old=r.complete,r.complete=function(){pe.isFunction(r.old)&&r.old.call(this),r.queue&&pe.dequeue(this,r.queue)},r},pe.fn.extend({fadeTo:function(e,t,n,r){return this.filter(Re).css(\"opacity\",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=pe.isEmptyObject(e),o=pe.speed(t,n,r),a=function(){var t=$(this,pe.extend({},e),o);(i||pe._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,t,n){var r=function(e){var t=e.stop;delete e.stop,t(n)};return\"string\"!=typeof e&&(n=t,t=e,e=void 0),t&&e!==!1&&this.queue(e||\"fx\",[]),this.each(function(){var t=!0,i=null!=e&&e+\"queueHooks\",o=pe.timers,a=pe._data(this);if(i)a[i]&&a[i].stop&&r(a[i]);else for(i in a)a[i]&&a[i].stop&&At.test(i)&&r(a[i]);for(i=o.length;i--;)o[i].elem!==this||null!=e&&o[i].queue!==e||(o[i].anim.stop(n),t=!1,o.splice(i,1));!t&&n||pe.dequeue(this,e)})},finish:function(e){return e!==!1&&(e=e||\"fx\"),this.each(function(){var t,n=pe._data(this),r=n[e+\"queue\"],i=n[e+\"queueHooks\"],o=pe.timers,a=r?r.length:0;for(n.finish=!0,pe.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;t<a;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}}),pe.each([\"toggle\",\"show\",\"hide\"],function(e,t){var n=pe.fn[t];pe.fn[t]=function(e,r,i){return null==e||\"boolean\"==typeof e?n.apply(this,arguments):this.animate(P(t,!0),e,r,i)}}),pe.each({slideDown:P(\"show\"),slideUp:P(\"hide\"),slideToggle:P(\"toggle\"),fadeIn:{opacity:\"show\"},fadeOut:{opacity:\"hide\"},fadeToggle:{opacity:\"toggle\"}},function(e,t){pe.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),pe.timers=[],pe.fx.tick=function(){var e,t=pe.timers,n=0;for(Nt=pe.now();n<t.length;n++)e=t[n],e()||t[n]!==e||t.splice(n--,1);t.length||pe.fx.stop(),Nt=void 0},pe.fx.timer=function(e){pe.timers.push(e),e()?pe.fx.start():pe.timers.pop()},pe.fx.interval=13,pe.fx.start=function(){kt||(kt=e.setInterval(pe.fx.tick,pe.fx.interval))},pe.fx.stop=function(){e.clearInterval(kt),kt=null},pe.fx.speeds={slow:600,fast:200,_default:400},pe.fn.delay=function(t,n){return t=pe.fx?pe.fx.speeds[t]||t:t,n=n||\"fx\",this.queue(n,function(n,r){var i=e.setTimeout(n,t);r.stop=function(){e.clearTimeout(i)}})},function(){var e,t=re.createElement(\"input\"),n=re.createElement(\"div\"),r=re.createElement(\"select\"),i=r.appendChild(re.createElement(\"option\"));n=re.createElement(\"div\"),n.setAttribute(\"className\",\"t\"),n.innerHTML=\"  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>\",e=n.getElementsByTagName(\"a\")[0],t.setAttribute(\"type\",\"checkbox\"),n.appendChild(t),e=n.getElementsByTagName(\"a\")[0],e.style.cssText=\"top:1px\",fe.getSetAttribute=\"t\"!==n.className,fe.style=/top/.test(e.getAttribute(\"style\")),fe.hrefNormalized=\"/a\"===e.getAttribute(\"href\"),fe.checkOn=!!t.value,fe.optSelected=i.selected,fe.enctype=!!re.createElement(\"form\").enctype,r.disabled=!0,fe.optDisabled=!i.disabled,t=re.createElement(\"input\"),t.setAttribute(\"value\",\"\"),fe.input=\"\"===t.getAttribute(\"value\"),t.value=\"t\",t.setAttribute(\"type\",\"radio\"),fe.radioValue=\"t\"===t.value}();var Dt=/\\r/g,jt=/[\\x20\\t\\r\\n\\f]+/g;pe.fn.extend({val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=pe.isFunction(e),this.each(function(n){var i;1===this.nodeType&&(i=r?e.call(this,n,pe(this).val()):e,null==i?i=\"\":\"number\"==typeof i?i+=\"\":pe.isArray(i)&&(i=pe.map(i,function(e){return null==e?\"\":e+\"\"})),t=pe.valHooks[this.type]||pe.valHooks[this.nodeName.toLowerCase()],t&&\"set\"in t&&void 0!==t.set(this,i,\"value\")||(this.value=i))});if(i)return t=pe.valHooks[i.type]||pe.valHooks[i.nodeName.toLowerCase()],t&&\"get\"in t&&void 0!==(n=t.get(i,\"value\"))?n:(n=i.value,\"string\"==typeof n?n.replace(Dt,\"\"):null==n?\"\":n)}}}),pe.extend({valHooks:{option:{get:function(e){var t=pe.find.attr(e,\"value\");return null!=t?t:pe.trim(pe.text(e)).replace(jt,\" \")}},select:{get:function(e){for(var t,n,r=e.options,i=e.selectedIndex,o=\"select-one\"===e.type||i<0,a=o?null:[],s=o?i+1:r.length,u=i<0?s:o?i:0;u<s;u++)if(n=r[u],(n.selected||u===i)&&(fe.optDisabled?!n.disabled:null===n.getAttribute(\"disabled\"))&&(!n.parentNode.disabled||!pe.nodeName(n.parentNode,\"optgroup\"))){if(t=pe(n).val(),o)return t;a.push(t)}return a},set:function(e,t){for(var n,r,i=e.options,o=pe.makeArray(t),a=i.length;a--;)if(r=i[a],pe.inArray(pe.valHooks.option.get(r),o)>-1)try{r.selected=n=!0}catch(s){r.scrollHeight}else r.selected=!1;return n||(e.selectedIndex=-1),i}}}}),pe.each([\"radio\",\"checkbox\"],function(){pe.valHooks[this]={set:function(e,t){if(pe.isArray(t))return e.checked=pe.inArray(pe(e).val(),t)>-1}},fe.checkOn||(pe.valHooks[this].get=function(e){return null===e.getAttribute(\"value\")?\"on\":e.value})});var Lt,Ht,qt=pe.expr.attrHandle,_t=/^(?:checked|selected)$/i,Ft=fe.getSetAttribute,Mt=fe.input;pe.fn.extend({attr:function(e,t){return Pe(this,pe.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){pe.removeAttr(this,e)})}}),pe.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return\"undefined\"==typeof e.getAttribute?pe.prop(e,t,n):(1===o&&pe.isXMLDoc(e)||(t=t.toLowerCase(),i=pe.attrHooks[t]||(pe.expr.match.bool.test(t)?Ht:Lt)),void 0!==n?null===n?void pe.removeAttr(e,t):i&&\"set\"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+\"\"),n):i&&\"get\"in i&&null!==(r=i.get(e,t))?r:(r=pe.find.attr(e,t),null==r?void 0:r))},attrHooks:{type:{set:function(e,t){if(!fe.radioValue&&\"radio\"===t&&pe.nodeName(e,\"input\")){var n=e.value;return e.setAttribute(\"type\",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(De);if(o&&1===e.nodeType)for(;n=o[i++];)r=pe.propFix[n]||n,pe.expr.match.bool.test(n)?Mt&&Ft||!_t.test(n)?e[r]=!1:e[pe.camelCase(\"default-\"+n)]=e[r]=!1:pe.attr(e,n,\"\"),e.removeAttribute(Ft?n:r)}}),Ht={set:function(e,t,n){return t===!1?pe.removeAttr(e,n):Mt&&Ft||!_t.test(n)?e.setAttribute(!Ft&&pe.propFix[n]||n,n):e[pe.camelCase(\"default-\"+n)]=e[n]=!0,n}},pe.each(pe.expr.match.bool.source.match(/\\w+/g),function(e,t){var n=qt[t]||pe.find.attr;Mt&&Ft||!_t.test(t)?qt[t]=function(e,t,r){var i,o;return r||(o=qt[t],qt[t]=i,i=null!=n(e,t,r)?t.toLowerCase():null,qt[t]=o),i}:qt[t]=function(e,t,n){if(!n)return e[pe.camelCase(\"default-\"+t)]?t.toLowerCase():null}}),Mt&&Ft||(pe.attrHooks.value={set:function(e,t,n){return pe.nodeName(e,\"input\")?void(e.defaultValue=t):Lt&&Lt.set(e,t,n)}}),Ft||(Lt={set:function(e,t,n){var r=e.getAttributeNode(n);if(r||e.setAttributeNode(r=e.ownerDocument.createAttribute(n)),r.value=t+=\"\",\"value\"===n||t===e.getAttribute(n))return t}},qt.id=qt.name=qt.coords=function(e,t,n){var r;if(!n)return(r=e.getAttributeNode(t))&&\"\"!==r.value?r.value:null},pe.valHooks.button={get:function(e,t){var n=e.getAttributeNode(t);if(n&&n.specified)return n.value},set:Lt.set},pe.attrHooks.contenteditable={set:function(e,t,n){Lt.set(e,\"\"!==t&&t,n)}},pe.each([\"width\",\"height\"],function(e,t){pe.attrHooks[t]={set:function(e,n){if(\"\"===n)return e.setAttribute(t,\"auto\"),n}}})),fe.style||(pe.attrHooks.style={get:function(e){return e.style.cssText||void 0},set:function(e,t){return e.style.cssText=t+\"\"}});var Ot=/^(?:input|select|textarea|button|object)$/i,Rt=/^(?:a|area)$/i;pe.fn.extend({prop:function(e,t){return Pe(this,pe.prop,e,t,arguments.length>1)},removeProp:function(e){return e=pe.propFix[e]||e,this.each(function(){try{this[e]=void 0,delete this[e]}catch(t){}})}}),pe.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&pe.isXMLDoc(e)||(t=pe.propFix[t]||t,i=pe.propHooks[t]),void 0!==n?i&&\"set\"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&\"get\"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=pe.find.attr(e,\"tabindex\");return t?parseInt(t,10):Ot.test(e.nodeName)||Rt.test(e.nodeName)&&e.href?0:-1}}},propFix:{\"for\":\"htmlFor\",\"class\":\"className\"}}),fe.hrefNormalized||pe.each([\"href\",\"src\"],function(e,t){pe.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}}),fe.optSelected||(pe.propHooks.selected={get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),pe.each([\"tabIndex\",\"readOnly\",\"maxLength\",\"cellSpacing\",\"cellPadding\",\"rowSpan\",\"colSpan\",\"useMap\",\"frameBorder\",\"contentEditable\"],function(){pe.propFix[this.toLowerCase()]=this}),fe.enctype||(pe.propFix.enctype=\"encoding\");var Pt=/[\\t\\r\\n\\f]/g;pe.fn.extend({addClass:function(e){var t,n,r,i,o,a,s,u=0;if(pe.isFunction(e))return this.each(function(t){pe(this).addClass(e.call(this,t,z(this)))});if(\"string\"==typeof e&&e)for(t=e.match(De)||[];n=this[u++];)if(i=z(n),r=1===n.nodeType&&(\" \"+i+\" \").replace(Pt,\" \")){for(a=0;o=t[a++];)r.indexOf(\" \"+o+\" \")<0&&(r+=o+\" \");s=pe.trim(r),i!==s&&pe.attr(n,\"class\",s)}return this},removeClass:function(e){var t,n,r,i,o,a,s,u=0;if(pe.isFunction(e))return this.each(function(t){pe(this).removeClass(e.call(this,t,z(this)))});if(!arguments.length)return this.attr(\"class\",\"\");if(\"string\"==typeof e&&e)for(t=e.match(De)||[];n=this[u++];)if(i=z(n),r=1===n.nodeType&&(\" \"+i+\" \").replace(Pt,\" \")){for(a=0;o=t[a++];)for(;r.indexOf(\" \"+o+\" \")>-1;)r=r.replace(\" \"+o+\" \",\" \");s=pe.trim(r),i!==s&&pe.attr(n,\"class\",s)}return this},toggleClass:function(e,t){var n=typeof e;return\"boolean\"==typeof t&&\"string\"===n?t?this.addClass(e):this.removeClass(e):pe.isFunction(e)?this.each(function(n){pe(this).toggleClass(e.call(this,n,z(this),t),t)}):this.each(function(){var t,r,i,o;if(\"string\"===n)for(r=0,i=pe(this),o=e.match(De)||[];t=o[r++];)i.hasClass(t)?i.removeClass(t):i.addClass(t);else void 0!==e&&\"boolean\"!==n||(t=z(this),t&&pe._data(this,\"__className__\",t),pe.attr(this,\"class\",t||e===!1?\"\":pe._data(this,\"__className__\")||\"\"))})},hasClass:function(e){var t,n,r=0;for(t=\" \"+e+\" \";n=this[r++];)if(1===n.nodeType&&(\" \"+z(n)+\" \").replace(Pt,\" \").indexOf(t)>-1)return!0;return!1}}),pe.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){pe.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),pe.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}});var Bt=e.location,Wt=pe.now(),It=/\\?/,$t=/(,)|(\\[|{)|(}|])|\"(?:[^\"\\\\\\r\\n]|\\\\[\"\\\\\\/bfnrt]|\\\\u[\\da-fA-F]{4})*\"\\s*:?|true|false|null|-?(?!0\\d)\\d+(?:\\.\\d+|)(?:[eE][+-]?\\d+|)/g;pe.parseJSON=function(t){if(e.JSON&&e.JSON.parse)return e.JSON.parse(t+\"\");var n,r=null,i=pe.trim(t+\"\");return i&&!pe.trim(i.replace($t,function(e,t,i,o){return n&&t&&(r=0),0===r?e:(n=i||t,r+=!o-!i,\"\")}))?Function(\"return \"+i)():pe.error(\"Invalid JSON: \"+t)},pe.parseXML=function(t){var n,r;if(!t||\"string\"!=typeof t)return null;try{e.DOMParser?(r=new e.DOMParser,n=r.parseFromString(t,\"text/xml\")):(n=new e.ActiveXObject(\"Microsoft.XMLDOM\"),n.async=\"false\",n.loadXML(t))}catch(i){n=void 0}return n&&n.documentElement&&!n.getElementsByTagName(\"parsererror\").length||pe.error(\"Invalid XML: \"+t),n};var zt=/#.*$/,Xt=/([?&])_=[^&]*/,Ut=/^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/gm,Vt=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Yt=/^(?:GET|HEAD)$/,Jt=/^\\/\\//,Gt=/^([\\w.+-]+:)(?:\\/\\/(?:[^\\/?#]*@|)([^\\/?#:]*)(?::(\\d+)|)|)/,Kt={},Qt={},Zt=\"*/\".concat(\"*\"),en=Bt.href,tn=Gt.exec(en.toLowerCase())||[];pe.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:en,type:\"GET\",isLocal:Vt.test(tn[1]),global:!0,processData:!0,async:!0,contentType:\"application/x-www-form-urlencoded; charset=UTF-8\",accepts:{\"*\":Zt,text:\"text/plain\",html:\"text/html\",xml:\"application/xml, text/xml\",json:\"application/json, text/javascript\"},contents:{xml:/\\bxml\\b/,html:/\\bhtml/,json:/\\bjson\\b/},responseFields:{xml:\"responseXML\",text:\"responseText\",json:\"responseJSON\"},converters:{\"* text\":String,\"text html\":!0,\"text json\":pe.parseJSON,\"text xml\":pe.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?V(V(e,pe.ajaxSettings),t):V(pe.ajaxSettings,e)},ajaxPrefilter:X(Kt),ajaxTransport:X(Qt),ajax:function(t,n){function r(t,n,r,i){var o,f,v,x,w,C=n;2!==b&&(b=2,u&&e.clearTimeout(u),c=void 0,s=i||\"\",T.readyState=t>0?4:0,o=t>=200&&t<300||304===t,r&&(x=Y(d,T,r)),x=J(d,x,T,o),o?(d.ifModified&&(w=T.getResponseHeader(\"Last-Modified\"),w&&(pe.lastModified[a]=w),w=T.getResponseHeader(\"etag\"),w&&(pe.etag[a]=w)),204===t||\"HEAD\"===d.type?C=\"nocontent\":304===t?C=\"notmodified\":(C=x.state,f=x.data,v=x.error,o=!v)):(v=C,!t&&C||(C=\"error\",t<0&&(t=0))),T.status=t,T.statusText=(n||C)+\"\",o?g.resolveWith(p,[f,C,T]):g.rejectWith(p,[T,C,v]),T.statusCode(y),y=void 0,l&&h.trigger(o?\"ajaxSuccess\":\"ajaxError\",[T,d,o?f:v]),m.fireWith(p,[T,C]),l&&(h.trigger(\"ajaxComplete\",[T,d]),--pe.active||pe.event.trigger(\"ajaxStop\")))}\"object\"==typeof t&&(n=t,t=void 0),n=n||{};var i,o,a,s,u,l,c,f,d=pe.ajaxSetup({},n),p=d.context||d,h=d.context&&(p.nodeType||p.jquery)?pe(p):pe.event,g=pe.Deferred(),m=pe.Callbacks(\"once memory\"),y=d.statusCode||{},v={},x={},b=0,w=\"canceled\",T={readyState:0,getResponseHeader:function(e){var t;if(2===b){if(!f)for(f={};t=Ut.exec(s);)f[t[1].toLowerCase()]=t[2];t=f[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===b?s:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return b||(e=x[n]=x[n]||e,v[e]=t),this},overrideMimeType:function(e){return b||(d.mimeType=e),this},statusCode:function(e){var t;if(e)if(b<2)for(t in e)y[t]=[y[t],e[t]];else T.always(e[T.status]);return this},abort:function(e){var t=e||w;return c&&c.abort(t),r(0,t),this}};if(g.promise(T).complete=m.add,T.success=T.done,T.error=T.fail,d.url=((t||d.url||en)+\"\").replace(zt,\"\").replace(Jt,tn[1]+\"//\"),d.type=n.method||n.type||d.method||d.type,d.dataTypes=pe.trim(d.dataType||\"*\").toLowerCase().match(De)||[\"\"],null==d.crossDomain&&(i=Gt.exec(d.url.toLowerCase()),d.crossDomain=!(!i||i[1]===tn[1]&&i[2]===tn[2]&&(i[3]||(\"http:\"===i[1]?\"80\":\"443\"))===(tn[3]||(\"http:\"===tn[1]?\"80\":\"443\")))),d.data&&d.processData&&\"string\"!=typeof d.data&&(d.data=pe.param(d.data,d.traditional)),U(Kt,d,n,T),2===b)return T;l=pe.event&&d.global,l&&0===pe.active++&&pe.event.trigger(\"ajaxStart\"),d.type=d.type.toUpperCase(),d.hasContent=!Yt.test(d.type),a=d.url,d.hasContent||(d.data&&(a=d.url+=(It.test(a)?\"&\":\"?\")+d.data,delete d.data),d.cache===!1&&(d.url=Xt.test(a)?a.replace(Xt,\"$1_=\"+Wt++):a+(It.test(a)?\"&\":\"?\")+\"_=\"+Wt++)),d.ifModified&&(pe.lastModified[a]&&T.setRequestHeader(\"If-Modified-Since\",pe.lastModified[a]),pe.etag[a]&&T.setRequestHeader(\"If-None-Match\",pe.etag[a])),(d.data&&d.hasContent&&d.contentType!==!1||n.contentType)&&T.setRequestHeader(\"Content-Type\",d.contentType),T.setRequestHeader(\"Accept\",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(\"*\"!==d.dataTypes[0]?\", \"+Zt+\"; q=0.01\":\"\"):d.accepts[\"*\"]);for(o in d.headers)T.setRequestHeader(o,d.headers[o]);if(d.beforeSend&&(d.beforeSend.call(p,T,d)===!1||2===b))return T.abort();w=\"abort\";for(o in{success:1,error:1,complete:1})T[o](d[o]);if(c=U(Qt,d,n,T)){if(T.readyState=1,l&&h.trigger(\"ajaxSend\",[T,d]),2===b)return T;d.async&&d.timeout>0&&(u=e.setTimeout(function(){T.abort(\"timeout\")},d.timeout));try{b=1,c.send(v,r)}catch(C){if(!(b<2))throw C;r(-1,C)}}else r(-1,\"No Transport\");return T},getJSON:function(e,t,n){return pe.get(e,t,n,\"json\")},getScript:function(e,t){return pe.get(e,void 0,t,\"script\")}}),pe.each([\"get\",\"post\"],function(e,t){pe[t]=function(e,n,r,i){return pe.isFunction(n)&&(i=i||r,r=n,n=void 0),pe.ajax(pe.extend({url:e,type:t,dataType:i,data:n,success:r},pe.isPlainObject(e)&&e))}}),pe._evalUrl=function(e){return pe.ajax({url:e,type:\"GET\",dataType:\"script\",cache:!0,async:!1,global:!1,\"throws\":!0})},pe.fn.extend({wrapAll:function(e){if(pe.isFunction(e))return this.each(function(t){pe(this).wrapAll(e.call(this,t))});if(this[0]){var t=pe(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){for(var e=this;e.firstChild&&1===e.firstChild.nodeType;)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return pe.isFunction(e)?this.each(function(t){pe(this).wrapInner(e.call(this,t))}):this.each(function(){var t=pe(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=pe.isFunction(e);return this.each(function(n){pe(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){pe.nodeName(this,\"body\")||pe(this).replaceWith(this.childNodes)}).end()}}),pe.expr.filters.hidden=function(e){return fe.reliableHiddenOffsets()?e.offsetWidth<=0&&e.offsetHeight<=0&&!e.getClientRects().length:K(e)},pe.expr.filters.visible=function(e){return!pe.expr.filters.hidden(e)};var nn=/%20/g,rn=/\\[\\]$/,on=/\\r?\\n/g,an=/^(?:submit|button|image|reset|file)$/i,sn=/^(?:input|select|textarea|keygen)/i;pe.param=function(e,t){var n,r=[],i=function(e,t){t=pe.isFunction(t)?t():null==t?\"\":t,r[r.length]=encodeURIComponent(e)+\"=\"+encodeURIComponent(t)};if(void 0===t&&(t=pe.ajaxSettings&&pe.ajaxSettings.traditional),pe.isArray(e)||e.jquery&&!pe.isPlainObject(e))pe.each(e,function(){i(this.name,this.value)});else for(n in e)Q(n,e[n],t,i);return r.join(\"&\").replace(nn,\"+\")},pe.fn.extend({serialize:function(){return pe.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=pe.prop(this,\"elements\");return e?pe.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!pe(this).is(\":disabled\")&&sn.test(this.nodeName)&&!an.test(e)&&(this.checked||!Be.test(e))}).map(function(e,t){var n=pe(this).val();return null==n?null:pe.isArray(n)?pe.map(n,function(e){return{name:t.name,value:e.replace(on,\"\\r\\n\")}}):{name:t.name,value:n.replace(on,\"\\r\\n\")}}).get()}}),pe.ajaxSettings.xhr=void 0!==e.ActiveXObject?function(){return this.isLocal?ee():re.documentMode>8?Z():/^(get|post|head|put|delete|options)$/i.test(this.type)&&Z()||ee()}:Z;var un=0,ln={},cn=pe.ajaxSettings.xhr();e.attachEvent&&e.attachEvent(\"onunload\",function(){for(var e in ln)ln[e](void 0,!0)}),fe.cors=!!cn&&\"withCredentials\"in cn,cn=fe.ajax=!!cn,cn&&pe.ajaxTransport(function(t){if(!t.crossDomain||fe.cors){var n;return{send:function(r,i){var o,a=t.xhr(),s=++un;if(a.open(t.type,t.url,t.async,t.username,t.password),t.xhrFields)for(o in t.xhrFields)a[o]=t.xhrFields[o];t.mimeType&&a.overrideMimeType&&a.overrideMimeType(t.mimeType),t.crossDomain||r[\"X-Requested-With\"]||(r[\"X-Requested-With\"]=\"XMLHttpRequest\");for(o in r)void 0!==r[o]&&a.setRequestHeader(o,r[o]+\"\");a.send(t.hasContent&&t.data||null),n=function(e,r){var o,u,l;if(n&&(r||4===a.readyState))if(delete ln[s],n=void 0,a.onreadystatechange=pe.noop,r)4!==a.readyState&&a.abort();else{l={},o=a.status,\"string\"==typeof a.responseText&&(l.text=a.responseText);try{u=a.statusText}catch(c){u=\"\"}o||!t.isLocal||t.crossDomain?1223===o&&(o=204):o=l.text?200:404}l&&i(o,u,l,a.getAllResponseHeaders())},t.async?4===a.readyState?e.setTimeout(n):a.onreadystatechange=ln[s]=n:n()},abort:function(){n&&n(void 0,!0)}}}}),pe.ajaxSetup({accepts:{script:\"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"},contents:{script:/\\b(?:java|ecma)script\\b/},converters:{\"text script\":function(e){return pe.globalEval(e),e}}}),pe.ajaxPrefilter(\"script\",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type=\"GET\",e.global=!1)}),pe.ajaxTransport(\"script\",function(e){if(e.crossDomain){var t,n=re.head||pe(\"head\")[0]||re.documentElement;return{send:function(r,i){t=re.createElement(\"script\"),t.async=!0,e.scriptCharset&&(t.charset=e.scriptCharset),t.src=e.url,t.onload=t.onreadystatechange=function(e,n){(n||!t.readyState||/loaded|complete/.test(t.readyState))&&(t.onload=t.onreadystatechange=null,t.parentNode&&t.parentNode.removeChild(t),t=null,n||i(200,\"success\"))},n.insertBefore(t,n.firstChild)},abort:function(){t&&t.onload(void 0,!0)}}}});var fn=[],dn=/(=)\\?(?=&|$)|\\?\\?/;pe.ajaxSetup({jsonp:\"callback\",jsonpCallback:function(){var e=fn.pop()||pe.expando+\"_\"+Wt++;return this[e]=!0,e}}),pe.ajaxPrefilter(\"json jsonp\",function(t,n,r){var i,o,a,s=t.jsonp!==!1&&(dn.test(t.url)?\"url\":\"string\"==typeof t.data&&0===(t.contentType||\"\").indexOf(\"application/x-www-form-urlencoded\")&&dn.test(t.data)&&\"data\");if(s||\"jsonp\"===t.dataTypes[0])return i=t.jsonpCallback=pe.isFunction(t.jsonpCallback)?t.jsonpCallback():t.jsonpCallback,s?t[s]=t[s].replace(dn,\"$1\"+i):t.jsonp!==!1&&(t.url+=(It.test(t.url)?\"&\":\"?\")+t.jsonp+\"=\"+i),t.converters[\"script json\"]=function(){return a||pe.error(i+\" was not called\"),a[0]},t.dataTypes[0]=\"json\",o=e[i],e[i]=function(){a=arguments},r.always(function(){void 0===o?pe(e).removeProp(i):e[i]=o,t[i]&&(t.jsonpCallback=n.jsonpCallback,fn.push(i)),a&&pe.isFunction(o)&&o(a[0]),a=o=void 0}),\"script\"}),pe.parseHTML=function(e,t,n){if(!e||\"string\"!=typeof e)return null;\"boolean\"==typeof t&&(n=t,t=!1),t=t||re;var r=Te.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=y([e],t,i),i&&i.length&&pe(i).remove(),pe.merge([],r.childNodes))};var pn=pe.fn.load;return pe.fn.load=function(e,t,n){if(\"string\"!=typeof e&&pn)return pn.apply(this,arguments);var r,i,o,a=this,s=e.indexOf(\" \");return s>-1&&(r=pe.trim(e.slice(s,e.length)),e=e.slice(0,s)),pe.isFunction(t)?(n=t,t=void 0):t&&\"object\"==typeof t&&(i=\"POST\"),a.length>0&&pe.ajax({url:e,type:i||\"GET\",dataType:\"html\",data:t}).done(function(e){o=arguments,a.html(r?pe(\"<div>\").append(pe.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},pe.each([\"ajaxStart\",\"ajaxStop\",\"ajaxComplete\",\"ajaxError\",\"ajaxSuccess\",\"ajaxSend\"],function(e,t){pe.fn[t]=function(e){return this.on(t,e)}}),pe.expr.filters.animated=function(e){return pe.grep(pe.timers,function(t){return e===t.elem}).length},pe.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l,c=pe.css(e,\"position\"),f=pe(e),d={};\"static\"===c&&(e.style.position=\"relative\"),s=f.offset(),o=pe.css(e,\"top\"),u=pe.css(e,\"left\"),l=(\"absolute\"===c||\"fixed\"===c)&&pe.inArray(\"auto\",[o,u])>-1,l?(r=f.position(),a=r.top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),pe.isFunction(t)&&(t=t.call(e,n,pe.extend({},s))),null!=t.top&&(d.top=t.top-s.top+a),null!=t.left&&(d.left=t.left-s.left+i),\"using\"in t?t.using.call(e,d):f.css(d)}},pe.fn.extend({offset:function(e){if(arguments.length)return void 0===e?this:this.each(function(t){pe.offset.setOffset(this,e,t)});var t,n,r={top:0,left:0},i=this[0],o=i&&i.ownerDocument;if(o)return t=o.documentElement,pe.contains(t,i)?(\"undefined\"!=typeof i.getBoundingClientRect&&(r=i.getBoundingClientRect()),n=te(o),{top:r.top+(n.pageYOffset||t.scrollTop)-(t.clientTop||0),left:r.left+(n.pageXOffset||t.scrollLeft)-(t.clientLeft||0)}):r},position:function(){if(this[0]){var e,t,n={top:0,left:0},r=this[0];return\"fixed\"===pe.css(r,\"position\")?t=r.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),pe.nodeName(e[0],\"html\")||(n=e.offset()),n.top+=pe.css(e[0],\"borderTopWidth\",!0),n.left+=pe.css(e[0],\"borderLeftWidth\",!0)),{top:t.top-n.top-pe.css(r,\"marginTop\",!0),left:t.left-n.left-pe.css(r,\"marginLeft\",!0)}}},offsetParent:function(){return this.map(function(){\nfor(var e=this.offsetParent;e&&!pe.nodeName(e,\"html\")&&\"static\"===pe.css(e,\"position\");)e=e.offsetParent;return e||pt})}}),pe.each({scrollLeft:\"pageXOffset\",scrollTop:\"pageYOffset\"},function(e,t){var n=/Y/.test(t);pe.fn[e]=function(r){return Pe(this,function(e,r,i){var o=te(e);return void 0===i?o?t in o?o[t]:o.document.documentElement[r]:e[r]:void(o?o.scrollTo(n?pe(o).scrollLeft():i,n?i:pe(o).scrollTop()):e[r]=i)},e,r,arguments.length,null)}}),pe.each([\"top\",\"left\"],function(e,t){pe.cssHooks[t]=L(fe.pixelPosition,function(e,n){if(n)return n=gt(e,t),ft.test(n)?pe(e).position()[t]+\"px\":n})}),pe.each({Height:\"height\",Width:\"width\"},function(e,t){pe.each({padding:\"inner\"+e,content:t,\"\":\"outer\"+e},function(n,r){pe.fn[r]=function(r,i){var o=arguments.length&&(n||\"boolean\"!=typeof r),a=n||(r===!0||i===!0?\"margin\":\"border\");return Pe(this,function(t,n,r){var i;return pe.isWindow(t)?t.document.documentElement[\"client\"+e]:9===t.nodeType?(i=t.documentElement,Math.max(t.body[\"scroll\"+e],i[\"scroll\"+e],t.body[\"offset\"+e],i[\"offset\"+e],i[\"client\"+e])):void 0===r?pe.css(t,n,a):pe.style(t,n,r,a)},t,o?r:void 0,o,null)}})}),pe.fn.extend({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)}}),pe.fn.size=function(){return this.length},pe.fn.andSelf=pe.fn.addBack,layui.define(function(e){e(\"jquery\",pe)}),pe});!function(e,t){\"use strict\";var i,n,a=e.layui&&layui.define,o={getPath:function(){var e=document.scripts,t=e[e.length-1],i=t.src;if(!t.getAttribute(\"merge\"))return i.substring(0,i.lastIndexOf(\"/\")+1)}(),config:{},end:{},minIndex:0,minLeft:[],btn:[\"&#x786E;&#x5B9A;\",\"&#x53D6;&#x6D88;\"],type:[\"dialog\",\"page\",\"iframe\",\"loading\",\"tips\"]},r={v:\"3.0.1\",ie:function(){var t=navigator.userAgent.toLowerCase();return!!(e.ActiveXObject||\"ActiveXObject\"in e)&&((t.match(/msie\\s(\\d+)/)||[])[1]||\"11\")}(),index:e.layer&&e.layer.v?1e5:0,path:o.getPath,config:function(e,t){return e=e||{},r.cache=o.config=i.extend({},o.config,e),r.path=o.config.path||r.path,\"string\"==typeof e.extend&&(e.extend=[e.extend]),o.config.path&&r.ready(),e.extend?(a?layui.addcss(\"modules/layer/\"+e.extend):r.link(\"skin/\"+e.extend),this):this},link:function(t,n,a){if(r.path){var o=i(\"head\")[0],l=document.createElement(\"link\");\"string\"==typeof n&&(a=n);var s=(a||t).replace(/\\.|\\//g,\"\"),f=\"layuicss-\"+s,c=0;l.rel=\"stylesheet\",l.href=r.path+t,l.id=f,i(\"#\"+f)[0]||o.appendChild(l),\"function\"==typeof n&&!function d(){return++c>80?e.console&&console.error(\"layer.css: Invalid\"):void(1989===parseInt(i(\"#\"+f).css(\"width\"))?n():setTimeout(d,100))}()}},ready:function(e){var t=\"skinlayercss\",i=\"1110\";return a?layui.addcss(\"modules/layer/default/layer.css?v=\"+r.v+i,e,t):r.link(\"skin/default/layer.css?v=\"+r.v+i,e,t),this},alert:function(e,t,n){var a=\"function\"==typeof t;return a&&(n=t),r.open(i.extend({content:e,yes:n},a?{}:t))},confirm:function(e,t,n,a){var l=\"function\"==typeof t;return l&&(a=n,n=t),r.open(i.extend({content:e,btn:o.btn,yes:n,btn2:a},l?{}:t))},msg:function(e,n,a){var l=\"function\"==typeof n,f=o.config.skin,c=(f?f+\" \"+f+\"-msg\":\"\")||\"layui-layer-msg\",d=s.anim.length-1;return l&&(a=n),r.open(i.extend({content:e,time:3e3,shade:!1,skin:c,title:!1,closeBtn:!1,btn:!1,resize:!1,end:a},l&&!o.config.skin?{skin:c+\" layui-layer-hui\",anim:d}:function(){return n=n||{},(n.icon===-1||n.icon===t&&!o.config.skin)&&(n.skin=c+\" \"+(n.skin||\"layui-layer-hui\")),n}()))},load:function(e,t){return r.open(i.extend({type:3,icon:e||0,resize:!1,shade:.01},t))},tips:function(e,t,n){return r.open(i.extend({type:4,content:[e,t],closeBtn:!1,time:3e3,shade:!1,resize:!1,fixed:!1,maxWidth:210},n))}},l=function(e){var t=this;t.index=++r.index,t.config=i.extend({},t.config,o.config,e),document.body?t.creat():setTimeout(function(){t.creat()},50)};l.pt=l.prototype;var s=[\"layui-layer\",\".layui-layer-title\",\".layui-layer-main\",\".layui-layer-dialog\",\"layui-layer-iframe\",\"layui-layer-content\",\"layui-layer-btn\",\"layui-layer-close\"];s.anim=[\"layer-anim\",\"layer-anim-01\",\"layer-anim-02\",\"layer-anim-03\",\"layer-anim-04\",\"layer-anim-05\",\"layer-anim-06\"],l.pt.config={type:0,shade:.3,fixed:!0,move:s[1],title:\"&#x4FE1;&#x606F;\",offset:\"auto\",area:\"auto\",closeBtn:1,time:0,zIndex:19891014,maxWidth:360,anim:0,icon:-1,moveType:1,resize:!0,scrollbar:!0,tips:2},l.pt.vessel=function(e,t){var n=this,a=n.index,r=n.config,l=r.zIndex+a,f=\"object\"==typeof r.title,c=r.maxmin&&(1===r.type||2===r.type),d=r.title?'<div class=\"layui-layer-title\" style=\"'+(f?r.title[1]:\"\")+'\">'+(f?r.title[0]:r.title)+\"</div>\":\"\";return r.zIndex=l,t([r.shade?'<div class=\"layui-layer-shade\" id=\"layui-layer-shade'+a+'\" times=\"'+a+'\" style=\"'+(\"z-index:\"+(l-1)+\"; background-color:\"+(r.shade[1]||\"#000\")+\"; opacity:\"+(r.shade[0]||r.shade)+\"; filter:alpha(opacity=\"+(100*r.shade[0]||100*r.shade)+\");\")+'\"></div>':\"\",'<div class=\"'+s[0]+(\" layui-layer-\"+o.type[r.type])+(0!=r.type&&2!=r.type||r.shade?\"\":\" layui-layer-border\")+\" \"+(r.skin||\"\")+'\" id=\"'+s[0]+a+'\" type=\"'+o.type[r.type]+'\" times=\"'+a+'\" showtime=\"'+r.time+'\" conType=\"'+(e?\"object\":\"string\")+'\" style=\"z-index: '+l+\"; width:\"+r.area[0]+\";height:\"+r.area[1]+(r.fixed?\"\":\";position:absolute;\")+'\">'+(e&&2!=r.type?\"\":d)+'<div id=\"'+(r.id||\"\")+'\" class=\"layui-layer-content'+(0==r.type&&r.icon!==-1?\" layui-layer-padding\":\"\")+(3==r.type?\" layui-layer-loading\"+r.icon:\"\")+'\">'+(0==r.type&&r.icon!==-1?'<i class=\"layui-layer-ico layui-layer-ico'+r.icon+'\"></i>':\"\")+(1==r.type&&e?\"\":r.content||\"\")+'</div><span class=\"layui-layer-setwin\">'+function(){var e=c?'<a class=\"layui-layer-min\" href=\"javascript:;\"><cite></cite></a><a class=\"layui-layer-ico layui-layer-max\" href=\"javascript:;\"></a>':\"\";return r.closeBtn&&(e+='<a class=\"layui-layer-ico '+s[7]+\" \"+s[7]+(r.title?r.closeBtn:4==r.type?\"1\":\"2\")+'\" href=\"javascript:;\"></a>'),e}()+\"</span>\"+(r.btn?function(){var e=\"\";\"string\"==typeof r.btn&&(r.btn=[r.btn]);for(var t=0,i=r.btn.length;t<i;t++)e+='<a class=\"'+s[6]+t+'\">'+r.btn[t]+\"</a>\";return'<div class=\"'+s[6]+\" layui-layer-btn-\"+(r.btnAlign||\"\")+'\">'+e+\"</div>\"}():\"\")+(r.resize?'<span class=\"layui-layer-resize\"></span>':\"\")+\"</div>\"],d,i('<div class=\"layui-layer-move\"></div>')),n},l.pt.creat=function(){var e=this,t=e.config,a=e.index,l=t.content,f=\"object\"==typeof l,c=i(\"body\");if(!i(\"#\"+t.id)[0]){switch(\"string\"==typeof t.area&&(t.area=\"auto\"===t.area?[\"\",\"\"]:[t.area,\"\"]),t.shift&&(t.anim=t.shift),6==r.ie&&(t.fixed=!1),t.type){case 0:t.btn=\"btn\"in t?t.btn:o.btn[0],r.closeAll(\"dialog\");break;case 2:var l=t.content=f?t.content:[t.content||\"http://layer.layui.com\",\"auto\"];t.content='<iframe scrolling=\"'+(t.content[1]||\"auto\")+'\" allowtransparency=\"true\" id=\"'+s[4]+a+'\" name=\"'+s[4]+a+'\" onload=\"this.className=\\'\\';\" class=\"layui-layer-load\" frameborder=\"0\" src=\"'+t.content[0]+'\"></iframe>';break;case 3:delete t.title,delete t.closeBtn,t.icon===-1&&0===t.icon,r.closeAll(\"loading\");break;case 4:f||(t.content=[t.content,\"body\"]),t.follow=t.content[1],t.content=t.content[0]+'<i class=\"layui-layer-TipsG\"></i>',delete t.title,t.tips=\"object\"==typeof t.tips?t.tips:[t.tips,!0],t.tipsMore||r.closeAll(\"tips\")}e.vessel(f,function(n,r,d){c.append(n[0]),f?function(){2==t.type||4==t.type?function(){i(\"body\").append(n[1])}():function(){l.parents(\".\"+s[0])[0]||(l.data(\"display\",l.css(\"display\")).show().addClass(\"layui-layer-wrap\").wrap(n[1]),i(\"#\"+s[0]+a).find(\".\"+s[5]).before(r))}()}():c.append(n[1]),i(\".layui-layer-move\")[0]||c.append(o.moveElem=d),e.layero=i(\"#\"+s[0]+a),t.scrollbar||s.html.css(\"overflow\",\"hidden\").attr(\"layer-full\",a)}).auto(a),2==t.type&&6==r.ie&&e.layero.find(\"iframe\").attr(\"src\",l[0]),4==t.type?e.tips():e.offset(),t.fixed&&n.on(\"resize\",function(){e.offset(),(/^\\d+%$/.test(t.area[0])||/^\\d+%$/.test(t.area[1]))&&e.auto(a),4==t.type&&e.tips()}),t.time<=0||setTimeout(function(){r.close(e.index)},t.time),e.move().callback(),s.anim[t.anim]&&e.layero.addClass(s.anim[t.anim]).data(\"anim\",!0)}},l.pt.auto=function(e){function t(e){e=l.find(e),e.height(f[1]-c-d-2*(0|parseFloat(e.css(\"padding\"))))}var a=this,o=a.config,l=i(\"#\"+s[0]+e);\"\"===o.area[0]&&o.maxWidth>0&&(r.ie&&r.ie<8&&o.btn&&l.width(l.innerWidth()),l.outerWidth()>o.maxWidth&&l.width(o.maxWidth));var f=[l.innerWidth(),l.innerHeight()],c=l.find(s[1]).outerHeight()||0,d=l.find(\".\"+s[6]).outerHeight()||0;switch(o.type){case 2:t(\"iframe\");break;default:\"\"===o.area[1]?o.fixed&&f[1]>=n.height()&&(f[1]=n.height(),t(\".\"+s[5])):t(\".\"+s[5])}return a},l.pt.offset=function(){var e=this,t=e.config,i=e.layero,a=[i.outerWidth(),i.outerHeight()],o=\"object\"==typeof t.offset;e.offsetTop=(n.height()-a[1])/2,e.offsetLeft=(n.width()-a[0])/2,o?(e.offsetTop=t.offset[0],e.offsetLeft=t.offset[1]||e.offsetLeft):\"auto\"!==t.offset&&(\"t\"===t.offset?e.offsetTop=0:\"r\"===t.offset?e.offsetLeft=n.width()-a[0]:\"b\"===t.offset?e.offsetTop=n.height()-a[1]:\"l\"===t.offset?e.offsetLeft=0:\"lt\"===t.offset?(e.offsetTop=0,e.offsetLeft=0):\"lb\"===t.offset?(e.offsetTop=n.height()-a[1],e.offsetLeft=0):\"rt\"===t.offset?(e.offsetTop=0,e.offsetLeft=n.width()-a[0]):\"rb\"===t.offset?(e.offsetTop=n.height()-a[1],e.offsetLeft=n.width()-a[0]):e.offsetTop=t.offset),t.fixed||(e.offsetTop=/%$/.test(e.offsetTop)?n.height()*parseFloat(e.offsetTop)/100:parseFloat(e.offsetTop),e.offsetLeft=/%$/.test(e.offsetLeft)?n.width()*parseFloat(e.offsetLeft)/100:parseFloat(e.offsetLeft),e.offsetTop+=n.scrollTop(),e.offsetLeft+=n.scrollLeft()),i.attr(\"minLeft\")&&(e.offsetTop=n.height()-(i.find(s[1]).outerHeight()||0),e.offsetLeft=i.css(\"left\")),i.css({top:e.offsetTop,left:e.offsetLeft})},l.pt.tips=function(){var e=this,t=e.config,a=e.layero,o=[a.outerWidth(),a.outerHeight()],r=i(t.follow);r[0]||(r=i(\"body\"));var l={width:r.outerWidth(),height:r.outerHeight(),top:r.offset().top,left:r.offset().left},f=a.find(\".layui-layer-TipsG\"),c=t.tips[0];t.tips[1]||f.remove(),l.autoLeft=function(){l.left+o[0]-n.width()>0?(l.tipLeft=l.left+l.width-o[0],f.css({right:12,left:\"auto\"})):l.tipLeft=l.left},l.where=[function(){l.autoLeft(),l.tipTop=l.top-o[1]-10,f.removeClass(\"layui-layer-TipsB\").addClass(\"layui-layer-TipsT\").css(\"border-right-color\",t.tips[1])},function(){l.tipLeft=l.left+l.width+10,l.tipTop=l.top,f.removeClass(\"layui-layer-TipsL\").addClass(\"layui-layer-TipsR\").css(\"border-bottom-color\",t.tips[1])},function(){l.autoLeft(),l.tipTop=l.top+l.height+10,f.removeClass(\"layui-layer-TipsT\").addClass(\"layui-layer-TipsB\").css(\"border-right-color\",t.tips[1])},function(){l.tipLeft=l.left-o[0]-10,l.tipTop=l.top,f.removeClass(\"layui-layer-TipsR\").addClass(\"layui-layer-TipsL\").css(\"border-bottom-color\",t.tips[1])}],l.where[c-1](),1===c?l.top-(n.scrollTop()+o[1]+16)<0&&l.where[2]():2===c?n.width()-(l.left+l.width+o[0]+16)>0||l.where[3]():3===c?l.top-n.scrollTop()+l.height+o[1]+16-n.height()>0&&l.where[0]():4===c&&o[0]+16-l.left>0&&l.where[1](),a.find(\".\"+s[5]).css({\"background-color\":t.tips[1],\"padding-right\":t.closeBtn?\"30px\":\"\"}),a.css({left:l.tipLeft-(t.fixed?n.scrollLeft():0),top:l.tipTop-(t.fixed?n.scrollTop():0)})},l.pt.move=function(){var e=this,t=e.config,a=i(document),l=e.layero,s=l.find(t.move),f=l.find(\".layui-layer-resize\"),c={};return t.move&&s.css(\"cursor\",\"move\"),s.on(\"mousedown\",function(e){e.preventDefault(),t.move&&(c.moveStart=!0,c.offset=[e.clientX-parseFloat(l.css(\"left\")),e.clientY-parseFloat(l.css(\"top\"))],o.moveElem.css(\"cursor\",\"move\").show())}),f.on(\"mousedown\",function(e){e.preventDefault(),c.resizeStart=!0,c.offset=[e.clientX,e.clientY],c.area=[l.outerWidth(),l.outerHeight()],o.moveElem.css(\"cursor\",\"se-resize\").show()}),a.on(\"mousemove\",function(i){if(c.moveStart){var a=i.clientX-c.offset[0],o=i.clientY-c.offset[1],s=\"fixed\"===l.css(\"position\");if(i.preventDefault(),c.stX=s?0:n.scrollLeft(),c.stY=s?0:n.scrollTop(),!t.moveOut){var f=n.width()-l.outerWidth()+c.stX,d=n.height()-l.outerHeight()+c.stY;a<c.stX&&(a=c.stX),a>f&&(a=f),o<c.stY&&(o=c.stY),o>d&&(o=d)}l.css({left:a,top:o})}if(t.resize&&c.resizeStart){var a=i.clientX-c.offset[0],o=i.clientY-c.offset[1];i.preventDefault(),r.style(e.index,{width:c.area[0]+a,height:c.area[1]+o}),c.isResize=!0}}).on(\"mouseup\",function(e){c.moveStart&&(delete c.moveStart,o.moveElem.hide(),t.moveEnd&&t.moveEnd()),c.resizeStart&&(delete c.resizeStart,o.moveElem.hide())}),e},l.pt.callback=function(){function e(){var e=a.cancel&&a.cancel(t.index,n);e===!1||r.close(t.index)}var t=this,n=t.layero,a=t.config;t.openLayer(),a.success&&(2==a.type?n.find(\"iframe\").on(\"load\",function(){a.success(n,t.index)}):a.success(n,t.index)),6==r.ie&&t.IE6(n),n.find(\".\"+s[6]).children(\"a\").on(\"click\",function(){var e=i(this).index();if(0===e)a.yes?a.yes(t.index,n):a.btn1?a.btn1(t.index,n):r.close(t.index);else{var o=a[\"btn\"+(e+1)]&&a[\"btn\"+(e+1)](t.index,n);o===!1||r.close(t.index)}}),n.find(\".\"+s[7]).on(\"click\",e),a.shadeClose&&i(\"#layui-layer-shade\"+t.index).on(\"click\",function(){r.close(t.index)}),n.find(\".layui-layer-min\").on(\"click\",function(){var e=a.min&&a.min(n);e===!1||r.min(t.index,a)}),n.find(\".layui-layer-max\").on(\"click\",function(){i(this).hasClass(\"layui-layer-maxmin\")?(r.restore(t.index),a.restore&&a.restore(n)):(r.full(t.index,a),setTimeout(function(){a.full&&a.full(n)},100))}),a.end&&(o.end[t.index]=a.end)},o.reselect=function(){i.each(i(\"select\"),function(e,t){var n=i(this);n.parents(\".\"+s[0])[0]||1==n.attr(\"layer\")&&i(\".\"+s[0]).length<1&&n.removeAttr(\"layer\").show(),n=null})},l.pt.IE6=function(e){i(\"select\").each(function(e,t){var n=i(this);n.parents(\".\"+s[0])[0]||\"none\"===n.css(\"display\")||n.attr({layer:\"1\"}).hide(),n=null})},l.pt.openLayer=function(){var e=this;r.zIndex=e.config.zIndex,r.setTop=function(e){var t=function(){r.zIndex++,e.css(\"z-index\",r.zIndex+1)};return r.zIndex=parseInt(e[0].style.zIndex),e.on(\"mousedown\",t),r.zIndex}},o.record=function(e){var t=[e.width(),e.height(),e.position().top,e.position().left+parseFloat(e.css(\"margin-left\"))];e.find(\".layui-layer-max\").addClass(\"layui-layer-maxmin\"),e.attr({area:t})},o.rescollbar=function(e){s.html.attr(\"layer-full\")==e&&(s.html[0].style.removeProperty?s.html[0].style.removeProperty(\"overflow\"):s.html[0].style.removeAttribute(\"overflow\"),s.html.removeAttr(\"layer-full\"))},e.layer=r,r.getChildFrame=function(e,t){return t=t||i(\".\"+s[4]).attr(\"times\"),i(\"#\"+s[0]+t).find(\"iframe\").contents().find(e)},r.getFrameIndex=function(e){return i(\"#\"+e).parents(\".\"+s[4]).attr(\"times\")},r.iframeAuto=function(e){if(e){var t=r.getChildFrame(\"html\",e).outerHeight(),n=i(\"#\"+s[0]+e),a=n.find(s[1]).outerHeight()||0,o=n.find(\".\"+s[6]).outerHeight()||0;n.css({height:t+a+o}),n.find(\"iframe\").css({height:t})}},r.iframeSrc=function(e,t){i(\"#\"+s[0]+e).find(\"iframe\").attr(\"src\",t)},r.style=function(e,t,n){var a=i(\"#\"+s[0]+e),r=a.find(\".layui-layer-content\"),l=a.attr(\"type\"),f=a.find(s[1]).outerHeight()||0,c=a.find(\".\"+s[6]).outerHeight()||0;a.attr(\"minLeft\");l!==o.type[3]&&l!==o.type[4]&&(n||(parseFloat(t.width)<=260&&(t.width=260),parseFloat(t.height)-f-c<=64&&(t.height=64+f+c)),a.css(t),c=a.find(\".\"+s[6]).outerHeight(),l===o.type[2]?a.find(\"iframe\").css({height:parseFloat(t.height)-f-c}):r.css({height:parseFloat(t.height)-f-c-parseFloat(r.css(\"padding-top\"))-parseFloat(r.css(\"padding-bottom\"))}))},r.min=function(e,t){var a=i(\"#\"+s[0]+e),l=a.find(s[1]).outerHeight()||0,f=a.attr(\"minLeft\")||181*o.minIndex+\"px\",c=a.css(\"position\");o.record(a),o.minLeft[0]&&(f=o.minLeft[0],o.minLeft.shift()),a.attr(\"position\",c),r.style(e,{width:180,height:l,left:f,top:n.height()-l,position:\"fixed\",overflow:\"hidden\"},!0),a.find(\".layui-layer-min\").hide(),\"page\"===a.attr(\"type\")&&a.find(s[4]).hide(),o.rescollbar(e),a.attr(\"minLeft\")||o.minIndex++,a.attr(\"minLeft\",f)},r.restore=function(e){var t=i(\"#\"+s[0]+e),n=t.attr(\"area\").split(\",\");t.attr(\"type\");r.style(e,{width:parseFloat(n[0]),height:parseFloat(n[1]),top:parseFloat(n[2]),left:parseFloat(n[3]),position:t.attr(\"position\"),overflow:\"visible\"},!0),t.find(\".layui-layer-max\").removeClass(\"layui-layer-maxmin\"),t.find(\".layui-layer-min\").show(),\"page\"===t.attr(\"type\")&&t.find(s[4]).show(),o.rescollbar(e)},r.full=function(e){var t,a=i(\"#\"+s[0]+e);o.record(a),s.html.attr(\"layer-full\")||s.html.css(\"overflow\",\"hidden\").attr(\"layer-full\",e),clearTimeout(t),t=setTimeout(function(){var t=\"fixed\"===a.css(\"position\");r.style(e,{top:t?0:n.scrollTop(),left:t?0:n.scrollLeft(),width:n.width(),height:n.height()},!0),a.find(\".layui-layer-min\").hide()},100)},r.title=function(e,t){var n=i(\"#\"+s[0]+(t||r.index)).find(s[1]);n.html(e)},r.close=function(e){var t=i(\"#\"+s[0]+e),n=t.attr(\"type\"),a=\"layer-anim-close\";if(t[0]){var l=\"layui-layer-wrap\",f=function(){if(n===o.type[1]&&\"object\"===t.attr(\"conType\")){t.children(\":not(.\"+s[5]+\")\").remove();for(var a=t.find(\".\"+l),r=0;r<2;r++)a.unwrap();a.css(\"display\",a.data(\"display\")).removeClass(l)}else{if(n===o.type[2])try{var f=i(\"#\"+s[4]+e)[0];f.contentWindow.document.write(\"\"),f.contentWindow.close(),t.find(\".\"+s[5])[0].removeChild(f)}catch(c){}t[0].innerHTML=\"\",t.remove()}\"function\"==typeof o.end[e]&&o.end[e](),delete o.end[e]};t.data(\"anim\")&&t.addClass(a),i(\"#layui-layer-moves, #layui-layer-shade\"+e).remove(),6==r.ie&&o.reselect(),o.rescollbar(e),t.attr(\"minLeft\")&&(o.minIndex--,o.minLeft.push(t.attr(\"minLeft\"))),setTimeout(function(){f()},r.ie&&r.ie<10||!t.data(\"anim\")?0:200)}},r.closeAll=function(e){i.each(i(\".\"+s[0]),function(){var t=i(this),n=e?t.attr(\"type\")===e:1;n&&r.close(t.attr(\"times\")),n=null})};var f=r.cache||{},c=function(e){return f.skin?\" \"+f.skin+\" \"+f.skin+\"-\"+e:\"\"};r.prompt=function(e,t){var a=\"\";if(e=e||{},\"function\"==typeof e&&(t=e),e.area){var o=e.area;a='style=\"width: '+o[0]+\"; height: \"+o[1]+';\"',delete e.area}var l,s=2==e.formType?'<textarea class=\"layui-layer-input\"'+a+\">\"+(e.value||\"\")+\"</textarea>\":function(){return'<input type=\"'+(1==e.formType?\"password\":\"text\")+'\" class=\"layui-layer-input\" value=\"'+(e.value||\"\")+'\">'}();return r.open(i.extend({type:1,btn:[\"&#x786E;&#x5B9A;\",\"&#x53D6;&#x6D88;\"],content:s,skin:\"layui-layer-prompt\"+c(\"prompt\"),maxWidth:n.width(),success:function(e){l=e.find(\".layui-layer-input\"),l.focus()},resize:!1,yes:function(i){var n=l.val();\"\"===n?l.focus():n.length>(e.maxlength||500)?r.tips(\"&#x6700;&#x591A;&#x8F93;&#x5165;\"+(e.maxlength||500)+\"&#x4E2A;&#x5B57;&#x6570;\",l,{tips:1}):t&&t(n,i,l)}},e))},r.tab=function(e){e=e||{};var t=e.tab||{};return r.open(i.extend({type:1,skin:\"layui-layer-tab\"+c(\"tab\"),resize:!1,title:function(){var e=t.length,i=1,n=\"\";if(e>0)for(n='<span class=\"layui-layer-tabnow\">'+t[0].title+\"</span>\";i<e;i++)n+=\"<span>\"+t[i].title+\"</span>\";return n}(),content:'<ul class=\"layui-layer-tabmain\">'+function(){var e=t.length,i=1,n=\"\";if(e>0)for(n='<li class=\"layui-layer-tabli xubox_tab_layer\">'+(t[0].content||\"no content\")+\"</li>\";i<e;i++)n+='<li class=\"layui-layer-tabli\">'+(t[i].content||\"no  content\")+\"</li>\";return n}()+\"</ul>\",success:function(t){var n=t.find(\".layui-layer-title\").children(),a=t.find(\".layui-layer-tabmain\").children();n.on(\"mousedown\",function(t){t.stopPropagation?t.stopPropagation():t.cancelBubble=!0;var n=i(this),o=n.index();n.addClass(\"layui-layer-tabnow\").siblings().removeClass(\"layui-layer-tabnow\"),a.eq(o).show().siblings().hide(),\"function\"==typeof e.change&&e.change(o)})}},e))},r.photos=function(t,n,a){function o(e,t,i){var n=new Image;return n.src=e,n.complete?t(n):(n.onload=function(){n.onload=null,t(n)},void(n.onerror=function(e){n.onerror=null,i(e)}))}var l={};if(t=t||{},t.photos){var s=t.photos.constructor===Object,f=s?t.photos:{},d=f.data||[],u=f.start||0;if(l.imgIndex=(0|u)+1,t.img=t.img||\"img\",s){if(0===d.length)return r.msg(\"&#x6CA1;&#x6709;&#x56FE;&#x7247;\")}else{var y=i(t.photos),p=function(){d=[],y.find(t.img).each(function(e){var t=i(this);t.attr(\"layer-index\",e),d.push({alt:t.attr(\"alt\"),pid:t.attr(\"layer-pid\"),src:t.attr(\"layer-src\")||t.attr(\"src\"),thumb:t.attr(\"src\")})})};if(p(),0===d.length)return;if(n||y.on(\"click\",t.img,function(){var e=i(this),n=e.attr(\"layer-index\");r.photos(i.extend(t,{photos:{start:n,data:d,tab:t.tab},full:t.full}),!0),p()}),!n)return}l.imgprev=function(e){l.imgIndex--,l.imgIndex<1&&(l.imgIndex=d.length),l.tabimg(e)},l.imgnext=function(e,t){l.imgIndex++,l.imgIndex>d.length&&(l.imgIndex=1,t)||l.tabimg(e)},l.keyup=function(e){if(!l.end){var t=e.keyCode;e.preventDefault(),37===t?l.imgprev(!0):39===t?l.imgnext(!0):27===t&&r.close(l.index)}},l.tabimg=function(e){d.length<=1||(f.start=l.imgIndex-1,r.close(l.index),r.photos(t,!0,e))},l.event=function(){l.bigimg.hover(function(){l.imgsee.show()},function(){l.imgsee.hide()}),l.bigimg.find(\".layui-layer-imgprev\").on(\"click\",function(e){e.preventDefault(),l.imgprev()}),l.bigimg.find(\".layui-layer-imgnext\").on(\"click\",function(e){e.preventDefault(),l.imgnext()}),i(document).on(\"keyup\",l.keyup)},l.loadi=r.load(1,{shade:!(\"shade\"in t)&&.9,scrollbar:!1}),o(d[u].src,function(n){r.close(l.loadi),l.index=r.open(i.extend({type:1,area:function(){var a=[n.width,n.height],o=[i(e).width()-100,i(e).height()-100];if(!t.full&&(a[0]>o[0]||a[1]>o[1])){var r=[a[0]/o[0],a[1]/o[1]];r[0]>r[1]?(a[0]=a[0]/r[0],a[1]=a[1]/r[0]):r[0]<r[1]&&(a[0]=a[0]/r[1],a[1]=a[1]/r[1])}return[a[0]+\"px\",a[1]+\"px\"]}(),title:!1,shade:.9,shadeClose:!0,closeBtn:!1,move:\".layui-layer-phimg img\",moveType:1,scrollbar:!1,moveOut:!0,anim:5*Math.random()|0,skin:\"layui-layer-photos\"+c(\"photos\"),content:'<div class=\"layui-layer-phimg\"><img src=\"'+d[u].src+'\" alt=\"'+(d[u].alt||\"\")+'\" layer-pid=\"'+d[u].pid+'\"><div class=\"layui-layer-imgsee\">'+(d.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:'+(a?\"block\":\"\")+'\"><span class=\"layui-layer-imgtit\"><a href=\"javascript:;\">'+(d[u].alt||\"\")+\"</a><em>\"+l.imgIndex+\"/\"+d.length+\"</em></span></div></div></div>\",success:function(e,i){l.bigimg=e.find(\".layui-layer-phimg\"),l.imgsee=e.find(\".layui-layer-imguide,.layui-layer-imgbar\"),l.event(e),t.tab&&t.tab(d[u],e)},end:function(){l.end=!0,i(document).off(\"keyup\",l.keyup)}},t))},function(){r.close(l.loadi),r.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(){d.length>1&&l.imgnext(!0,!0)}})})}},o.run=function(t){i=t,n=i(e),s.html=i(\"html\"),r.open=function(e){var t=new l(e);return t.index}},e.layui&&layui.define?(r.ready(),layui.define(\"jquery\",function(t){r.path=layui.cache.dir,o.run(layui.jquery),e.layer=r,t(\"layer\",r)})):\"function\"==typeof define?define([\"jquery\"],function(){return o.run(e.jQuery),r}):function(){o.run(e.jQuery),r.ready()}()}(window);layui.define(\"jquery\",function(i){\"use strict\";var t=layui.jquery,a=(layui.hint(),layui.device()),e=\"element\",l=\"layui-this\",n=\"layui-show\",s=function(){this.config={}};s.prototype.set=function(i){var a=this;return t.extend(!0,a.config,i),a},s.prototype.on=function(i,t){return layui.onevent(e,i,t)},s.prototype.tabAdd=function(i,a){var e=t(\".layui-tab[lay-filter=\"+i+\"]\"),l=e.children(\".layui-tab-title\"),n=e.children(\".layui-tab-content\");return l.append(\"<li>\"+(a.title||\"unnaming\")+\"</li>\"),n.append('<div class=\"layui-tab-item\">'+(a.content||\"\")+\"</div>\"),y.tabAuto(),this},s.prototype.tabDelete=function(i,a){var e=t(\".layui-tab[lay-filter=\"+i+\"]\"),l=e.children(\".layui-tab-title\").find(\">li\").eq(a);return y.tabDelete(null,l),this},s.prototype.tabChange=function(i,a){var e=t(\".layui-tab[lay-filter=\"+i+\"]\"),l=e.children(\".layui-tab-title\").find(\">li\").eq(a);return y.tabClick(null,a,l),this};var o=\".layui-nav\",c=\"layui-nav-item\",r=\"layui-nav-bar\",u=\"layui-nav-tree\",d=\"layui-nav-child\",h=\"layui-nav-more\",f=\"layui-anim layui-anim-upbit\",y={tabClick:function(i,a,s){var o=s||t(this),a=a||o.index(),c=o.parents(\".layui-tab\"),r=c.children(\".layui-tab-content\").children(\".layui-tab-item\"),u=c.attr(\"lay-filter\");o.addClass(l).siblings().removeClass(l),r.eq(a).addClass(n).siblings().removeClass(n),layui.event.call(this,e,\"tab(\"+u+\")\",{elem:c,index:a})},tabDelete:function(i,a){var e=a||t(this).parent(),n=e.index(),s=e.parents(\".layui-tab\"),o=s.children(\".layui-tab-content\").children(\".layui-tab-item\");e.hasClass(l)&&(e.next()[0]?y.tabClick.call(e.next()[0],null,n+1):e.prev()[0]&&y.tabClick.call(e.prev()[0],null,n-1)),e.remove(),o.eq(n).remove()},tabAuto:function(){var i=\"layui-tab-more\",e=\"layui-tab-bar\",l=\"layui-tab-close\",n=this;t(\".layui-tab\").each(function(){var s=t(this),o=s.children(\".layui-tab-title\"),c=(s.children(\".layui-tab-content\").children(\".layui-tab-item\"),'lay-stope=\"tabmore\"'),r=t('<span class=\"layui-unselect layui-tab-bar\" '+c+\"><i \"+c+' class=\"layui-icon\">&#xe61a;</i></span>');if(n===window&&8!=a.ie&&y.hideTabMore(!0),s.attr(\"lay-allowClose\")&&o.find(\"li\").each(function(){var i=t(this);if(!i.find(\".\"+l)[0]){var a=t('<i class=\"layui-icon layui-unselect '+l+'\">&#x1006;</i>');a.on(\"click\",y.tabDelete),i.append(a)}}),o.prop(\"scrollWidth\")>o.outerWidth()+1){if(o.find(\".\"+e)[0])return;o.append(r),r.on(\"click\",function(t){o[this.title?\"removeClass\":\"addClass\"](i),this.title=this.title?\"\":\"收缩\"})}else o.find(\".\"+e).remove()})},hideTabMore:function(i){var a=t(\".layui-tab-title\");i!==!0&&\"tabmore\"===t(i.target).attr(\"lay-stope\")||(a.removeClass(\"layui-tab-more\"),a.find(\".layui-tab-bar\").attr(\"title\",\"\"))},clickThis:function(){var i=t(this),a=i.parents(o),n=a.attr(\"lay-filter\");i.find(\".\"+d)[0]||(i.addClass(l).siblings().removeClass(l),layui.event.call(this,e,\"nav(\"+n+\")\",i))},clickChild:function(){var i=t(this),a=i.parents(o),n=a.attr(\"lay-filter\");i.addClass(l).siblings().removeClass(l),layui.event.call(this,e,\"nav(\"+n+\")\",i)},showChild:function(){var i=t(this),a=i.parents(o),e=i.parent(),l=i.siblings(\".\"+d);a.hasClass(u)&&(l.removeClass(f),e[\"none\"===l.css(\"display\")?\"addClass\":\"removeClass\"](c+\"ed\"))}};s.prototype.init=function(i){var e={tab:function(){y.tabAuto.call({})},nav:function(){var i,e,l,s=200,b=function(o,c){var r=t(this),y=r.find(\".\"+d);c.hasClass(u)?o.css({top:r.position().top,height:r.children(\"a\").height(),opacity:1}):(y.addClass(f),o.css({left:r.position().left+parseFloat(r.css(\"marginLeft\")),top:r.position().top+r.height()-5}),i=setTimeout(function(){o.css({width:r.width(),opacity:1})},a.ie&&a.ie<10?0:s),clearTimeout(l),\"block\"===y.css(\"display\")&&clearTimeout(e),e=setTimeout(function(){y.addClass(n),r.find(\".\"+h).addClass(h+\"d\")},300))};t(o).each(function(){var a=t(this),o=t('<span class=\"'+r+'\"></span>'),f=a.find(\".\"+c);a.find(\".\"+r)[0]||(a.append(o),f.on(\"mouseenter\",function(){b.call(this,o,a)}).on(\"mouseleave\",function(){a.hasClass(u)||(clearTimeout(e),e=setTimeout(function(){a.find(\".\"+d).removeClass(n),a.find(\".\"+h).removeClass(h+\"d\")},300))}),a.on(\"mouseleave\",function(){clearTimeout(i),l=setTimeout(function(){a.hasClass(u)?o.css({height:0,top:o.position().top+o.height()/2,opacity:0}):o.css({width:0,left:o.position().left+o.width()/2,opacity:0})},s)})),f.each(function(){var i=t(this),a=i.find(\".\"+d);if(a[0]&&!i.find(\".\"+h)[0]){var e=i.children(\"a\");e.append('<span class=\"'+h+'\"></span>')}i.off(\"click\",y.clickThis).on(\"click\",y.clickThis),i.children(\"a\").off(\"click\",y.showChild).on(\"click\",y.showChild),a.children(\"dd\").off(\"click\",y.clickChild).on(\"click\",y.clickChild)})})},breadcrumb:function(){var i=\".layui-breadcrumb\";t(i).each(function(){var i=t(this),a=i.attr(\"lay-separator\")||\">\",e=i.find(\"a\");e.find(\".layui-box\")[0]||(e.each(function(i){i!==e.length-1&&t(this).append('<span class=\"layui-box\">'+a+\"</span>\")}),i.css(\"visibility\",\"visible\"))})}};return layui.each(e,function(i,t){t()})};var b=new s,p=t(document);b.init();var v=\".layui-tab-title li\";p.on(\"click\",v,y.tabClick),p.on(\"click\",y.hideTabMore),t(window).on(\"resize\",y.tabAuto),i(e,function(i){return b.set(i)})});layui.define(\"layer\",function(e){\"use strict\";var a=layui.jquery,t=layui.layer,i=(layui.device(),\"layui-upload-enter\"),n=\"layui-upload-iframe\",r={icon:2,shift:6},o={file:\"文件\",video:\"视频\",audio:\"音频\"},s=function(e){this.options=e};s.prototype.init=function(){var e=this,t=e.options,r=a(\"body\"),s=a(t.elem||\".layui-upload-file\"),u=a('<iframe id=\"'+n+'\" class=\"'+n+'\" name=\"'+n+'\"></iframe>');return a(\"#\"+n)[0]||r.append(u),s.each(function(r,s){s=a(s);var u='<form target=\"'+n+'\" method=\"'+(t.method||\"post\")+'\" key=\"set-mine\" enctype=\"multipart/form-data\" action=\"'+(t.url||\"\")+'\"></form>',l=s.attr(\"lay-type\")||t.type;t.unwrap||(u='<div class=\"layui-box layui-upload-button\">'+u+'<span class=\"layui-upload-icon\"><i class=\"layui-icon\">&#xe608;</i>'+(s.attr(\"lay-title\")||t.title||\"上传\"+(o[l]||\"图片\"))+\"</span></div>\"),u=a(u),t.unwrap||u.on(\"dragover\",function(e){e.preventDefault(),a(this).addClass(i)}).on(\"dragleave\",function(){a(this).removeClass(i)}).on(\"drop\",function(){a(this).removeClass(i)}),s.parent(\"form\").attr(\"target\")===n&&(t.unwrap?s.unwrap():(s.parent().next().remove(),s.unwrap().unwrap())),s.wrap(u),s.off(\"change\").on(\"change\",function(){e.action(this,l)})})},s.prototype.action=function(e,i){var o=this,s=o.options,u=e.value,l=a(e),p=l.attr(\"lay-ext\")||s.ext||\"\";if(u){switch(i){case\"file\":if(p&&!RegExp(\"\\\\w\\\\.(\"+p+\")$\",\"i\").test(escape(u)))return t.msg(\"不支持该文件格式\",r),e.value=\"\";break;case\"video\":if(!RegExp(\"\\\\w\\\\.(\"+(p||\"avi|mp4|wma|rmvb|rm|flash|3gp|flv\")+\")$\",\"i\").test(escape(u)))return t.msg(\"不支持该视频格式\",r),e.value=\"\";break;case\"audio\":if(!RegExp(\"\\\\w\\\\.(\"+(p||\"mp3|wav|mid\")+\")$\",\"i\").test(escape(u)))return t.msg(\"不支持该音频格式\",r),e.value=\"\";break;default:if(!RegExp(\"\\\\w\\\\.(\"+(p||\"jpg|png|gif|bmp|jpeg\")+\")$\",\"i\").test(escape(u)))return t.msg(\"不支持该图片格式\",r),e.value=\"\"}s.before&&s.before(e),l.parent().submit();var c=a(\"#\"+n),f=setInterval(function(){var a;try{a=c.contents().find(\"body\").text()}catch(i){t.msg(\"上传接口存在跨域\",r),clearInterval(f)}if(a){clearInterval(f),c.contents().find(\"body\").html(\"\");try{a=JSON.parse(a)}catch(i){return a={},t.msg(\"请对上传接口返回JSON字符\",r)}\"function\"==typeof s.success&&s.success(a,e)}},30);e.value=\"\"}},e(\"upload\",function(e){var a=new s(e=e||{});a.init()})});layui.define(\"layer\",function(e){\"use strict\";var i=layui.jquery,a=layui.layer,t=layui.hint(),n=layui.device(),l=\"form\",s=\".layui-form\",c=\"layui-this\",r=\"layui-disabled\",u=function(){this.config={verify:{required:[/[\\S]+/,\"必填项不能为空\"],phone:[/^1\\d{10}$/,\"请输入正确的手机号\"],email:[/^([a-zA-Z0-9_\\.\\-])+\\@(([a-zA-Z0-9\\-])+\\.)+([a-zA-Z0-9]{2,4})+$/,\"邮箱格式不正确\"],url:[/(^#)|(^http(s*):\\/\\/[^\\s]+\\.[^\\s]+)/,\"链接格式不正确\"],number:[/^\\d+$/,\"只能填写数字\"],date:[/^(\\d{4})[-\\/](\\d{1}|0\\d{1}|1[0-2])([-\\/](\\d{1}|0\\d{1}|[1-2][0-9]|3[0-1]))*$/,\"日期格式不正确\"],identity:[/(^\\d{15}$)|(^\\d{17}(x|X|\\d)$)/,\"请输入正确的身份证号\"]}}};u.prototype.set=function(e){var a=this;return i.extend(!0,a.config,e),a},u.prototype.verify=function(e){var a=this;return i.extend(!0,a.config.verify,e),a},u.prototype.on=function(e,i){return layui.onevent(l,e,i)},u.prototype.render=function(e){var a=this,n={select:function(){var e=\"请选择\",a=\"layui-form-select\",t=\"layui-select-title\",n=i(s).find(\"select\"),u=function(e,n){i(e.target).parent().hasClass(t)&&!n||i(\".\"+a).removeClass(a+\"ed\")},o=function(e,n){var s=i(this),o=e.find(\".\"+t);n||(o.on(\"click\",function(i){e.hasClass(a+\"ed\")?e.removeClass(a+\"ed\"):(u(i,!0),e.addClass(a+\"ed\"))}),e.find(\"dl>dd\").on(\"click\",function(){var e=i(this),a=e.attr(\"lay-value\"),t=s.attr(\"lay-filter\");return!e.hasClass(r)&&(s.val(a).removeClass(\"layui-form-danger\"),o.find(\"input\").val(e.text()),e.addClass(c).siblings().removeClass(c),void layui.event(l,\"select(\"+t+\")\",{elem:s[0],value:a}))}),e.find(\"dl>dt\").on(\"click\",function(e){return!1}),i(document).off(\"click\",u).on(\"click\",u))};n.each(function(n,l){var s=i(this),u=s.next(\".\"+a),d=this.disabled,f=l.value,y=i(l.options[l.selectedIndex]),v=i(['<div class=\"layui-unselect '+a+(d?\" layui-select-disabled\":\"\")+'\">','<div class=\"'+t+'\"><input type=\"text\" placeholder=\"'+(l.options[0].innerHTML?l.options[0].innerHTML:e)+'\" value=\"'+(f?y.html():\"\")+'\" readonly class=\"layui-input layui-unselect'+(d?\" \"+r:\"\")+'\">','<i class=\"layui-edge\"></i></div>','<dl class=\"layui-anim layui-anim-upbit'+(s.find(\"optgroup\")[0]?\" layui-select-group\":\"\")+'\">'+function(e){var i=[];return layui.each(e,function(e,a){(0!==e||a.value)&&(\"optgroup\"===a.tagName.toLowerCase()?i.push(\"<dt>\"+a.label+\"</dt>\"):i.push('<dd lay-value=\"'+a.value+'\" class=\"'+(f===a.value?c:\"\")+(a.disabled?\" \"+r:\"\")+'\">'+a.innerHTML+\"</dd>\"))}),i.join(\"\")}(s.find(\"*\"))+\"</dl>\",\"</div>\"].join(\"\"));u[0]&&u.remove(),s.after(v),o.call(this,v,d)})},checkbox:function(){var e={checkbox:[\"layui-form-checkbox\",\"layui-form-checked\",\"checkbox\"],_switch:[\"layui-form-switch\",\"layui-form-onswitch\",\"switch\"]},a=i(s).find(\"input[type=checkbox]\"),t=function(e,a){var t=i(this);e.on(\"click\",function(){var i=t.attr(\"lay-filter\");t[0].disabled||(t[0].checked?(t[0].checked=!1,e.removeClass(a[1])):(t[0].checked=!0,e.addClass(a[1])),layui.event(l,a[2]+\"(\"+i+\")\",{elem:t[0],value:t[0].value}))})};a.each(function(a,n){var l=i(this),s=l.attr(\"lay-skin\"),c=this.disabled;\"switch\"===s&&(s=\"_\"+s);var u=e[s]||e.checkbox,o=l.next(\".\"+u[0]),d=i(['<div class=\"layui-unselect '+u[0]+(n.checked?\" \"+u[1]:\"\")+(c?\" layui-checkbox-disbaled \"+r:\"\")+'\">',{_switch:\"<i></i>\"}[s]||\"<span>\"+(n.title||\"勾选\")+'</span><i class=\"layui-icon\">&#xe618;</i>',\"</div>\"].join(\"\"));o[0]&&o.remove(),l.after(d),t.call(this,d,u)})},radio:function(){var e=\"layui-form-radio\",a=[\"&#xe643;\",\"&#xe63f;\"],t=i(s).find(\"input[type=radio]\"),n=function(t){var n=i(this),c=\"layui-anim-scaleSpring\";t.on(\"click\",function(){var r=n[0].name,u=n.parents(s),o=n.attr(\"lay-filter\"),d=u.find(\"input[name=\"+r.replace(/(\\.|#|\\[|\\])/g,\"\\\\$1\")+\"]\");n[0].disabled||(layui.each(d,function(){var t=i(this).next(\".\"+e);this.checked=!1,t.removeClass(e+\"ed\"),t.find(\".layui-icon\").removeClass(c).html(a[1])}),n[0].checked=!0,t.addClass(e+\"ed\"),t.find(\".layui-icon\").addClass(c).html(a[0]),layui.event(l,\"radio(\"+o+\")\",{elem:n[0],value:n[0].value}))})};t.each(function(t,l){var s=i(this),c=s.next(\".\"+e),u=this.disabled,o=i(['<div class=\"layui-unselect '+e+(l.checked?\" \"+e+\"ed\":\"\")+(u?\" layui-radio-disbaled \"+r:\"\")+'\">','<i class=\"layui-anim layui-icon\">'+a[l.checked?0:1]+\"</i>\",\"<span>\"+(l.title||\"未命名\")+\"</span>\",\"</div>\"].join(\"\"));c[0]&&c.remove(),s.after(o),n.call(this,o)})}};return e?n[e]?n[e]():t.error(\"不支持的\"+e+\"表单渲染\"):layui.each(n,function(e,i){i()}),a};var o=function(){var e=i(this),t=d.config.verify,c=null,r=\"layui-form-danger\",u={},o=e.parents(s),f=o.find(\"*[lay-verify]\"),y=e.parents(\"form\")[0],v=o.find(\"input,select,textarea\"),h=e.attr(\"lay-filter\");return layui.each(f,function(e,l){var s=i(this),u=s.attr(\"lay-verify\"),o=\"\",d=s.val(),f=\"function\"==typeof t[u];if(s.removeClass(r),t[u]&&(f?o=t[u](d,l):!t[u][0].test(d)))return a.msg(o||t[u][1],{icon:5,shift:6}),n.android||n.ios||l.focus(),s.addClass(r),c=!0}),!c&&(layui.each(v,function(e,i){i.name&&(/^checkbox|radio$/.test(i.type)&&!i.checked||(u[i.name]=i.value))}),layui.event.call(this,l,\"submit(\"+h+\")\",{elem:this,form:y,field:u}))},d=new u,f=i(document);d.render(),f.on(\"reset\",s,function(){setTimeout(function(){d.render()},50)}),f.on(\"submit\",s,o).on(\"click\",\"*[lay-submit]\",o),e(l,function(e){return d.set(e)})});layui.define(\"jquery\",function(e){\"use strict\";var o=layui.jquery,a=layui.hint(),r=\"layui-tree-enter\",i=function(e){this.options=e},t={arrow:[\"&#xe623;\",\"&#xe625;\"],checkbox:[\"&#xe626;\",\"&#xe627;\"],radio:[\"&#xe62b;\",\"&#xe62a;\"],branch:[\"&#xe622;\",\"&#xe624;\"],leaf:\"&#xe621;\"};i.prototype.init=function(e){var o=this;e.addClass(\"layui-box layui-tree\"),o.options.skin&&e.addClass(\"layui-tree-skin-\"+o.options.skin),o.tree(e),o.on(e)},i.prototype.tree=function(e,a){var r=this,i=r.options,n=a||i.nodes;layui.each(n,function(a,n){var l=n.children&&n.children.length>0,c=o('<ul class=\"'+(n.spread?\"layui-show\":\"\")+'\"></ul>'),s=o([\"<li \"+(n.spread?'data-spread=\"'+n.spread+'\"':\"\")+\">\",function(){return l?'<i class=\"layui-icon layui-tree-spread\">'+(n.spread?t.arrow[1]:t.arrow[0])+\"</i>\":\"\"}(),function(){return i.check?'<i class=\"layui-icon layui-tree-check\">'+(\"checkbox\"===i.check?t.checkbox[0]:\"radio\"===i.check?t.radio[0]:\"\")+\"</i>\":\"\"}(),function(){return'<a href=\"'+(n.href||\"javascript:;\")+'\" '+(i.target&&n.href?'target=\"'+i.target+'\"':\"\")+\">\"+('<i class=\"layui-icon layui-tree-'+(l?\"branch\":\"leaf\")+'\">'+(l?n.spread?t.branch[1]:t.branch[0]:t.leaf)+\"</i>\")+(\"<cite>\"+(n.name||\"未命名\")+\"</cite></a>\")}(),\"</li>\"].join(\"\"));l&&(s.append(c),r.tree(c,n.children)),e.append(s),\"function\"==typeof i.click&&r.click(s,n),r.spread(s,n),i.drag&&r.drag(s,n)})},i.prototype.click=function(e,o){var a=this,r=a.options;e.children(\"a\").on(\"click\",function(e){layui.stope(e),r.click(o)})},i.prototype.spread=function(e,o){var a=this,r=(a.options,e.children(\".layui-tree-spread\")),i=e.children(\"ul\"),n=e.children(\"a\"),l=function(){e.data(\"spread\")?(e.data(\"spread\",null),i.removeClass(\"layui-show\"),r.html(t.arrow[0]),n.find(\".layui-icon\").html(t.branch[0])):(e.data(\"spread\",!0),i.addClass(\"layui-show\"),r.html(t.arrow[1]),n.find(\".layui-icon\").html(t.branch[1]))};i[0]&&(r.on(\"click\",l),n.on(\"dblclick\",l))},i.prototype.on=function(e){var a=this,i=a.options,t=\"layui-tree-drag\";e.find(\"i\").on(\"selectstart\",function(e){return!1}),i.drag&&o(document).on(\"mousemove\",function(e){var r=a.move;if(r.from){var i=(r.to,o('<div class=\"layui-box '+t+'\"></div>'));e.preventDefault(),o(\".\"+t)[0]||o(\"body\").append(i);var n=o(\".\"+t)[0]?o(\".\"+t):i;n.addClass(\"layui-show\").html(r.from.elem.children(\"a\").html()),n.css({left:e.pageX+10,top:e.pageY+10})}}).on(\"mouseup\",function(){var e=a.move;e.from&&(e.from.elem.children(\"a\").removeClass(r),e.to&&e.to.elem.children(\"a\").removeClass(r),a.move={},o(\".\"+t).remove())})},i.prototype.move={},i.prototype.drag=function(e,a){var i=this,t=(i.options,e.children(\"a\")),n=function(){var t=o(this),n=i.move;n.from&&(n.to={item:a,elem:e},t.addClass(r))};t.on(\"mousedown\",function(){var o=i.move;o.from={item:a,elem:e}}),t.on(\"mouseenter\",n).on(\"mousemove\",n).on(\"mouseleave\",function(){var e=o(this),a=i.move;a.from&&(delete a.to,e.removeClass(r))})},e(\"tree\",function(e){var r=new i(e=e||{}),t=o(e.elem);return t[0]?void r.init(t):a.error(\"layui.tree 没有找到\"+e.elem+\"元素\")})});layui.define(\"jquery\",function(l){\"use strict\";var o=layui.jquery,i={fixbar:function(l){l=l||{},l.bgcolor=l.bgcolor?\"background-color:\"+l.bgcolor:\"\";var i,a,c=\"layui-fixbar-top\",t=[l.bar1===!0?\"&#xe606;\":l.bar1,l.bar2===!0?\"&#xe607;\":l.bar2,\"&#xe604;\"],r=o(['<ul class=\"layui-fixbar\">',l.bar1?'<li class=\"layui-icon\" lay-type=\"bar1\" style=\"'+l.bgcolor+'\">'+t[0]+\"</li>\":\"\",l.bar2?'<li class=\"layui-icon\" lay-type=\"bar2\" style=\"'+l.bgcolor+'\">'+t[1]+\"</li>\":\"\",'<li class=\"layui-icon '+c+'\" lay-type=\"top\" style=\"'+l.bgcolor+'\">'+t[2]+\"</li>\",\"</ul>\"].join(\"\")),e=r.find(\".\"+c),s=function(){var i=o(document).scrollTop();i>=(l.showHeight||200)?a||(e.show(),a=1):a&&(e.hide(),a=0)};o(\".layui-fixbar\")[0]||(\"object\"==typeof l.css&&r.css(l.css),o(\"body\").append(r),s(),r.find(\"li\").on(\"click\",function(){var i=o(this),a=i.attr(\"lay-type\");\"top\"===a&&o(\"html,body\").animate({scrollTop:0},200),l.click&&l.click.call(this,a)}),o(document).on(\"scroll\",function(){i&&clearTimeout(i),i=setTimeout(function(){s()},100)}))}};l(\"util\",i)});layui.define(\"jquery\",function(e){\"use strict\";var l=layui.jquery,o=function(e){},t='<i class=\"layui-anim layui-anim-rotate layui-anim-loop layui-icon \">&#xe63e;</i>';o.prototype.load=function(e){var o,i,n,r,a=this,c=0;e=e||{};var u=l(e.elem);if(u[0]){var f=l(e.scrollElem||document),m=e.mb||50,s=!(\"isAuto\"in e)||e.isAuto,y=e.end||\"没有更多了\",v=e.scrollElem&&e.scrollElem!==document,d=\"<cite>加载更多</cite>\",h=l('<div class=\"layui-flow-more\"><a href=\"javascript:;\">'+d+\"</a></div>\");u.find(\".layui-flow-more\")[0]||u.append(h);var p=function(e,t){e=l(e),h.before(e),t=0==t||null,t?h.html(y):h.find(\"a\").html(d),i=t,o=null,n&&n()},g=function(){o=!0,h.find(\"a\").html(t),\"function\"==typeof e.done&&e.done(++c,p)};if(g(),h.find(\"a\").on(\"click\",function(){l(this);i||o||g()}),e.isLazyimg)var n=a.lazyimg({elem:e.elem+\" img\",scrollElem:e.scrollElem});return s?(f.on(\"scroll\",function(){var e=l(this),t=e.scrollTop();r&&clearTimeout(r),i||(r=setTimeout(function(){var i=v?e.height():l(window).height(),n=v?e.prop(\"scrollHeight\"):document.documentElement.scrollHeight;n-t-i<=m&&(o||g())},100))}),a):a}},o.prototype.lazyimg=function(e){var o,t=this,i=0;e=e||{};var n=l(e.scrollElem||document),r=e.elem||\"img\",a=e.scrollElem&&e.scrollElem!==document,c=function(e,l){var o=n.scrollTop(),r=o+l,c=a?function(){return e.offset().top-n.offset().top+o}():e.offset().top;if(c>=o&&c<=r&&!e.attr(\"src\")){var f=e.attr(\"lay-src\");layui.img(f,function(){var l=t.lazyimg.elem.eq(i);e.attr(\"src\",f).removeAttr(\"lay-src\"),l[0]&&u(l),i++})}},u=function(e,o){var u=a?(o||n).height():l(window).height(),f=n.scrollTop(),m=f+u;if(t.lazyimg.elem=l(r),e)c(e,u);else for(var s=0;s<t.lazyimg.elem.length;s++){var y=t.lazyimg.elem.eq(s),v=a?function(){return y.offset().top-n.offset().top+f}():y.offset().top;if(c(y,u),i=s,v>m)break}};if(u(),!o){var f;n.on(\"scroll\",function(){var e=l(this);f&&clearTimeout(f),f=setTimeout(function(){u(null,e)},50)}),o=!0}return u},e(\"flow\",new o)});layui.define([\"layer\",\"form\"],function(t){\"use strict\";var e=layui.jquery,i=layui.layer,a=layui.form(),l=(layui.hint(),layui.device()),n=\"layedit\",o=\"layui-show\",r=\"layui-disabled\",s=function(){var t=this;t.index=0,t.config={tool:[\"strong\",\"italic\",\"underline\",\"del\",\"|\",\"left\",\"center\",\"right\",\"|\",\"link\",\"unlink\",\"face\",\"image\"],hideTool:[],height:280}};s.prototype.set=function(t){var i=this;return e.extend(!0,i.config,t),i},s.prototype.on=function(t,e){return layui.onevent(n,t,e)},s.prototype.build=function(t,i){i=i||{};var a=this,n=a.config,r=\"layui-layedit\",s=e(\"#\"+t),u=\"LAY_layedit_\"+ ++a.index,d=s.next(\".\"+r),y=e.extend({},n,i),f=function(){var t=[],e={};return layui.each(y.hideTool,function(t,i){e[i]=!0}),layui.each(y.tool,function(i,a){C[a]&&!e[a]&&t.push(C[a])}),t.join(\"\")}(),m=e(['<div class=\"'+r+'\">','<div class=\"layui-unselect layui-layedit-tool\">'+f+\"</div>\",'<div class=\"layui-layedit-iframe\">','<iframe id=\"'+u+'\" name=\"'+u+'\" textarea=\"'+t+'\" frameborder=\"0\"></iframe>',\"</div>\",\"</div>\"].join(\"\"));return l.ie&&l.ie<8?s.removeClass(\"layui-hide\").addClass(o):(d[0]&&d.remove(),c.call(a,m,s[0],y),s.addClass(\"layui-hide\").after(m),a.index)},s.prototype.getContent=function(t){var e=u(t);if(e[0])return d(e[0].document.body.innerHTML)},s.prototype.getText=function(t){var i=u(t);if(i[0])return e(i[0].document.body).text()},s.prototype.sync=function(t){var i=u(t);if(i[0]){var a=e(\"#\"+i[1].attr(\"textarea\"));a.val(d(i[0].document.body.innerHTML))}},s.prototype.getSelection=function(t){var e=u(t);if(e[0]){var i=m(e[0].document);return document.selection?i.text:i.toString()}};var c=function(t,i,a){var l=this,n=t.find(\"iframe\");n.css({height:a.height}).on(\"load\",function(){var o=n.contents(),r=n.prop(\"contentWindow\"),s=o.find(\"head\"),c=e([\"<style>\",\"*{margin: 0; padding: 0;}\",\"body{padding: 10px; line-height: 20px; overflow-x: hidden; word-wrap: break-word; font: 14px Helvetica Neue,Helvetica,PingFang SC,Microsoft YaHei,Tahoma,Arial,sans-serif; -webkit-box-sizing: border-box !important; -moz-box-sizing: border-box !important; box-sizing: border-box !important;}\",\"a{color:#01AAED; text-decoration:none;}a:hover{color:#c00}\",\"p{margin-bottom: 10px;}\",\"img{display: inline-block; border: none; vertical-align: middle;}\",\"pre{margin: 10px 0; padding: 10px; line-height: 20px; border: 1px solid #ddd; border-left-width: 6px; background-color: #F2F2F2; color: #333; font-family: Courier New; font-size: 12px;}\",\"</style>\"].join(\"\")),u=o.find(\"body\");s.append(c),u.attr(\"contenteditable\",\"true\").css({\"min-height\":a.height}).html(i.value||\"\"),y.apply(l,[r,n,i,a]),g.call(l,r,t,a)})},u=function(t){var i=e(\"#LAY_layedit_\"+t),a=i.prop(\"contentWindow\");return[a,i]},d=function(t){return 8==l.ie&&(t=t.replace(/<.+>/g,function(t){return t.toLowerCase()})),t},y=function(t,a,n,o){var r=t.document,s=e(r.body);s.on(\"keydown\",function(t){var e=t.keyCode;if(13===e){var a=m(r),l=p(a),n=l.parentNode;if(\"pre\"===n.tagName.toLowerCase()){if(t.shiftKey)return;return i.msg(\"请暂时用shift+enter\"),!1}r.execCommand(\"formatBlock\",!1,\"<p>\")}}),e(n).parents(\"form\").on(\"submit\",function(){var t=s.html();8==l.ie&&(t=t.replace(/<.+>/g,function(t){return t.toLowerCase()})),n.value=t}),s.on(\"paste\",function(e){r.execCommand(\"formatBlock\",!1,\"<p>\"),setTimeout(function(){f.call(t,s),n.value=s.html()},100)})},f=function(t){var i=this;i.document;t.find(\"*[style]\").each(function(){var t=this.style.textAlign;this.removeAttribute(\"style\"),e(this).css({\"text-align\":t||\"\"})}),t.find(\"table\").addClass(\"layui-table\"),t.find(\"script,link\").remove()},m=function(t){return t.selection?t.selection.createRange():t.getSelection().getRangeAt(0)},p=function(t){return t.endContainer||t.parentElement().childNodes[0]},v=function(t,i,a){var l=this.document,n=document.createElement(t);for(var o in i)n.setAttribute(o,i[o]);if(n.removeAttribute(\"text\"),l.selection){var r=a.text||i.text;if(\"a\"===t&&!r)return;r&&(n.innerHTML=r),a.pasteHTML(e(n).prop(\"outerHTML\")),a.select()}else{var r=a.toString()||i.text;if(\"a\"===t&&!r)return;r&&(n.innerHTML=r),a.deleteContents(),a.insertNode(n)}},h=function(t,i){var a=this.document,l=\"layedit-tool-active\",n=p(m(a)),o=function(e){return t.find(\".layedit-tool-\"+e)};i&&i[i.hasClass(l)?\"removeClass\":\"addClass\"](l),t.find(\">i\").removeClass(l),o(\"unlink\").addClass(r),e(n).parents().each(function(){var t=this.tagName.toLowerCase(),e=this.style.textAlign;\"b\"!==t&&\"strong\"!==t||o(\"b\").addClass(l),\"i\"!==t&&\"em\"!==t||o(\"i\").addClass(l),\"u\"===t&&o(\"u\").addClass(l),\"strike\"===t&&o(\"d\").addClass(l),\"p\"===t&&(\"center\"===e?o(\"center\").addClass(l):\"right\"===e?o(\"right\").addClass(l):o(\"left\").addClass(l)),\"a\"===t&&(o(\"link\").addClass(l),o(\"unlink\").removeClass(r))})},g=function(t,a,l){var n=t.document,o=e(n.body),s={link:function(i){var a=p(i),l=e(a).parent();b.call(o,{href:l.attr(\"href\"),target:l.attr(\"target\")},function(e){var a=l[0];\"A\"===a.tagName?a.href=e.url:v.call(t,\"a\",{target:e.target,href:e.url,text:e.url},i)})},unlink:function(t){n.execCommand(\"unlink\")},face:function(e){x.call(this,function(i){v.call(t,\"img\",{src:i.src,alt:i.alt},e)})},image:function(a){var n=this;layui.use(\"upload\",function(o){var r=l.uploadImage||{};o({url:r.url,method:r.type,elem:e(n).find(\"input\")[0],unwrap:!0,success:function(e){0==e.code?(e.data=e.data||{},v.call(t,\"img\",{src:e.data.src,alt:e.data.title},a)):i.msg(e.msg||\"上传失败\")}})})},code:function(e){k.call(o,function(i){v.call(t,\"pre\",{text:i.code,\"lay-lang\":i.lang},e)})},help:function(){i.open({type:2,title:\"帮助\",area:[\"600px\",\"380px\"],shadeClose:!0,shade:.1,skin:\"layui-layer-msg\",content:[\"http://www.layui.com/about/layedit/help.html\",\"no\"]})}},c=a.find(\".layui-layedit-tool\"),u=function(){var i=e(this),a=i.attr(\"layedit-event\"),l=i.attr(\"lay-command\");if(!i.hasClass(r)){o.focus();var u=m(n);u.commonAncestorContainer;l?(n.execCommand(l),/justifyLeft|justifyCenter|justifyRight/.test(l)&&n.execCommand(\"formatBlock\",!1,\"<p>\"),setTimeout(function(){o.focus()},10)):s[a]&&s[a].call(this,u),h.call(t,c,i)}},d=/image/;c.find(\">i\").on(\"mousedown\",function(){var t=e(this),i=t.attr(\"layedit-event\");d.test(i)||u.call(this)}).on(\"click\",function(){var t=e(this),i=t.attr(\"layedit-event\");d.test(i)&&u.call(this)}),o.on(\"click\",function(){h.call(t,c),i.close(x.index)})},b=function(t,e){var l=this,n=i.open({type:1,id:\"LAY_layedit_link\",area:\"350px\",shade:.05,shadeClose:!0,moveType:1,title:\"超链接\",skin:\"layui-layer-msg\",content:['<ul class=\"layui-form\" style=\"margin: 15px;\">','<li class=\"layui-form-item\">','<label class=\"layui-form-label\" style=\"width: 60px;\">URL</label>','<div class=\"layui-input-block\" style=\"margin-left: 90px\">','<input name=\"url\" lay-verify=\"url\" value=\"'+(t.href||\"\")+'\" autofocus=\"true\" autocomplete=\"off\" class=\"layui-input\">',\"</div>\",\"</li>\",'<li class=\"layui-form-item\">','<label class=\"layui-form-label\" style=\"width: 60px;\">打开方式</label>','<div class=\"layui-input-block\" style=\"margin-left: 90px\">','<input type=\"radio\" name=\"target\" value=\"_self\" class=\"layui-input\" title=\"当前窗口\"'+(\"_self\"!==t.target&&t.target?\"\":\"checked\")+\">\",'<input type=\"radio\" name=\"target\" value=\"_blank\" class=\"layui-input\" title=\"新窗口\" '+(\"_blank\"===t.target?\"checked\":\"\")+\">\",\"</div>\",\"</li>\",'<li class=\"layui-form-item\" style=\"text-align: center;\">','<button type=\"button\" lay-submit lay-filter=\"layedit-link-yes\" class=\"layui-btn\"> 确定 </button>','<button style=\"margin-left: 20px;\" type=\"button\" class=\"layui-btn layui-btn-primary\"> 取消 </button>',\"</li>\",\"</ul>\"].join(\"\"),success:function(t,n){var o=\"submit(layedit-link-yes)\";a.render(\"radio\"),t.find(\".layui-btn-primary\").on(\"click\",function(){i.close(n),l.focus()}),a.on(o,function(t){i.close(b.index),e&&e(t.field)})}});b.index=n},x=function(t){var a=function(){var t=[\"[微笑]\",\"[嘻嘻]\",\"[哈哈]\",\"[可爱]\",\"[可怜]\",\"[挖鼻]\",\"[吃惊]\",\"[害羞]\",\"[挤眼]\",\"[闭嘴]\",\"[鄙视]\",\"[爱你]\",\"[泪]\",\"[偷笑]\",\"[亲亲]\",\"[生病]\",\"[太开心]\",\"[白眼]\",\"[右哼哼]\",\"[左哼哼]\",\"[嘘]\",\"[衰]\",\"[委屈]\",\"[吐]\",\"[哈欠]\",\"[抱抱]\",\"[怒]\",\"[疑问]\",\"[馋嘴]\",\"[拜拜]\",\"[思考]\",\"[汗]\",\"[困]\",\"[睡]\",\"[钱]\",\"[失望]\",\"[酷]\",\"[色]\",\"[哼]\",\"[鼓掌]\",\"[晕]\",\"[悲伤]\",\"[抓狂]\",\"[黑线]\",\"[阴险]\",\"[怒骂]\",\"[互粉]\",\"[心]\",\"[伤心]\",\"[猪头]\",\"[熊猫]\",\"[兔子]\",\"[ok]\",\"[耶]\",\"[good]\",\"[NO]\",\"[赞]\",\"[来]\",\"[弱]\",\"[草泥马]\",\"[神马]\",\"[囧]\",\"[浮云]\",\"[给力]\",\"[围观]\",\"[威武]\",\"[奥特曼]\",\"[礼物]\",\"[钟]\",\"[话筒]\",\"[蜡烛]\",\"[蛋糕]\"],e={};return layui.each(t,function(t,i){e[i]=layui.cache.dir+\"images/face/\"+t+\".gif\"}),e}();return x.hide=x.hide||function(t){\"face\"!==e(t.target).attr(\"layedit-event\")&&i.close(x.index)},x.index=i.tips(function(){var t=[];return layui.each(a,function(e,i){t.push('<li title=\"'+e+'\"><img src=\"'+i+'\" alt=\"'+e+'\"></li>')}),'<ul class=\"layui-clear\">'+t.join(\"\")+\"</ul>\"}(),this,{tips:1,time:0,skin:\"layui-box layui-util-face\",maxWidth:500,success:function(l,n){l.css({marginTop:-4,marginLeft:-10}).find(\".layui-clear>li\").on(\"click\",function(){t&&t({src:a[this.title],alt:this.title}),i.close(n)}),e(document).off(\"click\",x.hide).on(\"click\",x.hide)}})},k=function(t){var e=this,l=i.open({type:1,id:\"LAY_layedit_code\",area:\"550px\",shade:.05,shadeClose:!0,moveType:1,title:\"插入代码\",skin:\"layui-layer-msg\",content:['<ul class=\"layui-form layui-form-pane\" style=\"margin: 15px;\">','<li class=\"layui-form-item\">','<label class=\"layui-form-label\">请选择语言</label>','<div class=\"layui-input-block\">','<select name=\"lang\">','<option value=\"JavaScript\">JavaScript</option>','<option value=\"HTML\">HTML</option>','<option value=\"CSS\">CSS</option>','<option value=\"Java\">Java</option>','<option value=\"PHP\">PHP</option>','<option value=\"C#\">C#</option>','<option value=\"Python\">Python</option>','<option value=\"Ruby\">Ruby</option>','<option value=\"Go\">Go</option>',\"</select>\",\"</div>\",\"</li>\",'<li class=\"layui-form-item layui-form-text\">','<label class=\"layui-form-label\">代码</label>','<div class=\"layui-input-block\">','<textarea name=\"code\" lay-verify=\"required\" autofocus=\"true\" class=\"layui-textarea\" style=\"height: 200px;\"></textarea>',\"</div>\",\"</li>\",'<li class=\"layui-form-item\" style=\"text-align: center;\">','<button type=\"button\" lay-submit lay-filter=\"layedit-code-yes\" class=\"layui-btn\"> 确定 </button>','<button style=\"margin-left: 20px;\" type=\"button\" class=\"layui-btn layui-btn-primary\"> 取消 </button>',\"</li>\",\"</ul>\"].join(\"\"),success:function(l,n){var o=\"submit(layedit-code-yes)\";a.render(\"select\"),l.find(\".layui-btn-primary\").on(\"click\",function(){i.close(n),e.focus()}),a.on(o,function(e){i.close(k.index),t&&t(e.field)})}});k.index=l},C={html:'<i class=\"layui-icon layedit-tool-html\" title=\"HTML源代码\" lay-command=\"html\" layedit-event=\"html\"\">&#xe64b;</i><span class=\"layedit-tool-mid\"></span>',strong:'<i class=\"layui-icon layedit-tool-b\" title=\"加粗\" lay-command=\"Bold\" layedit-event=\"b\"\">&#xe62b;</i>',italic:'<i class=\"layui-icon layedit-tool-i\" title=\"斜体\" lay-command=\"italic\" layedit-event=\"i\"\">&#xe644;</i>',underline:'<i class=\"layui-icon layedit-tool-u\" title=\"下划线\" lay-command=\"underline\" layedit-event=\"u\"\">&#xe646;</i>',del:'<i class=\"layui-icon layedit-tool-d\" title=\"删除线\" lay-command=\"strikeThrough\" layedit-event=\"d\"\">&#xe64f;</i>',\"|\":'<span class=\"layedit-tool-mid\"></span>',left:'<i class=\"layui-icon layedit-tool-left\" title=\"左对齐\" lay-command=\"justifyLeft\" layedit-event=\"left\"\">&#xe649;</i>',center:'<i class=\"layui-icon layedit-tool-center\" title=\"居中对齐\" lay-command=\"justifyCenter\" layedit-event=\"center\"\">&#xe647;</i>',right:'<i class=\"layui-icon layedit-tool-right\" title=\"右对齐\" lay-command=\"justifyRight\" layedit-event=\"right\"\">&#xe648;</i>',link:'<i class=\"layui-icon layedit-tool-link\" title=\"插入链接\" layedit-event=\"link\"\">&#xe64c;</i>',unlink:'<i class=\"layui-icon layedit-tool-unlink layui-disabled\" title=\"清除链接\" lay-command=\"unlink\" layedit-event=\"unlink\"\">&#xe64d;</i>',face:'<i class=\"layui-icon layedit-tool-face\" title=\"表情\" layedit-event=\"face\"\">&#xe650;</i>',image:'<i class=\"layui-icon layedit-tool-image\" title=\"图片\" layedit-event=\"image\">&#xe64a;<input type=\"file\" name=\"file\"></i>',code:'<i class=\"layui-icon layedit-tool-code\" title=\"插入代码\" layedit-event=\"code\">&#xe64e;</i>',help:'<i class=\"layui-icon layedit-tool-help\" title=\"帮助\" layedit-event=\"help\">&#xe607;</i>'},w=new s;t(n,w)});layui.define(\"jquery\",function(e){\"use strict\";var a=layui.jquery,l=\"http://www.layui.com/doc/modules/code.html\";e(\"code\",function(e){var t=[];e=e||{},e.elem=a(e.elem||\".layui-code\"),e.about=!(\"about\"in e)||e.about,e.elem.each(function(){t.push(this)}),layui.each(t.reverse(),function(t,i){var c=a(i),o=c.html();(c.attr(\"lay-encode\")||e.encode)&&(o=o.replace(/&(?!#?[a-zA-Z0-9]+;)/g,\"&amp;\").replace(/</g,\"&lt;\").replace(/>/g,\"&gt;\").replace(/'/g,\"&#39;\").replace(/\"/g,\"&quot;\")),c.html('<ol class=\"layui-code-ol\"><li>'+o.replace(/[\\r\\t\\n]+/g,\"</li><li>\")+\"</li></ol>\"),c.find(\">.layui-code-h3\")[0]||c.prepend('<h3 class=\"layui-code-h3\">'+(c.attr(\"lay-title\")||e.title||\"code\")+(e.about?'<a href=\"'+l+'\" target=\"_blank\">layui.code</a>':\"\")+\"</h3>\");var d=c.find(\">.layui-code-ol\");c.addClass(\"layui-box layui-code-view\"),(c.attr(\"lay-skin\")||e.skin)&&c.addClass(\"layui-code-\"+(c.attr(\"lay-skin\")||e.skin)),(d.find(\"li\").length/100|0)>0&&d.css(\"margin-left\",(d.find(\"li\").length/100|0)+\"px\"),(c.attr(\"lay-height\")||e.height)&&d.css(\"max-height\",c.attr(\"lay-height\")||e.height)})})}).addcss(\"modules/code.css\",\"skincodecss\");"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/plugins/layui/lay/lib/jquery.js",
    "content": "/** layui-v1.0.7 LGPL License By http://www.layui.com */\n ;!function(e,t){\"object\"==typeof module&&\"object\"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error(\"jQuery requires a window with a document\");return t(e)}:t(e)}(\"undefined\"!=typeof window?window:this,function(e,t){function n(e){var t=!!e&&\"length\"in e&&e.length,n=pe.type(e);return\"function\"!==n&&!pe.isWindow(e)&&(\"array\"===n||0===t||\"number\"==typeof t&&t>0&&t-1 in e)}function r(e,t,n){if(pe.isFunction(t))return pe.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return pe.grep(e,function(e){return e===t!==n});if(\"string\"==typeof t){if(Ce.test(t))return pe.filter(t,e,n);t=pe.filter(t,e)}return pe.grep(e,function(e){return pe.inArray(e,t)>-1!==n})}function i(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}function o(e){var t={};return pe.each(e.match(De)||[],function(e,n){t[n]=!0}),t}function a(){re.addEventListener?(re.removeEventListener(\"DOMContentLoaded\",s),e.removeEventListener(\"load\",s)):(re.detachEvent(\"onreadystatechange\",s),e.detachEvent(\"onload\",s))}function s(){(re.addEventListener||\"load\"===e.event.type||\"complete\"===re.readyState)&&(a(),pe.ready())}function u(e,t,n){if(void 0===n&&1===e.nodeType){var r=\"data-\"+t.replace(_e,\"-$1\").toLowerCase();if(n=e.getAttribute(r),\"string\"==typeof n){try{n=\"true\"===n||\"false\"!==n&&(\"null\"===n?null:+n+\"\"===n?+n:qe.test(n)?pe.parseJSON(n):n)}catch(i){}pe.data(e,t,n)}else n=void 0}return n}function l(e){var t;for(t in e)if((\"data\"!==t||!pe.isEmptyObject(e[t]))&&\"toJSON\"!==t)return!1;return!0}function c(e,t,n,r){if(He(e)){var i,o,a=pe.expando,s=e.nodeType,u=s?pe.cache:e,l=s?e[a]:e[a]&&a;if(l&&u[l]&&(r||u[l].data)||void 0!==n||\"string\"!=typeof t)return l||(l=s?e[a]=ne.pop()||pe.guid++:a),u[l]||(u[l]=s?{}:{toJSON:pe.noop}),\"object\"!=typeof t&&\"function\"!=typeof t||(r?u[l]=pe.extend(u[l],t):u[l].data=pe.extend(u[l].data,t)),o=u[l],r||(o.data||(o.data={}),o=o.data),void 0!==n&&(o[pe.camelCase(t)]=n),\"string\"==typeof t?(i=o[t],null==i&&(i=o[pe.camelCase(t)])):i=o,i}}function f(e,t,n){if(He(e)){var r,i,o=e.nodeType,a=o?pe.cache:e,s=o?e[pe.expando]:pe.expando;if(a[s]){if(t&&(r=n?a[s]:a[s].data)){pe.isArray(t)?t=t.concat(pe.map(t,pe.camelCase)):t in r?t=[t]:(t=pe.camelCase(t),t=t in r?[t]:t.split(\" \")),i=t.length;for(;i--;)delete r[t[i]];if(n?!l(r):!pe.isEmptyObject(r))return}(n||(delete a[s].data,l(a[s])))&&(o?pe.cleanData([e],!0):fe.deleteExpando||a!=a.window?delete a[s]:a[s]=void 0)}}}function d(e,t,n,r){var i,o=1,a=20,s=r?function(){return r.cur()}:function(){return pe.css(e,t,\"\")},u=s(),l=n&&n[3]||(pe.cssNumber[t]?\"\":\"px\"),c=(pe.cssNumber[t]||\"px\"!==l&&+u)&&Me.exec(pe.css(e,t));if(c&&c[3]!==l){l=l||c[3],n=n||[],c=+u||1;do o=o||\".5\",c/=o,pe.style(e,t,c+l);while(o!==(o=s()/u)&&1!==o&&--a)}return n&&(c=+c||+u||0,i=n[1]?c+(n[1]+1)*n[2]:+n[2],r&&(r.unit=l,r.start=c,r.end=i)),i}function p(e){var t=ze.split(\"|\"),n=e.createDocumentFragment();if(n.createElement)for(;t.length;)n.createElement(t.pop());return n}function h(e,t){var n,r,i=0,o=\"undefined\"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||\"*\"):\"undefined\"!=typeof e.querySelectorAll?e.querySelectorAll(t||\"*\"):void 0;if(!o)for(o=[],n=e.childNodes||e;null!=(r=n[i]);i++)!t||pe.nodeName(r,t)?o.push(r):pe.merge(o,h(r,t));return void 0===t||t&&pe.nodeName(e,t)?pe.merge([e],o):o}function g(e,t){for(var n,r=0;null!=(n=e[r]);r++)pe._data(n,\"globalEval\",!t||pe._data(t[r],\"globalEval\"))}function m(e){Be.test(e.type)&&(e.defaultChecked=e.checked)}function y(e,t,n,r,i){for(var o,a,s,u,l,c,f,d=e.length,y=p(t),v=[],x=0;x<d;x++)if(a=e[x],a||0===a)if(\"object\"===pe.type(a))pe.merge(v,a.nodeType?[a]:a);else if(Ue.test(a)){for(u=u||y.appendChild(t.createElement(\"div\")),l=(We.exec(a)||[\"\",\"\"])[1].toLowerCase(),f=Xe[l]||Xe._default,u.innerHTML=f[1]+pe.htmlPrefilter(a)+f[2],o=f[0];o--;)u=u.lastChild;if(!fe.leadingWhitespace&&$e.test(a)&&v.push(t.createTextNode($e.exec(a)[0])),!fe.tbody)for(a=\"table\"!==l||Ve.test(a)?\"<table>\"!==f[1]||Ve.test(a)?0:u:u.firstChild,o=a&&a.childNodes.length;o--;)pe.nodeName(c=a.childNodes[o],\"tbody\")&&!c.childNodes.length&&a.removeChild(c);for(pe.merge(v,u.childNodes),u.textContent=\"\";u.firstChild;)u.removeChild(u.firstChild);u=y.lastChild}else v.push(t.createTextNode(a));for(u&&y.removeChild(u),fe.appendChecked||pe.grep(h(v,\"input\"),m),x=0;a=v[x++];)if(r&&pe.inArray(a,r)>-1)i&&i.push(a);else if(s=pe.contains(a.ownerDocument,a),u=h(y.appendChild(a),\"script\"),s&&g(u),n)for(o=0;a=u[o++];)Ie.test(a.type||\"\")&&n.push(a);return u=null,y}function v(){return!0}function x(){return!1}function b(){try{return re.activeElement}catch(e){}}function w(e,t,n,r,i,o){var a,s;if(\"object\"==typeof t){\"string\"!=typeof n&&(r=r||n,n=void 0);for(s in t)w(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&(\"string\"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),i===!1)i=x;else if(!i)return e;return 1===o&&(a=i,i=function(e){return pe().off(e),a.apply(this,arguments)},i.guid=a.guid||(a.guid=pe.guid++)),e.each(function(){pe.event.add(this,t,i,r,n)})}function T(e,t){return pe.nodeName(e,\"table\")&&pe.nodeName(11!==t.nodeType?t:t.firstChild,\"tr\")?e.getElementsByTagName(\"tbody\")[0]||e.appendChild(e.ownerDocument.createElement(\"tbody\")):e}function C(e){return e.type=(null!==pe.find.attr(e,\"type\"))+\"/\"+e.type,e}function E(e){var t=it.exec(e.type);return t?e.type=t[1]:e.removeAttribute(\"type\"),e}function N(e,t){if(1===t.nodeType&&pe.hasData(e)){var n,r,i,o=pe._data(e),a=pe._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;r<i;r++)pe.event.add(t,n,s[n][r])}a.data&&(a.data=pe.extend({},a.data))}}function k(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!fe.noCloneEvent&&t[pe.expando]){i=pe._data(t);for(r in i.events)pe.removeEvent(t,r,i.handle);t.removeAttribute(pe.expando)}\"script\"===n&&t.text!==e.text?(C(t).text=e.text,E(t)):\"object\"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),fe.html5Clone&&e.innerHTML&&!pe.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):\"input\"===n&&Be.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)}}function S(e,t,n,r){t=oe.apply([],t);var i,o,a,s,u,l,c=0,f=e.length,d=f-1,p=t[0],g=pe.isFunction(p);if(g||f>1&&\"string\"==typeof p&&!fe.checkClone&&rt.test(p))return e.each(function(i){var o=e.eq(i);g&&(t[0]=p.call(this,i,o.html())),S(o,t,n,r)});if(f&&(l=y(t,e[0].ownerDocument,!1,e,r),i=l.firstChild,1===l.childNodes.length&&(l=i),i||r)){for(s=pe.map(h(l,\"script\"),C),a=s.length;c<f;c++)o=l,c!==d&&(o=pe.clone(o,!0,!0),a&&pe.merge(s,h(o,\"script\"))),n.call(e[c],o,c);if(a)for(u=s[s.length-1].ownerDocument,pe.map(s,E),c=0;c<a;c++)o=s[c],Ie.test(o.type||\"\")&&!pe._data(o,\"globalEval\")&&pe.contains(u,o)&&(o.src?pe._evalUrl&&pe._evalUrl(o.src):pe.globalEval((o.text||o.textContent||o.innerHTML||\"\").replace(ot,\"\")));l=i=null}return e}function A(e,t,n){for(var r,i=t?pe.filter(t,e):e,o=0;null!=(r=i[o]);o++)n||1!==r.nodeType||pe.cleanData(h(r)),r.parentNode&&(n&&pe.contains(r.ownerDocument,r)&&g(h(r,\"script\")),r.parentNode.removeChild(r));return e}function D(e,t){var n=pe(t.createElement(e)).appendTo(t.body),r=pe.css(n[0],\"display\");return n.detach(),r}function j(e){var t=re,n=lt[e];return n||(n=D(e,t),\"none\"!==n&&n||(ut=(ut||pe(\"<iframe frameborder='0' width='0' height='0'/>\")).appendTo(t.documentElement),t=(ut[0].contentWindow||ut[0].contentDocument).document,t.write(),t.close(),n=D(e,t),ut.detach()),lt[e]=n),n}function L(e,t){return{get:function(){return e()?void delete this.get:(this.get=t).apply(this,arguments)}}}function H(e){if(e in Et)return e;for(var t=e.charAt(0).toUpperCase()+e.slice(1),n=Ct.length;n--;)if(e=Ct[n]+t,e in Et)return e}function q(e,t){for(var n,r,i,o=[],a=0,s=e.length;a<s;a++)r=e[a],r.style&&(o[a]=pe._data(r,\"olddisplay\"),n=r.style.display,t?(o[a]||\"none\"!==n||(r.style.display=\"\"),\"\"===r.style.display&&Re(r)&&(o[a]=pe._data(r,\"olddisplay\",j(r.nodeName)))):(i=Re(r),(n&&\"none\"!==n||!i)&&pe._data(r,\"olddisplay\",i?n:pe.css(r,\"display\"))));for(a=0;a<s;a++)r=e[a],r.style&&(t&&\"none\"!==r.style.display&&\"\"!==r.style.display||(r.style.display=t?o[a]||\"\":\"none\"));return e}function _(e,t,n){var r=bt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||\"px\"):t}function F(e,t,n,r,i){for(var o=n===(r?\"border\":\"content\")?4:\"width\"===t?1:0,a=0;o<4;o+=2)\"margin\"===n&&(a+=pe.css(e,n+Oe[o],!0,i)),r?(\"content\"===n&&(a-=pe.css(e,\"padding\"+Oe[o],!0,i)),\"margin\"!==n&&(a-=pe.css(e,\"border\"+Oe[o]+\"Width\",!0,i))):(a+=pe.css(e,\"padding\"+Oe[o],!0,i),\"padding\"!==n&&(a+=pe.css(e,\"border\"+Oe[o]+\"Width\",!0,i)));return a}function M(t,n,r){var i=!0,o=\"width\"===n?t.offsetWidth:t.offsetHeight,a=ht(t),s=fe.boxSizing&&\"border-box\"===pe.css(t,\"boxSizing\",!1,a);if(re.msFullscreenElement&&e.top!==e&&t.getClientRects().length&&(o=Math.round(100*t.getBoundingClientRect()[n])),o<=0||null==o){if(o=gt(t,n,a),(o<0||null==o)&&(o=t.style[n]),ft.test(o))return o;i=s&&(fe.boxSizingReliable()||o===t.style[n]),o=parseFloat(o)||0}return o+F(t,n,r||(s?\"border\":\"content\"),i,a)+\"px\"}function O(e,t,n,r,i){return new O.prototype.init(e,t,n,r,i)}function R(){return e.setTimeout(function(){Nt=void 0}),Nt=pe.now()}function P(e,t){var n,r={height:e},i=0;for(t=t?1:0;i<4;i+=2-t)n=Oe[i],r[\"margin\"+n]=r[\"padding\"+n]=e;return t&&(r.opacity=r.width=e),r}function B(e,t,n){for(var r,i=($.tweeners[t]||[]).concat($.tweeners[\"*\"]),o=0,a=i.length;o<a;o++)if(r=i[o].call(n,t,e))return r}function W(e,t,n){var r,i,o,a,s,u,l,c,f=this,d={},p=e.style,h=e.nodeType&&Re(e),g=pe._data(e,\"fxshow\");n.queue||(s=pe._queueHooks(e,\"fx\"),null==s.unqueued&&(s.unqueued=0,u=s.empty.fire,s.empty.fire=function(){s.unqueued||u()}),s.unqueued++,f.always(function(){f.always(function(){s.unqueued--,pe.queue(e,\"fx\").length||s.empty.fire()})})),1===e.nodeType&&(\"height\"in t||\"width\"in t)&&(n.overflow=[p.overflow,p.overflowX,p.overflowY],l=pe.css(e,\"display\"),c=\"none\"===l?pe._data(e,\"olddisplay\")||j(e.nodeName):l,\"inline\"===c&&\"none\"===pe.css(e,\"float\")&&(fe.inlineBlockNeedsLayout&&\"inline\"!==j(e.nodeName)?p.zoom=1:p.display=\"inline-block\")),n.overflow&&(p.overflow=\"hidden\",fe.shrinkWrapBlocks()||f.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],St.exec(i)){if(delete t[r],o=o||\"toggle\"===i,i===(h?\"hide\":\"show\")){if(\"show\"!==i||!g||void 0===g[r])continue;h=!0}d[r]=g&&g[r]||pe.style(e,r)}else l=void 0;if(pe.isEmptyObject(d))\"inline\"===(\"none\"===l?j(e.nodeName):l)&&(p.display=l);else{g?\"hidden\"in g&&(h=g.hidden):g=pe._data(e,\"fxshow\",{}),o&&(g.hidden=!h),h?pe(e).show():f.done(function(){pe(e).hide()}),f.done(function(){var t;pe._removeData(e,\"fxshow\");for(t in d)pe.style(e,t,d[t])});for(r in d)a=B(h?g[r]:0,r,f),r in g||(g[r]=a.start,h&&(a.end=a.start,a.start=\"width\"===r||\"height\"===r?1:0))}}function I(e,t){var n,r,i,o,a;for(n in e)if(r=pe.camelCase(n),i=t[r],o=e[n],pe.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),a=pe.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}function $(e,t,n){var r,i,o=0,a=$.prefilters.length,s=pe.Deferred().always(function(){delete u.elem}),u=function(){if(i)return!1;for(var t=Nt||R(),n=Math.max(0,l.startTime+l.duration-t),r=n/l.duration||0,o=1-r,a=0,u=l.tweens.length;a<u;a++)l.tweens[a].run(o);return s.notifyWith(e,[l,o,n]),o<1&&u?n:(s.resolveWith(e,[l]),!1)},l=s.promise({elem:e,props:pe.extend({},t),opts:pe.extend(!0,{specialEasing:{},easing:pe.easing._default},n),originalProperties:t,originalOptions:n,startTime:Nt||R(),duration:n.duration,tweens:[],createTween:function(t,n){var r=pe.Tween(e,l.opts,t,n,l.opts.specialEasing[t]||l.opts.easing);return l.tweens.push(r),r},stop:function(t){var n=0,r=t?l.tweens.length:0;if(i)return this;for(i=!0;n<r;n++)l.tweens[n].run(1);return t?(s.notifyWith(e,[l,1,0]),s.resolveWith(e,[l,t])):s.rejectWith(e,[l,t]),this}}),c=l.props;for(I(c,l.opts.specialEasing);o<a;o++)if(r=$.prefilters[o].call(l,e,c,l.opts))return pe.isFunction(r.stop)&&(pe._queueHooks(l.elem,l.opts.queue).stop=pe.proxy(r.stop,r)),r;return pe.map(c,B,l),pe.isFunction(l.opts.start)&&l.opts.start.call(e,l),pe.fx.timer(pe.extend(u,{elem:e,anim:l,queue:l.opts.queue})),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always)}function z(e){return pe.attr(e,\"class\")||\"\"}function X(e){return function(t,n){\"string\"!=typeof t&&(n=t,t=\"*\");var r,i=0,o=t.toLowerCase().match(De)||[];if(pe.isFunction(n))for(;r=o[i++];)\"+\"===r.charAt(0)?(r=r.slice(1)||\"*\",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function U(e,t,n,r){function i(s){var u;return o[s]=!0,pe.each(e[s]||[],function(e,s){var l=s(t,n,r);return\"string\"!=typeof l||a||o[l]?a?!(u=l):void 0:(t.dataTypes.unshift(l),i(l),!1)}),u}var o={},a=e===Qt;return i(t.dataTypes[0])||!o[\"*\"]&&i(\"*\")}function V(e,t){var n,r,i=pe.ajaxSettings.flatOptions||{};for(r in t)void 0!==t[r]&&((i[r]?e:n||(n={}))[r]=t[r]);return n&&pe.extend(!0,e,n),e}function Y(e,t,n){for(var r,i,o,a,s=e.contents,u=e.dataTypes;\"*\"===u[0];)u.shift(),void 0===i&&(i=e.mimeType||t.getResponseHeader(\"Content-Type\"));if(i)for(a in s)if(s[a]&&s[a].test(i)){u.unshift(a);break}if(u[0]in n)o=u[0];else{for(a in n){if(!u[0]||e.converters[a+\" \"+u[0]]){o=a;break}r||(r=a)}o=o||r}if(o)return o!==u[0]&&u.unshift(o),n[o]}function J(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];for(o=c.shift();o;)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if(\"*\"===o)o=u;else if(\"*\"!==u&&u!==o){if(a=l[u+\" \"+o]||l[\"* \"+o],!a)for(i in l)if(s=i.split(\" \"),s[1]===o&&(a=l[u+\" \"+s[0]]||l[\"* \"+s[0]])){a===!0?a=l[i]:l[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(f){return{state:\"parsererror\",error:a?f:\"No conversion from \"+u+\" to \"+o}}}return{state:\"success\",data:t}}function G(e){return e.style&&e.style.display||pe.css(e,\"display\")}function K(e){for(;e&&1===e.nodeType;){if(\"none\"===G(e)||\"hidden\"===e.type)return!0;e=e.parentNode}return!1}function Q(e,t,n,r){var i;if(pe.isArray(t))pe.each(t,function(t,i){n||rn.test(e)?r(e,i):Q(e+\"[\"+(\"object\"==typeof i&&null!=i?t:\"\")+\"]\",i,n,r)});else if(n||\"object\"!==pe.type(t))r(e,t);else for(i in t)Q(e+\"[\"+i+\"]\",t[i],n,r)}function Z(){try{return new e.XMLHttpRequest}catch(t){}}function ee(){try{return new e.ActiveXObject(\"Microsoft.XMLHTTP\")}catch(t){}}function te(e){return pe.isWindow(e)?e:9===e.nodeType&&(e.defaultView||e.parentWindow)}var ne=[],re=e.document,ie=ne.slice,oe=ne.concat,ae=ne.push,se=ne.indexOf,ue={},le=ue.toString,ce=ue.hasOwnProperty,fe={},de=\"1.12.3\",pe=function(e,t){return new pe.fn.init(e,t)},he=/^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g,ge=/^-ms-/,me=/-([\\da-z])/gi,ye=function(e,t){return t.toUpperCase()};pe.fn=pe.prototype={jquery:de,constructor:pe,selector:\"\",length:0,toArray:function(){return ie.call(this)},get:function(e){return null!=e?e<0?this[e+this.length]:this[e]:ie.call(this)},pushStack:function(e){var t=pe.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e){return pe.each(this,e)},map:function(e){return this.pushStack(pe.map(this,function(t,n){return e.call(t,n,t)}))},slice:function(){return this.pushStack(ie.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(n>=0&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:ae,sort:ne.sort,splice:ne.splice},pe.extend=pe.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for(\"boolean\"==typeof a&&(l=a,a=arguments[s]||{},s++),\"object\"==typeof a||pe.isFunction(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(i=arguments[s]))for(r in i)e=a[r],n=i[r],a!==n&&(l&&n&&(pe.isPlainObject(n)||(t=pe.isArray(n)))?(t?(t=!1,o=e&&pe.isArray(e)?e:[]):o=e&&pe.isPlainObject(e)?e:{},a[r]=pe.extend(l,o,n)):void 0!==n&&(a[r]=n));return a},pe.extend({expando:\"jQuery\"+(de+Math.random()).replace(/\\D/g,\"\"),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isFunction:function(e){return\"function\"===pe.type(e)},isArray:Array.isArray||function(e){return\"array\"===pe.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){var t=e&&e.toString();return!pe.isArray(e)&&t-parseFloat(t)+1>=0},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},isPlainObject:function(e){var t;if(!e||\"object\"!==pe.type(e)||e.nodeType||pe.isWindow(e))return!1;try{if(e.constructor&&!ce.call(e,\"constructor\")&&!ce.call(e.constructor.prototype,\"isPrototypeOf\"))return!1}catch(n){return!1}if(!fe.ownFirst)for(t in e)return ce.call(e,t);for(t in e);return void 0===t||ce.call(e,t)},type:function(e){return null==e?e+\"\":\"object\"==typeof e||\"function\"==typeof e?ue[le.call(e)]||\"object\":typeof e},globalEval:function(t){t&&pe.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(ge,\"ms-\").replace(me,ye)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t){var r,i=0;if(n(e))for(r=e.length;i<r&&t.call(e[i],i,e[i])!==!1;i++);else for(i in e)if(t.call(e[i],i,e[i])===!1)break;return e},trim:function(e){return null==e?\"\":(e+\"\").replace(he,\"\")},makeArray:function(e,t){var r=t||[];return null!=e&&(n(Object(e))?pe.merge(r,\"string\"==typeof e?[e]:e):ae.call(r,e)),r},inArray:function(e,t,n){var r;if(t){if(se)return se.call(t,e,n);for(r=t.length,n=n?n<0?Math.max(0,r+n):n:0;n<r;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;)e[i++]=t[r++];if(n!==n)for(;void 0!==t[r];)e[i++]=t[r++];return e.length=i,e},grep:function(e,t,n){for(var r,i=[],o=0,a=e.length,s=!n;o<a;o++)r=!t(e[o],o),r!==s&&i.push(e[o]);return i},map:function(e,t,r){var i,o,a=0,s=[];if(n(e))for(i=e.length;a<i;a++)o=t(e[a],a,r),null!=o&&s.push(o);else for(a in e)o=t(e[a],a,r),null!=o&&s.push(o);return oe.apply([],s)},guid:1,proxy:function(e,t){var n,r,i;if(\"string\"==typeof t&&(i=e[t],t=e,e=i),pe.isFunction(e))return n=ie.call(arguments,2),r=function(){return e.apply(t||this,n.concat(ie.call(arguments)))},r.guid=e.guid=e.guid||pe.guid++,r},now:function(){return+new Date},support:fe}),\"function\"==typeof Symbol&&(pe.fn[Symbol.iterator]=ne[Symbol.iterator]),pe.each(\"Boolean Number String Function Array Date RegExp Object Error Symbol\".split(\" \"),function(e,t){ue[\"[object \"+t+\"]\"]=t.toLowerCase()});var ve=function(e){function t(e,t,n,r){var i,o,a,s,u,l,f,p,h=t&&t.ownerDocument,g=t?t.nodeType:9;if(n=n||[],\"string\"!=typeof e||!e||1!==g&&9!==g&&11!==g)return n;if(!r&&((t?t.ownerDocument||t:B)!==H&&L(t),t=t||H,_)){if(11!==g&&(l=ye.exec(e)))if(i=l[1]){if(9===g){if(!(a=t.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(h&&(a=h.getElementById(i))&&R(t,a)&&a.id===i)return n.push(a),n}else{if(l[2])return Q.apply(n,t.getElementsByTagName(e)),n;if((i=l[3])&&w.getElementsByClassName&&t.getElementsByClassName)return Q.apply(n,t.getElementsByClassName(i)),n}if(w.qsa&&!X[e+\" \"]&&(!F||!F.test(e))){if(1!==g)h=t,p=e;else if(\"object\"!==t.nodeName.toLowerCase()){for((s=t.getAttribute(\"id\"))?s=s.replace(xe,\"\\\\$&\"):t.setAttribute(\"id\",s=P),f=N(e),o=f.length,u=de.test(s)?\"#\"+s:\"[id='\"+s+\"']\";o--;)f[o]=u+\" \"+d(f[o]);p=f.join(\",\"),h=ve.test(e)&&c(t.parentNode)||t}if(p)try{return Q.apply(n,h.querySelectorAll(p)),n}catch(m){}finally{s===P&&t.removeAttribute(\"id\")}}}return S(e.replace(se,\"$1\"),t,n,r)}function n(){function e(n,r){return t.push(n+\" \")>T.cacheLength&&delete e[t.shift()],e[n+\" \"]=r}var t=[];return e}function r(e){return e[P]=!0,e}function i(e){var t=H.createElement(\"div\");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function o(e,t){for(var n=e.split(\"|\"),r=n.length;r--;)T.attrHandle[n[r]]=t}function a(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||V)-(~e.sourceIndex||V);if(r)return r;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function s(e){return function(t){var n=t.nodeName.toLowerCase();return\"input\"===n&&t.type===e}}function u(e){return function(t){var n=t.nodeName.toLowerCase();return(\"input\"===n||\"button\"===n)&&t.type===e}}function l(e){return r(function(t){return t=+t,r(function(n,r){for(var i,o=e([],n.length,t),a=o.length;a--;)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}function c(e){return e&&\"undefined\"!=typeof e.getElementsByTagName&&e}function f(){}function d(e){for(var t=0,n=e.length,r=\"\";t<n;t++)r+=e[t].value;return r}function p(e,t,n){var r=t.dir,i=n&&\"parentNode\"===r,o=I++;return t.first?function(t,n,o){for(;t=t[r];)if(1===t.nodeType||i)return e(t,n,o)}:function(t,n,a){var s,u,l,c=[W,o];if(a){for(;t=t[r];)if((1===t.nodeType||i)&&e(t,n,a))return!0}else for(;t=t[r];)if(1===t.nodeType||i){if(l=t[P]||(t[P]={}),u=l[t.uniqueID]||(l[t.uniqueID]={}),(s=u[r])&&s[0]===W&&s[1]===o)return c[2]=s[2];if(u[r]=c,c[2]=e(t,n,a))return!0}}}function h(e){return e.length>1?function(t,n,r){for(var i=e.length;i--;)if(!e[i](t,n,r))return!1;return!0}:e[0]}function g(e,n,r){for(var i=0,o=n.length;i<o;i++)t(e,n[i],r);return r}function m(e,t,n,r,i){for(var o,a=[],s=0,u=e.length,l=null!=t;s<u;s++)(o=e[s])&&(n&&!n(o,r,i)||(a.push(o),l&&t.push(s)));return a}function y(e,t,n,i,o,a){return i&&!i[P]&&(i=y(i)),o&&!o[P]&&(o=y(o,a)),r(function(r,a,s,u){var l,c,f,d=[],p=[],h=a.length,y=r||g(t||\"*\",s.nodeType?[s]:s,[]),v=!e||!r&&t?y:m(y,d,e,s,u),x=n?o||(r?e:h||i)?[]:a:v;if(n&&n(v,x,s,u),i)for(l=m(x,p),i(l,[],s,u),c=l.length;c--;)(f=l[c])&&(x[p[c]]=!(v[p[c]]=f));if(r){if(o||e){if(o){for(l=[],c=x.length;c--;)(f=x[c])&&l.push(v[c]=f);o(null,x=[],l,u)}for(c=x.length;c--;)(f=x[c])&&(l=o?ee(r,f):d[c])>-1&&(r[l]=!(a[l]=f))}}else x=m(x===a?x.splice(h,x.length):x),o?o(null,a,x,u):Q.apply(a,x)})}function v(e){for(var t,n,r,i=e.length,o=T.relative[e[0].type],a=o||T.relative[\" \"],s=o?1:0,u=p(function(e){return e===t},a,!0),l=p(function(e){return ee(t,e)>-1},a,!0),c=[function(e,n,r){var i=!o&&(r||n!==A)||((t=n).nodeType?u(e,n,r):l(e,n,r));return t=null,i}];s<i;s++)if(n=T.relative[e[s].type])c=[p(h(c),n)];else{if(n=T.filter[e[s].type].apply(null,e[s].matches),n[P]){for(r=++s;r<i&&!T.relative[e[r].type];r++);return y(s>1&&h(c),s>1&&d(e.slice(0,s-1).concat({value:\" \"===e[s-2].type?\"*\":\"\"})).replace(se,\"$1\"),n,s<r&&v(e.slice(s,r)),r<i&&v(e=e.slice(r)),r<i&&d(e))}c.push(n)}return h(c)}function x(e,n){var i=n.length>0,o=e.length>0,a=function(r,a,s,u,l){var c,f,d,p=0,h=\"0\",g=r&&[],y=[],v=A,x=r||o&&T.find.TAG(\"*\",l),b=W+=null==v?1:Math.random()||.1,w=x.length;for(l&&(A=a===H||a||l);h!==w&&null!=(c=x[h]);h++){if(o&&c){for(f=0,a||c.ownerDocument===H||(L(c),s=!_);d=e[f++];)if(d(c,a||H,s)){u.push(c);break}l&&(W=b)}i&&((c=!d&&c)&&p--,r&&g.push(c))}if(p+=h,i&&h!==p){for(f=0;d=n[f++];)d(g,y,a,s);if(r){if(p>0)for(;h--;)g[h]||y[h]||(y[h]=G.call(u));y=m(y)}Q.apply(u,y),l&&!r&&y.length>0&&p+n.length>1&&t.uniqueSort(u)}return l&&(W=b,A=v),g};return i?r(a):a}var b,w,T,C,E,N,k,S,A,D,j,L,H,q,_,F,M,O,R,P=\"sizzle\"+1*new Date,B=e.document,W=0,I=0,$=n(),z=n(),X=n(),U=function(e,t){return e===t&&(j=!0),0},V=1<<31,Y={}.hasOwnProperty,J=[],G=J.pop,K=J.push,Q=J.push,Z=J.slice,ee=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},te=\"checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped\",ne=\"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",re=\"(?:\\\\\\\\.|[\\\\w-]|[^\\\\x00-\\\\xa0])+\",ie=\"\\\\[\"+ne+\"*(\"+re+\")(?:\"+ne+\"*([*^$|!~]?=)\"+ne+\"*(?:'((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\"|(\"+re+\"))|)\"+ne+\"*\\\\]\",oe=\":(\"+re+\")(?:\\\\((('((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\")|((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\"+ie+\")*)|.*)\\\\)|)\",ae=new RegExp(ne+\"+\",\"g\"),se=new RegExp(\"^\"+ne+\"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\"+ne+\"+$\",\"g\"),ue=new RegExp(\"^\"+ne+\"*,\"+ne+\"*\"),le=new RegExp(\"^\"+ne+\"*([>+~]|\"+ne+\")\"+ne+\"*\"),ce=new RegExp(\"=\"+ne+\"*([^\\\\]'\\\"]*?)\"+ne+\"*\\\\]\",\"g\"),fe=new RegExp(oe),de=new RegExp(\"^\"+re+\"$\"),pe={ID:new RegExp(\"^#(\"+re+\")\"),CLASS:new RegExp(\"^\\\\.(\"+re+\")\"),TAG:new RegExp(\"^(\"+re+\"|[*])\"),ATTR:new RegExp(\"^\"+ie),PSEUDO:new RegExp(\"^\"+oe),CHILD:new RegExp(\"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\"+ne+\"*(even|odd|(([+-]|)(\\\\d*)n|)\"+ne+\"*(?:([+-]|)\"+ne+\"*(\\\\d+)|))\"+ne+\"*\\\\)|)\",\"i\"),bool:new RegExp(\"^(?:\"+te+\")$\",\"i\"),needsContext:new RegExp(\"^\"+ne+\"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\"+ne+\"*((?:-\\\\d)?\\\\d*)\"+ne+\"*\\\\)|)(?=[^-]|$)\",\"i\")},he=/^(?:input|select|textarea|button)$/i,ge=/^h\\d$/i,me=/^[^{]+\\{\\s*\\[native \\w/,ye=/^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,ve=/[+~]/,xe=/'|\\\\/g,be=new RegExp(\"\\\\\\\\([\\\\da-f]{1,6}\"+ne+\"?|(\"+ne+\")|.)\",\"ig\"),we=function(e,t,n){var r=\"0x\"+t-65536;return r!==r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},Te=function(){L()};try{Q.apply(J=Z.call(B.childNodes),B.childNodes),J[B.childNodes.length].nodeType}catch(Ce){Q={apply:J.length?function(e,t){K.apply(e,Z.call(t))}:function(e,t){for(var n=e.length,r=0;e[n++]=t[r++];);e.length=n-1}}}w=t.support={},E=t.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return!!t&&\"HTML\"!==t.nodeName},L=t.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:B;return r!==H&&9===r.nodeType&&r.documentElement?(H=r,q=H.documentElement,_=!E(H),(n=H.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener(\"unload\",Te,!1):n.attachEvent&&n.attachEvent(\"onunload\",Te)),w.attributes=i(function(e){return e.className=\"i\",!e.getAttribute(\"className\")}),w.getElementsByTagName=i(function(e){return e.appendChild(H.createComment(\"\")),!e.getElementsByTagName(\"*\").length}),w.getElementsByClassName=me.test(H.getElementsByClassName),w.getById=i(function(e){return q.appendChild(e).id=P,!H.getElementsByName||!H.getElementsByName(P).length}),w.getById?(T.find.ID=function(e,t){if(\"undefined\"!=typeof t.getElementById&&_){var n=t.getElementById(e);return n?[n]:[]}},T.filter.ID=function(e){var t=e.replace(be,we);return function(e){return e.getAttribute(\"id\")===t}}):(delete T.find.ID,T.filter.ID=function(e){var t=e.replace(be,we);return function(e){var n=\"undefined\"!=typeof e.getAttributeNode&&e.getAttributeNode(\"id\");return n&&n.value===t}}),T.find.TAG=w.getElementsByTagName?function(e,t){return\"undefined\"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):w.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if(\"*\"===e){for(;n=o[i++];)1===n.nodeType&&r.push(n);return r}return o},T.find.CLASS=w.getElementsByClassName&&function(e,t){if(\"undefined\"!=typeof t.getElementsByClassName&&_)return t.getElementsByClassName(e)},M=[],F=[],(w.qsa=me.test(H.querySelectorAll))&&(i(function(e){q.appendChild(e).innerHTML=\"<a id='\"+P+\"'></a><select id='\"+P+\"-\\r\\\\' msallowcapture=''><option selected=''></option></select>\",e.querySelectorAll(\"[msallowcapture^='']\").length&&F.push(\"[*^$]=\"+ne+\"*(?:''|\\\"\\\")\"),e.querySelectorAll(\"[selected]\").length||F.push(\"\\\\[\"+ne+\"*(?:value|\"+te+\")\"),e.querySelectorAll(\"[id~=\"+P+\"-]\").length||F.push(\"~=\"),e.querySelectorAll(\":checked\").length||F.push(\":checked\"),e.querySelectorAll(\"a#\"+P+\"+*\").length||F.push(\".#.+[+~]\")}),i(function(e){var t=H.createElement(\"input\");t.setAttribute(\"type\",\"hidden\"),e.appendChild(t).setAttribute(\"name\",\"D\"),e.querySelectorAll(\"[name=d]\").length&&F.push(\"name\"+ne+\"*[*^$|!~]?=\"),e.querySelectorAll(\":enabled\").length||F.push(\":enabled\",\":disabled\"),e.querySelectorAll(\"*,:x\"),F.push(\",.*:\")})),(w.matchesSelector=me.test(O=q.matches||q.webkitMatchesSelector||q.mozMatchesSelector||q.oMatchesSelector||q.msMatchesSelector))&&i(function(e){w.disconnectedMatch=O.call(e,\"div\"),O.call(e,\"[s!='']:x\"),M.push(\"!=\",oe)}),F=F.length&&new RegExp(F.join(\"|\")),M=M.length&&new RegExp(M.join(\"|\")),t=me.test(q.compareDocumentPosition),R=t||me.test(q.contains)?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)for(;t=t.parentNode;)if(t===e)return!0;return!1},U=t?function(e,t){if(e===t)return j=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n?n:(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1,1&n||!w.sortDetached&&t.compareDocumentPosition(e)===n?e===H||e.ownerDocument===B&&R(B,e)?-1:t===H||t.ownerDocument===B&&R(B,t)?1:D?ee(D,e)-ee(D,t):0:4&n?-1:1)}:function(e,t){if(e===t)return j=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,s=[e],u=[t];if(!i||!o)return e===H?-1:t===H?1:i?-1:o?1:D?ee(D,e)-ee(D,t):0;if(i===o)return a(e,t);for(n=e;n=n.parentNode;)s.unshift(n);for(n=t;n=n.parentNode;)u.unshift(n);for(;s[r]===u[r];)r++;return r?a(s[r],u[r]):s[r]===B?-1:u[r]===B?1:0},H):H},t.matches=function(e,n){return t(e,null,null,n)},t.matchesSelector=function(e,n){if((e.ownerDocument||e)!==H&&L(e),n=n.replace(ce,\"='$1']\"),w.matchesSelector&&_&&!X[n+\" \"]&&(!M||!M.test(n))&&(!F||!F.test(n)))try{var r=O.call(e,n);if(r||w.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(i){}return t(n,H,null,[e]).length>0},t.contains=function(e,t){return(e.ownerDocument||e)!==H&&L(e),R(e,t)},t.attr=function(e,t){(e.ownerDocument||e)!==H&&L(e);var n=T.attrHandle[t.toLowerCase()],r=n&&Y.call(T.attrHandle,t.toLowerCase())?n(e,t,!_):void 0;return void 0!==r?r:w.attributes||!_?e.getAttribute(t):(r=e.getAttributeNode(t))&&r.specified?r.value:null},t.error=function(e){throw new Error(\"Syntax error, unrecognized expression: \"+e)},t.uniqueSort=function(e){var t,n=[],r=0,i=0;if(j=!w.detectDuplicates,D=!w.sortStable&&e.slice(0),e.sort(U),j){for(;t=e[i++];)t===e[i]&&(r=n.push(i));for(;r--;)e.splice(n[r],1)}return D=null,e},C=t.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+=C(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r++];)n+=C(t);return n},T=t.selectors={cacheLength:50,createPseudo:r,match:pe,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(be,we),e[3]=(e[3]||e[4]||e[5]||\"\").replace(be,we),\"~=\"===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]||t.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]&&t.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return pe.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||\"\":n&&fe.test(n)&&(t=N(n,!0))&&(t=n.indexOf(\")\",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(be,we).toLowerCase();return\"*\"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=$[e+\" \"];return t||(t=new RegExp(\"(^|\"+ne+\")\"+e+\"(\"+ne+\"|$)\"))&&$(e,function(e){return t.test(\"string\"==typeof e.className&&e.className||\"undefined\"!=typeof e.getAttribute&&e.getAttribute(\"class\")||\"\")})},ATTR:function(e,n,r){return function(i){var o=t.attr(i,e);return null==o?\"!=\"===n:!n||(o+=\"\",\"=\"===n?o===r:\"!=\"===n?o!==r:\"^=\"===n?r&&0===o.indexOf(r):\"*=\"===n?r&&o.indexOf(r)>-1:\"$=\"===n?r&&o.slice(-r.length)===r:\"~=\"===n?(\" \"+o.replace(ae,\" \")+\" \").indexOf(r)>-1:\"|=\"===n&&(o===r||o.slice(0,r.length+1)===r+\"-\"))}},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,u){var l,c,f,d,p,h,g=o!==a?\"nextSibling\":\"previousSibling\",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!u&&!s,x=!1;if(m){if(o){for(;g;){for(d=t;d=d[g];)if(s?d.nodeName.toLowerCase()===y:1===d.nodeType)return!1;h=g=\"only\"===e&&!h&&\"nextSibling\"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){for(d=m,f=d[P]||(d[P]={}),c=f[d.uniqueID]||(f[d.uniqueID]={}),\nl=c[e]||[],p=l[0]===W&&l[1],x=p&&l[2],d=p&&m.childNodes[p];d=++p&&d&&d[g]||(x=p=0)||h.pop();)if(1===d.nodeType&&++x&&d===t){c[e]=[W,p,x];break}}else if(v&&(d=t,f=d[P]||(d[P]={}),c=f[d.uniqueID]||(f[d.uniqueID]={}),l=c[e]||[],p=l[0]===W&&l[1],x=p),x===!1)for(;(d=++p&&d&&d[g]||(x=p=0)||h.pop())&&((s?d.nodeName.toLowerCase()!==y:1!==d.nodeType)||!++x||(v&&(f=d[P]||(d[P]={}),c=f[d.uniqueID]||(f[d.uniqueID]={}),c[e]=[W,x]),d!==t)););return x-=i,x===r||x%r===0&&x/r>=0}}},PSEUDO:function(e,n){var i,o=T.pseudos[e]||T.setFilters[e.toLowerCase()]||t.error(\"unsupported pseudo: \"+e);return o[P]?o(n):o.length>1?(i=[e,e,\"\",n],T.setFilters.hasOwnProperty(e.toLowerCase())?r(function(e,t){for(var r,i=o(e,n),a=i.length;a--;)r=ee(e,i[a]),e[r]=!(t[r]=i[a])}):function(e){return o(e,0,i)}):o}},pseudos:{not:r(function(e){var t=[],n=[],i=k(e.replace(se,\"$1\"));return i[P]?r(function(e,t,n,r){for(var o,a=i(e,null,r,[]),s=e.length;s--;)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,r,o){return t[0]=e,i(t,null,o,n),t[0]=null,!n.pop()}}),has:r(function(e){return function(n){return t(e,n).length>0}}),contains:r(function(e){return e=e.replace(be,we),function(t){return(t.textContent||t.innerText||C(t)).indexOf(e)>-1}}),lang:r(function(e){return de.test(e||\"\")||t.error(\"unsupported lang: \"+e),e=e.replace(be,we).toLowerCase(),function(t){var n;do if(n=_?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===q},focus:function(e){return e===H.activeElement&&(!H.hasFocus||H.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.nodeType<6)return!1;return!0},parent:function(e){return!T.pseudos.empty(e)},header:function(e){return ge.test(e.nodeName)},input:function(e){return he.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\"))||\"text\"===t.toLowerCase())},first:l(function(){return[0]}),last:l(function(e,t){return[t-1]}),eq:l(function(e,t,n){return[n<0?n+t:n]}),even:l(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:l(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:l(function(e,t,n){for(var r=n<0?n+t:n;--r>=0;)e.push(r);return e}),gt:l(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}},T.pseudos.nth=T.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})T.pseudos[b]=s(b);for(b in{submit:!0,reset:!0})T.pseudos[b]=u(b);return f.prototype=T.filters=T.pseudos,T.setFilters=new f,N=t.tokenize=function(e,n){var r,i,o,a,s,u,l,c=z[e+\" \"];if(c)return n?0:c.slice(0);for(s=e,u=[],l=T.preFilter;s;){r&&!(i=ue.exec(s))||(i&&(s=s.slice(i[0].length)||s),u.push(o=[])),r=!1,(i=le.exec(s))&&(r=i.shift(),o.push({value:r,type:i[0].replace(se,\" \")}),s=s.slice(r.length));for(a in T.filter)!(i=pe[a].exec(s))||l[a]&&!(i=l[a](i))||(r=i.shift(),o.push({value:r,type:a,matches:i}),s=s.slice(r.length));if(!r)break}return n?s.length:s?t.error(e):z(e,u).slice(0)},k=t.compile=function(e,t){var n,r=[],i=[],o=X[e+\" \"];if(!o){for(t||(t=N(e)),n=t.length;n--;)o=v(t[n]),o[P]?r.push(o):i.push(o);o=X(e,x(i,r)),o.selector=e}return o},S=t.select=function(e,t,n,r){var i,o,a,s,u,l=\"function\"==typeof e&&e,f=!r&&N(e=l.selector||e);if(n=n||[],1===f.length){if(o=f[0]=f[0].slice(0),o.length>2&&\"ID\"===(a=o[0]).type&&w.getById&&9===t.nodeType&&_&&T.relative[o[1].type]){if(t=(T.find.ID(a.matches[0].replace(be,we),t)||[])[0],!t)return n;l&&(t=t.parentNode),e=e.slice(o.shift().value.length)}for(i=pe.needsContext.test(e)?0:o.length;i--&&(a=o[i],!T.relative[s=a.type]);)if((u=T.find[s])&&(r=u(a.matches[0].replace(be,we),ve.test(o[0].type)&&c(t.parentNode)||t))){if(o.splice(i,1),e=r.length&&d(o),!e)return Q.apply(n,r),n;break}}return(l||k(e,f))(r,t,!_,n,!t||ve.test(e)&&c(t.parentNode)||t),n},w.sortStable=P.split(\"\").sort(U).join(\"\")===P,w.detectDuplicates=!!j,L(),w.sortDetached=i(function(e){return 1&e.compareDocumentPosition(H.createElement(\"div\"))}),i(function(e){return e.innerHTML=\"<a href='#'></a>\",\"#\"===e.firstChild.getAttribute(\"href\")})||o(\"type|href|height|width\",function(e,t,n){if(!n)return e.getAttribute(t,\"type\"===t.toLowerCase()?1:2)}),w.attributes&&i(function(e){return e.innerHTML=\"<input/>\",e.firstChild.setAttribute(\"value\",\"\"),\"\"===e.firstChild.getAttribute(\"value\")})||o(\"value\",function(e,t,n){if(!n&&\"input\"===e.nodeName.toLowerCase())return e.defaultValue}),i(function(e){return null==e.getAttribute(\"disabled\")})||o(te,function(e,t,n){var r;if(!n)return e[t]===!0?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),t}(e);pe.find=ve,pe.expr=ve.selectors,pe.expr[\":\"]=pe.expr.pseudos,pe.uniqueSort=pe.unique=ve.uniqueSort,pe.text=ve.getText,pe.isXMLDoc=ve.isXML,pe.contains=ve.contains;var xe=function(e,t,n){for(var r=[],i=void 0!==n;(e=e[t])&&9!==e.nodeType;)if(1===e.nodeType){if(i&&pe(e).is(n))break;r.push(e)}return r},be=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},we=pe.expr.match.needsContext,Te=/^<([\\w-]+)\\s*\\/?>(?:<\\/\\1>|)$/,Ce=/^.[^:#\\[\\.,]*$/;pe.filter=function(e,t,n){var r=t[0];return n&&(e=\":not(\"+e+\")\"),1===t.length&&1===r.nodeType?pe.find.matchesSelector(r,e)?[r]:[]:pe.find.matches(e,pe.grep(t,function(e){return 1===e.nodeType}))},pe.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if(\"string\"!=typeof e)return this.pushStack(pe(e).filter(function(){for(t=0;t<i;t++)if(pe.contains(r[t],this))return!0}));for(t=0;t<i;t++)pe.find(e,r[t],n);return n=this.pushStack(i>1?pe.unique(n):n),n.selector=this.selector?this.selector+\" \"+e:e,n},filter:function(e){return this.pushStack(r(this,e||[],!1))},not:function(e){return this.pushStack(r(this,e||[],!0))},is:function(e){return!!r(this,\"string\"==typeof e&&we.test(e)?pe(e):e||[],!1).length}});var Ee,Ne=/^(?:\\s*(<[\\w\\W]+>)[^>]*|#([\\w-]*))$/,ke=pe.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||Ee,\"string\"==typeof e){if(r=\"<\"===e.charAt(0)&&\">\"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:Ne.exec(e),!r||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof pe?t[0]:t,pe.merge(this,pe.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:re,!0)),Te.test(r[1])&&pe.isPlainObject(t))for(r in t)pe.isFunction(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}if(i=re.getElementById(r[2]),i&&i.parentNode){if(i.id!==r[2])return Ee.find(e);this.length=1,this[0]=i}return this.context=re,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):pe.isFunction(e)?\"undefined\"!=typeof n.ready?n.ready(e):e(pe):(void 0!==e.selector&&(this.selector=e.selector,this.context=e.context),pe.makeArray(e,this))};ke.prototype=pe.fn,Ee=pe(re);var Se=/^(?:parents|prev(?:Until|All))/,Ae={children:!0,contents:!0,next:!0,prev:!0};pe.fn.extend({has:function(e){var t,n=pe(e,this),r=n.length;return this.filter(function(){for(t=0;t<r;t++)if(pe.contains(this,n[t]))return!0})},closest:function(e,t){for(var n,r=0,i=this.length,o=[],a=we.test(e)||\"string\"!=typeof e?pe(e,t||this.context):0;r<i;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(n.nodeType<11&&(a?a.index(n)>-1:1===n.nodeType&&pe.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(o.length>1?pe.uniqueSort(o):o)},index:function(e){return e?\"string\"==typeof e?pe.inArray(this[0],pe(e)):pe.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(pe.uniqueSort(pe.merge(this.get(),pe(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),pe.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return xe(e,\"parentNode\")},parentsUntil:function(e,t,n){return xe(e,\"parentNode\",n)},next:function(e){return i(e,\"nextSibling\")},prev:function(e){return i(e,\"previousSibling\")},nextAll:function(e){return xe(e,\"nextSibling\")},prevAll:function(e){return xe(e,\"previousSibling\")},nextUntil:function(e,t,n){return xe(e,\"nextSibling\",n)},prevUntil:function(e,t,n){return xe(e,\"previousSibling\",n)},siblings:function(e){return be((e.parentNode||{}).firstChild,e)},children:function(e){return be(e.firstChild)},contents:function(e){return pe.nodeName(e,\"iframe\")?e.contentDocument||e.contentWindow.document:pe.merge([],e.childNodes)}},function(e,t){pe.fn[e]=function(n,r){var i=pe.map(this,t,n);return\"Until\"!==e.slice(-5)&&(r=n),r&&\"string\"==typeof r&&(i=pe.filter(r,i)),this.length>1&&(Ae[e]||(i=pe.uniqueSort(i)),Se.test(e)&&(i=i.reverse())),this.pushStack(i)}});var De=/\\S+/g;pe.Callbacks=function(e){e=\"string\"==typeof e?o(e):pe.extend({},e);var t,n,r,i,a=[],s=[],u=-1,l=function(){for(i=e.once,r=t=!0;s.length;u=-1)for(n=s.shift();++u<a.length;)a[u].apply(n[0],n[1])===!1&&e.stopOnFalse&&(u=a.length,n=!1);e.memory||(n=!1),t=!1,i&&(a=n?[]:\"\")},c={add:function(){return a&&(n&&!t&&(u=a.length-1,s.push(n)),function r(t){pe.each(t,function(t,n){pe.isFunction(n)?e.unique&&c.has(n)||a.push(n):n&&n.length&&\"string\"!==pe.type(n)&&r(n)})}(arguments),n&&!t&&l()),this},remove:function(){return pe.each(arguments,function(e,t){for(var n;(n=pe.inArray(t,a,n))>-1;)a.splice(n,1),n<=u&&u--}),this},has:function(e){return e?pe.inArray(e,a)>-1:a.length>0},empty:function(){return a&&(a=[]),this},disable:function(){return i=s=[],a=n=\"\",this},disabled:function(){return!a},lock:function(){return i=!0,n||c.disable(),this},locked:function(){return!!i},fireWith:function(e,n){return i||(n=n||[],n=[e,n.slice?n.slice():n],s.push(n),t||l()),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!r}};return c},pe.extend({Deferred:function(e){var t=[[\"resolve\",\"done\",pe.Callbacks(\"once memory\"),\"resolved\"],[\"reject\",\"fail\",pe.Callbacks(\"once memory\"),\"rejected\"],[\"notify\",\"progress\",pe.Callbacks(\"memory\")]],n=\"pending\",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return pe.Deferred(function(n){pe.each(t,function(t,o){var a=pe.isFunction(e[t])&&e[t];i[o[1]](function(){var e=a&&a.apply(this,arguments);e&&pe.isFunction(e.promise)?e.promise().progress(n.notify).done(n.resolve).fail(n.reject):n[o[0]+\"With\"](this===r?n.promise():this,a?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?pe.extend(e,r):r}},i={};return r.pipe=r.then,pe.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,n,r,i=0,o=ie.call(arguments),a=o.length,s=1!==a||e&&pe.isFunction(e.promise)?a:0,u=1===s?e:pe.Deferred(),l=function(e,n,r){return function(i){n[e]=this,r[e]=arguments.length>1?ie.call(arguments):i,r===t?u.notifyWith(n,r):--s||u.resolveWith(n,r)}};if(a>1)for(t=new Array(a),n=new Array(a),r=new Array(a);i<a;i++)o[i]&&pe.isFunction(o[i].promise)?o[i].promise().progress(l(i,n,t)).done(l(i,r,o)).fail(u.reject):--s;return s||u.resolveWith(r,o),u.promise()}});var je;pe.fn.ready=function(e){return pe.ready.promise().done(e),this},pe.extend({isReady:!1,readyWait:1,holdReady:function(e){e?pe.readyWait++:pe.ready(!0)},ready:function(e){(e===!0?--pe.readyWait:pe.isReady)||(pe.isReady=!0,e!==!0&&--pe.readyWait>0||(je.resolveWith(re,[pe]),pe.fn.triggerHandler&&(pe(re).triggerHandler(\"ready\"),pe(re).off(\"ready\"))))}}),pe.ready.promise=function(t){if(!je)if(je=pe.Deferred(),\"complete\"===re.readyState||\"loading\"!==re.readyState&&!re.documentElement.doScroll)e.setTimeout(pe.ready);else if(re.addEventListener)re.addEventListener(\"DOMContentLoaded\",s),e.addEventListener(\"load\",s);else{re.attachEvent(\"onreadystatechange\",s),e.attachEvent(\"onload\",s);var n=!1;try{n=null==e.frameElement&&re.documentElement}catch(r){}n&&n.doScroll&&!function i(){if(!pe.isReady){try{n.doScroll(\"left\")}catch(t){return e.setTimeout(i,50)}a(),pe.ready()}}()}return je.promise(t)},pe.ready.promise();var Le;for(Le in pe(fe))break;fe.ownFirst=\"0\"===Le,fe.inlineBlockNeedsLayout=!1,pe(function(){var e,t,n,r;n=re.getElementsByTagName(\"body\")[0],n&&n.style&&(t=re.createElement(\"div\"),r=re.createElement(\"div\"),r.style.cssText=\"position:absolute;border:0;width:0;height:0;top:0;left:-9999px\",n.appendChild(r).appendChild(t),\"undefined\"!=typeof t.style.zoom&&(t.style.cssText=\"display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1\",fe.inlineBlockNeedsLayout=e=3===t.offsetWidth,e&&(n.style.zoom=1)),n.removeChild(r))}),function(){var e=re.createElement(\"div\");fe.deleteExpando=!0;try{delete e.test}catch(t){fe.deleteExpando=!1}e=null}();var He=function(e){var t=pe.noData[(e.nodeName+\" \").toLowerCase()],n=+e.nodeType||1;return(1===n||9===n)&&(!t||t!==!0&&e.getAttribute(\"classid\")===t)},qe=/^(?:\\{[\\w\\W]*\\}|\\[[\\w\\W]*\\])$/,_e=/([A-Z])/g;pe.extend({cache:{},noData:{\"applet \":!0,\"embed \":!0,\"object \":\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"},hasData:function(e){return e=e.nodeType?pe.cache[e[pe.expando]]:e[pe.expando],!!e&&!l(e)},data:function(e,t,n){return c(e,t,n)},removeData:function(e,t){return f(e,t)},_data:function(e,t,n){return c(e,t,n,!0)},_removeData:function(e,t){return f(e,t,!0)}}),pe.fn.extend({data:function(e,t){var n,r,i,o=this[0],a=o&&o.attributes;if(void 0===e){if(this.length&&(i=pe.data(o),1===o.nodeType&&!pe._data(o,\"parsedAttrs\"))){for(n=a.length;n--;)a[n]&&(r=a[n].name,0===r.indexOf(\"data-\")&&(r=pe.camelCase(r.slice(5)),u(o,r,i[r])));pe._data(o,\"parsedAttrs\",!0)}return i}return\"object\"==typeof e?this.each(function(){pe.data(this,e)}):arguments.length>1?this.each(function(){pe.data(this,e,t)}):o?u(o,e,pe.data(o,e)):void 0},removeData:function(e){return this.each(function(){pe.removeData(this,e)})}}),pe.extend({queue:function(e,t,n){var r;if(e)return t=(t||\"fx\")+\"queue\",r=pe._data(e,t),n&&(!r||pe.isArray(n)?r=pe._data(e,t,pe.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||\"fx\";var n=pe.queue(e,t),r=n.length,i=n.shift(),o=pe._queueHooks(e,t),a=function(){pe.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 pe._data(e,n)||pe._data(e,n,{empty:pe.Callbacks(\"once memory\").add(function(){pe._removeData(e,t+\"queue\"),pe._removeData(e,n)})})}}),pe.fn.extend({queue:function(e,t){var n=2;return\"string\"!=typeof e&&(t=e,e=\"fx\",n--),arguments.length<n?pe.queue(this[0],e):void 0===t?this:this.each(function(){var n=pe.queue(this,e,t);pe._queueHooks(this,e),\"fx\"===e&&\"inprogress\"!==n[0]&&pe.dequeue(this,e)})},dequeue:function(e){return this.each(function(){pe.dequeue(this,e)})},clearQueue:function(e){return this.queue(e||\"fx\",[])},promise:function(e,t){var n,r=1,i=pe.Deferred(),o=this,a=this.length,s=function(){--r||i.resolveWith(o,[o])};for(\"string\"!=typeof e&&(t=e,e=void 0),e=e||\"fx\";a--;)n=pe._data(o[a],e+\"queueHooks\"),n&&n.empty&&(r++,n.empty.add(s));return s(),i.promise(t)}}),function(){var e;fe.shrinkWrapBlocks=function(){if(null!=e)return e;e=!1;var t,n,r;return n=re.getElementsByTagName(\"body\")[0],n&&n.style?(t=re.createElement(\"div\"),r=re.createElement(\"div\"),r.style.cssText=\"position:absolute;border:0;width:0;height:0;top:0;left:-9999px\",n.appendChild(r).appendChild(t),\"undefined\"!=typeof t.style.zoom&&(t.style.cssText=\"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:1px;width:1px;zoom:1\",t.appendChild(re.createElement(\"div\")).style.width=\"5px\",e=3!==t.offsetWidth),n.removeChild(r),e):void 0}}();var Fe=/[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/.source,Me=new RegExp(\"^(?:([+-])=|)(\"+Fe+\")([a-z%]*)$\",\"i\"),Oe=[\"Top\",\"Right\",\"Bottom\",\"Left\"],Re=function(e,t){return e=t||e,\"none\"===pe.css(e,\"display\")||!pe.contains(e.ownerDocument,e)},Pe=function(e,t,n,r,i,o,a){var s=0,u=e.length,l=null==n;if(\"object\"===pe.type(n)){i=!0;for(s in n)Pe(e,t,s,n[s],!0,o,a)}else if(void 0!==r&&(i=!0,pe.isFunction(r)||(a=!0),l&&(a?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(pe(e),n)})),t))for(;s<u;s++)t(e[s],n,a?r:r.call(e[s],s,t(e[s],n)));return i?e:l?t.call(e):u?t(e[0],n):o},Be=/^(?:checkbox|radio)$/i,We=/<([\\w:-]+)/,Ie=/^$|\\/(?:java|ecma)script/i,$e=/^\\s+/,ze=\"abbr|article|aside|audio|bdi|canvas|data|datalist|details|dialog|figcaption|figure|footer|header|hgroup|main|mark|meter|nav|output|picture|progress|section|summary|template|time|video\";!function(){var e=re.createElement(\"div\"),t=re.createDocumentFragment(),n=re.createElement(\"input\");e.innerHTML=\"  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>\",fe.leadingWhitespace=3===e.firstChild.nodeType,fe.tbody=!e.getElementsByTagName(\"tbody\").length,fe.htmlSerialize=!!e.getElementsByTagName(\"link\").length,fe.html5Clone=\"<:nav></:nav>\"!==re.createElement(\"nav\").cloneNode(!0).outerHTML,n.type=\"checkbox\",n.checked=!0,t.appendChild(n),fe.appendChecked=n.checked,e.innerHTML=\"<textarea>x</textarea>\",fe.noCloneChecked=!!e.cloneNode(!0).lastChild.defaultValue,t.appendChild(e),n=re.createElement(\"input\"),n.setAttribute(\"type\",\"radio\"),n.setAttribute(\"checked\",\"checked\"),n.setAttribute(\"name\",\"t\"),e.appendChild(n),fe.checkClone=e.cloneNode(!0).cloneNode(!0).lastChild.checked,fe.noCloneEvent=!!e.addEventListener,e[pe.expando]=1,fe.attributes=!e.getAttribute(pe.expando)}();var Xe={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:fe.htmlSerialize?[0,\"\",\"\"]:[1,\"X<div>\",\"</div>\"]};Xe.optgroup=Xe.option,Xe.tbody=Xe.tfoot=Xe.colgroup=Xe.caption=Xe.thead,Xe.th=Xe.td;var Ue=/<|&#?\\w+;/,Ve=/<tbody/i;!function(){var t,n,r=re.createElement(\"div\");for(t in{submit:!0,change:!0,focusin:!0})n=\"on\"+t,(fe[t]=n in e)||(r.setAttribute(n,\"t\"),fe[t]=r.attributes[n].expando===!1);r=null}();var Ye=/^(?:input|select|textarea)$/i,Je=/^key/,Ge=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ke=/^(?:focusinfocus|focusoutblur)$/,Qe=/^([^.]*)(?:\\.(.+)|)/;pe.event={global:{},add:function(e,t,n,r,i){var o,a,s,u,l,c,f,d,p,h,g,m=pe._data(e);if(m){for(n.handler&&(u=n,n=u.handler,i=u.selector),n.guid||(n.guid=pe.guid++),(a=m.events)||(a=m.events={}),(c=m.handle)||(c=m.handle=function(e){return\"undefined\"==typeof pe||e&&pe.event.triggered===e.type?void 0:pe.event.dispatch.apply(c.elem,arguments)},c.elem=e),t=(t||\"\").match(De)||[\"\"],s=t.length;s--;)o=Qe.exec(t[s])||[],p=g=o[1],h=(o[2]||\"\").split(\".\").sort(),p&&(l=pe.event.special[p]||{},p=(i?l.delegateType:l.bindType)||p,l=pe.event.special[p]||{},f=pe.extend({type:p,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&pe.expr.match.needsContext.test(i),namespace:h.join(\".\")},u),(d=a[p])||(d=a[p]=[],d.delegateCount=0,l.setup&&l.setup.call(e,r,h,c)!==!1||(e.addEventListener?e.addEventListener(p,c,!1):e.attachEvent&&e.attachEvent(\"on\"+p,c))),l.add&&(l.add.call(e,f),f.handler.guid||(f.handler.guid=n.guid)),i?d.splice(d.delegateCount++,0,f):d.push(f),pe.event.global[p]=!0);e=null}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,d,p,h,g,m=pe.hasData(e)&&pe._data(e);if(m&&(c=m.events)){for(t=(t||\"\").match(De)||[\"\"],l=t.length;l--;)if(s=Qe.exec(t[l])||[],p=g=s[1],h=(s[2]||\"\").split(\".\").sort(),p){for(f=pe.event.special[p]||{},p=(r?f.delegateType:f.bindType)||p,d=c[p]||[],s=s[2]&&new RegExp(\"(^|\\\\.)\"+h.join(\"\\\\.(?:.*\\\\.|)\")+\"(\\\\.|$)\"),u=o=d.length;o--;)a=d[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&(\"**\"!==r||!a.selector)||(d.splice(o,1),a.selector&&d.delegateCount--,f.remove&&f.remove.call(e,a));u&&!d.length&&(f.teardown&&f.teardown.call(e,h,m.handle)!==!1||pe.removeEvent(e,p,m.handle),delete c[p])}else for(p in c)pe.event.remove(e,p+t[l],n,r,!0);pe.isEmptyObject(c)&&(delete m.handle,pe._removeData(e,\"events\"))}},trigger:function(t,n,r,i){var o,a,s,u,l,c,f,d=[r||re],p=ce.call(t,\"type\")?t.type:t,h=ce.call(t,\"namespace\")?t.namespace.split(\".\"):[];if(s=c=r=r||re,3!==r.nodeType&&8!==r.nodeType&&!Ke.test(p+pe.event.triggered)&&(p.indexOf(\".\")>-1&&(h=p.split(\".\"),p=h.shift(),h.sort()),a=p.indexOf(\":\")<0&&\"on\"+p,t=t[pe.expando]?t:new pe.Event(p,\"object\"==typeof t&&t),t.isTrigger=i?2:3,t.namespace=h.join(\".\"),t.rnamespace=t.namespace?new RegExp(\"(^|\\\\.)\"+h.join(\"\\\\.(?:.*\\\\.|)\")+\"(\\\\.|$)\"):null,t.result=void 0,t.target||(t.target=r),n=null==n?[t]:pe.makeArray(n,[t]),l=pe.event.special[p]||{},i||!l.trigger||l.trigger.apply(r,n)!==!1)){if(!i&&!l.noBubble&&!pe.isWindow(r)){for(u=l.delegateType||p,Ke.test(u+p)||(s=s.parentNode);s;s=s.parentNode)d.push(s),c=s;c===(r.ownerDocument||re)&&d.push(c.defaultView||c.parentWindow||e)}for(f=0;(s=d[f++])&&!t.isPropagationStopped();)t.type=f>1?u:l.bindType||p,o=(pe._data(s,\"events\")||{})[t.type]&&pe._data(s,\"handle\"),o&&o.apply(s,n),o=a&&s[a],o&&o.apply&&He(s)&&(t.result=o.apply(s,n),t.result===!1&&t.preventDefault());if(t.type=p,!i&&!t.isDefaultPrevented()&&(!l._default||l._default.apply(d.pop(),n)===!1)&&He(r)&&a&&r[p]&&!pe.isWindow(r)){c=r[a],c&&(r[a]=null),pe.event.triggered=p;try{r[p]()}catch(g){}pe.event.triggered=void 0,c&&(r[a]=c)}return t.result}},dispatch:function(e){e=pe.event.fix(e);var t,n,r,i,o,a=[],s=ie.call(arguments),u=(pe._data(this,\"events\")||{})[e.type]||[],l=pe.event.special[e.type]||{};if(s[0]=e,e.delegateTarget=this,!l.preDispatch||l.preDispatch.call(this,e)!==!1){for(a=pe.event.handlers.call(this,e,u),t=0;(i=a[t++])&&!e.isPropagationStopped();)for(e.currentTarget=i.elem,n=0;(o=i.handlers[n++])&&!e.isImmediatePropagationStopped();)e.rnamespace&&!e.rnamespace.test(o.namespace)||(e.handleObj=o,e.data=o.data,r=((pe.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,s),void 0!==r&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()));return l.postDispatch&&l.postDispatch.call(this,e),e.result}},handlers:function(e,t){var n,r,i,o,a=[],s=t.delegateCount,u=e.target;if(s&&u.nodeType&&(\"click\"!==e.type||isNaN(e.button)||e.button<1))for(;u!=this;u=u.parentNode||this)if(1===u.nodeType&&(u.disabled!==!0||\"click\"!==e.type)){for(r=[],n=0;n<s;n++)o=t[n],i=o.selector+\" \",void 0===r[i]&&(r[i]=o.needsContext?pe(i,this).index(u)>-1:pe.find(i,this,null,[u]).length),r[i]&&r.push(o);r.length&&a.push({elem:u,handlers:r})}return s<t.length&&a.push({elem:this,handlers:t.slice(s)}),a},fix:function(e){if(e[pe.expando])return e;var t,n,r,i=e.type,o=e,a=this.fixHooks[i];for(a||(this.fixHooks[i]=a=Ge.test(i)?this.mouseHooks:Je.test(i)?this.keyHooks:{}),r=a.props?this.props.concat(a.props):this.props,e=new pe.Event(o),t=r.length;t--;)n=r[t],e[n]=o[n];return e.target||(e.target=o.srcElement||re),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,a.filter?a.filter(e,o):e},props:\"altKey bubbles cancelable ctrlKey currentTarget detail 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,t){var n,r,i,o=t.button,a=t.fromElement;return null==e.pageX&&null!=t.clientX&&(r=e.target.ownerDocument||re,i=r.documentElement,n=r.body,e.pageX=t.clientX+(i&&i.scrollLeft||n&&n.scrollLeft||0)-(i&&i.clientLeft||n&&n.clientLeft||0),e.pageY=t.clientY+(i&&i.scrollTop||n&&n.scrollTop||0)-(i&&i.clientTop||n&&n.clientTop||0)),!e.relatedTarget&&a&&(e.relatedTarget=a===e.target?t.toElement:a),e.which||void 0===o||(e.which=1&o?1:2&o?3:4&o?2:0),e}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==b()&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:\"focusin\"},blur:{trigger:function(){if(this===b()&&this.blur)return this.blur(),!1},delegateType:\"focusout\"},click:{trigger:function(){if(pe.nodeName(this,\"input\")&&\"checkbox\"===this.type&&this.click)return this.click(),!1},_default:function(e){return pe.nodeName(e.target,\"a\")}},beforeunload:{postDispatch:function(e){void 0!==e.result&&e.originalEvent&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n){var r=pe.extend(new pe.Event,n,{type:e,isSimulated:!0});pe.event.trigger(r,null,t),r.isDefaultPrevented()&&n.preventDefault()}},pe.removeEvent=re.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n)}:function(e,t,n){var r=\"on\"+t;e.detachEvent&&(\"undefined\"==typeof e[r]&&(e[r]=null),e.detachEvent(r,n))},pe.Event=function(e,t){return this instanceof pe.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||void 0===e.defaultPrevented&&e.returnValue===!1?v:x):this.type=e,t&&pe.extend(this,t),this.timeStamp=e&&e.timeStamp||pe.now(),void(this[pe.expando]=!0)):new pe.Event(e,t)},pe.Event.prototype={constructor:pe.Event,isDefaultPrevented:x,isPropagationStopped:x,isImmediatePropagationStopped:x,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=v,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=v,e&&!this.isSimulated&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){var e=this.originalEvent;this.isImmediatePropagationStopped=v,e&&e.stopImmediatePropagation&&e.stopImmediatePropagation(),this.stopPropagation()}},pe.each({mouseenter:\"mouseover\",mouseleave:\"mouseout\",pointerenter:\"pointerover\",pointerleave:\"pointerout\"},function(e,t){pe.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return i&&(i===r||pe.contains(r,i))||(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),fe.submit||(pe.event.special.submit={setup:function(){return!pe.nodeName(this,\"form\")&&void pe.event.add(this,\"click._submit keypress._submit\",function(e){var t=e.target,n=pe.nodeName(t,\"input\")||pe.nodeName(t,\"button\")?pe.prop(t,\"form\"):void 0;n&&!pe._data(n,\"submit\")&&(pe.event.add(n,\"submit._submit\",function(e){e._submitBubble=!0}),pe._data(n,\"submit\",!0))})},postDispatch:function(e){e._submitBubble&&(delete e._submitBubble,this.parentNode&&!e.isTrigger&&pe.event.simulate(\"submit\",this.parentNode,e))},teardown:function(){return!pe.nodeName(this,\"form\")&&void pe.event.remove(this,\"._submit\")}}),fe.change||(pe.event.special.change={setup:function(){return Ye.test(this.nodeName)?(\"checkbox\"!==this.type&&\"radio\"!==this.type||(pe.event.add(this,\"propertychange._change\",function(e){\"checked\"===e.originalEvent.propertyName&&(this._justChanged=!0)}),pe.event.add(this,\"click._change\",function(e){this._justChanged&&!e.isTrigger&&(this._justChanged=!1),pe.event.simulate(\"change\",this,e)})),!1):void pe.event.add(this,\"beforeactivate._change\",function(e){var t=e.target;Ye.test(t.nodeName)&&!pe._data(t,\"change\")&&(pe.event.add(t,\"change._change\",function(e){!this.parentNode||e.isSimulated||e.isTrigger||pe.event.simulate(\"change\",this.parentNode,e)}),pe._data(t,\"change\",!0))})},handle:function(e){var t=e.target;if(this!==t||e.isSimulated||e.isTrigger||\"radio\"!==t.type&&\"checkbox\"!==t.type)return e.handleObj.handler.apply(this,arguments)},teardown:function(){return pe.event.remove(this,\"._change\"),!Ye.test(this.nodeName)}}),fe.focusin||pe.each({focus:\"focusin\",blur:\"focusout\"},function(e,t){var n=function(e){pe.event.simulate(t,e.target,pe.event.fix(e))};pe.event.special[t]={setup:function(){var r=this.ownerDocument||this,i=pe._data(r,t);i||r.addEventListener(e,n,!0),pe._data(r,t,(i||0)+1)},teardown:function(){var r=this.ownerDocument||this,i=pe._data(r,t)-1;i?pe._data(r,t,i):(r.removeEventListener(e,n,!0),pe._removeData(r,t))}}}),pe.fn.extend({on:function(e,t,n,r){return w(this,e,t,n,r)},one:function(e,t,n,r){return w(this,e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,pe(e.delegateTarget).off(r.namespace?r.origType+\".\"+r.namespace:r.origType,r.selector,r.handler),this;if(\"object\"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return t!==!1&&\"function\"!=typeof t||(n=t,t=void 0),n===!1&&(n=x),this.each(function(){pe.event.remove(this,e,n,t)})},trigger:function(e,t){return this.each(function(){pe.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return pe.event.trigger(e,t,n,!0)}});var Ze=/ jQuery\\d+=\"(?:null|\\d+)\"/g,et=new RegExp(\"<(?:\"+ze+\")[\\\\s/>]\",\"i\"),tt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:-]+)[^>]*)\\/>/gi,nt=/<script|<style|<link/i,rt=/checked\\s*(?:[^=]|=\\s*.checked.)/i,it=/^true\\/(.*)/,ot=/^\\s*<!(?:\\[CDATA\\[|--)|(?:\\]\\]|--)>\\s*$/g,at=p(re),st=at.appendChild(re.createElement(\"div\"));pe.extend({htmlPrefilter:function(e){return e.replace(tt,\"<$1></$2>\")},clone:function(e,t,n){var r,i,o,a,s,u=pe.contains(e.ownerDocument,e);if(fe.html5Clone||pe.isXMLDoc(e)||!et.test(\"<\"+e.nodeName+\">\")?o=e.cloneNode(!0):(st.innerHTML=e.outerHTML,st.removeChild(o=st.firstChild)),!(fe.noCloneEvent&&fe.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||pe.isXMLDoc(e)))for(r=h(o),s=h(e),a=0;null!=(i=s[a]);++a)r[a]&&k(i,r[a]);if(t)if(n)for(s=s||h(e),r=r||h(o),a=0;null!=(i=s[a]);a++)N(i,r[a]);else N(e,o);return r=h(o,\"script\"),r.length>0&&g(r,!u&&h(e,\"script\")),r=s=i=null,o},cleanData:function(e,t){for(var n,r,i,o,a=0,s=pe.expando,u=pe.cache,l=fe.attributes,c=pe.event.special;null!=(n=e[a]);a++)if((t||He(n))&&(i=n[s],o=i&&u[i])){if(o.events)for(r in o.events)c[r]?pe.event.remove(n,r):pe.removeEvent(n,r,o.handle);u[i]&&(delete u[i],l||\"undefined\"==typeof n.removeAttribute?n[s]=void 0:n.removeAttribute(s),ne.push(i))}}}),pe.fn.extend({domManip:S,detach:function(e){return A(this,e,!0)},remove:function(e){return A(this,e)},text:function(e){return Pe(this,function(e){return void 0===e?pe.text(this):this.empty().append((this[0]&&this[0].ownerDocument||re).createTextNode(e))},null,e,arguments.length)},append:function(){return S(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=T(this,e);t.appendChild(e)}})},prepend:function(){return S(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=T(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return S(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return S(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++){for(1===e.nodeType&&pe.cleanData(h(e,!1));e.firstChild;)e.removeChild(e.firstChild);e.options&&pe.nodeName(e,\"select\")&&(e.options.length=0)}return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return pe.clone(this,e,t)})},html:function(e){return Pe(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e)return 1===t.nodeType?t.innerHTML.replace(Ze,\"\"):void 0;if(\"string\"==typeof e&&!nt.test(e)&&(fe.htmlSerialize||!et.test(e))&&(fe.leadingWhitespace||!$e.test(e))&&!Xe[(We.exec(e)||[\"\",\"\"])[1].toLowerCase()]){e=pe.htmlPrefilter(e);try{for(;n<r;n++)t=this[n]||{},1===t.nodeType&&(pe.cleanData(h(t,!1)),t.innerHTML=e);t=0}catch(i){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=[];return S(this,arguments,function(t){var n=this.parentNode;pe.inArray(this,e)<0&&(pe.cleanData(h(this)),\nn&&n.replaceChild(t,this))},e)}}),pe.each({appendTo:\"append\",prependTo:\"prepend\",insertBefore:\"before\",insertAfter:\"after\",replaceAll:\"replaceWith\"},function(e,t){pe.fn[e]=function(e){for(var n,r=0,i=[],o=pe(e),a=o.length-1;r<=a;r++)n=r===a?this:this.clone(!0),pe(o[r])[t](n),ae.apply(i,n.get());return this.pushStack(i)}});var ut,lt={HTML:\"block\",BODY:\"block\"},ct=/^margin/,ft=new RegExp(\"^(\"+Fe+\")(?!px)[a-z%]+$\",\"i\"),dt=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},pt=re.documentElement;!function(){function t(){var t,c,f=re.documentElement;f.appendChild(u),l.style.cssText=\"-webkit-box-sizing:border-box;box-sizing:border-box;position:relative;display:block;margin:auto;border:1px;padding:1px;top:1%;width:50%\",n=i=s=!1,r=a=!0,e.getComputedStyle&&(c=e.getComputedStyle(l),n=\"1%\"!==(c||{}).top,s=\"2px\"===(c||{}).marginLeft,i=\"4px\"===(c||{width:\"4px\"}).width,l.style.marginRight=\"50%\",r=\"4px\"===(c||{marginRight:\"4px\"}).marginRight,t=l.appendChild(re.createElement(\"div\")),t.style.cssText=l.style.cssText=\"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0\",t.style.marginRight=t.style.width=\"0\",l.style.width=\"1px\",a=!parseFloat((e.getComputedStyle(t)||{}).marginRight),l.removeChild(t)),l.style.display=\"none\",o=0===l.getClientRects().length,o&&(l.style.display=\"\",l.innerHTML=\"<table><tr><td></td><td>t</td></tr></table>\",t=l.getElementsByTagName(\"td\"),t[0].style.cssText=\"margin:0;border:0;padding:0;display:none\",o=0===t[0].offsetHeight,o&&(t[0].style.display=\"\",t[1].style.display=\"none\",o=0===t[0].offsetHeight)),f.removeChild(u)}var n,r,i,o,a,s,u=re.createElement(\"div\"),l=re.createElement(\"div\");l.style&&(l.style.cssText=\"float:left;opacity:.5\",fe.opacity=\"0.5\"===l.style.opacity,fe.cssFloat=!!l.style.cssFloat,l.style.backgroundClip=\"content-box\",l.cloneNode(!0).style.backgroundClip=\"\",fe.clearCloneStyle=\"content-box\"===l.style.backgroundClip,u=re.createElement(\"div\"),u.style.cssText=\"border:0;width:8px;height:0;top:0;left:-9999px;padding:0;margin-top:1px;position:absolute\",l.innerHTML=\"\",u.appendChild(l),fe.boxSizing=\"\"===l.style.boxSizing||\"\"===l.style.MozBoxSizing||\"\"===l.style.WebkitBoxSizing,pe.extend(fe,{reliableHiddenOffsets:function(){return null==n&&t(),o},boxSizingReliable:function(){return null==n&&t(),i},pixelMarginRight:function(){return null==n&&t(),r},pixelPosition:function(){return null==n&&t(),n},reliableMarginRight:function(){return null==n&&t(),a},reliableMarginLeft:function(){return null==n&&t(),s}}))}();var ht,gt,mt=/^(top|right|bottom|left)$/;e.getComputedStyle?(ht=function(t){var n=t.ownerDocument.defaultView;return n&&n.opener||(n=e),n.getComputedStyle(t)},gt=function(e,t,n){var r,i,o,a,s=e.style;return n=n||ht(e),a=n?n.getPropertyValue(t)||n[t]:void 0,\"\"!==a&&void 0!==a||pe.contains(e.ownerDocument,e)||(a=pe.style(e,t)),n&&!fe.pixelMarginRight()&&ft.test(a)&&ct.test(t)&&(r=s.width,i=s.minWidth,o=s.maxWidth,s.minWidth=s.maxWidth=s.width=a,a=n.width,s.width=r,s.minWidth=i,s.maxWidth=o),void 0===a?a:a+\"\"}):pt.currentStyle&&(ht=function(e){return e.currentStyle},gt=function(e,t,n){var r,i,o,a,s=e.style;return n=n||ht(e),a=n?n[t]:void 0,null==a&&s&&s[t]&&(a=s[t]),ft.test(a)&&!mt.test(t)&&(r=s.left,i=e.runtimeStyle,o=i&&i.left,o&&(i.left=e.currentStyle.left),s.left=\"fontSize\"===t?\"1em\":a,a=s.pixelLeft+\"px\",s.left=r,o&&(i.left=o)),void 0===a?a:a+\"\"||\"auto\"});var yt=/alpha\\([^)]*\\)/i,vt=/opacity\\s*=\\s*([^)]*)/i,xt=/^(none|table(?!-c[ea]).+)/,bt=new RegExp(\"^(\"+Fe+\")(.*)$\",\"i\"),wt={position:\"absolute\",visibility:\"hidden\",display:\"block\"},Tt={letterSpacing:\"0\",fontWeight:\"400\"},Ct=[\"Webkit\",\"O\",\"Moz\",\"ms\"],Et=re.createElement(\"div\").style;pe.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=gt(e,\"opacity\");return\"\"===n?\"1\":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{\"float\":fe.cssFloat?\"cssFloat\":\"styleFloat\"},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=pe.camelCase(t),u=e.style;if(t=pe.cssProps[s]||(pe.cssProps[s]=H(s)||s),a=pe.cssHooks[t]||pe.cssHooks[s],void 0===n)return a&&\"get\"in a&&void 0!==(i=a.get(e,!1,r))?i:u[t];if(o=typeof n,\"string\"===o&&(i=Me.exec(n))&&i[1]&&(n=d(e,t,i),o=\"number\"),null!=n&&n===n&&(\"number\"===o&&(n+=i&&i[3]||(pe.cssNumber[s]?\"\":\"px\")),fe.clearCloneStyle||\"\"!==n||0!==t.indexOf(\"background\")||(u[t]=\"inherit\"),!(a&&\"set\"in a&&void 0===(n=a.set(e,n,r)))))try{u[t]=n}catch(l){}}},css:function(e,t,n,r){var i,o,a,s=pe.camelCase(t);return t=pe.cssProps[s]||(pe.cssProps[s]=H(s)||s),a=pe.cssHooks[t]||pe.cssHooks[s],a&&\"get\"in a&&(o=a.get(e,!0,n)),void 0===o&&(o=gt(e,t,r)),\"normal\"===o&&t in Tt&&(o=Tt[t]),\"\"===n||n?(i=parseFloat(o),n===!0||isFinite(i)?i||0:o):o}}),pe.each([\"height\",\"width\"],function(e,t){pe.cssHooks[t]={get:function(e,n,r){if(n)return xt.test(pe.css(e,\"display\"))&&0===e.offsetWidth?dt(e,wt,function(){return M(e,t,r)}):M(e,t,r)},set:function(e,n,r){var i=r&&ht(e);return _(e,n,r?F(e,t,r,fe.boxSizing&&\"border-box\"===pe.css(e,\"boxSizing\",!1,i),i):0)}}}),fe.opacity||(pe.cssHooks.opacity={get:function(e,t){return vt.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=pe.isNumeric(t)?\"alpha(opacity=\"+100*t+\")\":\"\",o=r&&r.filter||n.filter||\"\";n.zoom=1,(t>=1||\"\"===t)&&\"\"===pe.trim(o.replace(yt,\"\"))&&n.removeAttribute&&(n.removeAttribute(\"filter\"),\"\"===t||r&&!r.filter)||(n.filter=yt.test(o)?o.replace(yt,i):o+\" \"+i)}}),pe.cssHooks.marginRight=L(fe.reliableMarginRight,function(e,t){if(t)return dt(e,{display:\"inline-block\"},gt,[e,\"marginRight\"])}),pe.cssHooks.marginLeft=L(fe.reliableMarginLeft,function(e,t){if(t)return(parseFloat(gt(e,\"marginLeft\"))||(pe.contains(e.ownerDocument,e)?e.getBoundingClientRect().left-dt(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}):0))+\"px\"}),pe.each({margin:\"\",padding:\"\",border:\"Width\"},function(e,t){pe.cssHooks[e+t]={expand:function(n){for(var r=0,i={},o=\"string\"==typeof n?n.split(\" \"):[n];r<4;r++)i[e+Oe[r]+t]=o[r]||o[r-2]||o[0];return i}},ct.test(e)||(pe.cssHooks[e+t].set=_)}),pe.fn.extend({css:function(e,t){return Pe(this,function(e,t,n){var r,i,o={},a=0;if(pe.isArray(t)){for(r=ht(e),i=t.length;a<i;a++)o[t[a]]=pe.css(e,t[a],!1,r);return o}return void 0!==n?pe.style(e,t,n):pe.css(e,t)},e,t,arguments.length>1)},show:function(){return q(this,!0)},hide:function(){return q(this)},toggle:function(e){return\"boolean\"==typeof e?e?this.show():this.hide():this.each(function(){Re(this)?pe(this).show():pe(this).hide()})}}),pe.Tween=O,O.prototype={constructor:O,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||pe.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(pe.cssNumber[n]?\"\":\"px\")},cur:function(){var e=O.propHooks[this.prop];return e&&e.get?e.get(this):O.propHooks._default.get(this)},run:function(e){var t,n=O.propHooks[this.prop];return this.options.duration?this.pos=t=pe.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=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):O.propHooks._default.set(this),this}},O.prototype.init.prototype=O.prototype,O.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=pe.css(e.elem,e.prop,\"\"),t&&\"auto\"!==t?t:0)},set:function(e){pe.fx.step[e.prop]?pe.fx.step[e.prop](e):1!==e.elem.nodeType||null==e.elem.style[pe.cssProps[e.prop]]&&!pe.cssHooks[e.prop]?e.elem[e.prop]=e.now:pe.style(e.elem,e.prop,e.now+e.unit)}}},O.propHooks.scrollTop=O.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},pe.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:\"swing\"},pe.fx=O.prototype.init,pe.fx.step={};var Nt,kt,St=/^(?:toggle|show|hide)$/,At=/queueHooks$/;pe.Animation=pe.extend($,{tweeners:{\"*\":[function(e,t){var n=this.createTween(e,t);return d(n.elem,e,Me.exec(t),n),n}]},tweener:function(e,t){pe.isFunction(e)?(t=e,e=[\"*\"]):e=e.match(De);for(var n,r=0,i=e.length;r<i;r++)n=e[r],$.tweeners[n]=$.tweeners[n]||[],$.tweeners[n].unshift(t)},prefilters:[W],prefilter:function(e,t){t?$.prefilters.unshift(e):$.prefilters.push(e)}}),pe.speed=function(e,t,n){var r=e&&\"object\"==typeof e?pe.extend({},e):{complete:n||!n&&t||pe.isFunction(e)&&e,duration:e,easing:n&&t||t&&!pe.isFunction(t)&&t};return r.duration=pe.fx.off?0:\"number\"==typeof r.duration?r.duration:r.duration in pe.fx.speeds?pe.fx.speeds[r.duration]:pe.fx.speeds._default,null!=r.queue&&r.queue!==!0||(r.queue=\"fx\"),r.old=r.complete,r.complete=function(){pe.isFunction(r.old)&&r.old.call(this),r.queue&&pe.dequeue(this,r.queue)},r},pe.fn.extend({fadeTo:function(e,t,n,r){return this.filter(Re).css(\"opacity\",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=pe.isEmptyObject(e),o=pe.speed(t,n,r),a=function(){var t=$(this,pe.extend({},e),o);(i||pe._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,t,n){var r=function(e){var t=e.stop;delete e.stop,t(n)};return\"string\"!=typeof e&&(n=t,t=e,e=void 0),t&&e!==!1&&this.queue(e||\"fx\",[]),this.each(function(){var t=!0,i=null!=e&&e+\"queueHooks\",o=pe.timers,a=pe._data(this);if(i)a[i]&&a[i].stop&&r(a[i]);else for(i in a)a[i]&&a[i].stop&&At.test(i)&&r(a[i]);for(i=o.length;i--;)o[i].elem!==this||null!=e&&o[i].queue!==e||(o[i].anim.stop(n),t=!1,o.splice(i,1));!t&&n||pe.dequeue(this,e)})},finish:function(e){return e!==!1&&(e=e||\"fx\"),this.each(function(){var t,n=pe._data(this),r=n[e+\"queue\"],i=n[e+\"queueHooks\"],o=pe.timers,a=r?r.length:0;for(n.finish=!0,pe.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;t<a;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}}),pe.each([\"toggle\",\"show\",\"hide\"],function(e,t){var n=pe.fn[t];pe.fn[t]=function(e,r,i){return null==e||\"boolean\"==typeof e?n.apply(this,arguments):this.animate(P(t,!0),e,r,i)}}),pe.each({slideDown:P(\"show\"),slideUp:P(\"hide\"),slideToggle:P(\"toggle\"),fadeIn:{opacity:\"show\"},fadeOut:{opacity:\"hide\"},fadeToggle:{opacity:\"toggle\"}},function(e,t){pe.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),pe.timers=[],pe.fx.tick=function(){var e,t=pe.timers,n=0;for(Nt=pe.now();n<t.length;n++)e=t[n],e()||t[n]!==e||t.splice(n--,1);t.length||pe.fx.stop(),Nt=void 0},pe.fx.timer=function(e){pe.timers.push(e),e()?pe.fx.start():pe.timers.pop()},pe.fx.interval=13,pe.fx.start=function(){kt||(kt=e.setInterval(pe.fx.tick,pe.fx.interval))},pe.fx.stop=function(){e.clearInterval(kt),kt=null},pe.fx.speeds={slow:600,fast:200,_default:400},pe.fn.delay=function(t,n){return t=pe.fx?pe.fx.speeds[t]||t:t,n=n||\"fx\",this.queue(n,function(n,r){var i=e.setTimeout(n,t);r.stop=function(){e.clearTimeout(i)}})},function(){var e,t=re.createElement(\"input\"),n=re.createElement(\"div\"),r=re.createElement(\"select\"),i=r.appendChild(re.createElement(\"option\"));n=re.createElement(\"div\"),n.setAttribute(\"className\",\"t\"),n.innerHTML=\"  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>\",e=n.getElementsByTagName(\"a\")[0],t.setAttribute(\"type\",\"checkbox\"),n.appendChild(t),e=n.getElementsByTagName(\"a\")[0],e.style.cssText=\"top:1px\",fe.getSetAttribute=\"t\"!==n.className,fe.style=/top/.test(e.getAttribute(\"style\")),fe.hrefNormalized=\"/a\"===e.getAttribute(\"href\"),fe.checkOn=!!t.value,fe.optSelected=i.selected,fe.enctype=!!re.createElement(\"form\").enctype,r.disabled=!0,fe.optDisabled=!i.disabled,t=re.createElement(\"input\"),t.setAttribute(\"value\",\"\"),fe.input=\"\"===t.getAttribute(\"value\"),t.value=\"t\",t.setAttribute(\"type\",\"radio\"),fe.radioValue=\"t\"===t.value}();var Dt=/\\r/g,jt=/[\\x20\\t\\r\\n\\f]+/g;pe.fn.extend({val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=pe.isFunction(e),this.each(function(n){var i;1===this.nodeType&&(i=r?e.call(this,n,pe(this).val()):e,null==i?i=\"\":\"number\"==typeof i?i+=\"\":pe.isArray(i)&&(i=pe.map(i,function(e){return null==e?\"\":e+\"\"})),t=pe.valHooks[this.type]||pe.valHooks[this.nodeName.toLowerCase()],t&&\"set\"in t&&void 0!==t.set(this,i,\"value\")||(this.value=i))});if(i)return t=pe.valHooks[i.type]||pe.valHooks[i.nodeName.toLowerCase()],t&&\"get\"in t&&void 0!==(n=t.get(i,\"value\"))?n:(n=i.value,\"string\"==typeof n?n.replace(Dt,\"\"):null==n?\"\":n)}}}),pe.extend({valHooks:{option:{get:function(e){var t=pe.find.attr(e,\"value\");return null!=t?t:pe.trim(pe.text(e)).replace(jt,\" \")}},select:{get:function(e){for(var t,n,r=e.options,i=e.selectedIndex,o=\"select-one\"===e.type||i<0,a=o?null:[],s=o?i+1:r.length,u=i<0?s:o?i:0;u<s;u++)if(n=r[u],(n.selected||u===i)&&(fe.optDisabled?!n.disabled:null===n.getAttribute(\"disabled\"))&&(!n.parentNode.disabled||!pe.nodeName(n.parentNode,\"optgroup\"))){if(t=pe(n).val(),o)return t;a.push(t)}return a},set:function(e,t){for(var n,r,i=e.options,o=pe.makeArray(t),a=i.length;a--;)if(r=i[a],pe.inArray(pe.valHooks.option.get(r),o)>-1)try{r.selected=n=!0}catch(s){r.scrollHeight}else r.selected=!1;return n||(e.selectedIndex=-1),i}}}}),pe.each([\"radio\",\"checkbox\"],function(){pe.valHooks[this]={set:function(e,t){if(pe.isArray(t))return e.checked=pe.inArray(pe(e).val(),t)>-1}},fe.checkOn||(pe.valHooks[this].get=function(e){return null===e.getAttribute(\"value\")?\"on\":e.value})});var Lt,Ht,qt=pe.expr.attrHandle,_t=/^(?:checked|selected)$/i,Ft=fe.getSetAttribute,Mt=fe.input;pe.fn.extend({attr:function(e,t){return Pe(this,pe.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){pe.removeAttr(this,e)})}}),pe.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return\"undefined\"==typeof e.getAttribute?pe.prop(e,t,n):(1===o&&pe.isXMLDoc(e)||(t=t.toLowerCase(),i=pe.attrHooks[t]||(pe.expr.match.bool.test(t)?Ht:Lt)),void 0!==n?null===n?void pe.removeAttr(e,t):i&&\"set\"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+\"\"),n):i&&\"get\"in i&&null!==(r=i.get(e,t))?r:(r=pe.find.attr(e,t),null==r?void 0:r))},attrHooks:{type:{set:function(e,t){if(!fe.radioValue&&\"radio\"===t&&pe.nodeName(e,\"input\")){var n=e.value;return e.setAttribute(\"type\",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(De);if(o&&1===e.nodeType)for(;n=o[i++];)r=pe.propFix[n]||n,pe.expr.match.bool.test(n)?Mt&&Ft||!_t.test(n)?e[r]=!1:e[pe.camelCase(\"default-\"+n)]=e[r]=!1:pe.attr(e,n,\"\"),e.removeAttribute(Ft?n:r)}}),Ht={set:function(e,t,n){return t===!1?pe.removeAttr(e,n):Mt&&Ft||!_t.test(n)?e.setAttribute(!Ft&&pe.propFix[n]||n,n):e[pe.camelCase(\"default-\"+n)]=e[n]=!0,n}},pe.each(pe.expr.match.bool.source.match(/\\w+/g),function(e,t){var n=qt[t]||pe.find.attr;Mt&&Ft||!_t.test(t)?qt[t]=function(e,t,r){var i,o;return r||(o=qt[t],qt[t]=i,i=null!=n(e,t,r)?t.toLowerCase():null,qt[t]=o),i}:qt[t]=function(e,t,n){if(!n)return e[pe.camelCase(\"default-\"+t)]?t.toLowerCase():null}}),Mt&&Ft||(pe.attrHooks.value={set:function(e,t,n){return pe.nodeName(e,\"input\")?void(e.defaultValue=t):Lt&&Lt.set(e,t,n)}}),Ft||(Lt={set:function(e,t,n){var r=e.getAttributeNode(n);if(r||e.setAttributeNode(r=e.ownerDocument.createAttribute(n)),r.value=t+=\"\",\"value\"===n||t===e.getAttribute(n))return t}},qt.id=qt.name=qt.coords=function(e,t,n){var r;if(!n)return(r=e.getAttributeNode(t))&&\"\"!==r.value?r.value:null},pe.valHooks.button={get:function(e,t){var n=e.getAttributeNode(t);if(n&&n.specified)return n.value},set:Lt.set},pe.attrHooks.contenteditable={set:function(e,t,n){Lt.set(e,\"\"!==t&&t,n)}},pe.each([\"width\",\"height\"],function(e,t){pe.attrHooks[t]={set:function(e,n){if(\"\"===n)return e.setAttribute(t,\"auto\"),n}}})),fe.style||(pe.attrHooks.style={get:function(e){return e.style.cssText||void 0},set:function(e,t){return e.style.cssText=t+\"\"}});var Ot=/^(?:input|select|textarea|button|object)$/i,Rt=/^(?:a|area)$/i;pe.fn.extend({prop:function(e,t){return Pe(this,pe.prop,e,t,arguments.length>1)},removeProp:function(e){return e=pe.propFix[e]||e,this.each(function(){try{this[e]=void 0,delete this[e]}catch(t){}})}}),pe.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&pe.isXMLDoc(e)||(t=pe.propFix[t]||t,i=pe.propHooks[t]),void 0!==n?i&&\"set\"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&\"get\"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=pe.find.attr(e,\"tabindex\");return t?parseInt(t,10):Ot.test(e.nodeName)||Rt.test(e.nodeName)&&e.href?0:-1}}},propFix:{\"for\":\"htmlFor\",\"class\":\"className\"}}),fe.hrefNormalized||pe.each([\"href\",\"src\"],function(e,t){pe.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}}),fe.optSelected||(pe.propHooks.selected={get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),pe.each([\"tabIndex\",\"readOnly\",\"maxLength\",\"cellSpacing\",\"cellPadding\",\"rowSpan\",\"colSpan\",\"useMap\",\"frameBorder\",\"contentEditable\"],function(){pe.propFix[this.toLowerCase()]=this}),fe.enctype||(pe.propFix.enctype=\"encoding\");var Pt=/[\\t\\r\\n\\f]/g;pe.fn.extend({addClass:function(e){var t,n,r,i,o,a,s,u=0;if(pe.isFunction(e))return this.each(function(t){pe(this).addClass(e.call(this,t,z(this)))});if(\"string\"==typeof e&&e)for(t=e.match(De)||[];n=this[u++];)if(i=z(n),r=1===n.nodeType&&(\" \"+i+\" \").replace(Pt,\" \")){for(a=0;o=t[a++];)r.indexOf(\" \"+o+\" \")<0&&(r+=o+\" \");s=pe.trim(r),i!==s&&pe.attr(n,\"class\",s)}return this},removeClass:function(e){var t,n,r,i,o,a,s,u=0;if(pe.isFunction(e))return this.each(function(t){pe(this).removeClass(e.call(this,t,z(this)))});if(!arguments.length)return this.attr(\"class\",\"\");if(\"string\"==typeof e&&e)for(t=e.match(De)||[];n=this[u++];)if(i=z(n),r=1===n.nodeType&&(\" \"+i+\" \").replace(Pt,\" \")){for(a=0;o=t[a++];)for(;r.indexOf(\" \"+o+\" \")>-1;)r=r.replace(\" \"+o+\" \",\" \");s=pe.trim(r),i!==s&&pe.attr(n,\"class\",s)}return this},toggleClass:function(e,t){var n=typeof e;return\"boolean\"==typeof t&&\"string\"===n?t?this.addClass(e):this.removeClass(e):pe.isFunction(e)?this.each(function(n){pe(this).toggleClass(e.call(this,n,z(this),t),t)}):this.each(function(){var t,r,i,o;if(\"string\"===n)for(r=0,i=pe(this),o=e.match(De)||[];t=o[r++];)i.hasClass(t)?i.removeClass(t):i.addClass(t);else void 0!==e&&\"boolean\"!==n||(t=z(this),t&&pe._data(this,\"__className__\",t),pe.attr(this,\"class\",t||e===!1?\"\":pe._data(this,\"__className__\")||\"\"))})},hasClass:function(e){var t,n,r=0;for(t=\" \"+e+\" \";n=this[r++];)if(1===n.nodeType&&(\" \"+z(n)+\" \").replace(Pt,\" \").indexOf(t)>-1)return!0;return!1}}),pe.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){pe.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),pe.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}});var Bt=e.location,Wt=pe.now(),It=/\\?/,$t=/(,)|(\\[|{)|(}|])|\"(?:[^\"\\\\\\r\\n]|\\\\[\"\\\\\\/bfnrt]|\\\\u[\\da-fA-F]{4})*\"\\s*:?|true|false|null|-?(?!0\\d)\\d+(?:\\.\\d+|)(?:[eE][+-]?\\d+|)/g;pe.parseJSON=function(t){if(e.JSON&&e.JSON.parse)return e.JSON.parse(t+\"\");var n,r=null,i=pe.trim(t+\"\");return i&&!pe.trim(i.replace($t,function(e,t,i,o){return n&&t&&(r=0),0===r?e:(n=i||t,r+=!o-!i,\"\")}))?Function(\"return \"+i)():pe.error(\"Invalid JSON: \"+t)},pe.parseXML=function(t){var n,r;if(!t||\"string\"!=typeof t)return null;try{e.DOMParser?(r=new e.DOMParser,n=r.parseFromString(t,\"text/xml\")):(n=new e.ActiveXObject(\"Microsoft.XMLDOM\"),n.async=\"false\",n.loadXML(t))}catch(i){n=void 0}return n&&n.documentElement&&!n.getElementsByTagName(\"parsererror\").length||pe.error(\"Invalid XML: \"+t),n};var zt=/#.*$/,Xt=/([?&])_=[^&]*/,Ut=/^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/gm,Vt=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Yt=/^(?:GET|HEAD)$/,Jt=/^\\/\\//,Gt=/^([\\w.+-]+:)(?:\\/\\/(?:[^\\/?#]*@|)([^\\/?#:]*)(?::(\\d+)|)|)/,Kt={},Qt={},Zt=\"*/\".concat(\"*\"),en=Bt.href,tn=Gt.exec(en.toLowerCase())||[];pe.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:en,type:\"GET\",isLocal:Vt.test(tn[1]),global:!0,processData:!0,async:!0,contentType:\"application/x-www-form-urlencoded; charset=UTF-8\",accepts:{\"*\":Zt,text:\"text/plain\",html:\"text/html\",xml:\"application/xml, text/xml\",json:\"application/json, text/javascript\"},contents:{xml:/\\bxml\\b/,html:/\\bhtml/,json:/\\bjson\\b/},responseFields:{xml:\"responseXML\",text:\"responseText\",json:\"responseJSON\"},converters:{\"* text\":String,\"text html\":!0,\"text json\":pe.parseJSON,\"text xml\":pe.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?V(V(e,pe.ajaxSettings),t):V(pe.ajaxSettings,e)},ajaxPrefilter:X(Kt),ajaxTransport:X(Qt),ajax:function(t,n){function r(t,n,r,i){var o,f,v,x,w,C=n;2!==b&&(b=2,u&&e.clearTimeout(u),c=void 0,s=i||\"\",T.readyState=t>0?4:0,o=t>=200&&t<300||304===t,r&&(x=Y(d,T,r)),x=J(d,x,T,o),o?(d.ifModified&&(w=T.getResponseHeader(\"Last-Modified\"),w&&(pe.lastModified[a]=w),w=T.getResponseHeader(\"etag\"),w&&(pe.etag[a]=w)),204===t||\"HEAD\"===d.type?C=\"nocontent\":304===t?C=\"notmodified\":(C=x.state,f=x.data,v=x.error,o=!v)):(v=C,!t&&C||(C=\"error\",t<0&&(t=0))),T.status=t,T.statusText=(n||C)+\"\",o?g.resolveWith(p,[f,C,T]):g.rejectWith(p,[T,C,v]),T.statusCode(y),y=void 0,l&&h.trigger(o?\"ajaxSuccess\":\"ajaxError\",[T,d,o?f:v]),m.fireWith(p,[T,C]),l&&(h.trigger(\"ajaxComplete\",[T,d]),--pe.active||pe.event.trigger(\"ajaxStop\")))}\"object\"==typeof t&&(n=t,t=void 0),n=n||{};var i,o,a,s,u,l,c,f,d=pe.ajaxSetup({},n),p=d.context||d,h=d.context&&(p.nodeType||p.jquery)?pe(p):pe.event,g=pe.Deferred(),m=pe.Callbacks(\"once memory\"),y=d.statusCode||{},v={},x={},b=0,w=\"canceled\",T={readyState:0,getResponseHeader:function(e){var t;if(2===b){if(!f)for(f={};t=Ut.exec(s);)f[t[1].toLowerCase()]=t[2];t=f[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===b?s:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return b||(e=x[n]=x[n]||e,v[e]=t),this},overrideMimeType:function(e){return b||(d.mimeType=e),this},statusCode:function(e){var t;if(e)if(b<2)for(t in e)y[t]=[y[t],e[t]];else T.always(e[T.status]);return this},abort:function(e){var t=e||w;return c&&c.abort(t),r(0,t),this}};if(g.promise(T).complete=m.add,T.success=T.done,T.error=T.fail,d.url=((t||d.url||en)+\"\").replace(zt,\"\").replace(Jt,tn[1]+\"//\"),d.type=n.method||n.type||d.method||d.type,d.dataTypes=pe.trim(d.dataType||\"*\").toLowerCase().match(De)||[\"\"],null==d.crossDomain&&(i=Gt.exec(d.url.toLowerCase()),d.crossDomain=!(!i||i[1]===tn[1]&&i[2]===tn[2]&&(i[3]||(\"http:\"===i[1]?\"80\":\"443\"))===(tn[3]||(\"http:\"===tn[1]?\"80\":\"443\")))),d.data&&d.processData&&\"string\"!=typeof d.data&&(d.data=pe.param(d.data,d.traditional)),U(Kt,d,n,T),2===b)return T;l=pe.event&&d.global,l&&0===pe.active++&&pe.event.trigger(\"ajaxStart\"),d.type=d.type.toUpperCase(),d.hasContent=!Yt.test(d.type),a=d.url,d.hasContent||(d.data&&(a=d.url+=(It.test(a)?\"&\":\"?\")+d.data,delete d.data),d.cache===!1&&(d.url=Xt.test(a)?a.replace(Xt,\"$1_=\"+Wt++):a+(It.test(a)?\"&\":\"?\")+\"_=\"+Wt++)),d.ifModified&&(pe.lastModified[a]&&T.setRequestHeader(\"If-Modified-Since\",pe.lastModified[a]),pe.etag[a]&&T.setRequestHeader(\"If-None-Match\",pe.etag[a])),(d.data&&d.hasContent&&d.contentType!==!1||n.contentType)&&T.setRequestHeader(\"Content-Type\",d.contentType),T.setRequestHeader(\"Accept\",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(\"*\"!==d.dataTypes[0]?\", \"+Zt+\"; q=0.01\":\"\"):d.accepts[\"*\"]);for(o in d.headers)T.setRequestHeader(o,d.headers[o]);if(d.beforeSend&&(d.beforeSend.call(p,T,d)===!1||2===b))return T.abort();w=\"abort\";for(o in{success:1,error:1,complete:1})T[o](d[o]);if(c=U(Qt,d,n,T)){if(T.readyState=1,l&&h.trigger(\"ajaxSend\",[T,d]),2===b)return T;d.async&&d.timeout>0&&(u=e.setTimeout(function(){T.abort(\"timeout\")},d.timeout));try{b=1,c.send(v,r)}catch(C){if(!(b<2))throw C;r(-1,C)}}else r(-1,\"No Transport\");return T},getJSON:function(e,t,n){return pe.get(e,t,n,\"json\")},getScript:function(e,t){return pe.get(e,void 0,t,\"script\")}}),pe.each([\"get\",\"post\"],function(e,t){pe[t]=function(e,n,r,i){return pe.isFunction(n)&&(i=i||r,r=n,n=void 0),pe.ajax(pe.extend({url:e,type:t,dataType:i,data:n,success:r},pe.isPlainObject(e)&&e))}}),pe._evalUrl=function(e){return pe.ajax({url:e,type:\"GET\",dataType:\"script\",cache:!0,async:!1,global:!1,\"throws\":!0})},pe.fn.extend({wrapAll:function(e){if(pe.isFunction(e))return this.each(function(t){pe(this).wrapAll(e.call(this,t))});if(this[0]){var t=pe(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){for(var e=this;e.firstChild&&1===e.firstChild.nodeType;)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return pe.isFunction(e)?this.each(function(t){pe(this).wrapInner(e.call(this,t))}):this.each(function(){var t=pe(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=pe.isFunction(e);return this.each(function(n){pe(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){pe.nodeName(this,\"body\")||pe(this).replaceWith(this.childNodes)}).end()}}),pe.expr.filters.hidden=function(e){return fe.reliableHiddenOffsets()?e.offsetWidth<=0&&e.offsetHeight<=0&&!e.getClientRects().length:K(e)},pe.expr.filters.visible=function(e){return!pe.expr.filters.hidden(e)};var nn=/%20/g,rn=/\\[\\]$/,on=/\\r?\\n/g,an=/^(?:submit|button|image|reset|file)$/i,sn=/^(?:input|select|textarea|keygen)/i;pe.param=function(e,t){var n,r=[],i=function(e,t){t=pe.isFunction(t)?t():null==t?\"\":t,r[r.length]=encodeURIComponent(e)+\"=\"+encodeURIComponent(t)};if(void 0===t&&(t=pe.ajaxSettings&&pe.ajaxSettings.traditional),pe.isArray(e)||e.jquery&&!pe.isPlainObject(e))pe.each(e,function(){i(this.name,this.value)});else for(n in e)Q(n,e[n],t,i);return r.join(\"&\").replace(nn,\"+\")},pe.fn.extend({serialize:function(){return pe.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=pe.prop(this,\"elements\");return e?pe.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!pe(this).is(\":disabled\")&&sn.test(this.nodeName)&&!an.test(e)&&(this.checked||!Be.test(e))}).map(function(e,t){var n=pe(this).val();return null==n?null:pe.isArray(n)?pe.map(n,function(e){return{name:t.name,value:e.replace(on,\"\\r\\n\")}}):{name:t.name,value:n.replace(on,\"\\r\\n\")}}).get()}}),pe.ajaxSettings.xhr=void 0!==e.ActiveXObject?function(){return this.isLocal?ee():re.documentMode>8?Z():/^(get|post|head|put|delete|options)$/i.test(this.type)&&Z()||ee()}:Z;var un=0,ln={},cn=pe.ajaxSettings.xhr();e.attachEvent&&e.attachEvent(\"onunload\",function(){for(var e in ln)ln[e](void 0,!0)}),fe.cors=!!cn&&\"withCredentials\"in cn,cn=fe.ajax=!!cn,cn&&pe.ajaxTransport(function(t){if(!t.crossDomain||fe.cors){var n;return{send:function(r,i){var o,a=t.xhr(),s=++un;if(a.open(t.type,t.url,t.async,t.username,t.password),t.xhrFields)for(o in t.xhrFields)a[o]=t.xhrFields[o];t.mimeType&&a.overrideMimeType&&a.overrideMimeType(t.mimeType),t.crossDomain||r[\"X-Requested-With\"]||(r[\"X-Requested-With\"]=\"XMLHttpRequest\");for(o in r)void 0!==r[o]&&a.setRequestHeader(o,r[o]+\"\");a.send(t.hasContent&&t.data||null),n=function(e,r){var o,u,l;if(n&&(r||4===a.readyState))if(delete ln[s],n=void 0,a.onreadystatechange=pe.noop,r)4!==a.readyState&&a.abort();else{l={},o=a.status,\"string\"==typeof a.responseText&&(l.text=a.responseText);try{u=a.statusText}catch(c){u=\"\"}o||!t.isLocal||t.crossDomain?1223===o&&(o=204):o=l.text?200:404}l&&i(o,u,l,a.getAllResponseHeaders())},t.async?4===a.readyState?e.setTimeout(n):a.onreadystatechange=ln[s]=n:n()},abort:function(){n&&n(void 0,!0)}}}}),pe.ajaxSetup({accepts:{script:\"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"},contents:{script:/\\b(?:java|ecma)script\\b/},converters:{\"text script\":function(e){return pe.globalEval(e),e}}}),pe.ajaxPrefilter(\"script\",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type=\"GET\",e.global=!1)}),pe.ajaxTransport(\"script\",function(e){if(e.crossDomain){var t,n=re.head||pe(\"head\")[0]||re.documentElement;return{send:function(r,i){t=re.createElement(\"script\"),t.async=!0,e.scriptCharset&&(t.charset=e.scriptCharset),t.src=e.url,t.onload=t.onreadystatechange=function(e,n){(n||!t.readyState||/loaded|complete/.test(t.readyState))&&(t.onload=t.onreadystatechange=null,t.parentNode&&t.parentNode.removeChild(t),t=null,n||i(200,\"success\"))},n.insertBefore(t,n.firstChild)},abort:function(){t&&t.onload(void 0,!0)}}}});var fn=[],dn=/(=)\\?(?=&|$)|\\?\\?/;pe.ajaxSetup({jsonp:\"callback\",jsonpCallback:function(){var e=fn.pop()||pe.expando+\"_\"+Wt++;return this[e]=!0,e}}),pe.ajaxPrefilter(\"json jsonp\",function(t,n,r){var i,o,a,s=t.jsonp!==!1&&(dn.test(t.url)?\"url\":\"string\"==typeof t.data&&0===(t.contentType||\"\").indexOf(\"application/x-www-form-urlencoded\")&&dn.test(t.data)&&\"data\");if(s||\"jsonp\"===t.dataTypes[0])return i=t.jsonpCallback=pe.isFunction(t.jsonpCallback)?t.jsonpCallback():t.jsonpCallback,s?t[s]=t[s].replace(dn,\"$1\"+i):t.jsonp!==!1&&(t.url+=(It.test(t.url)?\"&\":\"?\")+t.jsonp+\"=\"+i),t.converters[\"script json\"]=function(){return a||pe.error(i+\" was not called\"),a[0]},t.dataTypes[0]=\"json\",o=e[i],e[i]=function(){a=arguments},r.always(function(){void 0===o?pe(e).removeProp(i):e[i]=o,t[i]&&(t.jsonpCallback=n.jsonpCallback,fn.push(i)),a&&pe.isFunction(o)&&o(a[0]),a=o=void 0}),\"script\"}),pe.parseHTML=function(e,t,n){if(!e||\"string\"!=typeof e)return null;\"boolean\"==typeof t&&(n=t,t=!1),t=t||re;var r=Te.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=y([e],t,i),i&&i.length&&pe(i).remove(),pe.merge([],r.childNodes))};var pn=pe.fn.load;return pe.fn.load=function(e,t,n){if(\"string\"!=typeof e&&pn)return pn.apply(this,arguments);var r,i,o,a=this,s=e.indexOf(\" \");return s>-1&&(r=pe.trim(e.slice(s,e.length)),e=e.slice(0,s)),pe.isFunction(t)?(n=t,t=void 0):t&&\"object\"==typeof t&&(i=\"POST\"),a.length>0&&pe.ajax({url:e,type:i||\"GET\",dataType:\"html\",data:t}).done(function(e){o=arguments,a.html(r?pe(\"<div>\").append(pe.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},pe.each([\"ajaxStart\",\"ajaxStop\",\"ajaxComplete\",\"ajaxError\",\"ajaxSuccess\",\"ajaxSend\"],function(e,t){pe.fn[t]=function(e){return this.on(t,e)}}),pe.expr.filters.animated=function(e){return pe.grep(pe.timers,function(t){return e===t.elem}).length},pe.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l,c=pe.css(e,\"position\"),f=pe(e),d={};\"static\"===c&&(e.style.position=\"relative\"),s=f.offset(),o=pe.css(e,\"top\"),u=pe.css(e,\"left\"),l=(\"absolute\"===c||\"fixed\"===c)&&pe.inArray(\"auto\",[o,u])>-1,l?(r=f.position(),a=r.top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),pe.isFunction(t)&&(t=t.call(e,n,pe.extend({},s))),null!=t.top&&(d.top=t.top-s.top+a),null!=t.left&&(d.left=t.left-s.left+i),\"using\"in t?t.using.call(e,d):f.css(d)}},pe.fn.extend({offset:function(e){if(arguments.length)return void 0===e?this:this.each(function(t){pe.offset.setOffset(this,e,t)});var t,n,r={top:0,left:0},i=this[0],o=i&&i.ownerDocument;if(o)return t=o.documentElement,pe.contains(t,i)?(\"undefined\"!=typeof i.getBoundingClientRect&&(r=i.getBoundingClientRect()),n=te(o),{top:r.top+(n.pageYOffset||t.scrollTop)-(t.clientTop||0),left:r.left+(n.pageXOffset||t.scrollLeft)-(t.clientLeft||0)}):r},position:function(){if(this[0]){var e,t,n={top:0,left:0},r=this[0];return\"fixed\"===pe.css(r,\"position\")?t=r.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),pe.nodeName(e[0],\"html\")||(n=e.offset()),n.top+=pe.css(e[0],\"borderTopWidth\",!0),n.left+=pe.css(e[0],\"borderLeftWidth\",!0)),{top:t.top-n.top-pe.css(r,\"marginTop\",!0),left:t.left-n.left-pe.css(r,\"marginLeft\",!0)}}},offsetParent:function(){return this.map(function(){\nfor(var e=this.offsetParent;e&&!pe.nodeName(e,\"html\")&&\"static\"===pe.css(e,\"position\");)e=e.offsetParent;return e||pt})}}),pe.each({scrollLeft:\"pageXOffset\",scrollTop:\"pageYOffset\"},function(e,t){var n=/Y/.test(t);pe.fn[e]=function(r){return Pe(this,function(e,r,i){var o=te(e);return void 0===i?o?t in o?o[t]:o.document.documentElement[r]:e[r]:void(o?o.scrollTo(n?pe(o).scrollLeft():i,n?i:pe(o).scrollTop()):e[r]=i)},e,r,arguments.length,null)}}),pe.each([\"top\",\"left\"],function(e,t){pe.cssHooks[t]=L(fe.pixelPosition,function(e,n){if(n)return n=gt(e,t),ft.test(n)?pe(e).position()[t]+\"px\":n})}),pe.each({Height:\"height\",Width:\"width\"},function(e,t){pe.each({padding:\"inner\"+e,content:t,\"\":\"outer\"+e},function(n,r){pe.fn[r]=function(r,i){var o=arguments.length&&(n||\"boolean\"!=typeof r),a=n||(r===!0||i===!0?\"margin\":\"border\");return Pe(this,function(t,n,r){var i;return pe.isWindow(t)?t.document.documentElement[\"client\"+e]:9===t.nodeType?(i=t.documentElement,Math.max(t.body[\"scroll\"+e],i[\"scroll\"+e],t.body[\"offset\"+e],i[\"offset\"+e],i[\"client\"+e])):void 0===r?pe.css(t,n,a):pe.style(t,n,r,a)},t,o?r:void 0,o,null)}})}),pe.fn.extend({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)}}),pe.fn.size=function(){return this.length},pe.fn.andSelf=pe.fn.addBack,layui.define(function(e){e(\"jquery\",pe)}),pe});"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/plugins/layui/lay/modules/code.js",
    "content": "/** layui-v1.0.7 LGPL License By http://www.layui.com */\n ;layui.define(\"jquery\",function(e){\"use strict\";var a=layui.jquery,l=\"http://www.layui.com/doc/modules/code.html\";e(\"code\",function(e){var t=[];e=e||{},e.elem=a(e.elem||\".layui-code\"),e.about=!(\"about\"in e)||e.about,e.elem.each(function(){t.push(this)}),layui.each(t.reverse(),function(t,i){var c=a(i),o=c.html();(c.attr(\"lay-encode\")||e.encode)&&(o=o.replace(/&(?!#?[a-zA-Z0-9]+;)/g,\"&amp;\").replace(/</g,\"&lt;\").replace(/>/g,\"&gt;\").replace(/'/g,\"&#39;\").replace(/\"/g,\"&quot;\")),c.html('<ol class=\"layui-code-ol\"><li>'+o.replace(/[\\r\\t\\n]+/g,\"</li><li>\")+\"</li></ol>\"),c.find(\">.layui-code-h3\")[0]||c.prepend('<h3 class=\"layui-code-h3\">'+(c.attr(\"lay-title\")||e.title||\"code\")+(e.about?'<a href=\"'+l+'\" target=\"_blank\">layui.code</a>':\"\")+\"</h3>\");var d=c.find(\">.layui-code-ol\");c.addClass(\"layui-box layui-code-view\"),(c.attr(\"lay-skin\")||e.skin)&&c.addClass(\"layui-code-\"+(c.attr(\"lay-skin\")||e.skin)),(d.find(\"li\").length/100|0)>0&&d.css(\"margin-left\",(d.find(\"li\").length/100|0)+\"px\"),(c.attr(\"lay-height\")||e.height)&&d.css(\"max-height\",c.attr(\"lay-height\")||e.height)})})}).addcss(\"modules/code.css\",\"skincodecss\");"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/plugins/layui/lay/modules/element.js",
    "content": "/** layui-v1.0.7 LGPL License By http://www.layui.com */\n ;layui.define(\"jquery\",function(i){\"use strict\";var t=layui.jquery,a=(layui.hint(),layui.device()),e=\"element\",l=\"layui-this\",n=\"layui-show\",s=function(){this.config={}};s.prototype.set=function(i){var a=this;return t.extend(!0,a.config,i),a},s.prototype.on=function(i,t){return layui.onevent(e,i,t)},s.prototype.tabAdd=function(i,a){var e=t(\".layui-tab[lay-filter=\"+i+\"]\"),l=e.children(\".layui-tab-title\"),n=e.children(\".layui-tab-content\");return l.append(\"<li>\"+(a.title||\"unnaming\")+\"</li>\"),n.append('<div class=\"layui-tab-item\">'+(a.content||\"\")+\"</div>\"),y.tabAuto(),this},s.prototype.tabDelete=function(i,a){var e=t(\".layui-tab[lay-filter=\"+i+\"]\"),l=e.children(\".layui-tab-title\").find(\">li\").eq(a);return y.tabDelete(null,l),this},s.prototype.tabChange=function(i,a){var e=t(\".layui-tab[lay-filter=\"+i+\"]\"),l=e.children(\".layui-tab-title\").find(\">li\").eq(a);return y.tabClick(null,a,l),this};var o=\".layui-nav\",c=\"layui-nav-item\",r=\"layui-nav-bar\",u=\"layui-nav-tree\",d=\"layui-nav-child\",h=\"layui-nav-more\",f=\"layui-anim layui-anim-upbit\",y={tabClick:function(i,a,s){var o=s||t(this),a=a||o.index(),c=o.parents(\".layui-tab\"),r=c.children(\".layui-tab-content\").children(\".layui-tab-item\"),u=c.attr(\"lay-filter\");o.addClass(l).siblings().removeClass(l),r.eq(a).addClass(n).siblings().removeClass(n),layui.event.call(this,e,\"tab(\"+u+\")\",{elem:c,index:a})},tabDelete:function(i,a){var e=a||t(this).parent(),n=e.index(),s=e.parents(\".layui-tab\"),o=s.children(\".layui-tab-content\").children(\".layui-tab-item\");e.hasClass(l)&&(e.next()[0]?y.tabClick.call(e.next()[0],null,n+1):e.prev()[0]&&y.tabClick.call(e.prev()[0],null,n-1)),e.remove(),o.eq(n).remove()},tabAuto:function(){var i=\"layui-tab-more\",e=\"layui-tab-bar\",l=\"layui-tab-close\",n=this;t(\".layui-tab\").each(function(){var s=t(this),o=s.children(\".layui-tab-title\"),c=(s.children(\".layui-tab-content\").children(\".layui-tab-item\"),'lay-stope=\"tabmore\"'),r=t('<span class=\"layui-unselect layui-tab-bar\" '+c+\"><i \"+c+' class=\"layui-icon\">&#xe61a;</i></span>');if(n===window&&8!=a.ie&&y.hideTabMore(!0),s.attr(\"lay-allowClose\")&&o.find(\"li\").each(function(){var i=t(this);if(!i.find(\".\"+l)[0]){var a=t('<i class=\"layui-icon layui-unselect '+l+'\">&#x1006;</i>');a.on(\"click\",y.tabDelete),i.append(a)}}),o.prop(\"scrollWidth\")>o.outerWidth()+1){if(o.find(\".\"+e)[0])return;o.append(r),r.on(\"click\",function(t){o[this.title?\"removeClass\":\"addClass\"](i),this.title=this.title?\"\":\"收缩\"})}else o.find(\".\"+e).remove()})},hideTabMore:function(i){var a=t(\".layui-tab-title\");i!==!0&&\"tabmore\"===t(i.target).attr(\"lay-stope\")||(a.removeClass(\"layui-tab-more\"),a.find(\".layui-tab-bar\").attr(\"title\",\"\"))},clickThis:function(){var i=t(this),a=i.parents(o),n=a.attr(\"lay-filter\");i.find(\".\"+d)[0]||(a.find(\".\"+l).removeClass(l),i.addClass(l),layui.event.call(this,e,\"nav(\"+n+\")\",i))},clickChild:function(){var i=t(this),a=i.parents(o),n=a.attr(\"lay-filter\");a.find(\".\"+l).removeClass(l),i.addClass(l),layui.event.call(this,e,\"nav(\"+n+\")\",i)},showChild:function(){var i=t(this),a=i.parents(o),e=i.parent(),l=i.siblings(\".\"+d);a.hasClass(u)&&(l.removeClass(f),e[\"none\"===l.css(\"display\")?\"addClass\":\"removeClass\"](c+\"ed\"))}};s.prototype.init=function(i){var e={tab:function(){y.tabAuto.call({})},nav:function(){var i,e,l,s=200,p=function(o,c){var r=t(this),y=r.find(\".\"+d);c.hasClass(u)?o.css({top:r.position().top,height:r.children(\"a\").height(),opacity:1}):(y.addClass(f),o.css({left:r.position().left+parseFloat(r.css(\"marginLeft\")),top:r.position().top+r.height()-5}),i=setTimeout(function(){o.css({width:r.width(),opacity:1})},a.ie&&a.ie<10?0:s),clearTimeout(l),\"block\"===y.css(\"display\")&&clearTimeout(e),e=setTimeout(function(){y.addClass(n),r.find(\".\"+h).addClass(h+\"d\")},300))};t(o).each(function(){var a=t(this),o=t('<span class=\"'+r+'\"></span>'),f=a.find(\".\"+c);a.find(\".\"+r)[0]||(a.append(o),f.on(\"mouseenter\",function(){p.call(this,o,a)}).on(\"mouseleave\",function(){a.hasClass(u)||(clearTimeout(e),e=setTimeout(function(){a.find(\".\"+d).removeClass(n),a.find(\".\"+h).removeClass(h+\"d\")},300))}),a.on(\"mouseleave\",function(){clearTimeout(i),l=setTimeout(function(){a.hasClass(u)?o.css({height:0,top:o.position().top+o.height()/2,opacity:0}):o.css({width:0,left:o.position().left+o.width()/2,opacity:0})},s)})),f.each(function(){var i=t(this),a=i.find(\".\"+d);if(a[0]&&!i.find(\".\"+h)[0]){var e=i.children(\"a\");e.append('<span class=\"'+h+'\"></span>')}i.off(\"click\",y.clickThis).on(\"click\",y.clickThis),i.children(\"a\").off(\"click\",y.showChild).on(\"click\",y.showChild),a.children(\"dd\").off(\"click\",y.clickChild).on(\"click\",y.clickChild)})})},breadcrumb:function(){var i=\".layui-breadcrumb\";t(i).each(function(){var i=t(this),a=i.attr(\"lay-separator\")||\">\",e=i.find(\"a\");e.find(\".layui-box\")[0]||(e.each(function(i){i!==e.length-1&&t(this).append('<span class=\"layui-box\">'+a+\"</span>\")}),i.css(\"visibility\",\"visible\"))})}};return layui.each(e,function(i,t){t()})};var p=new s,b=t(document);p.init();var v=\".layui-tab-title li\";b.on(\"click\",v,y.tabClick),b.on(\"click\",y.hideTabMore),t(window).on(\"resize\",y.tabAuto),i(e,function(i){return p.set(i)})});"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/plugins/layui/lay/modules/flow.js",
    "content": "/** layui-v1.0.7 LGPL License By http://www.layui.com */\n ;layui.define(\"jquery\",function(e){\"use strict\";var l=layui.jquery,o=function(e){},t='<i class=\"layui-anim layui-anim-rotate layui-anim-loop layui-icon \">&#xe63e;</i>';o.prototype.load=function(e){var o,i,n,r,a=this,c=0;e=e||{};var u=l(e.elem);if(u[0]){var f=l(e.scrollElem||document),m=e.mb||50,s=!(\"isAuto\"in e)||e.isAuto,y=e.end||\"没有更多了\",v=e.scrollElem&&e.scrollElem!==document,d=\"<cite>加载更多</cite>\",h=l('<div class=\"layui-flow-more\"><a href=\"javascript:;\">'+d+\"</a></div>\");u.find(\".layui-flow-more\")[0]||u.append(h);var p=function(e,t){e=l(e),h.before(e),t=0==t||null,t?h.html(y):h.find(\"a\").html(d),i=t,o=null,n&&n()},g=function(){o=!0,h.find(\"a\").html(t),\"function\"==typeof e.done&&e.done(++c,p)};if(g(),h.find(\"a\").on(\"click\",function(){l(this);i||o||g()}),e.isLazyimg)var n=a.lazyimg({elem:e.elem+\" img\",scrollElem:e.scrollElem});return s?(f.on(\"scroll\",function(){var e=l(this),t=e.scrollTop();r&&clearTimeout(r),i||(r=setTimeout(function(){var i=v?e.height():l(window).height(),n=v?e.prop(\"scrollHeight\"):document.documentElement.scrollHeight;n-t-i<=m&&(o||g())},100))}),a):a}},o.prototype.lazyimg=function(e){var o,t=this,i=0;e=e||{};var n=l(e.scrollElem||document),r=e.elem||\"img\",a=e.scrollElem&&e.scrollElem!==document,c=function(e,l){var o=n.scrollTop(),r=o+l,c=a?function(){return e.offset().top-n.offset().top+o}():e.offset().top;if(c>=o&&c<=r&&!e.attr(\"src\")){var f=e.attr(\"lay-src\");layui.img(f,function(){var l=t.lazyimg.elem.eq(i);e.attr(\"src\",f).removeAttr(\"lay-src\"),l[0]&&u(l),i++})}},u=function(e,o){var u=a?(o||n).height():l(window).height(),f=n.scrollTop(),m=f+u;if(t.lazyimg.elem=l(r),e)c(e,u);else for(var s=0;s<t.lazyimg.elem.length;s++){var y=t.lazyimg.elem.eq(s),v=a?function(){return y.offset().top-n.offset().top+f}():y.offset().top;if(c(y,u),i=s,v>m)break}};if(u(),!o){var f;n.on(\"scroll\",function(){var e=l(this);f&&clearTimeout(f),f=setTimeout(function(){u(null,e)},50)}),o=!0}return u},e(\"flow\",new o)});"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/plugins/layui/lay/modules/form.js",
    "content": "/** layui-v1.0.7 LGPL License By http://www.layui.com */\n ;layui.define(\"layer\",function(e){\"use strict\";var i=layui.jquery,a=layui.layer,t=layui.hint(),n=layui.device(),l=\"form\",s=\".layui-form\",c=\"layui-this\",r=\"layui-disabled\",u=function(){this.config={verify:{required:[/[\\S]+/,\"必填项不能为空\"],phone:[/^1\\d{10}$/,\"请输入正确的手机号\"],email:[/^([a-zA-Z0-9_\\.\\-])+\\@(([a-zA-Z0-9\\-])+\\.)+([a-zA-Z0-9]{2,4})+$/,\"邮箱格式不正确\"],url:[/(^#)|(^http(s*):\\/\\/[^\\s]+\\.[^\\s]+)/,\"链接格式不正确\"],number:[/^\\d+$/,\"只能填写数字\"],date:[/^(\\d{4})[-\\/](\\d{1}|0\\d{1}|1[0-2])([-\\/](\\d{1}|0\\d{1}|[1-2][0-9]|3[0-1]))*$/,\"日期格式不正确\"],identity:[/(^\\d{15}$)|(^\\d{17}(x|X|\\d)$)/,\"请输入正确的身份证号\"]}}};u.prototype.set=function(e){var a=this;return i.extend(!0,a.config,e),a},u.prototype.verify=function(e){var a=this;return i.extend(!0,a.config.verify,e),a},u.prototype.on=function(e,i){return layui.onevent(l,e,i)},u.prototype.render=function(e){var a=this,n={select:function(){var e=\"请选择\",a=\"layui-form-select\",t=\"layui-select-title\",n=i(s).find(\"select\"),u=function(e,n){i(e.target).parent().hasClass(t)&&!n||i(\".\"+a).removeClass(a+\"ed\")},o=function(e,n){var s=i(this),o=e.find(\".\"+t);n||(o.on(\"click\",function(i){e.hasClass(a+\"ed\")?e.removeClass(a+\"ed\"):(u(i,!0),e.addClass(a+\"ed\"))}),e.find(\"dl>dd\").on(\"click\",function(){var e=i(this),a=e.attr(\"lay-value\"),t=s.attr(\"lay-filter\");return!e.hasClass(r)&&(s.val(a).removeClass(\"layui-form-danger\"),o.find(\"input\").val(e.text()),e.addClass(c).siblings().removeClass(c),void layui.event(l,\"select(\"+t+\")\",{elem:s[0],value:a}))}),e.find(\"dl>dt\").on(\"click\",function(e){return!1}),i(document).off(\"click\",u).on(\"click\",u))};n.each(function(n,l){var s=i(this),u=s.next(\".\"+a),d=this.disabled,f=l.value,y=i(l.options[l.selectedIndex]),v=i(['<div class=\"layui-unselect '+a+(d?\" layui-select-disabled\":\"\")+'\">','<div class=\"'+t+'\"><input type=\"text\" placeholder=\"'+(l.options[0].innerHTML?l.options[0].innerHTML:e)+'\" value=\"'+(f?y.html():\"\")+'\" readonly class=\"layui-input layui-unselect'+(d?\" \"+r:\"\")+'\">','<i class=\"layui-edge\"></i></div>','<dl class=\"layui-anim layui-anim-upbit'+(s.find(\"optgroup\")[0]?\" layui-select-group\":\"\")+'\">'+function(e){var i=[];return layui.each(e,function(e,a){(0!==e||a.value)&&(\"optgroup\"===a.tagName.toLowerCase()?i.push(\"<dt>\"+a.label+\"</dt>\"):i.push('<dd lay-value=\"'+a.value+'\" class=\"'+(f===a.value?c:\"\")+(a.disabled?\" \"+r:\"\")+'\">'+a.innerHTML+\"</dd>\"))}),i.join(\"\")}(s.find(\"*\"))+\"</dl>\",\"</div>\"].join(\"\"));u[0]&&u.remove(),s.after(v),o.call(this,v,d)})},checkbox:function(){var e={checkbox:[\"layui-form-checkbox\",\"layui-form-checked\",\"checkbox\"],_switch:[\"layui-form-switch\",\"layui-form-onswitch\",\"switch\"]},a=i(s).find(\"input[type=checkbox]\"),t=function(e,a){var t=i(this);e.on(\"click\",function(){var i=t.attr(\"lay-filter\");t[0].disabled||(t[0].checked?(t[0].checked=!1,e.removeClass(a[1])):(t[0].checked=!0,e.addClass(a[1])),layui.event(l,a[2]+\"(\"+i+\")\",{elem:t[0],value:t[0].value}))})};a.each(function(a,n){var l=i(this),s=l.attr(\"lay-skin\"),c=this.disabled;\"switch\"===s&&(s=\"_\"+s);var u=e[s]||e.checkbox,o=l.next(\".\"+u[0]),d=i(['<div class=\"layui-unselect '+u[0]+(n.checked?\" \"+u[1]:\"\")+(c?\" layui-checkbox-disbaled \"+r:\"\")+'\">',{_switch:\"<i></i>\"}[s]||\"<span>\"+(n.title||\"勾选\")+'</span><i class=\"layui-icon\">&#xe618;</i>',\"</div>\"].join(\"\"));o[0]&&o.remove(),l.after(d),t.call(this,d,u)})},radio:function(){var e=\"layui-form-radio\",a=[\"&#xe643;\",\"&#xe63f;\"],t=i(s).find(\"input[type=radio]\"),n=function(t){var n=i(this),c=\"layui-anim-scaleSpring\";t.on(\"click\",function(){var r=n[0].name,u=n.parents(s),o=n.attr(\"lay-filter\"),d=u.find(\"input[name=\"+r.replace(/(\\.|#|\\[|\\])/g,\"\\\\$1\")+\"]\");n[0].disabled||(layui.each(d,function(){var t=i(this).next(\".\"+e);this.checked=!1,t.removeClass(e+\"ed\"),t.find(\".layui-icon\").removeClass(c).html(a[1])}),n[0].checked=!0,t.addClass(e+\"ed\"),t.find(\".layui-icon\").addClass(c).html(a[0]),layui.event(l,\"radio(\"+o+\")\",{elem:n[0],value:n[0].value}))})};t.each(function(t,l){var s=i(this),c=s.next(\".\"+e),u=this.disabled,o=i(['<div class=\"layui-unselect '+e+(l.checked?\" \"+e+\"ed\":\"\")+(u?\" layui-radio-disbaled \"+r:\"\")+'\">','<i class=\"layui-anim layui-icon\">'+a[l.checked?0:1]+\"</i>\",\"<span>\"+(l.title||\"未命名\")+\"</span>\",\"</div>\"].join(\"\"));c[0]&&c.remove(),s.after(o),n.call(this,o)})}};return e?n[e]?n[e]():t.error(\"不支持的\"+e+\"表单渲染\"):layui.each(n,function(e,i){i()}),a};var o=function(){var e=i(this),t=d.config.verify,c=null,r=\"layui-form-danger\",u={},o=e.parents(s),f=o.find(\"*[lay-verify]\"),y=e.parents(\"form\")[0],v=o.find(\"input,select,textarea\"),h=e.attr(\"lay-filter\");return layui.each(f,function(e,l){var s=i(this),u=s.attr(\"lay-verify\"),o=\"\",d=s.val(),f=\"function\"==typeof t[u];if(s.removeClass(r),t[u]&&(f?o=t[u](d,l):!t[u][0].test(d)))return a.msg(o||t[u][1],{icon:5,shift:6}),n.android||n.ios||l.focus(),s.addClass(r),c=!0}),!c&&(layui.each(v,function(e,i){i.name&&(/^checkbox|radio$/.test(i.type)&&!i.checked||(u[i.name]=i.value))}),layui.event.call(this,l,\"submit(\"+h+\")\",{elem:this,form:y,field:u}))},d=new u,f=i(document);d.render(),f.on(\"reset\",s,function(){setTimeout(function(){d.render()},50)}),f.on(\"submit\",s,o).on(\"click\",\"*[lay-submit]\",o),e(l,function(e){return d.set(e)})});"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/plugins/layui/lay/modules/laydate.js",
    "content": "/** layui-v1.0.7 LGPL License By http://www.layui.com */\n ;layui.define(function(e){\"use strict\";var t=window,a={path:\"\",skin:\"default\",format:\"YYYY-MM-DD\",min:\"1900-01-01 00:00:00\",max:\"2099-12-31 23:59:59\",isv:!1,init:!0},n={},s=document,i=\"createElement\",o=\"getElementById\",l=\"getElementsByTagName\",d=[\"laydate_box\",\"laydate_void\",\"laydate_click\",\"LayDateSkin\",\"skins/\",\"/laydate.css\"];t.laydate=function(e){return e=e||{},n.run(e),laydate},laydate.v=\"1.1\",n.trim=function(e){return e=e||\"\",e.replace(/^\\s|\\s$/g,\"\").replace(/\\s+/g,\" \")},n.digit=function(e){return e<10?\"0\"+(0|e):e},n.stopmp=function(e){return e=e||t.event,e.stopPropagation?e.stopPropagation():e.cancelBubble=!0,this},n.each=function(e,t){for(var a=0,n=e.length;a<n&&t(a,e[a])!==!1;a++);},n.hasClass=function(e,t){return e=e||{},new RegExp(\"\\\\b\"+t+\"\\\\b\").test(e.className)},n.addClass=function(e,t){return e=e||{},n.hasClass(e,t)||(e.className+=\" \"+t),e.className=n.trim(e.className),this},n.removeClass=function(e,t){if(e=e||{},n.hasClass(e,t)){var a=new RegExp(\"\\\\b\"+t+\"\\\\b\");e.className=e.className.replace(a,\"\")}return this},n.removeCssAttr=function(e,t){var a=e.style;a.removeProperty?a.removeProperty(t):a.removeAttribute(t)},n.shde=function(e,t){e.style.display=t?\"none\":\"block\"},n.query=function(e){if(e&&1===e.nodeType){if(\"input\"!==e.tagName.toLowerCase())throw new Error(\"选择器elem错误\");return e}var t,e=n.trim(e).split(\" \"),a=s[o](e[0].substr(1));if(a){if(e[1]){if(/^\\./.test(e[1])){var i,d=e[1].substr(1),r=new RegExp(\"\\\\b\"+d+\"\\\\b\");return t=[],i=s.getElementsByClassName?a.getElementsByClassName(d):a[l](\"*\"),n.each(i,function(e,a){r.test(a.className)&&t.push(a)}),t[0]?t:\"\"}return t=a[l](e[1]),t[0]?a[l](e[1]):\"\"}return a}},n.on=function(e,a,s){return e.attachEvent?e.attachEvent(\"on\"+a,function(){s.call(e,t.even)}):e.addEventListener(a,s,!1),n},n.stopMosup=function(e,t){\"mouseup\"!==e&&n.on(t,\"mouseup\",function(e){n.stopmp(e)})},n.run=function(e){var t=(n.query,e.elem);t&&(d.elemv=/textarea|input/.test(t.tagName.toLocaleLowerCase())?\"value\":\"innerHTML\",(\"init\"in e?e.init:a.init)&&!t[d.elemv]&&(t[d.elemv]=laydate.now(null,e.format||a.format)),n.view(t,e),n.reshow())},n.scroll=function(e){return e=e?\"scrollLeft\":\"scrollTop\",s.body[e]|s.documentElement[e]},n.winarea=function(e){return document.documentElement[e?\"clientWidth\":\"clientHeight\"]},n.isleap=function(e){return e%4===0&&e%100!==0||e%400===0},n.checkVoid=function(e,t,a){var s=[];return e=0|e,t=0|t,a=0|a,e<n.mins[0]?s=[\"y\"]:e>n.maxs[0]?s=[\"y\",1]:e>=n.mins[0]&&e<=n.maxs[0]&&(e==n.mins[0]&&(t<n.mins[1]?s=[\"m\"]:t==n.mins[1]&&a<n.mins[2]&&(s=[\"d\"])),e==n.maxs[0]&&(t>n.maxs[1]?s=[\"m\",1]:t==n.maxs[1]&&a>n.maxs[2]&&(s=[\"d\",1]))),s},n.timeVoid=function(e,t){if(n.ymd[1]+1==n.mins[1]&&n.ymd[2]==n.mins[2]){if(0===t&&e<n.mins[3])return 1;if(1===t&&e<n.mins[4])return 1;if(2===t&&e<n.mins[5])return 1}else if(n.ymd[1]+1==n.maxs[1]&&n.ymd[2]==n.maxs[2]){if(0===t&&e>n.maxs[3])return 1;if(1===t&&e>n.maxs[4])return 1;if(2===t&&e>n.maxs[5])return 1}if(e>(t?59:23))return 1},n.check=function(){var e=n.options.format.replace(/YYYY|MM|DD|hh|mm|ss/g,\"\\\\d+\\\\\").replace(/\\\\$/g,\"\"),t=new RegExp(e),a=n.elem[d.elemv],s=a.match(/\\d+/g)||[],i=n.checkVoid(s[0],s[1],s[2]);if(\"\"!==a.replace(/\\s/g,\"\")){if(!t.test(a))return n.elem[d.elemv]=\"\",n.msg(\"日期不符合格式，请重新选择。\"),1;if(i[0])return n.elem[d.elemv]=\"\",n.msg(\"日期不在有效期内，请重新选择。\"),1;i.value=n.elem[d.elemv].match(t).join(),s=i.value.match(/\\d+/g),s[1]<1?(s[1]=1,i.auto=1):s[1]>12?(s[1]=12,i.auto=1):s[1].length<2&&(i.auto=1),s[2]<1?(s[2]=1,i.auto=1):s[2]>n.months[(0|s[1])-1]?(s[2]=31,i.auto=1):s[2].length<2&&(i.auto=1),s.length>3&&(n.timeVoid(s[3],0)&&(i.auto=1),n.timeVoid(s[4],1)&&(i.auto=1),n.timeVoid(s[5],2)&&(i.auto=1)),i.auto?n.creation([s[0],0|s[1],0|s[2]],1):i.value!==n.elem[d.elemv]&&(n.elem[d.elemv]=i.value)}},n.months=[31,null,31,30,31,30,31,31,30,31,30,31],n.viewDate=function(e,t,a){var s=(n.query,{}),i=new Date;e<(0|n.mins[0])&&(e=0|n.mins[0]),e>(0|n.maxs[0])&&(e=0|n.maxs[0]),i.setFullYear(e,t,a),s.ymd=[i.getFullYear(),i.getMonth(),i.getDate()],n.months[1]=n.isleap(s.ymd[0])?29:28,i.setFullYear(s.ymd[0],s.ymd[1],1),s.FDay=i.getDay(),s.PDay=n.months[0===t?11:t-1]-s.FDay+1,s.NDay=1,n.each(d.tds,function(e,t){var a,i=s.ymd[0],o=s.ymd[1]+1;t.className=\"\",e<s.FDay?(t.innerHTML=a=e+s.PDay,n.addClass(t,\"laydate_nothis\"),1===o&&(i-=1),o=1===o?12:o-1):e>=s.FDay&&e<s.FDay+n.months[s.ymd[1]]?(t.innerHTML=a=e-s.FDay+1,e-s.FDay+1===s.ymd[2]&&(n.addClass(t,d[2]),s.thisDay=t)):(t.innerHTML=a=s.NDay++,n.addClass(t,\"laydate_nothis\"),12===o&&(i+=1),o=12===o?1:o+1),n.checkVoid(i,o,a)[0]&&n.addClass(t,d[1]),n.options.festival&&n.festival(t,o+\".\"+a),t.setAttribute(\"y\",i),t.setAttribute(\"m\",o),t.setAttribute(\"d\",a),i=o=a=null}),n.valid=!n.hasClass(s.thisDay,d[1]),n.ymd=s.ymd,d.year.value=n.ymd[0]+\"年\",d.month.value=n.digit(n.ymd[1]+1)+\"月\",n.each(d.mms,function(e,t){var a=n.checkVoid(n.ymd[0],(0|t.getAttribute(\"m\"))+1);\"y\"===a[0]||\"m\"===a[0]?n.addClass(t,d[1]):n.removeClass(t,d[1]),n.removeClass(t,d[2]),a=null}),n.addClass(d.mms[n.ymd[1]],d[2]),s.times=[0|n.inymd[3]||0,0|n.inymd[4]||0,0|n.inymd[5]||0],n.each(new Array(3),function(e){n.hmsin[e].value=n.digit(n.timeVoid(s.times[e],e)?0|n.mins[e+3]:0|s.times[e])}),n[n.valid?\"removeClass\":\"addClass\"](d.ok,d[1])},n.festival=function(e,t){var a;switch(t){case\"1.1\":a=\"元旦\";break;case\"3.8\":a=\"妇女\";break;case\"4.5\":a=\"清明\";break;case\"5.1\":a=\"劳动\";break;case\"6.1\":a=\"儿童\";break;case\"9.10\":a=\"教师\";break;case\"10.1\":a=\"国庆\"}a&&(e.innerHTML=a),a=null},n.viewYears=function(e){var t=n.query,a=\"\";n.each(new Array(14),function(t){a+=7===t?\"<li \"+(parseInt(d.year.value)===e?'class=\"'+d[2]+'\"':\"\")+' y=\"'+e+'\">'+e+\"年</li>\":'<li y=\"'+(e-7+t)+'\">'+(e-7+t)+\"年</li>\"}),t(\"#laydate_ys\").innerHTML=a,n.each(t(\"#laydate_ys li\"),function(e,t){\"y\"===n.checkVoid(t.getAttribute(\"y\"))[0]?n.addClass(t,d[1]):n.on(t,\"click\",function(e){n.stopmp(e).reshow(),n.viewDate(0|this.getAttribute(\"y\"),n.ymd[1],n.ymd[2])})})},n.initDate=function(){var e=(n.query,new Date),t=n.elem[d.elemv].match(/\\d+/g)||[];t.length<3&&(t=n.options.start.match(/\\d+/g)||[],t.length<3&&(t=[e.getFullYear(),e.getMonth()+1,e.getDate()])),n.inymd=t,n.viewDate(t[0],t[1]-1,t[2])},n.iswrite=function(){var e=n.query,t={time:e(\"#laydate_hms\")};n.shde(t.time,!n.options.istime),n.shde(d.oclear,!(\"isclear\"in n.options?n.options.isclear:1)),n.shde(d.otoday,!(\"istoday\"in n.options?n.options.istoday:1)),n.shde(d.ok,!(\"issure\"in n.options?n.options.issure:1))},n.orien=function(e,t){var a,s=n.elem.getBoundingClientRect();e.style.left=s.left+(t?0:n.scroll(1))+\"px\",a=s.bottom+e.offsetHeight/1.5<=n.winarea()?s.bottom-1:s.top>e.offsetHeight/1.5?s.top-e.offsetHeight+1:n.winarea()-e.offsetHeight,e.style.top=Math.max(a+(t?0:n.scroll()),1)+\"px\"},n.follow=function(e){n.options.fixed?(e.style.position=\"fixed\",n.orien(e,1)):(e.style.position=\"absolute\",n.orien(e))},n.viewtb=function(){var e,t=[],a=[\"日\",\"一\",\"二\",\"三\",\"四\",\"五\",\"六\"],o={},d=s[i](\"table\"),r=s[i](\"thead\");return r.appendChild(s[i](\"tr\")),o.creath=function(e){var t=s[i](\"th\");t.innerHTML=a[e],r[l](\"tr\")[0].appendChild(t),t=null},n.each(new Array(6),function(a){t.push([]),e=d.insertRow(0),n.each(new Array(7),function(n){t[a][n]=0,0===a&&o.creath(n),e.insertCell(n)})}),d.insertBefore(r,d.children[0]),d.id=d.className=\"laydate_table\",e=t=null,d.outerHTML.toLowerCase()}(),n.view=function(e,t){var o,l=n.query,r={};t=t||e,n.elem=e,n.options=t,n.options.format||(n.options.format=a.format),n.options.start=n.options.start||\"\",n.mm=r.mm=[n.options.min||a.min,n.options.max||a.max],n.mins=r.mm[0].match(/\\d+/g),n.maxs=r.mm[1].match(/\\d+/g),n.box?n.shde(n.box):(o=s[i](\"div\"),o.id=d[0],o.className=d[0],o.style.cssText=\"position: absolute;\",o.setAttribute(\"name\",\"laydate-v\"+laydate.v),o.innerHTML=r.html='<div class=\"laydate_top\"><div class=\"laydate_ym laydate_y\" id=\"laydate_YY\"><a class=\"laydate_choose laydate_chprev laydate_tab\"><cite></cite></a><input id=\"laydate_y\" readonly><label></label><a class=\"laydate_choose laydate_chnext laydate_tab\"><cite></cite></a><div class=\"laydate_yms\"><a class=\"laydate_tab laydate_chtop\"><cite></cite></a><ul id=\"laydate_ys\"></ul><a class=\"laydate_tab laydate_chdown\"><cite></cite></a></div></div><div class=\"laydate_ym laydate_m\" id=\"laydate_MM\"><a class=\"laydate_choose laydate_chprev laydate_tab\"><cite></cite></a><input id=\"laydate_m\" readonly><label></label><a class=\"laydate_choose laydate_chnext laydate_tab\"><cite></cite></a><div class=\"laydate_yms\" id=\"laydate_ms\">'+function(){var e=\"\";return n.each(new Array(12),function(t){e+='<span m=\"'+t+'\">'+n.digit(t+1)+\"月</span>\"}),e}()+\"</div></div></div>\"+n.viewtb+'<div class=\"laydate_bottom\"><ul id=\"laydate_hms\"><li class=\"laydate_sj\">时间</li><li><input readonly>:</li><li><input readonly>:</li><li><input readonly></li></ul><div class=\"laydate_time\" id=\"laydate_time\"></div><div class=\"laydate_btn\"><a id=\"laydate_clear\">清空</a><a id=\"laydate_today\">今天</a><a id=\"laydate_ok\">确认</a></div>'+(a.isv?'<a href=\"http://sentsin.com/layui/laydate/\" class=\"laydate_v\" target=\"_blank\">laydate-v'+laydate.v+\"</a>\":\"\")+\"</div>\",s.body.appendChild(o),n.box=l(\"#\"+d[0]),n.events(),o=null),n.follow(n.box),t.zIndex?n.box.style.zIndex=t.zIndex:n.removeCssAttr(n.box,\"z-index\"),n.stopMosup(\"click\",n.box),n.initDate(),n.iswrite(),n.check()},n.reshow=function(){return n.each(n.query(\"#\"+d[0]+\" .laydate_show\"),function(e,t){n.removeClass(t,\"laydate_show\")}),this},n.close=function(){n.reshow(),n.shde(n.query(\"#\"+d[0]),1),n.elem=null},n.parse=function(e,t,s){return e=e.concat(t),s=s||(n.options?n.options.format:a.format),s.replace(/YYYY|MM|DD|hh|mm|ss/g,function(t,a){return e.index=0|++e.index,n.digit(e[e.index])})},n.creation=function(e,t){var a=(n.query,n.hmsin),s=n.parse(e,[a[0].value,a[1].value,a[2].value]);n.elem[d.elemv]=s,t||(n.close(),\"function\"==typeof n.options.choose&&n.options.choose(s))},n.events=function(){var e=n.query,a={box:\"#\"+d[0]};n.addClass(s.body,\"laydate_body\"),d.tds=e(\"#laydate_table td\"),d.mms=e(\"#laydate_ms span\"),d.year=e(\"#laydate_y\"),d.month=e(\"#laydate_m\"),n.each(e(a.box+\" .laydate_ym\"),function(e,t){n.on(t,\"click\",function(t){n.stopmp(t).reshow(),n.addClass(this[l](\"div\")[0],\"laydate_show\"),e||(a.YY=parseInt(d.year.value),n.viewYears(a.YY))})}),n.on(e(a.box),\"click\",function(){n.reshow()}),a.tabYear=function(e){0===e?n.ymd[0]--:1===e?n.ymd[0]++:2===e?a.YY-=14:a.YY+=14,e<2?(n.viewDate(n.ymd[0],n.ymd[1],n.ymd[2]),n.reshow()):n.viewYears(a.YY)},n.each(e(\"#laydate_YY .laydate_tab\"),function(e,t){n.on(t,\"click\",function(t){n.stopmp(t),a.tabYear(e)})}),a.tabMonth=function(e){e?(n.ymd[1]++,12===n.ymd[1]&&(n.ymd[0]++,n.ymd[1]=0)):(n.ymd[1]--,n.ymd[1]===-1&&(n.ymd[0]--,n.ymd[1]=11)),n.viewDate(n.ymd[0],n.ymd[1],n.ymd[2])},n.each(e(\"#laydate_MM .laydate_tab\"),function(e,t){n.on(t,\"click\",function(t){n.stopmp(t).reshow(),a.tabMonth(e)})}),n.each(e(\"#laydate_ms span\"),function(e,t){n.on(t,\"click\",function(e){n.stopmp(e).reshow(),n.hasClass(this,d[1])||n.viewDate(n.ymd[0],0|this.getAttribute(\"m\"),n.ymd[2])})}),n.each(e(\"#laydate_table td\"),function(e,t){n.on(t,\"click\",function(e){n.hasClass(this,d[1])||(n.stopmp(e),n.creation([0|this.getAttribute(\"y\"),0|this.getAttribute(\"m\"),0|this.getAttribute(\"d\")]))})}),d.oclear=e(\"#laydate_clear\"),n.on(d.oclear,\"click\",function(){n.elem[d.elemv]=\"\",n.close()}),d.otoday=e(\"#laydate_today\"),n.on(d.otoday,\"click\",function(){var e=new Date;n.creation([e.getFullYear(),e.getMonth()+1,e.getDate()])}),d.ok=e(\"#laydate_ok\"),n.on(d.ok,\"click\",function(){n.valid&&n.creation([n.ymd[0],n.ymd[1]+1,n.ymd[2]])}),a.times=e(\"#laydate_time\"),n.hmsin=a.hmsin=e(\"#laydate_hms input\"),a.hmss=[\"小时\",\"分钟\",\"秒数\"],a.hmsarr=[],n.msg=function(t,s){var i='<div class=\"laydte_hsmtex\">'+(s||\"提示\")+\"<span>×</span></div>\";\"string\"==typeof t?(i+=\"<p>\"+t+\"</p>\",n.shde(e(\"#\"+d[0])),n.removeClass(a.times,\"laydate_time1\").addClass(a.times,\"laydate_msg\")):(a.hmsarr[t]?i=a.hmsarr[t]:(i+='<div id=\"laydate_hmsno\" class=\"laydate_hmsno\">',n.each(new Array(0===t?24:60),function(e){i+=\"<span>\"+e+\"</span>\"}),i+=\"</div>\",a.hmsarr[t]=i),n.removeClass(a.times,\"laydate_msg\"),n[0===t?\"removeClass\":\"addClass\"](a.times,\"laydate_time1\")),n.addClass(a.times,\"laydate_show\"),a.times.innerHTML=i},a.hmson=function(t,a){var s=e(\"#laydate_hmsno span\"),i=n.valid?null:1;n.each(s,function(e,s){i?n.addClass(s,d[1]):n.timeVoid(e,a)?n.addClass(s,d[1]):n.on(s,\"click\",function(e){n.hasClass(this,d[1])||(t.value=n.digit(0|this.innerHTML))})}),n.addClass(s[0|t.value],\"laydate_click\")},n.each(a.hmsin,function(e,t){n.on(t,\"click\",function(t){n.stopmp(t).reshow(),n.msg(e,a.hmss[e]),a.hmson(this,e)})}),n.on(s,\"mouseup\",function(){var t=e(\"#\"+d[0]);t&&\"none\"!==t.style.display&&(n.check()||n.close())}).on(s,\"keydown\",function(e){e=e||t.event;var a=e.keyCode;13===a&&n.elem&&n.creation([n.ymd[0],n.ymd[1]+1,n.ymd[2]])})},laydate.reset=function(){n.box&&n.elem&&n.follow(n.box)},laydate.now=function(e,t){var a=new Date(0|e?function(e){return e<864e5?+new Date+864e5*e:e}(parseInt(e)):+new Date);return n.parse([a.getFullYear(),a.getMonth()+1,a.getDate()],[a.getHours(),a.getMinutes(),a.getSeconds()],t)},layui.addcss(\"modules/laydate/laydate.css\",function(){},\"laydatecss\"),e(\"laydate\",laydate)});"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/plugins/layui/lay/modules/layedit.js",
    "content": "/** layui-v1.0.7 LGPL License By http://www.layui.com */\n ;layui.define([\"layer\",\"form\"],function(t){\"use strict\";var e=layui.jquery,i=layui.layer,a=layui.form(),l=(layui.hint(),layui.device()),n=\"layedit\",o=\"layui-show\",r=\"layui-disabled\",s=function(){var t=this;t.index=0,t.config={tool:[\"strong\",\"italic\",\"underline\",\"del\",\"|\",\"left\",\"center\",\"right\",\"|\",\"link\",\"unlink\",\"face\",\"image\"],hideTool:[],height:280}};s.prototype.set=function(t){var i=this;return e.extend(!0,i.config,t),i},s.prototype.on=function(t,e){return layui.onevent(n,t,e)},s.prototype.build=function(t,i){i=i||{};var a=this,n=a.config,r=\"layui-layedit\",s=e(\"#\"+t),u=\"LAY_layedit_\"+ ++a.index,d=s.next(\".\"+r),y=e.extend({},n,i),f=function(){var t=[],e={};return layui.each(y.hideTool,function(t,i){e[i]=!0}),layui.each(y.tool,function(i,a){C[a]&&!e[a]&&t.push(C[a])}),t.join(\"\")}(),m=e(['<div class=\"'+r+'\">','<div class=\"layui-unselect layui-layedit-tool\">'+f+\"</div>\",'<div class=\"layui-layedit-iframe\">','<iframe id=\"'+u+'\" name=\"'+u+'\" textarea=\"'+t+'\" frameborder=\"0\"></iframe>',\"</div>\",\"</div>\"].join(\"\"));return l.ie&&l.ie<8?s.removeClass(\"layui-hide\").addClass(o):(d[0]&&d.remove(),c.call(a,m,s[0],y),s.addClass(\"layui-hide\").after(m),a.index)},s.prototype.getContent=function(t){var e=u(t);if(e[0])return d(e[0].document.body.innerHTML)},s.prototype.getText=function(t){var i=u(t);if(i[0])return e(i[0].document.body).text()},s.prototype.sync=function(t){var i=u(t);if(i[0]){var a=e(\"#\"+i[1].attr(\"textarea\"));a.val(d(i[0].document.body.innerHTML))}},s.prototype.getSelection=function(t){var e=u(t);if(e[0]){var i=m(e[0].document);return document.selection?i.text:i.toString()}};var c=function(t,i,a){var l=this,n=t.find(\"iframe\");n.css({height:a.height}).on(\"load\",function(){var o=n.contents(),r=n.prop(\"contentWindow\"),s=o.find(\"head\"),c=e([\"<style>\",\"*{margin: 0; padding: 0;}\",\"body{padding: 10px; line-height: 20px; overflow-x: hidden; word-wrap: break-word; font: 14px Helvetica Neue,Helvetica,PingFang SC,Microsoft YaHei,Tahoma,Arial,sans-serif; -webkit-box-sizing: border-box !important; -moz-box-sizing: border-box !important; box-sizing: border-box !important;}\",\"a{color:#01AAED; text-decoration:none;}a:hover{color:#c00}\",\"p{margin-bottom: 10px;}\",\"img{display: inline-block; border: none; vertical-align: middle;}\",\"pre{margin: 10px 0; padding: 10px; line-height: 20px; border: 1px solid #ddd; border-left-width: 6px; background-color: #F2F2F2; color: #333; font-family: Courier New; font-size: 12px;}\",\"</style>\"].join(\"\")),u=o.find(\"body\");s.append(c),u.attr(\"contenteditable\",\"true\").css({\"min-height\":a.height}).html(i.value||\"\"),y.apply(l,[r,n,i,a]),g.call(l,r,t,a)})},u=function(t){var i=e(\"#LAY_layedit_\"+t),a=i.prop(\"contentWindow\");return[a,i]},d=function(t){return 8==l.ie&&(t=t.replace(/<.+>/g,function(t){return t.toLowerCase()})),t},y=function(t,a,n,o){var r=t.document,s=e(r.body);s.on(\"keydown\",function(t){var e=t.keyCode;if(13===e){var a=m(r),l=p(a),n=l.parentNode;if(\"pre\"===n.tagName.toLowerCase()){if(t.shiftKey)return;return i.msg(\"请暂时用shift+enter\"),!1}r.execCommand(\"formatBlock\",!1,\"<p>\")}}),e(n).parents(\"form\").on(\"submit\",function(){var t=s.html();8==l.ie&&(t=t.replace(/<.+>/g,function(t){return t.toLowerCase()})),n.value=t}),s.on(\"paste\",function(e){r.execCommand(\"formatBlock\",!1,\"<p>\"),setTimeout(function(){f.call(t,s),n.value=s.html()},100)})},f=function(t){var i=this;i.document;t.find(\"*[style]\").each(function(){var t=this.style.textAlign;this.removeAttribute(\"style\"),e(this).css({\"text-align\":t||\"\"})}),t.find(\"table\").addClass(\"layui-table\"),t.find(\"script,link\").remove()},m=function(t){return t.selection?t.selection.createRange():t.getSelection().getRangeAt(0)},p=function(t){return t.endContainer||t.parentElement().childNodes[0]},v=function(t,i,a){var l=this.document,n=document.createElement(t);for(var o in i)n.setAttribute(o,i[o]);if(n.removeAttribute(\"text\"),l.selection){var r=a.text||i.text;if(\"a\"===t&&!r)return;r&&(n.innerHTML=r),a.pasteHTML(e(n).prop(\"outerHTML\")),a.select()}else{var r=a.toString()||i.text;if(\"a\"===t&&!r)return;r&&(n.innerHTML=r),a.deleteContents(),a.insertNode(n)}},h=function(t,i){var a=this.document,l=\"layedit-tool-active\",n=p(m(a)),o=function(e){return t.find(\".layedit-tool-\"+e)};i&&i[i.hasClass(l)?\"removeClass\":\"addClass\"](l),t.find(\">i\").removeClass(l),o(\"unlink\").addClass(r),e(n).parents().each(function(){var t=this.tagName.toLowerCase(),e=this.style.textAlign;\"b\"!==t&&\"strong\"!==t||o(\"b\").addClass(l),\"i\"!==t&&\"em\"!==t||o(\"i\").addClass(l),\"u\"===t&&o(\"u\").addClass(l),\"strike\"===t&&o(\"d\").addClass(l),\"p\"===t&&(\"center\"===e?o(\"center\").addClass(l):\"right\"===e?o(\"right\").addClass(l):o(\"left\").addClass(l)),\"a\"===t&&(o(\"link\").addClass(l),o(\"unlink\").removeClass(r))})},g=function(t,a,l){var n=t.document,o=e(n.body),s={link:function(i){var a=p(i),l=e(a).parent();b.call(o,{href:l.attr(\"href\"),target:l.attr(\"target\")},function(e){var a=l[0];\"A\"===a.tagName?a.href=e.url:v.call(t,\"a\",{target:e.target,href:e.url,text:e.url},i)})},unlink:function(t){n.execCommand(\"unlink\")},face:function(e){x.call(this,function(i){v.call(t,\"img\",{src:i.src,alt:i.alt},e)})},image:function(a){var n=this;layui.use(\"upload\",function(o){var r=l.uploadImage||{};o({url:r.url,method:r.type,elem:e(n).find(\"input\")[0],unwrap:!0,success:function(e){0==e.code?(e.data=e.data||{},v.call(t,\"img\",{src:e.data.src,alt:e.data.title},a)):i.msg(e.msg||\"上传失败\")}})})},code:function(e){k.call(o,function(i){v.call(t,\"pre\",{text:i.code,\"lay-lang\":i.lang},e)})},help:function(){i.open({type:2,title:\"帮助\",area:[\"600px\",\"380px\"],shadeClose:!0,shade:.1,skin:\"layui-layer-msg\",content:[\"http://www.layui.com/about/layedit/help.html\",\"no\"]})}},c=a.find(\".layui-layedit-tool\"),u=function(){var i=e(this),a=i.attr(\"layedit-event\"),l=i.attr(\"lay-command\");if(!i.hasClass(r)){o.focus();var u=m(n);u.commonAncestorContainer;l?(n.execCommand(l),/justifyLeft|justifyCenter|justifyRight/.test(l)&&n.execCommand(\"formatBlock\",!1,\"<p>\"),setTimeout(function(){o.focus()},10)):s[a]&&s[a].call(this,u),h.call(t,c,i)}},d=/image/;c.find(\">i\").on(\"mousedown\",function(){var t=e(this),i=t.attr(\"layedit-event\");d.test(i)||u.call(this)}).on(\"click\",function(){var t=e(this),i=t.attr(\"layedit-event\");d.test(i)&&u.call(this)}),o.on(\"click\",function(){h.call(t,c),i.close(x.index)})},b=function(t,e){var l=this,n=i.open({type:1,id:\"LAY_layedit_link\",area:\"350px\",shade:.05,shadeClose:!0,moveType:1,title:\"超链接\",skin:\"layui-layer-msg\",content:['<ul class=\"layui-form\" style=\"margin: 15px;\">','<li class=\"layui-form-item\">','<label class=\"layui-form-label\" style=\"width: 60px;\">URL</label>','<div class=\"layui-input-block\" style=\"margin-left: 90px\">','<input name=\"url\" lay-verify=\"url\" value=\"'+(t.href||\"\")+'\" autofocus=\"true\" autocomplete=\"off\" class=\"layui-input\">',\"</div>\",\"</li>\",'<li class=\"layui-form-item\">','<label class=\"layui-form-label\" style=\"width: 60px;\">打开方式</label>','<div class=\"layui-input-block\" style=\"margin-left: 90px\">','<input type=\"radio\" name=\"target\" value=\"_self\" class=\"layui-input\" title=\"当前窗口\"'+(\"_self\"!==t.target&&t.target?\"\":\"checked\")+\">\",'<input type=\"radio\" name=\"target\" value=\"_blank\" class=\"layui-input\" title=\"新窗口\" '+(\"_blank\"===t.target?\"checked\":\"\")+\">\",\"</div>\",\"</li>\",'<li class=\"layui-form-item\" style=\"text-align: center;\">','<button type=\"button\" lay-submit lay-filter=\"layedit-link-yes\" class=\"layui-btn\"> 确定 </button>','<button style=\"margin-left: 20px;\" type=\"button\" class=\"layui-btn layui-btn-primary\"> 取消 </button>',\"</li>\",\"</ul>\"].join(\"\"),success:function(t,n){var o=\"submit(layedit-link-yes)\";a.render(\"radio\"),t.find(\".layui-btn-primary\").on(\"click\",function(){i.close(n),l.focus()}),a.on(o,function(t){i.close(b.index),e&&e(t.field)})}});b.index=n},x=function(t){var a=function(){var t=[\"[微笑]\",\"[嘻嘻]\",\"[哈哈]\",\"[可爱]\",\"[可怜]\",\"[挖鼻]\",\"[吃惊]\",\"[害羞]\",\"[挤眼]\",\"[闭嘴]\",\"[鄙视]\",\"[爱你]\",\"[泪]\",\"[偷笑]\",\"[亲亲]\",\"[生病]\",\"[太开心]\",\"[白眼]\",\"[右哼哼]\",\"[左哼哼]\",\"[嘘]\",\"[衰]\",\"[委屈]\",\"[吐]\",\"[哈欠]\",\"[抱抱]\",\"[怒]\",\"[疑问]\",\"[馋嘴]\",\"[拜拜]\",\"[思考]\",\"[汗]\",\"[困]\",\"[睡]\",\"[钱]\",\"[失望]\",\"[酷]\",\"[色]\",\"[哼]\",\"[鼓掌]\",\"[晕]\",\"[悲伤]\",\"[抓狂]\",\"[黑线]\",\"[阴险]\",\"[怒骂]\",\"[互粉]\",\"[心]\",\"[伤心]\",\"[猪头]\",\"[熊猫]\",\"[兔子]\",\"[ok]\",\"[耶]\",\"[good]\",\"[NO]\",\"[赞]\",\"[来]\",\"[弱]\",\"[草泥马]\",\"[神马]\",\"[囧]\",\"[浮云]\",\"[给力]\",\"[围观]\",\"[威武]\",\"[奥特曼]\",\"[礼物]\",\"[钟]\",\"[话筒]\",\"[蜡烛]\",\"[蛋糕]\"],e={};return layui.each(t,function(t,i){e[i]=layui.cache.dir+\"images/face/\"+t+\".gif\"}),e}();return x.hide=x.hide||function(t){\"face\"!==e(t.target).attr(\"layedit-event\")&&i.close(x.index)},x.index=i.tips(function(){var t=[];return layui.each(a,function(e,i){t.push('<li title=\"'+e+'\"><img src=\"'+i+'\" alt=\"'+e+'\"></li>')}),'<ul class=\"layui-clear\">'+t.join(\"\")+\"</ul>\"}(),this,{tips:1,time:0,skin:\"layui-box layui-util-face\",maxWidth:500,success:function(l,n){l.css({marginTop:-4,marginLeft:-10}).find(\".layui-clear>li\").on(\"click\",function(){t&&t({src:a[this.title],alt:this.title}),i.close(n)}),e(document).off(\"click\",x.hide).on(\"click\",x.hide)}})},k=function(t){var e=this,l=i.open({type:1,id:\"LAY_layedit_code\",area:\"550px\",shade:.05,shadeClose:!0,moveType:1,title:\"插入代码\",skin:\"layui-layer-msg\",content:['<ul class=\"layui-form layui-form-pane\" style=\"margin: 15px;\">','<li class=\"layui-form-item\">','<label class=\"layui-form-label\">请选择语言</label>','<div class=\"layui-input-block\">','<select name=\"lang\">','<option value=\"JavaScript\">JavaScript</option>','<option value=\"HTML\">HTML</option>','<option value=\"CSS\">CSS</option>','<option value=\"Java\">Java</option>','<option value=\"PHP\">PHP</option>','<option value=\"C#\">C#</option>','<option value=\"Python\">Python</option>','<option value=\"Ruby\">Ruby</option>','<option value=\"Go\">Go</option>',\"</select>\",\"</div>\",\"</li>\",'<li class=\"layui-form-item layui-form-text\">','<label class=\"layui-form-label\">代码</label>','<div class=\"layui-input-block\">','<textarea name=\"code\" lay-verify=\"required\" autofocus=\"true\" class=\"layui-textarea\" style=\"height: 200px;\"></textarea>',\"</div>\",\"</li>\",'<li class=\"layui-form-item\" style=\"text-align: center;\">','<button type=\"button\" lay-submit lay-filter=\"layedit-code-yes\" class=\"layui-btn\"> 确定 </button>','<button style=\"margin-left: 20px;\" type=\"button\" class=\"layui-btn layui-btn-primary\"> 取消 </button>',\"</li>\",\"</ul>\"].join(\"\"),success:function(l,n){var o=\"submit(layedit-code-yes)\";a.render(\"select\"),l.find(\".layui-btn-primary\").on(\"click\",function(){i.close(n),e.focus()}),a.on(o,function(e){i.close(k.index),t&&t(e.field)})}});k.index=l},C={html:'<i class=\"layui-icon layedit-tool-html\" title=\"HTML源代码\" lay-command=\"html\" layedit-event=\"html\"\">&#xe64b;</i><span class=\"layedit-tool-mid\"></span>',strong:'<i class=\"layui-icon layedit-tool-b\" title=\"加粗\" lay-command=\"Bold\" layedit-event=\"b\"\">&#xe62b;</i>',italic:'<i class=\"layui-icon layedit-tool-i\" title=\"斜体\" lay-command=\"italic\" layedit-event=\"i\"\">&#xe644;</i>',underline:'<i class=\"layui-icon layedit-tool-u\" title=\"下划线\" lay-command=\"underline\" layedit-event=\"u\"\">&#xe646;</i>',del:'<i class=\"layui-icon layedit-tool-d\" title=\"删除线\" lay-command=\"strikeThrough\" layedit-event=\"d\"\">&#xe64f;</i>',\"|\":'<span class=\"layedit-tool-mid\"></span>',left:'<i class=\"layui-icon layedit-tool-left\" title=\"左对齐\" lay-command=\"justifyLeft\" layedit-event=\"left\"\">&#xe649;</i>',center:'<i class=\"layui-icon layedit-tool-center\" title=\"居中对齐\" lay-command=\"justifyCenter\" layedit-event=\"center\"\">&#xe647;</i>',right:'<i class=\"layui-icon layedit-tool-right\" title=\"右对齐\" lay-command=\"justifyRight\" layedit-event=\"right\"\">&#xe648;</i>',link:'<i class=\"layui-icon layedit-tool-link\" title=\"插入链接\" layedit-event=\"link\"\">&#xe64c;</i>',unlink:'<i class=\"layui-icon layedit-tool-unlink layui-disabled\" title=\"清除链接\" lay-command=\"unlink\" layedit-event=\"unlink\"\">&#xe64d;</i>',face:'<i class=\"layui-icon layedit-tool-face\" title=\"表情\" layedit-event=\"face\"\">&#xe650;</i>',image:'<i class=\"layui-icon layedit-tool-image\" title=\"图片\" layedit-event=\"image\">&#xe64a;<input type=\"file\" name=\"file\"></i>',code:'<i class=\"layui-icon layedit-tool-code\" title=\"插入代码\" layedit-event=\"code\">&#xe64e;</i>',help:'<i class=\"layui-icon layedit-tool-help\" title=\"帮助\" layedit-event=\"help\">&#xe607;</i>'},w=new s;t(n,w)});"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/plugins/layui/lay/modules/layer.js",
    "content": "/** layui-v1.0.7 LGPL License By http://www.layui.com */\n ;!function(e,t){\"use strict\";var i,n,a=e.layui&&layui.define,o={getPath:function(){var e=document.scripts,t=e[e.length-1],i=t.src;if(!t.getAttribute(\"merge\"))return i.substring(0,i.lastIndexOf(\"/\")+1)}(),config:{},end:{},minIndex:0,minLeft:[],btn:[\"&#x786E;&#x5B9A;\",\"&#x53D6;&#x6D88;\"],type:[\"dialog\",\"page\",\"iframe\",\"loading\",\"tips\"]},r={v:\"3.0.1\",ie:function(){var t=navigator.userAgent.toLowerCase();return!!(e.ActiveXObject||\"ActiveXObject\"in e)&&((t.match(/msie\\s(\\d+)/)||[])[1]||\"11\")}(),index:e.layer&&e.layer.v?1e5:0,path:o.getPath,config:function(e,t){return e=e||{},r.cache=o.config=i.extend({},o.config,e),r.path=o.config.path||r.path,\"string\"==typeof e.extend&&(e.extend=[e.extend]),o.config.path&&r.ready(),e.extend?(a?layui.addcss(\"modules/layer/\"+e.extend):r.link(\"skin/\"+e.extend),this):this},link:function(t,n,a){if(r.path){var o=i(\"head\")[0],l=document.createElement(\"link\");\"string\"==typeof n&&(a=n);var s=(a||t).replace(/\\.|\\//g,\"\"),f=\"layuicss-\"+s,c=0;l.rel=\"stylesheet\",l.href=r.path+t,l.id=f,i(\"#\"+f)[0]||o.appendChild(l),\"function\"==typeof n&&!function d(){return++c>80?e.console&&console.error(\"layer.css: Invalid\"):void(1989===parseInt(i(\"#\"+f).css(\"width\"))?n():setTimeout(d,100))}()}},ready:function(e){var t=\"skinlayercss\",i=\"1110\";return a?layui.addcss(\"modules/layer/default/layer.css?v=\"+r.v+i,e,t):r.link(\"skin/default/layer.css?v=\"+r.v+i,e,t),this},alert:function(e,t,n){var a=\"function\"==typeof t;return a&&(n=t),r.open(i.extend({content:e,yes:n},a?{}:t))},confirm:function(e,t,n,a){var l=\"function\"==typeof t;return l&&(a=n,n=t),r.open(i.extend({content:e,btn:o.btn,yes:n,btn2:a},l?{}:t))},msg:function(e,n,a){var l=\"function\"==typeof n,f=o.config.skin,c=(f?f+\" \"+f+\"-msg\":\"\")||\"layui-layer-msg\",d=s.anim.length-1;return l&&(a=n),r.open(i.extend({content:e,time:3e3,shade:!1,skin:c,title:!1,closeBtn:!1,btn:!1,resize:!1,end:a},l&&!o.config.skin?{skin:c+\" layui-layer-hui\",anim:d}:function(){return n=n||{},(n.icon===-1||n.icon===t&&!o.config.skin)&&(n.skin=c+\" \"+(n.skin||\"layui-layer-hui\")),n}()))},load:function(e,t){return r.open(i.extend({type:3,icon:e||0,resize:!1,shade:.01},t))},tips:function(e,t,n){return r.open(i.extend({type:4,content:[e,t],closeBtn:!1,time:3e3,shade:!1,resize:!1,fixed:!1,maxWidth:210},n))}},l=function(e){var t=this;t.index=++r.index,t.config=i.extend({},t.config,o.config,e),document.body?t.creat():setTimeout(function(){t.creat()},50)};l.pt=l.prototype;var s=[\"layui-layer\",\".layui-layer-title\",\".layui-layer-main\",\".layui-layer-dialog\",\"layui-layer-iframe\",\"layui-layer-content\",\"layui-layer-btn\",\"layui-layer-close\"];s.anim=[\"layer-anim\",\"layer-anim-01\",\"layer-anim-02\",\"layer-anim-03\",\"layer-anim-04\",\"layer-anim-05\",\"layer-anim-06\"],l.pt.config={type:0,shade:.3,fixed:!0,move:s[1],title:\"&#x4FE1;&#x606F;\",offset:\"auto\",area:\"auto\",closeBtn:1,time:0,zIndex:19891014,maxWidth:360,anim:0,icon:-1,moveType:1,resize:!0,scrollbar:!0,tips:2},l.pt.vessel=function(e,t){var n=this,a=n.index,r=n.config,l=r.zIndex+a,f=\"object\"==typeof r.title,c=r.maxmin&&(1===r.type||2===r.type),d=r.title?'<div class=\"layui-layer-title\" style=\"'+(f?r.title[1]:\"\")+'\">'+(f?r.title[0]:r.title)+\"</div>\":\"\";return r.zIndex=l,t([r.shade?'<div class=\"layui-layer-shade\" id=\"layui-layer-shade'+a+'\" times=\"'+a+'\" style=\"'+(\"z-index:\"+(l-1)+\"; background-color:\"+(r.shade[1]||\"#000\")+\"; opacity:\"+(r.shade[0]||r.shade)+\"; filter:alpha(opacity=\"+(100*r.shade[0]||100*r.shade)+\");\")+'\"></div>':\"\",'<div class=\"'+s[0]+(\" layui-layer-\"+o.type[r.type])+(0!=r.type&&2!=r.type||r.shade?\"\":\" layui-layer-border\")+\" \"+(r.skin||\"\")+'\" id=\"'+s[0]+a+'\" type=\"'+o.type[r.type]+'\" times=\"'+a+'\" showtime=\"'+r.time+'\" conType=\"'+(e?\"object\":\"string\")+'\" style=\"z-index: '+l+\"; width:\"+r.area[0]+\";height:\"+r.area[1]+(r.fixed?\"\":\";position:absolute;\")+'\">'+(e&&2!=r.type?\"\":d)+'<div id=\"'+(r.id||\"\")+'\" class=\"layui-layer-content'+(0==r.type&&r.icon!==-1?\" layui-layer-padding\":\"\")+(3==r.type?\" layui-layer-loading\"+r.icon:\"\")+'\">'+(0==r.type&&r.icon!==-1?'<i class=\"layui-layer-ico layui-layer-ico'+r.icon+'\"></i>':\"\")+(1==r.type&&e?\"\":r.content||\"\")+'</div><span class=\"layui-layer-setwin\">'+function(){var e=c?'<a class=\"layui-layer-min\" href=\"javascript:;\"><cite></cite></a><a class=\"layui-layer-ico layui-layer-max\" href=\"javascript:;\"></a>':\"\";return r.closeBtn&&(e+='<a class=\"layui-layer-ico '+s[7]+\" \"+s[7]+(r.title?r.closeBtn:4==r.type?\"1\":\"2\")+'\" href=\"javascript:;\"></a>'),e}()+\"</span>\"+(r.btn?function(){var e=\"\";\"string\"==typeof r.btn&&(r.btn=[r.btn]);for(var t=0,i=r.btn.length;t<i;t++)e+='<a class=\"'+s[6]+t+'\">'+r.btn[t]+\"</a>\";return'<div class=\"'+s[6]+\" layui-layer-btn-\"+(r.btnAlign||\"\")+'\">'+e+\"</div>\"}():\"\")+(r.resize?'<span class=\"layui-layer-resize\"></span>':\"\")+\"</div>\"],d,i('<div class=\"layui-layer-move\"></div>')),n},l.pt.creat=function(){var e=this,t=e.config,a=e.index,l=t.content,f=\"object\"==typeof l,c=i(\"body\");if(!i(\"#\"+t.id)[0]){switch(\"string\"==typeof t.area&&(t.area=\"auto\"===t.area?[\"\",\"\"]:[t.area,\"\"]),t.shift&&(t.anim=t.shift),6==r.ie&&(t.fixed=!1),t.type){case 0:t.btn=\"btn\"in t?t.btn:o.btn[0],r.closeAll(\"dialog\");break;case 2:var l=t.content=f?t.content:[t.content||\"http://layer.layui.com\",\"auto\"];t.content='<iframe scrolling=\"'+(t.content[1]||\"auto\")+'\" allowtransparency=\"true\" id=\"'+s[4]+a+'\" name=\"'+s[4]+a+'\" onload=\"this.className=\\'\\';\" class=\"layui-layer-load\" frameborder=\"0\" src=\"'+t.content[0]+'\"></iframe>';break;case 3:delete t.title,delete t.closeBtn,t.icon===-1&&0===t.icon,r.closeAll(\"loading\");break;case 4:f||(t.content=[t.content,\"body\"]),t.follow=t.content[1],t.content=t.content[0]+'<i class=\"layui-layer-TipsG\"></i>',delete t.title,t.tips=\"object\"==typeof t.tips?t.tips:[t.tips,!0],t.tipsMore||r.closeAll(\"tips\")}e.vessel(f,function(n,r,d){c.append(n[0]),f?function(){2==t.type||4==t.type?function(){i(\"body\").append(n[1])}():function(){l.parents(\".\"+s[0])[0]||(l.data(\"display\",l.css(\"display\")).show().addClass(\"layui-layer-wrap\").wrap(n[1]),i(\"#\"+s[0]+a).find(\".\"+s[5]).before(r))}()}():c.append(n[1]),i(\".layui-layer-move\")[0]||c.append(o.moveElem=d),e.layero=i(\"#\"+s[0]+a),t.scrollbar||s.html.css(\"overflow\",\"hidden\").attr(\"layer-full\",a)}).auto(a),2==t.type&&6==r.ie&&e.layero.find(\"iframe\").attr(\"src\",l[0]),4==t.type?e.tips():e.offset(),t.fixed&&n.on(\"resize\",function(){e.offset(),(/^\\d+%$/.test(t.area[0])||/^\\d+%$/.test(t.area[1]))&&e.auto(a),4==t.type&&e.tips()}),t.time<=0||setTimeout(function(){r.close(e.index)},t.time),e.move().callback(),s.anim[t.anim]&&e.layero.addClass(s.anim[t.anim]).data(\"anim\",!0)}},l.pt.auto=function(e){function t(e){e=l.find(e),e.height(f[1]-c-d-2*(0|parseFloat(e.css(\"padding\"))))}var a=this,o=a.config,l=i(\"#\"+s[0]+e);\"\"===o.area[0]&&o.maxWidth>0&&(r.ie&&r.ie<8&&o.btn&&l.width(l.innerWidth()),l.outerWidth()>o.maxWidth&&l.width(o.maxWidth));var f=[l.innerWidth(),l.innerHeight()],c=l.find(s[1]).outerHeight()||0,d=l.find(\".\"+s[6]).outerHeight()||0;switch(o.type){case 2:t(\"iframe\");break;default:\"\"===o.area[1]?o.fixed&&f[1]>=n.height()&&(f[1]=n.height(),t(\".\"+s[5])):t(\".\"+s[5])}return a},l.pt.offset=function(){var e=this,t=e.config,i=e.layero,a=[i.outerWidth(),i.outerHeight()],o=\"object\"==typeof t.offset;e.offsetTop=(n.height()-a[1])/2,e.offsetLeft=(n.width()-a[0])/2,o?(e.offsetTop=t.offset[0],e.offsetLeft=t.offset[1]||e.offsetLeft):\"auto\"!==t.offset&&(\"t\"===t.offset?e.offsetTop=0:\"r\"===t.offset?e.offsetLeft=n.width()-a[0]:\"b\"===t.offset?e.offsetTop=n.height()-a[1]:\"l\"===t.offset?e.offsetLeft=0:\"lt\"===t.offset?(e.offsetTop=0,e.offsetLeft=0):\"lb\"===t.offset?(e.offsetTop=n.height()-a[1],e.offsetLeft=0):\"rt\"===t.offset?(e.offsetTop=0,e.offsetLeft=n.width()-a[0]):\"rb\"===t.offset?(e.offsetTop=n.height()-a[1],e.offsetLeft=n.width()-a[0]):e.offsetTop=t.offset),t.fixed||(e.offsetTop=/%$/.test(e.offsetTop)?n.height()*parseFloat(e.offsetTop)/100:parseFloat(e.offsetTop),e.offsetLeft=/%$/.test(e.offsetLeft)?n.width()*parseFloat(e.offsetLeft)/100:parseFloat(e.offsetLeft),e.offsetTop+=n.scrollTop(),e.offsetLeft+=n.scrollLeft()),i.attr(\"minLeft\")&&(e.offsetTop=n.height()-(i.find(s[1]).outerHeight()||0),e.offsetLeft=i.css(\"left\")),i.css({top:e.offsetTop,left:e.offsetLeft})},l.pt.tips=function(){var e=this,t=e.config,a=e.layero,o=[a.outerWidth(),a.outerHeight()],r=i(t.follow);r[0]||(r=i(\"body\"));var l={width:r.outerWidth(),height:r.outerHeight(),top:r.offset().top,left:r.offset().left},f=a.find(\".layui-layer-TipsG\"),c=t.tips[0];t.tips[1]||f.remove(),l.autoLeft=function(){l.left+o[0]-n.width()>0?(l.tipLeft=l.left+l.width-o[0],f.css({right:12,left:\"auto\"})):l.tipLeft=l.left},l.where=[function(){l.autoLeft(),l.tipTop=l.top-o[1]-10,f.removeClass(\"layui-layer-TipsB\").addClass(\"layui-layer-TipsT\").css(\"border-right-color\",t.tips[1])},function(){l.tipLeft=l.left+l.width+10,l.tipTop=l.top,f.removeClass(\"layui-layer-TipsL\").addClass(\"layui-layer-TipsR\").css(\"border-bottom-color\",t.tips[1])},function(){l.autoLeft(),l.tipTop=l.top+l.height+10,f.removeClass(\"layui-layer-TipsT\").addClass(\"layui-layer-TipsB\").css(\"border-right-color\",t.tips[1])},function(){l.tipLeft=l.left-o[0]-10,l.tipTop=l.top,f.removeClass(\"layui-layer-TipsR\").addClass(\"layui-layer-TipsL\").css(\"border-bottom-color\",t.tips[1])}],l.where[c-1](),1===c?l.top-(n.scrollTop()+o[1]+16)<0&&l.where[2]():2===c?n.width()-(l.left+l.width+o[0]+16)>0||l.where[3]():3===c?l.top-n.scrollTop()+l.height+o[1]+16-n.height()>0&&l.where[0]():4===c&&o[0]+16-l.left>0&&l.where[1](),a.find(\".\"+s[5]).css({\"background-color\":t.tips[1],\"padding-right\":t.closeBtn?\"30px\":\"\"}),a.css({left:l.tipLeft-(t.fixed?n.scrollLeft():0),top:l.tipTop-(t.fixed?n.scrollTop():0)})},l.pt.move=function(){var e=this,t=e.config,a=i(document),l=e.layero,s=l.find(t.move),f=l.find(\".layui-layer-resize\"),c={};return t.move&&s.css(\"cursor\",\"move\"),s.on(\"mousedown\",function(e){e.preventDefault(),t.move&&(c.moveStart=!0,c.offset=[e.clientX-parseFloat(l.css(\"left\")),e.clientY-parseFloat(l.css(\"top\"))],o.moveElem.css(\"cursor\",\"move\").show())}),f.on(\"mousedown\",function(e){e.preventDefault(),c.resizeStart=!0,c.offset=[e.clientX,e.clientY],c.area=[l.outerWidth(),l.outerHeight()],o.moveElem.css(\"cursor\",\"se-resize\").show()}),a.on(\"mousemove\",function(i){if(c.moveStart){var a=i.clientX-c.offset[0],o=i.clientY-c.offset[1],s=\"fixed\"===l.css(\"position\");if(i.preventDefault(),c.stX=s?0:n.scrollLeft(),c.stY=s?0:n.scrollTop(),!t.moveOut){var f=n.width()-l.outerWidth()+c.stX,d=n.height()-l.outerHeight()+c.stY;a<c.stX&&(a=c.stX),a>f&&(a=f),o<c.stY&&(o=c.stY),o>d&&(o=d)}l.css({left:a,top:o})}if(t.resize&&c.resizeStart){var a=i.clientX-c.offset[0],o=i.clientY-c.offset[1];i.preventDefault(),r.style(e.index,{width:c.area[0]+a,height:c.area[1]+o}),c.isResize=!0}}).on(\"mouseup\",function(e){c.moveStart&&(delete c.moveStart,o.moveElem.hide(),t.moveEnd&&t.moveEnd()),c.resizeStart&&(delete c.resizeStart,o.moveElem.hide())}),e},l.pt.callback=function(){function e(){var e=a.cancel&&a.cancel(t.index,n);e===!1||r.close(t.index)}var t=this,n=t.layero,a=t.config;t.openLayer(),a.success&&(2==a.type?n.find(\"iframe\").on(\"load\",function(){a.success(n,t.index)}):a.success(n,t.index)),6==r.ie&&t.IE6(n),n.find(\".\"+s[6]).children(\"a\").on(\"click\",function(){var e=i(this).index();if(0===e)a.yes?a.yes(t.index,n):a.btn1?a.btn1(t.index,n):r.close(t.index);else{var o=a[\"btn\"+(e+1)]&&a[\"btn\"+(e+1)](t.index,n);o===!1||r.close(t.index)}}),n.find(\".\"+s[7]).on(\"click\",e),a.shadeClose&&i(\"#layui-layer-shade\"+t.index).on(\"click\",function(){r.close(t.index)}),n.find(\".layui-layer-min\").on(\"click\",function(){var e=a.min&&a.min(n);e===!1||r.min(t.index,a)}),n.find(\".layui-layer-max\").on(\"click\",function(){i(this).hasClass(\"layui-layer-maxmin\")?(r.restore(t.index),a.restore&&a.restore(n)):(r.full(t.index,a),setTimeout(function(){a.full&&a.full(n)},100))}),a.end&&(o.end[t.index]=a.end)},o.reselect=function(){i.each(i(\"select\"),function(e,t){var n=i(this);n.parents(\".\"+s[0])[0]||1==n.attr(\"layer\")&&i(\".\"+s[0]).length<1&&n.removeAttr(\"layer\").show(),n=null})},l.pt.IE6=function(e){i(\"select\").each(function(e,t){var n=i(this);n.parents(\".\"+s[0])[0]||\"none\"===n.css(\"display\")||n.attr({layer:\"1\"}).hide(),n=null})},l.pt.openLayer=function(){var e=this;r.zIndex=e.config.zIndex,r.setTop=function(e){var t=function(){r.zIndex++,e.css(\"z-index\",r.zIndex+1)};return r.zIndex=parseInt(e[0].style.zIndex),e.on(\"mousedown\",t),r.zIndex}},o.record=function(e){var t=[e.width(),e.height(),e.position().top,e.position().left+parseFloat(e.css(\"margin-left\"))];e.find(\".layui-layer-max\").addClass(\"layui-layer-maxmin\"),e.attr({area:t})},o.rescollbar=function(e){s.html.attr(\"layer-full\")==e&&(s.html[0].style.removeProperty?s.html[0].style.removeProperty(\"overflow\"):s.html[0].style.removeAttribute(\"overflow\"),s.html.removeAttr(\"layer-full\"))},e.layer=r,r.getChildFrame=function(e,t){return t=t||i(\".\"+s[4]).attr(\"times\"),i(\"#\"+s[0]+t).find(\"iframe\").contents().find(e)},r.getFrameIndex=function(e){return i(\"#\"+e).parents(\".\"+s[4]).attr(\"times\")},r.iframeAuto=function(e){if(e){var t=r.getChildFrame(\"html\",e).outerHeight(),n=i(\"#\"+s[0]+e),a=n.find(s[1]).outerHeight()||0,o=n.find(\".\"+s[6]).outerHeight()||0;n.css({height:t+a+o}),n.find(\"iframe\").css({height:t})}},r.iframeSrc=function(e,t){i(\"#\"+s[0]+e).find(\"iframe\").attr(\"src\",t)},r.style=function(e,t,n){var a=i(\"#\"+s[0]+e),r=a.find(\".layui-layer-content\"),l=a.attr(\"type\"),f=a.find(s[1]).outerHeight()||0,c=a.find(\".\"+s[6]).outerHeight()||0;a.attr(\"minLeft\");l!==o.type[3]&&l!==o.type[4]&&(n||(parseFloat(t.width)<=260&&(t.width=260),parseFloat(t.height)-f-c<=64&&(t.height=64+f+c)),a.css(t),c=a.find(\".\"+s[6]).outerHeight(),l===o.type[2]?a.find(\"iframe\").css({height:parseFloat(t.height)-f-c}):r.css({height:parseFloat(t.height)-f-c-parseFloat(r.css(\"padding-top\"))-parseFloat(r.css(\"padding-bottom\"))}))},r.min=function(e,t){var a=i(\"#\"+s[0]+e),l=a.find(s[1]).outerHeight()||0,f=a.attr(\"minLeft\")||181*o.minIndex+\"px\",c=a.css(\"position\");o.record(a),o.minLeft[0]&&(f=o.minLeft[0],o.minLeft.shift()),a.attr(\"position\",c),r.style(e,{width:180,height:l,left:f,top:n.height()-l,position:\"fixed\",overflow:\"hidden\"},!0),a.find(\".layui-layer-min\").hide(),\"page\"===a.attr(\"type\")&&a.find(s[4]).hide(),o.rescollbar(e),a.attr(\"minLeft\")||o.minIndex++,a.attr(\"minLeft\",f)},r.restore=function(e){var t=i(\"#\"+s[0]+e),n=t.attr(\"area\").split(\",\");t.attr(\"type\");r.style(e,{width:parseFloat(n[0]),height:parseFloat(n[1]),top:parseFloat(n[2]),left:parseFloat(n[3]),position:t.attr(\"position\"),overflow:\"visible\"},!0),t.find(\".layui-layer-max\").removeClass(\"layui-layer-maxmin\"),t.find(\".layui-layer-min\").show(),\"page\"===t.attr(\"type\")&&t.find(s[4]).show(),o.rescollbar(e)},r.full=function(e){var t,a=i(\"#\"+s[0]+e);o.record(a),s.html.attr(\"layer-full\")||s.html.css(\"overflow\",\"hidden\").attr(\"layer-full\",e),clearTimeout(t),t=setTimeout(function(){var t=\"fixed\"===a.css(\"position\");r.style(e,{top:t?0:n.scrollTop(),left:t?0:n.scrollLeft(),width:n.width(),height:n.height()},!0),a.find(\".layui-layer-min\").hide()},100)},r.title=function(e,t){var n=i(\"#\"+s[0]+(t||r.index)).find(s[1]);n.html(e)},r.close=function(e){var t=i(\"#\"+s[0]+e),n=t.attr(\"type\"),a=\"layer-anim-close\";if(t[0]){var l=\"layui-layer-wrap\",f=function(){if(n===o.type[1]&&\"object\"===t.attr(\"conType\")){t.children(\":not(.\"+s[5]+\")\").remove();for(var a=t.find(\".\"+l),r=0;r<2;r++)a.unwrap();a.css(\"display\",a.data(\"display\")).removeClass(l)}else{if(n===o.type[2])try{var f=i(\"#\"+s[4]+e)[0];f.contentWindow.document.write(\"\"),f.contentWindow.close(),t.find(\".\"+s[5])[0].removeChild(f)}catch(c){}t[0].innerHTML=\"\",t.remove()}\"function\"==typeof o.end[e]&&o.end[e](),delete o.end[e]};t.data(\"anim\")&&t.addClass(a),i(\"#layui-layer-moves, #layui-layer-shade\"+e).remove(),6==r.ie&&o.reselect(),o.rescollbar(e),t.attr(\"minLeft\")&&(o.minIndex--,o.minLeft.push(t.attr(\"minLeft\"))),setTimeout(function(){f()},r.ie&&r.ie<10||!t.data(\"anim\")?0:200)}},r.closeAll=function(e){i.each(i(\".\"+s[0]),function(){var t=i(this),n=e?t.attr(\"type\")===e:1;n&&r.close(t.attr(\"times\")),n=null})};var f=r.cache||{},c=function(e){return f.skin?\" \"+f.skin+\" \"+f.skin+\"-\"+e:\"\"};r.prompt=function(e,t){var a=\"\";if(e=e||{},\"function\"==typeof e&&(t=e),e.area){var o=e.area;a='style=\"width: '+o[0]+\"; height: \"+o[1]+';\"',delete e.area}var l,s=2==e.formType?'<textarea class=\"layui-layer-input\"'+a+\">\"+(e.value||\"\")+\"</textarea>\":function(){return'<input type=\"'+(1==e.formType?\"password\":\"text\")+'\" class=\"layui-layer-input\" value=\"'+(e.value||\"\")+'\">'}();return r.open(i.extend({type:1,btn:[\"&#x786E;&#x5B9A;\",\"&#x53D6;&#x6D88;\"],content:s,skin:\"layui-layer-prompt\"+c(\"prompt\"),maxWidth:n.width(),success:function(e){l=e.find(\".layui-layer-input\"),l.focus()},resize:!1,yes:function(i){var n=l.val();\"\"===n?l.focus():n.length>(e.maxlength||500)?r.tips(\"&#x6700;&#x591A;&#x8F93;&#x5165;\"+(e.maxlength||500)+\"&#x4E2A;&#x5B57;&#x6570;\",l,{tips:1}):t&&t(n,i,l)}},e))},r.tab=function(e){e=e||{};var t=e.tab||{};return r.open(i.extend({type:1,skin:\"layui-layer-tab\"+c(\"tab\"),resize:!1,title:function(){var e=t.length,i=1,n=\"\";if(e>0)for(n='<span class=\"layui-layer-tabnow\">'+t[0].title+\"</span>\";i<e;i++)n+=\"<span>\"+t[i].title+\"</span>\";return n}(),content:'<ul class=\"layui-layer-tabmain\">'+function(){var e=t.length,i=1,n=\"\";if(e>0)for(n='<li class=\"layui-layer-tabli xubox_tab_layer\">'+(t[0].content||\"no content\")+\"</li>\";i<e;i++)n+='<li class=\"layui-layer-tabli\">'+(t[i].content||\"no  content\")+\"</li>\";return n}()+\"</ul>\",success:function(t){var n=t.find(\".layui-layer-title\").children(),a=t.find(\".layui-layer-tabmain\").children();n.on(\"mousedown\",function(t){t.stopPropagation?t.stopPropagation():t.cancelBubble=!0;var n=i(this),o=n.index();n.addClass(\"layui-layer-tabnow\").siblings().removeClass(\"layui-layer-tabnow\"),a.eq(o).show().siblings().hide(),\"function\"==typeof e.change&&e.change(o)})}},e))},r.photos=function(t,n,a){function o(e,t,i){var n=new Image;return n.src=e,n.complete?t(n):(n.onload=function(){n.onload=null,t(n)},void(n.onerror=function(e){n.onerror=null,i(e)}))}var l={};if(t=t||{},t.photos){var s=t.photos.constructor===Object,f=s?t.photos:{},d=f.data||[],u=f.start||0;if(l.imgIndex=(0|u)+1,t.img=t.img||\"img\",s){if(0===d.length)return r.msg(\"&#x6CA1;&#x6709;&#x56FE;&#x7247;\")}else{var y=i(t.photos),p=function(){d=[],y.find(t.img).each(function(e){var t=i(this);t.attr(\"layer-index\",e),d.push({alt:t.attr(\"alt\"),pid:t.attr(\"layer-pid\"),src:t.attr(\"layer-src\")||t.attr(\"src\"),thumb:t.attr(\"src\")})})};if(p(),0===d.length)return;if(n||y.on(\"click\",t.img,function(){var e=i(this),n=e.attr(\"layer-index\");r.photos(i.extend(t,{photos:{start:n,data:d,tab:t.tab},full:t.full}),!0),p()}),!n)return}l.imgprev=function(e){l.imgIndex--,l.imgIndex<1&&(l.imgIndex=d.length),l.tabimg(e)},l.imgnext=function(e,t){l.imgIndex++,l.imgIndex>d.length&&(l.imgIndex=1,t)||l.tabimg(e)},l.keyup=function(e){if(!l.end){var t=e.keyCode;e.preventDefault(),37===t?l.imgprev(!0):39===t?l.imgnext(!0):27===t&&r.close(l.index)}},l.tabimg=function(e){d.length<=1||(f.start=l.imgIndex-1,r.close(l.index),r.photos(t,!0,e))},l.event=function(){l.bigimg.hover(function(){l.imgsee.show()},function(){l.imgsee.hide()}),l.bigimg.find(\".layui-layer-imgprev\").on(\"click\",function(e){e.preventDefault(),l.imgprev()}),l.bigimg.find(\".layui-layer-imgnext\").on(\"click\",function(e){e.preventDefault(),l.imgnext()}),i(document).on(\"keyup\",l.keyup)},l.loadi=r.load(1,{shade:!(\"shade\"in t)&&.9,scrollbar:!1}),o(d[u].src,function(n){r.close(l.loadi),l.index=r.open(i.extend({type:1,area:function(){var a=[n.width,n.height],o=[i(e).width()-100,i(e).height()-100];if(!t.full&&(a[0]>o[0]||a[1]>o[1])){var r=[a[0]/o[0],a[1]/o[1]];r[0]>r[1]?(a[0]=a[0]/r[0],a[1]=a[1]/r[0]):r[0]<r[1]&&(a[0]=a[0]/r[1],a[1]=a[1]/r[1])}return[a[0]+\"px\",a[1]+\"px\"]}(),title:!1,shade:.9,shadeClose:!0,closeBtn:!1,move:\".layui-layer-phimg img\",moveType:1,scrollbar:!1,moveOut:!0,anim:5*Math.random()|0,skin:\"layui-layer-photos\"+c(\"photos\"),content:'<div class=\"layui-layer-phimg\"><img src=\"'+d[u].src+'\" alt=\"'+(d[u].alt||\"\")+'\" layer-pid=\"'+d[u].pid+'\"><div class=\"layui-layer-imgsee\">'+(d.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:'+(a?\"block\":\"\")+'\"><span class=\"layui-layer-imgtit\"><a href=\"javascript:;\">'+(d[u].alt||\"\")+\"</a><em>\"+l.imgIndex+\"/\"+d.length+\"</em></span></div></div></div>\",success:function(e,i){l.bigimg=e.find(\".layui-layer-phimg\"),l.imgsee=e.find(\".layui-layer-imguide,.layui-layer-imgbar\"),l.event(e),t.tab&&t.tab(d[u],e)},end:function(){l.end=!0,i(document).off(\"keyup\",l.keyup)}},t))},function(){r.close(l.loadi),r.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(){d.length>1&&l.imgnext(!0,!0)}})})}},o.run=function(t){i=t,n=i(e),s.html=i(\"html\"),r.open=function(e){var t=new l(e);return t.index}},e.layui&&layui.define?(r.ready(),layui.define(\"jquery\",function(t){r.path=layui.cache.dir,o.run(layui.jquery),e.layer=r,t(\"layer\",r)})):\"function\"==typeof define?define([\"jquery\"],function(){return o.run(e.jQuery),r}):function(){o.run(e.jQuery),r.ready()}()}(window);"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/plugins/layui/lay/modules/laypage.js",
    "content": "/** layui-v1.0.7 LGPL License By http://www.layui.com */\n ;layui.define(function(a){\"use strict\";function t(a){new p(a)}var e=document,r=\"getElementById\",n=\"getElementsByTagName\",s=0,p=function(a){var t=this,e=t.config=a||{};e.item=s++,t.render(!0)};p.on=function(a,t,e){return a.attachEvent?a.attachEvent(\"on\"+t,function(){e.call(a,window.even)}):a.addEventListener(t,e,!1),p},p.prototype.type=function(){var a=this.config;if(\"object\"==typeof a.cont)return void 0===a.cont.length?2:3},p.prototype.view=function(){var a=this,t=a.config,e=[],r={};if(t.pages=0|t.pages,t.curr=0|t.curr||1,t.groups=\"groups\"in t?0|t.groups:5,t.first=\"first\"in t?t.first:\"&#x9996;&#x9875;\",t.last=\"last\"in t?t.last:\"&#x672B;&#x9875;\",t.prev=\"prev\"in t?t.prev:\"&#x4E0A;&#x4E00;&#x9875;\",t.next=\"next\"in t?t.next:\"&#x4E0B;&#x4E00;&#x9875;\",t.pages<=1)return\"\";for(t.groups>t.pages&&(t.groups=t.pages),r.index=Math.ceil((t.curr+(t.groups>1&&t.groups!==t.pages?1:0))/(0===t.groups?1:t.groups)),t.curr>1&&t.prev&&e.push('<a href=\"javascript:;\" class=\"layui-laypage-prev\" data-page=\"'+(t.curr-1)+'\">'+t.prev+\"</a>\"),r.index>1&&t.first&&0!==t.groups&&e.push('<a href=\"javascript:;\" class=\"laypage_first\" data-page=\"1\"  title=\"&#x9996;&#x9875;\">'+t.first+\"</a><span>&#x2026;</span>\"),r.poor=Math.floor((t.groups-1)/2),r.start=r.index>1?t.curr-r.poor:1,r.end=r.index>1?function(){var a=t.curr+(t.groups-r.poor-1);return a>t.pages?t.pages:a}():t.groups,r.end-r.start<t.groups-1&&(r.start=r.end-t.groups+1);r.start<=r.end;r.start++)r.start===t.curr?e.push('<span class=\"layui-laypage-curr\"><em class=\"layui-laypage-em\" '+(/^#/.test(t.skin)?'style=\"background-color:'+t.skin+';\"':\"\")+\"></em><em>\"+r.start+\"</em></span>\"):e.push('<a href=\"javascript:;\" data-page=\"'+r.start+'\">'+r.start+\"</a>\");return t.pages>t.groups&&r.end<t.pages&&t.last&&0!==t.groups&&e.push('<span>&#x2026;</span><a href=\"javascript:;\" class=\"layui-laypage-last\" title=\"&#x5C3E;&#x9875;\"  data-page=\"'+t.pages+'\">'+t.last+\"</a>\"),r.flow=!t.prev&&0===t.groups,(t.curr!==t.pages&&t.next||r.flow)&&e.push(function(){return r.flow&&t.curr===t.pages?'<span class=\"layui-laypage-nomore\" title=\"&#x5DF2;&#x6CA1;&#x6709;&#x66F4;&#x591A;\">'+t.next+\"</span>\":'<a href=\"javascript:;\" class=\"layui-laypage-next\" data-page=\"'+(t.curr+1)+'\">'+t.next+\"</a>\"}()),'<div class=\"layui-box layui-laypage layui-laypage-'+(t.skin?function(a){return/^#/.test(a)?\"molv\":a}(t.skin):\"default\")+'\" id=\"layui-laypage-'+a.config.item+'\">'+e.join(\"\")+function(){return t.skip?'<span class=\"layui-laypage-total\">&#x5230;&#x7B2C; <input type=\"number\" min=\"1\" onkeyup=\"this.value=this.value.replace(/\\\\D/, \\'\\');\" value=\"'+t.curr+'\" class=\"layui-laypage-skip\"> &#x9875; <button type=\"button\" class=\"layui-laypage-btn\">&#x786e;&#x5b9a;</button></span>':\"\"}()+\"</div>\"},p.prototype.jump=function(a){if(a){for(var t=this,e=t.config,r=a.children,s=a[n](\"button\")[0],i=a[n](\"input\")[0],u=0,o=r.length;u<o;u++)\"a\"===r[u].nodeName.toLowerCase()&&p.on(r[u],\"click\",function(){var a=0|this.getAttribute(\"data-page\");e.curr=a,t.render()});s&&p.on(s,\"click\",function(){var a=0|i.value.replace(/\\s|\\D/g,\"\");a&&a<=e.pages&&(e.curr=a,t.render())})}},p.prototype.render=function(a){var t=this,n=t.config,s=t.type(),p=t.view();2===s?n.cont.innerHTML=p:3===s?n.cont.html(p):e[r](n.cont).innerHTML=p,n.jump&&n.jump(n,a),t.jump(e[r](\"layui-laypage-\"+n.item)),n.hash&&!a&&(location.hash=\"!\"+n.hash+\"=\"+n.curr)},a(\"laypage\",t)});"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/plugins/layui/lay/modules/laytpl.js",
    "content": "/** layui-v1.0.7 LGPL License By http://www.layui.com */\n ;layui.define(function(e){\"use strict\";var r={open:\"{{\",close:\"}}\"},n={exp:function(e){return new RegExp(e,\"g\")},query:function(e,n,t){var o=[\"#([\\\\s\\\\S])+?\",\"([^{#}])*?\"][e||0];return c((n||\"\")+r.open+o+r.close+(t||\"\"))},escape:function(e){return String(e||\"\").replace(/&(?!#?[a-zA-Z0-9]+;)/g,\"&amp;\").replace(/</g,\"&lt;\").replace(/>/g,\"&gt;\").replace(/'/g,\"&#39;\").replace(/\"/g,\"&quot;\")},error:function(e,r){var n=\"Laytpl Error：\";return\"object\"==typeof console&&console.error(n+e+\"\\n\"+(r||\"\")),n+e}},c=n.exp,t=function(e){this.tpl=e};t.pt=t.prototype,window.errors=0,t.pt.parse=function(e,t){var o=this,p=e,a=c(\"^\"+r.open+\"#\",\"\"),l=c(r.close+\"$\",\"\");e=e.replace(/\\s+|\\r|\\t|\\n/g,\" \").replace(c(r.open+\"#\"),r.open+\"# \").replace(c(r.close+\"}\"),\"} \"+r.close).replace(/\\\\/g,\"\\\\\\\\\").replace(/(?=\"|')/g,\"\\\\\").replace(n.query(),function(e){return e=e.replace(a,\"\").replace(l,\"\"),'\";'+e.replace(/\\\\/g,\"\")+';view+=\"'}).replace(n.query(1),function(e){var n='\"+(';return e.replace(/\\s/g,\"\")===r.open+r.close?\"\":(e=e.replace(c(r.open+\"|\"+r.close),\"\"),/^=/.test(e)&&(e=e.replace(/^=/,\"\"),n='\"+_escape_('),n+e.replace(/\\\\/g,\"\")+')+\"')}),e='\"use strict\";var view = \"'+e+'\";return view;';try{return o.cache=e=new Function(\"d, _escape_\",e),e(t,n.escape)}catch(u){return delete o.cache,n.error(u,p)}},t.pt.render=function(e,r){var c,t=this;return e?(c=t.cache?t.cache(e,n.escape):t.parse(t.tpl,e),r?void r(c):c):n.error(\"no data\")};var o=function(e){return\"string\"!=typeof e?n.error(\"Template not found\"):new t(e)};o.config=function(e){e=e||{};for(var n in e)r[n]=e[n]},o.v=\"1.2.0\",e(\"laytpl\",o)});"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/plugins/layui/lay/modules/tree.js",
    "content": "/** layui-v1.0.7 LGPL License By http://www.layui.com */\n ;layui.define(\"jquery\",function(e){\"use strict\";var o=layui.jquery,a=layui.hint(),r=\"layui-tree-enter\",i=function(e){this.options=e},t={arrow:[\"&#xe623;\",\"&#xe625;\"],checkbox:[\"&#xe626;\",\"&#xe627;\"],radio:[\"&#xe62b;\",\"&#xe62a;\"],branch:[\"&#xe622;\",\"&#xe624;\"],leaf:\"&#xe621;\"};i.prototype.init=function(e){var o=this;e.addClass(\"layui-box layui-tree\"),o.options.skin&&e.addClass(\"layui-tree-skin-\"+o.options.skin),o.tree(e),o.on(e)},i.prototype.tree=function(e,a){var r=this,i=r.options,n=a||i.nodes;layui.each(n,function(a,n){var l=n.children&&n.children.length>0,c=o('<ul class=\"'+(n.spread?\"layui-show\":\"\")+'\"></ul>'),s=o([\"<li \"+(n.spread?'data-spread=\"'+n.spread+'\"':\"\")+\">\",function(){return l?'<i class=\"layui-icon layui-tree-spread\">'+(n.spread?t.arrow[1]:t.arrow[0])+\"</i>\":\"\"}(),function(){return i.check?'<i class=\"layui-icon layui-tree-check\">'+(\"checkbox\"===i.check?t.checkbox[0]:\"radio\"===i.check?t.radio[0]:\"\")+\"</i>\":\"\"}(),function(){return'<a href=\"'+(n.href||\"javascript:;\")+'\" '+(i.target&&n.href?'target=\"'+i.target+'\"':\"\")+\">\"+('<i class=\"layui-icon layui-tree-'+(l?\"branch\":\"leaf\")+'\">'+(l?n.spread?t.branch[1]:t.branch[0]:t.leaf)+\"</i>\")+(\"<cite>\"+(n.name||\"未命名\")+\"</cite></a>\")}(),\"</li>\"].join(\"\"));l&&(s.append(c),r.tree(c,n.children)),e.append(s),\"function\"==typeof i.click&&r.click(s,n),r.spread(s,n),i.drag&&r.drag(s,n)})},i.prototype.click=function(e,o){var a=this,r=a.options;e.children(\"a\").on(\"click\",function(e){layui.stope(e),r.click(o)})},i.prototype.spread=function(e,o){var a=this,r=(a.options,e.children(\".layui-tree-spread\")),i=e.children(\"ul\"),n=e.children(\"a\"),l=function(){e.data(\"spread\")?(e.data(\"spread\",null),i.removeClass(\"layui-show\"),r.html(t.arrow[0]),n.find(\".layui-icon\").html(t.branch[0])):(e.data(\"spread\",!0),i.addClass(\"layui-show\"),r.html(t.arrow[1]),n.find(\".layui-icon\").html(t.branch[1]))};i[0]&&(r.on(\"click\",l),n.on(\"dblclick\",l))},i.prototype.on=function(e){var a=this,i=a.options,t=\"layui-tree-drag\";e.find(\"i\").on(\"selectstart\",function(e){return!1}),i.drag&&o(document).on(\"mousemove\",function(e){var r=a.move;if(r.from){var i=(r.to,o('<div class=\"layui-box '+t+'\"></div>'));e.preventDefault(),o(\".\"+t)[0]||o(\"body\").append(i);var n=o(\".\"+t)[0]?o(\".\"+t):i;n.addClass(\"layui-show\").html(r.from.elem.children(\"a\").html()),n.css({left:e.pageX+10,top:e.pageY+10})}}).on(\"mouseup\",function(){var e=a.move;e.from&&(e.from.elem.children(\"a\").removeClass(r),e.to&&e.to.elem.children(\"a\").removeClass(r),a.move={},o(\".\"+t).remove())})},i.prototype.move={},i.prototype.drag=function(e,a){var i=this,t=(i.options,e.children(\"a\")),n=function(){var t=o(this),n=i.move;n.from&&(n.to={item:a,elem:e},t.addClass(r))};t.on(\"mousedown\",function(){var o=i.move;o.from={item:a,elem:e}}),t.on(\"mouseenter\",n).on(\"mousemove\",n).on(\"mouseleave\",function(){var e=o(this),a=i.move;a.from&&(delete a.to,e.removeClass(r))})},e(\"tree\",function(e){var r=new i(e=e||{}),t=o(e.elem);return t[0]?void r.init(t):a.error(\"layui.tree 没有找到\"+e.elem+\"元素\")})});"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/plugins/layui/lay/modules/upload.js",
    "content": "/** layui-v1.0.7 LGPL License By http://www.layui.com */\n ;layui.define(\"layer\",function(e){\"use strict\";var a=layui.jquery,t=layui.layer,i=(layui.device(),\"layui-upload-enter\"),n=\"layui-upload-iframe\",r={icon:2,shift:6},o={file:\"文件\",video:\"视频\",audio:\"音频\"},s=function(e){this.options=e};s.prototype.init=function(){var e=this,t=e.options,r=a(\"body\"),s=a(t.elem||\".layui-upload-file\"),u=a('<iframe id=\"'+n+'\" class=\"'+n+'\" name=\"'+n+'\"></iframe>');return a(\"#\"+n)[0]||r.append(u),s.each(function(r,s){s=a(s);var u='<form target=\"'+n+'\" method=\"'+(t.method||\"post\")+'\" key=\"set-mine\" enctype=\"multipart/form-data\" action=\"'+(t.url||\"\")+'\"></form>',l=s.attr(\"lay-type\")||t.type;t.unwrap||(u='<div class=\"layui-box layui-upload-button\">'+u+'<span class=\"layui-upload-icon\"><i class=\"layui-icon\">&#xe608;</i>'+(s.attr(\"lay-title\")||t.title||\"上传\"+(o[l]||\"图片\"))+\"</span></div>\"),u=a(u),t.unwrap||u.on(\"dragover\",function(e){e.preventDefault(),a(this).addClass(i)}).on(\"dragleave\",function(){a(this).removeClass(i)}).on(\"drop\",function(){a(this).removeClass(i)}),s.parent(\"form\").attr(\"target\")===n&&(t.unwrap?s.unwrap():(s.parent().next().remove(),s.unwrap().unwrap())),s.wrap(u),s.off(\"change\").on(\"change\",function(){e.action(this,l)})})},s.prototype.action=function(e,i){var o=this,s=o.options,u=e.value,l=a(e),p=l.attr(\"lay-ext\")||s.ext||\"\";if(u){switch(i){case\"file\":if(p&&!RegExp(\"\\\\w\\\\.(\"+p+\")$\",\"i\").test(escape(u)))return t.msg(\"不支持该文件格式\",r),e.value=\"\";break;case\"video\":if(!RegExp(\"\\\\w\\\\.(\"+(p||\"avi|mp4|wma|rmvb|rm|flash|3gp|flv\")+\")$\",\"i\").test(escape(u)))return t.msg(\"不支持该视频格式\",r),e.value=\"\";break;case\"audio\":if(!RegExp(\"\\\\w\\\\.(\"+(p||\"mp3|wav|mid\")+\")$\",\"i\").test(escape(u)))return t.msg(\"不支持该音频格式\",r),e.value=\"\";break;default:if(!RegExp(\"\\\\w\\\\.(\"+(p||\"jpg|png|gif|bmp|jpeg\")+\")$\",\"i\").test(escape(u)))return t.msg(\"不支持该图片格式\",r),e.value=\"\"}s.before&&s.before(e),l.parent().submit();var c=a(\"#\"+n),f=setInterval(function(){var a;try{a=c.contents().find(\"body\").text()}catch(i){t.msg(\"上传接口存在跨域\",r),clearInterval(f)}if(a){clearInterval(f),c.contents().find(\"body\").html(\"\");try{a=JSON.parse(a)}catch(i){return a={},t.msg(\"请对上传接口返回JSON字符\",r)}\"function\"==typeof s.success&&s.success(a,e)}},30);e.value=\"\"}},e(\"upload\",function(e){var a=new s(e=e||{});a.init()})});"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/plugins/layui/lay/modules/util.js",
    "content": "/** layui-v1.0.7 LGPL License By http://www.layui.com */\n ;layui.define(\"jquery\",function(l){\"use strict\";var o=layui.jquery,i={fixbar:function(l){l=l||{},l.bgcolor=l.bgcolor?\"background-color:\"+l.bgcolor:\"\";var i,a,c=\"layui-fixbar-top\",t=[l.bar1===!0?\"&#xe606;\":l.bar1,l.bar2===!0?\"&#xe607;\":l.bar2,\"&#xe604;\"],r=o(['<ul class=\"layui-fixbar\">',l.bar1?'<li class=\"layui-icon\" lay-type=\"bar1\" style=\"'+l.bgcolor+'\">'+t[0]+\"</li>\":\"\",l.bar2?'<li class=\"layui-icon\" lay-type=\"bar2\" style=\"'+l.bgcolor+'\">'+t[1]+\"</li>\":\"\",'<li class=\"layui-icon '+c+'\" lay-type=\"top\" style=\"'+l.bgcolor+'\">'+t[2]+\"</li>\",\"</ul>\"].join(\"\")),e=r.find(\".\"+c),s=function(){var i=o(document).scrollTop();i>=(l.showHeight||200)?a||(e.show(),a=1):a&&(e.hide(),a=0)};o(\".layui-fixbar\")[0]||(\"object\"==typeof l.css&&r.css(l.css),o(\"body\").append(r),s(),r.find(\"li\").on(\"click\",function(){var i=o(this),a=i.attr(\"lay-type\");\"top\"===a&&o(\"html,body\").animate({scrollTop:0},200),l.click&&l.click.call(this,a)}),o(document).on(\"scroll\",function(){i&&clearTimeout(i),i=setTimeout(function(){s()},100)}))}};l(\"util\",i)});"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/plugins/layui/layui.js",
    "content": "/** layui-v1.0.7 LGPL License By http://www.layui.com */\n ;!function(e){\"use strict\";var t=function(){this.v=\"1.0.7\"};t.fn=t.prototype;var n=document,o=t.fn.cache={},i=function(){var e=n.scripts,t=e[e.length-1].src;return t.substring(0,t.lastIndexOf(\"/\")+1)}(),r=function(t){e.console&&console.error&&console.error(\"Layui hint: \"+t)},u=\"undefined\"!=typeof opera&&\"[object Opera]\"===opera.toString(),l={layer:\"modules/layer\",laydate:\"modules/laydate\",laypage:\"modules/laypage\",laytpl:\"modules/laytpl\",layim:\"modules/layim\",layedit:\"modules/layedit\",form:\"modules/form\",upload:\"modules/upload\",tree:\"modules/tree\",slide:\"modules/slide\",table:\"modules/table\",element:\"modules/element\",util:\"modules/util\",flow:\"modules/flow\",code:\"modules/code\",single:\"modules/single\",mobile:\"modules/mobile\",jquery:\"lib/jquery\",\"layui.mod\":\"dest/layui.mod\"};o.modules={},o.status={},o.timeout=10,o.event={},t.fn.define=function(e,t){var n=this,i=\"function\"==typeof e,r=function(){return\"function\"==typeof t&&t(function(e,t){layui[e]=t,o.status[e]=!0}),this};return i&&(t=e,e=[]),layui[\"layui.all\"]?r.call(n):(n.use(e,r),n)},t.fn.use=function(e,t,a){function s(e,t){var n=\"PLaySTATION 3\"===navigator.platform?/^complete$/:/^(complete|loaded)$/;(\"load\"===e.type||n.test((e.currentTarget||e.srcElement).readyState))&&(o.modules[m]=t,y.removeChild(v),function i(){return++p>1e3*o.timeout/4?r(m+\" is not a valid module\"):void(o.status[m]?c():setTimeout(i,4))}())}function c(){a.push(layui[m]),e.length>1?f.use(e.slice(1),t,a):\"function\"==typeof t&&t.apply(layui,a)}var f=this,d=o.dir=o.dir?o.dir:i,y=n.getElementsByTagName(\"head\")[0];e=\"string\"==typeof e?[e]:e,window.jQuery&&jQuery.fn.on&&(f.each(e,function(t,n){\"jquery\"===n&&e.splice(t,1)}),layui.jquery=jQuery);var m=e[0],p=0;if(a=a||[],o.host=o.host||(d.match(/\\/\\/([\\s\\S]+?)\\//)||[\"//\"+location.host+\"/\"])[0],0===e.length||layui[\"layui.all\"]&&l[m])return\"function\"==typeof t&&t.apply(layui,a),f;var v=n.createElement(\"script\"),h=(l[m]?d+\"lay/\":o.base||\"\")+(f.modules[m]||m)+\".js\";return v.async=!0,v.charset=\"utf-8\",v.src=h+function(){var e=o.version===!0?o.v||(new Date).getTime():o.version||\"\";return e?\"?v=\"+e:\"\"}(),o.modules[m]?!function g(){return++p>1e3*o.timeout/4?r(m+\" is not a valid module\"):void(\"string\"==typeof o.modules[m]&&o.status[m]?c():setTimeout(g,4))}():(y.appendChild(v),!v.attachEvent||v.attachEvent.toString&&v.attachEvent.toString().indexOf(\"[native code\")<0||u?v.addEventListener(\"load\",function(e){s(e,h)},!1):v.attachEvent(\"onreadystatechange\",function(e){s(e,h)})),o.modules[m]=h,f},t.fn.getStyle=function(t,n){var o=t.currentStyle?t.currentStyle:e.getComputedStyle(t,null);return o[o.getPropertyValue?\"getPropertyValue\":\"getAttribute\"](n)},t.fn.link=function(e,t,i){var u=this,l=n.createElement(\"link\"),a=n.getElementsByTagName(\"head\")[0];\"string\"==typeof t&&(i=t);var s=(i||e).replace(/\\.|\\//g,\"\"),c=l.id=\"layuicss-\"+s,f=0;l.rel=\"stylesheet\",l.href=e+(o.debug?\"?v=\"+(new Date).getTime():\"\"),l.media=\"all\",n.getElementById(c)||a.appendChild(l),\"function\"==typeof t&&!function d(){return++f>1e3*o.timeout/100?r(e+\" timeout\"):void(1989===parseInt(u.getStyle(n.getElementById(c),\"width\"))?function(){t()}():setTimeout(d,100))}()},t.fn.addcss=function(e,t,n){layui.link(o.dir+\"css/\"+e,t,n)},t.fn.img=function(e,t,n){var o=new Image;return o.src=e,o.complete?t(o):(o.onload=function(){o.onload=null,t(o)},void(o.onerror=function(e){o.onerror=null,n(e)}))},t.fn.config=function(e){e=e||{};for(var t in e)o[t]=e[t];return this},t.fn.modules=function(){var e={};for(var t in l)e[t]=l[t];return e}(),t.fn.extend=function(e){var t=this;e=e||{};for(var n in e)t[n]||t.modules[n]?r(\"模块名 \"+n+\" 已被占用\"):t.modules[n]=e[n];return t},t.fn.router=function(e){for(var t,n=(e||location.hash).replace(/^#/,\"\").split(\"/\")||[],o={dir:[]},i=0;i<n.length;i++)t=n[i].split(\"=\"),/^\\w+=/.test(n[i])?function(){\"dir\"!==t[0]&&(o[t[0]]=t[1])}():o.dir.push(n[i]),t=null;return o},t.fn.data=function(t,n){if(t=t||\"layui\",e.JSON&&e.JSON.parse){if(null===n)return delete localStorage[t];n=\"object\"==typeof n?n:{key:n};try{var o=JSON.parse(localStorage[t])}catch(i){var o={}}return n.value&&(o[n.key]=n.value),n.remove&&delete o[n.key],localStorage[t]=JSON.stringify(o),n.key?o[n.key]:o}},t.fn.device=function(t){var n=navigator.userAgent.toLowerCase(),o=function(e){var t=new RegExp(e+\"/([^\\\\s\\\\_\\\\-]+)\");return e=(n.match(t)||[])[1],e||!1},i={os:function(){return/windows/.test(n)?\"windows\":/linux/.test(n)?\"linux\":/iphone|ipod|ipad|ios/.test(n)?\"ios\":void 0}(),ie:function(){return!!(e.ActiveXObject||\"ActiveXObject\"in e)&&((n.match(/msie\\s(\\d+)/)||[])[1]||\"11\")}(),weixin:o(\"micromessenger\")};return t&&!i[t]&&(i[t]=o(t)),i.android=/android/.test(n),i.ios=\"ios\"===i.os,i},t.fn.hint=function(){return{error:r}},t.fn.each=function(e,t){var n,o=this;if(\"function\"!=typeof t)return o;if(e=e||[],e.constructor===Object){for(n in e)if(t.call(e[n],n,e[n]))break}else for(n=0;n<e.length&&!t.call(e[n],n,e[n]);n++);return o},t.fn.stope=function(t){t=t||e.event,t.stopPropagation?t.stopPropagation():t.cancelBubble=!0},t.fn.onevent=function(e,t,n){return\"string\"!=typeof e||\"function\"!=typeof n?this:(o.event[e+\".\"+t]=[n],this)},t.fn.event=function(e,t,n){var i=this,r=null,u=t.match(/\\(.*\\)$/)||[],l=(t=e+\".\"+t).replace(u,\"\"),a=function(e,t){var o=t&&t.call(i,n);o===!1&&null===r&&(r=!1)};return layui.each(o.event[l],a),u[0]&&layui.each(o.event[t],a),r},e.layui=new t}(window);"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/plugins/layui/modules/icheck.js",
    "content": "layui.define(['jquery'], function(exports) {\n\tvar JQuery = layui.jquery;\n\t/*! iCheck v1.0.2 by Damir Sultanov, http://git.io/arlzeA, MIT Licensed */\n(function(f){function A(a,b,d){var c=a[0],g=/er/.test(d)?_indeterminate:/bl/.test(d)?n:k,e=d==_update?{checked:c[k],disabled:c[n],indeterminate:\"true\"==a.attr(_indeterminate)||\"false\"==a.attr(_determinate)}:c[g];if(/^(ch|di|in)/.test(d)&&!e)x(a,g);else if(/^(un|en|de)/.test(d)&&e)q(a,g);else if(d==_update)for(var f in e)e[f]?x(a,f,!0):q(a,f,!0);else if(!b||\"toggle\"==d){if(!b)a[_callback](\"ifClicked\");e?c[_type]!==r&&q(a,g):x(a,g)}}function x(a,b,d){var c=a[0],g=a.parent(),e=b==k,u=b==_indeterminate,\nv=b==n,s=u?_determinate:e?y:\"enabled\",F=l(a,s+t(c[_type])),B=l(a,b+t(c[_type]));if(!0!==c[b]){if(!d&&b==k&&c[_type]==r&&c.name){var w=a.closest(\"form\"),p='input[name=\"'+c.name+'\"]',p=w.length?w.find(p):f(p);p.each(function(){this!==c&&f(this).data(m)&&q(f(this),b)})}u?(c[b]=!0,c[k]&&q(a,k,\"force\")):(d||(c[b]=!0),e&&c[_indeterminate]&&q(a,_indeterminate,!1));D(a,e,b,d)}c[n]&&l(a,_cursor,!0)&&g.find(\".\"+C).css(_cursor,\"default\");g[_add](B||l(a,b)||\"\");g.attr(\"role\")&&!u&&g.attr(\"aria-\"+(v?n:k),\"true\");\ng[_remove](F||l(a,s)||\"\")}function q(a,b,d){var c=a[0],g=a.parent(),e=b==k,f=b==_indeterminate,m=b==n,s=f?_determinate:e?y:\"enabled\",q=l(a,s+t(c[_type])),r=l(a,b+t(c[_type]));if(!1!==c[b]){if(f||!d||\"force\"==d)c[b]=!1;D(a,e,s,d)}!c[n]&&l(a,_cursor,!0)&&g.find(\".\"+C).css(_cursor,\"pointer\");g[_remove](r||l(a,b)||\"\");g.attr(\"role\")&&!f&&g.attr(\"aria-\"+(m?n:k),\"false\");g[_add](q||l(a,s)||\"\")}function E(a,b){if(a.data(m)){a.parent().html(a.attr(\"style\",a.data(m).s||\"\"));if(b)a[_callback](b);a.off(\".i\").unwrap();\nf(_label+'[for=\"'+a[0].id+'\"]').add(a.closest(_label)).off(\".i\")}}function l(a,b,f){if(a.data(m))return a.data(m).o[b+(f?\"\":\"Class\")]}function t(a){return a.charAt(0).toUpperCase()+a.slice(1)}function D(a,b,f,c){if(!c){if(b)a[_callback](\"ifToggled\");a[_callback](\"ifChanged\")[_callback](\"if\"+t(f))}}var m=\"iCheck\",C=m+\"-helper\",r=\"radio\",k=\"checked\",y=\"un\"+k,n=\"disabled\";_determinate=\"determinate\";_indeterminate=\"in\"+_determinate;_update=\"update\";_type=\"type\";_click=\"click\";_touch=\"touchbegin.i touchend.i\";\n_add=\"addClass\";_remove=\"removeClass\";_callback=\"trigger\";_label=\"label\";_cursor=\"cursor\";_mobile=/ipad|iphone|ipod|android|blackberry|windows phone|opera mini|silk/i.test(navigator.userAgent);f.fn[m]=function(a,b){var d='input[type=\"checkbox\"], input[type=\"'+r+'\"]',c=f(),g=function(a){a.each(function(){var a=f(this);c=a.is(d)?c.add(a):c.add(a.find(d))})};if(/^(check|uncheck|toggle|indeterminate|determinate|disable|enable|update|destroy)$/i.test(a))return a=a.toLowerCase(),g(this),c.each(function(){var c=\nf(this);\"destroy\"==a?E(c,\"ifDestroyed\"):A(c,!0,a);f.isFunction(b)&&b()});if(\"object\"!=typeof a&&a)return this;var e=f.extend({checkedClass:k,disabledClass:n,indeterminateClass:_indeterminate,labelHover:!0},a),l=e.handle,v=e.hoverClass||\"hover\",s=e.focusClass||\"focus\",t=e.activeClass||\"active\",B=!!e.labelHover,w=e.labelHoverClass||\"hover\",p=(\"\"+e.increaseArea).replace(\"%\",\"\")|0;if(\"checkbox\"==l||l==r)d='input[type=\"'+l+'\"]';-50>p&&(p=-50);g(this);return c.each(function(){var a=f(this);E(a);var c=this,\nb=c.id,g=-p+\"%\",d=100+2*p+\"%\",d={position:\"absolute\",top:g,left:g,display:\"block\",width:d,height:d,margin:0,padding:0,background:\"#fff\",border:0,opacity:0},g=_mobile?{position:\"absolute\",visibility:\"hidden\"}:p?d:{position:\"absolute\",opacity:0},l=\"checkbox\"==c[_type]?e.checkboxClass||\"icheckbox\":e.radioClass||\"i\"+r,z=f(_label+'[for=\"'+b+'\"]').add(a.closest(_label)),u=!!e.aria,y=m+\"-\"+Math.random().toString(36).substr(2,6),h='<div class=\"'+l+'\" '+(u?'role=\"'+c[_type]+'\" ':\"\");u&&z.each(function(){h+=\n'aria-labelledby=\"';this.id?h+=this.id:(this.id=y,h+=y);h+='\"'});h=a.wrap(h+\"/>\")[_callback](\"ifCreated\").parent().append(e.insert);d=f('<ins class=\"'+C+'\"/>').css(d).appendTo(h);a.data(m,{o:e,s:a.attr(\"style\")}).css(g);e.inheritClass&&h[_add](c.className||\"\");e.inheritID&&b&&h.attr(\"id\",m+\"-\"+b);\"static\"==h.css(\"position\")&&h.css(\"position\",\"relative\");A(a,!0,_update);if(z.length)z.on(_click+\".i mouseover.i mouseout.i \"+_touch,function(b){var d=b[_type],e=f(this);if(!c[n]){if(d==_click){if(f(b.target).is(\"a\"))return;\nA(a,!1,!0)}else B&&(/ut|nd/.test(d)?(h[_remove](v),e[_remove](w)):(h[_add](v),e[_add](w)));if(_mobile)b.stopPropagation();else return!1}});a.on(_click+\".i focus.i blur.i keyup.i keydown.i keypress.i\",function(b){var d=b[_type];b=b.keyCode;if(d==_click)return!1;if(\"keydown\"==d&&32==b)return c[_type]==r&&c[k]||(c[k]?q(a,k):x(a,k)),!1;if(\"keyup\"==d&&c[_type]==r)!c[k]&&x(a,k);else if(/us|ur/.test(d))h[\"blur\"==d?_remove:_add](s)});d.on(_click+\" mousedown mouseup mouseover mouseout \"+_touch,function(b){var d=\nb[_type],e=/wn|up/.test(d)?t:v;if(!c[n]){if(d==_click)A(a,!1,!0);else{if(/wn|er|in/.test(d))h[_add](e);else h[_remove](e+\" \"+t);if(z.length&&B&&e==v)z[/ut|nd/.test(d)?_remove:_add](w)}if(_mobile)b.stopPropagation();else return!1}})})}})(JQuery);\n\t//输出接口\n\texports('icheck', null);\n}).addcss('modules/icheck/icheck.css','skinicheckcss');"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/plugins/layui/modules/pjax.js",
    "content": "//依赖layui.js\n\nlayui.define(['jquery'], function(exports) {\n\tvar jQuery = layui.jquery;\n\n\t/*!\n\t * Copyright 2012, Chris Wanstrath\n\t * Released under the MIT License\n\t * https://github.com/defunkt/jquery-pjax\n\t */\n\n\t(function($) {\n\n\t\t// When called on a container with a selector, fetches the href with\n\t\t// ajax into the container or with the data-pjax attribute on the link\n\t\t// itself.\n\t\t//\n\t\t// Tries to make sure the back button and ctrl+click work the way\n\t\t// you'd expect.\n\t\t//\n\t\t// Exported as $.fn.pjax\n\t\t//\n\t\t// Accepts a jQuery ajax options object that may include these\n\t\t// pjax specific options:\n\t\t//\n\t\t//\n\t\t// container - Where to stick the response body. Usually a String selector.\n\t\t//             $(container).html(xhr.responseBody)\n\t\t//             (default: current jquery context)\n\t\t//      push - Whether to pushState the URL. Defaults to true (of course).\n\t\t//   replace - Want to use replaceState instead? That's cool.\n\t\t//\n\t\t// For convenience the second parameter can be either the container or\n\t\t// the options object.\n\t\t//\n\t\t// Returns the jQuery object\n\t\tfunction fnPjax(selector, container, options) {\n\t\t\tvar context = this\n\t\t\treturn this.on('click.pjax', selector, function(event) {\n\t\t\t\tvar opts = $.extend({}, optionsFor(container, options))\n\t\t\t\tif(!opts.container)\n\t\t\t\t\topts.container = $(this).attr('data-pjax') || context\n\t\t\t\thandleClick(event, opts)\n\t\t\t})\n\t\t}\n\n\t\t// Public: pjax on click handler\n\t\t//\n\t\t// Exported as $.pjax.click.\n\t\t//\n\t\t// event   - \"click\" jQuery.Event\n\t\t// options - pjax options\n\t\t//\n\t\t// Examples\n\t\t//\n\t\t//   $(document).on('click', 'a', $.pjax.click)\n\t\t//   // is the same as\n\t\t//   $(document).pjax('a')\n\t\t//\n\t\t//  $(document).on('click', 'a', function(event) {\n\t\t//    var container = $(this).closest('[data-pjax-container]')\n\t\t//    $.pjax.click(event, container)\n\t\t//  })\n\t\t//\n\t\t// Returns nothing.\n\t\tfunction handleClick(event, container, options) {\n\t\t\toptions = optionsFor(container, options)\n\n\t\t\tvar link = event.currentTarget\n\n\t\t\tif(link.tagName.toUpperCase() !== 'A')\n\t\t\t\tthrow \"$.fn.pjax or $.pjax.click requires an anchor element\"\n\n\t\t\t// Middle click, cmd click, and ctrl click should open\n\t\t\t// links in a new tab as normal.\n\t\t\tif(event.which > 1 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey)\n\t\t\t\treturn\n\n\t\t\t// Ignore cross origin links\n\t\t\tif(location.protocol !== link.protocol || location.hostname !== link.hostname)\n\t\t\t\treturn\n\n\t\t\t// Ignore case when a hash is being tacked on the current URL\n\t\t\tif(link.href.indexOf('#') > -1 && stripHash(link) == stripHash(location))\n\t\t\t\treturn\n\n\t\t\t// Ignore event with default prevented\n\t\t\tif(event.isDefaultPrevented())\n\t\t\t\treturn\n\n\t\t\tvar defaults = {\n\t\t\t\turl: link.href,\n\t\t\t\tcontainer: $(link).attr('data-pjax'),\n\t\t\t\ttarget: link\n\t\t\t}\n\n\t\t\tvar opts = $.extend({}, defaults, options)\n\t\t\tvar clickEvent = $.Event('pjax:click')\n\t\t\t$(link).trigger(clickEvent, [opts])\n\n\t\t\tif(!clickEvent.isDefaultPrevented()) {\n\t\t\t\tpjax(opts)\n\t\t\t\tevent.preventDefault()\n\t\t\t\t$(link).trigger('pjax:clicked', [opts])\n\t\t\t}\n\t\t}\n\n\t\t// Public: pjax on form submit handler\n\t\t//\n\t\t// Exported as $.pjax.submit\n\t\t//\n\t\t// event   - \"click\" jQuery.Event\n\t\t// options - pjax options\n\t\t//\n\t\t// Examples\n\t\t//\n\t\t//  $(document).on('submit', 'form', function(event) {\n\t\t//    var container = $(this).closest('[data-pjax-container]')\n\t\t//    $.pjax.submit(event, container)\n\t\t//  })\n\t\t//\n\t\t// Returns nothing.\n\t\tfunction handleSubmit(event, container, options) {\n\t\t\toptions = optionsFor(container, options)\n\n\t\t\tvar form = event.currentTarget\n\n\t\t\tif(form.tagName.toUpperCase() !== 'FORM')\n\t\t\t\tthrow \"$.pjax.submit requires a form element\"\n\n\t\t\tvar defaults = {\n\t\t\t\ttype: form.method.toUpperCase(),\n\t\t\t\turl: form.action,\n\t\t\t\tcontainer: $(form).attr('data-pjax'),\n\t\t\t\ttarget: form\n\t\t\t}\n\n\t\t\tif(defaults.type !== 'GET' && window.FormData !== undefined) {\n\t\t\t\tdefaults.data = new FormData(form);\n\t\t\t\tdefaults.processData = false;\n\t\t\t\tdefaults.contentType = false;\n\t\t\t} else {\n\t\t\t\t// Can't handle file uploads, exit\n\t\t\t\tif($(form).find(':file').length) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Fallback to manually serializing the fields\n\t\t\t\tdefaults.data = $(form).serializeArray();\n\t\t\t}\n\n\t\t\tpjax($.extend({}, defaults, options))\n\n\t\t\tevent.preventDefault()\n\t\t}\n\n\t\t// Loads a URL with ajax, puts the response body inside a container,\n\t\t// then pushState()'s the loaded URL.\n\t\t//\n\t\t// Works just like $.ajax in that it accepts a jQuery ajax\n\t\t// settings object (with keys like url, type, data, etc).\n\t\t//\n\t\t// Accepts these extra keys:\n\t\t//\n\t\t// container - Where to stick the response body.\n\t\t//             $(container).html(xhr.responseBody)\n\t\t//      push - Whether to pushState the URL. Defaults to true (of course).\n\t\t//   replace - Want to use replaceState instead? That's cool.\n\t\t//\n\t\t// Use it just like $.ajax:\n\t\t//\n\t\t//   var xhr = $.pjax({ url: this.href, container: '#main' })\n\t\t//   console.log( xhr.readyState )\n\t\t//\n\t\t// Returns whatever $.ajax returns.\n\t\tfunction pjax(options) {\n\t\t\toptions = $.extend(true, {}, $.ajaxSettings, pjax.defaults, options)\n\n\t\t\tif($.isFunction(options.url)) {\n\t\t\t\toptions.url = options.url()\n\t\t\t}\n\n\t\t\tvar target = options.target\n\n\t\t\tvar hash = parseURL(options.url).hash\n\n\t\t\tvar context = options.context = findContainerFor(options.container)\n\n\t\t\t// We want the browser to maintain two separate internal caches: one\n\t\t\t// for pjax'd partial page loads and one for normal page loads.\n\t\t\t// Without adding this secret parameter, some browsers will often\n\t\t\t// confuse the two.\n\t\t\tif(!options.data) options.data = {}\n\t\t\tif($.isArray(options.data)) {\n\t\t\t\toptions.data.push({\n\t\t\t\t\tname: '_pjax',\n\t\t\t\t\tvalue: context.selector\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\toptions.data._pjax = context.selector\n\t\t\t}\n\n\t\t\tfunction fire(type, args, props) {\n\t\t\t\tif(!props) props = {}\n\t\t\t\tprops.relatedTarget = target\n\t\t\t\tvar event = $.Event(type, props)\n\t\t\t\tcontext.trigger(event, args)\n\t\t\t\treturn !event.isDefaultPrevented()\n\t\t\t}\n\n\t\t\tvar timeoutTimer\n\n\t\t\toptions.beforeSend = function(xhr, settings) {\n\t\t\t\t// No timeout for non-GET requests\n\t\t\t\t// Its not safe to request the resource again with a fallback method.\n\t\t\t\tif(settings.type !== 'GET') {\n\t\t\t\t\tsettings.timeout = 0\n\t\t\t\t}\n\n\t\t\t\txhr.setRequestHeader('X-PJAX', 'true')\n\t\t\t\txhr.setRequestHeader('X-PJAX-Container', context.selector)\n\n\t\t\t\tif(!fire('pjax:beforeSend', [xhr, settings]))\n\t\t\t\t\treturn false\n\n\t\t\t\tif(settings.timeout > 0) {\n\t\t\t\t\ttimeoutTimer = setTimeout(function() {\n\t\t\t\t\t\tif(fire('pjax:timeout', [xhr, options]))\n\t\t\t\t\t\t\txhr.abort('timeout')\n\t\t\t\t\t}, settings.timeout)\n\n\t\t\t\t\t// Clear timeout setting so jquerys internal timeout isn't invoked\n\t\t\t\t\tsettings.timeout = 0\n\t\t\t\t}\n\n\t\t\t\tvar url = parseURL(settings.url)\n\t\t\t\tif(hash) url.hash = hash\n\t\t\t\toptions.requestUrl = stripInternalParams(url)\n\t\t\t}\n\n\t\t\toptions.complete = function(xhr, textStatus) {\n\t\t\t\tif(timeoutTimer)\n\t\t\t\t\tclearTimeout(timeoutTimer)\n\n\t\t\t\tfire('pjax:complete', [xhr, textStatus, options])\n\n\t\t\t\tfire('pjax:end', [xhr, options])\n\t\t\t}\n\n\t\t\toptions.error = function(xhr, textStatus, errorThrown) {\n\t\t\t\tvar container = extractContainer(\"\", xhr, options)\n\n\t\t\t\tvar allowed = fire('pjax:error', [xhr, textStatus, errorThrown, options])\n\t\t\t\tif(options.type == 'GET' && textStatus !== 'abort' && allowed) {\n\t\t\t\t\tlocationReplace(container.url)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\toptions.success = function(data, status, xhr) {\n\t\t\t\tvar previousState = pjax.state;\n\n\t\t\t\t// If $.pjax.defaults.version is a function, invoke it first.\n\t\t\t\t// Otherwise it can be a static string.\n\t\t\t\tvar currentVersion = (typeof $.pjax.defaults.version === 'function') ?\n\t\t\t\t\t$.pjax.defaults.version() :\n\t\t\t\t\t$.pjax.defaults.version\n\n\t\t\t\tvar latestVersion = xhr.getResponseHeader('X-PJAX-Version')\n\n\t\t\t\tvar container = extractContainer(data, xhr, options)\n\n\t\t\t\tvar url = parseURL(container.url)\n\t\t\t\tif(hash) {\n\t\t\t\t\turl.hash = hash\n\t\t\t\t\tcontainer.url = url.href\n\t\t\t\t}\n\n\t\t\t\t// If there is a layout version mismatch, hard load the new url\n\t\t\t\tif(currentVersion && latestVersion && currentVersion !== latestVersion) {\n\t\t\t\t\tlocationReplace(container.url)\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// If the new response is missing a body, hard load the page\n\t\t\t\tif(!container.contents) {\n\t\t\t\t\tlocationReplace(container.url)\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tpjax.state = {\n\t\t\t\t\tid: options.id || uniqueId(),\n\t\t\t\t\turl: container.url,\n\t\t\t\t\ttitle: container.title,\n\t\t\t\t\tcontainer: context.selector,\n\t\t\t\t\tfragment: options.fragment,\n\t\t\t\t\ttimeout: options.timeout\n\t\t\t\t}\n\n\t\t\t\tif(options.push || options.replace) {\n\t\t\t\t\twindow.history.replaceState(pjax.state, container.title, container.url)\n\t\t\t\t}\n\n\t\t\t\t// Clear out any focused controls before inserting new page contents.\n\t\t\t\ttry {\n\t\t\t\t\tdocument.activeElement.blur()\n\t\t\t\t} catch(e) {}\n\n\t\t\t\tif(container.title) document.title = container.title\n\n\t\t\t\tfire('pjax:beforeReplace', [container.contents, options], {\n\t\t\t\t\tstate: pjax.state,\n\t\t\t\t\tpreviousState: previousState\n\t\t\t\t})\n\t\t\t\tcontext.html(container.contents)\n\n\t\t\t\t// FF bug: Won't autofocus fields that are inserted via JS.\n\t\t\t\t// This behavior is incorrect. So if theres no current focus, autofocus\n\t\t\t\t// the last field.\n\t\t\t\t//\n\t\t\t\t// http://www.w3.org/html/wg/drafts/html/master/forms.html\n\t\t\t\tvar autofocusEl = context.find('input[autofocus], textarea[autofocus]').last()[0]\n\t\t\t\tif(autofocusEl && document.activeElement !== autofocusEl) {\n\t\t\t\t\tautofocusEl.focus();\n\t\t\t\t}\n\n\t\t\t\texecuteScriptTags(container.scripts)\n\n\t\t\t\tvar scrollTo = options.scrollTo\n\n\t\t\t\t// Ensure browser scrolls to the element referenced by the URL anchor\n\t\t\t\tif(hash) {\n\t\t\t\t\tvar name = decodeURIComponent(hash.slice(1))\n\t\t\t\t\tvar target = document.getElementById(name) || document.getElementsByName(name)[0]\n\t\t\t\t\tif(target) scrollTo = $(target).offset().top\n\t\t\t\t}\n\n\t\t\t\tif(typeof scrollTo == 'number') $(window).scrollTop(scrollTo)\n\n\t\t\t\tfire('pjax:success', [data, status, xhr, options])\n\t\t\t}\n\n\t\t\t// Initialize pjax.state for the initial page load. Assume we're\n\t\t\t// using the container and options of the link we're loading for the\n\t\t\t// back button to the initial page. This ensures good back button\n\t\t\t// behavior.\n\t\t\tif(!pjax.state) {\n\t\t\t\tpjax.state = {\n\t\t\t\t\tid: uniqueId(),\n\t\t\t\t\turl: window.location.href,\n\t\t\t\t\ttitle: document.title,\n\t\t\t\t\tcontainer: context.selector,\n\t\t\t\t\tfragment: options.fragment,\n\t\t\t\t\ttimeout: options.timeout\n\t\t\t\t}\n\t\t\t\twindow.history.replaceState(pjax.state, document.title)\n\t\t\t}\n\n\t\t\t// Cancel the current request if we're already pjaxing\n\t\t\tabortXHR(pjax.xhr)\n\n\t\t\tpjax.options = options\n\t\t\tvar xhr = pjax.xhr = $.ajax(options)\n\n\t\t\tif(xhr.readyState > 0) {\n\t\t\t\tif(options.push && !options.replace) {\n\t\t\t\t\t// Cache current container element before replacing it\n\t\t\t\t\tcachePush(pjax.state.id, cloneContents(context))\n\n\t\t\t\t\twindow.history.pushState(null, \"\", options.requestUrl)\n\t\t\t\t}\n\n\t\t\t\tfire('pjax:start', [xhr, options])\n\t\t\t\tfire('pjax:send', [xhr, options])\n\t\t\t}\n\n\t\t\treturn pjax.xhr\n\t\t}\n\n\t\t// Public: Reload current page with pjax.\n\t\t//\n\t\t// Returns whatever $.pjax returns.\n\t\tfunction pjaxReload(container, options) {\n\t\t\tvar defaults = {\n\t\t\t\turl: window.location.href,\n\t\t\t\tpush: false,\n\t\t\t\treplace: true,\n\t\t\t\tscrollTo: false\n\t\t\t}\n\n\t\t\treturn pjax($.extend(defaults, optionsFor(container, options)))\n\t\t}\n\n\t\t// Internal: Hard replace current state with url.\n\t\t//\n\t\t// Work for around WebKit\n\t\t//   https://bugs.webkit.org/show_bug.cgi?id=93506\n\t\t//\n\t\t// Returns nothing.\n\t\tfunction locationReplace(url) {\n\t\t\twindow.history.replaceState(null, \"\", pjax.state.url)\n\t\t\twindow.location.replace(url)\n\t\t}\n\n\t\tvar initialPop = true\n\t\tvar initialURL = window.location.href\n\t\tvar initialState = window.history.state\n\n\t\t// Initialize $.pjax.state if possible\n\t\t// Happens when reloading a page and coming forward from a different\n\t\t// session history.\n\t\tif(initialState && initialState.container) {\n\t\t\tpjax.state = initialState\n\t\t}\n\n\t\t// Non-webkit browsers don't fire an initial popstate event\n\t\tif('state' in window.history) {\n\t\t\tinitialPop = false\n\t\t}\n\n\t\t// popstate handler takes care of the back and forward buttons\n\t\t//\n\t\t// You probably shouldn't use pjax on pages with other pushState\n\t\t// stuff yet.\n\t\tfunction onPjaxPopstate(event) {\n\n\t\t\t// Hitting back or forward should override any pending PJAX request.\n\t\t\tif(!initialPop) {\n\t\t\t\tabortXHR(pjax.xhr)\n\t\t\t}\n\n\t\t\tvar previousState = pjax.state\n\t\t\tvar state = event.state\n\t\t\tvar direction\n\n\t\t\tif(state && state.container) {\n\t\t\t\t// When coming forward from a separate history session, will get an\n\t\t\t\t// initial pop with a state we are already at. Skip reloading the current\n\t\t\t\t// page.\n\t\t\t\tif(initialPop && initialURL == state.url) return\n\n\t\t\t\tif(previousState) {\n\t\t\t\t\t// If popping back to the same state, just skip.\n\t\t\t\t\t// Could be clicking back from hashchange rather than a pushState.\n\t\t\t\t\tif(previousState.id === state.id) return\n\n\t\t\t\t\t// Since state IDs always increase, we can deduce the navigation direction\n\t\t\t\t\tdirection = previousState.id < state.id ? 'forward' : 'back'\n\t\t\t\t}\n\n\t\t\t\tvar cache = cacheMapping[state.id] || []\n\t\t\t\tvar container = $(cache[0] || state.container),\n\t\t\t\t\tcontents = cache[1]\n\n\t\t\t\tif(container.length) {\n\t\t\t\t\tif(previousState) {\n\t\t\t\t\t\t// Cache current container before replacement and inform the\n\t\t\t\t\t\t// cache which direction the history shifted.\n\t\t\t\t\t\tcachePop(direction, previousState.id, cloneContents(container))\n\t\t\t\t\t}\n\n\t\t\t\t\tvar popstateEvent = $.Event('pjax:popstate', {\n\t\t\t\t\t\tstate: state,\n\t\t\t\t\t\tdirection: direction\n\t\t\t\t\t})\n\t\t\t\t\tcontainer.trigger(popstateEvent)\n\n\t\t\t\t\tvar options = {\n\t\t\t\t\t\tid: state.id,\n\t\t\t\t\t\turl: state.url,\n\t\t\t\t\t\tcontainer: container,\n\t\t\t\t\t\tpush: false,\n\t\t\t\t\t\tfragment: state.fragment,\n\t\t\t\t\t\ttimeout: state.timeout,\n\t\t\t\t\t\tscrollTo: false\n\t\t\t\t\t}\n\n\t\t\t\t\tif(contents) {\n\t\t\t\t\t\tcontainer.trigger('pjax:start', [null, options])\n\n\t\t\t\t\t\tpjax.state = state\n\t\t\t\t\t\tif(state.title) document.title = state.title\n\t\t\t\t\t\tvar beforeReplaceEvent = $.Event('pjax:beforeReplace', {\n\t\t\t\t\t\t\tstate: state,\n\t\t\t\t\t\t\tpreviousState: previousState\n\t\t\t\t\t\t})\n\t\t\t\t\t\tcontainer.trigger(beforeReplaceEvent, [contents, options])\n\t\t\t\t\t\tcontainer.html(contents)\n\n\t\t\t\t\t\tcontainer.trigger('pjax:end', [null, options])\n\t\t\t\t\t} else {\n\t\t\t\t\t\tpjax(options)\n\t\t\t\t\t}\n\n\t\t\t\t\t// Force reflow/relayout before the browser tries to restore the\n\t\t\t\t\t// scroll position.\n\t\t\t\t\tcontainer[0].offsetHeight\n\t\t\t\t} else {\n\t\t\t\t\tlocationReplace(location.href)\n\t\t\t\t}\n\t\t\t}\n\t\t\tinitialPop = false\n\t\t}\n\n\t\t// Fallback version of main pjax function for browsers that don't\n\t\t// support pushState.\n\t\t//\n\t\t// Returns nothing since it retriggers a hard form submission.\n\t\tfunction fallbackPjax(options) {\n\t\t\tvar url = $.isFunction(options.url) ? options.url() : options.url,\n\t\t\t\tmethod = options.type ? options.type.toUpperCase() : 'GET'\n\n\t\t\tvar form = $('<form>', {\n\t\t\t\tmethod: method === 'GET' ? 'GET' : 'POST',\n\t\t\t\taction: url,\n\t\t\t\tstyle: 'display:none'\n\t\t\t})\n\n\t\t\tif(method !== 'GET' && method !== 'POST') {\n\t\t\t\tform.append($('<input>', {\n\t\t\t\t\ttype: 'hidden',\n\t\t\t\t\tname: '_method',\n\t\t\t\t\tvalue: method.toLowerCase()\n\t\t\t\t}))\n\t\t\t}\n\n\t\t\tvar data = options.data\n\t\t\tif(typeof data === 'string') {\n\t\t\t\t$.each(data.split('&'), function(index, value) {\n\t\t\t\t\tvar pair = value.split('=')\n\t\t\t\t\tform.append($('<input>', {\n\t\t\t\t\t\ttype: 'hidden',\n\t\t\t\t\t\tname: pair[0],\n\t\t\t\t\t\tvalue: pair[1]\n\t\t\t\t\t}))\n\t\t\t\t})\n\t\t\t} else if($.isArray(data)) {\n\t\t\t\t$.each(data, function(index, value) {\n\t\t\t\t\tform.append($('<input>', {\n\t\t\t\t\t\ttype: 'hidden',\n\t\t\t\t\t\tname: value.name,\n\t\t\t\t\t\tvalue: value.value\n\t\t\t\t\t}))\n\t\t\t\t})\n\t\t\t} else if(typeof data === 'object') {\n\t\t\t\tvar key\n\t\t\t\tfor(key in data)\n\t\t\t\t\tform.append($('<input>', {\n\t\t\t\t\t\ttype: 'hidden',\n\t\t\t\t\t\tname: key,\n\t\t\t\t\t\tvalue: data[key]\n\t\t\t\t\t}))\n\t\t\t}\n\n\t\t\t$(document.body).append(form)\n\t\t\tform.submit()\n\t\t}\n\n\t\t// Internal: Abort an XmlHttpRequest if it hasn't been completed,\n\t\t// also removing its event handlers.\n\t\tfunction abortXHR(xhr) {\n\t\t\tif(xhr && xhr.readyState < 4) {\n\t\t\t\txhr.onreadystatechange = $.noop\n\t\t\t\txhr.abort()\n\t\t\t}\n\t\t}\n\n\t\t// Internal: Generate unique id for state object.\n\t\t//\n\t\t// Use a timestamp instead of a counter since ids should still be\n\t\t// unique across page loads.\n\t\t//\n\t\t// Returns Number.\n\t\tfunction uniqueId() {\n\t\t\treturn(new Date).getTime()\n\t\t}\n\n\t\tfunction cloneContents(container) {\n\t\t\tvar cloned = container.clone()\n\t\t\t\t// Unmark script tags as already being eval'd so they can get executed again\n\t\t\t\t// when restored from cache. HAXX: Uses jQuery internal method.\n\t\t\tcloned.find('script').each(function() {\n\t\t\t\tif(!this.src) jQuery._data(this, 'globalEval', false)\n\t\t\t})\n\t\t\treturn [container.selector, cloned.contents()]\n\t\t}\n\n\t\t// Internal: Strip internal query params from parsed URL.\n\t\t//\n\t\t// Returns sanitized url.href String.\n\t\tfunction stripInternalParams(url) {\n\t\t\turl.search = url.search.replace(/([?&])(_pjax|_)=[^&]*/g, '')\n\t\t\treturn url.href.replace(/\\?($|#)/, '$1')\n\t\t}\n\n\t\t// Internal: Parse URL components and returns a Locationish object.\n\t\t//\n\t\t// url - String URL\n\t\t//\n\t\t// Returns HTMLAnchorElement that acts like Location.\n\t\tfunction parseURL(url) {\n\t\t\tvar a = document.createElement('a')\n\t\t\ta.href = url\n\t\t\treturn a\n\t\t}\n\n\t\t// Internal: Return the `href` component of given URL object with the hash\n\t\t// portion removed.\n\t\t//\n\t\t// location - Location or HTMLAnchorElement\n\t\t//\n\t\t// Returns String\n\t\tfunction stripHash(location) {\n\t\t\treturn location.href.replace(/#.*/, '')\n\t\t}\n\n\t\t// Internal: Build options Object for arguments.\n\t\t//\n\t\t// For convenience the first parameter can be either the container or\n\t\t// the options object.\n\t\t//\n\t\t// Examples\n\t\t//\n\t\t//   optionsFor('#container')\n\t\t//   // => {container: '#container'}\n\t\t//\n\t\t//   optionsFor('#container', {push: true})\n\t\t//   // => {container: '#container', push: true}\n\t\t//\n\t\t//   optionsFor({container: '#container', push: true})\n\t\t//   // => {container: '#container', push: true}\n\t\t//\n\t\t// Returns options Object.\n\t\tfunction optionsFor(container, options) {\n\t\t\t// Both container and options\n\t\t\tif(container && options)\n\t\t\t\toptions.container = container\n\n\t\t\t// First argument is options Object\n\t\t\telse if($.isPlainObject(container))\n\t\t\t\toptions = container\n\n\t\t\t// Only container\n\t\t\telse\n\t\t\t\toptions = {\n\t\t\t\t\tcontainer: container\n\t\t\t\t}\n\n\t\t\t// Find and validate container\n\t\t\tif(options.container)\n\t\t\t\toptions.container = findContainerFor(options.container)\n\n\t\t\treturn options\n\t\t}\n\n\t\t// Internal: Find container element for a variety of inputs.\n\t\t//\n\t\t// Because we can't persist elements using the history API, we must be\n\t\t// able to find a String selector that will consistently find the Element.\n\t\t//\n\t\t// container - A selector String, jQuery object, or DOM Element.\n\t\t//\n\t\t// Returns a jQuery object whose context is `document` and has a selector.\n\t\tfunction findContainerFor(container) {\n\t\t\tcontainer = $(container)\n\n\t\t\tif(!container.length) {\n\t\t\t\tthrow \"no pjax container for \" + container.selector\n\t\t\t} else if(container.selector !== '' && container.context === document) {\n\t\t\t\treturn container\n\t\t\t} else if(container.attr('id')) {\n\t\t\t\treturn $('#' + container.attr('id'))\n\t\t\t} else {\n\t\t\t\tthrow \"cant get selector for pjax container!\"\n\t\t\t}\n\t\t}\n\n\t\t// Internal: Filter and find all elements matching the selector.\n\t\t//\n\t\t// Where $.fn.find only matches descendants, findAll will test all the\n\t\t// top level elements in the jQuery object as well.\n\t\t//\n\t\t// elems    - jQuery object of Elements\n\t\t// selector - String selector to match\n\t\t//\n\t\t// Returns a jQuery object.\n\t\tfunction findAll(elems, selector) {\n\t\t\treturn elems.filter(selector).add(elems.find(selector));\n\t\t}\n\n\t\tfunction parseHTML(html) {\n\t\t\treturn $.parseHTML(html, document, true)\n\t\t}\n\n\t\t// Internal: Extracts container and metadata from response.\n\t\t//\n\t\t// 1. Extracts X-PJAX-URL header if set\n\t\t// 2. Extracts inline <title> tags\n\t\t// 3. Builds response Element and extracts fragment if set\n\t\t//\n\t\t// data    - String response data\n\t\t// xhr     - XHR response\n\t\t// options - pjax options Object\n\t\t//\n\t\t// Returns an Object with url, title, and contents keys.\n\t\tfunction extractContainer(data, xhr, options) {\n\t\t\tvar obj = {},\n\t\t\t\tfullDocument = /<html/i.test(data)\n\n\t\t\t// Prefer X-PJAX-URL header if it was set, otherwise fallback to\n\t\t\t// using the original requested url.\n\t\t\tvar serverUrl = xhr.getResponseHeader('X-PJAX-URL')\n\t\t\tobj.url = serverUrl ? stripInternalParams(parseURL(serverUrl)) : options.requestUrl\n\n\t\t\t// Attempt to parse response html into elements\n\t\t\tif(fullDocument) {\n\t\t\t\tvar $head = $(parseHTML(data.match(/<head[^>]*>([\\s\\S.]*)<\\/head>/i)[0]))\n\t\t\t\tvar $body = $(parseHTML(data.match(/<body[^>]*>([\\s\\S.]*)<\\/body>/i)[0]))\n\t\t\t} else {\n\t\t\t\tvar $head = $body = $(parseHTML(data))\n\t\t\t}\n\n\t\t\t// If response data is empty, return fast\n\t\t\tif($body.length === 0)\n\t\t\t\treturn obj\n\n\t\t\t// If there's a <title> tag in the header, use it as\n\t\t\t// the page's title.\n\t\t\tobj.title = findAll($head, 'title').last().text()\n\n\t\t\tif(options.fragment) {\n\t\t\t\t// If they specified a fragment, look for it in the response\n\t\t\t\t// and pull it out.\n\t\t\t\tif(options.fragment === 'body') {\n\t\t\t\t\tvar $fragment = $body\n\t\t\t\t} else {\n\t\t\t\t\tvar $fragment = findAll($body, options.fragment).first()\n\t\t\t\t}\n\n\t\t\t\tif($fragment.length) {\n\t\t\t\t\tobj.contents = options.fragment === 'body' ? $fragment : $fragment.contents()\n\n\t\t\t\t\t// If there's no title, look for data-title and title attributes\n\t\t\t\t\t// on the fragment\n\t\t\t\t\tif(!obj.title)\n\t\t\t\t\t\tobj.title = $fragment.attr('title') || $fragment.data('title')\n\t\t\t\t}\n\n\t\t\t} else if(!fullDocument) {\n\t\t\t\tobj.contents = $body\n\t\t\t}\n\n\t\t\t// Clean up any <title> tags\n\t\t\tif(obj.contents) {\n\t\t\t\t// Remove any parent title elements\n\t\t\t\tobj.contents = obj.contents.not(function() {\n\t\t\t\t\treturn $(this).is('title')\n\t\t\t\t})\n\n\t\t\t\t// Then scrub any titles from their descendants\n\t\t\t\tobj.contents.find('title').remove()\n\n\t\t\t\t// Gather all script[src] elements\n\t\t\t\tobj.scripts = findAll(obj.contents, 'script[src]').remove()\n\t\t\t\tobj.contents = obj.contents.not(obj.scripts)\n\t\t\t}\n\n\t\t\t// Trim any whitespace off the title\n\t\t\tif(obj.title) obj.title = $.trim(obj.title)\n\n\t\t\treturn obj\n\t\t}\n\n\t\t// Load an execute scripts using standard script request.\n\t\t//\n\t\t// Avoids jQuery's traditional $.getScript which does a XHR request and\n\t\t// globalEval.\n\t\t//\n\t\t// scripts - jQuery object of script Elements\n\t\t//\n\t\t// Returns nothing.\n\t\tfunction executeScriptTags(scripts) {\n\t\t\tif(!scripts) return\n\n\t\t\tvar existingScripts = $('script[src]')\n\n\t\t\tscripts.each(function() {\n\t\t\t\tvar src = this.src\n\t\t\t\tvar matchedScripts = existingScripts.filter(function() {\n\t\t\t\t\treturn this.src === src\n\t\t\t\t})\n\t\t\t\tif(matchedScripts.length) return\n\n\t\t\t\tvar script = document.createElement('script')\n\t\t\t\tvar type = $(this).attr('type')\n\t\t\t\tif(type) script.type = type\n\t\t\t\tscript.src = $(this).attr('src')\n\t\t\t\tdocument.head.appendChild(script)\n\t\t\t})\n\t\t}\n\n\t\t// Internal: History DOM caching class.\n\t\tvar cacheMapping = {}\n\t\tvar cacheForwardStack = []\n\t\tvar cacheBackStack = []\n\n\t\t// Push previous state id and container contents into the history\n\t\t// cache. Should be called in conjunction with `pushState` to save the\n\t\t// previous container contents.\n\t\t//\n\t\t// id    - State ID Number\n\t\t// value - DOM Element to cache\n\t\t//\n\t\t// Returns nothing.\n\t\tfunction cachePush(id, value) {\n\t\t\tcacheMapping[id] = value\n\t\t\tcacheBackStack.push(id)\n\n\t\t\t// Remove all entries in forward history stack after pushing a new page.\n\t\t\ttrimCacheStack(cacheForwardStack, 0)\n\n\t\t\t// Trim back history stack to max cache length.\n\t\t\ttrimCacheStack(cacheBackStack, pjax.defaults.maxCacheLength)\n\t\t}\n\n\t\t// Shifts cache from directional history cache. Should be\n\t\t// called on `popstate` with the previous state id and container\n\t\t// contents.\n\t\t//\n\t\t// direction - \"forward\" or \"back\" String\n\t\t// id        - State ID Number\n\t\t// value     - DOM Element to cache\n\t\t//\n\t\t// Returns nothing.\n\t\tfunction cachePop(direction, id, value) {\n\t\t\tvar pushStack, popStack\n\t\t\tcacheMapping[id] = value\n\n\t\t\tif(direction === 'forward') {\n\t\t\t\tpushStack = cacheBackStack\n\t\t\t\tpopStack = cacheForwardStack\n\t\t\t} else {\n\t\t\t\tpushStack = cacheForwardStack\n\t\t\t\tpopStack = cacheBackStack\n\t\t\t}\n\n\t\t\tpushStack.push(id)\n\t\t\tif(id = popStack.pop())\n\t\t\t\tdelete cacheMapping[id]\n\n\t\t\t// Trim whichever stack we just pushed to to max cache length.\n\t\t\ttrimCacheStack(pushStack, pjax.defaults.maxCacheLength)\n\t\t}\n\n\t\t// Trim a cache stack (either cacheBackStack or cacheForwardStack) to be no\n\t\t// longer than the specified length, deleting cached DOM elements as necessary.\n\t\t//\n\t\t// stack  - Array of state IDs\n\t\t// length - Maximum length to trim to\n\t\t//\n\t\t// Returns nothing.\n\t\tfunction trimCacheStack(stack, length) {\n\t\t\twhile(stack.length > length)\n\t\t\t\tdelete cacheMapping[stack.shift()]\n\t\t}\n\n\t\t// Public: Find version identifier for the initial page load.\n\t\t//\n\t\t// Returns String version or undefined.\n\t\tfunction findVersion() {\n\t\t\treturn $('meta').filter(function() {\n\t\t\t\tvar name = $(this).attr('http-equiv')\n\t\t\t\treturn name && name.toUpperCase() === 'X-PJAX-VERSION'\n\t\t\t}).attr('content')\n\t\t}\n\n\t\t// Install pjax functions on $.pjax to enable pushState behavior.\n\t\t//\n\t\t// Does nothing if already enabled.\n\t\t//\n\t\t// Examples\n\t\t//\n\t\t//     $.pjax.enable()\n\t\t//\n\t\t// Returns nothing.\n\t\tfunction enable() {\n\t\t\t$.fn.pjax = fnPjax\n\t\t\t$.pjax = pjax\n\t\t\t$.pjax.enable = $.noop\n\t\t\t$.pjax.disable = disable\n\t\t\t$.pjax.click = handleClick\n\t\t\t$.pjax.submit = handleSubmit\n\t\t\t$.pjax.reload = pjaxReload\n\t\t\t$.pjax.defaults = {\n\t\t\t\ttimeout: 650,\n\t\t\t\tpush: true,\n\t\t\t\treplace: false,\n\t\t\t\ttype: 'GET',\n\t\t\t\tdataType: 'html',\n\t\t\t\tscrollTo: 0,\n\t\t\t\tmaxCacheLength: 20,\n\t\t\t\tversion: findVersion\n\t\t\t}\n\t\t\t$(window).on('popstate.pjax', onPjaxPopstate)\n\t\t}\n\n\t\t// Disable pushState behavior.\n\t\t//\n\t\t// This is the case when a browser doesn't support pushState. It is\n\t\t// sometimes useful to disable pushState for debugging on a modern\n\t\t// browser.\n\t\t//\n\t\t// Examples\n\t\t//\n\t\t//     $.pjax.disable()\n\t\t//\n\t\t// Returns nothing.\n\t\tfunction disable() {\n\t\t\t$.fn.pjax = function() {\n\t\t\t\treturn this\n\t\t\t}\n\t\t\t$.pjax = fallbackPjax\n\t\t\t$.pjax.enable = enable\n\t\t\t$.pjax.disable = $.noop\n\t\t\t$.pjax.click = $.noop\n\t\t\t$.pjax.submit = $.noop\n\t\t\t$.pjax.reload = function() {\n\t\t\t\twindow.location.reload()\n\t\t\t}\n\n\t\t\t$(window).off('popstate.pjax', onPjaxPopstate)\n\t\t}\n\n\t\t// Add the state property to jQuery's event object so we can use it in\n\t\t// $(window).bind('popstate')\n\t\tif($.inArray('state', $.event.props) < 0)\n\t\t\t$.event.props.push('state')\n\n\t\t// Is pjax supported by this browser?\n\t\t$.support.pjax =\n\t\t\twindow.history && window.history.pushState && window.history.replaceState &&\n\t\t\t// pushState isn't reliable on iOS until 5.\n\t\t\t!navigator.userAgent.match(/((iPod|iPhone|iPad).+\\bOS\\s+[1-4]\\D|WebApps\\/.+CFNetwork)/)\n\n\t\t$.support.pjax ? enable() : disable()\n\n\t})(jQuery);\n\t//输出接口\n\texports('pjax', null);\n});"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/plugins/ztree/css/awesomeStyle/awesome.css",
    "content": "/*-------------------------------------\nzTree Style using fontawesome instead of images\n\nversion:    1.1\nauthor:     Mike King\nemail:      mikkelking @ hotmail . com\nwebsite:    http://code.google.com/p/jquerytree/\n\n-------------------------------------*/\n/* Definitions ----------------------*/\n/* End of Definitions ---------------*/\n/* Imports  -------------------------*/\n/* End of Imports  ------------------*/\n.ztree * {\n  padding: 0;\n  margin: 0;\n  font-size: 12px;\n  font-family: Verdana, Arial, Helvetica, AppleGothic, sans-serif;\n  background-color: #af0000;\n}\n.ztree {\n  margin: 0;\n  padding: 5px;\n  color: #ffffff;\n  background-color: #af0000;\n}\n.ztree li {\n  padding: 0;\n  margin: 0;\n  list-style: none;\n  line-height: 17px;\n  text-align: left;\n  white-space: nowrap;\n  outline: 0;\n}\n.ztree li ul {\n  margin: 0px;\n  padding: 0 0 0 18px;\n}\n.ztree li a {\n  padding-right: 3px;\n  margin: 0;\n  cursor: pointer;\n  height: 17px;\n  color: #ffffff;\n  background-color: transparent;\n  text-decoration: none;\n  vertical-align: top;\n  display: inline-block;\n}\n.ztree li a input.rename {\n  height: 14px;\n  width: 80px;\n  padding: 0;\n  margin: 0;\n  color: #af0000;\n  background-color: #ffffff;\n  font-size: 12px;\n  border: 1px #585956 solid;\n  *border: 0px;\n}\n.ztree li a:hover {\n  text-decoration: underline;\n}\n.ztree li a.curSelectedNode {\n  padding-top: 0px;\n  background-color: #af4040;\n  color: #ffff00;\n  height: 17px;\n  opacity: 0.8;\n}\n.ztree li a.curSelectedNode_Edit {\n  padding-top: 0px;\n  background-color: transparent;\n  color: #ffff00;\n  height: 17px;\n  border: 1px #666 solid;\n  opacity: 0.8;\n}\n.ztree li a.tmpTargetNode_inner {\n  padding-top: 0px;\n  background-color: #aaa;\n  color: #ffff00;\n  height: 17px;\n  border: 1px #666 solid;\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n.ztree li span {\n  line-height: 17px;\n  margin-right: 2px;\n  background-color: transparent;\n}\n.ztree li span.button {\n  line-height: 0;\n  margin: 0;\n  padding: 0;\n  width: 15px;\n  height: 17px;\n  display: inline-block;\n  vertical-align: top;\n  border: 0px solid;\n  cursor: pointer;\n  outline: none;\n  background-color: transparent;\n  background-repeat: no-repeat;\n  background-attachment: scroll;\n}\n.ztree li span.button::before {\n  color: #ffffff;\n  font-family: FontAwesome;\n  padding-top: 10px;\n}\n.ztree li span.button.chk {\n  margin: 0px;\n  cursor: auto;\n  width: 12px;\n  display: inline-block;\n  padding-top: 10px;\n  padding-left: 2px;\n}\n.ztree li span.button.chk.checkbox_false_full::before {\n  content: \"\\f096\";\n}\n.ztree li span.button.chk.checkbox_false_full_focus::before {\n  content: \"\\f096\";\n  color: #ffff00;\n}\n.ztree li span.button.chk.checkbox_false_part::before {\n  content: \"\\f096\";\n  color: #aaaaaa;\n}\n.ztree li span.button.chk.checkbox_false_part_focus::before {\n  content: \"\\f096\";\n  color: #cad96c;\n}\n.ztree li span.button.chk.checkbox_false_disable::before {\n  content: \"\\f096\";\n  color: #808080;\n}\n.ztree li span.button.chk.checkbox_true_full::before {\n  content: \"\\f046\";\n}\n.ztree li span.button.chk.checkbox_true_full_focus::before {\n  content: \"\\f046\";\n}\n.ztree li span.button.chk.checkbox_true_part::before {\n  content: \"\\f14a\";\n}\n.ztree li span.button.chk.checkbox_true_part_focus::before {\n  content: \"\\f14a\";\n  color: #ffff00;\n}\n.ztree li span.button.chk.checkbox_true_full_focus::before {\n  content: \"\\f046\";\n  color: #ffff00;\n}\n.ztree li span.button.chk.checkbox_true_part::before {\n  content: \"\\f046\";\n  color: #aaaaaa;\n}\n.ztree li span.button.chk.checkbox_true_part_focus::before {\n  content: \"\\f046\";\n  color: #cad96c;\n}\n.ztree li span.button.chk.checkbox_true_disable::before {\n  content: \"\\f046\";\n  color: #808080;\n}\n.ztree li span.button.chk.radio_false_full::before {\n  content: \"\\f10c\";\n}\n.ztree li span.button.chk.radio_false_full_focus::before {\n  content: \"\\f10c\";\n  color: #ffff00;\n}\n.ztree li span.button.chk.radio_false_part::before {\n  content: \"\\f10c\";\n  color: #aaaaaa;\n}\n.ztree li span.button.chk.radio_false_part_focus::before {\n  content: \"\\f10c\";\n  color: #ffff00;\n}\n.ztree li span.button.chk.radio_false_disable::before {\n  content: \"\\f1db\";\n  color: #808080;\n}\n.ztree li span.button.chk.radio_true_full::before {\n  content: \"\\f192\";\n}\n.ztree li span.button.chk.radio_true_full_focus::before {\n  content: \"\\f192\";\n  color: #ffff00;\n}\n.ztree li span.button.chk.radio_true_part::before {\n  content: \"\\f192\";\n  color: #aaaaaa;\n}\n.ztree li span.button.chk.radio_true_part_focus::before {\n  content: \"\\f192\";\n  color: #aaaaaa;\n}\n.ztree li span.button.chk.radio_true_disable::before {\n  content: \"\\f1db\";\n  color: #808080;\n}\n.ztree li span.button.switch {\n  width: 15px;\n  height: 17px;\n}\n.ztree li span.button.root_open::before {\n  content: \"\\f078\";\n  padding-top: 10px;\n  padding-left: 2px;\n  display: inline-block;\n}\n.ztree li span.button.root_close::before {\n  content: \"\\f115\";\n  padding-top: 10px;\n  padding-left: 2px;\n  display: inline-block;\n}\n.ztree li span.button.roots_open::before {\n  content: \"\\f078\";\n  padding-top: 10px;\n  padding-left: 2px;\n  display: inline-block;\n}\n.ztree li span.button.roots_close::before {\n  content: \"\\f054\";\n  padding-top: 10px;\n  padding-left: 2px;\n  display: inline-block;\n}\n.ztree li span.button.center_open::before {\n  content: \"\\f078\";\n  padding-top: 10px;\n  padding-left: 2px;\n  display: inline-block;\n}\n.ztree li span.button.center_close::before {\n  content: \"\\f054\";\n  padding-top: 10px;\n  padding-left: 2px;\n  display: inline-block;\n}\n.ztree li span.button.bottom_open::before {\n  content: \"\\f078\";\n  padding-top: 10px;\n  padding-left: 2px;\n  display: inline-block;\n}\n.ztree li span.button.bottom_close::before {\n  content: \"\\f054\";\n  padding-top: 10px;\n  padding-left: 2px;\n  display: inline-block;\n}\n.ztree li span.button.root_docu {\n  background: none;\n}\n.ztree li span.button.roots_docu::before {\n  content: \"\\f022\";\n  padding-left: 2px;\n  display: inline-block;\n  color: #ffffff;\n}\n.ztree li span.button.center_docu::before {\n  padding-top: 10px;\n  padding-left: 2px;\n  display: inline-block;\n  color: #ffffff;\n}\n.ztree li span.button.bottom_docu::before {\n  padding-top: 10px;\n  padding-left: 2px;\n  display: inline-block;\n  color: #ffffff;\n}\n.ztree li span.button.noline_docu {\n  background: none;\n}\n.ztree li span.button.ico_open::before {\n  content: \"\\f115\";\n  font-family: FontAwesome;\n  padding-top: 10px;\n  padding-left: 2px;\n  display: inline-block;\n  color: #ffffff;\n}\n.ztree li span.button.ico_close::before {\n  content: \"\\f114\";\n  font-family: FontAwesome;\n  padding-top: 10px;\n  padding-left: 2px;\n  display: inline-block;\n  color: #ffffff;\n}\n.ztree li span.button.ico_docu::before {\n  content: \"\\f022\";\n  font-family: FontAwesome;\n  padding-top: 10px;\n  padding-left: 2px;\n  display: inline-block;\n  color: #ffffff;\n}\n.ztree li span.button.edit {\n  margin-left: 4px;\n  margin-right: -1px;\n  vertical-align: top;\n  *vertical-align: middle;\n  padding-top: 10px;\n}\n.ztree li span.button.edit::before {\n  content: \"\\f044\";\n  font-family: FontAwesome;\n}\n.ztree li span.button.remove {\n  margin-left: 4px;\n  margin-right: -1px;\n  vertical-align: top;\n  *vertical-align: middle;\n  padding-top: 10px;\n}\n.ztree li span.button.remove::before {\n  content: \"\\f1f8\";\n  font-family: FontAwesome;\n}\n.ztree li span.button.add {\n  margin-left: 4px;\n  margin-right: -1px;\n  vertical-align: top;\n  *vertical-align: middle;\n  padding-top: 10px;\n}\n.ztree li span.button.add::before {\n  content: \"\\f067\";\n  font-family: FontAwesome;\n}\n.ztree li span.button.ico_loading {\n  margin-right: 2px;\n  background: url(./img/loading.gif) no-repeat scroll 0 0 transparent;\n  vertical-align: top;\n  *vertical-align: middle;\n}\nul.tmpTargetzTree {\n  background-color: #FFE6B0;\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\nspan.tmpzTreeMove_arrow {\n  width: 16px;\n  height: 17px;\n  display: inline-block;\n  padding: 0;\n  margin: 2px 0 0 1px;\n  border: 0 none;\n  position: absolute;\n  background-color: transparent;\n  background-attachment: scroll;\n}\nspan.tmpzTreeMove_arrow::before {\n  content: \"\\f04b\";\n  font-family: FontAwesome;\n  color: #ffff00;\n}\nul.ztree.zTreeDragUL {\n  margin: 0;\n  padding: 0;\n  position: absolute;\n  width: auto;\n  height: auto;\n  overflow: hidden;\n  background-color: #cfcfcf;\n  border: 1px #ffff00 dotted;\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n.ztreeMask {\n  z-index: 10000;\n  background-color: #cfcfcf;\n  opacity: 0.0;\n  filter: alpha(opacity=0);\n  position: absolute;\n}\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/plugins/ztree/css/awesomeStyle/awesome.less",
    "content": "/*-------------------------------------\nzTree Style using fontawesome instead of images\n\nversion:    1.1\nauthor:     Mike King\nemail:      mikkelking @ hotmail . com\nwebsite:    http://code.google.com/p/jquerytree/\n\n-------------------------------------*/\n\n/* Definitions ----------------------*/\n@font-size: 12px;\n// Regular icon and text color is white, which suits any medium -> dark background \n@color-normal: white;\n// Background color\n@color-bg: #af0000;\n// Highlight color\n@color-highlight: yellow;\n// Partially selected (checkboxes, radio buttons)\n@color-partial: #aaaaaa;\n// Partially selected and focused (checkboxes, radio buttons)\n@color-partfocus: #cad96c;\n// Disabled altogether\n@color-disabled: #808080;\n// Editing color\n@color-edit: yellow;\n@w: 15px;\n@h: 17px;\n@pad-left: 2px;\n@pad-top: 10px;\n/* End of Definitions ---------------*/\n\n/* Imports  -------------------------*/\n@import \"fa.less\";\n/* End of Imports  ------------------*/\n\n.ztree * {padding:0; margin:0; font-size:@font-size; font-family: Verdana, Arial, Helvetica, AppleGothic, sans-serif; background-color: @color-bg;}\n.ztree {\n    margin:0; padding:5px; color:@color-normal; background-color: @color-bg;\n    li {\n        padding:0; margin:0; list-style:none; line-height:17px; text-align:left; white-space:nowrap; outline:0;\n        ul { \n            margin: 0px; padding:0 0 0 18px;\n        }\n        ul.line { }\n        a {padding-right:3px; margin:0; cursor:pointer; height:@h; color:@color-normal; background-color: transparent; \n            text-decoration:none; vertical-align:top; display: inline-block;\n            input.rename {height:14px; width:80px; padding:0; margin:0;\n                          color: @color-bg; background-color: @color-normal;\n                        font-size:@font-size; border:1px #585956 solid; *border:0px}\n        }\n        a:hover {text-decoration:underline}\n        a.curSelectedNode {padding-top:0px; background-color:#af4040; color:@color-highlight; height:@h; opacity:0.8;}\n        a.curSelectedNode_Edit {padding-top:0px; background-color:transparent; color:@color-highlight; height:@h; border:1px #666 solid; opacity:0.8;}\n        a.tmpTargetNode_inner {padding-top:0px; background-color:#aaa; color:@color-highlight; height:@h; border:1px #666 solid;\n          opacity:0.8; filter:alpha(opacity=80)}\n        a.tmpTargetNode_prev {}\n        a.tmpTargetNode_next {}\n        span {line-height:@h; margin-right:2px; background-color:transparent;}\n        span.button {line-height:0; margin:0; padding: 0; width:@w; height:@h; display: inline-block; vertical-align:top;\n          border:0px solid; cursor: pointer;outline:none;\n          background-color:transparent; background-repeat:no-repeat; background-attachment: scroll;\n \n            &::before{color: @color-normal; font-family: FontAwesome; padding-top:@pad-top;}\n            &.chk { margin:0px; cursor: auto; width: 12px;\n                display: inline-block;padding-top:@pad-top;padding-left:@pad-left;\n                \n                &.checkbox_false_full::before {content: @fa-square-o;}\n                &.checkbox_false_full_focus::before {content: @fa-square-o; color:@color-highlight;}\n                &.checkbox_false_part::before {content: @fa-square-o;color: @color-partial;}\n                &.checkbox_false_part_focus::before {content: @fa-square-o; color:@color-partfocus;}\n                &.checkbox_false_disable::before {content: @fa-square-o; color:@color-disabled;}\n                &.checkbox_true_full::before {content: @fa-check-square-o;}\n                &.checkbox_true_full_focus::before {content: @fa-check-square-o;}\n                &.checkbox_true_part::before {content: @fa-check-square;}\n                &.checkbox_true_part_focus::before {content: @fa-check-square; color: @color-highlight}\n                &.checkbox_true_full_focus::before {content: @fa-check-square-o; color: @color-highlight}\n                &.checkbox_true_part::before {content: @fa-check-square-o;color: @color-partial}\n                &.checkbox_true_part_focus::before {content: @fa-check-square-o;color: @color-partfocus;}\n                &.checkbox_true_disable::before {content: @fa-check-square-o;color: @color-disabled}\n                 \n                &.radio_false_full::before {content: @fa-circle-o;}\n                &.radio_false_full_focus::before {content: @fa-circle-o;color: @color-highlight}\n                &.radio_false_part::before {content: @fa-circle-o;color: @color-partial}\n                &.radio_false_part_focus::before {content: @fa-circle-o;color: @color-highlight}\n                &.radio_false_disable::before {content: @fa-circle-thin;color: @color-disabled}\n                &.radio_true_full::before {content: @fa-dot-circle-o;}\n                &.radio_true_full_focus::before {content: @fa-dot-circle-o;color: @color-highlight}\n                &.radio_true_part::before {content: @fa-dot-circle-o;color: @color-partial}\n                &.radio_true_part_focus::before {content: @fa-dot-circle-o;color: @color-partial;}\n                &.radio_true_disable::before {content: @fa-circle-thin;color: @color-disabled}\n                \n            }\n            &.switch  {width:@w; height:@h}\n            &.root_open::before{content: @fa-chevron-down;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;}\n            &.root_close::before{content: @fa-folder-open-o;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;}\n            &.roots_open::before{content: @fa-chevron-down;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;}\n            &.roots_close::before{content: @fa-chevron-right;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;}\n            &.center_open::before{content: @fa-chevron-down;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;}\n            &.center_close::before{content: @fa-chevron-right;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;}\n            &.bottom_open::before{content: @fa-chevron-down;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;}\n            &.bottom_close::before{content: @fa-chevron-right;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;}  \n            &.noline_open{}\n            &.noline_close{}\n            &.root_docu{ background:none;}\n            &.roots_docu::before{content: @fa-list-alt;padding-left:@pad-left;display: inline-block;color:@color-normal;}\n            &.center_docu::before{padding-top:@pad-top;padding-left:@pad-left;display: inline-block;color:@color-normal;}\n            &.bottom_docu::before{padding-top:@pad-top;padding-left:@pad-left;display: inline-block;color:@color-normal;}\n            &.noline_docu{ background:none;}\n    \n            &.ico_open::before {content: @fa-folder-open-o;font-family: FontAwesome;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;color:@color-normal;}\n            &.ico_close::before {content: @fa-folder-o;font-family: FontAwesome;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;color:@color-normal;}\n            &.ico_docu::before{content: @fa-list-alt;font-family: FontAwesome;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;color:@color-normal;}\n            \n            &.edit {margin-left:4px; margin-right: -1px;  vertical-align:top; *vertical-align:middle;padding-top:@pad-top;}\n            &.edit::before{content: @fa-pencil-square-o;font-family: FontAwesome;}\n    \n            &.remove {margin-left:4px; margin-right: -1px;  vertical-align:top; *vertical-align:middle;padding-top:@pad-top;}\n            &.remove::before{content: @fa-trash;font-family: FontAwesome;}\n\n    \n            &.add {margin-left:4px; margin-right: -1px; vertical-align:top; *vertical-align:middle;padding-top:@pad-top;}\n            &.add::before{content: @fa-plus;font-family: FontAwesome;}\n\n            &.ico_loading{margin-right:2px; background:url(./img/loading.gif) no-repeat scroll 0 0 transparent; vertical-align:top; *vertical-align:middle}\n        }\n\n    }\n}\n\n\nul.tmpTargetzTree {background-color:#FFE6B0; opacity:0.8; filter:alpha(opacity=80)}\n\n// this is the arrow that moves \nspan.tmpzTreeMove_arrow{width:16px; height:@h; display: inline-block; \n                                padding:0; margin:2px 0 0 1px; border:0 none; position:absolute;\n                                background-color:transparent;  background-attachment: scroll;\n                                 }\nspan.tmpzTreeMove_arrow::before{content: @fa-play;font-family: FontAwesome;color: @color-highlight;\n                                 }\n// outline\n\nul.ztree.zTreeDragUL {margin:0; padding:0; position:absolute; width:auto; height:auto;overflow:hidden; \n             background-color:#cfcfcf; border:1px @color-highlight 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"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/plugins/ztree/css/awesomeStyle/fa.less",
    "content": "@fa-glass: \"\\f000\";\n@fa-music: \"\\f001\";\n@fa-search: \"\\f002\";\n@fa-envelope-o: \"\\f003\";\n@fa-heart: \"\\f004\";\n@fa-star: \"\\f005\";\n@fa-star-o: \"\\f006\";\n@fa-user: \"\\f007\";\n@fa-film: \"\\f008\";\n@fa-th-large: \"\\f009\";\n@fa-th: \"\\f00a\";\n@fa-th-list: \"\\f00b\";\n@fa-check: \"\\f00c\";\n@fa-times: \"\\f00d\";\n@fa-search-plus: \"\\f00e\";\n@fa-search-minus: \"\\f010\";\n@fa-power-off: \"\\f011\";\n@fa-signal: \"\\f012\";\n@fa-cog: \"\\f013\";\n@fa-trash-o: \"\\f014\";\n@fa-home: \"\\f015\";\n@fa-file-o: \"\\f016\";\n@fa-clock-o: \"\\f017\";\n@fa-road: \"\\f018\";\n@fa-download: \"\\f019\";\n@fa-arrow-circle-o-down: \"\\f01a\";\n@fa-arrow-circle-o-up: \"\\f01b\";\n@fa-inbox: \"\\f01c\";\n@fa-play-circle-o: \"\\f01d\";\n@fa-repeat: \"\\f01e\";\n@fa-refresh: \"\\f021\";\n@fa-list-alt: \"\\f022\";\n@fa-lock: \"\\f023\";\n@fa-flag: \"\\f024\";\n@fa-headphones: \"\\f025\";\n@fa-volume-off: \"\\f026\";\n@fa-volume-down: \"\\f027\";\n@fa-volume-up: \"\\f028\";\n@fa-qrcode: \"\\f029\";\n@fa-barcode: \"\\f02a\";\n@fa-tag: \"\\f02b\";\n@fa-tags: \"\\f02c\";\n@fa-book: \"\\f02d\";\n@fa-bookmark: \"\\f02e\";\n@fa-print: \"\\f02f\";\n@fa-camera: \"\\f030\";\n@fa-font: \"\\f031\";\n@fa-bold: \"\\f032\";\n@fa-italic: \"\\f033\";\n@fa-text-height: \"\\f034\";\n@fa-text-width: \"\\f035\";\n@fa-align-left: \"\\f036\";\n@fa-align-center: \"\\f037\";\n@fa-align-right: \"\\f038\";\n@fa-align-justify: \"\\f039\";\n@fa-list: \"\\f03a\";\n@fa-outdent: \"\\f03b\";\n@fa-indent: \"\\f03c\";\n@fa-video-camera: \"\\f03d\";\n@fa-picture-o: \"\\f03e\";\n@fa-pencil: \"\\f040\";\n@fa-map-marker: \"\\f041\";\n@fa-adjust: \"\\f042\";\n@fa-tint: \"\\f043\";\n@fa-pencil-square-o: \"\\f044\";\n@fa-share-square-o: \"\\f045\";\n@fa-check-square-o: \"\\f046\";\n@fa-arrows: \"\\f047\";\n@fa-step-backward: \"\\f048\";\n@fa-fast-backward: \"\\f049\";\n@fa-backward: \"\\f04a\";\n@fa-play: \"\\f04b\";\n@fa-pause: \"\\f04c\";\n@fa-stop: \"\\f04d\";\n@fa-forward: \"\\f04e\";\n@fa-fast-forward: \"\\f050\";\n@fa-step-forward: \"\\f051\";\n@fa-eject: \"\\f052\";\n@fa-chevron-left: \"\\f053\";\n@fa-chevron-right: \"\\f054\";\n@fa-plus-circle: \"\\f055\";\n@fa-minus-circle: \"\\f056\";\n@fa-times-circle: \"\\f057\";\n@fa-check-circle: \"\\f058\";\n@fa-question-circle: \"\\f059\";\n@fa-info-circle: \"\\f05a\";\n@fa-crosshairs: \"\\f05b\";\n@fa-times-circle-o: \"\\f05c\";\n@fa-check-circle-o: \"\\f05d\";\n@fa-ban: \"\\f05e\";\n@fa-arrow-left: \"\\f060\";\n@fa-arrow-right: \"\\f061\";\n@fa-arrow-up: \"\\f062\";\n@fa-arrow-down: \"\\f063\";\n@fa-share: \"\\f064\";\n@fa-expand: \"\\f065\";\n@fa-compress: \"\\f066\";\n@fa-plus: \"\\f067\";\n@fa-minus: \"\\f068\";\n@fa-asterisk: \"\\f069\";\n@fa-exclamation-circle: \"\\f06a\";\n@fa-gift: \"\\f06b\";\n@fa-leaf: \"\\f06c\";\n@fa-fire: \"\\f06d\";\n@fa-eye: \"\\f06e\";\n@fa-eye-slash: \"\\f070\";\n@fa-exclamation-triangle: \"\\f071\";\n@fa-plane: \"\\f072\";\n@fa-calendar: \"\\f073\";\n@fa-random: \"\\f074\";\n@fa-comment: \"\\f075\";\n@fa-magnet: \"\\f076\";\n@fa-chevron-up: \"\\f077\";\n@fa-chevron-down: \"\\f078\";\n@fa-retweet: \"\\f079\";\n@fa-shopping-cart: \"\\f07a\";\n@fa-folder: \"\\f07b\";\n@fa-folder-open: \"\\f07c\";\n@fa-arrows-v: \"\\f07d\";\n@fa-arrows-h: \"\\f07e\";\n@fa-bar-chart: \"\\f080\";\n@fa-twitter-square: \"\\f081\";\n@fa-facebook-square: \"\\f082\";\n@fa-camera-retro: \"\\f083\";\n@fa-key: \"\\f084\";\n@fa-cogs: \"\\f085\";\n@fa-comments: \"\\f086\";\n@fa-thumbs-o-up: \"\\f087\";\n@fa-thumbs-o-down: \"\\f088\";\n@fa-star-half: \"\\f089\";\n@fa-heart-o: \"\\f08a\";\n@fa-sign-out: \"\\f08b\";\n@fa-linkedin-square: \"\\f08c\";\n@fa-thumb-tack: \"\\f08d\";\n@fa-external-link: \"\\f08e\";\n@fa-sign-in: \"\\f090\";\n@fa-trophy: \"\\f091\";\n@fa-github-square: \"\\f092\";\n@fa-upload: \"\\f093\";\n@fa-lemon-o: \"\\f094\";\n@fa-phone: \"\\f095\";\n@fa-square-o: \"\\f096\";\n@fa-bookmark-o: \"\\f097\";\n@fa-phone-square: \"\\f098\";\n@fa-twitter: \"\\f099\";\n@fa-facebook: \"\\f09a\";\n@fa-github: \"\\f09b\";\n@fa-unlock: \"\\f09c\";\n@fa-credit-card: \"\\f09d\";\n@fa-rss: \"\\f09e\";\n@fa-hdd-o: \"\\f0a0\";\n@fa-bullhorn: \"\\f0a1\";\n@fa-bell: \"\\f0f3\";\n@fa-certificate: \"\\f0a3\";\n@fa-hand-o-right: \"\\f0a4\";\n@fa-hand-o-left: \"\\f0a5\";\n@fa-hand-o-up: \"\\f0a6\";\n@fa-hand-o-down: \"\\f0a7\";\n@fa-arrow-circle-left: \"\\f0a8\";\n@fa-arrow-circle-right: \"\\f0a9\";\n@fa-arrow-circle-up: \"\\f0aa\";\n@fa-arrow-circle-down: \"\\f0ab\";\n@fa-globe: \"\\f0ac\";\n@fa-wrench: \"\\f0ad\";\n@fa-tasks: \"\\f0ae\";\n@fa-filter: \"\\f0b0\";\n@fa-briefcase: \"\\f0b1\";\n@fa-arrows-alt: \"\\f0b2\";\n@fa-users: \"\\f0c0\";\n@fa-link: \"\\f0c1\";\n@fa-cloud: \"\\f0c2\";\n@fa-flask: \"\\f0c3\";\n@fa-scissors: \"\\f0c4\";\n@fa-files-o: \"\\f0c5\";\n@fa-paperclip: \"\\f0c6\";\n@fa-floppy-o: \"\\f0c7\";\n@fa-square: \"\\f0c8\";\n@fa-bars: \"\\f0c9\";\n@fa-list-ul: \"\\f0ca\";\n@fa-list-ol: \"\\f0cb\";\n@fa-strikethrough: \"\\f0cc\";\n@fa-underline: \"\\f0cd\";\n@fa-table: \"\\f0ce\";\n@fa-magic: \"\\f0d0\";\n@fa-truck: \"\\f0d1\";\n@fa-pinterest: \"\\f0d2\";\n@fa-pinterest-square: \"\\f0d3\";\n@fa-google-plus-square: \"\\f0d4\";\n@fa-google-plus: \"\\f0d5\";\n@fa-money: \"\\f0d6\";\n@fa-caret-down: \"\\f0d7\";\n@fa-caret-up: \"\\f0d8\";\n@fa-caret-left: \"\\f0d9\";\n@fa-caret-right: \"\\f0da\";\n@fa-columns: \"\\f0db\";\n@fa-sort: \"\\f0dc\";\n@fa-sort-desc: \"\\f0dd\";\n@fa-sort-asc: \"\\f0de\";\n@fa-envelope: \"\\f0e0\";\n@fa-linkedin: \"\\f0e1\";\n@fa-undo: \"\\f0e2\";\n@fa-gavel: \"\\f0e3\";\n@fa-tachometer: \"\\f0e4\";\n@fa-comment-o: \"\\f0e5\";\n@fa-comments-o: \"\\f0e6\";\n@fa-bolt: \"\\f0e7\";\n@fa-sitemap: \"\\f0e8\";\n@fa-umbrella: \"\\f0e9\";\n@fa-clipboard: \"\\f0ea\";\n@fa-lightbulb-o: \"\\f0eb\";\n@fa-exchange: \"\\f0ec\";\n@fa-cloud-download: \"\\f0ed\";\n@fa-cloud-upload: \"\\f0ee\";\n@fa-user-md: \"\\f0f0\";\n@fa-stethoscope: \"\\f0f1\";\n@fa-suitcase: \"\\f0f2\";\n@fa-bell-o: \"\\f0a2\";\n@fa-coffee: \"\\f0f4\";\n@fa-cutlery: \"\\f0f5\";\n@fa-file-text-o: \"\\f0f6\";\n@fa-building-o: \"\\f0f7\";\n@fa-hospital-o: \"\\f0f8\";\n@fa-ambulance: \"\\f0f9\";\n@fa-medkit: \"\\f0fa\";\n@fa-fighter-jet: \"\\f0fb\";\n@fa-beer: \"\\f0fc\";\n@fa-h-square: \"\\f0fd\";\n@fa-plus-square: \"\\f0fe\";\n@fa-angle-double-left: \"\\f100\";\n@fa-angle-double-right: \"\\f101\";\n@fa-angle-double-up: \"\\f102\";\n@fa-angle-double-down: \"\\f103\";\n@fa-angle-left: \"\\f104\";\n@fa-angle-right: \"\\f105\";\n@fa-angle-up: \"\\f106\";\n@fa-angle-down: \"\\f107\";\n@fa-desktop: \"\\f108\";\n@fa-laptop: \"\\f109\";\n@fa-tablet: \"\\f10a\";\n@fa-mobile: \"\\f10b\";\n@fa-circle-o: \"\\f10c\";\n@fa-quote-left: \"\\f10d\";\n@fa-quote-right: \"\\f10e\";\n@fa-spinner: \"\\f110\";\n@fa-circle: \"\\f111\";\n@fa-reply: \"\\f112\";\n@fa-github-alt: \"\\f113\";\n@fa-folder-o: \"\\f114\";\n@fa-folder-open-o: \"\\f115\";\n@fa-smile-o: \"\\f118\";\n@fa-frown-o: \"\\f119\";\n@fa-meh-o: \"\\f11a\";\n@fa-gamepad: \"\\f11b\";\n@fa-keyboard-o: \"\\f11c\";\n@fa-flag-o: \"\\f11d\";\n@fa-flag-checkered: \"\\f11e\";\n@fa-terminal: \"\\f120\";\n@fa-code: \"\\f121\";\n@fa-reply-all: \"\\f122\";\n@fa-star-half-o: \"\\f123\";\n@fa-location-arrow: \"\\f124\";\n@fa-crop: \"\\f125\";\n@fa-code-fork: \"\\f126\";\n@fa-chain-broken: \"\\f127\";\n@fa-question: \"\\f128\";\n@fa-info: \"\\f129\";\n@fa-exclamation: \"\\f12a\";\n@fa-superscript: \"\\f12b\";\n@fa-subscript: \"\\f12c\";\n@fa-eraser: \"\\f12d\";\n@fa-puzzle-piece: \"\\f12e\";\n@fa-microphone: \"\\f130\";\n@fa-microphone-slash: \"\\f131\";\n@fa-shield: \"\\f132\";\n@fa-calendar-o: \"\\f133\";\n@fa-fire-extinguisher: \"\\f134\";\n@fa-rocket: \"\\f135\";\n@fa-maxcdn: \"\\f136\";\n@fa-chevron-circle-left: \"\\f137\";\n@fa-chevron-circle-right: \"\\f138\";\n@fa-chevron-circle-up: \"\\f139\";\n@fa-chevron-circle-down: \"\\f13a\";\n@fa-html5: \"\\f13b\";\n@fa-css3: \"\\f13c\";\n@fa-anchor: \"\\f13d\";\n@fa-unlock-alt: \"\\f13e\";\n@fa-bullseye: \"\\f140\";\n@fa-ellipsis-h: \"\\f141\";\n@fa-ellipsis-v: \"\\f142\";\n@fa-rss-square: \"\\f143\";\n@fa-play-circle: \"\\f144\";\n@fa-ticket: \"\\f145\";\n@fa-minus-square: \"\\f146\";\n@fa-minus-square-o: \"\\f147\";\n@fa-level-up: \"\\f148\";\n@fa-level-down: \"\\f149\";\n@fa-check-square: \"\\f14a\";\n@fa-pencil-square: \"\\f14b\";\n@fa-external-link-square: \"\\f14c\";\n@fa-share-square: \"\\f14d\";\n@fa-compass: \"\\f14e\";\n@fa-caret-square-o-down: \"\\f150\";\n@fa-caret-square-o-up: \"\\f151\";\n@fa-caret-square-o-right: \"\\f152\";\n@fa-eur: \"\\f153\";\n@fa-gbp: \"\\f154\";\n@fa-usd: \"\\f155\";\n@fa-inr: \"\\f156\";\n@fa-jpy: \"\\f157\";\n@fa-rub: \"\\f158\";\n@fa-krw: \"\\f159\";\n@fa-btc: \"\\f15a\";\n@fa-file: \"\\f15b\";\n@fa-file-text: \"\\f15c\";\n@fa-sort-alpha-asc: \"\\f15d\";\n@fa-sort-alpha-desc: \"\\f15e\";\n@fa-sort-amount-asc: \"\\f160\";\n@fa-sort-amount-desc: \"\\f161\";\n@fa-sort-numeric-asc: \"\\f162\";\n@fa-sort-numeric-desc: \"\\f163\";\n@fa-thumbs-up: \"\\f164\";\n@fa-thumbs-down: \"\\f165\";\n@fa-youtube-square: \"\\f166\";\n@fa-youtube: \"\\f167\";\n@fa-xing: \"\\f168\";\n@fa-xing-square: \"\\f169\";\n@fa-youtube-play: \"\\f16a\";\n@fa-dropbox: \"\\f16b\";\n@fa-stack-overflow: \"\\f16c\";\n@fa-instagram: \"\\f16d\";\n@fa-flickr: \"\\f16e\";\n@fa-adn: \"\\f170\";\n@fa-bitbucket: \"\\f171\";\n@fa-bitbucket-square: \"\\f172\";\n@fa-tumblr: \"\\f173\";\n@fa-tumblr-square: \"\\f174\";\n@fa-long-arrow-down: \"\\f175\";\n@fa-long-arrow-up: \"\\f176\";\n@fa-long-arrow-left: \"\\f177\";\n@fa-long-arrow-right: \"\\f178\";\n@fa-apple: \"\\f179\";\n@fa-windows: \"\\f17a\";\n@fa-android: \"\\f17b\";\n@fa-linux: \"\\f17c\";\n@fa-dribbble: \"\\f17d\";\n@fa-skype: \"\\f17e\";\n@fa-foursquare: \"\\f180\";\n@fa-trello: \"\\f181\";\n@fa-female: \"\\f182\";\n@fa-male: \"\\f183\";\n@fa-gittip: \"\\f184\";\n@fa-sun-o: \"\\f185\";\n@fa-moon-o: \"\\f186\";\n@fa-archive: \"\\f187\";\n@fa-bug: \"\\f188\";\n@fa-vk: \"\\f189\";\n@fa-weibo: \"\\f18a\";\n@fa-cf: \"\\f18b\";\n@fa-pagelines: \"\\f18c\";\n@fa-stack-exchange: \"\\f18d\";\n@fa-arrow-circle-o-right: \"\\f18e\";\n@fa-arrow-circle-o-left: \"\\f190\";\n@fa-caret-square-o-left: \"\\f191\";\n@fa-dot-circle-o: \"\\f192\";\n@fa-wheelchair: \"\\f193\";\n@fa-vimeo-square: \"\\f194\";\n@fa-try: \"\\f195\";\n@fa-plus-square-o: \"\\f196\";\n@fa-space-shuttle: \"\\f197\";\n@fa-slack: \"\\f198\";\n@fa-envelope-square: \"\\f199\";\n@fa-wordpress: \"\\f19a\";\n@fa-openid: \"\\f19b\";\n@fa-university: \"\\f19c\";\n@fa-graduation-cap: \"\\f19d\";\n@fa-yahoo: \"\\f19e\";\n@fa-google: \"\\f1a0\";\n@fa-reddit: \"\\f1a1\";\n@fa-reddit-square: \"\\f1a2\";\n@fa-stumbleupon-circle: \"\\f1a3\";\n@fa-stumbleupon: \"\\f1a4\";\n@fa-delicious: \"\\f1a5\";\n@fa-digg: \"\\f1a6\";\n@fa-pied-piper: \"\\f1a7\";\n@fa-pied-piper-alt: \"\\f1a8\";\n@fa-drupal: \"\\f1a9\";\n@fa-joomla: \"\\f1aa\";\n@fa-language: \"\\f1ab\";\n@fa-fax: \"\\f1ac\";\n@fa-building: \"\\f1ad\";\n@fa-child: \"\\f1ae\";\n@fa-paw: \"\\f1b0\";\n@fa-spoon: \"\\f1b1\";\n@fa-cube: \"\\f1b2\";\n@fa-cubes: \"\\f1b3\";\n@fa-behance: \"\\f1b4\";\n@fa-behance-square: \"\\f1b5\";\n@fa-steam: \"\\f1b6\";\n@fa-steam-square: \"\\f1b7\";\n@fa-recycle: \"\\f1b8\";\n@fa-car: \"\\f1b9\";\n@fa-taxi: \"\\f1ba\";\n@fa-tree: \"\\f1bb\";\n@fa-spotify: \"\\f1bc\";\n@fa-deviantart: \"\\f1bd\";\n@fa-soundcloud: \"\\f1be\";\n@fa-database: \"\\f1c0\";\n@fa-file-pdf-o: \"\\f1c1\";\n@fa-file-word-o: \"\\f1c2\";\n@fa-file-excel-o: \"\\f1c3\";\n@fa-file-powerpoint-o: \"\\f1c4\";\n@fa-file-image-o: \"\\f1c5\";\n@fa-file-archive-o: \"\\f1c6\";\n@fa-file-audio-o: \"\\f1c7\";\n@fa-file-video-o: \"\\f1c8\";\n@fa-file-code-o: \"\\f1c9\";\n@fa-vine: \"\\f1ca\";\n@fa-codepen: \"\\f1cb\";\n@fa-jsfiddle: \"\\f1cc\";\n@fa-life-ring: \"\\f1cd\";\n@fa-circle-o-notch: \"\\f1ce\";\n@fa-rebel: \"\\f1d0\";\n@fa-empire: \"\\f1d1\";\n@fa-git-square: \"\\f1d2\";\n@fa-git: \"\\f1d3\";\n@fa-hacker-news: \"\\f1d4\";\n@fa-tencent-weibo: \"\\f1d5\";\n@fa-qq: \"\\f1d6\";\n@fa-weixin: \"\\f1d7\";\n@fa-paper-plane: \"\\f1d8\";\n@fa-paper-plane-o: \"\\f1d9\";\n@fa-history: \"\\f1da\";\n@fa-circle-thin: \"\\f1db\";\n@fa-header: \"\\f1dc\";\n@fa-paragraph: \"\\f1dd\";\n@fa-sliders: \"\\f1de\";\n@fa-share-alt: \"\\f1e0\";\n@fa-share-alt-square: \"\\f1e1\";\n@fa-bomb: \"\\f1e2\";\n@fa-futbol-o: \"\\f1e3\";\n@fa-tty: \"\\f1e4\";\n@fa-binoculars: \"\\f1e5\";\n@fa-plug: \"\\f1e6\";\n@fa-slideshare: \"\\f1e7\";\n@fa-twitch: \"\\f1e8\";\n@fa-yelp: \"\\f1e9\";\n@fa-newspaper-o: \"\\f1ea\";\n@fa-wifi: \"\\f1eb\";\n@fa-calculator: \"\\f1ec\";\n@fa-paypal: \"\\f1ed\";\n@fa-google-wallet: \"\\f1ee\";\n@fa-cc-visa: \"\\f1f0\";\n@fa-cc-mastercard: \"\\f1f1\";\n@fa-cc-discover: \"\\f1f2\";\n@fa-cc-amex: \"\\f1f3\";\n@fa-cc-paypal: \"\\f1f4\";\n@fa-cc-stripe: \"\\f1f5\";\n@fa-bell-slash: \"\\f1f6\";\n@fa-bell-slash-o: \"\\f1f7\";\n@fa-trash: \"\\f1f8\";\n@fa-copyright: \"\\f1f9\";\n@fa-at: \"\\f1fa\";\n@fa-eyedropper: \"\\f1fb\";\n@fa-paint-brush: \"\\f1fc\";\n@fa-birthday-cake: \"\\f1fd\";\n@fa-area-chart: \"\\f1fe\";\n@fa-pie-chart: \"\\f200\";\n@fa-line-chart: \"\\f201\";\n@fa-lastfm: \"\\f202\";\n@fa-lastfm-square: \"\\f203\";\n@fa-toggle-off: \"\\f204\";\n@fa-toggle-on: \"\\f205\";\n@fa-bicycle: \"\\f206\";\n@fa-bus: \"\\f207\";\n@fa-ioxhost: \"\\f208\";\n@fa-angellist: \"\\f209\";\n@fa-cc: \"\\f20a\";\n@fa-ils: \"\\f20b\";\n@fa-meanpath: \"\\f20c\";\n\n"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/plugins/ztree/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.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"
  },
  {
    "path": "open-layui-web/src/main/view/static/public/plugins/ztree/css/zTreeStyle/zTreeStyle.css",
    "content": "/*-------------------------------------\nzTree Style\n\nversion:\t3.5.19\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": "open-monitor-center/cachecloud/LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"{}\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright {yyyy} {name of copyright owner}\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"
  },
  {
    "path": "open-monitor-center/cachecloud/README.md",
    "content": "### CacheCloud团队于2017年3月出版实体书《Redis开发与运维》，[更多详情请见](#cc10)\n\n## <a name=\"index\"/>目录&nbsp;&nbsp;(具体细节[wiki文档](https://github.com/sohutv/cachecloud/wiki \"Cachecloud Wiki\")、[博客](http://cachecloud.github.io/ \"Cachecloud page\")、QQ群：534429768)\n* [一、CacheCloud是做什么的](#cc1)\n* [二、CacheCloud提供哪些功能](#cc2)\n* [三、CacheCloud解决什么问题](#cc3)\n* [四、CacheCloud提供的价值](#cc4) \n* [五、CacheCloud在搜狐的规模](#cc5)\n* [六、CacheCloud环境需求](#cc6)\n* [七、CacheCloud相关文档](#cc7)\n    * [1.快速开始](#cc7)\n    * [2.常见问题](#cc7)\n    * [3.开发计划](#cc7)\n    * [4.已存在Redis接入CacheCloud](#cc7)\n    * [5.迁移工具](#cc7)\n* [八、CacheCloud开发计划TODO LIST](#cc8)\n* [九、CacheCloud已知用户](#cc9)\n* [十、Redis开发与运维图书](#cc10)\n\n<a name=\"cc1\"/>\n\n## 一、CacheCloud是做什么的\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CacheCloud提供一个Redis云管理平台：实现多种类型(**Redis Standalone**、**Redis Sentinel**、**Redis Cluster**)自动部署、解决Redis实例碎片化现象、提供完善统计、监控、运维功能、减少运维成本和误操作，提高机器的利用率，提供灵活的伸缩性，提供方便的接入客户端。\n\n![](http://i0.itc.cn/20170624/3084_753fa711_4d1d_7f51_7405_07723c1e43f6_1.png)\n\n<a name=\"cc2\"/>\n\n## 二、CacheCloud提供哪些功能\n\n+ **监控统计：**\t提供了机器、应用、实例下各个维度数据的监控和统计界面。\n+ **一键开启：**\tRedis Standalone、Redis Sentinel、Redis Cluster三种类型的应用，无需手动配置初始化。\n+ **Failover：**\t支持哨兵,集群的高可用模式。\n+ **伸缩：**\t    提供完善的垂直和水平在线伸缩功能。\n+ **完善运维：**    提供自动运维和简化运维操作功能，避免纯手工运维出错。\n+ **方便的客户端**  方便快捷的客户端接入。\n+ **元数据管理：**    提供机器、应用、实例、用户信息管理。\n+ **流程化：**      提供申请，运维，伸缩，修改等完善的处理流程\n+ **一键导入：**      [一键导入已经存在Redis](http://cachecloud.github.io/2016/04/17/%E5%B7%B2%E5%AD%98%E5%9C%A8Redis%E6%8E%A5%E5%85%A5CacheCloud/)\n\n\n<a name=\"cc3\"/>\n\n## 三、CacheCloud解决什么问题\n\n![](http://i3.itc.cn/20160125/3084_e6f2f51c_54cf_4081_450f_c69998e74d01_1.png)\n\n#### 1.部署成本\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Redis多机(Redis-Sentinel, Redis-Cluster)部署和配置相对比较复杂，较容易出错。例如：100个redis数据节点组成的redis-cluster集群，如果单纯手工安装，既耗时又容易出错。\n\n#### 2.实例碎片化\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;作为一个Redis管理员(可以看做redis DBA)需要帮助开发者管理上百个Redis-Cluster集群，分布在数百台机器上，人工维护成本很高，需要自动化运维工具。\n\n#### 3. 监控、统计和管理不完善\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;一些开源的Redis监控和管理工具，例如：RedisLive(Python)、Redis Commander(Node.js)，Redmon(Ruby)无论从功能的全面性(例如配置管理，支持Redis-Cluster等等)、扩展性很难满足需求。\n\n#### 4. 运维成本\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Redis的使用者需要维护各自的Redis，但是用户可能更加善于使用Redis实现各种功能，但是没有足够的精力和经验维护Redis。Redis的开发人员如同使用MySQL一样，不需要运维Mysql服务器，同样使用Redis服务，不要自己运维Redis，Redis由一些在Redis运维方面更有经验的人来维护（保证高可用，高扩展性），使得开发者更加关注于Redis使用本身。\n\n#### 5. 伸缩性\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;本产品支持Redis最新的Redis-Sentinel、Redis-Cluster集群机构，既满足Redis高可用性、又能满足Redis的可扩展性，具有较强的容量和性能伸缩能力。\n\n#### 6. 经济成本\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;机器利用率低，各个项目组的Redis较为分散的部署在各自服务器上，造成了大量闲置资源没有有效利用。 \n\n#### 7. 版本不统一 \n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;各个项目的Redis使用各种不同的版本，不便于管理和交互。\n\n<a name=\"cc4\"/>\n\n## 四、CacheCloud提供的价值\n\n+ 规模化自动运维：\t降低运维成本，降低人为操作出错率。\n+ 自由伸缩：\t    提供灵活的伸缩性，应用扩容/收缩成本降低，机器资源得到重复利用。\n+ 团队提升，开源贡献:提升云产品开发设计经验,自己作为开发者和使用者。\n\n<a name=\"cc5\"/>\n\n## 五、CacheCloud在搜狐的规模\n\n+ 每天500+亿次命令调用\n+ 2T+的内存空间\n+ 1600+个Redis实例\n+ 200+台机器\n\n<a name=\"cc6\"/>\n\n## 六、CacheCloud环境需求\n\n+ JDK 7+\n+ Maven 3\n+ MySQL 5.5\n+ Redis 3\n\n<a name=\"cc7\"/>\n\n## 七、相关文档\n\n+ [快速开始](https://github.com/sohutv/cachecloud/wiki/3.%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%AB%AF%E6%8E%A5%E5%85%A5%E6%96%87%E6%A1%A3)\n+ [常见问题](http://cachecloud.github.io/2016/04/12/CacheCloud%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98/)\n+ [已存在Redis接入CacheCloud](http://cachecloud.github.io/2016/04/17/%E5%B7%B2%E5%AD%98%E5%9C%A8Redis%E6%8E%A5%E5%85%A5CacheCloud/)\n+ [资源归档](http://cachecloud.github.io/2016/04/12/CacheCloud%E6%96%87%E6%A1%A3%E5%BD%92%E6%A1%A3/)\n+ [开发计划](http://cachecloud.github.io/2016/04/17/v2%E8%AE%A1%E5%88%92/)\n+ [迁移工具](http://cachecloud.github.io/2016/06/28/1.2.%20%E8%BF%81%E7%A7%BB%E5%B7%A5%E5%85%B7%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E/)\n\n### 更多内容参考：[wiki文档](https://github.com/sohutv/cachecloud/wiki)、[cachecloud官方博客](http://cachecloud.github.io/)\n\n<a name=\"cc8\"/>\n\n## 八、开发计划-TODO LIST\n\n[后期开发计划](http://cachecloud.github.io/2016/04/17/v2%E8%AE%A1%E5%88%92/)\n\n<a name=\"cc9\"/>\n\n## 九、已知用户\n\n![](http://i0.itc.cn/20170315/3084_f3e50a44_c732_9ac2_e117_90759d8e406b_1.png)\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;除此之外，还有天津联怡科技有限公司、瑞友科技、厦门美好出行物联网技术有限公司、北京九瑞网络科技有限公司、深圳市深软信息技术有限公司、欧乐在线科技有限公司、慧科教育、上海仁画信息股份有限公司等。\n\n<a name=\"cc10\"/>\n\n## 十、图书\n由CacheCloud团队撰写的实体书《Redis开发与运维》(机械工业出版)已在各大网店售卖，本书包含了CacheCloud团队在Redis规模化开发运维大量经验，以及Cachecloud更为系统的介绍，[目录介绍和购买地址](https://cachecloud.github.io/2016/10/24/Redis3%E5%BC%80%E5%8F%91%E8%BF%90%E7%BB%B4%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5-%E7%9B%AE%E5%BD%95/)，欢迎大家指教和购买。\n\n### 相关样章\n\n1.[Redis架构之防雪崩设计：网站不宕机背后的兵法](https://mp.weixin.qq.com/s/TBCEwLVAXdsTszRVpXhVug)\n\n2.[Redis的内存优化](https://cachecloud.github.io/2017/02/16/Redis%E5%86%85%E5%AD%98%E4%BC%98%E5%8C%96/)\n\n3.[Redis的Linux系统优化](https://cachecloud.github.io/2017/02/16/Redis%E7%9A%84Linux%E7%B3%BB%E7%BB%9F%E4%BC%98%E5%8C%96/)\n\n4.[Redis客户端常见异常分析](https://cachecloud.github.io/2017/02/20/Redis%E7%83%AD%E7%82%B9key%E5%AF%BB%E6%89%BE%E4%B8%8E%E4%BC%98%E5%8C%96/)\n\n5.[Redis热点key寻找与优化](https://cachecloud.github.io/2017/02/20/Redis%E7%83%AD%E7%82%B9key%E5%AF%BB%E6%89%BE%E4%B8%8E%E4%BC%98%E5%8C%96/)\n\n6.[Redis无限全量复制问题分析与优化](https://cachecloud.github.io/2016/11/24/%E5%85%A8%E9%87%8F%E5%A4%8D%E5%88%B6%E9%97%AE%E9%A2%98/)\n\n![](http://i0.itc.cn/20170527/3084_cfcdad5a_0310_c17e_f80b_064afb296b75_1.jpeg)\n\n\n\n## 十一、支持与帮助\n\n如果你觉得CacheCloud对你有帮助，欢迎Star。\n \n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/.gitignore",
    "content": "/bin/\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\"\n\txmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n\t<modelVersion>4.0.0</modelVersion>\n\t<parent>\n\t\t<groupId>com.sohu.tv</groupId>\n\t\t<artifactId>cachecloud-open-client</artifactId>\n\t\t<version>1.0-SNAPSHOT</version>\n\t</parent>\n\t<groupId>com.sohu.tv</groupId>\n\t<artifactId>cachecloud-jedis</artifactId>\n\t<version>1.0-SNAPSHOT</version>\n\t<name>cachecloud-jedis</name>\n\t<url>http://maven.apache.org</url>\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>junit</groupId>\n\t\t\t<artifactId>junit</artifactId>\n\t\t\t<type>jar</type>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.apache.commons</groupId>\n\t\t\t<artifactId>commons-pool2</artifactId>\n\t\t\t<version>2.3</version>\n\t\t\t<type>jar</type>\n\t\t\t<scope>compile</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.slf4j</groupId>\n\t\t\t<artifactId>slf4j-api</artifactId>\n\t\t\t<scope>compile</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>com.dyuproject.protostuff</groupId>\n\t\t\t<artifactId>protostuff-runtime</artifactId>\n\t\t\t<version>1.0.8</version>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.dyuproject.protostuff</groupId>\n\t\t\t<artifactId>protostuff-core</artifactId>\n\t\t\t<version>1.0.8</version>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.sohu.tv</groupId>\n\t\t\t<artifactId>cachecloud-open-client-basic</artifactId>\n\t\t\t<version>1.0-SNAPSHOT</version>\n\t\t</dependency>\n\n\t</dependencies>\n\n</project>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/BinaryClient.java",
    "content": "package redis.clients.jedis;\n\nimport static redis.clients.jedis.Protocol.sendCommand;\nimport static redis.clients.jedis.Protocol.toByteArray;\nimport static redis.clients.jedis.Protocol.Command.*;\nimport static redis.clients.jedis.Protocol.Keyword.ENCODING;\nimport static redis.clients.jedis.Protocol.Keyword.IDLETIME;\nimport static redis.clients.jedis.Protocol.Keyword.LEN;\nimport static redis.clients.jedis.Protocol.Keyword.LIMIT;\nimport static redis.clients.jedis.Protocol.Keyword.NO;\nimport static redis.clients.jedis.Protocol.Keyword.ONE;\nimport static redis.clients.jedis.Protocol.Keyword.REFCOUNT;\nimport static redis.clients.jedis.Protocol.Keyword.RESET;\nimport static redis.clients.jedis.Protocol.Keyword.STORE;\nimport static redis.clients.jedis.Protocol.Keyword.WITHSCORES;\n\nimport java.lang.reflect.Array;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\n\nimport redis.clients.jedis.Protocol.Command;\nimport redis.clients.jedis.Protocol.Keyword;\nimport redis.clients.jedis.params.geo.GeoRadiusParam;\nimport redis.clients.jedis.params.set.SetParams;\nimport redis.clients.jedis.params.sortedset.ZAddParams;\nimport redis.clients.jedis.params.sortedset.ZIncrByParams;\nimport redis.clients.util.SafeEncoder;\n\npublic class BinaryClient extends Connection {\n  public enum LIST_POSITION {\n    BEFORE, AFTER;\n    public final byte[] raw;\n\n    private LIST_POSITION() {\n      raw = SafeEncoder.encode(name());\n    }\n  }\n\n  private boolean isInMulti;\n\n  private String password;\n\n  private int db;\n\n  private boolean isInWatch;\n\n  public boolean isInMulti() {\n    return isInMulti;\n  }\n\n  public boolean isInWatch() {\n    return isInWatch;\n  }\n\n  public BinaryClient() {\n    super();\n  }\n\n  public BinaryClient(final String host) {\n    super(host);\n  }\n\n  public BinaryClient(final String host, final int port) {\n    super(host, port);\n  }\n\n  private byte[][] joinParameters(byte[] first, byte[][] rest) {\n    byte[][] result = new byte[rest.length + 1][];\n    result[0] = first;\n    System.arraycopy(rest, 0, result, 1, rest.length);\n    return result;\n  }\n\n  public void setPassword(final String password) {\n    this.password = password;\n  }\n\n  public void setDb(int db) {\n    this.db = db;\n  }\n\n  @Override\n  public void connect() {\n    if (!isConnected()) {\n      super.connect();\n      if (password != null) {\n        auth(password);\n        getStatusCodeReply();\n      }\n      if (db > 0) {\n        select(Long.valueOf(db).intValue());\n        getStatusCodeReply();\n      }\n    }\n  }\n\n  public void ping() {\n    sendCommand(Command.PING);\n  }\n\n  public void set(final byte[] key, final byte[] value) {\n    sendCommand(Command.SET, key, value);\n  }\n\n  public void set(final byte[] key, final byte[] value, final SetParams params) {\n    sendCommand(Command.SET, params.getByteParams(key, value));\n  }\n\n  public void get(final byte[] key) {\n    sendCommand(Command.GET, key);\n  }\n\n  public void quit() {\n    db = 0;\n    sendCommand(QUIT);\n  }\n\n  public void exists(final byte[]... keys) {\n    sendCommand(EXISTS, keys);\n  }\n\n  public void exists(final byte[] key) {\n    sendCommand(EXISTS, key);\n  }\n\n  public void del(final byte[]... keys) {\n    sendCommand(DEL, keys);\n  }\n\n  public void type(final byte[] key) {\n    sendCommand(TYPE, key);\n  }\n\n  public void flushDB() {\n    sendCommand(FLUSHDB);\n  }\n\n  public void keys(final byte[] pattern) {\n    sendCommand(KEYS, pattern);\n  }\n\n  public void randomKey() {\n    sendCommand(RANDOMKEY);\n  }\n\n  public void rename(final byte[] oldkey, final byte[] newkey) {\n    sendCommand(RENAME, oldkey, newkey);\n  }\n\n  public void renamenx(final byte[] oldkey, final byte[] newkey) {\n    sendCommand(RENAMENX, oldkey, newkey);\n  }\n\n  public void dbSize() {\n    sendCommand(DBSIZE);\n  }\n\n  public void expire(final byte[] key, final int seconds) {\n    sendCommand(EXPIRE, key, toByteArray(seconds));\n  }\n\n  public void expireAt(final byte[] key, final long unixTime) {\n    sendCommand(EXPIREAT, key, toByteArray(unixTime));\n  }\n\n  public void ttl(final byte[] key) {\n    sendCommand(TTL, key);\n  }\n\n  public void select(final int index) {\n    sendCommand(SELECT, toByteArray(index));\n  }\n\n  public void move(final byte[] key, final int dbIndex) {\n    sendCommand(MOVE, key, toByteArray(dbIndex));\n  }\n\n  public void flushAll() {\n    sendCommand(FLUSHALL);\n  }\n\n  public void getSet(final byte[] key, final byte[] value) {\n    sendCommand(GETSET, key, value);\n  }\n\n  public void mget(final byte[]... keys) {\n    sendCommand(MGET, keys);\n  }\n\n  public void setnx(final byte[] key, final byte[] value) {\n    sendCommand(SETNX, key, value);\n  }\n\n  public void setex(final byte[] key, final int seconds, final byte[] value) {\n    sendCommand(SETEX, key, toByteArray(seconds), value);\n  }\n\n  public void mset(final byte[]... keysvalues) {\n    sendCommand(MSET, keysvalues);\n  }\n\n  public void msetnx(final byte[]... keysvalues) {\n    sendCommand(MSETNX, keysvalues);\n  }\n\n  public void decrBy(final byte[] key, final long integer) {\n    sendCommand(DECRBY, key, toByteArray(integer));\n  }\n\n  public void decr(final byte[] key) {\n    sendCommand(DECR, key);\n  }\n\n  public void incrBy(final byte[] key, final long integer) {\n    sendCommand(INCRBY, key, toByteArray(integer));\n  }\n\n  public void incrByFloat(final byte[] key, final double value) {\n    sendCommand(INCRBYFLOAT, key, toByteArray(value));\n  }\n\n  public void incr(final byte[] key) {\n    sendCommand(INCR, key);\n  }\n\n  public void append(final byte[] key, final byte[] value) {\n    sendCommand(APPEND, key, value);\n  }\n\n  public void substr(final byte[] key, final int start, final int end) {\n    sendCommand(SUBSTR, key, toByteArray(start), toByteArray(end));\n  }\n\n  public void hset(final byte[] key, final byte[] field, final byte[] value) {\n    sendCommand(HSET, key, field, value);\n  }\n\n  public void hget(final byte[] key, final byte[] field) {\n    sendCommand(HGET, key, field);\n  }\n\n  public void hsetnx(final byte[] key, final byte[] field, final byte[] value) {\n    sendCommand(HSETNX, key, field, value);\n  }\n\n  public void hmset(final byte[] key, final Map<byte[], byte[]> hash) {\n    final List<byte[]> params = new ArrayList<byte[]>();\n    params.add(key);\n\n    for (final Entry<byte[], byte[]> entry : hash.entrySet()) {\n      params.add(entry.getKey());\n      params.add(entry.getValue());\n    }\n    sendCommand(HMSET, params.toArray(new byte[params.size()][]));\n  }\n\n  public void hmget(final byte[] key, final byte[]... fields) {\n    final byte[][] params = new byte[fields.length + 1][];\n    params[0] = key;\n    System.arraycopy(fields, 0, params, 1, fields.length);\n    sendCommand(HMGET, params);\n  }\n\n  public void hincrBy(final byte[] key, final byte[] field, final long value) {\n    sendCommand(HINCRBY, key, field, toByteArray(value));\n  }\n\n  public void hexists(final byte[] key, final byte[] field) {\n    sendCommand(HEXISTS, key, field);\n  }\n\n  public void hdel(final byte[] key, final byte[]... fields) {\n    sendCommand(HDEL, joinParameters(key, fields));\n  }\n\n  public void hlen(final byte[] key) {\n    sendCommand(HLEN, key);\n  }\n\n  public void hkeys(final byte[] key) {\n    sendCommand(HKEYS, key);\n  }\n\n  public void hvals(final byte[] key) {\n    sendCommand(HVALS, key);\n  }\n\n  public void hgetAll(final byte[] key) {\n    sendCommand(HGETALL, key);\n  }\n\n  public void rpush(final byte[] key, final byte[]... strings) {\n    sendCommand(RPUSH, joinParameters(key, strings));\n  }\n\n  public void lpush(final byte[] key, final byte[]... strings) {\n    sendCommand(LPUSH, joinParameters(key, strings));\n  }\n\n  public void llen(final byte[] key) {\n    sendCommand(LLEN, key);\n  }\n\n  public void lrange(final byte[] key, final long start, final long end) {\n    sendCommand(LRANGE, key, toByteArray(start), toByteArray(end));\n  }\n\n  public void ltrim(final byte[] key, final long start, final long end) {\n    sendCommand(LTRIM, key, toByteArray(start), toByteArray(end));\n  }\n\n  public void lindex(final byte[] key, final long index) {\n    sendCommand(LINDEX, key, toByteArray(index));\n  }\n\n  public void lset(final byte[] key, final long index, final byte[] value) {\n    sendCommand(LSET, key, toByteArray(index), value);\n  }\n\n  public void lrem(final byte[] key, long count, final byte[] value) {\n    sendCommand(LREM, key, toByteArray(count), value);\n  }\n\n  public void lpop(final byte[] key) {\n    sendCommand(LPOP, key);\n  }\n\n  public void rpop(final byte[] key) {\n    sendCommand(RPOP, key);\n  }\n\n  public void rpoplpush(final byte[] srckey, final byte[] dstkey) {\n    sendCommand(RPOPLPUSH, srckey, dstkey);\n  }\n\n  public void sadd(final byte[] key, final byte[]... members) {\n    sendCommand(SADD, joinParameters(key, members));\n  }\n\n  public void smembers(final byte[] key) {\n    sendCommand(SMEMBERS, key);\n  }\n\n  public void srem(final byte[] key, final byte[]... members) {\n    sendCommand(SREM, joinParameters(key, members));\n  }\n\n  public void spop(final byte[] key) {\n    sendCommand(SPOP, key);\n  }\n\n  public void spop(final byte[] key, final long count) {\n    sendCommand(SPOP, key, toByteArray(count));\n  }\n\n  public void smove(final byte[] srckey, final byte[] dstkey, final byte[] member) {\n    sendCommand(SMOVE, srckey, dstkey, member);\n  }\n\n  public void scard(final byte[] key) {\n    sendCommand(SCARD, key);\n  }\n\n  public void sismember(final byte[] key, final byte[] member) {\n    sendCommand(SISMEMBER, key, member);\n  }\n\n  public void sinter(final byte[]... keys) {\n    sendCommand(SINTER, keys);\n  }\n\n  public void sinterstore(final byte[] dstkey, final byte[]... keys) {\n    final byte[][] params = new byte[keys.length + 1][];\n    params[0] = dstkey;\n    System.arraycopy(keys, 0, params, 1, keys.length);\n    sendCommand(SINTERSTORE, params);\n  }\n\n  public void sunion(final byte[]... keys) {\n    sendCommand(SUNION, keys);\n  }\n\n  public void sunionstore(final byte[] dstkey, final byte[]... keys) {\n    byte[][] params = new byte[keys.length + 1][];\n    params[0] = dstkey;\n    System.arraycopy(keys, 0, params, 1, keys.length);\n    sendCommand(SUNIONSTORE, params);\n  }\n\n  public void sdiff(final byte[]... keys) {\n    sendCommand(SDIFF, keys);\n  }\n\n  public void sdiffstore(final byte[] dstkey, final byte[]... keys) {\n    byte[][] params = new byte[keys.length + 1][];\n    params[0] = dstkey;\n    System.arraycopy(keys, 0, params, 1, keys.length);\n    sendCommand(SDIFFSTORE, params);\n  }\n\n  public void srandmember(final byte[] key) {\n    sendCommand(SRANDMEMBER, key);\n  }\n\n  public void zadd(final byte[] key, final double score, final byte[] member) {\n    sendCommand(ZADD, key, toByteArray(score), member);\n  }\n\n  public void zadd(final byte[] key, final double score, final byte[] member,\n      final ZAddParams params) {\n    sendCommand(ZADD, params.getByteParams(key, toByteArray(score), member));\n  }\n\n  public void zadd(final byte[] key, final Map<byte[], Double> scoreMembers) {\n    ArrayList<byte[]> args = new ArrayList<byte[]>(scoreMembers.size() * 2 + 1);\n    args.add(key);\n    args.addAll(convertScoreMembersToByteArrays(scoreMembers));\n\n    byte[][] argsArray = new byte[args.size()][];\n    args.toArray(argsArray);\n\n    sendCommand(ZADD, argsArray);\n  }\n\n  public void zadd(final byte[] key, final Map<byte[], Double> scoreMembers, final ZAddParams params) {\n    ArrayList<byte[]> args = convertScoreMembersToByteArrays(scoreMembers);\n    byte[][] argsArray = new byte[args.size()][];\n    args.toArray(argsArray);\n\n    sendCommand(ZADD, params.getByteParams(key, argsArray));\n  }\n\n  public void zrange(final byte[] key, final long start, final long end) {\n    sendCommand(ZRANGE, key, toByteArray(start), toByteArray(end));\n  }\n\n  public void zrem(final byte[] key, final byte[]... members) {\n    sendCommand(ZREM, joinParameters(key, members));\n  }\n\n  public void zincrby(final byte[] key, final double score, final byte[] member) {\n    sendCommand(ZINCRBY, key, toByteArray(score), member);\n  }\n\n  public void zincrby(final byte[] key, final double score, final byte[] member,\n      final ZIncrByParams params) {\n    // Note that it actually calls ZADD with INCR option, so it requires Redis 3.0.2 or upper.\n    sendCommand(ZADD, params.getByteParams(key, toByteArray(score), member));\n  }\n\n  public void zrank(final byte[] key, final byte[] member) {\n    sendCommand(ZRANK, key, member);\n  }\n\n  public void zrevrank(final byte[] key, final byte[] member) {\n    sendCommand(ZREVRANK, key, member);\n  }\n\n  public void zrevrange(final byte[] key, final long start, final long end) {\n    sendCommand(ZREVRANGE, key, toByteArray(start), toByteArray(end));\n  }\n\n  public void zrangeWithScores(final byte[] key, final long start, final long end) {\n    sendCommand(ZRANGE, key, toByteArray(start), toByteArray(end), WITHSCORES.raw);\n  }\n\n  public void zrevrangeWithScores(final byte[] key, final long start, final long end) {\n    sendCommand(ZREVRANGE, key, toByteArray(start), toByteArray(end), WITHSCORES.raw);\n  }\n\n  public void zcard(final byte[] key) {\n    sendCommand(ZCARD, key);\n  }\n\n  public void zscore(final byte[] key, final byte[] member) {\n    sendCommand(ZSCORE, key, member);\n  }\n\n  public void multi() {\n    sendCommand(MULTI);\n    isInMulti = true;\n  }\n\n  public void discard() {\n    sendCommand(DISCARD);\n    isInMulti = false;\n    isInWatch = false;\n  }\n\n  public void exec() {\n    sendCommand(EXEC);\n    isInMulti = false;\n    isInWatch = false;\n  }\n\n  public void watch(final byte[]... keys) {\n    sendCommand(WATCH, keys);\n    isInWatch = true;\n  }\n\n  public void unwatch() {\n    sendCommand(UNWATCH);\n    isInWatch = false;\n  }\n\n  public void sort(final byte[] key) {\n    sendCommand(SORT, key);\n  }\n\n  public void sort(final byte[] key, final SortingParams sortingParameters) {\n    final List<byte[]> args = new ArrayList<byte[]>();\n    args.add(key);\n    args.addAll(sortingParameters.getParams());\n    sendCommand(SORT, args.toArray(new byte[args.size()][]));\n  }\n\n  public void blpop(final byte[][] args) {\n    sendCommand(BLPOP, args);\n  }\n\n  public void blpop(final int timeout, final byte[]... keys) {\n    final List<byte[]> args = new ArrayList<byte[]>();\n    for (final byte[] arg : keys) {\n      args.add(arg);\n    }\n    args.add(Protocol.toByteArray(timeout));\n    blpop(args.toArray(new byte[args.size()][]));\n  }\n\n  public void sort(final byte[] key, final SortingParams sortingParameters, final byte[] dstkey) {\n    final List<byte[]> args = new ArrayList<byte[]>();\n    args.add(key);\n    args.addAll(sortingParameters.getParams());\n    args.add(STORE.raw);\n    args.add(dstkey);\n    sendCommand(SORT, args.toArray(new byte[args.size()][]));\n  }\n\n  public void sort(final byte[] key, final byte[] dstkey) {\n    sendCommand(SORT, key, STORE.raw, dstkey);\n  }\n\n  public void brpop(final byte[][] args) {\n    sendCommand(BRPOP, args);\n  }\n\n  public void brpop(final int timeout, final byte[]... keys) {\n    final List<byte[]> args = new ArrayList<byte[]>();\n    for (final byte[] arg : keys) {\n      args.add(arg);\n    }\n    args.add(Protocol.toByteArray(timeout));\n    brpop(args.toArray(new byte[args.size()][]));\n  }\n\n  public void auth(final String password) {\n    setPassword(password);\n    sendCommand(AUTH, password);\n  }\n\n  public void subscribe(final byte[]... channels) {\n    sendCommand(SUBSCRIBE, channels);\n  }\n\n  public void publish(final byte[] channel, final byte[] message) {\n    sendCommand(PUBLISH, channel, message);\n  }\n\n  public void unsubscribe() {\n    sendCommand(UNSUBSCRIBE);\n  }\n\n  public void unsubscribe(final byte[]... channels) {\n    sendCommand(UNSUBSCRIBE, channels);\n  }\n\n  public void psubscribe(final byte[]... patterns) {\n    sendCommand(PSUBSCRIBE, patterns);\n  }\n\n  public void punsubscribe() {\n    sendCommand(PUNSUBSCRIBE);\n  }\n\n  public void punsubscribe(final byte[]... patterns) {\n    sendCommand(PUNSUBSCRIBE, patterns);\n  }\n\n  public void pubsub(final byte[]... args) {\n    sendCommand(PUBSUB, args);\n  }\n\n  public void zcount(final byte[] key, final double min, final double max) {\n\n    byte byteArrayMin[] = (min == Double.NEGATIVE_INFINITY) ? \"-inf\".getBytes() : toByteArray(min);\n    byte byteArrayMax[] = (max == Double.POSITIVE_INFINITY) ? \"+inf\".getBytes() : toByteArray(max);\n\n    sendCommand(ZCOUNT, key, byteArrayMin, byteArrayMax);\n  }\n\n  public void zcount(final byte[] key, final byte min[], final byte max[]) {\n    sendCommand(ZCOUNT, key, min, max);\n  }\n\n  public void zcount(final byte[] key, final String min, final String max) {\n    sendCommand(ZCOUNT, key, min.getBytes(), max.getBytes());\n  }\n\n  public void zrangeByScore(final byte[] key, final double min, final double max) {\n\n    byte byteArrayMin[] = (min == Double.NEGATIVE_INFINITY) ? \"-inf\".getBytes() : toByteArray(min);\n    byte byteArrayMax[] = (max == Double.POSITIVE_INFINITY) ? \"+inf\".getBytes() : toByteArray(max);\n\n    sendCommand(ZRANGEBYSCORE, key, byteArrayMin, byteArrayMax);\n  }\n\n  public void zrangeByScore(final byte[] key, final byte[] min, final byte[] max) {\n    sendCommand(ZRANGEBYSCORE, key, min, max);\n  }\n\n  public void zrangeByScore(final byte[] key, final String min, final String max) {\n    sendCommand(ZRANGEBYSCORE, key, min.getBytes(), max.getBytes());\n  }\n\n  public void zrevrangeByScore(final byte[] key, final double max, final double min) {\n\n    byte byteArrayMin[] = (min == Double.NEGATIVE_INFINITY) ? \"-inf\".getBytes() : toByteArray(min);\n    byte byteArrayMax[] = (max == Double.POSITIVE_INFINITY) ? \"+inf\".getBytes() : toByteArray(max);\n\n    sendCommand(ZREVRANGEBYSCORE, key, byteArrayMax, byteArrayMin);\n  }\n\n  public void zrevrangeByScore(final byte[] key, final byte[] max, final byte[] min) {\n    sendCommand(ZREVRANGEBYSCORE, key, max, min);\n  }\n\n  public void zrevrangeByScore(final byte[] key, final String max, final String min) {\n    sendCommand(ZREVRANGEBYSCORE, key, max.getBytes(), min.getBytes());\n  }\n\n  public void zrangeByScore(final byte[] key, final double min, final double max, final int offset,\n      int count) {\n\n    byte byteArrayMin[] = (min == Double.NEGATIVE_INFINITY) ? \"-inf\".getBytes() : toByteArray(min);\n    byte byteArrayMax[] = (max == Double.POSITIVE_INFINITY) ? \"+inf\".getBytes() : toByteArray(max);\n\n    sendCommand(ZRANGEBYSCORE, key, byteArrayMin, byteArrayMax, LIMIT.raw, toByteArray(offset),\n      toByteArray(count));\n  }\n\n  public void zrangeByScore(final byte[] key, final String min, final String max, final int offset,\n      int count) {\n\n    sendCommand(ZRANGEBYSCORE, key, min.getBytes(), max.getBytes(), LIMIT.raw, toByteArray(offset),\n      toByteArray(count));\n  }\n\n  public void zrevrangeByScore(final byte[] key, final double max, final double min,\n      final int offset, int count) {\n\n    byte byteArrayMin[] = (min == Double.NEGATIVE_INFINITY) ? \"-inf\".getBytes() : toByteArray(min);\n    byte byteArrayMax[] = (max == Double.POSITIVE_INFINITY) ? \"+inf\".getBytes() : toByteArray(max);\n\n    sendCommand(ZREVRANGEBYSCORE, key, byteArrayMax, byteArrayMin, LIMIT.raw, toByteArray(offset),\n      toByteArray(count));\n  }\n\n  public void zrevrangeByScore(final byte[] key, final String max, final String min,\n      final int offset, int count) {\n\n    sendCommand(ZREVRANGEBYSCORE, key, max.getBytes(), min.getBytes(), LIMIT.raw,\n      toByteArray(offset), toByteArray(count));\n  }\n\n  public void zrangeByScoreWithScores(final byte[] key, final double min, final double max) {\n\n    byte byteArrayMin[] = (min == Double.NEGATIVE_INFINITY) ? \"-inf\".getBytes() : toByteArray(min);\n    byte byteArrayMax[] = (max == Double.POSITIVE_INFINITY) ? \"+inf\".getBytes() : toByteArray(max);\n\n    sendCommand(ZRANGEBYSCORE, key, byteArrayMin, byteArrayMax, WITHSCORES.raw);\n  }\n\n  public void zrangeByScoreWithScores(final byte[] key, final String min, final String max) {\n\n    sendCommand(ZRANGEBYSCORE, key, min.getBytes(), max.getBytes(), WITHSCORES.raw);\n  }\n\n  public void zrevrangeByScoreWithScores(final byte[] key, final double max, final double min) {\n\n    byte byteArrayMin[] = (min == Double.NEGATIVE_INFINITY) ? \"-inf\".getBytes() : toByteArray(min);\n    byte byteArrayMax[] = (max == Double.POSITIVE_INFINITY) ? \"+inf\".getBytes() : toByteArray(max);\n\n    sendCommand(ZREVRANGEBYSCORE, key, byteArrayMax, byteArrayMin, WITHSCORES.raw);\n  }\n\n  public void zrevrangeByScoreWithScores(final byte[] key, final String max, final String min) {\n    sendCommand(ZREVRANGEBYSCORE, key, max.getBytes(), min.getBytes(), WITHSCORES.raw);\n  }\n\n  public void zrangeByScoreWithScores(final byte[] key, final double min, final double max,\n      final int offset, final int count) {\n\n    byte byteArrayMin[] = (min == Double.NEGATIVE_INFINITY) ? \"-inf\".getBytes() : toByteArray(min);\n    byte byteArrayMax[] = (max == Double.POSITIVE_INFINITY) ? \"+inf\".getBytes() : toByteArray(max);\n\n    sendCommand(ZRANGEBYSCORE, key, byteArrayMin, byteArrayMax, LIMIT.raw, toByteArray(offset),\n      toByteArray(count), WITHSCORES.raw);\n  }\n\n  public void zrangeByScoreWithScores(final byte[] key, final String min, final String max,\n      final int offset, final int count) {\n    sendCommand(ZRANGEBYSCORE, key, min.getBytes(), max.getBytes(), LIMIT.raw, toByteArray(offset),\n      toByteArray(count), WITHSCORES.raw);\n  }\n\n  public void zrevrangeByScoreWithScores(final byte[] key, final double max, final double min,\n      final int offset, final int count) {\n\n    byte byteArrayMin[] = (min == Double.NEGATIVE_INFINITY) ? \"-inf\".getBytes() : toByteArray(min);\n    byte byteArrayMax[] = (max == Double.POSITIVE_INFINITY) ? \"+inf\".getBytes() : toByteArray(max);\n\n    sendCommand(ZREVRANGEBYSCORE, key, byteArrayMax, byteArrayMin, LIMIT.raw, toByteArray(offset),\n      toByteArray(count), WITHSCORES.raw);\n  }\n\n  public void zrevrangeByScoreWithScores(final byte[] key, final String max, final String min,\n      final int offset, final int count) {\n\n    sendCommand(ZREVRANGEBYSCORE, key, max.getBytes(), min.getBytes(), LIMIT.raw,\n      toByteArray(offset), toByteArray(count), WITHSCORES.raw);\n  }\n\n  public void zrangeByScore(final byte[] key, final byte[] min, final byte[] max, final int offset,\n      int count) {\n    sendCommand(ZRANGEBYSCORE, key, min, max, LIMIT.raw, toByteArray(offset), toByteArray(count));\n  }\n\n  public void zrevrangeByScore(final byte[] key, final byte[] max, final byte[] min,\n      final int offset, int count) {\n    sendCommand(ZREVRANGEBYSCORE, key, max, min, LIMIT.raw, toByteArray(offset), toByteArray(count));\n  }\n\n  public void zrangeByScoreWithScores(final byte[] key, final byte[] min, final byte[] max) {\n    sendCommand(ZRANGEBYSCORE, key, min, max, WITHSCORES.raw);\n  }\n\n  public void zrevrangeByScoreWithScores(final byte[] key, final byte[] max, final byte[] min) {\n    sendCommand(ZREVRANGEBYSCORE, key, max, min, WITHSCORES.raw);\n  }\n\n  public void zrangeByScoreWithScores(final byte[] key, final byte[] min, final byte[] max,\n      final int offset, final int count) {\n    sendCommand(ZRANGEBYSCORE, key, min, max, LIMIT.raw, toByteArray(offset), toByteArray(count),\n      WITHSCORES.raw);\n  }\n\n  public void zrevrangeByScoreWithScores(final byte[] key, final byte[] max, final byte[] min,\n      final int offset, final int count) {\n    sendCommand(ZREVRANGEBYSCORE, key, max, min, LIMIT.raw, toByteArray(offset),\n      toByteArray(count), WITHSCORES.raw);\n  }\n\n  public void zremrangeByRank(final byte[] key, final long start, final long end) {\n    sendCommand(ZREMRANGEBYRANK, key, toByteArray(start), toByteArray(end));\n  }\n\n  public void zremrangeByScore(final byte[] key, final byte[] start, final byte[] end) {\n    sendCommand(ZREMRANGEBYSCORE, key, start, end);\n  }\n\n  public void zremrangeByScore(final byte[] key, final String start, final String end) {\n    sendCommand(ZREMRANGEBYSCORE, key, start.getBytes(), end.getBytes());\n  }\n\n  public void zunionstore(final byte[] dstkey, final byte[]... sets) {\n    final byte[][] params = new byte[sets.length + 2][];\n    params[0] = dstkey;\n    params[1] = toByteArray(sets.length);\n    System.arraycopy(sets, 0, params, 2, sets.length);\n    sendCommand(ZUNIONSTORE, params);\n  }\n\n  public void zunionstore(final byte[] dstkey, final ZParams params, final byte[]... sets) {\n    final List<byte[]> args = new ArrayList<byte[]>();\n    args.add(dstkey);\n    args.add(Protocol.toByteArray(sets.length));\n    for (final byte[] set : sets) {\n      args.add(set);\n    }\n    args.addAll(params.getParams());\n    sendCommand(ZUNIONSTORE, args.toArray(new byte[args.size()][]));\n  }\n\n  public void zinterstore(final byte[] dstkey, final byte[]... sets) {\n    final byte[][] params = new byte[sets.length + 2][];\n    params[0] = dstkey;\n    params[1] = Protocol.toByteArray(sets.length);\n    System.arraycopy(sets, 0, params, 2, sets.length);\n    sendCommand(ZINTERSTORE, params);\n  }\n\n  public void zinterstore(final byte[] dstkey, final ZParams params, final byte[]... sets) {\n    final List<byte[]> args = new ArrayList<byte[]>();\n    args.add(dstkey);\n    args.add(Protocol.toByteArray(sets.length));\n    for (final byte[] set : sets) {\n      args.add(set);\n    }\n    args.addAll(params.getParams());\n    sendCommand(ZINTERSTORE, args.toArray(new byte[args.size()][]));\n  }\n\n  public void zlexcount(final byte[] key, final byte[] min, final byte[] max) {\n    sendCommand(ZLEXCOUNT, key, min, max);\n  }\n\n  public void zrangeByLex(final byte[] key, final byte[] min, final byte[] max) {\n    sendCommand(ZRANGEBYLEX, key, min, max);\n  }\n\n  public void zrangeByLex(final byte[] key, final byte[] min, final byte[] max, final int offset,\n      final int count) {\n    sendCommand(ZRANGEBYLEX, key, min, max, LIMIT.raw, toByteArray(offset), toByteArray(count));\n  }\n\n  public void zrevrangeByLex(final byte[] key, final byte[] max, final byte[] min) {\n    sendCommand(ZREVRANGEBYLEX, key, max, min);\n  }\n\n  public void zrevrangeByLex(final byte[] key, final byte[] max, final byte[] min,\n      final int offset, final int count) {\n    sendCommand(ZREVRANGEBYLEX, key, max, min, LIMIT.raw, toByteArray(offset), toByteArray(count));\n  }\n\n  public void zremrangeByLex(byte[] key, byte[] min, byte[] max) {\n    sendCommand(ZREMRANGEBYLEX, key, min, max);\n  }\n\n  public void save() {\n    sendCommand(SAVE);\n  }\n\n  public void bgsave() {\n    sendCommand(BGSAVE);\n  }\n\n  public void bgrewriteaof() {\n    sendCommand(BGREWRITEAOF);\n  }\n\n  public void lastsave() {\n    sendCommand(LASTSAVE);\n  }\n\n  public void shutdown() {\n    sendCommand(SHUTDOWN);\n  }\n\n  public void info() {\n    sendCommand(INFO);\n  }\n\n  public void info(final String section) {\n    sendCommand(INFO, section);\n  }\n\n  public void monitor() {\n    sendCommand(MONITOR);\n  }\n\n  public void slaveof(final String host, final int port) {\n    sendCommand(SLAVEOF, host, String.valueOf(port));\n  }\n\n  public void slaveofNoOne() {\n    sendCommand(SLAVEOF, NO.raw, ONE.raw);\n  }\n\n  public void configGet(final byte[] pattern) {\n    sendCommand(CONFIG, Keyword.GET.raw, pattern);\n  }\n\n  public void configSet(final byte[] parameter, final byte[] value) {\n    sendCommand(CONFIG, Keyword.SET.raw, parameter, value);\n  }\n\n  public void strlen(final byte[] key) {\n    sendCommand(STRLEN, key);\n  }\n\n  public void sync() {\n    sendCommand(SYNC);\n  }\n\n  public void lpushx(final byte[] key, final byte[]... string) {\n    sendCommand(LPUSHX, joinParameters(key, string));\n  }\n\n  public void persist(final byte[] key) {\n    sendCommand(PERSIST, key);\n  }\n\n  public void rpushx(final byte[] key, final byte[]... string) {\n    sendCommand(RPUSHX, joinParameters(key, string));\n  }\n\n  public void echo(final byte[] string) {\n    sendCommand(ECHO, string);\n  }\n\n  public void linsert(final byte[] key, final LIST_POSITION where, final byte[] pivot,\n      final byte[] value) {\n    sendCommand(LINSERT, key, where.raw, pivot, value);\n  }\n\n  public void debug(final DebugParams params) {\n    sendCommand(DEBUG, params.getCommand());\n  }\n\n  public void brpoplpush(final byte[] source, final byte[] destination, final int timeout) {\n    sendCommand(BRPOPLPUSH, source, destination, toByteArray(timeout));\n  }\n\n  public void configResetStat() {\n    sendCommand(CONFIG, Keyword.RESETSTAT.name());\n  }\n\n  public void setbit(byte[] key, long offset, byte[] value) {\n    sendCommand(SETBIT, key, toByteArray(offset), value);\n  }\n\n  public void setbit(byte[] key, long offset, boolean value) {\n    sendCommand(SETBIT, key, toByteArray(offset), toByteArray(value));\n  }\n\n  public void getbit(byte[] key, long offset) {\n    sendCommand(GETBIT, key, toByteArray(offset));\n  }\n\n  public void bitpos(final byte[] key, final boolean value, final BitPosParams params) {\n    final List<byte[]> args = new ArrayList<byte[]>();\n    args.add(key);\n    args.add(toByteArray(value));\n    args.addAll(params.getParams());\n    sendCommand(BITPOS, args.toArray(new byte[args.size()][]));\n  }\n\n  public void setrange(byte[] key, long offset, byte[] value) {\n    sendCommand(SETRANGE, key, toByteArray(offset), value);\n  }\n\n  public void getrange(byte[] key, long startOffset, long endOffset) {\n    sendCommand(GETRANGE, key, toByteArray(startOffset), toByteArray(endOffset));\n  }\n\n  public int getDB() {\n    return db;\n  }\n\n  @Override\n  public void disconnect() {\n    db = 0;\n    super.disconnect();\n  }\n\n  @Override\n  public void close() {\n    db = 0;\n    super.close();\n  }\n\n  public void resetState() {\n    if (isInWatch()) unwatch();\n  }\n\n  private void sendEvalCommand(Command command, byte[] script, byte[] keyCount, byte[][] params) {\n\n    final byte[][] allArgs = new byte[params.length + 2][];\n\n    allArgs[0] = script;\n    allArgs[1] = keyCount;\n\n    for (int i = 0; i < params.length; i++)\n      allArgs[i + 2] = params[i];\n\n    sendCommand(command, allArgs);\n  }\n\n  public void eval(byte[] script, byte[] keyCount, byte[][] params) {\n    sendEvalCommand(EVAL, script, keyCount, params);\n  }\n\n  public void eval(byte[] script, int keyCount, byte[]... params) {\n    eval(script, toByteArray(keyCount), params);\n  }\n\n  public void evalsha(byte[] sha1, byte[] keyCount, byte[]... params) {\n    sendEvalCommand(EVALSHA, sha1, keyCount, params);\n  }\n\n  public void evalsha(byte[] sha1, int keyCount, byte[]... params) {\n    sendEvalCommand(EVALSHA, sha1, toByteArray(keyCount), params);\n  }\n\n  public void scriptFlush() {\n    sendCommand(SCRIPT, Keyword.FLUSH.raw);\n  }\n\n  public void scriptExists(byte[]... sha1) {\n    byte[][] args = new byte[sha1.length + 1][];\n    args[0] = Keyword.EXISTS.raw;\n    for (int i = 0; i < sha1.length; i++)\n      args[i + 1] = sha1[i];\n\n    sendCommand(SCRIPT, args);\n  }\n\n  public void scriptLoad(byte[] script) {\n    sendCommand(SCRIPT, Keyword.LOAD.raw, script);\n  }\n\n  public void scriptKill() {\n    sendCommand(SCRIPT, Keyword.KILL.raw);\n  }\n\n  public void slowlogGet() {\n    sendCommand(SLOWLOG, Keyword.GET.raw);\n  }\n\n  public void slowlogGet(long entries) {\n    sendCommand(SLOWLOG, Keyword.GET.raw, toByteArray(entries));\n  }\n\n  public void slowlogReset() {\n    sendCommand(SLOWLOG, RESET.raw);\n  }\n\n  public void slowlogLen() {\n    sendCommand(SLOWLOG, LEN.raw);\n  }\n\n  public void objectRefcount(byte[] key) {\n    sendCommand(OBJECT, REFCOUNT.raw, key);\n  }\n\n  public void objectIdletime(byte[] key) {\n    sendCommand(OBJECT, IDLETIME.raw, key);\n  }\n\n  public void objectEncoding(byte[] key) {\n    sendCommand(OBJECT, ENCODING.raw, key);\n  }\n\n  public void bitcount(byte[] key) {\n    sendCommand(BITCOUNT, key);\n  }\n\n  public void bitcount(byte[] key, long start, long end) {\n    sendCommand(BITCOUNT, key, toByteArray(start), toByteArray(end));\n  }\n\n  public void bitop(BitOP op, byte[] destKey, byte[]... srcKeys) {\n    Keyword kw = Keyword.AND;\n    int len = srcKeys.length;\n    switch (op) {\n    case AND:\n      kw = Keyword.AND;\n      break;\n    case OR:\n      kw = Keyword.OR;\n      break;\n    case XOR:\n      kw = Keyword.XOR;\n      break;\n    case NOT:\n      kw = Keyword.NOT;\n      len = Math.min(1, len);\n      break;\n    }\n\n    byte[][] bargs = new byte[len + 2][];\n    bargs[0] = kw.raw;\n    bargs[1] = destKey;\n    for (int i = 0; i < len; ++i) {\n      bargs[i + 2] = srcKeys[i];\n    }\n\n    sendCommand(BITOP, bargs);\n  }\n\n  public void sentinel(final byte[]... args) {\n    sendCommand(SENTINEL, args);\n  }\n\n  public void dump(final byte[] key) {\n    sendCommand(DUMP, key);\n  }\n\n  public void restore(final byte[] key, final int ttl, final byte[] serializedValue) {\n    sendCommand(RESTORE, key, toByteArray(ttl), serializedValue);\n  }\n\n  public void pexpire(final byte[] key, final long milliseconds) {\n    sendCommand(PEXPIRE, key, toByteArray(milliseconds));\n  }\n\n  public void pexpireAt(final byte[] key, final long millisecondsTimestamp) {\n    sendCommand(PEXPIREAT, key, toByteArray(millisecondsTimestamp));\n  }\n\n  public void pttl(final byte[] key) {\n    sendCommand(PTTL, key);\n  }\n\n  public void psetex(final byte[] key, final long milliseconds, final byte[] value) {\n    sendCommand(PSETEX, key, toByteArray(milliseconds), value);\n  }\n\n  public void srandmember(final byte[] key, final int count) {\n    sendCommand(SRANDMEMBER, key, toByteArray(count));\n  }\n\n  public void clientKill(final byte[] client) {\n    sendCommand(CLIENT, Keyword.KILL.raw, client);\n  }\n\n  public void clientGetname() {\n    sendCommand(CLIENT, Keyword.GETNAME.raw);\n  }\n\n  public void clientList() {\n    sendCommand(CLIENT, Keyword.LIST.raw);\n  }\n\n  public void clientSetname(final byte[] name) {\n    sendCommand(CLIENT, Keyword.SETNAME.raw, name);\n  }\n\n  public void time() {\n    sendCommand(TIME);\n  }\n\n  public void migrate(final byte[] host, final int port, final byte[] key, final int destinationDb,\n      final int timeout) {\n    sendCommand(MIGRATE, host, toByteArray(port), key, toByteArray(destinationDb),\n      toByteArray(timeout));\n  }\n  \n  public void migrate(final byte[] host, final int port, final int destinationDb,\n          final int timeout, final byte[]... keys) {\n      final List<byte[]> args = new ArrayList<byte[]>();\n      args.add(host);\n      args.add(toByteArray(port));\n      args.add(SafeEncoder.encode(\"\"));\n      args.add(toByteArray(destinationDb));\n      args.add(toByteArray(timeout));\n      args.add(SafeEncoder.encode(\"keys\"));\n      for (final byte[] key : keys) {\n          args.add(key);\n      }\n      sendCommand(MIGRATE, args.toArray(new byte[args.size()][]));\n  }\n\n  public void hincrByFloat(final byte[] key, final byte[] field, double increment) {\n    sendCommand(HINCRBYFLOAT, key, field, toByteArray(increment));\n  }\n\n  public void scan(final byte[] cursor, final ScanParams params) {\n    final List<byte[]> args = new ArrayList<byte[]>();\n    args.add(cursor);\n    args.addAll(params.getParams());\n    sendCommand(SCAN, args.toArray(new byte[args.size()][]));\n  }\n\n  public void hscan(final byte[] key, final byte[] cursor, final ScanParams params) {\n    final List<byte[]> args = new ArrayList<byte[]>();\n    args.add(key);\n    args.add(cursor);\n    args.addAll(params.getParams());\n    sendCommand(HSCAN, args.toArray(new byte[args.size()][]));\n  }\n\n  public void sscan(final byte[] key, final byte[] cursor, final ScanParams params) {\n    final List<byte[]> args = new ArrayList<byte[]>();\n    args.add(key);\n    args.add(cursor);\n    args.addAll(params.getParams());\n    sendCommand(SSCAN, args.toArray(new byte[args.size()][]));\n  }\n\n  public void zscan(final byte[] key, final byte[] cursor, final ScanParams params) {\n    final List<byte[]> args = new ArrayList<byte[]>();\n    args.add(key);\n    args.add(cursor);\n    args.addAll(params.getParams());\n    sendCommand(ZSCAN, args.toArray(new byte[args.size()][]));\n  }\n\n  public void waitReplicas(int replicas, long timeout) {\n    sendCommand(WAIT, toByteArray(replicas), toByteArray(timeout));\n  }\n\n  public void cluster(final byte[]... args) {\n    sendCommand(CLUSTER, args);\n  }\n\n  public void asking() {\n    sendCommand(Command.ASKING);\n  }\n\n  public void pfadd(final byte[] key, final byte[]... elements) {\n    sendCommand(PFADD, joinParameters(key, elements));\n  }\n\n  public void pfcount(final byte[] key) {\n    sendCommand(PFCOUNT, key);\n  }\n\n  public void pfcount(final byte[]... keys) {\n    sendCommand(PFCOUNT, keys);\n  }\n\n  public void pfmerge(final byte[] destkey, final byte[]... sourcekeys) {\n    sendCommand(PFMERGE, joinParameters(destkey, sourcekeys));\n  }\n\n  public void readonly() {\n    sendCommand(READONLY);\n  }\n\n  public void geoadd(byte[] key, double longitude, double latitude, byte[] member) {\n    sendCommand(GEOADD, key, toByteArray(longitude), toByteArray(latitude), member);\n  }\n\n  public void geoadd(byte[] key, Map<byte[], GeoCoordinate> memberCoordinateMap) {\n    List<byte[]> args = new ArrayList<byte[]>(memberCoordinateMap.size() * 3 + 1);\n    args.add(key);\n    args.addAll(convertGeoCoordinateMapToByteArrays(memberCoordinateMap));\n\n    byte[][] argsArray = new byte[args.size()][];\n    args.toArray(argsArray);\n\n    sendCommand(GEOADD, argsArray);\n  }\n\n  public void geodist(byte[] key, byte[] member1, byte[] member2) {\n    sendCommand(GEODIST, key, member1, member2);\n  }\n\n  public void geodist(byte[] key, byte[] member1, byte[] member2, GeoUnit unit) {\n    sendCommand(GEODIST, key, member1, member2, unit.raw);\n  }\n\n  public void geohash(byte[] key, byte[]... members) {\n    sendCommand(GEOHASH, joinParameters(key, members));\n  }\n\n  public void geopos(byte[] key, byte[][] members) {\n    sendCommand(GEOPOS, joinParameters(key, members));\n  }\n\n  public void georadius(byte[] key, double longitude, double latitude, double radius, GeoUnit unit) {\n    sendCommand(GEORADIUS, key, toByteArray(longitude), toByteArray(latitude), toByteArray(radius),\n      unit.raw);\n  }\n\n  public void georadius(byte[] key, double longitude, double latitude, double radius, GeoUnit unit,\n      GeoRadiusParam param) {\n    sendCommand(GEORADIUS, param.getByteParams(key, toByteArray(longitude), toByteArray(latitude),\n      toByteArray(radius), unit.raw));\n  }\n\n  public void georadiusByMember(byte[] key, byte[] member, double radius, GeoUnit unit) {\n    sendCommand(GEORADIUSBYMEMBER, key, member, toByteArray(radius), unit.raw);\n  }\n\n  public void georadiusByMember(byte[] key, byte[] member, double radius, GeoUnit unit,\n      GeoRadiusParam param) {\n    sendCommand(GEORADIUSBYMEMBER, param.getByteParams(key, member, toByteArray(radius), unit.raw));\n  }\n\n  private ArrayList<byte[]> convertScoreMembersToByteArrays(final Map<byte[], Double> scoreMembers) {\n    ArrayList<byte[]> args = new ArrayList<byte[]>(scoreMembers.size() * 2);\n\n    for (Map.Entry<byte[], Double> entry : scoreMembers.entrySet()) {\n      args.add(toByteArray(entry.getValue()));\n      args.add(entry.getKey());\n    }\n\n    return args;\n  }\n\n  private List<byte[]> convertGeoCoordinateMapToByteArrays(\n      Map<byte[], GeoCoordinate> memberCoordinateMap) {\n    List<byte[]> args = new ArrayList<byte[]>(memberCoordinateMap.size() * 3);\n\n    for (Entry<byte[], GeoCoordinate> entry : memberCoordinateMap.entrySet()) {\n      GeoCoordinate coordinate = entry.getValue();\n      args.add(toByteArray(coordinate.getLongitude()));\n      args.add(toByteArray(coordinate.getLatitude()));\n      args.add(entry.getKey());\n    }\n\n    return args;\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/BinaryJedis.java",
    "content": "package redis.clients.jedis;\n\nimport static redis.clients.jedis.Protocol.toByteArray;\n\nimport java.io.Closeable;\nimport java.net.URI;\nimport java.util.AbstractMap;\nimport java.util.AbstractSet;\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.Iterator;\nimport java.util.LinkedHashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\nimport redis.clients.jedis.BinaryClient.LIST_POSITION;\nimport redis.clients.jedis.commands.*;\nimport redis.clients.jedis.exceptions.InvalidURIException;\nimport redis.clients.jedis.exceptions.JedisDataException;\nimport redis.clients.jedis.exceptions.JedisException;\nimport redis.clients.jedis.params.geo.GeoRadiusParam;\nimport redis.clients.jedis.params.set.SetParams;\nimport redis.clients.jedis.params.sortedset.ZAddParams;\nimport redis.clients.jedis.params.sortedset.ZIncrByParams;\nimport redis.clients.util.JedisByteHashMap;\nimport redis.clients.util.JedisURIHelper;\nimport redis.clients.util.SafeEncoder;\n\npublic class BinaryJedis implements BasicCommands, BinaryJedisCommands, MultiKeyBinaryCommands,\n    AdvancedBinaryJedisCommands, BinaryScriptingCommands, Closeable {\n  protected Client client = null;\n  protected Transaction transaction = null;\n  protected Pipeline pipeline = null;\n\n  public BinaryJedis() {\n    client = new Client();\n  }\n\n  public BinaryJedis(final String host) {\n    URI uri = URI.create(host);\n    if (uri.getScheme() != null && uri.getScheme().equals(\"redis\")) {\n      initializeClientFromURI(uri);\n    } else {\n      client = new Client(host);\n    }\n  }\n\n  public BinaryJedis(final String host, final int port) {\n    client = new Client(host, port);\n  }\n\n  public BinaryJedis(final String host, final int port, final int timeout) {\n    client = new Client(host, port);\n    client.setConnectionTimeout(timeout);\n    client.setSoTimeout(timeout);\n  }\n\n  public BinaryJedis(final String host, final int port, final int connectionTimeout,\n      final int soTimeout) {\n    client = new Client(host, port);\n    client.setConnectionTimeout(connectionTimeout);\n    client.setSoTimeout(soTimeout);\n  }\n\n  public BinaryJedis(final JedisShardInfo shardInfo) {\n    client = new Client(shardInfo.getHost(), shardInfo.getPort());\n    client.setConnectionTimeout(shardInfo.getConnectionTimeout());\n    client.setSoTimeout(shardInfo.getSoTimeout());\n    client.setPassword(shardInfo.getPassword());\n    client.setDb(shardInfo.getDb());\n  }\n\n  public BinaryJedis(URI uri) {\n    initializeClientFromURI(uri);\n  }\n\n  public BinaryJedis(final URI uri, final int timeout) {\n    initializeClientFromURI(uri);\n    client.setConnectionTimeout(timeout);\n    client.setSoTimeout(timeout);\n  }\n\n  public BinaryJedis(final URI uri, final int connectionTimeout, final int soTimeout) {\n    initializeClientFromURI(uri);\n    client.setConnectionTimeout(connectionTimeout);\n    client.setSoTimeout(soTimeout);\n  }\n\n  private void initializeClientFromURI(URI uri) {\n    if (!JedisURIHelper.isValid(uri)) {\n      throw new InvalidURIException(String.format(\n        \"Cannot open Redis connection due invalid URI. %s\", uri.toString()));\n    }\n\n    client = new Client(uri.getHost(), uri.getPort());\n\n    String password = JedisURIHelper.getPassword(uri);\n    if (password != null) {\n      client.auth(password);\n      client.getStatusCodeReply();\n    }\n\n    int dbIndex = JedisURIHelper.getDBIndex(uri);\n    if (dbIndex > 0) {\n      client.select(dbIndex);\n      client.getStatusCodeReply();\n      client.setDb(dbIndex);\n    }\n  }\n\n  @Override\n  public String ping() {\n    checkIsInMultiOrPipeline();\n    client.ping();\n    return client.getStatusCodeReply();\n  }\n\n  /**\n   * Set the string value as value of the key. The string can't be longer than 1073741824 bytes (1\n   * GB).\n   * <p>\n   * Time complexity: O(1)\n   * @param key\n   * @param value\n   * @return Status code reply\n   */\n  @Override\n  public String set(final byte[] key, final byte[] value) {\n    checkIsInMultiOrPipeline();\n    client.set(key, value);\n    return client.getStatusCodeReply();\n  }\n\n  /**\n   * Set the string value as value of the key. The string can't be longer than 1073741824 bytes (1\n   * GB).\n   * @param key\n   * @param value\n   * @param params\n   * @return Status code reply\n   */\n  public String set(final byte[] key, final byte[] value, final SetParams params) {\n    checkIsInMultiOrPipeline();\n    client.set(key, value, params);\n    return client.getStatusCodeReply();\n  }\n\n  /**\n   * Get the value of the specified key. If the key does not exist the special value 'nil' is\n   * returned. If the value stored at key is not a string an error is returned because GET can only\n   * handle string values.\n   * <p>\n   * Time complexity: O(1)\n   * @param key\n   * @return Bulk reply\n   */\n  @Override\n  public byte[] get(final byte[] key) {\n    checkIsInMultiOrPipeline();\n    client.get(key);\n    return client.getBinaryBulkReply();\n  }\n\n  /**\n   * Ask the server to silently close the connection.\n   */\n  @Override\n  public String quit() {\n    checkIsInMultiOrPipeline();\n    client.quit();\n    String quitReturn = client.getStatusCodeReply();\n    client.disconnect();\n    return quitReturn;\n  }\n\n  /**\n   * Test if the specified keys exist. The command returns the number of keys existed Time\n   * complexity: O(N)\n   * @param keys\n   * @return Integer reply, specifically: an integer greater than 0 if one or more keys existed 0 if\n   *         none of the specified keys existed\n   */\n  public Long exists(final byte[]... keys) {\n    checkIsInMultiOrPipeline();\n    client.exists(keys);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Test if the specified key exists. The command returns \"1\" if the key exists, otherwise \"0\" is\n   * returned. Note that even keys set with an empty string as value will return \"1\". Time\n   * complexity: O(1)\n   * @param key\n   * @return Boolean reply, true if the key exists, otherwise false\n   */\n  @Override\n  public Boolean exists(final byte[] key) {\n    checkIsInMultiOrPipeline();\n    client.exists(key);\n    return client.getIntegerReply() == 1;\n  }\n\n  /**\n   * Remove the specified keys. If a given key does not exist no operation is performed for this\n   * key. The command returns the number of keys removed. Time complexity: O(1)\n   * @param keys\n   * @return Integer reply, specifically: an integer greater than 0 if one or more keys were removed\n   *         0 if none of the specified key existed\n   */\n  @Override\n  public Long del(final byte[]... keys) {\n    checkIsInMultiOrPipeline();\n    client.del(keys);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public Long del(final byte[] key) {\n    checkIsInMultiOrPipeline();\n    client.del(key);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Return the type of the value stored at key in form of a string. The type can be one of \"none\",\n   * \"string\", \"list\", \"set\". \"none\" is returned if the key does not exist. Time complexity: O(1)\n   * @param key\n   * @return Status code reply, specifically: \"none\" if the key does not exist \"string\" if the key\n   *         contains a String value \"list\" if the key contains a List value \"set\" if the key\n   *         contains a Set value \"zset\" if the key contains a Sorted Set value \"hash\" if the key\n   *         contains a Hash value\n   */\n  @Override\n  public String type(final byte[] key) {\n    checkIsInMultiOrPipeline();\n    client.type(key);\n    return client.getStatusCodeReply();\n  }\n\n  /**\n   * Delete all the keys of the currently selected DB. This command never fails.\n   * @return Status code reply\n   */\n  @Override\n  public String flushDB() {\n    checkIsInMultiOrPipeline();\n    client.flushDB();\n    return client.getStatusCodeReply();\n  }\n\n  /**\n   * Returns all the keys matching the glob-style pattern as space separated strings. For example if\n   * you have in the database the keys \"foo\" and \"foobar\" the command \"KEYS foo*\" will return\n   * \"foo foobar\".\n   * <p>\n   * Note that while the time complexity for this operation is O(n) the constant times are pretty\n   * low. For example Redis running on an entry level laptop can scan a 1 million keys database in\n   * 40 milliseconds. <b>Still it's better to consider this one of the slow commands that may ruin\n   * the DB performance if not used with care.</b>\n   * <p>\n   * In other words this command is intended only for debugging and special operations like creating\n   * a script to change the DB schema. Don't use it in your normal code. Use Redis Sets in order to\n   * group together a subset of objects.\n   * <p>\n   * Glob style patterns examples:\n   * <ul>\n   * <li>h?llo will match hello hallo hhllo\n   * <li>h*llo will match hllo heeeello\n   * <li>h[ae]llo will match hello and hallo, but not hillo\n   * </ul>\n   * <p>\n   * Use \\ to escape special chars if you want to match them verbatim.\n   * <p>\n   * Time complexity: O(n) (with n being the number of keys in the DB, and assuming keys and pattern\n   * of limited length)\n   * @param pattern\n   * @return Multi bulk reply\n   */\n  @Override\n  public Set<byte[]> keys(final byte[] pattern) {\n    checkIsInMultiOrPipeline();\n    client.keys(pattern);\n    return SetFromList.of(client.getBinaryMultiBulkReply());\n  }\n\n  /**\n   * Return a randomly selected key from the currently selected DB.\n   * <p>\n   * Time complexity: O(1)\n   * @return Singe line reply, specifically the randomly selected key or an empty string is the\n   *         database is empty\n   */\n  @Override\n  public byte[] randomBinaryKey() {\n    checkIsInMultiOrPipeline();\n    client.randomKey();\n    return client.getBinaryBulkReply();\n  }\n\n  /**\n   * Atomically renames the key oldkey to newkey. If the source and destination name are the same an\n   * error is returned. If newkey already exists it is overwritten.\n   * <p>\n   * Time complexity: O(1)\n   * @param oldkey\n   * @param newkey\n   * @return Status code repy\n   */\n  @Override\n  public String rename(final byte[] oldkey, final byte[] newkey) {\n    checkIsInMultiOrPipeline();\n    client.rename(oldkey, newkey);\n    return client.getStatusCodeReply();\n  }\n\n  /**\n   * Rename oldkey into newkey but fails if the destination key newkey already exists.\n   * <p>\n   * Time complexity: O(1)\n   * @param oldkey\n   * @param newkey\n   * @return Integer reply, specifically: 1 if the key was renamed 0 if the target key already exist\n   */\n  @Override\n  public Long renamenx(final byte[] oldkey, final byte[] newkey) {\n    checkIsInMultiOrPipeline();\n    client.renamenx(oldkey, newkey);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Return the number of keys in the currently selected database.\n   * @return Integer reply\n   */\n  @Override\n  public Long dbSize() {\n    checkIsInMultiOrPipeline();\n    client.dbSize();\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Set a timeout on the specified key. After the timeout the key will be automatically deleted by\n   * the server. A key with an associated timeout is said to be volatile in Redis terminology.\n   * <p>\n   * Voltile keys are stored on disk like the other keys, the timeout is persistent too like all the\n   * other aspects of the dataset. Saving a dataset containing expires and stopping the server does\n   * not stop the flow of time as Redis stores on disk the time when the key will no longer be\n   * available as Unix time, and not the remaining seconds.\n   * <p>\n   * Since Redis 2.1.3 you can update the value of the timeout of a key already having an expire\n   * set. It is also possible to undo the expire at all turning the key into a normal key using the\n   * {@link #persist(byte[]) PERSIST} command.\n   * <p>\n   * Time complexity: O(1)\n   * @see <a href=\"http://redis.io/commands/expire\">Expire Command</a>\n   * @param key\n   * @param seconds\n   * @return Integer reply, specifically: 1: the timeout was set. 0: the timeout was not set since\n   *         the key already has an associated timeout (this may happen only in Redis versions &lt;\n   *         2.1.3, Redis &gt;= 2.1.3 will happily update the timeout), or the key does not exist.\n   */\n  @Override\n  public Long expire(final byte[] key, final int seconds) {\n    checkIsInMultiOrPipeline();\n    client.expire(key, seconds);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * EXPIREAT works exctly like {@link #expire(byte[], int) EXPIRE} but instead to get the number of\n   * seconds representing the Time To Live of the key as a second argument (that is a relative way\n   * of specifing the TTL), it takes an absolute one in the form of a UNIX timestamp (Number of\n   * seconds elapsed since 1 Gen 1970).\n   * <p>\n   * EXPIREAT was introduced in order to implement the Append Only File persistence mode so that\n   * EXPIRE commands are automatically translated into EXPIREAT commands for the append only file.\n   * Of course EXPIREAT can also used by programmers that need a way to simply specify that a given\n   * key should expire at a given time in the future.\n   * <p>\n   * Since Redis 2.1.3 you can update the value of the timeout of a key already having an expire\n   * set. It is also possible to undo the expire at all turning the key into a normal key using the\n   * {@link #persist(byte[]) PERSIST} command.\n   * <p>\n   * Time complexity: O(1)\n   * @see <a href=\"http://redis.io/commands/expire\">Expire Command</a>\n   * @param key\n   * @param unixTime\n   * @return Integer reply, specifically: 1: the timeout was set. 0: the timeout was not set since\n   *         the key already has an associated timeout (this may happen only in Redis versions &lt;\n   *         2.1.3, Redis &gt;= 2.1.3 will happily update the timeout), or the key does not exist.\n   */\n  @Override\n  public Long expireAt(final byte[] key, final long unixTime) {\n    checkIsInMultiOrPipeline();\n    client.expireAt(key, unixTime);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * The TTL command returns the remaining time to live in seconds of a key that has an\n   * {@link #expire(byte[], int) EXPIRE} set. This introspection capability allows a Redis client to\n   * check how many seconds a given key will continue to be part of the dataset.\n   * @param key\n   * @return Integer reply, returns the remaining time to live in seconds of a key that has an\n   *         EXPIRE. If the Key does not exists or does not have an associated expire, -1 is\n   *         returned.\n   */\n  @Override\n  public Long ttl(final byte[] key) {\n    checkIsInMultiOrPipeline();\n    client.ttl(key);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Select the DB with having the specified zero-based numeric index. For default every new client\n   * connection is automatically selected to DB 0.\n   * @param index\n   * @return Status code reply\n   */\n  @Override\n  public String select(final int index) {\n    checkIsInMultiOrPipeline();\n    client.select(index);\n    String statusCodeReply = client.getStatusCodeReply();\n    client.setDb(index);\n\n    return statusCodeReply;\n  }\n\n  /**\n   * Move the specified key from the currently selected DB to the specified destination DB. Note\n   * that this command returns 1 only if the key was successfully moved, and 0 if the target key was\n   * already there or if the source key was not found at all, so it is possible to use MOVE as a\n   * locking primitive.\n   * @param key\n   * @param dbIndex\n   * @return Integer reply, specifically: 1 if the key was moved 0 if the key was not moved because\n   *         already present on the target DB or was not found in the current DB.\n   */\n  @Override\n  public Long move(final byte[] key, final int dbIndex) {\n    checkIsInMultiOrPipeline();\n    client.move(key, dbIndex);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Delete all the keys of all the existing databases, not just the currently selected one. This\n   * command never fails.\n   * @return Status code reply\n   */\n  @Override\n  public String flushAll() {\n    checkIsInMultiOrPipeline();\n    client.flushAll();\n    return client.getStatusCodeReply();\n  }\n\n  /**\n   * GETSET is an atomic set this value and return the old value command. Set key to the string\n   * value and return the old value stored at key. The string can't be longer than 1073741824 bytes\n   * (1 GB).\n   * <p>\n   * Time complexity: O(1)\n   * @param key\n   * @param value\n   * @return Bulk reply\n   */\n  @Override\n  public byte[] getSet(final byte[] key, final byte[] value) {\n    checkIsInMultiOrPipeline();\n    client.getSet(key, value);\n    return client.getBinaryBulkReply();\n  }\n\n  /**\n   * Get the values of all the specified keys. If one or more keys dont exist or is not of type\n   * String, a 'nil' value is returned instead of the value of the specified key, but the operation\n   * never fails.\n   * <p>\n   * Time complexity: O(1) for every key\n   * @param keys\n   * @return Multi bulk reply\n   */\n  @Override\n  public List<byte[]> mget(final byte[]... keys) {\n    checkIsInMultiOrPipeline();\n    client.mget(keys);\n    return client.getBinaryMultiBulkReply();\n  }\n\n  /**\n   * SETNX works exactly like {@link #set(byte[], byte[]) SET} with the only difference that if the\n   * key already exists no operation is performed. SETNX actually means \"SET if Not eXists\".\n   * <p>\n   * Time complexity: O(1)\n   * @param key\n   * @param value\n   * @return Integer reply, specifically: 1 if the key was set 0 if the key was not set\n   */\n  @Override\n  public Long setnx(final byte[] key, final byte[] value) {\n    checkIsInMultiOrPipeline();\n    client.setnx(key, value);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * The command is exactly equivalent to the following group of commands:\n   * {@link #set(byte[], byte[]) SET} + {@link #expire(byte[], int) EXPIRE}. The operation is\n   * atomic.\n   * <p>\n   * Time complexity: O(1)\n   * @param key\n   * @param seconds\n   * @param value\n   * @return Status code reply\n   */\n  @Override\n  public String setex(final byte[] key, final int seconds, final byte[] value) {\n    checkIsInMultiOrPipeline();\n    client.setex(key, seconds, value);\n    return client.getStatusCodeReply();\n  }\n\n  /**\n   * Set the the respective keys to the respective values. MSET will replace old values with new\n   * values, while {@link #msetnx(byte[]...) MSETNX} will not perform any operation at all even if\n   * just a single key already exists.\n   * <p>\n   * Because of this semantic MSETNX can be used in order to set different keys representing\n   * different fields of an unique logic object in a way that ensures that either all the fields or\n   * none at all are set.\n   * <p>\n   * Both MSET and MSETNX are atomic operations. This means that for instance if the keys A and B\n   * are modified, another client talking to Redis can either see the changes to both A and B at\n   * once, or no modification at all.\n   * @see #msetnx(byte[]...)\n   * @param keysvalues\n   * @return Status code reply Basically +OK as MSET can't fail\n   */\n  @Override\n  public String mset(final byte[]... keysvalues) {\n    checkIsInMultiOrPipeline();\n    client.mset(keysvalues);\n    return client.getStatusCodeReply();\n  }\n\n  /**\n   * Set the the respective keys to the respective values. {@link #mset(byte[]...) MSET} will\n   * replace old values with new values, while MSETNX will not perform any operation at all even if\n   * just a single key already exists.\n   * <p>\n   * Because of this semantic MSETNX can be used in order to set different keys representing\n   * different fields of an unique logic object in a way that ensures that either all the fields or\n   * none at all are set.\n   * <p>\n   * Both MSET and MSETNX are atomic operations. This means that for instance if the keys A and B\n   * are modified, another client talking to Redis can either see the changes to both A and B at\n   * once, or no modification at all.\n   * @see #mset(byte[]...)\n   * @param keysvalues\n   * @return Integer reply, specifically: 1 if the all the keys were set 0 if no key was set (at\n   *         least one key already existed)\n   */\n  @Override\n  public Long msetnx(final byte[]... keysvalues) {\n    checkIsInMultiOrPipeline();\n    client.msetnx(keysvalues);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * DECRBY work just like {@link #decr(byte[]) INCR} but instead to decrement by 1 the decrement is\n   * integer.\n   * <p>\n   * INCR commands are limited to 64 bit signed integers.\n   * <p>\n   * Note: this is actually a string operation, that is, in Redis there are not \"integer\" types.\n   * Simply the string stored at the key is parsed as a base 10 64 bit signed integer, incremented,\n   * and then converted back as a string.\n   * <p>\n   * Time complexity: O(1)\n   * @see #incr(byte[])\n   * @see #decr(byte[])\n   * @see #incrBy(byte[], long)\n   * @param key\n   * @param integer\n   * @return Integer reply, this commands will reply with the new value of key after the increment.\n   */\n  @Override\n  public Long decrBy(final byte[] key, final long integer) {\n    checkIsInMultiOrPipeline();\n    client.decrBy(key, integer);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Decrement the number stored at key by one. If the key does not exist or contains a value of a\n   * wrong type, set the key to the value of \"0\" before to perform the decrement operation.\n   * <p>\n   * INCR commands are limited to 64 bit signed integers.\n   * <p>\n   * Note: this is actually a string operation, that is, in Redis there are not \"integer\" types.\n   * Simply the string stored at the key is parsed as a base 10 64 bit signed integer, incremented,\n   * and then converted back as a string.\n   * <p>\n   * Time complexity: O(1)\n   * @see #incr(byte[])\n   * @see #incrBy(byte[], long)\n   * @see #decrBy(byte[], long)\n   * @param key\n   * @return Integer reply, this commands will reply with the new value of key after the increment.\n   */\n  @Override\n  public Long decr(final byte[] key) {\n    checkIsInMultiOrPipeline();\n    client.decr(key);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * INCRBY work just like {@link #incr(byte[]) INCR} but instead to increment by 1 the increment is\n   * integer.\n   * <p>\n   * INCR commands are limited to 64 bit signed integers.\n   * <p>\n   * Note: this is actually a string operation, that is, in Redis there are not \"integer\" types.\n   * Simply the string stored at the key is parsed as a base 10 64 bit signed integer, incremented,\n   * and then converted back as a string.\n   * <p>\n   * Time complexity: O(1)\n   * @see #incr(byte[])\n   * @see #decr(byte[])\n   * @see #decrBy(byte[], long)\n   * @param key\n   * @param integer\n   * @return Integer reply, this commands will reply with the new value of key after the increment.\n   */\n  @Override\n  public Long incrBy(final byte[] key, final long integer) {\n    checkIsInMultiOrPipeline();\n    client.incrBy(key, integer);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * INCRBYFLOAT work just like {@link #incrBy(byte[], long)} INCRBY} but increments by floats\n   * instead of integers.\n   * <p>\n   * INCRBYFLOAT commands are limited to double precision floating point values.\n   * <p>\n   * Note: this is actually a string operation, that is, in Redis there are not \"double\" types.\n   * Simply the string stored at the key is parsed as a base double precision floating point value,\n   * incremented, and then converted back as a string. There is no DECRYBYFLOAT but providing a\n   * negative value will work as expected.\n   * <p>\n   * Time complexity: O(1)\n   * @see #incr(byte[])\n   * @see #decr(byte[])\n   * @see #decrBy(byte[], long)\n   * @param key the key to increment\n   * @param integer the value to increment by\n   * @return Integer reply, this commands will reply with the new value of key after the increment.\n   */\n  @Override\n  public Double incrByFloat(final byte[] key, final double integer) {\n    checkIsInMultiOrPipeline();\n    client.incrByFloat(key, integer);\n    String dval = client.getBulkReply();\n    return (dval != null ? new Double(dval) : null);\n  }\n\n  /**\n   * Increment the number stored at key by one. If the key does not exist or contains a value of a\n   * wrong type, set the key to the value of \"0\" before to perform the increment operation.\n   * <p>\n   * INCR commands are limited to 64 bit signed integers.\n   * <p>\n   * Note: this is actually a string operation, that is, in Redis there are not \"integer\" types.\n   * Simply the string stored at the key is parsed as a base 10 64 bit signed integer, incremented,\n   * and then converted back as a string.\n   * <p>\n   * Time complexity: O(1)\n   * @see #incrBy(byte[], long)\n   * @see #decr(byte[])\n   * @see #decrBy(byte[], long)\n   * @param key\n   * @return Integer reply, this commands will reply with the new value of key after the increment.\n   */\n  @Override\n  public Long incr(final byte[] key) {\n    checkIsInMultiOrPipeline();\n    client.incr(key);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * If the key already exists and is a string, this command appends the provided value at the end\n   * of the string. If the key does not exist it is created and set as an empty string, so APPEND\n   * will be very similar to SET in this special case.\n   * <p>\n   * Time complexity: O(1). The amortized time complexity is O(1) assuming the appended value is\n   * small and the already present value is of any size, since the dynamic string library used by\n   * Redis will double the free space available on every reallocation.\n   * @param key\n   * @param value\n   * @return Integer reply, specifically the total length of the string after the append operation.\n   */\n  @Override\n  public Long append(final byte[] key, final byte[] value) {\n    checkIsInMultiOrPipeline();\n    client.append(key, value);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Return a subset of the string from offset start to offset end (both offsets are inclusive).\n   * Negative offsets can be used in order to provide an offset starting from the end of the string.\n   * So -1 means the last char, -2 the penultimate and so forth.\n   * <p>\n   * The function handles out of range requests without raising an error, but just limiting the\n   * resulting range to the actual length of the string.\n   * <p>\n   * Time complexity: O(start+n) (with start being the start index and n the total length of the\n   * requested range). Note that the lookup part of this command is O(1) so for small strings this\n   * is actually an O(1) command.\n   * @param key\n   * @param start\n   * @param end\n   * @return Bulk reply\n   */\n  @Override\n  public byte[] substr(final byte[] key, final int start, final int end) {\n    checkIsInMultiOrPipeline();\n    client.substr(key, start, end);\n    return client.getBinaryBulkReply();\n  }\n\n  /**\n   * Set the specified hash field to the specified value.\n   * <p>\n   * If key does not exist, a new key holding a hash is created.\n   * <p>\n   * <b>Time complexity:</b> O(1)\n   * @param key\n   * @param field\n   * @param value\n   * @return If the field already exists, and the HSET just produced an update of the value, 0 is\n   *         returned, otherwise if a new field is created 1 is returned.\n   */\n  @Override\n  public Long hset(final byte[] key, final byte[] field, final byte[] value) {\n    checkIsInMultiOrPipeline();\n    client.hset(key, field, value);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * If key holds a hash, retrieve the value associated to the specified field.\n   * <p>\n   * If the field is not found or the key does not exist, a special 'nil' value is returned.\n   * <p>\n   * <b>Time complexity:</b> O(1)\n   * @param key\n   * @param field\n   * @return Bulk reply\n   */\n  @Override\n  public byte[] hget(final byte[] key, final byte[] field) {\n    checkIsInMultiOrPipeline();\n    client.hget(key, field);\n    return client.getBinaryBulkReply();\n  }\n\n  /**\n   * Set the specified hash field to the specified value if the field not exists. <b>Time\n   * complexity:</b> O(1)\n   * @param key\n   * @param field\n   * @param value\n   * @return If the field already exists, 0 is returned, otherwise if a new field is created 1 is\n   *         returned.\n   */\n  @Override\n  public Long hsetnx(final byte[] key, final byte[] field, final byte[] value) {\n    checkIsInMultiOrPipeline();\n    client.hsetnx(key, field, value);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Set the respective fields to the respective values. HMSET replaces old values with new values.\n   * <p>\n   * If key does not exist, a new key holding a hash is created.\n   * <p>\n   * <b>Time complexity:</b> O(N) (with N being the number of fields)\n   * @param key\n   * @param hash\n   * @return Always OK because HMSET can't fail\n   */\n  @Override\n  public String hmset(final byte[] key, final Map<byte[], byte[]> hash) {\n    checkIsInMultiOrPipeline();\n    client.hmset(key, hash);\n    return client.getStatusCodeReply();\n  }\n\n  /**\n   * Retrieve the values associated to the specified fields.\n   * <p>\n   * If some of the specified fields do not exist, nil values are returned. Non existing keys are\n   * considered like empty hashes.\n   * <p>\n   * <b>Time complexity:</b> O(N) (with N being the number of fields)\n   * @param key\n   * @param fields\n   * @return Multi Bulk Reply specifically a list of all the values associated with the specified\n   *         fields, in the same order of the request.\n   */\n  @Override\n  public List<byte[]> hmget(final byte[] key, final byte[]... fields) {\n    checkIsInMultiOrPipeline();\n    client.hmget(key, fields);\n    return client.getBinaryMultiBulkReply();\n  }\n\n  /**\n   * Increment the number stored at field in the hash at key by value. If key does not exist, a new\n   * key holding a hash is created. If field does not exist or holds a string, the value is set to 0\n   * before applying the operation. Since the value argument is signed you can use this command to\n   * perform both increments and decrements.\n   * <p>\n   * The range of values supported by HINCRBY is limited to 64 bit signed integers.\n   * <p>\n   * <b>Time complexity:</b> O(1)\n   * @param key\n   * @param field\n   * @param value\n   * @return Integer reply The new value at field after the increment operation.\n   */\n  @Override\n  public Long hincrBy(final byte[] key, final byte[] field, final long value) {\n    checkIsInMultiOrPipeline();\n    client.hincrBy(key, field, value);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Increment the number stored at field in the hash at key by a double precision floating point\n   * value. If key does not exist, a new key holding a hash is created. If field does not exist or\n   * holds a string, the value is set to 0 before applying the operation. Since the value argument\n   * is signed you can use this command to perform both increments and decrements.\n   * <p>\n   * The range of values supported by HINCRBYFLOAT is limited to double precision floating point\n   * values.\n   * <p>\n   * <b>Time complexity:</b> O(1)\n   * @param key\n   * @param field\n   * @param value\n   * @return Double precision floating point reply The new value at field after the increment\n   *         operation.\n   */\n  @Override\n  public Double hincrByFloat(final byte[] key, final byte[] field, final double value) {\n    checkIsInMultiOrPipeline();\n    client.hincrByFloat(key, field, value);\n    final String dval = client.getBulkReply();\n    return (dval != null ? new Double(dval) : null);\n  }\n\n  /**\n   * Test for existence of a specified field in a hash. <b>Time complexity:</b> O(1)\n   * @param key\n   * @param field\n   * @return Return 1 if the hash stored at key contains the specified field. Return 0 if the key is\n   *         not found or the field is not present.\n   */\n  @Override\n  public Boolean hexists(final byte[] key, final byte[] field) {\n    checkIsInMultiOrPipeline();\n    client.hexists(key, field);\n    return client.getIntegerReply() == 1;\n  }\n\n  /**\n   * Remove the specified field from an hash stored at key.\n   * <p>\n   * <b>Time complexity:</b> O(1)\n   * @param key\n   * @param fields\n   * @return If the field was present in the hash it is deleted and 1 is returned, otherwise 0 is\n   *         returned and no operation is performed.\n   */\n  @Override\n  public Long hdel(final byte[] key, final byte[]... fields) {\n    checkIsInMultiOrPipeline();\n    client.hdel(key, fields);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Return the number of items in a hash.\n   * <p>\n   * <b>Time complexity:</b> O(1)\n   * @param key\n   * @return The number of entries (fields) contained in the hash stored at key. If the specified\n   *         key does not exist, 0 is returned assuming an empty hash.\n   */\n  @Override\n  public Long hlen(final byte[] key) {\n    checkIsInMultiOrPipeline();\n    client.hlen(key);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Return all the fields in a hash.\n   * <p>\n   * <b>Time complexity:</b> O(N), where N is the total number of entries\n   * @param key\n   * @return All the fields names contained into a hash.\n   */\n  @Override\n  public Set<byte[]> hkeys(final byte[] key) {\n    checkIsInMultiOrPipeline();\n    client.hkeys(key);\n    return SetFromList.of(client.getBinaryMultiBulkReply());\n  }\n\n  /**\n   * Return all the values in a hash.\n   * <p>\n   * <b>Time complexity:</b> O(N), where N is the total number of entries\n   * @param key\n   * @return All the fields values contained into a hash.\n   */\n  @Override\n  public List<byte[]> hvals(final byte[] key) {\n    checkIsInMultiOrPipeline();\n    client.hvals(key);\n    return client.getBinaryMultiBulkReply();\n  }\n\n  /**\n   * Return all the fields and associated values in a hash.\n   * <p>\n   * <b>Time complexity:</b> O(N), where N is the total number of entries\n   * @param key\n   * @return All the fields and values contained into a hash.\n   */\n  @Override\n  public Map<byte[], byte[]> hgetAll(final byte[] key) {\n    checkIsInMultiOrPipeline();\n    client.hgetAll(key);\n    final List<byte[]> flatHash = client.getBinaryMultiBulkReply();\n    final Map<byte[], byte[]> hash = new JedisByteHashMap();\n    final Iterator<byte[]> iterator = flatHash.iterator();\n    while (iterator.hasNext()) {\n      hash.put(iterator.next(), iterator.next());\n    }\n\n    return hash;\n  }\n\n  /**\n   * Add the string value to the head (LPUSH) or tail (RPUSH) of the list stored at key. If the key\n   * does not exist an empty list is created just before the append operation. If the key exists but\n   * is not a List an error is returned.\n   * <p>\n   * Time complexity: O(1)\n   * @see BinaryJedis#rpush(byte[], byte[]...)\n   * @param key\n   * @param strings\n   * @return Integer reply, specifically, the number of elements inside the list after the push\n   *         operation.\n   */\n  @Override\n  public Long rpush(final byte[] key, final byte[]... strings) {\n    checkIsInMultiOrPipeline();\n    client.rpush(key, strings);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Add the string value to the head (LPUSH) or tail (RPUSH) of the list stored at key. If the key\n   * does not exist an empty list is created just before the append operation. If the key exists but\n   * is not a List an error is returned.\n   * <p>\n   * Time complexity: O(1)\n   * @see BinaryJedis#rpush(byte[], byte[]...)\n   * @param key\n   * @param strings\n   * @return Integer reply, specifically, the number of elements inside the list after the push\n   *         operation.\n   */\n  @Override\n  public Long lpush(final byte[] key, final byte[]... strings) {\n    checkIsInMultiOrPipeline();\n    client.lpush(key, strings);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Return the length of the list stored at the specified key. If the key does not exist zero is\n   * returned (the same behaviour as for empty lists). If the value stored at key is not a list an\n   * error is returned.\n   * <p>\n   * Time complexity: O(1)\n   * @param key\n   * @return The length of the list.\n   */\n  @Override\n  public Long llen(final byte[] key) {\n    checkIsInMultiOrPipeline();\n    client.llen(key);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Return the specified elements of the list stored at the specified key. Start and end are\n   * zero-based indexes. 0 is the first element of the list (the list head), 1 the next element and\n   * so on.\n   * <p>\n   * For example LRANGE foobar 0 2 will return the first three elements of the list.\n   * <p>\n   * start and end can also be negative numbers indicating offsets from the end of the list. For\n   * example -1 is the last element of the list, -2 the penultimate element and so on.\n   * <p>\n   * <b>Consistency with range functions in various programming languages</b>\n   * <p>\n   * Note that if you have a list of numbers from 0 to 100, LRANGE 0 10 will return 11 elements,\n   * that is, rightmost item is included. This may or may not be consistent with behavior of\n   * range-related functions in your programming language of choice (think Ruby's Range.new,\n   * Array#slice or Python's range() function).\n   * <p>\n   * LRANGE behavior is consistent with one of Tcl.\n   * <p>\n   * <b>Out-of-range indexes</b>\n   * <p>\n   * Indexes out of range will not produce an error: if start is over the end of the list, or start\n   * &gt; end, an empty list is returned. If end is over the end of the list Redis will threat it\n   * just like the last element of the list.\n   * <p>\n   * Time complexity: O(start+n) (with n being the length of the range and start being the start\n   * offset)\n   * @param key\n   * @param start\n   * @param end\n   * @return Multi bulk reply, specifically a list of elements in the specified range.\n   */\n  @Override\n  public List<byte[]> lrange(final byte[] key, final long start, final long end) {\n    checkIsInMultiOrPipeline();\n    client.lrange(key, start, end);\n    return client.getBinaryMultiBulkReply();\n  }\n\n  /**\n   * Trim an existing list so that it will contain only the specified range of elements specified.\n   * Start and end are zero-based indexes. 0 is the first element of the list (the list head), 1 the\n   * next element and so on.\n   * <p>\n   * For example LTRIM foobar 0 2 will modify the list stored at foobar key so that only the first\n   * three elements of the list will remain.\n   * <p>\n   * start and end can also be negative numbers indicating offsets from the end of the list. For\n   * example -1 is the last element of the list, -2 the penultimate element and so on.\n   * <p>\n   * Indexes out of range will not produce an error: if start is over the end of the list, or start\n   * &gt; end, an empty list is left as value. If end over the end of the list Redis will threat it\n   * just like the last element of the list.\n   * <p>\n   * Hint: the obvious use of LTRIM is together with LPUSH/RPUSH. For example:\n   * <p>\n   * {@code lpush(\"mylist\", \"someelement\"); ltrim(\"mylist\", 0, 99); * }\n   * <p>\n   * The above two commands will push elements in the list taking care that the list will not grow\n   * without limits. This is very useful when using Redis to store logs for example. It is important\n   * to note that when used in this way LTRIM is an O(1) operation because in the average case just\n   * one element is removed from the tail of the list.\n   * <p>\n   * Time complexity: O(n) (with n being len of list - len of range)\n   * @param key\n   * @param start\n   * @param end\n   * @return Status code reply\n   */\n  @Override\n  public String ltrim(final byte[] key, final long start, final long end) {\n    checkIsInMultiOrPipeline();\n    client.ltrim(key, start, end);\n    return client.getStatusCodeReply();\n  }\n\n  /**\n   * Return the specified element of the list stored at the specified key. 0 is the first element, 1\n   * the second and so on. Negative indexes are supported, for example -1 is the last element, -2\n   * the penultimate and so on.\n   * <p>\n   * If the value stored at key is not of list type an error is returned. If the index is out of\n   * range a 'nil' reply is returned.\n   * <p>\n   * Note that even if the average time complexity is O(n) asking for the first or the last element\n   * of the list is O(1).\n   * <p>\n   * Time complexity: O(n) (with n being the length of the list)\n   * @param key\n   * @param index\n   * @return Bulk reply, specifically the requested element\n   */\n  @Override\n  public byte[] lindex(final byte[] key, final long index) {\n    checkIsInMultiOrPipeline();\n    client.lindex(key, index);\n    return client.getBinaryBulkReply();\n  }\n\n  /**\n   * Set a new value as the element at index position of the List at key.\n   * <p>\n   * Out of range indexes will generate an error.\n   * <p>\n   * Similarly to other list commands accepting indexes, the index can be negative to access\n   * elements starting from the end of the list. So -1 is the last element, -2 is the penultimate,\n   * and so forth.\n   * <p>\n   * <b>Time complexity:</b>\n   * <p>\n   * O(N) (with N being the length of the list), setting the first or last elements of the list is\n   * O(1).\n   * @see #lindex(byte[], long)\n   * @param key\n   * @param index\n   * @param value\n   * @return Status code reply\n   */\n  @Override\n  public String lset(final byte[] key, final long index, final byte[] value) {\n    checkIsInMultiOrPipeline();\n    client.lset(key, index, value);\n    return client.getStatusCodeReply();\n  }\n\n  /**\n   * Remove the first count occurrences of the value element from the list. If count is zero all the\n   * elements are removed. If count is negative elements are removed from tail to head, instead to\n   * go from head to tail that is the normal behaviour. So for example LREM with count -2 and hello\n   * as value to remove against the list (a,b,c,hello,x,hello,hello) will have the list\n   * (a,b,c,hello,x). The number of removed elements is returned as an integer, see below for more\n   * information about the returned value. Note that non existing keys are considered like empty\n   * lists by LREM, so LREM against non existing keys will always return 0.\n   * <p>\n   * Time complexity: O(N) (with N being the length of the list)\n   * @param key\n   * @param count\n   * @param value\n   * @return Integer Reply, specifically: The number of removed elements if the operation succeeded\n   */\n  @Override\n  public Long lrem(final byte[] key, final long count, final byte[] value) {\n    checkIsInMultiOrPipeline();\n    client.lrem(key, count, value);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Atomically return and remove the first (LPOP) or last (RPOP) element of the list. For example\n   * if the list contains the elements \"a\",\"b\",\"c\" LPOP will return \"a\" and the list will become\n   * \"b\",\"c\".\n   * <p>\n   * If the key does not exist or the list is already empty the special value 'nil' is returned.\n   * @see #rpop(byte[])\n   * @param key\n   * @return Bulk reply\n   */\n  @Override\n  public byte[] lpop(final byte[] key) {\n    checkIsInMultiOrPipeline();\n    client.lpop(key);\n    return client.getBinaryBulkReply();\n  }\n\n  /**\n   * Atomically return and remove the first (LPOP) or last (RPOP) element of the list. For example\n   * if the list contains the elements \"a\",\"b\",\"c\" LPOP will return \"a\" and the list will become\n   * \"b\",\"c\".\n   * <p>\n   * If the key does not exist or the list is already empty the special value 'nil' is returned.\n   * @see #lpop(byte[])\n   * @param key\n   * @return Bulk reply\n   */\n  @Override\n  public byte[] rpop(final byte[] key) {\n    checkIsInMultiOrPipeline();\n    client.rpop(key);\n    return client.getBinaryBulkReply();\n  }\n\n  /**\n   * Atomically return and remove the last (tail) element of the srckey list, and push the element\n   * as the first (head) element of the dstkey list. For example if the source list contains the\n   * elements \"a\",\"b\",\"c\" and the destination list contains the elements \"foo\",\"bar\" after an\n   * RPOPLPUSH command the content of the two lists will be \"a\",\"b\" and \"c\",\"foo\",\"bar\".\n   * <p>\n   * If the key does not exist or the list is already empty the special value 'nil' is returned. If\n   * the srckey and dstkey are the same the operation is equivalent to removing the last element\n   * from the list and pusing it as first element of the list, so it's a \"list rotation\" command.\n   * <p>\n   * Time complexity: O(1)\n   * @param srckey\n   * @param dstkey\n   * @return Bulk reply\n   */\n  @Override\n  public byte[] rpoplpush(final byte[] srckey, final byte[] dstkey) {\n    checkIsInMultiOrPipeline();\n    client.rpoplpush(srckey, dstkey);\n    return client.getBinaryBulkReply();\n  }\n\n  /**\n   * Add the specified member to the set value stored at key. If member is already a member of the\n   * set no operation is performed. If key does not exist a new set with the specified member as\n   * sole member is created. If the key exists but does not hold a set value an error is returned.\n   * <p>\n   * Time complexity O(1)\n   * @param key\n   * @param members\n   * @return Integer reply, specifically: 1 if the new element was added 0 if the element was\n   *         already a member of the set\n   */\n  @Override\n  public Long sadd(final byte[] key, final byte[]... members) {\n    checkIsInMultiOrPipeline();\n    client.sadd(key, members);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Return all the members (elements) of the set value stored at key. This is just syntax glue for\n   * {@link #sinter(byte[]...)} SINTER}.\n   * <p>\n   * Time complexity O(N)\n   * @param key the key of the set\n   * @return Multi bulk reply\n   */\n  @Override\n  public Set<byte[]> smembers(final byte[] key) {\n    checkIsInMultiOrPipeline();\n    client.smembers(key);\n    return SetFromList.of(client.getBinaryMultiBulkReply());\n  }\n\n  /**\n   * Remove the specified member from the set value stored at key. If member was not a member of the\n   * set no operation is performed. If key does not hold a set value an error is returned.\n   * <p>\n   * Time complexity O(1)\n   * @param key the key of the set\n   * @param member the set member to remove\n   * @return Integer reply, specifically: 1 if the new element was removed 0 if the new element was\n   *         not a member of the set\n   */\n  @Override\n  public Long srem(final byte[] key, final byte[]... member) {\n    checkIsInMultiOrPipeline();\n    client.srem(key, member);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Remove a random element from a Set returning it as return value. If the Set is empty or the key\n   * does not exist, a nil object is returned.\n   * <p>\n   * The {@link #srandmember(byte[])} command does a similar work but the returned element is not\n   * removed from the Set.\n   * <p>\n   * Time complexity O(1)\n   * @param key\n   * @return Bulk reply\n   */\n  @Override\n  public byte[] spop(final byte[] key) {\n    checkIsInMultiOrPipeline();\n    client.spop(key);\n    return client.getBinaryBulkReply();\n  }\n\n  @Override\n  public Set<byte[]> spop(final byte[] key, final long count) {\n    checkIsInMultiOrPipeline();\n    client.spop(key, count);\n    return SetFromList.of(client.getBinaryMultiBulkReply());\n  }\n\n  /**\n   * Move the specified member from the set at srckey to the set at dstkey. This operation is\n   * atomic, in every given moment the element will appear to be in the source or destination set\n   * for accessing clients.\n   * <p>\n   * If the source set does not exist or does not contain the specified element no operation is\n   * performed and zero is returned, otherwise the element is removed from the source set and added\n   * to the destination set. On success one is returned, even if the element was already present in\n   * the destination set.\n   * <p>\n   * An error is raised if the source or destination keys contain a non Set value.\n   * <p>\n   * Time complexity O(1)\n   * @param srckey\n   * @param dstkey\n   * @param member\n   * @return Integer reply, specifically: 1 if the element was moved 0 if the element was not found\n   *         on the first set and no operation was performed\n   */\n  @Override\n  public Long smove(final byte[] srckey, final byte[] dstkey, final byte[] member) {\n    checkIsInMultiOrPipeline();\n    client.smove(srckey, dstkey, member);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Return the set cardinality (number of elements). If the key does not exist 0 is returned, like\n   * for empty sets.\n   * @param key\n   * @return Integer reply, specifically: the cardinality (number of elements) of the set as an\n   *         integer.\n   */\n  @Override\n  public Long scard(final byte[] key) {\n    checkIsInMultiOrPipeline();\n    client.scard(key);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Return 1 if member is a member of the set stored at key, otherwise 0 is returned.\n   * <p>\n   * Time complexity O(1)\n   * @param key\n   * @param member\n   * @return Integer reply, specifically: 1 if the element is a member of the set 0 if the element\n   *         is not a member of the set OR if the key does not exist\n   */\n  @Override\n  public Boolean sismember(final byte[] key, final byte[] member) {\n    checkIsInMultiOrPipeline();\n    client.sismember(key, member);\n    return client.getIntegerReply() == 1;\n  }\n\n  /**\n   * Return the members of a set resulting from the intersection of all the sets hold at the\n   * specified keys. Like in {@link #lrange(byte[], long, long)} LRANGE} the result is sent to the\n   * client as a multi-bulk reply (see the protocol specification for more information). If just a\n   * single key is specified, then this command produces the same result as\n   * {@link #smembers(byte[]) SMEMBERS}. Actually SMEMBERS is just syntax sugar for SINTER.\n   * <p>\n   * Non existing keys are considered like empty sets, so if one of the keys is missing an empty set\n   * is returned (since the intersection with an empty set always is an empty set).\n   * <p>\n   * Time complexity O(N*M) worst case where N is the cardinality of the smallest set and M the\n   * number of sets\n   * @param keys\n   * @return Multi bulk reply, specifically the list of common elements.\n   */\n  @Override\n  public Set<byte[]> sinter(final byte[]... keys) {\n    checkIsInMultiOrPipeline();\n    client.sinter(keys);\n    return SetFromList.of(client.getBinaryMultiBulkReply());\n  }\n\n  /**\n   * This commnad works exactly like {@link #sinter(byte[]...) SINTER} but instead of being returned\n   * the resulting set is sotred as dstkey.\n   * <p>\n   * Time complexity O(N*M) worst case where N is the cardinality of the smallest set and M the\n   * number of sets\n   * @param dstkey\n   * @param keys\n   * @return Status code reply\n   */\n  @Override\n  public Long sinterstore(final byte[] dstkey, final byte[]... keys) {\n    checkIsInMultiOrPipeline();\n    client.sinterstore(dstkey, keys);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Return the members of a set resulting from the union of all the sets hold at the specified\n   * keys. Like in {@link #lrange(byte[], long, long)} LRANGE} the result is sent to the client as a\n   * multi-bulk reply (see the protocol specification for more information). If just a single key is\n   * specified, then this command produces the same result as {@link #smembers(byte[]) SMEMBERS}.\n   * <p>\n   * Non existing keys are considered like empty sets.\n   * <p>\n   * Time complexity O(N) where N is the total number of elements in all the provided sets\n   * @param keys\n   * @return Multi bulk reply, specifically the list of common elements.\n   */\n  @Override\n  public Set<byte[]> sunion(final byte[]... keys) {\n    checkIsInMultiOrPipeline();\n    client.sunion(keys);\n    return SetFromList.of(client.getBinaryMultiBulkReply());\n  }\n\n  /**\n   * This command works exactly like {@link #sunion(byte[]...) SUNION} but instead of being returned\n   * the resulting set is stored as dstkey. Any existing value in dstkey will be over-written.\n   * <p>\n   * Time complexity O(N) where N is the total number of elements in all the provided sets\n   * @param dstkey\n   * @param keys\n   * @return Status code reply\n   */\n  @Override\n  public Long sunionstore(final byte[] dstkey, final byte[]... keys) {\n    checkIsInMultiOrPipeline();\n    client.sunionstore(dstkey, keys);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Return the difference between the Set stored at key1 and all the Sets key2, ..., keyN\n   * <p>\n   * <b>Example:</b>\n   * \n   * <pre>\n   * key1 = [x, a, b, c]\n   * key2 = [c]\n   * key3 = [a, d]\n   * SDIFF key1,key2,key3 =&gt; [x, b]\n   * </pre>\n   * \n   * Non existing keys are considered like empty sets.\n   * <p>\n   * <b>Time complexity:</b>\n   * <p>\n   * O(N) with N being the total number of elements of all the sets\n   * @param keys\n   * @return Return the members of a set resulting from the difference between the first set\n   *         provided and all the successive sets.\n   */\n  @Override\n  public Set<byte[]> sdiff(final byte[]... keys) {\n    checkIsInMultiOrPipeline();\n    client.sdiff(keys);\n    return SetFromList.of(client.getBinaryMultiBulkReply());\n  }\n\n  /**\n   * This command works exactly like {@link #sdiff(byte[]...) SDIFF} but instead of being returned\n   * the resulting set is stored in dstkey.\n   * @param dstkey\n   * @param keys\n   * @return Status code reply\n   */\n  @Override\n  public Long sdiffstore(final byte[] dstkey, final byte[]... keys) {\n    checkIsInMultiOrPipeline();\n    client.sdiffstore(dstkey, keys);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Return a random element from a Set, without removing the element. If the Set is empty or the\n   * key does not exist, a nil object is returned.\n   * <p>\n   * The SPOP command does a similar work but the returned element is popped (removed) from the Set.\n   * <p>\n   * Time complexity O(1)\n   * @param key\n   * @return Bulk reply\n   */\n  @Override\n  public byte[] srandmember(final byte[] key) {\n    checkIsInMultiOrPipeline();\n    client.srandmember(key);\n    return client.getBinaryBulkReply();\n  }\n\n  @Override\n  public List<byte[]> srandmember(final byte[] key, final int count) {\n    checkIsInMultiOrPipeline();\n    client.srandmember(key, count);\n    return client.getBinaryMultiBulkReply();\n  }\n\n  /**\n   * Add the specified member having the specifeid score to the sorted set stored at key. If member\n   * is already a member of the sorted set the score is updated, and the element reinserted in the\n   * right position to ensure sorting. If key does not exist a new sorted set with the specified\n   * member as sole member is crated. If the key exists but does not hold a sorted set value an\n   * error is returned.\n   * <p>\n   * The score value can be the string representation of a double precision floating point number.\n   * <p>\n   * Time complexity O(log(N)) with N being the number of elements in the sorted set\n   * @param key\n   * @param score\n   * @param member\n   * @return Integer reply, specifically: 1 if the new element was added 0 if the element was\n   *         already a member of the sorted set and the score was updated\n   */\n  @Override\n  public Long zadd(final byte[] key, final double score, final byte[] member) {\n    checkIsInMultiOrPipeline();\n    client.zadd(key, score, member);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public Long zadd(byte[] key, double score, byte[] member, ZAddParams params) {\n    checkIsInMultiOrPipeline();\n    client.zadd(key, score, member, params);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public Long zadd(final byte[] key, final Map<byte[], Double> scoreMembers) {\n    checkIsInMultiOrPipeline();\n    client.zadd(key, scoreMembers);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public Long zadd(byte[] key, Map<byte[], Double> scoreMembers, ZAddParams params) {\n    checkIsInMultiOrPipeline();\n    client.zadd(key, scoreMembers, params);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public Set<byte[]> zrange(final byte[] key, final long start, final long end) {\n    checkIsInMultiOrPipeline();\n    client.zrange(key, start, end);\n    return SetFromList.of(client.getBinaryMultiBulkReply());\n  }\n\n  /**\n   * Remove the specified member from the sorted set value stored at key. If member was not a member\n   * of the set no operation is performed. If key does not not hold a set value an error is\n   * returned.\n   * <p>\n   * Time complexity O(log(N)) with N being the number of elements in the sorted set\n   * @param key\n   * @param members\n   * @return Integer reply, specifically: 1 if the new element was removed 0 if the new element was\n   *         not a member of the set\n   */\n  @Override\n  public Long zrem(final byte[] key, final byte[]... members) {\n    checkIsInMultiOrPipeline();\n    client.zrem(key, members);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * If member already exists in the sorted set adds the increment to its score and updates the\n   * position of the element in the sorted set accordingly. If member does not already exist in the\n   * sorted set it is added with increment as score (that is, like if the previous score was\n   * virtually zero). If key does not exist a new sorted set with the specified member as sole\n   * member is crated. If the key exists but does not hold a sorted set value an error is returned.\n   * <p>\n   * The score value can be the string representation of a double precision floating point number.\n   * It's possible to provide a negative value to perform a decrement.\n   * <p>\n   * For an introduction to sorted sets check the Introduction to Redis data types page.\n   * <p>\n   * Time complexity O(log(N)) with N being the number of elements in the sorted set\n   * @param key\n   * @param score\n   * @param member\n   * @return The new score\n   */\n  @Override\n  public Double zincrby(final byte[] key, final double score, final byte[] member) {\n    checkIsInMultiOrPipeline();\n    client.zincrby(key, score, member);\n    String newscore = client.getBulkReply();\n    return Double.valueOf(newscore);\n  }\n\n  @Override\n  public Double zincrby(byte[] key, double score, byte[] member, ZIncrByParams params) {\n    checkIsInMultiOrPipeline();\n    client.zincrby(key, score, member, params);\n    String newscore = client.getBulkReply();\n\n    // with nx / xx options it could return null now\n    if (newscore == null) return null;\n\n    return Double.valueOf(newscore);\n  }\n\n  /**\n   * Return the rank (or index) or member in the sorted set at key, with scores being ordered from\n   * low to high.\n   * <p>\n   * When the given member does not exist in the sorted set, the special value 'nil' is returned.\n   * The returned rank (or index) of the member is 0-based for both commands.\n   * <p>\n   * <b>Time complexity:</b>\n   * <p>\n   * O(log(N))\n   * @see #zrevrank(byte[], byte[])\n   * @param key\n   * @param member\n   * @return Integer reply or a nil bulk reply, specifically: the rank of the element as an integer\n   *         reply if the element exists. A nil bulk reply if there is no such element.\n   */\n  @Override\n  public Long zrank(final byte[] key, final byte[] member) {\n    checkIsInMultiOrPipeline();\n    client.zrank(key, member);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Return the rank (or index) or member in the sorted set at key, with scores being ordered from\n   * high to low.\n   * <p>\n   * When the given member does not exist in the sorted set, the special value 'nil' is returned.\n   * The returned rank (or index) of the member is 0-based for both commands.\n   * <p>\n   * <b>Time complexity:</b>\n   * <p>\n   * O(log(N))\n   * @see #zrank(byte[], byte[])\n   * @param key\n   * @param member\n   * @return Integer reply or a nil bulk reply, specifically: the rank of the element as an integer\n   *         reply if the element exists. A nil bulk reply if there is no such element.\n   */\n  @Override\n  public Long zrevrank(final byte[] key, final byte[] member) {\n    checkIsInMultiOrPipeline();\n    client.zrevrank(key, member);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public Set<byte[]> zrevrange(final byte[] key, final long start, final long end) {\n    checkIsInMultiOrPipeline();\n    client.zrevrange(key, start, end);\n    return SetFromList.of(client.getBinaryMultiBulkReply());\n  }\n\n  @Override\n  public Set<Tuple> zrangeWithScores(final byte[] key, final long start, final long end) {\n    checkIsInMultiOrPipeline();\n    client.zrangeWithScores(key, start, end);\n    return getBinaryTupledSet();\n  }\n\n  @Override\n  public Set<Tuple> zrevrangeWithScores(final byte[] key, final long start, final long end) {\n    checkIsInMultiOrPipeline();\n    client.zrevrangeWithScores(key, start, end);\n    return getBinaryTupledSet();\n  }\n\n  /**\n   * Return the sorted set cardinality (number of elements). If the key does not exist 0 is\n   * returned, like for empty sorted sets.\n   * <p>\n   * Time complexity O(1)\n   * @param key\n   * @return the cardinality (number of elements) of the set as an integer.\n   */\n  @Override\n  public Long zcard(final byte[] key) {\n    checkIsInMultiOrPipeline();\n    client.zcard(key);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Return the score of the specified element of the sorted set at key. If the specified element\n   * does not exist in the sorted set, or the key does not exist at all, a special 'nil' value is\n   * returned.\n   * <p>\n   * <b>Time complexity:</b> O(1)\n   * @param key\n   * @param member\n   * @return the score\n   */\n  @Override\n  public Double zscore(final byte[] key, final byte[] member) {\n    checkIsInMultiOrPipeline();\n    client.zscore(key, member);\n    final String score = client.getBulkReply();\n    return (score != null ? new Double(score) : null);\n  }\n\n  public Transaction multi() {\n    client.multi();\n    client.getOne(); // expected OK\n    transaction = new Transaction(client);\n    return transaction;\n  }\n\n  protected void checkIsInMultiOrPipeline() {\n    if (client.isInMulti()) {\n      throw new JedisDataException(\n          \"Cannot use Jedis when in Multi. Please use Transation or reset jedis state.\");\n    } else if (pipeline != null && pipeline.hasPipelinedResponse()) {\n      throw new JedisDataException(\n          \"Cannot use Jedis when in Pipeline. Please use Pipeline or reset jedis state .\");\n    }\n  }\n\n  public void connect() {\n    client.connect();\n  }\n\n  public void disconnect() {\n    client.disconnect();\n  }\n\n  public void resetState() {\n    if (client.isConnected()) {\n      if (transaction != null) {\n        transaction.clear();\n      }\n\n      if (pipeline != null) {\n        pipeline.clear();\n      }\n\n      if (client.isInWatch()) {\n        unwatch();\n      }\n\n      client.resetState();\n    }\n\n    transaction = null;\n    pipeline = null;\n  }\n\n  @Override\n  public String watch(final byte[]... keys) {\n    client.watch(keys);\n    return client.getStatusCodeReply();\n  }\n\n  @Override\n  public String unwatch() {\n    client.unwatch();\n    return client.getStatusCodeReply();\n  }\n\n  @Override\n  public void close() {\n    client.close();\n  }\n\n  /**\n   * Sort a Set or a List.\n   * <p>\n   * Sort the elements contained in the List, Set, or Sorted Set value at key. By default sorting is\n   * numeric with elements being compared as double precision floating point numbers. This is the\n   * simplest form of SORT.\n   * @see #sort(byte[], byte[])\n   * @see #sort(byte[], SortingParams)\n   * @see #sort(byte[], SortingParams, byte[])\n   * @param key\n   * @return Assuming the Set/List at key contains a list of numbers, the return value will be the\n   *         list of numbers ordered from the smallest to the biggest number.\n   */\n  @Override\n  public List<byte[]> sort(final byte[] key) {\n    checkIsInMultiOrPipeline();\n    client.sort(key);\n    return client.getBinaryMultiBulkReply();\n  }\n\n  /**\n   * Sort a Set or a List accordingly to the specified parameters.\n   * <p>\n   * <b>examples:</b>\n   * <p>\n   * Given are the following sets and key/values:\n   * \n   * <pre>\n   * x = [1, 2, 3]\n   * y = [a, b, c]\n   * \n   * k1 = z\n   * k2 = y\n   * k3 = x\n   * \n   * w1 = 9\n   * w2 = 8\n   * w3 = 7\n   * </pre>\n   * \n   * Sort Order:\n   * \n   * <pre>\n   * sort(x) or sort(x, sp.asc())\n   * -&gt; [1, 2, 3]\n   * \n   * sort(x, sp.desc())\n   * -&gt; [3, 2, 1]\n   * \n   * sort(y)\n   * -&gt; [c, a, b]\n   * \n   * sort(y, sp.alpha())\n   * -&gt; [a, b, c]\n   * \n   * sort(y, sp.alpha().desc())\n   * -&gt; [c, a, b]\n   * </pre>\n   * \n   * Limit (e.g. for Pagination):\n   * \n   * <pre>\n   * sort(x, sp.limit(0, 2))\n   * -&gt; [1, 2]\n   * \n   * sort(y, sp.alpha().desc().limit(1, 2))\n   * -&gt; [b, a]\n   * </pre>\n   * \n   * Sorting by external keys:\n   * \n   * <pre>\n   * sort(x, sb.by(w*))\n   * -&gt; [3, 2, 1]\n   * \n   * sort(x, sb.by(w*).desc())\n   * -&gt; [1, 2, 3]\n   * </pre>\n   * \n   * Getting external keys:\n   * \n   * <pre>\n   * sort(x, sp.by(w*).get(k*))\n   * -&gt; [x, y, z]\n   * \n   * sort(x, sp.by(w*).get(#).get(k*))\n   * -&gt; [3, x, 2, y, 1, z]\n   * </pre>\n   * @see #sort(byte[])\n   * @see #sort(byte[], SortingParams, byte[])\n   * @param key\n   * @param sortingParameters\n   * @return a list of sorted elements.\n   */\n  @Override\n  public List<byte[]> sort(final byte[] key, final SortingParams sortingParameters) {\n    checkIsInMultiOrPipeline();\n    client.sort(key, sortingParameters);\n    return client.getBinaryMultiBulkReply();\n  }\n\n  /**\n   * BLPOP (and BRPOP) is a blocking list pop primitive. You can see this commands as blocking\n   * versions of LPOP and RPOP able to block if the specified keys don't exist or contain empty\n   * lists.\n   * <p>\n   * The following is a description of the exact semantic. We describe BLPOP but the two commands\n   * are identical, the only difference is that BLPOP pops the element from the left (head) of the\n   * list, and BRPOP pops from the right (tail).\n   * <p>\n   * <b>Non blocking behavior</b>\n   * <p>\n   * When BLPOP is called, if at least one of the specified keys contain a non empty list, an\n   * element is popped from the head of the list and returned to the caller together with the name\n   * of the key (BLPOP returns a two elements array, the first element is the key, the second the\n   * popped value).\n   * <p>\n   * Keys are scanned from left to right, so for instance if you issue BLPOP list1 list2 list3 0\n   * against a dataset where list1 does not exist but list2 and list3 contain non empty lists, BLPOP\n   * guarantees to return an element from the list stored at list2 (since it is the first non empty\n   * list starting from the left).\n   * <p>\n   * <b>Blocking behavior</b>\n   * <p>\n   * If none of the specified keys exist or contain non empty lists, BLPOP blocks until some other\n   * client performs a LPUSH or an RPUSH operation against one of the lists.\n   * <p>\n   * Once new data is present on one of the lists, the client finally returns with the name of the\n   * key unblocking it and the popped value.\n   * <p>\n   * When blocking, if a non-zero timeout is specified, the client will unblock returning a nil\n   * special value if the specified amount of seconds passed without a push operation against at\n   * least one of the specified keys.\n   * <p>\n   * The timeout argument is interpreted as an integer value. A timeout of zero means instead to\n   * block forever.\n   * <p>\n   * <b>Multiple clients blocking for the same keys</b>\n   * <p>\n   * Multiple clients can block for the same key. They are put into a queue, so the first to be\n   * served will be the one that started to wait earlier, in a first-blpopping first-served fashion.\n   * <p>\n   * <b>blocking POP inside a MULTI/EXEC transaction</b>\n   * <p>\n   * BLPOP and BRPOP can be used with pipelining (sending multiple commands and reading the replies\n   * in batch), but it does not make sense to use BLPOP or BRPOP inside a MULTI/EXEC block (a Redis\n   * transaction).\n   * <p>\n   * The behavior of BLPOP inside MULTI/EXEC when the list is empty is to return a multi-bulk nil\n   * reply, exactly what happens when the timeout is reached. If you like science fiction, think at\n   * it like if inside MULTI/EXEC the time will flow at infinite speed :)\n   * <p>\n   * Time complexity: O(1)\n   * @see #brpop(int, byte[]...)\n   * @param timeout\n   * @param keys\n   * @return BLPOP returns a two-elements array via a multi bulk reply in order to return both the\n   *         unblocking key and the popped value.\n   *         <p>\n   *         When a non-zero timeout is specified, and the BLPOP operation timed out, the return\n   *         value is a nil multi bulk reply. Most client values will return false or nil\n   *         accordingly to the programming language used.\n   */\n  @Override\n  public List<byte[]> blpop(final int timeout, final byte[]... keys) {\n    return blpop(getArgsAddTimeout(timeout, keys));\n  }\n\n  private byte[][] getArgsAddTimeout(int timeout, byte[][] keys) {\n    int size = keys.length;\n    final byte[][] args = new byte[size + 1][];\n    for (int at = 0; at != size; ++at) {\n      args[at] = keys[at];\n    }\n    args[size] = Protocol.toByteArray(timeout);\n    return args;\n  }\n\n  /**\n   * Sort a Set or a List accordingly to the specified parameters and store the result at dstkey.\n   * @see #sort(byte[], SortingParams)\n   * @see #sort(byte[])\n   * @see #sort(byte[], byte[])\n   * @param key\n   * @param sortingParameters\n   * @param dstkey\n   * @return The number of elements of the list at dstkey.\n   */\n  @Override\n  public Long sort(final byte[] key, final SortingParams sortingParameters, final byte[] dstkey) {\n    checkIsInMultiOrPipeline();\n    client.sort(key, sortingParameters, dstkey);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Sort a Set or a List and Store the Result at dstkey.\n   * <p>\n   * Sort the elements contained in the List, Set, or Sorted Set value at key and store the result\n   * at dstkey. By default sorting is numeric with elements being compared as double precision\n   * floating point numbers. This is the simplest form of SORT.\n   * @see #sort(byte[])\n   * @see #sort(byte[], SortingParams)\n   * @see #sort(byte[], SortingParams, byte[])\n   * @param key\n   * @param dstkey\n   * @return The number of elements of the list at dstkey.\n   */\n  @Override\n  public Long sort(final byte[] key, final byte[] dstkey) {\n    checkIsInMultiOrPipeline();\n    client.sort(key, dstkey);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * BLPOP (and BRPOP) is a blocking list pop primitive. You can see this commands as blocking\n   * versions of LPOP and RPOP able to block if the specified keys don't exist or contain empty\n   * lists.\n   * <p>\n   * The following is a description of the exact semantic. We describe BLPOP but the two commands\n   * are identical, the only difference is that BLPOP pops the element from the left (head) of the\n   * list, and BRPOP pops from the right (tail).\n   * <p>\n   * <b>Non blocking behavior</b>\n   * <p>\n   * When BLPOP is called, if at least one of the specified keys contain a non empty list, an\n   * element is popped from the head of the list and returned to the caller together with the name\n   * of the key (BLPOP returns a two elements array, the first element is the key, the second the\n   * popped value).\n   * <p>\n   * Keys are scanned from left to right, so for instance if you issue BLPOP list1 list2 list3 0\n   * against a dataset where list1 does not exist but list2 and list3 contain non empty lists, BLPOP\n   * guarantees to return an element from the list stored at list2 (since it is the first non empty\n   * list starting from the left).\n   * <p>\n   * <b>Blocking behavior</b>\n   * <p>\n   * If none of the specified keys exist or contain non empty lists, BLPOP blocks until some other\n   * client performs a LPUSH or an RPUSH operation against one of the lists.\n   * <p>\n   * Once new data is present on one of the lists, the client finally returns with the name of the\n   * key unblocking it and the popped value.\n   * <p>\n   * When blocking, if a non-zero timeout is specified, the client will unblock returning a nil\n   * special value if the specified amount of seconds passed without a push operation against at\n   * least one of the specified keys.\n   * <p>\n   * The timeout argument is interpreted as an integer value. A timeout of zero means instead to\n   * block forever.\n   * <p>\n   * <b>Multiple clients blocking for the same keys</b>\n   * <p>\n   * Multiple clients can block for the same key. They are put into a queue, so the first to be\n   * served will be the one that started to wait earlier, in a first-blpopping first-served fashion.\n   * <p>\n   * <b>blocking POP inside a MULTI/EXEC transaction</b>\n   * <p>\n   * BLPOP and BRPOP can be used with pipelining (sending multiple commands and reading the replies\n   * in batch), but it does not make sense to use BLPOP or BRPOP inside a MULTI/EXEC block (a Redis\n   * transaction).\n   * <p>\n   * The behavior of BLPOP inside MULTI/EXEC when the list is empty is to return a multi-bulk nil\n   * reply, exactly what happens when the timeout is reached. If you like science fiction, think at\n   * it like if inside MULTI/EXEC the time will flow at infinite speed :)\n   * <p>\n   * Time complexity: O(1)\n   * @see #blpop(int, byte[]...)\n   * @param timeout\n   * @param keys\n   * @return BLPOP returns a two-elements array via a multi bulk reply in order to return both the\n   *         unblocking key and the popped value.\n   *         <p>\n   *         When a non-zero timeout is specified, and the BLPOP operation timed out, the return\n   *         value is a nil multi bulk reply. Most client values will return false or nil\n   *         accordingly to the programming language used.\n   */\n  @Override\n  public List<byte[]> brpop(final int timeout, final byte[]... keys) {\n    return brpop(getArgsAddTimeout(timeout, keys));\n  }\n\n  @Override\n  public List<byte[]> blpop(byte[]... args) {\n    checkIsInMultiOrPipeline();\n    client.blpop(args);\n    client.setTimeoutInfinite();\n    try {\n      return client.getBinaryMultiBulkReply();\n    } finally {\n      client.rollbackTimeout();\n    }\n  }\n\n  @Override\n  public List<byte[]> brpop(byte[]... args) {\n    checkIsInMultiOrPipeline();\n    client.brpop(args);\n    client.setTimeoutInfinite();\n    try {\n      return client.getBinaryMultiBulkReply();\n    } finally {\n      client.rollbackTimeout();\n    }\n  }\n\n  /**\n   * Request for authentication in a password protected Redis server. A Redis server can be\n   * instructed to require a password before to allow clients to issue commands. This is done using\n   * the requirepass directive in the Redis configuration file. If the password given by the client\n   * is correct the server replies with an OK status code reply and starts accepting commands from\n   * the client. Otherwise an error is returned and the clients needs to try a new password. Note\n   * that for the high performance nature of Redis it is possible to try a lot of passwords in\n   * parallel in very short time, so make sure to generate a strong and very long password so that\n   * this attack is infeasible.\n   * @param password\n   * @return Status code reply\n   */\n  @Override\n  public String auth(final String password) {\n    checkIsInMultiOrPipeline();\n    client.auth(password);\n    return client.getStatusCodeReply();\n  }\n\n  public Pipeline pipelined() {\n    pipeline = new Pipeline();\n    pipeline.setClient(client);\n    return pipeline;\n  }\n\n  @Override\n  public Long zcount(final byte[] key, final double min, final double max) {\n    return zcount(key, toByteArray(min), toByteArray(max));\n  }\n\n  @Override\n  public Long zcount(final byte[] key, final byte[] min, final byte[] max) {\n    checkIsInMultiOrPipeline();\n    client.zcount(key, min, max);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Return the all the elements in the sorted set at key with a score between min and max\n   * (including elements with score equal to min or max).\n   * <p>\n   * The elements having the same score are returned sorted lexicographically as ASCII strings (this\n   * follows from a property of Redis sorted sets and does not involve further computation).\n   * <p>\n   * Using the optional {@link #zrangeByScore(byte[], double, double, int, int) LIMIT} it's possible\n   * to get only a range of the matching elements in an SQL-alike way. Note that if offset is large\n   * the commands needs to traverse the list for offset elements and this adds up to the O(M)\n   * figure.\n   * <p>\n   * The {@link #zcount(byte[], double, double) ZCOUNT} command is similar to\n   * {@link #zrangeByScore(byte[], double, double) ZRANGEBYSCORE} but instead of returning the\n   * actual elements in the specified interval, it just returns the number of matching elements.\n   * <p>\n   * <b>Exclusive intervals and infinity</b>\n   * <p>\n   * min and max can be -inf and +inf, so that you are not required to know what's the greatest or\n   * smallest element in order to take, for instance, elements \"up to a given value\".\n   * <p>\n   * Also while the interval is for default closed (inclusive) it's possible to specify open\n   * intervals prefixing the score with a \"(\" character, so for instance:\n   * <p>\n   * {@code ZRANGEBYSCORE zset (1.3 5}\n   * <p>\n   * Will return all the values with score &gt; 1.3 and &lt;= 5, while for instance:\n   * <p>\n   * {@code ZRANGEBYSCORE zset (5 (10}\n   * <p>\n   * Will return all the values with score &gt; 5 and &lt; 10 (5 and 10 excluded).\n   * <p>\n   * <b>Time complexity:</b>\n   * <p>\n   * O(log(N))+O(M) with N being the number of elements in the sorted set and M the number of\n   * elements returned by the command, so if M is constant (for instance you always ask for the\n   * first ten elements with LIMIT) you can consider it O(log(N))\n   * @see #zrangeByScore(byte[], double, double)\n   * @see #zrangeByScore(byte[], double, double, int, int)\n   * @see #zrangeByScoreWithScores(byte[], double, double)\n   * @see #zrangeByScoreWithScores(byte[], double, double, int, int)\n   * @see #zcount(byte[], double, double)\n   * @param key\n   * @param min\n   * @param max\n   * @return Multi bulk reply specifically a list of elements in the specified score range.\n   */\n  @Override\n  public Set<byte[]> zrangeByScore(final byte[] key, final double min, final double max) {\n    return zrangeByScore(key, toByteArray(min), toByteArray(max));\n  }\n\n  @Override\n  public Set<byte[]> zrangeByScore(final byte[] key, final byte[] min, final byte[] max) {\n    checkIsInMultiOrPipeline();\n    client.zrangeByScore(key, min, max);\n    return SetFromList.of(client.getBinaryMultiBulkReply());\n  }\n\n  /**\n   * Return the all the elements in the sorted set at key with a score between min and max\n   * (including elements with score equal to min or max).\n   * <p>\n   * The elements having the same score are returned sorted lexicographically as ASCII strings (this\n   * follows from a property of Redis sorted sets and does not involve further computation).\n   * <p>\n   * Using the optional {@link #zrangeByScore(byte[], double, double, int, int) LIMIT} it's possible\n   * to get only a range of the matching elements in an SQL-alike way. Note that if offset is large\n   * the commands needs to traverse the list for offset elements and this adds up to the O(M)\n   * figure.\n   * <p>\n   * The {@link #zcount(byte[], double, double) ZCOUNT} command is similar to\n   * {@link #zrangeByScore(byte[], double, double) ZRANGEBYSCORE} but instead of returning the\n   * actual elements in the specified interval, it just returns the number of matching elements.\n   * <p>\n   * <b>Exclusive intervals and infinity</b>\n   * <p>\n   * min and max can be -inf and +inf, so that you are not required to know what's the greatest or\n   * smallest element in order to take, for instance, elements \"up to a given value\".\n   * <p>\n   * Also while the interval is for default closed (inclusive) it's possible to specify open\n   * intervals prefixing the score with a \"(\" character, so for instance:\n   * <p>\n   * {@code ZRANGEBYSCORE zset (1.3 5}\n   * <p>\n   * Will return all the values with score &gt; 1.3 and &lt;= 5, while for instance:\n   * <p>\n   * {@code ZRANGEBYSCORE zset (5 (10}\n   * <p>\n   * Will return all the values with score &gt; 5 and &lt; 10 (5 and 10 excluded).\n   * <p>\n   * <b>Time complexity:</b>\n   * <p>\n   * O(log(N))+O(M) with N being the number of elements in the sorted set and M the number of\n   * elements returned by the command, so if M is constant (for instance you always ask for the\n   * first ten elements with LIMIT) you can consider it O(log(N))\n   * @see #zrangeByScore(byte[], double, double)\n   * @see #zrangeByScore(byte[], double, double, int, int)\n   * @see #zrangeByScoreWithScores(byte[], double, double)\n   * @see #zrangeByScoreWithScores(byte[], double, double, int, int)\n   * @see #zcount(byte[], double, double)\n   * @param key\n   * @param min\n   * @param max\n   * @return Multi bulk reply specifically a list of elements in the specified score range.\n   */\n  @Override\n  public Set<byte[]> zrangeByScore(final byte[] key, final double min, final double max,\n      final int offset, final int count) {\n    return zrangeByScore(key, toByteArray(min), toByteArray(max), offset, count);\n  }\n\n  @Override\n  public Set<byte[]> zrangeByScore(final byte[] key, final byte[] min, final byte[] max,\n      final int offset, final int count) {\n    checkIsInMultiOrPipeline();\n    client.zrangeByScore(key, min, max, offset, count);\n    return SetFromList.of(client.getBinaryMultiBulkReply());\n  }\n\n  /**\n   * Return the all the elements in the sorted set at key with a score between min and max\n   * (including elements with score equal to min or max).\n   * <p>\n   * The elements having the same score are returned sorted lexicographically as ASCII strings (this\n   * follows from a property of Redis sorted sets and does not involve further computation).\n   * <p>\n   * Using the optional {@link #zrangeByScore(byte[], double, double, int, int) LIMIT} it's possible\n   * to get only a range of the matching elements in an SQL-alike way. Note that if offset is large\n   * the commands needs to traverse the list for offset elements and this adds up to the O(M)\n   * figure.\n   * <p>\n   * The {@link #zcount(byte[], double, double) ZCOUNT} command is similar to\n   * {@link #zrangeByScore(byte[], double, double) ZRANGEBYSCORE} but instead of returning the\n   * actual elements in the specified interval, it just returns the number of matching elements.\n   * <p>\n   * <b>Exclusive intervals and infinity</b>\n   * <p>\n   * min and max can be -inf and +inf, so that you are not required to know what's the greatest or\n   * smallest element in order to take, for instance, elements \"up to a given value\".\n   * <p>\n   * Also while the interval is for default closed (inclusive) it's possible to specify open\n   * intervals prefixing the score with a \"(\" character, so for instance:\n   * <p>\n   * {@code ZRANGEBYSCORE zset (1.3 5}\n   * <p>\n   * Will return all the values with score &gt; 1.3 and &lt;= 5, while for instance:\n   * <p>\n   * {@code ZRANGEBYSCORE zset (5 (10}\n   * <p>\n   * Will return all the values with score &gt; 5 and &lt; 10 (5 and 10 excluded).\n   * <p>\n   * <b>Time complexity:</b>\n   * <p>\n   * O(log(N))+O(M) with N being the number of elements in the sorted set and M the number of\n   * elements returned by the command, so if M is constant (for instance you always ask for the\n   * first ten elements with LIMIT) you can consider it O(log(N))\n   * @see #zrangeByScore(byte[], double, double)\n   * @see #zrangeByScore(byte[], double, double, int, int)\n   * @see #zrangeByScoreWithScores(byte[], double, double)\n   * @see #zrangeByScoreWithScores(byte[], double, double, int, int)\n   * @see #zcount(byte[], double, double)\n   * @param key\n   * @param min\n   * @param max\n   * @return Multi bulk reply specifically a list of elements in the specified score range.\n   */\n  @Override\n  public Set<Tuple> zrangeByScoreWithScores(final byte[] key, final double min, final double max) {\n    return zrangeByScoreWithScores(key, toByteArray(min), toByteArray(max));\n  }\n\n  @Override\n  public Set<Tuple> zrangeByScoreWithScores(final byte[] key, final byte[] min, final byte[] max) {\n    checkIsInMultiOrPipeline();\n    client.zrangeByScoreWithScores(key, min, max);\n    return getBinaryTupledSet();\n  }\n\n  /**\n   * Return the all the elements in the sorted set at key with a score between min and max\n   * (including elements with score equal to min or max).\n   * <p>\n   * The elements having the same score are returned sorted lexicographically as ASCII strings (this\n   * follows from a property of Redis sorted sets and does not involve further computation).\n   * <p>\n   * Using the optional {@link #zrangeByScore(byte[], double, double, int, int) LIMIT} it's possible\n   * to get only a range of the matching elements in an SQL-alike way. Note that if offset is large\n   * the commands needs to traverse the list for offset elements and this adds up to the O(M)\n   * figure.\n   * <p>\n   * The {@link #zcount(byte[], double, double) ZCOUNT} command is similar to\n   * {@link #zrangeByScore(byte[], double, double) ZRANGEBYSCORE} but instead of returning the\n   * actual elements in the specified interval, it just returns the number of matching elements.\n   * <p>\n   * <b>Exclusive intervals and infinity</b>\n   * <p>\n   * min and max can be -inf and +inf, so that you are not required to know what's the greatest or\n   * smallest element in order to take, for instance, elements \"up to a given value\".\n   * <p>\n   * Also while the interval is for default closed (inclusive) it's possible to specify open\n   * intervals prefixing the score with a \"(\" character, so for instance:\n   * <p>\n   * {@code ZRANGEBYSCORE zset (1.3 5}\n   * <p>\n   * Will return all the values with score &gt; 1.3 and &lt;= 5, while for instance:\n   * <p>\n   * {@code ZRANGEBYSCORE zset (5 (10}\n   * <p>\n   * Will return all the values with score &gt; 5 and &lt; 10 (5 and 10 excluded).\n   * <p>\n   * <b>Time complexity:</b>\n   * <p>\n   * O(log(N))+O(M) with N being the number of elements in the sorted set and M the number of\n   * elements returned by the command, so if M is constant (for instance you always ask for the\n   * first ten elements with LIMIT) you can consider it O(log(N))\n   * @see #zrangeByScore(byte[], double, double)\n   * @see #zrangeByScore(byte[], double, double, int, int)\n   * @see #zrangeByScoreWithScores(byte[], double, double)\n   * @see #zrangeByScoreWithScores(byte[], double, double, int, int)\n   * @see #zcount(byte[], double, double)\n   * @param key\n   * @param min\n   * @param max\n   * @return Multi bulk reply specifically a list of elements in the specified score range.\n   */\n  @Override\n  public Set<Tuple> zrangeByScoreWithScores(final byte[] key, final double min, final double max,\n      final int offset, final int count) {\n    return zrangeByScoreWithScores(key, toByteArray(min), toByteArray(max), offset, count);\n  }\n\n  @Override\n  public Set<Tuple> zrangeByScoreWithScores(final byte[] key, final byte[] min, final byte[] max,\n      final int offset, final int count) {\n    checkIsInMultiOrPipeline();\n    client.zrangeByScoreWithScores(key, min, max, offset, count);\n    return getBinaryTupledSet();\n  }\n\n  private Set<Tuple> getBinaryTupledSet() {\n    checkIsInMultiOrPipeline();\n    List<byte[]> membersWithScores = client.getBinaryMultiBulkReply();\n    if (membersWithScores.size() == 0) {\n      return Collections.emptySet();\n    }\n    Set<Tuple> set = new LinkedHashSet<Tuple>(membersWithScores.size() / 2, 1.0f);\n    Iterator<byte[]> iterator = membersWithScores.iterator();\n    while (iterator.hasNext()) {\n      set.add(new Tuple(iterator.next(), Double.valueOf(SafeEncoder.encode(iterator.next()))));\n    }\n    return set;\n  }\n\n  @Override\n  public Set<byte[]> zrevrangeByScore(final byte[] key, final double max, final double min) {\n    return zrevrangeByScore(key, toByteArray(max), toByteArray(min));\n  }\n\n  @Override\n  public Set<byte[]> zrevrangeByScore(final byte[] key, final byte[] max, final byte[] min) {\n    checkIsInMultiOrPipeline();\n    client.zrevrangeByScore(key, max, min);\n    return SetFromList.of(client.getBinaryMultiBulkReply());\n  }\n\n  @Override\n  public Set<byte[]> zrevrangeByScore(final byte[] key, final double max, final double min,\n      final int offset, final int count) {\n    return zrevrangeByScore(key, toByteArray(max), toByteArray(min), offset, count);\n  }\n\n  @Override\n  public Set<byte[]> zrevrangeByScore(final byte[] key, final byte[] max, final byte[] min,\n      final int offset, final int count) {\n    checkIsInMultiOrPipeline();\n    client.zrevrangeByScore(key, max, min, offset, count);\n    return SetFromList.of(client.getBinaryMultiBulkReply());\n  }\n\n  @Override\n  public Set<Tuple> zrevrangeByScoreWithScores(final byte[] key, final double max, final double min) {\n    return zrevrangeByScoreWithScores(key, toByteArray(max), toByteArray(min));\n  }\n\n  @Override\n  public Set<Tuple> zrevrangeByScoreWithScores(final byte[] key, final double max,\n      final double min, final int offset, final int count) {\n    return zrevrangeByScoreWithScores(key, toByteArray(max), toByteArray(min), offset, count);\n  }\n\n  @Override\n  public Set<Tuple> zrevrangeByScoreWithScores(final byte[] key, final byte[] max, final byte[] min) {\n    checkIsInMultiOrPipeline();\n    client.zrevrangeByScoreWithScores(key, max, min);\n    return getBinaryTupledSet();\n  }\n\n  @Override\n  public Set<Tuple> zrevrangeByScoreWithScores(final byte[] key, final byte[] max,\n      final byte[] min, final int offset, final int count) {\n    checkIsInMultiOrPipeline();\n    client.zrevrangeByScoreWithScores(key, max, min, offset, count);\n    return getBinaryTupledSet();\n  }\n\n  /**\n   * Remove all elements in the sorted set at key with rank between start and end. Start and end are\n   * 0-based with rank 0 being the element with the lowest score. Both start and end can be negative\n   * numbers, where they indicate offsets starting at the element with the highest rank. For\n   * example: -1 is the element with the highest score, -2 the element with the second highest score\n   * and so forth.\n   * <p>\n   * <b>Time complexity:</b> O(log(N))+O(M) with N being the number of elements in the sorted set\n   * and M the number of elements removed by the operation\n   */\n  @Override\n  public Long zremrangeByRank(final byte[] key, final long start, final long end) {\n    checkIsInMultiOrPipeline();\n    client.zremrangeByRank(key, start, end);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Remove all the elements in the sorted set at key with a score between min and max (including\n   * elements with score equal to min or max).\n   * <p>\n   * <b>Time complexity:</b>\n   * <p>\n   * O(log(N))+O(M) with N being the number of elements in the sorted set and M the number of\n   * elements removed by the operation\n   * @param key\n   * @param start\n   * @param end\n   * @return Integer reply, specifically the number of elements removed.\n   */\n  @Override\n  public Long zremrangeByScore(final byte[] key, final double start, final double end) {\n    return zremrangeByScore(key, toByteArray(start), toByteArray(end));\n  }\n\n  @Override\n  public Long zremrangeByScore(final byte[] key, final byte[] start, final byte[] end) {\n    checkIsInMultiOrPipeline();\n    client.zremrangeByScore(key, start, end);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Creates a union or intersection of N sorted sets given by keys k1 through kN, and stores it at\n   * dstkey. It is mandatory to provide the number of input keys N, before passing the input keys\n   * and the other (optional) arguments.\n   * <p>\n   * As the terms imply, the {@link #zinterstore(byte[], byte[]...)} ZINTERSTORE} command requires\n   * an element to be present in each of the given inputs to be inserted in the result. The {@link\n   * #zunionstore(byte[], byte[]...)} command inserts all elements across all inputs.\n   * <p>\n   * Using the WEIGHTS option, it is possible to add weight to each input sorted set. This means\n   * that the score of each element in the sorted set is first multiplied by this weight before\n   * being passed to the aggregation. When this option is not given, all weights default to 1.\n   * <p>\n   * With the AGGREGATE option, it's possible to specify how the results of the union or\n   * intersection are aggregated. This option defaults to SUM, where the score of an element is\n   * summed across the inputs where it exists. When this option is set to be either MIN or MAX, the\n   * resulting set will contain the minimum or maximum score of an element across the inputs where\n   * it exists.\n   * <p>\n   * <b>Time complexity:</b> O(N) + O(M log(M)) with N being the sum of the sizes of the input\n   * sorted sets, and M being the number of elements in the resulting sorted set\n   * @see #zunionstore(byte[], byte[]...)\n   * @see #zunionstore(byte[], ZParams, byte[]...)\n   * @see #zinterstore(byte[], byte[]...)\n   * @see #zinterstore(byte[], ZParams, byte[]...)\n   * @param dstkey\n   * @param sets\n   * @return Integer reply, specifically the number of elements in the sorted set at dstkey\n   */\n  @Override\n  public Long zunionstore(final byte[] dstkey, final byte[]... sets) {\n    checkIsInMultiOrPipeline();\n    client.zunionstore(dstkey, sets);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Creates a union or intersection of N sorted sets given by keys k1 through kN, and stores it at\n   * dstkey. It is mandatory to provide the number of input keys N, before passing the input keys\n   * and the other (optional) arguments.\n   * <p>\n   * As the terms imply, the {@link #zinterstore(byte[], byte[]...) ZINTERSTORE} command requires an\n   * element to be present in each of the given inputs to be inserted in the result. The {@link\n   * #zunionstore(byte[], byte[]...) ZUNIONSTORE} command inserts all elements across all inputs.\n   * <p>\n   * Using the WEIGHTS option, it is possible to add weight to each input sorted set. This means\n   * that the score of each element in the sorted set is first multiplied by this weight before\n   * being passed to the aggregation. When this option is not given, all weights default to 1.\n   * <p>\n   * With the AGGREGATE option, it's possible to specify how the results of the union or\n   * intersection are aggregated. This option defaults to SUM, where the score of an element is\n   * summed across the inputs where it exists. When this option is set to be either MIN or MAX, the\n   * resulting set will contain the minimum or maximum score of an element across the inputs where\n   * it exists.\n   * <p>\n   * <b>Time complexity:</b> O(N) + O(M log(M)) with N being the sum of the sizes of the input\n   * sorted sets, and M being the number of elements in the resulting sorted set\n   * @see #zunionstore(byte[], byte[]...)\n   * @see #zunionstore(byte[], ZParams, byte[]...)\n   * @see #zinterstore(byte[], byte[]...)\n   * @see #zinterstore(byte[], ZParams, byte[]...)\n   * @param dstkey\n   * @param sets\n   * @param params\n   * @return Integer reply, specifically the number of elements in the sorted set at dstkey\n   */\n  @Override\n  public Long zunionstore(final byte[] dstkey, final ZParams params, final byte[]... sets) {\n    checkIsInMultiOrPipeline();\n    client.zunionstore(dstkey, params, sets);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Creates a union or intersection of N sorted sets given by keys k1 through kN, and stores it at\n   * dstkey. It is mandatory to provide the number of input keys N, before passing the input keys\n   * and the other (optional) arguments.\n   * <p>\n   * As the terms imply, the {@link #zinterstore(byte[], byte[]...) ZINTERSTORE} command requires an\n   * element to be present in each of the given inputs to be inserted in the result. The {@link\n   * #zunionstore(byte[], byte[]...) ZUNIONSTORE} command inserts all elements across all inputs.\n   * <p>\n   * Using the WEIGHTS option, it is possible to add weight to each input sorted set. This means\n   * that the score of each element in the sorted set is first multiplied by this weight before\n   * being passed to the aggregation. When this option is not given, all weights default to 1.\n   * <p>\n   * With the AGGREGATE option, it's possible to specify how the results of the union or\n   * intersection are aggregated. This option defaults to SUM, where the score of an element is\n   * summed across the inputs where it exists. When this option is set to be either MIN or MAX, the\n   * resulting set will contain the minimum or maximum score of an element across the inputs where\n   * it exists.\n   * <p>\n   * <b>Time complexity:</b> O(N) + O(M log(M)) with N being the sum of the sizes of the input\n   * sorted sets, and M being the number of elements in the resulting sorted set\n   * @see #zunionstore(byte[], byte[]...)\n   * @see #zunionstore(byte[], ZParams, byte[]...)\n   * @see #zinterstore(byte[], byte[]...)\n   * @see #zinterstore(byte[], ZParams, byte[]...)\n   * @param dstkey\n   * @param sets\n   * @return Integer reply, specifically the number of elements in the sorted set at dstkey\n   */\n  @Override\n  public Long zinterstore(final byte[] dstkey, final byte[]... sets) {\n    checkIsInMultiOrPipeline();\n    client.zinterstore(dstkey, sets);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Creates a union or intersection of N sorted sets given by keys k1 through kN, and stores it at\n   * dstkey. It is mandatory to provide the number of input keys N, before passing the input keys\n   * and the other (optional) arguments.\n   * <p>\n   * As the terms imply, the {@link #zinterstore(byte[], byte[]...) ZINTERSTORE} command requires an\n   * element to be present in each of the given inputs to be inserted in the result. The {@link\n   * #zunionstore(byte[], byte[]...) ZUNIONSTORE} command inserts all elements across all inputs.\n   * <p>\n   * Using the WEIGHTS option, it is possible to add weight to each input sorted set. This means\n   * that the score of each element in the sorted set is first multiplied by this weight before\n   * being passed to the aggregation. When this option is not given, all weights default to 1.\n   * <p>\n   * With the AGGREGATE option, it's possible to specify how the results of the union or\n   * intersection are aggregated. This option defaults to SUM, where the score of an element is\n   * summed across the inputs where it exists. When this option is set to be either MIN or MAX, the\n   * resulting set will contain the minimum or maximum score of an element across the inputs where\n   * it exists.\n   * <p>\n   * <b>Time complexity:</b> O(N) + O(M log(M)) with N being the sum of the sizes of the input\n   * sorted sets, and M being the number of elements in the resulting sorted set\n   * @see #zunionstore(byte[], byte[]...)\n   * @see #zunionstore(byte[], ZParams, byte[]...)\n   * @see #zinterstore(byte[], byte[]...)\n   * @see #zinterstore(byte[], ZParams, byte[]...)\n   * @param dstkey\n   * @param sets\n   * @param params\n   * @return Integer reply, specifically the number of elements in the sorted set at dstkey\n   */\n  @Override\n  public Long zinterstore(final byte[] dstkey, final ZParams params, final byte[]... sets) {\n    checkIsInMultiOrPipeline();\n    client.zinterstore(dstkey, params, sets);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public Long zlexcount(final byte[] key, final byte[] min, final byte[] max) {\n    checkIsInMultiOrPipeline();\n    client.zlexcount(key, min, max);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public Set<byte[]> zrangeByLex(final byte[] key, final byte[] min, final byte[] max) {\n    checkIsInMultiOrPipeline();\n    client.zrangeByLex(key, min, max);\n    return SetFromList.of(client.getBinaryMultiBulkReply());\n  }\n\n  @Override\n  public Set<byte[]> zrangeByLex(final byte[] key, final byte[] min, final byte[] max,\n      final int offset, final int count) {\n    checkIsInMultiOrPipeline();\n    client.zrangeByLex(key, min, max, offset, count);\n    return SetFromList.of(client.getBinaryMultiBulkReply());\n  }\n\n  @Override\n  public Set<byte[]> zrevrangeByLex(byte[] key, byte[] max, byte[] min) {\n    checkIsInMultiOrPipeline();\n    client.zrevrangeByLex(key, max, min);\n    return SetFromList.of(client.getBinaryMultiBulkReply());\n  }\n\n  @Override\n  public Set<byte[]> zrevrangeByLex(byte[] key, byte[] max, byte[] min, int offset, int count) {\n    checkIsInMultiOrPipeline();\n    client.zrevrangeByLex(key, max, min, offset, count);\n    return SetFromList.of(client.getBinaryMultiBulkReply());\n  }\n\n  @Override\n  public Long zremrangeByLex(final byte[] key, final byte[] min, final byte[] max) {\n    checkIsInMultiOrPipeline();\n    client.zremrangeByLex(key, min, max);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Synchronously save the DB on disk.\n   * <p>\n   * Save the whole dataset on disk (this means that all the databases are saved, as well as keys\n   * with an EXPIRE set (the expire is preserved). The server hangs while the saving is not\n   * completed, no connection is served in the meanwhile. An OK code is returned when the DB was\n   * fully stored in disk.\n   * <p>\n   * The background variant of this command is {@link #bgsave() BGSAVE} that is able to perform the\n   * saving in the background while the server continues serving other clients.\n   * <p>\n   * @return Status code reply\n   */\n  @Override\n  public String save() {\n    client.save();\n    return client.getStatusCodeReply();\n  }\n\n  /**\n   * Asynchronously save the DB on disk.\n   * <p>\n   * Save the DB in background. The OK code is immediately returned. Redis forks, the parent\n   * continues to server the clients, the child saves the DB on disk then exit. A client my be able\n   * to check if the operation succeeded using the LASTSAVE command.\n   * @return Status code reply\n   */\n  @Override\n  public String bgsave() {\n    client.bgsave();\n    return client.getStatusCodeReply();\n  }\n\n  /**\n   * Rewrite the append only file in background when it gets too big. Please for detailed\n   * information about the Redis Append Only File check the <a\n   * href=\"http://redis.io/topics/persistence#append-only-file\">Append Only File Howto</a>.\n   * <p>\n   * BGREWRITEAOF rewrites the Append Only File in background when it gets too big. The Redis Append\n   * Only File is a Journal, so every operation modifying the dataset is logged in the Append Only\n   * File (and replayed at startup). This means that the Append Only File always grows. In order to\n   * rebuild its content the BGREWRITEAOF creates a new version of the append only file starting\n   * directly form the dataset in memory in order to guarantee the generation of the minimal number\n   * of commands needed to rebuild the database.\n   * <p>\n   * @return Status code reply\n   */\n  @Override\n  public String bgrewriteaof() {\n    client.bgrewriteaof();\n    return client.getStatusCodeReply();\n  }\n\n  /**\n   * Return the UNIX time stamp of the last successfully saving of the dataset on disk.\n   * <p>\n   * Return the UNIX TIME of the last DB save executed with success. A client may check if a\n   * {@link #bgsave() BGSAVE} command succeeded reading the LASTSAVE value, then issuing a BGSAVE\n   * command and checking at regular intervals every N seconds if LASTSAVE changed.\n   * @return Integer reply, specifically an UNIX time stamp.\n   */\n  @Override\n  public Long lastsave() {\n    client.lastsave();\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Synchronously save the DB on disk, then shutdown the server.\n   * <p>\n   * Stop all the clients, save the DB, then quit the server. This commands makes sure that the DB\n   * is switched off without the lost of any data. This is not guaranteed if the client uses simply\n   * {@link #save() SAVE} and then {@link #quit() QUIT} because other clients may alter the DB data\n   * between the two commands.\n   * @return Status code reply on error. On success nothing is returned since the server quits and\n   *         the connection is closed.\n   */\n  @Override\n  public String shutdown() {\n    client.shutdown();\n    String status;\n    try {\n      status = client.getStatusCodeReply();\n    } catch (JedisException ex) {\n      status = null;\n    }\n    return status;\n  }\n\n  /**\n   * Provide information and statistics about the server.\n   * <p>\n   * The info command returns different information and statistics about the server in an format\n   * that's simple to parse by computers and easy to read by humans.\n   * <p>\n   * <b>Format of the returned String:</b>\n   * <p>\n   * All the fields are in the form field:value\n   * \n   * <pre>\n   * edis_version:0.07\n   * connected_clients:1\n   * connected_slaves:0\n   * used_memory:3187\n   * changes_since_last_save:0\n   * last_save_time:1237655729\n   * total_connections_received:1\n   * total_commands_processed:1\n   * uptime_in_seconds:25\n   * uptime_in_days:0\n   * </pre>\n   * \n   * <b>Notes</b>\n   * <p>\n   * used_memory is returned in bytes, and is the total number of bytes allocated by the program\n   * using malloc.\n   * <p>\n   * uptime_in_days is redundant since the uptime in seconds contains already the full uptime\n   * information, this field is only mainly present for humans.\n   * <p>\n   * changes_since_last_save does not refer to the number of key changes, but to the number of\n   * operations that produced some kind of change in the dataset.\n   * <p>\n   * @return Bulk reply\n   */\n  @Override\n  public String info() {\n    client.info();\n    return client.getBulkReply();\n  }\n\n  @Override\n  public String info(final String section) {\n    client.info(section);\n    return client.getBulkReply();\n  }\n\n  /**\n   * Dump all the received requests in real time.\n   * <p>\n   * MONITOR is a debugging command that outputs the whole sequence of commands received by the\n   * Redis server. is very handy in order to understand what is happening into the database. This\n   * command is used directly via telnet.\n   * @param jedisMonitor\n   */\n  public void monitor(final JedisMonitor jedisMonitor) {\n    client.monitor();\n    client.getStatusCodeReply();\n    jedisMonitor.proceed(client);\n  }\n\n  /**\n   * Change the replication settings.\n   * <p>\n   * The SLAVEOF command can change the replication settings of a slave on the fly. If a Redis\n   * server is arleady acting as slave, the command SLAVEOF NO ONE will turn off the replicaiton\n   * turning the Redis server into a MASTER. In the proper form SLAVEOF hostname port will make the\n   * server a slave of the specific server listening at the specified hostname and port.\n   * <p>\n   * If a server is already a slave of some master, SLAVEOF hostname port will stop the replication\n   * against the old server and start the synchrnonization against the new one discarding the old\n   * dataset.\n   * <p>\n   * The form SLAVEOF no one will stop replication turning the server into a MASTER but will not\n   * discard the replication. So if the old master stop working it is possible to turn the slave\n   * into a master and set the application to use the new master in read/write. Later when the other\n   * Redis server will be fixed it can be configured in order to work as slave.\n   * <p>\n   * @param host\n   * @param port\n   * @return Status code reply\n   */\n  @Override\n  public String slaveof(final String host, final int port) {\n    client.slaveof(host, port);\n    return client.getStatusCodeReply();\n  }\n\n  @Override\n  public String slaveofNoOne() {\n    client.slaveofNoOne();\n    return client.getStatusCodeReply();\n  }\n\n  /**\n   * Retrieve the configuration of a running Redis server. Not all the configuration parameters are\n   * supported.\n   * <p>\n   * CONFIG GET returns the current configuration parameters. This sub command only accepts a single\n   * argument, that is glob style pattern. All the configuration parameters matching this parameter\n   * are reported as a list of key-value pairs.\n   * <p>\n   * <b>Example:</b>\n   * \n   * <pre>\n   * $ redis-cli config get '*'\n   * 1. \"dbfilename\"\n   * 2. \"dump.rdb\"\n   * 3. \"requirepass\"\n   * 4. (nil)\n   * 5. \"masterauth\"\n   * 6. (nil)\n   * 7. \"maxmemory\"\n   * 8. \"0\\n\"\n   * 9. \"appendfsync\"\n   * 10. \"everysec\"\n   * 11. \"save\"\n   * 12. \"3600 1 300 100 60 10000\"\n   * \n   * $ redis-cli config get 'm*'\n   * 1. \"masterauth\"\n   * 2. (nil)\n   * 3. \"maxmemory\"\n   * 4. \"0\\n\"\n   * </pre>\n   * @param pattern\n   * @return Bulk reply.\n   */\n  @Override\n  public List<byte[]> configGet(final byte[] pattern) {\n    client.configGet(pattern);\n    return client.getBinaryMultiBulkReply();\n  }\n\n  /**\n   * Reset the stats returned by INFO\n   * @return\n   */\n  @Override\n  public String configResetStat() {\n    client.configResetStat();\n    return client.getStatusCodeReply();\n  }\n\n  /**\n   * Alter the configuration of a running Redis server. Not all the configuration parameters are\n   * supported.\n   * <p>\n   * The list of configuration parameters supported by CONFIG SET can be obtained issuing a\n   * {@link #configGet(byte[]) CONFIG GET *} command.\n   * <p>\n   * The configuration set using CONFIG SET is immediately loaded by the Redis server that will\n   * start acting as specified starting from the next command.\n   * <p>\n   * <b>Parameters value format</b>\n   * <p>\n   * The value of the configuration parameter is the same as the one of the same parameter in the\n   * Redis configuration file, with the following exceptions:\n   * <p>\n   * <ul>\n   * <li>The save paramter is a list of space-separated integers. Every pair of integers specify the\n   * time and number of changes limit to trigger a save. For instance the command CONFIG SET save\n   * \"3600 10 60 10000\" will configure the server to issue a background saving of the RDB file every\n   * 3600 seconds if there are at least 10 changes in the dataset, and every 60 seconds if there are\n   * at least 10000 changes. To completely disable automatic snapshots just set the parameter as an\n   * empty string.\n   * <li>All the integer parameters representing memory are returned and accepted only using bytes\n   * as unit.\n   * </ul>\n   * @param parameter\n   * @param value\n   * @return Status code reply\n   */\n  @Override\n  public byte[] configSet(final byte[] parameter, final byte[] value) {\n    client.configSet(parameter, value);\n    return client.getBinaryBulkReply();\n  }\n\n  public boolean isConnected() {\n    return client.isConnected();\n  }\n\n  @Override\n  public Long strlen(final byte[] key) {\n    client.strlen(key);\n    return client.getIntegerReply();\n  }\n\n  public void sync() {\n    client.sync();\n  }\n\n  @Override\n  public Long lpushx(final byte[] key, final byte[]... string) {\n    client.lpushx(key, string);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Undo a {@link #expire(byte[], int) expire} at turning the expire key into a normal key.\n   * <p>\n   * Time complexity: O(1)\n   * @param key\n   * @return Integer reply, specifically: 1: the key is now persist. 0: the key is not persist (only\n   *         happens when key not set).\n   */\n  @Override\n  public Long persist(final byte[] key) {\n    client.persist(key);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public Long rpushx(final byte[] key, final byte[]... string) {\n    client.rpushx(key, string);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public byte[] echo(final byte[] string) {\n    client.echo(string);\n    return client.getBinaryBulkReply();\n  }\n\n  @Override\n  public Long linsert(final byte[] key, final LIST_POSITION where, final byte[] pivot,\n      final byte[] value) {\n    client.linsert(key, where, pivot, value);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public String debug(final DebugParams params) {\n    client.debug(params);\n    return client.getStatusCodeReply();\n  }\n\n  public Client getClient() {\n    return client;\n  }\n\n  /**\n   * Pop a value from a list, push it to another list and return it; or block until one is available\n   * @param source\n   * @param destination\n   * @param timeout\n   * @return the element\n   */\n  @Override\n  public byte[] brpoplpush(byte[] source, byte[] destination, int timeout) {\n    client.brpoplpush(source, destination, timeout);\n    client.setTimeoutInfinite();\n    try {\n      return client.getBinaryBulkReply();\n    } finally {\n      client.rollbackTimeout();\n    }\n  }\n\n  /**\n   * Sets or clears the bit at offset in the string value stored at key\n   * @param key\n   * @param offset\n   * @param value\n   * @return\n   */\n  @Override\n  public Boolean setbit(byte[] key, long offset, boolean value) {\n    client.setbit(key, offset, value);\n    return client.getIntegerReply() == 1;\n  }\n\n  @Override\n  public Boolean setbit(byte[] key, long offset, byte[] value) {\n    client.setbit(key, offset, value);\n    return client.getIntegerReply() == 1;\n  }\n\n  /**\n   * Returns the bit value at offset in the string value stored at key\n   * @param key\n   * @param offset\n   * @return\n   */\n  @Override\n  public Boolean getbit(byte[] key, long offset) {\n    client.getbit(key, offset);\n    return client.getIntegerReply() == 1;\n  }\n\n  public Long bitpos(final byte[] key, final boolean value) {\n    return bitpos(key, value, new BitPosParams());\n  }\n\n  public Long bitpos(final byte[] key, final boolean value, final BitPosParams params) {\n    client.bitpos(key, value, params);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public Long setrange(byte[] key, long offset, byte[] value) {\n    client.setrange(key, offset, value);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public byte[] getrange(byte[] key, long startOffset, long endOffset) {\n    client.getrange(key, startOffset, endOffset);\n    return client.getBinaryBulkReply();\n  }\n\n  @Override\n  public Long publish(byte[] channel, byte[] message) {\n    client.publish(channel, message);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public void subscribe(BinaryJedisPubSub jedisPubSub, byte[]... channels) {\n    client.setTimeoutInfinite();\n    try {\n      jedisPubSub.proceed(client, channels);\n    } finally {\n      client.rollbackTimeout();\n    }\n  }\n\n  @Override\n  public void psubscribe(BinaryJedisPubSub jedisPubSub, byte[]... patterns) {\n    client.setTimeoutInfinite();\n    try {\n      jedisPubSub.proceedWithPatterns(client, patterns);\n    } finally {\n      client.rollbackTimeout();\n    }\n  }\n\n  @Override\n  public int getDB() {\n    return client.getDB();\n  }\n\n  /**\n   * Evaluates scripts using the Lua interpreter built into Redis starting from version 2.6.0.\n   * <p>\n   * @return Script result\n   */\n  @Override\n  public Object eval(byte[] script, List<byte[]> keys, List<byte[]> args) {\n    return eval(script, toByteArray(keys.size()), getParamsWithBinary(keys, args));\n  }\n\n  protected static byte[][] getParamsWithBinary(List<byte[]> keys, List<byte[]> args) {\n    final int keyCount = keys.size();\n    final int argCount = args.size();\n    byte[][] params = new byte[keyCount + argCount][];\n\n    for (int i = 0; i < keyCount; i++)\n      params[i] = keys.get(i);\n\n    for (int i = 0; i < argCount; i++)\n      params[keyCount + i] = args.get(i);\n\n    return params;\n  }\n\n  @Override\n  public Object eval(byte[] script, byte[] keyCount, byte[]... params) {\n    client.setTimeoutInfinite();\n    try {\n      client.eval(script, keyCount, params);\n      return client.getOne();\n    } finally {\n      client.rollbackTimeout();\n    }\n  }\n\n  @Override\n  public Object eval(byte[] script, int keyCount, byte[]... params) {\n    return eval(script, toByteArray(keyCount), params);\n  }\n\n  @Override\n  public Object eval(byte[] script) {\n    return eval(script, 0);\n  }\n\n  @Override\n  public Object evalsha(byte[] sha1) {\n    return evalsha(sha1, 1);\n  }\n\n  @Override\n  public Object evalsha(byte[] sha1, List<byte[]> keys, List<byte[]> args) {\n    return evalsha(sha1, keys.size(), getParamsWithBinary(keys, args));\n  }\n\n  @Override\n  public Object evalsha(byte[] sha1, int keyCount, byte[]... params) {\n    client.setTimeoutInfinite();\n    try {\n      client.evalsha(sha1, keyCount, params);\n      return client.getOne();\n    } finally {\n      client.rollbackTimeout();\n    }\n  }\n\n  @Override\n  public String scriptFlush() {\n    client.scriptFlush();\n    return client.getStatusCodeReply();\n  }\n\n  public Long scriptExists(byte[] sha1) {\n    byte[][] a = new byte[1][];\n    a[0] = sha1;\n    return scriptExists(a).get(0);\n  }\n\n  @Override\n  public List<Long> scriptExists(byte[]... sha1) {\n    client.scriptExists(sha1);\n    return client.getIntegerMultiBulkReply();\n  }\n\n  @Override\n  public byte[] scriptLoad(byte[] script) {\n    client.scriptLoad(script);\n    return client.getBinaryBulkReply();\n  }\n\n  @Override\n  public String scriptKill() {\n    client.scriptKill();\n    return client.getStatusCodeReply();\n  }\n\n  @Override\n  public String slowlogReset() {\n    client.slowlogReset();\n    return client.getBulkReply();\n  }\n\n  @Override\n  public Long slowlogLen() {\n    client.slowlogLen();\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public List<byte[]> slowlogGetBinary() {\n    client.slowlogGet();\n    return client.getBinaryMultiBulkReply();\n  }\n\n  @Override\n  public List<byte[]> slowlogGetBinary(long entries) {\n    client.slowlogGet(entries);\n    return client.getBinaryMultiBulkReply();\n  }\n\n  @Override\n  public Long objectRefcount(byte[] key) {\n    client.objectRefcount(key);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public byte[] objectEncoding(byte[] key) {\n    client.objectEncoding(key);\n    return client.getBinaryBulkReply();\n  }\n\n  @Override\n  public Long objectIdletime(byte[] key) {\n    client.objectIdletime(key);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public Long bitcount(final byte[] key) {\n    client.bitcount(key);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public Long bitcount(final byte[] key, long start, long end) {\n    client.bitcount(key, start, end);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public Long bitop(BitOP op, final byte[] destKey, byte[]... srcKeys) {\n    client.bitop(op, destKey, srcKeys);\n    return client.getIntegerReply();\n  }\n\n  public byte[] dump(final byte[] key) {\n    checkIsInMultiOrPipeline();\n    client.dump(key);\n    return client.getBinaryBulkReply();\n  }\n\n  public String restore(final byte[] key, final int ttl, final byte[] serializedValue) {\n    checkIsInMultiOrPipeline();\n    client.restore(key, ttl, serializedValue);\n    return client.getStatusCodeReply();\n  }\n\n  /**\n   * Set a timeout on the specified key. After the timeout the key will be automatically deleted by\n   * the server. A key with an associated timeout is said to be volatile in Redis terminology.\n   * <p>\n   * Voltile keys are stored on disk like the other keys, the timeout is persistent too like all the\n   * other aspects of the dataset. Saving a dataset containing expires and stopping the server does\n   * not stop the flow of time as Redis stores on disk the time when the key will no longer be\n   * available as Unix time, and not the remaining milliseconds.\n   * <p>\n   * Since Redis 2.1.3 you can update the value of the timeout of a key already having an expire\n   * set. It is also possible to undo the expire at all turning the key into a normal key using the\n   * {@link #persist(byte[]) PERSIST} command.\n   * <p>\n   * Time complexity: O(1)\n   * @see <ahref=\"http://redis.io/commands/pexpire\">PEXPIRE Command</a>\n   * @param key\n   * @param milliseconds\n   * @return Integer reply, specifically: 1: the timeout was set. 0: the timeout was not set since\n   *         the key already has an associated timeout (this may happen only in Redis versions <\n   *         2.1.3, Redis >= 2.1.3 will happily update the timeout), or the key does not exist.\n   */\n  @Override\n  public Long pexpire(final byte[] key, final long milliseconds) {\n    checkIsInMultiOrPipeline();\n    client.pexpire(key, milliseconds);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public Long pexpireAt(final byte[] key, final long millisecondsTimestamp) {\n    checkIsInMultiOrPipeline();\n    client.pexpireAt(key, millisecondsTimestamp);\n    return client.getIntegerReply();\n  }\n\n  public Long pttl(final byte[] key) {\n    checkIsInMultiOrPipeline();\n    client.pttl(key);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * PSETEX works exactly like {@link #setex(byte[], int, byte[])} with the sole difference that the\n   * expire time is specified in milliseconds instead of seconds. Time complexity: O(1)\n   * @param key\n   * @param milliseconds\n   * @param value\n   * @return Status code reply\n   */\n  public String psetex(final byte[] key, final long milliseconds, final byte[] value) {\n    checkIsInMultiOrPipeline();\n    client.psetex(key, milliseconds, value);\n    return client.getStatusCodeReply();\n  }\n\n  public String clientKill(final byte[] client) {\n    checkIsInMultiOrPipeline();\n    this.client.clientKill(client);\n    return this.client.getStatusCodeReply();\n  }\n\n  public String clientGetname() {\n    checkIsInMultiOrPipeline();\n    client.clientGetname();\n    return client.getBulkReply();\n  }\n\n  public String clientList() {\n    checkIsInMultiOrPipeline();\n    client.clientList();\n    return client.getBulkReply();\n  }\n\n  public String clientSetname(final byte[] name) {\n    checkIsInMultiOrPipeline();\n    client.clientSetname(name);\n    return client.getBulkReply();\n  }\n\n  public List<String> time() {\n    checkIsInMultiOrPipeline();\n    client.time();\n    return client.getMultiBulkReply();\n  }\n\n  public String migrate(final byte[] host, final int port, final byte[] key,\n      final int destinationDb, final int timeout) {\n    checkIsInMultiOrPipeline();\n    client.migrate(host, port, key, destinationDb, timeout);\n    return client.getStatusCodeReply();\n  }\n\n  /**\n   * Syncrhonous replication of Redis as described here: http://antirez.com/news/66 Since Java\n   * Object class has implemented \"wait\" method, we cannot use it, so I had to change the name of\n   * the method. Sorry :S\n   */\n  @Override\n  public Long waitReplicas(int replicas, long timeout) {\n    checkIsInMultiOrPipeline();\n    client.waitReplicas(replicas, timeout);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public Long pfadd(final byte[] key, final byte[]... elements) {\n    checkIsInMultiOrPipeline();\n    client.pfadd(key, elements);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public long pfcount(final byte[] key) {\n    checkIsInMultiOrPipeline();\n    client.pfcount(key);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public String pfmerge(final byte[] destkey, final byte[]... sourcekeys) {\n    checkIsInMultiOrPipeline();\n    client.pfmerge(destkey, sourcekeys);\n    return client.getStatusCodeReply();\n  }\n\n  @Override\n  public Long pfcount(byte[]... keys) {\n    checkIsInMultiOrPipeline();\n    client.pfcount(keys);\n    return client.getIntegerReply();\n  }\n\n  public ScanResult<byte[]> scan(final byte[] cursor) {\n    return scan(cursor, new ScanParams());\n  }\n\n  public ScanResult<byte[]> scan(final byte[] cursor, final ScanParams params) {\n    checkIsInMultiOrPipeline();\n    client.scan(cursor, params);\n    List<Object> result = client.getObjectMultiBulkReply();\n    byte[] newcursor = (byte[]) result.get(0);\n    List<byte[]> rawResults = (List<byte[]>) result.get(1);\n    return new ScanResult<byte[]>(newcursor, rawResults);\n  }\n\n  public ScanResult<Map.Entry<byte[], byte[]>> hscan(final byte[] key, final byte[] cursor) {\n    return hscan(key, cursor, new ScanParams());\n  }\n\n  public ScanResult<Map.Entry<byte[], byte[]>> hscan(final byte[] key, final byte[] cursor,\n      final ScanParams params) {\n    checkIsInMultiOrPipeline();\n    client.hscan(key, cursor, params);\n    List<Object> result = client.getObjectMultiBulkReply();\n    byte[] newcursor = (byte[]) result.get(0);\n    List<Map.Entry<byte[], byte[]>> results = new ArrayList<Map.Entry<byte[], byte[]>>();\n    List<byte[]> rawResults = (List<byte[]>) result.get(1);\n    Iterator<byte[]> iterator = rawResults.iterator();\n    while (iterator.hasNext()) {\n      results.add(new AbstractMap.SimpleEntry<byte[], byte[]>(iterator.next(), iterator.next()));\n    }\n    return new ScanResult<Map.Entry<byte[], byte[]>>(newcursor, results);\n  }\n\n  public ScanResult<byte[]> sscan(final byte[] key, final byte[] cursor) {\n    return sscan(key, cursor, new ScanParams());\n  }\n\n  public ScanResult<byte[]> sscan(final byte[] key, final byte[] cursor, final ScanParams params) {\n    checkIsInMultiOrPipeline();\n    client.sscan(key, cursor, params);\n    List<Object> result = client.getObjectMultiBulkReply();\n    byte[] newcursor = (byte[]) result.get(0);\n    List<byte[]> rawResults = (List<byte[]>) result.get(1);\n    return new ScanResult<byte[]>(newcursor, rawResults);\n  }\n\n  public ScanResult<Tuple> zscan(final byte[] key, final byte[] cursor) {\n    return zscan(key, cursor, new ScanParams());\n  }\n\n  public ScanResult<Tuple> zscan(final byte[] key, final byte[] cursor, final ScanParams params) {\n    checkIsInMultiOrPipeline();\n    client.zscan(key, cursor, params);\n    List<Object> result = client.getObjectMultiBulkReply();\n    byte[] newcursor = (byte[]) result.get(0);\n    List<Tuple> results = new ArrayList<Tuple>();\n    List<byte[]> rawResults = (List<byte[]>) result.get(1);\n    Iterator<byte[]> iterator = rawResults.iterator();\n    while (iterator.hasNext()) {\n      results.add(new Tuple(iterator.next(), Double.valueOf(SafeEncoder.encode(iterator.next()))));\n    }\n    return new ScanResult<Tuple>(newcursor, results);\n  }\n\n  @Override\n  public Long geoadd(byte[] key, double longitude, double latitude, byte[] member) {\n    checkIsInMultiOrPipeline();\n    client.geoadd(key, longitude, latitude, member);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public Long geoadd(byte[] key, Map<byte[], GeoCoordinate> memberCoordinateMap) {\n    checkIsInMultiOrPipeline();\n    client.geoadd(key, memberCoordinateMap);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public Double geodist(byte[] key, byte[] member1, byte[] member2) {\n    checkIsInMultiOrPipeline();\n    client.geodist(key, member1, member2);\n    String dval = client.getBulkReply();\n    return (dval != null ? new Double(dval) : null);\n  }\n\n  @Override\n  public Double geodist(byte[] key, byte[] member1, byte[] member2, GeoUnit unit) {\n    checkIsInMultiOrPipeline();\n    client.geodist(key, member1, member2, unit);\n    String dval = client.getBulkReply();\n    return (dval != null ? new Double(dval) : null);\n  }\n\n  @Override\n  public List<byte[]> geohash(byte[] key, byte[]... members) {\n    checkIsInMultiOrPipeline();\n    client.geohash(key, members);\n    return client.getBinaryMultiBulkReply();\n  }\n\n  @Override\n  public List<GeoCoordinate> geopos(byte[] key, byte[]... members) {\n    checkIsInMultiOrPipeline();\n    client.geopos(key, members);\n    return BuilderFactory.GEO_COORDINATE_LIST.build(client.getObjectMultiBulkReply());\n  }\n\n  @Override\n  public List<GeoRadiusResponse> georadius(byte[] key, double longitude, double latitude,\n      double radius, GeoUnit unit) {\n    checkIsInMultiOrPipeline();\n    client.georadius(key, longitude, latitude, radius, unit);\n    return BuilderFactory.GEORADIUS_WITH_PARAMS_RESULT.build(client.getObjectMultiBulkReply());\n  }\n\n  @Override\n  public List<GeoRadiusResponse> georadius(byte[] key, double longitude, double latitude,\n      double radius, GeoUnit unit, GeoRadiusParam param) {\n    checkIsInMultiOrPipeline();\n    client.georadius(key, longitude, latitude, radius, unit, param);\n    return BuilderFactory.GEORADIUS_WITH_PARAMS_RESULT.build(client.getObjectMultiBulkReply());\n  }\n\n  @Override\n  public List<GeoRadiusResponse> georadiusByMember(byte[] key, byte[] member, double radius,\n      GeoUnit unit) {\n    checkIsInMultiOrPipeline();\n    client.georadiusByMember(key, member, radius, unit);\n    return BuilderFactory.GEORADIUS_WITH_PARAMS_RESULT.build(client.getObjectMultiBulkReply());\n  }\n\n  @Override\n  public List<GeoRadiusResponse> georadiusByMember(byte[] key, byte[] member, double radius,\n      GeoUnit unit, GeoRadiusParam param) {\n    checkIsInMultiOrPipeline();\n    client.georadiusByMember(key, member, radius, unit, param);\n    return BuilderFactory.GEORADIUS_WITH_PARAMS_RESULT.build(client.getObjectMultiBulkReply());\n  }\n\n  /**\n   * A decorator to implement Set from List. Assume that given List do not contains duplicated\n   * values. The resulting set displays the same ordering, concurrency, and performance\n   * characteristics as the backing list. This class should be used only for Redis commands which\n   * return Set result.\n   * @param <E>\n   */\n  protected static class SetFromList<E> extends AbstractSet<E> {\n    private final List<E> list;\n\n    private SetFromList(List<E> list) {\n      if (list == null) {\n        throw new NullPointerException(\"list\");\n      }\n      this.list = list;\n    }\n\n    @Override\n    public void clear() {\n      list.clear();\n    }\n\n    @Override\n    public int size() {\n      return list.size();\n    }\n\n    @Override\n    public boolean isEmpty() {\n      return list.isEmpty();\n    }\n\n    @Override\n    public boolean contains(Object o) {\n      return list.contains(o);\n    }\n\n    @Override\n    public boolean remove(Object o) {\n      return list.remove(o);\n    }\n\n    @Override\n    public boolean add(E e) {\n      return !contains(e) && list.add(e);\n    }\n\n    @Override\n    public Iterator<E> iterator() {\n      return list.iterator();\n    }\n\n    @Override\n    public Object[] toArray() {\n      return list.toArray();\n    }\n\n    @Override\n    public <T> T[] toArray(T[] a) {\n      return list.toArray(a);\n    }\n\n    public String toString() {\n      return list.toString();\n    }\n\n    public int hashCode() {\n      return list.hashCode();\n    }\n\n    public boolean equals(Object o) {\n      if (o == this) {\n        return true;\n      }\n\n      if (!(o instanceof Set)) {\n        return false;\n      }\n\n      Collection<?> c = (Collection<?>) o;\n      if (c.size() != size()) {\n        return false;\n      }\n\n      return containsAll(c);\n    }\n\n    @Override\n    public boolean containsAll(Collection<?> c) {\n      return list.containsAll(c);\n    }\n\n    @Override\n    public boolean removeAll(Collection<?> c) {\n      return list.removeAll(c);\n    }\n\n    @Override\n    public boolean retainAll(Collection<?> c) {\n      return list.retainAll(c);\n    }\n\n    protected static <E> SetFromList<E> of(List<E> list) {\n      return new SetFromList<E>(list);\n    }\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/BinaryJedisCluster.java",
    "content": "package redis.clients.jedis;\n\nimport redis.clients.jedis.commands.BinaryJedisClusterCommands;\nimport redis.clients.jedis.commands.JedisClusterBinaryScriptingCommands;\nimport redis.clients.jedis.commands.MultiKeyBinaryJedisClusterCommands;\nimport redis.clients.jedis.params.geo.GeoRadiusParam;\nimport redis.clients.jedis.params.set.SetParams;\nimport redis.clients.jedis.params.sortedset.ZAddParams;\nimport redis.clients.jedis.params.sortedset.ZIncrByParams;\nimport redis.clients.util.KeyMergeUtil;\nimport redis.clients.util.SafeEncoder;\n\nimport java.io.Closeable;\nimport java.util.Collection;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\nimport org.apache.commons.pool2.impl.GenericObjectPoolConfig;\n\npublic class BinaryJedisCluster implements BinaryJedisClusterCommands,\n    MultiKeyBinaryJedisClusterCommands, JedisClusterBinaryScriptingCommands, Closeable {\n\n  public static final short HASHSLOTS = 16384;\n  protected static final int DEFAULT_TIMEOUT = 2000;\n  protected static final int DEFAULT_MAX_REDIRECTIONS = 5;\n\n  protected int maxRedirections;\n\n  protected JedisClusterConnectionHandler connectionHandler;\n\n  public BinaryJedisCluster(Set<HostAndPort> nodes, int timeout) {\n    this(nodes, timeout, DEFAULT_MAX_REDIRECTIONS, new GenericObjectPoolConfig());\n  }\n\n  public BinaryJedisCluster(Set<HostAndPort> nodes) {\n    this(nodes, DEFAULT_TIMEOUT);\n  }\n\n  public BinaryJedisCluster(Set<HostAndPort> jedisClusterNode, int timeout, int maxRedirections,\n      final GenericObjectPoolConfig poolConfig) {\n    this.connectionHandler = new JedisSlotBasedConnectionHandler(jedisClusterNode, poolConfig,\n        timeout);\n    this.maxRedirections = maxRedirections;\n  }\n\n  public BinaryJedisCluster(Set<HostAndPort> jedisClusterNode, int connectionTimeout,\n      int soTimeout, int maxRedirections, final GenericObjectPoolConfig poolConfig) {\n    this.connectionHandler = new JedisSlotBasedConnectionHandler(jedisClusterNode, poolConfig,\n        connectionTimeout, soTimeout);\n    this.maxRedirections = maxRedirections;\n  }\n\n  @Override\n  public void close() {\n    if (connectionHandler != null) {\n      for (JedisPool pool : connectionHandler.getNodes().values()) {\n        try {\n          if (pool != null) {\n            pool.destroy();\n          }\n        } catch (Exception e) {\n          // pass\n        }\n      }\n    }\n  }\n\n  public Map<String, JedisPool> getClusterNodes() {\n    return connectionHandler.getNodes();\n  }\n\n  @Override\n  public String set(final byte[] key, final byte[] value) {\n    return new JedisClusterCommand<String>(connectionHandler, maxRedirections) {\n      @Override\n      public String execute(Jedis connection) {\n        return connection.set(key, value);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public String set(final byte[] key, final byte[] value, final SetParams params) {\n    return new JedisClusterCommand<String>(connectionHandler, maxRedirections) {\n      @Override\n      public String execute(Jedis connection) {\n        return connection.set(key, value, params);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public byte[] get(final byte[] key) {\n    return new JedisClusterCommand<byte[]>(connectionHandler, maxRedirections) {\n      @Override\n      public byte[] execute(Jedis connection) {\n        return connection.get(key);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long exists(final byte[]... keys) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.exists(keys);\n      }\n    }.runBinary(keys.length, keys);\n  }\n\n  @Override\n  public Boolean exists(final byte[] key) {\n    return new JedisClusterCommand<Boolean>(connectionHandler, maxRedirections) {\n      @Override\n      public Boolean execute(Jedis connection) {\n        return connection.exists(key);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long persist(final byte[] key) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.persist(key);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public String type(final byte[] key) {\n    return new JedisClusterCommand<String>(connectionHandler, maxRedirections) {\n      @Override\n      public String execute(Jedis connection) {\n        return connection.type(key);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long expire(final byte[] key, final int seconds) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.expire(key, seconds);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long pexpire(final byte[] key, final long milliseconds) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.pexpire(key, milliseconds);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long expireAt(final byte[] key, final long unixTime) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.expireAt(key, unixTime);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long pexpireAt(final byte[] key, final long millisecondsTimestamp) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.pexpire(key, millisecondsTimestamp);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long ttl(final byte[] key) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.ttl(key);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Boolean setbit(final byte[] key, final long offset, final boolean value) {\n    return new JedisClusterCommand<Boolean>(connectionHandler, maxRedirections) {\n      @Override\n      public Boolean execute(Jedis connection) {\n        return connection.setbit(key, offset, value);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Boolean setbit(final byte[] key, final long offset, final byte[] value) {\n    return new JedisClusterCommand<Boolean>(connectionHandler, maxRedirections) {\n      @Override\n      public Boolean execute(Jedis connection) {\n        return connection.setbit(key, offset, value);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Boolean getbit(final byte[] key, final long offset) {\n    return new JedisClusterCommand<Boolean>(connectionHandler, maxRedirections) {\n      @Override\n      public Boolean execute(Jedis connection) {\n        return connection.getbit(key, offset);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long setrange(final byte[] key, final long offset, final byte[] value) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.setrange(key, offset, value);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public byte[] getrange(final byte[] key, final long startOffset, final long endOffset) {\n    return new JedisClusterCommand<byte[]>(connectionHandler, maxRedirections) {\n      @Override\n      public byte[] execute(Jedis connection) {\n        return connection.getrange(key, startOffset, endOffset);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public byte[] getSet(final byte[] key, final byte[] value) {\n    return new JedisClusterCommand<byte[]>(connectionHandler, maxRedirections) {\n      @Override\n      public byte[] execute(Jedis connection) {\n        return connection.getSet(key, value);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long setnx(final byte[] key, final byte[] value) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.setnx(key, value);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public String setex(final byte[] key, final int seconds, final byte[] value) {\n    return new JedisClusterCommand<String>(connectionHandler, maxRedirections) {\n      @Override\n      public String execute(Jedis connection) {\n        return connection.setex(key, seconds, value);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long decrBy(final byte[] key, final long integer) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.decrBy(key, integer);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long decr(final byte[] key) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.decr(key);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long incrBy(final byte[] key, final long integer) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.incrBy(key, integer);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Double incrByFloat(final byte[] key, final double value) {\n    return new JedisClusterCommand<Double>(connectionHandler, maxRedirections) {\n      @Override\n      public Double execute(Jedis connection) {\n        return connection.incrByFloat(key, value);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long incr(final byte[] key) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.incr(key);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long append(final byte[] key, final byte[] value) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.append(key, value);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public byte[] substr(final byte[] key, final int start, final int end) {\n    return new JedisClusterCommand<byte[]>(connectionHandler, maxRedirections) {\n      @Override\n      public byte[] execute(Jedis connection) {\n        return connection.substr(key, start, end);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long hset(final byte[] key, final byte[] field, final byte[] value) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.hset(key, field, value);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public byte[] hget(final byte[] key, final byte[] field) {\n    return new JedisClusterCommand<byte[]>(connectionHandler, maxRedirections) {\n      @Override\n      public byte[] execute(Jedis connection) {\n        return connection.hget(key, field);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long hsetnx(final byte[] key, final byte[] field, final byte[] value) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.hsetnx(key, field, value);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public String hmset(final byte[] key, final Map<byte[], byte[]> hash) {\n    return new JedisClusterCommand<String>(connectionHandler, maxRedirections) {\n      @Override\n      public String execute(Jedis connection) {\n        return connection.hmset(key, hash);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public List<byte[]> hmget(final byte[] key, final byte[]... fields) {\n    return new JedisClusterCommand<List<byte[]>>(connectionHandler, maxRedirections) {\n      @Override\n      public List<byte[]> execute(Jedis connection) {\n        return connection.hmget(key, fields);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long hincrBy(final byte[] key, final byte[] field, final long value) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.hincrBy(key, field, value);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Double hincrByFloat(final byte[] key, final byte[] field, final double value) {\n    return new JedisClusterCommand<Double>(connectionHandler, maxRedirections) {\n      @Override\n      public Double execute(Jedis connection) {\n        return connection.hincrByFloat(key, field, value);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Boolean hexists(final byte[] key, final byte[] field) {\n    return new JedisClusterCommand<Boolean>(connectionHandler, maxRedirections) {\n      @Override\n      public Boolean execute(Jedis connection) {\n        return connection.hexists(key, field);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long hdel(final byte[] key, final byte[]... field) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.hdel(key, field);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long hlen(final byte[] key) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.hlen(key);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Set<byte[]> hkeys(final byte[] key) {\n    return new JedisClusterCommand<Set<byte[]>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<byte[]> execute(Jedis connection) {\n        return connection.hkeys(key);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Collection<byte[]> hvals(final byte[] key) {\n    return new JedisClusterCommand<Collection<byte[]>>(connectionHandler, maxRedirections) {\n      @Override\n      public Collection<byte[]> execute(Jedis connection) {\n        return connection.hvals(key);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Map<byte[], byte[]> hgetAll(final byte[] key) {\n    return new JedisClusterCommand<Map<byte[], byte[]>>(connectionHandler, maxRedirections) {\n      @Override\n      public Map<byte[], byte[]> execute(Jedis connection) {\n        return connection.hgetAll(key);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long rpush(final byte[] key, final byte[]... args) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.rpush(key, args);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long lpush(final byte[] key, final byte[]... args) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.lpush(key, args);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long llen(final byte[] key) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.llen(key);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public List<byte[]> lrange(final byte[] key, final long start, final long end) {\n    return new JedisClusterCommand<List<byte[]>>(connectionHandler, maxRedirections) {\n      @Override\n      public List<byte[]> execute(Jedis connection) {\n        return connection.lrange(key, start, end);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public String ltrim(final byte[] key, final long start, final long end) {\n    return new JedisClusterCommand<String>(connectionHandler, maxRedirections) {\n      @Override\n      public String execute(Jedis connection) {\n        return connection.ltrim(key, start, end);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public byte[] lindex(final byte[] key, final long index) {\n    return new JedisClusterCommand<byte[]>(connectionHandler, maxRedirections) {\n      @Override\n      public byte[] execute(Jedis connection) {\n        return connection.lindex(key, index);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public String lset(final byte[] key, final long index, final byte[] value) {\n    return new JedisClusterCommand<String>(connectionHandler, maxRedirections) {\n      @Override\n      public String execute(Jedis connection) {\n        return connection.lset(key, index, value);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long lrem(final byte[] key, final long count, final byte[] value) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.lrem(key, count, value);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public byte[] lpop(final byte[] key) {\n    return new JedisClusterCommand<byte[]>(connectionHandler, maxRedirections) {\n      @Override\n      public byte[] execute(Jedis connection) {\n        return connection.lpop(key);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public byte[] rpop(final byte[] key) {\n    return new JedisClusterCommand<byte[]>(connectionHandler, maxRedirections) {\n      @Override\n      public byte[] execute(Jedis connection) {\n        return connection.rpop(key);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long sadd(final byte[] key, final byte[]... member) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.sadd(key, member);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Set<byte[]> smembers(final byte[] key) {\n    return new JedisClusterCommand<Set<byte[]>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<byte[]> execute(Jedis connection) {\n        return connection.smembers(key);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long srem(final byte[] key, final byte[]... member) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.srem(key, member);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public byte[] spop(final byte[] key) {\n    return new JedisClusterCommand<byte[]>(connectionHandler, maxRedirections) {\n      @Override\n      public byte[] execute(Jedis connection) {\n        return connection.spop(key);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Set<byte[]> spop(final byte[] key, final long count) {\n    return new JedisClusterCommand<Set<byte[]>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<byte[]> execute(Jedis connection) {\n        return connection.spop(key, count);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long scard(final byte[] key) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.scard(key);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Boolean sismember(final byte[] key, final byte[] member) {\n    return new JedisClusterCommand<Boolean>(connectionHandler, maxRedirections) {\n      @Override\n      public Boolean execute(Jedis connection) {\n        return connection.sismember(key, member);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public byte[] srandmember(final byte[] key) {\n    return new JedisClusterCommand<byte[]>(connectionHandler, maxRedirections) {\n      @Override\n      public byte[] execute(Jedis connection) {\n        return connection.srandmember(key);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long strlen(final byte[] key) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.strlen(key);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long zadd(final byte[] key, final double score, final byte[] member) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.zadd(key, score, member);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long zadd(final byte[] key, final double score, final byte[] member,\n      final ZAddParams params) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.zadd(key, score, member, params);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long zadd(final byte[] key, final Map<byte[], Double> scoreMembers) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.zadd(key, scoreMembers);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long zadd(final byte[] key, final Map<byte[], Double> scoreMembers, final ZAddParams params) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.zadd(key, scoreMembers, params);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Set<byte[]> zrange(final byte[] key, final long start, final long end) {\n    return new JedisClusterCommand<Set<byte[]>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<byte[]> execute(Jedis connection) {\n        return connection.zrange(key, start, end);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long zrem(final byte[] key, final byte[]... member) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.zrem(key, member);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Double zincrby(final byte[] key, final double score, final byte[] member) {\n    return new JedisClusterCommand<Double>(connectionHandler, maxRedirections) {\n      @Override\n      public Double execute(Jedis connection) {\n        return connection.zincrby(key, score, member);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Double zincrby(final byte[] key, final double score, final byte[] member,\n      final ZIncrByParams params) {\n    return new JedisClusterCommand<Double>(connectionHandler, maxRedirections) {\n      @Override\n      public Double execute(Jedis connection) {\n        return connection.zincrby(key, score, member, params);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long zrank(final byte[] key, final byte[] member) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.zrank(key, member);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long zrevrank(final byte[] key, final byte[] member) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.zrevrank(key, member);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Set<byte[]> zrevrange(final byte[] key, final long start, final long end) {\n    return new JedisClusterCommand<Set<byte[]>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<byte[]> execute(Jedis connection) {\n        return connection.zrevrange(key, start, end);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Set<Tuple> zrangeWithScores(final byte[] key, final long start, final long end) {\n    return new JedisClusterCommand<Set<Tuple>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<Tuple> execute(Jedis connection) {\n        return connection.zrangeWithScores(key, start, end);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Set<Tuple> zrevrangeWithScores(final byte[] key, final long start, final long end) {\n    return new JedisClusterCommand<Set<Tuple>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<Tuple> execute(Jedis connection) {\n        return connection.zrevrangeWithScores(key, start, end);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long zcard(final byte[] key) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.zcard(key);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Double zscore(final byte[] key, final byte[] member) {\n    return new JedisClusterCommand<Double>(connectionHandler, maxRedirections) {\n      @Override\n      public Double execute(Jedis connection) {\n        return connection.zscore(key, member);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public List<byte[]> sort(final byte[] key) {\n    return new JedisClusterCommand<List<byte[]>>(connectionHandler, maxRedirections) {\n      @Override\n      public List<byte[]> execute(Jedis connection) {\n        return connection.sort(key);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public List<byte[]> sort(final byte[] key, final SortingParams sortingParameters) {\n    return new JedisClusterCommand<List<byte[]>>(connectionHandler, maxRedirections) {\n      @Override\n      public List<byte[]> execute(Jedis connection) {\n        return connection.sort(key, sortingParameters);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long zcount(final byte[] key, final double min, final double max) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.zcount(key, min, max);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long zcount(final byte[] key, final byte[] min, final byte[] max) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.zcount(key, min, max);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Set<byte[]> zrangeByScore(final byte[] key, final double min, final double max) {\n    return new JedisClusterCommand<Set<byte[]>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<byte[]> execute(Jedis connection) {\n        return connection.zrangeByScore(key, min, max);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Set<byte[]> zrangeByScore(final byte[] key, final byte[] min, final byte[] max) {\n    return new JedisClusterCommand<Set<byte[]>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<byte[]> execute(Jedis connection) {\n        return connection.zrangeByScore(key, min, max);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Set<byte[]> zrevrangeByScore(final byte[] key, final double max, final double min) {\n    return new JedisClusterCommand<Set<byte[]>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<byte[]> execute(Jedis connection) {\n        return connection.zrevrangeByScore(key, max, min);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Set<byte[]> zrangeByScore(final byte[] key, final double min, final double max,\n      final int offset, final int count) {\n    return new JedisClusterCommand<Set<byte[]>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<byte[]> execute(Jedis connection) {\n        return connection.zrangeByScore(key, min, max, offset, count);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Set<byte[]> zrevrangeByScore(final byte[] key, final byte[] max, final byte[] min) {\n    return new JedisClusterCommand<Set<byte[]>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<byte[]> execute(Jedis connection) {\n        return connection.zrevrangeByScore(key, max, min);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Set<byte[]> zrangeByScore(final byte[] key, final byte[] min, final byte[] max,\n      final int offset, final int count) {\n    return new JedisClusterCommand<Set<byte[]>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<byte[]> execute(Jedis connection) {\n        return connection.zrangeByScore(key, min, max, offset, count);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Set<byte[]> zrevrangeByScore(final byte[] key, final double max, final double min,\n      final int offset, final int count) {\n    return new JedisClusterCommand<Set<byte[]>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<byte[]> execute(Jedis connection) {\n        return connection.zrevrangeByScore(key, max, min, offset, count);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Set<Tuple> zrangeByScoreWithScores(final byte[] key, final double min, final double max) {\n    return new JedisClusterCommand<Set<Tuple>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<Tuple> execute(Jedis connection) {\n        return connection.zrangeByScoreWithScores(key, min, max);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Set<Tuple> zrevrangeByScoreWithScores(final byte[] key, final double max, final double min) {\n    return new JedisClusterCommand<Set<Tuple>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<Tuple> execute(Jedis connection) {\n        return connection.zrevrangeByScoreWithScores(key, max, min);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Set<Tuple> zrangeByScoreWithScores(final byte[] key, final double min, final double max,\n      final int offset, final int count) {\n    return new JedisClusterCommand<Set<Tuple>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<Tuple> execute(Jedis connection) {\n        return connection.zrangeByScoreWithScores(key, min, max, offset, count);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Set<byte[]> zrevrangeByScore(final byte[] key, final byte[] max, final byte[] min,\n      final int offset, final int count) {\n    return new JedisClusterCommand<Set<byte[]>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<byte[]> execute(Jedis connection) {\n        return connection.zrevrangeByScore(key, max, min, offset, count);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Set<Tuple> zrangeByScoreWithScores(final byte[] key, final byte[] min, final byte[] max) {\n    return new JedisClusterCommand<Set<Tuple>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<Tuple> execute(Jedis connection) {\n        return connection.zrangeByScoreWithScores(key, min, max);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Set<Tuple> zrevrangeByScoreWithScores(final byte[] key, final byte[] max, final byte[] min) {\n    return new JedisClusterCommand<Set<Tuple>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<Tuple> execute(Jedis connection) {\n        return connection.zrevrangeByScoreWithScores(key, max, min);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Set<Tuple> zrangeByScoreWithScores(final byte[] key, final byte[] min, final byte[] max,\n      final int offset, final int count) {\n    return new JedisClusterCommand<Set<Tuple>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<Tuple> execute(Jedis connection) {\n        return connection.zrangeByScoreWithScores(key, min, max, offset, count);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Set<Tuple> zrevrangeByScoreWithScores(final byte[] key, final double max,\n      final double min, final int offset, final int count) {\n    return new JedisClusterCommand<Set<Tuple>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<Tuple> execute(Jedis connection) {\n        return connection.zrevrangeByScoreWithScores(key, max, min, offset, count);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Set<Tuple> zrevrangeByScoreWithScores(final byte[] key, final byte[] max,\n      final byte[] min, final int offset, final int count) {\n    return new JedisClusterCommand<Set<Tuple>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<Tuple> execute(Jedis connection) {\n        return connection.zrevrangeByScoreWithScores(key, max, min, offset, count);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long zremrangeByRank(final byte[] key, final long start, final long end) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.zremrangeByRank(key, start, end);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long zremrangeByScore(final byte[] key, final double start, final double end) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.zremrangeByScore(key, start, end);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long zremrangeByScore(final byte[] key, final byte[] start, final byte[] end) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.zremrangeByScore(key, start, end);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long linsert(final byte[] key, final Client.LIST_POSITION where, final byte[] pivot,\n      final byte[] value) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.linsert(key, where, pivot, value);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long lpushx(final byte[] key, final byte[]... arg) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.lpushx(key, arg);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long rpushx(final byte[] key, final byte[]... arg) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.rpushx(key, arg);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long del(final byte[] key) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.del(key);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public byte[] echo(final byte[] arg) {\n    // note that it'll be run from arbitary node\n    return new JedisClusterCommand<byte[]>(connectionHandler, maxRedirections) {\n      @Override\n      public byte[] execute(Jedis connection) {\n        return connection.echo(arg);\n      }\n    }.runBinary(arg);\n  }\n\n  @Override\n  public Long bitcount(final byte[] key) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.bitcount(key);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long bitcount(final byte[] key, final long start, final long end) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.bitcount(key, start, end);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long pfadd(final byte[] key, final byte[]... elements) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.pfadd(key, elements);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public long pfcount(final byte[] key) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.pfcount(key);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public List<byte[]> srandmember(final byte[] key, final int count) {\n    return new JedisClusterCommand<List<byte[]>>(connectionHandler, maxRedirections) {\n      @Override\n      public List<byte[]> execute(Jedis connection) {\n        return connection.srandmember(key, count);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long zlexcount(final byte[] key, final byte[] min, final byte[] max) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.zlexcount(key, min, max);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Set<byte[]> zrangeByLex(final byte[] key, final byte[] min, final byte[] max) {\n    return new JedisClusterCommand<Set<byte[]>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<byte[]> execute(Jedis connection) {\n        return connection.zrangeByLex(key, min, max);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Set<byte[]> zrangeByLex(final byte[] key, final byte[] min, final byte[] max,\n      final int offset, final int count) {\n    return new JedisClusterCommand<Set<byte[]>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<byte[]> execute(Jedis connection) {\n        return connection.zrangeByLex(key, min, max, offset, count);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Set<byte[]> zrevrangeByLex(final byte[] key, final byte[] max, final byte[] min) {\n    return new JedisClusterCommand<Set<byte[]>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<byte[]> execute(Jedis connection) {\n        return connection.zrangeByLex(key, max, min);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Set<byte[]> zrevrangeByLex(final byte[] key, final byte[] max, final byte[] min,\n      final int offset, final int count) {\n    return new JedisClusterCommand<Set<byte[]>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<byte[]> execute(Jedis connection) {\n        return connection.zrevrangeByLex(key, max, min, offset, count);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long zremrangeByLex(final byte[] key, final byte[] min, final byte[] max) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.zremrangeByLex(key, min, max);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Object eval(final byte[] script, final byte[] keyCount, final byte[]... params) {\n    return new JedisClusterCommand<Object>(connectionHandler, maxRedirections) {\n      @Override\n      public Object execute(Jedis connection) {\n        return connection.eval(script, keyCount, params);\n      }\n    }.runBinary(Integer.parseInt(SafeEncoder.encode(keyCount)), params);\n  }\n\n  @Override\n  public Object eval(final byte[] script, final int keyCount, final byte[]... params) {\n    return new JedisClusterCommand<Object>(connectionHandler, maxRedirections) {\n      @Override\n      public Object execute(Jedis connection) {\n        return connection.eval(script, keyCount, params);\n      }\n    }.runBinary(keyCount, params);\n  }\n\n  @Override\n  public Object eval(final byte[] script, final List<byte[]> keys, final List<byte[]> args) {\n    return new JedisClusterCommand<Object>(connectionHandler, maxRedirections) {\n      @Override\n      public Object execute(Jedis connection) {\n        return connection.eval(script, keys, args);\n      }\n    }.runBinary(keys.size(), keys.toArray(new byte[keys.size()][]));\n  }\n\n  @Override\n  public Object eval(final byte[] script, byte[] key) {\n    return new JedisClusterCommand<Object>(connectionHandler, maxRedirections) {\n      @Override\n      public Object execute(Jedis connection) {\n        return connection.eval(script);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Object evalsha(final byte[] script, byte[] key) {\n    return new JedisClusterCommand<Object>(connectionHandler, maxRedirections) {\n      @Override\n      public Object execute(Jedis connection) {\n        return connection.evalsha(script);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Object evalsha(final byte[] sha1, final List<byte[]> keys, final List<byte[]> args) {\n    return new JedisClusterCommand<Object>(connectionHandler, maxRedirections) {\n      @Override\n      public Object execute(Jedis connection) {\n        return connection.evalsha(sha1, keys, args);\n      }\n    }.runBinary(keys.size(), keys.toArray(new byte[keys.size()][]));\n  }\n\n  @Override\n  public Object evalsha(final byte[] sha1, final int keyCount, final byte[]... params) {\n    return new JedisClusterCommand<Object>(connectionHandler, maxRedirections) {\n      @Override\n      public Object execute(Jedis connection) {\n        return connection.evalsha(sha1, keyCount, params);\n      }\n    }.runBinary(keyCount, params);\n  }\n\n  @Override\n  public List<Long> scriptExists(final byte[] key, final byte[][] sha1) {\n    return new JedisClusterCommand<List<Long>>(connectionHandler, maxRedirections) {\n      @Override\n      public List<Long> execute(Jedis connection) {\n        return connection.scriptExists(sha1);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public byte[] scriptLoad(final byte[] script, final byte[] key) {\n    return new JedisClusterCommand<byte[]>(connectionHandler, maxRedirections) {\n      @Override\n      public byte[] execute(Jedis connection) {\n        return connection.scriptLoad(script);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public String scriptFlush(final byte[] key) {\n    return new JedisClusterCommand<String>(connectionHandler, maxRedirections) {\n      @Override\n      public String execute(Jedis connection) {\n        return connection.scriptFlush();\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public String scriptKill(byte[] key) {\n    return new JedisClusterCommand<String>(connectionHandler, maxRedirections) {\n      @Override\n      public String execute(Jedis connection) {\n        return connection.scriptKill();\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long del(final byte[]... keys) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.del(keys);\n      }\n    }.runBinary(keys.length, keys);\n  }\n\n  @Override\n  public List<byte[]> blpop(final int timeout, final byte[]... keys) {\n    return new JedisClusterCommand<List<byte[]>>(connectionHandler, maxRedirections) {\n      @Override\n      public List<byte[]> execute(Jedis connection) {\n        return connection.blpop(timeout, keys);\n      }\n    }.runBinary(keys.length, keys);\n  }\n\n  @Override\n  public List<byte[]> brpop(final int timeout, final byte[]... keys) {\n    return new JedisClusterCommand<List<byte[]>>(connectionHandler, maxRedirections) {\n      @Override\n      public List<byte[]> execute(Jedis connection) {\n        return connection.brpop(timeout, keys);\n      }\n    }.runBinary(keys.length, keys);\n  }\n\n  @Override\n  public List<byte[]> mget(final byte[]... keys) {\n    return new JedisClusterCommand<List<byte[]>>(connectionHandler, maxRedirections) {\n      @Override\n      public List<byte[]> execute(Jedis connection) {\n        return connection.mget(keys);\n      }\n    }.runBinary(keys.length, keys);\n  }\n\n  @Override\n  public String mset(final byte[]... keysvalues) {\n    byte[][] keys = new byte[keysvalues.length / 2][];\n\n    for (int keyIdx = 0; keyIdx < keys.length; keyIdx++) {\n      keys[keyIdx] = keysvalues[keyIdx * 2];\n    }\n\n    return new JedisClusterCommand<String>(connectionHandler, maxRedirections) {\n      @Override\n      public String execute(Jedis connection) {\n        return connection.mset(keysvalues);\n      }\n    }.runBinary(keys.length, keys);\n  }\n\n  @Override\n  public Long msetnx(final byte[]... keysvalues) {\n    byte[][] keys = new byte[keysvalues.length / 2][];\n\n    for (int keyIdx = 0; keyIdx < keys.length; keyIdx++) {\n      keys[keyIdx] = keysvalues[keyIdx * 2];\n    }\n\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.msetnx(keysvalues);\n      }\n    }.runBinary(keys.length, keys);\n  }\n\n  @Override\n  public String rename(final byte[] oldkey, final byte[] newkey) {\n    return new JedisClusterCommand<String>(connectionHandler, maxRedirections) {\n      @Override\n      public String execute(Jedis connection) {\n        return connection.rename(oldkey, newkey);\n      }\n    }.runBinary(2, oldkey, newkey);\n  }\n\n  @Override\n  public Long renamenx(final byte[] oldkey, final byte[] newkey) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.renamenx(oldkey, newkey);\n      }\n    }.runBinary(2, oldkey, newkey);\n  }\n\n  @Override\n  public byte[] rpoplpush(final byte[] srckey, final byte[] dstkey) {\n    return new JedisClusterCommand<byte[]>(connectionHandler, maxRedirections) {\n      @Override\n      public byte[] execute(Jedis connection) {\n        return connection.rpoplpush(srckey, dstkey);\n      }\n    }.runBinary(2, srckey, dstkey);\n  }\n\n  @Override\n  public Set<byte[]> sdiff(final byte[]... keys) {\n    return new JedisClusterCommand<Set<byte[]>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<byte[]> execute(Jedis connection) {\n        return connection.sdiff(keys);\n      }\n    }.runBinary(keys.length, keys);\n  }\n\n  @Override\n  public Long sdiffstore(final byte[] dstkey, final byte[]... keys) {\n    byte[][] wholeKeys = KeyMergeUtil.merge(dstkey, keys);\n\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.sdiffstore(dstkey, keys);\n      }\n    }.runBinary(wholeKeys.length, wholeKeys);\n  }\n\n  @Override\n  public Set<byte[]> sinter(final byte[]... keys) {\n    return new JedisClusterCommand<Set<byte[]>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<byte[]> execute(Jedis connection) {\n        return connection.sinter(keys);\n      }\n    }.runBinary(keys.length, keys);\n  }\n\n  @Override\n  public Long sinterstore(final byte[] dstkey, final byte[]... keys) {\n    byte[][] wholeKeys = KeyMergeUtil.merge(dstkey, keys);\n\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.sinterstore(dstkey, keys);\n      }\n    }.runBinary(wholeKeys.length, wholeKeys);\n  }\n\n  @Override\n  public Long smove(final byte[] srckey, final byte[] dstkey, final byte[] member) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.smove(srckey, dstkey, member);\n      }\n    }.runBinary(2, srckey, dstkey);\n  }\n\n  @Override\n  public Long sort(final byte[] key, final SortingParams sortingParameters, final byte[] dstkey) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.sort(key, sortingParameters, dstkey);\n      }\n    }.runBinary(2, key, dstkey);\n  }\n\n  @Override\n  public Long sort(final byte[] key, final byte[] dstkey) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.sort(key, dstkey);\n      }\n    }.runBinary(2, key, dstkey);\n  }\n\n  @Override\n  public Set<byte[]> sunion(final byte[]... keys) {\n    return new JedisClusterCommand<Set<byte[]>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<byte[]> execute(Jedis connection) {\n        return connection.sunion(keys);\n      }\n    }.runBinary(keys.length, keys);\n  }\n\n  @Override\n  public Long sunionstore(final byte[] dstkey, final byte[]... keys) {\n    byte[][] wholeKeys = KeyMergeUtil.merge(dstkey, keys);\n\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.sunionstore(dstkey, keys);\n      }\n    }.runBinary(wholeKeys.length, wholeKeys);\n  }\n\n  @Override\n  public Long zinterstore(final byte[] dstkey, final byte[]... sets) {\n    byte[][] wholeKeys = KeyMergeUtil.merge(dstkey, sets);\n\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.zinterstore(dstkey, sets);\n      }\n    }.runBinary(wholeKeys.length, wholeKeys);\n  }\n\n  @Override\n  public Long zinterstore(final byte[] dstkey, final ZParams params, final byte[]... sets) {\n    byte[][] wholeKeys = KeyMergeUtil.merge(dstkey, sets);\n\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.zinterstore(dstkey, params, sets);\n      }\n    }.runBinary(wholeKeys.length, wholeKeys);\n  }\n\n  @Override\n  public Long zunionstore(final byte[] dstkey, final byte[]... sets) {\n    byte[][] wholeKeys = KeyMergeUtil.merge(dstkey, sets);\n\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.zunionstore(dstkey, sets);\n      }\n    }.runBinary(wholeKeys.length, wholeKeys);\n  }\n\n  @Override\n  public Long zunionstore(final byte[] dstkey, final ZParams params, final byte[]... sets) {\n    byte[][] wholeKeys = KeyMergeUtil.merge(dstkey, sets);\n\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.zunionstore(dstkey, params, sets);\n      }\n    }.runBinary(wholeKeys.length, wholeKeys);\n  }\n\n  @Override\n  public byte[] brpoplpush(final byte[] source, final byte[] destination, final int timeout) {\n    return new JedisClusterCommand<byte[]>(connectionHandler, maxRedirections) {\n      @Override\n      public byte[] execute(Jedis connection) {\n        return connection.brpoplpush(source, destination, timeout);\n      }\n    }.runBinary(2, source, destination);\n  }\n\n  @Override\n  public Long publish(final byte[] channel, final byte[] message) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.publish(channel, message);\n      }\n    }.runWithAnyNode();\n  }\n\n  @Override\n  public void subscribe(final BinaryJedisPubSub jedisPubSub, final byte[]... channels) {\n    new JedisClusterCommand<Integer>(connectionHandler, maxRedirections) {\n      @Override\n      public Integer execute(Jedis connection) {\n        connection.subscribe(jedisPubSub, channels);\n        return 0;\n      }\n    }.runWithAnyNode();\n  }\n\n  @Override\n  public void psubscribe(final BinaryJedisPubSub jedisPubSub, final byte[]... patterns) {\n    new JedisClusterCommand<Integer>(connectionHandler, maxRedirections) {\n      @Override\n      public Integer execute(Jedis connection) {\n        connection.subscribe(jedisPubSub, patterns);\n        return 0;\n      }\n    }.runWithAnyNode();\n  }\n\n  @Override\n  public Long bitop(final BitOP op, final byte[] destKey, final byte[]... srcKeys) {\n    byte[][] wholeKeys = KeyMergeUtil.merge(destKey, srcKeys);\n\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.bitop(op, destKey, srcKeys);\n      }\n    }.runBinary(wholeKeys.length, wholeKeys);\n  }\n\n  @Override\n  public String pfmerge(final byte[] destkey, final byte[]... sourcekeys) {\n    byte[][] wholeKeys = KeyMergeUtil.merge(destkey, sourcekeys);\n\n    return new JedisClusterCommand<String>(connectionHandler, maxRedirections) {\n      @Override\n      public String execute(Jedis connection) {\n        return connection.pfmerge(destkey, sourcekeys);\n      }\n    }.runBinary(wholeKeys.length, wholeKeys);\n  }\n\n  @Override\n  public Long pfcount(final byte[]... keys) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.pfcount(keys);\n      }\n    }.runBinary(keys.length, keys);\n  }\n\n  @Override\n  public Long geoadd(final byte[] key, final double longitude, final double latitude,\n      final byte[] member) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.geoadd(key, longitude, latitude, member);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Long geoadd(final byte[] key, final Map<byte[], GeoCoordinate> memberCoordinateMap) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.geoadd(key, memberCoordinateMap);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Double geodist(final byte[] key, final byte[] member1, final byte[] member2) {\n    return new JedisClusterCommand<Double>(connectionHandler, maxRedirections) {\n      @Override\n      public Double execute(Jedis connection) {\n        return connection.geodist(key, member1, member2);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public Double geodist(final byte[] key, final byte[] member1, final byte[] member2,\n      final GeoUnit unit) {\n    return new JedisClusterCommand<Double>(connectionHandler, maxRedirections) {\n      @Override\n      public Double execute(Jedis connection) {\n        return connection.geodist(key, member1, member2, unit);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public List<byte[]> geohash(final byte[] key, final byte[]... members) {\n    return new JedisClusterCommand<List<byte[]>>(connectionHandler, maxRedirections) {\n      @Override\n      public List<byte[]> execute(Jedis connection) {\n        return connection.geohash(key, members);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public List<GeoCoordinate> geopos(final byte[] key, final byte[]... members) {\n    return new JedisClusterCommand<List<GeoCoordinate>>(connectionHandler, maxRedirections) {\n      @Override\n      public List<GeoCoordinate> execute(Jedis connection) {\n        return connection.geopos(key, members);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public List<GeoRadiusResponse> georadius(final byte[] key, final double longitude,\n      final double latitude, final double radius, final GeoUnit unit) {\n    return new JedisClusterCommand<List<GeoRadiusResponse>>(connectionHandler, maxRedirections) {\n      @Override\n      public List<GeoRadiusResponse> execute(Jedis connection) {\n        return connection.georadius(key, longitude, latitude, radius, unit);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public List<GeoRadiusResponse> georadius(final byte[] key, final double longitude,\n      final double latitude, final double radius, final GeoUnit unit, final GeoRadiusParam param) {\n    return new JedisClusterCommand<List<GeoRadiusResponse>>(connectionHandler, maxRedirections) {\n      @Override\n      public List<GeoRadiusResponse> execute(Jedis connection) {\n        return connection.georadius(key, longitude, latitude, radius, unit, param);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public List<GeoRadiusResponse> georadiusByMember(final byte[] key, final byte[] member,\n      final double radius, final GeoUnit unit) {\n    return new JedisClusterCommand<List<GeoRadiusResponse>>(connectionHandler, maxRedirections) {\n      @Override\n      public List<GeoRadiusResponse> execute(Jedis connection) {\n        return connection.georadiusByMember(key, member, radius, unit);\n      }\n    }.runBinary(key);\n  }\n\n  @Override\n  public List<GeoRadiusResponse> georadiusByMember(final byte[] key, final byte[] member,\n      final double radius, final GeoUnit unit, final GeoRadiusParam param) {\n      return new JedisClusterCommand<List<GeoRadiusResponse>>(connectionHandler, maxRedirections) {\n          @Override\n          public List<GeoRadiusResponse> execute(Jedis connection) {\n              return connection.georadiusByMember(key, member, radius, unit, param);\n          }\n      }.runBinary(key);\n  }\n\n  public JedisClusterConnectionHandler getConnectionHandler() {\n      return connectionHandler;\n  }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/BinaryJedisPubSub.java",
    "content": "package redis.clients.jedis;\n\nimport static redis.clients.jedis.Protocol.Keyword.MESSAGE;\nimport static redis.clients.jedis.Protocol.Keyword.PMESSAGE;\nimport static redis.clients.jedis.Protocol.Keyword.PSUBSCRIBE;\nimport static redis.clients.jedis.Protocol.Keyword.PUNSUBSCRIBE;\nimport static redis.clients.jedis.Protocol.Keyword.SUBSCRIBE;\nimport static redis.clients.jedis.Protocol.Keyword.UNSUBSCRIBE;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport redis.clients.jedis.exceptions.JedisException;\n\npublic abstract class BinaryJedisPubSub {\n  private int subscribedChannels = 0;\n  private Client client;\n\n  public void onMessage(byte[] channel, byte[] message) {\n  }\n\n  public void onPMessage(byte[] pattern, byte[] channel, byte[] message) {\n  }\n\n  public void onSubscribe(byte[] channel, int subscribedChannels) {\n  }\n\n  public void onUnsubscribe(byte[] channel, int subscribedChannels) {\n  }\n\n  public void onPUnsubscribe(byte[] pattern, int subscribedChannels) {\n  }\n\n  public void onPSubscribe(byte[] pattern, int subscribedChannels) {\n  }\n\n  public void unsubscribe() {\n    client.unsubscribe();\n    client.flush();\n  }\n\n  public void unsubscribe(byte[]... channels) {\n    client.unsubscribe(channels);\n    client.flush();\n  }\n\n  public void subscribe(byte[]... channels) {\n    client.subscribe(channels);\n    client.flush();\n  }\n\n  public void psubscribe(byte[]... patterns) {\n    client.psubscribe(patterns);\n    client.flush();\n  }\n\n  public void punsubscribe() {\n    client.punsubscribe();\n    client.flush();\n  }\n\n  public void punsubscribe(byte[]... patterns) {\n    client.punsubscribe(patterns);\n    client.flush();\n  }\n\n  public boolean isSubscribed() {\n    return subscribedChannels > 0;\n  }\n\n  public void proceedWithPatterns(Client client, byte[]... patterns) {\n    this.client = client;\n    client.psubscribe(patterns);\n    client.flush();\n    process(client);\n  }\n\n  public void proceed(Client client, byte[]... channels) {\n    this.client = client;\n    client.subscribe(channels);\n    client.flush();\n    process(client);\n  }\n\n  private void process(Client client) {\n    do {\n      List<Object> reply = client.getRawObjectMultiBulkReply();\n      final Object firstObj = reply.get(0);\n      if (!(firstObj instanceof byte[])) {\n        throw new JedisException(\"Unknown message type: \" + firstObj);\n      }\n      final byte[] resp = (byte[]) firstObj;\n      if (Arrays.equals(SUBSCRIBE.raw, resp)) {\n        subscribedChannels = ((Long) reply.get(2)).intValue();\n        final byte[] bchannel = (byte[]) reply.get(1);\n        onSubscribe(bchannel, subscribedChannels);\n      } else if (Arrays.equals(UNSUBSCRIBE.raw, resp)) {\n        subscribedChannels = ((Long) reply.get(2)).intValue();\n        final byte[] bchannel = (byte[]) reply.get(1);\n        onUnsubscribe(bchannel, subscribedChannels);\n      } else if (Arrays.equals(MESSAGE.raw, resp)) {\n        final byte[] bchannel = (byte[]) reply.get(1);\n        final byte[] bmesg = (byte[]) reply.get(2);\n        onMessage(bchannel, bmesg);\n      } else if (Arrays.equals(PMESSAGE.raw, resp)) {\n        final byte[] bpattern = (byte[]) reply.get(1);\n        final byte[] bchannel = (byte[]) reply.get(2);\n        final byte[] bmesg = (byte[]) reply.get(3);\n        onPMessage(bpattern, bchannel, bmesg);\n      } else if (Arrays.equals(PSUBSCRIBE.raw, resp)) {\n        subscribedChannels = ((Long) reply.get(2)).intValue();\n        final byte[] bpattern = (byte[]) reply.get(1);\n        onPSubscribe(bpattern, subscribedChannels);\n      } else if (Arrays.equals(PUNSUBSCRIBE.raw, resp)) {\n        subscribedChannels = ((Long) reply.get(2)).intValue();\n        final byte[] bpattern = (byte[]) reply.get(1);\n        onPUnsubscribe(bpattern, subscribedChannels);\n      } else {\n        throw new JedisException(\"Unknown message type: \" + firstObj);\n      }\n    } while (isSubscribed());\n  }\n\n  public int getSubscribedChannels() {\n    return subscribedChannels;\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/BinaryShardedJedis.java",
    "content": "package redis.clients.jedis;\n\nimport java.util.Collection;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.regex.Pattern;\n\nimport redis.clients.jedis.BinaryClient.LIST_POSITION;\nimport redis.clients.jedis.commands.BinaryJedisCommands;\nimport redis.clients.jedis.exceptions.JedisConnectionException;\nimport redis.clients.jedis.params.geo.GeoRadiusParam;\nimport redis.clients.jedis.params.set.SetParams;\nimport redis.clients.jedis.params.sortedset.ZAddParams;\nimport redis.clients.jedis.params.sortedset.ZIncrByParams;\nimport redis.clients.util.Hashing;\nimport redis.clients.util.Sharded;\n\npublic class BinaryShardedJedis extends Sharded<Jedis, JedisShardInfo> implements\n    BinaryJedisCommands {\n  public BinaryShardedJedis(List<JedisShardInfo> shards) {\n    super(shards);\n  }\n\n  public BinaryShardedJedis(List<JedisShardInfo> shards, Hashing algo) {\n    super(shards, algo);\n  }\n\n  public BinaryShardedJedis(List<JedisShardInfo> shards, Pattern keyTagPattern) {\n    super(shards, keyTagPattern);\n  }\n\n  public BinaryShardedJedis(List<JedisShardInfo> shards, Hashing algo, Pattern keyTagPattern) {\n    super(shards, algo, keyTagPattern);\n  }\n\n  public void disconnect() {\n    for (Jedis jedis : getAllShards()) {\n      try {\n        jedis.quit();\n      } catch (JedisConnectionException e) {\n        // ignore the exception node, so that all other normal nodes can release all connections.\n      }\n      try {\n        jedis.disconnect();\n      } catch (JedisConnectionException e) {\n        // ignore the exception node, so that all other normal nodes can release all connections.\n      }\n    }\n  }\n\n  protected Jedis create(JedisShardInfo shard) {\n    return new Jedis(shard);\n  }\n\n  @Override\n  public String set(byte[] key, byte[] value) {\n    Jedis j = getShard(key);\n    return j.set(key, value);\n  }\n\n  @Override\n  public String set(byte[] key, byte[] value, SetParams params) {\n    Jedis j = getShard(key);\n    return j.set(key, value, params);\n  }\n\n  @Override\n  public byte[] get(byte[] key) {\n    Jedis j = getShard(key);\n    return j.get(key);\n  }\n\n  @Override\n  public Boolean exists(byte[] key) {\n    Jedis j = getShard(key);\n    return j.exists(key);\n  }\n\n  @Override\n  public String type(byte[] key) {\n    Jedis j = getShard(key);\n    return j.type(key);\n  }\n\n  @Override\n  public Long expire(byte[] key, int seconds) {\n    Jedis j = getShard(key);\n    return j.expire(key, seconds);\n  }\n\n  @Override\n  public Long pexpire(byte[] key, final long milliseconds) {\n    Jedis j = getShard(key);\n    return j.pexpire(key, milliseconds);\n  }\n\n  @Override\n  public Long expireAt(byte[] key, long unixTime) {\n    Jedis j = getShard(key);\n    return j.expireAt(key, unixTime);\n  }\n\n  @Override\n  public Long pexpireAt(byte[] key, long millisecondsTimestamp) {\n    Jedis j = getShard(key);\n    return j.pexpireAt(key, millisecondsTimestamp);\n  }\n\n  @Override\n  public Long ttl(byte[] key) {\n    Jedis j = getShard(key);\n    return j.ttl(key);\n  }\n\n  @Override\n  public byte[] getSet(byte[] key, byte[] value) {\n    Jedis j = getShard(key);\n    return j.getSet(key, value);\n  }\n\n  @Override\n  public Long setnx(byte[] key, byte[] value) {\n    Jedis j = getShard(key);\n    return j.setnx(key, value);\n  }\n\n  @Override\n  public String setex(byte[] key, int seconds, byte[] value) {\n    Jedis j = getShard(key);\n    return j.setex(key, seconds, value);\n  }\n\n  @Override\n  public Long decrBy(byte[] key, long integer) {\n    Jedis j = getShard(key);\n    return j.decrBy(key, integer);\n  }\n\n  @Override\n  public Long decr(byte[] key) {\n    Jedis j = getShard(key);\n    return j.decr(key);\n  }\n\n  @Override\n  public Long del(byte[] key) {\n    Jedis j = getShard(key);\n    return j.del(key);\n  }\n\n  @Override\n  public Long incrBy(byte[] key, long integer) {\n    Jedis j = getShard(key);\n    return j.incrBy(key, integer);\n  }\n\n  @Override\n  public Double incrByFloat(byte[] key, double integer) {\n    Jedis j = getShard(key);\n    return j.incrByFloat(key, integer);\n  }\n\n  @Override\n  public Long incr(byte[] key) {\n    Jedis j = getShard(key);\n    return j.incr(key);\n  }\n\n  @Override\n  public Long append(byte[] key, byte[] value) {\n    Jedis j = getShard(key);\n    return j.append(key, value);\n  }\n\n  @Override\n  public byte[] substr(byte[] key, int start, int end) {\n    Jedis j = getShard(key);\n    return j.substr(key, start, end);\n  }\n\n  @Override\n  public Long hset(byte[] key, byte[] field, byte[] value) {\n    Jedis j = getShard(key);\n    return j.hset(key, field, value);\n  }\n\n  @Override\n  public byte[] hget(byte[] key, byte[] field) {\n    Jedis j = getShard(key);\n    return j.hget(key, field);\n  }\n\n  @Override\n  public Long hsetnx(byte[] key, byte[] field, byte[] value) {\n    Jedis j = getShard(key);\n    return j.hsetnx(key, field, value);\n  }\n\n  @Override\n  public String hmset(byte[] key, Map<byte[], byte[]> hash) {\n    Jedis j = getShard(key);\n    return j.hmset(key, hash);\n  }\n\n  @Override\n  public List<byte[]> hmget(byte[] key, byte[]... fields) {\n    Jedis j = getShard(key);\n    return j.hmget(key, fields);\n  }\n\n  @Override\n  public Long hincrBy(byte[] key, byte[] field, long value) {\n    Jedis j = getShard(key);\n    return j.hincrBy(key, field, value);\n  }\n\n  @Override\n  public Double hincrByFloat(byte[] key, byte[] field, double value) {\n    Jedis j = getShard(key);\n    return j.hincrByFloat(key, field, value);\n  }\n\n  @Override\n  public Boolean hexists(byte[] key, byte[] field) {\n    Jedis j = getShard(key);\n    return j.hexists(key, field);\n  }\n\n  @Override\n  public Long hdel(byte[] key, byte[]... fields) {\n    Jedis j = getShard(key);\n    return j.hdel(key, fields);\n  }\n\n  @Override\n  public Long hlen(byte[] key) {\n    Jedis j = getShard(key);\n    return j.hlen(key);\n  }\n\n  @Override\n  public Set<byte[]> hkeys(byte[] key) {\n    Jedis j = getShard(key);\n    return j.hkeys(key);\n  }\n\n  @Override\n  public Collection<byte[]> hvals(byte[] key) {\n    Jedis j = getShard(key);\n    return j.hvals(key);\n  }\n\n  @Override\n  public Map<byte[], byte[]> hgetAll(byte[] key) {\n    Jedis j = getShard(key);\n    return j.hgetAll(key);\n  }\n\n  @Override\n  public Long rpush(byte[] key, byte[]... strings) {\n    Jedis j = getShard(key);\n    return j.rpush(key, strings);\n  }\n\n  @Override\n  public Long lpush(byte[] key, byte[]... strings) {\n    Jedis j = getShard(key);\n    return j.lpush(key, strings);\n  }\n\n  @Override\n  public Long strlen(final byte[] key) {\n    Jedis j = getShard(key);\n    return j.strlen(key);\n  }\n\n  @Override\n  public Long lpushx(byte[] key, byte[]... string) {\n    Jedis j = getShard(key);\n    return j.lpushx(key, string);\n  }\n\n  @Override\n  public Long persist(final byte[] key) {\n    Jedis j = getShard(key);\n    return j.persist(key);\n  }\n\n  @Override\n  public Long rpushx(byte[] key, byte[]... string) {\n    Jedis j = getShard(key);\n    return j.rpushx(key, string);\n  }\n\n  @Override\n  public Long llen(byte[] key) {\n    Jedis j = getShard(key);\n    return j.llen(key);\n  }\n\n  @Override\n  public List<byte[]> lrange(byte[] key, long start, long end) {\n    Jedis j = getShard(key);\n    return j.lrange(key, start, end);\n  }\n\n  @Override\n  public String ltrim(byte[] key, long start, long end) {\n    Jedis j = getShard(key);\n    return j.ltrim(key, start, end);\n  }\n\n  @Override\n  public byte[] lindex(byte[] key, long index) {\n    Jedis j = getShard(key);\n    return j.lindex(key, index);\n  }\n\n  @Override\n  public String lset(byte[] key, long index, byte[] value) {\n    Jedis j = getShard(key);\n    return j.lset(key, index, value);\n  }\n\n  @Override\n  public Long lrem(byte[] key, long count, byte[] value) {\n    Jedis j = getShard(key);\n    return j.lrem(key, count, value);\n  }\n\n  @Override\n  public byte[] lpop(byte[] key) {\n    Jedis j = getShard(key);\n    return j.lpop(key);\n  }\n\n  @Override\n  public byte[] rpop(byte[] key) {\n    Jedis j = getShard(key);\n    return j.rpop(key);\n  }\n\n  @Override\n  public Long sadd(byte[] key, byte[]... members) {\n    Jedis j = getShard(key);\n    return j.sadd(key, members);\n  }\n\n  @Override\n  public Set<byte[]> smembers(byte[] key) {\n    Jedis j = getShard(key);\n    return j.smembers(key);\n  }\n\n  @Override\n  public Long srem(byte[] key, byte[]... members) {\n    Jedis j = getShard(key);\n    return j.srem(key, members);\n  }\n\n  @Override\n  public byte[] spop(byte[] key) {\n    Jedis j = getShard(key);\n    return j.spop(key);\n  }\n\n  @Override\n  public Set<byte[]> spop(byte[] key, long count) {\n    Jedis j = getShard(key);\n    return j.spop(key, count);\n  }\n\n  @Override\n  public Long scard(byte[] key) {\n    Jedis j = getShard(key);\n    return j.scard(key);\n  }\n\n  @Override\n  public Boolean sismember(byte[] key, byte[] member) {\n    Jedis j = getShard(key);\n    return j.sismember(key, member);\n  }\n\n  @Override\n  public byte[] srandmember(byte[] key) {\n    Jedis j = getShard(key);\n    return j.srandmember(key);\n  }\n\n  @Override\n  public List srandmember(byte[] key, int count) {\n    Jedis j = getShard(key);\n    return j.srandmember(key, count);\n  }\n\n  @Override\n  public Long zadd(byte[] key, double score, byte[] member) {\n    Jedis j = getShard(key);\n    return j.zadd(key, score, member);\n  }\n\n  @Override\n  public Long zadd(byte[] key, double score, byte[] member, ZAddParams params) {\n    Jedis j = getShard(key);\n    return j.zadd(key, score, member, params);\n  }\n\n  @Override\n  public Long zadd(byte[] key, Map<byte[], Double> scoreMembers) {\n    Jedis j = getShard(key);\n    return j.zadd(key, scoreMembers);\n  }\n\n  @Override\n  public Long zadd(byte[] key, Map<byte[], Double> scoreMembers, ZAddParams params) {\n    Jedis j = getShard(key);\n    return j.zadd(key, scoreMembers, params);\n  }\n\n  @Override\n  public Set<byte[]> zrange(byte[] key, long start, long end) {\n    Jedis j = getShard(key);\n    return j.zrange(key, start, end);\n  }\n\n  @Override\n  public Long zrem(byte[] key, byte[]... members) {\n    Jedis j = getShard(key);\n    return j.zrem(key, members);\n  }\n\n  @Override\n  public Double zincrby(byte[] key, double score, byte[] member) {\n    Jedis j = getShard(key);\n    return j.zincrby(key, score, member);\n  }\n\n  @Override\n  public Double zincrby(byte[] key, double score, byte[] member, ZIncrByParams params) {\n    Jedis j = getShard(key);\n    return j.zincrby(key, score, member, params);\n  }\n\n  @Override\n  public Long zrank(byte[] key, byte[] member) {\n    Jedis j = getShard(key);\n    return j.zrank(key, member);\n  }\n\n  @Override\n  public Long zrevrank(byte[] key, byte[] member) {\n    Jedis j = getShard(key);\n    return j.zrevrank(key, member);\n  }\n\n  @Override\n  public Set<byte[]> zrevrange(byte[] key, long start, long end) {\n    Jedis j = getShard(key);\n    return j.zrevrange(key, start, end);\n  }\n\n  @Override\n  public Set<Tuple> zrangeWithScores(byte[] key, long start, long end) {\n    Jedis j = getShard(key);\n    return j.zrangeWithScores(key, start, end);\n  }\n\n  @Override\n  public Set<Tuple> zrevrangeWithScores(byte[] key, long start, long end) {\n    Jedis j = getShard(key);\n    return j.zrevrangeWithScores(key, start, end);\n  }\n\n  @Override\n  public Long zcard(byte[] key) {\n    Jedis j = getShard(key);\n    return j.zcard(key);\n  }\n\n  @Override\n  public Double zscore(byte[] key, byte[] member) {\n    Jedis j = getShard(key);\n    return j.zscore(key, member);\n  }\n\n  @Override\n  public List<byte[]> sort(byte[] key) {\n    Jedis j = getShard(key);\n    return j.sort(key);\n  }\n\n  @Override\n  public List<byte[]> sort(byte[] key, SortingParams sortingParameters) {\n    Jedis j = getShard(key);\n    return j.sort(key, sortingParameters);\n  }\n\n  @Override\n  public Long zcount(byte[] key, double min, double max) {\n    Jedis j = getShard(key);\n    return j.zcount(key, min, max);\n  }\n\n  @Override\n  public Long zcount(byte[] key, byte[] min, byte[] max) {\n    Jedis j = getShard(key);\n    return j.zcount(key, min, max);\n  }\n\n  @Override\n  public Set<byte[]> zrangeByScore(byte[] key, double min, double max) {\n    Jedis j = getShard(key);\n    return j.zrangeByScore(key, min, max);\n  }\n\n  @Override\n  public Set<byte[]> zrangeByScore(byte[] key, double min, double max, int offset, int count) {\n    Jedis j = getShard(key);\n    return j.zrangeByScore(key, min, max, offset, count);\n  }\n\n  @Override\n  public Set<Tuple> zrangeByScoreWithScores(byte[] key, double min, double max) {\n    Jedis j = getShard(key);\n    return j.zrangeByScoreWithScores(key, min, max);\n  }\n\n  @Override\n  public Set<Tuple> zrangeByScoreWithScores(byte[] key, double min, double max, int offset,\n      int count) {\n    Jedis j = getShard(key);\n    return j.zrangeByScoreWithScores(key, min, max, offset, count);\n  }\n\n  @Override\n  public Set<byte[]> zrangeByScore(byte[] key, byte[] min, byte[] max) {\n    Jedis j = getShard(key);\n    return j.zrangeByScore(key, min, max);\n  }\n\n  @Override\n  public Set<Tuple> zrangeByScoreWithScores(byte[] key, byte[] min, byte[] max) {\n    Jedis j = getShard(key);\n    return j.zrangeByScoreWithScores(key, min, max);\n  }\n\n  @Override\n  public Set<Tuple> zrangeByScoreWithScores(byte[] key, byte[] min, byte[] max, int offset,\n      int count) {\n    Jedis j = getShard(key);\n    return j.zrangeByScoreWithScores(key, min, max, offset, count);\n  }\n\n  @Override\n  public Set<byte[]> zrangeByScore(byte[] key, byte[] min, byte[] max, int offset, int count) {\n    Jedis j = getShard(key);\n    return j.zrangeByScore(key, min, max, offset, count);\n  }\n\n  @Override\n  public Set<byte[]> zrevrangeByScore(byte[] key, double max, double min) {\n    Jedis j = getShard(key);\n    return j.zrevrangeByScore(key, max, min);\n  }\n\n  @Override\n  public Set<byte[]> zrevrangeByScore(byte[] key, double max, double min, int offset, int count) {\n    Jedis j = getShard(key);\n    return j.zrevrangeByScore(key, max, min, offset, count);\n  }\n\n  @Override\n  public Set<Tuple> zrevrangeByScoreWithScores(byte[] key, double max, double min) {\n    Jedis j = getShard(key);\n    return j.zrevrangeByScoreWithScores(key, max, min);\n  }\n\n  @Override\n  public Set<Tuple> zrevrangeByScoreWithScores(byte[] key, double max, double min, int offset,\n      int count) {\n    Jedis j = getShard(key);\n    return j.zrevrangeByScoreWithScores(key, max, min, offset, count);\n  }\n\n  @Override\n  public Set<byte[]> zrevrangeByScore(byte[] key, byte[] max, byte[] min) {\n    Jedis j = getShard(key);\n    return j.zrevrangeByScore(key, max, min);\n  }\n\n  @Override\n  public Set<byte[]> zrevrangeByScore(byte[] key, byte[] max, byte[] min, int offset, int count) {\n    Jedis j = getShard(key);\n    return j.zrevrangeByScore(key, max, min, offset, count);\n  }\n\n  @Override\n  public Set<Tuple> zrevrangeByScoreWithScores(byte[] key, byte[] max, byte[] min) {\n    Jedis j = getShard(key);\n    return j.zrevrangeByScoreWithScores(key, max, min);\n  }\n\n  @Override\n  public Set<Tuple> zrevrangeByScoreWithScores(byte[] key, byte[] max, byte[] min, int offset,\n      int count) {\n    Jedis j = getShard(key);\n    return j.zrevrangeByScoreWithScores(key, max, min, offset, count);\n  }\n\n  @Override\n  public Long zremrangeByRank(byte[] key, long start, long end) {\n    Jedis j = getShard(key);\n    return j.zremrangeByRank(key, start, end);\n  }\n\n  @Override\n  public Long zremrangeByScore(byte[] key, double start, double end) {\n    Jedis j = getShard(key);\n    return j.zremrangeByScore(key, start, end);\n  }\n\n  @Override\n  public Long zremrangeByScore(byte[] key, byte[] start, byte[] end) {\n    Jedis j = getShard(key);\n    return j.zremrangeByScore(key, start, end);\n  }\n\n  @Override\n  public Long zlexcount(final byte[] key, final byte[] min, final byte[] max) {\n    Jedis j = getShard(key);\n    return j.zlexcount(key, min, max);\n  }\n\n  @Override\n  public Set<byte[]> zrangeByLex(final byte[] key, final byte[] min, final byte[] max) {\n    Jedis j = getShard(key);\n    return j.zrangeByLex(key, min, max);\n  }\n\n  @Override\n  public Set<byte[]> zrangeByLex(final byte[] key, final byte[] min, final byte[] max,\n      final int offset, final int count) {\n    Jedis j = getShard(key);\n    return j.zrangeByLex(key, min, max, offset, count);\n  }\n\n  @Override\n  public Set<byte[]> zrevrangeByLex(byte[] key, byte[] max, byte[] min) {\n    Jedis j = getShard(key);\n    return j.zrevrangeByLex(key, max, min);\n  }\n\n  @Override\n  public Set<byte[]> zrevrangeByLex(byte[] key, byte[] max, byte[] min, int offset, int count) {\n    Jedis j = getShard(key);\n    return j.zrevrangeByLex(key, max, min, offset, count);\n  }\n\n  @Override\n  public Long zremrangeByLex(final byte[] key, final byte[] min, final byte[] max) {\n    Jedis j = getShard(key);\n    return j.zremrangeByLex(key, min, max);\n  }\n\n  @Override\n  public Long linsert(byte[] key, LIST_POSITION where, byte[] pivot, byte[] value) {\n    Jedis j = getShard(key);\n    return j.linsert(key, where, pivot, value);\n  }\n\n  public ShardedJedisPipeline pipelined() {\n    ShardedJedisPipeline pipeline = new ShardedJedisPipeline();\n    pipeline.setShardedJedis(this);\n    return pipeline;\n  }\n\n  public Long objectRefcount(byte[] key) {\n    Jedis j = getShard(key);\n    return j.objectRefcount(key);\n  }\n\n  public byte[] objectEncoding(byte[] key) {\n    Jedis j = getShard(key);\n    return j.objectEncoding(key);\n  }\n\n  public Long objectIdletime(byte[] key) {\n    Jedis j = getShard(key);\n    return j.objectIdletime(key);\n  }\n\n  @Override\n  public Boolean setbit(byte[] key, long offset, boolean value) {\n    Jedis j = getShard(key);\n    return j.setbit(key, offset, value);\n  }\n\n  @Override\n  public Boolean setbit(byte[] key, long offset, byte[] value) {\n    Jedis j = getShard(key);\n    return j.setbit(key, offset, value);\n  }\n\n  @Override\n  public Boolean getbit(byte[] key, long offset) {\n    Jedis j = getShard(key);\n    return j.getbit(key, offset);\n  }\n\n  @Override\n  public Long setrange(byte[] key, long offset, byte[] value) {\n    Jedis j = getShard(key);\n    return j.setrange(key, offset, value);\n  }\n\n  @Override\n  public byte[] getrange(byte[] key, long startOffset, long endOffset) {\n    Jedis j = getShard(key);\n    return j.getrange(key, startOffset, endOffset);\n  }\n\n  @Override\n  public Long move(byte[] key, int dbIndex) {\n    Jedis j = getShard(key);\n    return j.move(key, dbIndex);\n  }\n\n  @Override\n  public byte[] echo(byte[] arg) {\n    Jedis j = getShard(arg);\n    return j.echo(arg);\n  }\n\n  public List<byte[]> brpop(byte[] arg) {\n    Jedis j = getShard(arg);\n    return j.brpop(arg);\n  }\n\n  public List<byte[]> blpop(byte[] arg) {\n    Jedis j = getShard(arg);\n    return j.blpop(arg);\n  }\n\n  @Override\n  public Long bitcount(byte[] key) {\n    Jedis j = getShard(key);\n    return j.bitcount(key);\n  }\n\n  @Override\n  public Long bitcount(byte[] key, long start, long end) {\n    Jedis j = getShard(key);\n    return j.bitcount(key, start, end);\n  }\n\n  @Override\n  public Long pfadd(final byte[] key, final byte[]... elements) {\n    Jedis j = getShard(key);\n    return j.pfadd(key, elements);\n  }\n\n  @Override\n  public long pfcount(final byte[] key) {\n    Jedis j = getShard(key);\n    return j.pfcount(key);\n  }\n\n  @Override\n  public Long geoadd(byte[] key, double longitude, double latitude, byte[] member) {\n    Jedis j = getShard(key);\n    return j.geoadd(key, longitude, latitude, member);\n  }\n\n  @Override\n  public Long geoadd(byte[] key, Map<byte[], GeoCoordinate> memberCoordinateMap) {\n    Jedis j = getShard(key);\n    return j.geoadd(key, memberCoordinateMap);\n  }\n\n  @Override\n  public Double geodist(byte[] key, byte[] member1, byte[] member2) {\n    Jedis j = getShard(key);\n    return j.geodist(key, member1, member2);\n  }\n\n  @Override\n  public Double geodist(byte[] key, byte[] member1, byte[] member2, GeoUnit unit) {\n    Jedis j = getShard(key);\n    return j.geodist(key, member1, member2, unit);\n  }\n\n  @Override\n  public List<byte[]> geohash(byte[] key, byte[]... members) {\n    Jedis j = getShard(key);\n    return j.geohash(key, members);\n  }\n\n  @Override\n  public List<GeoCoordinate> geopos(byte[] key, byte[]... members) {\n    Jedis j = getShard(key);\n    return j.geopos(key, members);\n  }\n\n  @Override\n  public List<GeoRadiusResponse> georadius(byte[] key, double longitude, double latitude,\n      double radius, GeoUnit unit) {\n    Jedis j = getShard(key);\n    return j.georadius(key, longitude, latitude, radius, unit);\n  }\n\n  @Override\n  public List<GeoRadiusResponse> georadius(byte[] key, double longitude, double latitude,\n      double radius, GeoUnit unit, GeoRadiusParam param) {\n    Jedis j = getShard(key);\n    return j.georadius(key, longitude, latitude, radius, unit, param);\n  }\n\n  @Override\n  public List<GeoRadiusResponse> georadiusByMember(byte[] key, byte[] member, double radius,\n      GeoUnit unit) {\n    Jedis j = getShard(key);\n    return j.georadiusByMember(key, member, radius, unit);\n  }\n\n  @Override\n  public List<GeoRadiusResponse> georadiusByMember(byte[] key, byte[] member, double radius,\n      GeoUnit unit, GeoRadiusParam param) {\n    Jedis j = getShard(key);\n    return j.georadiusByMember(key, member, radius, unit, param);\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/BitOP.java",
    "content": "package redis.clients.jedis;\n\npublic enum BitOP {\n  AND, OR, XOR, NOT;\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/BitPosParams.java",
    "content": "package redis.clients.jedis;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.List;\n\npublic class BitPosParams {\n  private List<byte[]> params = new ArrayList<byte[]>();\n\n  protected BitPosParams() {\n  }\n\n  public BitPosParams(long start) {\n    params.add(Protocol.toByteArray(start));\n  }\n\n  public BitPosParams(long start, long end) {\n    this(start);\n\n    params.add(Protocol.toByteArray(end));\n  }\n\n  public Collection<byte[]> getParams() {\n    return Collections.unmodifiableCollection(params);\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/Builder.java",
    "content": "package redis.clients.jedis;\n\npublic abstract class Builder<T> {\n  public abstract T build(Object data);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/BuilderFactory.java",
    "content": "package redis.clients.jedis;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.Iterator;\nimport java.util.LinkedHashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\nimport redis.clients.util.JedisByteHashMap;\nimport redis.clients.util.SafeEncoder;\n\npublic class BuilderFactory {\n  public static final Builder<Double> DOUBLE = new Builder<Double>() {\n    @Override\n    public Double build(Object data) {\n      String asString = STRING.build(data);\n      return asString == null ? null : Double.valueOf(asString);\n    }\n\n    public String toString() {\n      return \"double\";\n    }\n  };\n  public static final Builder<Boolean> BOOLEAN = new Builder<Boolean>() {\n    @Override\n    public Boolean build(Object data) {\n      return ((Long) data) == 1;\n    }\n\n    public String toString() {\n      return \"boolean\";\n    }\n  };\n  public static final Builder<byte[]> BYTE_ARRAY = new Builder<byte[]>() {\n    @Override\n    public byte[] build(Object data) {\n      return ((byte[]) data); // deleted == 1\n    }\n\n    public String toString() {\n      return \"byte[]\";\n    }\n  };\n\n  public static final Builder<Long> LONG = new Builder<Long>() {\n    @Override\n    public Long build(Object data) {\n      return (Long) data;\n    }\n\n    public String toString() {\n      return \"long\";\n    }\n\n  };\n  public static final Builder<String> STRING = new Builder<String>() {\n    @Override\n    public String build(Object data) {\n      return data == null ? null : SafeEncoder.encode((byte[]) data);\n    }\n\n    public String toString() {\n      return \"string\";\n    }\n\n  };\n  public static final Builder<List<String>> STRING_LIST = new Builder<List<String>>() {\n    @Override\n    @SuppressWarnings(\"unchecked\")\n    public List<String> build(Object data) {\n      if (null == data) {\n        return null;\n      }\n      List<byte[]> l = (List<byte[]>) data;\n      final ArrayList<String> result = new ArrayList<String>(l.size());\n      for (final byte[] barray : l) {\n        if (barray == null) {\n          result.add(null);\n        } else {\n          result.add(SafeEncoder.encode(barray));\n        }\n      }\n      return result;\n    }\n\n    public String toString() {\n      return \"List<String>\";\n    }\n\n  };\n  public static final Builder<Map<String, String>> STRING_MAP = new Builder<Map<String, String>>() {\n    @Override\n    @SuppressWarnings(\"unchecked\")\n    public Map<String, String> build(Object data) {\n      final List<byte[]> flatHash = (List<byte[]>) data;\n      final Map<String, String> hash = new HashMap<String, String>();\n      final Iterator<byte[]> iterator = flatHash.iterator();\n      while (iterator.hasNext()) {\n        hash.put(SafeEncoder.encode(iterator.next()), SafeEncoder.encode(iterator.next()));\n      }\n\n      return hash;\n    }\n\n    public String toString() {\n      return \"Map<String, String>\";\n    }\n\n  };\n\n  public static final Builder<Map<String, String>> PUBSUB_NUMSUB_MAP = new Builder<Map<String, String>>() {\n    @Override\n    @SuppressWarnings(\"unchecked\")\n    public Map<String, String> build(Object data) {\n      final List<Object> flatHash = (List<Object>) data;\n      final Map<String, String> hash = new HashMap<String, String>();\n      final Iterator<Object> iterator = flatHash.iterator();\n      while (iterator.hasNext()) {\n        hash.put(SafeEncoder.encode((byte[]) iterator.next()),\n          String.valueOf((Long) iterator.next()));\n      }\n\n      return hash;\n    }\n\n    public String toString() {\n      return \"PUBSUB_NUMSUB_MAP<String, String>\";\n    }\n\n  };\n\n  public static final Builder<Set<String>> STRING_SET = new Builder<Set<String>>() {\n    @Override\n    @SuppressWarnings(\"unchecked\")\n    public Set<String> build(Object data) {\n      if (null == data) {\n        return null;\n      }\n      List<byte[]> l = (List<byte[]>) data;\n      final Set<String> result = new HashSet<String>(l.size());\n      for (final byte[] barray : l) {\n        if (barray == null) {\n          result.add(null);\n        } else {\n          result.add(SafeEncoder.encode(barray));\n        }\n      }\n      return result;\n    }\n\n    public String toString() {\n      return \"Set<String>\";\n    }\n\n  };\n\n  public static final Builder<List<byte[]>> BYTE_ARRAY_LIST = new Builder<List<byte[]>>() {\n    @Override\n    @SuppressWarnings(\"unchecked\")\n    public List<byte[]> build(Object data) {\n      if (null == data) {\n        return null;\n      }\n      List<byte[]> l = (List<byte[]>) data;\n\n      return l;\n    }\n\n    public String toString() {\n      return \"List<byte[]>\";\n    }\n  };\n\n  public static final Builder<Set<byte[]>> BYTE_ARRAY_ZSET = new Builder<Set<byte[]>>() {\n    @Override\n    @SuppressWarnings(\"unchecked\")\n    public Set<byte[]> build(Object data) {\n      if (null == data) {\n        return null;\n      }\n      List<byte[]> l = (List<byte[]>) data;\n      final Set<byte[]> result = new LinkedHashSet<byte[]>(l);\n      for (final byte[] barray : l) {\n        if (barray == null) {\n          result.add(null);\n        } else {\n          result.add(barray);\n        }\n      }\n      return result;\n    }\n\n    public String toString() {\n      return \"ZSet<byte[]>\";\n    }\n  };\n  public static final Builder<Map<byte[], byte[]>> BYTE_ARRAY_MAP = new Builder<Map<byte[], byte[]>>() {\n    @Override\n    @SuppressWarnings(\"unchecked\")\n    public Map<byte[], byte[]> build(Object data) {\n      final List<byte[]> flatHash = (List<byte[]>) data;\n      final Map<byte[], byte[]> hash = new JedisByteHashMap();\n      final Iterator<byte[]> iterator = flatHash.iterator();\n      while (iterator.hasNext()) {\n        hash.put(iterator.next(), iterator.next());\n      }\n\n      return hash;\n    }\n\n    public String toString() {\n      return \"Map<byte[], byte[]>\";\n    }\n\n  };\n\n  public static final Builder<Set<String>> STRING_ZSET = new Builder<Set<String>>() {\n    @Override\n    @SuppressWarnings(\"unchecked\")\n    public Set<String> build(Object data) {\n      if (null == data) {\n        return null;\n      }\n      List<byte[]> l = (List<byte[]>) data;\n      final Set<String> result = new LinkedHashSet<String>(l.size());\n      for (final byte[] barray : l) {\n        if (barray == null) {\n          result.add(null);\n        } else {\n          result.add(SafeEncoder.encode(barray));\n        }\n      }\n      return result;\n    }\n\n    public String toString() {\n      return \"ZSet<String>\";\n    }\n\n  };\n\n  public static final Builder<Set<Tuple>> TUPLE_ZSET = new Builder<Set<Tuple>>() {\n    @Override\n    @SuppressWarnings(\"unchecked\")\n    public Set<Tuple> build(Object data) {\n      if (null == data) {\n        return null;\n      }\n      List<byte[]> l = (List<byte[]>) data;\n      final Set<Tuple> result = new LinkedHashSet<Tuple>(l.size());\n      Iterator<byte[]> iterator = l.iterator();\n      while (iterator.hasNext()) {\n        result.add(new Tuple(SafeEncoder.encode(iterator.next()), Double.valueOf(SafeEncoder\n            .encode(iterator.next()))));\n      }\n      return result;\n    }\n\n    public String toString() {\n      return \"ZSet<Tuple>\";\n    }\n\n  };\n\n  public static final Builder<Set<Tuple>> TUPLE_ZSET_BINARY = new Builder<Set<Tuple>>() {\n    @Override\n    @SuppressWarnings(\"unchecked\")\n    public Set<Tuple> build(Object data) {\n      if (null == data) {\n        return null;\n      }\n      List<byte[]> l = (List<byte[]>) data;\n      final Set<Tuple> result = new LinkedHashSet<Tuple>(l.size());\n      Iterator<byte[]> iterator = l.iterator();\n      while (iterator.hasNext()) {\n        result.add(new Tuple(iterator.next(), Double.valueOf(SafeEncoder.encode(iterator.next()))));\n      }\n\n      return result;\n\n    }\n\n    public String toString() {\n      return \"ZSet<Tuple>\";\n    }\n  };\n\n  public static final Builder<Object> EVAL_RESULT = new Builder<Object>() {\n\n    @Override\n    public Object build(Object data) {\n      return evalResult(data);\n    }\n\n    public String toString() {\n      return \"Eval<Object>\";\n    }\n\n    private Object evalResult(Object result) {\n      if (result instanceof byte[]) return SafeEncoder.encode((byte[]) result);\n\n      if (result instanceof List<?>) {\n        List<?> list = (List<?>) result;\n        List<Object> listResult = new ArrayList<Object>(list.size());\n        for (Object bin : list) {\n          listResult.add(evalResult(bin));\n        }\n\n        return listResult;\n      }\n\n      return result;\n    }\n\n  };\n\n  public static final Builder<Object> EVAL_BINARY_RESULT = new Builder<Object>() {\n\n    @Override\n    public Object build(Object data) {\n      return evalResult(data);\n    }\n\n    public String toString() {\n      return \"Eval<Object>\";\n    }\n\n    private Object evalResult(Object result) {\n      if (result instanceof List<?>) {\n        List<?> list = (List<?>) result;\n        List<Object> listResult = new ArrayList<Object>(list.size());\n        for (Object bin : list) {\n          listResult.add(evalResult(bin));\n        }\n\n        return listResult;\n      }\n\n      return result;\n    }\n\n  };\n\n  public static final Builder<List<GeoCoordinate>> GEO_COORDINATE_LIST = new Builder<List<GeoCoordinate>>() {\n    @Override\n    public List<GeoCoordinate> build(Object data) {\n      if (null == data) {\n        return null;\n      }\n      return interpretGeoposResult((List<Object>) data);\n    }\n\n    public String toString() {\n      return \"List<GeoCoordinate>\";\n    }\n\n    private List<GeoCoordinate> interpretGeoposResult(List<Object> responses) {\n      List<GeoCoordinate> responseCoordinate = new ArrayList<GeoCoordinate>(responses.size());\n      for (Object response : responses) {\n        if (response == null) {\n          responseCoordinate.add(null);\n        } else {\n          List<Object> respList = (List<Object>) response;\n          GeoCoordinate coord = new GeoCoordinate(Double.parseDouble(SafeEncoder\n              .encode((byte[]) respList.get(0))), Double.parseDouble(SafeEncoder\n              .encode((byte[]) respList.get(1))));\n          responseCoordinate.add(coord);\n        }\n      }\n      return responseCoordinate;\n    }\n  };\n\n  public static final Builder<List<GeoRadiusResponse>> GEORADIUS_WITH_PARAMS_RESULT = new Builder<List<GeoRadiusResponse>>() {\n    @Override\n    public List<GeoRadiusResponse> build(Object data) {\n      if (data == null) {\n        return null;\n      } else {\n        List<Object> objectList = (List<Object>) data;\n\n        if (objectList.size() == 0) {\n          return new ArrayList<GeoRadiusResponse>();\n        }\n\n        List<GeoRadiusResponse> responses = new ArrayList<GeoRadiusResponse>(objectList.size());\n        if (objectList.get(0) instanceof List<?>) {\n          // list of members with additional informations\n          GeoRadiusResponse resp;\n          for (Object obj : objectList) {\n            List<Object> informations = (List<Object>) obj;\n\n            resp = new GeoRadiusResponse((byte[]) informations.get(0));\n\n            int size = informations.size();\n            for (int idx = 1; idx < size; idx++) {\n              Object info = informations.get(idx);\n              if (info instanceof List<?>) {\n                // coordinate\n                List<Object> coord = (List<Object>) info;\n\n                resp.setCoordinate(new GeoCoordinate(convertByteArrayToDouble(coord.get(0)),\n                    convertByteArrayToDouble(coord.get(1))));\n              } else {\n                // distance\n                resp.setDistance(convertByteArrayToDouble(info));\n              }\n            }\n\n            responses.add(resp);\n          }\n        } else {\n          // list of members\n          for (Object obj : objectList) {\n            responses.add(new GeoRadiusResponse((byte[]) obj));\n          }\n        }\n\n        return responses;\n      }\n    }\n\n    private Double convertByteArrayToDouble(Object obj) {\n      return Double.valueOf(SafeEncoder.encode((byte[]) obj));\n    }\n\n    public String toString() {\n      return \"GeoRadiusWithParamsResult\";\n    }\n  };\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/Client.java",
    "content": "package redis.clients.jedis;\n\nimport static redis.clients.jedis.Protocol.Command.GEORADIUS;\nimport static redis.clients.jedis.Protocol.Command.CONFIG;\nimport static redis.clients.jedis.Protocol.toByteArray;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\n\nimport redis.clients.jedis.JedisCluster.Reset;\nimport redis.clients.jedis.commands.Commands;\nimport redis.clients.jedis.params.geo.GeoRadiusParam;\nimport redis.clients.jedis.params.set.SetParams;\nimport redis.clients.jedis.params.sortedset.ZAddParams;\nimport redis.clients.jedis.params.sortedset.ZIncrByParams;\nimport redis.clients.util.SafeEncoder;\n\npublic class Client extends BinaryClient implements Commands {\n\n  public Client() {\n    super();\n  }\n\n  public Client(final String host) {\n    super(host);\n  }\n\n  public Client(final String host, final int port) {\n    super(host, port);\n  }\n\n  @Override\n  public void set(final String key, final String value) {\n    set(SafeEncoder.encode(key), SafeEncoder.encode(value));\n  }\n\n  @Override\n  public void set(final String key, final String value, final SetParams params) {\n    set(SafeEncoder.encode(key), SafeEncoder.encode(value), params);\n  }\n\n  @Override\n  public void get(final String key) {\n    get(SafeEncoder.encode(key));\n  }\n\n  @Override\n  public void exists(final String key) {\n    exists(SafeEncoder.encode(key));\n  }\n\n  @Override\n  public void exists(final String... keys) {\n    final byte[][] bkeys = SafeEncoder.encodeMany(keys);\n    exists(bkeys);\n  }\n\n  public void del(final String... keys) {\n    final byte[][] bkeys = new byte[keys.length][];\n    for (int i = 0; i < keys.length; i++) {\n      bkeys[i] = SafeEncoder.encode(keys[i]);\n    }\n    del(bkeys);\n  }\n\n  @Override\n  public void type(final String key) {\n    type(SafeEncoder.encode(key));\n  }\n\n  @Override\n  public void keys(final String pattern) {\n    keys(SafeEncoder.encode(pattern));\n  }\n\n  @Override\n  public void rename(final String oldkey, final String newkey) {\n    rename(SafeEncoder.encode(oldkey), SafeEncoder.encode(newkey));\n  }\n\n  @Override\n  public void renamenx(final String oldkey, final String newkey) {\n    renamenx(SafeEncoder.encode(oldkey), SafeEncoder.encode(newkey));\n  }\n\n  @Override\n  public void expire(final String key, final int seconds) {\n    expire(SafeEncoder.encode(key), seconds);\n  }\n\n  @Override\n  public void expireAt(final String key, final long unixTime) {\n    expireAt(SafeEncoder.encode(key), unixTime);\n  }\n\n  @Override\n  public void ttl(final String key) {\n    ttl(SafeEncoder.encode(key));\n  }\n\n  @Override\n  public void move(final String key, final int dbIndex) {\n    move(SafeEncoder.encode(key), dbIndex);\n  }\n\n  @Override\n  public void getSet(final String key, final String value) {\n    getSet(SafeEncoder.encode(key), SafeEncoder.encode(value));\n  }\n\n  @Override\n  public void mget(final String... keys) {\n    final byte[][] bkeys = new byte[keys.length][];\n    for (int i = 0; i < bkeys.length; i++) {\n      bkeys[i] = SafeEncoder.encode(keys[i]);\n    }\n    mget(bkeys);\n  }\n\n  @Override\n  public void setnx(final String key, final String value) {\n    setnx(SafeEncoder.encode(key), SafeEncoder.encode(value));\n  }\n\n  @Override\n  public void setex(final String key, final int seconds, final String value) {\n    setex(SafeEncoder.encode(key), seconds, SafeEncoder.encode(value));\n  }\n\n  @Override\n  public void mset(final String... keysvalues) {\n    final byte[][] bkeysvalues = new byte[keysvalues.length][];\n    for (int i = 0; i < keysvalues.length; i++) {\n      bkeysvalues[i] = SafeEncoder.encode(keysvalues[i]);\n    }\n    mset(bkeysvalues);\n  }\n\n  @Override\n  public void msetnx(final String... keysvalues) {\n    final byte[][] bkeysvalues = new byte[keysvalues.length][];\n    for (int i = 0; i < keysvalues.length; i++) {\n      bkeysvalues[i] = SafeEncoder.encode(keysvalues[i]);\n    }\n    msetnx(bkeysvalues);\n  }\n\n  @Override\n  public void decrBy(final String key, final long integer) {\n    decrBy(SafeEncoder.encode(key), integer);\n  }\n\n  @Override\n  public void decr(final String key) {\n    decr(SafeEncoder.encode(key));\n  }\n\n  @Override\n  public void incrBy(final String key, final long integer) {\n    incrBy(SafeEncoder.encode(key), integer);\n  }\n\n  @Override\n  public void incr(final String key) {\n    incr(SafeEncoder.encode(key));\n  }\n\n  @Override\n  public void append(final String key, final String value) {\n    append(SafeEncoder.encode(key), SafeEncoder.encode(value));\n  }\n\n  @Override\n  public void substr(final String key, final int start, final int end) {\n    substr(SafeEncoder.encode(key), start, end);\n  }\n\n  @Override\n  public void hset(final String key, final String field, final String value) {\n    hset(SafeEncoder.encode(key), SafeEncoder.encode(field), SafeEncoder.encode(value));\n  }\n\n  @Override\n  public void hget(final String key, final String field) {\n    hget(SafeEncoder.encode(key), SafeEncoder.encode(field));\n  }\n\n  @Override\n  public void hsetnx(final String key, final String field, final String value) {\n    hsetnx(SafeEncoder.encode(key), SafeEncoder.encode(field), SafeEncoder.encode(value));\n  }\n\n  @Override\n  public void hmset(final String key, final Map<String, String> hash) {\n    final Map<byte[], byte[]> bhash = new HashMap<byte[], byte[]>(hash.size());\n    for (final Entry<String, String> entry : hash.entrySet()) {\n      bhash.put(SafeEncoder.encode(entry.getKey()), SafeEncoder.encode(entry.getValue()));\n    }\n    hmset(SafeEncoder.encode(key), bhash);\n  }\n\n  @Override\n  public void hmget(final String key, final String... fields) {\n    final byte[][] bfields = new byte[fields.length][];\n    for (int i = 0; i < bfields.length; i++) {\n      bfields[i] = SafeEncoder.encode(fields[i]);\n    }\n    hmget(SafeEncoder.encode(key), bfields);\n  }\n\n  @Override\n  public void hincrBy(final String key, final String field, final long value) {\n    hincrBy(SafeEncoder.encode(key), SafeEncoder.encode(field), value);\n  }\n\n  @Override\n  public void hexists(final String key, final String field) {\n    hexists(SafeEncoder.encode(key), SafeEncoder.encode(field));\n  }\n\n  @Override\n  public void hdel(final String key, final String... fields) {\n    hdel(SafeEncoder.encode(key), SafeEncoder.encodeMany(fields));\n  }\n\n  @Override\n  public void hlen(final String key) {\n    hlen(SafeEncoder.encode(key));\n  }\n\n  @Override\n  public void hkeys(final String key) {\n    hkeys(SafeEncoder.encode(key));\n  }\n\n  @Override\n  public void hvals(final String key) {\n    hvals(SafeEncoder.encode(key));\n  }\n\n  @Override\n  public void hgetAll(final String key) {\n    hgetAll(SafeEncoder.encode(key));\n  }\n\n  @Override\n  public void rpush(final String key, final String... string) {\n    rpush(SafeEncoder.encode(key), SafeEncoder.encodeMany(string));\n  }\n\n  @Override\n  public void lpush(final String key, final String... string) {\n    lpush(SafeEncoder.encode(key), SafeEncoder.encodeMany(string));\n  }\n\n  @Override\n  public void llen(final String key) {\n    llen(SafeEncoder.encode(key));\n  }\n\n  @Override\n  public void lrange(final String key, final long start, final long end) {\n    lrange(SafeEncoder.encode(key), start, end);\n  }\n\n  @Override\n  public void ltrim(final String key, final long start, final long end) {\n    ltrim(SafeEncoder.encode(key), start, end);\n  }\n\n  @Override\n  public void lindex(final String key, final long index) {\n    lindex(SafeEncoder.encode(key), index);\n  }\n\n  @Override\n  public void lset(final String key, final long index, final String value) {\n    lset(SafeEncoder.encode(key), index, SafeEncoder.encode(value));\n  }\n\n  @Override\n  public void lrem(final String key, long count, final String value) {\n    lrem(SafeEncoder.encode(key), count, SafeEncoder.encode(value));\n  }\n\n  @Override\n  public void lpop(final String key) {\n    lpop(SafeEncoder.encode(key));\n  }\n\n  @Override\n  public void rpop(final String key) {\n    rpop(SafeEncoder.encode(key));\n  }\n\n  @Override\n  public void rpoplpush(final String srckey, final String dstkey) {\n    rpoplpush(SafeEncoder.encode(srckey), SafeEncoder.encode(dstkey));\n  }\n\n  @Override\n  public void sadd(final String key, final String... members) {\n    sadd(SafeEncoder.encode(key), SafeEncoder.encodeMany(members));\n  }\n\n  @Override\n  public void smembers(final String key) {\n    smembers(SafeEncoder.encode(key));\n  }\n\n  @Override\n  public void srem(final String key, final String... members) {\n    srem(SafeEncoder.encode(key), SafeEncoder.encodeMany(members));\n  }\n\n  @Override\n  public void spop(final String key) {\n    spop(SafeEncoder.encode(key));\n  }\n\n  @Override\n  public void spop(final String key, final long count) {\n    spop(SafeEncoder.encode(key), count);\n  }\n\n  @Override\n  public void smove(final String srckey, final String dstkey, final String member) {\n    smove(SafeEncoder.encode(srckey), SafeEncoder.encode(dstkey), SafeEncoder.encode(member));\n  }\n\n  @Override\n  public void scard(final String key) {\n    scard(SafeEncoder.encode(key));\n  }\n\n  @Override\n  public void sismember(final String key, final String member) {\n    sismember(SafeEncoder.encode(key), SafeEncoder.encode(member));\n  }\n\n  @Override\n  public void sinter(final String... keys) {\n    final byte[][] bkeys = new byte[keys.length][];\n    for (int i = 0; i < bkeys.length; i++) {\n      bkeys[i] = SafeEncoder.encode(keys[i]);\n    }\n    sinter(bkeys);\n  }\n\n  @Override\n  public void sinterstore(final String dstkey, final String... keys) {\n    final byte[][] bkeys = new byte[keys.length][];\n    for (int i = 0; i < bkeys.length; i++) {\n      bkeys[i] = SafeEncoder.encode(keys[i]);\n    }\n    sinterstore(SafeEncoder.encode(dstkey), bkeys);\n  }\n\n  @Override\n  public void sunion(final String... keys) {\n    final byte[][] bkeys = new byte[keys.length][];\n    for (int i = 0; i < bkeys.length; i++) {\n      bkeys[i] = SafeEncoder.encode(keys[i]);\n    }\n    sunion(bkeys);\n  }\n\n  @Override\n  public void sunionstore(final String dstkey, final String... keys) {\n    final byte[][] bkeys = new byte[keys.length][];\n    for (int i = 0; i < bkeys.length; i++) {\n      bkeys[i] = SafeEncoder.encode(keys[i]);\n    }\n    sunionstore(SafeEncoder.encode(dstkey), bkeys);\n  }\n\n  @Override\n  public void sdiff(final String... keys) {\n    final byte[][] bkeys = new byte[keys.length][];\n    for (int i = 0; i < bkeys.length; i++) {\n      bkeys[i] = SafeEncoder.encode(keys[i]);\n    }\n    sdiff(bkeys);\n  }\n\n  @Override\n  public void sdiffstore(final String dstkey, final String... keys) {\n    final byte[][] bkeys = new byte[keys.length][];\n    for (int i = 0; i < bkeys.length; i++) {\n      bkeys[i] = SafeEncoder.encode(keys[i]);\n    }\n    sdiffstore(SafeEncoder.encode(dstkey), bkeys);\n  }\n\n  @Override\n  public void srandmember(final String key) {\n    srandmember(SafeEncoder.encode(key));\n  }\n\n  @Override\n  public void zadd(final String key, final double score, final String member) {\n    zadd(SafeEncoder.encode(key), score, SafeEncoder.encode(member));\n  }\n\n  @Override\n  public void zadd(final String key, final double score, final String member,\n      final ZAddParams params) {\n    zadd(SafeEncoder.encode(key), score, SafeEncoder.encode(member), params);\n  }\n\n  @Override\n  public void zadd(String key, Map<String, Double> scoreMembers) {\n    HashMap<byte[], Double> binaryScoreMembers = convertScoreMembersToBinary(scoreMembers);\n    zadd(SafeEncoder.encode(key), binaryScoreMembers);\n  }\n\n  @Override\n  public void zadd(final String key, final Map<String, Double> scoreMembers, final ZAddParams params) {\n    HashMap<byte[], Double> binaryScoreMembers = convertScoreMembersToBinary(scoreMembers);\n    zadd(SafeEncoder.encode(key), binaryScoreMembers, params);\n  }\n\n  @Override\n  public void zrange(final String key, final long start, final long end) {\n    zrange(SafeEncoder.encode(key), start, end);\n  }\n\n  @Override\n  public void zrem(final String key, final String... members) {\n    zrem(SafeEncoder.encode(key), SafeEncoder.encodeMany(members));\n  }\n\n  @Override\n  public void zincrby(final String key, final double score, final String member) {\n    zincrby(SafeEncoder.encode(key), score, SafeEncoder.encode(member));\n  }\n\n  @Override\n  public void zincrby(String key, double score, String member, ZIncrByParams params) {\n    zincrby(SafeEncoder.encode(key), score, SafeEncoder.encode(member), params);\n  }\n\n  @Override\n  public void zrank(final String key, final String member) {\n    zrank(SafeEncoder.encode(key), SafeEncoder.encode(member));\n  }\n\n  @Override\n  public void zrevrank(final String key, final String member) {\n    zrevrank(SafeEncoder.encode(key), SafeEncoder.encode(member));\n  }\n\n  @Override\n  public void zrevrange(final String key, final long start, final long end) {\n    zrevrange(SafeEncoder.encode(key), start, end);\n  }\n\n  @Override\n  public void zrangeWithScores(final String key, final long start, final long end) {\n    zrangeWithScores(SafeEncoder.encode(key), start, end);\n  }\n\n  @Override\n  public void zrevrangeWithScores(final String key, final long start, final long end) {\n    zrevrangeWithScores(SafeEncoder.encode(key), start, end);\n  }\n\n  @Override\n  public void zcard(final String key) {\n    zcard(SafeEncoder.encode(key));\n  }\n\n  @Override\n  public void zscore(final String key, final String member) {\n    zscore(SafeEncoder.encode(key), SafeEncoder.encode(member));\n  }\n\n  @Override\n  public void watch(final String... keys) {\n    final byte[][] bargs = new byte[keys.length][];\n    for (int i = 0; i < bargs.length; i++) {\n      bargs[i] = SafeEncoder.encode(keys[i]);\n    }\n    watch(bargs);\n  }\n\n  @Override\n  public void sort(final String key) {\n    sort(SafeEncoder.encode(key));\n  }\n\n  @Override\n  public void sort(final String key, final SortingParams sortingParameters) {\n    sort(SafeEncoder.encode(key), sortingParameters);\n  }\n\n  @Override\n  public void blpop(final String[] args) {\n    final byte[][] bargs = new byte[args.length][];\n    for (int i = 0; i < bargs.length; i++) {\n      bargs[i] = SafeEncoder.encode(args[i]);\n    }\n    blpop(bargs);\n  }\n\n  public void blpop(final int timeout, final String... keys) {\n    final int size = keys.length + 1;\n    List<String> args = new ArrayList<String>(size);\n    for (String arg : keys) {\n      args.add(arg);\n    }\n    args.add(String.valueOf(timeout));\n    blpop(args.toArray(new String[size]));\n  }\n\n  @Override\n  public void sort(final String key, final SortingParams sortingParameters, final String dstkey) {\n    sort(SafeEncoder.encode(key), sortingParameters, SafeEncoder.encode(dstkey));\n  }\n\n  @Override\n  public void sort(final String key, final String dstkey) {\n    sort(SafeEncoder.encode(key), SafeEncoder.encode(dstkey));\n  }\n\n  @Override\n  public void brpop(final String[] args) {\n    final byte[][] bargs = new byte[args.length][];\n    for (int i = 0; i < bargs.length; i++) {\n      bargs[i] = SafeEncoder.encode(args[i]);\n    }\n    brpop(bargs);\n  }\n\n  public void brpop(final int timeout, final String... keys) {\n    final int size = keys.length + 1;\n    List<String> args = new ArrayList<String>(size);\n    for (String arg : keys) {\n      args.add(arg);\n    }\n    args.add(String.valueOf(timeout));\n    brpop(args.toArray(new String[size]));\n  }\n\n  @Override\n  public void zcount(final String key, final double min, final double max) {\n    zcount(SafeEncoder.encode(key), toByteArray(min), toByteArray(max));\n  }\n\n  @Override\n  public void zcount(final String key, final String min, final String max) {\n    zcount(SafeEncoder.encode(key), SafeEncoder.encode(min), SafeEncoder.encode(max));\n  }\n\n  @Override\n  public void zrangeByScore(final String key, final double min, final double max) {\n    zrangeByScore(SafeEncoder.encode(key), toByteArray(min), toByteArray(max));\n  }\n\n  @Override\n  public void zrangeByScore(final String key, final String min, final String max) {\n    zrangeByScore(SafeEncoder.encode(key), SafeEncoder.encode(min), SafeEncoder.encode(max));\n  }\n\n  @Override\n  public void zrangeByScore(final String key, final double min, final double max, final int offset,\n      int count) {\n    zrangeByScore(SafeEncoder.encode(key), toByteArray(min), toByteArray(max), offset, count);\n  }\n\n  @Override\n  public void zrangeByScoreWithScores(final String key, final double min, final double max) {\n    zrangeByScoreWithScores(SafeEncoder.encode(key), toByteArray(min), toByteArray(max));\n  }\n\n  @Override\n  public void zrangeByScoreWithScores(final String key, final double min, final double max,\n      final int offset, final int count) {\n    zrangeByScoreWithScores(SafeEncoder.encode(key), toByteArray(min), toByteArray(max), offset,\n      count);\n  }\n\n  @Override\n  public void zrevrangeByScore(final String key, final double max, final double min) {\n    zrevrangeByScore(SafeEncoder.encode(key), toByteArray(max), toByteArray(min));\n  }\n\n  public void zrangeByScore(final String key, final String min, final String max, final int offset,\n      int count) {\n    zrangeByScore(SafeEncoder.encode(key), SafeEncoder.encode(min), SafeEncoder.encode(max),\n      offset, count);\n  }\n\n  @Override\n  public void zrangeByScoreWithScores(final String key, final String min, final String max) {\n    zrangeByScoreWithScores(SafeEncoder.encode(key), SafeEncoder.encode(min),\n      SafeEncoder.encode(max));\n  }\n\n  @Override\n  public void zrangeByScoreWithScores(final String key, final String min, final String max,\n      final int offset, final int count) {\n    zrangeByScoreWithScores(SafeEncoder.encode(key), SafeEncoder.encode(min),\n      SafeEncoder.encode(max), offset, count);\n  }\n\n  @Override\n  public void zrevrangeByScore(final String key, final String max, final String min) {\n    zrevrangeByScore(SafeEncoder.encode(key), SafeEncoder.encode(max), SafeEncoder.encode(min));\n  }\n\n  @Override\n  public void zrevrangeByScore(final String key, final double max, final double min,\n      final int offset, int count) {\n    zrevrangeByScore(SafeEncoder.encode(key), toByteArray(max), toByteArray(min), offset, count);\n  }\n\n  public void zrevrangeByScore(final String key, final String max, final String min,\n      final int offset, int count) {\n    zrevrangeByScore(SafeEncoder.encode(key), SafeEncoder.encode(max), SafeEncoder.encode(min),\n      offset, count);\n  }\n\n  @Override\n  public void zrevrangeByScoreWithScores(final String key, final double max, final double min) {\n    zrevrangeByScoreWithScores(SafeEncoder.encode(key), toByteArray(max), toByteArray(min));\n  }\n\n  @Override\n  public void zrevrangeByScoreWithScores(final String key, final String max, final String min) {\n    zrevrangeByScoreWithScores(SafeEncoder.encode(key), SafeEncoder.encode(max),\n      SafeEncoder.encode(min));\n  }\n\n  @Override\n  public void zrevrangeByScoreWithScores(final String key, final double max, final double min,\n      final int offset, final int count) {\n    zrevrangeByScoreWithScores(SafeEncoder.encode(key), toByteArray(max), toByteArray(min), offset,\n      count);\n  }\n\n  @Override\n  public void zrevrangeByScoreWithScores(final String key, final String max, final String min,\n      final int offset, final int count) {\n    zrevrangeByScoreWithScores(SafeEncoder.encode(key), SafeEncoder.encode(max),\n      SafeEncoder.encode(min), offset, count);\n  }\n\n  @Override\n  public void zremrangeByRank(final String key, final long start, final long end) {\n    zremrangeByRank(SafeEncoder.encode(key), start, end);\n  }\n\n  @Override\n  public void zremrangeByScore(final String key, final double start, final double end) {\n    zremrangeByScore(SafeEncoder.encode(key), toByteArray(start), toByteArray(end));\n  }\n\n  @Override\n  public void zremrangeByScore(final String key, final String start, final String end) {\n    zremrangeByScore(SafeEncoder.encode(key), SafeEncoder.encode(start), SafeEncoder.encode(end));\n  }\n\n  @Override\n  public void zunionstore(final String dstkey, final String... sets) {\n    final byte[][] bsets = new byte[sets.length][];\n    for (int i = 0; i < bsets.length; i++) {\n      bsets[i] = SafeEncoder.encode(sets[i]);\n    }\n    zunionstore(SafeEncoder.encode(dstkey), bsets);\n  }\n\n  @Override\n  public void zunionstore(final String dstkey, final ZParams params, final String... sets) {\n    final byte[][] bsets = new byte[sets.length][];\n    for (int i = 0; i < bsets.length; i++) {\n      bsets[i] = SafeEncoder.encode(sets[i]);\n    }\n    zunionstore(SafeEncoder.encode(dstkey), params, bsets);\n  }\n\n  @Override\n  public void zinterstore(final String dstkey, final String... sets) {\n    final byte[][] bsets = new byte[sets.length][];\n    for (int i = 0; i < bsets.length; i++) {\n      bsets[i] = SafeEncoder.encode(sets[i]);\n    }\n    zinterstore(SafeEncoder.encode(dstkey), bsets);\n  }\n\n  @Override\n  public void zinterstore(final String dstkey, final ZParams params, final String... sets) {\n    final byte[][] bsets = new byte[sets.length][];\n    for (int i = 0; i < bsets.length; i++) {\n      bsets[i] = SafeEncoder.encode(sets[i]);\n    }\n    zinterstore(SafeEncoder.encode(dstkey), params, bsets);\n  }\n\n  public void zlexcount(final String key, final String min, final String max) {\n    zlexcount(SafeEncoder.encode(key), SafeEncoder.encode(min), SafeEncoder.encode(max));\n  }\n\n  public void zrangeByLex(final String key, final String min, final String max) {\n    zrangeByLex(SafeEncoder.encode(key), SafeEncoder.encode(min), SafeEncoder.encode(max));\n  }\n\n  public void zrangeByLex(final String key, final String min, final String max, final int offset,\n      final int count) {\n    zrangeByLex(SafeEncoder.encode(key), SafeEncoder.encode(min), SafeEncoder.encode(max), offset,\n      count);\n  }\n\n  public void zrevrangeByLex(String key, String max, String min) {\n    zrevrangeByLex(SafeEncoder.encode(key), SafeEncoder.encode(max), SafeEncoder.encode(min));\n  }\n\n  public void zrevrangeByLex(String key, String max, String min, int offset, int count) {\n    zrevrangeByLex(SafeEncoder.encode(key), SafeEncoder.encode(max), SafeEncoder.encode(min),\n      offset, count);\n  }\n\n  public void zremrangeByLex(final String key, final String min, final String max) {\n    zremrangeByLex(SafeEncoder.encode(key), SafeEncoder.encode(min), SafeEncoder.encode(max));\n  }\n\n  @Override\n  public void strlen(final String key) {\n    strlen(SafeEncoder.encode(key));\n  }\n\n  @Override\n  public void lpushx(final String key, final String... string) {\n    lpushx(SafeEncoder.encode(key), getByteParams(string));\n  }\n\n  @Override\n  public void persist(final String key) {\n    persist(SafeEncoder.encode(key));\n  }\n\n  @Override\n  public void rpushx(final String key, final String... string) {\n    rpushx(SafeEncoder.encode(key), getByteParams(string));\n  }\n\n  @Override\n  public void echo(final String string) {\n    echo(SafeEncoder.encode(string));\n  }\n\n  @Override\n  public void linsert(final String key, final LIST_POSITION where, final String pivot,\n      final String value) {\n    linsert(SafeEncoder.encode(key), where, SafeEncoder.encode(pivot), SafeEncoder.encode(value));\n  }\n\n  @Override\n  public void brpoplpush(String source, String destination, int timeout) {\n    brpoplpush(SafeEncoder.encode(source), SafeEncoder.encode(destination), timeout);\n  }\n\n  @Override\n  public void setbit(final String key, final long offset, final boolean value) {\n    setbit(SafeEncoder.encode(key), offset, value);\n  }\n\n  @Override\n  public void setbit(final String key, final long offset, final String value) {\n    setbit(SafeEncoder.encode(key), offset, SafeEncoder.encode(value));\n  }\n\n  @Override\n  public void getbit(String key, long offset) {\n    getbit(SafeEncoder.encode(key), offset);\n  }\n\n  public void bitpos(final String key, final boolean value, final BitPosParams params) {\n    bitpos(SafeEncoder.encode(key), value, params);\n  }\n\n  @Override\n  public void setrange(String key, long offset, String value) {\n    setrange(SafeEncoder.encode(key), offset, SafeEncoder.encode(value));\n  }\n\n  @Override\n  public void getrange(String key, long startOffset, long endOffset) {\n    getrange(SafeEncoder.encode(key), startOffset, endOffset);\n  }\n\n  public void publish(final String channel, final String message) {\n    publish(SafeEncoder.encode(channel), SafeEncoder.encode(message));\n  }\n\n  public void unsubscribe(final String... channels) {\n    final byte[][] cs = new byte[channels.length][];\n    for (int i = 0; i < cs.length; i++) {\n      cs[i] = SafeEncoder.encode(channels[i]);\n    }\n    unsubscribe(cs);\n  }\n\n  public void psubscribe(final String... patterns) {\n    final byte[][] ps = new byte[patterns.length][];\n    for (int i = 0; i < ps.length; i++) {\n      ps[i] = SafeEncoder.encode(patterns[i]);\n    }\n    psubscribe(ps);\n  }\n\n  public void punsubscribe(final String... patterns) {\n    final byte[][] ps = new byte[patterns.length][];\n    for (int i = 0; i < ps.length; i++) {\n      ps[i] = SafeEncoder.encode(patterns[i]);\n    }\n    punsubscribe(ps);\n  }\n\n  public void subscribe(final String... channels) {\n    final byte[][] cs = new byte[channels.length][];\n    for (int i = 0; i < cs.length; i++) {\n      cs[i] = SafeEncoder.encode(channels[i]);\n    }\n    subscribe(cs);\n  }\n\n  public void pubsubChannels(String pattern) {\n    pubsub(Protocol.PUBSUB_CHANNELS, pattern);\n  }\n\n  public void pubsubNumPat() {\n    pubsub(Protocol.PUBSUB_NUM_PAT);\n  }\n\n  public void pubsubNumSub(String... channels) {\n    pubsub(Protocol.PUBSUB_NUMSUB, channels);\n  }\n\n  @Override\n  public void configSet(String parameter, String value) {\n    configSet(SafeEncoder.encode(parameter), SafeEncoder.encode(value));\n  }\n\n  @Override\n  public void configGet(String pattern) {\n    configGet(SafeEncoder.encode(pattern));\n  }\n\n  public void eval(String script, int keyCount, String... params) {\n    eval(SafeEncoder.encode(script), toByteArray(keyCount), getByteParams(params));\n  }\n\n  public void evalsha(String sha1, int keyCount, String... params) {\n    evalsha(SafeEncoder.encode(sha1), toByteArray(keyCount), getByteParams(params));\n  }\n\n  public void scriptExists(String... sha1) {\n    final byte[][] bsha1 = new byte[sha1.length][];\n    for (int i = 0; i < bsha1.length; i++) {\n      bsha1[i] = SafeEncoder.encode(sha1[i]);\n    }\n    scriptExists(bsha1);\n  }\n\n  public void scriptLoad(String script) {\n    scriptLoad(SafeEncoder.encode(script));\n  }\n\n  @Override\n  public void objectRefcount(String key) {\n    objectRefcount(SafeEncoder.encode(key));\n  }\n\n  @Override\n  public void objectIdletime(String key) {\n    objectIdletime(SafeEncoder.encode(key));\n  }\n\n  @Override\n  public void objectEncoding(String key) {\n    objectEncoding(SafeEncoder.encode(key));\n  }\n\n  @Override\n  public void bitcount(final String key) {\n    bitcount(SafeEncoder.encode(key));\n  }\n\n  @Override\n  public void bitcount(final String key, long start, long end) {\n    bitcount(SafeEncoder.encode(key), start, end);\n  }\n\n  @Override\n  public void bitop(BitOP op, final String destKey, String... srcKeys) {\n    bitop(op, SafeEncoder.encode(destKey), getByteParams(srcKeys));\n  }\n\n  public void sentinel(final String... args) {\n    final byte[][] arg = new byte[args.length][];\n    for (int i = 0; i < arg.length; i++) {\n      arg[i] = SafeEncoder.encode(args[i]);\n    }\n    sentinel(arg);\n  }\n\n  public void dump(final String key) {\n    dump(SafeEncoder.encode(key));\n  }\n\n  public void restore(final String key, final int ttl, final byte[] serializedValue) {\n    restore(SafeEncoder.encode(key), ttl, serializedValue);\n  }\n\n  public void pexpire(final String key, final long milliseconds) {\n    pexpire(SafeEncoder.encode(key), milliseconds);\n  }\n\n  public void pexpireAt(final String key, final long millisecondsTimestamp) {\n    pexpireAt(SafeEncoder.encode(key), millisecondsTimestamp);\n  }\n\n  public void pttl(final String key) {\n    pttl(SafeEncoder.encode(key));\n  }\n\n  @Override\n  public void incrByFloat(final String key, final double increment) {\n    incrByFloat(SafeEncoder.encode(key), increment);\n  }\n\n  public void psetex(final String key, final long milliseconds, final String value) {\n    psetex(SafeEncoder.encode(key), milliseconds, SafeEncoder.encode(value));\n  }\n\n  public void srandmember(final String key, final int count) {\n    srandmember(SafeEncoder.encode(key), count);\n  }\n\n  public void clientKill(final String client) {\n    clientKill(SafeEncoder.encode(client));\n  }\n\n  public void clientSetname(final String name) {\n    clientSetname(SafeEncoder.encode(name));\n  }\n\n  public void migrate(final String host, final int port, final String key, final int destinationDb,\n      final int timeout) {\n    migrate(SafeEncoder.encode(host), port, SafeEncoder.encode(key), destinationDb, timeout);\n  }\n  \n  public void migrate(final String host, final int port, final int destinationDb,\n          final int timeout, final String... keys) {\n    migrate(SafeEncoder.encode(host), port, destinationDb, timeout, SafeEncoder.encodeMany(keys));\n}\n\n  @Override\n  public void hincrByFloat(final String key, final String field, double increment) {\n    hincrByFloat(SafeEncoder.encode(key), SafeEncoder.encode(field), increment);\n  }\n\n  @Override\n  public void scan(final String cursor, final ScanParams params) {\n    scan(SafeEncoder.encode(cursor), params);\n  }\n\n  @Override\n  public void hscan(final String key, final String cursor, final ScanParams params) {\n    hscan(SafeEncoder.encode(key), SafeEncoder.encode(cursor), params);\n  }\n\n  @Override\n  public void sscan(final String key, final String cursor, final ScanParams params) {\n    sscan(SafeEncoder.encode(key), SafeEncoder.encode(cursor), params);\n  }\n\n  @Override\n  public void zscan(final String key, final String cursor, final ScanParams params) {\n    zscan(SafeEncoder.encode(key), SafeEncoder.encode(cursor), params);\n  }\n\n  public void cluster(final String subcommand, final int... args) {\n    final byte[][] arg = new byte[args.length + 1][];\n    for (int i = 1; i < arg.length; i++) {\n      arg[i] = toByteArray(args[i - 1]);\n    }\n    arg[0] = SafeEncoder.encode(subcommand);\n    cluster(arg);\n  }\n\n  public void pubsub(final String subcommand, final String... args) {\n    final byte[][] arg = new byte[args.length + 1][];\n    for (int i = 1; i < arg.length; i++) {\n      arg[i] = SafeEncoder.encode(args[i - 1]);\n    }\n    arg[0] = SafeEncoder.encode(subcommand);\n    pubsub(arg);\n  }\n\n  public void cluster(final String subcommand, final String... args) {\n    final byte[][] arg = new byte[args.length + 1][];\n    for (int i = 1; i < arg.length; i++) {\n      arg[i] = SafeEncoder.encode(args[i - 1]);\n    }\n    arg[0] = SafeEncoder.encode(subcommand);\n    cluster(arg);\n  }\n\n  public void cluster(final String subcommand) {\n    final byte[][] arg = new byte[1][];\n    arg[0] = SafeEncoder.encode(subcommand);\n    cluster(arg);\n  }\n\n  public void clusterNodes() {\n    cluster(Protocol.CLUSTER_NODES);\n  }\n\n  public void clusterMeet(final String ip, final int port) {\n    cluster(Protocol.CLUSTER_MEET, ip, String.valueOf(port));\n  }\n\n  public void clusterReset(Reset resetType) {\n    cluster(Protocol.CLUSTER_RESET, resetType.toString());\n  }\n\n  public void clusterAddSlots(final int... slots) {\n    cluster(Protocol.CLUSTER_ADDSLOTS, slots);\n  }\n\n  public void clusterDelSlots(final int... slots) {\n    cluster(Protocol.CLUSTER_DELSLOTS, slots);\n  }\n\n  public void clusterInfo() {\n    cluster(Protocol.CLUSTER_INFO);\n  }\n\n  public void clusterGetKeysInSlot(final int slot, final int count) {\n    final int[] args = new int[] { slot, count };\n    cluster(Protocol.CLUSTER_GETKEYSINSLOT, args);\n  }\n\n  public void clusterSetSlotNode(final int slot, final String nodeId) {\n    cluster(Protocol.CLUSTER_SETSLOT, String.valueOf(slot), Protocol.CLUSTER_SETSLOT_NODE, nodeId);\n  }\n\n  public void clusterSetSlotMigrating(final int slot, final String nodeId) {\n    cluster(Protocol.CLUSTER_SETSLOT, String.valueOf(slot), Protocol.CLUSTER_SETSLOT_MIGRATING,\n      nodeId);\n  }\n\n  public void clusterSetSlotImporting(final int slot, final String nodeId) {\n    cluster(Protocol.CLUSTER_SETSLOT, String.valueOf(slot), Protocol.CLUSTER_SETSLOT_IMPORTING,\n      nodeId);\n  }\n\n  public void pfadd(String key, final String... elements) {\n    pfadd(SafeEncoder.encode(key), SafeEncoder.encodeMany(elements));\n  }\n\n  public void pfcount(final String key) {\n    pfcount(SafeEncoder.encode(key));\n  }\n\n  public void pfcount(final String... keys) {\n    pfcount(SafeEncoder.encodeMany(keys));\n  }\n\n  public void pfmerge(final String destkey, final String... sourcekeys) {\n    pfmerge(SafeEncoder.encode(destkey), SafeEncoder.encodeMany(sourcekeys));\n  }\n\n  public void clusterSetSlotStable(final int slot) {\n    cluster(Protocol.CLUSTER_SETSLOT, String.valueOf(slot), Protocol.CLUSTER_SETSLOT_STABLE);\n  }\n\n  public void clusterForget(final String nodeId) {\n    cluster(Protocol.CLUSTER_FORGET, nodeId);\n  }\n\n  public void clusterFlushSlots() {\n    cluster(Protocol.CLUSTER_FLUSHSLOT);\n  }\n\n  public void clusterKeySlot(final String key) {\n    cluster(Protocol.CLUSTER_KEYSLOT, key);\n  }\n\n  public void clusterCountKeysInSlot(final int slot) {\n    cluster(Protocol.CLUSTER_COUNTKEYINSLOT, String.valueOf(slot));\n  }\n\n  public void clusterSaveConfig() {\n    cluster(Protocol.CLUSTER_SAVECONFIG);\n  }\n\n  public void clusterReplicate(final String nodeId) {\n    cluster(Protocol.CLUSTER_REPLICATE, nodeId);\n  }\n\n  public void clusterSlaves(final String nodeId) {\n    cluster(Protocol.CLUSTER_SLAVES, nodeId);\n  }\n\n  public void clusterFailover() {\n    cluster(Protocol.CLUSTER_FAILOVER);\n  }\n\n  public void clusterSlots() {\n    cluster(Protocol.CLUSTER_SLOTS);\n  }\n\n  public void geoadd(String key, double longitude, double latitude, String member) {\n    geoadd(SafeEncoder.encode(key), longitude, latitude, SafeEncoder.encode(member));\n  }\n\n  public void geoadd(String key, Map<String, GeoCoordinate> memberCoordinateMap) {\n    geoadd(SafeEncoder.encode(key), convertMemberCoordinateMapToBinary(memberCoordinateMap));\n  }\n\n  public void geodist(String key, String member1, String member2) {\n    geodist(SafeEncoder.encode(key), SafeEncoder.encode(member1), SafeEncoder.encode(member2));\n  }\n\n  public void geodist(String key, String member1, String member2, GeoUnit unit) {\n    geodist(SafeEncoder.encode(key), SafeEncoder.encode(member1), SafeEncoder.encode(member2), unit);\n  }\n\n  public void geohash(String key, String... members) {\n    geohash(SafeEncoder.encode(key), SafeEncoder.encodeMany(members));\n  }\n\n  public void geopos(String key, String[] members) {\n    geopos(SafeEncoder.encode(key), SafeEncoder.encodeMany(members));\n  }\n\n  public void georadius(String key, double longitude, double latitude, double radius, GeoUnit unit) {\n    georadius(SafeEncoder.encode(key), longitude, latitude, radius, unit);\n  }\n\n  public void georadius(String key, double longitude, double latitude, double radius, GeoUnit unit,\n      GeoRadiusParam param) {\n    georadius(SafeEncoder.encode(key), longitude, latitude, radius, unit, param);\n  }\n\n  public void georadiusByMember(String key, String member, double radius, GeoUnit unit) {\n    georadiusByMember(SafeEncoder.encode(key), SafeEncoder.encode(member), radius, unit);\n  }\n\n  public void georadiusByMember(String key, String member, double radius, GeoUnit unit,\n      GeoRadiusParam param) {\n    georadiusByMember(SafeEncoder.encode(key), SafeEncoder.encode(member), radius, unit, param);\n  }\n\n  private byte[][] getByteParams(String... params) {\n    byte[][] p = new byte[params.length][];\n    for (int i = 0; i < params.length; i++)\n      p[i] = SafeEncoder.encode(params[i]);\n\n    return p;\n  }\n\n  private HashMap<byte[], Double> convertScoreMembersToBinary(Map<String, Double> scoreMembers) {\n    HashMap<byte[], Double> binaryScoreMembers = new HashMap<byte[], Double>();\n\n    for (Entry<String, Double> entry : scoreMembers.entrySet()) {\n      binaryScoreMembers.put(SafeEncoder.encode(entry.getKey()), entry.getValue());\n    }\n    return binaryScoreMembers;\n  }\n\n  private HashMap<byte[], GeoCoordinate> convertMemberCoordinateMapToBinary(\n      Map<String, GeoCoordinate> memberCoordinateMap) {\n    HashMap<byte[], GeoCoordinate> binaryMemberCoordinateMap = new HashMap<byte[], GeoCoordinate>();\n\n    for (Entry<String, GeoCoordinate> entry : memberCoordinateMap.entrySet()) {\n      binaryMemberCoordinateMap.put(SafeEncoder.encode(entry.getKey()), entry.getValue());\n    }\n    return binaryMemberCoordinateMap;\n  }\n\n  public void clusterFailoverForce() {\n    cluster(Protocol.CLUSTER_FAILOVER, \"force\");\n  }\n  \n  public void clusterFailoverTakeOver() {\n      cluster(Protocol.CLUSTER_FAILOVER, \"takeover\");\n  }\n\n  public void configRewrite() {\n    sendCommand(CONFIG, \"rewrite\");\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/Connection.java",
    "content": "package redis.clients.jedis;\n\nimport java.io.Closeable;\nimport java.io.IOException;\nimport java.net.InetSocketAddress;\nimport java.net.Socket;\nimport java.net.SocketException;\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport com.sohu.tv.jedis.stat.data.UsefulDataCollector;\nimport com.sohu.tv.jedis.stat.model.UsefulDataModel;\n\nimport redis.clients.jedis.commands.ProtocolCommand;\nimport redis.clients.jedis.exceptions.JedisConnectionException;\nimport redis.clients.jedis.exceptions.JedisDataException;\nimport redis.clients.util.IOUtils;\nimport redis.clients.util.RedisInputStream;\nimport redis.clients.util.RedisOutputStream;\nimport redis.clients.util.SafeEncoder;\n\npublic class Connection implements Closeable {\n\n  private static final byte[][] EMPTY_ARGS = new byte[0][];\n\n  private String host = Protocol.DEFAULT_HOST;\n  private int port = Protocol.DEFAULT_PORT;\n  private Socket socket;\n  private RedisOutputStream outputStream;\n  private RedisInputStream inputStream;\n  private int connectionTimeout = Protocol.DEFAULT_TIMEOUT;\n  private int soTimeout = Protocol.DEFAULT_TIMEOUT;\n  private boolean broken = false;\n\n  private static ThreadLocal<UsefulDataModel> threadLocal = new ThreadLocal<UsefulDataModel>();\n\n  \n  public Connection() {\n  }\n\n  public Connection(final String host) {\n    this.host = host;\n  }\n\n  public Connection(final String host, final int port) {\n    this.host = host;\n    this.port = port;\n  }\n\n  public Socket getSocket() {\n    return socket;\n  }\n\n  public int getConnectionTimeout() {\n    return connectionTimeout;\n  }\n\n  public int getSoTimeout() {\n    return soTimeout;\n  }\n\n  public void setConnectionTimeout(int connectionTimeout) {\n    this.connectionTimeout = connectionTimeout;\n  }\n\n  public void setSoTimeout(int soTimeout) {\n    this.soTimeout = soTimeout;\n  }\n\n  public void setTimeoutInfinite() {\n    try {\n      if (!isConnected()) {\n        connect();\n      }\n      socket.setSoTimeout(0);\n    } catch (SocketException ex) {\n      broken = true;\n      throw new JedisConnectionException(ex);\n    }\n  }\n\n  public void rollbackTimeout() {\n    try {\n      socket.setSoTimeout(soTimeout);\n    } catch (SocketException ex) {\n      broken = true;\n      throw new JedisConnectionException(ex);\n    }\n  }\n\n  protected Connection sendCommand(final ProtocolCommand cmd, final String... args) {\n    final byte[][] bargs = new byte[args.length][];\n    for (int i = 0; i < args.length; i++) {\n      bargs[i] = SafeEncoder.encode(args[i]);\n    }\n    return sendCommand(cmd, bargs);\n  }\n\n  protected Connection sendCommand(final ProtocolCommand cmd) {\n    return sendCommand(cmd, EMPTY_ARGS);\n  }\n\n  protected Connection sendCommand(final ProtocolCommand cmd, final byte[]... args) {\n    try {\n      //统计开始\n      UsefulDataModel costModel = UsefulDataModel.getCostModel(threadLocal);\n      costModel.setCommand(cmd.toString().toLowerCase());\n      costModel.setStartTime(System.currentTimeMillis());\n      \n      connect();\n      Protocol.sendCommand(outputStream, cmd, args);\n      return this;\n    } catch (JedisConnectionException ex) {\n        UsefulDataCollector.collectException(ex, getHostPort(), System.currentTimeMillis());\n      /*\n       * When client send request which formed by invalid protocol, Redis send back error message\n       * before close connection. We try to read it to provide reason of failure.\n       */\n      try {\n        String errorMessage = Protocol.readErrorLineIfPossible(inputStream);\n        if (errorMessage != null && errorMessage.length() > 0) {\n          ex = new JedisConnectionException(errorMessage, ex.getCause());\n        }\n      } catch (Exception e) {\n        /*\n         * Catch any IOException or JedisConnectionException occurred from InputStream#read and just\n         * ignore. This approach is safe because reading error message is optional and connection\n         * will eventually be closed.\n         */\n      }\n      // Any other exceptions related to connection?\n      broken = true;\n      throw ex;\n    }\n  }\n\n  public String getHost() {\n    return host;\n  }\n\n  public void setHost(final String host) {\n    this.host = host;\n  }\n\n  public int getPort() {\n    return port;\n  }\n\n  public void setPort(final int port) {\n    this.port = port;\n  }\n\n  public void connect() {\n    if (!isConnected()) {\n      try {\n        socket = new Socket();\n        // ->@wjw_add\n        socket.setReuseAddress(true);\n        socket.setKeepAlive(true); // Will monitor the TCP connection is\n        // valid\n        socket.setTcpNoDelay(true); // Socket buffer Whetherclosed, to\n        // ensure timely delivery of data\n        socket.setSoLinger(true, 0); // Control calls close () method,\n        // the underlying socket is closed\n        // immediately\n        // <-@wjw_add\n\n        socket.connect(new InetSocketAddress(host, port), connectionTimeout);\n        socket.setSoTimeout(soTimeout);\n        outputStream = new RedisOutputStream(socket.getOutputStream());\n        inputStream = new RedisInputStream(socket.getInputStream());\n      } catch (IOException ex) {\n        UsefulDataCollector.collectException(ex, getHostPort(), System.currentTimeMillis());\n        \n        broken = true;\n        throw new JedisConnectionException(ex);\n      }\n    }\n  }\n\n  @Override\n  public void close() {\n    disconnect();\n  }\n\n  public void disconnect() {\n    if (isConnected()) {\n      try {\n        outputStream.flush();\n        socket.close();\n      } catch (IOException ex) {\n        UsefulDataCollector.collectException(ex, getHostPort(), System.currentTimeMillis());\n        broken = true;\n        throw new JedisConnectionException(ex);\n      } finally {\n        IOUtils.closeQuietly(socket);\n      }\n    }\n  }\n\n  public boolean isConnected() {\n    return socket != null && socket.isBound() && !socket.isClosed() && socket.isConnected()\n        && !socket.isInputShutdown() && !socket.isOutputShutdown();\n  }\n\n  public String getStatusCodeReply() {\n    flush();\n    final byte[] resp = (byte[]) readProtocolWithCheckingBroken();\n    if (null == resp) {\n      return null;\n    } else {\n      return SafeEncoder.encode(resp);\n    }\n  }\n\n  public String getBulkReply() {\n    final byte[] result = getBinaryBulkReply();\n    if (null != result) {\n      return SafeEncoder.encode(result);\n    } else {\n      return null;\n    }\n  }\n\n  public byte[] getBinaryBulkReply() {\n    flush();\n    return (byte[]) readProtocolWithCheckingBroken();\n  }\n\n  public Long getIntegerReply() {\n    flush();\n    return (Long) readProtocolWithCheckingBroken();\n  }\n\n  public List<String> getMultiBulkReply() {\n    return BuilderFactory.STRING_LIST.build(getBinaryMultiBulkReply());\n  }\n\n  @SuppressWarnings(\"unchecked\")\n  public List<byte[]> getBinaryMultiBulkReply() {\n    flush();\n    return (List<byte[]>) readProtocolWithCheckingBroken();\n  }\n\n  @SuppressWarnings(\"unchecked\")\n  public List<Object> getRawObjectMultiBulkReply() {\n    return (List<Object>) readProtocolWithCheckingBroken();\n  }\n\n  public List<Object> getObjectMultiBulkReply() {\n    flush();\n    return getRawObjectMultiBulkReply();\n  }\n\n  @SuppressWarnings(\"unchecked\")\n  public List<Long> getIntegerMultiBulkReply() {\n    flush();\n    return (List<Long>) readProtocolWithCheckingBroken();\n  }\n\n  public Object getOne() {\n    flush();\n    return readProtocolWithCheckingBroken();\n  }\n\n  public boolean isBroken() {\n    return broken;\n  }\n\n  protected void flush() {\n    try {\n      outputStream.flush();\n    } catch (IOException ex) {\n      broken = true;\n      throw new JedisConnectionException(ex);\n    }\n  }\n\n  protected Object readProtocolWithCheckingBroken() {\n        Object o = null;\n        try {\n            o = Protocol.read(inputStream);\n            return o;\n        } catch (JedisConnectionException exc) {\n            UsefulDataCollector.collectException(exc, getHostPort(), System.currentTimeMillis());\n            broken = true;\n            throw exc;\n        } finally {\n            UsefulDataModel costModel = UsefulDataModel.getCostModel(threadLocal);\n            costModel.setHostPort(getHostPort());\n            costModel.setEndTime(System.currentTimeMillis());\n            // 1.上报command + cost给指定\n            if (o != null) {\n                if (o instanceof byte[]) {\n                    byte[] bytes = (byte[]) o;\n                    // 2.上报字节大小\n                    costModel.setValueBytesLength(bytes.length);\n                }\n            }\n            // 清除threadLocal\n            threadLocal.remove();\n            // 排除掉subscribe问题\n            if (costModel.getCommand() != null) {\n                UsefulDataCollector.collectCostAndValueDistribute(costModel);\n            }\n        }\n  }\n\n  public List<Object> getMany(final int count) {\n    flush();\n    final List<Object> responses = new ArrayList<Object>(count);\n    for (int i = 0; i < count; i++) {\n      try {\n        responses.add(readProtocolWithCheckingBroken());\n      } catch (JedisDataException e) {\n        responses.add(e);\n      }\n    }\n    return responses;\n  }\n  \n  public String getHostPort(){\n      return getHost() + \":\" + getPort();\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/DebugParams.java",
    "content": "package redis.clients.jedis;\n\npublic class DebugParams {\n  private String[] command;\n\n  public String[] getCommand() {\n    return command;\n  }\n\n  private DebugParams() {\n\n  }\n\n  public static DebugParams SEGFAULT() {\n    DebugParams debugParams = new DebugParams();\n    debugParams.command = new String[] { \"SEGFAULT\" };\n    return debugParams;\n  }\n\n  public static DebugParams OBJECT(String key) {\n    DebugParams debugParams = new DebugParams();\n    debugParams.command = new String[] { \"OBJECT\", key };\n    return debugParams;\n  }\n\n  public static DebugParams RELOAD() {\n    DebugParams debugParams = new DebugParams();\n    debugParams.command = new String[] { \"RELOAD\" };\n    return debugParams;\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/GeoCoordinate.java",
    "content": "package redis.clients.jedis;\n\npublic class GeoCoordinate {\n  private double longitude;\n  private double latitude;\n\n  public GeoCoordinate(double longitude, double latitude) {\n    this.longitude = longitude;\n    this.latitude = latitude;\n  }\n\n  public double getLongitude() {\n    return longitude;\n  }\n\n  public double getLatitude() {\n    return latitude;\n  }\n\n  @Override\n  public boolean equals(Object o) {\n    if (this == o) return true;\n    if (!(o instanceof GeoCoordinate)) return false;\n\n    GeoCoordinate that = (GeoCoordinate) o;\n\n    if (Double.compare(that.longitude, longitude) != 0) return false;\n    return Double.compare(that.latitude, latitude) == 0;\n  }\n\n  @Override\n  public int hashCode() {\n    // follows IntelliJ default hashCode implementation\n    int result;\n    long temp;\n    temp = Double.doubleToLongBits(longitude);\n    result = (int) (temp ^ (temp >>> 32));\n    temp = Double.doubleToLongBits(latitude);\n    result = 31 * result + (int) (temp ^ (temp >>> 32));\n    return result;\n  }\n\n  @Override\n  public String toString() {\n    return \"(\" + longitude + \",\" + latitude + \")\";\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/GeoRadiusResponse.java",
    "content": "package redis.clients.jedis;\n\nimport redis.clients.util.SafeEncoder;\n\npublic class GeoRadiusResponse {\n  private byte[] member;\n  private double distance;\n  private GeoCoordinate coordinate;\n\n  public GeoRadiusResponse(byte[] member) {\n    this.member = member;\n  }\n\n  public void setDistance(double distance) {\n    this.distance = distance;\n  }\n\n  public void setCoordinate(GeoCoordinate coordinate) {\n    this.coordinate = coordinate;\n  }\n\n  public byte[] getMember() {\n    return member;\n  }\n\n  public String getMemberByString() {\n    return SafeEncoder.encode(member);\n  }\n\n  public double getDistance() {\n    return distance;\n  }\n\n  public GeoCoordinate getCoordinate() {\n    return coordinate;\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/GeoUnit.java",
    "content": "package redis.clients.jedis;\n\nimport redis.clients.util.SafeEncoder;\n\npublic enum GeoUnit {\n  M, KM, MI, FT;\n\n  public final byte[] raw;\n\n  GeoUnit() {\n    raw = SafeEncoder.encode(this.name().toLowerCase());\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/HostAndPort.java",
    "content": "package redis.clients.jedis;\n\nimport java.io.Serializable;\n\npublic class HostAndPort implements Serializable {\nprivate static final long serialVersionUID = -519876229978427751L;\n\npublic static final String LOCALHOST_STR = \"localhost\";\n\n  private String host;\n  private int port;\n\n  public HostAndPort(String host, int port) {\n    this.host = host;\n    this.port = port;\n  }\n\n  public String getHost() {\n    return host;\n  }\n\n  public int getPort() {\n    return port;\n  }\n\n  @Override\n  public boolean equals(Object obj) {\n    if (obj instanceof HostAndPort) {\n      HostAndPort hp = (HostAndPort) obj;\n\n      String thisHost = convertHost(host);\n      String hpHost = convertHost(hp.host);\n      return port == hp.port && thisHost.equals(hpHost);\n\n    }\n\n    return false;\n  }\n\n  @Override\n  public int hashCode() {\n    return 31 * convertHost(host).hashCode() + port;\n  }\n\n  @Override\n  public String toString() {\n    return host + \":\" + port;\n  }\n\n  private String convertHost(String host) {\n    if (host.equals(\"127.0.0.1\")) return LOCALHOST_STR;\n    else if (host.equals(\"::1\")) return LOCALHOST_STR;\n\n    return host;\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/Jedis.java",
    "content": "package redis.clients.jedis;\n\nimport java.net.URI;\nimport java.util.AbstractMap;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.Iterator;\nimport java.util.LinkedHashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.Set;\n\nimport redis.clients.jedis.BinaryClient.LIST_POSITION;\nimport redis.clients.jedis.JedisCluster.Reset;\nimport redis.clients.jedis.commands.*;\nimport redis.clients.jedis.params.geo.GeoRadiusParam;\nimport redis.clients.jedis.params.set.SetParams;\nimport redis.clients.jedis.params.sortedset.ZAddParams;\nimport redis.clients.jedis.params.sortedset.ZIncrByParams;\nimport redis.clients.util.SafeEncoder;\nimport redis.clients.util.Slowlog;\n\npublic class Jedis extends BinaryJedis implements JedisCommands, MultiKeyCommands,\n    AdvancedJedisCommands, ScriptingCommands, BasicCommands, ClusterCommands, SentinelCommands {\n\n  protected JedisPoolAbstract dataSource = null;\n\n  public Jedis() {\n    super();\n  }\n\n  public Jedis(final String host) {\n    super(host);\n  }\n\n  public Jedis(final String host, final int port) {\n    super(host, port);\n  }\n\n  public Jedis(final String host, final int port, final int timeout) {\n    super(host, port, timeout);\n  }\n\n  public Jedis(final String host, final int port, final int connectionTimeout, final int soTimeout) {\n    super(host, port, connectionTimeout, soTimeout);\n  }\n\n  public Jedis(JedisShardInfo shardInfo) {\n    super(shardInfo);\n  }\n\n  public Jedis(URI uri) {\n    super(uri);\n  }\n\n  public Jedis(final URI uri, final int timeout) {\n    super(uri, timeout);\n  }\n\n  public Jedis(final URI uri, final int connectionTimeout, final int soTimeout) {\n    super(uri, connectionTimeout, soTimeout);\n  }\n\n  /**\n   * Set the string value as value of the key. The string can't be longer than 1073741824 bytes (1\n   * GB).\n   * <p>\n   * Time complexity: O(1)\n   * @param key\n   * @param value\n   * @return Status code reply\n   */\n  @Override\n  public String set(final String key, String value) {\n    checkIsInMultiOrPipeline();\n    client.set(key, value);\n    return client.getStatusCodeReply();\n  }\n\n  /**\n   * Set the string value as value of the key. The string can't be longer than 1073741824 bytes (1\n   * GB).\n   * @param key\n   * @param value\n   * @param params NX|XX, NX -- Only set the key if it does not already exist. XX -- Only set the\n   *          key if it already exist. EX|PX, expire time units: EX = seconds; PX = milliseconds\n   * @return Status code reply\n   */\n  public String set(final String key, final String value, final SetParams params) {\n    checkIsInMultiOrPipeline();\n    client.set(key, value, params);\n    return client.getStatusCodeReply();\n  }\n\n  /**\n   * Get the value of the specified key. If the key does not exist null is returned. If the value\n   * stored at key is not a string an error is returned because GET can only handle string values.\n   * <p>\n   * Time complexity: O(1)\n   * @param key\n   * @return Bulk reply\n   */\n  @Override\n  public String get(final String key) {\n    checkIsInMultiOrPipeline();\n    client.sendCommand(Protocol.Command.GET, key);\n    return client.getBulkReply();\n  }\n\n  /**\n   * Test if the specified key exists. The command returns the number of keys existed Time\n   * complexity: O(N)\n   * @param keys\n   * @return Integer reply, specifically: an integer greater than 0 if one or more keys were removed\n   *         0 if none of the specified key existed\n   */\n  public Long exists(final String... keys) {\n    checkIsInMultiOrPipeline();\n    client.exists(keys);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Test if the specified key exists. The command returns \"1\" if the key exists, otherwise \"0\" is\n   * returned. Note that even keys set with an empty string as value will return \"1\". Time\n   * complexity: O(1)\n   * @param key\n   * @return Boolean reply, true if the key exists, otherwise false\n   */\n  @Override\n  public Boolean exists(final String key) {\n    checkIsInMultiOrPipeline();\n    client.exists(key);\n    return client.getIntegerReply() == 1;\n  }\n\n  /**\n   * Remove the specified keys. If a given key does not exist no operation is performed for this\n   * key. The command returns the number of keys removed. Time complexity: O(1)\n   * @param keys\n   * @return Integer reply, specifically: an integer greater than 0 if one or more keys were removed\n   *         0 if none of the specified key existed\n   */\n  @Override\n  public Long del(final String... keys) {\n    checkIsInMultiOrPipeline();\n    client.del(keys);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public Long del(String key) {\n    client.del(key);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Return the type of the value stored at key in form of a string. The type can be one of \"none\",\n   * \"string\", \"list\", \"set\". \"none\" is returned if the key does not exist. Time complexity: O(1)\n   * @param key\n   * @return Status code reply, specifically: \"none\" if the key does not exist \"string\" if the key\n   *         contains a String value \"list\" if the key contains a List value \"set\" if the key\n   *         contains a Set value \"zset\" if the key contains a Sorted Set value \"hash\" if the key\n   *         contains a Hash value\n   */\n  @Override\n  public String type(final String key) {\n    checkIsInMultiOrPipeline();\n    client.type(key);\n    return client.getStatusCodeReply();\n  }\n\n  /**\n   * Returns all the keys matching the glob-style pattern as space separated strings. For example if\n   * you have in the database the keys \"foo\" and \"foobar\" the command \"KEYS foo*\" will return\n   * \"foo foobar\".\n   * <p>\n   * Note that while the time complexity for this operation is O(n) the constant times are pretty\n   * low. For example Redis running on an entry level laptop can scan a 1 million keys database in\n   * 40 milliseconds. <b>Still it's better to consider this one of the slow commands that may ruin\n   * the DB performance if not used with care.</b>\n   * <p>\n   * In other words this command is intended only for debugging and special operations like creating\n   * a script to change the DB schema. Don't use it in your normal code. Use Redis Sets in order to\n   * group together a subset of objects.\n   * <p>\n   * Glob style patterns examples:\n   * <ul>\n   * <li>h?llo will match hello hallo hhllo\n   * <li>h*llo will match hllo heeeello\n   * <li>h[ae]llo will match hello and hallo, but not hillo\n   * </ul>\n   * <p>\n   * Use \\ to escape special chars if you want to match them verbatim.\n   * <p>\n   * Time complexity: O(n) (with n being the number of keys in the DB, and assuming keys and pattern\n   * of limited length)\n   * @param pattern\n   * @return Multi bulk reply\n   */\n  @Override\n  public Set<String> keys(final String pattern) {\n    checkIsInMultiOrPipeline();\n    client.keys(pattern);\n    return BuilderFactory.STRING_SET.build(client.getBinaryMultiBulkReply());\n  }\n\n  /**\n   * Return a randomly selected key from the currently selected DB.\n   * <p>\n   * Time complexity: O(1)\n   * @return Singe line reply, specifically the randomly selected key or an empty string is the\n   *         database is empty\n   */\n  @Override\n  public String randomKey() {\n    checkIsInMultiOrPipeline();\n    client.randomKey();\n    return client.getBulkReply();\n  }\n\n  /**\n   * Atomically renames the key oldkey to newkey. If the source and destination name are the same an\n   * error is returned. If newkey already exists it is overwritten.\n   * <p>\n   * Time complexity: O(1)\n   * @param oldkey\n   * @param newkey\n   * @return Status code repy\n   */\n  @Override\n  public String rename(final String oldkey, final String newkey) {\n    checkIsInMultiOrPipeline();\n    client.rename(oldkey, newkey);\n    return client.getStatusCodeReply();\n  }\n\n  /**\n   * Rename oldkey into newkey but fails if the destination key newkey already exists.\n   * <p>\n   * Time complexity: O(1)\n   * @param oldkey\n   * @param newkey\n   * @return Integer reply, specifically: 1 if the key was renamed 0 if the target key already exist\n   */\n  @Override\n  public Long renamenx(final String oldkey, final String newkey) {\n    checkIsInMultiOrPipeline();\n    client.renamenx(oldkey, newkey);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Set a timeout on the specified key. After the timeout the key will be automatically deleted by\n   * the server. A key with an associated timeout is said to be volatile in Redis terminology.\n   * <p>\n   * Voltile keys are stored on disk like the other keys, the timeout is persistent too like all the\n   * other aspects of the dataset. Saving a dataset containing expires and stopping the server does\n   * not stop the flow of time as Redis stores on disk the time when the key will no longer be\n   * available as Unix time, and not the remaining seconds.\n   * <p>\n   * Since Redis 2.1.3 you can update the value of the timeout of a key already having an expire\n   * set. It is also possible to undo the expire at all turning the key into a normal key using the\n   * {@link #persist(String) PERSIST} command.\n   * <p>\n   * Time complexity: O(1)\n   * @see <a href=\"http://redis.io/commands/expire\">Expire Command</a>\n   * @param key\n   * @param seconds\n   * @return Integer reply, specifically: 1: the timeout was set. 0: the timeout was not set since\n   *         the key already has an associated timeout (this may happen only in Redis versions &lt;\n   *         2.1.3, Redis &gt;= 2.1.3 will happily update the timeout), or the key does not exist.\n   */\n  @Override\n  public Long expire(final String key, final int seconds) {\n    checkIsInMultiOrPipeline();\n    client.expire(key, seconds);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * EXPIREAT works exctly like {@link #expire(String, int) EXPIRE} but instead to get the number of\n   * seconds representing the Time To Live of the key as a second argument (that is a relative way\n   * of specifing the TTL), it takes an absolute one in the form of a UNIX timestamp (Number of\n   * seconds elapsed since 1 Gen 1970).\n   * <p>\n   * EXPIREAT was introduced in order to implement the Append Only File persistence mode so that\n   * EXPIRE commands are automatically translated into EXPIREAT commands for the append only file.\n   * Of course EXPIREAT can also used by programmers that need a way to simply specify that a given\n   * key should expire at a given time in the future.\n   * <p>\n   * Since Redis 2.1.3 you can update the value of the timeout of a key already having an expire\n   * set. It is also possible to undo the expire at all turning the key into a normal key using the\n   * {@link #persist(String) PERSIST} command.\n   * <p>\n   * Time complexity: O(1)\n   * @see <a href=\"http://redis.io/commands/expire\">Expire Command</a>\n   * @param key\n   * @param unixTime\n   * @return Integer reply, specifically: 1: the timeout was set. 0: the timeout was not set since\n   *         the key already has an associated timeout (this may happen only in Redis versions &lt;\n   *         2.1.3, Redis &gt;= 2.1.3 will happily update the timeout), or the key does not exist.\n   */\n  @Override\n  public Long expireAt(final String key, final long unixTime) {\n    checkIsInMultiOrPipeline();\n    client.expireAt(key, unixTime);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * The TTL command returns the remaining time to live in seconds of a key that has an\n   * {@link #expire(String, int) EXPIRE} set. This introspection capability allows a Redis client to\n   * check how many seconds a given key will continue to be part of the dataset.\n   * @param key\n   * @return Integer reply, returns the remaining time to live in seconds of a key that has an\n   *         EXPIRE. In Redis 2.6 or older, if the Key does not exists or does not have an\n   *         associated expire, -1 is returned. In Redis 2.8 or newer, if the Key does not have an\n   *         associated expire, -1 is returned or if the Key does not exists, -2 is returned.\n   */\n  @Override\n  public Long ttl(final String key) {\n    checkIsInMultiOrPipeline();\n    client.ttl(key);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Move the specified key from the currently selected DB to the specified destination DB. Note\n   * that this command returns 1 only if the key was successfully moved, and 0 if the target key was\n   * already there or if the source key was not found at all, so it is possible to use MOVE as a\n   * locking primitive.\n   * @param key\n   * @param dbIndex\n   * @return Integer reply, specifically: 1 if the key was moved 0 if the key was not moved because\n   *         already present on the target DB or was not found in the current DB.\n   */\n  @Override\n  public Long move(final String key, final int dbIndex) {\n    checkIsInMultiOrPipeline();\n    client.move(key, dbIndex);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * GETSET is an atomic set this value and return the old value command. Set key to the string\n   * value and return the old value stored at key. The string can't be longer than 1073741824 bytes\n   * (1 GB).\n   * <p>\n   * Time complexity: O(1)\n   * @param key\n   * @param value\n   * @return Bulk reply\n   */\n  @Override\n  public String getSet(final String key, final String value) {\n    checkIsInMultiOrPipeline();\n    client.getSet(key, value);\n    return client.getBulkReply();\n  }\n\n  /**\n   * Get the values of all the specified keys. If one or more keys dont exist or is not of type\n   * String, a 'nil' value is returned instead of the value of the specified key, but the operation\n   * never fails.\n   * <p>\n   * Time complexity: O(1) for every key\n   * @param keys\n   * @return Multi bulk reply\n   */\n  @Override\n  public List<String> mget(final String... keys) {\n    checkIsInMultiOrPipeline();\n    client.mget(keys);\n    return client.getMultiBulkReply();\n  }\n\n  /**\n   * SETNX works exactly like {@link #set(String, String) SET} with the only difference that if the\n   * key already exists no operation is performed. SETNX actually means \"SET if Not eXists\".\n   * <p>\n   * Time complexity: O(1)\n   * @param key\n   * @param value\n   * @return Integer reply, specifically: 1 if the key was set 0 if the key was not set\n   */\n  @Override\n  public Long setnx(final String key, final String value) {\n    checkIsInMultiOrPipeline();\n    client.setnx(key, value);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * The command is exactly equivalent to the following group of commands:\n   * {@link #set(String, String) SET} + {@link #expire(String, int) EXPIRE}. The operation is\n   * atomic.\n   * <p>\n   * Time complexity: O(1)\n   * @param key\n   * @param seconds\n   * @param value\n   * @return Status code reply\n   */\n  @Override\n  public String setex(final String key, final int seconds, final String value) {\n    checkIsInMultiOrPipeline();\n    client.setex(key, seconds, value);\n    return client.getStatusCodeReply();\n  }\n\n  /**\n   * Set the the respective keys to the respective values. MSET will replace old values with new\n   * values, while {@link #msetnx(String...) MSETNX} will not perform any operation at all even if\n   * just a single key already exists.\n   * <p>\n   * Because of this semantic MSETNX can be used in order to set different keys representing\n   * different fields of an unique logic object in a way that ensures that either all the fields or\n   * none at all are set.\n   * <p>\n   * Both MSET and MSETNX are atomic operations. This means that for instance if the keys A and B\n   * are modified, another client talking to Redis can either see the changes to both A and B at\n   * once, or no modification at all.\n   * @see #msetnx(String...)\n   * @param keysvalues\n   * @return Status code reply Basically +OK as MSET can't fail\n   */\n  @Override\n  public String mset(final String... keysvalues) {\n    checkIsInMultiOrPipeline();\n    client.mset(keysvalues);\n    return client.getStatusCodeReply();\n  }\n\n  /**\n   * Set the the respective keys to the respective values. {@link #mset(String...) MSET} will\n   * replace old values with new values, while MSETNX will not perform any operation at all even if\n   * just a single key already exists.\n   * <p>\n   * Because of this semantic MSETNX can be used in order to set different keys representing\n   * different fields of an unique logic object in a way that ensures that either all the fields or\n   * none at all are set.\n   * <p>\n   * Both MSET and MSETNX are atomic operations. This means that for instance if the keys A and B\n   * are modified, another client talking to Redis can either see the changes to both A and B at\n   * once, or no modification at all.\n   * @see #mset(String...)\n   * @param keysvalues\n   * @return Integer reply, specifically: 1 if the all the keys were set 0 if no key was set (at\n   *         least one key already existed)\n   */\n  @Override\n  public Long msetnx(final String... keysvalues) {\n    checkIsInMultiOrPipeline();\n    client.msetnx(keysvalues);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * IDECRBY work just like {@link #decr(String) INCR} but instead to decrement by 1 the decrement\n   * is integer.\n   * <p>\n   * INCR commands are limited to 64 bit signed integers.\n   * <p>\n   * Note: this is actually a string operation, that is, in Redis there are not \"integer\" types.\n   * Simply the string stored at the key is parsed as a base 10 64 bit signed integer, incremented,\n   * and then converted back as a string.\n   * <p>\n   * Time complexity: O(1)\n   * @see #incr(String)\n   * @see #decr(String)\n   * @see #incrBy(String, long)\n   * @param key\n   * @param integer\n   * @return Integer reply, this commands will reply with the new value of key after the increment.\n   */\n  @Override\n  public Long decrBy(final String key, final long integer) {\n    checkIsInMultiOrPipeline();\n    client.decrBy(key, integer);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Decrement the number stored at key by one. If the key does not exist or contains a value of a\n   * wrong type, set the key to the value of \"0\" before to perform the decrement operation.\n   * <p>\n   * INCR commands are limited to 64 bit signed integers.\n   * <p>\n   * Note: this is actually a string operation, that is, in Redis there are not \"integer\" types.\n   * Simply the string stored at the key is parsed as a base 10 64 bit signed integer, incremented,\n   * and then converted back as a string.\n   * <p>\n   * Time complexity: O(1)\n   * @see #incr(String)\n   * @see #incrBy(String, long)\n   * @see #decrBy(String, long)\n   * @param key\n   * @return Integer reply, this commands will reply with the new value of key after the increment.\n   */\n  @Override\n  public Long decr(final String key) {\n    checkIsInMultiOrPipeline();\n    client.decr(key);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * INCRBY work just like {@link #incr(String) INCR} but instead to increment by 1 the increment is\n   * integer.\n   * <p>\n   * INCR commands are limited to 64 bit signed integers.\n   * <p>\n   * Note: this is actually a string operation, that is, in Redis there are not \"integer\" types.\n   * Simply the string stored at the key is parsed as a base 10 64 bit signed integer, incremented,\n   * and then converted back as a string.\n   * <p>\n   * Time complexity: O(1)\n   * @see #incr(String)\n   * @see #decr(String)\n   * @see #decrBy(String, long)\n   * @param key\n   * @param integer\n   * @return Integer reply, this commands will reply with the new value of key after the increment.\n   */\n  @Override\n  public Long incrBy(final String key, final long integer) {\n    checkIsInMultiOrPipeline();\n    client.incrBy(key, integer);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * INCRBYFLOAT\n   * <p>\n   * INCRBYFLOAT commands are limited to double precision floating point values.\n   * <p>\n   * Note: this is actually a string operation, that is, in Redis there are not \"double\" types.\n   * Simply the string stored at the key is parsed as a base double precision floating point value,\n   * incremented, and then converted back as a string. There is no DECRYBYFLOAT but providing a\n   * negative value will work as expected.\n   * <p>\n   * Time complexity: O(1)\n   * @param key\n   * @param value\n   * @return Double reply, this commands will reply with the new value of key after the increment.\n   */\n  @Override\n  public Double incrByFloat(final String key, final double value) {\n    checkIsInMultiOrPipeline();\n    client.incrByFloat(key, value);\n    String dval = client.getBulkReply();\n    return (dval != null ? new Double(dval) : null);\n  }\n\n  /**\n   * Increment the number stored at key by one. If the key does not exist or contains a value of a\n   * wrong type, set the key to the value of \"0\" before to perform the increment operation.\n   * <p>\n   * INCR commands are limited to 64 bit signed integers.\n   * <p>\n   * Note: this is actually a string operation, that is, in Redis there are not \"integer\" types.\n   * Simply the string stored at the key is parsed as a base 10 64 bit signed integer, incremented,\n   * and then converted back as a string.\n   * <p>\n   * Time complexity: O(1)\n   * @see #incrBy(String, long)\n   * @see #decr(String)\n   * @see #decrBy(String, long)\n   * @param key\n   * @return Integer reply, this commands will reply with the new value of key after the increment.\n   */\n  @Override\n  public Long incr(final String key) {\n    checkIsInMultiOrPipeline();\n    client.incr(key);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * If the key already exists and is a string, this command appends the provided value at the end\n   * of the string. If the key does not exist it is created and set as an empty string, so APPEND\n   * will be very similar to SET in this special case.\n   * <p>\n   * Time complexity: O(1). The amortized time complexity is O(1) assuming the appended value is\n   * small and the already present value is of any size, since the dynamic string library used by\n   * Redis will double the free space available on every reallocation.\n   * @param key\n   * @param value\n   * @return Integer reply, specifically the total length of the string after the append operation.\n   */\n  @Override\n  public Long append(final String key, final String value) {\n    checkIsInMultiOrPipeline();\n    client.append(key, value);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Return a subset of the string from offset start to offset end (both offsets are inclusive).\n   * Negative offsets can be used in order to provide an offset starting from the end of the string.\n   * So -1 means the last char, -2 the penultimate and so forth.\n   * <p>\n   * The function handles out of range requests without raising an error, but just limiting the\n   * resulting range to the actual length of the string.\n   * <p>\n   * Time complexity: O(start+n) (with start being the start index and n the total length of the\n   * requested range). Note that the lookup part of this command is O(1) so for small strings this\n   * is actually an O(1) command.\n   * @param key\n   * @param start\n   * @param end\n   * @return Bulk reply\n   */\n  @Override\n  public String substr(final String key, final int start, final int end) {\n    checkIsInMultiOrPipeline();\n    client.substr(key, start, end);\n    return client.getBulkReply();\n  }\n\n  /**\n   * Set the specified hash field to the specified value.\n   * <p>\n   * If key does not exist, a new key holding a hash is created.\n   * <p>\n   * <b>Time complexity:</b> O(1)\n   * @param key\n   * @param field\n   * @param value\n   * @return If the field already exists, and the HSET just produced an update of the value, 0 is\n   *         returned, otherwise if a new field is created 1 is returned.\n   */\n  @Override\n  public Long hset(final String key, final String field, final String value) {\n    checkIsInMultiOrPipeline();\n    client.hset(key, field, value);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * If key holds a hash, retrieve the value associated to the specified field.\n   * <p>\n   * If the field is not found or the key does not exist, a special 'nil' value is returned.\n   * <p>\n   * <b>Time complexity:</b> O(1)\n   * @param key\n   * @param field\n   * @return Bulk reply\n   */\n  @Override\n  public String hget(final String key, final String field) {\n    checkIsInMultiOrPipeline();\n    client.hget(key, field);\n    return client.getBulkReply();\n  }\n\n  /**\n   * Set the specified hash field to the specified value if the field not exists. <b>Time\n   * complexity:</b> O(1)\n   * @param key\n   * @param field\n   * @param value\n   * @return If the field already exists, 0 is returned, otherwise if a new field is created 1 is\n   *         returned.\n   */\n  @Override\n  public Long hsetnx(final String key, final String field, final String value) {\n    checkIsInMultiOrPipeline();\n    client.hsetnx(key, field, value);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Set the respective fields to the respective values. HMSET replaces old values with new values.\n   * <p>\n   * If key does not exist, a new key holding a hash is created.\n   * <p>\n   * <b>Time complexity:</b> O(N) (with N being the number of fields)\n   * @param key\n   * @param hash\n   * @return Return OK or Exception if hash is empty\n   */\n  @Override\n  public String hmset(final String key, final Map<String, String> hash) {\n    checkIsInMultiOrPipeline();\n    client.hmset(key, hash);\n    return client.getStatusCodeReply();\n  }\n\n  /**\n   * Retrieve the values associated to the specified fields.\n   * <p>\n   * If some of the specified fields do not exist, nil values are returned. Non existing keys are\n   * considered like empty hashes.\n   * <p>\n   * <b>Time complexity:</b> O(N) (with N being the number of fields)\n   * @param key\n   * @param fields\n   * @return Multi Bulk Reply specifically a list of all the values associated with the specified\n   *         fields, in the same order of the request.\n   */\n  @Override\n  public List<String> hmget(final String key, final String... fields) {\n    checkIsInMultiOrPipeline();\n    client.hmget(key, fields);\n    return client.getMultiBulkReply();\n  }\n\n  /**\n   * Increment the number stored at field in the hash at key by value. If key does not exist, a new\n   * key holding a hash is created. If field does not exist or holds a string, the value is set to 0\n   * before applying the operation. Since the value argument is signed you can use this command to\n   * perform both increments and decrements.\n   * <p>\n   * The range of values supported by HINCRBY is limited to 64 bit signed integers.\n   * <p>\n   * <b>Time complexity:</b> O(1)\n   * @param key\n   * @param field\n   * @param value\n   * @return Integer reply The new value at field after the increment operation.\n   */\n  @Override\n  public Long hincrBy(final String key, final String field, final long value) {\n    checkIsInMultiOrPipeline();\n    client.hincrBy(key, field, value);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Increment the number stored at field in the hash at key by a double precision floating point\n   * value. If key does not exist, a new key holding a hash is created. If field does not exist or\n   * holds a string, the value is set to 0 before applying the operation. Since the value argument\n   * is signed you can use this command to perform both increments and decrements.\n   * <p>\n   * The range of values supported by HINCRBYFLOAT is limited to double precision floating point\n   * values.\n   * <p>\n   * <b>Time complexity:</b> O(1)\n   * @param key\n   * @param field\n   * @param value\n   * @return Double precision floating point reply The new value at field after the increment\n   *         operation.\n   */\n  @Override\n  public Double hincrByFloat(final String key, final String field, final double value) {\n    checkIsInMultiOrPipeline();\n    client.hincrByFloat(key, field, value);\n    final String dval = client.getBulkReply();\n    return (dval != null ? new Double(dval) : null);\n  }\n\n  /**\n   * Test for existence of a specified field in a hash. <b>Time complexity:</b> O(1)\n   * @param key\n   * @param field\n   * @return Return 1 if the hash stored at key contains the specified field. Return 0 if the key is\n   *         not found or the field is not present.\n   */\n  @Override\n  public Boolean hexists(final String key, final String field) {\n    checkIsInMultiOrPipeline();\n    client.hexists(key, field);\n    return client.getIntegerReply() == 1;\n  }\n\n  /**\n   * Remove the specified field from an hash stored at key.\n   * <p>\n   * <b>Time complexity:</b> O(1)\n   * @param key\n   * @param fields\n   * @return If the field was present in the hash it is deleted and 1 is returned, otherwise 0 is\n   *         returned and no operation is performed.\n   */\n  @Override\n  public Long hdel(final String key, final String... fields) {\n    checkIsInMultiOrPipeline();\n    client.hdel(key, fields);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Return the number of items in a hash.\n   * <p>\n   * <b>Time complexity:</b> O(1)\n   * @param key\n   * @return The number of entries (fields) contained in the hash stored at key. If the specified\n   *         key does not exist, 0 is returned assuming an empty hash.\n   */\n  @Override\n  public Long hlen(final String key) {\n    checkIsInMultiOrPipeline();\n    client.hlen(key);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Return all the fields in a hash.\n   * <p>\n   * <b>Time complexity:</b> O(N), where N is the total number of entries\n   * @param key\n   * @return All the fields names contained into a hash.\n   */\n  @Override\n  public Set<String> hkeys(final String key) {\n    checkIsInMultiOrPipeline();\n    client.hkeys(key);\n    return BuilderFactory.STRING_SET.build(client.getBinaryMultiBulkReply());\n  }\n\n  /**\n   * Return all the values in a hash.\n   * <p>\n   * <b>Time complexity:</b> O(N), where N is the total number of entries\n   * @param key\n   * @return All the fields values contained into a hash.\n   */\n  @Override\n  public List<String> hvals(final String key) {\n    checkIsInMultiOrPipeline();\n    client.hvals(key);\n    final List<String> lresult = client.getMultiBulkReply();\n    return lresult;\n  }\n\n  /**\n   * Return all the fields and associated values in a hash.\n   * <p>\n   * <b>Time complexity:</b> O(N), where N is the total number of entries\n   * @param key\n   * @return All the fields and values contained into a hash.\n   */\n  @Override\n  public Map<String, String> hgetAll(final String key) {\n    checkIsInMultiOrPipeline();\n    client.hgetAll(key);\n    return BuilderFactory.STRING_MAP.build(client.getBinaryMultiBulkReply());\n  }\n\n  /**\n   * Add the string value to the head (LPUSH) or tail (RPUSH) of the list stored at key. If the key\n   * does not exist an empty list is created just before the append operation. If the key exists but\n   * is not a List an error is returned.\n   * <p>\n   * Time complexity: O(1)\n   * @param key\n   * @param strings\n   * @return Integer reply, specifically, the number of elements inside the list after the push\n   *         operation.\n   */\n  @Override\n  public Long rpush(final String key, final String... strings) {\n    checkIsInMultiOrPipeline();\n    client.rpush(key, strings);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Add the string value to the head (LPUSH) or tail (RPUSH) of the list stored at key. If the key\n   * does not exist an empty list is created just before the append operation. If the key exists but\n   * is not a List an error is returned.\n   * <p>\n   * Time complexity: O(1)\n   * @param key\n   * @param strings\n   * @return Integer reply, specifically, the number of elements inside the list after the push\n   *         operation.\n   */\n  @Override\n  public Long lpush(final String key, final String... strings) {\n    checkIsInMultiOrPipeline();\n    client.lpush(key, strings);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Return the length of the list stored at the specified key. If the key does not exist zero is\n   * returned (the same behaviour as for empty lists). If the value stored at key is not a list an\n   * error is returned.\n   * <p>\n   * Time complexity: O(1)\n   * @param key\n   * @return The length of the list.\n   */\n  @Override\n  public Long llen(final String key) {\n    checkIsInMultiOrPipeline();\n    client.llen(key);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Return the specified elements of the list stored at the specified key. Start and end are\n   * zero-based indexes. 0 is the first element of the list (the list head), 1 the next element and\n   * so on.\n   * <p>\n   * For example LRANGE foobar 0 2 will return the first three elements of the list.\n   * <p>\n   * start and end can also be negative numbers indicating offsets from the end of the list. For\n   * example -1 is the last element of the list, -2 the penultimate element and so on.\n   * <p>\n   * <b>Consistency with range functions in various programming languages</b>\n   * <p>\n   * Note that if you have a list of numbers from 0 to 100, LRANGE 0 10 will return 11 elements,\n   * that is, rightmost item is included. This may or may not be consistent with behavior of\n   * range-related functions in your programming language of choice (think Ruby's Range.new,\n   * Array#slice or Python's range() function).\n   * <p>\n   * LRANGE behavior is consistent with one of Tcl.\n   * <p>\n   * <b>Out-of-range indexes</b>\n   * <p>\n   * Indexes out of range will not produce an error: if start is over the end of the list, or start\n   * &gt; end, an empty list is returned. If end is over the end of the list Redis will threat it\n   * just like the last element of the list.\n   * <p>\n   * Time complexity: O(start+n) (with n being the length of the range and start being the start\n   * offset)\n   * @param key\n   * @param start\n   * @param end\n   * @return Multi bulk reply, specifically a list of elements in the specified range.\n   */\n  @Override\n  public List<String> lrange(final String key, final long start, final long end) {\n    checkIsInMultiOrPipeline();\n    client.lrange(key, start, end);\n    return client.getMultiBulkReply();\n  }\n\n  /**\n   * Trim an existing list so that it will contain only the specified range of elements specified.\n   * Start and end are zero-based indexes. 0 is the first element of the list (the list head), 1 the\n   * next element and so on.\n   * <p>\n   * For example LTRIM foobar 0 2 will modify the list stored at foobar key so that only the first\n   * three elements of the list will remain.\n   * <p>\n   * start and end can also be negative numbers indicating offsets from the end of the list. For\n   * example -1 is the last element of the list, -2 the penultimate element and so on.\n   * <p>\n   * Indexes out of range will not produce an error: if start is over the end of the list, or start\n   * &gt; end, an empty list is left as value. If end over the end of the list Redis will threat it\n   * just like the last element of the list.\n   * <p>\n   * Hint: the obvious use of LTRIM is together with LPUSH/RPUSH. For example:\n   * <p>\n   * {@code lpush(\"mylist\", \"someelement\"); ltrim(\"mylist\", 0, 99); * }\n   * <p>\n   * The above two commands will push elements in the list taking care that the list will not grow\n   * without limits. This is very useful when using Redis to store logs for example. It is important\n   * to note that when used in this way LTRIM is an O(1) operation because in the average case just\n   * one element is removed from the tail of the list.\n   * <p>\n   * Time complexity: O(n) (with n being len of list - len of range)\n   * @param key\n   * @param start\n   * @param end\n   * @return Status code reply\n   */\n  @Override\n  public String ltrim(final String key, final long start, final long end) {\n    checkIsInMultiOrPipeline();\n    client.ltrim(key, start, end);\n    return client.getStatusCodeReply();\n  }\n\n  /**\n   * Return the specified element of the list stored at the specified key. 0 is the first element, 1\n   * the second and so on. Negative indexes are supported, for example -1 is the last element, -2\n   * the penultimate and so on.\n   * <p>\n   * If the value stored at key is not of list type an error is returned. If the index is out of\n   * range a 'nil' reply is returned.\n   * <p>\n   * Note that even if the average time complexity is O(n) asking for the first or the last element\n   * of the list is O(1).\n   * <p>\n   * Time complexity: O(n) (with n being the length of the list)\n   * @param key\n   * @param index\n   * @return Bulk reply, specifically the requested element\n   */\n  @Override\n  public String lindex(final String key, final long index) {\n    checkIsInMultiOrPipeline();\n    client.lindex(key, index);\n    return client.getBulkReply();\n  }\n\n  /**\n   * Set a new value as the element at index position of the List at key.\n   * <p>\n   * Out of range indexes will generate an error.\n   * <p>\n   * Similarly to other list commands accepting indexes, the index can be negative to access\n   * elements starting from the end of the list. So -1 is the last element, -2 is the penultimate,\n   * and so forth.\n   * <p>\n   * <b>Time complexity:</b>\n   * <p>\n   * O(N) (with N being the length of the list), setting the first or last elements of the list is\n   * O(1).\n   * @see #lindex(String, long)\n   * @param key\n   * @param index\n   * @param value\n   * @return Status code reply\n   */\n  @Override\n  public String lset(final String key, final long index, final String value) {\n    checkIsInMultiOrPipeline();\n    client.lset(key, index, value);\n    return client.getStatusCodeReply();\n  }\n\n  /**\n   * Remove the first count occurrences of the value element from the list. If count is zero all the\n   * elements are removed. If count is negative elements are removed from tail to head, instead to\n   * go from head to tail that is the normal behaviour. So for example LREM with count -2 and hello\n   * as value to remove against the list (a,b,c,hello,x,hello,hello) will lave the list\n   * (a,b,c,hello,x). The number of removed elements is returned as an integer, see below for more\n   * information about the returned value. Note that non existing keys are considered like empty\n   * lists by LREM, so LREM against non existing keys will always return 0.\n   * <p>\n   * Time complexity: O(N) (with N being the length of the list)\n   * @param key\n   * @param count\n   * @param value\n   * @return Integer Reply, specifically: The number of removed elements if the operation succeeded\n   */\n  @Override\n  public Long lrem(final String key, final long count, final String value) {\n    checkIsInMultiOrPipeline();\n    client.lrem(key, count, value);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Atomically return and remove the first (LPOP) or last (RPOP) element of the list. For example\n   * if the list contains the elements \"a\",\"b\",\"c\" LPOP will return \"a\" and the list will become\n   * \"b\",\"c\".\n   * <p>\n   * If the key does not exist or the list is already empty the special value 'nil' is returned.\n   * @see #rpop(String)\n   * @param key\n   * @return Bulk reply\n   */\n  @Override\n  public String lpop(final String key) {\n    checkIsInMultiOrPipeline();\n    client.lpop(key);\n    return client.getBulkReply();\n  }\n\n  /**\n   * Atomically return and remove the first (LPOP) or last (RPOP) element of the list. For example\n   * if the list contains the elements \"a\",\"b\",\"c\" RPOP will return \"c\" and the list will become\n   * \"a\",\"b\".\n   * <p>\n   * If the key does not exist or the list is already empty the special value 'nil' is returned.\n   * @see #lpop(String)\n   * @param key\n   * @return Bulk reply\n   */\n  @Override\n  public String rpop(final String key) {\n    checkIsInMultiOrPipeline();\n    client.rpop(key);\n    return client.getBulkReply();\n  }\n\n  /**\n   * Atomically return and remove the last (tail) element of the srckey list, and push the element\n   * as the first (head) element of the dstkey list. For example if the source list contains the\n   * elements \"a\",\"b\",\"c\" and the destination list contains the elements \"foo\",\"bar\" after an\n   * RPOPLPUSH command the content of the two lists will be \"a\",\"b\" and \"c\",\"foo\",\"bar\".\n   * <p>\n   * If the key does not exist or the list is already empty the special value 'nil' is returned. If\n   * the srckey and dstkey are the same the operation is equivalent to removing the last element\n   * from the list and pusing it as first element of the list, so it's a \"list rotation\" command.\n   * <p>\n   * Time complexity: O(1)\n   * @param srckey\n   * @param dstkey\n   * @return Bulk reply\n   */\n  @Override\n  public String rpoplpush(final String srckey, final String dstkey) {\n    checkIsInMultiOrPipeline();\n    client.rpoplpush(srckey, dstkey);\n    return client.getBulkReply();\n  }\n\n  /**\n   * Add the specified member to the set value stored at key. If member is already a member of the\n   * set no operation is performed. If key does not exist a new set with the specified member as\n   * sole member is created. If the key exists but does not hold a set value an error is returned.\n   * <p>\n   * Time complexity O(1)\n   * @param key\n   * @param members\n   * @return Integer reply, specifically: 1 if the new element was added 0 if the element was\n   *         already a member of the set\n   */\n  @Override\n  public Long sadd(final String key, final String... members) {\n    checkIsInMultiOrPipeline();\n    client.sadd(key, members);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Return all the members (elements) of the set value stored at key. This is just syntax glue for\n   * {@link #sinter(String...) SINTER}.\n   * <p>\n   * Time complexity O(N)\n   * @param key\n   * @return Multi bulk reply\n   */\n  @Override\n  public Set<String> smembers(final String key) {\n    checkIsInMultiOrPipeline();\n    client.smembers(key);\n    final List<String> members = client.getMultiBulkReply();\n    if (members == null) {\n      return null;\n    }\n    return SetFromList.of(members);\n  }\n\n  /**\n   * Remove the specified member from the set value stored at key. If member was not a member of the\n   * set no operation is performed. If key does not hold a set value an error is returned.\n   * <p>\n   * Time complexity O(1)\n   * @param key\n   * @param members\n   * @return Integer reply, specifically: 1 if the new element was removed 0 if the new element was\n   *         not a member of the set\n   */\n  @Override\n  public Long srem(final String key, final String... members) {\n    checkIsInMultiOrPipeline();\n    client.srem(key, members);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Remove a random element from a Set returning it as return value. If the Set is empty or the key\n   * does not exist, a nil object is returned.\n   * <p>\n   * The {@link #srandmember(String)} command does a similar work but the returned element is not\n   * removed from the Set.\n   * <p>\n   * Time complexity O(1)\n   * @param key\n   * @return Bulk reply\n   */\n  @Override\n  public String spop(final String key) {\n    checkIsInMultiOrPipeline();\n    client.spop(key);\n    return client.getBulkReply();\n  }\n\n  @Override\n  public Set<String> spop(final String key, final long count) {\n    checkIsInMultiOrPipeline();\n    client.spop(key, count);\n    final List<String> members = client.getMultiBulkReply();\n    if (members == null) {\n      return null;\n    }\n    return SetFromList.of(members);\n  }\n\n  /**\n   * Move the specifided member from the set at srckey to the set at dstkey. This operation is\n   * atomic, in every given moment the element will appear to be in the source or destination set\n   * for accessing clients.\n   * <p>\n   * If the source set does not exist or does not contain the specified element no operation is\n   * performed and zero is returned, otherwise the element is removed from the source set and added\n   * to the destination set. On success one is returned, even if the element was already present in\n   * the destination set.\n   * <p>\n   * An error is raised if the source or destination keys contain a non Set value.\n   * <p>\n   * Time complexity O(1)\n   * @param srckey\n   * @param dstkey\n   * @param member\n   * @return Integer reply, specifically: 1 if the element was moved 0 if the element was not found\n   *         on the first set and no operation was performed\n   */\n  @Override\n  public Long smove(final String srckey, final String dstkey, final String member) {\n    checkIsInMultiOrPipeline();\n    client.smove(srckey, dstkey, member);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Return the set cardinality (number of elements). If the key does not exist 0 is returned, like\n   * for empty sets.\n   * @param key\n   * @return Integer reply, specifically: the cardinality (number of elements) of the set as an\n   *         integer.\n   */\n  @Override\n  public Long scard(final String key) {\n    checkIsInMultiOrPipeline();\n    client.scard(key);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Return 1 if member is a member of the set stored at key, otherwise 0 is returned.\n   * <p>\n   * Time complexity O(1)\n   * @param key\n   * @param member\n   * @return Integer reply, specifically: 1 if the element is a member of the set 0 if the element\n   *         is not a member of the set OR if the key does not exist\n   */\n  @Override\n  public Boolean sismember(final String key, final String member) {\n    checkIsInMultiOrPipeline();\n    client.sismember(key, member);\n    return client.getIntegerReply() == 1;\n  }\n\n  /**\n   * Return the members of a set resulting from the intersection of all the sets hold at the\n   * specified keys. Like in {@link #lrange(String, long, long) LRANGE} the result is sent to the\n   * client as a multi-bulk reply (see the protocol specification for more information). If just a\n   * single key is specified, then this command produces the same result as\n   * {@link #smembers(String) SMEMBERS}. Actually SMEMBERS is just syntax sugar for SINTER.\n   * <p>\n   * Non existing keys are considered like empty sets, so if one of the keys is missing an empty set\n   * is returned (since the intersection with an empty set always is an empty set).\n   * <p>\n   * Time complexity O(N*M) worst case where N is the cardinality of the smallest set and M the\n   * number of sets\n   * @param keys\n   * @return Multi bulk reply, specifically the list of common elements.\n   */\n  @Override\n  public Set<String> sinter(final String... keys) {\n    checkIsInMultiOrPipeline();\n    client.sinter(keys);\n    final List<String> members = client.getMultiBulkReply();\n    if (members == null) {\n      return null;\n    }\n    return SetFromList.of(members);\n  }\n\n  /**\n   * This commnad works exactly like {@link #sinter(String...) SINTER} but instead of being returned\n   * the resulting set is sotred as dstkey.\n   * <p>\n   * Time complexity O(N*M) worst case where N is the cardinality of the smallest set and M the\n   * number of sets\n   * @param dstkey\n   * @param keys\n   * @return Status code reply\n   */\n  @Override\n  public Long sinterstore(final String dstkey, final String... keys) {\n    checkIsInMultiOrPipeline();\n    client.sinterstore(dstkey, keys);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Return the members of a set resulting from the union of all the sets hold at the specified\n   * keys. Like in {@link #lrange(String, long, long) LRANGE} the result is sent to the client as a\n   * multi-bulk reply (see the protocol specification for more information). If just a single key is\n   * specified, then this command produces the same result as {@link #smembers(String) SMEMBERS}.\n   * <p>\n   * Non existing keys are considered like empty sets.\n   * <p>\n   * Time complexity O(N) where N is the total number of elements in all the provided sets\n   * @param keys\n   * @return Multi bulk reply, specifically the list of common elements.\n   */\n  @Override\n  public Set<String> sunion(final String... keys) {\n    checkIsInMultiOrPipeline();\n    client.sunion(keys);\n    final List<String> members = client.getMultiBulkReply();\n    if (members == null) {\n      return null;\n    }\n    return SetFromList.of(members);\n  }\n\n  /**\n   * This command works exactly like {@link #sunion(String...) SUNION} but instead of being returned\n   * the resulting set is stored as dstkey. Any existing value in dstkey will be over-written.\n   * <p>\n   * Time complexity O(N) where N is the total number of elements in all the provided sets\n   * @param dstkey\n   * @param keys\n   * @return Status code reply\n   */\n  @Override\n  public Long sunionstore(final String dstkey, final String... keys) {\n    checkIsInMultiOrPipeline();\n    client.sunionstore(dstkey, keys);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Return the difference between the Set stored at key1 and all the Sets key2, ..., keyN\n   * <p>\n   * <b>Example:</b>\n   * \n   * <pre>\n   * key1 = [x, a, b, c]\n   * key2 = [c]\n   * key3 = [a, d]\n   * SDIFF key1,key2,key3 =&gt; [x, b]\n   * </pre>\n   * \n   * Non existing keys are considered like empty sets.\n   * <p>\n   * <b>Time complexity:</b>\n   * <p>\n   * O(N) with N being the total number of elements of all the sets\n   * @param keys\n   * @return Return the members of a set resulting from the difference between the first set\n   *         provided and all the successive sets.\n   */\n  @Override\n  public Set<String> sdiff(final String... keys) {\n    checkIsInMultiOrPipeline();\n    client.sdiff(keys);\n    return BuilderFactory.STRING_SET.build(client.getBinaryMultiBulkReply());\n  }\n\n  /**\n   * This command works exactly like {@link #sdiff(String...) SDIFF} but instead of being returned\n   * the resulting set is stored in dstkey.\n   * @param dstkey\n   * @param keys\n   * @return Status code reply\n   */\n  @Override\n  public Long sdiffstore(final String dstkey, final String... keys) {\n    checkIsInMultiOrPipeline();\n    client.sdiffstore(dstkey, keys);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Return a random element from a Set, without removing the element. If the Set is empty or the\n   * key does not exist, a nil object is returned.\n   * <p>\n   * The SPOP command does a similar work but the returned element is popped (removed) from the Set.\n   * <p>\n   * Time complexity O(1)\n   * @param key\n   * @return Bulk reply\n   */\n  @Override\n  public String srandmember(final String key) {\n    checkIsInMultiOrPipeline();\n    client.srandmember(key);\n    return client.getBulkReply();\n  }\n\n  @Override\n  public List<String> srandmember(final String key, final int count) {\n    checkIsInMultiOrPipeline();\n    client.srandmember(key, count);\n    return client.getMultiBulkReply();\n  }\n\n  /**\n   * Add the specified member having the specifeid score to the sorted set stored at key. If member\n   * is already a member of the sorted set the score is updated, and the element reinserted in the\n   * right position to ensure sorting. If key does not exist a new sorted set with the specified\n   * member as sole member is crated. If the key exists but does not hold a sorted set value an\n   * error is returned.\n   * <p>\n   * The score value can be the string representation of a double precision floating point number.\n   * <p>\n   * Time complexity O(log(N)) with N being the number of elements in the sorted set\n   * @param key\n   * @param score\n   * @param member\n   * @return Integer reply, specifically: 1 if the new element was added 0 if the element was\n   *         already a member of the sorted set and the score was updated\n   */\n  @Override\n  public Long zadd(final String key, final double score, final String member) {\n    checkIsInMultiOrPipeline();\n    client.zadd(key, score, member);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public Long zadd(final String key, final double score, final String member,\n      final ZAddParams params) {\n    checkIsInMultiOrPipeline();\n    client.zadd(key, score, member, params);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public Long zadd(final String key, final Map<String, Double> scoreMembers) {\n    checkIsInMultiOrPipeline();\n    client.zadd(key, scoreMembers);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public Long zadd(String key, Map<String, Double> scoreMembers, ZAddParams params) {\n    checkIsInMultiOrPipeline();\n    client.zadd(key, scoreMembers, params);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public Set<String> zrange(final String key, final long start, final long end) {\n    checkIsInMultiOrPipeline();\n    client.zrange(key, start, end);\n    final List<String> members = client.getMultiBulkReply();\n    if (members == null) {\n      return null;\n    }\n    return SetFromList.of(members);\n  }\n\n  /**\n   * Remove the specified member from the sorted set value stored at key. If member was not a member\n   * of the set no operation is performed. If key does not not hold a set value an error is\n   * returned.\n   * <p>\n   * Time complexity O(log(N)) with N being the number of elements in the sorted set\n   * @param key\n   * @param members\n   * @return Integer reply, specifically: 1 if the new element was removed 0 if the new element was\n   *         not a member of the set\n   */\n  @Override\n  public Long zrem(final String key, final String... members) {\n    checkIsInMultiOrPipeline();\n    client.zrem(key, members);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * If member already exists in the sorted set adds the increment to its score and updates the\n   * position of the element in the sorted set accordingly. If member does not already exist in the\n   * sorted set it is added with increment as score (that is, like if the previous score was\n   * virtually zero). If key does not exist a new sorted set with the specified member as sole\n   * member is crated. If the key exists but does not hold a sorted set value an error is returned.\n   * <p>\n   * The score value can be the string representation of a double precision floating point number.\n   * It's possible to provide a negative value to perform a decrement.\n   * <p>\n   * For an introduction to sorted sets check the Introduction to Redis data types page.\n   * <p>\n   * Time complexity O(log(N)) with N being the number of elements in the sorted set\n   * @param key\n   * @param score\n   * @param member\n   * @return The new score\n   */\n  @Override\n  public Double zincrby(final String key, final double score, final String member) {\n    checkIsInMultiOrPipeline();\n    client.zincrby(key, score, member);\n    String newscore = client.getBulkReply();\n    return Double.valueOf(newscore);\n  }\n\n  @Override\n  public Double zincrby(String key, double score, String member, ZIncrByParams params) {\n    checkIsInMultiOrPipeline();\n    client.zincrby(key, score, member, params);\n    String newscore = client.getBulkReply();\n\n    // with nx / xx options it could return null now\n    if (newscore == null) return null;\n\n    return Double.valueOf(newscore);\n  }\n\n  /**\n   * Return the rank (or index) or member in the sorted set at key, with scores being ordered from\n   * low to high.\n   * <p>\n   * When the given member does not exist in the sorted set, the special value 'nil' is returned.\n   * The returned rank (or index) of the member is 0-based for both commands.\n   * <p>\n   * <b>Time complexity:</b>\n   * <p>\n   * O(log(N))\n   * @see #zrevrank(String, String)\n   * @param key\n   * @param member\n   * @return Integer reply or a nil bulk reply, specifically: the rank of the element as an integer\n   *         reply if the element exists. A nil bulk reply if there is no such element.\n   */\n  @Override\n  public Long zrank(final String key, final String member) {\n    checkIsInMultiOrPipeline();\n    client.zrank(key, member);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Return the rank (or index) or member in the sorted set at key, with scores being ordered from\n   * high to low.\n   * <p>\n   * When the given member does not exist in the sorted set, the special value 'nil' is returned.\n   * The returned rank (or index) of the member is 0-based for both commands.\n   * <p>\n   * <b>Time complexity:</b>\n   * <p>\n   * O(log(N))\n   * @see #zrank(String, String)\n   * @param key\n   * @param member\n   * @return Integer reply or a nil bulk reply, specifically: the rank of the element as an integer\n   *         reply if the element exists. A nil bulk reply if there is no such element.\n   */\n  @Override\n  public Long zrevrank(final String key, final String member) {\n    checkIsInMultiOrPipeline();\n    client.zrevrank(key, member);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public Set<String> zrevrange(final String key, final long start, final long end) {\n    checkIsInMultiOrPipeline();\n    client.zrevrange(key, start, end);\n    final List<String> members = client.getMultiBulkReply();\n    if (members == null) {\n      return null;\n    }\n    return SetFromList.of(members);\n  }\n\n  @Override\n  public Set<Tuple> zrangeWithScores(final String key, final long start, final long end) {\n    checkIsInMultiOrPipeline();\n    client.zrangeWithScores(key, start, end);\n    return getTupledSet();\n  }\n\n  @Override\n  public Set<Tuple> zrevrangeWithScores(final String key, final long start, final long end) {\n    checkIsInMultiOrPipeline();\n    client.zrevrangeWithScores(key, start, end);\n    return getTupledSet();\n  }\n\n  /**\n   * Return the sorted set cardinality (number of elements). If the key does not exist 0 is\n   * returned, like for empty sorted sets.\n   * <p>\n   * Time complexity O(1)\n   * @param key\n   * @return the cardinality (number of elements) of the set as an integer.\n   */\n  @Override\n  public Long zcard(final String key) {\n    checkIsInMultiOrPipeline();\n    client.zcard(key);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Return the score of the specified element of the sorted set at key. If the specified element\n   * does not exist in the sorted set, or the key does not exist at all, a special 'nil' value is\n   * returned.\n   * <p>\n   * <b>Time complexity:</b> O(1)\n   * @param key\n   * @param member\n   * @return the score\n   */\n  @Override\n  public Double zscore(final String key, final String member) {\n    checkIsInMultiOrPipeline();\n    client.zscore(key, member);\n    final String score = client.getBulkReply();\n    return (score != null ? new Double(score) : null);\n  }\n\n  @Override\n  public String watch(final String... keys) {\n    client.watch(keys);\n    return client.getStatusCodeReply();\n  }\n\n  /**\n   * Sort a Set or a List.\n   * <p>\n   * Sort the elements contained in the List, Set, or Sorted Set value at key. By default sorting is\n   * numeric with elements being compared as double precision floating point numbers. This is the\n   * simplest form of SORT.\n   * @see #sort(String, String)\n   * @see #sort(String, SortingParams)\n   * @see #sort(String, SortingParams, String)\n   * @param key\n   * @return Assuming the Set/List at key contains a list of numbers, the return value will be the\n   *         list of numbers ordered from the smallest to the biggest number.\n   */\n  @Override\n  public List<String> sort(final String key) {\n    checkIsInMultiOrPipeline();\n    client.sort(key);\n    return client.getMultiBulkReply();\n  }\n\n  /**\n   * Sort a Set or a List accordingly to the specified parameters.\n   * <p>\n   * <b>examples:</b>\n   * <p>\n   * Given are the following sets and key/values:\n   * \n   * <pre>\n   * x = [1, 2, 3]\n   * y = [a, b, c]\n   * \n   * k1 = z\n   * k2 = y\n   * k3 = x\n   * \n   * w1 = 9\n   * w2 = 8\n   * w3 = 7\n   * </pre>\n   * \n   * Sort Order:\n   * \n   * <pre>\n   * sort(x) or sort(x, sp.asc())\n   * -&gt; [1, 2, 3]\n   * \n   * sort(x, sp.desc())\n   * -&gt; [3, 2, 1]\n   * \n   * sort(y)\n   * -&gt; [c, a, b]\n   * \n   * sort(y, sp.alpha())\n   * -&gt; [a, b, c]\n   * \n   * sort(y, sp.alpha().desc())\n   * -&gt; [c, a, b]\n   * </pre>\n   * \n   * Limit (e.g. for Pagination):\n   * \n   * <pre>\n   * sort(x, sp.limit(0, 2))\n   * -&gt; [1, 2]\n   * \n   * sort(y, sp.alpha().desc().limit(1, 2))\n   * -&gt; [b, a]\n   * </pre>\n   * \n   * Sorting by external keys:\n   * \n   * <pre>\n   * sort(x, sb.by(w*))\n   * -&gt; [3, 2, 1]\n   * \n   * sort(x, sb.by(w*).desc())\n   * -&gt; [1, 2, 3]\n   * </pre>\n   * \n   * Getting external keys:\n   * \n   * <pre>\n   * sort(x, sp.by(w*).get(k*))\n   * -&gt; [x, y, z]\n   * \n   * sort(x, sp.by(w*).get(#).get(k*))\n   * -&gt; [3, x, 2, y, 1, z]\n   * </pre>\n   * @see #sort(String)\n   * @see #sort(String, SortingParams, String)\n   * @param key\n   * @param sortingParameters\n   * @return a list of sorted elements.\n   */\n  @Override\n  public List<String> sort(final String key, final SortingParams sortingParameters) {\n    checkIsInMultiOrPipeline();\n    client.sort(key, sortingParameters);\n    return client.getMultiBulkReply();\n  }\n\n  /**\n   * BLPOP (and BRPOP) is a blocking list pop primitive. You can see this commands as blocking\n   * versions of LPOP and RPOP able to block if the specified keys don't exist or contain empty\n   * lists.\n   * <p>\n   * The following is a description of the exact semantic. We describe BLPOP but the two commands\n   * are identical, the only difference is that BLPOP pops the element from the left (head) of the\n   * list, and BRPOP pops from the right (tail).\n   * <p>\n   * <b>Non blocking behavior</b>\n   * <p>\n   * When BLPOP is called, if at least one of the specified keys contain a non empty list, an\n   * element is popped from the head of the list and returned to the caller together with the name\n   * of the key (BLPOP returns a two elements array, the first element is the key, the second the\n   * popped value).\n   * <p>\n   * Keys are scanned from left to right, so for instance if you issue BLPOP list1 list2 list3 0\n   * against a dataset where list1 does not exist but list2 and list3 contain non empty lists, BLPOP\n   * guarantees to return an element from the list stored at list2 (since it is the first non empty\n   * list starting from the left).\n   * <p>\n   * <b>Blocking behavior</b>\n   * <p>\n   * If none of the specified keys exist or contain non empty lists, BLPOP blocks until some other\n   * client performs a LPUSH or an RPUSH operation against one of the lists.\n   * <p>\n   * Once new data is present on one of the lists, the client finally returns with the name of the\n   * key unblocking it and the popped value.\n   * <p>\n   * When blocking, if a non-zero timeout is specified, the client will unblock returning a nil\n   * special value if the specified amount of seconds passed without a push operation against at\n   * least one of the specified keys.\n   * <p>\n   * The timeout argument is interpreted as an integer value. A timeout of zero means instead to\n   * block forever.\n   * <p>\n   * <b>Multiple clients blocking for the same keys</b>\n   * <p>\n   * Multiple clients can block for the same key. They are put into a queue, so the first to be\n   * served will be the one that started to wait earlier, in a first-blpopping first-served fashion.\n   * <p>\n   * <b>blocking POP inside a MULTI/EXEC transaction</b>\n   * <p>\n   * BLPOP and BRPOP can be used with pipelining (sending multiple commands and reading the replies\n   * in batch), but it does not make sense to use BLPOP or BRPOP inside a MULTI/EXEC block (a Redis\n   * transaction).\n   * <p>\n   * The behavior of BLPOP inside MULTI/EXEC when the list is empty is to return a multi-bulk nil\n   * reply, exactly what happens when the timeout is reached. If you like science fiction, think at\n   * it like if inside MULTI/EXEC the time will flow at infinite speed :)\n   * <p>\n   * Time complexity: O(1)\n   * @see #brpop(int, String...)\n   * @param timeout\n   * @param keys\n   * @return BLPOP returns a two-elements array via a multi bulk reply in order to return both the\n   *         unblocking key and the popped value.\n   *         <p>\n   *         When a non-zero timeout is specified, and the BLPOP operation timed out, the return\n   *         value is a nil multi bulk reply. Most client values will return false or nil\n   *         accordingly to the programming language used.\n   */\n  @Override\n  public List<String> blpop(final int timeout, final String... keys) {\n    return blpop(getArgsAddTimeout(timeout, keys));\n  }\n\n  private String[] getArgsAddTimeout(int timeout, String[] keys) {\n    final int keyCount = keys.length;\n    final String[] args = new String[keyCount + 1];\n    for (int at = 0; at != keyCount; ++at) {\n      args[at] = keys[at];\n    }\n\n    args[keyCount] = String.valueOf(timeout);\n    return args;\n  }\n\n  @Override\n  public List<String> blpop(String... args) {\n    checkIsInMultiOrPipeline();\n    client.blpop(args);\n    client.setTimeoutInfinite();\n    try {\n      return client.getMultiBulkReply();\n    } finally {\n      client.rollbackTimeout();\n    }\n  }\n\n  @Override\n  public List<String> brpop(String... args) {\n    checkIsInMultiOrPipeline();\n    client.brpop(args);\n    client.setTimeoutInfinite();\n    try {\n      return client.getMultiBulkReply();\n    } finally {\n      client.rollbackTimeout();\n    }\n  }\n\n  /**\n   * Sort a Set or a List accordingly to the specified parameters and store the result at dstkey.\n   * @see #sort(String, SortingParams)\n   * @see #sort(String)\n   * @see #sort(String, String)\n   * @param key\n   * @param sortingParameters\n   * @param dstkey\n   * @return The number of elements of the list at dstkey.\n   */\n  @Override\n  public Long sort(final String key, final SortingParams sortingParameters, final String dstkey) {\n    checkIsInMultiOrPipeline();\n    client.sort(key, sortingParameters, dstkey);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Sort a Set or a List and Store the Result at dstkey.\n   * <p>\n   * Sort the elements contained in the List, Set, or Sorted Set value at key and store the result\n   * at dstkey. By default sorting is numeric with elements being compared as double precision\n   * floating point numbers. This is the simplest form of SORT.\n   * @see #sort(String)\n   * @see #sort(String, SortingParams)\n   * @see #sort(String, SortingParams, String)\n   * @param key\n   * @param dstkey\n   * @return The number of elements of the list at dstkey.\n   */\n  @Override\n  public Long sort(final String key, final String dstkey) {\n    checkIsInMultiOrPipeline();\n    client.sort(key, dstkey);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * BLPOP (and BRPOP) is a blocking list pop primitive. You can see this commands as blocking\n   * versions of LPOP and RPOP able to block if the specified keys don't exist or contain empty\n   * lists.\n   * <p>\n   * The following is a description of the exact semantic. We describe BLPOP but the two commands\n   * are identical, the only difference is that BLPOP pops the element from the left (head) of the\n   * list, and BRPOP pops from the right (tail).\n   * <p>\n   * <b>Non blocking behavior</b>\n   * <p>\n   * When BLPOP is called, if at least one of the specified keys contain a non empty list, an\n   * element is popped from the head of the list and returned to the caller together with the name\n   * of the key (BLPOP returns a two elements array, the first element is the key, the second the\n   * popped value).\n   * <p>\n   * Keys are scanned from left to right, so for instance if you issue BLPOP list1 list2 list3 0\n   * against a dataset where list1 does not exist but list2 and list3 contain non empty lists, BLPOP\n   * guarantees to return an element from the list stored at list2 (since it is the first non empty\n   * list starting from the left).\n   * <p>\n   * <b>Blocking behavior</b>\n   * <p>\n   * If none of the specified keys exist or contain non empty lists, BLPOP blocks until some other\n   * client performs a LPUSH or an RPUSH operation against one of the lists.\n   * <p>\n   * Once new data is present on one of the lists, the client finally returns with the name of the\n   * key unblocking it and the popped value.\n   * <p>\n   * When blocking, if a non-zero timeout is specified, the client will unblock returning a nil\n   * special value if the specified amount of seconds passed without a push operation against at\n   * least one of the specified keys.\n   * <p>\n   * The timeout argument is interpreted as an integer value. A timeout of zero means instead to\n   * block forever.\n   * <p>\n   * <b>Multiple clients blocking for the same keys</b>\n   * <p>\n   * Multiple clients can block for the same key. They are put into a queue, so the first to be\n   * served will be the one that started to wait earlier, in a first-blpopping first-served fashion.\n   * <p>\n   * <b>blocking POP inside a MULTI/EXEC transaction</b>\n   * <p>\n   * BLPOP and BRPOP can be used with pipelining (sending multiple commands and reading the replies\n   * in batch), but it does not make sense to use BLPOP or BRPOP inside a MULTI/EXEC block (a Redis\n   * transaction).\n   * <p>\n   * The behavior of BLPOP inside MULTI/EXEC when the list is empty is to return a multi-bulk nil\n   * reply, exactly what happens when the timeout is reached. If you like science fiction, think at\n   * it like if inside MULTI/EXEC the time will flow at infinite speed :)\n   * <p>\n   * Time complexity: O(1)\n   * @see #blpop(int, String...)\n   * @param timeout\n   * @param keys\n   * @return BLPOP returns a two-elements array via a multi bulk reply in order to return both the\n   *         unblocking key and the popped value.\n   *         <p>\n   *         When a non-zero timeout is specified, and the BLPOP operation timed out, the return\n   *         value is a nil multi bulk reply. Most client values will return false or nil\n   *         accordingly to the programming language used.\n   */\n  @Override\n  public List<String> brpop(final int timeout, final String... keys) {\n    return brpop(getArgsAddTimeout(timeout, keys));\n  }\n\n  @Override\n  public Long zcount(final String key, final double min, final double max) {\n    checkIsInMultiOrPipeline();\n    client.zcount(key, min, max);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public Long zcount(final String key, final String min, final String max) {\n    checkIsInMultiOrPipeline();\n    client.zcount(key, min, max);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Return the all the elements in the sorted set at key with a score between min and max\n   * (including elements with score equal to min or max).\n   * <p>\n   * The elements having the same score are returned sorted lexicographically as ASCII strings (this\n   * follows from a property of Redis sorted sets and does not involve further computation).\n   * <p>\n   * Using the optional {@link #zrangeByScore(String, double, double, int, int) LIMIT} it's possible\n   * to get only a range of the matching elements in an SQL-alike way. Note that if offset is large\n   * the commands needs to traverse the list for offset elements and this adds up to the O(M)\n   * figure.\n   * <p>\n   * The {@link #zcount(String, double, double) ZCOUNT} command is similar to\n   * {@link #zrangeByScore(String, double, double) ZRANGEBYSCORE} but instead of returning the\n   * actual elements in the specified interval, it just returns the number of matching elements.\n   * <p>\n   * <b>Exclusive intervals and infinity</b>\n   * <p>\n   * min and max can be -inf and +inf, so that you are not required to know what's the greatest or\n   * smallest element in order to take, for instance, elements \"up to a given value\".\n   * <p>\n   * Also while the interval is for default closed (inclusive) it's possible to specify open\n   * intervals prefixing the score with a \"(\" character, so for instance:\n   * <p>\n   * {@code ZRANGEBYSCORE zset (1.3 5}\n   * <p>\n   * Will return all the values with score &gt; 1.3 and &lt;= 5, while for instance:\n   * <p>\n   * {@code ZRANGEBYSCORE zset (5 (10}\n   * <p>\n   * Will return all the values with score &gt; 5 and &lt; 10 (5 and 10 excluded).\n   * <p>\n   * <b>Time complexity:</b>\n   * <p>\n   * O(log(N))+O(M) with N being the number of elements in the sorted set and M the number of\n   * elements returned by the command, so if M is constant (for instance you always ask for the\n   * first ten elements with LIMIT) you can consider it O(log(N))\n   * @see #zrangeByScore(String, double, double)\n   * @see #zrangeByScore(String, double, double, int, int)\n   * @see #zrangeByScoreWithScores(String, double, double)\n   * @see #zrangeByScoreWithScores(String, String, String)\n   * @see #zrangeByScoreWithScores(String, double, double, int, int)\n   * @see #zcount(String, double, double)\n   * @param key\n   * @param min a double or Double.MIN_VALUE for \"-inf\"\n   * @param max a double or Double.MAX_VALUE for \"+inf\"\n   * @return Multi bulk reply specifically a list of elements in the specified score range.\n   */\n  @Override\n  public Set<String> zrangeByScore(final String key, final double min, final double max) {\n    checkIsInMultiOrPipeline();\n    client.zrangeByScore(key, min, max);\n    final List<String> members = client.getMultiBulkReply();\n    if (members == null) {\n      return null;\n    }\n    return SetFromList.of(members);\n  }\n\n  @Override\n  public Set<String> zrangeByScore(final String key, final String min, final String max) {\n    checkIsInMultiOrPipeline();\n    client.zrangeByScore(key, min, max);\n    final List<String> members = client.getMultiBulkReply();\n    if (members == null) {\n      return null;\n    }\n    return SetFromList.of(members);\n  }\n\n  /**\n   * Return the all the elements in the sorted set at key with a score between min and max\n   * (including elements with score equal to min or max).\n   * <p>\n   * The elements having the same score are returned sorted lexicographically as ASCII strings (this\n   * follows from a property of Redis sorted sets and does not involve further computation).\n   * <p>\n   * Using the optional {@link #zrangeByScore(String, double, double, int, int) LIMIT} it's possible\n   * to get only a range of the matching elements in an SQL-alike way. Note that if offset is large\n   * the commands needs to traverse the list for offset elements and this adds up to the O(M)\n   * figure.\n   * <p>\n   * The {@link #zcount(String, double, double) ZCOUNT} command is similar to\n   * {@link #zrangeByScore(String, double, double) ZRANGEBYSCORE} but instead of returning the\n   * actual elements in the specified interval, it just returns the number of matching elements.\n   * <p>\n   * <b>Exclusive intervals and infinity</b>\n   * <p>\n   * min and max can be -inf and +inf, so that you are not required to know what's the greatest or\n   * smallest element in order to take, for instance, elements \"up to a given value\".\n   * <p>\n   * Also while the interval is for default closed (inclusive) it's possible to specify open\n   * intervals prefixing the score with a \"(\" character, so for instance:\n   * <p>\n   * {@code ZRANGEBYSCORE zset (1.3 5}\n   * <p>\n   * Will return all the values with score &gt; 1.3 and &lt;= 5, while for instance:\n   * <p>\n   * {@code ZRANGEBYSCORE zset (5 (10}\n   * <p>\n   * Will return all the values with score &gt; 5 and &lt; 10 (5 and 10 excluded).\n   * <p>\n   * <b>Time complexity:</b>\n   * <p>\n   * O(log(N))+O(M) with N being the number of elements in the sorted set and M the number of\n   * elements returned by the command, so if M is constant (for instance you always ask for the\n   * first ten elements with LIMIT) you can consider it O(log(N))\n   * @see #zrangeByScore(String, double, double)\n   * @see #zrangeByScore(String, double, double, int, int)\n   * @see #zrangeByScoreWithScores(String, double, double)\n   * @see #zrangeByScoreWithScores(String, double, double, int, int)\n   * @see #zcount(String, double, double)\n   * @param key\n   * @param min\n   * @param max\n   * @return Multi bulk reply specifically a list of elements in the specified score range.\n   */\n  @Override\n  public Set<String> zrangeByScore(final String key, final double min, final double max,\n      final int offset, final int count) {\n    checkIsInMultiOrPipeline();\n    client.zrangeByScore(key, min, max, offset, count);\n    final List<String> members = client.getMultiBulkReply();\n    if (members == null) {\n      return null;\n    }\n    return SetFromList.of(members);\n  }\n\n  @Override\n  public Set<String> zrangeByScore(final String key, final String min, final String max,\n      final int offset, final int count) {\n    checkIsInMultiOrPipeline();\n    client.zrangeByScore(key, min, max, offset, count);\n    final List<String> members = client.getMultiBulkReply();\n    if (members == null) {\n      return null;\n    }\n    return SetFromList.of(members);\n  }\n\n  /**\n   * Return the all the elements in the sorted set at key with a score between min and max\n   * (including elements with score equal to min or max).\n   * <p>\n   * The elements having the same score are returned sorted lexicographically as ASCII strings (this\n   * follows from a property of Redis sorted sets and does not involve further computation).\n   * <p>\n   * Using the optional {@link #zrangeByScore(String, double, double, int, int) LIMIT} it's possible\n   * to get only a range of the matching elements in an SQL-alike way. Note that if offset is large\n   * the commands needs to traverse the list for offset elements and this adds up to the O(M)\n   * figure.\n   * <p>\n   * The {@link #zcount(String, double, double) ZCOUNT} command is similar to\n   * {@link #zrangeByScore(String, double, double) ZRANGEBYSCORE} but instead of returning the\n   * actual elements in the specified interval, it just returns the number of matching elements.\n   * <p>\n   * <b>Exclusive intervals and infinity</b>\n   * <p>\n   * min and max can be -inf and +inf, so that you are not required to know what's the greatest or\n   * smallest element in order to take, for instance, elements \"up to a given value\".\n   * <p>\n   * Also while the interval is for default closed (inclusive) it's possible to specify open\n   * intervals prefixing the score with a \"(\" character, so for instance:\n   * <p>\n   * {@code ZRANGEBYSCORE zset (1.3 5}\n   * <p>\n   * Will return all the values with score &gt; 1.3 and &lt;= 5, while for instance:\n   * <p>\n   * {@code ZRANGEBYSCORE zset (5 (10}\n   * <p>\n   * Will return all the values with score &gt; 5 and &lt; 10 (5 and 10 excluded).\n   * <p>\n   * <b>Time complexity:</b>\n   * <p>\n   * O(log(N))+O(M) with N being the number of elements in the sorted set and M the number of\n   * elements returned by the command, so if M is constant (for instance you always ask for the\n   * first ten elements with LIMIT) you can consider it O(log(N))\n   * @see #zrangeByScore(String, double, double)\n   * @see #zrangeByScore(String, double, double, int, int)\n   * @see #zrangeByScoreWithScores(String, double, double)\n   * @see #zrangeByScoreWithScores(String, double, double, int, int)\n   * @see #zcount(String, double, double)\n   * @param key\n   * @param min\n   * @param max\n   * @return Multi bulk reply specifically a list of elements in the specified score range.\n   */\n  @Override\n  public Set<Tuple> zrangeByScoreWithScores(final String key, final double min, final double max) {\n    checkIsInMultiOrPipeline();\n    client.zrangeByScoreWithScores(key, min, max);\n    return getTupledSet();\n  }\n\n  @Override\n  public Set<Tuple> zrangeByScoreWithScores(final String key, final String min, final String max) {\n    checkIsInMultiOrPipeline();\n    client.zrangeByScoreWithScores(key, min, max);\n    return getTupledSet();\n  }\n\n  /**\n   * Return the all the elements in the sorted set at key with a score between min and max\n   * (including elements with score equal to min or max).\n   * <p>\n   * The elements having the same score are returned sorted lexicographically as ASCII strings (this\n   * follows from a property of Redis sorted sets and does not involve further computation).\n   * <p>\n   * Using the optional {@link #zrangeByScore(String, double, double, int, int) LIMIT} it's possible\n   * to get only a range of the matching elements in an SQL-alike way. Note that if offset is large\n   * the commands needs to traverse the list for offset elements and this adds up to the O(M)\n   * figure.\n   * <p>\n   * The {@link #zcount(String, double, double) ZCOUNT} command is similar to\n   * {@link #zrangeByScore(String, double, double) ZRANGEBYSCORE} but instead of returning the\n   * actual elements in the specified interval, it just returns the number of matching elements.\n   * <p>\n   * <b>Exclusive intervals and infinity</b>\n   * <p>\n   * min and max can be -inf and +inf, so that you are not required to know what's the greatest or\n   * smallest element in order to take, for instance, elements \"up to a given value\".\n   * <p>\n   * Also while the interval is for default closed (inclusive) it's possible to specify open\n   * intervals prefixing the score with a \"(\" character, so for instance:\n   * <p>\n   * {@code ZRANGEBYSCORE zset (1.3 5}\n   * <p>\n   * Will return all the values with score &gt; 1.3 and &lt;= 5, while for instance:\n   * <p>\n   * {@code ZRANGEBYSCORE zset (5 (10}\n   * <p>\n   * Will return all the values with score &gt; 5 and &lt; 10 (5 and 10 excluded).\n   * <p>\n   * <b>Time complexity:</b>\n   * <p>\n   * O(log(N))+O(M) with N being the number of elements in the sorted set and M the number of\n   * elements returned by the command, so if M is constant (for instance you always ask for the\n   * first ten elements with LIMIT) you can consider it O(log(N))\n   * @see #zrangeByScore(String, double, double)\n   * @see #zrangeByScore(String, double, double, int, int)\n   * @see #zrangeByScoreWithScores(String, double, double)\n   * @see #zrangeByScoreWithScores(String, double, double, int, int)\n   * @see #zcount(String, double, double)\n   * @param key\n   * @param min\n   * @param max\n   * @return Multi bulk reply specifically a list of elements in the specified score range.\n   */\n  @Override\n  public Set<Tuple> zrangeByScoreWithScores(final String key, final double min, final double max,\n      final int offset, final int count) {\n    checkIsInMultiOrPipeline();\n    client.zrangeByScoreWithScores(key, min, max, offset, count);\n    return getTupledSet();\n  }\n\n  @Override\n  public Set<Tuple> zrangeByScoreWithScores(final String key, final String min, final String max,\n      final int offset, final int count) {\n    checkIsInMultiOrPipeline();\n    client.zrangeByScoreWithScores(key, min, max, offset, count);\n    return getTupledSet();\n  }\n\n  private Set<Tuple> getTupledSet() {\n    checkIsInMultiOrPipeline();\n    List<String> membersWithScores = client.getMultiBulkReply();\n    if (membersWithScores == null) {\n      return null;\n    }\n    if (membersWithScores.size() == 0) {\n      return Collections.emptySet();\n    }\n    Set<Tuple> set = new LinkedHashSet<Tuple>(membersWithScores.size() / 2, 1.0f);\n    Iterator<String> iterator = membersWithScores.iterator();\n    while (iterator.hasNext()) {\n      set.add(new Tuple(iterator.next(), Double.valueOf(iterator.next())));\n    }\n    return set;\n  }\n\n  @Override\n  public Set<String> zrevrangeByScore(final String key, final double max, final double min) {\n    checkIsInMultiOrPipeline();\n    client.zrevrangeByScore(key, max, min);\n    final List<String> members = client.getMultiBulkReply();\n    if (members == null) {\n      return null;\n    }\n    return SetFromList.of(members);\n  }\n\n  @Override\n  public Set<String> zrevrangeByScore(final String key, final String max, final String min) {\n    checkIsInMultiOrPipeline();\n    client.zrevrangeByScore(key, max, min);\n    final List<String> members = client.getMultiBulkReply();\n    if (members == null) {\n      return null;\n    }\n    return SetFromList.of(members);\n  }\n\n  @Override\n  public Set<String> zrevrangeByScore(final String key, final double max, final double min,\n      final int offset, final int count) {\n    checkIsInMultiOrPipeline();\n    client.zrevrangeByScore(key, max, min, offset, count);\n    final List<String> members = client.getMultiBulkReply();\n    if (members == null) {\n      return null;\n    }\n    return SetFromList.of(members);\n  }\n\n  @Override\n  public Set<Tuple> zrevrangeByScoreWithScores(final String key, final double max, final double min) {\n    checkIsInMultiOrPipeline();\n    client.zrevrangeByScoreWithScores(key, max, min);\n    return getTupledSet();\n  }\n\n  @Override\n  public Set<Tuple> zrevrangeByScoreWithScores(final String key, final double max,\n      final double min, final int offset, final int count) {\n    checkIsInMultiOrPipeline();\n    client.zrevrangeByScoreWithScores(key, max, min, offset, count);\n    return getTupledSet();\n  }\n\n  @Override\n  public Set<Tuple> zrevrangeByScoreWithScores(final String key, final String max,\n      final String min, final int offset, final int count) {\n    checkIsInMultiOrPipeline();\n    client.zrevrangeByScoreWithScores(key, max, min, offset, count);\n    return getTupledSet();\n  }\n\n  @Override\n  public Set<String> zrevrangeByScore(final String key, final String max, final String min,\n      final int offset, final int count) {\n    checkIsInMultiOrPipeline();\n    client.zrevrangeByScore(key, max, min, offset, count);\n    final List<String> members = client.getMultiBulkReply();\n    if (members == null) {\n      return null;\n    }\n    return SetFromList.of(members);\n  }\n\n  @Override\n  public Set<Tuple> zrevrangeByScoreWithScores(final String key, final String max, final String min) {\n    checkIsInMultiOrPipeline();\n    client.zrevrangeByScoreWithScores(key, max, min);\n    return getTupledSet();\n  }\n\n  /**\n   * Remove all elements in the sorted set at key with rank between start and end. Start and end are\n   * 0-based with rank 0 being the element with the lowest score. Both start and end can be negative\n   * numbers, where they indicate offsets starting at the element with the highest rank. For\n   * example: -1 is the element with the highest score, -2 the element with the second highest score\n   * and so forth.\n   * <p>\n   * <b>Time complexity:</b> O(log(N))+O(M) with N being the number of elements in the sorted set\n   * and M the number of elements removed by the operation\n   */\n  @Override\n  public Long zremrangeByRank(final String key, final long start, final long end) {\n    checkIsInMultiOrPipeline();\n    client.zremrangeByRank(key, start, end);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Remove all the elements in the sorted set at key with a score between min and max (including\n   * elements with score equal to min or max).\n   * <p>\n   * <b>Time complexity:</b>\n   * <p>\n   * O(log(N))+O(M) with N being the number of elements in the sorted set and M the number of\n   * elements removed by the operation\n   * @param key\n   * @param start\n   * @param end\n   * @return Integer reply, specifically the number of elements removed.\n   */\n  @Override\n  public Long zremrangeByScore(final String key, final double start, final double end) {\n    checkIsInMultiOrPipeline();\n    client.zremrangeByScore(key, start, end);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public Long zremrangeByScore(final String key, final String start, final String end) {\n    checkIsInMultiOrPipeline();\n    client.zremrangeByScore(key, start, end);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Creates a union or intersection of N sorted sets given by keys k1 through kN, and stores it at\n   * dstkey. It is mandatory to provide the number of input keys N, before passing the input keys\n   * and the other (optional) arguments.\n   * <p>\n   * As the terms imply, the {@link #zinterstore(String, String...) ZINTERSTORE} command requires an\n   * element to be present in each of the given inputs to be inserted in the result. The\n   * {@link #zunionstore(String, String...) ZUNIONSTORE} command inserts all elements across all\n   * inputs.\n   * <p>\n   * Using the WEIGHTS option, it is possible to add weight to each input sorted set. This means\n   * that the score of each element in the sorted set is first multiplied by this weight before\n   * being passed to the aggregation. When this option is not given, all weights default to 1.\n   * <p>\n   * With the AGGREGATE option, it's possible to specify how the results of the union or\n   * intersection are aggregated. This option defaults to SUM, where the score of an element is\n   * summed across the inputs where it exists. When this option is set to be either MIN or MAX, the\n   * resulting set will contain the minimum or maximum score of an element across the inputs where\n   * it exists.\n   * <p>\n   * <b>Time complexity:</b> O(N) + O(M log(M)) with N being the sum of the sizes of the input\n   * sorted sets, and M being the number of elements in the resulting sorted set\n   * @see #zunionstore(String, String...)\n   * @see #zunionstore(String, ZParams, String...)\n   * @see #zinterstore(String, String...)\n   * @see #zinterstore(String, ZParams, String...)\n   * @param dstkey\n   * @param sets\n   * @return Integer reply, specifically the number of elements in the sorted set at dstkey\n   */\n  @Override\n  public Long zunionstore(final String dstkey, final String... sets) {\n    checkIsInMultiOrPipeline();\n    client.zunionstore(dstkey, sets);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Creates a union or intersection of N sorted sets given by keys k1 through kN, and stores it at\n   * dstkey. It is mandatory to provide the number of input keys N, before passing the input keys\n   * and the other (optional) arguments.\n   * <p>\n   * As the terms imply, the {@link #zinterstore(String, String...) ZINTERSTORE} command requires an\n   * element to be present in each of the given inputs to be inserted in the result. The\n   * {@link #zunionstore(String, String...) ZUNIONSTORE} command inserts all elements across all\n   * inputs.\n   * <p>\n   * Using the WEIGHTS option, it is possible to add weight to each input sorted set. This means\n   * that the score of each element in the sorted set is first multiplied by this weight before\n   * being passed to the aggregation. When this option is not given, all weights default to 1.\n   * <p>\n   * With the AGGREGATE option, it's possible to specify how the results of the union or\n   * intersection are aggregated. This option defaults to SUM, where the score of an element is\n   * summed across the inputs where it exists. When this option is set to be either MIN or MAX, the\n   * resulting set will contain the minimum or maximum score of an element across the inputs where\n   * it exists.\n   * <p>\n   * <b>Time complexity:</b> O(N) + O(M log(M)) with N being the sum of the sizes of the input\n   * sorted sets, and M being the number of elements in the resulting sorted set\n   * @see #zunionstore(String, String...)\n   * @see #zunionstore(String, ZParams, String...)\n   * @see #zinterstore(String, String...)\n   * @see #zinterstore(String, ZParams, String...)\n   * @param dstkey\n   * @param sets\n   * @param params\n   * @return Integer reply, specifically the number of elements in the sorted set at dstkey\n   */\n  @Override\n  public Long zunionstore(final String dstkey, final ZParams params, final String... sets) {\n    checkIsInMultiOrPipeline();\n    client.zunionstore(dstkey, params, sets);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Creates a union or intersection of N sorted sets given by keys k1 through kN, and stores it at\n   * dstkey. It is mandatory to provide the number of input keys N, before passing the input keys\n   * and the other (optional) arguments.\n   * <p>\n   * As the terms imply, the {@link #zinterstore(String, String...) ZINTERSTORE} command requires an\n   * element to be present in each of the given inputs to be inserted in the result. The\n   * {@link #zunionstore(String, String...) ZUNIONSTORE} command inserts all elements across all\n   * inputs.\n   * <p>\n   * Using the WEIGHTS option, it is possible to add weight to each input sorted set. This means\n   * that the score of each element in the sorted set is first multiplied by this weight before\n   * being passed to the aggregation. When this option is not given, all weights default to 1.\n   * <p>\n   * With the AGGREGATE option, it's possible to specify how the results of the union or\n   * intersection are aggregated. This option defaults to SUM, where the score of an element is\n   * summed across the inputs where it exists. When this option is set to be either MIN or MAX, the\n   * resulting set will contain the minimum or maximum score of an element across the inputs where\n   * it exists.\n   * <p>\n   * <b>Time complexity:</b> O(N) + O(M log(M)) with N being the sum of the sizes of the input\n   * sorted sets, and M being the number of elements in the resulting sorted set\n   * @see #zunionstore(String, String...)\n   * @see #zunionstore(String, ZParams, String...)\n   * @see #zinterstore(String, String...)\n   * @see #zinterstore(String, ZParams, String...)\n   * @param dstkey\n   * @param sets\n   * @return Integer reply, specifically the number of elements in the sorted set at dstkey\n   */\n  @Override\n  public Long zinterstore(final String dstkey, final String... sets) {\n    checkIsInMultiOrPipeline();\n    client.zinterstore(dstkey, sets);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Creates a union or intersection of N sorted sets given by keys k1 through kN, and stores it at\n   * dstkey. It is mandatory to provide the number of input keys N, before passing the input keys\n   * and the other (optional) arguments.\n   * <p>\n   * As the terms imply, the {@link #zinterstore(String, String...) ZINTERSTORE} command requires an\n   * element to be present in each of the given inputs to be inserted in the result. The\n   * {@link #zunionstore(String, String...) ZUNIONSTORE} command inserts all elements across all\n   * inputs.\n   * <p>\n   * Using the WEIGHTS option, it is possible to add weight to each input sorted set. This means\n   * that the score of each element in the sorted set is first multiplied by this weight before\n   * being passed to the aggregation. When this option is not given, all weights default to 1.\n   * <p>\n   * With the AGGREGATE option, it's possible to specify how the results of the union or\n   * intersection are aggregated. This option defaults to SUM, where the score of an element is\n   * summed across the inputs where it exists. When this option is set to be either MIN or MAX, the\n   * resulting set will contain the minimum or maximum score of an element across the inputs where\n   * it exists.\n   * <p>\n   * <b>Time complexity:</b> O(N) + O(M log(M)) with N being the sum of the sizes of the input\n   * sorted sets, and M being the number of elements in the resulting sorted set\n   * @see #zunionstore(String, String...)\n   * @see #zunionstore(String, ZParams, String...)\n   * @see #zinterstore(String, String...)\n   * @see #zinterstore(String, ZParams, String...)\n   * @param dstkey\n   * @param sets\n   * @param params\n   * @return Integer reply, specifically the number of elements in the sorted set at dstkey\n   */\n  @Override\n  public Long zinterstore(final String dstkey, final ZParams params, final String... sets) {\n    checkIsInMultiOrPipeline();\n    client.zinterstore(dstkey, params, sets);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public Long zlexcount(final String key, final String min, final String max) {\n    checkIsInMultiOrPipeline();\n    client.zlexcount(key, min, max);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public Set<String> zrangeByLex(final String key, final String min, final String max) {\n    checkIsInMultiOrPipeline();\n    client.zrangeByLex(key, min, max);\n    final List<String> members = client.getMultiBulkReply();\n    if (members == null) {\n      return null;\n    }\n    return SetFromList.of(members);\n  }\n\n  @Override\n  public Set<String> zrangeByLex(final String key, final String min, final String max,\n      final int offset, final int count) {\n    checkIsInMultiOrPipeline();\n    client.zrangeByLex(key, min, max, offset, count);\n    final List<String> members = client.getMultiBulkReply();\n    if (members == null) {\n      return null;\n    }\n    return SetFromList.of(members);\n  }\n\n  @Override\n  public Set<String> zrevrangeByLex(String key, String max, String min) {\n    checkIsInMultiOrPipeline();\n    client.zrevrangeByLex(key, max, min);\n    final List<String> members = client.getMultiBulkReply();\n    if (members == null) {\n      return null;\n    }\n    return SetFromList.of(members);\n  }\n\n  @Override\n  public Set<String> zrevrangeByLex(String key, String max, String min, int offset, int count) {\n    checkIsInMultiOrPipeline();\n    client.zrevrangeByLex(key, max, min, offset, count);\n    final List<String> members = client.getMultiBulkReply();\n    if (members == null) {\n      return null;\n    }\n    return SetFromList.of(members);\n  }\n\n  @Override\n  public Long zremrangeByLex(final String key, final String min, final String max) {\n    checkIsInMultiOrPipeline();\n    client.zremrangeByLex(key, min, max);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public Long strlen(final String key) {\n    client.strlen(key);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public Long lpushx(final String key, final String... string) {\n    client.lpushx(key, string);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Undo a {@link #expire(String, int) expire} at turning the expire key into a normal key.\n   * <p>\n   * Time complexity: O(1)\n   * @param key\n   * @return Integer reply, specifically: 1: the key is now persist. 0: the key is not persist (only\n   *         happens when key not set).\n   */\n  @Override\n  public Long persist(final String key) {\n    client.persist(key);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public Long rpushx(final String key, final String... string) {\n    client.rpushx(key, string);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public String echo(final String string) {\n    client.echo(string);\n    return client.getBulkReply();\n  }\n\n  @Override\n  public Long linsert(final String key, final LIST_POSITION where, final String pivot,\n      final String value) {\n    client.linsert(key, where, pivot, value);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Pop a value from a list, push it to another list and return it; or block until one is available\n   * @param source\n   * @param destination\n   * @param timeout\n   * @return the element\n   */\n  @Override\n  public String brpoplpush(String source, String destination, int timeout) {\n    client.brpoplpush(source, destination, timeout);\n    client.setTimeoutInfinite();\n    try {\n      return client.getBulkReply();\n    } finally {\n      client.rollbackTimeout();\n    }\n  }\n\n  /**\n   * Sets or clears the bit at offset in the string value stored at key\n   * @param key\n   * @param offset\n   * @param value\n   * @return\n   */\n  @Override\n  public Boolean setbit(String key, long offset, boolean value) {\n    client.setbit(key, offset, value);\n    return client.getIntegerReply() == 1;\n  }\n\n  @Override\n  public Boolean setbit(String key, long offset, String value) {\n    client.setbit(key, offset, value);\n    return client.getIntegerReply() == 1;\n  }\n\n  /**\n   * Returns the bit value at offset in the string value stored at key\n   * @param key\n   * @param offset\n   * @return\n   */\n  @Override\n  public Boolean getbit(String key, long offset) {\n    client.getbit(key, offset);\n    return client.getIntegerReply() == 1;\n  }\n\n  @Override\n  public Long setrange(String key, long offset, String value) {\n    client.setrange(key, offset, value);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public String getrange(String key, long startOffset, long endOffset) {\n    client.getrange(key, startOffset, endOffset);\n    return client.getBulkReply();\n  }\n\n  @Override\n  public Long bitpos(final String key, final boolean value) {\n    return bitpos(key, value, new BitPosParams());\n  }\n\n  @Override\n  public Long bitpos(final String key, final boolean value, final BitPosParams params) {\n    client.bitpos(key, value, params);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * Retrieve the configuration of a running Redis server. Not all the configuration parameters are\n   * supported.\n   * <p>\n   * CONFIG GET returns the current configuration parameters. This sub command only accepts a single\n   * argument, that is glob style pattern. All the configuration parameters matching this parameter\n   * are reported as a list of key-value pairs.\n   * <p>\n   * <b>Example:</b>\n   * \n   * <pre>\n   * $ redis-cli config get '*'\n   * 1. \"dbfilename\"\n   * 2. \"dump.rdb\"\n   * 3. \"requirepass\"\n   * 4. (nil)\n   * 5. \"masterauth\"\n   * 6. (nil)\n   * 7. \"maxmemory\"\n   * 8. \"0\\n\"\n   * 9. \"appendfsync\"\n   * 10. \"everysec\"\n   * 11. \"save\"\n   * 12. \"3600 1 300 100 60 10000\"\n   * \n   * $ redis-cli config get 'm*'\n   * 1. \"masterauth\"\n   * 2. (nil)\n   * 3. \"maxmemory\"\n   * 4. \"0\\n\"\n   * </pre>\n   * @param pattern\n   * @return Bulk reply.\n   */\n  @Override\n  public List<String> configGet(final String pattern) {\n    client.configGet(pattern);\n    return client.getMultiBulkReply();\n  }\n\n  /**\n   * Alter the configuration of a running Redis server. Not all the configuration parameters are\n   * supported.\n   * <p>\n   * The list of configuration parameters supported by CONFIG SET can be obtained issuing a\n   * {@link #configGet(String) CONFIG GET *} command.\n   * <p>\n   * The configuration set using CONFIG SET is immediately loaded by the Redis server that will\n   * start acting as specified starting from the next command.\n   * <p>\n   * <b>Parameters value format</b>\n   * <p>\n   * The value of the configuration parameter is the same as the one of the same parameter in the\n   * Redis configuration file, with the following exceptions:\n   * <p>\n   * <ul>\n   * <li>The save paramter is a list of space-separated integers. Every pair of integers specify the\n   * time and number of changes limit to trigger a save. For instance the command CONFIG SET save\n   * \"3600 10 60 10000\" will configure the server to issue a background saving of the RDB file every\n   * 3600 seconds if there are at least 10 changes in the dataset, and every 60 seconds if there are\n   * at least 10000 changes. To completely disable automatic snapshots just set the parameter as an\n   * empty string.\n   * <li>All the integer parameters representing memory are returned and accepted only using bytes\n   * as unit.\n   * </ul>\n   * @param parameter\n   * @param value\n   * @return Status code reply\n   */\n  @Override\n  public String configSet(final String parameter, final String value) {\n    client.configSet(parameter, value);\n    return client.getStatusCodeReply();\n  }\n\n  @Override\n  public Object eval(String script, int keyCount, String... params) {\n    client.setTimeoutInfinite();\n    try {\n      client.eval(script, keyCount, params);\n      return getEvalResult();\n    } finally {\n      client.rollbackTimeout();\n    }\n  }\n\n  @Override\n  public void subscribe(final JedisPubSub jedisPubSub, final String... channels) {\n    client.setTimeoutInfinite();\n    try {\n      jedisPubSub.proceed(client, channels);\n    } finally {\n      client.rollbackTimeout();\n    }\n  }\n\n  @Override\n  public Long publish(final String channel, final String message) {\n    checkIsInMultiOrPipeline();\n    connect();\n    client.publish(channel, message);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public void psubscribe(final JedisPubSub jedisPubSub, final String... patterns) {\n    checkIsInMultiOrPipeline();\n    client.setTimeoutInfinite();\n    try {\n      jedisPubSub.proceedWithPatterns(client, patterns);\n    } finally {\n      client.rollbackTimeout();\n    }\n  }\n\n  protected static String[] getParams(List<String> keys, List<String> args) {\n    int keyCount = keys.size();\n    int argCount = args.size();\n\n    String[] params = new String[keyCount + args.size()];\n\n    for (int i = 0; i < keyCount; i++)\n      params[i] = keys.get(i);\n\n    for (int i = 0; i < argCount; i++)\n      params[keyCount + i] = args.get(i);\n\n    return params;\n  }\n\n  @Override\n  public Object eval(String script, List<String> keys, List<String> args) {\n    return eval(script, keys.size(), getParams(keys, args));\n  }\n\n  @Override\n  public Object eval(String script) {\n    return eval(script, 0);\n  }\n\n  @Override\n  public Object evalsha(String script) {\n    return evalsha(script, 0);\n  }\n\n  private Object getEvalResult() {\n    return evalResult(client.getOne());\n  }\n\n  private Object evalResult(Object result) {\n    if (result instanceof byte[]) return SafeEncoder.encode((byte[]) result);\n\n    if (result instanceof List<?>) {\n      List<?> list = (List<?>) result;\n      List<Object> listResult = new ArrayList<Object>(list.size());\n      for (Object bin : list) {\n        listResult.add(evalResult(bin));\n      }\n\n      return listResult;\n    }\n\n    return result;\n  }\n\n  @Override\n  public Object evalsha(String sha1, List<String> keys, List<String> args) {\n    return evalsha(sha1, keys.size(), getParams(keys, args));\n  }\n\n  @Override\n  public Object evalsha(String sha1, int keyCount, String... params) {\n    checkIsInMultiOrPipeline();\n    client.evalsha(sha1, keyCount, params);\n    return getEvalResult();\n  }\n\n  @Override\n  public Boolean scriptExists(String sha1) {\n    String[] a = new String[1];\n    a[0] = sha1;\n    return scriptExists(a).get(0);\n  }\n\n  @Override\n  public List<Boolean> scriptExists(String... sha1) {\n    client.scriptExists(sha1);\n    List<Long> result = client.getIntegerMultiBulkReply();\n    List<Boolean> exists = new ArrayList<Boolean>();\n\n    for (Long value : result)\n      exists.add(value == 1);\n\n    return exists;\n  }\n\n  @Override\n  public String scriptLoad(String script) {\n    client.scriptLoad(script);\n    return client.getBulkReply();\n  }\n\n  @Override\n  public List<Slowlog> slowlogGet() {\n    client.slowlogGet();\n    return Slowlog.from(client.getObjectMultiBulkReply());\n  }\n\n  @Override\n  public List<Slowlog> slowlogGet(long entries) {\n    client.slowlogGet(entries);\n    return Slowlog.from(client.getObjectMultiBulkReply());\n  }\n\n  @Override\n  public Long objectRefcount(String string) {\n    client.objectRefcount(string);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public String objectEncoding(String string) {\n    client.objectEncoding(string);\n    return client.getBulkReply();\n  }\n\n  @Override\n  public Long objectIdletime(String string) {\n    client.objectIdletime(string);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public Long bitcount(final String key) {\n    client.bitcount(key);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public Long bitcount(final String key, long start, long end) {\n    client.bitcount(key, start, end);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public Long bitop(BitOP op, final String destKey, String... srcKeys) {\n    client.bitop(op, destKey, srcKeys);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * <pre>\n   * redis 127.0.0.1:26381&gt; sentinel masters\n   * 1)  1) \"name\"\n   *     2) \"mymaster\"\n   *     3) \"ip\"\n   *     4) \"127.0.0.1\"\n   *     5) \"port\"\n   *     6) \"6379\"\n   *     7) \"runid\"\n   *     8) \"93d4d4e6e9c06d0eea36e27f31924ac26576081d\"\n   *     9) \"flags\"\n   *    10) \"master\"\n   *    11) \"pending-commands\"\n   *    12) \"0\"\n   *    13) \"last-ok-ping-reply\"\n   *    14) \"423\"\n   *    15) \"last-ping-reply\"\n   *    16) \"423\"\n   *    17) \"info-refresh\"\n   *    18) \"6107\"\n   *    19) \"num-slaves\"\n   *    20) \"1\"\n   *    21) \"num-other-sentinels\"\n   *    22) \"2\"\n   *    23) \"quorum\"\n   *    24) \"2\"\n   * \n   * </pre>\n   * @return\n   */\n  @Override\n  @SuppressWarnings(\"rawtypes\")\n  public List<Map<String, String>> sentinelMasters() {\n    client.sentinel(Protocol.SENTINEL_MASTERS);\n    final List<Object> reply = client.getObjectMultiBulkReply();\n\n    final List<Map<String, String>> masters = new ArrayList<Map<String, String>>();\n    for (Object obj : reply) {\n      masters.add(BuilderFactory.STRING_MAP.build((List) obj));\n    }\n    return masters;\n  }\n\n  /**\n   * <pre>\n   * redis 127.0.0.1:26381&gt; sentinel get-master-addr-by-name mymaster\n   * 1) \"127.0.0.1\"\n   * 2) \"6379\"\n   * </pre>\n   * @param masterName\n   * @return two elements list of strings : host and port.\n   */\n  @Override\n  public List<String> sentinelGetMasterAddrByName(String masterName) {\n    client.sentinel(Protocol.SENTINEL_GET_MASTER_ADDR_BY_NAME, masterName);\n    final List<Object> reply = client.getObjectMultiBulkReply();\n    return BuilderFactory.STRING_LIST.build(reply);\n  }\n\n  /**\n   * <pre>\n   * redis 127.0.0.1:26381&gt; sentinel reset mymaster\n   * (integer) 1\n   * </pre>\n   * @param pattern\n   * @return\n   */\n  @Override\n  public Long sentinelReset(String pattern) {\n    client.sentinel(Protocol.SENTINEL_RESET, pattern);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * <pre>\n   * redis 127.0.0.1:26381&gt; sentinel slaves mymaster\n   * 1)  1) \"name\"\n   *     2) \"127.0.0.1:6380\"\n   *     3) \"ip\"\n   *     4) \"127.0.0.1\"\n   *     5) \"port\"\n   *     6) \"6380\"\n   *     7) \"runid\"\n   *     8) \"d7f6c0ca7572df9d2f33713df0dbf8c72da7c039\"\n   *     9) \"flags\"\n   *    10) \"slave\"\n   *    11) \"pending-commands\"\n   *    12) \"0\"\n   *    13) \"last-ok-ping-reply\"\n   *    14) \"47\"\n   *    15) \"last-ping-reply\"\n   *    16) \"47\"\n   *    17) \"info-refresh\"\n   *    18) \"657\"\n   *    19) \"master-link-down-time\"\n   *    20) \"0\"\n   *    21) \"master-link-status\"\n   *    22) \"ok\"\n   *    23) \"master-host\"\n   *    24) \"localhost\"\n   *    25) \"master-port\"\n   *    26) \"6379\"\n   *    27) \"slave-priority\"\n   *    28) \"100\"\n   * </pre>\n   * @param masterName\n   * @return\n   */\n  @Override\n  @SuppressWarnings(\"rawtypes\")\n  public List<Map<String, String>> sentinelSlaves(String masterName) {\n    client.sentinel(Protocol.SENTINEL_SLAVES, masterName);\n    final List<Object> reply = client.getObjectMultiBulkReply();\n\n    final List<Map<String, String>> slaves = new ArrayList<Map<String, String>>();\n    for (Object obj : reply) {\n      slaves.add(BuilderFactory.STRING_MAP.build((List) obj));\n    }\n    return slaves;\n  }\n\n  @Override\n  public String sentinelFailover(String masterName) {\n    client.sentinel(Protocol.SENTINEL_FAILOVER, masterName);\n    return client.getStatusCodeReply();\n  }\n\n  @Override\n  public String sentinelMonitor(String masterName, String ip, int port, int quorum) {\n    client.sentinel(Protocol.SENTINEL_MONITOR, masterName, ip, String.valueOf(port),\n      String.valueOf(quorum));\n    return client.getStatusCodeReply();\n  }\n\n  @Override\n  public String sentinelRemove(String masterName) {\n    client.sentinel(Protocol.SENTINEL_REMOVE, masterName);\n    return client.getStatusCodeReply();\n  }\n\n  @Override\n  public String sentinelSet(String masterName, Map<String, String> parameterMap) {\n    int index = 0;\n    int paramsLength = parameterMap.size() * 2 + 2;\n    String[] params = new String[paramsLength];\n\n    params[index++] = Protocol.SENTINEL_SET;\n    params[index++] = masterName;\n    for (Entry<String, String> entry : parameterMap.entrySet()) {\n      params[index++] = entry.getKey();\n      params[index++] = entry.getValue();\n    }\n\n    client.sentinel(params);\n    return client.getStatusCodeReply();\n  }\n\n  public byte[] dump(final String key) {\n    checkIsInMultiOrPipeline();\n    client.dump(key);\n    return client.getBinaryBulkReply();\n  }\n\n  public String restore(final String key, final int ttl, final byte[] serializedValue) {\n    checkIsInMultiOrPipeline();\n    client.restore(key, ttl, serializedValue);\n    return client.getStatusCodeReply();\n  }\n\n  @Override\n  public Long pexpire(final String key, final long milliseconds) {\n    checkIsInMultiOrPipeline();\n    client.pexpire(key, milliseconds);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public Long pexpireAt(final String key, final long millisecondsTimestamp) {\n    checkIsInMultiOrPipeline();\n    client.pexpireAt(key, millisecondsTimestamp);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public Long pttl(final String key) {\n    checkIsInMultiOrPipeline();\n    client.pttl(key);\n    return client.getIntegerReply();\n  }\n\n  /**\n   * PSETEX works exactly like {@link #setex(String, int, String)} with the sole difference that the\n   * expire time is specified in milliseconds instead of seconds. Time complexity: O(1)\n   * @param key\n   * @param milliseconds\n   * @param value\n   * @return Status code reply\n   */\n\n  @Override\n  public String psetex(final String key, final long milliseconds, final String value) {\n    checkIsInMultiOrPipeline();\n    client.psetex(key, milliseconds, value);\n    return client.getStatusCodeReply();\n  }\n\n  public String clientKill(final String client) {\n    checkIsInMultiOrPipeline();\n    this.client.clientKill(client);\n    return this.client.getStatusCodeReply();\n  }\n\n  public String clientSetname(final String name) {\n    checkIsInMultiOrPipeline();\n    client.clientSetname(name);\n    return client.getStatusCodeReply();\n  }\n\n  public String migrate(final String host, final int port, final String key,\n      final int destinationDb, final int timeout) {\n    checkIsInMultiOrPipeline();\n    client.migrate(host, port, key, destinationDb, timeout);\n    return client.getStatusCodeReply();\n  }\n  \n  public String migrate(final String host, final int port,\n          final int destinationDb, final int timeout, final String... keys) {\n      checkIsInMultiOrPipeline();\n      client.migrate(host, port, destinationDb, timeout, keys);\n      return client.getStatusCodeReply();\n  }\n\n  @Override\n  public ScanResult<String> scan(final String cursor) {\n    return scan(cursor, new ScanParams());\n  }\n\n  @Override\n  public ScanResult<String> scan(final String cursor, final ScanParams params) {\n    checkIsInMultiOrPipeline();\n    client.scan(cursor, params);\n    List<Object> result = client.getObjectMultiBulkReply();\n    String newcursor = new String((byte[]) result.get(0));\n    List<String> results = new ArrayList<String>();\n    List<byte[]> rawResults = (List<byte[]>) result.get(1);\n    for (byte[] bs : rawResults) {\n      results.add(SafeEncoder.encode(bs));\n    }\n    return new ScanResult<String>(newcursor, results);\n  }\n\n  @Override\n  public ScanResult<Map.Entry<String, String>> hscan(final String key, final String cursor) {\n    return hscan(key, cursor, new ScanParams());\n  }\n\n  @Override\n  public ScanResult<Map.Entry<String, String>> hscan(final String key, final String cursor,\n      final ScanParams params) {\n    checkIsInMultiOrPipeline();\n    client.hscan(key, cursor, params);\n    List<Object> result = client.getObjectMultiBulkReply();\n    String newcursor = new String((byte[]) result.get(0));\n    List<Map.Entry<String, String>> results = new ArrayList<Map.Entry<String, String>>();\n    List<byte[]> rawResults = (List<byte[]>) result.get(1);\n    Iterator<byte[]> iterator = rawResults.iterator();\n    while (iterator.hasNext()) {\n      results.add(new AbstractMap.SimpleEntry<String, String>(SafeEncoder.encode(iterator.next()),\n          SafeEncoder.encode(iterator.next())));\n    }\n    return new ScanResult<Map.Entry<String, String>>(newcursor, results);\n  }\n\n  @Override\n  public ScanResult<String> sscan(final String key, final String cursor) {\n    return sscan(key, cursor, new ScanParams());\n  }\n\n  @Override\n  public ScanResult<String> sscan(final String key, final String cursor, final ScanParams params) {\n    checkIsInMultiOrPipeline();\n    client.sscan(key, cursor, params);\n    List<Object> result = client.getObjectMultiBulkReply();\n    String newcursor = new String((byte[]) result.get(0));\n    List<String> results = new ArrayList<String>();\n    List<byte[]> rawResults = (List<byte[]>) result.get(1);\n    for (byte[] bs : rawResults) {\n      results.add(SafeEncoder.encode(bs));\n    }\n    return new ScanResult<String>(newcursor, results);\n  }\n\n  @Override\n  public ScanResult<Tuple> zscan(final String key, final String cursor) {\n    return zscan(key, cursor, new ScanParams());\n  }\n\n  @Override\n  public ScanResult<Tuple> zscan(final String key, final String cursor, final ScanParams params) {\n    checkIsInMultiOrPipeline();\n    client.zscan(key, cursor, params);\n    List<Object> result = client.getObjectMultiBulkReply();\n    String newcursor = new String((byte[]) result.get(0));\n    List<Tuple> results = new ArrayList<Tuple>();\n    List<byte[]> rawResults = (List<byte[]>) result.get(1);\n    Iterator<byte[]> iterator = rawResults.iterator();\n    while (iterator.hasNext()) {\n      results.add(new Tuple(SafeEncoder.encode(iterator.next()), Double.valueOf(SafeEncoder\n          .encode(iterator.next()))));\n    }\n    return new ScanResult<Tuple>(newcursor, results);\n  }\n\n  @Override\n  public String clusterNodes() {\n    checkIsInMultiOrPipeline();\n    client.clusterNodes();\n    return client.getBulkReply();\n  }\n\n  @Override\n  public String readonly() {\n    client.readonly();\n    return client.getStatusCodeReply();\n  }\n\n  @Override\n  public String clusterMeet(final String ip, final int port) {\n    checkIsInMultiOrPipeline();\n    client.clusterMeet(ip, port);\n    return client.getStatusCodeReply();\n  }\n\n  @Override\n  public String clusterReset(final Reset resetType) {\n    checkIsInMultiOrPipeline();\n    client.clusterReset(resetType);\n    return client.getStatusCodeReply();\n  }\n\n  @Override\n  public String clusterAddSlots(final int... slots) {\n    checkIsInMultiOrPipeline();\n    client.clusterAddSlots(slots);\n    return client.getStatusCodeReply();\n  }\n\n  @Override\n  public String clusterDelSlots(final int... slots) {\n    checkIsInMultiOrPipeline();\n    client.clusterDelSlots(slots);\n    return client.getStatusCodeReply();\n  }\n\n  @Override\n  public String clusterInfo() {\n    checkIsInMultiOrPipeline();\n    client.clusterInfo();\n    return client.getStatusCodeReply();\n  }\n\n  @Override\n  public List<String> clusterGetKeysInSlot(final int slot, final int count) {\n    checkIsInMultiOrPipeline();\n    client.clusterGetKeysInSlot(slot, count);\n    return client.getMultiBulkReply();\n  }\n\n  @Override\n  public String clusterSetSlotNode(final int slot, final String nodeId) {\n    checkIsInMultiOrPipeline();\n    client.clusterSetSlotNode(slot, nodeId);\n    return client.getStatusCodeReply();\n  }\n\n  @Override\n  public String clusterSetSlotMigrating(final int slot, final String nodeId) {\n    checkIsInMultiOrPipeline();\n    client.clusterSetSlotMigrating(slot, nodeId);\n    return client.getStatusCodeReply();\n  }\n\n  @Override\n  public String clusterSetSlotImporting(final int slot, final String nodeId) {\n    checkIsInMultiOrPipeline();\n    client.clusterSetSlotImporting(slot, nodeId);\n    return client.getStatusCodeReply();\n  }\n\n  @Override\n  public String clusterSetSlotStable(final int slot) {\n    checkIsInMultiOrPipeline();\n    client.clusterSetSlotStable(slot);\n    return client.getStatusCodeReply();\n  }\n\n  @Override\n  public String clusterForget(final String nodeId) {\n    checkIsInMultiOrPipeline();\n    client.clusterForget(nodeId);\n    return client.getStatusCodeReply();\n  }\n\n  @Override\n  public String clusterFlushSlots() {\n    checkIsInMultiOrPipeline();\n    client.clusterFlushSlots();\n    return client.getStatusCodeReply();\n  }\n\n  @Override\n  public Long clusterKeySlot(final String key) {\n    checkIsInMultiOrPipeline();\n    client.clusterKeySlot(key);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public Long clusterCountKeysInSlot(final int slot) {\n    checkIsInMultiOrPipeline();\n    client.clusterCountKeysInSlot(slot);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public String clusterSaveConfig() {\n    checkIsInMultiOrPipeline();\n    client.clusterSaveConfig();\n    return client.getStatusCodeReply();\n  }\n\n  @Override\n  public String clusterReplicate(final String nodeId) {\n    checkIsInMultiOrPipeline();\n    client.clusterReplicate(nodeId);\n    return client.getStatusCodeReply();\n  }\n\n  @Override\n  public List<String> clusterSlaves(final String nodeId) {\n    checkIsInMultiOrPipeline();\n    client.clusterSlaves(nodeId);\n    return client.getMultiBulkReply();\n  }\n\n  @Override\n  public String clusterFailover() {\n    checkIsInMultiOrPipeline();\n    client.clusterFailover();\n    return client.getStatusCodeReply();\n  }\n\n  @Override\n  public List<Object> clusterSlots() {\n    checkIsInMultiOrPipeline();\n    client.clusterSlots();\n    return client.getObjectMultiBulkReply();\n  }\n\n  public String asking() {\n    checkIsInMultiOrPipeline();\n    client.asking();\n    return client.getStatusCodeReply();\n  }\n\n  public List<String> pubsubChannels(String pattern) {\n    checkIsInMultiOrPipeline();\n    client.pubsubChannels(pattern);\n    return client.getMultiBulkReply();\n  }\n\n  public Long pubsubNumPat() {\n    checkIsInMultiOrPipeline();\n    client.pubsubNumPat();\n    return client.getIntegerReply();\n  }\n\n  public Map<String, String> pubsubNumSub(String... channels) {\n    checkIsInMultiOrPipeline();\n    client.pubsubNumSub(channels);\n    return BuilderFactory.PUBSUB_NUMSUB_MAP.build(client.getBinaryMultiBulkReply());\n  }\n\n  @Override\n  public void close() {\n    if (dataSource != null) {\n      if (client.isBroken()) {\n        this.dataSource.returnBrokenResource(this);\n      } else {\n        this.dataSource.returnResource(this);\n      }\n    } else {\n      client.close();\n    }\n  }\n\n  public void setDataSource(JedisPoolAbstract jedisPool) {\n    this.dataSource = jedisPool;\n  }\n\n  @Override\n  public Long pfadd(final String key, final String... elements) {\n    checkIsInMultiOrPipeline();\n    client.pfadd(key, elements);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public long pfcount(final String key) {\n    checkIsInMultiOrPipeline();\n    client.pfcount(key);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public long pfcount(String... keys) {\n    checkIsInMultiOrPipeline();\n    client.pfcount(keys);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public String pfmerge(final String destkey, final String... sourcekeys) {\n    checkIsInMultiOrPipeline();\n    client.pfmerge(destkey, sourcekeys);\n    return client.getStatusCodeReply();\n  }\n\n  @Override\n  public List<String> blpop(int timeout, String key) {\n    return blpop(key, String.valueOf(timeout));\n  }\n\n  @Override\n  public List<String> brpop(int timeout, String key) {\n    return brpop(key, String.valueOf(timeout));\n  }\n\n  @Override\n  public Long geoadd(String key, double longitude, double latitude, String member) {\n    checkIsInMultiOrPipeline();\n    client.geoadd(key, longitude, latitude, member);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public Long geoadd(String key, Map<String, GeoCoordinate> memberCoordinateMap) {\n    checkIsInMultiOrPipeline();\n    client.geoadd(key, memberCoordinateMap);\n    return client.getIntegerReply();\n  }\n\n  @Override\n  public Double geodist(String key, String member1, String member2) {\n    checkIsInMultiOrPipeline();\n    client.geodist(key, member1, member2);\n    String dval = client.getBulkReply();\n    return (dval != null ? new Double(dval) : null);\n  }\n\n  @Override\n  public Double geodist(String key, String member1, String member2, GeoUnit unit) {\n    checkIsInMultiOrPipeline();\n    client.geodist(key, member1, member2, unit);\n    String dval = client.getBulkReply();\n    return (dval != null ? new Double(dval) : null);\n  }\n\n  @Override\n  public List<String> geohash(String key, String... members) {\n    checkIsInMultiOrPipeline();\n    client.geohash(key, members);\n    return client.getMultiBulkReply();\n  }\n\n  @Override\n  public List<GeoCoordinate> geopos(String key, String... members) {\n    checkIsInMultiOrPipeline();\n    client.geopos(key, members);\n    return BuilderFactory.GEO_COORDINATE_LIST.build(client.getObjectMultiBulkReply());\n  }\n\n  @Override\n  public List<GeoRadiusResponse> georadius(String key, double longitude, double latitude,\n      double radius, GeoUnit unit) {\n    checkIsInMultiOrPipeline();\n    client.georadius(key, longitude, latitude, radius, unit);\n    return BuilderFactory.GEORADIUS_WITH_PARAMS_RESULT.build(client.getObjectMultiBulkReply());\n  }\n\n  @Override\n  public List<GeoRadiusResponse> georadius(String key, double longitude, double latitude,\n      double radius, GeoUnit unit, GeoRadiusParam param) {\n    checkIsInMultiOrPipeline();\n    client.georadius(key, longitude, latitude, radius, unit, param);\n    return BuilderFactory.GEORADIUS_WITH_PARAMS_RESULT.build(client.getObjectMultiBulkReply());\n  }\n\n  @Override\n  public List<GeoRadiusResponse> georadiusByMember(String key, String member, double radius,\n      GeoUnit unit) {\n    checkIsInMultiOrPipeline();\n    client.georadiusByMember(key, member, radius, unit);\n    return BuilderFactory.GEORADIUS_WITH_PARAMS_RESULT.build(client.getObjectMultiBulkReply());\n  }\n\n  @Override\n  public List<GeoRadiusResponse> georadiusByMember(String key, String member, double radius,\n      GeoUnit unit, GeoRadiusParam param) {\n    checkIsInMultiOrPipeline();\n    client.georadiusByMember(key, member, radius, unit, param);\n    return BuilderFactory.GEORADIUS_WITH_PARAMS_RESULT.build(client.getObjectMultiBulkReply());\n\n  }\n\n  public String clusterFailoverForce() {\n    checkIsInMultiOrPipeline();\n    client.clusterFailoverForce();\n    return client.getStatusCodeReply();\n  }\n  \n  public String clusterFailoverTakeOver() {\n      checkIsInMultiOrPipeline();\n      client.clusterFailoverTakeOver();\n      return client.getStatusCodeReply();\n   }\n\n  public String configRewrite() {\n    checkIsInMultiOrPipeline();\n    client.configRewrite();\n    return client.getStatusCodeReply();\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/JedisCluster.java",
    "content": "package redis.clients.jedis;\n\nimport redis.clients.jedis.BinaryClient.LIST_POSITION;\nimport redis.clients.jedis.params.geo.GeoRadiusParam;\nimport redis.clients.jedis.params.sortedset.ZAddParams;\nimport redis.clients.jedis.params.sortedset.ZIncrByParams;\nimport redis.clients.jedis.commands.JedisClusterCommands;\nimport redis.clients.jedis.commands.JedisClusterScriptingCommands;\nimport redis.clients.jedis.commands.MultiKeyJedisClusterCommands;\nimport redis.clients.util.KeyMergeUtil;\n\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.Set;\n\nimport org.apache.commons.pool2.impl.GenericObjectPoolConfig;\n\nimport redis.clients.jedis.params.set.SetParams;\n\npublic class JedisCluster extends BinaryJedisCluster implements JedisClusterCommands,\n    MultiKeyJedisClusterCommands, JedisClusterScriptingCommands {\n  public static enum Reset {\n    SOFT, HARD\n  }\n\n  public JedisCluster(HostAndPort node) {\n\tthis(Collections.singleton(node), DEFAULT_TIMEOUT);\n  }\n\n  public JedisCluster(HostAndPort node, int timeout) {\n    this(Collections.singleton(node), timeout, DEFAULT_MAX_REDIRECTIONS);\n  }\n\n  public JedisCluster(HostAndPort node, int timeout, int maxRedirections) {\n    this(Collections.singleton(node), timeout, maxRedirections, new GenericObjectPoolConfig());\n  }\n\n  public JedisCluster(HostAndPort node, final GenericObjectPoolConfig poolConfig) {\n    this(Collections.singleton(node), DEFAULT_TIMEOUT, DEFAULT_MAX_REDIRECTIONS, poolConfig);\n  }\n\n  public JedisCluster(HostAndPort node, int timeout, final GenericObjectPoolConfig poolConfig) {\n    this(Collections.singleton(node), timeout, DEFAULT_MAX_REDIRECTIONS, poolConfig);\n  }\n\n  public JedisCluster(HostAndPort node, int timeout, int maxRedirections,\n      final GenericObjectPoolConfig poolConfig) {\n    this(Collections.singleton(node), timeout, maxRedirections, poolConfig);\n  }\n\n  public JedisCluster(HostAndPort node, int connectionTimeout, int soTimeout,\n      int maxRedirections, final GenericObjectPoolConfig poolConfig) {\n    super(Collections.singleton(node), connectionTimeout, soTimeout, maxRedirections, poolConfig);\n  }\n  \n  public JedisCluster(Set<HostAndPort> nodes) {\n    this(nodes, DEFAULT_TIMEOUT);\n  }\n\n  public JedisCluster(Set<HostAndPort> nodes, int timeout) {\n    this(nodes, timeout, DEFAULT_MAX_REDIRECTIONS);\n  }\n\n  public JedisCluster(Set<HostAndPort> nodes, int timeout, int maxRedirections) {\n    this(nodes, timeout, maxRedirections, new GenericObjectPoolConfig());\n  }\n\n  public JedisCluster(Set<HostAndPort> nodes, final GenericObjectPoolConfig poolConfig) {\n    this(nodes, DEFAULT_TIMEOUT, DEFAULT_MAX_REDIRECTIONS, poolConfig);\n  }\n\n  public JedisCluster(Set<HostAndPort> nodes, int timeout, final GenericObjectPoolConfig poolConfig) {\n    this(nodes, timeout, DEFAULT_MAX_REDIRECTIONS, poolConfig);\n  }\n\n  public JedisCluster(Set<HostAndPort> jedisClusterNode, int timeout, int maxRedirections,\n      final GenericObjectPoolConfig poolConfig) {\n    super(jedisClusterNode, timeout, maxRedirections, poolConfig);\n  }\n\n  public JedisCluster(Set<HostAndPort> jedisClusterNode, int connectionTimeout, int soTimeout,\n      int maxRedirections, final GenericObjectPoolConfig poolConfig) {\n    super(jedisClusterNode, connectionTimeout, soTimeout, maxRedirections, poolConfig);\n  }\n\n  @Override\n  public String set(final String key, final String value) {\n    return new JedisClusterCommand<String>(connectionHandler, maxRedirections) {\n      @Override\n      public String execute(Jedis connection) {\n        return connection.set(key, value);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public String set(final String key, final String value, final SetParams params) {\n    return new JedisClusterCommand<String>(connectionHandler, maxRedirections) {\n      @Override\n      public String execute(Jedis connection) {\n        return connection.set(key, value, params);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public String get(final String key) {\n    return new JedisClusterCommand<String>(connectionHandler, maxRedirections) {\n      @Override\n      public String execute(Jedis connection) {\n        return connection.get(key);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Boolean exists(final String key) {\n    return new JedisClusterCommand<Boolean>(connectionHandler, maxRedirections) {\n      @Override\n      public Boolean execute(Jedis connection) {\n        return connection.exists(key);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long exists(final String... keys) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.exists(keys);\n      }\n    }.run(keys.length, keys);\n  }\n\n  @Override\n  public Long persist(final String key) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.persist(key);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public String type(final String key) {\n    return new JedisClusterCommand<String>(connectionHandler, maxRedirections) {\n      @Override\n      public String execute(Jedis connection) {\n        return connection.type(key);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long expire(final String key, final int seconds) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.expire(key, seconds);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long pexpire(final String key, final long milliseconds) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.pexpire(key, milliseconds);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long expireAt(final String key, final long unixTime) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.expireAt(key, unixTime);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long pexpireAt(final String key, final long millisecondsTimestamp) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.pexpireAt(key, millisecondsTimestamp);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long ttl(final String key) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.ttl(key);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Boolean setbit(final String key, final long offset, final boolean value) {\n    return new JedisClusterCommand<Boolean>(connectionHandler, maxRedirections) {\n      @Override\n      public Boolean execute(Jedis connection) {\n        return connection.setbit(key, offset, value);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Boolean setbit(final String key, final long offset, final String value) {\n    return new JedisClusterCommand<Boolean>(connectionHandler, maxRedirections) {\n      @Override\n      public Boolean execute(Jedis connection) {\n        return connection.setbit(key, offset, value);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Boolean getbit(final String key, final long offset) {\n    return new JedisClusterCommand<Boolean>(connectionHandler, maxRedirections) {\n      @Override\n      public Boolean execute(Jedis connection) {\n        return connection.getbit(key, offset);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long setrange(final String key, final long offset, final String value) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.setrange(key, offset, value);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public String getrange(final String key, final long startOffset, final long endOffset) {\n    return new JedisClusterCommand<String>(connectionHandler, maxRedirections) {\n      @Override\n      public String execute(Jedis connection) {\n        return connection.getrange(key, startOffset, endOffset);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public String getSet(final String key, final String value) {\n    return new JedisClusterCommand<String>(connectionHandler, maxRedirections) {\n      @Override\n      public String execute(Jedis connection) {\n        return connection.getSet(key, value);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long setnx(final String key, final String value) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.setnx(key, value);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public String setex(final String key, final int seconds, final String value) {\n    return new JedisClusterCommand<String>(connectionHandler, maxRedirections) {\n      @Override\n      public String execute(Jedis connection) {\n        return connection.setex(key, seconds, value);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long decrBy(final String key, final long integer) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.decrBy(key, integer);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long decr(final String key) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.decr(key);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long incrBy(final String key, final long integer) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.incrBy(key, integer);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Double incrByFloat(final String key, final double value) {\n    return new JedisClusterCommand<Double>(connectionHandler, maxRedirections) {\n      @Override\n      public Double execute(Jedis connection) {\n        return connection.incrByFloat(key, value);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long incr(final String key) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.incr(key);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long append(final String key, final String value) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.append(key, value);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public String substr(final String key, final int start, final int end) {\n    return new JedisClusterCommand<String>(connectionHandler, maxRedirections) {\n      @Override\n      public String execute(Jedis connection) {\n        return connection.substr(key, start, end);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long hset(final String key, final String field, final String value) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.hset(key, field, value);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public String hget(final String key, final String field) {\n    return new JedisClusterCommand<String>(connectionHandler, maxRedirections) {\n      @Override\n      public String execute(Jedis connection) {\n        return connection.hget(key, field);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long hsetnx(final String key, final String field, final String value) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.hsetnx(key, field, value);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public String hmset(final String key, final Map<String, String> hash) {\n    return new JedisClusterCommand<String>(connectionHandler, maxRedirections) {\n      @Override\n      public String execute(Jedis connection) {\n        return connection.hmset(key, hash);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public List<String> hmget(final String key, final String... fields) {\n    return new JedisClusterCommand<List<String>>(connectionHandler, maxRedirections) {\n      @Override\n      public List<String> execute(Jedis connection) {\n        return connection.hmget(key, fields);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long hincrBy(final String key, final String field, final long value) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.hincrBy(key, field, value);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Boolean hexists(final String key, final String field) {\n    return new JedisClusterCommand<Boolean>(connectionHandler, maxRedirections) {\n      @Override\n      public Boolean execute(Jedis connection) {\n        return connection.hexists(key, field);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long hdel(final String key, final String... field) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.hdel(key, field);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long hlen(final String key) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.hlen(key);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Set<String> hkeys(final String key) {\n    return new JedisClusterCommand<Set<String>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<String> execute(Jedis connection) {\n        return connection.hkeys(key);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public List<String> hvals(final String key) {\n    return new JedisClusterCommand<List<String>>(connectionHandler, maxRedirections) {\n      @Override\n      public List<String> execute(Jedis connection) {\n        return connection.hvals(key);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Map<String, String> hgetAll(final String key) {\n    return new JedisClusterCommand<Map<String, String>>(connectionHandler, maxRedirections) {\n      @Override\n      public Map<String, String> execute(Jedis connection) {\n        return connection.hgetAll(key);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long rpush(final String key, final String... string) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.rpush(key, string);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long lpush(final String key, final String... string) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.lpush(key, string);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long llen(final String key) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.llen(key);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public List<String> lrange(final String key, final long start, final long end) {\n    return new JedisClusterCommand<List<String>>(connectionHandler, maxRedirections) {\n      @Override\n      public List<String> execute(Jedis connection) {\n        return connection.lrange(key, start, end);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public String ltrim(final String key, final long start, final long end) {\n    return new JedisClusterCommand<String>(connectionHandler, maxRedirections) {\n      @Override\n      public String execute(Jedis connection) {\n        return connection.ltrim(key, start, end);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public String lindex(final String key, final long index) {\n    return new JedisClusterCommand<String>(connectionHandler, maxRedirections) {\n      @Override\n      public String execute(Jedis connection) {\n        return connection.lindex(key, index);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public String lset(final String key, final long index, final String value) {\n    return new JedisClusterCommand<String>(connectionHandler, maxRedirections) {\n      @Override\n      public String execute(Jedis connection) {\n        return connection.lset(key, index, value);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long lrem(final String key, final long count, final String value) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.lrem(key, count, value);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public String lpop(final String key) {\n    return new JedisClusterCommand<String>(connectionHandler, maxRedirections) {\n      @Override\n      public String execute(Jedis connection) {\n        return connection.lpop(key);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public String rpop(final String key) {\n    return new JedisClusterCommand<String>(connectionHandler, maxRedirections) {\n      @Override\n      public String execute(Jedis connection) {\n        return connection.rpop(key);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long sadd(final String key, final String... member) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.sadd(key, member);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Set<String> smembers(final String key) {\n    return new JedisClusterCommand<Set<String>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<String> execute(Jedis connection) {\n        return connection.smembers(key);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long srem(final String key, final String... member) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.srem(key, member);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public String spop(final String key) {\n    return new JedisClusterCommand<String>(connectionHandler, maxRedirections) {\n      @Override\n      public String execute(Jedis connection) {\n        return connection.spop(key);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Set<String> spop(final String key, final long count) {\n    return new JedisClusterCommand<Set<String>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<String> execute(Jedis connection) {\n        return connection.spop(key, count);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long scard(final String key) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.scard(key);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Boolean sismember(final String key, final String member) {\n    return new JedisClusterCommand<Boolean>(connectionHandler, maxRedirections) {\n      @Override\n      public Boolean execute(Jedis connection) {\n        return connection.sismember(key, member);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public String srandmember(final String key) {\n    return new JedisClusterCommand<String>(connectionHandler, maxRedirections) {\n      @Override\n      public String execute(Jedis connection) {\n        return connection.srandmember(key);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public List<String> srandmember(final String key, final int count) {\n    return new JedisClusterCommand<List<String>>(connectionHandler, maxRedirections) {\n      @Override\n      public List<String> execute(Jedis connection) {\n        return connection.srandmember(key, count);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long strlen(final String key) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.strlen(key);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long zadd(final String key, final double score, final String member) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.zadd(key, score, member);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long zadd(final String key, final double score, final String member,\n      final ZAddParams params) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.zadd(key, score, member, params);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long zadd(final String key, final Map<String, Double> scoreMembers) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.zadd(key, scoreMembers);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long zadd(final String key, final Map<String, Double> scoreMembers, final ZAddParams params) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.zadd(key, scoreMembers, params);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Set<String> zrange(final String key, final long start, final long end) {\n    return new JedisClusterCommand<Set<String>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<String> execute(Jedis connection) {\n        return connection.zrange(key, start, end);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long zrem(final String key, final String... member) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.zrem(key, member);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Double zincrby(final String key, final double score, final String member) {\n    return new JedisClusterCommand<Double>(connectionHandler, maxRedirections) {\n      @Override\n      public Double execute(Jedis connection) {\n        return connection.zincrby(key, score, member);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Double zincrby(final String key, final double score, final String member,\n      final ZIncrByParams params) {\n    return new JedisClusterCommand<Double>(connectionHandler, maxRedirections) {\n      @Override\n      public Double execute(Jedis connection) {\n        return connection.zincrby(key, score, member, params);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long zrank(final String key, final String member) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.zrank(key, member);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long zrevrank(final String key, final String member) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.zrevrank(key, member);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Set<String> zrevrange(final String key, final long start, final long end) {\n    return new JedisClusterCommand<Set<String>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<String> execute(Jedis connection) {\n        return connection.zrevrange(key, start, end);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Set<Tuple> zrangeWithScores(final String key, final long start, final long end) {\n    return new JedisClusterCommand<Set<Tuple>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<Tuple> execute(Jedis connection) {\n        return connection.zrangeWithScores(key, start, end);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Set<Tuple> zrevrangeWithScores(final String key, final long start, final long end) {\n    return new JedisClusterCommand<Set<Tuple>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<Tuple> execute(Jedis connection) {\n        return connection.zrevrangeWithScores(key, start, end);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long zcard(final String key) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.zcard(key);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Double zscore(final String key, final String member) {\n    return new JedisClusterCommand<Double>(connectionHandler, maxRedirections) {\n      @Override\n      public Double execute(Jedis connection) {\n        return connection.zscore(key, member);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public List<String> sort(final String key) {\n    return new JedisClusterCommand<List<String>>(connectionHandler, maxRedirections) {\n      @Override\n      public List<String> execute(Jedis connection) {\n        return connection.sort(key);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public List<String> sort(final String key, final SortingParams sortingParameters) {\n    return new JedisClusterCommand<List<String>>(connectionHandler, maxRedirections) {\n      @Override\n      public List<String> execute(Jedis connection) {\n        return connection.sort(key, sortingParameters);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long zcount(final String key, final double min, final double max) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.zcount(key, min, max);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long zcount(final String key, final String min, final String max) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.zcount(key, min, max);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Set<String> zrangeByScore(final String key, final double min, final double max) {\n    return new JedisClusterCommand<Set<String>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<String> execute(Jedis connection) {\n        return connection.zrangeByScore(key, min, max);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Set<String> zrangeByScore(final String key, final String min, final String max) {\n    return new JedisClusterCommand<Set<String>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<String> execute(Jedis connection) {\n        return connection.zrangeByScore(key, min, max);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Set<String> zrevrangeByScore(final String key, final double max, final double min) {\n    return new JedisClusterCommand<Set<String>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<String> execute(Jedis connection) {\n        return connection.zrevrangeByScore(key, max, min);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Set<String> zrangeByScore(final String key, final double min, final double max,\n      final int offset, final int count) {\n    return new JedisClusterCommand<Set<String>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<String> execute(Jedis connection) {\n        return connection.zrangeByScore(key, min, max, offset, count);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Set<String> zrevrangeByScore(final String key, final String max, final String min) {\n    return new JedisClusterCommand<Set<String>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<String> execute(Jedis connection) {\n        return connection.zrevrangeByScore(key, max, min);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Set<String> zrangeByScore(final String key, final String min, final String max,\n      final int offset, final int count) {\n    return new JedisClusterCommand<Set<String>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<String> execute(Jedis connection) {\n        return connection.zrangeByScore(key, min, max, offset, count);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Set<String> zrevrangeByScore(final String key, final double max, final double min,\n      final int offset, final int count) {\n    return new JedisClusterCommand<Set<String>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<String> execute(Jedis connection) {\n        return connection.zrevrangeByScore(key, max, min, offset, count);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Set<Tuple> zrangeByScoreWithScores(final String key, final double min, final double max) {\n    return new JedisClusterCommand<Set<Tuple>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<Tuple> execute(Jedis connection) {\n        return connection.zrangeByScoreWithScores(key, min, max);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Set<Tuple> zrevrangeByScoreWithScores(final String key, final double max, final double min) {\n    return new JedisClusterCommand<Set<Tuple>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<Tuple> execute(Jedis connection) {\n        return connection.zrevrangeByScoreWithScores(key, max, min);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Set<Tuple> zrangeByScoreWithScores(final String key, final double min, final double max,\n      final int offset, final int count) {\n    return new JedisClusterCommand<Set<Tuple>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<Tuple> execute(Jedis connection) {\n        return connection.zrangeByScoreWithScores(key, min, max, offset, count);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Set<String> zrevrangeByScore(final String key, final String max, final String min,\n      final int offset, final int count) {\n    return new JedisClusterCommand<Set<String>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<String> execute(Jedis connection) {\n        return connection.zrevrangeByScore(key, max, min, offset, count);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Set<Tuple> zrangeByScoreWithScores(final String key, final String min, final String max) {\n    return new JedisClusterCommand<Set<Tuple>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<Tuple> execute(Jedis connection) {\n        return connection.zrangeByScoreWithScores(key, min, max);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Set<Tuple> zrevrangeByScoreWithScores(final String key, final String max, final String min) {\n    return new JedisClusterCommand<Set<Tuple>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<Tuple> execute(Jedis connection) {\n        return connection.zrevrangeByScoreWithScores(key, max, min);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Set<Tuple> zrangeByScoreWithScores(final String key, final String min, final String max,\n      final int offset, final int count) {\n    return new JedisClusterCommand<Set<Tuple>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<Tuple> execute(Jedis connection) {\n        return connection.zrangeByScoreWithScores(key, min, max, offset, count);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Set<Tuple> zrevrangeByScoreWithScores(final String key, final double max,\n      final double min, final int offset, final int count) {\n    return new JedisClusterCommand<Set<Tuple>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<Tuple> execute(Jedis connection) {\n        return connection.zrevrangeByScoreWithScores(key, max, min, offset, count);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Set<Tuple> zrevrangeByScoreWithScores(final String key, final String max,\n      final String min, final int offset, final int count) {\n    return new JedisClusterCommand<Set<Tuple>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<Tuple> execute(Jedis connection) {\n        return connection.zrevrangeByScoreWithScores(key, max, min, offset, count);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long zremrangeByRank(final String key, final long start, final long end) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.zremrangeByRank(key, start, end);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long zremrangeByScore(final String key, final double start, final double end) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.zremrangeByScore(key, start, end);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long zremrangeByScore(final String key, final String start, final String end) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.zremrangeByScore(key, start, end);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long zlexcount(final String key, final String min, final String max) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.zlexcount(key, min, max);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Set<String> zrangeByLex(final String key, final String min, final String max) {\n    return new JedisClusterCommand<Set<String>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<String> execute(Jedis connection) {\n        return connection.zrangeByLex(key, min, max);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Set<String> zrangeByLex(final String key, final String min, final String max,\n      final int offset, final int count) {\n    return new JedisClusterCommand<Set<String>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<String> execute(Jedis connection) {\n        return connection.zrangeByLex(key, min, max, offset, count);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Set<String> zrevrangeByLex(final String key, final String max, final String min) {\n    return new JedisClusterCommand<Set<String>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<String> execute(Jedis connection) {\n        return connection.zrevrangeByLex(key, max, min);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Set<String> zrevrangeByLex(final String key, final String max, final String min,\n      final int offset, final int count) {\n    return new JedisClusterCommand<Set<String>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<String> execute(Jedis connection) {\n        return connection.zrevrangeByLex(key, max, min, offset, count);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long zremrangeByLex(final String key, final String min, final String max) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.zremrangeByLex(key, min, max);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long linsert(final String key, final LIST_POSITION where, final String pivot,\n      final String value) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.linsert(key, where, pivot, value);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long lpushx(final String key, final String... string) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.lpushx(key, string);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long rpushx(final String key, final String... string) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.rpushx(key, string);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long del(final String key) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.del(key);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public String echo(final String string) {\n    // note that it'll be run from arbitary node\n    return new JedisClusterCommand<String>(connectionHandler, maxRedirections) {\n      @Override\n      public String execute(Jedis connection) {\n        return connection.echo(string);\n      }\n    }.run(string);\n  }\n\n  @Override\n  public Long bitcount(final String key) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.bitcount(key);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long bitcount(final String key, final long start, final long end) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.bitcount(key, start, end);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public ScanResult<Entry<String, String>> hscan(final String key, final String cursor) {\n    return new JedisClusterCommand<ScanResult<Entry<String, String>>>(connectionHandler,\n        maxRedirections) {\n      @Override\n      public ScanResult<Entry<String, String>> execute(Jedis connection) {\n        return connection.hscan(key, cursor);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public ScanResult<String> sscan(final String key, final String cursor) {\n    return new JedisClusterCommand<ScanResult<String>>(connectionHandler, maxRedirections) {\n      @Override\n      public ScanResult<String> execute(Jedis connection) {\n        return connection.sscan(key, cursor);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public ScanResult<Tuple> zscan(final String key, final String cursor) {\n    return new JedisClusterCommand<ScanResult<Tuple>>(connectionHandler, maxRedirections) {\n      @Override\n      public ScanResult<Tuple> execute(Jedis connection) {\n        return connection.zscan(key, cursor);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long pfadd(final String key, final String... elements) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.pfadd(key, elements);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public long pfcount(final String key) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.pfcount(key);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public List<String> blpop(final int timeout, final String key) {\n    return new JedisClusterCommand<List<String>>(connectionHandler, maxRedirections) {\n      @Override\n      public List<String> execute(Jedis connection) {\n        return connection.blpop(timeout, key);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public List<String> brpop(final int timeout, final String key) {\n    return new JedisClusterCommand<List<String>>(connectionHandler, maxRedirections) {\n      @Override\n      public List<String> execute(Jedis connection) {\n        return connection.brpop(timeout, key);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long del(final String... keys) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.del(keys);\n      }\n    }.run(keys.length, keys);\n  }\n\n  @Override\n  public List<String> blpop(final int timeout, final String... keys) {\n    return new JedisClusterCommand<List<String>>(connectionHandler, maxRedirections) {\n      @Override\n      public List<String> execute(Jedis connection) {\n        return connection.blpop(timeout, keys);\n      }\n    }.run(keys.length, keys);\n\n  }\n\n  @Override\n  public List<String> brpop(final int timeout, final String... keys) {\n    return new JedisClusterCommand<List<String>>(connectionHandler, maxRedirections) {\n      @Override\n      public List<String> execute(Jedis connection) {\n        return connection.brpop(timeout, keys);\n      }\n    }.run(keys.length, keys);\n  }\n\n  @Override\n  public List<String> mget(final String... keys) {\n    return new JedisClusterCommand<List<String>>(connectionHandler, maxRedirections) {\n      @Override\n      public List<String> execute(Jedis connection) {\n        return connection.mget(keys);\n      }\n    }.run(keys.length, keys);\n  }\n\n  @Override\n  public String mset(final String... keysvalues) {\n    String[] keys = new String[keysvalues.length / 2];\n\n    for (int keyIdx = 0; keyIdx < keys.length; keyIdx++) {\n      keys[keyIdx] = keysvalues[keyIdx * 2];\n    }\n\n    return new JedisClusterCommand<String>(connectionHandler, maxRedirections) {\n      @Override\n      public String execute(Jedis connection) {\n        return connection.mset(keysvalues);\n      }\n    }.run(keys.length, keys);\n  }\n\n  @Override\n  public Long msetnx(final String... keysvalues) {\n    String[] keys = new String[keysvalues.length / 2];\n\n    for (int keyIdx = 0; keyIdx < keys.length; keyIdx++) {\n      keys[keyIdx] = keysvalues[keyIdx * 2];\n    }\n\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.msetnx(keysvalues);\n      }\n    }.run(keys.length, keys);\n  }\n\n  @Override\n  public String rename(final String oldkey, final String newkey) {\n    return new JedisClusterCommand<String>(connectionHandler, maxRedirections) {\n      @Override\n      public String execute(Jedis connection) {\n        return connection.rename(oldkey, newkey);\n      }\n    }.run(2, oldkey, newkey);\n  }\n\n  @Override\n  public Long renamenx(final String oldkey, final String newkey) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.renamenx(oldkey, newkey);\n      }\n    }.run(2, oldkey, newkey);\n  }\n\n  @Override\n  public String rpoplpush(final String srckey, final String dstkey) {\n    return new JedisClusterCommand<String>(connectionHandler, maxRedirections) {\n      @Override\n      public String execute(Jedis connection) {\n        return connection.rpoplpush(srckey, dstkey);\n      }\n    }.run(2, srckey, dstkey);\n  }\n\n  @Override\n  public Set<String> sdiff(final String... keys) {\n    return new JedisClusterCommand<Set<String>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<String> execute(Jedis connection) {\n        return connection.sdiff(keys);\n      }\n    }.run(keys.length, keys);\n  }\n\n  @Override\n  public Long sdiffstore(final String dstkey, final String... keys) {\n    String[] mergedKeys = KeyMergeUtil.merge(dstkey, keys);\n\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.sdiffstore(dstkey, keys);\n      }\n    }.run(mergedKeys.length, mergedKeys);\n  }\n\n  @Override\n  public Set<String> sinter(final String... keys) {\n    return new JedisClusterCommand<Set<String>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<String> execute(Jedis connection) {\n        return connection.sinter(keys);\n      }\n    }.run(keys.length, keys);\n  }\n\n  @Override\n  public Long sinterstore(final String dstkey, final String... keys) {\n    String[] mergedKeys = KeyMergeUtil.merge(dstkey, keys);\n\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.sinterstore(dstkey, keys);\n      }\n    }.run(mergedKeys.length, mergedKeys);\n  }\n\n  @Override\n  public Long smove(final String srckey, final String dstkey, final String member) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.smove(srckey, dstkey, member);\n      }\n    }.run(2, srckey, dstkey);\n  }\n\n  @Override\n  public Long sort(final String key, final SortingParams sortingParameters, final String dstkey) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.sort(key, sortingParameters, dstkey);\n      }\n    }.run(2, key, dstkey);\n  }\n\n  @Override\n  public Long sort(final String key, final String dstkey) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.sort(key, dstkey);\n      }\n    }.run(2, key, dstkey);\n  }\n\n  @Override\n  public Set<String> sunion(final String... keys) {\n    return new JedisClusterCommand<Set<String>>(connectionHandler, maxRedirections) {\n      @Override\n      public Set<String> execute(Jedis connection) {\n        return connection.sunion(keys);\n      }\n    }.run(keys.length, keys);\n  }\n\n  @Override\n  public Long sunionstore(final String dstkey, final String... keys) {\n    String[] wholeKeys = KeyMergeUtil.merge(dstkey, keys);\n\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.sunionstore(dstkey, keys);\n      }\n    }.run(wholeKeys.length, wholeKeys);\n  }\n\n  @Override\n  public Long zinterstore(final String dstkey, final String... sets) {\n    String[] wholeKeys = KeyMergeUtil.merge(dstkey, sets);\n\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.zinterstore(dstkey, sets);\n      }\n    }.run(wholeKeys.length, wholeKeys);\n  }\n\n  @Override\n  public Long zinterstore(final String dstkey, final ZParams params, final String... sets) {\n    String[] mergedKeys = KeyMergeUtil.merge(dstkey, sets);\n\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.zinterstore(dstkey, params, sets);\n      }\n    }.run(mergedKeys.length, mergedKeys);\n  }\n\n  @Override\n  public Long zunionstore(final String dstkey, final String... sets) {\n    String[] mergedKeys = KeyMergeUtil.merge(dstkey, sets);\n\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.zunionstore(dstkey, sets);\n      }\n    }.run(mergedKeys.length, mergedKeys);\n  }\n\n  @Override\n  public Long zunionstore(final String dstkey, final ZParams params, final String... sets) {\n    String[] mergedKeys = KeyMergeUtil.merge(dstkey, sets);\n\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.zunionstore(dstkey, params, sets);\n      }\n    }.run(mergedKeys.length, mergedKeys);\n  }\n\n  @Override\n  public String brpoplpush(final String source, final String destination, final int timeout) {\n    return new JedisClusterCommand<String>(connectionHandler, maxRedirections) {\n      @Override\n      public String execute(Jedis connection) {\n        return connection.brpoplpush(source, destination, timeout);\n      }\n    }.run(2, source, destination);\n  }\n\n  @Override\n  public Long publish(final String channel, final String message) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.publish(channel, message);\n      }\n    }.runWithAnyNode();\n  }\n\n  @Override\n  public void subscribe(final JedisPubSub jedisPubSub, final String... channels) {\n    new JedisClusterCommand<Integer>(connectionHandler, maxRedirections) {\n      @Override\n      public Integer execute(Jedis connection) {\n        connection.subscribe(jedisPubSub, channels);\n        return 0;\n      }\n    }.runWithAnyNode();\n  }\n\n  @Override\n  public void psubscribe(final JedisPubSub jedisPubSub, final String... patterns) {\n    new JedisClusterCommand<Integer>(connectionHandler, maxRedirections) {\n      @Override\n      public Integer execute(Jedis connection) {\n        connection.subscribe(jedisPubSub, patterns);\n        return 0;\n      }\n    }.runWithAnyNode();\n  }\n\n  @Override\n  public Long bitop(final BitOP op, final String destKey, final String... srcKeys) {\n    String[] mergedKeys = KeyMergeUtil.merge(destKey, srcKeys);\n\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.bitop(op, destKey, srcKeys);\n      }\n    }.run(mergedKeys.length, mergedKeys);\n  }\n\n  @Override\n  public String pfmerge(final String destkey, final String... sourcekeys) {\n    String[] mergedKeys = KeyMergeUtil.merge(destkey, sourcekeys);\n\n    return new JedisClusterCommand<String>(connectionHandler, maxRedirections) {\n      @Override\n      public String execute(Jedis connection) {\n        return connection.pfmerge(destkey, sourcekeys);\n      }\n    }.run(mergedKeys.length, mergedKeys);\n  }\n\n  @Override\n  public long pfcount(final String... keys) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.pfcount(keys);\n      }\n    }.run(keys.length, keys);\n  }\n\n  @Override\n  public Object eval(final String script, final int keyCount, final String... params) {\n    return new JedisClusterCommand<Object>(connectionHandler, maxRedirections) {\n      @Override\n      public Object execute(Jedis connection) {\n        return connection.eval(script, keyCount, params);\n      }\n    }.run(keyCount, params);\n  }\n\n  @Override\n  public Object eval(final String script, final String key) {\n    return new JedisClusterCommand<Object>(connectionHandler, maxRedirections) {\n      @Override\n      public Object execute(Jedis connection) {\n        return connection.eval(script);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Object eval(final String script, final List<String> keys, final List<String> args) {\n    return new JedisClusterCommand<Object>(connectionHandler, maxRedirections) {\n      @Override\n      public Object execute(Jedis connection) {\n        return connection.eval(script, keys, args);\n      }\n    }.run(keys.size(), keys.toArray(new String[keys.size()]));\n  }\n\n  @Override\n  public Object evalsha(final String sha1, final int keyCount, final String... params) {\n    return new JedisClusterCommand<Object>(connectionHandler, maxRedirections) {\n      @Override\n      public Object execute(Jedis connection) {\n        return connection.evalsha(sha1, keyCount, params);\n      }\n    }.run(keyCount, params);\n  }\n\n  @Override\n  public Object evalsha(final String sha1, final List<String> keys, final List<String> args) {\n    return new JedisClusterCommand<Object>(connectionHandler, maxRedirections) {\n      @Override\n      public Object execute(Jedis connection) {\n        return connection.evalsha(sha1, keys, args);\n      }\n    }.run(keys.size(), keys.toArray(new String[keys.size()]));\n  }\n\n  @Override\n  public Object evalsha(final String script, final String key) {\n    return new JedisClusterCommand<Object>(connectionHandler, maxRedirections) {\n      @Override\n      public Object execute(Jedis connection) {\n        return connection.evalsha(script);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Boolean scriptExists(final String sha1, final String key) {\n    return new JedisClusterCommand<Boolean>(connectionHandler, maxRedirections) {\n      @Override\n      public Boolean execute(Jedis connection) {\n        return connection.scriptExists(sha1);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public List<Boolean> scriptExists(final String key, final String... sha1) {\n    return new JedisClusterCommand<List<Boolean>>(connectionHandler, maxRedirections) {\n      @Override\n      public List<Boolean> execute(Jedis connection) {\n        return connection.scriptExists(sha1);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public String scriptLoad(final String script, final String key) {\n    return new JedisClusterCommand<String>(connectionHandler, maxRedirections) {\n      @Override\n      public String execute(Jedis connection) {\n        return connection.scriptLoad(script);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long geoadd(final String key, final double longitude, final double latitude,\n      final String member) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.geoadd(key, longitude, latitude, member);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Long geoadd(final String key, final Map<String, GeoCoordinate> memberCoordinateMap) {\n    return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n      @Override\n      public Long execute(Jedis connection) {\n        return connection.geoadd(key, memberCoordinateMap);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Double geodist(final String key, final String member1, final String member2) {\n    return new JedisClusterCommand<Double>(connectionHandler, maxRedirections) {\n      @Override\n      public Double execute(Jedis connection) {\n        return connection.geodist(key, member1, member2);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public Double geodist(final String key, final String member1, final String member2,\n      final GeoUnit unit) {\n    return new JedisClusterCommand<Double>(connectionHandler, maxRedirections) {\n      @Override\n      public Double execute(Jedis connection) {\n        return connection.geodist(key, member1, member2, unit);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public List<String> geohash(final String key, final String... members) {\n    return new JedisClusterCommand<List<String>>(connectionHandler, maxRedirections) {\n      @Override\n      public List<String> execute(Jedis connection) {\n        return connection.geohash(key, members);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public List<GeoCoordinate> geopos(final String key, final String... members) {\n    return new JedisClusterCommand<List<GeoCoordinate>>(connectionHandler, maxRedirections) {\n      @Override\n      public List<GeoCoordinate> execute(Jedis connection) {\n        return connection.geopos(key, members);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public List<GeoRadiusResponse> georadius(final String key, final double longitude,\n      final double latitude, final double radius, final GeoUnit unit) {\n    return new JedisClusterCommand<List<GeoRadiusResponse>>(connectionHandler, maxRedirections) {\n      @Override\n      public List<GeoRadiusResponse> execute(Jedis connection) {\n        return connection.georadius(key, longitude, latitude, radius, unit);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public List<GeoRadiusResponse> georadius(final String key, final double longitude,\n      final double latitude, final double radius, final GeoUnit unit, final GeoRadiusParam param) {\n    return new JedisClusterCommand<List<GeoRadiusResponse>>(connectionHandler, maxRedirections) {\n      @Override\n      public List<GeoRadiusResponse> execute(Jedis connection) {\n        return connection.georadius(key, longitude, latitude, radius, unit, param);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public List<GeoRadiusResponse> georadiusByMember(final String key, final String member,\n      final double radius, final GeoUnit unit) {\n    return new JedisClusterCommand<List<GeoRadiusResponse>>(connectionHandler, maxRedirections) {\n      @Override\n      public List<GeoRadiusResponse> execute(Jedis connection) {\n        return connection.georadiusByMember(key, member, radius, unit);\n      }\n    }.run(key);\n  }\n\n  @Override\n  public List<GeoRadiusResponse> georadiusByMember(final String key, final String member,\n      final double radius, final GeoUnit unit, final GeoRadiusParam param) {\n    return new JedisClusterCommand<List<GeoRadiusResponse>>(connectionHandler, maxRedirections) {\n      @Override\n      public List<GeoRadiusResponse> execute(Jedis connection) {\n        return connection.georadiusByMember(key, member, radius, unit, param);\n      }\n    }.run(key);\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/JedisClusterCommand.java",
    "content": "package redis.clients.jedis;\n\nimport com.sohu.tv.jedis.stat.data.UsefulDataCollector;\nimport com.sohu.tv.jedis.stat.enums.ClientExceptionType;\n\nimport redis.clients.jedis.exceptions.JedisAskDataException;\nimport redis.clients.jedis.exceptions.JedisClusterException;\nimport redis.clients.jedis.exceptions.JedisClusterMaxRedirectionsException;\nimport redis.clients.jedis.exceptions.JedisConnectionException;\nimport redis.clients.jedis.exceptions.JedisMovedDataException;\nimport redis.clients.jedis.exceptions.JedisRedirectionException;\nimport redis.clients.util.JedisClusterCRC16;\nimport redis.clients.util.SafeEncoder;\n\npublic abstract class JedisClusterCommand<T> {\n\n  private JedisClusterConnectionHandler connectionHandler;\n  private int redirections;\n  private ThreadLocal<Jedis> askConnection = new ThreadLocal<Jedis>();\n\n  public JedisClusterCommand(JedisClusterConnectionHandler connectionHandler, int maxRedirections) {\n    this.connectionHandler = connectionHandler;\n    this.redirections = maxRedirections;\n  }\n\n  public abstract T execute(Jedis connection);\n\n  public T run(String key) {\n    if (key == null) {\n      throw new JedisClusterException(\"No way to dispatch this command to Redis Cluster.\");\n    }\n\n    return runWithRetries(SafeEncoder.encode(key), this.redirections, false, false);\n  }\n\n  public T run(int keyCount, String... keys) {\n    if (keys == null || keys.length == 0) {\n      throw new JedisClusterException(\"No way to dispatch this command to Redis Cluster.\");\n    }\n\n    // For multiple keys, only execute if they all share the\n    // same connection slot.\n    if (keys.length > 1) {\n      int slot = JedisClusterCRC16.getSlot(keys[0]);\n      for (int i = 1; i < keyCount; i++) {\n        int nextSlot = JedisClusterCRC16.getSlot(keys[i]);\n        if (slot != nextSlot) {\n          throw new JedisClusterException(\"No way to dispatch this command to Redis Cluster \"\n              + \"because keys have different slots.\");\n        }\n      }\n    }\n\n    return runWithRetries(SafeEncoder.encode(keys[0]), this.redirections, false, false);\n  }\n\n  public T runBinary(byte[] key) {\n    if (key == null) {\n      throw new JedisClusterException(\"No way to dispatch this command to Redis Cluster.\");\n    }\n\n    return runWithRetries(key, this.redirections, false, false);\n  }\n\n  public T runBinary(int keyCount, byte[]... keys) {\n    if (keys == null || keys.length == 0) {\n      throw new JedisClusterException(\"No way to dispatch this command to Redis Cluster.\");\n    }\n\n    // For multiple keys, only execute if they all share the\n    // same connection slot.\n    if (keys.length > 1) {\n      int slot = JedisClusterCRC16.getSlot(keys[0]);\n      for (int i = 1; i < keyCount; i++) {\n        int nextSlot = JedisClusterCRC16.getSlot(keys[i]);\n        if (slot != nextSlot) {\n          throw new JedisClusterException(\"No way to dispatch this command to Redis Cluster \"\n              + \"because keys have different slots.\");\n        }\n      }\n    }\n\n    return runWithRetries(keys[0], this.redirections, false, false);\n  }\n\n  public T runWithAnyNode() {\n    Jedis connection = null;\n    try {\n      connection = connectionHandler.getConnection();\n      return execute(connection);\n    } catch (JedisConnectionException e) {\n      throw e;\n    } finally {\n      releaseConnection(connection);\n    }\n  }\n\n  private T runWithRetries(byte[] key, int redirections, boolean tryRandomNode, boolean asking) {\n    if (redirections <= 0) {\n        JedisClusterMaxRedirectionsException exception = new JedisClusterMaxRedirectionsException(\"Too many Cluster redirections? key=\" + SafeEncoder.encode(key));\n        //收集\n        UsefulDataCollector.collectException(exception, \"\", System.currentTimeMillis(), ClientExceptionType.REDIS_CLUSTER);\n        throw exception;\n    }\n\n    Jedis connection = null;\n    try {\n\n      if (asking) {\n        // TODO: Pipeline asking with the original command to make it\n        // faster....\n        connection = askConnection.get();\n        connection.asking();\n\n        // if asking success, reset asking flag\n        asking = false;\n      } else {\n        if (tryRandomNode) {\n          connection = connectionHandler.getConnection();\n        } else {\n          connection = connectionHandler.getConnectionFromSlot(JedisClusterCRC16.getSlot(key));\n        }\n      }\n\n      return execute(connection);\n    } catch (JedisConnectionException jce) {\n      if (tryRandomNode) {\n        // maybe all connection is down\n        throw jce;\n      }\n\n      // release current connection before recursion\n      releaseConnection(connection);\n      connection = null;\n\n      // retry with random connection\n      return runWithRetries(key, redirections - 1, true, asking);\n    } catch (JedisRedirectionException jre) {\n      // if MOVED redirection occurred,\n      if (jre instanceof JedisMovedDataException) {\n        // it rebuilds cluster's slot cache\n        // recommended by Redis cluster specification\n        this.connectionHandler.renewSlotCache(connection);\n      }\n\n      // release current connection before recursion or renewing\n      releaseConnection(connection);\n      connection = null;\n\n      if (jre instanceof JedisAskDataException) {\n        asking = true;\n        askConnection.set(this.connectionHandler.getConnectionFromNode(jre.getTargetNode()));\n      } else if (jre instanceof JedisMovedDataException) {\n      } else {\n        throw new JedisClusterException(jre);\n      }\n\n      return runWithRetries(key, redirections - 1, false, asking);\n    } finally {\n      releaseConnection(connection);\n    }\n  }\n\n  private void releaseConnection(Jedis connection) {\n    if (connection != null) {\n      connection.close();\n    }\n  }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/JedisClusterConnectionHandler.java",
    "content": "package redis.clients.jedis;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\nimport org.apache.commons.pool2.impl.GenericObjectPoolConfig;\n\nimport redis.clients.jedis.exceptions.JedisConnectionException;\n\npublic abstract class JedisClusterConnectionHandler {\n  protected final JedisClusterInfoCache cache;\n\n  abstract Jedis getConnection();\n\n  abstract Jedis getConnectionFromSlot(int slot);\n\n  public Jedis getConnectionFromNode(HostAndPort node) {\n    cache.setNodeIfNotExist(node);\n    return cache.getNode(JedisClusterInfoCache.getNodeKey(node)).getResource();\n  }\n\n  public JedisClusterConnectionHandler(Set<HostAndPort> nodes,\n      final GenericObjectPoolConfig poolConfig, int connectionTimeout, int soTimeout) {\n    this.cache = new JedisClusterInfoCache(poolConfig, connectionTimeout, soTimeout);\n    initializeSlotsCache(nodes, poolConfig);\n  }\n\n  public Map<String, JedisPool> getNodes() {\n    return cache.getNodes();\n  }\n\n  private void initializeSlotsCache(Set<HostAndPort> startNodes, GenericObjectPoolConfig poolConfig) {\n    for (HostAndPort hostAndPort : startNodes) {\n      Jedis jedis = new Jedis(hostAndPort.getHost(), hostAndPort.getPort());\n      try {\n        cache.discoverClusterNodesAndSlots(jedis);\n        break;\n      } catch (JedisConnectionException e) {\n        // try next nodes\n      } finally {\n        if (jedis != null) {\n          jedis.close();\n        }\n      }\n    }\n\n    for (HostAndPort node : startNodes) {\n      cache.setNodeIfNotExist(node);\n    }\n  }\n\n  public void renewSlotCache() {\n    for (JedisPool jp : getShuffledNodesPool()) {\n      Jedis jedis = null;\n      try {\n        jedis = jp.getResource();\n        cache.discoverClusterSlots(jedis);\n        break;\n      } catch (JedisConnectionException e) {\n        // try next nodes\n      } finally {\n        if (jedis != null) {\n          jedis.close();\n        }\n      }\n    }\n  }\n\n  public void renewSlotCache(Jedis jedis) {\n    try {\n      cache.discoverClusterSlots(jedis);\n    } catch (JedisConnectionException e) {\n      renewSlotCache();\n    }\n  }\n\n  protected List<JedisPool> getShuffledNodesPool() {\n    List<JedisPool> pools = new ArrayList<JedisPool>();\n    pools.addAll(cache.getNodes().values());\n    Collections.shuffle(pools);\n    return pools;\n  }\n    public JedisPool getJedisPoolFromSlot(int slot){\n        return cache.getSlotPool(slot);\n    }\n\n    private Jedis getRunningJedis(){\n        Jedis jedis = null;\n        for (JedisPool jp : cache.getNodes().values()) {\n            try {\n                jedis = jp.getResource();\n                if (jedis.ping().equalsIgnoreCase(\"PONG\")) {\n                    return jedis;\n                }\n            } catch (Exception e) {\n                //ignore\n            }\n        }\n        return jedis;\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/JedisClusterInfoCache.java",
    "content": "package redis.clients.jedis;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.locks.Lock;\nimport java.util.concurrent.locks.ReentrantReadWriteLock;\n\nimport org.apache.commons.pool2.impl.GenericObjectPoolConfig;\n\nimport redis.clients.util.ClusterNodeInformation;\nimport redis.clients.util.ClusterNodeInformationParser;\nimport redis.clients.util.SafeEncoder;\n\npublic class JedisClusterInfoCache {\n  public static final ClusterNodeInformationParser nodeInfoParser = new ClusterNodeInformationParser();\n\n  private Map<String, JedisPool> nodes = new HashMap<String, JedisPool>();\n  private Map<Integer, JedisPool> slots = new HashMap<Integer, JedisPool>();\n\n  private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();\n  private final Lock r = rwl.readLock();\n  private final Lock w = rwl.writeLock();\n  private final GenericObjectPoolConfig poolConfig;\n\n  private int connectionTimeout;\n  private int soTimeout;\n\n  public JedisClusterInfoCache(final GenericObjectPoolConfig poolConfig, int timeout) {\n    this(poolConfig, timeout, timeout);\n  }\n\n  public JedisClusterInfoCache(final GenericObjectPoolConfig poolConfig,\n      final int connectionTimeout, final int soTimeout) {\n    this.poolConfig = poolConfig;\n    this.connectionTimeout = connectionTimeout;\n    this.soTimeout = soTimeout;\n  }\n\n  public void discoverClusterNodesAndSlots(Jedis jedis) {\n    w.lock();\n\n    try {\n      this.nodes.clear();\n      this.slots.clear();\n\n      String localNodes = jedis.clusterNodes();\n      for (String nodeInfo : localNodes.split(\"\\n\")) {\n        ClusterNodeInformation clusterNodeInfo = nodeInfoParser.parse(nodeInfo, new HostAndPort(\n            jedis.getClient().getHost(), jedis.getClient().getPort()));\n\n        HostAndPort targetNode = clusterNodeInfo.getNode();\n        setNodeIfNotExist(targetNode);\n        assignSlotsToNode(clusterNodeInfo.getAvailableSlots(), targetNode);\n      }\n    } finally {\n      w.unlock();\n    }\n  }\n\n  public void discoverClusterSlots(Jedis jedis) {\n    w.lock();\n\n    try {\n      this.slots.clear();\n\n      List<Object> slots = jedis.clusterSlots();\n\n      for (Object slotInfoObj : slots) {\n        List<Object> slotInfo = (List<Object>) slotInfoObj;\n\n        if (slotInfo.size() <= 2) {\n          continue;\n        }\n\n        List<Integer> slotNums = getAssignedSlotArray(slotInfo);\n\n        // hostInfos\n        List<Object> hostInfos = (List<Object>) slotInfo.get(2);\n        if (hostInfos.size() <= 0) {\n          continue;\n        }\n\n        // at this time, we just use master, discard slave information\n        HostAndPort targetNode = generateHostAndPort(hostInfos);\n\n        setNodeIfNotExist(targetNode);\n        assignSlotsToNode(slotNums, targetNode);\n      }\n    } finally {\n      w.unlock();\n    }\n  }\n\n  private HostAndPort generateHostAndPort(List<Object> hostInfos) {\n    return new HostAndPort(SafeEncoder.encode((byte[]) hostInfos.get(0)),\n        ((Long) hostInfos.get(1)).intValue());\n  }\n\n  public void setNodeIfNotExist(HostAndPort node) {\n    w.lock();\n    try {\n      String nodeKey = getNodeKey(node);\n      if (nodes.containsKey(nodeKey)) return;\n\n      JedisPool nodePool = new JedisPool(poolConfig, node.getHost(), node.getPort(),\n          connectionTimeout, soTimeout, null, 0, null);\n      nodes.put(nodeKey, nodePool);\n    } finally {\n      w.unlock();\n    }\n  }\n\n  public void assignSlotToNode(int slot, HostAndPort targetNode) {\n    w.lock();\n    try {\n      JedisPool targetPool = nodes.get(getNodeKey(targetNode));\n\n      if (targetPool == null) {\n        setNodeIfNotExist(targetNode);\n        targetPool = nodes.get(getNodeKey(targetNode));\n      }\n      slots.put(slot, targetPool);\n    } finally {\n      w.unlock();\n    }\n  }\n\n  public void assignSlotsToNode(List<Integer> targetSlots, HostAndPort targetNode) {\n    w.lock();\n    try {\n      JedisPool targetPool = nodes.get(getNodeKey(targetNode));\n\n      if (targetPool == null) {\n        setNodeIfNotExist(targetNode);\n        targetPool = nodes.get(getNodeKey(targetNode));\n      }\n\n      for (Integer slot : targetSlots) {\n        slots.put(slot, targetPool);\n      }\n    } finally {\n      w.unlock();\n    }\n  }\n\n  public JedisPool getNode(String nodeKey) {\n    r.lock();\n    try {\n      return nodes.get(nodeKey);\n    } finally {\n      r.unlock();\n    }\n  }\n\n  public JedisPool getSlotPool(int slot) {\n    r.lock();\n    try {\n      return slots.get(slot);\n    } finally {\n      r.unlock();\n    }\n  }\n\n  public Map<String, JedisPool> getNodes() {\n    r.lock();\n    try {\n      return new HashMap<String, JedisPool>(nodes);\n    } finally {\n      r.unlock();\n    }\n  }\n\n  public static String getNodeKey(HostAndPort hnp) {\n    return hnp.getHost() + \":\" + hnp.getPort();\n  }\n\n  public static String getNodeKey(Client client) {\n    return client.getHost() + \":\" + client.getPort();\n  }\n\n  public static String getNodeKey(Jedis jedis) {\n    return getNodeKey(jedis.getClient());\n  }\n\n  private List<Integer> getAssignedSlotArray(List<Object> slotInfo) {\n    List<Integer> slotNums = new ArrayList<Integer>();\n    for (int slot = ((Long) slotInfo.get(0)).intValue(); slot <= ((Long) slotInfo.get(1))\n        .intValue(); slot++) {\n      slotNums.add(slot);\n    }\n    return slotNums;\n  }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/JedisFactory.java",
    "content": "package redis.clients.jedis;\n\nimport java.net.URI;\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport org.apache.commons.pool2.PooledObject;\nimport org.apache.commons.pool2.PooledObjectFactory;\nimport org.apache.commons.pool2.impl.DefaultPooledObject;\n\nimport redis.clients.jedis.exceptions.InvalidURIException;\nimport redis.clients.jedis.exceptions.JedisException;\nimport redis.clients.util.JedisURIHelper;\n\n/**\n * PoolableObjectFactory custom impl.\n */\nclass JedisFactory implements PooledObjectFactory<Jedis> {\n  private final AtomicReference<HostAndPort> hostAndPort = new AtomicReference<HostAndPort>();\n  private final int connectionTimeout;\n  private final int soTimeout;\n  private final String password;\n  private final int database;\n  private final String clientName;\n\n  public JedisFactory(final String host, final int port, final int connectionTimeout,\n      final int soTimeout, final String password, final int database, final String clientName) {\n    this.hostAndPort.set(new HostAndPort(host, port));\n    this.connectionTimeout = connectionTimeout;\n    this.soTimeout = soTimeout;\n    this.password = password;\n    this.database = database;\n    this.clientName = clientName;\n  }\n\n  public JedisFactory(final URI uri, final int connectionTimeout, final int soTimeout,\n      final String clientName) {\n    if (!JedisURIHelper.isValid(uri)) {\n      throw new InvalidURIException(String.format(\n        \"Cannot open Redis connection due invalid URI. %s\", uri.toString()));\n    }\n\n    this.hostAndPort.set(new HostAndPort(uri.getHost(), uri.getPort()));\n    this.connectionTimeout = connectionTimeout;\n    this.soTimeout = soTimeout;\n    this.password = JedisURIHelper.getPassword(uri);\n    this.database = JedisURIHelper.getDBIndex(uri);\n    this.clientName = clientName;\n  }\n\n  public void setHostAndPort(final HostAndPort hostAndPort) {\n    this.hostAndPort.set(hostAndPort);\n  }\n\n  @Override\n  public void activateObject(PooledObject<Jedis> pooledJedis) throws Exception {\n    final BinaryJedis jedis = pooledJedis.getObject();\n    if (jedis.getDB() != database) {\n      jedis.select(database);\n    }\n\n  }\n\n  @Override\n  public void destroyObject(PooledObject<Jedis> pooledJedis) throws Exception {\n    final BinaryJedis jedis = pooledJedis.getObject();\n    if (jedis.isConnected()) {\n      try {\n        try {\n          jedis.quit();\n        } catch (Exception e) {\n        }\n        jedis.disconnect();\n      } catch (Exception e) {\n\n      }\n    }\n\n  }\n\n  @Override\n  public PooledObject<Jedis> makeObject() throws Exception {\n    final HostAndPort hostAndPort = this.hostAndPort.get();\n    final Jedis jedis = new Jedis(hostAndPort.getHost(), hostAndPort.getPort(), connectionTimeout,\n        soTimeout);\n\n    try {\n      jedis.connect();\n      if (null != this.password) {\n        jedis.auth(this.password);\n      }\n      if (database != 0) {\n        jedis.select(database);\n      }\n      if (clientName != null) {\n        jedis.clientSetname(clientName);\n      }\n    } catch (JedisException je) {\n      jedis.close();\n      throw je;\n    }\n\n    return new DefaultPooledObject<Jedis>(jedis);\n\n  }\n\n  @Override\n  public void passivateObject(PooledObject<Jedis> pooledJedis) throws Exception {\n    // TODO maybe should select db 0? Not sure right now.\n  }\n\n  @Override\n  public boolean validateObject(PooledObject<Jedis> pooledJedis) {\n    final BinaryJedis jedis = pooledJedis.getObject();\n    try {\n      HostAndPort hostAndPort = this.hostAndPort.get();\n\n      String connectionHost = jedis.getClient().getHost();\n      int connectionPort = jedis.getClient().getPort();\n\n      return hostAndPort.getHost().equals(connectionHost)\n          && hostAndPort.getPort() == connectionPort && jedis.isConnected()\n          && jedis.ping().equals(\"PONG\");\n    } catch (final Exception e) {\n      return false;\n    }\n  }\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/JedisMonitor.java",
    "content": "package redis.clients.jedis;\n\npublic abstract class JedisMonitor {\n  protected Client client;\n\n  public void proceed(Client client) {\n    this.client = client;\n    this.client.setTimeoutInfinite();\n    do {\n      String command = client.getBulkReply();\n      onCommand(command);\n    } while (client.isConnected());\n  }\n\n  public abstract void onCommand(String command);\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/JedisPool.java",
    "content": "package redis.clients.jedis;\n\nimport java.net.URI;\n\nimport org.apache.commons.pool2.impl.GenericObjectPool;\nimport org.apache.commons.pool2.impl.GenericObjectPoolConfig;\n\nimport redis.clients.jedis.exceptions.JedisException;\nimport redis.clients.util.JedisURIHelper;\n\npublic class JedisPool extends JedisPoolAbstract {\n\n  public JedisPool() {\n    this(Protocol.DEFAULT_HOST, Protocol.DEFAULT_PORT);\n  }\n\n  public JedisPool(final GenericObjectPoolConfig poolConfig, final String host) {\n    this(poolConfig, host, Protocol.DEFAULT_PORT, Protocol.DEFAULT_TIMEOUT, null,\n        Protocol.DEFAULT_DATABASE, null);\n  }\n\n  public JedisPool(String host, int port) {\n    this(new GenericObjectPoolConfig(), host, port, Protocol.DEFAULT_TIMEOUT, null,\n        Protocol.DEFAULT_DATABASE, null);\n  }\n\n  public JedisPool(final String host) {\n    URI uri = URI.create(host);\n    if (JedisURIHelper.isValid(uri)) {\n      String h = uri.getHost();\n      int port = uri.getPort();\n      String password = JedisURIHelper.getPassword(uri);\n      int database = JedisURIHelper.getDBIndex(uri);\n      this.internalPool = new GenericObjectPool<Jedis>(new JedisFactory(h, port,\n          Protocol.DEFAULT_TIMEOUT, Protocol.DEFAULT_TIMEOUT, password, database, null),\n          new GenericObjectPoolConfig());\n      this.host = h;\n      this.port = port;\n    } else {\n      this.internalPool = new GenericObjectPool<Jedis>(new JedisFactory(host,\n          Protocol.DEFAULT_PORT, Protocol.DEFAULT_TIMEOUT, Protocol.DEFAULT_TIMEOUT, null,\n          Protocol.DEFAULT_DATABASE, null), new GenericObjectPoolConfig());\n        this.host = host;\n        this.port = Protocol.DEFAULT_PORT;\n    }\n  }\n\n  public JedisPool(final URI uri) {\n    this(new GenericObjectPoolConfig(), uri, Protocol.DEFAULT_TIMEOUT);\n  }\n\n  public JedisPool(final URI uri, final int timeout) {\n    this(new GenericObjectPoolConfig(), uri, timeout);\n  }\n\n  public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port,\n      int timeout, final String password) {\n    this(poolConfig, host, port, timeout, password, Protocol.DEFAULT_DATABASE, null);\n  }\n\n  public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, final int port) {\n    this(poolConfig, host, port, Protocol.DEFAULT_TIMEOUT, null, Protocol.DEFAULT_DATABASE, null);\n  }\n\n  public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, final int port,\n      final int timeout) {\n    this(poolConfig, host, port, timeout, null, Protocol.DEFAULT_DATABASE, null);\n  }\n\n  public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port,\n      int timeout, final String password, final int database) {\n    this(poolConfig, host, port, timeout, password, database, null);\n  }\n\n  public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port,\n      int timeout, final String password, final int database, final String clientName) {\n    this(poolConfig, host, port, timeout, timeout, password, database, clientName);\n  }\n\n  public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port,\n      final int connectionTimeout, final int soTimeout, final String password, final int database,\n      final String clientName) {\n    super(poolConfig, new JedisFactory(host, port, connectionTimeout, soTimeout, password,\n        database, clientName));\n    this.host = host;\n    this.port = port;\n  }\n\n  public JedisPool(final GenericObjectPoolConfig poolConfig, final URI uri) {\n    this(poolConfig, uri, Protocol.DEFAULT_TIMEOUT);\n  }\n\n  public JedisPool(final GenericObjectPoolConfig poolConfig, final URI uri, final int timeout) {\n    this(poolConfig, uri, timeout, timeout);\n  }\n\n  public JedisPool(final GenericObjectPoolConfig poolConfig, final URI uri,\n      final int connectionTimeout, final int soTimeout) {\n    super(poolConfig, new JedisFactory(uri, connectionTimeout, soTimeout, null));\n    this.host = uri.getHost();\n    this.port = uri.getPort();\n  }\n\n  @Override\n  public Jedis getResource() {\n    Jedis jedis = super.getResource();\n    jedis.setDataSource(this);\n    return jedis;\n  }\n\n  @Override\n  protected void returnBrokenResource(final Jedis resource) {\n    if (resource != null) {\n      returnBrokenResourceObject(resource);\n    }\n  }\n\n  @Override\n  protected void returnResource(final Jedis resource) {\n    if (resource != null) {\n      try {\n        resource.resetState();\n        returnResourceObject(resource);\n      } catch (Exception e) {\n        returnBrokenResource(resource);\n        throw new JedisException(\"Could not return the resource to the pool\", e);\n      }\n    }\n  }\n    private final String host;\n    private final int port;\n\n    public String getHost() {\n        return host;\n    }\n\n    public int getPort() {\n        return port;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) return true;\n        if (!(o instanceof JedisPool)) return false;\n\n        JedisPool jedisPool = (JedisPool) o;\n\n        if (port != jedisPool.port) return false;\n        if (!host.equals(jedisPool.host)) return false;\n\n        return true;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = host.hashCode();\n        result = 31 * result + port;\n        return result;\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/JedisPoolAbstract.java",
    "content": "package redis.clients.jedis;\n\nimport org.apache.commons.pool2.PooledObjectFactory;\nimport org.apache.commons.pool2.impl.GenericObjectPoolConfig;\n\nimport redis.clients.util.Pool;\n\npublic class JedisPoolAbstract extends Pool<Jedis> {\n\n  public JedisPoolAbstract() {\n    super();\n  }\n\n  public JedisPoolAbstract(GenericObjectPoolConfig poolConfig, PooledObjectFactory<Jedis> factory) {\n    super(poolConfig, factory);\n  }\n\n  @Override\n  protected void returnBrokenResource(Jedis resource) {\n    super.returnBrokenResource(resource);\n  }\n\n  @Override\n  protected void returnResource(Jedis resource) {\n    super.returnResource(resource);\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/JedisPoolConfig.java",
    "content": "package redis.clients.jedis;\n\nimport org.apache.commons.pool2.impl.GenericObjectPoolConfig;\n\npublic class JedisPoolConfig extends GenericObjectPoolConfig {\n  public JedisPoolConfig() {\n    // defaults to make your life with connection pool easier :)\n    setTestWhileIdle(true);\n    setMinEvictableIdleTimeMillis(60000);\n    setTimeBetweenEvictionRunsMillis(30000);\n    setNumTestsPerEvictionRun(-1);\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/JedisPubSub.java",
    "content": "package redis.clients.jedis;\n\nimport static redis.clients.jedis.Protocol.Keyword.MESSAGE;\nimport static redis.clients.jedis.Protocol.Keyword.PMESSAGE;\nimport static redis.clients.jedis.Protocol.Keyword.PSUBSCRIBE;\nimport static redis.clients.jedis.Protocol.Keyword.PUNSUBSCRIBE;\nimport static redis.clients.jedis.Protocol.Keyword.SUBSCRIBE;\nimport static redis.clients.jedis.Protocol.Keyword.UNSUBSCRIBE;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport redis.clients.jedis.exceptions.JedisConnectionException;\nimport redis.clients.jedis.exceptions.JedisException;\nimport redis.clients.util.SafeEncoder;\n\npublic abstract class JedisPubSub {\n  private int subscribedChannels = 0;\n  private volatile Client client;\n\n  public void onMessage(String channel, String message) {\n  }\n\n  public void onPMessage(String pattern, String channel, String message) {\n  }\n\n  public void onSubscribe(String channel, int subscribedChannels) {\n  }\n\n  public void onUnsubscribe(String channel, int subscribedChannels) {\n  }\n\n  public void onPUnsubscribe(String pattern, int subscribedChannels) {\n  }\n\n  public void onPSubscribe(String pattern, int subscribedChannels) {\n  }\n\n  public void unsubscribe() {\n    if (client == null) {\n      throw new JedisConnectionException(\"JedisPubSub was not subscribed to a Jedis instance.\");\n    }\n    client.unsubscribe();\n    client.flush();\n  }\n\n  public void unsubscribe(String... channels) {\n    if (client == null) {\n      throw new JedisConnectionException(\"JedisPubSub is not subscribed to a Jedis instance.\");\n    }\n    client.unsubscribe(channels);\n    client.flush();\n  }\n\n  public void subscribe(String... channels) {\n    if (client == null) {\n      throw new JedisConnectionException(\"JedisPubSub is not subscribed to a Jedis instance.\");\n    }\n    client.subscribe(channels);\n    client.flush();\n  }\n\n  public void psubscribe(String... patterns) {\n    if (client == null) {\n      throw new JedisConnectionException(\"JedisPubSub is not subscribed to a Jedis instance.\");\n    }\n    client.psubscribe(patterns);\n    client.flush();\n  }\n\n  public void punsubscribe() {\n    if (client == null) {\n      throw new JedisConnectionException(\"JedisPubSub is not subscribed to a Jedis instance.\");\n    }\n    client.punsubscribe();\n    client.flush();\n  }\n\n  public void punsubscribe(String... patterns) {\n    if (client == null) {\n      throw new JedisConnectionException(\"JedisPubSub is not subscribed to a Jedis instance.\");\n    }\n    client.punsubscribe(patterns);\n    client.flush();\n  }\n\n  public boolean isSubscribed() {\n    return subscribedChannels > 0;\n  }\n\n  public void proceedWithPatterns(Client client, String... patterns) {\n    this.client = client;\n    client.psubscribe(patterns);\n    client.flush();\n    process(client);\n  }\n\n  public void proceed(Client client, String... channels) {\n    this.client = client;\n    client.subscribe(channels);\n    client.flush();\n    process(client);\n  }\n\n  private void process(Client client) {\n\n    do {\n      List<Object> reply = client.getRawObjectMultiBulkReply();\n      final Object firstObj = reply.get(0);\n      if (!(firstObj instanceof byte[])) {\n        throw new JedisException(\"Unknown message type: \" + firstObj);\n      }\n      final byte[] resp = (byte[]) firstObj;\n      if (Arrays.equals(SUBSCRIBE.raw, resp)) {\n        subscribedChannels = ((Long) reply.get(2)).intValue();\n        final byte[] bchannel = (byte[]) reply.get(1);\n        final String strchannel = (bchannel == null) ? null : SafeEncoder.encode(bchannel);\n        onSubscribe(strchannel, subscribedChannels);\n      } else if (Arrays.equals(UNSUBSCRIBE.raw, resp)) {\n        subscribedChannels = ((Long) reply.get(2)).intValue();\n        final byte[] bchannel = (byte[]) reply.get(1);\n        final String strchannel = (bchannel == null) ? null : SafeEncoder.encode(bchannel);\n        onUnsubscribe(strchannel, subscribedChannels);\n      } else if (Arrays.equals(MESSAGE.raw, resp)) {\n        final byte[] bchannel = (byte[]) reply.get(1);\n        final byte[] bmesg = (byte[]) reply.get(2);\n        final String strchannel = (bchannel == null) ? null : SafeEncoder.encode(bchannel);\n        final String strmesg = (bmesg == null) ? null : SafeEncoder.encode(bmesg);\n        onMessage(strchannel, strmesg);\n      } else if (Arrays.equals(PMESSAGE.raw, resp)) {\n        final byte[] bpattern = (byte[]) reply.get(1);\n        final byte[] bchannel = (byte[]) reply.get(2);\n        final byte[] bmesg = (byte[]) reply.get(3);\n        final String strpattern = (bpattern == null) ? null : SafeEncoder.encode(bpattern);\n        final String strchannel = (bchannel == null) ? null : SafeEncoder.encode(bchannel);\n        final String strmesg = (bmesg == null) ? null : SafeEncoder.encode(bmesg);\n        onPMessage(strpattern, strchannel, strmesg);\n      } else if (Arrays.equals(PSUBSCRIBE.raw, resp)) {\n        subscribedChannels = ((Long) reply.get(2)).intValue();\n        final byte[] bpattern = (byte[]) reply.get(1);\n        final String strpattern = (bpattern == null) ? null : SafeEncoder.encode(bpattern);\n        onPSubscribe(strpattern, subscribedChannels);\n      } else if (Arrays.equals(PUNSUBSCRIBE.raw, resp)) {\n        subscribedChannels = ((Long) reply.get(2)).intValue();\n        final byte[] bpattern = (byte[]) reply.get(1);\n        final String strpattern = (bpattern == null) ? null : SafeEncoder.encode(bpattern);\n        onPUnsubscribe(strpattern, subscribedChannels);\n      } else {\n        throw new JedisException(\"Unknown message type: \" + firstObj);\n      }\n    } while (isSubscribed());\n\n    /* Invalidate instance since this thread is no longer listening */\n    this.client = null;\n  }\n\n  public int getSubscribedChannels() {\n    return subscribedChannels;\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/JedisSentinelPool.java",
    "content": "package redis.clients.jedis;\n\nimport java.util.Arrays;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Set;\nimport java.util.concurrent.atomic.AtomicBoolean;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\nimport org.apache.commons.pool2.impl.GenericObjectPoolConfig;\n\nimport redis.clients.jedis.exceptions.JedisConnectionException;\nimport redis.clients.jedis.exceptions.JedisException;\n\npublic class JedisSentinelPool extends JedisPoolAbstract {\n\n  protected GenericObjectPoolConfig poolConfig;\n\n  protected int connectionTimeout = Protocol.DEFAULT_TIMEOUT;\n  protected int soTimeout = Protocol.DEFAULT_TIMEOUT;\n\n  protected String password;\n\n  protected int database = Protocol.DEFAULT_DATABASE;\n\n  protected String clientName;\n\n  protected Set<MasterListener> masterListeners = new HashSet<MasterListener>();\n\n  protected Logger log = Logger.getLogger(getClass().getName());\n\n  private volatile JedisFactory factory;\n  private volatile HostAndPort currentHostMaster;\n\n  public JedisSentinelPool(String masterName, Set<String> sentinels,\n      final GenericObjectPoolConfig poolConfig) {\n    this(masterName, sentinels, poolConfig, Protocol.DEFAULT_TIMEOUT, null,\n        Protocol.DEFAULT_DATABASE);\n  }\n\n  public JedisSentinelPool(String masterName, Set<String> sentinels) {\n    this(masterName, sentinels, new GenericObjectPoolConfig(), Protocol.DEFAULT_TIMEOUT, null,\n        Protocol.DEFAULT_DATABASE);\n  }\n\n  public JedisSentinelPool(String masterName, Set<String> sentinels, String password) {\n    this(masterName, sentinels, new GenericObjectPoolConfig(), Protocol.DEFAULT_TIMEOUT, password);\n  }\n\n  public JedisSentinelPool(String masterName, Set<String> sentinels,\n      final GenericObjectPoolConfig poolConfig, int timeout, final String password) {\n    this(masterName, sentinels, poolConfig, timeout, password, Protocol.DEFAULT_DATABASE);\n  }\n\n  public JedisSentinelPool(String masterName, Set<String> sentinels,\n      final GenericObjectPoolConfig poolConfig, final int timeout) {\n    this(masterName, sentinels, poolConfig, timeout, null, Protocol.DEFAULT_DATABASE);\n  }\n\n  public JedisSentinelPool(String masterName, Set<String> sentinels,\n      final GenericObjectPoolConfig poolConfig, final String password) {\n    this(masterName, sentinels, poolConfig, Protocol.DEFAULT_TIMEOUT, password);\n  }\n\n  public JedisSentinelPool(String masterName, Set<String> sentinels,\n      final GenericObjectPoolConfig poolConfig, int timeout, final String password,\n      final int database) {\n    this(masterName, sentinels, poolConfig, timeout, timeout, password, database);\n  }\n\n  public JedisSentinelPool(String masterName, Set<String> sentinels,\n      final GenericObjectPoolConfig poolConfig, int timeout, final String password,\n      final int database, final String clientName) {\n    this(masterName, sentinels, poolConfig, timeout, timeout, password, database, clientName);\n  }\n\n  public JedisSentinelPool(String masterName, Set<String> sentinels,\n      final GenericObjectPoolConfig poolConfig, final int timeout, final int soTimeout,\n      final String password, final int database) {\n    this(masterName, sentinels, poolConfig, timeout, soTimeout, password, database, null);\n  }\n\n  public JedisSentinelPool(String masterName, Set<String> sentinels,\n      final GenericObjectPoolConfig poolConfig, final int connectionTimeout, final int soTimeout,\n      final String password, final int database, final String clientName) {\n    this.poolConfig = poolConfig;\n    this.connectionTimeout = connectionTimeout;\n    this.soTimeout = soTimeout;\n    this.password = password;\n    this.database = database;\n    this.clientName = clientName;\n\n    HostAndPort master = initSentinels(sentinels, masterName);\n    initPool(master);\n  }\n\n  public void destroy() {\n    for (MasterListener m : masterListeners) {\n      m.shutdown();\n    }\n\n    super.destroy();\n  }\n\n  public HostAndPort getCurrentHostMaster() {\n    return currentHostMaster;\n  }\n\n  private void initPool(HostAndPort master) {\n    if (!master.equals(currentHostMaster)) {\n      currentHostMaster = master;\n      if (factory == null) {\n        factory = new JedisFactory(master.getHost(), master.getPort(), connectionTimeout,\n            soTimeout, password, database, clientName);\n        initPool(poolConfig, factory);\n      } else {\n        factory.setHostAndPort(currentHostMaster);\n        // although we clear the pool, we still have to check the\n        // returned object\n        // in getResource, this call only clears idle instances, not\n        // borrowed instances\n        internalPool.clear();\n      }\n\n      log.info(\"Created JedisPool to master at \" + master);\n    }\n  }\n\n  private HostAndPort initSentinels(Set<String> sentinels, final String masterName) {\n\n    HostAndPort master = null;\n    boolean sentinelAvailable = false;\n\n    log.info(\"Trying to find master from available Sentinels...\");\n\n    for (String sentinel : sentinels) {\n      final HostAndPort hap = toHostAndPort(Arrays.asList(sentinel.split(\":\")));\n\n      log.fine(\"Connecting to Sentinel \" + hap);\n\n      Jedis jedis = null;\n      try {\n        jedis = new Jedis(hap.getHost(), hap.getPort());\n\n        List<String> masterAddr = jedis.sentinelGetMasterAddrByName(masterName);\n\n        // connected to sentinel...\n        sentinelAvailable = true;\n\n        if (masterAddr == null || masterAddr.size() != 2) {\n          log.warning(\"Can not get master addr, master name: \" + masterName + \". Sentinel: \" + hap\n              + \".\");\n          continue;\n        }\n\n        master = toHostAndPort(masterAddr);\n        log.fine(\"Found Redis master at \" + master);\n        break;\n      } catch (JedisException e) {\n        // resolves #1036, it should handle JedisException there's another chance\n        // of raising JedisDataException\n        log.warning(\"Cannot get master address from sentinel running @ \" + hap + \". Reason: \" + e\n            + \". Trying next one.\");\n      } finally {\n        if (jedis != null) {\n          jedis.close();\n        }\n      }\n    }\n\n    if (master == null) {\n      if (sentinelAvailable) {\n        // can connect to sentinel, but master name seems to not\n        // monitored\n        throw new JedisException(\"Can connect to sentinel, but \" + masterName\n            + \" seems to be not monitored...\");\n      } else {\n        throw new JedisConnectionException(\"All sentinels down, cannot determine where is \"\n            + masterName + \" master is running...\");\n      }\n    }\n\n    log.info(\"Redis master running at \" + master + \", starting Sentinel listeners...\");\n\n    for (String sentinel : sentinels) {\n      final HostAndPort hap = toHostAndPort(Arrays.asList(sentinel.split(\":\")));\n      MasterListener masterListener = new MasterListener(masterName, hap.getHost(), hap.getPort());\n      // whether MasterListener threads are alive or not, process can be stopped\n      masterListener.setDaemon(true);\n      masterListeners.add(masterListener);\n      masterListener.start();\n    }\n\n    return master;\n  }\n\n  private HostAndPort toHostAndPort(List<String> getMasterAddrByNameResult) {\n    String host = getMasterAddrByNameResult.get(0);\n    int port = Integer.parseInt(getMasterAddrByNameResult.get(1));\n\n    return new HostAndPort(host, port);\n  }\n\n  @Override\n  public Jedis getResource() {\n    while (true) {\n      Jedis jedis = super.getResource();\n      jedis.setDataSource(this);\n\n      // get a reference because it can change concurrently\n      final HostAndPort master = currentHostMaster;\n      final HostAndPort connection = new HostAndPort(jedis.getClient().getHost(), jedis.getClient()\n          .getPort());\n\n      if (master.equals(connection)) {\n        // connected to the correct master\n        return jedis;\n      } else {\n        returnBrokenResource(jedis);\n      }\n    }\n  }\n\n  protected void returnBrokenResource(final Jedis resource) {\n    if (resource != null) {\n      returnBrokenResourceObject(resource);\n    }\n  }\n\n  protected void returnResource(final Jedis resource) {\n    if (resource != null) {\n      resource.resetState();\n      returnResourceObject(resource);\n    }\n  }\n\n  protected class MasterListener extends Thread {\n\n    protected String masterName;\n    protected String host;\n    protected int port;\n    protected long subscribeRetryWaitTimeMillis = 5000;\n    protected volatile Jedis j;\n    protected AtomicBoolean running = new AtomicBoolean(false);\n\n    protected MasterListener() {\n    }\n\n    public MasterListener(String masterName, String host, int port) {\n      super(String.format(\"MasterListener-%s-[%s:%d]\", masterName, host, port));\n      this.masterName = masterName;\n      this.host = host;\n      this.port = port;\n    }\n\n    public MasterListener(String masterName, String host, int port,\n        long subscribeRetryWaitTimeMillis) {\n      this(masterName, host, port);\n      this.subscribeRetryWaitTimeMillis = subscribeRetryWaitTimeMillis;\n    }\n\n    public void run() {\n\n      running.set(true);\n\n      while (running.get()) {\n\n        j = new Jedis(host, port);\n\n        try {\n          // double check that it is not being shutdown\n          if (!running.get()) {\n            break;\n          }\n\n          j.subscribe(new JedisPubSub() {\n            @Override\n            public void onMessage(String channel, String message) {\n              log.fine(\"Sentinel \" + host + \":\" + port + \" published: \" + message + \".\");\n\n              String[] switchMasterMsg = message.split(\" \");\n\n              if (switchMasterMsg.length > 3) {\n\n                if (masterName.equals(switchMasterMsg[0])) {\n                  initPool(toHostAndPort(Arrays.asList(switchMasterMsg[3], switchMasterMsg[4])));\n                } else {\n                  log.fine(\"Ignoring message on +switch-master for master name \"\n                      + switchMasterMsg[0] + \", our master name is \" + masterName);\n                }\n\n              } else {\n                log.severe(\"Invalid message received on Sentinel \" + host + \":\" + port\n                    + \" on channel +switch-master: \" + message);\n              }\n            }\n          }, \"+switch-master\");\n\n        } catch (JedisConnectionException e) {\n\n          if (running.get()) {\n            log.log(Level.SEVERE, \"Lost connection to Sentinel at \" + host + \":\" + port\n                + \". Sleeping 5000ms and retrying.\", e);\n            try {\n              Thread.sleep(subscribeRetryWaitTimeMillis);\n            } catch (InterruptedException e1) {\n              log.log(Level.SEVERE, \"Sleep interrupted: \", e1);\n            }\n          } else {\n            log.fine(\"Unsubscribing from Sentinel at \" + host + \":\" + port);\n          }\n        } finally {\n          j.close();\n        }\n      }\n    }\n\n    public void shutdown() {\n      try {\n        log.fine(\"Shutting down listener on \" + host + \":\" + port);\n        running.set(false);\n        // This isn't good, the Jedis object is not thread safe\n        if (j != null) {\n          j.disconnect();\n        }\n      } catch (Exception e) {\n        log.log(Level.SEVERE, \"Caught exception while shutting down: \", e);\n      }\n    }\n  }\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/JedisShardInfo.java",
    "content": "package redis.clients.jedis;\n\nimport java.net.URI;\n\nimport redis.clients.jedis.exceptions.InvalidURIException;\nimport redis.clients.util.JedisURIHelper;\nimport redis.clients.util.ShardInfo;\nimport redis.clients.util.Sharded;\n\npublic class JedisShardInfo extends ShardInfo<Jedis> {\n\n  public String toString() {\n    return host + \":\" + port + \"*\" + getWeight();\n  }\n\n  private int connectionTimeout;\n  private int soTimeout;\n  private String host;\n  private int port;\n  private String password = null;\n  private String name = null;\n  // Default Redis DB\n  private int db = 0;\n\n  public String getHost() {\n    return host;\n  }\n\n  public int getPort() {\n    return port;\n  }\n\n  public JedisShardInfo(String host) {\n    super(Sharded.DEFAULT_WEIGHT);\n    URI uri = URI.create(host);\n    if (JedisURIHelper.isValid(uri)) {\n      this.host = uri.getHost();\n      this.port = uri.getPort();\n      this.password = JedisURIHelper.getPassword(uri);\n      this.db = JedisURIHelper.getDBIndex(uri);\n    } else {\n      this.host = host;\n      this.port = Protocol.DEFAULT_PORT;\n    }\n  }\n\n  public JedisShardInfo(String host, String name) {\n    this(host, Protocol.DEFAULT_PORT, name);\n  }\n\n  public JedisShardInfo(String host, int port) {\n    this(host, port, 2000);\n  }\n\n  public JedisShardInfo(String host, int port, String name) {\n    this(host, port, 2000, name);\n  }\n\n  public JedisShardInfo(String host, int port, int timeout) {\n    this(host, port, timeout, timeout, Sharded.DEFAULT_WEIGHT);\n  }\n\n  public JedisShardInfo(String host, int port, int timeout, String name) {\n    this(host, port, timeout, timeout, Sharded.DEFAULT_WEIGHT);\n    this.name = name;\n  }\n\n  public JedisShardInfo(String host, int port, int connectionTimeout, int soTimeout, int weight) {\n    super(weight);\n    this.host = host;\n    this.port = port;\n    this.connectionTimeout = connectionTimeout;\n    this.soTimeout = soTimeout;\n  }\n\n  public JedisShardInfo(String host, String name, int port, int timeout, int weight) {\n    super(weight);\n    this.host = host;\n    this.name = name;\n    this.port = port;\n    this.connectionTimeout = timeout;\n    this.soTimeout = timeout;\n  }\n\n  public JedisShardInfo(URI uri) {\n    super(Sharded.DEFAULT_WEIGHT);\n    if (!JedisURIHelper.isValid(uri)) {\n      throw new InvalidURIException(String.format(\n        \"Cannot open Redis connection due invalid URI. %s\", uri.toString()));\n    }\n\n    this.host = uri.getHost();\n    this.port = uri.getPort();\n    this.password = JedisURIHelper.getPassword(uri);\n    this.db = JedisURIHelper.getDBIndex(uri);\n  }\n\n  public String getPassword() {\n    return password;\n  }\n\n  public void setPassword(String auth) {\n    this.password = auth;\n  }\n\n  public int getConnectionTimeout() {\n    return connectionTimeout;\n  }\n\n  public void setConnectionTimeout(int connectionTimeout) {\n    this.connectionTimeout = connectionTimeout;\n  }\n\n  public int getSoTimeout() {\n    return soTimeout;\n  }\n\n  public void setSoTimeout(int soTimeout) {\n    this.soTimeout = soTimeout;\n  }\n\n  @Override\n  public String getName() {\n    return name;\n  }\n\n  public int getDb() {\n    return db;\n  }\n\n  @Override\n  public Jedis createResource() {\n    return new Jedis(this);\n  }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/JedisSlotBasedConnectionHandler.java",
    "content": "package redis.clients.jedis;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Set;\n\nimport org.apache.commons.pool2.impl.GenericObjectPoolConfig;\n\nimport redis.clients.jedis.exceptions.JedisConnectionException;\n\npublic class JedisSlotBasedConnectionHandler extends JedisClusterConnectionHandler {\n\n  public JedisSlotBasedConnectionHandler(Set<HostAndPort> nodes,\n      final GenericObjectPoolConfig poolConfig, int timeout) {\n    this(nodes, poolConfig, timeout, timeout);\n  }\n\n  public JedisSlotBasedConnectionHandler(Set<HostAndPort> nodes,\n      final GenericObjectPoolConfig poolConfig, int connectionTimeout, int soTimeout) {\n    super(nodes, poolConfig, connectionTimeout, soTimeout);\n  }\n\n  @Override\n  public Jedis getConnection() {\n    // In antirez's redis-rb-cluster implementation,\n    // getRandomConnection always return valid connection (able to\n    // ping-pong)\n    // or exception if all connections are invalid\n\n    List<JedisPool> pools = getShuffledNodesPool();\n\n    for (JedisPool pool : pools) {\n      Jedis jedis = null;\n      try {\n        jedis = pool.getResource();\n\n        if (jedis == null) {\n          continue;\n        }\n\n        String result = jedis.ping();\n\n        if (result.equalsIgnoreCase(\"pong\")) return jedis;\n\n        pool.returnBrokenResource(jedis);\n      } catch (JedisConnectionException ex) {\n        if (jedis != null) {\n          pool.returnBrokenResource(jedis);\n        }\n      }\n    }\n\n    throw new JedisConnectionException(\"no reachable node in cluster\");\n  }\n\n  @Override\n  public Jedis getConnectionFromSlot(int slot) {\n    JedisPool connectionPool = cache.getSlotPool(slot);\n    if (connectionPool != null) {\n      // It can't guaranteed to get valid connection because of node\n      // assignment\n      return connectionPool.getResource();\n    } else {\n      return getConnection();\n    }\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/MultiKeyPipelineBase.java",
    "content": "package redis.clients.jedis;\n\nimport redis.clients.jedis.commands.*;\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\npublic abstract class MultiKeyPipelineBase extends PipelineBase implements\n    MultiKeyBinaryRedisPipeline, MultiKeyCommandsPipeline, ClusterPipeline,\n    BinaryScriptingCommandsPipeline, ScriptingCommandsPipeline {\n\n  protected Client client = null;\n\n  public Response<List<String>> brpop(String... args) {\n    client.brpop(args);\n    return getResponse(BuilderFactory.STRING_LIST);\n  }\n\n  public Response<List<String>> brpop(int timeout, String... keys) {\n    client.brpop(timeout, keys);\n    return getResponse(BuilderFactory.STRING_LIST);\n  }\n\n  public Response<List<String>> blpop(String... args) {\n    client.blpop(args);\n    return getResponse(BuilderFactory.STRING_LIST);\n  }\n\n  public Response<List<String>> blpop(int timeout, String... keys) {\n    client.blpop(timeout, keys);\n    return getResponse(BuilderFactory.STRING_LIST);\n  }\n\n  public Response<Map<String, String>> blpopMap(int timeout, String... keys) {\n    client.blpop(timeout, keys);\n    return getResponse(BuilderFactory.STRING_MAP);\n  }\n\n  public Response<List<byte[]>> brpop(byte[]... args) {\n    client.brpop(args);\n    return getResponse(BuilderFactory.BYTE_ARRAY_LIST);\n  }\n\n  public Response<List<String>> brpop(int timeout, byte[]... keys) {\n    client.brpop(timeout, keys);\n    return getResponse(BuilderFactory.STRING_LIST);\n  }\n\n  public Response<Map<String, String>> brpopMap(int timeout, String... keys) {\n    client.blpop(timeout, keys);\n    return getResponse(BuilderFactory.STRING_MAP);\n  }\n\n  public Response<List<byte[]>> blpop(byte[]... args) {\n    client.blpop(args);\n    return getResponse(BuilderFactory.BYTE_ARRAY_LIST);\n  }\n\n  public Response<List<String>> blpop(int timeout, byte[]... keys) {\n    client.blpop(timeout, keys);\n    return getResponse(BuilderFactory.STRING_LIST);\n  }\n\n  public Response<Long> del(String... keys) {\n    client.del(keys);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<Long> del(byte[]... keys) {\n    client.del(keys);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<Long> exists(String... keys) {\n    client.exists(keys);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<Long> exists(byte[]... keys) {\n    client.exists(keys);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<Set<String>> keys(String pattern) {\n    getClient(pattern).keys(pattern);\n    return getResponse(BuilderFactory.STRING_SET);\n  }\n\n  public Response<Set<byte[]>> keys(byte[] pattern) {\n    getClient(pattern).keys(pattern);\n    return getResponse(BuilderFactory.BYTE_ARRAY_ZSET);\n  }\n\n  public Response<List<String>> mget(String... keys) {\n    client.mget(keys);\n    return getResponse(BuilderFactory.STRING_LIST);\n  }\n\n  public Response<List<byte[]>> mget(byte[]... keys) {\n    client.mget(keys);\n    return getResponse(BuilderFactory.BYTE_ARRAY_LIST);\n  }\n\n  public Response<String> mset(String... keysvalues) {\n    client.mset(keysvalues);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  public Response<String> mset(byte[]... keysvalues) {\n    client.mset(keysvalues);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  public Response<Long> msetnx(String... keysvalues) {\n    client.msetnx(keysvalues);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<Long> msetnx(byte[]... keysvalues) {\n    client.msetnx(keysvalues);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<String> rename(String oldkey, String newkey) {\n    client.rename(oldkey, newkey);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  public Response<String> rename(byte[] oldkey, byte[] newkey) {\n    client.rename(oldkey, newkey);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  public Response<Long> renamenx(String oldkey, String newkey) {\n    client.renamenx(oldkey, newkey);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<Long> renamenx(byte[] oldkey, byte[] newkey) {\n    client.renamenx(oldkey, newkey);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<String> rpoplpush(String srckey, String dstkey) {\n    client.rpoplpush(srckey, dstkey);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  public Response<byte[]> rpoplpush(byte[] srckey, byte[] dstkey) {\n    client.rpoplpush(srckey, dstkey);\n    return getResponse(BuilderFactory.BYTE_ARRAY);\n  }\n\n  public Response<Set<String>> sdiff(String... keys) {\n    client.sdiff(keys);\n    return getResponse(BuilderFactory.STRING_SET);\n  }\n\n  public Response<Set<byte[]>> sdiff(byte[]... keys) {\n    client.sdiff(keys);\n    return getResponse(BuilderFactory.BYTE_ARRAY_ZSET);\n  }\n\n  public Response<Long> sdiffstore(String dstkey, String... keys) {\n    client.sdiffstore(dstkey, keys);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<Long> sdiffstore(byte[] dstkey, byte[]... keys) {\n    client.sdiffstore(dstkey, keys);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<Set<String>> sinter(String... keys) {\n    client.sinter(keys);\n    return getResponse(BuilderFactory.STRING_SET);\n  }\n\n  public Response<Set<byte[]>> sinter(byte[]... keys) {\n    client.sinter(keys);\n    return getResponse(BuilderFactory.BYTE_ARRAY_ZSET);\n  }\n\n  public Response<Long> sinterstore(String dstkey, String... keys) {\n    client.sinterstore(dstkey, keys);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<Long> sinterstore(byte[] dstkey, byte[]... keys) {\n    client.sinterstore(dstkey, keys);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<Long> smove(String srckey, String dstkey, String member) {\n    client.smove(srckey, dstkey, member);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<Long> smove(byte[] srckey, byte[] dstkey, byte[] member) {\n    client.smove(srckey, dstkey, member);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<Long> sort(String key, SortingParams sortingParameters, String dstkey) {\n    client.sort(key, sortingParameters, dstkey);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<Long> sort(byte[] key, SortingParams sortingParameters, byte[] dstkey) {\n    client.sort(key, sortingParameters, dstkey);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<Long> sort(String key, String dstkey) {\n    client.sort(key, dstkey);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<Long> sort(byte[] key, byte[] dstkey) {\n    client.sort(key, dstkey);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<Set<String>> sunion(String... keys) {\n    client.sunion(keys);\n    return getResponse(BuilderFactory.STRING_SET);\n  }\n\n  public Response<Set<byte[]>> sunion(byte[]... keys) {\n    client.sunion(keys);\n    return getResponse(BuilderFactory.BYTE_ARRAY_ZSET);\n  }\n\n  public Response<Long> sunionstore(String dstkey, String... keys) {\n    client.sunionstore(dstkey, keys);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<Long> sunionstore(byte[] dstkey, byte[]... keys) {\n    client.sunionstore(dstkey, keys);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<String> watch(String... keys) {\n    client.watch(keys);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  public Response<String> watch(byte[]... keys) {\n    client.watch(keys);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  public Response<Long> zinterstore(String dstkey, String... sets) {\n    client.zinterstore(dstkey, sets);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<Long> zinterstore(byte[] dstkey, byte[]... sets) {\n    client.zinterstore(dstkey, sets);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<Long> zinterstore(String dstkey, ZParams params, String... sets) {\n    client.zinterstore(dstkey, params, sets);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<Long> zinterstore(byte[] dstkey, ZParams params, byte[]... sets) {\n    client.zinterstore(dstkey, params, sets);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<Long> zunionstore(String dstkey, String... sets) {\n    client.zunionstore(dstkey, sets);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<Long> zunionstore(byte[] dstkey, byte[]... sets) {\n    client.zunionstore(dstkey, sets);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<Long> zunionstore(String dstkey, ZParams params, String... sets) {\n    client.zunionstore(dstkey, params, sets);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<Long> zunionstore(byte[] dstkey, ZParams params, byte[]... sets) {\n    client.zunionstore(dstkey, params, sets);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<String> bgrewriteaof() {\n    client.bgrewriteaof();\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  public Response<String> bgsave() {\n    client.bgsave();\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  public Response<List<String>> configGet(String pattern) {\n    client.configGet(pattern);\n    return getResponse(BuilderFactory.STRING_LIST);\n  }\n\n  public Response<String> configSet(String parameter, String value) {\n    client.configSet(parameter, value);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  public Response<String> brpoplpush(String source, String destination, int timeout) {\n    client.brpoplpush(source, destination, timeout);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  public Response<byte[]> brpoplpush(byte[] source, byte[] destination, int timeout) {\n    client.brpoplpush(source, destination, timeout);\n    return getResponse(BuilderFactory.BYTE_ARRAY);\n  }\n\n  public Response<String> configResetStat() {\n    client.configResetStat();\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  public Response<String> save() {\n    client.save();\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  public Response<Long> lastsave() {\n    client.lastsave();\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<Long> publish(String channel, String message) {\n    client.publish(channel, message);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<Long> publish(byte[] channel, byte[] message) {\n    client.publish(channel, message);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<String> randomKey() {\n    client.randomKey();\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  public Response<byte[]> randomKeyBinary() {\n    client.randomKey();\n    return getResponse(BuilderFactory.BYTE_ARRAY);\n  }\n\n  public Response<String> flushDB() {\n    client.flushDB();\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  public Response<String> flushAll() {\n    client.flushAll();\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  public Response<String> info() {\n    client.info();\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  public Response<String> info(final String section) {\n    client.info(section);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  public Response<Long> dbSize() {\n    client.dbSize();\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<String> shutdown() {\n    client.shutdown();\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  public Response<String> ping() {\n    client.ping();\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  public Response<String> select(int index) {\n    client.select(index);\n    Response<String> response = getResponse(BuilderFactory.STRING);\n    client.setDb(index);\n\n    return response;\n  }\n\n  public Response<Long> bitop(BitOP op, byte[] destKey, byte[]... srcKeys) {\n    client.bitop(op, destKey, srcKeys);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<Long> bitop(BitOP op, String destKey, String... srcKeys) {\n    client.bitop(op, destKey, srcKeys);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<String> clusterNodes() {\n    client.clusterNodes();\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  public Response<String> clusterMeet(final String ip, final int port) {\n    client.clusterMeet(ip, port);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  public Response<String> clusterAddSlots(final int... slots) {\n    client.clusterAddSlots(slots);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  public Response<String> clusterDelSlots(final int... slots) {\n    client.clusterDelSlots(slots);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  public Response<String> clusterInfo() {\n    client.clusterInfo();\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  public Response<List<String>> clusterGetKeysInSlot(final int slot, final int count) {\n    client.clusterGetKeysInSlot(slot, count);\n    return getResponse(BuilderFactory.STRING_LIST);\n  }\n\n  public Response<String> clusterSetSlotNode(final int slot, final String nodeId) {\n    client.clusterSetSlotNode(slot, nodeId);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  public Response<String> clusterSetSlotMigrating(final int slot, final String nodeId) {\n    client.clusterSetSlotMigrating(slot, nodeId);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  public Response<String> clusterSetSlotImporting(final int slot, final String nodeId) {\n    client.clusterSetSlotImporting(slot, nodeId);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  public Response<Object> eval(String script) {\n    return this.eval(script, 0, new String[0]);\n  }\n\n  public Response<Object> eval(String script, List<String> keys, List<String> args) {\n    String[] argv = Jedis.getParams(keys, args);\n    return this.eval(script, keys.size(), argv);\n  }\n\n  public Response<Object> eval(String script, int keyCount, String... params) {\n    getClient(script).eval(script, keyCount, params);\n    return getResponse(BuilderFactory.EVAL_RESULT);\n  }\n\n  public Response<Object> evalsha(String script) {\n    return this.evalsha(script, 0, new String[0]);\n  }\n\n  public Response<Object> evalsha(String sha1, List<String> keys, List<String> args) {\n    String[] argv = Jedis.getParams(keys, args);\n    return this.evalsha(sha1, keys.size(), argv);\n  }\n\n  public Response<Object> evalsha(String sha1, int keyCount, String... params) {\n    getClient(sha1).evalsha(sha1, keyCount, params);\n    return getResponse(BuilderFactory.EVAL_RESULT);\n  }\n\n  public Response<Object> eval(byte[] script) {\n    return this.eval(script, 0);\n  }\n\n  public Response<Object> eval(byte[] script, byte[] keyCount, byte[]... params) {\n    getClient(script).eval(script, keyCount, params);\n    return getResponse(BuilderFactory.EVAL_BINARY_RESULT);\n  }\n\n  public Response<Object> eval(byte[] script, List<byte[]> keys, List<byte[]> args) {\n    byte[][] argv = BinaryJedis.getParamsWithBinary(keys, args);\n    return this.eval(script, keys.size(), argv);\n  }\n\n  public Response<Object> eval(byte[] script, int keyCount, byte[]... params) {\n    getClient(script).eval(script, keyCount, params);\n    return getResponse(BuilderFactory.EVAL_BINARY_RESULT);\n  }\n\n  public Response<Object> evalsha(byte[] sha1) {\n    return this.evalsha(sha1, 0);\n  }\n\n  public Response<Object> evalsha(byte[] sha1, List<byte[]> keys, List<byte[]> args) {\n    byte[][] argv = BinaryJedis.getParamsWithBinary(keys, args);\n    return this.evalsha(sha1, keys.size(), argv);\n  }\n\n  public Response<Object> evalsha(byte[] sha1, int keyCount, byte[]... params) {\n    getClient(sha1).evalsha(sha1, keyCount, params);\n    return getResponse(BuilderFactory.EVAL_BINARY_RESULT);\n  }\n\n  @Override\n  public Response<Long> pfcount(String... keys) {\n    client.pfcount(keys);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> pfcount(final byte[]... keys) {\n    client.pfcount(keys);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<String> pfmerge(byte[] destkey, byte[]... sourcekeys) {\n    client.pfmerge(destkey, sourcekeys);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  @Override\n  public Response<String> pfmerge(String destkey, String... sourcekeys) {\n    client.pfmerge(destkey, sourcekeys);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/Pipeline.java",
    "content": "package redis.clients.jedis;\n\nimport java.io.Closeable;\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport redis.clients.jedis.exceptions.JedisDataException;\n\npublic class Pipeline extends MultiKeyPipelineBase implements Closeable {\n\n  private MultiResponseBuilder currentMulti;\n\n  private class MultiResponseBuilder extends Builder<List<Object>> {\n    private List<Response<?>> responses = new ArrayList<Response<?>>();\n\n    @Override\n    public List<Object> build(Object data) {\n      @SuppressWarnings(\"unchecked\")\n      List<Object> list = (List<Object>) data;\n      List<Object> values = new ArrayList<Object>();\n\n      if (list.size() != responses.size()) {\n        throw new JedisDataException(\"Expected data size \" + responses.size() + \" but was \"\n            + list.size());\n      }\n\n      for (int i = 0; i < list.size(); i++) {\n        Response<?> response = responses.get(i);\n        response.set(list.get(i));\n        Object builtResponse;\n        try {\n          builtResponse = response.get();\n        } catch (JedisDataException e) {\n          builtResponse = e;\n        }\n        values.add(builtResponse);\n      }\n      return values;\n    }\n\n    public void setResponseDependency(Response<?> dependency) {\n      for (Response<?> response : responses) {\n        response.setDependency(dependency);\n      }\n    }\n\n    public void addResponse(Response<?> response) {\n      responses.add(response);\n    }\n  }\n\n  @Override\n  protected <T> Response<T> getResponse(Builder<T> builder) {\n    if (currentMulti != null) {\n      super.getResponse(BuilderFactory.STRING); // Expected QUEUED\n\n      Response<T> lr = new Response<T>(builder);\n      currentMulti.addResponse(lr);\n      return lr;\n    } else {\n      return super.getResponse(builder);\n    }\n  }\n\n  public void setClient(Client client) {\n    this.client = client;\n  }\n\n  @Override\n  protected Client getClient(byte[] key) {\n    return client;\n  }\n\n  @Override\n  protected Client getClient(String key) {\n    return client;\n  }\n\n  public void clear() {\n    if (isInMulti()) {\n      discard();\n    }\n\n    sync();\n  }\n\n  public boolean isInMulti() {\n    return currentMulti != null;\n  }\n\n  /**\n   * Synchronize pipeline by reading all responses. This operation close the pipeline. In order to\n   * get return values from pipelined commands, capture the different Response&lt;?&gt; of the\n   * commands you execute.\n   */\n  public void sync() {\n    if (getPipelinedResponseLength() > 0) {\n      List<Object> unformatted = client.getMany(getPipelinedResponseLength());\n      for (Object o : unformatted) {\n        generateResponse(o);\n      }\n    }\n  }\n\n  /**\n   * Synchronize pipeline by reading all responses. This operation close the pipeline. Whenever\n   * possible try to avoid using this version and use Pipeline.sync() as it won't go through all the\n   * responses and generate the right response type (usually it is a waste of time).\n   * @return A list of all the responses in the order you executed them.\n   */\n  public List<Object> syncAndReturnAll() {\n    if (getPipelinedResponseLength() > 0) {\n      List<Object> unformatted = client.getMany(getPipelinedResponseLength());\n      List<Object> formatted = new ArrayList<Object>();\n      for (Object o : unformatted) {\n        try {\n          formatted.add(generateResponse(o).get());\n        } catch (JedisDataException e) {\n          formatted.add(e);\n        }\n      }\n      return formatted;\n    } else {\n      return java.util.Collections.<Object> emptyList();\n    }\n  }\n\n  public Response<String> discard() {\n    if (currentMulti == null) throw new JedisDataException(\"DISCARD without MULTI\");\n    client.discard();\n    currentMulti = null;\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  public Response<List<Object>> exec() {\n    if (currentMulti == null) throw new JedisDataException(\"EXEC without MULTI\");\n\n    client.exec();\n    Response<List<Object>> response = super.getResponse(currentMulti);\n    currentMulti.setResponseDependency(response);\n    currentMulti = null;\n    return response;\n  }\n\n  public Response<String> multi() {\n    if (currentMulti != null) throw new JedisDataException(\"MULTI calls can not be nested\");\n\n    client.multi();\n    Response<String> response = getResponse(BuilderFactory.STRING); // Expecting\n    // OK\n    currentMulti = new MultiResponseBuilder();\n    return response;\n  }\n\n  @Override\n  public void close() {\n    clear();\n  }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/PipelineBase.java",
    "content": "package redis.clients.jedis;\n\nimport static redis.clients.jedis.Protocol.toByteArray;\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\nimport redis.clients.jedis.BinaryClient.LIST_POSITION;\nimport redis.clients.jedis.commands.BinaryRedisPipeline;\nimport redis.clients.jedis.commands.RedisPipeline;\nimport redis.clients.jedis.params.geo.GeoRadiusParam;\nimport redis.clients.jedis.params.set.SetParams;\nimport redis.clients.jedis.params.sortedset.ZAddParams;\nimport redis.clients.jedis.params.sortedset.ZIncrByParams;\n\npublic abstract class PipelineBase extends Queable implements BinaryRedisPipeline, RedisPipeline {\n\n  protected abstract Client getClient(String key);\n\n  protected abstract Client getClient(byte[] key);\n\n  @Override\n  public Response<Long> append(String key, String value) {\n    getClient(key).append(key, value);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> append(byte[] key, byte[] value) {\n    getClient(key).append(key, value);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<List<String>> blpop(String key) {\n    String[] temp = new String[1];\n    temp[0] = key;\n    getClient(key).blpop(temp);\n    return getResponse(BuilderFactory.STRING_LIST);\n  }\n\n  @Override\n  public Response<List<String>> brpop(String key) {\n    String[] temp = new String[1];\n    temp[0] = key;\n    getClient(key).brpop(temp);\n    return getResponse(BuilderFactory.STRING_LIST);\n  }\n\n  @Override\n  public Response<List<byte[]>> blpop(byte[] key) {\n    byte[][] temp = new byte[1][];\n    temp[0] = key;\n    getClient(key).blpop(temp);\n    return getResponse(BuilderFactory.BYTE_ARRAY_LIST);\n  }\n\n  @Override\n  public Response<List<byte[]>> brpop(byte[] key) {\n    byte[][] temp = new byte[1][];\n    temp[0] = key;\n    getClient(key).brpop(temp);\n    return getResponse(BuilderFactory.BYTE_ARRAY_LIST);\n  }\n\n  @Override\n  public Response<Long> decr(String key) {\n    getClient(key).decr(key);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> decr(byte[] key) {\n    getClient(key).decr(key);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> decrBy(String key, long integer) {\n    getClient(key).decrBy(key, integer);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> decrBy(byte[] key, long integer) {\n    getClient(key).decrBy(key, integer);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> del(String key) {\n    getClient(key).del(key);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> del(byte[] key) {\n    getClient(key).del(key);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<String> echo(String string) {\n    getClient(string).echo(string);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  @Override\n  public Response<byte[]> echo(byte[] string) {\n    getClient(string).echo(string);\n    return getResponse(BuilderFactory.BYTE_ARRAY);\n  }\n\n  @Override\n  public Response<Boolean> exists(String key) {\n    getClient(key).exists(key);\n    return getResponse(BuilderFactory.BOOLEAN);\n  }\n\n  @Override\n  public Response<Boolean> exists(byte[] key) {\n    getClient(key).exists(key);\n    return getResponse(BuilderFactory.BOOLEAN);\n  }\n\n  @Override\n  public Response<Long> expire(String key, int seconds) {\n    getClient(key).expire(key, seconds);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> expire(byte[] key, int seconds) {\n    getClient(key).expire(key, seconds);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> expireAt(String key, long unixTime) {\n    getClient(key).expireAt(key, unixTime);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> expireAt(byte[] key, long unixTime) {\n    getClient(key).expireAt(key, unixTime);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<String> get(String key) {\n    getClient(key).get(key);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  @Override\n  public Response<byte[]> get(byte[] key) {\n    getClient(key).get(key);\n    return getResponse(BuilderFactory.BYTE_ARRAY);\n  }\n\n  @Override\n  public Response<Boolean> getbit(String key, long offset) {\n    getClient(key).getbit(key, offset);\n    return getResponse(BuilderFactory.BOOLEAN);\n  }\n\n  @Override\n  public Response<Boolean> getbit(byte[] key, long offset) {\n    getClient(key).getbit(key, offset);\n    return getResponse(BuilderFactory.BOOLEAN);\n  }\n\n  public Response<Long> bitpos(final String key, final boolean value) {\n    return bitpos(key, value, new BitPosParams());\n  }\n\n  public Response<Long> bitpos(final String key, final boolean value, final BitPosParams params) {\n    getClient(key).bitpos(key, value, params);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<Long> bitpos(final byte[] key, final boolean value) {\n    return bitpos(key, value, new BitPosParams());\n  }\n\n  public Response<Long> bitpos(final byte[] key, final boolean value, final BitPosParams params) {\n    getClient(key).bitpos(key, value, params);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<String> getrange(String key, long startOffset, long endOffset) {\n    getClient(key).getrange(key, startOffset, endOffset);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  @Override\n  public Response<String> getSet(String key, String value) {\n    getClient(key).getSet(key, value);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  @Override\n  public Response<byte[]> getSet(byte[] key, byte[] value) {\n    getClient(key).getSet(key, value);\n    return getResponse(BuilderFactory.BYTE_ARRAY);\n  }\n\n  @Override\n  public Response<byte[]> getrange(byte[] key, long startOffset, long endOffset) {\n    getClient(key).getrange(key, startOffset, endOffset);\n    return getResponse(BuilderFactory.BYTE_ARRAY);\n  }\n\n  @Override\n  public Response<Long> hdel(String key, String... field) {\n    getClient(key).hdel(key, field);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> hdel(byte[] key, byte[]... field) {\n    getClient(key).hdel(key, field);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Boolean> hexists(String key, String field) {\n    getClient(key).hexists(key, field);\n    return getResponse(BuilderFactory.BOOLEAN);\n  }\n\n  @Override\n  public Response<Boolean> hexists(byte[] key, byte[] field) {\n    getClient(key).hexists(key, field);\n    return getResponse(BuilderFactory.BOOLEAN);\n  }\n\n  @Override\n  public Response<String> hget(String key, String field) {\n    getClient(key).hget(key, field);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  @Override\n  public Response<byte[]> hget(byte[] key, byte[] field) {\n    getClient(key).hget(key, field);\n    return getResponse(BuilderFactory.BYTE_ARRAY);\n  }\n\n  @Override\n  public Response<Map<String, String>> hgetAll(String key) {\n    getClient(key).hgetAll(key);\n    return getResponse(BuilderFactory.STRING_MAP);\n  }\n\n  @Override\n  public Response<Map<byte[], byte[]>> hgetAll(byte[] key) {\n    getClient(key).hgetAll(key);\n    return getResponse(BuilderFactory.BYTE_ARRAY_MAP);\n  }\n\n  @Override\n  public Response<Long> hincrBy(String key, String field, long value) {\n    getClient(key).hincrBy(key, field, value);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> hincrBy(byte[] key, byte[] field, long value) {\n    getClient(key).hincrBy(key, field, value);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Set<String>> hkeys(String key) {\n    getClient(key).hkeys(key);\n    return getResponse(BuilderFactory.STRING_SET);\n  }\n\n  @Override\n  public Response<Set<byte[]>> hkeys(byte[] key) {\n    getClient(key).hkeys(key);\n    return getResponse(BuilderFactory.BYTE_ARRAY_ZSET);\n  }\n\n  @Override\n  public Response<Long> hlen(String key) {\n    getClient(key).hlen(key);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> hlen(byte[] key) {\n    getClient(key).hlen(key);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<List<String>> hmget(String key, String... fields) {\n    getClient(key).hmget(key, fields);\n    return getResponse(BuilderFactory.STRING_LIST);\n  }\n\n  @Override\n  public Response<List<byte[]>> hmget(byte[] key, byte[]... fields) {\n    getClient(key).hmget(key, fields);\n    return getResponse(BuilderFactory.BYTE_ARRAY_LIST);\n  }\n\n  @Override\n  public Response<String> hmset(String key, Map<String, String> hash) {\n    getClient(key).hmset(key, hash);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  @Override\n  public Response<String> hmset(byte[] key, Map<byte[], byte[]> hash) {\n    getClient(key).hmset(key, hash);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  @Override\n  public Response<Long> hset(String key, String field, String value) {\n    getClient(key).hset(key, field, value);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> hset(byte[] key, byte[] field, byte[] value) {\n    getClient(key).hset(key, field, value);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> hsetnx(String key, String field, String value) {\n    getClient(key).hsetnx(key, field, value);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> hsetnx(byte[] key, byte[] field, byte[] value) {\n    getClient(key).hsetnx(key, field, value);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<List<String>> hvals(String key) {\n    getClient(key).hvals(key);\n    return getResponse(BuilderFactory.STRING_LIST);\n  }\n\n  @Override\n  public Response<List<byte[]>> hvals(byte[] key) {\n    getClient(key).hvals(key);\n    return getResponse(BuilderFactory.BYTE_ARRAY_LIST);\n  }\n\n  @Override\n  public Response<Long> incr(String key) {\n    getClient(key).incr(key);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> incr(byte[] key) {\n    getClient(key).incr(key);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> incrBy(String key, long integer) {\n    getClient(key).incrBy(key, integer);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> incrBy(byte[] key, long integer) {\n    getClient(key).incrBy(key, integer);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<String> lindex(String key, long index) {\n    getClient(key).lindex(key, index);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  @Override\n  public Response<byte[]> lindex(byte[] key, long index) {\n    getClient(key).lindex(key, index);\n    return getResponse(BuilderFactory.BYTE_ARRAY);\n  }\n\n  @Override\n  public Response<Long> linsert(String key, LIST_POSITION where, String pivot, String value) {\n    getClient(key).linsert(key, where, pivot, value);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> linsert(byte[] key, LIST_POSITION where, byte[] pivot, byte[] value) {\n    getClient(key).linsert(key, where, pivot, value);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> llen(String key) {\n    getClient(key).llen(key);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> llen(byte[] key) {\n    getClient(key).llen(key);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<String> lpop(String key) {\n    getClient(key).lpop(key);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  @Override\n  public Response<byte[]> lpop(byte[] key) {\n    getClient(key).lpop(key);\n    return getResponse(BuilderFactory.BYTE_ARRAY);\n  }\n\n  @Override\n  public Response<Long> lpush(String key, String... string) {\n    getClient(key).lpush(key, string);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> lpush(byte[] key, byte[]... string) {\n    getClient(key).lpush(key, string);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> lpushx(String key, String... string) {\n    getClient(key).lpushx(key, string);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> lpushx(byte[] key, byte[]... bytes) {\n    getClient(key).lpushx(key, bytes);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<List<String>> lrange(String key, long start, long end) {\n    getClient(key).lrange(key, start, end);\n    return getResponse(BuilderFactory.STRING_LIST);\n  }\n\n  @Override\n  public Response<List<byte[]>> lrange(byte[] key, long start, long end) {\n    getClient(key).lrange(key, start, end);\n    return getResponse(BuilderFactory.BYTE_ARRAY_LIST);\n  }\n\n  @Override\n  public Response<Long> lrem(String key, long count, String value) {\n    getClient(key).lrem(key, count, value);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> lrem(byte[] key, long count, byte[] value) {\n    getClient(key).lrem(key, count, value);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<String> lset(String key, long index, String value) {\n    getClient(key).lset(key, index, value);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  @Override\n  public Response<String> lset(byte[] key, long index, byte[] value) {\n    getClient(key).lset(key, index, value);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  @Override\n  public Response<String> ltrim(String key, long start, long end) {\n    getClient(key).ltrim(key, start, end);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  @Override\n  public Response<String> ltrim(byte[] key, long start, long end) {\n    getClient(key).ltrim(key, start, end);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  @Override\n  public Response<Long> move(String key, int dbIndex) {\n    getClient(key).move(key, dbIndex);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> move(byte[] key, int dbIndex) {\n    getClient(key).move(key, dbIndex);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> persist(String key) {\n    getClient(key).persist(key);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> persist(byte[] key) {\n    getClient(key).persist(key);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<String> rpop(String key) {\n    getClient(key).rpop(key);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  @Override\n  public Response<byte[]> rpop(byte[] key) {\n    getClient(key).rpop(key);\n    return getResponse(BuilderFactory.BYTE_ARRAY);\n  }\n\n  @Override\n  public Response<Long> rpush(String key, String... string) {\n    getClient(key).rpush(key, string);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> rpush(byte[] key, byte[]... string) {\n    getClient(key).rpush(key, string);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> rpushx(String key, String... string) {\n    getClient(key).rpushx(key, string);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> rpushx(byte[] key, byte[]... string) {\n    getClient(key).rpushx(key, string);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> sadd(String key, String... member) {\n    getClient(key).sadd(key, member);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> sadd(byte[] key, byte[]... member) {\n    getClient(key).sadd(key, member);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> scard(String key) {\n    getClient(key).scard(key);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> scard(byte[] key) {\n    getClient(key).scard(key);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<String> set(String key, String value) {\n    getClient(key).set(key, value);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  @Override\n  public Response<String> set(byte[] key, byte[] value) {\n    getClient(key).set(key, value);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  public Response<String> set(String key, String value, SetParams params) {\n    getClient(key).set(key, value, params);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  public Response<String> set(byte[] key, byte[] value, SetParams params) {\n    getClient(key).set(key, value, params);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  @Override\n  public Response<Boolean> setbit(String key, long offset, boolean value) {\n    getClient(key).setbit(key, offset, value);\n    return getResponse(BuilderFactory.BOOLEAN);\n  }\n\n  @Override\n  public Response<Boolean> setbit(byte[] key, long offset, byte[] value) {\n    getClient(key).setbit(key, offset, value);\n    return getResponse(BuilderFactory.BOOLEAN);\n  }\n\n  @Override\n  public Response<String> setex(String key, int seconds, String value) {\n    getClient(key).setex(key, seconds, value);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  @Override\n  public Response<String> setex(byte[] key, int seconds, byte[] value) {\n    getClient(key).setex(key, seconds, value);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  @Override\n  public Response<Long> setnx(String key, String value) {\n    getClient(key).setnx(key, value);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> setnx(byte[] key, byte[] value) {\n    getClient(key).setnx(key, value);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> setrange(String key, long offset, String value) {\n    getClient(key).setrange(key, offset, value);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> setrange(byte[] key, long offset, byte[] value) {\n    getClient(key).setrange(key, offset, value);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Boolean> sismember(String key, String member) {\n    getClient(key).sismember(key, member);\n    return getResponse(BuilderFactory.BOOLEAN);\n  }\n\n  @Override\n  public Response<Boolean> sismember(byte[] key, byte[] member) {\n    getClient(key).sismember(key, member);\n    return getResponse(BuilderFactory.BOOLEAN);\n  }\n\n  @Override\n  public Response<Set<String>> smembers(String key) {\n    getClient(key).smembers(key);\n    return getResponse(BuilderFactory.STRING_SET);\n  }\n\n  @Override\n  public Response<Set<byte[]>> smembers(byte[] key) {\n    getClient(key).smembers(key);\n    return getResponse(BuilderFactory.BYTE_ARRAY_ZSET);\n  }\n\n  @Override\n  public Response<List<String>> sort(String key) {\n    getClient(key).sort(key);\n    return getResponse(BuilderFactory.STRING_LIST);\n  }\n\n  @Override\n  public Response<List<byte[]>> sort(byte[] key) {\n    getClient(key).sort(key);\n    return getResponse(BuilderFactory.BYTE_ARRAY_LIST);\n  }\n\n  @Override\n  public Response<List<String>> sort(String key, SortingParams sortingParameters) {\n    getClient(key).sort(key, sortingParameters);\n    return getResponse(BuilderFactory.STRING_LIST);\n  }\n\n  @Override\n  public Response<List<byte[]>> sort(byte[] key, SortingParams sortingParameters) {\n    getClient(key).sort(key, sortingParameters);\n    return getResponse(BuilderFactory.BYTE_ARRAY_LIST);\n  }\n\n  @Override\n  public Response<String> spop(String key) {\n    getClient(key).spop(key);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  @Override\n  public Response<Set<String>> spop(String key, long count) {\n    getClient(key).spop(key, count);\n    return getResponse(BuilderFactory.STRING_SET);\n  }\n\n  @Override\n  public Response<byte[]> spop(byte[] key) {\n    getClient(key).spop(key);\n    return getResponse(BuilderFactory.BYTE_ARRAY);\n  }\n\n  @Override\n  public Response<Set<byte[]>> spop(byte[] key, long count) {\n    getClient(key).spop(key, count);\n    return getResponse(BuilderFactory.BYTE_ARRAY_ZSET);\n  }\n\n  @Override\n  public Response<String> srandmember(String key) {\n    getClient(key).srandmember(key);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  public Response<List<String>> srandmember(String key, int count) {\n    getClient(key).srandmember(key, count);\n    return getResponse(BuilderFactory.STRING_LIST);\n  }\n\n  @Override\n  public Response<byte[]> srandmember(byte[] key) {\n    getClient(key).srandmember(key);\n    return getResponse(BuilderFactory.BYTE_ARRAY);\n  }\n\n  public Response<List<byte[]>> srandmember(byte[] key, int count) {\n    getClient(key).srandmember(key, count);\n    return getResponse(BuilderFactory.BYTE_ARRAY_LIST);\n  }\n\n  @Override\n  public Response<Long> srem(String key, String... member) {\n    getClient(key).srem(key, member);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> srem(byte[] key, byte[]... member) {\n    getClient(key).srem(key, member);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> strlen(String key) {\n    getClient(key).strlen(key);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> strlen(byte[] key) {\n    getClient(key).strlen(key);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<String> substr(String key, int start, int end) {\n    getClient(key).substr(key, start, end);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  @Override\n  public Response<String> substr(byte[] key, int start, int end) {\n    getClient(key).substr(key, start, end);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  @Override\n  public Response<Long> ttl(String key) {\n    getClient(key).ttl(key);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> ttl(byte[] key) {\n    getClient(key).ttl(key);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<String> type(String key) {\n    getClient(key).type(key);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  @Override\n  public Response<String> type(byte[] key) {\n    getClient(key).type(key);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  @Override\n  public Response<Long> zadd(String key, double score, String member) {\n    getClient(key).zadd(key, score, member);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> zadd(String key, double score, String member, ZAddParams params) {\n    getClient(key).zadd(key, score, member, params);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<Long> zadd(String key, Map<String, Double> scoreMembers) {\n    getClient(key).zadd(key, scoreMembers);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> zadd(String key, Map<String, Double> scoreMembers, ZAddParams params) {\n    getClient(key).zadd(key, scoreMembers, params);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> zadd(byte[] key, double score, byte[] member) {\n    getClient(key).zadd(key, score, member);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> zadd(byte[] key, double score, byte[] member, ZAddParams params) {\n    getClient(key).zadd(key, score, member);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> zadd(byte[] key, Map<byte[], Double> scoreMembers) {\n    getClient(key).zadd(key, scoreMembers);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> zadd(byte[] key, Map<byte[], Double> scoreMembers, ZAddParams params) {\n    getClient(key).zadd(key, scoreMembers, params);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> zcard(String key) {\n    getClient(key).zcard(key);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> zcard(byte[] key) {\n    getClient(key).zcard(key);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> zcount(String key, double min, double max) {\n    getClient(key).zcount(key, min, max);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<Long> zcount(String key, String min, String max) {\n    getClient(key).zcount(key, min, max);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> zcount(byte[] key, double min, double max) {\n    getClient(key).zcount(key, toByteArray(min), toByteArray(max));\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<Long> zcount(byte[] key, byte[] min, byte[] max) {\n    getClient(key).zcount(key, min, max);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Double> zincrby(String key, double score, String member) {\n    getClient(key).zincrby(key, score, member);\n    return getResponse(BuilderFactory.DOUBLE);\n  }\n\n  @Override\n  public Response<Double> zincrby(String key, double score, String member, ZIncrByParams params) {\n    getClient(key).zincrby(key, score, member, params);\n    return getResponse(BuilderFactory.DOUBLE);\n  }\n\n  @Override\n  public Response<Double> zincrby(byte[] key, double score, byte[] member) {\n    getClient(key).zincrby(key, score, member);\n    return getResponse(BuilderFactory.DOUBLE);\n  }\n\n  @Override\n  public Response<Double> zincrby(byte[] key, double score, byte[] member, ZIncrByParams params) {\n    getClient(key).zincrby(key, score, member);\n    return getResponse(BuilderFactory.DOUBLE);\n  }\n\n  @Override\n  public Response<Set<String>> zrange(String key, long start, long end) {\n    getClient(key).zrange(key, start, end);\n    return getResponse(BuilderFactory.STRING_ZSET);\n  }\n\n  @Override\n  public Response<Set<byte[]>> zrange(byte[] key, long start, long end) {\n    getClient(key).zrange(key, start, end);\n    return getResponse(BuilderFactory.BYTE_ARRAY_ZSET);\n  }\n\n  @Override\n  public Response<Set<String>> zrangeByScore(String key, double min, double max) {\n    getClient(key).zrangeByScore(key, min, max);\n    return getResponse(BuilderFactory.STRING_ZSET);\n  }\n\n  @Override\n  public Response<Set<byte[]>> zrangeByScore(byte[] key, double min, double max) {\n    return zrangeByScore(key, toByteArray(min), toByteArray(max));\n  }\n\n  @Override\n  public Response<Set<String>> zrangeByScore(String key, String min, String max) {\n    getClient(key).zrangeByScore(key, min, max);\n    return getResponse(BuilderFactory.STRING_ZSET);\n  }\n\n  @Override\n  public Response<Set<byte[]>> zrangeByScore(byte[] key, byte[] min, byte[] max) {\n    getClient(key).zrangeByScore(key, min, max);\n    return getResponse(BuilderFactory.BYTE_ARRAY_ZSET);\n  }\n\n  @Override\n  public Response<Set<String>> zrangeByScore(String key, double min, double max, int offset,\n      int count) {\n    getClient(key).zrangeByScore(key, min, max, offset, count);\n    return getResponse(BuilderFactory.STRING_ZSET);\n  }\n\n  public Response<Set<String>> zrangeByScore(String key, String min, String max, int offset,\n      int count) {\n    getClient(key).zrangeByScore(key, min, max, offset, count);\n    return getResponse(BuilderFactory.STRING_ZSET);\n  }\n\n  @Override\n  public Response<Set<byte[]>> zrangeByScore(byte[] key, double min, double max, int offset,\n      int count) {\n    return zrangeByScore(key, toByteArray(min), toByteArray(max), offset, count);\n  }\n\n  @Override\n  public Response<Set<byte[]>> zrangeByScore(byte[] key, byte[] min, byte[] max, int offset,\n      int count) {\n    getClient(key).zrangeByScore(key, min, max, offset, count);\n    return getResponse(BuilderFactory.BYTE_ARRAY_ZSET);\n  }\n\n  @Override\n  public Response<Set<Tuple>> zrangeByScoreWithScores(String key, double min, double max) {\n    getClient(key).zrangeByScoreWithScores(key, min, max);\n    return getResponse(BuilderFactory.TUPLE_ZSET);\n  }\n\n  public Response<Set<Tuple>> zrangeByScoreWithScores(String key, String min, String max) {\n    getClient(key).zrangeByScoreWithScores(key, min, max);\n    return getResponse(BuilderFactory.TUPLE_ZSET);\n  }\n\n  @Override\n  public Response<Set<Tuple>> zrangeByScoreWithScores(byte[] key, double min, double max) {\n    return zrangeByScoreWithScores(key, toByteArray(min), toByteArray(max));\n  }\n\n  @Override\n  public Response<Set<Tuple>> zrangeByScoreWithScores(byte[] key, byte[] min, byte[] max) {\n    getClient(key).zrangeByScoreWithScores(key, min, max);\n    return getResponse(BuilderFactory.TUPLE_ZSET_BINARY);\n  }\n\n  @Override\n  public Response<Set<Tuple>> zrangeByScoreWithScores(String key, double min, double max,\n      int offset, int count) {\n    getClient(key).zrangeByScoreWithScores(key, min, max, offset, count);\n    return getResponse(BuilderFactory.TUPLE_ZSET);\n  }\n\n  public Response<Set<Tuple>> zrangeByScoreWithScores(String key, String min, String max,\n      int offset, int count) {\n    getClient(key).zrangeByScoreWithScores(key, min, max, offset, count);\n    return getResponse(BuilderFactory.TUPLE_ZSET);\n  }\n\n  @Override\n  public Response<Set<Tuple>> zrangeByScoreWithScores(byte[] key, double min, double max,\n      int offset, int count) {\n    getClient(key).zrangeByScoreWithScores(key, toByteArray(min), toByteArray(max), offset, count);\n    return getResponse(BuilderFactory.TUPLE_ZSET_BINARY);\n  }\n\n  @Override\n  public Response<Set<Tuple>> zrangeByScoreWithScores(byte[] key, byte[] min, byte[] max,\n      int offset, int count) {\n    getClient(key).zrangeByScoreWithScores(key, min, max, offset, count);\n    return getResponse(BuilderFactory.TUPLE_ZSET_BINARY);\n  }\n\n  @Override\n  public Response<Set<String>> zrevrangeByScore(String key, double max, double min) {\n    getClient(key).zrevrangeByScore(key, max, min);\n    return getResponse(BuilderFactory.STRING_ZSET);\n  }\n\n  @Override\n  public Response<Set<byte[]>> zrevrangeByScore(byte[] key, double max, double min) {\n    getClient(key).zrevrangeByScore(key, toByteArray(max), toByteArray(min));\n    return getResponse(BuilderFactory.BYTE_ARRAY_ZSET);\n  }\n\n  @Override\n  public Response<Set<String>> zrevrangeByScore(String key, String max, String min) {\n    getClient(key).zrevrangeByScore(key, max, min);\n    return getResponse(BuilderFactory.STRING_ZSET);\n  }\n\n  @Override\n  public Response<Set<byte[]>> zrevrangeByScore(byte[] key, byte[] max, byte[] min) {\n    getClient(key).zrevrangeByScore(key, max, min);\n    return getResponse(BuilderFactory.BYTE_ARRAY_ZSET);\n  }\n\n  @Override\n  public Response<Set<String>> zrevrangeByScore(String key, double max, double min, int offset,\n      int count) {\n    getClient(key).zrevrangeByScore(key, max, min, offset, count);\n    return getResponse(BuilderFactory.STRING_ZSET);\n  }\n\n  public Response<Set<String>> zrevrangeByScore(String key, String max, String min, int offset,\n      int count) {\n    getClient(key).zrevrangeByScore(key, max, min, offset, count);\n    return getResponse(BuilderFactory.STRING_ZSET);\n  }\n\n  @Override\n  public Response<Set<byte[]>> zrevrangeByScore(byte[] key, double max, double min, int offset,\n      int count) {\n    getClient(key).zrevrangeByScore(key, toByteArray(max), toByteArray(min), offset, count);\n    return getResponse(BuilderFactory.BYTE_ARRAY_ZSET);\n  }\n\n  @Override\n  public Response<Set<byte[]>> zrevrangeByScore(byte[] key, byte[] max, byte[] min, int offset,\n      int count) {\n    getClient(key).zrevrangeByScore(key, max, min, offset, count);\n    return getResponse(BuilderFactory.BYTE_ARRAY_ZSET);\n  }\n\n  @Override\n  public Response<Set<Tuple>> zrevrangeByScoreWithScores(String key, double max, double min) {\n    getClient(key).zrevrangeByScoreWithScores(key, max, min);\n    return getResponse(BuilderFactory.TUPLE_ZSET);\n  }\n\n  public Response<Set<Tuple>> zrevrangeByScoreWithScores(String key, String max, String min) {\n    getClient(key).zrevrangeByScoreWithScores(key, max, min);\n    return getResponse(BuilderFactory.TUPLE_ZSET);\n  }\n\n  @Override\n  public Response<Set<Tuple>> zrevrangeByScoreWithScores(byte[] key, double max, double min) {\n    getClient(key).zrevrangeByScoreWithScores(key, toByteArray(max), toByteArray(min));\n    return getResponse(BuilderFactory.TUPLE_ZSET_BINARY);\n  }\n\n  @Override\n  public Response<Set<Tuple>> zrevrangeByScoreWithScores(byte[] key, byte[] max, byte[] min) {\n    getClient(key).zrevrangeByScoreWithScores(key, max, min);\n    return getResponse(BuilderFactory.TUPLE_ZSET_BINARY);\n  }\n\n  @Override\n  public Response<Set<Tuple>> zrevrangeByScoreWithScores(String key, double max, double min,\n      int offset, int count) {\n    getClient(key).zrevrangeByScoreWithScores(key, max, min, offset, count);\n    return getResponse(BuilderFactory.TUPLE_ZSET);\n  }\n\n  public Response<Set<Tuple>> zrevrangeByScoreWithScores(String key, String max, String min,\n      int offset, int count) {\n    getClient(key).zrevrangeByScoreWithScores(key, max, min, offset, count);\n    return getResponse(BuilderFactory.TUPLE_ZSET);\n  }\n\n  @Override\n  public Response<Set<Tuple>> zrevrangeByScoreWithScores(byte[] key, double max, double min,\n      int offset, int count) {\n    getClient(key).zrevrangeByScoreWithScores(key, toByteArray(max), toByteArray(min), offset,\n      count);\n    return getResponse(BuilderFactory.TUPLE_ZSET_BINARY);\n  }\n\n  @Override\n  public Response<Set<Tuple>> zrevrangeByScoreWithScores(byte[] key, byte[] max, byte[] min,\n      int offset, int count) {\n    getClient(key).zrevrangeByScoreWithScores(key, max, min, offset, count);\n    return getResponse(BuilderFactory.TUPLE_ZSET_BINARY);\n  }\n\n  @Override\n  public Response<Set<Tuple>> zrangeWithScores(String key, long start, long end) {\n    getClient(key).zrangeWithScores(key, start, end);\n    return getResponse(BuilderFactory.TUPLE_ZSET);\n  }\n\n  @Override\n  public Response<Set<Tuple>> zrangeWithScores(byte[] key, long start, long end) {\n    getClient(key).zrangeWithScores(key, start, end);\n    return getResponse(BuilderFactory.TUPLE_ZSET_BINARY);\n  }\n\n  @Override\n  public Response<Long> zrank(String key, String member) {\n    getClient(key).zrank(key, member);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> zrank(byte[] key, byte[] member) {\n    getClient(key).zrank(key, member);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> zrem(String key, String... member) {\n    getClient(key).zrem(key, member);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> zrem(byte[] key, byte[]... member) {\n    getClient(key).zrem(key, member);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> zremrangeByRank(String key, long start, long end) {\n    getClient(key).zremrangeByRank(key, start, end);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> zremrangeByRank(byte[] key, long start, long end) {\n    getClient(key).zremrangeByRank(key, start, end);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> zremrangeByScore(String key, double start, double end) {\n    getClient(key).zremrangeByScore(key, start, end);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<Long> zremrangeByScore(String key, String start, String end) {\n    getClient(key).zremrangeByScore(key, start, end);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> zremrangeByScore(byte[] key, double start, double end) {\n    getClient(key).zremrangeByScore(key, toByteArray(start), toByteArray(end));\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> zremrangeByScore(byte[] key, byte[] start, byte[] end) {\n    getClient(key).zremrangeByScore(key, start, end);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Set<String>> zrevrange(String key, long start, long end) {\n    getClient(key).zrevrange(key, start, end);\n    return getResponse(BuilderFactory.STRING_ZSET);\n  }\n\n  @Override\n  public Response<Set<byte[]>> zrevrange(byte[] key, long start, long end) {\n    getClient(key).zrevrange(key, start, end);\n    return getResponse(BuilderFactory.BYTE_ARRAY_ZSET);\n  }\n\n  @Override\n  public Response<Set<Tuple>> zrevrangeWithScores(String key, long start, long end) {\n    getClient(key).zrevrangeWithScores(key, start, end);\n    return getResponse(BuilderFactory.TUPLE_ZSET);\n  }\n\n  @Override\n  public Response<Set<Tuple>> zrevrangeWithScores(byte[] key, long start, long end) {\n    getClient(key).zrevrangeWithScores(key, start, end);\n    return getResponse(BuilderFactory.TUPLE_ZSET);\n  }\n\n  @Override\n  public Response<Long> zrevrank(String key, String member) {\n    getClient(key).zrevrank(key, member);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> zrevrank(byte[] key, byte[] member) {\n    getClient(key).zrevrank(key, member);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Double> zscore(String key, String member) {\n    getClient(key).zscore(key, member);\n    return getResponse(BuilderFactory.DOUBLE);\n  }\n\n  @Override\n  public Response<Double> zscore(byte[] key, byte[] member) {\n    getClient(key).zscore(key, member);\n    return getResponse(BuilderFactory.DOUBLE);\n  }\n\n  @Override\n  public Response<Long> zlexcount(final byte[] key, final byte[] min, final byte[] max) {\n    getClient(key).zlexcount(key, min, max);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> zlexcount(final String key, final String min, final String max) {\n    getClient(key).zlexcount(key, min, max);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Set<byte[]>> zrangeByLex(final byte[] key, final byte[] min, final byte[] max) {\n    getClient(key).zrangeByLex(key, min, max);\n    return getResponse(BuilderFactory.BYTE_ARRAY_ZSET);\n  }\n\n  @Override\n  public Response<Set<String>> zrangeByLex(final String key, final String min, final String max) {\n    getClient(key).zrangeByLex(key, min, max);\n    return getResponse(BuilderFactory.STRING_ZSET);\n  }\n\n  @Override\n  public Response<Set<byte[]>> zrangeByLex(final byte[] key, final byte[] min, final byte[] max,\n      final int offset, final int count) {\n    getClient(key).zrangeByLex(key, min, max, offset, count);\n    return getResponse(BuilderFactory.BYTE_ARRAY_ZSET);\n  }\n\n  @Override\n  public Response<Set<String>> zrangeByLex(final String key, final String min, final String max,\n      final int offset, final int count) {\n    getClient(key).zrangeByLex(key, min, max, offset, count);\n    return getResponse(BuilderFactory.STRING_ZSET);\n  }\n\n  @Override\n  public Response<Set<byte[]>> zrevrangeByLex(final byte[] key, final byte[] max, final byte[] min) {\n    getClient(key).zrevrangeByLex(key, max, min);\n    return getResponse(BuilderFactory.BYTE_ARRAY_ZSET);\n  }\n\n  @Override\n  public Response<Set<String>> zrevrangeByLex(final String key, final String max, final String min) {\n    getClient(key).zrevrangeByLex(key, max, min);\n    return getResponse(BuilderFactory.STRING_ZSET);\n  }\n\n  @Override\n  public Response<Set<byte[]>> zrevrangeByLex(final byte[] key, final byte[] max, final byte[] min,\n      final int offset, final int count) {\n    getClient(key).zrevrangeByLex(key, max, min, offset, count);\n    return getResponse(BuilderFactory.BYTE_ARRAY_ZSET);\n  }\n\n  @Override\n  public Response<Set<String>> zrevrangeByLex(final String key, final String max, final String min,\n      final int offset, final int count) {\n    getClient(key).zrevrangeByLex(key, max, min, offset, count);\n    return getResponse(BuilderFactory.STRING_ZSET);\n  }\n\n  @Override\n  public Response<Long> zremrangeByLex(final byte[] key, final byte[] min, final byte[] max) {\n    getClient(key).zremrangeByLex(key, min, max);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> zremrangeByLex(final String key, final String min, final String max) {\n    getClient(key).zremrangeByLex(key, min, max);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> bitcount(String key) {\n    getClient(key).bitcount(key);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> bitcount(String key, long start, long end) {\n    getClient(key).bitcount(key, start, end);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> bitcount(byte[] key) {\n    getClient(key).bitcount(key);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> bitcount(byte[] key, long start, long end) {\n    getClient(key).bitcount(key, start, end);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<byte[]> dump(String key) {\n    getClient(key).dump(key);\n    return getResponse(BuilderFactory.BYTE_ARRAY);\n  }\n\n  public Response<byte[]> dump(byte[] key) {\n    getClient(key).dump(key);\n    return getResponse(BuilderFactory.BYTE_ARRAY);\n  }\n\n  public Response<String> migrate(String host, int port, String key, int destinationDb, int timeout) {\n    getClient(key).migrate(host, port, key, destinationDb, timeout);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  public Response<String> migrate(byte[] host, int port, byte[] key, int destinationDb, int timeout) {\n    getClient(key).migrate(host, port, key, destinationDb, timeout);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  public Response<Long> objectRefcount(String key) {\n    getClient(key).objectRefcount(key);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<Long> objectRefcount(byte[] key) {\n    getClient(key).objectRefcount(key);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<String> objectEncoding(String key) {\n    getClient(key).objectEncoding(key);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  public Response<byte[]> objectEncoding(byte[] key) {\n    getClient(key).objectEncoding(key);\n    return getResponse(BuilderFactory.BYTE_ARRAY);\n  }\n\n  public Response<Long> objectIdletime(String key) {\n    getClient(key).objectIdletime(key);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<Long> objectIdletime(byte[] key) {\n    getClient(key).objectIdletime(key);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> pexpire(String key, long milliseconds) {\n    getClient(key).pexpire(key, milliseconds);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> pexpire(byte[] key, long milliseconds) {\n    getClient(key).pexpire(key, milliseconds);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> pexpireAt(String key, long millisecondsTimestamp) {\n    getClient(key).pexpireAt(key, millisecondsTimestamp);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> pexpireAt(byte[] key, long millisecondsTimestamp) {\n    getClient(key).pexpireAt(key, millisecondsTimestamp);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<Long> pttl(String key) {\n    getClient(key).pttl(key);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<Long> pttl(byte[] key) {\n    getClient(key).pttl(key);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  public Response<String> restore(String key, int ttl, byte[] serializedValue) {\n    getClient(key).restore(key, ttl, serializedValue);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  public Response<String> restore(byte[] key, int ttl, byte[] serializedValue) {\n    getClient(key).restore(key, ttl, serializedValue);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  public Response<Double> incrByFloat(String key, double increment) {\n    getClient(key).incrByFloat(key, increment);\n    return getResponse(BuilderFactory.DOUBLE);\n  }\n\n  public Response<Double> incrByFloat(byte[] key, double increment) {\n    getClient(key).incrByFloat(key, increment);\n    return getResponse(BuilderFactory.DOUBLE);\n  }\n\n  public Response<String> psetex(String key, long milliseconds, String value) {\n    getClient(key).psetex(key, milliseconds, value);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  public Response<String> psetex(byte[] key, long milliseconds, byte[] value) {\n    getClient(key).psetex(key, milliseconds, value);\n    return getResponse(BuilderFactory.STRING);\n  }\n\n  public Response<Double> hincrByFloat(String key, String field, double increment) {\n    getClient(key).hincrByFloat(key, field, increment);\n    return getResponse(BuilderFactory.DOUBLE);\n  }\n\n  public Response<Double> hincrByFloat(byte[] key, byte[] field, double increment) {\n    getClient(key).hincrByFloat(key, field, increment);\n    return getResponse(BuilderFactory.DOUBLE);\n  }\n\n  @Override\n  public Response<Long> pfadd(byte[] key, byte[]... elements) {\n    getClient(key).pfadd(key, elements);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> pfcount(byte[] key) {\n    getClient(key).pfcount(key);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> pfadd(String key, String... elements) {\n    getClient(key).pfadd(key, elements);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> pfcount(String key) {\n    getClient(key).pfcount(key);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> geoadd(byte[] key, double longitude, double latitude, byte[] member) {\n    getClient(key).geoadd(key, longitude, latitude, member);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> geoadd(byte[] key, Map<byte[], GeoCoordinate> memberCoordinateMap) {\n    getClient(key).geoadd(key, memberCoordinateMap);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> geoadd(String key, double longitude, double latitude, String member) {\n    getClient(key).geoadd(key, longitude, latitude, member);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Long> geoadd(String key, Map<String, GeoCoordinate> memberCoordinateMap) {\n    getClient(key).geoadd(key, memberCoordinateMap);\n    return getResponse(BuilderFactory.LONG);\n  }\n\n  @Override\n  public Response<Double> geodist(byte[] key, byte[] member1, byte[] member2) {\n    getClient(key).geodist(key, member1, member2);\n    return getResponse(BuilderFactory.DOUBLE);\n  }\n\n  @Override\n  public Response<Double> geodist(byte[] key, byte[] member1, byte[] member2, GeoUnit unit) {\n    getClient(key).geodist(key, member1, member2, unit);\n    return getResponse(BuilderFactory.DOUBLE);\n  }\n\n  @Override\n  public Response<Double> geodist(String key, String member1, String member2) {\n    getClient(key).geodist(key, member1, member2);\n    return getResponse(BuilderFactory.DOUBLE);\n  }\n\n  @Override\n  public Response<Double> geodist(String key, String member1, String member2, GeoUnit unit) {\n    getClient(key).geodist(key, member1, member2);\n    return getResponse(BuilderFactory.DOUBLE);\n  }\n\n  @Override\n  public Response<List<byte[]>> geohash(byte[] key, byte[]... members) {\n    getClient(key).geohash(key, members);\n    return getResponse(BuilderFactory.BYTE_ARRAY_LIST);\n  }\n\n  @Override\n  public Response<List<String>> geohash(String key, String... members) {\n    getClient(key).geohash(key, members);\n    return getResponse(BuilderFactory.STRING_LIST);\n  }\n\n  @Override\n  public Response<List<GeoCoordinate>> geopos(byte[] key, byte[]... members) {\n    getClient(key).geopos(key, members);\n    return getResponse(BuilderFactory.GEO_COORDINATE_LIST);\n  }\n\n  @Override\n  public Response<List<GeoCoordinate>> geopos(String key, String... members) {\n    getClient(key).geopos(key, members);\n    return getResponse(BuilderFactory.GEO_COORDINATE_LIST);\n  }\n\n  @Override\n  public Response<List<GeoRadiusResponse>> georadius(byte[] key, double longitude, double latitude,\n      double radius, GeoUnit unit) {\n    getClient(key).georadius(key, longitude, latitude, radius, unit);\n    return getResponse(BuilderFactory.GEORADIUS_WITH_PARAMS_RESULT);\n  }\n\n  @Override\n  public Response<List<GeoRadiusResponse>> georadius(byte[] key, double longitude, double latitude,\n      double radius, GeoUnit unit, GeoRadiusParam param) {\n    getClient(key).georadius(key, longitude, latitude, radius, unit, param);\n    return getResponse(BuilderFactory.GEORADIUS_WITH_PARAMS_RESULT);\n  }\n\n  @Override\n  public Response<List<GeoRadiusResponse>> georadius(String key, double longitude, double latitude,\n      double radius, GeoUnit unit) {\n    getClient(key).georadius(key, longitude, latitude, radius, unit);\n    return getResponse(BuilderFactory.GEORADIUS_WITH_PARAMS_RESULT);\n  }\n\n  @Override\n  public Response<List<GeoRadiusResponse>> georadius(String key, double longitude, double latitude,\n      double radius, GeoUnit unit, GeoRadiusParam param) {\n    getClient(key).georadius(key, longitude, latitude, radius, unit, param);\n    return getResponse(BuilderFactory.GEORADIUS_WITH_PARAMS_RESULT);\n  }\n\n  @Override\n  public Response<List<GeoRadiusResponse>> georadiusByMember(byte[] key, byte[] member,\n      double radius, GeoUnit unit) {\n    getClient(key).georadiusByMember(key, member, radius, unit);\n    return getResponse(BuilderFactory.GEORADIUS_WITH_PARAMS_RESULT);\n  }\n\n  @Override\n  public Response<List<GeoRadiusResponse>> georadiusByMember(byte[] key, byte[] member,\n      double radius, GeoUnit unit, GeoRadiusParam param) {\n    getClient(key).georadiusByMember(key, member, radius, unit, param);\n    return getResponse(BuilderFactory.GEORADIUS_WITH_PARAMS_RESULT);\n  }\n\n  @Override\n  public Response<List<GeoRadiusResponse>> georadiusByMember(String key, String member,\n      double radius, GeoUnit unit) {\n    getClient(key).georadiusByMember(key, member, radius, unit);\n    return getResponse(BuilderFactory.GEORADIUS_WITH_PARAMS_RESULT);\n  }\n\n  @Override\n  public Response<List<GeoRadiusResponse>> georadiusByMember(String key, String member,\n      double radius, GeoUnit unit, GeoRadiusParam param) {\n    getClient(key).georadiusByMember(key, member, radius, unit, param);\n    return getResponse(BuilderFactory.GEORADIUS_WITH_PARAMS_RESULT);\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/PipelineCluster.java",
    "content": "package redis.clients.jedis;\n\nimport org.apache.commons.pool2.impl.GenericObjectPoolConfig;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport redis.clients.jedis.params.set.SetParams;\nimport redis.clients.jedis.valueobject.RangeScoreVO;\nimport redis.clients.jedis.valueobject.SortedSetVO;\nimport redis.clients.util.SafeEncoder;\n\nimport java.nio.charset.Charset;\nimport java.util.*;\n\n/**\n * Created by yijunzhang on 14-6-23.\n */\npublic class PipelineCluster extends JedisCluster {\n    private final Logger logger = LoggerFactory.getLogger(this.getClass());\n\n    public PipelineCluster(GenericObjectPoolConfig poolConfig, Set<HostAndPort> nodes, int timeout) {\n        super(nodes, timeout, poolConfig);\n    }\n\n    public PipelineCluster(GenericObjectPoolConfig poolConfig, Set<HostAndPort> nodes) {\n        super(nodes, poolConfig);\n    }\n\n    public PipelineCluster(GenericObjectPoolConfig poolConfig, Set<HostAndPort> jedisClusterNode, int timeout,\n                           int maxRedirections) {\n        super(jedisClusterNode, timeout, maxRedirections, poolConfig);\n    }\n\n    public String set(final String key, final byte[] value) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<String>(connectionHandler, maxRedirections) {\n            public String execute(Jedis connection) {\n                return connection.set(keyByte, value);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public String set(final String key, final byte[] value, final String expx, final long time) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<String>(connectionHandler, maxRedirections) {\n            @Override\n            public String execute(Jedis connection) {\n                SetParams params = SetParams.setParams();\n                if (expx.equalsIgnoreCase(\"px\")) {\n                    params.px(time);\n                } else {\n                    params.ex((int) time);\n                }\n                return connection.set(keyByte, value, params);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public byte[] getBytes(final String key) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<byte[]>(connectionHandler, maxRedirections) {\n            @Override\n            public byte[] execute(Jedis connection) {\n                return connection.get(keyByte);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public Boolean setbit(final String key, final long offset,\n                          final byte[] value) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<Boolean>(connectionHandler, maxRedirections) {\n            public Boolean execute(Jedis connection) {\n                return connection.setbit(keyByte, offset, value);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public Long setrange(final String key, final long offset, final byte[] value) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n            public Long execute(Jedis connection) {\n                return connection.setrange(keyByte, offset, value);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public byte[] getrangeBytes(final String key, final long startOffset, final long endOffset) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<byte[]>(connectionHandler, maxRedirections) {\n            public byte[] execute(Jedis connection) {\n                return connection.getrange(keyByte, startOffset, endOffset);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public byte[] getSetBytes(final String key, final byte[] value) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<byte[]>(connectionHandler, maxRedirections) {\n            public byte[] execute(Jedis connection) {\n                return connection.getSet(keyByte, value);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public Long setnx(final String key, final byte[] value) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n            public Long execute(Jedis connection) {\n                return connection.setnx(keyByte, value);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public String setex(final String key, final int seconds, final byte[] value) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<String>(connectionHandler, maxRedirections) {\n            public String execute(Jedis connection) {\n                return connection.setex(keyByte, seconds, value);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public byte[] substrBytes(final String key, final int start, final int end) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<byte[]>(connectionHandler, maxRedirections) {\n            public byte[] execute(Jedis connection) {\n                return connection.substr(keyByte, start, end);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public Long hset(final String key, final String field, final byte[] value) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n            public Long execute(Jedis connection) {\n                return connection.hset(keyByte, SafeEncoder.encode(field), value);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public byte[] hgetBytes(final String key, final String field) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<byte[]>(connectionHandler, maxRedirections) {\n            public byte[] execute(Jedis connection) {\n                return connection.hget(keyByte, SafeEncoder.encode(field));\n            }\n        }.runBinary(keyByte);\n    }\n\n    public Long hsetnx(final String key, final String field, final byte[] value) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n            public Long execute(Jedis connection) {\n                return connection.hsetnx(keyByte, SafeEncoder.encode(field), value);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public String hmsetBytes(final String key, final Map<byte[], byte[]> hash) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<String>(connectionHandler, maxRedirections) {\n            public String execute(Jedis connection) {\n                return connection.hmset(keyByte, hash);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public List<byte[]> hmget(final String key, final byte[]... fields) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<List<byte[]>>(connectionHandler, maxRedirections) {\n            public List<byte[]> execute(Jedis connection) {\n                return connection.hmget(keyByte, fields);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public Set<byte[]> hkeysBytes(final String key) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<Set<byte[]>>(connectionHandler, maxRedirections) {\n            public Set<byte[]> execute(Jedis connection) {\n                return connection.hkeys(SafeEncoder.encode(key));\n            }\n        }.runBinary(keyByte);\n    }\n\n    public List<byte[]> hvalsBytes(final String key) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<List<byte[]>>(connectionHandler, maxRedirections) {\n            public List<byte[]> execute(Jedis connection) {\n                return connection.hvals(keyByte);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public Map<byte[], byte[]> hgetAllBytes(final String key) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<Map<byte[], byte[]>>(connectionHandler, maxRedirections) {\n            public Map<byte[], byte[]> execute(Jedis connection) {\n                return connection.hgetAll(keyByte);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public Long rpush(final String key, final byte[]... string) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n            public Long execute(Jedis connection) {\n                return connection.rpush(keyByte, string);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public Long lpush(final String key, final byte[]... string) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n            public Long execute(Jedis connection) {\n                return connection.lpush(keyByte, string);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public List<byte[]> lrangeBytes(final String key, final long start, final long end) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<List<byte[]>>(connectionHandler, maxRedirections) {\n            public List<byte[]> execute(Jedis connection) {\n                return connection.lrange(keyByte, start, end);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public byte[] lindexBytes(final String key, final long index) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<byte[]>(connectionHandler, maxRedirections) {\n            public byte[] execute(Jedis connection) {\n                return connection.lindex(keyByte, index);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public String lset(final String key, final long index, final byte[] value) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<String>(connectionHandler, maxRedirections) {\n            public String execute(Jedis connection) {\n                return connection.lset(keyByte, index, value);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public Long lrem(final String key, final long count, final byte[] value) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n            public Long execute(Jedis connection) {\n                return connection.lrem(keyByte, count, value);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public byte[] lpopBytes(final String key) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<byte[]>(connectionHandler, maxRedirections) {\n            public byte[] execute(Jedis connection) {\n                return connection.lpop(keyByte);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public byte[] rpopBytes(final String key) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<byte[]>(connectionHandler, maxRedirections) {\n            public byte[] execute(Jedis connection) {\n                return connection.rpop(keyByte);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public Long sadd(final String key, final byte[]... member) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n            public Long execute(Jedis connection) {\n                return connection.sadd(keyByte, member);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public Set<byte[]> smembersBytes(final String key) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<Set<byte[]>>(connectionHandler, maxRedirections) {\n            public Set<byte[]> execute(Jedis connection) {\n                return connection.smembers(keyByte);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public Long srem(final String key, final byte[]... member) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n            public Long execute(Jedis connection) {\n                return connection.srem(keyByte, member);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public byte[] spopBytes(final String key) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<byte[]>(connectionHandler, maxRedirections) {\n            public byte[] execute(Jedis connection) {\n                return connection.spop(keyByte);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public Boolean sismember(final String key, final byte[] member) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<Boolean>(connectionHandler, maxRedirections) {\n            public Boolean execute(Jedis connection) {\n                return connection.sismember(keyByte, member);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public byte[] srandmemberBytes(final String key) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<byte[]>(connectionHandler, maxRedirections) {\n            public byte[] execute(Jedis connection) {\n                return connection.srandmember(keyByte);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public Long zadd(final String key, final double score, final byte[] member) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n            public Long execute(Jedis connection) {\n                return connection.zadd(keyByte, score, member);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public Set<byte[]> zrangeBytes(final String key, final long start, final long end) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<Set<byte[]>>(connectionHandler, maxRedirections) {\n            public Set<byte[]> execute(Jedis connection) {\n                return connection.zrange(keyByte, start, end);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public Long zrem(final String key, final byte[]... member) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n            public Long execute(Jedis connection) {\n                return connection.zrem(keyByte, member);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public Double zincrby(final String key, final double score,\n                          final byte[] member) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<Double>(connectionHandler, maxRedirections) {\n            public Double execute(Jedis connection) {\n                return connection.zincrby(keyByte, score, member);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public Long zrank(final String key, final byte[] member) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n            public Long execute(Jedis connection) {\n                return connection.zrank(keyByte, member);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public Long zrevrank(final String key, final byte[] member) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n            public Long execute(Jedis connection) {\n                return connection.zrevrank(keyByte, member);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public Set<byte[]> zrevrangeBytes(final String key, final long start,\n                                      final long end) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<Set<byte[]>>(connectionHandler, maxRedirections) {\n            public Set<byte[]> execute(Jedis connection) {\n                return connection.zrevrange(keyByte, start, end);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public Set<Tuple> zrangeWithScoresBytes(final String key, final long start, final long end) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<Set<Tuple>>(connectionHandler, maxRedirections) {\n            @Override\n            public Set<Tuple> execute(Jedis connection) {\n                return connection.zrangeWithScores(keyByte, start, end);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public Set<Tuple> zrevrangeWithScoresBytes(final String key, final long start, final long end) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<Set<Tuple>>(connectionHandler, maxRedirections) {\n            @Override\n            public Set<Tuple> execute(Jedis connection) {\n                return connection.zrevrangeWithScores(keyByte, start, end);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public Double zscore(final String key, final byte[] member) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<Double>(connectionHandler, maxRedirections) {\n            public Double execute(Jedis connection) {\n                return connection.zscore(keyByte, member);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public List<byte[]> sortBytes(final String key) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<List<byte[]>>(connectionHandler, maxRedirections) {\n            public List<byte[]> execute(Jedis connection) {\n                return connection.sort(keyByte);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public List<byte[]> sortBytes(final String key, final SortingParams sortingParameters) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<List<byte[]>>(connectionHandler, maxRedirections) {\n\n            public List<byte[]> execute(Jedis connection) {\n                return connection.sort(keyByte, sortingParameters);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public Set<byte[]> zrangeByScoreBytes(final String key, final double min, final double max) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<Set<byte[]>>(connectionHandler, maxRedirections) {\n\n            public Set<byte[]> execute(Jedis connection) {\n                return connection.zrangeByScore(keyByte, min, max);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public Set<byte[]> zrangeByScoreBytes(final String key, final String min, final String max) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<Set<byte[]>>(connectionHandler, maxRedirections) {\n\n            public Set<byte[]> execute(Jedis connection) {\n                return connection.zrangeByScore(keyByte, SafeEncoder.encode(min), SafeEncoder.encode(max));\n            }\n        }.runBinary(keyByte);\n    }\n\n    public Set<byte[]> zrevrangeByScoreBytes(final String key, final double max, final double min) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<Set<byte[]>>(connectionHandler, maxRedirections) {\n            public Set<byte[]> execute(Jedis connection) {\n                return connection.zrevrangeByScore(SafeEncoder.encode(key), max, min);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public Set<byte[]> zrangeByScoreBytes(final String key, final double min,\n                                          final double max, final int offset, final int count) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<Set<byte[]>>(connectionHandler, maxRedirections) {\n            public Set<byte[]> execute(Jedis connection) {\n                return connection.zrangeByScore(keyByte, min, max, offset, count);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public Set<byte[]> zrevrangeByScoreBytes(final String key, final String max, final String min) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<Set<byte[]>>(connectionHandler, maxRedirections) {\n            public Set<byte[]> execute(Jedis connection) {\n                return connection.zrevrangeByScore(keyByte,\n                        SafeEncoder.encode(max), SafeEncoder.encode(min));\n            }\n        }.runBinary(keyByte);\n    }\n\n    public Set<byte[]> zrangeByScoreBytes(final String key, final String min,\n                                          final String max, final int offset, final int count) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<Set<byte[]>>(connectionHandler, maxRedirections) {\n\n            public Set<byte[]> execute(Jedis connection) {\n                return connection.zrangeByScore(keyByte,\n                        SafeEncoder.encode(min), SafeEncoder.encode(max), offset, count);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public Set<byte[]> zrevrangeByScoreBytes(final String key, final double max,\n                                             final double min, final int offset, final int count) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<Set<byte[]>>(connectionHandler, maxRedirections) {\n            public Set<byte[]> execute(Jedis connection) {\n                return connection.zrevrangeByScore(keyByte, max, min, offset, count);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public Set<byte[]> zrevrangeByScoreBytes(final String key, final String max,\n                                             final String min, final int offset, final int count) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<Set<byte[]>>(connectionHandler, maxRedirections) {\n            public Set<byte[]> execute(Jedis connection) {\n                return connection.zrevrangeByScore(keyByte,\n                        SafeEncoder.encode(max), SafeEncoder.encode(min), offset, count);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public Long linsert(final String key, final BinaryClient.LIST_POSITION where,\n                        final byte[] pivot, final byte[] value) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n            public Long execute(Jedis connection) {\n                return connection.linsert(keyByte, where, pivot, value);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public Long lpushx(final String key, final byte[]... string) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n            public Long execute(Jedis connection) {\n                return connection.lpushx(keyByte, string);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public Long rpushx(final String key, final byte[]... string) {\n        final byte[] keyByte = SafeEncoder.encode(key);\n        return new JedisClusterCommand<Long>(connectionHandler, maxRedirections) {\n            public Long execute(Jedis connection) {\n                return connection.rpushx(keyByte, string);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public List<byte[]> blpopBytes(final String arg) {\n        final byte[] keyByte = SafeEncoder.encode(arg);\n        return new JedisClusterCommand<List<byte[]>>(connectionHandler, maxRedirections) {\n            public List<byte[]> execute(Jedis connection) {\n                return connection.blpop(keyByte);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public List<byte[]> brpopBytes(final String arg) {\n        final byte[] keyByte = SafeEncoder.encode(arg);\n        return new JedisClusterCommand<List<byte[]>>(connectionHandler, maxRedirections) {\n            public List<byte[]> execute(Jedis connection) {\n                return connection.brpop(keyByte);\n            }\n        }.runBinary(keyByte);\n    }\n\n    public Map<String, String> mget(final List<String> keys) {\n        if (keys == null || keys.isEmpty()) {\n            return null;\n        }\n        return new PipelineClusterCommand<Map<String, String>>(this, connectionHandler) {\n            @Override\n            public void pipelineCommand(Pipeline pipeline, List<String> pipelineKeys) {\n                for (String key : pipelineKeys) {\n                    pipeline.get(key);\n                }\n            }\n\n            @Override\n            public Map<String, String> getResult(Map<String, Object> resultMap) {\n                Map<String, String> result = new HashMap<String, String>();\n                if (resultMap == null || resultMap.isEmpty()) {\n                    return result;\n                }\n                for (Map.Entry<String, Object> entry : resultMap.entrySet()) {\n                    String key = entry.getKey();\n                    Object object = entry.getValue();\n                    if (object == null) {\n                        continue;\n                    }\n                    if (checkException(object)) {\n                        try {\n                            String value = pipelineCluster.get(key);\n                            if (value != null) {\n                                result.put(key, value);\n                            }\n                        } catch (Exception e) {\n                            logger.error(e.getMessage(), e);\n                        }\n                    } else {\n                        result.put(key, object.toString());\n                    }\n                }\n                return result;\n            }\n        }.run(keys);\n    }\n\n    public Map<String, Long> mexpire(final Map<String, Integer> keyTimeMap) {\n        if (keyTimeMap == null || keyTimeMap.isEmpty()) {\n            return null;\n        }\n        return new PipelineClusterCommand<Map<String, Long>>(this, connectionHandler) {\n\n            @Override\n            public void pipelineCommand(Pipeline pipeline, List<String> pipelineKeys) {\n                for (String key : pipelineKeys) {\n                    Integer seconds = keyTimeMap.get(key);\n                    pipeline.expire(key, seconds);\n                }\n            }\n\n            @Override\n            public Map<String, Long> getResult(Map<String, Object> resultMap) {\n                Map<String, Long> result = new HashMap<String, Long>();\n                if (resultMap == null || resultMap.isEmpty()) {\n                    return result;\n                }\n                for (Map.Entry<String, Object> entry : resultMap.entrySet()) {\n                    String key = entry.getKey();\n                    Object object = entry.getValue();\n                    if (object == null) {\n                        continue;\n                    }\n                    if (checkException(object)) {\n                        try {\n                            String value = pipelineCluster.get(key);\n                            Integer seconds = keyTimeMap.get(key);\n                            if (value != null) {\n                                pipelineCluster.expire(key, seconds);\n                            }\n                        } catch (Exception e) {\n                            logger.error(e.getMessage(), e);\n                        }\n                    } else {\n                        result.put(key, Long.valueOf(object.toString()));\n                    }\n                }\n                return result;\n            }\n        }.run(new ArrayList<String>(keyTimeMap.keySet()));\n    }\n    \n    public Map<String,Map<String,String>> mHgetAll(List<String> keys) {\n        if (keys == null || keys.isEmpty()) {\n            return null;\n        }\n        return new PipelineClusterCommand<Map<String,Map<String,String>>>(this, connectionHandler) {\n            @Override\n            public void pipelineCommand(Pipeline pipeline, List<String> pipelineKeys) {\n                for (String key : pipelineKeys) {\n                    pipeline.hgetAll(key);\n                }\n            }\n\n            @Override\n            public Map<String,Map<String,String>> getResult(Map<String, Object> resultMap) {\n                Map<String, Map<String,String>> result = new HashMap<String, Map<String,String>>();\n                for (Map.Entry<String, Object> entry : resultMap.entrySet()) {\n                    String key = entry.getKey();\n                    Object object = entry.getValue();\n                    if (object == null) {\n                        continue;\n                    }\n                    if (checkException(object)) {\n                        try {\n                            Map<String,String> exceptionHgetAllMap = pipelineCluster.hgetAll(key);\n                            if (exceptionHgetAllMap != null && !exceptionHgetAllMap.isEmpty()) {\n                                result.put(key, exceptionHgetAllMap);\n                            }\n                        } catch (Exception e) {\n                            logger.error(e.getMessage(), e);\n                        }\n                    } else {\n                        result.put(key, (Map<String, String>) object);\n                    }\n                }\n                return result;\n            }\n        }.run(keys);\n    }\n    \n    \n    public Map<String,String> mhmset(final Map<String,Map<String,String>> keyValueMap) {\n        if (keyValueMap == null || keyValueMap.isEmpty()) {\n            return null;\n        }\n        return new PipelineClusterCommand<Map<String,String>>(this, connectionHandler) {\n            @Override\n            public void pipelineCommand(Pipeline pipeline, List<String> pipelineKeys) {\n                for (String key : pipelineKeys) {\n                    Map<String,String> map = keyValueMap.get(key);\n                    pipeline.hmset(key, map);\n                }\n            }\n\n            @Override\n            public Map<String,String> getResult(Map<String, Object> resultMap) {\n                Map<String, String> result = new HashMap<String, String>();\n                for (Map.Entry<String, Object> entry : resultMap.entrySet()) {\n                    String key = entry.getKey();\n                    Object object = entry.getValue();\n                    if (object == null) {\n                        continue;\n                    }\n                    if (checkException(object)) {\n                        try {\n                            Map<String, String> value = keyValueMap.get(key);\n                            if (value != null) {\n                                String hmsetResult = pipelineCluster.hmset(key, value);\n                                result.put(key, hmsetResult);\n                            }\n                        } catch (Exception e) {\n                            logger.error(e.getMessage(), e);\n                        }\n                    }\n                }\n                return result;\n            }\n        }.run(new ArrayList<String>(keyValueMap.keySet()));\n    }\n\n    public String mset(final Map<String, String> keyValueMap) {\n        if (keyValueMap == null || keyValueMap.isEmpty()) {\n            return null;\n        }\n        return new PipelineClusterCommand<String>(this, connectionHandler) {\n            @Override\n            public void pipelineCommand(Pipeline pipeline, List<String> pipelineKeys) {\n                for (String key : pipelineKeys) {\n                    String value = keyValueMap.get(key);\n                    pipeline.set(key, value);\n                }\n            }\n\n            @Override\n            public String getResult(Map<String, Object> resultMap) {\n                String result = \"OK\";\n                if (resultMap == null || resultMap.isEmpty()) {\n                    result = \"FAIL\";\n                }\n                for (Map.Entry<String, Object> entry : resultMap.entrySet()) {\n                    String key = entry.getKey();\n                    Object object = entry.getValue();\n                    if (object == null) {\n                        continue;\n                    }\n                    if (checkException(object)) {\n                        try {\n                            String value = keyValueMap.get(key);\n                            if (value != null) {\n                                pipelineCluster.set(key, value);\n                            }\n                        } catch (Exception e) {\n                            logger.error(e.getMessage(), e);\n                        }\n                    }\n                }\n                return result;\n            }\n        }.run(new ArrayList<String>(keyValueMap.keySet()));\n    }\n\n    public Long mdel(final List<String> keys) {\n        if (keys == null || keys.isEmpty()) {\n            return null;\n        }\n        return new PipelineClusterCommand<Long>(this, connectionHandler) {\n            @Override\n            public void pipelineCommand(Pipeline pipeline, List<String> pipelineKeys) {\n                for (String key : pipelineKeys) {\n                    pipeline.del(key);\n                }\n            }\n\n            @Override\n            public Long getResult(Map<String, Object> resultMap) {\n                Long result = 0L;\n                if (resultMap == null || resultMap.isEmpty()) {\n                    return result;\n                }\n                for (Map.Entry<String, Object> entry : resultMap.entrySet()) {\n                    String key = entry.getKey();\n                    Object object = entry.getValue();\n                    if (object == null) {\n                        continue;\n                    }\n                    if (checkException(object)) {\n                        try {\n                            Long value = pipelineCluster.del(key);\n                            if (value != null) {\n                                result++;\n                            }\n                        } catch (Exception e) {\n                            logger.error(e.getMessage(), e);\n                        }\n                    } else {\n                        result++;\n                    }\n                }\n                return result;\n            }\n        }.run(keys);\n    }\n\n    public Map<String, Long> mzadd(final Map<String, SortedSetVO> map) {\n        if (map == null || map.isEmpty()) {\n            return null;\n        }\n        return new PipelineClusterCommand<Map<String, Long>>(this, connectionHandler) {\n\n            @Override\n            public void pipelineCommand(Pipeline pipeline, List<String> pipelineKeys) {\n                for (String key : pipelineKeys) {\n                    SortedSetVO vo = map.get(key);\n                    if (vo.getMemberStr() != null) {\n                        pipeline.zadd(key, vo.getScore(), vo.getMemberStr());\n                    } else {\n                        pipeline.zadd(SafeEncoder.encode(key), vo.getScore(), vo.getBytesBytes());\n                    }\n                }\n            }\n\n            @Override\n            public Map<String, Long> getResult(Map<String, Object> resultMap) {\n                Map<String, Long> result = new HashMap<String, Long>();\n                if (resultMap == null || resultMap.isEmpty()) {\n                    return result;\n                }\n                for (Map.Entry<String, Object> entry : resultMap.entrySet()) {\n                    String key = entry.getKey();\n                    Object object = entry.getValue();\n                    if (object == null) {\n                        continue;\n                    }\n                    if (checkException(object)) {\n                        try {\n                            SortedSetVO vo = map.get(key);\n                            Long value;\n                            if (vo.getMemberStr() != null) {\n                                value = pipelineCluster.zadd(key, vo.getScore(), vo.getMemberStr());\n                            } else {\n                                value = pipelineCluster\n                                        .zadd(SafeEncoder.encode(key), vo.getScore(), vo.getBytesBytes());\n                            }\n                            result.put(key, value);\n                        } catch (Exception e) {\n                            logger.error(e.getMessage(), e);\n                        }\n                    } else {\n                        result.put(key, Long.parseLong(object.toString()));\n                    }\n                }\n                return result;\n            }\n        }.run(new ArrayList<String>(map.keySet()));\n    }\n\n    public Map<String, Long> mzadds(final Map<String, Map<String, Double>> map) {\n        if (map == null || map.isEmpty()) {\n            return null;\n        }\n        return new PipelineClusterCommand<Map<String, Long>>(this, connectionHandler) {\n\n            @Override\n            public void pipelineCommand(Pipeline pipeline, List<String> pipelineKeys) {\n                for (String key : pipelineKeys) {\n                    Map<String, Double> scoreMemberMap = map.get(key);\n                    pipeline.zadd(key, scoreMemberMap);\n                }\n            }\n\n            @Override\n            public Map<String, Long> getResult(Map<String, Object> resultMap) {\n                Map<String, Long> result = new HashMap<String, Long>();\n                if (resultMap == null || resultMap.isEmpty()) {\n                    return result;\n                }\n                for (Map.Entry<String, Object> entry : resultMap.entrySet()) {\n                    String key = entry.getKey();\n                    Object object = entry.getValue();\n                    if (object == null) {\n                        continue;\n                    }\n                    if (checkException(object)) {\n                        try {\n                            Map<String, Double> voMap = map.get(key);\n                            Long value = pipelineCluster.zadd(key, voMap);\n                            result.put(key, value);\n                        } catch (Exception e) {\n                            logger.error(e.getMessage(), e);\n                        }\n                    } else {\n                        result.put(key, Long.parseLong(object.toString()));\n                    }\n                }\n                return result;\n            }\n        }.run(new ArrayList<String>(map.keySet()));\n    }\n\n    public Map<String, Set<String>> mzrangeByScore(final List<String> keys, final double min,\n                                                   final double max) {\n        return new PipelineClusterCommand<Map<String, Set<String>>>(this, connectionHandler) {\n\n            @Override\n            public void pipelineCommand(Pipeline pipeline, List<String> pipelineKeys) {\n                for (String key : pipelineKeys) {\n                    pipeline.zrangeByScore(key, min, max);\n                }\n            }\n\n            @Override\n            public Map<String, Set<String>> getResult(Map<String, Object> resultMap) {\n                Map<String, Set<String>> result = new HashMap<String, Set<String>>();\n                if (resultMap == null || resultMap.isEmpty()) {\n                    return result;\n                }\n                for (Map.Entry<String, Object> entry : resultMap.entrySet()) {\n                    String key = entry.getKey();\n                    Object object = entry.getValue();\n                    if (object == null) {\n                        continue;\n                    }\n                    if (checkException(object)) {\n                        try {\n                            Set<String> value = pipelineCluster.zrangeByScore(key, min, max);\n                            result.put(key, value);\n                        } catch (Exception e) {\n                            logger.error(e.getMessage(), e);\n                        }\n                    } else {\n                        result.put(key, (Set<String>) object);\n                    }\n                }\n                return result;\n            }\n        }.run(keys);\n    }\n\n    public Map<String, Set<String>> mzrangeByScore(final Map<String, RangeScoreVO> keyScoreMap) {\n        return new PipelineClusterCommand<Map<String, Set<String>>>(this, connectionHandler) {\n\n            @Override\n            public void pipelineCommand(Pipeline pipeline, List<String> pipelineKeys) {\n                for (String key : pipelineKeys) {\n                    RangeScoreVO vo = keyScoreMap.get(key);\n                    pipeline.zrangeByScore(key, vo.getMin(), vo.getMax());\n                }\n\n            }\n\n            @Override\n            public Map<String, Set<String>> getResult(Map<String, Object> resultMap) {\n                Map<String, Set<String>> result = new HashMap<String, Set<String>>();\n                if (resultMap == null || resultMap.isEmpty()) {\n                    return result;\n                }\n                for (Map.Entry<String, Object> entry : resultMap.entrySet()) {\n                    String key = entry.getKey();\n                    Object object = entry.getValue();\n                    if (object == null) {\n                        continue;\n                    }\n                    if (checkException(object)) {\n                        try {\n                            RangeScoreVO vo = keyScoreMap.get(key);\n                            Set<String> value = pipelineCluster.zrangeByScore(key, vo.getMin(), vo.getMax());\n                            result.put(key, value);\n                        } catch (Exception e) {\n                            logger.error(e.getMessage(), e);\n                        }\n                    } else {\n                        result.put(key, (Set<String>) object);\n                    }\n                }\n                return result;\n            }\n        }.run(new ArrayList<String>(keyScoreMap.keySet()));\n    }\n\n    public Map<String, Set<String>> mzrangeByScore(final List<String> keys, final String min,\n                                                   final String max) {\n        return new PipelineClusterCommand<Map<String, Set<String>>>(this, connectionHandler) {\n\n            @Override\n            public void pipelineCommand(Pipeline pipeline, List<String> pipelineKeys) {\n                for (String key : pipelineKeys) {\n                    pipeline.zrangeByScore(key, min, max);\n                }\n            }\n\n            @Override\n            public Map<String, Set<String>> getResult(Map<String, Object> resultMap) {\n                Map<String, Set<String>> result = new HashMap<String, Set<String>>();\n                if (resultMap == null || resultMap.isEmpty()) {\n                    return result;\n                }\n                for (Map.Entry<String, Object> entry : resultMap.entrySet()) {\n                    String key = entry.getKey();\n                    Object object = entry.getValue();\n                    if (object == null) {\n                        continue;\n                    }\n                    if (checkException(object)) {\n                        try {\n                            Set<String> value = pipelineCluster.zrangeByScore(key, min, max);\n                            result.put(key, value);\n                        } catch (Exception e) {\n                            logger.error(e.getMessage(), e);\n                        }\n                    } else {\n                        result.put(key, (Set<String>) object);\n                    }\n                }\n                return result;\n            }\n\n        }.run(keys);\n    }\n\n    public String mzremrangeByScore(final Map<String, RangeScoreVO> keyScoreMap) {\n        return new PipelineClusterCommand<String>(this, connectionHandler) {\n\n            @Override\n            public void pipelineCommand(Pipeline pipeline, List<String> pipelineKeys) {\n                for (String key : pipelineKeys) {\n                    RangeScoreVO vo = keyScoreMap.get(key);\n                    pipeline.zremrangeByScore(key, vo.getMin(), vo.getMax());\n                }\n            }\n\n            @Override\n            public String getResult(Map<String, Object> resultMap) {\n                String result = \"OK\";\n                if (resultMap == null || resultMap.isEmpty()) {\n                    result = \"FAIL\";\n                }\n                for (Map.Entry<String, Object> entry : resultMap.entrySet()) {\n                    String key = entry.getKey();\n                    Object object = entry.getValue();\n                    if (object == null) {\n                        continue;\n                    }\n                    if (checkException(object)) {\n                        try {\n                            RangeScoreVO vo = keyScoreMap.get(key);\n                            if (vo != null) {\n                                pipelineCluster.zremrangeByScore(key, vo.getMin(), vo.getMax());\n                            }\n                        } catch (Exception e) {\n                            logger.error(e.getMessage(), e);\n                        }\n                    }\n                }\n                return result;\n            }\n        }.run(new ArrayList<String>(keyScoreMap.keySet()));\n    }\n\n    public Map<String, byte[]> mgetBytes(final List<String> keys) {\n        if (keys == null || keys.isEmpty()) {\n            return null;\n        }\n        return new PipelineClusterCommand<Map<String, byte[]>>(this, connectionHandler) {\n\n            @Override\n            public void pipelineCommand(Pipeline pipeline, List<String> pipelineKeys) {\n                for (String key : pipelineKeys) {\n                    pipeline.get(SafeEncoder.encode(key));\n                }\n            }\n\n            @Override\n            public Map<String, byte[]> getResult(Map<String, Object> resultMap) {\n                Map<String, byte[]> result = new HashMap<String, byte[]>();\n                if (resultMap == null || resultMap.isEmpty()) {\n                    return result;\n                }\n                for (Map.Entry<String, Object> entry : resultMap.entrySet()) {\n                    String key = entry.getKey();\n                    Object object = entry.getValue();\n                    if (object == null) {\n                        continue;\n                    }\n                    if (checkException(object)) {\n                        try {\n                            byte[] value = pipelineCluster.getBytes(key);\n                            if (value != null) {\n                                result.put(key, value);\n                            }\n                        } catch (Exception e) {\n                            logger.error(e.getMessage(), e);\n                        }\n                    } else {\n                        result.put(key, (byte[]) object);\n                    }\n                }\n                return result;\n            }\n        }.run(keys);\n    }\n\n    public String msetBytes(final Map<String, byte[]> keyValueMap) {\n        if (keyValueMap == null || keyValueMap.isEmpty()) {\n            return null;\n        }\n        return new PipelineClusterCommand<String>(this, connectionHandler) {\n\n            @Override\n            public void pipelineCommand(Pipeline pipeline, List<String> pipelineKeys) {\n                for (String key : pipelineKeys) {\n                    byte[] value = keyValueMap.get(key);\n                    pipeline.set(SafeEncoder.encode(key), value);\n                }\n            }\n\n            @Override\n            public String getResult(Map<String, Object> resultMap) {\n                String result = \"OK\";\n                if (resultMap == null || resultMap.isEmpty()) {\n                    result = \"FAIL\";\n                }\n                for (Map.Entry<String, Object> entry : resultMap.entrySet()) {\n                    String key = entry.getKey();\n                    Object object = entry.getValue();\n                    if (object == null) {\n                        continue;\n                    }\n                    if (checkException(object)) {\n                        try {\n                            byte[] value = keyValueMap.get(key);\n                            if (value != null) {\n                                pipelineCluster.set(SafeEncoder.encode(key), value);\n                            }\n                        } catch (Exception e) {\n                            logger.error(e.getMessage(), e);\n                        }\n                    }\n                }\n                return result;\n            }\n        }.run(new ArrayList<String>(keyValueMap.keySet()));\n    }\n\n    /**\n     * @param channel\n     * @param message\n     * @return\n     */\n    public Long publish(final String channel, final String message) {\n        SubPubClusterCommand subPubClusterCommand = new SubPubClusterCommand(this, connectionHandler, maxRedirections);\n        Jedis jedis = subPubClusterCommand.getJedis(channel);\n        try {\n            return jedis.publish(channel, message);\n        } finally {\n            subPubClusterCommand.releaseConnection(jedis);\n        }\n    }\n\n    /**\n     * @param channel\n     * @param message\n     * @return\n     */\n    public Long publish(final String channel, final byte[] message) {\n        SubPubClusterCommand subPubClusterCommand = new SubPubClusterCommand(this, connectionHandler, maxRedirections);\n        Jedis jedis = subPubClusterCommand.getJedis(channel);\n        try {\n            return jedis.publish(SafeEncoder.encode(channel), message);\n        } finally {\n            subPubClusterCommand.releaseConnection(jedis);\n        }\n    }\n\n    /**\n     * 订阅单一频道(阻塞操作)\n     *\n     * @param jedisPubSub\n     * @param channel\n     */\n    public void subscribe(final JedisPubSub jedisPubSub, final String channel, final int timeout) {\n        SubPubClusterCommand subPubClusterCommand = new SubPubClusterCommand(this, connectionHandler, maxRedirections);\n        Jedis jedis = subPubClusterCommand.getNewJedis(channel, timeout);\n        try {\n            jedis.subscribe(jedisPubSub, channel);\n        } finally {\n            if (jedis != null) {\n                jedis.close();\n            }\n        }\n    }\n\n    /**\n     * 按校验和执行脚本\n     *\n     * @param sha\n     * @param key\n     * @param args\n     * @return\n     */\n    public Object evalsha(String sha, String key, String... args) {\n        SubPubClusterCommand subPubClusterCommand = new SubPubClusterCommand(this, connectionHandler, maxRedirections);\n        Jedis jedis = subPubClusterCommand.getJedis(key);\n        try {\n            return jedis.evalsha(sha, 1, getKeys(key, args));\n        } finally {\n            if (jedis != null) {\n                jedis.close();\n            }\n        }\n    }\n\n    private String[] getKeys(String key, String... args) {\n        List<String> list = new ArrayList<String>();\n        list.add(key);\n        if (args != null && args.length > 0) {\n            for (String arg : args) {\n                list.add(arg);\n            }\n            return list.toArray(new String[0]);\n        } else {\n            return new String[]{key};\n        }\n    }\n\n    /**\n     * 按校验和执行脚本\n     *\n     * @param sha\n     * @param key\n     * @return\n     */\n    public Object evalsha(String sha, String key) {\n        return evalsha(sha, key, null);\n    }\n\n    /**\n     * 按内容执行脚本\n     *\n     * @param sha\n     * @param key\n     * @param args\n     * @return\n     */\n    public Object eval(String sha, String key, String... args) {\n        SubPubClusterCommand subPubClusterCommand = new SubPubClusterCommand(this, connectionHandler, maxRedirections);\n        Jedis jedis = subPubClusterCommand.getJedis(key);\n\n        try {\n            return jedis.eval(sha, 1, getKeys(key, args));\n        } finally {\n            if (jedis != null) {\n                jedis.close();\n            }\n        }\n    }\n\n    /**\n     * 按内容执行脚本\n     *\n     * @param sha\n     * @param key\n     * @return\n     */\n    public Object eval(String sha, String key) {\n        return eval(sha, key, null);\n    }\n\n    /**\n     * 将脚本script添加到集群所有节点缓存中\n     *\n     * @param script\n     * @return\n     */\n    public String loadScruptAllNodes(String script) {\n        Map<String, JedisPool> nodeMap = getClusterNodes();\n        String md5 = null;\n        for (JedisPool jedisPool : nodeMap.values()) {\n            Jedis jedis = null;\n            try {\n                jedis = jedisPool.getResource();\n                String returnMd5 = jedis.scriptLoad(script);\n                if (returnMd5 != null) {\n                    md5 = returnMd5;\n                }\n            } finally {\n                if (jedis != null) {\n                    jedis.close();\n                }\n            }\n        }\n        return md5;\n    }\n\n    public ScanResult<String> sscan(final String key, final String cursor, final ScanParams params) {\n        return new JedisClusterCommand<ScanResult<String>>(connectionHandler, maxRedirections) {\n            @Override\n            public ScanResult<String> execute(Jedis connection) {\n                return connection.sscan(key, cursor, params);\n            }\n        }.run(key);\n    }\n\n    public ScanResult<byte[]> sscan(final byte[] key, final byte[] cursor, final ScanParams params) {\n        return new JedisClusterCommand<ScanResult<byte[]>>(connectionHandler, maxRedirections) {\n            @Override\n            public ScanResult<byte[]> execute(Jedis connection) {\n                return connection.sscan(key, cursor, params);\n            }\n        }.runBinary(key);\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/PipelineClusterCommand.java",
    "content": "package redis.clients.jedis;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport redis.clients.jedis.exceptions.JedisConnectionException;\nimport redis.clients.jedis.exceptions.JedisMovedDataException;\nimport redis.clients.jedis.exceptions.JedisRedirectionException;\nimport redis.clients.util.JedisClusterCRC16;\n\nimport java.util.*;\n\n/**\n * Created by yijunzhang on 14-5-26.\n */\npublic abstract class PipelineClusterCommand<T> {\n    private final Logger logger = LoggerFactory.getLogger(this.getClass());\n\n    private JedisClusterConnectionHandler connectionHandler;\n\n    protected final PipelineCluster pipelineCluster;\n\n    public PipelineClusterCommand(PipelineCluster pipelineCluster, JedisClusterConnectionHandler connectionHandler) {\n        this.pipelineCluster = pipelineCluster;\n        this.connectionHandler = connectionHandler;\n    }\n\n    /**\n     * 执行批处理命令\n     *\n     * @param pipeline\n     */\n    public abstract void pipelineCommand(Pipeline pipeline, List<String> pipelineKeys);\n\n    public abstract T getResult(Map<String, Object> resultMap);\n\n    public T run(List<String> keys) {\n        if (keys == null || keys.isEmpty()) {\n            return null;\n        }\n        Map<JedisPool, List<String>> poolKeysMap = getPoolKeyMap(keys);\n        Map<String, Object> resultMap = new HashMap<String, Object>();\n        for (Map.Entry<JedisPool, List<String>> entry : poolKeysMap.entrySet()) {\n            JedisPool jedisPool = entry.getKey();\n            List<String> subkeys = entry.getValue();\n            if (subkeys == null || subkeys.isEmpty()) {\n                continue;\n            }\n            //申请jedis对象\n            Jedis jedis = null;\n            Pipeline pipeline = null;\n            List<Object> subResultList = null;\n            try {\n                jedis = jedisPool.getResource();\n                pipeline = jedis.pipelined();\n                pipelineCommand(pipeline, subkeys);\n                subResultList = pipeline.syncAndReturnAll();\n            } catch (JedisConnectionException e) {\n                logger.error(\"RedisConnectionError-{}:{} keys={}\", jedisPool.getHost(), jedisPool.getPort(), subkeys);\n                logger.error(e.getMessage(), e);\n            } catch (Exception e) {\n                logger.error(e.getMessage(), e);\n            } finally {\n                if (pipeline != null)\n                    pipeline.clean();\n                //释放jedis对象\n                if (jedis != null) {\n                    jedis.close();\n                }\n            }\n            if (subResultList == null || subResultList.isEmpty()) {\n                continue;\n            }\n            if (subResultList.size() == subkeys.size()) {\n                for (int i = 0; i < subkeys.size(); i++) {\n                    String key = subkeys.get(i);\n                    Object result = subResultList.get(i);\n                    resultMap.put(key, result);\n                }\n            } else {\n                logger.error(\"PipelineClusterCommand:subkeys={} subResultList={}\", subkeys, subResultList);\n            }\n        }\n        return getResult(resultMap);\n    }\n\n    private Map<JedisPool, List<String>> getPoolKeyMap(List<String> keys) {\n        Map<JedisPool, List<String>> poolKeysMap = new LinkedHashMap<JedisPool, List<String>>();\n        try {\n            for (String key : keys) {\n                JedisPool jedisPool;\n                int slot = JedisClusterCRC16.getSlot(key);\n                jedisPool = connectionHandler.getJedisPoolFromSlot(slot);\n                if (poolKeysMap.containsKey(jedisPool)) {\n                    poolKeysMap.get(jedisPool).add(key);\n                } else {\n                    List<String> subKeyList = new ArrayList<String>();\n                    subKeyList.add(key);\n                    poolKeysMap.put(jedisPool, subKeyList);\n                }\n            }\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n        return poolKeysMap;\n    }\n\n    protected boolean checkException(Object obj) {\n        if (obj instanceof Exception) {\n            Exception e = (Exception) obj;\n            if (e instanceof JedisRedirectionException) {\n                //重定向slot 映射.\n                if (e instanceof JedisMovedDataException) {\n                    // it rebuilds cluster's slot cache\n                    // recommended by Redis cluster specification\n                    this.connectionHandler.renewSlotCache();\n                    logger.warn(\"JedisMovedDataException:\" + e.getMessage(), e);\n                } else {\n                    logger.error(\"pipeline-error:\" + e.getMessage(), e);\n                }\n            } else {\n                logger.error(e.getMessage(), e);\n            }\n            return true;\n        }\n        return false;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/Protocol.java",
    "content": "package redis.clients.jedis;\n\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport redis.clients.jedis.commands.ProtocolCommand;\nimport redis.clients.jedis.exceptions.JedisAskDataException;\nimport redis.clients.jedis.exceptions.JedisClusterException;\nimport redis.clients.jedis.exceptions.JedisConnectionException;\nimport redis.clients.jedis.exceptions.JedisDataException;\nimport redis.clients.jedis.exceptions.JedisMovedDataException;\nimport redis.clients.util.RedisInputStream;\nimport redis.clients.util.RedisOutputStream;\nimport redis.clients.util.SafeEncoder;\n\npublic final class Protocol {\n\n  private static final String ASK_RESPONSE = \"ASK\";\n  private static final String MOVED_RESPONSE = \"MOVED\";\n  private static final String CLUSTERDOWN_RESPONSE = \"CLUSTERDOWN\";\n  public static final String DEFAULT_HOST = \"localhost\";\n  public static final int DEFAULT_PORT = 6379;\n  public static final int DEFAULT_SENTINEL_PORT = 26379;\n  public static final int DEFAULT_TIMEOUT = 2000;\n  public static final int DEFAULT_DATABASE = 0;\n\n  public static final String CHARSET = \"UTF-8\";\n\n  public static final byte DOLLAR_BYTE = '$';\n  public static final byte ASTERISK_BYTE = '*';\n  public static final byte PLUS_BYTE = '+';\n  public static final byte MINUS_BYTE = '-';\n  public static final byte COLON_BYTE = ':';\n\n  public static final String SENTINEL_MASTERS = \"masters\";\n  public static final String SENTINEL_GET_MASTER_ADDR_BY_NAME = \"get-master-addr-by-name\";\n  public static final String SENTINEL_RESET = \"reset\";\n  public static final String SENTINEL_SLAVES = \"slaves\";\n  public static final String SENTINEL_FAILOVER = \"failover\";\n  public static final String SENTINEL_MONITOR = \"monitor\";\n  public static final String SENTINEL_REMOVE = \"remove\";\n  public static final String SENTINEL_SET = \"set\";\n\n  public static final String CLUSTER_NODES = \"nodes\";\n  public static final String CLUSTER_MEET = \"meet\";\n  public static final String CLUSTER_RESET = \"reset\";\n  public static final String CLUSTER_ADDSLOTS = \"addslots\";\n  public static final String CLUSTER_DELSLOTS = \"delslots\";\n  public static final String CLUSTER_INFO = \"info\";\n  public static final String CLUSTER_GETKEYSINSLOT = \"getkeysinslot\";\n  public static final String CLUSTER_SETSLOT = \"setslot\";\n  public static final String CLUSTER_SETSLOT_NODE = \"node\";\n  public static final String CLUSTER_SETSLOT_MIGRATING = \"migrating\";\n  public static final String CLUSTER_SETSLOT_IMPORTING = \"importing\";\n  public static final String CLUSTER_SETSLOT_STABLE = \"stable\";\n  public static final String CLUSTER_FORGET = \"forget\";\n  public static final String CLUSTER_FLUSHSLOT = \"flushslots\";\n  public static final String CLUSTER_KEYSLOT = \"keyslot\";\n  public static final String CLUSTER_COUNTKEYINSLOT = \"countkeysinslot\";\n  public static final String CLUSTER_SAVECONFIG = \"saveconfig\";\n  public static final String CLUSTER_REPLICATE = \"replicate\";\n  public static final String CLUSTER_SLAVES = \"slaves\";\n  public static final String CLUSTER_FAILOVER = \"failover\";\n  public static final String CLUSTER_SLOTS = \"slots\";\n  public static final String PUBSUB_CHANNELS = \"channels\";\n  public static final String PUBSUB_NUMSUB = \"numsub\";\n  public static final String PUBSUB_NUM_PAT = \"numpat\";\n\n  public static final byte[] BYTES_TRUE = toByteArray(1);\n  public static final byte[] BYTES_FALSE = toByteArray(0);\n\n  private Protocol() {\n    // this prevent the class from instantiation\n  }\n\n  public static void sendCommand(final RedisOutputStream os, final ProtocolCommand command,\n      final byte[]... args) {\n    sendCommand(os, command.getRaw(), args);\n  }\n\n  private static void sendCommand(final RedisOutputStream os, final byte[] command,\n      final byte[]... args) {\n    try {\n      os.write(ASTERISK_BYTE);\n      os.writeIntCrLf(args.length + 1);\n      os.write(DOLLAR_BYTE);\n      os.writeIntCrLf(command.length);\n      os.write(command);\n      os.writeCrLf();\n\n      for (final byte[] arg : args) {\n        os.write(DOLLAR_BYTE);\n        os.writeIntCrLf(arg.length);\n        os.write(arg);\n        os.writeCrLf();\n      }\n    } catch (IOException e) {\n      throw new JedisConnectionException(e);\n    }\n  }\n\n  private static void processError(final RedisInputStream is) {\n    String message = is.readLine();\n    // TODO: I'm not sure if this is the best way to do this.\n    // Maybe Read only first 5 bytes instead?\n    if (message.startsWith(MOVED_RESPONSE)) {\n      String[] movedInfo = parseTargetHostAndSlot(message);\n      throw new JedisMovedDataException(message, new HostAndPort(movedInfo[1],\n          Integer.valueOf(movedInfo[2])), Integer.valueOf(movedInfo[0]));\n    } else if (message.startsWith(ASK_RESPONSE)) {\n      String[] askInfo = parseTargetHostAndSlot(message);\n      throw new JedisAskDataException(message, new HostAndPort(askInfo[1],\n          Integer.valueOf(askInfo[2])), Integer.valueOf(askInfo[0]));\n    } else if (message.startsWith(CLUSTERDOWN_RESPONSE)) {\n      throw new JedisClusterException(message);\n    }\n    throw new JedisDataException(message);\n  }\n\n  public static String readErrorLineIfPossible(RedisInputStream is) {\n    final byte b = is.readByte();\n    // if buffer contains other type of response, just ignore.\n    if (b != MINUS_BYTE) {\n      return null;\n    }\n    return is.readLine();\n  }\n\n  private static String[] parseTargetHostAndSlot(String clusterRedirectResponse) {\n    String[] response = new String[3];\n    String[] messageInfo = clusterRedirectResponse.split(\" \");\n    String[] targetHostAndPort = messageInfo[2].split(\":\");\n    response[0] = messageInfo[1];\n    response[1] = targetHostAndPort[0];\n    response[2] = targetHostAndPort[1];\n    return response;\n  }\n\n  private static Object process(final RedisInputStream is) {\n\n    final byte b = is.readByte();\n    if (b == PLUS_BYTE) {\n      return processStatusCodeReply(is);\n    } else if (b == DOLLAR_BYTE) {\n      return processBulkReply(is);\n    } else if (b == ASTERISK_BYTE) {\n      return processMultiBulkReply(is);\n    } else if (b == COLON_BYTE) {\n      return processInteger(is);\n    } else if (b == MINUS_BYTE) {\n      processError(is);\n      return null;\n    } else {\n      throw new JedisConnectionException(\"Unknown reply: \" + (char) b);\n    }\n  }\n\n  private static byte[] processStatusCodeReply(final RedisInputStream is) {\n    return is.readLineBytes();\n  }\n\n  private static byte[] processBulkReply(final RedisInputStream is) {\n    final int len = is.readIntCrLf();\n    if (len == -1) {\n      return null;\n    }\n\n    final byte[] read = new byte[len];\n    int offset = 0;\n    while (offset < len) {\n      final int size = is.read(read, offset, (len - offset));\n      if (size == -1) throw new JedisConnectionException(\n          \"It seems like server has closed the connection.\");\n      offset += size;\n    }\n\n    // read 2 more bytes for the command delimiter\n    is.readByte();\n    is.readByte();\n\n    return read;\n  }\n\n  private static Long processInteger(final RedisInputStream is) {\n    return is.readLongCrLf();\n  }\n\n  private static List<Object> processMultiBulkReply(final RedisInputStream is) {\n    final int num = is.readIntCrLf();\n    if (num == -1) {\n      return null;\n    }\n    final List<Object> ret = new ArrayList<Object>(num);\n    for (int i = 0; i < num; i++) {\n      try {\n        ret.add(process(is));\n      } catch (JedisDataException e) {\n        ret.add(e);\n      }\n    }\n    return ret;\n  }\n\n  public static Object read(final RedisInputStream is) {\n    return process(is);\n  }\n\n  public static final byte[] toByteArray(final boolean value) {\n    return value ? BYTES_TRUE : BYTES_FALSE;\n  }\n\n  public static final byte[] toByteArray(final int value) {\n    return SafeEncoder.encode(String.valueOf(value));\n  }\n\n  public static final byte[] toByteArray(final long value) {\n    return SafeEncoder.encode(String.valueOf(value));\n  }\n\n  public static final byte[] toByteArray(final double value) {\n    return SafeEncoder.encode(String.valueOf(value));\n  }\n\n  public static enum Command implements ProtocolCommand {\n    PING, SET, GET, QUIT, EXISTS, DEL, TYPE, FLUSHDB, KEYS, RANDOMKEY, RENAME, RENAMENX, RENAMEX, DBSIZE, EXPIRE, EXPIREAT, TTL, SELECT, MOVE, FLUSHALL, GETSET, MGET, SETNX, SETEX, MSET, MSETNX, DECRBY, DECR, INCRBY, INCR, APPEND, SUBSTR, HSET, HGET, HSETNX, HMSET, HMGET, HINCRBY, HEXISTS, HDEL, HLEN, HKEYS, HVALS, HGETALL, RPUSH, LPUSH, LLEN, LRANGE, LTRIM, LINDEX, LSET, LREM, LPOP, RPOP, RPOPLPUSH, SADD, SMEMBERS, SREM, SPOP, SMOVE, SCARD, SISMEMBER, SINTER, SINTERSTORE, SUNION, SUNIONSTORE, SDIFF, SDIFFSTORE, SRANDMEMBER, ZADD, ZRANGE, ZREM, ZINCRBY, ZRANK, ZREVRANK, ZREVRANGE, ZCARD, ZSCORE, MULTI, DISCARD, EXEC, WATCH, UNWATCH, SORT, BLPOP, BRPOP, AUTH, SUBSCRIBE, PUBLISH, UNSUBSCRIBE, PSUBSCRIBE, PUNSUBSCRIBE, PUBSUB, ZCOUNT, ZRANGEBYSCORE, ZREVRANGEBYSCORE, ZREMRANGEBYRANK, ZREMRANGEBYSCORE, ZUNIONSTORE, ZINTERSTORE, ZLEXCOUNT, ZRANGEBYLEX, ZREVRANGEBYLEX, ZREMRANGEBYLEX, SAVE, BGSAVE, BGREWRITEAOF, LASTSAVE, SHUTDOWN, INFO, MONITOR, SLAVEOF, CONFIG, STRLEN, SYNC, LPUSHX, PERSIST, RPUSHX, ECHO, LINSERT, DEBUG, BRPOPLPUSH, SETBIT, GETBIT, BITPOS, SETRANGE, GETRANGE, EVAL, EVALSHA, SCRIPT, SLOWLOG, OBJECT, BITCOUNT, BITOP, SENTINEL, DUMP, RESTORE, PEXPIRE, PEXPIREAT, PTTL, INCRBYFLOAT, PSETEX, CLIENT, TIME, MIGRATE, HINCRBYFLOAT, SCAN, HSCAN, SSCAN, ZSCAN, WAIT, CLUSTER, ASKING, PFADD, PFCOUNT, PFMERGE, READONLY, GEOADD, GEODIST, GEOHASH, GEOPOS, GEORADIUS, GEORADIUSBYMEMBER;\n\n    private final byte[] raw;\n\n    Command() {\n      raw = SafeEncoder.encode(this.name());\n    }\n\n    @Override\n    public byte[] getRaw() {\n      return raw;\n    }\n  }\n\n  public static enum Keyword {\n    AGGREGATE, ALPHA, ASC, BY, DESC, GET, LIMIT, MESSAGE, NO, NOSORT, PMESSAGE, PSUBSCRIBE, PUNSUBSCRIBE, OK, ONE, QUEUED, SET, STORE, SUBSCRIBE, UNSUBSCRIBE, WEIGHTS, WITHSCORES, RESETSTAT, RESET, FLUSH, EXISTS, LOAD, KILL, LEN, REFCOUNT, ENCODING, IDLETIME, AND, OR, XOR, NOT, GETNAME, SETNAME, LIST, MATCH, COUNT;\n    public final byte[] raw;\n\n    Keyword() {\n      raw = SafeEncoder.encode(this.name().toLowerCase());\n    }\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/Queable.java",
    "content": "package redis.clients.jedis;\n\nimport java.util.LinkedList;\nimport java.util.Queue;\n\npublic class Queable {\n  private Queue<Response<?>> pipelinedResponses = new LinkedList<Response<?>>();\n\n  protected void clean() {\n    pipelinedResponses.clear();\n  }\n\n  protected Response<?> generateResponse(Object data) {\n    Response<?> response = pipelinedResponses.poll();\n    if (response != null) {\n      response.set(data);\n    }\n    return response;\n  }\n\n  protected <T> Response<T> getResponse(Builder<T> builder) {\n    Response<T> lr = new Response<T>(builder);\n    pipelinedResponses.add(lr);\n    return lr;\n  }\n\n  protected boolean hasPipelinedResponse() {\n    return pipelinedResponses.size() > 0;\n  }\n\n  protected int getPipelinedResponseLength() {\n    return pipelinedResponses.size();\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/RedisPipeline.java",
    "content": "package redis.clients.jedis;\n\nimport redis.clients.jedis.params.sortedset.ZAddParams;\nimport redis.clients.jedis.params.sortedset.ZIncrByParams;\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\npublic interface RedisPipeline {\n  Response<Long> append(String key, String value);\n\n  Response<List<String>> blpop(String arg);\n\n  Response<List<String>> brpop(String arg);\n\n  Response<Long> decr(String key);\n\n  Response<Long> decrBy(String key, long integer);\n\n  Response<Long> del(String key);\n\n  Response<String> echo(String string);\n\n  Response<Boolean> exists(String key);\n\n  Response<Long> expire(String key, int seconds);\n\n  Response<Long> pexpire(String key, long milliseconds);\n\n  Response<Long> expireAt(String key, long unixTime);\n\n  Response<Long> pexpireAt(String key, long millisecondsTimestamp);\n\n  Response<String> get(String key);\n\n  Response<Boolean> getbit(String key, long offset);\n\n  Response<String> getrange(String key, long startOffset, long endOffset);\n\n  Response<String> getSet(String key, String value);\n\n  Response<Long> hdel(String key, String... field);\n\n  Response<Boolean> hexists(String key, String field);\n\n  Response<String> hget(String key, String field);\n\n  Response<Map<String, String>> hgetAll(String key);\n\n  Response<Long> hincrBy(String key, String field, long value);\n\n  Response<Set<String>> hkeys(String key);\n\n  Response<Long> hlen(String key);\n\n  Response<List<String>> hmget(String key, String... fields);\n\n  Response<String> hmset(String key, Map<String, String> hash);\n\n  Response<Long> hset(String key, String field, String value);\n\n  Response<Long> hsetnx(String key, String field, String value);\n\n  Response<List<String>> hvals(String key);\n\n  Response<Long> incr(String key);\n\n  Response<Long> incrBy(String key, long integer);\n\n  Response<String> lindex(String key, long index);\n\n  Response<Long> linsert(String key, BinaryClient.LIST_POSITION where, String pivot, String value);\n\n  Response<Long> llen(String key);\n\n  Response<String> lpop(String key);\n\n  Response<Long> lpush(String key, String... string);\n\n  Response<Long> lpushx(String key, String... string);\n\n  Response<List<String>> lrange(String key, long start, long end);\n\n  Response<Long> lrem(String key, long count, String value);\n\n  Response<String> lset(String key, long index, String value);\n\n  Response<String> ltrim(String key, long start, long end);\n\n  Response<Long> move(String key, int dbIndex);\n\n  Response<Long> persist(String key);\n\n  Response<String> rpop(String key);\n\n  Response<Long> rpush(String key, String... string);\n\n  Response<Long> rpushx(String key, String... string);\n\n  Response<Long> sadd(String key, String... member);\n\n  Response<Long> scard(String key);\n\n  Response<Boolean> sismember(String key, String member);\n\n  Response<String> set(String key, String value);\n\n  Response<Boolean> setbit(String key, long offset, boolean value);\n\n  Response<String> setex(String key, int seconds, String value);\n\n  Response<Long> setnx(String key, String value);\n\n  Response<Long> setrange(String key, long offset, String value);\n\n  Response<Set<String>> smembers(String key);\n\n  Response<List<String>> sort(String key);\n\n  Response<List<String>> sort(String key, SortingParams sortingParameters);\n\n  Response<String> spop(String key);\n\n  Response<Set<String>> spop(String key, long count);\n\n  Response<String> srandmember(String key);\n\n  Response<Long> srem(String key, String... member);\n\n  Response<Long> strlen(String key);\n\n  Response<String> substr(String key, int start, int end);\n\n  Response<Long> ttl(String key);\n\n  Response<String> type(String key);\n\n  Response<Long> zadd(String key, double score, String member);\n\n  Response<Long> zadd(String key, double score, String member, ZAddParams params);\n\n  Response<Long> zadd(String key, Map<String, Double> scoreMembers);\n\n  Response<Long> zadd(String key, Map<String, Double> scoreMembers, ZAddParams params);\n\n  Response<Long> zcard(String key);\n\n  Response<Long> zcount(String key, double min, double max);\n\n  Response<Double> zincrby(String key, double score, String member);\n\n  Response<Double> zincrby(String key, double score, String member, ZIncrByParams params);\n\n  Response<Set<String>> zrange(String key, long start, long end);\n\n  Response<Set<String>> zrangeByScore(String key, double min, double max);\n\n  Response<Set<String>> zrangeByScore(String key, String min, String max);\n\n  Response<Set<String>> zrangeByScore(String key, double min, double max, int offset, int count);\n\n  Response<Set<Tuple>> zrangeByScoreWithScores(String key, double min, double max);\n\n  Response<Set<Tuple>> zrangeByScoreWithScores(String key, double min, double max, int offset,\n      int count);\n\n  Response<Set<String>> zrevrangeByScore(String key, double max, double min);\n\n  Response<Set<String>> zrevrangeByScore(String key, String max, String min);\n\n  Response<Set<String>> zrevrangeByScore(String key, double max, double min, int offset, int count);\n\n  Response<Set<Tuple>> zrevrangeByScoreWithScores(String key, double max, double min);\n\n  Response<Set<Tuple>> zrevrangeByScoreWithScores(String key, double max, double min, int offset,\n      int count);\n\n  Response<Set<Tuple>> zrangeWithScores(String key, long start, long end);\n\n  Response<Long> zrank(String key, String member);\n\n  Response<Long> zrem(String key, String... member);\n\n  Response<Long> zremrangeByRank(String key, long start, long end);\n\n  Response<Long> zremrangeByScore(String key, double start, double end);\n\n  Response<Set<String>> zrevrange(String key, long start, long end);\n\n  Response<Set<Tuple>> zrevrangeWithScores(String key, long start, long end);\n\n  Response<Long> zrevrank(String key, String member);\n\n  Response<Double> zscore(String key, String member);\n\n  Response<Long> zlexcount(final String key, final String min, final String max);\n\n  Response<Set<String>> zrangeByLex(final String key, final String min, final String max);\n\n  Response<Set<String>> zrangeByLex(final String key, final String min, final String max,\n      final int offset, final int count);\n\n  Response<Set<String>> zrevrangeByLex(final String key, final String max, final String min);\n\n  Response<Set<String>> zrevrangeByLex(final String key, final String max, final String min,\n      final int offset, final int count);\n\n  Response<Long> zremrangeByLex(final String key, final String start, final String end);\n\n  Response<Long> bitcount(String key);\n\n  Response<Long> bitcount(String key, long start, long end);\n\n  Response<Long> pfadd(final String key, final String... elements);\n\n  Response<Long> pfcount(final String key);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/Response.java",
    "content": "package redis.clients.jedis;\n\nimport redis.clients.jedis.exceptions.JedisDataException;\n\npublic class Response<T> {\n  protected T response = null;\n  protected JedisDataException exception = null;\n\n  private boolean building = false;\n  private boolean built = false;\n  private boolean set = false;\n\n  private Builder<T> builder;\n  private Object data;\n  private Response<?> dependency = null;\n\n  public Response(Builder<T> b) {\n    this.builder = b;\n  }\n\n  public void set(Object data) {\n    this.data = data;\n    set = true;\n  }\n\n  public T get() {\n    // if response has dependency response and dependency is not built,\n    // build it first and no more!!\n    if (dependency != null && dependency.set && !dependency.built) {\n      dependency.build();\n    }\n    if (!set) {\n      throw new JedisDataException(\n          \"Please close pipeline or multi block before calling this method.\");\n    }\n    if (!built) {\n      build();\n    }\n    if (exception != null) {\n      throw exception;\n    }\n    return response;\n  }\n\n  public void setDependency(Response<?> dependency) {\n    this.dependency = dependency;\n  }\n\n  private void build() {\n    // check build state to prevent recursion\n    if (building) {\n      return;\n    }\n\n    building = true;\n    try {\n      if (data != null) {\n        if (data instanceof JedisDataException) {\n          exception = (JedisDataException) data;\n        } else {\n          response = builder.build(data);\n        }\n      }\n\n      data = null;\n    } finally {\n      building = false;\n      built = true;\n    }\n  }\n\n  public String toString() {\n    return \"Response \" + builder.toString();\n  }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/ScanParams.java",
    "content": "package redis.clients.jedis;\n\nimport static redis.clients.jedis.Protocol.Keyword.COUNT;\nimport static redis.clients.jedis.Protocol.Keyword.MATCH;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.List;\n\nimport redis.clients.util.SafeEncoder;\n\npublic class ScanParams {\n  private List<byte[]> params = new ArrayList<byte[]>();\n  public final static String SCAN_POINTER_START = String.valueOf(0);\n  public final static byte[] SCAN_POINTER_START_BINARY = SafeEncoder.encode(SCAN_POINTER_START);\n\n  public ScanParams match(final byte[] pattern) {\n    params.add(MATCH.raw);\n    params.add(pattern);\n    return this;\n  }\n\n  public ScanParams match(final String pattern) {\n    params.add(MATCH.raw);\n    params.add(SafeEncoder.encode(pattern));\n    return this;\n  }\n\n  public ScanParams count(final int count) {\n    params.add(COUNT.raw);\n    params.add(Protocol.toByteArray(count));\n    return this;\n  }\n\n  public Collection<byte[]> getParams() {\n    return Collections.unmodifiableCollection(params);\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/ScanResult.java",
    "content": "package redis.clients.jedis;\n\nimport java.util.List;\n\nimport redis.clients.util.SafeEncoder;\n\npublic class ScanResult<T> {\n  private byte[] cursor;\n  private List<T> results;\n\n  public ScanResult(String cursor, List<T> results) {\n    this(SafeEncoder.encode(cursor), results);\n  }\n\n  public ScanResult(byte[] cursor, List<T> results) {\n    this.cursor = cursor;\n    this.results = results;\n  }\n\n  public String getCursor() {\n    return SafeEncoder.encode(cursor);\n  }\n\n  public byte[] getCursorAsBytes() {\n    return cursor;\n  }\n\n  public List<T> getResult() {\n    return results;\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/ShardedJedis.java",
    "content": "package redis.clients.jedis;\n\nimport java.io.Closeable;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.Set;\nimport java.util.regex.Pattern;\n\nimport redis.clients.jedis.BinaryClient.LIST_POSITION;\nimport redis.clients.jedis.commands.JedisCommands;\nimport redis.clients.jedis.params.geo.GeoRadiusParam;\nimport redis.clients.jedis.params.set.SetParams;\nimport redis.clients.jedis.params.sortedset.ZAddParams;\nimport redis.clients.jedis.params.sortedset.ZIncrByParams;\nimport redis.clients.util.Hashing;\n\npublic class ShardedJedis extends BinaryShardedJedis implements JedisCommands, Closeable {\n\n  protected ShardedJedisPool dataSource = null;\n\n  public ShardedJedis(List<JedisShardInfo> shards) {\n    super(shards);\n  }\n\n  public ShardedJedis(List<JedisShardInfo> shards, Hashing algo) {\n    super(shards, algo);\n  }\n\n  public ShardedJedis(List<JedisShardInfo> shards, Pattern keyTagPattern) {\n    super(shards, keyTagPattern);\n  }\n\n  public ShardedJedis(List<JedisShardInfo> shards, Hashing algo, Pattern keyTagPattern) {\n    super(shards, algo, keyTagPattern);\n  }\n\n  @Override\n  public String set(String key, String value) {\n    Jedis j = getShard(key);\n    return j.set(key, value);\n  }\n\n  @Override\n  public String set(String key, String value, SetParams params) {\n    Jedis j = getShard(key);\n    return j.set(key, value, params);\n  }\n\n  @Override\n  public String get(String key) {\n    Jedis j = getShard(key);\n    return j.get(key);\n  }\n\n  @Override\n  public String echo(String string) {\n    Jedis j = getShard(string);\n    return j.echo(string);\n  }\n\n  @Override\n  public Boolean exists(String key) {\n    Jedis j = getShard(key);\n    return j.exists(key);\n  }\n\n  @Override\n  public String type(String key) {\n    Jedis j = getShard(key);\n    return j.type(key);\n  }\n\n  @Override\n  public Long expire(String key, int seconds) {\n    Jedis j = getShard(key);\n    return j.expire(key, seconds);\n  }\n\n  @Override\n  public Long pexpire(final String key, final long milliseconds) {\n    Jedis j = getShard(key);\n    return j.pexpire(key, milliseconds);\n  }\n\n  @Override\n  public Long expireAt(String key, long unixTime) {\n    Jedis j = getShard(key);\n    return j.expireAt(key, unixTime);\n  }\n\n  @Override\n  public Long pexpireAt(String key, long millisecondsTimestamp) {\n    Jedis j = getShard(key);\n    return j.pexpireAt(key, millisecondsTimestamp);\n  }\n\n  @Override\n  public Long ttl(String key) {\n    Jedis j = getShard(key);\n    return j.ttl(key);\n  }\n\n  @Override\n  public Long pttl(String key) {\n    Jedis j = getShard(key);\n    return j.pttl(key);\n  }\n\n  @Override\n  public Boolean setbit(String key, long offset, boolean value) {\n    Jedis j = getShard(key);\n    return j.setbit(key, offset, value);\n  }\n\n  @Override\n  public Boolean setbit(String key, long offset, String value) {\n    Jedis j = getShard(key);\n    return j.setbit(key, offset, value);\n  }\n\n  @Override\n  public Boolean getbit(String key, long offset) {\n    Jedis j = getShard(key);\n    return j.getbit(key, offset);\n  }\n\n  @Override\n  public Long setrange(String key, long offset, String value) {\n    Jedis j = getShard(key);\n    return j.setrange(key, offset, value);\n  }\n\n  @Override\n  public String getrange(String key, long startOffset, long endOffset) {\n    Jedis j = getShard(key);\n    return j.getrange(key, startOffset, endOffset);\n  }\n\n  @Override\n  public String getSet(String key, String value) {\n    Jedis j = getShard(key);\n    return j.getSet(key, value);\n  }\n\n  @Override\n  public Long setnx(String key, String value) {\n    Jedis j = getShard(key);\n    return j.setnx(key, value);\n  }\n\n  @Override\n  public String setex(String key, int seconds, String value) {\n    Jedis j = getShard(key);\n    return j.setex(key, seconds, value);\n  }\n\n  @Override\n  public String psetex(String key, long milliseconds, String value) {\n    Jedis j = getShard(key);\n    return j.psetex(key, milliseconds, value);\n  }\n\n  public List<String> blpop(String arg) {\n    Jedis j = getShard(arg);\n    return j.blpop(arg);\n  }\n\n  @Override\n  public List<String> blpop(int timeout, String key) {\n    Jedis j = getShard(key);\n    return j.blpop(timeout, key);\n  }\n\n  public List<String> brpop(String arg) {\n    Jedis j = getShard(arg);\n    return j.brpop(arg);\n  }\n\n  @Override\n  public List<String> brpop(int timeout, String key) {\n    Jedis j = getShard(key);\n    return j.brpop(timeout, key);\n  }\n\n  @Override\n  public Long decrBy(String key, long integer) {\n    Jedis j = getShard(key);\n    return j.decrBy(key, integer);\n  }\n\n  @Override\n  public Long decr(String key) {\n    Jedis j = getShard(key);\n    return j.decr(key);\n  }\n\n  @Override\n  public Long incrBy(String key, long integer) {\n    Jedis j = getShard(key);\n    return j.incrBy(key, integer);\n  }\n\n  @Override\n  public Double incrByFloat(String key, double integer) {\n    Jedis j = getShard(key);\n    return j.incrByFloat(key, integer);\n  }\n\n  @Override\n  public Long incr(String key) {\n    Jedis j = getShard(key);\n    return j.incr(key);\n  }\n\n  @Override\n  public Long append(String key, String value) {\n    Jedis j = getShard(key);\n    return j.append(key, value);\n  }\n\n  @Override\n  public String substr(String key, int start, int end) {\n    Jedis j = getShard(key);\n    return j.substr(key, start, end);\n  }\n\n  @Override\n  public Long hset(String key, String field, String value) {\n    Jedis j = getShard(key);\n    return j.hset(key, field, value);\n  }\n\n  @Override\n  public String hget(String key, String field) {\n    Jedis j = getShard(key);\n    return j.hget(key, field);\n  }\n\n  @Override\n  public Long hsetnx(String key, String field, String value) {\n    Jedis j = getShard(key);\n    return j.hsetnx(key, field, value);\n  }\n\n  @Override\n  public String hmset(String key, Map<String, String> hash) {\n    Jedis j = getShard(key);\n    return j.hmset(key, hash);\n  }\n\n  @Override\n  public List<String> hmget(String key, String... fields) {\n    Jedis j = getShard(key);\n    return j.hmget(key, fields);\n  }\n\n  @Override\n  public Long hincrBy(String key, String field, long value) {\n    Jedis j = getShard(key);\n    return j.hincrBy(key, field, value);\n  }\n\n  @Override\n  public Double hincrByFloat(String key, String field, double value) {\n    Jedis j = getShard(key);\n    return j.hincrByFloat(key, field, value);\n  }\n\n  @Override\n  public Boolean hexists(String key, String field) {\n    Jedis j = getShard(key);\n    return j.hexists(key, field);\n  }\n\n  @Override\n  public Long del(String key) {\n    Jedis j = getShard(key);\n    return j.del(key);\n  }\n\n  @Override\n  public Long hdel(String key, String... fields) {\n    Jedis j = getShard(key);\n    return j.hdel(key, fields);\n  }\n\n  @Override\n  public Long hlen(String key) {\n    Jedis j = getShard(key);\n    return j.hlen(key);\n  }\n\n  @Override\n  public Set<String> hkeys(String key) {\n    Jedis j = getShard(key);\n    return j.hkeys(key);\n  }\n\n  @Override\n  public List<String> hvals(String key) {\n    Jedis j = getShard(key);\n    return j.hvals(key);\n  }\n\n  @Override\n  public Map<String, String> hgetAll(String key) {\n    Jedis j = getShard(key);\n    return j.hgetAll(key);\n  }\n\n  @Override\n  public Long rpush(String key, String... strings) {\n    Jedis j = getShard(key);\n    return j.rpush(key, strings);\n  }\n\n  @Override\n  public Long lpush(String key, String... strings) {\n    Jedis j = getShard(key);\n    return j.lpush(key, strings);\n  }\n\n  @Override\n  public Long lpushx(String key, String... string) {\n    Jedis j = getShard(key);\n    return j.lpushx(key, string);\n  }\n\n  @Override\n  public Long strlen(final String key) {\n    Jedis j = getShard(key);\n    return j.strlen(key);\n  }\n\n  @Override\n  public Long move(String key, int dbIndex) {\n    Jedis j = getShard(key);\n    return j.move(key, dbIndex);\n  }\n\n  @Override\n  public Long rpushx(String key, String... string) {\n    Jedis j = getShard(key);\n    return j.rpushx(key, string);\n  }\n\n  @Override\n  public Long persist(final String key) {\n    Jedis j = getShard(key);\n    return j.persist(key);\n  }\n\n  @Override\n  public Long llen(String key) {\n    Jedis j = getShard(key);\n    return j.llen(key);\n  }\n\n  @Override\n  public List<String> lrange(String key, long start, long end) {\n    Jedis j = getShard(key);\n    return j.lrange(key, start, end);\n  }\n\n  @Override\n  public String ltrim(String key, long start, long end) {\n    Jedis j = getShard(key);\n    return j.ltrim(key, start, end);\n  }\n\n  @Override\n  public String lindex(String key, long index) {\n    Jedis j = getShard(key);\n    return j.lindex(key, index);\n  }\n\n  @Override\n  public String lset(String key, long index, String value) {\n    Jedis j = getShard(key);\n    return j.lset(key, index, value);\n  }\n\n  @Override\n  public Long lrem(String key, long count, String value) {\n    Jedis j = getShard(key);\n    return j.lrem(key, count, value);\n  }\n\n  @Override\n  public String lpop(String key) {\n    Jedis j = getShard(key);\n    return j.lpop(key);\n  }\n\n  @Override\n  public String rpop(String key) {\n    Jedis j = getShard(key);\n    return j.rpop(key);\n  }\n\n  @Override\n  public Long sadd(String key, String... members) {\n    Jedis j = getShard(key);\n    return j.sadd(key, members);\n  }\n\n  @Override\n  public Set<String> smembers(String key) {\n    Jedis j = getShard(key);\n    return j.smembers(key);\n  }\n\n  @Override\n  public Long srem(String key, String... members) {\n    Jedis j = getShard(key);\n    return j.srem(key, members);\n  }\n\n  @Override\n  public String spop(String key) {\n    Jedis j = getShard(key);\n    return j.spop(key);\n  }\n\n  @Override\n  public Set<String> spop(String key, long count) {\n    Jedis j = getShard(key);\n    return j.spop(key, count);\n  }\n\n  @Override\n  public Long scard(String key) {\n    Jedis j = getShard(key);\n    return j.scard(key);\n  }\n\n  @Override\n  public Boolean sismember(String key, String member) {\n    Jedis j = getShard(key);\n    return j.sismember(key, member);\n  }\n\n  @Override\n  public String srandmember(String key) {\n    Jedis j = getShard(key);\n    return j.srandmember(key);\n  }\n\n  @Override\n  public List<String> srandmember(String key, int count) {\n    Jedis j = getShard(key);\n    return j.srandmember(key, count);\n  }\n\n  @Override\n  public Long zadd(String key, double score, String member) {\n    Jedis j = getShard(key);\n    return j.zadd(key, score, member);\n  }\n\n  @Override\n  public Long zadd(String key, double score, String member, ZAddParams params) {\n    Jedis j = getShard(key);\n    return j.zadd(key, score, member, params);\n  }\n\n  @Override\n  public Long zadd(String key, Map<String, Double> scoreMembers) {\n    Jedis j = getShard(key);\n    return j.zadd(key, scoreMembers);\n  }\n\n  @Override\n  public Long zadd(String key, Map<String, Double> scoreMembers, ZAddParams params) {\n    Jedis j = getShard(key);\n    return j.zadd(key, scoreMembers, params);\n  }\n\n  @Override\n  public Set<String> zrange(String key, long start, long end) {\n    Jedis j = getShard(key);\n    return j.zrange(key, start, end);\n  }\n\n  @Override\n  public Long zrem(String key, String... members) {\n    Jedis j = getShard(key);\n    return j.zrem(key, members);\n  }\n\n  @Override\n  public Double zincrby(String key, double score, String member) {\n    Jedis j = getShard(key);\n    return j.zincrby(key, score, member);\n  }\n\n  @Override\n  public Double zincrby(String key, double score, String member, ZIncrByParams params) {\n    Jedis j = getShard(key);\n    return j.zincrby(key, score, member, params);\n  }\n\n  @Override\n  public Long zrank(String key, String member) {\n    Jedis j = getShard(key);\n    return j.zrank(key, member);\n  }\n\n  @Override\n  public Long zrevrank(String key, String member) {\n    Jedis j = getShard(key);\n    return j.zrevrank(key, member);\n  }\n\n  @Override\n  public Set<String> zrevrange(String key, long start, long end) {\n    Jedis j = getShard(key);\n    return j.zrevrange(key, start, end);\n  }\n\n  @Override\n  public Set<Tuple> zrangeWithScores(String key, long start, long end) {\n    Jedis j = getShard(key);\n    return j.zrangeWithScores(key, start, end);\n  }\n\n  @Override\n  public Set<Tuple> zrevrangeWithScores(String key, long start, long end) {\n    Jedis j = getShard(key);\n    return j.zrevrangeWithScores(key, start, end);\n  }\n\n  @Override\n  public Long zcard(String key) {\n    Jedis j = getShard(key);\n    return j.zcard(key);\n  }\n\n  @Override\n  public Double zscore(String key, String member) {\n    Jedis j = getShard(key);\n    return j.zscore(key, member);\n  }\n\n  @Override\n  public List<String> sort(String key) {\n    Jedis j = getShard(key);\n    return j.sort(key);\n  }\n\n  @Override\n  public List<String> sort(String key, SortingParams sortingParameters) {\n    Jedis j = getShard(key);\n    return j.sort(key, sortingParameters);\n  }\n\n  @Override\n  public Long zcount(String key, double min, double max) {\n    Jedis j = getShard(key);\n    return j.zcount(key, min, max);\n  }\n\n  @Override\n  public Long zcount(String key, String min, String max) {\n    Jedis j = getShard(key);\n    return j.zcount(key, min, max);\n  }\n\n  @Override\n  public Set<String> zrangeByScore(String key, double min, double max) {\n    Jedis j = getShard(key);\n    return j.zrangeByScore(key, min, max);\n  }\n\n  @Override\n  public Set<String> zrevrangeByScore(String key, double max, double min) {\n    Jedis j = getShard(key);\n    return j.zrevrangeByScore(key, max, min);\n  }\n\n  @Override\n  public Set<String> zrangeByScore(String key, double min, double max, int offset, int count) {\n    Jedis j = getShard(key);\n    return j.zrangeByScore(key, min, max, offset, count);\n  }\n\n  @Override\n  public Set<String> zrevrangeByScore(String key, double max, double min, int offset, int count) {\n    Jedis j = getShard(key);\n    return j.zrevrangeByScore(key, max, min, offset, count);\n  }\n\n  @Override\n  public Set<Tuple> zrangeByScoreWithScores(String key, double min, double max) {\n    Jedis j = getShard(key);\n    return j.zrangeByScoreWithScores(key, min, max);\n  }\n\n  @Override\n  public Set<Tuple> zrevrangeByScoreWithScores(String key, double max, double min) {\n    Jedis j = getShard(key);\n    return j.zrevrangeByScoreWithScores(key, max, min);\n  }\n\n  @Override\n  public Set<Tuple> zrangeByScoreWithScores(String key, double min, double max, int offset,\n      int count) {\n    Jedis j = getShard(key);\n    return j.zrangeByScoreWithScores(key, min, max, offset, count);\n  }\n\n  @Override\n  public Set<Tuple> zrevrangeByScoreWithScores(String key, double max, double min, int offset,\n      int count) {\n    Jedis j = getShard(key);\n    return j.zrevrangeByScoreWithScores(key, max, min, offset, count);\n  }\n\n  @Override\n  public Set<String> zrangeByScore(String key, String min, String max) {\n    Jedis j = getShard(key);\n    return j.zrangeByScore(key, min, max);\n  }\n\n  @Override\n  public Set<String> zrevrangeByScore(String key, String max, String min) {\n    Jedis j = getShard(key);\n    return j.zrevrangeByScore(key, max, min);\n  }\n\n  @Override\n  public Set<String> zrangeByScore(String key, String min, String max, int offset, int count) {\n    Jedis j = getShard(key);\n    return j.zrangeByScore(key, min, max, offset, count);\n  }\n\n  @Override\n  public Set<String> zrevrangeByScore(String key, String max, String min, int offset, int count) {\n    Jedis j = getShard(key);\n    return j.zrevrangeByScore(key, max, min, offset, count);\n  }\n\n  @Override\n  public Set<Tuple> zrangeByScoreWithScores(String key, String min, String max) {\n    Jedis j = getShard(key);\n    return j.zrangeByScoreWithScores(key, min, max);\n  }\n\n  @Override\n  public Set<Tuple> zrevrangeByScoreWithScores(String key, String max, String min) {\n    Jedis j = getShard(key);\n    return j.zrevrangeByScoreWithScores(key, max, min);\n  }\n\n  @Override\n  public Set<Tuple> zrangeByScoreWithScores(String key, String min, String max, int offset,\n      int count) {\n    Jedis j = getShard(key);\n    return j.zrangeByScoreWithScores(key, min, max, offset, count);\n  }\n\n  @Override\n  public Set<Tuple> zrevrangeByScoreWithScores(String key, String max, String min, int offset,\n      int count) {\n    Jedis j = getShard(key);\n    return j.zrevrangeByScoreWithScores(key, max, min, offset, count);\n  }\n\n  @Override\n  public Long zremrangeByRank(String key, long start, long end) {\n    Jedis j = getShard(key);\n    return j.zremrangeByRank(key, start, end);\n  }\n\n  @Override\n  public Long zremrangeByScore(String key, double start, double end) {\n    Jedis j = getShard(key);\n    return j.zremrangeByScore(key, start, end);\n  }\n\n  @Override\n  public Long zremrangeByScore(String key, String start, String end) {\n    Jedis j = getShard(key);\n    return j.zremrangeByScore(key, start, end);\n  }\n\n  @Override\n  public Long zlexcount(final String key, final String min, final String max) {\n    return getShard(key).zlexcount(key, min, max);\n  }\n\n  @Override\n  public Set<String> zrangeByLex(final String key, final String min, final String max) {\n    return getShard(key).zrangeByLex(key, min, max);\n  }\n\n  @Override\n  public Set<String> zrangeByLex(final String key, final String min, final String max,\n      final int offset, final int count) {\n    return getShard(key).zrangeByLex(key, min, max, offset, count);\n  }\n\n  @Override\n  public Set<String> zrevrangeByLex(String key, String max, String min) {\n    return getShard(key).zrevrangeByLex(key, max, min);\n  }\n\n  @Override\n  public Set<String> zrevrangeByLex(String key, String max, String min, int offset, int count) {\n    return getShard(key).zrevrangeByLex(key, max, min, offset, count);\n  }\n\n  @Override\n  public Long zremrangeByLex(final String key, final String min, final String max) {\n    return getShard(key).zremrangeByLex(key, min, max);\n  }\n\n  @Override\n  public Long linsert(String key, LIST_POSITION where, String pivot, String value) {\n    Jedis j = getShard(key);\n    return j.linsert(key, where, pivot, value);\n  }\n\n  @Override\n  public Long bitcount(final String key) {\n    Jedis j = getShard(key);\n    return j.bitcount(key);\n  }\n\n  @Override\n  public Long bitcount(final String key, long start, long end) {\n    Jedis j = getShard(key);\n    return j.bitcount(key, start, end);\n  }\n\n  @Override\n  public Long bitpos(String key, boolean value) {\n    Jedis j = getShard(key);\n    return j.bitpos(key, value);\n  }\n\n  @Override\n  public Long bitpos(String key, boolean value, BitPosParams params) {\n    Jedis j = getShard(key);\n    return j.bitpos(key, value, params);\n  }\n\n  @Override\n  public ScanResult<Entry<String, String>> hscan(String key, final String cursor) {\n    Jedis j = getShard(key);\n    return j.hscan(key, cursor);\n  }\n\n  @Override\n  public ScanResult<Entry<String, String>> hscan(String key, String cursor, ScanParams params) {\n    Jedis j = getShard(key);\n    return j.hscan(key, cursor, params);\n  }\n\n  @Override\n  public ScanResult<String> sscan(String key, final String cursor) {\n    Jedis j = getShard(key);\n    return j.sscan(key, cursor);\n  }\n\n  @Override\n  public ScanResult<Tuple> zscan(String key, final String cursor) {\n    Jedis j = getShard(key);\n    return j.zscan(key, cursor);\n  }\n\n  @Override\n  public ScanResult<Tuple> zscan(String key, String cursor, ScanParams params) {\n    Jedis j = getShard(key);\n    return j.zscan(key, cursor, params);\n  }\n\n  @Override\n  public ScanResult<String> sscan(String key, String cursor, ScanParams params) {\n    Jedis j = getShard(key);\n    return j.sscan(key, cursor, params);\n  }\n\n  @Override\n  public void close() {\n    if (dataSource != null) {\n      boolean broken = false;\n\n      for (Jedis jedis : getAllShards()) {\n        if (jedis.getClient().isBroken()) {\n          broken = true;\n          break;\n        }\n      }\n\n      if (broken) {\n        dataSource.returnBrokenResource(this);\n      } else {\n        dataSource.returnResource(this);\n      }\n\n    } else {\n      disconnect();\n    }\n  }\n\n  public void setDataSource(ShardedJedisPool shardedJedisPool) {\n    this.dataSource = shardedJedisPool;\n  }\n\n  public void resetState() {\n    for (Jedis jedis : getAllShards()) {\n      jedis.resetState();\n    }\n  }\n\n  @Override\n  public Long pfadd(String key, String... elements) {\n    Jedis j = getShard(key);\n    return j.pfadd(key, elements);\n  }\n\n  @Override\n  public long pfcount(String key) {\n    Jedis j = getShard(key);\n    return j.pfcount(key);\n  }\n\n  @Override\n  public Long geoadd(String key, double longitude, double latitude, String member) {\n    Jedis j = getShard(key);\n    return j.geoadd(key, longitude, latitude, member);\n  }\n\n  @Override\n  public Long geoadd(String key, Map<String, GeoCoordinate> memberCoordinateMap) {\n    Jedis j = getShard(key);\n    return j.geoadd(key, memberCoordinateMap);\n  }\n\n  @Override\n  public Double geodist(String key, String member1, String member2) {\n    Jedis j = getShard(key);\n    return j.geodist(key, member1, member2);\n  }\n\n  @Override\n  public Double geodist(String key, String member1, String member2, GeoUnit unit) {\n    Jedis j = getShard(key);\n    return j.geodist(key, member1, member2, unit);\n  }\n\n  @Override\n  public List<String> geohash(String key, String... members) {\n    Jedis j = getShard(key);\n    return j.geohash(key, members);\n  }\n\n  @Override\n  public List<GeoCoordinate> geopos(String key, String... members) {\n    Jedis j = getShard(key);\n    return j.geopos(key, members);\n  }\n\n  @Override\n  public List<GeoRadiusResponse> georadius(String key, double longitude, double latitude,\n      double radius, GeoUnit unit) {\n    Jedis j = getShard(key);\n    return j.georadius(key, longitude, latitude, radius, unit);\n  }\n\n  @Override\n  public List<GeoRadiusResponse> georadius(String key, double longitude, double latitude,\n      double radius, GeoUnit unit, GeoRadiusParam param) {\n    Jedis j = getShard(key);\n    return j.georadius(key, longitude, latitude, radius, unit, param);\n  }\n\n  @Override\n  public List<GeoRadiusResponse> georadiusByMember(String key, String member, double radius,\n      GeoUnit unit) {\n    Jedis j = getShard(key);\n    return j.georadiusByMember(key, member, radius, unit);\n  }\n\n  @Override\n  public List<GeoRadiusResponse> georadiusByMember(String key, String member, double radius,\n      GeoUnit unit, GeoRadiusParam param) {\n    Jedis j = getShard(key);\n    return j.georadiusByMember(key, member, radius, unit, param);\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/ShardedJedisPipeline.java",
    "content": "package redis.clients.jedis;\n\nimport java.util.ArrayList;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Queue;\n\npublic class ShardedJedisPipeline extends PipelineBase {\n  private BinaryShardedJedis jedis;\n  private List<FutureResult> results = new ArrayList<FutureResult>();\n  private Queue<Client> clients = new LinkedList<Client>();\n\n  private static class FutureResult {\n    private Client client;\n\n    public FutureResult(Client client) {\n      this.client = client;\n    }\n\n    public Object get() {\n      return client.getOne();\n    }\n  }\n\n  public void setShardedJedis(BinaryShardedJedis jedis) {\n    this.jedis = jedis;\n  }\n\n  public List<Object> getResults() {\n    List<Object> r = new ArrayList<Object>();\n    for (FutureResult fr : results) {\n      r.add(fr.get());\n    }\n    return r;\n  }\n\n  /**\n   * Syncronize pipeline by reading all responses. This operation closes the pipeline. In order to\n   * get return values from pipelined commands, capture the different Response&lt;?&gt; of the\n   * commands you execute.\n   */\n  public void sync() {\n    for (Client client : clients) {\n      generateResponse(client.getOne());\n    }\n  }\n\n  /**\n   * Syncronize pipeline by reading all responses. This operation closes the pipeline. Whenever\n   * possible try to avoid using this version and use ShardedJedisPipeline.sync() as it won't go\n   * through all the responses and generate the right response type (usually it is a waste of time).\n   * @return A list of all the responses in the order you executed them.\n   */\n  public List<Object> syncAndReturnAll() {\n    List<Object> formatted = new ArrayList<Object>();\n    for (Client client : clients) {\n      formatted.add(generateResponse(client.getOne()).get());\n    }\n    return formatted;\n  }\n\n  @Override\n  protected Client getClient(String key) {\n    Client client = jedis.getShard(key).getClient();\n    clients.add(client);\n    results.add(new FutureResult(client));\n    return client;\n  }\n\n  @Override\n  protected Client getClient(byte[] key) {\n    Client client = jedis.getShard(key).getClient();\n    clients.add(client);\n    results.add(new FutureResult(client));\n    return client;\n  }\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/ShardedJedisPool.java",
    "content": "package redis.clients.jedis;\n\nimport java.util.List;\nimport java.util.regex.Pattern;\n\nimport org.apache.commons.pool2.PooledObject;\nimport org.apache.commons.pool2.PooledObjectFactory;\nimport org.apache.commons.pool2.impl.DefaultPooledObject;\nimport org.apache.commons.pool2.impl.GenericObjectPoolConfig;\n\nimport redis.clients.util.Hashing;\nimport redis.clients.util.Pool;\n\npublic class ShardedJedisPool extends Pool<ShardedJedis> {\n  public ShardedJedisPool(final GenericObjectPoolConfig poolConfig, List<JedisShardInfo> shards) {\n    this(poolConfig, shards, Hashing.MURMUR_HASH);\n  }\n\n  public ShardedJedisPool(final GenericObjectPoolConfig poolConfig, List<JedisShardInfo> shards,\n      Hashing algo) {\n    this(poolConfig, shards, algo, null);\n  }\n\n  public ShardedJedisPool(final GenericObjectPoolConfig poolConfig, List<JedisShardInfo> shards,\n      Pattern keyTagPattern) {\n    this(poolConfig, shards, Hashing.MURMUR_HASH, keyTagPattern);\n  }\n\n  public ShardedJedisPool(final GenericObjectPoolConfig poolConfig, List<JedisShardInfo> shards,\n      Hashing algo, Pattern keyTagPattern) {\n    super(poolConfig, new ShardedJedisFactory(shards, algo, keyTagPattern));\n  }\n\n  @Override\n  public ShardedJedis getResource() {\n    ShardedJedis jedis = super.getResource();\n    jedis.setDataSource(this);\n    return jedis;\n  }\n\n  @Override\n  protected void returnBrokenResource(final ShardedJedis resource) {\n    if (resource != null) {\n      returnBrokenResourceObject(resource);\n    }\n  }\n\n  @Override\n  protected void returnResource(final ShardedJedis resource) {\n    if (resource != null) {\n      resource.resetState();\n      returnResourceObject(resource);\n    }\n  }\n\n  /**\n   * PoolableObjectFactory custom impl.\n   */\n  private static class ShardedJedisFactory implements PooledObjectFactory<ShardedJedis> {\n    private List<JedisShardInfo> shards;\n    private Hashing algo;\n    private Pattern keyTagPattern;\n\n    public ShardedJedisFactory(List<JedisShardInfo> shards, Hashing algo, Pattern keyTagPattern) {\n      this.shards = shards;\n      this.algo = algo;\n      this.keyTagPattern = keyTagPattern;\n    }\n\n    @Override\n    public PooledObject<ShardedJedis> makeObject() throws Exception {\n      ShardedJedis jedis = new ShardedJedis(shards, algo, keyTagPattern);\n      return new DefaultPooledObject<ShardedJedis>(jedis);\n    }\n\n    @Override\n    public void destroyObject(PooledObject<ShardedJedis> pooledShardedJedis) throws Exception {\n      final ShardedJedis shardedJedis = pooledShardedJedis.getObject();\n      for (Jedis jedis : shardedJedis.getAllShards()) {\n        try {\n          try {\n            jedis.quit();\n          } catch (Exception e) {\n\n          }\n          jedis.disconnect();\n        } catch (Exception e) {\n\n        }\n      }\n    }\n\n    @Override\n    public boolean validateObject(PooledObject<ShardedJedis> pooledShardedJedis) {\n      try {\n        ShardedJedis jedis = pooledShardedJedis.getObject();\n        for (Jedis shard : jedis.getAllShards()) {\n          if (!shard.ping().equals(\"PONG\")) {\n            return false;\n          }\n        }\n        return true;\n      } catch (Exception ex) {\n        return false;\n      }\n    }\n\n    @Override\n    public void activateObject(PooledObject<ShardedJedis> p) throws Exception {\n\n    }\n\n    @Override\n    public void passivateObject(PooledObject<ShardedJedis> p) throws Exception {\n\n    }\n  }\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/SortingParams.java",
    "content": "package redis.clients.jedis;\n\nimport static redis.clients.jedis.Protocol.Keyword.ALPHA;\nimport static redis.clients.jedis.Protocol.Keyword.ASC;\nimport static redis.clients.jedis.Protocol.Keyword.BY;\nimport static redis.clients.jedis.Protocol.Keyword.DESC;\nimport static redis.clients.jedis.Protocol.Keyword.GET;\nimport static redis.clients.jedis.Protocol.Keyword.LIMIT;\nimport static redis.clients.jedis.Protocol.Keyword.NOSORT;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.List;\n\nimport redis.clients.util.SafeEncoder;\n\n/**\n * Builder Class for {@link Jedis#sort(String, SortingParams) SORT} Parameters.\n */\npublic class SortingParams {\n  private List<byte[]> params = new ArrayList<byte[]>();\n\n  /**\n   * Sort by weight in keys.\n   * <p>\n   * Takes a pattern that is used in order to generate the key names of the weights used for\n   * sorting. Weight key names are obtained substituting the first occurrence of * with the actual\n   * value of the elements on the list.\n   * <p>\n   * The pattern for a normal key/value pair is \"keyname*\" and for a value in a hash\n   * \"keyname*-&gt;fieldname\".\n   * @param pattern\n   * @return the SortingParams Object\n   */\n  public SortingParams by(final String pattern) {\n    return by(SafeEncoder.encode(pattern));\n  }\n\n  /**\n   * Sort by weight in keys.\n   * <p>\n   * Takes a pattern that is used in order to generate the key names of the weights used for\n   * sorting. Weight key names are obtained substituting the first occurrence of * with the actual\n   * value of the elements on the list.\n   * <p>\n   * The pattern for a normal key/value pair is \"keyname*\" and for a value in a hash\n   * \"keyname*-&gt;fieldname\".\n   * @param pattern\n   * @return the SortingParams Object\n   */\n  public SortingParams by(final byte[] pattern) {\n    params.add(BY.raw);\n    params.add(pattern);\n    return this;\n  }\n\n  /**\n   * No sorting.\n   * <p>\n   * This is useful if you want to retrieve a external key (using {@link #get(String...) GET}) but\n   * you don't want the sorting overhead.\n   * @return the SortingParams Object\n   */\n  public SortingParams nosort() {\n    params.add(BY.raw);\n    params.add(NOSORT.raw);\n    return this;\n  }\n\n  public Collection<byte[]> getParams() {\n    return Collections.unmodifiableCollection(params);\n  }\n\n  /**\n   * Get the Sorting in Descending Order.\n   * @return the sortingParams Object\n   */\n  public SortingParams desc() {\n    params.add(DESC.raw);\n    return this;\n  }\n\n  /**\n   * Get the Sorting in Ascending Order. This is the default order.\n   * @return the SortingParams Object\n   */\n  public SortingParams asc() {\n    params.add(ASC.raw);\n    return this;\n  }\n\n  /**\n   * Limit the Numbers of returned Elements.\n   * @param start is zero based\n   * @param count\n   * @return the SortingParams Object\n   */\n  public SortingParams limit(final int start, final int count) {\n    params.add(LIMIT.raw);\n    params.add(Protocol.toByteArray(start));\n    params.add(Protocol.toByteArray(count));\n    return this;\n  }\n\n  /**\n   * Sort lexicographicaly. Note that Redis is utf-8 aware assuming you set the right value for the\n   * LC_COLLATE environment variable.\n   * @return the SortingParams Object\n   */\n  public SortingParams alpha() {\n    params.add(ALPHA.raw);\n    return this;\n  }\n\n  /**\n   * Retrieving external keys from the result of the search.\n   * <p>\n   * Takes a pattern that is used in order to generate the key names of the result of sorting. The\n   * key names are obtained substituting the first occurrence of * with the actual value of the\n   * elements on the list.\n   * <p>\n   * The pattern for a normal key/value pair is \"keyname*\" and for a value in a hash\n   * \"keyname*-&gt;fieldname\".\n   * <p>\n   * To get the list itself use the char # as pattern.\n   * @param patterns\n   * @return the SortingParams Object\n   */\n  public SortingParams get(String... patterns) {\n    for (final String pattern : patterns) {\n      params.add(GET.raw);\n      params.add(SafeEncoder.encode(pattern));\n    }\n    return this;\n  }\n\n  /**\n   * Retrieving external keys from the result of the search.\n   * <p>\n   * Takes a pattern that is used in order to generate the key names of the result of sorting. The\n   * key names are obtained substituting the first occurrence of * with the actual value of the\n   * elements on the list.\n   * <p>\n   * The pattern for a normal key/value pair is \"keyname*\" and for a value in a hash\n   * \"keyname*-&gt;fieldname\".\n   * <p>\n   * To get the list itself use the char # as pattern.\n   * @param patterns\n   * @return the SortingParams Object\n   */\n  public SortingParams get(byte[]... patterns) {\n    for (final byte[] pattern : patterns) {\n      params.add(GET.raw);\n      params.add(pattern);\n    }\n    return this;\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/SubPubClusterCommand.java",
    "content": "package redis.clients.jedis;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport redis.clients.jedis.exceptions.*;\nimport redis.clients.util.JedisClusterCRC16;\n\n/**\n * Created by yijunzhang on 14-7-19.\n */\npublic class SubPubClusterCommand {\n    private final Logger logger = LoggerFactory.getLogger(this.getClass());\n\n    protected final PipelineCluster pipelineCluster;\n\n    private final JedisClusterConnectionHandler connectionHandler;\n\n    private final int redirections;\n\n    private ThreadLocal<Jedis> askConnection = new ThreadLocal<Jedis>();\n\n    public SubPubClusterCommand(PipelineCluster pipelineCluster, JedisClusterConnectionHandler connectionHandler,\n            int redirections) {\n        this.pipelineCluster = pipelineCluster;\n        this.connectionHandler = connectionHandler;\n        this.redirections = redirections;\n    }\n\n    private Jedis returnRetriesJedis(String key, int redirections,\n                                     boolean tryRandomNode, boolean asking) {\n        if (redirections <= 0) {\n            throw new JedisClusterMaxRedirectionsException(\n                    \"Too many Cluster redirections? key=\" + key);\n        }\n\n        Jedis jedis = null;\n        try {\n            if (asking) {\n                // TODO: Pipeline asking with the original command to make it\n                // faster....\n                jedis = askConnection.get();\n                jedis.asking();\n\n                // if asking success, reset asking flag\n                asking = false;\n            } else if (tryRandomNode) {\n                jedis = connectionHandler.getConnection();\n            } else {\n                jedis = connectionHandler.getConnectionFromSlot(JedisClusterCRC16.getSlot(key));\n            }\n\n            return jedis;\n        } catch (JedisConnectionException jce) {\n            if (tryRandomNode) {\n                // maybe all connection is down\n                throw jce;\n            }\n\n            releaseConnection(jedis);\n            // retry with random connection\n            return returnRetriesJedis(key, redirections--, true, asking);\n        }  catch (JedisRedirectionException jre) {\n            // if MOVED redirection occurred,\n            if (jre instanceof JedisMovedDataException) {\n                // it rebuilds cluster's slot cache\n                // recommended by Redis cluster specification\n                this.connectionHandler.renewSlotCache(jedis);\n            }\n\n            // release current connection before recursion or renewing\n            releaseConnection(jedis);\n            jedis = null;\n\n            if (jre instanceof JedisAskDataException) {\n                asking = true;\n                askConnection.set(this.connectionHandler.getConnectionFromNode(jre.getTargetNode()));\n            } else if (jre instanceof JedisMovedDataException) {\n            } else {\n                throw new JedisClusterException(jre);\n            }\n\n            return returnRetriesJedis(key, redirections - 1, false, asking);\n        }\n    }\n\n    public Jedis getJedis(String channel) {\n        return returnRetriesJedis(channel, this.redirections, false, false);\n    }\n\n    public Jedis getNewJedis(String channel, int timeout) {\n        Jedis jedis = getJedis(channel);\n        try {\n            String host = jedis.getClient().getHost();\n            int port = jedis.getClient().getPort();\n            Jedis newJedis = new Jedis(host, port, timeout);\n            String pong = newJedis.ping();\n            if (pong == null || !pong.equals(\"PONG\")) {\n                throw new JedisException(\"SubPubCluster:jedis is not ping !\");\n            }\n            return newJedis;\n        } finally {\n            releaseConnection(jedis);\n        }\n    }\n\n    public void releaseConnection(Jedis connection) {\n        if (connection != null) {\n            connection.close();\n        }\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/Transaction.java",
    "content": "package redis.clients.jedis;\n\nimport java.io.Closeable;\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport redis.clients.jedis.exceptions.JedisDataException;\n\n/**\n * Transaction is nearly identical to Pipeline, only differences are the multi/discard behaviors\n */\npublic class Transaction extends MultiKeyPipelineBase implements Closeable {\n\n  protected boolean inTransaction = true;\n\n  protected Transaction() {\n    // client will be set later in transaction block\n  }\n\n  public Transaction(final Client client) {\n    this.client = client;\n  }\n\n  @Override\n  protected Client getClient(String key) {\n    return client;\n  }\n\n  @Override\n  protected Client getClient(byte[] key) {\n    return client;\n  }\n\n  public void clear() {\n    if (inTransaction) {\n      discard();\n    }\n  }\n\n  public List<Object> exec() {\n    // Discard QUEUED or ERROR\n    client.getMany(getPipelinedResponseLength());\n    client.exec();\n    inTransaction = false;\n\n    List<Object> unformatted = client.getObjectMultiBulkReply();\n    if (unformatted == null) {\n      return null;\n    }\n    List<Object> formatted = new ArrayList<Object>();\n    for (Object o : unformatted) {\n      try {\n        formatted.add(generateResponse(o).get());\n      } catch (JedisDataException e) {\n        formatted.add(e);\n      }\n    }\n    return formatted;\n  }\n\n  public List<Response<?>> execGetResponse() {\n    // Discard QUEUED or ERROR\n    client.getMany(getPipelinedResponseLength());\n    client.exec();\n    inTransaction = false;\n\n    List<Object> unformatted = client.getObjectMultiBulkReply();\n    if (unformatted == null) {\n      return null;\n    }\n    List<Response<?>> response = new ArrayList<Response<?>>();\n    for (Object o : unformatted) {\n      response.add(generateResponse(o));\n    }\n    return response;\n  }\n\n  public String discard() {\n    client.getMany(getPipelinedResponseLength());\n    client.discard();\n    inTransaction = false;\n    clean();\n    return client.getStatusCodeReply();\n  }\n\n  public void setClient(Client client) {\n    this.client = client;\n  }\n\n  @Override\n  public void close() {\n    clear();\n  }\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/Tuple.java",
    "content": "package redis.clients.jedis;\n\nimport java.util.Arrays;\n\nimport redis.clients.util.SafeEncoder;\n\npublic class Tuple implements Comparable<Tuple> {\n  private byte[] element;\n  private Double score;\n\n  public int hashCode() {\n    final int prime = 31;\n    int result = 1;\n    result = prime * result;\n    if (null != element) {\n      for (final byte b : element) {\n        result = prime * result + b;\n      }\n    }\n    long temp;\n    temp = Double.doubleToLongBits(score);\n    result = prime * result + (int) (temp ^ (temp >>> 32));\n    return result;\n  }\n\n  public boolean equals(Object obj) {\n    if (this == obj) return true;\n    if (obj == null) return false;\n    if (getClass() != obj.getClass()) return false;\n    Tuple other = (Tuple) obj;\n    if (element == null) {\n      if (other.element != null) return false;\n    } else if (!Arrays.equals(element, other.element)) return false;\n    return true;\n  }\n\n  public int compareTo(Tuple other) {\n    if (this.score == other.getScore() || Arrays.equals(this.element, other.element)) return 0;\n    else return this.score < other.getScore() ? -1 : 1;\n  }\n\n  public Tuple(String element, Double score) {\n    super();\n    this.element = SafeEncoder.encode(element);\n    this.score = score;\n  }\n\n  public Tuple(byte[] element, Double score) {\n    super();\n    this.element = element;\n    this.score = score;\n  }\n\n  public String getElement() {\n    if (null != element) {\n      return SafeEncoder.encode(element);\n    } else {\n      return null;\n    }\n  }\n\n  public byte[] getBinaryElement() {\n    return element;\n  }\n\n  public double getScore() {\n    return score;\n  }\n\n  public String toString() {\n    return '[' + Arrays.toString(element) + ',' + score + ']';\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/ZParams.java",
    "content": "package redis.clients.jedis;\n\nimport static redis.clients.jedis.Protocol.Keyword.AGGREGATE;\nimport static redis.clients.jedis.Protocol.Keyword.WEIGHTS;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.List;\n\nimport redis.clients.util.SafeEncoder;\n\npublic class ZParams {\n  public enum Aggregate {\n    SUM, MIN, MAX;\n\n    public final byte[] raw;\n\n    Aggregate() {\n      raw = SafeEncoder.encode(name());\n    }\n  }\n\n  private List<byte[]> params = new ArrayList<byte[]>();\n\n  /**\n   * Set weights.\n   * @param weights weights.\n   */\n  public ZParams weights(final double... weights) {\n    params.add(WEIGHTS.raw);\n    for (final double weight : weights) {\n      params.add(Protocol.toByteArray(weight));\n    }\n\n    return this;\n  }\n\n  public Collection<byte[]> getParams() {\n    return Collections.unmodifiableCollection(params);\n  }\n\n  public ZParams aggregate(final Aggregate aggregate) {\n    params.add(AGGREGATE.raw);\n    params.add(aggregate.raw);\n    return this;\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/commands/AdvancedBinaryJedisCommands.java",
    "content": "package redis.clients.jedis.commands;\n\nimport java.util.List;\n\npublic interface AdvancedBinaryJedisCommands {\n\n  List<byte[]> configGet(byte[] pattern);\n\n  byte[] configSet(byte[] parameter, byte[] value);\n\n  String slowlogReset();\n\n  Long slowlogLen();\n\n  List<byte[]> slowlogGetBinary();\n\n  List<byte[]> slowlogGetBinary(long entries);\n\n  Long objectRefcount(byte[] key);\n\n  byte[] objectEncoding(byte[] key);\n\n  Long objectIdletime(byte[] key);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/commands/AdvancedJedisCommands.java",
    "content": "package redis.clients.jedis.commands;\n\nimport java.util.List;\n\nimport redis.clients.util.Slowlog;\n\npublic interface AdvancedJedisCommands {\n  List<String> configGet(String pattern);\n\n  String configSet(String parameter, String value);\n\n  String slowlogReset();\n\n  Long slowlogLen();\n\n  List<Slowlog> slowlogGet();\n\n  List<Slowlog> slowlogGet(long entries);\n\n  Long objectRefcount(String string);\n\n  String objectEncoding(String string);\n\n  Long objectIdletime(String string);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/commands/BasicCommands.java",
    "content": "package redis.clients.jedis.commands;\n\nimport redis.clients.jedis.DebugParams;\n\npublic interface BasicCommands {\n\n  String ping();\n\n  String quit();\n\n  String flushDB();\n\n  Long dbSize();\n\n  String select(int index);\n\n  String flushAll();\n\n  String auth(String password);\n\n  String save();\n\n  String bgsave();\n\n  String bgrewriteaof();\n\n  Long lastsave();\n\n  String shutdown();\n\n  String info();\n\n  String info(String section);\n\n  String slaveof(String host, int port);\n\n  String slaveofNoOne();\n\n  int getDB();\n\n  String debug(DebugParams params);\n\n  String configResetStat();\n\n  Long waitReplicas(int replicas, long timeout);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/commands/BasicRedisPipeline.java",
    "content": "package redis.clients.jedis.commands;\n\nimport redis.clients.jedis.Response;\n\nimport java.util.List;\n\n/**\n * Pipelined responses for all of the low level, non key related commands\n */\npublic interface BasicRedisPipeline {\n\n  Response<String> bgrewriteaof();\n\n  Response<String> bgsave();\n\n  Response<List<String>> configGet(String pattern);\n\n  Response<String> configSet(String parameter, String value);\n\n  Response<String> configResetStat();\n\n  Response<String> save();\n\n  Response<Long> lastsave();\n\n  Response<String> flushDB();\n\n  Response<String> flushAll();\n\n  Response<String> info();\n\n  Response<List<String>> time();\n\n  Response<Long> dbSize();\n\n  Response<String> shutdown();\n\n  Response<String> ping();\n\n  Response<String> select(int index);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/commands/BinaryJedisClusterCommands.java",
    "content": "package redis.clients.jedis.commands;\n\nimport redis.clients.jedis.*;\nimport redis.clients.jedis.params.geo.GeoRadiusParam;\nimport redis.clients.jedis.params.set.SetParams;\nimport redis.clients.jedis.params.sortedset.ZAddParams;\nimport redis.clients.jedis.params.sortedset.ZIncrByParams;\n\nimport java.util.Collection;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\npublic interface BinaryJedisClusterCommands {\n  String set(byte[] key, byte[] value);\n\n  String set(byte[] key, byte[] value, SetParams params);\n\n  byte[] get(byte[] key);\n\n  Boolean exists(byte[] key);\n\n  Long persist(byte[] key);\n\n  String type(byte[] key);\n\n  Long expire(byte[] key, int seconds);\n\n  Long pexpire(byte[] key, final long milliseconds);\n\n  Long expireAt(byte[] key, long unixTime);\n\n  Long pexpireAt(byte[] key, long millisecondsTimestamp);\n\n  Long ttl(byte[] key);\n\n  Boolean setbit(byte[] key, long offset, boolean value);\n\n  Boolean setbit(byte[] key, long offset, byte[] value);\n\n  Boolean getbit(byte[] key, long offset);\n\n  Long setrange(byte[] key, long offset, byte[] value);\n\n  byte[] getrange(byte[] key, long startOffset, long endOffset);\n\n  byte[] getSet(byte[] key, byte[] value);\n\n  Long setnx(byte[] key, byte[] value);\n\n  String setex(byte[] key, int seconds, byte[] value);\n\n  Long decrBy(byte[] key, long integer);\n\n  Long decr(byte[] key);\n\n  Long incrBy(byte[] key, long integer);\n\n  Double incrByFloat(byte[] key, double value);\n\n  Long incr(byte[] key);\n\n  Long append(byte[] key, byte[] value);\n\n  byte[] substr(byte[] key, int start, int end);\n\n  Long hset(byte[] key, byte[] field, byte[] value);\n\n  byte[] hget(byte[] key, byte[] field);\n\n  Long hsetnx(byte[] key, byte[] field, byte[] value);\n\n  String hmset(byte[] key, Map<byte[], byte[]> hash);\n\n  List<byte[]> hmget(byte[] key, byte[]... fields);\n\n  Long hincrBy(byte[] key, byte[] field, long value);\n\n  Double hincrByFloat(byte[] key, byte[] field, double value);\n\n  Boolean hexists(byte[] key, byte[] field);\n\n  Long hdel(byte[] key, byte[]... field);\n\n  Long hlen(byte[] key);\n\n  Set<byte[]> hkeys(byte[] key);\n\n  Collection<byte[]> hvals(byte[] key);\n\n  Map<byte[], byte[]> hgetAll(byte[] key);\n\n  Long rpush(byte[] key, byte[]... args);\n\n  Long lpush(byte[] key, byte[]... args);\n\n  Long llen(byte[] key);\n\n  List<byte[]> lrange(byte[] key, long start, long end);\n\n  String ltrim(byte[] key, long start, long end);\n\n  byte[] lindex(byte[] key, long index);\n\n  String lset(byte[] key, long index, byte[] value);\n\n  Long lrem(byte[] key, long count, byte[] value);\n\n  byte[] lpop(byte[] key);\n\n  byte[] rpop(byte[] key);\n\n  Long sadd(byte[] key, byte[]... member);\n\n  Set<byte[]> smembers(byte[] key);\n\n  Long srem(byte[] key, byte[]... member);\n\n  byte[] spop(byte[] key);\n\n  Set<byte[]> spop(byte[] key, long count);\n\n  Long scard(byte[] key);\n\n  Boolean sismember(byte[] key, byte[] member);\n\n  byte[] srandmember(byte[] key);\n\n  List<byte[]> srandmember(final byte[] key, final int count);\n\n  Long strlen(byte[] key);\n\n  Long zadd(byte[] key, double score, byte[] member);\n\n  Long zadd(byte[] key, double score, byte[] member, ZAddParams params);\n\n  Long zadd(byte[] key, Map<byte[], Double> scoreMembers);\n\n  Long zadd(byte[] key, Map<byte[], Double> scoreMembers, ZAddParams params);\n\n  Set<byte[]> zrange(byte[] key, long start, long end);\n\n  Long zrem(byte[] key, byte[]... member);\n\n  Double zincrby(byte[] key, double score, byte[] member);\n\n  Double zincrby(byte[] key, double score, byte[] member, ZIncrByParams params);\n\n  Long zrank(byte[] key, byte[] member);\n\n  Long zrevrank(byte[] key, byte[] member);\n\n  Set<byte[]> zrevrange(byte[] key, long start, long end);\n\n  Set<Tuple> zrangeWithScores(byte[] key, long start, long end);\n\n  Set<Tuple> zrevrangeWithScores(byte[] key, long start, long end);\n\n  Long zcard(byte[] key);\n\n  Double zscore(byte[] key, byte[] member);\n\n  List<byte[]> sort(byte[] key);\n\n  List<byte[]> sort(byte[] key, SortingParams sortingParameters);\n\n  Long zcount(byte[] key, double min, double max);\n\n  Long zcount(byte[] key, byte[] min, byte[] max);\n\n  Set<byte[]> zrangeByScore(byte[] key, double min, double max);\n\n  Set<byte[]> zrangeByScore(byte[] key, byte[] min, byte[] max);\n\n  Set<byte[]> zrevrangeByScore(byte[] key, double max, double min);\n\n  Set<byte[]> zrangeByScore(byte[] key, double min, double max, int offset, int count);\n\n  Set<byte[]> zrevrangeByScore(byte[] key, byte[] max, byte[] min);\n\n  Set<byte[]> zrangeByScore(byte[] key, byte[] min, byte[] max, int offset, int count);\n\n  Set<byte[]> zrevrangeByScore(byte[] key, double max, double min, int offset, int count);\n\n  Set<Tuple> zrangeByScoreWithScores(byte[] key, double min, double max);\n\n  Set<Tuple> zrevrangeByScoreWithScores(byte[] key, double max, double min);\n\n  Set<Tuple> zrangeByScoreWithScores(byte[] key, double min, double max, int offset, int count);\n\n  Set<byte[]> zrevrangeByScore(byte[] key, byte[] max, byte[] min, int offset, int count);\n\n  Set<Tuple> zrangeByScoreWithScores(byte[] key, byte[] min, byte[] max);\n\n  Set<Tuple> zrevrangeByScoreWithScores(byte[] key, byte[] max, byte[] min);\n\n  Set<Tuple> zrangeByScoreWithScores(byte[] key, byte[] min, byte[] max, int offset, int count);\n\n  Set<Tuple> zrevrangeByScoreWithScores(byte[] key, double max, double min, int offset, int count);\n\n  Set<Tuple> zrevrangeByScoreWithScores(byte[] key, byte[] max, byte[] min, int offset, int count);\n\n  Long zremrangeByRank(byte[] key, long start, long end);\n\n  Long zremrangeByScore(byte[] key, double start, double end);\n\n  Long zremrangeByScore(byte[] key, byte[] start, byte[] end);\n\n  Long zlexcount(final byte[] key, final byte[] min, final byte[] max);\n\n  Set<byte[]> zrangeByLex(final byte[] key, final byte[] min, final byte[] max);\n\n  Set<byte[]> zrangeByLex(final byte[] key, final byte[] min, final byte[] max, int offset,\n      int count);\n\n  Set<byte[]> zrevrangeByLex(final byte[] key, final byte[] max, final byte[] min);\n\n  Set<byte[]> zrevrangeByLex(final byte[] key, final byte[] max, final byte[] min, int offset,\n      int count);\n\n  Long zremrangeByLex(final byte[] key, final byte[] min, final byte[] max);\n\n  Long linsert(byte[] key, BinaryClient.LIST_POSITION where, byte[] pivot, byte[] value);\n\n  Long lpushx(byte[] key, byte[]... arg);\n\n  Long rpushx(byte[] key, byte[]... arg);\n\n  Long del(byte[] key);\n\n  byte[] echo(byte[] arg);\n\n  Long bitcount(final byte[] key);\n\n  Long bitcount(final byte[] key, long start, long end);\n\n  Long pfadd(final byte[] key, final byte[]... elements);\n\n  long pfcount(final byte[] key);\n\n  // Geo Commands\n\n  Long geoadd(byte[] key, double longitude, double latitude, byte[] member);\n\n  Long geoadd(byte[] key, Map<byte[], GeoCoordinate> memberCoordinateMap);\n\n  Double geodist(byte[] key, byte[] member1, byte[] member2);\n\n  Double geodist(byte[] key, byte[] member1, byte[] member2, GeoUnit unit);\n\n  List<byte[]> geohash(byte[] key, byte[]... members);\n\n  List<GeoCoordinate> geopos(byte[] key, byte[]... members);\n\n  List<GeoRadiusResponse> georadius(byte[] key, double longitude, double latitude, double radius,\n      GeoUnit unit);\n\n  List<GeoRadiusResponse> georadius(byte[] key, double longitude, double latitude, double radius,\n      GeoUnit unit, GeoRadiusParam param);\n\n  List<GeoRadiusResponse> georadiusByMember(byte[] key, byte[] member, double radius, GeoUnit unit);\n\n  List<GeoRadiusResponse> georadiusByMember(byte[] key, byte[] member, double radius, GeoUnit unit,\n      GeoRadiusParam param);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/commands/BinaryJedisCommands.java",
    "content": "package redis.clients.jedis.commands;\n\nimport java.util.Collection;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\nimport redis.clients.jedis.*;\nimport redis.clients.jedis.params.geo.GeoRadiusParam;\nimport redis.clients.jedis.params.set.SetParams;\nimport redis.clients.jedis.params.sortedset.ZAddParams;\nimport redis.clients.jedis.params.sortedset.ZIncrByParams;\n\n/**\n * Common interface for sharded and non-sharded BinaryJedis\n */\npublic interface BinaryJedisCommands {\n  String set(byte[] key, byte[] value);\n\n  String set(byte[] key, byte[] value, SetParams params);\n\n  byte[] get(byte[] key);\n\n  Boolean exists(byte[] key);\n\n  Long persist(byte[] key);\n\n  String type(byte[] key);\n\n  Long expire(byte[] key, int seconds);\n\n  Long pexpire(byte[] key, final long milliseconds);\n\n  Long expireAt(byte[] key, long unixTime);\n\n  Long pexpireAt(byte[] key, long millisecondsTimestamp);\n\n  Long ttl(byte[] key);\n\n  Boolean setbit(byte[] key, long offset, boolean value);\n\n  Boolean setbit(byte[] key, long offset, byte[] value);\n\n  Boolean getbit(byte[] key, long offset);\n\n  Long setrange(byte[] key, long offset, byte[] value);\n\n  byte[] getrange(byte[] key, long startOffset, long endOffset);\n\n  byte[] getSet(byte[] key, byte[] value);\n\n  Long setnx(byte[] key, byte[] value);\n\n  String setex(byte[] key, int seconds, byte[] value);\n\n  Long decrBy(byte[] key, long integer);\n\n  Long decr(byte[] key);\n\n  Long incrBy(byte[] key, long integer);\n\n  Double incrByFloat(byte[] key, double value);\n\n  Long incr(byte[] key);\n\n  Long append(byte[] key, byte[] value);\n\n  byte[] substr(byte[] key, int start, int end);\n\n  Long hset(byte[] key, byte[] field, byte[] value);\n\n  byte[] hget(byte[] key, byte[] field);\n\n  Long hsetnx(byte[] key, byte[] field, byte[] value);\n\n  String hmset(byte[] key, Map<byte[], byte[]> hash);\n\n  List<byte[]> hmget(byte[] key, byte[]... fields);\n\n  Long hincrBy(byte[] key, byte[] field, long value);\n\n  Double hincrByFloat(byte[] key, byte[] field, double value);\n\n  Boolean hexists(byte[] key, byte[] field);\n\n  Long hdel(byte[] key, byte[]... field);\n\n  Long hlen(byte[] key);\n\n  Set<byte[]> hkeys(byte[] key);\n\n  Collection<byte[]> hvals(byte[] key);\n\n  Map<byte[], byte[]> hgetAll(byte[] key);\n\n  Long rpush(byte[] key, byte[]... args);\n\n  Long lpush(byte[] key, byte[]... args);\n\n  Long llen(byte[] key);\n\n  List<byte[]> lrange(byte[] key, long start, long end);\n\n  String ltrim(byte[] key, long start, long end);\n\n  byte[] lindex(byte[] key, long index);\n\n  String lset(byte[] key, long index, byte[] value);\n\n  Long lrem(byte[] key, long count, byte[] value);\n\n  byte[] lpop(byte[] key);\n\n  byte[] rpop(byte[] key);\n\n  Long sadd(byte[] key, byte[]... member);\n\n  Set<byte[]> smembers(byte[] key);\n\n  Long srem(byte[] key, byte[]... member);\n\n  byte[] spop(byte[] key);\n\n  Set<byte[]> spop(byte[] key, long count);\n\n  Long scard(byte[] key);\n\n  Boolean sismember(byte[] key, byte[] member);\n\n  byte[] srandmember(byte[] key);\n\n  List<byte[]> srandmember(final byte[] key, final int count);\n\n  Long strlen(byte[] key);\n\n  Long zadd(byte[] key, double score, byte[] member);\n\n  Long zadd(byte[] key, double score, byte[] member, ZAddParams params);\n\n  Long zadd(byte[] key, Map<byte[], Double> scoreMembers);\n\n  Long zadd(byte[] key, Map<byte[], Double> scoreMembers, ZAddParams params);\n\n  Set<byte[]> zrange(byte[] key, long start, long end);\n\n  Long zrem(byte[] key, byte[]... member);\n\n  Double zincrby(byte[] key, double score, byte[] member);\n\n  Double zincrby(byte[] key, double score, byte[] member, ZIncrByParams params);\n\n  Long zrank(byte[] key, byte[] member);\n\n  Long zrevrank(byte[] key, byte[] member);\n\n  Set<byte[]> zrevrange(byte[] key, long start, long end);\n\n  Set<Tuple> zrangeWithScores(byte[] key, long start, long end);\n\n  Set<Tuple> zrevrangeWithScores(byte[] key, long start, long end);\n\n  Long zcard(byte[] key);\n\n  Double zscore(byte[] key, byte[] member);\n\n  List<byte[]> sort(byte[] key);\n\n  List<byte[]> sort(byte[] key, SortingParams sortingParameters);\n\n  Long zcount(byte[] key, double min, double max);\n\n  Long zcount(byte[] key, byte[] min, byte[] max);\n\n  Set<byte[]> zrangeByScore(byte[] key, double min, double max);\n\n  Set<byte[]> zrangeByScore(byte[] key, byte[] min, byte[] max);\n\n  Set<byte[]> zrevrangeByScore(byte[] key, double max, double min);\n\n  Set<byte[]> zrangeByScore(byte[] key, double min, double max, int offset, int count);\n\n  Set<byte[]> zrevrangeByScore(byte[] key, byte[] max, byte[] min);\n\n  Set<byte[]> zrangeByScore(byte[] key, byte[] min, byte[] max, int offset, int count);\n\n  Set<byte[]> zrevrangeByScore(byte[] key, double max, double min, int offset, int count);\n\n  Set<Tuple> zrangeByScoreWithScores(byte[] key, double min, double max);\n\n  Set<Tuple> zrevrangeByScoreWithScores(byte[] key, double max, double min);\n\n  Set<Tuple> zrangeByScoreWithScores(byte[] key, double min, double max, int offset, int count);\n\n  Set<byte[]> zrevrangeByScore(byte[] key, byte[] max, byte[] min, int offset, int count);\n\n  Set<Tuple> zrangeByScoreWithScores(byte[] key, byte[] min, byte[] max);\n\n  Set<Tuple> zrevrangeByScoreWithScores(byte[] key, byte[] max, byte[] min);\n\n  Set<Tuple> zrangeByScoreWithScores(byte[] key, byte[] min, byte[] max, int offset, int count);\n\n  Set<Tuple> zrevrangeByScoreWithScores(byte[] key, double max, double min, int offset, int count);\n\n  Set<Tuple> zrevrangeByScoreWithScores(byte[] key, byte[] max, byte[] min, int offset, int count);\n\n  Long zremrangeByRank(byte[] key, long start, long end);\n\n  Long zremrangeByScore(byte[] key, double start, double end);\n\n  Long zremrangeByScore(byte[] key, byte[] start, byte[] end);\n\n  Long zlexcount(final byte[] key, final byte[] min, final byte[] max);\n\n  Set<byte[]> zrangeByLex(final byte[] key, final byte[] min, final byte[] max);\n\n  Set<byte[]> zrangeByLex(final byte[] key, final byte[] min, final byte[] max, int offset,\n      int count);\n\n  Set<byte[]> zrevrangeByLex(final byte[] key, final byte[] max, final byte[] min);\n\n  Set<byte[]> zrevrangeByLex(final byte[] key, final byte[] max, final byte[] min, int offset,\n      int count);\n\n  Long zremrangeByLex(final byte[] key, final byte[] min, final byte[] max);\n\n  Long linsert(byte[] key, BinaryClient.LIST_POSITION where, byte[] pivot, byte[] value);\n\n  Long lpushx(byte[] key, byte[]... arg);\n\n  Long rpushx(byte[] key, byte[]... arg);\n\n  Long del(byte[] key);\n\n  byte[] echo(byte[] arg);\n\n  Long move(byte[] key, int dbIndex);\n\n  Long bitcount(final byte[] key);\n\n  Long bitcount(final byte[] key, long start, long end);\n\n  Long pfadd(final byte[] key, final byte[]... elements);\n\n  long pfcount(final byte[] key);\n\n  // Geo Commands\n\n  Long geoadd(byte[] key, double longitude, double latitude, byte[] member);\n\n  Long geoadd(byte[] key, Map<byte[], GeoCoordinate> memberCoordinateMap);\n\n  Double geodist(byte[] key, byte[] member1, byte[] member2);\n\n  Double geodist(byte[] key, byte[] member1, byte[] member2, GeoUnit unit);\n\n  List<byte[]> geohash(byte[] key, byte[]... members);\n\n  List<GeoCoordinate> geopos(byte[] key, byte[]... members);\n\n  List<GeoRadiusResponse> georadius(byte[] key, double longitude, double latitude, double radius,\n      GeoUnit unit);\n\n  List<GeoRadiusResponse> georadius(byte[] key, double longitude, double latitude, double radius,\n      GeoUnit unit, GeoRadiusParam param);\n\n  List<GeoRadiusResponse> georadiusByMember(byte[] key, byte[] member, double radius, GeoUnit unit);\n\n  List<GeoRadiusResponse> georadiusByMember(byte[] key, byte[] member, double radius, GeoUnit unit,\n      GeoRadiusParam param);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/commands/BinaryRedisPipeline.java",
    "content": "package redis.clients.jedis.commands;\n\nimport redis.clients.jedis.*;\n\nimport redis.clients.jedis.params.geo.GeoRadiusParam;\nimport redis.clients.jedis.params.sortedset.ZAddParams;\nimport redis.clients.jedis.params.sortedset.ZIncrByParams;\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\npublic interface BinaryRedisPipeline {\n  Response<Long> append(byte[] key, byte[] value);\n\n  Response<List<byte[]>> blpop(byte[] arg);\n\n  Response<List<byte[]>> brpop(byte[] arg);\n\n  Response<Long> decr(byte[] key);\n\n  Response<Long> decrBy(byte[] key, long integer);\n\n  Response<Long> del(byte[] keys);\n\n  Response<byte[]> echo(byte[] string);\n\n  Response<Boolean> exists(byte[] key);\n\n  Response<Long> expire(byte[] key, int seconds);\n\n  Response<Long> pexpire(byte[] key, long milliseconds);\n\n  Response<Long> expireAt(byte[] key, long unixTime);\n\n  Response<Long> pexpireAt(byte[] key, long millisecondsTimestamp);\n\n  Response<byte[]> get(byte[] key);\n\n  Response<Boolean> getbit(byte[] key, long offset);\n\n  Response<byte[]> getSet(byte[] key, byte[] value);\n\n  Response<byte[]> getrange(byte[] key, long startOffset, long endOffset);\n\n  Response<Long> hdel(byte[] key, byte[]... field);\n\n  Response<Boolean> hexists(byte[] key, byte[] field);\n\n  Response<byte[]> hget(byte[] key, byte[] field);\n\n  Response<Map<byte[], byte[]>> hgetAll(byte[] key);\n\n  Response<Long> hincrBy(byte[] key, byte[] field, long value);\n\n  Response<Set<byte[]>> hkeys(byte[] key);\n\n  Response<Long> hlen(byte[] key);\n\n  Response<List<byte[]>> hmget(byte[] key, byte[]... fields);\n\n  Response<String> hmset(byte[] key, Map<byte[], byte[]> hash);\n\n  Response<Long> hset(byte[] key, byte[] field, byte[] value);\n\n  Response<Long> hsetnx(byte[] key, byte[] field, byte[] value);\n\n  Response<List<byte[]>> hvals(byte[] key);\n\n  Response<Long> incr(byte[] key);\n\n  Response<Long> incrBy(byte[] key, long integer);\n\n  Response<byte[]> lindex(byte[] key, long index);\n\n  Response<Long> linsert(byte[] key, BinaryClient.LIST_POSITION where, byte[] pivot, byte[] value);\n\n  Response<Long> llen(byte[] key);\n\n  Response<byte[]> lpop(byte[] key);\n\n  Response<Long> lpush(byte[] key, byte[]... string);\n\n  Response<Long> lpushx(byte[] key, byte[]... bytes);\n\n  Response<List<byte[]>> lrange(byte[] key, long start, long end);\n\n  Response<Long> lrem(byte[] key, long count, byte[] value);\n\n  Response<String> lset(byte[] key, long index, byte[] value);\n\n  Response<String> ltrim(byte[] key, long start, long end);\n\n  Response<Long> move(byte[] key, int dbIndex);\n\n  Response<Long> persist(byte[] key);\n\n  Response<byte[]> rpop(byte[] key);\n\n  Response<Long> rpush(byte[] key, byte[]... string);\n\n  Response<Long> rpushx(byte[] key, byte[]... string);\n\n  Response<Long> sadd(byte[] key, byte[]... member);\n\n  Response<Long> scard(byte[] key);\n\n  Response<String> set(byte[] key, byte[] value);\n\n  Response<Boolean> setbit(byte[] key, long offset, byte[] value);\n\n  Response<Long> setrange(byte[] key, long offset, byte[] value);\n\n  Response<String> setex(byte[] key, int seconds, byte[] value);\n\n  Response<Long> setnx(byte[] key, byte[] value);\n\n  Response<Long> setrange(String key, long offset, String value);\n\n  Response<Set<byte[]>> smembers(byte[] key);\n\n  Response<Boolean> sismember(byte[] key, byte[] member);\n\n  Response<List<byte[]>> sort(byte[] key);\n\n  Response<List<byte[]>> sort(byte[] key, SortingParams sortingParameters);\n\n  Response<byte[]> spop(byte[] key);\n\n  Response<Set<byte[]>> spop(byte[] key, long count);\n\n  Response<byte[]> srandmember(byte[] key);\n\n  Response<Long> srem(byte[] key, byte[]... member);\n\n  Response<Long> strlen(byte[] key);\n\n  Response<String> substr(byte[] key, int start, int end);\n\n  Response<Long> ttl(byte[] key);\n\n  Response<String> type(byte[] key);\n\n  Response<Long> zadd(byte[] key, double score, byte[] member);\n\n  Response<Long> zadd(byte[] key, double score, byte[] member, ZAddParams params);\n\n  Response<Long> zadd(byte[] key, Map<byte[], Double> scoreMembers);\n\n  Response<Long> zadd(byte[] key, Map<byte[], Double> scoreMembers, ZAddParams params);\n\n  Response<Long> zcard(byte[] key);\n\n  Response<Long> zcount(byte[] key, double min, double max);\n\n  Response<Double> zincrby(byte[] key, double score, byte[] member);\n\n  Response<Double> zincrby(byte[] key, double score, byte[] member, ZIncrByParams params);\n\n  Response<Set<byte[]>> zrange(byte[] key, long start, long end);\n\n  Response<Set<byte[]>> zrangeByScore(byte[] key, double min, double max);\n\n  Response<Set<byte[]>> zrangeByScore(byte[] key, byte[] min, byte[] max);\n\n  Response<Set<byte[]>> zrangeByScore(byte[] key, double min, double max, int offset, int count);\n\n  Response<Set<byte[]>> zrangeByScore(byte[] key, byte[] min, byte[] max, int offset, int count);\n\n  Response<Set<Tuple>> zrangeByScoreWithScores(byte[] key, double min, double max);\n\n  Response<Set<Tuple>> zrangeByScoreWithScores(byte[] key, byte[] min, byte[] max);\n\n  Response<Set<Tuple>> zrangeByScoreWithScores(byte[] key, double min, double max, int offset,\n      int count);\n\n  Response<Set<Tuple>> zrangeByScoreWithScores(byte[] key, byte[] min, byte[] max, int offset,\n      int count);\n\n  Response<Set<byte[]>> zrevrangeByScore(byte[] key, double max, double min);\n\n  Response<Set<byte[]>> zrevrangeByScore(byte[] key, byte[] max, byte[] min);\n\n  Response<Set<byte[]>> zrevrangeByScore(byte[] key, double max, double min, int offset, int count);\n\n  Response<Set<byte[]>> zrevrangeByScore(byte[] key, byte[] max, byte[] min, int offset, int count);\n\n  Response<Set<Tuple>> zrevrangeByScoreWithScores(byte[] key, double max, double min);\n\n  Response<Set<Tuple>> zrevrangeByScoreWithScores(byte[] key, byte[] max, byte[] min);\n\n  Response<Set<Tuple>> zrevrangeByScoreWithScores(byte[] key, double max, double min, int offset,\n      int count);\n\n  Response<Set<Tuple>> zrevrangeByScoreWithScores(byte[] key, byte[] max, byte[] min, int offset,\n      int count);\n\n  Response<Set<Tuple>> zrangeWithScores(byte[] key, long start, long end);\n\n  Response<Long> zrank(byte[] key, byte[] member);\n\n  Response<Long> zrem(byte[] key, byte[]... member);\n\n  Response<Long> zremrangeByRank(byte[] key, long start, long end);\n\n  Response<Long> zremrangeByScore(byte[] key, double start, double end);\n\n  Response<Long> zremrangeByScore(byte[] key, byte[] start, byte[] end);\n\n  Response<Set<byte[]>> zrevrange(byte[] key, long start, long end);\n\n  Response<Set<Tuple>> zrevrangeWithScores(byte[] key, long start, long end);\n\n  Response<Long> zrevrank(byte[] key, byte[] member);\n\n  Response<Double> zscore(byte[] key, byte[] member);\n\n  Response<Long> zlexcount(final byte[] key, final byte[] min, final byte[] max);\n\n  Response<Set<byte[]>> zrangeByLex(final byte[] key, final byte[] min, final byte[] max);\n\n  Response<Set<byte[]>> zrangeByLex(final byte[] key, final byte[] min, final byte[] max,\n      int offset, int count);\n\n  Response<Set<byte[]>> zrevrangeByLex(final byte[] key, final byte[] max, final byte[] min);\n\n  Response<Set<byte[]>> zrevrangeByLex(final byte[] key, final byte[] max, final byte[] min,\n      int offset, int count);\n\n  Response<Long> zremrangeByLex(final byte[] key, final byte[] min, final byte[] max);\n\n  Response<Long> bitcount(byte[] key);\n\n  Response<Long> bitcount(byte[] key, long start, long end);\n\n  Response<Long> pfadd(final byte[] key, final byte[]... elements);\n\n  Response<Long> pfcount(final byte[] key);\n\n  // Geo Commands\n\n  Response<Long> geoadd(byte[] key, double longitude, double latitude, byte[] member);\n\n  Response<Long> geoadd(byte[] key, Map<byte[], GeoCoordinate> memberCoordinateMap);\n\n  Response<Double> geodist(byte[] key, byte[] member1, byte[] member2);\n\n  Response<Double> geodist(byte[] key, byte[] member1, byte[] member2, GeoUnit unit);\n\n  Response<List<byte[]>> geohash(byte[] key, byte[]... members);\n\n  Response<List<GeoCoordinate>> geopos(byte[] key, byte[]... members);\n\n  Response<List<GeoRadiusResponse>> georadius(byte[] key, double longitude, double latitude,\n      double radius, GeoUnit unit);\n\n  Response<List<GeoRadiusResponse>> georadius(byte[] key, double longitude, double latitude,\n      double radius, GeoUnit unit, GeoRadiusParam param);\n\n  Response<List<GeoRadiusResponse>> georadiusByMember(byte[] key, byte[] member, double radius,\n      GeoUnit unit);\n\n  Response<List<GeoRadiusResponse>> georadiusByMember(byte[] key, byte[] member, double radius,\n      GeoUnit unit, GeoRadiusParam param);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/commands/BinaryScriptingCommands.java",
    "content": "package redis.clients.jedis.commands;\n\nimport java.util.List;\n\npublic interface BinaryScriptingCommands {\n\n  Object eval(byte[] script, byte[] keyCount, byte[]... params);\n\n  Object eval(byte[] script, int keyCount, byte[]... params);\n\n  Object eval(byte[] script, List<byte[]> keys, List<byte[]> args);\n\n  Object eval(byte[] script);\n\n  Object evalsha(byte[] script);\n\n  Object evalsha(byte[] sha1, List<byte[]> keys, List<byte[]> args);\n\n  Object evalsha(byte[] sha1, int keyCount, byte[]... params);\n\n  // TODO: should be Boolean, add singular version\n  List<Long> scriptExists(byte[]... sha1);\n\n  byte[] scriptLoad(byte[] script);\n\n  String scriptFlush();\n\n  String scriptKill();\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/commands/BinaryScriptingCommandsPipeline.java",
    "content": "package redis.clients.jedis.commands;\n\nimport redis.clients.jedis.Response;\n\nimport java.util.List;\n\npublic interface BinaryScriptingCommandsPipeline {\n\n  Response<Object> eval(byte[] script, byte[] keyCount, byte[]... params);\n\n  Response<Object> eval(byte[] script, int keyCount, byte[]... params);\n\n  Response<Object> eval(byte[] script, List<byte[]> keys, List<byte[]> args);\n\n  Response<Object> eval(byte[] script);\n\n  Response<Object> evalsha(byte[] script);\n\n  Response<Object> evalsha(byte[] sha1, List<byte[]> keys, List<byte[]> args);\n\n  Response<Object> evalsha(byte[] sha1, int keyCount, byte[]... params);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/commands/ClusterCommands.java",
    "content": "package redis.clients.jedis.commands;\n\nimport java.util.List;\n\nimport redis.clients.jedis.JedisCluster.Reset;\n\npublic interface ClusterCommands {\n  String clusterNodes();\n\n  String clusterMeet(final String ip, final int port);\n\n  String clusterAddSlots(final int... slots);\n\n  String clusterDelSlots(final int... slots);\n\n  String clusterInfo();\n\n  List<String> clusterGetKeysInSlot(final int slot, final int count);\n\n  String clusterSetSlotNode(final int slot, final String nodeId);\n\n  String clusterSetSlotMigrating(final int slot, final String nodeId);\n\n  String clusterSetSlotImporting(final int slot, final String nodeId);\n\n  String clusterSetSlotStable(final int slot);\n\n  String clusterForget(final String nodeId);\n\n  String clusterFlushSlots();\n\n  Long clusterKeySlot(final String key);\n\n  Long clusterCountKeysInSlot(final int slot);\n\n  String clusterSaveConfig();\n\n  String clusterReplicate(final String nodeId);\n\n  List<String> clusterSlaves(final String nodeId);\n\n  String clusterFailover();\n\n  List<Object> clusterSlots();\n\n  String clusterReset(Reset resetType);\n\n  String readonly();\n\n  String clusterFailoverForce();\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/commands/ClusterPipeline.java",
    "content": "package redis.clients.jedis.commands;\n\nimport redis.clients.jedis.Response;\n\nimport java.util.List;\n\npublic interface ClusterPipeline {\n  Response<String> clusterNodes();\n\n  Response<String> clusterMeet(final String ip, final int port);\n\n  Response<String> clusterAddSlots(final int... slots);\n\n  Response<String> clusterDelSlots(final int... slots);\n\n  Response<String> clusterInfo();\n\n  Response<List<String>> clusterGetKeysInSlot(final int slot, final int count);\n\n  Response<String> clusterSetSlotNode(final int slot, final String nodeId);\n\n  Response<String> clusterSetSlotMigrating(final int slot, final String nodeId);\n\n  Response<String> clusterSetSlotImporting(final int slot, final String nodeId);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/commands/Commands.java",
    "content": "package redis.clients.jedis.commands;\n\nimport java.util.Map;\n\nimport redis.clients.jedis.BinaryClient.LIST_POSITION;\nimport redis.clients.jedis.BitOP;\nimport redis.clients.jedis.ScanParams;\nimport redis.clients.jedis.SortingParams;\nimport redis.clients.jedis.ZParams;\nimport redis.clients.jedis.params.set.SetParams;\nimport redis.clients.jedis.params.sortedset.ZAddParams;\nimport redis.clients.jedis.params.sortedset.ZIncrByParams;\n\npublic interface Commands {\n\n  void set(final String key, final String value);\n\n  void set(final String key, final String value, SetParams params);\n\n  void get(final String key);\n\n  void exists(final String key);\n\n  void exists(final String... keys);\n\n  void del(final String... keys);\n\n  void type(final String key);\n\n  void keys(final String pattern);\n\n  void rename(final String oldkey, final String newkey);\n\n  void renamenx(final String oldkey, final String newkey);\n\n  void expire(final String key, final int seconds);\n\n  void expireAt(final String key, final long unixTime);\n\n  void ttl(final String key);\n\n  void setbit(String key, long offset, boolean value);\n\n  void setbit(String key, long offset, String value);\n\n  void getbit(String key, long offset);\n\n  void setrange(String key, long offset, String value);\n\n  void getrange(String key, long startOffset, long endOffset);\n\n  void move(final String key, final int dbIndex);\n\n  void getSet(final String key, final String value);\n\n  void mget(final String... keys);\n\n  void setnx(final String key, final String value);\n\n  void setex(final String key, final int seconds, final String value);\n\n  void mset(final String... keysvalues);\n\n  void msetnx(final String... keysvalues);\n\n  void decrBy(final String key, final long integer);\n\n  void decr(final String key);\n\n  void incrBy(final String key, final long integer);\n\n  void incrByFloat(final String key, final double value);\n\n  void incr(final String key);\n\n  void append(final String key, final String value);\n\n  void substr(final String key, final int start, final int end);\n\n  void hset(final String key, final String field, final String value);\n\n  void hget(final String key, final String field);\n\n  void hsetnx(final String key, final String field, final String value);\n\n  void hmset(final String key, final Map<String, String> hash);\n\n  void hmget(final String key, final String... fields);\n\n  void hincrBy(final String key, final String field, final long value);\n\n  void hincrByFloat(final String key, final String field, final double value);\n\n  void hexists(final String key, final String field);\n\n  void hdel(final String key, final String... fields);\n\n  void hlen(final String key);\n\n  void hkeys(final String key);\n\n  void hvals(final String key);\n\n  void hgetAll(final String key);\n\n  void rpush(final String key, final String... strings);\n\n  void lpush(final String key, final String... strings);\n\n  void llen(final String key);\n\n  void lrange(final String key, final long start, final long end);\n\n  void ltrim(final String key, final long start, final long end);\n\n  void lindex(final String key, final long index);\n\n  void lset(final String key, final long index, final String value);\n\n  void lrem(final String key, final long count, final String value);\n\n  void lpop(final String key);\n\n  void rpop(final String key);\n\n  void rpoplpush(final String srckey, final String dstkey);\n\n  void sadd(final String key, final String... members);\n\n  void smembers(final String key);\n\n  void srem(final String key, final String... member);\n\n  void spop(final String key);\n\n  void spop(final String key, final long count);\n\n  void smove(final String srckey, final String dstkey, final String member);\n\n  void scard(final String key);\n\n  void sismember(final String key, final String member);\n\n  void sinter(final String... keys);\n\n  void sinterstore(final String dstkey, final String... keys);\n\n  void sunion(final String... keys);\n\n  void sunionstore(final String dstkey, final String... keys);\n\n  void sdiff(final String... keys);\n\n  void sdiffstore(final String dstkey, final String... keys);\n\n  void srandmember(final String key);\n\n  void zadd(final String key, final double score, final String member);\n\n  void zadd(final String key, final double score, final String member, final ZAddParams params);\n\n  void zadd(final String key, final Map<String, Double> scoreMembers);\n\n  void zadd(final String key, final Map<String, Double> scoreMembers, final ZAddParams params);\n\n  void zrange(final String key, final long start, final long end);\n\n  void zrem(final String key, final String... members);\n\n  void zincrby(final String key, final double score, final String member);\n\n  void zincrby(final String key, final double score, final String member, final ZIncrByParams params);\n\n  void zrank(final String key, final String member);\n\n  void zrevrank(final String key, final String member);\n\n  void zrevrange(final String key, final long start, final long end);\n\n  void zrangeWithScores(final String key, final long start, final long end);\n\n  void zrevrangeWithScores(final String key, final long start, final long end);\n\n  void zcard(final String key);\n\n  void zscore(final String key, final String member);\n\n  void watch(final String... keys);\n\n  void sort(final String key);\n\n  void sort(final String key, final SortingParams sortingParameters);\n\n  void blpop(final String[] args);\n\n  void sort(final String key, final SortingParams sortingParameters, final String dstkey);\n\n  void sort(final String key, final String dstkey);\n\n  void brpop(final String[] args);\n\n  void brpoplpush(final String source, final String destination, final int timeout);\n\n  void zcount(final String key, final double min, final double max);\n\n  void zcount(final String key, final String min, final String max);\n\n  void zrangeByScore(final String key, final double min, final double max);\n\n  void zrangeByScore(final String key, final String min, final String max);\n\n  void zrangeByScore(final String key, final double min, final double max, final int offset,\n      int count);\n\n  void zrangeByScoreWithScores(final String key, final double min, final double max);\n\n  void zrangeByScoreWithScores(final String key, final double min, final double max,\n      final int offset, final int count);\n\n  void zrangeByScoreWithScores(final String key, final String min, final String max);\n\n  void zrangeByScoreWithScores(final String key, final String min, final String max,\n      final int offset, final int count);\n\n  void zrevrangeByScore(final String key, final double max, final double min);\n\n  void zrevrangeByScore(final String key, final String max, final String min);\n\n  void zrevrangeByScore(final String key, final double max, final double min, final int offset,\n      int count);\n\n  void zrevrangeByScoreWithScores(final String key, final double max, final double min);\n\n  void zrevrangeByScoreWithScores(final String key, final double max, final double min,\n      final int offset, final int count);\n\n  void zrevrangeByScoreWithScores(final String key, final String max, final String min);\n\n  void zrevrangeByScoreWithScores(final String key, final String max, final String min,\n      final int offset, final int count);\n\n  void zremrangeByRank(final String key, final long start, final long end);\n\n  void zremrangeByScore(final String key, final double start, final double end);\n\n  void zremrangeByScore(final String key, final String start, final String end);\n\n  void zunionstore(final String dstkey, final String... sets);\n\n  void zunionstore(final String dstkey, final ZParams params, final String... sets);\n\n  void zinterstore(final String dstkey, final String... sets);\n\n  void zinterstore(final String dstkey, final ZParams params, final String... sets);\n\n  void strlen(final String key);\n\n  void lpushx(final String key, final String... string);\n\n  void persist(final String key);\n\n  void rpushx(final String key, final String... string);\n\n  void echo(final String string);\n\n  void linsert(final String key, final LIST_POSITION where, final String pivot, final String value);\n\n  void bgrewriteaof();\n\n  void bgsave();\n\n  void lastsave();\n\n  void save();\n\n  void configSet(final String parameter, final String value);\n\n  void configGet(final String pattern);\n\n  void configResetStat();\n\n  void multi();\n\n  void exec();\n\n  void discard();\n\n  void objectRefcount(String key);\n\n  void objectIdletime(String key);\n\n  void objectEncoding(String key);\n\n  void bitcount(final String key);\n\n  void bitcount(final String key, long start, long end);\n\n  void bitop(BitOP op, final String destKey, String... srcKeys);\n\n  void scan(final String cursor, final ScanParams params);\n\n  void hscan(final String key, final String cursor, final ScanParams params);\n\n  void sscan(final String key, final String cursor, final ScanParams params);\n\n  void zscan(final String key, final String cursor, final ScanParams params);\n\n  void waitReplicas(int replicas, long timeout);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/commands/JedisClusterBinaryScriptingCommands.java",
    "content": "package redis.clients.jedis.commands;\n\nimport java.util.List;\n\npublic interface JedisClusterBinaryScriptingCommands {\n  Object eval(byte[] script, byte[] keyCount, byte[]... params);\n\n  Object eval(byte[] script, int keyCount, byte[]... params);\n\n  Object eval(byte[] script, List<byte[]> keys, List<byte[]> args);\n\n  Object eval(byte[] script, byte[] key);\n\n  Object evalsha(byte[] script, byte[] key);\n\n  Object evalsha(byte[] sha1, List<byte[]> keys, List<byte[]> args);\n\n  Object evalsha(byte[] sha1, int keyCount, byte[]... params);\n\n  List<Long> scriptExists(byte[] key, byte[][] sha1);\n\n  byte[] scriptLoad(byte[] script, byte[] key);\n\n  String scriptFlush(byte[] key);\n\n  String scriptKill(byte[] key);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/commands/JedisClusterCommands.java",
    "content": "package redis.clients.jedis.commands;\n\nimport redis.clients.jedis.*;\nimport redis.clients.jedis.params.geo.GeoRadiusParam;\nimport redis.clients.jedis.params.set.SetParams;\nimport redis.clients.jedis.params.sortedset.ZAddParams;\nimport redis.clients.jedis.params.sortedset.ZIncrByParams;\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\npublic interface JedisClusterCommands {\n  String set(String key, String value);\n\n  String set(String key, String value, SetParams params);\n\n  String get(String key);\n\n  Boolean exists(String key);\n\n  Long persist(String key);\n\n  String type(String key);\n\n  Long expire(String key, int seconds);\n\n  Long pexpire(String key, long milliseconds);\n\n  Long expireAt(String key, long unixTime);\n\n  Long pexpireAt(String key, long millisecondsTimestamp);\n\n  Long ttl(String key);\n\n  Boolean setbit(String key, long offset, boolean value);\n\n  Boolean setbit(String key, long offset, String value);\n\n  Boolean getbit(String key, long offset);\n\n  Long setrange(String key, long offset, String value);\n\n  String getrange(String key, long startOffset, long endOffset);\n\n  String getSet(String key, String value);\n\n  Long setnx(String key, String value);\n\n  String setex(String key, int seconds, String value);\n\n  Long decrBy(String key, long integer);\n\n  Long decr(String key);\n\n  Long incrBy(String key, long integer);\n\n  Double incrByFloat(String key, double value);\n\n  Long incr(String key);\n\n  Long append(String key, String value);\n\n  String substr(String key, int start, int end);\n\n  Long hset(String key, String field, String value);\n\n  String hget(String key, String field);\n\n  Long hsetnx(String key, String field, String value);\n\n  String hmset(String key, Map<String, String> hash);\n\n  List<String> hmget(String key, String... fields);\n\n  Long hincrBy(String key, String field, long value);\n\n  Boolean hexists(String key, String field);\n\n  Long hdel(String key, String... field);\n\n  Long hlen(String key);\n\n  Set<String> hkeys(String key);\n\n  List<String> hvals(String key);\n\n  Map<String, String> hgetAll(String key);\n\n  Long rpush(String key, String... string);\n\n  Long lpush(String key, String... string);\n\n  Long llen(String key);\n\n  List<String> lrange(String key, long start, long end);\n\n  String ltrim(String key, long start, long end);\n\n  String lindex(String key, long index);\n\n  String lset(String key, long index, String value);\n\n  Long lrem(String key, long count, String value);\n\n  String lpop(String key);\n\n  String rpop(String key);\n\n  Long sadd(String key, String... member);\n\n  Set<String> smembers(String key);\n\n  Long srem(String key, String... member);\n\n  String spop(String key);\n\n  Set<String> spop(String key, long count);\n\n  Long scard(String key);\n\n  Boolean sismember(String key, String member);\n\n  String srandmember(String key);\n\n  List<String> srandmember(String key, int count);\n\n  Long strlen(String key);\n\n  Long zadd(String key, double score, String member);\n\n  Long zadd(String key, double score, String member, ZAddParams params);\n\n  Long zadd(String key, Map<String, Double> scoreMembers);\n\n  Long zadd(String key, Map<String, Double> scoreMembers, ZAddParams params);\n\n  Set<String> zrange(String key, long start, long end);\n\n  Long zrem(String key, String... member);\n\n  Double zincrby(String key, double score, String member);\n\n  Double zincrby(String key, double score, String member, ZIncrByParams params);\n\n  Long zrank(String key, String member);\n\n  Long zrevrank(String key, String member);\n\n  Set<String> zrevrange(String key, long start, long end);\n\n  Set<Tuple> zrangeWithScores(String key, long start, long end);\n\n  Set<Tuple> zrevrangeWithScores(String key, long start, long end);\n\n  Long zcard(String key);\n\n  Double zscore(String key, String member);\n\n  List<String> sort(String key);\n\n  List<String> sort(String key, SortingParams sortingParameters);\n\n  Long zcount(String key, double min, double max);\n\n  Long zcount(String key, String min, String max);\n\n  Set<String> zrangeByScore(String key, double min, double max);\n\n  Set<String> zrangeByScore(String key, String min, String max);\n\n  Set<String> zrevrangeByScore(String key, double max, double min);\n\n  Set<String> zrangeByScore(String key, double min, double max, int offset, int count);\n\n  Set<String> zrevrangeByScore(String key, String max, String min);\n\n  Set<String> zrangeByScore(String key, String min, String max, int offset, int count);\n\n  Set<String> zrevrangeByScore(String key, double max, double min, int offset, int count);\n\n  Set<Tuple> zrangeByScoreWithScores(String key, double min, double max);\n\n  Set<Tuple> zrevrangeByScoreWithScores(String key, double max, double min);\n\n  Set<Tuple> zrangeByScoreWithScores(String key, double min, double max, int offset, int count);\n\n  Set<String> zrevrangeByScore(String key, String max, String min, int offset, int count);\n\n  Set<Tuple> zrangeByScoreWithScores(String key, String min, String max);\n\n  Set<Tuple> zrevrangeByScoreWithScores(String key, String max, String min);\n\n  Set<Tuple> zrangeByScoreWithScores(String key, String min, String max, int offset, int count);\n\n  Set<Tuple> zrevrangeByScoreWithScores(String key, double max, double min, int offset, int count);\n\n  Set<Tuple> zrevrangeByScoreWithScores(String key, String max, String min, int offset, int count);\n\n  Long zremrangeByRank(String key, long start, long end);\n\n  Long zremrangeByScore(String key, double start, double end);\n\n  Long zremrangeByScore(String key, String start, String end);\n\n  Long zlexcount(final String key, final String min, final String max);\n\n  Set<String> zrangeByLex(final String key, final String min, final String max);\n\n  Set<String> zrangeByLex(final String key, final String min, final String max, final int offset,\n      final int count);\n\n  Set<String> zrevrangeByLex(final String key, final String max, final String min);\n\n  Set<String> zrevrangeByLex(final String key, final String max, final String min,\n      final int offset, final int count);\n\n  Long zremrangeByLex(final String key, final String min, final String max);\n\n  Long linsert(String key, BinaryClient.LIST_POSITION where, String pivot, String value);\n\n  Long lpushx(String key, String... string);\n\n  Long rpushx(String key, String... string);\n\n  List<String> blpop(int timeout, String key);\n\n  List<String> brpop(int timeout, String key);\n\n  Long del(String key);\n\n  String echo(String string);\n\n  Long bitcount(final String key);\n\n  Long bitcount(final String key, long start, long end);\n\n  ScanResult<Map.Entry<String, String>> hscan(final String key, final String cursor);\n\n  ScanResult<String> sscan(final String key, final String cursor);\n\n  ScanResult<Tuple> zscan(final String key, final String cursor);\n\n  Long pfadd(final String key, final String... elements);\n\n  long pfcount(final String key);\n\n  // Geo Commands\n\n  Long geoadd(String key, double longitude, double latitude, String member);\n\n  Long geoadd(String key, Map<String, GeoCoordinate> memberCoordinateMap);\n\n  Double geodist(String key, String member1, String member2);\n\n  Double geodist(String key, String member1, String member2, GeoUnit unit);\n\n  List<String> geohash(String key, String... members);\n\n  List<GeoCoordinate> geopos(String key, String... members);\n\n  List<GeoRadiusResponse> georadius(String key, double longitude, double latitude, double radius,\n      GeoUnit unit);\n\n  List<GeoRadiusResponse> georadius(String key, double longitude, double latitude, double radius,\n      GeoUnit unit, GeoRadiusParam param);\n\n  List<GeoRadiusResponse> georadiusByMember(String key, String member, double radius, GeoUnit unit);\n\n  List<GeoRadiusResponse> georadiusByMember(String key, String member, double radius, GeoUnit unit,\n      GeoRadiusParam param);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/commands/JedisClusterScriptingCommands.java",
    "content": "package redis.clients.jedis.commands;\n\nimport java.util.List;\n\npublic interface JedisClusterScriptingCommands {\n  Object eval(String script, int keyCount, String... params);\n\n  Object eval(String script, List<String> keys, List<String> args);\n\n  Object eval(String script, String key);\n\n  Object evalsha(String script, String key);\n\n  Object evalsha(String sha1, List<String> keys, List<String> args);\n\n  Object evalsha(String sha1, int keyCount, String... params);\n\n  Boolean scriptExists(String sha1, String key);\n\n  List<Boolean> scriptExists(String key, String... sha1);\n\n  String scriptLoad(String script, String key);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/commands/JedisCommands.java",
    "content": "package redis.clients.jedis.commands;\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\nimport redis.clients.jedis.*;\nimport redis.clients.jedis.params.geo.GeoRadiusParam;\nimport redis.clients.jedis.params.set.SetParams;\nimport redis.clients.jedis.params.sortedset.ZAddParams;\nimport redis.clients.jedis.params.sortedset.ZIncrByParams;\n\n/**\n * Common interface for sharded and non-sharded Jedis\n */\npublic interface JedisCommands {\n  String set(String key, String value);\n\n  String set(String key, String value, SetParams params);\n\n  String get(String key);\n\n  Boolean exists(String key);\n\n  Long persist(String key);\n\n  String type(String key);\n\n  Long expire(String key, int seconds);\n\n  Long pexpire(String key, long milliseconds);\n\n  Long expireAt(String key, long unixTime);\n\n  Long pexpireAt(String key, long millisecondsTimestamp);\n\n  Long ttl(String key);\n\n  Long pttl(final String key);\n\n  Boolean setbit(String key, long offset, boolean value);\n\n  Boolean setbit(String key, long offset, String value);\n\n  Boolean getbit(String key, long offset);\n\n  Long setrange(String key, long offset, String value);\n\n  String getrange(String key, long startOffset, long endOffset);\n\n  String getSet(String key, String value);\n\n  Long setnx(String key, String value);\n\n  String setex(String key, int seconds, String value);\n\n  String psetex(final String key, final long milliseconds, final String value);\n\n  Long decrBy(String key, long integer);\n\n  Long decr(String key);\n\n  Long incrBy(String key, long integer);\n\n  Double incrByFloat(String key, double value);\n\n  Long incr(String key);\n\n  Long append(String key, String value);\n\n  String substr(String key, int start, int end);\n\n  Long hset(String key, String field, String value);\n\n  String hget(String key, String field);\n\n  Long hsetnx(String key, String field, String value);\n\n  String hmset(String key, Map<String, String> hash);\n\n  List<String> hmget(String key, String... fields);\n\n  Long hincrBy(String key, String field, long value);\n\n  Double hincrByFloat(final String key, final String field, final double value);\n\n  Boolean hexists(String key, String field);\n\n  Long hdel(String key, String... field);\n\n  Long hlen(String key);\n\n  Set<String> hkeys(String key);\n\n  List<String> hvals(String key);\n\n  Map<String, String> hgetAll(String key);\n\n  Long rpush(String key, String... string);\n\n  Long lpush(String key, String... string);\n\n  Long llen(String key);\n\n  List<String> lrange(String key, long start, long end);\n\n  String ltrim(String key, long start, long end);\n\n  String lindex(String key, long index);\n\n  String lset(String key, long index, String value);\n\n  Long lrem(String key, long count, String value);\n\n  String lpop(String key);\n\n  String rpop(String key);\n\n  Long sadd(String key, String... member);\n\n  Set<String> smembers(String key);\n\n  Long srem(String key, String... member);\n\n  String spop(String key);\n\n  Set<String> spop(String key, long count);\n\n  Long scard(String key);\n\n  Boolean sismember(String key, String member);\n\n  String srandmember(String key);\n\n  List<String> srandmember(String key, int count);\n\n  Long strlen(String key);\n\n  Long zadd(String key, double score, String member);\n\n  Long zadd(String key, double score, String member, ZAddParams params);\n\n  Long zadd(String key, Map<String, Double> scoreMembers);\n\n  Long zadd(String key, Map<String, Double> scoreMembers, ZAddParams params);\n\n  Set<String> zrange(String key, long start, long end);\n\n  Long zrem(String key, String... member);\n\n  Double zincrby(String key, double score, String member);\n\n  Double zincrby(String key, double score, String member, ZIncrByParams params);\n\n  Long zrank(String key, String member);\n\n  Long zrevrank(String key, String member);\n\n  Set<String> zrevrange(String key, long start, long end);\n\n  Set<Tuple> zrangeWithScores(String key, long start, long end);\n\n  Set<Tuple> zrevrangeWithScores(String key, long start, long end);\n\n  Long zcard(String key);\n\n  Double zscore(String key, String member);\n\n  List<String> sort(String key);\n\n  List<String> sort(String key, SortingParams sortingParameters);\n\n  Long zcount(String key, double min, double max);\n\n  Long zcount(String key, String min, String max);\n\n  Set<String> zrangeByScore(String key, double min, double max);\n\n  Set<String> zrangeByScore(String key, String min, String max);\n\n  Set<String> zrevrangeByScore(String key, double max, double min);\n\n  Set<String> zrangeByScore(String key, double min, double max, int offset, int count);\n\n  Set<String> zrevrangeByScore(String key, String max, String min);\n\n  Set<String> zrangeByScore(String key, String min, String max, int offset, int count);\n\n  Set<String> zrevrangeByScore(String key, double max, double min, int offset, int count);\n\n  Set<Tuple> zrangeByScoreWithScores(String key, double min, double max);\n\n  Set<Tuple> zrevrangeByScoreWithScores(String key, double max, double min);\n\n  Set<Tuple> zrangeByScoreWithScores(String key, double min, double max, int offset, int count);\n\n  Set<String> zrevrangeByScore(String key, String max, String min, int offset, int count);\n\n  Set<Tuple> zrangeByScoreWithScores(String key, String min, String max);\n\n  Set<Tuple> zrevrangeByScoreWithScores(String key, String max, String min);\n\n  Set<Tuple> zrangeByScoreWithScores(String key, String min, String max, int offset, int count);\n\n  Set<Tuple> zrevrangeByScoreWithScores(String key, double max, double min, int offset, int count);\n\n  Set<Tuple> zrevrangeByScoreWithScores(String key, String max, String min, int offset, int count);\n\n  Long zremrangeByRank(String key, long start, long end);\n\n  Long zremrangeByScore(String key, double start, double end);\n\n  Long zremrangeByScore(String key, String start, String end);\n\n  Long zlexcount(final String key, final String min, final String max);\n\n  Set<String> zrangeByLex(final String key, final String min, final String max);\n\n  Set<String> zrangeByLex(final String key, final String min, final String max, final int offset,\n      final int count);\n\n  Set<String> zrevrangeByLex(final String key, final String max, final String min);\n\n  Set<String> zrevrangeByLex(final String key, final String max, final String min,\n      final int offset, final int count);\n\n  Long zremrangeByLex(final String key, final String min, final String max);\n\n  Long linsert(String key, BinaryClient.LIST_POSITION where, String pivot, String value);\n\n  Long lpushx(String key, String... string);\n\n  Long rpushx(String key, String... string);\n\n  List<String> blpop(int timeout, String key);\n\n  List<String> brpop(int timeout, String key);\n\n  Long del(String key);\n\n  String echo(String string);\n\n  Long move(String key, int dbIndex);\n\n  Long bitcount(final String key);\n\n  Long bitcount(final String key, long start, long end);\n\n  Long bitpos(final String key, final boolean value);\n\n  Long bitpos(final String key, final boolean value, final BitPosParams params);\n\n  ScanResult<Map.Entry<String, String>> hscan(final String key, final String cursor);\n\n  ScanResult<Map.Entry<String, String>> hscan(final String key, final String cursor,\n      final ScanParams params);\n\n  ScanResult<String> sscan(final String key, final String cursor);\n\n  ScanResult<Tuple> zscan(final String key, final String cursor);\n\n  ScanResult<Tuple> zscan(final String key, final String cursor, final ScanParams params);\n\n  ScanResult<String> sscan(final String key, final String cursor, final ScanParams params);\n\n  Long pfadd(final String key, final String... elements);\n\n  long pfcount(final String key);\n\n  // Geo Commands\n\n  Long geoadd(String key, double longitude, double latitude, String member);\n\n  Long geoadd(String key, Map<String, GeoCoordinate> memberCoordinateMap);\n\n  Double geodist(String key, String member1, String member2);\n\n  Double geodist(String key, String member1, String member2, GeoUnit unit);\n\n  List<String> geohash(String key, String... members);\n\n  List<GeoCoordinate> geopos(String key, String... members);\n\n  List<GeoRadiusResponse> georadius(String key, double longitude, double latitude, double radius,\n      GeoUnit unit);\n\n  List<GeoRadiusResponse> georadius(String key, double longitude, double latitude, double radius,\n      GeoUnit unit, GeoRadiusParam param);\n\n  List<GeoRadiusResponse> georadiusByMember(String key, String member, double radius, GeoUnit unit);\n\n  List<GeoRadiusResponse> georadiusByMember(String key, String member, double radius, GeoUnit unit,\n      GeoRadiusParam param);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/commands/MultiKeyBinaryCommands.java",
    "content": "package redis.clients.jedis.commands;\n\nimport redis.clients.jedis.BinaryJedisPubSub;\nimport redis.clients.jedis.BitOP;\nimport redis.clients.jedis.SortingParams;\nimport redis.clients.jedis.ZParams;\n\nimport java.util.List;\nimport java.util.Set;\n\npublic interface MultiKeyBinaryCommands {\n  Long del(byte[]... keys);\n\n  Long exists(byte[]... keys);\n\n  List<byte[]> blpop(int timeout, byte[]... keys);\n\n  List<byte[]> brpop(int timeout, byte[]... keys);\n\n  List<byte[]> blpop(byte[]... args);\n\n  List<byte[]> brpop(byte[]... args);\n\n  Set<byte[]> keys(byte[] pattern);\n\n  List<byte[]> mget(byte[]... keys);\n\n  String mset(byte[]... keysvalues);\n\n  Long msetnx(byte[]... keysvalues);\n\n  String rename(byte[] oldkey, byte[] newkey);\n\n  Long renamenx(byte[] oldkey, byte[] newkey);\n\n  byte[] rpoplpush(byte[] srckey, byte[] dstkey);\n\n  Set<byte[]> sdiff(byte[]... keys);\n\n  Long sdiffstore(byte[] dstkey, byte[]... keys);\n\n  Set<byte[]> sinter(byte[]... keys);\n\n  Long sinterstore(byte[] dstkey, byte[]... keys);\n\n  Long smove(byte[] srckey, byte[] dstkey, byte[] member);\n\n  Long sort(byte[] key, SortingParams sortingParameters, byte[] dstkey);\n\n  Long sort(byte[] key, byte[] dstkey);\n\n  Set<byte[]> sunion(byte[]... keys);\n\n  Long sunionstore(byte[] dstkey, byte[]... keys);\n\n  String watch(byte[]... keys);\n\n  String unwatch();\n\n  Long zinterstore(byte[] dstkey, byte[]... sets);\n\n  Long zinterstore(byte[] dstkey, ZParams params, byte[]... sets);\n\n  Long zunionstore(byte[] dstkey, byte[]... sets);\n\n  Long zunionstore(byte[] dstkey, ZParams params, byte[]... sets);\n\n  byte[] brpoplpush(byte[] source, byte[] destination, int timeout);\n\n  Long publish(byte[] channel, byte[] message);\n\n  void subscribe(BinaryJedisPubSub jedisPubSub, byte[]... channels);\n\n  void psubscribe(BinaryJedisPubSub jedisPubSub, byte[]... patterns);\n\n  byte[] randomBinaryKey();\n\n  Long bitop(BitOP op, final byte[] destKey, byte[]... srcKeys);\n\n  String pfmerge(final byte[] destkey, final byte[]... sourcekeys);\n\n  Long pfcount(byte[]... keys);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/commands/MultiKeyBinaryJedisClusterCommands.java",
    "content": "package redis.clients.jedis.commands;\n\nimport redis.clients.jedis.BinaryJedisPubSub;\nimport redis.clients.jedis.BitOP;\nimport redis.clients.jedis.SortingParams;\nimport redis.clients.jedis.ZParams;\n\nimport java.util.List;\nimport java.util.Set;\n\npublic interface MultiKeyBinaryJedisClusterCommands {\n  Long del(byte[]... keys);\n\n  Long exists(byte[]... keys);\n\n  List<byte[]> blpop(int timeout, byte[]... keys);\n\n  List<byte[]> brpop(int timeout, byte[]... keys);\n\n  List<byte[]> mget(byte[]... keys);\n\n  String mset(byte[]... keysvalues);\n\n  Long msetnx(byte[]... keysvalues);\n\n  String rename(byte[] oldkey, byte[] newkey);\n\n  Long renamenx(byte[] oldkey, byte[] newkey);\n\n  byte[] rpoplpush(byte[] srckey, byte[] dstkey);\n\n  Set<byte[]> sdiff(byte[]... keys);\n\n  Long sdiffstore(byte[] dstkey, byte[]... keys);\n\n  Set<byte[]> sinter(byte[]... keys);\n\n  Long sinterstore(byte[] dstkey, byte[]... keys);\n\n  Long smove(byte[] srckey, byte[] dstkey, byte[] member);\n\n  Long sort(byte[] key, SortingParams sortingParameters, byte[] dstkey);\n\n  Long sort(byte[] key, byte[] dstkey);\n\n  Set<byte[]> sunion(byte[]... keys);\n\n  Long sunionstore(byte[] dstkey, byte[]... keys);\n\n  Long zinterstore(byte[] dstkey, byte[]... sets);\n\n  Long zinterstore(byte[] dstkey, ZParams params, byte[]... sets);\n\n  Long zunionstore(byte[] dstkey, byte[]... sets);\n\n  Long zunionstore(byte[] dstkey, ZParams params, byte[]... sets);\n\n  byte[] brpoplpush(byte[] source, byte[] destination, int timeout);\n\n  Long publish(byte[] channel, byte[] message);\n\n  void subscribe(BinaryJedisPubSub jedisPubSub, byte[]... channels);\n\n  void psubscribe(BinaryJedisPubSub jedisPubSub, byte[]... patterns);\n\n  Long bitop(BitOP op, final byte[] destKey, byte[]... srcKeys);\n\n  String pfmerge(final byte[] destkey, final byte[]... sourcekeys);\n\n  Long pfcount(byte[]... keys);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/commands/MultiKeyBinaryRedisPipeline.java",
    "content": "package redis.clients.jedis.commands;\n\nimport redis.clients.jedis.BitOP;\nimport redis.clients.jedis.Response;\nimport redis.clients.jedis.SortingParams;\nimport redis.clients.jedis.ZParams;\n\nimport java.util.List;\nimport java.util.Set;\n\n/**\n * Multikey related commands (these are split out because they are non-shardable)\n */\npublic interface MultiKeyBinaryRedisPipeline {\n\n  Response<Long> del(byte[]... keys);\n\n  Response<Long> exists(byte[]... keys);\n\n  Response<List<byte[]>> blpop(byte[]... args);\n\n  Response<List<byte[]>> brpop(byte[]... args);\n\n  Response<Set<byte[]>> keys(byte[] pattern);\n\n  Response<List<byte[]>> mget(byte[]... keys);\n\n  Response<String> mset(byte[]... keysvalues);\n\n  Response<Long> msetnx(byte[]... keysvalues);\n\n  Response<String> rename(byte[] oldkey, byte[] newkey);\n\n  Response<Long> renamenx(byte[] oldkey, byte[] newkey);\n\n  Response<byte[]> rpoplpush(byte[] srckey, byte[] dstkey);\n\n  Response<Set<byte[]>> sdiff(byte[]... keys);\n\n  Response<Long> sdiffstore(byte[] dstkey, byte[]... keys);\n\n  Response<Set<byte[]>> sinter(byte[]... keys);\n\n  Response<Long> sinterstore(byte[] dstkey, byte[]... keys);\n\n  Response<Long> smove(byte[] srckey, byte[] dstkey, byte[] member);\n\n  Response<Long> sort(byte[] key, SortingParams sortingParameters, byte[] dstkey);\n\n  Response<Long> sort(byte[] key, byte[] dstkey);\n\n  Response<Set<byte[]>> sunion(byte[]... keys);\n\n  Response<Long> sunionstore(byte[] dstkey, byte[]... keys);\n\n  Response<String> watch(byte[]... keys);\n\n  Response<Long> zinterstore(byte[] dstkey, byte[]... sets);\n\n  Response<Long> zinterstore(byte[] dstkey, ZParams params, byte[]... sets);\n\n  Response<Long> zunionstore(byte[] dstkey, byte[]... sets);\n\n  Response<Long> zunionstore(byte[] dstkey, ZParams params, byte[]... sets);\n\n  Response<byte[]> brpoplpush(byte[] source, byte[] destination, int timeout);\n\n  Response<Long> publish(byte[] channel, byte[] message);\n\n  Response<byte[]> randomKeyBinary();\n\n  Response<Long> bitop(BitOP op, final byte[] destKey, byte[]... srcKeys);\n\n  Response<String> pfmerge(final byte[] destkey, final byte[]... sourcekeys);\n\n  Response<Long> pfcount(final byte[]... keys);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/commands/MultiKeyCommands.java",
    "content": "package redis.clients.jedis.commands;\n\nimport redis.clients.jedis.*;\n\nimport java.util.List;\nimport java.util.Set;\n\npublic interface MultiKeyCommands {\n  Long del(String... keys);\n\n  Long exists(String... keys);\n\n  List<String> blpop(int timeout, String... keys);\n\n  List<String> brpop(int timeout, String... keys);\n\n  List<String> blpop(String... args);\n\n  List<String> brpop(String... args);\n\n  Set<String> keys(String pattern);\n\n  List<String> mget(String... keys);\n\n  String mset(String... keysvalues);\n\n  Long msetnx(String... keysvalues);\n\n  String rename(String oldkey, String newkey);\n\n  Long renamenx(String oldkey, String newkey);\n\n  String rpoplpush(String srckey, String dstkey);\n\n  Set<String> sdiff(String... keys);\n\n  Long sdiffstore(String dstkey, String... keys);\n\n  Set<String> sinter(String... keys);\n\n  Long sinterstore(String dstkey, String... keys);\n\n  Long smove(String srckey, String dstkey, String member);\n\n  Long sort(String key, SortingParams sortingParameters, String dstkey);\n\n  Long sort(String key, String dstkey);\n\n  Set<String> sunion(String... keys);\n\n  Long sunionstore(String dstkey, String... keys);\n\n  String watch(String... keys);\n\n  String unwatch();\n\n  Long zinterstore(String dstkey, String... sets);\n\n  Long zinterstore(String dstkey, ZParams params, String... sets);\n\n  Long zunionstore(String dstkey, String... sets);\n\n  Long zunionstore(String dstkey, ZParams params, String... sets);\n\n  String brpoplpush(String source, String destination, int timeout);\n\n  Long publish(String channel, String message);\n\n  void subscribe(JedisPubSub jedisPubSub, String... channels);\n\n  void psubscribe(JedisPubSub jedisPubSub, String... patterns);\n\n  String randomKey();\n\n  Long bitop(BitOP op, final String destKey, String... srcKeys);\n\n  ScanResult<String> scan(final String cursor);\n\n  ScanResult<String> scan(final String cursor, final ScanParams params);\n\n  String pfmerge(final String destkey, final String... sourcekeys);\n\n  long pfcount(final String... keys);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/commands/MultiKeyCommandsPipeline.java",
    "content": "package redis.clients.jedis.commands;\n\nimport redis.clients.jedis.BitOP;\nimport redis.clients.jedis.Response;\nimport redis.clients.jedis.SortingParams;\nimport redis.clients.jedis.ZParams;\n\nimport java.util.List;\nimport java.util.Set;\n\n/**\n * Multikey related commands (these are split out because they are non-shardable)\n */\npublic interface MultiKeyCommandsPipeline {\n  Response<Long> del(String... keys);\n\n  Response<Long> exists(String... keys);\n\n  Response<List<String>> blpop(String... args);\n\n  Response<List<String>> brpop(String... args);\n\n  Response<Set<String>> keys(String pattern);\n\n  Response<List<String>> mget(String... keys);\n\n  Response<String> mset(String... keysvalues);\n\n  Response<Long> msetnx(String... keysvalues);\n\n  Response<String> rename(String oldkey, String newkey);\n\n  Response<Long> renamenx(String oldkey, String newkey);\n\n  Response<String> rpoplpush(String srckey, String dstkey);\n\n  Response<Set<String>> sdiff(String... keys);\n\n  Response<Long> sdiffstore(String dstkey, String... keys);\n\n  Response<Set<String>> sinter(String... keys);\n\n  Response<Long> sinterstore(String dstkey, String... keys);\n\n  Response<Long> smove(String srckey, String dstkey, String member);\n\n  Response<Long> sort(String key, SortingParams sortingParameters, String dstkey);\n\n  Response<Long> sort(String key, String dstkey);\n\n  Response<Set<String>> sunion(String... keys);\n\n  Response<Long> sunionstore(String dstkey, String... keys);\n\n  Response<String> watch(String... keys);\n\n  Response<Long> zinterstore(String dstkey, String... sets);\n\n  Response<Long> zinterstore(String dstkey, ZParams params, String... sets);\n\n  Response<Long> zunionstore(String dstkey, String... sets);\n\n  Response<Long> zunionstore(String dstkey, ZParams params, String... sets);\n\n  Response<String> brpoplpush(String source, String destination, int timeout);\n\n  Response<Long> publish(String channel, String message);\n\n  Response<String> randomKey();\n\n  Response<Long> bitop(BitOP op, final String destKey, String... srcKeys);\n\n  Response<String> pfmerge(final String destkey, final String... sourcekeys);\n\n  Response<Long> pfcount(final String... keys);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/commands/MultiKeyJedisClusterCommands.java",
    "content": "package redis.clients.jedis.commands;\n\nimport redis.clients.jedis.BitOP;\nimport redis.clients.jedis.JedisPubSub;\nimport redis.clients.jedis.SortingParams;\nimport redis.clients.jedis.ZParams;\n\nimport java.util.List;\nimport java.util.Set;\n\npublic interface MultiKeyJedisClusterCommands {\n  Long del(String... keys);\n\n  Long exists(String... keys);\n\n  List<String> blpop(int timeout, String... keys);\n\n  List<String> brpop(int timeout, String... keys);\n\n  List<String> mget(String... keys);\n\n  String mset(String... keysvalues);\n\n  Long msetnx(String... keysvalues);\n\n  String rename(String oldkey, String newkey);\n\n  Long renamenx(String oldkey, String newkey);\n\n  String rpoplpush(String srckey, String dstkey);\n\n  Set<String> sdiff(String... keys);\n\n  Long sdiffstore(String dstkey, String... keys);\n\n  Set<String> sinter(String... keys);\n\n  Long sinterstore(String dstkey, String... keys);\n\n  Long smove(String srckey, String dstkey, String member);\n\n  Long sort(String key, SortingParams sortingParameters, String dstkey);\n\n  Long sort(String key, String dstkey);\n\n  Set<String> sunion(String... keys);\n\n  Long sunionstore(String dstkey, String... keys);\n\n  Long zinterstore(String dstkey, String... sets);\n\n  Long zinterstore(String dstkey, ZParams params, String... sets);\n\n  Long zunionstore(String dstkey, String... sets);\n\n  Long zunionstore(String dstkey, ZParams params, String... sets);\n\n  String brpoplpush(String source, String destination, int timeout);\n\n  Long publish(String channel, String message);\n\n  void subscribe(JedisPubSub jedisPubSub, String... channels);\n\n  void psubscribe(JedisPubSub jedisPubSub, String... patterns);\n\n  Long bitop(BitOP op, final String destKey, String... srcKeys);\n\n  String pfmerge(final String destkey, final String... sourcekeys);\n\n  long pfcount(final String... keys);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/commands/ProtocolCommand.java",
    "content": "package redis.clients.jedis.commands;\n\npublic interface ProtocolCommand {\n\n  byte[] getRaw();\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/commands/RedisPipeline.java",
    "content": "package redis.clients.jedis.commands;\n\nimport redis.clients.jedis.*;\nimport redis.clients.jedis.params.geo.GeoRadiusParam;\nimport redis.clients.jedis.params.sortedset.ZAddParams;\nimport redis.clients.jedis.params.sortedset.ZIncrByParams;\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\npublic interface RedisPipeline {\n  Response<Long> append(String key, String value);\n\n  Response<List<String>> blpop(String arg);\n\n  Response<List<String>> brpop(String arg);\n\n  Response<Long> decr(String key);\n\n  Response<Long> decrBy(String key, long integer);\n\n  Response<Long> del(String key);\n\n  Response<String> echo(String string);\n\n  Response<Boolean> exists(String key);\n\n  Response<Long> expire(String key, int seconds);\n\n  Response<Long> pexpire(String key, long milliseconds);\n\n  Response<Long> expireAt(String key, long unixTime);\n\n  Response<Long> pexpireAt(String key, long millisecondsTimestamp);\n\n  Response<String> get(String key);\n\n  Response<Boolean> getbit(String key, long offset);\n\n  Response<String> getrange(String key, long startOffset, long endOffset);\n\n  Response<String> getSet(String key, String value);\n\n  Response<Long> hdel(String key, String... field);\n\n  Response<Boolean> hexists(String key, String field);\n\n  Response<String> hget(String key, String field);\n\n  Response<Map<String, String>> hgetAll(String key);\n\n  Response<Long> hincrBy(String key, String field, long value);\n\n  Response<Set<String>> hkeys(String key);\n\n  Response<Long> hlen(String key);\n\n  Response<List<String>> hmget(String key, String... fields);\n\n  Response<String> hmset(String key, Map<String, String> hash);\n\n  Response<Long> hset(String key, String field, String value);\n\n  Response<Long> hsetnx(String key, String field, String value);\n\n  Response<List<String>> hvals(String key);\n\n  Response<Long> incr(String key);\n\n  Response<Long> incrBy(String key, long integer);\n\n  Response<String> lindex(String key, long index);\n\n  Response<Long> linsert(String key, BinaryClient.LIST_POSITION where, String pivot, String value);\n\n  Response<Long> llen(String key);\n\n  Response<String> lpop(String key);\n\n  Response<Long> lpush(String key, String... string);\n\n  Response<Long> lpushx(String key, String... string);\n\n  Response<List<String>> lrange(String key, long start, long end);\n\n  Response<Long> lrem(String key, long count, String value);\n\n  Response<String> lset(String key, long index, String value);\n\n  Response<String> ltrim(String key, long start, long end);\n\n  Response<Long> move(String key, int dbIndex);\n\n  Response<Long> persist(String key);\n\n  Response<String> rpop(String key);\n\n  Response<Long> rpush(String key, String... string);\n\n  Response<Long> rpushx(String key, String... string);\n\n  Response<Long> sadd(String key, String... member);\n\n  Response<Long> scard(String key);\n\n  Response<Boolean> sismember(String key, String member);\n\n  Response<String> set(String key, String value);\n\n  Response<Boolean> setbit(String key, long offset, boolean value);\n\n  Response<String> setex(String key, int seconds, String value);\n\n  Response<Long> setnx(String key, String value);\n\n  Response<Long> setrange(String key, long offset, String value);\n\n  Response<Set<String>> smembers(String key);\n\n  Response<List<String>> sort(String key);\n\n  Response<List<String>> sort(String key, SortingParams sortingParameters);\n\n  Response<String> spop(String key);\n\n  Response<Set<String>> spop(String key, long count);\n\n  Response<String> srandmember(String key);\n\n  Response<Long> srem(String key, String... member);\n\n  Response<Long> strlen(String key);\n\n  Response<String> substr(String key, int start, int end);\n\n  Response<Long> ttl(String key);\n\n  Response<String> type(String key);\n\n  Response<Long> zadd(String key, double score, String member);\n\n  Response<Long> zadd(String key, double score, String member, ZAddParams params);\n\n  Response<Long> zadd(String key, Map<String, Double> scoreMembers);\n\n  Response<Long> zadd(String key, Map<String, Double> scoreMembers, ZAddParams params);\n\n  Response<Long> zcard(String key);\n\n  Response<Long> zcount(String key, double min, double max);\n\n  Response<Double> zincrby(String key, double score, String member);\n\n  Response<Double> zincrby(String key, double score, String member, ZIncrByParams params);\n\n  Response<Set<String>> zrange(String key, long start, long end);\n\n  Response<Set<String>> zrangeByScore(String key, double min, double max);\n\n  Response<Set<String>> zrangeByScore(String key, String min, String max);\n\n  Response<Set<String>> zrangeByScore(String key, double min, double max, int offset, int count);\n\n  Response<Set<Tuple>> zrangeByScoreWithScores(String key, double min, double max);\n\n  Response<Set<Tuple>> zrangeByScoreWithScores(String key, double min, double max, int offset,\n      int count);\n\n  Response<Set<String>> zrevrangeByScore(String key, double max, double min);\n\n  Response<Set<String>> zrevrangeByScore(String key, String max, String min);\n\n  Response<Set<String>> zrevrangeByScore(String key, double max, double min, int offset, int count);\n\n  Response<Set<Tuple>> zrevrangeByScoreWithScores(String key, double max, double min);\n\n  Response<Set<Tuple>> zrevrangeByScoreWithScores(String key, double max, double min, int offset,\n      int count);\n\n  Response<Set<Tuple>> zrangeWithScores(String key, long start, long end);\n\n  Response<Long> zrank(String key, String member);\n\n  Response<Long> zrem(String key, String... member);\n\n  Response<Long> zremrangeByRank(String key, long start, long end);\n\n  Response<Long> zremrangeByScore(String key, double start, double end);\n\n  Response<Set<String>> zrevrange(String key, long start, long end);\n\n  Response<Set<Tuple>> zrevrangeWithScores(String key, long start, long end);\n\n  Response<Long> zrevrank(String key, String member);\n\n  Response<Double> zscore(String key, String member);\n\n  Response<Long> zlexcount(final String key, final String min, final String max);\n\n  Response<Set<String>> zrangeByLex(final String key, final String min, final String max);\n\n  Response<Set<String>> zrangeByLex(final String key, final String min, final String max,\n      final int offset, final int count);\n\n  Response<Set<String>> zrevrangeByLex(final String key, final String max, final String min);\n\n  Response<Set<String>> zrevrangeByLex(final String key, final String max, final String min,\n      final int offset, final int count);\n\n  Response<Long> zremrangeByLex(final String key, final String start, final String end);\n\n  Response<Long> bitcount(String key);\n\n  Response<Long> bitcount(String key, long start, long end);\n\n  Response<Long> pfadd(final String key, final String... elements);\n\n  Response<Long> pfcount(final String key);\n\n  // Geo Commands\n\n  Response<Long> geoadd(String key, double longitude, double latitude, String member);\n\n  Response<Long> geoadd(String key, Map<String, GeoCoordinate> memberCoordinateMap);\n\n  Response<Double> geodist(String key, String member1, String member2);\n\n  Response<Double> geodist(String key, String member1, String member2, GeoUnit unit);\n\n  Response<List<String>> geohash(String key, String... members);\n\n  Response<List<GeoCoordinate>> geopos(String key, String... members);\n\n  Response<List<GeoRadiusResponse>> georadius(String key, double longitude, double latitude,\n      double radius, GeoUnit unit);\n\n  Response<List<GeoRadiusResponse>> georadius(String key, double longitude, double latitude,\n      double radius, GeoUnit unit, GeoRadiusParam param);\n\n  Response<List<GeoRadiusResponse>> georadiusByMember(String key, String member, double radius,\n      GeoUnit unit);\n\n  Response<List<GeoRadiusResponse>> georadiusByMember(String key, String member, double radius,\n      GeoUnit unit, GeoRadiusParam param);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/commands/ScriptingCommands.java",
    "content": "package redis.clients.jedis.commands;\n\nimport java.util.List;\n\npublic interface ScriptingCommands {\n  Object eval(String script, int keyCount, String... params);\n\n  Object eval(String script, List<String> keys, List<String> args);\n\n  Object eval(String script);\n\n  Object evalsha(String script);\n\n  Object evalsha(String sha1, List<String> keys, List<String> args);\n\n  Object evalsha(String sha1, int keyCount, String... params);\n\n  Boolean scriptExists(String sha1);\n\n  List<Boolean> scriptExists(String... sha1);\n\n  String scriptLoad(String script);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/commands/ScriptingCommandsPipeline.java",
    "content": "package redis.clients.jedis.commands;\n\nimport redis.clients.jedis.Response;\n\nimport java.util.List;\n\npublic interface ScriptingCommandsPipeline {\n  Response<Object> eval(String script, int keyCount, String... params);\n\n  Response<Object> eval(String script, List<String> keys, List<String> args);\n\n  Response<Object> eval(String script);\n\n  Response<Object> evalsha(String script);\n\n  Response<Object> evalsha(String sha1, List<String> keys, List<String> args);\n\n  Response<Object> evalsha(String sha1, int keyCount, String... params);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/commands/SentinelCommands.java",
    "content": "package redis.clients.jedis.commands;\n\nimport java.util.List;\nimport java.util.Map;\n\npublic interface SentinelCommands {\n  List<Map<String, String>> sentinelMasters();\n\n  List<String> sentinelGetMasterAddrByName(String masterName);\n\n  Long sentinelReset(String pattern);\n\n  List<Map<String, String>> sentinelSlaves(String masterName);\n\n  String sentinelFailover(String masterName);\n\n  String sentinelMonitor(String masterName, String ip, int port, int quorum);\n\n  String sentinelRemove(String masterName);\n\n  String sentinelSet(String masterName, Map<String, String> parameterMap);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/exceptions/InvalidURIException.java",
    "content": "package redis.clients.jedis.exceptions;\n\npublic class InvalidURIException extends JedisException {\n\n  private static final long serialVersionUID = -781691993326357802L;\n\n  public InvalidURIException(String message) {\n    super(message);\n  }\n\n  public InvalidURIException(Throwable cause) {\n    super(cause);\n  }\n\n  public InvalidURIException(String message, Throwable cause) {\n    super(message, cause);\n  }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/exceptions/JedisAskDataException.java",
    "content": "package redis.clients.jedis.exceptions;\n\nimport redis.clients.jedis.HostAndPort;\n\npublic class JedisAskDataException extends JedisRedirectionException {\n  private static final long serialVersionUID = 3878126572474819403L;\n\n  public JedisAskDataException(Throwable cause, HostAndPort targetHost, int slot) {\n    super(cause, targetHost, slot);\n  }\n\n  public JedisAskDataException(String message, Throwable cause, HostAndPort targetHost, int slot) {\n    super(message, cause, targetHost, slot);\n  }\n\n  public JedisAskDataException(String message, HostAndPort targetHost, int slot) {\n    super(message, targetHost, slot);\n  }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/exceptions/JedisClusterCrossSlotException.java",
    "content": "package redis.clients.jedis.exceptions;\n\npublic class JedisClusterCrossSlotException extends JedisClusterException {\n  private static final long serialVersionUID = -6355518994901704067L;\n\n  public JedisClusterCrossSlotException(Throwable cause) {\n    super(cause);\n  }\n\n  public JedisClusterCrossSlotException(String message, Throwable cause) {\n    super(message, cause);\n  }\n\n  public JedisClusterCrossSlotException(String message) {\n    super(message);\n  }\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/exceptions/JedisClusterException.java",
    "content": "package redis.clients.jedis.exceptions;\n\npublic class JedisClusterException extends JedisDataException {\n  private static final long serialVersionUID = 3878126572474819403L;\n\n  public JedisClusterException(Throwable cause) {\n    super(cause);\n  }\n\n  public JedisClusterException(String message, Throwable cause) {\n    super(message, cause);\n  }\n\n  public JedisClusterException(String message) {\n    super(message);\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/exceptions/JedisClusterMaxRedirectionsException.java",
    "content": "package redis.clients.jedis.exceptions;\n\npublic class JedisClusterMaxRedirectionsException extends JedisDataException {\n  private static final long serialVersionUID = 3878126572474819403L;\n\n  public JedisClusterMaxRedirectionsException(Throwable cause) {\n    super(cause);\n  }\n\n  public JedisClusterMaxRedirectionsException(String message, Throwable cause) {\n    super(message, cause);\n  }\n\n  public JedisClusterMaxRedirectionsException(String message) {\n    super(message);\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/exceptions/JedisConnectionException.java",
    "content": "package redis.clients.jedis.exceptions;\n\npublic class JedisConnectionException extends JedisException {\n  private static final long serialVersionUID = 3878126572474819403L;\n\n  public JedisConnectionException(String message) {\n    super(message);\n  }\n\n  public JedisConnectionException(Throwable cause) {\n    super(cause);\n  }\n\n  public JedisConnectionException(String message, Throwable cause) {\n    super(message, cause);\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/exceptions/JedisDataException.java",
    "content": "package redis.clients.jedis.exceptions;\n\npublic class JedisDataException extends JedisException {\n  private static final long serialVersionUID = 3878126572474819403L;\n\n  public JedisDataException(String message) {\n    super(message);\n  }\n\n  public JedisDataException(Throwable cause) {\n    super(cause);\n  }\n\n  public JedisDataException(String message, Throwable cause) {\n    super(message, cause);\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/exceptions/JedisException.java",
    "content": "package redis.clients.jedis.exceptions;\n\npublic class JedisException extends RuntimeException {\n  private static final long serialVersionUID = -2946266495682282677L;\n\n  public JedisException(String message) {\n    super(message);\n  }\n\n  public JedisException(Throwable e) {\n    super(e);\n  }\n\n  public JedisException(String message, Throwable cause) {\n    super(message, cause);\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/exceptions/JedisMovedDataException.java",
    "content": "package redis.clients.jedis.exceptions;\n\nimport redis.clients.jedis.HostAndPort;\n\npublic class JedisMovedDataException extends JedisRedirectionException {\n  private static final long serialVersionUID = 3878126572474819403L;\n\n  public JedisMovedDataException(String message, HostAndPort targetNode, int slot) {\n    super(message, targetNode, slot);\n  }\n\n  public JedisMovedDataException(Throwable cause, HostAndPort targetNode, int slot) {\n    super(cause, targetNode, slot);\n  }\n\n  public JedisMovedDataException(String message, Throwable cause, HostAndPort targetNode, int slot) {\n    super(message, cause, targetNode, slot);\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/exceptions/JedisRedirectionException.java",
    "content": "package redis.clients.jedis.exceptions;\n\nimport redis.clients.jedis.HostAndPort;\n\npublic class JedisRedirectionException extends JedisDataException {\n  private static final long serialVersionUID = 3878126572474819403L;\n\n  private HostAndPort targetNode;\n  private int slot;\n\n  public JedisRedirectionException(String message, HostAndPort targetNode, int slot) {\n    super(message);\n    this.targetNode = targetNode;\n    this.slot = slot;\n  }\n\n  public JedisRedirectionException(Throwable cause, HostAndPort targetNode, int slot) {\n    super(cause);\n    this.targetNode = targetNode;\n    this.slot = slot;\n  }\n\n  public JedisRedirectionException(String message, Throwable cause, HostAndPort targetNode, int slot) {\n    super(message, cause);\n    this.targetNode = targetNode;\n    this.slot = slot;\n  }\n\n  public HostAndPort getTargetNode() {\n    return targetNode;\n  }\n\n  public int getSlot() {\n    return slot;\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/params/Params.java",
    "content": "package redis.clients.jedis.params;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Map.Entry;\n\nimport redis.clients.util.SafeEncoder;\n\npublic abstract class Params {\n\n  private Map<String, Object> params;\n\n  @SuppressWarnings(\"unchecked\")\n  public <T> T getParam(String name) {\n    if (params == null) return null;\n\n    return (T) params.get(name);\n  }\n\n  public byte[][] getByteParams() {\n    ArrayList<byte[]> byteParams = new ArrayList<byte[]>();\n\n    for (Entry<String, Object> param : params.entrySet()) {\n      byteParams.add(SafeEncoder.encode(param.getKey()));\n      if (param.getValue() != null) {\n        byteParams.add(SafeEncoder.encode(String.valueOf(param.getValue())));\n      }\n    }\n\n    return byteParams.toArray(new byte[byteParams.size()][]);\n  }\n\n  public boolean contains(String name) {\n    if (params == null) return false;\n\n    return params.containsKey(name);\n  }\n\n  protected void addParam(String name, Object value) {\n    if (params == null) {\n      params = new HashMap<String, Object>();\n    }\n    params.put(name, value);\n  }\n\n  protected void addParam(String name) {\n    if (params == null) {\n      params = new HashMap<String, Object>();\n    }\n    params.put(name, null);\n  }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/params/geo/GeoRadiusParam.java",
    "content": "package redis.clients.jedis.params.geo;\n\nimport redis.clients.jedis.Protocol;\nimport redis.clients.jedis.params.Params;\nimport redis.clients.util.SafeEncoder;\n\nimport java.util.ArrayList;\n\npublic class GeoRadiusParam extends Params {\n  private static final String WITHCOORD = \"withcoord\";\n  private static final String WITHDIST = \"withdist\";\n\n  // Do not add WITHHASH since we can't classify result of WITHHASH and WITHDIST,\n  // and WITHHASH is for debugging purposes\n\n  private static final String ASC = \"asc\";\n  private static final String DESC = \"desc\";\n  private static final String COUNT = \"count\";\n\n  private GeoRadiusParam() {\n  }\n\n  public static GeoRadiusParam geoRadiusParam() {\n    return new GeoRadiusParam();\n  }\n\n  public GeoRadiusParam withCoord() {\n    addParam(WITHCOORD);\n    return this;\n  }\n\n  public GeoRadiusParam withDist() {\n    addParam(WITHDIST);\n    return this;\n  }\n\n  public GeoRadiusParam sortAscending() {\n    addParam(ASC);\n    return this;\n  }\n\n  public GeoRadiusParam sortDescending() {\n    addParam(DESC);\n    return this;\n  }\n\n  public GeoRadiusParam count(int count) {\n    if (count > 0) {\n      addParam(COUNT, count);\n    }\n    return this;\n  }\n\n  public byte[][] getByteParams(byte[]... args) {\n    ArrayList<byte[]> byteParams = new ArrayList<byte[]>();\n    for (byte[] arg : args) {\n      byteParams.add(arg);\n    }\n\n    if (contains(WITHCOORD)) {\n      byteParams.add(SafeEncoder.encode(WITHCOORD));\n    }\n    if (contains(WITHDIST)) {\n      byteParams.add(SafeEncoder.encode(WITHDIST));\n    }\n\n    if (contains(COUNT)) {\n      byteParams.add(SafeEncoder.encode(COUNT));\n      byteParams.add(Protocol.toByteArray((Integer) getParam(COUNT)));\n    }\n\n    if (contains(ASC)) {\n      byteParams.add(SafeEncoder.encode(ASC));\n    } else if (contains(DESC)) {\n      byteParams.add(SafeEncoder.encode(DESC));\n    }\n\n    return byteParams.toArray(new byte[byteParams.size()][]);\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/params/set/SetParams.java",
    "content": "package redis.clients.jedis.params.set;\n\nimport java.util.ArrayList;\n\nimport redis.clients.jedis.params.Params;\nimport redis.clients.util.SafeEncoder;\n\npublic class SetParams extends Params {\n\n  private static final String XX = \"xx\";\n  private static final String NX = \"nx\";\n  private static final String PX = \"px\";\n  private static final String EX = \"ex\";\n\n  private SetParams() {\n  }\n\n  public static SetParams setParams() {\n    return new SetParams();\n  }\n\n  /**\n   * Set the specified expire time, in seconds.\n   * @param secondsToExpire\n   * @return SetParams\n   */\n  public SetParams ex(int secondsToExpire) {\n    addParam(EX, secondsToExpire);\n    return this;\n  }\n\n  /**\n   * Set the specified expire time, in milliseconds.\n   * @param millisecondsToExpire\n   * @return SetParams\n   */\n  public SetParams px(long millisecondsToExpire) {\n    addParam(PX, millisecondsToExpire);\n    return this;\n  }\n\n  /**\n   * Only set the key if it does not already exist.\n   * @return SetParams\n   */\n  public SetParams nx() {\n    addParam(NX);\n    return this;\n  }\n\n  /**\n   * Only set the key if it already exist.\n   * @return SetParams\n   */\n  public SetParams xx() {\n    addParam(XX);\n    return this;\n  }\n\n  public byte[][] getByteParams(byte[]... args) {\n    ArrayList<byte[]> byteParams = new ArrayList<byte[]>();\n    for (byte[] arg : args) {\n      byteParams.add(arg);\n    }\n\n    if (contains(NX)) {\n      byteParams.add(SafeEncoder.encode(NX));\n    }\n    if (contains(XX)) {\n      byteParams.add(SafeEncoder.encode(XX));\n    }\n\n    if (contains(EX)) {\n      byteParams.add(SafeEncoder.encode(EX));\n      byteParams.add(SafeEncoder.encode(String.valueOf(getParam(EX))));\n    }\n    if (contains(PX)) {\n      byteParams.add(SafeEncoder.encode(PX));\n      byteParams.add(SafeEncoder.encode(String.valueOf(getParam(PX))));\n    }\n\n    return byteParams.toArray(new byte[byteParams.size()][]);\n  }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/params/sortedset/ZAddParams.java",
    "content": "package redis.clients.jedis.params.sortedset;\n\nimport redis.clients.jedis.params.Params;\nimport redis.clients.util.SafeEncoder;\n\nimport java.util.ArrayList;\n\npublic class ZAddParams extends Params {\n\n  private static final String XX = \"xx\";\n  private static final String NX = \"nx\";\n  private static final String CH = \"ch\";\n\n  private ZAddParams() {\n  }\n\n  public static ZAddParams zAddParams() {\n    return new ZAddParams();\n  }\n\n  /**\n   * Only set the key if it does not already exist.\n   * @return ZAddParams\n   */\n  public ZAddParams nx() {\n    addParam(NX);\n    return this;\n  }\n\n  /**\n   * Only set the key if it already exist.\n   * @return ZAddParams\n   */\n  public ZAddParams xx() {\n    addParam(XX);\n    return this;\n  }\n\n  /**\n   * Modify the return value from the number of new elements added to the total number of elements\n   * changed\n   * @return ZAddParams\n   */\n  public ZAddParams ch() {\n    addParam(CH);\n    return this;\n  }\n\n  public byte[][] getByteParams(byte[] key, byte[]... args) {\n    ArrayList<byte[]> byteParams = new ArrayList<byte[]>();\n    byteParams.add(key);\n\n    if (contains(NX)) {\n      byteParams.add(SafeEncoder.encode(NX));\n    }\n    if (contains(XX)) {\n      byteParams.add(SafeEncoder.encode(XX));\n    }\n    if (contains(CH)) {\n      byteParams.add(SafeEncoder.encode(CH));\n    }\n\n    for (byte[] arg : args) {\n      byteParams.add(arg);\n    }\n\n    return byteParams.toArray(new byte[byteParams.size()][]);\n  }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/params/sortedset/ZIncrByParams.java",
    "content": "package redis.clients.jedis.params.sortedset;\n\nimport redis.clients.jedis.params.Params;\nimport redis.clients.util.SafeEncoder;\n\nimport java.util.ArrayList;\n\n/**\n * Parameters for ZINCRBY commands <br/>\n * <br/>\n * In fact, Redis doesn't have parameters for ZINCRBY. Instead Redis has INCR parameter for ZADD.<br/>\n * When users call ZADD with INCR option, its restriction (only one member) and return type is same\n * to ZINCRBY. <br/>\n * Document page for ZADD also describes INCR option to act like ZINCRBY. <br/>\n * http://redis.io/commands/zadd <br/>\n * <br/>\n * So we decided to wrap \"ZADD with INCR option\" to ZINCRBY. <br/>\n * https://github.com/xetorthio/jedis/issues/1067 <br/>\n * <br/>\n * Works with Redis 3.0.2 and onwards.\n */\npublic class ZIncrByParams extends Params {\n\n  private static final String XX = \"xx\";\n  private static final String NX = \"nx\";\n  private static final String INCR = \"incr\";\n\n  private ZIncrByParams() {\n  }\n\n  public static ZIncrByParams zIncrByParams() {\n    return new ZIncrByParams();\n  }\n\n  /**\n   * Only set the key if it does not already exist.\n   * @return ZIncrByParams\n   */\n  public ZIncrByParams nx() {\n    addParam(NX);\n    return this;\n  }\n\n  /**\n   * Only set the key if it already exist.\n   * @return ZIncrByParams\n   */\n  public ZIncrByParams xx() {\n    addParam(XX);\n    return this;\n  }\n\n  public byte[][] getByteParams(byte[] key, byte[]... args) {\n    ArrayList<byte[]> byteParams = new ArrayList<byte[]>();\n    byteParams.add(key);\n\n    if (contains(NX)) {\n      byteParams.add(SafeEncoder.encode(NX));\n    }\n    if (contains(XX)) {\n      byteParams.add(SafeEncoder.encode(XX));\n    }\n\n    byteParams.add(SafeEncoder.encode(INCR));\n\n    for (byte[] arg : args) {\n      byteParams.add(arg);\n    }\n\n    return byteParams.toArray(new byte[byteParams.size()][]);\n  }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/serializable/ProtostuffSerializer.java",
    "content": "package redis.clients.jedis.serializable;\n\nimport com.dyuproject.protostuff.LinkedBuffer;\nimport com.dyuproject.protostuff.ProtostuffIOUtil;\nimport com.dyuproject.protostuff.Schema;\nimport com.dyuproject.protostuff.runtime.RuntimeSchema;\n\nimport java.util.concurrent.ConcurrentHashMap;\n\n/**\n * Created by yijunzhang on 14-4-10.\n */\npublic class ProtostuffSerializer {\n\n    private static ConcurrentHashMap<Class<?>, Schema<?>> cachedSchema = new ConcurrentHashMap<Class<?>, Schema<?>>();\n\n    public <T> byte[] serialize(final T source) {\n        VO<T> vo = new VO<T>(source);\n\n        final LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);\n        try {\n            final Schema<VO> schema = getSchema(VO.class);\n            return serializeInternal(vo, schema, buffer);\n        } catch (final Exception e) {\n            throw new IllegalStateException(e.getMessage(), e);\n        } finally {\n            buffer.clear();\n        }\n    }\n\n    public <T> T deserialize(final byte[] bytes) {\n        try {\n            Schema<VO> schema = getSchema(VO.class);\n            VO vo = deserializeInternal(bytes, schema.newMessage(), schema);\n            if (vo != null && vo.getValue() != null) {\n                return (T) vo.getValue();\n            }\n        } catch (final Exception e) {\n            throw new IllegalStateException(e.getMessage(), e);\n        }\n        return null;\n    }\n\n    private <T> byte[] serializeInternal(final T source, final Schema<T> schema, final LinkedBuffer buffer) {\n        return ProtostuffIOUtil.toByteArray(source, schema, buffer);\n    }\n\n    private <T> T deserializeInternal(final byte[] bytes, final T result, final Schema<T> schema) {\n        ProtostuffIOUtil.mergeFrom(bytes, result, schema);\n        return result;\n    }\n\n    private static <T> Schema<T> getSchema(Class<T> clazz) {\n        @SuppressWarnings(\"unchecked\")\n        Schema<T> schema = (Schema<T>) cachedSchema.get(clazz);\n        if (schema == null) {\n            schema = RuntimeSchema.createFrom(clazz);\n            cachedSchema.put(clazz, schema);\n        }\n        return schema;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/serializable/VO.java",
    "content": "package redis.clients.jedis.serializable;\n\nimport java.io.Serializable;\n\n/**\n * Created by yijunzhang on 14-4-2.\n */\npublic class VO<T> implements Serializable {\n\n    private T value;\n\n    public VO(T value) {\n        this.value = value;\n    }\n\n    public VO() {\n    }\n\n    public T getValue() {\n        return value;\n    }\n\n    @Override\n    public String toString() {\n        return \"VO{\" +\n                \"value=\" + value +\n                '}';\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) return true;\n        if (!(o instanceof VO)) return false;\n        VO vo = (VO) o;\n        if (value != null ? !value.equals(vo.value) : vo.value != null) return false;\n        return true;\n    }\n\n    @Override\n    public int hashCode() {\n        return value != null ? value.hashCode() : 0;\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/valueobject/RangeScoreVO.java",
    "content": "package redis.clients.jedis.valueobject;\n\n/**\n * Created by yijunzhang on 14-5-28.\n */\npublic class RangeScoreVO {\n\n    private final double max;\n\n    private final double min;\n\n    public RangeScoreVO(double max, double min) {\n        this.max = max;\n        this.min = min;\n    }\n\n    public double getMax() {\n        return max;\n    }\n\n    public double getMin() {\n        return min;\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/valueobject/ReshardProcess.java",
    "content": "package redis.clients.jedis.valueobject;\n\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentMap;\nimport java.util.concurrent.ConcurrentSkipListMap;\n\n/**\n * Created by yijunzhang on 14-9-26.\n */\npublic class ReshardProcess {\n\n    /**\n     * 存储每个slot迁移的数量\n     */\n    private ConcurrentMap<Integer, Long> slotProcessMap = new ConcurrentSkipListMap<Integer, Long>();\n\n    /**\n     * 已完成迁移的slot数量\n     */\n    private volatile int reshardSlot;\n\n    /**\n     * 需要迁移的总数\n     */\n    private volatile int totalSlot;\n\n    /**\n     * 0,上线节点\n     * 1,下线节点\n     *\n     */\n    private volatile int type;\n\n    /**\n     * 0:运行中\n     * 1:完成\n     * 2:出错\n     */\n    private volatile int status;\n\n    public Map<Integer, Long> getSlotProcessMap() {\n        return slotProcessMap;\n    }\n\n    public int getReshardSlot() {\n        return reshardSlot;\n    }\n\n    public int getTotalSlot() {\n        return totalSlot;\n    }\n\n    public void setTotalSlot(int totalSlot) {\n        this.totalSlot = totalSlot;\n    }\n\n    public void addReshardSlot(int slot, long removeCount) {\n        reshardSlot += 1;\n        slotProcessMap.put(slot, removeCount);\n    }\n\n    public void setStatus(int status) {\n        this.status = status;\n    }\n\n    public int getStatus() {\n        return status;\n    }\n\n    public int getType() {\n        return type;\n    }\n\n    public void setType(int type) {\n        this.type = type;\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/jedis/valueobject/SortedSetVO.java",
    "content": "package redis.clients.jedis.valueobject;\n\n/**\n * Created by yijunzhang on 14-5-27.\n */\npublic class SortedSetVO {\n\n    private final double score;\n\n    private String memberStr;\n\n    private byte[] bytesBytes;\n\n    public SortedSetVO(double score, String memberStr) {\n        this.score = score;\n        this.memberStr = memberStr;\n    }\n\n    public SortedSetVO(double score, byte[] bytesBytes) {\n        this.score = score;\n        this.bytesBytes = bytesBytes;\n    }\n\n    public double getScore() {\n        return score;\n    }\n\n    public String getMemberStr() {\n        return memberStr;\n    }\n\n    public byte[] getBytesBytes() {\n        return bytesBytes;\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/util/ClusterNodeInformation.java",
    "content": "package redis.clients.util;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport redis.clients.jedis.HostAndPort;\n\npublic class ClusterNodeInformation {\n  private HostAndPort node;\n  private List<Integer> availableSlots;\n  private List<Integer> slotsBeingImported;\n  private List<Integer> slotsBeingMigrated;\n\n  public ClusterNodeInformation(HostAndPort node) {\n    this.node = node;\n    this.availableSlots = new ArrayList<Integer>();\n    this.slotsBeingImported = new ArrayList<Integer>();\n    this.slotsBeingMigrated = new ArrayList<Integer>();\n  }\n\n  public void addAvailableSlot(int slot) {\n    availableSlots.add(slot);\n  }\n\n  public void addSlotBeingImported(int slot) {\n    slotsBeingImported.add(slot);\n  }\n\n  public void addSlotBeingMigrated(int slot) {\n    slotsBeingMigrated.add(slot);\n  }\n\n  public HostAndPort getNode() {\n    return node;\n  }\n\n  public List<Integer> getAvailableSlots() {\n    return availableSlots;\n  }\n\n  public List<Integer> getSlotsBeingImported() {\n    return slotsBeingImported;\n  }\n\n  public List<Integer> getSlotsBeingMigrated() {\n    return slotsBeingMigrated;\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/util/ClusterNodeInformationParser.java",
    "content": "package redis.clients.util;\n\nimport redis.clients.jedis.HostAndPort;\n\npublic class ClusterNodeInformationParser {\n  private static final String SLOT_IMPORT_IDENTIFIER = \"-<-\";\n  private static final String SLOT_IN_TRANSITION_IDENTIFIER = \"[\";\n  public static final int SLOT_INFORMATIONS_START_INDEX = 8;\n  public static final int HOST_AND_PORT_INDEX = 1;\n\n  public ClusterNodeInformation parse(String nodeInfo, HostAndPort current) {\n    String[] nodeInfoPartArray = nodeInfo.split(\" \");\n\n    HostAndPort node = getHostAndPortFromNodeLine(nodeInfoPartArray, current);\n    ClusterNodeInformation info = new ClusterNodeInformation(node);\n\n    if (nodeInfoPartArray.length >= SLOT_INFORMATIONS_START_INDEX) {\n      String[] slotInfoPartArray = extractSlotParts(nodeInfoPartArray);\n      fillSlotInformation(slotInfoPartArray, info);\n    }\n\n    return info;\n  }\n\n  private String[] extractSlotParts(String[] nodeInfoPartArray) {\n    String[] slotInfoPartArray = new String[nodeInfoPartArray.length\n        - SLOT_INFORMATIONS_START_INDEX];\n    for (int i = SLOT_INFORMATIONS_START_INDEX; i < nodeInfoPartArray.length; i++) {\n      slotInfoPartArray[i - SLOT_INFORMATIONS_START_INDEX] = nodeInfoPartArray[i];\n    }\n    return slotInfoPartArray;\n  }\n\n  public HostAndPort getHostAndPortFromNodeLine(String[] nodeInfoPartArray, HostAndPort current) {\n    String stringHostAndPort = nodeInfoPartArray[HOST_AND_PORT_INDEX];\n\n    String[] arrayHostAndPort = stringHostAndPort.split(\":\");\n    return new HostAndPort(arrayHostAndPort[0].isEmpty() ? current.getHost() : arrayHostAndPort[0],\n        arrayHostAndPort[1].isEmpty() ? current.getPort() : Integer.valueOf(arrayHostAndPort[1]));\n  }\n\n  private void fillSlotInformation(String[] slotInfoPartArray, ClusterNodeInformation info) {\n    for (String slotRange : slotInfoPartArray) {\n      fillSlotInformationFromSlotRange(slotRange, info);\n    }\n  }\n\n  private void fillSlotInformationFromSlotRange(String slotRange, ClusterNodeInformation info) {\n    if (slotRange.startsWith(SLOT_IN_TRANSITION_IDENTIFIER)) {\n      // slot is in transition\n      int slot = Integer.parseInt(slotRange.substring(1).split(\"-\")[0]);\n\n      if (slotRange.contains(SLOT_IMPORT_IDENTIFIER)) {\n        // import\n        info.addSlotBeingImported(slot);\n      } else {\n        // migrate (->-)\n        info.addSlotBeingMigrated(slot);\n      }\n    } else if (slotRange.contains(\"-\")) {\n      // slot range\n      String[] slotRangePart = slotRange.split(\"-\");\n      for (int slot = Integer.valueOf(slotRangePart[0]); slot <= Integer.valueOf(slotRangePart[1]); slot++) {\n        info.addAvailableSlot(slot);\n      }\n    } else {\n      // single slot\n      info.addAvailableSlot(Integer.valueOf(slotRange));\n    }\n  }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/util/Hashing.java",
    "content": "package redis.clients.util;\n\nimport java.security.MessageDigest;\nimport java.security.NoSuchAlgorithmException;\n\npublic interface Hashing {\n  Hashing MURMUR_HASH = new MurmurHash();\n  ThreadLocal<MessageDigest> md5Holder = new ThreadLocal<MessageDigest>();\n\n  Hashing MD5 = new Hashing() {\n    public long hash(String key) {\n      return hash(SafeEncoder.encode(key));\n    }\n\n    public long hash(byte[] key) {\n      try {\n        if (md5Holder.get() == null) {\n          md5Holder.set(MessageDigest.getInstance(\"MD5\"));\n        }\n      } catch (NoSuchAlgorithmException e) {\n        throw new IllegalStateException(\"++++ no md5 algorithm found\");\n      }\n      MessageDigest md5 = md5Holder.get();\n\n      md5.reset();\n      md5.update(key);\n      byte[] bKey = md5.digest();\n      long res = ((long) (bKey[3] & 0xFF) << 24) | ((long) (bKey[2] & 0xFF) << 16)\n          | ((long) (bKey[1] & 0xFF) << 8) | (long) (bKey[0] & 0xFF);\n      return res;\n    }\n  };\n\n  long hash(String key);\n\n  long hash(byte[] key);\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/util/IOUtils.java",
    "content": "package redis.clients.util;\n\nimport java.io.IOException;\nimport java.net.Socket;\n\npublic class IOUtils {\n  private IOUtils() {\n  }\n\n  public static void closeQuietly(Socket sock) {\n    // It's same thing as Apache Commons - IOUtils.closeQuietly()\n    if (sock != null) {\n      try {\n        sock.close();\n      } catch (IOException e) {\n        // ignored\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/util/JedisByteHashMap.java",
    "content": "package redis.clients.util;\n\nimport java.io.Serializable;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.Iterator;\nimport java.util.Map;\nimport java.util.Set;\n\npublic class JedisByteHashMap implements Map<byte[], byte[]>, Cloneable, Serializable {\n  private static final long serialVersionUID = -6971431362627219416L;\n  private Map<ByteArrayWrapper, byte[]> internalMap = new HashMap<ByteArrayWrapper, byte[]>();\n\n  @Override\n  public void clear() {\n    internalMap.clear();\n  }\n\n  @Override\n  public boolean containsKey(Object key) {\n    if (key instanceof byte[]) return internalMap.containsKey(new ByteArrayWrapper((byte[]) key));\n    return internalMap.containsKey(key);\n  }\n\n  @Override\n  public boolean containsValue(Object value) {\n    return internalMap.containsValue(value);\n  }\n\n  @Override\n  public Set<java.util.Map.Entry<byte[], byte[]>> entrySet() {\n    Iterator<java.util.Map.Entry<ByteArrayWrapper, byte[]>> iterator = internalMap.entrySet()\n        .iterator();\n    HashSet<Entry<byte[], byte[]>> hashSet = new HashSet<java.util.Map.Entry<byte[], byte[]>>();\n    while (iterator.hasNext()) {\n      Entry<ByteArrayWrapper, byte[]> entry = iterator.next();\n      hashSet.add(new JedisByteEntry(entry.getKey().data, entry.getValue()));\n    }\n    return hashSet;\n  }\n\n  @Override\n  public byte[] get(Object key) {\n    if (key instanceof byte[]) return internalMap.get(new ByteArrayWrapper((byte[]) key));\n    return internalMap.get(key);\n  }\n\n  @Override\n  public boolean isEmpty() {\n    return internalMap.isEmpty();\n  }\n\n  @Override\n  public Set<byte[]> keySet() {\n    Set<byte[]> keySet = new HashSet<byte[]>();\n    Iterator<ByteArrayWrapper> iterator = internalMap.keySet().iterator();\n    while (iterator.hasNext()) {\n      keySet.add(iterator.next().data);\n    }\n    return keySet;\n  }\n\n  @Override\n  public byte[] put(byte[] key, byte[] value) {\n    return internalMap.put(new ByteArrayWrapper(key), value);\n  }\n\n  @Override\n  @SuppressWarnings(\"unchecked\")\n  public void putAll(Map<? extends byte[], ? extends byte[]> m) {\n    Iterator<?> iterator = m.entrySet().iterator();\n    while (iterator.hasNext()) {\n      Entry<? extends byte[], ? extends byte[]> next = (Entry<? extends byte[], ? extends byte[]>) iterator\n          .next();\n      internalMap.put(new ByteArrayWrapper(next.getKey()), next.getValue());\n    }\n  }\n\n  @Override\n  public byte[] remove(Object key) {\n    if (key instanceof byte[]) return internalMap.remove(new ByteArrayWrapper((byte[]) key));\n    return internalMap.remove(key);\n  }\n\n  @Override\n  public int size() {\n    return internalMap.size();\n  }\n\n  @Override\n  public Collection<byte[]> values() {\n    return internalMap.values();\n  }\n\n  private static final class ByteArrayWrapper {\n    private final byte[] data;\n\n    public ByteArrayWrapper(byte[] data) {\n      if (data == null) {\n        throw new NullPointerException();\n      }\n      this.data = data;\n    }\n\n    public boolean equals(Object other) {\n      if (!(other instanceof ByteArrayWrapper)) {\n        return false;\n      }\n      return Arrays.equals(data, ((ByteArrayWrapper) other).data);\n    }\n\n    public int hashCode() {\n      return Arrays.hashCode(data);\n    }\n  }\n\n  private static final class JedisByteEntry implements Entry<byte[], byte[]> {\n    private byte[] value;\n    private byte[] key;\n\n    public JedisByteEntry(byte[] key, byte[] value) {\n      this.key = key;\n      this.value = value;\n    }\n\n    @Override\n    public byte[] getKey() {\n      return this.key;\n    }\n\n    @Override\n    public byte[] getValue() {\n      return this.value;\n    }\n\n    @Override\n    public byte[] setValue(byte[] value) {\n      this.value = value;\n      return value;\n    }\n\n  }\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/util/JedisClusterCRC16.java",
    "content": "package redis.clients.util;\n\n/**\n * CRC16 Implementation according to CCITT standard Polynomial : 1021 (x^16 + x^12 + x^5 + 1) See <a\n * href=\"http://redis.io/topics/cluster-spec\">Appendix A. CRC16 reference implementation in ANSI\n * C</a>\n */\npublic class JedisClusterCRC16 {\n  private static final int LOOKUP_TABLE[] = { 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5,\n      0x60C6, 0x70E7, 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, 0x1231,\n      0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, 0x9339, 0x8318, 0xB37B, 0xA35A,\n      0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4,\n      0x5485, 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, 0x3653, 0x2672,\n      0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF,\n      0xE7FE, 0xD79D, 0xC7BC, 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,\n      0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, 0x5AF5, 0x4AD4, 0x7AB7,\n      0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58,\n      0xBB3B, 0xAB1A, 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, 0xEDAE,\n      0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4,\n      0x3E13, 0x2E32, 0x1E51, 0x0E70, 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59,\n      0x8F78, 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, 0x1080, 0x00A1,\n      0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D,\n      0xD31C, 0xE37F, 0xF35E, 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,\n      0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, 0x34E2, 0x24C3, 0x14A0,\n      0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E,\n      0xC71D, 0xD73C, 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, 0xD94C,\n      0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, 0x5844, 0x4865, 0x7806, 0x6827,\n      0x18C0, 0x08E1, 0x3882, 0x28A3, 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB,\n      0xBB9A, 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, 0xFD2E, 0xED0F,\n      0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2,\n      0x2C83, 0x1CE0, 0x0CC1, 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,\n      0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0, };\n\n  public static int getSlot(String key) {\n    int s = key.indexOf(\"{\");\n    if (s > -1) {\n      int e = key.indexOf(\"}\", s + 1);\n      if (e > -1 && e != s + 1) {\n        key = key.substring(s + 1, e);\n      }\n    }\n    // optimization with modulo operator with power of 2\n    // equivalent to getCRC16(key) % 16384\n    return getCRC16(key) & (16384 - 1);\n  }\n\n  public static int getSlot(byte[] key) {\n    int s = -1;\n    int e = -1;\n    boolean sFound = false;\n    for (int i = 0; i < key.length; i++) {\n      if (key[i] == '{' && !sFound) {\n        s = i;\n        sFound = true;\n      }\n      if (key[i] == '}' && sFound) {\n        e = i;\n        break;\n      }\n    }\n    if (s > -1 && e > -1 && e != s + 1) {\n      return getCRC16(key, s + 1, e) & (16384 - 1);\n    }\n    return getCRC16(key) & (16384 - 1);\n  }\n\n  /**\n   * Create a CRC16 checksum from the bytes. implementation is from mp911de/lettuce, modified with\n   * some more optimizations\n   * @param bytes\n   * @return CRC16 as integer value See <a\n   *         href=\"https://github.com/xetorthio/jedis/pull/733#issuecomment-55840331\">Issue 733</a>\n   */\n  public static int getCRC16(byte[] bytes, int s, int e) {\n    int crc = 0x0000;\n\n    for (int i = s; i < e; i++) {\n      crc = ((crc << 8) ^ LOOKUP_TABLE[((crc >>> 8) ^ (bytes[i] & 0xFF)) & 0xFF]);\n    }\n    return crc & 0xFFFF;\n  }\n\n  public static int getCRC16(byte[] bytes) {\n    return getCRC16(bytes, 0, bytes.length);\n  }\n\n  public static int getCRC16(String key) {\n    byte[] bytesKey = SafeEncoder.encode(key);\n    return getCRC16(bytesKey, 0, bytesKey.length);\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/util/JedisURIHelper.java",
    "content": "package redis.clients.util;\n\nimport java.net.URI;\n\npublic class JedisURIHelper {\n\n  private static final int DEFAULT_DB = 0;\n\n  public static String getPassword(URI uri) {\n    String userInfo = uri.getUserInfo();\n    if (userInfo != null) {\n      return userInfo.split(\":\", 2)[1];\n    }\n    return null;\n  }\n\n  public static int getDBIndex(URI uri) {\n    String[] pathSplit = uri.getPath().split(\"/\", 2);\n    if (pathSplit.length > 1) {\n      String dbIndexStr = pathSplit[1];\n      if (dbIndexStr.isEmpty()) {\n        return DEFAULT_DB;\n      }\n      return Integer.parseInt(dbIndexStr);\n    } else {\n      return DEFAULT_DB;\n    }\n  }\n\n  public static boolean isValid(URI uri) {\n    if (isEmpty(uri.getScheme()) || isEmpty(uri.getHost()) || uri.getPort() == -1) {\n      return false;\n    }\n\n    return true;\n  }\n\n  private static boolean isEmpty(String value) {\n    return value == null || value.trim().length() == 0;\n  }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/util/KeyMergeUtil.java",
    "content": "package redis.clients.util;\n\npublic class KeyMergeUtil {\n  public static String[] merge(String destKey, String[] keys) {\n    String[] mergedKeys = new String[keys.length + 1];\n    mergedKeys[0] = destKey;\n    System.arraycopy(keys, 0, mergedKeys, 1, keys.length);\n    return mergedKeys;\n  }\n\n  public static byte[][] merge(byte[] destKey, byte[][] keys) {\n    byte[][] mergedKeys = new byte[keys.length + 1][];\n    mergedKeys[0] = destKey;\n    System.arraycopy(keys, 0, mergedKeys, 1, keys.length);\n    return mergedKeys;\n  }\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/util/MurmurHash.java",
    "content": "/*\n * Licensed to the Apache Software Foundation (ASF) under one or more contributor license\n * agreements. See the NOTICE file distributed with this work for additional information regarding\n * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the\n * \"License\"); you may not use this file except in compliance with the License. You may obtain a\n * copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable\n * law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\"\n * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License\n * for the specific language governing permissions and limitations under the License.\n */\n\npackage redis.clients.util;\n\nimport java.nio.ByteBuffer;\nimport java.nio.ByteOrder;\n\n/**\n * This is a very fast, non-cryptographic hash suitable for general hash-based lookup. See\n * http://murmurhash.googlepages.com/ for more details. <br>\n * <p>\n * The C version of MurmurHash 2.0 found at that site was ported to Java by Andrzej Bialecki (ab at\n * getopt org).\n * </p>\n */\npublic class MurmurHash implements Hashing {\n  /**\n   * Hashes bytes in an array.\n   * @param data The bytes to hash.\n   * @param seed The seed for the hash.\n   * @return The 32 bit hash of the bytes in question.\n   */\n  public static int hash(byte[] data, int seed) {\n    return hash(ByteBuffer.wrap(data), seed);\n  }\n\n  /**\n   * Hashes bytes in part of an array.\n   * @param data The data to hash.\n   * @param offset Where to start munging.\n   * @param length How many bytes to process.\n   * @param seed The seed to start with.\n   * @return The 32-bit hash of the data in question.\n   */\n  public static int hash(byte[] data, int offset, int length, int seed) {\n    return hash(ByteBuffer.wrap(data, offset, length), seed);\n  }\n\n  /**\n   * Hashes the bytes in a buffer from the current position to the limit.\n   * @param buf The bytes to hash.\n   * @param seed The seed for the hash.\n   * @return The 32 bit murmur hash of the bytes in the buffer.\n   */\n  public static int hash(ByteBuffer buf, int seed) {\n    // save byte order for later restoration\n    ByteOrder byteOrder = buf.order();\n    buf.order(ByteOrder.LITTLE_ENDIAN);\n\n    int m = 0x5bd1e995;\n    int r = 24;\n\n    int h = seed ^ buf.remaining();\n\n    int k;\n    while (buf.remaining() >= 4) {\n      k = buf.getInt();\n\n      k *= m;\n      k ^= k >>> r;\n      k *= m;\n\n      h *= m;\n      h ^= k;\n    }\n\n    if (buf.remaining() > 0) {\n      ByteBuffer finish = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN);\n      // for big-endian version, use this first:\n      // finish.position(4-buf.remaining());\n      finish.put(buf).rewind();\n      h ^= finish.getInt();\n      h *= m;\n    }\n\n    h ^= h >>> 13;\n    h *= m;\n    h ^= h >>> 15;\n\n    buf.order(byteOrder);\n    return h;\n  }\n\n  public static long hash64A(byte[] data, int seed) {\n    return hash64A(ByteBuffer.wrap(data), seed);\n  }\n\n  public static long hash64A(byte[] data, int offset, int length, int seed) {\n    return hash64A(ByteBuffer.wrap(data, offset, length), seed);\n  }\n\n  public static long hash64A(ByteBuffer buf, int seed) {\n    ByteOrder byteOrder = buf.order();\n    buf.order(ByteOrder.LITTLE_ENDIAN);\n\n    long m = 0xc6a4a7935bd1e995L;\n    int r = 47;\n\n    long h = seed ^ (buf.remaining() * m);\n\n    long k;\n    while (buf.remaining() >= 8) {\n      k = buf.getLong();\n\n      k *= m;\n      k ^= k >>> r;\n      k *= m;\n\n      h ^= k;\n      h *= m;\n    }\n\n    if (buf.remaining() > 0) {\n      ByteBuffer finish = ByteBuffer.allocate(8).order(ByteOrder.LITTLE_ENDIAN);\n      // for big-endian version, do this first:\n      // finish.position(8-buf.remaining());\n      finish.put(buf).rewind();\n      h ^= finish.getLong();\n      h *= m;\n    }\n\n    h ^= h >>> r;\n    h *= m;\n    h ^= h >>> r;\n\n    buf.order(byteOrder);\n    return h;\n  }\n\n  public long hash(byte[] key) {\n    return hash64A(key, 0x1234ABCD);\n  }\n\n  public long hash(String key) {\n    return hash(SafeEncoder.encode(key));\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/util/Pool.java",
    "content": "package redis.clients.util;\n\nimport java.io.Closeable;\n\nimport org.apache.commons.pool2.PooledObjectFactory;\nimport org.apache.commons.pool2.impl.GenericObjectPool;\nimport org.apache.commons.pool2.impl.GenericObjectPoolConfig;\n\nimport redis.clients.jedis.exceptions.JedisConnectionException;\nimport redis.clients.jedis.exceptions.JedisException;\n\npublic abstract class Pool<T> implements Closeable {\n  protected GenericObjectPool<T> internalPool;\n\n  /**\n   * Using this constructor means you have to set and initialize the internalPool yourself.\n   */\n  public Pool() {\n  }\n\n  @Override\n  public void close() {\n    destroy();\n  }\n\n  public boolean isClosed() {\n    return this.internalPool.isClosed();\n  }\n\n  public Pool(final GenericObjectPoolConfig poolConfig, PooledObjectFactory<T> factory) {\n    initPool(poolConfig, factory);\n  }\n\n  public void initPool(final GenericObjectPoolConfig poolConfig, PooledObjectFactory<T> factory) {\n\n    if (this.internalPool != null) {\n      try {\n        closeInternalPool();\n      } catch (Exception e) {\n      }\n    }\n\n    this.internalPool = new GenericObjectPool<T>(factory, poolConfig);\n  }\n\n  public T getResource() {\n    try {\n      return internalPool.borrowObject();\n    } catch (Exception e) {\n      throw new JedisConnectionException(\"Could not get a resource from the pool\", e);\n    }\n  }\n\n  protected void returnResourceObject(final T resource) {\n    if (resource == null) {\n      return;\n    }\n    try {\n      internalPool.returnObject(resource);\n    } catch (Exception e) {\n      throw new JedisException(\"Could not return the resource to the pool\", e);\n    }\n  }\n\n  protected void returnBrokenResource(final T resource) {\n    if (resource != null) {\n      returnBrokenResourceObject(resource);\n    }\n  }\n\n  protected void returnResource(final T resource) {\n    if (resource != null) {\n      returnResourceObject(resource);\n    }\n  }\n\n  public void destroy() {\n    closeInternalPool();\n  }\n\n  protected void returnBrokenResourceObject(final T resource) {\n    try {\n      internalPool.invalidateObject(resource);\n    } catch (Exception e) {\n      throw new JedisException(\"Could not return the resource to the pool\", e);\n    }\n  }\n\n  protected void closeInternalPool() {\n    try {\n      internalPool.close();\n    } catch (Exception e) {\n      throw new JedisException(\"Could not destroy the pool\", e);\n    }\n  }\n\n  public int getNumActive() {\n    if (poolInactive()) {\n      return -1;\n    }\n\n    return this.internalPool.getNumActive();\n  }\n\n  public int getNumIdle() {\n    if (poolInactive()) {\n      return -1;\n    }\n\n    return this.internalPool.getNumIdle();\n  }\n\n  public int getNumWaiters() {\n    if (poolInactive()) {\n      return -1;\n    }\n\n    return this.internalPool.getNumWaiters();\n  }\n\n  public long getMeanBorrowWaitTimeMillis() {\n    if (poolInactive()) {\n      return -1;\n    }\n\n    return this.internalPool.getMeanBorrowWaitTimeMillis();\n  }\n\n  public long getMaxBorrowWaitTimeMillis() {\n    if (poolInactive()) {\n      return -1;\n    }\n\n    return this.internalPool.getMaxBorrowWaitTimeMillis();\n  }\n\n  private boolean poolInactive() {\n    return this.internalPool == null || this.internalPool.isClosed();\n  }\n\n  public void addObjects(int count) {\n    try {\n      for (int i = 0; i < count; i++) {\n        this.internalPool.addObject();\n      }\n    } catch (Exception e) {\n      throw new JedisException(\"Error trying to add idle objects\", e);\n    }\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/util/RedisInputStream.java",
    "content": "/*\n * Copyright 2009-2010 MBTE Sweden AB. Licensed under the Apache License, Version 2.0 (the\n * \"License\"); you may not use this file except in compliance with the License. You may obtain a\n * copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable\n * law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\"\n * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License\n * for the specific language governing permissions and limitations under the License.\n */\n\npackage redis.clients.util;\n\nimport java.io.*;\n\nimport redis.clients.jedis.exceptions.JedisConnectionException;\n\n/**\n * This class assumes (to some degree) that we are reading a RESP stream. As such it assumes certain\n * conventions regarding CRLF line termination. It also assumes that if the Protocol layer requires\n * a byte that if that byte is not there it is a stream error.\n */\npublic class RedisInputStream extends FilterInputStream {\n\n  protected final byte buf[];\n\n  protected int count, limit;\n\n  public RedisInputStream(InputStream in, int size) {\n    super(in);\n    if (size <= 0) {\n      throw new IllegalArgumentException(\"Buffer size <= 0\");\n    }\n    buf = new byte[size];\n  }\n\n  public RedisInputStream(InputStream in) {\n    this(in, 8192);\n  }\n\n  public byte readByte() throws JedisConnectionException {\n    ensureFill();\n    return buf[count++];\n  }\n\n  public String readLine() {\n    final StringBuilder sb = new StringBuilder();\n    while (true) {\n      ensureFill();\n\n      byte b = buf[count++];\n      if (b == '\\r') {\n        ensureFill(); // Must be one more byte\n\n        byte c = buf[count++];\n        if (c == '\\n') {\n          break;\n        }\n        sb.append((char) b);\n        sb.append((char) c);\n      } else {\n        sb.append((char) b);\n      }\n    }\n\n    final String reply = sb.toString();\n    if (reply.length() == 0) {\n      throw new JedisConnectionException(\"It seems like server has closed the connection.\");\n    }\n\n    return reply;\n  }\n\n  public byte[] readLineBytes() {\n\n    /*\n     * This operation should only require one fill. In that typical case we optimize allocation and\n     * copy of the byte array. In the edge case where more than one fill is required then we take a\n     * slower path and expand a byte array output stream as is necessary.\n     */\n\n    ensureFill();\n\n    int pos = count;\n    final byte[] buf = this.buf;\n    while (true) {\n      if (pos == limit) {\n        return readLineBytesSlowly();\n      }\n\n      if (buf[pos++] == '\\r') {\n        if (pos == limit) {\n          return readLineBytesSlowly();\n        }\n\n        if (buf[pos++] == '\\n') {\n          break;\n        }\n      }\n    }\n\n    final int N = (pos - count) - 2;\n    final byte[] line = new byte[N];\n    System.arraycopy(buf, count, line, 0, N);\n    count = pos;\n    return line;\n  }\n\n  /**\n   * Slow path in case a line of bytes cannot be read in one #fill() operation. This is still faster\n   * than creating the StrinbBuilder, String, then encoding as byte[] in Protocol, then decoding\n   * back into a String.\n   */\n  private byte[] readLineBytesSlowly() {\n    ByteArrayOutputStream bout = null;\n    while (true) {\n      ensureFill();\n\n      byte b = buf[count++];\n      if (b == '\\r') {\n        ensureFill(); // Must be one more byte\n\n        byte c = buf[count++];\n        if (c == '\\n') {\n          break;\n        }\n\n        if (bout == null) {\n          bout = new ByteArrayOutputStream(16);\n        }\n\n        bout.write(b);\n        bout.write(c);\n      } else {\n        if (bout == null) {\n          bout = new ByteArrayOutputStream(16);\n        }\n\n        bout.write(b);\n      }\n    }\n\n    return bout == null ? new byte[0] : bout.toByteArray();\n  }\n\n  public int readIntCrLf() {\n    return (int) readLongCrLf();\n  }\n\n  public long readLongCrLf() {\n    final byte[] buf = this.buf;\n\n    ensureFill();\n\n    final boolean isNeg = buf[count] == '-';\n    if (isNeg) {\n      ++count;\n    }\n\n    long value = 0;\n    while (true) {\n      ensureFill();\n\n      final int b = buf[count++];\n      if (b == '\\r') {\n        ensureFill();\n\n        if (buf[count++] != '\\n') {\n          throw new JedisConnectionException(\"Unexpected character!\");\n        }\n\n        break;\n      } else {\n        value = value * 10 + b - '0';\n      }\n    }\n\n    return (isNeg ? -value : value);\n  }\n\n  public int read(byte[] b, int off, int len) throws JedisConnectionException {\n    ensureFill();\n\n    final int length = Math.min(limit - count, len);\n    System.arraycopy(buf, count, b, off, length);\n    count += length;\n    return length;\n  }\n\n  /**\n   * This methods assumes there are required bytes to be read. If we cannot read anymore bytes an\n   * exception is thrown to quickly ascertain that the stream was smaller than expected.\n   */\n  private void ensureFill() throws JedisConnectionException {\n    if (count >= limit) {\n      try {\n        limit = in.read(buf);\n        count = 0;\n        if (limit == -1) {\n          throw new JedisConnectionException(\"Unexpected end of stream.\");\n        }\n      } catch (IOException e) {\n        throw new JedisConnectionException(e);\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/util/RedisOutputStream.java",
    "content": "package redis.clients.util;\n\nimport java.io.FilterOutputStream;\nimport java.io.IOException;\nimport java.io.OutputStream;\n\n/**\n * The class implements a buffered output stream without synchronization There are also special\n * operations like in-place string encoding. This stream fully ignore mark/reset and should not be\n * used outside Jedis\n */\npublic final class RedisOutputStream extends FilterOutputStream {\n  protected final byte buf[];\n\n  protected int count;\n\n  public RedisOutputStream(final OutputStream out) {\n    this(out, 8192);\n  }\n\n  public RedisOutputStream(final OutputStream out, final int size) {\n    super(out);\n    if (size <= 0) {\n      throw new IllegalArgumentException(\"Buffer size <= 0\");\n    }\n    buf = new byte[size];\n  }\n\n  private void flushBuffer() throws IOException {\n    if (count > 0) {\n      out.write(buf, 0, count);\n      count = 0;\n    }\n  }\n\n  public void write(final byte b) throws IOException {\n    if (count == buf.length) {\n      flushBuffer();\n    }\n    buf[count++] = b;\n  }\n\n  public void write(final byte[] b) throws IOException {\n    write(b, 0, b.length);\n  }\n\n  public void write(final byte b[], final int off, final int len) throws IOException {\n    if (len >= buf.length) {\n      flushBuffer();\n      out.write(b, off, len);\n    } else {\n      if (len >= buf.length - count) {\n        flushBuffer();\n      }\n\n      System.arraycopy(b, off, buf, count, len);\n      count += len;\n    }\n  }\n\n  public void writeAsciiCrLf(final String in) throws IOException {\n    final int size = in.length();\n\n    for (int i = 0; i != size; ++i) {\n      if (count == buf.length) {\n        flushBuffer();\n      }\n      buf[count++] = (byte) in.charAt(i);\n    }\n\n    writeCrLf();\n  }\n\n  public static boolean isSurrogate(final char ch) {\n    return ch >= Character.MIN_SURROGATE && ch <= Character.MAX_SURROGATE;\n  }\n\n  public static int utf8Length(final String str) {\n    int strLen = str.length(), utfLen = 0;\n    for (int i = 0; i != strLen; ++i) {\n      char c = str.charAt(i);\n      if (c < 0x80) {\n        utfLen++;\n      } else if (c < 0x800) {\n        utfLen += 2;\n      } else if (isSurrogate(c)) {\n        i++;\n        utfLen += 4;\n      } else {\n        utfLen += 3;\n      }\n    }\n    return utfLen;\n  }\n\n  public void writeCrLf() throws IOException {\n    if (2 >= buf.length - count) {\n      flushBuffer();\n    }\n\n    buf[count++] = '\\r';\n    buf[count++] = '\\n';\n  }\n\n  public void writeUtf8CrLf(final String str) throws IOException {\n    int strLen = str.length();\n\n    int i;\n    for (i = 0; i < strLen; i++) {\n      char c = str.charAt(i);\n      if (!(c < 0x80)) break;\n      if (count == buf.length) {\n        flushBuffer();\n      }\n      buf[count++] = (byte) c;\n    }\n\n    for (; i < strLen; i++) {\n      char c = str.charAt(i);\n      if (c < 0x80) {\n        if (count == buf.length) {\n          flushBuffer();\n        }\n        buf[count++] = (byte) c;\n      } else if (c < 0x800) {\n        if (2 >= buf.length - count) {\n          flushBuffer();\n        }\n        buf[count++] = (byte) (0xc0 | (c >> 6));\n        buf[count++] = (byte) (0x80 | (c & 0x3f));\n      } else if (isSurrogate(c)) {\n        if (4 >= buf.length - count) {\n          flushBuffer();\n        }\n        int uc = Character.toCodePoint(c, str.charAt(i++));\n        buf[count++] = ((byte) (0xf0 | ((uc >> 18))));\n        buf[count++] = ((byte) (0x80 | ((uc >> 12) & 0x3f)));\n        buf[count++] = ((byte) (0x80 | ((uc >> 6) & 0x3f)));\n        buf[count++] = ((byte) (0x80 | (uc & 0x3f)));\n      } else {\n        if (3 >= buf.length - count) {\n          flushBuffer();\n        }\n        buf[count++] = ((byte) (0xe0 | ((c >> 12))));\n        buf[count++] = ((byte) (0x80 | ((c >> 6) & 0x3f)));\n        buf[count++] = ((byte) (0x80 | (c & 0x3f)));\n      }\n    }\n\n    writeCrLf();\n  }\n\n  private final static int[] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999, 99999999,\n      999999999, Integer.MAX_VALUE };\n\n  private final static byte[] DigitTens = { '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '1',\n      '1', '1', '1', '1', '1', '1', '1', '1', '1', '2', '2', '2', '2', '2', '2', '2', '2', '2',\n      '2', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '4', '4', '4', '4', '4', '4', '4',\n      '4', '4', '4', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '6', '6', '6', '6', '6',\n      '6', '6', '6', '6', '6', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '8', '8', '8',\n      '8', '8', '8', '8', '8', '8', '8', '9', '9', '9', '9', '9', '9', '9', '9', '9', '9', };\n\n  private final static byte[] DigitOnes = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0',\n      '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8',\n      '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6',\n      '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4',\n      '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2',\n      '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', };\n\n  private final static byte[] digits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a',\n      'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',\n      't', 'u', 'v', 'w', 'x', 'y', 'z' };\n\n  public void writeIntCrLf(int value) throws IOException {\n    if (value < 0) {\n      write((byte) '-');\n      value = -value;\n    }\n\n    int size = 0;\n    while (value > sizeTable[size])\n      size++;\n\n    size++;\n    if (size >= buf.length - count) {\n      flushBuffer();\n    }\n\n    int q, r;\n    int charPos = count + size;\n\n    while (value >= 65536) {\n      q = value / 100;\n      r = value - ((q << 6) + (q << 5) + (q << 2));\n      value = q;\n      buf[--charPos] = DigitOnes[r];\n      buf[--charPos] = DigitTens[r];\n    }\n\n    for (;;) {\n      q = (value * 52429) >>> (16 + 3);\n      r = value - ((q << 3) + (q << 1));\n      buf[--charPos] = digits[r];\n      value = q;\n      if (value == 0) break;\n    }\n    count += size;\n\n    writeCrLf();\n  }\n\n  public void flush() throws IOException {\n    flushBuffer();\n    out.flush();\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/util/SafeEncoder.java",
    "content": "package redis.clients.util;\n\nimport java.io.UnsupportedEncodingException;\n\nimport redis.clients.jedis.Protocol;\nimport redis.clients.jedis.exceptions.JedisDataException;\nimport redis.clients.jedis.exceptions.JedisException;\n\n/**\n * The only reason to have this is to be able to compatible with java 1.5 :(\n */\npublic class SafeEncoder {\n  public static byte[][] encodeMany(final String... strs) {\n    byte[][] many = new byte[strs.length][];\n    for (int i = 0; i < strs.length; i++) {\n      many[i] = encode(strs[i]);\n    }\n    return many;\n  }\n\n  public static byte[] encode(final String str) {\n    try {\n      if (str == null) {\n        throw new JedisDataException(\"value sent to redis cannot be null\");\n      }\n      return str.getBytes(Protocol.CHARSET);\n    } catch (UnsupportedEncodingException e) {\n      throw new JedisException(e);\n    }\n  }\n\n  public static String encode(final byte[] data) {\n    try {\n      return new String(data, Protocol.CHARSET);\n    } catch (UnsupportedEncodingException e) {\n      throw new JedisException(e);\n    }\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/util/ShardInfo.java",
    "content": "package redis.clients.util;\n\npublic abstract class ShardInfo<T> {\n  private int weight;\n\n  public ShardInfo() {\n  }\n\n  public ShardInfo(int weight) {\n    this.weight = weight;\n  }\n\n  public int getWeight() {\n    return this.weight;\n  }\n\n  protected abstract T createResource();\n\n  public abstract String getName();\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/util/Sharded.java",
    "content": "package redis.clients.util;\n\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.SortedMap;\nimport java.util.TreeMap;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\npublic class Sharded<R, S extends ShardInfo<R>> {\n\n  public static final int DEFAULT_WEIGHT = 1;\n  private TreeMap<Long, S> nodes;\n  private final Hashing algo;\n  private final Map<ShardInfo<R>, R> resources = new LinkedHashMap<ShardInfo<R>, R>();\n\n  /**\n   * The default pattern used for extracting a key tag. The pattern must have a group (between\n   * parenthesis), which delimits the tag to be hashed. A null pattern avoids applying the regular\n   * expression for each lookup, improving performance a little bit is key tags aren't being used.\n   */\n  private Pattern tagPattern = null;\n  // the tag is anything between {}\n  public static final Pattern DEFAULT_KEY_TAG_PATTERN = Pattern.compile(\"\\\\{(.+?)\\\\}\");\n\n  public Sharded(List<S> shards) {\n    this(shards, Hashing.MURMUR_HASH); // MD5 is really not good as we works\n    // with 64-bits not 128\n  }\n\n  public Sharded(List<S> shards, Hashing algo) {\n    this.algo = algo;\n    initialize(shards);\n  }\n\n  public Sharded(List<S> shards, Pattern tagPattern) {\n    this(shards, Hashing.MURMUR_HASH, tagPattern); // MD5 is really not good\n    // as we works with\n    // 64-bits not 128\n  }\n\n  public Sharded(List<S> shards, Hashing algo, Pattern tagPattern) {\n    this.algo = algo;\n    this.tagPattern = tagPattern;\n    initialize(shards);\n  }\n\n  private void initialize(List<S> shards) {\n    nodes = new TreeMap<Long, S>();\n\n    for (int i = 0; i != shards.size(); ++i) {\n      final S shardInfo = shards.get(i);\n      if (shardInfo.getName() == null) for (int n = 0; n < 160 * shardInfo.getWeight(); n++) {\n        nodes.put(this.algo.hash(\"SHARD-\" + i + \"-NODE-\" + n), shardInfo);\n      }\n      else for (int n = 0; n < 160 * shardInfo.getWeight(); n++) {\n        nodes.put(this.algo.hash(shardInfo.getName() + \"*\" + shardInfo.getWeight() + n), shardInfo);\n      }\n      resources.put(shardInfo, shardInfo.createResource());\n    }\n  }\n\n  public R getShard(byte[] key) {\n    return resources.get(getShardInfo(key));\n  }\n\n  public R getShard(String key) {\n    return resources.get(getShardInfo(key));\n  }\n\n  public S getShardInfo(byte[] key) {\n    SortedMap<Long, S> tail = nodes.tailMap(algo.hash(key));\n    if (tail.isEmpty()) {\n      return nodes.get(nodes.firstKey());\n    }\n    return tail.get(tail.firstKey());\n  }\n\n  public S getShardInfo(String key) {\n    return getShardInfo(SafeEncoder.encode(getKeyTag(key)));\n  }\n\n  /**\n   * A key tag is a special pattern inside a key that, if preset, is the only part of the key hashed\n   * in order to select the server for this key.\n   * @see <a href=\"http://redis.io/topics/partitioning\">partitioning</a>\n   * @param key\n   * @return The tag if it exists, or the original key\n   */\n  public String getKeyTag(String key) {\n    if (tagPattern != null) {\n      Matcher m = tagPattern.matcher(key);\n      if (m.find()) return m.group(1);\n    }\n    return key;\n  }\n\n  public Collection<S> getAllShardInfo() {\n    return Collections.unmodifiableCollection(nodes.values());\n  }\n\n  public Collection<R> getAllShards() {\n    return Collections.unmodifiableCollection(resources.values());\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/main/java/redis/clients/util/Slowlog.java",
    "content": "package redis.clients.util;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class Slowlog {\n  private final long id;\n  private final long timeStamp;\n  private final long executionTime;\n  private final List<String> args;\n  private static final String COMMA = \",\";\n\n  @SuppressWarnings(\"unchecked\")\n  public static List<Slowlog> from(List<Object> nestedMultiBulkReply) {\n    List<Slowlog> logs = new ArrayList<Slowlog>(nestedMultiBulkReply.size());\n    for (Object obj : nestedMultiBulkReply) {\n      List<Object> properties = (List<Object>) obj;\n      logs.add(new Slowlog(properties));\n    }\n\n    return logs;\n  }\n\n  @SuppressWarnings(\"unchecked\")\n  private Slowlog(List<Object> properties) {\n    super();\n    this.id = (Long) properties.get(0);\n    this.timeStamp = (Long) properties.get(1);\n    this.executionTime = (Long) properties.get(2);\n\n    List<byte[]> bargs = (List<byte[]>) properties.get(3);\n    this.args = new ArrayList<String>(bargs.size());\n\n    for (byte[] barg : bargs) {\n      this.args.add(SafeEncoder.encode(barg));\n    }\n  }\n\n  public long getId() {\n    return id;\n  }\n\n  public long getTimeStamp() {\n    return timeStamp;\n  }\n\n  public long getExecutionTime() {\n    return executionTime;\n  }\n\n  public List<String> getArgs() {\n    return args;\n  }\n\n  @Override\n  public String toString() {\n    return new StringBuilder().append(id).append(COMMA).append(timeStamp).append(COMMA)\n        .append(executionTime).append(COMMA).append(args).toString();\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/PipelineClusterTest.java",
    "content": "package redis.clients.jedis;\n\nimport org.apache.commons.pool2.impl.GenericObjectPoolConfig;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport redis.clients.util.SafeEncoder;\n\nimport java.util.*;\nimport java.util.Map.Entry;\n\npublic class PipelineClusterTest {\n\n    private PipelineCluster pipelineCluster;\n\n    private List<String> keys = new ArrayList<String>();\n\n    @Before\n    public void before() {\n        GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();\n        poolConfig.setMaxWaitMillis(2 * 1000L);\n        Set<HostAndPort> nodes = new HashSet<HostAndPort>();\n\n        //test mHgetAll\n        nodes.add(new HostAndPort(\"127.0.0.1\", 6386));\n        nodes.add(new HostAndPort(\"127.0.0.1\", 6386));\n        nodes.add(new HostAndPort(\"127.0.0.1\", 7642));\n        nodes.add(new HostAndPort(\"127.0.0.1\", 7643));\n        nodes.add(new HostAndPort(\"127.0.0.1\", 7644));\n        nodes.add(new HostAndPort(\"127.0.0.1\", 6392));\n        pipelineCluster = new PipelineCluster(poolConfig, nodes);\n        for (int i = 1; i < 10; i++) {\n            String key = \"key:\" + i;\n            keys.add(key);\n        }\n    }\n\n    @Test\n    public void testMset() throws Exception {\n        Map<String, String> keyValues = new HashMap<String, String>();\n        for (int i = 0; i < keys.size(); i++) {\n            keyValues.put(keys.get(i), \"value-\" + (i + 1));\n        }\n        String response = pipelineCluster.mset(keyValues);\n        System.out.println(response);\n    }\n\n    @Test\n    public void testMget() throws Exception {\n        Map<String, String> keyValues = pipelineCluster.mget(keys);\n        System.out.println(keyValues);\n    }\n\n    @Test\n    public void testMdel() throws Exception {\n        long deleteCount = pipelineCluster.mdel(keys);\n        System.out.println(deleteCount);\n    }\n\n    @Test\n    public void testHset() throws Exception {\n        String key = \"we:media:24:key\";\n        Set<String> keys = pipelineCluster.hkeys(key);\n        System.out.println(keys.size());\n        for (String vid : keys) {\n            System.out.println(vid);\n        }\n    }\n\n    @Test\n    public void testSScan() throws Exception {\n        String key = \"sscan:test:1\";\n        for (int i = 1; i <= 500; i++) {\n            pipelineCluster.sadd(key, \"v=\" + i);\n        }\n        String cursor = \"0\";\n        int count = 200;\n        ScanParams params = new ScanParams();\n        params.count(count);\n        while (true) {\n            ScanResult<byte[]> sscan = pipelineCluster.sscan(SafeEncoder.encode(key), SafeEncoder.encode(cursor), params);\n            List<byte[]> list = sscan.getResult();\n            cursor = sscan.getCursor();\n            System.out.println(\"cursor=\" + cursor + \" size\" + list.size());\n            if (cursor.equals(\"0\")) {\n                break;\n            }\n        }\n\n        pipelineCluster.del(key);\n    }\n    \n    \n    \n    @Test\n    public void testMHgetAll() {\n        List<String> keys = new ArrayList<String>();\n        keys.add(\"ugc:video:feature:5946211\");\n        keys.add(\"ugc:video:feature:30491583\");\n        keys.add(\"ugc:video:feature:63108807\");\n        keys.add(\"ugc:video:feature:77257903\");\n        keys.add(\"ugc:video:feature:10113377\");\n        keys.add(\"ugc:video:feature:30542906\");\n        keys.add(\"ugc:video:feature:54608980\");\n        keys.add(\"ugc:video:feature:72082818\");\n        Map<String, Map<String, String>> mmap = pipelineCluster.mHgetAll(keys);\n        for (Entry<String, Map<String, String>> entry : mmap.entrySet()) {\n            System.out.println(entry.getKey());\n            for (Entry<String, String> entry2 : entry.getValue().entrySet()) {\n                System.out.println(\"\\t\" + entry2.getKey() + \":\" + entry2.getValue());\n            }\n        }\n    }\n    \n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/TupleTest.java",
    "content": "package redis.clients.jedis;\n\nimport org.junit.Test;\nimport static org.junit.Assert.*;\n\n/**\n * @author Antonio Tomac <antonio.tomac@mediatoolkit.com>\n */\npublic class TupleTest {\n\n  @Test\n  public void testCompareTo() {\n    Tuple t1 = new Tuple(\"foo\", 1.0);\n    Tuple t2 = new Tuple(\"bar\", 1.0);\n    Tuple t3 = new Tuple(\"elem3\", 2.0);\n    Tuple t4 = new Tuple(\"foo\", 10.0);\n\n    assertEquals(0, t1.compareTo(t2));\n    assertEquals(0, t2.compareTo(t1));\n\n    assertEquals(-1, t1.compareTo(t3));\n    assertEquals(1, t3.compareTo(t1));\n\n    assertEquals(0, t1.compareTo(t4));\n    assertEquals(0, t4.compareTo(t1));\n  }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/BuilderFactoryTest.java",
    "content": "package redis.clients.jedis.tests;\n\nimport org.junit.Assert;\nimport org.junit.Test;\n\nimport redis.clients.jedis.BuilderFactory;\n\npublic class BuilderFactoryTest extends Assert {\n  @Test\n  public void buildDouble() {\n    Double build = BuilderFactory.DOUBLE.build(\"1.0\".getBytes());\n    assertEquals(new Double(1.0), build);\n  }\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/ConnectionCloseTest.java",
    "content": "package redis.clients.jedis.tests;\n\nimport org.junit.After;\nimport org.junit.Assert;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport redis.clients.jedis.Connection;\nimport redis.clients.jedis.exceptions.JedisConnectionException;\n\npublic class ConnectionCloseTest extends Assert {\n\n  private Connection client;\n\n  @Before\n  public void setUp() throws Exception {\n    client = new Connection();\n  }\n\n  @After\n  public void tearDown() throws Exception {\n    client.close();\n  }\n\n  @Test(expected = JedisConnectionException.class)\n  public void checkUnkownHost() {\n    client.setHost(\"someunknownhost\");\n    client.connect();\n  }\n\n  @Test(expected = JedisConnectionException.class)\n  public void checkWrongPort() {\n    client.setHost(\"localhost\");\n    client.setPort(55665);\n    client.connect();\n  }\n\n  @Test\n  public void connectIfNotConnectedWhenSettingTimeoutInfinite() {\n    client.setHost(\"localhost\");\n    client.setPort(6379);\n    client.setTimeoutInfinite();\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/ConnectionTest.java",
    "content": "package redis.clients.jedis.tests;\n\nimport org.junit.After;\nimport org.junit.Assert;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport redis.clients.jedis.Connection;\nimport redis.clients.jedis.Protocol.Command;\nimport redis.clients.jedis.commands.ProtocolCommand;\nimport redis.clients.jedis.exceptions.JedisConnectionException;\n\npublic class ConnectionTest extends Assert {\n  private Connection client;\n\n  @Before\n  public void setUp() throws Exception {\n    client = new Connection();\n  }\n\n  @After\n  public void tearDown() throws Exception {\n    client.disconnect();\n  }\n\n  @Test(expected = JedisConnectionException.class)\n  public void checkUnkownHost() {\n    client.setHost(\"someunknownhost\");\n    client.connect();\n  }\n\n  @Test(expected = JedisConnectionException.class)\n  public void checkWrongPort() {\n    client.setHost(\"localhost\");\n    client.setPort(55665);\n    client.connect();\n  }\n\n  @Test\n  public void connectIfNotConnectedWhenSettingTimeoutInfinite() {\n    client.setHost(\"localhost\");\n    client.setPort(6379);\n    client.setTimeoutInfinite();\n  }\n\n  @Test\n  public void checkCloseable() {\n    client.setHost(\"localhost\");\n    client.setPort(6379);\n    client.connect();\n    client.close();\n  }\n\n  @Test\n  public void getErrorAfterConnectionReset() throws Exception {\n    class TestConnection extends Connection {\n      public TestConnection() {\n        super(\"localhost\", 6379);\n      }\n\n      @Override\n      protected Connection sendCommand(ProtocolCommand cmd, byte[]... args) {\n        return super.sendCommand(cmd, args);\n      }\n    }\n\n    TestConnection conn = new TestConnection();\n\n    try {\n      conn.sendCommand(Command.HMSET, new byte[1024 * 1024 + 1][0]);\n      fail(\"Should throw exception\");\n    } catch (JedisConnectionException jce) {\n      assertEquals(\"ERR Protocol error: invalid multibulk length\", jce.getMessage());\n    }\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/FragmentedByteArrayInputStream.java",
    "content": "package redis.clients.jedis.tests;\n\nimport java.io.ByteArrayInputStream;\n\n/**\n * Test class the fragment a byte array for testing purpose.\n */\npublic class FragmentedByteArrayInputStream extends ByteArrayInputStream {\n  private int readMethodCallCount = 0;\n\n  public FragmentedByteArrayInputStream(final byte[] buf) {\n    super(buf);\n  }\n\n  public synchronized int read(final byte[] b, final int off, final int len) {\n    readMethodCallCount++;\n    if (len <= 10) {\n      // if the len <= 10, return as usual ..\n      return super.read(b, off, len);\n    } else {\n      // else return the first half ..\n      return super.read(b, off, len / 2);\n    }\n  }\n\n  public int getReadMethodCallCount() {\n    return readMethodCallCount;\n  }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/HostAndPortUtil.java",
    "content": "package redis.clients.jedis.tests;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport redis.clients.jedis.HostAndPort;\nimport redis.clients.jedis.Protocol;\n\npublic class HostAndPortUtil {\n  private static List<HostAndPort> redisHostAndPortList = new ArrayList<HostAndPort>();\n  private static List<HostAndPort> sentinelHostAndPortList = new ArrayList<HostAndPort>();\n  private static List<HostAndPort> clusterHostAndPortList = new ArrayList<HostAndPort>();\n\n  static {\n    redisHostAndPortList.add(new HostAndPort(\"localhost\", Protocol.DEFAULT_PORT));\n    redisHostAndPortList.add(new HostAndPort(\"localhost\", Protocol.DEFAULT_PORT + 1));\n    redisHostAndPortList.add(new HostAndPort(\"localhost\", Protocol.DEFAULT_PORT + 2));\n    redisHostAndPortList.add(new HostAndPort(\"localhost\", Protocol.DEFAULT_PORT + 3));\n    redisHostAndPortList.add(new HostAndPort(\"localhost\", Protocol.DEFAULT_PORT + 4));\n    redisHostAndPortList.add(new HostAndPort(\"localhost\", Protocol.DEFAULT_PORT + 5));\n    redisHostAndPortList.add(new HostAndPort(\"localhost\", Protocol.DEFAULT_PORT + 6));\n\n    sentinelHostAndPortList.add(new HostAndPort(\"localhost\", Protocol.DEFAULT_SENTINEL_PORT));\n    sentinelHostAndPortList.add(new HostAndPort(\"localhost\", Protocol.DEFAULT_SENTINEL_PORT + 1));\n    sentinelHostAndPortList.add(new HostAndPort(\"localhost\", Protocol.DEFAULT_SENTINEL_PORT + 2));\n    sentinelHostAndPortList.add(new HostAndPort(\"localhost\", Protocol.DEFAULT_SENTINEL_PORT + 3));\n\n    clusterHostAndPortList.add(new HostAndPort(\"localhost\", 7379));\n    clusterHostAndPortList.add(new HostAndPort(\"localhost\", 7380));\n    clusterHostAndPortList.add(new HostAndPort(\"localhost\", 7381));\n    clusterHostAndPortList.add(new HostAndPort(\"localhost\", 7382));\n    clusterHostAndPortList.add(new HostAndPort(\"localhost\", 7383));\n    clusterHostAndPortList.add(new HostAndPort(\"localhost\", 7384));\n\n    String envRedisHosts = System.getProperty(\"redis-hosts\");\n    String envSentinelHosts = System.getProperty(\"sentinel-hosts\");\n    String envClusterHosts = System.getProperty(\"cluster-hosts\");\n\n    redisHostAndPortList = parseHosts(envRedisHosts, redisHostAndPortList);\n    sentinelHostAndPortList = parseHosts(envSentinelHosts, sentinelHostAndPortList);\n    clusterHostAndPortList = parseHosts(envClusterHosts, clusterHostAndPortList);\n  }\n\n  public static List<HostAndPort> parseHosts(String envHosts,\n      List<HostAndPort> existingHostsAndPorts) {\n\n    if (null != envHosts && 0 < envHosts.length()) {\n\n      String[] hostDefs = envHosts.split(\",\");\n\n      if (null != hostDefs && 2 <= hostDefs.length) {\n\n        List<HostAndPort> envHostsAndPorts = new ArrayList<HostAndPort>(hostDefs.length);\n\n        for (String hostDef : hostDefs) {\n\n          String[] hostAndPort = hostDef.split(\":\");\n\n          if (null != hostAndPort && 2 == hostAndPort.length) {\n            String host = hostAndPort[0];\n            int port = Protocol.DEFAULT_PORT;\n\n            try {\n              port = Integer.parseInt(hostAndPort[1]);\n            } catch (final NumberFormatException nfe) {\n            }\n\n            envHostsAndPorts.add(new HostAndPort(host, port));\n          }\n        }\n\n        return envHostsAndPorts;\n      }\n    }\n\n    return existingHostsAndPorts;\n  }\n\n  public static List<HostAndPort> getRedisServers() {\n    return redisHostAndPortList;\n  }\n\n  public static List<HostAndPort> getSentinelServers() {\n    return sentinelHostAndPortList;\n  }\n\n  public static List<HostAndPort> getClusterServers() {\n    return clusterHostAndPortList;\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/JedisClusterNodeInformationParserTest.java",
    "content": "package redis.clients.jedis.tests;\n\nimport org.junit.Assert;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport redis.clients.jedis.HostAndPort;\nimport redis.clients.util.ClusterNodeInformation;\nimport redis.clients.util.ClusterNodeInformationParser;\n\npublic class JedisClusterNodeInformationParserTest extends Assert {\n  private ClusterNodeInformationParser parser;\n\n  @Before\n  public void setUp() {\n    parser = new ClusterNodeInformationParser();\n  }\n\n  @Test\n  public void testParseNodeMyself() {\n    String nodeInfo = \"9b0d2ab38ee31482c95fdb2c7847a0d40e88d518 :7379 myself,master - 0 0 1 connected 0-5460\";\n    HostAndPort current = new HostAndPort(\"localhost\", 7379);\n    ClusterNodeInformation clusterNodeInfo = parser.parse(nodeInfo, current);\n    assertEquals(clusterNodeInfo.getNode(), current);\n  }\n\n  @Test\n  public void testParseNormalState() {\n    String nodeInfo = \"5f4a2236d00008fba7ac0dd24b95762b446767bd 192.168.0.3:7380 master - 0 1400598804016 2 connected 5461-10922\";\n    HostAndPort current = new HostAndPort(\"localhost\", 7379);\n    ClusterNodeInformation clusterNodeInfo = parser.parse(nodeInfo, current);\n    assertNotEquals(clusterNodeInfo.getNode(), current);\n    assertEquals(clusterNodeInfo.getNode(), new HostAndPort(\"192.168.0.3\", 7380));\n\n    for (int slot = 5461; slot <= 10922; slot++) {\n      assertTrue(clusterNodeInfo.getAvailableSlots().contains(slot));\n    }\n\n    assertTrue(clusterNodeInfo.getSlotsBeingImported().isEmpty());\n    assertTrue(clusterNodeInfo.getSlotsBeingMigrated().isEmpty());\n  }\n\n  @Test\n  public void testParseSlotBeingMigrated() {\n    String nodeInfo = \"5f4a2236d00008fba7ac0dd24b95762b446767bd :7379 myself,master - 0 0 1 connected 0-5459 [5460->-5f4a2236d00008fba7ac0dd24b95762b446767bd] [5461-<-5f4a2236d00008fba7ac0dd24b95762b446767bd]\";\n    HostAndPort current = new HostAndPort(\"localhost\", 7379);\n    ClusterNodeInformation clusterNodeInfo = parser.parse(nodeInfo, current);\n    assertEquals(clusterNodeInfo.getNode(), current);\n\n    for (int slot = 0; slot <= 5459; slot++) {\n      assertTrue(clusterNodeInfo.getAvailableSlots().contains(slot));\n    }\n\n    assertEquals(1, clusterNodeInfo.getSlotsBeingMigrated().size());\n    assertTrue(clusterNodeInfo.getSlotsBeingMigrated().contains(5460));\n    assertEquals(1, clusterNodeInfo.getSlotsBeingImported().size());\n    assertTrue(clusterNodeInfo.getSlotsBeingImported().contains(5461));\n  }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/JedisClusterTest.java",
    "content": "package redis.clients.jedis.tests;\n\nimport org.apache.commons.pool2.impl.GenericObjectPoolConfig;\nimport org.junit.*;\nimport redis.clients.jedis.*;\nimport redis.clients.jedis.JedisCluster.Reset;\nimport redis.clients.jedis.exceptions.*;\nimport redis.clients.jedis.tests.utils.ClientKillerUtil;\nimport redis.clients.jedis.tests.utils.JedisClusterTestUtil;\nimport redis.clients.util.ClusterNodeInformationParser;\nimport redis.clients.util.JedisClusterCRC16;\n\nimport java.io.IOException;\nimport java.util.*;\nimport java.util.concurrent.*;\nimport java.util.logging.Logger;\n\npublic class JedisClusterTest extends Assert {\n  private static Jedis node1;\n  private static Jedis node2;\n  private static Jedis node3;\n  private static Jedis node4;\n  private static Jedis nodeSlave2;\n  private String localHost = \"127.0.0.1\";\n\n  private HostAndPort nodeInfo1 = HostAndPortUtil.getClusterServers().get(0);\n  private HostAndPort nodeInfo2 = HostAndPortUtil.getClusterServers().get(1);\n  private HostAndPort nodeInfo3 = HostAndPortUtil.getClusterServers().get(2);\n  private HostAndPort nodeInfo4 = HostAndPortUtil.getClusterServers().get(3);\n  private HostAndPort nodeInfoSlave2 = HostAndPortUtil.getClusterServers().get(4);\n  protected Logger log = Logger.getLogger(getClass().getName());\n\n  @Before\n  public void setUp() throws InterruptedException {\n    node1 = new Jedis(nodeInfo1.getHost(), nodeInfo1.getPort());\n    node1.connect();\n    node1.flushAll();\n\n    node2 = new Jedis(nodeInfo2.getHost(), nodeInfo2.getPort());\n    node2.connect();\n    node2.flushAll();\n\n    node3 = new Jedis(nodeInfo3.getHost(), nodeInfo3.getPort());\n    node3.connect();\n    node3.flushAll();\n\n    node4 = new Jedis(nodeInfo4.getHost(), nodeInfo4.getPort());\n    node4.connect();\n    node4.flushAll();\n\n    nodeSlave2 = new Jedis(nodeInfoSlave2.getHost(), nodeInfoSlave2.getPort());\n    nodeSlave2.connect();\n    nodeSlave2.flushAll();\n    // ---- configure cluster\n\n    // add nodes to cluster\n    node1.clusterMeet(localHost, nodeInfo2.getPort());\n    node1.clusterMeet(localHost, nodeInfo3.getPort());\n\n    // split available slots across the three nodes\n    int slotsPerNode = JedisCluster.HASHSLOTS / 3;\n    int[] node1Slots = new int[slotsPerNode];\n    int[] node2Slots = new int[slotsPerNode + 1];\n    int[] node3Slots = new int[slotsPerNode];\n    for (int i = 0, slot1 = 0, slot2 = 0, slot3 = 0; i < JedisCluster.HASHSLOTS; i++) {\n      if (i < slotsPerNode) {\n        node1Slots[slot1++] = i;\n      } else if (i > slotsPerNode * 2) {\n        node3Slots[slot3++] = i;\n      } else {\n        node2Slots[slot2++] = i;\n      }\n    }\n\n    node1.clusterAddSlots(node1Slots);\n    node2.clusterAddSlots(node2Slots);\n    node3.clusterAddSlots(node3Slots);\n\n    JedisClusterTestUtil.waitForClusterReady(node1, node2, node3);\n  }\n\n  @AfterClass\n  public static void cleanUp() {\n    node1.flushDB();\n    node2.flushDB();\n    node3.flushDB();\n    node4.flushDB();\n    node1.clusterReset(Reset.SOFT);\n    node2.clusterReset(Reset.SOFT);\n    node3.clusterReset(Reset.SOFT);\n    node4.clusterReset(Reset.SOFT);\n  }\n\n  @After\n  public void tearDown() throws InterruptedException {\n    cleanUp();\n  }\n\n  @Test(expected = JedisMovedDataException.class)\n  public void testThrowMovedException() {\n    node1.set(\"foo\", \"bar\");\n  }\n\n  @Test\n  public void testMovedExceptionParameters() {\n    try {\n      node1.set(\"foo\", \"bar\");\n    } catch (JedisMovedDataException jme) {\n      assertEquals(12182, jme.getSlot());\n      assertEquals(new HostAndPort(\"127.0.0.1\", 7381), jme.getTargetNode());\n      return;\n    }\n    fail();\n  }\n\n  @Test(expected = JedisAskDataException.class)\n  public void testThrowAskException() {\n    int keySlot = JedisClusterCRC16.getSlot(\"test\");\n    String node3Id = JedisClusterTestUtil.getNodeId(node3.clusterNodes());\n    node2.clusterSetSlotMigrating(keySlot, node3Id);\n    node2.get(\"test\");\n  }\n\n  @Test\n  public void testDiscoverNodesAutomatically() {\n    Set<HostAndPort> jedisClusterNode = new HashSet<HostAndPort>();\n    jedisClusterNode.add(new HostAndPort(\"127.0.0.1\", 7379));\n    JedisCluster jc = new JedisCluster(jedisClusterNode);\n    assertEquals(3, jc.getClusterNodes().size());\n    \n    JedisCluster jc2 = new JedisCluster(new HostAndPort(\"127.0.0.1\", 7379));\n    assertEquals(3, jc2.getClusterNodes().size());\n  }\n  \n  @Test\n  public void testCalculateConnectionPerSlot() {\n    Set<HostAndPort> jedisClusterNode = new HashSet<HostAndPort>();\n    jedisClusterNode.add(new HostAndPort(\"127.0.0.1\", 7379));\n    JedisCluster jc = new JedisCluster(jedisClusterNode);\n    jc.set(\"foo\", \"bar\");\n    jc.set(\"test\", \"test\");\n    assertEquals(\"bar\", node3.get(\"foo\"));\n    assertEquals(\"test\", node2.get(\"test\"));\n    \n    JedisCluster jc2 = new JedisCluster(new HostAndPort(\"127.0.0.1\", 7379));\n    jc2.set(\"foo\", \"bar\");\n    jc2.set(\"test\", \"test\");\n    assertEquals(\"bar\", node3.get(\"foo\"));\n    assertEquals(\"test\", node2.get(\"test\"));\n  }\n\n  @Test\n  public void testReadonly() throws Exception {\n    node1.clusterMeet(localHost, nodeInfoSlave2.getPort());\n    JedisClusterTestUtil.waitForClusterReady(node1, node2, node3, nodeSlave2);\n\n    ClusterNodeInformationParser nodeInfoParser = new ClusterNodeInformationParser();\n    for (String nodeInfo : node2.clusterNodes().split(\"\\n\")) {\n      if (nodeInfo.contains(\"myself\")) {\n        nodeSlave2.clusterReplicate(nodeInfo.split(\" \")[0]);\n        break;\n      }\n    }\n    try {\n      nodeSlave2.get(\"test\");\n      fail();\n    } catch (JedisMovedDataException e) {\n    }\n    nodeSlave2.readonly();\n    nodeSlave2.get(\"test\");\n\n    nodeSlave2.clusterReset(Reset.SOFT);\n    nodeSlave2.flushDB();\n  }\n\n  /**\n   * slot->nodes 15363 node3 e\n   */\n  @Test\n  public void testMigrate() {\n    log.info(\"test migrate slot\");\n    Set<HostAndPort> jedisClusterNode = new HashSet<HostAndPort>();\n    jedisClusterNode.add(nodeInfo1);\n    JedisCluster jc = new JedisCluster(jedisClusterNode);\n    String node3Id = JedisClusterTestUtil.getNodeId(node3.clusterNodes());\n    String node2Id = JedisClusterTestUtil.getNodeId(node2.clusterNodes());\n    node3.clusterSetSlotMigrating(15363, node2Id);\n    node2.clusterSetSlotImporting(15363, node3Id);\n    try {\n      node2.set(\"e\", \"e\");\n    } catch (JedisMovedDataException jme) {\n      assertEquals(15363, jme.getSlot());\n      assertEquals(new HostAndPort(localHost, nodeInfo3.getPort()), jme.getTargetNode());\n    }\n\n    try {\n      node3.set(\"e\", \"e\");\n    } catch (JedisAskDataException jae) {\n      assertEquals(15363, jae.getSlot());\n      assertEquals(new HostAndPort(localHost, nodeInfo2.getPort()), jae.getTargetNode());\n    }\n\n    jc.set(\"e\", \"e\");\n\n    try {\n      node2.get(\"e\");\n    } catch (JedisMovedDataException jme) {\n      assertEquals(15363, jme.getSlot());\n      assertEquals(new HostAndPort(localHost, nodeInfo3.getPort()), jme.getTargetNode());\n    }\n    try {\n      node3.get(\"e\");\n    } catch (JedisAskDataException jae) {\n      assertEquals(15363, jae.getSlot());\n      assertEquals(new HostAndPort(localHost, nodeInfo2.getPort()), jae.getTargetNode());\n    }\n\n    assertEquals(\"e\", jc.get(\"e\"));\n\n    node2.clusterSetSlotNode(15363, node2Id);\n    node3.clusterSetSlotNode(15363, node2Id);\n    // assertEquals(\"e\", jc.get(\"e\"));\n    assertEquals(\"e\", node2.get(\"e\"));\n\n    // assertEquals(\"e\", node3.get(\"e\"));\n\n  }\n\n  @Test\n  public void testMigrateToNewNode() throws InterruptedException {\n    log.info(\"test migrate slot to new node\");\n    Set<HostAndPort> jedisClusterNode = new HashSet<HostAndPort>();\n    jedisClusterNode.add(nodeInfo1);\n    JedisCluster jc = new JedisCluster(jedisClusterNode);\n    node4.clusterMeet(localHost, nodeInfo1.getPort());\n\n    String node3Id = JedisClusterTestUtil.getNodeId(node3.clusterNodes());\n    String node4Id = JedisClusterTestUtil.getNodeId(node4.clusterNodes());\n    JedisClusterTestUtil.waitForClusterReady(node4);\n    node3.clusterSetSlotMigrating(15363, node4Id);\n    node4.clusterSetSlotImporting(15363, node3Id);\n    try {\n      node4.set(\"e\", \"e\");\n    } catch (JedisMovedDataException jme) {\n      assertEquals(15363, jme.getSlot());\n      assertEquals(new HostAndPort(localHost, nodeInfo3.getPort()), jme.getTargetNode());\n    }\n\n    try {\n      node3.set(\"e\", \"e\");\n    } catch (JedisAskDataException jae) {\n      assertEquals(15363, jae.getSlot());\n      assertEquals(new HostAndPort(localHost, nodeInfo4.getPort()), jae.getTargetNode());\n    }\n\n    jc.set(\"e\", \"e\");\n\n    try {\n      node4.get(\"e\");\n    } catch (JedisMovedDataException jme) {\n      assertEquals(15363, jme.getSlot());\n      assertEquals(new HostAndPort(localHost, nodeInfo3.getPort()), jme.getTargetNode());\n    }\n    try {\n      node3.get(\"e\");\n    } catch (JedisAskDataException jae) {\n      assertEquals(15363, jae.getSlot());\n      assertEquals(new HostAndPort(localHost, nodeInfo4.getPort()), jae.getTargetNode());\n    }\n\n    assertEquals(\"e\", jc.get(\"e\"));\n\n    node4.clusterSetSlotNode(15363, node4Id);\n    node3.clusterSetSlotNode(15363, node4Id);\n    // assertEquals(\"e\", jc.get(\"e\"));\n    assertEquals(\"e\", node4.get(\"e\"));\n\n    // assertEquals(\"e\", node3.get(\"e\"));\n\n  }\n\n  @Test\n  public void testRecalculateSlotsWhenMoved() throws InterruptedException {\n    Set<HostAndPort> jedisClusterNode = new HashSet<HostAndPort>();\n    jedisClusterNode.add(new HostAndPort(\"127.0.0.1\", 7379));\n    JedisCluster jc = new JedisCluster(jedisClusterNode);\n    int slot51 = JedisClusterCRC16.getSlot(\"51\");\n    node2.clusterDelSlots(slot51);\n    node3.clusterDelSlots(slot51);\n    node3.clusterAddSlots(slot51);\n\n    JedisClusterTestUtil.waitForClusterReady(node1, node2, node3);\n    jc.set(\"51\", \"foo\");\n    assertEquals(\"foo\", jc.get(\"51\"));\n  }\n\n  @Test\n  public void testAskResponse() throws InterruptedException {\n    Set<HostAndPort> jedisClusterNode = new HashSet<HostAndPort>();\n    jedisClusterNode.add(new HostAndPort(\"127.0.0.1\", 7379));\n    JedisCluster jc = new JedisCluster(jedisClusterNode);\n    int slot51 = JedisClusterCRC16.getSlot(\"51\");\n    node3.clusterSetSlotImporting(slot51, JedisClusterTestUtil.getNodeId(node2.clusterNodes()));\n    node2.clusterSetSlotMigrating(slot51, JedisClusterTestUtil.getNodeId(node3.clusterNodes()));\n    jc.set(\"51\", \"foo\");\n    assertEquals(\"foo\", jc.get(\"51\"));\n  }\n\n  @Test(expected = JedisClusterMaxRedirectionsException.class)\n  public void testRedisClusterMaxRedirections() {\n    Set<HostAndPort> jedisClusterNode = new HashSet<HostAndPort>();\n    jedisClusterNode.add(new HostAndPort(\"127.0.0.1\", 7379));\n    JedisCluster jc = new JedisCluster(jedisClusterNode);\n    int slot51 = JedisClusterCRC16.getSlot(\"51\");\n    // This will cause an infinite redirection loop\n    node2.clusterSetSlotMigrating(slot51, JedisClusterTestUtil.getNodeId(node3.clusterNodes()));\n    jc.set(\"51\", \"foo\");\n  }\n\n  @Test\n  public void testRedisHashtag() {\n    assertEquals(JedisClusterCRC16.getSlot(\"{bar\"), JedisClusterCRC16.getSlot(\"foo{{bar}}zap\"));\n    assertEquals(JedisClusterCRC16.getSlot(\"{user1000}.following\"),\n      JedisClusterCRC16.getSlot(\"{user1000}.followers\"));\n    assertNotEquals(JedisClusterCRC16.getSlot(\"foo{}{bar}\"), JedisClusterCRC16.getSlot(\"bar\"));\n    assertEquals(JedisClusterCRC16.getSlot(\"foo{bar}{zap}\"), JedisClusterCRC16.getSlot(\"bar\"));\n  }\n\n  @Test\n  public void testClusterForgetNode() throws InterruptedException {\n    // at first, join node4 to cluster\n    node1.clusterMeet(\"127.0.0.1\", nodeInfo4.getPort());\n\n    String node7Id = JedisClusterTestUtil.getNodeId(node4.clusterNodes());\n\n    JedisClusterTestUtil.assertNodeIsKnown(node3, node7Id, 1000);\n    JedisClusterTestUtil.assertNodeIsKnown(node2, node7Id, 1000);\n    JedisClusterTestUtil.assertNodeIsKnown(node1, node7Id, 1000);\n\n    assertNodeHandshakeEnded(node3, 1000);\n    assertNodeHandshakeEnded(node2, 1000);\n    assertNodeHandshakeEnded(node1, 1000);\n\n    assertEquals(4, node1.clusterNodes().split(\"\\n\").length);\n    assertEquals(4, node2.clusterNodes().split(\"\\n\").length);\n    assertEquals(4, node3.clusterNodes().split(\"\\n\").length);\n\n    // do cluster forget\n    node1.clusterForget(node7Id);\n    node2.clusterForget(node7Id);\n    node3.clusterForget(node7Id);\n\n    JedisClusterTestUtil.assertNodeIsUnknown(node1, node7Id, 1000);\n    JedisClusterTestUtil.assertNodeIsUnknown(node2, node7Id, 1000);\n    JedisClusterTestUtil.assertNodeIsUnknown(node3, node7Id, 1000);\n\n    assertEquals(3, node1.clusterNodes().split(\"\\n\").length);\n    assertEquals(3, node2.clusterNodes().split(\"\\n\").length);\n    assertEquals(3, node3.clusterNodes().split(\"\\n\").length);\n  }\n\n  @Test\n  public void testClusterFlushSlots() {\n    String slotRange = getNodeServingSlotRange(node1.clusterNodes());\n    assertNotNull(slotRange);\n\n    try {\n      node1.clusterFlushSlots();\n      assertNull(getNodeServingSlotRange(node1.clusterNodes()));\n    } finally {\n      // rollback\n      String[] rangeInfo = slotRange.split(\"-\");\n      int lower = Integer.parseInt(rangeInfo[0]);\n      int upper = Integer.parseInt(rangeInfo[1]);\n\n      int[] node1Slots = new int[upper - lower + 1];\n      for (int i = 0; lower <= upper;) {\n        node1Slots[i++] = lower++;\n      }\n      node1.clusterAddSlots(node1Slots);\n    }\n  }\n\n  @Test\n  public void testClusterKeySlot() {\n    // It assumes JedisClusterCRC16 is correctly implemented\n    assertEquals(node1.clusterKeySlot(\"foo{bar}zap}\").intValue(),\n      JedisClusterCRC16.getSlot(\"foo{bar}zap\"));\n    assertEquals(node1.clusterKeySlot(\"{user1000}.following\").intValue(),\n      JedisClusterCRC16.getSlot(\"{user1000}.following\"));\n  }\n\n  @Test\n  public void testClusterCountKeysInSlot() {\n    Set<HostAndPort> jedisClusterNode = new HashSet<HostAndPort>();\n    jedisClusterNode.add(new HostAndPort(nodeInfo1.getHost(), nodeInfo1.getPort()));\n    JedisCluster jc = new JedisCluster(jedisClusterNode);\n\n    for (int index = 0; index < 5; index++) {\n      jc.set(\"foo{bar}\" + index, \"hello\");\n    }\n\n    int slot = JedisClusterCRC16.getSlot(\"foo{bar}\");\n    assertEquals(5, node1.clusterCountKeysInSlot(slot).intValue());\n  }\n\n  @Test\n  public void testStableSlotWhenMigratingNodeOrImportingNodeIsNotSpecified()\n      throws InterruptedException {\n    Set<HostAndPort> jedisClusterNode = new HashSet<HostAndPort>();\n    jedisClusterNode.add(new HostAndPort(nodeInfo1.getHost(), nodeInfo1.getPort()));\n    JedisCluster jc = new JedisCluster(jedisClusterNode);\n\n    int slot51 = JedisClusterCRC16.getSlot(\"51\");\n    jc.set(\"51\", \"foo\");\n    // node2 is responsible of taking care of slot51 (7186)\n\n    node3.clusterSetSlotImporting(slot51, JedisClusterTestUtil.getNodeId(node2.clusterNodes()));\n    assertEquals(\"foo\", jc.get(\"51\"));\n    node3.clusterSetSlotStable(slot51);\n    assertEquals(\"foo\", jc.get(\"51\"));\n\n    node2.clusterSetSlotMigrating(slot51, JedisClusterTestUtil.getNodeId(node3.clusterNodes()));\n    // assertEquals(\"foo\", jc.get(\"51\")); // it leads Max Redirections\n    node2.clusterSetSlotStable(slot51);\n    assertEquals(\"foo\", jc.get(\"51\"));\n  }\n\n  @Test(expected = JedisConnectionException.class)\n  public void testIfPoolConfigAppliesToClusterPools() {\n    GenericObjectPoolConfig config = new GenericObjectPoolConfig();\n    config.setMaxTotal(0);\n    config.setMaxWaitMillis(2000);\n    Set<HostAndPort> jedisClusterNode = new HashSet<HostAndPort>();\n    jedisClusterNode.add(new HostAndPort(\"127.0.0.1\", 7379));\n    JedisCluster jc = new JedisCluster(jedisClusterNode, config);\n    jc.set(\"52\", \"poolTestValue\");\n  }\n\n  @Test\n  public void testCloseable() throws IOException {\n    Set<HostAndPort> jedisClusterNode = new HashSet<HostAndPort>();\n    jedisClusterNode.add(new HostAndPort(nodeInfo1.getHost(), nodeInfo1.getPort()));\n\n    JedisCluster jc = null;\n    try {\n      jc = new JedisCluster(jedisClusterNode);\n      jc.set(\"51\", \"foo\");\n    } finally {\n      if (jc != null) {\n        jc.close();\n      }\n    }\n\n    Iterator<JedisPool> poolIterator = jc.getClusterNodes().values().iterator();\n    while (poolIterator.hasNext()) {\n      JedisPool pool = poolIterator.next();\n      try {\n        pool.getResource();\n        fail(\"JedisCluster's internal pools should be already destroyed\");\n      } catch (JedisConnectionException e) {\n        // ok to go...\n      }\n    }\n  }\n\n  @Test\n  public void testJedisClusterTimeout() {\n    Set<HostAndPort> jedisClusterNode = new HashSet<HostAndPort>();\n    jedisClusterNode.add(new HostAndPort(nodeInfo1.getHost(), nodeInfo1.getPort()));\n\n    JedisCluster jc = new JedisCluster(jedisClusterNode, 4000);\n\n    for (JedisPool pool : jc.getClusterNodes().values()) {\n      Jedis jedis = pool.getResource();\n      assertEquals(jedis.getClient().getConnectionTimeout(), 4000);\n      assertEquals(jedis.getClient().getSoTimeout(), 4000);\n      jedis.close();\n    }\n\n  }\n\n  @Test\n  public void testJedisClusterRunsWithMultithreaded() throws InterruptedException,\n      ExecutionException, IOException {\n    Set<HostAndPort> jedisClusterNode = new HashSet<HostAndPort>();\n    jedisClusterNode.add(new HostAndPort(\"127.0.0.1\", 7379));\n    final JedisCluster jc = new JedisCluster(jedisClusterNode);\n    jc.set(\"foo\", \"bar\");\n\n    ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 100, 0, TimeUnit.SECONDS,\n        new ArrayBlockingQueue<Runnable>(10));\n    List<Future<String>> futures = new ArrayList<Future<String>>();\n    for (int i = 0; i < 50; i++) {\n      executor.submit(new Callable<String>() {\n        @Override\n        public String call() throws Exception {\n          // FIXME : invalidate slot cache from JedisCluster to test\n          // random connection also does work\n          return jc.get(\"foo\");\n        }\n      });\n    }\n\n    for (Future<String> future : futures) {\n      String value = future.get();\n      assertEquals(\"bar\", value);\n    }\n\n    jc.close();\n  }\n\n  @Test(timeout = 2000)\n  public void testReturnConnectionOnJedisConnectionException() throws InterruptedException {\n    Set<HostAndPort> jedisClusterNode = new HashSet<HostAndPort>();\n    jedisClusterNode.add(new HostAndPort(\"127.0.0.1\", 7379));\n    JedisPoolConfig config = new JedisPoolConfig();\n    config.setMaxTotal(1);\n    JedisCluster jc = new JedisCluster(jedisClusterNode, config);\n\n    Jedis j = jc.getClusterNodes().get(\"127.0.0.1:7380\").getResource();\n    ClientKillerUtil.tagClient(j, \"DEAD\");\n    ClientKillerUtil.killClient(j, \"DEAD\");\n    j.close();\n\n    jc.get(\"test\");\n  }\n\n  @Test(expected = JedisClusterMaxRedirectionsException.class, timeout = 2000)\n  public void testReturnConnectionOnRedirection() {\n    Set<HostAndPort> jedisClusterNode = new HashSet<HostAndPort>();\n    jedisClusterNode.add(new HostAndPort(\"127.0.0.1\", 7379));\n    JedisPoolConfig config = new JedisPoolConfig();\n    config.setMaxTotal(1);\n    JedisCluster jc = new JedisCluster(jedisClusterNode, 0, 2, config);\n\n    // This will cause an infinite redirection between node 2 and 3\n    node3.clusterSetSlotMigrating(15363, JedisClusterTestUtil.getNodeId(node2.clusterNodes()));\n    jc.get(\"e\");\n  }\n\n  private static String getNodeServingSlotRange(String infoOutput) {\n    // f4f3dc4befda352a4e0beccf29f5e8828438705d 127.0.0.1:7380 master - 0\n    // 1394372400827 0 connected 5461-10922\n    for (String infoLine : infoOutput.split(\"\\n\")) {\n      if (infoLine.contains(\"myself\")) {\n        try {\n          return infoLine.split(\" \")[8];\n        } catch (ArrayIndexOutOfBoundsException e) {\n          return null;\n        }\n      }\n    }\n    return null;\n  }\n\n  private void assertNodeHandshakeEnded(Jedis node, int timeoutMs) {\n    int sleepInterval = 100;\n    for (int sleepTime = 0; sleepTime <= timeoutMs; sleepTime += sleepInterval) {\n      boolean isHandshaking = isAnyNodeHandshaking(node);\n      if (!isHandshaking) return;\n\n      try {\n        Thread.sleep(sleepInterval);\n      } catch (InterruptedException e) {\n      }\n    }\n\n    throw new JedisException(\"Node handshaking is not ended\");\n  }\n\n  private boolean isAnyNodeHandshaking(Jedis node) {\n    String infoOutput = node.clusterNodes();\n    for (String infoLine : infoOutput.split(\"\\n\")) {\n      if (infoLine.contains(\"handshake\")) {\n        return true;\n      }\n    }\n    return false;\n  }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/JedisPoolTest.java",
    "content": "package redis.clients.jedis.tests;\n\nimport java.net.URI;\nimport java.net.URISyntaxException;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport org.apache.commons.pool2.PooledObject;\nimport org.apache.commons.pool2.PooledObjectFactory;\nimport org.apache.commons.pool2.impl.DefaultPooledObject;\nimport org.apache.commons.pool2.impl.GenericObjectPoolConfig;\nimport org.junit.Assert;\nimport org.junit.Test;\n\nimport redis.clients.jedis.HostAndPort;\nimport redis.clients.jedis.Jedis;\nimport redis.clients.jedis.JedisPool;\nimport redis.clients.jedis.JedisPoolConfig;\nimport redis.clients.jedis.Transaction;\nimport redis.clients.jedis.exceptions.InvalidURIException;\nimport redis.clients.jedis.exceptions.JedisConnectionException;\nimport redis.clients.jedis.exceptions.JedisException;\n\npublic class JedisPoolTest extends Assert {\n  private static HostAndPort hnp = HostAndPortUtil.getRedisServers().get(0);\n\n  @Test\n  public void checkConnections() {\n    JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.getHost(), hnp.getPort(), 2000);\n    Jedis jedis = pool.getResource();\n    jedis.auth(\"foobared\");\n    jedis.set(\"foo\", \"bar\");\n    assertEquals(\"bar\", jedis.get(\"foo\"));\n    jedis.close();\n    pool.destroy();\n    assertTrue(pool.isClosed());\n  }\n\n  @Test\n  public void checkCloseableConnections() throws Exception {\n    JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.getHost(), hnp.getPort(), 2000);\n    Jedis jedis = pool.getResource();\n    jedis.auth(\"foobared\");\n    jedis.set(\"foo\", \"bar\");\n    assertEquals(\"bar\", jedis.get(\"foo\"));\n    jedis.close();\n    pool.close();\n    assertTrue(pool.isClosed());\n  }\n\n  @Test\n  public void checkConnectionWithDefaultPort() {\n    JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.getHost(), hnp.getPort());\n    Jedis jedis = pool.getResource();\n    jedis.auth(\"foobared\");\n    jedis.set(\"foo\", \"bar\");\n    assertEquals(\"bar\", jedis.get(\"foo\"));\n    jedis.close();\n    pool.destroy();\n    assertTrue(pool.isClosed());\n  }\n\n  @Test\n  public void checkJedisIsReusedWhenReturned() {\n\n    JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.getHost(), hnp.getPort());\n    Jedis jedis = pool.getResource();\n    jedis.auth(\"foobared\");\n    jedis.set(\"foo\", \"0\");\n    jedis.close();\n\n    jedis = pool.getResource();\n    jedis.auth(\"foobared\");\n    jedis.incr(\"foo\");\n    jedis.close();\n    pool.destroy();\n    assertTrue(pool.isClosed());\n  }\n\n  @Test\n  public void checkPoolRepairedWhenJedisIsBroken() {\n    JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.getHost(), hnp.getPort());\n    Jedis jedis = pool.getResource();\n    jedis.auth(\"foobared\");\n    jedis.quit();\n    jedis.close();\n\n    jedis = pool.getResource();\n    jedis.auth(\"foobared\");\n    jedis.incr(\"foo\");\n    jedis.close();\n    pool.destroy();\n    assertTrue(pool.isClosed());\n  }\n\n  @Test(expected = JedisConnectionException.class)\n  public void checkPoolOverflow() {\n    GenericObjectPoolConfig config = new GenericObjectPoolConfig();\n    config.setMaxTotal(1);\n    config.setBlockWhenExhausted(false);\n    JedisPool pool = new JedisPool(config, hnp.getHost(), hnp.getPort());\n    Jedis jedis = pool.getResource();\n    jedis.auth(\"foobared\");\n    jedis.set(\"foo\", \"0\");\n\n    Jedis newJedis = pool.getResource();\n    newJedis.auth(\"foobared\");\n    newJedis.incr(\"foo\");\n  }\n\n  @Test\n  public void securePool() {\n    JedisPoolConfig config = new JedisPoolConfig();\n    config.setTestOnBorrow(true);\n    JedisPool pool = new JedisPool(config, hnp.getHost(), hnp.getPort(), 2000, \"foobared\");\n    Jedis jedis = pool.getResource();\n    jedis.set(\"foo\", \"bar\");\n    jedis.close();\n    pool.destroy();\n    assertTrue(pool.isClosed());\n  }\n\n  @Test\n  public void nonDefaultDatabase() {\n    JedisPool pool0 = new JedisPool(new JedisPoolConfig(), hnp.getHost(), hnp.getPort(), 2000,\n        \"foobared\");\n    Jedis jedis0 = pool0.getResource();\n    jedis0.set(\"foo\", \"bar\");\n    assertEquals(\"bar\", jedis0.get(\"foo\"));\n    jedis0.close();\n    pool0.destroy();\n    assertTrue(pool0.isClosed());\n\n    JedisPool pool1 = new JedisPool(new JedisPoolConfig(), hnp.getHost(), hnp.getPort(), 2000,\n        \"foobared\", 1);\n    Jedis jedis1 = pool1.getResource();\n    assertNull(jedis1.get(\"foo\"));\n    jedis1.close();\n    pool1.destroy();\n    assertTrue(pool1.isClosed());\n  }\n\n  @Test\n  public void startWithUrlString() {\n    Jedis j = new Jedis(\"localhost\", 6380);\n    j.auth(\"foobared\");\n    j.select(2);\n    j.set(\"foo\", \"bar\");\n    JedisPool pool = new JedisPool(\"redis://:foobared@localhost:6380/2\");\n    Jedis jedis = pool.getResource();\n    assertEquals(\"PONG\", jedis.ping());\n    assertEquals(\"bar\", jedis.get(\"foo\"));\n  }\n\n  @Test\n  public void startWithUrl() throws URISyntaxException {\n    Jedis j = new Jedis(\"localhost\", 6380);\n    j.auth(\"foobared\");\n    j.select(2);\n    j.set(\"foo\", \"bar\");\n    JedisPool pool = new JedisPool(new URI(\"redis://:foobared@localhost:6380/2\"));\n    Jedis jedis = pool.getResource();\n    assertEquals(\"PONG\", jedis.ping());\n    assertEquals(\"bar\", jedis.get(\"foo\"));\n  }\n\n  @Test(expected = InvalidURIException.class)\n  public void shouldThrowInvalidURIExceptionForInvalidURI() throws URISyntaxException {\n    JedisPool pool = new JedisPool(new URI(\"localhost:6380\"));\n  }\n\n  @Test\n  public void allowUrlWithNoDBAndNoPassword() throws URISyntaxException {\n    new JedisPool(\"redis://localhost:6380\");\n    new JedisPool(new URI(\"redis://localhost:6380\"));\n  }\n\n  @Test\n  public void selectDatabaseOnActivation() {\n    JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.getHost(), hnp.getPort(), 2000,\n        \"foobared\");\n\n    Jedis jedis0 = pool.getResource();\n    assertEquals(0, jedis0.getDB());\n\n    jedis0.select(1);\n    assertEquals(1, jedis0.getDB());\n\n    jedis0.close();\n\n    Jedis jedis1 = pool.getResource();\n    assertTrue(\"Jedis instance was not reused\", jedis1 == jedis0);\n    assertEquals(0, jedis1.getDB());\n\n    jedis1.close();\n    pool.destroy();\n    assertTrue(pool.isClosed());\n  }\n\n  @Test\n  public void customClientName() {\n    JedisPool pool0 = new JedisPool(new JedisPoolConfig(), hnp.getHost(), hnp.getPort(), 2000,\n        \"foobared\", 0, \"my_shiny_client_name\");\n\n    Jedis jedis = pool0.getResource();\n\n    assertEquals(\"my_shiny_client_name\", jedis.clientGetname());\n\n    jedis.close();\n    pool0.destroy();\n    assertTrue(pool0.isClosed());\n  }\n\n  @Test\n  public void returnResourceDestroysResourceOnException() {\n\n    class CrashingJedis extends Jedis {\n      @Override\n      public void resetState() {\n        throw new RuntimeException();\n      }\n    }\n\n    final AtomicInteger destroyed = new AtomicInteger(0);\n\n    class CrashingJedisPooledObjectFactory implements PooledObjectFactory<Jedis> {\n\n      @Override\n      public PooledObject<Jedis> makeObject() throws Exception {\n        return new DefaultPooledObject<Jedis>(new CrashingJedis());\n      }\n\n      @Override\n      public void destroyObject(PooledObject<Jedis> p) throws Exception {\n        destroyed.incrementAndGet();\n      }\n\n      @Override\n      public boolean validateObject(PooledObject<Jedis> p) {\n        return true;\n      }\n\n      @Override\n      public void activateObject(PooledObject<Jedis> p) throws Exception {\n      }\n\n      @Override\n      public void passivateObject(PooledObject<Jedis> p) throws Exception {\n      }\n    }\n\n    GenericObjectPoolConfig config = new GenericObjectPoolConfig();\n    config.setMaxTotal(1);\n    JedisPool pool = new JedisPool(config, hnp.getHost(), hnp.getPort(), 2000, \"foobared\");\n    pool.initPool(config, new CrashingJedisPooledObjectFactory());\n    Jedis crashingJedis = pool.getResource();\n\n    try {\n      crashingJedis.close();\n    } catch (Exception ignored) {\n    }\n\n    assertEquals(destroyed.get(), 1);\n  }\n\n  @Test\n  public void returnResourceShouldResetState() {\n    GenericObjectPoolConfig config = new GenericObjectPoolConfig();\n    config.setMaxTotal(1);\n    config.setBlockWhenExhausted(false);\n    JedisPool pool = new JedisPool(config, hnp.getHost(), hnp.getPort(), 2000, \"foobared\");\n\n    Jedis jedis = pool.getResource();\n    try {\n      jedis.set(\"hello\", \"jedis\");\n      Transaction t = jedis.multi();\n      t.set(\"hello\", \"world\");\n    } finally {\n      jedis.close();\n    }\n\n    Jedis jedis2 = pool.getResource();\n    try {\n      assertTrue(jedis == jedis2);\n      assertEquals(\"jedis\", jedis2.get(\"hello\"));\n    } finally {\n      jedis2.close();\n    }\n\n    pool.destroy();\n    assertTrue(pool.isClosed());\n  }\n\n  @Test\n  public void checkResourceIsCloseable() {\n    GenericObjectPoolConfig config = new GenericObjectPoolConfig();\n    config.setMaxTotal(1);\n    config.setBlockWhenExhausted(false);\n    JedisPool pool = new JedisPool(config, hnp.getHost(), hnp.getPort(), 2000, \"foobared\");\n\n    Jedis jedis = pool.getResource();\n    try {\n      jedis.set(\"hello\", \"jedis\");\n    } finally {\n      jedis.close();\n    }\n\n    Jedis jedis2 = pool.getResource();\n    try {\n      assertEquals(jedis, jedis2);\n    } finally {\n      jedis2.close();\n    }\n  }\n\n  @Test\n  public void getNumActiveIsNegativeWhenPoolIsClosed() {\n    JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.getHost(), hnp.getPort(), 2000,\n        \"foobared\", 0, \"my_shiny_client_name\");\n\n    pool.destroy();\n    assertTrue(pool.getNumActive() < 0);\n  }\n\n  @Test\n  public void getNumActiveReturnsTheCorrectNumber() {\n    JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.getHost(), hnp.getPort(), 2000);\n    Jedis jedis = pool.getResource();\n    jedis.auth(\"foobared\");\n    jedis.set(\"foo\", \"bar\");\n    assertEquals(\"bar\", jedis.get(\"foo\"));\n\n    assertEquals(1, pool.getNumActive());\n\n    Jedis jedis2 = pool.getResource();\n    jedis.auth(\"foobared\");\n    jedis.set(\"foo\", \"bar\");\n\n    assertEquals(2, pool.getNumActive());\n\n    jedis.close();\n    assertEquals(1, pool.getNumActive());\n\n    jedis2.close();\n\n    assertEquals(0, pool.getNumActive());\n\n    pool.destroy();\n  }\n\n  @Test\n  public void testAddObject() {\n    JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.getHost(), hnp.getPort(), 2000);\n    pool.addObjects(1);\n    assertEquals(pool.getNumIdle(), 1);\n    pool.destroy();\n\n  }\n\n  @Test\n  public void testCloseConnectionOnMakeObject() {\n    JedisPoolConfig config = new JedisPoolConfig();\n    config.setTestOnBorrow(true);\n    JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.getHost(), hnp.getPort(), 2000, \"wrong pass\");\n    Jedis jedis = new Jedis(\"redis://:foobared@localhost:6379/\");\n    int currentClientCount = getClientCount(jedis.clientList());\n    try {\n      pool.getResource();\n      fail(\"Should throw exception as password is incorrect.\");\n    } catch (Exception e) {\n      assertEquals(currentClientCount, getClientCount(jedis.clientList()));\n    }\n\n  }\n\n  private int getClientCount(final String clientList) {\n    return clientList.split(\"\\n\").length;\n  }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/JedisSentinelPoolTest.java",
    "content": "package redis.clients.jedis.tests;\n\nimport java.util.HashSet;\nimport java.util.Set;\n\nimport org.apache.commons.pool2.impl.GenericObjectPoolConfig;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport redis.clients.jedis.HostAndPort;\nimport redis.clients.jedis.Jedis;\nimport redis.clients.jedis.JedisSentinelPool;\nimport redis.clients.jedis.Transaction;\nimport redis.clients.jedis.exceptions.JedisConnectionException;\nimport redis.clients.jedis.exceptions.JedisException;\nimport redis.clients.jedis.tests.utils.JedisSentinelTestUtil;\n\npublic class JedisSentinelPoolTest extends JedisTestBase {\n  private static final String MASTER_NAME = \"mymaster\";\n\n  protected static HostAndPort master = HostAndPortUtil.getRedisServers().get(2);\n  protected static HostAndPort slave1 = HostAndPortUtil.getRedisServers().get(3);\n\n  protected static HostAndPort sentinel1 = HostAndPortUtil.getSentinelServers().get(1);\n  protected static HostAndPort sentinel2 = HostAndPortUtil.getSentinelServers().get(3);\n\n  protected static Jedis sentinelJedis1;\n  protected static Jedis sentinelJedis2;\n\n  protected Set<String> sentinels = new HashSet<String>();\n\n  @Before\n  public void setUp() throws Exception {\n    sentinels.add(sentinel1.toString());\n    sentinels.add(sentinel2.toString());\n\n    sentinelJedis1 = new Jedis(sentinel1.getHost(), sentinel1.getPort());\n    sentinelJedis2 = new Jedis(sentinel2.getHost(), sentinel2.getPort());\n  }\n\n  @Test(expected = JedisConnectionException.class)\n  public void initializeWithNotAvailableSentinelsShouldThrowException() {\n    Set<String> wrongSentinels = new HashSet<String>();\n    wrongSentinels.add(new HostAndPort(\"localhost\", 65432).toString());\n    wrongSentinels.add(new HostAndPort(\"localhost\", 65431).toString());\n\n    JedisSentinelPool pool = new JedisSentinelPool(MASTER_NAME, wrongSentinels);\n    pool.destroy();\n  }\n\n  @Test(expected = JedisException.class)\n  public void initializeWithNotMonitoredMasterNameShouldThrowException() {\n    final String wrongMasterName = \"wrongMasterName\";\n    JedisSentinelPool pool = new JedisSentinelPool(wrongMasterName, sentinels);\n    pool.destroy();\n  }\n\n  @Test\n  public void checkCloseableConnections() throws Exception {\n    GenericObjectPoolConfig config = new GenericObjectPoolConfig();\n\n    JedisSentinelPool pool = new JedisSentinelPool(MASTER_NAME, sentinels, config, 1000,\n        \"foobared\", 2);\n    Jedis jedis = pool.getResource();\n    jedis.auth(\"foobared\");\n    jedis.set(\"foo\", \"bar\");\n    assertEquals(\"bar\", jedis.get(\"foo\"));\n    jedis.close();\n    pool.close();\n    assertTrue(pool.isClosed());\n  }\n\n  @Test\n  public void ensureSafeTwiceFailover() throws InterruptedException {\n    JedisSentinelPool pool = new JedisSentinelPool(MASTER_NAME, sentinels,\n        new GenericObjectPoolConfig(), 1000, \"foobared\", 2);\n\n    forceFailover(pool);\n    // after failover sentinel needs a bit of time to stabilize before a new\n    // failover\n    Thread.sleep(100);\n    forceFailover(pool);\n\n    // you can test failover as much as possible\n  }\n\n  @Test\n  public void returnResourceShouldResetState() {\n    GenericObjectPoolConfig config = new GenericObjectPoolConfig();\n    config.setMaxTotal(1);\n    config.setBlockWhenExhausted(false);\n    JedisSentinelPool pool = new JedisSentinelPool(MASTER_NAME, sentinels, config, 1000,\n        \"foobared\", 2);\n\n    Jedis jedis = pool.getResource();\n    Jedis jedis2 = null;\n\n    try {\n      jedis.set(\"hello\", \"jedis\");\n      Transaction t = jedis.multi();\n      t.set(\"hello\", \"world\");\n      jedis.close();\n\n      jedis2 = pool.getResource();\n\n      assertTrue(jedis == jedis2);\n      assertEquals(\"jedis\", jedis2.get(\"hello\"));\n    } catch (JedisConnectionException e) {\n      if (jedis2 != null) {\n        jedis2 = null;\n      }\n    } finally {\n      jedis2.close();\n\n      pool.destroy();\n    }\n  }\n\n  @Test\n  public void checkResourceIsCloseable() {\n    GenericObjectPoolConfig config = new GenericObjectPoolConfig();\n    config.setMaxTotal(1);\n    config.setBlockWhenExhausted(false);\n    JedisSentinelPool pool = new JedisSentinelPool(MASTER_NAME, sentinels, config, 1000,\n        \"foobared\", 2);\n\n    Jedis jedis = pool.getResource();\n    try {\n      jedis.set(\"hello\", \"jedis\");\n    } finally {\n      jedis.close();\n    }\n\n    Jedis jedis2 = pool.getResource();\n    try {\n      assertEquals(jedis, jedis2);\n    } finally {\n      jedis2.close();\n    }\n  }\n\n  @Test\n  public void customClientName() {\n    GenericObjectPoolConfig config = new GenericObjectPoolConfig();\n    config.setMaxTotal(1);\n    config.setBlockWhenExhausted(false);\n    JedisSentinelPool pool = new JedisSentinelPool(MASTER_NAME, sentinels, config, 1000,\n        \"foobared\", 0, \"my_shiny_client_name\");\n\n    Jedis jedis = pool.getResource();\n\n    try {\n      assertEquals(\"my_shiny_client_name\", jedis.clientGetname());\n    } finally {\n      jedis.close();\n      pool.destroy();\n    }\n\n    assertTrue(pool.isClosed());\n  }\n\n  private void forceFailover(JedisSentinelPool pool) throws InterruptedException {\n    HostAndPort oldMaster = pool.getCurrentHostMaster();\n\n    // jedis connection should be master\n    Jedis beforeFailoverJedis = pool.getResource();\n    assertEquals(\"PONG\", beforeFailoverJedis.ping());\n\n    waitForFailover(pool, oldMaster);\n\n    Jedis afterFailoverJedis = pool.getResource();\n    assertEquals(\"PONG\", afterFailoverJedis.ping());\n    assertEquals(\"foobared\", afterFailoverJedis.configGet(\"requirepass\").get(1));\n    assertEquals(2, afterFailoverJedis.getDB());\n\n    // returning both connections to the pool should not throw\n    beforeFailoverJedis.close();\n    afterFailoverJedis.close();\n  }\n\n  private void waitForFailover(JedisSentinelPool pool, HostAndPort oldMaster)\n      throws InterruptedException {\n    HostAndPort newMaster = JedisSentinelTestUtil.waitForNewPromotedMaster(MASTER_NAME,\n      sentinelJedis1, sentinelJedis2);\n\n    waitForJedisSentinelPoolRecognizeNewMaster(pool, newMaster);\n  }\n\n  private void waitForJedisSentinelPoolRecognizeNewMaster(JedisSentinelPool pool,\n      HostAndPort newMaster) throws InterruptedException {\n\n    while (true) {\n      HostAndPort currentHostMaster = pool.getCurrentHostMaster();\n\n      if (newMaster.equals(currentHostMaster)) break;\n\n      System.out.println(\"JedisSentinelPool's master is not yet changed, sleep...\");\n\n      Thread.sleep(100);\n    }\n  }\n\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/JedisSentinelTest.java",
    "content": "package redis.clients.jedis.tests;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport redis.clients.jedis.HostAndPort;\nimport redis.clients.jedis.Jedis;\nimport redis.clients.jedis.exceptions.JedisDataException;\nimport redis.clients.jedis.tests.utils.JedisSentinelTestUtil;\n\npublic class JedisSentinelTest extends JedisTestBase {\n  private static final String MASTER_NAME = \"mymaster\";\n  private static final String MONITOR_MASTER_NAME = \"mymastermonitor\";\n  private static final String REMOVE_MASTER_NAME = \"mymasterremove\";\n  private static final String FAILOVER_MASTER_NAME = \"mymasterfailover\";\n  private static final String MASTER_IP = \"127.0.0.1\";\n\n  protected static HostAndPort master = HostAndPortUtil.getRedisServers().get(0);\n  protected static HostAndPort slave = HostAndPortUtil.getRedisServers().get(4);\n  protected static HostAndPort sentinel = HostAndPortUtil.getSentinelServers().get(0);\n\n  protected static HostAndPort sentinelForFailover = HostAndPortUtil.getSentinelServers().get(2);\n  protected static HostAndPort masterForFailover = HostAndPortUtil.getRedisServers().get(5);\n\n  @Before\n  public void setup() throws InterruptedException {\n  }\n\n  @After\n  public void clear() throws InterruptedException {\n    // New Sentinel (after 2.8.1)\n    // when slave promoted to master (slave of no one), New Sentinel force\n    // to restore it (demote)\n    // so, promote(slaveof) slave to master has no effect, not same to old\n    // Sentinel's behavior\n    ensureRemoved(MONITOR_MASTER_NAME);\n    ensureRemoved(REMOVE_MASTER_NAME);\n  }\n\n  @Test\n  public void sentinel() {\n    Jedis j = new Jedis(sentinel.getHost(), sentinel.getPort());\n\n    try {\n      List<Map<String, String>> masters = j.sentinelMasters();\n\n      boolean inMasters = false;\n      for (Map<String, String> master : masters)\n        if (MASTER_NAME.equals(master.get(\"name\"))) inMasters = true;\n\n      assertTrue(inMasters);\n\n      List<String> masterHostAndPort = j.sentinelGetMasterAddrByName(MASTER_NAME);\n      HostAndPort masterFromSentinel = new HostAndPort(masterHostAndPort.get(0),\n          Integer.parseInt(masterHostAndPort.get(1)));\n      assertEquals(master, masterFromSentinel);\n\n      List<Map<String, String>> slaves = j.sentinelSlaves(MASTER_NAME);\n      assertTrue(slaves.size() > 0);\n      assertEquals(master.getPort(), Integer.parseInt(slaves.get(0).get(\"master-port\")));\n\n      // DO NOT RE-RUN TEST TOO FAST, RESET TAKES SOME TIME TO... RESET\n      assertEquals(Long.valueOf(1), j.sentinelReset(MASTER_NAME));\n      assertEquals(Long.valueOf(0), j.sentinelReset(\"woof\" + MASTER_NAME));\n    } finally {\n      j.close();\n    }\n  }\n\n  @Test\n  public void sentinelFailover() throws InterruptedException {\n    Jedis j = new Jedis(sentinelForFailover.getHost(), sentinelForFailover.getPort());\n    Jedis j2 = new Jedis(sentinelForFailover.getHost(), sentinelForFailover.getPort());\n\n    try {\n      List<String> masterHostAndPort = j.sentinelGetMasterAddrByName(FAILOVER_MASTER_NAME);\n      HostAndPort currentMaster = new HostAndPort(masterHostAndPort.get(0),\n          Integer.parseInt(masterHostAndPort.get(1)));\n\n      JedisSentinelTestUtil.waitForNewPromotedMaster(FAILOVER_MASTER_NAME, j, j2);\n\n      masterHostAndPort = j.sentinelGetMasterAddrByName(FAILOVER_MASTER_NAME);\n      HostAndPort newMaster = new HostAndPort(masterHostAndPort.get(0),\n          Integer.parseInt(masterHostAndPort.get(1)));\n\n      assertNotEquals(newMaster, currentMaster);\n    } finally {\n      j.close();\n    }\n\n  }\n\n  @Test\n  public void sentinelMonitor() {\n    Jedis j = new Jedis(sentinel.getHost(), sentinel.getPort());\n\n    try {\n      // monitor new master\n      String result = j.sentinelMonitor(MONITOR_MASTER_NAME, MASTER_IP, master.getPort(), 1);\n      assertEquals(\"OK\", result);\n\n      // already monitored\n      try {\n        j.sentinelMonitor(MONITOR_MASTER_NAME, MASTER_IP, master.getPort(), 1);\n        fail();\n      } catch (JedisDataException e) {\n        // pass\n      }\n    } finally {\n      j.close();\n    }\n  }\n\n  @Test\n  public void sentinelRemove() {\n    Jedis j = new Jedis(sentinel.getHost(), sentinel.getPort());\n\n    try {\n      ensureMonitored(sentinel, REMOVE_MASTER_NAME, MASTER_IP, master.getPort(), 1);\n\n      String result = j.sentinelRemove(REMOVE_MASTER_NAME);\n      assertEquals(\"OK\", result);\n\n      // not exist\n      try {\n        result = j.sentinelRemove(REMOVE_MASTER_NAME);\n        assertNotEquals(\"OK\", result);\n        fail();\n      } catch (JedisDataException e) {\n        // pass\n      }\n    } finally {\n      j.close();\n    }\n  }\n\n  @Test\n  public void sentinelSet() {\n    Jedis j = new Jedis(sentinel.getHost(), sentinel.getPort());\n\n    try {\n      Map<String, String> parameterMap = new HashMap<String, String>();\n      parameterMap.put(\"down-after-milliseconds\", String.valueOf(1234));\n      parameterMap.put(\"parallel-syncs\", String.valueOf(3));\n      parameterMap.put(\"quorum\", String.valueOf(2));\n      j.sentinelSet(MASTER_NAME, parameterMap);\n\n      List<Map<String, String>> masters = j.sentinelMasters();\n      for (Map<String, String> master : masters) {\n        if (master.get(\"name\").equals(MASTER_NAME)) {\n          assertEquals(1234, Integer.parseInt(master.get(\"down-after-milliseconds\")));\n          assertEquals(3, Integer.parseInt(master.get(\"parallel-syncs\")));\n          assertEquals(2, Integer.parseInt(master.get(\"quorum\")));\n        }\n      }\n\n      parameterMap.put(\"quorum\", String.valueOf(1));\n      j.sentinelSet(MASTER_NAME, parameterMap);\n    } finally {\n      j.close();\n    }\n  }\n\n  private void ensureMonitored(HostAndPort sentinel, String masterName, String ip, int port,\n      int quorum) {\n    Jedis j = new Jedis(sentinel.getHost(), sentinel.getPort());\n    try {\n      j.sentinelMonitor(masterName, ip, port, quorum);\n    } catch (JedisDataException e) {\n    } finally {\n      j.close();\n    }\n  }\n\n  private void ensureRemoved(String masterName) {\n    Jedis j = new Jedis(sentinel.getHost(), sentinel.getPort());\n    try {\n      j.sentinelRemove(masterName);\n    } catch (JedisDataException e) {\n    } finally {\n      j.close();\n    }\n  }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/JedisTest.java",
    "content": "package redis.clients.jedis.tests;\n\nimport java.io.IOException;\nimport java.net.URI;\nimport java.net.URISyntaxException;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport org.junit.Test;\n\nimport redis.clients.jedis.BinaryJedis;\nimport redis.clients.jedis.Jedis;\nimport redis.clients.jedis.JedisShardInfo;\nimport redis.clients.jedis.Protocol;\nimport redis.clients.jedis.exceptions.InvalidURIException;\nimport redis.clients.jedis.exceptions.JedisConnectionException;\nimport redis.clients.jedis.exceptions.JedisDataException;\nimport redis.clients.jedis.exceptions.JedisException;\nimport redis.clients.jedis.tests.commands.JedisCommandTestBase;\nimport redis.clients.util.SafeEncoder;\n\npublic class JedisTest extends JedisCommandTestBase {\n  @Test\n  public void useWithoutConnecting() {\n    Jedis jedis = new Jedis(\"localhost\");\n    jedis.auth(\"foobared\");\n    jedis.dbSize();\n  }\n\n  @Test\n  public void checkBinaryData() {\n    byte[] bigdata = new byte[1777];\n    for (int b = 0; b < bigdata.length; b++) {\n      bigdata[b] = (byte) ((byte) b % 255);\n    }\n    Map<String, String> hash = new HashMap<String, String>();\n    hash.put(\"data\", SafeEncoder.encode(bigdata));\n\n    String status = jedis.hmset(\"foo\", hash);\n    assertEquals(\"OK\", status);\n    assertEquals(hash, jedis.hgetAll(\"foo\"));\n  }\n\n  @Test\n  public void connectWithShardInfo() {\n    JedisShardInfo shardInfo = new JedisShardInfo(\"localhost\", Protocol.DEFAULT_PORT);\n    shardInfo.setPassword(\"foobared\");\n    Jedis jedis = new Jedis(shardInfo);\n    jedis.get(\"foo\");\n  }\n\n  @Test(expected = JedisConnectionException.class)\n  public void timeoutConnection() throws Exception {\n    jedis = new Jedis(\"localhost\", 6379, 15000);\n    jedis.auth(\"foobared\");\n    jedis.configSet(\"timeout\", \"1\");\n    Thread.sleep(2000);\n    jedis.hmget(\"foobar\", \"foo\");\n  }\n\n  @Test(expected = JedisConnectionException.class)\n  public void timeoutConnectionWithURI() throws Exception {\n    jedis = new Jedis(new URI(\"redis://:foobared@localhost:6380/2\"), 15000);\n    jedis.configSet(\"timeout\", \"1\");\n    Thread.sleep(2000);\n    jedis.hmget(\"foobar\", \"foo\");\n  }\n\n  @Test(expected = JedisDataException.class)\n  public void failWhenSendingNullValues() {\n    jedis.set(\"foo\", null);\n  }\n\n  @Test(expected = InvalidURIException.class)\n  public void shouldThrowInvalidURIExceptionForInvalidURI() throws URISyntaxException {\n    Jedis j = new Jedis(new URI(\"localhost:6380\"));\n    j.ping();\n  }\n\n  @Test\n  public void shouldReconnectToSameDB() throws IOException {\n    jedis.select(1);\n    jedis.set(\"foo\", \"bar\");\n    jedis.getClient().getSocket().shutdownInput();\n    jedis.getClient().getSocket().shutdownOutput();\n    assertEquals(\"bar\", jedis.get(\"foo\"));\n  }\n\n  @Test\n  public void startWithUrlString() {\n    Jedis j = new Jedis(\"localhost\", 6380);\n    j.auth(\"foobared\");\n    j.select(2);\n    j.set(\"foo\", \"bar\");\n    Jedis jedis = new Jedis(\"redis://:foobared@localhost:6380/2\");\n    assertEquals(\"PONG\", jedis.ping());\n    assertEquals(\"bar\", jedis.get(\"foo\"));\n  }\n\n  @Test\n  public void startWithUrl() throws URISyntaxException {\n    Jedis j = new Jedis(\"localhost\", 6380);\n    j.auth(\"foobared\");\n    j.select(2);\n    j.set(\"foo\", \"bar\");\n    Jedis jedis = new Jedis(new URI(\"redis://:foobared@localhost:6380/2\"));\n    assertEquals(\"PONG\", jedis.ping());\n    assertEquals(\"bar\", jedis.get(\"foo\"));\n  }\n\n  @Test\n  public void shouldNotUpdateDbIndexIfSelectFails() throws URISyntaxException {\n    int currentDb = jedis.getDB();\n    try {\n      int invalidDb = -1;\n      jedis.select(invalidDb);\n\n      fail(\"Should throw an exception if tried to select invalid db\");\n    } catch (JedisException e) {\n      assertEquals(currentDb, jedis.getDB());\n    }\n  }\n\n  @Test\n  public void allowUrlWithNoDBAndNoPassword() {\n    Jedis jedis = new Jedis(\"redis://localhost:6380\");\n    jedis.auth(\"foobared\");\n    assertEquals(jedis.getClient().getHost(), \"localhost\");\n    assertEquals(jedis.getClient().getPort(), 6380);\n    assertEquals(jedis.getDB(), 0);\n\n    jedis = new Jedis(\"redis://localhost:6380/\");\n    jedis.auth(\"foobared\");\n    assertEquals(jedis.getClient().getHost(), \"localhost\");\n    assertEquals(jedis.getClient().getPort(), 6380);\n    assertEquals(jedis.getDB(), 0);\n  }\n\n  @Test\n  public void checkCloseable() {\n    jedis.close();\n    BinaryJedis bj = new BinaryJedis(\"localhost\");\n    bj.connect();\n    bj.close();\n  }\n\n  @Test\n  public void checkDisconnectOnQuit() {\n    jedis.quit();\n    assertFalse(jedis.getClient().isConnected());\n  }\n\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/JedisTestBase.java",
    "content": "package redis.clients.jedis.tests;\n\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Set;\n\nimport org.junit.Assert;\n\npublic abstract class JedisTestBase extends Assert {\n  protected void assertEquals(List<byte[]> expected, List<byte[]> actual) {\n    assertEquals(expected.size(), actual.size());\n    for (int n = 0; n < expected.size(); n++) {\n      assertArrayEquals(expected.get(n), actual.get(n));\n    }\n  }\n\n  protected void assertEquals(Set<byte[]> expected, Set<byte[]> actual) {\n    assertEquals(expected.size(), actual.size());\n    Iterator<byte[]> iterator = expected.iterator();\n    Iterator<byte[]> iterator2 = actual.iterator();\n    while (iterator.hasNext() || iterator2.hasNext()) {\n      assertArrayEquals(iterator.next(), iterator2.next());\n    }\n  }\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/KeyMergeUtilTest.java",
    "content": "package redis.clients.jedis.tests;\n\nimport org.junit.Test;\n\nimport redis.clients.util.KeyMergeUtil;\nimport redis.clients.util.SafeEncoder;\nimport static org.junit.Assert.*;\n\npublic class KeyMergeUtilTest {\n\n  @Test\n  public void testMergeBinaryKeys() throws Exception {\n    byte[] key = SafeEncoder.encode(\"hello\");\n    byte[][] keys = new byte[2][];\n    keys[0] = SafeEncoder.encode(\"world\");\n    keys[1] = SafeEncoder.encode(\"jedis\");\n\n    byte[][] mergedKeys = KeyMergeUtil.merge(key, keys);\n    assertNotNull(mergedKeys);\n    assertEquals(3, mergedKeys.length);\n    assertEquals(key, mergedKeys[0]);\n    assertEquals(keys[0], mergedKeys[1]);\n    assertEquals(keys[1], mergedKeys[2]);\n  }\n\n  @Test\n  public void testMergeStringKeys() throws Exception {\n    String key = \"hello\";\n    String[] keys = new String[2];\n    keys[0] = \"world\";\n    keys[1] = \"jedis\";\n\n    String[] mergedKeys = KeyMergeUtil.merge(key, keys);\n    assertNotNull(mergedKeys);\n    assertEquals(3, mergedKeys.length);\n    assertEquals(key, mergedKeys[0]);\n    assertEquals(keys[0], mergedKeys[1]);\n    assertEquals(keys[1], mergedKeys[2]);\n  }\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/PipeliningTest.java",
    "content": "package redis.clients.jedis.tests;\n\nimport java.io.IOException;\nimport java.io.UnsupportedEncodingException;\nimport java.util.*;\n\nimport org.hamcrest.CoreMatchers;\nimport org.hamcrest.Matcher;\nimport org.junit.Assert;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport redis.clients.jedis.HostAndPort;\nimport redis.clients.jedis.Jedis;\nimport redis.clients.jedis.Pipeline;\nimport redis.clients.jedis.Response;\nimport redis.clients.jedis.Tuple;\nimport redis.clients.jedis.exceptions.JedisDataException;\nimport redis.clients.util.SafeEncoder;\n\nimport static org.hamcrest.CoreMatchers.equalTo;\n\npublic class PipeliningTest extends Assert {\n  private static HostAndPort hnp = HostAndPortUtil.getRedisServers().get(0);\n\n  private Jedis jedis;\n\n  @Before\n  public void setUp() throws Exception {\n    jedis = new Jedis(hnp.getHost(), hnp.getPort(), 2000);\n    jedis.connect();\n    jedis.auth(\"foobared\");\n    jedis.flushAll();\n  }\n\n  @Test\n  public void pipeline() throws UnsupportedEncodingException {\n    Pipeline p = jedis.pipelined();\n    p.set(\"foo\", \"bar\");\n    p.get(\"foo\");\n    List<Object> results = p.syncAndReturnAll();\n\n    assertEquals(2, results.size());\n    assertEquals(\"OK\", results.get(0));\n    assertEquals(\"bar\", results.get(1));\n\n  }\n\n  @Test\n  public void pipelineResponse() {\n    jedis.set(\"string\", \"foo\");\n    jedis.lpush(\"list\", \"foo\");\n    jedis.hset(\"hash\", \"foo\", \"bar\");\n    jedis.zadd(\"zset\", 1, \"foo\");\n    jedis.sadd(\"set\", \"foo\");\n    jedis.setrange(\"setrange\", 0, \"0123456789\");\n    byte[] bytesForSetRange = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };\n    jedis.setrange(\"setrangebytes\".getBytes(), 0, bytesForSetRange);\n\n    Pipeline p = jedis.pipelined();\n    Response<String> string = p.get(\"string\");\n    Response<String> list = p.lpop(\"list\");\n    Response<String> hash = p.hget(\"hash\", \"foo\");\n    Response<Set<String>> zset = p.zrange(\"zset\", 0, -1);\n    Response<String> set = p.spop(\"set\");\n    Response<Boolean> blist = p.exists(\"list\");\n    Response<Double> zincrby = p.zincrby(\"zset\", 1, \"foo\");\n    Response<Long> zcard = p.zcard(\"zset\");\n    p.lpush(\"list\", \"bar\");\n    Response<List<String>> lrange = p.lrange(\"list\", 0, -1);\n    Response<Map<String, String>> hgetAll = p.hgetAll(\"hash\");\n    p.sadd(\"set\", \"foo\");\n    Response<Set<String>> smembers = p.smembers(\"set\");\n    Response<Set<Tuple>> zrangeWithScores = p.zrangeWithScores(\"zset\", 0, -1);\n    Response<String> getrange = p.getrange(\"setrange\", 1, 3);\n    Response<byte[]> getrangeBytes = p.getrange(\"setrangebytes\".getBytes(), 6, 8);\n    p.sync();\n\n    assertEquals(\"foo\", string.get());\n    assertEquals(\"foo\", list.get());\n    assertEquals(\"bar\", hash.get());\n    assertEquals(\"foo\", zset.get().iterator().next());\n    assertEquals(\"foo\", set.get());\n    assertEquals(false, blist.get());\n    assertEquals(Double.valueOf(2), zincrby.get());\n    assertEquals(Long.valueOf(1), zcard.get());\n    assertEquals(1, lrange.get().size());\n    assertNotNull(hgetAll.get().get(\"foo\"));\n    assertEquals(1, smembers.get().size());\n    assertEquals(1, zrangeWithScores.get().size());\n    assertEquals(\"123\", getrange.get());\n    byte[] expectedGetRangeBytes = { 6, 7, 8 };\n    assertArrayEquals(expectedGetRangeBytes, getrangeBytes.get());\n  }\n\n  @Test\n  public void pipelineResponseWithData() {\n    jedis.zadd(\"zset\", 1, \"foo\");\n\n    Pipeline p = jedis.pipelined();\n    Response<Double> score = p.zscore(\"zset\", \"foo\");\n    p.sync();\n\n    assertNotNull(score.get());\n  }\n\n  @Test\n  public void pipelineBinarySafeHashCommands() {\n    jedis.hset(\"key\".getBytes(), \"f1\".getBytes(), \"v111\".getBytes());\n    jedis.hset(\"key\".getBytes(), \"f22\".getBytes(), \"v2222\".getBytes());\n\n    Pipeline p = jedis.pipelined();\n    Response<Map<byte[], byte[]>> fmap = p.hgetAll(\"key\".getBytes());\n    Response<Set<byte[]>> fkeys = p.hkeys(\"key\".getBytes());\n    Response<List<byte[]>> fordered = p.hmget(\"key\".getBytes(), \"f22\".getBytes(), \"f1\".getBytes());\n    Response<List<byte[]>> fvals = p.hvals(\"key\".getBytes());\n    p.sync();\n\n    assertNotNull(fmap.get());\n    // we have to do these strange contortions because byte[] is not a very\n    // good key\n    // for a java Map. It only works with equality (you need the exact key\n    // object to retrieve\n    // the value) I recommend we switch to using ByteBuffer or something\n    // similar:\n    // http://stackoverflow.com/questions/1058149/using-a-byte-array-as-hashmap-key-java\n    Map<byte[], byte[]> map = fmap.get();\n    Set<byte[]> mapKeys = map.keySet();\n    Iterator<byte[]> iterMap = mapKeys.iterator();\n    byte[] firstMapKey = iterMap.next();\n    byte[] secondMapKey = iterMap.next();\n    assertFalse(iterMap.hasNext());\n    verifyHasBothValues(firstMapKey, secondMapKey, \"f1\".getBytes(), \"f22\".getBytes());\n    byte[] firstMapValue = map.get(firstMapKey);\n    byte[] secondMapValue = map.get(secondMapKey);\n    verifyHasBothValues(firstMapValue, secondMapValue, \"v111\".getBytes(), \"v2222\".getBytes());\n\n    assertNotNull(fkeys.get());\n    Iterator<byte[]> iter = fkeys.get().iterator();\n    byte[] firstKey = iter.next();\n    byte[] secondKey = iter.next();\n    assertFalse(iter.hasNext());\n    verifyHasBothValues(firstKey, secondKey, \"f1\".getBytes(), \"f22\".getBytes());\n\n    assertNotNull(fordered.get());\n    assertArrayEquals(\"v2222\".getBytes(), fordered.get().get(0));\n    assertArrayEquals(\"v111\".getBytes(), fordered.get().get(1));\n\n    assertNotNull(fvals.get());\n    assertEquals(2, fvals.get().size());\n    byte[] firstValue = fvals.get().get(0);\n    byte[] secondValue = fvals.get().get(1);\n    verifyHasBothValues(firstValue, secondValue, \"v111\".getBytes(), \"v2222\".getBytes());\n  }\n\n  private void verifyHasBothValues(byte[] firstKey, byte[] secondKey, byte[] value1, byte[] value2) {\n    assertFalse(Arrays.equals(firstKey, secondKey));\n    assertTrue(Arrays.equals(firstKey, value1) || Arrays.equals(firstKey, value2));\n    assertTrue(Arrays.equals(secondKey, value1) || Arrays.equals(secondKey, value2));\n  }\n\n  @Test\n  public void pipelineSelect() {\n    Pipeline p = jedis.pipelined();\n    p.select(1);\n    p.sync();\n  }\n\n  @Test\n  public void pipelineResponseWithoutData() {\n    jedis.zadd(\"zset\", 1, \"foo\");\n\n    Pipeline p = jedis.pipelined();\n    Response<Double> score = p.zscore(\"zset\", \"bar\");\n    p.sync();\n\n    assertNull(score.get());\n  }\n\n  @Test(expected = JedisDataException.class)\n  public void pipelineResponseWithinPipeline() {\n    jedis.set(\"string\", \"foo\");\n\n    Pipeline p = jedis.pipelined();\n    Response<String> string = p.get(\"string\");\n    string.get();\n    p.sync();\n  }\n\n  @Test\n  public void pipelineWithPubSub() {\n    Pipeline pipelined = jedis.pipelined();\n    Response<Long> p1 = pipelined.publish(\"foo\", \"bar\");\n    Response<Long> p2 = pipelined.publish(\"foo\".getBytes(), \"bar\".getBytes());\n    pipelined.sync();\n    assertEquals(0, p1.get().longValue());\n    assertEquals(0, p2.get().longValue());\n  }\n\n  @Test\n  public void canRetrieveUnsetKey() {\n    Pipeline p = jedis.pipelined();\n    Response<String> shouldNotExist = p.get(UUID.randomUUID().toString());\n    p.sync();\n    assertNull(shouldNotExist.get());\n  }\n\n  @Test\n  public void piplineWithError() {\n    Pipeline p = jedis.pipelined();\n    p.set(\"foo\", \"bar\");\n    Response<Set<String>> error = p.smembers(\"foo\");\n    Response<String> r = p.get(\"foo\");\n    p.sync();\n    try {\n      error.get();\n      fail();\n    } catch (JedisDataException e) {\n      // that is fine we should be here\n    }\n    assertEquals(r.get(), \"bar\");\n  }\n\n  @Test\n  public void multi() {\n    Pipeline p = jedis.pipelined();\n    p.multi();\n    Response<Long> r1 = p.hincrBy(\"a\", \"f1\", -1);\n    Response<Long> r2 = p.hincrBy(\"a\", \"f1\", -2);\n    Response<List<Object>> r3 = p.exec();\n    List<Object> result = p.syncAndReturnAll();\n\n    assertEquals(new Long(-1), r1.get());\n    assertEquals(new Long(-3), r2.get());\n\n    assertEquals(4, result.size());\n\n    assertEquals(\"OK\", result.get(0));\n    assertEquals(\"QUEUED\", result.get(1));\n    assertEquals(\"QUEUED\", result.get(2));\n\n    // 4th result is a list with the results from the multi\n    @SuppressWarnings(\"unchecked\")\n    List<Object> multiResult = (List<Object>) result.get(3);\n    assertEquals(new Long(-1), multiResult.get(0));\n    assertEquals(new Long(-3), multiResult.get(1));\n\n    assertEquals(new Long(-1), r3.get().get(0));\n    assertEquals(new Long(-3), r3.get().get(1));\n\n  }\n\n  @Test\n  public void multiWithMassiveRequests() {\n    Pipeline p = jedis.pipelined();\n    p.multi();\n\n    List<Response<?>> responseList = new ArrayList<Response<?>>();\n    for (int i = 0; i < 100000; i++) {\n      // any operation should be ok, but shouldn't forget about timeout\n      responseList.add(p.setbit(\"test\", 1, true));\n    }\n\n    Response<List<Object>> exec = p.exec();\n    p.sync();\n\n    // we don't need to check return value\n    // if below codes run without throwing Exception, we're ok\n    exec.get();\n\n    for (Response<?> resp : responseList) {\n      resp.get();\n    }\n  }\n\n  @Test\n  public void multiWithSync() {\n    jedis.set(\"foo\", \"314\");\n    jedis.set(\"bar\", \"foo\");\n    jedis.set(\"hello\", \"world\");\n    Pipeline p = jedis.pipelined();\n    Response<String> r1 = p.get(\"bar\");\n    p.multi();\n    Response<String> r2 = p.get(\"foo\");\n    p.exec();\n    Response<String> r3 = p.get(\"hello\");\n    p.sync();\n\n    // before multi\n    assertEquals(\"foo\", r1.get());\n    // It should be readable whether exec's response was built or not\n    assertEquals(\"314\", r2.get());\n    // after multi\n    assertEquals(\"world\", r3.get());\n  }\n\n  @Test(expected = JedisDataException.class)\n  public void pipelineExecShoudThrowJedisDataExceptionWhenNotInMulti() {\n    Pipeline pipeline = jedis.pipelined();\n    pipeline.exec();\n  }\n\n  @Test(expected = JedisDataException.class)\n  public void pipelineDiscardShoudThrowJedisDataExceptionWhenNotInMulti() {\n    Pipeline pipeline = jedis.pipelined();\n    pipeline.discard();\n  }\n\n  @Test(expected = JedisDataException.class)\n  public void pipelineMultiShoudThrowJedisDataExceptionWhenAlreadyInMulti() {\n    Pipeline pipeline = jedis.pipelined();\n    pipeline.multi();\n    pipeline.set(\"foo\", \"3\");\n    pipeline.multi();\n  }\n\n  @Test(expected = JedisDataException.class)\n  public void testJedisThowExceptionWhenInPipeline() {\n    Pipeline pipeline = jedis.pipelined();\n    pipeline.set(\"foo\", \"3\");\n    jedis.get(\"somekey\");\n    fail(\"Can't use jedis instance when in Pipeline\");\n  }\n\n  @Test\n  public void testReuseJedisWhenPipelineIsEmpty() {\n    Pipeline pipeline = jedis.pipelined();\n    pipeline.set(\"foo\", \"3\");\n    pipeline.sync();\n    String result = jedis.get(\"foo\");\n    assertEquals(result, \"3\");\n  }\n\n  @Test\n  public void testResetStateWhenInPipeline() {\n    Pipeline pipeline = jedis.pipelined();\n    pipeline.set(\"foo\", \"3\");\n    jedis.resetState();\n    String result = jedis.get(\"foo\");\n    assertEquals(result, \"3\");\n  }\n\n  @Test\n  public void testDiscardInPipeline() {\n    Pipeline pipeline = jedis.pipelined();\n    pipeline.multi();\n    pipeline.set(\"foo\", \"bar\");\n    Response<String> discard = pipeline.discard();\n    Response<String> get = pipeline.get(\"foo\");\n    pipeline.sync();\n    discard.get();\n    get.get();\n  }\n\n  @Test\n  public void testEval() {\n    String script = \"return 'success!'\";\n\n    Pipeline p = jedis.pipelined();\n    Response<Object> result = p.eval(script);\n    p.sync();\n\n    assertEquals(\"success!\", result.get());\n  }\n\n  @Test\n  public void testEvalWithBinary() {\n    String script = \"return 'success!'\";\n\n    Pipeline p = jedis.pipelined();\n    Response<Object> result = p.eval(SafeEncoder.encode(script));\n    p.sync();\n\n    assertArrayEquals(SafeEncoder.encode(\"success!\"), (byte[]) result.get());\n  }\n\n  @Test\n  public void testEvalKeyAndArg() {\n    String key = \"test\";\n    String arg = \"3\";\n    String script = \"redis.call('INCRBY', KEYS[1], ARGV[1]) redis.call('INCRBY', KEYS[1], ARGV[1])\";\n\n    Pipeline p = jedis.pipelined();\n    p.set(key, \"0\");\n    Response<Object> result0 = p.eval(script, Arrays.asList(key), Arrays.asList(arg));\n    p.incr(key);\n    Response<Object> result1 = p.eval(script, Arrays.asList(key), Arrays.asList(arg));\n    Response<String> result2 = p.get(key);\n    p.sync();\n\n    assertNull(result0.get());\n    assertNull(result1.get());\n    assertEquals(\"13\", result2.get());\n  }\n\n  @Test\n  public void testEvalKeyAndArgWithBinary() {\n    // binary\n    byte[] bKey = SafeEncoder.encode(\"test\");\n    byte[] bArg = SafeEncoder.encode(\"3\");\n    byte[] bScript = SafeEncoder\n        .encode(\"redis.call('INCRBY', KEYS[1], ARGV[1]) redis.call('INCRBY', KEYS[1], ARGV[1])\");\n\n    Pipeline bP = jedis.pipelined();\n    bP.set(bKey, SafeEncoder.encode(\"0\"));\n    Response<Object> bResult0 = bP.eval(bScript, Arrays.asList(bKey), Arrays.asList(bArg));\n    bP.incr(bKey);\n    Response<Object> bResult1 = bP.eval(bScript, Arrays.asList(bKey), Arrays.asList(bArg));\n    Response<byte[]> bResult2 = bP.get(bKey);\n    bP.sync();\n\n    assertNull(bResult0.get());\n    assertNull(bResult1.get());\n    assertArrayEquals(SafeEncoder.encode(\"13\"), bResult2.get());\n  }\n\n  @Test\n  public void testEvalNestedLists() {\n    String script = \"return { {KEYS[1]} , {2} }\";\n\n    Pipeline p = jedis.pipelined();\n    Response<Object> result = p.eval(script, 1, \"key1\");\n    p.sync();\n\n    List<?> results = (List<?>) result.get();\n    assertThat((List<String>) results.get(0), listWithItem(\"key1\"));\n    assertThat((List<Long>) results.get(1), listWithItem(2L));\n  }\n\n  @Test\n  public void testEvalNestedListsWithBinary() {\n    byte[] bScript = SafeEncoder.encode(\"return { {KEYS[1]} , {2} }\");\n    byte[] bKey = SafeEncoder.encode(\"key1\");\n\n    Pipeline p = jedis.pipelined();\n    Response<Object> result = p.eval(bScript, 1, bKey);\n    p.sync();\n\n    List<?> results = (List<?>) result.get();\n    assertThat((List<byte[]>) results.get(0), listWithItem(bKey));\n    assertThat((List<Long>) results.get(1), listWithItem(2L));\n  }\n\n  @Test\n  public void testEvalsha() {\n    String script = \"return 'success!'\";\n    String sha1 = jedis.scriptLoad(script);\n\n    assertTrue(jedis.scriptExists(sha1));\n\n    Pipeline p = jedis.pipelined();\n    Response<Object> result = p.evalsha(sha1);\n    p.sync();\n\n    assertEquals(\"success!\", result.get());\n  }\n\n  @Test\n  public void testEvalshaKeyAndArg() {\n    String key = \"test\";\n    String arg = \"3\";\n    String script = \"redis.call('INCRBY', KEYS[1], ARGV[1]) redis.call('INCRBY', KEYS[1], ARGV[1])\";\n    String sha1 = jedis.scriptLoad(script);\n\n    assertTrue(jedis.scriptExists(sha1));\n\n    Pipeline p = jedis.pipelined();\n    p.set(key, \"0\");\n    Response<Object> result0 = p.evalsha(sha1, Arrays.asList(key), Arrays.asList(arg));\n    p.incr(key);\n    Response<Object> result1 = p.evalsha(sha1, Arrays.asList(key), Arrays.asList(arg));\n    Response<String> result2 = p.get(key);\n    p.sync();\n\n    assertNull(result0.get());\n    assertNull(result1.get());\n    assertEquals(\"13\", result2.get());\n  }\n\n  @Test\n  public void testEvalshaKeyAndArgWithBinary() {\n    byte[] bKey = SafeEncoder.encode(\"test\");\n    byte[] bArg = SafeEncoder.encode(\"3\");\n    String script = \"redis.call('INCRBY', KEYS[1], ARGV[1]) redis.call('INCRBY', KEYS[1], ARGV[1])\";\n    byte[] bScript = SafeEncoder.encode(script);\n    byte[] bSha1 = jedis.scriptLoad(bScript);\n\n    assertTrue(jedis.scriptExists(bSha1) == 1);\n\n    Pipeline p = jedis.pipelined();\n    p.set(bKey, SafeEncoder.encode(\"0\"));\n    Response<Object> result0 = p.evalsha(bSha1, Arrays.asList(bKey), Arrays.asList(bArg));\n    p.incr(bKey);\n    Response<Object> result1 = p.evalsha(bSha1, Arrays.asList(bKey), Arrays.asList(bArg));\n    Response<byte[]> result2 = p.get(bKey);\n    p.sync();\n\n    assertNull(result0.get());\n    assertNull(result1.get());\n    assertArrayEquals(SafeEncoder.encode(\"13\"), result2.get());\n  }\n\n  @Test\n  public void testPipelinedTransactionResponse() {\n\n    String key1 = \"key1\";\n    String val1 = \"val1\";\n\n    String key2 = \"key2\";\n    String val2 = \"val2\";\n\n    String key3 = \"key3\";\n    String field1 = \"field1\";\n    String field2 = \"field2\";\n    String field3 = \"field3\";\n    String field4 = \"field4\";\n\n    String value1 = \"value1\";\n    String value2 = \"value2\";\n    String value3 = \"value3\";\n    String value4 = \"value4\";\n\n    Map<String, String> hashMap = new HashMap<String, String>();\n    hashMap.put(field1, value1);\n    hashMap.put(field2, value2);\n\n    String key4 = \"key4\";\n    Map<String, String> hashMap1 = new HashMap<String, String>();\n    hashMap1.put(field3, value3);\n    hashMap1.put(field4, value4);\n\n    jedis.set(key1, val1);\n    jedis.set(key2, val2);\n    jedis.hmset(key3, hashMap);\n    jedis.hmset(key4, hashMap1);\n\n    Pipeline pipeline = jedis.pipelined();\n    pipeline.multi();\n\n    pipeline.get(key1);\n    pipeline.hgetAll(key2);\n    pipeline.hgetAll(key3);\n    pipeline.get(key4);\n\n    Response<List<Object>> response = pipeline.exec();\n    pipeline.sync();\n\n    List<Object> result = response.get();\n\n    assertEquals(4, result.size());\n\n    assertEquals(\"val1\", result.get(0));\n\n    assertTrue(result.get(1) instanceof JedisDataException);\n\n    Map<String, String> hashMapReceived = (Map<String, String>) result.get(2);\n    Iterator<String> iterator = hashMapReceived.keySet().iterator();\n    String mapKey1 = iterator.next();\n    String mapKey2 = iterator.next();\n    assertFalse(iterator.hasNext());\n    verifyHasBothValues(mapKey1, mapKey2, field1, field2);\n    String mapValue1 = hashMapReceived.get(mapKey1);\n    String mapValue2 = hashMapReceived.get(mapKey2);\n    verifyHasBothValues(mapValue1, mapValue2, value1, value2);\n\n    assertTrue(result.get(3) instanceof JedisDataException);\n  }\n\n  @Test\n  public void testSyncWithNoCommandQueued() {\n    // we need to test with fresh instance of Jedis\n    Jedis jedis2 = new Jedis(hnp.getHost(), hnp.getPort(), 500);\n\n    Pipeline pipeline = jedis2.pipelined();\n    pipeline.sync();\n\n    jedis2.close();\n\n    jedis2 = new Jedis(hnp.getHost(), hnp.getPort(), 500);\n\n    pipeline = jedis2.pipelined();\n    List<Object> resp = pipeline.syncAndReturnAll();\n    assertTrue(resp.isEmpty());\n\n    jedis2.close();\n  }\n\n  @Test\n  public void testCloseable() throws IOException {\n    // we need to test with fresh instance of Jedis\n    Jedis jedis2 = new Jedis(hnp.getHost(), hnp.getPort(), 500);\n    jedis2.auth(\"foobared\");\n\n    Pipeline pipeline = jedis2.pipelined();\n    Response<String> retFuture1 = pipeline.set(\"a\", \"1\");\n    Response<String> retFuture2 = pipeline.set(\"b\", \"2\");\n\n    pipeline.close();\n\n    // it shouldn't meet any exception\n    retFuture1.get();\n    retFuture2.get();\n  }\n\n  @Test\n  public void testCloseableWithMulti() throws IOException {\n    // we need to test with fresh instance of Jedis\n    Jedis jedis2 = new Jedis(hnp.getHost(), hnp.getPort(), 500);\n    jedis2.auth(\"foobared\");\n\n    Pipeline pipeline = jedis2.pipelined();\n    Response<String> retFuture1 = pipeline.set(\"a\", \"1\");\n    Response<String> retFuture2 = pipeline.set(\"b\", \"2\");\n\n    pipeline.multi();\n\n    pipeline.set(\"a\", \"a\");\n    pipeline.set(\"b\", \"b\");\n\n    pipeline.close();\n\n    try {\n      pipeline.exec();\n      fail(\"close should discard transaction\");\n    } catch (JedisDataException e) {\n      assertTrue(e.getMessage().contains(\"EXEC without MULTI\"));\n      // pass\n    }\n\n    // it shouldn't meet any exception\n    retFuture1.get();\n    retFuture2.get();\n  }\n\n  private void verifyHasBothValues(String firstKey, String secondKey, String value1, String value2) {\n    assertFalse(firstKey.equals(secondKey));\n    assertTrue(firstKey.equals(value1) || firstKey.equals(value2));\n    assertTrue(secondKey.equals(value1) || secondKey.equals(value2));\n  }\n\n  private <T> Matcher<Iterable<? super T>> listWithItem(T expected) {\n    return CoreMatchers.<T> hasItem(equalTo(expected));\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/ProtocolTest.java",
    "content": "package redis.clients.jedis.tests;\n\nimport java.io.BufferedInputStream;\nimport java.io.ByteArrayInputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.OutputStream;\nimport java.io.PipedInputStream;\nimport java.io.PipedOutputStream;\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.junit.Test;\n\nimport redis.clients.jedis.Protocol;\nimport redis.clients.util.RedisInputStream;\nimport redis.clients.util.RedisOutputStream;\nimport redis.clients.util.SafeEncoder;\n\npublic class ProtocolTest extends JedisTestBase {\n  @Test\n  public void buildACommand() throws IOException {\n    PipedInputStream pis = new PipedInputStream();\n    BufferedInputStream bis = new BufferedInputStream(pis);\n    PipedOutputStream pos = new PipedOutputStream(pis);\n    RedisOutputStream ros = new RedisOutputStream(pos);\n\n    Protocol.sendCommand(ros, Protocol.Command.GET, \"SOMEKEY\".getBytes(Protocol.CHARSET));\n    ros.flush();\n    pos.close();\n    String expectedCommand = \"*2\\r\\n$3\\r\\nGET\\r\\n$7\\r\\nSOMEKEY\\r\\n\";\n\n    int b;\n    StringBuilder sb = new StringBuilder();\n    while ((b = bis.read()) != -1) {\n      sb.append((char) b);\n    }\n\n    assertEquals(expectedCommand, sb.toString());\n  }\n\n  @Test(expected = IOException.class)\n  public void writeOverflow() throws IOException {\n    RedisOutputStream ros = new RedisOutputStream(new OutputStream() {\n\n      @Override\n      public void write(int b) throws IOException {\n        throw new IOException(\"thrown exception\");\n\n      }\n    });\n\n    ros.write(new byte[8191]);\n\n    try {\n      ros.write((byte) '*');\n    } catch (IOException ioe) {\n    }\n\n    ros.write((byte) '*');\n\n  }\n\n  @Test\n  public void bulkReply() {\n    InputStream is = new ByteArrayInputStream(\"$6\\r\\nfoobar\\r\\n\".getBytes());\n    byte[] response = (byte[]) Protocol.read(new RedisInputStream(is));\n    assertArrayEquals(SafeEncoder.encode(\"foobar\"), response);\n  }\n\n  @Test\n  public void fragmentedBulkReply() {\n    FragmentedByteArrayInputStream fis = new FragmentedByteArrayInputStream(\n        \"$30\\r\\n012345678901234567890123456789\\r\\n\".getBytes());\n    byte[] response = (byte[]) Protocol.read(new RedisInputStream(fis));\n    assertArrayEquals(SafeEncoder.encode(\"012345678901234567890123456789\"), response);\n  }\n\n  @Test\n  public void nullBulkReply() {\n    InputStream is = new ByteArrayInputStream(\"$-1\\r\\n\".getBytes());\n    String response = (String) Protocol.read(new RedisInputStream(is));\n    assertEquals(null, response);\n  }\n\n  @Test\n  public void singleLineReply() {\n    InputStream is = new ByteArrayInputStream(\"+OK\\r\\n\".getBytes());\n    byte[] response = (byte[]) Protocol.read(new RedisInputStream(is));\n    assertArrayEquals(SafeEncoder.encode(\"OK\"), response);\n  }\n\n  @Test\n  public void integerReply() {\n    InputStream is = new ByteArrayInputStream(\":123\\r\\n\".getBytes());\n    long response = (Long) Protocol.read(new RedisInputStream(is));\n    assertEquals(123, response);\n  }\n\n  @SuppressWarnings(\"unchecked\")\n  @Test\n  public void multiBulkReply() {\n    InputStream is = new ByteArrayInputStream(\n        \"*4\\r\\n$3\\r\\nfoo\\r\\n$3\\r\\nbar\\r\\n$5\\r\\nHello\\r\\n$5\\r\\nWorld\\r\\n\".getBytes());\n    List<byte[]> response = (List<byte[]>) Protocol.read(new RedisInputStream(is));\n    List<byte[]> expected = new ArrayList<byte[]>();\n    expected.add(SafeEncoder.encode(\"foo\"));\n    expected.add(SafeEncoder.encode(\"bar\"));\n    expected.add(SafeEncoder.encode(\"Hello\"));\n    expected.add(SafeEncoder.encode(\"World\"));\n\n    assertEquals(expected, response);\n  }\n\n  @SuppressWarnings(\"unchecked\")\n  @Test\n  public void nullMultiBulkReply() {\n    InputStream is = new ByteArrayInputStream(\"*-1\\r\\n\".getBytes());\n    List<String> response = (List<String>) Protocol.read(new RedisInputStream(is));\n    assertNull(response);\n  }\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/ShardedJedisPipelineTest.java",
    "content": "package redis.clients.jedis.tests;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertNull;\nimport static org.junit.Assert.assertTrue;\n\nimport java.io.UnsupportedEncodingException;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.UUID;\n\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport redis.clients.jedis.HostAndPort;\nimport redis.clients.jedis.Jedis;\nimport redis.clients.jedis.JedisShardInfo;\nimport redis.clients.jedis.Pipeline;\nimport redis.clients.jedis.Response;\nimport redis.clients.jedis.ShardedJedis;\nimport redis.clients.jedis.ShardedJedisPipeline;\nimport redis.clients.jedis.Tuple;\nimport redis.clients.jedis.exceptions.JedisDataException;\n\npublic class ShardedJedisPipelineTest {\n\n  private static HostAndPort redis1 = HostAndPortUtil.getRedisServers().get(0);\n  private static HostAndPort redis2 = HostAndPortUtil.getRedisServers().get(1);\n\n  private ShardedJedis jedis;\n\n  @Before\n  public void setUp() throws Exception {\n    Jedis jedis = new Jedis(redis1.getHost(), redis1.getPort());\n    jedis.auth(\"foobared\");\n    jedis.flushAll();\n    jedis.disconnect();\n    jedis = new Jedis(redis2.getHost(), redis2.getPort());\n    jedis.auth(\"foobared\");\n    jedis.flushAll();\n    jedis.disconnect();\n\n    JedisShardInfo shardInfo1 = new JedisShardInfo(redis1.getHost(), redis1.getPort());\n    JedisShardInfo shardInfo2 = new JedisShardInfo(redis2.getHost(), redis2.getPort());\n    shardInfo1.setPassword(\"foobared\");\n    shardInfo2.setPassword(\"foobared\");\n    List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();\n    shards.add(shardInfo1);\n    shards.add(shardInfo2);\n    this.jedis = new ShardedJedis(shards);\n\n  }\n\n  @Test\n  public void pipeline() throws UnsupportedEncodingException {\n    ShardedJedisPipeline p = jedis.pipelined();\n    p.set(\"foo\", \"bar\");\n    p.get(\"foo\");\n    List<Object> results = p.syncAndReturnAll();\n\n    assertEquals(2, results.size());\n    assertEquals(\"OK\", results.get(0));\n    assertEquals(\"bar\", results.get(1));\n  }\n\n  @Test\n  public void pipelineResponse() {\n    jedis.set(\"string\", \"foo\");\n    jedis.lpush(\"list\", \"foo\");\n    jedis.hset(\"hash\", \"foo\", \"bar\");\n    jedis.zadd(\"zset\", 1, \"foo\");\n    jedis.sadd(\"set\", \"foo\");\n\n    ShardedJedisPipeline p = jedis.pipelined();\n    Response<String> string = p.get(\"string\");\n    Response<Long> del = p.del(\"string\");\n    Response<String> emptyString = p.get(\"string\");\n    Response<String> list = p.lpop(\"list\");\n    Response<String> hash = p.hget(\"hash\", \"foo\");\n    Response<Set<String>> zset = p.zrange(\"zset\", 0, -1);\n    Response<String> set = p.spop(\"set\");\n    Response<Boolean> blist = p.exists(\"list\");\n    Response<Double> zincrby = p.zincrby(\"zset\", 1, \"foo\");\n    Response<Long> zcard = p.zcard(\"zset\");\n    p.lpush(\"list\", \"bar\");\n    Response<List<String>> lrange = p.lrange(\"list\", 0, -1);\n    Response<Map<String, String>> hgetAll = p.hgetAll(\"hash\");\n    p.sadd(\"set\", \"foo\");\n    Response<Set<String>> smembers = p.smembers(\"set\");\n    Response<Set<Tuple>> zrangeWithScores = p.zrangeWithScores(\"zset\", 0, -1);\n    p.sync();\n\n    assertEquals(\"foo\", string.get());\n    assertEquals(Long.valueOf(1), del.get());\n    assertNull(emptyString.get());\n    assertEquals(\"foo\", list.get());\n    assertEquals(\"bar\", hash.get());\n    assertEquals(\"foo\", zset.get().iterator().next());\n    assertEquals(\"foo\", set.get());\n    assertFalse(blist.get());\n    assertEquals(Double.valueOf(2), zincrby.get());\n    assertEquals(Long.valueOf(1), zcard.get());\n    assertEquals(1, lrange.get().size());\n    assertNotNull(hgetAll.get().get(\"foo\"));\n    assertEquals(1, smembers.get().size());\n    assertEquals(1, zrangeWithScores.get().size());\n  }\n\n  @Test(expected = JedisDataException.class)\n  public void pipelineResponseWithinPipeline() {\n    jedis.set(\"string\", \"foo\");\n\n    ShardedJedisPipeline p = jedis.pipelined();\n    Response<String> string = p.get(\"string\");\n    string.get();\n    p.sync();\n  }\n\n  @Test\n  public void canRetrieveUnsetKey() {\n    ShardedJedisPipeline p = jedis.pipelined();\n    Response<String> shouldNotExist = p.get(UUID.randomUUID().toString());\n    p.sync();\n    assertNull(shouldNotExist.get());\n  }\n\n  @Test\n  public void testSyncWithNoCommandQueued() {\n    JedisShardInfo shardInfo1 = new JedisShardInfo(redis1.getHost(), redis1.getPort());\n    JedisShardInfo shardInfo2 = new JedisShardInfo(redis2.getHost(), redis2.getPort());\n    shardInfo1.setPassword(\"foobared\");\n    shardInfo2.setPassword(\"foobared\");\n    List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();\n    shards.add(shardInfo1);\n    shards.add(shardInfo2);\n\n    ShardedJedis jedis2 = new ShardedJedis(shards);\n\n    ShardedJedisPipeline pipeline = jedis2.pipelined();\n    pipeline.sync();\n\n    jedis2.close();\n\n    jedis2 = new ShardedJedis(shards);\n    pipeline = jedis2.pipelined();\n    List<Object> resp = pipeline.syncAndReturnAll();\n    assertTrue(resp.isEmpty());\n\n    jedis2.close();\n  }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/ShardedJedisPoolTest.java",
    "content": "package redis.clients.jedis.tests;\n\nimport java.net.URI;\nimport java.net.URISyntaxException;\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.apache.commons.pool2.impl.GenericObjectPoolConfig;\nimport org.junit.Assert;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport redis.clients.jedis.HostAndPort;\nimport redis.clients.jedis.Jedis;\nimport redis.clients.jedis.JedisShardInfo;\nimport redis.clients.jedis.ShardedJedis;\nimport redis.clients.jedis.ShardedJedisPipeline;\nimport redis.clients.jedis.ShardedJedisPool;\nimport redis.clients.jedis.exceptions.JedisConnectionException;\n\npublic class ShardedJedisPoolTest extends Assert {\n  private static HostAndPort redis1 = HostAndPortUtil.getRedisServers().get(0);\n  private static HostAndPort redis2 = HostAndPortUtil.getRedisServers().get(1);\n\n  private List<JedisShardInfo> shards;\n\n  @Before\n  public void startUp() {\n    shards = new ArrayList<JedisShardInfo>();\n    shards.add(new JedisShardInfo(redis1.getHost(), redis1.getPort()));\n    shards.add(new JedisShardInfo(redis2.getHost(), redis2.getPort()));\n    shards.get(0).setPassword(\"foobared\");\n    shards.get(1).setPassword(\"foobared\");\n    Jedis j = new Jedis(shards.get(0));\n    j.connect();\n    j.flushAll();\n    j.disconnect();\n    j = new Jedis(shards.get(1));\n    j.connect();\n    j.flushAll();\n    j.disconnect();\n\n  }\n\n  @Test\n  public void checkConnections() {\n    ShardedJedisPool pool = new ShardedJedisPool(new GenericObjectPoolConfig(), shards);\n    ShardedJedis jedis = pool.getResource();\n    jedis.set(\"foo\", \"bar\");\n    assertEquals(\"bar\", jedis.get(\"foo\"));\n    jedis.close();\n    pool.destroy();\n  }\n\n  @Test\n  public void checkCloseableConnections() throws Exception {\n    ShardedJedisPool pool = new ShardedJedisPool(new GenericObjectPoolConfig(), shards);\n    ShardedJedis jedis = pool.getResource();\n    jedis.set(\"foo\", \"bar\");\n    assertEquals(\"bar\", jedis.get(\"foo\"));\n    jedis.close();\n    pool.close();\n    assertTrue(pool.isClosed());\n  }\n\n  @Test\n  public void checkConnectionWithDefaultPort() {\n    ShardedJedisPool pool = new ShardedJedisPool(new GenericObjectPoolConfig(), shards);\n    ShardedJedis jedis = pool.getResource();\n    jedis.set(\"foo\", \"bar\");\n    assertEquals(\"bar\", jedis.get(\"foo\"));\n    jedis.close();\n    pool.destroy();\n  }\n\n  @Test\n  public void checkJedisIsReusedWhenReturned() {\n    ShardedJedisPool pool = new ShardedJedisPool(new GenericObjectPoolConfig(), shards);\n    ShardedJedis jedis = pool.getResource();\n    jedis.set(\"foo\", \"0\");\n    jedis.close();\n\n    jedis = pool.getResource();\n    jedis.incr(\"foo\");\n    jedis.close();\n    pool.destroy();\n  }\n\n  @Test\n  public void checkPoolRepairedWhenJedisIsBroken() {\n    ShardedJedisPool pool = new ShardedJedisPool(new GenericObjectPoolConfig(), shards);\n    ShardedJedis jedis = pool.getResource();\n    jedis.disconnect();\n    jedis.close();\n\n    jedis = pool.getResource();\n    jedis.incr(\"foo\");\n    jedis.close();\n    pool.destroy();\n  }\n\n  @Test(expected = JedisConnectionException.class)\n  public void checkPoolOverflow() {\n    GenericObjectPoolConfig config = new GenericObjectPoolConfig();\n    config.setMaxTotal(1);\n    config.setBlockWhenExhausted(false);\n\n    ShardedJedisPool pool = new ShardedJedisPool(config, shards);\n\n    ShardedJedis jedis = pool.getResource();\n    jedis.set(\"foo\", \"0\");\n\n    ShardedJedis newJedis = pool.getResource();\n    newJedis.incr(\"foo\");\n  }\n\n  @Test\n  public void shouldNotShareInstances() {\n    GenericObjectPoolConfig config = new GenericObjectPoolConfig();\n    config.setMaxTotal(2);\n\n    ShardedJedisPool pool = new ShardedJedisPool(config, shards);\n\n    ShardedJedis j1 = pool.getResource();\n    ShardedJedis j2 = pool.getResource();\n\n    assertNotSame(j1.getShard(\"foo\"), j2.getShard(\"foo\"));\n  }\n\n  @Test\n  public void checkFailedJedisServer() {\n    ShardedJedisPool pool = new ShardedJedisPool(new GenericObjectPoolConfig(), shards);\n    ShardedJedis jedis = pool.getResource();\n    jedis.incr(\"foo\");\n    jedis.close();\n    pool.destroy();\n  }\n\n  @Test\n  public void shouldReturnActiveShardsWhenOneGoesOffline() {\n    GenericObjectPoolConfig redisConfig = new GenericObjectPoolConfig();\n    redisConfig.setTestOnBorrow(false);\n    ShardedJedisPool pool = new ShardedJedisPool(redisConfig, shards);\n    ShardedJedis jedis = pool.getResource();\n    // fill the shards\n    for (int i = 0; i < 1000; i++) {\n      jedis.set(\"a-test-\" + i, \"0\");\n    }\n    jedis.close();\n    // check quantity for each shard\n    Jedis j = new Jedis(shards.get(0));\n    j.connect();\n    Long c1 = j.dbSize();\n    j.disconnect();\n    j = new Jedis(shards.get(1));\n    j.connect();\n    Long c2 = j.dbSize();\n    j.disconnect();\n    // shutdown shard 2 and check thay the pool returns an instance with c1\n    // items on one shard\n    // alter shard 1 and recreate pool\n    pool.destroy();\n    shards.set(1, new JedisShardInfo(\"localhost\", 1234));\n    pool = new ShardedJedisPool(redisConfig, shards);\n    jedis = pool.getResource();\n    Long actual = Long.valueOf(0);\n    Long fails = Long.valueOf(0);\n    for (int i = 0; i < 1000; i++) {\n      try {\n        jedis.get(\"a-test-\" + i);\n        actual++;\n      } catch (RuntimeException e) {\n        fails++;\n      }\n    }\n    jedis.close();\n    pool.destroy();\n    assertEquals(actual, c1);\n    assertEquals(fails, c2);\n  }\n\n  @Test\n  public void startWithUrlString() {\n    Jedis j = new Jedis(\"localhost\", 6380);\n    j.auth(\"foobared\");\n    j.set(\"foo\", \"bar\");\n\n    j = new Jedis(\"localhost\", 6379);\n    j.auth(\"foobared\");\n    j.set(\"foo\", \"bar\");\n\n    List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();\n    shards.add(new JedisShardInfo(\"redis://:foobared@localhost:6380\"));\n    shards.add(new JedisShardInfo(\"redis://:foobared@localhost:6379\"));\n\n    GenericObjectPoolConfig redisConfig = new GenericObjectPoolConfig();\n    ShardedJedisPool pool = new ShardedJedisPool(redisConfig, shards);\n\n    Jedis[] jedises = pool.getResource().getAllShards().toArray(new Jedis[2]);\n\n    Jedis jedis = jedises[0];\n    assertEquals(\"PONG\", jedis.ping());\n    assertEquals(\"bar\", jedis.get(\"foo\"));\n\n    jedis = jedises[1];\n    assertEquals(\"PONG\", jedis.ping());\n    assertEquals(\"bar\", jedis.get(\"foo\"));\n  }\n\n  @Test\n  public void startWithUrl() throws URISyntaxException {\n    Jedis j = new Jedis(\"localhost\", 6380);\n    j.auth(\"foobared\");\n    j.set(\"foo\", \"bar\");\n\n    j = new Jedis(\"localhost\", 6379);\n    j.auth(\"foobared\");\n    j.set(\"foo\", \"bar\");\n\n    List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();\n    shards.add(new JedisShardInfo(new URI(\"redis://:foobared@localhost:6380\")));\n    shards.add(new JedisShardInfo(new URI(\"redis://:foobared@localhost:6379\")));\n\n    GenericObjectPoolConfig redisConfig = new GenericObjectPoolConfig();\n    ShardedJedisPool pool = new ShardedJedisPool(redisConfig, shards);\n\n    Jedis[] jedises = pool.getResource().getAllShards().toArray(new Jedis[2]);\n\n    Jedis jedis = jedises[0];\n    assertEquals(\"PONG\", jedis.ping());\n    assertEquals(\"bar\", jedis.get(\"foo\"));\n\n    jedis = jedises[1];\n    assertEquals(\"PONG\", jedis.ping());\n    assertEquals(\"bar\", jedis.get(\"foo\"));\n  }\n\n  @Test\n  public void returnResourceShouldResetState() throws URISyntaxException {\n    GenericObjectPoolConfig config = new GenericObjectPoolConfig();\n    config.setMaxTotal(1);\n    config.setBlockWhenExhausted(false);\n\n    List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();\n    shards.add(new JedisShardInfo(new URI(\"redis://:foobared@localhost:6380\")));\n    shards.add(new JedisShardInfo(new URI(\"redis://:foobared@localhost:6379\")));\n\n    ShardedJedisPool pool = new ShardedJedisPool(config, shards);\n\n    ShardedJedis jedis = pool.getResource();\n    jedis.set(\"pipelined\", String.valueOf(0));\n    jedis.set(\"pipelined2\", String.valueOf(0));\n\n    ShardedJedisPipeline pipeline = jedis.pipelined();\n\n    pipeline.incr(\"pipelined\");\n    pipeline.incr(\"pipelined2\");\n\n    jedis.resetState();\n\n    pipeline = jedis.pipelined();\n    pipeline.incr(\"pipelined\");\n    pipeline.incr(\"pipelined2\");\n    List<Object> results = pipeline.syncAndReturnAll();\n\n    assertEquals(2, results.size());\n    jedis.close();\n    pool.destroy();\n  }\n\n  @Test\n  public void checkResourceIsCloseable() throws URISyntaxException {\n    GenericObjectPoolConfig config = new GenericObjectPoolConfig();\n    config.setMaxTotal(1);\n    config.setBlockWhenExhausted(false);\n\n    List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();\n    shards.add(new JedisShardInfo(new URI(\"redis://:foobared@localhost:6380\")));\n    shards.add(new JedisShardInfo(new URI(\"redis://:foobared@localhost:6379\")));\n\n    ShardedJedisPool pool = new ShardedJedisPool(config, shards);\n\n    ShardedJedis jedis = pool.getResource();\n    try {\n      jedis.set(\"hello\", \"jedis\");\n    } finally {\n      jedis.close();\n    }\n\n    ShardedJedis jedis2 = pool.getResource();\n    try {\n      assertEquals(jedis, jedis2);\n    } finally {\n      jedis2.close();\n    }\n  }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/ShardedJedisTest.java",
    "content": "package redis.clients.jedis.tests;\n\nimport java.util.ArrayList;\nimport java.util.Iterator;\nimport java.util.List;\n\nimport org.junit.Assert;\nimport org.junit.Test;\n\nimport redis.clients.jedis.HostAndPort;\nimport redis.clients.jedis.Jedis;\nimport redis.clients.jedis.JedisShardInfo;\nimport redis.clients.jedis.Protocol;\nimport redis.clients.jedis.ShardedJedis;\nimport redis.clients.jedis.tests.utils.ClientKillerUtil;\nimport redis.clients.util.Hashing;\nimport redis.clients.util.Sharded;\n\npublic class ShardedJedisTest extends Assert {\n  private static HostAndPort redis1 = HostAndPortUtil.getRedisServers().get(0);\n  private static HostAndPort redis2 = HostAndPortUtil.getRedisServers().get(1);\n\n  /**\n   * Test for \"Issue - BinaryShardedJedis.disconnect() may occur memory leak\". You can find more\n   * detailed information at https://github.com/xetorthio/jedis/issues/808\n   * @throws InterruptedException\n   */\n  @Test\n  public void testAvoidLeaksUponDisconnect() throws InterruptedException {\n    List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>(2);\n    // 6379\n    JedisShardInfo shard1 = new JedisShardInfo(redis1.getHost(), redis1.getPort());\n    shard1.setPassword(\"foobared\");\n    shards.add(shard1);\n    // 6380\n    JedisShardInfo shard2 = new JedisShardInfo(redis2.getHost(), redis2.getPort());\n    shard2.setPassword(\"foobared\");\n    shards.add(shard2);\n\n    @SuppressWarnings(\"resource\")\n    ShardedJedis shardedJedis = new ShardedJedis(shards);\n    // establish the connection for two redis servers\n    shardedJedis.set(\"a\", \"bar\");\n    JedisShardInfo ak = shardedJedis.getShardInfo(\"a\");\n    assertEquals(shard2, ak);\n    shardedJedis.set(\"b\", \"bar1\");\n    JedisShardInfo bk = shardedJedis.getShardInfo(\"b\");\n    assertEquals(shard1, bk);\n\n    // We set a name to the instance so it's easy to find it\n    Iterator<Jedis> it = shardedJedis.getAllShards().iterator();\n    Jedis deadClient = it.next();\n    deadClient.clientSetname(\"DEAD\");\n\n    ClientKillerUtil.killClient(deadClient, \"DEAD\");\n\n    assertEquals(true, deadClient.isConnected());\n    assertEquals(false, deadClient.getClient().getSocket().isClosed());\n    assertEquals(false, deadClient.getClient().isBroken()); // normal - not found\n\n    shardedJedis.disconnect();\n\n    assertEquals(false, deadClient.isConnected());\n    assertEquals(true, deadClient.getClient().getSocket().isClosed());\n    assertEquals(true, deadClient.getClient().isBroken());\n\n    Jedis jedis2 = it.next();\n    assertEquals(false, jedis2.isConnected());\n    assertEquals(true, jedis2.getClient().getSocket().isClosed());\n    assertEquals(false, jedis2.getClient().isBroken());\n\n  }\n\n  private List<String> getKeysDifferentShard(ShardedJedis jedis) {\n    List<String> ret = new ArrayList<String>();\n    JedisShardInfo first = jedis.getShardInfo(\"a0\");\n    ret.add(\"a0\");\n    for (int i = 1; i < 100; ++i) {\n      JedisShardInfo actual = jedis.getShardInfo(\"a\" + i);\n      if (actual != first) {\n        ret.add(\"a\" + i);\n        break;\n\n      }\n\n    }\n    return ret;\n  }\n\n  @Test\n  public void checkSharding() {\n    List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();\n    shards.add(new JedisShardInfo(redis1.getHost(), redis1.getPort()));\n    shards.add(new JedisShardInfo(redis2.getHost(), redis2.getPort()));\n    ShardedJedis jedis = new ShardedJedis(shards);\n    List<String> keys = getKeysDifferentShard(jedis);\n    JedisShardInfo s1 = jedis.getShardInfo(keys.get(0));\n    JedisShardInfo s2 = jedis.getShardInfo(keys.get(1));\n    assertNotSame(s1, s2);\n  }\n\n  @Test\n  public void trySharding() {\n    List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();\n    JedisShardInfo si = new JedisShardInfo(redis1.getHost(), redis1.getPort());\n    si.setPassword(\"foobared\");\n    shards.add(si);\n    si = new JedisShardInfo(redis2.getHost(), redis2.getPort());\n    si.setPassword(\"foobared\");\n    shards.add(si);\n    ShardedJedis jedis = new ShardedJedis(shards);\n    jedis.set(\"a\", \"bar\");\n    JedisShardInfo s1 = jedis.getShardInfo(\"a\");\n    jedis.set(\"b\", \"bar1\");\n    JedisShardInfo s2 = jedis.getShardInfo(\"b\");\n    jedis.disconnect();\n\n    Jedis j = new Jedis(s1.getHost(), s1.getPort());\n    j.auth(\"foobared\");\n    assertEquals(\"bar\", j.get(\"a\"));\n    j.disconnect();\n\n    j = new Jedis(s2.getHost(), s2.getPort());\n    j.auth(\"foobared\");\n    assertEquals(\"bar1\", j.get(\"b\"));\n    j.disconnect();\n  }\n\n  @Test\n  public void tryShardingWithMurmure() {\n    List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();\n    JedisShardInfo si = new JedisShardInfo(redis1.getHost(), redis1.getPort());\n    si.setPassword(\"foobared\");\n    shards.add(si);\n    si = new JedisShardInfo(redis2.getHost(), redis2.getPort());\n    si.setPassword(\"foobared\");\n    shards.add(si);\n    ShardedJedis jedis = new ShardedJedis(shards, Hashing.MURMUR_HASH);\n    jedis.set(\"a\", \"bar\");\n    JedisShardInfo s1 = jedis.getShardInfo(\"a\");\n    jedis.set(\"b\", \"bar1\");\n    JedisShardInfo s2 = jedis.getShardInfo(\"b\");\n    jedis.disconnect();\n\n    Jedis j = new Jedis(s1.getHost(), s1.getPort());\n    j.auth(\"foobared\");\n    assertEquals(\"bar\", j.get(\"a\"));\n    j.disconnect();\n\n    j = new Jedis(s2.getHost(), s2.getPort());\n    j.auth(\"foobared\");\n    assertEquals(\"bar1\", j.get(\"b\"));\n    j.disconnect();\n  }\n\n  @Test\n  public void checkKeyTags() {\n    List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();\n    shards.add(new JedisShardInfo(redis1.getHost(), redis1.getPort()));\n    shards.add(new JedisShardInfo(redis2.getHost(), redis2.getPort()));\n    ShardedJedis jedis = new ShardedJedis(shards, ShardedJedis.DEFAULT_KEY_TAG_PATTERN);\n\n    assertEquals(jedis.getKeyTag(\"foo\"), \"foo\");\n    assertEquals(jedis.getKeyTag(\"foo{bar}\"), \"bar\");\n    assertEquals(jedis.getKeyTag(\"foo{bar}}\"), \"bar\"); // default pattern is\n    // non greedy\n    assertEquals(jedis.getKeyTag(\"{bar}foo\"), \"bar\"); // Key tag may appear\n    // anywhere\n    assertEquals(jedis.getKeyTag(\"f{bar}oo\"), \"bar\"); // Key tag may appear\n    // anywhere\n\n    JedisShardInfo s1 = jedis.getShardInfo(\"abc{bar}\");\n    JedisShardInfo s2 = jedis.getShardInfo(\"foo{bar}\");\n    assertSame(s1, s2);\n\n    List<String> keys = getKeysDifferentShard(jedis);\n    JedisShardInfo s3 = jedis.getShardInfo(keys.get(0));\n    JedisShardInfo s4 = jedis.getShardInfo(keys.get(1));\n    assertNotSame(s3, s4);\n\n    ShardedJedis jedis2 = new ShardedJedis(shards);\n\n    assertEquals(jedis2.getKeyTag(\"foo\"), \"foo\");\n    assertNotSame(jedis2.getKeyTag(\"foo{bar}\"), \"bar\");\n\n    JedisShardInfo s5 = jedis2.getShardInfo(keys.get(0) + \"{bar}\");\n    JedisShardInfo s6 = jedis2.getShardInfo(keys.get(1) + \"{bar}\");\n    assertNotSame(s5, s6);\n  }\n\n  @Test\n  public void testMD5Sharding() {\n    List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>(3);\n    shards.add(new JedisShardInfo(\"localhost\", Protocol.DEFAULT_PORT));\n    shards.add(new JedisShardInfo(\"localhost\", Protocol.DEFAULT_PORT + 1));\n    shards.add(new JedisShardInfo(\"localhost\", Protocol.DEFAULT_PORT + 2));\n    Sharded<Jedis, JedisShardInfo> sharded = new Sharded<Jedis, JedisShardInfo>(shards, Hashing.MD5);\n    int shard_6379 = 0;\n    int shard_6380 = 0;\n    int shard_6381 = 0;\n    for (int i = 0; i < 1000; i++) {\n      JedisShardInfo jedisShardInfo = sharded.getShardInfo(Integer.toString(i));\n      switch (jedisShardInfo.getPort()) {\n      case 6379:\n        shard_6379++;\n        break;\n      case 6380:\n        shard_6380++;\n        break;\n      case 6381:\n        shard_6381++;\n        break;\n      default:\n        fail(\"Attempting to use a non-defined shard!!:\" + jedisShardInfo);\n        break;\n      }\n    }\n    assertTrue(shard_6379 > 300 && shard_6379 < 400);\n    assertTrue(shard_6380 > 300 && shard_6380 < 400);\n    assertTrue(shard_6381 > 300 && shard_6381 < 400);\n  }\n\n  @Test\n  public void testMurmurSharding() {\n    List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>(3);\n    shards.add(new JedisShardInfo(\"localhost\", Protocol.DEFAULT_PORT));\n    shards.add(new JedisShardInfo(\"localhost\", Protocol.DEFAULT_PORT + 1));\n    shards.add(new JedisShardInfo(\"localhost\", Protocol.DEFAULT_PORT + 2));\n    Sharded<Jedis, JedisShardInfo> sharded = new Sharded<Jedis, JedisShardInfo>(shards,\n        Hashing.MURMUR_HASH);\n    int shard_6379 = 0;\n    int shard_6380 = 0;\n    int shard_6381 = 0;\n    for (int i = 0; i < 1000; i++) {\n      JedisShardInfo jedisShardInfo = sharded.getShardInfo(Integer.toString(i));\n      switch (jedisShardInfo.getPort()) {\n      case 6379:\n        shard_6379++;\n        break;\n      case 6380:\n        shard_6380++;\n        break;\n      case 6381:\n        shard_6381++;\n        break;\n      default:\n        fail(\"Attempting to use a non-defined shard!!:\" + jedisShardInfo);\n        break;\n      }\n    }\n    assertTrue(shard_6379 > 300 && shard_6379 < 400);\n    assertTrue(shard_6380 > 300 && shard_6380 < 400);\n    assertTrue(shard_6381 > 300 && shard_6381 < 400);\n  }\n\n  @Test\n  public void testMasterSlaveShardingConsistency() {\n    List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>(3);\n    shards.add(new JedisShardInfo(\"localhost\", Protocol.DEFAULT_PORT));\n    shards.add(new JedisShardInfo(\"localhost\", Protocol.DEFAULT_PORT + 1));\n    shards.add(new JedisShardInfo(\"localhost\", Protocol.DEFAULT_PORT + 2));\n    Sharded<Jedis, JedisShardInfo> sharded = new Sharded<Jedis, JedisShardInfo>(shards,\n        Hashing.MURMUR_HASH);\n\n    List<JedisShardInfo> otherShards = new ArrayList<JedisShardInfo>(3);\n    otherShards.add(new JedisShardInfo(\"otherhost\", Protocol.DEFAULT_PORT));\n    otherShards.add(new JedisShardInfo(\"otherhost\", Protocol.DEFAULT_PORT + 1));\n    otherShards.add(new JedisShardInfo(\"otherhost\", Protocol.DEFAULT_PORT + 2));\n    Sharded<Jedis, JedisShardInfo> sharded2 = new Sharded<Jedis, JedisShardInfo>(otherShards,\n        Hashing.MURMUR_HASH);\n\n    for (int i = 0; i < 1000; i++) {\n      JedisShardInfo jedisShardInfo = sharded.getShardInfo(Integer.toString(i));\n      JedisShardInfo jedisShardInfo2 = sharded2.getShardInfo(Integer.toString(i));\n      assertEquals(shards.indexOf(jedisShardInfo), otherShards.indexOf(jedisShardInfo2));\n    }\n\n  }\n\n  @Test\n  public void testMasterSlaveShardingConsistencyWithShardNaming() {\n    List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>(3);\n    shards.add(new JedisShardInfo(\"localhost\", Protocol.DEFAULT_PORT, \"HOST1:1234\"));\n    shards.add(new JedisShardInfo(\"localhost\", Protocol.DEFAULT_PORT + 1, \"HOST2:1234\"));\n    shards.add(new JedisShardInfo(\"localhost\", Protocol.DEFAULT_PORT + 2, \"HOST3:1234\"));\n    Sharded<Jedis, JedisShardInfo> sharded = new Sharded<Jedis, JedisShardInfo>(shards,\n        Hashing.MURMUR_HASH);\n\n    List<JedisShardInfo> otherShards = new ArrayList<JedisShardInfo>(3);\n    otherShards.add(new JedisShardInfo(\"otherhost\", Protocol.DEFAULT_PORT, \"HOST2:1234\"));\n    otherShards.add(new JedisShardInfo(\"otherhost\", Protocol.DEFAULT_PORT + 1, \"HOST3:1234\"));\n    otherShards.add(new JedisShardInfo(\"otherhost\", Protocol.DEFAULT_PORT + 2, \"HOST1:1234\"));\n    Sharded<Jedis, JedisShardInfo> sharded2 = new Sharded<Jedis, JedisShardInfo>(otherShards,\n        Hashing.MURMUR_HASH);\n\n    for (int i = 0; i < 1000; i++) {\n      JedisShardInfo jedisShardInfo = sharded.getShardInfo(Integer.toString(i));\n      JedisShardInfo jedisShardInfo2 = sharded2.getShardInfo(Integer.toString(i));\n      assertEquals(jedisShardInfo.getName(), jedisShardInfo2.getName());\n    }\n  }\n\n  @Test\n  public void checkCloseable() {\n    List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();\n    shards.add(new JedisShardInfo(redis1.getHost(), redis1.getPort()));\n    shards.add(new JedisShardInfo(redis2.getHost(), redis2.getPort()));\n    shards.get(0).setPassword(\"foobared\");\n    shards.get(1).setPassword(\"foobared\");\n\n    ShardedJedis jedisShard = new ShardedJedis(shards);\n    try {\n      jedisShard.set(\"shard_closeable\", \"true\");\n    } finally {\n      jedisShard.close();\n    }\n\n    for (Jedis jedis : jedisShard.getAllShards()) {\n      assertTrue(!jedis.isConnected());\n    }\n  }\n\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/benchmark/CRC16Benchmark.java",
    "content": "package redis.clients.jedis.tests.benchmark;\n\nimport java.util.Calendar;\n\nimport redis.clients.util.JedisClusterCRC16;\n\npublic class CRC16Benchmark {\n  private static final int TOTAL_OPERATIONS = 100000000;\n\n  private static String[] TEST_SET = { \"\", \"123456789\", \"sfger132515\",\n      \"hae9Napahngaikeethievubaibogiech\", \"AAAAAAAAAAAAAAAAAAAAAA\", \"Hello, World!\" };\n\n  public static void main(String[] args) {\n    long begin = Calendar.getInstance().getTimeInMillis();\n\n    for (int n = 0; n <= TOTAL_OPERATIONS; n++) {\n      JedisClusterCRC16.getSlot(TEST_SET[n % TEST_SET.length]);\n    }\n\n    long elapsed = Calendar.getInstance().getTimeInMillis() - begin;\n\n    System.out.println(((1000 * TOTAL_OPERATIONS) / elapsed) + \" ops\");\n  }\n\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/benchmark/GetSetBenchmark.java",
    "content": "package redis.clients.jedis.tests.benchmark;\n\nimport java.io.IOException;\nimport java.net.UnknownHostException;\nimport java.util.Calendar;\n\nimport redis.clients.jedis.HostAndPort;\nimport redis.clients.jedis.Jedis;\nimport redis.clients.jedis.tests.HostAndPortUtil;\n\npublic class GetSetBenchmark {\n  private static HostAndPort hnp = HostAndPortUtil.getRedisServers().get(0);\n  private static final int TOTAL_OPERATIONS = 100000;\n\n  public static void main(String[] args) throws UnknownHostException, IOException {\n    Jedis jedis = new Jedis(hnp.getHost(), hnp.getPort());\n    jedis.connect();\n    jedis.auth(\"foobared\");\n    jedis.flushAll();\n\n    long begin = Calendar.getInstance().getTimeInMillis();\n\n    for (int n = 0; n <= TOTAL_OPERATIONS; n++) {\n      String key = \"foo\" + n;\n      jedis.set(key, \"bar\" + n);\n      jedis.get(key);\n    }\n\n    long elapsed = Calendar.getInstance().getTimeInMillis() - begin;\n\n    jedis.disconnect();\n\n    System.out.println(((1000 * 2 * TOTAL_OPERATIONS) / elapsed) + \" ops\");\n  }\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/benchmark/HashingBenchmark.java",
    "content": "package redis.clients.jedis.tests.benchmark;\n\nimport java.io.IOException;\nimport java.net.UnknownHostException;\nimport java.util.ArrayList;\nimport java.util.Calendar;\nimport java.util.Collection;\nimport java.util.List;\n\nimport redis.clients.jedis.HostAndPort;\nimport redis.clients.jedis.Jedis;\nimport redis.clients.jedis.JedisShardInfo;\nimport redis.clients.jedis.ShardedJedis;\nimport redis.clients.jedis.tests.HostAndPortUtil;\n\npublic class HashingBenchmark {\n  private static HostAndPort hnp1 = HostAndPortUtil.getRedisServers().get(0);\n  private static HostAndPort hnp2 = HostAndPortUtil.getRedisServers().get(1);\n  private static final int TOTAL_OPERATIONS = 100000;\n\n  public static void main(String[] args) throws UnknownHostException, IOException {\n    List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();\n    JedisShardInfo shard = new JedisShardInfo(hnp1.getHost(), hnp1.getPort());\n    shard.setPassword(\"foobared\");\n    shards.add(shard);\n    shard = new JedisShardInfo(hnp2.getHost(), hnp2.getPort());\n    shard.setPassword(\"foobared\");\n    shards.add(shard);\n    ShardedJedis jedis = new ShardedJedis(shards);\n    Collection<Jedis> allShards = jedis.getAllShards();\n    for (Jedis j : allShards) {\n      j.flushAll();\n    }\n\n    long begin = Calendar.getInstance().getTimeInMillis();\n\n    for (int n = 0; n <= TOTAL_OPERATIONS; n++) {\n      String key = \"foo\" + n;\n      jedis.set(key, \"bar\" + n);\n      jedis.get(key);\n    }\n\n    long elapsed = Calendar.getInstance().getTimeInMillis() - begin;\n\n    jedis.disconnect();\n\n    System.out.println(((1000 * 2 * TOTAL_OPERATIONS) / elapsed) + \" ops\");\n  }\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/benchmark/PipelinedGetSetBenchmark.java",
    "content": "package redis.clients.jedis.tests.benchmark;\n\nimport java.io.IOException;\nimport java.net.UnknownHostException;\nimport java.util.Calendar;\n\nimport redis.clients.jedis.HostAndPort;\nimport redis.clients.jedis.Jedis;\nimport redis.clients.jedis.Pipeline;\nimport redis.clients.jedis.tests.HostAndPortUtil;\n\npublic class PipelinedGetSetBenchmark {\n  private static HostAndPort hnp = HostAndPortUtil.getRedisServers().get(0);\n  private static final int TOTAL_OPERATIONS = 200000;\n\n  public static void main(String[] args) throws UnknownHostException, IOException {\n    Jedis jedis = new Jedis(hnp.getHost(), hnp.getPort());\n    jedis.connect();\n    jedis.auth(\"foobared\");\n    jedis.flushAll();\n\n    long begin = Calendar.getInstance().getTimeInMillis();\n\n    Pipeline p = jedis.pipelined();\n    for (int n = 0; n <= TOTAL_OPERATIONS; n++) {\n      String key = \"foo\" + n;\n      p.set(key, \"bar\" + n);\n      p.get(key);\n    }\n    p.sync();\n\n    long elapsed = Calendar.getInstance().getTimeInMillis() - begin;\n\n    jedis.disconnect();\n\n    System.out.println(((1000 * 2 * TOTAL_OPERATIONS) / elapsed) + \" ops\");\n  }\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/benchmark/PoolBenchmark.java",
    "content": "package redis.clients.jedis.tests.benchmark;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport org.apache.commons.pool2.impl.GenericObjectPoolConfig;\n\nimport redis.clients.jedis.HostAndPort;\nimport redis.clients.jedis.Jedis;\nimport redis.clients.jedis.JedisPool;\nimport redis.clients.jedis.tests.HostAndPortUtil;\n\npublic class PoolBenchmark {\n  private static HostAndPort hnp = HostAndPortUtil.getRedisServers().get(0);\n  private static final int TOTAL_OPERATIONS = 100000;\n\n  public static void main(String[] args) throws Exception {\n    Jedis j = new Jedis(hnp.getHost(), hnp.getPort());\n    j.connect();\n    j.auth(\"foobared\");\n    j.flushAll();\n    j.quit();\n    j.disconnect();\n    long t = System.currentTimeMillis();\n    // withoutPool();\n    withPool();\n    long elapsed = System.currentTimeMillis() - t;\n    System.out.println(((1000 * 2 * TOTAL_OPERATIONS) / elapsed) + \" ops\");\n  }\n\n  private static void withPool() throws Exception {\n    final JedisPool pool = new JedisPool(new GenericObjectPoolConfig(), hnp.getHost(),\n        hnp.getPort(), 2000, \"foobared\");\n    List<Thread> tds = new ArrayList<Thread>();\n\n    final AtomicInteger ind = new AtomicInteger();\n    for (int i = 0; i < 50; i++) {\n      Thread hj = new Thread(new Runnable() {\n        public void run() {\n          for (int i = 0; (i = ind.getAndIncrement()) < TOTAL_OPERATIONS;) {\n            try {\n              Jedis j = pool.getResource();\n              final String key = \"foo\" + i;\n              j.set(key, key);\n              j.get(key);\n              j.close();\n            } catch (Exception e) {\n              e.printStackTrace();\n            }\n          }\n        }\n      });\n      tds.add(hj);\n      hj.start();\n    }\n\n    for (Thread t : tds)\n      t.join();\n\n    pool.destroy();\n\n  }\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/benchmark/ProtocolBenchmark.java",
    "content": "package redis.clients.jedis.tests.benchmark;\n\nimport redis.clients.jedis.Protocol;\nimport redis.clients.util.RedisInputStream;\nimport redis.clients.util.RedisOutputStream;\n\nimport java.io.ByteArrayInputStream;\nimport java.io.ByteArrayOutputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * Copyright (c) 2014\n */\npublic class ProtocolBenchmark {\n  private static final int TOTAL_OPERATIONS = 500000;\n\n  public static void main(String[] args) throws Exception, IOException {\n    long total = 0;\n    for (int at = 0; at != 10; ++at) {\n      long elapsed = measureInputMulti();\n      long ops = ((1000 * 2 * TOTAL_OPERATIONS) / TimeUnit.NANOSECONDS.toMillis(elapsed));\n      if (at >= 5) {\n        total += ops;\n      }\n    }\n    System.out.println((total / 5) + \" avg\");\n\n    total = 0;\n    for (int at = 0; at != 10; ++at) {\n      long elapsed = measureInputStatus();\n      long ops = ((1000 * 2 * TOTAL_OPERATIONS) / TimeUnit.NANOSECONDS.toMillis(elapsed));\n      if (at >= 5) {\n        total += ops;\n      }\n    }\n\n    System.out.println((total / 5) + \" avg\");\n\n    total = 0;\n    for (int at = 0; at != 10; ++at) {\n      long elapsed = measureCommand();\n      long ops = ((1000 * 2 * TOTAL_OPERATIONS) / TimeUnit.NANOSECONDS.toMillis(elapsed));\n      if (at >= 5) {\n        total += ops;\n      }\n    }\n\n    System.out.println((total / 5) + \" avg\");\n  }\n\n  private static long measureInputMulti() throws Exception {\n    long duration = 0;\n\n    InputStream is = new ByteArrayInputStream(\n        \"*4\\r\\n$3\\r\\nfoo\\r\\n$13\\r\\nbarbarbarfooz\\r\\n$5\\r\\nHello\\r\\n$5\\r\\nWorld\\r\\n\".getBytes());\n\n    RedisInputStream in = new RedisInputStream(is);\n    for (int n = 0; n <= TOTAL_OPERATIONS; n++) {\n      long start = System.nanoTime();\n      Protocol.read(in);\n      duration += (System.nanoTime() - start);\n      in.reset();\n    }\n\n    return duration;\n  }\n\n  private static long measureInputStatus() throws Exception {\n    long duration = 0;\n\n    InputStream is = new ByteArrayInputStream(\"+OK\\r\\n\".getBytes());\n\n    RedisInputStream in = new RedisInputStream(is);\n    for (int n = 0; n <= TOTAL_OPERATIONS; n++) {\n      long start = System.nanoTime();\n      Protocol.read(in);\n      duration += (System.nanoTime() - start);\n      in.reset();\n    }\n\n    return duration;\n  }\n\n  private static long measureCommand() throws Exception {\n    long duration = 0;\n\n    byte[] KEY = \"123456789\".getBytes();\n    byte[] VAL = \"FooBar\".getBytes();\n\n    for (int n = 0; n <= TOTAL_OPERATIONS; n++) {\n      RedisOutputStream out = new RedisOutputStream(new ByteArrayOutputStream(8192));\n      long start = System.nanoTime();\n      Protocol.sendCommand(out, Protocol.Command.SET, KEY, VAL);\n      duration += (System.nanoTime() - start);\n    }\n\n    return duration;\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/benchmark/SafeEncoderBenchmark.java",
    "content": "package redis.clients.jedis.tests.benchmark;\n\nimport java.io.IOException;\nimport java.net.UnknownHostException;\nimport java.util.Calendar;\n\nimport redis.clients.util.SafeEncoder;\n\npublic class SafeEncoderBenchmark {\n  private static final int TOTAL_OPERATIONS = 10000000;\n\n  public static void main(String[] args) throws UnknownHostException, IOException {\n    long begin = Calendar.getInstance().getTimeInMillis();\n\n    for (int n = 0; n <= TOTAL_OPERATIONS; n++) {\n      SafeEncoder.encode(\"foo bar!\");\n    }\n\n    long elapsed = Calendar.getInstance().getTimeInMillis() - begin;\n\n    System.out.println(((1000 * TOTAL_OPERATIONS) / elapsed) + \" ops to build byte[]\");\n\n    begin = Calendar.getInstance().getTimeInMillis();\n\n    byte[] bytes = \"foo bar!\".getBytes();\n    for (int n = 0; n <= TOTAL_OPERATIONS; n++) {\n      SafeEncoder.encode(bytes);\n    }\n\n    elapsed = Calendar.getInstance().getTimeInMillis() - begin;\n\n    System.out.println(((1000 * TOTAL_OPERATIONS) / elapsed) + \" ops to build Strings\");\n\n  }\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/benchmark/ShardedBenchmark.java",
    "content": "package redis.clients.jedis.tests.benchmark;\n\nimport java.io.IOException;\nimport java.net.UnknownHostException;\nimport java.util.Calendar;\n\nimport redis.clients.util.Hashing;\n\npublic class ShardedBenchmark {\n  private static final int TOTAL_OPERATIONS = 10000000;\n\n  public static void main(String[] args) throws UnknownHostException, IOException {\n\n    long begin = Calendar.getInstance().getTimeInMillis();\n\n    for (int n = 0; n <= TOTAL_OPERATIONS; n++) {\n      String key = \"foo\" + n;\n      Hashing.MD5.hash(key);\n    }\n\n    long elapsed = Calendar.getInstance().getTimeInMillis() - begin;\n\n    System.out.println(((1000 * TOTAL_OPERATIONS) / elapsed) + \" MD5 ops\");\n\n    begin = Calendar.getInstance().getTimeInMillis();\n\n    for (int n = 0; n <= TOTAL_OPERATIONS; n++) {\n      String key = \"foo\" + n;\n      Hashing.MURMUR_HASH.hash(key);\n    }\n\n    elapsed = Calendar.getInstance().getTimeInMillis() - begin;\n\n    System.out.println(((1000 * TOTAL_OPERATIONS) / elapsed) + \" Murmur ops\");\n\n  }\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/collections/SetFromListTest.java",
    "content": "package redis.clients.jedis.tests.collections;\n\nimport static org.junit.Assert.*;\n\nimport java.lang.reflect.Method;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Set;\n\nimport org.junit.BeforeClass;\nimport org.junit.Test;\n\npublic class SetFromListTest {\n\n  private static Method method;\n\n  @BeforeClass\n  public static void beforeClass() throws Exception {\n    Class<?> clazz = Class.forName(\"redis.clients.jedis.BinaryJedis$SetFromList\");\n    method = clazz.getDeclaredMethod(\"of\", List.class);\n    method.setAccessible(true);\n  }\n\n  /**\n   * Instantiate SetFromList class by reflection because it is protected static inner class of\n   * BinaryJedis.\n   */\n  @SuppressWarnings(\"unchecked\")\n  private <E> Set<E> setFromList(List<E> list) throws Exception {\n    return (Set<E>) method.invoke(null, list);\n  }\n\n  @Test\n  public void setOperations() throws Exception {\n\n    // add\n    Set<String> cut = setFromList(new ArrayList<String>());\n    cut.add(\"A\");\n    cut.add(\"B\");\n    cut.add(\"A\");\n\n    assertEquals(2, cut.size());\n\n    // remove\n    cut.remove(\"A\");\n    assertEquals(1, cut.size());\n\n    cut.remove(\"C\");\n    assertEquals(1, cut.size());\n\n    // contains\n    assertTrue(cut.contains(\"B\"));\n    assertFalse(cut.contains(\"A\"));\n\n    cut.add(\"C\");\n    cut.add(\"D\");\n\n    // containsAll\n    assertTrue(cut.containsAll(cut));\n\n    // retainAll\n    cut.retainAll(Arrays.asList(\"C\", \"D\"));\n    assertEquals(2, cut.size());\n    assertTrue(cut.contains(\"C\"));\n    assertTrue(cut.contains(\"D\"));\n\n    // removeAll\n    cut.removeAll(Arrays.asList(\"C\"));\n    assertEquals(1, cut.size());\n    assertTrue(cut.contains(\"D\"));\n\n    // clear\n    cut.clear();\n    assertTrue(cut.isEmpty());\n  }\n\n  @Test\n  public void iteration() throws Exception {\n\n    List<String> list = new ArrayList<String>();\n\n    for (int i = 'a'; i <= 'z'; i++) {\n      list.add(String.valueOf((char) i));\n    }\n\n    Set<String> cut = setFromList(list);\n\n    // ordering guarantee\n    int i = 0;\n    for (String x : cut) {\n      assertEquals(list.get(i++), x);\n    }\n  }\n\n  @Test\n  public void equals() throws Exception {\n\n    Set<String> hashSet = new HashSet<String>();\n\n    for (int i = 'a'; i <= 'z'; i++) {\n      hashSet.add(String.valueOf((char) i));\n    }\n\n    Set<String> cut = setFromList(new ArrayList<String>(hashSet));\n\n    assertTrue(hashSet.equals(cut));\n    assertTrue(cut.equals(hashSet));\n\n    // equals with null\n    assertFalse(cut.equals(null));\n\n    // equals with other types\n    assertFalse(cut.equals(new ArrayList<String>()));\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/commands/AllKindOfValuesCommandsTest.java",
    "content": "package redis.clients.jedis.tests.commands;\n\nimport static redis.clients.jedis.ScanParams.SCAN_POINTER_START;\nimport static redis.clients.jedis.ScanParams.SCAN_POINTER_START_BINARY;\nimport static redis.clients.jedis.params.set.SetParams.setParams;\n\nimport java.util.Arrays;\nimport java.util.HashSet;\nimport java.util.Set;\n\nimport org.junit.Test;\n\nimport redis.clients.jedis.Protocol.Keyword;\nimport redis.clients.jedis.ScanParams;\nimport redis.clients.jedis.ScanResult;\nimport redis.clients.jedis.exceptions.JedisDataException;\nimport redis.clients.util.SafeEncoder;\n\npublic class AllKindOfValuesCommandsTest extends JedisCommandTestBase {\n  final byte[] bfoo = { 0x01, 0x02, 0x03, 0x04 };\n  final byte[] bfoo1 = { 0x01, 0x02, 0x03, 0x04, 0x0A };\n  final byte[] bfoo2 = { 0x01, 0x02, 0x03, 0x04, 0x0B };\n  final byte[] bfoo3 = { 0x01, 0x02, 0x03, 0x04, 0x0C };\n  final byte[] bbar = { 0x05, 0x06, 0x07, 0x08 };\n  final byte[] bbar1 = { 0x05, 0x06, 0x07, 0x08, 0x0A };\n  final byte[] bbar2 = { 0x05, 0x06, 0x07, 0x08, 0x0B };\n  final byte[] bbar3 = { 0x05, 0x06, 0x07, 0x08, 0x0C };\n\n  final byte[] bfoobar = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };\n  final byte[] bfoostar = { 0x01, 0x02, 0x03, 0x04, '*' };\n  final byte[] bbarstar = { 0x05, 0x06, 0x07, 0x08, '*' };\n\n  final byte[] bnx = { 0x6E, 0x78 };\n  final byte[] bex = { 0x65, 0x78 };\n  final int expireSeconds = 2;\n\n  @Test\n  public void ping() {\n    String status = jedis.ping();\n    assertEquals(\"PONG\", status);\n  }\n\n  @Test\n  public void exists() {\n    String status = jedis.set(\"foo\", \"bar\");\n    assertEquals(\"OK\", status);\n\n    status = jedis.set(bfoo, bbar);\n    assertEquals(\"OK\", status);\n\n    boolean reply = jedis.exists(\"foo\");\n    assertTrue(reply);\n\n    reply = jedis.exists(bfoo);\n    assertTrue(reply);\n\n    long lreply = jedis.del(\"foo\");\n    assertEquals(1, lreply);\n\n    lreply = jedis.del(bfoo);\n    assertEquals(1, lreply);\n\n    reply = jedis.exists(\"foo\");\n    assertFalse(reply);\n\n    reply = jedis.exists(bfoo);\n    assertFalse(reply);\n  }\n\n  @Test\n  public void existsMany() {\n    String status = jedis.set(\"foo1\", \"bar1\");\n    assertEquals(\"OK\", status);\n\n    status = jedis.set(\"foo2\", \"bar2\");\n    assertEquals(\"OK\", status);\n\n    long reply = jedis.exists(\"foo1\", \"foo2\");\n    assertEquals(2, reply);\n\n    long lreply = jedis.del(\"foo1\");\n    assertEquals(1, lreply);\n\n    reply = jedis.exists(\"foo1\", \"foo2\");\n    assertEquals(1, reply);\n  }\n\n  @Test\n  public void del() {\n    jedis.set(\"foo1\", \"bar1\");\n    jedis.set(\"foo2\", \"bar2\");\n    jedis.set(\"foo3\", \"bar3\");\n\n    long reply = jedis.del(\"foo1\", \"foo2\", \"foo3\");\n    assertEquals(3, reply);\n\n    Boolean breply = jedis.exists(\"foo1\");\n    assertFalse(breply);\n    breply = jedis.exists(\"foo2\");\n    assertFalse(breply);\n    breply = jedis.exists(\"foo3\");\n    assertFalse(breply);\n\n    jedis.set(\"foo1\", \"bar1\");\n\n    reply = jedis.del(\"foo1\", \"foo2\");\n    assertEquals(1, reply);\n\n    reply = jedis.del(\"foo1\", \"foo2\");\n    assertEquals(0, reply);\n\n    // Binary ...\n    jedis.set(bfoo1, bbar1);\n    jedis.set(bfoo2, bbar2);\n    jedis.set(bfoo3, bbar3);\n\n    reply = jedis.del(bfoo1, bfoo2, bfoo3);\n    assertEquals(3, reply);\n\n    breply = jedis.exists(bfoo1);\n    assertFalse(breply);\n    breply = jedis.exists(bfoo2);\n    assertFalse(breply);\n    breply = jedis.exists(bfoo3);\n    assertFalse(breply);\n\n    jedis.set(bfoo1, bbar1);\n\n    reply = jedis.del(bfoo1, bfoo2);\n    assertEquals(1, reply);\n\n    reply = jedis.del(bfoo1, bfoo2);\n    assertEquals(0, reply);\n  }\n\n  @Test\n  public void type() {\n    jedis.set(\"foo\", \"bar\");\n    String status = jedis.type(\"foo\");\n    assertEquals(\"string\", status);\n\n    // Binary\n    jedis.set(bfoo, bbar);\n    status = jedis.type(bfoo);\n    assertEquals(\"string\", status);\n  }\n\n  @Test\n  public void keys() {\n    jedis.set(\"foo\", \"bar\");\n    jedis.set(\"foobar\", \"bar\");\n\n    Set<String> keys = jedis.keys(\"foo*\");\n    Set<String> expected = new HashSet<String>();\n    expected.add(\"foo\");\n    expected.add(\"foobar\");\n    assertEquals(expected, keys);\n\n    expected = new HashSet<String>();\n    keys = jedis.keys(\"bar*\");\n\n    assertEquals(expected, keys);\n\n    // Binary\n    jedis.set(bfoo, bbar);\n    jedis.set(bfoobar, bbar);\n\n    Set<byte[]> bkeys = jedis.keys(bfoostar);\n    assertEquals(2, bkeys.size());\n    assertTrue(setContains(bkeys, bfoo));\n    assertTrue(setContains(bkeys, bfoobar));\n\n    bkeys = jedis.keys(bbarstar);\n\n    assertEquals(0, bkeys.size());\n  }\n\n  @Test\n  public void randomKey() {\n    assertEquals(null, jedis.randomKey());\n\n    jedis.set(\"foo\", \"bar\");\n\n    assertEquals(\"foo\", jedis.randomKey());\n\n    jedis.set(\"bar\", \"foo\");\n\n    String randomkey = jedis.randomKey();\n    assertTrue(randomkey.equals(\"foo\") || randomkey.equals(\"bar\"));\n\n    // Binary\n    jedis.del(\"foo\");\n    jedis.del(\"bar\");\n    assertEquals(null, jedis.randomKey());\n\n    jedis.set(bfoo, bbar);\n\n    assertArrayEquals(bfoo, jedis.randomBinaryKey());\n\n    jedis.set(bbar, bfoo);\n\n    byte[] randomBkey = jedis.randomBinaryKey();\n    assertTrue(Arrays.equals(randomBkey, bfoo) || Arrays.equals(randomBkey, bbar));\n\n  }\n\n  @Test\n  public void rename() {\n    jedis.set(\"foo\", \"bar\");\n    String status = jedis.rename(\"foo\", \"bar\");\n    assertEquals(\"OK\", status);\n\n    String value = jedis.get(\"foo\");\n    assertEquals(null, value);\n\n    value = jedis.get(\"bar\");\n    assertEquals(\"bar\", value);\n\n    // Binary\n    jedis.set(bfoo, bbar);\n    String bstatus = jedis.rename(bfoo, bbar);\n    assertEquals(\"OK\", bstatus);\n\n    byte[] bvalue = jedis.get(bfoo);\n    assertEquals(null, bvalue);\n\n    bvalue = jedis.get(bbar);\n    assertArrayEquals(bbar, bvalue);\n  }\n\n  @Test\n  public void renameOldAndNewAreTheSame() {\n    jedis.set(\"foo\", \"bar\");\n    jedis.rename(\"foo\", \"foo\");\n\n    // Binary\n    jedis.set(bfoo, bbar);\n    jedis.rename(bfoo, bfoo);\n  }\n\n  @Test\n  public void renamenx() {\n    jedis.set(\"foo\", \"bar\");\n    long status = jedis.renamenx(\"foo\", \"bar\");\n    assertEquals(1, status);\n\n    jedis.set(\"foo\", \"bar\");\n    status = jedis.renamenx(\"foo\", \"bar\");\n    assertEquals(0, status);\n\n    // Binary\n    jedis.set(bfoo, bbar);\n    long bstatus = jedis.renamenx(bfoo, bbar);\n    assertEquals(1, bstatus);\n\n    jedis.set(bfoo, bbar);\n    bstatus = jedis.renamenx(bfoo, bbar);\n    assertEquals(0, bstatus);\n\n  }\n\n  @Test\n  public void dbSize() {\n    long size = jedis.dbSize();\n    assertEquals(0, size);\n\n    jedis.set(\"foo\", \"bar\");\n    size = jedis.dbSize();\n    assertEquals(1, size);\n\n    // Binary\n    jedis.set(bfoo, bbar);\n    size = jedis.dbSize();\n    assertEquals(2, size);\n  }\n\n  @Test\n  public void expire() {\n    long status = jedis.expire(\"foo\", 20);\n    assertEquals(0, status);\n\n    jedis.set(\"foo\", \"bar\");\n    status = jedis.expire(\"foo\", 20);\n    assertEquals(1, status);\n\n    // Binary\n    long bstatus = jedis.expire(bfoo, 20);\n    assertEquals(0, bstatus);\n\n    jedis.set(bfoo, bbar);\n    bstatus = jedis.expire(bfoo, 20);\n    assertEquals(1, bstatus);\n\n  }\n\n  @Test\n  public void expireAt() {\n    long unixTime = (System.currentTimeMillis() / 1000L) + 20;\n\n    long status = jedis.expireAt(\"foo\", unixTime);\n    assertEquals(0, status);\n\n    jedis.set(\"foo\", \"bar\");\n    unixTime = (System.currentTimeMillis() / 1000L) + 20;\n    status = jedis.expireAt(\"foo\", unixTime);\n    assertEquals(1, status);\n\n    // Binary\n    long bstatus = jedis.expireAt(bfoo, unixTime);\n    assertEquals(0, bstatus);\n\n    jedis.set(bfoo, bbar);\n    unixTime = (System.currentTimeMillis() / 1000L) + 20;\n    bstatus = jedis.expireAt(bfoo, unixTime);\n    assertEquals(1, bstatus);\n\n  }\n\n  @Test\n  public void ttl() {\n    long ttl = jedis.ttl(\"foo\");\n    assertEquals(-2, ttl);\n\n    jedis.set(\"foo\", \"bar\");\n    ttl = jedis.ttl(\"foo\");\n    assertEquals(-1, ttl);\n\n    jedis.expire(\"foo\", 20);\n    ttl = jedis.ttl(\"foo\");\n    assertTrue(ttl >= 0 && ttl <= 20);\n\n    // Binary\n    long bttl = jedis.ttl(bfoo);\n    assertEquals(-2, bttl);\n\n    jedis.set(bfoo, bbar);\n    bttl = jedis.ttl(bfoo);\n    assertEquals(-1, bttl);\n\n    jedis.expire(bfoo, 20);\n    bttl = jedis.ttl(bfoo);\n    assertTrue(bttl >= 0 && bttl <= 20);\n\n  }\n\n  @Test\n  public void select() {\n    jedis.set(\"foo\", \"bar\");\n    String status = jedis.select(1);\n    assertEquals(\"OK\", status);\n    assertEquals(null, jedis.get(\"foo\"));\n    status = jedis.select(0);\n    assertEquals(\"OK\", status);\n    assertEquals(\"bar\", jedis.get(\"foo\"));\n    // Binary\n    jedis.set(bfoo, bbar);\n    String bstatus = jedis.select(1);\n    assertEquals(\"OK\", bstatus);\n    assertEquals(null, jedis.get(bfoo));\n    bstatus = jedis.select(0);\n    assertEquals(\"OK\", bstatus);\n    assertArrayEquals(bbar, jedis.get(bfoo));\n  }\n\n  @Test\n  public void getDB() {\n    assertEquals(0, jedis.getDB());\n    jedis.select(1);\n    assertEquals(1, jedis.getDB());\n  }\n\n  @Test\n  public void move() {\n    long status = jedis.move(\"foo\", 1);\n    assertEquals(0, status);\n\n    jedis.set(\"foo\", \"bar\");\n    status = jedis.move(\"foo\", 1);\n    assertEquals(1, status);\n    assertEquals(null, jedis.get(\"foo\"));\n\n    jedis.select(1);\n    assertEquals(\"bar\", jedis.get(\"foo\"));\n\n    // Binary\n    jedis.select(0);\n    long bstatus = jedis.move(bfoo, 1);\n    assertEquals(0, bstatus);\n\n    jedis.set(bfoo, bbar);\n    bstatus = jedis.move(bfoo, 1);\n    assertEquals(1, bstatus);\n    assertEquals(null, jedis.get(bfoo));\n\n    jedis.select(1);\n    assertArrayEquals(bbar, jedis.get(bfoo));\n\n  }\n\n  @Test\n  public void flushDB() {\n    jedis.set(\"foo\", \"bar\");\n    assertEquals(1, jedis.dbSize().intValue());\n    jedis.set(\"bar\", \"foo\");\n    jedis.move(\"bar\", 1);\n    String status = jedis.flushDB();\n    assertEquals(\"OK\", status);\n    assertEquals(0, jedis.dbSize().intValue());\n    jedis.select(1);\n    assertEquals(1, jedis.dbSize().intValue());\n    jedis.del(\"bar\");\n\n    // Binary\n    jedis.select(0);\n    jedis.set(bfoo, bbar);\n    assertEquals(1, jedis.dbSize().intValue());\n    jedis.set(bbar, bfoo);\n    jedis.move(bbar, 1);\n    String bstatus = jedis.flushDB();\n    assertEquals(\"OK\", bstatus);\n    assertEquals(0, jedis.dbSize().intValue());\n    jedis.select(1);\n    assertEquals(1, jedis.dbSize().intValue());\n\n  }\n\n  @Test\n  public void flushAll() {\n    jedis.set(\"foo\", \"bar\");\n    assertEquals(1, jedis.dbSize().intValue());\n    jedis.set(\"bar\", \"foo\");\n    jedis.move(\"bar\", 1);\n    String status = jedis.flushAll();\n    assertEquals(\"OK\", status);\n    assertEquals(0, jedis.dbSize().intValue());\n    jedis.select(1);\n    assertEquals(0, jedis.dbSize().intValue());\n\n    // Binary\n    jedis.select(0);\n    jedis.set(bfoo, bbar);\n    assertEquals(1, jedis.dbSize().intValue());\n    jedis.set(bbar, bfoo);\n    jedis.move(bbar, 1);\n    String bstatus = jedis.flushAll();\n    assertEquals(\"OK\", bstatus);\n    assertEquals(0, jedis.dbSize().intValue());\n    jedis.select(1);\n    assertEquals(0, jedis.dbSize().intValue());\n\n  }\n\n  @Test\n  public void persist() {\n    jedis.setex(\"foo\", 60 * 60, \"bar\");\n    assertTrue(jedis.ttl(\"foo\") > 0);\n    long status = jedis.persist(\"foo\");\n    assertEquals(1, status);\n    assertEquals(-1, jedis.ttl(\"foo\").intValue());\n\n    // Binary\n    jedis.setex(bfoo, 60 * 60, bbar);\n    assertTrue(jedis.ttl(bfoo) > 0);\n    long bstatus = jedis.persist(bfoo);\n    assertEquals(1, bstatus);\n    assertEquals(-1, jedis.ttl(bfoo).intValue());\n\n  }\n\n  @Test\n  public void echo() {\n    String result = jedis.echo(\"hello world\");\n    assertEquals(\"hello world\", result);\n\n    // Binary\n    byte[] bresult = jedis.echo(SafeEncoder.encode(\"hello world\"));\n    assertArrayEquals(SafeEncoder.encode(\"hello world\"), bresult);\n  }\n\n  @Test\n  public void dumpAndRestore() {\n    jedis.set(\"foo1\", \"bar1\");\n    byte[] sv = jedis.dump(\"foo1\");\n    jedis.restore(\"foo2\", 0, sv);\n    assertTrue(jedis.exists(\"foo2\"));\n  }\n\n  @Test\n  public void pexpire() {\n    long status = jedis.pexpire(\"foo\", 10000);\n    assertEquals(0, status);\n\n    jedis.set(\"foo1\", \"bar1\");\n    status = jedis.pexpire(\"foo1\", 10000);\n    assertEquals(1, status);\n\n    jedis.set(\"foo2\", \"bar2\");\n    status = jedis.pexpire(\"foo2\", 200000000000L);\n    assertEquals(1, status);\n\n    long pttl = jedis.pttl(\"foo2\");\n    assertTrue(pttl > 100000000000L);\n  }\n\n  @Test\n  public void pexpireAt() {\n    long unixTime = (System.currentTimeMillis()) + 10000;\n\n    long status = jedis.pexpireAt(\"foo\", unixTime);\n    assertEquals(0, status);\n\n    jedis.set(\"foo\", \"bar\");\n    unixTime = (System.currentTimeMillis()) + 10000;\n    status = jedis.pexpireAt(\"foo\", unixTime);\n    assertEquals(1, status);\n  }\n\n  @Test\n  public void pttl() {\n    long pttl = jedis.pttl(\"foo\");\n    assertEquals(-2, pttl);\n\n    jedis.set(\"foo\", \"bar\");\n    pttl = jedis.pttl(\"foo\");\n    assertEquals(-1, pttl);\n\n    jedis.pexpire(\"foo\", 20000);\n    pttl = jedis.pttl(\"foo\");\n    assertTrue(pttl >= 0 && pttl <= 20000);\n  }\n\n  @Test\n  public void psetex() {\n    long pttl = jedis.pttl(\"foo\");\n    assertEquals(-2, pttl);\n\n    String status = jedis.psetex(\"foo\", 200000000000L, \"bar\");\n    assertTrue(Keyword.OK.name().equalsIgnoreCase(status));\n\n    pttl = jedis.pttl(\"foo\");\n    assertTrue(pttl > 100000000000L);\n  }\n\n  @Test\n  public void scan() {\n    jedis.set(\"b\", \"b\");\n    jedis.set(\"a\", \"a\");\n\n    ScanResult<String> result = jedis.scan(SCAN_POINTER_START);\n\n    assertEquals(SCAN_POINTER_START, result.getCursor());\n    assertFalse(result.getResult().isEmpty());\n\n    // binary\n    ScanResult<byte[]> bResult = jedis.scan(SCAN_POINTER_START_BINARY);\n\n    assertArrayEquals(SCAN_POINTER_START_BINARY, bResult.getCursorAsBytes());\n    assertFalse(bResult.getResult().isEmpty());\n  }\n\n  @Test\n  public void scanMatch() {\n    ScanParams params = new ScanParams();\n    params.match(\"a*\");\n\n    jedis.set(\"b\", \"b\");\n    jedis.set(\"a\", \"a\");\n    jedis.set(\"aa\", \"aa\");\n    ScanResult<String> result = jedis.scan(SCAN_POINTER_START, params);\n\n    assertEquals(SCAN_POINTER_START, result.getCursor());\n    assertFalse(result.getResult().isEmpty());\n\n    // binary\n    params = new ScanParams();\n    params.match(bfoostar);\n\n    jedis.set(bfoo1, bbar);\n    jedis.set(bfoo2, bbar);\n    jedis.set(bfoo3, bbar);\n\n    ScanResult<byte[]> bResult = jedis.scan(SCAN_POINTER_START_BINARY, params);\n\n    assertArrayEquals(SCAN_POINTER_START_BINARY, bResult.getCursorAsBytes());\n    assertFalse(bResult.getResult().isEmpty());\n  }\n\n  @Test\n  public void scanCount() {\n    ScanParams params = new ScanParams();\n    params.count(2);\n\n    for (int i = 0; i < 10; i++) {\n      jedis.set(\"a\" + i, \"a\" + i);\n    }\n\n    ScanResult<String> result = jedis.scan(SCAN_POINTER_START, params);\n\n    assertFalse(result.getResult().isEmpty());\n\n    // binary\n    params = new ScanParams();\n    params.count(2);\n\n    jedis.set(bfoo1, bbar);\n    jedis.set(bfoo2, bbar);\n    jedis.set(bfoo3, bbar);\n\n    ScanResult<byte[]> bResult = jedis.scan(SCAN_POINTER_START_BINARY, params);\n\n    assertFalse(bResult.getResult().isEmpty());\n  }\n\n  @Test\n  public void setNxExAndGet() {\n    String status = jedis.set(\"hello\", \"world\", setParams().nx().ex(expireSeconds));\n    assertTrue(Keyword.OK.name().equalsIgnoreCase(status));\n    String value = jedis.get(\"hello\");\n    assertEquals(\"world\", value);\n\n    jedis.set(\"hello\", \"bar\", setParams().nx().ex(expireSeconds));\n    value = jedis.get(\"hello\");\n    assertEquals(\"world\", value);\n\n    long ttl = jedis.ttl(\"hello\");\n    assertTrue(ttl > 0 && ttl <= expireSeconds);\n\n    // binary\n    byte[] bworld = { 0x77, 0x6F, 0x72, 0x6C, 0x64 };\n    byte[] bhello = { 0x68, 0x65, 0x6C, 0x6C, 0x6F };\n\n    String bstatus = jedis.set(bworld, bhello, setParams().nx().ex(expireSeconds));\n    assertTrue(Keyword.OK.name().equalsIgnoreCase(bstatus));\n    byte[] bvalue = jedis.get(bworld);\n    assertTrue(Arrays.equals(bhello, bvalue));\n\n    jedis.set(bworld, bbar, setParams().nx().ex(expireSeconds));\n    bvalue = jedis.get(bworld);\n    assertTrue(Arrays.equals(bhello, bvalue));\n\n    long bttl = jedis.ttl(bworld);\n    assertTrue(bttl > 0 && bttl <= expireSeconds);\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/commands/BinaryValuesCommandsTest.java",
    "content": "package redis.clients.jedis.tests.commands;\n\nimport static redis.clients.jedis.params.set.SetParams.setParams;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\n\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport redis.clients.jedis.Protocol.Keyword;\nimport redis.clients.jedis.exceptions.JedisDataException;\n\npublic class BinaryValuesCommandsTest extends JedisCommandTestBase {\n  byte[] bfoo = { 0x01, 0x02, 0x03, 0x04 };\n  byte[] bbar = { 0x05, 0x06, 0x07, 0x08 };\n  byte[] bxx = { 0x78, 0x78 };\n  byte[] bnx = { 0x6E, 0x78 };\n  byte[] bex = { 0x65, 0x78 };\n  byte[] bpx = { 0x70, 0x78 };\n  int expireSeconds = 2;\n  long expireMillis = expireSeconds * 1000;\n  byte[] binaryValue;\n\n  @Before\n  public void startUp() {\n    StringBuilder sb = new StringBuilder();\n\n    for (int n = 0; n < 1000; n++) {\n      sb.append(\"A\");\n    }\n\n    binaryValue = sb.toString().getBytes();\n  }\n\n  @Test\n  public void setAndGet() {\n    String status = jedis.set(bfoo, binaryValue);\n    assertTrue(Keyword.OK.name().equalsIgnoreCase(status));\n\n    byte[] value = jedis.get(bfoo);\n    assertTrue(Arrays.equals(binaryValue, value));\n\n    assertNull(jedis.get(bbar));\n  }\n\n  @Test\n  public void setNxExAndGet() {\n    String status = jedis.set(bfoo, binaryValue, setParams().nx().ex(expireSeconds));\n    assertTrue(Keyword.OK.name().equalsIgnoreCase(status));\n    byte[] value = jedis.get(bfoo);\n    assertTrue(Arrays.equals(binaryValue, value));\n\n    assertNull(jedis.get(bbar));\n  }\n\n  @Test\n  public void setIfNotExistAndGet() {\n    String status = jedis.set(bfoo, binaryValue);\n    assertTrue(Keyword.OK.name().equalsIgnoreCase(status));\n    // nx should fail if value exists\n    String statusFail = jedis.set(bfoo, binaryValue, setParams().nx().ex(expireSeconds));\n    assertNull(statusFail);\n\n    byte[] value = jedis.get(bfoo);\n    assertTrue(Arrays.equals(binaryValue, value));\n\n    assertNull(jedis.get(bbar));\n  }\n\n  @Test\n  public void setIfExistAndGet() {\n    String status = jedis.set(bfoo, binaryValue);\n    assertTrue(Keyword.OK.name().equalsIgnoreCase(status));\n    // nx should fail if value exists\n    String statusSuccess = jedis.set(bfoo, binaryValue, setParams().xx().ex(expireSeconds));\n    assertTrue(Keyword.OK.name().equalsIgnoreCase(statusSuccess));\n\n    byte[] value = jedis.get(bfoo);\n    assertTrue(Arrays.equals(binaryValue, value));\n\n    assertNull(jedis.get(bbar));\n  }\n\n  @Test\n  public void setFailIfNotExistAndGet() {\n    // xx should fail if value does NOT exists\n    String statusFail = jedis.set(bfoo, binaryValue, setParams().xx().ex(expireSeconds));\n    assertNull(statusFail);\n  }\n\n  @Test\n  public void setAndExpireMillis() {\n    String status = jedis.set(bfoo, binaryValue, setParams().nx().px(expireMillis));\n    assertTrue(Keyword.OK.name().equalsIgnoreCase(status));\n    long ttl = jedis.ttl(bfoo);\n    assertTrue(ttl > 0 && ttl <= expireSeconds);\n  }\n\n  @Test\n  public void setAndExpire() {\n    String status = jedis.set(bfoo, binaryValue, setParams().nx().ex(expireSeconds));\n    assertTrue(Keyword.OK.name().equalsIgnoreCase(status));\n    long ttl = jedis.ttl(bfoo);\n    assertTrue(ttl > 0 && ttl <= expireSeconds);\n  }\n\n  @Test\n  public void getSet() {\n    byte[] value = jedis.getSet(bfoo, binaryValue);\n    assertNull(value);\n    value = jedis.get(bfoo);\n    assertTrue(Arrays.equals(binaryValue, value));\n  }\n\n  @Test\n  public void mget() {\n    List<byte[]> values = jedis.mget(bfoo, bbar);\n    List<byte[]> expected = new ArrayList<byte[]>();\n    expected.add(null);\n    expected.add(null);\n\n    assertEquals(expected, values);\n\n    jedis.set(bfoo, binaryValue);\n\n    expected = new ArrayList<byte[]>();\n    expected.add(binaryValue);\n    expected.add(null);\n    values = jedis.mget(bfoo, bbar);\n\n    assertEquals(expected, values);\n\n    jedis.set(bbar, bfoo);\n\n    expected = new ArrayList<byte[]>();\n    expected.add(binaryValue);\n    expected.add(bfoo);\n    values = jedis.mget(bfoo, bbar);\n\n    assertEquals(expected, values);\n  }\n\n  @Test\n  public void setnx() {\n    long status = jedis.setnx(bfoo, binaryValue);\n    assertEquals(1, status);\n    assertTrue(Arrays.equals(binaryValue, jedis.get(bfoo)));\n\n    status = jedis.setnx(bfoo, bbar);\n    assertEquals(0, status);\n    assertTrue(Arrays.equals(binaryValue, jedis.get(bfoo)));\n  }\n\n  @Test\n  public void setex() {\n    String status = jedis.setex(bfoo, 20, binaryValue);\n    assertEquals(Keyword.OK.name(), status);\n    long ttl = jedis.ttl(bfoo);\n    assertTrue(ttl > 0 && ttl <= 20);\n  }\n\n  @Test\n  public void mset() {\n    String status = jedis.mset(bfoo, binaryValue, bbar, bfoo);\n    assertEquals(Keyword.OK.name(), status);\n    assertTrue(Arrays.equals(binaryValue, jedis.get(bfoo)));\n    assertTrue(Arrays.equals(bfoo, jedis.get(bbar)));\n  }\n\n  @Test\n  public void msetnx() {\n    long status = jedis.msetnx(bfoo, binaryValue, bbar, bfoo);\n    assertEquals(1, status);\n    assertTrue(Arrays.equals(binaryValue, jedis.get(bfoo)));\n    assertTrue(Arrays.equals(bfoo, jedis.get(bbar)));\n\n    status = jedis.msetnx(bfoo, bbar, \"bar2\".getBytes(), \"foo2\".getBytes());\n    assertEquals(0, status);\n    assertTrue(Arrays.equals(binaryValue, jedis.get(bfoo)));\n    assertTrue(Arrays.equals(bfoo, jedis.get(bbar)));\n  }\n\n  @Test(expected = JedisDataException.class)\n  public void incrWrongValue() {\n    jedis.set(bfoo, binaryValue);\n    jedis.incr(bfoo);\n  }\n\n  @Test\n  public void incr() {\n    long value = jedis.incr(bfoo);\n    assertEquals(1, value);\n    value = jedis.incr(bfoo);\n    assertEquals(2, value);\n  }\n\n  @Test(expected = JedisDataException.class)\n  public void incrByWrongValue() {\n    jedis.set(bfoo, binaryValue);\n    jedis.incrBy(bfoo, 2);\n  }\n\n  @Test\n  public void incrBy() {\n    long value = jedis.incrBy(bfoo, 2);\n    assertEquals(2, value);\n    value = jedis.incrBy(bfoo, 2);\n    assertEquals(4, value);\n  }\n\n  @Test(expected = JedisDataException.class)\n  public void decrWrongValue() {\n    jedis.set(bfoo, binaryValue);\n    jedis.decr(bfoo);\n  }\n\n  @Test\n  public void decr() {\n    long value = jedis.decr(bfoo);\n    assertEquals(-1, value);\n    value = jedis.decr(bfoo);\n    assertEquals(-2, value);\n  }\n\n  @Test(expected = JedisDataException.class)\n  public void decrByWrongValue() {\n    jedis.set(bfoo, binaryValue);\n    jedis.decrBy(bfoo, 2);\n  }\n\n  @Test\n  public void decrBy() {\n    long value = jedis.decrBy(bfoo, 2);\n    assertEquals(-2, value);\n    value = jedis.decrBy(bfoo, 2);\n    assertEquals(-4, value);\n  }\n\n  @Test\n  public void append() {\n    byte[] first512 = new byte[512];\n    System.arraycopy(binaryValue, 0, first512, 0, 512);\n    long value = jedis.append(bfoo, first512);\n    assertEquals(512, value);\n    assertTrue(Arrays.equals(first512, jedis.get(bfoo)));\n\n    byte[] rest = new byte[binaryValue.length - 512];\n    System.arraycopy(binaryValue, 512, rest, 0, binaryValue.length - 512);\n    value = jedis.append(bfoo, rest);\n    assertEquals(binaryValue.length, value);\n\n    assertTrue(Arrays.equals(binaryValue, jedis.get(bfoo)));\n  }\n\n  @Test\n  public void substr() {\n    jedis.set(bfoo, binaryValue);\n\n    byte[] first512 = new byte[512];\n    System.arraycopy(binaryValue, 0, first512, 0, 512);\n    byte[] rfirst512 = jedis.substr(bfoo, 0, 511);\n    assertTrue(Arrays.equals(first512, rfirst512));\n\n    byte[] last512 = new byte[512];\n    System.arraycopy(binaryValue, binaryValue.length - 512, last512, 0, 512);\n    assertTrue(Arrays.equals(last512, jedis.substr(bfoo, -512, -1)));\n\n    assertTrue(Arrays.equals(binaryValue, jedis.substr(bfoo, 0, -1)));\n\n    assertTrue(Arrays.equals(last512, jedis.substr(bfoo, binaryValue.length - 512, 100000)));\n  }\n\n  @Test\n  public void strlen() {\n    jedis.set(bfoo, binaryValue);\n    assertEquals(binaryValue.length, jedis.strlen(bfoo).intValue());\n  }\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/commands/BitCommandsTest.java",
    "content": "package redis.clients.jedis.tests.commands;\n\nimport org.junit.Test;\n\nimport redis.clients.jedis.BitOP;\nimport redis.clients.jedis.BitPosParams;\nimport redis.clients.jedis.Protocol;\n\npublic class BitCommandsTest extends JedisCommandTestBase {\n  @Test\n  public void setAndgetbit() {\n    boolean bit = jedis.setbit(\"foo\", 0, true);\n    assertEquals(false, bit);\n\n    bit = jedis.getbit(\"foo\", 0);\n    assertEquals(true, bit);\n\n    boolean bbit = jedis.setbit(\"bfoo\".getBytes(), 0, \"1\".getBytes());\n    assertFalse(bbit);\n\n    bbit = jedis.getbit(\"bfoo\".getBytes(), 0);\n    assertTrue(bbit);\n  }\n\n  @Test\n  public void bitpos() {\n    String foo = \"foo\";\n\n    jedis.set(foo, String.valueOf(0));\n\n    jedis.setbit(foo, 3, true);\n    jedis.setbit(foo, 7, true);\n    jedis.setbit(foo, 13, true);\n    jedis.setbit(foo, 39, true);\n\n    /*\n     * byte: 0 1 2 3 4 bit: 00010001 / 00000100 / 00000000 / 00000000 / 00000001\n     */\n    long offset = jedis.bitpos(foo, true);\n    assertEquals(2, offset);\n    offset = jedis.bitpos(foo, false);\n    assertEquals(0, offset);\n\n    offset = jedis.bitpos(foo, true, new BitPosParams(1));\n    assertEquals(13, offset);\n    offset = jedis.bitpos(foo, false, new BitPosParams(1));\n    assertEquals(8, offset);\n\n    offset = jedis.bitpos(foo, true, new BitPosParams(2, 3));\n    assertEquals(-1, offset);\n    offset = jedis.bitpos(foo, false, new BitPosParams(2, 3));\n    assertEquals(16, offset);\n\n    offset = jedis.bitpos(foo, true, new BitPosParams(3, 4));\n    assertEquals(39, offset);\n  }\n\n  @Test\n  public void bitposBinary() {\n    // binary\n    byte[] bfoo = { 0x01, 0x02, 0x03, 0x04 };\n\n    jedis.set(bfoo, Protocol.toByteArray(0));\n\n    jedis.setbit(bfoo, 3, true);\n    jedis.setbit(bfoo, 7, true);\n    jedis.setbit(bfoo, 13, true);\n    jedis.setbit(bfoo, 39, true);\n\n    /*\n     * byte: 0 1 2 3 4 bit: 00010001 / 00000100 / 00000000 / 00000000 / 00000001\n     */\n    long offset = jedis.bitpos(bfoo, true);\n    assertEquals(2, offset);\n    offset = jedis.bitpos(bfoo, false);\n    assertEquals(0, offset);\n\n    offset = jedis.bitpos(bfoo, true, new BitPosParams(1));\n    assertEquals(13, offset);\n    offset = jedis.bitpos(bfoo, false, new BitPosParams(1));\n    assertEquals(8, offset);\n\n    offset = jedis.bitpos(bfoo, true, new BitPosParams(2, 3));\n    assertEquals(-1, offset);\n    offset = jedis.bitpos(bfoo, false, new BitPosParams(2, 3));\n    assertEquals(16, offset);\n\n    offset = jedis.bitpos(bfoo, true, new BitPosParams(3, 4));\n    assertEquals(39, offset);\n  }\n\n  @Test\n  public void bitposWithNoMatchingBitExist() {\n    String foo = \"foo\";\n\n    jedis.set(foo, String.valueOf(0));\n    for (int idx = 0; idx < 8; idx++) {\n      jedis.setbit(foo, idx, true);\n    }\n\n    /*\n     * byte: 0 bit: 11111111\n     */\n    long offset = jedis.bitpos(foo, false);\n    // offset should be last index + 1\n    assertEquals(8, offset);\n  }\n\n  @Test\n  public void bitposWithNoMatchingBitExistWithinRange() {\n    String foo = \"foo\";\n\n    jedis.set(foo, String.valueOf(0));\n    for (int idx = 0; idx < 8 * 5; idx++) {\n      jedis.setbit(foo, idx, true);\n    }\n\n    /*\n     * byte: 0 1 2 3 4 bit: 11111111 / 11111111 / 11111111 / 11111111 / 11111111\n     */\n    long offset = jedis.bitpos(foo, false, new BitPosParams(2, 3));\n    // offset should be -1\n    assertEquals(-1, offset);\n  }\n\n  @Test\n  public void setAndgetrange() {\n    jedis.set(\"key1\", \"Hello World\");\n    long reply = jedis.setrange(\"key1\", 6, \"Jedis\");\n    assertEquals(11, reply);\n\n    assertEquals(jedis.get(\"key1\"), \"Hello Jedis\");\n\n    assertEquals(\"Hello\", jedis.getrange(\"key1\", 0, 4));\n    assertEquals(\"Jedis\", jedis.getrange(\"key1\", 6, 11));\n  }\n\n  @Test\n  public void bitCount() {\n    jedis.del(\"foo\");\n\n    jedis.setbit(\"foo\", 16, true);\n    jedis.setbit(\"foo\", 24, true);\n    jedis.setbit(\"foo\", 40, true);\n    jedis.setbit(\"foo\", 56, true);\n\n    long c4 = jedis.bitcount(\"foo\");\n    assertEquals(4, c4);\n\n    long c3 = jedis.bitcount(\"foo\", 2L, 5L);\n    assertEquals(3, c3);\n\n    jedis.del(\"foo\");\n  }\n\n  @Test\n  public void bitOp() {\n    jedis.set(\"key1\", \"\\u0060\");\n    jedis.set(\"key2\", \"\\u0044\");\n\n    jedis.bitop(BitOP.AND, \"resultAnd\", \"key1\", \"key2\");\n    String resultAnd = jedis.get(\"resultAnd\");\n    assertEquals(\"\\u0040\", resultAnd);\n\n    jedis.bitop(BitOP.OR, \"resultOr\", \"key1\", \"key2\");\n    String resultOr = jedis.get(\"resultOr\");\n    assertEquals(\"\\u0064\", resultOr);\n\n    jedis.bitop(BitOP.XOR, \"resultXor\", \"key1\", \"key2\");\n    String resultXor = jedis.get(\"resultXor\");\n    assertEquals(\"\\u0024\", resultXor);\n\n    jedis.del(\"resultAnd\");\n    jedis.del(\"resultOr\");\n    jedis.del(\"resultXor\");\n    jedis.del(\"key1\");\n    jedis.del(\"key2\");\n  }\n\n  @Test\n  public void bitOpNot() {\n    jedis.del(\"key\");\n    jedis.setbit(\"key\", 0, true);\n    jedis.setbit(\"key\", 4, true);\n\n    jedis.bitop(BitOP.NOT, \"resultNot\", \"key\");\n\n    String resultNot = jedis.get(\"resultNot\");\n    assertEquals(\"\\u0077\", resultNot);\n\n    jedis.del(\"key\");\n    jedis.del(\"resultNot\");\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/commands/ClusterBinaryJedisCommandsTest.java",
    "content": "package redis.clients.jedis.tests.commands;\n\nimport org.junit.After;\nimport org.junit.AfterClass;\nimport org.junit.Before;\nimport org.junit.Test;\nimport redis.clients.jedis.HostAndPort;\nimport redis.clients.jedis.Jedis;\nimport redis.clients.jedis.JedisCluster;\nimport redis.clients.jedis.tests.HostAndPortUtil;\nimport redis.clients.jedis.tests.JedisTestBase;\nimport redis.clients.util.JedisClusterCRC16;\n\nimport java.util.*;\n\npublic class ClusterBinaryJedisCommandsTest extends JedisTestBase {\n  private Jedis node1;\n  private static Jedis node2;\n  private static Jedis node3;\n\n  private HostAndPort nodeInfo1 = HostAndPortUtil.getClusterServers().get(0);\n  private HostAndPort nodeInfo2 = HostAndPortUtil.getClusterServers().get(1);\n  private HostAndPort nodeInfo3 = HostAndPortUtil.getClusterServers().get(2);\n  private final Set<HostAndPort> jedisClusterNode = new HashSet<HostAndPort>();\n  JedisCluster jedisCluster;\n\n  @Before\n  public void setUp() throws InterruptedException {\n    node1 = new Jedis(nodeInfo1.getHost(), nodeInfo1.getPort());\n    node1.connect();\n    node1.flushAll();\n\n    node2 = new Jedis(nodeInfo2.getHost(), nodeInfo2.getPort());\n    node2.connect();\n    node2.flushAll();\n\n    node3 = new Jedis(nodeInfo3.getHost(), nodeInfo3.getPort());\n    node3.connect();\n    node3.flushAll();\n\n    // ---- configure cluster\n\n    // add nodes to cluster\n    node1.clusterMeet(\"127.0.0.1\", nodeInfo2.getPort());\n    node1.clusterMeet(\"127.0.0.1\", nodeInfo3.getPort());\n\n    // split available slots across the three nodes\n    int slotsPerNode = JedisCluster.HASHSLOTS / 3;\n    int[] node1Slots = new int[slotsPerNode];\n    int[] node2Slots = new int[slotsPerNode + 1];\n    int[] node3Slots = new int[slotsPerNode];\n    for (int i = 0, slot1 = 0, slot2 = 0, slot3 = 0; i < JedisCluster.HASHSLOTS; i++) {\n      if (i < slotsPerNode) {\n        node1Slots[slot1++] = i;\n      } else if (i > slotsPerNode * 2) {\n        node3Slots[slot3++] = i;\n      } else {\n        node2Slots[slot2++] = i;\n      }\n    }\n\n    node1.clusterAddSlots(node1Slots);\n    node2.clusterAddSlots(node2Slots);\n    node3.clusterAddSlots(node3Slots);\n\n    waitForClusterReady();\n\n    jedisClusterNode.add(new HostAndPort(\"127.0.0.1\", 7379));\n    jedisCluster = new JedisCluster(jedisClusterNode);\n\n  }\n\n  @AfterClass\n  public static void cleanUp() {\n    int slotTest = JedisClusterCRC16.getSlot(\"test\");\n    int slot51 = JedisClusterCRC16.getSlot(\"51\");\n    String node3Id = getNodeId(node3.clusterNodes());\n    node2.clusterSetSlotNode(slotTest, node3Id);\n    node2.clusterSetSlotNode(slot51, node3Id);\n    node2.clusterDelSlots(slotTest, slot51);\n  }\n\n  @After\n  public void tearDown() {\n    // clear all slots\n    int[] slotsToDelete = new int[JedisCluster.HASHSLOTS];\n    for (int i = 0; i < JedisCluster.HASHSLOTS; i++) {\n      slotsToDelete[i] = i;\n    }\n    node1.clusterDelSlots(slotsToDelete);\n    node2.clusterDelSlots(slotsToDelete);\n    node3.clusterDelSlots(slotsToDelete);\n  }\n\n  @SuppressWarnings(\"unchecked\")\n  @Test\n  public void testBinaryGetAndSet() {\n    byte[] byteKey = \"foo\".getBytes();\n    byte[] byteValue = \"2\".getBytes();\n    jedisCluster.set(byteKey, byteValue);\n    assertEquals(new String(jedisCluster.get(byteKey)), \"2\");\n  }\n\n  @SuppressWarnings(\"unchecked\")\n  @Test\n  public void testIncr() {\n    byte[] byteKey = \"foo\".getBytes();\n    byte[] byteValue = \"2\".getBytes();\n    jedisCluster.set(byteKey, byteValue);\n    jedisCluster.incr(byteKey);\n    assertEquals(new String(jedisCluster.get(byteKey)), \"3\");\n  }\n\n  @SuppressWarnings(\"unchecked\")\n  @Test\n  public void testSadd() {\n    byte[] byteKey = \"languages\".getBytes();\n    byte[] firstLanguage = \"java\".getBytes();\n    byte[] secondLanguage = \"python\".getBytes();\n    byte[][] listLanguages = { firstLanguage, secondLanguage };\n    jedisCluster.sadd(byteKey, listLanguages);\n    Set<byte[]> setLanguages = jedisCluster.smembers(byteKey);\n    List<String> languages = new ArrayList<String>();\n    for (byte[] language : setLanguages) {\n      languages.add(new String(language));\n    }\n    assertTrue(languages.contains(\"java\"));\n    assertTrue(languages.contains(\"python\"));\n  }\n\n  @SuppressWarnings(\"unchecked\")\n  @Test\n  public void testHmset() {\n    byte[] byteKey = \"language\".getBytes();\n    byte[] language = \"java\".getBytes();\n    HashMap<byte[], byte[]> map = new HashMap();\n    map.put(byteKey, language);\n    jedisCluster.hmset(byteKey, map);\n    List<byte[]> listResults = jedisCluster.hmget(byteKey, byteKey);\n    for (byte[] result : listResults) {\n      String resultString = new String(result);\n      assertEquals(resultString, \"java\");\n    }\n  }\n\n  @SuppressWarnings(\"unchecked\")\n  @Test\n  public void testRpush() {\n    byte[] value1 = \"value1\".getBytes();\n    byte[] value2 = \"value2\".getBytes();\n    byte[] key = \"key1\".getBytes();\n    jedisCluster.del(key);\n    jedisCluster.rpush(key, value1);\n    jedisCluster.rpush(key, value2);\n    long num = 2L;\n    assertEquals(2, (long) jedisCluster.llen(key));\n  }\n\n  @Test\n  public void testGetSlot() {\n    assertEquals(JedisClusterCRC16.getSlot(\"{bar\".getBytes()), JedisClusterCRC16.getSlot(\"{bar\"));\n    assertEquals(JedisClusterCRC16.getSlot(\"{user1000}.following\".getBytes()),\n      JedisClusterCRC16.getSlot(\"{user1000}.followers\".getBytes()));\n    assertNotEquals(JedisClusterCRC16.getSlot(\"foo{}{bar}\".getBytes()),\n      JedisClusterCRC16.getSlot(\"bar\".getBytes()));\n    assertEquals(JedisClusterCRC16.getSlot(\"foo{bar}{zap}\".getBytes()),\n      JedisClusterCRC16.getSlot(\"bar\".getBytes()));\n  }\n\n  private static String getNodeId(String infoOutput) {\n    for (String infoLine : infoOutput.split(\"\\n\")) {\n      if (infoLine.contains(\"myself\")) {\n        return infoLine.split(\" \")[0];\n      }\n    }\n    return \"\";\n  }\n\n  private void waitForClusterReady() throws InterruptedException {\n    boolean clusterOk = false;\n    while (!clusterOk) {\n      if (node1.clusterInfo().split(\"\\n\")[0].contains(\"ok\")\n          && node2.clusterInfo().split(\"\\n\")[0].contains(\"ok\")\n          && node3.clusterInfo().split(\"\\n\")[0].contains(\"ok\")) {\n        clusterOk = true;\n      }\n      Thread.sleep(50);\n    }\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/commands/ClusterCommandsTest.java",
    "content": "package redis.clients.jedis.tests.commands;\n\nimport java.util.List;\n\nimport org.junit.After;\nimport org.junit.AfterClass;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport redis.clients.jedis.HostAndPort;\nimport redis.clients.jedis.Jedis;\nimport redis.clients.jedis.JedisCluster.Reset;\nimport redis.clients.jedis.tests.HostAndPortUtil;\nimport redis.clients.jedis.tests.JedisTestBase;\nimport redis.clients.jedis.tests.utils.JedisClusterTestUtil;\n\npublic class ClusterCommandsTest extends JedisTestBase {\n  private static Jedis node1;\n  private static Jedis node2;\n\n  private HostAndPort nodeInfo1 = HostAndPortUtil.getClusterServers().get(0);\n  private HostAndPort nodeInfo2 = HostAndPortUtil.getClusterServers().get(1);\n\n  @Before\n  public void setUp() throws Exception {\n\n    node1 = new Jedis(nodeInfo1.getHost(), nodeInfo1.getPort());\n    node1.connect();\n    node1.flushAll();\n\n    node2 = new Jedis(nodeInfo2.getHost(), nodeInfo2.getPort());\n    node2.connect();\n    node2.flushAll();\n  }\n\n  @After\n  public void tearDown() {\n    node1.disconnect();\n    node2.disconnect();\n  }\n\n  @AfterClass\n  public static void removeSlots() throws InterruptedException {\n    node1.clusterReset(Reset.SOFT);\n    node2.clusterReset(Reset.SOFT);\n  }\n\n  @Test\n  public void testClusterSoftReset() {\n    node1.clusterMeet(\"127.0.0.1\", nodeInfo2.getPort());\n    assertTrue(node1.clusterNodes().split(\"\\n\").length > 1);\n    node1.clusterReset(Reset.SOFT);\n    assertEquals(1, node1.clusterNodes().split(\"\\n\").length);\n  }\n\n  @Test\n  public void testClusterHardReset() {\n    String nodeId = JedisClusterTestUtil.getNodeId(node1.clusterNodes());\n    node1.clusterReset(Reset.HARD);\n    String newNodeId = JedisClusterTestUtil.getNodeId(node1.clusterNodes());\n    assertNotEquals(nodeId, newNodeId);\n  }\n\n  @Test\n  public void clusterSetSlotImporting() {\n    node2.clusterAddSlots(6000);\n    String[] nodes = node1.clusterNodes().split(\"\\n\");\n    String nodeId = nodes[0].split(\" \")[0];\n    String status = node1.clusterSetSlotImporting(6000, nodeId);\n    assertEquals(\"OK\", status);\n  }\n\n  @Test\n  public void clusterNodes() {\n    String nodes = node1.clusterNodes();\n    assertTrue(nodes.split(\"\\n\").length > 0);\n  }\n\n  @Test\n  public void clusterMeet() {\n    String status = node1.clusterMeet(\"127.0.0.1\", nodeInfo2.getPort());\n    assertEquals(\"OK\", status);\n  }\n\n  @Test\n  public void clusterAddSlots() {\n    String status = node1.clusterAddSlots(1, 2, 3, 4, 5);\n    assertEquals(\"OK\", status);\n  }\n\n  @Test\n  public void clusterDelSlots() {\n    node1.clusterAddSlots(900);\n    String status = node1.clusterDelSlots(900);\n    assertEquals(\"OK\", status);\n  }\n\n  @Test\n  public void clusterInfo() {\n    String info = node1.clusterInfo();\n    assertNotNull(info);\n  }\n\n  @Test\n  public void clusterGetKeysInSlot() {\n    node1.clusterAddSlots(500);\n    List<String> keys = node1.clusterGetKeysInSlot(500, 1);\n    assertEquals(0, keys.size());\n  }\n\n  @Test\n  public void clusterSetSlotNode() {\n    String[] nodes = node1.clusterNodes().split(\"\\n\");\n    String nodeId = nodes[0].split(\" \")[0];\n    String status = node1.clusterSetSlotNode(10000, nodeId);\n    assertEquals(\"OK\", status);\n  }\n\n  @Test\n  public void clusterSetSlotMigrating() {\n    node1.clusterAddSlots(5000);\n    String[] nodes = node1.clusterNodes().split(\"\\n\");\n    String nodeId = nodes[0].split(\" \")[0];\n    String status = node1.clusterSetSlotMigrating(5000, nodeId);\n    assertEquals(\"OK\", status);\n  }\n\n  @Test\n  public void clusterSlots() {\n    // please see cluster slot output format from below commit\n    // @see:\n    // https://github.com/antirez/redis/commit/e14829de3025ffb0d3294e5e5a1553afd9f10b60\n    String status = node1.clusterAddSlots(3000, 3001, 3002);\n    assertEquals(\"OK\", status);\n    status = node2.clusterAddSlots(4000, 4001, 4002);\n    assertEquals(\"OK\", status);\n\n    List<Object> slots = node1.clusterSlots();\n    assertNotNull(slots);\n    assertTrue(slots.size() > 0);\n\n    for (Object slotInfoObj : slots) {\n      List<Object> slotInfo = (List<Object>) slotInfoObj;\n      assertNotNull(slots);\n      assertTrue(slots.size() >= 2);\n\n      assertTrue(slotInfo.get(0) instanceof Long);\n      assertTrue(slotInfo.get(1) instanceof Long);\n\n      if (slots.size() > 2) {\n        // assigned slots\n        assertTrue(slotInfo.get(2) instanceof List);\n      }\n    }\n  }\n\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/commands/ClusterScriptingCommandsTest.java",
    "content": "package redis.clients.jedis.tests.commands;\n\nimport org.junit.After;\nimport org.junit.AfterClass;\nimport org.junit.Before;\nimport org.junit.Test;\nimport redis.clients.jedis.HostAndPort;\nimport redis.clients.jedis.Jedis;\nimport redis.clients.jedis.JedisCluster;\nimport redis.clients.jedis.exceptions.JedisClusterException;\nimport redis.clients.jedis.exceptions.JedisDataException;\nimport redis.clients.jedis.tests.HostAndPortUtil;\nimport redis.clients.jedis.tests.JedisTestBase;\nimport redis.clients.util.JedisClusterCRC16;\n\nimport java.util.ArrayList;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Set;\n\npublic class ClusterScriptingCommandsTest extends JedisTestBase {\n  private Jedis node1;\n  private static Jedis node2;\n  private static Jedis node3;\n\n  private HostAndPort nodeInfo1 = HostAndPortUtil.getClusterServers().get(0);\n  private HostAndPort nodeInfo2 = HostAndPortUtil.getClusterServers().get(1);\n  private HostAndPort nodeInfo3 = HostAndPortUtil.getClusterServers().get(2);\n  private final Set<HostAndPort> jedisClusterNode = new HashSet<HostAndPort>();\n  JedisCluster jedisCluster;\n\n  @Before\n  public void setUp() throws InterruptedException {\n    node1 = new Jedis(nodeInfo1.getHost(), nodeInfo1.getPort());\n    node1.connect();\n    node1.flushAll();\n\n    node2 = new Jedis(nodeInfo2.getHost(), nodeInfo2.getPort());\n    node2.connect();\n    node2.flushAll();\n\n    node3 = new Jedis(nodeInfo3.getHost(), nodeInfo3.getPort());\n    node3.connect();\n    node3.flushAll();\n\n    // ---- configure cluster\n\n    // add nodes to cluster\n    node1.clusterMeet(\"127.0.0.1\", nodeInfo2.getPort());\n    node1.clusterMeet(\"127.0.0.1\", nodeInfo3.getPort());\n\n    // split available slots across the three nodes\n    int slotsPerNode = JedisCluster.HASHSLOTS / 3;\n    int[] node1Slots = new int[slotsPerNode];\n    int[] node2Slots = new int[slotsPerNode + 1];\n    int[] node3Slots = new int[slotsPerNode];\n    for (int i = 0, slot1 = 0, slot2 = 0, slot3 = 0; i < JedisCluster.HASHSLOTS; i++) {\n      if (i < slotsPerNode) {\n        node1Slots[slot1++] = i;\n      } else if (i > slotsPerNode * 2) {\n        node3Slots[slot3++] = i;\n      } else {\n        node2Slots[slot2++] = i;\n      }\n    }\n\n    node1.clusterAddSlots(node1Slots);\n    node2.clusterAddSlots(node2Slots);\n    node3.clusterAddSlots(node3Slots);\n\n    waitForClusterReady();\n\n    jedisClusterNode.add(new HostAndPort(\"127.0.0.1\", 7379));\n    jedisCluster = new JedisCluster(jedisClusterNode);\n\n  }\n\n  @AfterClass\n  public static void cleanUp() {\n    int slotTest = JedisClusterCRC16.getSlot(\"test\");\n    int slot51 = JedisClusterCRC16.getSlot(\"51\");\n    String node3Id = getNodeId(node3.clusterNodes());\n    node2.clusterSetSlotNode(slotTest, node3Id);\n    node2.clusterSetSlotNode(slot51, node3Id);\n    node2.clusterDelSlots(slotTest, slot51);\n  }\n\n  @After\n  public void tearDown() {\n    // clear all slots\n    int[] slotsToDelete = new int[JedisCluster.HASHSLOTS];\n    for (int i = 0; i < JedisCluster.HASHSLOTS; i++) {\n      slotsToDelete[i] = i;\n    }\n    node1.clusterDelSlots(slotsToDelete);\n    node2.clusterDelSlots(slotsToDelete);\n    node3.clusterDelSlots(slotsToDelete);\n  }\n\n  @SuppressWarnings(\"unchecked\")\n  @Test(expected = JedisClusterException.class)\n  public void testJedisClusterException() {\n    String script = \"return {KEYS[1],KEYS[2],ARGV[1],ARGV[2],ARGV[3]}\";\n    List<String> keys = new ArrayList<String>();\n    keys.add(\"key1\");\n    keys.add(\"key2\");\n    List<String> args = new ArrayList<String>();\n    args.add(\"first\");\n    args.add(\"second\");\n    args.add(\"third\");\n    jedisCluster.eval(script, keys, args);\n  }\n\n  @SuppressWarnings(\"unchecked\")\n  @Test\n  public void testEval2() {\n    String script = \"return redis.call('set',KEYS[1],'bar')\";\n    int numKeys = 1;\n    String[] args = { \"foo\" };\n    jedisCluster.eval(script, numKeys, args);\n    assertEquals(jedisCluster.get(\"foo\"), \"bar\");\n  }\n\n  @SuppressWarnings(\"unchecked\")\n  @Test\n  public void testScriptLoadAndScriptExists() {\n    String sha1 = jedisCluster.scriptLoad(\"return redis.call('get','foo')\", \"key1\");\n    assertTrue(jedisCluster.scriptExists(sha1, \"key1\"));\n  }\n\n  @SuppressWarnings(\"unchecked\")\n  @Test\n  public void testEvalsha() {\n    String sha1 = jedisCluster.scriptLoad(\"return 10\", \"key1\");\n    Object o = jedisCluster.evalsha(sha1, 1, \"key1\");\n    assertEquals(\"10\", o.toString());\n  }\n\n  @SuppressWarnings(\"unchecked\")\n  @Test(expected = JedisClusterException.class)\n  public void testJedisClusterException2() {\n    byte[] script = \"return {KEYS[1],KEYS[2],ARGV[1],ARGV[2],ARGV[3]}\".getBytes();\n    List<byte[]> keys = new ArrayList<byte[]>();\n    keys.add(\"key1\".getBytes());\n    keys.add(\"key2\".getBytes());\n    List<byte[]> args = new ArrayList<byte[]>();\n    args.add(\"first\".getBytes());\n    args.add(\"second\".getBytes());\n    args.add(\"third\".getBytes());\n    jedisCluster.eval(script, keys, args);\n  }\n\n  @SuppressWarnings(\"unchecked\")\n  @Test\n  public void testBinaryEval() {\n    byte[] script = \"return redis.call('set',KEYS[1],'bar')\".getBytes();\n    byte[] args = \"foo\".getBytes();\n    jedisCluster.eval(script, 1, args);\n    assertEquals(jedisCluster.get(\"foo\"), \"bar\");\n  }\n\n  @SuppressWarnings(\"unchecked\")\n  @Test\n  public void testBinaryScriptFlush() {\n    byte[] byteKey = \"key1\".getBytes();\n    byte[] sha1 = jedisCluster.scriptLoad(\"return redis.call('get','foo')\".getBytes(), byteKey);\n    assertEquals(\"OK\", jedisCluster.scriptFlush(byteKey));\n  }\n\n  @SuppressWarnings(\"unchecked\")\n  @Test(expected = JedisDataException.class)\n  public void testBinaryScriptKill() {\n    byte[] byteKey = \"key1\".getBytes();\n    jedisCluster.scriptKill(byteKey);\n  }\n\n  @SuppressWarnings(\"unchecked\")\n  @Test\n  public void testBinaryScriptExists() {\n    byte[] byteKey = \"key1\".getBytes();\n    byte[] sha1 = jedisCluster.scriptLoad(\"return redis.call('get','foo')\".getBytes(), byteKey);\n    byte[][] arraySha1 = { sha1 };\n    Long result = 1L;\n    List<Long> listResult = new ArrayList();\n    listResult.add(result);\n    assertEquals(listResult, jedisCluster.scriptExists(byteKey, arraySha1));\n  }\n\n  private static String getNodeId(String infoOutput) {\n    for (String infoLine : infoOutput.split(\"\\n\")) {\n      if (infoLine.contains(\"myself\")) {\n        return infoLine.split(\" \")[0];\n      }\n    }\n    return \"\";\n  }\n\n  private void waitForClusterReady() throws InterruptedException {\n    boolean clusterOk = false;\n    while (!clusterOk) {\n      if (node1.clusterInfo().split(\"\\n\")[0].contains(\"ok\")\n          && node2.clusterInfo().split(\"\\n\")[0].contains(\"ok\")\n          && node3.clusterInfo().split(\"\\n\")[0].contains(\"ok\")) {\n        clusterOk = true;\n      }\n      Thread.sleep(50);\n    }\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/commands/ConnectionHandlingCommandsTest.java",
    "content": "package redis.clients.jedis.tests.commands;\n\nimport org.junit.Test;\n\nimport redis.clients.jedis.BinaryJedis;\nimport redis.clients.jedis.HostAndPort;\nimport redis.clients.jedis.tests.HostAndPortUtil;\n\npublic class ConnectionHandlingCommandsTest extends JedisCommandTestBase {\n  protected static HostAndPort hnp = HostAndPortUtil.getRedisServers().get(0);\n\n  @Test\n  public void quit() {\n    assertEquals(\"OK\", jedis.quit());\n  }\n\n  @Test\n  public void binary_quit() {\n    BinaryJedis bj = new BinaryJedis(hnp.getHost());\n    assertEquals(\"OK\", bj.quit());\n  }\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/commands/ControlCommandsTest.java",
    "content": "package redis.clients.jedis.tests.commands;\n\nimport java.util.List;\n\nimport org.junit.Test;\n\nimport redis.clients.jedis.DebugParams;\nimport redis.clients.jedis.Jedis;\nimport redis.clients.jedis.JedisMonitor;\nimport redis.clients.jedis.exceptions.JedisDataException;\n\npublic class ControlCommandsTest extends JedisCommandTestBase {\n  @Test\n  public void save() {\n    try {\n      String status = jedis.save();\n      assertEquals(\"OK\", status);\n    } catch (JedisDataException e) {\n      assertTrue(\"ERR Background save already in progress\".equalsIgnoreCase(e.getMessage()));\n    }\n  }\n\n  @Test\n  public void bgsave() {\n    try {\n      String status = jedis.bgsave();\n      assertEquals(\"Background saving started\", status);\n    } catch (JedisDataException e) {\n      assertTrue(\"ERR Background save already in progress\".equalsIgnoreCase(e.getMessage()));\n    }\n  }\n\n  @Test\n  public void bgrewriteaof() {\n    String scheduled = \"Background append only file rewriting scheduled\";\n    String started = \"Background append only file rewriting started\";\n\n    String status = jedis.bgrewriteaof();\n\n    boolean ok = status.equals(scheduled) || status.equals(started);\n    assertTrue(ok);\n  }\n\n  @Test\n  public void lastsave() throws InterruptedException {\n    long saved = jedis.lastsave();\n    assertTrue(saved > 0);\n  }\n\n  @Test\n  public void info() {\n    String info = jedis.info();\n    assertNotNull(info);\n    info = jedis.info(\"server\");\n    assertNotNull(info);\n  }\n\n  @Test\n  public void readonly() {\n    try {\n      jedis.readonly();\n    } catch (JedisDataException e) {\n      assertTrue(\"ERR This instance has cluster support disabled\".equalsIgnoreCase(e.getMessage()));\n    }\n  }\n\n  @Test\n  public void monitor() {\n    new Thread(new Runnable() {\n      @Override\n      public void run() {\n        try {\n          // sleep 100ms to make sure that monitor thread runs first\n          Thread.sleep(100);\n        } catch (InterruptedException e) {\n        }\n        Jedis j = new Jedis(\"localhost\");\n        j.auth(\"foobared\");\n        for (int i = 0; i < 5; i++) {\n          j.incr(\"foobared\");\n        }\n        j.disconnect();\n      }\n    }).start();\n\n    jedis.monitor(new JedisMonitor() {\n      private int count = 0;\n\n      @Override\n      public void onCommand(String command) {\n        if (command.contains(\"INCR\")) {\n          count++;\n        }\n        if (count == 5) {\n          client.disconnect();\n        }\n      }\n    });\n  }\n\n  @Test\n  public void configGet() {\n    List<String> info = jedis.configGet(\"m*\");\n    assertNotNull(info);\n  }\n\n  @Test\n  public void configSet() {\n    List<String> info = jedis.configGet(\"maxmemory\");\n    String memory = info.get(1);\n    String status = jedis.configSet(\"maxmemory\", \"200\");\n    assertEquals(\"OK\", status);\n    jedis.configSet(\"maxmemory\", memory);\n  }\n\n  @Test\n  public void sync() {\n    jedis.sync();\n  }\n\n  @Test\n  public void debug() {\n    jedis.set(\"foo\", \"bar\");\n    String resp = jedis.debug(DebugParams.OBJECT(\"foo\"));\n    assertNotNull(resp);\n    resp = jedis.debug(DebugParams.RELOAD());\n    assertNotNull(resp);\n  }\n\n  @Test\n  public void waitReplicas() {\n    Long replicas = jedis.waitReplicas(1, 100);\n    assertEquals(1, replicas.longValue());\n  }\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/commands/GeoCommandsTest.java",
    "content": "package redis.clients.jedis.tests.commands;\n\nimport org.junit.Test;\nimport redis.clients.jedis.GeoCoordinate;\nimport redis.clients.jedis.GeoRadiusResponse;\nimport redis.clients.jedis.GeoUnit;\nimport redis.clients.jedis.params.geo.GeoRadiusParam;\nimport redis.clients.util.SafeEncoder;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\npublic class GeoCommandsTest extends JedisCommandTestBase {\n  final byte[] bfoo = { 0x01, 0x02, 0x03, 0x04 };\n  final byte[] bA = { 0x0A };\n  final byte[] bB = { 0x0B };\n  final byte[] bC = { 0x0C };\n  final byte[] bD = { 0x0D };\n  final byte[] bNotexist = { 0x0F };\n\n  @Test\n  public void geoadd() {\n    long size = jedis.geoadd(\"foo\", 1, 2, \"a\");\n    assertEquals(1, size);\n    size = jedis.geoadd(\"foo\", 2, 3, \"a\");\n    assertEquals(0, size);\n\n    Map<String, GeoCoordinate> coordinateMap = new HashMap<String, GeoCoordinate>();\n    coordinateMap.put(\"a\", new GeoCoordinate(3, 4));\n    coordinateMap.put(\"b\", new GeoCoordinate(2, 3));\n    coordinateMap.put(\"c\", new GeoCoordinate(3.314, 2.3241));\n\n    size = jedis.geoadd(\"foo\", coordinateMap);\n    assertEquals(2, size);\n\n    // binary\n    size = jedis.geoadd(bfoo, 1, 2, bA);\n    assertEquals(1, size);\n    size = jedis.geoadd(bfoo, 2, 3, bA);\n    assertEquals(0, size);\n\n    Map<byte[], GeoCoordinate> bcoordinateMap = new HashMap<byte[], GeoCoordinate>();\n    bcoordinateMap.put(bA, new GeoCoordinate(3, 4));\n    bcoordinateMap.put(bB, new GeoCoordinate(2, 3));\n    bcoordinateMap.put(bC, new GeoCoordinate(3.314, 2.3241));\n\n    size = jedis.geoadd(bfoo, bcoordinateMap);\n    assertEquals(2, size);\n  }\n\n  @Test\n  public void geodist() {\n    prepareGeoData();\n\n    Double dist = jedis.geodist(\"foo\", \"a\", \"b\");\n    assertEquals(dist.intValue(), 157149);\n\n    dist = jedis.geodist(\"foo\", \"a\", \"b\", GeoUnit.KM);\n    assertEquals(dist.intValue(), 157);\n\n    dist = jedis.geodist(\"foo\", \"a\", \"b\", GeoUnit.MI);\n    assertEquals(dist.intValue(), 97);\n\n    dist = jedis.geodist(\"foo\", \"a\", \"b\", GeoUnit.FT);\n    assertEquals(dist.intValue(), 515583);\n\n    // binary\n    dist = jedis.geodist(bfoo, bA, bB);\n    assertEquals(dist.intValue(), 157149);\n\n    dist = jedis.geodist(bfoo, bA, bB, GeoUnit.KM);\n    assertEquals(dist.intValue(), 157);\n\n    dist = jedis.geodist(bfoo, bA, bB, GeoUnit.MI);\n    assertEquals(dist.intValue(), 97);\n\n    dist = jedis.geodist(bfoo, bA, bB, GeoUnit.FT);\n    assertEquals(dist.intValue(), 515583);\n  }\n\n  @Test\n  public void geohash() {\n    prepareGeoData();\n\n    List<String> hashes = jedis.geohash(\"foo\", \"a\", \"b\", \"notexist\");\n    assertEquals(3, hashes.size());\n    assertEquals(\"s0dnu20t9j0\", hashes.get(0));\n    assertEquals(\"s093jd0k720\", hashes.get(1));\n    assertNull(hashes.get(2));\n\n    // binary\n    List<byte[]> bhashes = jedis.geohash(bfoo, bA, bB, bNotexist);\n    assertEquals(3, bhashes.size());\n    assertArrayEquals(SafeEncoder.encode(\"s0dnu20t9j0\"), bhashes.get(0));\n    assertArrayEquals(SafeEncoder.encode(\"s093jd0k720\"), bhashes.get(1));\n    assertNull(bhashes.get(2));\n  }\n\n  @Test\n  public void geopos() {\n    prepareGeoData();\n\n    List<GeoCoordinate> coordinates = jedis.geopos(\"foo\", \"a\", \"b\", \"notexist\");\n    assertEquals(3, coordinates.size());\n    assertTrue(equalsWithinEpsilon(3.0, coordinates.get(0).getLongitude()));\n    assertTrue(equalsWithinEpsilon(4.0, coordinates.get(0).getLatitude()));\n    assertTrue(equalsWithinEpsilon(2.0, coordinates.get(1).getLongitude()));\n    assertTrue(equalsWithinEpsilon(3.0, coordinates.get(1).getLatitude()));\n    assertNull(coordinates.get(2));\n\n    List<GeoCoordinate> bcoordinates = jedis.geopos(bfoo, bA, bB, bNotexist);\n    assertEquals(3, bcoordinates.size());\n    assertTrue(equalsWithinEpsilon(3.0, bcoordinates.get(0).getLongitude()));\n    assertTrue(equalsWithinEpsilon(4.0, bcoordinates.get(0).getLatitude()));\n    assertTrue(equalsWithinEpsilon(2.0, bcoordinates.get(1).getLongitude()));\n    assertTrue(equalsWithinEpsilon(3.0, bcoordinates.get(1).getLatitude()));\n    assertNull(bcoordinates.get(2));\n  }\n\n  @Test\n  public void georadius() {\n    // prepare datas\n    Map<String, GeoCoordinate> coordinateMap = new HashMap<String, GeoCoordinate>();\n    coordinateMap.put(\"Palermo\", new GeoCoordinate(13.361389, 38.115556));\n    coordinateMap.put(\"Catania\", new GeoCoordinate(15.087269, 37.502669));\n    jedis.geoadd(\"Sicily\", coordinateMap);\n\n    List<GeoRadiusResponse> members = jedis.georadius(\"Sicily\", 15, 37, 200, GeoUnit.KM);\n    assertEquals(2, members.size());\n\n    // sort\n    members = jedis.georadius(\"Sicily\", 15, 37, 200, GeoUnit.KM, GeoRadiusParam.geoRadiusParam()\n        .sortAscending());\n    assertEquals(2, members.size());\n    assertEquals(\"Catania\", members.get(0).getMemberByString());\n    assertEquals(\"Palermo\", members.get(1).getMemberByString());\n\n    // sort, count 1\n    members = jedis.georadius(\"Sicily\", 15, 37, 200, GeoUnit.KM, GeoRadiusParam.geoRadiusParam()\n        .sortAscending().count(1));\n    assertEquals(1, members.size());\n\n    // sort, count 1, withdist, withcoord\n    members = jedis.georadius(\"Sicily\", 15, 37, 200, GeoUnit.KM, GeoRadiusParam.geoRadiusParam()\n        .sortAscending().count(1).withCoord().withDist());\n    assertEquals(1, members.size());\n    GeoRadiusResponse response = members.get(0);\n    assertTrue(equalsWithinEpsilon(56.4413, response.getDistance()));\n    assertTrue(equalsWithinEpsilon(15.087269, response.getCoordinate().getLongitude()));\n    assertTrue(equalsWithinEpsilon(37.502669, response.getCoordinate().getLatitude()));\n  }\n\n  @Test\n  public void georadiusBinary() {\n    // prepare datas\n    Map<byte[], GeoCoordinate> bcoordinateMap = new HashMap<byte[], GeoCoordinate>();\n    bcoordinateMap.put(bA, new GeoCoordinate(13.361389, 38.115556));\n    bcoordinateMap.put(bB, new GeoCoordinate(15.087269, 37.502669));\n    jedis.geoadd(bfoo, bcoordinateMap);\n\n    List<GeoRadiusResponse> members = jedis.georadius(bfoo, 15, 37, 200, GeoUnit.KM);\n    assertEquals(2, members.size());\n\n    // sort\n    members = jedis.georadius(bfoo, 15, 37, 200, GeoUnit.KM, GeoRadiusParam.geoRadiusParam()\n        .sortAscending());\n    assertEquals(2, members.size());\n    assertArrayEquals(bB, members.get(0).getMember());\n    assertArrayEquals(bA, members.get(1).getMember());\n\n    // sort, count 1\n    members = jedis.georadius(bfoo, 15, 37, 200, GeoUnit.KM, GeoRadiusParam.geoRadiusParam()\n        .sortAscending().count(1));\n    assertEquals(1, members.size());\n\n    // sort, count 1, withdist, withcoord\n    members = jedis.georadius(bfoo, 15, 37, 200, GeoUnit.KM, GeoRadiusParam.geoRadiusParam()\n        .sortAscending().count(1).withCoord().withDist());\n    assertEquals(1, members.size());\n    GeoRadiusResponse response = members.get(0);\n    assertTrue(equalsWithinEpsilon(56.4413, response.getDistance()));\n    assertTrue(equalsWithinEpsilon(15.087269, response.getCoordinate().getLongitude()));\n    assertTrue(equalsWithinEpsilon(37.502669, response.getCoordinate().getLatitude()));\n  }\n\n  @Test\n  public void georadiusByMember() {\n    jedis.geoadd(\"Sicily\", 13.583333, 37.316667, \"Agrigento\");\n    jedis.geoadd(\"Sicily\", 13.361389, 38.115556, \"Palermo\");\n    jedis.geoadd(\"Sicily\", 15.087269, 37.502669, \"Catania\");\n\n    List<GeoRadiusResponse> members = jedis.georadiusByMember(\"Sicily\", \"Agrigento\", 100,\n      GeoUnit.KM);\n    assertEquals(2, members.size());\n\n    members = jedis.georadiusByMember(\"Sicily\", \"Agrigento\", 100, GeoUnit.KM, GeoRadiusParam\n        .geoRadiusParam().sortAscending());\n    assertEquals(2, members.size());\n    assertEquals(\"Agrigento\", members.get(0).getMemberByString());\n    assertEquals(\"Palermo\", members.get(1).getMemberByString());\n\n    members = jedis.georadiusByMember(\"Sicily\", \"Agrigento\", 100, GeoUnit.KM, GeoRadiusParam\n        .geoRadiusParam().sortAscending().count(1).withCoord().withDist());\n    assertEquals(1, members.size());\n\n    GeoRadiusResponse member = members.get(0);\n    assertEquals(\"Agrigento\", member.getMemberByString());\n    assertTrue(equalsWithinEpsilon(0, member.getDistance()));\n    assertTrue(equalsWithinEpsilon(13.583333, member.getCoordinate().getLongitude()));\n    assertTrue(equalsWithinEpsilon(37.316667, member.getCoordinate().getLatitude()));\n  }\n\n  @Test\n  public void georadiusByMemberBinary() {\n    jedis.geoadd(bfoo, 13.583333, 37.316667, bA);\n    jedis.geoadd(bfoo, 13.361389, 38.115556, bB);\n    jedis.geoadd(bfoo, 15.087269, 37.502669, bC);\n\n    List<GeoRadiusResponse> members = jedis.georadiusByMember(bfoo, bA, 100, GeoUnit.KM);\n    assertEquals(2, members.size());\n\n    members = jedis.georadiusByMember(bfoo, bA, 100, GeoUnit.KM, GeoRadiusParam.geoRadiusParam()\n        .sortAscending());\n    assertEquals(2, members.size());\n    assertArrayEquals(bA, members.get(0).getMember());\n    assertArrayEquals(bB, members.get(1).getMember());\n\n    members = jedis.georadiusByMember(bfoo, bA, 100, GeoUnit.KM, GeoRadiusParam.geoRadiusParam()\n        .sortAscending().count(1).withCoord().withDist());\n    assertEquals(1, members.size());\n\n    GeoRadiusResponse member = members.get(0);\n    assertArrayEquals(bA, member.getMember());\n    assertTrue(equalsWithinEpsilon(0, member.getDistance()));\n    assertTrue(equalsWithinEpsilon(13.583333, member.getCoordinate().getLongitude()));\n    assertTrue(equalsWithinEpsilon(37.316667, member.getCoordinate().getLatitude()));\n  }\n\n  private void prepareGeoData() {\n    Map<String, GeoCoordinate> coordinateMap = new HashMap<String, GeoCoordinate>();\n    coordinateMap.put(\"a\", new GeoCoordinate(3, 4));\n    coordinateMap.put(\"b\", new GeoCoordinate(2, 3));\n    coordinateMap.put(\"c\", new GeoCoordinate(3.314, 2.3241));\n\n    long size = jedis.geoadd(\"foo\", coordinateMap);\n    assertEquals(3, size);\n\n    Map<byte[], GeoCoordinate> bcoordinateMap = new HashMap<byte[], GeoCoordinate>();\n    bcoordinateMap.put(bA, new GeoCoordinate(3, 4));\n    bcoordinateMap.put(bB, new GeoCoordinate(2, 3));\n    bcoordinateMap.put(bC, new GeoCoordinate(3.314, 2.3241));\n\n    size = jedis.geoadd(bfoo, bcoordinateMap);\n    assertEquals(3, size);\n  }\n\n  private boolean equalsWithinEpsilon(double d1, double d2) {\n    double epsilon = 1E-5;\n    return Math.abs(d1 - d2) < epsilon;\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/commands/HashesCommandsTest.java",
    "content": "package redis.clients.jedis.tests.commands;\n\nimport static redis.clients.jedis.ScanParams.SCAN_POINTER_START;\nimport static redis.clients.jedis.ScanParams.SCAN_POINTER_START_BINARY;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.LinkedHashMap;\nimport java.util.LinkedHashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\nimport org.junit.Test;\n\nimport redis.clients.jedis.Pipeline;\nimport redis.clients.jedis.Response;\nimport redis.clients.jedis.ScanParams;\nimport redis.clients.jedis.ScanResult;\n\npublic class HashesCommandsTest extends JedisCommandTestBase {\n  final byte[] bfoo = { 0x01, 0x02, 0x03, 0x04 };\n  final byte[] bbar = { 0x05, 0x06, 0x07, 0x08 };\n  final byte[] bcar = { 0x09, 0x0A, 0x0B, 0x0C };\n\n  final byte[] bbar1 = { 0x05, 0x06, 0x07, 0x08, 0x0A };\n  final byte[] bbar2 = { 0x05, 0x06, 0x07, 0x08, 0x0B };\n  final byte[] bbar3 = { 0x05, 0x06, 0x07, 0x08, 0x0C };\n  final byte[] bbarstar = { 0x05, 0x06, 0x07, 0x08, '*' };\n\n  @Test\n  public void hset() {\n    long status = jedis.hset(\"foo\", \"bar\", \"car\");\n    assertEquals(1, status);\n    status = jedis.hset(\"foo\", \"bar\", \"foo\");\n    assertEquals(0, status);\n\n    // Binary\n    long bstatus = jedis.hset(bfoo, bbar, bcar);\n    assertEquals(1, bstatus);\n    bstatus = jedis.hset(bfoo, bbar, bfoo);\n    assertEquals(0, bstatus);\n\n  }\n\n  @Test\n  public void hget() {\n    jedis.hset(\"foo\", \"bar\", \"car\");\n    assertEquals(null, jedis.hget(\"bar\", \"foo\"));\n    assertEquals(null, jedis.hget(\"foo\", \"car\"));\n    assertEquals(\"car\", jedis.hget(\"foo\", \"bar\"));\n\n    // Binary\n    jedis.hset(bfoo, bbar, bcar);\n    assertEquals(null, jedis.hget(bbar, bfoo));\n    assertEquals(null, jedis.hget(bfoo, bcar));\n    assertArrayEquals(bcar, jedis.hget(bfoo, bbar));\n  }\n\n  @Test\n  public void hsetnx() {\n    long status = jedis.hsetnx(\"foo\", \"bar\", \"car\");\n    assertEquals(1, status);\n    assertEquals(\"car\", jedis.hget(\"foo\", \"bar\"));\n\n    status = jedis.hsetnx(\"foo\", \"bar\", \"foo\");\n    assertEquals(0, status);\n    assertEquals(\"car\", jedis.hget(\"foo\", \"bar\"));\n\n    status = jedis.hsetnx(\"foo\", \"car\", \"bar\");\n    assertEquals(1, status);\n    assertEquals(\"bar\", jedis.hget(\"foo\", \"car\"));\n\n    // Binary\n    long bstatus = jedis.hsetnx(bfoo, bbar, bcar);\n    assertEquals(1, bstatus);\n    assertArrayEquals(bcar, jedis.hget(bfoo, bbar));\n\n    bstatus = jedis.hsetnx(bfoo, bbar, bfoo);\n    assertEquals(0, bstatus);\n    assertArrayEquals(bcar, jedis.hget(bfoo, bbar));\n\n    bstatus = jedis.hsetnx(bfoo, bcar, bbar);\n    assertEquals(1, bstatus);\n    assertArrayEquals(bbar, jedis.hget(bfoo, bcar));\n\n  }\n\n  @Test\n  public void hmset() {\n    Map<String, String> hash = new HashMap<String, String>();\n    hash.put(\"bar\", \"car\");\n    hash.put(\"car\", \"bar\");\n    String status = jedis.hmset(\"foo\", hash);\n    assertEquals(\"OK\", status);\n    assertEquals(\"car\", jedis.hget(\"foo\", \"bar\"));\n    assertEquals(\"bar\", jedis.hget(\"foo\", \"car\"));\n\n    // Binary\n    Map<byte[], byte[]> bhash = new HashMap<byte[], byte[]>();\n    bhash.put(bbar, bcar);\n    bhash.put(bcar, bbar);\n    String bstatus = jedis.hmset(bfoo, bhash);\n    assertEquals(\"OK\", bstatus);\n    assertArrayEquals(bcar, jedis.hget(bfoo, bbar));\n    assertArrayEquals(bbar, jedis.hget(bfoo, bcar));\n\n  }\n\n  @Test\n  public void hmget() {\n    Map<String, String> hash = new HashMap<String, String>();\n    hash.put(\"bar\", \"car\");\n    hash.put(\"car\", \"bar\");\n    jedis.hmset(\"foo\", hash);\n\n    List<String> values = jedis.hmget(\"foo\", \"bar\", \"car\", \"foo\");\n    List<String> expected = new ArrayList<String>();\n    expected.add(\"car\");\n    expected.add(\"bar\");\n    expected.add(null);\n\n    assertEquals(expected, values);\n\n    // Binary\n    Map<byte[], byte[]> bhash = new HashMap<byte[], byte[]>();\n    bhash.put(bbar, bcar);\n    bhash.put(bcar, bbar);\n    jedis.hmset(bfoo, bhash);\n\n    List<byte[]> bvalues = jedis.hmget(bfoo, bbar, bcar, bfoo);\n    List<byte[]> bexpected = new ArrayList<byte[]>();\n    bexpected.add(bcar);\n    bexpected.add(bbar);\n    bexpected.add(null);\n\n    assertEquals(bexpected, bvalues);\n  }\n\n  @Test\n  public void hincrBy() {\n    long value = jedis.hincrBy(\"foo\", \"bar\", 1);\n    assertEquals(1, value);\n    value = jedis.hincrBy(\"foo\", \"bar\", -1);\n    assertEquals(0, value);\n    value = jedis.hincrBy(\"foo\", \"bar\", -10);\n    assertEquals(-10, value);\n\n    // Binary\n    long bvalue = jedis.hincrBy(bfoo, bbar, 1);\n    assertEquals(1, bvalue);\n    bvalue = jedis.hincrBy(bfoo, bbar, -1);\n    assertEquals(0, bvalue);\n    bvalue = jedis.hincrBy(bfoo, bbar, -10);\n    assertEquals(-10, bvalue);\n\n  }\n\n  @Test\n  public void hincrByFloat() {\n    Double value = jedis.hincrByFloat(\"foo\", \"bar\", 1.5d);\n    assertEquals((Double) 1.5d, value);\n    value = jedis.hincrByFloat(\"foo\", \"bar\", -1.5d);\n    assertEquals((Double) 0d, value);\n    value = jedis.hincrByFloat(\"foo\", \"bar\", -10.7d);\n    assertEquals(Double.compare(-10.7d, value), 0);\n\n    // Binary\n    double bvalue = jedis.hincrByFloat(bfoo, bbar, 1.5d);\n    assertEquals(Double.compare(1.5d, bvalue), 0);\n    bvalue = jedis.hincrByFloat(bfoo, bbar, -1.5d);\n    assertEquals(Double.compare(0d, bvalue), 0);\n    bvalue = jedis.hincrByFloat(bfoo, bbar, -10.7d);\n    assertEquals(Double.compare(-10.7d, value), 0);\n\n  }\n\n  @Test\n  public void hexists() {\n    Map<String, String> hash = new HashMap<String, String>();\n    hash.put(\"bar\", \"car\");\n    hash.put(\"car\", \"bar\");\n    jedis.hmset(\"foo\", hash);\n\n    assertFalse(jedis.hexists(\"bar\", \"foo\"));\n    assertFalse(jedis.hexists(\"foo\", \"foo\"));\n    assertTrue(jedis.hexists(\"foo\", \"bar\"));\n\n    // Binary\n    Map<byte[], byte[]> bhash = new HashMap<byte[], byte[]>();\n    bhash.put(bbar, bcar);\n    bhash.put(bcar, bbar);\n    jedis.hmset(bfoo, bhash);\n\n    assertFalse(jedis.hexists(bbar, bfoo));\n    assertFalse(jedis.hexists(bfoo, bfoo));\n    assertTrue(jedis.hexists(bfoo, bbar));\n\n  }\n\n  @Test\n  public void hdel() {\n    Map<String, String> hash = new HashMap<String, String>();\n    hash.put(\"bar\", \"car\");\n    hash.put(\"car\", \"bar\");\n    jedis.hmset(\"foo\", hash);\n\n    assertEquals(0, jedis.hdel(\"bar\", \"foo\").intValue());\n    assertEquals(0, jedis.hdel(\"foo\", \"foo\").intValue());\n    assertEquals(1, jedis.hdel(\"foo\", \"bar\").intValue());\n    assertEquals(null, jedis.hget(\"foo\", \"bar\"));\n\n    // Binary\n    Map<byte[], byte[]> bhash = new HashMap<byte[], byte[]>();\n    bhash.put(bbar, bcar);\n    bhash.put(bcar, bbar);\n    jedis.hmset(bfoo, bhash);\n\n    assertEquals(0, jedis.hdel(bbar, bfoo).intValue());\n    assertEquals(0, jedis.hdel(bfoo, bfoo).intValue());\n    assertEquals(1, jedis.hdel(bfoo, bbar).intValue());\n    assertEquals(null, jedis.hget(bfoo, bbar));\n\n  }\n\n  @Test\n  public void hlen() {\n    Map<String, String> hash = new HashMap<String, String>();\n    hash.put(\"bar\", \"car\");\n    hash.put(\"car\", \"bar\");\n    jedis.hmset(\"foo\", hash);\n\n    assertEquals(0, jedis.hlen(\"bar\").intValue());\n    assertEquals(2, jedis.hlen(\"foo\").intValue());\n\n    // Binary\n    Map<byte[], byte[]> bhash = new HashMap<byte[], byte[]>();\n    bhash.put(bbar, bcar);\n    bhash.put(bcar, bbar);\n    jedis.hmset(bfoo, bhash);\n\n    assertEquals(0, jedis.hlen(bbar).intValue());\n    assertEquals(2, jedis.hlen(bfoo).intValue());\n\n  }\n\n  @Test\n  public void hkeys() {\n    Map<String, String> hash = new LinkedHashMap<String, String>();\n    hash.put(\"bar\", \"car\");\n    hash.put(\"car\", \"bar\");\n    jedis.hmset(\"foo\", hash);\n\n    Set<String> keys = jedis.hkeys(\"foo\");\n    Set<String> expected = new LinkedHashSet<String>();\n    expected.add(\"bar\");\n    expected.add(\"car\");\n    assertEquals(expected, keys);\n\n    // Binary\n    Map<byte[], byte[]> bhash = new LinkedHashMap<byte[], byte[]>();\n    bhash.put(bbar, bcar);\n    bhash.put(bcar, bbar);\n    jedis.hmset(bfoo, bhash);\n\n    Set<byte[]> bkeys = jedis.hkeys(bfoo);\n    Set<byte[]> bexpected = new LinkedHashSet<byte[]>();\n    bexpected.add(bbar);\n    bexpected.add(bcar);\n    assertEquals(bexpected, bkeys);\n  }\n\n  @Test\n  public void hvals() {\n    Map<String, String> hash = new LinkedHashMap<String, String>();\n    hash.put(\"bar\", \"car\");\n    hash.put(\"car\", \"bar\");\n    jedis.hmset(\"foo\", hash);\n\n    List<String> vals = jedis.hvals(\"foo\");\n    assertEquals(2, vals.size());\n    assertTrue(vals.contains(\"bar\"));\n    assertTrue(vals.contains(\"car\"));\n\n    // Binary\n    Map<byte[], byte[]> bhash = new LinkedHashMap<byte[], byte[]>();\n    bhash.put(bbar, bcar);\n    bhash.put(bcar, bbar);\n    jedis.hmset(bfoo, bhash);\n\n    List<byte[]> bvals = jedis.hvals(bfoo);\n\n    assertEquals(2, bvals.size());\n    assertTrue(arrayContains(bvals, bbar));\n    assertTrue(arrayContains(bvals, bcar));\n  }\n\n  @Test\n  public void hgetAll() {\n    Map<String, String> h = new HashMap<String, String>();\n    h.put(\"bar\", \"car\");\n    h.put(\"car\", \"bar\");\n    jedis.hmset(\"foo\", h);\n\n    Map<String, String> hash = jedis.hgetAll(\"foo\");\n    assertEquals(2, hash.size());\n    assertEquals(\"car\", hash.get(\"bar\"));\n    assertEquals(\"bar\", hash.get(\"car\"));\n\n    // Binary\n    Map<byte[], byte[]> bh = new HashMap<byte[], byte[]>();\n    bh.put(bbar, bcar);\n    bh.put(bcar, bbar);\n    jedis.hmset(bfoo, bh);\n    Map<byte[], byte[]> bhash = jedis.hgetAll(bfoo);\n\n    assertEquals(2, bhash.size());\n    assertArrayEquals(bcar, bhash.get(bbar));\n    assertArrayEquals(bbar, bhash.get(bcar));\n  }\n\n  @Test\n  public void hgetAllPipeline() {\n    Map<byte[], byte[]> bh = new HashMap<byte[], byte[]>();\n    bh.put(bbar, bcar);\n    bh.put(bcar, bbar);\n    jedis.hmset(bfoo, bh);\n    Pipeline pipeline = jedis.pipelined();\n    Response<Map<byte[], byte[]>> bhashResponse = pipeline.hgetAll(bfoo);\n    pipeline.sync();\n    Map<byte[], byte[]> bhash = bhashResponse.get();\n\n    assertEquals(2, bhash.size());\n    assertArrayEquals(bcar, bhash.get(bbar));\n    assertArrayEquals(bbar, bhash.get(bcar));\n  }\n\n  @Test\n  public void hscan() {\n    jedis.hset(\"foo\", \"b\", \"b\");\n    jedis.hset(\"foo\", \"a\", \"a\");\n\n    ScanResult<Map.Entry<String, String>> result = jedis.hscan(\"foo\", SCAN_POINTER_START);\n\n    assertEquals(SCAN_POINTER_START, result.getCursor());\n    assertFalse(result.getResult().isEmpty());\n\n    // binary\n    jedis.hset(bfoo, bbar, bcar);\n\n    ScanResult<Map.Entry<byte[], byte[]>> bResult = jedis.hscan(bfoo, SCAN_POINTER_START_BINARY);\n\n    assertArrayEquals(SCAN_POINTER_START_BINARY, bResult.getCursorAsBytes());\n    assertFalse(bResult.getResult().isEmpty());\n  }\n\n  @Test\n  public void hscanMatch() {\n    ScanParams params = new ScanParams();\n    params.match(\"a*\");\n\n    jedis.hset(\"foo\", \"b\", \"b\");\n    jedis.hset(\"foo\", \"a\", \"a\");\n    jedis.hset(\"foo\", \"aa\", \"aa\");\n    ScanResult<Map.Entry<String, String>> result = jedis.hscan(\"foo\", SCAN_POINTER_START, params);\n\n    assertEquals(SCAN_POINTER_START, result.getCursor());\n    assertFalse(result.getResult().isEmpty());\n\n    // binary\n    params = new ScanParams();\n    params.match(bbarstar);\n\n    jedis.hset(bfoo, bbar, bcar);\n    jedis.hset(bfoo, bbar1, bcar);\n    jedis.hset(bfoo, bbar2, bcar);\n    jedis.hset(bfoo, bbar3, bcar);\n\n    ScanResult<Map.Entry<byte[], byte[]>> bResult = jedis.hscan(bfoo, SCAN_POINTER_START_BINARY,\n      params);\n\n    assertArrayEquals(SCAN_POINTER_START_BINARY, bResult.getCursorAsBytes());\n    assertFalse(bResult.getResult().isEmpty());\n  }\n\n  @Test\n  public void hscanCount() {\n    ScanParams params = new ScanParams();\n    params.count(2);\n\n    for (int i = 0; i < 10; i++) {\n      jedis.hset(\"foo\", \"a\" + i, \"a\" + i);\n    }\n\n    ScanResult<Map.Entry<String, String>> result = jedis.hscan(\"foo\", SCAN_POINTER_START, params);\n\n    assertFalse(result.getResult().isEmpty());\n\n    // binary\n    params = new ScanParams();\n    params.count(2);\n\n    jedis.hset(bfoo, bbar, bcar);\n    jedis.hset(bfoo, bbar1, bcar);\n    jedis.hset(bfoo, bbar2, bcar);\n    jedis.hset(bfoo, bbar3, bcar);\n\n    ScanResult<Map.Entry<byte[], byte[]>> bResult = jedis.hscan(bfoo, SCAN_POINTER_START_BINARY,\n      params);\n\n    assertFalse(bResult.getResult().isEmpty());\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/commands/HyperLogLogCommandsTest.java",
    "content": "package redis.clients.jedis.tests.commands;\n\nimport org.junit.Test;\n\nimport redis.clients.util.SafeEncoder;\n\npublic class HyperLogLogCommandsTest extends JedisCommandTestBase {\n\n  @Test\n  public void pfadd() {\n    long status = jedis.pfadd(\"foo\", \"a\");\n    assertEquals(1, status);\n\n    status = jedis.pfadd(\"foo\", \"a\");\n    assertEquals(0, status);\n  }\n\n  @Test\n  public void pfaddBinary() {\n    byte[] bFoo = SafeEncoder.encode(\"foo\");\n    byte[] bBar = SafeEncoder.encode(\"bar\");\n    byte[] bBar2 = SafeEncoder.encode(\"bar2\");\n\n    long status = jedis.pfadd(bFoo, bBar, bBar2);\n    assertEquals(1, status);\n\n    status = jedis.pfadd(bFoo, bBar, bBar2);\n    assertEquals(0, status);\n  }\n\n  @Test\n  public void pfcount() {\n    long status = jedis.pfadd(\"hll\", \"foo\", \"bar\", \"zap\");\n    assertEquals(1, status);\n\n    status = jedis.pfadd(\"hll\", \"zap\", \"zap\", \"zap\");\n    assertEquals(0, status);\n\n    status = jedis.pfadd(\"hll\", \"foo\", \"bar\");\n    assertEquals(0, status);\n\n    status = jedis.pfcount(\"hll\");\n    assertEquals(3, status);\n  }\n\n  @Test\n  public void pfcounts() {\n    long status = jedis.pfadd(\"hll_1\", \"foo\", \"bar\", \"zap\");\n    assertEquals(1, status);\n    status = jedis.pfadd(\"hll_2\", \"foo\", \"bar\", \"zap\");\n    assertEquals(1, status);\n\n    status = jedis.pfadd(\"hll_3\", \"foo\", \"bar\", \"baz\");\n    assertEquals(1, status);\n    status = jedis.pfcount(\"hll_1\");\n    assertEquals(3, status);\n    status = jedis.pfcount(\"hll_2\");\n    assertEquals(3, status);\n    status = jedis.pfcount(\"hll_3\");\n    assertEquals(3, status);\n\n    status = jedis.pfcount(\"hll_1\", \"hll_2\");\n    assertEquals(3, status);\n\n    status = jedis.pfcount(\"hll_1\", \"hll_2\", \"hll_3\");\n    assertEquals(4, status);\n\n  }\n\n  @Test\n  public void pfcountBinary() {\n    byte[] bHll = SafeEncoder.encode(\"hll\");\n    byte[] bFoo = SafeEncoder.encode(\"foo\");\n    byte[] bBar = SafeEncoder.encode(\"bar\");\n    byte[] bZap = SafeEncoder.encode(\"zap\");\n\n    long status = jedis.pfadd(bHll, bFoo, bBar, bZap);\n    assertEquals(1, status);\n\n    status = jedis.pfadd(bHll, bZap, bZap, bZap);\n    assertEquals(0, status);\n\n    status = jedis.pfadd(bHll, bFoo, bBar);\n    assertEquals(0, status);\n\n    status = jedis.pfcount(bHll);\n    assertEquals(3, status);\n  }\n\n  @Test\n  public void pfmerge() {\n    long status = jedis.pfadd(\"hll1\", \"foo\", \"bar\", \"zap\", \"a\");\n    assertEquals(1, status);\n\n    status = jedis.pfadd(\"hll2\", \"a\", \"b\", \"c\", \"foo\");\n    assertEquals(1, status);\n\n    String mergeStatus = jedis.pfmerge(\"hll3\", \"hll1\", \"hll2\");\n    assertEquals(\"OK\", mergeStatus);\n\n    status = jedis.pfcount(\"hll3\");\n    assertEquals(6, status);\n  }\n\n  @Test\n  public void pfmergeBinary() {\n    byte[] bHll1 = SafeEncoder.encode(\"hll1\");\n    byte[] bHll2 = SafeEncoder.encode(\"hll2\");\n    byte[] bHll3 = SafeEncoder.encode(\"hll3\");\n    byte[] bFoo = SafeEncoder.encode(\"foo\");\n    byte[] bBar = SafeEncoder.encode(\"bar\");\n    byte[] bZap = SafeEncoder.encode(\"zap\");\n    byte[] bA = SafeEncoder.encode(\"a\");\n    byte[] bB = SafeEncoder.encode(\"b\");\n    byte[] bC = SafeEncoder.encode(\"c\");\n\n    long status = jedis.pfadd(bHll1, bFoo, bBar, bZap, bA);\n    assertEquals(1, status);\n\n    status = jedis.pfadd(bHll2, bA, bB, bC, bFoo);\n    assertEquals(1, status);\n\n    String mergeStatus = jedis.pfmerge(bHll3, bHll1, bHll2);\n    assertEquals(\"OK\", mergeStatus);\n\n    status = jedis.pfcount(\"hll3\");\n    assertEquals(6, status);\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/commands/JedisCommandTestBase.java",
    "content": "package redis.clients.jedis.tests.commands;\n\nimport java.util.Arrays;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Set;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.ComparisonFailure;\n\nimport redis.clients.jedis.HostAndPort;\nimport redis.clients.jedis.Jedis;\nimport redis.clients.jedis.tests.HostAndPortUtil;\nimport redis.clients.jedis.tests.JedisTestBase;\n\npublic abstract class JedisCommandTestBase extends JedisTestBase {\n  protected static HostAndPort hnp = HostAndPortUtil.getRedisServers().get(0);\n\n  protected Jedis jedis;\n\n  public JedisCommandTestBase() {\n    super();\n  }\n\n  @Before\n  public void setUp() throws Exception {\n    jedis = new Jedis(hnp.getHost(), hnp.getPort(), 500);\n    jedis.connect();\n    jedis.auth(\"foobared\");\n    jedis.configSet(\"timeout\", \"300\");\n    jedis.flushAll();\n  }\n\n  @After\n  public void tearDown() {\n    jedis.disconnect();\n  }\n\n  protected Jedis createJedis() {\n    Jedis j = new Jedis(hnp.getHost(), hnp.getPort());\n    j.connect();\n    j.auth(\"foobared\");\n    j.flushAll();\n    return j;\n  }\n\n  protected void assertEquals(List<byte[]> expected, List<byte[]> actual) {\n    assertEquals(expected.size(), actual.size());\n    for (int n = 0; n < expected.size(); n++) {\n      assertArrayEquals(expected.get(n), actual.get(n));\n    }\n  }\n\n  protected void assertEquals(Set<byte[]> expected, Set<byte[]> actual) {\n    assertEquals(expected.size(), actual.size());\n    Iterator<byte[]> e = expected.iterator();\n    while (e.hasNext()) {\n      byte[] next = e.next();\n      boolean contained = false;\n      for (byte[] element : expected) {\n        if (Arrays.equals(next, element)) {\n          contained = true;\n        }\n      }\n      if (!contained) {\n        throw new ComparisonFailure(\"element is missing\", Arrays.toString(next), actual.toString());\n      }\n    }\n  }\n\n  protected boolean arrayContains(List<byte[]> array, byte[] expected) {\n    for (byte[] a : array) {\n      try {\n        assertArrayEquals(a, expected);\n        return true;\n      } catch (AssertionError e) {\n\n      }\n    }\n    return false;\n  }\n\n  protected boolean setContains(Set<byte[]> set, byte[] expected) {\n    for (byte[] a : set) {\n      try {\n        assertArrayEquals(a, expected);\n        return true;\n      } catch (AssertionError e) {\n\n      }\n    }\n    return false;\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/commands/ListCommandsTest.java",
    "content": "package redis.clients.jedis.tests.commands;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\n\nimport org.junit.Test;\n\nimport redis.clients.jedis.Client;\nimport redis.clients.jedis.Jedis;\nimport redis.clients.jedis.exceptions.JedisDataException;\n\npublic class ListCommandsTest extends JedisCommandTestBase {\n  final byte[] bfoo = { 0x01, 0x02, 0x03, 0x04 };\n  final byte[] bbar = { 0x05, 0x06, 0x07, 0x08 };\n  final byte[] bcar = { 0x09, 0x0A, 0x0B, 0x0C };\n  final byte[] bA = { 0x0A };\n  final byte[] bB = { 0x0B };\n  final byte[] bC = { 0x0C };\n  final byte[] b1 = { 0x01 };\n  final byte[] b2 = { 0x02 };\n  final byte[] b3 = { 0x03 };\n  final byte[] bhello = { 0x04, 0x02 };\n  final byte[] bx = { 0x02, 0x04 };\n  final byte[] bdst = { 0x11, 0x12, 0x13, 0x14 };\n\n  @Test\n  public void rpush() {\n    long size = jedis.rpush(\"foo\", \"bar\");\n    assertEquals(1, size);\n    size = jedis.rpush(\"foo\", \"foo\");\n    assertEquals(2, size);\n    size = jedis.rpush(\"foo\", \"bar\", \"foo\");\n    assertEquals(4, size);\n\n    // Binary\n    long bsize = jedis.rpush(bfoo, bbar);\n    assertEquals(1, bsize);\n    bsize = jedis.rpush(bfoo, bfoo);\n    assertEquals(2, bsize);\n    bsize = jedis.rpush(bfoo, bbar, bfoo);\n    assertEquals(4, bsize);\n\n  }\n\n  @Test\n  public void lpush() {\n    long size = jedis.lpush(\"foo\", \"bar\");\n    assertEquals(1, size);\n    size = jedis.lpush(\"foo\", \"foo\");\n    assertEquals(2, size);\n    size = jedis.lpush(\"foo\", \"bar\", \"foo\");\n    assertEquals(4, size);\n\n    // Binary\n    long bsize = jedis.lpush(bfoo, bbar);\n    assertEquals(1, bsize);\n    bsize = jedis.lpush(bfoo, bfoo);\n    assertEquals(2, bsize);\n    bsize = jedis.lpush(bfoo, bbar, bfoo);\n    assertEquals(4, bsize);\n\n  }\n\n  @Test\n  public void llen() {\n    assertEquals(0, jedis.llen(\"foo\").intValue());\n    jedis.lpush(\"foo\", \"bar\");\n    jedis.lpush(\"foo\", \"car\");\n    assertEquals(2, jedis.llen(\"foo\").intValue());\n\n    // Binary\n    assertEquals(0, jedis.llen(bfoo).intValue());\n    jedis.lpush(bfoo, bbar);\n    jedis.lpush(bfoo, bcar);\n    assertEquals(2, jedis.llen(bfoo).intValue());\n\n  }\n\n  @Test\n  public void llenNotOnList() {\n    try {\n      jedis.set(\"foo\", \"bar\");\n      jedis.llen(\"foo\");\n      fail(\"JedisDataException expected\");\n    } catch (final JedisDataException e) {\n    }\n\n    // Binary\n    try {\n      jedis.set(bfoo, bbar);\n      jedis.llen(bfoo);\n      fail(\"JedisDataException expected\");\n    } catch (final JedisDataException e) {\n    }\n\n  }\n\n  @Test\n  public void lrange() {\n    jedis.rpush(\"foo\", \"a\");\n    jedis.rpush(\"foo\", \"b\");\n    jedis.rpush(\"foo\", \"c\");\n\n    List<String> expected = new ArrayList<String>();\n    expected.add(\"a\");\n    expected.add(\"b\");\n    expected.add(\"c\");\n\n    List<String> range = jedis.lrange(\"foo\", 0, 2);\n    assertEquals(expected, range);\n\n    range = jedis.lrange(\"foo\", 0, 20);\n    assertEquals(expected, range);\n\n    expected = new ArrayList<String>();\n    expected.add(\"b\");\n    expected.add(\"c\");\n\n    range = jedis.lrange(\"foo\", 1, 2);\n    assertEquals(expected, range);\n\n    expected = new ArrayList<String>();\n    range = jedis.lrange(\"foo\", 2, 1);\n    assertEquals(expected, range);\n\n    // Binary\n    jedis.rpush(bfoo, bA);\n    jedis.rpush(bfoo, bB);\n    jedis.rpush(bfoo, bC);\n\n    List<byte[]> bexpected = new ArrayList<byte[]>();\n    bexpected.add(bA);\n    bexpected.add(bB);\n    bexpected.add(bC);\n\n    List<byte[]> brange = jedis.lrange(bfoo, 0, 2);\n    assertEquals(bexpected, brange);\n\n    brange = jedis.lrange(bfoo, 0, 20);\n    assertEquals(bexpected, brange);\n\n    bexpected = new ArrayList<byte[]>();\n    bexpected.add(bB);\n    bexpected.add(bC);\n\n    brange = jedis.lrange(bfoo, 1, 2);\n    assertEquals(bexpected, brange);\n\n    bexpected = new ArrayList<byte[]>();\n    brange = jedis.lrange(bfoo, 2, 1);\n    assertEquals(bexpected, brange);\n\n  }\n\n  @Test\n  public void ltrim() {\n    jedis.lpush(\"foo\", \"1\");\n    jedis.lpush(\"foo\", \"2\");\n    jedis.lpush(\"foo\", \"3\");\n    String status = jedis.ltrim(\"foo\", 0, 1);\n\n    List<String> expected = new ArrayList<String>();\n    expected.add(\"3\");\n    expected.add(\"2\");\n\n    assertEquals(\"OK\", status);\n    assertEquals(2, jedis.llen(\"foo\").intValue());\n    assertEquals(expected, jedis.lrange(\"foo\", 0, 100));\n\n    // Binary\n    jedis.lpush(bfoo, b1);\n    jedis.lpush(bfoo, b2);\n    jedis.lpush(bfoo, b3);\n    String bstatus = jedis.ltrim(bfoo, 0, 1);\n\n    List<byte[]> bexpected = new ArrayList<byte[]>();\n    bexpected.add(b3);\n    bexpected.add(b2);\n\n    assertEquals(\"OK\", bstatus);\n    assertEquals(2, jedis.llen(bfoo).intValue());\n    assertEquals(bexpected, jedis.lrange(bfoo, 0, 100));\n\n  }\n\n  @Test\n  public void lindex() {\n    jedis.lpush(\"foo\", \"1\");\n    jedis.lpush(\"foo\", \"2\");\n    jedis.lpush(\"foo\", \"3\");\n\n    List<String> expected = new ArrayList<String>();\n    expected.add(\"3\");\n    expected.add(\"bar\");\n    expected.add(\"1\");\n\n    String status = jedis.lset(\"foo\", 1, \"bar\");\n\n    assertEquals(\"OK\", status);\n    assertEquals(expected, jedis.lrange(\"foo\", 0, 100));\n\n    // Binary\n    jedis.lpush(bfoo, b1);\n    jedis.lpush(bfoo, b2);\n    jedis.lpush(bfoo, b3);\n\n    List<byte[]> bexpected = new ArrayList<byte[]>();\n    bexpected.add(b3);\n    bexpected.add(bbar);\n    bexpected.add(b1);\n\n    String bstatus = jedis.lset(bfoo, 1, bbar);\n\n    assertEquals(\"OK\", bstatus);\n    assertEquals(bexpected, jedis.lrange(bfoo, 0, 100));\n  }\n\n  @Test\n  public void lset() {\n    jedis.lpush(\"foo\", \"1\");\n    jedis.lpush(\"foo\", \"2\");\n    jedis.lpush(\"foo\", \"3\");\n\n    assertEquals(\"3\", jedis.lindex(\"foo\", 0));\n    assertEquals(null, jedis.lindex(\"foo\", 100));\n\n    // Binary\n    jedis.lpush(bfoo, b1);\n    jedis.lpush(bfoo, b2);\n    jedis.lpush(bfoo, b3);\n\n    assertArrayEquals(b3, jedis.lindex(bfoo, 0));\n    assertEquals(null, jedis.lindex(bfoo, 100));\n\n  }\n\n  @Test\n  public void lrem() {\n    jedis.lpush(\"foo\", \"hello\");\n    jedis.lpush(\"foo\", \"hello\");\n    jedis.lpush(\"foo\", \"x\");\n    jedis.lpush(\"foo\", \"hello\");\n    jedis.lpush(\"foo\", \"c\");\n    jedis.lpush(\"foo\", \"b\");\n    jedis.lpush(\"foo\", \"a\");\n\n    long count = jedis.lrem(\"foo\", -2, \"hello\");\n\n    List<String> expected = new ArrayList<String>();\n    expected.add(\"a\");\n    expected.add(\"b\");\n    expected.add(\"c\");\n    expected.add(\"hello\");\n    expected.add(\"x\");\n\n    assertEquals(2, count);\n    assertEquals(expected, jedis.lrange(\"foo\", 0, 1000));\n    assertEquals(0, jedis.lrem(\"bar\", 100, \"foo\").intValue());\n\n    // Binary\n    jedis.lpush(bfoo, bhello);\n    jedis.lpush(bfoo, bhello);\n    jedis.lpush(bfoo, bx);\n    jedis.lpush(bfoo, bhello);\n    jedis.lpush(bfoo, bC);\n    jedis.lpush(bfoo, bB);\n    jedis.lpush(bfoo, bA);\n\n    long bcount = jedis.lrem(bfoo, -2, bhello);\n\n    List<byte[]> bexpected = new ArrayList<byte[]>();\n    bexpected.add(bA);\n    bexpected.add(bB);\n    bexpected.add(bC);\n    bexpected.add(bhello);\n    bexpected.add(bx);\n\n    assertEquals(2, bcount);\n    assertEquals(bexpected, jedis.lrange(bfoo, 0, 1000));\n    assertEquals(0, jedis.lrem(bbar, 100, bfoo).intValue());\n\n  }\n\n  @Test\n  public void lpop() {\n    jedis.rpush(\"foo\", \"a\");\n    jedis.rpush(\"foo\", \"b\");\n    jedis.rpush(\"foo\", \"c\");\n\n    String element = jedis.lpop(\"foo\");\n    assertEquals(\"a\", element);\n\n    List<String> expected = new ArrayList<String>();\n    expected.add(\"b\");\n    expected.add(\"c\");\n\n    assertEquals(expected, jedis.lrange(\"foo\", 0, 1000));\n    jedis.lpop(\"foo\");\n    jedis.lpop(\"foo\");\n\n    element = jedis.lpop(\"foo\");\n    assertEquals(null, element);\n\n    // Binary\n    jedis.rpush(bfoo, bA);\n    jedis.rpush(bfoo, bB);\n    jedis.rpush(bfoo, bC);\n\n    byte[] belement = jedis.lpop(bfoo);\n    assertArrayEquals(bA, belement);\n\n    List<byte[]> bexpected = new ArrayList<byte[]>();\n    bexpected.add(bB);\n    bexpected.add(bC);\n\n    assertEquals(bexpected, jedis.lrange(bfoo, 0, 1000));\n    jedis.lpop(bfoo);\n    jedis.lpop(bfoo);\n\n    belement = jedis.lpop(bfoo);\n    assertEquals(null, belement);\n\n  }\n\n  @Test\n  public void rpop() {\n    jedis.rpush(\"foo\", \"a\");\n    jedis.rpush(\"foo\", \"b\");\n    jedis.rpush(\"foo\", \"c\");\n\n    String element = jedis.rpop(\"foo\");\n    assertEquals(\"c\", element);\n\n    List<String> expected = new ArrayList<String>();\n    expected.add(\"a\");\n    expected.add(\"b\");\n\n    assertEquals(expected, jedis.lrange(\"foo\", 0, 1000));\n    jedis.rpop(\"foo\");\n    jedis.rpop(\"foo\");\n\n    element = jedis.rpop(\"foo\");\n    assertEquals(null, element);\n\n    // Binary\n    jedis.rpush(bfoo, bA);\n    jedis.rpush(bfoo, bB);\n    jedis.rpush(bfoo, bC);\n\n    byte[] belement = jedis.rpop(bfoo);\n    assertArrayEquals(bC, belement);\n\n    List<byte[]> bexpected = new ArrayList<byte[]>();\n    bexpected.add(bA);\n    bexpected.add(bB);\n\n    assertEquals(bexpected, jedis.lrange(bfoo, 0, 1000));\n    jedis.rpop(bfoo);\n    jedis.rpop(bfoo);\n\n    belement = jedis.rpop(bfoo);\n    assertEquals(null, belement);\n\n  }\n\n  @Test\n  public void rpoplpush() {\n    jedis.rpush(\"foo\", \"a\");\n    jedis.rpush(\"foo\", \"b\");\n    jedis.rpush(\"foo\", \"c\");\n\n    jedis.rpush(\"dst\", \"foo\");\n    jedis.rpush(\"dst\", \"bar\");\n\n    String element = jedis.rpoplpush(\"foo\", \"dst\");\n\n    assertEquals(\"c\", element);\n\n    List<String> srcExpected = new ArrayList<String>();\n    srcExpected.add(\"a\");\n    srcExpected.add(\"b\");\n\n    List<String> dstExpected = new ArrayList<String>();\n    dstExpected.add(\"c\");\n    dstExpected.add(\"foo\");\n    dstExpected.add(\"bar\");\n\n    assertEquals(srcExpected, jedis.lrange(\"foo\", 0, 1000));\n    assertEquals(dstExpected, jedis.lrange(\"dst\", 0, 1000));\n\n    // Binary\n    jedis.rpush(bfoo, bA);\n    jedis.rpush(bfoo, bB);\n    jedis.rpush(bfoo, bC);\n\n    jedis.rpush(bdst, bfoo);\n    jedis.rpush(bdst, bbar);\n\n    byte[] belement = jedis.rpoplpush(bfoo, bdst);\n\n    assertArrayEquals(bC, belement);\n\n    List<byte[]> bsrcExpected = new ArrayList<byte[]>();\n    bsrcExpected.add(bA);\n    bsrcExpected.add(bB);\n\n    List<byte[]> bdstExpected = new ArrayList<byte[]>();\n    bdstExpected.add(bC);\n    bdstExpected.add(bfoo);\n    bdstExpected.add(bbar);\n\n    assertEquals(bsrcExpected, jedis.lrange(bfoo, 0, 1000));\n    assertEquals(bdstExpected, jedis.lrange(bdst, 0, 1000));\n\n  }\n\n  @Test\n  public void blpop() throws InterruptedException {\n    List<String> result = jedis.blpop(1, \"foo\");\n    assertNull(result);\n\n    jedis.lpush(\"foo\", \"bar\");\n    result = jedis.blpop(1, \"foo\");\n\n    assertNotNull(result);\n    assertEquals(2, result.size());\n    assertEquals(\"foo\", result.get(0));\n    assertEquals(\"bar\", result.get(1));\n\n    // Binary\n    jedis.lpush(bfoo, bbar);\n    List<byte[]> bresult = jedis.blpop(1, bfoo);\n\n    assertNotNull(bresult);\n    assertEquals(2, bresult.size());\n    assertArrayEquals(bfoo, bresult.get(0));\n    assertArrayEquals(bbar, bresult.get(1));\n\n  }\n\n  @Test\n  public void brpop() throws InterruptedException {\n    List<String> result = jedis.brpop(1, \"foo\");\n    assertNull(result);\n\n    jedis.lpush(\"foo\", \"bar\");\n    result = jedis.brpop(1, \"foo\");\n    assertNotNull(result);\n    assertEquals(2, result.size());\n    assertEquals(\"foo\", result.get(0));\n    assertEquals(\"bar\", result.get(1));\n\n    // Binary\n\n    jedis.lpush(bfoo, bbar);\n    List<byte[]> bresult = jedis.brpop(1, bfoo);\n    assertNotNull(bresult);\n    assertEquals(2, bresult.size());\n    assertArrayEquals(bfoo, bresult.get(0));\n    assertArrayEquals(bbar, bresult.get(1));\n\n  }\n\n  @Test\n  public void lpushx() {\n    long status = jedis.lpushx(\"foo\", \"bar\");\n    assertEquals(0, status);\n\n    jedis.lpush(\"foo\", \"a\");\n    status = jedis.lpushx(\"foo\", \"b\");\n    assertEquals(2, status);\n\n    // Binary\n    long bstatus = jedis.lpushx(bfoo, bbar);\n    assertEquals(0, bstatus);\n\n    jedis.lpush(bfoo, bA);\n    bstatus = jedis.lpushx(bfoo, bB);\n    assertEquals(2, bstatus);\n\n  }\n\n  @Test\n  public void rpushx() {\n    long status = jedis.rpushx(\"foo\", \"bar\");\n    assertEquals(0, status);\n\n    jedis.lpush(\"foo\", \"a\");\n    status = jedis.rpushx(\"foo\", \"b\");\n    assertEquals(2, status);\n\n    // Binary\n    long bstatus = jedis.rpushx(bfoo, bbar);\n    assertEquals(0, bstatus);\n\n    jedis.lpush(bfoo, bA);\n    bstatus = jedis.rpushx(bfoo, bB);\n    assertEquals(2, bstatus);\n  }\n\n  @Test\n  public void linsert() {\n    long status = jedis.linsert(\"foo\", Client.LIST_POSITION.BEFORE, \"bar\", \"car\");\n    assertEquals(0, status);\n\n    jedis.lpush(\"foo\", \"a\");\n    status = jedis.linsert(\"foo\", Client.LIST_POSITION.AFTER, \"a\", \"b\");\n    assertEquals(2, status);\n\n    List<String> actual = jedis.lrange(\"foo\", 0, 100);\n    List<String> expected = new ArrayList<String>();\n    expected.add(\"a\");\n    expected.add(\"b\");\n\n    assertEquals(expected, actual);\n\n    status = jedis.linsert(\"foo\", Client.LIST_POSITION.BEFORE, \"bar\", \"car\");\n    assertEquals(-1, status);\n\n    // Binary\n    long bstatus = jedis.linsert(bfoo, Client.LIST_POSITION.BEFORE, bbar, bcar);\n    assertEquals(0, bstatus);\n\n    jedis.lpush(bfoo, bA);\n    bstatus = jedis.linsert(bfoo, Client.LIST_POSITION.AFTER, bA, bB);\n    assertEquals(2, bstatus);\n\n    List<byte[]> bactual = jedis.lrange(bfoo, 0, 100);\n    List<byte[]> bexpected = new ArrayList<byte[]>();\n    bexpected.add(bA);\n    bexpected.add(bB);\n\n    assertEquals(bexpected, bactual);\n\n    bstatus = jedis.linsert(bfoo, Client.LIST_POSITION.BEFORE, bbar, bcar);\n    assertEquals(-1, bstatus);\n\n  }\n\n  @Test\n  public void brpoplpush() {\n    (new Thread(new Runnable() {\n      public void run() {\n        try {\n          Thread.sleep(100);\n          Jedis j = createJedis();\n          j.lpush(\"foo\", \"a\");\n        } catch (InterruptedException e) {\n          e.printStackTrace();\n        }\n      }\n    })).start();\n\n    String element = jedis.brpoplpush(\"foo\", \"bar\", 0);\n\n    assertEquals(\"a\", element);\n    assertEquals(1, jedis.llen(\"bar\").longValue());\n    assertEquals(\"a\", jedis.lrange(\"bar\", 0, -1).get(0));\n\n    (new Thread(new Runnable() {\n      public void run() {\n        try {\n          Thread.sleep(100);\n          Jedis j = createJedis();\n          j.lpush(\"foo\", \"a\");\n        } catch (InterruptedException e) {\n          e.printStackTrace();\n        }\n      }\n    })).start();\n\n    byte[] brpoplpush = jedis.brpoplpush(\"foo\".getBytes(), \"bar\".getBytes(), 0);\n\n    assertTrue(Arrays.equals(\"a\".getBytes(), brpoplpush));\n    assertEquals(1, jedis.llen(\"bar\").longValue());\n    assertEquals(\"a\", jedis.lrange(\"bar\", 0, -1).get(0));\n\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/commands/ObjectCommandsTest.java",
    "content": "package redis.clients.jedis.tests.commands;\n\nimport org.junit.Test;\n\nimport redis.clients.util.SafeEncoder;\n\npublic class ObjectCommandsTest extends JedisCommandTestBase {\n\n  private String key = \"mylist\";\n  private byte[] binaryKey = SafeEncoder.encode(key);\n\n  @Test\n  public void objectRefcount() {\n    jedis.lpush(key, \"hello world\");\n    Long refcount = jedis.objectRefcount(key);\n    assertEquals(new Long(1), refcount);\n\n    // Binary\n    refcount = jedis.objectRefcount(binaryKey);\n    assertEquals(new Long(1), refcount);\n\n  }\n\n  @Test\n  public void objectEncoding() {\n    jedis.lpush(key, \"hello world\");\n    String encoding = jedis.objectEncoding(key);\n    assertEquals(\"quicklist\", encoding);\n\n    // Binary\n    encoding = SafeEncoder.encode(jedis.objectEncoding(binaryKey));\n    assertEquals(\"quicklist\", encoding);\n  }\n\n  @Test\n  public void objectIdletime() throws InterruptedException {\n    jedis.lpush(key, \"hello world\");\n\n    Long time = jedis.objectIdletime(key);\n    assertEquals(new Long(0), time);\n\n    // Binary\n    time = jedis.objectIdletime(binaryKey);\n    assertEquals(new Long(0), time);\n  }\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/commands/PublishSubscribeCommandsTest.java",
    "content": "package redis.clients.jedis.tests.commands;\n\nimport java.io.IOException;\nimport java.net.UnknownHostException;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\nimport org.junit.Test;\n\nimport redis.clients.jedis.*;\nimport redis.clients.jedis.exceptions.JedisConnectionException;\nimport redis.clients.util.SafeEncoder;\n\npublic class PublishSubscribeCommandsTest extends JedisCommandTestBase {\n  private void publishOne(final String channel, final String message) {\n    Thread t = new Thread(new Runnable() {\n      public void run() {\n        try {\n          Jedis j = createJedis();\n          j.publish(channel, message);\n          j.disconnect();\n        } catch (Exception ex) {\n        }\n      }\n    });\n    t.start();\n  }\n\n  @Test\n  public void subscribe() throws InterruptedException {\n    jedis.subscribe(new JedisPubSub() {\n      public void onMessage(String channel, String message) {\n        assertEquals(\"foo\", channel);\n        assertEquals(\"exit\", message);\n        unsubscribe();\n      }\n\n      public void onSubscribe(String channel, int subscribedChannels) {\n        assertEquals(\"foo\", channel);\n        assertEquals(1, subscribedChannels);\n\n        // now that I'm subscribed... publish\n        publishOne(\"foo\", \"exit\");\n      }\n\n      public void onUnsubscribe(String channel, int subscribedChannels) {\n        assertEquals(\"foo\", channel);\n        assertEquals(0, subscribedChannels);\n      }\n    }, \"foo\");\n  }\n\n  @Test\n  public void pubSubChannels() {\n    final List<String> expectedActiveChannels = Arrays\n        .asList(\"testchan1\", \"testchan2\", \"testchan3\");\n    jedis.subscribe(new JedisPubSub() {\n      private int count = 0;\n\n      @Override\n      public void onSubscribe(String channel, int subscribedChannels) {\n        count++;\n        // All channels are subscribed\n        if (count == 3) {\n          Jedis otherJedis = createJedis();\n          List<String> activeChannels = otherJedis.pubsubChannels(\"test*\");\n          assertTrue(expectedActiveChannels.containsAll(activeChannels));\n          unsubscribe();\n        }\n      }\n    }, \"testchan1\", \"testchan2\", \"testchan3\");\n  }\n\n  @Test\n  public void pubSubNumPat() {\n    jedis.psubscribe(new JedisPubSub() {\n      private int count = 0;\n\n      @Override\n      public void onPSubscribe(String pattern, int subscribedChannels) {\n        count++;\n        if (count == 3) {\n          Jedis otherJedis = createJedis();\n          Long numPatterns = otherJedis.pubsubNumPat();\n          assertEquals(new Long(2l), numPatterns);\n          punsubscribe();\n        }\n      }\n\n    }, \"test*\", \"test*\", \"chan*\");\n  }\n\n  @Test\n  public void pubSubNumSub() {\n    final Map<String, String> expectedNumSub = new HashMap<String, String>();\n    expectedNumSub.put(\"testchannel2\", \"1\");\n    expectedNumSub.put(\"testchannel1\", \"1\");\n    jedis.subscribe(new JedisPubSub() {\n      private int count = 0;\n\n      @Override\n      public void onSubscribe(String channel, int subscribedChannels) {\n        count++;\n        if (count == 2) {\n          Jedis otherJedis = createJedis();\n          Map<String, String> numSub = otherJedis.pubsubNumSub(\"testchannel1\", \"testchannel2\");\n          assertEquals(expectedNumSub, numSub);\n          unsubscribe();\n        }\n      }\n    }, \"testchannel1\", \"testchannel2\");\n  }\n\n  @Test\n  public void subscribeMany() throws UnknownHostException, IOException, InterruptedException {\n    jedis.subscribe(new JedisPubSub() {\n      public void onMessage(String channel, String message) {\n        unsubscribe(channel);\n      }\n\n      public void onSubscribe(String channel, int subscribedChannels) {\n        publishOne(channel, \"exit\");\n      }\n\n    }, \"foo\", \"bar\");\n  }\n\n  @Test\n  public void psubscribe() throws UnknownHostException, IOException, InterruptedException {\n    jedis.psubscribe(new JedisPubSub() {\n      public void onPSubscribe(String pattern, int subscribedChannels) {\n        assertEquals(\"foo.*\", pattern);\n        assertEquals(1, subscribedChannels);\n        publishOne(\"foo.bar\", \"exit\");\n\n      }\n\n      public void onPUnsubscribe(String pattern, int subscribedChannels) {\n        assertEquals(\"foo.*\", pattern);\n        assertEquals(0, subscribedChannels);\n      }\n\n      public void onPMessage(String pattern, String channel, String message) {\n        assertEquals(\"foo.*\", pattern);\n        assertEquals(\"foo.bar\", channel);\n        assertEquals(\"exit\", message);\n        punsubscribe();\n      }\n    }, \"foo.*\");\n  }\n\n  @Test\n  public void psubscribeMany() throws UnknownHostException, IOException, InterruptedException {\n    jedis.psubscribe(new JedisPubSub() {\n      public void onPSubscribe(String pattern, int subscribedChannels) {\n        publishOne(pattern.replace(\"*\", \"123\"), \"exit\");\n      }\n\n      public void onPMessage(String pattern, String channel, String message) {\n        punsubscribe(pattern);\n      }\n    }, \"foo.*\", \"bar.*\");\n  }\n\n  @Test\n  public void subscribeLazily() throws UnknownHostException, IOException, InterruptedException {\n    final JedisPubSub pubsub = new JedisPubSub() {\n      public void onMessage(String channel, String message) {\n        unsubscribe(channel);\n      }\n\n      public void onSubscribe(String channel, int subscribedChannels) {\n        publishOne(channel, \"exit\");\n        if (!channel.equals(\"bar\")) {\n          this.subscribe(\"bar\");\n          this.psubscribe(\"bar.*\");\n        }\n      }\n\n      public void onPSubscribe(String pattern, int subscribedChannels) {\n        publishOne(pattern.replace(\"*\", \"123\"), \"exit\");\n      }\n\n      public void onPMessage(String pattern, String channel, String message) {\n        punsubscribe(pattern);\n      }\n    };\n\n    jedis.subscribe(pubsub, \"foo\");\n  }\n\n  @Test\n  public void binarySubscribe() throws UnknownHostException, IOException, InterruptedException {\n    jedis.subscribe(new BinaryJedisPubSub() {\n      public void onMessage(byte[] channel, byte[] message) {\n        assertTrue(Arrays.equals(SafeEncoder.encode(\"foo\"), channel));\n        assertTrue(Arrays.equals(SafeEncoder.encode(\"exit\"), message));\n        unsubscribe();\n      }\n\n      public void onSubscribe(byte[] channel, int subscribedChannels) {\n        assertTrue(Arrays.equals(SafeEncoder.encode(\"foo\"), channel));\n        assertEquals(1, subscribedChannels);\n        publishOne(SafeEncoder.encode(channel), \"exit\");\n      }\n\n      public void onUnsubscribe(byte[] channel, int subscribedChannels) {\n        assertTrue(Arrays.equals(SafeEncoder.encode(\"foo\"), channel));\n        assertEquals(0, subscribedChannels);\n      }\n    }, SafeEncoder.encode(\"foo\"));\n  }\n\n  @Test\n  public void binarySubscribeMany() throws UnknownHostException, IOException, InterruptedException {\n    jedis.subscribe(new BinaryJedisPubSub() {\n      public void onMessage(byte[] channel, byte[] message) {\n        unsubscribe(channel);\n      }\n\n      public void onSubscribe(byte[] channel, int subscribedChannels) {\n        publishOne(SafeEncoder.encode(channel), \"exit\");\n      }\n    }, SafeEncoder.encode(\"foo\"), SafeEncoder.encode(\"bar\"));\n  }\n\n  @Test\n  public void binaryPsubscribe() throws UnknownHostException, IOException, InterruptedException {\n    jedis.psubscribe(new BinaryJedisPubSub() {\n      public void onPSubscribe(byte[] pattern, int subscribedChannels) {\n        assertTrue(Arrays.equals(SafeEncoder.encode(\"foo.*\"), pattern));\n        assertEquals(1, subscribedChannels);\n        publishOne(SafeEncoder.encode(pattern).replace(\"*\", \"bar\"), \"exit\");\n      }\n\n      public void onPUnsubscribe(byte[] pattern, int subscribedChannels) {\n        assertTrue(Arrays.equals(SafeEncoder.encode(\"foo.*\"), pattern));\n        assertEquals(0, subscribedChannels);\n      }\n\n      public void onPMessage(byte[] pattern, byte[] channel, byte[] message) {\n        assertTrue(Arrays.equals(SafeEncoder.encode(\"foo.*\"), pattern));\n        assertTrue(Arrays.equals(SafeEncoder.encode(\"foo.bar\"), channel));\n        assertTrue(Arrays.equals(SafeEncoder.encode(\"exit\"), message));\n        punsubscribe();\n      }\n    }, SafeEncoder.encode(\"foo.*\"));\n  }\n\n  @Test\n  public void binaryPsubscribeMany() throws UnknownHostException, IOException, InterruptedException {\n    jedis.psubscribe(new BinaryJedisPubSub() {\n      public void onPSubscribe(byte[] pattern, int subscribedChannels) {\n        publishOne(SafeEncoder.encode(pattern).replace(\"*\", \"123\"), \"exit\");\n      }\n\n      public void onPMessage(byte[] pattern, byte[] channel, byte[] message) {\n        punsubscribe(pattern);\n      }\n    }, SafeEncoder.encode(\"foo.*\"), SafeEncoder.encode(\"bar.*\"));\n  }\n\n  @Test\n  public void binarySubscribeLazily() throws UnknownHostException, IOException,\n      InterruptedException {\n    final BinaryJedisPubSub pubsub = new BinaryJedisPubSub() {\n      public void onMessage(byte[] channel, byte[] message) {\n        unsubscribe(channel);\n      }\n\n      public void onSubscribe(byte[] channel, int subscribedChannels) {\n        publishOne(SafeEncoder.encode(channel), \"exit\");\n\n        if (!SafeEncoder.encode(channel).equals(\"bar\")) {\n          this.subscribe(SafeEncoder.encode(\"bar\"));\n          this.psubscribe(SafeEncoder.encode(\"bar.*\"));\n        }\n      }\n\n      public void onPSubscribe(byte[] pattern, int subscribedChannels) {\n        publishOne(SafeEncoder.encode(pattern).replace(\"*\", \"123\"), \"exit\");\n      }\n\n      public void onPMessage(byte[] pattern, byte[] channel, byte[] message) {\n        punsubscribe(pattern);\n      }\n    };\n\n    jedis.subscribe(pubsub, SafeEncoder.encode(\"foo\"));\n  }\n\n  @Test(expected = JedisConnectionException.class)\n  public void unsubscribeWhenNotSusbscribed() throws InterruptedException {\n    JedisPubSub pubsub = new JedisPubSub() {\n    };\n    pubsub.unsubscribe();\n  }\n\n  @Test(expected = JedisConnectionException.class)\n  public void handleClientOutputBufferLimitForSubscribeTooSlow() throws InterruptedException {\n    final Jedis j = createJedis();\n    final AtomicBoolean exit = new AtomicBoolean(false);\n\n    final Thread t = new Thread(new Runnable() {\n      public void run() {\n        try {\n\n          // we already set jedis1 config to\n          // client-output-buffer-limit pubsub 256k 128k 5\n          // it means if subscriber delayed to receive over 256k or\n          // 128k continuously 5 sec,\n          // redis disconnects subscriber\n\n          // we publish over 100M data for making situation for exceed\n          // client-output-buffer-limit\n          String veryLargeString = makeLargeString(10485760);\n\n          // 10M * 10 = 100M\n          for (int i = 0; i < 10 && !exit.get(); i++) {\n            j.publish(\"foo\", veryLargeString);\n          }\n\n          j.disconnect();\n        } catch (Exception ex) {\n        }\n      }\n    });\n    t.start();\n    try {\n      jedis.subscribe(new JedisPubSub() {\n        public void onMessage(String channel, String message) {\n          try {\n            // wait 0.5 secs to slow down subscribe and\n            // client-output-buffer exceed\n            // System.out.println(\"channel - \" + channel +\n            // \" / message - \" + message);\n            Thread.sleep(100);\n          } catch (Exception e) {\n            try {\n              t.join();\n            } catch (InterruptedException e1) {\n            }\n\n            fail(e.getMessage());\n          }\n        }\n      }, \"foo\");\n    } finally {\n      // exit the publisher thread. if exception is thrown, thread might\n      // still keep publishing things.\n      exit.set(true);\n      if (t.isAlive()) {\n        t.join();\n      }\n    }\n  }\n\n  private String makeLargeString(int size) {\n    StringBuffer sb = new StringBuffer();\n    for (int i = 0; i < size; i++)\n      sb.append((char) ('a' + i % 26));\n\n    return sb.toString();\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/commands/ScriptingCommandsTest.java",
    "content": "package redis.clients.jedis.tests.commands;\n\nimport static org.hamcrest.CoreMatchers.equalTo;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.hamcrest.CoreMatchers;\nimport org.hamcrest.Matcher;\nimport org.junit.Test;\n\nimport redis.clients.jedis.BinaryJedis;\nimport redis.clients.jedis.Jedis;\nimport redis.clients.jedis.exceptions.JedisConnectionException;\nimport redis.clients.jedis.exceptions.JedisDataException;\nimport redis.clients.jedis.tests.utils.ClientKillerUtil;\nimport redis.clients.util.SafeEncoder;\n\npublic class ScriptingCommandsTest extends JedisCommandTestBase {\n\n  @SuppressWarnings(\"unchecked\")\n  @Test\n  public void evalMultiBulk() {\n    String script = \"return {KEYS[1],KEYS[2],ARGV[1],ARGV[2],ARGV[3]}\";\n    List<String> keys = new ArrayList<String>();\n    keys.add(\"key1\");\n    keys.add(\"key2\");\n\n    List<String> args = new ArrayList<String>();\n    args.add(\"first\");\n    args.add(\"second\");\n    args.add(\"third\");\n\n    List<String> response = (List<String>) jedis.eval(script, keys, args);\n\n    assertEquals(5, response.size());\n    assertEquals(\"key1\", response.get(0));\n    assertEquals(\"key2\", response.get(1));\n    assertEquals(\"first\", response.get(2));\n    assertEquals(\"second\", response.get(3));\n    assertEquals(\"third\", response.get(4));\n  }\n\n  @SuppressWarnings(\"unchecked\")\n  @Test\n  public void evalMultiBulkWithBinaryJedis() {\n    String script = \"return {KEYS[1],KEYS[2],ARGV[1],ARGV[2],ARGV[3]}\";\n    List<byte[]> keys = new ArrayList<byte[]>();\n    keys.add(\"key1\".getBytes());\n    keys.add(\"key2\".getBytes());\n\n    List<byte[]> args = new ArrayList<byte[]>();\n    args.add(\"first\".getBytes());\n    args.add(\"second\".getBytes());\n    args.add(\"third\".getBytes());\n\n    BinaryJedis binaryJedis = new BinaryJedis(hnp.getHost(), hnp.getPort(), 500);\n    binaryJedis.connect();\n    binaryJedis.auth(\"foobared\");\n\n    List<byte[]> responses = (List<byte[]>) binaryJedis.eval(script.getBytes(), keys, args);\n    assertEquals(5, responses.size());\n    assertEquals(\"key1\", new String(responses.get(0)));\n    assertEquals(\"key2\", new String(responses.get(1)));\n    assertEquals(\"first\", new String(responses.get(2)));\n    assertEquals(\"second\", new String(responses.get(3)));\n    assertEquals(\"third\", new String(responses.get(4)));\n\n    binaryJedis.close();\n  }\n\n  @Test\n  public void evalBulk() {\n    String script = \"return KEYS[1]\";\n    List<String> keys = new ArrayList<String>();\n    keys.add(\"key1\");\n\n    List<String> args = new ArrayList<String>();\n    args.add(\"first\");\n\n    String response = (String) jedis.eval(script, keys, args);\n\n    assertEquals(\"key1\", response);\n  }\n\n  @Test\n  public void evalInt() {\n    String script = \"return 2\";\n    List<String> keys = new ArrayList<String>();\n    keys.add(\"key1\");\n\n    Long response = (Long) jedis.eval(script, keys, new ArrayList<String>());\n\n    assertEquals(new Long(2), response);\n  }\n\n  @Test\n  public void evalNestedLists() {\n    String script = \"return { {KEYS[1]} , {2} }\";\n    List<?> results = (List<?>) jedis.eval(script, 1, \"key1\");\n\n    assertThat((List<String>) results.get(0), listWithItem(\"key1\"));\n    assertThat((List<Long>) results.get(1), listWithItem(2L));\n  }\n\n  @Test\n  public void evalNoArgs() {\n    String script = \"return KEYS[1]\";\n    List<String> keys = new ArrayList<String>();\n    keys.add(\"key1\");\n    String response = (String) jedis.eval(script, keys, new ArrayList<String>());\n\n    assertEquals(\"key1\", response);\n  }\n\n  @Test\n  public void evalsha() {\n    jedis.set(\"foo\", \"bar\");\n    jedis.eval(\"return redis.call('get','foo')\");\n    String result = (String) jedis.evalsha(\"6b1bf486c81ceb7edf3c093f4c48582e38c0e791\");\n\n    assertEquals(\"bar\", result);\n  }\n\n  @Test(expected = JedisDataException.class)\n  public void evalshaShaNotFound() {\n    jedis.evalsha(\"ffffffffffffffffffffffffffffffffffffffff\");\n  }\n\n  @Test\n  public void scriptFlush() {\n    jedis.set(\"foo\", \"bar\");\n    jedis.eval(\"return redis.call('get','foo')\");\n    jedis.scriptFlush();\n    assertFalse(jedis.scriptExists(\"6b1bf486c81ceb7edf3c093f4c48582e38c0e791\"));\n  }\n\n  @Test\n  public void scriptExists() {\n    jedis.scriptLoad(\"return redis.call('get','foo')\");\n    List<Boolean> exists = jedis.scriptExists(\"ffffffffffffffffffffffffffffffffffffffff\",\n      \"6b1bf486c81ceb7edf3c093f4c48582e38c0e791\");\n    assertFalse(exists.get(0));\n    assertTrue(exists.get(1));\n  }\n\n  @Test\n  public void scriptExistsBinary() {\n    jedis.scriptLoad(SafeEncoder.encode(\"return redis.call('get','foo')\"));\n    List<Long> exists = jedis.scriptExists(\n      SafeEncoder.encode(\"ffffffffffffffffffffffffffffffffffffffff\"),\n      SafeEncoder.encode(\"6b1bf486c81ceb7edf3c093f4c48582e38c0e791\"));\n    assertEquals(new Long(0), exists.get(0));\n    assertEquals(new Long(1), exists.get(1));\n  }\n\n  @Test\n  public void scriptLoad() {\n    jedis.scriptLoad(\"return redis.call('get','foo')\");\n    assertTrue(jedis.scriptExists(\"6b1bf486c81ceb7edf3c093f4c48582e38c0e791\"));\n  }\n\n  @Test\n  public void scriptLoadBinary() {\n    jedis.scriptLoad(SafeEncoder.encode(\"return redis.call('get','foo')\"));\n    Long exists = jedis\n        .scriptExists(SafeEncoder.encode(\"6b1bf486c81ceb7edf3c093f4c48582e38c0e791\"));\n    assertEquals((Long) 1L, exists);\n  }\n\n  @Test\n  public void scriptKill() {\n    try {\n      jedis.scriptKill();\n    } catch (JedisDataException e) {\n      assertTrue(e.getMessage().contains(\"No scripts in execution right now.\"));\n    }\n  }\n\n  @Test\n  public void scriptEvalReturnNullValues() {\n    jedis.del(\"key1\");\n    jedis.del(\"key2\");\n\n    String script = \"return {redis.call('hget',KEYS[1],ARGV[1]),redis.call('hget',KEYS[2],ARGV[2])}\";\n    List<String> results = (List<String>) jedis.eval(script, 2, \"key1\", \"key2\", \"1\", \"2\");\n    assertEquals(2, results.size());\n    assertNull(results.get(0));\n    assertNull(results.get(1));\n  }\n\n  @Test\n  public void scriptEvalShaReturnNullValues() {\n    jedis.del(\"key1\");\n    jedis.del(\"key2\");\n\n    String script = \"return {redis.call('hget',KEYS[1],ARGV[1]),redis.call('hget',KEYS[2],ARGV[2])}\";\n    String sha = jedis.scriptLoad(script);\n    List<String> results = (List<String>) jedis.evalsha(sha, 2, \"key1\", \"key2\", \"1\", \"2\");\n    assertEquals(2, results.size());\n    assertNull(results.get(0));\n    assertNull(results.get(1));\n  }\n\n  @Test\n  public void scriptExistsWithBrokenConnection() {\n    Jedis deadClient = new Jedis(jedis.getClient().getHost(), jedis.getClient().getPort());\n    deadClient.auth(\"foobared\");\n\n    deadClient.clientSetname(\"DEAD\");\n\n    ClientKillerUtil.killClient(deadClient, \"DEAD\");\n\n    // sure, script doesn't exist, but it's just for checking connection\n    try {\n      deadClient.scriptExists(\"abcdefg\");\n    } catch (JedisConnectionException e) {\n      // ignore it\n    }\n\n    assertEquals(true, deadClient.getClient().isBroken());\n\n    deadClient.close();\n  }\n\n  private <T> Matcher<Iterable<? super T>> listWithItem(T expected) {\n    return CoreMatchers.<T> hasItem(equalTo(expected));\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/commands/SetCommandsTest.java",
    "content": "package redis.clients.jedis.tests.commands;\n\nimport static redis.clients.jedis.ScanParams.SCAN_POINTER_START;\nimport static redis.clients.jedis.ScanParams.SCAN_POINTER_START_BINARY;\n\nimport java.util.Arrays;\nimport java.util.HashSet;\nimport java.util.Set;\n\nimport org.junit.Test;\n\nimport redis.clients.jedis.ScanParams;\nimport redis.clients.jedis.ScanResult;\n\npublic class SetCommandsTest extends JedisCommandTestBase {\n  final byte[] bfoo = { 0x01, 0x02, 0x03, 0x04 };\n  final byte[] bbar = { 0x05, 0x06, 0x07, 0x08 };\n  final byte[] bcar = { 0x09, 0x0A, 0x0B, 0x0C };\n  final byte[] ba = { 0x0A };\n  final byte[] bb = { 0x0B };\n  final byte[] bc = { 0x0C };\n  final byte[] bd = { 0x0D };\n  final byte[] bx = { 0x42 };\n\n  final byte[] bbar1 = { 0x05, 0x06, 0x07, 0x08, 0x0A };\n  final byte[] bbar2 = { 0x05, 0x06, 0x07, 0x08, 0x0B };\n  final byte[] bbar3 = { 0x05, 0x06, 0x07, 0x08, 0x0C };\n  final byte[] bbarstar = { 0x05, 0x06, 0x07, 0x08, '*' };\n\n  @Test\n  public void sadd() {\n    long status = jedis.sadd(\"foo\", \"a\");\n    assertEquals(1, status);\n\n    status = jedis.sadd(\"foo\", \"a\");\n    assertEquals(0, status);\n\n    long bstatus = jedis.sadd(bfoo, ba);\n    assertEquals(1, bstatus);\n\n    bstatus = jedis.sadd(bfoo, ba);\n    assertEquals(0, bstatus);\n\n  }\n\n  @Test\n  public void smembers() {\n    jedis.sadd(\"foo\", \"a\");\n    jedis.sadd(\"foo\", \"b\");\n\n    Set<String> expected = new HashSet<String>();\n    expected.add(\"a\");\n    expected.add(\"b\");\n\n    Set<String> members = jedis.smembers(\"foo\");\n\n    assertEquals(expected, members);\n\n    // Binary\n    jedis.sadd(bfoo, ba);\n    jedis.sadd(bfoo, bb);\n\n    Set<byte[]> bexpected = new HashSet<byte[]>();\n    bexpected.add(bb);\n    bexpected.add(ba);\n\n    Set<byte[]> bmembers = jedis.smembers(bfoo);\n\n    assertEquals(bexpected, bmembers);\n  }\n\n  @Test\n  public void srem() {\n    jedis.sadd(\"foo\", \"a\");\n    jedis.sadd(\"foo\", \"b\");\n\n    long status = jedis.srem(\"foo\", \"a\");\n\n    Set<String> expected = new HashSet<String>();\n    expected.add(\"b\");\n\n    assertEquals(1, status);\n    assertEquals(expected, jedis.smembers(\"foo\"));\n\n    status = jedis.srem(\"foo\", \"bar\");\n\n    assertEquals(0, status);\n\n    // Binary\n\n    jedis.sadd(bfoo, ba);\n    jedis.sadd(bfoo, bb);\n\n    long bstatus = jedis.srem(bfoo, ba);\n\n    Set<byte[]> bexpected = new HashSet<byte[]>();\n    bexpected.add(bb);\n\n    assertEquals(1, bstatus);\n    assertEquals(bexpected, jedis.smembers(bfoo));\n\n    bstatus = jedis.srem(bfoo, bbar);\n\n    assertEquals(0, bstatus);\n\n  }\n\n  @Test\n  public void spop() {\n    jedis.sadd(\"foo\", \"a\");\n    jedis.sadd(\"foo\", \"b\");\n\n    String member = jedis.spop(\"foo\");\n\n    assertTrue(\"a\".equals(member) || \"b\".equals(member));\n    assertEquals(1, jedis.smembers(\"foo\").size());\n\n    member = jedis.spop(\"bar\");\n    assertNull(member);\n\n    // Binary\n    jedis.sadd(bfoo, ba);\n    jedis.sadd(bfoo, bb);\n\n    byte[] bmember = jedis.spop(bfoo);\n\n    assertTrue(Arrays.equals(ba, bmember) || Arrays.equals(bb, bmember));\n    assertEquals(1, jedis.smembers(bfoo).size());\n\n    bmember = jedis.spop(bbar);\n    assertNull(bmember);\n\n  }\n\n  @Test\n  public void spopWithCount() {\n    jedis.sadd(\"foo\", \"a\");\n    jedis.sadd(\"foo\", \"b\");\n\n    Set<String> expected = new HashSet<String>();\n    expected.add(\"a\");\n    expected.add(\"b\");\n\n    Set<String> members = jedis.spop(\"foo\", 2);\n\n    assertEquals(2, members.size());\n    assertEquals(expected, members);\n\n    members = jedis.spop(\"foo\", 2);\n    assertTrue(members.isEmpty());\n\n    // Binary\n    jedis.sadd(bfoo, ba);\n    jedis.sadd(bfoo, bb);\n\n    Set<byte[]> bexpected = new HashSet<byte[]>();\n    bexpected.add(bb);\n    bexpected.add(ba);\n\n    Set<byte[]> bmembers = jedis.spop(bfoo, 2);\n\n    assertEquals(2, bmembers.size());\n    assertEquals(bexpected, bmembers);\n\n    bmembers = jedis.spop(bfoo, 2);\n    assertTrue(bmembers.isEmpty());\n  }\n\n  @Test\n  public void smove() {\n    jedis.sadd(\"foo\", \"a\");\n    jedis.sadd(\"foo\", \"b\");\n\n    jedis.sadd(\"bar\", \"c\");\n\n    long status = jedis.smove(\"foo\", \"bar\", \"a\");\n\n    Set<String> expectedSrc = new HashSet<String>();\n    expectedSrc.add(\"b\");\n\n    Set<String> expectedDst = new HashSet<String>();\n    expectedDst.add(\"c\");\n    expectedDst.add(\"a\");\n\n    assertEquals(status, 1);\n    assertEquals(expectedSrc, jedis.smembers(\"foo\"));\n    assertEquals(expectedDst, jedis.smembers(\"bar\"));\n\n    status = jedis.smove(\"foo\", \"bar\", \"a\");\n\n    assertEquals(status, 0);\n\n    // Binary\n    jedis.sadd(bfoo, ba);\n    jedis.sadd(bfoo, bb);\n\n    jedis.sadd(bbar, bc);\n\n    long bstatus = jedis.smove(bfoo, bbar, ba);\n\n    Set<byte[]> bexpectedSrc = new HashSet<byte[]>();\n    bexpectedSrc.add(bb);\n\n    Set<byte[]> bexpectedDst = new HashSet<byte[]>();\n    bexpectedDst.add(bc);\n    bexpectedDst.add(ba);\n\n    assertEquals(bstatus, 1);\n    assertEquals(bexpectedSrc, jedis.smembers(bfoo));\n    assertEquals(bexpectedDst, jedis.smembers(bbar));\n\n    bstatus = jedis.smove(bfoo, bbar, ba);\n    assertEquals(bstatus, 0);\n\n  }\n\n  @Test\n  public void scard() {\n    jedis.sadd(\"foo\", \"a\");\n    jedis.sadd(\"foo\", \"b\");\n\n    long card = jedis.scard(\"foo\");\n\n    assertEquals(2, card);\n\n    card = jedis.scard(\"bar\");\n    assertEquals(0, card);\n\n    // Binary\n    jedis.sadd(bfoo, ba);\n    jedis.sadd(bfoo, bb);\n\n    long bcard = jedis.scard(bfoo);\n\n    assertEquals(2, bcard);\n\n    bcard = jedis.scard(bbar);\n    assertEquals(0, bcard);\n\n  }\n\n  @Test\n  public void sismember() {\n    jedis.sadd(\"foo\", \"a\");\n    jedis.sadd(\"foo\", \"b\");\n\n    assertTrue(jedis.sismember(\"foo\", \"a\"));\n\n    assertFalse(jedis.sismember(\"foo\", \"c\"));\n\n    // Binary\n    jedis.sadd(bfoo, ba);\n    jedis.sadd(bfoo, bb);\n\n    assertTrue(jedis.sismember(bfoo, ba));\n\n    assertFalse(jedis.sismember(bfoo, bc));\n\n  }\n\n  @Test\n  public void sinter() {\n    jedis.sadd(\"foo\", \"a\");\n    jedis.sadd(\"foo\", \"b\");\n\n    jedis.sadd(\"bar\", \"b\");\n    jedis.sadd(\"bar\", \"c\");\n\n    Set<String> expected = new HashSet<String>();\n    expected.add(\"b\");\n\n    Set<String> intersection = jedis.sinter(\"foo\", \"bar\");\n    assertEquals(expected, intersection);\n\n    // Binary\n    jedis.sadd(bfoo, ba);\n    jedis.sadd(bfoo, bb);\n\n    jedis.sadd(bbar, bb);\n    jedis.sadd(bbar, bc);\n\n    Set<byte[]> bexpected = new HashSet<byte[]>();\n    bexpected.add(bb);\n\n    Set<byte[]> bintersection = jedis.sinter(bfoo, bbar);\n    assertEquals(bexpected, bintersection);\n  }\n\n  @Test\n  public void sinterstore() {\n    jedis.sadd(\"foo\", \"a\");\n    jedis.sadd(\"foo\", \"b\");\n\n    jedis.sadd(\"bar\", \"b\");\n    jedis.sadd(\"bar\", \"c\");\n\n    Set<String> expected = new HashSet<String>();\n    expected.add(\"b\");\n\n    long status = jedis.sinterstore(\"car\", \"foo\", \"bar\");\n    assertEquals(1, status);\n\n    assertEquals(expected, jedis.smembers(\"car\"));\n\n    // Binary\n    jedis.sadd(bfoo, ba);\n    jedis.sadd(bfoo, bb);\n\n    jedis.sadd(bbar, bb);\n    jedis.sadd(bbar, bc);\n\n    Set<byte[]> bexpected = new HashSet<byte[]>();\n    bexpected.add(bb);\n\n    long bstatus = jedis.sinterstore(bcar, bfoo, bbar);\n    assertEquals(1, bstatus);\n\n    assertEquals(bexpected, jedis.smembers(bcar));\n\n  }\n\n  @Test\n  public void sunion() {\n    jedis.sadd(\"foo\", \"a\");\n    jedis.sadd(\"foo\", \"b\");\n\n    jedis.sadd(\"bar\", \"b\");\n    jedis.sadd(\"bar\", \"c\");\n\n    Set<String> expected = new HashSet<String>();\n    expected.add(\"a\");\n    expected.add(\"b\");\n    expected.add(\"c\");\n\n    Set<String> union = jedis.sunion(\"foo\", \"bar\");\n    assertEquals(expected, union);\n\n    // Binary\n    jedis.sadd(bfoo, ba);\n    jedis.sadd(bfoo, bb);\n\n    jedis.sadd(bbar, bb);\n    jedis.sadd(bbar, bc);\n\n    Set<byte[]> bexpected = new HashSet<byte[]>();\n    bexpected.add(bb);\n    bexpected.add(bc);\n    bexpected.add(ba);\n\n    Set<byte[]> bunion = jedis.sunion(bfoo, bbar);\n    assertEquals(bexpected, bunion);\n\n  }\n\n  @Test\n  public void sunionstore() {\n    jedis.sadd(\"foo\", \"a\");\n    jedis.sadd(\"foo\", \"b\");\n\n    jedis.sadd(\"bar\", \"b\");\n    jedis.sadd(\"bar\", \"c\");\n\n    Set<String> expected = new HashSet<String>();\n    expected.add(\"a\");\n    expected.add(\"b\");\n    expected.add(\"c\");\n\n    long status = jedis.sunionstore(\"car\", \"foo\", \"bar\");\n    assertEquals(3, status);\n\n    assertEquals(expected, jedis.smembers(\"car\"));\n\n    // Binary\n    jedis.sadd(bfoo, ba);\n    jedis.sadd(bfoo, bb);\n\n    jedis.sadd(bbar, bb);\n    jedis.sadd(bbar, bc);\n\n    Set<byte[]> bexpected = new HashSet<byte[]>();\n    bexpected.add(bb);\n    bexpected.add(bc);\n    bexpected.add(ba);\n\n    long bstatus = jedis.sunionstore(bcar, bfoo, bbar);\n    assertEquals(3, bstatus);\n\n    assertEquals(bexpected, jedis.smembers(bcar));\n\n  }\n\n  @Test\n  public void sdiff() {\n    jedis.sadd(\"foo\", \"x\");\n    jedis.sadd(\"foo\", \"a\");\n    jedis.sadd(\"foo\", \"b\");\n    jedis.sadd(\"foo\", \"c\");\n\n    jedis.sadd(\"bar\", \"c\");\n\n    jedis.sadd(\"car\", \"a\");\n    jedis.sadd(\"car\", \"d\");\n\n    Set<String> expected = new HashSet<String>();\n    expected.add(\"x\");\n    expected.add(\"b\");\n\n    Set<String> diff = jedis.sdiff(\"foo\", \"bar\", \"car\");\n    assertEquals(expected, diff);\n\n    // Binary\n    jedis.sadd(bfoo, bx);\n    jedis.sadd(bfoo, ba);\n    jedis.sadd(bfoo, bb);\n    jedis.sadd(bfoo, bc);\n\n    jedis.sadd(bbar, bc);\n\n    jedis.sadd(bcar, ba);\n    jedis.sadd(bcar, bd);\n\n    Set<byte[]> bexpected = new HashSet<byte[]>();\n    bexpected.add(bb);\n    bexpected.add(bx);\n\n    Set<byte[]> bdiff = jedis.sdiff(bfoo, bbar, bcar);\n    assertEquals(bexpected, bdiff);\n\n  }\n\n  @Test\n  public void sdiffstore() {\n    jedis.sadd(\"foo\", \"x\");\n    jedis.sadd(\"foo\", \"a\");\n    jedis.sadd(\"foo\", \"b\");\n    jedis.sadd(\"foo\", \"c\");\n\n    jedis.sadd(\"bar\", \"c\");\n\n    jedis.sadd(\"car\", \"a\");\n    jedis.sadd(\"car\", \"d\");\n\n    Set<String> expected = new HashSet<String>();\n    expected.add(\"d\");\n    expected.add(\"a\");\n\n    long status = jedis.sdiffstore(\"tar\", \"foo\", \"bar\", \"car\");\n    assertEquals(2, status);\n    assertEquals(expected, jedis.smembers(\"car\"));\n\n    // Binary\n    jedis.sadd(bfoo, bx);\n    jedis.sadd(bfoo, ba);\n    jedis.sadd(bfoo, bb);\n    jedis.sadd(bfoo, bc);\n\n    jedis.sadd(bbar, bc);\n\n    jedis.sadd(bcar, ba);\n    jedis.sadd(bcar, bd);\n\n    Set<byte[]> bexpected = new HashSet<byte[]>();\n    bexpected.add(bd);\n    bexpected.add(ba);\n\n    long bstatus = jedis.sdiffstore(\"tar\".getBytes(), bfoo, bbar, bcar);\n    assertEquals(2, bstatus);\n    assertEquals(bexpected, jedis.smembers(bcar));\n\n  }\n\n  @Test\n  public void srandmember() {\n    jedis.sadd(\"foo\", \"a\");\n    jedis.sadd(\"foo\", \"b\");\n\n    String member = jedis.srandmember(\"foo\");\n\n    assertTrue(\"a\".equals(member) || \"b\".equals(member));\n    assertEquals(2, jedis.smembers(\"foo\").size());\n\n    member = jedis.srandmember(\"bar\");\n    assertNull(member);\n\n    // Binary\n    jedis.sadd(bfoo, ba);\n    jedis.sadd(bfoo, bb);\n\n    byte[] bmember = jedis.srandmember(bfoo);\n\n    assertTrue(Arrays.equals(ba, bmember) || Arrays.equals(bb, bmember));\n    assertEquals(2, jedis.smembers(bfoo).size());\n\n    bmember = jedis.srandmember(bbar);\n    assertNull(bmember);\n  }\n\n  @Test\n  public void sscan() {\n    jedis.sadd(\"foo\", \"a\", \"b\");\n\n    ScanResult<String> result = jedis.sscan(\"foo\", SCAN_POINTER_START);\n\n    assertEquals(SCAN_POINTER_START, result.getCursor());\n    assertFalse(result.getResult().isEmpty());\n\n    // binary\n    jedis.sadd(bfoo, ba, bb);\n\n    ScanResult<byte[]> bResult = jedis.sscan(bfoo, SCAN_POINTER_START_BINARY);\n\n    assertArrayEquals(SCAN_POINTER_START_BINARY, bResult.getCursorAsBytes());\n    assertFalse(bResult.getResult().isEmpty());\n  }\n\n  @Test\n  public void sscanMatch() {\n    ScanParams params = new ScanParams();\n    params.match(\"a*\");\n\n    jedis.sadd(\"foo\", \"b\", \"a\", \"aa\");\n    ScanResult<String> result = jedis.sscan(\"foo\", SCAN_POINTER_START, params);\n\n    assertEquals(SCAN_POINTER_START, result.getCursor());\n    assertFalse(result.getResult().isEmpty());\n\n    // binary\n    params = new ScanParams();\n    params.match(bbarstar);\n\n    jedis.sadd(bfoo, bbar1, bbar2, bbar3);\n    ScanResult<byte[]> bResult = jedis.sscan(bfoo, SCAN_POINTER_START_BINARY, params);\n\n    assertArrayEquals(SCAN_POINTER_START_BINARY, bResult.getCursorAsBytes());\n    assertFalse(bResult.getResult().isEmpty());\n  }\n\n  @Test\n  public void sscanCount() {\n    ScanParams params = new ScanParams();\n    params.count(2);\n\n    jedis.sadd(\"foo\", \"a1\", \"a2\", \"a3\", \"a4\", \"a5\");\n\n    ScanResult<String> result = jedis.sscan(\"foo\", SCAN_POINTER_START, params);\n\n    assertFalse(result.getResult().isEmpty());\n\n    // binary\n    params = new ScanParams();\n    params.count(2);\n\n    jedis.sadd(bfoo, bbar1, bbar2, bbar3);\n    ScanResult<byte[]> bResult = jedis.sscan(bfoo, SCAN_POINTER_START_BINARY, params);\n\n    assertFalse(bResult.getResult().isEmpty());\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/commands/SlowlogCommandsTest.java",
    "content": "package redis.clients.jedis.tests.commands;\n\nimport java.util.List;\n\nimport org.junit.Test;\n\nimport redis.clients.util.Slowlog;\n\npublic class SlowlogCommandsTest extends JedisCommandTestBase {\n\n  @Test\n  public void slowlog() {\n    // do something\n    jedis.configSet(\"slowlog-log-slower-than\", \"0\");\n    jedis.set(\"foo\", \"bar\");\n    jedis.set(\"foo2\", \"bar2\");\n\n    List<Slowlog> reducedLog = jedis.slowlogGet(1);\n    assertEquals(1, reducedLog.size());\n\n    Slowlog log = reducedLog.get(0);\n    assertTrue(log.getId() > 0);\n    assertTrue(log.getTimeStamp() > 0);\n    assertTrue(log.getExecutionTime() > 0);\n    assertNotNull(log.getArgs());\n\n    List<byte[]> breducedLog = jedis.slowlogGetBinary(1);\n    assertEquals(1, breducedLog.size());\n\n    List<Slowlog> log1 = jedis.slowlogGet();\n    List<byte[]> blog1 = jedis.slowlogGetBinary();\n\n    assertNotNull(log1);\n    assertNotNull(blog1);\n\n    long len1 = jedis.slowlogLen();\n\n    jedis.slowlogReset();\n\n    List<Slowlog> log2 = jedis.slowlogGet();\n    List<byte[]> blog2 = jedis.slowlogGetBinary();\n    long len2 = jedis.slowlogLen();\n\n    assertTrue(len1 > len2);\n    assertTrue(log1.size() > log2.size());\n    assertTrue(blog1.size() > blog2.size());\n  }\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/commands/SortedSetCommandsTest.java",
    "content": "package redis.clients.jedis.tests.commands;\n\nimport static redis.clients.jedis.ScanParams.SCAN_POINTER_START;\nimport static redis.clients.jedis.ScanParams.SCAN_POINTER_START_BINARY;\n\nimport java.util.HashMap;\nimport java.util.LinkedHashSet;\nimport java.util.Map;\nimport java.util.Set;\n\nimport org.junit.Test;\n\nimport redis.clients.jedis.ScanParams;\nimport redis.clients.jedis.ScanResult;\nimport redis.clients.jedis.Tuple;\nimport redis.clients.jedis.ZParams;\nimport redis.clients.jedis.params.sortedset.ZAddParams;\nimport redis.clients.jedis.params.sortedset.ZIncrByParams;\nimport redis.clients.util.SafeEncoder;\n\npublic class SortedSetCommandsTest extends JedisCommandTestBase {\n  final byte[] bfoo = { 0x01, 0x02, 0x03, 0x04 };\n  final byte[] bbar = { 0x05, 0x06, 0x07, 0x08 };\n  final byte[] bcar = { 0x09, 0x0A, 0x0B, 0x0C };\n  final byte[] ba = { 0x0A };\n  final byte[] bb = { 0x0B };\n  final byte[] bc = { 0x0C };\n  final byte[] bInclusiveB = { 0x5B, 0x0B };\n  final byte[] bExclusiveC = { 0x28, 0x0C };\n  final byte[] bLexMinusInf = { 0x2D };\n  final byte[] bLexPlusInf = { 0x2B };\n\n  final byte[] bbar1 = { 0x05, 0x06, 0x07, 0x08, 0x0A };\n  final byte[] bbar2 = { 0x05, 0x06, 0x07, 0x08, 0x0B };\n  final byte[] bbar3 = { 0x05, 0x06, 0x07, 0x08, 0x0C };\n  final byte[] bbarstar = { 0x05, 0x06, 0x07, 0x08, '*' };\n\n  @Test\n  public void zadd() {\n    long status = jedis.zadd(\"foo\", 1d, \"a\");\n    assertEquals(1, status);\n\n    status = jedis.zadd(\"foo\", 10d, \"b\");\n    assertEquals(1, status);\n\n    status = jedis.zadd(\"foo\", 0.1d, \"c\");\n    assertEquals(1, status);\n\n    status = jedis.zadd(\"foo\", 2d, \"a\");\n    assertEquals(0, status);\n\n    // Binary\n    long bstatus = jedis.zadd(bfoo, 1d, ba);\n    assertEquals(1, bstatus);\n\n    bstatus = jedis.zadd(bfoo, 10d, bb);\n    assertEquals(1, bstatus);\n\n    bstatus = jedis.zadd(bfoo, 0.1d, bc);\n    assertEquals(1, bstatus);\n\n    bstatus = jedis.zadd(bfoo, 2d, ba);\n    assertEquals(0, bstatus);\n\n  }\n\n  @Test\n  public void zaddWithParams() {\n    jedis.del(\"foo\");\n\n    // xx: never add new member\n    long status = jedis.zadd(\"foo\", 1d, \"a\", ZAddParams.zAddParams().xx());\n    assertEquals(0L, status);\n\n    jedis.zadd(\"foo\", 1d, \"a\");\n    // nx: never update current member\n    status = jedis.zadd(\"foo\", 2d, \"a\", ZAddParams.zAddParams().nx());\n    assertEquals(0L, status);\n    assertEquals(Double.valueOf(1d), jedis.zscore(\"foo\", \"a\"));\n\n    Map<String, Double> scoreMembers = new HashMap<String, Double>();\n    scoreMembers.put(\"a\", 2d);\n    scoreMembers.put(\"b\", 1d);\n    // ch: return count of members not only added, but also updated\n    status = jedis.zadd(\"foo\", scoreMembers, ZAddParams.zAddParams().ch());\n    assertEquals(2L, status);\n\n    // binary\n    jedis.del(bfoo);\n\n    // xx: never add new member\n    status = jedis.zadd(bfoo, 1d, ba, ZAddParams.zAddParams().xx());\n    assertEquals(0L, status);\n\n    jedis.zadd(bfoo, 1d, ba);\n    // nx: never update current member\n    status = jedis.zadd(bfoo, 2d, ba, ZAddParams.zAddParams().nx());\n    assertEquals(0L, status);\n    assertEquals(Double.valueOf(1d), jedis.zscore(bfoo, ba));\n\n    Map<byte[], Double> binaryScoreMembers = new HashMap<byte[], Double>();\n    binaryScoreMembers.put(ba, 2d);\n    binaryScoreMembers.put(bb, 1d);\n    // ch: return count of members not only added, but also updated\n    status = jedis.zadd(bfoo, binaryScoreMembers, ZAddParams.zAddParams().ch());\n    assertEquals(2L, status);\n  }\n\n  @Test\n  public void zrange() {\n    jedis.zadd(\"foo\", 1d, \"a\");\n    jedis.zadd(\"foo\", 10d, \"b\");\n    jedis.zadd(\"foo\", 0.1d, \"c\");\n    jedis.zadd(\"foo\", 2d, \"a\");\n\n    Set<String> expected = new LinkedHashSet<String>();\n    expected.add(\"c\");\n    expected.add(\"a\");\n\n    Set<String> range = jedis.zrange(\"foo\", 0, 1);\n    assertEquals(expected, range);\n\n    expected.add(\"b\");\n    range = jedis.zrange(\"foo\", 0, 100);\n    assertEquals(expected, range);\n\n    // Binary\n    jedis.zadd(bfoo, 1d, ba);\n    jedis.zadd(bfoo, 10d, bb);\n    jedis.zadd(bfoo, 0.1d, bc);\n    jedis.zadd(bfoo, 2d, ba);\n\n    Set<byte[]> bexpected = new LinkedHashSet<byte[]>();\n    bexpected.add(bc);\n    bexpected.add(ba);\n\n    Set<byte[]> brange = jedis.zrange(bfoo, 0, 1);\n    assertEquals(bexpected, brange);\n\n    bexpected.add(bb);\n    brange = jedis.zrange(bfoo, 0, 100);\n    assertEquals(bexpected, brange);\n\n  }\n\n  @Test\n  public void zrangeByLex() {\n    jedis.zadd(\"foo\", 1, \"aa\");\n    jedis.zadd(\"foo\", 1, \"c\");\n    jedis.zadd(\"foo\", 1, \"bb\");\n    jedis.zadd(\"foo\", 1, \"d\");\n\n    Set<String> expected = new LinkedHashSet<String>();\n    expected.add(\"bb\");\n    expected.add(\"c\");\n\n    // exclusive aa ~ inclusive c\n    assertEquals(expected, jedis.zrangeByLex(\"foo\", \"(aa\", \"[c\"));\n\n    expected.clear();\n    expected.add(\"bb\");\n    expected.add(\"c\");\n\n    // with LIMIT\n    assertEquals(expected, jedis.zrangeByLex(\"foo\", \"-\", \"+\", 1, 2));\n  }\n\n  @Test\n  public void zrangeByLexBinary() {\n    // binary\n    jedis.zadd(bfoo, 1, ba);\n    jedis.zadd(bfoo, 1, bc);\n    jedis.zadd(bfoo, 1, bb);\n\n    Set<byte[]> bExpected = new LinkedHashSet<byte[]>();\n    bExpected.add(bb);\n\n    assertEquals(bExpected, jedis.zrangeByLex(bfoo, bInclusiveB, bExclusiveC));\n\n    bExpected.clear();\n    bExpected.add(ba);\n    bExpected.add(bb);\n\n    // with LIMIT\n    assertEquals(bExpected, jedis.zrangeByLex(bfoo, bLexMinusInf, bLexPlusInf, 0, 2));\n  }\n\n  @Test\n  public void zrevrangeByLex() {\n    jedis.zadd(\"foo\", 1, \"aa\");\n    jedis.zadd(\"foo\", 1, \"c\");\n    jedis.zadd(\"foo\", 1, \"bb\");\n    jedis.zadd(\"foo\", 1, \"d\");\n\n    Set<String> expected = new LinkedHashSet<String>();\n    expected.add(\"c\");\n    expected.add(\"bb\");\n\n    // exclusive aa ~ inclusive c\n    assertEquals(expected, jedis.zrevrangeByLex(\"foo\", \"[c\", \"(aa\"));\n\n    expected.clear();\n    expected.add(\"c\");\n    expected.add(\"bb\");\n\n    // with LIMIT\n    assertEquals(expected, jedis.zrevrangeByLex(\"foo\", \"+\", \"-\", 1, 2));\n  }\n\n  @Test\n  public void zrevrangeByLexBinary() {\n    // binary\n    jedis.zadd(bfoo, 1, ba);\n    jedis.zadd(bfoo, 1, bc);\n    jedis.zadd(bfoo, 1, bb);\n\n    Set<byte[]> bExpected = new LinkedHashSet<byte[]>();\n    bExpected.add(bb);\n\n    assertEquals(bExpected, jedis.zrevrangeByLex(bfoo, bExclusiveC, bInclusiveB));\n\n    bExpected.clear();\n    bExpected.add(bb);\n    bExpected.add(ba);\n\n    // with LIMIT\n    assertEquals(bExpected, jedis.zrevrangeByLex(bfoo, bLexPlusInf, bLexMinusInf, 0, 2));\n  }\n\n  @Test\n  public void zrevrange() {\n    jedis.zadd(\"foo\", 1d, \"a\");\n    jedis.zadd(\"foo\", 10d, \"b\");\n    jedis.zadd(\"foo\", 0.1d, \"c\");\n    jedis.zadd(\"foo\", 2d, \"a\");\n\n    Set<String> expected = new LinkedHashSet<String>();\n    expected.add(\"b\");\n    expected.add(\"a\");\n\n    Set<String> range = jedis.zrevrange(\"foo\", 0, 1);\n    assertEquals(expected, range);\n\n    expected.add(\"c\");\n    range = jedis.zrevrange(\"foo\", 0, 100);\n    assertEquals(expected, range);\n\n    // Binary\n    jedis.zadd(bfoo, 1d, ba);\n    jedis.zadd(bfoo, 10d, bb);\n    jedis.zadd(bfoo, 0.1d, bc);\n    jedis.zadd(bfoo, 2d, ba);\n\n    Set<byte[]> bexpected = new LinkedHashSet<byte[]>();\n    bexpected.add(bb);\n    bexpected.add(ba);\n\n    Set<byte[]> brange = jedis.zrevrange(bfoo, 0, 1);\n    assertEquals(bexpected, brange);\n\n    bexpected.add(bc);\n    brange = jedis.zrevrange(bfoo, 0, 100);\n    assertEquals(bexpected, brange);\n\n  }\n\n  @Test\n  public void zrem() {\n    jedis.zadd(\"foo\", 1d, \"a\");\n    jedis.zadd(\"foo\", 2d, \"b\");\n\n    long status = jedis.zrem(\"foo\", \"a\");\n\n    Set<String> expected = new LinkedHashSet<String>();\n    expected.add(\"b\");\n\n    assertEquals(1, status);\n    assertEquals(expected, jedis.zrange(\"foo\", 0, 100));\n\n    status = jedis.zrem(\"foo\", \"bar\");\n\n    assertEquals(0, status);\n\n    // Binary\n    jedis.zadd(bfoo, 1d, ba);\n    jedis.zadd(bfoo, 2d, bb);\n\n    long bstatus = jedis.zrem(bfoo, ba);\n\n    Set<byte[]> bexpected = new LinkedHashSet<byte[]>();\n    bexpected.add(bb);\n\n    assertEquals(1, bstatus);\n    assertEquals(bexpected, jedis.zrange(bfoo, 0, 100));\n\n    bstatus = jedis.zrem(bfoo, bbar);\n\n    assertEquals(0, bstatus);\n\n  }\n\n  @Test\n  public void zincrby() {\n    jedis.zadd(\"foo\", 1d, \"a\");\n    jedis.zadd(\"foo\", 2d, \"b\");\n\n    double score = jedis.zincrby(\"foo\", 2d, \"a\");\n\n    Set<String> expected = new LinkedHashSet<String>();\n    expected.add(\"a\");\n    expected.add(\"b\");\n\n    assertEquals(3d, score, 0);\n    assertEquals(expected, jedis.zrange(\"foo\", 0, 100));\n\n    // Binary\n    jedis.zadd(bfoo, 1d, ba);\n    jedis.zadd(bfoo, 2d, bb);\n\n    double bscore = jedis.zincrby(bfoo, 2d, ba);\n\n    Set<byte[]> bexpected = new LinkedHashSet<byte[]>();\n    bexpected.add(bb);\n    bexpected.add(ba);\n\n    assertEquals(3d, bscore, 0);\n    assertEquals(bexpected, jedis.zrange(bfoo, 0, 100));\n\n  }\n\n  @Test\n  public void zincrbyWithParams() {\n    jedis.del(\"foo\");\n\n    // xx: never add new member\n    Double score = jedis.zincrby(\"foo\", 2d, \"a\", ZIncrByParams.zIncrByParams().xx());\n    assertNull(score);\n\n    jedis.zadd(\"foo\", 2d, \"a\");\n\n    // nx: never update current member\n    score = jedis.zincrby(\"foo\", 1d, \"a\", ZIncrByParams.zIncrByParams().nx());\n    assertNull(score);\n    assertEquals(Double.valueOf(2d), jedis.zscore(\"foo\", \"a\"));\n\n    // Binary\n\n    jedis.del(bfoo);\n\n    // xx: never add new member\n    score = jedis.zincrby(bfoo, 2d, ba, ZIncrByParams.zIncrByParams().xx());\n    assertNull(score);\n\n    jedis.zadd(bfoo, 2d, ba);\n\n    // nx: never update current member\n    score = jedis.zincrby(bfoo, 1d, ba, ZIncrByParams.zIncrByParams().nx());\n    assertNull(score);\n    assertEquals(Double.valueOf(2d), jedis.zscore(bfoo, ba));\n  }\n\n  @Test\n  public void zrank() {\n    jedis.zadd(\"foo\", 1d, \"a\");\n    jedis.zadd(\"foo\", 2d, \"b\");\n\n    long rank = jedis.zrank(\"foo\", \"a\");\n    assertEquals(0, rank);\n\n    rank = jedis.zrank(\"foo\", \"b\");\n    assertEquals(1, rank);\n\n    assertNull(jedis.zrank(\"car\", \"b\"));\n\n    // Binary\n    jedis.zadd(bfoo, 1d, ba);\n    jedis.zadd(bfoo, 2d, bb);\n\n    long brank = jedis.zrank(bfoo, ba);\n    assertEquals(0, brank);\n\n    brank = jedis.zrank(bfoo, bb);\n    assertEquals(1, brank);\n\n    assertNull(jedis.zrank(bcar, bb));\n\n  }\n\n  @Test\n  public void zrevrank() {\n    jedis.zadd(\"foo\", 1d, \"a\");\n    jedis.zadd(\"foo\", 2d, \"b\");\n\n    long rank = jedis.zrevrank(\"foo\", \"a\");\n    assertEquals(1, rank);\n\n    rank = jedis.zrevrank(\"foo\", \"b\");\n    assertEquals(0, rank);\n\n    // Binary\n    jedis.zadd(bfoo, 1d, ba);\n    jedis.zadd(bfoo, 2d, bb);\n\n    long brank = jedis.zrevrank(bfoo, ba);\n    assertEquals(1, brank);\n\n    brank = jedis.zrevrank(bfoo, bb);\n    assertEquals(0, brank);\n\n  }\n\n  @Test\n  public void zrangeWithScores() {\n    jedis.zadd(\"foo\", 1d, \"a\");\n    jedis.zadd(\"foo\", 10d, \"b\");\n    jedis.zadd(\"foo\", 0.1d, \"c\");\n    jedis.zadd(\"foo\", 2d, \"a\");\n\n    Set<Tuple> expected = new LinkedHashSet<Tuple>();\n    expected.add(new Tuple(\"c\", 0.1d));\n    expected.add(new Tuple(\"a\", 2d));\n\n    Set<Tuple> range = jedis.zrangeWithScores(\"foo\", 0, 1);\n    assertEquals(expected, range);\n\n    expected.add(new Tuple(\"b\", 10d));\n    range = jedis.zrangeWithScores(\"foo\", 0, 100);\n    assertEquals(expected, range);\n\n    // Binary\n    jedis.zadd(bfoo, 1d, ba);\n    jedis.zadd(bfoo, 10d, bb);\n    jedis.zadd(bfoo, 0.1d, bc);\n    jedis.zadd(bfoo, 2d, ba);\n\n    Set<Tuple> bexpected = new LinkedHashSet<Tuple>();\n    bexpected.add(new Tuple(bc, 0.1d));\n    bexpected.add(new Tuple(ba, 2d));\n\n    Set<Tuple> brange = jedis.zrangeWithScores(bfoo, 0, 1);\n    assertEquals(bexpected, brange);\n\n    bexpected.add(new Tuple(bb, 10d));\n    brange = jedis.zrangeWithScores(bfoo, 0, 100);\n    assertEquals(bexpected, brange);\n\n  }\n\n  @Test\n  public void zrevrangeWithScores() {\n    jedis.zadd(\"foo\", 1d, \"a\");\n    jedis.zadd(\"foo\", 10d, \"b\");\n    jedis.zadd(\"foo\", 0.1d, \"c\");\n    jedis.zadd(\"foo\", 2d, \"a\");\n\n    Set<Tuple> expected = new LinkedHashSet<Tuple>();\n    expected.add(new Tuple(\"b\", 10d));\n    expected.add(new Tuple(\"a\", 2d));\n\n    Set<Tuple> range = jedis.zrevrangeWithScores(\"foo\", 0, 1);\n    assertEquals(expected, range);\n\n    expected.add(new Tuple(\"c\", 0.1d));\n    range = jedis.zrevrangeWithScores(\"foo\", 0, 100);\n    assertEquals(expected, range);\n\n    // Binary\n    jedis.zadd(bfoo, 1d, ba);\n    jedis.zadd(bfoo, 10d, bb);\n    jedis.zadd(bfoo, 0.1d, bc);\n    jedis.zadd(bfoo, 2d, ba);\n\n    Set<Tuple> bexpected = new LinkedHashSet<Tuple>();\n    bexpected.add(new Tuple(bb, 10d));\n    bexpected.add(new Tuple(ba, 2d));\n\n    Set<Tuple> brange = jedis.zrevrangeWithScores(bfoo, 0, 1);\n    assertEquals(bexpected, brange);\n\n    bexpected.add(new Tuple(bc, 0.1d));\n    brange = jedis.zrevrangeWithScores(bfoo, 0, 100);\n    assertEquals(bexpected, brange);\n\n  }\n\n  @Test\n  public void zcard() {\n    jedis.zadd(\"foo\", 1d, \"a\");\n    jedis.zadd(\"foo\", 10d, \"b\");\n    jedis.zadd(\"foo\", 0.1d, \"c\");\n    jedis.zadd(\"foo\", 2d, \"a\");\n\n    long size = jedis.zcard(\"foo\");\n    assertEquals(3, size);\n\n    // Binary\n    jedis.zadd(bfoo, 1d, ba);\n    jedis.zadd(bfoo, 10d, bb);\n    jedis.zadd(bfoo, 0.1d, bc);\n    jedis.zadd(bfoo, 2d, ba);\n\n    long bsize = jedis.zcard(bfoo);\n    assertEquals(3, bsize);\n\n  }\n\n  @Test\n  public void zscore() {\n    jedis.zadd(\"foo\", 1d, \"a\");\n    jedis.zadd(\"foo\", 10d, \"b\");\n    jedis.zadd(\"foo\", 0.1d, \"c\");\n    jedis.zadd(\"foo\", 2d, \"a\");\n\n    Double score = jedis.zscore(\"foo\", \"b\");\n    assertEquals((Double) 10d, score);\n\n    score = jedis.zscore(\"foo\", \"c\");\n    assertEquals((Double) 0.1d, score);\n\n    score = jedis.zscore(\"foo\", \"s\");\n    assertNull(score);\n\n    // Binary\n    jedis.zadd(bfoo, 1d, ba);\n    jedis.zadd(bfoo, 10d, bb);\n    jedis.zadd(bfoo, 0.1d, bc);\n    jedis.zadd(bfoo, 2d, ba);\n\n    Double bscore = jedis.zscore(bfoo, bb);\n    assertEquals((Double) 10d, bscore);\n\n    bscore = jedis.zscore(bfoo, bc);\n    assertEquals((Double) 0.1d, bscore);\n\n    bscore = jedis.zscore(bfoo, SafeEncoder.encode(\"s\"));\n    assertNull(bscore);\n\n  }\n\n  @Test\n  public void zcount() {\n    jedis.zadd(\"foo\", 1d, \"a\");\n    jedis.zadd(\"foo\", 10d, \"b\");\n    jedis.zadd(\"foo\", 0.1d, \"c\");\n    jedis.zadd(\"foo\", 2d, \"a\");\n\n    long result = jedis.zcount(\"foo\", 0.01d, 2.1d);\n\n    assertEquals(2, result);\n\n    result = jedis.zcount(\"foo\", \"(0.01\", \"+inf\");\n\n    assertEquals(3, result);\n\n    // Binary\n    jedis.zadd(bfoo, 1d, ba);\n    jedis.zadd(bfoo, 10d, bb);\n    jedis.zadd(bfoo, 0.1d, bc);\n    jedis.zadd(bfoo, 2d, ba);\n\n    long bresult = jedis.zcount(bfoo, 0.01d, 2.1d);\n\n    assertEquals(2, bresult);\n\n    bresult = jedis.zcount(bfoo, SafeEncoder.encode(\"(0.01\"), SafeEncoder.encode(\"+inf\"));\n\n    assertEquals(3, bresult);\n  }\n\n  @Test\n  public void zlexcount() {\n    jedis.zadd(\"foo\", 1, \"a\");\n    jedis.zadd(\"foo\", 1, \"b\");\n    jedis.zadd(\"foo\", 1, \"c\");\n    jedis.zadd(\"foo\", 1, \"aa\");\n\n    long result = jedis.zlexcount(\"foo\", \"[aa\", \"(c\");\n    assertEquals(2, result);\n\n    result = jedis.zlexcount(\"foo\", \"-\", \"+\");\n    assertEquals(4, result);\n\n    result = jedis.zlexcount(\"foo\", \"-\", \"(c\");\n    assertEquals(3, result);\n\n    result = jedis.zlexcount(\"foo\", \"[aa\", \"+\");\n    assertEquals(3, result);\n  }\n\n  @Test\n  public void zlexcountBinary() {\n    // Binary\n    jedis.zadd(bfoo, 1, ba);\n    jedis.zadd(bfoo, 1, bc);\n    jedis.zadd(bfoo, 1, bb);\n\n    long result = jedis.zlexcount(bfoo, bInclusiveB, bExclusiveC);\n    assertEquals(1, result);\n\n    result = jedis.zlexcount(bfoo, bLexMinusInf, bLexPlusInf);\n    assertEquals(3, result);\n  }\n\n  @Test\n  public void zrangebyscore() {\n    jedis.zadd(\"foo\", 1d, \"a\");\n    jedis.zadd(\"foo\", 10d, \"b\");\n    jedis.zadd(\"foo\", 0.1d, \"c\");\n    jedis.zadd(\"foo\", 2d, \"a\");\n\n    Set<String> range = jedis.zrangeByScore(\"foo\", 0d, 2d);\n\n    Set<String> expected = new LinkedHashSet<String>();\n    expected.add(\"c\");\n    expected.add(\"a\");\n\n    assertEquals(expected, range);\n\n    range = jedis.zrangeByScore(\"foo\", 0d, 2d, 0, 1);\n\n    expected = new LinkedHashSet<String>();\n    expected.add(\"c\");\n\n    assertEquals(expected, range);\n\n    range = jedis.zrangeByScore(\"foo\", 0d, 2d, 1, 1);\n    Set<String> range2 = jedis.zrangeByScore(\"foo\", \"-inf\", \"(2\");\n    assertEquals(expected, range2);\n\n    expected = new LinkedHashSet<String>();\n    expected.add(\"a\");\n\n    assertEquals(expected, range);\n\n    // Binary\n    jedis.zadd(bfoo, 1d, ba);\n    jedis.zadd(bfoo, 10d, bb);\n    jedis.zadd(bfoo, 0.1d, bc);\n    jedis.zadd(bfoo, 2d, ba);\n\n    Set<byte[]> brange = jedis.zrangeByScore(bfoo, 0d, 2d);\n\n    Set<byte[]> bexpected = new LinkedHashSet<byte[]>();\n    bexpected.add(bc);\n    bexpected.add(ba);\n\n    assertEquals(bexpected, brange);\n\n    brange = jedis.zrangeByScore(bfoo, 0d, 2d, 0, 1);\n\n    bexpected = new LinkedHashSet<byte[]>();\n    bexpected.add(bc);\n\n    assertEquals(bexpected, brange);\n\n    brange = jedis.zrangeByScore(bfoo, 0d, 2d, 1, 1);\n    Set<byte[]> brange2 = jedis.zrangeByScore(bfoo, SafeEncoder.encode(\"-inf\"),\n      SafeEncoder.encode(\"(2\"));\n    assertEquals(bexpected, brange2);\n\n    bexpected = new LinkedHashSet<byte[]>();\n    bexpected.add(ba);\n\n    assertEquals(bexpected, brange);\n\n  }\n\n  @Test\n  public void zrevrangebyscore() {\n    jedis.zadd(\"foo\", 1.0d, \"a\");\n    jedis.zadd(\"foo\", 2.0d, \"b\");\n    jedis.zadd(\"foo\", 3.0d, \"c\");\n    jedis.zadd(\"foo\", 4.0d, \"d\");\n    jedis.zadd(\"foo\", 5.0d, \"e\");\n\n    Set<String> range = jedis.zrevrangeByScore(\"foo\", 3d, Double.NEGATIVE_INFINITY, 0, 1);\n    Set<String> expected = new LinkedHashSet<String>();\n    expected.add(\"c\");\n\n    assertEquals(expected, range);\n\n    range = jedis.zrevrangeByScore(\"foo\", 3.5d, Double.NEGATIVE_INFINITY, 0, 2);\n    expected = new LinkedHashSet<String>();\n    expected.add(\"c\");\n    expected.add(\"b\");\n\n    assertEquals(expected, range);\n\n    range = jedis.zrevrangeByScore(\"foo\", 3.5d, Double.NEGATIVE_INFINITY, 1, 1);\n    expected = new LinkedHashSet<String>();\n    expected.add(\"b\");\n\n    assertEquals(expected, range);\n\n    range = jedis.zrevrangeByScore(\"foo\", 4d, 2d);\n    expected = new LinkedHashSet<String>();\n    expected.add(\"d\");\n    expected.add(\"c\");\n    expected.add(\"b\");\n\n    assertEquals(expected, range);\n\n    range = jedis.zrevrangeByScore(\"foo\", \"+inf\", \"(4\");\n    expected = new LinkedHashSet<String>();\n    expected.add(\"e\");\n\n    assertEquals(expected, range);\n\n    // Binary\n    jedis.zadd(bfoo, 1d, ba);\n    jedis.zadd(bfoo, 10d, bb);\n    jedis.zadd(bfoo, 0.1d, bc);\n    jedis.zadd(bfoo, 2d, ba);\n\n    Set<byte[]> brange = jedis.zrevrangeByScore(bfoo, 2d, 0d);\n\n    Set<byte[]> bexpected = new LinkedHashSet<byte[]>();\n    bexpected.add(bc);\n    bexpected.add(ba);\n\n    assertEquals(bexpected, brange);\n\n    brange = jedis.zrevrangeByScore(bfoo, 2d, 0d, 0, 1);\n\n    bexpected = new LinkedHashSet<byte[]>();\n    bexpected.add(ba);\n\n    assertEquals(bexpected, brange);\n\n    Set<byte[]> brange2 = jedis.zrevrangeByScore(bfoo, SafeEncoder.encode(\"+inf\"),\n      SafeEncoder.encode(\"(2\"));\n\n    bexpected = new LinkedHashSet<byte[]>();\n    bexpected.add(bb);\n\n    assertEquals(bexpected, brange2);\n\n    brange = jedis.zrevrangeByScore(bfoo, 2d, 0d, 1, 1);\n    bexpected = new LinkedHashSet<byte[]>();\n    bexpected.add(bc);\n\n    assertEquals(bexpected, brange);\n  }\n\n  @Test\n  public void zrangebyscoreWithScores() {\n    jedis.zadd(\"foo\", 1d, \"a\");\n    jedis.zadd(\"foo\", 10d, \"b\");\n    jedis.zadd(\"foo\", 0.1d, \"c\");\n    jedis.zadd(\"foo\", 2d, \"a\");\n\n    Set<Tuple> range = jedis.zrangeByScoreWithScores(\"foo\", 0d, 2d);\n\n    Set<Tuple> expected = new LinkedHashSet<Tuple>();\n    expected.add(new Tuple(\"c\", 0.1d));\n    expected.add(new Tuple(\"a\", 2d));\n\n    assertEquals(expected, range);\n\n    range = jedis.zrangeByScoreWithScores(\"foo\", 0d, 2d, 0, 1);\n\n    expected = new LinkedHashSet<Tuple>();\n    expected.add(new Tuple(\"c\", 0.1d));\n\n    assertEquals(expected, range);\n\n    range = jedis.zrangeByScoreWithScores(\"foo\", 0d, 2d, 1, 1);\n\n    expected = new LinkedHashSet<Tuple>();\n    expected.add(new Tuple(\"a\", 2d));\n\n    assertEquals(expected, range);\n\n    // Binary\n\n    jedis.zadd(bfoo, 1d, ba);\n    jedis.zadd(bfoo, 10d, bb);\n    jedis.zadd(bfoo, 0.1d, bc);\n    jedis.zadd(bfoo, 2d, ba);\n\n    Set<Tuple> brange = jedis.zrangeByScoreWithScores(bfoo, 0d, 2d);\n\n    Set<Tuple> bexpected = new LinkedHashSet<Tuple>();\n    bexpected.add(new Tuple(bc, 0.1d));\n    bexpected.add(new Tuple(ba, 2d));\n\n    assertEquals(bexpected, brange);\n\n    brange = jedis.zrangeByScoreWithScores(bfoo, 0d, 2d, 0, 1);\n\n    bexpected = new LinkedHashSet<Tuple>();\n    bexpected.add(new Tuple(bc, 0.1d));\n\n    assertEquals(bexpected, brange);\n\n    brange = jedis.zrangeByScoreWithScores(bfoo, 0d, 2d, 1, 1);\n\n    bexpected = new LinkedHashSet<Tuple>();\n    bexpected.add(new Tuple(ba, 2d));\n\n    assertEquals(bexpected, brange);\n\n  }\n\n  @Test\n  public void zrevrangebyscoreWithScores() {\n    jedis.zadd(\"foo\", 1.0d, \"a\");\n    jedis.zadd(\"foo\", 2.0d, \"b\");\n    jedis.zadd(\"foo\", 3.0d, \"c\");\n    jedis.zadd(\"foo\", 4.0d, \"d\");\n    jedis.zadd(\"foo\", 5.0d, \"e\");\n\n    Set<Tuple> range = jedis.zrevrangeByScoreWithScores(\"foo\", 3d, Double.NEGATIVE_INFINITY, 0, 1);\n    Set<Tuple> expected = new LinkedHashSet<Tuple>();\n    expected.add(new Tuple(\"c\", 3.0d));\n\n    assertEquals(expected, range);\n\n    range = jedis.zrevrangeByScoreWithScores(\"foo\", 3.5d, Double.NEGATIVE_INFINITY, 0, 2);\n    expected = new LinkedHashSet<Tuple>();\n    expected.add(new Tuple(\"c\", 3.0d));\n    expected.add(new Tuple(\"b\", 2.0d));\n\n    assertEquals(expected, range);\n\n    range = jedis.zrevrangeByScoreWithScores(\"foo\", 3.5d, Double.NEGATIVE_INFINITY, 1, 1);\n    expected = new LinkedHashSet<Tuple>();\n    expected.add(new Tuple(\"b\", 2.0d));\n\n    assertEquals(expected, range);\n\n    range = jedis.zrevrangeByScoreWithScores(\"foo\", 4d, 2d);\n    expected = new LinkedHashSet<Tuple>();\n    expected.add(new Tuple(\"d\", 4.0d));\n    expected.add(new Tuple(\"c\", 3.0d));\n    expected.add(new Tuple(\"b\", 2.0d));\n\n    assertEquals(expected, range);\n\n    // Binary\n    jedis.zadd(bfoo, 1d, ba);\n    jedis.zadd(bfoo, 10d, bb);\n    jedis.zadd(bfoo, 0.1d, bc);\n    jedis.zadd(bfoo, 2d, ba);\n\n    Set<Tuple> brange = jedis.zrevrangeByScoreWithScores(bfoo, 2d, 0d);\n\n    Set<Tuple> bexpected = new LinkedHashSet<Tuple>();\n    bexpected.add(new Tuple(bc, 0.1d));\n    bexpected.add(new Tuple(ba, 2d));\n\n    assertEquals(bexpected, brange);\n\n    brange = jedis.zrevrangeByScoreWithScores(bfoo, 2d, 0d, 0, 1);\n\n    bexpected = new LinkedHashSet<Tuple>();\n    bexpected.add(new Tuple(ba, 2d));\n\n    assertEquals(bexpected, brange);\n\n    brange = jedis.zrevrangeByScoreWithScores(bfoo, 2d, 0d, 1, 1);\n\n    bexpected = new LinkedHashSet<Tuple>();\n    bexpected.add(new Tuple(bc, 0.1d));\n\n    assertEquals(bexpected, brange);\n  }\n\n  @Test\n  public void zremrangeByRank() {\n    jedis.zadd(\"foo\", 1d, \"a\");\n    jedis.zadd(\"foo\", 10d, \"b\");\n    jedis.zadd(\"foo\", 0.1d, \"c\");\n    jedis.zadd(\"foo\", 2d, \"a\");\n\n    long result = jedis.zremrangeByRank(\"foo\", 0, 0);\n\n    assertEquals(1, result);\n\n    Set<String> expected = new LinkedHashSet<String>();\n    expected.add(\"a\");\n    expected.add(\"b\");\n\n    assertEquals(expected, jedis.zrange(\"foo\", 0, 100));\n\n    // Binary\n    jedis.zadd(bfoo, 1d, ba);\n    jedis.zadd(bfoo, 10d, bb);\n    jedis.zadd(bfoo, 0.1d, bc);\n    jedis.zadd(bfoo, 2d, ba);\n\n    long bresult = jedis.zremrangeByRank(bfoo, 0, 0);\n\n    assertEquals(1, bresult);\n\n    Set<byte[]> bexpected = new LinkedHashSet<byte[]>();\n    bexpected.add(ba);\n    bexpected.add(bb);\n\n    assertEquals(bexpected, jedis.zrange(bfoo, 0, 100));\n\n  }\n\n  @Test\n  public void zremrangeByScore() {\n    jedis.zadd(\"foo\", 1d, \"a\");\n    jedis.zadd(\"foo\", 10d, \"b\");\n    jedis.zadd(\"foo\", 0.1d, \"c\");\n    jedis.zadd(\"foo\", 2d, \"a\");\n\n    long result = jedis.zremrangeByScore(\"foo\", 0, 2);\n\n    assertEquals(2, result);\n\n    Set<String> expected = new LinkedHashSet<String>();\n    expected.add(\"b\");\n\n    assertEquals(expected, jedis.zrange(\"foo\", 0, 100));\n\n    // Binary\n    jedis.zadd(bfoo, 1d, ba);\n    jedis.zadd(bfoo, 10d, bb);\n    jedis.zadd(bfoo, 0.1d, bc);\n    jedis.zadd(bfoo, 2d, ba);\n\n    long bresult = jedis.zremrangeByScore(bfoo, 0, 2);\n\n    assertEquals(2, bresult);\n\n    Set<byte[]> bexpected = new LinkedHashSet<byte[]>();\n    bexpected.add(bb);\n\n    assertEquals(bexpected, jedis.zrange(bfoo, 0, 100));\n  }\n\n  @Test\n  public void zremrangeByLex() {\n    jedis.zadd(\"foo\", 1, \"a\");\n    jedis.zadd(\"foo\", 1, \"b\");\n    jedis.zadd(\"foo\", 1, \"c\");\n    jedis.zadd(\"foo\", 1, \"aa\");\n\n    long result = jedis.zremrangeByLex(\"foo\", \"[aa\", \"(c\");\n\n    assertEquals(2, result);\n\n    Set<String> expected = new LinkedHashSet<String>();\n    expected.add(\"a\");\n    expected.add(\"c\");\n\n    assertEquals(expected, jedis.zrangeByLex(\"foo\", \"-\", \"+\"));\n  }\n\n  @Test\n  public void zremrangeByLexBinary() {\n    jedis.zadd(bfoo, 1, ba);\n    jedis.zadd(bfoo, 1, bc);\n    jedis.zadd(bfoo, 1, bb);\n\n    long bresult = jedis.zremrangeByLex(bfoo, bInclusiveB, bExclusiveC);\n\n    assertEquals(1, bresult);\n\n    Set<byte[]> bexpected = new LinkedHashSet<byte[]>();\n    bexpected.add(ba);\n    bexpected.add(bc);\n\n    assertEquals(bexpected, jedis.zrangeByLex(bfoo, bLexMinusInf, bLexPlusInf));\n  }\n\n  @Test\n  public void zunionstore() {\n    jedis.zadd(\"foo\", 1, \"a\");\n    jedis.zadd(\"foo\", 2, \"b\");\n    jedis.zadd(\"bar\", 2, \"a\");\n    jedis.zadd(\"bar\", 2, \"b\");\n\n    long result = jedis.zunionstore(\"dst\", \"foo\", \"bar\");\n\n    assertEquals(2, result);\n\n    Set<Tuple> expected = new LinkedHashSet<Tuple>();\n    expected.add(new Tuple(\"b\", new Double(4)));\n    expected.add(new Tuple(\"a\", new Double(3)));\n\n    assertEquals(expected, jedis.zrangeWithScores(\"dst\", 0, 100));\n\n    // Binary\n    jedis.zadd(bfoo, 1, ba);\n    jedis.zadd(bfoo, 2, bb);\n    jedis.zadd(bbar, 2, ba);\n    jedis.zadd(bbar, 2, bb);\n\n    long bresult = jedis.zunionstore(SafeEncoder.encode(\"dst\"), bfoo, bbar);\n\n    assertEquals(2, bresult);\n\n    Set<Tuple> bexpected = new LinkedHashSet<Tuple>();\n    bexpected.add(new Tuple(bb, new Double(4)));\n    bexpected.add(new Tuple(ba, new Double(3)));\n\n    assertEquals(bexpected, jedis.zrangeWithScores(SafeEncoder.encode(\"dst\"), 0, 100));\n  }\n\n  @Test\n  public void zunionstoreParams() {\n    jedis.zadd(\"foo\", 1, \"a\");\n    jedis.zadd(\"foo\", 2, \"b\");\n    jedis.zadd(\"bar\", 2, \"a\");\n    jedis.zadd(\"bar\", 2, \"b\");\n\n    ZParams params = new ZParams();\n    params.weights(2, 2.5);\n    params.aggregate(ZParams.Aggregate.SUM);\n    long result = jedis.zunionstore(\"dst\", params, \"foo\", \"bar\");\n\n    assertEquals(2, result);\n\n    Set<Tuple> expected = new LinkedHashSet<Tuple>();\n    expected.add(new Tuple(\"b\", new Double(9)));\n    expected.add(new Tuple(\"a\", new Double(7)));\n\n    assertEquals(expected, jedis.zrangeWithScores(\"dst\", 0, 100));\n\n    // Binary\n    jedis.zadd(bfoo, 1, ba);\n    jedis.zadd(bfoo, 2, bb);\n    jedis.zadd(bbar, 2, ba);\n    jedis.zadd(bbar, 2, bb);\n\n    ZParams bparams = new ZParams();\n    bparams.weights(2, 2.5);\n    bparams.aggregate(ZParams.Aggregate.SUM);\n    long bresult = jedis.zunionstore(SafeEncoder.encode(\"dst\"), bparams, bfoo, bbar);\n\n    assertEquals(2, bresult);\n\n    Set<Tuple> bexpected = new LinkedHashSet<Tuple>();\n    bexpected.add(new Tuple(bb, new Double(9)));\n    bexpected.add(new Tuple(ba, new Double(7)));\n\n    assertEquals(bexpected, jedis.zrangeWithScores(SafeEncoder.encode(\"dst\"), 0, 100));\n  }\n\n  @Test\n  public void zinterstore() {\n    jedis.zadd(\"foo\", 1, \"a\");\n    jedis.zadd(\"foo\", 2, \"b\");\n    jedis.zadd(\"bar\", 2, \"a\");\n\n    long result = jedis.zinterstore(\"dst\", \"foo\", \"bar\");\n\n    assertEquals(1, result);\n\n    Set<Tuple> expected = new LinkedHashSet<Tuple>();\n    expected.add(new Tuple(\"a\", new Double(3)));\n\n    assertEquals(expected, jedis.zrangeWithScores(\"dst\", 0, 100));\n\n    // Binary\n    jedis.zadd(bfoo, 1, ba);\n    jedis.zadd(bfoo, 2, bb);\n    jedis.zadd(bbar, 2, ba);\n\n    long bresult = jedis.zinterstore(SafeEncoder.encode(\"dst\"), bfoo, bbar);\n\n    assertEquals(1, bresult);\n\n    Set<Tuple> bexpected = new LinkedHashSet<Tuple>();\n    bexpected.add(new Tuple(ba, new Double(3)));\n\n    assertEquals(bexpected, jedis.zrangeWithScores(SafeEncoder.encode(\"dst\"), 0, 100));\n  }\n\n  @Test\n  public void zintertoreParams() {\n    jedis.zadd(\"foo\", 1, \"a\");\n    jedis.zadd(\"foo\", 2, \"b\");\n    jedis.zadd(\"bar\", 2, \"a\");\n\n    ZParams params = new ZParams();\n    params.weights(2, 2.5);\n    params.aggregate(ZParams.Aggregate.SUM);\n    long result = jedis.zinterstore(\"dst\", params, \"foo\", \"bar\");\n\n    assertEquals(1, result);\n\n    Set<Tuple> expected = new LinkedHashSet<Tuple>();\n    expected.add(new Tuple(\"a\", new Double(7)));\n\n    assertEquals(expected, jedis.zrangeWithScores(\"dst\", 0, 100));\n\n    // Binary\n    jedis.zadd(bfoo, 1, ba);\n    jedis.zadd(bfoo, 2, bb);\n    jedis.zadd(bbar, 2, ba);\n\n    ZParams bparams = new ZParams();\n    bparams.weights(2, 2.5);\n    bparams.aggregate(ZParams.Aggregate.SUM);\n    long bresult = jedis.zinterstore(SafeEncoder.encode(\"dst\"), bparams, bfoo, bbar);\n\n    assertEquals(1, bresult);\n\n    Set<Tuple> bexpected = new LinkedHashSet<Tuple>();\n    bexpected.add(new Tuple(ba, new Double(7)));\n\n    assertEquals(bexpected, jedis.zrangeWithScores(SafeEncoder.encode(\"dst\"), 0, 100));\n  }\n\n  @Test\n  public void tupleCompare() {\n    Tuple t1 = new Tuple(\"foo\", 1d);\n    Tuple t2 = new Tuple(\"bar\", 2d);\n\n    assertEquals(-1, t1.compareTo(t2));\n    assertEquals(1, t2.compareTo(t1));\n    assertEquals(0, t2.compareTo(t2));\n  }\n\n  @Test\n  public void zscan() {\n    jedis.zadd(\"foo\", 1, \"a\");\n    jedis.zadd(\"foo\", 2, \"b\");\n\n    ScanResult<Tuple> result = jedis.zscan(\"foo\", SCAN_POINTER_START);\n\n    assertEquals(SCAN_POINTER_START, result.getCursor());\n    assertFalse(result.getResult().isEmpty());\n\n    // binary\n    jedis.zadd(bfoo, 1, ba);\n    jedis.zadd(bfoo, 1, bb);\n\n    ScanResult<Tuple> bResult = jedis.zscan(bfoo, SCAN_POINTER_START_BINARY);\n\n    assertArrayEquals(SCAN_POINTER_START_BINARY, bResult.getCursorAsBytes());\n    assertFalse(bResult.getResult().isEmpty());\n  }\n\n  @Test\n  public void zscanMatch() {\n    ScanParams params = new ScanParams();\n    params.match(\"a*\");\n\n    jedis.zadd(\"foo\", 2, \"b\");\n    jedis.zadd(\"foo\", 1, \"a\");\n    jedis.zadd(\"foo\", 11, \"aa\");\n    ScanResult<Tuple> result = jedis.zscan(\"foo\", SCAN_POINTER_START, params);\n\n    assertEquals(SCAN_POINTER_START, result.getCursor());\n    assertFalse(result.getResult().isEmpty());\n\n    // binary\n    params = new ScanParams();\n    params.match(bbarstar);\n\n    jedis.zadd(bfoo, 2, bbar1);\n    jedis.zadd(bfoo, 1, bbar2);\n    jedis.zadd(bfoo, 11, bbar3);\n    ScanResult<Tuple> bResult = jedis.zscan(bfoo, SCAN_POINTER_START_BINARY, params);\n\n    assertArrayEquals(SCAN_POINTER_START_BINARY, bResult.getCursorAsBytes());\n    assertFalse(bResult.getResult().isEmpty());\n\n  }\n\n  @Test\n  public void zscanCount() {\n    ScanParams params = new ScanParams();\n    params.count(2);\n\n    jedis.zadd(\"foo\", 1, \"a1\");\n    jedis.zadd(\"foo\", 2, \"a2\");\n    jedis.zadd(\"foo\", 3, \"a3\");\n    jedis.zadd(\"foo\", 4, \"a4\");\n    jedis.zadd(\"foo\", 5, \"a5\");\n\n    ScanResult<Tuple> result = jedis.zscan(\"foo\", SCAN_POINTER_START, params);\n\n    assertFalse(result.getResult().isEmpty());\n\n    // binary\n    params = new ScanParams();\n    params.count(2);\n\n    jedis.zadd(bfoo, 2, bbar1);\n    jedis.zadd(bfoo, 1, bbar2);\n    jedis.zadd(bfoo, 11, bbar3);\n\n    ScanResult<Tuple> bResult = jedis.zscan(bfoo, SCAN_POINTER_START_BINARY, params);\n\n    assertFalse(bResult.getResult().isEmpty());\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/commands/SortingCommandsTest.java",
    "content": "package redis.clients.jedis.tests.commands;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.junit.Test;\n\nimport redis.clients.jedis.SortingParams;\n\npublic class SortingCommandsTest extends JedisCommandTestBase {\n  final byte[] bfoo = { 0x01, 0x02, 0x03, 0x04 };\n  final byte[] bbar1 = { 0x05, 0x06, 0x07, 0x08, '1' };\n  final byte[] bbar2 = { 0x05, 0x06, 0x07, 0x08, '2' };\n  final byte[] bbar3 = { 0x05, 0x06, 0x07, 0x08, '3' };\n  final byte[] bbar10 = { 0x05, 0x06, 0x07, 0x08, '1', '0' };\n  final byte[] bbarstar = { 0x05, 0x06, 0x07, 0x08, '*' };\n  final byte[] bcar1 = { 0x0A, 0x0B, 0x0C, 0x0D, '1' };\n  final byte[] bcar2 = { 0x0A, 0x0B, 0x0C, 0x0D, '2' };\n  final byte[] bcar10 = { 0x0A, 0x0B, 0x0C, 0x0D, '1', '0' };\n  final byte[] bcarstar = { 0x0A, 0x0B, 0x0C, 0x0D, '*' };\n  final byte[] b1 = { '1' };\n  final byte[] b2 = { '2' };\n  final byte[] b3 = { '3' };\n  final byte[] b10 = { '1', '0' };\n\n  @Test\n  public void sort() {\n    jedis.lpush(\"foo\", \"3\");\n    jedis.lpush(\"foo\", \"2\");\n    jedis.lpush(\"foo\", \"1\");\n\n    List<String> result = jedis.sort(\"foo\");\n\n    List<String> expected = new ArrayList<String>();\n    expected.add(\"1\");\n    expected.add(\"2\");\n    expected.add(\"3\");\n\n    assertEquals(expected, result);\n\n    // Binary\n    jedis.lpush(bfoo, b3);\n    jedis.lpush(bfoo, b2);\n    jedis.lpush(bfoo, b1);\n\n    List<byte[]> bresult = jedis.sort(bfoo);\n\n    List<byte[]> bexpected = new ArrayList<byte[]>();\n    bexpected.add(b1);\n    bexpected.add(b2);\n    bexpected.add(b3);\n\n    assertEquals(bexpected, bresult);\n  }\n\n  @Test\n  public void sortBy() {\n    jedis.lpush(\"foo\", \"2\");\n    jedis.lpush(\"foo\", \"3\");\n    jedis.lpush(\"foo\", \"1\");\n\n    jedis.set(\"bar1\", \"3\");\n    jedis.set(\"bar2\", \"2\");\n    jedis.set(\"bar3\", \"1\");\n\n    SortingParams sp = new SortingParams();\n    sp.by(\"bar*\");\n\n    List<String> result = jedis.sort(\"foo\", sp);\n\n    List<String> expected = new ArrayList<String>();\n    expected.add(\"3\");\n    expected.add(\"2\");\n    expected.add(\"1\");\n\n    assertEquals(expected, result);\n\n    // Binary\n    jedis.lpush(bfoo, b2);\n    jedis.lpush(bfoo, b3);\n    jedis.lpush(bfoo, b1);\n\n    jedis.set(bbar1, b3);\n    jedis.set(bbar2, b2);\n    jedis.set(bbar3, b1);\n\n    SortingParams bsp = new SortingParams();\n    bsp.by(bbarstar);\n\n    List<byte[]> bresult = jedis.sort(bfoo, bsp);\n\n    List<byte[]> bexpected = new ArrayList<byte[]>();\n    bexpected.add(b3);\n    bexpected.add(b2);\n    bexpected.add(b1);\n\n    assertEquals(bexpected, bresult);\n\n  }\n\n  @Test\n  public void sortDesc() {\n    jedis.lpush(\"foo\", \"3\");\n    jedis.lpush(\"foo\", \"2\");\n    jedis.lpush(\"foo\", \"1\");\n\n    SortingParams sp = new SortingParams();\n    sp.desc();\n\n    List<String> result = jedis.sort(\"foo\", sp);\n\n    List<String> expected = new ArrayList<String>();\n    expected.add(\"3\");\n    expected.add(\"2\");\n    expected.add(\"1\");\n\n    assertEquals(expected, result);\n\n    // Binary\n    jedis.lpush(bfoo, b3);\n    jedis.lpush(bfoo, b2);\n    jedis.lpush(bfoo, b1);\n\n    SortingParams bsp = new SortingParams();\n    bsp.desc();\n\n    List<byte[]> bresult = jedis.sort(bfoo, bsp);\n\n    List<byte[]> bexpected = new ArrayList<byte[]>();\n    bexpected.add(b3);\n    bexpected.add(b2);\n    bexpected.add(b1);\n\n    assertEquals(bexpected, bresult);\n  }\n\n  @Test\n  public void sortLimit() {\n    for (int n = 10; n > 0; n--) {\n      jedis.lpush(\"foo\", String.valueOf(n));\n    }\n\n    SortingParams sp = new SortingParams();\n    sp.limit(0, 3);\n\n    List<String> result = jedis.sort(\"foo\", sp);\n\n    List<String> expected = new ArrayList<String>();\n    expected.add(\"1\");\n    expected.add(\"2\");\n    expected.add(\"3\");\n\n    assertEquals(expected, result);\n\n    // Binary\n    jedis.rpush(bfoo, new byte[] { (byte) '4' });\n    jedis.rpush(bfoo, new byte[] { (byte) '3' });\n    jedis.rpush(bfoo, new byte[] { (byte) '2' });\n    jedis.rpush(bfoo, new byte[] { (byte) '1' });\n\n    SortingParams bsp = new SortingParams();\n    bsp.limit(0, 3);\n\n    List<byte[]> bresult = jedis.sort(bfoo, bsp);\n\n    List<byte[]> bexpected = new ArrayList<byte[]>();\n    bexpected.add(b1);\n    bexpected.add(b2);\n    bexpected.add(b3);\n\n    assertEquals(bexpected, bresult);\n  }\n\n  @Test\n  public void sortAlpha() {\n    jedis.lpush(\"foo\", \"1\");\n    jedis.lpush(\"foo\", \"2\");\n    jedis.lpush(\"foo\", \"10\");\n\n    SortingParams sp = new SortingParams();\n    sp.alpha();\n\n    List<String> result = jedis.sort(\"foo\", sp);\n\n    List<String> expected = new ArrayList<String>();\n    expected.add(\"1\");\n    expected.add(\"10\");\n    expected.add(\"2\");\n\n    assertEquals(expected, result);\n\n    // Binary\n    jedis.lpush(bfoo, b1);\n    jedis.lpush(bfoo, b2);\n    jedis.lpush(bfoo, b10);\n\n    SortingParams bsp = new SortingParams();\n    bsp.alpha();\n\n    List<byte[]> bresult = jedis.sort(bfoo, bsp);\n\n    List<byte[]> bexpected = new ArrayList<byte[]>();\n    bexpected.add(b1);\n    bexpected.add(b10);\n    bexpected.add(b2);\n\n    assertEquals(bexpected, bresult);\n  }\n\n  @Test\n  public void sortGet() {\n    jedis.lpush(\"foo\", \"1\");\n    jedis.lpush(\"foo\", \"2\");\n    jedis.lpush(\"foo\", \"10\");\n\n    jedis.set(\"bar1\", \"bar1\");\n    jedis.set(\"bar2\", \"bar2\");\n    jedis.set(\"bar10\", \"bar10\");\n\n    jedis.set(\"car1\", \"car1\");\n    jedis.set(\"car2\", \"car2\");\n    jedis.set(\"car10\", \"car10\");\n\n    SortingParams sp = new SortingParams();\n    sp.get(\"car*\", \"bar*\");\n\n    List<String> result = jedis.sort(\"foo\", sp);\n\n    List<String> expected = new ArrayList<String>();\n    expected.add(\"car1\");\n    expected.add(\"bar1\");\n    expected.add(\"car2\");\n    expected.add(\"bar2\");\n    expected.add(\"car10\");\n    expected.add(\"bar10\");\n\n    assertEquals(expected, result);\n\n    // Binary\n    jedis.lpush(bfoo, b1);\n    jedis.lpush(bfoo, b2);\n    jedis.lpush(bfoo, b10);\n\n    jedis.set(bbar1, bbar1);\n    jedis.set(bbar2, bbar2);\n    jedis.set(bbar10, bbar10);\n\n    jedis.set(bcar1, bcar1);\n    jedis.set(bcar2, bcar2);\n    jedis.set(bcar10, bcar10);\n\n    SortingParams bsp = new SortingParams();\n    bsp.get(bcarstar, bbarstar);\n\n    List<byte[]> bresult = jedis.sort(bfoo, bsp);\n\n    List<byte[]> bexpected = new ArrayList<byte[]>();\n    bexpected.add(bcar1);\n    bexpected.add(bbar1);\n    bexpected.add(bcar2);\n    bexpected.add(bbar2);\n    bexpected.add(bcar10);\n    bexpected.add(bbar10);\n\n    assertEquals(bexpected, bresult);\n  }\n\n  @Test\n  public void sortStore() {\n    jedis.lpush(\"foo\", \"1\");\n    jedis.lpush(\"foo\", \"2\");\n    jedis.lpush(\"foo\", \"10\");\n\n    long result = jedis.sort(\"foo\", \"result\");\n\n    List<String> expected = new ArrayList<String>();\n    expected.add(\"1\");\n    expected.add(\"2\");\n    expected.add(\"10\");\n\n    assertEquals(3, result);\n    assertEquals(expected, jedis.lrange(\"result\", 0, 1000));\n\n    // Binary\n    jedis.lpush(bfoo, b1);\n    jedis.lpush(bfoo, b2);\n    jedis.lpush(bfoo, b10);\n\n    byte[] bkresult = new byte[] { 0X09, 0x0A, 0x0B, 0x0C };\n    long bresult = jedis.sort(bfoo, bkresult);\n\n    List<byte[]> bexpected = new ArrayList<byte[]>();\n    bexpected.add(b1);\n    bexpected.add(b2);\n    bexpected.add(b10);\n\n    assertEquals(3, bresult);\n    assertEquals(bexpected, jedis.lrange(bkresult, 0, 1000));\n  }\n\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/commands/StringValuesCommandsTest.java",
    "content": "package redis.clients.jedis.tests.commands;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.junit.Test;\n\nimport redis.clients.jedis.exceptions.JedisDataException;\n\npublic class StringValuesCommandsTest extends JedisCommandTestBase {\n  @Test\n  public void setAndGet() {\n    String status = jedis.set(\"foo\", \"bar\");\n    assertEquals(\"OK\", status);\n\n    String value = jedis.get(\"foo\");\n    assertEquals(\"bar\", value);\n\n    assertEquals(null, jedis.get(\"bar\"));\n  }\n\n  @Test\n  public void getSet() {\n    String value = jedis.getSet(\"foo\", \"bar\");\n    assertEquals(null, value);\n    value = jedis.get(\"foo\");\n    assertEquals(\"bar\", value);\n  }\n\n  @Test\n  public void mget() {\n    List<String> values = jedis.mget(\"foo\", \"bar\");\n    List<String> expected = new ArrayList<String>();\n    expected.add(null);\n    expected.add(null);\n\n    assertEquals(expected, values);\n\n    jedis.set(\"foo\", \"bar\");\n\n    expected = new ArrayList<String>();\n    expected.add(\"bar\");\n    expected.add(null);\n    values = jedis.mget(\"foo\", \"bar\");\n\n    assertEquals(expected, values);\n\n    jedis.set(\"bar\", \"foo\");\n\n    expected = new ArrayList<String>();\n    expected.add(\"bar\");\n    expected.add(\"foo\");\n    values = jedis.mget(\"foo\", \"bar\");\n\n    assertEquals(expected, values);\n  }\n\n  @Test\n  public void setnx() {\n    long status = jedis.setnx(\"foo\", \"bar\");\n    assertEquals(1, status);\n    assertEquals(\"bar\", jedis.get(\"foo\"));\n\n    status = jedis.setnx(\"foo\", \"bar2\");\n    assertEquals(0, status);\n    assertEquals(\"bar\", jedis.get(\"foo\"));\n  }\n\n  @Test\n  public void setex() {\n    String status = jedis.setex(\"foo\", 20, \"bar\");\n    assertEquals(\"OK\", status);\n    long ttl = jedis.ttl(\"foo\");\n    assertTrue(ttl > 0 && ttl <= 20);\n  }\n\n  @Test\n  public void mset() {\n    String status = jedis.mset(\"foo\", \"bar\", \"bar\", \"foo\");\n    assertEquals(\"OK\", status);\n    assertEquals(\"bar\", jedis.get(\"foo\"));\n    assertEquals(\"foo\", jedis.get(\"bar\"));\n  }\n\n  @Test\n  public void msetnx() {\n    long status = jedis.msetnx(\"foo\", \"bar\", \"bar\", \"foo\");\n    assertEquals(1, status);\n    assertEquals(\"bar\", jedis.get(\"foo\"));\n    assertEquals(\"foo\", jedis.get(\"bar\"));\n\n    status = jedis.msetnx(\"foo\", \"bar1\", \"bar2\", \"foo2\");\n    assertEquals(0, status);\n    assertEquals(\"bar\", jedis.get(\"foo\"));\n    assertEquals(\"foo\", jedis.get(\"bar\"));\n  }\n\n  @Test(expected = JedisDataException.class)\n  public void incrWrongValue() {\n    jedis.set(\"foo\", \"bar\");\n    jedis.incr(\"foo\");\n  }\n\n  @Test\n  public void incr() {\n    long value = jedis.incr(\"foo\");\n    assertEquals(1, value);\n    value = jedis.incr(\"foo\");\n    assertEquals(2, value);\n  }\n\n  @Test(expected = JedisDataException.class)\n  public void incrByWrongValue() {\n    jedis.set(\"foo\", \"bar\");\n    jedis.incrBy(\"foo\", 2);\n  }\n\n  @Test\n  public void incrBy() {\n    long value = jedis.incrBy(\"foo\", 2);\n    assertEquals(2, value);\n    value = jedis.incrBy(\"foo\", 2);\n    assertEquals(4, value);\n  }\n\n  @Test(expected = JedisDataException.class)\n  public void incrByFloatWrongValue() {\n    jedis.set(\"foo\", \"bar\");\n    jedis.incrByFloat(\"foo\", 2d);\n  }\n\n  @Test(expected = JedisDataException.class)\n  public void decrWrongValue() {\n    jedis.set(\"foo\", \"bar\");\n    jedis.decr(\"foo\");\n  }\n\n  @Test\n  public void decr() {\n    long value = jedis.decr(\"foo\");\n    assertEquals(-1, value);\n    value = jedis.decr(\"foo\");\n    assertEquals(-2, value);\n  }\n\n  @Test(expected = JedisDataException.class)\n  public void decrByWrongValue() {\n    jedis.set(\"foo\", \"bar\");\n    jedis.decrBy(\"foo\", 2);\n  }\n\n  @Test\n  public void decrBy() {\n    long value = jedis.decrBy(\"foo\", 2);\n    assertEquals(-2, value);\n    value = jedis.decrBy(\"foo\", 2);\n    assertEquals(-4, value);\n  }\n\n  @Test\n  public void append() {\n    long value = jedis.append(\"foo\", \"bar\");\n    assertEquals(3, value);\n    assertEquals(\"bar\", jedis.get(\"foo\"));\n    value = jedis.append(\"foo\", \"bar\");\n    assertEquals(6, value);\n    assertEquals(\"barbar\", jedis.get(\"foo\"));\n  }\n\n  @Test\n  public void substr() {\n    jedis.set(\"s\", \"This is a string\");\n    assertEquals(\"This\", jedis.substr(\"s\", 0, 3));\n    assertEquals(\"ing\", jedis.substr(\"s\", -3, -1));\n    assertEquals(\"This is a string\", jedis.substr(\"s\", 0, -1));\n    assertEquals(\" string\", jedis.substr(\"s\", 9, 100000));\n  }\n\n  @Test\n  public void strlen() {\n    jedis.set(\"s\", \"This is a string\");\n    assertEquals(\"This is a string\".length(), jedis.strlen(\"s\").intValue());\n  }\n\n  @Test\n  public void incrLargeNumbers() {\n    long value = jedis.incr(\"foo\");\n    assertEquals(1, value);\n    assertEquals(1L + Integer.MAX_VALUE, (long) jedis.incrBy(\"foo\", Integer.MAX_VALUE));\n  }\n\n  @Test(expected = JedisDataException.class)\n  public void incrReallyLargeNumbers() {\n    jedis.set(\"foo\", Long.toString(Long.MAX_VALUE));\n    long value = jedis.incr(\"foo\");\n    assertEquals(Long.MIN_VALUE, value);\n  }\n\n  @Test\n  public void incrByFloat() {\n    double value = jedis.incrByFloat(\"foo\", 10.5);\n    assertEquals(10.5, value, 0.0);\n    value = jedis.incrByFloat(\"foo\", 0.1);\n    assertEquals(10.6, value, 0.0);\n  }\n\n  @Test\n  public void psetex() {\n    String status = jedis.psetex(\"foo\", 20000, \"bar\");\n    assertEquals(\"OK\", status);\n    long ttl = jedis.ttl(\"foo\");\n    assertTrue(ttl > 0 && ttl <= 20000);\n  }\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/commands/TransactionCommandsTest.java",
    "content": "package redis.clients.jedis.tests.commands;\n\nimport java.io.IOException;\nimport java.net.UnknownHostException;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Set;\n\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport redis.clients.jedis.Jedis;\nimport redis.clients.jedis.Pipeline;\nimport redis.clients.jedis.Protocol.Keyword;\nimport redis.clients.jedis.Response;\nimport redis.clients.jedis.Transaction;\nimport redis.clients.jedis.exceptions.JedisDataException;\n\npublic class TransactionCommandsTest extends JedisCommandTestBase {\n  final byte[] bfoo = { 0x01, 0x02, 0x03, 0x04 };\n  final byte[] bbar = { 0x05, 0x06, 0x07, 0x08 };\n  final byte[] ba = { 0x0A };\n  final byte[] bb = { 0x0B };\n\n  final byte[] bmykey = { 0x42, 0x02, 0x03, 0x04 };\n\n  Jedis nj;\n\n  @Before\n  public void setUp() throws Exception {\n    super.setUp();\n\n    nj = new Jedis(hnp.getHost(), hnp.getPort(), 500);\n    nj.connect();\n    nj.auth(\"foobared\");\n    nj.flushAll();\n  }\n\n  @Test\n  public void multi() {\n    Transaction trans = jedis.multi();\n\n    trans.sadd(\"foo\", \"a\");\n    trans.sadd(\"foo\", \"b\");\n    trans.scard(\"foo\");\n\n    List<Object> response = trans.exec();\n\n    List<Object> expected = new ArrayList<Object>();\n    expected.add(1L);\n    expected.add(1L);\n    expected.add(2L);\n    assertEquals(expected, response);\n\n    // Binary\n    trans = jedis.multi();\n\n    trans.sadd(bfoo, ba);\n    trans.sadd(bfoo, bb);\n    trans.scard(bfoo);\n\n    response = trans.exec();\n\n    expected = new ArrayList<Object>();\n    expected.add(1L);\n    expected.add(1L);\n    expected.add(2L);\n    assertEquals(expected, response);\n\n  }\n\n  @Test\n  public void watch() throws UnknownHostException, IOException {\n    jedis.watch(\"mykey\", \"somekey\");\n    Transaction t = jedis.multi();\n\n    nj.connect();\n    nj.auth(\"foobared\");\n    nj.set(\"mykey\", \"bar\");\n    nj.disconnect();\n\n    t.set(\"mykey\", \"foo\");\n    List<Object> resp = t.exec();\n    assertEquals(null, resp);\n    assertEquals(\"bar\", jedis.get(\"mykey\"));\n\n    // Binary\n    jedis.watch(bmykey, \"foobar\".getBytes());\n    t = jedis.multi();\n\n    nj.connect();\n    nj.auth(\"foobared\");\n    nj.set(bmykey, bbar);\n    nj.disconnect();\n\n    t.set(bmykey, bfoo);\n    resp = t.exec();\n    assertEquals(null, resp);\n    assertTrue(Arrays.equals(bbar, jedis.get(bmykey)));\n  }\n\n  @Test\n  public void unwatch() throws UnknownHostException, IOException {\n    jedis.watch(\"mykey\");\n    String val = jedis.get(\"mykey\");\n    val = \"foo\";\n    String status = jedis.unwatch();\n    assertEquals(\"OK\", status);\n    Transaction t = jedis.multi();\n\n    nj.connect();\n    nj.auth(\"foobared\");\n    nj.set(\"mykey\", \"bar\");\n    nj.disconnect();\n\n    t.set(\"mykey\", val);\n    List<Object> resp = t.exec();\n    assertEquals(1, resp.size());\n    assertEquals(\"OK\", resp.get(0));\n\n    // Binary\n    jedis.watch(bmykey);\n    byte[] bval = jedis.get(bmykey);\n    bval = bfoo;\n    status = jedis.unwatch();\n    assertEquals(Keyword.OK.name(), status);\n    t = jedis.multi();\n\n    nj.connect();\n    nj.auth(\"foobared\");\n    nj.set(bmykey, bbar);\n    nj.disconnect();\n\n    t.set(bmykey, bval);\n    resp = t.exec();\n    assertEquals(1, resp.size());\n    assertEquals(\"OK\", resp.get(0));\n  }\n\n  @Test(expected = JedisDataException.class)\n  public void validateWhenInMulti() {\n    jedis.multi();\n    jedis.ping();\n  }\n\n  @Test\n  public void discard() {\n    Transaction t = jedis.multi();\n    String status = t.discard();\n    assertEquals(\"OK\", status);\n  }\n\n  @Test\n  public void transactionResponse() {\n    jedis.set(\"string\", \"foo\");\n    jedis.lpush(\"list\", \"foo\");\n    jedis.hset(\"hash\", \"foo\", \"bar\");\n    jedis.zadd(\"zset\", 1, \"foo\");\n    jedis.sadd(\"set\", \"foo\");\n\n    Transaction t = jedis.multi();\n    Response<String> string = t.get(\"string\");\n    Response<String> list = t.lpop(\"list\");\n    Response<String> hash = t.hget(\"hash\", \"foo\");\n    Response<Set<String>> zset = t.zrange(\"zset\", 0, -1);\n    Response<String> set = t.spop(\"set\");\n    t.exec();\n\n    assertEquals(\"foo\", string.get());\n    assertEquals(\"foo\", list.get());\n    assertEquals(\"bar\", hash.get());\n    assertEquals(\"foo\", zset.get().iterator().next());\n    assertEquals(\"foo\", set.get());\n  }\n\n  @Test\n  public void transactionResponseBinary() {\n    jedis.set(\"string\", \"foo\");\n    jedis.lpush(\"list\", \"foo\");\n    jedis.hset(\"hash\", \"foo\", \"bar\");\n    jedis.zadd(\"zset\", 1, \"foo\");\n    jedis.sadd(\"set\", \"foo\");\n\n    Transaction t = jedis.multi();\n    Response<byte[]> string = t.get(\"string\".getBytes());\n    Response<byte[]> list = t.lpop(\"list\".getBytes());\n    Response<byte[]> hash = t.hget(\"hash\".getBytes(), \"foo\".getBytes());\n    Response<Set<byte[]>> zset = t.zrange(\"zset\".getBytes(), 0, -1);\n    Response<byte[]> set = t.spop(\"set\".getBytes());\n    t.exec();\n\n    assertArrayEquals(\"foo\".getBytes(), string.get());\n    assertArrayEquals(\"foo\".getBytes(), list.get());\n    assertArrayEquals(\"bar\".getBytes(), hash.get());\n    assertArrayEquals(\"foo\".getBytes(), zset.get().iterator().next());\n    assertArrayEquals(\"foo\".getBytes(), set.get());\n  }\n\n  @Test(expected = JedisDataException.class)\n  public void transactionResponseWithinPipeline() {\n    jedis.set(\"string\", \"foo\");\n\n    Transaction t = jedis.multi();\n    Response<String> string = t.get(\"string\");\n    string.get();\n    t.exec();\n  }\n\n  @Test\n  public void transactionResponseWithError() {\n    Transaction t = jedis.multi();\n    t.set(\"foo\", \"bar\");\n    Response<Set<String>> error = t.smembers(\"foo\");\n    Response<String> r = t.get(\"foo\");\n    List<Object> l = t.exec();\n    assertEquals(JedisDataException.class, l.get(1).getClass());\n    try {\n      error.get();\n      fail(\"We expect exception here!\");\n    } catch (JedisDataException e) {\n      // that is fine we should be here\n    }\n    assertEquals(r.get(), \"bar\");\n  }\n\n  @Test\n  public void execGetResponse() {\n    Transaction t = jedis.multi();\n\n    t.set(\"foo\", \"bar\");\n    t.smembers(\"foo\");\n    t.get(\"foo\");\n\n    List<Response<?>> lr = t.execGetResponse();\n    try {\n      lr.get(1).get();\n      fail(\"We expect exception here!\");\n    } catch (JedisDataException e) {\n      // that is fine we should be here\n    }\n    assertEquals(\"bar\", lr.get(2).get());\n  }\n\n  @Test\n  public void select() {\n    jedis.select(1);\n    jedis.set(\"foo\", \"bar\");\n    jedis.watch(\"foo\");\n    Transaction t = jedis.multi();\n    t.select(0);\n    t.set(\"bar\", \"foo\");\n\n    Jedis jedis2 = createJedis();\n    jedis2.select(1);\n    jedis2.set(\"foo\", \"bar2\");\n\n    List<Object> results = t.exec();\n\n    assertNull(results);\n  }\n\n  @Test\n  public void testResetStateWhenInMulti() {\n    jedis.auth(\"foobared\");\n\n    Transaction t = jedis.multi();\n    t.set(\"foooo\", \"barrr\");\n\n    jedis.resetState();\n    assertEquals(null, jedis.get(\"foooo\"));\n  }\n\n  @Test\n  public void testResetStateWhenInMultiWithinPipeline() {\n    jedis.auth(\"foobared\");\n\n    Pipeline p = jedis.pipelined();\n    p.multi();\n    p.set(\"foooo\", \"barrr\");\n\n    jedis.resetState();\n    assertEquals(null, jedis.get(\"foooo\"));\n  }\n\n  @Test\n  public void testResetStateWhenInWatch() {\n    jedis.watch(\"mykey\", \"somekey\");\n\n    // state reset : unwatch\n    jedis.resetState();\n\n    Transaction t = jedis.multi();\n\n    nj.connect();\n    nj.auth(\"foobared\");\n    nj.set(\"mykey\", \"bar\");\n    nj.disconnect();\n\n    t.set(\"mykey\", \"foo\");\n    List<Object> resp = t.exec();\n    assertNotNull(resp);\n    assertEquals(1, resp.size());\n    assertEquals(\"foo\", jedis.get(\"mykey\"));\n  }\n\n  @Test\n  public void testResetStateWithFullyExecutedTransaction() {\n    Jedis jedis2 = new Jedis(jedis.getClient().getHost(), jedis.getClient().getPort());\n    jedis2.auth(\"foobared\");\n\n    Transaction t = jedis2.multi();\n    t.set(\"mykey\", \"foo\");\n    t.get(\"mykey\");\n\n    List<Object> resp = t.exec();\n    assertNotNull(resp);\n    assertEquals(2, resp.size());\n\n    jedis2.resetState();\n    jedis2.close();\n  }\n\n  @Test\n  public void testCloseable() throws IOException {\n    // we need to test with fresh instance of Jedis\n    Jedis jedis2 = new Jedis(hnp.getHost(), hnp.getPort(), 500);\n    jedis2.auth(\"foobared\");\n\n    Transaction transaction = jedis2.multi();\n    transaction.set(\"a\", \"1\");\n    transaction.set(\"b\", \"2\");\n\n    transaction.close();\n\n    try {\n      transaction.exec();\n      fail(\"close should discard transaction\");\n    } catch (JedisDataException e) {\n      assertTrue(e.getMessage().contains(\"EXEC without MULTI\"));\n      // pass\n    }\n  }\n\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/commands/VariadicCommandsTest.java",
    "content": "package redis.clients.jedis.tests.commands;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.LinkedHashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\nimport org.junit.Test;\n\npublic class VariadicCommandsTest extends JedisCommandTestBase {\n  final byte[] bfoo = { 0x01, 0x02, 0x03, 0x04 };\n  final byte[] bbar = { 0x05, 0x06, 0x07, 0x08 };\n  final byte[] bcar = { 0x09, 0x0A, 0x0B, 0x0C };\n  final byte[] bfoo1 = { 0x01, 0x02, 0x03, 0x04, 0x0A };\n  final byte[] bfoo2 = { 0x01, 0x02, 0x03, 0x04, 0x0B };\n\n  @Test\n  public void hdel() {\n    Map<String, String> hash = new HashMap<String, String>();\n    hash.put(\"bar\", \"car\");\n    hash.put(\"car\", \"bar\");\n    hash.put(\"foo2\", \"bar\");\n    jedis.hmset(\"foo\", hash);\n\n    assertEquals(0, jedis.hdel(\"bar\", \"foo\", \"foo1\").intValue());\n    assertEquals(0, jedis.hdel(\"foo\", \"foo\", \"foo1\").intValue());\n    assertEquals(2, jedis.hdel(\"foo\", \"bar\", \"foo2\").intValue());\n    assertEquals(null, jedis.hget(\"foo\", \"bar\"));\n\n    // Binary\n    Map<byte[], byte[]> bhash = new HashMap<byte[], byte[]>();\n    bhash.put(bbar, bcar);\n    bhash.put(bcar, bbar);\n    bhash.put(bfoo2, bbar);\n    jedis.hmset(bfoo, bhash);\n\n    assertEquals(0, jedis.hdel(bbar, bfoo, bfoo1).intValue());\n    assertEquals(0, jedis.hdel(bfoo, bfoo, bfoo1).intValue());\n    assertEquals(2, jedis.hdel(bfoo, bbar, bfoo2).intValue());\n    assertEquals(null, jedis.hget(bfoo, bbar));\n\n  }\n\n  @Test\n  public void rpush() {\n    long size = jedis.rpush(\"foo\", \"bar\", \"foo\");\n    assertEquals(2, size);\n\n    List<String> expected = new ArrayList<String>();\n    expected.add(\"bar\");\n    expected.add(\"foo\");\n\n    List<String> values = jedis.lrange(\"foo\", 0, -1);\n    assertEquals(expected, values);\n\n    // Binary\n    size = jedis.rpush(bfoo, bbar, bfoo);\n    assertEquals(2, size);\n\n    List<byte[]> bexpected = new ArrayList<byte[]>();\n    bexpected.add(bbar);\n    bexpected.add(bfoo);\n\n    List<byte[]> bvalues = jedis.lrange(bfoo, 0, -1);\n    assertEquals(bexpected, bvalues);\n\n  }\n\n  @Test\n  public void lpush() {\n    long size = jedis.lpush(\"foo\", \"bar\", \"foo\");\n    assertEquals(2, size);\n\n    List<String> expected = new ArrayList<String>();\n    expected.add(\"foo\");\n    expected.add(\"bar\");\n\n    List<String> values = jedis.lrange(\"foo\", 0, -1);\n    assertEquals(expected, values);\n\n    // Binary\n    size = jedis.lpush(bfoo, bbar, bfoo);\n    assertEquals(2, size);\n\n    List<byte[]> bexpected = new ArrayList<byte[]>();\n    bexpected.add(bfoo);\n    bexpected.add(bbar);\n\n    List<byte[]> bvalues = jedis.lrange(bfoo, 0, -1);\n    assertEquals(bexpected, bvalues);\n\n  }\n\n  @Test\n  public void sadd() {\n    long status = jedis.sadd(\"foo\", \"bar\", \"foo1\");\n    assertEquals(2, status);\n\n    status = jedis.sadd(\"foo\", \"bar\", \"car\");\n    assertEquals(1, status);\n\n    status = jedis.sadd(\"foo\", \"bar\", \"foo1\");\n    assertEquals(0, status);\n\n    status = jedis.sadd(bfoo, bbar, bfoo1);\n    assertEquals(2, status);\n\n    status = jedis.sadd(bfoo, bbar, bcar);\n    assertEquals(1, status);\n\n    status = jedis.sadd(bfoo, bbar, bfoo1);\n    assertEquals(0, status);\n\n  }\n\n  @Test\n  public void zadd() {\n    Map<String, Double> scoreMembers = new HashMap<String, Double>();\n    scoreMembers.put(\"bar\", 1d);\n    scoreMembers.put(\"foo\", 10d);\n\n    long status = jedis.zadd(\"foo\", scoreMembers);\n    assertEquals(2, status);\n\n    scoreMembers.clear();\n    scoreMembers.put(\"car\", 0.1d);\n    scoreMembers.put(\"bar\", 2d);\n\n    status = jedis.zadd(\"foo\", scoreMembers);\n    assertEquals(1, status);\n\n    Map<byte[], Double> bscoreMembers = new HashMap<byte[], Double>();\n    bscoreMembers.put(bbar, 1d);\n    bscoreMembers.put(bfoo, 10d);\n\n    status = jedis.zadd(bfoo, bscoreMembers);\n    assertEquals(2, status);\n\n    bscoreMembers.clear();\n    bscoreMembers.put(bcar, 0.1d);\n    bscoreMembers.put(bbar, 2d);\n\n    status = jedis.zadd(bfoo, bscoreMembers);\n    assertEquals(1, status);\n\n  }\n\n  @Test\n  public void zrem() {\n    jedis.zadd(\"foo\", 1d, \"bar\");\n    jedis.zadd(\"foo\", 2d, \"car\");\n    jedis.zadd(\"foo\", 3d, \"foo1\");\n\n    long status = jedis.zrem(\"foo\", \"bar\", \"car\");\n\n    Set<String> expected = new LinkedHashSet<String>();\n    expected.add(\"foo1\");\n\n    assertEquals(2, status);\n    assertEquals(expected, jedis.zrange(\"foo\", 0, 100));\n\n    status = jedis.zrem(\"foo\", \"bar\", \"car\");\n    assertEquals(0, status);\n\n    status = jedis.zrem(\"foo\", \"bar\", \"foo1\");\n    assertEquals(1, status);\n\n    // Binary\n    jedis.zadd(bfoo, 1d, bbar);\n    jedis.zadd(bfoo, 2d, bcar);\n    jedis.zadd(bfoo, 3d, bfoo1);\n\n    status = jedis.zrem(bfoo, bbar, bcar);\n\n    Set<byte[]> bexpected = new LinkedHashSet<byte[]>();\n    bexpected.add(bfoo);\n\n    assertEquals(2, status);\n    assertEquals(bexpected, jedis.zrange(bfoo, 0, 100));\n\n    status = jedis.zrem(bfoo, bbar, bcar);\n    assertEquals(0, status);\n\n    status = jedis.zrem(bfoo, bbar, bfoo1);\n    assertEquals(1, status);\n\n  }\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/utils/ClientKillerUtil.java",
    "content": "package redis.clients.jedis.tests.utils;\n\nimport redis.clients.jedis.Jedis;\n\npublic class ClientKillerUtil {\n  public static void killClient(Jedis jedis, String clientName) {\n    for (String clientInfo : jedis.clientList().split(\"\\n\")) {\n      if (clientInfo.contains(\"name=\" + clientName)) {\n        // Ugly, but cmon, it's a test.\n        String[] hostAndPort = clientInfo.split(\" \")[1].split(\"=\")[1].split(\":\");\n        // It would be better if we kill the client by Id as it's safer but jedis doesn't implement\n        // the command yet.\n        jedis.clientKill(hostAndPort[0] + \":\" + hostAndPort[1]);\n      }\n    }\n  }\n\n  public static void tagClient(Jedis j, String name) {\n    j.clientSetname(name);\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/utils/FailoverAbortedException.java",
    "content": "package redis.clients.jedis.tests.utils;\n\npublic class FailoverAbortedException extends RuntimeException {\n  private static final long serialVersionUID = 1925110762858409954L;\n\n  public FailoverAbortedException(String message) {\n    super(message);\n  }\n\n  public FailoverAbortedException(Throwable cause) {\n    super(cause);\n  }\n\n  public FailoverAbortedException(String message, Throwable cause) {\n    super(message, cause);\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/utils/JedisClusterCRC16Test.java",
    "content": "package redis.clients.jedis.tests.utils;\n\nimport static org.junit.Assert.assertEquals;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Map.Entry;\n\nimport org.junit.Test;\n\nimport redis.clients.util.JedisClusterCRC16;\nimport redis.clients.util.SafeEncoder;\n\npublic class JedisClusterCRC16Test {\n\n  @Test\n  public void testGetCRC16() throws Exception {\n    Map<String, Integer> solutions = prepareSolutionSet();\n\n    for (Entry<String, Integer> entry : solutions.entrySet()) {\n      // string version\n      assertEquals(entry.getValue().intValue(), JedisClusterCRC16.getCRC16(entry.getKey()));\n\n      // byte array version\n      assertEquals(entry.getValue().intValue(),\n        JedisClusterCRC16.getCRC16(SafeEncoder.encode(entry.getKey())));\n    }\n  }\n\n  @Test\n  public void testGetSlot() {\n    assertEquals(7186, JedisClusterCRC16.getSlot(\"51\"));\n  }\n\n  private Map<String, Integer> prepareSolutionSet() {\n    Map<String, Integer> solutionMap = new HashMap<String, Integer>();\n    solutionMap.put(\"\", 0x0);\n    solutionMap.put(\"123456789\", 0x31C3);\n    solutionMap.put(\"sfger132515\", 0xA45C);\n    solutionMap.put(\"hae9Napahngaikeethievubaibogiech\", 0x58CE);\n    solutionMap.put(\"AAAAAAAAAAAAAAAAAAAAAA\", 0x92cd);\n    solutionMap.put(\"Hello, World!\", 0x4FD6);\n    return solutionMap;\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/utils/JedisClusterTestUtil.java",
    "content": "package redis.clients.jedis.tests.utils;\n\nimport redis.clients.jedis.HostAndPort;\nimport redis.clients.jedis.Jedis;\nimport redis.clients.jedis.exceptions.JedisException;\n\npublic class JedisClusterTestUtil {\n  public static void waitForClusterReady(Jedis... nodes) throws InterruptedException {\n    boolean clusterOk = false;\n    while (!clusterOk) {\n      boolean isOk = true;\n      for (Jedis node : nodes) {\n        if (!node.clusterInfo().split(\"\\n\")[0].contains(\"ok\")) {\n          isOk = false;\n          break;\n        }\n      }\n\n      if (isOk) {\n        clusterOk = true;\n      }\n\n      Thread.sleep(50);\n    }\n  }\n\n  public static String getNodeId(String infoOutput) {\n    for (String infoLine : infoOutput.split(\"\\n\")) {\n      if (infoLine.contains(\"myself\")) {\n        return infoLine.split(\" \")[0];\n      }\n    }\n    return \"\";\n  }\n\n  public static String getNodeId(String infoOutput, HostAndPort node) {\n\n    for (String infoLine : infoOutput.split(\"\\n\")) {\n      if (infoLine.contains(node.toString())) {\n        return infoLine.split(\" \")[0];\n      }\n    }\n    return \"\";\n  }\n\n  public static void assertNodeIsKnown(Jedis node, String targetNodeId, int timeoutMs) {\n    assertNodeRecognizedStatus(node, targetNodeId, true, timeoutMs);\n  }\n\n  public static void assertNodeIsUnknown(Jedis node, String targetNodeId, int timeoutMs) {\n    assertNodeRecognizedStatus(node, targetNodeId, false, timeoutMs);\n  }\n\n  private static void assertNodeRecognizedStatus(Jedis node, String targetNodeId,\n      boolean shouldRecognized, int timeoutMs) {\n    int sleepInterval = 100;\n    for (int sleepTime = 0; sleepTime <= timeoutMs; sleepTime += sleepInterval) {\n      boolean known = isKnownNode(node, targetNodeId);\n      if (shouldRecognized == known) return;\n\n      try {\n        Thread.sleep(sleepInterval);\n      } catch (InterruptedException e) {\n      }\n    }\n\n    throw new JedisException(\"Node recognize check error\");\n  }\n\n  private static boolean isKnownNode(Jedis node, String nodeId) {\n    String infoOutput = node.clusterNodes();\n    for (String infoLine : infoOutput.split(\"\\n\")) {\n      if (infoLine.contains(nodeId)) {\n        return true;\n      }\n    }\n    return false;\n  }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/utils/JedisSentinelTestUtil.java",
    "content": "package redis.clients.jedis.tests.utils;\n\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport redis.clients.jedis.HostAndPort;\nimport redis.clients.jedis.Jedis;\nimport redis.clients.jedis.JedisPubSub;\n\npublic class JedisSentinelTestUtil {\n  public static HostAndPort waitForNewPromotedMaster(final String masterName,\n      final Jedis sentinelJedis, final Jedis commandJedis) throws InterruptedException {\n\n    final AtomicReference<String> newmaster = new AtomicReference<String>(\"\");\n\n    sentinelJedis.psubscribe(new JedisPubSub() {\n\n      @Override\n      public void onPMessage(String pattern, String channel, String message) {\n        if (channel.equals(\"+switch-master\")) {\n          newmaster.set(message);\n          punsubscribe();\n        } else if (channel.startsWith(\"-failover-abort\")) {\n          punsubscribe();\n          throw new FailoverAbortedException(\n              \"Unfortunately sentinel cannot failover... reason(channel) : \" + channel\n                  + \" / message : \" + message);\n        }\n      }\n\n      @Override\n      public void onPSubscribe(String pattern, int subscribedChannels) {\n        commandJedis.sentinelFailover(masterName);\n      }\n    }, \"*\");\n\n    String[] chunks = newmaster.get().split(\" \");\n    HostAndPort newMaster = new HostAndPort(chunks[3], Integer.parseInt(chunks[4]));\n\n    return newMaster;\n  }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-jedis/src/test/java/redis/clients/jedis/tests/utils/JedisURIHelperTest.java",
    "content": "package redis.clients.jedis.tests.utils;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNull;\n\nimport java.net.URI;\nimport java.net.URISyntaxException;\n\nimport org.junit.Test;\n\nimport redis.clients.util.JedisURIHelper;\n\npublic class JedisURIHelperTest {\n\n  @Test\n  public void shouldGetPasswordFromURIWithCredentials() throws URISyntaxException {\n    URI uri = new URI(\"redis://user:password@host:9000/0\");\n    assertEquals(\"password\", JedisURIHelper.getPassword(uri));\n  }\n\n  @Test\n  public void shouldReturnNullIfURIDoesNotHaveCredentials() throws URISyntaxException {\n    URI uri = new URI(\"redis://host:9000/0\");\n    assertNull(JedisURIHelper.getPassword(uri));\n  }\n\n  @Test\n  public void shouldGetDbFromURIWithCredentials() throws URISyntaxException {\n    URI uri = new URI(\"redis://user:password@host:9000/3\");\n    assertEquals(3, JedisURIHelper.getDBIndex(uri));\n  }\n\n  @Test\n  public void shouldGetDbFromURIWithoutCredentials() throws URISyntaxException {\n    URI uri = new URI(\"redis://host:9000/4\");\n    assertEquals(4, JedisURIHelper.getDBIndex(uri));\n  }\n\n  @Test\n  public void shouldGetDefaultDbFromURIIfNoDbWasSpecified() throws URISyntaxException {\n    URI uri = new URI(\"redis://host:9000\");\n    assertEquals(0, JedisURIHelper.getDBIndex(uri));\n  }\n\n  @Test\n  public void shouldValidateInvalidURIs() throws URISyntaxException {\n    assertFalse(JedisURIHelper.isValid(new URI(\"host:9000\")));\n    assertFalse(JedisURIHelper.isValid(new URI(\"user:password@host:9000/0\")));\n    assertFalse(JedisURIHelper.isValid(new URI(\"host:9000/0\")));\n    assertFalse(JedisURIHelper.isValid(new URI(\"redis://host/0\")));\n  }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-basic/.gitignore",
    "content": ".idea/\n*.iml\n.svn/*\ntarget/\n*.class\n.settings\n.classpath\n.project\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-basic/pom.xml",
    "content": "<?xml version=\"1.0\"?>\n<project\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\"\n\txmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n\t<modelVersion>4.0.0</modelVersion>\n\t<parent>\n\t\t<groupId>com.sohu.tv</groupId>\n\t\t<artifactId>cachecloud-open-client</artifactId>\n\t\t<version>1.0-SNAPSHOT</version>\n\t</parent>\n\t<groupId>com.sohu.tv</groupId>\n\t<artifactId>cachecloud-open-client-basic</artifactId>\n\t<version>1.0-SNAPSHOT</version>\n\t<name>cachecloud-open-client-basic</name>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.slf4j</groupId>\n\t\t\t<artifactId>slf4j-api</artifactId>\n\t\t\t<scope>compile</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t  <groupId>com.alibaba</groupId>\n\t\t  <artifactId>fastjson</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>ch.qos.logback</groupId>\n\t\t\t<artifactId>logback-classic</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>junit</groupId>\n\t\t\t<artifactId>junit</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t</dependencies>\n</project>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-basic/src/main/java/com/sohu/tv/cache/client/common/jmx/CachecloudDataWatcher.java",
    "content": "package com.sohu.tv.cache.client.common.jmx;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.sohu.tv.jedis.stat.data.UsefulDataCollector;\nimport com.sohu.tv.jedis.stat.model.CostTimeDetailStatKey;\nimport com.sohu.tv.jedis.stat.model.ExceptionModel;\nimport com.sohu.tv.jedis.stat.model.ValueLengthModel;\nimport com.sohu.tv.jedis.stat.utils.AtomicLongMap;\n\nimport java.util.*;\nimport java.util.Map.Entry;\n\n/**\n * 监控cachecloud数据收集\n * @author leifu\n * @Date 2015年1月28日\n * @Time 下午2:02:04\n */\npublic class CachecloudDataWatcher implements CachecloudDataWatcherMBean {\n\tprivate final Logger logger = LoggerFactory.getLogger(this.getClass());\n\n\t@Override\n\tpublic Map<String, Map<Integer, Long>> getCostTimeMap() {\n\t\tMap<CostTimeDetailStatKey, AtomicLongMap<Integer>> map = UsefulDataCollector.getDataCostTimeMapAll();\n\t\tif (map == null || map.isEmpty()) {\n\t\t\treturn Collections.emptyMap();\n\t\t}\n\n\t\tMap<String, Map<Integer, Long>> result = new HashMap<String, Map<Integer, Long>>();\n\t\tfor (Entry<CostTimeDetailStatKey, AtomicLongMap<Integer>> entry : map.entrySet()) {\n\t\t\tCostTimeDetailStatKey costTimeDetailStatKey = entry.getKey();\n\t\t\tString key = costTimeDetailStatKey.getUiqueKey();\n\t\t\tresult.put(key, entry.getValue().asMap());\n\t\t}\n\n\t\treturn result;\n\t}\n\t\n\t@Override\n    public Map<String, Long> getCostTimeGroupByMinute() {\n        Map<CostTimeDetailStatKey, AtomicLongMap<Integer>> map = UsefulDataCollector.getDataCostTimeMapAll();\n        if (map == null || map.isEmpty()) {\n            return Collections.emptyMap();\n        }\n        Map<String, Long> result = new HashMap<String, Long>();\n        for (Entry<CostTimeDetailStatKey, AtomicLongMap<Integer>> entry : map.entrySet()) {\n            String minute = entry.getKey().getCurrentMinute();\n            Long totalCount = 0L;\n            for (Long count : entry.getValue().asMap().values()) {\n                totalCount += count;\n            }\n            if (result.containsKey(minute)) {\n                result.put(minute, result.get(minute) + totalCount);\n            } else {\n                result.put(minute, totalCount);\n            }\n        }\n        return result;\n    }\n\t\n\t@Override\n    public Map<String, Map<String, Long>> getCostTimeGroupByMinuteAndCommand() {\n        Map<CostTimeDetailStatKey, AtomicLongMap<Integer>> map = UsefulDataCollector.getDataCostTimeMapAll();\n        if (map == null || map.isEmpty()) {\n            return Collections.emptyMap();\n        }\n        // 20150130113700_127.0.0.1:6381_del={0=4, 1=4}\n        Map<String, Map<String, Long>> result = new HashMap<String, Map<String, Long>>();\n        for (Entry<CostTimeDetailStatKey, AtomicLongMap<Integer>> entry : map.entrySet()) {\n            String minute = entry.getKey().getCurrentMinute();\n            String command = entry.getKey().getCommand();\n            Long totalCount = 0L;\n            for (Long count : entry.getValue().asMap().values()) {\n                totalCount += count;\n            }\n            if (result.containsKey(minute)) {\n                Map<String, Long> tempMap = result.get(minute);\n                if (tempMap.containsKey(command)) {\n                    tempMap.put(command, tempMap.get(command) + totalCount);\n                } else {\n                    tempMap.put(command, totalCount);\n                }\n                result.put(minute, tempMap);\n            } else {\n                Map<String, Long> tempMap = new HashMap<String, Long>();\n                tempMap.put(command, totalCount);\n                result.put(minute, tempMap);\n            }\n        }\n        return result;\n    }\n\n\t@Override\n\tpublic Map<String, Map<String, Long>> getExceptionMap() {\n\t\tMap<String, AtomicLongMap<ExceptionModel>> map = UsefulDataCollector.getDataExceptionMapAll();\n\t\tif (map == null || map.isEmpty()) {\n\t\t\treturn Collections.emptyMap();\n\t\t}\n\n\t\tMap<String, Map<String, Long>> result = new HashMap<String, Map<String, Long>>();\n\t\tfor (Entry<String, AtomicLongMap<ExceptionModel>> entry : map.entrySet()) {\n\t\t\tString key = entry.getKey();\n\t\t\tMap<String, Long> tempMap = new HashMap<String, Long>();\n\t\t\tfor (Entry<ExceptionModel, Long> exceptionEntry : entry.getValue().asMap().entrySet()) {\n\t\t\t\ttempMap.put(exceptionEntry.getKey().getUniqKey(), exceptionEntry.getValue());\n\t\t\t}\n\t\t\tresult.put(key, tempMap);\n\t\t}\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic Map<String, Map<String, Long>> getValueLengthMap() {\n\t\tMap<String, AtomicLongMap<ValueLengthModel>> map = UsefulDataCollector\n\t\t\t\t.getDataValueLengthDistributeMapAll();\n\t\tif (map == null || map.isEmpty()) {\n\t\t\treturn Collections.emptyMap();\n\t\t}\n\n\t\tMap<String, Map<String, Long>> result = new HashMap<String, Map<String, Long>>();\n\t\tfor (Entry<String, AtomicLongMap<ValueLengthModel>> entry : map.entrySet()) {\n\t\t\tString key = entry.getKey();\n\t\t\tMap<String, Long> tempMap = new HashMap<String, Long>();\n\t\t\tfor (Entry<ValueLengthModel, Long> valueLengthEntry : entry.getValue().asMap().entrySet()) {\n\t\t\t\ttempMap.put(valueLengthEntry.getKey().getUniqKey(), valueLengthEntry.getValue());\n\t\t\t}\n\t\t\tresult.put(key, tempMap);\n\t\t}\n\t\treturn result;\n\t}\n\n    @Override\n    public Map<String, Map<Long, Long>> getCollectionCostTimeMap() {\n        Map<String, AtomicLongMap<Long>> map = UsefulDataCollector.getCollectionCostTimeMapAll();\n        if (map == null || map.isEmpty()) {\n            return Collections.emptyMap();\n        }\n        Map<String, Map<Long, Long>> result = new HashMap<String, Map<Long, Long>>();\n        for (Entry<String, AtomicLongMap<Long>> entry : map.entrySet()) {\n            String key = entry.getKey();\n            result.put(key, entry.getValue().asMap());\n        }\n        return result;\n    }\n\n\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-basic/src/main/java/com/sohu/tv/cache/client/common/jmx/CachecloudDataWatcherMBean.java",
    "content": "package com.sohu.tv.cache.client.common.jmx;\n\nimport java.util.Map;\n\n\n/**\n * 监控cachecloud数据收集\n * @author leifu\n * @Date 2015年1月25日\n * @Time 上午10:30:13\n */\npublic interface CachecloudDataWatcherMBean {\n\n    public Map<String, Map<Integer,Long>> getCostTimeMap();\n    \n    public Map<String, Long> getCostTimeGroupByMinute();\n    \n    public Map<String, Map<String,Long>> getCostTimeGroupByMinuteAndCommand();\n\n    public Map<String, Map<String,Long>> getExceptionMap();\n    \n    public Map<String, Map<String,Long>> getValueLengthMap();\n    \n    /**\n     * 收集数据本身的耗时\n     * @return\n     */\n    public Map<String, Map<Long,Long>> getCollectionCostTimeMap();\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-basic/src/main/java/com/sohu/tv/cachecloud/client/basic/component/EmailComponent.java",
    "content": "package com.sohu.tv.cachecloud.client.basic.component;\n\nimport java.util.List;\n\n/**\n * 邮件报警\n * @author leifu\n * @Date 2015年2月2日\n * @Time 上午11:37:39\n */\npublic interface EmailComponent {\n    \n\t/**\n     * 发送邮件\n     * @param title\n     * @param content\n     * @param emails\n     * @param cc(抄送)\n     * @return\n     */\n    boolean sendMail(String title, String content, List<String> emailList, List<String> ccList);\n\t\n\t\n    /**\n     * 发送邮件\n     * @param title\n     * @param content\n     * @param emails\n     * @return\n     */\n    boolean sendMail(String title, String content, List<String> emailList);\n    \n    /**\n     * 发送管理员邮件\n     * @param title\n     * @param content\n     * @return\n     */\n    boolean sendMailToAdmin(String title, String content);\n\n    \n    /**\n     * 获取管理员邮件组\n     * @return\n     */\n    String getAdminEmail();\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-basic/src/main/java/com/sohu/tv/cachecloud/client/basic/component/EmailComponentImpl.java",
    "content": "package com.sohu.tv.cachecloud.client.basic.component;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * 发送邮件服务\n * @author leifu\n * @Date 2015年2月2日\n * @Time 上午11:30:38\n */\npublic class EmailComponentImpl implements EmailComponent {\n    private final Logger logger = LoggerFactory.getLogger(EmailComponentImpl.class);\n\n    /**\n     * 管理员邮件列表\n     */\n    private String adminEmail;\n\n    @Override\n    public boolean sendMailToAdmin(String title, String content) {\n        return sendMail(title, content, Arrays.asList(adminEmail));\n    }\n\n    @Override\n    public boolean sendMail(String title, String content, List<String> emailList) {\n        return sendMail(title, content, emailList, null);\n    }\n    \n    @Override\n\tpublic boolean sendMail(String title, String content, List<String> emailList, List<String> ccList) {\n        /**\n         * your company send short message codes\n         */\n        return true;\n\t}\n\n    public void setAdminEmail(String adminEmail) {\n        this.adminEmail = adminEmail;\n    }\n\n\t@Override\n\tpublic String getAdminEmail() {\n\t\treturn adminEmail;\n\t}\n\t\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-basic/src/main/java/com/sohu/tv/cachecloud/client/basic/component/MobileAlertComponent.java",
    "content": "package com.sohu.tv.cachecloud.client.basic.component;\n\n\nimport java.util.List;\n\n/**\n * 短信报警\n * @author leifu\n * @Date 2014年11月26日\n * @Time 上午10:11:26\n */\npublic interface MobileAlertComponent {\n    \n    /**\n     * 发短信给管理员\n     * @param message\n     */\n    void sendPhoneToAdmin(String message);\n    \n    /**\n     * 发短信给指定号码列表\n     * @param message\n     * @param phoneList\n     */\n    void sendPhone(String message, List<String> phoneList);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-basic/src/main/java/com/sohu/tv/cachecloud/client/basic/component/MobileAlertComponentImpl.java",
    "content": "package com.sohu.tv.cachecloud.client.basic.component;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.sohu.tv.cachecloud.client.basic.util.StringUtil;\n\n/**\n * 手机短信报警\n * @author leifu\n * @Date 2015年2月2日\n * @Time 上午11:36:01\n */\npublic class MobileAlertComponentImpl implements MobileAlertComponent {\n\n    private final Logger logger = LoggerFactory.getLogger(MobileAlertComponentImpl.class);\n    /**\n     * 管理员电话\n     */\n    private String adminPhones;\n\n    private final static String COMMA = \",\";\n    \n\n    @Override\n    public void sendPhoneToAdmin(String message) {\n        if (StringUtil.isBlank(message) || StringUtil.isBlank(adminPhones)) {\n            logger.error(\"message is {}, maybe empty or adminPhones is {}, maybe empty\", message, adminPhones);\n        }\n        sendPhone(message, Arrays.asList(adminPhones.split(COMMA)));\n    }\n\n    @Override\n    public void sendPhone(String message, List<String> phoneList) {\n        /**\n         * your company send short message codes\n         */\n    }\n\n    public void setAdminPhones(String adminPhones) {\n        this.adminPhones = adminPhones;\n    }\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-basic/src/main/java/com/sohu/tv/cachecloud/client/basic/exception/CacheCloudClientHttpUtilsException.java",
    "content": "package com.sohu.tv.cachecloud.client.basic.exception;\n\n/**\n * http工具异常类\n * @author leifu\n * @Date 2015-1-31\n * @Time 下午6:41:22\n */\npublic class CacheCloudClientHttpUtilsException extends RuntimeException {\n\n\tprivate static final long serialVersionUID = 1087328658524130263L;\n\n\tpublic CacheCloudClientHttpUtilsException(String message) {\n\t\tsuper(message);\n\t}\n\n\tpublic CacheCloudClientHttpUtilsException(Throwable e) {\n\t\tsuper(e);\n\t}\n\n\tpublic CacheCloudClientHttpUtilsException(String message, Throwable cause) {\n\t\tsuper(message, cause);\n\t}\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-basic/src/main/java/com/sohu/tv/cachecloud/client/basic/heartbeat/ClientStatusEnum.java",
    "content": "package com.sohu.tv.cachecloud.client.basic.heartbeat;\n\n/**\n * 检查客户端的版本是否ok的枚举\n *\n * @author: lingguo\n * @time: 2014/10/22 10:13\n */\npublic enum ClientStatusEnum {\n    GOOD(1),\n    WARN(0),\n    ERROR(-1);\n\n    int status;\n\n    ClientStatusEnum(int status) {\n        this.status = status;\n    }\n\n    public int getStatus() {\n        return status;\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-basic/src/main/java/com/sohu/tv/cachecloud/client/basic/heartbeat/HeartbeatInfo.java",
    "content": "package com.sohu.tv.cachecloud.client.basic.heartbeat;\n\n/**\n * 服务器返回给客户端的应用信息\n * \n * @author leifu\n * @Date 2014年6月5日\n * @Time 上午10:46:57\n */\npublic class HeartbeatInfo {\n\t\n\t/**\n\t * 应用id\n\t */\n\tprivate long appId;\n\t\n\t/**\n\t * 实例个数\n\t */\n\tprivate int shardNum;\n\t\n\t/**\n\t * 分配信息\n\t */\n\tprivate String shardInfo;\n\t\n\t/**\n\t * 应用状态\n\t */\n\tprivate int status;\n\t\n\t/**\n\t * 消息\n\t */\n\tprivate String message;\n\n\tpublic long getAppId() {\n\t\treturn appId;\n\t}\n\n\tpublic void setAppId(long appId) {\n\t\tthis.appId = appId;\n\t}\n\n\tpublic int getShardNum() {\n\t\treturn shardNum;\n\t}\n\n\tpublic void setShardNum(int shardNum) {\n\t\tthis.shardNum = shardNum;\n\t}\n\n\tpublic String getShardInfo() {\n\t\treturn shardInfo;\n\t}\n\n\tpublic void setShardInfo(String shardInfo) {\n\t\tthis.shardInfo = shardInfo;\n\t}\n\n\tpublic int getStatus() {\n\t\treturn status;\n\t}\n\n\tpublic void setStatus(int status) {\n\t\tthis.status = status;\n\t}\n\n\tpublic String getMessage() {\n\t\treturn message;\n\t}\n\n\tpublic void setMessage(String message) {\n\t\tthis.message = message;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"HeartbeatInfo{\" + \"appId=\" + appId + \", shardNum=\" + shardNum\n\t\t\t\t+ \", shardInfo='\" + shardInfo + '\\'' + \", status=\" + status\n\t\t\t\t+ \", message='\" + message + '\\'' + '}';\n\t}\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-basic/src/main/java/com/sohu/tv/cachecloud/client/basic/util/ConstUtils.java",
    "content": "package com.sohu.tv.cachecloud.client.basic.util;\n\nimport java.util.ResourceBundle;\n\n/**\n * 客户端常量\n * \n * @author leifu\n * @Date 2014年6月21日\n * @Time 上午10:54:34\n */\npublic class ConstUtils {\n\n    /**\n     * http连接和读取超时\n     */\n    public static final int HTTP_CONN_TIMEOUT;\n    public static final int HTTP_SOCKET_TIMEOUT;\n\n    /**\n     * 客户端版本信息\n     */\n    public static final String CLIENT_VERSION;\n\n    /**\n     * 上报域名和对应各个类型redis的rest url.\n     */\n    public static final String DOMAIN_URL;\n    public static final String REDIS_CLUSTER_URL;\n    public static final String REDIS_SENTINEL_URL;\n    public static final String REDIS_STANDALONE_URL;\n    public static final String CACHECLOUD_REPORT_URL;\n\n    static {\n        ResourceBundle rb = ResourceBundle.getBundle(\"cacheCloudClient\");\n\n        HTTP_CONN_TIMEOUT = Integer.valueOf(rb.getString(\"http_conn_timeout\"));\n        HTTP_SOCKET_TIMEOUT = Integer.valueOf(rb.getString(\"http_socket_timeout\"));\n\n        CLIENT_VERSION = rb.getString(\"client_version\");\n\n        DOMAIN_URL = rb.getString(\"domain_url\");\n        REDIS_CLUSTER_URL = DOMAIN_URL + rb.getString(\"redis_cluster_suffix\") + CLIENT_VERSION;\n        REDIS_SENTINEL_URL = DOMAIN_URL + rb.getString(\"redis_sentinel_suffix\") + CLIENT_VERSION;\n        REDIS_STANDALONE_URL = DOMAIN_URL + rb.getString(\"redis_standalone_suffix\") + CLIENT_VERSION;\n        CACHECLOUD_REPORT_URL = DOMAIN_URL + rb.getString(\"cachecloud_report_url\");\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-basic/src/main/java/com/sohu/tv/cachecloud/client/basic/util/DateUtils.java",
    "content": "package com.sohu.tv.cachecloud.client.basic.util;\n\nimport java.text.SimpleDateFormat;\nimport java.util.Calendar;\nimport java.util.Date;\n\n/**\n * 简易DateUtils\n * \n * @author leifu\n * @Date 2015年1月15日\n * @Time 上午11:43:31\n */\npublic class DateUtils {\n\n    public static String formatDate(Date date, String format) {\n        SimpleDateFormat sdf = new SimpleDateFormat(format);\n        return sdf.format(date);\n    }\n\n    public static Date add(Date date, int calendarField, int amount) {\n        if (date == null) {\n            throw new IllegalArgumentException(\"The date must not be null\");\n        }\n        Calendar c = Calendar.getInstance();\n        c.setTime(date);\n        c.add(calendarField, amount);\n        return c.getTime();\n    }\n\n    public static Date addMinutes(Date date, int amount) {\n        return add(date, Calendar.MINUTE, amount);\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-basic/src/main/java/com/sohu/tv/cachecloud/client/basic/util/HttpUtils.java",
    "content": "package com.sohu.tv.cachecloud.client.basic.util;\n\nimport java.io.BufferedInputStream;\nimport java.io.BufferedReader;\nimport java.io.ByteArrayOutputStream;\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\nimport java.io.UnsupportedEncodingException;\nimport java.net.HttpURLConnection;\nimport java.net.URL;\nimport java.net.URLEncoder;\nimport java.util.Iterator;\nimport java.util.Map;\n\nimport com.sohu.tv.cachecloud.client.basic.exception.CacheCloudClientHttpUtilsException;\n\n/**\n * http原生工具类\n * \n * @author leifu\n * @Date 2015年1月15日\n * @Time 上午9:42:47\n */\npublic final class HttpUtils {\n\n    public static String doPost(String reqUrl, Map<String, String> parameters) {\n        return doPost(reqUrl, parameters, \"UTF-8\", ConstUtils.HTTP_CONN_TIMEOUT, ConstUtils.HTTP_SOCKET_TIMEOUT);\n    }\n\n    public static String doPost(String reqUrl, Map<String, String> parameters, String encoding) {\n        return doPost(reqUrl, parameters, encoding, ConstUtils.HTTP_CONN_TIMEOUT, ConstUtils.HTTP_SOCKET_TIMEOUT);\n    }\n\n    public static String doPost(String reqUrl, Map<String, String> parameters, String encoding, int connectTimeout,\n            int readTimeout) {\n        HttpURLConnection urlConn = null;\n        try {\n            urlConn = sendPost(reqUrl, parameters, encoding, connectTimeout, readTimeout);\n            String responseContent = getContent(urlConn, encoding);\n            return responseContent.trim();\n        } finally {\n            if (urlConn != null) {\n                urlConn.disconnect();\n                urlConn = null;\n            }\n        }\n    }\n\n    private static HttpURLConnection sendPost(String reqUrl,\n            Map<String, String> parameters, String encoding, int connectTimeout, int readTimeout) {\n        HttpURLConnection urlConn = null;\n        try {\n            String params = generatorParamString(parameters, encoding);\n            URL url = new URL(reqUrl);\n            urlConn = (HttpURLConnection) url.openConnection();\n            urlConn.setRequestMethod(\"POST\");\n            // urlConn\n            // .setRequestProperty(\n            // \"User-Agent\",\n            // \"Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3\");\n            urlConn.setConnectTimeout(connectTimeout);// （单位：毫秒）jdk\n            urlConn.setReadTimeout(readTimeout);// （单位：毫秒）jdk 1.5换成这个,读操作超时\n            urlConn.setDoOutput(true);\n            // String按照字节处理是一个好方法\n            byte[] b = params.getBytes(encoding);\n            urlConn.getOutputStream().write(b, 0, b.length);\n            urlConn.getOutputStream().flush();\n            urlConn.getOutputStream().close();\n        } catch (Exception e) {\n            throw new CacheCloudClientHttpUtilsException(e.getMessage(), e);\n        }\n        return urlConn;\n    }\n\n    private static String getContent(HttpURLConnection urlConn, String encoding) {\n        try {\n            String responseContent = null;\n            InputStream in = urlConn.getInputStream();\n            BufferedReader rd = new BufferedReader(new InputStreamReader(in, encoding));\n            String tempLine = rd.readLine();\n            StringBuffer tempStr = new StringBuffer();\n            String crlf = System.getProperty(\"line.separator\");\n            while (tempLine != null) {\n                tempStr.append(tempLine);\n                tempStr.append(crlf);\n                tempLine = rd.readLine();\n            }\n            responseContent = tempStr.toString();\n            rd.close();\n            in.close();\n            return responseContent;\n        } catch (Exception e) {\n            throw new CacheCloudClientHttpUtilsException(e.getMessage(), e);\n        }\n    }\n\n    /**\n     * @param link\n     * @param encoding\n     * @return\n     */\n    public static String doGet(String link, String encoding, int connectTimeout, int readTimeout) {\n        HttpURLConnection conn = null;\n        try {\n            URL url = new URL(link);\n            conn = (HttpURLConnection) url.openConnection();\n            conn.setRequestMethod(\"GET\");\n            conn.setConnectTimeout(connectTimeout);\n            conn.setReadTimeout(readTimeout);\n            // conn.setRequestProperty(\"User-Agent\", \"Mozilla/5.0\");\n            BufferedInputStream in = new BufferedInputStream(\n                    conn.getInputStream());\n            ByteArrayOutputStream out = new ByteArrayOutputStream();\n            byte[] buf = new byte[1024];\n            for (int i = 0; (i = in.read(buf)) > 0;) {\n                out.write(buf, 0, i);\n            }\n            out.flush();\n            String s = new String(out.toByteArray(), encoding);\n            return s;\n        } catch (Exception e) {\n            throw new CacheCloudClientHttpUtilsException(e.getMessage(), e);\n        } finally {\n            if (conn != null) {\n                conn.disconnect();\n                conn = null;\n            }\n        }\n    }\n\n    /**\n     * UTF-8编码\n     * \n     * @param link\n     * @return\n     */\n    public static String doGet(String link) {\n        return doGet(link, \"UTF-8\", ConstUtils.HTTP_CONN_TIMEOUT, ConstUtils.HTTP_SOCKET_TIMEOUT);\n    }\n\n    /**\n     * 将parameters中数据转换成用\"&\"链接的http请求参数形式\n     * \n     * @param parameters\n     * @return\n     */\n    private static String generatorParamString(Map<String, String> parameters, String encoding) {\n        StringBuffer params = new StringBuffer();\n        if (parameters != null) {\n            for (Iterator<String> iter = parameters.keySet().iterator(); iter\n                    .hasNext();) {\n                String name = iter.next();\n                String value = parameters.get(name);\n                params.append(name + \"=\");\n                try {\n                    params.append(URLEncoder.encode(value, encoding));\n                } catch (UnsupportedEncodingException e) {\n                    throw new RuntimeException(e.getMessage(), e);\n                } catch (Exception e) {\n                    String message = String.format(\"'%s'='%s'\", name, value);\n                    throw new RuntimeException(message, e);\n                }\n                if (iter.hasNext())\n                    params.append(\"&\");\n            }\n        }\n        return params.toString();\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-basic/src/main/java/com/sohu/tv/cachecloud/client/basic/util/JsonUtil.java",
    "content": "package com.sohu.tv.cachecloud.client.basic.util;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.alibaba.fastjson.JSONObject;\n\n/**\n * jackson Json转换工具\n * \n * @author leifu\n * @Date 2016年1月21日\n * @Time 上午10:55:30\n */\npublic class JsonUtil {\n    private static final Logger logger = LoggerFactory.getLogger(JsonUtil.class);\n\n    public static String toJson(Object entity) {\n        if (entity == null) {\n            return null;\n        }\n        return JSONObject.toJSONString(entity);\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-basic/src/main/java/com/sohu/tv/cachecloud/client/basic/util/NamedThreadFactory.java",
    "content": "package com.sohu.tv.cachecloud.client.basic.util;\n\nimport java.util.concurrent.ThreadFactory;\nimport java.util.concurrent.atomic.AtomicInteger;\n\n/**\n * Created by yijunzhang on 14-7-18.\n */\npublic class NamedThreadFactory implements ThreadFactory {\n    private final AtomicInteger mThreadNum = new AtomicInteger(1);\n\n    private final String mPrefix;\n\n    private final boolean mDaemo;\n\n    private final ThreadGroup mGroup;\n\n    public NamedThreadFactory(String prefix, boolean daemo) {\n        mPrefix = prefix + \"-thread-\";\n        mDaemo = daemo;\n        SecurityManager s = System.getSecurityManager();\n        mGroup = (s == null) ? Thread.currentThread().getThreadGroup() : s.getThreadGroup();\n    }\n\n    public Thread newThread(Runnable runnable) {\n        String name = mPrefix + mThreadNum.getAndIncrement();\n        Thread ret = new Thread(mGroup, runnable, name, 0);\n        ret.setDaemon(mDaemo);\n        return ret;\n    }\n\n    public ThreadGroup getThreadGroup() {\n        return mGroup;\n    }\n\n    @Override\n    public String toString() {\n        return mPrefix;\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-basic/src/main/java/com/sohu/tv/cachecloud/client/basic/util/NetUtils.java",
    "content": "/*\n * Copyright 1999-2011 Alibaba Group.\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 */\npackage com.sohu.tv.cachecloud.client.basic.util;\n\n\nimport java.io.IOException;\nimport java.net.*;\nimport java.util.Enumeration;\nimport java.util.Random;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.regex.Pattern;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * IP and Port Helper for RPC,\n *\n * @author shawn.qianx\n */\n\npublic class NetUtils {\n\n    private static final Logger logger = LoggerFactory.getLogger(NetUtils.class);\n\n    public static final String LOCALHOST = \"127.0.0.1\";\n\n    public static final String ANYHOST = \"0.0.0.0\";\n\n    private static final int RND_PORT_START = 30000;\n\n    private static final int RND_PORT_RANGE = 10000;\n\n    private static final Random RANDOM = new Random(System.currentTimeMillis());\n\n    public static int getRandomPort() {\n        return RND_PORT_START + RANDOM.nextInt(RND_PORT_RANGE);\n    }\n\n    public static int getAvailablePort() {\n        ServerSocket ss = null;\n        try {\n            ss = new ServerSocket();\n            ss.bind(null);\n            return ss.getLocalPort();\n        } catch (IOException e) {\n            return getRandomPort();\n        } finally {\n            if (ss != null) {\n                try {\n                    ss.close();\n                } catch (IOException e) {\n                }\n            }\n        }\n    }\n\n    public static int getAvailablePort(int port) {\n        if (port <= 0) {\n            return getAvailablePort();\n        }\n        for (int i = port; i < MAX_PORT; i++) {\n            ServerSocket ss = null;\n            try {\n                ss = new ServerSocket(i);\n                return i;\n            } catch (IOException e) {\n                // continue\n            } finally {\n                if (ss != null) {\n                    try {\n                        ss.close();\n                    } catch (IOException e) {\n                    }\n                }\n            }\n        }\n        return port;\n    }\n\n    private static final int MIN_PORT = 0;\n\n    private static final int MAX_PORT = 65535;\n\n    public static boolean isInvalidPort(int port) {\n        return port > MIN_PORT || port <= MAX_PORT;\n    }\n\n    private static final Pattern ADDRESS_PATTERN = Pattern.compile(\"^\\\\d{1,3}(\\\\.\\\\d{1,3}){3}\\\\:\\\\d{1,5}$\");\n\n    public static boolean isValidAddress(String address) {\n        return ADDRESS_PATTERN.matcher(address).matches();\n    }\n\n    private static final Pattern LOCAL_IP_PATTERN = Pattern.compile(\"127(\\\\.\\\\d{1,3}){3}$\");\n\n    public static boolean isLocalHost(String host) {\n        return host != null\n                && (LOCAL_IP_PATTERN.matcher(host).matches()\n                || host.equalsIgnoreCase(\"localhost\"));\n    }\n\n    public static boolean isAnyHost(String host) {\n        return \"0.0.0.0\".equals(host);\n    }\n\n    public static boolean isInvalidLocalHost(String host) {\n        return host == null\n                || host.length() == 0\n                || host.equalsIgnoreCase(\"localhost\")\n                || host.equals(\"0.0.0.0\")\n                || (LOCAL_IP_PATTERN.matcher(host).matches());\n    }\n\n    public static boolean isValidLocalHost(String host) {\n        return !isInvalidLocalHost(host);\n    }\n\n    public static InetSocketAddress getLocalSocketAddress(String host, int port) {\n        return isInvalidLocalHost(host) ?\n                new InetSocketAddress(port) : new InetSocketAddress(host, port);\n    }\n\n    private static final Pattern IP_PATTERN = Pattern.compile(\"\\\\d{1,3}(\\\\.\\\\d{1,3}){3,5}$\");\n\n    private static boolean isValidAddress(InetAddress address) {\n        if (address == null || address.isLoopbackAddress())\n            return false;\n        String name = address.getHostAddress();\n        return (name != null\n                && !ANYHOST.equals(name)\n                && !LOCALHOST.equals(name)\n                && IP_PATTERN.matcher(name).matches());\n    }\n\n    private static final Pattern IP_INTRANET_PATTERN = Pattern.compile(\"(10|192)(\\\\.\\\\d{1,3}){3,5}$\");\n\n    private static boolean isValidIntranetAddress(InetAddress address) {\n        if (address == null || address.isLoopbackAddress())\n            return false;\n        String name = address.getHostAddress();\n        return (name != null\n                && !ANYHOST.equals(name)\n                && !LOCALHOST.equals(name)\n                && IP_PATTERN.matcher(name).matches()\n                && IP_INTRANET_PATTERN.matcher(name).matches());\n    }\n\n    public static String getLocalHost() {\n        InetAddress address = getLocalAddress();\n        return address == null ? LOCALHOST : address.getHostAddress();\n    }\n\n    private static volatile InetAddress LOCAL_ADDRESS = null;\n\n    /**\n     * 遍历本地网卡，返回第一个合理的IP。\n     *\n     * @return 本地网卡IP\n     */\n    public static InetAddress getLocalAddress() {\n        if (LOCAL_ADDRESS != null)\n            return LOCAL_ADDRESS;\n        InetAddress localAddress = getLocalAddress0();\n        if (localAddress == null) {\n            localAddress = getLocalAddress1();\n        }\n        LOCAL_ADDRESS = localAddress;\n        return localAddress;\n    }\n\n    public static String getLogHost() {\n        InetAddress address = LOCAL_ADDRESS;\n        return address == null ? LOCALHOST : address.getHostAddress();\n    }\n\n    private static InetAddress getLocalAddress0() {\n        InetAddress localAddress = null;\n        try {\n            localAddress = InetAddress.getLocalHost();\n            if (isValidIntranetAddress(localAddress)) {\n                return localAddress;\n            }\n        } catch (Throwable e) {\n            logger.warn(\"Failed to retriving ip address, \" + e.getMessage(), e);\n        }\n        try {\n            Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();\n            if (interfaces != null) {\n                while (interfaces.hasMoreElements()) {\n                    try {\n                        NetworkInterface network = interfaces.nextElement();\n                        Enumeration<InetAddress> addresses = network.getInetAddresses();\n                        if (addresses != null) {\n                            while (addresses.hasMoreElements()) {\n                                try {\n                                    InetAddress address = addresses.nextElement();\n                                    if (isValidIntranetAddress(address)) {\n                                        return address;\n                                    }\n                                } catch (Throwable e) {\n                                    logger.warn(\"Failed to retriving ip address, \" + e.getMessage(), e);\n                                }\n                            }\n                        }\n                    } catch (Throwable e) {\n                        logger.warn(\"Failed to retriving ip address, \" + e.getMessage(), e);\n                    }\n                }\n            }\n        } catch (Throwable e) {\n            logger.warn(\"Failed to retriving ip address, \" + e.getMessage(), e);\n        }\n        logger.error(\"Could not get local host ip address, will use 127.0.0.1 instead.\");\n        return null;\n    }\n\n    private static InetAddress getLocalAddress1() {\n        InetAddress localAddress = null;\n        try {\n            localAddress = InetAddress.getLocalHost();\n            if (isValidAddress(localAddress)) {\n                return localAddress;\n            }\n        } catch (Throwable e) {\n            logger.warn(\"Failed to retriving ip address, \" + e.getMessage(), e);\n        }\n        try {\n            Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();\n            if (interfaces != null) {\n                while (interfaces.hasMoreElements()) {\n                    try {\n                        NetworkInterface network = interfaces.nextElement();\n                        Enumeration<InetAddress> addresses = network.getInetAddresses();\n                        if (addresses != null) {\n                            while (addresses.hasMoreElements()) {\n                                try {\n                                    InetAddress address = addresses.nextElement();\n                                    if (isValidAddress(address)) {\n                                        return address;\n                                    }\n                                } catch (Throwable e) {\n                                    logger.warn(\"Failed to retriving ip address, \" + e.getMessage(), e);\n                                }\n                            }\n                        }\n                    } catch (Throwable e) {\n                        logger.warn(\"Failed to retriving ip address, \" + e.getMessage(), e);\n                    }\n                }\n            }\n        } catch (Throwable e) {\n            logger.warn(\"Failed to retriving ip address, \" + e.getMessage(), e);\n        }\n        logger.error(\"Could not get local host ip address, will use 127.0.0.1 instead.\");\n        return localAddress;\n    }\n\n    private static final ConcurrentHashMap<String, String> hostIpCache = new ConcurrentHashMap<String, String>();\n    /**\n     * @param hostName\n     * @return ip address or hostName if UnknownHostException\n     */\n    public static String getIpByHost(String hostName) {\n        try {\n            String ip = hostIpCache.get(hostName);\n            if(ip == \"\" || \"\".equals(hostName.trim())){\n                ip = InetAddress.getByName(hostName).getHostAddress();\n                hostIpCache.putIfAbsent(hostName, ip);\n            }\n            return ip;\n        } catch (UnknownHostException e) {\n            return hostName;\n        }\n    }\n\n    public static String toAddressString(InetSocketAddress address) {\n        return address.getAddress().getHostAddress() + \":\" + address.getPort();\n    }\n\n    public static InetSocketAddress toAddress(String address) {\n        int i = address.indexOf(':');\n        String host;\n        int port;\n        if (i > -1) {\n            host = address.substring(0, i);\n            port = Integer.parseInt(address.substring(i + 1));\n        } else {\n            host = address;\n            port = 0;\n        }\n        return new InetSocketAddress(host, port);\n    }\n\n    public static String toURL(String protocol, String host, int port, String path) {\n        StringBuilder sb = new StringBuilder();\n        sb.append(protocol).append(\"://\");\n        sb.append(host).append(':').append(port);\n        if (path.charAt(0) != '/')\n            sb.append('/');\n        sb.append(path);\n        return sb.toString();\n    }\n\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-basic/src/main/java/com/sohu/tv/cachecloud/client/basic/util/StringUtil.java",
    "content": "package com.sohu.tv.cachecloud.client.basic.util;\n\nimport java.util.List;\n\n/**\n * 简单字符串类\n * 减少common-lang依赖\n * \n * @author leifu\n * @Date 2015年2月10日\n * @Time 上午9:47:29\n */\npublic class StringUtil {\n    \n    /**\n     * 列表转为字符串(用逗号分隔)\n     * @param list\n     * @param separator\n     * @return\n     */\n    public static String simpleListJoinToStrWithSeparator(List<String> list, String separator) {\n        if (list == null || list.isEmpty()) {\n            return \"\";\n        }\n        StringBuilder finalEmailStr = new StringBuilder();\n        for (int i = 0; i < list.size(); i++) {\n            if (i != 0) {\n                finalEmailStr.append(separator);\n            }\n            finalEmailStr.append(list.get(i));\n        }\n        return finalEmailStr.toString();\n    }\n\n    /**\n     * 判断字符串是否为空\n     * @param str\n     * @return\n     */\n    public static boolean isBlank(String str) {\n        int strLen;\n        if (str == null || (strLen = str.length()) == 0) {\n            return true;\n        }\n        for (int i = 0; i < strLen; i++) {\n            if ((Character.isWhitespace(str.charAt(i)) == false)) {\n                return false;\n            }\n        }\n        return true;\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-basic/src/main/java/com/sohu/tv/jedis/stat/constant/ClientReportConstant.java",
    "content": "package com.sohu.tv.jedis.stat.constant;\n\nimport java.text.SimpleDateFormat;\n\n/**\n * 客户端收集上报常量\n * @author leifu\n * @Date 2015年1月16日\n * @Time 下午2:50:59\n */\npublic class ClientReportConstant {\n    \n    /**\n     * 上报客户端版本\n     */\n    public static final String CLIENT_VERSION = \"clientVersion\";\n    \n    /**\n     * 上报json数据\n     */\n    public static final String JSON_PARAM = \"json\";\n\n    /**\n     * 客户端上报数据类型\n     */\n    public static final String CLIENT_DATA_TYPE = \"client_data_type\";\n    \n    /**\n     * 异常相关参数\n     */\n    //异常类名\n    public static final String EXCEPTION_CLASS = \"exception_class\";\n    //异常消息\n    public static final String EXCEPTION_MSG = \"exception_msg\";\n    //异常发生时间\n    public static final String EXCEPTION_HAPPEN_TIME = \"exception_happen_time\";\n    //实例ip:port\n    public static final String EXCEPTION_HOST_PORT = \"exception_host_port\";\n    //异常个数\n    public static final String EXCEPTION_COUNT = \"exception_count\";\n    //异常类型(ClientExceptionType)\n    public static final String EXCEPTION_TYPE = \"exception_type\";\n\n    /**\n     * 耗时相关参数\n     */\n    //耗时分布\n    public static final String COST_DISTRI = \"cost_distri\";\n    //调用次数\n    public static final String COST_COUNT = \"cost_count\";\n    //命令\n    public static final String COST_COMMAND = \"cost_command\";\n    //实例ip:port\n    public static final String COST_HOST_PORT = \"cost_host_port\";\n    //耗时90%最大\n    public static final String COST_TIME_90_MAX = \"cost_time_90_max\";\n    //耗时99%最大\n    public static final String COST_TIME_99_MAX = \"cost_time_99_max\";\n    //耗时最大\n    public static final String COST_TIME_100_MAX = \"cost_time_100_max\";\n    //耗时平均值\n    public static final String COST_TIME_MEAN = \"cost_time_mean\";\n    //耗时中值(50%)\n    public static final String COST_TIME_MEDIAN = \"cost_time_median\";\n\n\n    /**\n     * 值分布相关参数\n     */\n    //值分布区间\n    public static final String VALUE_DISTRI = \"value_distri\";\n    //调用量\n    public static final String VALUE_COUNT = \"value_count\";\n    //命令\n    public static final String VALUE_COMMAND = \"value_command\";\n    //host:port\n    public static final String VALUE_HOST_PORT = \"value_host_port\";\n    \n    \n    /**\n     * 其他信息\n     */\n    //耗时map的大小\n    public static final String COST_MAP_SIZE = \"cost_map_size\";\n    //值区间map的大小\n    public static final String VALUE_MAP_SIZE = \"value_map_size\";\n    //异常map的大小\n    public static final String EXCEPTION_MAP_SIZE = \"exception_map_size\";\n    //收集统计耗时map的大小\n    public static final String COLLECTION_MAP_SIZE = \"collection_map_size\";\n\n    public static SimpleDateFormat getCollectTimeSDf(){\n        return new SimpleDateFormat(\"yyyyMMddHHmm00\");\n    }\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-basic/src/main/java/com/sohu/tv/jedis/stat/data/UsefulDataCollector.java",
    "content": "package com.sohu.tv.jedis.stat.data;\n\nimport java.text.DecimalFormat;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.TreeMap;\nimport java.util.Map.Entry;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.ScheduledFuture;\nimport java.util.concurrent.TimeUnit;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.sohu.tv.cachecloud.client.basic.util.DateUtils;\nimport com.sohu.tv.jedis.stat.constant.ClientReportConstant;\nimport com.sohu.tv.jedis.stat.enums.ClientExceptionType;\nimport com.sohu.tv.jedis.stat.enums.ValueSizeDistriEnum;\nimport com.sohu.tv.jedis.stat.model.CostTimeDetailStatKey;\nimport com.sohu.tv.jedis.stat.model.CostTimeDetailStatModel;\nimport com.sohu.tv.jedis.stat.model.ExceptionModel;\nimport com.sohu.tv.jedis.stat.model.UsefulDataModel;\nimport com.sohu.tv.jedis.stat.model.ValueLengthModel;\nimport com.sohu.tv.jedis.stat.utils.AtomicLongMap;\nimport com.sohu.tv.jedis.stat.utils.NamedThreadFactory;\nimport com.sohu.tv.jedis.stat.utils.NumberUtil;\n\n/**\n * jedis有价值数据收集器(耗时,值分布,异常等)\n * \n * @author leifu\n * @Date 2015年1月13日\n * @Time 下午5:42:31\n */\npublic class UsefulDataCollector {\n\n    private final static Logger logger = LoggerFactory.getLogger(UsefulDataCollector.class);\n\n    /**\n     * 耗时详细统计\n     */\n    private static ConcurrentHashMap<CostTimeDetailStatKey, AtomicLongMap<Integer>> DATA_COST_TIME_MAP_ALL = new ConcurrentHashMap<CostTimeDetailStatKey, AtomicLongMap<Integer>>();\n\n    /**\n     * 值分布统计\n     */\n    private static ConcurrentHashMap<String, AtomicLongMap<ValueLengthModel>> DATA_VALUE_LENGTH_DISTRIBUTE_MAP_ALL = new ConcurrentHashMap<String, AtomicLongMap<ValueLengthModel>>();\n\n    /**\n     * 异常详细统计\n     */\n    private static ConcurrentHashMap<String, AtomicLongMap<ExceptionModel>> DATA_EXCEPTION_MAP_ALL = new ConcurrentHashMap<String, AtomicLongMap<ExceptionModel>>();\n\n    /**\n     * 收集耗时统计(统计收集数据本身对于速度的影响)\n     */\n    private static ConcurrentHashMap<String, AtomicLongMap<Long>> COLLECTION_COST_TIME_MAP_ALL = new ConcurrentHashMap<String, AtomicLongMap<Long>>();\n\n    /**\n     * 数据定时清理\n     */\n    private final static ScheduledExecutorService jedisDataCleanScheduledExecutor = Executors.newScheduledThreadPool(2,\n            new NamedThreadFactory(\"jedisCleanScheduledExecutor\", true));\n    private static ScheduledFuture<?> jedisDataCleanScheduleFuture;\n    private final static int delay = 10;\n    private final static int fixCycle = 60;\n\n    static {\n        init();\n    }\n\n    public static void init() {\n        Thread jedisCleanDataThread = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                try {\n                    // 清理2分钟前数据\n                    Date date = DateUtils.addMinutes(new Date(), -2);\n                    String dateSdf = ClientReportConstant.getCollectTimeSDf().format(date);\n                    clearCostTime(dateSdf);\n                    clearException(dateSdf);\n                    clearValueLength(dateSdf);\n                    clearCollectionCost(dateSdf);\n                } catch (Exception e) {\n                    logger.error(\"jedisCleanData thread message is\" + e.getMessage(), e);\n                }\n            }\n        });\n        jedisCleanDataThread.setDaemon(true);\n\n        // 启动定时任务\n        jedisDataCleanScheduleFuture = jedisDataCleanScheduledExecutor\n                .scheduleWithFixedDelay(jedisCleanDataThread, delay, fixCycle,\n                        TimeUnit.SECONDS);\n    }\n\n    /**\n     * 关闭\n     */\n    public static void close() {\n        try {\n            jedisDataCleanScheduleFuture.cancel(true);\n        } catch (Throwable t) {\n            logger.error(t.getMessage(), t);\n        }\n    }\n\n    /**\n     * 收集耗时和值分布\n     * \n     * @param costModel\n     */\n    public static void collectCostAndValueDistribute(UsefulDataModel costModel) {\n        Long start = System.currentTimeMillis();\n        try {\n            // 基础数据\n            String currentMinute = ClientReportConstant.getCollectTimeSDf().format(new Date());\n            int cost = (int) costModel.getCost();\n            String command = costModel.getCommand();\n            String hostPort = costModel.getHostPort();\n            int valueBytesLength = costModel.getValueBytesLength();\n\n            // 耗时详细统计\n            CostTimeDetailStatKey costTimeDetailStatKey = new CostTimeDetailStatKey(currentMinute, command, hostPort);\n            if (DATA_COST_TIME_MAP_ALL.containsKey(costTimeDetailStatKey)) {\n                AtomicLongMap<Integer> stat = DATA_COST_TIME_MAP_ALL.get(costTimeDetailStatKey);\n                stat.getAndIncrement(cost);\n            } else {\n                AtomicLongMap<Integer> stat = AtomicLongMap.create();\n                stat.getAndIncrement(cost);\n                AtomicLongMap<Integer> currentStat = DATA_COST_TIME_MAP_ALL.putIfAbsent(costTimeDetailStatKey, stat);\n                if (currentStat != null) {\n                    currentStat.getAndIncrement(cost);\n                }\n            }\n\n            // 值分布\n            ValueSizeDistriEnum redisValueSizeEnum = ValueSizeDistriEnum.getRightSizeBetween(valueBytesLength);\n            if (redisValueSizeEnum != null) {\n                ValueLengthModel valueLengthModel = new ValueLengthModel(redisValueSizeEnum, costModel.getCommand(),\n                        costModel.getHostPort());\n                if (DATA_VALUE_LENGTH_DISTRIBUTE_MAP_ALL.containsKey(currentMinute)) {\n                    DATA_VALUE_LENGTH_DISTRIBUTE_MAP_ALL.get(currentMinute).getAndIncrement(valueLengthModel);\n                } else {\n                    AtomicLongMap<ValueLengthModel> dataValueLengthMap = AtomicLongMap.create();\n                    dataValueLengthMap.getAndIncrement(valueLengthModel);\n                    AtomicLongMap<ValueLengthModel> currentDataValueLengthMap = DATA_VALUE_LENGTH_DISTRIBUTE_MAP_ALL\n                            .putIfAbsent(currentMinute, dataValueLengthMap);\n                    if (currentDataValueLengthMap != null) {\n                        currentDataValueLengthMap.getAndIncrement(valueLengthModel);\n                    }\n                }\n            }\n\n            // 统计收集这件事本身的耗时\n            Long collectCostTime = System.currentTimeMillis() - start;\n            if (COLLECTION_COST_TIME_MAP_ALL.containsKey(currentMinute)) {\n                AtomicLongMap<Long> stat = COLLECTION_COST_TIME_MAP_ALL.get(currentMinute);\n                stat.getAndIncrement(collectCostTime);\n            } else {\n                AtomicLongMap<Long> stat = AtomicLongMap.create();\n                stat.getAndIncrement(collectCostTime);\n                AtomicLongMap<Long> currentStat = COLLECTION_COST_TIME_MAP_ALL.putIfAbsent(currentMinute, stat);\n                if (currentStat != null) {\n                    currentStat.getAndIncrement(collectCostTime);\n                }\n            }\n        } catch (Exception e) {\n            logger.error(\"collect data error: \" + e.getMessage());\n        }\n    }\n\n    /**\n     * 收集异常\n     * \n     * @param exception\n     * @param hostPort\n     * @param currentTime(保留)\n     */\n    public static void collectException(Exception exception, String hostPort, long currentTime) {\n        collectException(exception, hostPort, currentTime, ClientExceptionType.REDIS_TYPE);\n    }\n\n    /**\n     * 收集异常\n     * \n     * @param exception\n     * @param hostPort\n     * @param currentTime\n     * @param clientExceptionType（区分jedis还是client）\n     */\n    public static void collectException(Exception exception, String hostPort, long currentTime,\n            ClientExceptionType clientExceptionType) {\n        if (exception == null) {\n            return;\n        }\n        try {\n            // 当前分钟 yyyyMMddHHmm00\n            String currentMinute = ClientReportConstant.getCollectTimeSDf().format(new Date());\n\n            ExceptionModel jedisExceptionModel = new ExceptionModel();\n            String exceptionClassName = exception.getClass().getName();\n            jedisExceptionModel.setExceptionClass(exceptionClassName);\n            jedisExceptionModel.setHostPort(hostPort);\n            jedisExceptionModel.setClientExceptionType(clientExceptionType);\n\n            if (DATA_EXCEPTION_MAP_ALL.containsKey(currentMinute)) {\n                DATA_EXCEPTION_MAP_ALL.get(currentMinute).getAndIncrement(jedisExceptionModel);\n            } else {\n                AtomicLongMap<ExceptionModel> dataExcpetionMap = AtomicLongMap.create();\n                dataExcpetionMap.getAndIncrement(jedisExceptionModel);\n                AtomicLongMap<ExceptionModel> currentDataExcpetionMap = DATA_EXCEPTION_MAP_ALL.putIfAbsent(\n                        currentMinute, dataExcpetionMap);\n                if (currentDataExcpetionMap != null) {\n                    currentDataExcpetionMap.getAndIncrement(jedisExceptionModel);\n                }\n            }\n        } catch (Exception e) {\n            logger.error(\"collect exception error: \" + e.getMessage());\n        }\n    }\n\n    /**\n     * 清除targetMinute之前的耗时\n     * \n     * @param targetMinute\n     */\n    private static void clearCostTime(String targetMinute) {\n        try {\n            if (targetMinute == \"\" || \"\".equals(targetMinute)) {\n                return;\n            }\n            long targetMinuteLong = NumberUtil.toLong(targetMinute);\n            if (targetMinuteLong == 0) {\n                return;\n            }\n            for (CostTimeDetailStatKey key : DATA_COST_TIME_MAP_ALL.keySet()) {\n                long minute = NumberUtil.toLong(key.getCurrentMinute());\n                if (minute < targetMinuteLong) {\n                    DATA_COST_TIME_MAP_ALL.remove(key);\n                }\n            }\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n    }\n\n    /**\n     * 清除targetMinute之前的值分布\n     * \n     * @param targetMinute\n     */\n    private static void clearValueLength(String targetMinute) {\n        try {\n            if (targetMinute == \"\" || \"\".equals(targetMinute)) {\n                return;\n            }\n            long targetMinuteLong = NumberUtil.toLong(targetMinute);\n            if (targetMinuteLong == 0) {\n                return;\n            }\n            for (String key : DATA_VALUE_LENGTH_DISTRIBUTE_MAP_ALL.keySet()) {\n                long minute = NumberUtil.toLong(key);\n                if (minute < targetMinuteLong) {\n                    DATA_VALUE_LENGTH_DISTRIBUTE_MAP_ALL.remove(key);\n                }\n            }\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n    }\n\n    /**\n     * 清除收集数据耗时本身\n     * \n     * @param targetMinute\n     */\n    private static void clearCollectionCost(String targetMinute) {\n        try {\n            if (targetMinute == \"\" || \"\".equals(targetMinute)) {\n                return;\n            }\n            long targetMinuteLong = NumberUtil.toLong(targetMinute);\n            if (targetMinuteLong == 0) {\n                return;\n            }\n            for (String key : COLLECTION_COST_TIME_MAP_ALL.keySet()) {\n                long minute = NumberUtil.toLong(key);\n                if (minute < targetMinuteLong) {\n                    COLLECTION_COST_TIME_MAP_ALL.remove(key);\n                }\n            }\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n    }\n\n    /**\n     * 清除targetMinute之前的异常\n     * \n     * @param targetMinute\n     */\n    private static void clearException(String targetMinute) {\n        try {\n            if (targetMinute == \"\" || \"\".equals(targetMinute)) {\n                return;\n            }\n            long targetMinuteLong = NumberUtil.toLong(targetMinute);\n            if (targetMinuteLong == 0) {\n                return;\n            }\n            for (String key : DATA_EXCEPTION_MAP_ALL.keySet()) {\n                long minute = NumberUtil.toLong(key);\n                if (minute < targetMinuteLong) {\n                    DATA_EXCEPTION_MAP_ALL.remove(key);\n                }\n            }\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n    }\n\n    /**\n     * 获取上一分钟的值分布\n     * \n     * @param currentMinuteStamp\n     */\n    public static Map<ValueLengthModel, Long> getValueLengthLastMinute(String currentMinuteStamp) {\n        AtomicLongMap<ValueLengthModel> map = DATA_VALUE_LENGTH_DISTRIBUTE_MAP_ALL.get(currentMinuteStamp);\n        if (map == null || map.isEmpty()) {\n            return Collections.emptyMap();\n        }\n        return map.asMap();\n    }\n\n    /**\n     * 获取上一分钟的耗时\n     * \n     * @param currentMinuteStamp\n     */\n    public static Map<CostTimeDetailStatKey, AtomicLongMap<Integer>> getCostTimeLastMinute(String currentMinuteStamp) {\n        Map<CostTimeDetailStatKey, AtomicLongMap<Integer>> result = new HashMap<CostTimeDetailStatKey, AtomicLongMap<Integer>>();\n        for (Entry<CostTimeDetailStatKey, AtomicLongMap<Integer>> entry : DATA_COST_TIME_MAP_ALL.entrySet()) {\n            CostTimeDetailStatKey costTimeDetailStatKey = entry.getKey();\n            if (costTimeDetailStatKey != null && costTimeDetailStatKey.getCurrentMinute() != null\n                    && costTimeDetailStatKey.getCurrentMinute().equals(currentMinuteStamp)) {\n                result.put(costTimeDetailStatKey, entry.getValue());\n            }\n        }\n        return result;\n    }\n\n    /**\n     * 获取上一分钟的异常\n     * \n     * @param currentMinuteStamp\n     */\n    public static Map<ExceptionModel, Long> getExceptionLastMinute(String currentMinuteStamp) {\n        AtomicLongMap<ExceptionModel> map = DATA_EXCEPTION_MAP_ALL.get(currentMinuteStamp);\n        if (map == null || map.isEmpty()) {\n            return Collections.emptyMap();\n        }\n        return map.asMap();\n    }\n\n    /**\n     * 产生耗时详细分布\n     * \n     * @param statMap\n     */\n    public static CostTimeDetailStatModel generateCostTimeDetailStatKey(AtomicLongMap<Integer> statMap) {\n        CostTimeDetailStatModel model = new CostTimeDetailStatModel();\n        model.setMean(getMeanValue(statMap));\n        model.setMedian(fillCostTimeDetailStatModel(model, statMap, 50));\n        model.setNinetyPercentMax(fillCostTimeDetailStatModel(model, statMap, 90));\n        model.setNinetyNinePercentMax(fillCostTimeDetailStatModel(model, statMap, 99));\n        model.setHundredMax(fillCostTimeDetailStatModel(model, statMap, 100));\n        // 上面已经设置过了\n        // model.setTotalCount(getTotalValue(statMap));\n        return model;\n\n    }\n\n    /**\n     * 获取平均值\n     * \n     * @param statMap\n     */\n    private static double getMeanValue(AtomicLongMap<Integer> statMap) {\n        if (statMap == null || statMap.isEmpty()) {\n            return 0;\n        }\n        Map<Integer, Long> map = statMap.asMap();\n        Long totalCount = 0L;\n        Long totalValue = 0L;\n        for (Entry<Integer, Long> entry : map.entrySet()) {\n            totalCount += entry.getValue();\n            totalValue += entry.getKey() * entry.getValue();\n        }\n        DecimalFormat df = new DecimalFormat(\"#.00\");\n        Double result = totalValue * 1.0 / totalCount * 1.0;\n        return NumberUtil.toDouble(df.format(result));\n    }\n\n    /**\n     * 计算Integer-Long结构排序后，百分之多少所在的对应数据\n     * \n     * @param statMap\n     * @param percent\n     * @return\n     */\n    private static int fillCostTimeDetailStatModel(CostTimeDetailStatModel model, AtomicLongMap<Integer> statMap,\n            double percent) {\n        int wrongResultValue = 0;\n        if (percent > 100 || percent < 0) {\n            return wrongResultValue;\n        }\n        if (statMap == null || statMap.isEmpty()) {\n            return wrongResultValue;\n        }\n        Map<Integer, Long> sortKeyMap = new TreeMap<Integer, Long>(statMap.asMap());\n        Long totalSize = model.getTotalCount();\n        if (totalSize <= 0) {\n            for (Long count : sortKeyMap.values()) {\n                totalSize += count;\n            }\n            model.setTotalCount(totalSize);\n        }\n        return getPercentValue(totalSize, sortKeyMap, percent);\n    }\n\n    private static int getPercentValue(Long totalSize, Map<Integer, Long> sortKeyMap, double percent) {\n        // 计算百分比所在个数\n        Long targetLocation = (long) (totalSize * percent / 100.0);\n        Long count = 0L;\n        Integer key = 0;\n        for (Entry<Integer, Long> entry : sortKeyMap.entrySet()) {\n            key = entry.getKey();\n            count += entry.getValue();\n            if (count > targetLocation) {\n                break;\n            }\n        }\n        return key;\n    }\n\n    public static Map<CostTimeDetailStatKey, AtomicLongMap<Integer>> getDataCostTimeMapAll() {\n        return DATA_COST_TIME_MAP_ALL;\n    }\n\n    public static Map<String, AtomicLongMap<ValueLengthModel>> getDataValueLengthDistributeMapAll() {\n        return DATA_VALUE_LENGTH_DISTRIBUTE_MAP_ALL;\n    }\n\n    public static Map<String, AtomicLongMap<ExceptionModel>> getDataExceptionMapAll() {\n        return DATA_EXCEPTION_MAP_ALL;\n    }\n\n    public static Map<String, AtomicLongMap<Long>> getCollectionCostTimeMapAll() {\n        return COLLECTION_COST_TIME_MAP_ALL;\n    }\n\n    public static void setCOLLECTION_COST_TIME_MAP_ALL(ConcurrentHashMap<String, AtomicLongMap<Long>> cOLLECTION_COST_TIME_MAP_ALL) {\n        COLLECTION_COST_TIME_MAP_ALL = cOLLECTION_COST_TIME_MAP_ALL;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-basic/src/main/java/com/sohu/tv/jedis/stat/enums/ClientCollectDataTypeEnum.java",
    "content": "package com.sohu.tv.jedis.stat.enums;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * 上报类型\n * @author leifu\n * @Date 2015年1月13日\n * @Time 下午6:33:22\n */\npublic enum ClientCollectDataTypeEnum {\n    /**\n     * 耗时分布\n     */\n    COST_TIME_DISTRI_TYPE(1, \"cost_time_distri_type\"),\n    \n    /**\n     * 值大小分布\n     */\n    VALUE_LENGTH_DISTRI_TYPE(2, \"value_length_distri_type\"),\n    \n    /**\n     * 异常\n     */\n    EXCEPTION_TYPE(3, \"exception_type\");\n    \n    \n    public static Map<Integer, ClientCollectDataTypeEnum> MAP = new HashMap<Integer, ClientCollectDataTypeEnum>();\n    \n    static{\n        for(ClientCollectDataTypeEnum clientCollectDataTypeEnum : ClientCollectDataTypeEnum.values()){\n            MAP.put(clientCollectDataTypeEnum.getValue(), clientCollectDataTypeEnum);\n        }\n    }\n    \n\n    private int value;\n    private String info;\n\n    private ClientCollectDataTypeEnum(int value, String info) {\n        this.value = value;\n        this.info = info;\n    }\n\n    public String getInfo() {\n        return info;\n    }\n\n    public int getValue() {\n        return value;\n    }\n    \n    public static boolean isRightType(Integer type){\n        return MAP.containsKey(type);\n    }\n    \n    public static ClientCollectDataTypeEnum get(Integer type){\n        return MAP.get(type);\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-basic/src/main/java/com/sohu/tv/jedis/stat/enums/ClientExceptionType.java",
    "content": "package com.sohu.tv.jedis.stat.enums;\n\n/**\n * 错误类型\n * \n * @author leifu\n * @Date 2015年2月4日\n * @Time 下午4:54:02\n */\npublic enum ClientExceptionType {\n    /**\n     * redis产生的错误\n     */\n    REDIS_TYPE(1),\n    /**\n     * 客户端产生的错误(比如上报，定时线程抛出的异常)\n     */\n    CLIENT_EXCEPTION_TYPE(2),\n    \n    /**\n     * redis-cluster异常\n     */\n    REDIS_CLUSTER(3);\n\n    private int type;\n\n    private ClientExceptionType(int type) {\n        this.type = type;\n    }\n\n    public int getType() {\n        return type;\n    }\n\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-basic/src/main/java/com/sohu/tv/jedis/stat/enums/CostTimeDistriEnum.java",
    "content": "package com.sohu.tv.jedis.stat.enums;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport com.sohu.tv.jedis.stat.utils.NumberUtil;\n\n/**\n * 耗时分布\n * \n * @author leifu\n * @Date 2015年1月13日\n * @Time 下午5:22:28\n */\npublic enum CostTimeDistriEnum {\n    // 单位字节\n    BETWEEN_MIN_TO_0_MS(\"-2147483648_0\", \"非法\", 1),\n    BETWEEN_0_TO_1_MS(\"0_1\", \"0-1毫秒\", 2),\n    BETWEEN_1_TO_2_MS(\"1_2\", \"1-2毫秒\", 3),\n    BETWEEN_2_TO_5_MS(\"2_5\", \"2-5毫秒\", 4),\n    BETWEEN_5_TO_10_MS(\"5_10\", \"5-10毫秒\", 5),\n    BETWEEN_10_TO_50_MS(\"10_50\", \"10-50毫秒\", 6),\n    BETWEEN_50_TO_100_MS(\"50_100\", \"50-100毫秒\", 7),\n    BETWEEN_100_TO_MAX_MS(\"100_MAX\", \"100毫秒以上\", 8);\n\n    private String value;\n    private String info;\n    private int type;\n\n    private CostTimeDistriEnum(String value, String info, int type) {\n        this.value = value;\n        this.info = info;\n        this.type = type;\n    }\n\n    public String getValue() {\n        return value;\n    }\n\n    public String getInfo() {\n        return info;\n    }\n\n    public int getType() {\n        return type;\n    }\n\n    public final static Map<String, CostTimeDistriEnum> MAP = new HashMap<String, CostTimeDistriEnum>();\n    static {\n        for (CostTimeDistriEnum enumObject : CostTimeDistriEnum.values()) {\n            MAP.put(enumObject.getValue(), enumObject);\n        }\n    }\n    \n    public static CostTimeDistriEnum getByValue(String targetValue){\n        return MAP.get(targetValue);\n    }\n\n    /**\n     * 查看length在哪个区间\n     * \n     * @param length\n     * @return\n     */\n    public static CostTimeDistriEnum getRightCostDistri(int costTime) {\n        CostTimeDistriEnum[] enumArr = CostTimeDistriEnum.values();\n        for (CostTimeDistriEnum enumObject : enumArr) {\n            if (isInSize(enumObject, costTime)) {\n                return enumObject;\n            }\n        }\n        return null;\n    }\n\n    /**\n     * 确定length在指定区间\n     * \n     * @param enumObject\n     * @param size\n     * @return\n     */\n    private static boolean isInSize(CostTimeDistriEnum enumObject, int costTime) {\n        String value = enumObject.getValue();\n        int index = value.indexOf(\"_\");\n        int start = NumberUtil.toInt(value.substring(0, index));\n        int end = NumberUtil.toInt(value.substring(index + 1));\n        if (costTime >= start && costTime < end) {\n            return true;\n        }\n        return false;\n    }\n\n    public static void main(String[] args) {\n        // 获取活在字节区间\n        // CostTimeDistriEnum a = getRightCostDistri(6);\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-basic/src/main/java/com/sohu/tv/jedis/stat/enums/ValueSizeDistriEnum.java",
    "content": "package com.sohu.tv.jedis.stat.enums;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport com.sohu.tv.jedis.stat.utils.NumberUtil;\n\n/**\n * 值分布\n * \n * @author leifu\n * @Time 2014年7月21日\n */\npublic enum ValueSizeDistriEnum {\n    // 单位字节\n    BETWEEN_MIN_TO_0_BYTE(\"-2147483648_0\", \"非法\", 0),\n    BETWEEN_0_TO_50_BYTE(\"0_50\", \"0-0.05k\", 1),\n    BETWEEN_50_TO_100_BYTE(\"50_100\", \"0.05k-0.1k\", 2),\n    BETWEEN_100_TO_200_BYTE(\"100_200\", \"0.1k-0.2k\", 3),\n    BETWEEN_200_TO_500_BYTE(\"200_500\", \"0.2k-0.5k\", 4),\n    BETWEEN_500_TO_1024_BYTE(\"500_1024\", \"0.5k-1k\", 5),\n    BETWEEN_1024_TO_2048_BYTE(\"1024_2048\", \"1-2k\", 6),\n    BETWEEN_2048_TO_5120_BYTE(\"2048_5120\", \"2-5k\", 7),\n    BETWEEN_5120_TO_10240_BYTE(\"5120_10240\", \"5-10k\", 8),\n    BETWEEN_10240_TO_20480_BYTE(\"10240_20480\", \"10-20k\", 9),\n    BETWEEN_20480_TO_51200_BYTE(\"20480_51200\", \"20-50k\", 10),\n    BETWEEN_51200_TO_102400_BYTE(\"51200_102400\", \"50-100k\", 11),\n    BETWEEN_102400_TO_204800_BYTE(\"102400_204800\", \"100-200k\", 12),\n    BETWEEN_204800_TO_512000_BYTE(\"204800_512000\", \"200-500k\", 13),\n    BETWEEN_512000_TO_MAX_BYTE(\"512000_2147483647\", \"500k以上\", 14);\n\n    private String value;\n    private String info;\n    private int type;\n\n    private ValueSizeDistriEnum(String value, String info, int type) {\n        this.value = value;\n        this.info = info;\n        this.type = type;\n    }\n\n    public int getType() {\n        return type;\n    }\n\n    public String getValue() {\n        return value;\n    }\n\n    public String getInfo() {\n        return info;\n    }\n    \n    public final static Map<String, ValueSizeDistriEnum> VALUE_MAP = new HashMap<String, ValueSizeDistriEnum>();\n    static {\n        for (ValueSizeDistriEnum enumObject : ValueSizeDistriEnum.values()) {\n            VALUE_MAP.put(enumObject.getValue(), enumObject);\n        }\n    }\n    \n    public static ValueSizeDistriEnum getByValue(String targetValue){\n        return VALUE_MAP.get(targetValue);\n    }\n    \n    public final static Map<Integer, ValueSizeDistriEnum> TYPE_MAP = new HashMap<Integer, ValueSizeDistriEnum>();\n    static {\n        for (ValueSizeDistriEnum enumObject : ValueSizeDistriEnum.values()) {\n            TYPE_MAP.put(enumObject.getType(), enumObject);\n        }\n    }\n    \n    public static ValueSizeDistriEnum getByType(int targetType){\n        return TYPE_MAP.get(targetType);\n    }\n\n    /**\n     * 查看length在哪个区间\n     * \n     * @param length\n     * @return\n     */\n    public static ValueSizeDistriEnum getRightSizeBetween(int size) {\n        ValueSizeDistriEnum[] enumArr = ValueSizeDistriEnum.values();\n        for (ValueSizeDistriEnum enumObject : enumArr) {\n            if (isInSize(enumObject, size)) {\n                return enumObject;\n            }\n        }\n        return null;\n    }\n\n    /**\n     * 确定length在指定区间\n     * \n     * @param enumObject\n     * @param size\n     * @return\n     */\n    private static boolean isInSize(ValueSizeDistriEnum enumObject, int size) {\n        String value = enumObject.getValue();\n        int index = value.indexOf(\"_\");\n        int start = NumberUtil.toInt(value.substring(0, index));\n        int end = NumberUtil.toInt(value.substring(index + 1));\n        if (size >= start && size < end) {\n            return true;\n        }\n        return false;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-basic/src/main/java/com/sohu/tv/jedis/stat/model/ClientReportBean.java",
    "content": "package com.sohu.tv.jedis.stat.model;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 上报实体\n * \n * @author leifu\n * @Date 2015年1月16日\n * @Time 下午3:01:06\n */\npublic class ClientReportBean {\n\t\n    /**\n     * 客户端ip\n     */\n    private String clientIp;\n\n    /**\n     * 收集时间\n     */\n    private long collectTime;\n    \n    /**\n     * 上报时间\n     */\n    private long reportTimeStamp;\n\n    /**\n     * 上报数据\n     */\n    private List<Map<String, Object>> datas;\n    \n    /**\n     * 其他信息\n     */\n    private Map<String,Object> otherInfo;\n\n    public ClientReportBean() {\n    }\n\n\tpublic ClientReportBean(String clientIp, long collectTime, long reportTimeStamp, List<Map<String, Object>> datas,\n            Map<String, Object> otherInfo) {\n        this.clientIp = clientIp;\n        this.collectTime = collectTime;\n        this.reportTimeStamp = reportTimeStamp;\n        this.datas = datas;\n        this.otherInfo = otherInfo;\n    }\n\n    public String getClientIp() {\n        return clientIp;\n    }\n\n    public void setClientIp(String clientIp) {\n        this.clientIp = clientIp;\n    }\n\n    public long getCollectTime() {\n        return collectTime;\n    }\n\n    public void setCollectTime(long collectTime) {\n        this.collectTime = collectTime;\n    }\n\n    public List<Map<String, Object>> getDatas() {\n        return datas;\n    }\n\n    public void setDatas(List<Map<String, Object>> datas) {\n        this.datas = datas;\n    }\n\n\n    public long getReportTimeStamp() {\n        return reportTimeStamp;\n    }\n\n    public void setReportTimeStamp(long reportTimeStamp) {\n        this.reportTimeStamp = reportTimeStamp;\n    }\n\n    public Map<String, Object> getOtherInfo() {\n        return otherInfo;\n    }\n\n    public void setOtherInfo(Map<String, Object> otherInfo) {\n        this.otherInfo = otherInfo;\n    }\n\n    @Override\n    public String toString() {\n        return \"ClientReportBean [clientIp=\" + clientIp + \", collectTime=\" + collectTime + \", reportTimeStamp=\"\n                + reportTimeStamp + \", datas=\" + datas + \", otherInfo=\" + otherInfo + \"]\";\n    }\n\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-basic/src/main/java/com/sohu/tv/jedis/stat/model/CostTimeDetailStatKey.java",
    "content": "package com.sohu.tv.jedis.stat.model;\n\n/**\n * 耗时详细统计key\n * \n * @author leifu\n * @Date 2015年1月23日\n * @Time 上午11:24:58\n */\npublic class CostTimeDetailStatKey {\n\n    /**\n     * 当前分钟 yyyyMMddHHmm00\n     */\n    private String currentMinute;\n\n    /**\n     * 命令\n     */\n    private String command;\n\n    /**\n     * ip:port\n     */\n    private String hostPort;\n\n    public CostTimeDetailStatKey() {\n    }\n\n    public CostTimeDetailStatKey(String currentMinute, String command, String hostPort) {\n        this.currentMinute = currentMinute;\n        this.command = command;\n        this.hostPort = hostPort;\n    }\n\n    public String getCurrentMinute() {\n        return currentMinute;\n    }\n\n    public void setCurrentMinute(String currentMinute) {\n        this.currentMinute = currentMinute;\n    }\n\n    public String getCommand() {\n        return command;\n    }\n\n    public void setCommand(String command) {\n        this.command = command;\n    }\n\n    public String getHostPort() {\n        return hostPort;\n    }\n\n    public void setHostPort(String hostPort) {\n        this.hostPort = hostPort;\n    }\n\n    public String getUiqueKey() {\n        return currentMinute + \"_\" + hostPort + \"_\" + command;\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((command == null) ? 0 : command.hashCode());\n        result = prime * result + ((currentMinute == null) ? 0 : currentMinute.hashCode());\n        result = prime * result + ((hostPort == null) ? 0 : hostPort.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj)\n            return true;\n        if (obj == null)\n            return false;\n        if (getClass() != obj.getClass())\n            return false;\n        CostTimeDetailStatKey other = (CostTimeDetailStatKey) obj;\n        if (command == null) {\n            if (other.command != null)\n                return false;\n        } else if (!command.equals(other.command))\n            return false;\n        if (currentMinute == null) {\n            if (other.currentMinute != null)\n                return false;\n        } else if (!currentMinute.equals(other.currentMinute))\n            return false;\n        if (hostPort == null) {\n            if (other.hostPort != null)\n                return false;\n        } else if (!hostPort.equals(other.hostPort))\n            return false;\n        return true;\n    }\n\n    @Override\n    public String toString() {\n        return \"CostTimeDetailStatKey [currentMinute=\" + currentMinute + \", command=\" + command + \", hostPort=\"\n                + hostPort + \"]\";\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-basic/src/main/java/com/sohu/tv/jedis/stat/model/CostTimeDetailStatModel.java",
    "content": "package com.sohu.tv.jedis.stat.model;\n\n/**\n * 耗时详细统计(平均值、中位值、多维度最大值等等)\n * @author leifu\n * @Date 2015年1月23日\n * @Time 上午11:23:20\n */\npublic class CostTimeDetailStatModel {\n\n    /**\n     * 中位值\n     */\n    private int median;\n\n    /**\n     * 平均值\n     */\n    private double mean;\n\n    /**\n     * 90%最大值\n     */\n    private int ninetyPercentMax;\n\n    /**\n     * 99%最大值\n     */\n    private int ninetyNinePercentMax;\n\n    /**\n     * 100%最大值\n     */\n    private int hundredMax;\n    \n    /**\n     * 总次数\n     */\n    private long totalCount;\n\n    public int getMedian() {\n        return median;\n    }\n\n    public void setMedian(int median) {\n        this.median = median;\n    }\n\n    public double getMean() {\n        return mean;\n    }\n\n    public void setMean(double mean) {\n        this.mean = mean;\n    }\n\n    public int getNinetyPercentMax() {\n        return ninetyPercentMax;\n    }\n\n    public void setNinetyPercentMax(int ninetyPercentMax) {\n        this.ninetyPercentMax = ninetyPercentMax;\n    }\n\n    public int getNinetyNinePercentMax() {\n        return ninetyNinePercentMax;\n    }\n\n    public void setNinetyNinePercentMax(int ninetyNinePercentMax) {\n        this.ninetyNinePercentMax = ninetyNinePercentMax;\n    }\n\n    public int getHundredMax() {\n        return hundredMax;\n    }\n\n    public void setHundredMax(int hundredMax) {\n        this.hundredMax = hundredMax;\n    }\n\n    public long getTotalCount() {\n        return totalCount;\n    }\n\n    public void setTotalCount(long totalCount) {\n        this.totalCount = totalCount;\n    }\n\n    @Override\n    public String toString() {\n        return \"CostTimeDetailStatModel [median=\" + median + \", mean=\" + mean + \", ninetyPercentMax=\"\n                + ninetyPercentMax + \", ninetyNinePercentMax=\" + ninetyNinePercentMax + \", hundredMax=\" + hundredMax\n                + \", totalCount=\" + totalCount + \"]\";\n    }\n\n\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-basic/src/main/java/com/sohu/tv/jedis/stat/model/CostTimeModel.java",
    "content": "package com.sohu.tv.jedis.stat.model;\n\nimport com.sohu.tv.jedis.stat.enums.CostTimeDistriEnum;\n\n/**\n * 耗时model,作为AtomicLongMap的key\n * \n * @author leifu\n * @Date 2015年1月13日\n * @Time 下午5:47:27\n */\npublic class CostTimeModel{\n    /**\n     * 耗时区间枚举\n     */\n    private CostTimeDistriEnum redisCostTimeDistriEnum;\n\n    /**\n     * 命令\n     */\n    private String command;\n    \n    /**\n     * ip:port\n     */\n    private String hostPort;\n    \n    public CostTimeModel(CostTimeDistriEnum redisCostTimeDistriEnum, String command, String hostPort) {\n        this.redisCostTimeDistriEnum = redisCostTimeDistriEnum;\n        this.command = command;\n        this.hostPort = hostPort;\n    }\n\n    public CostTimeDistriEnum getRedisCostTimeDistriEnum() {\n        return redisCostTimeDistriEnum;\n    }\n\n    public String getCommand() {\n        return command;\n    }\n\n    public String getHostPort() {\n        return hostPort;\n    }\n\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((command == null) ? 0 : command.hashCode());\n        result = prime * result + ((hostPort == null) ? 0 : hostPort.hashCode());\n        result = prime * result + ((redisCostTimeDistriEnum == null) ? 0 : redisCostTimeDistriEnum.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj)\n            return true;\n        if (obj == null)\n            return false;\n        if (getClass() != obj.getClass())\n            return false;\n        CostTimeModel other = (CostTimeModel) obj;\n        if (command == null) {\n            if (other.command != null)\n                return false;\n        } else if (!command.equals(other.command))\n            return false;\n        if (hostPort == null) {\n            if (other.hostPort != null)\n                return false;\n        } else if (!hostPort.equals(other.hostPort))\n            return false;\n        if (redisCostTimeDistriEnum != other.redisCostTimeDistriEnum)\n            return false;\n        return true;\n    }\n\n    @Override\n    public String toString() {\n        return \"CostTimeModel [redisCostTimeDistriEnum=\" + redisCostTimeDistriEnum + \", command=\" + command\n                + \", hostPort=\" + hostPort + \"]\";\n    }\n\n    \n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-basic/src/main/java/com/sohu/tv/jedis/stat/model/ExceptionModel.java",
    "content": "package com.sohu.tv.jedis.stat.model;\n\nimport com.sohu.tv.jedis.stat.enums.ClientExceptionType;\n\n/**\n * jedis异常(exceptionClass,hostPort作为唯一哈希)\n * @author leifu\n * @Date 2015年1月13日\n * @Time 下午6:00:35\n */\npublic class ExceptionModel{\n    \n    /**\n     * 异常类\n     */\n    private String exceptionClass;\n    \n    /**\n     * ip:port\n     */\n    private String hostPort;\n    \n    /**\n     * 异常类型\n     */\n    private ClientExceptionType clientExceptionType;\n    \n    public String getExceptionClass() {\n\t\treturn exceptionClass;\n\t}\n\n\tpublic void setExceptionClass(String exceptionClass) {\n\t\tthis.exceptionClass = exceptionClass;\n\t}\n\n    public String getHostPort() {\n        return hostPort;\n    }\n\n    public void setHostPort(String hostPort) {\n        this.hostPort = hostPort;\n    }\n    \n    public ClientExceptionType getClientExceptionType() {\n        return clientExceptionType;\n    }\n\n    public void setClientExceptionType(ClientExceptionType clientExceptionType) {\n        this.clientExceptionType = clientExceptionType;\n    }\n\n    public String getUniqKey(){\n    \treturn hostPort + \"_\" + exceptionClass;\n    }\n\n\t@Override\n\tpublic int hashCode() {\n\t\tfinal int prime = 31;\n\t\tint result = 1;\n\t\tresult = prime * result\n\t\t\t\t+ ((exceptionClass == null) ? 0 : exceptionClass.hashCode());\n\t\tresult = prime * result\n\t\t\t\t+ ((hostPort == null) ? 0 : hostPort.hashCode());\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic boolean equals(Object obj) {\n\t\tif (this == obj)\n\t\t\treturn true;\n\t\tif (obj == null)\n\t\t\treturn false;\n\t\tif (getClass() != obj.getClass())\n\t\t\treturn false;\n\t\tExceptionModel other = (ExceptionModel) obj;\n\t\tif (exceptionClass == null) {\n\t\t\tif (other.exceptionClass != null)\n\t\t\t\treturn false;\n\t\t} else if (!exceptionClass.equals(other.exceptionClass))\n\t\t\treturn false;\n\t\tif (hostPort == null) {\n\t\t\tif (other.hostPort != null)\n\t\t\t\treturn false;\n\t\t} else if (!hostPort.equals(other.hostPort))\n\t\t\treturn false;\n\t\treturn true;\n\t}\n\n    @Override\n    public String toString() {\n        return \"ExceptionModel [exceptionClass=\" + exceptionClass + \", hostPort=\" + hostPort + \", clientExceptionType=\"\n                + clientExceptionType + \"]\";\n    }\n\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-basic/src/main/java/com/sohu/tv/jedis/stat/model/UsefulDataModel.java",
    "content": "package com.sohu.tv.jedis.stat.model;\n\n/**\n * 从jedis收集有价值的数据简单模型\n * \n * @author leifu\n * @Date 2015年1月13日\n * @Time 下午3:42:01\n */\npublic class UsefulDataModel {\n    /**\n     * sendCommand开始时间\n     */\n    private long startTime;\n\n    /**\n     * process结束时间\n     */\n    private long endTime;\n\n    /**\n     * 命令名\n     */\n    private String command;\n\n    /**\n     * 值大小\n     */\n    private int valueBytesLength;\n    \n    /**\n     * host:ip\n     */\n    private String hostPort;\n\n    public long getStartTime() {\n        return startTime;\n    }\n\n    public void setStartTime(long startTime) {\n        this.startTime = startTime;\n    }\n\n    public long getEndTime() {\n        return endTime;\n    }\n\n    public void setEndTime(long endTime) {\n        this.endTime = endTime;\n    }\n\n    public String getCommand() {\n        return command;\n    }\n\n    public void setCommand(String command) {\n        this.command = command;\n    }\n\n    public int getValueBytesLength() {\n        return valueBytesLength;\n    }\n\n    public void setValueBytesLength(int valueBytesLength) {\n        this.valueBytesLength = valueBytesLength;\n    }\n\n    private UsefulDataModel() {\n        super();\n    }\n\n    public long getCost() {\n        return this.endTime - this.startTime;\n    }\n\n    public String getHostPort() {\n        return hostPort;\n    }\n\n    public void setHostPort(String hostPort) {\n        this.hostPort = hostPort;\n    }\n\n    /**\n     * 从ThreadLocal里面获取JedisUsefulData\n     * \n     * @param threadLocal\n     * @return\n     */\n    public static UsefulDataModel getCostModel(ThreadLocal<UsefulDataModel> threadLocal) {\n        UsefulDataModel costModel = threadLocal.get();\n        if (costModel == null) {\n            costModel = new UsefulDataModel();\n            threadLocal.set(costModel);\n        }\n        return costModel;\n    }\n\n    @Override\n    public String toString() {\n        return \"UsefulDataModel [startTime=\" + startTime + \", endTime=\" + endTime + \", command=\" + command\n                + \", valueBytesLength=\" + valueBytesLength + \", costTime=\" + (endTime - startTime) + \"ms]\";\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-basic/src/main/java/com/sohu/tv/jedis/stat/model/ValueLengthModel.java",
    "content": "package com.sohu.tv.jedis.stat.model;\n\nimport com.sohu.tv.jedis.stat.enums.ValueSizeDistriEnum;\n\n/**\n * 值分布\n * @author leifu\n * @Date 2015年1月14日\n * @Time 上午10:47:51\n */\npublic class ValueLengthModel{\n    /**\n     * 值分布区间枚举\n     */\n    private ValueSizeDistriEnum redisValueSizeEnum;\n    \n    /**\n     * 命令\n     */\n    private String command;\n    \n    /**\n     * ip:port\n     */\n    private String hostPort;\n    \n\n    public ValueLengthModel(ValueSizeDistriEnum redisValueSizeEnum, String command, String hostPort) {\n        this.redisValueSizeEnum = redisValueSizeEnum;\n        this.command = command;\n        this.hostPort = hostPort;\n    }\n\n    public ValueSizeDistriEnum getRedisValueSizeEnum() {\n        return redisValueSizeEnum;\n    }\n\n    public String getCommand() {\n        return command;\n    }\n\n    public String getHostPort() {\n        return hostPort;\n    }\n    \n    public String getUniqKey(){\n    \treturn redisValueSizeEnum.getValue() + \"_\" + hostPort + \"_\" + command;\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((command == null) ? 0 : command.hashCode());\n        result = prime * result + ((hostPort == null) ? 0 : hostPort.hashCode());\n        result = prime * result + ((redisValueSizeEnum == null) ? 0 : redisValueSizeEnum.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj)\n            return true;\n        if (obj == null)\n            return false;\n        if (getClass() != obj.getClass())\n            return false;\n        ValueLengthModel other = (ValueLengthModel) obj;\n        if (command == null) {\n            if (other.command != null)\n                return false;\n        } else if (!command.equals(other.command))\n            return false;\n        if (hostPort == null) {\n            if (other.hostPort != null)\n                return false;\n        } else if (!hostPort.equals(other.hostPort))\n            return false;\n        if (redisValueSizeEnum != other.redisValueSizeEnum)\n            return false;\n        return true;\n    }\n\n    @Override\n    public String toString() {\n        return \"ValueLengthModel [redisValueSizeEnum=\" + redisValueSizeEnum + \", command=\" + command\n                + \", hostPort=\" + hostPort + \"]\";\n    }\n\n\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-basic/src/main/java/com/sohu/tv/jedis/stat/utils/AtomicLongMap.java",
    "content": "package com.sohu.tv.jedis.stat.utils;\n\nimport java.util.Collections;\nimport java.util.LinkedHashMap;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.atomic.AtomicLong;\n\n/**\n * A map containing {@code long} values that can be atomically updated. While writes to a\n * traditional {@code Map} rely on {@code put(K, V)}, the typical mechanism for writing to this map\n * is {@code addAndGet(K, long)}, which adds a {@code long} to the value currently associated with\n * {@code K}. If a key has not yet been associated with a value, its implicit value is zero.\n * <p/>\n * <p>Most methods in this class treat absent values and zero values identically, as individually\n * documented. Exceptions to this are {@link #containsKey}, {@link #size}, {@link #isEmpty},\n *  and {@link #toString}.\n * <p/>\n * <p>Instances of this class may be used by multiple threads concurrently. All operations are\n * atomic unless otherwise noted.\n * <p/>\n * <p/>\n * <b>Warning:</b> Unlike {@code Multiset}, entries whose values are zero are not automatically\n * removed from the map. Instead they must be removed manually with {@link #removeAllZeros}.\n *\n * @author Charles Fry\n * @since 11.0\n */\npublic class AtomicLongMap<K> {\n    private final ConcurrentHashMap<K, AtomicLong> map;\n\n    private AtomicLongMap(ConcurrentHashMap<K, AtomicLong> map) {\n        this.map = map;\n    }\n\n    /**\n     * Creates an {@code AtomicLongMap}.\n     */\n    public static <K> AtomicLongMap<K> create() {\n        return new AtomicLongMap<K>(new ConcurrentHashMap<K, AtomicLong>());\n    }\n\n    /**\n     * Creates an {@code AtomicLongMap} with the same mappings as the specified {@code Map}.\n     */\n    public static <K> AtomicLongMap<K> create(Map<? extends K, ? extends Long> m) {\n        AtomicLongMap<K> result = create();\n        result.putAll(m);\n        return result;\n    }\n\n    /**\n     * Returns the value associated with {@code key}, or zero if there is no value associated with\n     * {@code key}.\n     */\n    public long get(K key) {\n        AtomicLong atomic = map.get(key);\n        return atomic == null ? 0L : atomic.get();\n    }\n\n    /**\n     * Increments by one the value currently associated with {@code key}, and returns the new value.\n     */\n    public long incrementAndGet(K key) {\n        return addAndGet(key, 1);\n    }\n\n    /**\n     * Decrements by one the value currently associated with {@code key}, and returns the new value.\n     */\n    public long decrementAndGet(K key) {\n        return addAndGet(key, -1);\n    }\n\n    /**\n     * Adds {@code delta} to the value currently associated with {@code key}, and returns the new\n     * value.\n     */\n    public long addAndGet(K key, long delta) {\n        outer:\n        for (; ; ) {\n            AtomicLong atomic = map.get(key);\n            if (atomic == null) {\n                atomic = map.putIfAbsent(key, new AtomicLong(delta));\n                if (atomic == null) {\n                    return delta;\n                }\n                // atomic is now non-null; fall through\n            }\n\n            for (; ; ) {\n                long oldValue = atomic.get();\n                if (oldValue == 0L) {\n                    // don't compareAndSet a zero\n                    if (map.replace(key, atomic, new AtomicLong(delta))) {\n                        return delta;\n                    }\n                    // atomic replaced\n                    continue outer;\n                }\n\n                long newValue = oldValue + delta;\n                if (atomic.compareAndSet(oldValue, newValue)) {\n                    return newValue;\n                }\n                // value changed\n            }\n        }\n    }\n\n    /**\n     * Increments by one the value currently associated with {@code key}, and returns the old value.\n     */\n    public long getAndIncrement(K key) {\n        return getAndAdd(key, 1);\n    }\n\n    /**\n     * Decrements by one the value currently associated with {@code key}, and returns the old value.\n     */\n    public long getAndDecrement(K key) {\n        return getAndAdd(key, -1);\n    }\n\n    /**\n     * Adds {@code delta} to the value currently associated with {@code key}, and returns the old\n     * value.\n     */\n    public long getAndAdd(K key, long delta) {\n        outer:\n        for (; ; ) {\n            AtomicLong atomic = map.get(key);\n            if (atomic == null) {\n                atomic = map.putIfAbsent(key, new AtomicLong(delta));\n                if (atomic == null) {\n                    return 0L;\n                }\n                // atomic is now non-null; fall through\n            }\n\n            for (; ; ) {\n                long oldValue = atomic.get();\n                if (oldValue == 0L) {\n                    // don't compareAndSet a zero\n                    if (map.replace(key, atomic, new AtomicLong(delta))) {\n                        return 0L;\n                    }\n                    // atomic replaced\n                    continue outer;\n                }\n\n                long newValue = oldValue + delta;\n                if (atomic.compareAndSet(oldValue, newValue)) {\n                    return oldValue;\n                }\n                // value changed\n            }\n        }\n    }\n\n    /**\n     * Associates {@code newValue} with {@code key} in this map, and returns the value previously\n     * associated with {@code key}, or zero if there was no such value.\n     */\n    public long put(K key, long newValue) {\n        outer:\n        for (; ; ) {\n            AtomicLong atomic = map.get(key);\n            if (atomic == null) {\n                atomic = map.putIfAbsent(key, new AtomicLong(newValue));\n                if (atomic == null) {\n                    return 0L;\n                }\n                // atomic is now non-null; fall through\n            }\n\n            for (; ; ) {\n                long oldValue = atomic.get();\n                if (oldValue == 0L) {\n                    // don't compareAndSet a zero\n                    if (map.replace(key, atomic, new AtomicLong(newValue))) {\n                        return 0L;\n                    }\n                    // atomic replaced\n                    continue outer;\n                }\n\n                if (atomic.compareAndSet(oldValue, newValue)) {\n                    return oldValue;\n                }\n                // value changed\n            }\n        }\n    }\n\n    /**\n     * Copies all of the mappings from the specified map to this map. The effect of this call is\n     * equivalent to that of calling {@code put(k, v)} on this map once for each mapping from key\n     * {@code k} to value {@code v} in the specified map. The behavior of this operation is undefined\n     * if the specified map is modified while the operation is in progress.\n     */\n    public void putAll(Map<? extends K, ? extends Long> m) {\n        for (Map.Entry<? extends K, ? extends Long> entry : m.entrySet()) {\n            put(entry.getKey(), entry.getValue());\n        }\n    }\n\n    /**\n     * Removes and returns the value associated with {@code key}. If {@code key} is not\n     * in the map, this method has no effect and returns zero.\n     */\n    public long remove(K key) {\n        AtomicLong atomic = map.get(key);\n        if (atomic == null) {\n            return 0L;\n        }\n\n        for (; ; ) {\n            long oldValue = atomic.get();\n            if (oldValue == 0L || atomic.compareAndSet(oldValue, 0L)) {\n                // only remove after setting to zero, to avoid concurrent updates\n                map.remove(key, atomic);\n                // succeed even if the remove fails, since the value was already adjusted\n                return oldValue;\n            }\n        }\n    }\n\n    /**\n     * Removes all mappings from this map whose values are zero.\n     * <p/>\n     * <p>This method is not atomic: the map may be visible in intermediate states, where some\n     * of the zero values have been removed and others have not.\n     */\n    public void removeAllZeros() {\n        for (K key : map.keySet()) {\n            AtomicLong atomic = map.get(key);\n            if (atomic != null && atomic.get() == 0L) {\n                map.remove(key, atomic);\n            }\n        }\n    }\n\n    /**\n     * Returns the sum of all values in this map.\n     * <p/>\n     * <p>This method is not atomic: the sum may or may not include other concurrent operations.\n     */\n    public long sum() {\n        long sum = 0L;\n        for (AtomicLong value : map.values()) {\n            sum = sum + value.get();\n        }\n        return sum;\n    }\n\n    /**\n     * Returns true if this map contains a mapping for the specified key.\n     */\n    public boolean containsKey(Object key) {\n        return map.containsKey(key);\n    }\n\n    /**\n     * Returns the number of key-value mappings in this map. If the map contains more than\n     * {@code Integer.MAX_VALUE} elements, returns {@code Integer.MAX_VALUE}.\n     */\n    public int size() {\n        return map.size();\n    }\n\n    /**\n     * Returns {@code true} if this map contains no key-value mappings.\n     */\n    public boolean isEmpty() {\n        return map.isEmpty();\n    }\n\n    /**\n     * Removes all of the mappings from this map. The map will be empty after this call returns.\n     * <p/>\n     * <p>This method is not atomic: the map may not be empty after returning if there were concurrent\n     * writes.\n     */\n    public void clear() {\n        map.clear();\n    }\n\n    @Override\n    public String toString() {\n        return map.toString();\n    }\n\n  /*\n   * ConcurrentMap operations which we may eventually add.\n   *\n   * The problem with these is that remove(K, long) has to be done in two phases by definition ---\n   * first decrementing to zero, and then removing. putIfAbsent or replace could observe the\n   * intermediate zero-state. Ways we could deal with this are:\n   *\n   * - Don't define any of the ConcurrentMap operations. This is the current state of affairs.\n   *\n   * - Define putIfAbsent and replace as treating zero and absent identically (as currently\n   *   implemented below). This is a bit surprising with putIfAbsent, which really becomes\n   *   putIfZero.\n   *\n   * - Allow putIfAbsent and replace to distinguish between zero and absent, but don't implement\n   *   remove(K, long). Without any two-phase operations it becomes feasible for all remaining\n   *   operations to distinguish between zero and absent. If we do this, then perhaps we should add\n   *   replace(key, long).\n   *\n   * - Introduce a special-value private static final AtomicLong that would have the meaning of\n   *   removal-in-progress, and rework all operations to properly distinguish between zero and\n   *   absent.\n   */\n\n    /**\n     * If {@code key} is not already associated with a value or if {@code key} is associated with\n     * zero, associate it with {@code newValue}. Returns the previous value associated with\n     * {@code key}, or zero if there was no mapping for {@code key}.\n     */\n    long putIfAbsent(K key, long newValue) {\n        for (; ; ) {\n            AtomicLong atomic = map.get(key);\n            if (atomic == null) {\n                atomic = map.putIfAbsent(key, new AtomicLong(newValue));\n                if (atomic == null) {\n                    return 0L;\n                }\n                // atomic is now non-null; fall through\n            }\n\n            long oldValue = atomic.get();\n            if (oldValue == 0L) {\n                // don't compareAndSet a zero\n                if (map.replace(key, atomic, new AtomicLong(newValue))) {\n                    return 0L;\n                }\n                // atomic replaced\n                continue;\n            }\n\n            return oldValue;\n        }\n    }\n\n    /**\n     * If {@code (key, expectedOldValue)} is currently in the map, this method replaces\n     * {@code expectedOldValue} with {@code newValue} and returns true; otherwise, this method\n     * returns false.\n     * <p/>\n     * <p>If {@code expectedOldValue} is zero, this method will succeed if {@code (key, zero)}\n     * is currently in the map, or if {@code key} is not in the map at all.\n     */\n    boolean replace(K key, long expectedOldValue, long newValue) {\n        if (expectedOldValue == 0L) {\n            return putIfAbsent(key, newValue) == 0L;\n        } else {\n            AtomicLong atomic = map.get(key);\n            return (atomic == null) ? false : atomic.compareAndSet(expectedOldValue, newValue);\n        }\n    }\n\n    /**\n     * If {@code (key, value)} is currently in the map, this method removes it and returns\n     * true; otherwise, this method returns false.\n     */\n    boolean remove(K key, long value) {\n        AtomicLong atomic = map.get(key);\n        if (atomic == null) {\n            return false;\n        }\n\n        long oldValue = atomic.get();\n        if (oldValue != value) {\n            return false;\n        }\n\n        if (oldValue == 0L || atomic.compareAndSet(oldValue, 0L)) {\n            // only remove after setting to zero, to avoid concurrent updates\n            map.remove(key, atomic);\n            // succeed even if the remove fails, since the value was already adjusted\n            return true;\n        }\n\n        // value changed\n        return false;\n    }\n    \n//    private transient Map<K, Long> asMap;\n\n    /**\n     * Returns a live, read-only view of the map backing this {@code AtomicLongMap}.\n     */\n    public Map<K, Long> asMap() {\n//      Map<K, Long> result = asMap;\n//      return (result == null) ? asMap = createAsMap() : result;\n      return createAsMap();\n    }\n\n    private Map<K, Long> createAsMap() {\n        Map<K,Long> resultMap = new LinkedHashMap<K, Long>();\n        if(map != null && !map.isEmpty()){\n            for(Entry<K, AtomicLong> entry : map.entrySet()){\n                resultMap.put(entry.getKey(), entry.getValue().get());\n            }\n        }\n        return Collections.unmodifiableMap(resultMap);\n    }\n\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-basic/src/main/java/com/sohu/tv/jedis/stat/utils/NamedThreadFactory.java",
    "content": "package com.sohu.tv.jedis.stat.utils;\n\nimport java.util.concurrent.ThreadFactory;\nimport java.util.concurrent.atomic.AtomicInteger;\n\n/**\n * Created by yijunzhang on 14-7-18.\n */\npublic class NamedThreadFactory implements ThreadFactory {\n    private final AtomicInteger mThreadNum = new AtomicInteger(1);\n\n    private final String mPrefix;\n\n    private final boolean mDaemo;\n\n    private final ThreadGroup mGroup;\n\n    public NamedThreadFactory(String prefix, boolean daemo) {\n        mPrefix = prefix + \"-thread-\";\n        mDaemo = daemo;\n        SecurityManager s = System.getSecurityManager();\n        mGroup = (s == null) ? Thread.currentThread().getThreadGroup() : s.getThreadGroup();\n    }\n\n    public Thread newThread(Runnable runnable) {\n        String name = mPrefix + mThreadNum.getAndIncrement();\n        Thread ret = new Thread(mGroup, runnable, name, 0);\n        ret.setDaemon(mDaemo);\n        return ret;\n    }\n\n    public ThreadGroup getThreadGroup() {\n        return mGroup;\n    }\n\n    @Override\n    public String toString() {\n        return mPrefix;\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-basic/src/main/java/com/sohu/tv/jedis/stat/utils/NumberUtil.java",
    "content": "package com.sohu.tv.jedis.stat.utils;\n\n/**\n * 从commons-lang抄的\n * @author leifu\n * @Date 2015年1月13日\n * @Time 下午5:52:18\n */\npublic class NumberUtil {\n    \n    public static int toInt(String str, int defaultValue) {\n        if (str == null) {\n            return defaultValue;\n        }\n        try {\n            return Integer.parseInt(str);\n        } catch (NumberFormatException nfe) {\n            return defaultValue;\n        }\n    }\n\n    public static int toInt(String str) {\n        return toInt(str, 0);\n    }\n    \n    public static long toLong(String str, long defaultValue) {\n        if (str == null) {\n            return defaultValue;\n        }\n        try {\n            return Long.parseLong(str);\n        } catch (NumberFormatException nfe) {\n            return defaultValue;\n        }\n    }\n    \n    public static long toLong(String str) {\n        return toLong(str, 0L);\n    }\n    \n    public static double toDouble(final String str) {\n        return toDouble(str, 0.0d);\n    }\n    \n    public static double toDouble(final String str, final double defaultValue) {\n        if (str == null) {\n            return defaultValue;\n        }\n        try {\n            return Double.parseDouble(str);\n        } catch (final NumberFormatException nfe) {\n            return defaultValue;\n        }\n      }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-basic/src/main/resources/cacheCloudClient.properties",
    "content": "http_conn_timeout = 3000\nhttp_socket_timeout = 5000\nclient_version = 1.0-SNAPSHOT\ndomain_url = http://127.0.0.1:9999\nredis_cluster_suffix = /cache/client/redis/cluster/%s.json?clientVersion=\nredis_sentinel_suffix = /cache/client/redis/sentinel/%s.json?clientVersion=\nredis_standalone_suffix = /cache/client/redis/standalone/%s.json?clientVersion=\ncachecloud_report_url = /cachecloud/client/reportData.json"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-basic/src/test/java/com/sohu/tv/base/test/BaseTest.java",
    "content": "package com.sohu.tv.base.test;\n\nimport org.junit.Assert;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * 基类测试\n * \n * @author leifu\n * @Date 2014年06月06日\n * @Time 上午10:50:11\n */\npublic class BaseTest extends Assert {\n\tprotected final Logger logger = LoggerFactory.getLogger(this.getClass());\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-redis/.gitignore",
    "content": ".idea/\n*.iml\n.svn/*\ntarget/\n*.class\n.settings\n.classpath\n.project\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-redis/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\"\n\txmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n\t<modelVersion>4.0.0</modelVersion>\n\t<parent>\n\t\t<groupId>com.sohu.tv</groupId>\n\t\t<artifactId>cachecloud-open-client</artifactId>\n\t\t<version>1.0-SNAPSHOT</version>\n\t</parent>\n\t<groupId>com.sohu.tv</groupId>\n\t<artifactId>cachecloud-open-client-redis</artifactId>\n\t<version>1.0-SNAPSHOT</version>\n\t<name>cachecloud-open-client-redis</name>\n\n\t<properties>\n\t\t<cachecloud-open-client-basic.version>1.0-SNAPSHOT</cachecloud-open-client-basic.version>\n        <jedis.version>2.9.0</jedis.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>junit</groupId>\n\t\t\t<artifactId>junit</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t\n\t\t<dependency>\n\t\t\t<groupId>redis.clients</groupId>\n\t\t\t<artifactId>jedis</artifactId>\n            <version>${jedis.version}</version>\n\t\t</dependency>\n\t\t\n\t\t<dependency>\n\t\t\t<groupId>com.sohu.tv</groupId>\n\t\t\t<artifactId>cachecloud-open-client-basic</artifactId>\n\t\t\t<version>${cachecloud-open-client-basic.version}</version>\n\t\t</dependency>\n\t</dependencies>\n\n\t<developers>\n\t\t<developer>\n\t\t\t<name>leifu</name>\n\t\t\t<email>leifu@sohu-inc.com</email>\n\t\t\t<organization>sohu-tv</organization>\n\t\t\t<roles>\n\t\t\t\t<role>developer</role>\n\t\t\t</roles>\n\t\t</developer>\n\t\t<developer>\n\t\t\t<name>yongfeigao</name>\n\t\t\t<email>yongfeigao@sohu-inc.com</email>\n\t\t\t<organization>sohu-tv</organization>\n\t\t\t<roles>\n\t\t\t\t<role>developer</role>\n\t\t\t</roles>\n\t\t</developer>\n\t\t<developer>\n\t\t\t<name>haibogu</name>\n\t\t\t<email>haibogu@sohu-inc.com</email>\n\t\t\t<organization>sohu-tv</organization>\n\t\t\t<roles>\n\t\t\t\t<role>developer</role>\n\t\t\t</roles>\n\t\t</developer>\n\t\t<developer>\n\t\t\t<name>yijunzhang</name>\n\t\t\t<email>yijunzhang@sohu-inc.com</email>\n\t\t\t<organization>sohu-tv</organization>\n\t\t\t<roles>\n\t\t\t\t<role>developer</role>\n\t\t\t</roles>\n\t\t</developer>\n\t</developers>\n\n\t<build>\n\t\t<resources>\n\t\t\t<resource>\n\t\t\t\t<directory>${project.basedir}/src/main/resources</directory>\n\t\t\t\t<filtering>true</filtering>\n\t\t\t</resource>\n\t\t</resources>\n\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-compiler-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<source>${maven.compiler.target}</source>\n\t\t\t\t\t<target>${maven.compiler.target}</target>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-source-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<attach>true</attach>\n\t\t\t\t</configuration>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<phase>compile</phase>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>jar</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n</project>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-redis/src/main/java/com/sohu/tv/builder/ClientBuilder.java",
    "content": "package com.sohu.tv.builder;\n\n/**\n * cachecloud-redis客户端builder\n * @author leifu\n * @Date 2015年2月5日\n * @Time 下午12:11:26\n */\npublic class ClientBuilder {\n\n    /**\n     * 构造redis cluster的builder\n     *\n     * @param appId\n     * @return\n     */\n    public static RedisClusterBuilder redisCluster(final long appId) {\n        return new RedisClusterBuilder(appId);\n    }\n\n    /**\n     * 构造redis sentinel的builder\n     *\n     * @param appId\n     * @return\n     */\n    public static RedisSentinelBuilder redisSentinel(final long appId) {\n        return new RedisSentinelBuilder(appId);\n    }\n\n    /**\n     * 构造redis standalone的builder\n     * @param appId\n     * @return\n     */\n    public static RedisStandaloneBuilder redisStandalone(final long appId) {\n        return new RedisStandaloneBuilder(appId);\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-redis/src/main/java/com/sohu/tv/builder/RedisClusterBuilder.java",
    "content": "package com.sohu.tv.builder;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.sohu.tv.cachecloud.client.basic.heartbeat.ClientStatusEnum;\nimport com.sohu.tv.cachecloud.client.basic.util.ConstUtils;\nimport com.sohu.tv.cachecloud.client.basic.util.HttpUtils;\nimport com.sohu.tv.cachecloud.client.basic.util.StringUtil;\nimport com.sohu.tv.cachecloud.client.jedis.stat.ClientDataCollectReportExecutor;\n\nimport org.apache.commons.pool2.impl.GenericObjectPoolConfig;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport redis.clients.jedis.HostAndPort;\nimport redis.clients.jedis.JedisCluster;\nimport redis.clients.jedis.JedisPool;\nimport redis.clients.jedis.Protocol;\n\nimport java.util.HashSet;\nimport java.util.Random;\nimport java.util.Set;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.locks.Lock;\nimport java.util.concurrent.locks.ReentrantLock;\n\n/**\n * redis cluster 客户端builder\n * Created by yijunzhang on 14-7-27.\n */\npublic class RedisClusterBuilder {\n    private final Logger logger = LoggerFactory.getLogger(this.getClass());\n\n    /**\n     * 应用id\n     */\n    private final long appId;\n    \n    /**\n     * jedis对象池配置\n     */\n    private GenericObjectPoolConfig jedisPoolConfig;\n    \n    /**\n     * jedis集群对象\n     */\n    private JedisCluster jedisCluster;\n\n    /**\n     * jedis连接超时(单位:毫秒)\n     */\n    private int connectionTimeout = Protocol.DEFAULT_TIMEOUT;\n    \n    /**\n     * jedis读写超时(单位:毫秒)\n     */\n    private int soTimeout = Protocol.DEFAULT_TIMEOUT;\n\n    /**\n     * 节点定位重试次数:默认3次\n     */\n    private int maxRedirections = 5;\n\n    /**\n     * 构建锁\n     */\n    private final Lock lock = new ReentrantLock();\n    \n    /**\n     * 是否开启统计\n     */\n    private boolean clientStatIsOpen = true;\n\n    /**\n     * 构造函数package访问域，package外不能直接构造实例；\n     *\n     * @param appId\n     */\n    RedisClusterBuilder(final long appId) {\n        this.appId = appId;\n        GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();\n        poolConfig.setMaxTotal(GenericObjectPoolConfig.DEFAULT_MAX_TOTAL * 5);\n        poolConfig.setMaxIdle(GenericObjectPoolConfig.DEFAULT_MAX_IDLE * 2);\n        poolConfig.setMinIdle(GenericObjectPoolConfig.DEFAULT_MAX_IDLE);\n        //JedisPool.borrowObject最大等待时间\n        poolConfig.setMaxWaitMillis(1000L);\n        poolConfig.setJmxNamePrefix(\"jedis-pool\");\n        poolConfig.setJmxEnabled(true);\n        this.jedisPoolConfig = poolConfig;\n    }\n\n    public JedisCluster build() {\n        if (jedisCluster == null) {\n            while (true) {\n                try {\n                    lock.tryLock(10, TimeUnit.SECONDS);\n                    if (jedisCluster != null) {\n                        return jedisCluster;\n                    }\n                    String url = String.format(ConstUtils.REDIS_CLUSTER_URL, String.valueOf(appId));\n                    String response = HttpUtils.doGet(url);\n                    JSONObject jsonObject = null;\n                    try {\n                        jsonObject = JSONObject.parseObject(response);\n                    } catch (Exception e) {\n                        logger.error(\"remote build error, appId: {}\", appId, e);\n                    }\n                    if (jsonObject == null) {\n                        logger.error(\"get cluster info for appId: {} error. continue...\", appId);\n                        continue;\n                    }\n                    int status = jsonObject.getIntValue(\"status\");\n                    String message = jsonObject.getString(\"message\");\n\n                    /** 检查客户端版本 **/\n                    if (status == ClientStatusEnum.ERROR.getStatus()) {\n                        throw new IllegalStateException(message);\n                    } else if (status == ClientStatusEnum.WARN.getStatus()) {\n                        logger.warn(message);\n                    } else {\n                        logger.info(message);\n                    }\n\n                    Set<HostAndPort> nodeList = new HashSet<HostAndPort>();\n                    //形如 ip1:port1,ip2:port2,ip3:port3\n                    String nodeInfo = jsonObject.getString(\"shardInfo\");\n                    //为了兼容,如果允许直接nodeInfo.split(\" \")\n                    nodeInfo = nodeInfo.replace(\" \", \",\");\n                    String[] nodeArray = nodeInfo.split(\",\");\n                    for (String node : nodeArray) {\n                        String[] ipAndPort = node.split(\":\");\n                        if (ipAndPort.length < 2) {\n                            continue;\n                        }\n                        String ip = ipAndPort[0];\n                        int port = Integer.parseInt(ipAndPort[1]);\n                        nodeList.add(new HostAndPort(ip, port));\n                    }\n                    \n                    //收集上报数据\n                    if (clientStatIsOpen) {\n                        ClientDataCollectReportExecutor.getInstance();\n                    }\n                    \n                    String password = jsonObject.getString(\"password\");\n                    if (StringUtil.isBlank(password)) {\n                        jedisCluster = new JedisCluster(nodeList, connectionTimeout, soTimeout, maxRedirections, jedisPoolConfig);\n                    } else {\n                        jedisCluster = new JedisCluster(nodeList, connectionTimeout, soTimeout, maxRedirections, password, jedisPoolConfig);\n                    }\n                    \n                    return jedisCluster;\n                } catch (Throwable e) {\n                    logger.error(e.getMessage(), e);\n                } finally {\n                    lock.unlock();\n                }\n                try {\n                    TimeUnit.MILLISECONDS.sleep(200 + new Random().nextInt(1000));//活锁\n                } catch (InterruptedException e) {\n                    logger.error(e.getMessage(), e);\n                }\n            }\n        } else {\n            return jedisCluster;\n        }\n    }\n\n    /**\n     * 设置配置\n     *\n     * @param jedisPoolConfig\n     * @return\n     */\n    public RedisClusterBuilder setJedisPoolConfig(GenericObjectPoolConfig jedisPoolConfig) {\n        this.jedisPoolConfig = jedisPoolConfig;\n        return this;\n    }\n\n\n    /**\n     * 设置jedis连接超时时间\n     * @param connectionTimeout\n     */\n    public RedisClusterBuilder setConnectionTimeout(int connectionTimeout) {\n        this.connectionTimeout = connectionTimeout;\n        return this;\n    }\n\n    /**\n     * 设置jedis读写超时时间\n     * @param soTimeout\n     */\n    public RedisClusterBuilder setSoTimeout(int soTimeout) {\n        this.soTimeout = soTimeout;\n        return this;\n    }\n\n    /**\n     * 节点定位重试次数:默认5次\n     */\n    public RedisClusterBuilder setMaxRedirections(final int maxRedirections) {\n        this.maxRedirections = maxRedirections;\n        return this;\n    }\n    \n    /**\n     * 是否开启统计\n     * @param clientStatIsOpen\n     * @return\n     */\n    public RedisClusterBuilder setClientStatIsOpen(boolean clientStatIsOpen) {\n        this.clientStatIsOpen = clientStatIsOpen;\n        return this;\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-redis/src/main/java/com/sohu/tv/builder/RedisSentinelBuilder.java",
    "content": "package com.sohu.tv.builder;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.sohu.tv.cachecloud.client.basic.heartbeat.ClientStatusEnum;\nimport com.sohu.tv.cachecloud.client.basic.util.ConstUtils;\nimport com.sohu.tv.cachecloud.client.basic.util.HttpUtils;\nimport com.sohu.tv.cachecloud.client.basic.util.StringUtil;\nimport com.sohu.tv.cachecloud.client.jedis.stat.ClientDataCollectReportExecutor;\n\nimport org.apache.commons.pool2.impl.GenericObjectPoolConfig;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport redis.clients.jedis.JedisPool;\nimport redis.clients.jedis.JedisSentinelPool;\nimport redis.clients.jedis.Protocol;\n\nimport java.util.HashSet;\nimport java.util.Random;\nimport java.util.Set;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.locks.Lock;\nimport java.util.concurrent.locks.ReentrantLock;\n\n/**\n * redis sentinel 客户端的builder\n * Created by yijunzhang on 14-9-11.\n */\npublic class RedisSentinelBuilder {\n    private static Logger logger = LoggerFactory.getLogger(RedisSentinelBuilder.class);\n    \n    /**\n     * 应用id\n     */\n    private final long appId;\n    \n\n    /**\n     * jedis对象池配置\n     */\n    private GenericObjectPoolConfig poolConfig;\n    \n    /**\n     * jedis连接超时(单位:毫秒)\n     */\n    private int connectionTimeout = Protocol.DEFAULT_TIMEOUT;\n    \n    /**\n     * jedis读写超时(单位:毫秒)\n     */\n    private int soTimeout = Protocol.DEFAULT_TIMEOUT;\n\n    /**\n     * jedis sentinel连接池\n     */\n    private volatile JedisSentinelPool sentinelPool;\n    \n    /**\n     * 构建锁\n     */\n    private static final Lock LOCK = new ReentrantLock();\n    \n    /**\n     * 是否开启统计\n     */\n    private boolean clientStatIsOpen = true;\n\n    /**\n     * 构造函数package访问域，package外不能直接构造实例；\n     *\n     * @param appId\n     */\n    RedisSentinelBuilder(final long appId) {\n        this.appId = appId;\n        poolConfig = new GenericObjectPoolConfig();\n        poolConfig.setMaxTotal(GenericObjectPoolConfig.DEFAULT_MAX_TOTAL * 3);\n        poolConfig.setMaxIdle(GenericObjectPoolConfig.DEFAULT_MAX_IDLE * 2);\n        poolConfig.setMinIdle(GenericObjectPoolConfig.DEFAULT_MIN_IDLE);\n        poolConfig.setMaxWaitMillis(1000L);\n        poolConfig.setJmxNamePrefix(\"jedis-sentinel-pool\");\n        poolConfig.setJmxEnabled(true);\n    }\n\n    public JedisSentinelPool build() {\n        if (sentinelPool == null) {\n            while (true) {\n                try {\n                    LOCK.tryLock(10, TimeUnit.MILLISECONDS);\n                    if (sentinelPool == null) {\n                        /**\n                         * http请求返回的结果是空的；\n                         */\n                        String response = HttpUtils.doGet(String.format(ConstUtils.REDIS_SENTINEL_URL, appId));\n                        if (response == null || response.isEmpty()) {\n                            logger.warn(\"get response from remote server error, appId: {}, continue...\", appId);\n                            continue;\n                        }\n                        \n                        /**\n                         * http请求返回的结果是无效的；\n                         */\n                        JSONObject jsonObject = null;\n                        try {\n                            jsonObject = JSONObject.parseObject(response);\n                        } catch (Exception e) {\n                            logger.error(\"heartbeat error, appId: {}. continue...\", appId, e);\n                        }\n                        if (jsonObject == null) {\n                            logger.error(\"get sentinel info for appId: {} error. continue...\", appId);\n                            continue;\n                        }\n                        int status = jsonObject.getIntValue(\"status\");\n                        String message = jsonObject.getString(\"message\");\n\n                        /** 检查客户端版本 **/\n                        if (status == ClientStatusEnum.ERROR.getStatus()) {\n                            throw new IllegalStateException(message);\n                        } else if (status == ClientStatusEnum.WARN.getStatus()) {\n                            logger.warn(message);\n                        } else {\n                            logger.info(message);\n                        }\n\n                        /**\n                         * 有效的请求：取出masterName和sentinels，并创建JedisSentinelPool的实例；\n                         */\n                        String masterName = jsonObject.getString(\"masterName\");\n                        String sentinels = jsonObject.getString(\"sentinels\");\n                        Set<String> sentinelSet = new HashSet<String>();\n                        for (String sentinelStr : sentinels.split(\" \")) {\n                            String[] sentinelArr = sentinelStr.split(\":\");\n                            if (sentinelArr.length == 2) {\n                                sentinelSet.add(sentinelStr);\n                            }\n                        }\n                        \n                        //收集上报数据\n                        if (clientStatIsOpen) {\n                            ClientDataCollectReportExecutor.getInstance();\n                        }\n                        \n                        String password = jsonObject.getString(\"password\");\n                        if (StringUtil.isBlank(password)) {\n                            sentinelPool = new JedisSentinelPool(masterName, sentinelSet, poolConfig, connectionTimeout, soTimeout, null, Protocol.DEFAULT_DATABASE);\n                        } else {\n                            sentinelPool = new JedisSentinelPool(masterName, sentinelSet, poolConfig, connectionTimeout, soTimeout, password, Protocol.DEFAULT_DATABASE);\n                        }\n                        \n                        return sentinelPool;\n                    }\n                } catch (Throwable e) {//容错\n                    logger.error(\"error in build, appId: {}\", appId, e);\n                } finally {\n                    LOCK.unlock();\n                }\n                try {\n                    TimeUnit.MILLISECONDS.sleep(200 + new Random().nextInt(1000));//活锁\n                } catch (InterruptedException e) {\n                    logger.error(e.getMessage(), e);\n                }\n            }\n        }\n        return sentinelPool;\n    }\n\n    /**\n     * 设置配置参数\n     *\n     * @param poolConfig\n     * @return\n     */\n    public RedisSentinelBuilder setPoolConfig(GenericObjectPoolConfig poolConfig) {\n        this.poolConfig = poolConfig;\n        return this;\n    }\n\n    /**\n     * 设置jedis连接超时时间\n     * @param connectionTimeout\n     */\n    public RedisSentinelBuilder setConnectionTimeout(int connectionTimeout) {\n        this.connectionTimeout = connectionTimeout;\n        return this;\n    }\n\n    /**\n     * 设置jedis读写超时时间\n     * @param soTimeout\n     */\n    public RedisSentinelBuilder setSoTimeout(int soTimeout) {\n        this.soTimeout = soTimeout;\n        return this;\n    }\n    \n    /**\n     * (兼容老客户端)\n     * @param timeout 单位:毫秒\n     * @return\n     */\n    public RedisSentinelBuilder setTimeout(int timeout) {\n        //兼容老版本\n        this.connectionTimeout = timeout;\n        this.soTimeout = timeout;\n        return this;\n    }\n\n    /**\n     * 是否开启统计\n     * @param clientStatIsOpen\n     * @return\n     */\n    public RedisSentinelBuilder setClientStatIsOpen(boolean clientStatIsOpen) {\n        this.clientStatIsOpen = clientStatIsOpen;\n        return this;\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-redis/src/main/java/com/sohu/tv/builder/RedisStandaloneBuilder.java",
    "content": "package com.sohu.tv.builder;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.sohu.tv.cachecloud.client.basic.util.ConstUtils;\nimport com.sohu.tv.cachecloud.client.basic.util.HttpUtils;\nimport com.sohu.tv.cachecloud.client.basic.util.StringUtil;\nimport com.sohu.tv.cachecloud.client.jedis.stat.ClientDataCollectReportExecutor;\n\nimport org.apache.commons.pool2.impl.GenericObjectPoolConfig;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport redis.clients.jedis.JedisPool;\nimport redis.clients.jedis.Protocol;\n\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.locks.Lock;\nimport java.util.concurrent.locks.ReentrantLock;\n\n/**\n * 构造redis单机的builder；\n *\n * @author: lingguo\n * @time: 2014/9/23 17:42\n */\npublic class RedisStandaloneBuilder {\n    private Logger logger = LoggerFactory.getLogger(RedisStandaloneBuilder.class);\n\n    private static final Lock LOCK = new ReentrantLock();\n    private volatile JedisPool jedisPool;\n    private GenericObjectPoolConfig poolConfig;\n    private final long appId;\n    private int timeout = Protocol.DEFAULT_TIMEOUT;\n    /**\n     * 是否开启统计\n     */\n    private boolean clientStatIsOpen = true;\n\n    /**\n     * 构造函数package访问域，package外直接构造实例；\n     *\n     * @param appId\n     */\n    RedisStandaloneBuilder(final long appId) {\n        this.appId = appId;\n        poolConfig = new GenericObjectPoolConfig();\n        poolConfig.setMaxTotal(GenericObjectPoolConfig.DEFAULT_MAX_TOTAL * 3);\n        poolConfig.setMaxIdle(GenericObjectPoolConfig.DEFAULT_MAX_IDLE * 2);\n        poolConfig.setMinIdle(GenericObjectPoolConfig.DEFAULT_MIN_IDLE);\n        poolConfig.setJmxEnabled(true);\n        poolConfig.setJmxNamePrefix(\"jedis-pool\");\n    }\n\n    public JedisPool build() {\n        if (jedisPool == null) {\n            while (true) {\n                try {\n                    LOCK.tryLock(100, TimeUnit.MILLISECONDS);\n                    if (jedisPool == null) {\n                        /**\n                         * 心跳返回的请求为空；\n                         */\n                        String response = HttpUtils.doGet(String.format(ConstUtils.REDIS_STANDALONE_URL, appId));\n                        if (response == null || response.isEmpty()) {\n                            logger.warn(\"cannot get response from server, appId={}. continue...\", appId);\n                            continue;\n                        }\n                        JSONObject jsonObject = null;\n                        try {\n                            jsonObject = JSONObject.parseObject(response);\n                        } catch (Exception e) {\n                            logger.error(\"read json from response error, appId: {}.\", appId, e);\n                        }\n                        if (jsonObject == null) {\n                            logger.warn(\"invalid response, appId: {}. continue...\", appId);\n                            continue;\n                        }\n                        /**\n                         * 从心跳中提取HostAndPort，构造JedisPool实例；\n                         */\n                        String instance = jsonObject.getString(\"standalone\");\n                        String[] instanceArr = instance.split(\":\");\n                        if (instanceArr.length != 2) {\n                            logger.warn(\"instance info is invalid, instance: {}, appId: {}, continue...\", instance, appId);\n                            continue;\n                        }\n                        \n                        //收集上报数据\n                        if (clientStatIsOpen) {\n                            ClientDataCollectReportExecutor.getInstance();\n                        }\n                        \n                        String password = jsonObject.getString(\"password\");\n                        if (StringUtil.isBlank(password)) {\n                            jedisPool = new JedisPool(poolConfig, instanceArr[0], Integer.valueOf(instanceArr[1]), timeout);\n                        } else {\n                            jedisPool = new JedisPool(poolConfig, instanceArr[0], Integer.valueOf(instanceArr[1]), timeout, password);\n                        }\n\n                        return jedisPool;\n                    }\n                } catch (InterruptedException e) {\n                    logger.error(\"error in build().\", e);\n                }\n            }\n        }\n        return jedisPool;\n    }\n\n    /**\n     * 配置\n     *\n     * @param poolConfig\n     * @return\n     */\n    public RedisStandaloneBuilder setPoolConfig(GenericObjectPoolConfig poolConfig) {\n        this.poolConfig = poolConfig;\n        return this;\n    }\n\n    /**\n     *\n     * @param timeout 单位:毫秒\n     * @return\n     */\n    public RedisStandaloneBuilder setTimeout(int timeout) {\n        this.timeout = timeout;\n        return this;\n    }\n    \n    /**\n     * 是否开启统计\n     * @param clientStatIsOpen\n     * @return\n     */\n    public RedisStandaloneBuilder setClientStatIsOpen(boolean clientStatIsOpen) {\n        this.clientStatIsOpen = clientStatIsOpen;\n        return this;\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-redis/src/main/java/com/sohu/tv/cachecloud/client/jedis/stat/ClientDataCollectReportExecutor.java",
    "content": "package com.sohu.tv.cachecloud.client.jedis.stat;\n\nimport java.text.ParseException;\nimport java.text.SimpleDateFormat;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.ScheduledFuture;\nimport java.util.concurrent.TimeUnit;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.sohu.tv.cachecloud.client.basic.util.DateUtils;\nimport com.sohu.tv.cachecloud.client.basic.util.NamedThreadFactory;\nimport com.sohu.tv.cachecloud.client.basic.util.NetUtils;\nimport com.sohu.tv.jedis.stat.constant.ClientReportConstant;\nimport com.sohu.tv.jedis.stat.data.UsefulDataCollector;\nimport com.sohu.tv.jedis.stat.enums.ClientCollectDataTypeEnum;\nimport com.sohu.tv.jedis.stat.enums.ClientExceptionType;\nimport com.sohu.tv.jedis.stat.model.ClientReportBean;\nimport com.sohu.tv.jedis.stat.model.CostTimeDetailStatKey;\nimport com.sohu.tv.jedis.stat.model.CostTimeDetailStatModel;\nimport com.sohu.tv.jedis.stat.model.ExceptionModel;\nimport com.sohu.tv.jedis.stat.model.ValueLengthModel;\nimport com.sohu.tv.jedis.stat.utils.AtomicLongMap;\nimport com.sohu.tv.jedis.stat.utils.NumberUtil;\n\n/**\n * jedis数据收集上报任务执行器\n * \n * @author leifu\n * @Date 2015年1月14日\n * @Time 上午11:45:09\n */\npublic class ClientDataCollectReportExecutor {\n\n    private final Logger logger = LoggerFactory.getLogger(ClientDataCollectReportExecutor.class);\n\n    /**\n     * 客户端ip(实际使用了web中统计的ip作为真正的客户端ip, 这个作为备用)\n     */\n    private static String clientIp = NetUtils.getLocalHost();\n\n    /**\n     * 数据收集上报\n     */\n    private final ScheduledExecutorService jedisDataCollectReportScheduledExecutor = Executors.newScheduledThreadPool(3,\n            new NamedThreadFactory(\"jedisDataCollectReportScheduledExecutor\", true));\n    private ScheduledFuture<?> jedisDataCollectReportScheduleFuture;\n    private final int delay = 5;\n    private final int fixCycle = 60;\n\n    private volatile static ClientDataCollectReportExecutor jedisDataCollectAndReportExecutor;\n\n    private ClientDataCollectReportExecutor() {\n        init();\n    }\n\n    public static ClientDataCollectReportExecutor getInstance() {\n        if (jedisDataCollectAndReportExecutor == null) {\n            synchronized (ClientDataCollectReportExecutor.class) {\n                if (jedisDataCollectAndReportExecutor == null) {\n                    jedisDataCollectAndReportExecutor = new ClientDataCollectReportExecutor();\n                }\n            }\n        }\n        return jedisDataCollectAndReportExecutor;\n    }\n\n    /**\n     * 初始化\n     */\n    public void init() {\n        Thread clientDataCollectReportThread = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                try {\n                    String currentMinuteStamp = ClientReportConstant.getCollectTimeSDf().format(new Date());\n                    collectReportAllData(currentMinuteStamp);\n                } catch (Exception e) {\n                    UsefulDataCollector.collectException(e, \"\", System.currentTimeMillis(), ClientExceptionType.CLIENT_EXCEPTION_TYPE);\n                    logger.error(\"ClientDataCollectReport thread message is\" + e.getMessage(), e);\n                }\n            }\n        });\n        clientDataCollectReportThread.setDaemon(true);\n\n        // 启动定时任务\n        jedisDataCollectReportScheduleFuture = jedisDataCollectReportScheduledExecutor.scheduleWithFixedDelay(\n                clientDataCollectReportThread, delay, fixCycle, TimeUnit.SECONDS);\n\n    }\n    \n    /**\n     * 收集上报数据\n     * @param currentMinuteStamp\n     */\n    private void collectReportAllData(String currentMinuteStamp) {\n    \t//1. 获取上一分钟的所有数据\n        String lastMinute = getLastMinute(currentMinuteStamp);\n        if (lastMinute == null || \"\".equals(lastMinute.trim())) {\n        \treturn;\n        }\n        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();\n        list.addAll(collectReportCostTimeData(lastMinute));\n        list.addAll(collectReportValueDistriData(lastMinute));\n        list.addAll(collectReportExceptionData(lastMinute));\n\n        //上报统计数据,观察是否存在内存泄露的情况\n        Map<String, Object> otherInfo = new HashMap<String, Object>(4, 1);\n        otherInfo.put(ClientReportConstant.COST_MAP_SIZE, UsefulDataCollector.getDataCostTimeMapAll().size());\n        otherInfo.put(ClientReportConstant.VALUE_MAP_SIZE, UsefulDataCollector.getDataValueLengthDistributeMapAll().size());\n        otherInfo.put(ClientReportConstant.EXCEPTION_MAP_SIZE, UsefulDataCollector.getDataExceptionMapAll().size());\n        otherInfo.put(ClientReportConstant.COLLECTION_MAP_SIZE, UsefulDataCollector.getCollectionCostTimeMapAll().size());\n        \n\t\t//2. 上报数据\n\t\tif (!list.isEmpty()) {\n\t        ClientReportBean ccReportBean = new ClientReportBean(clientIp, NumberUtil.toLong(lastMinute), System.currentTimeMillis(), list, otherInfo);\n\t        ClientReportDataCenter.reportData(ccReportBean);\n\t\t}\n\t}\n\n    /**\n     * 收集耗时\n     * \n     * @param lastMinute\n     */\n    private List<Map<String, Object>> collectReportCostTimeData(String lastMinute) {\n        try {\n        \t//1. 收集数据\n            Map<CostTimeDetailStatKey, AtomicLongMap<Integer>> map = UsefulDataCollector.getCostTimeLastMinute(lastMinute);\n            if (map == null || map.isEmpty()) {\n                return Collections.emptyList();\n            }\n\n            // 2. 组装数据\n            List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();\n            for (Entry<CostTimeDetailStatKey, AtomicLongMap<Integer>> entry : map.entrySet()) {\n                CostTimeDetailStatKey costTimeDetailStatKey = entry.getKey();\n                AtomicLongMap<Integer> statMap = entry.getValue();\n                CostTimeDetailStatModel model = UsefulDataCollector.generateCostTimeDetailStatKey(statMap);\n                \n                Map<String, Object> tempMap = new HashMap<String, Object>();\n                tempMap.put(ClientReportConstant.COST_COUNT, model.getTotalCount());\n                tempMap.put(ClientReportConstant.COST_COMMAND, costTimeDetailStatKey.getCommand());\n                tempMap.put(ClientReportConstant.COST_HOST_PORT, costTimeDetailStatKey.getHostPort());\n                tempMap.put(ClientReportConstant.COST_TIME_90_MAX, model.getNinetyPercentMax());\n                tempMap.put(ClientReportConstant.COST_TIME_99_MAX, model.getNinetyNinePercentMax());\n                tempMap.put(ClientReportConstant.COST_TIME_100_MAX, model.getHundredMax());\n                tempMap.put(ClientReportConstant.COST_TIME_MEAN, model.getMean());\n                tempMap.put(ClientReportConstant.COST_TIME_MEDIAN, model.getMedian());\n                tempMap.put(ClientReportConstant.CLIENT_DATA_TYPE, ClientCollectDataTypeEnum.COST_TIME_DISTRI_TYPE.getValue());\n                list.add(tempMap);\n            }\n            return list;\n        } catch (Exception e) {\n            UsefulDataCollector.collectException(e, \"\", System.currentTimeMillis(), ClientExceptionType.CLIENT_EXCEPTION_TYPE);\n            logger.error(\"collectReportCostTimeData:\" + e.getMessage(), e);\n            return Collections.emptyList();\n        }\n    }\n\n    /**\n     * 收集异常\n     * @param lastMinute\n     */\n    private List<Map<String, Object>> collectReportExceptionData(String lastMinute) {\n        try {\n            // 1. 只取当前时间前一分钟的的数据\n            Map<ExceptionModel, Long> map = UsefulDataCollector.getExceptionLastMinute(lastMinute);\n            if (map == null || map.isEmpty()) {\n                return Collections.emptyList();\n            }\n\n            // 2. 组装数据\n            List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();\n            Map<String, Object> tempMap = null;\n            for (Entry<ExceptionModel, Long> entry : map.entrySet()){\n            \tExceptionModel exceptionModel = entry.getKey();\n            \tLong exceptionCount = entry.getValue();\n                tempMap = new HashMap<String, Object>();\n                tempMap.put(ClientReportConstant.EXCEPTION_CLASS, exceptionModel.getExceptionClass());\n                tempMap.put(ClientReportConstant.EXCEPTION_MSG, \"\");\n                tempMap.put(ClientReportConstant.EXCEPTION_HAPPEN_TIME, System.currentTimeMillis());\n                tempMap.put(ClientReportConstant.EXCEPTION_HOST_PORT, exceptionModel.getHostPort());\n                tempMap.put(ClientReportConstant.EXCEPTION_COUNT, exceptionCount);\n                tempMap.put(ClientReportConstant.EXCEPTION_TYPE, exceptionModel.getClientExceptionType().getType());\n                tempMap.put(ClientReportConstant.CLIENT_DATA_TYPE, ClientCollectDataTypeEnum.EXCEPTION_TYPE.getValue());\n                list.add(tempMap);\n            }\n            return list;\n        } catch (Exception e) {\n            UsefulDataCollector.collectException(e, \"\", System.currentTimeMillis(), ClientExceptionType.CLIENT_EXCEPTION_TYPE);\n            logger.error(\"collectReportExceptionData:\" + e.getMessage(), e);\n            return Collections.emptyList();\n        }\n    }\n\n    /**\n     * 收集值分布\n     * \n     * @param lastMinute\n     */\n    private List<Map<String, Object>> collectReportValueDistriData(String lastMinute) {\n        try {\n            // 1. 只取当前时间前一分钟的的数据\n            Map<ValueLengthModel, Long> jedisValueLengthMap = UsefulDataCollector.getValueLengthLastMinute(lastMinute);\n            if (jedisValueLengthMap == null || jedisValueLengthMap.isEmpty()) {\n                return Collections.emptyList();\n            }\n\n            // 2.解析拼接数据\n            List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();\n            for (Entry<ValueLengthModel, Long> entry : jedisValueLengthMap.entrySet()) {\n            \tValueLengthModel model = entry.getKey();\n                Long count = entry.getValue();\n                Map<String, Object> tempMap = new HashMap<String, Object>();\n                tempMap.put(ClientReportConstant.VALUE_DISTRI, model.getRedisValueSizeEnum().getValue());\n                tempMap.put(ClientReportConstant.VALUE_COUNT, count);\n                tempMap.put(ClientReportConstant.VALUE_COMMAND, model.getCommand());\n                tempMap.put(ClientReportConstant.VALUE_HOST_PORT, model.getHostPort());\n                tempMap.put(ClientReportConstant.CLIENT_DATA_TYPE, ClientCollectDataTypeEnum.VALUE_LENGTH_DISTRI_TYPE.getValue());\n                list.add(tempMap);\n            }\n            return list;\n        } catch (Exception e) {\n            UsefulDataCollector.collectException(e, \"\", System.currentTimeMillis(), ClientExceptionType.CLIENT_EXCEPTION_TYPE);\n            logger.error(\"collectReportValueDistriData:\" + e.getMessage(), e);\n            return Collections.emptyList();\n        }\n    }\n    \n    /**\n     * 获取上一分钟的字符串\n     * \n     * @param currentMinuteStamp\n     * @return\n     */\n    private String getLastMinute(String currentMinuteStamp) {\n        try {\n            SimpleDateFormat sdf = new SimpleDateFormat(\"yyyyMMddHHmmss\");\n            Date currentDate = sdf.parse(currentMinuteStamp);\n            Date lastMinute = DateUtils.addMinutes(currentDate, -1);\n            return sdf.format(lastMinute);\n        } catch (ParseException e) {\n            logger.error(e.getMessage(), e);\n            return null;\n        }\n    }\n\n    /**\n     * 关闭\n     */\n    public void close() {\n    \t//TODO可以加个JVM钩子\n        try {\n            jedisDataCollectReportScheduleFuture.cancel(true);\n        } catch (Throwable t) {\n            logger.error(t.getMessage(), t);\n        }\n    }\n\n    public static String getClientIp() {\n        return clientIp;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-redis/src/main/java/com/sohu/tv/cachecloud/client/jedis/stat/ClientReportDataCenter.java",
    "content": "package com.sohu.tv.cachecloud.client.jedis.stat;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.sohu.tv.cachecloud.client.basic.util.ConstUtils;\nimport com.sohu.tv.cachecloud.client.basic.util.HttpUtils;\nimport com.sohu.tv.cachecloud.client.basic.util.JsonUtil;\nimport com.sohu.tv.jedis.stat.constant.ClientReportConstant;\nimport com.sohu.tv.jedis.stat.data.UsefulDataCollector;\nimport com.sohu.tv.jedis.stat.enums.ClientExceptionType;\nimport com.sohu.tv.jedis.stat.model.ClientReportBean;\n\n/**\n * 客户端常量和上报工具\n * @author leifu\n * @Date 2015年1月16日\n * @Time 下午2:50:59\n */\npublic class ClientReportDataCenter {\n\n    private static Logger logger = LoggerFactory.getLogger(ClientReportDataCenter.class);\n\n    /**\n     * 上报\n     * \n     * @param ccReportBean\n     */\n    public static void reportData(ClientReportBean ccReportBean) {\n\n        if (ccReportBean == null) {\n            logger.error(\"ccReportBean is null!\");\n        }\n\n        Map<String, String> parameters = new HashMap<String, String>();\n        parameters.put(ClientReportConstant.JSON_PARAM, JsonUtil.toJson(ccReportBean));\n        parameters.put(ClientReportConstant.CLIENT_VERSION, ConstUtils.CLIENT_VERSION);\n        \n        try {\n            HttpUtils.doPost(ConstUtils.CACHECLOUD_REPORT_URL, parameters);\n        } catch (Exception e) {\n            logger.error(\"cachecloud reportData exception: \" + e.getMessage());\n            UsefulDataCollector.collectException(e, \"\", System.currentTimeMillis(), ClientExceptionType.CLIENT_EXCEPTION_TYPE);\n        }\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-redis/src/test/java/com/sohu/tv/test/base/BaseTest.java",
    "content": "package com.sohu.tv.test.base;\n\nimport org.junit.Assert;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * User: lingguo\n * Date: 14-6-6\n * Time: 上午10:30\n */\npublic class BaseTest extends Assert {\n    protected final Logger logger = LoggerFactory.getLogger(this.getClass());\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-redis/src/test/java/com/sohu/tv/test/client/RedisClusterTest.java",
    "content": "package com.sohu.tv.test.client;\n\nimport com.sohu.tv.builder.ClientBuilder;\nimport com.sohu.tv.test.base.BaseTest;\n\nimport org.apache.commons.pool2.impl.GenericObjectPoolConfig;\nimport org.junit.Test;\n\nimport redis.clients.jedis.*;\nimport java.util.Map;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * cachecloud-rediscluster客户端测试\n * \n * @author leifu\n * @Date 2014年11月21日\n * @Time 上午11:58:53\n */\npublic class RedisClusterTest extends BaseTest {\n\n    private final static long appId = 0L;\n\n    @Test\n    public void pushData() throws Exception {\n        JedisCluster redisCluster = ClientBuilder.redisCluster(appId)\n                .setJedisPoolConfig(getPoolConfig())\n                .setConnectionTimeout(2000)\n                .setSoTimeout(1000)\n                .build();\n        for (int i = 1; i < 100; i++) {\n            redisCluster.setex(\"tmp:key\" + i, 60 * 20, \"value\" + i);\n            TimeUnit.MILLISECONDS.sleep(20);\n            logger.info(\"push:\" + i);\n        }\n    }\n\n    @Test\n    public void testCluster() {\n        JedisCluster redisCluster = ClientBuilder.redisCluster(appId)\n                .setJedisPoolConfig(getPoolConfig())\n                .setConnectionTimeout(2000)\n                .setSoTimeout(1000)\n                .build();\n        Map<String, JedisPool> clusterMap = redisCluster.getClusterNodes();\n        for (String key : clusterMap.keySet()) {\n            logger.info(\"key={}\", key);\n            JedisPool jedisPool = clusterMap.get(key);\n            Jedis jedis = jedisPool.getResource();\n\n            logger.info(\"before:cluster-slave-validity-factor->\"\n                    + jedis.configGet(\"cluster-slave-validity-factor\"));\n            jedis.configSet(\"cluster-slave-validity-factor\", \"10\");\n            logger.info(\"after:cluster-slave-validity-factor->\"\n                    + jedis.configGet(\"cluster-slave-validity-factor\"));\n            logger.info(\"------------------------------------\");\n            logger.info(\"before:repl-disable-tcp-nodelay->\" + jedis.configGet(\"repl-disable-tcp-nodelay\"));\n            jedis.configSet(\"repl-disable-tcp-nodelay\", \"no\");\n            logger.info(\"after:repl-disable-tcp-nodelay->\" + jedis.configGet(\"repl-disable-tcp-nodelay\"));\n            logger.info(\"####################################\");\n            jedis.close();\n        }\n    }\n\n    private GenericObjectPoolConfig getPoolConfig() {\n        GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();\n        poolConfig.setMaxTotal(GenericObjectPoolConfig.DEFAULT_MAX_TOTAL * 20);\n        poolConfig.setMaxIdle(GenericObjectPoolConfig.DEFAULT_MAX_IDLE * 20);\n        poolConfig.setMinIdle(GenericObjectPoolConfig.DEFAULT_MAX_IDLE * 10);\n        // JedisPool.borrowObject最大等待时间\n        poolConfig.setMaxWaitMillis(1000L);\n        poolConfig.setJmxNamePrefix(\"jedis-pool\");\n        poolConfig.setJmxEnabled(true);\n        return poolConfig;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-redis/src/test/java/com/sohu/tv/test/client/RedisSentinelTest.java",
    "content": "package com.sohu.tv.test.client;\n\nimport com.sohu.tv.builder.ClientBuilder;\nimport com.sohu.tv.test.base.BaseTest;\n\nimport org.apache.commons.pool2.impl.GenericObjectPoolConfig;\nimport org.junit.Test;\n\nimport redis.clients.jedis.HostAndPort;\nimport redis.clients.jedis.Jedis;\nimport redis.clients.jedis.JedisSentinelPool;\n\n/**\n * cachecloud-redisSentinel客户端测试\n * \n * @author leifu\n * @Date 2014年11月21日\n * @Time 上午11:58:53\n */\npublic class RedisSentinelTest extends BaseTest {\n\n    private final static long appId = 0L;\n\n    @Test\n    public void testSentinel() {\n        JedisSentinelPool sentinelPool = ClientBuilder.redisSentinel(appId)\n                .setConnectionTimeout(2000)\n                .setSoTimeout(1000)\n                .build();\n        HostAndPort currentHostMaster = sentinelPool.getCurrentHostMaster();\n        logger.info(\"current master: {}\", currentHostMaster.toString());\n\n        Jedis jedis = sentinelPool.getResource();\n        for (int i = 0; i < 10; i++) {\n            jedis.lpush(\"mylist\", \"list-\" + i);\n        }\n        jedis.close();\n        sentinelPool.destroy();\n    }\n\n    @Test\n    public void testSentinelExample() {\n        JedisSentinelPool sentinelPool = null;\n\n        // 使用默认配置\n//        sentinelPool = ClientBuilder.redisSentinel(appId).build();\n\n        /**\n         * 自定义配置\n         */\n        GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();\n        poolConfig.setMaxIdle(GenericObjectPoolConfig.DEFAULT_MAX_IDLE * 3);\n        poolConfig.setMinIdle(GenericObjectPoolConfig.DEFAULT_MIN_IDLE * 2);\n        poolConfig.setJmxEnabled(true);\n        poolConfig.setMaxWaitMillis(3000);\n\n        sentinelPool = ClientBuilder.redisSentinel(appId)\n                .setPoolConfig(poolConfig)\n                .setConnectionTimeout(2000)\n                .setSoTimeout(1000)\n                .build();\n\n        Jedis jedis = sentinelPool.getResource();\n        jedis.set(\"key1\", \"1\");\n        assertEquals(\"2\", jedis.incr(\"key1\"));\n        jedis.close();\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-client-redis/src/test/java/com/sohu/tv/test/client/RedisStandaloneTest.java",
    "content": "package com.sohu.tv.test.client;\n\nimport com.sohu.tv.builder.ClientBuilder;\nimport com.sohu.tv.test.base.BaseTest;\n\nimport org.apache.commons.pool2.impl.GenericObjectPoolConfig;\nimport org.junit.Test;\n\nimport redis.clients.jedis.*;\n\nimport java.util.Set;\n\npublic class RedisStandaloneTest extends BaseTest {\n\n    @Test\n    public void testStandalone() {\n        long appId = 10121;\n        JedisPool jedisPool = ClientBuilder.redisStandalone(appId)\n                .setPoolConfig(new GenericObjectPoolConfig())\n                .setTimeout(2000)\n                .build();\n        Jedis jedis = jedisPool.getResource();\n        for (int i = 0; i < 10; i++) {\n            jedis.zadd(\"key-zset\", i * 0.1, \"value-\" + i);\n        }\n        Set<String> result = jedis.zrevrangeByScore(\"key-zset\", 2, 0);\n        for (String s : result) {\n            logger.info(\"{}->\", s);\n        }\n        jedis.close();\n        jedisPool.destroy();\n    }\n\n    @Test\n    public void testStandaloneExample() {\n        long appId = 10122;\n        JedisPool jedisPool = null;\n\n        // 使用默认配置\n//        jedisPool = ClientBuilder.redisStandalone(appId).build();\n\n        /**\n         * 使用自定义配置\n         */\n        GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();\n        poolConfig.setMaxIdle(GenericObjectPoolConfig.DEFAULT_MAX_IDLE * 3);\n        poolConfig.setMinIdle(GenericObjectPoolConfig.DEFAULT_MIN_IDLE * 2);\n        poolConfig.setJmxEnabled(true);\n        poolConfig.setMaxWaitMillis(3000);\n\n        jedisPool = ClientBuilder.redisStandalone(appId)\n                .setPoolConfig(poolConfig)\n                .setTimeout(2000)\n                .build();\n\n        Jedis jedis = jedisPool.getResource();\n        jedis.setnx(\"key2\", \"5\");\n        assertEquals(\"10\", jedis.incrBy(\"key2\", 5));\n        jedis.close();\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-jedis-stat/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" 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  <parent>\n    <groupId>com.sohu.tv</groupId>\n    <artifactId>cachecloud-open-client</artifactId>\n    <version>1.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>cachecloud-open-jedis-stat</artifactId>\n  <description>jedis command statistic</description>\n  <version>1.0</version>\n  <dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.slf4j</groupId>\n\t\t\t<artifactId>slf4j-api</artifactId>\n\t\t\t<scope>compile</scope>\n\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>ch.qos.logback</groupId>\n\t\t\t<artifactId>logback-classic</artifactId>\n\t\t\t<scope>test</scope>\n\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>junit</groupId>\n\t\t\t<artifactId>junit</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-compiler-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<source>${maven.compiler.target}</source>\n\t\t\t\t\t<target>${maven.compiler.target}</target>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-surefire-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<skipTests>true</skipTests>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-source-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<attach>true</attach>\n\t\t\t\t</configuration>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<phase>compile</phase>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>jar</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-deploy-plugin</artifactId>\n\t\t\t</plugin>\n\n\t\t</plugins>\n\t</build>\n</project>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-jedis-stat/src/main/java/com/sohu/tv/cache/client/common/jmx/CachecloudDataWatcher.java",
    "content": "package com.sohu.tv.cache.client.common.jmx;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.sohu.tv.jedis.stat.data.UsefulDataCollector;\nimport com.sohu.tv.jedis.stat.model.CostTimeDetailStatKey;\nimport com.sohu.tv.jedis.stat.model.ExceptionModel;\nimport com.sohu.tv.jedis.stat.model.ValueLengthModel;\nimport com.sohu.tv.jedis.stat.utils.AtomicLongMap;\n\nimport java.util.*;\nimport java.util.Map.Entry;\n\n/**\n * 监控cachecloud数据收集\n * @author leifu\n * @Date 2015年1月28日\n * @Time 下午2:02:04\n */\npublic class CachecloudDataWatcher implements CachecloudDataWatcherMBean {\n\tprivate final Logger logger = LoggerFactory.getLogger(this.getClass());\n\n\t@Override\n\tpublic Map<String, Map<Integer, Long>> getCostTimeMap() {\n\t\tMap<CostTimeDetailStatKey, AtomicLongMap<Integer>> map = UsefulDataCollector.getDataCostTimeMapAll();\n\t\tif (map == null || map.isEmpty()) {\n\t\t\treturn Collections.emptyMap();\n\t\t}\n\n\t\tMap<String, Map<Integer, Long>> result = new HashMap<String, Map<Integer, Long>>();\n\t\tfor (Entry<CostTimeDetailStatKey, AtomicLongMap<Integer>> entry : map.entrySet()) {\n\t\t\tCostTimeDetailStatKey costTimeDetailStatKey = entry.getKey();\n\t\t\tString key = costTimeDetailStatKey.getUiqueKey();\n\t\t\tresult.put(key, entry.getValue().asMap());\n\t\t}\n\n\t\treturn result;\n\t}\n\t\n\t@Override\n    public Map<String, Long> getCostTimeGroupByMinute() {\n        Map<CostTimeDetailStatKey, AtomicLongMap<Integer>> map = UsefulDataCollector.getDataCostTimeMapAll();\n        if (map == null || map.isEmpty()) {\n            return Collections.emptyMap();\n        }\n        Map<String, Long> result = new HashMap<String, Long>();\n        for (Entry<CostTimeDetailStatKey, AtomicLongMap<Integer>> entry : map.entrySet()) {\n            String minute = entry.getKey().getCurrentMinute();\n            Long totalCount = 0L;\n            for (Long count : entry.getValue().asMap().values()) {\n                totalCount += count;\n            }\n            if (result.containsKey(minute)) {\n                result.put(minute, result.get(minute) + totalCount);\n            } else {\n                result.put(minute, totalCount);\n            }\n        }\n        return result;\n    }\n\t\n\t@Override\n    public Map<String, Map<String, Long>> getCostTimeGroupByMinuteAndCommand() {\n        Map<CostTimeDetailStatKey, AtomicLongMap<Integer>> map = UsefulDataCollector.getDataCostTimeMapAll();\n        if (map == null || map.isEmpty()) {\n            return Collections.emptyMap();\n        }\n        // 20150130113700_127.0.0.1:6381_del={0=4, 1=4}\n        Map<String, Map<String, Long>> result = new HashMap<String, Map<String, Long>>();\n        for (Entry<CostTimeDetailStatKey, AtomicLongMap<Integer>> entry : map.entrySet()) {\n            String minute = entry.getKey().getCurrentMinute();\n            String command = entry.getKey().getCommand();\n            Long totalCount = 0L;\n            for (Long count : entry.getValue().asMap().values()) {\n                totalCount += count;\n            }\n            if (result.containsKey(minute)) {\n                Map<String, Long> tempMap = result.get(minute);\n                if (tempMap.containsKey(command)) {\n                    tempMap.put(command, tempMap.get(command) + totalCount);\n                } else {\n                    tempMap.put(command, totalCount);\n                }\n                result.put(minute, tempMap);\n            } else {\n                Map<String, Long> tempMap = new HashMap<String, Long>();\n                tempMap.put(command, totalCount);\n                result.put(minute, tempMap);\n            }\n        }\n        return result;\n    }\n\n\t@Override\n\tpublic Map<String, Map<String, Long>> getExceptionMap() {\n\t\tMap<String, AtomicLongMap<ExceptionModel>> map = UsefulDataCollector.getDataExceptionMapAll();\n\t\tif (map == null || map.isEmpty()) {\n\t\t\treturn Collections.emptyMap();\n\t\t}\n\n\t\tMap<String, Map<String, Long>> result = new HashMap<String, Map<String, Long>>();\n\t\tfor (Entry<String, AtomicLongMap<ExceptionModel>> entry : map.entrySet()) {\n\t\t\tString key = entry.getKey();\n\t\t\tMap<String, Long> tempMap = new HashMap<String, Long>();\n\t\t\tfor (Entry<ExceptionModel, Long> exceptionEntry : entry.getValue().asMap().entrySet()) {\n\t\t\t\ttempMap.put(exceptionEntry.getKey().getUniqKey(), exceptionEntry.getValue());\n\t\t\t}\n\t\t\tresult.put(key, tempMap);\n\t\t}\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic Map<String, Map<String, Long>> getValueLengthMap() {\n\t\tMap<String, AtomicLongMap<ValueLengthModel>> map = UsefulDataCollector\n\t\t\t\t.getDataValueLengthDistributeMapAll();\n\t\tif (map == null || map.isEmpty()) {\n\t\t\treturn Collections.emptyMap();\n\t\t}\n\n\t\tMap<String, Map<String, Long>> result = new HashMap<String, Map<String, Long>>();\n\t\tfor (Entry<String, AtomicLongMap<ValueLengthModel>> entry : map.entrySet()) {\n\t\t\tString key = entry.getKey();\n\t\t\tMap<String, Long> tempMap = new HashMap<String, Long>();\n\t\t\tfor (Entry<ValueLengthModel, Long> valueLengthEntry : entry.getValue().asMap().entrySet()) {\n\t\t\t\ttempMap.put(valueLengthEntry.getKey().getUniqKey(), valueLengthEntry.getValue());\n\t\t\t}\n\t\t\tresult.put(key, tempMap);\n\t\t}\n\t\treturn result;\n\t}\n\n    @Override\n    public Map<String, Map<Long, Long>> getCollectionCostTimeMap() {\n        Map<String, AtomicLongMap<Long>> map = UsefulDataCollector.getCollectionCostTimeMapAll();\n        if (map == null || map.isEmpty()) {\n            return Collections.emptyMap();\n        }\n        Map<String, Map<Long, Long>> result = new HashMap<String, Map<Long, Long>>();\n        for (Entry<String, AtomicLongMap<Long>> entry : map.entrySet()) {\n            String key = entry.getKey();\n            result.put(key, entry.getValue().asMap());\n        }\n        return result;\n    }\n\n\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-jedis-stat/src/main/java/com/sohu/tv/cache/client/common/jmx/CachecloudDataWatcherMBean.java",
    "content": "package com.sohu.tv.cache.client.common.jmx;\n\nimport java.util.Map;\n\n\n/**\n * 监控cachecloud数据收集\n * @author leifu\n * @Date 2015年1月25日\n * @Time 上午10:30:13\n */\npublic interface CachecloudDataWatcherMBean {\n\n    public Map<String, Map<Integer,Long>> getCostTimeMap();\n    \n    public Map<String, Long> getCostTimeGroupByMinute();\n    \n    public Map<String, Map<String,Long>> getCostTimeGroupByMinuteAndCommand();\n\n    public Map<String, Map<String,Long>> getExceptionMap();\n    \n    public Map<String, Map<String,Long>> getValueLengthMap();\n    \n    /**\n     * 收集数据本身的耗时\n     * @return\n     */\n    public Map<String, Map<Long,Long>> getCollectionCostTimeMap();\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-jedis-stat/src/main/java/com/sohu/tv/jedis/stat/constant/ClientReportConstant.java",
    "content": "package com.sohu.tv.jedis.stat.constant;\n\nimport java.text.SimpleDateFormat;\n\n/**\n * 客户端收集上报常量\n * @author leifu\n * @Date 2015年1月16日\n * @Time 下午2:50:59\n */\npublic class ClientReportConstant {\n    \n    /**\n     * 上报客户端版本\n     */\n    public static final String CLIENT_VERSION = \"clientVersion\";\n    \n    /**\n     * 上报json数据\n     */\n    public static final String JSON_PARAM = \"json\";\n\n    /**\n     * 客户端上报数据类型\n     */\n    public static final String CLIENT_DATA_TYPE = \"client_data_type\";\n    \n    /**\n     * 异常相关参数\n     */\n    //异常类名\n    public static final String EXCEPTION_CLASS = \"exception_class\";\n    //异常消息\n    public static final String EXCEPTION_MSG = \"exception_msg\";\n    //异常发生时间\n    public static final String EXCEPTION_HAPPEN_TIME = \"exception_happen_time\";\n    //实例ip:port\n    public static final String EXCEPTION_HOST_PORT = \"exception_host_port\";\n    //异常个数\n    public static final String EXCEPTION_COUNT = \"exception_count\";\n    //异常类型(ClientExceptionType)\n    public static final String EXCEPTION_TYPE = \"exception_type\";\n\n    /**\n     * 耗时相关参数\n     */\n    //耗时分布\n    public static final String COST_DISTRI = \"cost_distri\";\n    //调用次数\n    public static final String COST_COUNT = \"cost_count\";\n    //命令\n    public static final String COST_COMMAND = \"cost_command\";\n    //实例ip:port\n    public static final String COST_HOST_PORT = \"cost_host_port\";\n    //耗时90%最大\n    public static final String COST_TIME_90_MAX = \"cost_time_90_max\";\n    //耗时99%最大\n    public static final String COST_TIME_99_MAX = \"cost_time_99_max\";\n    //耗时最大\n    public static final String COST_TIME_100_MAX = \"cost_time_100_max\";\n    //耗时平均值\n    public static final String COST_TIME_MEAN = \"cost_time_mean\";\n    //耗时中值(50%)\n    public static final String COST_TIME_MEDIAN = \"cost_time_median\";\n\n\n    /**\n     * 值分布相关参数\n     */\n    //值分布区间\n    public static final String VALUE_DISTRI = \"value_distri\";\n    //调用量\n    public static final String VALUE_COUNT = \"value_count\";\n    //命令\n    public static final String VALUE_COMMAND = \"value_command\";\n    //host:port\n    public static final String VALUE_HOST_PORT = \"value_host_port\";\n    \n    \n    /**\n     * 其他信息\n     */\n    //耗时map的大小\n    public static final String COST_MAP_SIZE = \"cost_map_size\";\n    //值区间map的大小\n    public static final String VALUE_MAP_SIZE = \"value_map_size\";\n    //异常map的大小\n    public static final String EXCEPTION_MAP_SIZE = \"exception_map_size\";\n    //收集统计耗时map的大小\n    public static final String COLLECTION_MAP_SIZE = \"collection_map_size\";\n\n    public static SimpleDateFormat getCollectTimeSDf(){\n        return new SimpleDateFormat(\"yyyyMMddHHmm00\");\n    }\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-jedis-stat/src/main/java/com/sohu/tv/jedis/stat/data/UsefulDataCollector.java",
    "content": "package com.sohu.tv.jedis.stat.data;\n\nimport java.text.DecimalFormat;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.TreeMap;\nimport java.util.Map.Entry;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.ScheduledFuture;\nimport java.util.concurrent.TimeUnit;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.sohu.tv.jedis.stat.constant.ClientReportConstant;\nimport com.sohu.tv.jedis.stat.enums.ClientExceptionType;\nimport com.sohu.tv.jedis.stat.enums.ValueSizeDistriEnum;\nimport com.sohu.tv.jedis.stat.model.CostTimeDetailStatKey;\nimport com.sohu.tv.jedis.stat.model.CostTimeDetailStatModel;\nimport com.sohu.tv.jedis.stat.model.ExceptionModel;\nimport com.sohu.tv.jedis.stat.model.UsefulDataModel;\nimport com.sohu.tv.jedis.stat.model.ValueLengthModel;\nimport com.sohu.tv.jedis.stat.utils.AtomicLongMap;\nimport com.sohu.tv.jedis.stat.utils.DateUtils;\nimport com.sohu.tv.jedis.stat.utils.NamedThreadFactory;\nimport com.sohu.tv.jedis.stat.utils.NumberUtil;\n\n/**\n * jedis有价值数据收集器(耗时,值分布,异常等)\n * \n * @author leifu\n * @Date 2015年1月13日\n * @Time 下午5:42:31\n */\npublic class UsefulDataCollector {\n\n    private final static Logger logger = LoggerFactory.getLogger(UsefulDataCollector.class);\n\n    /**\n     * 耗时详细统计\n     */\n    private static ConcurrentHashMap<CostTimeDetailStatKey, AtomicLongMap<Integer>> DATA_COST_TIME_MAP_ALL = new ConcurrentHashMap<CostTimeDetailStatKey, AtomicLongMap<Integer>>();\n\n    /**\n     * 值分布统计\n     */\n    private static ConcurrentHashMap<String, AtomicLongMap<ValueLengthModel>> DATA_VALUE_LENGTH_DISTRIBUTE_MAP_ALL = new ConcurrentHashMap<String, AtomicLongMap<ValueLengthModel>>();\n\n    /**\n     * 异常详细统计\n     */\n    private static ConcurrentHashMap<String, AtomicLongMap<ExceptionModel>> DATA_EXCEPTION_MAP_ALL = new ConcurrentHashMap<String, AtomicLongMap<ExceptionModel>>();\n\n    /**\n     * 收集耗时统计(统计收集数据本身对于速度的影响)\n     */\n    private static ConcurrentHashMap<String, AtomicLongMap<Long>> COLLECTION_COST_TIME_MAP_ALL = new ConcurrentHashMap<String, AtomicLongMap<Long>>();\n\n    /**\n     * 数据定时清理\n     */\n    private final static ScheduledExecutorService jedisDataCleanScheduledExecutor = Executors.newScheduledThreadPool(2,\n            new NamedThreadFactory(\"jedisCleanScheduledExecutor\", true));\n    private static ScheduledFuture<?> jedisDataCleanScheduleFuture;\n    private final static int delay = 10;\n    private final static int fixCycle = 60;\n\n    static {\n        init();\n    }\n\n    public static void init() {\n        Thread jedisCleanDataThread = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                try {\n                    // 清理2分钟前数据\n                    Date date = DateUtils.addMinutes(new Date(), -2);\n                    String dateSdf = ClientReportConstant.getCollectTimeSDf().format(date);\n                    clearCostTime(dateSdf);\n                    clearException(dateSdf);\n                    clearValueLength(dateSdf);\n                    clearCollectionCost(dateSdf);\n                } catch (Exception e) {\n                    logger.error(\"jedisCleanData thread message is\" + e.getMessage(), e);\n                }\n            }\n        });\n        jedisCleanDataThread.setDaemon(true);\n\n        // 启动定时任务\n        jedisDataCleanScheduleFuture = jedisDataCleanScheduledExecutor\n                .scheduleWithFixedDelay(jedisCleanDataThread, delay, fixCycle,\n                        TimeUnit.SECONDS);\n    }\n\n    /**\n     * 关闭\n     */\n    public static void close() {\n        try {\n            jedisDataCleanScheduleFuture.cancel(true);\n        } catch (Throwable t) {\n            logger.error(t.getMessage(), t);\n        }\n    }\n\n    /**\n     * 收集耗时和值分布\n     * \n     * @param costModel\n     */\n    public static void collectCostAndValueDistribute(UsefulDataModel costModel) {\n        Long start = System.currentTimeMillis();\n        try {\n            // 基础数据\n            String currentMinute = ClientReportConstant.getCollectTimeSDf().format(new Date());\n            int cost = (int) costModel.getCost();\n            String command = costModel.getCommand();\n            String hostPort = costModel.getHostPort();\n            int valueBytesLength = costModel.getValueBytesLength();\n\n            // 耗时详细统计\n            CostTimeDetailStatKey costTimeDetailStatKey = new CostTimeDetailStatKey(currentMinute, command, hostPort);\n            if (DATA_COST_TIME_MAP_ALL.containsKey(costTimeDetailStatKey)) {\n                AtomicLongMap<Integer> stat = DATA_COST_TIME_MAP_ALL.get(costTimeDetailStatKey);\n                stat.getAndIncrement(cost);\n            } else {\n                AtomicLongMap<Integer> stat = AtomicLongMap.create();\n                stat.getAndIncrement(cost);\n                AtomicLongMap<Integer> currentStat = DATA_COST_TIME_MAP_ALL.putIfAbsent(costTimeDetailStatKey, stat);\n                if (currentStat != null) {\n                    currentStat.getAndIncrement(cost);\n                }\n            }\n\n            // 值分布\n            ValueSizeDistriEnum redisValueSizeEnum = ValueSizeDistriEnum.getRightSizeBetween(valueBytesLength);\n            if (redisValueSizeEnum != null) {\n                ValueLengthModel valueLengthModel = new ValueLengthModel(redisValueSizeEnum, costModel.getCommand(),\n                        costModel.getHostPort());\n                if (DATA_VALUE_LENGTH_DISTRIBUTE_MAP_ALL.containsKey(currentMinute)) {\n                    DATA_VALUE_LENGTH_DISTRIBUTE_MAP_ALL.get(currentMinute).getAndIncrement(valueLengthModel);\n                } else {\n                    AtomicLongMap<ValueLengthModel> dataValueLengthMap = AtomicLongMap.create();\n                    dataValueLengthMap.getAndIncrement(valueLengthModel);\n                    AtomicLongMap<ValueLengthModel> currentDataValueLengthMap = DATA_VALUE_LENGTH_DISTRIBUTE_MAP_ALL\n                            .putIfAbsent(currentMinute, dataValueLengthMap);\n                    if (currentDataValueLengthMap != null) {\n                        currentDataValueLengthMap.getAndIncrement(valueLengthModel);\n                    }\n                }\n            }\n\n            // 统计收集这件事本身的耗时\n            Long collectCostTime = System.currentTimeMillis() - start;\n            if (COLLECTION_COST_TIME_MAP_ALL.containsKey(currentMinute)) {\n                AtomicLongMap<Long> stat = COLLECTION_COST_TIME_MAP_ALL.get(currentMinute);\n                stat.getAndIncrement(collectCostTime);\n            } else {\n                AtomicLongMap<Long> stat = AtomicLongMap.create();\n                stat.getAndIncrement(collectCostTime);\n                AtomicLongMap<Long> currentStat = COLLECTION_COST_TIME_MAP_ALL.putIfAbsent(currentMinute, stat);\n                if (currentStat != null) {\n                    currentStat.getAndIncrement(collectCostTime);\n                }\n            }\n        } catch (Exception e) {\n            logger.error(\"collect data error: \" + e.getMessage());\n        }\n    }\n\n    /**\n     * 收集异常\n     * \n     * @param exception\n     * @param hostPort\n     * @param currentTime(保留)\n     */\n    public static void collectException(Exception exception, String hostPort, long currentTime) {\n        collectException(exception, hostPort, currentTime, ClientExceptionType.REDIS_TYPE);\n    }\n\n    /**\n     * 收集异常\n     * \n     * @param exception\n     * @param hostPort\n     * @param currentTime\n     * @param clientExceptionType（区分jedis还是client）\n     */\n    public static void collectException(Exception exception, String hostPort, long currentTime,\n            ClientExceptionType clientExceptionType) {\n        if (exception == null) {\n            return;\n        }\n        try {\n            // 当前分钟 yyyyMMddHHmm00\n            String currentMinute = ClientReportConstant.getCollectTimeSDf().format(new Date());\n\n            ExceptionModel jedisExceptionModel = new ExceptionModel();\n            String exceptionClassName = exception.getClass().getName();\n            jedisExceptionModel.setExceptionClass(exceptionClassName);\n            jedisExceptionModel.setHostPort(hostPort);\n            jedisExceptionModel.setClientExceptionType(clientExceptionType);\n\n            if (DATA_EXCEPTION_MAP_ALL.containsKey(currentMinute)) {\n                DATA_EXCEPTION_MAP_ALL.get(currentMinute).getAndIncrement(jedisExceptionModel);\n            } else {\n                AtomicLongMap<ExceptionModel> dataExcpetionMap = AtomicLongMap.create();\n                dataExcpetionMap.getAndIncrement(jedisExceptionModel);\n                AtomicLongMap<ExceptionModel> currentDataExcpetionMap = DATA_EXCEPTION_MAP_ALL.putIfAbsent(\n                        currentMinute, dataExcpetionMap);\n                if (currentDataExcpetionMap != null) {\n                    currentDataExcpetionMap.getAndIncrement(jedisExceptionModel);\n                }\n            }\n        } catch (Exception e) {\n            logger.error(\"collect exception error: \" + e.getMessage());\n        }\n    }\n\n    /**\n     * 清除targetMinute之前的耗时\n     * \n     * @param targetMinute\n     */\n    private static void clearCostTime(String targetMinute) {\n        try {\n            if (targetMinute == \"\" || \"\".equals(targetMinute)) {\n                return;\n            }\n            long targetMinuteLong = NumberUtil.toLong(targetMinute);\n            if (targetMinuteLong == 0) {\n                return;\n            }\n            for (CostTimeDetailStatKey key : DATA_COST_TIME_MAP_ALL.keySet()) {\n                long minute = NumberUtil.toLong(key.getCurrentMinute());\n                if (minute < targetMinuteLong) {\n                    DATA_COST_TIME_MAP_ALL.remove(key);\n                }\n            }\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n    }\n\n    /**\n     * 清除targetMinute之前的值分布\n     * \n     * @param targetMinute\n     */\n    private static void clearValueLength(String targetMinute) {\n        try {\n            if (targetMinute == \"\" || \"\".equals(targetMinute)) {\n                return;\n            }\n            long targetMinuteLong = NumberUtil.toLong(targetMinute);\n            if (targetMinuteLong == 0) {\n                return;\n            }\n            for (String key : DATA_VALUE_LENGTH_DISTRIBUTE_MAP_ALL.keySet()) {\n                long minute = NumberUtil.toLong(key);\n                if (minute < targetMinuteLong) {\n                    DATA_VALUE_LENGTH_DISTRIBUTE_MAP_ALL.remove(key);\n                }\n            }\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n    }\n\n    /**\n     * 清除收集数据耗时本身\n     * \n     * @param targetMinute\n     */\n    private static void clearCollectionCost(String targetMinute) {\n        try {\n            if (targetMinute == \"\" || \"\".equals(targetMinute)) {\n                return;\n            }\n            long targetMinuteLong = NumberUtil.toLong(targetMinute);\n            if (targetMinuteLong == 0) {\n                return;\n            }\n            for (String key : COLLECTION_COST_TIME_MAP_ALL.keySet()) {\n                long minute = NumberUtil.toLong(key);\n                if (minute < targetMinuteLong) {\n                    COLLECTION_COST_TIME_MAP_ALL.remove(key);\n                }\n            }\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n    }\n\n    /**\n     * 清除targetMinute之前的异常\n     * \n     * @param targetMinute\n     */\n    private static void clearException(String targetMinute) {\n        try {\n            if (targetMinute == \"\" || \"\".equals(targetMinute)) {\n                return;\n            }\n            long targetMinuteLong = NumberUtil.toLong(targetMinute);\n            if (targetMinuteLong == 0) {\n                return;\n            }\n            for (String key : DATA_EXCEPTION_MAP_ALL.keySet()) {\n                long minute = NumberUtil.toLong(key);\n                if (minute < targetMinuteLong) {\n                    DATA_EXCEPTION_MAP_ALL.remove(key);\n                }\n            }\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n    }\n\n    /**\n     * 获取上一分钟的值分布\n     * \n     * @param currentMinuteStamp\n     */\n    public static Map<ValueLengthModel, Long> getValueLengthLastMinute(String currentMinuteStamp) {\n        AtomicLongMap<ValueLengthModel> map = DATA_VALUE_LENGTH_DISTRIBUTE_MAP_ALL.get(currentMinuteStamp);\n        if (map == null || map.isEmpty()) {\n            return Collections.emptyMap();\n        }\n        return map.asMap();\n    }\n\n    /**\n     * 获取上一分钟的耗时\n     * \n     * @param currentMinuteStamp\n     */\n    public static Map<CostTimeDetailStatKey, AtomicLongMap<Integer>> getCostTimeLastMinute(String currentMinuteStamp) {\n        Map<CostTimeDetailStatKey, AtomicLongMap<Integer>> result = new HashMap<CostTimeDetailStatKey, AtomicLongMap<Integer>>();\n        for (Entry<CostTimeDetailStatKey, AtomicLongMap<Integer>> entry : DATA_COST_TIME_MAP_ALL.entrySet()) {\n            CostTimeDetailStatKey costTimeDetailStatKey = entry.getKey();\n            if (costTimeDetailStatKey != null && costTimeDetailStatKey.getCurrentMinute() != null\n                    && costTimeDetailStatKey.getCurrentMinute().equals(currentMinuteStamp)) {\n                result.put(costTimeDetailStatKey, entry.getValue());\n            }\n        }\n        return result;\n    }\n\n    /**\n     * 获取上一分钟的异常\n     * \n     * @param currentMinuteStamp\n     */\n    public static Map<ExceptionModel, Long> getExceptionLastMinute(String currentMinuteStamp) {\n        AtomicLongMap<ExceptionModel> map = DATA_EXCEPTION_MAP_ALL.get(currentMinuteStamp);\n        if (map == null || map.isEmpty()) {\n            return Collections.emptyMap();\n        }\n        return map.asMap();\n    }\n\n    /**\n     * 产生耗时详细分布\n     * \n     * @param statMap\n     */\n    public static CostTimeDetailStatModel generateCostTimeDetailStatKey(AtomicLongMap<Integer> statMap) {\n        CostTimeDetailStatModel model = new CostTimeDetailStatModel();\n        model.setMean(getMeanValue(statMap));\n        model.setMedian(fillCostTimeDetailStatModel(model, statMap, 50));\n        model.setNinetyPercentMax(fillCostTimeDetailStatModel(model, statMap, 90));\n        model.setNinetyNinePercentMax(fillCostTimeDetailStatModel(model, statMap, 99));\n        model.setHundredMax(fillCostTimeDetailStatModel(model, statMap, 100));\n        // 上面已经设置过了\n        // model.setTotalCount(getTotalValue(statMap));\n        return model;\n\n    }\n\n    /**\n     * 获取平均值\n     * \n     * @param statMap\n     */\n    private static double getMeanValue(AtomicLongMap<Integer> statMap) {\n        if (statMap == null || statMap.isEmpty()) {\n            return 0;\n        }\n        Map<Integer, Long> map = statMap.asMap();\n        Long totalCount = 0L;\n        Long totalValue = 0L;\n        for (Entry<Integer, Long> entry : map.entrySet()) {\n            totalCount += entry.getValue();\n            totalValue += entry.getKey() * entry.getValue();\n        }\n        DecimalFormat df = new DecimalFormat(\"#.00\");\n        Double result = totalValue * 1.0 / totalCount * 1.0;\n        return NumberUtil.toDouble(df.format(result));\n    }\n\n    /**\n     * 计算Integer-Long结构排序后，百分之多少所在的对应数据\n     * \n     * @param statMap\n     * @param percent\n     * @return\n     */\n    private static int fillCostTimeDetailStatModel(CostTimeDetailStatModel model, AtomicLongMap<Integer> statMap,\n            double percent) {\n        int wrongResultValue = 0;\n        if (percent > 100 || percent < 0) {\n            return wrongResultValue;\n        }\n        if (statMap == null || statMap.isEmpty()) {\n            return wrongResultValue;\n        }\n        Map<Integer, Long> sortKeyMap = new TreeMap<Integer, Long>(statMap.asMap());\n        Long totalSize = model.getTotalCount();\n        if (totalSize <= 0) {\n            for (Long count : sortKeyMap.values()) {\n                totalSize += count;\n            }\n            model.setTotalCount(totalSize);\n        }\n        return getPercentValue(totalSize, sortKeyMap, percent);\n    }\n\n    private static int getPercentValue(Long totalSize, Map<Integer, Long> sortKeyMap, double percent) {\n        // 计算百分比所在个数\n        Long targetLocation = (long) (totalSize * percent / 100.0);\n        Long count = 0L;\n        Integer key = 0;\n        for (Entry<Integer, Long> entry : sortKeyMap.entrySet()) {\n            key = entry.getKey();\n            count += entry.getValue();\n            if (count > targetLocation) {\n                break;\n            }\n        }\n        return key;\n    }\n\n    public static Map<CostTimeDetailStatKey, AtomicLongMap<Integer>> getDataCostTimeMapAll() {\n        return DATA_COST_TIME_MAP_ALL;\n    }\n\n    public static Map<String, AtomicLongMap<ValueLengthModel>> getDataValueLengthDistributeMapAll() {\n        return DATA_VALUE_LENGTH_DISTRIBUTE_MAP_ALL;\n    }\n\n    public static Map<String, AtomicLongMap<ExceptionModel>> getDataExceptionMapAll() {\n        return DATA_EXCEPTION_MAP_ALL;\n    }\n\n    public static Map<String, AtomicLongMap<Long>> getCollectionCostTimeMapAll() {\n        return COLLECTION_COST_TIME_MAP_ALL;\n    }\n\n    public static void setCOLLECTION_COST_TIME_MAP_ALL(ConcurrentHashMap<String, AtomicLongMap<Long>> cOLLECTION_COST_TIME_MAP_ALL) {\n        COLLECTION_COST_TIME_MAP_ALL = cOLLECTION_COST_TIME_MAP_ALL;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-jedis-stat/src/main/java/com/sohu/tv/jedis/stat/enums/ClientCollectDataTypeEnum.java",
    "content": "package com.sohu.tv.jedis.stat.enums;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * 上报类型\n * @author leifu\n * @Date 2015年1月13日\n * @Time 下午6:33:22\n */\npublic enum ClientCollectDataTypeEnum {\n    /**\n     * 耗时分布\n     */\n    COST_TIME_DISTRI_TYPE(1, \"cost_time_distri_type\"),\n    \n    /**\n     * 值大小分布\n     */\n    VALUE_LENGTH_DISTRI_TYPE(2, \"value_length_distri_type\"),\n    \n    /**\n     * 异常\n     */\n    EXCEPTION_TYPE(3, \"exception_type\");\n    \n    \n    public static Map<Integer, ClientCollectDataTypeEnum> MAP = new HashMap<Integer, ClientCollectDataTypeEnum>();\n    \n    static{\n        for(ClientCollectDataTypeEnum clientCollectDataTypeEnum : ClientCollectDataTypeEnum.values()){\n            MAP.put(clientCollectDataTypeEnum.getValue(), clientCollectDataTypeEnum);\n        }\n    }\n    \n\n    private int value;\n    private String info;\n\n    private ClientCollectDataTypeEnum(int value, String info) {\n        this.value = value;\n        this.info = info;\n    }\n\n    public String getInfo() {\n        return info;\n    }\n\n    public int getValue() {\n        return value;\n    }\n    \n    public static boolean isRightType(Integer type){\n        return MAP.containsKey(type);\n    }\n    \n    public static ClientCollectDataTypeEnum get(Integer type){\n        return MAP.get(type);\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-jedis-stat/src/main/java/com/sohu/tv/jedis/stat/enums/ClientExceptionType.java",
    "content": "package com.sohu.tv.jedis.stat.enums;\n\n/**\n * 错误类型\n * \n * @author leifu\n * @Date 2015年2月4日\n * @Time 下午4:54:02\n */\npublic enum ClientExceptionType {\n    /**\n     * redis产生的错误\n     */\n    REDIS_TYPE(1),\n    /**\n     * 客户端产生的错误(比如上报，定时线程抛出的异常)\n     */\n    CLIENT_EXCEPTION_TYPE(2),\n    \n    /**\n     * redis-cluster异常\n     */\n    REDIS_CLUSTER(3);\n\n    private int type;\n\n    private ClientExceptionType(int type) {\n        this.type = type;\n    }\n\n    public int getType() {\n        return type;\n    }\n\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-jedis-stat/src/main/java/com/sohu/tv/jedis/stat/enums/CostTimeDistriEnum.java",
    "content": "package com.sohu.tv.jedis.stat.enums;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport com.sohu.tv.jedis.stat.utils.NumberUtil;\n\n/**\n * 耗时分布\n * \n * @author leifu\n * @Date 2015年1月13日\n * @Time 下午5:22:28\n */\npublic enum CostTimeDistriEnum {\n    // 单位字节\n    BETWEEN_MIN_TO_0_MS(\"-2147483648_0\", \"非法\", 1),\n    BETWEEN_0_TO_1_MS(\"0_1\", \"0-1毫秒\", 2),\n    BETWEEN_1_TO_2_MS(\"1_2\", \"1-2毫秒\", 3),\n    BETWEEN_2_TO_5_MS(\"2_5\", \"2-5毫秒\", 4),\n    BETWEEN_5_TO_10_MS(\"5_10\", \"5-10毫秒\", 5),\n    BETWEEN_10_TO_50_MS(\"10_50\", \"10-50毫秒\", 6),\n    BETWEEN_50_TO_100_MS(\"50_100\", \"50-100毫秒\", 7),\n    BETWEEN_100_TO_MAX_MS(\"100_MAX\", \"100毫秒以上\", 8);\n\n    private String value;\n    private String info;\n    private int type;\n\n    private CostTimeDistriEnum(String value, String info, int type) {\n        this.value = value;\n        this.info = info;\n        this.type = type;\n    }\n\n    public String getValue() {\n        return value;\n    }\n\n    public String getInfo() {\n        return info;\n    }\n\n    public int getType() {\n        return type;\n    }\n\n    public final static Map<String, CostTimeDistriEnum> MAP = new HashMap<String, CostTimeDistriEnum>();\n    static {\n        for (CostTimeDistriEnum enumObject : CostTimeDistriEnum.values()) {\n            MAP.put(enumObject.getValue(), enumObject);\n        }\n    }\n    \n    public static CostTimeDistriEnum getByValue(String targetValue){\n        return MAP.get(targetValue);\n    }\n\n    /**\n     * 查看length在哪个区间\n     * \n     * @param length\n     * @return\n     */\n    public static CostTimeDistriEnum getRightCostDistri(int costTime) {\n        CostTimeDistriEnum[] enumArr = CostTimeDistriEnum.values();\n        for (CostTimeDistriEnum enumObject : enumArr) {\n            if (isInSize(enumObject, costTime)) {\n                return enumObject;\n            }\n        }\n        return null;\n    }\n\n    /**\n     * 确定length在指定区间\n     * \n     * @param enumObject\n     * @param size\n     * @return\n     */\n    private static boolean isInSize(CostTimeDistriEnum enumObject, int costTime) {\n        String value = enumObject.getValue();\n        int index = value.indexOf(\"_\");\n        int start = NumberUtil.toInt(value.substring(0, index));\n        int end = NumberUtil.toInt(value.substring(index + 1));\n        if (costTime >= start && costTime < end) {\n            return true;\n        }\n        return false;\n    }\n\n    public static void main(String[] args) {\n        // 获取活在字节区间\n        // CostTimeDistriEnum a = getRightCostDistri(6);\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-jedis-stat/src/main/java/com/sohu/tv/jedis/stat/enums/ValueSizeDistriEnum.java",
    "content": "package com.sohu.tv.jedis.stat.enums;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport com.sohu.tv.jedis.stat.utils.NumberUtil;\n\n/**\n * 值分布\n * \n * @author leifu\n * @Time 2014年7月21日\n */\npublic enum ValueSizeDistriEnum {\n    // 单位字节\n    BETWEEN_MIN_TO_0_BYTE(\"-2147483648_0\", \"wrong\", 0),\n    BETWEEN_0_TO_50_BYTE(\"0_50\", \"0-0.05k\", 1),\n    BETWEEN_50_TO_100_BYTE(\"50_100\", \"0.05k-0.1k\", 2),\n    BETWEEN_100_TO_200_BYTE(\"100_200\", \"0.1k-0.2k\", 3),\n    BETWEEN_200_TO_500_BYTE(\"200_500\", \"0.2k-0.5k\", 4),\n    BETWEEN_500_TO_1024_BYTE(\"500_1024\", \"0.5k-1k\", 5),\n    BETWEEN_1024_TO_2048_BYTE(\"1024_2048\", \"1-2k\", 6),\n    BETWEEN_2048_TO_5120_BYTE(\"2048_5120\", \"2-5k\", 7),\n    BETWEEN_5120_TO_10240_BYTE(\"5120_10240\", \"5-10k\", 8),\n    BETWEEN_10240_TO_20480_BYTE(\"10240_20480\", \"10-20k\", 9),\n    BETWEEN_20480_TO_51200_BYTE(\"20480_51200\", \"20-50k\", 10),\n    BETWEEN_51200_TO_102400_BYTE(\"51200_102400\", \"50-100k\", 11),\n    BETWEEN_102400_TO_204800_BYTE(\"102400_204800\", \"100-200k\", 12),\n    BETWEEN_204800_TO_512000_BYTE(\"204800_512000\", \"200-500k\", 13),\n    BETWEEN_512000_TO_MAX_BYTE(\"512000_2147483647\", \"above 500k\", 14);\n\n    private String value;\n    private String info;\n    private int type;\n\n    private ValueSizeDistriEnum(String value, String info, int type) {\n        this.value = value;\n        this.info = info;\n        this.type = type;\n    }\n\n    public int getType() {\n        return type;\n    }\n\n    public String getValue() {\n        return value;\n    }\n\n    public String getInfo() {\n        return info;\n    }\n    \n    public final static Map<String, ValueSizeDistriEnum> MAP = new HashMap<String, ValueSizeDistriEnum>();\n    static {\n        for (ValueSizeDistriEnum enumObject : ValueSizeDistriEnum.values()) {\n            MAP.put(enumObject.getValue(), enumObject);\n        }\n    }\n    \n    public static ValueSizeDistriEnum getByValue(String targetValue){\n        return MAP.get(targetValue);\n    }\n\n    /**\n     * 查看length在哪个区间\n     * \n     * @param length\n     * @return\n     */\n    public static ValueSizeDistriEnum getRightSizeBetween(int size) {\n        ValueSizeDistriEnum[] enumArr = ValueSizeDistriEnum.values();\n        for (ValueSizeDistriEnum enumObject : enumArr) {\n            if (isInSize(enumObject, size)) {\n                return enumObject;\n            }\n        }\n        return null;\n    }\n\n    /**\n     * 确定length在指定区间\n     * \n     * @param enumObject\n     * @param size\n     * @return\n     */\n    private static boolean isInSize(ValueSizeDistriEnum enumObject, int size) {\n        String value = enumObject.getValue();\n        int index = value.indexOf(\"_\");\n        int start = NumberUtil.toInt(value.substring(0, index));\n        int end = NumberUtil.toInt(value.substring(index + 1));\n        if (size >= start && size < end) {\n            return true;\n        }\n        return false;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-jedis-stat/src/main/java/com/sohu/tv/jedis/stat/model/ClientReportBean.java",
    "content": "package com.sohu.tv.jedis.stat.model;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 上报实体\n * \n * @author leifu\n * @Date 2015年1月16日\n * @Time 下午3:01:06\n */\npublic class ClientReportBean {\n\t\n    /**\n     * 客户端ip\n     */\n    private String clientIp;\n\n    /**\n     * 收集时间\n     */\n    private long collectTime;\n    \n    /**\n     * 上报时间\n     */\n    private long reportTimeStamp;\n\n    /**\n     * 上报数据\n     */\n    private List<Map<String, Object>> datas;\n    \n    /**\n     * 其他信息\n     */\n    private Map<String,Object> otherInfo;\n\n    public ClientReportBean() {\n    }\n\n\tpublic ClientReportBean(String clientIp, long collectTime, long reportTimeStamp, List<Map<String, Object>> datas,\n            Map<String, Object> otherInfo) {\n        this.clientIp = clientIp;\n        this.collectTime = collectTime;\n        this.reportTimeStamp = reportTimeStamp;\n        this.datas = datas;\n        this.otherInfo = otherInfo;\n    }\n\n    public String getClientIp() {\n        return clientIp;\n    }\n\n    public void setClientIp(String clientIp) {\n        this.clientIp = clientIp;\n    }\n\n    public long getCollectTime() {\n        return collectTime;\n    }\n\n    public void setCollectTime(long collectTime) {\n        this.collectTime = collectTime;\n    }\n\n    public List<Map<String, Object>> getDatas() {\n        return datas;\n    }\n\n    public void setDatas(List<Map<String, Object>> datas) {\n        this.datas = datas;\n    }\n\n\n    public long getReportTimeStamp() {\n        return reportTimeStamp;\n    }\n\n    public void setReportTimeStamp(long reportTimeStamp) {\n        this.reportTimeStamp = reportTimeStamp;\n    }\n\n    public Map<String, Object> getOtherInfo() {\n        return otherInfo;\n    }\n\n    public void setOtherInfo(Map<String, Object> otherInfo) {\n        this.otherInfo = otherInfo;\n    }\n\n    @Override\n    public String toString() {\n        return \"ClientReportBean [clientIp=\" + clientIp + \", collectTime=\" + collectTime + \", reportTimeStamp=\"\n                + reportTimeStamp + \", datas=\" + datas + \", otherInfo=\" + otherInfo + \"]\";\n    }\n\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-jedis-stat/src/main/java/com/sohu/tv/jedis/stat/model/CostTimeDetailStatKey.java",
    "content": "package com.sohu.tv.jedis.stat.model;\n\n/**\n * 耗时详细统计key\n * \n * @author leifu\n * @Date 2015年1月23日\n * @Time 上午11:24:58\n */\npublic class CostTimeDetailStatKey {\n\n    /**\n     * 当前分钟 yyyyMMddHHmm00\n     */\n    private String currentMinute;\n\n    /**\n     * 命令\n     */\n    private String command;\n\n    /**\n     * ip:port\n     */\n    private String hostPort;\n\n    public CostTimeDetailStatKey() {\n    }\n\n    public CostTimeDetailStatKey(String currentMinute, String command, String hostPort) {\n        this.currentMinute = currentMinute;\n        this.command = command;\n        this.hostPort = hostPort;\n    }\n\n    public String getCurrentMinute() {\n        return currentMinute;\n    }\n\n    public void setCurrentMinute(String currentMinute) {\n        this.currentMinute = currentMinute;\n    }\n\n    public String getCommand() {\n        return command;\n    }\n\n    public void setCommand(String command) {\n        this.command = command;\n    }\n\n    public String getHostPort() {\n        return hostPort;\n    }\n\n    public void setHostPort(String hostPort) {\n        this.hostPort = hostPort;\n    }\n\n    public String getUiqueKey() {\n        return currentMinute + \"_\" + hostPort + \"_\" + command;\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((command == null) ? 0 : command.hashCode());\n        result = prime * result + ((currentMinute == null) ? 0 : currentMinute.hashCode());\n        result = prime * result + ((hostPort == null) ? 0 : hostPort.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj)\n            return true;\n        if (obj == null)\n            return false;\n        if (getClass() != obj.getClass())\n            return false;\n        CostTimeDetailStatKey other = (CostTimeDetailStatKey) obj;\n        if (command == null) {\n            if (other.command != null)\n                return false;\n        } else if (!command.equals(other.command))\n            return false;\n        if (currentMinute == null) {\n            if (other.currentMinute != null)\n                return false;\n        } else if (!currentMinute.equals(other.currentMinute))\n            return false;\n        if (hostPort == null) {\n            if (other.hostPort != null)\n                return false;\n        } else if (!hostPort.equals(other.hostPort))\n            return false;\n        return true;\n    }\n\n    @Override\n    public String toString() {\n        return \"CostTimeDetailStatKey [currentMinute=\" + currentMinute + \", command=\" + command + \", hostPort=\"\n                + hostPort + \"]\";\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-jedis-stat/src/main/java/com/sohu/tv/jedis/stat/model/CostTimeDetailStatModel.java",
    "content": "package com.sohu.tv.jedis.stat.model;\n\n/**\n * 耗时详细统计(平均值、中位值、多维度最大值等等)\n * @author leifu\n * @Date 2015年1月23日\n * @Time 上午11:23:20\n */\npublic class CostTimeDetailStatModel {\n\n    /**\n     * 中位值\n     */\n    private int median;\n\n    /**\n     * 平均值\n     */\n    private double mean;\n\n    /**\n     * 90%最大值\n     */\n    private int ninetyPercentMax;\n\n    /**\n     * 99%最大值\n     */\n    private int ninetyNinePercentMax;\n\n    /**\n     * 100%最大值\n     */\n    private int hundredMax;\n    \n    /**\n     * 总次数\n     */\n    private long totalCount;\n\n    public int getMedian() {\n        return median;\n    }\n\n    public void setMedian(int median) {\n        this.median = median;\n    }\n\n    public double getMean() {\n        return mean;\n    }\n\n    public void setMean(double mean) {\n        this.mean = mean;\n    }\n\n    public int getNinetyPercentMax() {\n        return ninetyPercentMax;\n    }\n\n    public void setNinetyPercentMax(int ninetyPercentMax) {\n        this.ninetyPercentMax = ninetyPercentMax;\n    }\n\n    public int getNinetyNinePercentMax() {\n        return ninetyNinePercentMax;\n    }\n\n    public void setNinetyNinePercentMax(int ninetyNinePercentMax) {\n        this.ninetyNinePercentMax = ninetyNinePercentMax;\n    }\n\n    public int getHundredMax() {\n        return hundredMax;\n    }\n\n    public void setHundredMax(int hundredMax) {\n        this.hundredMax = hundredMax;\n    }\n\n    public long getTotalCount() {\n        return totalCount;\n    }\n\n    public void setTotalCount(long totalCount) {\n        this.totalCount = totalCount;\n    }\n\n    @Override\n    public String toString() {\n        return \"CostTimeDetailStatModel [median=\" + median + \", mean=\" + mean + \", ninetyPercentMax=\"\n                + ninetyPercentMax + \", ninetyNinePercentMax=\" + ninetyNinePercentMax + \", hundredMax=\" + hundredMax\n                + \", totalCount=\" + totalCount + \"]\";\n    }\n\n\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-jedis-stat/src/main/java/com/sohu/tv/jedis/stat/model/CostTimeModel.java",
    "content": "package com.sohu.tv.jedis.stat.model;\n\nimport com.sohu.tv.jedis.stat.enums.CostTimeDistriEnum;\n\n/**\n * 耗时model,作为AtomicLongMap的key\n * \n * @author leifu\n * @Date 2015年1月13日\n * @Time 下午5:47:27\n */\npublic class CostTimeModel{\n    /**\n     * 耗时区间枚举\n     */\n    private CostTimeDistriEnum redisCostTimeDistriEnum;\n\n    /**\n     * 命令\n     */\n    private String command;\n    \n    /**\n     * ip:port\n     */\n    private String hostPort;\n    \n    public CostTimeModel(CostTimeDistriEnum redisCostTimeDistriEnum, String command, String hostPort) {\n        this.redisCostTimeDistriEnum = redisCostTimeDistriEnum;\n        this.command = command;\n        this.hostPort = hostPort;\n    }\n\n    public CostTimeDistriEnum getRedisCostTimeDistriEnum() {\n        return redisCostTimeDistriEnum;\n    }\n\n    public String getCommand() {\n        return command;\n    }\n\n    public String getHostPort() {\n        return hostPort;\n    }\n\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((command == null) ? 0 : command.hashCode());\n        result = prime * result + ((hostPort == null) ? 0 : hostPort.hashCode());\n        result = prime * result + ((redisCostTimeDistriEnum == null) ? 0 : redisCostTimeDistriEnum.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj)\n            return true;\n        if (obj == null)\n            return false;\n        if (getClass() != obj.getClass())\n            return false;\n        CostTimeModel other = (CostTimeModel) obj;\n        if (command == null) {\n            if (other.command != null)\n                return false;\n        } else if (!command.equals(other.command))\n            return false;\n        if (hostPort == null) {\n            if (other.hostPort != null)\n                return false;\n        } else if (!hostPort.equals(other.hostPort))\n            return false;\n        if (redisCostTimeDistriEnum != other.redisCostTimeDistriEnum)\n            return false;\n        return true;\n    }\n\n    @Override\n    public String toString() {\n        return \"CostTimeModel [redisCostTimeDistriEnum=\" + redisCostTimeDistriEnum + \", command=\" + command\n                + \", hostPort=\" + hostPort + \"]\";\n    }\n\n    \n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-jedis-stat/src/main/java/com/sohu/tv/jedis/stat/model/ExceptionModel.java",
    "content": "package com.sohu.tv.jedis.stat.model;\n\nimport com.sohu.tv.jedis.stat.enums.ClientExceptionType;\n\n/**\n * jedis异常(exceptionClass,hostPort作为唯一哈希)\n * @author leifu\n * @Date 2015年1月13日\n * @Time 下午6:00:35\n */\npublic class ExceptionModel{\n    \n    /**\n     * 异常类\n     */\n    private String exceptionClass;\n    \n    /**\n     * ip:port\n     */\n    private String hostPort;\n    \n    /**\n     * 异常类型\n     */\n    private ClientExceptionType clientExceptionType;\n    \n    public String getExceptionClass() {\n\t\treturn exceptionClass;\n\t}\n\n\tpublic void setExceptionClass(String exceptionClass) {\n\t\tthis.exceptionClass = exceptionClass;\n\t}\n\n    public String getHostPort() {\n        return hostPort;\n    }\n\n    public void setHostPort(String hostPort) {\n        this.hostPort = hostPort;\n    }\n    \n    public ClientExceptionType getClientExceptionType() {\n        return clientExceptionType;\n    }\n\n    public void setClientExceptionType(ClientExceptionType clientExceptionType) {\n        this.clientExceptionType = clientExceptionType;\n    }\n\n    public String getUniqKey(){\n    \treturn hostPort + \"_\" + exceptionClass;\n    }\n\n\t@Override\n\tpublic int hashCode() {\n\t\tfinal int prime = 31;\n\t\tint result = 1;\n\t\tresult = prime * result\n\t\t\t\t+ ((exceptionClass == null) ? 0 : exceptionClass.hashCode());\n\t\tresult = prime * result\n\t\t\t\t+ ((hostPort == null) ? 0 : hostPort.hashCode());\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic boolean equals(Object obj) {\n\t\tif (this == obj)\n\t\t\treturn true;\n\t\tif (obj == null)\n\t\t\treturn false;\n\t\tif (getClass() != obj.getClass())\n\t\t\treturn false;\n\t\tExceptionModel other = (ExceptionModel) obj;\n\t\tif (exceptionClass == null) {\n\t\t\tif (other.exceptionClass != null)\n\t\t\t\treturn false;\n\t\t} else if (!exceptionClass.equals(other.exceptionClass))\n\t\t\treturn false;\n\t\tif (hostPort == null) {\n\t\t\tif (other.hostPort != null)\n\t\t\t\treturn false;\n\t\t} else if (!hostPort.equals(other.hostPort))\n\t\t\treturn false;\n\t\treturn true;\n\t}\n\n    @Override\n    public String toString() {\n        return \"ExceptionModel [exceptionClass=\" + exceptionClass + \", hostPort=\" + hostPort + \", clientExceptionType=\"\n                + clientExceptionType + \"]\";\n    }\n\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-jedis-stat/src/main/java/com/sohu/tv/jedis/stat/model/UsefulDataModel.java",
    "content": "package com.sohu.tv.jedis.stat.model;\n\n/**\n * 从jedis收集有价值的数据简单模型\n * \n * @author leifu\n * @Date 2015年1月13日\n * @Time 下午3:42:01\n */\npublic class UsefulDataModel {\n    /**\n     * sendCommand开始时间\n     */\n    private long startTime;\n\n    /**\n     * process结束时间\n     */\n    private long endTime;\n\n    /**\n     * 命令名\n     */\n    private String command;\n\n    /**\n     * 值大小\n     */\n    private int valueBytesLength;\n    \n    /**\n     * host:ip\n     */\n    private String hostPort;\n\n    public long getStartTime() {\n        return startTime;\n    }\n\n    public void setStartTime(long startTime) {\n        this.startTime = startTime;\n    }\n\n    public long getEndTime() {\n        return endTime;\n    }\n\n    public void setEndTime(long endTime) {\n        this.endTime = endTime;\n    }\n\n    public String getCommand() {\n        return command;\n    }\n\n    public void setCommand(String command) {\n        this.command = command;\n    }\n\n    public int getValueBytesLength() {\n        return valueBytesLength;\n    }\n\n    public void setValueBytesLength(int valueBytesLength) {\n        this.valueBytesLength = valueBytesLength;\n    }\n\n    private UsefulDataModel() {\n        super();\n    }\n\n    public long getCost() {\n        return this.endTime - this.startTime;\n    }\n\n    public String getHostPort() {\n        return hostPort;\n    }\n\n    public void setHostPort(String hostPort) {\n        this.hostPort = hostPort;\n    }\n\n    /**\n     * 从ThreadLocal里面获取JedisUsefulData\n     * \n     * @param threadLocal\n     * @return\n     */\n    public static UsefulDataModel getCostModel(ThreadLocal<UsefulDataModel> threadLocal) {\n        UsefulDataModel costModel = threadLocal.get();\n        if (costModel == null) {\n            costModel = new UsefulDataModel();\n            threadLocal.set(costModel);\n        }\n        return costModel;\n    }\n\n    @Override\n    public String toString() {\n        return \"UsefulDataModel [startTime=\" + startTime + \", endTime=\" + endTime + \", command=\" + command\n                + \", valueBytesLength=\" + valueBytesLength + \", costTime=\" + (endTime - startTime) + \"ms]\";\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-jedis-stat/src/main/java/com/sohu/tv/jedis/stat/model/ValueLengthModel.java",
    "content": "package com.sohu.tv.jedis.stat.model;\n\nimport com.sohu.tv.jedis.stat.enums.ValueSizeDistriEnum;\n\n/**\n * 值分布\n * @author leifu\n * @Date 2015年1月14日\n * @Time 上午10:47:51\n */\npublic class ValueLengthModel{\n    /**\n     * 值分布区间枚举\n     */\n    private ValueSizeDistriEnum redisValueSizeEnum;\n    \n    /**\n     * 命令\n     */\n    private String command;\n    \n    /**\n     * ip:port\n     */\n    private String hostPort;\n    \n\n    public ValueLengthModel(ValueSizeDistriEnum redisValueSizeEnum, String command, String hostPort) {\n        this.redisValueSizeEnum = redisValueSizeEnum;\n        this.command = command;\n        this.hostPort = hostPort;\n    }\n\n    public ValueSizeDistriEnum getRedisValueSizeEnum() {\n        return redisValueSizeEnum;\n    }\n\n    public String getCommand() {\n        return command;\n    }\n\n    public String getHostPort() {\n        return hostPort;\n    }\n    \n    public String getUniqKey(){\n    \treturn redisValueSizeEnum.getValue() + \"_\" + hostPort + \"_\" + command;\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((command == null) ? 0 : command.hashCode());\n        result = prime * result + ((hostPort == null) ? 0 : hostPort.hashCode());\n        result = prime * result + ((redisValueSizeEnum == null) ? 0 : redisValueSizeEnum.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj)\n            return true;\n        if (obj == null)\n            return false;\n        if (getClass() != obj.getClass())\n            return false;\n        ValueLengthModel other = (ValueLengthModel) obj;\n        if (command == null) {\n            if (other.command != null)\n                return false;\n        } else if (!command.equals(other.command))\n            return false;\n        if (hostPort == null) {\n            if (other.hostPort != null)\n                return false;\n        } else if (!hostPort.equals(other.hostPort))\n            return false;\n        if (redisValueSizeEnum != other.redisValueSizeEnum)\n            return false;\n        return true;\n    }\n\n    @Override\n    public String toString() {\n        return \"ValueLengthModel [redisValueSizeEnum=\" + redisValueSizeEnum + \", command=\" + command\n                + \", hostPort=\" + hostPort + \"]\";\n    }\n\n\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-jedis-stat/src/main/java/com/sohu/tv/jedis/stat/utils/AtomicLongMap.java",
    "content": "package com.sohu.tv.jedis.stat.utils;\n\nimport java.util.Collections;\nimport java.util.LinkedHashMap;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.atomic.AtomicLong;\n\n/**\n * A map containing {@code long} values that can be atomically updated. While writes to a\n * traditional {@code Map} rely on {@code put(K, V)}, the typical mechanism for writing to this map\n * is {@code addAndGet(K, long)}, which adds a {@code long} to the value currently associated with\n * {@code K}. If a key has not yet been associated with a value, its implicit value is zero.\n * <p/>\n * <p>Most methods in this class treat absent values and zero values identically, as individually\n * documented. Exceptions to this are {@link #containsKey}, {@link #size}, {@link #isEmpty},\n *  and {@link #toString}.\n * <p/>\n * <p>Instances of this class may be used by multiple threads concurrently. All operations are\n * atomic unless otherwise noted.\n * <p/>\n * <p/>\n * <b>Warning:</b> Unlike {@code Multiset}, entries whose values are zero are not automatically\n * removed from the map. Instead they must be removed manually with {@link #removeAllZeros}.\n *\n * @author Charles Fry\n * @since 11.0\n */\npublic class AtomicLongMap<K> {\n    private final ConcurrentHashMap<K, AtomicLong> map;\n\n    private AtomicLongMap(ConcurrentHashMap<K, AtomicLong> map) {\n        this.map = map;\n    }\n\n    /**\n     * Creates an {@code AtomicLongMap}.\n     */\n    public static <K> AtomicLongMap<K> create() {\n        return new AtomicLongMap<K>(new ConcurrentHashMap<K, AtomicLong>());\n    }\n\n    /**\n     * Creates an {@code AtomicLongMap} with the same mappings as the specified {@code Map}.\n     */\n    public static <K> AtomicLongMap<K> create(Map<? extends K, ? extends Long> m) {\n        AtomicLongMap<K> result = create();\n        result.putAll(m);\n        return result;\n    }\n\n    /**\n     * Returns the value associated with {@code key}, or zero if there is no value associated with\n     * {@code key}.\n     */\n    public long get(K key) {\n        AtomicLong atomic = map.get(key);\n        return atomic == null ? 0L : atomic.get();\n    }\n\n    /**\n     * Increments by one the value currently associated with {@code key}, and returns the new value.\n     */\n    public long incrementAndGet(K key) {\n        return addAndGet(key, 1);\n    }\n\n    /**\n     * Decrements by one the value currently associated with {@code key}, and returns the new value.\n     */\n    public long decrementAndGet(K key) {\n        return addAndGet(key, -1);\n    }\n\n    /**\n     * Adds {@code delta} to the value currently associated with {@code key}, and returns the new\n     * value.\n     */\n    public long addAndGet(K key, long delta) {\n        outer:\n        for (; ; ) {\n            AtomicLong atomic = map.get(key);\n            if (atomic == null) {\n                atomic = map.putIfAbsent(key, new AtomicLong(delta));\n                if (atomic == null) {\n                    return delta;\n                }\n                // atomic is now non-null; fall through\n            }\n\n            for (; ; ) {\n                long oldValue = atomic.get();\n                if (oldValue == 0L) {\n                    // don't compareAndSet a zero\n                    if (map.replace(key, atomic, new AtomicLong(delta))) {\n                        return delta;\n                    }\n                    // atomic replaced\n                    continue outer;\n                }\n\n                long newValue = oldValue + delta;\n                if (atomic.compareAndSet(oldValue, newValue)) {\n                    return newValue;\n                }\n                // value changed\n            }\n        }\n    }\n\n    /**\n     * Increments by one the value currently associated with {@code key}, and returns the old value.\n     */\n    public long getAndIncrement(K key) {\n        return getAndAdd(key, 1);\n    }\n\n    /**\n     * Decrements by one the value currently associated with {@code key}, and returns the old value.\n     */\n    public long getAndDecrement(K key) {\n        return getAndAdd(key, -1);\n    }\n\n    /**\n     * Adds {@code delta} to the value currently associated with {@code key}, and returns the old\n     * value.\n     */\n    public long getAndAdd(K key, long delta) {\n        outer:\n        for (; ; ) {\n            AtomicLong atomic = map.get(key);\n            if (atomic == null) {\n                atomic = map.putIfAbsent(key, new AtomicLong(delta));\n                if (atomic == null) {\n                    return 0L;\n                }\n                // atomic is now non-null; fall through\n            }\n\n            for (; ; ) {\n                long oldValue = atomic.get();\n                if (oldValue == 0L) {\n                    // don't compareAndSet a zero\n                    if (map.replace(key, atomic, new AtomicLong(delta))) {\n                        return 0L;\n                    }\n                    // atomic replaced\n                    continue outer;\n                }\n\n                long newValue = oldValue + delta;\n                if (atomic.compareAndSet(oldValue, newValue)) {\n                    return oldValue;\n                }\n                // value changed\n            }\n        }\n    }\n\n    /**\n     * Associates {@code newValue} with {@code key} in this map, and returns the value previously\n     * associated with {@code key}, or zero if there was no such value.\n     */\n    public long put(K key, long newValue) {\n        outer:\n        for (; ; ) {\n            AtomicLong atomic = map.get(key);\n            if (atomic == null) {\n                atomic = map.putIfAbsent(key, new AtomicLong(newValue));\n                if (atomic == null) {\n                    return 0L;\n                }\n                // atomic is now non-null; fall through\n            }\n\n            for (; ; ) {\n                long oldValue = atomic.get();\n                if (oldValue == 0L) {\n                    // don't compareAndSet a zero\n                    if (map.replace(key, atomic, new AtomicLong(newValue))) {\n                        return 0L;\n                    }\n                    // atomic replaced\n                    continue outer;\n                }\n\n                if (atomic.compareAndSet(oldValue, newValue)) {\n                    return oldValue;\n                }\n                // value changed\n            }\n        }\n    }\n\n    /**\n     * Copies all of the mappings from the specified map to this map. The effect of this call is\n     * equivalent to that of calling {@code put(k, v)} on this map once for each mapping from key\n     * {@code k} to value {@code v} in the specified map. The behavior of this operation is undefined\n     * if the specified map is modified while the operation is in progress.\n     */\n    public void putAll(Map<? extends K, ? extends Long> m) {\n        for (Map.Entry<? extends K, ? extends Long> entry : m.entrySet()) {\n            put(entry.getKey(), entry.getValue());\n        }\n    }\n\n    /**\n     * Removes and returns the value associated with {@code key}. If {@code key} is not\n     * in the map, this method has no effect and returns zero.\n     */\n    public long remove(K key) {\n        AtomicLong atomic = map.get(key);\n        if (atomic == null) {\n            return 0L;\n        }\n\n        for (; ; ) {\n            long oldValue = atomic.get();\n            if (oldValue == 0L || atomic.compareAndSet(oldValue, 0L)) {\n                // only remove after setting to zero, to avoid concurrent updates\n                map.remove(key, atomic);\n                // succeed even if the remove fails, since the value was already adjusted\n                return oldValue;\n            }\n        }\n    }\n\n    /**\n     * Removes all mappings from this map whose values are zero.\n     * <p/>\n     * <p>This method is not atomic: the map may be visible in intermediate states, where some\n     * of the zero values have been removed and others have not.\n     */\n    public void removeAllZeros() {\n        for (K key : map.keySet()) {\n            AtomicLong atomic = map.get(key);\n            if (atomic != null && atomic.get() == 0L) {\n                map.remove(key, atomic);\n            }\n        }\n    }\n\n    /**\n     * Returns the sum of all values in this map.\n     * <p/>\n     * <p>This method is not atomic: the sum may or may not include other concurrent operations.\n     */\n    public long sum() {\n        long sum = 0L;\n        for (AtomicLong value : map.values()) {\n            sum = sum + value.get();\n        }\n        return sum;\n    }\n\n    /**\n     * Returns true if this map contains a mapping for the specified key.\n     */\n    public boolean containsKey(Object key) {\n        return map.containsKey(key);\n    }\n\n    /**\n     * Returns the number of key-value mappings in this map. If the map contains more than\n     * {@code Integer.MAX_VALUE} elements, returns {@code Integer.MAX_VALUE}.\n     */\n    public int size() {\n        return map.size();\n    }\n\n    /**\n     * Returns {@code true} if this map contains no key-value mappings.\n     */\n    public boolean isEmpty() {\n        return map.isEmpty();\n    }\n\n    /**\n     * Removes all of the mappings from this map. The map will be empty after this call returns.\n     * <p/>\n     * <p>This method is not atomic: the map may not be empty after returning if there were concurrent\n     * writes.\n     */\n    public void clear() {\n        map.clear();\n    }\n\n    @Override\n    public String toString() {\n        return map.toString();\n    }\n\n  /*\n   * ConcurrentMap operations which we may eventually add.\n   *\n   * The problem with these is that remove(K, long) has to be done in two phases by definition ---\n   * first decrementing to zero, and then removing. putIfAbsent or replace could observe the\n   * intermediate zero-state. Ways we could deal with this are:\n   *\n   * - Don't define any of the ConcurrentMap operations. This is the current state of affairs.\n   *\n   * - Define putIfAbsent and replace as treating zero and absent identically (as currently\n   *   implemented below). This is a bit surprising with putIfAbsent, which really becomes\n   *   putIfZero.\n   *\n   * - Allow putIfAbsent and replace to distinguish between zero and absent, but don't implement\n   *   remove(K, long). Without any two-phase operations it becomes feasible for all remaining\n   *   operations to distinguish between zero and absent. If we do this, then perhaps we should add\n   *   replace(key, long).\n   *\n   * - Introduce a special-value private static final AtomicLong that would have the meaning of\n   *   removal-in-progress, and rework all operations to properly distinguish between zero and\n   *   absent.\n   */\n\n    /**\n     * If {@code key} is not already associated with a value or if {@code key} is associated with\n     * zero, associate it with {@code newValue}. Returns the previous value associated with\n     * {@code key}, or zero if there was no mapping for {@code key}.\n     */\n    long putIfAbsent(K key, long newValue) {\n        for (; ; ) {\n            AtomicLong atomic = map.get(key);\n            if (atomic == null) {\n                atomic = map.putIfAbsent(key, new AtomicLong(newValue));\n                if (atomic == null) {\n                    return 0L;\n                }\n                // atomic is now non-null; fall through\n            }\n\n            long oldValue = atomic.get();\n            if (oldValue == 0L) {\n                // don't compareAndSet a zero\n                if (map.replace(key, atomic, new AtomicLong(newValue))) {\n                    return 0L;\n                }\n                // atomic replaced\n                continue;\n            }\n\n            return oldValue;\n        }\n    }\n\n    /**\n     * If {@code (key, expectedOldValue)} is currently in the map, this method replaces\n     * {@code expectedOldValue} with {@code newValue} and returns true; otherwise, this method\n     * returns false.\n     * <p/>\n     * <p>If {@code expectedOldValue} is zero, this method will succeed if {@code (key, zero)}\n     * is currently in the map, or if {@code key} is not in the map at all.\n     */\n    boolean replace(K key, long expectedOldValue, long newValue) {\n        if (expectedOldValue == 0L) {\n            return putIfAbsent(key, newValue) == 0L;\n        } else {\n            AtomicLong atomic = map.get(key);\n            return (atomic == null) ? false : atomic.compareAndSet(expectedOldValue, newValue);\n        }\n    }\n\n    /**\n     * If {@code (key, value)} is currently in the map, this method removes it and returns\n     * true; otherwise, this method returns false.\n     */\n    boolean remove(K key, long value) {\n        AtomicLong atomic = map.get(key);\n        if (atomic == null) {\n            return false;\n        }\n\n        long oldValue = atomic.get();\n        if (oldValue != value) {\n            return false;\n        }\n\n        if (oldValue == 0L || atomic.compareAndSet(oldValue, 0L)) {\n            // only remove after setting to zero, to avoid concurrent updates\n            map.remove(key, atomic);\n            // succeed even if the remove fails, since the value was already adjusted\n            return true;\n        }\n\n        // value changed\n        return false;\n    }\n    \n//    private transient Map<K, Long> asMap;\n\n    /**\n     * Returns a live, read-only view of the map backing this {@code AtomicLongMap}.\n     */\n    public Map<K, Long> asMap() {\n//      Map<K, Long> result = asMap;\n//      return (result == null) ? asMap = createAsMap() : result;\n      return createAsMap();\n    }\n\n    private Map<K, Long> createAsMap() {\n        Map<K,Long> resultMap = new LinkedHashMap<K, Long>();\n        if(map != null && !map.isEmpty()){\n            for(Entry<K, AtomicLong> entry : map.entrySet()){\n                resultMap.put(entry.getKey(), entry.getValue().get());\n            }\n        }\n        return Collections.unmodifiableMap(resultMap);\n    }\n\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-jedis-stat/src/main/java/com/sohu/tv/jedis/stat/utils/DateUtils.java",
    "content": "package com.sohu.tv.jedis.stat.utils;\n\nimport java.text.SimpleDateFormat;\nimport java.util.Calendar;\nimport java.util.Date;\n\n/**\n * 简易DateUtils\n * @author leifu\n * @Date 2015年1月15日\n * @Time 上午11:43:31\n */\npublic class DateUtils {\n\n    public static String formatDate(Date date, String format) {\n        SimpleDateFormat sdf = new SimpleDateFormat(format);\n        return sdf.format(date);\n    }\n    \n    public static Date add(Date date, int calendarField, int amount) {\n        if (date == null) {\n            throw new IllegalArgumentException(\"The date must not be null\");\n        }\n        Calendar c = Calendar.getInstance();\n        c.setTime(date);\n        c.add(calendarField, amount);\n        return c.getTime();\n    }\n    \n    public static Date addMinutes(Date date, int amount) {\n        return add(date, Calendar.MINUTE, amount);\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-jedis-stat/src/main/java/com/sohu/tv/jedis/stat/utils/NamedThreadFactory.java",
    "content": "package com.sohu.tv.jedis.stat.utils;\n\nimport java.util.concurrent.ThreadFactory;\nimport java.util.concurrent.atomic.AtomicInteger;\n\n/**\n * Created by yijunzhang on 14-7-18.\n */\npublic class NamedThreadFactory implements ThreadFactory {\n    private final AtomicInteger mThreadNum = new AtomicInteger(1);\n\n    private final String mPrefix;\n\n    private final boolean mDaemo;\n\n    private final ThreadGroup mGroup;\n\n    public NamedThreadFactory(String prefix, boolean daemo) {\n        mPrefix = prefix + \"-thread-\";\n        mDaemo = daemo;\n        SecurityManager s = System.getSecurityManager();\n        mGroup = (s == null) ? Thread.currentThread().getThreadGroup() : s.getThreadGroup();\n    }\n\n    public Thread newThread(Runnable runnable) {\n        String name = mPrefix + mThreadNum.getAndIncrement();\n        Thread ret = new Thread(mGroup, runnable, name, 0);\n        ret.setDaemon(mDaemo);\n        return ret;\n    }\n\n    public ThreadGroup getThreadGroup() {\n        return mGroup;\n    }\n\n    @Override\n    public String toString() {\n        return mPrefix;\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-jedis-stat/src/main/java/com/sohu/tv/jedis/stat/utils/NumberUtil.java",
    "content": "package com.sohu.tv.jedis.stat.utils;\n\n/**\n * 从commons-lang抄的\n * @author leifu\n * @Date 2015年1月13日\n * @Time 下午5:52:18\n */\npublic class NumberUtil {\n    \n    public static int toInt(String str, int defaultValue) {\n        if (str == null) {\n            return defaultValue;\n        }\n        try {\n            return Integer.parseInt(str);\n        } catch (NumberFormatException nfe) {\n            return defaultValue;\n        }\n    }\n\n    public static int toInt(String str) {\n        return toInt(str, 0);\n    }\n    \n    public static long toLong(String str, long defaultValue) {\n        if (str == null) {\n            return defaultValue;\n        }\n        try {\n            return Long.parseLong(str);\n        } catch (NumberFormatException nfe) {\n            return defaultValue;\n        }\n    }\n    \n    public static long toLong(String str) {\n        return toLong(str, 0L);\n    }\n    \n    public static double toDouble(final String str) {\n        return toDouble(str, 0.0d);\n    }\n    \n    public static double toDouble(final String str, final double defaultValue) {\n        if (str == null) {\n            return defaultValue;\n        }\n        try {\n            return Double.parseDouble(str);\n        } catch (final NumberFormatException nfe) {\n            return defaultValue;\n        }\n      }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-jedis-stat/src/test/java/com/sohu/tv/jedis/stat/data/test/UsefulDataCollectorTest.java",
    "content": "package com.sohu.tv.jedis.stat.data.test;\n\nimport org.junit.Test;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.sohu.tv.jedis.stat.data.UsefulDataCollector;\nimport com.sohu.tv.jedis.stat.model.CostTimeDetailStatModel;\nimport com.sohu.tv.jedis.stat.utils.AtomicLongMap;\n\n/**\n * @author leifu\n * @Date 2015年1月23日\n * @Time 下午3:23:34\n */\npublic class UsefulDataCollectorTest {\n    private final static Logger logger = LoggerFactory.getLogger(UsefulDataCollectorTest.class);\n\n    @Test\n    public void testGenerateCostTimeDetailStatKey() {\n        AtomicLongMap<Integer> map = AtomicLongMap.create();\n        map.addAndGet(5, 300);\n        map.addAndGet(2, 100);\n        map.addAndGet(1, 500);\n        map.addAndGet(4, 300);\n        map.addAndGet(10, 30);\n        map.addAndGet(30, 2);\n\n        CostTimeDetailStatModel model = UsefulDataCollector.generateCostTimeDetailStatKey(map);\n        logger.info(model.toString());\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/cachecloud-open-jedis-stat/src/test/resources/logback-test.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n  Example LOGBACK Configuration File\n  http://logback.qos.ch/manual/configuration.html\n  -->\n<!-- 30秒扫描一次 -->  \n<configuration scan=\"true\" scanPeriod=\"30 seconds\">\n\n    <appender name=\"STDOUT\" class=\"ch.qos.logback.core.ConsoleAppender\">\n        <encoder>\n            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>\n        </encoder>\n    </appender>\n\n    <root level=\"DEBUG\">\n        <appender-ref ref=\"STDOUT\"/>\n    </root>\n</configuration>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-client/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    <parent>\n        <artifactId>open-cachecloud</artifactId>\n        <groupId>com.sohu.tv</groupId>\n        <version>1.0-SNAPSHOT</version>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n    <groupId>com.sohu.tv</groupId>\n    <artifactId>cachecloud-open-client</artifactId>\n    <packaging>pom</packaging>\n    <version>1.0-SNAPSHOT</version>\n    <description>cachecloud-open-client modules</description>\n    <modules>\n        <module>cachecloud-open-client-basic</module>\n        <module>cachecloud-open-client-redis</module>\n        <module>cachecloud-jedis</module>\n        <module>cachecloud-open-jedis-stat</module>\n    </modules>\n\n\n</project>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-common/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" 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  <parent>\n    <groupId>com.sohu.tv</groupId>\n    <artifactId>open-cachecloud</artifactId>\n    <version>1.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>cachecloud-open-common</artifactId>\n  <name>cachecloud-open-common</name>\n  \n  <dependencies>\n\t\t<dependency>\n\t\t\t<artifactId>slf4j-api</artifactId>\n\t\t\t<groupId>org.slf4j</groupId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>commons-lang</groupId>\n\t\t\t<artifactId>commons-lang</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n            <groupId>javax.servlet</groupId>\n            <artifactId>javax.servlet-api</artifactId>\n        </dependency>\n\t</dependencies>\n</project>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-common/src/main/java/com/sohu/cache/util/ConstUtils.java",
    "content": "package com.sohu.cache.util;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.ResourceBundle;\n\n/**\n * cachecloud常量\n * @author leifu\n * @Date 2016年3月1日\n * @Time 下午12:54:45\n */\npublic class ConstUtils {\n    // cache的类型区分\n    public static final int CACHE_TYPE_REDIS_CLUSTER = 2;\n    public static final int CACHE_REDIS_SENTINEL = 5;\n    public static final int CACHE_REDIS_STANDALONE = 6;\n\n    // 数据源名称\n    public static final String REDIS = \"redis\";\n    public static final String MACHINE = \"machine\";\n\n    // redis job/trigger name/group\n    public static final String REDIS_JOB_NAME = \"redisJob\";\n    public static final String REDIS_JOB_GROUP = \"redis\";\n    public static final String REDIS_TRIGGER_GROUP = \"redis-\";\n\n    // machine job/trigger name/group\n    public static final String MACHINE_JOB_NAME = \"machineJob\";\n    public static final String MACHINE_JOB_GROUP = \"machine\";\n    public static final String MACHINE_TRIGGER_GROUP = \"machine-\";\n\n    // machine monitor job/trigger name/group\n    public static final String MACHINE_MONITOR_JOB_NAME = \"machineMonitorJob\";\n    public static final String MACHINE_MONITOR_JOB_GROUP = \"machineMonitor\";\n    public static final String MACHINE_MONITOR_TRIGGER_GROUP = \"machineMonitor-\";\n\n    \n    // redis-slowlog job/trigger name/group\n    public static final String REDIS_SLOWLOG_JOB_NAME = \"redisSlowLogJob\";\n    public static final String REDIS_SLOWLOG_JOB_GROUP = \"redisSlowLog\";\n    public static final String REDIS_SLOWLOG_TRIGGER_GROUP = \"redisSlowLog-\";\n    \n    // 创建trigger时，dataMap的数据key\n    public static final String HOST_KEY = \"host_key\";\n    public static final String PORT_KEY = \"port_key\";\n    public static final String APP_KEY = \"app_key\";\n    public static final String HOST_ID_KEY = \"host_id_key\";\n    // server job/trigger name/group\n    public static final String SERVER_JOB_NAME = \"serverJob\";\n    public static final String SERVER_JOB_GROUP = \"server\";\n    public static final String SERVER_TRIGGER_GROUP = \"server-\";\n\n    //mysql收集数据的时间字段\n    public static final String COLLECT_TIME = \"CollectTime\";\n\n    // 触发时间\n    public static final String TRIGGER_TIME_KEY = \"trigger_time_key\";\n\n    // 容量转换\n    public static final int _1024 = 1024;\n    \n    // 表示空字符串\n    public static final String EMPTY = \"\";\n    \n    /**\n     * 服务端版本\n     */\n    public static final String CACHECLOUD_VERSION = \"master\";\n\n    /**\n     * 机器报警阀值\n     */\n    public static double DEFAULT_CPU_USAGE_RATIO_THRESHOLD = 80.0;\n    public static double CPU_USAGE_RATIO_THRESHOLD = DEFAULT_CPU_USAGE_RATIO_THRESHOLD;\n\n    \n    public static double DEFAULT_MEMORY_USAGE_RATIO_THRESHOLD = 80.0;\n    public static double MEMORY_USAGE_RATIO_THRESHOLD = DEFAULT_MEMORY_USAGE_RATIO_THRESHOLD;\n\n    public static double DEFAULT_LOAD_THRESHOLD = 8.0;\n    public static double LOAD_THRESHOLD = DEFAULT_LOAD_THRESHOLD;\n\n    /**\n     * 应用客户端连接数报警阀值 \n     */\n    public static int DEFAULT_APP_CLIENT_CONN_THRESHOLD = 2000;\n    public static int APP_CLIENT_CONN_THRESHOLD = DEFAULT_APP_CLIENT_CONN_THRESHOLD;\n\n    /**\n     * 机器统一的用户名、密码、端口\n     */\n    public static String DEFAULT_USERNAME = \"cachecloud\";\n    public static String USERNAME = DEFAULT_USERNAME;\n\n    public static String DEFAULT_PASSWORD = \"cachecloud\";\n    public static String PASSWORD = DEFAULT_PASSWORD;\n\n    public static int DEFAULT_SSH_PORT_DEFAULT = 22;\n    public static int SSH_PORT_DEFAULT = DEFAULT_SSH_PORT_DEFAULT;\n\n\n    /**\n     * 管理员相关\n     */\n    public static String DEFAULT_SUPER_ADMIN_NAME = \"admin\";\n    public static String SUPER_ADMIN_NAME = DEFAULT_SUPER_ADMIN_NAME;\n    \n    public static String DEFAULT_SUPER_ADMIN_PASS = \"admin\";\n    public static String SUPER_ADMIN_PASS = DEFAULT_SUPER_ADMIN_PASS;\n    \n    public static String DEFAULT_SUPER_ADMINS=\"admin\";\n    public static String SUPER_ADMINS = DEFAULT_SUPER_ADMINS;\n    \n    public static List<String> SUPER_MANAGER;\n    \n    /**\n     * ldap登陆\n     */\n    public static String DEFAULT_LDAP_URL = EMPTY;\n    public static String LDAP_URL = DEFAULT_LDAP_URL;\n    \n    /**\n     * 登陆邮箱后缀\n     */\n    public static String EMAIL_SUFFIX = \"\";\n    \n    /**\n     * 是否为调试\n     */\n    public static boolean IS_DEBUG;\n    \n    /**\n     * 联系人\n     */\n    public static String DEFAULT_CONTACT = \"user1:(xx@zz.com, user1:135xxxxxxxx)<br/>user2: (user2@zz.com, user2:138xxxxxxxx)\";\n    public static String CONTACT = DEFAULT_CONTACT;\n\n    \n    /**\n     * 文档地址\n     */\n    public static String DEFAULT_DOCUMENT_URL = \"http://cachecloud.github.io\";\n    public static String DOCUMENT_URL = DEFAULT_DOCUMENT_URL;\n    \n    /**\n     * 报警相关\n     */\n    public static String DEFAULT_EMAILS = \"xx@sohu.com,yy@qq.com\";\n    public static String EMAILS = DEFAULT_EMAILS;\n\n    public static String DEFAULT_PHONES = \"13812345678,13787654321\";\n    public static String PHONES = DEFAULT_PHONES;\n\n    /**\n     * 邮箱报警接口\n     */\n    public static String DEFAULT_EMAIL_ALERT_INTERFACE = EMPTY;\n    public static String EMAIL_ALERT_INTERFACE = DEFAULT_EMAIL_ALERT_INTERFACE;\n    \n    /**\n     * 短信报警接口\n     */\n    public static String DEFAULT_MOBILE_ALERT_INTERFACE = EMPTY;\n    public static String MOBILE_ALERT_INTERFACE = DEFAULT_MOBILE_ALERT_INTERFACE;\n    \n    /**\n     * maven仓库地址\n     */\n    public static String DEFAULT_MAVEN_WAREHOUSE = \"http://your_maven_house\";\n    public static String MAVEN_WAREHOUSE = DEFAULT_MAVEN_WAREHOUSE;\n    \n    \n    /**\n     * 客户端可用版本\n     */\n    public static String DEFAULT_GOOD_CLIENT_VERSIONS = \"1.0-SNAPSHOT\";\n    public static String GOOD_CLIENT_VERSIONS = DEFAULT_GOOD_CLIENT_VERSIONS;\n\n    /**\n     * 客户端警告版本\n     */\n    public static String DEFAULT_WARN_CLIENT_VERSIONS = \"0.1\";\n    public static String WARN_CLIENT_VERSIONS = DEFAULT_WARN_CLIENT_VERSIONS;\n    \n    \n    /**\n     * 客户端错误版本\n     */\n    public static String DEFAULT_ERROR_CLIENT_VERSIONS = \"0.0\";\n    public static String ERROR_CLIENT_VERSIONS = DEFAULT_ERROR_CLIENT_VERSIONS;\n\n    /**\n     * redis-migrate-tool相关路径\n     */\n    public static String DEFAULT_REDIS_MIGRATE_TOOL_HOME = \"/opt/cachecloud/redis-migrate-tool/\";\n    public static String REDIS_MIGRATE_TOOL_HOME = DEFAULT_REDIS_MIGRATE_TOOL_HOME;\n\n    public static String getRedisMigrateToolCmd() {\n        return REDIS_MIGRATE_TOOL_HOME + \"src/redis-migrate-tool\";\n    }\n    \n    public static String getRedisMigrateToolDir() {\n        return REDIS_MIGRATE_TOOL_HOME + \"data/\";\n    }\n    \n    /**\n     * redis-migrate-tool端口\n     */\n    public static int REDIS_MIGRATE_TOOL_PORT = 8888;\n    \n    /**\n     * 1是session,2是cookie(参考UserLoginTypeEnum)\n     */\n    public static int DEFAULT_USER_LOGIN_TYPE = 1;\n    public static int USER_LOGIN_TYPE = DEFAULT_USER_LOGIN_TYPE;\n    \n    /**\n     * cookie登录方式所需要的域\n     */\n    public static String DEFAULT_COOKIE_DOMAIN = EMPTY;\n    public static String COOKIE_DOMAIN = DEFAULT_COOKIE_DOMAIN;\n    \n    /**\n     * cachecloud根目录，这个要与cachecloud-init.sh脚本中的目录一致\n     */\n    public static String DEFAULT_CACHECLOUD_BASE_DIR = \"/opt\";\n    public static String CACHECLOUD_BASE_DIR = DEFAULT_CACHECLOUD_BASE_DIR;\n    \n    /**\n     * 是否定期清理各种统计数据：(详见CleanUpStatisticsJob)\n     */\n    public static boolean DEFAULT_WHETHER_SCHEDULE_CLEAN_DATA = false;\n    public static boolean WHETHER_SCHEDULE_CLEAN_DATA = DEFAULT_WHETHER_SCHEDULE_CLEAN_DATA;\n    \n    \n    /**\n     * appkey秘钥\n     */\n    public static String DEFAULT_APP_SECRET_BASE_KEY = \"cachecloud-2014\";\n    public static String APP_SECRET_BASE_KEY = DEFAULT_APP_SECRET_BASE_KEY;\n    \n    \n    /**\n     * 机器性能统计周期(分钟)\n     */\n    public static int DEFAULT_MACHINE_STATS_CRON_MINUTE = 1;\n    public static int MACHINE_STATS_CRON_MINUTE = DEFAULT_MACHINE_STATS_CRON_MINUTE;\n    \n    \n    /**\n     * 网站域名\n     */\n    public static final String CC_DOMAIN = \"http://your.domain.com\";\n    \n    /**\n     * 领导邮件\n     */\n    public static List<String> LEADER_EMAIL_LIST = new ArrayList<String>();\n    static {\n    }\n    \n    static {\n        ResourceBundle applicationResourceBundle = ResourceBundle.getBundle(\"application\");\n        IS_DEBUG = \"true\".equals(applicationResourceBundle.getString(\"isDebug\"));\n    }\n    \n    /**\n     * 逗号\n     */\n    public static final String COMMA = \",\";\n    \n    /**\n     * 换行\n     */\n    public static final String NEXT_LINE = \"\\n\";\n\n    /**\n     * 空格\n     */\n    public static final String SPACE = \" \";\n    \n\n    /**\n     * 冒号\n     */\n    public static final String COLON = \":\";\n\n    \n    /**\n     * 内部错误\n     */\n    public static final String INNER_ERROR = \"cachecloud_inner_error\";\n    \n    /**\n     * 登录跳转参数\n     */\n    public final static String RREDIRECT_URL_PARAM = \"redirectUrl\";\n\n}\n\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-common/src/main/java/com/sohu/cache/util/DemoCodeUtil.java",
    "content": "package com.sohu.cache.util;\n\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\n\n\n/**\n * Created by hym on 14-11-3.\n */\npublic class DemoCodeUtil {\n\n    public static final List<String> redisCluster = new ArrayList<String>();\n    public static final List<String> redisSentinel = new ArrayList<String>();\n    public static final List<String> redisStandalone = new ArrayList<String>();\n    \n    public static final List<String> redisSentinelSpring = new ArrayList<String>();\n    public static final List<String> redisClusterSpring = new ArrayList<String>();\n    \n    \n    private static final String springAppId = \"${your appId}\";\n    \n    static {\n        redisCluster.add(\"/**                                                                       \");\n        redisCluster.add(\" * 使用自定义配置：                                                         \");\n        redisCluster.add(\" *  1. setTimeout：redis操作的超时设置；                                    \");\n        redisCluster.add(\" *  2. setMaxRedirections：节点定位重试的次数；                              \");\n        redisCluster.add(\" */                                                                       \");\n        redisCluster.add(\"GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();       \");\n        redisCluster.add(\"JedisCluster redisCluster = ClientBuilder.redisCluster(appId)                       \");\n        redisCluster.add(\"&nbsp;&nbsp;&nbsp;&nbsp;.setJedisPoolConfig(poolConfig)                                   \");\n        redisCluster.add(\"&nbsp;&nbsp;&nbsp;&nbsp;.setConnectionTimeout(1000)                                                    \");\n        redisCluster.add(\"&nbsp;&nbsp;&nbsp;&nbsp;.setSoTimeout(1000)                                                    \");\n        redisCluster.add(\"&nbsp;&nbsp;&nbsp;&nbsp;.setMaxRedirections(5)                                            \");\n        redisCluster.add(\"&nbsp;&nbsp;&nbsp;&nbsp;.build();                                                         \");\n        redisCluster.add(\"//1.字符串value\");\n        redisCluster.add(\"redisCluster.set(\\\"key1\\\", \\\"value1\\\");                                \");\n        redisCluster.add(\"System.out.println(redisCluster.get(\\\"key1\\\"));                  \");\n\n        \n        redisSentinel.add(\"/**                                                                      \");\n        redisSentinel.add(\" * 自定义配置                                                             \");\n        redisSentinel.add(\" */                                                                      \");\n        redisSentinel.add(\"GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();      \");\n        redisSentinel.add(\"JedisSentinelPool sentinelPool = ClientBuilder.redisSentinel(appId)                        \");\n        redisSentinel.add(\"&nbsp;&nbsp;&nbsp;&nbsp;.setConnectionTimeout(1000)                                                \");\n        redisSentinel.add(\"&nbsp;&nbsp;&nbsp;&nbsp;.setSoTimeout(1000)                                                \");\n        redisSentinel.add(\"&nbsp;&nbsp;&nbsp;&nbsp;.setPoolConfig(poolConfig)                                       \");\n        redisSentinel.add(\"&nbsp;&nbsp;&nbsp;&nbsp;.build();                                                        \");\n        \n        redisSentinel.add(\"Jedis jedis = null;                                                                           \");\n        redisSentinel.add(\"try {                                                                           \");\n        redisSentinel.add(\"&nbsp;&nbsp;&nbsp;&nbsp;jedis = sentinelPool.getResource();                                         \");\n        redisSentinel.add(\"&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(jedis.get(\\\"key1\\\"));                  \");\n        redisSentinel.add(\"&nbsp;&nbsp;&nbsp;&nbsp;//1.字符串value                                                              \");\n        redisSentinel.add(\"&nbsp;&nbsp;&nbsp;&nbsp;jedis.set(\\\"key1\\\", \\\"1\\\");                                                  \"); \n        redisSentinel.add(\"&nbsp;&nbsp;&nbsp;&nbsp\");\n        \n        redisSentinel.add(\"} catch (Exception e) {                                                         \");\n        redisSentinel.add(\"&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();                                            \");\n        redisSentinel.add(\"} finally {                                                                     \");\n        redisSentinel.add(\"&nbsp;&nbsp;&nbsp;&nbsp;if(jedis!=null)                                                                \");\n        redisSentinel.add(\"&nbsp;&nbsp;&nbsp;&nbsp;jedis.close();                                                                 \");\n        redisSentinel.add(\"}                                                                               \");\n        \n        \n\n        redisStandalone.add(\"// 使用默认配置                                                      \");\n        redisStandalone.add(\"//jedisPool = ClientBuilder.redisStandalone(appId).build();         \");\n        redisStandalone.add(\"/**                                                                 \");\n        redisStandalone.add(\" * 使用自定义配置                                                    \");\n        redisStandalone.add(\" */                                                                 \");\n        redisStandalone.add(\"GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig(); \");\n        \n        redisStandalone.add(\"JedisPool jedisPool = ClientBuilder.redisStandalone(appId)                    \");\n        redisStandalone.add(\"&nbsp;&nbsp;&nbsp;&nbsp;.setTimeout(2000)                                           \");\n        redisStandalone.add(\"&nbsp;&nbsp;&nbsp;&nbsp;.setPoolConfig(poolConfig)                                  \");\n        redisStandalone.add(\"&nbsp;&nbsp;&nbsp;&nbsp;.build();                                                   \");\n        \n        redisStandalone.add(\"Jedis jedis = null;                                                                           \");\n        redisStandalone.add(\"try {                                                                           \");\n        redisStandalone.add(\"&nbsp;&nbsp;&nbsp;&nbsp;jedis = jedisPool.getResource();                                          \");\n        redisStandalone.add(\"&nbsp;&nbsp;&nbsp;&nbsp;jedis.set(\\\"key1\\\", \\\"1\\\");                                                  \");\n        redisStandalone.add(\"&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(jedis.get(\\\"key1\\\"));                  \");\n        redisStandalone.add(\"&nbsp;&nbsp;&nbsp;&nbsp\");\n        \n        redisStandalone.add(\"} catch (Exception e) {                                                         \");\n        redisStandalone.add(\"&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();                                            \");\n        redisStandalone.add(\"} finally {                                                                     \");\n        redisStandalone.add(\"&nbsp;&nbsp;&nbsp;&nbsp;if(jedis!=null)                                                                \");\n        redisStandalone.add(\"&nbsp;&nbsp;&nbsp;&nbsp;jedis.close();                                                                 \");\n        redisStandalone.add(\"}                                                                               \");\n        \n        \n        //redis-sentinel的spring配置\n        redisSentinelSpring.add(\"//spring 配置\");\n        redisSentinelSpring.add(\"&lt;bean id=\\\"redisSentinelFactory\\\" class=\\\"com.sohu.tv.mobil.common.data.RedisSentinelFactory\\\" init-method=\\\"init\\\"&gt;\");\n        redisSentinelSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&lt;property name=\\\"appId\\\" value=\\\"\"+springAppId+\"\\\"/&gt;\");\n        redisSentinelSpring.add(\"&lt;/bean&gt;\");\n        redisSentinelSpring.add(\"&lt;bean id=\\\"redisSentinelPool\\\" factory-bean=\\\"redisSentinelFactory\\\" factory-method=\\\"getJedisSentinelPool\\\"/&gt;\");\n        redisSentinelSpring.add(\"&lt;!--高效的序列化工具--/&gt\");\n        redisSentinelSpring.add(\"&lt;bean id=\\\"protostuffSerializer\\\" class=\\\"redis.clients.jedis.serializable.ProtostuffSerializer\\\"/&gt;\");\n        redisSentinelSpring.add(\"\");\n        redisSentinelSpring.add(\"package xx.xx;\");\n        redisSentinelSpring.add(\"import com.sohu.tv.builder.ClientBuilder;\");\n        redisSentinelSpring.add(\"import org.apache.commons.pool2.impl.GenericObjectPoolConfig;\");\n        redisSentinelSpring.add(\"import org.slf4j.Logger;\");\n        redisSentinelSpring.add(\"import org.slf4j.LoggerFactory;\");\n        redisSentinelSpring.add(\"import redis.clients.jedis.JedisSentinelPool;\");\n        redisSentinelSpring.add(\"public class RedisSentinelFactory {\");\n        redisSentinelSpring.add(\"\");\n        redisSentinelSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;private final Logger logger = LoggerFactory.getLogger(this.getClass());\");\n        redisSentinelSpring.add(\"\");\n        redisSentinelSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;private JedisSentinelPool jedisSentinelPool;\");\n        redisSentinelSpring.add(\"\");\n        redisSentinelSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;private int appId;\");\n        redisSentinelSpring.add(\"\");\n        redisSentinelSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;public void init(){\");\n        redisSentinelSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//根据自己需要设置poolConfig\");\n        redisSentinelSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();\");\n        redisSentinelSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;poolConfig.setMaxTotal(GenericObjectPoolConfig.DEFAULT_MAX_TOTAL * 10);\");\n        redisSentinelSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;poolConfig.setMaxIdle(GenericObjectPoolConfig.DEFAULT_MAX_IDLE * 5);\");\n        redisSentinelSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;poolConfig.setMinIdle(GenericObjectPoolConfig.DEFAULT_MAX_IDLE * 2);\");\n        redisSentinelSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;poolConfig.setMaxWaitMillis(1000L);\");\n        redisSentinelSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;poolConfig.setJmxEnabled(true);\");\n        redisSentinelSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try {\");\n        redisSentinelSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//根据自己需要设置超时时间\");\n        redisSentinelSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;jedisSentinelPool = ClientBuilder.redisSentinel(appId)\");\n        redisSentinelSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.setTimeout(2000)\");\n        redisSentinelSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.setPoolConfig(poolConfig)\");\n        redisSentinelSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.build();\");\n        redisSentinelSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} catch (Exception e) {\");\n        redisSentinelSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logger.error(e.getMessage(), e);\");\n        redisSentinelSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}\");\n        redisSentinelSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;}\");\n        redisSentinelSpring.add(\"\");\n        redisSentinelSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;public JedisSentinelPool getJedisSentinelPool() {\");\n        redisSentinelSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return jedisSentinelPool;\");\n        redisSentinelSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;}\");\n        redisSentinelSpring.add(\"\");\n        redisSentinelSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;public void setAppId(int appId) {\");\n        redisSentinelSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.appId = appId;\");\n        redisSentinelSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;}\");\n        redisSentinelSpring.add(\"}\");\n        \n        // redis-cluster的spring配置\n        redisClusterSpring.add(\"//spring 配置\");\n        redisClusterSpring.add(\"&lt;bean id=\\\"redisClusterFactory\\\" class=\\\"xx.xx.RedisClusterFactory\\\" init-method=\\\"init\\\"&gt;\");\n        redisClusterSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&lt;property name=\\\"appId\\\" value=\\\"\"+springAppId+\"\\\"/&gt;\");\n        redisClusterSpring.add(\"&lt;/bean>\");\n        redisClusterSpring.add(\"&lt;bean id=\\\"redisCluster\\\" factory-bean=\\\"redisClusterFactory\\\" factory-method=\\\"getRedisCluster\\\"/&gt;\");\n        redisClusterSpring.add(\"&lt;!--高效的序列化工具--/&gt\");\n        redisClusterSpring.add(\"&lt;bean id=\\\"protostuffSerializer\\\" class=\\\"redis.clients.jedis.serializable.ProtostuffSerializer\\\"/&gt;\");\n        redisClusterSpring.add(\"\");\n        redisClusterSpring.add(\"package xx.xx;\");\n        redisClusterSpring.add(\"import com.sohu.tv.builder.ClientBuilder;\");\n        redisClusterSpring.add(\"import org.apache.commons.pool2.impl.GenericObjectPoolConfig;\");\n        redisClusterSpring.add(\"import org.slf4j.Logger;\");\n        redisClusterSpring.add(\"import org.slf4j.LoggerFactory;\");\n        redisClusterSpring.add(\"import redis.clients.jedis.PipelineCluster;\");\n        redisClusterSpring.add(\"public class RedisClusterFactory {\");\n        redisClusterSpring.add(\"\");\n        redisClusterSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;private final Logger logger = LoggerFactory.getLogger(this.getClass());\");\n        redisClusterSpring.add(\"\");\n        redisClusterSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;private PipelineCluster redisCluster;\");\n        redisClusterSpring.add(\"\");\n        redisClusterSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;private int appId;\");\n        redisClusterSpring.add(\"\");\n        redisClusterSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;public void init() {\");\n        redisClusterSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//根据自己需要设置poolConfig\");\n        redisClusterSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();\");\n        redisClusterSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;poolConfig.setMaxTotal(GenericObjectPoolConfig.DEFAULT_MAX_TOTAL * 10);\");\n        redisClusterSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;poolConfig.setMaxIdle(GenericObjectPoolConfig.DEFAULT_MAX_IDLE * 5);\");\n        redisClusterSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;poolConfig.setMinIdle(GenericObjectPoolConfig.DEFAULT_MAX_IDLE * 2);\");\n        redisClusterSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;poolConfig.setMaxWaitMillis(1000L);\");\n        redisClusterSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;poolConfig.setJmxEnabled(true);\");\n        redisClusterSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try {\");\n        redisClusterSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//根据自己需要修改参数\");\n        redisClusterSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;redisCluster = ClientBuilder.redisCluster(appId)\");\n        redisClusterSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.setJedisPoolConfig(poolConfig)\");\n        redisClusterSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.setTimeout(2)\");\n        redisClusterSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.build();\");\n        redisClusterSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} catch (Exception e) {\");\n        redisClusterSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logger.error(e.getMessage(), e);\");\n        redisClusterSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}\");\n        redisClusterSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;}\");\n        redisClusterSpring.add(\"\");\n        redisClusterSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;public PipelineCluster getRedisCluster() {\");\n        redisClusterSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return redisCluster;\");\n        redisClusterSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;}\");\n        redisClusterSpring.add(\"\");\n        redisClusterSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;public void setAppId(int appId) {\");\n        redisClusterSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.appId = appId;\");\n        redisClusterSpring.add(\"&nbsp;&nbsp;&nbsp;&nbsp;}\");\n        redisClusterSpring.add(\"}\");\n\n    }\n\n    /**\n     * 获取依赖\n     * @return\n     */\n    public static List<String> getDependencyRedis() {\n        List<String> dependencyRedis = new ArrayList<String>();\n        \n        // redis版本\n        String redisGoodVersion = getGoodVersion();\n        \n        // 依赖\n        dependencyRedis.add(\"&lt;dependency&gt;                                                     \");\n        dependencyRedis.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&lt;groupId&gt;com.sohu.tv&lt;/groupId&gt;                                   \");\n        dependencyRedis.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&lt;artifactId&gt;cachecloud-open-client-redis&lt;/artifactId&gt;                       \");\n        dependencyRedis.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&lt;version&gt;\" + redisGoodVersion + \"&lt;/version&gt;                                           \");\n\n        dependencyRedis.add(\"&lt;/dependency&gt;                                                    \");\n        dependencyRedis.add(\"&lt;repositories&gt;                                                   \");\n        dependencyRedis.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&lt;repository&gt;                                                     \");\n        dependencyRedis.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;id&gt;sohu.nexus&lt;/id&gt;                                              \");\n        dependencyRedis.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;url&gt;\" + ConstUtils.MAVEN_WAREHOUSE + \"&lt;/url&gt;\");\n        dependencyRedis.add(\"&nbsp;&nbsp;&nbsp;&nbsp;&lt;/repository&gt;                                                    \");\n        dependencyRedis.add(\"&lt;/repositories&gt;                                                  \");\n        \n        return dependencyRedis;\n    }\n    \n    /**\n     * 获取最好的版本\n     * @return\n     */\n    private static String getGoodVersion() {\n        String[] redisGoodVersionArr = ConstUtils.GOOD_CLIENT_VERSIONS.split(ConstUtils.COMMA);\n        List<String> redisGoodVersions = Arrays.asList(redisGoodVersionArr);\n        String redisGoodVersion = redisGoodVersions.get(redisGoodVersions.size() - 1);\n        return redisGoodVersion;\n    }\n\n    public static List<String> getCode(int appType, long appId) {\n        List<String> list = null;\n        switch (appType) {\n            case ConstUtils.CACHE_REDIS_SENTINEL: {\n                list = new ArrayList<String>(redisSentinel);\n                break;\n            }\n            case ConstUtils.CACHE_REDIS_STANDALONE: {\n                list = new ArrayList<String>(redisStandalone);\n                break;\n            }\n            case ConstUtils.CACHE_TYPE_REDIS_CLUSTER: {\n                list = new ArrayList<String>(redisCluster);\n                break;\n            }\n        }\n        if (list != null && list.size() > 0) {\n            if (!list.get(0).contains(\"appId =\")) {\n                list.add(0, \"long appId = \" + appId + \";\");\n            }\n//            else {\n//                list.set(0, \"long appId = \" + appDesc.getAppId() + \";\");\n//            }\n        }\n        return list;\n    }\n\n    public static List<String> getSpringConfig(int appType, long appId) {\n        List<String> list = new ArrayList<String>();\n        switch (appType) {\n            case ConstUtils.CACHE_REDIS_SENTINEL: {\n                list.addAll(redisSentinelSpring);\n                break;\n            }\n            case ConstUtils.CACHE_REDIS_STANDALONE: {\n//                list = new ArrayList<String>();\n//                list.add(\"CACHE_REDIS_STANDALONE spring\");\n                break;\n            }\n            case ConstUtils.CACHE_TYPE_REDIS_CLUSTER: {\n                list.addAll(redisClusterSpring);\n                break;\n            }\n        }\n        \n        if (list != null && list.size() > 0) {\n            for (int i = 0; i < list.size(); i++) {\n                String line = list.get(i);\n                if (line != null && line.contains(springAppId)) {\n                    line = line.replace(springAppId,\n                            String.valueOf(appId));\n                    list.set(i, line);\n                }\n            }\n        }\n        return null;\n    }\n    \n    \n    public static String getRestAPI(int appType, long appId) {\n        String redisGoodVersion = getGoodVersion();\n        String appTypePath = \"\";\n        switch (appType) {\n            case ConstUtils.CACHE_REDIS_SENTINEL: {\n                appTypePath = \"sentinel\";\n                break;\n            }\n            case ConstUtils.CACHE_REDIS_STANDALONE: {\n                appTypePath = \"standalone\";\n                break;\n            }\n            case ConstUtils.CACHE_TYPE_REDIS_CLUSTER: {\n                appTypePath = \"cluster\";\n                break;\n            }\n        }\n        return ConstUtils.CC_DOMAIN + \"/cache/client/redis/\" + appTypePath + \"/\" + appId + \".json?clientVersion=\"\n                + redisGoodVersion;\n    }\n\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-common/src/main/java/com/sohu/cache/web/component/EmailComponent.java",
    "content": "package com.sohu.cache.web.component;\n\nimport java.util.List;\n\n/**\n * 邮件服务\n * @author leifu\n * @Date 2015-6-2\n * @Time 上午10:56:35\n */\npublic interface EmailComponent {\n\t/**\n     * 发送邮件\n     * @param title\n     * @param content\n     * @param emails\n     * @param cc(抄送)\n     * @return\n     */\n    boolean sendMail(String title, String content, List<String> emailList, List<String> ccList);\n\t\n\t\n    /**\n     * 发送邮件\n     * @param title\n     * @param content\n     * @param emails\n     * @return\n     */\n    boolean sendMail(String title, String content, List<String> emailList);\n    \n    /**\n     * 发送管理员邮件\n     * @param title\n     * @param content\n     * @return\n     */\n    boolean sendMailToAdmin(String title, String content);\n\n    \n    /**\n     * 获取管理员邮件组\n     * @return\n     */\n    String getAdminEmail();\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-common/src/main/java/com/sohu/cache/web/component/EmailComponentImpl.java",
    "content": "package com.sohu.cache.web.component;\n\nimport org.apache.commons.lang.StringUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.sohu.cache.util.ConstUtils;\nimport com.sohu.cache.web.util.HttpRequestUtil;\n\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 邮件服务\n * @author leifu\n * @Date 2015-6-2\n * @Time 上午10:56:35\n */\npublic class EmailComponentImpl implements EmailComponent {\n    private final Logger logger = LoggerFactory.getLogger(EmailComponentImpl.class);\n\n    private String adminEmail = ConstUtils.EMAILS;\n\n    @Override\n    public boolean sendMailToAdmin(String title, String content) {\n        return sendMail(title, content, Arrays.asList(adminEmail));\n    }\n\n    @Override\n    public boolean sendMail(String title, String content, List<String> emailList) {\n        return sendMail(title, content, emailList, null);\n    }\n    \n    @Override\n\tpublic boolean sendMail(String title, String content, List<String> emailList, List<String> ccList) {\n        String alertUrl = ConstUtils.EMAIL_ALERT_INTERFACE;\n        if (StringUtils.isBlank(alertUrl)) {\n            logger.error(\"emailAlertInterface url is empty!\");\n            return false;\n        }\n    \ttry {\n            String charSet = \"UTF-8\";\n            Map<String, String> postMap = new HashMap<String, String>();\n            postMap.put(\"title\", title);\n            postMap.put(\"content\", content);\n            postMap.put(\"receiver\", StringUtils.join(emailList, \",\"));\n            if(ccList != null && ccList.size() > 0){\n            \tpostMap.put(\"cc\", StringUtils.join(ccList, \",\"));\n            }\n            String responseStr = HttpRequestUtil.doPost(alertUrl, postMap, charSet);\n            if (responseStr == null) {\n                logger.error(\"发送邮件失败 : url:{}\", alertUrl);\n            }\n            return true;\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return false;\n        }\n\t}\n\n    public void setAdminEmail(String adminEmail) {\n        this.adminEmail = adminEmail;\n    }\n\n\t@Override\n\tpublic String getAdminEmail() {\n\t\treturn adminEmail;\n\t}\n\n\t\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-common/src/main/java/com/sohu/cache/web/component/MobileAlertComponent.java",
    "content": "package com.sohu.cache.web.component;\n\n\nimport java.util.List;\n\n/**\n * 短信报警\n * @author leifu\n * @Date 2014年11月26日\n * @Time 上午10:11:26\n */\npublic interface MobileAlertComponent {\n    \n    /**\n     * 发短信给管理员\n     * @param message\n     */\n    void sendPhoneToAdmin(String message);\n    \n    /**\n     * 发短信给指定号码集合\n     * @param message\n     * @param phoneList\n     */\n    void sendPhone(String message, List<String> phoneList);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-common/src/main/java/com/sohu/cache/web/component/MobileAlertComponentImpl.java",
    "content": "package com.sohu.cache.web.component;\n\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport org.apache.commons.lang.StringUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.sohu.cache.util.ConstUtils;\nimport com.sohu.cache.web.util.HttpRequestUtil;\n\n/**\n * 手机短信报警\n * @author leifu\n * @Date 2014年11月26日\n * @Time 上午10:11:26\n */\npublic class MobileAlertComponentImpl implements MobileAlertComponent {\n\n    private final Logger logger = LoggerFactory.getLogger(MobileAlertComponentImpl.class);\n    /**\n     * 管理员电话\n     */\n    private String adminPhones = ConstUtils.PHONES;\n\n    @Override\n    public void sendPhoneToAdmin(String message) {\n        if (StringUtils.isBlank(message) || StringUtils.isBlank(adminPhones)) {\n            logger.error(\"message is {}, maybe empty or adminPhones is {}, maybe empty\", message, adminPhones);\n        }\n        sendPhone(message, Arrays.asList(adminPhones.split(ConstUtils.COMMA)));\n    }\n\n    @Override\n    public void sendPhone(String message, List<String> phoneList) {\n        String alertUrl = ConstUtils.MOBILE_ALERT_INTERFACE;\n        if (StringUtils.isBlank(alertUrl)) {\n            logger.error(\"mobileAlertInterface url is empty!\");\n            return;\n        }\n        if (StringUtils.isBlank(message) || phoneList == null || phoneList.isEmpty()) {\n            logger.error(\"message is {}, phoneList is {} both maybe empty!\", message, phoneList);\n            return;\n        }\n        String charSet = \"UTF-8\";\n        String phone = StringUtils.join(phoneList, ConstUtils.COMMA);\n        Map<String, String> postMap = new HashMap<String, String>();\n        postMap.put(\"msg\", message);\n        postMap.put(\"phone\", phone);\n        String responseStr = HttpRequestUtil.doPost(alertUrl, postMap, charSet);\n        if (StringUtils.isBlank(responseStr)) {\n            logger.error(\"发送短信失败 : url:{}\", alertUrl);\n        }\n        logger.warn(\"send Done!\");\n    }\n\n    public void setAdminPhones(String adminPhones) {\n        this.adminPhones = adminPhones;\n    }\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-common/src/main/java/com/sohu/cache/web/util/HttpRequestUtil.java",
    "content": "package com.sohu.cache.web.util;\n\nimport java.io.BufferedInputStream;\nimport java.io.BufferedReader;\nimport java.io.ByteArrayOutputStream;\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\nimport java.io.UnsupportedEncodingException;\nimport java.net.HttpURLConnection;\nimport java.net.URL;\nimport java.net.URLEncoder;\nimport java.util.Iterator;\nimport java.util.Map;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * http原生工具类\n * \n * @author leifu\n * @Date 2015年1月15日\n * @Time 上午9:42:47\n */\npublic final class HttpRequestUtil {\n    \n    // http 超时设置\n    private static final int HTTP_CONNECTION_TIMEOUT = 3000;\n    private static final int HTTP_SOCKET_TIMEOUT = 3000;\n    \n    private static Logger logger = LoggerFactory.getLogger(HttpRequestUtil.class);\n\n    public static String doPost(String reqUrl, Map<String, String> parameters) {\n        return doPost(reqUrl, parameters, \"UTF-8\", HTTP_CONNECTION_TIMEOUT, HTTP_SOCKET_TIMEOUT);\n    }\n\n    public static String doPost(String reqUrl, Map<String, String> parameters, String encoding) {\n        return doPost(reqUrl, parameters, encoding, HTTP_CONNECTION_TIMEOUT, HTTP_SOCKET_TIMEOUT);\n    }\n\n    public static String doPost(String reqUrl, Map<String, String> parameters, String encoding, int connectTimeout,\n            int readTimeout) {\n        HttpURLConnection urlConn = null;\n        try {\n            urlConn = sendPost(reqUrl, parameters, encoding, connectTimeout, readTimeout);\n            String responseContent = getContent(urlConn, encoding);\n            return responseContent.trim();\n        } finally {\n            if (urlConn != null) {\n                urlConn.disconnect();\n                urlConn = null;\n            }\n        }\n    }\n\n    private static HttpURLConnection sendPost(String reqUrl,\n            Map<String, String> parameters, String encoding, int connectTimeout, int readTimeout) {\n        HttpURLConnection urlConn = null;\n        try {\n            String params = generatorParamString(parameters, encoding);\n            URL url = new URL(reqUrl);\n            urlConn = (HttpURLConnection) url.openConnection();\n            urlConn.setRequestMethod(\"POST\");\n            // urlConn\n            // .setRequestProperty(\n            // \"User-Agent\",\n            // \"Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3\");\n            urlConn.setConnectTimeout(connectTimeout);// （单位：毫秒）jdk\n            urlConn.setReadTimeout(readTimeout);// （单位：毫秒）jdk 1.5换成这个,读操作超时\n            urlConn.setDoOutput(true);\n            // String按照字节处理是一个好方法\n            byte[] b = params.getBytes(encoding);\n            urlConn.getOutputStream().write(b, 0, b.length);\n            urlConn.getOutputStream().flush();\n            urlConn.getOutputStream().close();\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n        return urlConn;\n    }\n\n    private static String getContent(HttpURLConnection urlConn, String encoding) {\n        try {\n            String responseContent = null;\n            InputStream in = urlConn.getInputStream();\n            BufferedReader rd = new BufferedReader(new InputStreamReader(in, encoding));\n            String tempLine = rd.readLine();\n            StringBuffer tempStr = new StringBuffer();\n            String crlf = System.getProperty(\"line.separator\");\n            while (tempLine != null) {\n                tempStr.append(tempLine);\n                tempStr.append(crlf);\n                tempLine = rd.readLine();\n            }\n            responseContent = tempStr.toString();\n            rd.close();\n            in.close();\n            return responseContent;\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return null;\n        }\n    }\n\n    /**\n     * @param link\n     * @param encoding\n     * @return\n     */\n    public static String doGet(String link, String encoding, int connectTimeout, int readTimeout) {\n        HttpURLConnection conn = null;\n        try {\n            URL url = new URL(link);\n            conn = (HttpURLConnection) url.openConnection();\n            conn.setRequestMethod(\"GET\");\n            conn.setConnectTimeout(connectTimeout);\n            conn.setReadTimeout(readTimeout);\n            // conn.setRequestProperty(\"User-Agent\", \"Mozilla/5.0\");\n            BufferedInputStream in = new BufferedInputStream(\n                    conn.getInputStream());\n            ByteArrayOutputStream out = new ByteArrayOutputStream();\n            byte[] buf = new byte[1024];\n            for (int i = 0; (i = in.read(buf)) > 0;) {\n                out.write(buf, 0, i);\n            }\n            out.flush();\n            String s = new String(out.toByteArray(), encoding);\n            return s;\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return null;\n        } finally {\n            if (conn != null) {\n                conn.disconnect();\n                conn = null;\n            }\n        }\n    }\n\n    /**\n     * UTF-8编码\n     * \n     * @param link\n     * @return\n     */\n    public static String doGet(String link) {\n        return doGet(link, \"UTF-8\", HTTP_CONNECTION_TIMEOUT, HTTP_SOCKET_TIMEOUT);\n    }\n\n    /**\n     * 将parameters中数据转换成用\"&\"链接的http请求参数形式\n     * \n     * @param parameters\n     * @return\n     */\n    private static String generatorParamString(Map<String, String> parameters, String encoding) {\n        StringBuffer params = new StringBuffer();\n        if (parameters != null) {\n            for (Iterator<String> iter = parameters.keySet().iterator(); iter\n                    .hasNext();) {\n                String name = iter.next();\n                String value = parameters.get(name);\n                params.append(name + \"=\");\n                try {\n                    params.append(URLEncoder.encode(value, encoding));\n                } catch (UnsupportedEncodingException e) {\n                    throw new RuntimeException(e.getMessage(), e);\n                } catch (Exception e) {\n                    String message = String.format(\"'%s'='%s'\", name, value);\n                    throw new RuntimeException(message, e);\n                }\n                if (iter.hasNext())\n                    params.append(\"&\");\n            }\n        }\n        return params.toString();\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-common/src/main/java/com/sohu/cache/web/util/LoginUtil.java",
    "content": "package com.sohu.cache.web.util;\n\nimport java.util.Hashtable;\n\nimport javax.naming.directory.DirContext;\nimport javax.naming.directory.InitialDirContext;\n\nimport org.apache.commons.lang.StringUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.sohu.cache.util.ConstUtils;\n\n/**\n * 域账户LDAP登陆简单工具\n * \n * @author leifu\n * @Time 2014年6月12日\n */\npublic class LoginUtil {\n    \n    private final static Logger logger = LoggerFactory.getLogger(LoginUtil.class);\n\n    public static boolean passportCheck(String username, String password) {\n        //LDAP登陆地址\n        String ldapUrl = ConstUtils.LDAP_URL;\n        if (StringUtils.isBlank(ldapUrl)) {\n            logger.warn(\"ldap url is empty!!\");\n            return true;\n        }\n        if (ConstUtils.IS_DEBUG) {\n            logger.warn(\"isDebug=true return\");\n            return true;\n        }\n        Hashtable<String, String> env = new Hashtable<String, String>();\n        env.put(\"java.naming.factory.initial\", \"com.sun.jndi.ldap.LdapCtxFactory\");\n        env.put(\"java.naming.provider.url\", ldapUrl);\n        env.put(\"java.naming.security.authentication\", \"simple\");\n        env.put(\"java.naming.security.principal\", username + ConstUtils.EMAIL_SUFFIX);\n        env.put(\"java.naming.security.credentials\", password);\n        DirContext ctx = null;\n        try {\n            ctx = new InitialDirContext(env);\n            if (ctx != null) {\n                return true;\n            }\n        } catch (Exception e) {\n            logger.error(\"username {} passportCheck: \" + e.getMessage(), username, e);\n        } finally {\n            if (ctx != null) {\n                try {\n                    ctx.close();\n                } catch (Exception e) {\n                    logger.error(e.getMessage(), e);\n                }\n            }\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/.gitignore",
    "content": ".idea/\n*.iml\n.svn/*\ntarget/\n*.class\n.settings\n.classpath\n.project\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/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    <parent>\n        <groupId>com.sohu.tv</groupId>\n        <artifactId>open-cachecloud</artifactId>\n        <version>1.0-SNAPSHOT</version>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n    <name>cachecloud-open-web</name>\n    <groupId>com.sohu.tv</groupId>\n    <artifactId>cachecloud-open-web</artifactId>\n    <version>1.0-SNAPSHOT</version>\n    <packaging>war</packaging>\n    <properties>\n        <spring-boot.version>1.3.1.RELEASE</spring-boot.version>\n        <tomcat.version>8.0.28</tomcat.version>\n        <cachecloud-open-client-basic>1.0-SNAPSHOT</cachecloud-open-client-basic>\n        <cachecloud-jedis>1.0-SNAPSHOT</cachecloud-jedis>\n        <cachecloud-open-common.version>1.0-SNAPSHOT</cachecloud-open-common.version>\n    </properties>\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework</groupId>\n            <artifactId>spring-context-support</artifactId>\n        </dependency>\n\n        <!-- spring-boot start -->\n        <dependency>\n            <!-- Import dependency management from Spring Boot -->\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-dependencies</artifactId>\n            <version>${spring-boot.version}</version>\n            <type>pom</type>\n            <scope>import</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter</artifactId>\n            <version>${spring-boot.version}</version>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n            <version>${spring-boot.version}</version>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-jdbc</artifactId>\n            <version>${spring-boot.version}</version>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-remote-shell</artifactId>\n            <version>${spring-boot.version}</version>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <version>${spring-boot.version}</version>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-actuator</artifactId>\n            <version>${spring-boot.version}</version>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-tomcat</artifactId>\n            <version>${spring-boot.version}</version>\n            <scope>provided</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.tomcat.embed</groupId>\n            <artifactId>tomcat-embed-jasper</artifactId>\n            <version>${tomcat.version}</version>\n            <scope>provided</scope>\n        </dependency>\n        <!--spring boot end-->\n\n        <dependency>\n            <groupId>javax.servlet</groupId>\n            <artifactId>jstl</artifactId>\n            <version>1.2</version>\n        </dependency>\n\n        <dependency>\n            <groupId>org.quartz-scheduler</groupId>\n            <artifactId>quartz</artifactId>\n            <exclusions>\n                <exclusion>\n                    <artifactId>slf4j-api</artifactId>\n                    <groupId>org.slf4j</groupId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>ch.qos.logback</groupId>\n            <artifactId>logback-classic</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>mysql</groupId>\n            <artifactId>mysql-connector-java</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>junit</groupId>\n            <artifactId>junit</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.mybatis</groupId>\n            <artifactId>mybatis-spring</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.mybatis</groupId>\n            <artifactId>mybatis</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.fasterxml.jackson.core</groupId>\n            <artifactId>jackson-databind</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.httpcomponents</groupId>\n            <artifactId>httpclient</artifactId>\n        </dependency>\n\n        <!-- toolkit -->\n        <dependency>\n            <groupId>ch.ethz.ganymed</groupId>\n            <artifactId>ganymed-ssh2</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.commons</groupId>\n            <artifactId>commons-collections4</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.google.guava</groupId>\n            <artifactId>guava</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>commons-lang</groupId>\n            <artifactId>commons-lang</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>net.sf.json-lib</groupId>\n            <artifactId>json-lib</artifactId>\n            <version>2.2.3</version>\n            <classifier>jdk15</classifier>  \n        </dependency>\n        <dependency>\n            <groupId>commons-configuration</groupId>\n            <artifactId>commons-configuration</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.velocity</groupId>\n            <artifactId>velocity</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.apache.velocity</groupId>\n            <artifactId>velocity-tools</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba</groupId>\n            <artifactId>fastjson</artifactId>\n        </dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.sohu.tv</groupId>\n\t\t\t<artifactId>cachecloud-open-client-basic</artifactId>\n\t\t\t<version>${cachecloud-open-client-basic}</version>\n\t\t</dependency>\n\t\n\t\t<dependency>\n\t\t\t<groupId>com.sohu.tv</groupId>\n\t\t\t<artifactId>cachecloud-jedis</artifactId>\n\t\t\t<version>${cachecloud-jedis}</version>\n\t\t</dependency>\n\t\t\n\t\t<dependency>\n\t\t\t<groupId>com.sohu.tv</groupId>\n\t\t\t<artifactId>cachecloud-open-common</artifactId>\n\t\t\t<version>${cachecloud-open-common.version}</version>\n\t\t</dependency>\n\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-surefire-plugin</artifactId>\n            </plugin>\n\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n                <version>${spring-boot.version}</version>\n                <configuration>\n                    <mainClass>com.sohu.cache.app.ApplicationStarter</mainClass>\n                    <addResources>false</addResources>\n                    <executable>true</executable>\n                </configuration>\n                <executions>\n                    <execution>\n                        <goals>\n                            <goal>repackage</goal>\n                        </goals>\n                        <id>1</id>\n                    </execution>\n                </executions>\n            </plugin>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-resources-plugin</artifactId>\n                <configuration>\n                    <encoding>UTF-8</encoding>\n                </configuration>\n            </plugin>\n        </plugins>\n        <resources>\n            <resource>\n                <directory>src/main/resources</directory>\n                <filtering>true</filtering>\n            </resource>\n        </resources>\n    </build>\n    <profiles>\n        <profile>\n            <id>local</id>\n            <activation>\n                <activeByDefault>true</activeByDefault>\n            </activation>\n            <build>\n                <filters>\n                    <filter>${project.basedir}/src/main/swap/local.properties</filter>\n                </filters>\n            </build>\n        </profile>\n        <profile>\n            <id>online</id>\n            <activation>\n                <activeByDefault>false</activeByDefault>\n            </activation>\n            <build>\n                <filters>\n                    <filter>${project.basedir}/src/main/swap/online.properties</filter>\n                </filters>\n            </build>\n        </profile>\n    </profiles>\n</project>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/alert/AppAlertService.java",
    "content": "package com.sohu.cache.alert;\n\nimport com.sohu.cache.entity.InstanceFault;\n\nimport java.util.List;\n\n/**\n * 应用报警\n * @author leifu\n * @Date 2014年12月16日\n * @Time 下午2:51:51\n */\npublic interface AppAlertService {\n\t\n    /**\n     * 应用故障列表\n     *\n     * @param appId\n     * @return\n     */\n    List<InstanceFault> getListByAppId(long appId);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/alert/InstanceAlertService.java",
    "content": "package com.sohu.cache.alert;\n\nimport com.sohu.cache.entity.InstanceFault;\n\nimport java.util.List;\n\n/**\n * 实例报警检测\n * @author leifu\n * @Date 2014年12月16日\n * @Time 下午1:56:35\n */\npublic interface InstanceAlertService {\n    \n    /**\n     * 实例故障列表\n     *\n     * @param instId\n     * @return\n     */\n    List<InstanceFault> getListByInstId(int instId);\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/alert/bean/AlertConfigBaseData.java",
    "content": "package com.sohu.cache.alert.bean;\n\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.entity.StandardStats;\n\n/**\n * 报警基础数据\n * @author leifu\n * @Date 2017年6月16日\n * @Time 下午2:19:10\n */\npublic class AlertConfigBaseData {\n    /**\n     * 基准数据\n     */\n    private StandardStats standardStats;\n    \n    /**\n     * 实例信息\n     */\n    private InstanceInfo instanceInfo;\n\n    public StandardStats getStandardStats() {\n        return standardStats;\n    }\n\n    public void setStandardStats(StandardStats standardStats) {\n        this.standardStats = standardStats;\n    }\n\n    public InstanceInfo getInstanceInfo() {\n        return instanceInfo;\n    }\n\n    public void setInstanceInfo(InstanceInfo instanceInfo) {\n        this.instanceInfo = instanceInfo;\n    }\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/alert/impl/AppAlertServiceImpl.java",
    "content": "package com.sohu.cache.alert.impl;\n\nimport java.util.List;\n\nimport org.springframework.util.Assert;\n\nimport com.sohu.cache.alert.AppAlertService;\nimport com.sohu.cache.dao.InstanceFaultDao;\nimport com.sohu.cache.entity.InstanceFault;\n\n/**\n * 应用报警实现\n * \n * @author leifu\n * @Date 2014年12月17日\n * @Time 上午9:51:21\n */\npublic class AppAlertServiceImpl extends BaseAlertService implements AppAlertService {\n\n    private InstanceFaultDao instanceFaultDao;\n\n    @Override\n    public List<InstanceFault> getListByAppId(long appId) {\n        Assert.isTrue(appId > 0);\n        return instanceFaultDao.getListByAppId(appId);\n    }\n\n    public void setInstanceFaultDao(InstanceFaultDao instanceFaultDao) {\n        this.instanceFaultDao = instanceFaultDao;\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/alert/impl/BaseAlertService.java",
    "content": "package com.sohu.cache.alert.impl;\n\nimport com.sohu.cache.web.component.EmailComponent;\nimport com.sohu.cache.web.component.MobileAlertComponent;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * 报警基类\n * @author leifu\n * @Date 2014年12月16日\n * @Time 下午4:15:11\n */\npublic class BaseAlertService {\n    protected final Logger logger = LoggerFactory.getLogger(this.getClass());\n\n    /**\n     * 邮箱报警\n     */\n    protected EmailComponent emailComponent;\n\n    /**\n     * 手机短信报警\n     */\n    protected MobileAlertComponent mobileAlertComponent;\n\n    public void setEmailComponent(EmailComponent emailComponent) {\n        this.emailComponent = emailComponent;\n    }\n\n    public void setMobileAlertComponent(MobileAlertComponent mobileAlertComponent) {\n        this.mobileAlertComponent = mobileAlertComponent;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/alert/impl/InstanceAlertServiceImpl.java",
    "content": "package com.sohu.cache.alert.impl;\n\nimport java.util.List;\n\nimport org.springframework.util.Assert;\n\nimport com.sohu.cache.alert.InstanceAlertService;\nimport com.sohu.cache.dao.InstanceFaultDao;\nimport com.sohu.cache.entity.InstanceFault;\n\n/**\n * 实例报警\n * @author leifu\n * @Date 2014年12月16日\n * @Time 下午2:02:13\n */\npublic class InstanceAlertServiceImpl extends BaseAlertService implements InstanceAlertService {\n    \n    private InstanceFaultDao instanceFaultDao;\n\n    @Override\n    public List<InstanceFault> getListByInstId(int instId) {\n        Assert.isTrue(instId > 0);\n        return instanceFaultDao.getListByInstId(instId);\n    }\n\n    public void setInstanceFaultDao(InstanceFaultDao instanceFaultDao) {\n        this.instanceFaultDao = instanceFaultDao;\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/alert/strategy/AlertConfigStrategy.java",
    "content": "package com.sohu.cache.alert.strategy;\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\n\nimport org.apache.commons.collections.MapUtils;\nimport org.apache.commons.lang.math.NumberUtils;\n\nimport com.sohu.cache.alert.bean.AlertConfigBaseData;\nimport com.sohu.cache.entity.InstanceAlertConfig;\nimport com.sohu.cache.entity.InstanceAlertValueResult;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.entity.StandardStats;\nimport com.sohu.cache.redis.enums.InstanceAlertCompareTypeEnum;\nimport com.sohu.cache.util.JsonUtil;\n\n/**\n * @author leifu\n * @Date 2017年6月2日\n * @Time 下午3:24:53\n */\npublic abstract class AlertConfigStrategy {\n    \n    protected final static String MB_STRING = \"MB\";\n    protected final static String EMPTY = \"\";\n\n    /**\n     * 检查配置\n     * \n     * @param instanceAlertConfig\n     * @param alertConfigBaseData\n     */\n    public abstract List<InstanceAlertValueResult> checkConfig(InstanceAlertConfig instanceAlertConfig,\n            AlertConfigBaseData alertConfigBaseData);\n\n    /**\n     * 比较long类型\n     * \n     * @param instanceAlertConfig 报警配置\n     * @param currentValue 当前值\n     * @return\n     */\n    protected boolean isCompareLongRight(InstanceAlertConfig instanceAlertConfig, long currentValue) {\n        long alertValue = NumberUtils.toLong(instanceAlertConfig.getAlertValue());\n        int compareType = instanceAlertConfig.getCompareType();\n        if (compareType == InstanceAlertCompareTypeEnum.LESS_THAN.getValue() && currentValue < alertValue) {\n            return false;\n        } else if (compareType == InstanceAlertCompareTypeEnum.MORE_THAN.getValue() && currentValue > alertValue) {\n            return false;\n        } else if (compareType == InstanceAlertCompareTypeEnum.EQUAL.getValue() && currentValue == alertValue) {\n            return false;\n        } else if (compareType == InstanceAlertCompareTypeEnum.NOT_EQUAL.getValue() && currentValue != alertValue) {\n            return false;\n        }\n        return true;\n    }\n\n    /**\n     * 比较int类型\n     * \n     * @param instanceAlertConfig 报警配置\n     * @param currentValue 当前值\n     * @return\n     */\n    protected boolean isCompareIntRight(InstanceAlertConfig instanceAlertConfig, int currentValue) {\n        int alertValue = NumberUtils.toInt(instanceAlertConfig.getAlertValue());\n        int compareType = instanceAlertConfig.getCompareType();\n        if (compareType == InstanceAlertCompareTypeEnum.LESS_THAN.getValue() && currentValue < alertValue) {\n            return false;\n        } else if (compareType == InstanceAlertCompareTypeEnum.MORE_THAN.getValue() && currentValue > alertValue) {\n            return false;\n        } else if (compareType == InstanceAlertCompareTypeEnum.EQUAL.getValue() && currentValue == alertValue) {\n            return false;\n        } else if (compareType == InstanceAlertCompareTypeEnum.NOT_EQUAL.getValue() && currentValue != alertValue) {\n            return false;\n        }\n        return true;\n    }\n    \n    /**\n     * 比较double类型\n     * \n     * @param instanceAlertConfig 报警配置\n     * @param currentValue 当前值\n     * @return\n     */\n    protected boolean isCompareDoubleRight(InstanceAlertConfig instanceAlertConfig, double currentValue) {\n        double alertValue = NumberUtils.toDouble(instanceAlertConfig.getAlertValue());\n        int compareType = instanceAlertConfig.getCompareType();\n        if (compareType == InstanceAlertCompareTypeEnum.LESS_THAN.getValue() && currentValue < alertValue) {\n            return false;\n        } else if (compareType == InstanceAlertCompareTypeEnum.MORE_THAN.getValue() && currentValue > alertValue) {\n            return false;\n        } else if (compareType == InstanceAlertCompareTypeEnum.EQUAL.getValue() && currentValue == alertValue) {\n            return false;\n        } else if (compareType == InstanceAlertCompareTypeEnum.NOT_EQUAL.getValue() && currentValue != alertValue) {\n            return false;\n        }\n        return true;\n    }\n\n    /**\n     * 比较字符串类型\n     * \n     * @param instanceAlertConfig 报警配置\n     * @param currentValue 当期值\n     * @return\n     */\n    protected boolean isCompareStringRight(InstanceAlertConfig instanceAlertConfig, String currentValue) {\n        String alertValue = instanceAlertConfig.getAlertValue();\n        int compareType = instanceAlertConfig.getCompareType();\n        if (compareType == InstanceAlertCompareTypeEnum.EQUAL.getValue() && currentValue.equals(alertValue)) {\n            return false;\n        } else if (compareType == InstanceAlertCompareTypeEnum.NOT_EQUAL.getValue()\n                && !currentValue.equals(alertValue)) {\n            return false;\n        }\n        return true;\n    }\n\n    /**\n     * 生成instance级别报警文案\n     * @param instanceAlertConfig\n     * @param instanceInfo\n     * @param currentValue\n     * @param unit\n     * @return\n     */\n    protected String genInstanceAlertText(InstanceAlertConfig instanceAlertConfig, InstanceInfo instanceInfo,\n            String currentValue, String unit) {\n        String configKey = instanceAlertConfig.getAlertConfig();\n        String configValue = instanceAlertConfig.getAlertValue();\n        String compareTypeInfo = InstanceAlertCompareTypeEnum\n                .getInstanceAlertCompareTypeEnum(instanceAlertConfig.getCompareType()).getInfo();\n        StringBuilder alertText = new StringBuilder();\n        alertText.append(instanceInfo.getHostPort());\n        alertText.append(\",报警项:\").append(configKey);\n        alertText.append(\"=\").append(currentValue).append(unit).append(\",\");\n        alertText.append(compareTypeInfo);\n        alertText.append(\"报警阈值:\").append(configValue).append(unit);\n        return alertText.toString();\n    }\n\n    /**\n     * 获取全量统计项中的内容\n     * @param redisInfo\n     * @param attribute\n     * @return\n     */\n    protected static Object getValueFromRedisInfo(StandardStats standardStats, String attribute) {\n        if (standardStats == null) {\n            return null;\n        }\n        // 转换成Map\n        Map<String, Object> infoMap = JsonUtil.fromJson(standardStats.getInfoJson(), Map.class);\n        if (MapUtils.isEmpty(infoMap)) {\n            return null;\n        }\n        for (Entry<String, Object> entry : infoMap.entrySet()) {\n            Object object = entry.getValue();\n            // 转换成Map<String, Map<String,Object>>\n            if (!(object instanceof Map)) {\n                continue;\n            }\n            Map<String, Object> sectionInfoMap = (Map<String, Object>) object;\n            if (sectionInfoMap != null && sectionInfoMap.containsKey(attribute)) {\n                return MapUtils.getObject(sectionInfoMap, attribute);\n            }\n        }\n        return null;\n    }\n    \n    /**\n     * 获取差值统计项中的内容\n     * @param redisInfo\n     * @param attribute\n     * @return\n     */\n    protected static Object getValueFromDiffInfo(StandardStats standardStats, String attribute) {\n        if (standardStats == null) {\n            return null;\n        }\n        Map<String, Object> diffInfoMap = JsonUtil.fromJson(standardStats.getDiffJson(), Map.class);\n        if (MapUtils.isEmpty(diffInfoMap)) {\n            return null;\n        }\n        return MapUtils.getObject(diffInfoMap, attribute);\n    }\n    \n    /**\n     * 获取cluster info统计项中的内容\n     * @param redisInfo\n     * @param attribute\n     * @return\n     */\n    protected static Object getValueFromClusterInfo(StandardStats standardStats, String attribute) {\n        if (standardStats == null) {\n            return null;\n        }\n        Map<String, Object> clusterInfoMap = JsonUtil.fromJson(standardStats.getClusterInfoJson(), Map.class);\n        if (MapUtils.isEmpty(clusterInfoMap)) {\n            return null;\n        }\n        return MapUtils.getObject(clusterInfoMap, attribute);\n    }\n    \n    /**\n     * 把字节变为兆\n     * @param value\n     * @return\n     */\n    protected long changeByteToMB(long value) {\n        return value / 1024 / 1024;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/alert/strategy/AofCurrentSizeAlertStrategy.java",
    "content": "package com.sohu.cache.alert.strategy;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport org.apache.commons.lang.math.NumberUtils;\n\nimport com.sohu.cache.alert.bean.AlertConfigBaseData;\nimport com.sohu.cache.entity.InstanceAlertConfig;\nimport com.sohu.cache.entity.InstanceAlertValueResult;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.redis.enums.RedisInfoEnum;\n\n/**\n * aof当前尺寸检测\n * @author leifu\n * @Date 2017年6月16日\n * @Time 下午2:34:10\n */\npublic class AofCurrentSizeAlertStrategy extends AlertConfigStrategy {\n\n    @Override\n    public List<InstanceAlertValueResult> checkConfig(InstanceAlertConfig instanceAlertConfig, AlertConfigBaseData alertConfigBaseData) {\n        Object object = getValueFromRedisInfo(alertConfigBaseData.getStandardStats(), RedisInfoEnum.aof_current_size.getValue());\n        // 没有配置Aof\n        if (object == null) {\n            return null;\n        }\n        long aofCurrentSize = NumberUtils.toLong(object.toString());\n        aofCurrentSize = changeByteToMB(aofCurrentSize);\n        boolean compareRight = isCompareLongRight(instanceAlertConfig, aofCurrentSize);\n        if (compareRight) {\n            return null;\n        }\n        InstanceInfo instanceInfo = alertConfigBaseData.getInstanceInfo();\n        return Arrays.asList(new InstanceAlertValueResult(instanceAlertConfig, instanceInfo, String.valueOf(aofCurrentSize),\n                instanceInfo.getAppId(), MB_STRING));\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/alert/strategy/ClientBiggestInputBufAlertStrategy.java",
    "content": "package com.sohu.cache.alert.strategy;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport org.apache.commons.lang.math.NumberUtils;\n\nimport com.sohu.cache.alert.bean.AlertConfigBaseData;\nimport com.sohu.cache.entity.InstanceAlertConfig;\nimport com.sohu.cache.entity.InstanceAlertValueResult;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.redis.enums.RedisInfoEnum;\n\n/**\n * 客户端输入缓冲区最大buffer\n * \n * @author leifu\n * @Date 2017年6月16日\n * @Time 下午2:34:10\n */\npublic class ClientBiggestInputBufAlertStrategy extends AlertConfigStrategy {\n    @Override\n    public List<InstanceAlertValueResult> checkConfig(InstanceAlertConfig instanceAlertConfig, AlertConfigBaseData alertConfigBaseData) {\n        Object object = getValueFromRedisInfo(alertConfigBaseData.getStandardStats(), RedisInfoEnum.client_biggest_input_buf.getValue());\n        if (object == null) {\n            return null;\n        }\n        // 关系比对\n        long clientBiggestInputBuf = NumberUtils.toLong(object.toString()) ;\n        clientBiggestInputBuf = changeByteToMB(clientBiggestInputBuf);\n        boolean compareRight = isCompareLongRight(instanceAlertConfig, clientBiggestInputBuf);\n        if (compareRight) {\n            return null;\n        }\n        InstanceInfo instanceInfo = alertConfigBaseData.getInstanceInfo();\n        return Arrays.asList(new InstanceAlertValueResult(instanceAlertConfig, instanceInfo, String.valueOf(clientBiggestInputBuf),\n                instanceInfo.getAppId(), MB_STRING));\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/alert/strategy/ClientLongestOutputListAlertStrategy.java",
    "content": "package com.sohu.cache.alert.strategy;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport org.apache.commons.lang.math.NumberUtils;\n\nimport com.sohu.cache.alert.bean.AlertConfigBaseData;\nimport com.sohu.cache.entity.InstanceAlertConfig;\nimport com.sohu.cache.entity.InstanceAlertValueResult;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.redis.enums.RedisInfoEnum;\n\n/**\n * 客户端输出缓冲区最大队列长度\n * \n * @author leifu\n * @Date 2017年6月16日\n * @Time 下午2:34:10\n */\npublic class ClientLongestOutputListAlertStrategy extends AlertConfigStrategy {\n    @Override\n    public List<InstanceAlertValueResult> checkConfig(InstanceAlertConfig instanceAlertConfig, AlertConfigBaseData alertConfigBaseData) {\n        Object object = getValueFromRedisInfo(alertConfigBaseData.getStandardStats(), RedisInfoEnum.client_longest_output_list.getValue());\n        if (object == null) {\n            return null;\n        }\n        // 关系比对\n        long clientLongestOutputList = NumberUtils.toLong(object.toString());\n        boolean compareRight = isCompareLongRight(instanceAlertConfig, clientLongestOutputList);\n        if (compareRight) {\n            return null;\n        }\n        InstanceInfo instanceInfo = alertConfigBaseData.getInstanceInfo();\n        return Arrays.asList(new InstanceAlertValueResult(instanceAlertConfig, instanceInfo, String.valueOf(clientLongestOutputList),\n                instanceInfo.getAppId(), EMPTY));\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/alert/strategy/ClusterSlotsOkAlertStrategy.java",
    "content": "package com.sohu.cache.alert.strategy;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport org.apache.commons.lang.math.NumberUtils;\n\nimport com.sohu.cache.alert.bean.AlertConfigBaseData;\nimport com.sohu.cache.entity.InstanceAlertConfig;\nimport com.sohu.cache.entity.InstanceAlertValueResult;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.redis.enums.RedisClusterInfoEnum;\n\n/**\n * 集群成功分配槽个数监控\n * @author leifu\n * @Date 2017年6月21日\n * @Time 下午3:01:21\n */\npublic class ClusterSlotsOkAlertStrategy extends AlertConfigStrategy {\n\n    @Override\n    public List<InstanceAlertValueResult> checkConfig(InstanceAlertConfig instanceAlertConfig, AlertConfigBaseData alertConfigBaseData) {\n        Object object = getValueFromClusterInfo(alertConfigBaseData.getStandardStats(), RedisClusterInfoEnum.cluster_slots_ok.getValue());\n        if (object == null) {\n            return null;\n        }\n        // 关系比对\n        int clusterSlotsOk = NumberUtils.toInt(object.toString());\n        boolean compareRight = isCompareIntRight(instanceAlertConfig, clusterSlotsOk);\n        if (compareRight) {\n            return null;\n        }\n        InstanceInfo instanceInfo = alertConfigBaseData.getInstanceInfo();\n        return Arrays.asList(new InstanceAlertValueResult(instanceAlertConfig, instanceInfo, String.valueOf(clusterSlotsOk),\n                instanceInfo.getAppId(), EMPTY));\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/alert/strategy/ClusterStateAlertStrategy.java",
    "content": "package com.sohu.cache.alert.strategy;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport com.sohu.cache.alert.bean.AlertConfigBaseData;\nimport com.sohu.cache.entity.InstanceAlertConfig;\nimport com.sohu.cache.entity.InstanceAlertValueResult;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.redis.enums.RedisClusterInfoEnum;\n\n/**\n * 集群状态监控\n * @author leifu\n * @Date 2017年6月21日\n * @Time 下午3:01:21\n */\npublic class ClusterStateAlertStrategy extends AlertConfigStrategy {\n\n    @Override\n    public List<InstanceAlertValueResult> checkConfig(InstanceAlertConfig instanceAlertConfig, AlertConfigBaseData alertConfigBaseData) {\n        Object object = getValueFromClusterInfo(alertConfigBaseData.getStandardStats(), RedisClusterInfoEnum.cluster_state.getValue());\n        if (object == null) {\n            return null;\n        }\n        // 关系比对\n        String clusterState = object.toString();\n        boolean compareRight = isCompareStringRight(instanceAlertConfig, clusterState);\n        if (compareRight) {\n            return null;\n        }\n        InstanceInfo instanceInfo = alertConfigBaseData.getInstanceInfo();\n        return Arrays.asList(new InstanceAlertValueResult(instanceAlertConfig, instanceInfo, String.valueOf(clusterState),\n                instanceInfo.getAppId(), EMPTY));\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/alert/strategy/InstantaneousOpsPerSecAlertStrategy.java",
    "content": "package com.sohu.cache.alert.strategy;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport org.apache.commons.lang.math.NumberUtils;\n\nimport com.sohu.cache.alert.bean.AlertConfigBaseData;\nimport com.sohu.cache.entity.InstanceAlertConfig;\nimport com.sohu.cache.entity.InstanceAlertValueResult;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.redis.enums.RedisInfoEnum;\n\n/**\n * 实时ops\n * \n * @author leifu\n * @Date 2017年6月16日\n * @Time 下午2:34:10\n */\npublic class InstantaneousOpsPerSecAlertStrategy extends AlertConfigStrategy {\n    @Override\n    public List<InstanceAlertValueResult> checkConfig(InstanceAlertConfig instanceAlertConfig, AlertConfigBaseData alertConfigBaseData) {\n        Object object = getValueFromRedisInfo(alertConfigBaseData.getStandardStats(), RedisInfoEnum.instantaneous_ops_per_sec.getValue());\n        if (object == null) {\n            return null;\n        }\n        // 关系比对\n        long instantaneousOpsPerSec = NumberUtils.toLong(object.toString());\n        boolean compareRight = isCompareLongRight(instanceAlertConfig, instantaneousOpsPerSec);\n        if (compareRight) {\n            return null;\n        }\n        InstanceInfo instanceInfo = alertConfigBaseData.getInstanceInfo();\n        return Arrays.asList(new InstanceAlertValueResult(instanceAlertConfig, instanceInfo, String.valueOf(instantaneousOpsPerSec),\n                instanceInfo.getAppId(), EMPTY));\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/alert/strategy/LatestForkUsecAlertStrategy.java",
    "content": "package com.sohu.cache.alert.strategy;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport org.apache.commons.lang.math.NumberUtils;\n\nimport com.sohu.cache.alert.bean.AlertConfigBaseData;\nimport com.sohu.cache.entity.InstanceAlertConfig;\nimport com.sohu.cache.entity.InstanceAlertValueResult;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.redis.enums.RedisInfoEnum;\n\n/**\n * 上一次fork的微秒\n * \n * @author leifu\n * @Date 2017年6月16日\n * @Time 下午2:34:10\n */\npublic class LatestForkUsecAlertStrategy extends AlertConfigStrategy {\n    @Override\n    public List<InstanceAlertValueResult> checkConfig(InstanceAlertConfig instanceAlertConfig, AlertConfigBaseData alertConfigBaseData) {\n        Object object = getValueFromRedisInfo(alertConfigBaseData.getStandardStats(), RedisInfoEnum.latest_fork_usec.getValue());\n        if (object == null) {\n            return null;\n        }\n        // 关系比对\n        long latestForkUsec = NumberUtils.toLong(object.toString());\n        boolean compareRight = isCompareLongRight(instanceAlertConfig, latestForkUsec);\n        if (compareRight) {\n            return null;\n        }\n        InstanceInfo instanceInfo = alertConfigBaseData.getInstanceInfo();\n        return Arrays.asList(new InstanceAlertValueResult(instanceAlertConfig, instanceInfo, String.valueOf(latestForkUsec),\n                instanceInfo.getAppId(), EMPTY));\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/alert/strategy/MasterSlaveOffsetAlertStrategy.java",
    "content": "package com.sohu.cache.alert.strategy;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.apache.commons.lang.math.NumberUtils;\n\nimport com.sohu.cache.alert.bean.AlertConfigBaseData;\nimport com.sohu.cache.entity.InstanceAlertConfig;\nimport com.sohu.cache.entity.InstanceAlertValueResult;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.redis.enums.RedisInfoEnum;\n\n/**\n * 主从偏移量监控\n * @author leifu\n * @Date 2017年6月16日\n * @Time 下午2:34:10\n */\npublic class MasterSlaveOffsetAlertStrategy extends AlertConfigStrategy {\n\n    /**\n     * 格式：\n     *     connected_slaves:2\n     *     slave0:ip=10.10.76.151,port=6380,state=online,offset=33119690469561,lag=1\n     *     slave1:ip=10.10.76.160,port=6380,state=online,offset=33119690513578,lag=0\n     *     master_repl_offset:33119653194425\n     */\n    @Override\n    public List<InstanceAlertValueResult> checkConfig(InstanceAlertConfig instanceAlertConfig, AlertConfigBaseData alertConfigBaseData) {\n        Object connectedSlavesObject = getValueFromRedisInfo(alertConfigBaseData.getStandardStats(), RedisInfoEnum.connected_slaves.getValue());\n        if (connectedSlavesObject == null) {\n            return null;\n        }\n        int connectedSlaves = NumberUtils.toInt(connectedSlavesObject.toString());\n        if (connectedSlaves == 0) {\n            return null;\n        }\n        Object masterReplOffsetObject = getValueFromRedisInfo(alertConfigBaseData.getStandardStats(), RedisInfoEnum.master_repl_offset.getValue());\n        if (masterReplOffsetObject == null) {\n            return null;\n        }\n        List<InstanceAlertValueResult> instanceAlertValueResultList = new ArrayList<InstanceAlertValueResult>();\n        for (int i = 0; i < connectedSlaves; i++) {\n            Object slaveInfo = getValueFromRedisInfo(alertConfigBaseData.getStandardStats(), \"slave\" + i);\n            if (slaveInfo == null) {\n                continue;\n            }\n            String[] arr = slaveInfo.toString().split(\",\");\n            if (arr.length < 5) {\n                continue;\n            }\n            String state = arr[2];\n            if (!\"state=online\".equals(state)) {\n                continue;\n            }\n            String slaveHostPort = arr[0] + \",\" + arr[1];\n            String slaveOffsetStr = arr[3];\n            String[] slaveOffsetArr = slaveOffsetStr.split(\"=\");\n            if (slaveOffsetArr.length != 2) {\n                continue;\n            }\n            String slaveOffset = slaveOffsetArr[1];\n            long diffOffset = Math.abs(NumberUtils.toLong(masterReplOffsetObject.toString()) - NumberUtils.toLong(slaveOffset));\n            boolean compareRight = isCompareDoubleRight(instanceAlertConfig, diffOffset);\n            if (compareRight) {\n                return null;\n            }\n            InstanceInfo instanceInfo = alertConfigBaseData.getInstanceInfo();\n            InstanceAlertValueResult instanceAlertValueResult = new InstanceAlertValueResult(instanceAlertConfig, instanceInfo, String.valueOf(diffOffset),\n                    instanceInfo.getAppId(), EMPTY);\n            String otherInfo = String.format(\"masterOffset is %s<br/>slaveOffset  is %s<br/>%s\", masterReplOffsetObject.toString(), slaveOffset, slaveHostPort);\n            instanceAlertValueResult.setOtherInfo(otherInfo);\n            instanceAlertValueResultList.add(instanceAlertValueResult);\n        }\n        return instanceAlertValueResultList;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/alert/strategy/MemFragmentationRatioAlertStrategy.java",
    "content": "package com.sohu.cache.alert.strategy;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport org.apache.commons.lang.math.NumberUtils;\n\nimport com.sohu.cache.alert.bean.AlertConfigBaseData;\nimport com.sohu.cache.entity.InstanceAlertConfig;\nimport com.sohu.cache.entity.InstanceAlertValueResult;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.redis.enums.RedisInfoEnum;\n\n/**\n * 内存碎片率\n * \n * @author leifu\n * @Date 2017年6月16日\n * @Time 下午2:34:10\n */\npublic class MemFragmentationRatioAlertStrategy extends AlertConfigStrategy {\n    \n    /**\n     * 实例最小500MB才进行内存碎片率检查，否则价值不是很大\n     */\n    private final static long MIN_CHECK_MEMORY = 500 * 1024 * 1024;\n    \n    @Override\n    public List<InstanceAlertValueResult> checkConfig(InstanceAlertConfig instanceAlertConfig, AlertConfigBaseData alertConfigBaseData) {\n        // 检查内存\n        Object usedMemoryObject = getValueFromRedisInfo(alertConfigBaseData.getStandardStats(), RedisInfoEnum.used_memory.getValue());\n        long usedMemory = NumberUtils.toLong(usedMemoryObject.toString());\n        if (usedMemory < MIN_CHECK_MEMORY) {\n            return null;\n        }\n        \n        // 内存碎片率\n        Object memFragmentationRatioObject = getValueFromRedisInfo(alertConfigBaseData.getStandardStats(), RedisInfoEnum.mem_fragmentation_ratio.getValue());\n        if (memFragmentationRatioObject == null) {\n            return null;\n        }\n        \n        // 关系比对\n        double memFragmentationRatio = NumberUtils.toDouble(memFragmentationRatioObject.toString());\n        boolean compareRight = isCompareDoubleRight(instanceAlertConfig, memFragmentationRatio);\n        if (compareRight) {\n            return null;\n        }\n        InstanceInfo instanceInfo = alertConfigBaseData.getInstanceInfo();\n        InstanceAlertValueResult instanceAlertValueResult = new InstanceAlertValueResult(instanceAlertConfig, instanceInfo, String.valueOf(memFragmentationRatio),\n                instanceInfo.getAppId(), EMPTY);\n        instanceAlertValueResult.setOtherInfo(String.format(\"内存使用为%s MB\", String.valueOf(changeByteToMB(usedMemory))));\n        return Arrays.asList();\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/alert/strategy/MinuteAofDelayedFsyncAlertStrategy.java",
    "content": "package com.sohu.cache.alert.strategy;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport org.apache.commons.lang.math.NumberUtils;\n\nimport com.sohu.cache.alert.bean.AlertConfigBaseData;\nimport com.sohu.cache.entity.InstanceAlertConfig;\nimport com.sohu.cache.entity.InstanceAlertValueResult;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.redis.enums.RedisInfoEnum;\n\n/**\n * 分钟aof delay fsync检测\n * @author leifu\n * @Date 2017年6月16日\n * @Time 下午2:34:10\n */\npublic class MinuteAofDelayedFsyncAlertStrategy extends AlertConfigStrategy {\n\n    @Override\n    public List<InstanceAlertValueResult> checkConfig(InstanceAlertConfig instanceAlertConfig, AlertConfigBaseData alertConfigBaseData) {\n        Object object = getValueFromDiffInfo(alertConfigBaseData.getStandardStats(), RedisInfoEnum.aof_delayed_fsync.getValue());\n        if (object == null) {\n            return null;\n        }\n        long aofDelayedFsync = NumberUtils.toLong(object.toString());\n        boolean compareRight = isCompareLongRight(instanceAlertConfig, aofDelayedFsync);\n        if (compareRight) {\n            return null;\n        }\n        InstanceInfo instanceInfo = alertConfigBaseData.getInstanceInfo();\n        return Arrays.asList(new InstanceAlertValueResult(instanceAlertConfig, instanceInfo, String.valueOf(aofDelayedFsync),\n                instanceInfo.getAppId(), EMPTY));\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/alert/strategy/MinuteRejectedConnectionsAlertStrategy.java",
    "content": "package com.sohu.cache.alert.strategy;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport org.apache.commons.lang.math.NumberUtils;\n\nimport com.sohu.cache.alert.bean.AlertConfigBaseData;\nimport com.sohu.cache.entity.InstanceAlertConfig;\nimport com.sohu.cache.entity.InstanceAlertValueResult;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.redis.enums.RedisInfoEnum;\n\n/**\n * 分钟拒绝客户端连接数\n * @author leifu\n * @Date 2017年6月16日\n * @Time 下午2:34:10\n */\npublic class MinuteRejectedConnectionsAlertStrategy extends AlertConfigStrategy {\n\n    @Override\n    public List<InstanceAlertValueResult> checkConfig(InstanceAlertConfig instanceAlertConfig, AlertConfigBaseData alertConfigBaseData) {\n        Object object = getValueFromDiffInfo(alertConfigBaseData.getStandardStats(), RedisInfoEnum.rejected_connections.getValue());\n        if (object == null) {\n            return null;\n        }\n        long minuteRejectedConnections = NumberUtils.toLong(object.toString());\n        boolean compareRight = isCompareLongRight(instanceAlertConfig, minuteRejectedConnections);\n        if (compareRight) {\n            return null;\n        }\n        InstanceInfo instanceInfo = alertConfigBaseData.getInstanceInfo();\n        return Arrays.asList(new InstanceAlertValueResult(instanceAlertConfig, instanceInfo, String.valueOf(minuteRejectedConnections),\n                instanceInfo.getAppId(), EMPTY));\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/alert/strategy/MinuteSyncFullAlertStrategy.java",
    "content": "package com.sohu.cache.alert.strategy;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport org.apache.commons.lang.math.NumberUtils;\n\nimport com.sohu.cache.alert.bean.AlertConfigBaseData;\nimport com.sohu.cache.entity.InstanceAlertConfig;\nimport com.sohu.cache.entity.InstanceAlertValueResult;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.redis.enums.RedisInfoEnum;\n\n/**\n * 分钟全量复制次数\n * @author leifu\n * @Date 2017年6月16日\n * @Time 下午2:34:10\n */\npublic class MinuteSyncFullAlertStrategy extends AlertConfigStrategy {\n\n    @Override\n    public List<InstanceAlertValueResult> checkConfig(InstanceAlertConfig instanceAlertConfig, AlertConfigBaseData alertConfigBaseData) {\n        Object object = getValueFromDiffInfo(alertConfigBaseData.getStandardStats(), RedisInfoEnum.sync_full.getValue());\n        if (object == null) {\n            return null;\n        }\n        long minuteSyncFull = NumberUtils.toLong(object.toString());\n        boolean compareRight = isCompareLongRight(instanceAlertConfig, minuteSyncFull);\n        if (compareRight) {\n            return null;\n        }\n        InstanceInfo instanceInfo = alertConfigBaseData.getInstanceInfo();\n        return Arrays.asList(new InstanceAlertValueResult(instanceAlertConfig, instanceInfo, String.valueOf(minuteSyncFull),\n                instanceInfo.getAppId(), EMPTY));\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/alert/strategy/MinuteSyncPartialErrAlertStrategy.java",
    "content": "package com.sohu.cache.alert.strategy;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport org.apache.commons.lang.math.NumberUtils;\n\nimport com.sohu.cache.alert.bean.AlertConfigBaseData;\nimport com.sohu.cache.entity.InstanceAlertConfig;\nimport com.sohu.cache.entity.InstanceAlertValueResult;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.redis.enums.RedisInfoEnum;\n\n/**\n * 分钟部分复制失败次数\n * @author leifu\n * @Date 2017年6月16日\n * @Time 下午2:34:10\n */\npublic class MinuteSyncPartialErrAlertStrategy extends AlertConfigStrategy {\n\n    @Override\n    public List<InstanceAlertValueResult> checkConfig(InstanceAlertConfig instanceAlertConfig, AlertConfigBaseData alertConfigBaseData) {\n        Object object = getValueFromDiffInfo(alertConfigBaseData.getStandardStats(), RedisInfoEnum.sync_partial_err.getValue());\n        if (object == null) {\n            return null;\n        }\n        long minuteSyncPartialErr = NumberUtils.toLong(object.toString());\n        boolean compareRight = isCompareLongRight(instanceAlertConfig, minuteSyncPartialErr);\n        if (compareRight) {\n            return null;\n        }\n        InstanceInfo instanceInfo = alertConfigBaseData.getInstanceInfo();\n        return Arrays.asList(new InstanceAlertValueResult(instanceAlertConfig, instanceInfo, String.valueOf(minuteSyncPartialErr),\n                instanceInfo.getAppId(), EMPTY));\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/alert/strategy/MinuteSyncPartialOkAlertStrategy.java",
    "content": "package com.sohu.cache.alert.strategy;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport org.apache.commons.lang.math.NumberUtils;\n\nimport com.sohu.cache.alert.bean.AlertConfigBaseData;\nimport com.sohu.cache.entity.InstanceAlertConfig;\nimport com.sohu.cache.entity.InstanceAlertValueResult;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.redis.enums.RedisInfoEnum;\n\n/**\n * 分钟部分复制成功次数\n * @author leifu\n * @Date 2017年6月16日\n * @Time 下午2:34:10\n */\npublic class MinuteSyncPartialOkAlertStrategy extends AlertConfigStrategy {\n\n    @Override\n    public List<InstanceAlertValueResult> checkConfig(InstanceAlertConfig instanceAlertConfig, AlertConfigBaseData alertConfigBaseData) {\n        Object object = getValueFromDiffInfo(alertConfigBaseData.getStandardStats(), RedisInfoEnum.sync_partial_ok.getValue());\n        if (object == null) {\n            return null;\n        }\n        long minuteSyncPartialOk = NumberUtils.toLong(object.toString());\n        boolean compareRight = isCompareLongRight(instanceAlertConfig, minuteSyncPartialOk);\n        if (compareRight) {\n            return null;\n        }\n        InstanceInfo instanceInfo = alertConfigBaseData.getInstanceInfo();\n        return Arrays.asList(new InstanceAlertValueResult(instanceAlertConfig, instanceInfo, String.valueOf(minuteSyncPartialOk),\n                instanceInfo.getAppId(), EMPTY));\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/alert/strategy/MinuteTotalNetInputMBytesAlertStrategy.java",
    "content": "package com.sohu.cache.alert.strategy;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport org.apache.commons.lang.math.NumberUtils;\n\nimport com.sohu.cache.alert.bean.AlertConfigBaseData;\nimport com.sohu.cache.entity.InstanceAlertConfig;\nimport com.sohu.cache.entity.InstanceAlertValueResult;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.redis.enums.RedisInfoEnum;\n\n/**\n * 分钟输入网络流量\n * @author leifu\n * @Date 2017年6月16日\n * @Time 下午2:34:10\n */\npublic class MinuteTotalNetInputMBytesAlertStrategy extends AlertConfigStrategy {\n    @Override\n    public List<InstanceAlertValueResult> checkConfig(InstanceAlertConfig instanceAlertConfig, AlertConfigBaseData alertConfigBaseData) {\n        Object totalNetInputBytesObject = getValueFromDiffInfo(alertConfigBaseData.getStandardStats(), RedisInfoEnum.total_net_input_bytes.getValue());\n        if (totalNetInputBytesObject == null) {\n            return null;\n        }\n        // 关系比对\n        long totalNetInputBytes = NumberUtils.toLong(totalNetInputBytesObject.toString()) ;\n        totalNetInputBytes = changeByteToMB(totalNetInputBytes);\n        boolean compareRight = isCompareLongRight(instanceAlertConfig, totalNetInputBytes);\n        if (compareRight) {\n            return null;\n        }\n        InstanceInfo instanceInfo = alertConfigBaseData.getInstanceInfo();\n        return Arrays.asList(new InstanceAlertValueResult(instanceAlertConfig, instanceInfo, String.valueOf(totalNetInputBytes),\n                instanceInfo.getAppId(), MB_STRING));\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/alert/strategy/MinuteTotalNetOutputMBytesAlertStrategy.java",
    "content": "package com.sohu.cache.alert.strategy;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport org.apache.commons.lang.math.NumberUtils;\n\nimport com.sohu.cache.alert.bean.AlertConfigBaseData;\nimport com.sohu.cache.entity.InstanceAlertConfig;\nimport com.sohu.cache.entity.InstanceAlertValueResult;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.redis.enums.RedisInfoEnum;\n\n/**\n * 分钟输出网络流量\n * @author leifu\n * @Date 2017年6月16日\n * @Time 下午2:34:10\n */\npublic class MinuteTotalNetOutputMBytesAlertStrategy extends AlertConfigStrategy {\n    @Override\n    public List<InstanceAlertValueResult> checkConfig(InstanceAlertConfig instanceAlertConfig, AlertConfigBaseData alertConfigBaseData) {\n        Object totalNetOutputBytesObject = getValueFromDiffInfo(alertConfigBaseData.getStandardStats(), RedisInfoEnum.total_net_output_bytes.getValue());\n        if (totalNetOutputBytesObject == null) {\n            return null;\n        }\n        // 关系比对\n        long totalNetOutputBytes = NumberUtils.toLong(totalNetOutputBytesObject.toString());\n        totalNetOutputBytes = changeByteToMB(totalNetOutputBytes);\n        boolean compareRight = isCompareLongRight(instanceAlertConfig, totalNetOutputBytes);\n        if (compareRight) {\n            return null;\n        }\n        InstanceInfo instanceInfo = alertConfigBaseData.getInstanceInfo();\n        return Arrays.asList(new InstanceAlertValueResult(instanceAlertConfig, instanceInfo, String.valueOf(totalNetOutputBytes),\n                instanceInfo.getAppId(), MB_STRING));\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/alert/strategy/RdbLastBgsaveStatusAlertStrategy.java",
    "content": "package com.sohu.cache.alert.strategy;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport com.sohu.cache.alert.bean.AlertConfigBaseData;\nimport com.sohu.cache.entity.InstanceAlertConfig;\nimport com.sohu.cache.entity.InstanceAlertValueResult;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.redis.enums.RedisInfoEnum;\n\n/**\n * RDB最近一次bgsave的执行状态\n * \n * @author leifu\n * @Date 2017年6月16日\n * @Time 下午2:34:10\n */\npublic class RdbLastBgsaveStatusAlertStrategy extends AlertConfigStrategy {\n    @Override\n    public List<InstanceAlertValueResult> checkConfig(InstanceAlertConfig instanceAlertConfig, AlertConfigBaseData alertConfigBaseData) {\n        Object object = getValueFromRedisInfo(alertConfigBaseData.getStandardStats(), RedisInfoEnum.rdb_last_bgsave_status.getValue());\n        if (object == null) {\n            return null;\n        }\n        // 关系比对\n        String rdbLastBgsaveStatus = object.toString();\n        boolean compareRight = isCompareStringRight(instanceAlertConfig, rdbLastBgsaveStatus);\n        if (compareRight) {\n            return null;\n        }\n        InstanceInfo instanceInfo = alertConfigBaseData.getInstanceInfo();\n        return Arrays.asList(new InstanceAlertValueResult(instanceAlertConfig, instanceInfo, String.valueOf(rdbLastBgsaveStatus),\n                instanceInfo.getAppId(), EMPTY));\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/app/AliasesResourceSqlSessionFactoryBean.java",
    "content": "package com.sohu.cache.app;\n\nimport org.apache.ibatis.logging.Log;\nimport org.apache.ibatis.logging.LogFactory;\nimport org.mybatis.spring.SqlSessionFactoryBean;\nimport org.springframework.core.io.ClassPathResource;\nimport org.springframework.core.io.FileSystemResource;\nimport org.springframework.core.io.Resource;\nimport org.springframework.util.ClassUtils;\n\nimport java.util.ArrayList;\n\n/**\n * Created by zhangyijun on 15/10/28.\n */\npublic class AliasesResourceSqlSessionFactoryBean extends SqlSessionFactoryBean {\n    private static final Log LOGGER = LogFactory.getLog(SqlSessionFactoryBean.class);\n\n    private String packages;\n\n    public void setTypeAliasesPackage(String packages) {\n        this.packages = packages;\n    }\n\n    public void setTypeAliasesClassResources(Resource[] resources) {\n        ArrayList<Class<?>> classList = new ArrayList<Class<?>>();\n        for (int i = 0; i < resources.length; i++) {\n            Resource resource = resources[i];\n            try {\n                String className;\n                if (resource instanceof ClassPathResource) {\n                    String path = ((ClassPathResource) resource).getPath();\n                    className = getClassNameByPath(path);\n                } else if (resource instanceof FileSystemResource) {\n                    String path = ((FileSystemResource) resource).getPath();\n                    className = getClassNameByPath(path);\n                } else {\n                    throw new RuntimeException(\"resources is unsupported\");\n                }\n                className = packages + className;\n                Class<?> clazz = ClassUtils.resolveClassName(className, Thread.currentThread().getContextClassLoader());\n                classList.add(clazz);\n            } catch (Exception e) {\n                LOGGER.error(e.getMessage(),e);\n            }\n        }\n        this.setTypeAliases(classList.toArray(new Class[0]));\n    }\n\n    public String getClassNameByPath(String path) {\n        String className = path.substring(path.lastIndexOf('/'), path.length());\n        className = className.replace(\".class\", \"\").replace('/', '.');\n        return className;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/app/ApplicationStarter.java",
    "content": "package com.sohu.cache.app;\n\nimport org.springframework.boot.Banner;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.context.annotation.ImportResource;\n\n/**\n * Created by zhangyijun on 15/10/26.\n */\n@SpringBootApplication\n@ImportResource(\"classpath:spring/spring.xml\")\npublic class ApplicationStarter {\n\n    public static void main(String[] args) {\n        SpringApplication app = new SpringApplication(ApplicationStarter.class);\n        app.setAdditionalProfiles();\n        app.setBannerMode(Banner.Mode.LOG);\n        app.run(args);\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/app/JvmConfiger.java",
    "content": "package com.sohu.cache.app;\n\nimport java.net.*;\nimport java.util.ArrayList;\nimport java.util.Enumeration;\nimport java.util.ResourceBundle;\n\n/**\n * Created by zhangyijun on 15/11/2.\n */\npublic class JvmConfiger {\n    public final static ResourceBundle RESOURCE = ResourceBundle.getBundle(\"application\");\n\n\n    public static String getJvmConfig() {\n        StringBuilder buffer = new StringBuilder();\n        append(buffer, RESOURCE, \"jvm.mem\");\n        append(buffer, RESOURCE, \"jvm.log\");\n        append(buffer, RESOURCE, \"jvm.gc\");\n        append(buffer, RESOURCE, \"jvm.others\");\n        append(buffer, RESOURCE, \"jvm.args\");\n        return buffer.toString();\n    }\n\n    public static String getRun() {\n        StringBuilder buffer = new StringBuilder();\n        buffer.append(\"nohup java \");\n        buffer.append(String.format(\"`java -jar %s -jvm`\",getPackageName()));\n        buffer.append(\" -jar \");\n        buffer.append(getPackageName());\n        buffer.append(\" > \");\n        buffer.append(\"./console.log\");\n        buffer.append(\" 2>&1 &\");\n        return buffer.toString();\n    }\n\n    private static String getPackageName(){\n        return getAppConfig(\"project.name\") + \".\" + getAppConfig(\"project.package\");\n    }\n\n    private static StringBuilder append(StringBuilder buffer, ResourceBundle resource, String key) {\n        if (resource.containsKey(key)) {\n            String value = resource.getString(key);\n            if (value.contains(\"hostname=%s\")) {\n                value = String.format(value, getLocalAddress());\n            }\n            return buffer.append(\" \" + value);\n        }\n        return buffer;\n    }\n\n    public static String getAppConfig(String key) {\n        if (RESOURCE.containsKey(key)) {\n            return RESOURCE.getString(key);\n        }\n        return null;\n    }\n\n    public static String getLocalAddress() {\n        try {\n            // Traversal Network interface to get the first non-loopback and non-private address\n            Enumeration<NetworkInterface> enumeration = NetworkInterface.getNetworkInterfaces();\n            ArrayList<String> ipv4Result = new ArrayList<String>();\n            ArrayList<String> ipv6Result = new ArrayList<String>();\n            while (enumeration.hasMoreElements()) {\n                final NetworkInterface networkInterface = enumeration.nextElement();\n                final Enumeration<InetAddress> en = networkInterface.getInetAddresses();\n                while (en.hasMoreElements()) {\n                    final InetAddress address = en.nextElement();\n                    if (!address.isLoopbackAddress()) {\n                        if (address instanceof Inet6Address) {\n                            ipv6Result.add(normalizeHostAddress(address));\n                        } else {\n                            ipv4Result.add(normalizeHostAddress(address));\n                        }\n                    }\n                }\n            }\n\n            // prefer ipv4\n            if (!ipv4Result.isEmpty()) {\n                for (String ip : ipv4Result) {\n                    if (ip.startsWith(\"127.0\") || ip.startsWith(\"192.168\")) {\n                        continue;\n                    }\n\n                    return ip;\n                }\n\n                return ipv4Result.get(ipv4Result.size() - 1);\n            } else if (!ipv6Result.isEmpty()) {\n                return ipv6Result.get(0);\n            }\n            //If failed to find,fall back to localhost\n            final InetAddress localHost = InetAddress.getLocalHost();\n            return normalizeHostAddress(localHost);\n        } catch (SocketException e) {\n            e.printStackTrace();\n        } catch (UnknownHostException e) {\n            e.printStackTrace();\n        }\n\n        return null;\n    }\n\n    public static String normalizeHostAddress(final InetAddress localHost) {\n        if (localHost instanceof Inet6Address) {\n            return \"[\" + localHost.getHostAddress() + \"]\";\n        } else {\n            return localHost.getHostAddress();\n        }\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/async/AsyncService.java",
    "content": "package com.sohu.cache.async;\n\nimport java.util.concurrent.Callable;\nimport java.util.concurrent.Future;\nimport java.util.concurrent.ThreadPoolExecutor;\n\n/**\n * 异步服务类\n * Created by yijunzhang on 14-6-18.\n */\npublic interface AsyncService {\n\n    /**\n     * 提交任务\n     *\n     * @param callable\n     * @return 返回是否提交成功\n     */\n    public boolean submitFuture(KeyCallable<?> callable);\n\n    /**\n     * 提交任务\n     *\n     * @param threadPoolKey\n     * @param callable\n     * @return 返回是否提交成功\n     */\n    public boolean submitFuture(String threadPoolKey, KeyCallable<?> callable);\n\n    /**\n     * 提交任务\n     *\n     * @param callable\n     * @return 返回成功结果\n     */\n    public Future<?> submitFuture(Callable<?> callable);\n\n    /**\n     * 装配key对应的线程池\n     *\n     * @param threadPoolKey\n     * @param threadPool\n     */\n    public void assemblePool(String threadPoolKey, ThreadPoolExecutor threadPool);\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/async/AsyncThreadPoolFactory.java",
    "content": "package com.sohu.cache.async;\n\nimport java.util.concurrent.LinkedBlockingQueue;\nimport java.util.concurrent.SynchronousQueue;\nimport java.util.concurrent.ThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\n\nimport com.sohu.cache.client.service.impl.ClientReportDataServiceImpl;\nimport com.sohu.cache.redis.impl.RedisCenterImpl;\n\n/**\n * 异步线程池 Created by yijunzhang on 14-7-10.\n */\npublic class AsyncThreadPoolFactory {\n\n    public static final ThreadPoolExecutor CLIENT_REPORT_THREAD_POOL =\n            new ThreadPoolExecutor(100, 100, 0L, TimeUnit.MILLISECONDS,\n                    new SynchronousQueue<Runnable>(), new NamedThreadFactory(\n                            ClientReportDataServiceImpl.CLIENT_REPORT_POOL, true));\n    \n    \n    public static final ThreadPoolExecutor REDIS_SLOWLOG_THREAD_POOL =\n            new ThreadPoolExecutor(30, 30, 0L, TimeUnit.MILLISECONDS,\n                    new SynchronousQueue<Runnable>(), new NamedThreadFactory(\n                            RedisCenterImpl.REDIS_SLOWLOG_POOL, true));\n    \n    public static final String MACHINE_POOL =\"machine-pool\";\n    public static final ThreadPoolExecutor MACHINE_THREAD_POOL =\n            new ThreadPoolExecutor(100, 100, 0L, TimeUnit.MILLISECONDS,\n                    new LinkedBlockingQueue<Runnable>(1000), new NamedThreadFactory(\n                    \t\tMACHINE_POOL, true));\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/async/KeyCallable.java",
    "content": "package com.sohu.cache.async;\n\nimport java.util.concurrent.Callable;\n\n/**\n * Created by yijunzhang on 14-6-18.\n */\npublic abstract class KeyCallable<V> implements Callable<V> {\n    private final String key;\n\n    private volatile boolean cancelled = false;\n\n    public KeyCallable(String key) {\n        this.key = key;\n    }\n\n    public abstract V execute();\n\n    @Override\n    public V call() throws Exception {\n        if (!cancelled) {\n            V v =  execute();\n            return v;\n        }\n        return null;\n    }\n\n    public void cancel() {\n        this.cancelled = true;\n    }\n\n    public String getKey() {\n        return key;\n    }\n\n    public boolean isCancelled() {\n        return cancelled;\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/async/KeyFuture.java",
    "content": "package com.sohu.cache.async;\n\nimport java.util.concurrent.Future;\n\n/**\n * Created by yijunzhang on 15-1-20.\n */\npublic class KeyFuture<V> {\n    private final String key;\n    private final Future<V> future;\n\n    public KeyFuture(String key, Future<V> future) {\n        this.key = key;\n        this.future = future;\n    }\n\n    public String getKey() {\n        return key;\n    }\n\n    public Future<V> getFuture() {\n        return future;\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/async/NamedThreadFactory.java",
    "content": "package com.sohu.cache.async;\n\nimport java.util.concurrent.ThreadFactory;\nimport java.util.concurrent.atomic.AtomicInteger;\n\n/**\n * Created by yijunzhang on 14-6-18.\n */\npublic class NamedThreadFactory implements ThreadFactory {\n    private static final AtomicInteger POOL_SEQ = new AtomicInteger(1);\n\n    private final AtomicInteger mThreadNum = new AtomicInteger(1);\n\n    private final String mPrefix;\n\n    private final boolean mDaemo;\n\n    private final ThreadGroup mGroup;\n\n    public NamedThreadFactory() {\n        this(\"pool-\" + POOL_SEQ.getAndIncrement(), false);\n    }\n\n    public NamedThreadFactory(String prefix) {\n        this(prefix, false);\n    }\n\n    public NamedThreadFactory(String prefix, boolean daemo) {\n        mPrefix = prefix + \"-thread-\";\n        mDaemo = daemo;\n        SecurityManager s = System.getSecurityManager();\n        mGroup = (s == null) ? Thread.currentThread().getThreadGroup() : s.getThreadGroup();\n    }\n\n    public Thread newThread(Runnable runnable) {\n        String name = mPrefix + mThreadNum.getAndIncrement();\n        Thread ret = new Thread(mGroup, runnable, name, 0);\n        ret.setDaemon(mDaemo);\n        return ret;\n    }\n\n    public ThreadGroup getThreadGroup() {\n        return mGroup;\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/async/impl/AsyncServiceImpl.java",
    "content": "package com.sohu.cache.async.impl;\n\n\nimport com.sohu.cache.async.AsyncService;\nimport com.sohu.cache.async.KeyCallable;\nimport com.sohu.cache.async.KeyFuture;\nimport com.sohu.cache.async.NamedThreadFactory;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.concurrent.*;\n\n/**\n * Created by yijunzhang on 14-6-18.\n */\npublic class AsyncServiceImpl implements AsyncService {\n    private final Logger logger = LoggerFactory.getLogger(this.getClass());\n\n    private final int WARNING_TIMEOUT = 2000;\n\n    private final int INTERRUPT_TIMEOUT = 10000;\n\n    private final String DEFAULT_THREAD_POOL = \"default_thread_pool\";\n\n    private final ExecutorService defaultThreadPool;\n\n    private final ThreadPoolExecutor observeFuturePool;\n\n    public ConcurrentMap<String, ExecutorService> threadPoolMap;\n\n    private final BlockingQueue<KeyFuture<?>> futureQueue;\n\n    public AsyncServiceImpl() {\n        defaultThreadPool = new ThreadPoolExecutor(256, 256,\n                0L, TimeUnit.MILLISECONDS,\n                new SynchronousQueue<Runnable>(),\n                new NamedThreadFactory(\"async\", true));\n\n        observeFuturePool = new ThreadPoolExecutor(3, 3,\n                0L, TimeUnit.MILLISECONDS,\n                new SynchronousQueue<Runnable>(),\n                new NamedThreadFactory(\"future-observe\", true));\n        threadPoolMap = new ConcurrentSkipListMap<String, ExecutorService>();\n        futureQueue = new LinkedBlockingQueue<KeyFuture<?>>();\n\n        threadPoolMap.put(DEFAULT_THREAD_POOL, defaultThreadPool);\n        startObserveFuture();\n    }\n\n    private final Runnable observeTask = new Runnable() {\n        @Override\n        public void run() {\n            while (true) {\n                try {\n                    KeyFuture<?> keyFuture = futureQueue.take();\n                    String key = keyFuture.getKey();\n                    Future<?> future = keyFuture.getFuture();\n                    try {\n                        long begin = System.currentTimeMillis();\n                        future.get(INTERRUPT_TIMEOUT, TimeUnit.MILLISECONDS);\n                        long costTime = System.currentTimeMillis() - begin;\n                        if (costTime >= WARNING_TIMEOUT) {\n                            logger.warn(\"WARNING:future={} costTime={}\", key, costTime);\n                        } else {\n                            logger.info(\"future={} costTime={}\", key, costTime);\n                        }\n                    } catch (TimeoutException te) {\n                        logger.error(\"ERROR:Timeout:future={},costTime={}\", key, INTERRUPT_TIMEOUT);\n                    } catch (Exception e) {\n                        logger.error(e.getMessage(), e);\n                    }\n                } catch (Exception e) {\n                    logger.error(e.getMessage(), e);\n                }\n            }\n        }\n    };\n\n    private void startObserveFuture() {\n        observeFuturePool.execute(observeTask);\n        observeFuturePool.execute(observeTask);\n    }\n\n    @Override\n    public boolean submitFuture(KeyCallable<?> callable) {\n        return submitFuture(DEFAULT_THREAD_POOL, callable);\n    }\n\n    @Override\n    public boolean submitFuture(String threadPoolKey, KeyCallable<?> callable) {\n        try {\n            Future<?> future = getExecutorService(threadPoolKey).submit(callable);\n            //忽略queue溢出\n            futureQueue.put(new KeyFuture(callable.getKey(), future));\n            return true;\n        } catch (Exception e) {\n            logger.error(e.getMessage() + callable.getKey(), e);\n            return false;\n        }\n    }\n\n    @Override\n    public Future<?> submitFuture(Callable<?> callable) {\n        try {\n            Future<?> future = defaultThreadPool.submit(callable);\n            //忽略queue溢出\n            futureQueue.put(new KeyFuture(callable.getClass().getName(), future));\n            return future;\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return null;\n        }\n    }\n\n    private ExecutorService getExecutorService(String key) {\n        return threadPoolMap.get(key);\n    }\n\n    @Override\n    public void assemblePool(String threadPoolKey, ThreadPoolExecutor threadPool) {\n        ExecutorService executorService = threadPoolMap.putIfAbsent(threadPoolKey, threadPool);\n        if (executorService != null) {\n            logger.error(\"{} is assembled\", threadPoolKey);\n        }\n    }\n\n    public void destory() {\n        for (ExecutorService executorService : threadPoolMap.values()) {\n            if (!executorService.isShutdown()) {\n                executorService.shutdown();\n            }\n        }\n        threadPoolMap.clear();\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/client/heartbeat/RedisClientController.java",
    "content": "package com.sohu.cache.client.heartbeat;\n\nimport com.sohu.cache.client.service.ClientVersionService;\nimport com.sohu.cache.constant.ClientStatusEnum;\nimport com.sohu.cache.dao.AppDao;\nimport com.sohu.cache.dao.InstanceDao;\nimport com.sohu.cache.entity.AppDesc;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.util.ConstUtils;\nimport com.sohu.cache.util.ObjectConvert;\nimport com.sohu.cache.web.util.IpUtil;\nimport com.google.common.collect.Lists;\n\nimport org.apache.commons.lang.StringUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestMapping;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport javax.annotation.Resource;\nimport javax.servlet.http.HttpServletRequest;\n\n/**\n * redis 客户端连接类\n */\n@Controller\n@RequestMapping(value = \"/cache/client\")\npublic class RedisClientController {\n    private final Logger logger = LoggerFactory.getLogger(RedisClientController.class);\n\n    @Resource\n    private AppDao appDao;\n\n    @Resource\n    private InstanceDao instanceDao;\n    \n    @Resource(name = \"clientVersionService\")\n    private ClientVersionService clientVersionService;\n\n    \n    /**\n     * 通过appId返回RedisCluster实例信息\n     *\n     * @param appId\n     */\n    @RequestMapping(value = \"/redis/cluster/{appId}.json\")\n    public void getClusterByAppIdAndKey(HttpServletRequest request, @PathVariable long appId, Model model) {\n        if (!handleRedisApp(appId, request, model, ConstUtils.CACHE_TYPE_REDIS_CLUSTER, false)) {\n            return;\n        }\n        getRedisClusterInfo(request, appId, model);\n    }\n    \n    /**\n     * 通过appId返回RedisCluster实例信息(要求有appkey)\n     *\n     * @param appId\n     */\n    @RequestMapping(value = \"/redis/cluster/safe/{appId}.json\")\n    public void getClusterAppById(HttpServletRequest request, @PathVariable long appId, Model model) {\n        if (!handleRedisApp(appId, request, model, ConstUtils.CACHE_TYPE_REDIS_CLUSTER, true)) {\n            return;\n        }\n        getRedisClusterInfo(request, appId, model);\n        \n    }\n\n    private void getRedisClusterInfo(HttpServletRequest request, long appId, Model model) {\n        String clientVersion = request.getParameter(\"clientVersion\");\n        if (!checkClientVersion(appId, clientVersion, model)) {\n            return;\n        }\n\n        List<InstanceInfo> instanceList = instanceDao.getInstListByAppId(appId);\n        if (instanceList == null || instanceList.isEmpty()) {\n            model.addAttribute(\"status\", ClientStatusEnum.ERROR.getStatus());\n            model.addAttribute(\"message\", \"ERROR: appId:\" + appId + \"实例集合为空 \");\n            return;\n        }\n        String shardsInfo = ObjectConvert.assembleInstance(instanceList);\n        if (StringUtils.isBlank(shardsInfo)) {\n            model.addAttribute(\"status\", ClientStatusEnum.ERROR.getStatus());\n            model.addAttribute(\"message\", \"ERROR: appId:\" + appId + \"shardsInfo为空 \");\n            return;\n        }\n        int shardNum = shardsInfo.split(\" \").length;\n        model.addAttribute(\"appId\", appId);\n        model.addAttribute(\"shardNum\", shardNum);\n        model.addAttribute(\"shardInfo\", shardsInfo);\n        AppDesc appDesc = appDao.getAppDescById(appId);\n        String password = appDesc.getPassword();\n        if (StringUtils.isNotBlank(password)) {\n            model.addAttribute(\"password\", appDesc.getPassword());\n        }\n        //保存版本信息\n        try {\n            clientVersionService.saveOrUpdateClientVersion(appId, IpUtil.getIpAddr(request), clientVersion);\n        } catch (Exception e) {\n            logger.error(\"redisCluster heart error:\" + e.getMessage(), e);\n        }\n    }\n\n    /**\n     * 通过appId返回RedisSentinel实例信息\n     *\n     * @param appId\n     */\n    @RequestMapping(value = \"/redis/sentinel/{appId}.json\")\n    public void getSentinelAppById(HttpServletRequest request, @PathVariable long appId, Model model) {\n        if (!handleRedisApp(appId, request, model, ConstUtils.CACHE_REDIS_SENTINEL, false)) {\n            return;\n        }\n        getRedisSentinelInfo(request, appId, model);\n    }\n    \n    \n    /**\n     * 通过appId返回RedisSentinel实例信息(要求有appkey)\n     *\n     * @param appId\n     */\n    @RequestMapping(value = \"/redis/sentinel/safe/{appId}.json\")\n    public void getSentinelByAppIdAndKey(HttpServletRequest request, @PathVariable long appId, Model model) {\n        if (!handleRedisApp(appId, request, model, ConstUtils.CACHE_REDIS_SENTINEL, true)) {\n            return;\n        }\n        getRedisSentinelInfo(request, appId, model);\n    }\n\n    private void getRedisSentinelInfo(HttpServletRequest request, long appId, Model model) {\n        String clientVersion = request.getParameter(\"clientVersion\");\n        if (!checkClientVersion(appId, clientVersion, model)) {\n            return;\n        }\n\n        List<InstanceInfo> instanceList = instanceDao.getInstListByAppId(appId);\n        if (instanceList == null || instanceList.isEmpty()) {\n            model.addAttribute(\"status\", ClientStatusEnum.ERROR.getStatus());\n            model.addAttribute(\"message\", \"appId: \" + appId + \" 实例集合为空 \");\n            return;\n        }\n        String masterName = null;\n        List<String> sentinelList = new ArrayList<String>();\n        for (InstanceInfo instance : instanceList) {\n            if (instance.isOffline()) {\n                continue;\n            }\n            if (instance.getType() == ConstUtils.CACHE_REDIS_SENTINEL\n                    && masterName == null\n                    && StringUtils.isNotBlank(instance.getCmd())) {\n                masterName = instance.getCmd();\n            }\n            if (instance.getType() == ConstUtils.CACHE_REDIS_SENTINEL) {\n                sentinelList.add(instance.getIp() + \":\" + instance.getPort());\n            }\n        }\n        String sentinels = StringUtils.join(sentinelList, \" \");\n        model.addAttribute(\"sentinels\", sentinels);\n        model.addAttribute(\"masterName\", masterName);\n        model.addAttribute(\"appId\", appId);\n        model.addAttribute(\"status\", ClientStatusEnum.GOOD.getStatus());\n        AppDesc appDesc = appDao.getAppDescById(appId);\n        String password = appDesc.getPassword();\n        if (StringUtils.isNotBlank(password)) {\n            model.addAttribute(\"password\", appDesc.getPassword());\n        }\n        \n        //保存版本信息\n        try {\n            clientVersionService.saveOrUpdateClientVersion(appId, IpUtil.getIpAddr(request), clientVersion);\n        } catch (Exception e) {\n            logger.error(\"redisSentinel heart error:\" + e.getMessage(), e);\n        }\n    }\n\n    /**\n     * 通过appId返回RedisStandalone实例信息\n     *\n     * @param appId\n     */\n    @RequestMapping(value = \"/redis/standalone/{appId}.json\")\n    public void getStandaloneAppById(HttpServletRequest request, @PathVariable long appId, Model model) {\n        if (!handleRedisApp(appId, request, model, ConstUtils.CACHE_REDIS_STANDALONE, false)) {\n            return;\n        }\n        getRedisStandaloneInfo(request, appId, model);\n        \n    }\n    \n    /**\n     * 通过appId返回RedisStandalone实例信息\n     *\n     * @param appId\n     */\n    @RequestMapping(value = \"/redis/standalone/safe/{appId}.json\")\n    public void getStandaloneByAppIdAndKey(HttpServletRequest request, @PathVariable long appId, Model model) {\n        if (!handleRedisApp(appId, request, model, ConstUtils.CACHE_REDIS_STANDALONE, true)) {\n            return;\n        }\n        getRedisStandaloneInfo(request, appId, model);\n        \n    }\n\n    private void getRedisStandaloneInfo(HttpServletRequest request, long appId, Model model) {\n        String clientVersion = request.getParameter(\"clientVersion\");\n        if (!checkClientVersion(appId, clientVersion, model)) {\n            return;\n        }\n\n        List<InstanceInfo> instanceList = instanceDao.getInstListByAppId(appId);\n        String standalone = null;\n        for (InstanceInfo instanceInfo : instanceList) {\n            if (instanceInfo.isOffline()) {\n                continue;\n            }\n            standalone = instanceInfo.getIp() + \":\" + instanceInfo.getPort();\n        }\n        model.addAttribute(\"standalone\", standalone);\n        model.addAttribute(\"status\", ClientStatusEnum.GOOD.getStatus());\n        AppDesc appDesc = appDao.getAppDescById(appId);\n        String password = appDesc.getPassword();\n        if (StringUtils.isNotBlank(password)) {\n            model.addAttribute(\"password\", appDesc.getPassword());\n        }\n        \n        //保存版本信息\n        try {\n            clientVersionService.saveOrUpdateClientVersion(appId, IpUtil.getIpAddr(request), clientVersion);\n        } catch (Exception e) {\n            logger.error(\"redisStandalone heart error:\" + e.getMessage(), e);\n        }\n    }\n    \n    /**\n     * 检查客户端相关参数\n     * @param appId 应用id\n     * @param request\n     * @param model\n     * @param type 应用类型\n     * @param isCheckAppKey 是否检测appKey\n     * @return\n     */\n    private boolean handleRedisApp(long appId, HttpServletRequest request, Model model, int type, boolean isCheckAppKey) {\n        AppDesc appDesc = appDao.getAppDescById(appId);\n\n        if (appDesc == null) {\n            model.addAttribute(\"status\", ClientStatusEnum.ERROR.getStatus());\n            model.addAttribute(\"message\", String.format(\"appId:%s 不存在\", appId));\n            return false;\n        } else if (appDesc.getType() != type) {\n            model.addAttribute(\"status\", ClientStatusEnum.ERROR.getStatus());\n            model.addAttribute(\"message\", String.format(\"appId:%s 类型不符,期望类型:%s,实际类型%s,请联系管理员!\", appId, type, appDesc.getType()));\n            return false;\n        } else if (isCheckAppKey) {\n            String appKey = request.getParameter(\"appKey\");\n            if (StringUtils.isBlank(appKey)) {\n                model.addAttribute(\"status\", ClientStatusEnum.ERROR.getStatus());\n                model.addAttribute(\"message\", String.format(\"appId=%s,appKey参数为空\", appId));\n                return false;\n            }\n            if (!appKey.equals(appDesc.getAppKey())) {\n                model.addAttribute(\"status\", ClientStatusEnum.ERROR.getStatus());\n                model.addAttribute(\"message\", String.format(\"appId=%s,appKey:%s错误,与服务端不匹配\", appId, appKey));\n                return false;\n            }\n        }\n        return true;\n    }\n\n    private boolean checkClientVersion(long appId, String clientVersion, Model model) {\n        /** 检查客户端的版本 **/\n        List<String> goodVersions = Lists.newArrayList(ConstUtils.GOOD_CLIENT_VERSIONS.split(ConstUtils.COMMA));\n        List<String> warnVersions = Lists.newArrayList(ConstUtils.WARN_CLIENT_VERSIONS.split(ConstUtils.COMMA));\n\n        boolean versionOk = true;\n\n        if (goodVersions.contains(clientVersion)) {\n            model.addAttribute(\"status\", ClientStatusEnum.GOOD.getStatus());\n            model.addAttribute(\"message\", \"appId:\" + appId + \" client is up to date, Cheers!\");\n        } else if (warnVersions.contains(clientVersion)) {\n            model.addAttribute(\"status\", ClientStatusEnum.WARN.getStatus());\n            model.addAttribute(\"message\", \"WARN: client is NOT the newest, please update!\");\n        } else {\n            model.addAttribute(\"status\", ClientStatusEnum.ERROR.getStatus());\n            model.addAttribute(\"message\", \"ERROR: client is TOO old or NOT recognized, please update NOW!\");\n            versionOk = false;\n        }\n        return versionOk;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/client/heartbeat/RedisClientReportDataController.java",
    "content": "package com.sohu.cache.client.heartbeat;\n\nimport java.util.List;\n\nimport javax.annotation.Resource;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\nimport org.apache.commons.lang.StringUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\n\nimport com.google.common.collect.Lists;\nimport com.sohu.cache.client.service.ClientReportDataService;\nimport com.sohu.cache.constant.ClientStatusEnum;\nimport com.sohu.cache.util.ConstUtils;\nimport com.sohu.cache.util.JsonUtil;\nimport com.sohu.cache.web.service.AppService;\nimport com.sohu.cache.web.util.IpUtil;\nimport com.sohu.tv.jedis.stat.constant.ClientReportConstant;\nimport com.sohu.tv.jedis.stat.model.ClientReportBean;\n\n/**\n * cachecloud客户端上报数据接口\n * \n * @author leifu\n * @Date 2015年1月16日\n * @Time 下午2:10:25\n */\n@Controller\n@RequestMapping(value = \"/cachecloud/client\")\npublic class RedisClientReportDataController {\n    private final Logger logger = LoggerFactory.getLogger(RedisClientReportDataController.class);\n\n    @Resource(name = \"appService\")\n    private AppService appService;\n\n    @Resource(name = \"clientReportDataService\")\n    private ClientReportDataService clientReportDataService;\n\n    /**\n     * 上报客户端上传数据\n     * \n     * @param appId\n     * @param model\n     */\n    @RequestMapping(value = \"/reportData.json\" , method = RequestMethod.POST)\n    public void reportData(HttpServletRequest request, HttpServletResponse response, Model model) {\n        \n        // 1. 验证版本的正确性\n        String clientVersion = request.getParameter(ClientReportConstant.CLIENT_VERSION);\n        if (!checkClientVersion(clientVersion)) {\n            return;\n        }\n\n        // 2. 验证json的正确性\n        String json = request.getParameter(ClientReportConstant.JSON_PARAM);\n        ClientReportBean clientReportBean = checkReportJson(json);\n        if (clientReportBean == null) {\n            logger.error(\"reportWrong json: {}\", json);\n            return;\n        }\n                \n        // 3.使用访问web的ip作为客户端最终的ip\n        String clientIp = IpUtil.getIpAddr(request);\n        if(StringUtils.isNotBlank(clientIp)){\n            clientReportBean.setClientIp(clientIp);\n        }\n        \n    \t// 4. 根据类型处理数据\n        boolean result = clientReportDataService.deal(clientReportBean);\n        if (!result) {\n            logger.error(\"ClientReportDataService deal fail, clientReportBean is {}\", clientReportBean);\n        }\n\n    }\n    \n    /**\n     * 检验json正确性，返回JavaBean\n     * \n     * @param json\n     * @return\n     */\n    private ClientReportBean checkReportJson(String json) {\n        if (StringUtils.isNotBlank(json)) {\n            try {\n                return JsonUtil.fromJson(json, ClientReportBean.class);\n            } catch (Exception e) {\n                logger.error(e.getMessage(), e);\n            }\n        }\n        return null;\n    }\n\n    /**\n     * 检查客户端的版本\n     * \n     * @param clientVersion\n     * @return\n     */\n    private boolean checkClientVersion(String clientVersion) {\n        if (StringUtils.isBlank(clientVersion)) {\n            return false;\n        }\n        // 获取合格的客户端版本\n        List<String> goodVersions = Lists.newArrayList(ConstUtils.GOOD_CLIENT_VERSIONS.split(ConstUtils.COMMA));\n        List<String> warnVersions = Lists.newArrayList(ConstUtils.WARN_CLIENT_VERSIONS.split(ConstUtils.COMMA));\n\n        // 错误版本\n        if (goodVersions.contains(clientVersion) && warnVersions.contains(clientVersion)) {\n            logger.error(\"status: {}, message: {}\", ClientStatusEnum.ERROR.getStatus(),\n                    \"ERROR: client is TOO old or NOT recognized, please update NOW!\");\n            return false;\n        }\n        return true;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/client/service/AppInstanceClientRelationService.java",
    "content": "package com.sohu.cache.client.service;\n\nimport java.util.Date;\nimport java.util.List;\n\nimport com.sohu.cache.entity.AppClientCostTimeStat;\nimport com.sohu.cache.entity.AppInstanceClientRelation;\n\n/**\n * 应用下节点和客户端关系服务\n * \n * @author leifu\n * @Date 2016年5月3日\n * @Time 下午6:48:40\n */\npublic interface AppInstanceClientRelationService {\n\n    void batchSave(List<AppClientCostTimeStat> appClientCostTimeStatList);\n\n    List<AppInstanceClientRelation> getAppInstanceClientRelationList(Long appId, Date date);\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/client/service/ClientReportCostDistriService.java",
    "content": "package com.sohu.cache.client.service;\n\nimport java.util.List;\n\nimport com.sohu.cache.entity.AppClientCostTimeStat;\nimport com.sohu.cache.entity.AppClientCostTimeTotalStat;\nimport com.sohu.tv.jedis.stat.model.ClientReportBean;\n\n/**\n * @author leifu\n * @Date 2015年1月19日\n * @Time 上午10:02:28\n */\npublic interface ClientReportCostDistriService {\n\n    /**\n     * 获取一段时间内某个应用执行的命令列表\n     * \n     * @param appId\n     * @param startTime\n     * @param endTime\n     * @return\n     */\n    List<String> getAppDistinctCommand(Long appId, long startTime, long endTime);\n    \n\n    /**\n     * 获取一段时间内某个应用某个命令单个客户端当个实例的统计信息\n     * @param appId\n     * @param command\n     * @param instanceId\n     * @param clientIp\n     * @param startTime\n     * @param endTime\n     * @return\n     */\n    List<AppClientCostTimeStat> getAppCommandClientToInstanceStat(Long appId, String command, Long instanceId,\n            String clientIp, long startTime, long endTime);\n    \n    /**\n     * 获取一个应用一段时间内某个命令的统计信息\n     * @param appId\n     * @param command\n     * @param startTime\n     * @param endTime\n     * @return\n     */\n    List<AppClientCostTimeTotalStat> getAppClientCommandTotalStat(Long appId, String command, long startTime, long endTime);\n    \n    /**\n     * 批量保存\n     * @param clientReportBean\n     */\n    void batchSave(ClientReportBean clientReportBean);\n\n    /**\n     * 删除collectTime之前的数据\n     * @param collectTime\n     */\n    int deleteBeforeCollectTime(long collectTime);\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/client/service/ClientReportDataService.java",
    "content": "package com.sohu.cache.client.service;\n\nimport com.sohu.tv.jedis.stat.model.ClientReportBean;\n\n/**\n * cachecloud客户端上报数据处理\n * @author leifu\n * @Date 2015年1月19日\n * @Time 上午10:02:01\n */\npublic interface ClientReportDataService {\n    \n    /**\n     * 处理上报数据\n     * @param clientReportBean\n     */\n    public boolean deal(ClientReportBean clientReportBean);\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/client/service/ClientReportDataSizeService.java",
    "content": "package com.sohu.cache.client.service;\n\nimport com.sohu.tv.jedis.stat.model.ClientReportBean;\n\n/**\n * 记录客户端统计map的尺寸\n * \n * @author leifu\n * @Date 2015年7月13日\n * @Time 下午3:00:40\n */\npublic interface ClientReportDataSizeService {\n\n    void save(ClientReportBean clientReportBean);\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/client/service/ClientReportExceptionService.java",
    "content": "package com.sohu.cache.client.service;\n\nimport java.util.List;\n\nimport com.sohu.cache.entity.AppClientExceptionStat;\nimport com.sohu.cache.entity.ClientInstanceException;\nimport com.sohu.cache.web.util.Page;\nimport com.sohu.tv.jedis.stat.model.ClientReportBean;\n\n\n/**\n * 客户端上报异常记录\n * @author leifu\n * @Date 2015年1月19日\n * @Time 上午10:02:32\n */\npublic interface ClientReportExceptionService {\n    \n    /**\n     * 获取客户端异常列表\n     * @param appId 应用id\n     * @param startTime 开始收集时间\n     * @param endTime 结束收集时间\n     * @param type 异常类型(ClientExceptionType)\n     * @param clientIp 客户端ip\n     * @return\n     */\n    List<AppClientExceptionStat> getAppExceptionList(Long appId, long startTime, long endTime, int type, String clientIp, Page page);\n\n    /**\n     * 获取客户端异常个数\n     * @param appId 应用id\n     * @param startTime 开始收集时间\n     * @param endTime 结束收集时间\n     * @param type 异常类型(ClientExceptionType)\n     * @param clientIp 客户端ip\n     * @return\n     */\n    int getAppExceptionCount(Long appId, long startTime, long endTime, int type, String clientIp);\n\n    /**\n     * 大于collectTime期间各个实例的异常统计\n     * @param ip\n     * @param collectTime\n     * @return\n     */\n    List<ClientInstanceException> getInstanceExceptionStat(String ip, long collectTime);\n    \n    /**\n     * 批量保存\n     * @param clientReportBean\n     * @return\n     */\n    void batchSave(ClientReportBean clientReportBean);\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/client/service/ClientReportInstanceService.java",
    "content": "package com.sohu.cache.client.service;\n\nimport com.sohu.cache.entity.InstanceInfo;\n\n/**\n * \n * @author leifu\n * @Date 2015年1月19日\n * @Time 上午10:02:28\n */\npublic interface ClientReportInstanceService {\n    \n    /**\n     * 根据host:port获取instance信息(缓存，不要求一致性)\n     * @param host\n     * @param port\n     * @return\n     */\n    InstanceInfo getInstanceInfoByHostPort(String host, int port);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/client/service/ClientReportValueDistriService.java",
    "content": "package com.sohu.cache.client.service;\n\nimport java.util.List;\n\nimport com.sohu.cache.entity.AppClientValueDistriSimple;\nimport com.sohu.tv.jedis.stat.model.ClientReportBean;\n\n\n/**\n * 客户端值分布服务\n * @author leifu\n * @Date 2015年1月19日\n * @Time 上午10:02:37\n */\npublic interface ClientReportValueDistriService {\n    \n    /**\n     * 获取某个应用一段时间内值分布统计\n     * @param appId\n     * @param startTime\n     * @param endTime\n     * @return\n     */\n    List<AppClientValueDistriSimple> getAppValueDistriList(long appId, long startTime, long endTime);\n    \n    /**\n     * 批量保存\n     * @param clientReportBean\n     * @return\n     */\n    void batchSave(ClientReportBean clientReportBean);\n\n    /**\n     * 删除指定收集日期前的数据\n     * @param collectTime\n     * @return\n     */\n    int deleteBeforeCollectTime(long collectTime);\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/client/service/ClientVersionService.java",
    "content": "package com.sohu.cache.client.service;\n\nimport java.util.List;\n\nimport com.sohu.cache.entity.AppClientVersion;\n\n/**\n * 客户端版本信息\n * @author leifu\n * @Date 2015年2月2日\n * @Time 上午10:19:59\n */\npublic interface ClientVersionService {\n\n    /**\n     * 保存客户端版本信息\n     * @param appId\n     * @param appClientIp\n     * @param clientVersion\n     */\n    void saveOrUpdateClientVersion(long appId, String appClientIp, String clientVersion);\n    \n    /**\n     * 获取应用的所有客户端版本信息\n     * @param appId\n     * @return\n     */\n    List<AppClientVersion> getAppAllClientVersion(long appId);\n    \n    /**\n     * 获取应用的所有客户端版本信息(过滤掉版本网段 10.7 10.2 10.1)\n     * @param appId\n     * @return\n     */\n    List<AppClientVersion> getAppAllServerClientVersion(long appId);\n\n    /**\n     * 获取所有客户端版本\n     * @return\n     */\n    List<AppClientVersion> getAll(long appId);\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/client/service/impl/AppInstanceClientRelationServiceImpl.java",
    "content": "package com.sohu.cache.client.service.impl;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.List;\n\nimport org.apache.commons.collections.CollectionUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.sohu.cache.client.service.AppInstanceClientRelationService;\nimport com.sohu.cache.dao.AppInstanceClientRelationDao;\nimport com.sohu.cache.entity.AppClientCostTimeStat;\nimport com.sohu.cache.entity.AppInstanceClientRelation;\n\n/**\n * 应用下节点和客户端关系服务\n * \n * @author leifu\n * @Date 2016年5月3日\n * @Time 下午6:48:40\n */\npublic class AppInstanceClientRelationServiceImpl implements AppInstanceClientRelationService {\n\n    private Logger logger = LoggerFactory.getLogger(AppInstanceClientRelationServiceImpl.class);\n\n    private AppInstanceClientRelationDao appInstanceClientRelationDao;\n\n    @Override\n    public void batchSave(List<AppClientCostTimeStat> appClientCostTimeStatList) {\n        if (CollectionUtils.isEmpty(appClientCostTimeStatList)) {\n            return;\n        }\n        try {\n            List<AppInstanceClientRelation> appInstanceClientRelationList = new ArrayList<AppInstanceClientRelation>();\n            for (AppClientCostTimeStat appClientCostTimeStat : appClientCostTimeStatList) {\n                AppInstanceClientRelation appInstanceClientRelation = AppInstanceClientRelation.generateFromAppClientCostTimeStat(appClientCostTimeStat);\n                if (appInstanceClientRelation != null) {\n                    appInstanceClientRelationList.add(appInstanceClientRelation);\n                }\n            }\n            if (CollectionUtils.isNotEmpty(appInstanceClientRelationList)) {\n                appInstanceClientRelationDao.batchSave(appInstanceClientRelationList);\n            }\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n    }\n\n    @Override\n    public List<AppInstanceClientRelation> getAppInstanceClientRelationList(Long appId, Date date) {\n        try {\n            return appInstanceClientRelationDao.getAppInstanceClientRelationList(appId, date);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return Collections.emptyList();\n        }\n    }\n\n    public void setAppInstanceClientRelationDao(AppInstanceClientRelationDao appInstanceClientRelationDao) {\n        this.appInstanceClientRelationDao = appInstanceClientRelationDao;\n    }\n\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/client/service/impl/ClientReportCostDistriServiceImpl.java",
    "content": "package com.sohu.cache.client.service.impl;\n\nimport java.text.DecimalFormat;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\n\nimport org.apache.commons.collections.CollectionUtils;\nimport org.apache.commons.collections.MapUtils;\nimport org.apache.commons.lang.StringUtils;\nimport org.apache.commons.lang.math.NumberUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.sohu.cache.client.service.AppInstanceClientRelationService;\nimport com.sohu.cache.client.service.ClientReportCostDistriService;\nimport com.sohu.cache.client.service.ClientReportInstanceService;\nimport com.sohu.cache.dao.AppClientCostTimeStatDao;\nimport com.sohu.cache.dao.AppClientCostTimeTotalStatDao;\nimport com.sohu.cache.entity.AppClientCostTimeStat;\nimport com.sohu.cache.entity.AppClientCostTimeTotalStat;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.tv.jedis.stat.constant.ClientReportConstant;\nimport com.sohu.tv.jedis.stat.enums.ClientCollectDataTypeEnum;\nimport com.sohu.tv.jedis.stat.model.ClientReportBean;\n\n/**\n * 客户端上报耗时分布\n * \n * @author leifu\n * @Date 2015年1月19日\n * @Time 下午1:49:39\n */\npublic class ClientReportCostDistriServiceImpl implements ClientReportCostDistriService {\n\n    private final Logger logger = LoggerFactory.getLogger(ClientReportCostDistriServiceImpl.class);\n\n    /**\n     * 客户端耗时操作\n     */\n    private AppClientCostTimeStatDao appClientCostTimeStatDao;\n    \n    /**\n     * 基于应用的客户端耗时操作\n     */\n    private AppClientCostTimeTotalStatDao appClientCostTimeTotalStatDao;\n\n    /**\n     * host:port与instanceInfo简单缓存\n     */\n    private ClientReportInstanceService clientReportInstanceService;\n    \n    /**\n     * 应用下节点和客户端关系\n     */\n    private AppInstanceClientRelationService appInstanceClientRelationService;\n\n    @Override\n    public List<String> getAppDistinctCommand(Long appId, long startTime, long endTime) {\n        try {\n            return appClientCostTimeTotalStatDao.getAppDistinctCommand(appId, startTime, endTime);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return Collections.emptyList();\n        }\n    }\n    \n    @Override\n    public List<AppClientCostTimeStat> getAppCommandClientToInstanceStat(Long appId, String command, Long instanceId,\n            String clientIp, long startTime, long endTime) {\n        try {\n            return appClientCostTimeStatDao.getAppCommandClientToInstanceStat(appId, command, instanceId, clientIp,\n                    startTime, endTime);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return Collections.emptyList();\n        }\n    }\n    \n    @Override\n    public List<AppClientCostTimeTotalStat> getAppClientCommandTotalStat(Long appId, String command, long startTime,\n            long endTime) {\n        try {\n            return appClientCostTimeTotalStatDao.getAppClientCommandStat(appId, command, startTime, endTime);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return Collections.emptyList();\n        }\n    }\n    \n    @Override\n    public void batchSave(ClientReportBean clientReportBean) {\n        try {\n            // 1.client上报\n            final String clientIp = clientReportBean.getClientIp();\n            final long collectTime = clientReportBean.getCollectTime();\n            final long reportTime = clientReportBean.getReportTimeStamp();\n            final List<Map<String, Object>> datas = clientReportBean.getDatas();\n            if (datas == null || datas.isEmpty()) {\n                logger.warn(\"datas field {} is empty\", clientReportBean);\n                return;\n            }\n            \n            // 2.结果集\n            List<AppClientCostTimeStat> appClientCostTimeStatList = new ArrayList<AppClientCostTimeStat>();\n\n            // 3.解析结果\n            for (Map<String, Object> map : datas) {\n                Integer clientDataType = MapUtils.getInteger(map, ClientReportConstant.CLIENT_DATA_TYPE, -1);\n                ClientCollectDataTypeEnum clientCollectDataTypeEnum = ClientCollectDataTypeEnum.MAP.get(clientDataType);\n                if (clientCollectDataTypeEnum == null) {\n                    continue;\n                }\n                if (ClientCollectDataTypeEnum.COST_TIME_DISTRI_TYPE.equals(clientCollectDataTypeEnum)) {\n                    AppClientCostTimeStat appClientCostTimeStat = generate(clientIp, collectTime, reportTime, map);\n                    if (appClientCostTimeStat != null) {\n                        appClientCostTimeStatList.add(appClientCostTimeStat);\n                    }\n                }\n            }\n            \n            if (CollectionUtils.isNotEmpty(appClientCostTimeStatList)) {\n                // 4.批量保存\n                appClientCostTimeStatDao.batchSave(appClientCostTimeStatList);\n                // 5.合并app统计结果\n                List<AppClientCostTimeTotalStat> appClientCostTimeTotalStatList = mergeAppClientCostTimeStat(appClientCostTimeStatList);\n                if (CollectionUtils.isNotEmpty(appClientCostTimeTotalStatList)) {\n                    appClientCostTimeTotalStatDao.batchSave(appClientCostTimeTotalStatList);\n                }\n                // 6.保存应用下节点和客户端关系\n                appInstanceClientRelationService.batchSave(appClientCostTimeStatList);\n            }\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n    }\n    \n    /**\n     * 合并以app为单位的\n     * @param appClientCostTimeStatList\n     */\n    private List<AppClientCostTimeTotalStat> mergeAppClientCostTimeStat(List<AppClientCostTimeStat> appClientCostTimeStatList) {\n        // 1. merge后的结果\n        List<AppClientCostTimeTotalStat> resultList = new ArrayList<AppClientCostTimeTotalStat>();\n        \n        // 2. 以appid_command_collectTime为key，拆分appClientCostTimeStatList\n        Map<String, List<AppClientCostTimeStat>> map = new HashMap<String, List<AppClientCostTimeStat>>();\n        for (AppClientCostTimeStat appClientCostTimeStat : appClientCostTimeStatList) {\n            long appId = appClientCostTimeStat.getAppId();\n            String command = appClientCostTimeStat.getCommand();\n            long collectTime = appClientCostTimeStat.getCollectTime();\n            String key = appId + \"_\" + command + \"_\" + collectTime;\n            if (map.containsKey(key)) {\n                map.get(key).add(appClientCostTimeStat);\n            } else {\n                List<AppClientCostTimeStat> list = new ArrayList<AppClientCostTimeStat>();\n                list.add(appClientCostTimeStat);\n                map.put(key, list);\n            }\n        }\n        \n        // 3.生成结果\n        for (Entry<String, List<AppClientCostTimeStat>> entry : map.entrySet()) {\n            String key = entry.getKey();\n            String[] items = key.split(\"_\");\n            long appId = NumberUtils.toLong(items[0]);\n            String command = items[1];\n            long collectTime = NumberUtils.toLong(items[2]);\n            \n            double totalCost = 0.0;\n            long totalCount = 0;\n            int median = 0;\n            int ninetyPercentMax = 0;\n            int ninetyNinePercentMax = 0;\n            int hundredMax = 0;\n            String maxInstanceHost = \"\";\n            int maxInstancePort = 0;\n            long maxInstanceId = 0;\n            String maxClientIp = \"\";\n            double mean = 0.0;\n            for (AppClientCostTimeStat appClientCostTimeStat : entry.getValue()) {\n                AppClientCostTimeTotalStat appClientCostTimeTotalStat = AppClientCostTimeTotalStat.getFromAppClientCostTimeStat(appClientCostTimeStat);\n                totalCost += appClientCostTimeTotalStat.getTotalCost();\n                totalCount += appClientCostTimeTotalStat.getTotalCount();\n                if (appClientCostTimeTotalStat.getMedian() > median) {\n                    median = appClientCostTimeTotalStat.getMedian();\n                }\n                if (appClientCostTimeTotalStat.getNinetyPercentMax() > ninetyPercentMax) {\n                    ninetyPercentMax = appClientCostTimeTotalStat.getNinetyPercentMax();\n                }\n                if (appClientCostTimeTotalStat.getNinetyNinePercentMax() > ninetyNinePercentMax) {\n                    ninetyNinePercentMax = appClientCostTimeTotalStat.getNinetyNinePercentMax();\n                }\n                if (appClientCostTimeTotalStat.getHundredMax() > hundredMax) {\n                    hundredMax = appClientCostTimeTotalStat.getHundredMax();\n                    maxInstanceHost = appClientCostTimeTotalStat.getMaxInstanceHost();\n                    maxInstancePort = appClientCostTimeTotalStat.getMaxInstancePort();\n                    maxInstanceId = appClientCostTimeTotalStat.getMaxInstanceId();\n                    maxClientIp = appClientCostTimeTotalStat.getMaxClientIp();\n                }\n            }\n            DecimalFormat df = new DecimalFormat(\"0.00\");\n            totalCost = NumberUtils.toDouble(df.format(totalCost));\n            \n            //平均值\n            if (totalCount > 0) {\n                mean = totalCost / totalCount;\n                mean = NumberUtils.toDouble(df.format(mean));\n            }\n            \n            //添加到结果集\n            resultList.add(new AppClientCostTimeTotalStat(-1, appId, collectTime, new Date(), command,\n                    totalCount, totalCost, median, mean, ninetyPercentMax, ninetyNinePercentMax, hundredMax,\n                    maxInstanceHost, maxInstancePort, maxInstanceId, maxClientIp));\n        }\n        return resultList;\n    }\n    \n    private AppClientCostTimeStat generate(String clientIp, long collectTime, long reportTime, Map<String, Object> map) {\n        try {\n            Integer count = MapUtils.getInteger(map, ClientReportConstant.COST_COUNT, 0);\n            String command = MapUtils.getString(map, ClientReportConstant.COST_COMMAND, \"\");\n            if (StringUtils.isBlank(command)) {\n                logger.warn(\"command is empty!\");\n                return null;\n            }\n            String hostPort = MapUtils.getString(map, ClientReportConstant.COST_HOST_PORT, \"\");\n            if (StringUtils.isBlank(hostPort)) {\n                logger.warn(\"hostPort is empty\", hostPort);\n                return null;\n            }\n            int index = hostPort.indexOf(\":\");\n            if (index <= 0) {\n                logger.warn(\"hostPort {} format is wrong\", hostPort);\n                return null;\n            }\n            String host = hostPort.substring(0, index);\n            int port = NumberUtils.toInt(hostPort.substring(index + 1));\n\n            // 实例信息\n            InstanceInfo instanceInfo = clientReportInstanceService.getInstanceInfoByHostPort(host, port);\n            if (instanceInfo == null) {\n//                logger.warn(\"instanceInfo is empty, host is {}, port is {}\", host, port);\n                return null;\n            }\n            long appId = instanceInfo.getAppId();\n            // 耗时分布详情\n            double mean = MapUtils.getDouble(map, ClientReportConstant.COST_TIME_MEAN, 0.0);\n            Integer median = MapUtils.getInteger(map, ClientReportConstant.COST_TIME_MEDIAN, 0);\n            Integer ninetyPercentMax = MapUtils.getInteger(map, ClientReportConstant.COST_TIME_90_MAX, 0);\n            Integer ninetyNinePercentMax = MapUtils.getInteger(map, ClientReportConstant.COST_TIME_99_MAX, 0);\n            Integer hunredMax = MapUtils.getInteger(map, ClientReportConstant.COST_TIME_100_MAX, 0);\n\n            AppClientCostTimeStat stat = new AppClientCostTimeStat();\n            stat.setAppId(appId);\n            stat.setClientIp(clientIp);\n            stat.setReportTime(new Date(reportTime));\n            stat.setCollectTime(collectTime);\n            stat.setCreateTime(new Date());\n            stat.setCommand(command);\n            stat.setCount(count);\n            stat.setInstanceHost(host);\n            stat.setInstancePort(port);\n            stat.setMean(NumberUtils.toDouble(new DecimalFormat(\"#.00\").format(mean)));\n            stat.setMedian(median);\n            stat.setNinetyPercentMax(ninetyPercentMax);\n            stat.setNinetyNinePercentMax(ninetyNinePercentMax);\n            stat.setHundredMax(hunredMax);\n            stat.setInstanceId(instanceInfo.getId());\n\n            return stat;\n            \n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return null;\n        }\n    }\n    \n    /**\n     * 1.获取最小的id\n     * 2.获取date的id\n     * 3.按照id批量删除\n     */\n    @Override\n    public int deleteBeforeCollectTime(long collectTime) {\n        long startTime = System.currentTimeMillis();\n        int deleteCount = 0;\n        try {\n            int batchSize = 10000;\n            long minId = appClientCostTimeStatDao.getTableMinimumId();\n            long maxId = appClientCostTimeStatDao.getMinimumIdByCollectTime(collectTime);\n            if (minId > maxId) {\n                return deleteCount;\n            }\n            long startId = minId;\n            long endId = startId + batchSize;\n            while (startId < maxId) {\n                if (endId > maxId) {\n                    endId = maxId;\n                }\n                deleteCount += appClientCostTimeStatDao.deleteByIds(startId, endId);\n                startId += batchSize;\n                endId += batchSize;\n            }\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n        logger.warn(\"batch delete before collectTime {} cost time is {} ms\", collectTime, (System.currentTimeMillis() - startTime));\n        return deleteCount;\n    }\n\n    public void setAppClientCostTimeStatDao(AppClientCostTimeStatDao appClientCostTimeStatDao) {\n        this.appClientCostTimeStatDao = appClientCostTimeStatDao;\n    }\n\n    public void setClientReportInstanceService(ClientReportInstanceService clientReportInstanceService) {\n        this.clientReportInstanceService = clientReportInstanceService;\n    }\n\n    public void setAppClientCostTimeTotalStatDao(AppClientCostTimeTotalStatDao appClientCostTimeTotalStatDao) {\n        this.appClientCostTimeTotalStatDao = appClientCostTimeTotalStatDao;\n    }\n\n    public void setAppInstanceClientRelationService(AppInstanceClientRelationService appInstanceClientRelationService) {\n        this.appInstanceClientRelationService = appInstanceClientRelationService;\n    }\n\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/client/service/impl/ClientReportDataServiceImpl.java",
    "content": "package com.sohu.cache.client.service.impl;\n\nimport java.util.List;\nimport java.util.Map;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.sohu.cache.async.AsyncService;\nimport com.sohu.cache.async.AsyncThreadPoolFactory;\nimport com.sohu.cache.async.KeyCallable;\nimport com.sohu.cache.client.service.ClientReportCostDistriService;\nimport com.sohu.cache.client.service.ClientReportDataService;\nimport com.sohu.cache.client.service.ClientReportDataSizeService;\nimport com.sohu.cache.client.service.ClientReportExceptionService;\nimport com.sohu.cache.client.service.ClientReportValueDistriService;\nimport com.sohu.tv.jedis.stat.model.ClientReportBean;\n\n/**\n * cachecloud客户端数据统一处理\n * \n * @author leifu\n * @Date 2015年1月19日\n * @Time 上午10:02:01\n */\npublic class ClientReportDataServiceImpl implements ClientReportDataService {\n    public static final String CLIENT_REPORT_POOL =\"client-report-pool\";\n    \n    private AsyncService asyncService;\n    \n    private final Logger logger = LoggerFactory.getLogger(ClientReportDataServiceImpl.class);\n    \n    private ClientReportCostDistriService clientReportCostDistriService;\n    \n    private ClientReportValueDistriService clientReportValueDistriService;\n    \n    private ClientReportExceptionService clientReportExceptionService;\n    \n    private ClientReportDataSizeService clientReportDataSizeService;\n    \n    public void init() {\n        asyncService.assemblePool(getThreadPoolKey(), AsyncThreadPoolFactory.CLIENT_REPORT_THREAD_POOL);\n    }\n    \n    private String getThreadPoolKey() {\n        return CLIENT_REPORT_POOL;\n    }\n    \n    @Override\n    public boolean deal(final ClientReportBean clientReportBean) {\n        try {\n            // 上报的数据\n            final String clientIp = clientReportBean.getClientIp();\n            final List<Map<String, Object>> datas = clientReportBean.getDatas();\n            if (datas == null || datas.isEmpty()) {\n                logger.warn(\"datas field {} is empty\", clientReportBean);\n                return false;\n            }\n            String key = getThreadPoolKey() + \"_\" + clientIp;\n            asyncService.submitFuture(getThreadPoolKey(), new KeyCallable<Boolean>(key) {\n                @Override\n                public Boolean execute() {\n                    try {\n                        \n                        clientReportCostDistriService.batchSave(clientReportBean);\n                        clientReportValueDistriService.batchSave(clientReportBean);\n                        clientReportExceptionService.batchSave(clientReportBean);\n                        clientReportDataSizeService.save(clientReportBean);\n                        return true;\n                    } catch (Exception e) {\n                        logger.error(e.getMessage(), e);\n                        return false;\n                    }\n                }\n            });\n            return true;\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return false;\n        }\n    }\n\n    public void setAsyncService(AsyncService asyncService) {\n        this.asyncService = asyncService;\n    }\n\n    public void setClientReportCostDistriService(ClientReportCostDistriService clientReportCostDistriService) {\n        this.clientReportCostDistriService = clientReportCostDistriService;\n    }\n\n    public void setClientReportExceptionService(ClientReportExceptionService clientReportExceptionService) {\n        this.clientReportExceptionService = clientReportExceptionService;\n    }\n\n    public void setClientReportDataSizeService(ClientReportDataSizeService clientReportDataSizeService) {\n        this.clientReportDataSizeService = clientReportDataSizeService;\n    }\n\n    public void setClientReportValueDistriService(ClientReportValueDistriService clientReportValueDistriService) {\n        this.clientReportValueDistriService = clientReportValueDistriService;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/client/service/impl/ClientReportDataSizeServiceImpl.java",
    "content": "package com.sohu.cache.client.service.impl;\n\nimport java.util.Date;\nimport java.util.Map;\n\nimport org.apache.commons.collections.MapUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.sohu.cache.client.service.ClientReportDataSizeService;\nimport com.sohu.cache.dao.AppClientReportDataSizeDao;\nimport com.sohu.cache.entity.AppClientDataSizeStat;\nimport com.sohu.tv.jedis.stat.constant.ClientReportConstant;\nimport com.sohu.tv.jedis.stat.model.ClientReportBean;\n\n/**\n * 记录客户端统计map的尺寸\n * \n * @author leifu\n * @Date 2015年7月13日\n * @Time 下午3:00:40\n */\npublic class ClientReportDataSizeServiceImpl implements ClientReportDataSizeService {\n    \n    private Logger logger = LoggerFactory.getLogger(ClientReportDataSizeServiceImpl.class);\n\n    private AppClientReportDataSizeDao appClientReportDataSizeDao;\n    \n    @Override\n    public void save(ClientReportBean clientReportBean) {\n        try {\n            // 1.client上报\n            final String clientIp = clientReportBean.getClientIp();\n            final long collectTime = clientReportBean.getCollectTime();\n            final long reportTime = clientReportBean.getReportTimeStamp();\n            final Map<String, Object> otherInfo = clientReportBean.getOtherInfo();\n            if (otherInfo == null || otherInfo.isEmpty()) {\n                logger.warn(\"otherInfo field is empty, client ip {}\", clientIp);\n                return;\n            }\n            int costMapSize = MapUtils.getInteger(otherInfo, ClientReportConstant.COST_MAP_SIZE, 0);\n            int valueMapSize = MapUtils.getInteger(otherInfo, ClientReportConstant.VALUE_MAP_SIZE, 0);\n            int exceptionMapSize = MapUtils.getInteger(otherInfo, ClientReportConstant.EXCEPTION_MAP_SIZE, 0);\n            int collectMapSize = MapUtils.getInteger(otherInfo, ClientReportConstant.COLLECTION_MAP_SIZE, 0);\n            // 只记录大于minSize\n            int minSize = 100;\n            if (costMapSize < minSize && valueMapSize < minSize && exceptionMapSize < minSize && collectMapSize < minSize) {\n                return;\n            }\n            // 设置实体\n            AppClientDataSizeStat appClientDataSizeStat = new AppClientDataSizeStat();\n            appClientDataSizeStat.setClientIp(clientIp);\n            appClientDataSizeStat.setCollectTime(collectTime);\n            appClientDataSizeStat.setCollectMapSize(collectMapSize);\n            appClientDataSizeStat.setCostMapSize(costMapSize);\n            appClientDataSizeStat.setValueMapSize(valueMapSize);\n            appClientDataSizeStat.setExceptionMapSize(exceptionMapSize);\n            appClientDataSizeStat.setCreateTime(new Date());\n            appClientDataSizeStat.setReportTime(new Date(reportTime));\n            \n            appClientReportDataSizeDao.save(appClientDataSizeStat);\n            \n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n    }\n\n    public void setAppClientReportDataSizeDao(AppClientReportDataSizeDao appClientReportDataSizeDao) {\n        this.appClientReportDataSizeDao = appClientReportDataSizeDao;\n    }\n\n    \n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/client/service/impl/ClientReportExceptionServiceImpl.java",
    "content": "package com.sohu.cache.client.service.impl;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Map;\n\nimport org.apache.commons.collections.CollectionUtils;\nimport org.apache.commons.collections.MapUtils;\nimport org.apache.commons.lang.StringUtils;\nimport org.apache.commons.lang.math.NumberUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.sohu.cache.client.service.ClientReportExceptionService;\nimport com.sohu.cache.client.service.ClientReportInstanceService;\nimport com.sohu.cache.dao.AppClientExceptionStatDao;\nimport com.sohu.cache.dao.AppClientVersionDao;\nimport com.sohu.cache.entity.AppClientExceptionStat;\nimport com.sohu.cache.entity.AppClientVersion;\nimport com.sohu.cache.entity.ClientInstanceException;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.web.util.Page;\nimport com.sohu.tv.jedis.stat.constant.ClientReportConstant;\nimport com.sohu.tv.jedis.stat.enums.ClientCollectDataTypeEnum;\nimport com.sohu.tv.jedis.stat.enums.ClientExceptionType;\nimport com.sohu.tv.jedis.stat.model.ClientReportBean;\n\n/**\n * 客户端上报异常service\n * \n * @author leifu\n * @Date 2015年1月19日\n * @Time 上午10:02:32\n */\npublic class ClientReportExceptionServiceImpl implements ClientReportExceptionService {\n\n    private final Logger logger = LoggerFactory.getLogger(ClientReportExceptionServiceImpl.class);\n\n    /**\n     * 客户端异常操作\n     */\n    private AppClientExceptionStatDao appClientExceptionStatDao;\n\n    /**\n     * host:port与instanceInfo简单缓存\n     */\n    private ClientReportInstanceService clientReportInstanceService;\n    \n    /**\n     * 客户端ip,版本查询\n     */\n    private AppClientVersionDao appClientVersionDao;\n\n    \n\n    @Override\n    public List<AppClientExceptionStat> getAppExceptionList(Long appId, long startTime, long endTime, int type,\n            String clientIp, Page page) {\n        try {\n            return appClientExceptionStatDao.getAppExceptionList(appId, startTime, endTime, type, clientIp, page);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return Collections.emptyList();\n        }\n    }\n    \n    @Override\n    public int getAppExceptionCount(Long appId, long startTime, long endTime, int type, String clientIp) {\n        try {\n            return appClientExceptionStatDao.getAppExceptionCount(appId, startTime, endTime, type, clientIp);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return 0;\n        }\n    }\n    \n    @Override\n    public List<ClientInstanceException> getInstanceExceptionStat(String ip, long collectTime) {\n        try {\n            return appClientExceptionStatDao.getInstanceExceptionStat(ip, collectTime);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return Collections.emptyList();\n        }\n    }\n    \n    @Override\n    public void batchSave(ClientReportBean clientReportBean) {\n        try {\n            // 1.client上报\n            final String clientIp = clientReportBean.getClientIp();\n            final long collectTime = clientReportBean.getCollectTime();\n            final long reportTime = clientReportBean.getReportTimeStamp();\n            final List<Map<String, Object>> datas = clientReportBean.getDatas();\n            if (datas == null || datas.isEmpty()) {\n                logger.warn(\"datas field {} is empty\", clientReportBean);\n                return;\n            }\n\n            // 2.结果集\n            List<AppClientExceptionStat> appClientExceptionStatList = new ArrayList<AppClientExceptionStat>();\n\n            // 3.解析\n            for (Map<String, Object> map : datas) {\n                Integer clientDataType = MapUtils.getInteger(map, ClientReportConstant.CLIENT_DATA_TYPE, -1);\n                ClientCollectDataTypeEnum clientCollectDataTypeEnum = ClientCollectDataTypeEnum.MAP.get(clientDataType);\n                if (clientCollectDataTypeEnum == null) {\n                    continue;\n                }\n                if (ClientCollectDataTypeEnum.EXCEPTION_TYPE.equals(clientCollectDataTypeEnum)) {\n                    AppClientExceptionStat appClientExceptionStat = generate(clientIp, collectTime, reportTime, map);\n                    if (appClientExceptionStat != null) {\n                        appClientExceptionStatList.add(appClientExceptionStat);\n                    }\n                }\n            }\n            \n            // 4.批量保存\n            if (CollectionUtils.isNotEmpty(appClientExceptionStatList)) {\n                appClientExceptionStatDao.batchSave(appClientExceptionStatList);\n            }\n            \n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n    }\n    \n    private AppClientExceptionStat generate(String clientIp, long collectTime, long reportTime, Map<String, Object> map) {\n\n        // 异常信息\n        String exceptionClass = MapUtils.getString(map, ClientReportConstant.EXCEPTION_CLASS, \"\");\n        Long exceptionCount = MapUtils.getLong(map, ClientReportConstant.EXCEPTION_COUNT, 0L);\n        int exceptionType = MapUtils.getInteger(map, ClientReportConstant.EXCEPTION_TYPE, ClientExceptionType.REDIS_TYPE.getType());\n\n        String host = null;\n        Integer port = null;\n        Integer instanceId = null;\n        long appId;\n        if (ClientExceptionType.REDIS_TYPE.getType() == exceptionType) {\n            // 实例host:port\n            String hostPort = MapUtils.getString(map, ClientReportConstant.EXCEPTION_HOST_PORT, \"\");\n            if (StringUtils.isEmpty(hostPort)) {\n                logger.warn(\"hostPort is empty\", hostPort);\n                return null;\n            }\n            int index = hostPort.indexOf(\":\");\n            if (index <= 0) {\n                logger.warn(\"hostPort {} format is wrong\", hostPort);\n                return null;\n            }\n            host = hostPort.substring(0, index);\n            port = NumberUtils.toInt(hostPort.substring(index + 1));\n\n            // 实例信息\n            InstanceInfo instanceInfo = clientReportInstanceService.getInstanceInfoByHostPort(host, port);\n            if (instanceInfo == null) {\n//                logger.warn(\"instanceInfo is empty, host is {}, port is {}\", host, port);\n                return null;\n            }\n            // 实例id\n            instanceId = instanceInfo.getId();\n            // 应用id\n            appId = instanceInfo.getAppId();\n        } else {\n            List<AppClientVersion> appClientVersion = appClientVersionDao.getByClientIp(clientIp);\n            if (CollectionUtils.isNotEmpty(appClientVersion)) {\n                appId = appClientVersion.get(0).getAppId();\n            } else {\n                appId = 0;\n            }\n        }\n\n        // 组装AppClientExceptionStat\n        AppClientExceptionStat stat = new AppClientExceptionStat();\n        stat.setAppId(appId);\n        stat.setClientIp(clientIp);\n        stat.setReportTime(new Date(reportTime));\n        stat.setCollectTime(collectTime);\n        stat.setCreateTime(new Date());\n        stat.setExceptionClass(exceptionClass);\n        stat.setExceptionCount(exceptionCount);\n        stat.setInstanceHost(host);\n        stat.setInstancePort(port);\n        stat.setInstanceId(instanceId);\n        stat.setType(exceptionType);\n\n        return stat;\n    }\n\n    public void setAppClientExceptionStatDao(AppClientExceptionStatDao appClientExceptionStatDao) {\n        this.appClientExceptionStatDao = appClientExceptionStatDao;\n    }\n\n    public void setAppClientVersionDao(AppClientVersionDao appClientVersionDao) {\n        this.appClientVersionDao = appClientVersionDao;\n    }\n\n    public void setClientReportInstanceService(ClientReportInstanceService clientReportInstanceService) {\n        this.clientReportInstanceService = clientReportInstanceService;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/client/service/impl/ClientReportInstanceServiceImpl.java",
    "content": "package com.sohu.cache.client.service.impl;\n\nimport java.util.concurrent.ConcurrentHashMap;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.sohu.cache.client.service.ClientReportInstanceService;\nimport com.sohu.cache.dao.InstanceDao;\nimport com.sohu.cache.entity.InstanceInfo;\n\n/**\n * @author leifu\n * @Date 2016年5月5日\n * @Time 上午11:05:35\n */\npublic class ClientReportInstanceServiceImpl implements ClientReportInstanceService {\n\n    private Logger logger = LoggerFactory.getLogger(ClientReportInstanceServiceImpl.class);\n\n    /**\n     * 不要求一致性的本地缓存(hostport<=>instanceInfo)\n     */\n    private final static ConcurrentHashMap<String, InstanceInfo> hostPortInstanceMap = new ConcurrentHashMap<String, InstanceInfo>();\n\n    private InstanceDao instanceDao;\n\n    @Override\n    public InstanceInfo getInstanceInfoByHostPort(String host, int port) {\n        String hostPort = host + \":\" + port;\n        try {\n            InstanceInfo instanceInfo = hostPortInstanceMap.get(hostPort);\n            if (instanceInfo == null) {\n                instanceInfo = instanceDao.getInstByIpAndPort(host, port);\n                if (instanceInfo != null) {\n                    hostPortInstanceMap.putIfAbsent(hostPort, instanceInfo);\n                }\n            }\n            return instanceInfo;\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return null;\n        }\n    }\n\n    public void setInstanceDao(InstanceDao instanceDao) {\n        this.instanceDao = instanceDao;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/client/service/impl/ClientReportValueDistriServiceImplV2.java",
    "content": "package com.sohu.cache.client.service.impl;\n\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\nimport org.apache.commons.collections.MapUtils;\nimport org.apache.commons.lang.StringUtils;\nimport org.apache.commons.lang.math.NumberUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.sohu.cache.client.service.ClientReportInstanceService;\nimport com.sohu.cache.client.service.ClientReportValueDistriService;\nimport com.sohu.cache.dao.AppClientValueStatDao;\nimport com.sohu.cache.entity.AppClientValueDistriSimple;\nimport com.sohu.cache.entity.AppClientValueDistriStatTotal;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.tv.jedis.stat.constant.ClientReportConstant;\nimport com.sohu.tv.jedis.stat.enums.ClientCollectDataTypeEnum;\nimport com.sohu.tv.jedis.stat.enums.ValueSizeDistriEnum;\nimport com.sohu.tv.jedis.stat.model.ClientReportBean;\n\n/**\n * 客户端上报值分布serviceV2\n * \n * @author leifu\n * @Date 2016年5月5日\n * @Time 上午10:23:00\n */\npublic class ClientReportValueDistriServiceImplV2 implements ClientReportValueDistriService {\n\n    private final Logger logger = LoggerFactory.getLogger(ClientReportValueDistriServiceImplV2.class);\n\n    public static Set<String> excludeCommands = new HashSet<String>();\n    static {\n        excludeCommands.add(\"ping\");\n        excludeCommands.add(\"quit\");\n    }\n    \n    /**\n     * 客户端统计值分布数据操作\n     */\n    private AppClientValueStatDao appClientValueStatDao;\n\n    /**\n     * host:port与instanceInfo简单缓存\n     */\n    private ClientReportInstanceService clientReportInstanceService;\n\n    @Override\n    public List<AppClientValueDistriSimple> getAppValueDistriList(long appId, long startTime, long endTime) {\n        try {\n            return appClientValueStatDao.getAppValueDistriList(appId, startTime, endTime);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return Collections.emptyList();\n        }\n    }\n\n    @Override\n    public void batchSave(ClientReportBean clientReportBean) {\n        try {\n            // 1.client上报\n            final long collectTime = clientReportBean.getCollectTime();\n            final long reportTime = clientReportBean.getReportTimeStamp();\n            final List<Map<String, Object>> datas = clientReportBean.getDatas();\n            if (datas == null || datas.isEmpty()) {\n                logger.warn(\"datas field {} is empty\", clientReportBean);\n                return;\n            }\n\n            // 3.解析\n            for (Map<String, Object> map : datas) {\n                Integer clientDataType = MapUtils.getInteger(map, ClientReportConstant.CLIENT_DATA_TYPE, -1);\n                ClientCollectDataTypeEnum clientCollectDataTypeEnum = ClientCollectDataTypeEnum.MAP.get(clientDataType);\n                if (clientCollectDataTypeEnum == null) {\n                    continue;\n                }\n                if (ClientCollectDataTypeEnum.VALUE_LENGTH_DISTRI_TYPE.equals(clientCollectDataTypeEnum)) {\n                    AppClientValueDistriStatTotal appClientValueDistriStat = generate(collectTime, reportTime, map);\n                    if (appClientValueDistriStat != null) {\n                        appClientValueStatDao.save(appClientValueDistriStat);\n                    }\n                }\n            }\n\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n    }\n\n    private AppClientValueDistriStatTotal generate(long collectTime, long reportTime, Map<String, Object> map) {\n        String valueDistri = MapUtils.getString(map, ClientReportConstant.VALUE_DISTRI, \"\");\n        ValueSizeDistriEnum valueSizeDistriEnum = ValueSizeDistriEnum.getByValue(valueDistri);\n        if (valueSizeDistriEnum == null) {\n            logger.warn(\"valueDistri {} is wrong, not in enums {}\", valueDistri, ValueSizeDistriEnum.values());\n        }\n\n        // 次数\n        Integer count = MapUtils.getInteger(map, ClientReportConstant.VALUE_COUNT, 0);\n\n        // 命令\n        String command = MapUtils.getString(map, ClientReportConstant.VALUE_COMMAND, \"\");\n        if (StringUtils.isBlank(command)) {\n            logger.warn(\"command is empty!\");\n            return null;\n        }\n        if (excludeCommands.contains(command)) {\n            return null;\n        }\n\n        // 实例host:port\n        String hostPort = MapUtils.getString(map, ClientReportConstant.VALUE_HOST_PORT, \"\");\n        if (StringUtils.isEmpty(hostPort)) {\n            logger.warn(\"hostPort is empty\", hostPort);\n            return null;\n        }\n        int index = hostPort.indexOf(\":\");\n        if (index <= 0) {\n            logger.warn(\"hostPort {} format is wrong\", hostPort);\n            return null;\n        }\n        String host = hostPort.substring(0, index);\n        int port = NumberUtils.toInt(hostPort.substring(index + 1));\n\n        // 实例信息\n        InstanceInfo instanceInfo = clientReportInstanceService.getInstanceInfoByHostPort(host, port);\n        if (instanceInfo == null) {\n            // logger.warn(\"instanceInfo is empty, host is {}, port is {}\",\n            // host, port);\n            return null;\n        }\n\n        AppClientValueDistriStatTotal stat = new AppClientValueDistriStatTotal();\n        stat.setAppId(instanceInfo.getAppId());\n        stat.setCollectTime(collectTime);\n        stat.setUpdateTime(new Date());\n        stat.setCommand(command);\n        stat.setDistributeType(valueSizeDistriEnum.getType());\n        stat.setCount(count);\n\n        return stat;\n    }\n\n    @Override\n    public int deleteBeforeCollectTime(long collectTime) {\n        try {\n            return appClientValueStatDao.deleteBeforeCollectTime(collectTime);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return -1;\n        }\n    }\n\n    public void setClientReportInstanceService(ClientReportInstanceService clientReportInstanceService) {\n        this.clientReportInstanceService = clientReportInstanceService;\n    }\n\n    public void setAppClientValueStatDao(AppClientValueStatDao appClientValueStatDao) {\n        this.appClientValueStatDao = appClientValueStatDao;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/client/service/impl/ClientVersionServiceImpl.java",
    "content": "package com.sohu.cache.client.service.impl;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Set;\n\nimport org.apache.commons.collections.CollectionUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.sohu.cache.client.service.ClientVersionService;\nimport com.sohu.cache.dao.AppClientVersionDao;\nimport com.sohu.cache.entity.AppClientVersion;\n\n/**\n * 客户端版本信息\n * \n * @author leifu\n * @Date 2015年2月2日\n * @Time 上午10:19:59\n */\npublic class ClientVersionServiceImpl implements ClientVersionService {\n\n    private final Logger logger = LoggerFactory.getLogger(ClientVersionServiceImpl.class);\n\n    private AppClientVersionDao appClientVersionDao;\n\n    /**\n     * 办公网段ip\n     */\n    private static Set<String> OFFICE_IP = new HashSet<String>();\n    static {\n        OFFICE_IP.add(\"10.1\");\n        OFFICE_IP.add(\"10.2\");\n        OFFICE_IP.add(\"10.7\");\n    }\n\n    @Override\n    public void saveOrUpdateClientVersion(long appId, String appClientIp, String clientVersion) {\n        try {\n            AppClientVersion appClientVersion = new AppClientVersion();\n            appClientVersion.setAppId(appId);\n            appClientVersion.setClientIp(appClientIp);\n            appClientVersion.setClientVersion(clientVersion);\n            appClientVersion.setReportTime(new Date());\n            appClientVersionDao.saveOrUpdateClientVersion(appClientVersion);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n    }\n\n    @Override\n    public List<AppClientVersion> getAppAllClientVersion(long appId) {\n        try {\n            return appClientVersionDao.getAppAllClientVersion(appId);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return Collections.emptyList();\n        }\n    }\n\n    @Override\n    public List<AppClientVersion> getAppAllServerClientVersion(long appId) {\n        List<AppClientVersion> appClientVersionList = getAppAllClientVersion(appId);\n        if (CollectionUtils.isEmpty(appClientVersionList)) {\n            return Collections.emptyList();\n        }\n        List<AppClientVersion> appClientVersionServerList = new ArrayList<AppClientVersion>();\n        for (AppClientVersion appClientVersion : appClientVersionList) {\n            String clientIp = appClientVersion.getClientIp();\n            String[] items = clientIp.split(\".\");\n            //过滤办公网段ip\n            if (!OFFICE_IP.contains(items[0] + \".\" + items[1])) {\n                appClientVersionServerList.add(appClientVersion);\n            }\n        }\n        return appClientVersionServerList;\n    }\n    \n    @Override\n    public List<AppClientVersion> getAll(long appId) {\n        try {\n            return appClientVersionDao.getAll(appId);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return Collections.emptyList();\n        }\n    }\n\n    public void setAppClientVersionDao(AppClientVersionDao appClientVersionDao) {\n        this.appClientVersionDao = appClientVersionDao;\n    }\n\n    \n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/constant/AppAuditLogTypeEnum.java",
    "content": "package com.sohu.cache.constant;\n\n/**\n * 日志类型\n * @author leifu\n * @Time 2014年10月21日\n */\npublic enum AppAuditLogTypeEnum {\n    // 申请应用\n    APP_DESC_APPLY(1),\n    // 扩容申请\n    APP_SCALE_APPLY(2),\n    // 应用配置修改申请\n    APP_CONFIG_APPLY(3),\n    // 审批\n    APP_CHECK(4),\n    // 修改报警阀值\n    APP_CHANGE_ALERT(5),\n    // 清理数据\n    APP_CLEAN_DATA(6),\n    // 实例配置修改申请\n    INSTANCE_CONFIG_APPLY(7);\n    \n    private int value;\n    \n\n    private AppAuditLogTypeEnum(int value) {\n        this.value = value;\n    }\n\n    public int value() {\n        return value;\n    }\n\n    @Override\n    public String toString() {\n        return String.valueOf(value);\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/constant/AppAuditType.java",
    "content": "package com.sohu.cache.constant;\n\n/**\n * Created by yijunzhang on 14-10-20.\n */\npublic enum AppAuditType {\n\n    APP_AUDIT(0),\n    APP_SCALE(1),\n    APP_MODIFY_CONFIG(2),\n    REGISTER_USER_APPLY(3),\n    INSTANCE_MODIFY_CONFIG(4);\n\n    private int value;\n\n    AppAuditType(int value) {\n        this.value = value;\n    }\n\n    public int getValue() {\n        return value;\n    }\n\n    @Override\n    public String toString() {\n        return String.valueOf(value);\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/constant/AppCheckEnum.java",
    "content": "package com.sohu.cache.constant;\n\n/**\n * 审批状态\n * \n * @author leifu\n * @Time 2014年10月20日\n */\npublic enum AppCheckEnum {\n\n    // 通过审批\n    APP_PASS(1),\n    // 驳回审批\n    APP_REJECT(-1),\n    // 等待审批\n    APP_WATING_CHECK(0),\n    //分配资源完毕\n    APP_ALLOCATE_RESOURCE(2);\n\n    private Integer value;\n\n    public Integer value() {\n        return value;\n    }\n    \n    private AppCheckEnum(Integer value) {\n        this.value = value;\n    }\n\n    @Override\n    public String toString() {\n        return String.valueOf(value);\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/constant/AppDataMigrateEnum.java",
    "content": "package com.sohu.cache.constant;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * Redis迁移类型枚举\n * @author leifu\n * @Date 2016-6-8\n * @Time 下午3:02:50\n */\npublic enum AppDataMigrateEnum {\n    REDIS_NODE(0, \"single\"),\n    REDIS_CLUSTER_NODE(1, \"redis cluster\"),\n    RDB_FILE(2, \"rdb file\"),\n    TWEMPROXY(3, \"twemproxy\"),\n    AOF_FILE(4, \"aof file\");\n\n    private int index;\n\n    private String type;\n\n    private static Map<Integer, AppDataMigrateEnum> MAP = new HashMap<Integer, AppDataMigrateEnum>();\n    static {\n        for (AppDataMigrateEnum redisMigrateEnum : AppDataMigrateEnum.values()) {\n            MAP.put(redisMigrateEnum.getIndex(), redisMigrateEnum);\n        }\n    }\n\n    public static AppDataMigrateEnum getByIndex(int index) {\n        return MAP.get(index);\n    }\n\n    private AppDataMigrateEnum(int index, String type) {\n        this.index = index;\n        this.type = type;\n    }\n    \n    public static boolean isFileType(AppDataMigrateEnum appDataMigrateEnum) {\n        if (RDB_FILE.equals(appDataMigrateEnum) || AOF_FILE.equals(appDataMigrateEnum)) {\n            return true;\n        }\n        return false;\n    }\n\n    public int getIndex() {\n        return index;\n    }\n\n    public String getType() {\n        return type;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/constant/AppDataMigrateResult.java",
    "content": "package com.sohu.cache.constant;\n\n/**\n * 迁移结果\n * \n * @author leifu\n * @Date 2016-6-8\n * @Time 下午3:15:08\n */\npublic class AppDataMigrateResult {\n\n    private int status;\n\n    private String message;\n\n    public AppDataMigrateResult(int status, String message) {\n        this.status = status;\n        this.message = message;\n    }\n\n    public boolean isSuccess() {\n        if (status == 1) {\n            return true;\n        }\n        return false;\n    }\n\n    public static AppDataMigrateResult success() {\n        return new AppDataMigrateResult(1, \"所有检查都成功，可以迁移啦!\");\n    }\n    \n    public static AppDataMigrateResult success(String message) {\n        return new AppDataMigrateResult(1, message);\n    }\n\n    public static AppDataMigrateResult fail(String message) {\n        return new AppDataMigrateResult(0, message);\n    }\n\n    public int getStatus() {\n        return status;\n    }\n\n    public void setStatus(int status) {\n        this.status = status;\n    }\n\n    public String getMessage() {\n        return message;\n    }\n\n    public void setMessage(String message) {\n        this.message = message;\n    }\n\n    @Override\n    public String toString() {\n        return \"RedisMigrateResult [status=\" + status + \", message=\" + message + \"]\";\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/constant/AppDataMigrateStatusEnum.java",
    "content": "package com.sohu.cache.constant;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * 迁移状态\n * @author leifu\n * @Date 2016-6-9\n * @Time 下午7:53:28\n */\npublic enum AppDataMigrateStatusEnum {\n\n    START(0, \"开始\"),\n    END(1, \"结束\"),\n    ERROR(-1, \"失败\")\n    ;\n\n    private int status;\n\n    private String info;\n\n    private static Map<Integer, AppDataMigrateStatusEnum> MAP = new HashMap<Integer, AppDataMigrateStatusEnum>();\n    static {\n        for (AppDataMigrateStatusEnum rppDataMigrateStatusEnum : AppDataMigrateStatusEnum.values()) {\n            MAP.put(rppDataMigrateStatusEnum.getStatus(), rppDataMigrateStatusEnum);\n        }\n    }\n\n    public static AppDataMigrateStatusEnum getByStatus(int status) {\n        return MAP.get(status);\n    }\n\n    private AppDataMigrateStatusEnum(int status, String info) {\n        this.status = status;\n        this.info = info;\n    }\n\n    public int getStatus() {\n        return status;\n    }\n\n    public String getInfo() {\n        return info;\n    }\n\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/constant/AppDescEnum.java",
    "content": "package com.sohu.cache.constant;\n\n/**\n * app详情枚举(以后有关app详情的都往这里面迁)\n * \n * @author leifu\n * @Date 2015年1月26日\n * @Time 上午11:34:22\n */\npublic class AppDescEnum {\n    \n    /**\n     * 是否为测试应用\n     */\n    public static enum AppTest {\n        IS_TEST(1),\n        NOT_TEST(0);\n\n        private int value;\n\n        private AppTest(int value) {\n            this.value = value;\n        }\n\n        public int getValue() {\n            return value;\n        }\n\n        public void setValue(int value) {\n            this.value = value;\n        }\n    }\n    \n    /**\n     * 应用重要度\n     */\n    public static enum AppImportantLevel {\n        SUPER_IMPORTANT(1, \"S\"),\n        VERY_IMPORTANT(2, \"A\"),\n        IMPORTANT(3, \"B\"),\n        COMMON(4, \"C\");\n\n        private int value;\n        \n        private String info;\n\n        private AppImportantLevel(int value, String info) {\n            this.value = value;\n            this.info = info;\n        }\n\n        public int getValue() {\n            return value;\n        }\n\n        public String getInfo() {\n            return info;\n        }\n\n\n    }\n    \n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/constant/AppStatusEnum.java",
    "content": "package com.sohu.cache.constant;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * 应用发布状态\n * \n * @author leifu\n * @Time 2014年6月28日\n */\npublic enum AppStatusEnum {\n    STATUS_INITIALIZE(0, \"未分配\"),\n    STATUS_ALLOCATED(1, \"已申请未审批\"),\n    STATUS_PUBLISHED(2, \"运行中\"),\n    STATUS_OFFLINE(3, \"已下线\"),\n    STATUS_DENY(4, \"驳回\");\n\n    private int status;\n\n    private String info;\n\n    private static Map<Integer, AppStatusEnum> MAP = new HashMap<Integer, AppStatusEnum>();\n    static {\n        for (AppStatusEnum appStatusEnum : AppStatusEnum.values()) {\n            MAP.put(appStatusEnum.getStatus(), appStatusEnum);\n        }\n    }\n\n    private AppStatusEnum(int status, String info) {\n        this.status = status;\n        this.info = info;\n    }\n\n    public static AppStatusEnum getByStatus(int status) {\n        return MAP.get(status);\n    }\n\n    public int getStatus() {\n        return status;\n    }\n\n    public String getInfo() {\n        return info;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/constant/AppTopology.java",
    "content": "package com.sohu.cache.constant;\n\n/**\n * 应用的配置、节点信息\n *\n * Created by lingguo on 14-6-26.\n */\npublic enum AppTopology {\n    TOTAL_MEMORY(\"total_memory\"),           /* 应用的总内存 */\n    MACHINE_COUNT(\"machine_count\"),         /* 应用的机器数量 */\n    MASTER_COUNT(\"master_count\"),           /* 主节点的数量 */\n    SLAVE_COUNT(\"slave_count\");             /* 从节点的数量 */\n\n    private String value;\n\n    AppTopology(String value) {\n        this.value = value;\n    }\n\n    public String getValue() {\n        return this.value;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/constant/AppUserTypeEnum.java",
    "content": "package com.sohu.cache.constant;\n\n/**\n * 用户类型\n * @author leifu\n * @Time 2014年10月21日\n */\npublic enum AppUserTypeEnum {\n\n    //管理员\n    ADMIN_USER(0),\n    //普通用户\n    REGULAR_USER(2),\n    //不存在用户\n    NO_USER(-1);\n    \n    private Integer value;\n\n    private AppUserTypeEnum(Integer value) {\n        this.value = value;\n    }\n\n    public Integer value() {\n        return value;\n    }\n\n    @Override\n    public String toString() {\n        return String.valueOf(value);\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/constant/BaseConstant.java",
    "content": "package com.sohu.cache.constant;\n\n/**\n * @author leifu\n * @Date 2016-1-26\n * @Time 下午9:26:58\n */\npublic class BaseConstant {\n\n    /** mill seconds of one day */\n    public static long MILLISECONDS_OF_ONE_SECOND = 1000;\n\n    /** mill seconds of one day */\n    public static long MILLISECONDS_OF_ONE_MINUTE = 1000 * 60;\n\n    /** mill seconds of one day */\n    public static long MILLISECONDS_OF_ONE_DAY = 1000 * 60 * 60 * 24;\n\n    /** mill seconds of one hour */\n    public static long MILLISECONDS_OF_ONE_HOUR = 1000 * 60 * 60;\n\n    /**\n     * WORD_SEPARATOR ( char )2\n     */\n    public static final String WORD_SEPARATOR = Character.toString((char) 2);\n\n    public static final String SYSTEM_PROPERTY_CONFIG_FILE_PATH = \"configFilePath\";\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/constant/ClientStatusEnum.java",
    "content": "package com.sohu.cache.constant;\n\n/**\n * 检查客户端的版本是否ok的枚举\n *\n * @author: lingguo\n * @time: 2014/10/22 10:13\n */\npublic enum ClientStatusEnum {\n    GOOD(1),\n    WARN(0),\n    ERROR(-1);\n\n    int status;\n\n    ClientStatusEnum(int status) {\n        this.status = status;\n    }\n\n    public int getStatus() {\n        return status;\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/constant/ClusterOperateResult.java",
    "content": "package com.sohu.cache.constant;\n\n\n/**\n * Cluster Operate Result\n * @author leifu\n * @Date 2017年6月27日\n * @Time 上午8:43:10\n */\npublic class ClusterOperateResult {\n\n    private int status;\n\n    private String message;\n\n    public ClusterOperateResult(int status, String message) {\n        this.status = status;\n        this.message = message;\n    }\n\n    public static ClusterOperateResult success() {\n        return new ClusterOperateResult(1, \"\");\n    }\n\n    public static ClusterOperateResult fail(String message) {\n        return new ClusterOperateResult(0, message);\n    }\n    \n    public boolean isSuccess() {\n        return status == 1;\n    }\n\n    public int getStatus() {\n        return status;\n    }\n\n    public String getMessage() {\n        return message;\n    }\n\n    @Override\n    public String toString() {\n        return \"ClusterOperateResult [status=\" + status + \", message=\" + message + \"]\";\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/constant/CommandResult.java",
    "content": "package com.sohu.cache.constant;\n\nimport java.util.List;\n\n/**\n * ssh命令简单封装\n * @author leifu\n * @Date 2016年7月27日\n * @Time 下午3:06:42\n */\npublic class CommandResult {\n    private String command;\n    \n    private String result;\n    \n    private List<String> resultLines;\n    \n    public CommandResult(String command, String result) {\n        super();\n        this.command = command;\n        this.result = result;\n    }\n\n    public String getCommand() {\n        return command;\n    }\n\n    public void setCommand(String command) {\n        this.command = command;\n    }\n\n    public String getResult() {\n        return result;\n    }\n\n    public void setResult(String result) {\n        this.result = result;\n    }\n\n    public List<String> getResultLines() {\n        return resultLines;\n    }\n\n    public void setResultLines(List<String> resultLines) {\n        this.resultLines = resultLines;\n    }\n\n    @Override\n    public String toString() {\n        return \"CommandResult [command=\" + command + \", result=\" + result + \", resultLines=\" + resultLines + \"]\";\n    }\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/constant/DataFormatCheckResult.java",
    "content": "package com.sohu.cache.constant;\n\n/**\n * 数据格式检测\n * @author leifu\n * @Date 2016年7月4日\n * @Time 下午5:37:03\n */\npublic class DataFormatCheckResult {\n\n    private int status;\n\n    private String message;\n    \n    private final static int SUCCESS = 1;\n    private final static int FAIL = 0;\n\n    public DataFormatCheckResult(int status, String message) {\n        this.status = status;\n        this.message = message;\n    }\n\n    public boolean isSuccess() {\n        if (status == SUCCESS) {\n            return true;\n        }\n        return false;\n    }\n\n    public static DataFormatCheckResult success(String message) {\n        return new DataFormatCheckResult(SUCCESS, message);\n    }\n\n    public static DataFormatCheckResult fail(String message) {\n        return new DataFormatCheckResult(FAIL, message);\n    }\n\n    public int getStatus() {\n        return status;\n    }\n\n    public void setStatus(int status) {\n        this.status = status;\n    }\n\n    public String getMessage() {\n        return message;\n    }\n\n    public void setMessage(String message) {\n        this.message = message;\n    }\n\n    @Override\n    public String toString() {\n        return \"DataFormatCheckResult [status=\" + status + \", message=\" + message + \"]\";\n    }\n\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/constant/EmptyObjectConstant.java",
    "content": "package com.sohu.cache.constant;\n\n/**\n * 空对象常量\n * @author leifu\n * @Date 2016-1-26\n * @Time 下午9:27:23\n */\npublic class EmptyObjectConstant {\n\n\tpublic static String EMPTY_STRING = \"\";\n\tpublic static String[] EMPTY_STRING_ARRAY = new String[0];\n\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/constant/ErrorMessageEnum.java",
    "content": "package com.sohu.cache.constant;\n\n/**\n * 系统错误提示\n * @author leifu\n * @Date 2016-6-25\n * @Time 下午2:50:07\n */\npublic enum ErrorMessageEnum {\n\n    INNER_ERROR_MSG(1, \"系统异常，请观察系统日志!\"),\n    PARAM_ERROR_MSG(2, \"参数错误!\")\n    ;\n    \n    private int id;\n    \n    private String message;\n\n    private ErrorMessageEnum(int id, String message) {\n        this.id = id;\n        this.message = message;\n    }\n\n    public int getId() {\n        return id;\n    }\n\n    public String getMessage() {\n        return message;\n    }\n    \n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/constant/HorizontalResult.java",
    "content": "package com.sohu.cache.constant;\n\n/**\n * 水平扩容结果标识\n * @author leifu\n * @Date 2016年12月4日\n * @Time 下午1:30:19\n */\npublic class HorizontalResult {\n\n    private int status;\n\n    private String message;\n\n    public HorizontalResult(int status, String message) {\n        this.status = status;\n        this.message = message;\n    }\n\n    public static HorizontalResult checkSuccess() {\n        return new HorizontalResult(1, \"所有检查都成功，可以开始水平扩容了!\");\n    }\n    \n    public static HorizontalResult scaleSuccess() {\n        return new HorizontalResult(1, \"水平扩容已经成功开始!\");\n    }\n\n    public static HorizontalResult fail(String message) {\n        return new HorizontalResult(0, message);\n    }\n\n    public int getStatus() {\n        return status;\n    }\n\n    public void setStatus(int status) {\n        this.status = status;\n    }\n\n    public String getMessage() {\n        return message;\n    }\n\n    public void setMessage(String message) {\n        this.message = message;\n    }\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"HorizontalResult [status=\" + status + \", message=\" + message + \"]\";\n\t}\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/constant/ImportAppResult.java",
    "content": "package com.sohu.cache.constant;\n\n/**\n * 导入结果\n * \n * @author leifu\n * @Date 2016-4-16\n * @Time 下午3:41:37\n */\npublic class ImportAppResult {\n\n    private int status;\n\n    private String message;\n\n    public ImportAppResult(int status, String message) {\n        this.status = status;\n        this.message = message;\n    }\n\n    public static ImportAppResult success() {\n        return new ImportAppResult(1, \"所有检查都成功，可以添加啦!\");\n    }\n\n    public static ImportAppResult fail(String message) {\n        return new ImportAppResult(0, message);\n    }\n\n    public int getStatus() {\n        return status;\n    }\n\n    public void setStatus(int status) {\n        this.status = status;\n    }\n\n    public String getMessage() {\n        return message;\n    }\n\n    public void setMessage(String message) {\n        this.message = message;\n    }\n\n    @Override\n    public String toString() {\n        return \"ImportAppResult [status=\" + status + \", message=\" + message + \"]\";\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/constant/InstanceStatusEnum.java",
    "content": "package com.sohu.cache.constant;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * 实例状态\n * @author leifu\n * @Date 2014年11月26日\n * @Time 下午5:05:35\n */\npublic enum InstanceStatusEnum {\n    ERROR_STATUS(0, \"心跳停止\"),\n    GOOD_STATUS(1, \"运行中\"),\n    OFFLINE_STATUS(2, \"已下线\");\n\n    private int status;\n    \n    private String info;\n    \n    private static Map<Integer, InstanceStatusEnum> MAP = new HashMap<Integer, InstanceStatusEnum>();\n    static {\n        for(InstanceStatusEnum instanceStatusEnum : InstanceStatusEnum.values()) {\n            MAP.put(instanceStatusEnum.getStatus(), instanceStatusEnum);\n        }\n    }\n    \n    public static InstanceStatusEnum getByStatus(int status) {\n        return MAP.get(status);\n    }\n    \n    private InstanceStatusEnum(int status, String info) {\n        this.status = status;\n        this.info = info;\n    }\n\n    public int getStatus() {\n        return status;\n    }\n\n    public String getInfo() {\n        return info;\n    }\n    \n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/constant/MachineConstant.java",
    "content": "package com.sohu.cache.constant;\n\n/**\n * User: lingguo\n * Date: 14-6-12\n * Time: 上午11:42\n */\npublic enum MachineConstant {\n    Ip(\"ip\"),\n    Load(\"load\"),\n    Traffic(\"traffic\"),\n    CpuUsage(\"cpuUsage\"),\n    MemoryUsageRatio(\"memoryUsageRatio\"),\n    MemoryFree(\"memoryFree\"),\n    MemoryTotal(\"memoryTotal\"),\n    DiskUsage(\"diskUsageMap\");\n\n    private String value;\n\n    MachineConstant(String value) {\n        this.value = value;\n    }\n\n    public String getValue() {\n        return this.value;\n    }\n\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/constant/MachineInfoEnum.java",
    "content": "package com.sohu.cache.constant;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * 机器信息枚举\n * @author leifu\n * @Date 2016年7月9日\n * @Time 下午4:38:15\n */\npublic class MachineInfoEnum {\n    \n    /**\n     * 是否为可用\n     * @author leifu\n     * @Date 2016年7月9日\n     * @Time 下午4:43:49\n     */\n    public static enum AvailableEnum {\n        YES(1),\n        NO(0);\n\n        private int value;\n\n        private AvailableEnum(int value) {\n            this.value = value;\n        }\n\n        public int getValue() {\n            return value;\n        }\n\n        public void setValue(int value) {\n            this.value = value;\n        }\n    }\n    \n    /**\n     * 机器类型\n     * @author leifu\n     * @Date 2016年7月9日\n     * @Time 下午4:42:58\n     */\n    public static enum TypeEnum {\n        REDIS_NODE(0, \"redis实例\"),\n        REDIS_MIGRATE_TOOL(2, \"redis迁移工具\");\n\n        private int type;\n\n        private String info;\n\n        private static Map<Integer, TypeEnum> MAP = new HashMap<Integer, TypeEnum>();\n        static {\n            for (TypeEnum typeEnum : TypeEnum.values()) {\n                MAP.put(typeEnum.getType(), typeEnum);\n            }\n        }\n\n        public static TypeEnum getByType(int type) {\n            return MAP.get(type);\n        }\n\n        private TypeEnum(int type, String info) {\n            this.type = type;\n            this.info = info;\n        }\n        public int getType() {\n            return type;\n        }\n        public String getInfo() {\n            return info;\n        }\n\n\n    }\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/constant/PipelineEnum.java",
    "content": "package com.sohu.cache.constant;\n\n/**\n * @author leifu\n * @Date 2017年7月13日\n * @Time 下午3:26:03\n */\npublic enum PipelineEnum {\n    NO(0), YES(1);\n    \n    private int value;\n\n    private PipelineEnum(int value) {\n        this.value = value;\n    }\n    \n    public static PipelineEnum getPipelineEnum(int pipelineInt) {\n        for (PipelineEnum pipelineEnum : PipelineEnum.values()) {\n            if (pipelineInt == pipelineEnum.value) {\n                return pipelineEnum;\n            }\n        }\n        return null;\n    }\n\n    public int getValue() {\n        return value;\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/constant/RedisConfigTemplateChangeEnum.java",
    "content": "package com.sohu.cache.constant;\n\n/**\n * 配置模板改变行为枚举\n * \n * @author leifu\n * @Date 2016年7月27日\n * @Time 下午3:51:13\n */\npublic enum RedisConfigTemplateChangeEnum {\n\n    UPDATE(1, \"更新\"),\n    ADD(2, \"添加\"),\n    DELETE(3, \"删除\");\n\n    private int index;\n\n    private String info;\n\n    private RedisConfigTemplateChangeEnum(int index, String info) {\n        this.index = index;\n        this.info = info;\n    }\n\n    public int getIndex() {\n        return index;\n    }\n\n    public String getInfo() {\n        return info;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/constant/RedisConstant.java",
    "content": "package com.sohu.cache.constant;\n\n/**\n * redis 相关常量\n * Created by yijunzhang on 14-6-10.\n */\npublic enum RedisConstant {\n    Stats(\"Stats\"),\n    Keyspace(\"Keyspace\"),\n    Commandstats(\"Commandstats\"),\n    Replication(\"Replication\"),\n    Clients(\"Clients\"),\n    CPU(\"CPU\"),\n    Memory(\"Memory\"),\n    Server(\"Server\"),\n    Persistence(\"Persistence\"),\n    CollectTime(\"CollectTime\"),\n    DIFF(\"diff\");\n\n    private String value;\n\n    RedisConstant(String value) {\n        this.value = value;\n    }\n\n    @Override\n    public String toString() {\n        return this.value;\n    }\n\n    public static RedisConstant value(String input) {\n        RedisConstant[] constants = RedisConstant.values();\n        for (RedisConstant constant : constants) {\n            if (constant.value.equals(input)) {\n                return constant;\n            }\n        }\n        return null;\n    }\n\n    public String getValue() {\n        return value;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/constant/RedisExcludeCommand.java",
    "content": "package com.sohu.cache.constant;\n\nimport java.util.HashSet;\nimport java.util.Set;\n\n/**\n * Created by yijunzhang on 14-6-25.\n */\npublic class RedisExcludeCommand {\n\n    private static Set<String> excludeCommands = new HashSet<String>();\n\n    static {\n        //排除这些redis命令\n        excludeCommands.add(\"ping\");\n        excludeCommands.add(\"cluster\");\n        excludeCommands.add(\"config\");\n        excludeCommands.add(\"ttl\");\n        excludeCommands.add(\"client\");\n        excludeCommands.add(\"bgrewriteaof\");\n        excludeCommands.add(\"bgsave\");\n        excludeCommands.add(\"dbsize\");\n        excludeCommands.add(\"debug\");\n        excludeCommands.add(\"flushall\");\n        excludeCommands.add(\"flushdb\");\n        excludeCommands.add(\"flush\");\n        excludeCommands.add(\"info\");\n        excludeCommands.add(\"lastsave\");\n        excludeCommands.add(\"monitor\");\n        excludeCommands.add(\"psync\");\n        excludeCommands.add(\"save\");\n        excludeCommands.add(\"shutdown\");\n        excludeCommands.add(\"slaveof\");\n        excludeCommands.add(\"slowlog\");\n        excludeCommands.add(\"sync\");\n        excludeCommands.add(\"time\");\n        excludeCommands.add(\"replconf\");\n        excludeCommands.add(\"asking\");\n        excludeCommands.add(\"restore-asking\");\n        excludeCommands.add(\"restore\");\n        excludeCommands.add(\"select\");\n    }\n\n    public static boolean isExcludeCommand(String command) {\n        return excludeCommands.contains(command);\n    }\n\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/constant/RedisMigrateToolConstant.java",
    "content": "package com.sohu.cache.constant;\n\n/**\n * Redis-Migrate-Tool常量\n * @author leifu\n * @Date 2016-6-10\n * @Time 上午9:23:30\n */\npublic enum RedisMigrateToolConstant {\n    Stats(\"Stats\"),\n    Keyspace(\"Group\"),\n    Clients(\"Clients\"),\n    Memory(\"Memory\"),\n    Server(\"Server\");\n\n    private String value;\n\n    RedisMigrateToolConstant(String value) {\n        this.value = value;\n    }\n\n    @Override\n    public String toString() {\n        return this.value;\n    }\n\n    public static RedisMigrateToolConstant value(String input) {\n        RedisMigrateToolConstant[] constants = RedisMigrateToolConstant.values();\n        for (RedisMigrateToolConstant constant : constants) {\n            if (constant.value.equals(input)) {\n                return constant;\n            }\n        }\n        return null;\n    }\n\n    public String getValue() {\n        return value;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/constant/ReshardStatusEnum.java",
    "content": "package com.sohu.cache.constant;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * Reshard状态\n */\npublic enum ReshardStatusEnum {\n    RUNNING(0, \"运行中\"), \n    FINISH(1, \"完成\"),\n    ERROR(2, \"出错\");\n\n    private int value;\n    private String info;\n\n    private final static Map<Integer, ReshardStatusEnum> MAP = new HashMap<Integer, ReshardStatusEnum>();\n    static {\n        for (ReshardStatusEnum reshardStatusEnum : ReshardStatusEnum.values()) {\n            MAP.put(reshardStatusEnum.getValue(), reshardStatusEnum);\n        }\n    }\n\n    public static ReshardStatusEnum getReshardStatusEnum(int value) {\n        return MAP.get(value);\n    }\n\n    private ReshardStatusEnum(int value, String info) {\n        this.value = value;\n        this.info = info;\n    }\n\n    public int getValue() {\n        return value;\n    }\n\n    public String getInfo() {\n        return info;\n    }\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/constant/SymbolConstant.java",
    "content": "package com.sohu.cache.constant;\n\n/**\n * 符号常量\n * \n * @author leifu\n * @Date 2016-1-26\n * @Time 下午9:25:32\n */\npublic class SymbolConstant {\n\n    /** , */\n    public final static String COMMA = \",\";\n\n    public final static String SLASH = \"/\";\n    public final static String BACK_SLASH = \"\\\\\";\n    /** : */\n    public final static String COLON = \":\";\n    public final static String SPACE = \" \";\n    public final static String ENTER = System.lineSeparator();\n\n\n    /** ; */\n    public final static String SEMICOLON = \";\";\n\n    /** [ */\n    public final static String SQUARE_BRACKETS_LEFT = \"[\";\n    /** ] */\n    public final static String SQUARE_BRACKETS_RIGHT = \"]\";\n\n    public final static String CURLY_BRACKETS_LEFT = \"{\";\n    public final static String CURLY_BRACKETS_RIGHT = \"}\";\n    /** ( */\n    public final static String PARENTHESES_BRACKETS_LEFT = \"(\";\n    /** ) */\n    public final static String PARENTHESES_BRACKETS_RIGHT = \")\";\n\n    public final static String QUESTION_SIGN = \"?\";\n    public final static String AND_SIGN = \"&\";\n    /** # */\n    public final static String POUND = \"#\";\n    /** * */\n    public final static String ASTERISK = \"*\";\n\n    /** $ */\n    public final static String DOLLAR_SIGN = \"$\";\n\n    public final static String ELLIPSIS_THREE = \"...\";\n    public final static String ELLIPSIS_SIX = \"......\";\n\n    /** = */\n    public final static String EQUAL_SIGN = \"=\";\n    /** - */\n    public final static String MINUS_SIGN = \"-\";\n    public final static String PLUS_SIGN = \"+\";\n    public final static String MULTIPLICATION_SIGN = \"*\";\n    public final static String PERCENT = \"%\";\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/constant/TimeDimensionalityEnum.java",
    "content": "package com.sohu.cache.constant;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport org.apache.commons.lang.math.NumberUtils;\n\n/**\n * 时间维度枚举\n * \n * @author leifu\n * @Date 2016年8月1日\n * @Time 下午3:50:38\n */\npublic enum TimeDimensionalityEnum {\n    MINUTE(0, \"以分钟为维度\"),\n    HOUR(1, \"以小时为维度\");\n\n    private int index;\n\n    private String info;\n\n    private static final Map<Integer, TimeDimensionalityEnum> MAP = new HashMap<Integer, TimeDimensionalityEnum>();\n    static {\n        for (TimeDimensionalityEnum timeDimensionalityEnum : TimeDimensionalityEnum.values()) {\n            MAP.put(timeDimensionalityEnum.getIndex(), timeDimensionalityEnum);\n        }\n    }\n\n    private TimeDimensionalityEnum(int index, String info) {\n        this.index = index;\n        this.info = info;\n    }\n\n    public int getIndex() {\n        return index;\n    }\n\n    public String getInfo() {\n        return info;\n    }\n\n    public static TimeDimensionalityEnum getTimeDimensionalityEnumByIndex(String index) {\n        return MAP.get(NumberUtils.toInt(index));\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/constant/UserLoginTypeEnum.java",
    "content": "package com.sohu.cache.constant;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * 登录类型\n * \n * @author leifu\n * @Date 2016年6月15日\n * @Time 下午12:03:05\n */\npublic enum UserLoginTypeEnum {\n\n    SESSION(1, \"session\"),\n    COOKIE(2, \"cookie\");\n\n    private int type;\n\n    private String desc;\n    \n    private final static Map<Integer, UserLoginTypeEnum> MAP = new HashMap<Integer, UserLoginTypeEnum>();\n    static {\n        for (UserLoginTypeEnum userLoginTypeEnum : UserLoginTypeEnum.values()) {\n            MAP.put(userLoginTypeEnum.getType(), userLoginTypeEnum);\n        }\n    }\n\n    public static UserLoginTypeEnum getLoginTypeEnum(int type) {\n        return MAP.get(type);\n    }\n    \n    private UserLoginTypeEnum(int type, String desc) {\n        this.type = type;\n        this.desc = desc;\n    }\n\n    public int getType() {\n        return type;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/dao/AppAuditDao.java",
    "content": "package com.sohu.cache.dao;\n\nimport com.sohu.cache.entity.AppAudit;\n\nimport org.apache.ibatis.annotations.Param;\n\nimport java.util.List;\n\n/**\n * Created by yijunzhang on 14-10-20.\n */\npublic interface AppAuditDao {\n\n    /**\n     * 新增审核记录\n     * @param appAudit\n     */\n    public void insertAppAudit(AppAudit appAudit);\n\n    /**\n     * 查询所有等待审批的记录\n     */\n    public List<AppAudit> selectWaitAppAudits(@Param(\"status\") Integer status, @Param(\"type\") Integer type);\n\n    /**\n     * 按id查询\n     * @param id\n     * @return\n     */\n    public AppAudit getAppAudit(@Param(\"id\") long id);\n\n    /**\n     * 更新审核状态\n     */\n    public void updateAppAudit(@Param(\"id\") long id, @Param(\"status\") int status);\n    \n    /**\n     * 更新驳回理由\n     */\n    public void updateRefuseReason(@Param(\"id\") long id, @Param(\"refuseReason\") String refuseReason);\n\n    /**\n     * 通过appId获取所有审批记录\n     */\n    public List<AppAudit> getAppAuditByAppId(@Param(\"appId\")Long appId);\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/dao/AppAuditLogDao.java",
    "content": "package com.sohu.cache.dao;\n\nimport org.apache.ibatis.annotations.Param;\n\nimport com.sohu.cache.entity.AppAuditLog;\n\n\n/**\n * 应用审批日志记录\n * \n * @author leifu\n * @Time 2014年6月5日\n */\npublic interface AppAuditLogDao {\n\n    public int save(AppAuditLog appAuditLog);\n\n    /**\n     * 根据类型type(参考AppAuditLogTypeEnum)获取审批日志\n     * @param appAuditId\n     * @param type\n     * @return\n     */\n    public AppAuditLog getAuditByType(@Param(\"appAuditId\") Long appAuditId, @Param(\"type\") int type);\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/dao/AppClientCostTimeStatDao.java",
    "content": "package com.sohu.cache.dao;\n\nimport java.util.List;\n\nimport org.apache.ibatis.annotations.Param;\n\nimport com.sohu.cache.entity.AppClientCostTimeStat;\n\n/**\n * 客户端耗时dao\n * \n * @author leifu\n * @Date 2015年1月20日\n * @Time 上午11:50:01\n */\npublic interface AppClientCostTimeStatDao {\n\n    /**\n     * \n     * @param appClientCostTimeStat\n     */\n    void save(AppClientCostTimeStat appClientCostTimeStat);\n\n    /**\n     * 查询应用一段时间内某个命令、某对客户端和实例的耗时统计信息\n     * @param appId\n     * @param command\n     * @param instanceId\n     * @param clientIp\n     * @param startTime\n     * @param endTime\n     * @return\n     */\n    List<AppClientCostTimeStat> getAppCommandClientToInstanceStat(@Param(\"appId\") Long appId,\n            @Param(\"command\") String command, @Param(\"instanceId\") long instanceId,\n            @Param(\"clientIp\") String clientIp, @Param(\"startTime\") long startTime, @Param(\"endTime\") long endTime);\n\n    /**\n     * 批量更新\n     * @param appClientCostTimeStatList\n     * @return\n     */\n    int batchSave(@Param(\"appClientCostTimeStatList\") List<AppClientCostTimeStat> appClientCostTimeStatList);\n\n    /**\n     * 获取最小id\n     * @return\n     */\n    long getTableMinimumId();\n\n    /**\n     * 按照collectTime获取最小id\n     * @param collectTime\n     * @return\n     */\n    long getMinimumIdByCollectTime(@Param(\"collectTime\") long collectTime);\n\n    /**\n     * 按照id区间删除\n     * @param startId\n     * @param endId\n     */\n    long deleteByIds(@Param(\"startId\") long startId, @Param(\"endId\") long endId);\n\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/dao/AppClientCostTimeTotalStatDao.java",
    "content": "package com.sohu.cache.dao;\n\nimport java.util.List;\n\nimport org.apache.ibatis.annotations.Param;\n\nimport com.sohu.cache.entity.AppClientCostTimeTotalStat;\n\n/**\n * 基于应用全局耗时统计(uniquekey: app_id, command, collect_time)\n * @author leifu\n * @Date 2015年6月26日\n * @Time 下午4:24:24\n */\npublic interface AppClientCostTimeTotalStatDao {\n\n    /**\n     * 保存基于应用的耗时统计\n     * @param appClientCostTimeTotalStat\n     */\n    void save(AppClientCostTimeTotalStat appClientCostTimeTotalStat);\n\n    /**\n     * 获取应用指定时间内调用过的命令\n     * @param appId\n     * @param startTime\n     * @param endTime\n     * @return\n     */\n    List<String> getAppDistinctCommand(@Param(\"appId\") Long appId, @Param(\"startTime\") long startTime,\n            @Param(\"endTime\") long endTime);\n\n    /**\n     * 获取应用指定时间内某个命令的耗时统计\n     * @param appId\n     * @param command\n     * @param startTime\n     * @param endTime\n     * @return\n     */\n    List<AppClientCostTimeTotalStat> getAppClientCommandStat(@Param(\"appId\") Long appId,\n            @Param(\"command\") String command, @Param(\"startTime\") long startTime, @Param(\"endTime\") long endTime);\n\n    /**\n     * 批量保存\n     * @param appClientCostTimeTotalStatList\n     */\n    void batchSave(@Param(\"appClientCostTimeTotalStatList\") List<AppClientCostTimeTotalStat> appClientCostTimeTotalStatList);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/dao/AppClientExceptionStatDao.java",
    "content": "package com.sohu.cache.dao;\n\nimport java.util.List;\n\nimport org.apache.ibatis.annotations.Param;\n\nimport com.sohu.cache.entity.AppClientExceptionStat;\nimport com.sohu.cache.entity.ClientInstanceException;\nimport com.sohu.cache.web.util.Page;\n\n/**\n * 客户端异常dao\n * \n * @author leifu\n * @Date 2015年1月20日\n * @Time 上午11:50:06\n */\npublic interface AppClientExceptionStatDao {\n\n    /**\n     * 保存上报异常\n     * \n     * @param appClientExceptionStat\n     */\n    void save(AppClientExceptionStat appClientExceptionStat);\n\n    /**\n     * 获取客户端异常列表\n     * \n     * @param appId 应用id\n     * @param startTime 开始收集时间\n     * @param endTime 结束收集时间\n     * @param type 异常类型(ClientExceptionType)\n     * @param clientIp 客户端ip\n     * @return\n     */\n    List<AppClientExceptionStat> getAppExceptionList(@Param(\"appId\") Long appId, @Param(\"startTime\") long startTime,\n            @Param(\"endTime\") long endTime, @Param(\"type\") int type, @Param(\"clientIp\") String clientIp, @Param(\"page\") Page page);\n\n    /**\n     * 获取客户端异常个数\n     * \n     * @param appId 应用id\n     * @param startTime 开始收集时间\n     * @param endTime 结束收集时间\n     * @param type 异常类型(ClientExceptionType)\n     * @param clientIp 客户端ip\n     * @return\n     */\n    int getAppExceptionCount(@Param(\"appId\") Long appId, @Param(\"startTime\") long startTime,\n            @Param(\"endTime\") long endTime, @Param(\"type\") int type, @Param(\"clientIp\") String clientIp);\n\n    /**\n     * 大于collectTime后实例的异常统计\n     * @param ip\n     * @param collectTime\n     * @return\n     */\n    List<ClientInstanceException> getInstanceExceptionStat(@Param(\"ip\") String ip, @Param(\"collectTime\") long collectTime);\n\n    /**\n     * 批量保存\n     * @param appClientExceptionStatList\n     * @return\n     */\n    int batchSave(@Param(\"appClientExceptionStatList\") List<AppClientExceptionStat> appClientExceptionStatList);\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/dao/AppClientReportDataSizeDao.java",
    "content": "package com.sohu.cache.dao;\n\nimport com.sohu.cache.entity.AppClientDataSizeStat;\n\n/**\n * 客户端内收集数据map的尺寸查询\n * @author leifu\n * @Date 2015年7月13日\n * @Time 下午3:26:48\n */\npublic interface AppClientReportDataSizeDao {\n    \n    /**\n     * 保存-客户端收集map的尺寸信息\n     * @param appClientDataSizeStat\n     */\n    void save(AppClientDataSizeStat appClientDataSizeStat);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/dao/AppClientValueStatDao.java",
    "content": "package com.sohu.cache.dao;\n\nimport java.util.List;\n\nimport org.apache.ibatis.annotations.Param;\n\nimport com.sohu.cache.entity.AppClientValueDistriSimple;\nimport com.sohu.cache.entity.AppClientValueDistriStatTotal;\n\n/**\n * \n * @author leifu\n * @Date 2016年5月9日\n * @Time 下午5:25:52\n */\npublic interface AppClientValueStatDao {\n\n    /**\n     * 按照时间区间查询客户端值分布\n     * @param appId\n     * @param startTime\n     * @param endTime\n     * @return\n     */\n    List<AppClientValueDistriSimple> getAppValueDistriList(@Param(\"appId\") long appId, @Param(\"startTime\") long startTime, @Param(\"endTime\") long endTime);\n\n    /**\n     * 批量保存\n     * @param appClientValueDistriStatList\n     */\n    void batchSave(@Param(\"appClientValueDistriStatTotalList\") List<AppClientValueDistriStatTotal> appClientValueDistriStatTotalList);\n    \n    \n    /**\n     * 保存\n     * @param appClientValueDistriStatTotal\n     */\n    int save(AppClientValueDistriStatTotal appClientValueDistriStatTotal);\n\n    /**\n     * 删除指定收集时间前的数据\n     * @param collectTime\n     * @return\n     */\n    int deleteBeforeCollectTime(@Param(\"collectTime\") long collectTime);\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/dao/AppClientVersionDao.java",
    "content": "package com.sohu.cache.dao;\n\nimport java.util.List;\n\nimport org.apache.ibatis.annotations.Param;\n\nimport com.sohu.cache.entity.AppClientVersion;\n\n/**\n * 客户端版本dao\n * @author leifu\n * @Date 2015年2月2日\n * @Time 上午10:36:20\n */\npublic interface AppClientVersionDao {\n\n    /**\n     * 保存或者更新客户端版本信息\n     * @param appClientVersion\n     */\n    void saveOrUpdateClientVersion(AppClientVersion appClientVersion);\n\n    /**\n     * 根据客户端ip获取所有的appId\n     * @param clientIp\n     * @return\n     */\n    List<AppClientVersion> getByClientIp(@Param(\"clientIp\") String clientIp);\n\n    /**\n     * 获取应用的所有客户端版本信息\n     * @param appId\n     * @return\n     */\n    List<AppClientVersion> getAppAllClientVersion(@Param(\"appId\") long appId);\n    \n    /**\n     * 获取所有版本，暂时不分页\n     * @return\n     */\n    List<AppClientVersion> getAll(@Param(\"appId\") long appId);\n\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/dao/AppDailyDao.java",
    "content": "package com.sohu.cache.dao;\n\nimport org.apache.ibatis.annotations.Param;\n\nimport com.sohu.cache.entity.AppDailyData;\n\n/**\n * 应用日报\n * \n * @author leifu\n * @Date 2017年1月19日\n * @Time 上午10:25:39\n */\npublic interface AppDailyDao {\n\n    void save(AppDailyData appDailyData);\n    \n    AppDailyData getAppDaily(@Param(\"appId\") long appId, @Param(\"date\") String date);\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/dao/AppDao.java",
    "content": "package com.sohu.cache.dao;\n\nimport java.util.List;\n\nimport com.sohu.cache.entity.AppDesc;\nimport com.sohu.cache.entity.AppSearch;\n\nimport org.apache.ibatis.annotations.Param;\n\n/**\n * 基于app的dao操作\n * @author leifu\n * @Date 2014年5月15日\n * @Time 下午1:58:22\n */\npublic interface AppDao {\n    /**\n     * 通过appId获取对应的app\n     * @param appId\n     * @return\n     */\n    public AppDesc getAppDescById(@Param(\"appId\") long appId);\n    \n    /**\n     * 通过应用名获取对应app\n     * @param appName\n     * @return\n     */\n\tpublic AppDesc getByAppName(@Param(\"appName\") String appName);\n\t\n\t/**\n\t * 保存app\n\t * @param appDesc\n\t * @return\n\t */\n\tpublic int save(AppDesc appDesc);\n\t\n\t/**\n\t * 更新app\n\t * @param appDesc\n\t * @return\n\t */\n\tpublic int update(AppDesc appDesc);\n\t\n\t/**\n\t * 删除app\n\t * @param id\n\t * @return\n\t */\n\tpublic int delete(@Param(\"id\") Long id);\n\n\t/**\n\t * 获取用户拥有的应用\n\t * @param userId\n\t * @return\n\t */\n    public List<AppDesc> getAppDescList(@Param(\"userId\") long userId);\n    \n    /**\n     * 获取应用拥有的应用个数\n     * @param userId\n     * @return\n     */\n    public int getUserAppCount(@Param(\"userId\") long userId);\n\n    /**\n     * 获取所有应用\n     * @param userId\n     * @return\n     */\n    public List<AppDesc> getAllAppDescList(AppSearch appSearch);\n\n    /**\n     * 获取应用个数\n     * @param appSearch\n     * @return\n     */\n    public int getAllAppCount(AppSearch appSearch);\n\n    /**\n     * 更新appKey\n     * @param appId\n     * @param appKey\n     */\n    public void updateAppKey(@Param(\"appId\") long appId, @Param(\"appKey\") String appKey);\n\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/dao/AppDataMigrateStatusDao.java",
    "content": "package com.sohu.cache.dao;\n\nimport java.util.List;\n\nimport org.apache.ibatis.annotations.Param;\n\nimport com.sohu.cache.entity.AppDataMigrateSearch;\nimport com.sohu.cache.entity.AppDataMigrateStatus;\n\n/**\n * 迁移状态Dao\n * \n * @author leifu\n * @Date 2016-6-9\n * @Time 下午5:25:53\n */\npublic interface AppDataMigrateStatusDao {\n\n    int save(AppDataMigrateStatus appDataMigrateStatus);\n\n    int getMigrateMachineStatCount(@Param(\"migrateMachineIp\") String migrateMachineIp, @Param(\"status\") int status);\n\n    AppDataMigrateStatus get(@Param(\"id\") long id);\n\n    int updateStatus(@Param(\"id\") long id, @Param(\"status\") int status);\n\n    List<AppDataMigrateStatus> search(@Param(\"appDataMigrateSearch\") AppDataMigrateSearch appDataMigrateSearch);\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/dao/AppInstanceClientRelationDao.java",
    "content": "package com.sohu.cache.dao;\n\nimport java.util.Date;\nimport java.util.List;\n\nimport org.apache.ibatis.annotations.Param;\n\nimport com.sohu.cache.entity.AppInstanceClientRelation;\n\n/**\n * 应用下节点和客户端关系Dao\n * \n * @author leifu\n * @Date 2016年5月4日\n * @Time 上午9:19:44\n */\npublic interface AppInstanceClientRelationDao {\n\n    int save(AppInstanceClientRelation appInstanceClientRelation);\n\n    int batchSave(@Param(\"appInstanceClientRelationList\") List<AppInstanceClientRelation> appInstanceClientRelationList);\n\n    int isExist(AppInstanceClientRelation appInstanceClientRelation);\n\n    List<AppInstanceClientRelation> getAppInstanceClientRelationList(@Param(\"appId\") Long appId, @Param(\"day\") Date day);\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/dao/AppStatsDao.java",
    "content": "package com.sohu.cache.dao;\n\nimport com.sohu.cache.entity.AppCommandGroup;\nimport com.sohu.cache.entity.AppCommandStats;\nimport com.sohu.cache.entity.AppStats;\nimport com.sohu.cache.entity.TimeDimensionality;\n\nimport org.apache.ibatis.annotations.Param;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * Created by yijunzhang on 14-6-9.\n */\npublic interface AppStatsDao {\n\n    public static final int MINUTE_DIMENSIONALITY = 0;\n\n    public static final int HOUR_DIMENSIONALITY = 1;\n\n    /**\n     * 插入或更新AppStats分钟统计\n     */\n    public void mergeMinuteAppStats(AppStats appStats);\n\n    /**\n     * 插入或更新AppCommandStats分钟统计\n     */\n    public void mergeMinuteCommandStatus(AppCommandStats commandStats);\n\n    /**\n     * 插入或更新AppStats小时统计\n     */\n    public void mergeHourAppStats(AppStats appStats);\n\n    /**\n     * 插入或更新AppCommandStats小时统计\n     */\n    public void mergeHourCommandStatus(AppCommandStats commandStats);\n    \n    /**\n     * 按时间查询应用统计\n     *\n     * @param appId 应用id\n     * @param td    时间维度\n     * @return\n     */\n    public List<AppStats> getAppStatsList(@Param(\"appId\") long appId, @Param(\"td\") TimeDimensionality td);\n\n    /**\n     * 按照分钟查询应用统计\n     * @param appId\n     * @param beginTime\n     * @param endTime\n     * @return\n     */\n    public List<AppStats> getAppStatsByMinute(@Param(\"appId\") long appId, @Param(\"beginTime\") long beginTime, @Param(\"endTime\") long endTime);\n\n    /**\n     * 按照小时查询应用统计\n     * @param appId\n     * @param beginTime\n     * @param endTime\n     * @return\n     */\n    public List<AppStats> getAppStatsByHour(@Param(\"appId\") long appId, @Param(\"beginTime\") long beginTime, @Param(\"endTime\") long endTime);\n\n    /**\n     * 按时间查询应用命令统计\n     *\n     * @param appId       应用id\n     * @param commandName 命令名称\n     * @param td          时间维度\n     * @return\n     */\n    public List<AppCommandStats> getAppCommandStatsList(@Param(\"appId\") long appId, @Param(\"commandName\") String commandName,\n                                                        @Param(\"td\") TimeDimensionality td);\n\n    /**\n     * 按应用命令统计\n     *\n     * @param appId       应用id\n     * @param td          时间维度\n     * @return\n     */\n    public List<AppCommandStats> getAppAllCommandStatsList(@Param(\"appId\") long appId,@Param(\"td\") TimeDimensionality td);\n\n    /**\n     * \n     * @param appId\n     * @param beginTime\n     * @param endTime\n     * @param commandName\n     * @return\n     */\n    public List<AppCommandStats> getAppCommandStatsListByMinuteWithCommand(@Param(\"appId\") long appId, @Param(\"beginTime\") long beginTime, @Param(\"endTime\") long endTime, @Param(\"commandName\") String commandName);\n\n    /**\n     * \n     * @param appId\n     * @param beginTime\n     * @param endTime\n     * @param commandName\n     * @return\n     */\n    public List<AppCommandStats> getAppCommandStatsListByHourWithCommand(@Param(\"appId\") long appId, @Param(\"beginTime\") long beginTime, @Param(\"endTime\") long endTime, @Param(\"commandName\") String commandName);\n\n    /**\n     * \n     * @param appId\n     * @param beginTime\n     * @param endTime\n     * @return\n     */\n    public List<AppCommandStats> getAppAllCommandStatsListByMinute(@Param(\"appId\") long appId, @Param(\"beginTime\") long beginTime, @Param(\"endTime\") long endTime);\n\n    /**\n     * \n     * @param appId\n     * @param beginTime\n     * @param endTime\n     * @return\n     */\n    public List<AppCommandStats> getAppAllCommandStatsListByHour(@Param(\"appId\") long appId, @Param(\"beginTime\") long beginTime, @Param(\"endTime\") long endTime);\n\n    /**\n     * 查询一天中应用的命令执行次数的topN\n     *\n     * @param appId 应用id\n     * @param td    时间维度\n     * @return\n     */\n    public List<AppCommandStats> getTopAppCommandStatsList(@Param(\"appId\") long appId, @Param(\"td\") TimeDimensionality td, @Param(\"top\") int top);\n\n    /**\n     * 查询一段时间内，各个命令执行次数分布\n     *\n     * @param appId 应用id\n     * @param td    时间维度\n     * @return\n     */\n    public List<AppCommandStats> getTopAppCommandGroupSum(@Param(\"appId\") long appId, @Param(\"td\") TimeDimensionality td, @Param(\"top\") int top);\n    \n    /**\n     * 获取一定时间内命令峰值\n     *\n     * @param appId\n     * @param commandName\n     * @param td          时间维度\n     * @return\n     */\n    public AppCommandStats getCommandClimax(@Param(\"appId\") long appId, @Param(\"commandName\") String commandName, @Param(\"td\") TimeDimensionality td);\n    \n    public AppCommandStats getCommandClimaxCount(@Param(\"appId\") long appId, @Param(\"commandName\") String commandName, @Param(\"td\") TimeDimensionality td);\n    \n    public AppCommandStats getCommandClimaxCreateTime(@Param(\"appId\") long appId, @Param(\"commandName\") String commandName, @Param(\"commandCount\") long commandCount, @Param(\"td\") TimeDimensionality td);\n    \n\n    /**\n     * 获取应用命令调用次数分布\n     *\n     * @param appId\n     * @param td    时间维度\n     * @return\n     */\n    public List<AppCommandGroup> getAppCommandGroup(@Param(\"appId\") long appId, @Param(\"td\") TimeDimensionality td);\n\n    /**\n     * 应用分钟统计\n     * @param appId\n     * @param beginTime\n     * @param endTime\n     * @return\n     */\n    public Map<String, Object> getAppMinuteStat(@Param(\"appId\") long appId, @Param(\"beginTime\") long beginTime, @Param(\"endTime\") long endTime);\n\n    \n\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/dao/AppToUserDao.java",
    "content": "package com.sohu.cache.dao;\n\nimport java.util.List;\n\nimport org.apache.ibatis.annotations.Param;\n\nimport com.sohu.cache.entity.AppToUser;\n\n\n/**\n * 用户-应用对应关系\n * \n * @author leifu\n * @Time 2014年6月5日\n */\npublic interface AppToUserDao {\n    \n    List<AppToUser> getByUserId(@Param(\"userId\") Long userId);\n\n    Long save(AppToUser appToUser);\n\n    void deleteByAppId(@Param(\"appId\") Long appId);\n\n    List<AppToUser> getByAppId(@Param(\"appId\") Long appId);\n\n    void deleteAppToUser(@Param(\"appId\") long appId, @Param(\"userId\") long userId);\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/dao/AppUserDao.java",
    "content": "package com.sohu.cache.dao;\n\nimport java.util.List;\n\nimport org.apache.ibatis.annotations.Param;\n\nimport com.sohu.cache.entity.AppUser;\n\n/**\n * 用户管理dao\n * @author leifu\n * @Time 2014年6月5日\n */\npublic interface AppUserDao {\n\n\tpublic AppUser get(@Param(\"id\") Long id);\n\t\n\tpublic int save(AppUser user);\n\t\n\tpublic int update(AppUser user);\n\t\n\tpublic int delete(@Param(\"id\") Long id);\n\t\n\tpublic AppUser getByName(@Param(\"name\") String name);\n\n    public List<AppUser> getUserList(@Param(\"chName\") String chName);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/dao/ConfigDao.java",
    "content": "package com.sohu.cache.dao;\n\nimport java.util.List;\n\nimport org.apache.ibatis.annotations.Param;\n\nimport com.sohu.cache.entity.SystemConfig;\n\n/**\n * 配置修改dao\n * \n * @author leifu\n * @Date 2016年5月23日\n * @Time 下午12:51:45\n */\npublic interface ConfigDao {\n\n    /**\n     * 更新配置对key-value\n     * \n     * @param configKey\n     * @param configValue\n     */\n    public void update(@Param(\"configKey\") String configKey, @Param(\"configValue\") String configValue);\n\n    /**\n     * 获取配置列表\n     * \n     * @param status\n     * @return\n     */\n    public List<SystemConfig> getConfigList(@Param(\"status\") int status);\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/dao/InstanceAlertConfigDao.java",
    "content": "package com.sohu.cache.dao;\n\nimport java.util.Date;\nimport java.util.List;\n\nimport org.apache.ibatis.annotations.Param;\n\nimport com.sohu.cache.entity.InstanceAlertConfig;\n\n/**\n * 实例报警配置Dao\n * @author leifu\n * @Date 2017年5月19日\n * @Time 上午11:56:56\n */\npublic interface InstanceAlertConfigDao {\n    \n    int save(InstanceAlertConfig instanceAlertConfig);\n\n    List<InstanceAlertConfig> getAll();\n    \n    List<InstanceAlertConfig> getByType(@Param(\"type\") int type);\n    \n    List<InstanceAlertConfig> getByAlertConfig(@Param(\"alertConfig\") String alertConfig);\n\n    InstanceAlertConfig get(@Param(\"id\") int id);\n\n    int remove(@Param(\"id\") int id);\n    \n    void update(@Param(\"id\") long id, @Param(\"alertValue\") String alertValue, @Param(\"checkCycle\") int checkCycle);\n    \n    void updateLastCheckTime(@Param(\"id\") long id, @Param(\"lastCheckTime\") Date lastCheckTime);\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/dao/InstanceConfigDao.java",
    "content": "package com.sohu.cache.dao;\n\nimport java.util.List;\n\nimport org.apache.ibatis.annotations.Param;\n\nimport com.sohu.cache.entity.InstanceConfig;\n\n/**\n * 配置模板Dao\n * \n * @author leifu\n * @Date 2016年6月22日\n * @Time 下午5:46:37\n */\npublic interface InstanceConfigDao {\n    \n    /**\n     * 获取所有配置模板\n     * @return\n     */\n    List<InstanceConfig> getAllInstanceConfig();\n\n    /**\n     * 根据type获取配置模板列表\n     * \n     * @param type\n     * @return\n     */\n    List<InstanceConfig> getByType(@Param(\"type\") int type);\n\n    /**\n     * 保存或者更新配置模板\n     * \n     * @param instanceConfig\n     * @return\n     */\n    int saveOrUpdate(InstanceConfig instanceConfig);\n\n    /**\n     * 根据id获取配置模板\n     * \n     * @param id\n     * @return\n     */\n    InstanceConfig getById(@Param(\"id\") long id);\n\n    /**\n     * 根据configKey和type获取配置\n     * \n     * @param configKey\n     * @param type\n     * @return\n     */\n    InstanceConfig getByConfigKeyAndType(@Param(\"configKey\") String configKey, @Param(\"type\") int type);\n\n    /**\n     * 更改配置状态\n     * @param id\n     * @param status\n     * @return\n     */\n    int updateStatus(@Param(\"id\") long id, @Param(\"status\") int status);\n\n    /**\n     * 删除配置\n     * @param id\n     * @return\n     */\n    int remove(@Param(\"id\") long id);\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/dao/InstanceDao.java",
    "content": "package com.sohu.cache.dao;\n\nimport com.sohu.cache.entity.InstanceInfo;\n\nimport org.apache.ibatis.annotations.Param;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 基于instance的dao操作\n * <p/>\n * User: lingguo\n * Date: 14-6-3\n * Time: 下午3:58\n */\npublic interface InstanceDao {\n    /**\n     * 通过type查询实例列表\n     *\n     * @param type\n     * @return\n     */\n    public List<InstanceInfo> getInstListByType(@Param(\"type\") int type);\n\n    /**\n     * 查询appId下的所有instance\n     *\n     * @param appId\n     * @return\n     */\n    public List<InstanceInfo> getInstListByAppId(@Param(\"appId\") long appId);\n\n    /**\n     * 通过host和port查询一个实例信息\n     *\n     * @param ip\n     * @param port\n     * @return\n     */\n    public InstanceInfo getInstByIpAndPort(@Param(\"ip\") String ip, @Param(\"port\") int port);\n\n    /**\n     * 通过host和port查询一个实例信息\n     *\n     * @param ip\n     * @param port\n     * @return\n     */\n    public InstanceInfo getAllInstByIpAndPort(@Param(\"ip\") String ip, @Param(\"port\") int port);\n\n    /**\n     * 通过所有实例列表(包括:0:节点异常,1:正常启用)\n     *\n     * @return\n     */\n    public List<InstanceInfo> getAllInsts();\n\n    /**\n     * 通过host和port查询一个实例信息\n     *\n     * @param ip\n     * @param port\n     * @return\n     */\n    public int getCountByIpAndPort(@Param(\"ip\") String ip, @Param(\"port\") int port);\n\n    /**\n     * 保存一个实例\n     *\n     * @param instanceInfo\n     */\n    public void saveInstance(InstanceInfo instanceInfo);\n\n    /**\n     * 根据ip和type查询实例数量\n     *\n     * @param ip\n     * @param type\n     * @return\n     */\n    public int getInstanceTypeCount(@Param(\"ip\") String ip, @Param(\"type\") int type);\n\n\n    public InstanceInfo getInstanceInfoById(@Param(\"id\") long id);\n\n    public int getMemoryByHost(String host);\n\n    public int update(InstanceInfo instanceInfo);\n\n    /**\n     * 获取一台机器的所有实例\n     * @param ip\n     * @return\n     */\n    public List<InstanceInfo> getInstListByIp(@Param(\"ip\") String ip);\n    \n    \n    /**\n     * 机器实例数map\n     * @return\n     */\n    public List<Map<String, Object>> getMachineInstanceCountMap();\n    \n\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/dao/InstanceFaultDao.java",
    "content": "package com.sohu.cache.dao;\n\nimport com.sohu.cache.entity.InstanceFault;\n\nimport java.util.List;\n\n/**\n * Created by yijunzhang on 14-12-29.\n */\npublic interface InstanceFaultDao {\n\n    /**\n     * 添加InstanceFault实例\n     *\n     * @return\n     */\n    int insert(InstanceFault instanceFault);\n\n    /**\n     * 实例故障列表\n     *\n     * @param instId\n     * @return\n     */\n    List<InstanceFault> getListByInstId(int instId);\n\n    /**\n     * 应用故障列表\n     *\n     * @param appId\n     * @return\n     */\n    List<InstanceFault> getListByAppId(long appId);\n\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/dao/InstanceReshardProcessDao.java",
    "content": "package com.sohu.cache.dao;\n\nimport java.util.Date;\nimport java.util.List;\n\nimport org.apache.ibatis.annotations.Param;\n\nimport com.sohu.cache.entity.InstanceReshardProcess;\n\n\n/**\n * 实例Reshard进度保存\n * @author leifu\n * @Date 2017年6月24日\n * @Time 下午7:17:36\n */\npublic interface InstanceReshardProcessDao {\n\n    int save(InstanceReshardProcess instanceReshardProcess);\n    \n    List<InstanceReshardProcess> getByAuditId(@Param(\"auditId\") long auditId);\n    \n    int updateStatus(@Param(\"id\") long id, @Param(\"status\") int status);\n    \n    int updateEndTime(@Param(\"id\") long id, @Param(\"endTime\") Date endTime);\n    \n    int increaseFinishSlotNum(@Param(\"id\") long id);\n\n    int updateMigratingSlot(@Param(\"id\") int id, @Param(\"migratingSlot\") int migratingSlot);\n\n    InstanceReshardProcess get(@Param(\"id\") int id);\n\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/dao/InstanceSlowLogDao.java",
    "content": "package com.sohu.cache.dao;\n\nimport com.sohu.cache.entity.InstanceSlowLog;\n\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Map;\n\nimport org.apache.ibatis.annotations.Param;\n\n/**\n * 实例慢查询dao\n * \n * @author leifu\n * @Date 2016年2月22日\n * @Time 下午1:48:43\n */\npublic interface InstanceSlowLogDao {\n\n    /**\n     * 批量报错实例慢查询\n     * @param instanceSlowLogList\n     */\n    int batchSave(@Param(\"instanceSlowLogList\") List<InstanceSlowLog> instanceSlowLogList);\n\n    /**\n     * 按照应用id获取慢查询列表\n     * @param appId\n     * @return\n     */\n    List<InstanceSlowLog> getByAppId(@Param(\"appId\") long appId);\n\n    /**\n     * 搜索慢查询日志\n     * @param appId\n     * @param startTime\n     * @param endTime\n     * @param limit\n     * @return\n     */\n    List<InstanceSlowLog> search(@Param(\"appId\") long appId, @Param(\"startDate\") Date startDate, @Param(\"endDate\") Date endDate);\n\n    /**\n     * \n     * @param appId\n     * @param startDate\n     * @param endDate\n     * @return\n     */\n    List<Map<String, Object>> getInstanceSlowLogCountMapByAppId(@Param(\"appId\") long appId, @Param(\"startDate\") Date startDate, @Param(\"endDate\") Date endDate);\n    \n    \n    /**\n     * 获取指定日期慢查询个数\n     * @param appId\n     * @param startDate\n     * @param endDate\n     * @return\n     */\n    int getAppSlowLogCount(@Param(\"appId\") long appId, @Param(\"startDate\") Date startDate, @Param(\"endDate\") Date endDate);\n    \n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/dao/InstanceStatsDao.java",
    "content": "package com.sohu.cache.dao;\n\nimport com.sohu.cache.entity.StandardStats;\nimport com.sohu.cache.entity.InstanceStats;\nimport org.apache.ibatis.annotations.Param;\n\nimport java.util.Date;\nimport java.util.List;\n\n/**\n * 实例统计相关DAO\n */\npublic interface InstanceStatsDao {\n\n    public void updateInstanceStats(InstanceStats instanceStats);\n\n    public InstanceStats getInstanceStatsByHost(@Param(\"ip\") String ip, @Param(\"port\") long port);\n\n    public InstanceStats getInstanceStatsByInsId(@Param(\"id\") long id);\n\n    public List<InstanceStats> getInstanceStatsByAppId(@Param(\"appId\") long appId);\n\n    public List<InstanceStats> getInstanceStats();\n\n    public List<InstanceStats> getInstanceStatsByIp(@Param(\"ip\") String ip);\n\n    public int mergeStandardStats(StandardStats standardStats);\n\n    public StandardStats getStandardStats(@Param(\"collectTime\") long collectTime, @Param(\"ip\") String ip,\n            @Param(\"port\") int port, @Param(\"dbType\") String dbType);\n\n    public List<StandardStats> getDiffJsonList(@Param(\"beginTime\") long beginTime, @Param(\"endTime\") long endTime,\n            @Param(\"ip\") String ip, @Param(\"port\") int port, @Param(\"dbType\") String dbType);\n\n    public int deleteStandardStatsByCreatedTime(@Param(\"createdTime\") Date createdTime);\n\n    public int deleteStandardStatsByScanTime(@Param(\"startTime\") Date startTime,@Param(\"endTime\") Date endTime);\n\n    public List<StandardStats> getStandardStatsByCreateTime(@Param(\"beginTime\") Date beginTime, @Param(\"endTime\") Date endTime, @Param(\"dbType\") String dbType);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/dao/MachineDao.java",
    "content": "package com.sohu.cache.dao;\n\nimport com.sohu.cache.entity.MachineInfo;\n\nimport org.apache.ibatis.annotations.Param;\n\nimport java.util.List;\n\n/**\n * 机器相关的操作\n *\n * User: lingguo\n * Date: 14-6-12\n * Time: 下午2:33\n */\npublic interface MachineDao {\n\n    /**\n     * 返回所有可用的机器资源\n     *\n     * @return\n     */\n    public List<MachineInfo> getAllMachines();\n\n    /**\n     * 通过ip查询机器信息\n     *\n     * @param ip\n     * @return\n     */\n    public MachineInfo getMachineInfoByIp(@Param(\"ip\") String ip);\n    \n    /**\n     * 通过ip模糊查询机器信息\n     * @param ipLike\n     * @return\n     */\n    public List<MachineInfo> getMachineInfoByLikeIp(@Param(\"ipLike\")String ipLike);\n\n\n    /**\n     * 保存一条机器信息\n     *\n     * @param machineInfo\n     */\n    public void saveMachineInfo(MachineInfo machineInfo);\n\n    /**\n     * 根据ip删除一台机器的信息；\n     *\n     * @param ip\n     */\n    public void removeMachineInfoByIp(@Param(\"ip\") String ip);\n    \n    /**\n     * 通过type查询机器列表\n     * @param type\n     * @return\n     */\n    public List<MachineInfo> getMachineInfoByType(@Param(\"type\") int type);\n    \n    /**\n     * 更新机器type\n     * @return\n     */\n    public int updateMachineType(@Param(\"id\") long id, @Param(\"type\") int type);\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/dao/MachineStatsDao.java",
    "content": "package com.sohu.cache.dao;\n\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.entity.InstanceStats;\nimport com.sohu.cache.entity.MachineStats;\n\nimport org.apache.ibatis.annotations.Param;\n\nimport java.util.List;\n\n/**\n * Created by yijunzhang on 14-6-25.\n */\npublic interface MachineStatsDao {\n\n    /**\n     * 插入或更新machineInfo\n     */\n    public void mergeMachineStats(MachineStats machineStats);\n\n    /**\n     * 查询机器下的所有实例的信息\n     *\n     * @param ip\n     * @return\n     */\n    public List<InstanceInfo> getInstInfoOfMachine(@Param(\"ip\") String ip);\n\n    /**\n     * 查询ip所在的机器的最新状态信息\n     *\n     * @param ip    ip\n     * @return      机器的最新状态\n     */\n    public MachineStats getMachineStatsByIp(@Param(\"ip\") String ip);\n\n    /**\n     * 根据机器的hostId查询机器的最新状态信息\n     *\n     * @param hostId\n     * @return\n     */\n    public MachineStats getMachineStatsByHostId(@Param(\"hostId\") long hostId);\n\n    /**\n     * 查询机器下的所有实例的最新状态信息\n     *\n     * @param hostId    机器的hostId\n     * @return          该机器下所有实例的最新统计状态\n     */\n    public List<InstanceStats> getInstStatOfMachine(@Param(\"hostId\") long hostId);\n\n    /**\n     * 分页查询机器统计\n     * @param ipLike\n     * @return\n     */\n    public List<MachineStats> getMachineStats(@Param(\"ipLike\") String ipLike);\n\n    /**\n     * 获取全部机器统计\n     * @return\n     */\n    public List<MachineStats> getAllMachineStats();\n\n    /**\n     * 删除机器统计信息\n     * @param ip\n     * @return\n     */\n    public void deleteMachineStatsByIp(@Param(\"ip\") String ip);\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/dao/MemFaultDao.java",
    "content": "package com.sohu.cache.dao;\n\nimport java.util.List;\n\nimport com.sohu.cache.entity.InstanceFault;\n\n/**\n * 故障管理\n * @author leifu\n * @Date 2015年3月2日\n * @Time 下午2:02:07\n */\npublic interface MemFaultDao {\n    \n\t/**\n\t * 返回所有故障\n\t * @return\n\t */\n    List<InstanceFault> getMemFaultList();\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/dao/QuartzDao.java",
    "content": "package com.sohu.cache.dao;\n\nimport com.sohu.cache.entity.TriggerInfo;\n\nimport java.util.List;\n\n/**\n * quartz相关的dao操作\n *\n * @author: lingguo\n * @time: 2014/10/13 14:44\n */\npublic interface QuartzDao {\n\n    public List<TriggerInfo> getTriggersByJobGroup(String jobGroup);\n\n    public List<TriggerInfo> getAllTriggers();\n\n    public List<TriggerInfo> searchTriggerByNameOrGroup(String queryString);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/dao/ServerStatusDao.java",
    "content": "package com.sohu.cache.dao;\n\nimport java.util.List;\n\nimport org.apache.ibatis.annotations.Param;\n\nimport com.sohu.cache.entity.ServerInfo;\nimport com.sohu.cache.entity.ServerStatus;\nimport com.sohu.cache.server.data.Server;\n\n/**\n * 服务器状态信息持久化\n */\npublic interface ServerStatusDao {\n\n\t/**\n\t * 查询服务器基本信息\n\t * @param ip\n\t * @return @ServerInfo\n\t */\n\tpublic ServerInfo queryServerInfo(@Param(\"ip\") String ip);\n\t\n\t/**\n\t * 保存服务器发行版信息\n\t * @param ip\n\t * @param dist from /etc/issue\n\t */\n\tpublic void saveServerInfo(@Param(\"ip\") String ip, @Param(\"dist\") String dist);\n\t\n\t/**\n\t * 删除服务器信息\n\t * @param ip\n\t * @return 删除的数量\n\t */\n\tpublic Integer deleteServerInfo(@Param(\"ip\") String ip);\n\t\n\t/**\n\t * 保存/更新服务器信息\n\t * @param server\n\t * @return 影响的行数\n\t */\n\tpublic Integer saveAndUpdateServerInfo(@Param(\"server\")Server server);\n\t\n\t/**\n\t * 查询服务器状态\n\t * @param ip\n\t * @param date\n\t * @return List<ServerStatus>\n\t */\n\tpublic List<ServerStatus> queryServerStatus(@Param(\"ip\") String ip, \n\t\t\t@Param(\"cdate\") String date);\n\t\n\t/**\n\t * 查询服务器状态\n\t * @param ip\n\t * @param date\n\t * @return List<ServerStatus>\n\t */\n\tpublic List<ServerStatus> queryServerOverview(@Param(\"ip\") String ip, \n\t\t\t@Param(\"cdate\") String date);\n\t\n\t/**\n\t * 查询服务器状态\n\t * @param ip\n\t * @param date\n\t * @return List<ServerStatus>\n\t */\n\tpublic List<ServerStatus> queryServerCpu(@Param(\"ip\") String ip, \n\t\t\t@Param(\"cdate\") String date);\n\t\n\t/**\n\t * 查询服务器状态\n\t * @param ip\n\t * @param date\n\t * @return List<ServerStatus>\n\t */\n\tpublic List<ServerStatus> queryServerNet(@Param(\"ip\") String ip, \n\t\t\t@Param(\"cdate\") String date);\n\t\n\t/**\n\t * 查询服务器状态\n\t * @param ip\n\t * @param date\n\t * @return List<ServerStatus>\n\t */\n\tpublic List<ServerStatus> queryServerDisk(@Param(\"ip\") String ip, \n\t\t\t@Param(\"cdate\") String date);\n\t\n\t/**\n\t * 保存服务器状态\n\t * @param Server\n\t */\n\tpublic void saveServerStat(@Param(\"server\") Server server);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/AppAudit.java",
    "content": "package com.sohu.cache.entity;\n\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\n\n/**\n * Created by yijunzhang on 14-10-20.\n */\npublic class AppAudit {\n\n    private long id;\n\n    private long appId;\n\n    private long userId;\n\n    private String userName;\n\n    /**\n     * 申请类型:0:申请应用,1:应用扩容,2:修改配置\n     */\n    private int type;\n\n    /**\n     * 预留参数1\n     */\n    private String param1;\n    /**\n     * 预留参数2\n     */\n    private String param2;\n    /**\n     * 预留参数3\n     */\n    private String param3;\n\n    /**\n     * 申请描述\n     */\n    private String info;\n\n    /**\n     * 0:等待审批; 1:审批通过; -1:驳回\n     */\n    private int status;\n\n    private Date createTime;\n\n    private Date modifyTime;\n\n    /**\n     * 驳回原因\n     */\n    private String refuseReason;\n\n    private AppDesc appDesc;\n    \n    private AppAuditLog appAuditLog;\n\n    public long getId() {\n        return id;\n    }\n\n    public void setId(long id) {\n        this.id = id;\n    }\n\n    public long getAppId() {\n        return appId;\n    }\n\n    public void setAppId(long appId) {\n        this.appId = appId;\n    }\n\n    public long getUserId() {\n        return userId;\n    }\n\n    public void setUserId(long userId) {\n        this.userId = userId;\n    }\n\n    public int getType() {\n        return type;\n    }\n\n    public void setType(int type) {\n        this.type = type;\n    }\n\n    public String getParam1() {\n        return param1;\n    }\n\n    public void setParam1(String param1) {\n        this.param1 = param1;\n    }\n\n    public String getParam2() {\n        return param2;\n    }\n\n    public void setParam2(String param2) {\n        this.param2 = param2;\n    }\n\n    public String getParam3() {\n        return param3;\n    }\n\n    public void setParam3(String param3) {\n        this.param3 = param3;\n    }\n\n    public String getInfo() {\n        return info;\n    }\n\n    public void setInfo(String info) {\n        this.info = info;\n    }\n\n    public int getStatus() {\n        return status;\n    }\n\n    public void setStatus(int status) {\n        this.status = status;\n    }\n\n    public Date getCreateTime() {\n        return createTime;\n    }\n\n    public void setCreateTime(Date createTime) {\n        this.createTime = createTime;\n    }\n\n    public Date getModifyTime() {\n        return modifyTime;\n    }\n\n    public void setModifyTime(Date modifyTime) {\n        this.modifyTime = modifyTime;\n    }\n\n    public AppDesc getAppDesc() {\n        return appDesc;\n    }\n\n    public void setAppDesc(AppDesc appDesc) {\n        this.appDesc = appDesc;\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 getRefuseReason() {\n        return refuseReason;\n    }\n\n    public void setRefuseReason(String refuseReason) {\n        this.refuseReason = refuseReason;\n    }\n\n    public AppAuditLog getAppAuditLog() {\n        return appAuditLog;\n    }\n\n    public void setAppAuditLog(AppAuditLog appAuditLog) {\n        this.appAuditLog = appAuditLog;\n    }\n\n    public String getTypeDesc() {\n        if (type == 0) {\n            return \"申请应用\";\n        } else if (type == 1) {\n            return \"应用扩容\";\n        } else if (type == 2) {\n            return \"修改配置\";\n        } else {\n            return type + \"\";\n        }\n    }\n\n    public String getStatusDesc() {\n//        0:等待审批; 1:审批通过; -1:驳回\n        if (status == 0) {\n            return \"等待审批\";\n        } else if (status == 1) {\n            return \"审批通过\";\n        } else if (status == -1) {\n            return \"驳回\";\n        } else {\n            return status + \"\";\n        }\n    }\n    \n    public String getModifyTimeFormat(){\n        SimpleDateFormat sdf = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n        if(modifyTime != null){\n            return sdf.format(modifyTime);\n        }\n        return \"\";\n    }\n    \n    public String getCreateTimeFormat(){\n        SimpleDateFormat sdf = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n        if(createTime != null){\n            return sdf.format(createTime);\n        }\n        return \"\";\n    }\n\n    @Override\n    public String toString() {\n        return \"AppAudit [id=\" + id + \", appId=\" + appId + \", userId=\" + userId + \", userName=\" + userName + \", type=\"\n                + type + \", param1=\" + param1 + \", param2=\" + param2 + \", param3=\" + param3 + \", info=\" + info\n                + \", status=\" + status + \", createTime=\" + createTime + \", modifyTime=\" + modifyTime\n                + \", refuseReason=\" + refuseReason + \", appDesc=\" + appDesc + \"]\";\n    }\n\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/AppAuditLog.java",
    "content": "package com.sohu.cache.entity;\n\nimport java.io.Serializable;\nimport java.util.Date;\n\nimport net.sf.json.JSONObject;\n\nimport org.apache.commons.lang.builder.ToStringBuilder;\n\nimport com.sohu.cache.constant.AppAuditLogTypeEnum;\n\n/**\n * 资源的审批发布日志\n * \n * @author leifu\n * @Time 2014年6月5日\n */\npublic class AppAuditLog implements Serializable {\n\n    private static final long serialVersionUID = 7218664733731725364L;\n\n    /**\n     * 日志id\n     */\n    private Long id;\n\n    /**\n     * 应用id\n     */\n    private Long appId;\n    \n    /**\n     * 审批id\n     */\n    private Long appAuditId;\n    \n    /**\n     * 用户id\n     */\n    private Long userId;\n    \n    /**\n     * 用户\n     */\n    private AppUser appUser;\n    \n    /**\n     * 日志详情 是个json\n     */\n    private String info;\n    \n    /**\n     * 创建时间\n     */\n    private Date createTime;\n    \n    /**\n     * 日志类型\n     */\n    private Integer type;\n    \n    public Long getId() {\n        return id;\n    }\n\n    public void setId(Long appId) {\n        this.id = appId;\n    }\n\n    public Long getAppId() {\n        return appId;\n    }\n\n    public void setAppId(Long appId) {\n        this.appId = appId;\n    }\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 getInfo() {\n        return info;\n    }\n\n    public void setInfo(String info) {\n        this.info = info;\n    }\n\n    public Date getCreateTime() {\n        return createTime;\n    }\n\n    public void setCreateTime(Date createTime) {\n        this.createTime = createTime;\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 Long getAppAuditId() {\n        return appAuditId;\n    }\n\n    public void setAppAuditId(Long appAuditId) {\n        this.appAuditId = appAuditId;\n    }\n    \n    public AppUser getAppUser() {\n        return appUser;\n    }\n\n    public void setAppUser(AppUser appUser) {\n        this.appUser = appUser;\n    }\n\n    /**\n     * 生成日志\n     * @param appDesc\n     * @param appUser\n     * @param appAuditId\n     * @param type\n     * @return\n     */\n    public static AppAuditLog generate(AppDesc appDesc, AppUser appUser, Long appAuditId, AppAuditLogTypeEnum type){\n        if(appDesc == null || appUser == null || appAuditId == null){\n            return null;\n        }\n        AppAuditLog log = new AppAuditLog();\n        log.setAppId(appDesc.getAppId());\n        log.setUserId(appUser.getId());\n        log.setAppAuditId(appAuditId);\n        log.setType(type.value());\n        log.setCreateTime(new Date());\n        log.setInfo(JSONObject.fromObject(appDesc).toString());\n        return log;\n    }\n\n    @Override\n    public String toString() {\n        return ToStringBuilder.reflectionToString(this).toString();\n    }\n    \n\n}\n\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/AppClientCostTimeStat.java",
    "content": "package com.sohu.cache.entity;\n\nimport java.text.ParseException;\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\n\nimport org.apache.commons.lang.builder.ToStringBuilder;\n\n/**\n * 客户端耗时统计\n * @author leifu\n * @Date 2015年1月20日\n * @Time 上午11:44:09\n */\npublic class AppClientCostTimeStat {\n    \n    private long id;\n\n    /**\n     * 应用id\n     */\n    private long appId;\n\n    /**\n     * 格式yyyyMMddHHmm00\n     */\n    private long collectTime;\n\n    /**\n     * 客户端ip\n     */\n    private String clientIp;\n\n    /**\n     * 上报时间\n     */\n    private Date reportTime;\n\n    /**\n     * 创建时间\n     */\n    private Date createTime;\n\n    /**\n     * 命令\n     */\n    private String command;\n\n    /**\n     * 调用次数\n     */\n    private int count;\n\n    /**\n     * 实例ip\n     */\n    private String instanceHost;\n\n    /**\n     * 实例port\n     */\n    private int instancePort;\n    \n    /**\n     * 实例id\n     */\n    private long instanceId;\n    \n    /**\n     * 中位值\n     */\n    private int median;\n\n    /**\n     * 平均值\n     */\n    private double mean;\n\n    /**\n     * 90%最大值\n     */\n    private int ninetyPercentMax;\n\n    /**\n     * 99%最大值\n     */\n    private int ninetyNinePercentMax;\n\n    /**\n     * 100%最大值\n     */\n    private int hundredMax;\n    \n\n    public long getId() {\n        return id;\n    }\n\n    public void setId(long id) {\n        this.id = id;\n    }\n\n    public long getAppId() {\n        return appId;\n    }\n\n    public void setAppId(long appId) {\n        this.appId = appId;\n    }\n\n    public long getCollectTime() {\n        return collectTime;\n    }\n\n    public void setCollectTime(long collectTime) {\n        this.collectTime = collectTime;\n    }\n\n    public String getClientIp() {\n        return clientIp;\n    }\n\n    public void setClientIp(String clientIp) {\n        this.clientIp = clientIp;\n    }\n\n    public Date getReportTime() {\n        return reportTime;\n    }\n\n    public void setReportTime(Date reportTime) {\n        this.reportTime = reportTime;\n    }\n\n    public Date getCreateTime() {\n        return createTime;\n    }\n\n    public void setCreateTime(Date createTime) {\n        this.createTime = createTime;\n    }\n\n    public String getCommand() {\n        return command;\n    }\n\n    public void setCommand(String command) {\n        this.command = command;\n    }\n\n    public int getCount() {\n        return count;\n    }\n\n    public void setCount(int count) {\n        this.count = count;\n    }\n\n    public String getInstanceHost() {\n        return instanceHost;\n    }\n\n    public void setInstanceHost(String instanceHost) {\n        this.instanceHost = instanceHost;\n    }\n\n    public int getInstancePort() {\n        return instancePort;\n    }\n\n    public void setInstancePort(int instancePort) {\n        this.instancePort = instancePort;\n    }\n\n    public long getInstanceId() {\n        return instanceId;\n    }\n\n    public void setInstanceId(long instanceId) {\n        this.instanceId = instanceId;\n    }\n    \n    public int getMedian() {\n        return median;\n    }\n\n    public void setMedian(int median) {\n        this.median = median;\n    }\n\n    public double getMean() {\n        return mean;\n    }\n\n    public void setMean(double mean) {\n        this.mean = mean;\n    }\n\n    public int getNinetyPercentMax() {\n        return ninetyPercentMax;\n    }\n\n    public void setNinetyPercentMax(int ninetyPercentMax) {\n        this.ninetyPercentMax = ninetyPercentMax;\n    }\n\n    public int getNinetyNinePercentMax() {\n        return ninetyNinePercentMax;\n    }\n\n    public void setNinetyNinePercentMax(int ninetyNinePercentMax) {\n        this.ninetyNinePercentMax = ninetyNinePercentMax;\n    }\n\n    public int getHundredMax() {\n        return hundredMax;\n    }\n\n    public void setHundredMax(int hundredMax) {\n        this.hundredMax = hundredMax;\n    }\n\n    public Long getCollectTimeStamp() throws ParseException{\n        SimpleDateFormat sdf = new SimpleDateFormat(\"yyyyMMddHHmmss\");\n        Date date;\n        try {\n            date = sdf.parse(String.valueOf(this.collectTime));\n            return date.getTime();\n        } catch (Exception e) {\n            return 0L;\n        }\n    }\n    \n    public Long getTimeStamp() throws ParseException{\n        SimpleDateFormat sdf = new SimpleDateFormat(\"yyyyMMddHHmmss\");\n        Date date = sdf.parse(String.valueOf(this.collectTime));\n        return date.getTime();\n    }\n    \n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((clientIp == null) ? 0 : clientIp.hashCode());\n        result = prime * result + (int) (instanceId ^ (instanceId >>> 32));\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj)\n            return true;\n        if (obj == null)\n            return false;\n        if (getClass() != obj.getClass())\n            return false;\n        AppClientCostTimeStat other = (AppClientCostTimeStat) obj;\n        if (clientIp == null) {\n            if (other.clientIp != null)\n                return false;\n        } else if (!clientIp.equals(other.clientIp))\n            return false;\n        if (instanceId != other.instanceId)\n            return false;\n        return true;\n    }\n\n    @Override\n    public String toString() {\n        return ToStringBuilder.reflectionToString(this).toString();\n    }\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/AppClientCostTimeTotalStat.java",
    "content": "package com.sohu.cache.entity;\n\nimport java.text.DecimalFormat;\nimport java.text.ParseException;\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\n\nimport org.apache.commons.lang.builder.ToStringBuilder;\nimport org.apache.commons.lang.math.NumberUtils;\n\n/**\n * 基于应用全局耗时统计(uniquekey: app_id, command, collect_time)\n * @author leifu\n * @Date 2015年6月26日\n * @Time 下午4:26:54\n */\npublic class AppClientCostTimeTotalStat {\n    \n    private long id;\n\n    /**\n     * 应用id\n     */\n    private long appId;\n\n    /**\n     * 格式yyyyMMddHHmm00\n     */\n    private long collectTime;\n\n    /**\n     * 创建时间\n     */\n    private Date createTime;\n\n    /**\n     * 命令\n     */\n    private String command;\n\n    /**\n     * 调用总次数\n     */\n    private long totalCount;\n    \n    /**\n     * 调用总耗时\n     */\n    private double totalCost;\n\n    /**\n     * 中位值\n     */\n    private int median;\n\n    /**\n     * 平均值\n     */\n    private double mean;\n\n    /**\n     * 90%最大值\n     */\n    private int ninetyPercentMax;\n\n    /**\n     * 99%最大值\n     */\n    private int ninetyNinePercentMax;\n\n    /**\n     * 100%最大值\n     */\n    private int hundredMax;\n    \n    /**\n     * 实例ip\n     */\n    private String maxInstanceHost;\n\n    /**\n     * 实例port\n     */\n    private int maxInstancePort;\n    \n    /**\n     * 实例id\n     */\n    private long maxInstanceId;\n    \n    /**\n     * 客户端\n     */\n    private String maxClientIp;\n    \n\n    public AppClientCostTimeTotalStat(long id, long appId, long collectTime, Date createTime, String command,\n            long totalCount, double totalCost, int median, double mean, int ninetyPercentMax, int ninetyNinePercentMax,\n            int hundredMax, String maxInstanceHost, int maxInstancePort, long maxInstanceId, String maxClientIp) {\n        this.id = id;\n        this.appId = appId;\n        this.collectTime = collectTime;\n        this.createTime = createTime;\n        this.command = command;\n        this.totalCount = totalCount;\n        this.totalCost = totalCost;\n        this.median = median;\n        this.mean = mean;\n        this.ninetyPercentMax = ninetyPercentMax;\n        this.ninetyNinePercentMax = ninetyNinePercentMax;\n        this.hundredMax = hundredMax;\n        this.maxInstanceHost = maxInstanceHost;\n        this.maxInstancePort = maxInstancePort;\n        this.maxInstanceId = maxInstanceId;\n        this.maxClientIp = maxClientIp;\n    }\n\n    public AppClientCostTimeTotalStat() {\n    }\n\n    public long getId() {\n        return id;\n    }\n\n    public void setId(long id) {\n        this.id = id;\n    }\n\n    public long getAppId() {\n        return appId;\n    }\n\n    public void setAppId(long appId) {\n        this.appId = appId;\n    }\n\n    public long getCollectTime() {\n        return collectTime;\n    }\n\n    public void setCollectTime(long collectTime) {\n        this.collectTime = collectTime;\n    }\n\n    public Date getCreateTime() {\n        return createTime;\n    }\n\n    public void setCreateTime(Date createTime) {\n        this.createTime = createTime;\n    }\n\n    public String getCommand() {\n        return command;\n    }\n\n    public void setCommand(String command) {\n        this.command = command;\n    }\n\n    public int getMedian() {\n        return median;\n    }\n\n    public void setMedian(int median) {\n        this.median = median;\n    }\n\n    public double getMean() {\n        return mean;\n    }\n\n    public void setMean(double mean) {\n        this.mean = mean;\n    }\n\n    public int getNinetyPercentMax() {\n        return ninetyPercentMax;\n    }\n\n    public void setNinetyPercentMax(int ninetyPercentMax) {\n        this.ninetyPercentMax = ninetyPercentMax;\n    }\n\n    public int getNinetyNinePercentMax() {\n        return ninetyNinePercentMax;\n    }\n\n    public void setNinetyNinePercentMax(int ninetyNinePercentMax) {\n        this.ninetyNinePercentMax = ninetyNinePercentMax;\n    }\n\n    public int getHundredMax() {\n        return hundredMax;\n    }\n\n    public void setHundredMax(int hundredMax) {\n        this.hundredMax = hundredMax;\n    }\n\n    public long getTotalCount() {\n        return totalCount;\n    }\n\n    public void setTotalCount(long totalCount) {\n        this.totalCount = totalCount;\n    }\n\n    public void setTotalCost(double totalCost) {\n        this.totalCost = totalCost;\n    }\n\n    public double getTotalCost() {\n        return totalCost;\n    }\n\n    public String getMaxInstanceHost() {\n        return maxInstanceHost;\n    }\n\n    public void setMaxInstanceHost(String maxInstanceHost) {\n        this.maxInstanceHost = maxInstanceHost;\n    }\n\n    public int getMaxInstancePort() {\n        return maxInstancePort;\n    }\n\n    public void setMaxInstancePort(int maxInstancePort) {\n        this.maxInstancePort = maxInstancePort;\n    }\n\n    public long getMaxInstanceId() {\n        return maxInstanceId;\n    }\n\n    public void setMaxInstanceId(long maxInstanceId) {\n        this.maxInstanceId = maxInstanceId;\n    }\n\n    public String getMaxClientIp() {\n        return maxClientIp;\n    }\n\n    public void setMaxClientIp(String maxClientIp) {\n        this.maxClientIp = maxClientIp;\n    }\n    \n    public Long getTimeStamp() {\n        SimpleDateFormat sdf = new SimpleDateFormat(\"yyyyMMddHHmmss\");\n        try {\n            Date date = sdf.parse(String.valueOf(this.collectTime));\n            return date.getTime();\n        } catch (ParseException e) {\n            return 0L;\n        }\n        \n    }\n\n    @Override\n    public String toString() {\n        return ToStringBuilder.reflectionToString(this).toString();\n    }\n\n    public static AppClientCostTimeTotalStat getFromAppClientCostTimeStat(AppClientCostTimeStat stat) {\n        AppClientCostTimeTotalStat appClientCostTimeTotalStat = new AppClientCostTimeTotalStat();\n        appClientCostTimeTotalStat.setAppId(stat.getAppId());\n        appClientCostTimeTotalStat.setCollectTime(stat.getCollectTime());\n        appClientCostTimeTotalStat.setCommand(stat.getCommand());\n        appClientCostTimeTotalStat.setCreateTime(stat.getCreateTime());\n        appClientCostTimeTotalStat.setMean(stat.getMean());\n        appClientCostTimeTotalStat.setMedian(stat.getMedian());\n        appClientCostTimeTotalStat.setHundredMax(stat.getHundredMax());\n        appClientCostTimeTotalStat.setNinetyPercentMax(stat.getNinetyPercentMax());\n        appClientCostTimeTotalStat.setNinetyNinePercentMax(stat.getNinetyNinePercentMax());\n        appClientCostTimeTotalStat.setMaxClientIp(stat.getClientIp());\n        appClientCostTimeTotalStat.setMaxInstanceHost(stat.getInstanceHost());\n        appClientCostTimeTotalStat.setMaxInstancePort(stat.getInstancePort());\n        appClientCostTimeTotalStat.setMaxInstanceId(stat.getInstanceId());\n        appClientCostTimeTotalStat.setMaxClientIp(stat.getClientIp());\n        //保留两位小数\n        DecimalFormat df = new DecimalFormat(\"#.00\");\n        appClientCostTimeTotalStat.setTotalCost(NumberUtils.toDouble(df.format(stat.getMean() * stat.getCount())));\n        appClientCostTimeTotalStat.setTotalCount(stat.getCount());\n        return appClientCostTimeTotalStat;\n    }\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/AppClientDataSizeStat.java",
    "content": "package com.sohu.cache.entity;\n\nimport java.util.Date;\n\nimport org.apache.commons.lang.builder.ToStringBuilder;\n\n/**\n * 客户端内收集数据map的尺寸\n * @author leifu\n * @Date 2015年7月13日\n * @Time 下午3:01:34\n */\npublic class AppClientDataSizeStat {\n    \n    private long id;\n\n    /**\n     * 格式yyyyMMddHHmm00\n     */\n    private long collectTime;\n\n    /**\n     * 客户端ip\n     */\n    private String clientIp;\n\n    /**\n     * 上报时间\n     */\n    private Date reportTime;\n\n    /**\n     * 创建时间\n     */\n    private Date createTime;\n    \n    /**\n     * 耗时map尺寸\n     */\n    private int costMapSize;\n    \n    /**\n     * 值map尺寸\n     */\n    private int valueMapSize;\n    \n    /**\n     * 异常map尺寸\n     */\n    private int exceptionMapSize;\n    \n    /**\n     * 收集map尺寸\n     */\n    private int collectMapSize;\n\n    public long getId() {\n        return id;\n    }\n\n    public void setId(long id) {\n        this.id = id;\n    }\n\n    public long getCollectTime() {\n        return collectTime;\n    }\n\n    public void setCollectTime(long collectTime) {\n        this.collectTime = collectTime;\n    }\n\n    public String getClientIp() {\n        return clientIp;\n    }\n\n    public void setClientIp(String clientIp) {\n        this.clientIp = clientIp;\n    }\n\n    public Date getReportTime() {\n        return reportTime;\n    }\n\n    public void setReportTime(Date reportTime) {\n        this.reportTime = reportTime;\n    }\n\n    public Date getCreateTime() {\n        return createTime;\n    }\n\n    public void setCreateTime(Date createTime) {\n        this.createTime = createTime;\n    }\n\n    public int getCostMapSize() {\n        return costMapSize;\n    }\n\n    public void setCostMapSize(int costMapSize) {\n        this.costMapSize = costMapSize;\n    }\n\n    public int getValueMapSize() {\n        return valueMapSize;\n    }\n\n    public void setValueMapSize(int valueMapSize) {\n        this.valueMapSize = valueMapSize;\n    }\n\n    public int getExceptionMapSize() {\n        return exceptionMapSize;\n    }\n\n    public void setExceptionMapSize(int exceptionMapSize) {\n        this.exceptionMapSize = exceptionMapSize;\n    }\n\n    public int getCollectMapSize() {\n        return collectMapSize;\n    }\n\n    public void setCollectMapSize(int collectMapSize) {\n        this.collectMapSize = collectMapSize;\n    }\n\n    @Override\n    public String toString() {\n        return ToStringBuilder.reflectionToString(this).toString();\n    }\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/AppClientExceptionStat.java",
    "content": "package com.sohu.cache.entity;\n\nimport java.text.ParseException;\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\n\nimport org.apache.commons.lang.builder.ToStringBuilder;\n\n/**\n * 客户端异常统计\n * @author leifu\n * @Date 2015年1月20日\n * @Time 上午11:44:09\n */\npublic class AppClientExceptionStat {\n    \n    private long id;\n\n    /**\n     * 应用id\n     */\n    private long appId;\n\n    /**\n     * 格式yyyyMMddHHmm00\n     */\n    private long collectTime;\n\n    /**\n     * 客户端ip\n     */\n    private String clientIp;\n\n    /**\n     * 上报时间\n     */\n    private Date reportTime;\n\n    /**\n     * 创建时间\n     */\n    private Date createTime;\n    \n    /**\n     * 异常类\n     */\n    private String exceptionClass;\n    \n    /**\n     * 异常数\n     */\n    private Long exceptionCount;\n\n    /**\n     * 实例ip\n     */\n    private String instanceHost;\n\n    /**\n     * 实例port\n     */\n    private Integer instancePort;\n    \n    /**\n     * 实例id\n     */\n    private Integer instanceId;\n    \n    /**\n     * 异常类型，参考ClientExceptionType.type\n     */\n    private Integer type;\n\n    public long getId() {\n        return id;\n    }\n\n    public void setId(long id) {\n        this.id = id;\n    }\n\n    public long getAppId() {\n        return appId;\n    }\n\n    public void setAppId(long appId) {\n        this.appId = appId;\n    }\n\n    public long getCollectTime() {\n        return collectTime;\n    }\n\n    public void setCollectTime(long collectTime) {\n        this.collectTime = collectTime;\n    }\n\n    public String getClientIp() {\n        return clientIp;\n    }\n\n    public void setClientIp(String clientIp) {\n        this.clientIp = clientIp;\n    }\n\n    public Date getReportTime() {\n        return reportTime;\n    }\n\n    public void setReportTime(Date reportTime) {\n        this.reportTime = reportTime;\n    }\n\n    public Date getCreateTime() {\n        return createTime;\n    }\n\n    public void setCreateTime(Date createTime) {\n        this.createTime = createTime;\n    }\n\n\n    public String getExceptionClass() {\n        return exceptionClass;\n    }\n\n    public void setExceptionClass(String exceptionClass) {\n        this.exceptionClass = exceptionClass;\n    }\n\n    public Long getExceptionCount() {\n\t\treturn exceptionCount;\n\t}\n\n\tpublic void setExceptionCount(Long exceptionCount) {\n\t\tthis.exceptionCount = exceptionCount;\n\t}\n\n\tpublic String getInstanceHost() {\n        return instanceHost;\n    }\n\n    public void setInstanceHost(String instanceHost) {\n        this.instanceHost = instanceHost;\n    }\n\n    public Integer getInstancePort() {\n        return instancePort;\n    }\n\n    public void setInstancePort(Integer instancePort) {\n        this.instancePort = instancePort;\n    }\n\n    public Integer getInstanceId() {\n        return instanceId;\n    }\n\n    public void setInstanceId(Integer instanceId) {\n        this.instanceId = instanceId;\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 getCollectTimeFormat(){\n        SimpleDateFormat sdf = new SimpleDateFormat(\"yyyyMMddHHmmss\");\n        try {\n            Date date = sdf.parse(String.valueOf(collectTime));\n            SimpleDateFormat newSdf = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n            return newSdf.format(date);\n        } catch (ParseException e) {\n            return \"\";\n        }\n    }\n\n    @Override\n    public String toString() {\n        return ToStringBuilder.reflectionToString(this).toString();\n    }\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/AppClientValueDistriSimple.java",
    "content": "package com.sohu.cache.entity;\n\nimport org.apache.commons.lang.builder.ToStringBuilder;\n\nimport com.sohu.tv.jedis.stat.enums.ValueSizeDistriEnum;\n\n/**\n * \n * @author leifu\n * @Date 2015-6-20\n * @Time 下午4:37:02\n */\npublic class AppClientValueDistriSimple {\n\n    /**\n     * 值分布类型\n     */\n    private int distributeType;\n\n    /**\n     * 调用次数\n     */\n    private long count;\n\n    public int getDistributeType() {\n        return distributeType;\n    }\n\n    public void setDistributeType(int distributeType) {\n        this.distributeType = distributeType;\n    }\n\n\n    public long getCount() {\n        return count;\n    }\n\n    public void setCount(long count) {\n        this.count = count;\n    }\n\n    public String getDistributeDesc() {\n        ValueSizeDistriEnum valueSizeDistriEnum = ValueSizeDistriEnum.getByType(distributeType);\n        return valueSizeDistriEnum == null ? \"\" : valueSizeDistriEnum.getInfo();\n    }\n    \n\n    @Override\n    public String toString() {\n        return ToStringBuilder.reflectionToString(this).toString();\n    }\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/AppClientValueDistriStat.java",
    "content": "package com.sohu.cache.entity;\n\nimport java.util.Date;\n\nimport org.apache.commons.lang.builder.ToStringBuilder;\n\n/**\n * 客户端值分布统计\n * @author leifu\n * @Date 2015年1月20日\n * @Time 上午11:44:09\n */\npublic class AppClientValueDistriStat {\n    \n    private long id;\n\n    /**\n     * 应用id\n     */\n    private long appId;\n\n    /**\n     * 格式yyyyMMddHHmm00\n     */\n    private long collectTime;\n\n    /**\n     * 客户端ip\n     */\n    private String clientIp;\n\n    /**\n     * 上报时间\n     */\n    private Date reportTime;\n\n    /**\n     * 创建时间\n     */\n    private Date createTime;\n\n    /**\n     * 命令\n     */\n    private String command;\n\n    /**\n     * 值分布值\n     */\n    private String distributeValue;\n\n    /**\n     * 值分布类型\n     */\n    private int distributeType;\n\n    /**\n     * 调用次数\n     */\n    private int count;\n\n    /**\n     * 实例ip\n     */\n    private String instanceHost;\n\n    /**\n     * 实例port\n     */\n    private int instancePort;\n    \n    /**\n     * 实例id\n     */\n    private long instanceId;\n\n    public long getId() {\n        return id;\n    }\n\n    public void setId(long id) {\n        this.id = id;\n    }\n\n    public long getAppId() {\n        return appId;\n    }\n\n    public void setAppId(long appId) {\n        this.appId = appId;\n    }\n\n    public long getCollectTime() {\n        return collectTime;\n    }\n\n    public void setCollectTime(long collectTime) {\n        this.collectTime = collectTime;\n    }\n\n    public String getClientIp() {\n        return clientIp;\n    }\n\n    public void setClientIp(String clientIp) {\n        this.clientIp = clientIp;\n    }\n\n    public Date getReportTime() {\n        return reportTime;\n    }\n\n    public void setReportTime(Date reportTime) {\n        this.reportTime = reportTime;\n    }\n\n    public Date getCreateTime() {\n        return createTime;\n    }\n\n    public void setCreateTime(Date createTime) {\n        this.createTime = createTime;\n    }\n\n    public String getCommand() {\n        return command;\n    }\n\n    public void setCommand(String command) {\n        this.command = command;\n    }\n\n    public String getDistributeValue() {\n        return distributeValue;\n    }\n\n    public void setDistributeValue(String distributeValue) {\n        this.distributeValue = distributeValue;\n    }\n\n    public int getDistributeType() {\n        return distributeType;\n    }\n\n    public void setDistributeType(int distributeType) {\n        this.distributeType = distributeType;\n    }\n\n    public int getCount() {\n        return count;\n    }\n\n    public void setCount(int count) {\n        this.count = count;\n    }\n\n    public String getInstanceHost() {\n        return instanceHost;\n    }\n\n    public void setInstanceHost(String instanceHost) {\n        this.instanceHost = instanceHost;\n    }\n\n    public int getInstancePort() {\n        return instancePort;\n    }\n\n    public void setInstancePort(int instancePort) {\n        this.instancePort = instancePort;\n    }\n\n    public long getInstanceId() {\n        return instanceId;\n    }\n\n    public void setInstanceId(long instanceId) {\n        this.instanceId = instanceId;\n    }\n\n    @Override\n    public String toString() {\n        return ToStringBuilder.reflectionToString(this).toString();\n    }\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/AppClientValueDistriStatTotal.java",
    "content": "package com.sohu.cache.entity;\n\nimport java.util.Date;\n\nimport org.apache.commons.lang.builder.ToStringBuilder;\n\n/**\n * 客户端值分布统计\n * @author leifu\n * @Date 2015年1月20日\n * @Time 上午11:44:09\n */\npublic class AppClientValueDistriStatTotal {\n    \n    /**\n     * 应用id\n     */\n    private long appId;\n\n    /**\n     * 格式yyyyMMddHHmm00\n     */\n    private long collectTime;\n\n    /**\n     * 创建时间\n     */\n    private Date updateTime;\n\n    /**\n     * 命令\n     */\n    private String command;\n\n    /**\n     * 值分布类型\n     */\n    private int distributeType;\n\n    /**\n     * 调用次数\n     */\n    private int count;\n\n    public long getAppId() {\n        return appId;\n    }\n\n    public void setAppId(long appId) {\n        this.appId = appId;\n    }\n\n    public long getCollectTime() {\n        return collectTime;\n    }\n\n    public void setCollectTime(long collectTime) {\n        this.collectTime = collectTime;\n    }\n\n\n    public Date getUpdateTime() {\n        return updateTime;\n    }\n\n    public void setUpdateTime(Date updateTime) {\n        this.updateTime = updateTime;\n    }\n\n    public String getCommand() {\n        return command;\n    }\n\n    public void setCommand(String command) {\n        this.command = command;\n    }\n\n\n    public int getDistributeType() {\n        return distributeType;\n    }\n\n    public void setDistributeType(int distributeType) {\n        this.distributeType = distributeType;\n    }\n\n    public int getCount() {\n        return count;\n    }\n\n    public void setCount(int count) {\n        this.count = count;\n    }\n\n    @Override\n    public String toString() {\n        return ToStringBuilder.reflectionToString(this).toString();\n    }\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/AppClientVersion.java",
    "content": "package com.sohu.cache.entity;\n\nimport java.util.Date;\n\n/**\n * 客户端版本\n * @author leifu\n * @Date 2015年2月2日\n * @Time 下午3:22:52\n */\npublic class AppClientVersion {\n    \n    /**\n     * 自增id\n     */\n    private long id;\n    \n    /**\n     * 应用id\n     */\n    private long appId;\n    \n    /**\n     * 客户端ip\n     */\n    private String clientIp;\n    \n    /**\n     * 客户端版本\n     */\n    private String clientVersion;\n    \n    /**\n     * 上报时间\n     */\n    private Date reportTime;\n\n    public long getId() {\n        return id;\n    }\n\n    public void setId(long id) {\n        this.id = id;\n    }\n\n    public long getAppId() {\n        return appId;\n    }\n\n    public void setAppId(long appId) {\n        this.appId = appId;\n    }\n\n    public String getClientIp() {\n        return clientIp;\n    }\n\n    public void setClientIp(String clientIp) {\n        this.clientIp = clientIp;\n    }\n\n    public String getClientVersion() {\n        return clientVersion;\n    }\n\n    public void setClientVersion(String clientVersion) {\n        this.clientVersion = clientVersion;\n    }\n\n    public Date getReportTime() {\n        return reportTime;\n    }\n\n    public void setReportTime(Date reportTime) {\n        this.reportTime = reportTime;\n    }\n\n    @Override\n    public String toString() {\n        return \"AppClientVersion [id=\" + id + \", appId=\" + appId + \", clientIp=\" + clientIp + \", clientVersion=\"\n                + clientVersion + \", reportTime=\" + reportTime + \"]\";\n    }\n    \n    \n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/AppCommandGroup.java",
    "content": "package com.sohu.cache.entity;\n\n/**\n * 命令分布\n */\npublic class AppCommandGroup {\n\t/**\n\t * 命令名\n\t */\n\tprivate String commandName;\n\t\n\t/**\n\t * 调用次数\n\t */\n\tprivate long count;\n\n\tpublic String getCommandName() {\n\t\treturn commandName;\n\t}\n\n\tpublic void setCommandName(String commandName) {\n\t\tthis.commandName = commandName;\n\t}\n\n\tpublic long getCount() {\n\t\treturn count;\n\t}\n\n\tpublic void setCount(long count) {\n\t\tthis.count = count;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"AppCommandGroupVO [commandName=\" + commandName + \", count=\"\n\t\t\t\t+ count + \"]\";\n\t}\n\t\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/AppCommandStats.java",
    "content": "package com.sohu.cache.entity;\n\nimport java.util.Date;\n\n/**\n * Created by yijunzhang on 14-6-9.\n */\npublic class AppCommandStats implements Comparable<AppCommandStats> {\n\n    /**\n     * 应用id\n     */\n    private long appId;\n\n    /**\n     * 收集时间:格式yyyyMMddHHmm/yyyyMMdd/yyyyMMddHH\n     */\n    private long collectTime;\n\n    /**\n     * 命令名称\n     */\n    private String commandName;\n\n    /**\n     * 命令执行次数\n     */\n    private long commandCount;\n\n    /**\n     * 创建时间\n     */\n    private Date createTime;\n\n    /**\n     * 修改时间\n     */\n    private Date modifyTime;\n\n    public long getAppId() {\n        return appId;\n    }\n\n    public void setAppId(long appId) {\n        this.appId = appId;\n    }\n\n    public long getCollectTime() {\n        return collectTime;\n    }\n\n    public void setCollectTime(long collectTime) {\n        this.collectTime = collectTime;\n    }\n\n    public String getCommandName() {\n        return commandName;\n    }\n\n    public void setCommandName(String commandName) {\n        this.commandName = commandName;\n    }\n\n    public long getCommandCount() {\n        return commandCount;\n    }\n\n    public void setCommandCount(long commandCount) {\n        this.commandCount = commandCount;\n    }\n\n    public Date getCreateTime() {\n        return createTime;\n    }\n\n    public void setCreateTime(Date createTime) {\n        this.createTime = createTime;\n    }\n\n    public Date getModifyTime() {\n        return modifyTime;\n    }\n\n    public void setModifyTime(Date modifyTime) {\n        this.modifyTime = modifyTime;\n    }\n\n    @Override\n    public int compareTo(AppCommandStats o) {\n        if (o.commandCount > this.commandCount) {\n            return 1;\n        } else if (o.commandCount < this.commandCount) {\n            return -1;\n        }\n        return 0;\n    }\n\n    @Override\n    public String toString() {\n        return \"AppCommandStats{\" +\n                \"appId=\" + appId +\n                \", collectTime=\" + collectTime +\n                \", commandName=\" + commandName +\n                \", commandCount=\" + commandCount +\n                \", createTime=\" + createTime +\n                \", modifyTime=\" + modifyTime +\n                '}';\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/AppDailyData.java",
    "content": "package com.sohu.cache.entity;\n\nimport java.util.Date;\nimport java.util.Map;\nimport java.util.Map.Entry;\n\nimport org.apache.commons.collections.MapUtils;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.sohu.cache.web.vo.AppDetailVO;\n\n/**\n * 应用日报数据\n * @author leifu\n * @Date 2016年8月10日\n * @Time 下午5:12:45\n */\npublic class AppDailyData {\n\n    /**\n     * 应用id\n     */\n    private long appId;\n    \n    /**\n     * 开始日期\n     */\n    private Date startDate;\n\n    \n    /**\n     * 结束日期\n     */\n    private Date endDate;\n    \n    /**\n     * 日期\n     */\n    private Date date;\n    \n    /**\n     * bigkey次数\n     */\n    private long bigKeyTimes;\n    \n    /**\n     * bigkey信息\n     */\n    private String bigKeyInfo;\n    \n    /**\n     * 慢查询次数\n     */\n    private long slowLogCount;\n    \n    /**\n     * 客户端异常个数\n     */\n    private long clientExceptionCount;\n    \n    /**\n     * 每分钟最大客户端连接数\n     */\n    private long maxMinuteClientCount;\n    \n    /**\n     * 每分钟平均客户端连接数\n     */\n    private long avgMinuteClientCount;\n    \n    /**\n     * 每分钟最大命令数\n     */\n    private long maxMinuteCommandCount;\n    \n    /**\n     * 每分钟平均命令数\n     */\n    private long avgMinuteCommandCount;\n    \n    /**\n     * 平均命中率\n     */\n    private double avgHitRatio;\n    \n    /**\n     * 每分钟最小命中率\n     */\n    private double minMinuteHitRatio;\n    \n    /**\n     * 每分钟最大命中率\n     */\n    private double maxMinuteHitRatio;\n    \n    /**\n     * 平均内存使用量\n     */\n    private long avgUsedMemory;\n    \n    /**\n     * 最大内存使用量\n     */\n    private long maxUsedMemory;\n    \n    /**\n     * 过期键个数\n     */\n    private long expiredKeysCount;\n    \n    /**\n     * 剔除键个数\n     */\n    private long evictedKeysCount;\n    \n    /**\n     * 每分钟平均网络input量\n     */\n    private double avgMinuteNetInputByte;\n    \n    /**\n     * 每分钟最大网络input量\n     */\n    private double maxMinuteNetInputByte;\n    \n    /**\n     * 每分钟平均网络output量\n     */\n    private double avgMinuteNetOutputByte;\n    \n    /**\n     * 每分钟最大网络output量\n     */\n    private double maxMinuteNetOutputByte;\n    \n    /**\n     * 键个数平均值\n     */\n    private long avgObjectSize;\n    \n    /**\n     * 键个数最大值\n     */\n    private long maxObjectSize;\n    \n    /**\n     * 值分布\n     */\n    private Map<String, Long> valueSizeDistributeCountMap;\n    \n    /**\n     * 应用详情\n     */\n    private AppDetailVO appDetailVO;\n\n    public long getAppId() {\n        return appId;\n    }\n\n    public void setAppId(long appId) {\n        this.appId = appId;\n    }\n\n    public Date getStartDate() {\n        return startDate;\n    }\n\n    public void setStartDate(Date startDate) {\n        this.startDate = startDate;\n    }\n\n    public Date getEndDate() {\n        return endDate;\n    }\n\n    public void setEndDate(Date endDate) {\n        this.endDate = endDate;\n    }\n\n    public long getSlowLogCount() {\n        return slowLogCount;\n    }\n\n    public void setSlowLogCount(long slowLogCount) {\n        this.slowLogCount = slowLogCount;\n    }\n\n    public long getClientExceptionCount() {\n        return clientExceptionCount;\n    }\n\n    public void setClientExceptionCount(long clientExceptionCount) {\n        this.clientExceptionCount = clientExceptionCount;\n    }\n\n    public long getMaxMinuteClientCount() {\n        return maxMinuteClientCount;\n    }\n\n    public void setMaxMinuteClientCount(long maxMinuteClientCount) {\n        this.maxMinuteClientCount = maxMinuteClientCount;\n    }\n\n    public long getAvgMinuteClientCount() {\n        return avgMinuteClientCount;\n    }\n\n    public void setAvgMinuteClientCount(long avgMinuteClientCount) {\n        this.avgMinuteClientCount = avgMinuteClientCount;\n    }\n\n    public long getMaxMinuteCommandCount() {\n        return maxMinuteCommandCount;\n    }\n\n    public void setMaxMinuteCommandCount(long maxMinuteCommandCount) {\n        this.maxMinuteCommandCount = maxMinuteCommandCount;\n    }\n\n    public long getAvgMinuteCommandCount() {\n        return avgMinuteCommandCount;\n    }\n\n    public void setAvgMinuteCommandCount(long avgMinuteCommandCount) {\n        this.avgMinuteCommandCount = avgMinuteCommandCount;\n    }\n\n    public double getAvgHitRatio() {\n        return avgHitRatio;\n    }\n\n    public void setAvgHitRatio(double avgHitRatio) {\n        this.avgHitRatio = avgHitRatio;\n    }\n\n    public double getMinMinuteHitRatio() {\n        return minMinuteHitRatio;\n    }\n\n    public void setMinMinuteHitRatio(double minMinuteHitRatio) {\n        this.minMinuteHitRatio = minMinuteHitRatio;\n    }\n\n    public double getMaxMinuteHitRatio() {\n        return maxMinuteHitRatio;\n    }\n\n    public void setMaxMinuteHitRatio(double maxMinuteHitRatio) {\n        this.maxMinuteHitRatio = maxMinuteHitRatio;\n    }\n\n    public long getAvgUsedMemory() {\n        return avgUsedMemory;\n    }\n\n    public void setAvgUsedMemory(long avgUsedMemory) {\n        this.avgUsedMemory = avgUsedMemory;\n    }\n\n    public long getMaxUsedMemory() {\n        return maxUsedMemory;\n    }\n\n    public void setMaxUsedMemory(long maxUsedMemory) {\n        this.maxUsedMemory = maxUsedMemory;\n    }\n\n    public long getExpiredKeysCount() {\n        return expiredKeysCount;\n    }\n\n    public void setExpiredKeysCount(long expiredKeysCount) {\n        this.expiredKeysCount = expiredKeysCount;\n    }\n\n    public long getEvictedKeysCount() {\n        return evictedKeysCount;\n    }\n\n    public void setEvictedKeysCount(long evictedKeysCount) {\n        this.evictedKeysCount = evictedKeysCount;\n    }\n\n    public double getAvgMinuteNetInputByte() {\n        return avgMinuteNetInputByte;\n    }\n\n    public void setAvgMinuteNetInputByte(double avgMinuteNetInputByte) {\n        this.avgMinuteNetInputByte = avgMinuteNetInputByte;\n    }\n\n    public double getMaxMinuteNetInputByte() {\n        return maxMinuteNetInputByte;\n    }\n\n    public void setMaxMinuteNetInputByte(double maxMinuteNetInputByte) {\n        this.maxMinuteNetInputByte = maxMinuteNetInputByte;\n    }\n\n    public double getAvgMinuteNetOutputByte() {\n        return avgMinuteNetOutputByte;\n    }\n\n    public void setAvgMinuteNetOutputByte(double avgMinuteNetOutputByte) {\n        this.avgMinuteNetOutputByte = avgMinuteNetOutputByte;\n    }\n\n    public double getMaxMinuteNetOutputByte() {\n        return maxMinuteNetOutputByte;\n    }\n\n    public void setMaxMinuteNetOutputByte(double maxMinuteNetOutputByte) {\n        this.maxMinuteNetOutputByte = maxMinuteNetOutputByte;\n    }\n\n    public long getAvgObjectSize() {\n        return avgObjectSize;\n    }\n\n    public void setAvgObjectSize(long avgObjectSize) {\n        this.avgObjectSize = avgObjectSize;\n    }\n\n    public long getMaxObjectSize() {\n        return maxObjectSize;\n    }\n\n    public void setMaxObjectSize(long maxObjectSize) {\n        this.maxObjectSize = maxObjectSize;\n    }\n\n    public Map<String, Long> getValueSizeDistributeCountMap() {\n        return valueSizeDistributeCountMap;\n    }\n    \n    public String getValueSizeDistributeCountDesc() {\n        if (MapUtils.isEmpty(valueSizeDistributeCountMap)) {\n            return \"无\";\n        }\n        StringBuffer desc = new StringBuffer();\n        for(Entry<String, Long> entry : valueSizeDistributeCountMap.entrySet()) {\n            desc.append(entry.getKey()).append(\":\").append(entry.getValue()).append(\"次<br/>\");\n        }\n        return desc.toString();\n    }\n    \n    public String getValueSizeDistributeCountDescHtml() {\n        return bigKeyInfo.replace(\"\\n\", \"<br/>\").replace(\":\", \":\\t\");\n    }\n\n    public void setValueSizeDistributeCountMap(Map<String, Long> valueSizeDistributeCountMap) {\n        this.valueSizeDistributeCountMap = valueSizeDistributeCountMap;\n    }\n\n    public AppDetailVO getAppDetailVO() {\n        return appDetailVO;\n    }\n\n    public void setAppDetailVO(AppDetailVO appDetailVO) {\n        this.appDetailVO = appDetailVO;\n    }\n\n    public Date getDate() {\n        return date;\n    }\n\n    public void setDate(Date date) {\n        this.date = date;\n    }\n\n    public long getBigKeyTimes() {\n        return bigKeyTimes;\n    }\n\n    public void setBigKeyTimes(long bigKeyTimes) {\n        this.bigKeyTimes = bigKeyTimes;\n    }\n\n    public String getBigKeyInfo() {\n        return bigKeyInfo;\n    }\n\n    public void setBigKeyInfo(String bigKeyInfo) {\n        this.bigKeyInfo = bigKeyInfo;\n    }\n\n    @Override\n    public String toString() {\n        return JSONObject.toJSONString(this);\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/AppDataMigrateSearch.java",
    "content": "package com.sohu.cache.entity;\n\n/**\n * 应用数据迁移搜索\n * \n * @author leifu\n * @Date 2016年8月4日\n * @Time 下午2:49:43\n */\npublic class AppDataMigrateSearch {\n    /**\n     * 源应用id\n     */\n    private Long sourceAppId;\n    \n    /**\n     * 目标应用id\n     */\n    private Long targetAppId;\n\n    /**\n     * 源实例\n     */\n    private String sourceInstanceIp;\n    \n    /**\n     * 目标实例\n     */\n    private String targetInstanceIp;\n\n    /**\n     * 开始时间\n     */\n    private String startDate;\n\n    /**\n     * 结束时间\n     */\n    private String endDate;\n    \n    /**\n     * 状态\n     */\n    private int status = -2;\n\n    public AppDataMigrateSearch() {\n        super();\n    }\n\n    public AppDataMigrateSearch(Long sourceAppId, Long targetAppId, String sourceInstanceIp, String targetInstanceIp,\n            String startDate, String endDate, int status) {\n        super();\n        this.sourceAppId = sourceAppId;\n        this.targetAppId = targetAppId;\n        this.sourceInstanceIp = sourceInstanceIp;\n        this.targetInstanceIp = targetInstanceIp;\n        this.startDate = startDate;\n        this.endDate = endDate;\n        this.status = status;\n    }\n\n    public Long getSourceAppId() {\n        return sourceAppId;\n    }\n\n\n    public void setSourceAppId(Long sourceAppId) {\n        this.sourceAppId = sourceAppId;\n    }\n\n\n    public Long getTargetAppId() {\n        return targetAppId;\n    }\n\n\n    public void setTargetAppId(Long targetAppId) {\n        this.targetAppId = targetAppId;\n    }\n\n\n    public String getSourceInstanceIp() {\n        return sourceInstanceIp;\n    }\n\n\n    public void setSourceInstanceIp(String sourceInstanceIp) {\n        this.sourceInstanceIp = sourceInstanceIp;\n    }\n\n\n    public String getTargetInstanceIp() {\n        return targetInstanceIp;\n    }\n\n\n    public void setTargetInstanceIp(String targetInstanceIp) {\n        this.targetInstanceIp = targetInstanceIp;\n    }\n\n\n    public String getStartDate() {\n        return startDate;\n    }\n\n    public void setStartDate(String startDate) {\n        this.startDate = startDate;\n    }\n\n    public String getEndDate() {\n        return endDate;\n    }\n\n    public void setEndDate(String endDate) {\n        this.endDate = endDate;\n    }\n\n\n    public int getStatus() {\n        return status;\n    }\n\n    public void setStatus(int status) {\n        this.status = status;\n    }\n\n    @Override\n    public String toString() {\n        return \"AppDataMigrateSearch [sourceAppId=\" + sourceAppId + \", targetAppId=\" + targetAppId\n                + \", sourceInstanceIp=\" + sourceInstanceIp + \", targetInstanceIp=\" + targetInstanceIp + \", startDate=\"\n                + startDate + \", endDate=\" + endDate + \", status=\" + status + \"]\";\n    }\n\n\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/AppDataMigrateStatus.java",
    "content": "package com.sohu.cache.entity;\n\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\n\nimport com.sohu.cache.constant.AppDataMigrateEnum;\nimport com.sohu.cache.constant.AppDataMigrateStatusEnum;\n\n/**\n * 迁移状态\n * \n * @author leifu\n * @Date 2016-6-9\n * @Time 下午5:13:13\n */\npublic class AppDataMigrateStatus {\n\n    /**\n     * 自增id\n     */\n    private long id;\n\n    /**\n     * 迁移工具所在机器ip\n     */\n    private String migrateMachineIp;\n    \n    /**\n     * 迁移工具所占port\n     */\n    private int migrateMachinePort;\n\n    /**\n     * 目标实例列表\n     */\n    private String sourceServers;\n\n    /**\n     * 源迁移类型,0:single,1:redis cluster,2:rdb file,3:twemproxy\n     */\n    private int sourceMigrateType;\n\n    /**\n     * 目标实例列表\n     */\n    private String targetServers;\n\n    /**\n     * 目标迁移类型,0:single,1:redis cluster,2:rdb file,3:twemproxy\n     */\n    private int targetMigrateType;\n\n    /**\n     * 源应用id\n     */\n    private long sourceAppId;\n\n    /**\n     * 目标应用id\n     */\n    private long targetAppId;\n\n    /**\n     * 操作人\n     */\n    private long userId;\n\n    /**\n     * 迁移执行状态\n     */\n    private int status;\n\n    /**\n     * 迁移开始执行时间\n     */\n    private Date startTime;\n\n    /**\n     * 迁移结束执行时间\n     */\n    private Date endTime;\n    \n    /**\n     * 日志路径\n     */\n    private String logPath;\n\n    /**\n     * 配置路径\n     */\n    private String configPath;\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 getMigrateMachineIp() {\n        return migrateMachineIp;\n    }\n\n    public void setMigrateMachineIp(String migrateMachineIp) {\n        this.migrateMachineIp = migrateMachineIp;\n    }\n\n    public int getMigrateMachinePort() {\n        return migrateMachinePort;\n    }\n\n    public void setMigrateMachinePort(int migrateMachinePort) {\n        this.migrateMachinePort = migrateMachinePort;\n    }\n\n    public String getSourceServers() {\n        return sourceServers;\n    }\n\n    public void setSourceServers(String sourceServers) {\n        this.sourceServers = sourceServers;\n    }\n\n    public int getSourceMigrateType() {\n        return sourceMigrateType;\n    }\n    \n    public String getSourceMigrateTypeDesc() {\n        AppDataMigrateEnum appDataMigrateEnum = AppDataMigrateEnum.getByIndex(sourceMigrateType);\n        return appDataMigrateEnum == null ? \"异常\" :appDataMigrateEnum.getType();\n    }\n\n    public void setSourceMigrateType(int sourceMigrateType) {\n        this.sourceMigrateType = sourceMigrateType;\n    }\n\n    public String getTargetServers() {\n        return targetServers;\n    }\n\n    public void setTargetServers(String targetServers) {\n        this.targetServers = targetServers;\n    }\n\n    public int getTargetMigrateType() {\n        return targetMigrateType;\n    }\n    \n    public String getTargetMigrateTypeDesc() {\n        AppDataMigrateEnum appDataMigrateEnum = AppDataMigrateEnum.getByIndex(targetMigrateType);\n        return appDataMigrateEnum == null ? \"异常\" :appDataMigrateEnum.getType();\n    }\n\n    public void setTargetMigrateType(int targetMigrateType) {\n        this.targetMigrateType = targetMigrateType;\n    }\n\n    public long getSourceAppId() {\n        return sourceAppId;\n    }\n\n    public void setSourceAppId(long sourceAppId) {\n        this.sourceAppId = sourceAppId;\n    }\n\n    public long getTargetAppId() {\n        return targetAppId;\n    }\n\n    public void setTargetAppId(long targetAppId) {\n        this.targetAppId = targetAppId;\n    }\n\n    public long getUserId() {\n        return userId;\n    }\n\n    public void setUserId(long userId) {\n        this.userId = userId;\n    }\n\n    public int getStatus() {\n        return status;\n    }\n    \n    public String getStatusDesc() {\n        AppDataMigrateStatusEnum appDataMigrateStatusEnum = AppDataMigrateStatusEnum.getByStatus(status);\n        return appDataMigrateStatusEnum == null ? \"异常\" : appDataMigrateStatusEnum.getInfo();\n    }\n\n    public void setStatus(int status) {\n        this.status = status;\n    }\n\n    public Date getStartTime() {\n        return startTime;\n    }\n    \n    public String getStartTimeFormat() {\n        if (startTime == null) {\n            return \"\";\n        }\n        SimpleDateFormat sdf = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n        return sdf.format(startTime);\n    }\n\n    public void setStartTime(Date startTime) {\n        this.startTime = startTime;\n    }\n\n    public Date getEndTime() {\n        return endTime;\n    }\n    \n    public String getEndTimeFormat() {\n        if (endTime == null) {\n            return \"\";\n        }\n        SimpleDateFormat sdf = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n        return sdf.format(endTime);\n    }\n\n    public void setEndTime(Date endTime) {\n        this.endTime = endTime;\n    }\n\n    public String getLogPath() {\n        return logPath;\n    }\n\n    public void setLogPath(String logPath) {\n        this.logPath = logPath;\n    }\n\n    public String getConfigPath() {\n        return configPath;\n    }\n\n    public void setConfigPath(String configPath) {\n        this.configPath = configPath;\n    }\n\n    @Override\n    public String toString() {\n        return \"AppDataMigrateStatus [id=\" + id + \", migrateMachineIp=\" + migrateMachineIp + \", migrateMachinePort=\"\n                + migrateMachinePort + \", sourceServers=\" + sourceServers + \", sourceMigrateType=\" + sourceMigrateType\n                + \", targetServers=\" + targetServers + \", targetMigrateType=\" + targetMigrateType + \", sourceAppId=\"\n                + sourceAppId + \", targetAppId=\" + targetAppId + \", userId=\" + userId + \", status=\" + status\n                + \", startTime=\" + startTime + \", endTime=\" + endTime + \", logPath=\" + logPath + \", configPath=\"\n                + configPath + \"]\";\n    }\n\n\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/AppDesc.java",
    "content": "package com.sohu.cache.entity;\n\nimport java.io.Serializable;\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\nimport java.util.concurrent.TimeUnit;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.sohu.cache.constant.AppDescEnum;\nimport com.sohu.cache.constant.AppDescEnum.AppImportantLevel;\nimport com.sohu.cache.constant.AppStatusEnum;\nimport com.sohu.cache.util.ConstUtils;\n\n/**\n * 应用的信息，包括分片、类型以及各分片的ip\n * <p/>\n * User: lingguo\n * Date: 14-5-29\n * Time: 下午9:42\n */\npublic class AppDesc implements Serializable {\n    private static final long serialVersionUID = -3507970915810652761L;\n\n    /**\n     * 应用id\n     */\n    private long appId;\n    \n    /**\n     * 应用秘钥\n     */\n    private String appKey;\n\n    /**\n     * 应用名称\n     */\n    private String name;\n\n    /**\n     * 用户id\n     */\n    private long userId;\n\n    /**\n     * 应用状态, 0未分配，1是申请了未审批，2是审批并发布, 3应用下线\n     */\n    private int status;\n\n    /**\n     * 应用描述\n     */\n    private String intro;\n\n    /**\n     * 创建时间\n     */\n    private Date createTime;\n\n    /**\n     * 申请通过的时间\n     */\n    private Date passedTime;\n\n    /**\n     * 类型\n     */\n    private int type;\n\n    /**\n     * 类型描述\n     */\n    private String typeDesc;\n\n    /**\n     * 负责人\n     */\n    private String officer;\n\n    /**\n     * 版本号\n     */\n    private int verId;\n\n    /**\n     * 是否测试：1是0否\n     */\n    private int isTest;\n\n    /**\n     * 是否有后端数据源: 1是0否\n     */\n    private int hasBackStore;\n\n    /**\n     * 是否需要持久化: 1是0否\n     */\n    private int needPersistence;\n\n    /**\n     * 预估qps\n     */\n    private int forecaseQps;\n\n    /**\n     * 是否需要热备: 1是0否\n     */\n    private int needHotBackUp;\n\n    /**\n     * 预估条目数\n     */\n    private int forecastObjNum;\n\n    /**\n     * 内存报警阀值\n     */\n    private int memAlertValue;\n    \n    /**\n     * 客户端连接数报警阀值\n     */\n    private int clientConnAlertValue;\n    \n    /**\n     * 客户端机器机房\n     */\n    private String clientMachineRoom;\n    \n    /**\n     * redis密码\n     */\n    private String password;\n    \n    /**\n     * 重要度，默认重要\n     */\n    private int importantLevel = AppImportantLevel.IMPORTANT.getValue();\n\n    public long getAppId() {\n        return appId;\n    }\n\n    public void setAppId(long appId) {\n        this.appId = appId;\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 long getUserId() {\n        return userId;\n    }\n\n    public void setUserId(long userId) {\n        this.userId = userId;\n    }\n\n    public int getStatus() {\n        return status;\n    }\n\n    public void setStatus(int status) {\n        this.status = status;\n    }\n\n    public String getIntro() {\n        return intro;\n    }\n\n    public void setIntro(String intro) {\n        this.intro = intro;\n    }\n\n    public Date getCreateTime() {\n        return createTime;\n    }\n\n    public void setCreateTime(Date createTime) {\n        this.createTime = createTime;\n    }\n\n    public Date getPassedTime() {\n        return passedTime;\n    }\n\n    public void setPassedTime(Date passedTime) {\n        this.passedTime = passedTime;\n    }\n\n    public int getType() {\n        return type;\n    }\n\n    public void setType(int type) {\n        this.type = type;\n    }\n\n    public String getOfficer() {\n        return officer;\n    }\n\n    public void setOfficer(String officer) {\n        this.officer = officer;\n    }\n\n    public int getVerId() {\n        return verId;\n    }\n\n    public void setVerId(int verId) {\n        this.verId = verId;\n    }\n\n    public int getIsTest() {\n        return isTest;\n    }\n\n    public void setIsTest(int isTest) {\n        this.isTest = isTest;\n    }\n\n    public int getHasBackStore() {\n        return hasBackStore;\n    }\n\n    public void setHasBackStore(int hasBackStore) {\n        this.hasBackStore = hasBackStore;\n    }\n\n    public int getNeedPersistence() {\n        return needPersistence;\n    }\n\n    public void setNeedPersistence(int needPersistence) {\n        this.needPersistence = needPersistence;\n    }\n\n\n    public int getForecaseQps() {\n        return forecaseQps;\n    }\n\n    public void setForecaseQps(int forecaseQps) {\n        this.forecaseQps = forecaseQps;\n    }\n\n    public int getNeedHotBackUp() {\n        return needHotBackUp;\n    }\n\n    public void setNeedHotBackUp(int needHotBackUp) {\n        this.needHotBackUp = needHotBackUp;\n    }\n\n    public int getForecastObjNum() {\n        return forecastObjNum;\n    }\n\n    public void setForecastObjNum(int forecastObjNum) {\n        this.forecastObjNum = forecastObjNum;\n    }\n\n    public int getMemAlertValue() {\n        return memAlertValue;\n    }\n\n    public void setMemAlertValue(int memAlertValue) {\n        this.memAlertValue = memAlertValue;\n    }\n\n    public void setTypeDesc(String typeDesc) {\n        this.typeDesc = typeDesc;\n    }\n\n    public String getClientMachineRoom() {\n        return clientMachineRoom;\n    }\n\n    public void setClientMachineRoom(String clientMachineRoom) {\n        this.clientMachineRoom = clientMachineRoom;\n    }\n    \n    public String getAppKey() {\n        return appKey;\n    }\n\n    public void setAppKey(String appKey) {\n        this.appKey = appKey;\n    }\n\n    public int getClientConnAlertValue() {\n        return clientConnAlertValue;\n    }\n\n    public void setClientConnAlertValue(int clientConnAlertValue) {\n        this.clientConnAlertValue = clientConnAlertValue;\n    }\n    \n    public int getImportantLevel() {\n        return importantLevel;\n    }\n\n    public void setImportantLevel(int importantLevel) {\n        this.importantLevel = importantLevel;\n    }\n    \n    public String getPassword() {\n        return password;\n    }\n\n    public void setPassword(String password) {\n        this.password = password;\n    }\n\n    /**\n     * 应用运行天数\n     */\n    public int getAppRunDays() {\n        if (createTime == null) {\n            return -1;\n        }\n        Date now = new Date();\n        long diff = now.getTime() - createTime.getTime();\n        return (int) (diff / TimeUnit.DAYS.toMillis(1));\n    }\n\n    public String getTypeDesc() {\n        if (type <= 0) {\n            return \"\";\n        } else if (type == ConstUtils.CACHE_TYPE_REDIS_CLUSTER) {\n            return \"redis-cluster\";\n        } else if (type == ConstUtils.CACHE_REDIS_SENTINEL) {\n            return \"redis-sentinel\";\n        } else if (type == ConstUtils.CACHE_REDIS_STANDALONE) {\n            return \"redis-standalone\";\n        }\n        return \"\";\n    }\n    \n    public String getCreateTimeFormat(){\n        SimpleDateFormat sdf = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n        if(createTime != null){\n            return sdf.format(createTime);\n        }\n        return \"\";\n    }\n\n\n    @Override\n    public String toString() {\n        return JSONObject.toJSONString(this);\n    }\n\n    public String getStatusDesc() {\n        AppStatusEnum appStatusEnum = AppStatusEnum.getByStatus(status);\n        if (appStatusEnum != null) {\n            return appStatusEnum.getInfo();\n        }\n        return \"\";\n    }\n\n\n    /**\n     * 是否下线\n     * @return\n     */\n    public boolean isOffline() {\n        return status == AppStatusEnum.STATUS_OFFLINE.getStatus();\n    }\n\n    /**\n     * 是否是测试\n     * @return\n     */\n    public boolean isTest() {\n        return isTest == AppDescEnum.AppTest.IS_TEST.getValue();\n    }\n\n    /**\n     * 非常重要\n     * @return\n     */\n    public boolean isVeryImportant() {\n        return importantLevel == AppDescEnum.AppImportantLevel.VERY_IMPORTANT.getValue();\n    }\n    \n    /**\n     * 超级重要\n     * @return\n     */\n    public boolean isSuperImportant() {\n        return importantLevel == AppDescEnum.AppImportantLevel.SUPER_IMPORTANT.getValue();\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/AppInstanceClientRelation.java",
    "content": "package com.sohu.cache.entity;\n\nimport java.util.Date;\n\n/**\n * 应用下实例与客户端对应关系\n * \n * @author leifu\n * @Date 2016年5月3日\n * @Time 下午6:50:04\n */\npublic class AppInstanceClientRelation {\n\n    /**\n     * 应用id\n     */\n    private long appId;\n\n    /**\n     * 客户端ip\n     */\n    private String clientIp;\n\n    /**\n     * 节点ip\n     */\n    private String instanceHost;\n\n    /**\n     * 节点端口\n     */\n    private int instancePort;\n\n    /**\n     * 节点端口\n     */\n    private long instanceId;\n\n    /**\n     * 日期\n     */\n    private Date day;\n\n    public AppInstanceClientRelation(long appId, String clientIp, String instanceHost, int instancePort,\n            long instanceId, Date day) {\n        this.appId = appId;\n        this.clientIp = clientIp;\n        this.instanceHost = instanceHost;\n        this.instancePort = instancePort;\n        this.instanceId = instanceId;\n        this.day = day;\n    }\n\n    public AppInstanceClientRelation() {\n    }\n\n    public long getAppId() {\n        return appId;\n    }\n\n    public void setAppId(long appId) {\n        this.appId = appId;\n    }\n\n    public String getClientIp() {\n        return clientIp;\n    }\n\n    public void setClientIp(String clientIp) {\n        this.clientIp = clientIp;\n    }\n\n    public String getInstanceHost() {\n        return instanceHost;\n    }\n\n    public void setInstanceHost(String instanceHost) {\n        this.instanceHost = instanceHost;\n    }\n\n    public int getInstancePort() {\n        return instancePort;\n    }\n\n    public void setInstancePort(int instancePort) {\n        this.instancePort = instancePort;\n    }\n\n    public long getInstanceId() {\n        return instanceId;\n    }\n\n    public void setInstanceId(long instanceId) {\n        this.instanceId = instanceId;\n    }\n\n    public Date getDay() {\n        return day;\n    }\n\n    public void setDay(Date day) {\n        this.day = day;\n    }\n\n    @Override\n    public String toString() {\n        return \"AppInstanceClientRelation [appId=\" + appId + \", clientIp=\" + clientIp + \", instanceHost=\"\n                + instanceHost + \", instancePort=\" + instancePort + \", instanceId=\" + instanceId + \", day=\" + day + \"]\";\n    }\n\n    public static AppInstanceClientRelation generateFromAppClientCostTimeStat(\n            AppClientCostTimeStat appClientCostTimeStat) {\n        if (appClientCostTimeStat == null) {\n            return null;\n        } else {\n            return new AppInstanceClientRelation(appClientCostTimeStat.getAppId(),\n                    appClientCostTimeStat.getClientIp(), appClientCostTimeStat.getInstanceHost(), appClientCostTimeStat\n                            .getInstancePort(), appClientCostTimeStat.getInstanceId(), new Date(\n                            System.currentTimeMillis()));\n        }\n    }\n\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/AppSearch.java",
    "content": "package com.sohu.cache.entity;\n\nimport com.sohu.cache.web.util.Page;\n\n/**\n * 搜索实体\n * \n * @author leifu\n * @Date 2014年11月14日\n * @Time 上午10:44:01\n */\npublic class AppSearch {\n    /**\n     * 应用id\n     */\n    private Long appId;\n\n    /**\n     * 应用名\n     */\n    private String appName;\n\n    /**\n     * 应用类型\n     */\n    private Integer appType;\n\n    /**\n     * 申请状态\n     */\n    private Integer appStatus;\n    \n    /**\n     * 命中率排序\n     */\n    private String orderBy;\n    \n    /**\n     * 重要度\n     */\n    private Integer importantLevel;\n    \n    /**\n     * 分页\n     */\n    private Page page;\n    \n    public Long getAppId() {\n        return appId;\n    }\n\n    public void setAppId(Long appId) {\n        this.appId = appId;\n    }\n\n    public String getAppName() {\n        return appName;\n    }\n\n    public void setAppName(String appName) {\n        this.appName = appName;\n    }\n\n    public Integer getAppType() {\n        return appType;\n    }\n\n    public void setAppType(Integer appType) {\n        this.appType = appType;\n    }\n\n    public Integer getAppStatus() {\n        return appStatus;\n    }\n\n    public void setAppStatus(Integer appStatus) {\n        this.appStatus = appStatus;\n    }\n\n    public String getOrderBy() {\n        return orderBy;\n    }\n\n    public void setOrderBy(String orderBy) {\n        this.orderBy = orderBy;\n    }\n\n    public Page getPage() {\n        return page;\n    }\n\n    public void setPage(Page page) {\n        this.page = page;\n    }\n\n    public Integer getImportantLevel() {\n        return importantLevel;\n    }\n\n    public void setImportantLevel(Integer importantLevel) {\n        this.importantLevel = importantLevel;\n    }\n\n    @Override\n    public String toString() {\n        return \"AppSearch [appId=\" + appId + \", appName=\" + appName + \", appType=\" + appType + \", appStatus=\"\n                + appStatus + \", orderBy=\" + orderBy + \", importantLevel=\" + importantLevel + \", page=\" + page + \"]\";\n    }\n\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/AppStats.java",
    "content": "package com.sohu.cache.entity;\n\nimport java.text.DecimalFormat;\nimport java.text.NumberFormat;\nimport java.util.Date;\nimport java.util.List;\n\nimport org.apache.commons.lang.math.NumberUtils;\n\n/**\n * Created by yijunzhang on 14-6-9.\n */\npublic class AppStats {\n\n    /**\n     * 应用id\n     */\n    private long appId;\n\n    /**\n     * 收集时间:格式yyyyMMddHHmm/yyyyMMdd/yyyyMMddHH\n     */\n    private long collectTime;\n\n    /**\n     * 命中数量\n     */\n    private long hits;\n\n    /**\n     * 未命中数量\n     */\n    private long misses;\n\n    /**\n     * 命令执行次数\n     */\n    private long commandCount;\n\n    /**\n     * 内存占用\n     */\n    private long usedMemory;\n\n    /**\n     * 过期key数量\n     */\n    private long expiredKeys;\n\n    /**\n     * 驱逐key数量\n     */\n    private long evictedKeys;\n\n    /**\n     * 网络输入字节\n     */\n    private long netInputByte;\n\n    /**\n     * 网络输出字节\n     */\n    private long netOutputByte;\n\n    /**\n     * 客户端连接数\n     */\n    private int connectedClients;\n\n    /**\n     * 存储对象数\n     */\n    private long objectSize;\n\n    /**\n     * 累加的实例数\n     */\n    private int accumulation;\n\n    /**\n     * 创建时间\n     */\n    private Date createTime;\n    /**\n     * 修改时间\n     */\n    private Date modifyTime;\n\n    /**\n     * 命令统计集合\n     */\n    private List<AppCommandStats> commandStatsList;\n\n    public long getAppId() {\n        return appId;\n    }\n\n    public void setAppId(long appId) {\n        this.appId = appId;\n    }\n\n    public long getCollectTime() {\n        return collectTime;\n    }\n\n    public void setCollectTime(long collectTime) {\n        this.collectTime = collectTime;\n    }\n\n    public long getHits() {\n        return hits;\n    }\n    \n    /**\n     * 命中率\n     * @return\n     */\n    public long getHitPercent() {\n        long total = hits + misses;\n        if (total == 0) {\n            return 0;\n        } else {\n            NumberFormat formatter = new DecimalFormat(\"0\");\n            return NumberUtils.toLong(formatter.format(hits * 100.0 / total));\n        }\n    }\n    \n    public void setHits(long hits) {\n        this.hits = hits;\n    }\n\n    public long getMisses() {\n        return misses;\n    }\n\n    public void setMisses(long misses) {\n        this.misses = misses;\n    }\n\n    public long getUsedMemory() {\n        return usedMemory;\n    }\n\n    public void setUsedMemory(long usedMemory) {\n        this.usedMemory = usedMemory;\n    }\n\n    public long getExpiredKeys() {\n        return expiredKeys;\n    }\n\n    public void setExpiredKeys(long expiredKeys) {\n        this.expiredKeys = expiredKeys;\n    }\n\n    public long getEvictedKeys() {\n        return evictedKeys;\n    }\n\n    public void setEvictedKeys(long evictedKeys) {\n        this.evictedKeys = evictedKeys;\n    }\n\n    public int getConnectedClients() {\n        return connectedClients;\n    }\n\n    public void setConnectedClients(int connectedClients) {\n        this.connectedClients = connectedClients;\n    }\n\n    public Date getCreateTime() {\n        return createTime;\n    }\n\n    public void setCreateTime(Date createTime) {\n        this.createTime = createTime;\n    }\n\n    public Date getModifyTime() {\n        return modifyTime;\n    }\n\n    public void setModifyTime(Date modifyTime) {\n        this.modifyTime = modifyTime;\n    }\n\n    @Override\n    public String toString() {\n        return \"AppStats{\" +\n                \"appId=\" + appId +\n                \", collectTime=\" + collectTime +\n                \", hits=\" + hits +\n                \", misses=\" + misses +\n                \", usedMemory=\" + usedMemory +\n                \", expiredKeys=\" + expiredKeys +\n                \", evictedKeys=\" + evictedKeys +\n                \", connectedClients=\" + connectedClients +\n                \", createTime=\" + createTime +\n                \", modifyTime=\" + modifyTime +\n                \", objectSize=\" + objectSize +\n                \", accumulation=\" + accumulation +\n                '}';\n    }\n\n    public long getCommandCount() {\n        return commandCount;\n    }\n\n    public void setCommandCount(long commandCount) {\n        this.commandCount = commandCount;\n    }\n\n    public void setObjectSize(long objectSize) {\n        this.objectSize = objectSize;\n    }\n\n    public long getObjectSize() {\n        return objectSize;\n    }\n\n    public int getAccumulation() {\n        return accumulation;\n    }\n\n    public void setAccumulation(int accumulation) {\n        this.accumulation = accumulation;\n    }\n\n    public List<AppCommandStats> getCommandStatsList() {\n        return commandStatsList;\n    }\n\n    public void setCommandStatsList(List<AppCommandStats> commandStatsList) {\n        this.commandStatsList = commandStatsList;\n    }\n\n    public long getNetInputByte() {\n        return netInputByte;\n    }\n\n    public void setNetInputByte(long netInputByte) {\n        this.netInputByte = netInputByte;\n    }\n\n    public long getNetOutputByte() {\n        return netOutputByte;\n    }\n\n    public void setNetOutputByte(long netOutputByte) {\n        this.netOutputByte = netOutputByte;\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/AppToUser.java",
    "content": "package com.sohu.cache.entity;\n\nimport java.io.Serializable;\n\nimport org.apache.commons.lang.builder.ToStringBuilder;\n\n/**\n * 应用和用户的对应关系\n * \n * @author leifu\n * @Time 2014年6月5日\n */\npublic class AppToUser implements Serializable {\n\n    private static final long serialVersionUID = 1326072190198022633L;\n\n    /**\n     * 自增id\n     */\n    private Long id;\n\n    /**\n     * 用户id\n     */\n    private Long userId;\n\n    /**\n     * 应用id\n     */\n    private Long appId;\n    \n\n    public AppToUser() {\n        super();\n    }\n\n    public AppToUser(Long userId, Long appId) {\n        super();\n        this.userId = userId;\n        this.appId = appId;\n    }\n\n    public Long getId() {\n        return id;\n    }\n\n    public void setId(Long id) {\n        this.id = id;\n    }\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 getAppId() {\n        return appId;\n    }\n\n    public void setAppId(Long appId) {\n        this.appId = appId;\n    }\n\n    @Override\n    public String toString() {\n        return ToStringBuilder.reflectionToString(this).toString();\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/AppUser.java",
    "content": "package com.sohu.cache.entity;\n\nimport java.io.Serializable;\n\nimport org.apache.commons.lang.builder.ToStringBuilder;\n\n/**\n * 系统用户信息\n * \n * @author leifu\n * @Time 2014年6月5日\n */\npublic class AppUser implements Serializable {\n\n    private static final long serialVersionUID = 7425158151337667662L;\n\n    /**\n     * 自增id\n     */\n    private Long id;\n\n    /**\n     * 用户名(英文，域账户)\n     */\n    private String name;\n    \n    /**\n     * 中文名\n     */\n    private String chName;\n    \n    /**\n     * 用户域账户邮箱\n     */\n    private String email;\n\n    /**\n     * 用户手机\n     */\n    private String mobile;\n\n    /**\n     * 用户类型(类型参考AppUserTypeEnum)\n     */\n    private int type;\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 String getEmail() {\n        return email;\n    }\n\n    public void setEmail(String email) {\n        this.email = email;\n    }\n\n    public String getMobile() {\n        return mobile;\n    }\n\n    public void setMobile(String mobile) {\n        this.mobile = mobile;\n    }\n\n    public int getType() {\n        return type;\n    }\n\n    public void setType(int type) {\n        this.type = type;\n    }\n\n    public String getChName() {\n        return chName;\n    }\n\n    public void setChName(String chName) {\n        this.chName = chName;\n    }\n\n    @Override\n    public String toString() {\n        return ToStringBuilder.reflectionToString(this).toString();\n    }\n\n    public static AppUser buildFrom(Long userId, String name, String chName, String email, String mobile,\n            Integer type) {\n        AppUser appUser = new AppUser();\n        appUser.setId(userId);\n        appUser.setName(name);\n        appUser.setChName(chName);\n        appUser.setEmail(email);\n        appUser.setMobile(mobile);\n        appUser.setType(type);\n        return appUser;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/ClientInstanceException.java",
    "content": "package com.sohu.cache.entity;\n\n/**\n * 客户端实例异常\n * @author leifu\n * @Date 2016年2月18日\n * @Time 下午5:07:42\n */\npublic class ClientInstanceException {\n\n    private long appId;\n\n    private long instanceId;\n\n    private String instanceHost;\n\n    private int instancePort;\n\n    private int exceptionCount;\n\n    public ClientInstanceException(long appId, long instanceId, String instanceHost, int instancePort, int exceptionCount) {\n        this.appId = appId;\n        this.instanceId = instanceId;\n        this.instanceHost = instanceHost;\n        this.instancePort = instancePort;\n        this.exceptionCount = exceptionCount;\n    }\n\n    public ClientInstanceException() {\n    }\n\n    public long getAppId() {\n        return appId;\n    }\n\n    public void setAppId(long appId) {\n        this.appId = appId;\n    }\n\n    public long getInstanceId() {\n        return instanceId;\n    }\n\n    public void setInstanceId(long instanceId) {\n        this.instanceId = instanceId;\n    }\n\n    public String getInstanceHost() {\n        return instanceHost;\n    }\n\n    public void setInstanceHost(String instanceHost) {\n        this.instanceHost = instanceHost;\n    }\n\n    public int getInstancePort() {\n        return instancePort;\n    }\n\n    public void setInstancePort(int instancePort) {\n        this.instancePort = instancePort;\n    }\n\n    public int getExceptionCount() {\n        return exceptionCount;\n    }\n\n    public void setExceptionCount(int exceptionCount) {\n        this.exceptionCount = exceptionCount;\n    }\n\n    @Override\n    public String toString() {\n        return \"ClientInstanceExceptionVO [appId=\" + appId + \", instanceId=\" + instanceId + \", instanceHost=\" + instanceHost\n                + \", instancePort=\" + instancePort + \", exceptionCount=\" + exceptionCount + \"]\";\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/InstanceAlertConfig.java",
    "content": "package com.sohu.cache.entity;\n\nimport java.util.Date;\nimport java.util.concurrent.TimeUnit;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.sohu.cache.redis.enums.InstanceAlertCheckCycleEnum;\nimport com.sohu.cache.redis.enums.InstanceAlertCompareTypeEnum;\nimport com.sohu.cache.redis.enums.InstanceAlertTypeEnum;\n\n/**\n * 实例报警阀值配置\n * @author leifu\n * @Date 2017年5月19日\n * @Time 上午11:09:16\n */\npublic class InstanceAlertConfig {\n    \n    /**\n     * 自增id\n     */\n    private long id;\n    \n    /**\n     * 报警配置\n     */\n    private String alertConfig;\n\n    /**\n     * 报警阀值\n     */\n    private String alertValue;\n    \n    /**\n     * 详见CompareTypeEnumNew\n     */\n    private int compareType;\n\n    /**\n     * 配置说明\n     */\n    private String configInfo;\n    \n    /**\n     * 详见TypeEnum\n     */\n    private int type;\n    \n    /**\n     * -1全局配置，其他代表实例id\n     */\n    private long instanceId;\n    \n    /**\n     * 实例信息\n     */\n    private InstanceInfo instanceInfo;\n\n    /**\n     * 相关StatusEnum\n     */\n    private int status;\n\n    /**\n     * 详见CheckCycleEnum\n     */\n    private int checkCycle;\n    \n    /**\n     * 配置更新时间\n     */\n    private Date updateTime;\n    \n    /**\n     * 上次检测时间\n     */\n    private Date lastCheckTime;\n\n    public InstanceAlertConfig() {\n        super();\n    }\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 getAlertConfig() {\n        return alertConfig;\n    }\n\n    public void setAlertConfig(String alertConfig) {\n        this.alertConfig = alertConfig;\n    }\n\n    public String getAlertValue() {\n        return alertValue;\n    }\n\n    public void setAlertValue(String alertValue) {\n        this.alertValue = alertValue;\n    }\n\n    public int getCompareType() {\n        return compareType;\n    }\n    \n    public String getCompareInfo() {\n        return InstanceAlertCompareTypeEnum.getInstanceAlertCompareTypeEnum(compareType).getInfo();\n    }\n\n    public void setCompareType(int compareType) {\n        this.compareType = compareType;\n    }\n\n    public String getConfigInfo() {\n        return configInfo;\n    }\n\n    public void setConfigInfo(String configInfo) {\n        this.configInfo = configInfo;\n    }\n\n    public int getType() {\n        return type;\n    }\n\n    public void setType(int type) {\n        this.type = type;\n    }\n\n    public long getInstanceId() {\n        return instanceId;\n    }\n\n    public void setInstanceId(long instanceId) {\n        this.instanceId = instanceId;\n    }\n\n    public int getStatus() {\n        return status;\n    }\n\n    public void setStatus(int status) {\n        this.status = status;\n    }\n\n    public int getCheckCycle() {\n        return checkCycle;\n    }\n\n    public void setCheckCycle(int checkCycle) {\n        this.checkCycle = checkCycle;\n    }\n\n    public Date getUpdateTime() {\n        return updateTime;\n    }\n\n    public void setUpdateTime(Date updateTime) {\n        this.updateTime = updateTime;\n    }\n\n    public Date getLastCheckTime() {\n        return lastCheckTime;\n    }\n\n    public void setLastCheckTime(Date lastCheckTime) {\n        this.lastCheckTime = lastCheckTime;\n    }\n    \n    public InstanceInfo getInstanceInfo() {\n        return instanceInfo;\n    }\n\n    public void setInstanceInfo(InstanceInfo instanceInfo) {\n        this.instanceInfo = instanceInfo;\n    }\n\n    public Long getCheckCycleMillionTime() {\n        if (InstanceAlertCheckCycleEnum.ONE_MINUTE.getValue() == checkCycle) {\n            return TimeUnit.MINUTES.toMillis(1);\n        } else if (InstanceAlertCheckCycleEnum.FIVE_MINUTE.getValue() == checkCycle) {\n            return TimeUnit.MINUTES.toMillis(5);\n        } else if (InstanceAlertCheckCycleEnum.HALF_HOUR.getValue() == checkCycle) {\n            return TimeUnit.MINUTES.toMillis(30);\n        } else if (InstanceAlertCheckCycleEnum.ONE_HOUR.getValue() == checkCycle) {\n            return TimeUnit.MINUTES.toMillis(60);\n        } else if (InstanceAlertCheckCycleEnum.ONE_DAY.getValue() == checkCycle) {\n            return TimeUnit.DAYS.toMillis(1);\n        } \n        return null;\n    }\n    \n    public boolean isSpecail() {\n        return instanceId > 0 && type == InstanceAlertTypeEnum.INSTANCE_ALERT.getValue();\n    }\n\n    @Override\n    public String toString() {\n        return JSONObject.toJSONString(this);\n    }\n\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/InstanceAlertValueResult.java",
    "content": "package com.sohu.cache.entity;\n\nimport com.alibaba.fastjson.JSONObject;\n\n/**\n * 实例报警结果\n * @author leifu\n * @Date 2017年6月19日\n * @Time 下午10:50:23\n */\npublic class InstanceAlertValueResult {\n    \n    /**\n     * 实例报警配置\n     */\n    private InstanceAlertConfig instanceAlertConfig;\n    \n    /**\n     * 实例信息\n     */\n    private InstanceInfo instanceInfo;\n\n    /**\n     * 当前值\n     */\n    private String currentValue;\n    \n    /**\n     * 应用id\n     */\n    private long appId;\n    \n    /**\n     * 单位\n     */\n    private String unit;\n\n    /**\n     * 应用信息\n     */\n    private AppDesc appDesc;\n    \n    /**\n     * 其他信息\n     */\n    private String otherInfo;\n\n    public InstanceAlertValueResult() {\n    }\n\n    public InstanceAlertValueResult(InstanceAlertConfig instanceAlertConfig, InstanceInfo instanceInfo,\n            String currentValue, long appId, String unit) {\n        this.instanceAlertConfig = instanceAlertConfig;\n        this.instanceInfo = instanceInfo;\n        this.currentValue = currentValue;\n        this.appId = appId;\n        this.unit = unit;\n    }\n\n    public InstanceAlertConfig getInstanceAlertConfig() {\n        return instanceAlertConfig;\n    }\n\n    public void setInstanceAlertConfig(InstanceAlertConfig instanceAlertConfig) {\n        this.instanceAlertConfig = instanceAlertConfig;\n    }\n\n    public InstanceInfo getInstanceInfo() {\n        return instanceInfo;\n    }\n\n    public void setInstanceInfo(InstanceInfo instanceInfo) {\n        this.instanceInfo = instanceInfo;\n    }\n\n    public String getCurrentValue() {\n        return currentValue;\n    }\n\n    public void setCurrentValue(String currentValue) {\n        this.currentValue = currentValue;\n    }\n\n    public long getAppId() {\n        return appId;\n    }\n\n    public void setAppId(long appId) {\n        this.appId = appId;\n    }\n\n    public AppDesc getAppDesc() {\n        return appDesc;\n    }\n\n    public void setAppDesc(AppDesc appDesc) {\n        this.appDesc = appDesc;\n    }\n\n    public String getUnit() {\n        return unit;\n    }\n\n    public String getOtherInfo() {\n        return otherInfo;\n    }\n\n    public void setOtherInfo(String otherInfo) {\n        this.otherInfo = otherInfo;\n    }\n\n    public void setUnit(String unit) {\n        this.unit = unit;\n    }\n\n    public String getAlertMessage() {\n        return String.format(\"实际值为%s%s,%s预设值%s%s\", currentValue, unit, instanceAlertConfig.getCompareInfo(),\n                instanceAlertConfig.getAlertValue(), unit);\n    }\n    \n    @Override\n    public String toString() {\n        return JSONObject.toJSONString(this);\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/InstanceCommandStats.java",
    "content": "package com.sohu.cache.entity;\n\nimport java.text.ParseException;\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\n\n\npublic class InstanceCommandStats implements Comparable<InstanceCommandStats> {\n\n    /**\n     * 应用id\n     */\n    private long instanceId;\n\n    /**\n     * 收集时间:格式yyyyMMddHHmm/yyyyMMdd/yyyyMMddHH\n     */\n    private long collectTime;\n\n    /**\n     * 命令名称\n     */\n    private String commandName;\n\n    /**\n     * 命令执行次数\n     */\n    private long commandCount;\n\n    /**\n     * 创建时间\n     */\n    private Date createTime;\n\n    /**\n     * 修改时间\n     */\n    private Date modifyTime;\n\n    public long getInstanceId() {\n        return instanceId;\n    }\n\n    public void setInstanceId(long instanceId) {\n        this.instanceId = instanceId;\n    }\n\n    public long getCollectTime() {\n        return collectTime;\n    }\n\n    public void setCollectTime(long collectTime) {\n        this.collectTime = collectTime;\n    }\n\n    public String getCommandName() {\n        return commandName;\n    }\n\n    public void setCommandName(String commandName) {\n        this.commandName = commandName;\n    }\n\n    public long getCommandCount() {\n        return commandCount;\n    }\n\n    public void setCommandCount(long commandCount) {\n        this.commandCount = commandCount;\n    }\n\n    public Date getCreateTime() {\n        return createTime;\n    }\n\n    public void setCreateTime(Date createTime) {\n        this.createTime = createTime;\n    }\n\n    public Date getModifyTime() {\n        return modifyTime;\n    }\n\n    public void setModifyTime(Date modifyTime) {\n        this.modifyTime = modifyTime;\n    }\n\n    @Override\n    public int compareTo(InstanceCommandStats o) {\n        if (o.commandCount > this.commandCount) {\n            return 1;\n        } else if (o.commandCount < this.commandCount) {\n            return -1;\n        }\n        return 0;\n    }\n    \n    public Long getTimeStamp() throws ParseException{\n        SimpleDateFormat sdf = new SimpleDateFormat(\"yyyyMMddHHmm\");\n        Date date = sdf.parse(String.valueOf(this.collectTime));\n        return date.getTime();\n    }\n\n    @Override\n    public String toString() {\n        return \"InstanceCommandStats{\" +\n                \"instanceId=\" + instanceId +\n                \", collectTime=\" + collectTime +\n                \", commandName='\" + commandName + '\\'' +\n                \", commandCount=\" + commandCount +\n                \", createTime=\" + createTime +\n                \", modifyTime=\" + modifyTime +\n                '}';\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/InstanceConfig.java",
    "content": "package com.sohu.cache.entity;\n\nimport java.util.Date;\n\n/**\n * 实例配置模板\n * @author leifu\n * @Date 2016年6月22日\n * @Time 下午5:45:29\n */\npublic class InstanceConfig {\n    \n    private long id;\n    \n    /**\n     * 配置名:为了防止与key冲突\n     */\n    private String configKey;\n    \n    /**\n     * 配置值:为了防止与value冲突\n     */\n    private String configValue;\n    \n    /**\n     * 配置说明\n     */\n    private String info;\n    \n    /**\n     * 更新时间\n     */\n    private Date updateTime;\n    \n    /**\n     * Redis类型(参考ConstUtil)\n     */\n    private int type;\n    \n    /**\n     * 状态，1有效0无效\n     */\n    private int status;\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 getConfigKey() {\n        return configKey;\n    }\n\n    public void setConfigKey(String configKey) {\n        this.configKey = configKey;\n    }\n\n    public String getConfigValue() {\n        return configValue;\n    }\n\n    public void setConfigValue(String configValue) {\n        this.configValue = configValue;\n    }\n\n    public String getInfo() {\n        return info;\n    }\n\n    public void setInfo(String info) {\n        this.info = info;\n    }\n\n    public Date getUpdateTime() {\n        return updateTime;\n    }\n\n    public void setUpdateTime(Date updateTime) {\n        this.updateTime = updateTime;\n    }\n\n    public int getType() {\n        return type;\n    }\n\n    public void setType(int type) {\n        this.type = type;\n    }\n\n    public int getStatus() {\n        return status;\n    }\n    \n    public String getStatusDesc() {\n        if (1 == status) {\n            return \"有效\";\n        } else if (0 == status) {\n            return \"无效\";\n        } else {\n            return \"\";\n        }\n    }\n\n    public void setStatus(int status) {\n        this.status = status;\n    }\n    \n    public boolean isEffective() {\n        if (1 == getStatus()) {\n            return true;\n        }\n        return false;\n    }\n\n    @Override\n    public String toString() {\n        return \"InstanceConfig [id=\" + id + \", configKey=\" + configKey + \", configValue=\" + configValue\n                + \", info=\" + info  + \", updateTime=\" + updateTime\n                + \", type=\" + type + \", status=\" + status + \"]\";\n    }\n    \n    \n\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/InstanceFault.java",
    "content": "package com.sohu.cache.entity;\n\nimport java.io.Serializable;\nimport java.util.Date;\n\npublic class InstanceFault implements Serializable {\n\n    private static final long serialVersionUID = 8141174905675892249L;\n\n    private int id;\n\n    private int appId;\n\n    private int instId;\n\n    private String ip;\n\n    private int port;\n\n    private int status;\n\n    private int type;\n\n    private Date createTime;\n\n    private String reason;\n\n    public int getId() {\n        return id;\n    }\n\n    public void setId(int id) {\n        this.id = id;\n    }\n\n    public int getAppId() {\n        return appId;\n    }\n\n    public void setAppId(int appId) {\n        this.appId = appId;\n    }\n\n    public int getInstId() {\n        return instId;\n    }\n\n    public void setInstId(int instId) {\n        this.instId = instId;\n    }\n\n    public String getIp() {\n        return ip;\n    }\n\n    public void setIp(String ip) {\n        this.ip = ip;\n    }\n\n    public int getPort() {\n        return port;\n    }\n\n    public void setPort(int port) {\n        this.port = port;\n    }\n\n    public int getStatus() {\n        return status;\n    }\n\n    public void setStatus(int status) {\n        this.status = status;\n    }\n\n    public int getType() {\n        return type;\n    }\n\n    public void setType(int type) {\n        this.type = type;\n    }\n\n    public Date getCreateTime() {\n        return createTime;\n    }\n\n    public void setCreateTime(Date createTime) {\n        this.createTime = createTime;\n    }\n\n    public String getReason() {\n        return reason;\n    }\n\n    public void setReason(String reason) {\n        this.reason = reason;\n    }\n\n    public String getTypeDesc() {\n        InstanceInfo info = new InstanceInfo();\n        info.setType(type);\n        return info.getTypeDesc();\n    }\n\n    public String getStatusDesc() {\n        InstanceInfo info = new InstanceInfo();\n        info.setStatus(this.status);\n        return info.getStatusDesc();\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/InstanceInfo.java",
    "content": "package com.sohu.cache.entity;\n\nimport com.sohu.cache.constant.InstanceStatusEnum;\nimport com.sohu.cache.util.ConstUtils;\n\nimport java.io.Serializable;\n\n/**\n * 实例信息\n * User: lingguo\n * Date: 14-5-29\n * Time: 下午9:38\n */\npublic class InstanceInfo implements Serializable {\n    private static final long serialVersionUID = -903896025243493024L;\n\n    /**\n     * 实例id\n     */\n    private int id;\n\n    /**\n     * 应用id\n     */\n    private long appId;\n\n    /**\n     * host id\n     */\n    private long hostId;\n\n    /**\n     * ip\n     */\n    private String ip;\n\n    /**\n     * 端口\n     */\n    private int port;\n\n    /**\n     * 是否启用 0:节点异常,1:正常启用,2:节点下线\n     */\n    private int status;\n\n    /**\n     * 开启的内存\n     */\n    private int mem;\n\n    /**\n     * 连接数\n     */\n    private int conn;\n\n    /**\n     * 启动命令 或者 redis-sentinel的masterName\n     */\n    private String cmd;\n\n    private int type;\n\n    private String typeDesc;\n\n    private int masterInstanceId;\n\n    private String masterHost;\n\n    private int masterPort;\n\n    private String roleDesc;\n    \n    private int groupId;\n\n    public int getId() {\n        return id;\n    }\n\n    public void setId(int id) {\n        this.id = id;\n    }\n\n    public long getAppId() {\n        return appId;\n    }\n\n    public void setAppId(long appId) {\n        this.appId = appId;\n    }\n\n    public long getHostId() {\n        return hostId;\n    }\n\n    public void setHostId(long hostId) {\n        this.hostId = hostId;\n    }\n\n    public String getIp() {\n        return ip;\n    }\n\n    public void setIp(String ip) {\n        this.ip = ip;\n    }\n\n    public int getPort() {\n        return port;\n    }\n\n    public void setPort(int port) {\n        this.port = port;\n    }\n\n    public int getStatus() {\n        return status;\n    }\n\n    public void setStatus(int status) {\n        this.status = status;\n    }\n\n    public int getMem() {\n        return mem;\n    }\n\n    public void setMem(int mem) {\n        this.mem = mem;\n    }\n\n    public int getConn() {\n        return conn;\n    }\n\n    public void setConn(int conn) {\n        this.conn = conn;\n    }\n\n    public String getCmd() {\n        return cmd;\n    }\n\n    public void setCmd(String cmd) {\n        this.cmd = cmd;\n    }\n\n    public int getType() {\n        return type;\n    }\n\n    public void setType(int type) {\n        this.type = type;\n    }\n\n    public String getTypeDesc() {\n        if (type <= 0) {\n            return \"\";\n        } else if (type == ConstUtils.CACHE_TYPE_REDIS_CLUSTER) {\n            return \"redis-cluster\";\n        } else if (type == ConstUtils.CACHE_REDIS_SENTINEL) {\n            return \"redis-sentinel\";\n        } else if (type == ConstUtils.CACHE_REDIS_STANDALONE) {\n            return \"redis-standalone\";\n        }\n        return \"\";\n    }\n\n    @Override\n    public String toString() {\n        return \"InstanceInfo{\" +\n                \"id=\" + id +\n                \", appId=\" + appId +\n                \", hostId=\" + hostId +\n                \", ip='\" + ip + '\\'' +\n                \", port=\" + port +\n                \", status=\" + status +\n                \", mem=\" + mem +\n                \", conn=\" + conn +\n                \", cmd='\" + cmd + '\\'' +\n                \", type=\" + type +\n                \", group=\" + groupId +\n                '}';\n    }\n\n    public int getMasterInstanceId() {\n        return masterInstanceId;\n    }\n\n    public void setMasterInstanceId(int masterInstanceId) {\n        this.masterInstanceId = masterInstanceId;\n    }\n\n    public String getMasterHost() {\n        return masterHost;\n    }\n\n    public void setMasterHost(String masterHost) {\n        this.masterHost = masterHost;\n    }\n\n    public int getMasterPort() {\n        return masterPort;\n    }\n\n    public void setMasterPort(int masterPort) {\n        this.masterPort = masterPort;\n    }\n\n    public int getGroupId() {\n        return groupId;\n    }\n\n    public void setGroupId(int groupId) {\n        this.groupId = groupId;\n    }\n\n    public String getStatusDesc() {\n        InstanceStatusEnum instanceStatusEnum = InstanceStatusEnum.getByStatus(status);\n        if (instanceStatusEnum != null) {\n            return instanceStatusEnum.getInfo();\n        }\n        return \"\";\n    }\n\n    /**\n     * 判断当前节点是否下线\n     *\n     * @return\n     */\n    public boolean isOffline() {\n        if (status == InstanceStatusEnum.OFFLINE_STATUS.getStatus()) {\n            return true;\n        }\n        return false;\n    }\n\n    public void setRoleDesc(Boolean isMaster) {\n        if (isMaster == null) {\n            roleDesc = \"未知\";\n        } else if (isMaster) {\n            roleDesc = \"master\";\n        } else {\n            roleDesc = \"slave\";\n        }\n    }\n\n    public String getRoleDesc() {\n        if (type == ConstUtils.CACHE_REDIS_SENTINEL) {\n            return \"sentinel\";\n        } else {\n            return roleDesc;\n        }\n    }\n    \n    public String getHostPort() {\n    \treturn ip + \":\" + port;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/InstanceReshardProcess.java",
    "content": "package com.sohu.cache.entity;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.sohu.cache.constant.ReshardStatusEnum;\n\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\n\n/**\n * 进度持久化\n * \n * @author leifu\n * @Date 2017年6月24日\n * @Time 下午6:34:07\n */\npublic class InstanceReshardProcess {\n    \n    private int id;\n\n    /**\n     * 应用id\n     */\n    private long appId;\n\n    /**\n     * 审批id\n     */\n    private long auditId;\n\n    /**\n     * 源实例id\n     */\n    private int sourceInstanceId;\n    \n    \n    /**\n     * 源实例\n     */\n    private InstanceInfo sourceInstanceInfo;\n    \n    /**\n     * 目标实例id\n     */\n    private int targetInstanceId;\n    \n    /**\n     * 目标实例\n     */\n    private InstanceInfo targetInstanceInfo;\n\n    /**\n     * 开始slot\n     */\n    private int startSlot;\n\n    /**\n     * 结束slot\n     */\n    private int endSlot;\n\n    /**\n     * 正在迁移的slot\n     */\n    private int migratingSlot;\n   \n    /**\n     * 0是,1否\n     */\n    private int isPipeline;\n    \n    /**\n     * 已完成迁移的slot数量\n     */\n    private int finishSlotNum;\n\n    /**\n     * 0:运行中 1:完成 2:出错\n     */\n    private int status;\n\n    /**\n     * 迁移开始时间\n     */\n    private Date startTime;\n\n    /**\n     * 迁移结束时间\n     */\n    private Date endTime;\n    \n    /**\n     * 创建时间\n     * @return\n     */\n    private Date createTime;\n    \n    /**\n     * 更新时间\n     */\n    private Date updateTime;\n    \n    private final static String dateTimeFormat = \"yyyy-MM-dd HH:mm:ss\";\n\n    public int getId() {\n        return id;\n    }\n\n    public void setId(int id) {\n        this.id = id;\n    }\n\n    public long getAppId() {\n        return appId;\n    }\n\n    public void setAppId(long appId) {\n        this.appId = appId;\n    }\n\n    public long getAuditId() {\n        return auditId;\n    }\n\n    public void setAuditId(long auditId) {\n        this.auditId = auditId;\n    }\n\n    public int getSourceInstanceId() {\n        return sourceInstanceId;\n    }\n\n    public void setSourceInstanceId(int sourceInstanceId) {\n        this.sourceInstanceId = sourceInstanceId;\n    }\n\n    public int getTargetInstanceId() {\n        return targetInstanceId;\n    }\n\n    public void setTargetInstanceId(int targetInstanceId) {\n        this.targetInstanceId = targetInstanceId;\n    }\n\n    public int getStartSlot() {\n        return startSlot;\n    }\n\n    public void setStartSlot(int startSlot) {\n        this.startSlot = startSlot;\n    }\n\n    public int getEndSlot() {\n        return endSlot;\n    }\n\n    public void setEndSlot(int endSlot) {\n        this.endSlot = endSlot;\n    }\n\n\n    public void setEndTime(Date endTime) {\n        this.endTime = endTime;\n    }\n\n    public int getMigratingSlot() {\n        return migratingSlot;\n    }\n\n    public void setMigratingSlot(int migratingSlot) {\n        this.migratingSlot = migratingSlot;\n    }\n\n    public int getFinishSlotNum() {\n        return finishSlotNum;\n    }\n\n    public void setFinishSlotNum(int finishSlotNum) {\n        this.finishSlotNum = finishSlotNum;\n    }\n\n    public void setStatus(int status) {\n        this.status = status;\n    }\n\n    public int getStatus() {\n        return status;\n    }\n\n    public Date getStartTime() {\n        return startTime;\n    }\n    \n    public int getIsPipeline() {\n        return isPipeline;\n    }\n\n    public void setIsPipeline(int isPipeline) {\n        this.isPipeline = isPipeline;\n    }\n\n    public InstanceInfo getSourceInstanceInfo() {\n        return sourceInstanceInfo;\n    }\n\n    public void setSourceInstanceInfo(InstanceInfo sourceInstanceInfo) {\n        this.sourceInstanceInfo = sourceInstanceInfo;\n    }\n\n    public InstanceInfo getTargetInstanceInfo() {\n        return targetInstanceInfo;\n    }\n\n    public void setTargetInstanceInfo(InstanceInfo targetInstanceInfo) {\n        this.targetInstanceInfo = targetInstanceInfo;\n    }\n\n    public String getStartTimeFormat() {\n        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateTimeFormat);\n        return simpleDateFormat.format(startTime);\n    }\n\n    public void setStartTime(Date startTime) {\n        this.startTime = startTime;\n    }\n\n    public Date getEndTime() {\n        return endTime;\n    }\n    \n    public String getEndTimeFormat() {\n        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateTimeFormat);\n        return simpleDateFormat.format(endTime);\n    }\n\n    public Date getCreateTime() {\n        return createTime;\n    }\n    \n    public String getCreateTimeFormat() {\n        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateTimeFormat);\n        return simpleDateFormat.format(createTime);\n    }\n\n    public void setCreateTime(Date createTime) {\n        this.createTime = createTime;\n    }\n\n    public Date getUpdateTime() {\n        return updateTime;\n    }\n    \n    public String getUpdateTimeFormat() {\n        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateTimeFormat);\n        return simpleDateFormat.format(updateTime);\n    }\n\n    public void setUpdateTime(Date updateTime) {\n        this.updateTime = updateTime;\n    }\n\n    public int getTotalSlot() {\n        return endSlot - startSlot + 1;\n    }\n    \n    public String getStatusDesc() {\n        ReshardStatusEnum reshardStatusEnum = ReshardStatusEnum.getReshardStatusEnum(status);\n        return reshardStatusEnum == null ? \"\" : reshardStatusEnum.getInfo();\n    }\n\n    @Override\n    public String toString() {\n        return JSONObject.toJSONString(this);\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/InstanceSlotModel.java",
    "content": "package com.sohu.cache.entity;\n\nimport java.util.List;\n\n/**\n * 实例slot\n * \n * @author leifu\n * @Date 2016年12月4日\n * @Time 下午2:30:29\n */\npublic class InstanceSlotModel {\n\t/**\n\t * slot分布，例如： 0-4096 或者0-8 9-4096\n\t */\n\tprivate List<String> slotDistributeList;\n\n\t/**\n\t * slot列表\n\t */\n\tprivate List<Integer> slotList;\n\t\n\t/**\n\t * ip\n\t */\n\tprivate String host;\n\t\n\t/**\n\t * 端口\n\t */\n\tprivate int port;\n\n\tpublic List<String> getSlotDistributeList() {\n\t\treturn slotDistributeList;\n\t}\n\n\tpublic void setSlotDistributeList(List<String> slotDistributeList) {\n\t\tthis.slotDistributeList = slotDistributeList;\n\t}\n\n\tpublic List<Integer> getSlotList() {\n\t\treturn slotList;\n\t}\n\n\tpublic void setSlotList(List<Integer> slotList) {\n\t\tthis.slotList = slotList;\n\t}\n\n\tpublic String getHost() {\n\t\treturn host;\n\t}\n\n\tpublic void setHost(String host) {\n\t\tthis.host = host;\n\t}\n\n\tpublic int getPort() {\n\t\treturn port;\n\t}\n\n\tpublic void setPort(int port) {\n\t\tthis.port = port;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"InstanceSlotModel [slotDistributeList=\" + slotDistributeList + \", slotList=\" + slotList + \", host=\"\n\t\t\t\t+ host + \", port=\" + port + \"]\";\n\t}\n\t\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/InstanceSlowLog.java",
    "content": "package com.sohu.cache.entity;\n\nimport java.sql.Timestamp;\n\nimport org.apache.commons.lang.StringUtils;\n\n/**\n * 实例慢查询日志\n * @author leifu\n * @Date 2016年2月22日\n * @Time 上午11:57:02\n */\npublic class InstanceSlowLog {\n    \n    private long id;\n\n    /**\n     * 实例id\n     */\n    private long instanceId;\n\n    /**\n     * app id\n     */\n    private long appId;\n\n    /**\n     * ip地址\n     */\n    private String ip;\n\n    /**\n     * port\n     */\n    private int port;\n\n    /**\n     * 慢查询日志id\n     */\n    private long slowLogId;\n\n    /**\n     * 耗时\n     */\n    private int costTime;\n    \n    /**\n     * 命令\n     */\n    private String command;\n\n    /**\n     * 记录创建时间\n     */\n    private Timestamp createTime;\n\n    /**\n     * 慢查询发生时间\n     */\n    private Timestamp executeTime;\n\n    public long getId() {\n        return id;\n    }\n\n    public void setId(long id) {\n        this.id = id;\n    }\n\n\n    public long getInstanceId() {\n        return instanceId;\n    }\n\n    public void setInstanceId(long instanceId) {\n        this.instanceId = instanceId;\n    }\n\n    public long getAppId() {\n        return appId;\n    }\n\n    public void setAppId(long appId) {\n        this.appId = appId;\n    }\n\n    public String getIp() {\n        return ip;\n    }\n\n    public void setIp(String ip) {\n        this.ip = ip;\n    }\n\n    public int getPort() {\n        return port;\n    }\n\n    public void setPort(int port) {\n        this.port = port;\n    }\n\n    public long getSlowLogId() {\n        return slowLogId;\n    }\n\n    public void setSlowLogId(long slowLogId) {\n        this.slowLogId = slowLogId;\n    }\n\n    public int getCostTime() {\n        return costTime;\n    }\n\n    public void setCostTime(int costTime) {\n        this.costTime = costTime;\n    }\n\n    public String getCommand() {\n        int maxLength = 30;\n        if (StringUtils.isNotBlank(command) && command.length() > maxLength) {\n            return command.substring(0, maxLength) + \"...\";\n        }\n        return command;\n    }\n\n    public void setCommand(String command) {\n        this.command = command;\n    }\n\n    public Timestamp getCreateTime() {\n        return createTime;\n    }\n\n    public void setCreateTime(Timestamp createTime) {\n        this.createTime = createTime;\n    }\n\n    public Timestamp getExecuteTime() {\n        return executeTime;\n    }\n\n    public void setExecuteTime(Timestamp executeTime) {\n        this.executeTime = executeTime;\n    }\n\n    @Override\n    public String toString() {\n        return \"InstanceSlowLog [id=\" + id + \", instanceId=\" + instanceId + \", appId=\" + appId + \", ip=\" + ip + \", port=\"\n                + port + \", slowLogId=\" + slowLogId + \", costTime=\" + costTime + \", command=\" + command\n                + \", createTime=\" + createTime + \", executeTime=\" + executeTime + \"]\";\n    }\n\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/InstanceStats.java",
    "content": "package com.sohu.cache.entity;\n\nimport java.sql.Timestamp;\nimport java.text.DecimalFormat;\nimport java.util.Map;\n\n/**\n * 实例的简化的统计信息\n *\n * User: lingguo\n * Date: 14-7-27 下午3:59\n */\npublic class InstanceStats {\n    /* id */\n    private long id;\n\n    /* 实例id */\n    private long instId;\n\n    /* app id */\n    private long appId;\n\n    /* host id */\n    private long hostId;\n\n    /* ip地址 */\n    private String ip;\n\n    /* port */\n    private int port;\n\n    /* 主从，1主2从 */\n    private byte role;\n\n    /* 启用实例时设置的内存，单位：byte */\n    private long maxMemory;\n\n    /* 实例当前已用的内存，单位：byte */\n    private long usedMemory;\n\n    /*\n     * 实例内存使用率\n     */\n    private double memUsePercent;\n\n    /* 当前的item数 */\n    private long currItems;\n\n    /* 当前的连接数 */\n    private int currConnections;\n\n    /* 未命中数*/\n    private long misses;\n\n    /* 命中数 */\n    private long hits;\n\n    /* 开始收集时间 */\n    private Timestamp createTime;\n\n    /* 最后更新时间 */\n    private Timestamp modifyTime;\n    \n    /**\n     * 内存碎片率\n     */\n    private double memFragmentationRatio;\n    \n    /**\n     * aof阻塞次数\n     */\n    private int aofDelayedFsync;\n\n    private boolean isRun;\n\n    /**\n     * 实例相关全部统计指标\n     */\n    private Map<String,Object> infoMap;\n\n    public String getIp() {\n        return ip;\n    }\n\n    public void setIp(String ip) {\n        this.ip = ip;\n    }\n\n    public int getPort() {\n        return port;\n    }\n\n    public void setPort(int port) {\n        this.port = port;\n    }\n\n    public long getMaxMemory() {\n        return maxMemory;\n    }\n\n    public void setMaxMemory(long maxMemory) {\n        this.maxMemory = maxMemory;\n    }\n\n    public long getUsedMemory() {\n        return usedMemory;\n    }\n\n    public void setUsedMemory(long usedMemory) {\n        this.usedMemory = usedMemory;\n    }\n\n    public long getCurrItems() {\n        return currItems;\n    }\n\n    public void setCurrItems(long currItems) {\n        this.currItems = currItems;\n    }\n\n    public int getCurrConnections() {\n        return currConnections;\n    }\n\n    public void setCurrConnections(int currConnections) {\n        this.currConnections = currConnections;\n    }\n\n\n    public long getMisses() {\n        return misses;\n    }\n\n    public void setMisses(long misses) {\n        this.misses = misses;\n    }\n\n    public long getHits() {\n        return hits;\n    }\n\n    public void setHits(long hits) {\n        this.hits = hits;\n    }\n\n    public long getAppId() {\n        return appId;\n    }\n\n    public void setAppId(long appId) {\n        this.appId = appId;\n    }\n\n    public long getHostId() {\n        return hostId;\n    }\n\n    public void setHostId(long hostId) {\n        this.hostId = hostId;\n    }\n\n    public long getId() {\n        return id;\n    }\n\n    public void setId(long id) {\n        this.id = id;\n    }\n\n    public Timestamp getCreateTime() {\n        return createTime;\n    }\n\n    public void setCreateTime(Timestamp createTime) {\n        this.createTime = createTime;\n    }\n\n    public Timestamp getModifyTime() {\n        return modifyTime;\n    }\n\n    public void setModifyTime(Timestamp modifyTime) {\n        this.modifyTime = modifyTime;\n    }\n\n    public byte getRole() {\n        return role;\n    }\n\n    public void setRole(byte role) {\n        this.role = role;\n    }\n\n    public long getInstId() {\n        return instId;\n    }\n\n    public void setInstId(long instId) {\n        this.instId = instId;\n    }\n\n    public double getMemFragmentationRatio() {\n        return memFragmentationRatio;\n    }\n\n    public void setMemFragmentationRatio(double memFragmentationRatio) {\n        this.memFragmentationRatio = memFragmentationRatio;\n    }\n\n    public int getAofDelayedFsync() {\n        return aofDelayedFsync;\n    }\n\n    public void setAofDelayedFsync(int aofDelayedFsync) {\n        this.aofDelayedFsync = aofDelayedFsync;\n    }\n\n    @Override\n    public String toString() {\n        return \"InstanceStats [id=\" + id + \", instId=\" + instId + \", appId=\" + appId + \", hostId=\" + hostId + \", ip=\"\n                + ip + \", port=\" + port + \", role=\" + role + \", maxMemory=\" + maxMemory + \", usedMemory=\" + usedMemory\n                + \", memUsePercent=\" + memUsePercent + \", currItems=\" + currItems + \", currConnections=\"\n                + currConnections + \", misses=\" + misses + \", hits=\" + hits + \", createTime=\" + createTime\n                + \", modifyTime=\" + modifyTime + \", memFragmentationRatio=\" + memFragmentationRatio\n                + \", aofDelayedFsync=\" + aofDelayedFsync + \", isRun=\" + isRun + \", infoMap=\" + infoMap + \"]\";\n    }\n\n    public Map<String, Object> getInfoMap() {\n        return infoMap;\n    }\n\n    public void setInfoMap(Map<String, Object> infoMap) {\n        this.infoMap = infoMap;\n    }\n\n    public boolean isRun() {\n        return isRun;\n    }\n\n    public void setRun(boolean isRun) {\n        this.isRun = isRun;\n    }\n\n    public double getMemUsePercent() {\n        if(maxMemory<=0){\n            return 0.0D;\n        }\n        double percent = 100 * (double) usedMemory / (maxMemory);\n        DecimalFormat df = new DecimalFormat(\"##.##\");\n        return Double.parseDouble(df.format(percent));\n    }\n    \n    /**\n     * 命中率\n     * @return\n     */\n    public String getHitPercent(){\n\t\tlong totalHits = hits + misses;\n\t\tif (totalHits <= 0) {\n\t\t\treturn \"无命令执行\";\n\t\t}\n\t\tdouble percent = 100 * (double) hits / totalHits;\n\t\tDecimalFormat df = new DecimalFormat(\"##.##\");\n\t\treturn df.format(percent) + \"%\";\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/LoginResult.java",
    "content": "package com.sohu.cache.entity;\n\nimport com.sohu.cache.web.enums.AdminEnum;\nimport com.sohu.cache.web.enums.LoginEnum;\n\n/**\n * 登录结果\n * \n * @author leifu\n * @Time 2014年10月16日\n */\npublic class LoginResult {\n    /**\n     * 登录验证结果\n     */\n    private LoginEnum loginEnum;\n\n    /**\n     * 是否是管理员\n     */\n    private AdminEnum adminEnum;\n\n    public LoginResult(LoginEnum loginEnum, AdminEnum adminEnum) {\n        this.loginEnum = loginEnum;\n        this.adminEnum = adminEnum;\n    }\n\n    public LoginResult() {\n    }\n\n    public LoginEnum getLoginEnum() {\n        return loginEnum;\n    }\n\n    public void setLoginEnum(LoginEnum loginEnum) {\n        this.loginEnum = loginEnum;\n    }\n\n    public AdminEnum getAdminEnum() {\n        return adminEnum;\n    }\n\n    public void setAdminEnum(AdminEnum adminEnum) {\n        this.adminEnum = adminEnum;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/MachineInfo.java",
    "content": "package com.sohu.cache.entity;\n\n\nimport java.util.Date;\n\nimport com.sohu.cache.constant.MachineInfoEnum;\n\n/**\n * 机器的属性信息\n *\n * Created by lingguo on 14-6-27.\n */\npublic class MachineInfo {\n    /**\n     * 机器id\n     */\n    private long id;\n    \n    /**\n     * ssh用户名\n     */\n    private String sshUser;\n    \n    /**\n     * ssh密码\n     */\n    private String sshPasswd;\n    \n    /**\n     * ip地址\n     */\n    private String ip;\n    \n    /**\n     * 机房\n     */\n    private String room;\n    \n    /**\n     * 内存，单位G\n     */\n    private int mem;\n    \n    /**\n     * cpu数量\n     */\n    private int cpu;\n    \n    /**\n     * 是否虚机，0否，1是\n     */\n    private int virtual;\n    \n    /**\n     * 宿主机ip\n     */\n    private String realIp; \n    \n    /**\n     * 上线时间\n     */\n    private Date serviceTime;\n    \n    /**\n     * 故障次数\n     */\n    private int faultCount;\n    \n    /**\n     * 修改时间\n     */\n    private Date modifyTime;\n    \n    /**\n     * 是否启用报警，0否，1是\n     */\n    private int warn;\n    \n    /**\n     * 是否可用，MachineInfoEnum.AvailableEnum\n     */\n    private int available;\n    \n    /**\n     * 机器类型：详见MachineInfoEnum.TypeEnum\n     */\n    private int type;           \n    \n    /**\n     * groupId\n     */\n    private int groupId;\n    \n    /**\n     * 额外说明:(例如本机器有其他web或者其他服务)\n     */\n    private String extraDesc;\n    \n    /**\n     * 是否收集服务器信息，0否，1是\n     */\n    private int collect;\n\n    public long getId() {\n        return id;\n    }\n\n    public void setId(long id) {\n        this.id = id;\n    }\n    \n    public int getCollect() {\n\t\treturn collect;\n\t}\n\n\tpublic void setCollect(int collect) {\n\t\tthis.collect = collect;\n\t}\n\n\tpublic String getSshUser() {\n        return sshUser;\n    }\n\n    public void setSshUser(String sshUser) {\n        this.sshUser = sshUser;\n    }\n\n    public String getSshPasswd() {\n        return sshPasswd;\n    }\n\n    public void setSshPasswd(String sshPasswd) {\n        this.sshPasswd = sshPasswd;\n    }\n\n    public String getIp() {\n        return ip;\n    }\n\n    public void setIp(String ip) {\n        this.ip = ip;\n    }\n\n    public String getRoom() {\n        return room;\n    }\n\n    public void setRoom(String room) {\n        this.room = room;\n    }\n\n    public int getMem() {\n        return mem;\n    }\n\n    public void setMem(int mem) {\n        this.mem = mem;\n    }\n\n    public int getCpu() {\n        return cpu;\n    }\n\n    public void setCpu(int cpu) {\n        this.cpu = cpu;\n    }\n\n    public int getVirtual() {\n        return virtual;\n    }\n\n    public void setVirtual(int virtual) {\n        this.virtual = virtual;\n    }\n\n    public String getRealIp() {\n        return realIp;\n    }\n\n    public void setRealIp(String realIp) {\n        this.realIp = realIp;\n    }\n\n    public Date getServiceTime() {\n        return serviceTime;\n    }\n\n    public void setServiceTime(Date serviceTime) {\n        this.serviceTime = serviceTime;\n    }\n\n    public int getFaultCount() {\n        return faultCount;\n    }\n\n    public void setFaultCount(int faultCount) {\n        this.faultCount = faultCount;\n    }\n\n    public Date getModifyTime() {\n        return modifyTime;\n    }\n\n    public void setModifyTime(Date modifyTime) {\n        this.modifyTime = modifyTime;\n    }\n\n    public int getWarn() {\n        return warn;\n    }\n\n    public void setWarn(int warn) {\n        this.warn = warn;\n    }\n\n    public int getAvailable() {\n        return available;\n    }\n\n    public void setAvailable(int available) {\n        this.available = available;\n    }\n\n    public int getType() {\n        return type;\n    }\n\n    public void setType(int type) {\n        this.type = type;\n    }\n\n    public int getGroupId() {\n        return groupId;\n    }\n\n    public void setGroupId(int groupId) {\n        this.groupId = groupId;\n    }\n\n    public String getExtraDesc() {\n        return extraDesc;\n    }\n\n    public void setExtraDesc(String extraDesc) {\n        this.extraDesc = extraDesc;\n    }\n    \n    @Override\n    public String toString() {\n        return \"MachineInfo{\" +\n                \"id=\" + id +\n                \", sshUser='\" + sshUser + '\\'' +\n                \", sshPasswd='\" + sshPasswd + '\\'' +\n                \", ip='\" + ip + '\\'' +\n                \", room='\" + room + '\\'' +\n                \", mem=\" + mem +\n                \", cpu=\" + cpu +\n                \", virtual=\" + virtual +\n                \", realIp='\" + realIp + '\\'' +\n                \", serviceTime=\" + serviceTime +\n                \", faultCount=\" + faultCount +\n                \", modifyTime=\" + modifyTime +\n                \", warn=\" + warn +\n                \", available=\" + available +\n                \", type=\" + type +\n                \", groupId=\" + groupId +\n                \", extraDesc=\" + extraDesc +\n                \", collect=\" + collect +\n                '}';\n    }\n\n    /**\n     * 判断机器是否已经下线\n     * @return\n     */\n    public boolean isOffline() {\n        return MachineInfoEnum.AvailableEnum.NO.getValue() == this.available;\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/MachineMemInfo.java",
    "content": "package com.sohu.cache.entity;\n\n/**\n * Created by hym on 14-10-30.\n */\npublic class MachineMemInfo {\n    private String ip;\n    private long applyMem;\n    private long usedMem;\n\n    public String getIp() {\n        return ip;\n    }\n\n    public void setIp(String ip) {\n        this.ip = ip;\n    }\n\n    public long getApplyMem() {\n        return applyMem;\n    }\n\n    public void setApplyMem(long applyMem) {\n        this.applyMem = applyMem;\n    }\n\n    public long getUsedMem() {\n        return usedMem;\n    }\n\n    public void setUsedMem(long usedMem) {\n        this.usedMem = usedMem;\n    }\n\n    public long getLockedMem() {\n        return this.applyMem - this.usedMem;\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/MachineStats.java",
    "content": "package com.sohu.cache.entity;\n\nimport java.util.Date;\nimport java.util.Map;\n\n/**\n * Created by yijunzhang on 14-6-20.\n */\npublic class MachineStats {\n    private long id;\n\n    private long hostId;\n\n    private String ip;\n\n    private String cpuUsage;\n\n    private String load;\n\n    private String traffic;\n\n    private String memoryUsageRatio;\n\n    private String memoryFree;\n\n    private int memoryAllocated;\n\n    private String memoryTotal;\n\n    private MachineInfo info;\n\n    private MachineMemInfo machineMemInfo;\n\n    private Map<String/**挂载点*/, String/**使用百分比*/> diskUsageMap;\n\n    /**\n     * 创建时间\n     */\n    private Date createTime;\n\n    /**\n     * 修改时间\n     */\n    private Date modifyTime;\n\n    public String getIp() {\n        return ip;\n    }\n\n    public void setIp(String ip) {\n        this.ip = ip;\n    }\n\n    public String getMemoryUsageRatio() {\n        return memoryUsageRatio;\n    }\n\n    /**\n     * 这里将会返回 30%\n     */\n    public String getCpuUsage() {\n        return cpuUsage;\n    }\n\n    /**\n     * 按这样的格式赋值 30%\n     */\n    public void setCpuUsage(String cpuUsage) {\n        this.cpuUsage = cpuUsage;\n    }\n\n    public String getLoad() {\n        return load;\n    }\n\n    public void setLoad(String load) {\n        this.load = load;\n    }\n\n    public String getTraffic() {\n        return traffic;\n    }\n\n    public void setTraffic(String traffic) {\n        this.traffic = traffic;\n    }\n\n    public void setMemoryUsageRatio(String memoryUsageRatio) {\n        this.memoryUsageRatio = memoryUsageRatio;\n    }\n\n    public Map<String, String> getDiskUsageMap() {\n        return diskUsageMap;\n    }\n\n    public void setDiskUsageMap(Map<String, String> diskUsageMap) {\n        this.diskUsageMap = diskUsageMap;\n    }\n\n    public String getMemoryTotal() {\n        return memoryTotal;\n    }\n\n    public String getMemoryFree() {\n        return memoryFree;\n    }\n\n    public void setMemoryFree(String memoryFree) {\n        this.memoryFree = memoryFree;\n    }\n\n    public void setMemoryTotal(String memoryTotal) {\n        this.memoryTotal = memoryTotal;\n    }\n\n    public long getId() {\n        return id;\n    }\n\n    public void setId(long id) {\n        this.id = id;\n    }\n\n    public Date getCreateTime() {\n        return createTime;\n    }\n\n    public void setCreateTime(Date createTime) {\n        this.createTime = createTime;\n    }\n\n    public Date getModifyTime() {\n        return modifyTime;\n    }\n\n    public void setModifyTime(Date modifyTime) {\n        this.modifyTime = modifyTime;\n    }\n\n    public long getHostId() {\n        return hostId;\n    }\n\n    public void setHostId(long hostId) {\n        this.hostId = hostId;\n    }\n\n    public int getMemoryAllocated() {\n        return memoryAllocated;\n    }\n\n    public void setMemoryAllocated(int memoryAllocated) {\n        this.memoryAllocated = memoryAllocated;\n    }\n\n    public MachineInfo getInfo() {\n        return info;\n    }\n\n    public void setInfo(MachineInfo info) {\n        this.info = info;\n    }\n\n    public MachineMemInfo getMachineMemInfo() {\n        return machineMemInfo;\n    }\n\n    public void setMachineMemInfo(MachineMemInfo machineMemInfo) {\n        this.machineMemInfo = machineMemInfo;\n    }\n\n    @Override\n    public String toString() {\n        return \"MachineStats{\" +\n                \"id=\" + id +\n                \", hostId=\" + hostId +\n                \", ip='\" + ip + '\\'' +\n                \", cpuUsage='\" + cpuUsage + '\\'' +\n                \", load='\" + load + '\\'' +\n                \", traffic='\" + traffic + '\\'' +\n                \", memoryUsageRatio='\" + memoryUsageRatio + '\\'' +\n                \", memoryFree='\" + memoryFree + '\\'' +\n                \", memoryTotal='\" + memoryTotal + '\\'' +\n                \", diskUsageMap=\" + diskUsageMap +\n                \", createTime=\" + createTime +\n                \", modifyTime=\" + modifyTime +\n                '}';\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/ServerInfo.java",
    "content": "package com.sohu.cache.entity;\n/**\n * 服务器信息\n */\npublic class ServerInfo {\n\tprivate String ip;\n\tprivate String host;\n\t//逻辑cpu个数\n\tprivate int cpus;\n\t//nmon版本\n\tprivate String nmon;\n\t//cpu型号\n\tprivate String cpuModel;\n\t//内核版本\n\tprivate String kernel;\n\t//发行版本\n\tprivate String dist;\n\t//ulimit\n\tprivate String ulimit;\n\t\n\tpublic String getUlimit() {\n\t\treturn ulimit;\n\t}\n\tpublic void setUlimit(String ulimit) {\n\t\tthis.ulimit = ulimit;\n\t}\n\tpublic String getIp() {\n\t\treturn ip;\n\t}\n\tpublic void setIp(String ip) {\n\t\tthis.ip = ip;\n\t}\n\tpublic String getHost() {\n\t\treturn host;\n\t}\n\tpublic void setHost(String host) {\n\t\tthis.host = host;\n\t}\n\tpublic int getCpus() {\n\t\treturn cpus;\n\t}\n\tpublic void setCpus(int cpus) {\n\t\tthis.cpus = cpus;\n\t}\n\tpublic String getNmon() {\n\t\treturn nmon;\n\t}\n\tpublic void setNmon(String nmon) {\n\t\tthis.nmon = nmon;\n\t}\n\tpublic String getCpuModel() {\n\t\treturn cpuModel;\n\t}\n\tpublic void setCpuModel(String cpuModel) {\n\t\tthis.cpuModel = cpuModel;\n\t}\n\tpublic String getKernel() {\n\t\treturn kernel;\n\t}\n\tpublic void setKernel(String kernel) {\n\t\tthis.kernel = kernel;\n\t}\n\tpublic String getDist() {\n\t\treturn dist;\n\t}\n\tpublic void setDist(String dist) {\n\t\tthis.dist = dist;\n\t}\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/ServerStatus.java",
    "content": "package com.sohu.cache.entity;\n/**\n * 服务器状态\n */\npublic class ServerStatus {\n\tprivate String cdate;\n\tprivate String ctime;\n\tprivate float cuser;\n\tprivate float csys;\n\tprivate float cwio;\n\tprivate String cExt;\n\tprivate float cload1;\n\tprivate float cload5;\n\tprivate float cload15;\n\tprivate float mtotal;\n\tprivate float mfree;\n\tprivate float mcache;\n\tprivate float mbuffer;\n\tprivate float mswap;\n\tprivate float mswapFree;\n\tprivate float nin;\n\tprivate float nout;\n\tprivate int tuse;\n\tprivate int torphan;\n\tprivate int twait;\n\tprivate String ninExt;\n\tprivate String noutExt;\n\tprivate float dread;\n\tprivate float dwrite;\n\tprivate float diops;\n\tprivate float dbusy;\n\tprivate String dExt;\n\tprivate String dspace;\n\tpublic String getCdate() {\n\t\treturn cdate;\n\t}\n\tpublic void setCdate(String cdate) {\n\t\tthis.cdate = cdate;\n\t}\n\tpublic String getCtime() {\n\t\treturn ctime;\n\t}\n\tpublic void setCtime(String ctime) {\n\t\tthis.ctime = ctime;\n\t}\n\tpublic float getCuser() {\n\t\treturn cuser;\n\t}\n\tpublic void setCuser(float cuser) {\n\t\tthis.cuser = cuser;\n\t}\n\tpublic float getCsys() {\n\t\treturn csys;\n\t}\n\tpublic void setCsys(float csys) {\n\t\tthis.csys = csys;\n\t}\n\tpublic float getCwio() {\n\t\treturn cwio;\n\t}\n\tpublic void setCwio(float cwio) {\n\t\tthis.cwio = cwio;\n\t}\n\tpublic String getcExt() {\n\t\treturn cExt;\n\t}\n\tpublic void setcExt(String cExt) {\n\t\tthis.cExt = cExt;\n\t}\n\tpublic float getCload1() {\n\t\treturn cload1;\n\t}\n\tpublic void setCload1(float cload1) {\n\t\tthis.cload1 = cload1;\n\t}\n\tpublic float getCload5() {\n\t\treturn cload5;\n\t}\n\tpublic void setCload5(float cload5) {\n\t\tthis.cload5 = cload5;\n\t}\n\tpublic float getCload15() {\n\t\treturn cload15;\n\t}\n\tpublic int getTuse() {\n\t\treturn tuse;\n\t}\n\tpublic void setTuse(int tuse) {\n\t\tthis.tuse = tuse;\n\t}\n\tpublic int getTorphan() {\n\t\treturn torphan;\n\t}\n\tpublic void setTorphan(int torphan) {\n\t\tthis.torphan = torphan;\n\t}\n\tpublic int getTwait() {\n\t\treturn twait;\n\t}\n\tpublic void setTwait(int twait) {\n\t\tthis.twait = twait;\n\t}\n\tpublic void setCload15(float cload15) {\n\t\tthis.cload15 = cload15;\n\t}\n\tpublic float getMtotal() {\n\t\treturn mtotal;\n\t}\n\tpublic void setMtotal(float mtotal) {\n\t\tthis.mtotal = mtotal;\n\t}\n\tpublic float getMfree() {\n\t\treturn mfree;\n\t}\n\tpublic void setMfree(float mfree) {\n\t\tthis.mfree = mfree;\n\t}\n\tpublic float getMcache() {\n\t\treturn mcache;\n\t}\n\tpublic void setMcache(float mcache) {\n\t\tthis.mcache = mcache;\n\t}\n\tpublic float getMbuffer() {\n\t\treturn mbuffer;\n\t}\n\tpublic void setMbuffer(float mbuffer) {\n\t\tthis.mbuffer = mbuffer;\n\t}\n\tpublic float getMswap() {\n\t\treturn mswap;\n\t}\n\tpublic void setMswap(float mswap) {\n\t\tthis.mswap = mswap;\n\t}\n\tpublic float getNin() {\n\t\treturn nin;\n\t}\n\tpublic void setNin(float nin) {\n\t\tthis.nin = nin;\n\t}\n\tpublic float getNout() {\n\t\treturn nout;\n\t}\n\tpublic void setNout(float nout) {\n\t\tthis.nout = nout;\n\t}\n\tpublic float getDread() {\n\t\treturn dread;\n\t}\n\tpublic void setDread(float dread) {\n\t\tthis.dread = dread;\n\t}\n\tpublic float getDwrite() {\n\t\treturn dwrite;\n\t}\n\tpublic void setDwrite(float dwrite) {\n\t\tthis.dwrite = dwrite;\n\t}\n\tpublic float getDiops() {\n\t\treturn diops;\n\t}\n\tpublic void setDiops(float diops) {\n\t\tthis.diops = diops;\n\t}\n\tpublic float getDbusy() {\n\t\treturn dbusy;\n\t}\n\tpublic void setDbusy(float dbusy) {\n\t\tthis.dbusy = dbusy;\n\t}\n\tpublic String getDspace() {\n\t\treturn dspace;\n\t}\n\tpublic void setDspace(String dspace) {\n\t\tthis.dspace = dspace;\n\t}\n\tpublic float getMswapFree() {\n\t\treturn mswapFree;\n\t}\n\tpublic void setMswapFree(float mswapFree) {\n\t\tthis.mswapFree = mswapFree;\n\t}\n\tpublic String getNinExt() {\n\t\treturn ninExt;\n\t}\n\tpublic void setNinExt(String ninExt) {\n\t\tthis.ninExt = ninExt;\n\t}\n\tpublic String getNoutExt() {\n\t\treturn noutExt;\n\t}\n\tpublic void setNoutExt(String noutExt) {\n\t\tthis.noutExt = noutExt;\n\t}\n\tpublic String getdExt() {\n\t\treturn dExt;\n\t}\n\tpublic void setdExt(String dExt) {\n\t\tthis.dExt = dExt;\n\t}\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/StandardStats.java",
    "content": "package com.sohu.cache.entity;\n\nimport net.sf.json.JSONObject;\nimport org.apache.commons.lang.StringUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.Date;\nimport java.util.Iterator;\nimport java.util.LinkedHashMap;\nimport java.util.Map;\n\n/**\n * 实例基准统计\n * Created by zhangyijun on 15/6/17.\n */\npublic class StandardStats {\n    private final Logger logger = LoggerFactory.getLogger(this.getClass());\n\n    /**\n     * id\n     */\n    private long id;\n\n    /**\n     * 实例IP\n     */\n    private String ip;\n\n    /**\n     * 实例端口号/hostId\n     */\n    private int port;\n\n    /**\n     * 实例类型\n     */\n    private String dbType;\n\n    /**\n     * 收集时间:格式yyyyMMddHHmm\n     */\n    private long collectTime;\n\n    /**\n     * 实例收集的json数据\n     */\n    private String infoJson;\n\n    /**\n     * 与上一次收集差异的json数据\n     */\n    private String diffJson;\n    \n    /**\n     * 实例收集的cluster info json数据\n     */\n    private String clusterInfoJson;\n\n    /**\n     * infoJson的Map输出\n     */\n    private Map<String, Object> infoMap;\n\n    /**\n     * diffJson的Map输出\n     */\n    private Map<String, Object> diffMap;\n    \n    /**\n     * clusterInfoJson的Map输出\n     */\n    private Map<String, Object> clusterInfoMap;\n\n\n    private Date createdTime;\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 getIp() {\n        return ip;\n    }\n\n    public void setIp(String ip) {\n        this.ip = ip;\n    }\n\n    public int getPort() {\n        return port;\n    }\n\n    public void setPort(int port) {\n        this.port = port;\n    }\n\n    public String getDbType() {\n        return dbType;\n    }\n\n    public void setDbType(String dbType) {\n        this.dbType = dbType;\n    }\n\n    public long getCollectTime() {\n        return collectTime;\n    }\n\n    public void setCollectTime(long collectTime) {\n        this.collectTime = collectTime;\n    }\n\n    public String getInfoJson() {\n        return infoJson;\n    }\n\n    public void setInfoJson(String infoJson) {\n        this.infoJson = infoJson;\n    }\n\n    public String getDiffJson() {\n        return diffJson;\n    }\n\n    public void setDiffJson(String diffJson) {\n        this.diffJson = diffJson;\n    }\n\n    public StandardStats(String diffJson) {\n        this.diffJson = diffJson;\n    }\n\n    public StandardStats() {\n    }\n\n    public Map<String, Object> getInfoMap() {\n        if (infoMap != null) {\n            return infoMap;\n        } else {\n            if (StringUtils.isNotBlank(infoJson)) {\n                JSONObject jsonObject;\n                try {\n                    jsonObject = JSONObject.fromObject(infoJson);\n                    Map<String, Object> map = transferMapByJson(jsonObject);\n                    infoMap = map;\n                } catch (Exception e) {\n                    logger.error(e.getMessage());\n                }\n            }\n        }\n        return infoMap;\n    }\n\n    public void setInfoMap(Map<String, Object> infoMap) {\n        if (infoJson == null) {\n            JSONObject jsonObject;\n            try {\n                jsonObject = JSONObject.fromObject(infoMap);\n                infoJson = jsonObject.toString();\n            } catch (Exception e) {\n                logger.error(e.getMessage());\n            }\n        }\n        this.infoMap = infoMap;\n    }\n\n    public Map<String, Object> getDiffMap() {\n        if (diffMap != null) {\n            return diffMap;\n        } else {\n            if (StringUtils.isNotBlank(diffJson)) {\n                JSONObject jsonObject;\n                try {\n                    jsonObject = JSONObject.fromObject(diffJson);\n                    Map<String, Object> map = transferMapByJson(jsonObject);\n                    diffMap = map;\n                } catch (Exception e) {\n                    logger.error(e.getMessage());\n                }\n            }\n        }\n        return diffMap;\n    }\n\n    /**\n     * 递归转换JsonObject\n     * @param jsonObject\n     * @return\n     */\n    private Map<String, Object> transferMapByJson(JSONObject jsonObject) {\n        Map<String, Object> map = new LinkedHashMap<String, Object>();\n        for (Iterator keys = jsonObject.keys(); keys.hasNext(); ) {\n            String key = String.valueOf(keys.next());\n            Object value = jsonObject.get(key);\n            if(value instanceof JSONObject){\n                JSONObject subJsonObject = (JSONObject) value;\n                Map<String, Object> subMap = transferMapByJson(subJsonObject);\n                map.put(key,subMap);\n            }else{\n                map.put(key, value);\n            }\n        }\n        return map;\n    }\n\n    public void setDiffMap(Map<String, Object> diffMap) {\n        if (diffJson == null) {\n            JSONObject jsonObject;\n            try {\n                jsonObject = JSONObject.fromObject(diffMap);\n                diffJson = jsonObject.toString();\n            } catch (Exception e) {\n                logger.error(e.getMessage());\n            }\n        }\n        this.diffMap = diffMap;\n    }\n\n    public String getClusterInfoJson() {\n        return clusterInfoJson;\n    }\n\n    public void setClusterInfoJson(String clusterInfoJson) {\n        this.clusterInfoJson = clusterInfoJson;\n    }\n\n    public Map<String, Object> getClusterInfoMap() {\n        if (clusterInfoMap != null) {\n            return clusterInfoMap;\n        } else {\n            if (StringUtils.isNotBlank(clusterInfoJson)) {\n                JSONObject jsonObject;\n                try {\n                    jsonObject = JSONObject.fromObject(clusterInfoJson);\n                    Map<String, Object> map = transferMapByJson(jsonObject);\n                    clusterInfoMap = map;\n                } catch (Exception e) {\n                    logger.error(e.getMessage());\n                }\n            }\n        }\n        return clusterInfoMap;\n    }\n\n    public void setClusterInfoMap(Map<String, Object> clusterInfoMap) {\n        if (clusterInfoJson == null) {\n            JSONObject jsonObject;\n            try {\n                jsonObject = JSONObject.fromObject(clusterInfoMap);\n                clusterInfoJson = jsonObject.toString();\n            } catch (Exception e) {\n                logger.error(e.getMessage());\n            }\n        }\n        this.clusterInfoMap = clusterInfoMap;\n    }\n\n    public Date getCreatedTime() {\n        return createdTime;\n    }\n\n    public void setCreatedTime(Date createdTime) {\n        this.createdTime = createdTime;\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/SystemConfig.java",
    "content": "package com.sohu.cache.entity;\n\n/**\n * 系统配置\n * \n * @author leifu\n * @Date 2016年5月23日\n * @Time 上午11:18:11\n */\npublic class SystemConfig {\n\n    private String configKey;\n\n    private String configValue;\n\n    private String info;\n\n    private int status;\n    \n    private int orderId;\n\n\n    public SystemConfig() {\n        super();\n    }\n\n    public String getConfigKey() {\n        return configKey;\n    }\n\n    public void setConfigKey(String configKey) {\n        this.configKey = configKey;\n    }\n\n    public String getConfigValue() {\n        return configValue;\n    }\n\n    public void setConfigValue(String configValue) {\n        this.configValue = configValue;\n    }\n\n    public String getInfo() {\n        return info;\n    }\n\n    public void setInfo(String info) {\n        this.info = info;\n    }\n\n    public int getStatus() {\n        return status;\n    }\n\n    public void setStatus(int status) {\n        this.status = status;\n    }\n\n    public int getOrderId() {\n        return orderId;\n    }\n\n    public void setOrderId(int orderId) {\n        this.orderId = orderId;\n    }\n\n    @Override\n    public String toString() {\n        return \"SystemConfig [configKey=\" + configKey + \", configValue=\" + configValue + \", info=\" + info + \", status=\"\n                + status + \", orderId=\" + orderId + \"]\";\n    }\n\n\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/TimeBetween.java",
    "content": "package com.sohu.cache.entity;\n\nimport java.util.Date;\n\n/**\n * @author leifu\n * @Date 2017年5月6日\n * @Time 上午11:19:50\n */\npublic class TimeBetween {\n\n    private long startTime;\n    \n    private long endTime;\n    \n    private Date startDate;\n    \n    private Date endDate;\n\n    public TimeBetween() {\n    }\n\n    public TimeBetween(long startTime, long endTime, Date startDate, Date endDate) {\n        this.startTime = startTime;\n        this.endTime = endTime;\n        this.startDate = startDate;\n        this.endDate = endDate;\n    }\n\n    public long getStartTime() {\n        return startTime;\n    }\n\n    public void setStartTime(long startTime) {\n        this.startTime = startTime;\n    }\n\n    public long getEndTime() {\n        return endTime;\n    }\n\n    public void setEndTime(long endTime) {\n        this.endTime = endTime;\n    }\n    \n    public Date getStartDate() {\n        return startDate;\n    }\n\n    public void setStartDate(Date startDate) {\n        this.startDate = startDate;\n    }\n\n    public Date getEndDate() {\n        return endDate;\n    }\n\n    public void setEndDate(Date endDate) {\n        this.endDate = endDate;\n    }\n\n    @Override\n    public String toString() {\n        return \"TimeBetween [startTime=\" + startTime + \", endTime=\" + endTime + \", startDate=\" + startDate\n                + \", endDate=\" + endDate + \"]\";\n    }\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/TimeDimensionality.java",
    "content": "package com.sohu.cache.entity;\n\nimport com.sohu.cache.dao.AppStatsDao;\nimport com.sohu.cache.web.util.DateUtil;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.util.NumberUtils;\n\nimport java.util.Date;\n\n/**\n * Created by yijunzhang on 14-9-2.\n */\npublic class TimeDimensionality {\n    private final Logger logger = LoggerFactory.getLogger(this.getClass());\n\n    private final long begin;\n\n    private final long end;\n\n    private final int dimensionality;\n\n    public TimeDimensionality(long begin, long end, String format) {\n        Date beginDate = DateUtil.getDateByFormat(String.valueOf(begin), format);\n        Date endDate = DateUtil.getDateByFormat(String.valueOf(end), format);\n        this.dimensionality = getSuitableDimensionality(beginDate, endDate);\n        if (dimensionality == AppStatsDao.MINUTE_DIMENSIONALITY) {\n            this.begin = Long.parseLong(DateUtil.formatDate(beginDate, \"yyyyMMddHHmm\"));\n        } else {\n            this.begin = Long.parseLong(DateUtil.formatDate(beginDate, \"yyyyMMddHH\"));\n        }\n\n        if (dimensionality == AppStatsDao.MINUTE_DIMENSIONALITY) {\n            this.end = Long.parseLong(DateUtil.formatDate(endDate, \"yyyyMMddHHmm\"));\n        } else {\n            this.end = Long.parseLong(DateUtil.formatDate(endDate, \"yyyyMMddHH\"));\n        }\n    }\n\n\n    public long getBegin() {\n        return begin;\n    }\n\n    public long getEnd() {\n        return end;\n    }\n\n    public int getDimensionality() {\n        return dimensionality;\n    }\n\n    /**\n     * 获取合适的维度\n     */\n    private int getSuitableDimensionality(Date begin, Date end) {\n        try {\n            long s1 = begin.getTime();\n            long s2 = end.getTime();\n            long hour = (s2 - s1) / 1000 / 60 / 60;\n            if (hour >= 48) {\n                return AppStatsDao.HOUR_DIMENSIONALITY;\n            } else {\n                return AppStatsDao.MINUTE_DIMENSIONALITY;\n            }\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n        return AppStatsDao.MINUTE_DIMENSIONALITY;\n    }\n\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"TimeDimensionality [begin=\" + begin + \", end=\" + end\n\t\t\t\t+ \", dimensionality=\" + dimensionality + \"]\";\n\t}\n    \n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/entity/TriggerInfo.java",
    "content": "package com.sohu.cache.entity;\n\nimport com.sohu.cache.web.util.DateUtil;\n\nimport java.util.Date;\n\n/**\n * trigger的信息及状态\n */\npublic class TriggerInfo {\n    private String schedName;\n    private String triggerName;\n    private String triggerGroup;\n    private String jobName;\n    private String jobGroup;\n    private String description;\n    private long nextFireTime;\n    private String nextFireDate;\n    private long prevFireTime;\n    private String prevFireDate;\n    private int priority;\n    private String triggerState;\n    private String triggerType;\n    private long startTime;\n    private String startDate;\n    private long endTime;\n    private String endDate;\n    private String calendarName;\n    private short misfireInstr;\n    private String cron;\n\n    public String getSchedName() {\n        return schedName;\n    }\n\n    public void setSchedName(String schedName) {\n        this.schedName = schedName;\n    }\n\n    public String getTriggerName() {\n        return triggerName;\n    }\n\n    public void setTriggerName(String triggerName) {\n        this.triggerName = triggerName;\n    }\n\n    public String getTriggerGroup() {\n        return triggerGroup;\n    }\n\n    public void setTriggerGroup(String triggerGroup) {\n        this.triggerGroup = triggerGroup;\n    }\n\n    public String getJobName() {\n        return jobName;\n    }\n\n    public void setJobName(String jobName) {\n        this.jobName = jobName;\n    }\n\n    public String getJobGroup() {\n        return jobGroup;\n    }\n\n    public void setJobGroup(String jobGroup) {\n        this.jobGroup = jobGroup;\n    }\n\n    public String getDescription() {\n        return description;\n    }\n\n    public void setDescription(String description) {\n        this.description = description;\n    }\n\n    public long getNextFireTime() {\n        return nextFireTime;\n    }\n\n    public void setNextFireTime(long nextFireTime) {\n        this.nextFireTime = nextFireTime;\n    }\n\n    public long getPrevFireTime() {\n        return prevFireTime;\n    }\n\n    public void setPrevFireTime(long prevFireTime) {\n        this.prevFireTime = prevFireTime;\n    }\n\n    public int getPriority() {\n        return priority;\n    }\n\n    public void setPriority(int priority) {\n        this.priority = priority;\n    }\n\n    public String getTriggerState() {\n        return triggerState;\n    }\n\n    public void setTriggerState(String triggerState) {\n        this.triggerState = triggerState;\n    }\n\n    public String getTriggerType() {\n        return triggerType;\n    }\n\n    public void setTriggerType(String triggerType) {\n        this.triggerType = triggerType;\n    }\n\n    public long getStartTime() {\n        return startTime;\n    }\n\n    public void setStartTime(long startTime) {\n        this.startTime = startTime;\n    }\n\n    public long getEndTime() {\n        return endTime;\n    }\n\n    public void setEndTime(long endTime) {\n        this.endTime = endTime;\n    }\n\n    public String getCalendarName() {\n        return calendarName;\n    }\n\n    public void setCalendarName(String calendarName) {\n        this.calendarName = calendarName;\n    }\n\n    public short getMisfireInstr() {\n        return misfireInstr;\n    }\n\n    public void setMisfireInstr(short misfireInstr) {\n        this.misfireInstr = misfireInstr;\n    }\n\n    public String getCron() {\n        return cron;\n    }\n\n    public void setCron(String cron) {\n        this.cron = cron;\n    }\n\n    @Override\n    public String toString() {\n        return \"TriggerInfo{\" +\n                \"schedName='\" + schedName + '\\'' +\n                \", triggerName='\" + triggerName + '\\'' +\n                \", triggerGroup='\" + triggerGroup + '\\'' +\n                \", jobName='\" + jobName + '\\'' +\n                \", jobGroup='\" + jobGroup + '\\'' +\n                \", description='\" + description + '\\'' +\n                \", nextFireTime='\" + nextFireTime + '\\'' +\n                \", prevFireTime='\" + prevFireTime + '\\'' +\n                \", priority=\" + priority +\n                \", triggerState='\" + triggerState + '\\'' +\n                \", triggerType='\" + triggerType + '\\'' +\n                \", startTime=\" + startTime +\n                \", endTime=\" + endTime +\n                \", calendarName='\" + calendarName + '\\'' +\n                \", misfireInstr=\" + misfireInstr +\n                \", cron=\" + cron +\n                '}';\n    }\n\n    public String getNextFireDate() {\n        if (nextFireTime > 0) {\n            return DateUtil.formatYYYYMMddHHMMSS(new Date(nextFireTime));\n        }\n        return \"\";\n    }\n\n    public String getPrevFireDate() {\n        if (prevFireTime > 0) {\n            return DateUtil.formatYYYYMMddHHMMSS(new Date(prevFireTime));\n        }\n        return \"\";\n    }\n\n    public String getStartDate() {\n        if (startTime > 0) {\n            return DateUtil.formatYYYYMMddHHMMSS(new Date(startTime));\n        }\n        return \"\";\n    }\n\n    public String getEndDate() {\n        if (endTime > 0) {\n            return DateUtil.formatYYYYMMddHHMMSS(new Date(endTime));\n        }\n        return \"\";\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/exception/IllegalParamException.java",
    "content": "package com.sohu.cache.exception;\n\n/**\n * 参数异常\n * \n * @author leifu\n * @Date 2016-1-26\n * @Time 下午9:21:03\n */\npublic class IllegalParamException extends Exception {\n    \n    private static final long serialVersionUID = -1148039976867829902L;\n\n    public IllegalParamException() {\n        super();\n    }\n\n    public IllegalParamException(String message) {\n        super(message);\n    }\n\n    public IllegalParamException(String message, Throwable cause) {\n        super(message, cause);\n    }\n\n    public IllegalParamException(Throwable cause) {\n        super(cause);\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/exception/SSHException.java",
    "content": "package com.sohu.cache.exception;\n\n/**\n * ssh异常\n * @author leifu\n * @Date 2016-1-26\n * @Time 下午9:18:54\n */\npublic class SSHException extends Exception {\n\n    private static final long serialVersionUID = -6213665149000064880L;\n\n    public SSHException() {\n        super();\n    }\n\n    public SSHException(String message) {\n        super(message);\n    }\n\n    public SSHException(String message, Throwable cause) {\n        super(message, cause);\n    }\n\n    public SSHException(Throwable cause) {\n        super(cause);\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/init/AsyncLoad.java",
    "content": "package com.sohu.cache.init;\n\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\n\n/**\n * Created by yijunzhang on 14-9-25.\n */\npublic class AsyncLoad {\n\n    protected ExecutorService executorService = Executors.newCachedThreadPool();\n\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/init/MachineInitLoad.java",
    "content": "package com.sohu.cache.init;\n\nimport com.sohu.cache.dao.MachineDao;\nimport com.sohu.cache.entity.MachineInfo;\nimport com.sohu.cache.machine.MachineCenter;\nimport com.sohu.cache.util.ConstUtils;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.util.Assert;\n\nimport java.util.List;\n\n/**\n * 初始化，加载所有的host\n *\n * User: lingguo\n * Date: 14-6-12\n * Time: 下午12:40\n */\npublic class MachineInitLoad extends AsyncLoad{\n    private final Logger logger = LoggerFactory.getLogger(MachineInitLoad.class);\n\n    private MachineCenter machineCenter;\n    private MachineDao machineDao;\n\n    public void init() {\n        if (ConstUtils.IS_DEBUG) {\n            logger.warn(\"isDebug=true return\");\n            return;\n        }\n\n        executorService.submit(new Runnable() {\n            @Override\n            public void run() {\n                try {\n                    initAsync();\n                } catch (Exception e) {\n                    logger.error(e.getMessage(), e);\n                }\n            }\n        });\n    }\n    /**\n     * 为机器部署trigger，主要两类：统计机器的信息以及监控机器的状态\n     */\n    public void initAsync() {\n        List<MachineInfo> machineInfoList = machineDao.getAllMachines();\n        for (MachineInfo machineInfo : machineInfoList) {\n            long hostId = machineInfo.getId();\n            String ip = machineInfo.getIp();\n            Assert.hasText(ip);\n            Assert.isTrue(hostId > 0);\n            machineCenter.deployMachineCollection(hostId, ip);\n            machineCenter.deployMachineMonitor(hostId, ip);\n            if(machineInfo.getCollect() == 1) {\n            \tmachineCenter.deployServerCollection(hostId, ip);\n            }\n        }\n        logger.info(\"init deploy all host and monitor done.\");\n    }\n\n    public void setMachineCenter(MachineCenter machineCenter) {\n        this.machineCenter = machineCenter;\n    }\n\n    public void setMachineDao(MachineDao machineDao) {\n        this.machineDao = machineDao;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/init/RedisInitLoad.java",
    "content": "package com.sohu.cache.init;\n\nimport com.sohu.cache.dao.InstanceDao;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.redis.RedisCenter;\nimport com.sohu.cache.util.ConstUtils;\nimport com.sohu.cache.util.TypeUtil;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.List;\n\n/**\n * 初始化加载所有的redis实例\n *\n * User: lingguo\n * Date: 14-6-11\n * Time: 下午11:13\n */\npublic class RedisInitLoad extends AsyncLoad{\n    private final Logger logger = LoggerFactory.getLogger(RedisInitLoad.class);\n\n    private InstanceDao instanceDao;\n\n    private RedisCenter redisCenter;\n\n    public void init() {\n        if (ConstUtils.IS_DEBUG) {\n            logger.warn(\"isDebug=true return\");\n            return;\n        }\n        executorService.submit(new Runnable() {\n            @Override\n            public void run() {\n                try {\n                    initAsync();\n                } catch (Exception e) {\n                    logger.error(e.getMessage(), e);\n                }\n            }\n        });\n    }\n    /**\n     * spring启动时调用，加载所有的redis实例\n     */\n    public void initAsync() {\n        initByType(ConstUtils.CACHE_TYPE_REDIS_CLUSTER);\n        initByType(ConstUtils.CACHE_REDIS_STANDALONE);\n    }\n\n    private void initByType(int type) {\n        List<InstanceInfo> instanceInfoList = instanceDao.getInstListByType(type);\n        for (InstanceInfo instanceInfo : instanceInfoList) {\n            if (TypeUtil.isRedisSentinel(instanceInfo.getType())) {\n                continue;\n            }\n            String host = instanceInfo.getIp();\n            int port = instanceInfo.getPort();\n            Long appId = instanceInfo.getAppId();\n            redisCenter.deployRedisCollection(appId, host, port);\n            redisCenter.deployRedisSlowLogCollection(appId, host, port);\n        }\n        logger.info(\"init redis type={} deploy instance done.\", type);\n    }\n\n    public void setInstanceDao(InstanceDao instanceDao) {\n        this.instanceDao = instanceDao;\n    }\n\n    public void setRedisCenter(RedisCenter redisCenter) {\n        this.redisCenter = redisCenter;\n    }\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/inspect/InspectHandler.java",
    "content": "package com.sohu.cache.inspect;\n\nimport java.util.List;\n\n/**\n * Created by yijunzhang on 15-1-20.\n */\npublic interface InspectHandler {\n\n    public void handle();\n\n    public void setInspectorList(List<Inspector> inspectorList);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/inspect/InspectParamEnum.java",
    "content": "package com.sohu.cache.inspect;\n\n/**\n * Created by yijunzhang on 15-1-20.\n */\npublic enum InspectParamEnum {\n    /**\n     * 分组字段:\n     * HostInspectHandler 表示host\n     * AppInspectHandler 表示appId\n     */\n    SPLIT_KEY(\"split_key\"),\n    INSTANCE_LIST(\"instance_list\");\n\n    private String value;\n\n    InspectParamEnum(String value) {\n        this.value = value;\n    }\n\n    public String value(){\n        return value;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/inspect/Inspector.java",
    "content": "package com.sohu.cache.inspect;\n\nimport java.util.Map;\n\n/**\n * Created by yijunzhang on 15-1-20.\n */\npublic interface Inspector {\n\n    /**\n     * 执行检测逻辑\n     *\n     * @return\n     */\n    public boolean inspect(Map<InspectParamEnum, Object> paramMap);\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/inspect/InspectorJob.java",
    "content": "package com.sohu.cache.inspect;\n\nimport com.sohu.cache.schedule.jobs.CacheBaseJob;\nimport org.apache.commons.collections.MapUtils;\nimport org.apache.commons.lang.StringUtils;\nimport org.quartz.JobDataMap;\nimport org.quartz.JobExecutionContext;\nimport org.quartz.SchedulerContext;\nimport org.springframework.context.ApplicationContext;\n\n/**\n * Created by yijunzhang on 15-1-20.\n */\npublic class InspectorJob extends CacheBaseJob {\n    private static final long serialVersionUID = -4277329946053271489L;\n\n    @Override\n    public void action(JobExecutionContext context) {\n        try {\n            long start = System.currentTimeMillis();\n            SchedulerContext schedulerContext = context.getScheduler().getContext();\n            ApplicationContext applicationContext = (ApplicationContext) schedulerContext.get(APPLICATION_CONTEXT_KEY);\n            // 应用相关\n            InspectHandler inspectHandler;\n            JobDataMap jobDataMap = context.getMergedJobDataMap();\n            String inspectorType = MapUtils.getString(jobDataMap, \"inspectorType\");\n            if (StringUtils.isBlank(inspectorType)) {\n                logger.error(\"=====================InspectorJob:inspectorType is null=====================\");\n                return;\n            } else if (inspectorType.equals(\"host\")) {\n                inspectHandler = applicationContext.getBean(\"hostInspectHandler\", InspectHandler.class);\n            } else if (inspectorType.equals(\"app\")) {\n                inspectHandler = applicationContext.getBean(\"appInspectHandler\", InspectHandler.class);\n            } else {\n                logger.error(\"=====================InspectorJob:inspectorType not match:{}=====================\", inspectorType);\n                return;\n            }\n            inspectHandler.handle();\n            long end = System.currentTimeMillis();\n            logger.info(\"=====================InspectorJob {} Done! cost={} ms=====================\",\n                    inspectHandler.getClass().getSimpleName(), (end - start));\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            throw new RuntimeException(e);\n        }\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/inspect/impl/AbstractInspectHandler.java",
    "content": "package com.sohu.cache.inspect.impl;\n\nimport com.sohu.cache.async.AsyncService;\nimport com.sohu.cache.async.KeyCallable;\nimport com.sohu.cache.async.NamedThreadFactory;\nimport com.sohu.cache.dao.InstanceDao;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.inspect.InspectHandler;\nimport com.sohu.cache.inspect.InspectParamEnum;\nimport com.sohu.cache.inspect.Inspector;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.*;\nimport java.util.concurrent.LinkedBlockingQueue;\nimport java.util.concurrent.SynchronousQueue;\nimport java.util.concurrent.ThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * Created by yijunzhang on 15-1-20.\n */\npublic abstract class AbstractInspectHandler implements InspectHandler {\n    protected final Logger logger = LoggerFactory.getLogger(this.getClass());\n\n    protected InstanceDao instanceDao;\n\n    protected AsyncService asyncService;\n\n    protected List<Inspector> inspectorList;\n\n    protected abstract String getThreadPoolKey();\n\n    protected abstract Map<String, List<InstanceInfo>> getSplitMap();\n\n    public void init() {\n        asyncService.assemblePool(getThreadPoolKey(), new ThreadPoolExecutor(5, 100,\n                0L, TimeUnit.MILLISECONDS,\n                new LinkedBlockingQueue<Runnable>(1024),\n                new NamedThreadFactory(getThreadPoolKey(), true)));\n    }\n\n    public void handle() {\n        if (inspectorList == null || inspectorList.isEmpty()) {\n            logger.warn(\"inspectorList is null\");\n            return;\n        }\n        Map<String, List<InstanceInfo>> splitMap = getSplitMap();\n        for (Map.Entry<String, List<InstanceInfo>> entry : splitMap.entrySet()) {\n            String splitKey = entry.getKey();\n            List<InstanceInfo> instances = entry.getValue();\n            final Map<InspectParamEnum, Object> paramMap = new HashMap<InspectParamEnum, Object>();\n            paramMap.put(InspectParamEnum.SPLIT_KEY, splitKey);\n            paramMap.put(InspectParamEnum.INSTANCE_LIST, instances);\n            String key = getThreadPoolKey() + \"-\" + splitKey;\n            asyncService.submitFuture(getThreadPoolKey(), new KeyCallable<Boolean>(key) {\n                @Override\n                public Boolean execute() {\n                    for (Inspector inspector : inspectorList) {\n                        boolean isSuccess = false;\n                        try {\n                            isSuccess = inspector.inspect(paramMap);\n                        } catch (Throwable e) {\n                            logger.error(e.getMessage(), e);\n                        }\n                        if (!isSuccess) {\n                            logger.error(getThreadPoolKey() + \"-failed:\" + inspector.getClass().getName());\n                            return false;\n                        }\n                    }\n                    return true;\n                }\n            });\n        }\n    }\n\n    public void setInspectorList(List<Inspector> inspectorList) {\n        this.inspectorList = inspectorList;\n    }\n\n    public List<InstanceInfo> getAllInstanceList() {\n        return instanceDao.getAllInsts();\n    }\n\n    public void setInstanceDao(InstanceDao instanceDao) {\n        this.instanceDao = instanceDao;\n    }\n\n    public void setAsyncService(AsyncService asyncService) {\n        this.asyncService = asyncService;\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/inspect/impl/AppClientConnInspector.java",
    "content": "package com.sohu.cache.inspect.impl;\n\nimport com.sohu.cache.alert.impl.BaseAlertService;\nimport com.sohu.cache.entity.AppDesc;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.entity.InstanceStats;\nimport com.sohu.cache.inspect.InspectParamEnum;\nimport com.sohu.cache.inspect.Inspector;\nimport com.sohu.cache.stats.app.AppStatsCenter;\nimport com.sohu.cache.stats.instance.InstanceStatsCenter;\nimport com.sohu.cache.util.ConstUtils;\nimport com.sohu.cache.util.TypeUtil;\nimport com.sohu.cache.web.vo.AppDetailVO;\n\nimport org.apache.commons.collections.CollectionUtils;\nimport org.apache.commons.collections.MapUtils;\n\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 应用客户端连接监控\n * \n * @author leifu\n * @Date 2016年6月16日\n * @Time 上午9:44:34\n */\npublic class AppClientConnInspector extends BaseAlertService implements Inspector {\n\n    /**\n     * app统计相关\n     */\n    private AppStatsCenter appStatsCenter;\n\n    /**\n     * 实例统计相关\n     */\n    private InstanceStatsCenter instanceStatsCenter;\n\n    @Override\n    public boolean inspect(Map<InspectParamEnum, Object> paramMap) {\n        Long appId = MapUtils.getLong(paramMap, InspectParamEnum.SPLIT_KEY);\n        AppDetailVO appDetailVO = appStatsCenter.getAppDetail(appId);\n        if (appDetailVO == null) {\n            logger.warn(\"appId {} appDetailVO is empty\", appId);\n            return true;\n        }\n        List<InstanceInfo> appInstanceInfoList = (List<InstanceInfo>) paramMap.get(InspectParamEnum.INSTANCE_LIST);\n        if (CollectionUtils.isEmpty(appInstanceInfoList)) {\n            logger.warn(\"appId {} instanceList is empty\", appId);\n            return true;\n        }\n        // 报警阀值\n        int appClientConnThreshold = getClientConnThreshold(appDetailVO.getAppDesc());\n        int appClientConnNum = appDetailVO.getConn();\n        // 阀值乘以分片个数\n        int instanceCount = appInstanceInfoList.size();\n        if (appClientConnNum > appClientConnThreshold * instanceCount) {\n            alertAppClientConn(appDetailVO, appClientConnThreshold, instanceCount);\n        } else {\n            for (InstanceInfo instanceInfo : appInstanceInfoList) {\n                if (instanceInfo == null) {\n                    continue;\n                }\n                if (instanceInfo.isOffline()) {\n                    continue;\n                }\n                if (!TypeUtil.isRedisType(instanceInfo.getType())) {\n                    continue;\n                }\n                // 忽略sentinel观察者\n                if (TypeUtil.isRedisSentinel(instanceInfo.getType())) {\n                    continue;\n                }\n                long instanceId = instanceInfo.getId();\n                InstanceStats instanceStats = instanceStatsCenter.getInstanceStats(instanceId);\n                if (instanceStats == null) {\n                    continue;\n                }\n                double instanceClientConnNum = instanceStats.getCurrConnections();\n                // 大于标准值\n                if (instanceClientConnNum > appClientConnThreshold) {\n                    alertInstanceClientConn(instanceStats, appDetailVO, appClientConnThreshold);\n                }\n            }\n        }\n        return true;\n    }\n\n    /**\n     * 获取报警阀值(如果用户预设超过系统预设，以系统为准，反之以用户为准)\n     * @param appDesc\n     * @return\n     */\n    private int getClientConnThreshold(AppDesc appDesc) {\n        int userClientConnThreshold = appDesc.getClientConnAlertValue();\n        int systemClientConnThreshold =  ConstUtils.APP_CLIENT_CONN_THRESHOLD;\n        return userClientConnThreshold > systemClientConnThreshold ? systemClientConnThreshold : userClientConnThreshold;\n    }\n\n    /**\n     * 应用连接数报警\n     * @param appDetailVO\n     * @param appClientConnThreshold\n     * @param instanceCount\n     */\n    private void alertAppClientConn(final AppDetailVO appDetailVO, final int appClientConnThreshold, final int instanceCount) {\n        AppDesc appDesc = appDetailVO.getAppDesc();\n        String content = String.format(\"应用(%s)-客户端连接数报警-预设阀值每个分片为%s-现已达到%s(分片个数:%s)-请及时关注\",\n                appDesc.getAppId(), appClientConnThreshold, appDetailVO.getConn(), instanceCount);\n        String title = \"CacheCloud系统-客户端连接数报警\";\n        logger.warn(\"app title {}\", title);\n        logger.warn(\"app content {}\", content);\n        emailComponent.sendMail(title, content, appDetailVO.getEmailList(),\n                Arrays.asList(emailComponent.getAdminEmail().split(ConstUtils.COMMA)));\n    }\n\n    /**\n     * 单个分片连接数报警\n     * @param instanceStats\n     * @param appDetailVO\n     * @param appClientConnThreshold\n     */\n    private void alertInstanceClientConn(final InstanceStats instanceStats, final AppDetailVO appDetailVO,\n            final int appClientConnThreshold) {\n        String instanceHostPort = instanceStats.getIp() + \":\" + instanceStats.getPort();\n        String content = String.format(\"分片(%s,应用(%s))客户端连接数报警-预设%s-现已达到%s-请及时关注\", instanceHostPort,\n                instanceStats.getAppId(), appClientConnThreshold, instanceStats.getCurrConnections());\n        String title = \"CacheCloud系统-分片客户端连接数报警\";\n        logger.warn(\"instance title {}\", title);\n        logger.warn(\"instace content {}\", content);\n        emailComponent.sendMail(title, content, appDetailVO.getEmailList(),\n                Arrays.asList(emailComponent.getAdminEmail().split(ConstUtils.COMMA)));\n    }\n\n    public void setAppStatsCenter(AppStatsCenter appStatsCenter) {\n        this.appStatsCenter = appStatsCenter;\n    }\n\n    public void setInstanceStatsCenter(InstanceStatsCenter instanceStatsCenter) {\n        this.instanceStatsCenter = instanceStatsCenter;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/inspect/impl/AppInspectHandler.java",
    "content": "package com.sohu.cache.inspect.impl;\n\nimport com.sohu.cache.entity.InstanceInfo;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.TreeMap;\n\n/**\n * Created by yijunzhang on 15-1-20.\n */\npublic class AppInspectHandler extends AbstractInspectHandler{\n    private final String inspectPoolKey=\"inspector-app-pool\";\n\n    @Override\n    public String getThreadPoolKey() {\n        return inspectPoolKey;\n    }\n\n    @Override\n    protected Map<String, List<InstanceInfo>> getSplitMap() {\n        List<InstanceInfo> list = getAllInstanceList();\n        Map<String, List<InstanceInfo>> hostMap = new TreeMap<String, List<InstanceInfo>>();\n        for (InstanceInfo instanceInfo : list) {\n            String appId = String.valueOf(instanceInfo.getAppId());\n            if (hostMap.containsKey(appId)) {\n                hostMap.get(appId).add(instanceInfo);\n            } else {\n                List<InstanceInfo> hostInstances = new ArrayList<InstanceInfo>();\n                hostInstances.add(instanceInfo);\n                hostMap.put(appId, hostInstances);\n            }\n        }\n        return hostMap;\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/inspect/impl/AppMemInspector.java",
    "content": "package com.sohu.cache.inspect.impl;\n\nimport com.sohu.cache.alert.impl.BaseAlertService;\nimport com.sohu.cache.dao.AppDao;\nimport com.sohu.cache.entity.AppDesc;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.entity.InstanceStats;\nimport com.sohu.cache.inspect.InspectParamEnum;\nimport com.sohu.cache.inspect.Inspector;\nimport com.sohu.cache.stats.app.AppStatsCenter;\nimport com.sohu.cache.stats.instance.InstanceStatsCenter;\nimport com.sohu.cache.util.ConstUtils;\nimport com.sohu.cache.util.TypeUtil;\nimport com.sohu.cache.web.vo.AppDetailVO;\n\nimport org.apache.commons.collections.CollectionUtils;\nimport org.apache.commons.collections.MapUtils;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * Created by yijunzhang on 15-1-20.\n */\npublic class AppMemInspector extends BaseAlertService implements Inspector {\n\n    /**\n     * app统计相关\n     */\n    private AppStatsCenter appStatsCenter;\n\n    /**\n     * 应用相关dao\n     */\n    private AppDao appDao;\n\n    /**\n     * 实例统计相关\n     */\n    private InstanceStatsCenter instanceStatsCenter;\n\n    @Override\n    public boolean inspect(Map<InspectParamEnum, Object> paramMap) {\n        Long appId = MapUtils.getLong(paramMap, InspectParamEnum.SPLIT_KEY);\n        List<AppDesc> appDescList = new ArrayList<AppDesc>();\n        AppDesc app = appDao.getAppDescById(appId);\n        if (app != null) {\n            appDescList.add(app);\n        }\n        if (CollectionUtils.isEmpty(appDescList)) {\n            logger.error(\"appList is empty, appId={}\", appId);\n            return true;\n        }\n        for (AppDesc appDesc : appDescList) {\n            //测试不检查\n            if(appDesc.getIsTest() == 1){\n                continue;\n            }\n            long checkAppId = appDesc.getAppId();\n            AppDetailVO appDetailVO = appStatsCenter.getAppDetail(checkAppId);\n            if (appDetailVO == null) {\n                continue;\n            }\n            double appMemUsePercent = appDetailVO.getMemUsePercent();\n            int appUseSetMemAlertValue = appDesc.getMemAlertValue();\n            // 先检查应用的内存使用率是否超过阀值，如果没有再检查分片\n            if (appMemUsePercent > appUseSetMemAlertValue) {\n                // 报警\n                alertAppMemUse(appDetailVO);\n            } else {\n                List<InstanceInfo> appInstanceInfoList = (List<InstanceInfo>) paramMap.get(InspectParamEnum.INSTANCE_LIST);\n                if (CollectionUtils.isNotEmpty(appInstanceInfoList)) {\n                    for (InstanceInfo instanceInfo : appInstanceInfoList) {\n                        if (instanceInfo == null) {\n                            continue;\n                        }\n                        if (!TypeUtil.isRedisType(instanceInfo.getType())) {\n                            continue;\n                        }\n                        // 忽略sentinel观察者\n                        if (TypeUtil.isRedisSentinel(instanceInfo.getType())) {\n                            continue;\n                        }\n                        long instanceId = instanceInfo.getId();\n                        InstanceStats instanceStats = instanceStatsCenter.getInstanceStats(instanceId);\n                        if(instanceStats == null){\n                            continue;\n                        }\n                        double instanceMemUsePercent = instanceStats.getMemUsePercent();\n                        // 大于标准值\n                        if (instanceMemUsePercent > appUseSetMemAlertValue) {\n                            alertInstanceMemUse(instanceStats, appDetailVO);\n                        }\n                    }\n                }\n            }\n        }\n        return true;\n    }\n\n    /**\n     * @param appDetailVO\n     */\n    private void alertAppMemUse(final AppDetailVO appDetailVO) {\n        AppDesc appDesc = appDetailVO.getAppDesc();\n        String content = String.format(\"应用(%s)-内存使用率报警-预设百分之%s-现已达到百分之%s-请及时关注\",\n                appDesc.getAppId(), appDesc.getMemAlertValue(), appDetailVO.getMemUsePercent());\n        String title = \"CacheCloud系统-应用内存使用率报警\";\n        emailComponent.sendMail(title, content, appDetailVO.getEmailList(),\n                Arrays.asList(emailComponent.getAdminEmail().split(ConstUtils.COMMA)));\n        // TODO 临时注释掉\n        // mobileAlertComponent.sendPhone(content,\n        // appDetailVO.getPhoneList());\n\n    }\n\n    private void alertInstanceMemUse(final InstanceStats instanceStats, final AppDetailVO appDetailVO) {\n        String instanceInfo = instanceStats.getIp() + \":\" + instanceStats.getPort();\n        String content = String.format(\"分片(%s,应用(%s))内存使用率报警-预设百分之%s-现已达到百分之%s-应用的内存使用率百分之%s-请及时关注\",\n                instanceInfo,\n                instanceStats.getAppId(), appDetailVO.getAppDesc().getMemAlertValue(),\n                instanceStats.getMemUsePercent(), appDetailVO.getMemUsePercent());\n        String title = \"CacheCloud系统-分片内存使用率报警\";\n        emailComponent.sendMail(title, content, appDetailVO.getEmailList(),\n                Arrays.asList(emailComponent.getAdminEmail().split(ConstUtils.COMMA)));\n        // TODO 临时注释掉\n        // mobileAlertComponent.sendPhone(content,\n        // appDetailVO.getPhoneList());\n    }\n\n    public void setAppStatsCenter(AppStatsCenter appStatsCenter) {\n        this.appStatsCenter = appStatsCenter;\n    }\n\n    public void setAppDao(AppDao appDao) {\n        this.appDao = appDao;\n    }\n\n    public void setInstanceStatsCenter(InstanceStatsCenter instanceStatsCenter) {\n        this.instanceStatsCenter = instanceStatsCenter;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/inspect/impl/HostInspectHandler.java",
    "content": "package com.sohu.cache.inspect.impl;\n\nimport com.sohu.cache.entity.InstanceInfo;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.TreeMap;\n\n/**\n * Created by yijunzhang on 15-1-20.\n */\npublic class HostInspectHandler extends AbstractInspectHandler{\n    private final String inspectPoolKey=\"inspector-host-pool\";\n\n    @Override\n    public String getThreadPoolKey() {\n        return inspectPoolKey;\n    }\n\n    @Override\n    protected Map<String, List<InstanceInfo>> getSplitMap() {\n        List<InstanceInfo> list = getAllInstanceList();\n        Map<String, List<InstanceInfo>> hostMap = new TreeMap<String, List<InstanceInfo>>();\n        for (InstanceInfo instanceInfo : list) {\n            String host = instanceInfo.getIp();\n            if (hostMap.containsKey(host)) {\n                hostMap.get(host).add(instanceInfo);\n            } else {\n                List<InstanceInfo> hostInstances = new ArrayList<InstanceInfo>();\n                hostInstances.add(instanceInfo);\n                hostMap.put(host, hostInstances);\n            }\n        }\n        return hostMap;\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/inspect/impl/InstanceRunInspector.java",
    "content": "package com.sohu.cache.inspect.impl;\n\nimport com.sohu.cache.alert.impl.BaseAlertService;\nimport com.sohu.cache.constant.InstanceStatusEnum;\nimport com.sohu.cache.dao.AppDao;\nimport com.sohu.cache.dao.InstanceDao;\nimport com.sohu.cache.dao.InstanceFaultDao;\nimport com.sohu.cache.entity.AppDesc;\nimport com.sohu.cache.entity.InstanceFault;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.inspect.InspectParamEnum;\nimport com.sohu.cache.inspect.Inspector;\nimport com.sohu.cache.redis.RedisCenter;\nimport com.sohu.cache.util.TypeUtil;\nimport org.apache.commons.collections4.MapUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * Created by yijunzhang on 15-1-20.\n */\npublic class InstanceRunInspector extends BaseAlertService implements Inspector {\n    private final Logger logger = LoggerFactory.getLogger(this.getClass());\n\n    /**\n     * 实例相关\n     */\n    private InstanceDao instanceDao;\n\n    /**\n     * redis相关\n     */\n    private RedisCenter redisCenter;\n\n    /**\n     * 应用相关dao\n     */\n    private AppDao appDao;\n\n    private InstanceFaultDao instanceFaultDao;\n\n    @Override\n    public boolean inspect(Map<InspectParamEnum, Object> paramMap) {\n        String host = MapUtils.getString(paramMap, InspectParamEnum.SPLIT_KEY);\n        List<InstanceInfo> list = (List<InstanceInfo>) paramMap.get(InspectParamEnum.INSTANCE_LIST);\n        for (InstanceInfo info : list) {\n            final int port = info.getPort();\n            final int type = info.getType();\n            long appId = info.getAppId();\n            if (TypeUtil.isRedisType(type)) {\n            \t\tboolean isRun;\n            \t\tif (TypeUtil.isRedisSentinel(type)) {\n            \t\t\tisRun = redisCenter.isRun(host, port);\n            \t\t} else {\n            \t\t\tisRun = redisCenter.isRun(appId, host, port);\n            \t\t}\n                Boolean isUpdate = updateInstanceByRun(isRun, info);\n                if (isUpdate == null) {\n                    continue;\n                } else if (isUpdate) {\n                    redisCenter.deployRedisCollection(appId, host, port);\n                    redisCenter.deployRedisSlowLogCollection(appId, host, port);\n                } else {\n                    redisCenter.unDeployRedisCollection(appId, host, port);\n                    redisCenter.unDeployRedisSlowLogCollection(appId, host, port);\n                }\n                // 错误\n                if (isUpdate != null) {\n                    alertInstanceInfo(info);\n                }\n\n            }\n        }\n\n        return true;\n    }\n\n    /**\n     * 邮箱+短信\n     * @param info\n     */\n    private void alertInstanceInfo(InstanceInfo info){\n        sendEmailAlert(info);\n        sendPhoneAlert(info);\n    }\n\n    /**\n     * 发送短信报警\n     *\n     * @param info\n     */\n    private void sendPhoneAlert(InstanceInfo info) {\n        if (info == null) {\n            return;\n        }\n        String message = generateMessage(info, false);\n        mobileAlertComponent.sendPhoneToAdmin(message);\n    }\n\n\n    /**\n     * 发送邮箱报警\n     *\n     * @param info\n     */\n    private void sendEmailAlert(InstanceInfo info) {\n        if (info == null) {\n            return;\n        }\n        String title = \"实例(\" + info.getIp() + \":\" + info.getPort() + \")状态发生变化\";\n        String message = generateMessage(info, true);\n        emailComponent.sendMailToAdmin(title, message);\n    }\n\n    /**\n     * 返回示例消息\n     *\n     * @param info\n     * @return\n     */\n    private String generateMessage(InstanceInfo info, boolean isEmail) {\n        StringBuffer message = new StringBuffer();\n        long appId = info.getAppId();\n        AppDesc appDesc = appDao.getAppDescById(appId);\n        message.append(\"CacheCloud系统-实例(\" + info.getIp() + \":\" + info.getPort() + \")-\");\n        if (info.getStatus() == InstanceStatusEnum.ERROR_STATUS.getStatus()) {\n            message.append(\"由运行中变为心跳停止\");\n        } else if (info.getStatus() == InstanceStatusEnum.GOOD_STATUS.getStatus()) {\n            message.append(\"由心跳停止变为运行中\");\n        }\n        if(isEmail){\n            message.append(\", appId:\");\n            message.append(appId + \"-\" + appDesc.getName());\n        }else{\n            message.append(\"-appId(\" + appId +\"-\" + appDesc.getName() +\")\");\n        }\n\n        return message.toString();\n    }\n\n    private void saveFault(InstanceInfo info, boolean isRun) {\n        InstanceFault instanceFault = new InstanceFault();\n        instanceFault.setAppId((int) info.getAppId());\n        instanceFault.setInstId(info.getId());\n        instanceFault.setIp(info.getIp());\n        instanceFault.setPort(info.getPort());\n        instanceFault.setType(info.getType());\n        instanceFault.setCreateTime(new Date());\n        if (isRun) {\n            instanceFault.setReason(\"恢复运行\");\n        } else {\n            instanceFault.setReason(\"心跳停止\");\n        }\n        instanceFaultDao.insert(instanceFault);\n    }\n\n    private Boolean updateInstanceByRun(boolean isRun, InstanceInfo info) {\n        if (isRun) {\n            if (info.getStatus() != InstanceStatusEnum.GOOD_STATUS.getStatus()) {\n                info.setStatus(InstanceStatusEnum.GOOD_STATUS.getStatus());\n                instanceDao.update(info);\n                logger.warn(\"instance:{} instance is run\", info);\n                saveFault(info, isRun);\n                return true;\n            }\n        } else {\n            if (info.getStatus() != InstanceStatusEnum.ERROR_STATUS.getStatus()) {\n                info.setStatus(InstanceStatusEnum.ERROR_STATUS.getStatus());\n                instanceDao.update(info);\n                logger.error(\"instance:{} instance failed\", info);\n                saveFault(info, isRun);\n                return false;\n            }\n        }\n        return null;\n    }\n\n    public void setInstanceDao(InstanceDao instanceDao) {\n        this.instanceDao = instanceDao;\n    }\n\n    public void setRedisCenter(RedisCenter redisCenter) {\n        this.redisCenter = redisCenter;\n    }\n\n    public void setAppDao(AppDao appDao) {\n        this.appDao = appDao;\n    }\n\n    public void setInstanceFaultDao(InstanceFaultDao instanceFaultDao) {\n        this.instanceFaultDao = instanceFaultDao;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/inspect/impl/RedisIsolationPersistenceInspector.java",
    "content": "package com.sohu.cache.inspect.impl;\n\nimport com.sohu.cache.alert.impl.BaseAlertService;\nimport com.sohu.cache.constant.InstanceStatusEnum;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.inspect.InspectParamEnum;\nimport com.sohu.cache.inspect.Inspector;\nimport com.sohu.cache.redis.RedisCenter;\nimport com.sohu.cache.redis.enums.RedisInfoEnum;\nimport com.sohu.cache.util.IdempotentConfirmer;\nimport com.sohu.cache.util.TypeUtil;\n\nimport org.apache.commons.collections.MapUtils;\nimport org.apache.commons.lang.StringUtils;\n\nimport redis.clients.jedis.Jedis;\n\nimport java.util.Collections;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * Created by yijunzhang on 15-1-30.\n */\npublic class RedisIsolationPersistenceInspector extends BaseAlertService implements Inspector {\n    \n    public static final int REDIS_DEFAULT_TIME = 5000;\n    \n    private RedisCenter redisCenter;\n\n    @Override\n    public boolean inspect(Map<InspectParamEnum, Object> paramMap) {\n        final String host = MapUtils.getString(paramMap, InspectParamEnum.SPLIT_KEY);\n        List<InstanceInfo> list = (List<InstanceInfo>) paramMap.get(InspectParamEnum.INSTANCE_LIST);\n        outer:\n        for (InstanceInfo info : list) {\n            final int port = info.getPort();\n            final int type = info.getType();\n            final long appId = info.getAppId();\n            int status = info.getStatus();\n            //非正常节点\n            if (status != InstanceStatusEnum.GOOD_STATUS.getStatus()) {\n                continue;\n            }\n            if (TypeUtil.isRedisDataType(type)) {\n                Jedis jedis = redisCenter.getJedis(appId, host, port, REDIS_DEFAULT_TIME, REDIS_DEFAULT_TIME);\n                try {\n                    Map<String, String> persistenceMap = parseMap(jedis);\n                    if (persistenceMap.isEmpty()) {\n                        logger.error(\"{}:{} get persistenceMap failed\", host, port);\n                        continue;\n                    }\n                    if (!isAofEnabled(persistenceMap)) {\n                        continue;\n                    }\n                    long aofCurrentSize = MapUtils.getLongValue(persistenceMap, RedisInfoEnum.aof_current_size.getValue());\n                    long aofBaseSize = MapUtils.getLongValue(persistenceMap, RedisInfoEnum.aof_base_size.getValue());\n                    //阀值大于60%\n                    long aofThresholdSize = (long) (aofBaseSize * 1.6);\n                    double percentage = getPercentage(aofCurrentSize, aofBaseSize);\n                    if (aofCurrentSize >= aofThresholdSize\n                            //大于64Mb\n                            && aofCurrentSize > (64 * 1024 * 1024)) {\n                        //bgRewriteAof\n                        boolean isInvoke = invokeBgRewriteAof(jedis);\n                        if (!isInvoke) {\n                            logger.error(\"{}:{} invokeBgRewriteAof failed\", host, port);\n                            continue;\n                        } else {\n                            logger.warn(\"{}:{} invokeBgRewriteAof started percentage={}\", host, port, percentage);\n                        }\n                        while (true) {\n                            try {\n                                //before wait 1s\n                                TimeUnit.SECONDS.sleep(1);\n                                Map<String, String> loopMap = parseMap(jedis);\n                                Integer aofRewriteInProgress = MapUtils.getInteger(loopMap, \"aof_rewrite_in_progress\", null);\n                                if (aofRewriteInProgress == null) {\n                                    logger.error(\"loop watch:{}:{} return failed\", host, port);\n                                    break;\n                                } else if (aofRewriteInProgress <= 0) {\n                                    //bgrewriteaof Done\n                                    logger.warn(\"{}:{} bgrewriteaof Done lastSize:{}Mb,currentSize:{}Mb\", host, port, getMb(aofCurrentSize), getMb(MapUtils.getLongValue(loopMap, \"aof_current_size\")));\n                                    break;\n                                } else {\n                                    //wait 1s\n                                    TimeUnit.SECONDS.sleep(1);\n                                }\n                            } catch (Exception e) {\n                                logger.error(e.getMessage(), e);\n                            }\n                        }\n                    } else {\n                        if (percentage > 50D) {\n                            long currentSize = getMb(aofCurrentSize);\n                            logger.info(\"checked {}:{} aof increase percentage:{}% currentSize:{}Mb\", host, port, percentage, currentSize > 0 ? currentSize : \"<1\");\n                        }\n                    }\n                } finally {\n                    jedis.close();\n                }\n            }\n        }\n        return true;\n    }\n\n    private long getMb(long bytes) {\n        return (long) (bytes / 1024 / 1024);\n    }\n\n    private boolean isAofEnabled(Map<String, String> infoMap) {\n        Integer aofEnabled = MapUtils.getInteger(infoMap, \"aof_enabled\", null);\n        return aofEnabled != null && aofEnabled == 1;\n    }\n\n    private double getPercentage(long aofCurrentSize, long aofBaseSize) {\n        if (aofBaseSize == 0) {\n            return 0.0D;\n        }\n        String format = String.format(\"%.2f\", (Double.valueOf(aofCurrentSize - aofBaseSize) * 100 / aofBaseSize));\n        return Double.parseDouble(format);\n    }\n\n    private Map<String, String> parseMap(final Jedis jedis) {\n        final StringBuilder builder = new StringBuilder();\n        boolean isInfo = new IdempotentConfirmer() {\n            @Override\n            public boolean execute() {\n                String persistenceInfo = null;\n                try {\n                    persistenceInfo = jedis.info(\"Persistence\");\n                } catch (Exception e) {\n                    logger.warn(e.getMessage() + \"-{}:{}\", jedis.getClient().getHost(), jedis.getClient().getPort(), e.getMessage());\n                }\n                boolean isOk = StringUtils.isNotBlank(persistenceInfo);\n                if (isOk) {\n                    builder.append(persistenceInfo);\n                }\n                return isOk;\n            }\n        }.run();\n        if (!isInfo) {\n            logger.error(\"{}:{} info Persistence failed\", jedis.getClient().getHost(), jedis.getClient().getPort());\n            return Collections.emptyMap();\n        }\n        String persistenceInfo = builder.toString();\n        if (StringUtils.isBlank(persistenceInfo)) {\n            return Collections.emptyMap();\n        }\n        Map<String, String> map = new LinkedHashMap<String, String>();\n        String[] array = persistenceInfo.split(\"\\r\\n\");\n        for (String line : array) {\n            String[] cells = line.split(\":\");\n            if (cells.length > 1) {\n                map.put(cells[0], cells[1]);\n            }\n        }\n\n        return map;\n    }\n\n    public boolean invokeBgRewriteAof(final Jedis jedis) {\n        return new IdempotentConfirmer() {\n            @Override\n            public boolean execute() {\n                try {\n                    String response = jedis.bgrewriteaof();\n                    if (response != null && response.contains(\"rewriting started\")) {\n                        return true;\n                    }\n                } catch (Exception e) {\n                    String message = e.getMessage();\n                    if (message.contains(\"rewriting already\")) {\n                        return true;\n                    }\n                    logger.error(message, e);\n                }\n                return false;\n            }\n        }.run();\n    }\n\n\tpublic void setRedisCenter(RedisCenter redisCenter) {\n\t\tthis.redisCenter = redisCenter;\n\t}\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/interceptor/AppAndInstanceAuthorityInterceptor.java",
    "content": "package com.sohu.cache.interceptor;\n\nimport java.io.IOException;\nimport java.util.List;\n\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport javax.servlet.http.HttpSession;\n\nimport org.apache.commons.collections.CollectionUtils;\nimport org.apache.commons.lang.StringUtils;\nimport org.apache.commons.lang.math.NumberUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.web.servlet.ModelAndView;\nimport org.springframework.web.servlet.handler.HandlerInterceptorAdapter;\n\nimport com.sohu.cache.constant.AppUserTypeEnum;\nimport com.sohu.cache.entity.AppToUser;\nimport com.sohu.cache.entity.AppUser;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.stats.instance.InstanceStatsCenter;\nimport com.sohu.cache.web.service.AppService;\nimport com.sohu.cache.web.service.UserLoginStatusService;\nimport com.sohu.cache.web.service.UserService;\n\n/**\n * 应用和实例权限验证\n * \n * @author leifu\n * @Date 2014年10月29日\n * @Time 下午3:18:00\n */\npublic class AppAndInstanceAuthorityInterceptor extends HandlerInterceptorAdapter {\n    private Logger logger = LoggerFactory.getLogger(AppAndInstanceAuthorityInterceptor.class);\n\n    private AppService appService;\n\n    private UserService userService;\n\n    private InstanceStatsCenter instanceStatsCenter;\n    \n    private UserLoginStatusService userLoginStatusService;\n\n    @Override\n    public boolean preHandle(HttpServletRequest request,\n            HttpServletResponse response, Object handler) throws Exception {\n        // 1. 获取用户\n        long userId = userLoginStatusService.getUserIdFromLoginStatus(request);\n        AppUser user = userService.get(userId);\n        \n        // 2. 管理员直接跳过\n        if (AppUserTypeEnum.ADMIN_USER.value().equals(user.getType())) {\n            return true;\n        }\n\n        // 3. 应用id\n        String appId = request.getParameter(\"appId\");\n        if (StringUtils.isNotBlank(appId)) {\n            checkUserAppPower(response, request.getSession(true), user, NumberUtils.toLong(appId));\n        }\n\n        // 4. 实例权限检测(其实也是应用)\n        String instanceId = request.getParameter(\"instanceId\");\n        if (StringUtils.isNotBlank(instanceId)) {\n            InstanceInfo instanceInfo = instanceStatsCenter.getInstanceInfo(Long.parseLong(instanceId));\n            checkUserAppPower(response, request.getSession(true), user, instanceInfo.getAppId());\n        }\n\n        return true;\n    }\n\n    /**\n     * 检查用户应用的权限\n     * \n     * @param response\n     * @param session\n     * @param user\n     * @param appId\n     * @return\n     */\n    private void checkUserAppPower(HttpServletResponse response, HttpSession session, AppUser user, Long appId) {\n        // 应用下的用户\n        List<AppToUser> appToUsers = appService.getAppToUserList(appId);\n        if (CollectionUtils.isNotEmpty(appToUsers)) {\n            for (AppToUser tempAppToUser : appToUsers) {\n                if (user.getId().equals(tempAppToUser.getUserId())) {\n                    return;\n                }\n            }\n            // 没权限\n            String path = session.getServletContext().getContextPath();\n            try {\n                response.sendRedirect(path + \"/resources/error/noPower.jsp?appId=\" + appId);\n            } catch (IOException e) {\n                logger.error(e.getMessage(), e);\n            }\n        }\n    }\n\n    @Override\n    public void postHandle(HttpServletRequest request,\n            HttpServletResponse response, Object handler,\n            ModelAndView modelAndView) throws Exception {\n    }\n\n    @Override\n    public void afterCompletion(HttpServletRequest request,\n            HttpServletResponse response, Object handler, Exception ex)\n            throws Exception {\n    }\n\n    public void setAppService(AppService appService) {\n        this.appService = appService;\n    }\n\n    public void setUserService(UserService userService) {\n        this.userService = userService;\n    }\n\n    public void setInstanceStatsCenter(InstanceStatsCenter instanceStatsCenter) {\n        this.instanceStatsCenter = instanceStatsCenter;\n    }\n\n    public void setUserLoginStatusService(UserLoginStatusService userLoginStatusService) {\n        this.userLoginStatusService = userLoginStatusService;\n    }\n\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/interceptor/FrontUserLoginInterceptor.java",
    "content": "package com.sohu.cache.interceptor;\n\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.web.servlet.ModelAndView;\nimport org.springframework.web.servlet.handler.HandlerInterceptorAdapter;\n\nimport com.sohu.cache.entity.AppUser;\nimport com.sohu.cache.util.ConstUtils;\nimport com.sohu.cache.web.service.UserLoginStatusService;\nimport com.sohu.cache.web.service.UserService;\n\n/**\n * 前台登陆验证\n *\n * @author leifu\n * @Time 2014年6月12日\n */\npublic class FrontUserLoginInterceptor extends HandlerInterceptorAdapter {\n    private Logger logger = LoggerFactory.getLogger(FrontUserLoginInterceptor.class);\n    \n    private UserService userService;\n    \n    private UserLoginStatusService userLoginStatusService;\n\n    @Override\n    public boolean preHandle(HttpServletRequest request,\n                             HttpServletResponse response, Object handler) throws Exception {\n\n        long userId = userLoginStatusService.getUserIdFromLoginStatus(request);\n        AppUser user = userService.get(userId);\n        \n        if (user == null) {\n            String redirectUrl = LoginInterceptorUtil.getLoginRedirectUrl(request);\n            response.sendRedirect(redirectUrl);\n            return false;\n        }\n        \n        request.setAttribute(\"userInfo\", user);\n        request.setAttribute(\"uri\", request.getRequestURI());\n        \n        return true;\n    }\n\n    @Override\n    public void postHandle(HttpServletRequest request,\n                           HttpServletResponse response, Object handler,\n                           ModelAndView modelAndView) throws Exception {\n    }\n\n    @Override\n    public void afterCompletion(HttpServletRequest request,\n                                HttpServletResponse response, Object handler, Exception ex)\n            throws Exception {\n    }\n\n    public void setUserService(UserService userService) {\n        this.userService = userService;\n    }\n\n    public void setUserLoginStatusService(UserLoginStatusService userLoginStatusService) {\n        this.userLoginStatusService = userLoginStatusService;\n    }\n\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/interceptor/LoginInterceptorUtil.java",
    "content": "package com.sohu.cache.interceptor;\n\nimport javax.servlet.http.HttpServletRequest;\n\nimport org.apache.commons.lang.StringUtils;\n\nimport com.sohu.cache.util.ConstUtils;\n\n/**\n * @author leifu\n * @Date 2016年11月23日\n * @Time 下午3:23:54\n */\npublic class LoginInterceptorUtil {\n\n    /**\n     * 获取登录跳转地址\n     * \n     * @param request\n     * @return\n     * @throws Exception\n     */\n    public static String getLoginRedirectUrl(HttpServletRequest request) throws Exception {\n        StringBuffer redirectUrl = new StringBuffer();\n        redirectUrl.append(request.getSession(true).getServletContext().getContextPath());\n        redirectUrl.append(\"/manage/login?\");\n        // 跳转地址\n        redirectUrl.append(ConstUtils.RREDIRECT_URL_PARAM);\n        redirectUrl.append(\"=\");\n        redirectUrl.append(request.getRequestURI());\n        // 跳转参数\n        String query = request.getQueryString();\n        if (StringUtils.isNotBlank(query)) {\n            redirectUrl.append(\"?\");\n            redirectUrl.append(java.net.URLEncoder.encode(request.getQueryString(), \"UTF-8\"));\n        }\n        return redirectUrl.toString();\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/interceptor/ManageUserLoginInterceptor.java",
    "content": "package com.sohu.cache.interceptor;\n\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.web.servlet.ModelAndView;\nimport org.springframework.web.servlet.handler.HandlerInterceptorAdapter;\n\nimport com.sohu.cache.constant.AppUserTypeEnum;\nimport com.sohu.cache.entity.AppUser;\nimport com.sohu.cache.web.service.UserLoginStatusService;\nimport com.sohu.cache.web.service.UserService;\n\n/**\n * 管理员登录验证\n * @author leifu\n * @Date 2014年10月28日\n * @Time 下午1:35:14\n */\npublic class ManageUserLoginInterceptor extends HandlerInterceptorAdapter {\n    private Logger logger = LoggerFactory.getLogger(ManageUserLoginInterceptor.class);\n\n    private UserService userService;\n    \n    private UserLoginStatusService userLoginStatusService;\n    \n    @Override\n    public boolean preHandle(HttpServletRequest request,\n            HttpServletResponse response, Object handler) throws Exception {\n\n        long userId = userLoginStatusService.getUserIdFromLoginStatus(request);\n        AppUser user = userService.get(userId);\n\n        //必须是管理员\n        if (user == null || user.getType() != AppUserTypeEnum.ADMIN_USER.value()) {\n            String redirectUrl = LoginInterceptorUtil.getLoginRedirectUrl(request);\n            response.sendRedirect(redirectUrl);\n            return false;\n        }\n        \n        request.setAttribute(\"userInfo\", user);\n        request.setAttribute(\"uri\", request.getRequestURI());\n        \n        return true;\n\n    }\n\n    @Override\n    public void postHandle(HttpServletRequest request,\n            HttpServletResponse response, Object handler,\n            ModelAndView modelAndView) throws Exception {\n    }\n\n    @Override\n    public void afterCompletion(HttpServletRequest request,\n            HttpServletResponse response, Object handler, Exception ex)\n            throws Exception {\n    }\n\n    public void setUserService(UserService userService) {\n        this.userService = userService;\n    }\n\n    public void setUserLoginStatusService(UserLoginStatusService userLoginStatusService) {\n        this.userLoginStatusService = userLoginStatusService;\n    }\n\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/jmx/ErrorLoggerWatcher.java",
    "content": "package com.sohu.cache.jmx;\n\nimport ch.qos.logback.classic.Logger;\nimport ch.qos.logback.classic.LoggerContext;\n\nimport com.google.common.util.concurrent.AtomicLongMap;\nimport com.sohu.cache.log.statistic.ErrorStatisticsAppender;\n\nimport org.slf4j.LoggerFactory;\n\nimport java.util.*;\n\n/**\n * Created by yijunzhang on 14-2-19.\n */\npublic class ErrorLoggerWatcher implements ErrorLoggerWatcherMBean {\n    private final org.slf4j.Logger logger = LoggerFactory.getLogger(this.getClass());\n\n    /**\n     * 初始化logback 自定义appender\n     */\n    public void init() {\n        logger.warn(\"ErrorStatisticsAppender init begin!\");\n        if (LoggerFactory.getILoggerFactory() instanceof LoggerContext) {\n            LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();\n            Logger rootLogger = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME);\n            ErrorStatisticsAppender errorStatisticsAppender = new ErrorStatisticsAppender();\n            errorStatisticsAppender.setContext(loggerContext);\n            errorStatisticsAppender.start();\n            rootLogger.addAppender(errorStatisticsAppender);\n            logger.warn(\"ErrorStatisticsAppender init Done!\");\n        } else {\n            logger.error(\"ErrorStatisticsAppender init failed , LoggerFactory.getILoggerFactory()={}\", LoggerFactory.getILoggerFactory());\n        }\n\n    }\n\n    @Override\n    public long getTotalErrorCount() {\n        AtomicLongMap<String> atomicLongMap = ErrorStatisticsAppender.ERROR_NAME_VALUE_MAP;\n        return atomicLongMap.sum();\n    }\n\n    @Override\n    public Map<String, Long> getErrorInfos() {\n        Map<String, Long> longMap = ErrorStatisticsAppender.ERROR_NAME_VALUE_MAP.asMap();\n        Map<String, Long> resultMap = new LinkedHashMap<String, Long>();\n        //排序\n        SortedMap<Long, List<String>> sortedMap = new TreeMap<Long, List<String>>();\n        for (Map.Entry<String, Long> entry : longMap.entrySet()) {\n            String key = entry.getKey();\n            Long num = entry.getValue();\n            if (num == 0L) {\n                continue;\n            }\n            if (sortedMap.containsKey(num)) {\n                sortedMap.get(num).add(key);\n            } else {\n                List<String> keys = new ArrayList<String>();\n                keys.add(key);\n                sortedMap.put(num, keys);\n            }\n        }\n        List<Long> keys = new ArrayList<Long>(sortedMap.keySet());\n        Collections.reverse(keys);\n\n        for (Long num : keys) {\n            for (String key : sortedMap.get(num)) {\n                resultMap.put(key, num);\n            }\n        }\n        return resultMap;\n    }\n\n    @Override\n    public void clear() {\n        ErrorStatisticsAppender.ERROR_NAME_VALUE_MAP.clear();\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/jmx/ErrorLoggerWatcherMBean.java",
    "content": "package com.sohu.cache.jmx;\n\nimport java.util.Map;\n\n/**\n * Created by yijunzhang on 14-2-18.\n */\npublic interface ErrorLoggerWatcherMBean {\n\n    public long getTotalErrorCount();\n\n    public Map<String, Long> getErrorInfos();\n\n    public void clear();\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/jmx/ThreadPoolStatisticsImpl.java",
    "content": "package com.sohu.cache.jmx;\n\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.ThreadPoolExecutor;\n\n/**\n * Created by yijunzhang on 14-7-21.\n */\npublic class ThreadPoolStatisticsImpl implements ThreadPoolStatisticsMBean {\n\n    private final ThreadPoolExecutor threadPoolExecutor;\n\n    public ThreadPoolStatisticsImpl(ExecutorService executorService) {\n        if (executorService != null && executorService instanceof ThreadPoolExecutor) {\n            this.threadPoolExecutor = (ThreadPoolExecutor) executorService;\n        } else {\n            throw new IllegalArgumentException(\"executorService not instanceof ThreadPoolExecutor\");\n        }\n    }\n\n    @Override\n    public double getUsedPercentage() {\n        if (threadPoolExecutor == null) {\n            return 0;\n        }\n        long completedTaskCount = threadPoolExecutor.getCompletedTaskCount();\n        long taskCount = threadPoolExecutor.getTaskCount();\n        long runningCount = (taskCount - completedTaskCount);\n        if (runningCount < 0L) {\n            runningCount = 0L;\n        }\n        long maxPoolSize = threadPoolExecutor.getMaximumPoolSize();\n\n        double run = Double.valueOf(runningCount);\n        double size = Double.valueOf(maxPoolSize);\n        if (run == 0d || size == 0d) {\n            return 0D;\n        }\n        return run / size;\n    }\n\n    @Override\n    public int getActiveCount() {\n        if (threadPoolExecutor == null) {\n            return 0;\n        }\n        return threadPoolExecutor.getActiveCount();\n    }\n\n    @Override\n    public long getCompletedTaskCount() {\n        if (threadPoolExecutor == null) {\n            return 0;\n        }\n        return threadPoolExecutor.getCompletedTaskCount();\n    }\n\n    @Override\n    public int getCorePoolSize() {\n        if (threadPoolExecutor == null) {\n            return 0;\n        }\n        return threadPoolExecutor.getCorePoolSize();\n    }\n\n    @Override\n    public int getLargestPoolSize() {\n        if (threadPoolExecutor == null) {\n            return 0;\n        }\n        return threadPoolExecutor.getLargestPoolSize();\n    }\n\n    @Override\n    public int getMaximumPoolSize() {\n        if (threadPoolExecutor == null) {\n            return 0;\n        }\n        return threadPoolExecutor.getMaximumPoolSize();\n    }\n\n    @Override\n    public int getPoolSize() {\n        if (threadPoolExecutor == null) {\n            return 0;\n        }\n        return threadPoolExecutor.getPoolSize();\n    }\n\n    @Override\n    public long getTaskCount() {\n        if (threadPoolExecutor == null) {\n            return 0;\n        }\n        return threadPoolExecutor.getTaskCount();\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/jmx/ThreadPoolStatisticsMBean.java",
    "content": "package com.sohu.cache.jmx;\n\n/**\n * Created by yijunzhang on 14-7-21.\n */\npublic interface ThreadPoolStatisticsMBean {\n\n    /**\n     * @return 获取当前线程池使用率\n     */\n    double getUsedPercentage();\n\n    /**\n     * @return 返回主动执行任务的近似线程数\n     */\n    int getActiveCount();\n\n    /**\n     * @return 返回已完成执行的近似任务总数\n     */\n    long getCompletedTaskCount();\n\n    /**\n     * @return 返回核心线程数\n     */\n    int getCorePoolSize();\n\n    /**\n     * @return 返回曾经同时位于池中的最大线程数。\n     */\n    int getLargestPoolSize();\n\n    /**\n     * @return 返回允许的最大线程数\n     */\n    int getMaximumPoolSize();\n\n    /**\n     * @return 返回池中的当前线程数。\n     */\n    int getPoolSize();\n\n    /**\n     * @return 返回曾计划执行的近似任务总数\n     */\n    long getTaskCount();\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/log/statistic/ErrorStatisticsAppender.java",
    "content": "package com.sohu.cache.log.statistic;\n\nimport ch.qos.logback.classic.Level;\nimport ch.qos.logback.classic.spi.ILoggingEvent;\nimport ch.qos.logback.classic.spi.IThrowableProxy;\nimport ch.qos.logback.core.AppenderBase;\nimport com.google.common.util.concurrent.AtomicLongMap;\n/**\n * 自定义Appender，用于统计异常名和数量键值对\n * @author leifu\n * @Time 2014年10月17日\n */\npublic class ErrorStatisticsAppender extends AppenderBase<ILoggingEvent> {\n\t/**\n\t * guava的AtomicLongMap\n\t */\n    public static final AtomicLongMap<String> ERROR_NAME_VALUE_MAP = AtomicLongMap.create();\n    @Override\n    protected void append(ILoggingEvent event) {\n        if (event == null) {\n            return;\n        }\n        if (event.getLevel() == Level.ERROR || event.getLevel() == Level.WARN) {\n            IThrowableProxy throwableProxy = event.getThrowableProxy();\n            if (throwableProxy != null) {\n            \t//接口名\n                String errorClassName = throwableProxy.getClassName();\n                if (errorClassName != null && !\"\".equals(errorClassName.trim())) {\n                \t//写入AtomicLongMap并计数\n                    ERROR_NAME_VALUE_MAP.getAndIncrement(errorClassName);\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/machine/MachineCenter.java",
    "content": "package com.sohu.cache.machine;\n\nimport java.util.List;\nimport java.util.Map;\n\nimport com.sohu.cache.constant.MachineInfoEnum.TypeEnum;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.entity.InstanceStats;\nimport com.sohu.cache.entity.MachineInfo;\nimport com.sohu.cache.entity.MachineStats;\n\n/**\n * 基于host的操作\n *\n * User: lingguo\n * Date: 14-6-12\n * Time: 上午10:32\n */\npublic interface MachineCenter {\n\n    /**\n     * 为当前host创建trigger，并部署\n     *\n     * @param hostId    机器id\n     * @param ip        ip\n     * @return          是否部署成功\n     */\n    public boolean deployMachineCollection(final long hostId, final String ip);\n    \n    /**\n     * 为当前host删除trigger,取消部署\n     *\n     * @param hostId    机器id\n     * @param ip        ip\n     * @return          是否取消部署成功\n     */\n    public boolean unDeployMachineCollection(final long hostId, final String ip);\n\n    /**\n     * 收集host的状态信息\n     *\n     * @param hostId        机器id\n     * @param collectTime   收集时间\n     * @param ip            ip\n     * @return              机器的信息\n     */\n    public Map<String, Object> collectMachineInfo(final long hostId, final long collectTime, final String ip);\n    \n    /**\n     * 异步收集host的状态信息\n     *\n     * @param hostId        机器id\n     * @param collectTime   收集时间\n     * @param ip            ip\n     */\n    public void asyncCollectMachineInfo(final long hostId, final long collectTime, final String ip);\n\n    /**\n     * 为当前机器的监控删除trigger\n     *\n     * @param hostId    机器id\n     * @param ip    ip\n     * @return      取消部署成功返回true， 否则返回false\n     */\n    public boolean unDeployMachineMonitor(final long hostId, final String ip);\n    \n    /**\n     * 为当前机器的监控创建trigger\n     *\n     * @param hostId    机器id\n     * @param ip    ip\n     * @return      部署成功返回true， 否则返回false\n     */\n    public boolean deployMachineMonitor(final long hostId, final String ip);\n\n    /**\n     * 监控机器的状态信息，向上层汇报或者报警\n     *\n     * @param hostId    机器id\n     * @param ip        ip\n     * @return\n     */\n    public void monitorMachineStats(final long hostId, final String ip);\n    \n    /**\n     * 异步监控机器的状态信息，向上层汇报或者报警\n     *\n     * @param hostId    机器id\n     * @param ip        ip\n     * @return\n     */\n    public void asyncMonitorMachineStats(final long hostId, final String ip);\n\n    /**\n     * 在主机ip上的端口port上启动一个进程，并check是否启动成功；\n     *\n     * @param ip    ip\n     * @param port  端口\n     * @param shell shell命令\n     * @return 是否成功\n     */\n    public boolean startProcessAtPort(String ip, int port, final String shell);\n\n    /**\n     * 执行shell命令并获取返回结果\n     *\n     * @param ip\n     * @param shell\n     * @return\n     */\n    public String executeShell(final String ip, String shell);\n\n    /**\n     * 根据类型返回机器可用端口\n     *\n     * @param ip\n     * @param type\n     * @return\n     */\n    public Integer getAvailablePort(final String ip, final int type);\n\n    /**\n     * 创建远程文件\n     *\n     * @param host\n     * @param fileName\n     * @param content\n     * @return 是否创建成功\n     */\n    public String createRemoteFile(final String host, String fileName, List<String> content);\n\n\n    /**\n     * 获取机器列表\n     * @param ipLike\n     * @return\n     */\n    public List<MachineStats> getMachineStats(String ipLike);\n    \n    /**\n     * 获取全部机器列表\n     * @return\n     */\n    public List<MachineStats> getAllMachineStats();\n\n    /**\n     * 根据ip获取机器信息\n     * @param ip\n     * @return\n     */\n    public MachineInfo getMachineInfoByIp(String ip);\n\n\n    MachineStats getMachineMemoryDetail(String ip);\n    \n    /**\n     * 获取一台机器的所有实例\n     * @param ip\n     * @return\n     */\n    List<InstanceInfo> getMachineInstanceInfo(String ip);\n    \n    \n    /**\n     * 获取一台机器的所有实例统计信息\n     * @param ip\n     * @return\n     */\n    List<InstanceStats> getMachineInstanceStatsByIp(String ip);\n\n    /**\n     * 获取指定机器某个redis端口的最近日志\n     * @param maxLineNum\n     * @return\n     */\n    String showInstanceRecentLog(InstanceInfo instanceInfo, int maxLineNum);\n\n    /**\n     * 根据机器类型获取机器列表\n     * @param typeEnum\n     * @return\n     */\n    List<MachineInfo> getMachineInfoByType(TypeEnum typeEnum);\n    \n    /**\n     * 为当前ip创建trigger，并部署\n     *\n     * @param hostId    机器id\n     * @param ip        ip\n     * @return          是否部署成功\n     */\n    public boolean deployServerCollection(long hostId, String ip);\n    \n    /**\n     * 为当前服务器状态收集删除trigger\n     * @param hostId    机器id\n     * @param ip    ip\n     * @return      取消部署成功返回true， 否则返回false\n     */\n    public boolean unDeployServerCollection(final long hostId, final String ip);\n\n    /**\n     * 获取机器下实例数map\n     * @return\n     */\n    public Map<String, Integer> getMachineInstanceCountMap();\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/machine/MachineDeployCenter.java",
    "content": "package com.sohu.cache.machine;\n\nimport com.sohu.cache.entity.MachineInfo;\n\n/**\n * 机器部署相关\n * @author leifu\n * changed @Date 2016-4-24\n * @Time 下午5:07:30\n */\npublic interface MachineDeployCenter {\n\n    /**\n     * 增加一台机器:入db和开启统计\n     *\n     * @param machineInfo\n     */\n    public boolean addMachine(MachineInfo machineInfo);\n\n    /**\n     * 移除一台机器：删db数据和关闭统计\n     *\n     * @param machineInfo\n     */\n    public boolean removeMachine(MachineInfo machineInfo);\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/machine/MachineProperty.java",
    "content": "package com.sohu.cache.machine;\n\nimport com.google.common.collect.ComparisonChain;\n\nimport java.util.Comparator;\n\n/**\n * 选择机器时根据机器的memory、traffic和load进行排序；\n * 在memory满足的情况，排序规则是：traffic > load > memory\n *\n * @author: lingguo\n * @time: 2014/9/17 12:04\n */\npublic class MachineProperty implements Comparator<MachineProperty> {\n    private long hostId;\n    private long memory;\n    private double traffic;\n    private double load;\n\n    public MachineProperty() {}\n\n    public MachineProperty(long hostId, long memory, double traffic, double load) {\n        this.hostId = hostId;\n        this.memory = memory;\n        this.traffic = traffic;\n        this.load = load;\n    }\n\n    public long getHostId() {\n        return hostId;\n    }\n\n    public void setHostId(long hostId) {\n        this.hostId = hostId;\n    }\n\n    public long getMemory() {\n        return memory;\n    }\n\n    public void setMemory(long memory) {\n        this.memory = memory;\n    }\n\n    public double getTraffic() {\n        return traffic;\n    }\n\n    public void setTraffic(double traffic) {\n        this.traffic = traffic;\n    }\n\n    public double getLoad() {\n        return load;\n    }\n\n    public void setLoad(double load) {\n        this.load = load;\n    }\n\n    @Override\n    public int compare(MachineProperty o1, MachineProperty o2) {\n        return ComparisonChain.start()\n                .compare(o1.traffic, o2.traffic)\n                .compare(o1.load, o2.load)\n                .compare(o2.memory, o1.memory)\n                .result();\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/machine/PortGenerator.java",
    "content": "package com.sohu.cache.machine;\n\nimport com.sohu.cache.constant.EmptyObjectConstant;\nimport com.sohu.cache.constant.SymbolConstant;\nimport com.sohu.cache.exception.SSHException;\nimport com.sohu.cache.ssh.SSHUtil;\nimport com.sohu.cache.util.ConstUtils;\nimport com.google.common.util.concurrent.AtomicLongMap;\n\nimport org.apache.commons.lang.StringUtils;\nimport org.apache.commons.lang.math.NumberUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * 生成一个redis可用端口\n *\n * @author: lingguo\n * @time: 2014/8/25 20:57\n */\npublic class PortGenerator {\n    private static Logger logger = LoggerFactory.getLogger(PortGenerator.class);\n    /**\n     * redis port常量\n     */\n    private static final Integer REDIS_START_PORT = 6379;\n    private static AtomicLongMap<String> redisPortHolder = AtomicLongMap.create();\n\n    /**\n     * 返回一个redis的可用端口：\n     *  - 1. 通过shell查询redis当前已用的最大port；\n     *  - 2. 为什么同步：防止多线程访问时获取到同样的端口；\n     *  - 3. 为什么还用原子计数：连续两次调用时，如果进程还没启动，则拿到的仍然是相同的端口；\n     *\n     * @param ip\n     * @return\n     */\n    public static synchronized Integer getRedisPort(final String ip) {\n        if (redisPortHolder.get(ip) == 0L) {\n            redisPortHolder.put(ip, REDIS_START_PORT);\n        }\n        String maxPortStr = \"\";\n        try {\n            int sshPort = SSHUtil.getSshPort(ip);\n            maxPortStr = getMaxPortStr(ip, sshPort);\n        } catch (SSHException e) {\n            logger.error(\"cannot get max port of redis by ssh, ip: {}\", ip, e);\n        }\n\n        if (StringUtils.isBlank(maxPortStr) || !StringUtils.isNumeric(maxPortStr)) {\n            logger.warn(\"{} the max port of redis is invalid, maxPortStr: {}\", ip, maxPortStr);\n            return new Long(redisPortHolder.getAndIncrement(ip)).intValue();\n        }\n\n        int availablePort = Integer.valueOf(maxPortStr) + 1;\n        // 兼容连续调用的情况\n        if (availablePort < redisPortHolder.get(ip)) {\n            availablePort = new Long(redisPortHolder.getAndIncrement(ip)).intValue();\n        } else {    // 正常情况，以及兼容系统重启和当前端口不可用的情形\n            redisPortHolder.put(ip, availablePort + 1);\n        }\n\n        try {\n            while (SSHUtil.isPortUsed(ip, availablePort)) {\n                availablePort++;\n            }\n        } catch (SSHException e) {\n            logger.error(\"check port error, ip: {}, port: {}\", ip, availablePort, e);\n        }\n        redisPortHolder.put(ip, availablePort+1);\n        return availablePort;\n    }\n\n    @Deprecated\n    public static String getMaxPortStrOld(String ip, int sshPort) throws SSHException {\n        String redisPidCmd = \"ps -ef | grep redis | grep -v 'grep' |  awk -F '*:' '{print $2}' \" +\n                \" | awk -F ' ' '{print $1}' | sort -r | head -1\";\n        return SSHUtil.execute(ip, sshPort, ConstUtils.USERNAME, ConstUtils.PASSWORD, redisPidCmd);\n    }\n    \n    /**\n     * 直接解析ps -ef | grep redis | grep -v 'grep'\n     * @param ip\n     * @param sshPort\n     * @return\n     * @throws SSHException\n     */\n     public static String getMaxPortStr(String ip, int sshPort) throws SSHException {\n        String redisPidCmd = \"ps -ef | grep redis | grep -v 'grep'\";\n        String redisProcessStr = SSHUtil.execute(ip, sshPort, ConstUtils.USERNAME, ConstUtils.PASSWORD, redisPidCmd);\n        if (StringUtils.isBlank(redisProcessStr)) {\n            return EmptyObjectConstant.EMPTY_STRING;\n        }\n        int maxPort = 0;\n        String[] lines = redisProcessStr.split(SymbolConstant.ENTER);\n        for (String line : lines) {\n            if (StringUtils.isBlank(line)) {\n                continue;\n            }\n            int redisServerIndex = line.indexOf(\"redis-server\");\n            int redisSentinelIndex = line.indexOf(\"redis-sentinel\");\n            if (redisServerIndex >= 0) {\n                line = line.substring(redisServerIndex);\n            }\n            if (redisSentinelIndex >= 0) {\n                line = line.substring(redisSentinelIndex);\n            }\n            if (redisServerIndex < 0 && redisSentinelIndex < 0) {\n                continue;\n            }\n            String[] items = line.split(SymbolConstant.SPACE);\n            if (items.length >= 2) {\n                String hostPort = items[1];\n                if (StringUtils.isBlank(hostPort)) {\n                    continue;\n                }\n                String[] hostPortArr = hostPort.split(SymbolConstant.COLON);\n                if (hostPortArr.length != 2) {\n                    continue;\n                }\n                String portStr = hostPortArr[1];\n                if (!NumberUtils.isDigits(portStr)) {\n                    continue;\n                }\n                int port = NumberUtils.toInt(portStr);\n                if (port > maxPort) {\n                    maxPort = port;\n                }\n            }\n        }\n        return maxPort == 0 ? EmptyObjectConstant.EMPTY_STRING : String.valueOf(maxPort);\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/machine/impl/MachineCenterImpl.java",
    "content": "package com.sohu.cache.machine.impl;\n\nimport static com.google.common.base.Preconditions.checkArgument;\n\nimport java.io.BufferedWriter;\nimport java.io.File;\nimport java.io.IOException;\nimport java.nio.charset.Charset;\nimport java.nio.file.Files;\nimport java.nio.file.Path;\nimport java.nio.file.Paths;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.TimeUnit;\n\nimport org.apache.commons.collections.CollectionUtils;\nimport org.apache.commons.collections.MapUtils;\nimport org.apache.commons.lang.StringUtils;\nimport org.quartz.JobKey;\nimport org.quartz.Trigger;\nimport org.quartz.TriggerKey;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.util.Assert;\n\nimport redis.clients.jedis.HostAndPort;\n\nimport com.google.common.base.Strings;\nimport com.sohu.cache.async.AsyncService;\nimport com.sohu.cache.async.AsyncThreadPoolFactory;\nimport com.sohu.cache.async.KeyCallable;\nimport com.sohu.cache.constant.InstanceStatusEnum;\nimport com.sohu.cache.constant.MachineConstant;\nimport com.sohu.cache.constant.MachineInfoEnum.TypeEnum;\nimport com.sohu.cache.dao.AppDao;\nimport com.sohu.cache.dao.InstanceDao;\nimport com.sohu.cache.dao.InstanceStatsDao;\nimport com.sohu.cache.dao.MachineDao;\nimport com.sohu.cache.dao.MachineStatsDao;\nimport com.sohu.cache.entity.AppDesc;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.entity.InstanceStats;\nimport com.sohu.cache.entity.MachineInfo;\nimport com.sohu.cache.entity.MachineMemInfo;\nimport com.sohu.cache.entity.MachineStats;\nimport com.sohu.cache.exception.SSHException;\nimport com.sohu.cache.machine.MachineCenter;\nimport com.sohu.cache.machine.PortGenerator;\nimport com.sohu.cache.protocol.MachineProtocol;\nimport com.sohu.cache.redis.RedisCenter;\nimport com.sohu.cache.schedule.SchedulerCenter;\nimport com.sohu.cache.ssh.SSHUtil;\nimport com.sohu.cache.stats.instance.InstanceStatsCenter;\nimport com.sohu.cache.util.ConstUtils;\nimport com.sohu.cache.util.IdempotentConfirmer;\nimport com.sohu.cache.util.ObjectConvert;\nimport com.sohu.cache.util.ScheduleUtil;\nimport com.sohu.cache.util.TypeUtil;\nimport com.sohu.cache.web.component.EmailComponent;\nimport com.sohu.cache.web.component.MobileAlertComponent;\n\n/**\n * 机器接口的实现\n * User: lingguo\n * Date: 14-6-12\n * Time: 上午10:46\n */\npublic class MachineCenterImpl implements MachineCenter {\n    private final Logger logger = LoggerFactory.getLogger(MachineCenterImpl.class);\n\n    private SchedulerCenter schedulerCenter;\n\n    private InstanceStatsCenter instanceStatsCenter;\n\n    private MachineStatsDao machineStatsDao;\n\n    private InstanceDao instanceDao;\n\n    private InstanceStatsDao instanceStatsDao;\n\n    private MachineDao machineDao;\n\n    private RedisCenter redisCenter;\n    \n    private AppDao appDao;\n    \n    /**\n     * 邮箱报警\n     */\n    private EmailComponent emailComponent;\n\n    /**\n     * 手机短信报警\n     */\n    private MobileAlertComponent mobileAlertComponent;\n    \n\tprivate AsyncService asyncService;\n\t\n\tpublic void init() {\n\t\tasyncService.assemblePool(AsyncThreadPoolFactory.MACHINE_POOL, \n\t\t\t\tAsyncThreadPoolFactory.MACHINE_THREAD_POOL);\n\t}\n\n    /**\n     * 为当前机器收集信息创建trigger并部署\n     *\n     * @param hostId 机器id\n     * @param ip     ip\n     * @return 部署成功返回true，否则返回false\n     */\n    @Override\n    public boolean deployMachineCollection(final long hostId, final String ip) {\n        Assert.isTrue(hostId > 0);\n        Assert.hasText(ip);\n\n        Map<String, Object> dataMap = new HashMap<String, Object>();\n        dataMap.put(ConstUtils.HOST_KEY, ip);\n        dataMap.put(ConstUtils.HOST_ID_KEY, hostId);\n        JobKey jobKey = JobKey.jobKey(ConstUtils.MACHINE_JOB_NAME, ConstUtils.MACHINE_JOB_GROUP);\n        TriggerKey triggerKey = TriggerKey.triggerKey(ip, ConstUtils.MACHINE_TRIGGER_GROUP + hostId);\n        boolean result = schedulerCenter.deployJobByCron(jobKey, triggerKey, dataMap, ScheduleUtil.getMachineStatsCron(hostId), false);\n\n        return result;\n    }\n    \n    @Override\n    public boolean unDeployMachineCollection(long hostId, String ip) {\n        Assert.isTrue(hostId > 0);\n        Assert.hasText(ip);\n        TriggerKey collectionTriggerKey = TriggerKey.triggerKey(ip, ConstUtils.MACHINE_TRIGGER_GROUP + hostId);\n        Trigger trigger = schedulerCenter.getTrigger(collectionTriggerKey);\n        if (trigger == null) {\n            return true;\n        }\n        return schedulerCenter.unscheduleJob(collectionTriggerKey);\n    }\n    \n    //异步执行任务\n    public void asyncCollectMachineInfo(final long hostId, final long collectTime, final String ip) {\n    \tString key = \"collect-machine-\"+hostId+\"-\"+ip+\"-\"+collectTime;\n\t\tasyncService.submitFuture(AsyncThreadPoolFactory.MACHINE_POOL, new KeyCallable<Boolean>(key) {\n            public Boolean execute() {\n                try {\n                \tcollectMachineInfo(hostId, collectTime, ip);\n                    return true;\n                } catch (Exception e) {\n                    logger.error(e.getMessage(), e);\n                    return false;\n                }\n            }\n        });\n    }\n    \n    /**\n     * 收集当前host的状态信息，保存到mysql；\n     * 这里将hostId作为参数传入，mysql中集合名为：ip:hostId\n     *\n     * @param hostId      机器id\n     * @param collectTime 收集时间，格式：yyyyMMddHHmm\n     * @param ip          ip\n     * @return 机器的统计信息\n     */\n    @Override\n    public Map<String, Object> collectMachineInfo(final long hostId, final long collectTime, final String ip) {\n        Map<String, Object> infoMap = new HashMap<String, Object>();\n        MachineStats machineStats = null;\n        try {\n            int sshPort = SSHUtil.getSshPort(ip);\n            machineStats = SSHUtil.getMachineInfo(ip, sshPort, ConstUtils.USERNAME, ConstUtils.PASSWORD);\n            machineStats.setHostId(hostId);\n            if (machineStats != null) {\n                infoMap.put(MachineConstant.Ip.getValue(), machineStats.getIp());\n                infoMap.put(MachineConstant.CpuUsage.getValue(), machineStats.getCpuUsage());\n                infoMap.put(MachineConstant.MemoryUsageRatio.getValue(), machineStats.getMemoryUsageRatio());\n                /**\n                 * SSHUtil返回的内存单位为k，由于实例的内存基本存储单位都是byte，所以统一为byte\n                 */\n                if (machineStats.getMemoryFree() != null) {\n                    infoMap.put(MachineConstant.MemoryFree.getValue(), Long.valueOf(machineStats.getMemoryFree()) * ConstUtils._1024);\n                } else {\n                    infoMap.put(MachineConstant.MemoryFree.getValue(), 0);\n                }\n                infoMap.put(MachineConstant.MemoryTotal.getValue(), Long.valueOf(machineStats.getMemoryTotal()) * ConstUtils._1024);\n                infoMap.put(MachineConstant.Load.getValue(), machineStats.getLoad());\n                infoMap.put(MachineConstant.Traffic.getValue(), machineStats.getTraffic());\n                infoMap.put(MachineConstant.DiskUsage.getValue(), machineStats.getDiskUsageMap());\n                infoMap.put(ConstUtils.COLLECT_TIME, collectTime);\n                instanceStatsCenter.saveStandardStats(infoMap, new HashMap<String, Object>(0), ip, (int) hostId, ConstUtils.MACHINE);\n                machineStats.setMemoryFree(Long.valueOf(machineStats.getMemoryFree()) * ConstUtils._1024 + \"\");\n                machineStats.setMemoryTotal(Long.valueOf(machineStats.getMemoryTotal()) * ConstUtils._1024 + \"\");\n                machineStats.setModifyTime(new Date());\n                machineStatsDao.mergeMachineStats(machineStats);\n                logger.info(\"collect machine info done, host: {}, time: {}\", ip, collectTime);\n            }\n        } catch (Exception e) {\n            logger.error(\"collectMachineErrorStats=>\" + machineStats);\n            logger.error(e.getMessage(), e);\n        }\n        return infoMap;\n    }\n\n    /**\n     * 为监控每台机器的状态部署trigger\n     *\n     * @param hostId 机器id\n     * @param ip     ip\n     * @return 是否部署成功\n     */\n    @Override\n    public boolean deployMachineMonitor(final long hostId, final String ip) {\n        Assert.isTrue(hostId > 0);\n        Assert.hasText(ip);\n\n        Map<String, Object> dataMap = new HashMap<String, Object>();\n        dataMap.put(ConstUtils.HOST_KEY, ip);\n        dataMap.put(ConstUtils.HOST_ID_KEY, hostId);\n\n        JobKey jobKey = JobKey.jobKey(ConstUtils.MACHINE_MONITOR_JOB_NAME, ConstUtils.MACHINE_MONITOR_JOB_GROUP);\n        TriggerKey triggerKey = TriggerKey.triggerKey(ip, ConstUtils.MACHINE_MONITOR_TRIGGER_GROUP + hostId);\n        boolean result = schedulerCenter.deployJobByCron(jobKey, triggerKey, dataMap, ScheduleUtil.getHourCronByHostId\n                (hostId), false);\n\n        return result;\n    }\n    \n    @Override\n    public boolean unDeployMachineMonitor(long hostId, String ip) {\n        Assert.isTrue(hostId > 0);\n        Assert.hasText(ip);\n        TriggerKey monitorTriggerKey = TriggerKey.triggerKey(ip, ConstUtils.MACHINE_MONITOR_TRIGGER_GROUP + hostId);\n        Trigger trigger = schedulerCenter.getTrigger(monitorTriggerKey);\n        if (trigger == null) {\n            return true;\n        }\n        return schedulerCenter.unscheduleJob(monitorTriggerKey);\n    }\n    \n    //异步执行任务\n    public void asyncMonitorMachineStats(final long hostId, final String ip) {\n    \tString key = \"monitor-machine-\"+hostId+\"-\"+ip;\n\t\tasyncService.submitFuture(AsyncThreadPoolFactory.MACHINE_POOL, new KeyCallable<Boolean>(key) {\n            public Boolean execute() {\n                try {\n                \tmonitorMachineStats(hostId, ip);\n                    return true;\n                } catch (Exception e) {\n                    logger.error(e.getMessage(), e);\n                    return false;\n                }\n            }\n        });\n    }\n\n    /**\n     * 监控机器的状态\n     *\n     * @param hostId 机器id\n     * @param ip     ip\n     */\n    @Override\n    public void monitorMachineStats(final long hostId, final String ip) {\n        Assert.isTrue(hostId > 0);\n        Assert.hasText(ip);\n\n        MachineStats machineStats = machineStatsDao.getMachineStatsByIp(ip);\n        if (machineStats == null) {\n            logger.warn(\"machine stats is null, ip: {}, time: {}\", ip, new Date());\n            return;\n        }\n        double cpuUsage = ObjectConvert.percentToDouble(machineStats.getCpuUsage(), 0);\n        double memoryUsage = ObjectConvert.percentToDouble(machineStats.getMemoryUsageRatio(), 0);\n        double load = 0;\n        try {\n            load = Double.valueOf(machineStats.getLoad());\n        } catch (NumberFormatException e) {\n            logger.error(e.getMessage(), e);\n        }\n        \n\n        double memoryThreshold = ConstUtils.MEMORY_USAGE_RATIO_THRESHOLD;\n\n        /**\n         * 当机器的状态超过预设的阀值时，向上汇报或者报警\n         */\n        StringBuilder alertContent = new StringBuilder();\n        // cpu使用率 todo\n        if (cpuUsage > ConstUtils.CPU_USAGE_RATIO_THRESHOLD) {\n            logger.warn(\"cpuUsageRatio is above security line. ip: {}, cpuUsage: {}%\", ip, cpuUsage);\n            alertContent.append(\"ip:\").append(ip).append(\",cpuUse:\").append(cpuUsage);\n        }\n\n        // 内存使用率 todo\n        if (memoryUsage > memoryThreshold) {\n            logger.warn(\"memoryUsageRatio is above security line, ip: {}, memoryUsage: {}%\", ip, memoryUsage);\n            alertContent.append(\"ip:\").append(ip).append(\",memUse:\").append(memoryUsage);\n        }\n\n        // 负载 todo\n        if (load > ConstUtils.LOAD_THRESHOLD) {\n            logger.warn(\"load is above security line, ip: {}, load: {}%\", ip, load);\n            alertContent.append(\"ip:\").append(ip).append(\",load:\").append(load);\n        }\n        \n        // 报警\n        if (StringUtils.isNotBlank(alertContent.toString())) {\n            String title = \"cachecloud机器异常:\";\n            emailComponent.sendMailToAdmin(title, alertContent.toString());\n            mobileAlertComponent.sendPhoneToAdmin(title + alertContent.toString());\n        }\n    }\n\n    /**\n     * 在主机ip上的端口port上启动一个进程，并check是否启动成功；\n     *\n     * @param ip    ip\n     * @param port  port\n     * @param shell shell命令\n     * @return 成功返回true，否则返回false；\n     */\n    @Override\n    public boolean startProcessAtPort(final String ip, final int port, final String shell) {\n        checkArgument(!Strings.isNullOrEmpty(ip), \"invalid ip.\");\n        checkArgument(port > 0 && port < 65536, \"invalid port\");\n        checkArgument(!Strings.isNullOrEmpty(shell), \"invalid shell.\");\n\n        boolean success = true;\n\n        try {\n            // 执行shell命令，有的是后台执行命令，没有返回值; 如果端口被占用，表示启动成功；\n            SSHUtil.execute(ip, shell);\n            success = isPortUsed(ip, port);\n        } catch (SSHException e) {\n            logger.error(\"execute shell command error, ip: {}, port: {}, shell: {}\", ip, port, shell);\n            logger.error(e.getMessage(), e);\n        }\n        return success;\n    }\n    \n    /**\n     * 多次验证是否进程已经启动\n     * @param ip\n     * @param port\n     * @return\n     */\n    private boolean isPortUsed(final String ip, final int port) {\n        boolean isPortUsed = new IdempotentConfirmer() {\n            private int sleepTime = 100;\n            \n            @Override\n            public boolean execute() {\n                try {\n                    boolean success = SSHUtil.isPortUsed(ip, port);\n                    if (!success) {\n                        TimeUnit.MILLISECONDS.sleep(sleepTime);\n                        sleepTime += 100;\n                    }\n                    return success;\n                } catch (SSHException e) {\n                    logger.error(e.getMessage(), e);\n                    return false;\n                } catch (InterruptedException e) {\n                    logger.error(e.getMessage(), e);\n                    return false;\n                }\n            }\n        }.run();\n        return isPortUsed;\n    }\n\n    /**\n     * 执行shell命令，并将结果返回；\n     *\n     * @param ip    机器ip\n     * @param shell shell命令\n     * @return 命令的返回值\n     */\n    @Override\n    public String executeShell(final String ip, final String shell) {\n        checkArgument(!Strings.isNullOrEmpty(ip), \"invalid ip.\");\n        checkArgument(!Strings.isNullOrEmpty(shell), \"invalid shell.\");\n\n        String result = null;\n        try {\n            result = SSHUtil.execute(ip, shell);\n        } catch (SSHException e) {\n            logger.error(\"execute shell: {} at ip: {} error.\", shell, ip, e);\n            result = ConstUtils.INNER_ERROR;\n        }\n\n        return result;\n    }\n\n    /**\n     * 获取指定server上的一个可用的端口；type表示cache的类型；\n     * PortGenerator是线程安全的；\n     *\n     * @param ip   目标server；\n     * @param type cache类型\n     * @return 可用端口，如果为null，则表示发生异常；\n     */\n    @Override\n    public Integer getAvailablePort(final String ip, final int type) {\n\n        Integer availablePort = PortGenerator.getRedisPort(ip);\n        // 去实例表中再check一下，该端口是否从来没被使用过\n        while (instanceDao.getCountByIpAndPort(ip, availablePort) > 0) {\n            availablePort++;\n        }\n        return availablePort;\n    }\n\n    /**\n     * 根据content的配置内容创建配置文件，并推送到目标server的约定目录下；\n     * 文件内容有更新，会覆写；\n     *\n     * @param host     要推送到的目标server；\n     * @param fileName 配置文件名\n     * @param content  配置文件的内容\n     * @return 配置文件在远程server上的绝对路径，如果为null则表示失败；\n     */\n    @Override\n    public String createRemoteFile(final String host, String fileName, List<String> content) {\n        checkArgument(!Strings.isNullOrEmpty(host), \"invalid host.\");\n        checkArgument(!Strings.isNullOrEmpty(fileName), \"invalid fileName.\");\n        checkArgument(content != null && content.size() > 0, \"content is empty.\");\n\n        String localAbsolutePath = MachineProtocol.TMP_DIR + fileName;\n        File tmpDir = new File(MachineProtocol.TMP_DIR);\n        if (!tmpDir.exists()) {\n            if (!tmpDir.mkdirs()) {\n                logger.error(\"cannot create /tmp/cachecloud directory.\");\n                return null;\n            }\n        }\n\n        Path path = Paths.get(MachineProtocol.TMP_DIR + fileName);\n        String remotePath = MachineProtocol.CONF_DIR + fileName;\n        /**\n         * 将配置文件的内容写到本地\n         */\n        try {\n            BufferedWriter bufferedWriter = Files.newBufferedWriter(path, Charset.forName(MachineProtocol.ENCODING_UTF8));\n            try {\n                for (String line : content) {\n                    bufferedWriter.write(line);\n                    bufferedWriter.newLine();\n                }\n            } finally {\n                if(bufferedWriter != null)\n                    bufferedWriter.close();\n            }\n        } catch (IOException e) {\n            logger.error(\"write redis config file error, ip: {}, filename: {}, content: {}, e\", host, fileName, content, e);\n            return null;\n        }finally {\n\n        }\n\n        /**\n         * 将配置文件推送到目标机器上\n         */\n        try {\n            SSHUtil.scpFileToRemote(host, localAbsolutePath, MachineProtocol.CONF_DIR);\n        } catch (SSHException e) {\n            logger.error(\"scp config file to remote server error: ip: {}, fileName: {}\", host, fileName, e);\n            return null;\n        }\n\n        /**\n         * 删除临时文件\n         */\n        File file = new File(localAbsolutePath);\n        if (file.exists()) {\n            file.delete();\n        }\n\n        return remotePath;\n    }\n\n    @Override\n    public List<MachineStats> getMachineStats(String ipLike) {\n        List<MachineInfo> machineInfoList = machineDao.getMachineInfoByLikeIp(ipLike);\n        List<MachineStats> machineStatsList = new ArrayList<MachineStats>();\n        for (MachineInfo machineInfo : machineInfoList) {\n            String ip = machineInfo.getIp();\n            MachineStats machineStats = machineStatsDao.getMachineStatsByIp(ip);\n            if (machineStats == null) {\n                machineStats = new MachineStats();\n            }\n            machineStats.setMemoryAllocated(instanceDao.getMemoryByHost(ip));\n            machineStats.setInfo(machineInfo);\n            machineStatsList.add(machineStats);\n        }\n        return machineStatsList;\n    }\n\n    @Override\n    public List<MachineStats> getAllMachineStats() {\n        List<MachineStats> list = machineStatsDao.getAllMachineStats();\n        for (MachineStats ms : list) {\n            String ip = ms.getIp();\n            MachineInfo machineInfo = machineDao.getMachineInfoByIp(ip);\n            if (machineInfo == null || machineInfo.isOffline()) {\n                continue;\n            }\n            \n            int memoryHost = instanceDao.getMemoryByHost(ip);\n            getMachineMemoryDetail(ms.getIp());\n\n            //获取机器申请和使用内存\n            long applyMem = 0;\n            long usedMem = 0;\n            List<InstanceStats> instanceStats = instanceStatsDao.getInstanceStatsByIp(ip);\n            for (InstanceStats instance : instanceStats) {\n                applyMem += instance.getMaxMemory();\n                usedMem += instance.getUsedMemory();\n            }\n            MachineMemInfo machineMemInfo = new MachineMemInfo();\n            machineMemInfo.setIp(ip);\n            machineMemInfo.setApplyMem(applyMem);\n            machineMemInfo.setUsedMem(usedMem);\n            ms.setMachineMemInfo(machineMemInfo);\n            \n\n            ms.setMemoryAllocated(memoryHost);\n            ms.setInfo(machineInfo);\n        }\n        return list;\n    }\n\n    @Override\n    public MachineInfo getMachineInfoByIp(String ip) {\n        return machineDao.getMachineInfoByIp(ip);\n    }\n\n    \n    @Override\n    public MachineStats getMachineMemoryDetail(String ip) {\n        long applyMem = 0;\n        long usedMem = 0;\n        List<InstanceStats> instanceStats = instanceStatsDao.getInstanceStatsByIp(ip);\n        for (InstanceStats instance : instanceStats) {\n            applyMem += instance.getMaxMemory();\n            usedMem += instance.getUsedMemory();\n        }\n\n        MachineStats machineStats = machineStatsDao.getMachineStatsByIp(ip);\n        machineStats.setInfo(machineDao.getMachineInfoByIp(ip));\n        MachineMemInfo machineMemInfo = new MachineMemInfo();\n        machineMemInfo.setIp(ip);\n        machineMemInfo.setApplyMem(applyMem);\n        machineMemInfo.setUsedMem(usedMem);\n        machineStats.setMachineMemInfo(machineMemInfo);\n        \n        int memoryHost = instanceDao.getMemoryByHost(ip);\n        machineStats.setMemoryAllocated(memoryHost);\n        \n        return machineStats;\n    }\n    \n    public List<InstanceStats> getMachineInstanceStatsByIp(String ip) {\n        return instanceStatsDao.getInstanceStatsByIp(ip);\n    }\n    \n    @Override\n    public List<InstanceInfo> getMachineInstanceInfo(String ip) {\n        List<InstanceInfo> resultList = instanceDao.getInstListByIp(ip);\n        if (resultList == null || resultList.isEmpty()) {\n            return resultList;\n        }\n        if (resultList != null && resultList.size() > 0) {\n            for (InstanceInfo instanceInfo : resultList) {\n                int type = instanceInfo.getType();\n                if(instanceInfo.getStatus() != InstanceStatusEnum.GOOD_STATUS.getStatus()){\n                    continue;\n                }\n                if (TypeUtil.isRedisType(type)) {\n                    if (TypeUtil.isRedisSentinel(type)) {\n                        continue;\n                    }\n                    String host = instanceInfo.getIp();\n                    int port = instanceInfo.getPort();\n                    long appId = instanceInfo.getAppId();\n                    AppDesc appDesc = appDao.getAppDescById(appId);\n                    String password = appDesc.getPassword();\n                    Boolean isMaster = redisCenter.isMaster(appId, host, port);\n                    instanceInfo.setRoleDesc(isMaster);\n                    if(isMaster != null && !isMaster){\n                        HostAndPort hap = redisCenter.getMaster(host, port, password);\n                        if (hap != null) {\n                            instanceInfo.setMasterHost(hap.getHost());\n                            instanceInfo.setMasterPort(hap.getPort());\n                            for (InstanceInfo innerInfo : resultList) {\n                                if (innerInfo.getIp().equals(hap.getHost())\n                                        && innerInfo.getPort() == hap.getPort()) {\n                                    instanceInfo.setMasterInstanceId(innerInfo.getId());\n                                    break;\n                                }\n                            }\n                        }\n                    }\n\n                }\n            }\n        }\n        return resultList;\n    }\n    \n    @Override\n    public String showInstanceRecentLog(InstanceInfo instanceInfo, int maxLineNum) {\n        String host = instanceInfo.getIp();\n        int port = instanceInfo.getPort();\n        int type = instanceInfo.getType();\n        String logType = \"\";\n        if (TypeUtil.isRedisDataType(type)) {\n            logType = \"redis-\";\n        } else if (TypeUtil.isRedisSentinel(type)) {\n            logType = \"redis-sentinel-\";\n        }\n\n        String remoteFilePath = MachineProtocol.LOG_DIR + logType + port + \"-*.log\";\n        StringBuilder command = new StringBuilder();\n        command.append(\"/usr/bin/tail -n\").append(maxLineNum).append(\" \").append(remoteFilePath);\n        try {\n            return SSHUtil.execute(host, command.toString());\n        } catch (SSHException e) {\n            logger.error(e.getMessage(), e);\n            return \"\";\n        }\n    }\n    \n    @Override\n    public List<MachineInfo> getMachineInfoByType(TypeEnum typeEnum) {\n        try {\n            return machineDao.getMachineInfoByType(typeEnum.getType());\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return Collections.emptyList();\n        }\n    }\n\n    public void setRedisCenter(RedisCenter redisCenter) {\n        this.redisCenter = redisCenter;\n    }\n\n    public void setSchedulerCenter(SchedulerCenter schedulerCenter) {\n        this.schedulerCenter = schedulerCenter;\n    }\n\n    public void setMachineStatsDao(MachineStatsDao machineStatsDao) {\n        this.machineStatsDao = machineStatsDao;\n    }\n\n    public void setInstanceDao(InstanceDao instanceDao) {\n        this.instanceDao = instanceDao;\n    }\n\n    public void setMachineDao(MachineDao machineDao) {\n        this.machineDao = machineDao;\n    }\n\n    public void setInstanceStatsDao(InstanceStatsDao instanceStatsDao) {\n        this.instanceStatsDao = instanceStatsDao;\n    }\n    \n    public void setEmailComponent(EmailComponent emailComponent) {\n        this.emailComponent = emailComponent;\n    }\n\n    public void setMobileAlertComponent(MobileAlertComponent mobileAlertComponent) {\n        this.mobileAlertComponent = mobileAlertComponent;\n    }\n\n    public void setInstanceStatsCenter(InstanceStatsCenter instanceStatsCenter) {\n        this.instanceStatsCenter = instanceStatsCenter;\n    }\n\n\t@Override\n\tpublic boolean deployServerCollection(long hostId, String ip) {\n        Assert.hasText(ip);\n        Map<String, Object> dataMap = new HashMap<String, Object>();\n        dataMap.put(ConstUtils.HOST_KEY, ip);\n        JobKey jobKey = JobKey.jobKey(ConstUtils.SERVER_JOB_NAME, ConstUtils.SERVER_JOB_GROUP);\n        TriggerKey triggerKey = TriggerKey.triggerKey(ip, ConstUtils.SERVER_TRIGGER_GROUP + ip);\n        boolean result = schedulerCenter.deployJobByCron(jobKey, triggerKey, dataMap, ScheduleUtil.getFiveMinuteCronByHostId(hostId), false);\n\n        return result;\n\t}\n\n\t@Override\n\tpublic boolean unDeployServerCollection(long hostId, String ip) {\n        Assert.hasText(ip);\n        TriggerKey collectionTriggerKey = TriggerKey.triggerKey(ip, ConstUtils.SERVER_TRIGGER_GROUP + ip);\n        Trigger trigger = schedulerCenter.getTrigger(collectionTriggerKey);\n        if (trigger == null) {\n            return true;\n        }\n        return schedulerCenter.unscheduleJob(collectionTriggerKey);\n\t}\n\t\n\t@Override\n    public Map<String, Integer> getMachineInstanceCountMap() {\n\t    List<Map<String,Object>> mapList = instanceDao.getMachineInstanceCountMap();\n\t    if (CollectionUtils.isEmpty(mapList)) {\n\t        return Collections.emptyMap();\n\t    }\n\t    \n\t    Map<String, Integer> resultMap = new HashMap<String, Integer>();\n\t    for(Map<String,Object> map : mapList) {\n\t        String ip = MapUtils.getString(map, \"ip\", \"\");\n\t        if (StringUtils.isBlank(ip)) {\n\t            continue;\n\t        }\n\t        int count = MapUtils.getIntValue(map, \"count\");\n\t        resultMap.put(ip, count);\n\t    }\n        return resultMap;\n    }\n\n\tpublic void setAsyncService(AsyncService asyncService) {\n\t\tthis.asyncService = asyncService;\n\t}\n\n\tpublic void setAppDao(AppDao appDao) {\n\t\tthis.appDao = appDao;\n\t}\n    \n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/machine/impl/MachineDeployCenterImpl.java",
    "content": "package com.sohu.cache.machine.impl;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.google.common.base.Strings;\nimport com.sohu.cache.dao.MachineDao;\nimport com.sohu.cache.dao.MachineStatsDao;\nimport com.sohu.cache.dao.ServerStatusDao;\nimport com.sohu.cache.entity.MachineInfo;\nimport com.sohu.cache.machine.MachineCenter;\nimport com.sohu.cache.machine.MachineDeployCenter;\n\n/**\n * 机器部署相关\n * @author leifu\n * changed @Date 2016-4-24\n * @Time 下午5:07:30\n */\npublic class MachineDeployCenterImpl implements MachineDeployCenter {\n    private Logger logger = LoggerFactory.getLogger(MachineDeployCenterImpl.class);\n\n    private MachineDao machineDao;\n\n    private MachineCenter machineCenter;\n\n    private MachineStatsDao machineStatsDao;\n    \n    private ServerStatusDao serverStatusDao;\n\n    /**\n     * 将机器加入资源池并统计、监控\n     *\n     * @param machineInfo\n     * @return\n     */\n    @Override\n    public boolean addMachine(MachineInfo machineInfo) {\n        boolean success = true;\n\n        if (machineInfo == null || Strings.isNullOrEmpty(machineInfo.getIp())) {\n            logger.error(\"machineInfo is null or ip is valid.\");\n            return false;\n        }\n        // 将机器信息保存到db中\n        try {\n            machineDao.saveMachineInfo(machineInfo);\n        } catch (Exception e) {\n            logger.error(\"save machineInfo: {} to db error.\", machineInfo.toString(), e);\n            return false;\n        }\n\n        // 为机器添加统计和监控的定时任务\n        try {\n            MachineInfo thisMachine = machineDao.getMachineInfoByIp(machineInfo.getIp());\n            if (thisMachine != null) {\n                long hostId = thisMachine.getId();\n                String ip = thisMachine.getIp();\n                if (!machineCenter.deployMachineCollection(hostId, ip)) {\n                    logger.error(\"deploy machine collection error, machineInfo: {}\", thisMachine.toString());\n                    success = false;\n                }\n                if (!machineCenter.deployMachineMonitor(hostId, ip)) {\n                    logger.error(\"deploy machine monitor error, machineInfo: {}\", thisMachine.toString());\n                    success = false;\n                }\n                if(thisMachine.getCollect() == 1) {\n                \tif (!machineCenter.deployServerCollection(hostId, ip)) {\n                \t\tlogger.error(\"deploy server monitor error, machineInfo: {}\", thisMachine.toString());\n                \t\tsuccess = false;\n                \t}\n                } else {\n                \tif (!machineCenter.unDeployServerCollection(hostId, ip)) {\n                \t\tlogger.error(\"undeploy server monitor error, machineInfo: {}\", thisMachine.toString());\n                \t\tsuccess = false;\n                \t}\n                }\n            }\n        } catch (Exception e) {\n            logger.error(\"query machineInfo from db error, ip: {}\", machineInfo.getIp(), e);\n        }\n\n        if (success) {\n            logger.info(\"save and deploy machine ok, machineInfo: {}\", machineInfo.toString());\n        }\n        return success;\n    }\n\n    /**\n     * 删除机器，并删除相关的定时任务\n     *\n     * @param machineInfo\n     * @return\n     */\n    @Override\n    public boolean removeMachine(MachineInfo machineInfo) {\n        if (machineInfo == null || Strings.isNullOrEmpty(machineInfo.getIp())) {\n            logger.warn(\"machineInfo is null or ip is empty.\");\n            return false;\n        }\n        String machineIp = machineInfo.getIp();\n        \n        //从quartz中删除相关的定时任务\n        try {\n            MachineInfo thisMachine = machineDao.getMachineInfoByIp(machineIp);\n            long hostId = thisMachine.getId();\n            \n            if (!machineCenter.unDeployMachineCollection(hostId, machineIp)) {\n                logger.error(\"remove trigger for machine error: {}\", thisMachine.toString());\n                return false;\n            }\n            if (!machineCenter.unDeployMachineMonitor(hostId, machineIp)) {\n                logger.error(\"remove trigger for machine monitor error: {}\", thisMachine.toString());\n                return false;\n            }\n            if (!machineCenter.unDeployServerCollection(hostId, machineIp)) {\n                logger.error(\"remove trigger for server monitor error: {}\", thisMachine.toString());\n                return false;\n            }\n        } catch (Exception e) {\n            logger.error(\"query machineInfo from db error: {}\", machineInfo.toString());\n        }\n        \n        // 从db中删除machine和相关统计信息\n        try {\n            machineDao.removeMachineInfoByIp(machineIp);\n            machineStatsDao.deleteMachineStatsByIp(machineIp);\n            serverStatusDao.deleteServerInfo(machineIp);\n        } catch (Exception e) {\n            logger.error(\"remove machineInfo from db error, machineInfo: {}\", machineInfo.toString(), e);\n            return false;\n        }\n        logger.info(\"remove and undeploy machine ok: {}\", machineInfo.toString());\n        return true;\n    }\n\n\n    public void setMachineDao(MachineDao machineDao) {\n        this.machineDao = machineDao;\n    }\n\n    public void setMachineCenter(MachineCenter machineCenter) {\n        this.machineCenter = machineCenter;\n    }\n\n    public void setMachineStatsDao(MachineStatsDao machineStatsDao) {\n        this.machineStatsDao = machineStatsDao;\n    }\n\n\tpublic void setServerStatusDao(ServerStatusDao serverStatusDao) {\n\t\tthis.serverStatusDao = serverStatusDao;\n\t}\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/protocol/MachineProtocol.java",
    "content": "package com.sohu.cache.protocol;\n\nimport com.sohu.cache.util.ConstUtils;\n\n/**\n * 机器相关的一些常量\n *\n * @author: lingguo\n * @time: 2014/8/26 16:18\n */\npublic class MachineProtocol {\n    \n    /**\n     * 统一的目录结构\n     */\n    public static final String CONF_DIR = ConstUtils.CACHECLOUD_BASE_DIR + \"/cachecloud/conf/\";\n    public static final String DATA_DIR = ConstUtils.CACHECLOUD_BASE_DIR + \"/cachecloud/data\";\n    public static final String LOG_DIR = ConstUtils.CACHECLOUD_BASE_DIR + \"/cachecloud/logs/\";\n\n    /**\n     * 配置文件的临时目录；\n     */\n    public static final String TMP_DIR = \"/tmp/cachecloud/\";\n\n    /**\n     * 编码\n     */\n    public static final String ENCODING_UTF8 = \"UTF-8\";\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/protocol/RedisProtocol.java",
    "content": "package com.sohu.cache.protocol;\n\nimport com.sohu.cache.web.util.DateUtil;\n\nimport java.util.Date;\n\nimport org.apache.commons.lang.StringUtils;\n\n/**\n * Created by yijunzhang on 14-11-26.\n */\npublic class RedisProtocol {\n\n    private static final String RUN_SHELL = \"redis-server %s > \" + MachineProtocol.LOG_DIR + \"redis-%d-%s.log 2>&1 &\";\n\n    private static final String SENTINEL_SHELL = \"redis-server %s --sentinel > \" + MachineProtocol.LOG_DIR + \"redis-sentinel-%d-%s.log 2>&1 &\";\n\n    private static final String CLUSTER_CONFIG = \"redis-cluster-%d.conf\";\n\n    private static final String COMMON_CONFIG = \"redis-sentinel-%d.conf\";\n\n    public static String getRunShell(int port, boolean isCluster) {\n        return String.format(RUN_SHELL, MachineProtocol.CONF_DIR + getConfig(port, isCluster), port, DateUtil.formatYYYYMMddHHMM(new Date()));\n    }\n\n    public static String getSentinelShell(int port) {\n        return String.format(SENTINEL_SHELL, MachineProtocol.CONF_DIR + getConfig(port, false), port, DateUtil.formatYYYYMMddHHMM(new Date()));\n    }\n\n    public static String getExecuteCommandShell(String host, int port, String password, String command) {\n    \t\tStringBuffer shell = new StringBuffer();\n    \t\tshell.append(String.format(\"redis-cli -h %s -p %s\", host, port));\n    \t\tif (StringUtils.isNotBlank(password)) {\n    \t\t\tshell.append(String.format(\" -a %s\", password));\n    \t\t}\n    \t\tshell.append(String.format(\" --raw %s\", command));\n    \t\treturn shell.toString();\n    }\n\n    public static String getConfig(int port, boolean isCluster) {\n        if (isCluster) {\n            return String.format(CLUSTER_CONFIG, port);\n        } else {\n            return String.format(COMMON_CONFIG, port);\n        }\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/redis/RedisCenter.java",
    "content": "package com.sohu.cache.redis;\n\nimport com.sohu.cache.constant.RedisConstant;\nimport com.sohu.cache.entity.AppDesc;\nimport com.sohu.cache.entity.AppUser;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.entity.InstanceSlotModel;\nimport com.sohu.cache.entity.InstanceSlowLog;\nimport com.sohu.cache.web.vo.RedisSlowLog;\n\nimport redis.clients.jedis.HostAndPort;\nimport redis.clients.jedis.Jedis;\nimport redis.clients.jedis.JedisSentinelPool;\n\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * redis相关操作接口\n * Created by yijunzhang on 14-6-10.\n */\npublic interface RedisCenter {\n\n    /**\n     * 部署redis数据收集任务(幂等操作)\n     *\n     * @param appId\n     * @param host\n     * @param port\n     * @return\n     */\n    public boolean deployRedisCollection(long appId, String host, int port);\n\n    /**\n     * 取消部署redis收集任务\n     *\n     * @param appId\n     * @param host\n     * @param port\n     * @return\n     */\n    public boolean unDeployRedisCollection(long appId, String host, int port);\n    \n    /**\n     * 部署redis收集慢查询日志\n     *\n     * @param appId\n     * @param host\n     * @param port\n     * @return\n     */\n    public boolean deployRedisSlowLogCollection(long appId, String host, int port);\n\n    /**\n     * 取消部署redis收集慢查询日志\n     *\n     * @param appId\n     * @param host\n     * @param port\n     * @return\n     */\n    public boolean unDeployRedisSlowLogCollection(long appId, String host, int port);\n\n    /**\n     * 收集redis统计信息\n     *\n     * @param appId\n     * @param host\n     * @param port\n     * @return\n     */\n    public Map<RedisConstant, Map<String, Object>> collectRedisInfo(long appId, long collectTime, String host,\n            int port);\n\n    /**\n     * 收集redis统计信息\n     *\n     * @param host\n     * @param port\n     * @return\n     */\n    public Map<RedisConstant, Map<String, Object>> getInfoStats(long appId, String host, int port);\n    \n    /**\n     * 节点cluster info信息\n     * @param appId\n     * @param host\n     * @param port\n     * @return\n     */\n    public Map<String, Object> getClusterInfoStats(long appId, String host, int port);\n    \n    /**\n     * 节点cluster info信息\n     * @param appId\n     * @param instanceInfo\n     * @return\n     */\n    public Map<String, Object> getClusterInfoStats(long appId, InstanceInfo instanceInfo);\n\n    /**\n     * 根据ip和port判断redis实例当前是主还是从\n     *\n     * @param ip   ip\n     * @param port port\n     * @return 主返回true，从返回false；\n     */\n    public Boolean isMaster(long appId, String ip, int port);\n    \n    /**\n     * 根据ip和port判断redis实例当前是否有从节点\n     * @param ip   ip\n     * @param port port\n     * @return 主返回true，从返回false；\n     */\n    public Boolean hasSlaves(long appId, String ip, int port);\n\n    /**\n     * 获取从节点的主节点地址\n     *\n     * @param ip\n     * @param port\n     * @param password\n     * @return\n     */\n    public HostAndPort getMaster(String ip, int port, String password);\n\n    /**\n     * 判断实例是否运行\n     *\n     * @param appId\n     * @param ip\n     * @param port\n     * @return\n     */\n    public boolean isRun(final long appId, String ip, int port);\n    \n    \n    /**\n     * 判断实例是否运行\n     *\n     * @param ip\n     * @param port\n     * @return\n     */\n\tpublic boolean isRun(String ip, int port);\n    \n    /**\n     * 判断实例是否运行\n     *\n     * @param ip\n     * @param port\n     * @param password\n     * @return\n     */\n\tpublic boolean isRun(String ip, int port, String redisPassword);\n\n\t/**\n     * 下线指定实例\n     *\n     * @param appId\n     * @param ip\n     * @param port\n     * @return\n     */\n    public boolean shutdown(String ip, int port);\n\t\n\t\n    /**\n     * 下线指定实例\n     *\n     * @param appId\n     * @param ip\n     * @param port\n     * @return\n     */\n    public boolean shutdown(long appId, String ip, int port);\n\n    /**\n     * 执行redis命令返回结果\n     *\n     * @param appDesc\n     * @param command\n     * @return\n     */\n    public String executeCommand(AppDesc appDesc, String command);\n\n    /**\n     * 实例执行redis命令\n     *\n     * @param appId\n     * @param host\n     * @param port\n     * @param command\n     * @return\n     */\n    public String executeCommand(long appId, String host, int port, String command);\n\n    /**\n     * 获取jedisSentinelPool实例,必须是sentinel类型应用\n     *\n     * @param appDesc\n     * @return\n     */\n    public JedisSentinelPool getJedisSentinelPool(AppDesc appDesc);\n\n    /**\n     * 获取redis实例配置信息\n     *\n     * @param instanceId\n     * @return\n     */\n    public Map<String, String> getRedisConfigList(int instanceId);\n\n    /**\n     * 获取redis实例慢查询\n     *\n     * @param instanceId\n     * @return\n     */\n    public List<RedisSlowLog> getRedisSlowLogs(int instanceId, int maxCount);\n\n    /**\n     * 获取client连接信息\n     *\n     * @param instanceId\n     * @return\n     */\n    public List<String> getClientList(int instanceId);\n\n    /**\n     * 配置重写\n     *\n     * @return\n     */\n    public boolean configRewrite(final long appId, final String host, final int port);\n\n    /**\n     * 获取maxmemory配置\n     *\n     * @param appId\n     * @param host\n     * @param port\n     * @return\n     */\n    public Long getRedisMaxMemory(long appId, String host, int port);\n\n    /**\n     * 清理app数据\n     *\n     * @param appDesc\n     * @param appUser\n     * @return\n     */\n    public boolean cleanAppData(AppDesc appDesc, AppUser appUser);\n\n    /**\n     * 判断是否为孤立节点\n     * @param appId\n     * @param host\n     * @param port\n     * @return\n     */\n    public boolean isSingleClusterNode(long appId, String host, int port);\n\n    \n    /**\n     * 获取集群中失联的slots\n     * @param appId\n     * @return\n     */\n    public Map<String,String> getClusterLossSlots(long appId);\n    \n    /**\n     * 获取集群中失联的slots\n     * @param appId\n     * @param host\n     * @param port\n     * @return\n     */\n    public List<Integer> getClusterLossSlots(long appId, String host, int port);\n\n    /**\n     * 获取集群中失联的slots\n     * @param appId\n     * @param healthyHost\n     * @param healthyPort\n     * @param lossSlotsHost\n     * @param lossSlotsPort\n     * @return\n     */\n    public List<Integer> getInstanceSlots(long appId, String healthyHost, int healthyPort, String lossSlotsHost, int lossSlotsPort);\n\n    /**\n     * 从一个应用中获取一个健康的实例\n     * @param appId\n     * @return\n     */\n    public InstanceInfo getHealthyInstanceInfo(long appId);\n\n    /**\n     * 从一个应用中获取所有健康的master实例\n     * @param appId\n     * @return\n     */\n    public List<InstanceInfo> getAllHealthyInstanceInfo(long appId);\n\n    /**\n     * 收集redis慢查询日志\n     *\n     * @param appId\n     * @param host\n     * @param port\n     * @return\n     */\n    public List<InstanceSlowLog> collectRedisSlowLog(long appId, long collectTime, String host,\n            int port);\n    \n    /**\n     * 按照appid获取慢查询日志\n     * @param appId\n     * @return\n     */\n    public List<InstanceSlowLog> getInstanceSlowLogByAppId(long appId);\n\n    /**\n     * 按照appid获取慢查询日志\n     * @param appId\n     * @param startDate\n     * @param endDate\n     * @return\n     */\n    public List<InstanceSlowLog> getInstanceSlowLogByAppId(long appId, Date startDate, Date endDate);\n\n    /**\n     * 按照appid获取慢查询日志数关系\n     * @param appId\n     * @param startDate\n     * @param endDate\n     * @return\n     */\n    public Map<String, Long> getInstanceSlowLogCountMapByAppId(Long appId, Date startDate, Date endDate);\n    \n    /**\n     * 获取集群的slots分布\n     * @param appId\n     * @return\n     */\n    Map<String, InstanceSlotModel> getClusterSlotsMap(long appId);\n\n    /**\n     * 获取Redis版本\n     * @param appId\n     * @param ip\n     * @param port\n     * @return\n     */\n    public String getRedisVersion(long appId, String ip, int port);\n    \n    \n    /**\n     * 获取nodeId\n     * @param appId\n     * @param ip\n     * @param port\n     * @return\n     */\n    public String getNodeId(long appId, String ip, int port);\n    \n    Jedis getJedis(String host, int port, String password);\n    \n    Jedis getJedis(String host, int port);\n\t\n\tJedis getJedis(long appId, String host, int port);\n\n\tJedis getJedis(long appId, String host, int port, int connectionTimeout, int soTimeout);\n\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/redis/RedisClusterNode.java",
    "content": "package com.sohu.cache.redis;\n\n/**\n * Created by yijunzhang on 14-8-25.\n */\npublic class RedisClusterNode {\n\n    /**\n     * 主节点地址\n     */\n    private String masterHost;\n\n    /**\n     * 从节点地址\n     */\n    private String slaveHost;\n\n    public String getMasterHost() {\n        return masterHost;\n    }\n\n    public void setMasterHost(String masterHost) {\n        this.masterHost = masterHost;\n    }\n\n    public String getSlaveHost() {\n        return slaveHost;\n    }\n\n    public void setSlaveHost(String slaveHost) {\n        this.slaveHost = slaveHost;\n    }\n\n    public RedisClusterNode(String masterHost, String slaveHost) {\n        this.masterHost = masterHost;\n        this.slaveHost = slaveHost;\n    }\n\n    public RedisClusterNode() {\n    }\n\n    @Override\n    public String toString() {\n        return \"RedisClusterNode{\" +\n                \"masterHost='\" + masterHost + '\\'' +\n                \", slaveHost='\" + slaveHost + '\\'' +\n                '}';\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/redis/RedisClusterReshard.java",
    "content": "package com.sohu.cache.redis;\n\nimport com.sohu.cache.constant.ReshardStatusEnum;\nimport com.sohu.cache.dao.InstanceReshardProcessDao;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.entity.InstanceReshardProcess;\nimport com.sohu.cache.util.IdempotentConfirmer;\nimport org.apache.commons.lang.StringUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport redis.clients.jedis.*;\nimport redis.clients.jedis.exceptions.JedisException;\n\nimport java.util.*;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * 水平扩容重构\n * @author leifu\n * @Date 2016年12月7日\n * @Time 上午10:13:00\n */\npublic class RedisClusterReshard {\n    private final Logger logger = LoggerFactory.getLogger(this.getClass());\n\n    /**\n     * migrate超时时间\n     */\n    private int migrateTimeout = 10000;\n\n    /**\n     * 普通jedis操作超时时间\n     */\n    private int defaultTimeout = Protocol.DEFAULT_TIMEOUT * 5;\n\n    /**\n     * 每次迁移key个数\n     */\n    private int migrateBatch = 10;\n\n    /**\n     * 所有有效节点\n     */\n    private Set<HostAndPort> hosts;\n    \n    /**\n     * redis操作封装\n     */\n    private RedisCenter redisCenter;\n    \n    private InstanceReshardProcessDao instanceReshardProcessDao;\n    \n    \n    public RedisClusterReshard(Set<HostAndPort> hosts, RedisCenter redisCenter, InstanceReshardProcessDao instanceReshardProcessDao) {\n        this.hosts = hosts;\n        this.redisCenter = redisCenter;\n        this.instanceReshardProcessDao = instanceReshardProcessDao;\n    }\n\n    /**\n     * 加入主从分片\n     */\n    public boolean joinCluster(long appId, String masterHost, int masterPort, final String slaveHost, final int slavePort) {\n        //1. 确认主从节点是否正常\n        final Jedis masterJedis = redisCenter.getJedis(appId, masterHost, masterPort, defaultTimeout, defaultTimeout);\n        boolean isRun = redisCenter.isRun(appId, masterHost, masterPort);\n        if (!isRun) {\n            logger.error(String.format(\"joinCluster: master host=%s,port=%s is not run\", masterHost, masterPort));\n            return false;\n        }\n        boolean hasSlave = StringUtils.isNotBlank(slaveHost) && slavePort > 0;\n        final Jedis slaveJedis = hasSlave ? redisCenter.getJedis(appId, slaveHost, slavePort, defaultTimeout, defaultTimeout) : null;\n        if (hasSlave) {\n            isRun = redisCenter.isRun(appId, slaveHost, slavePort);\n            if (!isRun) {\n                logger.error(String.format(\"joinCluster: slave host=%s,port=%s is not run\", slaveHost, slavePort));\n                return false;\n            }\n        }\n\n        //2. 对主从节点进行meet操作\n        //获取所有主节点 \n        List<HostAndPort> masterHostAndPostList = getMasterNodeList(appId);\n        //meet master\n        boolean isClusterMeet = clusterMeet(appId, masterHostAndPostList, masterHost, masterPort);\n        if (!isClusterMeet) {\n            logger.error(\"master isClusterMeet failed {}:{}\", masterHost, masterPort);\n            return false;\n        }\n        if (hasSlave) {\n            isClusterMeet = clusterMeet(appId, masterHostAndPostList, slaveHost, slavePort);\n            if (!isClusterMeet) {\n                logger.error(\"slave isClusterMeet failed {}:{}\", slaveHost, slavePort);\n                return false;\n            }\n        }\n        \n        //3.复制\n        if (hasSlave) {\n            final String masterNodeId = getNodeId(appId, masterJedis);\n            if (masterNodeId == null) {\n                logger.error(String.format(\"joinCluster:host=%s,port=%s nodeId is null\", masterHost, masterPort));\n                return false;\n            }\n            return new IdempotentConfirmer() {\n                @Override\n                public boolean execute() {\n                    try {\n                        //等待广播节点\n                        TimeUnit.SECONDS.sleep(2);\n                    } catch (Exception e) {\n                        logger.error(e.getMessage(), e);\n                    }\n                    String response = slaveJedis.clusterReplicate(masterNodeId);\n                    logger.info(\"clusterReplicate-{}:{}={}\", slaveHost, slavePort, response);\n                    return response != null && response.equalsIgnoreCase(\"OK\");\n                }\n            }.run();\n        } else {\n            return true;\n        }\n    }\n\n    /**\n     * 节点meet\n     * @param masterHostAndPostList\n     * @param host\n     * @param port\n     * @return\n     */\n    private boolean clusterMeet(long appId, List<HostAndPort> masterHostAndPostList, final String host, final int port) {\n        boolean isSingleNode = redisCenter.isSingleClusterNode(appId, host, port);\n        if (!isSingleNode) {\n            logger.error(\"{}:{} isNotSingleNode\", host, port);\n            return false;\n        } else {\n            logger.warn(\"{}:{} isSingleNode\", host, port);\n        }\n        for (HostAndPort hostAndPort : masterHostAndPostList) {\n            String clusterHost = hostAndPort.getHost();\n            int clusterPort = hostAndPort.getPort();\n            final Jedis jedis = redisCenter.getJedis(appId, clusterHost, clusterPort, defaultTimeout, defaultTimeout);\n            try {\n                boolean isClusterMeet = new IdempotentConfirmer() {\n                    @Override\n                    public boolean execute() {\n                        //将新节点添加到集群当中,成为集群中已知新节点\n                        String meet = jedis.clusterMeet(host, port);\n                        return meet != null && meet.equalsIgnoreCase(\"OK\");\n                    }\n                }.run();\n                if (isClusterMeet) {\n                    return true;\n                }\n            } catch (Exception e) {\n                logger.error(e.getMessage(), e);\n            } finally {\n                if (jedis != null)\n                    jedis.close();\n            }\n        }\n        return false;\n    }\n    \n    /**\n     * 将source中的startSlot到endSlot迁移到target\n     *\n     */\n//    public boolean migrateSlotOld(long appId, long appAuditId, InstanceInfo sourceInstanceInfo, InstanceInfo targetInstanceInfo, int startSlot, int endSlot, PipelineEnum pipelineEnum) {\n//        long startTime = System.currentTimeMillis();\n//        InstanceReshardProcess instanceReshardProcess = saveInstanceReshardProcess(appId, appAuditId, sourceInstanceInfo, targetInstanceInfo, startSlot, endSlot, pipelineEnum);\n//        //源和目标Jedis\n//        Jedis sourceJedis = redisCenter.getJedis(appId, sourceInstanceInfo.getIp(), sourceInstanceInfo.getPort(), defaultTimeout, defaultTimeout);\n//        Jedis targetJedis = redisCenter.getJedis(appId, targetInstanceInfo.getIp(), targetInstanceInfo.getPort(), defaultTimeout, defaultTimeout);\n//        //逐个slot迁移\n//        boolean hasError = false;\n//        for (int slot = startSlot; slot <= endSlot; slot++) {\n//            long slotStartTime = System.currentTimeMillis();\n//            try {\n//                instanceReshardProcessDao.updateMigratingSlot(instanceReshardProcess.getId(), slot);\n//                //num是迁移key的总数\n//                int num = migrateSlotData(appId, sourceJedis, targetJedis, slot, pipelineEnum);\n//                instanceReshardProcessDao.increaseFinishSlotNum(instanceReshardProcess.getId());\n//                logger.warn(\"clusterReshard:{}->{}, slot={}, keys={}, costTime={} ms\", sourceInstanceInfo.getHostPort(),\n//                        targetInstanceInfo.getHostPort(), slot, num, (System.currentTimeMillis() - slotStartTime));\n//            } catch (Exception e) {\n//                logger.error(e.getMessage(), e);\n//                hasError = true;\n//                break;\n//            }\n//        }\n//        long endTime = System.currentTimeMillis();\n//        logger.warn(\"clusterReshard:{}->{}, slot:{}->{}, costTime={} ms\", sourceInstanceInfo.getHostPort(),\n//                targetInstanceInfo.getHostPort(), startSlot, endSlot, (endTime - startTime));\n//        if (hasError) {\n//            instanceReshardProcessDao.updateStatus(instanceReshardProcess.getId(), ReshardStatusEnum.ERROR.getValue());\n//            return false;\n//        } else {\n//            instanceReshardProcessDao.updateStatus(instanceReshardProcess.getId(), ReshardStatusEnum.FINISH.getValue());\n//            instanceReshardProcessDao.updateEndTime(instanceReshardProcess.getId(), new Date());\n//            return true;\n//        }\n//    }\n    \n    /**\n     * 将source中的startSlot到endSlot迁移到target\n     *\n     */\n    public boolean migrateSlot(InstanceReshardProcess instanceReshardProcess) {\n        long appId = instanceReshardProcess.getAppId();\n        int migratingSlot = instanceReshardProcess.getMigratingSlot();\n        int endSlot = instanceReshardProcess.getEndSlot();\n        int isPipeline = instanceReshardProcess.getIsPipeline();\n        InstanceInfo sourceInstanceInfo = instanceReshardProcess.getSourceInstanceInfo();\n        InstanceInfo targetInstanceInfo = instanceReshardProcess.getTargetInstanceInfo();\n        \n        long startTime = System.currentTimeMillis();\n        //源和目标Jedis\n        Jedis sourceJedis = redisCenter.getJedis(appId, sourceInstanceInfo.getIp(), sourceInstanceInfo.getPort(), defaultTimeout, defaultTimeout);\n        Jedis targetJedis = redisCenter.getJedis(appId, targetInstanceInfo.getIp(), targetInstanceInfo.getPort(), defaultTimeout, defaultTimeout);\n        //逐个slot迁移\n        boolean hasError = false;\n        for (int slot = migratingSlot; slot <= endSlot; slot++) {\n            long slotStartTime = System.currentTimeMillis();\n            try {\n                instanceReshardProcessDao.updateMigratingSlot(instanceReshardProcess.getId(), slot);\n                //num是迁移key的总数\n                int num = migrateSlotData(appId, sourceJedis, targetJedis, slot, isPipeline);\n                instanceReshardProcessDao.increaseFinishSlotNum(instanceReshardProcess.getId());\n                logger.warn(\"clusterReshard:{}->{}, slot={}, keys={}, costTime={} ms\", sourceInstanceInfo.getHostPort(),\n                        targetInstanceInfo.getHostPort(), slot, num, (System.currentTimeMillis() - slotStartTime));\n            } catch (Exception e) {\n                logger.error(e.getMessage(), e);\n                hasError = true;\n                break;\n            }\n        }\n        long endTime = System.currentTimeMillis();\n        logger.warn(\"clusterReshard:{}->{}, slot:{}->{}, costTime={} ms\", sourceInstanceInfo.getHostPort(),\n                targetInstanceInfo.getHostPort(), migratingSlot, endSlot, (endTime - startTime));\n        if (hasError) {\n            instanceReshardProcessDao.updateStatus(instanceReshardProcess.getId(), ReshardStatusEnum.ERROR.getValue());\n            return false;\n        } else {\n            instanceReshardProcessDao.updateStatus(instanceReshardProcess.getId(), ReshardStatusEnum.FINISH.getValue());\n            instanceReshardProcessDao.updateEndTime(instanceReshardProcess.getId(), new Date());\n            return true;\n        }\n    }\n\n    /**\n     * 迁移slot数据，并稳定slot配置\n     * @throws Exception\n     */\n    private int moveSlotData(final long appId, final Jedis source, final Jedis target, final int slot, int isPipeline) throws Exception {\n        int num = 0;\n        while (true) {\n            final Set<String> keys = new HashSet<String>();\n            boolean isGetKeysInSlot = new IdempotentConfirmer() {\n                @Override\n                public boolean execute() {\n                    List<String> perKeys = source.clusterGetKeysInSlot(slot, migrateBatch);\n                    if (perKeys != null && perKeys.size() > 0) {\n                        keys.addAll(perKeys);\n                    }\n                    return true;\n                }\n            }.run();\n            if (!isGetKeysInSlot) {\n                throw new RuntimeException(String.format(\"get keys failed slot=%d num=%d\", slot, num));\n            }\n            if (keys.isEmpty()) {\n                break;\n            }\n            for (final String key : keys) {\n                boolean isKeyMigrate = new IdempotentConfirmer() {\n                    // 失败后，迁移时限加倍\n                    private int migrateTimeOutFactor = 1;\n\n                    @Override\n                    public boolean execute() {\n                        String response = source.migrate(target.getClient().getHost(), target.getClient().getPort(),\n                                key, 0, migrateTimeout * (migrateTimeOutFactor++));\n                        return response != null && (response.equalsIgnoreCase(\"OK\") || response.equalsIgnoreCase(\"NOKEY\"));\n                    }\n                }.run();\n                if (!isKeyMigrate) {\n                    throw new RuntimeException(\"migrate key=\" + key + failedInfo(source, slot));\n                } else {\n                    num++;\n                    logger.info(\"migrate key={};response=OK\", key);\n                }\n            }\n        }\n        final String targetNodeId = getNodeId(appId, target);\n        boolean isClusterSetSlotNode;\n        //设置 slot新归属节点\n        isClusterSetSlotNode = new IdempotentConfirmer() {\n            @Override\n            public boolean execute() {\n                boolean isOk = false;\n                List<HostAndPort> masterNodesList = getMasterNodeList(appId);\n                for (HostAndPort hostAndPort : masterNodesList) {\n                    Jedis jedis = null;\n                    try {\n                        jedis = redisCenter.getJedis(appId, hostAndPort.getHost(), hostAndPort.getPort());\n                        String response = jedis.clusterSetSlotNode(slot, targetNodeId);\n                        isOk = response != null && response.equalsIgnoreCase(\"OK\");\n                        if (!isOk) {\n                            logger.error(\"clusterSetSlotNode-{}={}\", getNodeId(appId, target), response);\n                            break;\n                        }\n                    } catch (Exception e) {\n                        logger.error(e.getMessage(), e);\n                    } finally {\n                       if (jedis != null)\n                           jedis.close();\n                    }\n                }\n                return isOk;\n            }\n        }.run();\n        if (!isClusterSetSlotNode) {\n            throw new RuntimeException(\"clusterSetSlotNode:\" + failedInfo(target, slot));\n        }\n        return num;\n    }\n\n    /**\n     * 指派迁移节点数据\n     * CLUSTER SETSLOT <slot> IMPORTING <node_id> 从 node_id 指定的节点中导入槽 slot 到本节点。\n     * CLUSTER SETSLOT <slot> MIGRATING <node_id> 将本节点的槽 slot 迁移到 node_id 指定的节点中。\n     * CLUSTER GETKEYSINSLOT <slot> <count> 返回 count 个 slot 槽中的键。\n     * MIGRATE host port key destination-db timeout [COPY] [REPLACE]\n     * CLUSTER SETSLOT <slot> NODE <node_id> 将槽 slot 指派给 node_id 指定的节点，如果槽已经指派给另一个节点，那么先让另一个节点删除该槽>，然后再进行指派。\n     */\n    private int migrateSlotData(long appId, final Jedis source, final Jedis target, final int slot, int isPipeline) {\n        int num = 0;\n        final String sourceNodeId = getNodeId(appId, source);\n        final String targetNodeId = getNodeId(appId, target);\n        boolean isError = false;\n        if (sourceNodeId == null || targetNodeId == null) {\n            throw new JedisException(String.format(\"sourceNodeId = %s || targetNodeId = %s\", sourceNodeId, targetNodeId));\n        }\n        boolean isImport = new IdempotentConfirmer() {\n            @Override\n            public boolean execute() {\n                String importing = target.clusterSetSlotImporting(slot, sourceNodeId);\n                logger.info(\"slot={},clusterSetSlotImporting={}\", slot, importing);\n                return importing != null && importing.equalsIgnoreCase(\"OK\");\n            }\n        }.run();\n        if (!isImport) {\n            isError = true;\n            logger.error(\"clusterSetSlotImporting\" + failedInfo(target, slot));\n        }\n        boolean isMigrate = new IdempotentConfirmer() {\n            @Override\n            public boolean execute() {\n                String migrating = source.clusterSetSlotMigrating(slot, targetNodeId);\n                logger.info(\"slot={},clusterSetSlotMigrating={}\", slot, migrating);\n                return migrating != null && migrating.equalsIgnoreCase(\"OK\");\n            }\n        }.run();\n\n        if (!isMigrate) {\n            isError = true;\n            logger.error(\"clusterSetSlotMigrating\" + failedInfo(source, slot));\n        }\n\n        try {\n            num = moveSlotData(appId, source, target, slot, isPipeline);\n        } catch (Exception e) {\n            isError = true;\n            logger.error(e.getMessage(), e);\n        }\n        if (!isError) {\n            return num;\n        } else {\n            String errorMessage = \"source=%s target=%s slot=%d num=%d reShard failed\";\n            throw new RuntimeException(String.format(errorMessage, getNodeKey(source), getNodeKey(target), slot, num));\n        }\n    }\n\n    private String failedInfo(Jedis jedis, int slot) {\n        return String.format(\" failed %s:%d slot=%d\", jedis.getClient().getHost(), jedis.getClient().getPort(), slot);\n    }\n    \n    /**\n     * 获取所有主节点\n     * @return\n     */\n    private List<HostAndPort> getMasterNodeList(long appId) {\n        List<HostAndPort> masterNodeList = new ArrayList<HostAndPort>();\n        //获取RedisCluster所有节点\n        JedisCluster jedisCluster = new JedisCluster(hosts, defaultTimeout);\n        Collection<JedisPool> allNodes = jedisCluster.getConnectionHandler().getNodes().values();\n        try {\n            for (JedisPool jedisPool : allNodes) {\n                String host = jedisPool.getHost();\n                int port = jedisPool.getPort();\n                if (!redisCenter.isMaster(appId, host, port)) {\n                    continue;\n                }\n                masterNodeList.add(new HostAndPort(host, port));\n            }\n        } finally {\n            jedisCluster.close();\n        }\n        return masterNodeList;\n    }\n\n    private final Map<String, String> nodeIdCachedMap = new HashMap<String, String>();\n\n    public String getNodeId(final long appId, final Jedis jedis) {\n        String nodeKey = getNodeKey(jedis);\n        if (nodeIdCachedMap.get(nodeKey) != null) {\n            return nodeIdCachedMap.get(nodeKey);\n        } else {\n            String nodeId = redisCenter.getNodeId(appId, jedis.getClient().getHost(), jedis.getClient().getPort());\n            nodeIdCachedMap.put(nodeKey, nodeId);\n            return nodeId;\n        }\n    }\n    \n    protected String getNodeKey(Jedis jedis) {\n        return jedis.getClient().getHost() + \":\" + jedis.getClient().getPort();\n    }\n\n    public void setMigrateTimeout(int migrateTimeout) {\n        this.migrateTimeout = migrateTimeout;\n    }\n\n    public void setDefaultTimeout(int defaultTimeout) {\n        this.defaultTimeout = defaultTimeout;\n    }\n\n    public void setInstanceReshardProcessDao(InstanceReshardProcessDao instanceReshardProcessDao) {\n        this.instanceReshardProcessDao = instanceReshardProcessDao;\n    }\n\n    public void setRedisCenter(RedisCenter redisCenter) {\n        this.redisCenter = redisCenter;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/redis/RedisConfigTemplateService.java",
    "content": "package com.sohu.cache.redis;\n\nimport java.util.List;\n\nimport com.sohu.cache.entity.InstanceConfig;\n\n/**\n * redis配置模板服务\n * @author leifu\n * @Date 2016年6月23日\n * @Time 下午2:08:03\n */\npublic interface RedisConfigTemplateService {\n\n    /**\n     * 获取所有配置模板列表\n     * @return\n     */\n    List<InstanceConfig> getAllInstanceConfig();\n\n    /**\n     * 根据type获取配置模板列表\n     * \n     * @param type\n     * @return\n     */\n    List<InstanceConfig> getByType(int type);\n\n    /**\n     * 保存或者更新配置模板\n     * \n     * @param instanceConfig\n     * @return\n     */\n    int saveOrUpdate(InstanceConfig instanceConfig);\n\n    /**\n     * 根据id获取配置模板\n     * \n     * @param id\n     * @return\n     */\n    InstanceConfig getById(long id);\n\n    /**\n     * 根据configKey和type获取配置\n     * \n     * @param configKey\n     * @param type\n     * @return\n     */\n    InstanceConfig getByConfigKeyAndType(String configKey, int type);\n\n    /**\n     * 更改配置状态\n     * @param id\n     * @param status\n     * @return\n     */\n    int updateStatus(long id, int status);\n    \n    /**\n     * 删除配置\n     * @param id\n     */\n    int remove(long id);\n    \n    /**\n     * 普通节点配置\n     * @param port\n     * @param maxMemory\n     * @return\n     */\n    List<String> handleCommonConfig(int port, int maxMemory);\n\n    /**\n     * sentinel节点配置\n     * @param masterName\n     * @param host\n     * @param port\n     * @param sentinelPort\n     * @param quorum\n     * @return\n     */\n    List<String> handleSentinelConfig(String masterName, String host, int port, int sentinelPort);\n    \n    /**\n     * cluster节点配置\n     * @param port\n     * @return\n     */\n    List<String> handleClusterConfig(int port);\n    \n    \n    /**\n     * 普通节点默认配置\n     * @param port\n     * @param maxMemory\n     * @return\n     */\n    List<String> handleCommonDefaultConfig(int port, int maxMemory);\n\n    /**\n     * sentinel节点默认配置\n     * @param masterName\n     * @param host\n     * @param port\n     * @param sentinelPort\n     * @param quorum\n     * @return\n     */\n    List<String> handleSentinelDefaultConfig(String masterName, String host, int port, int sentinelPort);\n    \n    /**\n     * cluster节点默认配置\n     * @param port\n     * @return\n     */\n    List<String> handleClusterDefaultConfig(int port);\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/redis/RedisDeployCenter.java",
    "content": "package com.sohu.cache.redis;\n\nimport java.util.List;\n\nimport com.sohu.cache.constant.ClusterOperateResult;\nimport com.sohu.cache.entity.AppDesc;\nimport com.sohu.cache.web.enums.RedisOperateEnum;\n\n/**\n * redis 部署配置\n * Created by yijunzhang on 14-7-1.\n */\npublic interface RedisDeployCenter {\n\n    /**\n     * 部署cluster 集群\n     *\n     * @param appId        应用id\n     * @param clusterNodes redis实例集合\n     * @param maxMemory 实例最大内存,单位MB\n     * @return 实例是否部署成功\n     */\n    public boolean deployClusterInstance(long appId, List<RedisClusterNode> clusterNodes, int maxMemory);\n\n    /**\n     * 部署redis sentinel实例 实例组\n     *\n     * @param appId        应用id\n     * @param masterHost       主节点地址\n     * @param slaveHost        从节点地址\n     * @param maxMemory    实例最大内存,单位MB\n     * @param sentinelList sentinel-host列表\n     * @param \n     * @return 实例是否部署成功\n     */\n    public boolean deploySentinelInstance(long appId, String masterHost, String slaveHost, int maxMemory, List<String> sentinelList);\n\n    /**\n     * 部署Standalone redis实例\n     *\n     * @param appId        应用id\n     * @param host        节点地址\n     * @param maxMemory    实例最大内存,单位MB\n     * @return 实例是否部署成功\n     */\n    public boolean deployStandaloneInstance(long appId, String host, int maxMemory);\n\n    /**\n     * 修改app下所有实例的配置\n     *\n     * @param appId\n     * @param parameter\n     * @param value\n     * @return\n     */\n    public boolean modifyAppConfig(long appId, String parameter, String value);\n\n    /**\n     * 修改实例配置\n     * @param appId\n     * @param host\n     * @param port\n     * @param parameter\n     * @param value\n     * @return\n     */\n    public boolean modifyInstanceConfig(long appId, String host, int port, String parameter, String value);\n\n    /**\n     * 为应用appId添加sentinel服务器\n     *\n     * @param appId\n     * @param sentinelHost\n     * @return\n     */\n    public boolean addSentinel(long appId, String sentinelHost) throws Exception;\n\n    /**\n     * 为主节点添加从节点\n     *\n     * @param appId\n     * @param masterInstanceId\n     * @param slaveHost\n     * @return\n     */\n    public boolean addSlave(long appId, int masterInstanceId, String slaveHost) throws Exception;\n    \n    /**\n     * 填充集群中失败的slots，添加一个master节点\n     * @param appId\n     * @param instanceId\n     * @param masterHost\n     * @return\n     * @throws Exception\n     */\n    public RedisOperateEnum addSlotsFailMaster(long appId, int instanceId, String masterHost) throws Exception;\n    \n    /**\n     * 创建一个redis实例\n     *\n     * @param appDesc\n     * @param host\n     * @param port\n     * @param maxMemory\n     * @return\n     */\n    public boolean createRunNode(AppDesc appDesc, String host, Integer port, int maxMemory, boolean isCluster);\n\n    /**\n     * sentinel类型应用执行Failover,主从切换\n     * @param appId\n     * @return\n     */\n    public boolean sentinelFailover(long appId) throws Exception;\n\n    /**\n     * cluster类型应用执行Failover,主从切换,只能在从节点执行\n     *\n     * @param appId\n     * @param slaveInstanceId\n     * @param failoverParam\n     * @return\n     */\n    public boolean clusterFailover(long appId, int slaveInstanceId, String failoverParam) throws Exception;\n\n    /**\n     * 检查是否具备forget的条件\n     * @param appId\n     * @param forgetInstanceId\n     * @return\n     */\n    public ClusterOperateResult checkClusterForget(Long appId, int forgetInstanceId);\n\n    /**\n     * 删除节点\n     * @param appId\n     * @param delNodeInstanceId\n     * @return\n     */\n    public ClusterOperateResult delNode(Long appId, int delNodeInstanceId);\n\n\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/redis/enums/InstanceAlertCheckCycleEnum.java",
    "content": "package com.sohu.cache.redis.enums;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * 实例报警检测周期枚举\n * @author leifu\n * @Date 2017年6月14日\n * @Time 上午10:21:29\n */\npublic enum InstanceAlertCheckCycleEnum {\n    ONE_MINUTE(1, \"1分钟\"),\n    FIVE_MINUTE(2, \"5分钟\"),\n    HALF_HOUR(3, \"30分钟\"),\n    ONE_HOUR(4, \"1小时\"),\n    ONE_DAY(5, \"1天\"),\n    ;\n    \n    private final static List<InstanceAlertCheckCycleEnum> instanceAlertCheckCycleEnumList = new ArrayList<InstanceAlertCheckCycleEnum>();\n    static {\n        for (InstanceAlertCheckCycleEnum instanceAlertCheckCycleEnum : InstanceAlertCheckCycleEnum.values()) {\n            instanceAlertCheckCycleEnumList.add(instanceAlertCheckCycleEnum);\n        }\n    }\n\n    private int value;\n    \n    private String info;\n\n    private InstanceAlertCheckCycleEnum(int value, String info) {\n        this.value = value;\n        this.info = info;\n    }\n\n    public static List<InstanceAlertCheckCycleEnum> getInstanceAlertCheckCycleEnumList() {\n        return instanceAlertCheckCycleEnumList;\n    }\n\n    public int getValue() {\n        return value;\n    }\n\n    public String getInfo() {\n        return info;\n    }\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/redis/enums/InstanceAlertCompareTypeEnum.java",
    "content": "package com.sohu.cache.redis.enums;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 实例报警比较枚举\n * @author leifu\n * @Date 2017年6月14日\n * @Time 上午10:20:47\n */\npublic enum InstanceAlertCompareTypeEnum {\n    LESS_THAN(1, \"小于\"),\n    EQUAL(2, \"等于\"),\n    MORE_THAN(3, \"大于\"),\n    NOT_EQUAL(4, \"不等于\");\n    \n    private final static List<InstanceAlertCompareTypeEnum> instanceAlertCompareTypeEnumList = new ArrayList<InstanceAlertCompareTypeEnum>();\n    static {\n        for (InstanceAlertCompareTypeEnum instanceAlertCompareTypeEnum : InstanceAlertCompareTypeEnum.values()) {\n            instanceAlertCompareTypeEnumList.add(instanceAlertCompareTypeEnum);\n        }\n    }\n    \n    private final static Map<Integer, InstanceAlertCompareTypeEnum> instanceAlertCompareTypeEnumMap = new HashMap<Integer, InstanceAlertCompareTypeEnum>();\n    static {\n        for (InstanceAlertCompareTypeEnum instanceAlertCompareTypeEnum : InstanceAlertCompareTypeEnum.values()) {\n            instanceAlertCompareTypeEnumMap.put(instanceAlertCompareTypeEnum.getValue(), instanceAlertCompareTypeEnum);\n        }\n    }\n    \n    private int value;\n    \n    private String info;\n\n    private InstanceAlertCompareTypeEnum(int value, String info) {\n        this.value = value;\n        this.info = info;\n    }\n\n    public static List<InstanceAlertCompareTypeEnum> getInstanceAlertCompareTypeEnumList() {\n        return instanceAlertCompareTypeEnumList;\n    }\n    \n    public static InstanceAlertCompareTypeEnum getInstanceAlertCompareTypeEnum(int value) {\n        return instanceAlertCompareTypeEnumMap.get(value);\n    }\n\n    public int getValue() {\n        return value;\n    }\n\n    public String getInfo() {\n        return info;\n    }\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/redis/enums/InstanceAlertStatusEnum.java",
    "content": "package com.sohu.cache.redis.enums;\n\n/**\n * 实例报警有效性枚举\n * @author leifu\n * @Date 2017年6月14日\n * @Time 上午10:22:39\n */\npublic enum InstanceAlertStatusEnum {\n    YES(1, \"有效\"),\n    NO(0, \"无效\");\n\n    private int value;\n    \n    private String info;\n\n    private InstanceAlertStatusEnum(int value, String info) {\n        this.value = value;\n        this.info = info;\n    }\n\n    public int getValue() {\n        return value;\n    }\n\n    public String getInfo() {\n        return info;\n    }\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/redis/enums/InstanceAlertTypeEnum.java",
    "content": "package com.sohu.cache.redis.enums;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * 实例报警类型枚举\n * @author leifu\n * @Date 2017年6月14日\n * @Time 上午10:22:10\n */\npublic enum InstanceAlertTypeEnum {\n    ALL_ALERT(1, \"全局报警\"),\n    INSTANCE_ALERT(2, \"实例报警\");\n\n    \n    private final static List<InstanceAlertTypeEnum> instanceAlertTypeEnumList = new ArrayList<InstanceAlertTypeEnum>();\n    static {\n        for (InstanceAlertTypeEnum instanceAlertTypeEnum : InstanceAlertTypeEnum.values()) {\n            instanceAlertTypeEnumList.add(instanceAlertTypeEnum);\n        }\n    }\n    \n    private int value;\n    \n    private String info;\n\n    private InstanceAlertTypeEnum(int value, String info) {\n        this.value = value;\n        this.info = info;\n    }\n\n    public int getValue() {\n        return value;\n    }\n\n    public String getInfo() {\n        return info;\n    }\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/redis/enums/RedisAlertConfigEnum.java",
    "content": "package com.sohu.cache.redis.enums;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * Redis报警配置枚举\n * @author leifu\n * @Date 2017年6月13日\n * @Time 下午5:34:42\n */\npublic enum RedisAlertConfigEnum {\n    aof_current_size(\"aof_current_size\", \"aof当前尺寸(单位：MB)\"),\n    minute_aof_delayed_fsync(\"aof_delayed_fsync\", \"分钟aof阻塞个数\"),\n    client_biggest_input_buf(\"client_biggest_input_buf\", \"输入缓冲区最大buffer大小(单位：MB)\"),\n    client_longest_output_list(\"client_longest_output_list\", \"输出缓冲区最大队列长度\"),\n    instantaneous_ops_per_sec(\"instantaneous_ops_per_sec\", \"实时ops\"),\n    latest_fork_usec(\"latest_fork_usec\", \"上次fork所用时间(单位：微秒)\"),\n    mem_fragmentation_ratio(\"mem_fragmentation_ratio\", \"内存碎片率(检测大于500MB)\"),\n    rdb_last_bgsave_status(\"rdb_last_bgsave_status\", \"上一次bgsave状态\"),\n    minute_rejected_connections(\"rejected_connections\", \"分钟拒绝连接数\"),\n    minute_sync_partial_err(\"sync_partial_err\", \"分钟部分复制失败次数\"),\n    minute_sync_partial_ok(\"sync_partial_ok\", \"分钟部分复制成功次数\"),\n    minute_sync_full(\"sync_full\", \"分钟全量复制执行次数\"),\n    minute_total_net_input_bytes(\"total_net_input_bytes\", \"分钟网络输入流量(单位：MB)\"),\n    minute_total_net_output_bytes(\"total_net_output_bytes\", \"分钟网络输出流量(单位：MB)\"),\n    master_slave_offset_diff(\"master_slave_offset_diff\", \"主从节点偏移量差(单位：字节)\"),\n    cluster_state(\"cluster_state\", \"集群状态\"),\n    cluster_slots_ok(\"cluster_slots_ok\", \"集群成功分配槽个数\"),\n    ;\n    private final static List<RedisAlertConfigEnum> redisAlertConfigEnumList = new ArrayList<RedisAlertConfigEnum>();\n    static {\n        for (RedisAlertConfigEnum redisAlertConfigEnum : RedisAlertConfigEnum.values()) {\n            redisAlertConfigEnumList.add(redisAlertConfigEnum);\n        }\n    }\n    \n    private final static Map<String, RedisAlertConfigEnum> redisAlertConfigEnumMap = new HashMap<String, RedisAlertConfigEnum>();\n    static {\n        for (RedisAlertConfigEnum redisAlertConfigEnum : RedisAlertConfigEnum.values()) {\n            redisAlertConfigEnumMap.put(redisAlertConfigEnum.getValue(), redisAlertConfigEnum);\n        }\n    }\n    \n    private String value;\n    \n    private String info;\n    \n\n    public static List<RedisAlertConfigEnum> getRedisAlertConfigEnumList() {\n        return redisAlertConfigEnumList;\n    }\n\n    public static Map<String, RedisAlertConfigEnum> getRedisAlertConfigEnumMap() {\n        return redisAlertConfigEnumMap;\n    }\n    \n    public static RedisAlertConfigEnum getRedisAlertConfig(String alertConfig) {\n        return redisAlertConfigEnumMap.get(alertConfig);\n    }\n\n    private RedisAlertConfigEnum(String value, String info) {\n        this.value = value;\n        this.info = info;\n    }\n\n    public String getValue() {\n        return value;\n    }\n\n    public String getInfo() {\n        return info;\n    }\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/redis/enums/RedisClusterConfigEnum.java",
    "content": "package com.sohu.cache.redis.enums;\n\n/**\n * Created by yijunzhang on 14-8-25.\n */\npublic enum RedisClusterConfigEnum {\n    CLUSTER_ENABLED(\"cluster-enabled\", \"yes\", \"是否开启集群模式\"),\n    CLUSTER_NODE_TIMEOUT(\"cluster-node-timeout\", \"15000\", \"集群节点超时时间,默认15秒\"),\n    CLUSTER_SLAVE_VALIDITY_FACTOR(\"cluster-slave-validity-factor\", \"10\", \"集群从节点,延迟有效性判断因子,默认10秒:(node-timeout * slave-validity-factor) + repl-ping-slave-period\"),\n    CLUSTER_MIGRATION_BARRIER(\"cluster-migration-barrier\", \"1\", \"cluster主从迁移至少需要的从节点数,默认1个\"),\n    CLUSTER_CONFIG_FILE(\"cluster-config-file\", \"nodes-%d.conf\", \"集群配置文件名称,格式:nodes-{port}.conf\"),\n    CLUSTER_REQUIRE_FULL_COVERAGE(\"cluster-require-full-coverage\", \"no\", \"节点部分失败期间,其他节点是否继续工作\");\n\n    private String key;\n\n    private String value;\n\n    private String desc;\n\n    RedisClusterConfigEnum(String key, String value, String desc) {\n        this.key = key;\n        this.value = value;\n        this.desc = desc;\n    }\n\n    public void setValue(String value) {\n        this.value = value;\n    }\n\n    public String getValue() {\n        return value;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public String getKey() {\n        return key;\n    }\n\n    public static RedisClusterConfigEnum get(String key) {\n        if (key == null) {\n            return null;\n        }\n        for (RedisClusterConfigEnum config : RedisClusterConfigEnum.values()) {\n            if (config.key.equals(key)) {\n                return config;\n            }\n        }\n        return null;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/redis/enums/RedisClusterInfoEnum.java",
    "content": "package com.sohu.cache.redis.enums;\n\n/**\n * cluster info枚举\n * @author leifu\n * @Date 2017年6月21日\n * @Time 下午2:36:47\n */\npublic enum RedisClusterInfoEnum {\n    \n    cluster_state(\"cluster_state\", \"集群状态\", false),\n    cluster_slots_assigned(\"cluster_slots_assigned\", \"分配slot个数\", false),\n    cluster_slots_ok(\"cluster_slots_ok\", \"成功分配slot个数\", false),\n    cluster_slots_pfail(\"cluster_slots_pfail\", \"pfail个数\", false),\n    cluster_slots_fail(\"cluster_slots_fail\", \"fail个数\", false),\n    cluster_stats_messages_sent(\"cluster_stats_messages_sent\", \"发送消息字节数\", false),\n    cluster_stats_messages_received(\"cluster_stats_messages_received\", \"接收消息字节数\", false),\n    ;\n    \n    private String value;\n    \n    private String info;\n    \n    private boolean needCalDif;\n\n    private RedisClusterInfoEnum(String value, String info, boolean needCalDif) {\n        this.value = value;\n        this.info = info;\n        this.needCalDif = needCalDif;\n    }\n\n    public String getValue() {\n        return value;\n    }\n\n    public String getInfo() {\n        return info;\n    }\n\n    public boolean isNeedCalDif() {\n        return needCalDif;\n    }\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/redis/enums/RedisConfigEnum.java",
    "content": "package com.sohu.cache.redis.enums;\n\nimport com.sohu.cache.protocol.MachineProtocol;\n\n/**\n * Created by yijunzhang on 14-7-27.\n */\npublic enum RedisConfigEnum {\n    DAEMONIZE(\"daemonize\", \"no\", \"是否守护进程\"),\n    TCP_BACKLOG(\"tcp-backlog\", \"511\", \"TCP连接完成队列\"),\n    TIMEOUT(\"timeout\", \"0\", \"客户端闲置多少秒后关闭连接,默认为0,永不关闭\"),\n    TCP_KEEPALIVE(\"tcp-keepalive\", \"0\", \"检测客户端是否健康周期,默认关闭\"),\n    LOGLEVEL(\"loglevel\", \"notice\", \"默认普通的verbose\"),\n    DATABASES(\"databases\", \"16\", \"可用的数据库数，默认值为16个,默认数据库为0\"),\n    DIR(\"dir\", MachineProtocol.DATA_DIR, \"redis工作目录,默认:\" + MachineProtocol.DATA_DIR),\n    STOP_WRITES_ON_BGSAVE_ERROR(\"stop-writes-on-bgsave-error\", \"no\", \"bgsave出错了不停写\"),\n    REPL_TIMEOUT(\"repl-timeout\", \"60\", \"master批量数据传输时间或者ping回复时间间隔,默认:60秒\"),\n    REPL_PING_SLAVE_PERIOD(\"repl-ping-slave-period\", \"10\", \"指定slave定期ping master的周期,默认:10秒\"),\n    REPL_DISABLE_TCP_NODELAY(\"repl-disable-tcp-nodelay\", \"no\", \"是否禁用socket的NO_DELAY,默认关闭，影响主从延迟\"),\n    REPL_BACKLOG_SIZE(\"repl-backlog-size\", \"10M\", \"复制缓存区,默认:1mb,配置为:10Mb\"),\n    REPL_BACKLOG_TTL(\"repl-backlog-ttl\", \"7200\", \"master在没有Slave的情况下释放BACKLOG的时间多久:默认:3600,配置为:7200\"),\n    SLAVE_SERVE_STALE_DATA(\"slave-serve-stale-data\", \"yes\", \"当slave服务器和master服务器失去连接后，或者当数据正在复制传输的时候，如果此参数值设置“yes”，slave服务器可以继续接受客户端的请求\"),\n    SLAVE_READ_ONLY(\"slave-read-only\", \"yes\", \"slave服务器节点是否只读,cluster的slave节点默认读写都不可用,需要调用readonly开启可读模式\"),\n    SLAVE_PRIORITY(\"slave-priority\", \"100\", \"slave的优先级,影响sentinel/cluster晋升master操作,0永远不晋升\"),\n    LUA_TIME_LIMIT(\"lua-time-limit\", \"5000\", \"Lua脚本最长的执行时间，单位为毫秒\"),\n    SLOWLOG_LOG_SLOWER_THAN(\"slowlog-log-slower-than\", \"10000\", \"慢查询被记录的阀值,默认10毫秒\"),\n    SLOWLOG_MAX_LEN(\"slowlog-max-len\", \"128\", \"最多记录慢查询的条数\"),\n    HASH_MAX_ZIPLIST_ENTRIES(\"hash-max-ziplist-entries\", \"512\", \"hash数据结构优化参数\"),\n    HASH_MAX_ZIPLIST_VALUE(\"hash-max-ziplist-value\", \"64\", \"hash数据结构优化参数\"),\n    LIST_MAX_ZIPLIST_ENTRIES(\"list-max-ziplist-entries\", \"512\", \"list数据结构优化参数\"),\n    LIST_MAX_ZIPLIST_VALUE(\"list-max-ziplist-value\", \"64\", \"list数据结构优化参数\"),\n    SET_MAX_INTSET_ENTRIES(\"set-max-intset-entries\", \"512\", \"set数据结构优化参数\"),\n    ZSET_MAX_ZIPLIST_ENTRIES(\"zset-max-ziplist-entries\", \"128\", \"zset数据结构优化参数\"),\n    ZSET_MAX_ZIPLIST_VALUE(\"zset-max-ziplist-value\", \"64\", \"zset数据结构优化参数\"),\n    ACTIVEREHASHING(\"activerehashing\", \"yes\", \"是否激活重置哈希,默认:yes\"),\n    CLIENT_OUTPUT_BUFFER_LIMIT_NORMAL(\"client-output-buffer-limit normal\", \"0 0 0\", \"\"),\n    CLIENT_OUTPUT_BUFFER_LIMIT_SLAVE(\"client-output-buffer-limit slave\", \"512mb 128mb 60\", \"\"),\n    CLIENT_OUTPUT_BUFFER_LIMIT_PUBSUB(\"client-output-buffer-limit pubsub\", \"32mb 8mb 60\", \"\"),\n    HZ(\"hz\", \"10\", \"执行后台task数量,默认:10\"),\n    PORT(\"port\", \"%d\", \"端口\"),\n    MAXMEMORY(\"maxmemory\", \"%dmb\", \"当前实例最大可用内存\"),\n    MAXMEMORY_POLICY(\"maxmemory-policy\", \"volatile-lru\", \"内存不够时,淘汰策略,默认:volatile-lru\"),\n    REQUIREPASS(\"requirepass\", \"\", \"密码\"),\n    MASTERAUTH(\"masterauth\", \"\", \"从节点需要配置的主节点密码\"),\n    AUTH_PASS(\"auth-pass\", \"\", \"sentinel节点需要配置的主节点密码\"),\n    APPENDONLY(\"appendonly\", \"yes\", \"开启append only持久化模式\"),\n    APPENDFSYNC(\"appendfsync\", \"everysec\", \"默认:aof每秒同步一次\"),\n    APPENDFILENAME(\"appendfilename\", \"appendonly-%d.aof\", \"aof文件名称,默认:appendonly-{port}.aof\"),\n    DBFILENAME(\"dbfilename\", \"dump-%d.rdb\", \"RDB文件默认名称,默认dump-{port}.rdb\"),\n    AOF_REWRITE_INCREMENTAL_FSYNC(\"aof-rewrite-incremental-fsync\",\"yes\",\"aof rewrite过程中,是否采取增量文件同步策略,默认:yes\"),\n    NO_APPENDFSYNC_ON_REWRITE(\"no-appendfsync-on-rewrite\", \"yes\", \"是否在后台aof文件rewrite期间调用fsync,默认调用,修改为yes,防止可能fsync阻塞,但可能丢失rewrite期间的数据\"),\n    AUTO_AOF_REWRITE_MIN_SIZE(\"auto-aof-rewrite-min-size\", \"64m\", \"触发rewrite的aof文件最小阀值,默认64m\"),\n    AUTO_AOF_REWRITE_PERCENTAGE(\"auto-aof-rewrite-percentage\", \"%d\", \"Redis重写aof文件的比例条件,默认从100开始,统一机器下不同实例按4%递减\");\n\n    private String key;\n\n    private String value;\n\n    private String desc;\n\n    RedisConfigEnum(String key, String value, String desc) {\n        this.key = key;\n        this.value = value;\n        this.desc = desc;\n    }\n\n    public void setValue(String value) {\n        this.value = value;\n    }\n\n    public String getValue() {\n        return value;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public String getKey() {\n        return key;\n    }\n\n    public static RedisConfigEnum get(String key) {\n        if (key == null) {\n            return null;\n        }\n        for (RedisConfigEnum config : RedisConfigEnum.values()) {\n            if (config.key.equals(key)) {\n                return config;\n            }\n        }\n        return null;\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/redis/enums/RedisInfoEnum.java",
    "content": "package com.sohu.cache.redis.enums;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport com.sohu.cache.constant.RedisConstant;\n\n/**\n * Redis报警配置枚举\n * @author leifu\n * @Date 2017年6月13日\n * @Time 下午5:34:42\n */\npublic enum RedisInfoEnum {\n    \n    /**\n     * Stats\n     */\n    client_biggest_input_buf(RedisConstant.Stats, \"client_biggest_input_buf\", \"输入缓冲区最大buffer大小(单位：字节)\", false),\n    client_longest_output_list(RedisConstant.Stats, \"client_longest_output_list\", \"输出缓冲区最大队列长度\", false),\n    instantaneous_ops_per_sec(RedisConstant.Stats, \"instantaneous_ops_per_sec\", \"实时ops\", false),\n    rejected_connections(RedisConstant.Stats, \"rejected_connections\", \"拒绝客户端连接数\", true),\n    sync_partial_err(RedisConstant.Stats, \"sync_partial_err\", \"部分复制失败次数\", true),\n    sync_partial_ok(RedisConstant.Stats, \"sync_partial_ok\", \"部分复制成功次数\", true),\n    sync_full(RedisConstant.Stats, \"sync_full\", \"全量复制执行次数\", true),\n    total_net_input_bytes(RedisConstant.Stats, \"total_net_input_bytes\", \"网络输入流量(单位：字节)\", true),\n    total_net_output_bytes(RedisConstant.Stats, \"total_net_output_bytes\", \"网络输出流量(单位：字节)\", true),\n    keyspace_hits(RedisConstant.Stats, \"keyspace_hits\", \"键命中数\", true),\n    keyspace_misses(RedisConstant.Stats, \"keyspace_misses\", \"键未命中数\", true),\n    evicted_keys(RedisConstant.Stats, \"evicted_keys\", \"键剔除数\", true),\n    expired_keys(RedisConstant.Stats, \"expired_keys\", \"键过期数\", true),\n    connected_clients(RedisConstant.Stats, \"connected_clients\", \"客户端连接数\", false),\n\n    /**\n     * Persistence\n     */\n    aof_current_size(RedisConstant.Persistence, \"aof_current_size\", \"aof当前尺寸(单位：字节)\", false),\n    aof_base_size(RedisConstant.Persistence, \"aof_base_size\", \"aof基准尺寸(单位：字节)\", false),\n    aof_delayed_fsync(RedisConstant.Persistence, \"aof_delayed_fsync\", \"aof阻塞次数\", true),\n    latest_fork_usec(RedisConstant.Persistence, \"latest_fork_usec\", \"上次fork所用时间(单位：微秒)\", false),\n    rdb_last_bgsave_status(RedisConstant.Persistence, \"rdb_last_bgsave_status\", \"上一次bgsave状态\", false),\n    \n    /**\n     * Memory\n     */\n    used_memory(RedisConstant.Memory, \"used_memory\", \"内存使用(单位：字节)\", false),\n    mem_fragmentation_ratio(RedisConstant.Memory, \"mem_fragmentation_ratio\", \"内存碎片率\", false),\n    \n    /**\n     * Replication\n     */\n    role(RedisConstant.Replication, \"role\", \"主从角色\", false),\n    master_host(RedisConstant.Replication, \"master_host\", \"主节点host\", false),\n    master_port(RedisConstant.Replication, \"master_port\", \"主节点端口\", false),\n    connected_slaves(RedisConstant.Replication, \"connected_slaves\", \"从节点数量\", false),\n    master_repl_offset(RedisConstant.Replication, \"master_repl_offset\", \"主节点偏移量\", false),\n    \n    ;\n    \n    private final static List<RedisInfoEnum> RedisInfoEnumList = new ArrayList<RedisInfoEnum>();\n    static {\n        for (RedisInfoEnum redisInfoEnum : RedisInfoEnum.values()) {\n            RedisInfoEnumList.add(redisInfoEnum);\n        }\n    }\n    \n    private RedisConstant redisConstant;\n    \n    private String value;\n    \n    private String info;\n    \n    private boolean needCalDif;\n\n    private RedisInfoEnum(RedisConstant redisConstant, String value, String info, boolean needCalDif) {\n        this.redisConstant = redisConstant;\n        this.value = value;\n        this.info = info;\n        this.needCalDif = needCalDif;\n    }\n    \n    /**\n     * 获取需要计算差值的统计属性\n     * @return\n     */\n    public static List<RedisInfoEnum> getNeedCalDifRedisInfoEnumList() {\n        List<RedisInfoEnum> resultList = new ArrayList<RedisInfoEnum>();\n        for (RedisInfoEnum redisInfoEnum : RedisInfoEnumList) {\n            if (redisInfoEnum.isNeedCalDif()) {\n                resultList.add(redisInfoEnum);\n            }\n        }\n        return resultList;\n    }\n    \n    public RedisConstant getRedisConstant() {\n        return redisConstant;\n    }\n\n    public String getValue() {\n        return value;\n    }\n\n    public String getInfo() {\n        return info;\n    }\n\n    public boolean isNeedCalDif() {\n        return needCalDif;\n    }\n\n\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/redis/enums/RedisReadOnlyCommandEnum.java",
    "content": "package com.sohu.cache.redis.enums;\n\nimport org.apache.commons.lang.StringUtils;\n\n/**\n * Created by yijunzhang on 14-10-14.\n */\npublic enum RedisReadOnlyCommandEnum {\n    debug,\n    exists,\n    object,\n    ttl,\n    type,\n    scan,\n    get,\n    getbit,\n    getrange,\n    mget,\n    setrange,\n    strlen,\n    hexists,\n    hget,\n    hgetall,\n    hkeys,\n    hlen,\n    hmget,\n    hvals,\n    hscan,\n    lindex,\n    llen,\n    lrange,\n    scard,\n    sismember,\n    sscan,\n    srandmember,\n    zcard,\n    zcount,\n    zrange,\n    zrangebyscore,\n    zrank,\n    zrevrange,\n    zscore,\n    zscan,\n    dbsize,\n    info,\n    time,\n    lastsave;\n    public static boolean contains(String command) {\n        if (StringUtils.isBlank(command)) {\n            return false;\n        }\n        for (RedisReadOnlyCommandEnum readEnum : RedisReadOnlyCommandEnum.values()) {\n            String readCommand = readEnum.toString();\n            command = StringUtils.trim(command);\n            if (command.length() < readCommand.toString().length()) {\n                continue;\n            }\n            String head = StringUtils.substring(command, 0, readCommand.length());\n            if (readCommand.equalsIgnoreCase(head)) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/redis/enums/RedisSentinelConfigEnum.java",
    "content": "package com.sohu.cache.redis.enums;\n\n/**\n * Created by yijunzhang on 14-8-25.\n */\npublic enum RedisSentinelConfigEnum {\n    PORT(\"port\", \"%d\", \"sentinel实例端口\"),\n    DIR(\"dir\", \"/tmp\", \"文件目录\"),\n    MONITOR(\"sentinel monitor\", \"%s %s %d %d\", \"master名称定义和最少参与监控的sentinel数,格式:masterName ip port num\"),\n    DOWN_AFTER_MILLISECONDS(\"sentinel down-after-milliseconds\", \"%s 20000\", \"Sentinel判定服务器断线的毫秒数,默认:20秒\"),\n    FAILOVER_TIMEOUT(\"sentinel failover-timeout\", \"%s 180000\", \"故障迁移超时时间,默认:3分钟\"),\n    PARALLEL_SYNCS(\"sentinel parallel-syncs\", \"%s 1\", \"在执行故障转移时,最多有多少个从服务器同时对新的主服务器进行同步,默认:1\");\n\n    private String key;\n\n    private String value;\n\n    private String desc;\n\n    RedisSentinelConfigEnum(String key, String value, String desc) {\n        this.key = key;\n        this.value = value;\n        this.desc = desc;\n    }\n\n    public void setValue(String value) {\n        this.value = value;\n    }\n\n    public String getValue() {\n        return value;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public String getKey() {\n        return key;\n    }\n\n    public static RedisSentinelConfigEnum get(String key) {\n        if (key == null) {\n            return null;\n        }\n        for (RedisSentinelConfigEnum config : RedisSentinelConfigEnum.values()) {\n            if (config.key.equals(key)) {\n                return config;\n            }\n        }\n        return null;\n    }\n\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/redis/impl/RedisCenterImpl.java",
    "content": "package com.sohu.cache.redis.impl;\n\nimport com.google.common.collect.HashBasedTable;\nimport com.google.common.collect.Table;\nimport com.sohu.cache.async.AsyncService;\nimport com.sohu.cache.async.AsyncThreadPoolFactory;\nimport com.sohu.cache.async.KeyCallable;\nimport com.sohu.cache.constant.*;\nimport com.sohu.cache.dao.*;\nimport com.sohu.cache.entity.*;\nimport com.sohu.cache.machine.MachineCenter;\nimport com.sohu.cache.protocol.RedisProtocol;\nimport com.sohu.cache.redis.RedisCenter;\nimport com.sohu.cache.redis.enums.RedisInfoEnum;\nimport com.sohu.cache.redis.enums.RedisReadOnlyCommandEnum;\nimport com.sohu.cache.schedule.SchedulerCenter;\nimport com.sohu.cache.stats.instance.InstanceStatsCenter;\nimport com.sohu.cache.util.*;\nimport com.sohu.cache.web.util.DateUtil;\nimport com.sohu.cache.web.vo.RedisSlowLog;\n\nimport org.apache.commons.collections.CollectionUtils;\nimport org.apache.commons.collections.MapUtils;\nimport org.apache.commons.lang.StringUtils;\nimport org.apache.commons.pool2.impl.GenericObjectPoolConfig;\nimport org.quartz.JobKey;\nimport org.quartz.Trigger;\nimport org.quartz.TriggerKey;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.util.Assert;\n\nimport redis.clients.jedis.*;\nimport redis.clients.jedis.exceptions.JedisAskDataException;\nimport redis.clients.jedis.exceptions.JedisDataException;\nimport redis.clients.jedis.exceptions.JedisMovedDataException;\nimport redis.clients.util.*;\n\nimport java.sql.Timestamp;\nimport java.util.*;\nimport java.util.Map.Entry;\nimport java.util.concurrent.locks.Lock;\nimport java.util.concurrent.locks.ReentrantLock;\n\n/**\n * Created by yijunzhang on 14-6-10.\n */\npublic class RedisCenterImpl implements RedisCenter {\n    private final Logger logger = LoggerFactory.getLogger(this.getClass());\n\n    public static final int REDIS_DEFAULT_TIME = 4000;\n\n    private SchedulerCenter schedulerCenter;\n\n    private AppStatsDao appStatsDao;\n\n    private AsyncService asyncService;\n\n    private InstanceDao instanceDao;\n\n    private InstanceStatsDao instanceStatsDao;\n\n    private InstanceStatsCenter instanceStatsCenter;\n\n    private MachineCenter machineCenter;\n\n    private volatile Map<String, JedisPool> jedisPoolMap = new HashMap<String, JedisPool>();\n\n    private final Lock lock = new ReentrantLock();\n\n    private AppDao appDao;\n\n    private AppAuditLogDao appAuditLogDao;\n\n    public static final String REDIS_SLOWLOG_POOL = \"redis-slowlog-pool\";\n\n    public void init() {\n        asyncService.assemblePool(getThreadPoolKey(), AsyncThreadPoolFactory.REDIS_SLOWLOG_THREAD_POOL);\n    }\n\n    private InstanceSlowLogDao instanceSlowLogDao;\n\n    @Override\n    public boolean deployRedisCollection(long appId, String host, int port) {\n        Assert.isTrue(appId > 0);\n        Assert.hasText(host);\n        Assert.isTrue(port > 0);\n        Map<String, Object> dataMap = new HashMap<String, Object>();\n        dataMap.put(ConstUtils.HOST_KEY, host);\n        dataMap.put(ConstUtils.PORT_KEY, port);\n        dataMap.put(ConstUtils.APP_KEY, appId);\n        JobKey jobKey = JobKey.jobKey(ConstUtils.REDIS_JOB_NAME, ConstUtils.REDIS_JOB_GROUP);\n        TriggerKey triggerKey = TriggerKey\n                .triggerKey(ObjectConvert.linkIpAndPort(host, port), ConstUtils.REDIS_TRIGGER_GROUP + appId);\n        return schedulerCenter\n                .deployJobByCron(jobKey, triggerKey, dataMap, ScheduleUtil.getMinuteCronByAppId(appId), false);\n    }\n\n    private JedisPool maintainJedisPool(String host, int port, String password) {\n        String hostAndPort = ObjectConvert.linkIpAndPort(host, port);\n        JedisPool jedisPool = jedisPoolMap.get(hostAndPort);\n        if (jedisPool == null) {\n            lock.lock();\n            try {\n                //double check\n                jedisPool = jedisPoolMap.get(hostAndPort);\n                if (jedisPool == null) {\n                    try {\n                        if (StringUtils.isNotBlank(password)) {\n                            jedisPool = new JedisPool(new GenericObjectPoolConfig(), host, port, Protocol.DEFAULT_TIMEOUT, password);\n                        } else {\n                            jedisPool = new JedisPool(new GenericObjectPoolConfig(), host, port, Protocol.DEFAULT_TIMEOUT);\n                        }\n                        jedisPoolMap.put(hostAndPort, jedisPool);\n                    } catch (Exception e) {\n                        logger.error(e.getMessage(), e);\n                    } finally {\n\n                    }\n                }\n            } finally {\n                lock.unlock();\n            }\n        }\n        return jedisPool;\n    }\n\n    @Override\n    public boolean unDeployRedisCollection(long appId, String host, int port) {\n        Assert.isTrue(appId > 0);\n        Assert.hasText(host);\n        Assert.isTrue(port > 0);\n        TriggerKey triggerKey = TriggerKey\n                .triggerKey(ObjectConvert.linkIpAndPort(host, port), ConstUtils.REDIS_TRIGGER_GROUP + appId);\n        Trigger trigger = schedulerCenter.getTrigger(triggerKey);\n        if (trigger == null) {\n            return true;\n        }\n        return schedulerCenter.unscheduleJob(triggerKey);\n    }\n\n    private String buildFutureKey(long appId, long collectTime, String host, int port) {\n        StringBuilder keyBuffer = new StringBuilder(\"redis-\");\n        keyBuffer.append(collectTime);\n        keyBuffer.append(\"-\");\n        keyBuffer.append(appId);\n        keyBuffer.append(\"-\");\n        keyBuffer.append(host + \":\" + port);\n        return keyBuffer.toString();\n    }\n\n    private class RedisKeyCallable extends KeyCallable<Boolean> {\n        private final long appId;\n        private final long collectTime;\n        private final String host;\n        private final int port;\n        private final Map<RedisConstant, Map<String, Object>> infoMap;\n        private final Map<String, Object> clusterInfoMap;\n\n\n        private RedisKeyCallable(long appId, long collectTime, String host, int port,\n                                 Map<RedisConstant, Map<String, Object>> infoMap, Map<String, Object> clusterInfoMap) {\n            super(buildFutureKey(appId, collectTime, host, port));\n            this.appId = appId;\n            this.collectTime = collectTime;\n            this.host = host;\n            this.port = port;\n            this.infoMap = infoMap;\n            this.clusterInfoMap = clusterInfoMap;\n        }\n\n        @Override\n        public Boolean execute() {\n            //比对currentInfoMap和lastInfoMap,计算差值\n            long lastCollectTime = ScheduleUtil.getLastCollectTime(collectTime);\n            Map<String, Object> lastInfoMap = instanceStatsCenter\n                    .queryStandardInfoMap(lastCollectTime, host, port, ConstUtils.REDIS);\n\n            if (lastInfoMap == null || lastInfoMap.isEmpty()) {\n                logger.error(\"[redis-lastInfoMap] : lastCollectTime = {} appId={} host:port = {}:{} is null\",\n                        lastCollectTime, appId, host, port);\n            }\n            //基本统计累加差值\n            Table<RedisConstant, String, Long> baseDiffTable = getAccumulationDiff(infoMap, lastInfoMap);\n            fillAccumulationMap(infoMap, baseDiffTable);\n\n            //命令累加差值\n            Table<RedisConstant, String, Long> commandDiffTable = getCommandsDiff(infoMap, lastInfoMap);\n            fillAccumulationMap(infoMap, commandDiffTable);\n\n            Map<String, Object> currentInfoMap = new LinkedHashMap<String, Object>();\n            for (RedisConstant constant : infoMap.keySet()) {\n                currentInfoMap.put(constant.getValue(), infoMap.get(constant));\n            }\n            currentInfoMap.put(ConstUtils.COLLECT_TIME, collectTime);\n            instanceStatsCenter.saveStandardStats(currentInfoMap, clusterInfoMap, host, port, ConstUtils.REDIS);\n\n            // 更新实例在db中的状态\n            InstanceStats instanceStats = getInstanceStats(appId, host, port, infoMap);\n            if (instanceStats != null) {\n                instanceStatsDao.updateInstanceStats(instanceStats);\n            }\n\n            boolean isMaster = isMaster(infoMap);\n            if (isMaster) {\n                Table<RedisConstant, String, Long> diffTable = HashBasedTable.create();\n                diffTable.putAll(baseDiffTable);\n                diffTable.putAll(commandDiffTable);\n\n                long allCommandCount = 0L;\n                //更新命令统计\n                List<AppCommandStats> commandStatsList = getCommandStatsList(appId, collectTime, diffTable);\n                for (AppCommandStats commandStats : commandStatsList) {\n                    //排除无效命令且存储有累加的数据\n                    if (RedisExcludeCommand.isExcludeCommand(commandStats.getCommandName())\n                            || commandStats.getCommandCount() <= 0L) {\n                        continue;\n                    }\n                    allCommandCount += commandStats.getCommandCount();\n                    try {\n                        appStatsDao.mergeMinuteCommandStatus(commandStats);\n                        appStatsDao.mergeHourCommandStatus(commandStats);\n                    } catch (Exception e) {\n                        logger.error(e.getMessage() + appId, e);\n                    }\n                }\n                //写入app分钟统计\n                AppStats appStats = getAppStats(appId, collectTime, diffTable, infoMap);\n                try {\n                    appStats.setCommandCount(allCommandCount);\n                    appStatsDao.mergeMinuteAppStats(appStats);\n                    appStatsDao.mergeHourAppStats(appStats);\n                } catch (Exception e) {\n                    logger.error(e.getMessage() + appId, e);\n                }\n                logger.info(\"collect redis info done, appId: {}, instance: {}:{}, time: {}\", appId, host, port,\n                        collectTime);\n            }\n\n            return true;\n        }\n    }\n\n\n    @Override\n    public List<InstanceSlowLog> collectRedisSlowLog(long appId, long collectTime, String host, int port) {\n        Assert.isTrue(appId > 0);\n        Assert.hasText(host);\n        Assert.isTrue(port > 0);\n        InstanceInfo instanceInfo = instanceDao.getInstByIpAndPort(host, port);\n        //不存在实例/实例异常/下线\n        if (instanceInfo == null) {\n            return null;\n        }\n        if (TypeUtil.isRedisSentinel(instanceInfo.getType())) {\n            //忽略sentinel redis实例\n            return null;\n        }\n        // 从redis中获取慢查询日志\n        List<RedisSlowLog> redisLowLogList = getRedisSlowLogs(appId, host, port, 100);\n        if (CollectionUtils.isEmpty(redisLowLogList)) {\n            return Collections.emptyList();\n        }\n\n        // transfer\n        final List<InstanceSlowLog> instanceSlowLogList = new ArrayList<InstanceSlowLog>();\n        for (RedisSlowLog redisSlowLog : redisLowLogList) {\n            InstanceSlowLog instanceSlowLog = transferRedisSlowLogToInstance(redisSlowLog, instanceInfo);\n            if (instanceSlowLog == null) {\n                continue;\n            }\n            instanceSlowLogList.add(instanceSlowLog);\n        }\n\n        if (CollectionUtils.isEmpty(instanceSlowLogList)) {\n            return Collections.emptyList();\n        }\n\n        //处理\n        String key = getThreadPoolKey() + \"_\" + host + \"_\" + port;\n        boolean isOk = asyncService.submitFuture(getThreadPoolKey(), new KeyCallable<Boolean>(key) {\n            @Override\n            public Boolean execute() {\n                try {\n                    instanceSlowLogDao.batchSave(instanceSlowLogList);\n                    return true;\n                } catch (Exception e) {\n                    logger.error(e.getMessage(), e);\n                    return false;\n                }\n            }\n        });\n        if (!isOk) {\n            logger.error(\"slowlog submitFuture failed,appId:{},collectTime:{},host:{},port:{}\", appId, collectTime, host, port);\n        }\n        return instanceSlowLogList;\n    }\n\n    private InstanceSlowLog transferRedisSlowLogToInstance(RedisSlowLog redisSlowLog, InstanceInfo instanceInfo) {\n        if (redisSlowLog == null) {\n            return null;\n        }\n        String command = redisSlowLog.getCommand();\n        long executionTime = redisSlowLog.getExecutionTime();\n        //如果command=BGREWRITEAOF并且小于50毫秒,则忽略\n        if (command.equalsIgnoreCase(\"BGREWRITEAOF\") && executionTime < 50000) {\n            return null;\n        }\n        InstanceSlowLog instanceSlowLog = new InstanceSlowLog();\n        instanceSlowLog.setAppId(instanceInfo.getAppId());\n        instanceSlowLog.setCommand(redisSlowLog.getCommand());\n        instanceSlowLog.setCostTime((int) redisSlowLog.getExecutionTime());\n        instanceSlowLog.setCreateTime(new Timestamp(System.currentTimeMillis()));\n        instanceSlowLog.setExecuteTime(new Timestamp(redisSlowLog.getDate().getTime()));\n        instanceSlowLog.setInstanceId(instanceInfo.getId());\n        instanceSlowLog.setIp(instanceInfo.getIp());\n        instanceSlowLog.setPort(instanceInfo.getPort());\n        instanceSlowLog.setSlowLogId(redisSlowLog.getId());\n\n        return instanceSlowLog;\n    }\n\n    private String getThreadPoolKey() {\n        return REDIS_SLOWLOG_POOL;\n    }\n\n    @Override\n    public Map<RedisConstant, Map<String, Object>> collectRedisInfo(long appId, long collectTime, String host,\n                                                                    int port) {\n        Assert.isTrue(appId > 0);\n        Assert.hasText(host);\n        Assert.isTrue(port > 0);\n        long start = System.currentTimeMillis();\n        InstanceInfo instanceInfo = instanceDao.getInstByIpAndPort(host, port);\n        //不存在实例/实例异常/下线\n        if (instanceInfo == null) {\n            return null;\n        }\n        if (TypeUtil.isRedisSentinel(instanceInfo.getType())) {\n            //忽略sentinel redis实例\n            return null;\n        }\n        Map<RedisConstant, Map<String, Object>> infoMap = this.getInfoStats(appId, host, port);\n        if (infoMap == null || infoMap.isEmpty()) {\n            logger.error(\"appId:{},collectTime:{},host:{},port:{} cost={} ms redis infoMap is null\",\n                    new Object[]{appId, collectTime, host, port, (System.currentTimeMillis() - start)});\n            return infoMap;\n        }\n        // cluster info统计\n        Map<String,Object> clusterInfoMap = getClusterInfoStats(appId, instanceInfo);\n        \n        boolean isOk = asyncService.submitFuture(new RedisKeyCallable(appId, collectTime, host, port, infoMap, clusterInfoMap));\n        if (!isOk) {\n            logger.error(\"submitFuture failed,appId:{},collectTime:{},host:{},port:{} cost={} ms\",\n                    new Object[]{appId, collectTime, host, port, (System.currentTimeMillis() - start)});\n        }\n        return infoMap;\n    }\n\n    @Override\n    public Map<RedisConstant, Map<String, Object>> getInfoStats(final long appId, final String host, final int port) {\n        Map<RedisConstant, Map<String, Object>> infoMap = null;\n        final StringBuilder infoBuilder = new StringBuilder();\n        try {\n            boolean isOk = new IdempotentConfirmer() {\n                private int timeOutFactor = 1;\n\n                @Override\n                public boolean execute() {\n                    Jedis jedis = null;\n                    try {\n                    \t    jedis = getJedis(appId, host, port);\n                        jedis.getClient().setConnectionTimeout(REDIS_DEFAULT_TIME * (timeOutFactor++));\n                        jedis.getClient().setSoTimeout(REDIS_DEFAULT_TIME * (timeOutFactor++));\n                        String info = jedis.info(\"all\");\n                        infoBuilder.append(info);\n                        return StringUtils.isNotBlank(info);\n                    } catch (Exception e) {\n                        logger.warn(\"{}:{}, redis-getInfoStats errorMsg:{}\", host, port, e.getMessage());\n                        return false;\n                    } finally {\n                        if (jedis != null)\n                            jedis.close();\n                    }\n                }\n            }.run();\n            if (!isOk) {\n                return infoMap;\n            }\n            infoMap = processRedisStats(infoBuilder.toString());\n        } catch (Exception e) {\n            logger.error(e.getMessage() + \" {}:{}\", host, port, e);\n        }\n        if (infoMap == null || infoMap.isEmpty()) {\n            logger.error(\"host:{},port:{} redis infoMap is null\", host, port);\n            return infoMap;\n        }\n        return infoMap;\n    }\n    \n    @Override\n    public Map<String, Object> getClusterInfoStats(final long appId, final String host, final int port) {\n        InstanceInfo instanceInfo = instanceDao.getAllInstByIpAndPort(host, port);\n        return getClusterInfoStats(appId, instanceInfo);\n    }\n    \n    @Override\n    public Map<String, Object> getClusterInfoStats(final long appId, final InstanceInfo instanceInfo) {\n        long startTime = System.currentTimeMillis();\n        if (instanceInfo == null) {\n            logger.warn(\"getClusterInfoStats instanceInfo is null\");\n            return Collections.emptyMap();\n        }\n        if (!TypeUtil.isRedisCluster(instanceInfo.getType())) {\n            return Collections.emptyMap();\n        }\n        final String host = instanceInfo.getIp();\n        final int port = instanceInfo.getPort();\n        Map<String, Object> clusterInfoMap = null;\n        final StringBuilder infoBuilder = new StringBuilder();\n        try {\n            boolean isOk = new IdempotentConfirmer() {\n                private int timeOutFactor = 1;\n\n                @Override\n                public boolean execute() {\n                    Jedis jedis = null;\n                    try {\n                        jedis = getJedis(appId, host, port);\n                        jedis.getClient().setConnectionTimeout(REDIS_DEFAULT_TIME * (timeOutFactor++));\n                        jedis.getClient().setSoTimeout(REDIS_DEFAULT_TIME * (timeOutFactor++));\n                        String clusterInfo = jedis.clusterInfo();\n                        infoBuilder.append(clusterInfo);\n                        return StringUtils.isNotBlank(clusterInfo);\n                    } catch (Exception e) {\n                        logger.warn(\"{}:{}, redis-getInfoStats errorMsg:{}\", host, port, e.getMessage());\n                        return false;\n                    } finally {\n                        if (jedis != null)\n                            jedis.close();\n                    }\n                }\n            }.run();\n            if (!isOk) {\n                return clusterInfoMap;\n            }\n            clusterInfoMap = processClusterInfoStats(infoBuilder.toString());\n        } catch (Exception e) {\n            logger.error(e.getMessage() + \" {}:{}\", host, port, e);\n        }\n        if (MapUtils.isEmpty(clusterInfoMap)) {\n            logger.error(\"{}:{} redis clusterInfoMap is null\", host, port);\n            return Collections.emptyMap();\n        }\n        long costTime = System.currentTimeMillis() - startTime;\n        if (costTime > 100) {\n            logger.warn(\"{}:{} cluster info cost time {} ms\", host, port, costTime);\n        }\n        return clusterInfoMap;\n    }\n\n    private void fillAccumulationMap(Map<RedisConstant, Map<String, Object>> infoMap,\n                                     Table<RedisConstant, String, Long> table) {\n        if (table == null || table.isEmpty()) {\n            return;\n        }\n        Map<String, Object> accMap = infoMap.get(RedisConstant.DIFF);\n        if (accMap == null) {\n            accMap = new LinkedHashMap<String, Object>();\n            infoMap.put(RedisConstant.DIFF, accMap);\n        }\n        for (RedisConstant constant : table.rowKeySet()) {\n            Map<String, Long> rowMap = table.row(constant);\n            accMap.putAll(rowMap);\n        }\n    }\n\n    /**\n     * 获取累加参数值\n     *\n     * @param currentInfoMap\n     * @return 累加差值map\n     */\n    private Table<RedisConstant, String, Long> getAccumulationDiff(\n            Map<RedisConstant, Map<String, Object>> currentInfoMap,\n            Map<String, Object> lastInfoMap) {\n        //没有上一次统计快照，忽略差值统计\n        if (lastInfoMap == null || lastInfoMap.isEmpty()) {\n            return HashBasedTable.create();\n        }\n        Map<RedisInfoEnum, Long> currentMap = new LinkedHashMap<RedisInfoEnum, Long>();\n        for (RedisInfoEnum acc : RedisInfoEnum.getNeedCalDifRedisInfoEnumList()) {\n            Long count = getCommonCount(currentInfoMap, acc.getRedisConstant(), acc.getValue());\n            if (count != null) {\n                currentMap.put(acc, count);\n            }\n        }\n        Map<RedisInfoEnum, Long> lastMap = new LinkedHashMap<RedisInfoEnum, Long>();\n        for (RedisInfoEnum acc : RedisInfoEnum.getNeedCalDifRedisInfoEnumList()) {\n            if (lastInfoMap != null) {\n                Long lastCount = getCommonCount(lastInfoMap, acc.getRedisConstant(), acc.getValue());\n                if (lastCount != null) {\n                    lastMap.put(acc, lastCount);\n                }\n            }\n        }\n        Table<RedisConstant, String, Long> resultTable = HashBasedTable.create();\n        for (RedisInfoEnum key : currentMap.keySet()) {\n            Long value = MapUtils.getLong(currentMap, key, null);\n            Long lastValue = MapUtils.getLong(lastMap, key, null);\n            if (value == null || lastValue == null) {\n                //忽略\n                continue;\n            }\n            long diff = 0L;\n            if (value > lastValue) {\n                diff = value - lastValue;\n            }\n            resultTable.put(key.getRedisConstant(), key.getValue(), diff);\n        }\n        return resultTable;\n    }\n\n    /**\n     * 获取命令差值统计\n     *\n     * @param currentInfoMap\n     * @param lastInfoMap\n     * @return 命令统计\n     */\n    private Table<RedisConstant, String, Long> getCommandsDiff(Map<RedisConstant, Map<String, Object>> currentInfoMap,\n                                                               Map<String, Object> lastInfoMap) {\n        //没有上一次统计快照，忽略差值统计\n        if (lastInfoMap == null || lastInfoMap.isEmpty()) {\n            return HashBasedTable.create();\n        }\n        Map<String, Object> map = currentInfoMap.get(RedisConstant.Commandstats);\n        Map<String, Long> currentMap = transferLongMap(map);\n        Map<String, Object> lastObjectMap;\n        if (lastInfoMap.get(RedisConstant.Commandstats.getValue()) == null) {\n            lastObjectMap = new HashMap<String, Object>();\n        } else {\n            lastObjectMap = (Map<String, Object>) lastInfoMap.get(RedisConstant.Commandstats.getValue());\n        }\n        Map<String, Long> lastMap = transferLongMap(lastObjectMap);\n\n        Table<RedisConstant, String, Long> resultTable = HashBasedTable.create();\n        for (String command : currentMap.keySet()) {\n            long lastCount = MapUtils.getLong(lastMap, command, 0L);\n            long currentCount = MapUtils.getLong(currentMap, command, 0L);\n            if (currentCount > lastCount) {\n                resultTable.put(RedisConstant.Commandstats, command, currentCount - lastCount);\n            }\n        }\n        return resultTable;\n    }\n\n    private AppStats getAppStats(long appId, long collectTime, Table<RedisConstant, String, Long> table,\n                                 Map<RedisConstant, Map<String, Object>> infoMap) {\n        AppStats appStats = new AppStats();\n        appStats.setAppId(appId);\n        appStats.setCollectTime(collectTime);\n        appStats.setModifyTime(new Date());\n        appStats.setUsedMemory(MapUtils.getLong(infoMap.get(RedisConstant.Memory), RedisInfoEnum.used_memory.getValue(), 0L));\n        appStats.setHits(MapUtils.getLong(table.row(RedisConstant.Stats), RedisInfoEnum.keyspace_hits.getValue(), 0L));\n        appStats.setMisses(MapUtils.getLong(table.row(RedisConstant.Stats), RedisInfoEnum.keyspace_misses.getValue(), 0L));\n        appStats.setEvictedKeys(MapUtils.getLong(table.row(RedisConstant.Stats), RedisInfoEnum.evicted_keys.getValue(), 0L));\n        appStats.setExpiredKeys(MapUtils.getLong(table.row(RedisConstant.Stats), RedisInfoEnum.expired_keys.getValue(), 0L));\n        appStats.setNetInputByte(MapUtils.getLong(table.row(RedisConstant.Stats), RedisInfoEnum.total_net_input_bytes.getValue(), 0L));\n        appStats.setNetOutputByte(MapUtils.getLong(table.row(RedisConstant.Stats), RedisInfoEnum.total_net_output_bytes.getValue(), 0L));\n        appStats.setConnectedClients(MapUtils.getIntValue(infoMap.get(RedisConstant.Clients), RedisInfoEnum.connected_clients.getValue(), 0));\n        appStats.setObjectSize(getObjectSize(infoMap));\n        return appStats;\n    }\n\n    private long getObjectSize(Map<RedisConstant, Map<String, Object>> currentInfoMap) {\n        Map<String, Object> sizeMap = currentInfoMap.get(RedisConstant.Keyspace);\n        if (sizeMap == null || sizeMap.isEmpty()) {\n            return 0L;\n        }\n        long result = 0L;\n        Map<String, Long> longSizeMap = transferLongMap(sizeMap);\n        for (String key : longSizeMap.keySet()) {\n            result += longSizeMap.get(key);\n        }\n        return result;\n    }\n\n    private Long getCommonCount(Map<?, ?> infoMap, RedisConstant redisConstant, String commond) {\n        Object constantObject =\n                infoMap.get(redisConstant) == null ? infoMap.get(redisConstant.getValue()) : infoMap.get(redisConstant);\n        if (constantObject != null && (constantObject instanceof Map)) {\n            Map constantMap = (Map) constantObject;\n            if (constantMap == null || constantMap.get(commond) == null) {\n                return null;\n            }\n            return MapUtils.getLongValue(constantMap, commond);\n        }\n        return null;\n    }\n\n    /**\n     * 转换redis 命令行统计结果\n     *\n     * @param commandMap\n     * @return\n     */\n    private Map<String, Long> transferLongMap(Map<String, Object> commandMap) {\n        Map<String, Long> resultMap = new HashMap<String, Long>();\n        if (commandMap == null || commandMap.isEmpty()) {\n            return resultMap;\n        }\n        for (String key : commandMap.keySet()) {\n            if (commandMap.get(key) == null) {\n                continue;\n            }\n            String value = commandMap.get(key).toString();\n            String[] stats = value.split(\",\");\n            if (stats.length == 0) {\n                continue;\n            }\n            String[] calls = stats[0].split(\"=\");\n            if (calls == null || calls.length < 2) {\n                continue;\n            }\n            long callCount = Long.valueOf(calls[1]);\n            resultMap.put(key, callCount);\n        }\n        return resultMap;\n    }\n\n    private List<AppCommandStats> getCommandStatsList(long appId, long collectTime,\n                                                      Table<RedisConstant, String, Long> table) {\n        Map<String, Long> commandMap = table.row(RedisConstant.Commandstats);\n        List<AppCommandStats> list = new ArrayList<AppCommandStats>();\n        if (commandMap == null) {\n            return list;\n        }\n        for (String key : commandMap.keySet()) {\n            String commandName = key.replace(\"cmdstat_\", \"\");\n            long callCount = MapUtils.getLong(commandMap, key, 0L);\n            if (callCount == 0L) {\n                continue;\n            }\n            AppCommandStats commandStats = new AppCommandStats();\n            commandStats.setAppId(appId);\n            commandStats.setCollectTime(collectTime);\n            commandStats.setCommandName(commandName);\n            commandStats.setCommandCount(callCount);\n            commandStats.setModifyTime(new Date());\n            list.add(commandStats);\n        }\n        return list;\n    }\n    \n    /**\n     * 处理clusterinfo统计信息\n     * @param clusterInfo\n     * @return\n     */\n    private Map<String, Object> processClusterInfoStats(String clusterInfo) {\n        Map<String, Object> clusterInfoMap = new HashMap<String, Object>();\n        String[] lines = clusterInfo.split(\"\\r\\n\");\n        for (String line : lines) {\n            String[] pair = line.split(\":\");\n            if (pair.length == 2) {\n                clusterInfoMap.put(pair[0], pair[1]);\n            }\n        }\n        return clusterInfoMap;\n    }\n\n    /**\n     * 处理redis统计信息\n     *\n     * @param statResult 统计结果串\n     */\n    private Map<RedisConstant, Map<String, Object>> processRedisStats(String statResult) {\n        Map<RedisConstant, Map<String, Object>> redisStatMap = new HashMap<RedisConstant, Map<String, Object>>();\n        String[] data = statResult.split(\"\\r\\n\");\n        String key;\n        int i = 0;\n        int length = data.length;\n        while (i < length) {\n            if (data[i].contains(\"#\")) {\n                int index = data[i].indexOf('#');\n                key = data[i].substring(index + 1);\n                ++i;\n                RedisConstant redisConstant = RedisConstant.value(key.trim());\n                if (redisConstant == null) {\n                    continue;\n                }\n                Map<String, Object> sectionMap = new LinkedHashMap<String, Object>();\n                while (i < length && data[i].contains(\":\")) {\n                    String[] pair = StringUtils.splitByWholeSeparator(data[i], \":\");\n                    sectionMap.put(pair[0], pair[1]);\n                    i++;\n                }\n                redisStatMap.put(redisConstant, sectionMap);\n            } else {\n                i++;\n            }\n        }\n        return redisStatMap;\n    }\n    \n    /**\n     * 根据infoMap的结果判断实例的主从\n     *\n     * @param infoMap\n     * @return\n     */\n    private Boolean hasSlaves(Map<RedisConstant, Map<String, Object>> infoMap) {\n        Map<String, Object> replicationMap = infoMap.get(RedisConstant.Replication);\n        if (MapUtils.isEmpty(replicationMap)) {\n            return null;\n        }\n        for (Entry<String, Object> entry : replicationMap.entrySet()) {\n            String key = entry.getKey();\n            //判断一个即可\n            if (key != null && key.contains(\"slave0\")) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    /**\n     * 根据infoMap的结果判断实例的主从\n     *\n     * @param infoMap\n     * @return\n     */\n    private Boolean isMaster(Map<RedisConstant, Map<String, Object>> infoMap) {\n        Map<String, Object> map = infoMap.get(RedisConstant.Replication);\n        if (map == null || map.get(RedisInfoEnum.role.getValue()) == null) {\n            return null;\n        }\n        if (String.valueOf(map.get(RedisInfoEnum.role.getValue())).equals(\"master\")) {\n            return true;\n        }\n        return false;\n    }\n\n    /**\n     * 根据ip和port判断某一个实例当前是主还是从\n     *\n     * @param ip   ip\n     * @param port port\n     * @return 主返回true， 从返回false；\n     */\n    @Override\n    public Boolean isMaster(long appId, String ip, int port) {\n        Jedis jedis = getJedis(appId, ip, port, REDIS_DEFAULT_TIME, REDIS_DEFAULT_TIME);\n        try {\n            String info = jedis.info(\"all\");\n            Map<RedisConstant, Map<String, Object>> infoMap = processRedisStats(info);\n            return isMaster(infoMap);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return null;\n        } finally {\n            jedis.close();\n        }\n    }\n    \n    /**\n     * 根据ip和port判断redis实例当前是否有从节点\n     * @param ip   ip\n     * @param port port\n     * @return 主返回true，从返回false；\n     */\n    public Boolean hasSlaves(long appId, String ip, int port) {\n        Jedis jedis = getJedis(appId, ip, port, REDIS_DEFAULT_TIME, REDIS_DEFAULT_TIME);\n        try {\n            String info = jedis.info(\"all\");\n            Map<RedisConstant, Map<String, Object>> infoMap = processRedisStats(info);\n            return hasSlaves(infoMap);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return null;\n        } finally {\n            jedis.close();\n        }\n    }   \n\n    @Override\n    public HostAndPort getMaster(String ip, int port, String password) {\n        JedisPool jedisPool = maintainJedisPool(ip, port, password);\n        Jedis jedis = null;\n        try {\n            jedis = jedisPool.getResource();\n            String info = jedis.info(RedisConstant.Replication.getValue());\n            Map<RedisConstant, Map<String, Object>> infoMap = processRedisStats(info);\n            Map<String, Object> map = infoMap.get(RedisConstant.Replication);\n            if (map == null) {\n                return null;\n            }\n            String masterHost = MapUtils.getString(map, RedisInfoEnum.master_host.getValue(), null);\n            int masterPort = MapUtils.getInteger(map, RedisInfoEnum.master_port.getValue(), 0);\n            if (StringUtils.isNotBlank(masterHost) && masterPort > 0) {\n                return new HostAndPort(masterHost, masterPort);\n            }\n            return null;\n        } catch (Exception e) {\n            logger.error(\"{}:{} getMaster failed {}\", ip, port, e.getMessage(), e);\n            return null;\n        } finally {\n            if (jedis != null)\n                jedis.close();\n        }\n    }\n    \n    @Override\n\tpublic boolean isRun(final String ip, final int port) {\n    \t\treturn isRun(ip, port, null);\n    }\n\n    @Override\n    public boolean isRun(final long appId, final String ip, final int port) {\n    \t\tAppDesc appDesc = appDao.getAppDescById(appId);\n    \t\treturn isRun(ip, port, appDesc.getPassword());\n    }\n    \n    @Override\n\tpublic boolean isRun(final String ip, final int port, final String password) {\n   \t\tboolean isRun = new IdempotentConfirmer() {\n            private int timeOutFactor = 1;\n\n            @Override\n            public boolean execute() {\n                Jedis jedis = null;\n                try {\n                \t\tjedis = getJedis(ip, port, password);\n                    jedis.getClient().setConnectionTimeout(Protocol.DEFAULT_TIMEOUT * (timeOutFactor++));\n                    jedis.getClient().setSoTimeout(Protocol.DEFAULT_TIMEOUT * (timeOutFactor++));\n                    String pong = jedis.ping();\n                    return pong != null && pong.equalsIgnoreCase(\"PONG\");\n                } catch (JedisDataException e) {\n                    String message = e.getMessage();\n                    logger.warn(e.getMessage());\n                    if (StringUtils.isNotBlank(message) && message.startsWith(\"LOADING\")) {\n                        return true;\n                    }\n                    return false;\n                } catch (Exception e) {\n                    logger.warn(\"{}:{} error message is {} \", ip, port, e.getMessage());\n                    return false;\n                } finally {\n                \t\tif (jedis != null) {\n                \t\t\tjedis.close();\n\t\t\t\t\t}\n                }\n            }\n        }.run();\n        return isRun;\n\t}\n    \n\n    @Override\n    public boolean shutdown(long appId, String ip, int port) {\n        boolean isRun = isRun(appId, ip, port);\n        if (!isRun) {\n            return true;\n        }\n        final Jedis jedis = getJedis(appId, ip, port);\n        try {\n            //关闭实例节点\n            boolean isShutdown = new IdempotentConfirmer() {\n                @Override\n                public boolean execute() {\n                    jedis.shutdown();\n                    return true;\n                }\n            }.run();\n            if (!isShutdown) {\n                logger.error(\"{}:{} redis not shutdown!\", ip, port);\n            }\n            return isShutdown;\n        } finally {\n            jedis.close();\n        }\n    }\n    \n    @Override\n\tpublic boolean shutdown(String ip, int port) {\n    \t\tboolean isRun = isRun(ip, port);\n        if (!isRun) {\n            return true;\n        }\n        final Jedis jedis = getJedis(ip, port);\n        try {\n            //关闭实例节点\n            boolean isShutdown = new IdempotentConfirmer() {\n                @Override\n                public boolean execute() {\n                    jedis.shutdown();\n                    return true;\n                }\n            }.run();\n            if (!isShutdown) {\n                logger.error(\"{}:{} redis not shutdown!\", ip, port);\n            }\n            return isShutdown;\n        } finally {\n            jedis.close();\n        }\n\t}\n\n    /**\n     * 返回当前实例的一些关键指标\n     *\n     * @param appId\n     * @param ip\n     * @param port\n     * @param infoMap\n     * @return\n     */\n    public InstanceStats getInstanceStats(long appId, String ip, int port,\n                                          Map<RedisConstant, Map<String, Object>> infoMap) {\n        if (infoMap == null) {\n            return null;\n        }\n        // 查询最大内存限制\n        Long maxMemory = this.getRedisMaxMemory(appId, ip, port);\n        /**\n         * 将实例的一些关键指标返回\n         */\n        InstanceStats instanceStats = new InstanceStats();\n        instanceStats.setAppId(appId);\n        InstanceInfo curInst = instanceDao.getInstByIpAndPort(ip, port);\n        if (curInst != null) {\n            instanceStats.setHostId(curInst.getHostId());\n            instanceStats.setInstId(curInst.getId());\n        } else {\n            logger.error(\"redis={}:{} not found\", ip, port);\n            return null;\n        }\n        instanceStats.setIp(ip);\n        instanceStats.setPort(port);\n        if (maxMemory != null) {\n            instanceStats.setMaxMemory(maxMemory);\n        }\n        instanceStats.setUsedMemory(MapUtils.getLongValue(infoMap.get(RedisConstant.Memory), RedisInfoEnum.used_memory.getValue(), 0));\n        instanceStats.setHits(MapUtils.getLongValue(infoMap.get(RedisConstant.Stats), RedisInfoEnum.keyspace_hits.getValue(), 0));\n        instanceStats.setMisses(MapUtils.getLongValue(infoMap.get(RedisConstant.Stats), RedisInfoEnum.keyspace_misses.getValue(), 0));\n        instanceStats.setCurrConnections(MapUtils.getIntValue(infoMap.get(RedisConstant.Clients), RedisInfoEnum.connected_clients.getValue(), 0));\n        instanceStats.setCurrItems(getObjectSize(infoMap));\n        instanceStats.setRole((byte) 1);\n        if (MapUtils.getString(infoMap.get(RedisConstant.Replication), RedisInfoEnum.role.getValue()).equals(\"slave\")) {\n            instanceStats.setRole((byte) 2);\n        }\n        instanceStats.setModifyTime(new Timestamp(System.currentTimeMillis()));\n        instanceStats.setMemFragmentationRatio(MapUtils.getDoubleValue(infoMap.get(RedisConstant.Memory), RedisInfoEnum.mem_fragmentation_ratio.getValue(), 0.0));\n        instanceStats.setAofDelayedFsync(MapUtils.getIntValue(infoMap.get(RedisConstant.Persistence), RedisInfoEnum.aof_delayed_fsync.getValue(), 0));\n        return instanceStats;\n    }\n\n    @Override\n    public Long getRedisMaxMemory(final long appId, final String ip, final int port) {\n        final String key = \"maxmemory\";\n        final Map<String, Long> resultMap = new HashMap<String, Long>();\n        boolean isSuccess = new IdempotentConfirmer() {\n            private int timeOutFactor = 1;\n\n            @Override\n            public boolean execute() {\n                Jedis jedis = null;\n                try {\n                    jedis = getJedis(appId, ip, port);\n                    jedis.getClient().setConnectionTimeout(REDIS_DEFAULT_TIME * (timeOutFactor++));\n                    jedis.getClient().setSoTimeout(REDIS_DEFAULT_TIME * (timeOutFactor++));\n                    List<String> maxMemoryList = jedis.configGet(key); // 返回结果：list中是2个字符串，如：\"maxmemory\",\n                    // \"4096000000\"\n                    if (maxMemoryList != null && maxMemoryList.size() >= 2) {\n                        resultMap.put(key, Long.valueOf(maxMemoryList.get(1)));\n                    }\n                    return MapUtils.isNotEmpty(resultMap);\n                } catch (Exception e) {\n                    logger.warn(\"{}:{} errorMsg: {}\", ip, port, e.getMessage());\n                    return false;\n                } finally {\n                    if (jedis != null) {\n                        jedis.close();\n                    }\n                }\n            }\n        }.run();\n        if (isSuccess) {\n            return MapUtils.getLong(resultMap, key);\n        } else {\n            logger.error(\"{}:{} getMaxMemory failed!\", ip, port);\n            return null;\n        }\n    }\n\n    @Override\n    public String executeCommand(AppDesc appDesc, String command) {\n        //非测试应用只能执行白名单里面的命令\n        if (AppDescEnum.AppTest.NOT_TEST.getValue() == appDesc.getIsTest()) {\n            if (!RedisReadOnlyCommandEnum.contains(command)) {\n                return \"online app only support read-only and safe command\";\n            }\n        }\n        int type = appDesc.getType();\n        long appId = appDesc.getAppId();\n        String password = appDesc.getPassword();\n        if (type == ConstUtils.CACHE_REDIS_SENTINEL) {\n            JedisSentinelPool jedisSentinelPool = getJedisSentinelPool(appDesc);\n            if (jedisSentinelPool == null) {\n                return \"sentinel can not execute \";\n            }\n            Jedis jedis = null;\n            try {\n                jedis = jedisSentinelPool.getResource();\n                String host = jedis.getClient().getHost();\n                int port = jedis.getClient().getPort();\n                return executeCommand(appId, host, port, command);\n            } catch (Exception e) {\n                logger.error(e.getMessage(), e);\n                return \"运行出错:\" + e.getMessage();\n            } finally {\n                if (jedis != null) jedis.close();\n                jedisSentinelPool.destroy();\n            }\n        } else if (type == ConstUtils.CACHE_REDIS_STANDALONE) {\n            List<InstanceInfo> instanceList = instanceDao.getInstListByAppId(appId);\n            if (instanceList == null || instanceList.isEmpty()) {\n                return \"应用没有运行的实例\";\n            }\n            String host = null;\n            int port = 0;\n            for (InstanceInfo instanceInfo : instanceList) {\n                host = instanceInfo.getIp();\n                port = instanceInfo.getPort();\n                break;\n            }\n            try {\n                return executeCommand(appId, host, port, command);\n            } catch (Exception e) {\n                logger.error(e.getMessage(), e);\n                return \"运行出错:\" + e.getMessage();\n            }\n        } else if (type == ConstUtils.CACHE_TYPE_REDIS_CLUSTER) {\n            List<InstanceInfo> instanceList = instanceDao.getInstListByAppId(appId);\n            if (instanceList == null || instanceList.isEmpty()) {\n                return \"应用没有运行的实例\";\n            }\n            Set<HostAndPort> clusterHosts = new LinkedHashSet<HostAndPort>();\n            for (InstanceInfo instance : instanceList) {\n                if (instance == null || instance.getStatus() == InstanceStatusEnum.OFFLINE_STATUS.getStatus()) {\n                    continue;\n                }\n                clusterHosts.add(new HostAndPort(instance.getIp(), instance.getPort()));\n            }\n            if (clusterHosts.isEmpty()) {\n                return \"no run instance\";\n            }\n            String commandKey = getCommandKey(command);\n            for (HostAndPort hostAndPort : clusterHosts) {\n                HostAndPort rightHostAndPort = getClusterRightHostAndPort(hostAndPort.getHost(), hostAndPort.getPort(), password, command, commandKey);\n                if (rightHostAndPort != null) {\n                    try {\n                        return executeCommand(appId, rightHostAndPort.getHost(), rightHostAndPort.getPort(), command);\n                    } catch (Exception e) {\n                        logger.error(e.getMessage(), e);\n                        return \"运行出错:\" + e.getMessage();\n                    }\n                }\n            }\n            \n        }\n        return \"不支持应用类型\";\n    }\n    \n    /**\n     * 获取key对应的节点\n     * @param host\n     * @param port\n     * @param password\n     * @param command\n     * @param key\n     * @return\n     */\n    private HostAndPort getClusterRightHostAndPort(String host, int port, String password, String command, String key) {\n        Jedis jedis = null;\n        try {\n            jedis = getJedis(host, port, password);\n            jedis.type(key);\n            return new HostAndPort(host, port);\n        } catch (JedisMovedDataException e) {\n            return e.getTargetNode();\n        } catch (JedisAskDataException e) {\n            return e.getTargetNode();\n        } catch (Exception e) {\n            logger.error(\"command {} is error\", command, e.getMessage(), e);\n            return null;\n        } finally {\n            if (jedis != null) {\n                jedis.close();\n            }\n        }\n    }\n\n    private String getCommandKey(String command) {\n        String[] array = StringUtils.trim(command).split(\"\\\\s+\");\n        if (array.length > 1) {\n            return array[1];\n        } else {\n            return null;\n        }\n    }\n\n    @Override\n    public String executeCommand(long appId, String host, int port, String command) {\n        AppDesc appDesc = appDao.getAppDescById(appId);\n        if (appDesc == null) {\n            return \"not exist appId\";\n        }\n        //非测试应用只能执行白名单里面的命令\n        if (AppDescEnum.AppTest.NOT_TEST.getValue() == appDesc.getIsTest()) {\n            if (!RedisReadOnlyCommandEnum.contains(command)) {\n                return \"online app only support read-only and safe command \";\n            }\n        }\n        String password = appDesc.getPassword();\n        String shell = RedisProtocol.getExecuteCommandShell(host, port, password, command);\n        //记录客户端发送日志\n        logger.warn(\"executeRedisShell={}\", shell);\n        return machineCenter.executeShell(host, shell);\n    }\n\n    @Override\n    public JedisSentinelPool getJedisSentinelPool(AppDesc appDesc) {\n        if (appDesc == null) {\n            logger.error(\"appDesc is null\");\n            return null;\n        }\n        if (appDesc.getType() != ConstUtils.CACHE_REDIS_SENTINEL) {\n            logger.error(\"type={} is not sentinel\", appDesc.getType());\n            return null;\n        }\n        long appId = appDesc.getAppId();\n        List<InstanceInfo> instanceInfos = instanceDao.getInstListByAppId(appId);\n\n        String masterName = null;\n        for (Iterator<InstanceInfo> i = instanceInfos.iterator(); i.hasNext(); ) {\n            InstanceInfo instanceInfo = i.next();\n            if (instanceInfo.getType() != ConstUtils.CACHE_REDIS_SENTINEL) {\n                i.remove();\n                continue;\n            }\n            if (masterName == null && StringUtils.isNotBlank(instanceInfo.getCmd())) {\n                masterName = instanceInfo.getCmd();\n            }\n        }\n        Set<String> sentinels = new HashSet<String>();\n        for (InstanceInfo instanceInfo : instanceInfos) {\n            sentinels.add(instanceInfo.getIp() + \":\" + instanceInfo.getPort());\n        }\n        JedisSentinelPool jedisSentinelPool = new JedisSentinelPool(masterName, sentinels);\n        return jedisSentinelPool;\n    }\n\n    @Override\n    public Map<String, String> getRedisConfigList(int instanceId) {\n        if (instanceId <= 0) {\n            return Collections.emptyMap();\n        }\n        InstanceInfo instanceInfo = instanceDao.getInstanceInfoById(instanceId);\n        if (instanceInfo == null) {\n            return Collections.emptyMap();\n        }\n        if (TypeUtil.isRedisType(instanceInfo.getType())) {\n            Jedis jedis = null;\n            try {\n            \t\tjedis = getJedis(instanceInfo.getAppId(), instanceInfo.getIp(), instanceInfo.getPort(), REDIS_DEFAULT_TIME, REDIS_DEFAULT_TIME);\n                List<String> configs = jedis.configGet(\"*\");\n                Map<String, String> configMap = new LinkedHashMap<String, String>();\n                for (int i = 0; i < configs.size(); i += 2) {\n                    if (i < configs.size()) {\n                        String key = configs.get(i);\n                        String value = configs.get(i + 1);\n                        if (StringUtils.isBlank(value)) {\n                            continue;\n                        }\n                        configMap.put(key, value);\n                    }\n                }\n                return configMap;\n            } catch (Exception e) {\n                logger.error(e.getMessage(), e);\n            } finally {\n                if (jedis != null) {\n                    jedis.close();\n                }\n            }\n        }\n\n        return Collections.emptyMap();\n    }\n\n    @Override\n    public List<RedisSlowLog> getRedisSlowLogs(int instanceId, int maxCount) {\n        if (instanceId <= 0) {\n            return Collections.emptyList();\n        }\n        InstanceInfo instanceInfo = instanceDao.getInstanceInfoById(instanceId);\n        if (instanceInfo == null) {\n            return Collections.emptyList();\n        }\n        if (TypeUtil.isRedisType(instanceInfo.getType())) {\n            return getRedisSlowLogs(instanceInfo.getAppId(), instanceInfo.getIp(), instanceInfo.getPort(), maxCount);\n        }\n        return Collections.emptyList();\n    }\n\n\n    private List<RedisSlowLog> getRedisSlowLogs(long appId, String host, int port, int maxCount) {\n        Jedis jedis = null;\n        try {\n        \t\tjedis = getJedis(appId, host, port, REDIS_DEFAULT_TIME, REDIS_DEFAULT_TIME);\n            List<RedisSlowLog> resultList = new ArrayList<RedisSlowLog>();\n            List<Slowlog> slowlogs = null;\n            if (maxCount > 0) {\n                slowlogs = jedis.slowlogGet(maxCount);\n            } else {\n                slowlogs = jedis.slowlogGet();\n            }\n            if (slowlogs != null && slowlogs.size() > 0) {\n                for (Slowlog sl : slowlogs) {\n                    RedisSlowLog rs = new RedisSlowLog();\n                    rs.setId(sl.getId());\n                    rs.setExecutionTime(sl.getExecutionTime());\n                    long time = sl.getTimeStamp() * 1000L;\n                    rs.setDate(new Date(time));\n                    rs.setTimeStamp(DateUtil.formatYYYYMMddHHMMSS(new Date(time)));\n                    rs.setCommand(StringUtils.join(sl.getArgs(), \" \"));\n                    resultList.add(rs);\n                }\n            }\n            return resultList;\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return Collections.emptyList();\n        } finally {\n            if (jedis != null) {\n                jedis.close();\n            }\n        }\n    }\n\n    @Override\n    public boolean configRewrite(final long appId, final String host, final int port) {\n        return new IdempotentConfirmer() {\n            @Override\n            public boolean execute() {\n                Jedis jedis = getJedis(appId, host, port, REDIS_DEFAULT_TIME, REDIS_DEFAULT_TIME);\n                try {\n                    String response = jedis.configRewrite();\n                    return response != null && response.equalsIgnoreCase(\"OK\");\n                } finally {\n                    jedis.close();\n                }\n            }\n        }.run();\n    }\n\n    @Override\n    public boolean cleanAppData(AppDesc appDesc, AppUser appUser) {\n        if (appDesc == null) {\n            return false;\n        }\n\n        long appId = appDesc.getAppId();\n\n        // 线上应用不能清理数据\n        if (AppDescEnum.AppTest.IS_TEST.getValue() != appDesc.getIsTest()) {\n            logger.error(\"appId {} profile must be test\", appId);\n            return false;\n        }\n\n        // 必须是redis应用\n        if (!TypeUtil.isRedisType(appDesc.getType())) {\n            logger.error(\"appId {} type must be redis\", appId);\n            return false;\n        }\n\n        // 实例验证\n        List<InstanceInfo> instanceList = instanceDao.getInstListByAppId(appId);\n        if (CollectionUtils.isEmpty(instanceList)) {\n            logger.error(\"appId {} instanceList is empty\", appId);\n            return false;\n        }\n\n        // 开始清除\n        for (InstanceInfo instance : instanceList) {\n            if (instance.getStatus() != InstanceStatusEnum.GOOD_STATUS.getStatus()) {\n                continue;\n            }\n            String host = instance.getIp();\n            int port = instance.getPort();\n            // master + 非sentinel节点\n            Boolean isMater = isMaster(appId, host, port);\n            if (isMater != null && isMater.equals(true) && !TypeUtil.isRedisSentinel(instance.getType())) {\n            \t\tJedis jedis = getJedis(appId, host, port);\n            \t\tjedis.getClient().setConnectionTimeout(REDIS_DEFAULT_TIME);\n            \t\tjedis.getClient().setSoTimeout(60000);\n                try {\n                    logger.warn(\"{}:{} start clear data\", host, port);\n                    long start = System.currentTimeMillis();\n                    String result = jedis.flushAll();\n                    if (!\"ok\".equalsIgnoreCase(result)) {\n                        return false;\n                    }\n                    logger.warn(\"{}:{} finish clear data, cost time:{} ms\", host, port,\n                            (System.currentTimeMillis() - start));\n                } catch (Exception e) {\n                    logger.error(\"clear redis: \" + e.getMessage(), e);\n                    return false;\n                } finally {\n                    jedis.close();\n                }\n            }\n        }\n\n        //记录日志\n        AppAuditLog appAuditLog = AppAuditLog.generate(appDesc, appUser, 0L, AppAuditLogTypeEnum.APP_CLEAN_DATA);\n        appAuditLogDao.save(appAuditLog);\n\n        return true;\n    }\n\n    @Override\n    public boolean isSingleClusterNode(long appId, String host, int port) {\n        final Jedis jedis = getJedis(appId, host, port);\n        try {\n            String clusterNodes = jedis.clusterNodes();\n            if (StringUtils.isBlank(clusterNodes)) {\n                throw new RuntimeException(host + \":\" + port + \"clusterNodes is null\");\n            }\n            String[] nodeInfos = clusterNodes.split(\"\\n\");\n            if (nodeInfos.length == 1) {\n                return true;\n            }\n            return false;\n        } finally {\n            jedis.close();\n        }\n    }\n\n    @Override\n    public List<String> getClientList(int instanceId) {\n        if (instanceId <= 0) {\n            return Collections.emptyList();\n        }\n        InstanceInfo instanceInfo = instanceDao.getInstanceInfoById(instanceId);\n        if (instanceInfo == null) {\n            return Collections.emptyList();\n        }\n        if (TypeUtil.isRedisType(instanceInfo.getType())) {\n            Jedis jedis = null;\n            try {\n            \t\tjedis = getJedis(instanceInfo.getAppId(), instanceInfo.getIp(), instanceInfo.getPort(), REDIS_DEFAULT_TIME, REDIS_DEFAULT_TIME);\n                jedis.clientList();\n                List<String> resultList = new ArrayList<String>();\n                String clientList = jedis.clientList();\n                if (StringUtils.isNotBlank(clientList)) {\n                    String[] array = clientList.split(\"\\n\");\n                    resultList.addAll(Arrays.asList(array));\n                }\n                return resultList;\n            } catch (Exception e) {\n                logger.error(e.getMessage(), e);\n            } finally {\n                if (jedis != null) {\n                    jedis.close();\n                }\n            }\n        }\n        return Collections.emptyList();\n    }\n\n    @Override\n    public Map<String, String> getClusterLossSlots(long appId) {\n        // 1.从应用中获取一个健康的主节点\n        InstanceInfo sourceMasterInstance = getHealthyInstanceInfo(appId);\n        if (sourceMasterInstance == null) {\n            return Collections.emptyMap();\n        }\n        // 2. 获取所有slot和节点的对应关系\n        Map<Integer, String> slotHostPortMap = getSlotsHostPortMap(appId, sourceMasterInstance.getIp(), sourceMasterInstance.getPort());\n        // 3. 获取集群中失联的slot\n        List<Integer> lossSlotList = getClusterLossSlots(appId, sourceMasterInstance.getIp(), sourceMasterInstance.getPort());\n        // 3.1 将失联的slot列表组装成Map<String host:port,List<Integer> lossSlotList>\n        Map<String, List<Integer>> hostPortSlotMap = new HashMap<String, List<Integer>>();\n        if (CollectionUtils.isNotEmpty(lossSlotList)) {\n            for (Integer lossSlot : lossSlotList) {\n                String key = slotHostPortMap.get(lossSlot);\n                if (hostPortSlotMap.containsKey(key)) {\n                    hostPortSlotMap.get(key).add(lossSlot);\n                } else {\n                    List<Integer> list = new ArrayList<Integer>();\n                    list.add(lossSlot);\n                    hostPortSlotMap.put(key, list);\n                }\n            }\n        }\n        // 3.2 hostPortSlotMap组装成Map<String host:port,String startSlot-endSlot>\n        Map<String, String> slotSegmentsMap = new HashMap<String, String>();\n        for (Entry<String, List<Integer>> entry : hostPortSlotMap.entrySet()) {\n            List<Integer> list = entry.getValue();\n            List<String> slotSegments = new ArrayList<String>();\n            int min = list.get(0);\n            int max = min;\n            for (int i = 1; i < list.size(); i++) {\n                int temp = list.get(i);\n                if (temp == max + 1) {\n                    max = temp;\n                } else {\n                    slotSegments.add(String.valueOf(min) + \"-\" + String.valueOf(max));\n                    min = temp;\n                    max = temp;\n                }\n            }\n            slotSegments.add(String.valueOf(min) + \"-\" + String.valueOf(max));\n            slotSegmentsMap.put(entry.getKey(), slotSegments.toString());\n        }\n        return slotSegmentsMap;\n    }\n\n    /**\n     * 从一个应用中获取一个健康的主节点\n     *\n     * @param appId\n     * @return\n     */\n    public InstanceInfo getHealthyInstanceInfo(long appId) {\n        InstanceInfo sourceMasterInstance = null;\n        List<InstanceInfo> appInstanceInfoList = instanceDao.getInstListByAppId(appId);\n        if (CollectionUtils.isEmpty(appInstanceInfoList)) {\n            logger.error(\"appId {} has not instances\", appId);\n            return null;\n        }\n        for (InstanceInfo instanceInfo : appInstanceInfoList) {\n            int instanceType = instanceInfo.getType();\n            if (!TypeUtil.isRedisCluster(instanceType)) {\n                continue;\n            }\n            final String host = instanceInfo.getIp();\n            final int port = instanceInfo.getPort();\n            if (instanceInfo.getStatus() != InstanceStatusEnum.GOOD_STATUS.getStatus()) {\n                continue;\n            }\n            boolean isRun = isRun(appId, host, port);\n            if (!isRun) {\n                logger.warn(\"{}:{} is not run\", host, port);\n                continue;\n            }\n            boolean isMaster = isMaster(appId, host, port);\n            if (!isMaster) {\n                logger.warn(\"{}:{} is not master\", host, port);\n                continue;\n            }\n            sourceMasterInstance = instanceInfo;\n            break;\n        }\n        return sourceMasterInstance;\n    }\n\n    /**\n     * 从一个应用中获取所有健康master节点\n     *\n     * @param appId\n     * @return 应用对应master节点列表\n     */\n    public List<InstanceInfo> getAllHealthyInstanceInfo(long appId) {\n        // return instances\n        List<InstanceInfo> allInstance = new ArrayList<InstanceInfo>();\n        List<InstanceInfo> appInstanceInfoList = instanceDao.getInstListByAppId(appId);\n        if (CollectionUtils.isEmpty(appInstanceInfoList)) {\n            logger.error(\"appId {} has not instances\", appId);\n            return null;\n        }\n        for (InstanceInfo instanceInfo : appInstanceInfoList) {\n            int instanceType = instanceInfo.getType();\n            if (!TypeUtil.isRedisCluster(instanceType)) {\n                continue;\n            }\n            final String host = instanceInfo.getIp();\n            final int port = instanceInfo.getPort();\n            if (instanceInfo.getStatus() != InstanceStatusEnum.GOOD_STATUS.getStatus()) {\n                continue;\n            }\n            boolean isRun = isRun(appId, host, port);\n            if (!isRun) {\n                logger.warn(\"{}:{} is not run\", host, port);\n                continue;\n            }\n            boolean isMaster = isMaster(appId, host, port);\n            if (!isMaster) {\n                logger.warn(\"{}:{} is not master\", host, port);\n                continue;\n            }\n            // add exist redis\n            allInstance.add(instanceInfo);\n        }\n        return allInstance;\n    }\n\n    /**\n     * clusterslots命令拼接成Map<Integer slot, String host:port>\n     *\n     * @param host\n     * @param port\n     * @return\n     */\n    private Map<Integer, String> getSlotsHostPortMap(long appId, String host, int port) {\n        Map<Integer, String> slotHostPortMap = new HashMap<Integer, String>();\n        Jedis jedis = null;\n        try {\n            jedis = getJedis(appId, host, port);\n            List<Object> slots = jedis.clusterSlots();\n            for (Object slotInfoObj : slots) {\n                List<Object> slotInfo = (List<Object>) slotInfoObj;\n                if (slotInfo.size() <= 2) {\n                    continue;\n                }\n                List<Integer> slotNums = getAssignedSlotArray(slotInfo);\n\n                // hostInfos\n                List<Object> hostInfos = (List<Object>) slotInfo.get(2);\n                if (hostInfos.size() <= 0) {\n                    continue;\n                }\n                HostAndPort targetNode = generateHostAndPort(hostInfos);\n\n                for (Integer slot : slotNums) {\n                    slotHostPortMap.put(slot, targetNode.getHost() + \":\" + targetNode.getPort());\n                }\n            }\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        } finally {\n            if (jedis != null) {\n                jedis.close();\n            }\n        }\n        return slotHostPortMap;\n    }\n\n    private HostAndPort generateHostAndPort(List<Object> hostInfos) {\n        return new HostAndPort(SafeEncoder.encode((byte[]) hostInfos.get(0)),\n                ((Long) hostInfos.get(1)).intValue());\n    }\n\n    private List<Integer> getAssignedSlotArray(List<Object> slotInfo) {\n        List<Integer> slotNums = new ArrayList<Integer>();\n        for (int slot = ((Long) slotInfo.get(0)).intValue(); slot <= ((Long) slotInfo.get(1))\n                .intValue(); slot++) {\n            slotNums.add(slot);\n        }\n        return slotNums;\n    }\n\n\n    @Override\n    public List<Integer> getClusterLossSlots(long appId, String host, int port) {\n        InstanceInfo instanceInfo = instanceDao.getAllInstByIpAndPort(host, port);\n        if (instanceInfo == null) {\n            logger.warn(\"{}:{} instanceInfo is null\", host, port);\n            return Collections.emptyList();\n        }\n        if (!TypeUtil.isRedisCluster(instanceInfo.getType())) {\n            logger.warn(\"{}:{} is not rediscluster type\", host, port);\n            return Collections.emptyList();\n        }\n        List<Integer> clusterLossSlots = new ArrayList<Integer>();\n        Jedis jedis = null;\n        try {\n            jedis = getJedis(appId, host, port, REDIS_DEFAULT_TIME, REDIS_DEFAULT_TIME);\n            String clusterNodes = jedis.clusterNodes();\n            if (StringUtils.isBlank(clusterNodes)) {\n                throw new RuntimeException(host + \":\" + port + \"clusterNodes is null\");\n            }\n            Set<Integer> allSlots = new LinkedHashSet<Integer>();\n            for (int i = 0; i <= 16383; i++) {\n                allSlots.add(i);\n            }\n\n            // 解析\n            ClusterNodeInformationParser nodeInfoParser = new ClusterNodeInformationParser();\n            for (String nodeInfo : clusterNodes.split(\"\\n\")) {\n                if (StringUtils.isNotBlank(nodeInfo) && !nodeInfo.contains(\"disconnected\")) {\n                    ClusterNodeInformation clusterNodeInfo = nodeInfoParser.parse(nodeInfo, new HostAndPort(host, port));\n                    List<Integer> availableSlots = clusterNodeInfo.getAvailableSlots();\n                    for (Integer slot : availableSlots) {\n                        allSlots.remove(slot);\n                    }\n                }\n            }\n            clusterLossSlots = new ArrayList<Integer>(allSlots);\n        } catch (Exception e) {\n            logger.error(\"getClusterLossSlots: \" + e.getMessage(), e);\n        } finally {\n            if (jedis != null) {\n                jedis.close();\n            }\n        }\n        return clusterLossSlots;\n    }\n\n    @Override\n    public List<Integer> getInstanceSlots(long appId, String healthHost, int healthPort, String lossSlotsHost, int lossSlotsPort) {\n        InstanceInfo instanceInfo = instanceDao.getAllInstByIpAndPort(healthHost, healthPort);\n        if (instanceInfo == null) {\n            logger.warn(\"{}:{} instanceInfo is null\", healthHost, healthPort);\n            return Collections.emptyList();\n        }\n        if (!TypeUtil.isRedisCluster(instanceInfo.getType())) {\n            logger.warn(\"{}:{} is not rediscluster type\", healthHost, healthPort);\n            return Collections.emptyList();\n        }\n        List<Integer> clusterLossSlots = new ArrayList<Integer>();\n        Jedis jedis = null;\n        try {\n        \t\tjedis = getJedis(appId, healthHost, healthPort, REDIS_DEFAULT_TIME, REDIS_DEFAULT_TIME);\n            String clusterNodes = jedis.clusterNodes();\n            if (StringUtils.isBlank(clusterNodes)) {\n                throw new RuntimeException(healthHost + \":\" + healthPort + \"clusterNodes is null\");\n            }\n            // 解析\n            ClusterNodeInformationParser nodeInfoParser = new ClusterNodeInformationParser();\n            for (String nodeInfo : clusterNodes.split(\"\\n\")) {\n                if (StringUtils.isNotBlank(nodeInfo) && nodeInfo.contains(\"disconnected\") && nodeInfo.contains(lossSlotsHost + \":\" + lossSlotsPort)) {\n                    ClusterNodeInformation clusterNodeInfo = nodeInfoParser.parse(nodeInfo, new HostAndPort(healthHost, healthPort));\n                    clusterLossSlots = clusterNodeInfo.getAvailableSlots();\n                }\n            }\n        } catch (Exception e) {\n            logger.error(\"getClusterLossSlots: \" + e.getMessage(), e);\n        } finally {\n            if (jedis != null) {\n                jedis.close();\n            }\n        }\n        return clusterLossSlots;\n    }\n\n\n    public void destory() {\n        for (JedisPool jedisPool : jedisPoolMap.values()) {\n            jedisPool.destroy();\n        }\n    }\n\n    @Override\n    public boolean deployRedisSlowLogCollection(long appId, String host, int port) {\n        Assert.isTrue(appId > 0);\n        Assert.hasText(host);\n        Assert.isTrue(port > 0);\n        Map<String, Object> dataMap = new HashMap<String, Object>();\n        dataMap.put(ConstUtils.HOST_KEY, host);\n        dataMap.put(ConstUtils.PORT_KEY, port);\n        dataMap.put(ConstUtils.APP_KEY, appId);\n        JobKey jobKey = JobKey.jobKey(ConstUtils.REDIS_SLOWLOG_JOB_NAME, ConstUtils.REDIS_SLOWLOG_JOB_GROUP);\n        TriggerKey triggerKey = TriggerKey.triggerKey(ObjectConvert.linkIpAndPort(host, port), ConstUtils.REDIS_SLOWLOG_TRIGGER_GROUP + appId);\n        boolean result = schedulerCenter.deployJobByCron(jobKey, triggerKey, dataMap, ScheduleUtil.getRedisSlowLogCron(appId), false);\n        return result;\n    }\n\n    @Override\n    public boolean unDeployRedisSlowLogCollection(long appId, String host, int port) {\n        Assert.isTrue(appId > 0);\n        Assert.hasText(host);\n        Assert.isTrue(port > 0);\n        TriggerKey triggerKey = TriggerKey.triggerKey(ObjectConvert.linkIpAndPort(host, port), ConstUtils.REDIS_SLOWLOG_TRIGGER_GROUP + appId);\n        Trigger trigger = schedulerCenter.getTrigger(triggerKey);\n        if (trigger == null) {\n            return true;\n        }\n        return schedulerCenter.unscheduleJob(triggerKey);\n    }\n\n    @Override\n    public List<InstanceSlowLog> getInstanceSlowLogByAppId(long appId) {\n        try {\n            return instanceSlowLogDao.getByAppId(appId);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return Collections.emptyList();\n        }\n    }\n\n\n    @Override\n    public List<InstanceSlowLog> getInstanceSlowLogByAppId(long appId, Date startDate, Date endDate) {\n        try {\n            return instanceSlowLogDao.search(appId, startDate, endDate);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return Collections.emptyList();\n        }\n    }\n\n    @Override\n    public Map<String, Long> getInstanceSlowLogCountMapByAppId(Long appId, Date startDate, Date endDate) {\n        try {\n            List<Map<String, Object>> list = instanceSlowLogDao.getInstanceSlowLogCountMapByAppId(appId, startDate, endDate);\n            if (CollectionUtils.isEmpty(list)) {\n                return Collections.emptyMap();\n            }\n            Map<String, Long> resultMap = new LinkedHashMap<String, Long>();\n            for (Map<String, Object> map : list) {\n                long count = MapUtils.getLongValue(map, \"count\");\n                String hostPort = MapUtils.getString(map, \"hostPort\");\n                if (StringUtils.isNotBlank(hostPort)) {\n                    resultMap.put(hostPort, count);\n                }\n            }\n            return resultMap;\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return Collections.emptyMap();\n        }\n    }\n\n    @Override\n    public Map<String, InstanceSlotModel> getClusterSlotsMap(long appId) {\n    \t\tAppDesc appDesc = appDao.getAppDescById(appId);\n    \t\tif (!TypeUtil.isRedisCluster(appDesc.getType())) {\n    \t\t\treturn Collections.emptyMap();\n    \t\t}\n\t\t// 最终结果\n\t\tMap<String, InstanceSlotModel> resultMap = new HashMap<String, InstanceSlotModel>();\n\n\t\t// 找到一个运行的节点用来执行cluster slots\n\t\tList<InstanceInfo> instanceList = instanceDao.getInstListByAppId(appId);\n\t\tString host = null;\n\t\tint port = 0;\n\t\tfor (InstanceInfo instanceInfo : instanceList) {\n\t\t\tif (instanceInfo.isOffline()) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\thost = instanceInfo.getIp();\n\t\t\tport = instanceInfo.getPort();\n\t\t\tboolean isRun = isRun(appId, host, port);\n\t\t\tif (isRun) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (StringUtils.isBlank(host) || port <= 0) {\n\t\t\treturn Collections.emptyMap();\n\t\t}\n\n\t\t// 获取cluster slots\n\t\tList<Object> clusterSlotList = null;\n\t\tJedis jedis = null;\n\t\ttry {\n\t\t\tjedis = getJedis(appId, host, port);\n\t\t\tclusterSlotList = jedis.clusterSlots();\n\t\t} catch (Exception e) {\n\t\t\tlogger.error(e.getMessage(), e);\n\t\t} finally {\n\t\t\tif (jedis != null)\n\t\t\t\tjedis.close();\n\t\t}\n\t\tif (clusterSlotList == null || clusterSlotList.size() == 0) {\n\t\t\treturn Collections.emptyMap();\n\t\t}\n\t\t//clusterSlotList形如：\n//\t\t[0, 1, [[B@5caf905d, 6380], [[B@27716f4, 6379]]\n//\t\t[3, 4096, [[B@8efb846, 6380], [[B@2a84aee7, 6379]]\n//\t\t[12291, 16383, [[B@a09ee92, 6383], [[B@30f39991, 6382]]\n//\t\t[2, 2, [[B@452b3a41, 6381], [[B@4a574795, 6382]]\n//\t\t[8194, 12290, [[B@f6f4d33, 6381], [[B@23fc625e, 6382]]\n//\t\t[4097, 8193, [[B@3f99bd52, 6380], [[B@4f023edb, 6381]]\n\n\t\tfor (Object clusterSlotObj : clusterSlotList) {\n\t\t\tList<Object> slotInfoList = (List<Object>) clusterSlotObj;\n\t\t\tif (slotInfoList.size() <= 2) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t//获取slot的start到end相关\n\t\t\tint startSlot = ((Long) slotInfoList.get(0)).intValue();\n\t\t\tint endSlot = ((Long) slotInfoList.get(1)).intValue();\n\t\t\tString slotDistribute = getStartToEndSlotDistribute(startSlot, endSlot);\n\t\t\tList<Integer> slotList = getStartToEndSlotList(startSlot, endSlot);\n\n\t\t\tList<Object> masterInfoList = (List<Object>) slotInfoList.get(2);\n\t\t\tString tempHost = SafeEncoder.encode((byte[]) masterInfoList.get(0));\n\t\t\tint tempPort = ((Long) masterInfoList.get(1)).intValue();\n\t\t\tString hostPort = tempHost + \":\" + tempPort;\n\t\t\tif (resultMap.containsKey(hostPort)) {\n\t\t\t\tInstanceSlotModel instanceSlotModel = resultMap.get(hostPort);\n\t\t\t\tinstanceSlotModel.getSlotDistributeList().add(slotDistribute);\n\t\t\t\tinstanceSlotModel.getSlotList().addAll(slotList);\n\t\t\t} else {\n\t\t\t\tInstanceSlotModel instanceSlotModel = new InstanceSlotModel();\n\t\t\t\tinstanceSlotModel.setHost(tempHost);\n\t\t\t\tinstanceSlotModel.setPort(tempPort);\n\t\t\t\tList<String> slotDistributeList = new ArrayList<String>();\n\t\t\t\tslotDistributeList.add(slotDistribute);\n\t\t\t\tinstanceSlotModel.setSlotDistributeList(slotDistributeList);\n\t\t\t\tinstanceSlotModel.setSlotList(slotList);\n\t\t\t\tresultMap.put(hostPort, instanceSlotModel);\n\t\t\t}\n\t\t}\n\t\treturn resultMap;\n\t}\n\n\t/**\n\t * 获取slot列表\n\t * @param startSlot\n\t * @param endSlot\n\t * @return\n\t */\n\tprivate List<Integer> getStartToEndSlotList(int startSlot, int endSlot) {\n\t\tList<Integer> slotList = new ArrayList<Integer>();\n\t\tif (startSlot == endSlot) {\n\t\t\tslotList.add(startSlot);\n\t\t} else {\n\t\t\tfor (int i = startSlot; i <= endSlot; i++) {\n\t\t\t\tslotList.add(i);\n\t\t\t}\n\t\t}\n\t\treturn slotList;\n\t}\n\n\t/**\n     * 0,4096 0-4096\n     * 2,2 2-2\n     * @param slotInfo\n     * @return\n     */\n\tprivate String getStartToEndSlotDistribute(int startSlot, int endSlot) {\n\t\tif (startSlot == endSlot) {\n\t\t\treturn String.valueOf(startSlot);\n\t\t} else {\n\t\t\treturn startSlot + \"-\" + endSlot;\n\t\t}\n    }\n\t\n\t@Override\n    public String getRedisVersion(long appId, String ip, int port) {\n\t    Map<RedisConstant, Map<String, Object>> infoAllMap = getInfoStats(appId, ip, port);\n\t    if (MapUtils.isEmpty(infoAllMap)) {\n\t        return null;\n\t    }\n\t    Map<String, Object> serverMap = infoAllMap.get(RedisConstant.Server);\n\t    if (MapUtils.isEmpty(serverMap)) {\n            return null;\n        }\n\t    return MapUtils.getString(serverMap, \"redis_version\");\n    }\n\t\n\t@Override\n\tpublic String getNodeId(long appId, String ip, int port) {\n        final Jedis jedis = getJedis(appId, ip, port);\n        try {\n            final StringBuilder clusterNodes = new StringBuilder();\n            boolean isGetNodes = new IdempotentConfirmer() {\n                @Override\n                public boolean execute() {\n                    String nodes = jedis.clusterNodes();\n                    if (nodes != null && nodes.length() > 0) {\n                        clusterNodes.append(nodes);\n                        return true;\n                    }\n                    return false;\n                }\n            }.run();\n            if (!isGetNodes) {\n                logger.error(\"{}:{} clusterNodes failed\", jedis.getClient().getHost(), jedis.getClient().getPort());\n                return null;\n            }\n            for (String infoLine : clusterNodes.toString().split(\"\\n\")) {\n                if (infoLine.contains(\"myself\")) {\n                    String nodeId = infoLine.split(\" \")[0];\n                    return nodeId;\n                }\n            }\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        } finally {\n            if (jedis != null)\n                jedis.close();\n        }\n        return null;\n    }\n\t\n    public void setSchedulerCenter(SchedulerCenter schedulerCenter) {\n        this.schedulerCenter = schedulerCenter;\n    }\n\n    public void setInstanceStatsCenter(InstanceStatsCenter instanceStatsCenter) {\n        this.instanceStatsCenter = instanceStatsCenter;\n    }\n\n    public void setAppStatsDao(AppStatsDao appStatsDao) {\n        this.appStatsDao = appStatsDao;\n    }\n\n    public void setAsyncService(AsyncService asyncService) {\n        this.asyncService = asyncService;\n    }\n\n    public void setInstanceDao(InstanceDao instanceDao) {\n        this.instanceDao = instanceDao;\n    }\n\n    public void setInstanceStatsDao(InstanceStatsDao instanceStatsDao) {\n        this.instanceStatsDao = instanceStatsDao;\n    }\n\n    public void setMachineCenter(MachineCenter machineCenter) {\n        this.machineCenter = machineCenter;\n    }\n\n    public void setAppDao(AppDao appDao) {\n        this.appDao = appDao;\n    }\n\n    public void setAppAuditLogDao(AppAuditLogDao appAuditLogDao) {\n        this.appAuditLogDao = appAuditLogDao;\n    }\n\n    public void setInstanceSlowLogDao(InstanceSlowLogDao instanceSlowLogDao) {\n        this.instanceSlowLogDao = instanceSlowLogDao;\n    }\n    \n    @Override\n\tpublic Jedis getJedis(long appId, String host, int port) {\n\t\treturn getJedis(appId, host, port, Protocol.DEFAULT_TIMEOUT, Protocol.DEFAULT_TIMEOUT);\n\t}\n\n\t@Override\n\tpublic Jedis getJedis(long appId, String host, int port, int connectionTimeout, int soTimeout) {\n\t\tAppDesc appDesc = appDao.getAppDescById(appId);\n\t\tString password = appDesc.getPassword();\n\t\tJedis jedis = new Jedis(host, port);\n\t\tjedis.getClient().setConnectionTimeout(connectionTimeout);\n\t\tjedis.getClient().setSoTimeout(soTimeout);\n\t\tif (StringUtils.isNotBlank(password)) {\n\t\t\tjedis.auth(password);\n\t\t}\n\t\treturn jedis;\n\t}\n\n\t@Override\n\tpublic Jedis getJedis(String host, int port, String password) {\n\t\tJedis jedis = new Jedis(host, port);\n\t\tjedis.getClient().setConnectionTimeout(Protocol.DEFAULT_TIMEOUT);\n\t\tjedis.getClient().setSoTimeout(Protocol.DEFAULT_TIMEOUT);\n\t\tif (StringUtils.isNotBlank(password)) {\n\t\t\tjedis.auth(password);\n\t\t}\n\t\treturn jedis;\n\t}\n\t\n\t@Override\n\tpublic Jedis getJedis(String host, int port) {\n\t\treturn getJedis(host, port, null);\n\t}\n\n    \n\n\t\n\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/redis/impl/RedisConfigTemplateServiceImpl.java",
    "content": "package com.sohu.cache.redis.impl;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Random;\n\nimport org.apache.commons.collections.CollectionUtils;\nimport org.apache.commons.lang.StringUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.sohu.cache.dao.InstanceConfigDao;\nimport com.sohu.cache.entity.InstanceConfig;\nimport com.sohu.cache.protocol.MachineProtocol;\nimport com.sohu.cache.redis.RedisConfigTemplateService;\nimport com.sohu.cache.redis.enums.RedisClusterConfigEnum;\nimport com.sohu.cache.redis.enums.RedisConfigEnum;\nimport com.sohu.cache.redis.enums.RedisSentinelConfigEnum;\nimport com.sohu.cache.util.ConstUtils;\n\n/**\n * redis配置模板服务\n * \n * @author leifu\n * @Date 2016年6月23日\n * @Time 下午2:08:03\n */\npublic class RedisConfigTemplateServiceImpl implements RedisConfigTemplateService {\n\n    private Logger logger = LoggerFactory.getLogger(RedisConfigTemplateServiceImpl.class);\n    \n    private final static String SPECIAL_EMPTY_STR = \"\\\"\\\"\";\n\n    private InstanceConfigDao instanceConfigDao;\n    \n    @Override\n    public List<InstanceConfig> getAllInstanceConfig() {\n        try {\n            return instanceConfigDao.getAllInstanceConfig();\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return Collections.emptyList();\n        }\n    }\n\n    @Override\n    public List<InstanceConfig> getByType(int type) {\n        try {\n            return instanceConfigDao.getByType(type);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return Collections.emptyList();\n        }\n    }\n\n    @Override\n    public int saveOrUpdate(InstanceConfig instanceConfig) {\n        return instanceConfigDao.saveOrUpdate(instanceConfig);\n    }\n\n    @Override\n    public InstanceConfig getById(long id) {\n        try {\n            return instanceConfigDao.getById(id);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return null;\n        }\n    }\n\n    @Override\n    public InstanceConfig getByConfigKeyAndType(String configKey, int type) {\n        try {\n            return instanceConfigDao.getByConfigKeyAndType(configKey, type);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return null;\n        }\n    }\n    \n    @Override\n    public int remove(long id) {\n        return instanceConfigDao.remove(id);\n    }\n\n    @Override\n    public int updateStatus(long id, int status) {\n        return instanceConfigDao.updateStatus(id, status);\n    }\n\n\n    @Override\n    public List<String> handleCommonConfig(int port, int maxMemory) {\n        List<InstanceConfig> instanceConfigList = getByType(ConstUtils.CACHE_REDIS_STANDALONE);\n        if (CollectionUtils.isEmpty(instanceConfigList)) {\n            return Collections.emptyList();\n        }\n        List<String> configs = new ArrayList<String>();\n        for (InstanceConfig instanceConfig : instanceConfigList) {\n            // 无效配置过滤\n            if (!instanceConfig.isEffective()) {\n                continue;\n            }\n            String configKey = instanceConfig.getConfigKey();\n            String configValue = instanceConfig.getConfigValue();\n            if (StringUtils.isBlank(configValue)) {\n                configValue = SPECIAL_EMPTY_STR;\n            }\n            if (RedisConfigEnum.MAXMEMORY.getKey().equals(configKey)) {\n                configValue = String.format(configValue, maxMemory);\n            } else if (RedisConfigEnum.DBFILENAME.getKey().equals(configKey) \n                    || RedisConfigEnum.APPENDFILENAME.getKey().equals(configKey) || RedisConfigEnum.PORT.getKey().equals(configKey)) {\n                configValue = String.format(configValue, port);\n            } else if (RedisConfigEnum.DIR.getKey().equals(configKey)) {\n                configValue = MachineProtocol.DATA_DIR;\n            } else if (RedisConfigEnum.AUTO_AOF_REWRITE_PERCENTAGE.getKey().equals(configKey)) {\n                //随机比例 auto-aof-rewrite-percentage\n                int percent = 69 + new Random().nextInt(30);\n                configValue = String.format(configValue, percent);\n            }\n            configs.add(combineConfigKeyValue(configKey, configValue));\n        }\n        return configs;\n    }\n\n    @Override\n    public List<String> handleSentinelConfig(String masterName, String host, int port, int sentinelPort) {\n        List<InstanceConfig> instanceConfigList = instanceConfigDao.getByType(ConstUtils.CACHE_REDIS_SENTINEL);\n        if (CollectionUtils.isEmpty(instanceConfigList)) {\n            return Collections.emptyList();\n        }\n        List<String> configs = new ArrayList<String>();\n        for (InstanceConfig instanceConfig : instanceConfigList) {\n            if (!instanceConfig.isEffective()) {\n                continue;\n            }\n            String configKey = instanceConfig.getConfigKey();\n            String configValue = instanceConfig.getConfigValue();\n            if (StringUtils.isBlank(configValue)) {\n                configValue = SPECIAL_EMPTY_STR;\n            }\n            if (RedisSentinelConfigEnum.PORT.getKey().equals(configKey)) {\n                configValue = String.format(configValue, sentinelPort);\n            } else if(RedisSentinelConfigEnum.MONITOR.getKey().equals(configKey)) {\n                configValue = String.format(configValue, masterName, host, port);\n            } else if(RedisSentinelConfigEnum.DOWN_AFTER_MILLISECONDS.getKey().equals(configKey) || RedisSentinelConfigEnum.FAILOVER_TIMEOUT.getKey().equals(configKey) || RedisSentinelConfigEnum.PARALLEL_SYNCS.getKey().equals(configKey)) {\n                configValue = String.format(configValue, masterName);\n            } else if (RedisConfigEnum.DIR.getKey().equals(configKey)) {\n                configValue = MachineProtocol.DATA_DIR;\n            } \n            configs.add(combineConfigKeyValue(configKey, configValue));\n        }\n        return configs;\n    }\n\n    @Override\n    public List<String> handleClusterConfig(int port) {\n        List<InstanceConfig> instanceConfigList = getByType(ConstUtils.CACHE_TYPE_REDIS_CLUSTER);\n        if (CollectionUtils.isEmpty(instanceConfigList)) {\n            return Collections.emptyList();\n        }\n        List<String> configs = new ArrayList<String>();\n        for (InstanceConfig instanceConfig : instanceConfigList) {\n            if (!instanceConfig.isEffective()) {\n                continue;\n            }\n            String configKey = instanceConfig.getConfigKey();\n            String configValue = instanceConfig.getConfigValue();\n            if (StringUtils.isBlank(configValue)) {\n                configValue = SPECIAL_EMPTY_STR;\n            }\n            if (RedisClusterConfigEnum.CLUSTER_CONFIG_FILE.getKey().equals(configKey)) {\n                configValue = String.format(configValue, port);\n            }\n            configs.add(combineConfigKeyValue(configKey, configValue));\n\n        }\n        return configs;\n    }\n    \n    @Override\n    public List<String> handleCommonDefaultConfig(int port, int maxMemory) {\n        List<String> configs = new ArrayList<String>();\n        for (RedisConfigEnum config : RedisConfigEnum.values()) {\n            if (RedisConfigEnum.MAXMEMORY.equals(config)) {\n                configs.add(config.getKey() + \" \" + String.format(config.getValue(), maxMemory));\n            } else if (RedisConfigEnum.DBFILENAME.equals(config) ||\n                    RedisConfigEnum.APPENDFILENAME.equals(config) || RedisConfigEnum.PORT.equals(config)) {\n                configs.add(config.getKey() + \" \" + String.format(config.getValue(), port));\n            } else if (RedisConfigEnum.DIR.equals(config)) {\n                configs.add(config.getKey() + \" \" + MachineProtocol.DATA_DIR);\n            } else if (RedisConfigEnum.AUTO_AOF_REWRITE_PERCENTAGE.equals(config)) {\n                //随机比例 auto-aof-rewrite-percentage\n                int percent = 69 + new Random().nextInt(30);\n                configs.add(config.getKey() + \" \" + String.format(RedisConfigEnum.AUTO_AOF_REWRITE_PERCENTAGE.getValue(), percent));\n            } else {\n                configs.add(config.getKey() + \" \" + config.getValue());\n            }\n        }\n        return configs;\n    }\n\n    @Override\n    public List<String> handleSentinelDefaultConfig(String masterName, String host, int port, int sentinelPort) {\n        List<String> configs = new ArrayList<String>();\n        configs.add(RedisSentinelConfigEnum.PORT.getKey() + \" \" + String.format(RedisSentinelConfigEnum.PORT.getValue(), sentinelPort));\n        configs.add(RedisSentinelConfigEnum.DIR.getKey() + \" \" + RedisSentinelConfigEnum.DIR.getValue());\n        configs.add(RedisSentinelConfigEnum.MONITOR.getKey() + \" \" + String.format(RedisSentinelConfigEnum.MONITOR.getValue(), masterName, host, port, 1));\n        configs.add(RedisSentinelConfigEnum.DOWN_AFTER_MILLISECONDS.getKey() + \" \" + String\n                .format(RedisSentinelConfigEnum.DOWN_AFTER_MILLISECONDS.getValue(), masterName));\n        configs.add(RedisSentinelConfigEnum.FAILOVER_TIMEOUT.getKey() + \" \" + String\n                .format(RedisSentinelConfigEnum.FAILOVER_TIMEOUT.getValue(), masterName));\n        configs.add(RedisSentinelConfigEnum.PARALLEL_SYNCS.getKey() + \" \" + String\n                .format(RedisSentinelConfigEnum.PARALLEL_SYNCS.getValue(), masterName));\n        return configs;\n    }\n\n    @Override\n    public List<String> handleClusterDefaultConfig(int port) {\n        List<String> configs = new ArrayList<String>();\n        for (RedisClusterConfigEnum config : RedisClusterConfigEnum.values()) {\n            if (config.equals(RedisClusterConfigEnum.CLUSTER_CONFIG_FILE)) {\n                configs.add(RedisClusterConfigEnum.CLUSTER_CONFIG_FILE.getKey() + \" \"\n                        + String.format(RedisClusterConfigEnum.CLUSTER_CONFIG_FILE.getValue(), port));\n            } else {\n                configs.add(config.getKey() + \" \"\n                        + config.getValue());\n            }\n        }\n        return configs;\n    }\n\n    /**\n     * 组合\n     * @param configKey\n     * @param configValue\n     * @return\n     */\n    private String combineConfigKeyValue(String configKey, String configValue) {\n        return configKey + ConstUtils.SPACE + configValue;\n    }\n\n    public void setInstanceConfigDao(InstanceConfigDao instanceConfigDao) {\n        this.instanceConfigDao = instanceConfigDao;\n    }\n\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/redis/impl/RedisDeployCenterImpl.java",
    "content": "package com.sohu.cache.redis.impl;\n\nimport com.sohu.cache.constant.ClusterOperateResult;\nimport com.sohu.cache.constant.InstanceStatusEnum;\nimport com.sohu.cache.dao.AppDao;\nimport com.sohu.cache.dao.InstanceDao;\nimport com.sohu.cache.dao.MachineDao;\nimport com.sohu.cache.entity.AppDesc;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.entity.InstanceSlotModel;\nimport com.sohu.cache.entity.MachineInfo;\nimport com.sohu.cache.machine.MachineCenter;\nimport com.sohu.cache.protocol.MachineProtocol;\nimport com.sohu.cache.protocol.RedisProtocol;\nimport com.sohu.cache.redis.RedisCenter;\nimport com.sohu.cache.redis.RedisClusterNode;\nimport com.sohu.cache.redis.RedisConfigTemplateService;\nimport com.sohu.cache.redis.RedisDeployCenter;\nimport com.sohu.cache.redis.enums.RedisConfigEnum;\nimport com.sohu.cache.stats.instance.InstanceDeployCenter;\nimport com.sohu.cache.util.ConstUtils;\nimport com.sohu.cache.util.IdempotentConfirmer;\nimport com.sohu.cache.util.TypeUtil;\nimport com.sohu.cache.web.enums.RedisOperateEnum;\n\nimport org.apache.commons.collections.CollectionUtils;\nimport org.apache.commons.lang.StringUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.util.Assert;\n\nimport redis.clients.jedis.Jedis;\nimport redis.clients.jedis.JedisSentinelPool;\nimport redis.clients.jedis.Protocol;\nimport redis.clients.jedis.exceptions.JedisDataException;\n\nimport java.util.*;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * Created by yijunzhang on 14-8-25.\n */\npublic class RedisDeployCenterImpl implements RedisDeployCenter {\n    private final Logger logger = LoggerFactory.getLogger(this.getClass());\n\n    private InstanceDao instanceDao;\n\n    private MachineDao machineDao;\n\n    private MachineCenter machineCenter;\n\n    private RedisCenter redisCenter;\n\n    private AppDao appDao;\n    \n    private RedisConfigTemplateService redisConfigTemplateService;\n    \n    private InstanceDeployCenter instanceDeployCenter;\n    \n    @Override\n    public boolean deployClusterInstance(long appId, List<RedisClusterNode> clusterNodes, int maxMemory) {\n        if (!isExist(appId)) {\n            return false;\n        }\n        AppDesc appDesc = appDao.getAppDescById(appId);\n        String host = null;\n        Integer port = null;\n        Map<Jedis, Jedis> clusterMap = new LinkedHashMap<Jedis, Jedis>();\n        for (RedisClusterNode node : clusterNodes) {\n            String masterHost = node.getMasterHost();\n            String slaveHost = node.getSlaveHost();\n            Integer masterPort = machineCenter.getAvailablePort(masterHost, ConstUtils.CACHE_TYPE_REDIS_CLUSTER);\n            if (masterPort == null) {\n                logger.error(\"masterHost={} getAvailablePort is null\", masterHost);\n                return false;\n            }\n\n            if (host == null || port == null) {\n                host = masterHost;\n                port = masterPort;\n            }\n            boolean isMasterRun = runInstance(appDesc, masterHost, masterPort, maxMemory, true);\n            if (!isMasterRun) {\n                return false;\n            }\n            if (StringUtils.isNotBlank(slaveHost)) {\n                Integer slavePort = machineCenter.getAvailablePort(slaveHost, ConstUtils.CACHE_TYPE_REDIS_CLUSTER);\n                if (slavePort == null) {\n                    logger.error(\"slavePort={} getAvailablePort is null\", slavePort);\n                    return false;\n                }\n                boolean isSlaveRun = runInstance(appDesc, slaveHost, slavePort, maxMemory, true);\n                if (!isSlaveRun) {\n                    return false;\n                }\n                clusterMap.put(redisCenter.getJedis(appId, masterHost, masterPort), redisCenter.getJedis(appId, slaveHost, slavePort));\n            } else {\n                clusterMap.put(redisCenter.getJedis(appId, masterHost, masterPort), null);\n            }\n        }\n\n        boolean isCluster;\n        try {\n            isCluster = startCluster(appId, clusterMap);\n            if (!isCluster) {\n                logger.error(\"startCluster create error!\");\n                return false;\n            }\n            for (Map.Entry<Jedis, Jedis> entry : clusterMap.entrySet()) {\n                Jedis master = entry.getKey();\n                Jedis slave = entry.getValue();\n                //保存实例信息 & 触发收集\n                saveInstance(appId, master.getClient().getHost(),\n                        master.getClient().getPort(), maxMemory, ConstUtils.CACHE_TYPE_REDIS_CLUSTER, \"\");\n                redisCenter.deployRedisCollection(appId, master.getClient().getHost(), master.getClient().getPort());\n                if (slave != null) {\n                    saveInstance(appId, slave.getClient().getHost(), slave.getClient().getPort(),\n                            maxMemory, ConstUtils.CACHE_TYPE_REDIS_CLUSTER, \"\");\n                    redisCenter.deployRedisCollection(appId, slave.getClient().getHost(), slave.getClient().getPort());\n                }\n            }\n        } finally {\n            //关闭jedis连接\n            for (Jedis master : clusterMap.keySet()) {\n                master.close();\n                if (clusterMap.get(master) != null) {\n                    clusterMap.get(master).close();\n                }\n            }\n        }\n\n        return true;\n    }\n\n    private boolean clusterMeet(Jedis jedis, long appId, String host, int port) {\n        boolean isSingleNode = redisCenter.isSingleClusterNode(appId, host, port);\n        if (!isSingleNode) {\n            logger.error(\"{}:{} isNotSingleNode\", host, port);\n            return false;\n        } else {\n            logger.warn(\"{}:{} isSingleNode\", host, port);\n        }\n\n        String response = jedis.clusterMeet(host, port);\n        boolean isMeet = response != null && response.equalsIgnoreCase(\"OK\");\n        if (!isMeet) {\n            logger.error(\"{}:{} meet error\", host, port);\n            return false;\n        }\n        return true;\n    }\n\n    private boolean startCluster(final long appId, Map<Jedis, Jedis> clusterMap) {\n        final Jedis jedis = new ArrayList<Jedis>(clusterMap.keySet()).get(0);\n        //meet集群节点\n        for (final Jedis master : clusterMap.keySet()) {\n            boolean isMeet = new IdempotentConfirmer() {\n\n                @Override\n                public boolean execute() {\n                    boolean isMeet = clusterMeet(jedis, appId, master.getClient().getHost(), master.getClient().getPort());\n                    if (!isMeet) {\n                        return false;\n                    }\n                    return true;\n                }\n            }.run();\n            if (!isMeet) {\n                return false;\n            }\n            final Jedis slave = clusterMap.get(master);\n            if (slave != null) {\n                isMeet = new IdempotentConfirmer() {\n                    @Override\n                    public boolean execute() {\n                        boolean isMeet = clusterMeet(jedis, appId, slave.getClient().getHost(), slave.getClient().getPort());\n                        if (!isMeet) {\n                            return false;\n                        }\n                        return true;\n                    }\n                }.run();\n                if (!isMeet) {\n                    return false;\n                }\n            }\n        }\n        int masterSize = clusterMap.size();\n        int perSize = (int) Math.ceil(16384 / masterSize);\n        int index = 0;\n        int masterIndex = 0;\n        final ArrayList<Integer> slots = new ArrayList<Integer>();\n        List<Jedis> masters = new ArrayList<Jedis>(clusterMap.keySet());\n        //分配slot\n        for (int slot = 0; slot <= 16383; slot++) {\n            slots.add(slot);\n            if (index++ >= perSize || slot == 16383) {\n                final int[] slotArr = new int[slots.size()];\n                for (int i = 0; i < slotArr.length; i++) {\n                    slotArr[i] = slots.get(i);\n                }\n                final Jedis masterJedis = masters.get(masterIndex++);\n                boolean isSlot = new IdempotentConfirmer() {\n                    @Override\n                    public boolean execute() {\n                        String response = masterJedis.clusterAddSlots(slotArr);\n                        boolean isSlot = response != null && response.equalsIgnoreCase(\"OK\");\n                        if (!isSlot) {\n                            return false;\n                        }\n                        return true;\n                    }\n                }.run();\n                if (!isSlot) {\n                    logger.error(\"{}:{} set slots:{}\", masterJedis.getClient().getHost(),\n                            masterJedis.getClient().getPort(), slots);\n                    return false;\n                }\n                slots.clear();\n                index = 0;\n            }\n        }\n        //设置从节点\n        for (Jedis masterJedis : clusterMap.keySet()) {\n            final Jedis slaveJedis = clusterMap.get(masterJedis);\n            if (slaveJedis == null) {\n                continue;\n            }\n            final String nodeId = getClusterNodeId(masterJedis);\n            boolean isReplicate = new IdempotentConfirmer() {\n                @Override\n                public boolean execute() {\n                    try {\n                        //等待广播节点\n                        TimeUnit.SECONDS.sleep(2);\n                    } catch (Exception e) {\n                        logger.error(e.getMessage(), e);\n                    }\n                    String response = null;\n                    try {\n                        response = slaveJedis.clusterReplicate(nodeId);\n                    } catch (Exception e) {\n                        logger.error(e.getMessage(), e);\n                    }\n                    boolean isReplicate = response != null && response.equalsIgnoreCase(\"OK\");\n                    if (!isReplicate) {\n                        try {\n                            //等待广播节点\n                            TimeUnit.SECONDS.sleep(2);\n                        } catch (Exception e) {\n                            logger.error(e.getMessage(), e);\n                        }\n                        return false;\n                    }\n                    return true;\n                }\n            }.run();\n\n            if (!isReplicate) {\n                logger.error(\"{}:{} set replicate:{}\", slaveJedis.getClient().getHost(),\n                        slaveJedis.getClient().getPort());\n                return false;\n            }\n        }\n\n        return true;\n    }\n\n    private String getClusterNodeId(Jedis jedis) {\n        try {\n            String infoOutput = jedis.clusterNodes();\n            for (String infoLine : infoOutput.split(\"\\n\")) {\n                if (infoLine.contains(\"myself\")) {\n                    return infoLine.split(\" \")[0];\n                }\n            }\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n        return null;\n    }\n\n    @Override\n    public boolean deploySentinelInstance(long appId, String masterHost, String slaveHost, int maxMemory, List<String> sentinelList) {\n        if (!isExist(appId)) {\n            return false;\n        }\n        AppDesc appDesc = appDao.getAppDescById(appId);\n        //获取端口\n        Integer masterPort = machineCenter.getAvailablePort(masterHost, ConstUtils.CACHE_REDIS_STANDALONE);\n        if (masterPort == null) {\n            logger.error(\"masterHost={} getAvailablePort is null\", masterHost);\n            return false;\n        }\n        Integer slavePort = machineCenter.getAvailablePort(slaveHost, ConstUtils.CACHE_REDIS_STANDALONE);\n        if (slavePort == null) {\n            logger.error(\"slaveHost={} getAvailablePort is null\", slavePort);\n            return false;\n        }\n        //运行实例\n        boolean isMasterRun = runInstance(appDesc, masterHost, masterPort, maxMemory, false);\n        if (!isMasterRun) {\n            return false;\n        }\n        boolean isSlaveRun = runInstance(appDesc, slaveHost, slavePort, maxMemory, false);\n        if (!isSlaveRun) {\n            return false;\n        }\n        //添加slaveof配置\n        boolean isSlave = slaveOf(appDesc.getAppId(), masterHost, masterPort, slaveHost, slavePort);\n        if (!isSlave) {\n            return false;\n        }\n\n        //运行sentinel实例组\n        boolean isRunSentinel = runSentinelGroup(appDesc, sentinelList, masterHost, masterPort, appId, appDesc.getPassword());\n        if (!isRunSentinel) {\n            return false;\n        }\n\n        //写入instanceInfo 信息\n        saveInstance(appId, masterHost, masterPort, maxMemory,\n                ConstUtils.CACHE_REDIS_STANDALONE, \"\");\n        saveInstance(appId, slaveHost, slavePort, maxMemory, ConstUtils.CACHE_REDIS_STANDALONE, \"\");\n\n        //启动监控trigger\n        boolean isMasterDeploy = redisCenter.deployRedisCollection(appId, masterHost, masterPort);\n        boolean isSlaveDeploy = redisCenter.deployRedisCollection(appId, slaveHost, slavePort);\n        if (!isMasterDeploy) {\n            logger.warn(\"host={},port={},isMasterDeploy=false\", masterHost, masterPort);\n        }\n        if (!isSlaveDeploy) {\n            logger.warn(\"host={},port={},isSlaveDeploy=false\", slaveHost, slavePort);\n        }\n        return true;\n    }\n\n    @Override\n    public boolean deployStandaloneInstance(long appId, String host, int maxMemory) {\n        if (!isExist(appId)) {\n            return false;\n        }\n        AppDesc appDesc = appDao.getAppDescById(appId);\n        //获取端口\n        Integer port = machineCenter.getAvailablePort(host, ConstUtils.CACHE_REDIS_STANDALONE);\n        if (port == null) {\n            logger.error(\"masterHost={} getAvailablePort is null\", host);\n            return false;\n        }\n\n        //运行实例\n        boolean isMasterRun = runInstance(appDesc, host, port, maxMemory, false);\n        if (!isMasterRun) {\n            return false;\n        }\n\n        //写入instanceInfo 信息\n        saveInstance(appId, host, port, maxMemory, ConstUtils.CACHE_REDIS_STANDALONE,\n                \"\");\n\n        //启动监控trigger\n        boolean isMasterDeploy = redisCenter.deployRedisCollection(appId, host, port);\n        if (!isMasterDeploy) {\n            logger.warn(\"host={},port={},isMasterDeploy=false\", host, port);\n        }\n        return true;\n    }\n\n    private InstanceInfo saveInstance(long appId, String host, int port, int maxMemory, int type,\n            String cmd) {\n        InstanceInfo instanceInfo = new InstanceInfo();\n        instanceInfo.setAppId(appId);\n        MachineInfo machineInfo = machineDao.getMachineInfoByIp(host);\n        instanceInfo.setHostId(machineInfo.getId());\n        instanceInfo.setConn(0);\n        instanceInfo.setMem(maxMemory);\n        instanceInfo.setStatus(InstanceStatusEnum.GOOD_STATUS.getStatus());\n        instanceInfo.setPort(port);\n        instanceInfo.setType(type);\n        instanceInfo.setCmd(cmd);\n        instanceInfo.setIp(host);\n        instanceDao.saveInstance(instanceInfo);\n        return instanceInfo;\n    }\n\n    private boolean runSentinelGroup(AppDesc appDesc, List<String> sentinelList, String masterHost, int masterPort, long appId, String password) {\n        for (String sentinelHost : sentinelList) {\n            boolean isRun = runSentinel(appDesc, sentinelHost, getMasterName(masterHost, masterPort), masterHost, masterPort);\n            if (!isRun) {\n                return false;\n            }\n        }\n        return true;\n    }\n\n    @Override\n    public boolean createRunNode(AppDesc appDesc, String host, Integer port, int maxMemory, boolean isCluster) {\n        return runInstance(appDesc, host, port, maxMemory, isCluster);\n    }\n\n    private boolean runInstance(AppDesc appDesc, String host, Integer port, int maxMemory, boolean isCluster) {\n    \t\tlong appId = appDesc.getAppId();\n    \t\tString password = appDesc.getPassword();\n        // 生成配置\n        List<String> configs = handleCommonConfig(port, maxMemory);\n        if (isCluster) {\n            configs.addAll(handleClusterConfig(port));\n        }\n        if (StringUtils.isNotBlank(password)) {\n\t        \t//加两个选项\n\t    \t\tconfigs.add(RedisConfigEnum.REQUIREPASS.getKey() + ConstUtils.SPACE + password);\n\t    \t\tconfigs.add(RedisConfigEnum.MASTERAUTH.getKey() + ConstUtils.SPACE + password);\n        }\n        printConfig(configs);\n        String fileName;\n        String runShell;\n        if (isCluster) {\n            runShell = RedisProtocol.getRunShell(port, true);\n            fileName = RedisProtocol.getConfig(port, true);\n        } else {\n            runShell = RedisProtocol.getRunShell(port, false);\n            fileName = RedisProtocol.getConfig(port, false);\n        }\n        String pathFile = machineCenter.createRemoteFile(host, fileName, configs);\n        if (StringUtils.isBlank(pathFile)) {\n            logger.error(\"createFile={} error\", pathFile);\n            return false;\n        }\n        if (isCluster) {\n            //删除cluster节点配置\n            String deleteNodeShell = String.format(\"rm -rf %s/nodes-%s.conf\", MachineProtocol.DATA_DIR, port);\n            String deleteNodeResult = machineCenter.executeShell(host, deleteNodeShell);\n            if (!ConstUtils.INNER_ERROR.equals(deleteNodeResult)) {\n                logger.warn(\"runDeleteNodeShell={} at host {}\", deleteNodeShell, host);\n            }\n        }\n        //启动实例\n        logger.info(\"masterShell:host={};shell={}\", host, runShell);\n        boolean isMasterShell = machineCenter.startProcessAtPort(host, port, runShell);\n        if (!isMasterShell) {\n            logger.error(\"runShell={} error,{}:{}\", runShell, host, port);\n            return false;\n        }\n        //验证实例\n        if (!redisCenter.isRun(appId, host, port)) {\n            logger.error(\"host:{};port:{} not run\", host, port);\n            return false;\n        } else {\n            logger.warn(\"runInstance-fallback : redis-cli -h {} -p {} shutdown\", host, port);\n        }\n        return true;\n    }\n\n    private boolean slaveOf(final long appId, final String masterHost, final int masterPort, final String slaveHost,\n            final int slavePort) {\n    \t\tfinal Jedis slave = redisCenter.getJedis(appId, slaveHost, slavePort, Protocol.DEFAULT_TIMEOUT * 3, Protocol.DEFAULT_TIMEOUT * 3);\n        try {\n            boolean isSlave = new IdempotentConfirmer() {\n                @Override\n                public boolean execute() {\n                    String result = slave.slaveof(masterHost, masterPort);\n                    return result != null && result.equalsIgnoreCase(\"OK\");\n                }\n            }.run();\n            if (!isSlave) {\n                logger.error(String.format(\"modifyAppConfig:ip=%s,port=%s failed\", slaveHost, slavePort));\n                return false;\n            }\n            redisCenter.configRewrite(appId, slaveHost, slavePort);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return false;\n        } finally {\n            if (slave != null)\n                slave.close();\n        }\n\n        return true;\n    }\n\n    private boolean runSentinel(AppDesc appDesc, String sentinelHost, String masterName, String masterHost, Integer masterPort) {\n    \t\t//应用信息\n    \t\tlong appId = appDesc.getAppId();\n    \t\tString password = appDesc.getPassword();\n    \t\n        //启动sentinel实例\n        Integer sentinelPort = machineCenter.getAvailablePort(sentinelHost, ConstUtils.CACHE_REDIS_SENTINEL);\n        if (sentinelPort == null) {\n            logger.error(\"host={} getAvailablePort is null\", sentinelHost);\n            return false;\n        }\n        List<String> masterSentinelConfigs = handleSentinelConfig(masterName, masterHost, masterPort, sentinelPort);\n        if (StringUtils.isNotBlank(password)) {\n        \t\tmasterSentinelConfigs.add(\"sentinel \" + RedisConfigEnum.AUTH_PASS.getKey() + ConstUtils.SPACE + masterName + ConstUtils.SPACE + password);\n        }\n        \n        printConfig(masterSentinelConfigs);\n        String masterSentinelFileName = RedisProtocol.getConfig(sentinelPort, false);\n        String sentinelPathFile = machineCenter\n                .createRemoteFile(sentinelHost, masterSentinelFileName, masterSentinelConfigs);\n        if (StringUtils.isBlank(sentinelPathFile)) {\n            return false;\n        }\n        String sentinelShell = RedisProtocol.getSentinelShell(sentinelPort);\n        logger.info(\"sentinelMasterShell:{}\", sentinelShell);\n        boolean isSentinelMasterShell = machineCenter.startProcessAtPort(sentinelHost, sentinelPort, sentinelShell);\n        if (!isSentinelMasterShell) {\n            logger.error(\"sentinelMasterShell={} error\", sentinelShell);\n            return false;\n        }\n        //验证实例\n        if (!redisCenter.isRun(sentinelHost, sentinelPort)) {\n            logger.error(\"host:{};port:{} not run\", sentinelHost, sentinelPort);\n            return false;\n        } else {\n            logger.warn(\"runSentinel-fallback : redis-cli -h {} -p {} shutdown\", sentinelHost, sentinelPort);\n        }\n        //save sentinel\n        saveInstance(appId, sentinelHost, sentinelPort, 0, ConstUtils.CACHE_REDIS_SENTINEL,\n                getMasterName(masterHost, masterPort));\n        return true;\n    }\n\n    /**\n     * 获取redis 基础配置\n     *\n     * @param port\n     * @param maxMemory\n     * @return\n     */\n    public List<String> handleCommonConfig(int port, int maxMemory) {\n        List<String> configs = null;\n        try {\n            configs = redisConfigTemplateService.handleCommonConfig(port, maxMemory);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n        if (CollectionUtils.isEmpty(configs)) {\n            configs = redisConfigTemplateService.handleCommonDefaultConfig(port, maxMemory);\n        }\n        return configs;\n    }\n\n    private List<String> handleSentinelConfig(String masterName, String host, int port, int sentinelPort) {\n        List<String> configs = null;\n        try {\n            configs = redisConfigTemplateService.handleSentinelConfig(masterName, host, port, sentinelPort);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n        if (CollectionUtils.isEmpty(configs)) {\n            configs = redisConfigTemplateService.handleSentinelDefaultConfig(masterName, host, port, sentinelPort);\n        }\n        return configs;\n    }\n\n    private List<String> handleClusterConfig(int port) {\n        List<String> configs = null;\n        try {\n            configs = redisConfigTemplateService.handleClusterConfig(port);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n        if (CollectionUtils.isEmpty(configs)) {\n            configs = redisConfigTemplateService.handleClusterDefaultConfig(port);\n        }\n        return configs;\n    }\n\n    private String getMasterName(String host, int port) {\n        String masterSentinelName = String.format(\"sentinel-%s-%s\", host, port);\n        return masterSentinelName;\n    }\n\n    private void printConfig(List<String> masterConfigs) {\n        logger.info(\"==================redis-{}-config==================\", masterConfigs);\n        for (String line : masterConfigs) {\n            logger.info(line);\n        }\n    }\n\n    private boolean isExist(long appId) {\n        List<InstanceInfo> instanceInfos = instanceDao.getInstListByAppId(appId);\n        if (instanceInfos != null && instanceInfos.size() > 0) {\n            logger.error(\"appId={} instances is exist , instanceInfos={}\", appId, instanceInfos);\n            return false;\n        }\n        return true;\n    }\n\n    @Override\n    public boolean modifyAppConfig(long appId, String parameter, String value) {\n        List<InstanceInfo> list = instanceDao.getInstListByAppId(appId);\n        if (list == null || list.isEmpty()) {\n            logger.error(String.format(\"appId=%s no instances\", appId));\n            return false;\n        }\n        for (InstanceInfo instance : list) {\n            int type = instance.getType();\n            if (!TypeUtil.isRedisType(type)) {\n                logger.error(\"appId={};type={};is not redisType\", appId, type);\n                return false;\n            }\n            //忽略sentinel\n            if (TypeUtil.isRedisSentinel(type)) {\n                continue;\n            }\n            //忽略下线\n            if (instance.isOffline()) {\n                continue;\n            }\n            String host = instance.getIp();\n            int port = instance.getPort();\n            if (!modifyInstanceConfig(appId, host, port, parameter, value)) {\n                return false;\n            }\n        }\n        return true;\n    }\n\n    @Override\n    public boolean modifyInstanceConfig(final long appId, final String host, final int port, final String parameter, final String value) {\n        final Jedis jedis = redisCenter.getJedis(appId, host, port, 5000, 5000);\n        try {\n            boolean isConfig = new IdempotentConfirmer() {\n                @Override\n                public boolean execute() {\n                    boolean isRun = redisCenter.isRun(appId, host, port);\n                    if (!isRun) {\n                        logger.warn(\"modifyInstanceConfig{}:{} is shutdown\", host, port);\n                        return true;\n                    }\n                    String result = jedis.configSet(parameter, value);\n                    boolean isConfig = result != null && result.equalsIgnoreCase(\"OK\");\n                    if (!isConfig) {\n                        logger.error(String.format(\"modifyConfigError:ip=%s,port=%s,result=%s\", host, port, result));\n                        return false;\n                    }\n                    return isConfig;\n                }\n            }.run();\n            boolean isRewrite = redisCenter.configRewrite(appId, host, port);\n            if (!isRewrite) {\n                logger.error(\"configRewrite={}:{} failed\", host, port);\n            }\n            return isConfig;\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return false;\n        } finally {\n            if (jedis != null)\n                jedis.close();\n        }\n    }\n\n    @Override\n    public boolean addSentinel(long appId, String sentinelHost) {\n        AppDesc appDesc = appDao.getAppDescById(appId);\n        JedisSentinelPool jedisSentinelPool = redisCenter.getJedisSentinelPool(appDesc);\n        if (jedisSentinelPool == null) {\n            return false;\n        }\n        List<InstanceInfo> instanceInfos = instanceDao.getInstListByAppId(appId);\n        String masterName = null;\n        for (Iterator<InstanceInfo> i = instanceInfos.iterator(); i.hasNext(); ) {\n            InstanceInfo instanceInfo = i.next();\n            if (instanceInfo.getType() != ConstUtils.CACHE_REDIS_SENTINEL) {\n                i.remove();\n                continue;\n            }\n            if (masterName == null && StringUtils.isNotBlank(instanceInfo.getCmd())) {\n                masterName = instanceInfo.getCmd();\n            }\n        }\n        Jedis jedis = null;\n        String masterHost = null;\n        Integer masterPort = null;\n        try {\n            jedis = jedisSentinelPool.getResource();\n            masterHost = jedis.getClient().getHost();\n            masterPort = jedis.getClient().getPort();\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        } finally {\n            jedis.close();\n            jedisSentinelPool.destroy();\n        }\n        boolean isRun = runSentinel(appDesc, sentinelHost, masterName, masterHost, masterPort);\n        if (!isRun) {\n            return false;\n        }\n        return true;\n    }\n    \n    @Override\n    public RedisOperateEnum addSlotsFailMaster(final long appId, int lossSlotsInstanceId,final String newMasterHost) throws Exception {\n        // 1.参数、应用、实例信息确认\n        Assert.isTrue(appId > 0);\n        Assert.isTrue(lossSlotsInstanceId > 0);\n        Assert.isTrue(StringUtils.isNotBlank(newMasterHost));\n        AppDesc appDesc = appDao.getAppDescById(appId);\n        Assert.isTrue(appDesc != null);\n        int type = appDesc.getType();\n        if (!TypeUtil.isRedisCluster(type)) {\n            logger.error(\"{} is not redis cluster type\", appDesc);\n            return RedisOperateEnum.FAIL;\n        }\n        //获取失联slots的实例信息\n        InstanceInfo lossSlotsInstanceInfo = instanceDao.getInstanceInfoById(lossSlotsInstanceId);\n        Assert.isTrue(lossSlotsInstanceInfo != null);\n\n        // 2.获取集群中一个健康的master作为clusterInfo Nodes的数据源\n        List<InstanceInfo> allInstanceInfo = redisCenter.getAllHealthyInstanceInfo(appId);\n        //InstanceInfo sourceMasterInstance = redisCenter.getHealthyInstanceInfo(appId);\n        if (allInstanceInfo == null || allInstanceInfo.size() == 0) {\n            logger.warn(\"appId {} get all instance is zero\", appId);\n            return RedisOperateEnum.FAIL;\n        }\n        //默认获取第一个master节点\n        InstanceInfo sourceMasterInstance = allInstanceInfo.get(0);\n        // 并未找到一个合适的实例可以\n        if (sourceMasterInstance == null) {\n            logger.warn(\"appId {} does not have right instance\", appId);\n            return RedisOperateEnum.FAIL;\n        }\n\n        // 3. 找到丢失的slots，如果没找到就说明集群正常，直接返回\n        String healthyMasterHost = sourceMasterInstance.getIp();\n        int healthyMasterPort = sourceMasterInstance.getPort();\n        int healthyMasterMem = sourceMasterInstance.getMem();\n        // 3.1 查看整个集群中是否有丢失的slots\n        List<Integer> allLossSlots = redisCenter.getClusterLossSlots(appId, healthyMasterHost, healthyMasterPort);\n        if (CollectionUtils.isEmpty(allLossSlots)) {\n            logger.warn(\"appId {} all slots is regular and assigned\", appId);\n            return RedisOperateEnum.ALREADY_SUCCESS;\n        }\n        // 3.2 查看目标实例丢失slots \n        final List<Integer> clusterLossSlots = redisCenter.getInstanceSlots(appId, healthyMasterHost, healthyMasterPort, lossSlotsInstanceInfo.getIp(), lossSlotsInstanceInfo.getPort());\n        // 4.开启新的节点\n        // 4.1 从newMasterHost找到可用的端口newMasterPort\n        final Integer newMasterPort = machineCenter.getAvailablePort(newMasterHost, ConstUtils.CACHE_TYPE_REDIS_CLUSTER);\n        if (newMasterPort == null) {\n            logger.error(\"host={} getAvailablePort is null\", newMasterHost);\n            return RedisOperateEnum.FAIL;\n        }\n        // 4.2 按照sourceMasterInstance的内存启动\n        boolean isRun = runInstance(appDesc, newMasterHost, newMasterPort, healthyMasterMem, true);\n        if (!isRun) {\n            logger.error(\"{}:{} is not run\", newMasterHost, newMasterPort);\n            return RedisOperateEnum.FAIL;\n        }\n        // 4.3 拷贝配置\n        boolean isCopy = copyCommonConfig(appId, healthyMasterHost, healthyMasterPort, newMasterHost, newMasterPort);\n        if (!isCopy) {\n            logger.error(\"{}:{} copy config {}:{} is error\", healthyMasterHost, healthyMasterPort, newMasterHost, newMasterPort);\n            return RedisOperateEnum.FAIL;\n        }\n        \n        // 5. meet\n        boolean isClusterMeet = false;\n        Jedis sourceMasterJedis = null;\n        try {\n            sourceMasterJedis = redisCenter.getJedis(appId, healthyMasterHost, healthyMasterPort);\n            isClusterMeet = clusterMeet(sourceMasterJedis, appId, newMasterHost, newMasterPort);\n            if (!isClusterMeet) {\n                logger.error(\"{}:{} cluster is failed\", newMasterHost, newMasterPort);\n                return RedisOperateEnum.FAIL;\n            }\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        } finally {\n            if (sourceMasterJedis != null) {\n                sourceMasterJedis.close();\n            }\n        }\n        if (!isClusterMeet) {\n            logger.warn(\"{}:{} meet {}:{} is fail\", healthyMasterHost, healthyMasterPort, newMasterHost, newMasterPort);\n            return RedisOperateEnum.FAIL;\n        }\n        \n        // 6. 分配slots\n        //String addSlotsResult = \"\";\n        Jedis newMasterJedis = null;\n        //Jedis healthyMasterJedis = null;\n        try {\n            newMasterJedis = redisCenter.getJedis(appId, newMasterHost, newMasterPort, 5000, 5000);\n            //获取新的补救节点的nodeid\n            final String nodeId = getClusterNodeId(newMasterJedis);\n            //healthyMasterJedis = redisCenter.getJedis(appId, healthyMasterHost, healthyMasterPort, 5000, 5000);\n            for (InstanceInfo instance : allInstanceInfo) {\n                final Jedis masterJedis = redisCenter.getJedis(appId, instance.getIp(), instance.getPort(), 5000, 5000);\n                logger.warn(\"{}:{} set {}:{} slots start\", instance.getIp(), instance.getPort(), newMasterHost, newMasterPort);\n                // 1. nodes meet 2. nodes set\n                boolean setSlotStatus = true;\n                try {\n                    setSlotStatus = new IdempotentConfirmer() {\n                        @Override\n                        public boolean execute() {\n                            String setSlotsResult = null;\n                            try {\n                                for (final Integer slot : clusterLossSlots) {\n                                    setSlotsResult = masterJedis.clusterSetSlotNode(slot, nodeId);\n                                    logger.warn(\"set slot {}, result is {}\", slot, setSlotsResult);\n                                }\n                            } catch (JedisDataException exception) {\n                                logger.warn(exception.getMessage());\n                                // unkown jedis node\n                                try {\n                                    TimeUnit.SECONDS.sleep(2);\n                                } catch (InterruptedException e) {\n                                    logger.error(e.getMessage(), e);\n                                }\n                            }\n                            // result\n                            boolean nodeSetStatus = setSlotsResult != null && setSlotsResult.equalsIgnoreCase(\"OK\");\n                            return nodeSetStatus;\n                        }\n                    }.run();\n                } catch (Exception e) {\n                    logger.error(e.getMessage(), e);\n                } finally {\n                    //close jedis\n                    if (masterJedis != null) {\n                        masterJedis.close();\n                    }\n                }\n                // set slots result\n                if (setSlotStatus) {\n                    logger.warn(\"{}:{} set {}:{} slots success\", instance.getIp(), instance.getPort(), newMasterHost, newMasterPort);\n                } else {\n                    logger.warn(\"{}:{} set {}:{} slots faily\", instance.getIp(), instance.getPort(), newMasterHost, newMasterPort);\n                    return RedisOperateEnum.FAIL;\n                }\n            }\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        } finally {\n            if (newMasterJedis != null) {\n                newMasterJedis.close();\n            }\n        }\n        /*if (!\"OK\".equalsIgnoreCase(addSlotsResult)) {\n            logger.warn(\"{}:{} set slots faily\", newMasterHost, newMasterPort);\n            return RedisOperateEnum.FAIL;\n        }*/\n        \n        // 7.保存实例信息、并开启收集信息\n        saveInstance(appId, newMasterHost, newMasterPort, healthyMasterMem, ConstUtils.CACHE_TYPE_REDIS_CLUSTER, \"\");\n        redisCenter.deployRedisCollection(appId, newMasterHost, newMasterPort);\n        \n        // 休息一段时间，同步clusterNodes信息\n        TimeUnit.SECONDS.sleep(2);\n        \n        // 8.最终打印出当前还没有补充的slots\n        List<Integer> currentLossSlots = redisCenter.getClusterLossSlots(appId, newMasterHost, newMasterPort);\n        logger.warn(\"appId {} failslots assigned unsuccessfully, lossslots is {}\", appId, currentLossSlots);\n        \n        return RedisOperateEnum.OP_SUCCESS;        \n    }\n\n    @Override\n    public boolean addSlave(long appId, int instanceId, final String slaveHost) {\n        Assert.isTrue(appId > 0);\n        Assert.isTrue(instanceId > 0);\n        Assert.isTrue(StringUtils.isNotBlank(slaveHost));\n        AppDesc appDesc = appDao.getAppDescById(appId);\n        Assert.isTrue(appDesc != null);\n        int type = appDesc.getType();\n        if (!TypeUtil.isRedisType(type)) {\n            logger.error(\"{} is not redis type\", appDesc);\n            return false;\n        }\n        InstanceInfo instanceInfo = instanceDao.getInstanceInfoById(instanceId);\n        Assert.isTrue(instanceInfo != null);\n        String masterHost = instanceInfo.getIp();\n        int masterPort = instanceInfo.getPort();\n        final Integer slavePort = machineCenter.getAvailablePort(slaveHost, ConstUtils.CACHE_REDIS_STANDALONE);\n        if (slavePort == null) {\n            logger.error(\"host={} getAvailablePort is null\", slaveHost);\n            return false;\n        }\n        boolean isRun;\n        if (TypeUtil.isRedisCluster(type)) {\n            isRun = runInstance(appDesc, slaveHost, slavePort, instanceInfo.getMem(), true);\n        } else {\n            isRun = runInstance(appDesc, slaveHost, slavePort, instanceInfo.getMem(), false);\n        }\n\n        if (!isRun) {\n            logger.error(\"{}:{} is not run\", slaveHost, slavePort);\n            return false;\n        }\n\n        boolean isCopy = copyCommonConfig(appId, masterHost, masterPort, slaveHost, slavePort);\n        if (!isCopy) {\n            logger.error(\"{}:{} copy config {}:{} is error\", masterHost, masterPort, slaveHost, slavePort);\n            return false;\n        }\n        if (TypeUtil.isRedisCluster(type)) {\n            final Jedis masterJedis = redisCenter.getJedis(appId, masterHost, masterPort, Protocol.DEFAULT_TIMEOUT, Protocol.DEFAULT_TIMEOUT);\n            final Jedis slaveJedis = redisCenter.getJedis(appId, slaveHost, slavePort, Protocol.DEFAULT_TIMEOUT, Protocol.DEFAULT_TIMEOUT);\n            try {\n\n                boolean isClusterMeet = clusterMeet(masterJedis, appId, slaveHost, slavePort);\n                if (!isClusterMeet) {\n                    logger.error(\"{}:{} cluster is failed\", slaveHost, slaveHost);\n                    return isClusterMeet;\n                }\n                final String nodeId = redisCenter.getNodeId(appId, masterHost, masterPort);\n                if (StringUtils.isBlank(nodeId)) {\n                    logger.error(\"{}:{} getNodeId failed\", masterHost, masterPort);\n                    return false;\n                }\n                boolean isClusterReplicate = new IdempotentConfirmer() {\n                    @Override\n                    public boolean execute() {\n                        try {\n                            //等待广播节点\n                            TimeUnit.SECONDS.sleep(2);\n                        } catch (Exception e) {\n                            logger.error(e.getMessage(), e);\n                        }\n                        String response = slaveJedis.clusterReplicate(nodeId);\n                        logger.info(\"clusterReplicate-{}:{}={}\", slaveHost, slavePort, response);\n                        return response != null && response.equalsIgnoreCase(\"OK\");\n                    }\n                }.run();\n                if (!isClusterReplicate) {\n                    logger.error(\"{}:{} clusterReplicate {} is failed \", slaveHost, slavePort, nodeId);\n                    return false;\n                }\n                //保存配置\n                masterJedis.clusterSaveConfig();\n                slaveJedis.clusterSaveConfig();\n                redisCenter.configRewrite(appId, masterHost, masterPort);\n                redisCenter.configRewrite(appId, slaveHost, slavePort);\n            } finally {\n                masterJedis.close();\n                slaveJedis.close();\n            }\n        } else {\n            boolean isSlave = slaveOf(appId, masterHost, masterPort, slaveHost, slavePort);\n            if (!isSlave) {\n                logger.error(\"{}:{} sync {}:{} is error\", slaveHost, slavePort, masterHost, masterPort);\n                return false;\n            }\n        }\n\n        //写入instanceInfo 信息\n        if (TypeUtil.isRedisCluster(type)) {\n            saveInstance(appId, slaveHost, slavePort, instanceInfo.getMem(),\n                    ConstUtils.CACHE_TYPE_REDIS_CLUSTER, \"\");\n        } else {\n            saveInstance(appId, slaveHost, slavePort, instanceInfo.getMem(),\n                    ConstUtils.CACHE_REDIS_STANDALONE, \"\");\n        }\n        //启动监控trigger\n        boolean isDeploy = redisCenter.deployRedisCollection(appId, slaveHost, slavePort);\n        if (!isDeploy) {\n            logger.warn(\"host={},port={},isMasterDeploy=false\", slaveHost, slavePort);\n        }\n\n        return true;\n    }\n\n    @Override\n    public boolean sentinelFailover(final long appId) throws Exception {\n        Assert.isTrue(appId > 0);\n        AppDesc appDesc = appDao.getAppDescById(appId);\n        Assert.isTrue(appDesc != null);\n        int type = appDesc.getType();\n        if (!TypeUtil.isRedisSentinel(type)) {\n            logger.warn(\"app={} is not sentinel\", appDesc);\n            return false;\n        }\n        final List<InstanceInfo> instanceList = instanceDao.getInstListByAppId(appId);\n        if (instanceList == null || instanceList.isEmpty()) {\n            logger.warn(\"app={} instances is empty\");\n            return false;\n        }\n        for (InstanceInfo instanceInfo : instanceList) {\n            int instanceType = instanceInfo.getType();\n            if (TypeUtil.isRedisSentinel(instanceType)) {\n                final String host = instanceInfo.getIp();\n                final int port = instanceInfo.getPort();\n                final String masterName = instanceInfo.getCmd();\n                if (StringUtils.isBlank(masterName)) {\n                    logger.warn(\"{} cmd is null\", instanceInfo);\n                    continue;\n                }\n                boolean isRun = redisCenter.isRun(host, port);\n                if (!isRun) {\n                    logger.warn(\"{} is not run\");\n                    continue;\n                }\n                boolean isSentinelFailOver = new IdempotentConfirmer() {\n                    @Override\n                    public boolean execute() {\n                    \t\n                        Jedis jedis = redisCenter.getJedis(host, port);\n                        try {\n                            String response = jedis.sentinelFailover(masterName);\n                            return response != null && response.equalsIgnoreCase(\"OK\");\n                        } finally {\n                            jedis.close();\n                        }\n                    }\n                }.run();\n                if (!isSentinelFailOver) {\n                    logger.warn(\"{}:{} sentienl isSentinelFailOver error\", host, port);\n                    return false;\n                } else {\n                    logger.warn(\"SentinelFailOver done! \");\n                    break;\n                }\n            }\n        }\n        return true;\n    }\n\n    @Override\n    public boolean clusterFailover(final long appId, int slaveInstanceId, final String failoverParam) throws Exception {\n        Assert.isTrue(appId > 0);\n        Assert.isTrue(slaveInstanceId > 0);\n        AppDesc appDesc = appDao.getAppDescById(appId);\n        Assert.isTrue(appDesc != null);\n        int type = appDesc.getType();\n        if (!TypeUtil.isRedisCluster(type)) {\n            logger.error(\"{} is not redis cluster type\", appDesc);\n            return false;\n        }\n        InstanceInfo instanceInfo = instanceDao.getInstanceInfoById(slaveInstanceId);\n        Assert.isTrue(instanceInfo != null);\n        String slaveHost = instanceInfo.getIp();\n        int slavePort = instanceInfo.getPort();\n        final Jedis slaveJedis = redisCenter.getJedis(appId, slaveHost, slavePort);\n        boolean isClusterFailOver = new IdempotentConfirmer() {\n            @Override\n            public boolean execute() {\n                String response = null;\n                if (StringUtils.isBlank(failoverParam)) {\n                    response = slaveJedis.clusterFailover();\n                } else if (\"force\".equals(failoverParam)) {\n                    response = slaveJedis.clusterFailoverForce();\n                } else if (\"takeover\".equals(failoverParam)) {\n                    response = slaveJedis.clusterFailoverTakeOver();\n                } else {\n                    logger.error(\"appId {} failoverParam {} is wrong\", appId, failoverParam);\n                }\n                return response != null && response.equalsIgnoreCase(\"OK\");\n            }\n        }.run();\n        if (!isClusterFailOver) {\n            logger.error(\"{}:{} clusterFailover {} failed\", slaveHost, slavePort, failoverParam);\n            return false;\n        } else {\n            logger.warn(\"{}:{} clusterFailover {} Done! \", slaveHost, slavePort, failoverParam);\n        }\n        return true;\n    }\n    \n    @Override\n    public ClusterOperateResult delNode(final Long appId, int delNodeInstanceId) {\n        final InstanceInfo forgetInstanceInfo = instanceDao.getInstanceInfoById(delNodeInstanceId);\n        final String forgetNodeId = redisCenter.getNodeId(appId, forgetInstanceInfo.getIp(),\n                forgetInstanceInfo.getPort());\n        if (StringUtils.isBlank(forgetNodeId)) {\n            logger.warn(\"{} nodeId is null\", forgetInstanceInfo.getHostPort());\n            return ClusterOperateResult.fail(String.format(\"%s nodeId is null\", forgetInstanceInfo.getHostPort()));\n        }\n        List<InstanceInfo> instanceInfos = instanceDao.getInstListByAppId(appId);\n        for (InstanceInfo instanceInfo : instanceInfos) {\n            if (instanceInfo == null) {\n                continue;\n            }\n            if (instanceInfo.isOffline()) {\n                continue;\n            }\n            // 过滤当前节点\n            if (forgetInstanceInfo.getHostPort().equals(instanceInfo.getHostPort())) {\n                continue;\n            }\n            final String instanceHost = instanceInfo.getIp();\n            final int instancePort = instanceInfo.getPort();\n            boolean isForget = new IdempotentConfirmer() {\n                @Override\n                public boolean execute() {\n                    String response = null;\n                    Jedis jedis = null;\n                    try {\n                        jedis = redisCenter.getJedis(appId, instanceHost, instancePort);\n                        logger.warn(\"{}:{} is forgetting {}\", instanceHost, instancePort, forgetNodeId);\n                        response = jedis.clusterForget(forgetNodeId);\n                        boolean success = response != null && response.equalsIgnoreCase(\"OK\");\n                        logger.warn(\"{}:{} is forgetting {} result is {}\", instanceHost, instancePort, forgetNodeId,\n                                success);\n                        return success;\n                    } catch (Exception e) {\n                        logger.error(e.getMessage());\n                    } finally {\n                        if (jedis != null) {\n                            jedis.close();\n                        }\n                    }\n                    return response != null && response.equalsIgnoreCase(\"OK\");\n                }\n            }.run();\n            if (!isForget) {\n                logger.warn(\"{}:{} forget {} failed\", instanceHost, instancePort, forgetNodeId);\n                return ClusterOperateResult.fail(String.format(\"%s:%s forget %s failed\", instanceHost, instancePort, forgetNodeId));\n            }\n        }\n        \n        // shutdown\n        boolean isShutdown = instanceDeployCenter.shutdownExistInstance(appId, delNodeInstanceId);\n        if (!isShutdown) {\n            logger.warn(\"{} shutdown failed\", forgetInstanceInfo.getHostPort());\n            return ClusterOperateResult.fail(String.format(\"%s shutdown failed\", forgetInstanceInfo.getHostPort()));\n        }\n        \n        return ClusterOperateResult.success();\n    }\n    \n    \n    /**\n     * 1. 被forget的节点必须在线(这个条件有待验证) \n     * 2. 被forget的节点不能有从节点 \n     * 3. 被forget的节点不能有slots\n     */\n    @Override\n    public ClusterOperateResult checkClusterForget(Long appId, int forgetInstanceId) {\n        // 0.各种验证\n        Assert.isTrue(appId > 0);\n        Assert.isTrue(forgetInstanceId > 0);\n        AppDesc appDesc = appDao.getAppDescById(appId);\n        Assert.isTrue(appDesc != null);\n        int type = appDesc.getType();\n        if (!TypeUtil.isRedisCluster(type)) {\n            logger.error(\"{} is not redis cluster type\", appDesc);\n            return ClusterOperateResult.fail(String.format(\"instanceId: %s must be cluster type\", forgetInstanceId));\n        }\n        InstanceInfo instanceInfo = instanceDao.getInstanceInfoById(forgetInstanceId);\n        Assert.isTrue(instanceInfo != null);\n        String forgetHost = instanceInfo.getIp();\n        int forgetPort = instanceInfo.getPort();\n        // 1.是否在线\n        boolean isRun = redisCenter.isRun(appId, forgetHost, forgetPort);\n        if (!isRun) {\n            logger.warn(\"{}:{} is not run\", forgetHost, forgetPort);\n            return ClusterOperateResult.fail(String.format(\"被forget的节点(%s:%s)必须在线\", forgetHost, forgetPort));\n        }\n        // 2.被forget的节点不能有从节点\n        Boolean hasSlaves = redisCenter.hasSlaves(appId, forgetHost, forgetPort);\n        if (hasSlaves == null || hasSlaves) {\n            logger.warn(\"{}:{} has slave\", forgetHost, forgetPort);\n            return ClusterOperateResult.fail(String.format(\"被forget的节点(%s:%s)不能有从节点\", forgetHost, forgetPort));\n        }\n\n        // 3.被forget的节点不能有slots\n        Map<String, InstanceSlotModel> clusterSlotsMap = redisCenter.getClusterSlotsMap(appId);\n        InstanceSlotModel instanceSlotModel = clusterSlotsMap.get(instanceInfo.getHostPort());\n        if (instanceSlotModel != null && instanceSlotModel.getSlotList() != null\n                && instanceSlotModel.getSlotList().size() > 0) {\n            logger.warn(\"{}:{} has slots\", forgetHost, forgetPort);\n            return ClusterOperateResult.fail(String.format(\"被forget的节点(%s:%s)不能持有slot\", forgetHost, forgetPort));\n        }\n\n        return ClusterOperateResult.success();\n    }\n\n    /**\n     * 拷贝redis配置\n     *\n     * @param sourceHost\n     * @param sourcePort\n     * @param targetHost\n     * @param targetPort\n     * @return\n     */\n    private boolean copyCommonConfig(long appId, String sourceHost, int sourcePort, String targetHost, int targetPort) {\n        String[] compareConfigs = new String[] {\"maxmemory-policy\", \"maxmemory\", \"cluster-node-timeout\",\n                \"cluster-require-full-coverage\", \"repl-backlog-size\", \"appendonly\", \"hash-max-ziplist-entries\",\n                \"hash-max-ziplist-value\", \"list-max-ziplist-entries\", \"list-max-ziplist-value\", \"set-max-intset-entries\",\n                \"zset-max-ziplist-entries\", \"zset-max-ziplist-value\", \"timeout\", \"tcp-keepalive\"};\n        try {\n            for (String config : compareConfigs) {\n                String sourceValue = getConfigValue(appId, sourceHost, sourcePort, config);\n                if (StringUtils.isBlank(sourceValue)) {\n                    continue;\n                }\n                String targetValue = getConfigValue(appId, targetHost, targetPort, config);\n                if (StringUtils.isNotBlank(targetHost)) {\n                    if (!targetValue.equals(sourceValue)) {\n                        this.modifyInstanceConfig(appId, targetHost, targetPort, config, sourceValue);\n                    }\n                }\n            }\n            return true;\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return false;\n        }\n    }\n\n    private String getConfigValue(long appId, String host, int port, String key) {\n        Jedis jedis = redisCenter.getJedis(appId, host, port, Protocol.DEFAULT_TIMEOUT * 3, Protocol.DEFAULT_TIMEOUT * 3);\n        try {\n            List<String> values = jedis.configGet(key);\n            if (values == null || values.size() < 1) {\n                return null;\n            }\n            return values.get(1);\n        } catch (Exception e) {\n            throw new RuntimeException(e.getMessage(), e);\n        } finally {\n            jedis.close();\n        }\n    }\n\n    public void setInstanceDao(InstanceDao instanceDao) {\n        this.instanceDao = instanceDao;\n    }\n\n    public void setMachineCenter(MachineCenter machineCenter) {\n        this.machineCenter = machineCenter;\n    }\n\n    public void setMachineDao(MachineDao machineDao) {\n        this.machineDao = machineDao;\n    }\n\n    public void setRedisCenter(RedisCenter redisCenter) {\n        this.redisCenter = redisCenter;\n    }\n\n    public void setAppDao(AppDao appDao) {\n        this.appDao = appDao;\n    }\n\n    public void setRedisConfigTemplateService(RedisConfigTemplateService redisConfigTemplateService) {\n        this.redisConfigTemplateService = redisConfigTemplateService;\n    }\n\n    public void setInstanceDeployCenter(InstanceDeployCenter instanceDeployCenter) {\n        this.instanceDeployCenter = instanceDeployCenter;\n    }\n\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/schedule/SchedulerCenter.java",
    "content": "package com.sohu.cache.schedule;\n\nimport com.sohu.cache.entity.TriggerInfo;\nimport org.quartz.JobDetail;\nimport org.quartz.JobKey;\nimport org.quartz.Trigger;\nimport org.quartz.TriggerKey;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 控制job、trigger和scheduler的基类\n * User: lingguo\n * Date: 14-5-18\n * Time: 下午8:18\n */\npublic interface SchedulerCenter {\n\n    public Trigger getTrigger(TriggerKey triggerKey);\n\n    /**\n     * @param triggerKey\n     * @return\n     */\n    public boolean unscheduleJob(TriggerKey triggerKey);\n\n    /**\n     * 根据cron部署Job\n     *\n     * @param jobKey\n     * @param triggerKey\n     * @param dataMap\n     * @param cron\n     * @param replace\n     * @return\n     */\n    public boolean deployJobByCron(JobKey jobKey, TriggerKey triggerKey, Map<String, Object> dataMap, String cron, boolean replace);\n\n    /**\n     * 根据延迟执行的Job\n     *\n     * @param jobKey\n     * @param triggerKey\n     * @param dataMap\n     * @param delaySeconds\n     * @param replace\n     * @return\n     */\n    public boolean deployJobByDelay(JobKey jobKey, TriggerKey triggerKey, Map<String, Object> dataMap, int delaySeconds, boolean replace);\n\n    /**\n     * 获取所有trigger\n     *\n     * @return\n     */\n    public List<TriggerInfo> getAllTriggers();\n\n    /**\n     * 模糊查询trigger\n     *\n     * @return\n     */\n    public List<TriggerInfo> getTriggersByNameOrGroup(String query);\n\n    /**\n     * 暂定trigger\n     *\n     * @param triggerKey\n     * @return\n     */\n    public boolean pauseTrigger(TriggerKey triggerKey);\n\n    /**\n     * 恢复trigger\n     *\n     * @param triggerKey\n     * @return\n     */\n    public boolean resumeTrigger(TriggerKey triggerKey);\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/schedule/TriggerCenter.java",
    "content": "package com.sohu.cache.schedule;\n\nimport com.sohu.cache.entity.TriggerInfo;\n\nimport org.quartz.TriggerKey;\n\nimport java.util.List;\n\n/**\n * trigger管理接口\n *\n * @author: lingguo\n * @time: 2014/10/13 14:02\n */\npublic interface TriggerCenter {\n\n    /**\n     * 增加一个新的trigger\n     *\n     * @param jobGroup  trigger所属的job分组：redis/machine/machineMonitor\n     * @param ip\n     * @param port\n     * @return\n     */\n    public boolean addTrigger(String jobGroup, String ip, int port);\n    /**\n     * 暂停trigger\n     *\n     * @param triggerKey\n     * @return\n     */\n    public boolean pauseTrigger(TriggerKey triggerKey);\n\n    /**\n     * 恢复trigger\n     *\n     * @param triggerKey\n     * @return\n     */\n    public boolean resumeTrigger(TriggerKey triggerKey);\n\n    /**\n     * 删除trigger(从db中删除了)\n     *\n     * @param triggerKey\n     * @return\n     */\n    public boolean removeTrigger(TriggerKey triggerKey);\n\n    /**\n     * 查询某一job类型下的所有trigger\n     *\n     * @param jobGroup job类型：redis/machine/machineMonitor\n     * @return\n     */\n    public List<TriggerInfo> getTriggersByJobGroup(String jobGroup);\n\n    /**\n     * 返回所有的trigger\n     *\n     * @return\n     */\n    public List<TriggerInfo> getAllTriggers();\n\n    /**\n     * 查询trigger，模糊匹配trigger name或trigger group\n     *\n     * @param queryString   trigger name或trigger group的关键字\n     * @return\n     */\n    public List<TriggerInfo> searchTriggerByNameOrGroup(String queryString);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/schedule/impl/SchedulerCenterImpl.java",
    "content": "package com.sohu.cache.schedule.impl;\n\nimport com.sohu.cache.dao.QuartzDao;\nimport com.sohu.cache.entity.TriggerInfo;\nimport com.sohu.cache.schedule.SchedulerCenter;\n\nimport org.apache.commons.lang.time.DateUtils;\nimport org.quartz.*;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.util.Assert;\n\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Map;\n\nimport static org.quartz.SimpleScheduleBuilder.simpleSchedule;\n\n/**\n * 根据scheduler控制job、trigger和scheduler的执行和状态\n * <p/>\n * User: lingguo\n * Date: 14-5-18\n * Time: 下午10:15\n */\npublic class SchedulerCenterImpl implements SchedulerCenter {\n    private Logger logger = LoggerFactory.getLogger(this.getClass());\n\n    // 注入预定义的scheduler\n    private Scheduler clusterScheduler;\n\n    private QuartzDao quartzDao;\n\n    /**\n     * 删除trigger\n     *\n     * @param triggerKey\n     * @return\n     */\n    @Override\n    public boolean unscheduleJob(TriggerKey triggerKey) {\n        boolean opResult = true;\n        try {\n            opResult = clusterScheduler.checkExists(triggerKey);\n            if (opResult) {\n                opResult = clusterScheduler.unscheduleJob(triggerKey);\n            }\n        } catch (SchedulerException e) {\n            logger.error(e.getMessage(), e);\n            opResult = false;\n        }\n        return opResult;\n    }\n\n    @Override\n    public Trigger getTrigger(TriggerKey triggerKey) {\n        Trigger trigger = null;\n        try {\n            trigger = clusterScheduler.getTrigger(triggerKey);\n        } catch (SchedulerException e) {\n            logger.error(e.getMessage(), e);\n        }\n        return trigger;\n    }\n\n    @Override\n    public boolean deployJobByCron(JobKey jobKey, TriggerKey triggerKey, Map<String, Object> dataMap, String cron, boolean replace) {\n        Assert.isTrue(jobKey != null);\n        Assert.isTrue(triggerKey != null);\n        Assert.isTrue(CronExpression.isValidExpression(cron), \"invalid cron = \" + cron);\n        try {\n            JobDetail jobDetail = clusterScheduler.getJobDetail(jobKey);\n            if (jobDetail == null) {\n                logger.error(\"JobKey {}:{} is not exist\", jobKey.getName(), jobKey.getGroup());\n                return false;\n            }\n            fireCronTrigger(triggerKey, jobDetail, cron, replace, dataMap);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return false;\n        }\n\n        return true;\n    }\n\n    @Override\n    public boolean deployJobByDelay(JobKey jobKey, TriggerKey triggerKey, Map<String, Object> dataMap, int  delaySeconds, boolean replace) {\n        Assert.isTrue(jobKey != null);\n        Assert.isTrue(triggerKey != null);\n        Assert.isTrue(delaySeconds > 0);\n        try {\n            JobDetail jobDetail = clusterScheduler.getJobDetail(jobKey);\n            if (jobDetail == null) {\n                logger.error(\"JobKey {}:{} is not exist\", jobKey.getName(), jobKey.getGroup());\n                return false;\n            }\n            fireSimpleTrigger(triggerKey, jobDetail, replace, dataMap, delaySeconds);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return false;\n        }\n\n        return true;\n    }\n\n    private boolean fireSimpleTrigger(TriggerKey triggerKey, JobDetail jobDetail, boolean replace, Map<String, Object> dataMap,int delaySeconds) {\n        try {\n            boolean isExists = clusterScheduler.checkExists(triggerKey);\n            if (isExists) {\n                if (replace) {\n                    logger.warn(\"replace trigger={}:{} \", triggerKey.getName(), triggerKey.getGroup());\n                    clusterScheduler.unscheduleJob(triggerKey);\n                } else {\n                    logger.info(\"exist trigger={}:{} \", triggerKey.getName(), triggerKey.getGroup());\n                    return false;\n                }\n            }\n            Date startAtDate = new Date(System.currentTimeMillis() + delaySeconds * 1000);\n            Trigger trigger = TriggerBuilder.newTrigger()\n                    .withIdentity(triggerKey)\n                    .forJob(jobDetail)\n                    .withSchedule(simpleSchedule()\n                            .withIntervalInSeconds(1)\n\n                            .withRepeatCount(0)\n                            )\n                    .startAt(startAtDate)\n                    .build();\n            if (dataMap != null && dataMap.size() > 0) {\n                trigger.getJobDataMap().putAll(dataMap);\n            }\n            clusterScheduler.scheduleJob(trigger);\n        } catch (SchedulerException e) {\n            logger.error(e.getMessage(), e);\n            return false;\n        }\n        return true;\n    }\n\n    private boolean fireCronTrigger(TriggerKey triggerKey, JobDetail jobDetail, String cron, boolean replace, Map<String, Object> dataMap) {\n        try {\n            boolean isExists = clusterScheduler.checkExists(triggerKey);\n            if (isExists) {\n                if (replace) {\n                    logger.warn(\"replace trigger={}:{} \", triggerKey.getName(), triggerKey.getGroup());\n                    clusterScheduler.unscheduleJob(triggerKey);\n                } else {\n                    logger.info(\"exist trigger={}:{} \", triggerKey.getName(), triggerKey.getGroup());\n                    return false;\n                }\n            }\n            Date startDate = DateUtils.addSeconds(new Date(), 20);\n            Trigger trigger = TriggerBuilder.newTrigger()\n                    .withIdentity(triggerKey)\n                    .forJob(jobDetail)\n                    .withSchedule(\n                            CronScheduleBuilder.cronSchedule(cron)\n                            .withMisfireHandlingInstructionDoNothing()// 忽略misfire处理\n                    )\n                    .startAt(startDate)\n                    .build();\n            if (dataMap != null && dataMap.size() > 0) {\n                trigger.getJobDataMap().putAll(dataMap);\n            }\n            clusterScheduler.scheduleJob(trigger);\n        } catch (SchedulerException e) {\n            logger.error(e.getMessage(), e);\n            return false;\n        }\n        return true;\n    }\n\n    @Override\n    public List<TriggerInfo> getAllTriggers() {\n        return quartzDao.getAllTriggers();\n    }\n\n    @Override\n    public List<TriggerInfo> getTriggersByNameOrGroup(String query) {\n        return quartzDao.searchTriggerByNameOrGroup(query);\n    }\n\n    @Override\n    public boolean pauseTrigger(TriggerKey triggerKey) {\n        try {\n            boolean exists = clusterScheduler.checkExists(triggerKey);\n            if (exists) {\n                clusterScheduler.pauseTrigger(triggerKey);\n                return true;\n            }\n            logger.error(\"triggerKey={} not exists\", triggerKey);\n            return false;\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return false;\n        }\n    }\n\n    @Override\n    public boolean resumeTrigger(TriggerKey triggerKey) {\n        try {\n            boolean exists = clusterScheduler.checkExists(triggerKey);\n            if (exists) {\n                clusterScheduler.resumeTrigger(triggerKey);\n                return true;\n            }\n            logger.error(\"triggerKey={} not exists\", triggerKey);\n            return false;\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return false;\n        }\n    }\n\n    public void setClusterScheduler(Scheduler clusterScheduler) {\n        this.clusterScheduler = clusterScheduler;\n    }\n\n    public void setQuartzDao(QuartzDao quartzDao) {\n        this.quartzDao = quartzDao;\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/schedule/impl/TriggerCenterImpl.java",
    "content": "package com.sohu.cache.schedule.impl;\n\nimport com.sohu.cache.dao.InstanceDao;\nimport com.sohu.cache.dao.MachineDao;\nimport com.sohu.cache.dao.QuartzDao;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.entity.MachineInfo;\nimport com.sohu.cache.entity.TriggerInfo;\nimport com.sohu.cache.machine.MachineCenter;\nimport com.sohu.cache.redis.RedisCenter;\nimport com.sohu.cache.schedule.TriggerCenter;\nimport com.sohu.cache.util.ConstUtils;\n\nimport org.quartz.Scheduler;\nimport org.quartz.SchedulerException;\nimport org.quartz.TriggerKey;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.util.Assert;\n\nimport java.util.List;\n\n/**\n * trigger管理接口的实现\n *\n * @author: lingguo\n * @time: 2014/10/13 14:03\n */\npublic class TriggerCenterImpl implements TriggerCenter {\n    private Logger logger = LoggerFactory.getLogger(this.getClass());\n\n    private Scheduler clusterScheduler;\n    private QuartzDao quartzDao;\n    private RedisCenter redisCenter;\n    private MachineCenter machineCenter;\n    private InstanceDao instanceDao;\n    private MachineDao machineDao;\n\n    /**\n     * 增加一个新trigger\n     *\n     * @param jobGroup  trigger所属的job分组：redis/machine/machineMonitor\n     * @param ip\n     * @param port\n     * @return\n     */\n    @Override\n    public boolean addTrigger(String jobGroup, String ip, int port) {\n        Assert.hasText(jobGroup, \"jobGroup is invalid: \" + jobGroup);\n        Assert.hasText(ip, \"ip is invalid, ip: \" + ip);\n        Assert.isTrue(port > 0, \"port is invalid, port: \" + port);\n\n        boolean opResult = false;\n        if (jobGroup.equals(ConstUtils.REDIS_JOB_GROUP)) {\n            InstanceInfo instanceInfo = instanceDao.getInstByIpAndPort(ip, port);\n            opResult = redisCenter.deployRedisCollection(instanceInfo.getAppId(), ip, port);\n        } else if (jobGroup.equals(ConstUtils.REDIS_SLOWLOG_JOB_GROUP)) {\n            InstanceInfo instanceInfo = instanceDao.getInstByIpAndPort(ip, port);\n            opResult = redisCenter.deployRedisSlowLogCollection(instanceInfo.getAppId(), ip, port);\n        } else if (jobGroup.equals(ConstUtils.MACHINE_JOB_GROUP)) {\n            MachineInfo machineInfo = machineDao.getMachineInfoByIp(ip);\n            opResult = machineCenter.deployMachineCollection(machineInfo.getId(), ip);\n        } else if (jobGroup.equals(ConstUtils.MACHINE_MONITOR_JOB_GROUP)) {\n            MachineInfo machineInfo = machineDao.getMachineInfoByIp(ip);\n            opResult = machineCenter.deployMachineMonitor(machineInfo.getId(), ip);\n        } else if (jobGroup.equals(ConstUtils.SERVER_TRIGGER_GROUP)) {\n            MachineInfo machineInfo = machineDao.getMachineInfoByIp(ip);\n            opResult = machineCenter.deployServerCollection(machineInfo.getId(), ip);\n        }\n        return opResult;\n    }\n\n    /**\n     * 暂停trigger\n     *\n     * @param triggerKey\n     * @return 操作成功返回true，否则返回false；\n     */\n    @Override\n    public boolean pauseTrigger(TriggerKey triggerKey) {\n        boolean opResult = true;\n        try {\n            clusterScheduler.pauseTrigger(triggerKey);\n        } catch (SchedulerException e) {\n            logger.error(e.getMessage(), e);\n            opResult = false;\n        }\n        return opResult;\n    }\n\n    /**\n     * 恢复暂停的trigger\n     *\n     * @param triggerKey\n     */\n    @Override\n    public boolean resumeTrigger(TriggerKey triggerKey) {\n        boolean opResult = true;\n        try {\n            clusterScheduler.resumeTrigger(triggerKey);\n        } catch (SchedulerException e) {\n            logger.error(e.getMessage(), e);\n            opResult = false;\n        }\n        return opResult;\n    }\n\n    /**\n     * 删除一个trigger\n     *\n     * @param triggerKey\n     * @return\n     */\n    @Override\n    public boolean removeTrigger(TriggerKey triggerKey) {\n        boolean opResult = true;\n        try {\n            clusterScheduler.unscheduleJob(triggerKey);\n        } catch (SchedulerException e) {\n            logger.error(e.getMessage(), e);\n            opResult = false;\n        }\n        return opResult;\n    }\n\n    /**\n     * 查询特定job类型下的所有trigger\n     *\n     * @param jobGroup job类型：redis/machine/machineMonitor\n     * @return\n     */\n    @Override\n    public List<TriggerInfo> getTriggersByJobGroup(String jobGroup) {\n        List<TriggerInfo> triggersOfGroup = null;\n        try {\n            triggersOfGroup = quartzDao.getTriggersByJobGroup(jobGroup);\n        } catch (Exception e) {\n            logger.error(\"jobGroup: {}\", jobGroup, e);\n        }\n        return triggersOfGroup;\n    }\n\n    /**\n     * 返回所有的trigger\n     *\n     * @return\n     */\n    @Override\n    public List<TriggerInfo> getAllTriggers() {\n        List<TriggerInfo> allTriggers = null;\n        try {\n            allTriggers = quartzDao.getAllTriggers();\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n        return allTriggers;\n    }\n\n    /**\n     * 查询trigger，模糊匹配trigger name或trigger group\n     *\n     * @param queryString   trigger name或trigger group的关键字\n     * @return\n     */\n    @Override\n    public List<TriggerInfo> searchTriggerByNameOrGroup(String queryString) {\n        List<TriggerInfo> matchTriggers = null;\n        try {\n            matchTriggers = quartzDao.searchTriggerByNameOrGroup(queryString);\n        } catch (Exception e) {\n            logger.error(\"queryString: {}\", queryString, e);\n        }\n        return matchTriggers;\n    }\n\n    public void setClusterScheduler(Scheduler scheduler) {\n        this.clusterScheduler = scheduler;\n    }\n\n    public void setQuartzDao(QuartzDao quartzDao) {\n        this.quartzDao = quartzDao;\n    }\n\n    public void setInstanceDao(InstanceDao instanceDao) {\n        this.instanceDao = instanceDao;\n    }\n\n    public void setMachineDao(MachineDao machineDao) {\n        this.machineDao = machineDao;\n    }\n\n    public void setRedisCenter(RedisCenter redisCenter) {\n        this.redisCenter = redisCenter;\n    }\n\n    public void setMachineCenter(MachineCenter machineCenter) {\n        this.machineCenter = machineCenter;\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/schedule/jobs/AppDailyJob.java",
    "content": "package com.sohu.cache.schedule.jobs;\n\nimport org.quartz.JobExecutionContext;\nimport org.quartz.SchedulerContext;\nimport org.quartz.SchedulerException;\nimport org.springframework.context.ApplicationContext;\n\nimport com.sohu.cache.schedule.jobs.CacheBaseJob;\nimport com.sohu.cache.stats.app.AppDailyDataCenter;\n\n/**\n * 发送日报\n * @author leifu\n * @Date 2016年8月12日\n * @Time 上午11:25:09\n */\npublic class AppDailyJob extends CacheBaseJob {\n\n    private static final long serialVersionUID = 7751425759758902400L;\n\n    @Override\n    public void action(JobExecutionContext context) {\n        try {\n            SchedulerContext schedulerContext = context.getScheduler().getContext();\n            ApplicationContext applicationContext = (ApplicationContext) schedulerContext.get(APPLICATION_CONTEXT_KEY);\n            AppDailyDataCenter appDailyDataCenter = applicationContext.getBean(\"appDailyDataCenter\", AppDailyDataCenter.class);\n            appDailyDataCenter.sendAppDailyEmail();\n        } catch (SchedulerException e) {\n            logger.error(e.getMessage(), e);\n        }\n        \n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/schedule/jobs/CacheBaseJob.java",
    "content": "package com.sohu.cache.schedule.jobs;\n\nimport org.quartz.Job;\nimport org.quartz.JobExecutionContext;\nimport org.quartz.JobExecutionException;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.io.Serializable;\n\n/**\n * job父类，包含一个抽象函方法，将实现推迟到具体的子类\n * <p/>\n * User: lingguo\n * Date: 14-5-15\n * Time: 下午6:04\n */\npublic abstract class CacheBaseJob implements Job, Serializable {\n    private static final long serialVersionUID = -6605766126594260961L;\n    protected Logger logger = LoggerFactory.getLogger(this.getClass());\n\n    protected final String APPLICATION_CONTEXT_KEY = \"applicationContext\";\n\n    // 抽象方法，由子类实现，即具体的业务逻辑\n    public abstract void action(JobExecutionContext context);\n\n    /**\n     * 统计时间\n     *\n     * @param context\n     * @throws JobExecutionException\n     */\n    @Override\n    public void execute(JobExecutionContext context) throws JobExecutionException {\n        long start = System.currentTimeMillis();\n        this.action(context);\n        long end = System.currentTimeMillis();\n        long cost = (start - end);\n        if (cost > 2000) {\n            logger.warn(\"slowJob: job: {}, trigger: {}, cost: {} ms\", context.getJobDetail().getKey(),\n                    context.getTrigger().getKey(), (end - start));\n        } else {\n            logger.info(\"job: {}, trigger: {}, cost: {} ms\", context.getJobDetail().getKey(),\n                    context.getTrigger().getKey(), (end - start));\n        }\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/schedule/jobs/CleanUpStatisticsJob.java",
    "content": "package com.sohu.cache.schedule.jobs;\n\nimport com.sohu.cache.client.service.ClientReportCostDistriService;\nimport com.sohu.cache.client.service.ClientReportValueDistriService;\nimport com.sohu.cache.stats.instance.InstanceStatsCenter;\nimport com.sohu.cache.util.ConstUtils;\n\nimport org.apache.commons.lang.math.NumberUtils;\nimport org.quartz.JobExecutionContext;\nimport org.quartz.SchedulerContext;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.jdbc.core.JdbcTemplate;\n\nimport java.text.SimpleDateFormat;\nimport java.util.Calendar;\nimport java.util.Date;\n\n/**\n * Created by yijunzhang on 14-12-8.\n */\npublic class CleanUpStatisticsJob extends CacheBaseJob {\n    \n    private static final long serialVersionUID = 8815839394475276540L;\n\n    private static final String CLEAN_APP_HOUR_COMMAND_STATISTICS = \"delete from app_hour_command_statistics where create_time < ?\";\n\n    private static final String CLEAN_APP_MINUTE_COMMAND_STATISTICS = \"delete from app_minute_command_statistics where create_time < ?\";\n\n    private static final String CLEAN_APP_HOUR_STATISTICS = \"delete from app_hour_statistics where create_time < ?\";\n\n    private static final String CLEAN_APP_MINUTE_STATISTICS = \"delete from app_minute_statistics where create_time < ?\";\n\n    /**\n     * 清除客户端耗时汇总数据\n     */\n    private static final String CLEAN_APP_CLIENT_MINUTE_COST_TOTAL = \"delete from app_client_costtime_minute_stat_total where collect_time < ?\";\n    \n    //清除服务器统计数据\n    private static final String CLEAN_SERVER_STAT_STATISTICS = \"delete from server_stat where cdate < ?\";\n    \n    @Override\n    public void action(JobExecutionContext context) {\n        if (!ConstUtils.WHETHER_SCHEDULE_CLEAN_DATA) {\n            return;\n        }\n        try {\n            SchedulerContext schedulerContext = context.getScheduler().getContext();\n            ApplicationContext applicationContext = (ApplicationContext) schedulerContext.get(APPLICATION_CONTEXT_KEY);\n            InstanceStatsCenter InstanceStatsCenter =  applicationContext.getBean(\"instanceStatsCenter\", InstanceStatsCenter.class);\n\n            try {\n                InstanceStatsCenter.cleanUpStandardStats(2);\n            } catch (Exception e) {\n                logger.error(e.getMessage(), e);\n            }\n\n            JdbcTemplate jdbcTemplate = applicationContext.getBean(\"jdbcTemplate\", JdbcTemplate.class);\n            Calendar calendar = Calendar.getInstance();\n            calendar.setTime(new Date());\n            calendar.add(Calendar.DAY_OF_MONTH, -31);\n            Date time = calendar.getTime();\n            int cleanCount = jdbcTemplate.update(CLEAN_APP_HOUR_COMMAND_STATISTICS, time);\n            logger.warn(\"clean_app_hour_command_statistics count={}\", cleanCount);\n            cleanCount = jdbcTemplate.update(CLEAN_APP_MINUTE_COMMAND_STATISTICS, time);\n            logger.warn(\"clean_app_minute_command_statistics count={}\", cleanCount);\n            cleanCount = jdbcTemplate.update(CLEAN_APP_HOUR_STATISTICS, time);\n            logger.warn(\"clean_app_hour_statistics count={}\", cleanCount);\n            cleanCount = jdbcTemplate.update(CLEAN_APP_MINUTE_STATISTICS, time);\n            logger.warn(\"clean_app_minute_statistics count={}\", cleanCount);\n            \n            //清除客户端耗时数据(保存2天)\n            ClientReportCostDistriService clientReportCostDistriService = applicationContext.getBean(\n                    \"clientReportCostDistriService\", ClientReportCostDistriService.class);\n            calendar.setTime(new Date());\n            calendar.add(Calendar.DAY_OF_MONTH, -2);\n            long timeFormat = NumberUtils.toLong(new SimpleDateFormat(\"yyyyMMddHHmm00\").format(calendar.getTime()));\n            cleanCount = clientReportCostDistriService.deleteBeforeCollectTime(timeFormat);\n            logger.warn(\"clean_app_client_costtime_minute_stat count={}\", cleanCount);\n            \n            //清除客户端耗时汇总数据(保存14天)\n            calendar.setTime(new Date());\n            calendar.add(Calendar.DAY_OF_MONTH, -14);\n            timeFormat = NumberUtils.toLong(new SimpleDateFormat(\"yyyyMMddHHmm00\").format(calendar.getTime()));\n            cleanCount = jdbcTemplate.update(CLEAN_APP_CLIENT_MINUTE_COST_TOTAL, timeFormat);\n            logger.warn(\"clean_app_client_costtime_minute_stat_total count={}\", cleanCount);\n            \n            //清除客户端值数据(保存2天)\n            ClientReportValueDistriService clientReportValueDistriService = applicationContext.getBean(\n                    \"clientReportValueDistriService\", ClientReportValueDistriService.class);\n            calendar.setTime(new Date());\n            calendar.add(Calendar.DAY_OF_MONTH, -2);\n            timeFormat = NumberUtils.toLong(new SimpleDateFormat(\"yyyyMMddHHmm00\").format(calendar.getTime()));\n            cleanCount = clientReportValueDistriService.deleteBeforeCollectTime(timeFormat);\n            logger.warn(\"clean_app_client_value_minute_stats count={}\", cleanCount);\n            \n            //清除服务器统计数据\n            calendar.setTime(new Date());\n            calendar.add(Calendar.DAY_OF_MONTH, -7);\n            String date = new SimpleDateFormat(\"yyyy-MM-dd\").format(calendar.getTime());\n            cleanCount = jdbcTemplate.update(CLEAN_SERVER_STAT_STATISTICS, date);\n            logger.warn(\"clean_server_stat_total count={}\", cleanCount);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n\n    }\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/schedule/jobs/ErrorStatisticsJob.java",
    "content": "package com.sohu.cache.schedule.jobs;\n\nimport org.quartz.JobExecutionContext;\nimport org.quartz.SchedulerContext;\nimport org.quartz.SchedulerException;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.context.ApplicationContext;\n\nimport com.sohu.cache.jmx.ErrorLoggerWatcherMBean;\nimport com.sohu.cache.schedule.jobs.CacheBaseJob;\nimport com.sohu.cache.web.component.EmailComponent;\n\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\nimport java.util.Map;\n\n/**\n * 异常统计\n * @author leifu\n * @Date 2014年10月31日\n * @Time 上午11:05:42\n */\npublic class ErrorStatisticsJob extends CacheBaseJob {\n    private static final long serialVersionUID = 3566693097569373471L;\n    private final Logger logger = LoggerFactory.getLogger(this.getClass());\n\n    @Override\n    public void action(JobExecutionContext context) {\n        Date date = new Date();\n        SimpleDateFormat dateFormat = new SimpleDateFormat(\"yyyy-MM-dd\");\n        SchedulerContext schedulerContext;\n        try {\n            schedulerContext = context.getScheduler().getContext();\n            ApplicationContext applicationContext = (ApplicationContext) schedulerContext.get(APPLICATION_CONTEXT_KEY);\n            EmailComponent emailComponent = applicationContext.getBean(\"emailComponent\", EmailComponent.class);\n            ErrorLoggerWatcherMBean errorLoggerWatcher = applicationContext.getBean(\"errorLoggerWatcher\", ErrorLoggerWatcherMBean.class);\n//            if (errorLoggerWatcher.getTotalErrorCount() == 0L) {\n//                logger.warn(\"errorLoggerWatcher.totalErrorCount == 0 -o-\");\n//                return;\n//            }\n            String title = \"CacheCloud异常统计， 日期:\" + dateFormat.format(date) + \";服务器:\" + System.getProperty(\"local.ip\") + \";总数:\" + errorLoggerWatcher.getTotalErrorCount();\n\n            StringBuilder buffer = new StringBuilder();\n            buffer.append(title + \":<br/>\");\n            for (Map.Entry<String, Long> entry : errorLoggerWatcher.getErrorInfos().entrySet()) {\n                Long num = entry.getValue();\n                if (num == 0L) {\n                    continue;\n                }\n                String key = entry.getKey();\n                buffer.append(key + \"=\" + num + \"<br/>\");\n            }\n\n            emailComponent.sendMailToAdmin(title, buffer.toString());\n            //清理异常\n            errorLoggerWatcher.clear();\n        } catch (SchedulerException e) {\n            logger.error(e.getMessage(), e);\n        }\n        \n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/schedule/jobs/InstanceAlertValueJob.java",
    "content": "package com.sohu.cache.schedule.jobs;\n\nimport org.quartz.JobExecutionContext;\nimport org.quartz.SchedulerContext;\nimport org.quartz.SchedulerException;\nimport org.springframework.context.ApplicationContext;\n\nimport com.sohu.cache.schedule.jobs.CacheBaseJob;\nimport com.sohu.cache.stats.instance.InstanceAlertConfigService;\n\n/**\n * 实例分钟报警\n * @author leifu\n * @Date 2016年9月13日\n * @Time 下午3:53:04\n */\npublic class InstanceAlertValueJob extends CacheBaseJob {\n\n    private static final long serialVersionUID = 1035952011763660681L;\n\n    @Override\n    public void action(JobExecutionContext context) {\n        try {\n            long startTime = System.currentTimeMillis();\n            SchedulerContext schedulerContext = context.getScheduler().getContext();\n            ApplicationContext applicationContext = (ApplicationContext) schedulerContext.get(APPLICATION_CONTEXT_KEY);\n            InstanceAlertConfigService instanceAlertConfigService = applicationContext.getBean(\"instanceAlertConfigService\", InstanceAlertConfigService.class);\n            instanceAlertConfigService.monitorLastMinuteAllInstanceInfo();\n            logger.info(\"InstanceAlertValueJob cost time {} ms\", (System.currentTimeMillis() - startTime));\n        } catch (SchedulerException e) {\n            logger.error(e.getMessage(), e);\n        }\n        \n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/schedule/jobs/MachineJob.java",
    "content": "package com.sohu.cache.schedule.jobs;\n\nimport java.util.Date;\n\nimport org.quartz.JobDataMap;\nimport org.quartz.JobExecutionContext;\nimport org.quartz.SchedulerContext;\nimport org.quartz.SchedulerException;\nimport org.springframework.context.ApplicationContext;\n\nimport com.sohu.cache.machine.MachineCenter;\nimport com.sohu.cache.util.ConstUtils;\nimport com.sohu.cache.util.ScheduleUtil;\n\n/**\n * 基于机器的job\n *\n * Created by yijunzhang on 14-6-5.\n */\npublic class MachineJob extends CacheBaseJob {\n\n    @Override\n    public void action(JobExecutionContext context) {\n        try {\n            JobDataMap dataMap =  context.getMergedJobDataMap();\n            Date now = new Date();\n            dataMap.put(ConstUtils.TRIGGER_TIME_KEY, now);\n            SchedulerContext schedulerContext = context.getScheduler().getContext();\n            ApplicationContext applicationContext = (ApplicationContext)schedulerContext.get(APPLICATION_CONTEXT_KEY);\n            MachineCenter machineCenter = applicationContext.getBean(\"machineCenter\", MachineCenter.class);\n            String ip = dataMap.getString(ConstUtils.HOST_KEY);\n            long hostId = dataMap.getLong(ConstUtils.HOST_ID_KEY);\n            machineCenter.asyncCollectMachineInfo(hostId, ScheduleUtil.getCollectTime(new Date()), ip);\n        } catch (SchedulerException e) {\n            logger.error(e.getMessage(), e);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/schedule/jobs/MachineMonitorJob.java",
    "content": "package com.sohu.cache.schedule.jobs;\n\nimport org.quartz.JobDataMap;\nimport org.quartz.JobExecutionContext;\nimport org.quartz.SchedulerContext;\nimport org.quartz.SchedulerException;\nimport org.springframework.context.ApplicationContext;\n\nimport com.sohu.cache.machine.MachineCenter;\nimport com.sohu.cache.util.ConstUtils;\n\n/**\n * 监控机器的状态信息的job\n *\n * User: lingguo\n * Date: 14-7-2\n */\npublic class MachineMonitorJob extends CacheBaseJob {\n    @Override\n    public void action(JobExecutionContext context) {\n        try {\n            JobDataMap dataMap = context.getMergedJobDataMap();\n            String ip = dataMap.getString(ConstUtils.HOST_KEY);\n            long hostId = dataMap.getLong(ConstUtils.HOST_ID_KEY);\n\n            SchedulerContext schedulerContext = context.getScheduler().getContext();\n            ApplicationContext applicationContext = (ApplicationContext) schedulerContext.get(APPLICATION_CONTEXT_KEY);\n            MachineCenter machineCenter = applicationContext.getBean(\"machineCenter\", MachineCenter.class);\n            machineCenter.asyncMonitorMachineStats(hostId, ip);\n        } catch (SchedulerException e) {\n            logger.error(e.getMessage(), e);\n        }\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/schedule/jobs/RedisJob.java",
    "content": "package com.sohu.cache.schedule.jobs;\n\nimport com.sohu.cache.redis.RedisCenter;\nimport com.sohu.cache.util.ConstUtils;\nimport com.sohu.cache.util.ScheduleUtil;\n\nimport org.quartz.JobDataMap;\nimport org.quartz.JobExecutionContext;\nimport org.quartz.SchedulerContext;\nimport org.quartz.SchedulerException;\nimport org.quartz.Trigger;\nimport org.springframework.context.ApplicationContext;\n\n/**\n * redis job类\n * <p/>\n * User: lingguo\n * Date: 14-5-13\n * Time: 下午4:11\n */\npublic class RedisJob extends CacheBaseJob {\n    private static final long serialVersionUID = 2626836144949582163L;\n\n    /**\n     * 实现收集任务，通过RedisCenter\n     *\n     * @param context\n     */\n    @Override\n    public void action(JobExecutionContext context) {\n        JobDataMap dataMap = new JobDataMap();\n        try {\n            SchedulerContext schedulerContext = context.getScheduler().getContext();\n            ApplicationContext applicationContext = (ApplicationContext) schedulerContext.get(APPLICATION_CONTEXT_KEY);\n            RedisCenter redisCenter = (RedisCenter) applicationContext.getBean(\"redisCenter\");\n            dataMap = context.getMergedJobDataMap();\n            String host = dataMap.getString(ConstUtils.HOST_KEY);\n            int port = dataMap.getInt(ConstUtils.PORT_KEY);\n            long appId = dataMap.getLong(ConstUtils.APP_KEY);\n            Trigger trigger = context.getTrigger();\n            long collectTime = ScheduleUtil.getCollectTime(trigger.getPreviousFireTime());\n            redisCenter.collectRedisInfo(appId, collectTime, host, port);\n        } catch (SchedulerException e) {\n            logger.error(\"host: {}, appId: {}\", dataMap.get(ConstUtils.HOST_KEY), dataMap.get(ConstUtils.APP_KEY));\n            logger.error(\"port: {}\", dataMap.get(ConstUtils.PORT_KEY));\n            logger.error(e.getMessage(), e);\n        } catch (Exception e) {\n            logger.error(\"host: {}, appId: {}\", dataMap.get(ConstUtils.HOST_KEY), dataMap.get(ConstUtils.APP_KEY));\n            logger.error(\"port: {}\", dataMap.get(ConstUtils.PORT_KEY));\n            logger.error(e.getMessage(), e);\n        }\n    }\n}\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/schedule/jobs/RedisSlowLogJob.java",
    "content": "package com.sohu.cache.schedule.jobs;\n\nimport com.sohu.cache.redis.RedisCenter;\nimport com.sohu.cache.util.ConstUtils;\nimport com.sohu.cache.util.ScheduleUtil;\n\nimport org.quartz.JobDataMap;\nimport org.quartz.JobExecutionContext;\nimport org.quartz.SchedulerContext;\nimport org.quartz.SchedulerException;\nimport org.quartz.Trigger;\nimport org.springframework.context.ApplicationContext;\n\n/**\n * redis慢查询job\n * \n * @author leifu\n * @Date 2016年2月22日\n * @Time 上午9:38:49\n */\npublic class RedisSlowLogJob extends CacheBaseJob {\n    private static final long serialVersionUID = 2626836144949582163L;\n\n    @Override\n    public void action(JobExecutionContext context) {\n        try {\n            SchedulerContext schedulerContext = context.getScheduler().getContext();\n            ApplicationContext applicationContext = (ApplicationContext) schedulerContext.get(APPLICATION_CONTEXT_KEY);\n            RedisCenter redisCenter = (RedisCenter) applicationContext.getBean(\"redisCenter\");\n            JobDataMap dataMap = context.getMergedJobDataMap();\n            String host = dataMap.getString(ConstUtils.HOST_KEY);\n            int port = dataMap.getInt(ConstUtils.PORT_KEY);\n            long appId = dataMap.getLong(ConstUtils.APP_KEY);\n            Trigger trigger = context.getTrigger();\n            long collectTime = ScheduleUtil.getCollectTime(trigger.getPreviousFireTime());\n            redisCenter.collectRedisSlowLog(appId, collectTime, host, port);\n        } catch (SchedulerException e) {\n            logger.error(e.getMessage(), e);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/schedule/jobs/ServerJob.java",
    "content": "package com.sohu.cache.schedule.jobs;\n\nimport org.quartz.JobDataMap;\nimport org.quartz.JobExecutionContext;\nimport org.quartz.SchedulerContext;\nimport org.quartz.SchedulerException;\nimport org.springframework.context.ApplicationContext;\n\nimport com.sohu.cache.server.ServerStatusCollector;\nimport com.sohu.cache.util.ConstUtils;\n\n/**\n * 基于服务器的job\n */\npublic class ServerJob extends CacheBaseJob {\n\n    @Override\n    public void action(JobExecutionContext context) {\n//        try {\n//            JobDataMap dataMap =  context.getMergedJobDataMap();\n//            SchedulerContext schedulerContext = context.getScheduler().getContext();\n//            ApplicationContext applicationContext = (ApplicationContext)schedulerContext.get(APPLICATION_CONTEXT_KEY);\n//            ServerStatusCollector serverStatusCollector = applicationContext.getBean(\"serverStatusCollector\", ServerStatusCollector.class);\n//            String ip = dataMap.getString(ConstUtils.HOST_KEY);\n//            serverStatusCollector.fetchServerStatus(ip);\n//        } catch (SchedulerException e) {\n//            logger.error(e.getMessage(), e);\n//        } catch (Exception e) {\n//            logger.error(e.getMessage(), e);\n//        }\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/schedule/jobs/SystemConfigRefreshJob.java",
    "content": "package com.sohu.cache.schedule.jobs;\n\nimport org.quartz.JobExecutionContext;\nimport org.quartz.SchedulerContext;\nimport org.quartz.SchedulerException;\nimport org.springframework.context.ApplicationContext;\n\nimport com.sohu.cache.schedule.jobs.CacheBaseJob;\nimport com.sohu.cache.web.service.ConfigService;\n\n/**\n * 刷新系统配置\n * @author leifu\n * @Date 2016年6月30日\n * @Time 下午5:30:42\n */\npublic class SystemConfigRefreshJob extends CacheBaseJob {\n\n    private static final long serialVersionUID = 7751425759758902400L;\n\n    @Override\n    public void action(JobExecutionContext context) {\n        try {\n            SchedulerContext schedulerContext = context.getScheduler().getContext();\n            ApplicationContext applicationContext = (ApplicationContext) schedulerContext.get(APPLICATION_CONTEXT_KEY);\n            ConfigService configService = applicationContext.getBean(\"configService\", ConfigService.class);\n            configService.reloadSystemConfig();\n        } catch (SchedulerException e) {\n            logger.error(e.getMessage(), e);\n        }\n        \n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/server/ServerStatusCollector.java",
    "content": "package com.sohu.cache.server;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.sohu.cache.async.AsyncService;\nimport com.sohu.cache.async.AsyncThreadPoolFactory;\nimport com.sohu.cache.async.KeyCallable;\nimport com.sohu.cache.server.data.OSInfo;\nimport com.sohu.cache.server.data.Server;\nimport com.sohu.cache.server.nmon.NMONService;\nimport com.sohu.cache.ssh.SSHTemplate;\nimport com.sohu.cache.ssh.SSHTemplate.DefaultLineProcessor;\nimport com.sohu.cache.ssh.SSHTemplate.Result;\nimport com.sohu.cache.ssh.SSHTemplate.SSHCallback;\nimport com.sohu.cache.ssh.SSHTemplate.SSHSession;\nimport com.sohu.cache.web.service.ServerDataService;\n\n/**\n * 服务器状态监控服务\n */\npublic class ServerStatusCollector {\n\tprivate static final Logger logger = LoggerFactory.getLogger(ServerStatusCollector.class);\n\n\t//获取监控结果\n\tpublic static final String COLLECT_SERVER_STATUS = \n\t\t\t  \"[ -e \\\"\"+NMONService.SOCK_LOG+\"\\\" ] && /bin/cat \" + NMONService.SOCK_LOG + \" >> \" + NMONService.NMON_LOG\n\t\t\t+ \";[ -e \\\"\"+NMONService.ULIMIT_LOG+\"\\\" ] && /bin/cat \" + NMONService.ULIMIT_LOG + \" >> \" + NMONService.NMON_LOG\n\t\t\t+ \";/bin/mv \" + NMONService.NMON_LOG + \" \" + NMONService.NMON_OLD_LOG\n\t\t\t+ \";[ $? -eq 0 ] && /bin/cat \" + NMONService.NMON_OLD_LOG;\n\t\n\t//nmon服务\n\tprivate NMONService nmonService;\n\t//ssh 模板类\n\tprivate SSHTemplate sshTemplate;\n\t//持久化\n\tprivate ServerDataService serverDataService;\n\t\n\tprivate AsyncService asyncService;\n\t\n\tpublic void init() {\n\t\tasyncService.assemblePool(AsyncThreadPoolFactory.MACHINE_POOL, \n\t\t\t\tAsyncThreadPoolFactory.MACHINE_THREAD_POOL);\n\t}\n\t\n\t//异步执行任务\n\tpublic void asyncFetchServerStatus(final String ip) {\n\t\tString key = \"collect-server-\"+ip;\n\t\tasyncService.submitFuture(AsyncThreadPoolFactory.MACHINE_POOL, new KeyCallable<Boolean>(key) {\n            public Boolean execute() {\n                try {\n                \tfetchServerStatus(ip);\n                    return true;\n                } catch (Exception e) {\n                    logger.error(e.getMessage(), e);\n                    return false;\n                }\n            }\n        });\n\t}\n\t\n\t/**\n\t * 抓取服务器状态\n\t * @param ip\n\t */\n\tpublic void fetchServerStatus(final String ip) {\n\t\ttry {\n\t\t\tsshTemplate.execute(ip, new SSHCallback() {\n\t\t\t\tpublic Result call(SSHSession session) {\n\t\t\t\t\t//尝试收集服务器运行状况\n\t\t\t\t\tcollectServerStatus(ip, session);\n\t\t\t\t\t//启动nmon收集服务器运行状况\n\t\t\t\t\tOSInfo info = nmonService.start(ip, session);\n\t\t\t\t\tsaveServerStatus(ip, info);\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t});\n\t\t} catch (Exception e) {\n\t\t\tlogger.error(\"fetchServerStatus \"+ip+\" err\", e);\n\t\t}\n\t}\n\t\n\t/**\n\t * 收集系统状况\n\t * @param ip\n\t * @param session\n\t */\n\tprivate void collectServerStatus(String ip, SSHSession session) {\n\t\tfinal Server server = new Server();\n\t\tserver.setIp(ip);\n\t\tResult result = session.executeCommand(COLLECT_SERVER_STATUS, new DefaultLineProcessor() {\n\t\t\tpublic void process(String line, int lineNum) throws Exception {\n\t\t\t\tserver.parse(line, null);\n\t\t\t}\n\t\t});\n\t\tif(!result.isSuccess()) {\n\t\t\tlogger.error(\"collect \" + ip + \" err:\" + result.getResult(), result.getExcetion());\n\t\t}\n\t\t//保存服务器静态信息\n\t\tserverDataService.saveAndUpdateServerInfo(server);\n\t\t//保存服务器状况信息\n\t\tserverDataService.saveServerStat(server);\n\t}\n\t\n\t/**\n\t * 保存服务器dist信息\n\t * @param ip\n\t * @param OSInfo\n\t */\n\tprivate void saveServerStatus(String ip, OSInfo osInfo) {\n\t\tif(osInfo == null) {\n\t\t\treturn;\n\t\t}\n\t\tserverDataService.saveServerInfo(ip, osInfo.getIssue());\n\t}\n\t\n\tpublic void setNmonService(NMONService nmonService) {\n\t\tthis.nmonService = nmonService;\n\t}\n\tpublic void setSshTemplate(SSHTemplate sshTemplate) {\n\t\tthis.sshTemplate = sshTemplate;\n\t}\n\tpublic void setServerDataService(ServerDataService serverDataService) {\n\t\tthis.serverDataService = serverDataService;\n\t}\n\tpublic void setAsyncService(AsyncService asyncService) {\n\t\tthis.asyncService = asyncService;\n\t}\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/server/data/CPU.java",
    "content": "package com.sohu.cache.server.data;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.apache.commons.lang.math.NumberUtils;\n/**\n *\tcpu状况\n */\npublic class CPU implements LineParser{\n\tpublic static final String FLAG = \"CPU\";\n\tpublic static final String CPU_ALL = \"CPU_ALL\";\n\tprivate Usage allUsage;\n\t//包含各个虚拟cpu的情况\n\tprivate List<Usage> cpuList = new ArrayList<Usage>();\n\t\n\t/**\n\t * line format:\n\t * CPU001,CPU 1 bx-50-13,User%,Sys%,Wait%,Idle%\n\t * CPU002,CPU 2 bx-50-13,User%,Sys%,Wait%,Idle%\n\t * CPU_ALL,CPU Total bx-50-13,User%,Sys%,Wait%,Idle%,Busy,CPUs\n\t * CPU001,T0001,1.8,0.9,4.5,92.9\n\t * CPU002,T0001,3.6,1.8,0.0,94.6\n\t * CPU_ALL,T0001,2.1,1.3,0.6,95.9,,16\n\t */\n\tpublic void parse(String line, String timeKey) throws Exception{\n\t\tif(line.startsWith(FLAG)) {\n\t\t\tString[] items = line.split(\",\", 6);\n\t\t\tif(items.length != 6) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif(!items[1].equals(timeKey)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tUsage usage = new Usage();\n\t\t\tusage.setUser(NumberUtils.toFloat(items[2]));\n\t\t\tusage.setSys(NumberUtils.toFloat(items[3]));\n\t\t\tusage.setWait(NumberUtils.toFloat(items[4]));\n\t\t\tif(CPU_ALL.equals(items[0])) {\n\t\t\t\tallUsage = usage;\n\t\t\t} else {\n\t\t\t\tusage.setName(items[0]);\n\t\t\t\tcpuList.add(usage);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic List<Usage> getCpuList() {\n\t\treturn cpuList;\n\t}\n\t\n\tpublic Usage getAllUsage() {\n\t\treturn allUsage;\n\t}\n\t\n\tpublic float getUser() {\n\t\treturn allUsage == null ? 0 : allUsage.getUser();\n\t}\n\t\n\tpublic float getSys() {\n\t\treturn allUsage == null ? 0 : allUsage.getSys();\n\t}\n\t\n\tpublic float getWait() {\n\t\treturn allUsage == null ? 0 : allUsage.getWait();\n\t}\n\t\n\tpublic String getExt(){\n\t\tStringBuilder sb = new StringBuilder();\n\t\tfor(Usage usage : cpuList) {\n\t\t\tsb.append(usage.getName());\n\t\t\tsb.append(\",\");\n\t\t\tsb.append(usage.getUser());\n\t\t\tsb.append(\",\");\n\t\t\tsb.append(usage.getSys());\n\t\t\tsb.append(\",\");\n\t\t\tsb.append(usage.getWait());\n\t\t\tsb.append(\";\");\n\t\t}\n\t\treturn sb.toString();\n\t}\n\tpublic String toString() {\n\t\treturn \"CPU [cpuList=\" + cpuList + \"]\";\n\t}\n\n\t/**\n\t * cpu使用率\n\t */\n\tpublic class Usage{\n\t\t//代表那个cpu\n\t\tprivate String name;\n\t\t//用户空间使用率\n\t\tprivate float user;\n\t\t//内核空间使用率\n\t\tprivate float sys;\n\t\t//wio\n\t\tprivate float wait;\n\t\tpublic float getUser() {\n\t\t\treturn user;\n\t\t}\n\t\tpublic void setUser(float user) {\n\t\t\tthis.user = user;\n\t\t}\n\t\tpublic float getSys() {\n\t\t\treturn sys;\n\t\t}\n\t\tpublic void setSys(float sys) {\n\t\t\tthis.sys = sys;\n\t\t}\n\t\tpublic float getWait() {\n\t\t\treturn wait;\n\t\t}\n\t\tpublic void setWait(float wait) {\n\t\t\tthis.wait = wait;\n\t\t}\n\t\tpublic String getName() {\n\t\t\treturn name;\n\t\t}\n\t\tpublic void setName(String name) {\n\t\t\tthis.name = name;\n\t\t}\n\t\t@Override\n\t\tpublic String toString() {\n\t\t\treturn \"Usage [name=\" + name + \", user=\" + user + \", sys=\" + sys\n\t\t\t\t\t+ \", wait=\" + wait + \"]\";\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/server/data/Connection.java",
    "content": "package com.sohu.cache.server.data;\n\nimport org.apache.commons.lang.math.NumberUtils;\n\n/**\n * tcp连接\n */\npublic class Connection implements LineParser{\n\tpublic static final String FLAG = \"TCP\";\n\t\n\tprivate int established;\n\tprivate int timeWait;\n\tprivate int orphan;\n\t\n\t/**\n\t * line format:\n\t * TCP: inuse 454 orphan 0 tw 159620 alloc 454 mem 79\n\t */\n\tpublic void parse(String line, String timeKey) throws Exception{\n\t\tif(line.startsWith(FLAG)) {\n\t\t\tString[] items = line.split(\"\\\\s+\");\n\t\t\tfor(int i = 0; i < items.length; ++i) {\n\t\t\t\tif(items[i].equals(\"inuse\")) {\n\t\t\t\t\testablished = NumberUtils.toInt(items[i+1]);\n\t\t\t\t} else if(items[i].equals(\"orphan\")) {\n\t\t\t\t\torphan = NumberUtils.toInt(items[i+1]);\n\t\t\t\t} else if(items[i].equals(\"tw\")) {\n\t\t\t\t\ttimeWait = NumberUtils.toInt(items[i+1]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tpublic int getEstablished() {\n\t\treturn established;\n\t}\n\n\tpublic int getTimeWait() {\n\t\treturn timeWait;\n\t}\n\n\tpublic int getOrphan() {\n\t\treturn orphan;\n\t}\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/server/data/Disk.java",
    "content": "package com.sohu.cache.server.data;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.regex.Pattern;\n\nimport org.apache.commons.lang.math.NumberUtils;\n/**\n * io读写情况\n */\npublic class Disk implements LineParser{\n\tpublic static final String FLAG = \"DISK\";\n\tpublic static final Pattern PATTERN = Pattern.compile(\"^BBBP,[0-9]+,/bin/df-m,\");\n\tpublic static final Pattern SUBPARTITION_PATTERN = Pattern.compile(\"[0-9]+$\");\n\t//包括总的状况及各个分区的状况\n\tprivate Map<DiskUsageType, List<Usage>> diskMap = new HashMap<Disk.DiskUsageType, List<Usage>>();\n\t\n\t/**\n\t * line format:\n\t * DISKBUSY,Disk %Busy iZ256oe4w5bZ,xvda,xvda1,xvdb,xvdb1\n\t * DISKREAD,Disk Read KB/s iZ256oe4w5bZ,xvda,xvda1,xvdb,xvdb1\n\t * DISKWRITE,Disk Write KB/s iZ256oe4w5bZ,xvda,xvda1,xvdb,xvdb1\n\t * DISKXFER,Disk transfers per second iZ256oe4w5bZ,xvda,xvda1,xvdb,xvdb1\n\t * DISKBSIZE,Disk Block Size iZ256oe4w5bZ,xvda,xvda1,xvdb,xvdb1\n\t * DISKBUSY,T0001,0.0,0.0,0.0,0.0\n\t * DISKREAD,T0001,0.0,0.0,0.0,0.0\n\t * DISKWRITE,T0001,0.0,0.0,0.0,0.0\n\t * DISKXFER,T0001,0.0,0.0,0.0,0.0\n\t * DISKBSIZE,T0001,0.0,0.0,0.0,0.0\n\t * BBBP,173,/bin/df-m,\"ddev/xvda1         20158 16018      3117  84% /\"\n\t */\n\tpublic void parse(String line, String timeKey) throws Exception{\n\t\tif(line.startsWith(FLAG)) {\n\t\t\tString[] items = line.split(\",\");\n\t\t\tif(!items[1].equals(timeKey)) {\n\t\t\t\tDiskUsageType type = DiskUsageType.getType(items[0]);\n\t\t\t\tif(type == null) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tList<Usage> list = diskMap.get(type);\n\t\t\t\tif(list == null) {\n\t\t\t\t\tlist = new ArrayList<Usage>();\n\t\t\t\t\tdiskMap.put(type, list);\n\t\t\t\t}\n\t\t\t\tfor(int i = 2; i < items.length; ++i) {\n\t\t\t\t\tUsage usage = new Usage();\n\t\t\t\t\tusage.setDiskUsageTyp(type);\n\t\t\t\t\tusage.setName(items[i]);\n\t\t\t\t\tlist.add(usage);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tDiskUsageType type = DiskUsageType.getType(items[0]);\n\t\t\t\tif(type == null) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tList<Usage> list = diskMap.get(type);\n\t\t\t\tif(list == null) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tfor(int i = 2; i < items.length; ++i) {\n\t\t\t\t\tfloat value = NumberUtils.toFloat(items[i]);\n\t\t\t\t\tif(value > 0) {\n\t\t\t\t\t\tlist.get(i-2).setValue(value);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else if(PATTERN.matcher(line).find()) {\n\t\t\tString[] tmp = line.split(\",\\\"\");\n\t\t\tif(tmp.length > 0) {\n\t\t\t\tString[] item = tmp[tmp.length - 1].split(\"\\\\s+\");\n\t\t\t\tif(item.length != 6 || !item[4].contains(\"%\")) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tList<Usage> list = diskMap.get(DiskUsageType.busy);\n\t\t\t\tString[] tp = item[0].split(\"/\");\n\t\t\t\tString mount = tp[tp.length - 1];\n\t\t\t\tfor(Usage usage : list) {\n\t\t\t\t\tif(usage.getName().equals(mount)) {\n\t\t\t\t\t\tList<Usage> spaceList = diskMap.get(DiskUsageType.space);\n\t\t\t\t\t\tif(spaceList == null) {\n\t\t\t\t\t\t\tspaceList = new ArrayList<Usage>();\n\t\t\t\t\t\t\tdiskMap.put(DiskUsageType.space, spaceList);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tUsage spaceUsage = new Usage();\n\t\t\t\t\t\tspaceUsage.setDiskUsageTyp(DiskUsageType.space);\n\t\t\t\t\t\tspaceUsage.setName(usage.getName());\n\t\t\t\t\t\tspaceUsage.setValue(NumberUtils.toFloat(item[4].split(\"%\")[0]));\n\t\t\t\t\t\tspaceList.add(spaceUsage);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t\n\tpublic Map<DiskUsageType, List<Usage>> getDiskMap() {\n\t\treturn diskMap;\n\t}\n\t\n\tpublic float getRead() {\n\t\tList<Usage> usageList = diskMap.get(DiskUsageType.read);\n\t\treturn getUsage(usageList);\n\t}\n\t\n\tpublic float getWrite() {\n\t\tList<Usage> usageList = diskMap.get(DiskUsageType.write);\n\t\treturn getUsage(usageList);\n\t}\n\t\n\tpublic float getIops() {\n\t\tList<Usage> usageList = diskMap.get(DiskUsageType.transfer);\n\t\treturn getUsage(usageList);\n\t}\n\t\n\tpublic float getBusy() {\n\t\tList<Usage> usageList = diskMap.get(DiskUsageType.busy);\n\t\treturn getUsage(usageList);\n\t}\n\t\n\tpublic String getExt() {\n\t\tStringBuilder sb = new StringBuilder();\n\t\tfor(DiskUsageType type : diskMap.keySet()) {\n\t\t\tif(DiskUsageType.space == type) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tsb.append(type.getValue());\n\t\t\tsb.append(\"=\");\n\t\t\tList<Usage> usageList = diskMap.get(type);\n\t\t\tfor(Usage use : usageList) {\n                sb.append(use.getName());\n                sb.append(\":\");\n                sb.append(use.getValue());\n                sb.append(\",\");\n            }\n\t\t\tsb.append(\";\");\n\t\t}\n\t\treturn sb.toString();\n\t}\n\t\n\tpublic String getSpace() {\n\t\tStringBuilder sb = new StringBuilder();\n\t\tList<Usage> usageList = diskMap.get(DiskUsageType.space);\n\t\tif(usageList == null) {\n\t\t\treturn sb.toString();\n\t\t}\n\t\tfor(Usage use : usageList) {\n\t\t\tsb.append(use.getName());\n\t\t\tsb.append(\":\");\n\t\t\tsb.append(use.getValue());\n\t\t\tsb.append(\",\");\n\t\t}\n\t\treturn sb.toString();\n\t}\n\t\n\tprivate float getUsage(List<Usage> usageList) {\n\t\tfloat usage = 0;\n\t\tif(usageList != null) {\n\t\t\tfor(Usage u : usageList) {\n\t\t\t\tif(!SUBPARTITION_PATTERN.matcher(u.getName()).find()) {\n\t\t\t\t\tusage += u.getValue();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn usage;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"Disk [diskMap=\" + diskMap + \"]\";\n\t}\n\t\n\t/**\n\t * 使用率\n\t */\n\tclass Usage{\n\t\t//分区名字\n\t\tprivate String name;\n\t\t//使用率类型\n\t\tprivate DiskUsageType diskUsageType;\n\t\t//使用率\n\t\tprivate float value;\n\t\tpublic DiskUsageType getDiskUsageType() {\n\t\t\treturn diskUsageType;\n\t\t}\n\t\tpublic void setDiskUsageTyp(DiskUsageType diskUsageType) {\n\t\t\tthis.diskUsageType = diskUsageType;\n\t\t}\n\t\tpublic float getValue() {\n\t\t\treturn value;\n\t\t}\n\t\tpublic void setValue(float value) {\n\t\t\tthis.value = value;\n\t\t}\n\t\tpublic String getName() {\n\t\t\treturn name;\n\t\t}\n\t\tpublic void setName(String name) {\n\t\t\tthis.name = name;\n\t\t}\n\t\t@Override\n\t\tpublic String toString() {\n\t\t\treturn \"Usage [name=\" + name + \", diskUsageType=\" + diskUsageType\n\t\t\t\t\t+ \", value=\" + value + \"]\";\n\t\t}\n\t}\n\t/**\n\t * 使用率类型\n\t */\n\tenum DiskUsageType{\n\t\t//繁忙程度\n\t\tbusy(\"DISKBUSY\"),\n\t\t//读\n\t\tread(\"DISKREAD\"),\n\t\t//写\n\t\twrite(\"DISKWRITE\"),\n\t\t//io次数\n\t\ttransfer(\"DISKXFER\"),\n\t\t//空间使用率\n\t\tspace(\"df\"),\n\t\t;\n\t\tprivate String value;\n\t\t\n\t\tprivate DiskUsageType(String value) {\n\t\t\tthis.value = value;\n\t\t}\n\t\tpublic String getValue() {\n\t\t\treturn value;\n\t\t}\n\t\tpublic static DiskUsageType getType(String type) {\n\t\t\tfor(DiskUsageType dut : DiskUsageType.values()) {\n\t\t\t\tif(dut.getValue().equals(type)) {\n\t\t\t\t\treturn dut;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/server/data/LineParser.java",
    "content": "package com.sohu.cache.server.data;\n/**\n * 行解析器\n */\npublic interface LineParser {\n\t/**\n\t * 解析nmon行\n\t * @param line     nmon行内容\n\t * @param timeKey  时间戳\n\t * @throws Exception\n\t */\n\tvoid parse(String line, String timeKey) throws Exception;\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/server/data/Load.java",
    "content": "package com.sohu.cache.server.data;\n\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\nimport org.apache.commons.lang.math.NumberUtils;\n\n/**\n * 系统负载\n */\npublic class Load implements LineParser{\n\tpublic static final Pattern PATTERN = Pattern.compile(\n\t\t\t\"^BBBP,[0-9]+,uptime,.*(\\\\d+\\\\.\\\\d+), (\\\\d+\\\\.\\\\d+), (\\\\d+\\\\.\\\\d+)\");\n\t//1分钟负载\n\tprivate float load1;\n\t//5分钟负载\n\tprivate float load5;\n\t//15分钟负载\n\tprivate float load15;\n\t\n\t/**\n\t * line format:\n\t * BBBP,585,uptime,\" 09:35:00 up 567 days, 15:07,  0 users,  load average: 0.60, 0.63, 0.67\"\n\t */\n\tpublic void parse(String line, String timeKey) throws Exception{\n\t\tMatcher matcher = PATTERN.matcher(line);\n\t\tif(matcher.find()) {\n\t\t\tload1 = NumberUtils.toFloat(matcher.group(1));\n\t\t\tload5 = NumberUtils.toFloat(matcher.group(2));\n\t\t\tload15 = NumberUtils.toFloat(matcher.group(3));\n\t\t}\n\t}\n\t\n\tpublic float getLoad1() {\n\t\treturn load1;\n\t}\n\tpublic float getLoad5() {\n\t\treturn load5;\n\t}\n\tpublic float getLoad15() {\n\t\treturn load15;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"Load [load1=\" + load1 + \", load5=\" + load5 + \", load15=\"\n\t\t\t\t+ load15 + \"]\";\n\t}\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/server/data/Memory.java",
    "content": "package com.sohu.cache.server.data;\n\nimport org.apache.commons.lang.math.NumberUtils;\n/**\n * 内存使用情况\n */\npublic class Memory implements LineParser{\n\tpublic static final String FLAG = \"MEM\";\n\t//总内存，单位M\n\tprivate float total;\n\t//总空闲内存，单位M\n\tprivate float totalFree;\n\t//buffer，单位M\n\tprivate float buffer;\n\t//cache，单位M\n\tprivate float cache;\n\t//swap，单位M\n\tprivate float swap;\n\t//swap空闲内存，单位M\n\tprivate float swapFree;\n\t\n\t/**\n\t * line format:\n\t * MEM,Memory MB bx-50-13,memtotal,hightotal,lowtotal,swaptotal,memfree,highfree,lowfree,swapfree,memshared,cached,active,bigfree,buffers,swapcached,inactive\n\t * MEM,T0001,48288.7,0.0,48288.7,8189.4,132.6,0.0,132.6,8189.1,-0.0,24210.6,30819.7,-1.0,153.9,0.0,16451.1\n\t */\n\tpublic void parse(String line, String timeKey) throws Exception{\n\t\tif(line.startsWith(FLAG)) {\n\t\t\tString[] items = line.split(\",\");\n\t\t\tif(!items[1].equals(timeKey)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\ttotal = NumberUtils.toFloat(items[2]);\n\t\t\tswap = NumberUtils.toFloat(items[5]);\n\t\t\ttotalFree = NumberUtils.toFloat(items[6]);\n\t\t\tswapFree = NumberUtils.toFloat(items[9]);\n\t\t\tcache = NumberUtils.toFloat(items[11]);\n\t\t\tbuffer = NumberUtils.toFloat(items[14]);\n\t\t}\n\t}\n\t\n\tpublic float getTotal() {\n\t\treturn total;\n\t}\n\n\tpublic float getTotalFree() {\n\t\treturn totalFree;\n\t}\n\n\tpublic float getBuffer() {\n\t\treturn buffer;\n\t}\n\n\tpublic float getCache() {\n\t\treturn cache;\n\t}\n\n\tpublic float getSwap() {\n\t\treturn swap;\n\t}\n\n\tpublic float getSwapFree() {\n\t\treturn swapFree;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"Memory [total=\" + total + \", totalFree=\" + totalFree\n\t\t\t\t+ \", buffer=\" + buffer + \", cache=\" + cache + \", swap=\" + swap\n\t\t\t\t+ \", swapFree=\" + swapFree + \"]\";\n\t}\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/server/data/Net.java",
    "content": "package com.sohu.cache.server.data;\n\nimport java.math.BigDecimal;\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.apache.commons.lang.math.NumberUtils;\n\n\n/**\n * 网络流量\n */\npublic class Net implements LineParser{\n\tpublic static final String FLAG = \"NET,\";\n\t\n\tprivate float nin;\n\tprivate float nout;\n\tprivate StringBuilder ninDetail = new StringBuilder();\n\tprivate StringBuilder noutDetail = new StringBuilder();\n\t\n\tprivate List<NetworkInterfaceCard> ncList = new ArrayList<NetworkInterfaceCard>();\n\t\n\t/**\n\t * line format:\n\t * NET,Network I/O bx-50-13,lo-read-KB/s,eth0-read-KB/s,eth1-read-KB/s,eth2-read-KB/s,eth3-read-KB/s,lo-write-KB/s,eth0-write-KB/s,eth1-write-KB/s,eth2-write-KB/s,eth3-write-KB/s,\n\t * NET,T0001,190.3,3317.8,0.0,0.0,0.0,190.3,3377.7,0.0,0.0,0.0,\n\t */\n\tpublic void parse(String line, String timeKey) throws Exception{\n\t\tif(line.startsWith(FLAG)) {\n\t\t\tString[] items = line.split(\",\");\n\t\t\tif(items[1].startsWith(\"Network\")) {\n\t\t\t\tfor(int i = 0; i < items.length; ++i) {\n\t\t\t\t\tif(items[i].startsWith(\"eth\")) {\n\t\t\t\t\t\tNetworkInterfaceCard nic = new NetworkInterfaceCard();\n\t\t\t\t\t\tnic.setName(items[i]);\n\t\t\t\t\t\tnic.setIdx(i);\n\t\t\t\t\t\tncList.add(nic);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor(NetworkInterfaceCard nic : ncList) {\n\t\t\t\t\tnic.setValue(NumberUtils.toFloat(items[nic.getIdx()]));\n\t\t\t\t}\n\t\t\t\tcaculate();\n\t\t\t}\n\t\t}\n\t}\n\t\n\tprivate void caculate() {\n\t\tfloat totalIn = 0;\n\t\tfloat totalOut = 0;\n\t\tfor(NetworkInterfaceCard nic : ncList) {\n\t\t\tString[] array = nic.getName().split(\"-\");\n\t\t\tif(\"read\".equals(array[1])) {\n\t\t\t\tninDetail.append(array[0]);\n\t\t\t\tninDetail.append(\",\");\n\t\t\t\tninDetail.append(nic.getValue());\n\t\t\t\tninDetail.append(\";\");\n\t\t\t\ttotalIn += nic.getValue();\n\t\t\t} else if(\"write\".equals(array[1])) {\n\t\t\t\tnoutDetail.append(array[0]);\n\t\t\t\tnoutDetail.append(\",\");\n\t\t\t\tnoutDetail.append(nic.getValue());\n\t\t\t\tnoutDetail.append(\";\");\n\t\t\t\ttotalOut += nic.getValue();\n\t\t\t}\n\t\t}\n\t\tnin = new BigDecimal(totalIn).setScale(2, BigDecimal.ROUND_HALF_UP).floatValue(); \n\t\tnout = new BigDecimal(totalOut).setScale(2, BigDecimal.ROUND_HALF_UP).floatValue(); \n\t}\n\t\n\tpublic float getNin() {\n\t\treturn nin;\n\t}\n\n\tpublic float getNout() {\n\t\treturn nout;\n\t}\n\tpublic String getNinDetail() {\n\t\treturn ninDetail.toString();\n\t}\n\n\tpublic String getNoutDetail() {\n\t\treturn noutDetail.toString();\n\t}\n\n\tclass NetworkInterfaceCard{\n\t\tprivate String name;\n\t\tprivate float value;\n\t\tprivate int idx;\n\t\tpublic String getName() {\n\t\t\treturn name;\n\t\t}\n\t\tpublic void setName(String name) {\n\t\t\tthis.name = name;\n\t\t}\n\t\tpublic float getValue() {\n\t\t\treturn value;\n\t\t}\n\t\tpublic void setValue(float value) {\n\t\t\tthis.value = value;\n\t\t}\n\t\tpublic int getIdx() {\n\t\t\treturn idx;\n\t\t}\n\t\tpublic void setIdx(int idx) {\n\t\t\tthis.idx = idx;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/server/data/OS.java",
    "content": "package com.sohu.cache.server.data;\n\nimport com.sohu.cache.server.data.OSInfo.DistributionType;\nimport com.sohu.cache.server.data.OSInfo.DistributionVersion;\nimport com.sohu.cache.server.data.OSInfo.OSType;\nimport com.sohu.cache.server.data.OSInfo.ProcessorArchitecture;\n/**\n * 从OSInfo解析后的OS\n */\npublic class OS {\n\t//操作系统类型\n\tprivate OSType osType;\n\t//发行版本\n\tprivate DistributionType distributionType;\n\t//发行版本号\n\tprivate DistributionVersion distributionVersion;\n\t//处理器架构\n\tprivate ProcessorArchitecture processorArchitecture;\n\t\n\tpublic OS(OSType osType, DistributionType distributionType,\n\t\t\tDistributionVersion distributionVersion,\n\t\t\tProcessorArchitecture processorArchitecture) {\n\t\tthis.osType = osType;\n\t\tthis.distributionType = distributionType;\n\t\tthis.distributionVersion = distributionVersion;\n\t\tthis.processorArchitecture = processorArchitecture;\n\t}\n\n\tpublic OSType getOsType() {\n\t\treturn osType;\n\t}\n\n\tpublic void setOsType(OSType osType) {\n\t\tthis.osType = osType;\n\t}\n\n\tpublic DistributionType getDistributionType() {\n\t\treturn distributionType;\n\t}\n\n\tpublic void setDistributionType(DistributionType distributionType) {\n\t\tthis.distributionType = distributionType;\n\t}\n\t\n\tpublic DistributionVersion getDistributionVersion() {\n\t\treturn distributionVersion;\n\t}\n\n\tpublic void setDistributionVersion(DistributionVersion distributionVersion) {\n\t\tthis.distributionVersion = distributionVersion;\n\t}\n\n\tpublic ProcessorArchitecture getProcessorArchitecture() {\n\t\treturn processorArchitecture;\n\t}\n\n\tpublic void setProcessorArchitecture(ProcessorArchitecture processorArchitecture) {\n\t\tthis.processorArchitecture = processorArchitecture;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"OS [osType=\" + osType + \", dist=\"\n\t\t\t\t+ distributionType + \", version=\"\n\t\t\t\t+ distributionVersion + \", bit=\"\n\t\t\t\t+ processorArchitecture + \"]\";\n\t}\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/server/data/OSInfo.java",
    "content": "package com.sohu.cache.server.data;\n/**\n * 代表操作系统的原始信息\n * 及一些类型定义\n */\npublic class OSInfo {\n\t//操作系统信息  uname -a\n\tprivate String uname;\n\t//发布版本 - /etc/issue\n\tprivate String issue;\n\tpublic String getUname() {\n\t\treturn uname;\n\t}\n\tpublic void setUname(String uname) {\n\t\tthis.uname = uname;\n\t}\n\tpublic String getIssue() {\n\t\treturn issue;\n\t}\n\tpublic void setIssue(String issue) {\n\t\tthis.issue = issue;\n\t}\n\tpublic String toString() {\n\t\treturn \"OSInfo [uname=\" + uname + \", issue=\" + issue + \"]\";\n\t}\n\t/**\n\t * 操作系统类型\n\t */\n\tpublic enum OSType{\n\t\tLINUX(\"linux\"),\n\t\t;\n\t\tprivate String value;\n\t\tprivate OSType(String value) {\n\t\t\tthis.value = value;\n\t\t}\n\t\tpublic String getValue() {\n\t\t\treturn value;\n\t\t}\n\t\tpublic static OSType findByValue(String value) {\n\t\t\tfor(OSType os : values()) {\n\t\t\t\tif(os.getValue().equals(value)) {\n\t\t\t\t\treturn os;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t}\n\t\n\t/**\n\t * 操作系统的发行版本\n\t */\n\tpublic enum DistributionType{\n\t\t//通用系列\n\t\tLINUX(\"linux\", \"@@linux@@\", new DistributionVersion[]{DistributionVersion.DEFAULT}),\n\t\tLINUX_OLD(\"linux_old\", \"@@linux_old@@\", new DistributionVersion[]{DistributionVersion.DEFAULT}),\n\t\t\n\t\t//红帽系列\n\t\tREDHAT(\"rhel\", \"red hat\", new DistributionVersion[]{\n\t\t\t\tDistributionVersion.REDHAT_4,\n\t\t\t\tDistributionVersion.REDHAT_45,\n\t\t\t\tDistributionVersion.REDHAT_5,\n\t\t\t\tDistributionVersion.REDHAT_52,\n\t\t\t\tDistributionVersion.REDHAT_54,\n\t\t\t\tDistributionVersion.REDHAT_6,\n\t\t\t\tDistributionVersion.REDHAT_65,\n\t\t\t\tDistributionVersion.REDHAT_7,\n\t\t\t\tDistributionVersion.REDHAT_71,\n\t\t\t\tDistributionVersion.REDHAT_72,\n\t\t\t\t}),\n\t\t\n\t\t//centos系列\n\t\tCENTOS(\"centos\", \"centos\", new DistributionVersion[]{\n\t\t\t\tDistributionVersion.CENTOS_6,\n\t\t\t\tDistributionVersion.CENTOS_7,\n\t\t\t\t}),\n\t\t\n\t\t//ubuntu系列\n\t\tUBUNTU(\"ubuntu\", \"ubuntu\", new DistributionVersion[]{\n\t\t\t\tDistributionVersion.UBUNTU_6,\n\t\t\t\tDistributionVersion.UBUNTU_7,\n\t\t\t\tDistributionVersion.UBUNTU_8,\n\t\t\t\tDistributionVersion.UBUNTU_810,\n\t\t\t\tDistributionVersion.UBUNTU_9,\n\t\t\t\tDistributionVersion.UBUNTU_910,\n\t\t\t\tDistributionVersion.UBUNTU_10,\n\t\t\t\tDistributionVersion.UBUNTU_1004,\n\t\t\t\tDistributionVersion.UBUNTU_1010,\n\t\t\t\tDistributionVersion.UBUNTU_1104,\n\t\t\t\tDistributionVersion.UBUNTU_1110,\n\t\t\t\tDistributionVersion.UBUNTU_13,\n\t\t\t\tDistributionVersion.UBUNTU_14,\n\t\t\t\tDistributionVersion.UBUNTU_1404,\n\t\t\t\tDistributionVersion.UBUNTU_1410,\n\t\t\t\tDistributionVersion.UBUNTU_15,\n\t\t\t\tDistributionVersion.UBUNTU_1504,\n\t\t\t\tDistributionVersion.UBUNTU_1510,\n\t\t}),\n\t\t\n\t\t//debian系列\n\t\tDEBIAN(\"debian\", \"debian\", new DistributionVersion[]{\n\t\t\t\tDistributionVersion.DEBIAN_5,\n\t\t\t\tDistributionVersion.DEBIAN_50,\n\t\t\t\tDistributionVersion.DEBIAN_6,\n\t\t\t\tDistributionVersion.DEBIAN_60,\n\t\t\t\tDistributionVersion.DEBIAN_7,\n\t\t\t\tDistributionVersion.DEBIAN_8,\n\t\t}),\n\t\t\n\t\t//fedora系列\n\t\tFEDORA(\"fedora\", \"fedora\", new DistributionVersion[]{\n\t\t\t\tDistributionVersion.FEDORA_14,\n\t\t\t\tDistributionVersion.FEDORA_15,\n\t\t\t\tDistributionVersion.FEDORA_16,\n\t\t\t\tDistributionVersion.FEDORA_17,\n\t\t\t\tDistributionVersion.FEDORA_18,\n\t\t\t\tDistributionVersion.FEDORA_19,\n\t\t\t\tDistributionVersion.FEDORA_20,\n\t\t\t\tDistributionVersion.FEDORA_21,\n\t\t\t\tDistributionVersion.FEDORA_22,\n\t\t}),\n\t\t\n\t\t//mint系列\n\t\tMINT(\"mint\", \"mint\", new DistributionVersion[]{\n\t\t\t\tDistributionVersion.MINT_7,\n\t\t\t\tDistributionVersion.MINT_8,\n\t\t\t\tDistributionVersion.MINT_12,\n\t\t\t\tDistributionVersion.MINT_14,\n\t\t\t\tDistributionVersion.MINT_15,\n\t\t\t\tDistributionVersion.MINT_16,\n\t\t\t\tDistributionVersion.MINT_17,\n\t\t}),\n\t\t\n\t\t//opensuse系列\n\t\tOPENSUSE(\"opensuse\", \"opensuse\", new DistributionVersion[]{\n\t\t\t\tDistributionVersion.OPENSUSE_11,\n\t\t\t\tDistributionVersion.OPENSUSE_12,\n\t\t\t\tDistributionVersion.OPENSUSE_13,\n\t\t}),\n\t\t\n\t\t//sles系列(SuSE Linux Enterprise Server)\n\t\tSLES(\"sles\", \"sles\", new DistributionVersion[]{\n\t\t\t\tDistributionVersion.SLES_11,\n\t\t\t\tDistributionVersion.SLES_12,\n\t\t\t\tDistributionVersion.SLES_13,\n\t\t}),\n\t\t\n\t\t//knoppix\n\t\tKNOPPIX(\"knoppix\", \"knoppix\", new DistributionVersion[]{\n\t\t\t\tDistributionVersion.KNOPPIX_4,\n\t\t\t\tDistributionVersion.KNOPPIX_5,\n\t\t\t\tDistributionVersion.KNOPPIX_6,\n\t\t\t\tDistributionVersion.KNOPPIX_7,\n\t\t}),\n\t\t\n\t\t;\n\t\t//nmon文件对应的名字\n\t\tprivate String nmonName;\n\t\t//发行版本对应的标志\n\t\tprivate String distSign;\n\t\tprivate DistributionVersion[] versions;\n\t\t\n\t\tprivate DistributionType(String nmonName, String distSign, \n\t\t\t\tDistributionVersion[] versions) {\n\t\t\tthis.nmonName = nmonName;\n\t\t\tthis.distSign = distSign;\n\t\t\tthis.versions = versions;\n\t\t}\n\t\t\n\t\tpublic String getNmonName() {\n\t\t\treturn nmonName;\n\t\t}\n\n\t\tpublic String getDistSign() {\n\t\t\treturn distSign;\n\t\t}\n\n\t\tpublic DistributionVersion[] getVersions() {\n\t\t\treturn versions;\n\t\t}\n\t\t\n\t\tpublic static DistributionType findByContains(String value) {\n\t\t\tfor(DistributionType type : values()) {\n\t\t\t\tif(value.contains(type.getDistSign())) {\n\t\t\t\t\treturn type;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t}\n\t\n\t/**\n\t * 操作系统的发行版本号\n\t */\n\tpublic enum DistributionVersion{\n\t\t//通用系列无版本\n\t\tDEFAULT(\"\"),\n\t\t\n\t\t//红帽系列\n\t\tREDHAT_4(\"4\"),\n\t\tREDHAT_45(\"45\"),\n\t\tREDHAT_5(\"5\"),\n\t\tREDHAT_52(\"52\"),\n\t\tREDHAT_54(\"54\"),\n\t\tREDHAT_6(\"6\"),\n\t\tREDHAT_65(\"65\"),\n\t\tREDHAT_7(\"7\"),\n\t\tREDHAT_71(\"71\"),\n\t\tREDHAT_72(\"72\"),\n\t\t\n\t\t//centos系列\n\t\tCENTOS_6(\"6\"),\n\t\tCENTOS_7(\"7\"),\n\t\t\n\t\t//ubuntu系列\n\t\tUBUNTU_6(\"6\"),\n\t\tUBUNTU_7(\"7\"),\n\t\tUBUNTU_8(\"8\"),\n\t\tUBUNTU_810(\"810\"),\n\t\tUBUNTU_9(\"9\"),\n\t\tUBUNTU_910(\"910\"),\n\t\tUBUNTU_10(\"10\"),\n\t\tUBUNTU_1004(\"1004\"),\n\t\tUBUNTU_1010(\"1010\"),\n\t\tUBUNTU_1104(\"1104\"),\n\t\tUBUNTU_1110(\"1110\"),\n\t\tUBUNTU_13(\"13\"),\n\t\tUBUNTU_14(\"14\"),\n\t\tUBUNTU_1404(\"1404\"),\n\t\tUBUNTU_1410(\"1410\"),\n\t\tUBUNTU_15(\"15\"),\n\t\tUBUNTU_1504(\"1504\"),\n\t\tUBUNTU_1510(\"1510\"),\n\t\t\n\t\t//debian系列\n\t\tDEBIAN_5(\"5\"),\n\t\tDEBIAN_50(\"50\"),\n\t\tDEBIAN_6(\"6\"),\n\t\tDEBIAN_60(\"60\"),\n\t\tDEBIAN_7(\"7\"),\n\t\tDEBIAN_8(\"8\"),\n\t\t\n\t\t//fedora系列\n\t\tFEDORA_14(\"14\"),\n\t\tFEDORA_15(\"15\"),\n\t\tFEDORA_16(\"16\"),\n\t\tFEDORA_17(\"17\"),\n\t\tFEDORA_18(\"18\"),\n\t\tFEDORA_19(\"19\"),\n\t\tFEDORA_20(\"20\"),\n\t\tFEDORA_21(\"21\"),\n\t\tFEDORA_22(\"22\"),\n\t\t\n\t\t//mint系列\n\t\tMINT_7(\"7\"),\n\t\tMINT_8(\"8\"),\n\t\tMINT_12(\"12\"),\n\t\tMINT_14(\"14\"),\n\t\tMINT_15(\"15\"),\n\t\tMINT_16(\"16\"),\n\t\tMINT_17(\"17\"),\n\t\t\n\t\t//opensuse系列\n\t\tOPENSUSE_11(\"11\"),\n\t\tOPENSUSE_12(\"12\"),\n\t\tOPENSUSE_13(\"13\"),\n\t\t\n\t\t//sles系列(SuSE Linux Enterprise Server)\n\t\tSLES_11(\"11\"),\n\t\tSLES_12(\"12\"),\n\t\tSLES_13(\"13\"),\n\t\t\n\t\t//knoppix\n\t\tKNOPPIX_4(\"4\"),\n\t\tKNOPPIX_5(\"5\"),\n\t\tKNOPPIX_6(\"6\"),\n\t\tKNOPPIX_7(\"7\"),\n\t\t;\n\t\t\n\t\tprivate String value;\n\t\t\n\t\tprivate DistributionVersion(String value) {\n\t\t\tthis.value = value;\n\t\t}\n\t\tpublic String getValue() {\n\t\t\treturn value;\n\t\t}\n\t}\n\t\n\t/**\n\t * 处理器架构\n\t */\n\tpublic enum ProcessorArchitecture{\n\t\tX86_64(\"x86_64\"),\n\t\tX86(\"x86\"),\n\t\tUNKONW(\"\"),\n\t\t;\n\t\tprivate String value;\n\t\t\n\t\tprivate ProcessorArchitecture(String value) {\n\t\t\tthis.value = value;\n\t\t}\n\t\tpublic String getValue() {\n\t\t\treturn value;\n\t\t}\n\t\t\n\t}\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/server/data/Server.java",
    "content": "package com.sohu.cache.server.data;\n\nimport java.text.ParseException;\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\nimport java.util.Locale;\nimport java.util.regex.Pattern;\n\nimport org.apache.commons.lang.math.NumberUtils;\n/**\n *\t服务器基本状态\n */\npublic class Server implements LineParser{\n\tpublic static final String TIME_FLAG = \"ZZZZ\";\n\tpublic static final String FLAG = \"AAA\";\n\tpublic static final Pattern pattern = Pattern.compile(\"^BBBP,[0-9]+,/proc/cpuinfo,\\\"model name\");\n\tpublic static final String OPEN_FILES = \"open files\";\n\tpublic static final String MX_PROCESS = \"max user processes\";\n\t//标志时间的字段\n\tprivate String timeKey;\n\t//收集日期 类似18:49:21,31-MAY-2016格式\n\tprivate String dateTime;\n\tprivate Date collectTime;\n\tprivate String ip;\n\t//host\n\tprivate String host;\n\t//逻辑cpu个数\n\tprivate int cpus;\n\t//nmon版本\n\tprivate String nmon;\n\t//cpu型号\n\tprivate String cpuModel;\n\t//内核版本\n\tprivate String kernel;\n\t//发行版本\n\tprivate String dist;\n\t//ulimit\n\tprivate String ulimit = \"\";\n\t\n\tprivate CPU cpu;\n\tprivate Memory mem;\n\tprivate Load load;\n\tprivate Disk disk;\n\tprivate Net net;\n\tprivate Connection connection;\n\t\n\tpublic Server() {\n\t\tcpu = new CPU();\n\t\tmem = new Memory();\n\t\tload = new Load();\n\t\tdisk = new Disk();\n\t\tnet = new Net();\n\t\tconnection = new Connection();\n\t}\n\t\n\tpublic static void main(String[] args) throws ParseException {\n\t\tString s = \"18:49:21,31-MAY-2016\";\n\t\tSimpleDateFormat sdf = new SimpleDateFormat(\n\t\t\t\t\"HH:mm:ss,dd-MMM-yyyy\", Locale.ENGLISH);\n\t\tSystem.out.println(sdf.parse(s));\n\t}\n\n\t/**\n\t * line format:\n\t * ZZZZ,T0001,09:50:01,01-JUL-2016\n\t * AAA,host,localhost\n\t * AAA,version,14g\n\t * AAA,cpus,16\n\t * AAA,OS,Linux,2.6.18-348.el5,#1 SMP Wed Nov 28 21:22:00 EST 2012,x86_64\n\t * BBBP,374,/proc/cpuinfo,\"model name      : Intel(R) Xeon(R) CPU           E5620  @ 2.40GHz\"\n\t * open files                      (-n) 65535\n\t * max user processes              (-u) 65535\n\t */\n\tpublic void parse(String line, String key) throws Exception {\n\t\tif(line.startsWith(TIME_FLAG)) {\n\t\t\tString[] items = line.split(\",\", 3);\n\t\t\tif(items.length == 3) {\n\t\t\t\tthis.timeKey = items[1];\n\t\t\t\tthis.dateTime = items[2];\n\t\t\t\tSimpleDateFormat sdf = new SimpleDateFormat(\n\t\t\t\t\t\t\"HH:mm:ss,dd-MMM-yyyy\", Locale.ENGLISH);\n\t\t\t\tthis.collectTime = sdf.parse(dateTime);\n\t\t\t}\n\t\t} else if(line.startsWith(FLAG)) {\n\t\t\tString[] items = line.split(\",\", 3);\n\t\t\tif(items.length > 2) {\n\t\t\t\tif(\"host\".equals(items[1])) {\n\t\t\t\t\thost = items[2];\n\t\t\t\t} else if(\"version\".equals(items[1])) {\n\t\t\t\t\tnmon = items[2];\n\t\t\t\t} else if(\"cpus\".equals(items[1])) {\n\t\t\t\t\tcpus = NumberUtils.toInt(items[2]);\n\t\t\t\t} else if(\"OS\".equals(items[1])) {\n\t\t\t\t\tkernel = items[2];\n\t\t\t\t}\n\t\t\t}\n\t\t} else if(cpuModel == null && pattern.matcher(line).find()) {\n\t\t\tString[] tmp = line.split(\"model name\");\n\t\t\tif(tmp.length == 2) {\n\t\t\t\tcpuModel = tmp[1].trim();\n\t\t\t\tcpuModel = cpuModel.substring(1, cpuModel.length() - 1);\n\t\t\t}\n\t\t}\n\t\tString mxFile = parseULimit(line, OPEN_FILES, \"f\");\n\t\tif(mxFile != null) {\n\t\t\tulimit += mxFile;\n\t\t}\n\t\tString mxProcess = parseULimit(line, MX_PROCESS, \"p\");\n\t\tif(mxProcess != null) {\n\t\t\tulimit += mxProcess;\n\t\t}\n\t\t\n\t\tload.parse(line, timeKey);\n\t\tcpu.parse(line, timeKey);\n\t\tmem.parse(line, timeKey);\n\t\tnet.parse(line, timeKey);\n\t\tdisk.parse(line, timeKey);\n\t\tconnection.parse(line, timeKey);\n\t}\n\t\n\tprivate String parseULimit(String line, String prefix, String flag) {\n\t\tString result = null;\n\t\tif(line.startsWith(prefix)) {\n\t\t\tString[] tmp = line.split(\"\\\\s+\");\n\t\t\tif(tmp.length > 0) {\n\t\t\t\tint v = NumberUtils.toInt(tmp[tmp.length - 1]);\n\t\t\t\tif(v > 0) {\n\t\t\t\t\tresult = flag + \",\" + v +\";\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\tpublic String getDateTime() {\n\t\treturn dateTime;\n\t}\n\tpublic Date getCollectTime() {\n\t\treturn collectTime;\n\t}\n\n\tpublic Connection getConnection() {\n\t\treturn connection;\n\t}\n\tpublic String getIp() {\n\t\treturn ip;\n\t}\n\tpublic void setIp(String ip) {\n\t\tthis.ip = ip;\n\t}\n\n\tpublic String getHost() {\n\t\treturn host;\n\t}\n\n\tpublic int getCpus() {\n\t\treturn cpus;\n\t}\n\n\tpublic String getUlimit() {\n\t\treturn ulimit;\n\t}\n\n\tpublic String getNmon() {\n\t\treturn nmon;\n\t}\n\n\tpublic String getCpuModel() {\n\t\treturn cpuModel;\n\t}\n\n\tpublic String getKernel() {\n\t\treturn kernel;\n\t}\n\n\tpublic String getDist() {\n\t\treturn dist;\n\t}\n\n\tpublic CPU getCpu() {\n\t\treturn cpu;\n\t}\n\n\tpublic Memory getMem() {\n\t\treturn mem;\n\t}\n\tpublic String getTime() {\n\t\treturn new SimpleDateFormat(\"HHmm\").format(collectTime);\n\t}\n\tpublic Load getLoad() {\n\t\treturn load;\n\t}\n\n\tpublic Disk getDisk() {\n\t\treturn disk;\n\t}\n\n\tpublic Net getNet() {\n\t\treturn net;\n\t}\n\tpublic void setHost(String host) {\n\t\tthis.host = host;\n\t}\n\n\tpublic void setCpus(int cpus) {\n\t\tthis.cpus = cpus;\n\t}\n\n\tpublic void setNmon(String nmon) {\n\t\tthis.nmon = nmon;\n\t}\n\n\tpublic void setCpuModel(String cpuModel) {\n\t\tthis.cpuModel = cpuModel;\n\t}\n\tpublic void setDist(String dist) {\n\t\tthis.dist = dist;\n\t}\n\n\tpublic void setKernel(String kernel) {\n\t\tthis.kernel = kernel;\n\t}\n\n\tpublic void setUlimit(String ulimit) {\n\t\tthis.ulimit = ulimit;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"Server [timeKey=\" + timeKey + \", dateTime=\" + dateTime\n\t\t\t\t+ \", collectTime=\" + collectTime + \", ip=\" + ip + \", host=\"\n\t\t\t\t+ host + \", cpus=\" + cpus + \", nmon=\" + nmon + \", cpuModel=\"\n\t\t\t\t+ cpuModel + \", kernel=\" + kernel + \", dist=\" + dist\n\t\t\t\t+ \", ulimit=\" + ulimit + \", cpu=\" + cpu + \", mem=\" + mem\n\t\t\t\t+ \", load=\" + load + \", disk=\" + disk + \", net=\" + net\n\t\t\t\t+ \", connection=\" + connection + \"]\";\n\t}\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/server/nmon/NMONService.java",
    "content": "package com.sohu.cache.server.nmon;\n\nimport java.io.File;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.sohu.cache.server.data.OS;\nimport com.sohu.cache.server.data.OSInfo;\nimport com.sohu.cache.ssh.SSHTemplate.DefaultLineProcessor;\nimport com.sohu.cache.ssh.SSHTemplate.Result;\nimport com.sohu.cache.ssh.SSHTemplate.SSHSession;\nimport com.sohu.cache.util.NMONFileFactory;\nimport com.sohu.cache.util.OSFactory;\n/**\n * 服务器监控脚本服务(nmon识别和监控)\n */\npublic class NMONService {\n\tprivate static final Logger logger = LoggerFactory.getLogger(NMONService.class);\n\t//获取系统版本位数命令\n\tpublic static final String OS_INFO_CMD = \"/bin/uname -a; /bin/cat /etc/issue\";\n\t//nmon路径\n\tpublic static final String NMON_DIR = \"/opt/cachecloud/soft/\";\n\t//nmon文件名\n\tpublic static final String NMON = \"nmon\";\n\t//nmon完整路径\n\tpublic static final String NMON_FILE = NMON_DIR + NMON;\n\t//获取nmon版本\n\tpublic static final String NMON_VERSION = \"[ -e \\\"\"+NMON_FILE+\"\\\" ] && \"+NMON_FILE+\" -V\";\n\t//nmon输出的结果文件\n\tpublic static final String NMON_LOG = \"/tmp/nmon.log\";\n\t//nmon输出的老结果文件\n\tpublic static final String NMON_OLD_LOG = \"/tmp/nmon.old.log\";\n\t//tcp输出的结果文件\n\tpublic static final String SOCK_LOG = \"/tmp/sock.log\";\n\t//ulimit输出的结果文件\n\tpublic static final String ULIMIT_LOG = \"/tmp/ulimit.log\";\n\t//nmon监控启动\n\tpublic static final String START_SERVER_COLLECT = NMON_FILE+\" -F \" + NMON_LOG + \" -s0 -c1;\" +\n\t\t\t\"/bin/grep TCP /proc/net/sockstat > \" + SOCK_LOG + \n\t\t\t\";ulimit -n -u > \" + ULIMIT_LOG;\n\t//创建nmon路径\n\tpublic static final String MK_NMON_DIR = \"/bin/mkdir -p /opt/cachecloud/soft/\";\n\t\n\t/**\n\t * 启动nmon收集系统状况\n\t * @param ip\n\t * @param session\n\t * @return @OSInfo 收集到的操作系统信息\n\t */\n\tpublic OSInfo start(String ip, SSHSession session) {\n\t\tResult startCollectResult = session.executeCommand(START_SERVER_COLLECT);\n\t\tif(!startCollectResult.isSuccess()) {\n\t\t\tlogger.error(\"start nmon \"+ip+\" err:\"+startCollectResult.getResult(), \n\t\t\t\t\tstartCollectResult.getExcetion());\n\t\t\t//执行命令没有发生异常，则nmon可能不存在或有问题\n\t\t\tif(startCollectResult.getExcetion() == null) {\n\t\t\t\t//尝试处理出错信息\n\t\t\t\treturn initNmon(ip, session);\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\t\n\t/**\n\t * 尝试修复启动失败的错误\n\t * @param ip\n\t * @param session\n\t */\n\tprivate OSInfo initNmon(String ip, SSHSession session) {\n\t\t//获取nmon版本\n\t\tString version = getNMONVersion(ip, session);\n\t\t//获取操作系统原始信息\n\t\tOSInfo osInfo = getOSInfo(ip, session);\n\t\tOS os = null;\n\t\t//nmon文件不存在，需要根据操作系统识别是否支持\n\t\tif(null == version) {\n\t\t\tlogger.warn(\"{} not exist {}\", ip, NMON_FILE);\n\t\t\t//将原始信息转换为可识别的操作系统\n\t\t\tos = OSFactory.getOS(osInfo);\n\t\t} else {\n\t\t\t//nmon存在，但是版本有问题，此时不应该再判断系统信息了，直接用默认的  \n\t\t\tlogger.warn(\"{} {} version err:\"+version, ip, NMON_FILE);\n\t\t\tos = OSFactory.getDefaultOS(osInfo);\n\t\t}\n\t\tif(os == null) {\n\t\t\tlogger.error(\"unkonw os info={}\", osInfo);\n\t\t\treturn null;\n\t\t}\n\t\t//获取nmon文件\n\t\tFile nmonFile = NMONFileFactory.getNMONFile(os);\n\t\tif(nmonFile == null) {\n\t\t\tlogger.warn(\"{} no corresponding nmon file\", os);\n\t\t\tnmonFile = NMONFileFactory.getNMONFile(OSFactory.getDefaultOS(osInfo));\n\t\t}\n\t\t//将nmon文件传输至服务器\n\t\tsendNMONToServer(ip, session, nmonFile);\n\t\t\n\t\treturn osInfo;\n\t}\n\t\n\t/**\n\t * 获取nmon文件版本\n\t * @param ip\n\t * @param session\n\t * @return 存在返回版本，不存在返回null, 执行错误返回异常\n\t */\n\tprivate String getNMONVersion(String ip, SSHSession session) {\n\t\tResult nmonVersionResult = session.executeCommand(NMON_VERSION);\n\t\tif(nmonVersionResult.isSuccess()) {\n\t\t\treturn nmonVersionResult.getResult();\n\t\t} else {\n\t\t\tlogger.error(NMON_VERSION+\" err:\"+nmonVersionResult.getResult(), nmonVersionResult.getExcetion());\n\t\t}\n\t\treturn null;\n\t}\n\t\n\t/**\n\t * 获取操作系统信息\n\t * @param ip\n\t * @param session\n\t * @return OSInfo\n\t */\n\tprivate OSInfo getOSInfo(String ip, SSHSession session) {\n\t\tfinal OSInfo osInfo = new OSInfo();\n\t\tsession.executeCommand(OS_INFO_CMD, new DefaultLineProcessor() {\n\t\t\tpublic void process(String line, int lineNum) throws Exception {\n\t\t\t\tswitch(lineNum) {\n\t\t\t\tcase 1:\n\t\t\t\t\tosInfo.setUname(line);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 2:\n\t\t\t\t\tosInfo.setIssue(line);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\treturn osInfo;\n\t}\n\t\n\t/**\n\t * 将nmon文件scp到服务器上\n\t * @param ip\n\t * @param session\n\t * @param nmonFile\n\t */\n\tprivate void sendNMONToServer(String ip, SSHSession session, File nmonFile) {\n\t\tResult mkResult = session.executeCommand(MK_NMON_DIR);\n\t\tif(!mkResult.isSuccess()) {\n\t\t\tlogger.error(\"mkdir err:\"+mkResult.getResult(), mkResult.getExcetion());\n\t\t\treturn;\n\t\t}\n\t\tResult scpRst = session.scpToFile(nmonFile.getAbsolutePath(), NMON, NMON_DIR);\n\t\tif(scpRst.isSuccess()) {\n\t\t\tlogger.info(\"scp {} to {} success\", nmonFile.getAbsolutePath(), ip);\n\t\t} else {\n\t\t\tlogger.error(\"scp to \"+ip+\" err\", scpRst.getExcetion());\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/ssh/SSHTemplate.java",
    "content": "package com.sohu.cache.ssh;\n\nimport java.io.BufferedReader;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\nimport java.util.Arrays;\nimport java.util.concurrent.Callable;\nimport java.util.concurrent.Future;\nimport java.util.concurrent.LinkedBlockingQueue;\nimport java.util.concurrent.ThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.TimeoutException;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport ch.ethz.ssh2.Connection;\nimport ch.ethz.ssh2.SCPClient;\nimport ch.ethz.ssh2.Session;\nimport ch.ethz.ssh2.StreamGobbler;\n\nimport com.google.common.util.concurrent.ThreadFactoryBuilder;\nimport com.sohu.cache.exception.SSHException;\nimport com.sohu.cache.util.ConstUtils;\n/**\n * SSH操作模板类\n */\npublic class SSHTemplate {\n\tprivate static final Logger logger = LoggerFactory.getLogger(SSHTemplate.class);\n\t\n\tprivate static final int CONNCET_TIMEOUT = 6000;\n\t\n\tprivate static final int OP_TIMEOUT = 12000;\n\t\n\tprivate static ThreadPoolExecutor taskPool = new ThreadPoolExecutor(\n\t\t\t200, 200, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(1000), \n\t\t\tnew ThreadFactoryBuilder().setNameFormat(\"SSH-%d\").setDaemon(true).build());\n\t\n\tpublic Result execute(String ip, SSHCallback callback) throws SSHException{\n\t\treturn execute(ip,ConstUtils.DEFAULT_SSH_PORT_DEFAULT, ConstUtils.USERNAME, \n\t\t\t\tConstUtils.PASSWORD, callback);\n\t}\n\t\n\t/**\n\t * 通过回调执行命令\n\t * @param ip\n\t * @param port\n\t * @param username\n\t * @param password\n\t * @param callback 可以使用Session执行多个命令\n\t * @throws SSHException \n\t */\n    public Result execute(String ip, int port, String username, String password, \n    \t\tSSHCallback callback) throws SSHException{\n        Connection conn = null;\n        try {\n            conn = getConnection(ip, port, username, password);\n            return callback.call(new SSHSession(conn, ip+\":\"+port));\n        } catch (Exception e) {\n            throw new SSHException(\"SSH err: \" + e.getMessage(), e);\n        } finally {\n        \tclose(conn);\n        }\n    }\n    \n    /**\n     * 获取连接并校验\n     * @param ip\n     * @param port\n     * @param username\n     * @param password\n     * @return Connection\n     * @throws Exception\n     */\n    private Connection getConnection(String ip, int port, \n    \t\tString username, String password) throws Exception {\n    \tConnection conn = new Connection(ip, port);\n        conn.connect(null, CONNCET_TIMEOUT, CONNCET_TIMEOUT);\n        boolean isAuthenticated = conn.authenticateWithPassword(username, password);\n        if (isAuthenticated == false) {\n            throw new Exception(\"SSH authentication failed with [ userName: \" + \n            \t\tusername + \", password: \" + password + \"]\");\n        }\n        return conn;\n    }\n    \n    /**\n     * 获取调用命令后的返回结果\n     * @param is 输入流\n     * @return 如果获取结果有异常或者无结果，那么返回null\n     */\n    private String getResult(InputStream is) {\n    \tfinal StringBuilder buffer = new StringBuilder();\n    \tLineProcessor lp = new DefaultLineProcessor() {\n\t\t\tpublic void process(String line, int lineNum) throws Exception {\n\t\t\t\tif(lineNum > 1) {\n\t\t\t\t\tbuffer.append(System.lineSeparator());\n\t\t\t\t}\n\t\t\t\tbuffer.append(line);\n\t\t\t}\n    \t};\n    \tprocessStream(is, lp);\n    \treturn buffer.length() > 0 ? buffer.toString() : null;\n    } \n    \n    /**\n     * 从流中获取内容\n     * @param is\n     */\n    private void processStream(InputStream is, LineProcessor lineProcessor) {\n    \tBufferedReader reader = null;\n        try {\n        \treader = new BufferedReader(new InputStreamReader(new StreamGobbler(is)));\n\t    \tString line = null;\n\t    \tint lineNum = 1;\n\t        while ((line = reader.readLine()) != null) {\n\t        \ttry {\n\t\t\t\t\tlineProcessor.process(line, lineNum);\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\tlogger.error(\"err line:\"+line, e);\n\t\t\t\t}\n\t\t\t\tlineNum++;\n\t        }\n\t        lineProcessor.finish();\n        } catch (IOException e) {\n            logger.error(e.getMessage(), e);\n        } finally {\n        \tclose(reader);\n        }\n    }\n    \n    private void close(BufferedReader read) {\n    \tif (read != null) {\n            try {\n                read.close();\n            } catch (IOException e) {\n                logger.error(e.getMessage(), e);\n            }\n        }\n    }\n    \n    private void close(Connection conn) {\n    \tif (conn != null) {\n            try {\n            \tconn.close();\n            } catch (Exception e) {\n                logger.error(e.getMessage(), e);\n            }\n        }\n    }\n    \n    private static void close(Session session) {\n    \tif (session != null) {\n            try {\n            \tsession.close();\n            } catch (Exception e) {\n                logger.error(e.getMessage(), e);\n            }\n        }\n    }\n    \n    /**\n     * 可以调用多次executeCommand， 并返回结果\n     */\n    public class SSHSession{\n    \tprivate String address;\n    \tprivate Connection conn;\n    \tprivate SSHSession(Connection conn, String address) {\n    \t\tthis.conn = conn;\n    \t\tthis.address = address;\n    \t}\n    \t/**\n    \t * 执行命令并返回结果，可以执行多次\n    \t * @param cmd\n    \t * @return 执行成功Result为true，并携带返回信息,返回信息可能为null\n    \t *         执行失败Result为false，并携带失败信息\n    \t *         执行异常Result为false，并携带异常\n    \t */\n    \tpublic Result executeCommand(String cmd) {\n    \t\treturn executeCommand(cmd, OP_TIMEOUT);\n    \t}\n    \t\n    \tpublic Result executeCommand(String cmd, int timoutMillis) {\n    \t\treturn executeCommand(cmd, null, timoutMillis);\n    \t}\n    \t\n    \tpublic Result executeCommand(String cmd, LineProcessor lineProcessor) {\n    \t\treturn executeCommand(cmd, lineProcessor, OP_TIMEOUT);\n    \t}\n    \t\n    \t/**\n    \t * 执行命令并返回结果，可以执行多次\n    \t * @param cmd\n    \t * @param lineProcessor 回调处理行\n    \t * @return 如果lineProcessor不为null,那么永远返回Result.true\n    \t */\n    \tpublic Result executeCommand(String cmd, LineProcessor lineProcessor, int timoutMillis) {\n    \t\tSession session = null;\n    \t\ttry {\n    \t\t\tsession = conn.openSession();\n    \t\t\treturn executeCommand(session, cmd, timoutMillis, lineProcessor);\n\t\t\t} catch (Exception e) {\n\t\t\t\tlogger.error(\"execute ip:\"+conn.getHostname()+\" cmd:\"+cmd, e);\n\t\t\t\treturn new Result(e);\n\t\t\t} finally {\n\t\t\t\tclose(session);\n\t\t\t}\n    \t}\n    \t\n    \tpublic Result executeCommand(final Session session, final String cmd, \n    \t\t\tfinal int timoutMillis, final LineProcessor lineProcessor) throws Exception{\n    \t\tFuture<Result> future = taskPool.submit(new Callable<Result>() {\n\t\t\t\tpublic Result call() throws Exception {\n\t\t\t\t\tsession.execCommand(cmd);\n\t\t\t\t\t//如果客户端需要进行行处理，则直接进行回调\n\t\t\t\t\tif(lineProcessor != null) {\n\t\t\t\t\t\tprocessStream(session.getStdout(), lineProcessor);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t//获取标准输出\n\t\t\t\t\t\tString rst = getResult(session.getStdout());\n\t\t\t\t\t\tif(rst != null) {\n\t\t\t\t\t\t\treturn new Result(true, rst);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t//返回为null代表可能有异常，需要检测标准错误输出，以便记录日志\n\t\t\t\t\t\tResult errResult = tryLogError(session.getStderr(), cmd);\n\t\t\t\t\t\tif(errResult != null) {\n\t\t\t\t\t\t\treturn errResult;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn new Result(true, null);\n\t\t\t\t}\n\t\t\t});\n    \t\tResult rst = null;\n    \t\ttry {\n    \t\t\trst = future.get(timoutMillis, TimeUnit.MILLISECONDS);\n    \t\t\tfuture.cancel(true);\n    \t\t} catch (TimeoutException e) {\n    \t\t\tlogger.error(\"exec ip:{} {} timeout:{}\", conn.getHostname(), cmd, timoutMillis);\n    \t\t\tthrow new SSHException(e);\n    \t\t}\n    \t\treturn rst;\n    \t}\n    \t\n    \tprivate Result tryLogError(InputStream is, String cmd) {\n    \t\tString errInfo = getResult(is);\n        \tif(errInfo != null) {\n        \t\tlogger.error(\"address \"+address+\" execute cmd:({}), err:{}\", cmd, errInfo);\n        \t\treturn new Result(false, errInfo);\n        \t}\n        \treturn null;\n    \t}\n    \t\n    \t/**\n    \t * Copy a set of local files to a remote directory, uses the specified mode when\n    \t * creating the file on the remote side.\n    \t * @param localFiles\n    \t *            Path and name of local file.\n    \t * @param remoteFiles\n    \t *            name of remote file.\n    \t * @param remoteTargetDirectory\n    \t *            Remote target directory. Use an empty string to specify the default directory.\n    \t * @param mode\n    \t *            a four digit string (e.g., 0644, see \"man chmod\", \"man open\")\n    \t * @throws IOException\n    \t */\n    \tpublic Result scp(String[] localFiles, String[] remoteFiles, String remoteTargetDirectory, String mode) {\n    \t\ttry {\n    \t\t\tSCPClient client = conn.createSCPClient();\n\t\t\t\tclient.put(localFiles, remoteFiles, remoteTargetDirectory, mode);\n\t\t\t\treturn new Result(true);\n\t\t\t} catch (Exception e) {\n\t\t\t\tlogger.error(\"scp local=\"+Arrays.toString(localFiles)+\" to \"+\n\t\t\t\t\t\tremoteTargetDirectory+\" remote=\"+Arrays.toString(remoteFiles)+\" err\", e);\n\t\t\t\treturn new Result(e);\n\t\t\t}\n    \t}\n    \t\n    \tpublic Result scpToDir(String localFile, String remoteTargetDirectory) {\n    \t\treturn scpToDir(localFile, remoteTargetDirectory, \"0744\");\n    \t}\n    \t\n    \tpublic Result scpToDir(String localFile, String remoteTargetDirectory, String mode) {\n    \t\treturn scp(new String[] { localFile }, null, remoteTargetDirectory, mode);\n    \t}\n    \t\n    \tpublic Result scpToDir(String[] localFile, String remoteTargetDirectory) {\n    \t\treturn scp(localFile, null, remoteTargetDirectory, \"0744\");\n    \t}\n    \tpublic Result scpToFile(String localFile, String remoteFile, String remoteTargetDirectory) {\n    \t\treturn scpToFile(localFile, remoteFile, remoteTargetDirectory, \"0744\");\n    \t}\n    \tpublic Result scpToFile(String localFile, String remoteFile, String remoteTargetDirectory, String mode) {\n    \t\treturn scp(new String[] { localFile }, new String[] { remoteFile }, remoteTargetDirectory, \"0744\");\n    \t}\n    }\n    \n    /**\n     * 结果封装\n     */\n    public class Result{\n    \tprivate boolean success;\n    \tprivate String result;\n    \tprivate Exception excetion;\n    \tpublic Result(boolean success) {\n\t\t\tthis.success = success;\n\t\t}\n\t\tpublic Result(boolean success, String result) {\n\t\t\tthis.success = success;\n\t\t\tthis.result = result;\n\t\t}\n\t\tpublic Result(Exception excetion) {\n\t\t\tthis.success = false;\n\t\t\tthis.excetion = excetion;\n\t\t}\n\t\t\n\t\tpublic Exception getExcetion() {\n\t\t\treturn excetion;\n\t\t}\n\t\tpublic void setExcetion(Exception excetion) {\n\t\t\tthis.excetion = excetion;\n\t\t}\n\t\tpublic boolean isSuccess() {\n\t\t\treturn success;\n\t\t}\n\t\tpublic void setSuccess(boolean success) {\n\t\t\tthis.success = success;\n\t\t}\n\t\tpublic String getResult() {\n\t\t\treturn result;\n\t\t}\n\t\tpublic void setResult(String result) {\n\t\t\tthis.result = result;\n\t\t}\n\t\t@Override\n\t\tpublic String toString() {\n\t\t\treturn \"Result [success=\" + success + \", result=\" + result\n\t\t\t\t\t+ \", excetion=\" + excetion + \"]\";\n\t\t}\n    }\n    \n    /**\n     *\t执行命令回调\n     */\n    public interface SSHCallback{\n    \t/**\n    \t * 执行回调\n    \t * @param session\n    \t */\n    \tResult call(SSHSession session);\n    }\n    \n    /**\n     * 从流中直接解析数据\n     */\n\tpublic static interface LineProcessor{\n\t\t/**\n\t\t * 处理行\n\t\t * @param line  内容\n\t\t * @param lineNum   行号，从1开始\n\t\t * @throws Exception\n\t\t */\n\t\tvoid process(String line, int lineNum) throws Exception;\n\t\t\n\t\t/**\n\t\t * 所有的行处理完毕回调该方法\n\t\t */\n\t\tvoid finish();\n\t}\n\t\n\tpublic static abstract class DefaultLineProcessor implements LineProcessor{\n\t\tpublic void finish() {}\n\t}\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/ssh/SSHUtil.java",
    "content": "package com.sohu.cache.ssh;\n\nimport static com.sohu.cache.constant.BaseConstant.WORD_SEPARATOR;\nimport static com.sohu.cache.constant.EmptyObjectConstant.EMPTY_STRING;\nimport static com.sohu.cache.constant.SymbolConstant.COMMA;\n\nimport java.text.DecimalFormat;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\nimport org.apache.commons.lang.StringUtils;\nimport org.apache.commons.lang.math.NumberUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.sohu.cache.entity.MachineStats;\nimport com.sohu.cache.exception.IllegalParamException;\nimport com.sohu.cache.exception.SSHException;\nimport com.sohu.cache.ssh.SSHTemplate.DefaultLineProcessor;\nimport com.sohu.cache.ssh.SSHTemplate.LineProcessor;\nimport com.sohu.cache.ssh.SSHTemplate.Result;\nimport com.sohu.cache.ssh.SSHTemplate.SSHCallback;\nimport com.sohu.cache.ssh.SSHTemplate.SSHSession;\nimport com.sohu.cache.util.ConstUtils;\nimport com.sohu.cache.util.IntegerUtil;\nimport com.sohu.cache.util.StringUtil;\n\n/**\n * Created by yijunzhang on 14-6-20.\n */\npublic class SSHUtil {\n\n    private static final Logger logger = LoggerFactory.getLogger(SSHUtil.class);\n    \n    private final static String COMMAND_TOP = \"top -b -n 1 | head -5\";\n    private final static String COMMAND_DF_LH = \"df -lh\";\n    private final static String LOAD_AVERAGE_STRING = \"load average: \";\n    private final static String COMMAND_MEM = \"cat /proc/meminfo | grep -E -w 'MemTotal|MemFree|Buffers|Cached'\";\n    private final static String MEM_TOTAL = \"MemTotal\";\n    private final static String MEM_FREE = \"MemFree\";\n    private final static String MEM_BUFFERS = \"Buffers\";\n    private final static String MEM_CACHED = \"Cached\";\n    \n    //使用 @SSHTemplate 重构SSHUtil\n    private final static SSHTemplate sshTemplate = new SSHTemplate();\n\n    /**\n     * Get HostPerformanceEntity[cpuUsage, memUsage, load] by ssh.<br>\n     * 方法返回前已经释放了所有资源，调用方不需要关心\n     *\n     * @param ip\n     * @param userName\n     * @param password\n     * @throws Exception\n     * @since 1.0.0\n     */\n    public static MachineStats getMachineInfo(String ip, int port, String userName, \n    \t\tString password) throws SSHException {\n        if (StringUtil.isBlank(ip)) {\n            try {\n                throw new IllegalParamException(\"Param ip is empty!\");\n            } catch (IllegalParamException e) {\n                throw new SSHException(e.getMessage(), e);\n            }\n        }\n        port = IntegerUtil.defaultIfSmallerThan0(port, ConstUtils.SSH_PORT_DEFAULT);\n        final MachineStats systemPerformanceEntity =  new MachineStats();\n        systemPerformanceEntity.setIp(ip);\n        \n        sshTemplate.execute(ip, port, userName, password, new SSHCallback() {\n\t\t\tpublic Result call(SSHSession session) {\n\t\t\t\t//解析top命令\n\t\t\t\tsession.executeCommand(COMMAND_TOP, new DefaultLineProcessor() {\n\t\t\t\t\tpublic void process(String line, int lineNum) throws Exception {\n\t\t                if (lineNum > 5) {\n\t\t                    return;\n\t\t                }\n\t\t                if (1 == lineNum) {\n\t\t                    // 第一行，通常是这样：\n\t\t                    // top - 19:58:52 up 416 days, 30 min, 1 user, load average:\n\t\t                    // 0.00, 0.00, 0.00\n\t\t                    int loadAverageIndex = line.indexOf(LOAD_AVERAGE_STRING);\n\t\t                    String loadAverages = line.substring(loadAverageIndex).replace(LOAD_AVERAGE_STRING, EMPTY_STRING);\n\t\t                    String[] loadAverageArray = loadAverages.split(\",\");\n\t\t                    if (3 == loadAverageArray.length) {\n\t\t                    \tsystemPerformanceEntity.setLoad(StringUtil.trimToEmpty(loadAverageArray[0]));\n\t\t                    }\n\t\t                } else if (3 == lineNum) {\n\t\t                    // 第三行通常是这样：\n\t\t                    // , 0.0% sy, 0.0% ni, 100.0% id, 0.0% wa,\n\t\t                    // 0.0% hi, 0.0% si\n\t\t                \t// redhat:%Cpu(s):  0.0 us\n\t\t                \t// centos7:Cpu(s): 0.0% us\n\t\t                    double cpuUs = getUsCpu(line);\n\t\t                    systemPerformanceEntity.setCpuUsage(String.valueOf(cpuUs));\n\t\t                } \n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\t//解析memory\n\t\t\t\tsession.executeCommand(COMMAND_MEM, new LineProcessor() {\n\t\t\t\t\tprivate String totalMem;\n\t\t\t\t\tprivate String freeMem;\n\t\t\t\t\tprivate String buffersMem;\n\t\t\t\t\tprivate String cachedMem;\n\t\t\t\t\tpublic void process(String line, int lineNum) throws Exception {\n\t\t\t\t\t\tif (line.contains(MEM_TOTAL)) {\n\t\t            \t\ttotalMem = matchMemLineNumber(line).trim();\n\t\t            \t} else if (line.contains(MEM_FREE)) {\n\t\t            \t\tfreeMem = matchMemLineNumber(line).trim();\n\t\t            \t} else if (line.contains(MEM_BUFFERS)) {\n\t\t            \t\tbuffersMem = matchMemLineNumber(line).trim();\n\t\t            \t} else if (line.contains(MEM_CACHED)) {\n\t\t            \t\tcachedMem = matchMemLineNumber(line).trim();\n\t\t            \t}\n\t\t\t\t\t}\n\t\t\t\t\tpublic void finish() {\n\t\t\t\t\t\tif (!StringUtil.isBlank(totalMem, freeMem, buffersMem)) {\n\t\t\t\t\t\t\tLong totalMemLong = NumberUtils.toLong(totalMem);\n\t\t\t\t\t\t\tLong freeMemLong = NumberUtils.toLong(freeMem);\n\t\t\t\t\t\t\tLong buffersMemLong = NumberUtils.toLong(buffersMem);\n\t\t\t\t\t\t\tLong cachedMemLong = NumberUtils.toLong(cachedMem);\n\t\t\t\t\t\t\tLong usedMemFree = freeMemLong + buffersMemLong + cachedMemLong;\n\t\t\t\t\t\t\tDouble memoryUsage = 1 - (NumberUtils.toDouble(usedMemFree.toString()) / NumberUtils.toDouble(totalMemLong.toString()) / 1.0);\n\t\t\t\t\t\t\tsystemPerformanceEntity.setMemoryTotal(String.valueOf(totalMemLong));\n\t\t\t\t\t\t\tsystemPerformanceEntity.setMemoryFree(String.valueOf(usedMemFree));\n\t\t\t\t\t\t\tDecimalFormat df = new DecimalFormat(\"0.00\");\n\t\t\t\t\t\t\tsystemPerformanceEntity.setMemoryUsageRatio(df.format(memoryUsage * 100));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\t// 统计磁盘使用状况\n\t\t\t\t/**\n\t             * 内容通常是这样： Filesystem 容量 已用 可用 已用% 挂载点 /dev/xvda2 5.8G 3.2G 2.4G\n\t             * 57% / /dev/xvda1 99M 8.0M 86M 9% /boot none 769M 0 769M 0%\n\t             * /dev/shm /dev/xvda7 68G 7.1G 57G 12% /home /dev/xvda6 2.0G 36M\n\t             * 1.8G 2% /tmp /dev/xvda5 2.0G 199M 1.7G 11% /var\n\t             * */\n\t\t\t\tsession.executeCommand(COMMAND_DF_LH, new LineProcessor() {\n\t\t\t\t\tprivate Map<String, String> diskUsageMap = new HashMap<String, String>();\n\t\t\t\t\tpublic void process(String line, int lineNum) throws Exception {\n\t\t\t\t\t\tif(lineNum == 1) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tline = line.replaceAll(\" {1,}\", WORD_SEPARATOR);\n\t\t                String[] lineArray = line.split(WORD_SEPARATOR);\n\t\t                if (6 == lineArray.length) {\n\t\t                \tString diskUsage = lineArray[4];\n\t\t                \tString mountedOn = lineArray[5];\n\t\t                \tdiskUsageMap.put(mountedOn, diskUsage);\n\t\t                }\n\t\t\t\t\t}\n\t\t\t\t\tpublic void finish() {\n\t\t\t\t\t\tsystemPerformanceEntity.setDiskUsageMap(diskUsageMap);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\treturn null;\n\t\t\t}\n\t\t});\n\n        // 统计当前网络流量 @TODO \n        Double traffic = 0.0;\n        systemPerformanceEntity.setTraffic(traffic.toString());\n\n        return systemPerformanceEntity;\n    }\n\n    /**\n     * SSH 方式登录远程主机，执行命令,方法内部会关闭所有资源，调用方无须关心。\n     *\n     * @param ip       主机ip\n     * @param username 用户名\n     * @param password 密码\n     * @param command  要执行的命令\n     */\n    public static String execute(String ip, int port, String username, String password, \n    \t\tfinal String command) throws SSHException {\n\n        if (StringUtil.isBlank(command)) {\n        \treturn EMPTY_STRING;\n        }\n        port = IntegerUtil.defaultIfSmallerThan0(port, ConstUtils.SSH_PORT_DEFAULT);\n        \n        Result rst = sshTemplate.execute(ip, port, username, password, new SSHCallback() {\n\t\t\tpublic Result call(SSHSession session) {\n\t\t\t\treturn session.executeCommand(command);\n\t\t\t}\n\t\t});\n        if(rst.isSuccess()) {\n        \treturn rst.getResult();\n        }\n        return \"\";\n    }\n\n    /**\n     * @param ip\n     * @param port\n     * @param username\n     * @param password\n     * @param localPath\n     * @param remoteDir\n     * @return\n     * @throws SSHException\n     */\n    public static boolean scpFileToRemote(String ip, int port, String username, \n    \t\tString password, final String localPath, final String remoteDir) throws SSHException{\n    \tResult rst = sshTemplate.execute(ip, port, username, password, new SSHCallback() {\n\t\t\tpublic Result call(SSHSession session) {\n\t\t\t\treturn session.scpToDir(localPath, remoteDir, \"0644\");\n\t\t\t}\n\t\t});\n    \tif(rst.isSuccess()) {\n    \t\treturn true;\n    \t}\n    \tif(rst.getExcetion() != null) {\n    \t\tthrow new SSHException(rst.getExcetion());\n    \t}\n    \treturn false;\n    }\n\n    /**\n     * 重载，使用默认端口、用户名和密码\n     *\n     * @param ip\n     * @param localPath\n     * @param remoteDir\n     * @return\n     * @throws SSHException\n     */\n    public static boolean scpFileToRemote(String ip, String localPath, String remoteDir) throws SSHException {\n        int sshPort = SSHUtil.getSshPort(ip);\n        return scpFileToRemote(ip, sshPort, ConstUtils.USERNAME, ConstUtils.PASSWORD, localPath, remoteDir);\n    }\n\n    /**\n     * 重载，使用默认端口、用户名和密码\n     *\n     * @param ip\n     * @param cmd\n     * @return\n     * @throws SSHException\n     */\n    public static String execute(String ip, String cmd) throws SSHException {\n        int sshPort = SSHUtil.getSshPort(ip);\n        return execute(ip, sshPort, ConstUtils.USERNAME, ConstUtils.PASSWORD, cmd);\n    }\n\n    /**\n     * 查看机器ip上的端口port是否已被占用；\n     *\n     * @param ip    机器ip\n     * @param port  要检查的端口\n     * @return  如果被占用返回true，否则返回false；\n     * @throws SSHException\n     */\n    public static boolean isPortUsed(String ip, int port) throws SSHException {\n        /**\n         * 执行ps命令，查看端口，以确认刚才执行的shell命令是否成功，返回一般是这样的：\n         *  root     12510 12368  0 14:34 pts/0    00:00:00 redis-server *:6379\n         */\n        String psCmd = \"/bin/ps -ef | grep %s | grep -v grep\";\n        psCmd = String.format(psCmd, port);\n        String psResponse = execute(ip, psCmd);\n        boolean isUsed = false;\n\n        if (StringUtils.isNotBlank(psResponse)) {\n            String[] resultArr = psResponse.split(System.lineSeparator());\n            for (String resultLine: resultArr) {\n                if (resultLine.contains(String.valueOf(port))) {\n                    isUsed = true;\n                    break;\n                }\n            }\n        }\n        return isUsed;\n    }\n\n    /**\n     * 通过ip来判断ssh端口\n     *\n     * @param ip\n     * @return\n     */\n    public static int getSshPort(String ip) {\n        /**\n         * 如果ssh默认端口不是22,请自行实现该逻辑\n         */\n        return ConstUtils.SSH_PORT_DEFAULT;\n    }\n\n    /**\n     * 匹配字符串中的数字\n     * \n     * @param content\n     * @return\n     */\n    private static String matchMemLineNumber(String content) {\n        String result = EMPTY_STRING;\n        if (content == null || EMPTY_STRING.equals(content.trim())) {\n            return result;\n        }\n        Pattern pattern = Pattern.compile(\"(\\\\d+)\");\n        Matcher matcher = pattern.matcher(content);\n        if (matcher.find()) {\n            result = matcher.group(1);\n        }\n        return result;\n    }\n    \n    /**\n     * 从top的cpuLine解析出us\n     * @param cpuLine\n     * @return\n     */\n    public static double getUsCpu(String cpuLine) {\n        if (cpuLine == null || EMPTY_STRING.equals(cpuLine.trim())) {\n            return 0;\n        }\n        String[] items = cpuLine.split(COMMA);\n        if (items.length < 1) {\n            return 0;\n        }\n        String usCpuStr = items[0];\n        return NumberUtils.toDouble(matchCpuLine(usCpuStr));\n    }\n\n    private static String matchCpuLine(String content) {\n        String result = EMPTY_STRING;\n        if (content == null || EMPTY_STRING.equals(content.trim())) {\n            return result;\n        }\n        Pattern pattern = Pattern.compile(\"(\\\\d+).(\\\\d+)\");\n        Matcher matcher = pattern.matcher(content);\n        if (matcher.find()) {\n            result = matcher.group();\n        }\n        return result;\n    }\n    \n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/stats/app/AppDailyDataCenter.java",
    "content": "package com.sohu.cache.stats.app;\n\nimport java.util.Date;\n\nimport com.sohu.cache.entity.AppDailyData;\n\n\n/**\n * 应用日数据统计\n * @author leifu\n * @Date 2016年8月10日\n * @Time 下午5:11:03\n */\npublic interface AppDailyDataCenter {\n\n    /**\n     * 发送所有应用日报\n     */\n    int sendAppDailyEmail();\n\n    /**\n     * 发送单个应用日报\n     */\n    boolean sendAppDailyEmail(long appId, Date startDate, Date endDate);\n    \n    /**\n     * 获取单天应用日报\n     */\n    AppDailyData getAppDailyData(long appId, Date date);\n    \n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/stats/app/AppDataMigrateCenter.java",
    "content": "package com.sohu.cache.stats.app;\n\nimport java.util.List;\nimport java.util.Map;\n\nimport com.sohu.cache.constant.AppDataMigrateEnum;\nimport com.sohu.cache.constant.AppDataMigrateResult;\nimport com.sohu.cache.constant.CommandResult;\nimport com.sohu.cache.constant.RedisMigrateToolConstant;\nimport com.sohu.cache.entity.AppDataMigrateSearch;\nimport com.sohu.cache.entity.AppDataMigrateStatus;\n\n/**\n * 数据迁移\n * \n * @author leifu\n * @Date 2016-6-8\n * @Time 下午2:54:33\n */\npublic interface AppDataMigrateCenter {\n    \n    /**\n     * 检查配置\n     * \n     * @param migrateMachineIp\n     * @param sourceRedisMigrateEnum\n     * @param sourceServers\n     * @param targetRedisMigrateEnum\n     * @param targetServers\n     * @param redisSourcePass\n     * @param redisTargetPass\n     * @return \n     */\n    AppDataMigrateResult check(String migrateMachineIp, AppDataMigrateEnum sourceRedisMigrateEnum, String sourceServers,\n            AppDataMigrateEnum targetRedisMigrateEnum, String targetServers, String redisSourcePass, String redisTargetPass);\n\n    /**\n     * 开始迁移\n     * \n     * @param migrateMachineIp\n     * @param sourceRedisMigrateEnum\n     * @param sourceServers\n     * @param targetRedisMigrateEnum\n     * @param targetServers\n     * @param redisSourcePass\n     * @param targetSourcePass\n     * @return\n     */\n    boolean migrate(String migrateMachineIp, AppDataMigrateEnum sourceRedisMigrateEnum, String sourceServers,\n            AppDataMigrateEnum targetRedisMigrateEnum, String targetServers, long sourceAppId, long targetAppId, String redisSourcePass, String targetSourcePass, long userId);\n\n\n    /**\n     * 搜索列表\n     * @param appDataMigrateSearch\n     * @return\n     */\n\tList<AppDataMigrateStatus> search(AppDataMigrateSearch appDataMigrateSearch);\n\n    /**\n     * 查看日志\n     * @param id\n     * @param pageSize\n     * @return\n     */\n    String showDataMigrateLog(long id, int pageSize);\n    \n    /**\n     * 查看配置\n     * @param id\n     * @return\n     */\n    String showDataMigrateConf(long id);\n\n    /**\n     * 查询迁移工具的实时状态\n     * @param id\n     * @return\n     */\n    Map<RedisMigrateToolConstant, Map<String, Object>> showMiragteToolProcess(long id);\n\n\n    /**\n     * 比较源和目标的样本数据\n     * @param id\n     * @param nums\n     * @return\n     */\n    CommandResult sampleCheckData(long id, int nums);\n\n\n    /**\n     * 关闭迁移\n     * @param id\n     * @return\n     */\n    AppDataMigrateResult stopMigrate(long id);\n\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/stats/app/AppDeployCenter.java",
    "content": "package com.sohu.cache.stats.app;\n\nimport com.sohu.cache.constant.DataFormatCheckResult;\nimport com.sohu.cache.constant.HorizontalResult;\nimport com.sohu.cache.entity.AppDesc;\nimport com.sohu.cache.entity.AppUser;\nimport com.sohu.cache.entity.InstanceReshardProcess;\n\nimport java.util.List;\n\n/**\n * app相关发布操作\n * Created by yijunzhang on 14-10-20.\n */\npublic interface AppDeployCenter {\n\n    /**\n     * 新建应用\n     *\n     * @param appDesc\n     * @param appUser\n     * @param memSize\n     */\n    public boolean createApp(AppDesc appDesc, AppUser appUser, String memSize);\n\n    /**\n     * 为应用分配资源\n     *\n     * @param appAuditId\n     * @param nodeInfoList <br/>格式=masterIp:空间:slaveIp\n     * @param auditUser\n     * @return\n     */\n    public boolean allocateResourceApp(Long appAuditId, List<String> nodeInfoList, AppUser auditUser);\n\n\n    /**\n     * 为应用分配的资源格式检测\n     * @param appAuditId\n     * @param appDeployText\n     * @return\n     */\n    public DataFormatCheckResult checkAppDeployDetail(Long appAuditId, String appDeployText);\n\n    /**\n     * 下线应用\n     *\n     * @param appId\n     * @return\n     */\n    public boolean offLineApp(Long appId);\n\n    /**\n     * 修改应用下节点配置\n     *\n     * @param appId\n     * @param appAuditId\n     * @param key\n     * @param value\n     * @return\n     */\n    public boolean modifyAppConfig(Long appId, Long appAuditId, String key, String value);\n\n    /**\n     * 垂直扩展\n     *\n     * @param appId\n     * @param appAuditId\n     * @param memory 单位MB\n     * @return\n     */\n    public boolean verticalExpansion(Long appId, Long appAuditId, int memory);\n\n    /**\n     * 检测水平扩容节点\n     * @param appAuditId\n     * @param masterSizeSlave\n     * @return\n     */\n    public DataFormatCheckResult checkHorizontalNodes(Long appAuditId, String masterSizeSlave);\n    \n    /**\n     * 检查水平扩容的格式\n     * @param appId\n     * @param appAuditId\n     * @param sourceId\n     * @param targetId\n     * @param startSlot\n     * @param endSlot\n     * @param migrateType\n     * @return\n     */\n    public HorizontalResult checkHorizontal(long appId, long appAuditId, long sourceId, long targetId, int startSlot,\n            int endSlot, int migrateType);\n    \n    \n    /**\n     * 开始水平扩容\n     * @param appId\n     * @param appAuditId\n     * @param sourceId\n     * @param targetId\n     * @param startSlot\n     * @param endSlot\n     * @param migrateType\n     * @return\n     */\n    public HorizontalResult startHorizontal(long appId, long appAuditId, long sourceId, long targetId, int startSlot,\n            int endSlot, int migrateType);\n    \n    /**\n     * 重试水平扩容\n     * @param instanceReshardProcessId\n     * @return\n     */\n    public HorizontalResult retryHorizontal(final int instanceReshardProcessId);\n    \n    /**\n     * 添加cluster一个主(从)节点\n     *\n     * @param appId\n     * @param masterHost\n     * @param slaveHost 从节点可为空\n     * @param memory\n     * @return\n     */\n    public boolean addHorizontalNodes(Long appId, String masterHost, String slaveHost, int memory);\n    \n\n    /**\n     * 获取当前水平扩展进度列表\n     *\n     * @return\n     */\n    public List<InstanceReshardProcess> getHorizontalProcess(long auditId);\n    \n    \n    /**\n     * 清理应用数据\n     * @param appId\n     * @param appUser\n     * @return\n     */\n    public boolean cleanAppData(long appId, AppUser appUser);\n\n    \n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/stats/app/AppStatsCenter.java",
    "content": "package com.sohu.cache.stats.app;\n\nimport com.sohu.cache.constant.AppTopology;\nimport com.sohu.cache.constant.TimeDimensionalityEnum;\nimport com.sohu.cache.entity.AppCommandGroup;\nimport com.sohu.cache.entity.AppCommandStats;\nimport com.sohu.cache.entity.AppStats;\nimport com.sohu.cache.entity.InstanceSlowLog;\nimport com.sohu.cache.web.vo.AppDetailVO;\n\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * app级别的查询、统计和汇总\n *\n * Created by lingguo on 14-6-26.\n */\npublic interface AppStatsCenter {\n    \n    /**\n     * 通过时间区间查询app的分钟统计数据\n     *\n     * @param appId\n     * @param beginTime      时间，格式：yyyyMMddHHmm\n     * @param endTime        时间，格式：yyyyMMddHHmm\n     * @return\n     */\n    public List<AppStats> getAppStatsListByMinuteTime(final long appId, long beginTime, long endTime);\n\n    /**\n     * 通过时间区间查询app的分钟统计数据\n     *\n     * @param appId\n     * @param beginTime      时间，格式：yyyyMMddHHmm\n     * @param endTime        时间，格式：yyyyMMddHHmm\n     * @return\n     */\n    public List<AppStats> getAppStatsList(final long appId, long beginTime, long endTime, TimeDimensionalityEnum timeDimensionalityEnum);\n\n    /**\n     * 查询一天中应用的命令执行次数的top5\n     *\n     * @param appId 应用id\n     * @param begin 日期格式：yyyyMMddHHmm\n     * @param end 日期格式：yyyyMMddHHmm\n     * @return\n     */\n    public List<AppCommandStats> getTop5AppCommandStatsList(final long appId, long begin, long end);\n\n    /**\n     * 查询一天中应用的命令执行次数的top5\n     *\n     * @param appId 应用id\n     * @param begin 日期格式：yyyyMMddHHmm\n     * @param end 日期格式：yyyyMMddHHmm\n     * @return\n     */\n    public List<AppCommandStats> getTopLimitAppCommandStatsList(final long appId, long begin, long end, int limit);\n\n    /**\n     * 查询应用的配置和节点信息\n     *\n     * @param appId\n     * @return\n     */\n    public Map<AppTopology, Object> queryAppTopology(final long appId);\n    \n    \n    /**\n     * 查询应用指定时间段，指定命令名的结果集合\n     * \n     * @param appId 应用id\n     * @param beginTime 时间，格式：yyyyMMddHHmm\n     * @param endTime 时间，格式：yyyyMMddHHmm\n     * @param commandName 命令名\n     * @return\n     */\n    public List<AppCommandStats> getCommandStatsListV2(long appId, long beginTime, long endTime, TimeDimensionalityEnum timeDimensionalityEnum, String commandName);\n    \n    /**\n     * 查询应用指定时间段，指定命令名的结果集合\n     * \n     * @param appId 应用id\n     * @param beginTime 时间，格式：yyyyMMddHHmm\n     * @param endTime 时间，格式：yyyyMMddHHmm\n     * @param commandName 命令名\n     * @return\n     */\n    public List<AppCommandStats> getCommandStatsList(long appId, long beginTime, long endTime, String commandName);\n\n    /**\n     * 查询应用指定时间段，指定命令名的结果集合\n     *\n     * @param appId 应用id\n     * @param beginTime 时间，格式：yyyyMMddHHmm\n     * @param endTime 时间，格式：yyyyMMddHHmm\n     * @return\n     */\n    public List<AppCommandStats> getCommandStatsList(long appId, long beginTime, long endTime);\n    \n    /**\n     * 查询应用指定时间段，指定命令名的结果集合\n     *\n     * @param appId 应用id\n     * @param beginTime 时间，格式：yyyyMMddHHmm\n     * @param endTime 时间，格式：yyyyMMddHHmm\n     * @return\n     */\n    public List<AppCommandStats> getCommandStatsListV2(long appId, long beginTime, long endTime, TimeDimensionalityEnum timeDimensionalityEnum);\n\n    /**\n     * 查询应用指定命令的峰值\n     * \n     * @param appId 应用id\n     * @param beginTime 时间，格式：yyyyMMddHHmm\n     * @param endTime 时间，格式：yyyyMMddHHmm\n     * @param commandName 命令名\n     * @return\n     */\n    public AppCommandStats getCommandClimax(long appId, Long beginTime, Long endTime, String commandName);\n\n    /**\n     * 获取应用详细信息\n     * \n     * @param appId\n     * @return\n     */\n    public AppDetailVO getAppDetail(long appId);\n    \n    /**\n     * 获取应用命令调用次数分布\n     * @param appId\n     * @param beginTime\n     * @param endTime\n     * @return\n     */\n    public List<AppCommandGroup> getAppCommandGroup(long appId, Long beginTime, Long endTime);\n\n    /**\n     * 在appId级别执行命令\n     *\n     * @param appId\n     * @param command\n     * @return\n     */\n    public String executeCommand(long appId, String command);\n\n\n    /**\n     * 按照appId获取实例所有慢查询日志\n     * @param appId\n     * @param startDate\n     * @param endDate\n     * @return\n     */\n    public List<InstanceSlowLog> getInstanceSlowLogByAppId(long appId, Date startDate, Date endDate);\n\n    /**\n     * 按照appId获取每个实例慢查询个数\n     * @param appId\n     * @param startDate\n     * @param endDate\n     * @return\n     */\n    public Map<String, Long> getInstanceSlowLogCountMapByAppId(Long appId, Date startDate, Date endDate);\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/stats/app/ImportAppCenter.java",
    "content": "package com.sohu.cache.stats.app;\n\nimport com.sohu.cache.constant.ImportAppResult;\nimport com.sohu.cache.entity.AppDesc;\n\n/**\n * 导入应用\n * @author leifu\n * @Date 2016-4-16\n * @Time 下午3:42:49\n */\npublic interface ImportAppCenter {\n\n    /**\n     * 检查应用和实例\n     * \n     * @param appDesc\n     * @param appInstanceInfo\n     * @return\n     */\n    ImportAppResult check(AppDesc appDesc, String appInstanceInfo);\n\n    /**\n     * 导入应用和相关实例\n     * \n     * @param appDesc\n     * @param appInstanceInfo\n     * @return\n     */\n    boolean importAppAndInstance(AppDesc appDesc, String appInstanceInfo);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/stats/app/impl/AppDailyDataCenterImpl.java",
    "content": "package com.sohu.cache.stats.app.impl;\n\nimport java.text.DecimalFormat;\nimport java.text.SimpleDateFormat;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.LinkedHashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.Set;\nimport java.util.TreeMap;\n\nimport org.apache.commons.collections.MapUtils;\nimport org.apache.commons.lang.math.NumberUtils;\nimport org.apache.commons.lang.time.DateUtils;\nimport org.apache.velocity.app.VelocityEngine;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.util.Assert;\n\nimport com.sohu.cache.dao.AppClientExceptionStatDao;\nimport com.sohu.cache.dao.AppClientValueStatDao;\nimport com.sohu.cache.dao.AppDailyDao;\nimport com.sohu.cache.dao.AppStatsDao;\nimport com.sohu.cache.dao.InstanceSlowLogDao;\nimport com.sohu.cache.entity.AppClientValueDistriSimple;\nimport com.sohu.cache.entity.AppDailyData;\nimport com.sohu.cache.entity.AppDesc;\nimport com.sohu.cache.stats.app.AppDailyDataCenter;\nimport com.sohu.cache.stats.app.AppStatsCenter;\nimport com.sohu.cache.util.ConstUtils;\nimport com.sohu.cache.web.component.EmailComponent;\nimport com.sohu.cache.web.service.AppService;\nimport com.sohu.cache.web.util.DateUtil;\nimport com.sohu.cache.web.util.VelocityUtils;\nimport com.sohu.cache.web.vo.AppDetailVO;\n\n/**\n * 应用日报\n * @author leifu\n * @Date 2016年8月10日\n * @Time 下午5:17:02\n */\npublic class AppDailyDataCenterImpl implements AppDailyDataCenter {\n\n    private Logger logger = LoggerFactory.getLogger(AppDailyDataCenterImpl.class);\n\n    private EmailComponent emailComponent;\n\n    private AppStatsCenter appStatsCenter;\n\n    private VelocityEngine velocityEngine;\n\n    private InstanceSlowLogDao instanceSlowLogDao;\n\n    private AppClientExceptionStatDao appClientExceptionStatDao;\n\n    private AppStatsDao appStatsDao;\n\n    private AppClientValueStatDao appClientValueStatDao;\n    \n    private AppDailyDao appDailyDao;\n    \n    private AppService appService;\n\n    private final static int STAT_ERROR = 0;\n    \n    @Override\n    public int sendAppDailyEmail() {\n        Date endDate = new Date();\n        Date startDate = DateUtils.addDays(endDate, -1);\n        int successCount = 0;\n        List<AppDesc> appDescList = appService.getAllAppDesc();\n        for (AppDesc appDesc : appDescList) {\n            try {\n                boolean result = sendAppDailyEmail(appDesc.getAppId(), startDate, endDate);\n                if (result) {\n                    successCount++;\n                }\n            } catch (Exception e) {\n                logger.error(e.getMessage(), e);\n            }\n        }\n        return successCount;\n    }\n    \n    @Override\n    public boolean sendAppDailyEmail(long appId, Date startDate, Date endDate) {\n        try {\n            AppDailyData appDailyData = generateAppDaily(appId, startDate, endDate);\n            if (appDailyData == null) {\n                return false;\n            }\n            fillAppDailyData(appDailyData);\n            //保存每天的日报，后期查询和分析\n            appDailyDao.save(appDailyData);\n            AppDetailVO appDetailVO = appDailyData.getAppDetailVO();\n            noticeAppDaily(startDate, appDetailVO, appDailyData);\n            return true;\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return false;\n        }\n    }\n\n    /**\n     * 填充信息\n     * @param appDailyData\n     */\n    private void fillAppDailyData(AppDailyData appDailyData) {\n        appDailyData.setAppId(appDailyData.getAppDetailVO().getAppDesc().getAppId());\n        appDailyData.setDate(appDailyData.getStartDate());\n        Map<String, Long> valueSizeDistributeCountMap = appDailyData.getValueSizeDistributeCountMap();\n        //@TODO 暂时不计数\n        long bigKeyTimes = 0;\n        StringBuffer bigKeyInfo = new StringBuffer();\n        for(Entry<String, Long> entry : valueSizeDistributeCountMap.entrySet()) {\n            String key = entry.getKey();\n            long times = entry.getValue();\n            bigKeyInfo.append(key + \":\" + times + \"\\n\");\n        }\n        appDailyData.setBigKeyInfo(bigKeyInfo.toString());\n        appDailyData.setBigKeyTimes(bigKeyTimes);\n    }\n\n    public AppDailyData generateAppDaily(long appId, Date startDate, Date endDate) {\n        Assert.isTrue(appId > 0L);\n        AppDetailVO appDetailVO = appStatsCenter.getAppDetail(appId);\n        if (appDetailVO == null) {\n            logger.error(\"appId={} not exist\", appId);\n            return null;\n        }\n        AppDesc appDesc = appDetailVO.getAppDesc();\n        if (appDesc.isOffline()) {\n            return null;\n        }\n        if (appDesc.isTest()) {\n            return null;\n        }\n        AppDailyData appDailyData = new AppDailyData();\n        appDailyData.setStartDate(startDate);\n        appDailyData.setEndDate(endDate);\n        \n        // 应用详情\n        appDailyData.setAppDetailVO(appDetailVO);\n\n        // 慢查询\n        int slowLogCount = getSlowLogCount(appId, startDate, endDate);\n        appDailyData.setSlowLogCount(slowLogCount);\n\n        // 客户端异常数\n        int clientExceptionCount = getClientExceptionCount(appId, startDate, endDate);\n        appDailyData.setClientExceptionCount(clientExceptionCount);\n\n        // 客户端值分布\n        Map<String, Long> valueSizeDistributeCountMap = getAppClientValueSizeDistributeCountMap(appId, startDate, endDate);\n        appDailyData.setValueSizeDistributeCountMap(valueSizeDistributeCountMap);\n\n        \n        // 应用相关统计\n        Map<String, Object> appMinuteStatMap = getAppMinuteStat(appId, startDate, endDate);\n        appDailyData.setMaxMinuteClientCount(MapUtils.getIntValue(appMinuteStatMap, \"maxClientCount\"));\n        appDailyData.setAvgMinuteClientCount(MapUtils.getIntValue(appMinuteStatMap, \"avgClientCount\"));\n        appDailyData.setMaxMinuteCommandCount(MapUtils.getIntValue(appMinuteStatMap, \"maxCommandCount\"));\n        appDailyData.setAvgMinuteCommandCount(MapUtils.getIntValue(appMinuteStatMap, \"avgCommandCount\"));\n        appDailyData.setMaxMinuteHitRatio(remainNumberTwoPoint(MapUtils.getDoubleValue(appMinuteStatMap, \"maxHitRatio\") * 100.0));\n        appDailyData.setMinMinuteHitRatio(remainNumberTwoPoint(MapUtils.getDoubleValue(appMinuteStatMap, \"minHitRatio\") * 100.0));\n        appDailyData.setAvgHitRatio(remainNumberTwoPoint(MapUtils.getDoubleValue(appMinuteStatMap, \"avgHitRatio\") * 100.0));\n        appDailyData.setAvgUsedMemory(MapUtils.getLongValue(appMinuteStatMap, \"avgUsedMemory\") / 1024 / 1024);\n        appDailyData.setMaxUsedMemory(MapUtils.getLongValue(appMinuteStatMap, \"maxUsedMemory\") / 1024 / 1024);\n        appDailyData.setExpiredKeysCount(MapUtils.getIntValue(appMinuteStatMap, \"expiredKeys\"));\n        appDailyData.setEvictedKeysCount(MapUtils.getIntValue(appMinuteStatMap, \"evictedKeys\"));\n        appDailyData.setAvgMinuteNetOutputByte(remainNumberTwoPoint(MapUtils.getDoubleValue(appMinuteStatMap, \"avgNetInputByte\") / 1024.0 / 1024.0));\n        appDailyData.setMaxMinuteNetOutputByte(remainNumberTwoPoint(MapUtils.getDoubleValue(appMinuteStatMap, \"maxNetInputByte\") / 1024.0 / 1024.0));\n        appDailyData.setAvgMinuteNetInputByte(remainNumberTwoPoint(MapUtils.getDoubleValue(appMinuteStatMap, \"avgNetOutputByte\") / 1024.0 / 1024.0));\n        appDailyData.setMaxMinuteNetInputByte(remainNumberTwoPoint(MapUtils.getDoubleValue(appMinuteStatMap, \"maxNetOutputByte\") / 1024.0 / 1024.0));\n        appDailyData.setAvgObjectSize(MapUtils.getIntValue(appMinuteStatMap, \"avgObjectSize\"));\n        appDailyData.setMaxObjectSize(MapUtils.getIntValue(appMinuteStatMap, \"maxObjectSize\"));\n\n        return appDailyData;\n    }\n    \n    \n    /**\n     * 保留两位\n     * @param num\n     * @return\n     */\n    private double remainNumberTwoPoint(double num) {\n        DecimalFormat df = new DecimalFormat(\"0.00\");\n        return NumberUtils.toDouble(df.format(num));\n    }\n    \n\n    private Map<String, Long> getAppClientValueSizeDistributeCountMap(long appId, Date startDate, Date endDate) {\n        try {\n            String COLLECT_TIME_FORMAT = \"yyyyMMddHHmmss\";\n            long startTime = NumberUtils.toLong(DateUtil.formatDate(startDate, COLLECT_TIME_FORMAT));\n            long endTime = NumberUtils.toLong(DateUtil.formatDate(endDate, COLLECT_TIME_FORMAT));\n            List<AppClientValueDistriSimple> appClientValueDistriSimpleList = appClientValueStatDao.getAppValueDistriList(appId, startTime, endTime);\n            Map<String, Long> valueSizeInfoCountMap = new TreeMap<String, Long>();\n            for (AppClientValueDistriSimple appClientValueDistriSimple : appClientValueDistriSimpleList) {\n                valueSizeInfoCountMap.put(appClientValueDistriSimple.getDistributeDesc(),\n                        appClientValueDistriSimple.getCount());\n            }\n            return valueSizeInfoCountMap;\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return Collections.emptyMap();\n        }\n    }\n\n    /**\n     * 获取客户端连接数统计\n     * \n     * @param appId\n     * @param startDate\n     * @param endDate\n     * @return\n     */\n    private Map<String, Object> getAppMinuteStat(long appId, Date startDate, Date endDate) {\n        try {\n            String COLLECT_TIME_FORMAT = \"yyyyMMddHHmm\";\n            long startTime = NumberUtils.toLong(DateUtil.formatDate(startDate, COLLECT_TIME_FORMAT));\n            long endTime = NumberUtils.toLong(DateUtil.formatDate(endDate, COLLECT_TIME_FORMAT));\n            return appStatsDao.getAppMinuteStat(appId, startTime, endTime);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return Collections.emptyMap();\n        }\n    }\n\n    /**\n     * 客户端异常数\n     * \n     * @param appId\n     * @param startDate\n     * @param endDate\n     * @return\n     */\n    private int getClientExceptionCount(long appId, Date startDate, Date endDate) {\n        try {\n            String COLLECT_TIME_FORMAT = \"yyyyMMddHHmmss\";\n            long startTime = NumberUtils.toLong(DateUtil.formatDate(startDate, COLLECT_TIME_FORMAT));\n            long endTime = NumberUtils.toLong(DateUtil.formatDate(endDate, COLLECT_TIME_FORMAT));\n            return appClientExceptionStatDao.getAppExceptionCount(appId, startTime, endTime, -1, null);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return STAT_ERROR;\n        }\n    }\n\n    /**\n     * 获取应用在指定日期内慢查询次数\n     * \n     * @param appId\n     * @param startDate\n     * @param endDate\n     * @return\n     */\n    private int getSlowLogCount(long appId, Date startDate, Date endDate) {\n        try {\n            return instanceSlowLogDao.getAppSlowLogCount(appId, startDate, endDate);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return STAT_ERROR;\n        }\n    }\n\n    /**\n     * 日报通知\n     * @param startDate\n     * @param appDetailVO\n     * @param appDailyData\n     */\n    public void noticeAppDaily(Date startDate, AppDetailVO appDetailVO, AppDailyData appDailyData) {\n        List<String> ccEmailList = getCCEmailList(appDetailVO.getAppDesc());\n        String startDateFormat = DateUtil.formatYYYYMMdd(startDate);\n        String title = String.format(\"【CacheCloud】%s日报(appId=%s)\", startDateFormat, appDetailVO.getAppDesc().getAppId());\n        String mailContent = VelocityUtils.createText(velocityEngine, appDetailVO.getAppDesc(), null, appDailyData, null, \"appDaily.vm\",\"UTF-8\");\n        emailComponent.sendMail(title, mailContent, appDetailVO.getEmailList(), ccEmailList);\n    }\n    \n    /**\n     * A级以上抄送管理员，S级抄送领导\n     * @param appDesc\n     * @return\n     */\n    private List<String> getCCEmailList(AppDesc appDesc) {\n        Set<String> ccEmailSet = new LinkedHashSet<String>();\n        //A级\n        if (appDesc.isVeryImportant()) {\n            for (String email : emailComponent.getAdminEmail().split(ConstUtils.COMMA)) {\n                ccEmailSet.add(email);\n            }\n        }\n        //S级\n        if (appDesc.isSuperImportant()) {\n            ccEmailSet.addAll(ConstUtils.LEADER_EMAIL_LIST);\n        }\n        return new ArrayList<String>(ccEmailSet);\n    }\n    \n    @Override\n    public AppDailyData getAppDailyData(long appId, Date date) {\n        try {\n            return appDailyDao.getAppDaily(appId, new SimpleDateFormat(\"yyyy-MM-dd\").format(date));\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return null;\n        }\n    }\n    \n    public void setInstanceSlowLogDao(InstanceSlowLogDao instanceSlowLogDao) {\n        this.instanceSlowLogDao = instanceSlowLogDao;\n    }\n\n    public void setEmailComponent(EmailComponent emailComponent) {\n        this.emailComponent = emailComponent;\n    }\n\n    public void setVelocityEngine(VelocityEngine velocityEngine) {\n        this.velocityEngine = velocityEngine;\n    }\n\n    public void setAppClientExceptionStatDao(AppClientExceptionStatDao appClientExceptionStatDao) {\n        this.appClientExceptionStatDao = appClientExceptionStatDao;\n    }\n\n    public void setAppStatsDao(AppStatsDao appStatsDao) {\n        this.appStatsDao = appStatsDao;\n    }\n\n    public void setAppClientValueStatDao(AppClientValueStatDao appClientValueStatDao) {\n        this.appClientValueStatDao = appClientValueStatDao;\n    }\n\n    public void setAppStatsCenter(AppStatsCenter appStatsCenter) {\n        this.appStatsCenter = appStatsCenter;\n    }\n\n    public void setAppService(AppService appService) {\n        this.appService = appService;\n    }\n\n    public void setAppDailyDao(AppDailyDao appDailyDao) {\n        this.appDailyDao = appDailyDao;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/stats/app/impl/AppDataMigrateCenterImpl.java",
    "content": "package com.sohu.cache.stats.app.impl;\n\nimport java.io.BufferedWriter;\nimport java.io.File;\nimport java.io.IOException;\nimport java.nio.charset.Charset;\nimport java.nio.file.Files;\nimport java.nio.file.Path;\nimport java.nio.file.Paths;\nimport java.text.SimpleDateFormat;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport org.apache.commons.collections.CollectionUtils;\nimport org.apache.commons.collections.MapUtils;\nimport org.apache.commons.lang.StringUtils;\nimport org.apache.commons.lang.math.NumberUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport redis.clients.jedis.Jedis;\n\nimport com.sohu.cache.constant.AppDataMigrateEnum;\nimport com.sohu.cache.constant.AppDataMigrateResult;\nimport com.sohu.cache.constant.AppDataMigrateStatusEnum;\nimport com.sohu.cache.constant.CommandResult;\nimport com.sohu.cache.constant.ErrorMessageEnum;\nimport com.sohu.cache.constant.RedisMigrateToolConstant;\nimport com.sohu.cache.dao.AppDataMigrateStatusDao;\nimport com.sohu.cache.entity.AppDataMigrateSearch;\nimport com.sohu.cache.entity.AppDataMigrateStatus;\nimport com.sohu.cache.entity.MachineInfo;\nimport com.sohu.cache.exception.SSHException;\nimport com.sohu.cache.machine.MachineCenter;\nimport com.sohu.cache.protocol.MachineProtocol;\nimport com.sohu.cache.redis.RedisCenter;\nimport com.sohu.cache.ssh.SSHUtil;\nimport com.sohu.cache.stats.app.AppDataMigrateCenter;\nimport com.sohu.cache.util.ConstUtils;\nimport com.sohu.cache.web.service.AppService;\n\n/**\n * 数据迁移(使用唯品会的开源工具redis-migrate-tool进行迁移)\n * \n * @author leifu\n * @Date 2016-6-8\n * @Time 下午2:54:33\n */\npublic class AppDataMigrateCenterImpl implements AppDataMigrateCenter {\n\n    private Logger logger = LoggerFactory.getLogger(AppDataMigrateCenterImpl.class);\n\n    private AppService appService;\n\n    private RedisCenter redisCenter;\n\n    private MachineCenter machineCenter;\n    \n    private AppDataMigrateStatusDao appDataMigrateStatusDao;\n\n    @Override\n    public AppDataMigrateResult check(String migrateMachineIp, AppDataMigrateEnum sourceRedisMigrateEnum,\n            String sourceServers,\n            AppDataMigrateEnum targetRedisMigrateEnum, String targetServers, String redisSourcePass, String redisTargetPass) {\n\n        // 1. 检查migrateMachineIp是否安装\n        AppDataMigrateResult migrateMachineResult = checkMigrateMachine(migrateMachineIp);\n        if (!migrateMachineResult.isSuccess()) {\n            return migrateMachineResult;\n        }\n\n        // 2. 检查源配置\n        AppDataMigrateResult sourceResult = checkMigrateConfig(migrateMachineIp, sourceRedisMigrateEnum, sourceServers, redisSourcePass, true);\n        if (!sourceResult.isSuccess()) {\n            return sourceResult;\n        }\n\n        // 3. 检查目标\n        AppDataMigrateResult targetResult = checkMigrateConfig(migrateMachineIp, targetRedisMigrateEnum, targetServers, redisTargetPass, false);\n        if (!targetResult.isSuccess()) {\n            return targetResult;\n        }\n\n        return AppDataMigrateResult.success();\n    }\n\n    /**\n     * 检查迁移的机器是否正常\n     * \n     * @param migrateMachineIp\n     * @return\n     */\n    private AppDataMigrateResult checkMigrateMachine(String migrateMachineIp) {\n        if (StringUtils.isBlank(migrateMachineIp)) {\n            return AppDataMigrateResult.fail(\"redis-migrate-tool所在机器的IP不能为空\");\n        }\n        // 1. 检查机器是否存在在机器列表中\n        try {\n            MachineInfo machineInfo = machineCenter.getMachineInfoByIp(migrateMachineIp);\n            if (machineInfo == null) {\n                return AppDataMigrateResult.fail(migrateMachineIp + \"没有在机器管理列表中\");\n            } else if (machineInfo.isOffline()) {\n                return AppDataMigrateResult.fail(migrateMachineIp + \",该机器已经被删除\");\n            }\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return AppDataMigrateResult.fail(\"检测发生异常，请观察日志\");\n        }\n        // 2. 检查是否安装redis-migrate-tool\n        try {\n            String cmd = ConstUtils.getRedisMigrateToolCmd();\n            String response = SSHUtil.execute(migrateMachineIp, cmd);\n            if (StringUtils.isBlank(response) || !response.contains(\"source\") || !response.contains(\"target\")) {\n                return AppDataMigrateResult.fail(migrateMachineIp + \"下，\" + cmd + \"执行失败，请确保redis-migrate-tool安装正确!\");\n            }\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return AppDataMigrateResult.fail(\"检测发生异常，请观察日志\");\n        }\n\n        // 3. 检查是否有运行的redis-migrate-tool\n        // 3.1 从数据库里检测，每次迁移记录迁移的详情,状态不太好控制，暂时去掉\n//        try {\n//            int count = appDataMigrateStatusDao.getMigrateMachineStatCount(migrateMachineIp, AppDataMigrateStatusEnum.START.getStatus());\n//            if (count > 0) {\n//                return AppDataMigrateResult.fail(migrateMachineIp + \"下有redis-migrate-tool进程，请确保只有一台机器只有一个迁移任务进行\");\n//            }\n//        } catch (Exception e) {\n//            logger.error(e.getMessage(), e);\n//        }\n\n        // 3.2 查看进程是否存在\n        try {\n            String cmd = \"/bin/ps -ef | grep redis-migrate-tool | grep -v grep | grep -v tail\";\n            String response = SSHUtil.execute(migrateMachineIp, cmd);\n            if (StringUtils.isNotBlank(response)) {\n                return AppDataMigrateResult.fail(migrateMachineIp + \"下有redis-migrate-tool进程，请确保只有一台机器只有一个迁移任务进行\");\n            }\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return AppDataMigrateResult.fail(\"检测发生异常，请观察日志\");\n        }\n\n        return AppDataMigrateResult.success();\n    }\n\n    /**\n     * 检测配置\n     * \n     * @param migrateMachineIp\n     * @param redisMigrateEnum\n     * @param servers\n     * @param redisSourcePass 源密码\n     * @return\n     */\n    private AppDataMigrateResult checkMigrateConfig(String migrateMachineIp, AppDataMigrateEnum redisMigrateEnum,\n            String servers, String redisPassword, boolean isSource) {\n        //target如果是rdb是没有路径的，不需要检测\n        if (isSource || !AppDataMigrateEnum.isFileType(redisMigrateEnum)) {\n            if (StringUtils.isBlank(servers)) {\n                return AppDataMigrateResult.fail(\"服务器信息不能为空!\");\n            }\n        }\n        List<String> serverList = Arrays.asList(servers.split(ConstUtils.NEXT_LINE));\n        if (CollectionUtils.isEmpty(serverList)) {\n            return AppDataMigrateResult.fail(\"服务器信息格式有问题!\");\n        }\n        for (String server : serverList) {\n            if (AppDataMigrateEnum.isFileType(redisMigrateEnum)) {\n                if (!isSource) {\n                    continue;\n                }\n                // 检查文件是否存在 \n                String filePath = server;\n                String cmd = \"head \" + filePath;\n                try {\n                    String headResult = SSHUtil.execute(migrateMachineIp, cmd);\n                    if (StringUtils.isBlank(headResult)) {\n                        return AppDataMigrateResult.fail(migrateMachineIp + \"上的rdb:\" + filePath + \"不存在或者为空!\");\n                    }\n                } catch (Exception e) {\n                    logger.error(e.getMessage());\n                    return AppDataMigrateResult.fail(migrateMachineIp + \"上的rdb:\" + filePath + \"读取异常!\");\n                }\n            } else {\n                // 1. 检查是否为ip:port格式(简单检查一下，无需正则表达式)\n                // 2. 检查Redis节点是否存在\n                String[] instanceItems = server.split(\":\");\n                if (instanceItems.length != 2) {\n                    return AppDataMigrateResult.fail(\"实例信息\" + server + \"格式错误，必须为ip:port格式\");\n                }\n                String ip = instanceItems[0];\n                String portStr = instanceItems[1];\n                boolean portIsDigit = NumberUtils.isDigits(portStr);\n                if (!portIsDigit) {\n                    return AppDataMigrateResult.fail(server + \"中的port不是整数\");\n                }\n                int port = NumberUtils.toInt(portStr);\n                boolean isRun = redisCenter.isRun(ip, port, redisPassword);\n                if (!isRun) {\n                    return AppDataMigrateResult.fail(server + \"不是存活的或者密码错误!\");\n                }\n            }\n        }\n\n        return AppDataMigrateResult.success();\n    }\n\n    @Override\n\tpublic boolean migrate(String migrateMachineIp, AppDataMigrateEnum sourceRedisMigrateEnum, String sourceServers,\n\t\t\tAppDataMigrateEnum targetRedisMigrateEnum, String targetServers, long sourceAppId, long targetAppId,\n\t\t\tString redisSourcePass, String redisTargetPass, long userId) {\n        // 1. 生成配置\n        int migrateMachinePort = ConstUtils.REDIS_MIGRATE_TOOL_PORT;\n        String configContent = generateConfig(migrateMachinePort, sourceRedisMigrateEnum, sourceServers, targetRedisMigrateEnum,\n                targetServers, redisSourcePass, redisTargetPass);\n        // 2. 上传配置\n        String timestamp = new SimpleDateFormat(\"yyyyMMddHHmmss\").format(new Date());\n        String confileFileName = \"rmt-\" + timestamp + \".conf\";\n        String logFileName = \"rmt-\" + timestamp + \".log\";\n        boolean uploadConfig = createRemoteFile(migrateMachineIp, confileFileName, configContent);\n        if (!uploadConfig) {\n            return false;\n        }\n        // 3. 开始执行: 指定的配置名、目录、日志名\n        String cmd = ConstUtils.getRedisMigrateToolCmd() + \" -c \" + ConstUtils.getRedisMigrateToolDir() + confileFileName\n                + \" -o \" + ConstUtils.getRedisMigrateToolDir() + logFileName + \" -d\";\n        logger.warn(cmd);\n        try {\n            SSHUtil.execute(migrateMachineIp, cmd);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return false;\n        }\n\n        // 4. 记录执行记录\n        AppDataMigrateStatus appDataMigrateStatus = new AppDataMigrateStatus();\n        appDataMigrateStatus.setMigrateMachineIp(migrateMachineIp);\n        appDataMigrateStatus.setMigrateMachinePort(migrateMachinePort);\n        appDataMigrateStatus.setStartTime(new Date());\n        appDataMigrateStatus.setSourceMigrateType(sourceRedisMigrateEnum.getIndex());\n        appDataMigrateStatus.setSourceServers(sourceServers);\n        appDataMigrateStatus.setTargetMigrateType(targetRedisMigrateEnum.getIndex());\n        appDataMigrateStatus.setTargetServers(targetServers);\n        appDataMigrateStatus.setLogPath(ConstUtils.getRedisMigrateToolDir() + logFileName);\n        appDataMigrateStatus.setConfigPath(ConstUtils.getRedisMigrateToolDir() + confileFileName);\n        appDataMigrateStatus.setUserId(userId);\n        appDataMigrateStatus.setSourceAppId(sourceAppId);\n        appDataMigrateStatus.setTargetAppId(targetAppId);\n        appDataMigrateStatus.setStatus(AppDataMigrateStatusEnum.START.getStatus());\n        appDataMigrateStatusDao.save(appDataMigrateStatus);\n\n        return true;\n    }\n\n    /**\n     * 生成配置\n     * \n     * @param sourceRedisMigrateEnum\n     * @param sourceServers\n     * @param targetRedisMigrateEnum\n     * @param targetServers\n     * @return\n     */\n    public String generateConfig(int listenPort, AppDataMigrateEnum sourceRedisMigrateEnum, String sourceServers,\n            AppDataMigrateEnum targetRedisMigrateEnum, String targetServers, String redisSourcePass, String redisTargetPass) {\n        // source\n        StringBuffer config = new StringBuffer();\n        config.append(\"[source]\" + ConstUtils.NEXT_LINE);\n        config.append(\"type: \" + sourceRedisMigrateEnum.getType() + ConstUtils.NEXT_LINE);\n        config.append(\"servers:\" + ConstUtils.NEXT_LINE);\n        List<String> sourceServerList = Arrays.asList(sourceServers.split(ConstUtils.NEXT_LINE));\n        for (String server : sourceServerList) {\n            config.append(\" - \" + server + ConstUtils.NEXT_LINE);\n        }\n        if (StringUtils.isNotBlank(redisSourcePass)) {\n            config.append(\"redis_auth: \" + redisSourcePass + ConstUtils.NEXT_LINE);\n        }\n        config.append(ConstUtils.NEXT_LINE);\n\n        // target\n        config.append(\"[target]\" + ConstUtils.NEXT_LINE);\n        config.append(\"type: \" + targetRedisMigrateEnum.getType() + ConstUtils.NEXT_LINE);\n        if (!AppDataMigrateEnum.isFileType(targetRedisMigrateEnum)) {\n            config.append(\"servers:\" + ConstUtils.NEXT_LINE);\n            List<String> targetServerList = Arrays.asList(targetServers.split(ConstUtils.NEXT_LINE));\n            for (String server : targetServerList) {\n                config.append(\" - \" + server + ConstUtils.NEXT_LINE);\n            }\n            if (StringUtils.isNotBlank(redisTargetPass)) {\n                config.append(\"redis_auth: \" + redisTargetPass + ConstUtils.NEXT_LINE);\n            }\n            config.append(ConstUtils.NEXT_LINE);\n        }\n\n        // common:使用最简配置\n        config.append(\"[common]\" + ConstUtils.NEXT_LINE);\n        config.append(\"listen: 0.0.0.0:\" + listenPort + ConstUtils.NEXT_LINE);\n        config.append(\"dir: \" + ConstUtils.getRedisMigrateToolDir());\n\n        return config.toString();\n    }\n\n    /**\n     * 创建远程文件\n     * \n     * @param host\n     * @param fileName\n     * @param content\n     */\n    public boolean createRemoteFile(String host, String fileName, String content) {\n        /**\n         * 1. 创建本地文件\n         */\n        // 确认目录\n        String localAbsolutePath = MachineProtocol.TMP_DIR + fileName;\n        File tmpDir = new File(MachineProtocol.TMP_DIR);\n        if (!tmpDir.exists()) {\n            if (!tmpDir.mkdirs()) {\n                logger.error(\"cannot create /tmp/cachecloud directory.\");\n            }\n        }\n        Path path = Paths.get(MachineProtocol.TMP_DIR + fileName);\n        // 将配置文件的内容写到本地\n        BufferedWriter bufferedWriter = null;\n        try {\n            bufferedWriter = Files.newBufferedWriter(path, Charset.forName(MachineProtocol.ENCODING_UTF8));\n            bufferedWriter.write(content);\n        } catch (IOException e) {\n            logger.error(\"write rmt file error, ip: {}, filename: {}, content: {}\", host, fileName, content, e);\n            return false;\n        } finally {\n            if (bufferedWriter != null) {\n                try {\n                    bufferedWriter.close();\n                } catch (IOException e) {\n                \tlogger.error(e.getMessage(), e);\n                }\n            }\n        }\n\n        /**\n         * 2. 将配置文件推送到目标机器上\n         */\n        try {\n            SSHUtil.scpFileToRemote(host, localAbsolutePath, ConstUtils.getRedisMigrateToolDir());\n        } catch (SSHException e) {\n            logger.error(\"scp rmt file to remote server error: ip: {}, fileName: {}\", host, fileName, e);\n            return false;\n        }\n\n        /**\n         * 3. 删除临时文件\n         */\n        File file = new File(localAbsolutePath);\n        if (file.exists()) {\n            file.delete();\n        }\n\n        return true;\n    }\n    \n    @Override\n\tpublic List<AppDataMigrateStatus> search(AppDataMigrateSearch appDataMigrateSearch) {\n    \ttry {\n            return appDataMigrateStatusDao.search(appDataMigrateSearch);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return Collections.emptyList();\n        }\n\t}\n    \n    \n    @Override\n    public String showDataMigrateLog(long id, int pageSize) {\n        AppDataMigrateStatus appDataMigrateStatus = appDataMigrateStatusDao.get(id);\n        if (appDataMigrateStatus == null) {\n            return \"\";\n        }\n        String logPath = appDataMigrateStatus.getLogPath();\n        String host = appDataMigrateStatus.getMigrateMachineIp();\n        StringBuilder command = new StringBuilder();\n        command.append(\"/usr/bin/tail -n\").append(pageSize).append(\" \").append(logPath);\n        try {\n            return SSHUtil.execute(host, command.toString());\n        } catch (SSHException e) {\n            logger.error(e.getMessage(), e);\n            return \"\";\n        }\n    }\n    \n    @Override\n    public String showDataMigrateConf(long id) {\n        AppDataMigrateStatus appDataMigrateStatus = appDataMigrateStatusDao.get(id);\n        if (appDataMigrateStatus == null) {\n            return \"\";\n        }\n        String configPath = appDataMigrateStatus.getConfigPath();\n        String host = appDataMigrateStatus.getMigrateMachineIp();\n        String command = \"cat \" + configPath;\n        try {\n            return SSHUtil.execute(host, command);\n        } catch (SSHException e) {\n            logger.error(e.getMessage(), e);\n            return \"\";\n        }\n    }\n    \n    @Override\n    public Map<RedisMigrateToolConstant, Map<String, Object>> showMiragteToolProcess(long id) {\n        AppDataMigrateStatus appDataMigrateStatus = appDataMigrateStatusDao.get(id);\n        if (appDataMigrateStatus == null) {\n            return Collections.emptyMap();\n        }\n        String info = \"\";\n        String host = appDataMigrateStatus.getMigrateMachineIp();\n        int port = appDataMigrateStatus.getMigrateMachinePort();\n        Jedis jedis = null;\n        try {\n            jedis = new Jedis(host, port, 5000);\n            info = jedis.info();\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        } finally {\n            if (jedis != null) {\n                jedis.close();\n            }\n        }\n        if (StringUtils.isBlank(info)) {\n            return Collections.emptyMap();\n        }\n\n        return processRedisMigrateToolStats(info);\n        \n    }\n    \n    /**\n     * 处理迁移工具状态\n     * @param statResult\n     * @return\n     */\n    private Map<RedisMigrateToolConstant, Map<String, Object>> processRedisMigrateToolStats(String statResult) {\n        Map<RedisMigrateToolConstant, Map<String, Object>> redisStatMap = new HashMap<RedisMigrateToolConstant, Map<String, Object>>();\n        String[] data = statResult.split(\"\\r\\n\");\n        String key;\n        int i = 0;\n        int length = data.length;\n        while (i < length) {\n            if (data[i].contains(\"#\")) {\n                int index = data[i].indexOf('#');\n                key = data[i].substring(index + 1);\n                ++i;\n                RedisMigrateToolConstant redisMigrateToolConstant = RedisMigrateToolConstant.value(key.trim());\n                if (redisMigrateToolConstant == null) {\n                    continue;\n                }\n                Map<String, Object> sectionMap = new LinkedHashMap<String, Object>();\n                while (i < length && data[i].contains(\":\")) {\n                    String[] pair = data[i].split(\":\");\n                    sectionMap.put(pair[0], pair[1]);\n                    i++;\n                }\n                redisStatMap.put(redisMigrateToolConstant, sectionMap);\n            } else {\n                i++;\n            }\n        }\n        return redisStatMap;\n    }\n    \n    \n    @Override\n    public CommandResult sampleCheckData(long id, int nums) {\n        AppDataMigrateStatus appDataMigrateStatus = appDataMigrateStatusDao.get(id);\n        if (appDataMigrateStatus == null) {\n            return null;\n        }\n        String ip = appDataMigrateStatus.getMigrateMachineIp();\n        String configPath = appDataMigrateStatus.getConfigPath();\n        String sampleCheckDataCmd = ConstUtils.getRedisMigrateToolCmd() + \" -c \" + configPath + \" -C\" + \" 'redis_check \" + nums + \"'\";\n        logger.warn(\"sampleCheckDataCmd: {}\", sampleCheckDataCmd);\n        try {\n            return new CommandResult(sampleCheckDataCmd, SSHUtil.execute(ip, sampleCheckDataCmd));\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return new CommandResult(sampleCheckDataCmd, ErrorMessageEnum.INNER_ERROR_MSG.getMessage());\n        }\n    }\n    \n    @Override\n    public AppDataMigrateResult stopMigrate(long id) {\n        // 获取基本信息\n        AppDataMigrateStatus appDataMigrateStatus = appDataMigrateStatusDao.get(id);\n        if (appDataMigrateStatus == null) {\n            return AppDataMigrateResult.fail(\"id=\" + id + \"迁移记录不存在!\");\n        }\n        // 获取进程号\n        String migrateMachineIp = appDataMigrateStatus.getMigrateMachineIp();\n        String migrateMachineHostPort = migrateMachineIp + \":\" + appDataMigrateStatus.getMigrateMachinePort();\n        Map<RedisMigrateToolConstant, Map<String, Object>> redisMigrateToolStatMap = showMiragteToolProcess(id);\n        if (MapUtils.isEmpty(redisMigrateToolStatMap)) {\n            return AppDataMigrateResult.fail(\"获取\" + migrateMachineHostPort + \"相关信息失败，可能是进程不存在或者客户端超时，请查找原因或重试!\");\n        }\n        Map<String, Object> serverMap = redisMigrateToolStatMap.get(RedisMigrateToolConstant.Server);\n        int pid = MapUtils.getInteger(serverMap, \"process_id\", -1);\n        if (pid <= 0) {\n            return AppDataMigrateResult.fail(\"获取\" + migrateMachineHostPort + \"的进程号\" + pid + \"异常\");\n        }\n\n        // 确认进程号是redis-migrate-tool进程\n        Boolean exist = checkPidWhetherIsRmt(migrateMachineIp, pid);\n        if (exist == null) {\n            return AppDataMigrateResult.fail(\"执行过程中发生异常,请查看系统日志!\");\n        } else if (exist.equals(false)) {\n            return AppDataMigrateResult.fail(migrateMachineIp + \"进程号\" + pid + \"不存在,请确认!\");\n        }\n\n        // kill掉进程\n        try {\n            String cmd = \"kill \" + pid;\n            SSHUtil.execute(migrateMachineIp, cmd);\n            exist = checkPidWhetherIsRmt(migrateMachineIp, pid);\n            if (exist == null) {\n                return AppDataMigrateResult.fail(ErrorMessageEnum.INNER_ERROR_MSG.getMessage());\n            } else if (exist.equals(false)) {\n                // 更新记录完成更新\n                appDataMigrateStatusDao.updateStatus(id, AppDataMigrateStatusEnum.END.getStatus());\n                return AppDataMigrateResult.success(\"已经成功停止了id=\" + id + \"的迁移任务\");\n            } else {\n                return AppDataMigrateResult.fail(migrateMachineIp + \"进程号\" + pid + \"仍然存在,没有kill掉,请确认!\");\n            }\n        } catch (Exception e) {\n            logger.error(e.getMessage());\n            return AppDataMigrateResult.fail(ErrorMessageEnum.INNER_ERROR_MSG.getMessage());\n        }\n    }\n\n    /**\n     * 检查pid是否是redis-migrate-tool进程\n     * @param migrateMachineIp\n     * @param pid\n     * @return\n     * @throws SSHException\n     */\n    private Boolean checkPidWhetherIsRmt(String migrateMachineIp, int pid){\n        try {\n            String cmd = \"/bin/ps -ef | grep redis-migrate-tool | grep -v grep | grep \" + pid;\n            String response = SSHUtil.execute(migrateMachineIp, cmd);\n            if (StringUtils.isNotBlank(response)) {\n                return true;\n            } else {\n                return false;\n            }\n        } catch (SSHException e) {\n            logger.error(e.getMessage(), e);\n            return null;\n        }\n    }\n\n    public void setRedisCenter(RedisCenter redisCenter) {\n        this.redisCenter = redisCenter;\n    }\n\n    public void setMachineCenter(MachineCenter machineCenter) {\n        this.machineCenter = machineCenter;\n    }\n\n    public void setAppService(AppService appService) {\n        this.appService = appService;\n    }\n\n    public void setAppDataMigrateStatusDao(AppDataMigrateStatusDao appDataMigrateStatusDao) {\n        this.appDataMigrateStatusDao = appDataMigrateStatusDao;\n    }\n\n\t\n\n    \n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/stats/app/impl/AppDeployCenterImpl.java",
    "content": "package com.sohu.cache.stats.app.impl;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.SynchronousQueue;\nimport java.util.concurrent.ThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\n\nimport org.apache.commons.collections.CollectionUtils;\nimport org.apache.commons.collections.MapUtils;\nimport org.apache.commons.lang.StringUtils;\nimport org.apache.commons.lang.math.NumberUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.util.Assert;\n\nimport com.sohu.cache.async.NamedThreadFactory;\nimport com.sohu.cache.constant.AppAuditLogTypeEnum;\nimport com.sohu.cache.constant.AppAuditType;\nimport com.sohu.cache.constant.AppCheckEnum;\nimport com.sohu.cache.constant.AppStatusEnum;\nimport com.sohu.cache.constant.DataFormatCheckResult;\nimport com.sohu.cache.constant.HorizontalResult;\nimport com.sohu.cache.constant.InstanceStatusEnum;\nimport com.sohu.cache.constant.PipelineEnum;\nimport com.sohu.cache.constant.ReshardStatusEnum;\nimport com.sohu.cache.dao.AppAuditDao;\nimport com.sohu.cache.dao.AppAuditLogDao;\nimport com.sohu.cache.dao.AppDao;\nimport com.sohu.cache.dao.InstanceDao;\nimport com.sohu.cache.dao.InstanceReshardProcessDao;\nimport com.sohu.cache.entity.AppAudit;\nimport com.sohu.cache.entity.AppAuditLog;\nimport com.sohu.cache.entity.AppDesc;\nimport com.sohu.cache.entity.AppUser;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.entity.InstanceReshardProcess;\nimport com.sohu.cache.entity.InstanceSlotModel;\nimport com.sohu.cache.entity.MachineInfo;\nimport com.sohu.cache.machine.MachineCenter;\nimport com.sohu.cache.redis.RedisCenter;\nimport com.sohu.cache.redis.RedisClusterNode;\nimport com.sohu.cache.redis.RedisClusterReshard;\nimport com.sohu.cache.redis.RedisDeployCenter;\nimport com.sohu.cache.stats.app.AppDeployCenter;\nimport com.sohu.cache.util.ConstUtils;\nimport com.sohu.cache.util.TypeUtil;\nimport com.sohu.cache.web.service.AppService;\nimport com.sohu.cache.web.util.AppEmailUtil;\n\nimport redis.clients.jedis.HostAndPort;\n\n/**\n * Created by yijunzhang on 14-10-20.\n */\npublic class AppDeployCenterImpl implements AppDeployCenter {\n    private final Logger logger = LoggerFactory.getLogger(this.getClass());\n\n    private AppService appService;\n\n    private RedisDeployCenter redisDeployCenter;\n\n    private RedisCenter redisCenter;\n\n    private AppEmailUtil appEmailUtil;\n\n    private AppAuditDao appAuditDao;\n\n    private MachineCenter machineCenter;\n\n    private InstanceDao instanceDao;\n\n    private AppAuditLogDao appAuditLogDao;\n    \n    private AppDao appDao;\n    \n    private InstanceReshardProcessDao instanceReshardProcessDao;\n\n    private ExecutorService processThreadPool = new ThreadPoolExecutor(0, 256,\n            0L, TimeUnit.MILLISECONDS,\n            new SynchronousQueue<Runnable>(),\n            new NamedThreadFactory(\"redis-cluster-reshard\", false));\n\n    @Override\n    public boolean createApp(AppDesc appDesc, AppUser appUser, String memSize) {\n        try {\n            appService.save(appDesc);\n            // 保存应用和用户的关系\n            appService.saveAppToUser(appDesc.getAppId(), appDesc.getUserId());\n            // 更新appKey\n            long appId = appDesc.getAppId();\n            appService.updateAppKey(appId);\n\n            // 保存应用审批信息\n            AppAudit appAudit = new AppAudit();\n            appAudit.setAppId(appId);\n            appAudit.setUserId(appUser.getId());\n            appAudit.setUserName(appUser.getName());\n            appAudit.setModifyTime(new Date());\n            appAudit.setParam1(memSize);\n            appAudit.setParam2(appDesc.getTypeDesc());\n            appAudit.setInfo(\"类型:\" + appDesc.getTypeDesc() + \";初始申请空间:\" + memSize);\n            appAudit.setStatus(AppCheckEnum.APP_WATING_CHECK.value());\n            appAudit.setType(AppAuditType.APP_AUDIT.getValue());\n            appAuditDao.insertAppAudit(appAudit);\n\n            // 发邮件\n            appEmailUtil.noticeAppResult(appDesc, appAudit);\n\n            // 保存申请日志\n            AppAuditLog appAuditLog = AppAuditLog.generate(appDesc, appUser, appAudit.getId(),\n                    AppAuditLogTypeEnum.APP_DESC_APPLY);\n            if (appAuditLog != null) {\n                appAuditLogDao.save(appAuditLog);\n            }\n\n            return true;\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return false;\n        }\n    }\n    \n    @Override\n    public DataFormatCheckResult checkAppDeployDetail(Long appAuditId, String appDeployText) {\n        if (appAuditId == null) {\n            logger.error(\"appAuditId is null\");\n            return DataFormatCheckResult.fail(\"审核id不能为空!\");\n        }\n        if (StringUtils.isBlank(appDeployText)) {\n            logger.error(\"appDeployText is null\");\n            return DataFormatCheckResult.fail(\"部署节点列表不能为空!\");\n        }\n        String[] nodeInfoList = appDeployText.split(ConstUtils.NEXT_LINE);\n        if (nodeInfoList == null || nodeInfoList.length == 0) {\n            logger.error(\"nodeInfoList is null\");\n            return DataFormatCheckResult.fail(\"部署节点列表不能为空!\");\n        }\n        AppAudit appAudit = appAuditDao.getAppAudit(appAuditId);\n        if (appAudit == null) {\n            logger.error(\"appAudit:id={} is not exist\", appAuditId);\n            return DataFormatCheckResult.fail(String.format(\"审核id=%s不存在\", appAuditId));\n        }\n        long appId = appAudit.getAppId();\n        AppDesc appDesc = appService.getByAppId(appId);\n        if (appDesc == null) {\n            logger.error(\"appDesc:id={} is not exist\");\n            return DataFormatCheckResult.fail(String.format(\"appId=%s不存在\", appId));\n        }\n        int type = appDesc.getType();\n        //检查每一行\n        for (String nodeInfo : nodeInfoList) {\n            nodeInfo = StringUtils.trim(nodeInfo);\n            if (StringUtils.isBlank(nodeInfo)) {\n                return DataFormatCheckResult.fail(String.format(\"部署列表%s中存在空行\", appDeployText));\n            }\n            String[] array = nodeInfo.split(ConstUtils.COLON);\n            if (array == null || array.length == 0) {\n                return DataFormatCheckResult.fail(String.format(\"部署列表%s中存在空行\", appDeployText));\n            }\n            String masterHost = null;\n            String memSize = null;\n            String slaveHost = null;\n            if (TypeUtil.isRedisCluster(type)) {\n                if (array.length == 2) {\n                    masterHost = array[0];\n                    memSize = array[1];\n                } else if (array.length == 3) {\n                    masterHost = array[0];\n                    memSize = array[1];\n                    slaveHost = array[2];\n                } else {\n                    return DataFormatCheckResult.fail(String.format(\"部署列表中%s, 格式错误!\", nodeInfo));\n                }\n            } else if (TypeUtil.isRedisSentinel(type)) {\n                if (array.length == 3) {\n                    masterHost = array[0];\n                    memSize = array[1];\n                    slaveHost = array[2];\n                } else if (array.length == 1) {\n                    masterHost = array[0];\n                } else {\n                    return DataFormatCheckResult.fail(String.format(\"部署列表中%s, 格式错误!\", nodeInfo));\n                }\n            } else if (TypeUtil.isRedisStandalone(type)) {\n                if (array.length == 2) {\n                    masterHost = array[0];\n                    memSize = array[1];\n                } else {\n                    return DataFormatCheckResult.fail(String.format(\"部署列表中%s, 格式错误!\", nodeInfo));\n                }\n            }\n            if (!checkHostExist(masterHost)) {\n                return DataFormatCheckResult.fail(String.format(\"%s中的ip=%s不存在，请在机器管理中添加!\", nodeInfo, masterHost));\n            }\n            if (StringUtils.isNotBlank(memSize) && !NumberUtils.isDigits(memSize)) {\n                return DataFormatCheckResult.fail(String.format(\"%s中的中的memSize=%s不是整数!\", nodeInfo, memSize));\n            }\n            if (StringUtils.isNotBlank(slaveHost) && !checkHostExist(slaveHost)) {\n                return DataFormatCheckResult.fail(String.format(\"%s中的ip=%s不存在，请在机器管理中添加!\", nodeInfo, slaveHost));\n            }\n        }\n        //检查sentinel类型:数据节点一行，sentinel节点多行\n        if (TypeUtil.isRedisSentinel(type)) {\n            return checkSentinelAppDeploy(nodeInfoList);\n        //检查单点类型:只能有一行数据节点\n        } else if (TypeUtil.isRedisStandalone(type)) {\n            return checkStandaloneAppDeploy(nodeInfoList);\n        } \n        return DataFormatCheckResult.success(\"应用部署格式正确，可以开始部署了!\");\n    }\n\n    /**\n     * 检查单点格式\n     * @param nodeInfoList\n     * @return\n     */\n    private DataFormatCheckResult checkStandaloneAppDeploy(String[] nodeInfoList) {\n        int redisLineNum = 0;\n        for (String nodeInfo : nodeInfoList) {\n            nodeInfo = StringUtils.trim(nodeInfo);\n            String[] array = nodeInfo.split(ConstUtils.COLON);\n            if (array.length == 2) {\n                redisLineNum++;\n            }\n        }\n        // redis节点只有一行\n        if (redisLineNum != 1) {\n            return DataFormatCheckResult.fail(\"应用部署格式错误, Standalone格式必须是一行masterIp:memSize(M)\");\n        }\n        return DataFormatCheckResult.success(\"应用部署格式正确，可以开始部署了!\");\n    }\n\n    /**\n     * 检查redis sentinel格式\n     * @param nodeInfoList\n     * @return\n     */\n    private DataFormatCheckResult checkSentinelAppDeploy(String[] nodeInfoList) {\n        int redisLineNum = 0;\n        int sentinelLineNum = 0;\n        for (String nodeInfo : nodeInfoList) {\n            nodeInfo = StringUtils.trim(nodeInfo);\n            String[] array = nodeInfo.split(ConstUtils.COLON);\n            if (array.length == 3) {\n                redisLineNum++;\n            } else if (array.length == 1) {\n                sentinelLineNum++;\n            }\n        }\n        // redis节点只有redisLineMustNum行\n        final int redisLineMustNum = 1;\n        if (redisLineNum < redisLineMustNum) {\n            return DataFormatCheckResult.fail(\"应用部署格式错误, Sentinel应用中必须有Redis数据节点!\");\n        } else if (redisLineNum > redisLineMustNum) {\n            return DataFormatCheckResult.fail(\"应用部署格式错误, Sentinel应用中Redis数据节点只能有一行!\");\n        }  \n        \n        // sentinel节点至少有sentinelLessNum个\n        final int sentinelLessNum = 3;\n        if (sentinelLineNum < sentinelLessNum) {\n            return DataFormatCheckResult.fail(\"应用部署格式错误, Sentinel应用中Sentinel节点至少要有\" + sentinelLessNum + \"个!\");\n        }\n        return DataFormatCheckResult.success(\"应用部署格式正确，可以开始部署了!\");\n    }\n\n    /**\n     * 查看host是否存在\n     * @param host\n     * @return\n     */\n    private boolean checkHostExist(String host) {\n        try {\n            MachineInfo machineInfo = machineCenter.getMachineInfoByIp(host);\n            if (machineInfo == null) {\n                return false;\n            }\n            if (machineInfo.isOffline()) {\n                logger.warn(\"host {} is offline\", host);\n                return false;\n            }\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return false;\n        }\n        return true;\n    }\n\n    @Override\n    public boolean allocateResourceApp(Long appAuditId, List<String> nodeInfoList, AppUser auditUser) {\n        if (appAuditId == null || appAuditId <= 0L) {\n            logger.error(\"appAuditId is null\");\n            return false;\n        }\n        if (nodeInfoList == null || nodeInfoList.isEmpty()) {\n            logger.error(\"nodeInfoList is null\");\n            return false;\n        }\n        AppAudit appAudit = appAuditDao.getAppAudit(appAuditId);\n        if (appAudit == null) {\n            logger.error(\"appAudit:id={} is not exist\", appAuditId);\n            return false;\n        }\n        long appId = appAudit.getAppId();\n        AppDesc appDesc = appService.getByAppId(appId);\n        if (appDesc == null) {\n            logger.error(\"appDesc:id={} is not exist\");\n            return false;\n        }\n        int type = appDesc.getType();\n        List<String[]> nodes = new ArrayList<String[]>();\n        for (String nodeInfo : nodeInfoList) {\n            nodeInfo = StringUtils.trim(nodeInfo);\n            if (StringUtils.isBlank(nodeInfo)) {\n                continue;\n            }\n            String[] array = nodeInfo.split(\":\");\n//            if (array.length < 2) {\n//                logger.error(\"error nodeInfo:{}\", Arrays.toString(array));\n//                continue;\n//            }\n            nodes.add(array);\n        }\n\n        boolean isAudited = false;\n        if (TypeUtil.isRedisType(type)) {\n            if (TypeUtil.isRedisCluster(type)) {\n                isAudited = deployCluster(appId, nodes);\n            } else if (nodes.size() > 0) {\n                if (TypeUtil.isRedisSentinel(type)) {\n                    isAudited = deploySentinel(appId, nodes);\n                } else {\n                    isAudited = deployStandalone(appId, nodes.get(0));\n                }\n            } else {\n                logger.error(\"nodeInfoList={} is error\", nodeInfoList);\n            }\n        } else {\n            logger.error(\"unknown type : {}\", type);\n            return false;\n        }\n\n        //审核通过\n        if (isAudited) {\n            // 改变审核状态\n            appAuditDao.updateAppAudit(appAudit.getId(), AppCheckEnum.APP_ALLOCATE_RESOURCE.value());\n        }\n\n        return true;\n    }\n\n    @Override\n    public boolean offLineApp(Long appId) {\n        Assert.isTrue(appId != null && appId > 0L);\n        AppDesc appDesc = appService.getByAppId(appId);\n        if (appDesc == null) {\n            logger.error(\"appId={} not exist\", appId);\n            return false;\n        }\n        List<InstanceInfo> instanceInfos = instanceDao.getInstListByAppId(appId);\n        int type = appDesc.getType();\n        if (instanceInfos != null) {\n            for (InstanceInfo instanceInfo : instanceInfos) {\n                final String ip = instanceInfo.getIp();\n                final int port = instanceInfo.getPort();\n                if (TypeUtil.isRedisType(type)) {\n                    //取消收集\n                    redisCenter.unDeployRedisCollection(appId, ip, port);\n                    redisCenter.unDeployRedisSlowLogCollection(appId, ip, port);\n                    boolean isShutdown = redisCenter.shutdown(appId, ip, port);\n                    if (!isShutdown) {\n                        logger.error(\"{}:{} redis not shutdown!\", ip, port);\n                        return false;\n                    }\n                }\n                //更新实例下线\n                instanceInfo.setStatus(InstanceStatusEnum.OFFLINE_STATUS.getStatus());\n                instanceDao.update(instanceInfo);\n            }\n        }\n        //更新应用信息\n        appDesc.setStatus(AppStatusEnum.STATUS_OFFLINE.getStatus());\n        appService.update(appDesc);\n        return true;\n    }\n\n    @Override\n    public boolean modifyAppConfig(Long appId, Long appAuditId, String key, String value) {\n        Assert.isTrue(appId != null && appId > 0L);\n        Assert.isTrue(appAuditId != null && appAuditId > 0L);\n        Assert.isTrue(StringUtils.isNotBlank(key));\n        Assert.isTrue(StringUtils.isNotBlank(value));\n        boolean isModify = redisDeployCenter.modifyAppConfig(appId, key, value);\n        if (isModify) {\n            // 改变审核状态\n            appAuditDao.updateAppAudit(appAuditId, AppCheckEnum.APP_ALLOCATE_RESOURCE.value());\n        }\n        return isModify;\n    }\n\n    private boolean deploySentinel(long appId, List<String[]> nodes) {\n        //数据节点\n        String[] dataNodeInfo = nodes.get(0);\n        String master = dataNodeInfo[0];\n        int memory = NumberUtils.createInteger(dataNodeInfo[1]);\n        String slave = dataNodeInfo[2];\n        // sentinel节点\n        List<String> sentinelList = new ArrayList<String>();\n        if (nodes.size() < 2) {\n            logger.error(\"sentinelList is none,don't generate sentinel app!\");\n            return false;\n        }\n\n        // sentinel节点\n        for (int i = 1; i < nodes.size(); i++) {\n            String[] nodeInfo = nodes.get(i);\n            if (nodeInfo.length == 0 || StringUtils.isBlank(nodeInfo[0])) {\n                logger.error(\"sentinel line {} may be empty\", i);\n                return false;\n            }\n            sentinelList.add(nodeInfo[0]);\n        }\n        \n        return redisDeployCenter.deploySentinelInstance(appId, master, slave, memory, sentinelList);\n    }\n\n    private boolean deployCluster(long appId, List<String[]> nodes) {\n        List<RedisClusterNode> clusterNodes = new ArrayList<RedisClusterNode>();\n        int maxMemory = 0;\n        for (String[] array : nodes) {\n            String master = array[0];\n            int memory = NumberUtils.createInteger(array[1]);\n            String slave = null;\n            if (array.length > 2) {\n                slave = array[2];\n            }\n            RedisClusterNode node = new RedisClusterNode(master, slave);\n            maxMemory = memory;\n            clusterNodes.add(node);\n        }\n        return redisDeployCenter.deployClusterInstance(appId, clusterNodes, maxMemory);\n    }\n\n    private boolean deployStandalone(long appId, String[] nodeInfo) {\n        String host = nodeInfo[0];\n        int memory = NumberUtils.createInteger(nodeInfo[1]);\n        return redisDeployCenter.deployStandaloneInstance(appId, host, memory);\n    }\n\n    @Override\n    public boolean verticalExpansion(Long appId, Long appAuditId, final int memory) {\n        Assert.isTrue(appId != null && appId > 0L);\n        Assert.isTrue(appAuditId != null && appAuditId > 0L);\n        Assert.isTrue(memory > 0);\n        AppDesc appDesc = appService.getByAppId(appId);\n        Assert.isTrue(appDesc != null);\n        int type = appDesc.getType();\n        if (!TypeUtil.isRedisType(type)) {\n            logger.error(\"appId={};type={} is not redis!\", appDesc, type);\n            return false;\n        }\n        List<InstanceInfo> instanceInfos = instanceDao.getInstListByAppId(appId);\n        if (instanceInfos == null || instanceInfos.isEmpty()) {\n            logger.error(\"instanceInfos is null\");\n            return false;\n        }\n        for (InstanceInfo instanceInfo : instanceInfos) {\n            int instanceType = instanceInfo.getType();\n            if (TypeUtil.isRedisSentinel(instanceType)) {\n                continue;\n            }\n            // 下线实例不做操作\n            if (instanceInfo.isOffline()) {\n                continue;\n            }\n            String host = instanceInfo.getIp();\n            int port = instanceInfo.getPort();\n\n            final long maxMemoryBytes = Long.valueOf(memory) * 1024 * 1024;\n            boolean isConfig = redisDeployCenter.modifyInstanceConfig(appId, host, port, \"maxmemory\", String.valueOf(maxMemoryBytes));\n            if (!isConfig) {\n                logger.error(\"{}:{} set maxMemory error\", host, port);\n                return false;\n            }\n            //更新instanceInfo配置\n            instanceInfo.setMem(memory);\n            instanceDao.update(instanceInfo);\n        }\n        // 改变审核状态\n        appAuditDao.updateAppAudit(appAuditId, AppCheckEnum.APP_ALLOCATE_RESOURCE.value());\n        return true;\n    }\n\n    @Override\n    public boolean addHorizontalNodes(Long appId, String masterHost, String slaveHost, int memory) {\n    \t\tAppDesc appDesc = appDao.getAppDescById(appId);\n        //1. 寻找主从节点的可用端口\n        Integer masterPort = machineCenter.getAvailablePort(masterHost, ConstUtils.CACHE_TYPE_REDIS_CLUSTER);\n        if (masterPort == null) {\n            logger.error(\"master host={} getAvailablePort is null\", masterHost);\n            return false;\n        }\n        Integer slavePort = 0;\n        boolean hasSlave = StringUtils.isNotBlank(slaveHost);\n        if (hasSlave) {\n            slavePort = machineCenter.getAvailablePort(slaveHost, ConstUtils.CACHE_TYPE_REDIS_CLUSTER);\n            if (slavePort == null) {\n                logger.error(\"slave host={} getAvailablePort is null\", slaveHost);\n                return false;\n            }\n        }\n\n        //2. 启动主从节点\n        boolean isMasterCreate = redisDeployCenter.createRunNode(appDesc, masterHost, masterPort, memory, true);\n        if (!isMasterCreate) {\n            logger.error(\"createRunNode master failed {}:{}\", masterHost, masterPort);\n            return false;\n        }\n        if (hasSlave) {\n            //运行节点\n            boolean isSlaveCreate = redisDeployCenter.createRunNode(appDesc, slaveHost, slavePort, memory, true);\n            if (!isSlaveCreate) {\n                logger.error(\"createRunNode slave failed {}:{}\", slaveHost, slavePort);\n                return false;\n            }\n        }\n        \n        //3. 获取应用下有效节点\n        Set<HostAndPort> clusterHosts = getEffectiveInstanceList(appId);\n        \n        \n        //4. 添加新节点: meet,复制，不做slot分配\n        RedisClusterReshard clusterReshard = new RedisClusterReshard(clusterHosts, redisCenter, instanceReshardProcessDao);\n        boolean joinCluster = clusterReshard.joinCluster(appId, masterHost, masterPort, slaveHost, slavePort);\n        if (joinCluster) {\n            //5. 保存实例,开启统计功能\n            saveInstance(appId, masterHost, masterPort, memory);\n            redisCenter.deployRedisCollection(appId, masterHost, masterPort);\n            if (hasSlave) {\n                saveInstance(appId, slaveHost, slavePort, memory);\n                redisCenter.deployRedisCollection(appId, slaveHost, slavePort);\n            }\n        }\n        return joinCluster;\n    }\n\n    @Override\n    public boolean cleanAppData(long appId, AppUser appUser) {\n        try {\n            AppDesc appDesc = appDao.getAppDescById(appId);\n            if (appDesc == null) {\n                return false;\n            }\n            if (TypeUtil.isRedisType(appDesc.getType())) {\n                return redisCenter.cleanAppData(appDesc, appUser);\n            } else {\n                return false;\n            }\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return false;\n        }\n    }\n\n    /**\n     * @param appId\n     * @param appAuditId\n     * @param startSlot\n     * @param endSlot\n     * @return\n     */\n    private boolean isInProcess(Long appId, long appAuditId, int startSlot, int endSlot) {\n        return false;\n    }\n\n\n    private InstanceInfo saveInstance(long appId, String host, int port, int maxMemory) {\n        InstanceInfo instanceInfo = new InstanceInfo();\n        instanceInfo.setAppId(appId);\n        MachineInfo machineInfo = machineCenter.getMachineInfoByIp(host);\n        instanceInfo.setHostId(machineInfo.getId());\n        instanceInfo.setConn(0);\n        instanceInfo.setMem(maxMemory);\n        instanceInfo.setStatus(InstanceStatusEnum.GOOD_STATUS.getStatus());\n        instanceInfo.setPort(port);\n        instanceInfo.setType(ConstUtils.CACHE_TYPE_REDIS_CLUSTER);\n        instanceInfo.setCmd(\"\");\n        instanceInfo.setIp(host);\n        instanceDao.saveInstance(instanceInfo);\n        return instanceInfo;\n    }\n    \n    @Override\n\tpublic HorizontalResult checkHorizontal(long appId, long appAuditId, long sourceId, long targetId, int startSlot,\n\t\t\tint endSlot, int migrateType) {\n        boolean isInProcess = isInProcess(appId, appAuditId, startSlot, endSlot);\n    \t    if (isInProcess) {\n\t\t\treturn HorizontalResult.fail(String.format(\"appId=%s %s:%s正在迁移!\", appId, startSlot, endSlot));\n    \t    }\n\t\t// 1.应用信息\n\t\tAppDesc appDesc = appService.getByAppId(appId);\n\t\tif (appDesc == null) {\n\t\t\treturn HorizontalResult.fail(\"应用信息为空\");\n\t\t}\n\t\t\n\t\t// 2.0 源实例ID不能等于目标实例ID\n\t\tif (sourceId == targetId) {\n            return HorizontalResult.fail(String.format(\"源实例ID=%s不能等于目标实例ID=%s\", sourceId, targetId));\n\t\t}\n\t\t\n\t\t// 2.1 源实例信息\n\t\tInstanceInfo sourceInstanceInfo = instanceDao.getInstanceInfoById(sourceId);\n\t\tif (sourceInstanceInfo == null) {\n\t\t\treturn HorizontalResult.fail(String.format(\"源实例id=%s为空\", sourceId));\n\t\t}\n\t\t// 2.2 对比源实例的appId是否正确\n\t\tlong sourceAppId = sourceInstanceInfo.getAppId();\n\t\tif (sourceAppId != appId) {\n\t\t\treturn HorizontalResult.fail(String.format(\"源实例id=%s不属于appId=%s\", sourceId, appId));\n\t\t}\n\t\t// 2.3 源实例是否在线\n\t\tboolean sourceIsRun = redisCenter.isRun(appId, sourceInstanceInfo.getIp(), sourceInstanceInfo.getPort());\n\t\tif (!sourceIsRun) {\n\t\t\treturn HorizontalResult.fail(String.format(\"源实例%s必须运行中\", sourceInstanceInfo.getHostPort()));\n\t\t}\n\t\t// 2.4必须是master节点\n\t\tboolean sourceIsMaster = redisCenter.isMaster(appId, sourceInstanceInfo.getIp(), sourceInstanceInfo.getPort());\n\t\tif (!sourceIsMaster) {\n\t\t\treturn HorizontalResult.fail(String.format(\"源实例%s必须是主节点\", sourceInstanceInfo.getHostPort()));\n\t\t}\n\t\t\n\n\t\t// 3.1 目标实例信息\n\t\tInstanceInfo targetInstanceInfo = instanceDao.getInstanceInfoById(targetId);\n\t\tif (targetInstanceInfo == null) {\n\t\t\treturn HorizontalResult.fail(String.format(\"目标实例id=%s为空\", targetId));\n\t\t}\n\t\t// 3.2 对比目标实例的appId是否正确\n\t\tlong targetAppId = targetInstanceInfo.getAppId();\n\t\tif (targetAppId != appId) {\n\t\t\treturn HorizontalResult.fail(String.format(\"目标实例id=%s不属于appId=%s\", targetId, appId));\n\t\t}\n\t\t// 3.3 目标实例是否在线\n\t\tboolean targetIsRun = redisCenter.isRun(appId, targetInstanceInfo.getIp(), targetInstanceInfo.getPort());\n\t\tif (!targetIsRun) {\n\t\t\treturn HorizontalResult.fail(String.format(\"目标实例%s必须运行中\", targetInstanceInfo.getHostPort()));\n\t\t}\n\t\t// 3.4 必须是master节点\n\t\tboolean targetIsMaster = redisCenter.isMaster(appId, targetInstanceInfo.getIp(), targetInstanceInfo.getPort());\n\t\tif (!targetIsMaster) {\n\t\t\treturn HorizontalResult.fail(String.format(\"目标实例%s必须是主节点\", targetInstanceInfo.getHostPort()));\n\t\t}\n\t\t\n\t\t// 4.startSlot和endSlot是否在源实例中\n\t\t// 4.1 判断数值\n\t\tint maxSlot = 16383;\n\t\tif (startSlot < 0 || startSlot > maxSlot) {\n\t\t\treturn HorizontalResult.fail(String.format(\"startSlot=%s必须在0-%s\", startSlot, maxSlot));\n\t\t}\n\t\tif (endSlot < 0 || endSlot > maxSlot) {\n\t\t\treturn HorizontalResult.fail(String.format(\"endSlot=%s必须在0-%s\", endSlot, maxSlot));\n\t\t}\n\t\tif (startSlot > endSlot) {\n\t\t\treturn HorizontalResult.fail(\"startSlot不能大于endSlot\");\n\t\t}\n\t\t\n\t\t// 4.2 判断startSlot和endSlot属于sourceId\n\t\t// 获取所有slot分布\n\t\tMap<String, InstanceSlotModel> clusterSlotsMap = redisCenter.getClusterSlotsMap(appId);\n\t\tif (MapUtils.isEmpty(clusterSlotsMap)) {\n\t\t\treturn HorizontalResult.fail(\"无法获取slot分布!\");\n\t\t}\n\t\t// 获取源实例负责的slot\n\t\tString sourceHostPort = sourceInstanceInfo.getHostPort();\n\t\tInstanceSlotModel instanceSlotModel = clusterSlotsMap.get(sourceHostPort);\n\t\tif (instanceSlotModel == null || CollectionUtils.isEmpty(instanceSlotModel.getSlotList())) {\n\t\t\treturn HorizontalResult.fail(\"源实例上没有slot!\");\n\t\t}\n\t\tList<Integer> slotList = instanceSlotModel.getSlotList();\n\t\tfor (int i = startSlot; i <= endSlot; i++) {\n\t\t\tif (!slotList.contains(i)) {\n\t\t\t\treturn HorizontalResult.fail(String.format(\"源实例没有包含尽startSlot=%s到endSlot=%s\", startSlot, endSlot));\n\t\t\t}\n\t\t}\n\t\t\n\t\t//5.是否支持批量，版本要大于等于3.0.6\n\t\tString sourceRedisVersion = redisCenter.getRedisVersion(sourceAppId, sourceInstanceInfo.getIp(), sourceInstanceInfo.getPort());\n\t\tif (StringUtils.isBlank(sourceRedisVersion)) {\n            return HorizontalResult.fail(String.format(\"源实例%s版本为空\", sourceInstanceInfo.getHostPort()));\n\t\t}\n\t    String targetRedisVersion = redisCenter.getRedisVersion(targetAppId, targetInstanceInfo.getIp(), targetInstanceInfo.getPort());\n\t    if (StringUtils.isBlank(targetRedisVersion)) {\n            return HorizontalResult.fail(String.format(\"目标实例%s版本为空\", targetInstanceInfo.getHostPort()));\n        }\n\t    RedisVersion sourceRedisVersionModel = getRedisVersion(sourceRedisVersion);\n\t    //选择了批量，但是当前版本不支持pipeline\n\t    if (migrateType == 1 && !sourceRedisVersionModel.isSupportPipelineMigrate()) {\n            return HorizontalResult.fail(String.format(\"源实例%s版本为%s,不支持pipeline migrate!\", sourceInstanceInfo.getHostPort(), sourceRedisVersion));\n\t    }\n\t    \n\t    RedisVersion targetRedisVersionModel = getRedisVersion(targetRedisVersion);\n\t    //选择了批量，但是当前版本不支持pipeline\n        if (migrateType == 1 && !targetRedisVersionModel.isSupportPipelineMigrate()) {\n            return HorizontalResult.fail(String.format(\"目标实例%s版本为%s,不支持pipeline migrate!\", targetInstanceInfo.getHostPort(), targetRedisVersion));\n        }\n\t\t\n\t\treturn HorizontalResult.checkSuccess();\n\t}\n\n    private RedisVersion getRedisVersion(String redisVersion) {\n        String[] versionArr = redisVersion.split(\"\\\\.\");\n        if (versionArr.length == 1) {\n            return new RedisVersion(NumberUtils.toInt(versionArr[0]), 0, 0);\n        } else if (versionArr.length == 2) {\n            return new RedisVersion(NumberUtils.toInt(versionArr[0]), NumberUtils.toInt(versionArr[1]), 0);\n        } else if (versionArr.length >= 3) {\n            return new RedisVersion(NumberUtils.toInt(versionArr[0]), NumberUtils.toInt(versionArr[1]),\n                    NumberUtils.toInt(versionArr[2]));\n        }\n        return null;\n    }\n\t\n\tprivate class RedisVersion {\n\t    int majorVersion;\n\t    int minorVersion;\n\t    int patchVersion;\n        public RedisVersion(int majorVersion, int minorVersion, int patchVersion) {\n            super();\n            this.majorVersion = majorVersion;\n            this.minorVersion = minorVersion;\n            this.patchVersion = patchVersion;\n        }\n        \n        /**\n         * 大于等于3.0.6\n         * @return\n         */\n        public boolean isSupportPipelineMigrate() {\n            if (majorVersion < 3) {\n                return false;\n            } else if (majorVersion == 3) {\n                if (minorVersion > 0) {\n                    return true;\n                } else {\n                    return patchVersion >= 6;\n                }\n            } else {\n                return true;\n            }\n        }\n\n        @Override\n        public String toString() {\n            return \"RedisVersion [majorVersion=\" + majorVersion + \", minorVersion=\" + minorVersion + \", patchVersion=\"\n                    + patchVersion + \"]\";\n        }\n\t}\n\t\n\t/**\n\t * 获取应用下有效节点\n\t * @param appId\n\t * @return\n\t */\n\tprivate Set<HostAndPort> getEffectiveInstanceList(long appId) {\n\t    Set<HostAndPort> clusterHosts = new HashSet<HostAndPort>();\n\t    //全部节点\n        List<InstanceInfo> instanceInfos = instanceDao.getInstListByAppId(appId);\n        for (InstanceInfo instance : instanceInfos) {\n            if (instance.isOffline()) {\n                continue;\n            }\n            clusterHosts.add(new HostAndPort(instance.getIp(), instance.getPort()));\n        }\n        return clusterHosts;\n\t}\n\n    @Override\n\tpublic HorizontalResult startHorizontal(final long appId, final long appAuditId, long sourceId, final long targetId, final int startSlot,\n            final int endSlot, final int migrateType) {\n\t\tInstanceInfo sourceInstanceInfo = instanceDao.getInstanceInfoById(sourceId);\n\t    InstanceInfo targetInstanceInfo = instanceDao.getInstanceInfoById(targetId);\n\t    InstanceReshardProcess instanceReshardProcess = saveInstanceReshardProcess(appId, appAuditId, sourceInstanceInfo, targetInstanceInfo, startSlot, endSlot, PipelineEnum.getPipelineEnum(migrateType));\n\t    instanceReshardProcess.setSourceInstanceInfo(sourceInstanceInfo);\n\t    instanceReshardProcess.setTargetInstanceInfo(targetInstanceInfo);\n\t    startMigrateSlot(instanceReshardProcess);\n        logger.warn(\"start reshard appId={} instance={}:{} deploy done\", instanceReshardProcess.getAppId(), targetInstanceInfo.getIp(), targetInstanceInfo.getPort());\n\t\treturn HorizontalResult.scaleSuccess();\n\t}\n    \n    @Override\n    public HorizontalResult retryHorizontal(final int instanceReshardProcessId) {\n        InstanceReshardProcess instanceReshardProcess = instanceReshardProcessDao.get(instanceReshardProcessId);\n        instanceReshardProcess.setStatus(ReshardStatusEnum.RUNNING.getValue());\n        instanceReshardProcessDao.updateStatus(instanceReshardProcess.getId(), ReshardStatusEnum.RUNNING.getValue());\n        InstanceInfo sourceInstanceInfo = instanceDao.getInstanceInfoById(instanceReshardProcess.getSourceInstanceId());\n        InstanceInfo targetInstanceInfo = instanceDao.getInstanceInfoById(instanceReshardProcess.getTargetInstanceId());\n        instanceReshardProcess.setSourceInstanceInfo(sourceInstanceInfo);\n        instanceReshardProcess.setTargetInstanceInfo(targetInstanceInfo);\n        startMigrateSlot(instanceReshardProcess);\n        logger.warn(\"retry reshard appId={} instance={}:{} deploy done\", instanceReshardProcess.getAppId(), targetInstanceInfo.getIp(), targetInstanceInfo.getPort());\n        return HorizontalResult.scaleSuccess();\n    }\n    \n    private void startMigrateSlot(final InstanceReshardProcess instanceReshardProcess) {\n        final long appId = instanceReshardProcess.getAppId();\n        final long appAuditId = instanceReshardProcess.getAuditId();\n        final InstanceInfo targetInstanceInfo = instanceReshardProcess.getTargetInstanceInfo();\n        processThreadPool.execute(new Runnable() {\n            @Override\n            public void run() {\n                //所有节点用户clustersetslot\n                Set<HostAndPort> clusterHosts = getEffectiveInstanceList(appId);\n                RedisClusterReshard clusterReshard = new RedisClusterReshard(clusterHosts, redisCenter, instanceReshardProcessDao);\n                //添加进度\n                boolean joinCluster = clusterReshard.migrateSlot(instanceReshardProcess);\n                if (joinCluster) {\n                    // 改变审核状态\n                    appAuditDao.updateAppAudit(appAuditId, AppCheckEnum.APP_ALLOCATE_RESOURCE.value());\n                    if (targetInstanceInfo != null && targetInstanceInfo.getStatus() != InstanceStatusEnum.GOOD_STATUS.getStatus()) {\n                        targetInstanceInfo.setStatus(InstanceStatusEnum.GOOD_STATUS.getStatus());\n                        instanceDao.update(targetInstanceInfo);\n                    }\n                }\n            }\n        });\n    }\n\n    /**\n     * 保存进度\n     * @param appId\n     * @param appAuditId\n     * @param sourceInstanceInfo\n     * @param targetInstanceInfo\n     * @param startSlot\n     * @param endSlot\n     * @return\n     */\n    private InstanceReshardProcess saveInstanceReshardProcess(long appId, long appAuditId,\n            InstanceInfo sourceInstanceInfo, InstanceInfo targetInstanceInfo, int startSlot, int endSlot, PipelineEnum pipelineEnum) {\n        Date now = new Date();\n        InstanceReshardProcess instanceReshardProcess = new InstanceReshardProcess();\n        instanceReshardProcess.setAppId(appId);\n        instanceReshardProcess.setAuditId(appAuditId);\n        instanceReshardProcess.setFinishSlotNum(0);\n        instanceReshardProcess.setIsPipeline(pipelineEnum.getValue());\n        instanceReshardProcess.setSourceInstanceId(sourceInstanceInfo.getId());\n        instanceReshardProcess.setTargetInstanceId(targetInstanceInfo.getId());\n        instanceReshardProcess.setMigratingSlot(startSlot);\n        instanceReshardProcess.setStartSlot(startSlot);\n        instanceReshardProcess.setEndSlot(endSlot);\n        instanceReshardProcess.setStatus(ReshardStatusEnum.RUNNING.getValue());\n        instanceReshardProcess.setStartTime(now);\n        //用status控制显示结束时间\n        instanceReshardProcess.setEndTime(now);\n        instanceReshardProcess.setCreateTime(now);\n        instanceReshardProcess.setUpdateTime(now);\n        \n        instanceReshardProcessDao.save(instanceReshardProcess);\n        return instanceReshardProcess;\n    }\n    \n    @Override\n    public DataFormatCheckResult checkHorizontalNodes(Long appAuditId, String masterSizeSlave) {\n        if (appAuditId == null) {\n            logger.error(\"appAuditId is null\");\n            return DataFormatCheckResult.fail(\"审核id不能为空!\");\n        }\n        if (StringUtils.isBlank(masterSizeSlave)) {\n            logger.error(\"masterSizeSlave is null\");\n            return DataFormatCheckResult.fail(\"添加节点不能为空!\");\n        }\n        AppAudit appAudit = appAuditDao.getAppAudit(appAuditId);\n        if (appAudit == null) {\n            logger.error(\"appAudit:id={} is not exist\", appAuditId);\n            return DataFormatCheckResult.fail(String.format(\"审核id=%s不存在\", appAuditId));\n        }\n        long appId = appAudit.getAppId();\n        AppDesc appDesc = appService.getByAppId(appId);\n        if (appDesc == null) {\n            logger.error(\"appDesc:id={} is not exist\");\n            return DataFormatCheckResult.fail(String.format(\"appId=%s不存在\", appId));\n        }\n        //节点数组 master:memSize:slave\n        String[] array = masterSizeSlave.split(ConstUtils.COLON);\n        if (array == null || array.length == 0) {\n            return DataFormatCheckResult.fail(String.format(\"添加节点%s格式错误\", masterSizeSlave));\n        }\n        //检查格式\n        String masterHost = null;\n        String memSize = null;\n        String slaveHost = null;\n        if (array.length == 2) {\n            masterHost = array[0];\n            memSize = array[1];\n        } else if (array.length == 3) {\n            masterHost = array[0];\n            memSize = array[1];\n            slaveHost = array[2];\n        } else {\n            return DataFormatCheckResult.fail(String.format(\"添加节点%s, 格式错误!\", masterSizeSlave));\n        }\n        //检查主节点机器是否存在\n        if (!checkHostExist(masterHost)) {\n            return DataFormatCheckResult.fail(String.format(\"%s中的ip=%s不存在，请在机器管理中添加!\", masterSizeSlave, masterHost));\n        }\n        //检查memSize格式\n        if (StringUtils.isNotBlank(memSize) && !NumberUtils.isDigits(memSize)) {\n            return DataFormatCheckResult.fail(String.format(\"%s中的中的memSize=%s不是整数!\", masterSizeSlave, memSize));\n        }\n        //检查从节点格式\n        if (StringUtils.isNotBlank(slaveHost) && !checkHostExist(slaveHost)) {\n            return DataFormatCheckResult.fail(String.format(\"%s中的ip=%s不存在，请在机器管理中添加!\", masterSizeSlave, slaveHost));\n        }\n        return DataFormatCheckResult.success(\"添加节点格式正确，可以开始部署了!\");\n    }\n    \n    @Override\n    public List<InstanceReshardProcess> getHorizontalProcess(long auditId) {\n        try {\n            return instanceReshardProcessDao.getByAuditId(auditId);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return Collections.emptyList();\n        }\n    }\n    \n    \n    public void setAppService(AppService appService) {\n        this.appService = appService;\n    }\n\n    public void setRedisDeployCenter(RedisDeployCenter redisDeployCenter) {\n        this.redisDeployCenter = redisDeployCenter;\n    }\n\n    public void setAppEmailUtil(AppEmailUtil appEmailUtil) {\n        this.appEmailUtil = appEmailUtil;\n    }\n\n    public void setAppAuditDao(AppAuditDao appAuditDao) {\n        this.appAuditDao = appAuditDao;\n    }\n\n    public void setInstanceDao(InstanceDao instanceDao) {\n        this.instanceDao = instanceDao;\n    }\n\n    public void setRedisCenter(RedisCenter redisCenter) {\n        this.redisCenter = redisCenter;\n    }\n\n    public void setMachineCenter(MachineCenter machineCenter) {\n        this.machineCenter = machineCenter;\n    }\n\n    public void setAppAuditLogDao(AppAuditLogDao appAuditLogDao) {\n        this.appAuditLogDao = appAuditLogDao;\n    }\n\n    public void setAppDao(AppDao appDao) {\n        this.appDao = appDao;\n    }\n\n    public void setInstanceReshardProcessDao(InstanceReshardProcessDao instanceReshardProcessDao) {\n        this.instanceReshardProcessDao = instanceReshardProcessDao;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/stats/app/impl/AppStatsCenterImpl.java",
    "content": "package com.sohu.cache.stats.app.impl;\n\nimport com.sohu.cache.constant.AppTopology;\nimport com.sohu.cache.constant.TimeDimensionalityEnum;\nimport com.sohu.cache.dao.AppDao;\nimport com.sohu.cache.dao.AppStatsDao;\nimport com.sohu.cache.dao.InstanceDao;\nimport com.sohu.cache.dao.InstanceStatsDao;\nimport com.sohu.cache.entity.*;\nimport com.sohu.cache.redis.RedisCenter;\nimport com.sohu.cache.stats.app.AppStatsCenter;\nimport com.sohu.cache.util.ConstUtils;\nimport com.sohu.cache.util.TypeUtil;\nimport com.sohu.cache.web.vo.AppDetailVO;\nimport com.sohu.cache.web.service.UserService;\n\nimport org.apache.commons.lang.StringUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.util.Assert;\n\nimport java.text.DecimalFormat;\nimport java.util.*;\n\n/**\n * 基于app的统计信息的接口：包括app详情、app配置以及基于app的统计\n * @author leifu\n * @Date 2015年3月2日\n * @Time 下午1:50:09\n */\npublic class AppStatsCenterImpl implements AppStatsCenter {\n    \n    private final Logger logger = LoggerFactory.getLogger(this.getClass());\n\n    private AppDao appDao;\n    \n    private InstanceDao instanceDao;\n\n    private AppStatsDao appStatsDao;\n\n    private InstanceStatsDao instanceStatsDao;\n\n    private RedisCenter redisCenter;\n\n    private UserService userService;\n    \n    private final static String COLLECT_DATE_FORMAT = \"yyyyMMddHHmm\";\n\n    \n    @Override\n    public List<AppStats> getAppStatsListByMinuteTime(long appId, long beginTime, long endTime) {\n        Assert.isTrue(appId > 0);\n        Assert.isTrue(beginTime > 0 && endTime > 0);\n\n        List<AppStats> appStatsList = null;\n        try {\n            appStatsList = appStatsDao.getAppStatsList(appId, new TimeDimensionality(beginTime, endTime, COLLECT_DATE_FORMAT));\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n        return appStatsList;\n    }\n\n    /**\n     * 通过时间区间查询app的分钟统计数据\n     *\n     * @param appId\n     * @param beginTime 时间，格式：yyyyMMddHHmm\n     * @param endTime   时间，格式：yyyyMMddHHmm\n     * @return\n     */\n    @Override\n    public List<AppStats> getAppStatsList(final long appId, long beginTime, long endTime, TimeDimensionalityEnum timeDimensionalityEnum) {\n        Assert.isTrue(appId > 0);\n        Assert.isTrue(beginTime > 0 && endTime > 0);\n\n        List<AppStats> appStatsList = null;\n        try {\n            if (TimeDimensionalityEnum.MINUTE.equals(timeDimensionalityEnum)) {\n                appStatsList = appStatsDao.getAppStatsByMinute(appId, beginTime, endTime);\n            } else if(TimeDimensionalityEnum.HOUR.equals(timeDimensionalityEnum)) {\n                appStatsList = appStatsDao.getAppStatsByHour(appId, beginTime, endTime);\n            }\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n        return appStatsList;\n    }\n\n    @Override\n    public List<AppCommandStats> getTop5AppCommandStatsList(final long appId, long begin, long end) {\n        Assert.isTrue(appId > 0);\n        Assert.isTrue(begin > 0L);\n        Assert.isTrue(end > 0L);\n\n        List<AppCommandStats> topAppCmdList = null;\n        try {\n            topAppCmdList = appStatsDao.getTopAppCommandGroupSum(appId, new TimeDimensionality(begin, end, COLLECT_DATE_FORMAT), 5);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n        return topAppCmdList;\n    }\n\n    @Override\n    public List<AppCommandStats> getTopLimitAppCommandStatsList(long appId, long begin, long end, int limit) {\n        Assert.isTrue(appId > 0);\n        Assert.isTrue(begin > 0L);\n        Assert.isTrue(end > 0L);\n\n        List<AppCommandStats> topAppCmdList = null;\n        try {\n            topAppCmdList = appStatsDao.getTopAppCommandStatsList(appId, new TimeDimensionality(begin, end, COLLECT_DATE_FORMAT), limit);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n        return topAppCmdList;\n    }\n\n    /**\n     * 查询应用的配置和节点信息\n     *\n     * @param appId\n     * @return\n     */\n    @Override\n    public Map<AppTopology, Object> queryAppTopology(final long appId) {\n        Assert.isTrue(appId > 0);\n\n        Map<AppTopology, Object> appTopologyMap = new HashMap<AppTopology, Object>();\n        AppDesc appDesc = null;\n        double totalMemory = 0.0;\n        Set<Long> machineSet = new HashSet<Long>();\n        int masterCount = 0;\n        int slaveCount = 0;\n\n        List<InstanceInfo> instanceInfoList = null;\n        try {\n            appDesc = appDao.getAppDescById(appId);\n            instanceInfoList = instanceDao.getInstListByAppId(appId);\n            if (appDesc == null || instanceInfoList == null || instanceInfoList.isEmpty()) {\n                logger.error(\"get app and it's instances error， appId = {}\", appId);\n                return null;\n            }\n            if (appDesc.getType() == ConstUtils.CACHE_TYPE_REDIS_CLUSTER) {\n                for (InstanceInfo instance : instanceInfoList) {\n                    machineSet.add(instance.getHostId());\n                    totalMemory += instance.getMem();\n                    Boolean isMaster = redisCenter.isMaster(appId, instance.getIp(), instance.getPort());\n                    if (isMaster == null) {\n                        continue;\n                    }\n                    if (isMaster) {\n                        masterCount++;\n                    } else {\n                        slaveCount++;\n                    }\n                }\n            }\n            appTopologyMap.put(AppTopology.TOTAL_MEMORY, totalMemory / ConstUtils._1024);\n            appTopologyMap.put(AppTopology.MACHINE_COUNT, machineSet.size());\n            appTopologyMap.put(AppTopology.MASTER_COUNT, masterCount);\n            appTopologyMap.put(AppTopology.SLAVE_COUNT, slaveCount);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n\n        return appTopologyMap;\n    }\n\n    /**\n     * 查询应用指定时间段，指定命令名的结果集合\n     *\n     * @param appId       应用id\n     * @param beginTime   时间，格式：yyyyMMddHHmm\n     * @param endTime     时间，格式：yyyyMMddHHmm\n     * @param commandName 命令名\n     * @return\n     */\n    @Override\n    public List<AppCommandStats> getCommandStatsList(long appId, long beginTime, long endTime, String commandName) {\n        return appStatsDao.getAppCommandStatsList(appId, commandName, new TimeDimensionality(beginTime, endTime, COLLECT_DATE_FORMAT));\n    }\n\n    /**\n     * 查询应用指定时间段，指定命令名的结果集合\n     *\n     * @param appId     应用id\n     * @param beginTime 时间，格式：yyyyMMddHHmm\n     * @param endTime   时间，格式：yyyyMMddHHmm\n     * @return\n     */\n    @Override\n    public List<AppCommandStats> getCommandStatsList(long appId, long beginTime, long endTime) {\n        return appStatsDao.getAppAllCommandStatsList(appId, new TimeDimensionality(beginTime, endTime, COLLECT_DATE_FORMAT));\n    }\n    \n    @Override\n    public List<AppCommandStats> getCommandStatsListV2(long appId, long beginTime, long endTime, TimeDimensionalityEnum timeDimensionalityEnum, String commandName) {\n        if (TimeDimensionalityEnum.MINUTE.equals(timeDimensionalityEnum)) {\n            return appStatsDao.getAppCommandStatsListByMinuteWithCommand(appId, beginTime, endTime, commandName);\n        } else if(TimeDimensionalityEnum.HOUR.equals(timeDimensionalityEnum)) {\n            return appStatsDao.getAppCommandStatsListByHourWithCommand(appId, beginTime, endTime, commandName);\n        }\n        return Collections.emptyList();\n    }\n\n    @Override\n    public List<AppCommandStats> getCommandStatsListV2(long appId, long beginTime, long endTime, TimeDimensionalityEnum timeDimensionalityEnum) {\n        if (TimeDimensionalityEnum.MINUTE.equals(timeDimensionalityEnum)) {\n            return appStatsDao.getAppAllCommandStatsListByMinute(appId, beginTime, endTime);\n        } else if(TimeDimensionalityEnum.HOUR.equals(timeDimensionalityEnum)) {\n            return appStatsDao.getAppAllCommandStatsListByHour(appId, beginTime, endTime);\n        }\n        return Collections.emptyList();\n    }\n    \n\n    /**\n     * 查询应用指定命令的峰值\n     *\n     * @param appId       应用id\n     * @param beginTime   时间，格式：yyyyMMddHHmm\n     * @param endTime     时间，格式：yyyyMMddHHmm\n     * @param commandName 命令名\n     * @return\n     */\n    @Override\n    public AppCommandStats getCommandClimax(long appId, Long beginTime, Long endTime, String commandName) {\n        TimeDimensionality td = new TimeDimensionality(beginTime, endTime, COLLECT_DATE_FORMAT);\n        AppCommandStats appCommandStats = appStatsDao.getCommandClimaxCount(appId, commandName, td);\n        if (appCommandStats == null) {\n            return null;\n        }\n        appCommandStats.setCommandName(commandName);\n        AppCommandStats appCommandStatsTemp = appStatsDao.getCommandClimaxCreateTime(appId, commandName, appCommandStats.getCommandCount(), td);\n        if (appCommandStatsTemp != null) {\n            appCommandStats.setCreateTime(appCommandStatsTemp.getCreateTime());\n        }\n        return appCommandStats;\n    }\n\n    /**\n     * 获取应用命令调用次数分布\n     *\n     * @param appId\n     * @param beginTime\n     * @param endTime\n     * @return\n     */\n    @Override\n    public List<AppCommandGroup> getAppCommandGroup(long appId, Long beginTime, Long endTime) {\n        return appStatsDao.getAppCommandGroup(appId, new TimeDimensionality(beginTime, endTime, COLLECT_DATE_FORMAT));\n    }\n\n    /**\n     * 获取应用详细信息\n     */\n    @Override\n    public AppDetailVO getAppDetail(long appId) {\n        AppDesc appDesc = appDao.getAppDescById(appId);\n        if (appDesc == null) {\n            return null;\n        }\n        AppDetailVO resultVO = new AppDetailVO();\n        resultVO.setAppDesc(appDesc);\n        Set<String> machines = new HashSet<String>();\n        List<InstanceInfo> instanceList = instanceDao.getInstListByAppId(appId);\n\n        if (instanceList == null || instanceList.isEmpty()) {\n            return resultVO;\n        }\n        long hits = 0L;\n        long miss = 0L;\n        long allUsedMemory = 0L;\n        long allMaxMemory = 0L;\n        List<InstanceStats> instanceStatsList = instanceStatsDao.getInstanceStatsByAppId(appId);\n        if(instanceStatsList != null && instanceStatsList.size() > 0){\n            Map<Long, InstanceStats> instanceStatMap = new HashMap<Long, InstanceStats>();\n            for (InstanceStats stats : instanceStatsList) {\n                instanceStatMap.put(stats.getInstId(), stats);\n            }\n\n            for (InstanceInfo instanceInfo : instanceList) {\n                if (instanceInfo.isOffline()) {\n                    continue;\n                }\n                machines.add(instanceInfo.getIp());\n                InstanceStats instanceStats = instanceStatMap.get(Long.valueOf(instanceInfo.getId()));\n                if (instanceStats == null) {\n                    continue;\n                }\n                boolean isMaster = isMaster(instanceStats);\n\n                long usedMemory = instanceStats.getUsedMemory();\n                long usedMemoryMB = usedMemory / 1024 / 1024;\n\n                allUsedMemory += usedMemory;\n                allMaxMemory += instanceStats.getMaxMemory();\n\n                hits += instanceStats.getHits();\n                miss += instanceStats.getMisses();\n                if (isMaster) {\n                    resultVO.setMem(resultVO.getMem() + instanceInfo.getMem());\n                    resultVO.setCurrentMem(resultVO.getCurrentMem() + usedMemoryMB);\n                    resultVO.setCurrentObjNum(resultVO.getCurrentObjNum() + instanceStats.getCurrItems());\n                    resultVO.setMasterNum(resultVO.getMasterNum() + 1);\n                    //按instanceStats计算conn\n                    resultVO.setConn(resultVO.getConn() + instanceStats.getCurrConnections());\n                } else {\n                    resultVO.setSlaveNum(resultVO.getSlaveNum() + 1);\n                }\n            }\n        }\n\n        List<AppUser> userList = userService.getByAppId(appId);\n        if (userList != null && userList.size() > 0) {\n            resultVO.setAppUsers(userList);\n        }\n        resultVO.setMachineNum(machines.size());\n        if (allMaxMemory == 0L) {\n            resultVO.setMemUsePercent(0.0D);\n        } else {\n            double percent = 100 * (double) allUsedMemory / (allMaxMemory);\n            DecimalFormat df = new DecimalFormat(\"##.##\");\n            resultVO.setMemUsePercent(Double.parseDouble(df.format(percent)));\n        }\n\n        if (miss == 0L) {\n            if (hits > 0) {\n                resultVO.setHitPercent(100.0D);\n            } else {\n                resultVO.setHitPercent(0.0D);\n            }\n        } else {\n            double percent = 100 * (double) hits / (hits + miss);\n            DecimalFormat df = new DecimalFormat(\"##.##\");\n            resultVO.setHitPercent(Double.parseDouble(df.format(percent)));\n        }\n\n        return resultVO;\n    }\n\n    private boolean isMaster(InstanceStats instanceStats) {\n        return instanceStats.getRole() == 1 ? true : false;\n    }\n\n    @Override\n    public String executeCommand(long appId, String command) {\n        if (StringUtils.isBlank(command)) {\n            return \"命令不能为空\";\n        }\n        AppDesc appDesc = appDao.getAppDescById(appId);\n        if (appDesc == null) {\n            return \"app not found\";\n        }\n        if (TypeUtil.isRedisType(appDesc.getType())) {\n            return redisCenter.executeCommand(appDesc, command);\n        }\n        return \"not support app\";\n    }\n    \n    @Override\n    public Map<String, Long> getInstanceSlowLogCountMapByAppId(Long appId, Date startDate, Date endDate) {\n        AppDesc appDesc = appDao.getAppDescById(appId);\n        if (appDesc == null) {\n            return Collections.emptyMap();\n        }\n        if (TypeUtil.isRedisType(appDesc.getType())) {\n            return redisCenter.getInstanceSlowLogCountMapByAppId(appId, startDate, endDate);\n        }\n        return Collections.emptyMap();\n    }\n    \n    @Override\n    public List<InstanceSlowLog> getInstanceSlowLogByAppId(long appId, Date startDate, Date endDate) {\n        AppDesc appDesc = appDao.getAppDescById(appId);\n        if (appDesc == null) {\n            return Collections.emptyList();\n        }\n        if (TypeUtil.isRedisType(appDesc.getType())) {\n            return redisCenter.getInstanceSlowLogByAppId(appId, startDate, endDate);\n        }\n        return Collections.emptyList();\n    }\n\n    public void setAppDao(AppDao appDao) {\n        this.appDao = appDao;\n    }\n\n    public void setAppStatsDao(AppStatsDao appStatsDao) {\n        this.appStatsDao = appStatsDao;\n    }\n\n    public void setInstanceDao(InstanceDao instanceDao) {\n        this.instanceDao = instanceDao;\n    }\n\n    public void setRedisCenter(RedisCenter redisCenter) {\n        this.redisCenter = redisCenter;\n    }\n\n    public void setInstanceStatsDao(InstanceStatsDao instanceStatsDao) {\n        this.instanceStatsDao = instanceStatsDao;\n    }\n\n    public void setUserService(UserService userService) {\n        this.userService = userService;\n    }\n\n\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/stats/app/impl/ImportAppCenterImpl.java",
    "content": "package com.sohu.cache.stats.app.impl;\n\nimport java.util.List;\nimport java.util.Map;\n\nimport org.apache.commons.collections.MapUtils;\nimport org.apache.commons.lang.StringUtils;\nimport org.apache.commons.lang.math.NumberUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport redis.clients.jedis.Jedis;\nimport redis.clients.jedis.Protocol;\n\nimport com.sohu.cache.constant.ImportAppResult;\nimport com.sohu.cache.constant.InstanceStatusEnum;\nimport com.sohu.cache.dao.InstanceDao;\nimport com.sohu.cache.dao.InstanceStatsDao;\nimport com.sohu.cache.entity.AppDesc;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.entity.InstanceStats;\nimport com.sohu.cache.entity.MachineInfo;\nimport com.sohu.cache.machine.MachineCenter;\nimport com.sohu.cache.redis.RedisCenter;\nimport com.sohu.cache.stats.app.ImportAppCenter;\nimport com.sohu.cache.util.ConstUtils;\nimport com.sohu.cache.util.IdempotentConfirmer;\nimport com.sohu.cache.web.service.AppService;\n\n/**\n * 导入应用\n * \n * @author leifu\n * @Date 2016-4-16\n * @Time 下午3:42:49\n */\npublic class ImportAppCenterImpl implements ImportAppCenter {\n\n    private Logger logger = LoggerFactory.getLogger(ImportAppCenterImpl.class);\n\n    private AppService appService;\n\n    private RedisCenter redisCenter;\n\n    private MachineCenter machineCenter;\n\n    private InstanceDao instanceDao;\n    \n    private InstanceStatsDao instanceStatsDao;\n    \n    @Override\n    public ImportAppResult check(AppDesc appDesc, String appInstanceInfo) {\n        // 1.检查是否应用信息为空\n        if (appDesc == null) {\n            return ImportAppResult.fail(\"应用信息为空\");\n        }\n        // 2.检查应用名是否重复\n        String appName = appDesc.getName();\n        AppDesc existAppDesc = appService.getAppByName(appName);\n        if (existAppDesc != null) {\n            return ImportAppResult.fail(appName + \", 应用名重复\");\n        }\n        // 3.实例信息是否为空\n        if (StringUtils.isBlank(appInstanceInfo)) {\n            return ImportAppResult.fail(\"实例详情为空\");\n        }\n\n        String[] appInstanceDetails = appInstanceInfo.split(\"\\n\");\n\n        // 4.检查实例信息格式是否正确\n        for (String appInstance : appInstanceDetails) {\n            if (StringUtils.isBlank(appInstance)) {\n                return ImportAppResult.fail(\"应用实例信息有空行\");\n            }\n            String[] instanceItems = appInstance.split(\":\");\n            if (instanceItems.length != 3) {\n                return ImportAppResult.fail(\"应用实例信息\" + appInstance + \"格式错误，必须有2个冒号\");\n            }\n            String ip = instanceItems[0];\n            // 4.1.检查ip对应的机器是否存在\n            try {\n                MachineInfo machineInfo = machineCenter.getMachineInfoByIp(ip);\n                if (machineInfo == null) {\n                    return ImportAppResult.fail(appInstance + \"中的ip不存在\");\n                } else if (machineInfo.isOffline()) {\n                    return ImportAppResult.fail(appInstance + \"中的ip已经被删除\");\n                }\n            } catch (Exception e) {\n                return ImportAppResult.fail(appInstance + \"中的ip不存在\");\n            }\n            // 4.2.检查端口是否为整数\n            String portStr = instanceItems[1];\n            boolean portIsDigit = NumberUtils.isDigits(portStr);\n            if (!portIsDigit) {\n                return ImportAppResult.fail(appInstance + \"中的port不是整数\");\n            }\n\n            int port = NumberUtils.toInt(portStr);\n            // 4.3.检查ip:port是否已经在instance_info表和instance_statistics中\n            int count = instanceDao.getCountByIpAndPort(ip, port);\n            if (count > 0) {\n                return ImportAppResult.fail(appInstance + \"中ip:port已经在instance_info存在\");\n            }\n            InstanceStats instanceStats = instanceStatsDao.getInstanceStatsByHost(ip, port);\n            if (instanceStats != null) { \n                return ImportAppResult.fail(appInstance + \"中ip:port已经在instance_statistics存在\");\n            }\n            // 4.4.检查Redis实例是否存活\n            String memoryOrMasterName = instanceItems[2];\n            int memoryOrMasterNameInt = NumberUtils.toInt(memoryOrMasterName);\n            boolean isRun;\n            if (memoryOrMasterNameInt > 0) {\n            \t\tisRun = redisCenter.isRun(ip, port, appDesc.getPassword());\n            } else {\n            \t\tisRun = redisCenter.isRun(ip, port);\n            }\n            if (!isRun) {\n                return ImportAppResult.fail(appInstance + \"中的节点不是存活的\");\n            }\n\n            // 4.5.检查内存是否为整数\n            boolean isSentinelNode = memoryOrMasterNameInt <= 0;\n            if (isSentinelNode) {\n                // 4.5.1 sentinel节点masterName判断\n                if (StringUtils.isEmpty(memoryOrMasterName)) {\n                    return ImportAppResult.fail(appInstance + \"中的sentinel节点master为空\");\n                }\n                // 判断masterName\n                String masterName = getSentinelMasterName(ip, port);\n                if (StringUtils.isEmpty(masterName) || !memoryOrMasterName.equals(masterName)) {\n                    return ImportAppResult.fail(ip + \":\" + port + \", masterName:\" + masterName + \"与所填\"\n                            + memoryOrMasterName + \"不一致\");\n                }\n            } else {\n                // 4.5.2 内存必须是整数\n                boolean maxMemoryIsDigit = NumberUtils.isDigits(memoryOrMasterName);\n                if (!maxMemoryIsDigit) {\n                    return ImportAppResult.fail(appInstance + \"中的maxmemory不是整数\");\n                }\n            }\n        }\n        \n        // 5. 节点之间关系是否正确，这个比较麻烦，还是依赖于用户填写的正确性。\n\n        return ImportAppResult.success();\n    }\n\n\n    @Override\n    public boolean importAppAndInstance(AppDesc appDesc, String appInstanceInfo) {\n        boolean isSuccess = true;\n        try {\n            // 1.1 保存应用信息\n            appService.save(appDesc);\n            long appId = appDesc.getAppId();\n            // 1.2 更新appKey\n            appService.updateAppKey(appId);\n\n            int type = appDesc.getType();\n            // 2.保存应用和用户的关系\n            appService.saveAppToUser(appId, appDesc.getUserId());\n            // 3.保存实例信息并开启统计\n            String[] appInstanceDetails = appInstanceInfo.split(\"\\n\");\n            // 4.检查实例信息格式是否正确\n            for (String appInstance : appInstanceDetails) {\n                String[] instanceItems = appInstance.split(\":\");\n                String host = instanceItems[0];\n                int port = NumberUtils.toInt(instanceItems[1]);\n\n                String memoryOrMasterName = instanceItems[2];\n                boolean isSentinelNode = NumberUtils.toInt(memoryOrMasterName) <= 0;\n                if (isSentinelNode) {\n                    saveInstance(appId, host, port, 0, ConstUtils.CACHE_REDIS_SENTINEL, memoryOrMasterName);\n                } else {\n                    if (ConstUtils.CACHE_REDIS_STANDALONE == type || ConstUtils.CACHE_REDIS_SENTINEL == type) {\n                        saveInstance(appId, host, port, NumberUtils.toInt(memoryOrMasterName), ConstUtils.CACHE_REDIS_STANDALONE, \"\");\n                    } else if (ConstUtils.CACHE_TYPE_REDIS_CLUSTER == type) {\n                        saveInstance(appId, host, port, NumberUtils.toInt(memoryOrMasterName), ConstUtils.CACHE_TYPE_REDIS_CLUSTER, \"\");\n                    }\n                    //deploy quartz\n                    redisCenter.deployRedisCollection(appId, host, port);\n                    redisCenter.deployRedisSlowLogCollection(appId, host, port);\n                }\n            }\n\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            isSuccess = false;\n        }\n        return isSuccess;\n    }\n    \n    /**\n     * 获取sentinel的masterName\n     * @param ip\n     * @param port\n     * @return\n     */\n    private String getSentinelMasterName(final String ip, final int port) {\n        final StringBuilder masterName = new StringBuilder();\n        new IdempotentConfirmer() {\n            private int timeOutFactor = 1;\n            @Override\n            public boolean execute() {\n                Jedis jedis = null;\n                try {\n                    // 预留\n                    String password = null;\n                    jedis = redisCenter.getJedis(ip, port, password);\n                    jedis.getClient().setConnectionTimeout(Protocol.DEFAULT_TIMEOUT * (timeOutFactor++));\n                    jedis.getClient().setSoTimeout(Protocol.DEFAULT_TIMEOUT * (timeOutFactor++));\n                    List<Map<String, String>> mapList = jedis.sentinelMasters();\n                    String targetKey = \"name\";\n                    for (Map<String, String> map : mapList) {\n                        if (map.containsKey(targetKey)) {\n                            masterName.append(MapUtils.getString(map, targetKey, \"\"));\n                        }\n                    }\n                    return true;\n                } catch (Exception e) {\n                    logger.warn(\"{}:{} error message is {} \", ip, port, e.getMessage());\n                    return false;\n                } finally {\n                    if (jedis != null) {\n                        jedis.close();\n                    }\n                }\n            }\n        }.run();\n        return masterName.toString();\n    }\n\n    /**\n     * 保存实例信息\n     * @param appId\n     * @param host\n     * @param port\n     * @param maxMemory\n     * @param type\n     * @param cmd\n     * @return\n     */\n    private InstanceInfo saveInstance(long appId, String host, int port, int maxMemory, int type,\n            String cmd) {\n        InstanceInfo instanceInfo = new InstanceInfo();\n        instanceInfo.setAppId(appId);\n        MachineInfo machineInfo = machineCenter.getMachineInfoByIp(host);\n        instanceInfo.setHostId(machineInfo.getId());\n        instanceInfo.setConn(0);\n        instanceInfo.setMem(maxMemory);\n        instanceInfo.setStatus(InstanceStatusEnum.GOOD_STATUS.getStatus());\n        instanceInfo.setPort(port);\n        instanceInfo.setType(type);\n        instanceInfo.setCmd(cmd);\n        instanceInfo.setIp(host);\n        instanceDao.saveInstance(instanceInfo);\n        return instanceInfo;\n    }\n\n    public void setAppService(AppService appService) {\n        this.appService = appService;\n    }\n\n    public void setRedisCenter(RedisCenter redisCenter) {\n        this.redisCenter = redisCenter;\n    }\n\n    public void setMachineCenter(MachineCenter machineCenter) {\n        this.machineCenter = machineCenter;\n    }\n\n    public void setInstanceDao(InstanceDao instanceDao) {\n        this.instanceDao = instanceDao;\n    }\n\n\n    public void setInstanceStatsDao(InstanceStatsDao instanceStatsDao) {\n        this.instanceStatsDao = instanceStatsDao;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/stats/instance/InstanceAlertConfigService.java",
    "content": "package com.sohu.cache.stats.instance;\n\nimport java.util.Date;\nimport java.util.List;\n\nimport com.sohu.cache.entity.InstanceAlertConfig;\n\n/**\n * 实例报警阀值配置\n * @author leifu\n * @Date 2017年5月19日\n * @Time 下午2:12:29\n */\npublic interface InstanceAlertConfigService {\n\n    /**\n     * 获取所有实例报警配置列表\n     * @return\n     */\n    List<InstanceAlertConfig> getAll();\n    \n    /**\n     * 根据类型获取实例报警配置列表\n     * @param type\n     * @return\n     */\n    List<InstanceAlertConfig> getByType(int type);\n\n    /**\n     * 保存\n     * @param instanceAlert\n     * @return\n     */\n    int save(InstanceAlertConfig instanceAlertConfig);\n\n    /**\n     * 根据id获取\n     * @param id\n     * @return\n     */\n    InstanceAlertConfig get(int id);\n\n    /**\n     * 根据id删除\n     * @param id\n     * @return\n     */\n    int remove(int id);\n    \n    /**\n     * 更新alertValue和checkCycle\n     * @param id\n     * @param alertValue\n     * @param checkCycle\n     */\n    void update(long id, String alertValue, int checkCycle);\n    \n    /**\n     * 更新配置的最后检测时间\n     * @param id\n     * @param lastCheckTime\n     */\n    void updateLastCheckTime(long id, Date lastCheckTime);\n    \n    /**\n     * 监控所有Redis上一分钟状态\n     */\n    void monitorLastMinuteAllInstanceInfo();\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/stats/instance/InstanceDeployCenter.java",
    "content": "package com.sohu.cache.stats.instance;\n\n/**\n * Created by yijunzhang on 14-11-26.\n */\npublic interface InstanceDeployCenter {\n\n    /**\n     * 启动已经存在的实例\n     * @param appId\n     * @param instanceId\n     * @return\n     */\n    boolean startExistInstance(long appId, int instanceId);\n\n    /**\n     * 下线已经存在的实例\n     * @param appId\n     * @param instanceId\n     * @return\n     */\n    boolean shutdownExistInstance(long appId, int instanceId);\n    \n    \n    /**\n     * 展示实例最近的日志\n     * @param instanceId\n     * @param maxLineNum\n     * @return\n     */\n    String showInstanceRecentLog(int instanceId, int maxLineNum);\n\n    /**\n     * 修改实例配置\n     * @param appId\n     * @param appAuditId\n     * @param host\n     * @param port\n     * @param instanceConfigKey\n     * @param instanceConfigValue\n     * @return\n     */\n    boolean modifyInstanceConfig(long appId, Long appAuditId, String host, int port, String instanceConfigKey,\n            String instanceConfigValue);\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/stats/instance/InstanceStatsCenter.java",
    "content": "package com.sohu.cache.stats.instance;\n\nimport com.sohu.cache.entity.InstanceCommandStats;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.entity.InstanceStats;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 实例统计方法\n * Created by yijunzhang on 14-9-17.\n */\npublic interface InstanceStatsCenter {\n\n    /**\n     * 根据实例id获取实例的静态信息\n     *\n     * @param instanceId 实例id\n     * @return 实例信息对象\n     */\n    InstanceInfo getInstanceInfo(long instanceId);\n\n    /**\n     * 根据实例id获取实例的实施统计&是否在线&redis实时统计信息\n     *\n     * @param instanceId 实例id\n     * @return 实例实时状态信息\n     */\n    InstanceStats getInstanceStats(long instanceId);\n\n    /**\n     * 根据实例id，起止时间，命令名称获取实例对应命令的执行次数曲线\n     *\n     * @param instanceId  实例id\n     * @param beginTime   起始时间 闭区间 yyyyMMddHHmm\n     * @param endTime     结束时间 闭区间 yyyyMMddHHmm\n     * @param commandName 命令名称\n     * @return 实例命令执行对象的列表\n     */\n    List<InstanceCommandStats> getCommandStatsList(Long instanceId, long beginTime, long endTime, String commandName);\n\n    /**\n     * 根据appId，起止时间，统计指标名称 获取实例对应指标统计列表\n     *\n     * @param appId  实例id\n     * @param beginTime   起始时间 闭区间 yyyyMMddHHmm\n     * @param endTime     结束时间 闭区间 yyyyMMddHHmm\n     * @param commands 命令名称\n     * @return 应用下 所有实例 命令执行对象的列表\n     * <br/>\n     * Map<Integer, Map<String, List<InstanceCommandStats>>> : Map<InstanceId,Map<CommandName,List<InstanceCommandStats>>>\n     */\n    Map<Integer, Map<String, List<InstanceCommandStats>>> getStandardStatsList(Long appId, long beginTime, long endTime,\n            List<String> commands);\n\n    /**\n     * 在实例上执行命令\n     *\n     * @param host\n     * @param port\n     * @param command\n     * @return\n     */\n    public String executeCommand(String host, int port, String command);\n\n    /**\n     * 在实例上执行命令\n     *\n     * @param instanceId\n     * @param command\n     * @return\n     */\n    public String executeCommand(Long instanceId, String command);\n\n    /**\n     * 获取所有统计信息\n     * @return\n     */\n    public List<InstanceStats> getInstanceStats();\n\n    /**\n     * 按照机器获取实例列表\n     * @param ip\n     * @return\n     */\n    List<InstanceStats> getInstanceStats(String ip);\n\n    /**\n     * 将一个对象（如统计信息）保存到mysql里\n     *\n     * @param infoMap 统计信息对象\n     * @param clusterInfoMap clusterinfo统计信息\n     * @param ip      ip\n     * @param port    port\n     * @param dbType\n     * @return 成功保存返回true，否则返回false\n     */\n    public boolean saveStandardStats(Map<String, Object> infoMap, Map<String, Object> clusterInfoMap, String ip, int port, String dbType);\n\n    /**\n     * 根据收集时间查询某一个实例或机器的统计信息\n     *\n     * @param collectTime 时间点，格式：yyyyMMddHHmm\n     * @param ip          ip\n     * @param port        port\n     * @param dbType\n     * @return 该时间点对应的统计信息\n     */\n    public Map<String, Object> queryStandardInfoMap(long collectTime, String ip, int port, String dbType);\n\n    /**\n     * 查询一段时间内，实例或机器的统计信息的列表，如实例或机器一天中每分钟的统计数据\n     *\n     * @param beginTime 起始时间，格式：yyyyMMddHHmm\n     * @param endTime   结束时间，格式：yyyyMMddHHmm\n     * @param ip        ip\n     * @param port      port\n     * @param dbType\n     * @return 该时间区间内，对应的统计信息的列表\n     */\n    public List<Map<String, Object>> queryDiffMapList(long beginTime, long endTime, String ip, int port, String dbType);\n\n    /**\n     * 清理{day}之前的数据\n     *\n     * @param day\n     */\n    public void cleanUpStandardStats(int day);\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/stats/instance/impl/InstanceAlertConfigServiceImpl.java",
    "content": "package com.sohu.cache.stats.instance.impl;\n\nimport java.text.SimpleDateFormat;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.Comparator;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport org.apache.commons.collections.CollectionUtils;\nimport org.apache.commons.collections.MapUtils;\nimport org.apache.commons.lang.time.DateUtils;\nimport org.apache.velocity.app.VelocityEngine;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.sohu.cache.alert.bean.AlertConfigBaseData;\nimport com.sohu.cache.alert.strategy.AlertConfigStrategy;\nimport com.sohu.cache.alert.strategy.AofCurrentSizeAlertStrategy;\nimport com.sohu.cache.alert.strategy.ClientBiggestInputBufAlertStrategy;\nimport com.sohu.cache.alert.strategy.ClientLongestOutputListAlertStrategy;\nimport com.sohu.cache.alert.strategy.ClusterSlotsOkAlertStrategy;\nimport com.sohu.cache.alert.strategy.ClusterStateAlertStrategy;\nimport com.sohu.cache.alert.strategy.InstantaneousOpsPerSecAlertStrategy;\nimport com.sohu.cache.alert.strategy.LatestForkUsecAlertStrategy;\nimport com.sohu.cache.alert.strategy.MasterSlaveOffsetAlertStrategy;\nimport com.sohu.cache.alert.strategy.MemFragmentationRatioAlertStrategy;\nimport com.sohu.cache.alert.strategy.MinuteAofDelayedFsyncAlertStrategy;\nimport com.sohu.cache.alert.strategy.MinuteSyncFullAlertStrategy;\nimport com.sohu.cache.alert.strategy.MinuteSyncPartialErrAlertStrategy;\nimport com.sohu.cache.alert.strategy.MinuteSyncPartialOkAlertStrategy;\nimport com.sohu.cache.alert.strategy.MinuteTotalNetInputMBytesAlertStrategy;\nimport com.sohu.cache.alert.strategy.MinuteTotalNetOutputMBytesAlertStrategy;\nimport com.sohu.cache.alert.strategy.RdbLastBgsaveStatusAlertStrategy;\nimport com.sohu.cache.dao.AppDao;\nimport com.sohu.cache.dao.InstanceAlertConfigDao;\nimport com.sohu.cache.dao.InstanceDao;\nimport com.sohu.cache.dao.InstanceStatsDao;\nimport com.sohu.cache.entity.AppDesc;\nimport com.sohu.cache.entity.InstanceAlertConfig;\nimport com.sohu.cache.entity.InstanceAlertValueResult;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.entity.StandardStats;\nimport com.sohu.cache.redis.enums.InstanceAlertTypeEnum;\nimport com.sohu.cache.redis.enums.RedisAlertConfigEnum;\nimport com.sohu.cache.stats.instance.InstanceAlertConfigService;\nimport com.sohu.cache.util.ConstUtils;\nimport com.sohu.cache.web.component.EmailComponent;\nimport com.sohu.cache.web.util.VelocityUtils;\n\n/**\n * @author leifu\n * @Date 2017年5月19日\n * @Time 下午2:16:36\n */\npublic class InstanceAlertConfigServiceImpl implements InstanceAlertConfigService {\n\n    private Logger logger = LoggerFactory.getLogger(InstanceAlertConfigServiceImpl.class);\n\n    private InstanceAlertConfigDao instanceAlertConfigDao;\n\n    private InstanceStatsDao instanceStatsDao;\n\n    private InstanceDao instanceDao;\n\n    private EmailComponent emailComponent;\n    \n    private VelocityEngine velocityEngine;\n    \n    private AppDao appDao;\n\n    private static Map<RedisAlertConfigEnum, AlertConfigStrategy> alertConfigStrategyMap = new HashMap<RedisAlertConfigEnum, AlertConfigStrategy>();\n    static {\n        alertConfigStrategyMap.put(RedisAlertConfigEnum.aof_current_size, new AofCurrentSizeAlertStrategy());\n        alertConfigStrategyMap.put(RedisAlertConfigEnum.client_biggest_input_buf, new ClientBiggestInputBufAlertStrategy());\n        alertConfigStrategyMap.put(RedisAlertConfigEnum.client_longest_output_list, new ClientLongestOutputListAlertStrategy());\n        alertConfigStrategyMap.put(RedisAlertConfigEnum.instantaneous_ops_per_sec, new InstantaneousOpsPerSecAlertStrategy()); \n        alertConfigStrategyMap.put(RedisAlertConfigEnum.latest_fork_usec, new LatestForkUsecAlertStrategy()); \n        alertConfigStrategyMap.put(RedisAlertConfigEnum.mem_fragmentation_ratio, new MemFragmentationRatioAlertStrategy()); \n        alertConfigStrategyMap.put(RedisAlertConfigEnum.rdb_last_bgsave_status, new RdbLastBgsaveStatusAlertStrategy()); \n        alertConfigStrategyMap.put(RedisAlertConfigEnum.minute_aof_delayed_fsync, new MinuteAofDelayedFsyncAlertStrategy());\n        alertConfigStrategyMap.put(RedisAlertConfigEnum.minute_rejected_connections, new RdbLastBgsaveStatusAlertStrategy());\n        alertConfigStrategyMap.put(RedisAlertConfigEnum.minute_sync_partial_err, new MinuteSyncPartialErrAlertStrategy());\n        alertConfigStrategyMap.put(RedisAlertConfigEnum.minute_sync_partial_ok, new MinuteSyncPartialOkAlertStrategy());\n        alertConfigStrategyMap.put(RedisAlertConfigEnum.minute_sync_full, new MinuteSyncFullAlertStrategy());\n        alertConfigStrategyMap.put(RedisAlertConfigEnum.minute_total_net_input_bytes, new MinuteTotalNetInputMBytesAlertStrategy());\n        alertConfigStrategyMap.put(RedisAlertConfigEnum.minute_total_net_output_bytes, new MinuteTotalNetOutputMBytesAlertStrategy());\n        alertConfigStrategyMap.put(RedisAlertConfigEnum.master_slave_offset_diff, new MasterSlaveOffsetAlertStrategy());\n        alertConfigStrategyMap.put(RedisAlertConfigEnum.cluster_state, new ClusterStateAlertStrategy());\n        alertConfigStrategyMap.put(RedisAlertConfigEnum.cluster_slots_ok, new ClusterSlotsOkAlertStrategy());\n    }\n\n    @Override\n    public List<InstanceAlertConfig> getAll() {\n        try {\n            return instanceAlertConfigDao.getAll();\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return Collections.emptyList();\n        }\n    }\n\n    @Override\n    public int save(InstanceAlertConfig instanceAlertConfig) {\n        try {\n            return instanceAlertConfigDao.save(instanceAlertConfig);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return -1;\n        }\n    }\n\n    @Override\n    public InstanceAlertConfig get(int id) {\n        try {\n            return instanceAlertConfigDao.get(id);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return null;\n        }\n    }\n\n    @Override\n    public int remove(int id) {\n        try {\n            return instanceAlertConfigDao.remove(id);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return -1;\n        }\n    }\n\n    @Override\n    public List<InstanceAlertConfig> getByType(int type) {\n        try {\n            return instanceAlertConfigDao.getByType(type);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return Collections.emptyList();\n        }\n    }\n\n    @Override\n    public void update(long id, String alertValue, int checkCycle) {\n        try {\n            instanceAlertConfigDao.update(id, alertValue, checkCycle);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n    }\n\n    @Override\n    public void updateLastCheckTime(long id, Date lastCheckTime) {\n        try {\n            instanceAlertConfigDao.updateLastCheckTime(id, lastCheckTime);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n    }\n\n    @Override\n    public void monitorLastMinuteAllInstanceInfo() {\n        long startTime = System.currentTimeMillis();\n        // 1.全部和特殊实例报警配置\n        List<InstanceAlertConfig> commonInstanceAlertConfigList = getByType(InstanceAlertTypeEnum.ALL_ALERT.getValue());\n        List<InstanceAlertConfig> specialInstanceAlertConfigList = getByType(InstanceAlertTypeEnum.INSTANCE_ALERT.getValue());\n        List<InstanceAlertConfig> allInstanceAlertConfigList = new ArrayList<InstanceAlertConfig>();\n        allInstanceAlertConfigList.addAll(commonInstanceAlertConfigList);\n        allInstanceAlertConfigList.addAll(specialInstanceAlertConfigList);\n        if (CollectionUtils.isEmpty(allInstanceAlertConfigList)) {\n            return;\n        }\n        // 2.所有实例信息\n        List<InstanceInfo> allInstanceInfoList = instanceDao.getAllInsts();\n        if (CollectionUtils.isEmpty(allInstanceInfoList)) {\n            return;\n        }\n        // 3. 取上1分钟Redis实例统计信息\n        Date currentTime = new Date();\n        Date beginTime = DateUtils.addMinutes(currentTime, -2);\n        Date endTime = DateUtils.addMinutes(currentTime, -1);\n        Map<String, StandardStats> standardStatMap = getStandardStatsMap(beginTime, endTime);\n        if (MapUtils.isEmpty(standardStatMap)) {\n            logger.warn(\"standardStatMap is empty!\");\n            return;\n        }\n        \n        // 4.检测所有配置\n        List<InstanceAlertValueResult> instanceAlertValueResultList = new ArrayList<InstanceAlertValueResult>();\n        \n        for (InstanceAlertConfig instanceAlertConfig : allInstanceAlertConfigList) {\n            if (!checkInCycle(instanceAlertConfig)) {\n                continue;\n            }\n            List<InstanceInfo> tempInstanceInfoList = allInstanceInfoList;\n            if (instanceAlertConfig.isSpecail()) {\n                tempInstanceInfoList.clear();\n                InstanceInfo instanceInfo = instanceDao.getInstanceInfoById(instanceAlertConfig.getInstanceId());\n                if (instanceInfo == null) {\n                    continue;\n                }\n                tempInstanceInfoList.add(instanceInfo);\n            }\n            for (InstanceInfo instanceInfo : tempInstanceInfoList) {\n                List<InstanceAlertValueResult> InstanceAlertValueResultTempList = dealInstanceAlert(specialInstanceAlertConfigList, instanceAlertConfig, instanceInfo, standardStatMap, currentTime);\n                if (CollectionUtils.isNotEmpty(InstanceAlertValueResultTempList)) {\n                    instanceAlertValueResultList.addAll(InstanceAlertValueResultTempList);\n                }\n            }\n            // 更新配置最后检测时间\n            updateLastCheckTime(instanceAlertConfig.getId(), currentTime);\n        }\n        if (CollectionUtils.isNotEmpty(instanceAlertValueResultList)) {\n            // 发送邮件\n            sendInstanceAlertEmail(beginTime, endTime, instanceAlertValueResultList);\n        }\n        long costTime = System.currentTimeMillis() - startTime;\n        if (costTime > 20000) {\n            logger.warn(\"monitorLastMinuteAllInstanceInfo cost {} ms\", costTime);\n        }\n    }\n    \n    /**\n     * 处理实例\n     * @param instanceAlertConfig\n     * @param instanceInfo\n     * @param standardStatMap\n     * @param currentTime\n     */\n    private List<InstanceAlertValueResult> dealInstanceAlert(List<InstanceAlertConfig> specialInstanceAlertConfigList, InstanceAlertConfig instanceAlertConfig, InstanceInfo instanceInfo, Map<String, StandardStats> standardStatMap, Date currentTime) {\n        if (instanceInfo.isOffline()) {\n            return null;\n        }\n        // 单个实例的统计信息\n        String hostPort = instanceInfo.getHostPort();\n        StandardStats standardStats = standardStatMap.get(hostPort);\n        if (standardStats == null) {\n            return null;\n        }\n        // 判断是不是特殊实例\n        InstanceAlertConfig finalInstanceConfig = filterSpecial(specialInstanceAlertConfigList, instanceAlertConfig, instanceInfo);\n        // 普通配置，但finalInstanceConfig不等于instanceAlertConfig，跳过\n        if (!instanceAlertConfig.isSpecail() && finalInstanceConfig.getId() != instanceAlertConfig.getId()) {\n            return null;\n        }\n        // 是否进入检测周期\n        boolean isInCycle = checkInCycle(finalInstanceConfig);\n        if (!isInCycle) {\n            return null;\n        }\n        // 枚举检测\n        String alertConfig = finalInstanceConfig.getAlertConfig();\n        RedisAlertConfigEnum redisAlertConfigEnum = RedisAlertConfigEnum.getRedisAlertConfig(alertConfig);\n        if (redisAlertConfigEnum == null) {\n            logger.warn(\"alertConfig {} is not in RedisAlertConfigEnum\", alertConfig);\n            return null;\n        }\n        // 策略检测\n        AlertConfigStrategy alertConfigStrategy = alertConfigStrategyMap.get(redisAlertConfigEnum);\n        if (alertConfigStrategy == null) {\n            return null;\n        }\n        \n        // 获取基准数据\n        AlertConfigBaseData alertConfigBaseData = new AlertConfigBaseData();\n        alertConfigBaseData.setInstanceInfo(instanceInfo);\n        alertConfigBaseData.setStandardStats(standardStats);\n        // 开始检测\n        try {\n            return alertConfigStrategy.checkConfig(finalInstanceConfig, alertConfigBaseData);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return null;\n        }\n    }\n\n    /**\n     * 发送邮件\n     * \n     * @param instanceAlertValueResultList\n     */\n    private void sendInstanceAlertEmail(Date beginTime, Date endTime,\n            List<InstanceAlertValueResult> instanceAlertValueResultList) {\n        if (CollectionUtils.isEmpty(instanceAlertValueResultList)) {\n            return;\n        }\n        Collections.sort(instanceAlertValueResultList, new Comparator<InstanceAlertValueResult>() {\n\n            @Override\n            public int compare(InstanceAlertValueResult o1, InstanceAlertValueResult o2) {\n                return (int) (o1.getAppId() - o2.getAppId());\n            }\n        });\n        Map<Long, AppDesc> appDescMap = new HashMap<Long, AppDesc>();\n        for (InstanceAlertValueResult instanceAlertValueResult : instanceAlertValueResultList) {\n            long appId = instanceAlertValueResult.getAppId();\n            AppDesc appDesc = null;\n            if (appDescMap.containsKey(appId)) {\n                appDesc = appDescMap.get(appId);\n            } else {\n                appDesc = appDao.getAppDescById(instanceAlertValueResult.getAppId());\n                appDescMap.put(appId, appDesc);\n            }\n            instanceAlertValueResult.setAppDesc(appDesc);\n        }\n        SimpleDateFormat sdf = new SimpleDateFormat(\"yyyy-MM-dd HH:mm\");\n        String emailTitle = String.format(\"Redis实例分钟报警(%s~%s)\", sdf.format(beginTime), sdf.format(endTime));\n        String emailContent = VelocityUtils.createText(velocityEngine, null, null, null, instanceAlertValueResultList,\n                \"instanceAlert.vm\", \"UTF-8\");\n        emailComponent.sendMailToAdmin(emailTitle, emailContent.toString());\n    }\n\n    /**\n     * 检测是否在周期内\n     * \n     * @param finalInstanceConfig\n     * @return\n     */\n    private boolean checkInCycle(InstanceAlertConfig finalInstanceConfig) {\n        if (ConstUtils.IS_DEBUG) {\n            return true;\n        }\n        // 检测周期转换为毫秒\n        long checkCycleMillionTime = finalInstanceConfig.getCheckCycleMillionTime();\n        // 当前距离上一次检测过去的毫秒\n        long betweenTime = new Date().getTime() - finalInstanceConfig.getLastCheckTime().getTime();\n        // 超过说明需要进行再测检测了\n        if (betweenTime >= checkCycleMillionTime) {\n            return true;\n        }\n        return false;\n    }\n\n    /**\n     * 判断当前实例是否在特殊报警配置中\n     * @param specialInstanceAlertConfigList\n     * @param instanceAlertConfig\n     * @param instanceInfo\n     * @return\n     */\n    private InstanceAlertConfig filterSpecial(List<InstanceAlertConfig> specialInstanceAlertConfigList, InstanceAlertConfig instanceAlertConfig, InstanceInfo instanceInfo) {\n        // 如果没有则返回原来的配置\n        if (CollectionUtils.isEmpty(specialInstanceAlertConfigList)) {\n            return instanceAlertConfig;\n        }\n        // 寻找特殊配置 \n        for (InstanceAlertConfig specialInstanceAlertConfig : specialInstanceAlertConfigList) {\n            String specialAlertConfig = specialInstanceAlertConfig.getAlertConfig();\n            long instanceId = specialInstanceAlertConfig.getInstanceId();\n            // 配置名和实例id对上\n            if (instanceAlertConfig.getAlertConfig().equals(specialAlertConfig) && instanceInfo.getId() == instanceId) {\n                return specialInstanceAlertConfig;\n            }\n        }\n        return instanceAlertConfig;\n    }\n\n    /**\n     * 获取指定时间内的标准统计信息Map\n     * @param beginTime\n     * @param endTime\n     * @return\n     */\n    private Map<String, StandardStats> getStandardStatsMap(Date beginTime, Date endTime) {\n        List<StandardStats> standardStatsList = instanceStatsDao.getStandardStatsByCreateTime(beginTime, endTime, ConstUtils.REDIS);\n        // 按照host:port做分组\n        Map<String, StandardStats> resultMap = new HashMap<String, StandardStats>();\n        for (StandardStats standardStats : standardStatsList) {\n            String hostPort = standardStats.getIp() + \":\" + standardStats.getPort();\n            resultMap.put(hostPort, standardStats);\n        }\n        return resultMap;\n    }\n\n    public void setInstanceAlertConfigDao(InstanceAlertConfigDao instanceAlertConfigDao) {\n        this.instanceAlertConfigDao = instanceAlertConfigDao;\n    }\n\n    public void setInstanceStatsDao(InstanceStatsDao instanceStatsDao) {\n        this.instanceStatsDao = instanceStatsDao;\n    }\n\n    public void setInstanceDao(InstanceDao instanceDao) {\n        this.instanceDao = instanceDao;\n    }\n\n    public void setEmailComponent(EmailComponent emailComponent) {\n        this.emailComponent = emailComponent;\n    }\n\n    public void setVelocityEngine(VelocityEngine velocityEngine) {\n        this.velocityEngine = velocityEngine;\n    }\n\n    public void setAppDao(AppDao appDao) {\n        this.appDao = appDao;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/stats/instance/impl/InstanceDeployCenterImpl.java",
    "content": "package com.sohu.cache.stats.instance.impl;\n\nimport com.sohu.cache.constant.AppCheckEnum;\nimport com.sohu.cache.constant.InstanceStatusEnum;\nimport com.sohu.cache.dao.AppAuditDao;\nimport com.sohu.cache.dao.InstanceDao;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.machine.MachineCenter;\nimport com.sohu.cache.protocol.RedisProtocol;\nimport com.sohu.cache.redis.RedisCenter;\nimport com.sohu.cache.redis.RedisDeployCenter;\nimport com.sohu.cache.stats.instance.InstanceDeployCenter;\nimport com.sohu.cache.util.TypeUtil;\n\nimport org.apache.commons.lang.StringUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.util.Assert;\n\n/**\n * Created by yijunzhang on 14-11-26.\n */\npublic class InstanceDeployCenterImpl implements InstanceDeployCenter {\n\n    private final Logger logger = LoggerFactory.getLogger(this.getClass());\n\n    private InstanceDao instanceDao;\n\n    private RedisCenter redisCenter;\n    \n    private RedisDeployCenter redisDeployCenter;\n\n    private MachineCenter machineCenter;\n    \n    private AppAuditDao appAuditDao;\n\n    @Override\n    public boolean startExistInstance(long appId, int instanceId) {\n        Assert.isTrue(instanceId > 0L);\n        InstanceInfo instanceInfo = instanceDao.getInstanceInfoById(instanceId);\n        Assert.isTrue(instanceInfo != null);\n        int type = instanceInfo.getType();\n        String host = instanceInfo.getIp();\n        int port = instanceInfo.getPort();\n        boolean isRun;\n        if (TypeUtil.isRedisType(type)) {\n        \t\tif (TypeUtil.isRedisSentinel(type)) {\n                isRun = redisCenter.isRun(host, port);\n            } else {\n                isRun = redisCenter.isRun(appId, host, port);\n            }\n            if (isRun) {\n                logger.warn(\"{}:{} instance is Running\", host, port);\n            } else {\n                String runShell;\n                if (TypeUtil.isRedisCluster(type)) {\n                    runShell = RedisProtocol.getRunShell(port, true);\n                } else if (TypeUtil.isRedisSentinel(type)) {\n                    runShell = RedisProtocol.getSentinelShell(port);\n                } else {\n                    runShell = RedisProtocol.getRunShell(port, false);\n                }\n                boolean isRunShell = machineCenter.startProcessAtPort(host, port, runShell);\n                if (!isRunShell) {\n                    logger.error(\"startProcessAtPort-> {}:{} shell= {} failed\", host, port, runShell);\n                    return false;\n                } else {\n                    logger.warn(\"{}:{} instance has Run\", host, port);\n                }\n                if (TypeUtil.isRedisSentinel(type)) {\n                    isRun = redisCenter.isRun(host, port);\n                } else {\n                    isRun = redisCenter.isRun(appId, host, port);\n                }\n            }\n        } else {\n            logger.error(\"type={} not match!\", type);\n            isRun = false;\n        }\n        if (isRun) {\n            instanceInfo.setStatus(InstanceStatusEnum.GOOD_STATUS.getStatus());\n            instanceDao.update(instanceInfo);\n            if (TypeUtil.isRedisType(type)) {\n                redisCenter.deployRedisCollection(instanceInfo.getAppId(), instanceInfo.getIp(), instanceInfo.getPort());\n            }\n        }\n\n        return isRun;\n    }\n\n    @Override\n    public boolean shutdownExistInstance(long appId, int instanceId) {\n        Assert.isTrue(instanceId > 0L);\n        InstanceInfo instanceInfo = instanceDao.getInstanceInfoById(instanceId);\n        Assert.isTrue(instanceInfo != null);\n        int type = instanceInfo.getType();\n        String host = instanceInfo.getIp();\n        int port = instanceInfo.getPort();\n        boolean isShutdown;\n        if (TypeUtil.isRedisType(type)) {\n        \t\tif (TypeUtil.isRedisSentinel(type)) {\n        \t\t\tisShutdown = redisCenter.shutdown(host, port);\n        \t\t} else {\n        \t\t\tisShutdown = redisCenter.shutdown(appId, host, port);\n        \t\t}\n            if (isShutdown) {\n                logger.warn(\"{}:{} redis is shutdown\", host, port);\n            } else {\n                logger.error(\"{}:{} redis shutdown error\", host, port);\n            }\n        } else {\n            logger.error(\"type={} not match!\", type);\n            isShutdown = false;\n        }\n\n        if (isShutdown) {\n            instanceInfo.setStatus(InstanceStatusEnum.OFFLINE_STATUS.getStatus());\n            instanceDao.update(instanceInfo);\n            if (TypeUtil.isRedisType(type)) {\n                redisCenter.unDeployRedisCollection(instanceInfo.getAppId(), instanceInfo.getIp(), instanceInfo.getPort());\n                redisCenter.unDeployRedisSlowLogCollection(instanceInfo.getAppId(), host, port);\n            }\n        }\n        return isShutdown;\n    }\n    \n    @Override\n    public String showInstanceRecentLog(int instanceId, int maxLineNum){\n        Assert.isTrue(instanceId > 0L);\n        InstanceInfo instanceInfo = instanceDao.getInstanceInfoById(instanceId);\n        Assert.isTrue(instanceInfo != null);\n        try {\n            return machineCenter.showInstanceRecentLog(instanceInfo, maxLineNum);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return \"\";\n        }\n    }\n    \n    @Override\n    public boolean modifyInstanceConfig(long appId, Long appAuditId, String host, int port, String instanceConfigKey,\n            String instanceConfigValue) {\n        Assert.isTrue(appAuditId != null && appAuditId > 0L);\n        Assert.isTrue(StringUtils.isNotBlank(host));\n        Assert.isTrue(port > 0);\n        Assert.isTrue(StringUtils.isNotBlank(instanceConfigKey));\n        Assert.isTrue(StringUtils.isNotBlank(instanceConfigValue));\n        boolean isModify = redisDeployCenter.modifyInstanceConfig(appId, host, port, instanceConfigKey, instanceConfigValue);\n        if (isModify) {\n            // 改变审核状态\n            appAuditDao.updateAppAudit(appAuditId, AppCheckEnum.APP_ALLOCATE_RESOURCE.value());\n        }\n        return isModify;\n    }\n    \n\n    public void setInstanceDao(InstanceDao instanceDao) {\n        this.instanceDao = instanceDao;\n    }\n\n    public void setRedisCenter(RedisCenter redisCenter) {\n        this.redisCenter = redisCenter;\n    }\n\n    public void setMachineCenter(MachineCenter machineCenter) {\n        this.machineCenter = machineCenter;\n    }\n\n    public void setRedisDeployCenter(RedisDeployCenter redisDeployCenter) {\n        this.redisDeployCenter = redisDeployCenter;\n    }\n\n    public void setAppAuditDao(AppAuditDao appAuditDao) {\n        this.appAuditDao = appAuditDao;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/stats/instance/impl/InstanceStatsCenterImpl.java",
    "content": "package com.sohu.cache.stats.instance.impl;\n\nimport com.sohu.cache.constant.RedisConstant;\nimport com.sohu.cache.dao.InstanceDao;\nimport com.sohu.cache.dao.InstanceStatsDao;\nimport com.sohu.cache.entity.InstanceCommandStats;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.entity.InstanceStats;\nimport com.sohu.cache.entity.StandardStats;\nimport com.sohu.cache.redis.RedisCenter;\nimport com.sohu.cache.stats.instance.InstanceStatsCenter;\nimport com.sohu.cache.util.ConstUtils;\nimport com.sohu.cache.util.TypeUtil;\nimport com.sohu.cache.web.util.DateUtil;\nimport org.apache.commons.collections4.MapUtils;\nimport org.apache.commons.lang.BooleanUtils;\nimport org.apache.commons.lang.StringUtils;\nimport org.apache.commons.lang.time.DateUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.util.Assert;\n\nimport java.text.SimpleDateFormat;\nimport java.util.*;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * Created by yijunzhang on 14-9-17.\n */\npublic class InstanceStatsCenterImpl implements InstanceStatsCenter {\n    private final Logger logger = LoggerFactory.getLogger(this.getClass());\n\n    private InstanceDao instanceDao;\n\n    private InstanceStatsDao instanceStatsDao;\n\n    private RedisCenter redisCenter;\n    \n    @Override\n    public InstanceInfo getInstanceInfo(long instanceId) {\n        return instanceDao.getInstanceInfoById(instanceId);\n    }\n\n    @Override\n    public InstanceStats getInstanceStats(long instanceId) {\n        InstanceStats instanceStats = instanceStatsDao.getInstanceStatsByInsId(instanceId);\n        if (instanceStats == null) {\n            logger.error(\"instanceStats id={} is null\", instanceId);\n            return null;\n        }\n        InstanceInfo instanceInfo = instanceDao.getInstanceInfoById(instanceId);\n        int type = instanceInfo.getType();\n        boolean isRun = redisCenter.isRun(instanceInfo.getAppId(), instanceInfo.getIp(), instanceInfo.getPort());\n        instanceStats.setRun(isRun);\n        if (isRun) {\n            Map<String, Object> infoMap = getInfoMap(instanceInfo.getAppId(), type, instanceInfo.getIp(), instanceInfo.getPort());\n            instanceStats.setInfoMap(infoMap);\n            if (infoMap == null || infoMap.isEmpty()) {\n                instanceStats.setRun(false);\n            }\n        }\n        return instanceStats;\n    }\n\n    private Map<String, Object> getInfoMap(long appId, int type, String ip, int port) {\n        Map<RedisConstant, Map<String, Object>> infoMap = redisCenter.getInfoStats(appId, ip, port);\n        Map<String, Object> resultMap = new LinkedHashMap<String, Object>();\n        if (infoMap != null) {\n            for (RedisConstant redisConstant : infoMap.keySet()) {\n                resultMap.put(redisConstant.getValue(), infoMap.get(redisConstant));\n            }\n        }\n        return resultMap;\n    }\n\n    @Override\n    public List<InstanceCommandStats> getCommandStatsList(Long instanceId, long beginTime, long endTime,\n            String commandName) {\n        if (instanceId == null) {\n            return Collections.emptyList();\n        }\n        InstanceInfo instanceInfo = instanceDao.getInstanceInfoById(instanceId);\n        List<InstanceCommandStats> resultList = new ArrayList<InstanceCommandStats>();\n        String ip = instanceInfo.getIp();\n        int port = instanceInfo.getPort();\n        int type = instanceInfo.getType();\n        List<Map<String, Object>> objectList = this.queryDiffMapList(beginTime, endTime, ip, port, ConstUtils.REDIS);;\n        if (objectList != null) {\n            for (Map<String, Object> map : objectList) {\n                InstanceCommandStats stats = parseCommand(instanceId, commandName, map, true, type);\n                if (stats != null) {\n                    resultList.add(stats);\n                }\n            }\n        }\n\n        return resultList;\n    }\n\n    @Override\n    public Map<Integer, Map<String, List<InstanceCommandStats>>> getStandardStatsList(Long appId, long beginTime,\n            long endTime, List<String> commands) {\n        if (appId == null) {\n            return Collections.emptyMap();\n        }\n        List<InstanceInfo> list = instanceDao.getInstListByAppId(appId);\n        if (list == null || list.isEmpty()) {\n            return Collections.emptyMap();\n        }\n        Map<Integer, Map<String, List<InstanceCommandStats>>> resultMap = new LinkedHashMap<Integer, Map<String, List<InstanceCommandStats>>>();\n        for (InstanceInfo instance : list) {\n            if (instance.isOffline()) {\n                continue;\n            }\n            int instanceId = instance.getId();\n            String ip = instance.getIp();\n            int port = instance.getPort();\n            int type = instance.getType();\n            Boolean isMaster = redisCenter.isMaster(appId, ip, port);\n            if (BooleanUtils.isNotTrue(isMaster)){\n                continue;\n            }\n            List<Map<String, Object>> objectList = this.queryDiffMapList(beginTime, endTime, ip, port, ConstUtils.REDIS);;\n            if (objectList != null) {\n                Map<String, List<InstanceCommandStats>> commandMap = new LinkedHashMap<String, List<InstanceCommandStats>>();\n                for (String commandName : commands) {\n                    List<InstanceCommandStats> resultList = new ArrayList<InstanceCommandStats>(objectList.size());\n                    for (Map<String, Object> map : objectList) {\n                        InstanceCommandStats stats = parseCommand(instanceId, commandName, map, false, type);\n                        if (stats != null) {\n                            resultList.add(stats);\n                        }\n                    }\n                    commandMap.put(commandName, resultList);\n                }\n                resultMap.put(instanceId, commandMap);\n            }\n        }\n        return resultMap;\n    }\n\n    private InstanceCommandStats parseCommand(long instanceId, String command,\n            Map<String, Object> commandMap, boolean isCommand, int type) {\n        Long collectTime = MapUtils.getLong(commandMap, ConstUtils.COLLECT_TIME, null);\n        if (collectTime == null) {\n            return null;\n        }\n        Long count;\n        if (isCommand) {\n            count = MapUtils.getLong(commandMap, \"cmdstat_\" + command.toLowerCase(), null);\n        } else {\n            count = MapUtils.getLong(commandMap, command.toLowerCase(), null);\n        }\n        if (count == null) {\n            return null;\n        }\n        InstanceCommandStats stats = new InstanceCommandStats();\n        stats.setCommandCount(count);\n        stats.setCommandName(command);\n        stats.setCollectTime(collectTime);\n        stats.setCreateTime(DateUtil.getDateByFormat(String.valueOf(collectTime), \"yyyyMMddHHmm\"));\n        stats.setModifyTime(DateUtil.getDateByFormat(String.valueOf(collectTime), \"yyyyMMddHHmm\"));\n        stats.setInstanceId(instanceId);\n\n        return stats;\n    }\n\n    @Override\n    public String executeCommand(String host, int port, String command) {\n        if (StringUtils.isBlank(host) || port == 0) {\n            return \"host or port is null\";\n        }\n        InstanceInfo instanceInfo = instanceDao.getAllInstByIpAndPort(host, port);\n        if (instanceInfo == null) {\n            return \"instance not exist\";\n        }\n        if (TypeUtil.isRedisType(instanceInfo.getType())) {\n            return redisCenter.executeCommand(instanceInfo.getAppId(), host, port, command);\n        }\n        return \"not support type\";\n    }\n\n    @Override\n    public String executeCommand(Long instanceId, String command) {\n        InstanceInfo instanceInfo = getInstanceInfo(instanceId);\n        return executeCommand(instanceInfo.getIp(), instanceInfo.getPort(), command);\n    }\n\n    @Override\n    public List<InstanceStats> getInstanceStats() {\n        return instanceStatsDao.getInstanceStats();\n    }\n\n    @Override\n    public List<InstanceStats> getInstanceStats(String ip) {\n        List<InstanceStats> instanceStatsList = instanceStatsDao.getInstanceStatsByIp(ip);\n        return instanceStatsList;\n    }\n\n    @Override\n    public boolean saveStandardStats(Map<String, Object> infoMap, Map<String, Object> clusterInfoMap, String ip, int port, String dbType) {\n        Assert.isTrue(infoMap != null && infoMap.size() > 0);\n        Assert.isTrue(StringUtils.isNotBlank(ip));\n        Assert.isTrue(port > 0);\n        Assert.isTrue(infoMap.containsKey(ConstUtils.COLLECT_TIME), ConstUtils.COLLECT_TIME + \" not in infoMap\");\n        long collectTime = MapUtils.getLong(infoMap, ConstUtils.COLLECT_TIME);\n        StandardStats ss = new StandardStats();\n        ss.setCollectTime(collectTime);\n        ss.setIp(ip);\n        ss.setPort(port);\n        ss.setDbType(dbType);\n        if (infoMap.containsKey(RedisConstant.DIFF.getValue())) {\n            Map<String, Object> diffMap = (Map<String, Object>) infoMap.get(RedisConstant.DIFF.getValue());\n            ss.setDiffMap(diffMap);\n            infoMap.remove(RedisConstant.DIFF.getValue());\n        } else {\n            ss.setDiffMap(new HashMap<String, Object>(0));\n        }\n        ss.setInfoMap(infoMap);\n        ss.setClusterInfoMap(clusterInfoMap);\n\n        int mergeCount = instanceStatsDao.mergeStandardStats(ss);\n        return mergeCount > 0;\n    }\n\n    @Override\n    public Map<String, Object> queryStandardInfoMap(long collectTime, String ip, int port, String dbType) {\n        Assert.isTrue(StringUtils.isNotBlank(ip));\n        Assert.isTrue(port > 0);\n        Assert.isTrue(collectTime > 0);\n        StandardStats ss = instanceStatsDao.getStandardStats(collectTime, ip, port, dbType);\n        if (ss != null) {\n            Map<String, Object> infoMap = ss.getInfoMap();\n            Map<String, Object> diffMap = ss.getDiffMap();\n            infoMap.put(RedisConstant.DIFF.getValue(), diffMap);\n            return infoMap;\n        } else {\n            return Collections.emptyMap();\n        }\n    }\n\n    @Override\n    public List<Map<String, Object>> queryDiffMapList(long beginTime, long endTime, String ip, int port,\n            String dbType) {\n        Assert.isTrue(StringUtils.isNotBlank(ip));\n        Assert.isTrue(port > 0);\n        Assert.isTrue(beginTime > 0);\n        Assert.isTrue(endTime > 0);\n        List<StandardStats> list = instanceStatsDao.getDiffJsonList(beginTime, endTime, ip, port, dbType);\n        if (list == null || list.isEmpty()) {\n            return new ArrayList<Map<String, Object>>(0);\n        }\n        List<Map<String, Object>> resultList = new ArrayList<Map<String, Object>>(list.size());\n        for (StandardStats ss : list) {\n            Map<String, Object> diffMap = ss.getDiffMap();\n            diffMap.put(ConstUtils.COLLECT_TIME, ss.getCollectTime());\n            resultList.add(diffMap);\n        }\n        return resultList;\n    }\n\n    @Override\n    public void cleanUpStandardStats(int day) {\n        try {\n            SimpleDateFormat minSdf = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n            SimpleDateFormat hourSdf = new SimpleDateFormat(\"yyyy-MM-dd HH\");\n            // 基准时间\n            Date baseTime = DateUtils.addDays(hourSdf.parse(minSdf.format(new Date())), 0 - day);\n            Date startTime = null;          //删除开始时间\n            Date endTime = null;            //删除结束时间\n            int mins = 24 * 60 * (day - 1); //天换算分钟数,保留一天数据\n            int perMin = 10;                //每10分钟区间做一次删除\n            long beginTime = System.currentTimeMillis();\n            for (int count = 1; count <= mins / perMin; count++) {\n                startTime = DateUtils.addMinutes(baseTime, perMin * (count - 1));\n                endTime = DateUtils.addMinutes(baseTime, perMin * count);\n                long startMills = System.currentTimeMillis();\n                instanceStatsDao.deleteStandardStatsByScanTime(startTime, endTime);\n                logger.warn(\"execute delete task cost：{} ms ,time :{},{}\", System.currentTimeMillis() - startMills, minSdf.format(startTime), minSdf.format(endTime));\n                try {\n                    TimeUnit.MILLISECONDS.sleep(10);\n                } catch (InterruptedException e) {\n                    logger.error(e.getMessage(), e);\n                }\n            }\n            logger.info(\"cleanUpStandardStats total costTime =\" + (System.currentTimeMillis() - beginTime) / 1000 + \" s\");\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n    }\n\n    public void setInstanceDao(InstanceDao instanceDao) {\n        this.instanceDao = instanceDao;\n    }\n\n    public void setInstanceStatsDao(InstanceStatsDao instanceStatsDao) {\n        this.instanceStatsDao = instanceStatsDao;\n    }\n\n    public void setRedisCenter(RedisCenter redisCenter) {\n        this.redisCenter = redisCenter;\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/util/AppKeyUtil.java",
    "content": "package com.sohu.cache.util;\n\nimport java.util.Arrays;\n\nimport org.springframework.util.DigestUtils;\n\n/**\n * appkey计算工具\n * \n * @author leifu\n * @Date 2016-7-9\n * @Time 下午9:23:59\n */\npublic class AppKeyUtil {\n\n    public static String genSecretKey(long appId) {\n        StringBuilder key = new StringBuilder();\n        // 相关参数\n        key.append(appId).append(ConstUtils.APP_SECRET_BASE_KEY);\n        // 转成char[]\n        char[] strs = key.toString().toCharArray();\n        // 排序\n        Arrays.sort(strs);\n        // md5\n        return MD5(new String(strs));\n    }\n\n    private static String MD5(String s) {\n        return DigestUtils.md5DigestAsHex(s.getBytes());\n    }\n    \n    public static void main(String[] args) {\n        System.out.println(genSecretKey(10010));\n    }\n\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/util/IdempotentConfirmer.java",
    "content": "package com.sohu.cache.util;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * 幂等操作器\n * Created by yijunzhang on 14-10-22.\n */\npublic abstract class IdempotentConfirmer {\n    private final Logger logger = LoggerFactory.getLogger(this.getClass());\n\n    private int retry = 3;\n\n    protected IdempotentConfirmer(int retry) {\n        this.retry = retry;\n    }\n\n    public IdempotentConfirmer() {\n    }\n\n    public abstract boolean execute();\n\n    public boolean run() {\n        while (retry-- > 0) {\n            try {\n                boolean isOk = execute();\n                if (isOk){\n                    return true;\n                }\n            } catch (Exception e) {\n                logger.error(e.getMessage(), e);\n                continue;\n            }\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/util/IntegerUtil.java",
    "content": "package com.sohu.cache.util;\n\n/**\n * Integer 工具类\n * \n * @author 银时：yinshi.nc / yinshi.nc@taobao.com\n * @Date Jan 13, 2012\n */\npublic class IntegerUtil {\n\n\t/**\n\t * 如果为0,则返回默认值\n\t * \n\t * @param originalInt\n\t * @param defaultInt\n\t *            默认Integer\n\t * @return\n\t */\n\tpublic static Integer defaultIfZero( Integer originalInt, Integer defaultInt ) {\n\t\tif ( 0 == originalInt ) {\n\t\t\treturn defaultInt;\n\t\t}\n\t\treturn originalInt;\n\t}\n\n\t/**\n\t * 如果为0,则返回默认值\n\t * \n\t * @param originalInt\n\t * @param defaultInt\n\t *            默认Integer\n\t * @return\n\t */\n\tpublic static Integer defaultIfError( String originalStr, Integer defaultInt ) {\n\n\t\ttry {\n\t\t\treturn Integer.parseInt( StringUtil.trimToEmpty( originalStr ) );\n\t\t} catch ( Exception e ) {\n\t\t\treturn defaultInt;\n\t\t}\n\t}\n\n\t/**\n\t * 如果是一个不合法的整型，那么返回一个默认值\n\t * \n\t * @param originalInt\n\t * @param defaultInt\n\t *            默认Integer\n\t * @return\n\t */\n\tpublic static Integer defaultIfError( Integer originalStr, Integer defaultInt ) {\n\n\t\ttry {\n\t\t\treturn Integer.valueOf( originalStr );\n\t\t} catch ( Exception e ) {\n\t\t\treturn defaultInt;\n\t\t}\n\t}\n\n\t/**\n\t * 如果非正,则返回默认值<br>\n\t * @param originalInt\n\t * @param defaultInt\n\t *            默认Integer\n\t * @return originalInt if originalInt>0, return defaultInt if originalInt<=0\n\t */\n\tpublic static Integer defaultIfSmallerThan0( Integer originalInt, Integer defaultInt ) {\n\t\tif ( 0 >= originalInt ) {\n\t\t\treturn defaultInt;\n\t\t}\n\t\treturn originalInt;\n\t}\n\t\n\t/** 将String 转化成 Integer，如果小于等于0，将抛异常 */\n\tpublic static Integer exceptionIfSmallerThan0( String originalStr )throws Exception{\n\t\ttry {\n\t\t\tint num = Integer.parseInt( StringUtil.trimToEmpty( originalStr ) );\n\t\t\tif( num > 0  )\n\t\t\t\treturn num;\n\t\t\telse\n\t\t\t\tthrow new Exception();\n\t\t} catch ( Exception e ) {\n\t\t\tthrow new Exception( originalStr + \" is smaller than 0, or it is a  invalid parameter \" );\n\t\t}\n\t}\n\t\n\t\n\t\n\t/**\n\t * 判断是否大余0\n\t * @return false if num <=0  , true if num >0\n\t */\n\tpublic static boolean isBiggerThan0( int num ){\n\t\tif( 0>= num )\n\t\t\treturn false;\n\t\treturn true;\n\t}\n\n\t/**\n\t * Return maxInt if too big, else return original.\n\t * \n\t * @param originalInt\n\t * @param maxInt\n\t *            max int\n\t * @return\n\t */\n\tpublic static Integer maxIfTooBig( Integer originalInt, Integer maxInt ) {\n\t\tif ( originalInt >= maxInt ) {\n\t\t\toriginalInt = maxInt;\n\t\t}\n\t\treturn originalInt;\n\t}\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/util/JsonUtil.java",
    "content": "package com.sohu.cache.util;\n\nimport java.io.IOException;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.fasterxml.jackson.databind.node.ArrayNode;\nimport com.fasterxml.jackson.databind.node.ObjectNode;\n\n/**\n * jackson转换工具\n * @author leifu\n * @Date 2016年3月23日\n * @Time 上午10:47:57\n */\npublic class JsonUtil {\n    private static final Logger logger = LoggerFactory.getLogger(JsonUtil.class);\n    // 采用jackson\n    private static ObjectMapper mapper = new ObjectMapper();\n\n    /**\n     * 将对象转换为json\n     * \n     * @param entity\n     * @return\n     */\n    public static String toJson(Object entity) {\n        if (entity == null) {\n            return null;\n        }\n        try {\n            return mapper.writeValueAsString(entity);\n        } catch (IOException e) {\n            logger.error(\"parse entity=\" + entity + \" to json error!\", e);\n        }\n        return null;\n    }\n\n    /**\n     * 从json解析出对象\n     * \n     * @param <T>\n     * @param content\n     * @param valueType\n     * @return\n     */\n    public static <T> T fromJson(String content, Class<T> valueType) {\n        if (content == null) {\n            return null;\n        }\n        try {\n            return mapper.readValue(content, valueType);\n        } catch (IOException e) {\n            logger.error(\"parse content=\" + content + \" error!\", e);\n        }\n        return null;\n    }\n\n    private static ObjectMapper getObjectMapper() {\n        return mapper;\n    }\n\n    public static ObjectNode createObjectNode() {\n        return getObjectMapper().createObjectNode();\n    }\n\n    public static ArrayNode createArrayNode() {\n        return getObjectMapper().createArrayNode();\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/util/NMONFileFactory.java",
    "content": "package com.sohu.cache.util;\n\nimport java.io.File;\nimport java.security.CodeSource;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.sohu.cache.server.data.OS;\n/**\n * nmon文件存储工厂\n */\npublic class NMONFileFactory {\n\tprivate static final Logger logger = LoggerFactory.getLogger(NMONFileFactory.class);\n\tpublic static final String NMON_PATH = \"/nmon\";\n\tpublic static final String NMON_DIR_PATH = \"nmon.dir\";\n\tpublic static final String FILE = \"file\";\n\t//nmon文件存储 key为OSType_ProcessorArchitecture_DistributionType\n\tprivate static final Map<String, File> nmonFileMap = new HashMap<String, File>();\n\t\n\tstatic {\n\t\tinit();\n\t}\n\t\n\t/**\n\t * 初始化nmon文件\n\t */\n\tprivate static void init() {\n\t\ttry {\n\t\t\tString path = System.getProperty(NMON_DIR_PATH);\n\t\t\tif(path == null) {\n\t\t\t\tString classpath = null;\n\t\t\t\ttry {\n\t\t\t\t\tCodeSource codeSource = NMONFileFactory.class.getProtectionDomain().getCodeSource();\n\t\t\t\t\tclasspath = codeSource.getLocation().getPath();\n\t\t        \tif(classpath.startsWith(FILE)) {\n\t\t        \t\t//like that: file:/opt/app/cachecloud/cachecloud-web-1.0-SNAPSHOT.war!/WEB-INF/classes!/\n\t\t        \t\tclasspath = classpath.substring(FILE.length()+1);\n\t\t        \t}\n\t\t        \tif(new File(classpath).isDirectory()) {\n\t\t        \t\tpath = classpath+\"../..\"+NMON_PATH;\n\t\t        \t} else {\n\t\t        \t\t//like that: /opt/app/cachecloud/cachecloud-web-1.0-SNAPSHOT.war!/WEB-INF/classes!/\n\t\t        \t\tString[] tmp = classpath.split(\"!/\", 2);\n\t\t        \t\tpath = tmp[0].substring(0, tmp[0].lastIndexOf(\"/\"))+NMON_PATH;\n\t\t        \t}\n\t\t        } catch (Exception e) {\n\t\t            logger.error(classpath, e);\n\t\t        }\n\t\t\t}\n\t        File nmonDir = new File(path);\n\t\t\tif(!nmonDir.exists()) {\n\t\t\t\tlogger.error(\"{} path not exist\", nmonDir.getAbsolutePath());\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t//获取操作系统目录\n\t\t\tFile[] osDirs = nmonDir.listFiles();\n\t\t\tif(osDirs == null) {\n\t\t\t\tlogger.error(\"{} not contains OS folders\", nmonDir.getAbsolutePath());\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfor(File osDir : osDirs) {\n\t\t\t\t//获取处理器架构目录\n\t\t\t\tFile[] archFiles = osDir.listFiles();\n\t\t\t\tif(archFiles == null) {\n\t\t\t\t\tlogger.info(\"{} not contains architecture folders\", osDir.getName());\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tfor(File archDir : archFiles) {\n\t\t\t\t\t//获取nmon文件目录\n\t\t\t\t\tFile[] nmonFiles = archDir.listFiles();\n\t\t\t\t\tif(nmonFiles == null) {\n\t\t\t\t\t\tlogger.info(\"{} not contains nomon files\", archDir.getName());\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tfor(File nmonFile : nmonFiles) {\n\t\t\t\t\t\tnmonFileMap.put(osDir.getName() + \"_\" + archDir.getName() \n\t\t\t\t\t\t\t\t+ \"_\" + nmonFile.getName() , nmonFile);\n\t\t\t\t\t}\n\t\t\t\t\tlogger.info(\"init {} {} nmon file size=\"+nmonFiles.length, \n\t\t\t\t\t\t\tosDir.getName(), archDir.getName());\n\t\t\t\t}\n\t\t\t}\n\t\t\tlogger.info(\"init {} finished, os size={}\", nmonDir.getAbsolutePath(), osDirs.length);\n\t\t} catch (Exception e) {\n\t\t\tlogger.error(\"init nmon factory\", e);\n\t\t}\n\t}\n\t\n\t/**\n\t * 根据OS信息获取对应版本的NMON文件\n\t * @param os\n\t * @return File\n\t */\n\tpublic static File getNMONFile(OS os) {\n\t\tString key = os.getOsType().getValue() \n\t\t\t\t+ \"_\" + os.getProcessorArchitecture().getValue()\n\t\t\t\t+ \"_\" + os.getDistributionType().getNmonName()\n\t\t\t\t+ os.getDistributionVersion().getValue();\n\t\treturn nmonFileMap.get(key);\n\t}\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/util/OSFactory.java",
    "content": "package com.sohu.cache.util;\n\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.sohu.cache.server.data.OS;\nimport com.sohu.cache.server.data.OSInfo;\nimport com.sohu.cache.server.data.OSInfo.DistributionType;\nimport com.sohu.cache.server.data.OSInfo.DistributionVersion;\nimport com.sohu.cache.server.data.OSInfo.OSType;\nimport com.sohu.cache.server.data.OSInfo.ProcessorArchitecture;\n\n/**\n * 根据操作系统原生信息解析出OS\n */\npublic class OSFactory {\n\tprivate static final Logger logger = LoggerFactory.getLogger(OSFactory.class);\n\t//获取发行版本号的主版本和次版本\n\tprivate static final Pattern VERSION_PATTERN = Pattern.compile(\"([1-9]+(\\\\.[0-9]+)?)\");\n\t\n\tpublic static OS getDefaultOS(OSInfo osInfo) {\n\t\tString uname = osInfo.getUname();\n\t\t//无法获取系统位数\n\t\tif(uname == null) {\n\t\t\treturn null;\n\t\t}\n\t\tuname = uname.toLowerCase();\n\t\tProcessorArchitecture defaultArch = ProcessorArchitecture.X86_64;\n\t\t//其次获取操作系统位数\n\t\tif(!uname.contains(defaultArch.getValue())) {\n\t\t\tdefaultArch = ProcessorArchitecture.X86;\n\t\t}\n\t\treturn new OS(OSType.LINUX, DistributionType.LINUX_OLD, \n\t\t\t\tDistributionVersion.DEFAULT, defaultArch);\n\t}\n\t\n\t/**\n\t * 采用uname -a信息和/etc/issue解析出目前能够支持的操作系统\n\t * @param osInfo\n\t * @return OS\n\t */\n\tpublic static OS getOS(OSInfo osInfo) {\n\t\tString uname = osInfo.getUname();\n\t\tString issue = osInfo.getIssue();\n\t\tOSType osType = OSType.LINUX;\n\t\tProcessorArchitecture defaultArch = ProcessorArchitecture.X86_64;\n\t\tDistributionType defaultDist = DistributionType.LINUX_OLD;\n\t\tDistributionVersion version = DistributionVersion.DEFAULT;\n\t\t\n\t\t//无法获取系统类型，位数 版本，采用默认\n\t\tif(uname == null || issue == null) {\n\t\t\tOS os = new OS(osType, defaultDist, version, defaultArch);\n\t\t\treturn os;\n\t\t}\n\t\t\n\t\tuname = uname.toLowerCase();\n\t\t//首先获取操作系统类型\n\t\tif(!uname.contains(OSType.LINUX.getValue())) {\n\t\t\tlogger.error(\"os={} is temporarily not supported\", uname);\n\t\t\treturn null;\n\t\t}\n\t\t//其次获取操作系统位数\n\t\tif(!uname.contains(defaultArch.getValue())) {\n\t\t\tdefaultArch = ProcessorArchitecture.X86;\n\t\t}\n\t\t//再次解析操作系统发行版本\n\t\tissue = issue.toLowerCase();\n\t\t\n\t\tDistributionType findType = DistributionType.findByContains(issue);\n\t\t//没有找到匹配的版本，使用默认\n\t\tif(findType == null) {\n\t\t\tlogger.warn(\"dist cannot matched, {}\", issue);\n\t\t\tOS os = new OS(osType, defaultDist, version, defaultArch);\n\t\t\treturn os;\n\t\t}\n\t\t\n\t\t//最后解析版本号\n\t\tMatcher matcher = VERSION_PATTERN.matcher(issue);\n\t\t//没有版本好用默认的\n\t\tif(!matcher.find()) {\n\t\t\tlogger.warn(\"version not matched, {}\", issue);\n\t\t\tOS os = new OS(osType, defaultDist, version, defaultArch);\n\t\t\treturn os;\n\t\t}\n\t\tString ver = matcher.group();\n\t\tver = ver.replaceAll(\"\\\\.\", \"\");\n\t\tlogger.info(\"version matched, {} - {}\", ver, issue);\n\t\tDistributionVersion versionResult = findVersion(findType.getVersions(), ver);\n\t\t//没有具体的版本能匹配上\n\t\tif(versionResult == null) {\n\t\t\tlogger.info(\"version {} not found, {}\", ver);\n\t\t\tOS os = new OS(osType, defaultDist, version, defaultArch);\n\t\t\treturn os;\n\t\t}\n\t\t\n\t\tOS os = new OS(osType, findType, versionResult, defaultArch);\n\t\tlogger.info(\"find OS={}\", os);\n\t\treturn os;\n\t}\n\t\n\tprivate static DistributionVersion findVersion(DistributionVersion[] versions, String target) {\n\t\tfor(DistributionVersion dv : versions) {\n\t\t\tif(dv.getValue().equals(target)){\n\t\t\t\treturn dv;\n\t\t\t} \n\t\t}\n\t\treturn null;\n\t}\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/util/ObjectConvert.java",
    "content": "package com.sohu.cache.util;\n\nimport com.sohu.cache.entity.InstanceInfo;\n\nimport org.apache.commons.lang.StringUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.List;\n\n/**\n * 对象转换工具类\n *\n * User: lingguo\n * Date: 14-5-29\n * Time: 下午6:17\n */\npublic class ObjectConvert {\n    private static Logger logger = LoggerFactory.getLogger(ObjectConvert.class);\n\n    /**\n     * 将ip和port连接起来\n     *\n     * @param ip\n     * @param port\n     * @return\n     */\n    public static String linkIpAndPort(String ip, int port) {\n        return ip + \":\" + port;\n    }\n\n    /**\n     * 将实例列表转化为ip1:port1 ip2:port2\n     *\n     * @param instanceList\n     * @return\n     */\n    public static String assembleInstance(List<InstanceInfo> instanceList) {\n        if (instanceList.isEmpty()) {\n            return null;\n        }\n        StringBuilder instanceBuilder = new StringBuilder();\n        for (int i = 0; i < instanceList.size(); i++) {\n            InstanceInfo instanceInfo = instanceList.get(i);\n            if (instanceInfo.isOffline()) {\n                continue;\n            }\n            if (i > 0) {\n                instanceBuilder.append(\" \");\n            }\n            instanceBuilder.append(instanceInfo.getIp()).append(\":\").append(instanceInfo.getPort());\n        }\n        return StringUtils.trim(instanceBuilder.toString());\n    }\n\n    /**\n     * 将百分比的比值转换为对应浮点数\n     *\n     * @param value         百分比表示\n     * @param defaultVal    默认值\n     * @return              转换后的浮点表示\n     */\n    public static double percentToDouble(String value, double defaultVal) {\n        double result = defaultVal;\n        if (value == null || value.isEmpty()) {\n            return result;\n        }\n        try {\n            result = Double.valueOf(value.substring(0, value.length() - 1));\n        } catch (NumberFormatException e) {\n            logger.error(e.getMessage(), e);\n        }\n\n        return result;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/util/ScheduleUtil.java",
    "content": "package com.sohu.cache.util;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.text.ParseException;\nimport java.text.SimpleDateFormat;\nimport java.util.Calendar;\nimport java.util.Date;\nimport java.util.Random;\n\n/**\n * 调度相关的工具类\n * <p/>\n * Created by yijunzhang on 14-6-10.\n */\npublic class ScheduleUtil {\n    private static final Logger LOGGER = LoggerFactory.getLogger(ScheduleUtil.class);\n\n    private static final String COLLECT_TIME_FORMAT = \"yyyyMMddHHmm\";\n    private static final String DATE_FORMAT = \"yyyyMMdd\";\n\n    /**\n     * cron表达式：每分钟，根据appId计算分钟的秒数\n     *\n     * @param appId\n     * @return\n     */\n    public static String getMinuteCronByAppId(long appId) {\n        String baseCron = (appId % 50) + \" 0/1 * ? * *\";\n        return baseCron;\n    }\n    \n    public static String getMachineStatsCron(long hostId) {\n        String baseCron = (hostId % 50) + \" 0/\" + ConstUtils.MACHINE_STATS_CRON_MINUTE + \" * ? * *\";\n        return baseCron;\n    }\n    \n    public static String getFiveMinuteCronByHostId(long hostId) {\n        String baseCron = (hostId % 50) + \" 0/5 * ? * *\";\n        return baseCron;\n    }\n    \n    public static String getRedisSlowLogCron(long appId) {\n        Random random = new Random();\n        String baseCron = random.nextInt(60) + \" 0/20 * ? * *\";\n        return baseCron;\n    }\n\n    /**\n     * cron表达式：每小时，根据hostId计算小时的分钟数\n     *\n     * @param hostId\n     * @return\n     */\n    public static String getHourCronByHostId(long hostId) {\n        String hourCron = \"0 %s 0/1 ? * *\";\n        Random random = new Random();\n        long minute = (hostId + random.nextInt(Integer.MAX_VALUE)) % 60;\n        return String.format(hourCron, minute);\n    }\n\n    /**\n     * 计算前一分钟的时间，并格式化\n     *\n     * @param collectTime 基准时间\n     * @return\n     */\n    public static long getLastCollectTime(long collectTime) {\n        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(COLLECT_TIME_FORMAT);\n        try {\n            Date date = simpleDateFormat.parse(String.valueOf(collectTime));\n            Calendar calendar = Calendar.getInstance();\n            calendar.setTime(date);\n            calendar.add(Calendar.MINUTE, -1);\n            Date lastDate = calendar.getTime();\n            return Long.valueOf(simpleDateFormat.format(lastDate));\n        } catch (ParseException e) {\n            LOGGER.error(e.getMessage(), e);\n            return 0L;\n        }\n    }\n\n    /**\n     * 格式化时间\n     *\n     * @param date\n     * @return\n     */\n    public static long getCollectTime(Date date) {\n        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(COLLECT_TIME_FORMAT);\n        return Long.valueOf(simpleDateFormat.format(date));\n    }\n\n    /**\n     * 返回某一天的起始时间，如：201406300000\n     *\n     * @param date  当前日期\n     * @param offset 针对当前日期的偏移\n     * @return 日期的long形式，如201406300000\n     */\n    public static long getBeginTimeOfDay(Date date, int offset) {\n        Calendar calendar = Calendar.getInstance();\n        calendar.setTime(date);\n        calendar.add(Calendar.DAY_OF_YEAR, offset);\n        date = calendar.getTime();\n        SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT);\n        return Long.valueOf(dateFormat.format(date) + \"0000\");\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/util/StringUtil.java",
    "content": "package com.sohu.cache.util;\n\nimport static com.sohu.cache.constant.EmptyObjectConstant.EMPTY_STRING;\n\nimport java.io.UnsupportedEncodingException;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\nimport com.sohu.cache.constant.BaseConstant;\nimport com.sohu.cache.constant.EmptyObjectConstant;\n\n/**\n * Description: String Utils\n * \n * @author nileader / nileader@gmail.com\n * @Date Feb 10, 2012\n */\npublic class StringUtil {\n\n    /**\n     * Check String is equals. targetStr compare with compareStrArray, and\n     * return true if equals one or more\n     * \n     * @param targetStr\n     *            寰呮瘮杈冪殑瀛楃涓�\n     * @param compareStrArray\n     *            瑕佹瘮杈冪殑涓�釜鎴栧涓瓧绗︿覆鏍囧噯\n     * @return\n     */\n    public static boolean containsIgnoreCase( final String originalStr, final CharSequence targetStr ) {\n\n        if ( null == originalStr ) {\n            return false;\n        }\n\n        String originalStrCaps = originalStr.toUpperCase();\n        String targetStrCaps = targetStr.toString().toUpperCase();\n        return originalStrCaps.contains( targetStrCaps );\n    }\n\n\n    /**\n     * Description: Remove {_, -, @, $, #, /, &} in string and make letter after\n     * this uppercase.<br>\n     * e.g. ni_lea-der@gmail./com -> niLeaDerGmail.Com\n     * \n     * @param @param inputString\n     * @param @param firstCharacterUppercase The first letter is need uppercase.\n     * @return String\n     * @throws\n     */\n    public static String convertToCamelCaseString( String inputString, boolean firstCharacterUppercase ) {\n        if ( null == inputString ) {\n            return null;\n        }\n        StringBuilder sb = new StringBuilder();\n\n        boolean nextUpperCase = false;\n        for ( int i = 0; i < inputString.length(); i++ ) {\n            char c = inputString.charAt( i );\n\n            switch ( c ) {\n            case '_':\n            case '-':\n            case '@':\n            case '$':\n            case '#':\n            case ' ':\n            case '/':\n            case '&':\n                if ( sb.length() > 0 ) {\n                    nextUpperCase = true;\n                }\n                break;\n\n            default:\n                if ( nextUpperCase ) {\n                    sb.append( Character.toUpperCase( c ) );\n                    nextUpperCase = false;\n                } else {\n                    sb.append( c );\n                }\n                break;\n            }\n        }\n\n        if ( firstCharacterUppercase ) {\n            sb.setCharAt( 0, Character.toUpperCase( sb.charAt( 0 ) ) );\n        } else {\n            sb.setCharAt( 0, Character.toLowerCase( sb.charAt( 0 ) ) );\n        }\n\n        return sb.toString();\n    }\n\n    /**\n     * Return Default if originalStr is empty.\n     * \n     * @param originalStr\n     *            寰呯‘璁ゅ�\n     * @param defaultStr\n     *            榛樿鍊�\n     * @return 濡傛灉originalStr涓虹┖锛岄偅涔堝氨杩斿洖defaultStr\n     */\n    public static String defaultIfBlank( String originalStr, String defaultStr ) {\n        if ( StringUtil.isBlank( originalStr ) ) {\n            return defaultStr;\n        }\n        Collections.emptyList();\n        return originalStr;\n    }\n\n    /**\n     * Check String is equals Ignore Case. targetStr compare with\n     * compareStrArray, and return true if equals all\n     * \n     * @param targetStr\n     *            寰呮瘮杈冪殑瀛楃涓�\n     * @param compareStrArray\n     *            瑕佹瘮杈冪殑涓�釜鎴栧涓瓧绗︿覆鏍囧噯\n     * @return true if targetStr same with every string in compareStrArray\n     */\n    public static boolean equalsIgnoreCaseAll( String targetStr, String... compareStrArray ) {\n\n        if ( StringUtil.isBlank( targetStr ) || null == compareStrArray || 0 == compareStrArray.length ) {\n            return false;\n        }\n        for ( int i = 0; i < compareStrArray.length; i++ ) {\n            if ( !targetStr.equalsIgnoreCase( compareStrArray[i] ) ) {\n                return false;\n            }\n        }\n        return true;\n    }\n\n    /**\n     * Check String is equals. targetStr compare with compareStrArray, and\n     * return true if equals one or more\n     * \n     * @param targetStr\n     *            寰呮瘮杈冪殑瀛楃涓�\n     * @param compareStrArray\n     *            瑕佹瘮杈冪殑涓�釜鎴栧涓瓧绗︿覆鏍囧噯\n     * @return true if targetStr same with string in compareStrArray one at\n     *         least\n     */\n    public static boolean equalsIgnoreCaseOne( String targetStr, String... compareStrArray ) {\n\n        if ( StringUtil.isBlank( targetStr ) || null == compareStrArray || 0 == compareStrArray.length ) {\n            return false;\n        }\n        for ( int i = 0; i < compareStrArray.length; i++ ) {\n            if ( targetStr.equalsIgnoreCase( compareStrArray[i] ) ) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    /**\n     * 閫氳繃姝ｅ垯琛ㄨ揪鏂瑰紡锛屾壘鍑轰竴涓瓧绗︿覆涓墍鏈夋寚瀹氱殑瀛愪覆\n     * \n     * @param @param originalStr 瀛楃涓�\n     * @param @param regex 寰呮煡鎵惧瓙涓茬殑姝ｅ垯琛ㄨ揪寮�\n     * @return List<String> 瀛愪覆闆嗗悎\n     * \n     *         <pre>\n     *  瀵�/1.1.1.1:sid=0x2337c7074dofj02e,37775[1](queued=0,recved=6,sent=7,sid=0x2337c7074f1102e,sdlfjle,dsfe鐨勭粨鏋滄槸锛�\n     * [sid=0x2337c7074dofj02e, , sid=0x2337c7074f1102e, ]\n     * </pre>\n     */\n    public static List< String > findAllByRegex( String originalStr, String regex ) {\n\n        if ( StringUtil.isBlank( originalStr ) || StringUtil.isBlank( regex ) )\n            return null;\n\n        List< String > targetStrList = new ArrayList< String >();\n        final Pattern patternOfTargetStr = Pattern.compile( regex, Pattern.CANON_EQ );\n        final Matcher matcherOfTargetStr = patternOfTargetStr.matcher( originalStr );\n        /** 寮�瑙ｆ瀽 */\n        while ( matcherOfTargetStr.find() ) {\n            targetStrList.add( StringUtil.trimToEmpty( matcherOfTargetStr.group() ) );\n        }\n        return targetStrList;\n    }\n\n    /**\n     * 閫氳繃姝ｅ垯琛ㄨ揪鏂瑰紡锛屾壘鍑轰竴涓瓧绗︿覆涓涓�釜鎸囧畾鐨勫瓙涓�\n     * \n     * @param @param originalStr 瀛楃涓�\n     * @param @param regex 寰呮煡鎵惧瓙涓茬殑姝ｅ垯琛ㄨ揪寮�\n     * @return List<String> 瀛愪覆闆嗗悎\n     * \n     *         <pre>\n     *  瀵�/1.1.1.1:sid=0x2337c7074dofj02e,37775[1](queued=0,recved=6,sent=7,sid=0x2337c7074f1102e,sdlfjle,dsfe鐨勭粨鏋滄槸锛�\n     * sid=0x2337c7074dofj02e,\n     * </pre>\n     */\n    public static String findFirstByRegex( String originalStr, String regex ) {\n\n        if ( StringUtil.isBlank( originalStr ) || StringUtil.isBlank( regex ) )\n            return EMPTY_STRING;\n\n        final Pattern patternOfTargetStr = Pattern.compile( regex, Pattern.CANON_EQ );\n        final Matcher matcherOfTargetStr = patternOfTargetStr.matcher( originalStr );\n        /** 寮�瑙ｆ瀽 */\n        if ( matcherOfTargetStr.find() ) {\n            return StringUtil.trimToEmpty( matcherOfTargetStr.group() );\n        }\n        return EMPTY_STRING;\n    }\n\n    /**\n     * 鐢熸垚绌虹櫧琛�\n     * \n     * @param lines\n     *            琛屾暟\n     */\n    public static String generateLineBlank( int lines ) {\n        StringBuilder sb = new StringBuilder();\n\n        for ( int i = 0; i < lines; i++ ) {\n            sb.append( \"\\n\" );\n        }\n\n        return sb.toString();\n    }\n\n    /**\n     * make first letter lower case for str\n     * \n     * @return Same letter, but the first letter is lower case.\n     */\n    public static String makeFirstLetterLowerCase( String str ) {\n        String firstLetter = str.substring( 0, 1 );\n        return firstLetter.toLowerCase() + str.substring( 1, str.length() );\n    }\n\n    /***\n     * check if orginalStr is null or empty. <br>\n     * If have more than one originalStr, use isBlank(String...\n     * originalStrArray)\n     * \n     * @param originalStr\n     *            寰呯‘璁ゅ�\n     * @return true or false;\n     */\n    public static boolean isBlank( String originalStr ) {\n        if ( null == originalStr ) {\n            return true;\n        }\n        if ( originalStr.contains( BaseConstant.WORD_SEPARATOR ) ) {\n            return false;\n        }\n        return trimToEmpty( originalStr ).isEmpty();\n    }\n\n    /***\n     * check if orginalStr is null or empty\n     * \n     * @param String\n     *            ... originalStrArray\n     * @return true if have one blank at least.\n     */\n    public static boolean isBlank( String... originalStrArray ) {\n\n        if ( null == originalStrArray || 0 == originalStrArray.length )\n            return true;\n        for ( int i = 0; i < originalStrArray.length; i++ ) {\n            if ( isBlank( originalStrArray[i] ) )\n                return true;\n        }\n        return false;\n    }\n\n    /**\n     * check the originalStr is contain the whitespace\n     * \n     * @param originalStr\n     * @return true if contain whitespace\n     */\n    public static boolean isContainWhitespace( String originalStr ) {\n\n        if ( StringUtil.isBlank( originalStr ) ) {\n            return true;\n        }\n        int strLen = originalStr.length();\n        for ( int i = 0; i < strLen; i++ ) {\n            char ch = originalStr.charAt( i );\n            if ( Character.isWhitespace( ch ) ) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    /**\n     * 字符串连接，使用指定分隔符\n     * \n     * @param subStr\n     * @return\n     */\n    public static String join( String... subStrs ) {\n\n        if ( null == subStrs || 0 == subStrs.length ) {\n            return EMPTY_STRING;\n        }\n        StringBuilder sb = new StringBuilder();\n        for ( String subStr : subStrs ) {\n            sb.append( subStr ).append( BaseConstant.WORD_SEPARATOR );\n        }\n        String sbStr = sb.toString();\n        if ( sbStr.endsWith( BaseConstant.WORD_SEPARATOR ) ) {\n            sbStr = StringUtil.replaceLast( sbStr, BaseConstant.WORD_SEPARATOR, \"\" );\n        }\n        return sbStr;\n    }\n\n    /**\n     * Description: Replaces last substring of this string that matches the\n     * given regular expression with the given replacement.<br>\n     * Do not worry about null pointer\n     * \n     * @param @param regex\n     * @param @param replacement\n     * @return String\n     * @throws\n     */\n    public static String replaceAll( String originalStr, String replacement, String regex ) {\n        return StringUtil.trimToEmpty( originalStr ).replaceAll( regex, replacement );\n    }\n\n    public static String replaceAll( String originalStr, String replacement, String... regexArray ) {\n\n        if ( 0 == regexArray.length )\n            return originalStr;\n\n        for ( String regex : regexArray ) {\n            originalStr = StringUtil.replaceAll( originalStr, replacement, regex );\n        }\n\n        return originalStr;\n    }\n\n    /**\n     * Description: Replaces last substring of this string that matches the\n     * given regular expression with the given replacement.\n     * \n     * @param @param regex\n     * @param @param replacement\n     * @param @return\n     * @return String\n     * @throws\n     */\n    public static String replaceLast( String originalStr, String regex, String replacement ) {\n\n        if ( StringUtil.isBlank( originalStr ) )\n            return EMPTY_STRING;\n\n        int index = originalStr.lastIndexOf( regex );\n        if ( -1 == index )\n            return originalStr;\n\n        // 鍏堝瓨鍌ㄨ繖涓猧ndex涔嬪墠鐨勬墍鏈塻tr\n        String temp = originalStr.substring( 0, index );\n        String temp2 = originalStr.substring( index, originalStr.length() );\n\n        temp2 = temp2.replaceFirst( regex, replacement );\n\n        originalStr = temp + temp2;\n\n        return originalStr;\n    }\n\n    \n    /**\n     * Description: Replaces all {n} placeholder use params\n     * \n     * @param originalStr\n     *            a string such as :\n     *            \"select * from table where id={0}, name={1}, gender={3}\"\n     * @param replacementParams\n     *            real params: 1,yinshi.nc,male\n     * @note n start with 0\n     */\n    public static String replaceSequenced( String originalStr, Object... replacementParams ) {\n\n        if ( StringUtil.isBlank( originalStr ) )\n            return EMPTY_STRING;\n        if ( null == replacementParams || 0 == replacementParams.length )\n            return originalStr;\n\n        for ( int i = 0; i < replacementParams.length; i++ ) {\n            String elementOfParams = replacementParams[i] + EmptyObjectConstant.EMPTY_STRING;\n            if ( StringUtil.trimToEmpty( elementOfParams ).equalsIgnoreCase( \"null\" ) )\n                elementOfParams = EmptyObjectConstant.EMPTY_STRING;\n            originalStr = originalStr.replace( \"{\" + i + \"}\", StringUtil.trimToEmpty( elementOfParams ) );\n        }\n\n        return originalStr;\n    }\n\n    /**\n     * 璁剧疆鍓嶇紑锛屽鏋滆繖涓瓧绗︿覆宸茬粡鏄繖涓墠缂�簡锛岄偅涔堝氨涓嶄綔浠讳綍鎿嶄綔銆� TODO none test\n     * */\n    public static String setPrefix( String originalStr, String prefix ) {\n        originalStr = StringUtil.trimToEmpty( originalStr );\n        prefix = StringUtil.trimToEmpty( prefix );\n        if ( !originalStr.startsWith( prefix ) ) {\n            originalStr = prefix + originalStr;\n        }\n        return originalStr;\n    }\n\n    /**\n\n    /**\n     * 鍒ゆ柇瀛楃涓叉槸鍚﹁秴杩囨寚瀹氶暱搴︼紝濡備綍瓒呰繃锛屾坊鍔犳寚瀹氬悗缂�\n     * \n     * @param originalStr\n     *            \"閾舵椂鐨�\n     * @param maxLength\n     *            2\n     * @param suffix\n     *            ...\n     * @return \"閾舵椂...\"\n     */\n    public static String subStringIfTooLong( String originalStr, int maxLength, String suffix ) {\n        if ( StringUtil.isBlank( originalStr ) )\n            return EmptyObjectConstant.EMPTY_STRING;\n        if ( maxLength < 0 )\n            maxLength = 0;\n        if ( originalStr.length() > maxLength )\n            return originalStr.substring( 0, maxLength ) + StringUtil.trimToEmpty( suffix );\n        return originalStr;\n    }\n\n    /**\n     * Returns a copy of the string, with leading and trailing whitespace\n     * omitted. Don't worry the NullPointerException. Will never return Null.\n     * \n     * @param originalStr\n     * @return \"\" or String without empty str.\n     */\n    public static String trimToEmpty( String originalStr ) {\n        if ( null == originalStr || originalStr.isEmpty() )\n            return EMPTY_STRING;\n        if ( originalStr.equals( BaseConstant.WORD_SEPARATOR ) )\n            return originalStr;\n        return originalStr.trim();\n    }\n\n    /**\n     * URL编码\n     * \n     * @param s\n     *            String to be translated.\n     * @param enc\n     *            The name of a supported character encoding.\n     * @return\n     */\n    public static String urlEncode( String s, String enc ) {\n        if ( StringUtil.isBlank( s ) )\n            return StringUtil.trimToEmpty( s );\n        try {\n            return java.net.URLEncoder.encode( trimToEmpty( s ), enc );\n        } catch ( UnsupportedEncodingException e ) {\n            return s;\n        }\n    }\n\n    /**\n     * URL编码,使用UTF-8编码\n     * \n     * @param s\n     *            String to be translated.\n     * @param enc\n     *            The name of a supported character encoding.\n     * @return\n     */\n    public static String urlEncode( String s ) {\n        if ( StringUtil.isBlank( s ) )\n            return StringUtil.trimToEmpty( s );\n        return urlEncode( trimToEmpty( s ), \"UTF-8\" );\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/util/TypeUtil.java",
    "content": "package com.sohu.cache.util;\n\n/**\n * Created by yijunzhang on 14-9-26.\n */\npublic class TypeUtil {\n\n    public static boolean isRedisType(int type) {\n        if (type == ConstUtils.CACHE_REDIS_SENTINEL\n                || type == ConstUtils.CACHE_TYPE_REDIS_CLUSTER\n                || type == ConstUtils.CACHE_REDIS_STANDALONE) {\n            return true;\n        }\n        return false;\n    }\n\n    public static boolean isRedisCluster(int type) {\n        if (type == ConstUtils.CACHE_TYPE_REDIS_CLUSTER) {\n            return true;\n        }\n        return false;\n    }\n\n    public static boolean isRedisSentinel(int type) {\n        if (type == ConstUtils.CACHE_REDIS_SENTINEL) {\n            return true;\n        }\n        return false;\n    }\n    \n    public static boolean isRedisStandalone(int type) {\n        if (type == ConstUtils.CACHE_REDIS_STANDALONE) {\n            return true;\n        }\n        return false;\n    }\n\n    public static boolean isRedisDataType(int type) {\n        if (type == ConstUtils.CACHE_TYPE_REDIS_CLUSTER\n                || type == ConstUtils.CACHE_REDIS_STANDALONE) {\n            return true;\n        }\n        return false;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/chart/key/ChartKeysUtil.java",
    "content": "package com.sohu.cache.web.chart.key;\n\n/**\n * Created by hym on 14-7-27.\n */\npublic class ChartKeysUtil {\n    public enum ChartKey {\n        RENDER_TO(\"renderTo\"), TYPE(\"type\");\n        private String key;\n\n        ChartKey(String key) {\n            this.key = key;\n        }\n\n        public String getKey() {\n            return key;\n        }\n    }\n\n    public enum TitleKey {\n        TEXT(\"text\");\n        private String key;\n\n        TitleKey(String key) {\n            this.key = key;\n        }\n\n        public String getKey() {\n            return key;\n        }\n    }\n\n    public enum SubTitleKey {\n        TEXT(\"text\");\n        private String key;\n\n        SubTitleKey(String key) {\n            this.key = key;\n        }\n\n        public String getKey() {\n            return key;\n        }\n    }\n\n    public enum XAxisKey {\n        CATEGORIES(\"categories\"),\n        LABELS(\"labels\"),LABELS_STEP(\"step\"),LABELS_ROTATION(\"rotation\"), LABELS_Y(\"y\"),\n        MAX_STAGGER_LINES(\"maxStaggerLines\");\n        private String key;\n\n        XAxisKey(String key) {\n            this.key = key;\n        }\n\n        public String getKey() {\n            return key;\n        }\n    }\n\n    public enum YAxisKey {\n        TITLE(\"title\"), TITLE_TEXT(\"text\"),\n        PLOTLINES(\"plotLines\"), PLOTLINES_VALUE(\"value\"), PLOTLINES_WIDTH(\"width\"), PLOTLINES_COLOR(\"color\");\n        private String key;\n\n        YAxisKey(String key) {\n            this.key = key;\n        }\n\n        public String getKey() {\n            return key;\n        }\n    }\n\n    public enum TooltipKey {\n        VALUESUFFIX(\"valueSuffix\"),CROSSHAIRS(\"crosshairs\"),SHARED(\"shared\");\n        private String key;\n\n        TooltipKey(String key) {\n            this.key = key;\n        }\n\n        public String getKey() {\n            return key;\n        }\n    }\n\n    public enum LegendKey {\n        LAYOUT(\"layout\"), ALIGN(\"align\"), VERTICALALIGN(\"verticalAlign\"), BORDERWIDTH(\"borderWidth\");\n        private String key;\n\n        LegendKey(String key) {\n            this.key = key;\n        }\n\n        public String getKey() {\n            return key;\n        }\n    }\n\n    public enum SeriesKey {\n        DATA(\"data\"), NAME(\"name\");\n        private String key;\n\n        SeriesKey(String key) {\n            this.key = key;\n        }\n\n        public String getKey() {\n            return key;\n        }\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/chart/model/AreaChartEntity.java",
    "content": "package com.sohu.cache.web.chart.model;\n\nimport com.sohu.cache.web.chart.key.ChartKeysUtil;\n\nimport java.util.HashMap;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\n\npublic class AreaChartEntity extends ChartEntity {\n    public AreaChartEntity() {\n        super();\n        putChartType();\n        setTooltipShared(true);\n    }\n\n    @Override\n    protected void putChartType() {\n        this.getChart().put(ChartKeysUtil.ChartKey.TYPE.getKey(), \"area\");\n    }\n\n    public void setXAxisCategories(List<Object> xAxisCategories) {\n        setXAxisCategories(xAxisCategories, 14);\n    }\n\n    public void setXAxisCategories(List<Object> xAxisCategories, int totalLabels) {\n        setXAxisCategories(xAxisCategories, totalLabels, 0, -5);\n    }\n\n    public void setXAxisCategories(List<Object> xAxisCategories, int totalLabels, int rotation, int y) {\n        putXAxis(ChartKeysUtil.XAxisKey.CATEGORIES.getKey(), xAxisCategories);\n        if (xAxisCategories.size() >= totalLabels) {\n            Map<String, Object> m = null;\n            if (this.getxAxis().containsKey(ChartKeysUtil.XAxisKey.LABELS.getKey())) {\n                m = (Map<String, Object>) this.getxAxis().get(ChartKeysUtil.XAxisKey.LABELS.getKey());\n            }\n            if (m == null) {\n                m = new LinkedHashMap<String, Object>();\n            }\n            m.put(ChartKeysUtil.XAxisKey.LABELS_STEP.getKey(), xAxisCategories.size() / totalLabels + 1);\n            m.put(ChartKeysUtil.XAxisKey.LABELS_ROTATION.getKey(), rotation);\n            m.put(ChartKeysUtil.XAxisKey.LABELS_Y.getKey(), y);\n            m.put(ChartKeysUtil.XAxisKey.MAX_STAGGER_LINES.getKey(), 1);\n            putXAxis(ChartKeysUtil.XAxisKey.LABELS.getKey(), m);\n        }\n    }\n\n    public void setYAxisTitle(String title) {\n        if (this.getyAxis().containsKey(ChartKeysUtil.YAxisKey.TITLE.getKey())) {\n            ((Map<String, Object>) this.getyAxis().get(ChartKeysUtil.YAxisKey.TITLE.getKey())).put(ChartKeysUtil.YAxisKey.TITLE_TEXT.getKey(), title);\n        } else {\n            Map<String, Object> map = new HashMap<String, Object>();\n            map.put(ChartKeysUtil.YAxisKey.TITLE_TEXT.getKey(), title);\n            putYAxis(ChartKeysUtil.YAxisKey.TITLE.getKey(), map);\n        }\n    }\n\n    public void setTooltipCrosshairs(boolean crosshairs) {\n        putTooltip(ChartKeysUtil.TooltipKey.CROSSHAIRS.getKey(), crosshairs);\n    }\n\n    public void setTooltipShared(boolean shared) {\n        putTooltip(ChartKeysUtil.TooltipKey.SHARED.getKey(), shared);\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/chart/model/ChartEntity.java",
    "content": "package com.sohu.cache.web.chart.model;\n\nimport com.sohu.cache.web.chart.key.ChartKeysUtil;\n\nimport java.util.LinkedHashMap;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\n\npublic abstract class ChartEntity {\n    private Map<String, Object> chart;\n    private Map<String, Object> title;\n    private Map<String, Object> subtitle;\n    private Map<String, Object> xAxis;\n    private Map<String, Object> yAxis;\n    private Map<String, Object> tooltip;\n    private Map<String, Object> legend;\n    private List<Map<String, Object>> series;\n\n    public ChartEntity() {\n        // 初始化chart\n        Map<String, Object> chart = new LinkedHashMap<String, Object>();\n        chart.put(ChartKeysUtil.ChartKey.RENDER_TO.getKey(), \"container\");\n        this.setChart(chart);\n        // 初始化title\n        Map<String, Object> title = new LinkedHashMap<String, Object>();\n        title.put(ChartKeysUtil.TitleKey.TEXT.getKey(), \"请设置图表title\");\n        this.setTitle(title);\n        // 初始化subtitle\n        Map<String, Object> subtitle = new LinkedHashMap<String, Object>();\n        this.setSubtitle(subtitle);\n        // 初始化xAxis\n        Map<String, Object> xAxis = new LinkedHashMap<String, Object>();\n        this.setxAxis(xAxis);\n        // 初始化yAxis\n        Map<String, Object> yAxis = new LinkedHashMap<String, Object>();\n        this.setyAxis(yAxis);\n        // 初始化tooltip\n        Map<String, Object> tooltip = new LinkedHashMap<String, Object>();\n        this.setTooltip(tooltip);\n        // 初始化legend\n        Map<String, Object> legend = new LinkedHashMap<String, Object>();\n        this.setLegend(legend);\n        //初始化series\n        List<Map<String, Object>> series = new LinkedList<Map<String, Object>>();\n        this.setSeries(series);\n\n    }\n\n    /**\n     * 所有曲线类型必须设置曲线类型\n     */\n    protected abstract void putChartType();\n\n    /**\n     * 指定容器，即页面div的id\n     * 默认为container，用户可以覆盖\n     *\n     * @param container 页面div的id\n     */\n    public void renderTo(String container) {\n        this.putChart(ChartKeysUtil.ChartKey.RENDER_TO.getKey(), container);\n    }\n\n    /**\n     * 设置chart属性\n     *\n     * @param key\n     * @param value\n     */\n    public void putChart(String key, Object value) {\n        this.getChart().put(key, value);\n    }\n\n    /**\n     * 设置title属性\n     *\n     * @param key\n     * @param value\n     */\n    public void putTitle(String key, Object value) {\n        this.getTitle().put(key, value);\n    }\n\n    /**\n     * 设置subTitle属性\n     *\n     * @param key\n     * @param value\n     */\n    public void putSubTitle(String key, Object value) {\n        this.getSubtitle().put(key, value);\n    }\n\n    /**\n     * @param key\n     * @param value\n     */\n    public void putXAxis(String key, Object value) {\n        this.getxAxis().put(key, value);\n    }\n\n    /**\n     * @param key\n     * @param value\n     */\n    public void putYAxis(String key, Object value) {\n        this.getyAxis().put(key, value);\n    }\n\n    /**\n     * @param key\n     * @param value\n     */\n    public void putTooltip(String key, Object value) {\n        this.getTooltip().put(key, value);\n    }\n\n    /**\n     * @param key\n     * @param value\n     */\n    public void putLegend(String key, Object value) {\n        this.getLegend().put(key, value);\n    }\n\n    /**\n     * @param series\n     */\n    public void putSeries(Map<String, Object> series) {\n        this.getSeries().add(series);\n    }\n\n\n\n\n\n\n\n\n\n\n    // 以下是get set 方法\n    public Map<String, Object> getChart() {\n        return chart;\n    }\n\n    private void setChart(Map<String, Object> chart) {\n        this.chart = chart;\n    }\n\n    public Map<String, Object> getTitle() {\n        return title;\n    }\n\n    private void setTitle(Map<String, Object> title) {\n        this.title = title;\n    }\n\n    public Map<String, Object> getSubtitle() {\n        return subtitle;\n    }\n\n    private void setSubtitle(Map<String, Object> subtitle) {\n        this.subtitle = subtitle;\n    }\n\n    public Map<String, Object> getxAxis() {\n        return xAxis;\n    }\n\n    private void setxAxis(Map<String, Object> xAxis) {\n        this.xAxis = xAxis;\n    }\n\n    public Map<String, Object> getyAxis() {\n        return yAxis;\n    }\n\n    private void setyAxis(Map<String, Object> yAxis) {\n        this.yAxis = yAxis;\n    }\n\n    public Map<String, Object> getTooltip() {\n        return tooltip;\n    }\n\n    private void setTooltip(Map<String, Object> tooltip) {\n        this.tooltip = tooltip;\n    }\n\n    public Map<String, Object> getLegend() {\n        return legend;\n    }\n\n    private void setLegend(Map<String, Object> legend) {\n        this.legend = legend;\n    }\n\n    public List<Map<String, Object>> getSeries() {\n        return series;\n    }\n\n    private void setSeries(List<Map<String, Object>> series) {\n        this.series = series;\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/chart/model/HighchartPoint.java",
    "content": "package com.sohu.cache.web.chart.model;\n\nimport java.text.ParseException;\nimport java.util.Date;\n\nimport org.apache.commons.lang.time.DateUtils;\n\nimport com.sohu.cache.entity.AppCommandStats;\nimport com.sohu.cache.entity.AppStats;\nimport com.sohu.cache.web.util.DateUtil;\n\n/**\n * highchart最简单的点\n * \n * @author leifu\n * @Date 2016年8月1日\n * @Time 下午12:59:29\n */\npublic class HighchartPoint {\n    /**\n     * 时间戳\n     */\n    private Long x;\n\n    /**\n     * 用于表示y轴数量\n     */\n    private Long y;\n    \n    /**\n     * 日期\n     */\n    private String date;\n\n    public HighchartPoint() {\n\n    }\n\n    public HighchartPoint(Long x, Long y, String date) {\n        this.x = x;\n        this.y = y;\n        this.date = date;\n    }\n\n\n    public Long getX() {\n        return x;\n    }\n\n    public void setX(Long x) {\n        this.x = x;\n    }\n\n    public Long getY() {\n        return y;\n    }\n\n    public void setY(Long y) {\n        this.y = y;\n    }\n\n    public String getDate() {\n        return date;\n    }\n\n    public void setDate(String date) {\n        this.date = date;\n    }\n\n    public static HighchartPoint getFromAppCommandStats(AppCommandStats appCommandStats, Date currentDate, int diffDays) throws ParseException {\n        Date collectDate = getDateTime(appCommandStats.getCollectTime());\n        if (!DateUtils.isSameDay(currentDate, collectDate)) {\n            return null;\n        }\n        \n        //显示用的时间\n        String date = null;\n        try {\n            date = DateUtil.formatDate(collectDate, \"yyyy-MM-dd HH:mm\");\n        } catch (Exception e) {\n            date = DateUtil.formatDate(collectDate, \"yyyy-MM-dd HH\");\n        }\n        // y坐标\n        long commandCount = appCommandStats.getCommandCount();\n        // x坐标\n        //为了显示在一个时间范围内\n        if (diffDays > 0) {\n            collectDate = DateUtils.addDays(collectDate, diffDays);\n        }\n        \n        return new HighchartPoint(collectDate.getTime(), commandCount, date);\n    }\n\n    public static HighchartPoint getFromAppStats(AppStats appStat, String statName, Date currentDate, int diffDays) throws ParseException {\n        Date collectDate = getDateTime(appStat.getCollectTime());\n        if (!DateUtils.isSameDay(currentDate, collectDate)) {\n            return null;\n        }\n        //显示用的时间\n        String date = null;\n        try {\n            date = DateUtil.formatDate(collectDate, \"yyyy-MM-dd HH:mm\");\n        } catch (Exception e) {\n            date = DateUtil.formatDate(collectDate, \"yyyy-MM-dd HH\");\n        }\n        // y坐标\n        long count = 0;\n        if (\"hits\".equals(statName)) {\n            count = appStat.getHits();\n        } else if (\"misses\".equals(statName)) {\n            count = appStat.getMisses();\n        } else if (\"usedMemory\".equals(statName)) {\n            count = appStat.getUsedMemory() / 1024 / 1024;\n        } else if (\"netInput\".equals(statName)) {\n            count = appStat.getNetInputByte();\n        } else if (\"netOutput\".equals(statName)) {\n            count = appStat.getNetOutputByte();\n        } else if (\"connectedClient\".equals(statName)) {\n            count = appStat.getConnectedClients();\n        } else if (\"objectSize\".equals(statName)) {\n            count = appStat.getObjectSize();\n        } else if (\"hitPercent\".equals(statName)) {\n            count = appStat.getHitPercent();\n        }\n        //为了显示在一个时间范围内\n        if (diffDays > 0) {\n            collectDate = DateUtils.addDays(collectDate, diffDays);\n        }\n        \n        return new HighchartPoint(collectDate.getTime(), count, date);\n    }\n\n    private static Date getDateTime(long collectTime) throws ParseException {\n        try {\n            return DateUtil.parseYYYYMMddHHMM(String.valueOf(collectTime));\n        } catch (Exception e) {\n            return DateUtil.parseYYYYMMddHH(String.valueOf(collectTime));\n        }\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/chart/model/SimpleChartData.java",
    "content": "package com.sohu.cache.web.chart.model;\n\nimport java.text.ParseException;\nimport java.util.Date;\nimport java.util.concurrent.TimeUnit;\n\nimport com.sohu.cache.entity.AppCommandGroup;\nimport com.sohu.cache.entity.AppCommandStats;\nimport com.sohu.cache.entity.AppStats;\nimport com.sohu.cache.web.util.DateUtil;\n\n/**\n * 用于显示chart的简单对象\n * \n * @author leifu\n * @Time 2014年8月31日\n */\npublic class SimpleChartData {\n\t/**\n\t * 时间戳\n\t */\n\tprivate Long x;\n\n\t/**\n\t * 用于表示y轴数量\n\t */\n\tprivate Long y;\n\n\t/**\n\t * 命令名\n\t */\n\tprivate String commandName;\n\t\n\t/**\n\t * 日期\n\t */\n\tprivate String date;\n\n\tpublic Long getX() {\n\t\treturn x;\n\t}\n\n\tpublic void setX(Long x) {\n\t\tthis.x = x;\n\t}\n\n\tpublic Long getY() {\n\t\treturn y;\n\t}\n\n\tpublic void setY(Long y) {\n\t\tthis.y = y;\n\t}\n\n\tpublic String getCommandName() {\n\t\treturn commandName;\n\t}\n\n\tpublic void setCommandName(String commandName) {\n\t\tthis.commandName = commandName;\n\t}\n\n\tpublic String getDate() {\n        return date;\n    }\n\n    public void setDate(String date) {\n        this.date = date;\n    }\n\n    /**\n\t * AppCommandStats转换为SimpleChartData\n\t * \n\t * @param appCommandStats\n\t * @return\n\t * @throws ParseException\n\t */\n\tpublic static SimpleChartData getFromAppCommandStats(\n\t\t\tAppCommandStats appCommandStats, Integer addDay) throws ParseException {\n\t\tSimpleChartData chartData = new SimpleChartData();\n\t\tlong collectTime = appCommandStats.getCollectTime();\n\t\tString commandName = appCommandStats.getCommandName();\n\t\tlong commandCount = appCommandStats.getCommandCount();\n\t\tDate dateTime = null;\n\t\ttry {\n\t\t\tdateTime = DateUtil.parseYYYYMMddHHMM(String.valueOf(collectTime));\n\t\t} catch (Exception e) {\n\t\t\tdateTime = DateUtil.parseYYYYMMddHH(String.valueOf(collectTime));\n\t\t}\n\t\tLong x = dateTime.getTime();\n\t\tif(addDay != null){\n\t\t    x += TimeUnit.DAYS.toMillis(1) * addDay;\n\t\t}\n\t\tLong y = commandCount;\n\t\tString date = null;\n        try {\n            date = DateUtil.formatDate(dateTime, \"yyyy-MM-dd HH:mm\");\n        } catch (Exception e) {\n            date = DateUtil.formatDate(dateTime, \"yyyy-MM-dd HH\");\n        }\n\t\tchartData.setX(x);\n\t\tchartData.setY(y);\n\t\tchartData.setDate(date);\n\t\tchartData.setCommandName(commandName);\n\t\treturn chartData;\n\t}\n\n\t/**\n\t * AppStats转换为SimpleChartData\n\t * \n\t * @param appStat\n\t * @param statName\n\t *            命中数、丢失数的字段\n\t * @return\n\t * @throws ParseException\n\t */\n\tpublic static SimpleChartData getFromAppStats(AppStats appStat, String statName) throws ParseException {\n\t\tSimpleChartData chartData = new SimpleChartData();\n\t\tlong collectTime = appStat.getCollectTime();\n\t\tlong count = 0;\n\t\tif (\"hits\".equals(statName)) {\n\t\t\tcount = appStat.getHits();\n\t\t} else if (\"misses\".equals(statName)) {\n\t\t\tcount = appStat.getMisses();\n\t\t} else if (\"usedMemory\".equals(statName)){\n\t\t    count = appStat.getUsedMemory() / 1024 / 1024;\n\t\t} else if (\"netInput\".equals(statName)) {\n\t\t    count = appStat.getNetInputByte();\n\t\t} else if (\"netOutput\".equals(statName)) {\n            count = appStat.getNetOutputByte();\n        } else if (\"hitPercent\".equals(statName)) {\n            count = appStat.getHitPercent();\n        }\n\t\tDate dateTime = null;\n\t\ttry {\n\t\t\tdateTime = DateUtil.parseYYYYMMddHHMM(String.valueOf(collectTime));\n\t\t} catch (Exception e) {\n\t\t\tdateTime = DateUtil.parseYYYYMMddHH(String.valueOf(collectTime));\n\t\t}\n\t\tLong x = dateTime.getTime();\n\t\tLong y = count;\n\t\tString date = null;\n\t\ttry {\n            date = DateUtil.formatDate(dateTime, \"yyyy-MM-dd HH:mm\");\n        } catch (Exception e) {\n            date = DateUtil.formatDate(dateTime, \"yyyy-MM-dd HH\");\n        }\n\t\tchartData.setX(x);\n\t\tchartData.setY(y);\n\t\tchartData.setDate(date);\n\n\t\treturn chartData;\n\t}\n\n\t/**\n\t * AppCommandGroup转换为SimpleChartData用于显示pie图\n\t * \n\t * @param appCommandGroup\n\t * @return\n\t */\n\tpublic static SimpleChartData getFromAppCommandGroup(\n\t\t\tAppCommandGroup appCommandGroup) {\n\t\tSimpleChartData chartData = new SimpleChartData();\n\t\tchartData.setCommandName(appCommandGroup.getCommandName());\n\t\tchartData.setY(appCommandGroup.getCount());\n\t\treturn chartData;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"SimpleChartData [x=\" + x + \", y=\" + y + \", commandName=\"\n\t\t\t\t+ commandName + \"]\";\n\t}\n\n\t\n\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/chart/model/SplineChartEntity.java",
    "content": "package com.sohu.cache.web.chart.model;\n\nimport com.sohu.cache.web.chart.key.ChartKeysUtil;\n\nimport java.util.*;\n\npublic class SplineChartEntity extends ChartEntity {\n    public SplineChartEntity() {\n        super();\n        putChartType();\n        setTooltipShared(true);\n    }\n\n    @Override\n    protected void putChartType() {\n        this.getChart().put(ChartKeysUtil.ChartKey.TYPE.getKey(), \"spline\");\n    }\n\n    public void setXAxisCategories(List<Object> xAxisCategories) {\n        setXAxisCategories(xAxisCategories, 14);\n    }\n\n    public void setXAxisCategories(List<Object> xAxisCategories, int totalLabels) {\n        setXAxisCategories(xAxisCategories, totalLabels, 0, -5);\n    }\n\n    public void setXAxisCategories(List<Object> xAxisCategories, int totalLabels, int rotation, int y) {\n        putXAxis(ChartKeysUtil.XAxisKey.CATEGORIES.getKey(), xAxisCategories);\n        if (xAxisCategories.size() >= totalLabels) {\n            Map<String, Object> m = null;\n            if (this.getxAxis().containsKey(ChartKeysUtil.XAxisKey.LABELS.getKey())) {\n                m = (Map<String, Object>) this.getxAxis().get(ChartKeysUtil.XAxisKey.LABELS.getKey());\n            }\n            if (m == null) {\n                m = new LinkedHashMap<String, Object>();\n            }\n            m.put(ChartKeysUtil.XAxisKey.LABELS_STEP.getKey(), xAxisCategories.size() / totalLabels + 1);\n            m.put(ChartKeysUtil.XAxisKey.LABELS_ROTATION.getKey(), rotation);\n            m.put(ChartKeysUtil.XAxisKey.LABELS_Y.getKey(), y);\n            m.put(ChartKeysUtil.XAxisKey.MAX_STAGGER_LINES.getKey(), 1);\n            putXAxis(ChartKeysUtil.XAxisKey.LABELS.getKey(), m);\n        }\n    }\n\n    public void setYAxisTitle(String title) {\n        if (this.getyAxis().containsKey(ChartKeysUtil.YAxisKey.TITLE.getKey())) {\n            ((Map<String, Object>) this.getyAxis().get(ChartKeysUtil.YAxisKey.TITLE.getKey())).put(ChartKeysUtil.YAxisKey.TITLE_TEXT.getKey(), title);\n        } else {\n            Map<String, Object> map = new HashMap<String, Object>();\n            map.put(ChartKeysUtil.YAxisKey.TITLE_TEXT.getKey(), title);\n            putYAxis(ChartKeysUtil.YAxisKey.TITLE.getKey(), map);\n        }\n    }\n\n    public void setTooltipCrosshairs(boolean crosshairs) {\n        putTooltip(ChartKeysUtil.TooltipKey.CROSSHAIRS.getKey(), crosshairs);\n    }\n\n    public void setTooltipShared(boolean shared) {\n        putTooltip(ChartKeysUtil.TooltipKey.SHARED.getKey(), shared);\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/controller/AppClientDataShowController.java",
    "content": "package com.sohu.cache.web.controller;\n\nimport java.text.ParseException;\nimport java.text.SimpleDateFormat;\nimport java.util.ArrayList;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.TimeUnit;\n\nimport javax.annotation.Resource;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\nimport org.apache.commons.collections.CollectionUtils;\nimport org.apache.commons.lang.StringUtils;\nimport org.apache.commons.lang.math.NumberUtils;\nimport org.apache.commons.lang.time.DateUtils;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.servlet.ModelAndView;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.sohu.cache.client.service.AppInstanceClientRelationService;\nimport com.sohu.cache.client.service.ClientReportCostDistriService;\nimport com.sohu.cache.client.service.ClientReportExceptionService;\nimport com.sohu.cache.client.service.ClientReportValueDistriService;\nimport com.sohu.cache.entity.AppClientCostTimeStat;\nimport com.sohu.cache.entity.AppClientCostTimeTotalStat;\nimport com.sohu.cache.entity.AppClientExceptionStat;\nimport com.sohu.cache.entity.AppClientValueDistriSimple;\nimport com.sohu.cache.entity.AppDesc;\nimport com.sohu.cache.entity.AppInstanceClientRelation;\nimport com.sohu.cache.entity.TimeBetween;\nimport com.sohu.cache.stats.instance.InstanceStatsCenter;\nimport com.sohu.cache.web.service.AppService;\nimport com.sohu.cache.web.util.DateUtil;\nimport com.sohu.cache.web.util.Page;\nimport com.sohu.tv.jedis.stat.utils.NumberUtil;\n\n/**\n * 应用客户端统计相关\n * \n * @author leifu\n * @Time 2014年8月31日\n */\n@Controller\n@RequestMapping(\"/client/show\")\npublic class AppClientDataShowController extends BaseController {\n    \n    /**\n     * 客户端耗时服务\n     */\n    @Resource(name = \"clientReportCostDistriService\")\n    private ClientReportCostDistriService clientReportCostDistriService;\n\n    /**\n     * 客户端异常服务\n     */\n    @Resource(name = \"clientReportExceptionService\")\n    private ClientReportExceptionService clientReportExceptionService;\n\n    /**\n     * 客户端值分布服务\n     */\n    @Resource(name = \"clientReportValueDistriService\")\n    private ClientReportValueDistriService clientReportValueDistriService;\n    \n    /**\n     * 应用基本服务\n     */\n    @Resource(name = \"appService\")\n    private AppService appService;\n    \n    /**\n     * 实例信息\n     */\n    @Resource(name = \"instanceStatsCenter\")\n    private InstanceStatsCenter instanceStatsCenter;\n    \n    /**\n     * 应用下节点和客户端关系服务\n     */\n    @Resource(name = \"appInstanceClientRelationService\")\n    private AppInstanceClientRelationService appInstanceClientRelationService;\n\n    /**\n     * 收集数据时间format\n     */\n    private final static String COLLECT_TIME_FORMAT = \"yyyyMMddHHmmss\";\n\n    /**\n     * 应用客户端统计首页\n     * \n     * @param appId 应用id\n     */\n    @RequestMapping(\"/index\")\n    public ModelAndView doIndex(HttpServletRequest request, HttpServletResponse response, Model model) {\n        Long appId = NumberUtils.toLong(request.getParameter(\"appId\"));\n        if (appId == null || appId <= 0) {\n            return new ModelAndView(\"\");\n        }\n        AppDesc appDesc = appService.getByAppId(appId);\n        model.addAttribute(\"appId\", appId);\n        model.addAttribute(\"appDesc\", appDesc);\n        model.addAttribute(\"tabTag\", request.getParameter(\"tabTag\"));\n        model.addAttribute(\"type\", request.getParameter(\"type\"));\n        model.addAttribute(\"startDate\", request.getParameter(\"startDate\"));\n        model.addAttribute(\"endDate\", request.getParameter(\"endDate\"));\n        model.addAttribute(\"exceptionStartDate\", request.getParameter(\"exceptionStartDate\"));\n        model.addAttribute(\"exceptionEndDate\", request.getParameter(\"exceptionEndDate\"));\n        model.addAttribute(\"valueDistriStartDate\", request.getParameter(\"valueDistriStartDate\"));\n        model.addAttribute(\"valueDistriEndDate\", request.getParameter(\"valueDistriEndDate\"));\n        model.addAttribute(\"costDistriStartDate\", request.getParameter(\"costDistriStartDate\"));\n        model.addAttribute(\"costDistriEndDate\", request.getParameter(\"costDistriEndDate\"));\n        model.addAttribute(\"clientIp\", request.getParameter(\"clientIp\"));\n        model.addAttribute(\"pageNo\", request.getParameter(\"pageNo\"));\n        model.addAttribute(\"firstCommand\", request.getParameter(\"firstCommand\"));\n        model.addAttribute(\"timeDimensionality\", request.getParameter(\"timeDimensionality\"));\n        return new ModelAndView(\"client/appClientIndex\");\n    }\n    \n    /**\n     * 客户端异常查询\n     */\n    @RequestMapping(\"/exception\")\n    public ModelAndView doException(HttpServletRequest request, HttpServletResponse response, Model model) {\n        // 1.1 应用信息\n        Long appId = NumberUtils.toLong(request.getParameter(\"appId\"));\n        if (appId <= 0) {\n            return new ModelAndView(\"\");\n        }\n        AppDesc appDesc = appService.getByAppId(appId);\n        model.addAttribute(\"appDesc\", appDesc);\n\n        // 1.2 异常类型\n        int type = NumberUtil.toInt(request.getParameter(\"type\"));\n        model.addAttribute(\"type\", type);\n\n        // 1.3 客户端ip\n        String clientIp = request.getParameter(\"clientIp\");\n        model.addAttribute(\"clientIp\", clientIp);\n\n        // 1.4 日期格式转换\n        TimeBetween timeBetween = new TimeBetween();\n        try {\n            timeBetween = fillWithClientExceptionTime(request, model);\n        } catch (ParseException e) {\n            logger.error(e.getMessage(), e);\n        }\n\n        // 2. 分页查询异常\n        int totalCount = clientReportExceptionService.getAppExceptionCount(appId, timeBetween.getStartTime(), timeBetween.getEndTime(), type, clientIp);\n        int pageNo = NumberUtils.toInt(request.getParameter(\"pageNo\"), 1);\n        int pageSize = NumberUtils.toInt(request.getParameter(\"pageSize\"), 10);\n        Page page = new Page(pageNo,pageSize, totalCount);\n        model.addAttribute(\"page\", page);\n        \n        List<AppClientExceptionStat> appClientExceptionList = clientReportExceptionService.getAppExceptionList(appId,\n                timeBetween.getStartTime(), timeBetween.getEndTime(), type, clientIp, page);\n        model.addAttribute(\"appClientExceptionList\", appClientExceptionList);\n\n        return new ModelAndView(\"client/clientException\");\n    }\n    \n    /**\n     * 异常查询日期格式\n     */\n    private TimeBetween fillWithClientExceptionTime(HttpServletRequest request, Model model) throws ParseException {\n        final String exceptionDateFormat = \"yyyy-MM-dd\";\n        String exceptionStartDateParam = request.getParameter(\"exceptionStartDate\");\n        String exceptionEndDateParam = request.getParameter(\"exceptionEndDate\");\n        Date startDate;\n        Date endDate;\n        if (StringUtils.isBlank(exceptionStartDateParam) || StringUtils.isBlank(exceptionEndDateParam)) {\n            // 如果为空默认取昨天和今天\n            SimpleDateFormat sdf = new SimpleDateFormat(exceptionDateFormat);\n            startDate = sdf.parse(sdf.format(new Date()));\n            endDate = DateUtils.addDays(startDate, 1);\n            exceptionStartDateParam = DateUtil.formatDate(startDate, exceptionDateFormat);\n            exceptionEndDateParam = DateUtil.formatDate(endDate, exceptionDateFormat);\n        } else {\n            endDate = DateUtil.parse(exceptionEndDateParam, exceptionDateFormat);\n            startDate = DateUtil.parse(exceptionStartDateParam, exceptionDateFormat);\n            //限制不能超过7天\n            if (endDate.getTime() - startDate.getTime() > TimeUnit.DAYS.toMillis(7)) {\n                startDate = DateUtils.addDays(endDate, -7);\n            }\n        }\n        // 前端需要\n        model.addAttribute(\"exceptionStartDate\", exceptionStartDateParam);\n        model.addAttribute(\"exceptionEndDate\", exceptionEndDateParam);\n        // 查询后台需要\n        long startTime = NumberUtils.toLong(DateUtil.formatDate(startDate, COLLECT_TIME_FORMAT));\n        long endTime = NumberUtils.toLong(DateUtil.formatDate(endDate, COLLECT_TIME_FORMAT));\n        return new TimeBetween(startTime, endTime, startDate, endDate);\n    }\n\n    /**\n     * 应用客户端耗时统计\n     */\n    @RequestMapping(\"/costDistribute\")\n    public ModelAndView doCostDistribute(HttpServletRequest request, HttpServletResponse response, Model model) {\n        // 1.应用信息\n        Long appId = NumberUtils.toLong(request.getParameter(\"appId\"));\n        if (appId <= 0) {\n            return new ModelAndView(\"\");\n        }\n        AppDesc appDesc = appService.getByAppId(appId);\n        model.addAttribute(\"appDesc\", appDesc);\n        model.addAttribute(\"appId\", appId);\n\n        // 2.获取时间区间\n        TimeBetween timeBetween = new TimeBetween();\n        try {\n            timeBetween = fillWithCostDateFormat(request, model);\n        } catch (ParseException e) {\n            logger.error(e.getMessage(), e);\n        }\n        long startTime = timeBetween.getStartTime();\n        long endTime = timeBetween.getEndTime();\n        Date startDate = timeBetween.getStartDate();\n        \n        // 3.所有命令和第一个命令\n        List<String> allCommands = clientReportCostDistriService.getAppDistinctCommand(appId, startTime, endTime);\n        model.addAttribute(\"allCommands\", allCommands);\n        \n        // 4.所有客户端和实例对应关系\n        List<AppInstanceClientRelation> appInstanceClientRelationList = appInstanceClientRelationService.getAppInstanceClientRelationList(appId, startDate);\n        model.addAttribute(\"appInstanceClientRelationList\", appInstanceClientRelationList);\n        \n        String firstCommand = request.getParameter(\"firstCommand\");\n        if (StringUtils.isBlank(firstCommand) && CollectionUtils.isNotEmpty(allCommands)) {\n            firstCommand = allCommands.get(0);\n            model.addAttribute(\"firstCommand\", firstCommand);\n        } else {\n            model.addAttribute(\"firstCommand\", firstCommand);\n        }\n        \n        // 5.1 应用下客户端和实例的全局耗时统计列表\n        List<AppClientCostTimeTotalStat> appChartStatList = clientReportCostDistriService.getAppClientCommandTotalStat(appId, firstCommand, startTime, endTime);\n        Map<String, Object> resultMap = new HashMap<String, Object>();\n        \n        // 5.2 简化字段\n        List<Map<String, Object>> app = new ArrayList<Map<String, Object>>();\n        for (AppClientCostTimeTotalStat appClientCostTimeTotalStat : appChartStatList) {\n            Map<String, Object> map = new HashMap<String, Object>();\n            map.put(\"timeStamp\", appClientCostTimeTotalStat.getTimeStamp());\n            map.put(\"count\", appClientCostTimeTotalStat.getTotalCount());\n            map.put(\"mean\", appClientCostTimeTotalStat.getMean());\n            map.put(\"median\", appClientCostTimeTotalStat.getMedian());\n            map.put(\"max90\", appClientCostTimeTotalStat.getNinetyPercentMax());\n            map.put(\"max99\", appClientCostTimeTotalStat.getNinetyNinePercentMax());\n            map.put(\"max100\", appClientCostTimeTotalStat.getHundredMax());\n            map.put(\"maxInst\", appClientCostTimeTotalStat.getMaxInstanceHost() + \":\" + appClientCostTimeTotalStat.getMaxInstancePort());\n            map.put(\"maxClient\", appClientCostTimeTotalStat.getMaxClientIp());\n            app.add(map);\n        }\n        \n        resultMap.put(\"app\", app);\n        model.addAttribute(\"appChartStatListJson\", JSONObject.toJSONString(resultMap));\n        \n        return new ModelAndView(\"client/clientCostDistribute\");\n    }\n    \n    /**\n     * 获取耗时时间区间\n     * @throws ParseException \n     */\n    private TimeBetween fillWithCostDateFormat(HttpServletRequest request, Model model) throws ParseException {\n        \n        final String costDistriDateFormat = \"yyyy-MM-dd\";\n        String costDistriStartDateParam = request.getParameter(\"costDistriStartDate\");\n        String costDistriEndDateParam = request.getParameter(\"costDistriEndDate\");\n        Date startDate;\n        Date endDate;\n        if (StringUtils.isBlank(costDistriStartDateParam) || StringUtils.isBlank(costDistriEndDateParam)) {\n            // 如果为空默认取昨天和今天\n            SimpleDateFormat sdf = new SimpleDateFormat(costDistriDateFormat);\n            startDate = sdf.parse(sdf.format(new Date()));\n            endDate = DateUtils.addDays(startDate, 1);\n            costDistriStartDateParam = DateUtil.formatDate(startDate, costDistriDateFormat);\n            costDistriEndDateParam = DateUtil.formatDate(endDate, costDistriDateFormat);\n        } else {\n            endDate = DateUtil.parse(costDistriEndDateParam, costDistriDateFormat);\n            startDate = DateUtil.parse(costDistriStartDateParam, costDistriDateFormat);\n            //限制不能超过1天\n            if (endDate.getTime() - startDate.getTime() > TimeUnit.DAYS.toMillis(1)) {\n                startDate = DateUtils.addDays(endDate, -1);\n            }\n        }\n        // 前端需要\n        model.addAttribute(\"costDistriStartDate\", costDistriStartDateParam);\n        model.addAttribute(\"costDistriEndDate\", costDistriEndDateParam);\n        // 查询后台需要\n        long startTime = NumberUtils.toLong(DateUtil.formatDate(startDate, COLLECT_TIME_FORMAT));\n        long endTime = NumberUtils.toLong(DateUtil.formatDate(endDate, COLLECT_TIME_FORMAT));\n        return new TimeBetween(startTime, endTime, startDate, endDate);\n    }\n\n    /**\n     * 获取指定时间内某个命令某个客户端和实例的统计数据\n     * @param appId\n     */\n    @RequestMapping(\"/getAppClientInstanceCommandCost\")\n    public ModelAndView doGetAppClientInstanceCommandCost(HttpServletRequest request, HttpServletResponse response, Model model) throws ParseException {\n        final String costDistriDateFormat = \"yyyy-MM-dd\";\n        long appId = NumberUtils.toLong(request.getParameter(\"appId\"));\n        //时间转换\n        String costDistriStartDate = request.getParameter(\"costDistriStartDate\");\n        String costDistriEndDate = request.getParameter(\"costDistriEndDate\");\n        Date startDate = DateUtil.parse(costDistriStartDate, costDistriDateFormat);\n        Date endDate = DateUtil.parse(costDistriEndDate, costDistriDateFormat);\n        long startTime = NumberUtils.toLong(DateUtil.formatDate(startDate, COLLECT_TIME_FORMAT));\n        long endTime = NumberUtils.toLong(DateUtil.formatDate(endDate, COLLECT_TIME_FORMAT));\n        \n        String firstCommand = request.getParameter(\"firstCommand\");\n        long instanceId = NumberUtils.toLong(request.getParameter(\"instanceId\"));\n        String clientIp = request.getParameter(\"clientIp\");\n        \n        //客户端和实例统计\n        List<AppClientCostTimeStat> clientInstanceChartStatList = clientReportCostDistriService.getAppCommandClientToInstanceStat(appId, firstCommand, instanceId, clientIp, startTime, endTime);\n        //缩减字段\n        List<Map<String, Object>> clientInstanceStat = new ArrayList<Map<String, Object>>();\n        for (AppClientCostTimeStat appClientCostTimeStat : clientInstanceChartStatList) {\n            Map<String, Object> map = new HashMap<String, Object>();\n            map.put(\"timeStamp\", appClientCostTimeStat.getTimeStamp());\n            map.put(\"count\", appClientCostTimeStat.getCount());\n            map.put(\"mean\", appClientCostTimeStat.getMean());\n            map.put(\"median\", appClientCostTimeStat.getMedian());\n            map.put(\"max90\", appClientCostTimeStat.getNinetyPercentMax());\n            map.put(\"max99\", appClientCostTimeStat.getNinetyNinePercentMax());\n            map.put(\"max100\", appClientCostTimeStat.getHundredMax());\n            clientInstanceStat.add(map);\n        }\n        //生成数据map json\n        Map<String, Object> resultMap = new HashMap<String, Object>();\n        resultMap.put(\"clientInstanceStat\", clientInstanceStat);\n        sendMessage(response, JSONObject.toJSONString(resultMap));\n        return null;\n    }\n\n    /**\n     * 应用客户端值分布相关\n     */\n    @RequestMapping(\"/valueDistribute\")\n    public ModelAndView doValueDistribute(HttpServletRequest request, HttpServletResponse response, Model model)\n            throws ParseException {\n        // 1.1 应用信息\n        Long appId = NumberUtils.toLong(request.getParameter(\"appId\"));\n        if (appId <= 0) {\n            return new ModelAndView(\"\");\n        }\n        AppDesc appDesc = appService.getByAppId(appId);\n        model.addAttribute(\"appDesc\", appDesc);\n\n        // 1.2 时间格式转换\n        TimeBetween timeBetween = new TimeBetween();\n        try {\n            timeBetween = fillWithValueDistriTime(request, model);\n        } catch (ParseException e) {\n            logger.error(e.getMessage(), e);\n        }\n        long startTime = timeBetween.getStartTime();\n        long endTime = timeBetween.getEndTime();\n        \n        //值分布列表\n        List<AppClientValueDistriSimple> appClientValueDistriSimpleList = clientReportValueDistriService.getAppValueDistriList(appId, startTime, endTime);\n        model.addAttribute(\"appClientValueDistriSimpleList\", appClientValueDistriSimpleList);\n        \n        //值分布json\n        model.addAttribute(\"appClientValueDistriSimpleListJson\", JSONObject.toJSONString(appClientValueDistriSimpleList));\n        \n        return new ModelAndView(\"client/clientValueDistribute\");\n    }\n    \n    /**\n     * 值分布日期格式\n     */\n    private TimeBetween fillWithValueDistriTime(HttpServletRequest request, Model model) throws ParseException {\n        final String valueDistriDateFormat = \"yyyy-MM-dd\";\n        String valueDistriStartDateParam = request.getParameter(\"valueDistriStartDate\");\n        String valueDistriEndDateParam = request.getParameter(\"valueDistriEndDate\");\n        Date startDate;\n        Date endDate;\n        if (StringUtils.isBlank(valueDistriStartDateParam) || StringUtils.isBlank(valueDistriEndDateParam)) {\n            // 如果为空默认取昨天和今天\n            SimpleDateFormat sdf = new SimpleDateFormat(valueDistriDateFormat);\n            startDate = sdf.parse(sdf.format(new Date()));\n            endDate = DateUtils.addDays(startDate, 1);\n            valueDistriStartDateParam = DateUtil.formatDate(startDate, valueDistriDateFormat);\n            valueDistriEndDateParam = DateUtil.formatDate(endDate, valueDistriDateFormat);\n        } else {\n            endDate = DateUtil.parse(valueDistriEndDateParam, valueDistriDateFormat);\n            startDate = DateUtil.parse(valueDistriStartDateParam, valueDistriDateFormat);\n            //限制不能超过1天\n            if (endDate.getTime() - startDate.getTime() > TimeUnit.DAYS.toMillis(1)) {\n                startDate = DateUtils.addDays(endDate, -1);\n            }\n        }\n        // 前端需要\n        model.addAttribute(\"valueDistriStartDate\", valueDistriStartDateParam);\n        model.addAttribute(\"valueDistriEndDate\", valueDistriEndDateParam);\n        // 查询后台需要\n        long startTime = NumberUtils.toLong(DateUtil.formatDate(startDate, COLLECT_TIME_FORMAT));\n        long endTime = NumberUtils.toLong(DateUtil.formatDate(endDate, COLLECT_TIME_FORMAT));\n        return new TimeBetween(startTime, endTime, startDate, endDate);\n    }\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/controller/AppController.java",
    "content": "package com.sohu.cache.web.controller;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.sohu.cache.constant.AppAuditType;\nimport com.sohu.cache.constant.AppStatusEnum;\nimport com.sohu.cache.constant.AppUserTypeEnum;\nimport com.sohu.cache.constant.TimeDimensionalityEnum;\nimport com.sohu.cache.entity.*;\nimport com.sohu.cache.stats.app.AppDailyDataCenter;\nimport com.sohu.cache.stats.app.AppDeployCenter;\nimport com.sohu.cache.stats.app.AppStatsCenter;\nimport com.sohu.cache.stats.instance.InstanceStatsCenter;\nimport com.sohu.cache.util.ConstUtils;\nimport com.sohu.cache.util.DemoCodeUtil;\nimport com.sohu.cache.web.vo.AppDetailVO;\nimport com.sohu.cache.web.chart.model.HighchartPoint;\nimport com.sohu.cache.web.chart.model.SimpleChartData;\nimport com.sohu.cache.web.enums.SuccessEnum;\nimport com.sohu.cache.web.util.AppEmailUtil;\nimport com.sohu.cache.web.util.DateUtil;\nimport com.sohu.cache.web.util.Page;\n\nimport net.sf.json.JSONArray;\n\nimport org.apache.commons.collections.CollectionUtils;\nimport org.apache.commons.lang.StringUtils;\nimport org.apache.commons.lang.math.NumberUtils;\nimport org.apache.commons.lang.time.DateUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.servlet.ModelAndView;\n\nimport javax.annotation.Resource;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\nimport java.sql.Timestamp;\nimport java.text.ParseException;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * 应用统计相关\n *\n * @author leifu\n * @Time 2014年8月31日\n */\n@Controller\n@RequestMapping(\"/admin/app\")\npublic class AppController extends BaseController {\n    private Logger logger = LoggerFactory.getLogger(AppController.class);\n    \n    @Resource(name = \"appStatsCenter\")\n    private AppStatsCenter appStatsCenter;\n\n    @Resource(name = \"appEmailUtil\")\n    private AppEmailUtil appEmailUtil;\n\n    @Resource(name = \"appDeployCenter\")\n    private AppDeployCenter appDeployCenter;\n    \n    @Resource(name = \"instanceStatsCenter\")\n    private InstanceStatsCenter instanceStatsCenter;\n    \n    @Resource(name = \"appDailyDataCenter\")\n    private AppDailyDataCenter appDailyDataCenter;\n    \n    /**\n     * 初始化贡献者页面\n     * @return\n     */\n    @RequestMapping(\"/initBecomeContributor\")\n    public ModelAndView doInitBecomeContributor(HttpServletRequest request,\n                        HttpServletResponse response, Model model){\n        model.addAttribute(\"currentUser\", getUserInfo(request));\n        return new ModelAndView(\"app/initBecomeContributor\");\n    }\n    \n    /**\n     * 成为cachecloud贡献者\n     * @param groupName 项目组\n     * @param applyReason 申请理由\n     * @return\n     */\n    @RequestMapping(\"/addBecomeContributor\")\n    public ModelAndView doAddBecomeContributor(HttpServletRequest request,\n                        HttpServletResponse response, Model model, String groupName, String applyReason){\n        appEmailUtil.noticeBecomeContributor(groupName, applyReason, getUserInfo(request));\n        model.addAttribute(\"success\", SuccessEnum.SUCCESS.value());\n        return new ModelAndView(\"\");    \n    }\n    \n    /**\n     * 单个应用首页\n     *\n     * @param appId\n     * @param tabTag       标签名\n     * @param firstCommand 第一条命令\n     * @return\n     * @throws ParseException\n     */\n    @RequestMapping(\"/index\")\n    public ModelAndView index(HttpServletRequest request,\n                              HttpServletResponse response, Model model, Long appId, String tabTag, String firstCommand)\n            throws ParseException {\n        // 如果应用id为空，取第一个应用id\n        if (appId == null) {\n            return new ModelAndView(\"redirect:/admin/app/list\");\n        }\n        \n        // 日期转换\n        String startDateParam = request.getParameter(\"startDate\");\n        String endDateParam = request.getParameter(\"endDate\");\n        if (StringUtils.isBlank(startDateParam) || StringUtils.isBlank(endDateParam)) {\n            Date startDate = new Date();\n            startDateParam = DateUtil.formatDate(startDate, \"yyyy-MM-dd\");\n            endDateParam = DateUtil.formatDate(DateUtils.addDays(startDate, 1), \"yyyy-MM-dd\");\n        }\n        \n        //慢查询\n        String slowLogStartDateParam = request.getParameter(\"slowLogStartDate\");\n        String slowLogEndDateParam = request.getParameter(\"slowLogEndDate\");\n        if (StringUtils.isBlank(slowLogStartDateParam) || StringUtils.isBlank(slowLogEndDateParam)) {\n            Date startDate = new Date();\n            slowLogStartDateParam = DateUtil.formatDate(startDate, \"yyyy-MM-dd\");\n            slowLogEndDateParam = DateUtil.formatDate(DateUtils.addDays(startDate, 1), \"yyyy-MM-dd\");\n        }\n        \n        //日报\n        String dailyDateParam = request.getParameter(\"dailyDate\");\n        if (StringUtils.isBlank(dailyDateParam)) {\n            dailyDateParam = DateUtil.formatDate(DateUtils.addDays(new Date(), -1), \"yyyy-MM-dd\");\n        }\n        \n        model.addAttribute(\"startDate\", startDateParam);\n        model.addAttribute(\"endDate\", endDateParam);\n        model.addAttribute(\"slowLogStartDate\", slowLogStartDateParam);\n        model.addAttribute(\"slowLogEndDate\", slowLogEndDateParam);\n        model.addAttribute(\"dailyDate\", dailyDateParam);\n        model.addAttribute(\"appId\", appId);\n        model.addAttribute(\"tabTag\", tabTag);\n        model.addAttribute(\"firstCommand\", firstCommand);\n        \n\n        return new ModelAndView(\"app/userAppsIndex\");\n\n    }\n\n    \n    /**\n     * 应用统计相关\n     */\n    @RequestMapping(\"/stat\")\n    public ModelAndView appStat(HttpServletRequest request,\n                                HttpServletResponse response, Model model, Long appId) throws ParseException {\n        // 1.获取app的VO\n        AppDetailVO appDetail = appStatsCenter.getAppDetail(appId);\n        model.addAttribute(\"appDetail\", appDetail);\n\n        // 2. 时间\n        TimeBetween timeBetween = getTimeBetween(request, model, \"startDate\", \"endDate\");\n        long beginTime = timeBetween.getStartTime();\n        long endTime = timeBetween.getEndTime();\n        \n        // 3.是否超过1天\n        if (endTime - beginTime > TimeUnit.DAYS.toMillis(1)) {\n            model.addAttribute(\"betweenOneDay\", 0);\n        } else {\n            model.addAttribute(\"betweenOneDay\", 1);\n        }\n\n        // 4. top5命令\n        List<AppCommandStats> top5Commands = appStatsCenter.getTopLimitAppCommandStatsList(appId, beginTime, endTime, 5);\n        model.addAttribute(\"top5Commands\", top5Commands);\n        \n        // 5.峰值\n        List<AppCommandStats> top5ClimaxList = new ArrayList<AppCommandStats>();\n        if (CollectionUtils.isNotEmpty(top5Commands)) {\n            for (AppCommandStats appCommandStats : top5Commands) {\n                AppCommandStats temp = appStatsCenter.getCommandClimax(appId, beginTime, endTime, appCommandStats.getCommandName());\n                if (temp != null) {\n                    top5ClimaxList.add(temp);\n                }\n            }\n        }\n        model.addAttribute(\"top5ClimaxList\", top5ClimaxList);\n\n        model.addAttribute(\"appId\", appId);\n        return new ModelAndView(\"app/appStat\");\n    }\n    \n    /**\n     * 命令曲线\n     * @param firstCommand 第一条命令\n     */\n    @RequestMapping(\"/commandAnalysis\")\n    public ModelAndView appCommandAnalysis(HttpServletRequest request,\n                                           HttpServletResponse response, Model model, Long appId, String firstCommand) throws ParseException {\n        // 1.获取app的VO\n        AppDetailVO appDetail = appStatsCenter.getAppDetail(appId);\n        model.addAttribute(\"appDetail\", appDetail);\n\n        // 2.返回日期\n        TimeBetween timeBetween = getTimeBetween(request, model, \"startDate\", \"endDate\");\n\n        // 3.是否超过1天\n        if (timeBetween.getEndTime() - timeBetween.getStartTime() > TimeUnit.DAYS.toMillis(1)) {\n            model.addAttribute(\"betweenOneDay\", 0);\n        } else {\n            model.addAttribute(\"betweenOneDay\", 1);\n        }\n\n        // 4.获取top命令\n        List<AppCommandStats> allCommands = appStatsCenter.getTopLimitAppCommandStatsList(appId, timeBetween.getStartTime(), timeBetween.getEndTime(), 20);\n        model.addAttribute(\"allCommands\", allCommands);\n        if (StringUtils.isBlank(firstCommand) && CollectionUtils.isNotEmpty(allCommands)) {\n            model.addAttribute(\"firstCommand\", allCommands.get(0).getCommandName());\n        } else {\n            model.addAttribute(\"firstCommand\", firstCommand);\n        }\n        model.addAttribute(\"appId\", appId);\n        // 返回标签名\n        return new ModelAndView(\"app/appCommandAnalysis\");\n    }\n\n    /**\n     * 应用故障\n     */\n    @RequestMapping(\"/fault\")\n    public ModelAndView appFault(HttpServletRequest request,\n                                 HttpServletResponse response, Model model) {\n\n        return new ModelAndView(\"app/appFault\");\n    }\n\n    /**\n     * 应用拓扑图\n     *\n     * @param appId\n     * @return\n     */\n    @RequestMapping(\"/topology\")\n    public ModelAndView statTopology(HttpServletRequest request,\n                                     HttpServletResponse response, Long appId, Model model) {\n        //应用信息\n        AppDesc appDesc = appService.getByAppId(appId);\n        model.addAttribute(\"appDesc\", appDesc);\n        //实例相关信息(包含统计)\n        fillAppInstanceStats(appId, model);\n        return new ModelAndView(\"app/appTopology\");\n    }\n    \n    /**\n     * 应用机器拓扑图\n     *\n     * @param appId\n     * @return\n     */\n    @RequestMapping(\"/machineInstancesTopology\")\n    public ModelAndView machineInstancesTopology(HttpServletRequest request,\n                                     HttpServletResponse response, Long appId, Model model) {\n        //应用信息\n        AppDesc appDesc = appService.getByAppId(appId);\n        model.addAttribute(\"appDesc\", appDesc);\n        //拓扑\n        fillAppMachineInstanceTopology(appId, model);\n        return new ModelAndView(\"app/appMachineInstancesTopology\");\n    }\n\n    /**\n     * 应用基本信息\n     *\n     * @param appId 应用id\n     */\n    @RequestMapping(\"/detail\")\n    public ModelAndView appDetail(HttpServletRequest request,\n                                  HttpServletResponse response, Model model, Long appId) {\n        // 获取应用vo\n        AppDetailVO appDetail = appStatsCenter.getAppDetail(appId);\n        model.addAttribute(\"appDetail\", appDetail);\n        return new ModelAndView(\"app/appDetail\");\n    }\n\n    /**\n     * 获取某个命令时间分布图\n     *\n     * @param appId 应用id\n     * @throws ParseException\n     */\n    @RequestMapping(\"/getCommandStats\")\n    public ModelAndView getCommandStats(HttpServletRequest request,\n                                        HttpServletResponse response, Model model, Long appId) throws ParseException {\n        TimeBetween timeBetween = getJsonTimeBetween(request);\n        long beginTime = timeBetween.getStartTime();\n        long endTime = timeBetween.getEndTime();\n        // 命令参数\n        String commandName = request.getParameter(\"commandName\");\n        List<AppCommandStats> appCommandStatsList;\n        if (StringUtils.isNotBlank(commandName)) {\n            appCommandStatsList = appStatsCenter.getCommandStatsList(appId, beginTime, endTime, commandName);\n        } else {\n            appCommandStatsList = appStatsCenter.getCommandStatsList(appId, beginTime, endTime);\n        }\n        String result = assembleJson(appCommandStatsList);\n        write(response, result);\n        return null;\n    }\n    \n    /**\n     * 获取某个命令时间分布图\n     *\n     * @param appId 应用id\n     * @throws ParseException\n     */\n    @RequestMapping(\"/getMutiDatesCommandStats\")\n    public ModelAndView getMutiDatesCommandStats(HttpServletRequest request,\n                                        HttpServletResponse response, Model model, Long appId) throws ParseException {\n        TimeBetween timeBetween = getJsonTimeBetween(request);\n        // 命令参数\n        String commandName = request.getParameter(\"commandName\");\n        List<AppCommandStats> appCommandStatsList;\n        if (StringUtils.isNotBlank(commandName)) {\n            appCommandStatsList = appStatsCenter.getCommandStatsListV2(appId, timeBetween.getStartTime(), timeBetween.getEndTime(), TimeDimensionalityEnum.MINUTE, commandName);\n        } else {\n            appCommandStatsList = appStatsCenter.getCommandStatsListV2(appId, timeBetween.getStartTime(), timeBetween.getEndTime(), TimeDimensionalityEnum.MINUTE);\n        }\n        String result = assembleMutilDateAppCommandJsonMinute(appCommandStatsList, timeBetween.getStartDate(), timeBetween.getEndDate());\n        model.addAttribute(\"data\", result);\n        return new ModelAndView(\"\");\n    }\n\n    \n    /**\n     * 获取命中率、丢失率等分布\n     *\n     * @param appId    应用id\n     * @param statName 统计项(hit,miss等)\n     * @throws ParseException\n     */\n    @RequestMapping(\"/getAppStats\")\n    public ModelAndView getAppStats(HttpServletRequest request,\n                                    HttpServletResponse response, Model model, Long appId,\n                                    String statName) throws ParseException {\n        TimeBetween timeBetween = getJsonTimeBetween(request);\n        List<AppStats> appStats = appStatsCenter.getAppStatsListByMinuteTime(appId, timeBetween.getStartTime(), timeBetween.getEndTime());\n        String result = assembleAppStatsJson(appStats, statName);\n        write(response, result);\n        return null;\n    }\n\n    /**\n     * 多命令\n     * @param appId\n     * @param statName\n     * @return\n     * @throws ParseException\n     */\n    @RequestMapping(\"/getMutiStatAppStats\")\n    public ModelAndView getMutiStatAppStats(HttpServletRequest request,\n                                    HttpServletResponse response, Model model, Long appId) throws ParseException {\n        String statNames = request.getParameter(\"statName\");\n        List<String> statNameList = Arrays.asList(statNames.split(ConstUtils.COMMA));\n        TimeBetween timeBetween = getJsonTimeBetween(request);\n        List<AppStats> appStats = appStatsCenter.getAppStatsList(appId, timeBetween.getStartTime(), timeBetween.getEndTime(), TimeDimensionalityEnum.MINUTE);\n        String result = assembleMutiStatAppStatsJsonMinute(appStats, statNameList, timeBetween.getStartDate());\n        model.addAttribute(\"data\", result);\n        return new ModelAndView(\"\");\n    }\n\n    /**\n     * 获取命中率、丢失率等分布\n     *\n     * @param appId    应用id\n     * @param statName 统计项(hit,miss等)\n     * @throws ParseException\n     */\n    @RequestMapping(\"/getMutiDatesAppStats\")\n    public ModelAndView getMutiDatesAppStats(HttpServletRequest request,\n                                    HttpServletResponse response, Model model, Long appId,\n                                    String statName, Integer addDay) throws ParseException {\n        TimeBetween timeBetween = getJsonTimeBetween(request);\n        List<AppStats> appStats = appStatsCenter.getAppStatsList(appId, timeBetween.getStartTime(), timeBetween.getEndTime(), TimeDimensionalityEnum.MINUTE);\n        String result = assembleMutilDateAppStatsJsonMinute(appStats, statName, timeBetween.getStartDate(), timeBetween.getEndDate());\n        model.addAttribute(\"data\", result);\n        return new ModelAndView(\"\");\n    }\n    \n    /**\n     * 获取指定时间内某个应用全部实例的统计信息\n     * @param appId\n     */\n    @RequestMapping(\"/appInstanceNetStat\")\n    public ModelAndView appInstanceNetStat(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) throws ParseException {\n        // 应用基本信息\n        AppDesc appDesc = appService.getByAppId(appId);\n        model.addAttribute(\"appDesc\", appDesc);\n        model.addAttribute(\"appId\", appId);\n\n        // 日期格式转换\n        getTimeBetween(request, model, \"startDate\", \"endDate\");\n        \n        return new ModelAndView(\"app/appInstanceNetStat\");\n    }\n    \n    \n    \n    /**\n     * 获取指定时间内某个应用全部实例的统计信息\n     * @param appId 应用流量\n     */\n    @RequestMapping(\"/getAppInstancesNetStat\")\n    public ModelAndView getAppInstancesNetStat(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) throws ParseException {\n        //时间转换\n        TimeBetween timeBetween = getJsonTimeBetween(request);\n        \n        //缩减字段\n        String netInCommand = \"total_net_input_bytes\";\n        String netOutCommand = \"total_net_output_bytes\";\n        Map<String,String> commandMap = new HashMap<String, String>();\n        commandMap.put(netInCommand, \"i\");\n        commandMap.put(netOutCommand, \"o\");\n        \n        //获取应用下所有实例网络流量统计\n        Map<Integer, Map<String, List<InstanceCommandStats>>> appInstancesNetStat = instanceStatsCenter\n                .getStandardStatsList(appId, timeBetween.getStartTime(), timeBetween.getEndTime(),\n                        Arrays.asList(netInCommand, netOutCommand));\n\n        //解析成json数组\n        List<Map<String, Object>> appInstancesNetStatList = new ArrayList<Map<String, Object>>();\n        for (Entry<Integer, Map<String, List<InstanceCommandStats>>> entry : appInstancesNetStat.entrySet()) {\n            Integer instanceId = entry.getKey();\n            \n            //实例基本信息\n            Map<String, Object> instanceStatMap = new HashMap<String, Object>();\n            instanceStatMap.put(\"instanceId\", instanceId);\n            InstanceInfo instanceInfo = instanceStatsCenter.getInstanceInfo(instanceId);\n            instanceStatMap.put(\"instanceInfo\", instanceInfo.getIp() + \":\" + instanceInfo.getPort());\n            \n            //每个实例的统计信息\n            List<Map<String, Object>> instanceNetStatMapList = new ArrayList<Map<String, Object>>();\n            instanceStatMap.put(\"instanceNetStatMapList\", instanceNetStatMapList);\n            appInstancesNetStatList.add(instanceStatMap);\n\n            //记录输入和输出流量\n            Map<String, List<InstanceCommandStats>> map = entry.getValue();\n            List<InstanceCommandStats> instanceCommandStatsList = new ArrayList<InstanceCommandStats>();\n            instanceCommandStatsList.addAll(map.get(netInCommand));\n            instanceCommandStatsList.addAll(map.get(netOutCommand));\n\n            Map<Long, Map<String, Object>> total = new HashMap<Long, Map<String, Object>>();\n            for (InstanceCommandStats instanceCommandStat : instanceCommandStatsList) {\n                //用timestamp作为key,保证输入和输出流量在一个Map统计里\n                long timestamp = instanceCommandStat.getTimeStamp();\n                long commandCount = instanceCommandStat.getCommandCount();\n                String command = instanceCommandStat.getCommandName();\n                //精简字段\n                command = commandMap.get(command);\n                if (total.containsKey(timestamp)) {\n                    Map<String,Object> tmpMap = total.get(timestamp);\n                    tmpMap.put(command, commandCount);\n                } else {\n                    Map<String,Object> tmpMap = new HashMap<String, Object>();\n                    tmpMap.put(\"t\", timestamp);\n                    tmpMap.put(command, commandCount);\n                    total.put(timestamp, tmpMap);\n                    instanceNetStatMapList.add(tmpMap);\n                }\n            }\n        }\n        \n        String result = JSONObject.toJSONString(appInstancesNetStatList);\n        write(response, result);\n        return null;\n    }\n    \n\n    /**\n     *\n     * @param appId\n     * @throws ParseException\n     */\n    @RequestMapping(\"/getTop5Commands\")\n    public ModelAndView getAppTop5Commands(HttpServletRequest request,\n                                           HttpServletResponse response, Model model, Long appId) throws ParseException {\n        TimeBetween timeBetween = getJsonTimeBetween(request);\n        List<AppCommandStats> appCommandStats = appStatsCenter.getTop5AppCommandStatsList(appId, timeBetween.getStartTime(), timeBetween.getEndTime());\n        String result = assembleJson(appCommandStats);\n        write(response, result);\n        return null;\n    }\n\n    /**\n     * 应用各个命令分布情况\n\n     *\n     * @param appId 应用id\n     * @throws ParseException\n     */\n    @RequestMapping(\"/appCommandDistribute\")\n    public ModelAndView appCommandDistribute(HttpServletRequest request,\n                                             HttpServletResponse response, Model model, Long appId) throws ParseException {\n        TimeBetween timeBetween = getJsonTimeBetween(request);\n        List<AppCommandGroup> appCommandGroupList = appStatsCenter.getAppCommandGroup(appId, timeBetween.getStartTime(), timeBetween.getEndTime());\n        String result = assembleGroupJson(appCommandGroupList);\n        write(response, result);\n        return null;\n    }\n    \n    \n    /**\n     * 应用列表\n     *\n     * @param userId\n     * @return\n     */\n    @RequestMapping(value = \"/list\")\n    public ModelAndView doAppList(HttpServletRequest request,\n                                  HttpServletResponse response, Model model, AppSearch appSearch) {\n        // 1.获取该用户能够读取的应用列表,没有返回申请页面\n        AppUser currentUser = getUserInfo(request);\n        model.addAttribute(\"currentUser\", currentUser);\n        int userAppCount = appService.getUserAppCount(currentUser.getId());\n        if (userAppCount == 0 && !AppUserTypeEnum.ADMIN_USER.value().equals(currentUser.getType())) {\n            return new ModelAndView(\"redirect:/admin/app/init\");\n        }\n        // 默认只出运行中的\n        if (appSearch.getAppStatus() == null) {\n            appSearch.setAppStatus(AppStatusEnum.STATUS_PUBLISHED.getStatus());\n        }\n        // 2.1 分页相关\n        int totalCount = appService.getAppDescCount(currentUser, appSearch);\n        int pageNo = NumberUtils.toInt(request.getParameter(\"pageNo\"), 1);\n        int pageSize = NumberUtils.toInt(request.getParameter(\"pageSize\"), 10);\n        Page page = new Page(pageNo,pageSize, totalCount);\n        model.addAttribute(\"page\", page);\n\n        // 2.2 查询指定时间客户端异常\n        appSearch.setPage(page);\n        List<AppDesc> apps = appService.getAppDescList(currentUser, appSearch);\n        // 2.3 应用列表\n        List<AppDetailVO> appDetailList = new ArrayList<AppDetailVO>();\n        model.addAttribute(\"appDetailList\", appDetailList);\n\n        // 3. 全局统计\n        long totalApplyMem = 0;\n        long totalUsedMem = 0;\n        long totalApps = 0;\n        if (apps != null && apps.size() > 0) {\n            for (AppDesc appDesc : apps) {\n                AppDetailVO appDetail = appStatsCenter.getAppDetail(appDesc.getAppId());\n                appDetailList.add(appDetail);\n                totalApplyMem += appDetail.getMem();\n                totalUsedMem += appDetail.getMemUsePercent() * appDetail.getMem() / 100.0;\n                totalApps++;\n            }\n        }\n        model.addAttribute(\"totalApps\", totalApps);\n        model.addAttribute(\"totalApplyMem\", totalApplyMem);\n        model.addAttribute(\"totalUsedMem\", totalUsedMem);\n\n        return new ModelAndView(\"app/appList\");\n    }\n\n    /**\n     * 初始化应用申请\n     */\n    @RequestMapping(value = \"/init\")\n    public ModelAndView doAppInit(HttpServletRequest request,\n                                  HttpServletResponse response, Model model) {\n        return new ModelAndView(\"app/appInit\");\n    }\n\n    /**\n     * 添加应用\n     *\n     * @param appDesc 应用实体\n     * @param memSize 申请容量(G)\n     * @return\n     */\n    @RequestMapping(value = \"/add\", method = RequestMethod.POST)\n    public ModelAndView doAppAdd(HttpServletRequest request,\n                                 HttpServletResponse response, Model model, AppDesc appDesc, String memSize) {\n        AppUser appUser = getUserInfo(request);\n        if (appDesc != null) {\n            Timestamp now = new Timestamp(new Date().getTime());\n            appDesc.setCreateTime(now);\n            appDesc.setPassedTime(now);\n            appDesc.setVerId(1);\n            appDesc.setStatus((short) AppStatusEnum.STATUS_ALLOCATED.getStatus());\n            appDeployCenter.createApp(appDesc, appUser, memSize);\n        }\n        return new ModelAndView(\"redirect:/admin/app/list\");\n    }\n\n    /**\n     * 查看应用名是否存在\n     *\n     * @param appName\n     * @return\n     */\n    @RequestMapping(value = \"/checkAppNameExist\")\n    public ModelAndView doCheckAppNameExist(HttpServletRequest request,\n                                            HttpServletResponse response, Model model, String appName) {\n        AppDesc appDesc = appService.getAppByName(appName);\n        if (appDesc != null) {\n            write(response, String.valueOf(SuccessEnum.SUCCESS.value()));\n        } else {\n            write(response, String.valueOf(SuccessEnum.FAIL.value()));\n        }\n        return null;\n    }\n\n    /**\n     * 应用命令查询\n     *\n     * @param appId\n     * @return\n     */\n    @RequestMapping(\"/command\")\n    public ModelAndView command(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) {\n        if (appId != null && appId > 0) {\n            model.addAttribute(\"appId\", appId);\n        }\n        return new ModelAndView(\"app/appCommand\");\n    }\n\n    /**\n     * 执行应用命令\n     *\n     * @param appId\n     * @return\n     */\n    @RequestMapping(\"/commandExecute\")\n    public ModelAndView commandExecute(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) {\n        if (appId != null && appId > 0) {\n            model.addAttribute(\"appId\", appId);\n            String command = request.getParameter(\"command\");\n            String result = appStatsCenter.executeCommand(appId, command);\n            model.addAttribute(\"result\", result);\n        } else {\n            model.addAttribute(\"result\", \"error\");\n        }\n        return new ModelAndView(\"app/commandExecute\");\n    }\n\n    /**\n     * 删除应用下的指定用户\n     *\n     * @param userId\n     * @param appId\n     * @return\n     */\n    @RequestMapping(value = \"/deleteAppToUser\")\n    public ModelAndView doDeleteAppToUser(HttpServletRequest request,\n                                          HttpServletResponse response, Model model, Long userId, Long appId) {\n        if (userId != null && appId != null) {\n            // 验证删除权限\n            AppUser currentUser = getUserInfo(request);\n            List<AppToUser> appToUsers = appService.getAppToUserList(appId);\n            if (CollectionUtils.isNotEmpty(appToUsers)) {\n                for (AppToUser appToUser : appToUsers) {\n                    if (appToUser.getUserId().equals(currentUser.getId())) {\n                        write(response, String.valueOf(SuccessEnum.FAIL.value()));\n                    }\n                }\n            }\n            appService.deleteAppToUser(appId, userId);\n            write(response, String.valueOf(SuccessEnum.SUCCESS.value()));\n        } else {\n            write(response, String.valueOf(SuccessEnum.FAIL.value()));\n        }\n        return null;\n    }\n    \n    /**\n     * 更新用户\n     * @param name\n     * @param chName\n     * @param email\n     * @param mobile\n     * @param type\n     * @param userId\n     * @return\n     */\n    @RequestMapping(value = \"/changeAppUserInfo\")\n    public ModelAndView doAddUser(HttpServletRequest request,\n            HttpServletResponse response, Model model, String name, String chName, String email, String mobile,\n            Integer type, Long userId) {\n        // 后台暂时不对参数进行验证\n        AppUser appUser = AppUser.buildFrom(userId, name, chName, email, mobile, type);\n        try {\n            if (userId == null) {\n                userService.save(appUser);\n            } else {\n                userService.update(appUser);\n            }\n            write(response, String.valueOf(SuccessEnum.SUCCESS.value()));\n        } catch (Exception e) {\n            write(response, String.valueOf(SuccessEnum.FAIL.value()));\n            logger.error(e.getMessage(), e);\n        }\n        return null;\n    }\n    \n\n    /**\n     * 扩容申请\n     *\n     * @param appId          应用id\n     * @param applyMemSize   申请容量\n     * @param appScaleReason 申请原因\n     * @return\n     */\n    @RequestMapping(value = \"/scale\")\n    public ModelAndView doScaleApp(HttpServletRequest request,\n                                   HttpServletResponse response, Model model, Long appId, String applyMemSize, String appScaleReason) {\n        AppUser appUser = getUserInfo(request);\n        AppDesc appDesc = appService.getByAppId(appId);\n        AppAudit appAudit = appService.saveAppScaleApply(appDesc, appUser, applyMemSize, appScaleReason, AppAuditType.APP_SCALE);\n        appEmailUtil.noticeAppResult(appDesc, appAudit);\n        write(response, String.valueOf(SuccessEnum.SUCCESS.value()));\n        return null;\n    }\n\n    /**\n     * 应用修改配置申请\n     *\n     * @param appId          应用id\n     * @param appConfigKey   配置项\n     * @param appConfigValue 配置值\n     * @return\n     */\n    @RequestMapping(value = \"/changeAppConfig\")\n    public ModelAndView doChangeAppConfig(HttpServletRequest request,\n                                          HttpServletResponse response, Model model, Long appId, Long instanceId, String appConfigKey, String appConfigValue, String appConfigReason) {\n        AppUser appUser = getUserInfo(request);\n        AppDesc appDesc = appService.getByAppId(appId);\n        AppAudit appAudit = appService.saveAppChangeConfig(appDesc, appUser, instanceId, appConfigKey, appConfigValue,appConfigReason, AppAuditType.APP_MODIFY_CONFIG);\n        appEmailUtil.noticeAppResult(appDesc, appAudit);\n        write(response, String.valueOf(SuccessEnum.SUCCESS.value()));\n        return null;\n    }\n    \n    /**\n     * 实例修改配置申请\n     *\n     * @param appId          应用id\n     * @param appConfigKey   配置项\n     * @param appConfigValue 配置值\n     * @return\n     */\n    @RequestMapping(value = \"/changeInstanceConfig\")\n    public ModelAndView doChangeInstanceConfig(HttpServletRequest request,\n                                          HttpServletResponse response, Model model, Long appId, Long instanceId, String instanceConfigKey, String instanceConfigValue, String instanceConfigReason) {\n        AppUser appUser = getUserInfo(request);\n        AppDesc appDesc = appService.getByAppId(appId);\n        AppAudit appAudit = appService.saveInstanceChangeConfig(appDesc, appUser, instanceId, instanceConfigKey, instanceConfigValue, instanceConfigReason, AppAuditType.INSTANCE_MODIFY_CONFIG);\n        appEmailUtil.noticeAppResult(appDesc, appAudit);\n        write(response, String.valueOf(SuccessEnum.SUCCESS.value()));\n        return null;\n    }\n\n    /**\n     * 添加应用和用户对应关系\n     *\n     * @param appId    应用id\n     * @param userName 用户名(邮箱前缀)\n     * @return\n     */\n    @RequestMapping(value = \"/addAppToUser\")\n    public ModelAndView doAddAppToUser(HttpServletRequest request,\n                                       HttpServletResponse response, Model model, Long appId, String userName) {\n        if (StringUtils.isNotBlank(userName)) {\n            AppUser needAddAppUser = userService.getByName(userName);\n            if (needAddAppUser != null) {\n                appService.saveAppToUser(appId, needAddAppUser.getId());\n                write(response, String.valueOf(SuccessEnum.SUCCESS.value()));\n            } else {\n                write(response, String.valueOf(SuccessEnum.FAIL.value()));\n            }\n        }\n        return null;\n    }\n\n    /**\n     * 修改应用报警配置\n     */\n    @RequestMapping(value = \"/changeAppAlertConfig\")\n    public ModelAndView doChangeAppAlertConfig(HttpServletRequest request,\n                                               HttpServletResponse response, Model model) {\n\n        long appId = NumberUtils.toLong(request.getParameter(\"appId\"), -1);\n        int memAlertValue =  NumberUtils.toInt(request.getParameter(\"memAlertValue\"), -1);\n        int clientConnAlertValue =  NumberUtils.toInt(request.getParameter(\"clientConnAlertValue\"), -1);\n        SuccessEnum result = appService.changeAppAlertConfig(appId, memAlertValue,clientConnAlertValue, getUserInfo(request));\n        write(response, String.valueOf(result.value()));\n        return null;\n    }\n    \n    /**\n     * 修改应用信息\n     */\n    @RequestMapping(value = \"/updateAppDetail\")\n    public ModelAndView doUpdateAppDetail(HttpServletRequest request,\n                                               HttpServletResponse response, Model model) {\n        long appId = NumberUtils.toLong(request.getParameter(\"appId\"), 0);\n        AppUser appUser = getUserInfo(request);\n        logger.warn(\"{} want to update appId={} info!\", appUser.getName(), appId);\n        String appDescName =  request.getParameter(\"appDescName\");\n        String appDescIntro =  request.getParameter(\"appDescIntro\");\n        String officer = request.getParameter(\"officer\");\n        SuccessEnum successEnum = SuccessEnum.SUCCESS;\n        if (appId <= 0 || StringUtils.isBlank(appDescName) || StringUtils.isBlank(appDescIntro) || StringUtils.isBlank(officer)) {\n            successEnum = SuccessEnum.FAIL;\n        } else {\n            try {\n                AppDesc appDesc = appService.getByAppId(appId);\n                appDesc.setName(appDescName);\n                appDesc.setIntro(appDescIntro);\n                appDesc.setOfficer(officer);\n                appService.update(appDesc);\n            } catch (Exception e) {\n                logger.error(e.getMessage(), e);\n                successEnum = SuccessEnum.FAIL;\n            }\n        }\n        write(response, String.valueOf(successEnum.value()));\n        return null;\n    }\n    \n\n    @RequestMapping(value = \"/demo\")\n    public ModelAndView doDemo(HttpServletRequest request, HttpServletResponse response, Long appId, Model model) {\n        if (appId != null && appId > 0) {\n            AppDesc appDesc = appService.getByAppId(appId);\n            List<String> code = DemoCodeUtil.getCode(appDesc.getType(), appDesc.getAppId());\n            List<String> dependency = DemoCodeUtil.getDependencyRedis();\n            List<String> springConfig = DemoCodeUtil.getSpringConfig(appDesc.getType(), appDesc.getAppId());\n            String restApi = DemoCodeUtil.getRestAPI(appDesc.getType(), appDesc.getAppId());\n            \n            if(CollectionUtils.isNotEmpty(springConfig) && springConfig.size() > 0){\n                model.addAttribute(\"springConfig\", springConfig);\n            }\n            model.addAttribute(\"dependency\",dependency);\n            model.addAttribute(\"code\", code);\n            model.addAttribute(\"status\", 1);\n            model.addAttribute(\"restApi\", restApi);\n        } else {\n            model.addAttribute(\"status\", 0);\n        }\n        return new ModelAndView(\"app/appDemo\");\n    }\n\n    /**\n     * 应用日报查询\n     */\n    @RequestMapping(\"/daily\")\n    public ModelAndView appDaily(HttpServletRequest request,\n                                  HttpServletResponse response, Model model, Long appId) throws ParseException {\n        // 1. 应用信息\n        AppDesc appDesc = appService.getByAppId(appId);\n        model.addAttribute(\"appDesc\", appDesc);\n\n        // 2. 日期\n        String dailyDateParam = request.getParameter(\"dailyDate\");\n        Date date;\n        if (StringUtils.isBlank(dailyDateParam)) {\n            date = DateUtils.addDays(new Date(), -1);\n        } else {\n            date = DateUtil.parseYYYY_MM_dd(dailyDateParam);\n        }\n        model.addAttribute(\"dailyDate\", dailyDateParam);\n\n        // 3. 日报\n        AppDailyData appDailyData = appDailyDataCenter.getAppDailyData(appId, date);\n        model.addAttribute(\"appDailyData\", appDailyData);\n\n        return new ModelAndView(\"app/appDaily\");\n    }\n\n    /**\n     * 应用历史慢查询\n     * @param appId\n     * @return\n     * @throws ParseException \n     */\n    @RequestMapping(\"/slowLog\")\n    public ModelAndView appSlowLog(HttpServletRequest request,\n                                  HttpServletResponse response, Model model, Long appId) throws ParseException {\n        // 应用基本信息\n        AppDesc appDesc = appService.getByAppId(appId);\n        model.addAttribute(\"appDesc\", appDesc);\n        \n        // 开始和结束日期\n        TimeBetween timeBetween = getTimeBetween(request, model, \"slowLogStartDate\", \"slowLogEndDate\");\n        Date startDate = timeBetween.getStartDate();\n        Date endDate = timeBetween.getEndDate();\n        \n        // 应用慢查询日志\n        Map<String,Long> appInstanceSlowLogCountMap = appStatsCenter.getInstanceSlowLogCountMapByAppId(appId, startDate, endDate);\n        model.addAttribute(\"appInstanceSlowLogCountMap\", appInstanceSlowLogCountMap);\n        List<InstanceSlowLog> appInstanceSlowLogList = appStatsCenter.getInstanceSlowLogByAppId(appId, startDate, endDate);\n        model.addAttribute(\"appInstanceSlowLogList\", appInstanceSlowLogList);\n        \n        // 各个实例对应的慢查询日志\n        Map<String, List<InstanceSlowLog>> instaceSlowLogMap = new HashMap<String, List<InstanceSlowLog>>();\n        Map<String, Long> instanceHostPortIdMap = new HashMap<String, Long>();\n        for(InstanceSlowLog instanceSlowLog : appInstanceSlowLogList) {\n            String hostPort = instanceSlowLog.getIp() + \":\" + instanceSlowLog.getPort();\n            instanceHostPortIdMap.put(hostPort, instanceSlowLog.getInstanceId());\n            if(instaceSlowLogMap.containsKey(hostPort)) {\n                instaceSlowLogMap.get(hostPort).add(instanceSlowLog);\n            } else {\n                List<InstanceSlowLog> list = new ArrayList<InstanceSlowLog>();\n                list.add(instanceSlowLog);\n                instaceSlowLogMap.put(hostPort, list);\n            }\n        }\n        model.addAttribute(\"instaceSlowLogMap\", instaceSlowLogMap);\n        model.addAttribute(\"instanceHostPortIdMap\", instanceHostPortIdMap);\n\n        \n        return new ModelAndView(\"app/slowLog\");\n    }\n    \n    /**\n     * 清理应用数据\n     */\n    @RequestMapping(value = \"/cleanAppData\")\n    public ModelAndView doCleanAppData(HttpServletRequest request, HttpServletResponse response, Model model, long appId) {\n        AppUser appUser = getUserInfo(request);\n        logger.warn(\"{} start to clean appId={} data!\", appUser.getName(), appId);\n        SuccessEnum successEnum = SuccessEnum.FAIL;\n        if (appId > 0) {\n            //验证用户对应用的权限 以及数据清理的结果\n            if (checkAppUserProvilege(request, appId) && appDeployCenter.cleanAppData(appId, getUserInfo(request))) {\n                successEnum = SuccessEnum.SUCCESS;\n            }\n        }\n        logger.warn(\"{} end to clean appId={} data, result is {}\", appUser.getName(), appId, successEnum.info());\n        write(response, String.valueOf(successEnum.value()));\n        return null;\n    }\n\n\n    /**\n     * AppCommandGroup列表组装成json串\n     */\n    private String assembleGroupJson(List<AppCommandGroup> appCommandGroupList) {\n        if (appCommandGroupList == null || appCommandGroupList.isEmpty()) {\n            return \"[]\";\n        }\n        List<SimpleChartData> list = new ArrayList<SimpleChartData>();\n        for (AppCommandGroup appCommandGroup : appCommandGroupList) {\n            SimpleChartData chartData = SimpleChartData\n                    .getFromAppCommandGroup(appCommandGroup);\n            list.add(chartData);\n        }\n        JSONArray jsonArray = JSONArray.fromObject(list);\n        return jsonArray.toString();\n    }\n\n    /**\n     * AppStats列表组装成json串\n     */\n    private String assembleAppStatsJson(List<AppStats> appStats, String statName) {\n        if (appStats == null || appStats.isEmpty()) {\n            return \"[]\";\n        }\n        List<SimpleChartData> list = new ArrayList<SimpleChartData>();\n        for (AppStats stat : appStats) {\n            try {\n                SimpleChartData chartData = SimpleChartData.getFromAppStats(stat, statName);\n                list.add(chartData);\n            } catch (ParseException e) {\n                logger.info(e.getMessage(), e);\n            }\n        }\n        JSONArray jsonArray = JSONArray.fromObject(list);\n        return jsonArray.toString();\n    }\n    \n    private String assembleMutilDateAppCommandJsonMinute(List<AppCommandStats> appCommandStats, Date startDate, Date endDate) {\n        if (appCommandStats == null || appCommandStats.isEmpty()) {\n            return \"[]\";\n        }\n        Map<String, List<HighchartPoint>> map = new HashMap<String, List<HighchartPoint>>();\n        Date currentDate = DateUtils.addDays(endDate, -1);\n        int diffDays = 0;\n        while (currentDate.getTime() >= startDate.getTime()) {\n            List<HighchartPoint> list = new ArrayList<HighchartPoint>();\n            for (AppCommandStats stat : appCommandStats) {\n                try {\n                    HighchartPoint highchartPoint = HighchartPoint.getFromAppCommandStats(stat, currentDate, diffDays);\n                    if (highchartPoint == null) {\n                        continue;\n                    }\n                    list.add(highchartPoint);\n                } catch (ParseException e) {\n                    logger.info(e.getMessage(), e);\n                }\n            }\n            String formatDate = DateUtil.formatDate(currentDate, \"yyyy-MM-dd\");\n            map.put(formatDate, list);\n            currentDate = DateUtils.addDays(currentDate, -1);\n            diffDays++;\n        }\n        net.sf.json.JSONObject jsonObject = net.sf.json.JSONObject.fromObject(map);\n        return jsonObject.toString();\n    }\n    \n    /**\n     * 多命令组装\n     * @param appStats\n     * @param statNameList\n     * @param startDate\n     * @return\n     */\n    private String assembleMutiStatAppStatsJsonMinute(List<AppStats> appStats, List<String> statNameList, Date startDate) {\n        if (appStats == null || appStats.isEmpty()) {\n            return \"[]\";\n        }\n        Map<String, List<HighchartPoint>> map = new HashMap<String, List<HighchartPoint>>();\n        for(String statName : statNameList) {\n            List<HighchartPoint> list = new ArrayList<HighchartPoint>();\n            for (AppStats stat : appStats) {\n                try {\n                    HighchartPoint highchartPoint = HighchartPoint.getFromAppStats(stat, statName, startDate, 0);\n                    if (highchartPoint == null) {\n                        continue;\n                    }\n                    list.add(highchartPoint);\n                } catch (ParseException e) {\n                    logger.info(e.getMessage(), e);\n                }\n            }\n            map.put(statName, list);\n        }\n        net.sf.json.JSONObject jsonObject = net.sf.json.JSONObject.fromObject(map);\n        return jsonObject.toString();\n    }\n    \n    /**\n     * 多时间组装\n     * @param appStats\n     * @param statName\n     * @param startDate\n     * @param endDate\n     * @return\n     */\n    private String assembleMutilDateAppStatsJsonMinute(List<AppStats> appStats, String statName, Date startDate, Date endDate) {\n        if (appStats == null || appStats.isEmpty()) {\n            return \"[]\";\n        }\n        Map<String, List<HighchartPoint>> map = new HashMap<String, List<HighchartPoint>>();\n        Date currentDate = DateUtils.addDays(endDate, -1);\n        int diffDays = 0;\n        while (currentDate.getTime() >= startDate.getTime()) {\n            List<HighchartPoint> list = new ArrayList<HighchartPoint>();\n            for (AppStats stat : appStats) {\n                try {\n                    HighchartPoint highchartPoint = HighchartPoint.getFromAppStats(stat, statName, currentDate, diffDays);\n                    if (highchartPoint == null) {\n                        continue;\n                    }\n                    list.add(highchartPoint);\n                } catch (ParseException e) {\n                    logger.info(e.getMessage(), e);\n                }\n            }\n            String formatDate = DateUtil.formatDate(currentDate, \"yyyy-MM-dd\");\n            map.put(formatDate, list);\n            currentDate = DateUtils.addDays(currentDate, -1);\n            diffDays++;\n        }\n        net.sf.json.JSONObject jsonObject = net.sf.json.JSONObject.fromObject(map);\n        return jsonObject.toString();\n    }\n\n    /**\n     * AppCommandStats列表组装成json串\n     */\n    private String assembleJson(List<AppCommandStats> appCommandStatsList) {\n        return assembleJson(appCommandStatsList, null);\n    }\n\n    private String assembleJson(List<AppCommandStats> appCommandStatsList, Integer addDay) {\n        if (appCommandStatsList == null || appCommandStatsList.isEmpty()) {\n            return \"[]\";\n        }\n        List<SimpleChartData> list = new ArrayList<SimpleChartData>();\n        for (AppCommandStats stat : appCommandStatsList) {\n            try {\n                SimpleChartData chartData = SimpleChartData\n                        .getFromAppCommandStats(stat, addDay);\n                list.add(chartData);\n            } catch (ParseException e) {\n                logger.info(e.getMessage(), e);\n            }\n        }\n        JSONArray jsonArray = JSONArray.fromObject(list);\n        return jsonArray.toString();\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/controller/AppDataMigrateController.java",
    "content": "package com.sohu.cache.web.controller;\n\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Random;\nimport java.util.Set;\n\nimport javax.annotation.Resource;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\nimport org.apache.commons.collections.CollectionUtils;\nimport org.apache.commons.lang.StringUtils;\nimport org.apache.commons.lang.math.NumberUtils;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.servlet.ModelAndView;\n\nimport com.sohu.cache.constant.CommandResult;\nimport com.sohu.cache.constant.MachineInfoEnum;\nimport com.sohu.cache.constant.AppDataMigrateEnum;\nimport com.sohu.cache.constant.AppDataMigrateResult;\nimport com.sohu.cache.constant.RedisMigrateToolConstant;\nimport com.sohu.cache.entity.AppDataMigrateSearch;\nimport com.sohu.cache.entity.AppDataMigrateStatus;\nimport com.sohu.cache.entity.AppDesc;\nimport com.sohu.cache.entity.AppUser;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.entity.MachineInfo;\nimport com.sohu.cache.machine.MachineCenter;\nimport com.sohu.cache.redis.RedisCenter;\nimport com.sohu.cache.stats.app.AppDataMigrateCenter;\nimport com.sohu.cache.util.ConstUtils;\nimport com.sohu.cache.util.TypeUtil;\nimport com.sohu.cache.web.service.AppService;\n\n/**\n * 应用数据迁移入口\n * \n * @author leifu\n * @Date 2016-6-8\n * @Time 下午11:10:34\n */\n@Controller\n@RequestMapping(\"/data/migrate\")\npublic class AppDataMigrateController extends BaseController {\n\n    @Resource(name = \"appDataMigrateCenter\")\n    private AppDataMigrateCenter appDataMigrateCenter;\n    \n    @Resource(name = \"appService\")\n    private AppService appService;\n    \n    @Resource(name = \"machineCenter\")\n    private MachineCenter machineCenter;\n    \n    @Resource(name = \"redisCenter\")\n    private RedisCenter redisCenter;\n    \n    private static Set<String> MIGRATE_SAMPLE_USEFUL_LINES = new HashSet<String>();\n    static {\n        MIGRATE_SAMPLE_USEFUL_LINES.add(\"Checked keys\");\n        MIGRATE_SAMPLE_USEFUL_LINES.add(\"Inconsistent value keys\");\n        MIGRATE_SAMPLE_USEFUL_LINES.add(\"Inconsistent expire keys\");\n        MIGRATE_SAMPLE_USEFUL_LINES.add(\"Other check error keys\");\n        MIGRATE_SAMPLE_USEFUL_LINES.add(\"Checked OK keys\");\n    }\n    \n\n    /**\n     * 初始化界面\n     * @return\n     */\n    @RequestMapping(value = \"/init\")\n    public ModelAndView init(HttpServletRequest request, HttpServletResponse response, Model model) {\n        List<MachineInfo> machineInfoList = machineCenter.getMachineInfoByType(MachineInfoEnum.TypeEnum.REDIS_MIGRATE_TOOL);\n        model.addAttribute(\"machineInfoList\", machineInfoList);\n        return new ModelAndView(\"migrate/init\");\n    }\n\n    /**\n     * 检查配置\n     * @return\n     */\n    @RequestMapping(value = \"/check\")\n    public ModelAndView check(HttpServletRequest request, HttpServletResponse response, Model model) {\n        //相关参数\n        String migrateMachineIp = request.getParameter(\"migrateMachineIp\");\n        String sourceRedisMigrateIndex = request.getParameter(\"sourceRedisMigrateIndex\");\n        AppDataMigrateEnum sourceRedisMigrateEnum = AppDataMigrateEnum.getByIndex(NumberUtils.toInt(sourceRedisMigrateIndex, -1));\n        String sourceServers = request.getParameter(\"sourceServers\");\n        String targetRedisMigrateIndex = request.getParameter(\"targetRedisMigrateIndex\");\n        AppDataMigrateEnum targetRedisMigrateEnum = AppDataMigrateEnum.getByIndex(NumberUtils.toInt(targetRedisMigrateIndex, -1));\n        String targetServers = request.getParameter(\"targetServers\");\n        String redisSourcePass = request.getParameter(\"redisSourcePass\");\n        String redisTargetPass = request.getParameter(\"redisTargetPass\");\n\n        //检查返回结果\n        AppDataMigrateResult redisMigrateResult = appDataMigrateCenter.check(migrateMachineIp, sourceRedisMigrateEnum, sourceServers, targetRedisMigrateEnum, targetServers, redisSourcePass, redisTargetPass);\n        model.addAttribute(\"status\", redisMigrateResult.getStatus());\n        model.addAttribute(\"message\", redisMigrateResult.getMessage());\n        return new ModelAndView(\"\");\n    }\n\n    /**\n     * 开始迁移\n     * @return\n     */\n    @RequestMapping(value = \"/start\")\n    public ModelAndView start(HttpServletRequest request, HttpServletResponse response, Model model) {\n        //相关参数\n        String migrateMachineIp = request.getParameter(\"migrateMachineIp\");\n        String sourceRedisMigrateIndex = request.getParameter(\"sourceRedisMigrateIndex\");\n        AppDataMigrateEnum sourceRedisMigrateEnum = AppDataMigrateEnum.getByIndex(NumberUtils.toInt(sourceRedisMigrateIndex, -1));\n        String sourceServers = request.getParameter(\"sourceServers\");\n        String targetRedisMigrateIndex = request.getParameter(\"targetRedisMigrateIndex\");\n        AppDataMigrateEnum targetRedisMigrateEnum = AppDataMigrateEnum.getByIndex(NumberUtils.toInt(targetRedisMigrateIndex, -1));\n        String targetServers = request.getParameter(\"targetServers\");\n        long sourceAppId = NumberUtils.toLong(request.getParameter(\"sourceAppId\"));\n        long targetAppId = NumberUtils.toLong(request.getParameter(\"targetAppId\"));\n        String redisSourcePass = request.getParameter(\"redisSourcePass\");\n        String redisTargetPass = request.getParameter(\"redisTargetPass\");\n\n        AppUser appUser = getUserInfo(request);\n        long userId = appUser == null ? 0 : appUser.getId();\n\n        // 不需要对格式进行检验,check已经做过了，开始迁移\n        boolean isSuccess = appDataMigrateCenter.migrate(migrateMachineIp, sourceRedisMigrateEnum, sourceServers,\n                targetRedisMigrateEnum, targetServers, sourceAppId, targetAppId, redisSourcePass, redisTargetPass, userId);\n\n        model.addAttribute(\"status\", isSuccess ? 1 : 0);\n        return new ModelAndView(\"\");\n    }\n    \n    /**\n     * 停掉迁移任务\n     * @return\n     */\n    @RequestMapping(value = \"/stop\")\n    public ModelAndView stop(HttpServletRequest request, HttpServletResponse response, Model model) {\n        //任务id：查到任务相关信息\n        long id = NumberUtils.toLong(request.getParameter(\"id\"));\n        AppDataMigrateResult stopMigrateResult = appDataMigrateCenter.stopMigrate(id);\n        model.addAttribute(\"status\", stopMigrateResult.getStatus());\n        model.addAttribute(\"message\", stopMigrateResult.getMessage());\n        return new ModelAndView(\"\");\n    }\n    \n    /**\n     * 查看迁移日志\n     * @return\n     */\n    @RequestMapping(value = \"/log\")\n    public ModelAndView log(HttpServletRequest request, HttpServletResponse response, Model model) {\n        //任务id：查到任务相关信息\n        long id = NumberUtils.toLong(request.getParameter(\"id\"));\n        int pageSize = NumberUtils.toInt(request.getParameter(\"pageSize\"), 0);\n        if (pageSize == 0) {\n            pageSize = 100;\n        }\n        \n        String log = appDataMigrateCenter.showDataMigrateLog(id, pageSize);\n        model.addAttribute(\"logList\", Arrays.asList(log.split(ConstUtils.NEXT_LINE)));\n        return new ModelAndView(\"migrate/log\");\n    }\n    \n    /**\n     * 查看迁移日志\n     * @return\n     */\n    @RequestMapping(value = \"/config\")\n    public ModelAndView config(HttpServletRequest request, HttpServletResponse response, Model model) {\n        //任务id：查到任务相关信息\n        long id = NumberUtils.toLong(request.getParameter(\"id\"));\n        String config = appDataMigrateCenter.showDataMigrateConf(id);\n        model.addAttribute(\"configList\", Arrays.asList(config.split(ConstUtils.NEXT_LINE)));\n        return new ModelAndView(\"migrate/config\");\n    }\n    \n    /**\n     * 查看迁移进度\n     * @return\n     */\n    @RequestMapping(value = \"/process\")\n    public ModelAndView showProcess(HttpServletRequest request, HttpServletResponse response, Model model) {\n        long id = NumberUtils.toLong(request.getParameter(\"id\"));\n        Map<RedisMigrateToolConstant, Map<String, Object>> migrateToolStatMap = appDataMigrateCenter.showMiragteToolProcess(id);\n        model.addAttribute(\"migrateToolStatMap\", migrateToolStatMap);\n        return new ModelAndView(\"migrate/process\");\n    }\n    \n    /**\n     * 查看迁移进度\n     * @return\n     */\n    @RequestMapping(value = \"/checkData\")\n    public ModelAndView checkData(HttpServletRequest request, HttpServletResponse response, Model model) {\n        long id = NumberUtils.toLong(request.getParameter(\"id\"));\n        int nums = 1000 + new Random().nextInt(2000);\n        //为了方便，直接传入命令\n        CommandResult commandResult = appDataMigrateCenter.sampleCheckData(id, nums);\n        String message = commandResult.getResult();\n        List<String> checkDataResultList = new ArrayList<String>();\n        checkDataResultList.add(\"一共随机检验了\" + nums + \"个key\" + \",检查结果如下:\");\n        String[] lineArr = message.split(ConstUtils.NEXT_LINE);\n        for (String line : lineArr) {\n            if (StringUtils.isBlank(line)) {\n                continue;\n            }\n            // 行数太多显示会有问题\n            if (lineArr.length > 100 && !isUsefulLine(line)) {\n                continue;\n            }\n            //message格式显示有点问题\n            line = line.replace(\"[0m\", \"\");\n            line = line.replace(\"[31m\", \"\");\n            line = line.replace(\"[33m\", \"\");\n            checkDataResultList.add(line.trim());\n        }\n        model.addAttribute(\"checkDataResultList\", checkDataResultList);\n        model.addAttribute(\"checkDataCommand\", commandResult.getCommand());\n        return new ModelAndView(\"migrate/checkData\");\n    }\n\n    private boolean isUsefulLine(String line) {\n        for (String usefulLine : MIGRATE_SAMPLE_USEFUL_LINES) {\n            if (line.contains(usefulLine)) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    /**\n     * 查看迁移列表(包含历史)\n     * @return\n     */\n    @RequestMapping(value = \"/list\")\n    public ModelAndView list(HttpServletRequest request, HttpServletResponse response, Model model, AppDataMigrateSearch appDataMigrateSearch) {\n        List<AppDataMigrateStatus> appDataMigrateStatusList = appDataMigrateCenter.search(appDataMigrateSearch);\n        model.addAttribute(\"appDataMigrateStatusList\", appDataMigrateStatusList);\n        model.addAttribute(\"appDataMigrateSearch\", appDataMigrateSearch);\n        return new ModelAndView(\"migrate/list\");\n    }\n    \n    /**\n     * 通过应用id获取可用的Redis实例信息\n     * @return\n     */\n    @RequestMapping(value = \"/appInstanceList\")\n    public ModelAndView appInstanceList(HttpServletRequest request, HttpServletResponse response, Model model) {\n        String appIdStr = request.getParameter(\"appId\");\n        long appId = NumberUtils.toLong(appIdStr);\n        AppDesc appDesc = appService.getByAppId(appId);\n        StringBuffer instances = new StringBuffer();\n        List<InstanceInfo> instanceList = appService.getAppInstanceInfo(appId);\n        if (CollectionUtils.isNotEmpty(instanceList)) {\n            for (int i = 0; i < instanceList.size(); i++) {\n                InstanceInfo instanceInfo = instanceList.get(i);\n                if (instanceInfo == null) {\n                    continue;\n                }\n                if (instanceInfo.isOffline()) {\n                    continue;\n                }\n                // 如果是sentinel类型的应用只出master\n                if (TypeUtil.isRedisSentinel(appDesc.getType())) {\n                    if (TypeUtil.isRedisSentinel(instanceInfo.getType())) {\n                        continue;\n                    }\n                    if (!redisCenter.isMaster(appId, instanceInfo.getIp(), instanceInfo.getPort())) {\n                        continue;\n                    }\n                }\n                instances.append(instanceInfo.getIp() + \":\" + instanceInfo.getPort());\n                if (i != instanceList.size() - 1) {\n                    instances.append(ConstUtils.NEXT_LINE);\n                }\n            }\n        }\n        model.addAttribute(\"instances\", instances.toString());\n        model.addAttribute(\"appType\", appDesc == null ? -1 : appDesc.getType());\n        return new ModelAndView(\"\");\n    }\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/controller/AppManageController.java",
    "content": "package com.sohu.cache.web.controller;\n\nimport com.sohu.cache.web.enums.RedisOperateEnum;\nimport com.sohu.cache.constant.AppCheckEnum;\nimport com.sohu.cache.constant.ClusterOperateResult;\nimport com.sohu.cache.constant.DataFormatCheckResult;\nimport com.sohu.cache.constant.ErrorMessageEnum;\nimport com.sohu.cache.constant.HorizontalResult;\nimport com.sohu.cache.dao.InstanceReshardProcessDao;\nimport com.sohu.cache.entity.*;\nimport com.sohu.cache.machine.MachineCenter;\nimport com.sohu.cache.redis.RedisCenter;\nimport com.sohu.cache.redis.RedisDeployCenter;\nimport com.sohu.cache.stats.app.AppDailyDataCenter;\nimport com.sohu.cache.stats.app.AppDeployCenter;\nimport com.sohu.cache.stats.instance.InstanceDeployCenter;\nimport com.sohu.cache.util.ConstUtils;\nimport com.sohu.cache.util.TypeUtil;\nimport com.sohu.cache.web.enums.SuccessEnum;\nimport com.sohu.cache.web.util.AppEmailUtil;\nimport com.sohu.cache.web.util.DateUtil;\n\nimport net.sf.json.JSONArray;\n\nimport org.apache.commons.lang.StringUtils;\nimport org.apache.commons.lang.math.NumberUtils;\nimport org.apache.commons.lang.time.DateUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.servlet.ModelAndView;\n\nimport javax.annotation.Resource;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\nimport java.text.ParseException;\nimport java.util.*;\n\n/**\n * 应用后台管理\n *\n * @author leifu\n * @Time 2014年7月3日\n */\n@Controller\n@RequestMapping(\"manage/app\")\npublic class AppManageController extends BaseController {\n\n\tprivate Logger logger = LoggerFactory.getLogger(AppManageController.class);\n\n\t@Resource(name = \"machineCenter\")\n\tprivate MachineCenter machineCenter;\n\n\t@Resource(name = \"appEmailUtil\")\n\tprivate AppEmailUtil appEmailUtil;\n\n\t@Resource(name = \"appDeployCenter\")\n\tprivate AppDeployCenter appDeployCenter;\n\n\t@Resource(name = \"redisCenter\")\n\tprivate RedisCenter redisCenter;\n\n\t@Resource(name = \"redisDeployCenter\")\n\tprivate RedisDeployCenter redisDeployCenter;\n\t\n\t@Resource(name = \"instanceDeployCenter\")\n\tprivate InstanceDeployCenter instanceDeployCenter;\n\n\t@Resource(name = \"appDailyDataCenter\")\n    private AppDailyDataCenter appDailyDataCenter;\n\t\n    @Resource(name = \"instanceReshardProcessDao\")\n\tprivate InstanceReshardProcessDao instanceReshardProcessDao;\n\t\n\t@RequestMapping(\"/appDaily\")\n    public ModelAndView appDaily(HttpServletRequest request, HttpServletResponse response, Model model) throws ParseException {\n\t    AppUser userInfo = getUserInfo(request);\n        logger.warn(\"user {} want to send appdaily\", userInfo.getName());\n        if (ConstUtils.SUPER_MANAGER.contains(userInfo.getName())) {\n            Date startDate;\n            Date endDate;\n            String startDateParam = request.getParameter(\"startDate\");\n            String endDateParam = request.getParameter(\"endDate\");\n            if (StringUtils.isBlank(startDateParam) || StringUtils.isBlank(endDateParam)) {\n                endDate = new Date();\n                startDate = DateUtils.addDays(endDate, -1);\n            } else {\n                startDate = DateUtil.parseYYYY_MM_dd(startDateParam);\n                endDate = DateUtil.parseYYYY_MM_dd(endDateParam);\n            }\n            long appId = NumberUtils.toLong(request.getParameter(\"appId\"));\n            if (appId > 0) {\n                appDailyDataCenter.sendAppDailyEmail(appId, startDate, endDate);\n            } else {\n                appDailyDataCenter.sendAppDailyEmail();\n            }\n            model.addAttribute(\"msg\", \"success!\");\n        } else {\n            model.addAttribute(\"msg\", \"no power!\");\n        }\n        return new ModelAndView(\"\");\n    }\n\t\n\t/**\n\t * 审核列表\n\t * \n\t * @param status 审核状态\n\t * @param type 申请类型\n\t */\n\t@RequestMapping(value = \"/auditList\")\n\tpublic ModelAndView doAppAuditList(HttpServletRequest request,HttpServletResponse response, Model model,\n\t        Integer status, Integer type) {\n\t    //获取审核列表\n\t\tList<AppAudit> list = appService.getAppAudits(status, type);\n\n\t\tmodel.addAttribute(\"list\", list);\n\t\tmodel.addAttribute(\"status\", status);\n\t\tmodel.addAttribute(\"type\", type);\n\t\tmodel.addAttribute(\"checkActive\", SuccessEnum.SUCCESS.value());\n\n\t\treturn new ModelAndView(\"manage/appAudit/list\");\n\t}\n\n\t/**\n\t * 处理应用配置修改\n\t * \n\t * @param appAuditId 审批id\n\t */\n\t@RequestMapping(value = \"/initAppConfigChange\")\n\tpublic ModelAndView doInitAppConfigChange(HttpServletRequest request,\n\t\t\tHttpServletResponse response, Model model, Long appAuditId) {\n\t\t// 申请原因\n\t\tAppAudit appAudit = appService.getAppAuditById(appAuditId);\n\t\tmodel.addAttribute(\"appAudit\", appAudit);\n\n\t\t// 用第一个参数存实例id\n\t\tLong instanceId = NumberUtils.toLong(appAudit.getParam1());\n\t\tMap<String, String> redisConfigList = redisCenter.getRedisConfigList(instanceId.intValue());\n\t\tmodel.addAttribute(\"redisConfigList\", redisConfigList);\n\t\tmodel.addAttribute(\"instanceId\", instanceId);\n\n\t\t// 实例列表\n\t\tList<InstanceInfo> instanceList = appService.getAppInstanceInfo(appAudit.getAppId());\n\t\tmodel.addAttribute(\"instanceList\", instanceList);\n\t\tmodel.addAttribute(\"appId\", appAudit.getAppId());\n\t\tmodel.addAttribute(\"appAuditId\", appAuditId);\n\n\t\t// 修改配置的键值对\n\t\tmodel.addAttribute(\"appConfigKey\", appAudit.getParam2());\n\t\tmodel.addAttribute(\"appConfigValue\", appAudit.getParam3());\n\n\t\treturn new ModelAndView(\"manage/appAudit/initAppConfigChange\");\n\t}\n\n\t/**\n\t * 添加应用配置修改\n\t * \n\t * @param appId 应用id\n\t * @param appConfigKey 配置项\n\t * @param appConfigValue 配置值\n\t * @param appAuditId 审批id\n\t */\n\t@RequestMapping(value = \"/addAppConfigChange\")\n\tpublic ModelAndView doAddAppConfigChange(HttpServletRequest request,\n\t\t\tHttpServletResponse response, Model model, Long appId,\n\t\t\tString appConfigKey, String appConfigValue, Long appAuditId) {\n\t    AppUser appUser = getUserInfo(request);\n        logger.warn(\"user {} change appConfig:appId={};key={};value={},appAuditId:{}\", appUser.getName(), appId, appConfigKey, appConfigValue, appAuditId);\n        boolean isModify = false;\n        if (appId != null && appAuditId != null && StringUtils.isNotBlank(appConfigKey) && StringUtils.isNotBlank(appConfigValue)) {\n\t\t\ttry {\n\t\t\t\tisModify = appDeployCenter.modifyAppConfig(appId, appAuditId, appConfigKey, appConfigValue);\n\t\t\t} catch (Exception e) {\n\t\t\t\tlogger.error(e.getMessage(), e);\n\t\t\t}\n\t\t}\n        logger.warn(\"user {} change appConfig:appId={};key={};value={},appAuditId:{},result is:{}\", appUser.getName(), appId, appConfigKey, appConfigValue, appAuditId, isModify);\n\t\treturn new ModelAndView(\"redirect:/manage/app/auditList\");\n\t}\n\n\t/**\n\t * 初始化水平扩容申请\n\t */\n\t@RequestMapping(value = \"/initHorizontalScaleApply\")\n\tpublic ModelAndView doInitHorizontalScaleApply(HttpServletRequest request, HttpServletResponse response, Model model, Long appAuditId) {\n\t\tAppAudit appAudit = appService.getAppAuditById(appAuditId);\n\t\tmodel.addAttribute(\"appAudit\", appAudit);\n\t\tmodel.addAttribute(\"appId\", appAudit.getAppId());\n\t\treturn new ModelAndView(\"manage/appAudit/initHorizontalScaleApply\");\n\t}\n\t\n\t\n\n    /**\n     * 添加水平扩容节点\n     * \n     * @return\n     */\n    @RequestMapping(value = \"/addHorizontalNodes\")\n    public ModelAndView doAddHorizontalNodes(HttpServletRequest request,\n            HttpServletResponse response, Model model, String masterSizeSlave,\n            Long appAuditId) {\n        AppUser appUser = getUserInfo(request);\n        logger.warn(\"user {} addHorizontalNodes:{}\", appUser.getName(), masterSizeSlave);\n        boolean isAdd = false;\n        AppAudit appAudit = appService.getAppAuditById(appAuditId);\n        // 解析配置\n        String[] configArr = masterSizeSlave.split(ConstUtils.COLON);\n        String masterHost = configArr[0];\n        String memSize = configArr[1];\n        int memSizeInt = NumberUtils.toInt(memSize);\n        String slaveHost = null;\n        if (configArr.length >= 3) {\n            slaveHost = configArr[2];\n        }\n        try {\n            isAdd = appDeployCenter.addHorizontalNodes(appAudit.getAppId(), masterHost, slaveHost, memSizeInt);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n        logger.warn(\"addAppClusterSharding:{}, result is {}\", masterSizeSlave, isAdd);\n        model.addAttribute(\"status\", isAdd ? 1 : 0);\n        return new ModelAndView(\"\");\n    }\n\n    /**\n     * 检测水平扩容节点\n     * @param masterSizeSlave\n     * @param appAuditId\n     * @return\n     */\n\t@RequestMapping(value = \"/checkHorizontalNodes\")\n\tpublic ModelAndView doCheckHorizontalNodes(HttpServletRequest request,\n\t\t\tHttpServletResponse response, Model model, String masterSizeSlave,\n\t\t\tLong appAuditId) {\n\t    DataFormatCheckResult dataFormatCheckResult = null;\n        try {\n            dataFormatCheckResult = appDeployCenter.checkHorizontalNodes(appAuditId, masterSizeSlave);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            dataFormatCheckResult = DataFormatCheckResult.fail(ErrorMessageEnum.INNER_ERROR_MSG.getMessage());\n        }\n        model.addAttribute(\"status\", dataFormatCheckResult.getStatus());\n        model.addAttribute(\"message\", dataFormatCheckResult.getMessage());\n        return new ModelAndView(\"\");\n\t}\n\n\t/**\n\t * 水平扩容初始化\n\t * \n\t * @param appAuditId\n\t */\n\t@RequestMapping(value = \"/handleHorizontalScale\")\n\tpublic ModelAndView doHandleHorizontalScale(HttpServletRequest request,\n\t\t\tHttpServletResponse response, Model model, Long appAuditId) {\n\t\t// 1. 审批\n\t\tAppAudit appAudit = appService.getAppAuditById(appAuditId);\n\t\tmodel.addAttribute(\"appAudit\", appAudit);\n\t\tmodel.addAttribute(\"appId\", appAudit.getAppId());\n\n\t\t// 2. 进度\n\t\tList<InstanceReshardProcess> instanceReshardProcessList = instanceReshardProcessDao.getByAuditId(appAudit.getId());\n\t\tmodel.addAttribute(\"instanceReshardProcessList\", instanceReshardProcessList);\n\n\t\t// 3. 实例列表和统计\n\t\tfillAppInstanceStats(appAudit.getAppId(), model);\n\t\t// 4. 实例所在机器信息\n\t\tfillAppMachineStat(appAudit.getAppId(), model);\n\n\t\treturn new ModelAndView(\"manage/appAudit/handleHorizontalScale\");\n\t}\n\n\t/**\n\t * 显示reshard进度\n\t */\n\t@RequestMapping(value = \"/showReshardProcess\")\n\tpublic ModelAndView doShowReshardProcess(HttpServletRequest request, HttpServletResponse response, Model model) {\n\t    long auditId = NumberUtils.toLong(request.getParameter(\"auditId\"));\n        List<InstanceReshardProcess> instanceReshardProcessList = instanceReshardProcessDao.getByAuditId(auditId);\n        write(response, JSONArray.fromObject(instanceReshardProcessList).toString());\n        return null;\n\t}\n\n//\t/**\n//     * 把Map组装成JsonArray\n//     * \n//     * @param appScaleProcessMap\n//     * @return\n//     */\n//    private String filterMapToJsonArray(ConcurrentMap<Long, ReshardProcess> appScaleProcessMap) {\n//        if (MapUtils.isEmpty(appScaleProcessMap)) {\n//            return \"[]\";\n//        }\n//        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();\n//        for (Entry<Long, ReshardProcess> entry : appScaleProcessMap.entrySet()) {\n//            Map<String, Object> map = new HashMap<String, Object>();\n//            map.put(\"appId\", entry.getKey());\n//            map.put(\"reshardSlot\", entry.getValue().getReshardSlot());\n//            map.put(\"totalSlot\", entry.getValue().getTotalSlot());\n//            map.put(\"status\", entry.getValue().getStatus());\n//            list.add(map);\n//        }\n//        return JSONArray.fromObject(list).toString();\n//    }\n\n\t/**\n\t * 水平扩容配置检查\n\t * @param sourceId 源实例ID\n\t * @param targetId 目标实例ID\n\t * @param startSlot 开始slot\n\t * @param endSlot 结束slot\n\t * @param appId 应用id\n\t * @param appAuditId 审批id\n\t * @return\n\t */\n\t@RequestMapping(value = \"/checkHorizontalScale\")\n\tpublic ModelAndView doCheckHorizontalScale(HttpServletRequest request, HttpServletResponse response, Model model,\n\t\t\tlong sourceId, long targetId, int startSlot, int endSlot, long appId, long appAuditId, int migrateType) {\n\t\tHorizontalResult horizontalResult = appDeployCenter.checkHorizontal(appId, appAuditId, sourceId, targetId,\n\t\t\t\tstartSlot, endSlot, migrateType);\n\t\tmodel.addAttribute(\"status\", horizontalResult.getStatus());\n\t\tmodel.addAttribute(\"message\", horizontalResult.getMessage());\n\t\treturn new ModelAndView(\"\");\n\t}\n\t\n\t/**\n\t * 开始水平扩容\n\t * @param sourceId 源实例ID\n\t * @param targetId 目标实例ID\n\t * @param startSlot 开始slot\n\t * @param endSlot 结束slot\n\t * @param appId 应用id\n\t * @param appAuditId 审批id\n\t * @return\n\t */\n\t@RequestMapping(value = \"/startHorizontalScale\")\n\tpublic ModelAndView doStartHorizontalScale(HttpServletRequest request, HttpServletResponse response, Model model,\n\t\t\tlong sourceId, long targetId, int startSlot, int endSlot, long appId, long appAuditId, int migrateType) {\n\t\tAppUser appUser = getUserInfo(request);\n\t\tlogger.warn(\"user {} horizontalScaleApply appId {} appAuditId {} sourceId {} targetId {} startSlot {} endSlot {}\",\n\t\t\t\tappUser.getName(), appId, appAuditId, sourceId, targetId, startSlot, endSlot);\n\t\tHorizontalResult horizontalResult = appDeployCenter.startHorizontal(appId, appAuditId, sourceId, targetId,\n\t\t\t\tstartSlot, endSlot, migrateType);\n        model.addAttribute(\"status\", horizontalResult.getStatus());\n\t\tmodel.addAttribute(\"message\", horizontalResult.getMessage());\n\t\treturn new ModelAndView(\"\");\n\t}\n\t\n\t/**\n\t * 重试水平扩容\n\t * @param instanceReshardProcessId\n\t * @return\n\t */\n    @RequestMapping(value = \"/retryHorizontalScale\")\n    public ModelAndView retryHorizontalScale(HttpServletRequest request, HttpServletResponse response, Model model, int instanceReshardProcessId) {\n        AppUser appUser = getUserInfo(request);\n        logger.warn(\"user {} retryHorizontalScale id {}\", appUser.getName(), instanceReshardProcessId);\n        HorizontalResult horizontalResult = appDeployCenter.retryHorizontal(instanceReshardProcessId);\n        model.addAttribute(\"status\", horizontalResult.getStatus());\n        model.addAttribute(\"message\", horizontalResult.getMessage());\n        return new ModelAndView(\"\");\n    }\n\n\t/**\n\t * 处理应用扩容\n\t * \n\t * @param appAuditId 审批id\n\t */\n\t@RequestMapping(value = \"/initAppScaleApply\")\n\tpublic ModelAndView doInitAppScaleApply(HttpServletRequest request, HttpServletResponse response, Model model, Long appAuditId) {\n\t\t// 申请原因\n\t\tAppAudit appAudit = appService.getAppAuditById(appAuditId);\n\t\tmodel.addAttribute(\"appAudit\", appAudit);\n\n\t\t// 实例列表和统计\n\t\tfillAppInstanceStats(appAudit.getAppId(), model);\n\t\t// 实例所在机器信息\n        fillAppMachineStat(appAudit.getAppId(), model);\n\n\t\tlong appId = appAudit.getAppId();\n\t\tAppDesc appDesc = appService.getByAppId(appId);\n        model.addAttribute(\"appAuditId\", appAuditId);\n\t\tmodel.addAttribute(\"appId\", appAudit.getAppId());\n        model.addAttribute(\"appDesc\", appDesc);\n\t\t\n\t\treturn new ModelAndView(\"manage/appAudit/initAppScaleApply\");\n\t}\n\n\t/**\n\t * 添加扩容配置\n\t * \n\t * @param appScaleText 扩容配置\n\t * @param appAuditId 审批id\n\t */\n\t@RequestMapping(value = \"/addAppScaleApply\")\n\tpublic ModelAndView doAddAppScaleApply(HttpServletRequest request,\n\t\t\tHttpServletResponse response, Model model, String appScaleText,\n\t\t\tLong appAuditId, Long appId) {\n\t    AppUser appUser = getUserInfo(request);\n        logger.error(\"user {} appScaleApplay : appScaleText={},appAuditId:{}\", appUser.getName(), appScaleText, appAuditId);\n        boolean isSuccess = false;\n\t\tif (appAuditId != null && StringUtils.isNotBlank(appScaleText)) {\n\t\t\tint mem = NumberUtils.toInt(appScaleText, 0);\n\t\t\ttry {\n\t\t\t    isSuccess = appDeployCenter.verticalExpansion(appId, appAuditId, mem);\n\t\t\t} catch (Exception e) {\n\t\t\t\tlogger.error(e.getMessage(), e);\n\t\t\t}\n\t\t} else {\n\t\t\tlogger.error(\"appScaleApplay error param: appScaleText={},appAuditId:{}\", appScaleText, appAuditId);\n\t\t}\n        logger.error(\"user {} appScaleApplay: appScaleText={},appAuditId:{}, result is {}\", appUser.getName(), appScaleText, appAuditId, isSuccess);\n\t\treturn new ModelAndView(\"redirect:/manage/app/auditList\");\n\t}\n\n\t/**\n\t * 初始化部署应用\n\t * \n\t * @param appAuditId 审批id\n\t * @return\n\t */\n\t@RequestMapping(value = \"/initAppDeploy\")\n\tpublic ModelAndView doInitAppDeploy(HttpServletRequest request, HttpServletResponse response, Model model, Long appAuditId) {\n\t\t// 申请原因\n\t\tAppAudit appAudit = appService.getAppAuditById(appAuditId);\n\t\tmodel.addAttribute(\"appAudit\", appAudit);\n\n\t\t// 机器列表\n\t\tList<MachineStats> machineList = machineCenter.getAllMachineStats();\n\t\tmodel.addAttribute(\"machineList\", machineList);\n\t\tmodel.addAttribute(\"appAuditId\", appAuditId);\n\t\tmodel.addAttribute(\"appId\", appAudit.getAppId());\n\t\tmodel.addAttribute(\"appDesc\", appService.getByAppId(appAudit.getAppId()));\n\n\t\treturn new ModelAndView(\"manage/appAudit/initAppDeploy\");\n\t}\n\t\n\t/**\n     * 应用部署配置检查\n     * @return\n     */\n    @RequestMapping(value = \"/appDeployCheck\")\n    public ModelAndView doAppDeployCheck(HttpServletRequest request, HttpServletResponse response, Model model, String appDeployText,\n            Long appAuditId) {\n        DataFormatCheckResult dataFormatCheckResult = null;\n        try {\n            dataFormatCheckResult = appDeployCenter.checkAppDeployDetail(appAuditId, appDeployText);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            dataFormatCheckResult = DataFormatCheckResult.fail(ErrorMessageEnum.INNER_ERROR_MSG.getMessage());\n        }\n        model.addAttribute(\"status\", dataFormatCheckResult.getStatus());\n        model.addAttribute(\"message\", dataFormatCheckResult.getMessage());\n        return new ModelAndView(\"\");\n    }\n\n\t/**\n\t * 添加应用部署\n\t * \n\t * @param appDeployText 部署配置\n\t * @param appAuditId 审批id\n\t * @return\n\t */\n\t@RequestMapping(value = \"/addAppDeploy\")\n\tpublic ModelAndView doAddAppDeploy(HttpServletRequest request,\n\t\t\tHttpServletResponse response, Model model, String appDeployText,\n\t\t\tLong appAuditId) {\n\t    AppUser appUser = getUserInfo(request);\n        logger.warn(\"user {} appDeploy: appDeployText={},appAuditId:{}\", appUser.getName(), appDeployText, appAuditId);\n        boolean isSuccess = false;\n\t    if (appAuditId != null && StringUtils.isNotBlank(appDeployText)) {\n\t\t\tString[] appDetails = appDeployText.split(\"\\n\");\n\t\t\t// 部署service\n\t\t\tisSuccess = appDeployCenter.allocateResourceApp(appAuditId, Arrays.asList(appDetails), getUserInfo(request));\n\t\t} else {\n\t\t\tlogger.error(\"appDeploy error param: appDeployText={},appAuditId:{}\", appDeployText, appAuditId);\n\t\t}\n        logger.warn(\"user {} appDeploy: appDeployText={},appAuditId:{}, result is {}\", appUser.getName(), appDeployText, appAuditId, isSuccess);\n        model.addAttribute(\"status\", isSuccess ? 1 : 0);\n        return new ModelAndView(\"\");\n\t}\n\n\t/**\n\t * 通过,获取驳回申请\n\t * \n\t * @param status 审批状态\n\t * @param appAuditId 审批id\n\t * @param refuseReason 应用id\n\t * @return\n\t */\n\t@RequestMapping(value = \"/addAuditStatus\")\n\tpublic ModelAndView doAddAuditStatus(HttpServletRequest request, HttpServletResponse response, Model model, Integer status, Long appAuditId, String refuseReason) {\n\t    AppUser appUser = getUserInfo(request);\n        logger.warn(\"user {} addAuditStatus: status={},appAuditId:{},refuseReason:{}\", appUser.getName(), status, appAuditId, refuseReason);\n\t    AppAudit appAudit = appService.getAppAuditById(appAuditId);\n\t\tLong appId = appAudit.getAppId();\n\t\t// 通过或者驳回并记录日志\n\t\tappService.updateAppAuditStatus(appAuditId, appId, status, getUserInfo(request));\n\n\t\t// 记录驳回原因\n\t\tif (AppCheckEnum.APP_REJECT.value().equals(status)) {\n\t\t\tappAudit.setRefuseReason(refuseReason);\n\t\t\tappService.updateRefuseReason(appAudit, getUserInfo(request));\n\t\t}\n\n\t\t// 发邮件统计\n\t\tif (AppCheckEnum.APP_PASS.value().equals(status) || AppCheckEnum.APP_REJECT.value().equals(status)) {\n\t\t\tAppDesc appDesc = appService.getByAppId(appId);\n\t\t\tappEmailUtil.noticeAppResult(appDesc, appService.getAppAuditById(appAuditId));\n\t\t}\n\n\t\t// 批准成功直接跳转\n\t\tif (AppCheckEnum.APP_PASS.value().equals(status)) {\n\t\t\treturn new ModelAndView(\"redirect:/manage/app/auditList\");\n\t\t}\n\n\t\twrite(response, String.valueOf(SuccessEnum.SUCCESS.value()));\n\t\treturn null;\n\t}\n\n\t/**\n\t * 下线应用\n\t * \n\t * @param appId\n\t * @return\n\t */\n\t@RequestMapping(value = \"/offLine\")\n\tpublic ModelAndView offLineApp(HttpServletRequest request,\n\t\t\tHttpServletResponse response, Model model, Long appId) {\n\t\tAppUser userInfo = getUserInfo(request);\n\t\tlogger.warn(\"user {} hope to offline appId: {}\", userInfo.getName(), appId);\n\t\tif (ConstUtils.SUPER_MANAGER.contains(userInfo.getName())) {\n\t\t\tboolean result = appDeployCenter.offLineApp(appId);\n\t\t\tmodel.addAttribute(\"appId\", appId);\n\t\t\tmodel.addAttribute(\"result\", result);\n\t\t\tif (result) {\n\t\t\t\tmodel.addAttribute(\"msg\", \"操作成功\");\n\t\t\t} else {\n\t\t\t\tmodel.addAttribute(\"msg\", \"操作失败\");\n\t\t\t}\n\t\t    logger.warn(\"user {} offline appId: {}, result is {}\", userInfo.getName(), appId, result);\n\t\t    appEmailUtil.noticeOfflineApp(userInfo, appId, result);\n\t\t} else {\n\t\t    logger.warn(\"user {} hope to offline appId: {}, hasn't provilege\", userInfo.getName(), appId);\n\t\t\tmodel.addAttribute(\"result\", false);\n\t\t\tmodel.addAttribute(\"msg\", \"权限不足\");\n\t        appEmailUtil.noticeOfflineApp(userInfo, appId, false);\n\t\t}\n\t\treturn new ModelAndView();\n\t}\n\n\t/**\n\t * 实例机器信息\n\t * @param appId\n\t * @param model\n\t */\n\tprivate void fillAppMachineStat(Long appId, Model model){\n        List<InstanceInfo> instanceList = appService.getAppInstanceInfo(appId);\n        \n        Map<String, MachineStats> machineStatsMap = new HashMap<String, MachineStats>();\n        Map<String, Long> machineCanUseMem = new HashMap<String, Long>();\n        \n        for (InstanceInfo instanceInfo : instanceList) {\n            if (TypeUtil.isRedisSentinel(instanceInfo.getType())) {\n                continue;\n            }\n            String ip = instanceInfo.getIp();\n            if (machineStatsMap.containsKey(ip)) {\n                continue;\n            }\n            MachineStats machineStats = machineCenter.getMachineMemoryDetail(ip);\n            machineStatsMap.put(ip, machineStats);\n            machineCanUseMem.put(ip, machineStats.getMachineMemInfo().getLockedMem());\n        }\n        model.addAttribute(\"machineCanUseMem\", machineCanUseMem);\n        model.addAttribute(\"machineStatsMap\", machineStatsMap);\n\t}\n\t\n\t\n\t/**\n\t * 应用运维\n\t * @param appId\n\t */\n\t@RequestMapping(\"/index\")\n\tpublic ModelAndView index(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) {\n\t\tmodel.addAttribute(\"appId\", appId);\n\t\treturn new ModelAndView(\"manage/appOps/appOpsIndex\");\n\t}\n\n\t/**\n\t * 应用机器运维\n\t * @param appId\n\t */\n\t@RequestMapping(\"/machine\")\n\tpublic ModelAndView appMachine(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) {\n\t\tif (appId != null && appId > 0) {\n\t\t\tList<MachineStats> appMachineList = appService.getAppMachineDetail(appId);\n\t\t\tmodel.addAttribute(\"appMachineList\", appMachineList);\n\t\t\tAppDesc appDesc = appService.getByAppId(appId);\n\t\t\tmodel.addAttribute(\"appDesc\", appDesc);\n\t\t}\n\t\treturn new ModelAndView(\"manage/appOps/appMachine\");\n\t}\n\n\t/**\n\t * 应用实例运维\n\t * @param appId\n\t */\n\t@RequestMapping(\"/instance\")\n\tpublic ModelAndView appInstance(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) {\n\t\tif (appId != null && appId > 0) {\n\t\t\tAppDesc appDesc = appService.getByAppId(appId);\n\t\t\tmodel.addAttribute(\"appDesc\", appDesc);\n\t\t\t//实例信息和统计\n\t\t\tfillAppInstanceStats(appId, model);\n\t\t\t\n\t\t\t//只有cluster类型才需要计算slot相关\n            if (TypeUtil.isRedisCluster(appDesc.getType())) {\n                // 计算丢失的slot区间\n                Map<String,String> lossSlotsSegmentMap = redisCenter.getClusterLossSlots(appId);\n                model.addAttribute(\"lossSlotsSegmentMap\", lossSlotsSegmentMap);\n            }\n\t\t}\n\t\treturn new ModelAndView(\"manage/appOps/appInstance\");\n\t}\n\n\t/**\n\t * 应用详细信息和各种申请记录\n\t * @param appId\n\t */\n\t@RequestMapping(\"/detail\")\n\tpublic ModelAndView appInfoAndAudit(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) {\n\t\tif (appId != null && appId > 0) {\n\t\t\tList<AppAudit> appAuditList = appService.getAppAuditListByAppId(appId);\n\t\t\tAppDesc appDesc = appService.getByAppId(appId);\n\t\t\tmodel.addAttribute(\"appAuditList\", appAuditList);\n\t\t\tmodel.addAttribute(\"appDesc\", appDesc);\n\t\t}\n\t\treturn new ModelAndView(\"manage/appOps/appInfoAndAudit\");\n\t}\n\t\n\t/**\n     * redisCluster节点删除: forget + shutdown\n     * \n     * @param appId 应用id\n     * @param forgetInstanceId 需要被forget的节点\n     * @return\n     */\n    @RequestMapping(\"/clusterDelNode\")\n    public ModelAndView clusterDelNode(HttpServletRequest request, HttpServletResponse response, Model model, Long appId,\n            int delNodeInstanceId) {\n        AppUser appUser = getUserInfo(request);\n        logger.warn(\"user {}, clusterForget: appId:{}, instanceId:{}\", appUser.getName(), appId, delNodeInstanceId);\n        // 检测forget条件\n        ClusterOperateResult checkClusterForgetResult = null;\n        try {\n            checkClusterForgetResult = redisDeployCenter.checkClusterForget(appId, delNodeInstanceId);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n        if (checkClusterForgetResult == null || !checkClusterForgetResult.isSuccess()) {\n            model.addAttribute(\"success\", checkClusterForgetResult.getStatus());\n            model.addAttribute(\"message\", checkClusterForgetResult.getMessage());\n            return new ModelAndView(\"\");\n        }\n        \n        // 执行delnode:forget + shutdown\n        ClusterOperateResult delNodeResult = null;\n        try {\n            delNodeResult = redisDeployCenter.delNode(appId, delNodeInstanceId);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n        model.addAttribute(\"success\", delNodeResult.getStatus());\n        model.addAttribute(\"message\", delNodeResult.getMessage());\n        logger.warn(\"user {}, clusterForget: appId:{}, instanceId:{}, result is {}\", appUser.getName(), appId, delNodeInstanceId, delNodeResult.getStatus());\n        \n        return new ModelAndView(\"\");\n        \n    }\n\n\t/**\n\t * redisCluster从节点failover\n\t * \n\t * @param appId 应用id\n\t * @param slaveInstanceId 从节点instanceId\n\t * @return\n\t */\n\t@RequestMapping(\"/clusterSlaveFailOver\")\n\tpublic void clusterSlaveFailOver(HttpServletRequest request, HttpServletResponse response, Model model, Long appId,\n\t\t\tint slaveInstanceId) {\n\t\tboolean success = false;\n\t\tString failoverParam = request.getParameter(\"failoverParam\");\n\t\tlogger.warn(\"clusterSlaveFailOver: appId:{}, slaveInstanceId:{}, failoverParam:{}\", appId, slaveInstanceId, failoverParam);\n\t\tif (appId != null && appId > 0 && slaveInstanceId > 0) {\n\t\t\ttry {\n\t\t\t\tsuccess = redisDeployCenter.clusterFailover(appId, slaveInstanceId, failoverParam);\n\t\t\t} catch (Exception e) {\n\t\t\t\tlogger.error(e.getMessage(), e);\n\t\t\t}\n\t\t} else {\n\t\t\tlogger.error(\"error param clusterSlaveFailOver: appId:{}, slaveInstanceId:{}, failoverParam:{}\", appId, slaveInstanceId, failoverParam);\n\t\t}\n\t    logger.warn(\"clusterSlaveFailOver: appId:{}, slaveInstanceId:{}, failoverParam:{}, result is {}\", appId, slaveInstanceId, failoverParam, success);\n\t\twrite(response, String.valueOf(success == true ? SuccessEnum.SUCCESS.value() : SuccessEnum.FAIL.value()));\n\t}\n\n\t/**\n\t * 添加slave节点\n\t * \n\t * @param appId\n\t * @param masterInstanceId\n\t * @param slaveHost\n\t * @return\n\t */\n    @RequestMapping(value = \"/addSlave\")\n    public void addSlave(HttpServletRequest request, HttpServletResponse response, Model model, long appId,\n            int masterInstanceId, String slaveHost) {\n        AppUser appUser = getUserInfo(request);\n        logger.warn(\"user {} addSlave: appId:{},masterInstanceId:{},slaveHost:{}\", appUser.getName(), appId, masterInstanceId, slaveHost);\n        boolean success = false;\n        if (appId > 0 && StringUtils.isNotBlank(slaveHost) && masterInstanceId > 0) {\n            try {\n                success = redisDeployCenter.addSlave(appId, masterInstanceId, slaveHost);\n            } catch (Exception e) {\n                logger.error(e.getMessage(), e);\n            }\n        } \n        logger.warn(\"user {} addSlave: appId:{},masterInstanceId:{},slaveHost:{} result is {}\", appUser.getName(), appId, masterInstanceId, slaveHost, success);\n        write(response, String.valueOf(success == true ? SuccessEnum.SUCCESS.value() : SuccessEnum.FAIL.value()));\n    }\n\n    /**\n     * 添加sentinel节点\n     * @param appId\n     * @param sentinelHost\n     * @return\n     */\n\t@RequestMapping(value = \"/addSentinel\")\n\tpublic void addSentinel(HttpServletRequest request, HttpServletResponse response, Model model, long appId, String sentinelHost) {\n        AppUser appUser = getUserInfo(request);\n\t\tlogger.warn(\"user {} addSentinel: appId:{}, sentinelHost:{}\", appUser.getName(), appId, sentinelHost);\n\t    boolean success = false;\n\t\tif (appId > 0 && StringUtils.isNotBlank(sentinelHost)) {\n\t\t\ttry {\n\t\t\t\tsuccess = redisDeployCenter.addSentinel(appId, sentinelHost);\n\t\t\t} catch (Exception e) {\n\t\t\t\tlogger.error(e.getMessage(), e);\n\t\t\t}\n\t\t}\n\t    logger.warn(\"user {} addSentinel: appId:{}, sentinelHost:{} result is {}\", appUser.getName(), appId, sentinelHost, success);\n\t\twrite(response, String.valueOf(success == true ? SuccessEnum.SUCCESS.value() : SuccessEnum.FAIL.value()));\n\t}\n\t\n\t/**\n\t * 为失联的slot添加master节点\n\t * @param appId\n\t * @param sentinelHost\n\t */\n\t@RequestMapping(value = \"/addFailSlotsMaster\")\n    public void addFailSlotsMaster(HttpServletRequest request, HttpServletResponse response, Model model, long appId, String failSlotsMasterHost, int instanceId) {\n        AppUser appUser = getUserInfo(request);\n        logger.warn(\"user {} addFailSlotsMaster: appId:{}, instanceId {}, newMasterHost:{}\", appUser.getName(), appId, instanceId, failSlotsMasterHost);\n        RedisOperateEnum redisOperateEnum = RedisOperateEnum.FAIL;\n        if (appId > 0 && StringUtils.isNotBlank(failSlotsMasterHost)) {\n            try {\n                redisOperateEnum = redisDeployCenter.addSlotsFailMaster(appId, instanceId, failSlotsMasterHost);\n            } catch (Exception e) {\n                logger.error(e.getMessage(), e);\n            }\n        }\n        logger.warn(\"user {} addFailSlotsMaster: appId:{}, instanceId {}, newMasterHost:{} result is {}\", appUser.getName(), appId, instanceId, failSlotsMasterHost, redisOperateEnum.getValue());\n        write(response, String.valueOf(redisOperateEnum.getValue()));\n    }\n\n\t\n\t\n\t/**\n\t * sentinelFailOver操作\n\t * \n\t * @param appId\n\t * @return\n\t */\n    @RequestMapping(\"/sentinelFailOver\")\n\tpublic void sentinelFailOver(HttpServletRequest request, HttpServletResponse response, Model model, long appId) {\n        AppUser appUser = getUserInfo(request);\n\t\tlogger.warn(\"user {} sentinelFailOver, appId:{}\", appUser.getName(), appId);\n\t    boolean success = false;\n\t\tif (appId > 0) {\n\t\t\ttry {\n\t\t\t\tsuccess = redisDeployCenter.sentinelFailover(appId);\n\t\t\t} catch (Exception e) {\n\t\t\t\tlogger.error(e.getMessage(), e);\n\t\t\t}\n\t\t} else {\n\t\t\tlogger.error(\"error param, sentinelFailOver: appId:{}\", appId);\n\t\t}\n\t    logger.warn(\"user {} sentinelFailOver, appId:{}, result is {}\", appUser.getName(), appId, success);\n\t\twrite(response, String.valueOf(success == true ? SuccessEnum.SUCCESS.value() : SuccessEnum.FAIL.value()));\n\t}\n    \n    /**\n     * 应用重要性级别\n     */\n    @RequestMapping(value = \"/updateAppImportantLevel\")\n    public ModelAndView doUpdateAppImportantLevel(HttpServletRequest request, HttpServletResponse response, Model model) {\n        long appId = NumberUtils.toLong(request.getParameter(\"appId\"));\n        int importantLevel = NumberUtils.toInt(request.getParameter(\"importantLevel\"));\n        SuccessEnum successEnum = SuccessEnum.FAIL;\n        if (appId > 0 && importantLevel >= 0) {\n            try {\n                AppDesc appDesc = appService.getByAppId(appId);\n                appDesc.setImportantLevel(importantLevel);\n                appService.update(appDesc);\n                successEnum = SuccessEnum.SUCCESS;\n            } catch (Exception e) {\n                logger.error(e.getMessage(), e);\n            }\n        }\n        model.addAttribute(\"status\", successEnum.value());\n        return new ModelAndView(\"\");\n    }\n    \n    /**\n     * 更新应用密码\n     */\n    @RequestMapping(value = \"/updateAppPassword\")\n    public ModelAndView doUpdateAppPassword(HttpServletRequest request, HttpServletResponse response, Model model) {\n        long appId = NumberUtils.toLong(request.getParameter(\"appId\"));\n        String password = request.getParameter(\"password\");\n        SuccessEnum successEnum = SuccessEnum.FAIL;\n        if (appId > 0) {\n            try {\n                AppDesc appDesc = appService.getByAppId(appId);\n                appDesc.setPassword(password);\n                appService.update(appDesc);\n                successEnum = SuccessEnum.SUCCESS;\n            } catch (Exception e) {\n                logger.error(e.getMessage(), e);\n            }\n        }\n        model.addAttribute(\"status\", successEnum.value());\n        return new ModelAndView(\"\");\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/controller/BaseController.java",
    "content": "package com.sohu.cache.web.controller;\n\nimport java.io.IOException;\nimport java.io.PrintWriter;\nimport java.text.ParseException;\nimport java.util.ArrayList;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\nimport com.sohu.cache.web.service.AppService;\nimport com.sohu.cache.web.service.UserLoginStatusService;\nimport com.sohu.cache.web.service.UserService;\nimport com.sohu.cache.web.util.DateUtil;\n\nimport org.apache.commons.collections.CollectionUtils;\nimport org.apache.commons.lang.StringUtils;\nimport org.apache.commons.lang.exception.ExceptionUtils;\nimport org.apache.commons.lang.math.NumberUtils;\nimport org.apache.commons.lang.time.DateUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.ui.Model;\n\nimport com.sohu.cache.constant.AppUserTypeEnum;\nimport com.sohu.cache.entity.AppToUser;\nimport com.sohu.cache.entity.AppUser;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.entity.InstanceSlotModel;\nimport com.sohu.cache.entity.InstanceStats;\nimport com.sohu.cache.entity.TimeBetween;\nimport com.sohu.cache.machine.MachineCenter;\nimport com.sohu.cache.redis.RedisCenter;\n\n/**\n * 基类controller\n *\n * @author leifu\n * @Time 2014年10月16日\n */\npublic class BaseController {\n    protected final Logger logger = LoggerFactory.getLogger(getClass());\n\n    protected UserService userService;\n    \n    protected AppService appService;\n    \n    protected MachineCenter machineCenter;\n    \n    protected UserLoginStatusService userLoginStatusService;\n    \n    protected RedisCenter redisCenter;\n\n    public void setUserService(UserService userService) {\n        this.userService = userService;\n    }\n\n    public void setAppService(AppService appService) {\n        this.appService = appService;\n    }\n\n    public void setMachineCenter(MachineCenter machineCenter) {\n        this.machineCenter = machineCenter;\n    }\n\n    public void setUserLoginStatusService(UserLoginStatusService userLoginStatusService) {\n        this.userLoginStatusService = userLoginStatusService;\n    }\n\n    public void setRedisCenter(RedisCenter redisCenter) {\n\t\tthis.redisCenter = redisCenter;\n\t}\n    \n    protected TimeBetween getJsonTimeBetween(HttpServletRequest request) throws ParseException {\n        String startDateParam = request.getParameter(\"startDate\");\n        String endDateParam = request.getParameter(\"endDate\");\n        Date startDate = DateUtil.parseYYYY_MM_dd(startDateParam);\n        Date endDate = DateUtil.parseYYYY_MM_dd(endDateParam);\n        long beginTime = NumberUtils.toLong(DateUtil.formatYYYYMMddHHMM(startDate));\n        long endTime = NumberUtils.toLong(DateUtil.formatYYYYMMddHHMM(endDate));\n        return new TimeBetween(beginTime, endTime, startDate, endDate);\n    }\n    \n    protected TimeBetween getTimeBetween(HttpServletRequest request, Model model, String startDateAtr,\n            String endDateAtr) throws ParseException {\n        String startDateParam = request.getParameter(startDateAtr);\n        String endDateParam = request.getParameter(endDateAtr);\n        Date startDate;\n        Date endDate;\n        if (StringUtils.isBlank(startDateParam) || StringUtils.isBlank(endDateParam)) {\n            startDate = new Date();\n            endDate = DateUtils.addDays(startDate, 1);\n        } else {\n            endDate = DateUtil.parseYYYY_MM_dd(endDateParam);\n            startDate = DateUtil.parseYYYY_MM_dd(startDateParam);\n        }\n        Date yesterDay = DateUtils.addDays(startDate, -1);\n        \n        long beginTime = NumberUtils.toLong(DateUtil.formatYYYYMMddHHMM(startDate));\n        long endTime = NumberUtils.toLong(DateUtil.formatYYYYMMddHHMM(endDate));\n        model.addAttribute(startDateAtr, startDateParam);\n        model.addAttribute(endDateAtr, endDateParam);\n        model.addAttribute(\"yesterDay\", DateUtil.formatDate(yesterDay, \"yyyy-MM-dd\"));\n        return new TimeBetween(beginTime, endTime, startDate, endDate);\n    }\n\n\t/**\n     * 返回用户基本信息\n     *\n     * @param request\n     * @return\n     */\n    public AppUser getUserInfo(HttpServletRequest request) {\n        long userId = userLoginStatusService.getUserIdFromLoginStatus(request);\n        return userService.get(userId);\n    }\n\n\n    /**\n     * 发送json消息\n     *\n     * @param response\n     * @param message\n     */\n    public void sendMessage(HttpServletResponse response, String message) {\n        response.reset();\n        response.setContentType(\"application/X-JSON;charset=UTF-8\");\n        PrintWriter printWriter = null;\n        try {\n            printWriter = response.getWriter();\n            printWriter.write(message);\n        } catch (IOException e) {\n            logger.error(ExceptionUtils.getFullStackTrace(e));\n        } finally {\n            if (printWriter != null) {\n                printWriter.flush();\n                printWriter.close();\n            }\n        }\n\n    }\n\n    /**\n     * @param response\n     * @param result\n     */\n    protected void write(HttpServletResponse response, String result) {\n        try {\n            response.setContentType(\"text/javascript\");\n            response.getWriter().print(result);\n            response.getWriter().flush();\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n    }\n    \n    /**\n     * 查看用户对于app操作的权限\n     * @param request\n     * @param appId\n     * @return\n     */\n    protected boolean checkAppUserProvilege(HttpServletRequest request, long appId) {\n        // 当前用户\n        AppUser currentUser = getUserInfo(request);\n        if (currentUser == null) {\n            logger.error(\"currentUser is empty\");\n            return false;\n        }\n        \n        if (AppUserTypeEnum.ADMIN_USER.value().equals(currentUser.getType())) {\n            return true;\n        }\n\n        // 应用用户列表\n        List<AppToUser> appToUsers = appService.getAppToUserList(appId);\n        if (CollectionUtils.isEmpty(appToUsers)) {\n            logger.error(\"appId {} userList is empty\", appId);\n            return false;\n        }\n\n        // 应用下用户id集合\n        Set<Long> appUserIdSet = new HashSet<Long>();\n        for (AppToUser appToUser : appToUsers) {\n            appUserIdSet.add(appToUser.getUserId());\n        }\n        \n        //最终判断\n        if (!appUserIdSet.contains(currentUser.getId())) {\n            logger.error(\"currentUser {} hasn't previlege in appId {}\", currentUser.getId(), appId);\n            return false;\n        }\n        return true;\n    }\n    \n    /**\n     * 实例统计信息\n     * \n     * @param appId\n     * @param model\n     */\n    protected void fillAppInstanceStats(Long appId, Model model) {\n        // 实例列表\n        List<InstanceInfo> instanceList = appService.getAppInstanceInfo(appId);\n        model.addAttribute(\"instanceList\", instanceList);\n        \n        // 实例Map\n        Map<Integer, InstanceInfo> instanceInfoMap = new HashMap<Integer, InstanceInfo>();\n        for (InstanceInfo instanceInfo : instanceList) {\n            instanceInfoMap.put(instanceInfo.getId(), instanceInfo);\n        }\n        model.addAttribute(\"instanceInfoMap\", instanceInfoMap);\n        \n        // 实例统计\n        List<InstanceStats> appInstanceStats = appService.getAppInstanceStats(appId);\n        Map<String, InstanceStats> instanceStatsMap = new HashMap<String, InstanceStats>();\n        for (InstanceStats instanceStats : appInstanceStats) {\n            instanceStatsMap.put(instanceStats.getIp() + \":\" + instanceStats.getPort(), instanceStats);\n        }\n        model.addAttribute(\"instanceStatsMap\", instanceStatsMap);\n        \n        //slot分布\n        Map<String, InstanceSlotModel> clusterSlotsMap = redisCenter.getClusterSlotsMap(appId);\n\t\tmodel.addAttribute(\"clusterSlotsMap\", clusterSlotsMap);\n        \n    }\n    \n    /**\n     * 应用机器实例分布图\n     * @param appId\n     * @param model\n     */\n    protected void fillAppMachineInstanceTopology(Long appId, Model model) {\n        List<InstanceInfo> instanceList = appService.getAppInstanceInfo(appId);\n        int groupId = 1;\n        // 1.分组，同一个主从在一组\n        for (int i = 0; i < instanceList.size(); i++) {\n            InstanceInfo instance = instanceList.get(i);\n            // 有了groupId，不再设置\n            if (instance.getGroupId() > 0) {\n                continue;\n            }\n            if (instance.isOffline()) {\n                continue;\n            }\n            for (int j = i + 1; j < instanceList.size(); j++) {\n                InstanceInfo instanceCompare = instanceList.get(j);\n                if (instanceCompare.isOffline()) {\n                    continue;\n                }\n                // 寻找主从对应关系\n                if (instanceCompare.getMasterInstanceId() == instance.getId()\n                        || instance.getMasterInstanceId() == instanceCompare.getId()) {\n                    instanceCompare.setGroupId(groupId);\n                }\n            }\n            instance.setGroupId(groupId++);\n        }\n\n        // 2.机器下的实例列表\n        Map<String, List<InstanceInfo>> machineInstanceMap = new HashMap<String, List<InstanceInfo>>();\n        for (InstanceInfo instance : instanceList) {\n            String ip = instance.getIp();\n            if (machineInstanceMap.containsKey(ip)) {\n                machineInstanceMap.get(ip).add(instance);\n            } else {\n                List<InstanceInfo> tempInstanceList = new ArrayList<InstanceInfo>();\n                tempInstanceList.add(instance);\n                machineInstanceMap.put(ip, tempInstanceList);\n            }\n        }\n\n        model.addAttribute(\"machineInstanceMap\", machineInstanceMap);\n        model.addAttribute(\"instancePairCount\", groupId - 1);\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/controller/ClientManageController.java",
    "content": "package com.sohu.cache.web.controller;\n\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport javax.annotation.Resource;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\nimport org.apache.commons.lang.math.NumberUtils;\nimport org.apache.commons.lang.time.DateUtils;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.servlet.ModelAndView;\n\nimport com.sohu.cache.client.service.ClientReportExceptionService;\nimport com.sohu.cache.client.service.ClientVersionService;\nimport com.sohu.cache.entity.AppClientVersion;\nimport com.sohu.cache.entity.AppDesc;\nimport com.sohu.cache.entity.ClientInstanceException;\nimport com.sohu.cache.web.enums.SuccessEnum;\n\n/**\n * 客户端管理\n * \n * @author leifu\n * @Date 2016年2月18日\n * @Time 下午4:55:32\n */\n@Controller\n@RequestMapping(\"manage/client\")\npublic class ClientManageController extends BaseController {\n\n    /**\n     * 客户端异常服务\n     */\n    @Resource(name = \"clientReportExceptionService\")\n    private ClientReportExceptionService clientReportExceptionService;\n    \n    /**\n     * 客户端版本服务\n     */\n    @Resource(name = \"clientVersionService\")\n    private ClientVersionService clientVersionService;\n\n    /**\n     * /manage/client/exception\n     * @param request\n     * @param response\n     * @param model\n     * @return\n     */\n    @RequestMapping(value = \"/exception\")\n    public ModelAndView doClientExceptionStat(HttpServletRequest request, HttpServletResponse response, Model model) {\n        String ip = request.getParameter(\"ip\");\n        model.addAttribute(\"ip\", ip);\n        //近一个月\n        long collectTime = NumberUtils.toLong(new SimpleDateFormat(\"yyyyMMdd000000\").format(DateUtils.addMonths(new Date(), -1)));\n        \n        // 一段时间内客户端异常\n        List<ClientInstanceException> clientInstanceExceptionList = clientReportExceptionService.getInstanceExceptionStat(ip, collectTime);\n        model.addAttribute(\"clientInstanceExceptionList\", clientInstanceExceptionList);\n        \n        // 应用相关map\n        fillAppInfoMap(model);\n        \n        model.addAttribute(\"clientExceptionActive\", SuccessEnum.SUCCESS.value());\n        return new ModelAndView(\"manage/client/exception/list\");\n    }\n\n    private void fillAppInfoMap(Model model) {\n        List<AppDesc> appDescList = appService.getAllAppDesc();\n        \n        // 所有应用id和负责人对应关系\n        Map<Long, String> appIdOwnerMap = new HashMap<Long, String>();\n        for (AppDesc appDesc : appDescList) {\n            appIdOwnerMap.put(appDesc.getAppId(), appDesc.getOfficer());\n        }\n        model.addAttribute(\"appIdOwnerMap\", appIdOwnerMap);\n        \n        // 所有应用id和应用名对应关系\n        Map<Long, String> appIdNameMap = new HashMap<Long, String>();\n        for (AppDesc appDesc : appDescList) {\n            appIdNameMap.put(appDesc.getAppId(), appDesc.getName());\n        }\n        model.addAttribute(\"appIdNameMap\", appIdNameMap);\n    }\n\n    /**\n     * /manage/client/version\n     * @param request\n     * @param response\n     * @param model\n     * @return\n     */\n    @RequestMapping(value = \"/version\")\n    public ModelAndView doVersionStat(HttpServletRequest request, HttpServletResponse response, Model model) {\n        long appId = NumberUtils.toLong(request.getParameter(\"appId\"),-1);\n        List<AppClientVersion> appClientVersionList =  clientVersionService.getAll(appId);\n        \n        // 应用相关map\n        fillAppInfoMap(model);\n        \n        model.addAttribute(\"appClientVersionList\", appClientVersionList);\n        model.addAttribute(\"clientVersionActive\", SuccessEnum.SUCCESS.value());\n        model.addAttribute(\"appId\", request.getParameter(\"appId\"));\n        \n        return new ModelAndView(\"manage/client/version/list\");\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/controller/ConfigManageController.java",
    "content": "package com.sohu.cache.web.controller;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\n\nimport javax.annotation.Resource;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\nimport org.apache.commons.collections.MapUtils;\nimport org.apache.commons.lang.StringUtils;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.servlet.ModelAndView;\n\nimport com.sohu.cache.entity.AppUser;\nimport com.sohu.cache.entity.SystemConfig;\nimport com.sohu.cache.web.enums.SuccessEnum;\nimport com.sohu.cache.web.service.ConfigService;\nimport com.sohu.cache.web.util.AppEmailUtil;\n\n/**\n * cachecloud配置管理\n * \n * @author leifu\n * @Date 2016年5月23日\n * @Time 上午10:31:16\n */\n@Controller\n@RequestMapping(\"manage/config\")\npublic class ConfigManageController extends BaseController {\n\n    @Resource(name = \"configService\")\n    private ConfigService configService;\n    \n    @Resource(name = \"appEmailUtil\")\n    private AppEmailUtil appEmailUtil;\n\n    /**\n     * 初始化配置\n     * \n     * @param request\n     * @param response\n     * @param model\n     * @return\n     */\n    @RequestMapping(value = \"/init\")\n    public ModelAndView init(HttpServletRequest request, HttpServletResponse response, Model model) {\n        List<SystemConfig> configList = configService.getConfigList(1);\n        model.addAttribute(\"configList\", configList);\n        model.addAttribute(\"success\", request.getParameter(\"success\"));\n        model.addAttribute(\"configActive\", SuccessEnum.SUCCESS.value());\n        return new ModelAndView(\"manage/config/init\");\n    }\n\n    /**\n     * 修改配置\n     * \n     * @param request\n     * @param response\n     * @param model\n     * @return\n     */\n    @RequestMapping(value = \"/update\")\n    public ModelAndView update(HttpServletRequest request, HttpServletResponse response, Model model) {\n        AppUser appUser = getUserInfo(request);\n        logger.warn(\"user {} want to change config!\", appUser.getName());\n        List<SystemConfig> oldConfigList = configService.getConfigList(1);\n        SuccessEnum successEnum;\n        Map<String, String> configMap = new HashMap<String, String>();\n        try {\n            Map<String, String[]> paramMap = request.getParameterMap();\n            for (Entry<String, String[]> entry : paramMap.entrySet()) {\n                String key = entry.getKey();\n                String value = entry.getValue()[0];\n                if (StringUtils.isNotBlank(key)) {\n                    configMap.put(key, value);\n                }\n            }\n            if (MapUtils.isEmpty(configMap)) {\n                logger.error(\"params {} may be empty!!\", paramMap);\n            }\n            successEnum = configService.updateConfig(configMap);\n            if (successEnum.equals(SuccessEnum.SUCCESS)) {\n                configService.reloadSystemConfig();\n            }\n        } catch (Exception e) {\n            successEnum = SuccessEnum.FAIL;\n            logger.error(e.getMessage(), e);\n        }\n        Map<String, String> systemDifConfigMap = getDifConfigMap(oldConfigList, configMap);\n        appEmailUtil.sendSystemConfigDifEmail(appUser, systemDifConfigMap, successEnum);\n        logger.warn(\"user {} change config result is {}!\", appUser.getName(), successEnum.value());\n        return new ModelAndView(\"redirect:/manage/config/init?success=\" + successEnum.value());\n    }\n\n    private Map<String, String> getDifConfigMap(List<SystemConfig> oldConfigList, Map<String, String> configMap) {\n        Map<String, String> systemDifConfigMap = new HashMap<String, String>();\n        for (SystemConfig systemConfig : oldConfigList) {\n            String key = systemConfig.getConfigKey();\n            String oldValue = systemConfig.getConfigValue();\n            String newValue = configMap.get(key);\n            if (newValue != null && !oldValue.equals(newValue)) {\n                systemDifConfigMap.put(systemConfig.getInfo(), String.format(\"old value: %s, new value: %s\", oldValue, newValue));\n            }\n        }\n        return systemDifConfigMap;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/controller/FaultController.java",
    "content": "package com.sohu.cache.web.controller;\n\nimport java.util.List;\n\nimport javax.annotation.Resource;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.servlet.ModelAndView;\n\nimport com.sohu.cache.entity.InstanceFault;\nimport com.sohu.cache.web.service.MemFaultService;\n\n/**\n * 故障展示\n * @author leifu\n * @Time 2014年6月12日\n */\n@Controller\n@RequestMapping(\"manage/fault\")\npublic class FaultController extends BaseController {\n\n    @Resource(name = \"memFaultService\")\n    private MemFaultService memFaultService;\n\n    \n    @RequestMapping(value = \"/list\")\n    public ModelAndView doUserList(HttpServletRequest request,\n            HttpServletResponse response, Model model) {\n        List<InstanceFault> faults = memFaultService.getFaultList();\n        model.addAttribute(\"faults\", faults);\n        return new ModelAndView(\"manage/fault/list\");\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/controller/ImportAppController.java",
    "content": "package com.sohu.cache.web.controller;\n\nimport java.util.Date;\n\nimport javax.annotation.Resource;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\nimport org.apache.commons.lang.math.NumberUtils;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.servlet.ModelAndView;\n\nimport com.sohu.cache.constant.ImportAppResult;\nimport com.sohu.cache.entity.AppDesc;\nimport com.sohu.cache.entity.AppUser;\nimport com.sohu.cache.stats.app.ImportAppCenter;\n\n/**\n * 已经存在Redis导入\n * \n * @author leifu\n * @Date 2016-4-16\n * @Time 下午2:31:14\n */\n@Controller\n@RequestMapping(\"/import/app\")\npublic class ImportAppController extends BaseController {\n\n    @Resource(name = \"importAppCenter\")\n    private ImportAppCenter importAppCenter;\n\n    @RequestMapping(value = \"/init\")\n    public ModelAndView init(HttpServletRequest request, HttpServletResponse response, Model model) {\n        return new ModelAndView(\"import/init\");\n    }\n\n    @RequestMapping(value = \"/check\")\n    public ModelAndView check(HttpServletRequest request, HttpServletResponse response, Model model) {\n        AppDesc appDesc = genAppDesc(request);\n        String appInstanceInfo = request.getParameter(\"appInstanceInfo\");\n        ImportAppResult importAppResult = importAppCenter.check(appDesc, appInstanceInfo);\n        model.addAttribute(\"status\", importAppResult.getStatus());\n        model.addAttribute(\"message\", importAppResult.getMessage());\n        return new ModelAndView(\"\");\n    }\n\n    @RequestMapping(value = \"/add\")\n    public ModelAndView add(HttpServletRequest request,\n            HttpServletResponse response, Model model) {\n        AppDesc appDesc = genAppDesc(request);\n        String appInstanceInfo = request.getParameter(\"appInstanceInfo\");\n        logger.warn(\"appDesc:\" + appDesc);\n        logger.warn(\"appInstanceInfo: \" + appInstanceInfo);\n\n        // 不需要对格式进行检验,check已经做过了。\n        boolean isSuccess = importAppCenter.importAppAndInstance(appDesc, appInstanceInfo);\n        logger.warn(\"import app result is {}\", isSuccess);\n\n        model.addAttribute(\"status\", isSuccess ? 1 : 0);\n        return new ModelAndView(\"\");\n    }\n\n    /**\n     * 生成AppDesc\n     * \n     * @param request\n     * @return\n     */\n    private AppDesc genAppDesc(HttpServletRequest request) {\n        // 当前用户\n        AppUser currentUser = getUserInfo(request);\n        // 当前时间\n        Date date = new Date();\n        // 组装Appdesc\n        AppDesc appDesc = new AppDesc();\n        appDesc.setName(request.getParameter(\"name\"));\n        appDesc.setIntro(request.getParameter(\"intro\"));\n        appDesc.setOfficer(request.getParameter(\"officer\"));\n        appDesc.setType(NumberUtils.toInt(request.getParameter(\"type\")));\n        appDesc.setIsTest(NumberUtils.toInt(request.getParameter(\"isTest\")));\n        appDesc.setMemAlertValue(NumberUtils.toInt(request.getParameter(\"memAlertValue\")));\n        appDesc.setPassword(request.getParameter(\"password\"));\n        appDesc.setUserId(currentUser.getId());\n        appDesc.setStatus(2);\n        appDesc.setCreateTime(date);\n        appDesc.setPassedTime(date);\n        appDesc.setVerId(1);\n\n        return appDesc;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/controller/IndexController.java",
    "content": "package com.sohu.cache.web.controller;\n\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.servlet.ModelAndView;\n\n/**\n * 首页\n * @author leifu\n * @Date 2014年10月28日\n * @Time 上午10:49:32\n */\n@Controller\n@RequestMapping(\"/\")\npublic class IndexController extends BaseController {\n\n    @RequestMapping(value = \"\")\n    public ModelAndView index(HttpServletRequest request,\n                        HttpServletResponse response, Model model){\n        return new ModelAndView(\"redirect:/admin/app/list\");\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/controller/InstanceAlertValueController.java",
    "content": "package com.sohu.cache.web.controller;\n\nimport java.util.Date;\nimport java.util.List;\n\nimport javax.annotation.Resource;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\nimport org.apache.commons.collections.CollectionUtils;\nimport org.apache.commons.lang.StringUtils;\nimport org.apache.commons.lang.math.NumberUtils;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.servlet.ModelAndView;\n\nimport com.sohu.cache.constant.ErrorMessageEnum;\nimport com.sohu.cache.dao.InstanceDao;\nimport com.sohu.cache.entity.AppUser;\nimport com.sohu.cache.entity.InstanceAlertConfig;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.redis.enums.InstanceAlertCheckCycleEnum;\nimport com.sohu.cache.redis.enums.InstanceAlertCompareTypeEnum;\nimport com.sohu.cache.redis.enums.InstanceAlertStatusEnum;\nimport com.sohu.cache.redis.enums.InstanceAlertTypeEnum;\nimport com.sohu.cache.redis.enums.RedisAlertConfigEnum;\nimport com.sohu.cache.stats.instance.InstanceAlertConfigService;\nimport com.sohu.cache.web.enums.SuccessEnum;\n\n/**\n * 实例报警阀值\n * @author leifu\n * @Date 2016年8月24日\n * @Time 下午1:24:25\n */\n@Controller\n@RequestMapping(\"manage/instanceAlert\")\npublic class InstanceAlertValueController extends BaseController {\n    \n    @Resource(name = \"instanceAlertConfigService\")\n    private InstanceAlertConfigService instanceAlertConfigService;\n    \n    @Resource(name = \"instanceDao\")\n    private InstanceDao instanceDao;\n    \n    /**\n     * 初始化配置\n     */\n    @RequestMapping(value = \"/init\")\n    public ModelAndView init(HttpServletRequest request, HttpServletResponse response, Model model) {\n        model.addAttribute(\"instanceAlertCheckCycleEnumList\", InstanceAlertCheckCycleEnum.getInstanceAlertCheckCycleEnumList());\n        model.addAttribute(\"instanceAlertCompareTypeEnumList\", InstanceAlertCompareTypeEnum.getInstanceAlertCompareTypeEnumList());\n        model.addAttribute(\"redisAlertConfigEnumList\", RedisAlertConfigEnum.getRedisAlertConfigEnumList());\n        model.addAttribute(\"instanceAlertAllList\", instanceAlertConfigService.getByType(InstanceAlertTypeEnum.ALL_ALERT.getValue()));\n        model.addAttribute(\"instanceAlertList\", instanceAlertConfigService.getAll());\n        model.addAttribute(\"success\", request.getParameter(\"success\"));\n        model.addAttribute(\"instanceAlertValueActive\", SuccessEnum.SUCCESS.value());\n        List<InstanceAlertConfig> instanceAlertSpecialList = instanceAlertConfigService.getByType(InstanceAlertTypeEnum.INSTANCE_ALERT.getValue());\n        fillinstanceHostPort(instanceAlertSpecialList);\n        model.addAttribute(\"instanceAlertSpecialList\", instanceAlertSpecialList);\n        return new ModelAndView(\"manage/instanceAlert/init\");\n    }\n    \n    /**\n     * 填充hostport\n     * @param instanceAlertSpecialList\n     */\n    private void fillinstanceHostPort(List<InstanceAlertConfig> instanceAlertSpecialList) {\n        if (CollectionUtils.isEmpty(instanceAlertSpecialList)) {\n            return;\n        }\n        for (InstanceAlertConfig instanceAlertConfig : instanceAlertSpecialList) {\n            long instanceId = instanceAlertConfig.getInstanceId();\n            InstanceInfo instanceInfo = instanceDao.getInstanceInfoById(instanceId);\n            if (instanceInfo == null) {\n                continue;\n            }\n            instanceAlertConfig.setInstanceInfo(instanceInfo);\n        }\n    }\n\n    /**\n     * 添加配置\n     */\n    @RequestMapping(value = \"/add\")\n    public ModelAndView add(HttpServletRequest request, HttpServletResponse response, Model model) {\n        AppUser appUser = getUserInfo(request);\n        InstanceAlertConfig instanceAlertConfig = getInstanceAlertConfig(request);\n        SuccessEnum successEnum;\n        try {\n            logger.warn(\"user {} want to add instanceAlertConfig {}, result is {}\", appUser.getName(), instanceAlertConfig);\n            instanceAlertConfigService.save(instanceAlertConfig);\n            successEnum = SuccessEnum.SUCCESS;\n        } catch (Exception e) {\n            successEnum = SuccessEnum.FAIL;\n            model.addAttribute(\"message\", ErrorMessageEnum.INNER_ERROR_MSG.getMessage());\n            logger.error(e.getMessage(), e);\n        }\n        logger.warn(\"user {} add instanceAlertConfig {}, result is {}\", appUser.getName(),instanceAlertConfig,successEnum.value());\n        model.addAttribute(\"status\", successEnum.value());\n        return new ModelAndView(\"\");\n    }\n    \n    /**\n     * 检查hostPort是否存在\n     */\n    @RequestMapping(value = \"/checkInstanceHostPort\")\n    public ModelAndView checkInstanceHostPort(HttpServletRequest request, HttpServletResponse response, Model model) {\n        String hostPort = request.getParameter(\"instanceHostPort\");\n        if (StringUtils.isBlank(hostPort)) {\n            model.addAttribute(\"status\", SuccessEnum.FAIL.value());\n            model.addAttribute(\"message\",\"参数为空\");\n            return new ModelAndView(\"\");\n        }\n        String[] hostPortArr = hostPort.split(\":\");\n        if (hostPortArr.length != 2) {\n            model.addAttribute(\"status\", SuccessEnum.FAIL.value());\n            model.addAttribute(\"message\",\"hostPort:\" + hostPort + \"格式错误\");\n            return new ModelAndView(\"\");\n        }\n        String host = hostPortArr[0];\n        int port = NumberUtils.toInt(hostPortArr[1]);\n        InstanceInfo instanceInfo = instanceDao.getAllInstByIpAndPort(host, port);\n        if (instanceInfo == null) {\n            model.addAttribute(\"status\", SuccessEnum.FAIL.value());\n            model.addAttribute(\"message\",\"hostPort:\" + hostPort + \"不存在\");\n        } else {\n            model.addAttribute(\"status\", SuccessEnum.SUCCESS.value());\n        }\n        return new ModelAndView(\"\");\n    }\n    \n    /**\n     * 初始化配置\n     */\n    @RequestMapping(value = \"/monitor\")\n    public ModelAndView monitor(HttpServletRequest request, HttpServletResponse response, Model model) {\n        instanceAlertConfigService.monitorLastMinuteAllInstanceInfo();\n        return null;\n    }\n\n    /**\n     * 修改配置\n     */\n    @RequestMapping(value = \"/update\")\n    public ModelAndView update(HttpServletRequest request, HttpServletResponse response, Model model) {\n        AppUser appUser = getUserInfo(request);\n        int id = NumberUtils.toInt(request.getParameter(\"id\"));\n        String alertValue = request.getParameter(\"alertValue\");\n        int checkCycle = NumberUtils.toInt(request.getParameter(\"checkCycle\"));\n        logger.warn(\"user {} want to change instance alert id={}, alertValue={}, checkCycle={}\", appUser.getName(), alertValue, checkCycle);\n        SuccessEnum successEnum;\n        try {\n            instanceAlertConfigService.update(id, alertValue, checkCycle);\n            successEnum = SuccessEnum.SUCCESS;\n        } catch (Exception e) {\n            successEnum = SuccessEnum.FAIL;\n            model.addAttribute(\"message\", ErrorMessageEnum.INNER_ERROR_MSG.getMessage());\n            logger.error(e.getMessage(), e);\n        }\n        logger.warn(\"user {} change instance alert id={}, alertValue={}, checkCycle={}, result is {}\", appUser.getName(), alertValue, checkCycle, successEnum.info());\n        model.addAttribute(\"status\", successEnum.value());\n        return new ModelAndView(\"\");\n    }\n\n    /**\n     * 删除配置\n     */\n    @RequestMapping(value = \"/remove\")\n    public ModelAndView remove(HttpServletRequest request, HttpServletResponse response, Model model) {\n        AppUser appUser = getUserInfo(request);\n        int id = NumberUtils.toInt(request.getParameter(\"id\"));\n        InstanceAlertConfig instanceAlertConfig = instanceAlertConfigService.get(id);\n        logger.warn(\"user {} want to delete config id {}, instanceAlertConfig {}\", appUser.getName(), id, instanceAlertConfig);\n        SuccessEnum successEnum;\n        try {\n            instanceAlertConfigService.remove(id);\n            successEnum = SuccessEnum.SUCCESS;\n        } catch (Exception e) {\n            successEnum = SuccessEnum.FAIL;\n            model.addAttribute(\"message\", ErrorMessageEnum.INNER_ERROR_MSG.getMessage());\n            logger.error(e.getMessage(), e);\n        }\n        logger.warn(\"user {} want to delete config id {}, instanceAlertConfig {}, result is {}\", appUser.getName(), id, instanceAlertConfig, successEnum.info());\n        model.addAttribute(\"status\", successEnum.value());\n        return new ModelAndView(\"\");\n\n    }\n\n    \n    private InstanceInfo getInstanceInfo (String hostPort) {\n        String[] hostPortArr = hostPort.split(\":\");\n        String host = hostPortArr[0];\n        int port = NumberUtils.toInt(hostPortArr[1]);\n        return instanceDao.getAllInstByIpAndPort(host, port);\n    }\n\n\n    private InstanceAlertConfig getInstanceAlertConfig(HttpServletRequest request) {\n        // 相关参数\n        Date now = new Date();\n        String alertConfig = request.getParameter(\"alertConfig\");\n        String alertValue = request.getParameter(\"alertValue\");\n        RedisAlertConfigEnum redisAlertConfigEnum = RedisAlertConfigEnum.getRedisAlertConfig(alertConfig);\n        String configInfo = redisAlertConfigEnum == null ? \"\" : redisAlertConfigEnum.getInfo();\n        int compareType = NumberUtils.toInt(request.getParameter(\"compareType\"));\n        int checkCycle = NumberUtils.toInt(request.getParameter(\"checkCycle\"));\n        int instanceId = 0;\n        int type = NumberUtils.toInt(request.getParameter(\"type\"));\n        if (InstanceAlertTypeEnum.INSTANCE_ALERT.getValue() == type) {\n            String hostPort = request.getParameter(\"instanceHostPort\");\n            InstanceInfo instanceInfo = getInstanceInfo(hostPort);\n            instanceId = instanceInfo.getId();\n        }\n        // 生成对象\n        InstanceAlertConfig instanceAlertConfig = new InstanceAlertConfig();\n        instanceAlertConfig.setAlertConfig(alertConfig);\n        instanceAlertConfig.setAlertValue(alertValue);\n        instanceAlertConfig.setConfigInfo(configInfo);\n        instanceAlertConfig.setCompareType(compareType);\n        instanceAlertConfig.setInstanceId(instanceId);\n        instanceAlertConfig.setCheckCycle(checkCycle);\n        instanceAlertConfig.setLastCheckTime(now);\n        instanceAlertConfig.setType(type);\n        instanceAlertConfig.setUpdateTime(now);\n        instanceAlertConfig.setStatus(InstanceAlertStatusEnum.YES.getValue());\n        return instanceAlertConfig;\n    }\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/controller/InstanceController.java",
    "content": "package com.sohu.cache.web.controller;\n\nimport com.sohu.cache.alert.InstanceAlertService;\nimport com.sohu.cache.entity.*;\nimport com.sohu.cache.redis.RedisCenter;\nimport com.sohu.cache.stats.app.AppStatsCenter;\nimport com.sohu.cache.stats.instance.InstanceStatsCenter;\nimport com.sohu.cache.util.ConstUtils;\nimport com.sohu.cache.web.vo.RedisSlowLog;\nimport com.sohu.cache.web.chart.key.ChartKeysUtil;\nimport com.sohu.cache.web.chart.model.SplineChartEntity;\nimport com.sohu.cache.web.util.DateUtil;\nimport org.apache.commons.lang.StringUtils;\nimport org.apache.commons.lang.math.NumberUtils;\nimport org.apache.commons.lang.time.DateUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.servlet.ModelAndView;\n\nimport javax.annotation.Resource;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport java.text.ParseException;\nimport java.util.*;\n\n/**\n * Created by hym on 14-7-27.\n */\n@Controller\n@RequestMapping(\"/admin/instance\")\npublic class InstanceController {\n    private final Logger logger = LoggerFactory.getLogger(this.getClass());\n\n    @Resource(name = \"instanceStatsCenter\")\n    private InstanceStatsCenter instanceStatsCenter;\n\n    @Resource(name = \"appStatsCenter\")\n    private AppStatsCenter appStatsCenter;\n\n    @Resource(name = \"redisCenter\")\n    private RedisCenter redisCenter;\n\n    @Resource\n    private InstanceAlertService instanceAlertService;\n\n    @RequestMapping(\"/index\")\n    public ModelAndView index(HttpServletRequest request, HttpServletResponse response, Model model, Integer admin, Long instanceId, Long appId, String tabTag) {\n\n        String startDateParam = request.getParameter(\"startDate\");\n        String endDateParam = request.getParameter(\"endDate\");\n\n        if (StringUtils.isBlank(startDateParam) || StringUtils.isBlank(endDateParam)) {\n            Date endDate = new Date();\n            Date startDate = DateUtils.addDays(endDate, -1);\n            startDateParam = DateUtil.formatDate(startDate, \"yyyyMMdd\");\n            endDateParam = DateUtil.formatDate(endDate, \"yyyyMMdd\");\n        }\n        model.addAttribute(\"startDate\", startDateParam);\n        model.addAttribute(\"endDate\", endDateParam);\n\n        if (instanceId != null && instanceId > 0) {\n            model.addAttribute(\"instanceId\", instanceId);\n            InstanceInfo instanceInfo = instanceStatsCenter.getInstanceInfo(instanceId);\n\n            if (instanceInfo == null) {\n                model.addAttribute(\"type\", -1);\n            } else {\n                if (appId != null && appId > 0) {\n                    model.addAttribute(\"appId\", appId);\n                } else {\n                    model.addAttribute(\"appId\", instanceInfo.getAppId());\n                }\n                model.addAttribute(\"type\", instanceInfo.getType());\n            }\n        } else {\n\n        }\n        if (tabTag != null) {\n            model.addAttribute(\"tabTag\", tabTag);\n        }\n        return new ModelAndView(\"instance/instanceIndex\");\n    }\n\n    @RequestMapping(\"/stat\")\n    public ModelAndView stat(HttpServletRequest request, HttpServletResponse response, Model model, Integer admin, Long instanceId) {\n\n        String startDateParam = request.getParameter(\"startDate\");\n        String endDateParam = request.getParameter(\"endDate\");\n\n        if (StringUtils.isBlank(startDateParam) || StringUtils.isBlank(endDateParam)) {\n            Date endDate = new Date();\n            Date startDate = DateUtils.addDays(endDate, -1);\n            startDateParam = DateUtil.formatDate(startDate, \"yyyyMMdd\");\n            endDateParam = DateUtil.formatDate(endDate, \"yyyyMMdd\");\n        }\n        model.addAttribute(\"startDate\", startDateParam);\n        model.addAttribute(\"endDate\", endDateParam);\n\n        if (instanceId != null && instanceId > 0) {\n            model.addAttribute(\"instanceId\", instanceId);\n            InstanceInfo instanceInfo = instanceStatsCenter.getInstanceInfo(instanceId);\n            model.addAttribute(\"instanceInfo\", instanceInfo);\n            model.addAttribute(\"appId\", instanceInfo.getAppId());\n            model.addAttribute(\"appDetail\", appStatsCenter.getAppDetail(instanceInfo.getAppId()));\n            InstanceStats instanceStats = instanceStatsCenter.getInstanceStats(instanceId);\n            model.addAttribute(\"instanceStats\", instanceStats);\n            List<AppCommandStats> topLimitAppCommandStatsList = appStatsCenter.getTopLimitAppCommandStatsList(instanceInfo.getAppId(), Long.parseLong(startDateParam) * 10000, Long.parseLong(endDateParam) * 10000, 5);\n            model.addAttribute(\"appCommandStats\", topLimitAppCommandStatsList);\n        }\n        return new ModelAndView(\"instance/instanceStat\");\n    }\n\n    @RequestMapping(\"/advancedAnalysis\")\n    public ModelAndView advancedAnalysis(HttpServletRequest request, HttpServletResponse response, Model model, Integer admin, Long instanceId) {\n\n        String startDateParam = request.getParameter(\"startDate\");\n        String endDateParam = request.getParameter(\"endDate\");\n\n        if (StringUtils.isBlank(startDateParam) || StringUtils.isBlank(endDateParam)) {\n            Date endDate = new Date();\n            Date startDate = DateUtils.addDays(endDate, -1);\n            startDateParam = DateUtil.formatDate(startDate, \"yyyyMMdd\");\n            endDateParam = DateUtil.formatDate(endDate, \"yyyyMMdd\");\n        }\n        model.addAttribute(\"startDate\", startDateParam);\n        model.addAttribute(\"endDate\", endDateParam);\n\n        if (instanceId != null && instanceId > 0) {\n            model.addAttribute(\"instanceId\", instanceId);\n            InstanceInfo instanceInfo = instanceStatsCenter.getInstanceInfo(instanceId);\n            model.addAttribute(\"instanceInfo\", instanceInfo);\n            model.addAttribute(\"appId\", instanceInfo.getAppId());\n            List<AppCommandStats> topLimitAppCommandStatsList = appStatsCenter.getTopLimitAppCommandStatsList(instanceInfo.getAppId(), Long.parseLong(startDateParam) * 10000, Long.parseLong(endDateParam) * 10000, 5);\n            model.addAttribute(\"appCommandStats\", topLimitAppCommandStatsList);\n        } else {\n\n        }\n        return new ModelAndView(\"instance/instanceAdvancedAnalysis\");\n    }\n\n    /**\n     * 获取某个命令时间分布图\n     *\n     * @param instanceId  实例id\n     * @param commandName 命令名称\n     * @throws java.text.ParseException\n     */\n    @RequestMapping(\"/getCommandStats\")\n    public ModelAndView getCommandStats(HttpServletRequest request,\n                                        HttpServletResponse response, Model model, Long instanceId,\n                                        String commandName) throws ParseException {\n        String startDateParam = request.getParameter(\"startDate\");\n        String endDateParam = request.getParameter(\"endDate\");\n\n        if (StringUtils.isBlank(startDateParam) || StringUtils.isBlank(endDateParam)) {\n            Date endDate = new Date();\n            Date startDate = DateUtils.addDays(endDate, -1);\n            startDateParam = DateUtil.formatDate(startDate, \"yyyyMMdd\");\n            endDateParam = DateUtil.formatDate(endDate, \"yyyyMMdd\");\n        }\n        model.addAttribute(\"startDate\", startDateParam);\n        model.addAttribute(\"endDate\", endDateParam);\n\n        Date startDate = DateUtil.parseYYYYMMdd(startDateParam);\n        Date endDate = DateUtil.parseYYYYMMdd(endDateParam);\n        if (instanceId != null) {\n            long firstDayBegin = NumberUtils.toLong(DateUtil.formatYYYYMMdd(startDate) + \"0000\");\n            long firstDayEnd = NumberUtils.toLong(DateUtil.formatYYYYMMdd(startDate) + \"2359\");\n            long secondDayBegin = NumberUtils.toLong(DateUtil.formatYYYYMMdd(endDate) + \"0000\");\n            long secondDayEnd = NumberUtils.toLong(DateUtil.formatYYYYMMdd(endDate) + \"2359\");\n            long bt = System.currentTimeMillis();\n            List<InstanceCommandStats> instanceCommandStatsListFirst = instanceStatsCenter\n                    .getCommandStatsList(instanceId, firstDayBegin, firstDayEnd, commandName);\n            List<InstanceCommandStats> instanceCommandStatsListSecond = instanceStatsCenter\n                    .getCommandStatsList(instanceId, secondDayBegin, secondDayEnd, commandName);\n            long et = System.currentTimeMillis() - bt;\n            Map<String, InstanceCommandStats> cmdStatsFirst = new HashMap<String, InstanceCommandStats>();\n            Map<String, InstanceCommandStats> cmdStatsSecond = new HashMap<String, InstanceCommandStats>();\n\n            for (InstanceCommandStats first : instanceCommandStatsListFirst) {\n                cmdStatsFirst.put(first.getCollectTime() + \"\", first);\n            }\n            for (InstanceCommandStats second : instanceCommandStatsListSecond) {\n                cmdStatsSecond.put(second.getCollectTime() + \"\", second);\n            }\n\n            SplineChartEntity splineChartEntity = new SplineChartEntity();\n            String container = request.getParameter(\"container\");\n            if (container != null) {\n                splineChartEntity.renderTo(container);\n            }\n            model.addAttribute(\"chart\", splineChartEntity);\n            splineChartEntity.putTitle(ChartKeysUtil.TitleKey.TEXT.getKey(), \"命令:\" + commandName + \" 的比较曲线【\" + startDateParam + \"】-【\" + endDateParam + \"】\");\n            splineChartEntity.setYAxisTitle(\"y\");\n            List<Long> data1 = new ArrayList<Long>();\n            List<Long> data2 = new ArrayList<Long>();\n            Map<String, Object> serie1 = new HashMap<String, Object>();\n            serie1.put(\"name\", startDateParam);\n            serie1.put(\"data\", data1);\n//            serie1.put(\"type\", \"area\");\n            Map<String, Object> serie2 = new HashMap<String, Object>();\n            serie2.put(\"name\", endDateParam);\n            serie2.put(\"data\", data2);\n//            serie2.put(\"type\", \"area\");\n            splineChartEntity.putSeries(serie1);\n            splineChartEntity.putSeries(serie2);\n            List<Object> x = new LinkedList<Object>();\n            for (int i = 0; i < 1440; i += 1) {\n                Date date = DateUtils.addMinutes(startDate, i);\n                String s = DateUtil.formatHHMM(date);\n                if (cmdStatsFirst.containsKey(startDateParam + s)) {\n                    data1.add(cmdStatsFirst.get(startDateParam + s).getCommandCount());\n                } else {\n                    data1.add(0l);\n                }\n                if (cmdStatsSecond.containsKey(endDateParam + s)) {\n                    data2.add(cmdStatsSecond.get(endDateParam + s).getCommandCount());\n                } else {\n                    data2.add(0l);\n                }\n\n                x.add(s);\n            }\n            splineChartEntity.setXAxisCategories(x);\n        }\n        return new ModelAndView(\"\");\n    }\n\n    /**\n     * 获取某个命令时间分布图\n     *\n     * @param instanceId  实例id\n     * @param commandName 命令名称\n     * @throws java.text.ParseException\n     */\n    @RequestMapping(\"/getCommandStatsV2\")\n    public ModelAndView getCommandStatsV2(HttpServletRequest request,\n                                          HttpServletResponse response, Model model, Long instanceId,\n                                          String commandName) throws ParseException {\n        String startDateParam = request.getParameter(\"startDate\");\n        String endDateParam = request.getParameter(\"endDate\");\n\n        if (StringUtils.isBlank(startDateParam) || StringUtils.isBlank(endDateParam)) {\n            Date endDate = new Date();\n            Date startDate = DateUtils.addDays(endDate, -1);\n            startDateParam = DateUtil.formatDate(startDate, \"yyyyMMdd\");\n            endDateParam = DateUtil.formatDate(endDate, \"yyyyMMdd\");\n        }\n        model.addAttribute(\"startDate\", startDateParam);\n        model.addAttribute(\"endDate\", endDateParam);\n\n        Date startDate = DateUtil.parseYYYYMMdd(startDateParam);\n        Date endDate = DateUtil.parseYYYYMMdd(endDateParam);\n        if (instanceId != null) {\n            long firstDayBegin = NumberUtils.toLong(DateUtil.formatYYYYMMdd(startDate) + \"0000\");\n            long firstDayEnd = NumberUtils.toLong(DateUtil.formatYYYYMMdd(startDate) + \"2359\");\n            long secondDayBegin = NumberUtils.toLong(DateUtil.formatYYYYMMdd(endDate) + \"0000\");\n            long secondDayEnd = NumberUtils.toLong(DateUtil.formatYYYYMMdd(endDate) + \"2359\");\n            long bt = System.currentTimeMillis();\n            List<InstanceCommandStats> instanceCommandStatsListFirst = instanceStatsCenter\n                    .getCommandStatsList(instanceId, firstDayBegin, firstDayEnd, commandName);\n            List<InstanceCommandStats> instanceCommandStatsListSecond = instanceStatsCenter\n                    .getCommandStatsList(instanceId, secondDayBegin, secondDayEnd, commandName);\n            long et = System.currentTimeMillis() - bt;\n            Map<String, InstanceCommandStats> cmdStatsFirst = new HashMap<String, InstanceCommandStats>();\n            Map<String, InstanceCommandStats> cmdStatsSecond = new HashMap<String, InstanceCommandStats>();\n\n            for (InstanceCommandStats first : instanceCommandStatsListFirst) {\n                cmdStatsFirst.put(first.getCollectTime() + \"\", first);\n            }\n            for (InstanceCommandStats second : instanceCommandStatsListSecond) {\n                cmdStatsSecond.put(second.getCollectTime() + \"\", second);\n            }\n\n            SplineChartEntity splineChartEntity = new SplineChartEntity();\n            String container = request.getParameter(\"container\");\n            if (container != null) {\n                splineChartEntity.renderTo(container);\n            }\n            model.addAttribute(\"chart\", splineChartEntity);\n            splineChartEntity.putTitle(ChartKeysUtil.TitleKey.TEXT.getKey(), \"命令:\" + commandName + \" 的比较曲线【\" + startDateParam + \"】-【\" + endDateParam + \"】\");\n            splineChartEntity.setYAxisTitle(\"y\");\n            List<Long> data1 = new ArrayList<Long>();\n            List<Long> data2 = new ArrayList<Long>();\n            Map<String, Object> marker = new HashMap<String, Object>();\n            marker.put(\"radius\", 1);\n            Map<String, Object> serie1 = new HashMap<String, Object>();\n            serie1.put(\"name\", startDateParam);\n            serie1.put(\"data\", data1);\n            serie1.put(\"marker\", marker);\n            Map<String, Object> serie2 = new HashMap<String, Object>();\n            serie2.put(\"name\", endDateParam);\n            serie2.put(\"data\", data2);\n            serie2.put(\"marker\", marker);\n            splineChartEntity.putSeries(serie1);\n            splineChartEntity.putSeries(serie2);\n            List<Object> x = new LinkedList<Object>();\n            for (int i = 0; i < 1440; i += 1) {\n                Date date = DateUtils.addMinutes(startDate, i);\n                String s = DateUtil.formatHHMM(date);\n                if (cmdStatsFirst.containsKey(startDateParam + s)) {\n                    data1.add(cmdStatsFirst.get(startDateParam + s).getCommandCount());\n                } else {\n                    data1.add(0l);\n                }\n                if (cmdStatsSecond.containsKey(endDateParam + s)) {\n                    data2.add(cmdStatsSecond.get(endDateParam + s).getCommandCount());\n                } else {\n                    data2.add(0l);\n                }\n\n                x.add(s);\n            }\n            splineChartEntity.setXAxisCategories(x);\n        }\n        return new ModelAndView(\"\");\n    }\n\n    @RequestMapping(\"/fault\")\n    public ModelAndView fault(HttpServletRequest request, HttpServletResponse response, Model model, Integer admin, Integer instanceId, Long appId) {\n        //String startDateParam = request.getParameter(\"startDate\");\n        //String endDateParam = request.getParameter(\"endDate\");\n        List<InstanceFault> list = null;\n        try {\n            list = instanceAlertService.getListByInstId(instanceId);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n        if (list == null) {\n            list = new ArrayList<InstanceFault>();\n        }\n        model.addAttribute(\"list\", list);\n        return new ModelAndView(\"instance/instanceFault\");\n    }\n\n    @RequestMapping(\"/configSelect\")\n    public ModelAndView configSelect(HttpServletRequest request, HttpServletResponse response, Model model, Integer admin, Long instanceId, Long appId) {\n        if (instanceId != null && instanceId > 0) {\n            model.addAttribute(\"instanceId\", instanceId);\n            Map<String, String> redisConfigList = redisCenter.getRedisConfigList(instanceId.intValue());\n            model.addAttribute(\"redisConfigList\", redisConfigList);\n        }\n        if (appId != null && appId > 0) {\n            model.addAttribute(\"appId\", appId);\n        }\n        return new ModelAndView(\"instance/instanceConfigSelect\");\n    }\n\n    @RequestMapping(\"/slowSelect\")\n    public ModelAndView slowSelect(HttpServletRequest request, HttpServletResponse response, Model model, Integer admin, Long instanceId) {\n        if (instanceId != null && instanceId > 0) {\n            model.addAttribute(\"instanceId\", instanceId);\n            List<RedisSlowLog> redisSlowLogs = redisCenter.getRedisSlowLogs(instanceId.intValue(), -1);\n            model.addAttribute(\"redisSlowLogs\", redisSlowLogs);\n        }\n        return new ModelAndView(\"instance/instanceSlowSelect\");\n    }\n\n    @RequestMapping(\"/clientList\")\n    public ModelAndView clientList(HttpServletRequest request, HttpServletResponse response, Model model, Integer admin, Long instanceId) {\n        if (instanceId != null && instanceId > 0) {\n            model.addAttribute(\"instanceId\", instanceId);\n            List<String> clientList = redisCenter.getClientList(instanceId.intValue());\n            model.addAttribute(\"clientList\", clientList);\n        }\n        return new ModelAndView(\"instance/instanceClientList\");\n    }\n\n    @RequestMapping(\"/command\")\n    public ModelAndView command(HttpServletRequest request, HttpServletResponse response, Model model, Integer admin, Long instanceId, Long appId) {\n        if (instanceId != null && instanceId > 0) {\n            model.addAttribute(\"instanceId\", instanceId);\n        }\n        return new ModelAndView(\"instance/instanceCommand\");\n    }\n\n    @RequestMapping(\"/commandExecute\")\n    public ModelAndView commandExecute(HttpServletRequest request, HttpServletResponse response, Model model, Integer admin, Long instanceId, Long appId) {\n        if (instanceId != null && instanceId > 0) {\n            model.addAttribute(\"instanceId\", instanceId);\n            String command = request.getParameter(\"command\");\n            String result = instanceStatsCenter.executeCommand(instanceId, command);\n            model.addAttribute(\"result\", result);\n        } else {\n            model.addAttribute(\"result\", \"error\");\n        }\n        return new ModelAndView(\"instance/commandExecute\");\n    }\n\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/controller/InstanceManageController.java",
    "content": "package com.sohu.cache.web.controller;\n\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\n\nimport javax.annotation.Resource;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\nimport org.apache.commons.lang.StringUtils;\nimport org.apache.commons.lang.math.NumberUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.servlet.ModelAndView;\n\nimport com.sohu.cache.entity.AppAudit;\nimport com.sohu.cache.entity.AppUser;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.redis.RedisCenter;\nimport com.sohu.cache.redis.RedisDeployCenter;\nimport com.sohu.cache.stats.instance.InstanceDeployCenter;\nimport com.sohu.cache.stats.instance.InstanceStatsCenter;\nimport com.sohu.cache.web.enums.SuccessEnum;\n\n/**\n * 应用后台管理\n * \n * @author leifu\n * @Time 2014年7月3日\n */\n@Controller\n@RequestMapping(\"manage/instance\")\npublic class InstanceManageController extends BaseController {\n\n    private Logger logger = LoggerFactory.getLogger(InstanceManageController.class);\n\n    @Resource(name = \"instanceDeployCenter\")\n    private InstanceDeployCenter instanceDeployCenter;\n    \n    @Resource(name = \"redisCenter\")\n    private RedisCenter redisCenter;\n    \n    @Resource(name = \"instanceStatsCenter\")\n    private InstanceStatsCenter instanceStatsCenter;\n    \n    /**\n     * 上线(和下线分开)\n     * \n     * @param instanceId\n     */\n    @RequestMapping(value = \"/startInstance\")\n    public ModelAndView doStartInstance(HttpServletRequest request, HttpServletResponse response, Model model, long appId, int instanceId) {\n        AppUser appUser = getUserInfo(request);\n        logger.warn(\"user {} startInstance {} \", appUser.getName(), instanceId);\n        boolean result = false;\n        if (instanceId > 0) {\n            try {\n                result = instanceDeployCenter.startExistInstance(appId, instanceId);\n            } catch (Exception e) {\n                logger.error(e.getMessage(), e);\n                model.addAttribute(\"message\", e.getMessage());\n            }\n        } else {\n            logger.error(\"doStartInstance instanceId:{}\", instanceId);\n            model.addAttribute(\"message\", \"wrong param\");\n        }\n        logger.warn(\"user {} startInstance {} result is {}\", appUser.getName(), instanceId, result);\n        if (result) {\n            model.addAttribute(\"success\", SuccessEnum.SUCCESS.value());\n        } else {\n            model.addAttribute(\"success\", SuccessEnum.FAIL.value());\n        }\n        return new ModelAndView();\n    }\n\n    /**\n     * 下线实例\n     * \n     * @param instanceId\n     * @param ip\n     */\n    @RequestMapping(value = \"/shutdownInstance\")\n    public ModelAndView doShutdownInstance(HttpServletRequest request, HttpServletResponse response, Model model, long appId, int instanceId) {\n        AppUser appUser = getUserInfo(request);\n        logger.warn(\"user {} shutdownInstance {} \", appUser.getName(), instanceId);\n        boolean result = false;\n        if (instanceId > 0) {\n            try {\n                result = instanceDeployCenter.shutdownExistInstance(appId, instanceId);\n            } catch (Exception e) {\n                logger.error(e.getMessage(), e);\n                model.addAttribute(\"message\", e.getMessage());\n            }\n        } else {\n            logger.error(\"doShutdownInstance instanceId:{}\", instanceId);\n            model.addAttribute(\"message\", \"wrong param\");\n        }\n        logger.warn(\"user {} shutdownInstance {}, result is {}\", appUser.getName(), instanceId, result);\n        if (result) {\n            model.addAttribute(\"success\", SuccessEnum.SUCCESS.value());\n        } else {\n            model.addAttribute(\"success\", SuccessEnum.FAIL.value());\n        }\n        return new ModelAndView();\n    }\n    \n    /**\n     * 查看redis节点日志\n     * @param appId\n     * @param slaveInstanceId\n     */\n    @RequestMapping(\"/log\")\n    public ModelAndView doShowLog(HttpServletRequest request, HttpServletResponse response, Model model, int instanceId) {\n        int pageSize = NumberUtils.toInt(request.getParameter(\"pageSize\"), 0);\n        if (pageSize == 0) {\n            pageSize = 100;\n        }\n        String instanceLogStr = instanceDeployCenter.showInstanceRecentLog(instanceId, pageSize);\n        model.addAttribute(\"instanceLogList\", StringUtils.isBlank(instanceLogStr) ? Collections.emptyList() : Arrays.asList(instanceLogStr.split(\"\\n\")));\n        return new ModelAndView(\"manage/instance/log\");\n    }\n    \n    /**\n     * 处理实例配置修改\n     * \n     * @param appAuditId 审批id\n     */\n    @RequestMapping(value = \"/initInstanceConfigChange\")\n    public ModelAndView doInitInstanceConfigChange(HttpServletRequest request,\n            HttpServletResponse response, Model model, Long appAuditId) {\n        // 申请原因\n        AppAudit appAudit = appService.getAppAuditById(appAuditId);\n        model.addAttribute(\"appAudit\", appAudit);\n\n        // 用第一个参数存实例id\n        Long instanceId = NumberUtils.toLong(appAudit.getParam1());\n        Map<String, String> redisConfigList = redisCenter.getRedisConfigList(instanceId.intValue());\n        model.addAttribute(\"redisConfigList\", redisConfigList);\n\n        // 实例\n        InstanceInfo instanceInfo = instanceStatsCenter.getInstanceInfo(instanceId);\n        model.addAttribute(\"instanceInfo\", instanceInfo);\n        model.addAttribute(\"appId\", appAudit.getAppId());\n        model.addAttribute(\"appAuditId\", appAuditId);\n\n        // 修改配置的键值对\n        model.addAttribute(\"instanceConfigKey\", appAudit.getParam2());\n        model.addAttribute(\"instanceConfigValue\", appAudit.getParam3());\n\n        return new ModelAndView(\"manage/appAudit/initInstanceConfigChange\");\n    }\n\n    /**\n     * \n     * @param appId 应用id\n     * @param host 实例ip\n     * @param port 实例端口\n     * @param instanceConfigKey 实例配置key\n     * @param instanceConfigValue 实例配置value\n     * @param appAuditId 审批id\n     * @return\n     */\n    @RequestMapping(value = \"/addInstanceConfigChange\")\n    public ModelAndView doAddAppConfigChange(HttpServletRequest request,\n            HttpServletResponse response, Model model, Long appId, String host, int port,\n            String instanceConfigKey, String instanceConfigValue, Long appAuditId) {\n        AppUser appUser = getUserInfo(request);\n        logger.warn(\"user {} change instanceConfig:appId={},{}:{};key={};value={},appAuditId:{}\", appUser.getName(), appId, host, port, instanceConfigKey, instanceConfigValue, appAuditId);\n        boolean isModify = false;\n        if (StringUtils.isNotBlank(host) && port > 0 && appAuditId != null && StringUtils.isNotBlank(instanceConfigKey) && StringUtils.isNotBlank(instanceConfigValue)) {\n            try {\n                isModify = instanceDeployCenter.modifyInstanceConfig(appId, appAuditId, host, port, instanceConfigKey, instanceConfigValue);\n            } catch (Exception e) {\n                logger.error(e.getMessage(), e);\n            }\n        }\n        logger.warn(\"user {} change instanceConfig:appId={},{}:{};key={};value={},appAuditId:{},result is:{}\", appUser.getName(), appId, host, port, instanceConfigKey, instanceConfigValue, appAuditId, isModify);\n        return new ModelAndView(\"redirect:/manage/app/auditList\");\n    }\n    \n    \n    \n    \n    \n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/controller/JobController.java",
    "content": "package com.sohu.cache.web.controller;\n\nimport com.sohu.cache.machine.MachineCenter;\nimport com.sohu.cache.redis.RedisCenter;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.util.Assert;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestMapping;\n\nimport javax.annotation.Resource;\n\n/**\n * job操作\n * @author leifu\n * @Date 2014年05月19日\n * @Time 下午12:45:36\n */\n@Controller\n@RequestMapping(value = \"/cache/jobs\")\npublic class JobController {\n    private Logger logger = LoggerFactory.getLogger(this.getClass());\n\n    @Resource\n    private RedisCenter redisCenter;\n    \n    @Resource\n    private MachineCenter machineCenter;\n\n    @RequestMapping(value = \"/add/{appId}/{type}/{host}/{port}\")\n    public void addJob(@PathVariable long appId, @PathVariable int type, @PathVariable String host, @PathVariable int port) {\n        Assert.isTrue(appId > 0);\n        Assert.isTrue(type > 0);\n        Assert.hasText(host);\n        Assert.isTrue(port > 0);\n\n        redisCenter.deployRedisCollection(appId, host, port);\n        logger.info(\"deploy instance: {}:{} done.\", host, port);\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/controller/LoginController.java",
    "content": "package com.sohu.cache.web.controller;\n\nimport javax.annotation.Resource;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.servlet.ModelAndView;\n\nimport com.sohu.cache.constant.AppUserTypeEnum;\nimport com.sohu.cache.entity.AppUser;\nimport com.sohu.cache.entity.LoginResult;\nimport com.sohu.cache.util.ConstUtils;\nimport com.sohu.cache.web.enums.AdminEnum;\nimport com.sohu.cache.web.enums.LoginEnum;\nimport com.sohu.cache.web.service.UserLoginStatusService;\nimport com.sohu.cache.web.util.LoginUtil;\n\n/**\n * 登录逻辑\n *\n * @author leifu\n * @Time 2014年6月12日\n */\n@Controller\n@RequestMapping(\"manage\")\npublic class LoginController extends BaseController {\n    \n    @Resource(name = \"userLoginStatusService\")\n    private UserLoginStatusService userLoginStatusService;\n\n    /**\n     * 用户登录界面\n     *\n     * @param request\n     * @return\n     */\n    @RequestMapping(value = \"/login\", method = RequestMethod.GET)\n    public ModelAndView init(HttpServletRequest request, HttpServletResponse response, Model model) {\n        model.addAttribute(ConstUtils.RREDIRECT_URL_PARAM, request.getParameter(ConstUtils.RREDIRECT_URL_PARAM));\n        return new ModelAndView(\"manage/login\");\n    }\n\n    /**\n     * 用户登录\n     *\n     * @param userName 用户名\n     * @param password 密码\n     * @param isAdmin  是否勾选超级管理员选项,1是0否\n     * @return\n     */\n    @RequestMapping(value = \"/loginIn\", method = RequestMethod.POST)\n    public ModelAndView loginIn(HttpServletRequest request,\n                                HttpServletResponse response, Model model, String userName, String password, boolean isAdmin) {\n        // 登录结果\n        LoginResult loginResult = new LoginResult();\n        loginResult.setAdminEnum((isAdmin == true ? AdminEnum.IS_ADMIN : AdminEnum.NOT_ADMIN));\n        loginResult.setLoginEnum(LoginEnum.LOGIN_WRONG_USER_OR_PASSWORD);\n\n        AppUser userModel = null;\n        if (ConstUtils.SUPER_ADMIN_NAME.equals(userName)) {\n            userModel = userService.getByName(userName);\n            if (userModel != null && ConstUtils.SUPER_ADMIN_PASS.equals(password)) {\n                loginResult.setLoginEnum(LoginEnum.LOGIN_SUCCESS);\n            } else {\n                loginResult.setLoginEnum(LoginEnum.LOGIN_WRONG_USER_OR_PASSWORD);\n            }\n        } else {\n            if (LoginUtil.passportCheck(userName, password)) {\n                // 同时要验证是否有cachecloud权限\n                userModel = userService.getByName(userName);\n                if (userModel != null && userModel.getType() != AppUserTypeEnum.NO_USER.value()) {\n                    if (isAdmin) {\n                        if (AppUserTypeEnum.ADMIN_USER.value().equals(userModel.getType())) {\n                            loginResult.setLoginEnum(LoginEnum.LOGIN_SUCCESS);\n                        } else {\n                            loginResult.setLoginEnum(LoginEnum.LOGIN_NOT_ADMIN);\n                        }\n                    } else {\n                        loginResult.setLoginEnum(LoginEnum.LOGIN_SUCCESS);\n                    }\n                } else {\n                    // 用户不存在\n                    loginResult.setLoginEnum(LoginEnum.LOGIN_USER_NOT_EXIST);\n                }\n            }\n        }\n        // 登录成功写入登录状态\n        if (loginResult.getLoginEnum().equals(LoginEnum.LOGIN_SUCCESS)) {\n            userLoginStatusService.addLoginStatus(request, response, userModel.getId().toString());\n        }\n        model.addAttribute(\"success\", loginResult.getLoginEnum().value());\n        model.addAttribute(\"admin\", loginResult.getAdminEnum().value());\n        return new ModelAndView();\n    }\n\n    /**\n     * 用户注销\n     *\n     * @param reqeust\n     * @return\n     */\n    @RequestMapping(value = \"/logout\", method = RequestMethod.GET)\n    public ModelAndView logout(HttpServletRequest request, HttpServletResponse response) {\n        userLoginStatusService.removeLoginStatus(request, response);\n        return new ModelAndView(\"redirect:/manage/login\");\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/controller/MachineManageController.java",
    "content": "package com.sohu.cache.web.controller;\n\nimport com.sohu.cache.constant.MachineInfoEnum;\nimport com.sohu.cache.entity.AppDesc;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.entity.InstanceStats;\nimport com.sohu.cache.entity.MachineInfo;\nimport com.sohu.cache.entity.MachineStats;\nimport com.sohu.cache.machine.MachineDeployCenter;\nimport com.sohu.cache.util.ConstUtils;\nimport com.sohu.cache.util.TypeUtil;\nimport com.sohu.cache.web.enums.SuccessEnum;\n\nimport org.apache.commons.collections.CollectionUtils;\nimport org.apache.commons.lang.StringUtils;\nimport org.apache.commons.lang.math.NumberUtils;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.servlet.ModelAndView;\n\nimport javax.annotation.Resource;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 机器管理\n *\n * @author leifu\n * @Time 2014年10月14日\n */\n@Controller\n@RequestMapping(\"manage/machine\")\npublic class MachineManageController extends BaseController{\n\n    @Resource\n    private MachineDeployCenter machineDeployCenter;\n\n    @RequestMapping(value = \"/list\")\n    public ModelAndView doMachineList(HttpServletRequest request,\n                                HttpServletResponse response, Model model, String ipLike) {\n        List<MachineStats> machineList = machineCenter.getMachineStats(ipLike);\n        Map<String, Integer> machineInstanceCountMap = machineCenter.getMachineInstanceCountMap();\n        model.addAttribute(\"list\", machineList);\n        model.addAttribute(\"ipLike\", ipLike);\n        model.addAttribute(\"machineActive\", SuccessEnum.SUCCESS.value());\n        model.addAttribute(\"collectAlert\", \"(请等待\" + ConstUtils.MACHINE_STATS_CRON_MINUTE + \"分钟)\");\n        model.addAttribute(\"machineInstanceCountMap\", machineInstanceCountMap);\n        return new ModelAndView(\"manage/machine/list\");\n    }\n    \n    /**\n     * 机器实例展示\n     * @param ip\n     * @return\n     */\n    @RequestMapping(value = \"/machineInstances\")\n    public ModelAndView doMachineInstances(HttpServletRequest request,\n                                HttpServletResponse response, Model model, String ip) {\n        //机器以及机器下面的实例信息\n        MachineInfo machineInfo = machineCenter.getMachineInfoByIp(ip);\n        List<InstanceInfo> instanceList = machineCenter.getMachineInstanceInfo(ip);\n        List<InstanceStats> instanceStatList = machineCenter.getMachineInstanceStatsByIp(ip);       \n        //统计信息\n        fillInstanceModel(instanceList, instanceStatList, model);\n        \n        model.addAttribute(\"machineInfo\", machineInfo);\n        model.addAttribute(\"machineActive\", SuccessEnum.SUCCESS.value());\n        return new ModelAndView(\"manage/machine/machineInstances\");\n    }\n    \n    /**\n     * 检查机器下是否有存活的实例\n     * @param ip\n     * @return\n     */\n    @RequestMapping(value = \"/checkMachineInstances\")\n    public ModelAndView doCheckMachineInstances(HttpServletRequest request,\n                                HttpServletResponse response, Model model, String ip) {\n        List<InstanceInfo> instanceList = machineCenter.getMachineInstanceInfo(ip);\n        model.addAttribute(\"machineHasInstance\", CollectionUtils.isNotEmpty(instanceList));\n        return new ModelAndView(\"\");\n    }\n    \n\n    @RequestMapping(value = \"/add\", method = {RequestMethod.POST})\n    public ModelAndView doAdd(HttpServletRequest request,\n                              HttpServletResponse response, Model model) {\n        MachineInfo machineInfo = new MachineInfo();\n        machineInfo.setIp(request.getParameter(\"ip\"));\n        machineInfo.setRoom(request.getParameter(\"room\"));\n        machineInfo.setMem(NumberUtils.toInt(request.getParameter(\"mem\"), 0));\n        machineInfo.setCpu(NumberUtils.toInt(request.getParameter(\"cpu\"), 0));\n        machineInfo.setVirtual(NumberUtils.toInt(request.getParameter(\"virtual\"), 0));\n        machineInfo.setRealIp(request.getParameter(\"realIp\"));\n        machineInfo.setType(NumberUtils.toInt(request.getParameter(\"machineType\"), 0));\n        machineInfo.setExtraDesc(request.getParameter(\"extraDesc\"));\n        machineInfo.setCollect(NumberUtils.toInt(request.getParameter(\"collect\"), 1));\n        \n        Date date = new Date();\n        machineInfo.setSshUser(ConstUtils.USERNAME);\n        machineInfo.setSshPasswd(ConstUtils.PASSWORD);\n        machineInfo.setServiceTime(date);\n        machineInfo.setModifyTime(date);\n        machineInfo.setAvailable(MachineInfoEnum.AvailableEnum.YES.getValue());\n        boolean isSuccess = machineDeployCenter.addMachine(machineInfo);\n        model.addAttribute(\"result\", isSuccess);\n        return new ModelAndView(\"\");\n    }\n    \n    @RequestMapping(value = \"/delete\")\n    public ModelAndView doDelete(HttpServletRequest request, HttpServletResponse response, Model model) {\n        String machineIp = request.getParameter(\"machineIp\");\n        if (StringUtils.isNotBlank(machineIp)) {\n            MachineInfo machineInfo = machineCenter.getMachineInfoByIp(machineIp);\n            boolean success = machineDeployCenter.removeMachine(machineInfo);\n            logger.warn(\"delete machine {}, result is {}\", machineIp, success);\n        } else {\n            logger.warn(\"machineIp is empty!\");\n        }\n        return new ModelAndView(\"redirect:/manage/machine/list\");\n    }\n    \n    \n    /**\n     * 实例统计信息\n     * @param appAudit\n     * @param model\n     */\n    protected void fillInstanceModel(List<InstanceInfo> instanceList, List<InstanceStats> appInstanceStats, Model model) {\n        Map<String, MachineStats> machineStatsMap = new HashMap<String, MachineStats>();\n        Map<String, Long> machineCanUseMem = new HashMap<String, Long>();\n        Map<String, InstanceStats> instanceStatsMap = new HashMap<String, InstanceStats>();\n        Map<Long, AppDesc> appInfoMap = new HashMap<Long, AppDesc>();\n\n        for (InstanceStats instanceStats : appInstanceStats) {\n            instanceStatsMap.put(instanceStats.getIp() + \":\" + instanceStats.getPort(), instanceStats);\n            appInfoMap.put(instanceStats.getAppId(), appService.getByAppId(instanceStats.getAppId()));\n        }\n\n        for (InstanceInfo instanceInfo : instanceList) {\n            if (TypeUtil.isRedisSentinel(instanceInfo.getType())) {\n                continue;\n            }\n            String ip = instanceInfo.getIp();\n            if (machineStatsMap.containsKey(ip)) {\n                continue;\n            }\n            List<MachineStats> machineStatsList = machineCenter.getMachineStats(ip);\n            MachineStats machineStats = null;\n            for (MachineStats stats : machineStatsList) {\n                if (stats.getIp().equals(ip)) {\n                    machineStats = stats;\n                    machineStatsMap.put(ip, machineStats);\n                    break;\n                }\n            }\n            MachineStats ms = machineCenter.getMachineMemoryDetail(ip);\n            machineCanUseMem.put(ip, ms.getMachineMemInfo().getLockedMem());\n        }\n        model.addAttribute(\"appInfoMap\", appInfoMap);\n        \n        model.addAttribute(\"machineCanUseMem\", machineCanUseMem);\n        model.addAttribute(\"machineStatsMap\", machineStatsMap);\n\n        model.addAttribute(\"instanceList\", instanceList);\n        model.addAttribute(\"instanceStatsMap\", instanceStatsMap);\n    }\n    \n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/controller/NoticeManageController.java",
    "content": "package com.sohu.cache.web.controller;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\n\nimport javax.annotation.Resource;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\nimport org.apache.commons.lang.StringUtils;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.servlet.ModelAndView;\n\nimport com.sohu.cache.util.ConstUtils;\nimport com.sohu.cache.web.enums.SuccessEnum;\nimport com.sohu.cache.web.util.AppEmailUtil;\n\n@Controller\n@RequestMapping(\"manage/notice\")\npublic class NoticeManageController extends BaseController {\n    \n    @Resource(name = \"appEmailUtil\")\n    private AppEmailUtil appEmailUtil;\n\n    /**\n     * 初始化系统通知\n     * \n     * @return\n     */\n    @RequestMapping(value = \"/initNotice\")\n    public ModelAndView init(HttpServletRequest request,\n            HttpServletResponse response, Model model) {\n\n        String notice = \"\";\n        model.addAttribute(\"notice\", notice);\n        model.addAttribute(\"success\", request.getParameter(\"success\"));\n        model.addAttribute(\"noticeActive\", SuccessEnum.SUCCESS.value());\n        return new ModelAndView(\"manage/notice/initNotice\");\n    }\n\n    /**\n     * 发送邮件通知\n     */\n    @RequestMapping(value = \"/add\")\n    public ModelAndView addNotice(HttpServletRequest request,\n            HttpServletResponse response, Model model) {\n        String notice = request.getParameter(\"notice\");\n        boolean result = appEmailUtil.noticeAllUser(notice);\n        model.addAttribute(\"success\", result ? SuccessEnum.SUCCESS.value() : SuccessEnum.FAIL.value());\n        return new ModelAndView(\"\");\n    }\n\n    /**\n     * 获取系统通知\n     * \n     * @return\n     */\n    @RequestMapping(value = \"/get\")\n    public ModelAndView getNotice(HttpServletRequest request,\n            HttpServletResponse response, Model model) {\n        String notice = \"\";\n        List<String> list = null;\n        if (StringUtils.isNotBlank(notice)) {\n            list = Arrays.asList(notice.split(ConstUtils.NEXT_LINE));\n            model.addAttribute(\"status\", SuccessEnum.SUCCESS.value());\n        } else {\n            list = new ArrayList<String>();\n            model.addAttribute(\"status\", SuccessEnum.FAIL.value());\n        }\n        model.addAttribute(\"data\", list);\n        return new ModelAndView(\"\");\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/controller/QuartzManageController.java",
    "content": "package com.sohu.cache.web.controller;\n\nimport java.util.List;\n\nimport javax.annotation.Resource;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\nimport com.sohu.cache.entity.TriggerInfo;\nimport com.sohu.cache.schedule.SchedulerCenter;\nimport org.apache.commons.lang.StringUtils;\nimport org.quartz.TriggerKey;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.servlet.ModelAndView;\n\nimport com.sohu.cache.web.enums.SuccessEnum;\n\n/**\n * quartz管理test\n * \n * @author leifu\n * @Time 2014年7月4日\n */\n@Controller\n@RequestMapping(\"manage/quartz\")\npublic class QuartzManageController extends BaseController {\n\n    @Resource\n    private SchedulerCenter schedulerCenter;\n\n    @RequestMapping(value = \"/list\")\n    public ModelAndView doQuartzList(HttpServletRequest request,\n                                     HttpServletResponse response, Model model) {\n        String query = request.getParameter(\"query\");\n        List<TriggerInfo> triggerList;\n        if (StringUtils.isBlank(query)) {\n            triggerList = schedulerCenter.getAllTriggers();\n            query = \"\";\n        } else {\n            triggerList = schedulerCenter.getTriggersByNameOrGroup(query);\n        }\n        model.addAttribute(\"triggerList\", triggerList);\n        model.addAttribute(\"quartzActive\", SuccessEnum.SUCCESS.value());\n        model.addAttribute(\"query\", query);\n        return new ModelAndView(\"manage/quartz/list\");\n    }\n\n    @RequestMapping(value = \"/pause\")\n    public String pause(HttpServletRequest request,\n                                     HttpServletResponse response, Model model) {\n        String name = request.getParameter(\"name\");\n        String group = request.getParameter(\"group\");\n        if (StringUtils.isNotBlank(name) || StringUtils.isNotBlank(group)) {\n            schedulerCenter.pauseTrigger(new TriggerKey(name, group));\n        }\n        return \"redirect:/manage/quartz/list\";\n    }\n\n    @RequestMapping(value = \"/resume\")\n    public String resume(HttpServletRequest request,\n                        HttpServletResponse response, Model model) {\n        String name = request.getParameter(\"name\");\n        String group = request.getParameter(\"group\");\n        if (StringUtils.isNotBlank(name) || StringUtils.isNotBlank(group)) {\n            schedulerCenter.resumeTrigger(new TriggerKey(name, group));\n        }\n        return \"redirect:/manage/quartz/list\";\n    }\n\n    @RequestMapping(value = \"/remove\")\n    public String remove(HttpServletRequest request,\n                         HttpServletResponse response, Model model) {\n        String name = request.getParameter(\"name\");\n        String group = request.getParameter(\"group\");\n        if (StringUtils.isNotBlank(name) || StringUtils.isNotBlank(group)) {\n            schedulerCenter.unscheduleJob(new TriggerKey(name, group));\n        }\n        return \"redirect:/manage/quartz/list\";\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/controller/RedisConfigTemplateController.java",
    "content": "package com.sohu.cache.web.controller;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport javax.annotation.Resource;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\nimport org.apache.commons.lang.StringUtils;\nimport org.apache.commons.lang.math.NumberUtils;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.servlet.ModelAndView;\n\nimport com.sohu.cache.constant.ErrorMessageEnum;\nimport com.sohu.cache.constant.RedisConfigTemplateChangeEnum;\nimport com.sohu.cache.entity.AppUser;\nimport com.sohu.cache.entity.InstanceConfig;\nimport com.sohu.cache.redis.RedisConfigTemplateService;\nimport com.sohu.cache.util.ConstUtils;\nimport com.sohu.cache.web.enums.SuccessEnum;\nimport com.sohu.cache.web.util.AppEmailUtil;\n\n/**\n * Redis配置模板管理\n * \n * @author leifu\n * @Date 2016-6-25\n * @Time 下午2:48:25\n */\n@Controller\n@RequestMapping(\"manage/redisConfig\")\npublic class RedisConfigTemplateController extends BaseController {\n\n    @Resource(name = \"redisConfigTemplateService\")\n    private RedisConfigTemplateService redisConfigTemplateService;\n\n    @Resource(name = \"appEmailUtil\")\n    private AppEmailUtil appEmailUtil;\n\n    /**\n     * 初始化配置\n     */\n    @RequestMapping(value = \"/init\")\n    public ModelAndView init(HttpServletRequest request, HttpServletResponse response, Model model) {\n        // 默认是Redis普通节点配置\n        int type = NumberUtils.toInt(request.getParameter(\"type\"), ConstUtils.CACHE_REDIS_STANDALONE);\n        model.addAttribute(\"redisConfigList\", redisConfigTemplateService.getByType(type));\n        model.addAttribute(\"success\", request.getParameter(\"success\"));\n        model.addAttribute(\"redisConfigActive\", SuccessEnum.SUCCESS.value());\n        model.addAttribute(\"type\", type);\n        return new ModelAndView(\"manage/redisConfig/init\");\n    }\n\n    /**\n     * 修改配置\n     */\n    @RequestMapping(value = \"/update\")\n    public ModelAndView update(HttpServletRequest request, HttpServletResponse response, Model model) {\n        AppUser appUser = getUserInfo(request);\n        String id = request.getParameter(\"id\");\n        String configKey = request.getParameter(\"configKey\");\n        String configValue = request.getParameter(\"configValue\");\n        String info = request.getParameter(\"info\");\n        int status = NumberUtils.toInt(request.getParameter(\"status\"), -1);\n        if (StringUtils.isBlank(id) || !NumberUtils.isDigits(id) || StringUtils.isBlank(configKey) || status > 1\n                || status < 0) {\n            model.addAttribute(\"status\", SuccessEnum.FAIL.value());\n            model.addAttribute(\"message\", ErrorMessageEnum.PARAM_ERROR_MSG.getMessage() + \"id=\" + id + \",configKey=\"\n                    + configKey + \",configValue=\" + configValue + \",status=\" + status);\n            return new ModelAndView(\"\");\n        }\n        //开始修改\n        logger.warn(\"user {} want to change id={}'s configKey={}, configValue={}, info={}, status={}\", appUser.getName(),\n                id, configKey, configValue, info, status);\n        SuccessEnum successEnum;\n        InstanceConfig instanceConfig = redisConfigTemplateService.getById(NumberUtils.toLong(id));\n        try {\n            instanceConfig.setConfigValue(configValue);\n            instanceConfig.setInfo(info);\n            instanceConfig.setStatus(status);\n            redisConfigTemplateService.saveOrUpdate(instanceConfig);\n            successEnum = SuccessEnum.SUCCESS;\n        } catch (Exception e) {\n            successEnum = SuccessEnum.FAIL;\n            model.addAttribute(\"message\", ErrorMessageEnum.INNER_ERROR_MSG.getMessage());\n            logger.error(e.getMessage(), e);\n        }\n        logger.warn(\"user {} want to change id={}'s configKey={}, configValue={}, info={}, status={}, result is {}\", appUser.getName(),\n                id, configKey, configValue, info, status, successEnum.value());\n        //发送邮件通知\n        appEmailUtil.sendRedisConfigTemplateChangeEmail(appUser, instanceConfig, successEnum, RedisConfigTemplateChangeEnum.UPDATE);\n        model.addAttribute(\"status\", successEnum.value());\n        return new ModelAndView(\"\");\n    }\n\n    /**\n     * 删除配置\n     */\n    @RequestMapping(value = \"/remove\")\n    public ModelAndView remove(HttpServletRequest request, HttpServletResponse response, Model model) {\n        AppUser appUser = getUserInfo(request);\n        String idParam = request.getParameter(\"id\");\n        long id = NumberUtils.toLong(idParam);\n        if (id <= 0) {\n            model.addAttribute(\"status\", SuccessEnum.FAIL.value());\n            model.addAttribute(\"message\", ErrorMessageEnum.PARAM_ERROR_MSG.getMessage() + \"id=\" + idParam);\n            return new ModelAndView(\"\");\n        }\n        logger.warn(\"user {} want to delete id={}'s config\", appUser.getName(), id);\n        SuccessEnum successEnum;\n        InstanceConfig instanceConfig = redisConfigTemplateService.getById(id);\n        try {\n            redisConfigTemplateService.remove(id);\n            successEnum = SuccessEnum.SUCCESS;\n        } catch (Exception e) {\n            successEnum = SuccessEnum.FAIL;\n            model.addAttribute(\"message\", ErrorMessageEnum.INNER_ERROR_MSG.getMessage());\n            logger.error(e.getMessage(), e);\n        }\n        logger.warn(\"user {} want to delete id={}'s config, result is {}\", appUser.getName(), id, successEnum.value());\n        //发送邮件通知\n        appEmailUtil.sendRedisConfigTemplateChangeEmail(appUser, instanceConfig, successEnum, RedisConfigTemplateChangeEnum.DELETE);\n        model.addAttribute(\"status\", successEnum.value());\n        return new ModelAndView(\"\");\n\n    }\n\n    /**\n     * 添加配置\n     */\n    @RequestMapping(value = \"/add\")\n    public ModelAndView add(HttpServletRequest request, HttpServletResponse response, Model model) {\n        AppUser appUser = getUserInfo(request);\n        InstanceConfig instanceConfig = getInstanceConfig(request);\n        if (StringUtils.isBlank(instanceConfig.getConfigKey())) {\n            model.addAttribute(\"status\", SuccessEnum.FAIL.value());\n            model.addAttribute(\"message\", ErrorMessageEnum.PARAM_ERROR_MSG.getMessage() + \"configKey=\" + instanceConfig.getConfigKey());\n            return new ModelAndView(\"\");\n        }\n        logger.warn(\"user {} want to add config, configKey is {}, configValue is {}, type is {}\", appUser.getName(),\n                instanceConfig.getConfigKey(), instanceConfig.getType());\n        SuccessEnum successEnum;\n        try {\n            redisConfigTemplateService.saveOrUpdate(instanceConfig);\n            successEnum = SuccessEnum.SUCCESS;\n        } catch (Exception e) {\n            successEnum = SuccessEnum.FAIL;\n            model.addAttribute(\"message\", ErrorMessageEnum.INNER_ERROR_MSG.getMessage());\n            logger.error(e.getMessage(), e);\n        }\n        logger.warn(\"user {} want to add config, configKey is {}, configValue is {}, type is {}, result is {}\",\n                appUser.getName(),\n                instanceConfig.getConfigKey(), instanceConfig.getConfigValue(), instanceConfig.getType(), successEnum.value());\n        model.addAttribute(\"status\", successEnum.value());\n        //发送邮件通知\n        appEmailUtil.sendRedisConfigTemplateChangeEmail(appUser, instanceConfig, successEnum, RedisConfigTemplateChangeEnum.ADD);\n        return new ModelAndView(\"\");\n\n    }\n\n    /**\n     * 预览配置\n     */\n    @RequestMapping(value = \"/preview\")\n    public ModelAndView preview(HttpServletRequest request, HttpServletResponse response, Model model) {\n        //默认配置\n        int type = NumberUtils.toInt(request.getParameter(\"type\"), -1);\n        String host = StringUtils.isBlank(request.getParameter(\"host\")) ? \"127.0.0.1\" : request.getParameter(\"host\");\n        int port = NumberUtils.toInt(request.getParameter(\"port\"), 6379);\n        int maxMemory = NumberUtils.toInt(request.getParameter(\"maxMemory\"), 2048);\n        int sentinelPort = NumberUtils.toInt(request.getParameter(\"sentinelPort\"), 26379);\n        String masterName = StringUtils.isBlank(request.getParameter(\"masterName\")) ? \"myMaster\" : request\n                .getParameter(\"masterName\");\n        int quorum = NumberUtils.toInt(request.getParameter(\"quorum\"), 2);\n\n        // 根据类型生成配置模板\n        List<String> configList = new ArrayList<String>();\n        if (ConstUtils.CACHE_REDIS_STANDALONE == type) {\n            configList = redisConfigTemplateService.handleCommonConfig(port, maxMemory);\n        } else if (ConstUtils.CACHE_REDIS_SENTINEL == type) {\n            configList = redisConfigTemplateService.handleSentinelConfig(masterName, host, port, sentinelPort);\n        } else if (ConstUtils.CACHE_TYPE_REDIS_CLUSTER == type) {\n            configList = redisConfigTemplateService.handleClusterConfig(port);\n        }\n        model.addAttribute(\"type\", type);\n        model.addAttribute(\"host\", host);\n        model.addAttribute(\"port\", port);\n        model.addAttribute(\"maxMemory\", maxMemory);\n        model.addAttribute(\"sentinelPort\", sentinelPort);\n        model.addAttribute(\"masterName\", masterName);\n        model.addAttribute(\"configList\", configList);\n        return new ModelAndView(\"manage/redisConfig/preview\");\n    }\n\n    /**\n     * 使用最简单的request生成InstanceConfig对象\n     * \n     * @return\n     */\n    private InstanceConfig getInstanceConfig(HttpServletRequest request) {\n        String configKey = request.getParameter(\"configKey\");\n        String configValue = request.getParameter(\"configValue\");\n        String info = request.getParameter(\"info\");\n        String type = request.getParameter(\"type\");\n        InstanceConfig instanceConfig = new InstanceConfig();\n        instanceConfig.setConfigKey(configKey);\n        instanceConfig.setConfigValue(configValue);\n        instanceConfig.setInfo(info);\n        instanceConfig.setType(NumberUtils.toInt(type));\n        instanceConfig.setStatus(1);\n        return instanceConfig;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/controller/ServerController.java",
    "content": "package com.sohu.cache.web.controller;\n\nimport java.math.BigDecimal;\nimport java.text.DecimalFormat;\nimport java.text.SimpleDateFormat;\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.TreeMap;\n\nimport javax.annotation.Resource;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\nimport org.apache.commons.lang.StringUtils;\nimport org.apache.commons.lang.math.NumberUtils;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.servlet.ModelAndView;\n\nimport com.alibaba.fastjson.JSON;\nimport com.sohu.cache.entity.ServerInfo;\nimport com.sohu.cache.entity.ServerStatus;\nimport com.sohu.cache.web.service.ServerDataService;\n\n/**\n * 获取服务器状态\n */\n@Controller\n@RequestMapping(\"/server\")\npublic class ServerController extends BaseController{\n\n\t@Resource\n\tprivate ServerDataService serverDataService;\n\t\n\tprivate DecimalFormat df = new DecimalFormat(\"0.0\");\n\t/**\n\t * 跳转到主页\n\t * @param request\n\t * @param response\n\t * @param model\n\t * @return\n\t */\n\t@RequestMapping(\"/index\")\n\tpublic ModelAndView index(HttpServletRequest request, HttpServletResponse response, Model model) {\n\t\tString ip = request.getParameter(\"ip\");\n\t\tmodel.addAttribute(\"ip\", ip);\n\t\tString date = request.getParameter(\"date\");\n\t\tif(date == null) {\n\t\t\tSimpleDateFormat sdf = new SimpleDateFormat(\"yyyy-MM-dd\");\n\t\t\tdate = sdf.format(new Date());\n\t\t}\n\t\tmodel.addAttribute(\"date\", date);\n        return new ModelAndView(\"server/index\");\n\t}\n\t/**\n\t * 服务器信息概览\n\t * @param request\n\t * @param response\n\t * @param model\n\t * @return\n\t */\n\t@RequestMapping(\"/overview\")\n\tpublic ModelAndView overview(HttpServletRequest request, HttpServletResponse response, Model model) {\n        String ip = request.getParameter(\"ip\");\n        String date = request.getParameter(\"date\");\n        //获取服务器静态信息\n        ServerInfo info = serverDataService.queryServerInfo(ip);\n        if(info != null) {\n\t        model.addAttribute(\"info\", info);\n\t        //解析ulimit\n\t        String ulimit = info.getUlimit();\n\t\t\tif(!StringUtils.isEmpty(ulimit)) {\n\t\t\t\tString[] tmp = ulimit.split(\";\");\n\t\t\t\tif(tmp.length ==2) {\n\t\t\t\t\tString[] a = tmp[0].split(\",\");\n\t\t\t\t\tif(a != null && a.length == 2) {\n\t\t\t\t\t\tif(\"f\".equals(a[0])) {\n\t\t\t\t\t\t\tmodel.addAttribute(\"file\", a[1]);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\ta = tmp[1].split(\",\");\n\t\t\t\t\tif(a != null && a.length == 2) {\n\t\t\t\t\t\tif(\"p\".equals(a[0])) {\n\t\t\t\t\t\t\tmodel.addAttribute(\"process\", a[1]);\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        List<ServerStatus> list = serverDataService.queryServerOverview(ip, date);\n    \t//x轴坐标\n\t\tList<String> xAxis = new ArrayList<String>();\n\t\t\n\t\t//1分钟最大load\n\t\tfloat maxLoad1 = 0;\n\t\t//load1总量\n\t\tdouble totalLoad1 = 0;\n\t\t\n\t\t//最大user\n\t\tfloat maxUser = 0;\n\t\t//最大sys\n\t\tfloat maxSys = 0;\n\t\t//最大wio\n\t\tfloat maxWa = 0;\n\t\t\n\t\t//当前可用内存\n\t\tfloat curFree = 0;\n\t\t//最大内存使用量\n\t\tfloat maxUse = 0;\n\t\t//最大内存cache量\n\t\tfloat maxCache = 0;\n\t\t//最大内存buffer量\n\t\tfloat maxBuffer = 0;\n\t\t//最大swap使用量\n\t\tfloat maxSwapUse = 0;\n\t\t\n\t\t//最大网络流入速度\n\t\tfloat maxNetIn = 0;\n\t\t//最大网络流出速度\n\t\tfloat maxNetOut = 0;\n\t\t//最大连接ESTABLISHED数\n\t\tint maxConn = 0;\n\t\t//最大连接TIME_WAIT数\n\t\tint maxWait = 0;\n\t\t//最大连接ORPHAN数\n\t\tint maxOrphan = 0;\n\t\t\n\t\t//最大读取速率\n\t\tfloat maxRead = 0;\n\t\t//最大写入速率\n\t\tfloat maxWrite = 0;\n\t\t//最繁忙程度\n\t\tfloat maxBusy = 0;\n\t\t//最大iops量\n\t\tfloat maxIops = 0;\n\t\t\n\t\t//load serie\n\t\tSeries<Float> load1Serie = new Series<Float>(\"1-min\");\n\t\tSeries<Float> load5Serie = new Series<Float>(\"5-min\");\n\t\tSeries<Float> load15Serie = new Series<Float>(\"15-min\");\n\t\t\n\t\t//cpu serie\n\t\tSeries<Float> userSerie = new Series<Float>(\"user\");\n\t\tSeries<Float> sysSerie = new Series<Float>(\"sys\");\n\t\tSeries<Float> waSerie = new Series<Float>(\"wa\");\n\t\t\n\t\t//memory serie\n\t\tSeries<Float> totalSerie = new Series<Float>(\"total\");\n\t\tSeries<Float> useSerie = new Series<Float>(\"use\");\n\t\tuseSerie.setType(\"area\");\n\t\tSeries<Float> cacheSerie = new Series<Float>(\"cache\");\n\t\tcacheSerie.setType(\"area\");\n\t\tSeries<Float> bufferSerie = new Series<Float>(\"buffer\");\n\t\tbufferSerie.setType(\"area\");\n\t\tSeries<Float> swapSerie = new Series<Float>(\"total\");\n\t\tSeries<Float> swapUseSerie = new Series<Float>(\"use\");\n\t\t\n\t\t//net serie\n\t\tSeries<Float> netInSerie = new Series<Float>(\"in\");\n\t\tSeries<Float> netOutSerie = new Series<Float>(\"out\");\n\t\t\n\t\t//tcp serie\n\t\tSeries<Integer> establishedSerie = new Series<Integer>(\"established\");\n\t\tSeries<Integer> twSerie = new Series<Integer>(\"time wait\");\n\t\tSeries<Integer> orphanSerie = new Series<Integer>(\"orphan\");\n\t\t\n\t\t//disk serie\n\t\tSeries<Float> readSerie = new Series<Float>(\"read\");\n\t\treadSerie.setType(\"column\");\n\t\tSeries<Float> writeSerie = new Series<Float>(\"write\");\n\t\twriteSerie.setType(\"column\");\n\t\tSeries<Float> busySerie = new Series<Float>(\"busy\");\n\t\tbusySerie.setYAxis(1);\n\t\tSeries<Float> iopsSerie = new Series<Float>(\"iops\");\n\t\tiopsSerie.setYAxis(2);\n\t\t\n\t\tfor(int i = 0; i < list.size(); ++i) {\n\t\t\tServerStatus ss = list.get(i);\n\t\t\t//x axis\n\t\t\txAxis.add(ss.getCtime().substring(0, 2) + \":\" + ss.getCtime().substring(2));\n\t\t\t//load相关\n\t\t\tload1Serie.addData(ss.getCload1());\n\t\t\tload5Serie.addData(ss.getCload5());\n\t\t\tload15Serie.addData(ss.getCload15());\n\t\t\tmaxLoad1 = getBigger(maxLoad1, ss.getCload1());\n\t\t\ttotalLoad1 += ss.getCload1();\n\t\t\t//cpu相关\n\t\t\tuserSerie.addData(ss.getCuser());\n\t\t\tsysSerie.addData(ss.getCsys());\n\t\t\twaSerie.addData(ss.getCwio());\n\t\t\tmaxUser = getBigger(maxUser, ss.getCuser());\n\t\t\tmaxSys = getBigger(maxSys, ss.getCsys());\n\t\t\tmaxWa = getBigger(maxWa, ss.getCwio());\n\t\t\t//memory相关\n\t\t\ttotalSerie.addData(ss.getMtotal());\n\t\t\tfloat use = ss.getMtotal()-ss.getMfree()-ss.getMcache()-ss.getMbuffer();\n\t\t\tuseSerie.addData(use);\n\t\t\tcacheSerie.addData(ss.getMcache());\n\t\t\tbufferSerie.addData(ss.getMbuffer());\n\t\t\tmaxUse = getBigger(maxUse, use);\n\t\t\tmaxCache = getBigger(maxCache, ss.getMcache());\n\t\t\tmaxBuffer = getBigger(maxBuffer, ss.getMbuffer());\n\t\t\tif(i == list.size() - 1) {\n\t\t\t\tcurFree = ss.getMtotal() - use;\n\t\t\t}\n\t\t\t//swap相关\n\t\t\tswapSerie.addData(ss.getMswap());\n\t\t\tfloat swapUse = ss.getMswap() - ss.getMswapFree();\n\t\t\tswapUse = floor(swapUse);\n\t\t\tswapUseSerie.addData(swapUse);\n\t\t\tmaxSwapUse = getBigger(maxSwapUse, swapUse);\n\t\t\t//net相关\n\t\t\tnetInSerie.addData(ss.getNin());\n\t\t\tnetOutSerie.addData(ss.getNout());\n\t\t\tmaxNetIn = getBigger(maxNetIn, ss.getNin());\n\t\t\tmaxNetOut = getBigger(maxNetOut, ss.getNout());\n\t\t\t//tcp相关\n\t\t\testablishedSerie.addData(ss.getTuse());\n\t\t\ttwSerie.addData(ss.getTwait());\n\t\t\torphanSerie.addData(ss.getTorphan());\n\t\t\tmaxConn = getBigger(maxConn, ss.getTuse());\n\t\t\tmaxWait = getBigger(maxWait, ss.getTwait());\n\t\t\tmaxOrphan = getBigger(maxOrphan, ss.getTorphan());\n\t\t\t//disk相关\n\t\t\treadSerie.addData(ss.getDread());\n\t\t\twriteSerie.addData(ss.getDwrite());\n\t\t\tbusySerie.addData(ss.getDbusy());\n\t\t\tiopsSerie.addData(ss.getDiops());\n\t\t\tmaxRead = getBigger(maxRead, ss.getDread());\n\t\t\tmaxWrite = getBigger(maxWrite, ss.getDwrite());\n\t\t\tmaxBusy = getBigger(maxBusy, ss.getDbusy());\n\t\t\tmaxIops = getBigger(maxIops, ss.getDiops());\n\t\t}\n\t\t//x axis\n\t\tmodel.addAttribute(\"xAxis\", JSON.toJSONString(xAxis));\n\t\t//load\n\t\tmodel.addAttribute(\"load1\", JSON.toJSONString(load1Serie));\n\t\tmodel.addAttribute(\"load5\", JSON.toJSONString(load5Serie));\n\t\tmodel.addAttribute(\"load15\", JSON.toJSONString(load15Serie));\n\t\tmodel.addAttribute(\"maxLoad1\", maxLoad1);\n\t\tmodel.addAttribute(\"avgLoad1\", format(totalLoad1, list.size()));\n\t\t//cpu\n\t\tmodel.addAttribute(\"user\", JSON.toJSONString(userSerie));\n\t\tmodel.addAttribute(\"sys\", JSON.toJSONString(sysSerie));\n\t\tmodel.addAttribute(\"wa\", JSON.toJSONString(waSerie));\n\t\tmodel.addAttribute(\"maxUser\", maxUser);\n\t\tmodel.addAttribute(\"maxSys\", maxSys);\n\t\tmodel.addAttribute(\"maxWa\", maxWa);\n\t\t//memory\n\t\tmodel.addAttribute(\"mtotal\", JSON.toJSONString(totalSerie));\n\t\tmodel.addAttribute(\"muse\", JSON.toJSONString(useSerie));\n\t\tmodel.addAttribute(\"mcache\", JSON.toJSONString(cacheSerie));\n\t\tmodel.addAttribute(\"mbuffer\", JSON.toJSONString(bufferSerie));\n\t\tmodel.addAttribute(\"curFree\", format(curFree, 1024));\n\t\tmodel.addAttribute(\"maxUse\", format(maxUse, 1024));\n\t\tmodel.addAttribute(\"maxCache\", format(maxCache, 1024));\n\t\tmodel.addAttribute(\"maxBuffer\", format(maxBuffer, 1024));\n\t\t//swap\n\t\tmodel.addAttribute(\"mswap\", JSON.toJSONString(swapSerie));\n\t\tmodel.addAttribute(\"mswapUse\", JSON.toJSONString(swapUseSerie));\n\t\tmodel.addAttribute(\"maxSwap\", maxSwapUse);\n\t\t//net\n\t\tmodel.addAttribute(\"nin\", JSON.toJSONString(netInSerie));\n\t\tmodel.addAttribute(\"nout\", JSON.toJSONString(netOutSerie));\n\t\tmodel.addAttribute(\"maxNetIn\", format(maxNetIn, 1024));\n\t\tmodel.addAttribute(\"maxNetOut\", format(maxNetOut, 1024));\n\t\t//tcp\n\t\tmodel.addAttribute(\"testab\", JSON.toJSONString(establishedSerie));\n\t\tmodel.addAttribute(\"twait\", JSON.toJSONString(twSerie));\n\t\tmodel.addAttribute(\"torph\", JSON.toJSONString(orphanSerie));\n\t\tmodel.addAttribute(\"maxConn\", maxConn);\n\t\tmodel.addAttribute(\"maxWait\", maxWait);\n\t\tmodel.addAttribute(\"maxOrphan\", maxOrphan);\n\t\t//disk\n\t\tmodel.addAttribute(\"dread\", JSON.toJSONString(readSerie));\n\t\tmodel.addAttribute(\"dwrite\", JSON.toJSONString(writeSerie));\n\t\tmodel.addAttribute(\"dbusy\", JSON.toJSONString(busySerie));\n\t\tmodel.addAttribute(\"diops\", JSON.toJSONString(iopsSerie));\n\t\tmodel.addAttribute(\"maxRead\", format(maxRead, 1024));\n\t\tmodel.addAttribute(\"maxWrite\", format(maxWrite, 1024));\n\t\tmodel.addAttribute(\"maxBusy\", maxBusy);\n\t\tmodel.addAttribute(\"maxIops\", maxIops);\n        model.addAttribute(\"date\", date);\n        return new ModelAndView(\"server/overview\");\n\t}\n\t\n\tprivate String format(double a, int b) {\n\t\tif(b <= 0) {\n\t\t\treturn \"0\";\n\t\t}\n\t\treturn df.format(a/b);\n\t}\n\t\n\tprivate float getBigger(float a, float b) {\n\t\tif(a > b) {\n\t\t\treturn a;\n\t\t}\n\t\treturn b;\n\t}\n\t\n\tprivate int getBigger(int a, int b) {\n\t\tif(a > b) {\n\t\t\treturn a;\n\t\t}\n\t\treturn b;\n\t}\n\t\n\t/**\n\t * 保留一位小数，四舍五入\n\t * @param v\n\t * @return\n\t */\n\tprivate float floor(float v) {\n\t\treturn new BigDecimal(v).setScale(1, BigDecimal.ROUND_HALF_UP).floatValue();\n\t}\n\t\n\t/**\n\t * 获取服务器cpu各个核状态\n\t * @param request\n\t * @param response\n\t * @param model\n\t * @return\n\t */\n\t@RequestMapping(\"/cpu\")\n\tpublic ModelAndView cpu(HttpServletRequest request, HttpServletResponse response, Model model) {\n\t\tString ip = request.getParameter(\"ip\");\n        String date = request.getParameter(\"date\");\n        List<ServerStatus> list = serverDataService.queryServerCpu(ip, date);\n        Map<String, CpuChart> subcpuMap = new TreeMap<String, CpuChart>();\n        //x轴坐标\n\t\tList<String> xAxis = new ArrayList<String>();\n        for(ServerStatus ss : list) {\n        \tString subcpuString = ss.getcExt();\n\t\t\tString[] subCpuArray = subcpuString.split(\";\");\n\t\t\txAxis.add(ss.getCtime());\n\t\t\tfor(String subcpu : subCpuArray) {\n\t\t\t\tif(StringUtils.isEmpty(subcpu)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tString[] cpu = subcpu.split(\",\");\n\t\t\t\tCpuChart cpuChart = subcpuMap.get(cpu[0]);\n\t\t\t\tif(cpuChart == null) {\n\t\t\t\t\tcpuChart = new CpuChart(cpu[0]);\n\t\t\t\t\tsubcpuMap.put(cpu[0], cpuChart);\n\t\t\t\t}\n\t\t\t\tfloat user = NumberUtils.toFloat(cpu[1]);\n\t\t\t\tfloat sys = NumberUtils.toFloat(cpu[2]);\n\t\t\t\tfloat wa = NumberUtils.toFloat(cpu[3]);\n\t\t\t\tcpuChart.addUserSeries(user);\n\t\t\t\tcpuChart.addSysSeries(sys);\n\t\t\t\tcpuChart.addWaSeries(wa);\n\t\t\t\tcpuChart.setMaxUser(user);\n\t\t\t\tcpuChart.setMaxSys(sys);\n\t\t\t\tcpuChart.setMaxWa(wa);\n\t\t\t\tcpuChart.addUser(user);\n\t\t\t\tcpuChart.addSys(sys);\n\t\t\t\tcpuChart.addWa(wa);\n\t\t\t}\n        }\n        //x axis\n\t\tmodel.addAttribute(\"xAxis\", JSON.toJSONString(xAxis));\n        model.addAttribute(\"cpu\", subcpuMap.values());\n        return new ModelAndView(\"server/cpu\");\n\t}\n\t\n\t/**\n\t * 获取服务器各网卡状态\n\t * @param request\n\t * @param response\n\t * @param model\n\t * @return\n\t */\n\t@RequestMapping(\"/net\")\n\tpublic ModelAndView net(HttpServletRequest request, HttpServletResponse response, Model model) {\n\t\tString ip = request.getParameter(\"ip\");\n        String date = request.getParameter(\"date\");\n        List<ServerStatus> list = serverDataService.queryServerNet(ip, date);\n        Map<String, NetChart> subnetMap = new TreeMap<String, NetChart>();\n        //x轴坐标\n\t\tList<String> xAxis = new ArrayList<String>();\n        for(ServerStatus ss : list) {\n        \txAxis.add(ss.getCtime());\n        \taddNetMap(ss.getNinExt(), subnetMap, true);\n        \taddNetMap(ss.getNoutExt(), subnetMap, false);\n        }\n        //x axis\n\t\tmodel.addAttribute(\"xAxis\", JSON.toJSONString(xAxis));\n        model.addAttribute(\"net\", subnetMap.values());\n        return new ModelAndView(\"server/net\");\n\t}\n\t\n\t/**\n\t * parse net to map\n\t * @param netString\n\t * @param subnetMap\n\t * @param isIn\n\t */\n\tprivate void addNetMap(String netString, Map<String, NetChart> subnetMap, boolean isIn) {\n\t\tString[] subnetArray = netString.split(\";\");\n\t\tfor(String subnet : subnetArray) {\n\t\t\tif(StringUtils.isEmpty(subnet)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tString[] net = subnet.split(\",\");\n\t\t\tNetChart netChart = subnetMap.get(net[0]);\n\t\t\tif(netChart == null) {\n\t\t\t\tnetChart = new NetChart(net[0]);\n\t\t\t\tsubnetMap.put(net[0], netChart);\n\t\t\t}\n\t\t\tfloat v = NumberUtils.toFloat(net[1]);\n\t\t\tif(isIn) {\n\t\t\t\tnetChart.addInSeries(v);\n\t\t\t\tnetChart.addTotalIn(v);\n\t\t\t\tnetChart.setMaxIn(v);\n\t\t\t}else {\n\t\t\t\tnetChart.addOutSeries(v);\n\t\t\t\tnetChart.addTotalOut(v);\n\t\t\t\tnetChart.setMaxOut(v);\n\t\t\t}\n\t\t}\n\t}\n\t\n\t/**\n\t * 获取硬盘各分区状态\n\t * @param request\n\t * @param response\n\t * @param model\n\t * @return\n\t */\n\t@RequestMapping(\"/disk\")\n\tpublic ModelAndView disk(HttpServletRequest request, HttpServletResponse response, Model model) {\n\t\tString ip = request.getParameter(\"ip\");\n        String date = request.getParameter(\"date\");\n        List<ServerStatus> list = serverDataService.queryServerDisk(ip, date);\n        DiskChart readChart = new DiskChart();\n        DiskChart writeChart = new DiskChart();\n        DiskChart busyChart = new DiskChart();\n        DiskChart iopsChart = new DiskChart();\n        DiskChart spaceChart = new DiskChart();\n        //x轴坐标\n\t\tList<String> xAxis = new ArrayList<String>();\n        for(ServerStatus ss : list) {\n        \txAxis.add(ss.getCtime());\n        \t//解析use\n        \tString dext = ss.getdExt();\n\t\t\tif(!StringUtils.isEmpty(dext)) {\n\t\t\t\tString[] items = dext.split(\";\");\n\t\t\t\tif(items != null) {\n\t\t\t\t\tfor(String item : items) {\n\t\t\t\t\t\tString[] sds = item.split(\"=\");\n\t\t\t\t\t\tif(sds.length == 2) {\n\t\t\t\t\t\t\tif(\"DISKXFER\".equals(sds[0])) {\n\t\t\t\t\t\t\t\taddToChart(sds[1], iopsChart);\n\t\t\t\t\t\t\t} else if(\"DISKREAD\".equals(sds[0])) {\n\t\t\t\t\t\t\t\taddToChart(sds[1], readChart);\n\t\t\t\t\t\t\t} else if(\"DISKWRITE\".equals(sds[0])) {\n\t\t\t\t\t\t\t\taddToChart(sds[1], writeChart);\n\t\t\t\t\t\t\t} else if(\"DISKBUSY\".equals(sds[0])) {\n\t\t\t\t\t\t\t\taddToChart(sds[1], busyChart);\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\t//解析space\n\t\t\tString space = ss.getDspace();\n\t\t\taddToChart(space, spaceChart);\n        }\n        //x axis\n\t\tmodel.addAttribute(\"xAxis\", JSON.toJSONString(xAxis));\n        model.addAttribute(\"read\", readChart);\n        model.addAttribute(\"write\", writeChart);\n        model.addAttribute(\"busy\", busyChart);\n        model.addAttribute(\"iops\", iopsChart);\n        model.addAttribute(\"space\", spaceChart);\n        return new ModelAndView(\"server/disk\");\n\t}\n\t\n\tprivate void addToChart(String line, DiskChart chart) {\n\t\tString[] parts = line.split(\",\");\n\t\tfor(String part : parts) {\n\t\t\tif(StringUtils.isEmpty(part)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tString[] values = part.split(\":\");\n\t\t\tfloat d = NumberUtils.toFloat(values[1]);\n\t\t\tchart.addSeries(values[0], d);\n\t\t\tchart.setMax(d);\n\t\t\tchart.addTotal(d);\n\t\t}\n\t}\n\t\n\t/**\n\t * net chart\n\t */\n\tpublic class NetChart{\n\t\tprivate String name;\n\t\tprivate Series<Float> inSeries = new Series<Float>(\"in\");\n\t\tprivate Series<Float> outSeries = new Series<Float>(\"out\");\n\t\tprivate float maxIn;\n\t\tprivate float maxOut;\n\t\tprivate float totalIn;\n\t\tprivate float totalOut;\n\t\tpublic NetChart(String name) {\n\t\t\tthis.name = name;\n\t\t}\n\t\tpublic String getName() {\n\t\t\treturn name;\n\t\t}\n\t\tpublic void setName(String name) {\n\t\t\tthis.name = name;\n\t\t}\n\t\tpublic Series<Float> getInSeries() {\n\t\t\treturn inSeries;\n\t\t}\n\t\tpublic void addInSeries(float d) {\n\t\t\tthis.inSeries.addData(d);\n\t\t}\n\t\tpublic Series<Float> getOutSeries() {\n\t\t\treturn outSeries;\n\t\t}\n\t\tpublic void addOutSeries(float d) {\n\t\t\tthis.outSeries.addData(d);\n\t\t}\n\t\tpublic float getMaxIn() {\n\t\t\treturn maxIn;\n\t\t}\n\t\tpublic void setMaxIn(float in) {\n\t\t\tif(this.maxIn < in) {\n\t\t\t\tthis.maxIn = in;\n\t\t\t}\n\t\t}\n\t\tpublic float getMaxOut() {\n\t\t\treturn maxOut;\n\t\t}\n\t\tpublic void setMaxOut(float out) {\n\t\t\tif(this.maxOut < out) {\n\t\t\t\tthis.maxOut = out;\n\t\t\t}\n\t\t}\n\t\tpublic void addTotalIn(float in) {\n\t\t\tthis.totalIn += in;\n\t\t}\n\t\tpublic void addTotalOut(float out) {\n\t\t\tthis.totalOut += out;\n\t\t}\n\t\tpublic String getAvgIn() {\n\t\t\treturn format(totalIn, inSeries.getData().size());\n\t\t}\n\t\tpublic String getAvgOut() {\n\t\t\treturn format(totalOut, outSeries.getData().size());\n\t\t}\n\t}\n\t\n\t/**\n\t * disk chart\n\t */\n\tpublic class DiskChart{\n\t\tprivate float max;\n\t\tprivate float total;\n\t\tprivate Map<String, Series<Float>> seriesMap = new TreeMap<String, Series<Float>>();\n\t\tpublic void addSeries(String partition, float d) {\n\t\t\tSeries<Float> series = seriesMap.get(partition);\n\t\t\tif(series == null) {\n\t\t\t\tseries = new Series<Float>(partition);\n\t\t\t\tseriesMap.put(partition, series);\n\t\t\t}\n\t\t\tseries.addData(d);\n\t\t}\n\t\tpublic Collection<Series<Float>> getSeries() {\n\t\t\treturn seriesMap.values();\n\t\t}\n\t\tpublic float getMax() {\n\t\t\treturn max;\n\t\t}\n\t\tpublic void setMax(float max) {\n\t\t\tif(this.max < max) {\n\t\t\t\tthis.max = max;\n\t\t\t}\n\t\t}\n\t\tpublic String getAvg() {\n\t\t\tCollection<Series<Float>> coll = seriesMap.values();\n\t\t\tint size = 0;\n\t\t\tif(coll != null) {\n\t\t\t\tfor(Series<Float> series : coll) {\n\t\t\t\t\tsize += series.getData().size();\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn format(total, size);\n\t\t}\n\t\tpublic void addTotal(float total) {\n\t\t\tthis.total += total;\n\t\t}\n\t}\n\t\n\t/**\n\t * cpu chart\n\t */\n\tpublic class CpuChart{\n\t\tprivate String name;\n\t\tprivate Series<Float> userSeries = new Series<Float>(\"user\");\n\t\tprivate Series<Float> sysSeries = new Series<Float>(\"sys\");\n\t\tprivate Series<Float> waSeries = new Series<Float>(\"wa\");\n\t\tprivate float maxUser;\n\t\tprivate float maxSys;\n\t\tprivate float maxWa;\n\t\tprivate float totalUser;\n\t\tprivate float totalSys;\n\t\tprivate float totalWa;\n\t\tpublic CpuChart(String name) {\n\t\t\tthis.name = name;\n\t\t}\n\t\tpublic String getName() {\n\t\t\treturn name;\n\t\t}\n\t\tpublic float getMaxUser() {\n\t\t\treturn maxUser;\n\t\t}\n\t\tpublic void setMaxUser(float user) {\n\t\t\tif(this.maxUser < user) {\n\t\t\t\tthis.maxUser = user;\n\t\t\t}\n\t\t}\n\t\tpublic float getMaxSys() {\n\t\t\treturn maxSys;\n\t\t}\n\t\tpublic void setMaxSys(float sys) {\n\t\t\tif(this.maxSys < sys) {\n\t\t\t\tthis.maxSys = sys;\n\t\t\t}\n\t\t}\n\t\tpublic float getMaxWa() {\n\t\t\treturn maxWa;\n\t\t}\n\t\tpublic void setMaxWa(float wa) {\n\t\t\tif(this.maxWa < wa) {\n\t\t\t\tthis.maxWa = wa;\n\t\t\t}\n\t\t}\n\t\tpublic String getAvgUser() {\n\t\t\treturn format(totalUser, userSeries.getData().size());\n\t\t}\n\t\tpublic String getAvgSys() {\n\t\t\treturn format(totalSys, sysSeries.getData().size());\n\t\t}\n\t\tpublic String getAvgWa() {\n\t\t\treturn format(totalWa, waSeries.getData().size());\n\t\t}\n\t\tpublic void addUser(float user) {\n\t\t\tthis.totalUser += user;\n\t\t}\n\t\tpublic void addSys(float sys) {\n\t\t\tthis.totalSys += sys;\n\t\t}\n\t\tpublic void addWa(float wa) {\n\t\t\tthis.totalWa += wa;\n\t\t}\n\t\tpublic Series<Float> getUserSeries() {\n\t\t\treturn userSeries;\n\t\t}\n\t\tpublic void addUserSeries(Float v) {\n\t\t\tthis.userSeries.addData(v);\n\t\t}\n\t\tpublic Series<Float> getSysSeries() {\n\t\t\treturn sysSeries;\n\t\t}\n\t\tpublic void addSysSeries(Float v) {\n\t\t\tthis.sysSeries.addData(v);\n\t\t}\n\t\tpublic Series<Float> getWaSeries() {\n\t\t\treturn waSeries;\n\t\t}\n\t\tpublic void addWaSeries(Float v) {\n\t\t\tthis.waSeries.addData(v);\n\t\t}\n\t}\n\t\n\t/**\n\t * Highchars Series\n\t * @param <T> \n\t */\n\tpublic class Series<T>{\n\t\tprivate String name;\n\t\tprivate List<T> data = new ArrayList<T>();\n\t\tprivate String type = \"spline\";\n\t\tprivate int yAxis;\n\t\tpublic String toJson() {\n\t\t\treturn JSON.toJSONString(this);\n\t\t}\n\t\tpublic Series(String name) {\n\t\t\tthis.name = name;\n\t\t}\n\t\tpublic int getYAxis() {\n\t\t\treturn yAxis;\n\t\t}\n\t\tpublic void setYAxis(int yAxis) {\n\t\t\tthis.yAxis = yAxis;\n\t\t}\n\t\tpublic void setType(String type) {\n\t\t\tthis.type = type;\n\t\t}\n\t\tpublic String getType() {\n\t\t\treturn type;\n\t\t}\n\t\tpublic String getName() {\n\t\t\treturn name;\n\t\t}\n\t\tpublic void setName(String name) {\n\t\t\tthis.name = name;\n\t\t}\n\t\tpublic void addData(T d) {\n\t\t\tdata.add(d);\n\t\t}\n\t\tpublic List<T> getData() {\n\t\t\treturn data;\n\t\t}\n\t\t@Override\n\t\tpublic String toString() {\n\t\t\treturn \"Serie [name=\" + name + \", data=\" + data + \", type=\" + type\n\t\t\t\t\t+ \", yAxis=\" + yAxis + \"]\";\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/controller/TotalManageController.java",
    "content": "package com.sohu.cache.web.controller;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport javax.annotation.Resource;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\nimport com.sohu.cache.constant.AppStatusEnum;\nimport com.sohu.cache.entity.*;\nimport com.sohu.cache.machine.MachineCenter;\nimport com.sohu.cache.stats.app.AppStatsCenter;\nimport com.sohu.cache.stats.instance.InstanceStatsCenter;\nimport com.sohu.cache.web.vo.AppDetailVO;\nimport org.apache.commons.lang.math.NumberUtils;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.servlet.ModelAndView;\n\nimport com.sohu.cache.web.enums.SuccessEnum;\n\n/**\n * 全局统计\n *\n * @author leifu\n * @Time 2014年10月14日\n */\n@Controller\n@RequestMapping(\"manage/total\")\npublic class TotalManageController extends BaseController {\n\n    @Resource(name = \"appStatsCenter\")\n    private AppStatsCenter appStatsCenter;\n\n    @Resource\n    private MachineCenter machineCenter;\n\n    @Resource\n    private InstanceStatsCenter instanceStatsCenter;\n\n    @RequestMapping(value = \"/list\")\n    public ModelAndView doTotalList(HttpServletRequest request,\n                                    HttpServletResponse response, Model model) {\n        AppUser currentUser = getUserInfo(request);\n        List<AppDesc> apps = appService.getAppDescList(currentUser, new AppSearch());\n        List<AppDetailVO> appDetailList = new ArrayList<AppDetailVO>();\n\n        long totalApplyMem = 0;\n        long totalUsedMem = 0;\n        long totalApps = 0;\n        long totalRunningApps = 0;\n        if (apps != null && apps.size() > 0) {\n            for (AppDesc appDesc : apps) {\n                AppDetailVO appDetail = appStatsCenter.getAppDetail(appDesc.getAppId());\n                appDetailList.add(appDetail);\n                totalApplyMem += appDetail.getMem();\n                totalUsedMem += appDetail.getMemUsePercent() * appDetail.getMem() / 100.0;\n                if (appDesc.getStatus() == AppStatusEnum.STATUS_PUBLISHED.getStatus()) {\n                    totalRunningApps++;\n                }\n                totalApps++;\n            }\n        }\n\n        long totalMachineMem = 0;\n        long totalFreeMachineMem = 0;\n        List<MachineStats> allMachineStats = machineCenter.getAllMachineStats();\n        for (MachineStats machineStats : allMachineStats) {\n            totalMachineMem += NumberUtils.toLong(machineStats.getMemoryTotal(), 0l);\n            totalFreeMachineMem += NumberUtils.toLong(machineStats.getMemoryFree(), 0l);\n        }\n\n        long totalInstanceMem = 0;\n        long totalUseInstanceMem = 0;\n        List<InstanceStats> instanceStats = instanceStatsCenter.getInstanceStats();\n        for (InstanceStats instanceStat : instanceStats) {\n            totalInstanceMem += instanceStat.getMaxMemory();\n            totalUseInstanceMem += instanceStat.getUsedMemory();\n        }\n\n        model.addAttribute(\"totalApps\", totalApps);\n        model.addAttribute(\"totalApplyMem\", totalApplyMem);\n        model.addAttribute(\"totalUsedMem\", totalUsedMem);\n        model.addAttribute(\"totalRunningApps\", totalRunningApps);\n\n        model.addAttribute(\"totalMachineMem\", totalMachineMem);\n        model.addAttribute(\"totalFreeMachineMem\", totalFreeMachineMem);\n\n        model.addAttribute(\"totalInstanceMem\", totalInstanceMem);\n        model.addAttribute(\"totalUseInstanceMem\", totalUseInstanceMem);\n\n        model.addAttribute(\"apps\", apps);\n        model.addAttribute(\"appDetailList\", appDetailList);\n        model.addAttribute(\"list\", apps);\n        model.addAttribute(\"totalActive\", SuccessEnum.SUCCESS.value());\n        return new ModelAndView(\"manage/total/list\");\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/controller/TriggerController.java",
    "content": "package com.sohu.cache.web.controller;\n\nimport com.sohu.cache.util.ConstUtils;\nimport com.sohu.cache.util.ObjectConvert;\n\nimport org.quartz.Scheduler;\nimport org.quartz.SchedulerException;\nimport org.quartz.TriggerKey;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Qualifier;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.util.Assert;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestMapping;\n\n/**\n * trigger操作\n * @author leifu\n * @Date 2014年05月19日\n * @Time 下午5:15:36\n */\n@Controller\n@RequestMapping(value = \"/cache/triggers\")\npublic class TriggerController {\n    private Logger logger = LoggerFactory.getLogger(this.getClass());\n\n    @Autowired(required = false)\n    @Qualifier(\"clusterScheduler\")\n    private Scheduler scheduler;\n\n    @RequestMapping(value = \"/pause/{appId}/{type}/{host}/{port}\")\n    public void pauseTrigger(@PathVariable long appId, @PathVariable int type, @PathVariable String host, @PathVariable int port) {\n        Assert.isTrue(appId > 0);\n        Assert.isTrue(type > 0);\n        Assert.hasText(host);\n        Assert.isTrue(port > 0);\n\n        String triggerName = ObjectConvert.linkIpAndPort(host, port);\n        String triggerGroup = \"\";\n        if (type == ConstUtils.CACHE_TYPE_REDIS_CLUSTER) {\n            triggerGroup = ConstUtils.REDIS_TRIGGER_GROUP + appId;\n        }\n\n        TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroup);\n        try {\n            scheduler.pauseTrigger(triggerKey);\n        } catch (SchedulerException e) {\n            logger.error(e.getMessage(), e);\n        }\n        logger.info(\"trigger with name: {}, group: {} is paused\", port, host);\n    }\n\n    @RequestMapping(value = \"/resume/{appId}/{type}/{host}/{port}\")\n    public void resumeTrigger(@PathVariable long appId, @PathVariable int type, @PathVariable String host, @PathVariable int port) {\n        Assert.isTrue(appId > 0);\n        Assert.isTrue(type > 0);\n        Assert.hasText(host);\n        Assert.isTrue(port > 0);\n\n        String triggerName = ObjectConvert.linkIpAndPort(host, port);\n        String triggerGroup = \"\";\n        if (type == ConstUtils.CACHE_TYPE_REDIS_CLUSTER) {\n            triggerGroup = ConstUtils.REDIS_TRIGGER_GROUP + appId;\n        }\n\n        TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroup);\n        try {\n            scheduler.resumeTrigger(triggerKey);\n        } catch (SchedulerException e) {\n            logger.error(e.getMessage(), e);\n        }\n        logger.info(\"trigger with name: {}, group: {} is resumed\", port, host);\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/controller/UserController.java",
    "content": "package com.sohu.cache.web.controller;\n\nimport javax.annotation.Resource;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.servlet.ModelAndView;\n\nimport com.sohu.cache.constant.AppAuditType;\nimport com.sohu.cache.entity.AppAudit;\nimport com.sohu.cache.entity.AppUser;\nimport com.sohu.cache.web.enums.SuccessEnum;\nimport com.sohu.cache.web.util.AppEmailUtil;\n\n/**\n * 注册用户管理(页面没有权限限制)\n * \n * @author leifu\n * @Date 2014年10月28日\n * @Time 上午10:49:32\n */\n@Controller\n@RequestMapping(\"/user\")\npublic class UserController extends BaseController{\n    \n    @Resource(name = \"appEmailUtil\")\n    private AppEmailUtil appEmailUtil;\n    \n    /**\n     * 注册用户页面\n     */\n    @RequestMapping(value = \"/register\")\n    public ModelAndView userRegister(HttpServletRequest request,\n            HttpServletResponse response, Model model, Integer success) {\n        model.addAttribute(\"success\", success);\n        return new ModelAndView(\"user/userRegister\");\n    }\n    \n    /**\n     * 注册用户申请\n     */\n    @RequestMapping(value = \"/apply\")\n    public ModelAndView doAddUser(HttpServletRequest request,\n            HttpServletResponse response, Model model, String name, String chName, String email, String mobile,\n            Integer type, Long userId) {\n        SuccessEnum success = SuccessEnum.SUCCESS;\n        try {\n            //保存用户(type=-1为无效用户,需要审批)\n            AppUser appUser = AppUser.buildFrom(userId, name, chName, email, mobile, type);\n            userService.save(appUser);\n            //提交审批\n            AppAudit appAudit = appService.saveRegisterUserApply(appUser,AppAuditType.REGISTER_USER_APPLY);\n            appEmailUtil.noticeUserResult(appUser, appAudit);\n        } catch (Exception e) {\n            success = SuccessEnum.FAIL;\n            logger.error(e.getMessage(), e);\n        }\n        return new ModelAndView(\"redirect:/user/register?success=\" + success.value());\n    }\n    \n    \n    @RequestMapping(value = \"/checkUserNameExist\")\n    public ModelAndView doCheckUserNameExist(HttpServletRequest request,\n            HttpServletResponse response, Model model, String userName) {\n        AppUser appUser = userService.getByName(userName);\n        if (appUser != null) {\n            write(response, String.valueOf(SuccessEnum.SUCCESS.value()));\n        } else {\n            write(response, String.valueOf(SuccessEnum.FAIL.value()));\n        }\n        return null;\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/controller/UserManageController.java",
    "content": "package com.sohu.cache.web.controller;\n\nimport java.util.List;\n\nimport javax.annotation.Resource;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.servlet.ModelAndView;\n\nimport com.sohu.cache.constant.AppCheckEnum;\nimport com.sohu.cache.constant.AppUserTypeEnum;\nimport com.sohu.cache.entity.AppAudit;\nimport com.sohu.cache.entity.AppUser;\nimport com.sohu.cache.web.enums.SuccessEnum;\nimport com.sohu.cache.web.util.AppEmailUtil;\n\n/**\n * 用户信息管理\n * @author leifu\n * @Time 2014年6月6日\n */\n@Controller\n@RequestMapping(\"manage/user\")\npublic class UserManageController extends BaseController {\n    \n    @Resource(name = \"appEmailUtil\")\n    private AppEmailUtil appEmailUtil;\n\n    /**\n     * 用户初始化\n     * @param id 用户id\n     * @return\n     */\n    @RequestMapping(value = \"/init\")\n    public ModelAndView doUserInit(HttpServletRequest request,\n            HttpServletResponse response, Model model, Long id) {\n        if (id != null) {\n            AppUser user = userService.get(id);\n            model.addAttribute(\"user\", user);\n            model.addAttribute(\"modify\", true);\n        }\n        return new ModelAndView(\"manage/user/initUser\");\n    }\n\n    /**\n     * 更新用户\n     * @param name\n     * @param chName\n     * @param email\n     * @param mobile\n     * @param type\n     * @param userId\n     * @return\n     */\n    @RequestMapping(value = \"/add\")\n    public ModelAndView doAddUser(HttpServletRequest request,\n            HttpServletResponse response, Model model, String name, String chName, String email, String mobile,\n            Integer type, Long userId) {\n        // 后台暂时不对参数进行验证\n        AppUser appUser = AppUser.buildFrom(userId, name, chName, email, mobile, type);\n        try {\n\t\t\tif (userId == null) {\n\t\t\t    userService.save(appUser);\n\t\t\t} else {\n\t\t\t    userService.update(appUser);\n\t\t\t}\n\t        write(response, String.valueOf(SuccessEnum.SUCCESS.value()));\n\t\t} catch (Exception e) {\n\t\t    write(response, String.valueOf(SuccessEnum.FAIL.value()));\n\t        logger.error(e.getMessage(), e);\n\t\t}\n        return null;\n    }\n\n    /**\n     * 删除用户\n     * @param userId\n     * @return\n     */\n    @RequestMapping(value = \"/delete\")\n    public ModelAndView doDeleteUser(HttpServletRequest request,\n            HttpServletResponse response, Model model, Long userId) {\n        userService.delete(userId);\n        return new ModelAndView(\"redirect:/manage/user/list\");\n    }\n\n    /**\n     * 用户列表\n     * @param chName 中文名\n     * @return\n     */\n    @RequestMapping(value = \"/list\")\n    public ModelAndView doUserList(HttpServletRequest request,\n            HttpServletResponse response, Model model, String searchChName) {\n        List<AppUser> users = userService.getUserList(searchChName);\n        model.addAttribute(\"users\", users);\n        model.addAttribute(\"searchChName\", searchChName);\n        model.addAttribute(\"userActive\", SuccessEnum.SUCCESS.value());\n        return new ModelAndView(\"manage/user/list\");\n    }\n    \n    @RequestMapping(value = \"/addAuditStatus\")\n    public ModelAndView doAddAuditStatus(HttpServletRequest request,\n            HttpServletResponse response, Model model, Integer status,\n            Long appAuditId, String refuseReason) {\n        AppAudit appAudit = appService.getAppAuditById(appAuditId);\n        AppUser appUser = userService.get(appAudit.getUserId());\n        // 通过或者驳回并记录日志\n        appService.updateUserAuditStatus(appAuditId, status);\n\n        // 记录驳回原因\n        if (AppCheckEnum.APP_REJECT.value().equals(status)) {\n            appAudit.setRefuseReason(refuseReason);\n            appService.updateRefuseReason(appAudit, getUserInfo(request));\n            userService.delete(appUser.getId());\n        }\n\n        // 发邮件统计\n        if (AppCheckEnum.APP_PASS.value().equals(status)\n                || AppCheckEnum.APP_REJECT.value().equals(status)) {\n            appUser.setType(AppUserTypeEnum.REGULAR_USER.value());\n            appAudit.setStatus(status);\n            userService.update(appUser);\n            appEmailUtil.noticeUserResult(appUser, appAudit);\n        }\n\n        // 批准成功直接跳转\n        if (AppCheckEnum.APP_PASS.value().equals(status)) {\n            return new ModelAndView(\"redirect:/manage/app/auditList\");\n        }\n\n        write(response, String.valueOf(SuccessEnum.SUCCESS.value()));\n        return null;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/enums/AdminEnum.java",
    "content": "package com.sohu.cache.web.enums;\n\n/**\n * 管理员\n * \n * @author leifu\n * @Time 2014年10月16日\n */\npublic enum AdminEnum {\n    IS_ADMIN(1), // 是管理员\n    NOT_ADMIN(0); // 不是管理员\n\n    int value;\n\n    private AdminEnum(int value) {\n        this.value = value;\n    }\n\n    public int value() {\n        return value;\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/enums/AppOrderByEnum.java",
    "content": "package com.sohu.cache.web.enums;\n\n/**\n * app列表排序\n * @author leifu\n * @Date 2014年11月14日\n * @Time 上午10:55:47\n */\npublic enum AppOrderByEnum {\n    HIT_PERCENTAGE_HIGH_TO_LOW(\"hit_percentage_high_to_low\"),\n    HIT_PERCENTAGE_LOW_TO_HIGH(\"hit_percentage_low_to_high\");\n    \n    private String value;\n\n    private AppOrderByEnum(String value) {\n        this.value = value;\n    }\n\n    public String getValue() {\n        return value;\n    }\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/enums/LoginEnum.java",
    "content": "package com.sohu.cache.web.enums;\n\n/**\n * 登录状态\n * \n * @author leifu\n * @Time 2014年10月16日\n */\npublic enum LoginEnum {\n    LOGIN_SUCCESS(1), // 成功\n    LOGIN_WRONG_USER_OR_PASSWORD(0), // 用户名或者密码错误\n    LOGIN_USER_NOT_EXIST(-1), // 不是cachecloud用户\n    LOGIN_NOT_ADMIN(-2);// 不是超级管理员\n\n    int value;\n\n    private LoginEnum(int value) {\n        this.value = value;\n    }\n\n    public int value() {\n        return value;\n    }\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/enums/RedisOperateEnum.java",
    "content": "package com.sohu.cache.web.enums;\n\n/**\n * \n * @author leifu\n * @Date 2016年1月12日\n * @Time 下午2:28:25\n */\npublic enum RedisOperateEnum {\n   \n    OP_SUCCESS(1),\n    ALREADY_SUCCESS(2),\n    FAIL(0);\n    \n    private int value;\n\n    private RedisOperateEnum(int value) {\n        this.value = value;\n    }\n\n    public int getValue() {\n        return value;\n    }\n    \n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/enums/SuccessEnum.java",
    "content": "package com.sohu.cache.web.enums;\n\n/**\n * 成功失败状态\n * \n * @author leifu\n * @Time 2014年10月16日\n */\npublic enum SuccessEnum {\n    SUCCESS(1),\n    FAIL(0);\n\n    int value;\n\n    private SuccessEnum(int value) {\n        this.value = value;\n    }\n\n    public int value() {\n        return value;\n    }\n    \n    public String info() {\n        if (value == 1) {\n            return \"成功\";\n        } else {\n            return \"失败\";\n        }\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/factory/UserLoginStatusFactory.java",
    "content": "package com.sohu.cache.web.factory;\n\nimport java.util.Map;\n\nimport com.sohu.cache.constant.UserLoginTypeEnum;\nimport com.sohu.cache.util.ConstUtils;\nimport com.sohu.cache.web.service.UserLoginStatusService;\n\n/**\n * 用户登录状态信息服务工厂\n * @author leifu\n * @Date 2016年6月15日\n * @Time 下午1:48:36\n */\npublic class UserLoginStatusFactory {\n\n    private Map<UserLoginTypeEnum, UserLoginStatusService> userloginTypeMap;\n\n    public UserLoginStatusService getUserLoginStatusService() {\n        UserLoginTypeEnum loginTypeEnum = UserLoginTypeEnum.getLoginTypeEnum(ConstUtils.USER_LOGIN_TYPE);\n        return userloginTypeMap.get(loginTypeEnum);\n    }\n\n    public void setUserloginTypeMap(Map<UserLoginTypeEnum, UserLoginStatusService> userloginTypeMap) {\n        this.userloginTypeMap = userloginTypeMap;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/service/AppService.java",
    "content": "package com.sohu.cache.web.service;\n\nimport java.util.List;\n\nimport com.sohu.cache.constant.AppAuditType;\nimport com.sohu.cache.entity.*;\nimport com.sohu.cache.web.enums.SuccessEnum;\n\n/**\n * 应用相关操作\n * @author leifu\n * @Time 2014年10月21日\n */\npublic interface AppService {\n    \n    /**\n     * 查询指定用户下的应用个数\n     * @param appUser\n     * @return\n     */\n    int getAppDescCount(AppUser appUser, AppSearch appSearch);\n\n    /**\n     * 查询指定用户下的所有的应用\n     * @param appUser\n     * @return\n     */\n    List<AppDesc> getAppDescList(AppUser appUser, AppSearch appSearch);\n\n    /**\n     * 按照Appid取应用信息\n     * @param appId\n     * @return\n     */\n    AppDesc getByAppId(Long appId);\n\n    /**\n     * 保存应用\n     * @param appDesc\n     * @return\n     */\n    int save(AppDesc appDesc);\n\n    /**\n     * 更新应用\n     * @param appDesc\n     * @return\n     */\n    int update(AppDesc appDesc);\n\n    /**\n     * 获取应用的实例\n     * @param appId\n     * @return\n     */\n    List<InstanceInfo> getAppInstanceInfo(Long appId);\n\n    List<InstanceStats> getAppInstanceStats(Long appId);\n\n    /**\n     * 保存用户与应用的关系\n     * @param appId\n     * @param userId\n     * @return\n     */\n    boolean saveAppToUser(Long appId, Long userId);\n\n    /**\n     * 更新审核状态\n     * @param id 审批id\n     * @param appId\n     * @param status 审批状态\n     * @param appUser 更新人\n     */\n    void updateAppAuditStatus(Long id, Long appId, Integer status, AppUser appUser);\n\n    /**\n     * 更新用户审核状态\n     * @param id 审批id\n     * @param status 审批状态\n     */\n    void updateUserAuditStatus(Long id, Integer status);\n\n    \n    /**\n     * 通过应用名获取应用\n     * @param appName\n     * @return\n     */\n    AppDesc getAppByName(String appName);\n\n    /**\n     * 获取应用下的所有用户应用关系列表\n     * @param appId\n     * @return\n     */\n    List<AppToUser> getAppToUserList(Long appId);\n    \n    /**\n     * 删除用户应用关系\n     * @param appId\n     * @param userId\n     */\n    SuccessEnum deleteAppToUser(Long appId, Long userId);\n\n    /**\n     * 获取审批列表\n     * @param status(参考AppAppCheckEnum)\n     * @param type (参考AppAuditType)\n     * @return\n     */\n    List<AppAudit> getAppAudits(Integer status, Integer type);\n\n    /**\n     * 保存扩容申请\n     * @param appDesc\n     * @param appUser \n     * @param applyMemSize 扩容容量\n     * @param appScaleReason 扩容原因\n     * @param appScale 申请类型\n     */\n    AppAudit saveAppScaleApply(AppDesc appDesc, AppUser appUser, String applyMemSize, String appScaleReason, AppAuditType appScale);\n\n    /**\n     * 保存应用配置申请\n     * @param appDesc\n     * @param appUser\n     * @param instanceId 实例id\n     * @param appConfigKey 配置项\n     * @param appConfigValue 配置值\n     * @param modifyConfig 申请类型\n     */\n    AppAudit saveAppChangeConfig(AppDesc appDesc, AppUser appUser, Long instanceId, String appConfigKey, String appConfigValue,String appConfigReason, AppAuditType modifyConfig);\n\n    /**\n     * 保存实例配置申请\n     * @param appDesc\n     * @param appUser\n     * @param instanceId\n     * @param instanceConfigKey\n     * @param instanceConfigValue\n     * @param instanceConfigReason\n     * @param instanceModifyConfig\n     * @return\n     */\n    AppAudit saveInstanceChangeConfig(AppDesc appDesc, AppUser appUser, Long instanceId, String instanceConfigKey, String instanceConfigValue, String instanceConfigReason, AppAuditType instanceModifyConfig);\n    \n    /**\n     * 获取审批信息\n     * @param appAuditId\n     * @return\n     */\n    AppAudit getAppAuditById(Long appAuditId);\n\n    /**\n     * 驳回理由\n     * @param appAudit\n     * @param userInfo\n     */\n    SuccessEnum updateRefuseReason(AppAudit appAudit, AppUser userInfo);\n\n    /**\n     * 获取用户的应用数量\n     * @param userId\n     * @return\n     */\n    int getUserAppCount(Long userId);\n\n    /**\n     * 获取应用的机器信息\n     * @param appId\n     * @return\n     */\n    List<MachineStats> getAppMachineDetail(Long appId);\n\n    /**\n     * 根据应用id获取审批记录\n     * @param appId\n     * @return\n     */\n    List<AppAudit> getAppAuditListByAppId(Long appId);\n\n    /**\n     * 注册用户申请\n     * @param appUser\n     * @param registerUserApply\n     * @return\n     */\n    AppAudit saveRegisterUserApply(AppUser appUser, AppAuditType registerUserApply);\n\n    /**\n     * 获取所有应用\n     */\n    List<AppDesc> getAllAppDesc();\n\n    /**\n     * 修改报警配置\n     * @param appId\n     * @param memAlertValue\n     * @param clientConnAlertValue\n     * @param appUser\n     * @return\n     */\n    SuccessEnum changeAppAlertConfig(long appId, int memAlertValue, int clientConnAlertValue, AppUser appUser);\n\n    /**\n     * 更新appKey\n     * @param appId\n     */\n    void updateAppKey(long appId);\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/service/ConfigService.java",
    "content": "package com.sohu.cache.web.service;\n\nimport java.util.List;\nimport java.util.Map;\n\nimport com.sohu.cache.entity.SystemConfig;\nimport com.sohu.cache.web.enums.SuccessEnum;\n\n/**\n * cachecloud配置服务\n * @author leifu\n * @Date 2016年5月23日\n * @Time 上午10:35:04\n */\npublic interface ConfigService {\n    \n    /**\n     * 加载配置\n     */\n    public void reloadSystemConfig();\n\n    /**\n     * 更新配置\n     * @param configMap\n     * @return\n     */\n    SuccessEnum updateConfig(Map<String, String> configMap);\n\n    /**\n     * 获取配置列表\n     * @param status\n     * @return\n     */\n    List<SystemConfig> getConfigList(int status);\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/service/MemFaultService.java",
    "content": "package com.sohu.cache.web.service;\n\nimport java.util.List;\n\nimport com.sohu.cache.entity.InstanceFault;\n\n/**\n * 故障服务\n * @author leifu\n * @Date 2015-6-6\n * @Time 下午10:03:38\n */\npublic interface MemFaultService {\n    \n    /**\n     * 获取故障列表\n     * @return\n     */\n    List<InstanceFault> getFaultList();\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/service/ServerDataService.java",
    "content": "package com.sohu.cache.web.service;\n\nimport java.util.List;\n\nimport com.sohu.cache.entity.ServerInfo;\nimport com.sohu.cache.entity.ServerStatus;\nimport com.sohu.cache.server.data.Server;\n\npublic interface ServerDataService {\n\t/**\n\t * 查询服务器基本信息\n\t * @param ip\n\t * @return @ServerInfo\n\t */\n\tpublic ServerInfo queryServerInfo(String ip);\n\t\n\t/**\n\t * 保存服务器发行版信息\n\t * @param ip\n\t * @param dist from /etc/issue\n\t */\n\tpublic void saveServerInfo(String ip, String dist);\n\t\n\t/**\n\t * 保存/更新服务器信息\n\t * @param server\n\t * @return 影响的行数\n\t */\n\tpublic Integer saveAndUpdateServerInfo(Server server);\n\t\n\t/**\n\t * 查询服务器状态\n\t * @param ip\n\t * @param date\n\t * @return List<ServerStatus>\n\t */\n\tpublic List<ServerStatus> queryServerStatus(String ip, String date);\n\t\n\t/**\n\t * 查询服务器状态\n\t * @param ip\n\t * @param date\n\t * @return List<ServerStatus>\n\t */\n\tpublic List<ServerStatus> queryServerOverview(String ip, String date);\n\t/**\n\t * 查询服务器状态\n\t * @param ip\n\t * @param date\n\t * @return List<ServerStatus>\n\t */\n\tpublic List<ServerStatus> queryServerCpu(String ip, String date);\n\t/**\n\t * 查询服务器状态\n\t * @param ip\n\t * @param date\n\t * @return List<ServerStatus>\n\t */\n\tpublic List<ServerStatus> queryServerNet(String ip, String date);\n\t/**\n\t * 查询服务器状态\n\t * @param ip\n\t * @param date\n\t * @return List<ServerStatus>\n\t */\n\tpublic List<ServerStatus> queryServerDisk(String ip, String date);\n\t\n\t/**\n\t * 保存服务器状态\n\t */\n\tpublic void saveServerStat(Server server);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/service/UserLoginStatusService.java",
    "content": "package com.sohu.cache.web.service;\n\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\n/**\n * 用户登录状态信息服务\n * \n * @author leifu\n * @Date 2016年6月15日\n * @Time 下午1:24:09\n */\npublic interface UserLoginStatusService {\n    public final static String LOGIN_USER_STATUS_NAME = \"CACHE_CLOUD_USER_STATUS\";\n\n    /**\n     * 获取用户登录状态信息\n     * \n     * @param request\n     * @return\n     */\n    long getUserIdFromLoginStatus(HttpServletRequest request);\n\n    /**\n     * 添加用户登录状态信息\n     * \n     * @param request\n     * @param response\n     * @param userId\n     */\n    void addLoginStatus(HttpServletRequest request, HttpServletResponse response, String userId);\n\n    /**\n     * 移除用户登录状态信息\n     * \n     * @param request\n     * @param response\n     */\n    void removeLoginStatus(HttpServletRequest request, HttpServletResponse response);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/service/UserService.java",
    "content": "package com.sohu.cache.web.service;\n\nimport java.util.List;\n\nimport com.sohu.cache.entity.AppUser;\nimport com.sohu.cache.web.enums.SuccessEnum;\n\n/**\n * 用户管理service\n * @author leifu\n * @Date 2014年10月27日\n * @Time 上午9:57:47\n */\npublic interface UserService {\n\n    /**\n     * 通过id获取用户\n     * @param userId\n     * @return\n     */\n    AppUser get(Long userId);\n\n    /**\n     * 通过中文名获取用户\n     * @param chName\n     * @return\n     */\n    List<AppUser> getUserList(String chName);\n\n    /**\n     * 获取某个应用下的所有用户\n     * @param appId\n     * @return\n     */\n    List<AppUser> getByAppId(Long appId);\n\n    /**\n     * 通过域账户前缀获取用户\n     * @param name\n     * @return\n     */\n    AppUser getByName(String name);\n\n    /**\n     * 保存用户\n     * @param appUser\n     * @return\n     */\n    SuccessEnum save(AppUser appUser);\n\n    /**\n     * 更新用户\n     * @param appUser\n     * @return\n     */\n    SuccessEnum update(AppUser appUser);\n\n    /**\n     * 删除用户\n     * @param userId\n     * @return\n     */\n    SuccessEnum delete(Long userId);\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/service/impl/AppServiceImpl.java",
    "content": "package com.sohu.cache.web.service.impl;\n\nimport com.sohu.cache.constant.*;\nimport com.sohu.cache.dao.*;\nimport com.sohu.cache.entity.*;\nimport com.sohu.cache.machine.MachineCenter;\nimport com.sohu.cache.redis.RedisCenter;\nimport com.sohu.cache.util.AppKeyUtil;\nimport com.sohu.cache.util.TypeUtil;\nimport com.sohu.cache.web.enums.SuccessEnum;\nimport com.sohu.cache.web.service.AppService;\n\nimport org.springframework.util.Assert;\n\nimport java.util.*;\n\nimport org.apache.commons.collections.CollectionUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport redis.clients.jedis.HostAndPort;\n\n/**\n * 应用操作实现类\n *\n * @author leifu\n * @Time 2014年10月21日\n */\npublic class AppServiceImpl implements AppService {\n\n    private Logger logger = LoggerFactory.getLogger(AppServiceImpl.class);\n\n    /**\n     * 应用相关dao\n     */\n    private AppDao appDao;\n\n    /**\n     * 应用日志相关dao\n     */\n    private AppAuditLogDao appAuditLogDao;\n\n    /**\n     * 实例相关dao\n     */\n    private InstanceDao instanceDao;\n\n    /**\n     * 应用用户关系相关dao\n     */\n    private AppToUserDao appToUserDao;\n\n    /**\n     * 应用申请相关dao\n     */\n    private AppAuditDao appAuditDao;\n    \n    /**\n     * 用户信息dao\n     */\n    private AppUserDao appUserDao;\n\n    private InstanceStatsDao instanceStatsDao;\n\n    private RedisCenter redisCenter;\n\n    private MachineCenter machineCenter;\n    \n    private MachineStatsDao machineStatsDao;\n    \n    @Override\n    public int getAppDescCount(AppUser appUser, AppSearch appSearch) {\n        int count = 0;\n        // 管理员获取全部应用\n        if (AppUserTypeEnum.ADMIN_USER.value().equals(appUser.getType())) {\n            count = appDao.getAllAppCount(appSearch);\n        } else {\n            count = appDao.getUserAppCount(appUser.getId());\n        }\n        return count;\n    }\n    \n    @Override\n    public List<AppDesc> getAppDescList(AppUser appUser, AppSearch appSearch) {\n        List<AppDesc> list = new ArrayList<AppDesc>();\n        // 管理员获取全部应用\n        if (AppUserTypeEnum.ADMIN_USER.value().equals(appUser.getType())) {\n            list = appDao.getAllAppDescList(appSearch);\n        } else {\n            list = appDao.getAppDescList(appUser.getId());\n        }\n        return list;\n    }\n\n    @Override\n    public AppDesc getByAppId(Long appId) {\n        Assert.isTrue(appId > 0);\n\n        AppDesc appDesc = null;\n        try {\n            appDesc = appDao.getAppDescById(appId);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n        return appDesc;\n    }\n\n    @Override\n    public int save(AppDesc appDesc) {\n        return appDao.save(appDesc);\n    }\n\n    @Override\n    public int update(AppDesc appDesc) {\n        return appDao.update(appDesc);\n    }\n\n    @Override\n    public boolean saveAppToUser(Long appId, Long userId) {\n        try {\n            // 用户id下应用\n            List<AppToUser> list = appToUserDao.getByUserId(userId);\n            if (CollectionUtils.isNotEmpty(list)) {\n                for (AppToUser appToUser : list) {\n                    if (appToUser.getAppId().equals(appId)) {\n                        return true;\n                    }\n                }\n            }\n            appToUserDao.save(new AppToUser(userId, appId));\n            return true;\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return false;\n        }\n    }\n\n    @Override\n    public void updateAppAuditStatus(Long id, Long appId, Integer status, AppUser appUser) {\n        appAuditDao.updateAppAudit(id, status);\n        AppDesc appDesc = appDao.getAppDescById(appId);\n        AppAudit appAudit = appAuditDao.getAppAudit(id);\n        \n        // 只有应用创建才会设置状态\n        if (AppAuditType.APP_AUDIT.getValue() == appAudit.getType()) {\n            if (AppCheckEnum.APP_PASS.value().equals(status)) {\n                appDesc.setStatus(AppStatusEnum.STATUS_PUBLISHED.getStatus());\n                appDesc.setPassedTime(new Date());\n                appDao.update(appDesc);\n            } else if (AppCheckEnum.APP_REJECT.value().equals(status)) {\n                appDesc.setStatus(AppStatusEnum.STATUS_DENY.getStatus());\n                appDao.update(appDesc);\n            }\n        }\n        \n        // 保存审批日志\n        AppAuditLog appAuditLog = AppAuditLog.generate(appDesc, appUser, appAudit.getId(),\n                AppAuditLogTypeEnum.APP_CHECK);\n        if (appAuditLog != null) {\n            appAuditLogDao.save(appAuditLog);\n        }\n    }\n    \n    @Override\n    public void updateUserAuditStatus(Long id, Integer status) {\n        appAuditDao.updateAppAudit(id, status);\n    }\n\n    @Override\n    public List<AppToUser> getAppToUserList(Long appId) {\n        return appToUserDao.getByAppId(appId);\n    }\n\n    @Override\n    public AppDesc getAppByName(String appName) {\n        return appDao.getByAppName(appName);\n    }\n\n    @Override\n    public List<InstanceInfo> getAppInstanceInfo(Long appId) {\n    \t\tAppDesc appDesc = appDao.getAppDescById(appId);\n    \t\tString password = appDesc.getPassword();\n    \t\t\n        List<InstanceInfo> resultList = instanceDao.getInstListByAppId(appId);\n        if (resultList != null && resultList.size() > 0) {\n            for (InstanceInfo instanceInfo : resultList) {\n                int type = instanceInfo.getType();\n                if(instanceInfo.getStatus() != InstanceStatusEnum.GOOD_STATUS.getStatus()){\n                    continue;\n                }\n                if (TypeUtil.isRedisType(type)) {\n                    if (TypeUtil.isRedisSentinel(type)) {\n                        continue;\n                    }\n                    String host = instanceInfo.getIp();\n                    int port = instanceInfo.getPort();\n                    Boolean isMaster = redisCenter.isMaster(appId, host, port);\n                    instanceInfo.setRoleDesc(isMaster);\n                    if(isMaster != null && !isMaster){\n                        HostAndPort hap = redisCenter.getMaster(host, port, password);\n                        if (hap != null) {\n                            instanceInfo.setMasterHost(hap.getHost());\n                            instanceInfo.setMasterPort(hap.getPort());\n                            for (InstanceInfo innerInfo : resultList) {\n                                if (innerInfo.getIp().equals(hap.getHost())\n                                        && innerInfo.getPort() == hap.getPort()) {\n                                    instanceInfo.setMasterInstanceId(innerInfo.getId());\n                                    break;\n                                }\n                            }\n                        }\n                    }\n\n                }\n            }\n        }\n        return resultList;\n    }\n    @Override\n    public List<InstanceStats> getAppInstanceStats(Long appId) {\n        List<InstanceStats> instanceStats = instanceStatsDao.getInstanceStatsByAppId(appId);\n        return instanceStats;\n    }\n\n    @Override\n    public SuccessEnum deleteAppToUser(Long appId, Long userId) {\n        try {\n            appToUserDao.deleteAppToUser(appId, userId);\n            return SuccessEnum.SUCCESS;\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return SuccessEnum.FAIL;\n        }\n    }\n\n    @Override\n    public List<AppAudit> getAppAudits(Integer status, Integer type) {\n        List<AppAudit> list = appAuditDao.selectWaitAppAudits(status, type);\n        for (Iterator<AppAudit> i = list.iterator(); i.hasNext(); ) {\n            AppAudit appAudit = i.next();\n            AppDesc appDesc = appDao.getAppDescById(appAudit.getAppId());\n//            if (appDesc == null) {\n//                i.remove();\n//            }\n            appAudit.setAppDesc(appDesc);\n        }\n        return list;\n    }\n\n    @Override\n    public AppAudit saveAppScaleApply(AppDesc appDesc, AppUser appUser, String applyMemSize, String appScaleReason,\n                                      AppAuditType appScale) {\n        AppAudit appAudit = new AppAudit();\n        appAudit.setAppId(appDesc.getAppId());\n        appAudit.setUserId(appUser.getId());\n        appAudit.setUserName(appUser.getName());\n        appAudit.setModifyTime(new Date());\n        appAudit.setParam1(applyMemSize);\n        appAudit.setParam2(appScaleReason);\n        appAudit.setInfo(\"扩容申请---申请容量:\" + applyMemSize + \", 申请原因: \" + appScaleReason);\n        appAudit.setStatus(AppCheckEnum.APP_WATING_CHECK.value());\n        appAudit.setType(appScale.getValue());\n        appAuditDao.insertAppAudit(appAudit);\n\n        //保存扩容申请\n        AppAuditLog appAuditLog = AppAuditLog.generate(appDesc, appUser, appAudit.getId(),\n                AppAuditLogTypeEnum.APP_SCALE_APPLY);\n        if (appAuditLog != null) {\n            appAuditLogDao.save(appAuditLog);\n        }\n\n        return appAudit;\n    }\n\n    @Override\n    public AppAudit saveAppChangeConfig(AppDesc appDesc, AppUser appUser, Long instanceId, String appConfigKey, String appConfigValue, String appConfigReason, AppAuditType modifyConfig) {\n        AppAudit appAudit = new AppAudit();\n        appAudit.setAppId(appDesc.getAppId());\n        appAudit.setUserId(appUser.getId());\n        appAudit.setUserName(appUser.getName());\n        appAudit.setModifyTime(new Date());\n        appAudit.setParam1(String.valueOf(instanceId));\n        appAudit.setParam2(appConfigKey);\n        appAudit.setParam3(appConfigValue);\n        appAudit.setInfo(\"修改配置项:\" + appConfigKey + \", 配置值: \" + appConfigValue + \", 修改原因: \" + appConfigReason);\n        appAudit.setStatus(AppCheckEnum.APP_WATING_CHECK.value());\n        appAudit.setType(modifyConfig.getValue());\n        appAuditDao.insertAppAudit(appAudit);\n\n        //保存日志\n        AppAuditLog appAuditLog = AppAuditLog.generate(appDesc, appUser, appAudit.getId(),\n                AppAuditLogTypeEnum.APP_CONFIG_APPLY);\n        if (appAuditLog != null) {\n            appAuditLogDao.save(appAuditLog);\n        }\n\n        return appAudit;\n\n    }\n    \n    @Override\n    public AppAudit saveInstanceChangeConfig(AppDesc appDesc, AppUser appUser, Long instanceId,\n            String instanceConfigKey, String instanceConfigValue, String instanceConfigReason,\n            AppAuditType instanceModifyConfig) {\n        AppAudit appAudit = new AppAudit();\n        long appId = appDesc.getAppId();\n        appAudit.setAppId(appId);\n        appAudit.setUserId(appUser.getId());\n        appAudit.setUserName(appUser.getName());\n        appAudit.setModifyTime(new Date());\n        appAudit.setParam1(String.valueOf(instanceId));\n        appAudit.setParam2(instanceConfigKey);\n        appAudit.setParam3(instanceConfigValue);\n        InstanceInfo instanceInfo = instanceDao.getInstanceInfoById(instanceId);\n        String hostPort = instanceInfo == null ? \"\" : (instanceInfo.getIp() + \":\" + instanceInfo.getPort());\n        appAudit.setInfo(\"appId=\" + appId + \"下的\" + hostPort + \"实例申请修改配置项:\" + instanceConfigKey + \", 配置值: \" + instanceConfigValue + \", 修改原因: \" + instanceConfigReason);\n        appAudit.setStatus(AppCheckEnum.APP_WATING_CHECK.value());\n        appAudit.setType(instanceModifyConfig.getValue());\n        appAuditDao.insertAppAudit(appAudit);\n\n        //保存日志\n        AppAuditLog appAuditLog = AppAuditLog.generate(appDesc, appUser, appAudit.getId(), AppAuditLogTypeEnum.INSTANCE_CONFIG_APPLY);\n        if (appAuditLog != null) {\n            appAuditLogDao.save(appAuditLog);\n        }\n\n        return appAudit;\n    }\n    \n    @Override\n    public SuccessEnum updateRefuseReason(AppAudit appAudit, AppUser userInfo) {\n        try {\n            appAuditDao.updateRefuseReason(appAudit.getId(), appAudit.getRefuseReason());\n            return SuccessEnum.SUCCESS;\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return SuccessEnum.FAIL;\n        }\n    }\n\n    @Override\n    public int getUserAppCount(Long userId) {\n        int count = 0;\n        try {\n            // 表比较小\n            List<AppToUser> list = appToUserDao.getByUserId(userId);\n            if (CollectionUtils.isNotEmpty(list)) {\n                count = list.size();\n            }\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n        return count;\n    }\n    \n    @Override\n    public List<MachineStats> getAppMachineDetail(Long appId) {\n        //应用信息\n        Assert.isTrue(appId != null && appId > 0L);\n        AppDesc appDesc = appDao.getAppDescById(appId);\n        if (appDesc == null) {\n            logger.error(\"appDesc:id={} is not exist\");\n            return Collections.emptyList();\n        }\n        \n        //应用实例列表\n        List<InstanceInfo> appInstanceList = getAppInstanceInfo(appId);\n        if (CollectionUtils.isEmpty(appInstanceList)) {\n            return Collections.emptyList();\n        }\n        \n        //防止重复\n        Set<String> instanceMachineHosts = new HashSet<String>();\n        //结果列表\n        List<MachineStats> machineDetailVOList = new ArrayList<MachineStats>();\n        //应用的机器信息\n        for (InstanceInfo instanceInfo : appInstanceList) {\n            String ip = instanceInfo.getIp();\n            if (instanceMachineHosts.contains(ip)) {\n                continue;\n            } else {\n                instanceMachineHosts.add(ip);\n            }\n            MachineStats machineStats = machineStatsDao.getMachineStatsByIp(ip);\n            if (machineStats == null) {\n                continue;\n            }\n            //已经分配的内存\n            int memoryHost = instanceDao.getMemoryByHost(ip);\n            machineStats.setMemoryAllocated(memoryHost);\n            //机器信息\n            MachineInfo machineInfo = machineCenter.getMachineInfoByIp(ip);\n            if (machineInfo == null) {\n                continue;\n            }\n            //下线机器不展示\n            if (machineInfo.isOffline()) {\n                continue;\n            }\n            machineStats.setInfo(machineInfo);\n            machineDetailVOList.add(machineStats);\n        }\n        return machineDetailVOList;\n    }\n\n    @Override\n    public AppAudit getAppAuditById(Long appAuditId) {\n        return appAuditDao.getAppAudit(appAuditId);\n    }\n    \n    @Override\n    public List<AppAudit> getAppAuditListByAppId(Long appId) {\n        Assert.isTrue(appId != null && appId > 0L);\n        List<AppAudit> appAudits = appAuditDao.getAppAuditByAppId(appId);\n        if (CollectionUtils.isNotEmpty(appAudits)) {\n            for (AppAudit appAudit : appAudits) {\n                Long appAuditId = appAudit.getId();\n                AppAuditLog log = appAuditLogDao.getAuditByType(appAuditId, AppAuditLogTypeEnum.APP_CHECK.value());\n                if(log != null){\n                    log.setAppUser(appUserDao.get(log.getUserId()));\n                }\n                appAudit.setAppAuditLog(log);\n            }\n        }\n        return appAudits;\n    }\n    \n    @Override\n    public AppAudit saveRegisterUserApply(AppUser appUser, AppAuditType registerUserApply) {\n        AppAudit appAudit = new AppAudit();\n        appAudit.setAppId(0);\n        appAudit.setUserId(appUser.getId());\n        appAudit.setUserName(appUser.getName());\n        appAudit.setModifyTime(new Date());\n        appAudit.setInfo(appUser.getChName() + \"申请成为Cachecloud用户, 手机:\" + appUser.getMobile() + \",邮箱:\" + appUser.getEmail());\n        appAudit.setStatus(AppCheckEnum.APP_WATING_CHECK.value());\n        appAudit.setType(registerUserApply.getValue());\n        appAuditDao.insertAppAudit(appAudit);\n        return appAudit;\n    }\n    \n    @Override\n    public List<AppDesc> getAllAppDesc() {\n        return appDao.getAllAppDescList(null);\n    }\n    \n    @Override\n    public SuccessEnum changeAppAlertConfig(long appId, int memAlertValue, int clientConnAlertValue, AppUser appUser) {\n        if (appId <= 0 || memAlertValue <= 0 || clientConnAlertValue <= 0) {\n            return SuccessEnum.FAIL;\n        }\n        AppDesc appDesc = appDao.getAppDescById(appId);\n        if (appDesc == null) {\n            return SuccessEnum.FAIL;\n        }\n        try {\n            // 修改报警阀值\n            appDesc.setMemAlertValue(memAlertValue);\n            appDesc.setClientConnAlertValue(clientConnAlertValue);\n            appDao.update(appDesc);\n            // 添加日志\n            AppAuditLog appAuditLog = AppAuditLog.generate(appDesc, appUser, 0L, AppAuditLogTypeEnum.APP_CHANGE_ALERT);\n            if (appAuditLog != null) {\n                appAuditLogDao.save(appAuditLog);\n            }\n            return SuccessEnum.SUCCESS;\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return SuccessEnum.FAIL;\n        }\n    }\n    \n    @Override\n    public void updateAppKey(long appId) {\n        appDao.updateAppKey(appId, AppKeyUtil.genSecretKey(appId));\n    }\n\n    public void setAppDao(AppDao appDao) {\n        this.appDao = appDao;\n    }\n\n    public void setAppAuditLogDao(AppAuditLogDao appAuditLogDao) {\n        this.appAuditLogDao = appAuditLogDao;\n    }\n\n    public void setAppToUserDao(AppToUserDao appToUserDao) {\n        this.appToUserDao = appToUserDao;\n    }\n\n    public void setInstanceDao(InstanceDao instanceDao) {\n        this.instanceDao = instanceDao;\n    }\n\n    public void setAppAuditDao(AppAuditDao appAuditDao) {\n        this.appAuditDao = appAuditDao;\n    }\n\n    public void setInstanceStatsDao(InstanceStatsDao instanceStatsDao) {\n        this.instanceStatsDao = instanceStatsDao;\n    }\n\n    public void setRedisCenter(RedisCenter redisCenter) {\n        this.redisCenter = redisCenter;\n    }\n\n    public void setMachineCenter(MachineCenter machineCenter) {\n        this.machineCenter = machineCenter;\n    }\n\n    public void setMachineStatsDao(MachineStatsDao machineStatsDao) {\n        this.machineStatsDao = machineStatsDao;\n    }\n\n    public void setAppUserDao(AppUserDao appUserDao) {\n        this.appUserDao = appUserDao;\n    }\n\n    \n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/service/impl/ConfigServiceImpl.java",
    "content": "package com.sohu.cache.web.service.impl;\n\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\n\nimport org.apache.commons.collections.MapUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.sohu.cache.constant.UserLoginTypeEnum;\nimport com.sohu.cache.dao.ConfigDao;\nimport com.sohu.cache.entity.SystemConfig;\nimport com.sohu.cache.util.ConstUtils;\nimport com.sohu.cache.web.enums.SuccessEnum;\nimport com.sohu.cache.web.service.ConfigService;\n\n/**\n * @author leifu\n * @Date 2016年5月23日\n * @Time 上午10:35:26\n */\npublic class ConfigServiceImpl implements ConfigService {\n\n    private Logger logger = LoggerFactory.getLogger(ConfigServiceImpl.class);\n\n    private ConfigDao configDao;\n\n    public void init() {\n        reloadSystemConfig();\n    }\n\n    /**\n     * 加载配置\n     */\n    public void reloadSystemConfig() {\n        logger.info(\"===========ConfigServiceImpl reload config start============\");\n        // 加载配置\n        Map<String, String> configMap = getConfigMap();\n\n        // 文案相关\n        ConstUtils.CONTACT = MapUtils.getString(configMap, \"cachecloud.contact\", ConstUtils.DEFAULT_CONTACT);\n        logger.info(\"{}: {}\", \"ConstUtils.CONTACT\", ConstUtils.CONTACT);\n        \n        ConstUtils.DOCUMENT_URL = MapUtils.getString(configMap, \"cachecloud.documentUrl\",\n                ConstUtils.DEFAULT_DOCUMENT_URL);\n        logger.info(\"{}: {}\", \"ConstUtils.DOCUMENT_URL\", ConstUtils.DOCUMENT_URL);\n\n        \n        ConstUtils.MAVEN_WAREHOUSE = MapUtils.getString(configMap, \"cachecloud.mavenWareHouse\",\n                ConstUtils.DEFAULT_MAVEN_WAREHOUSE);\n        logger.info(\"{}: {}\", \"ConstUtils.MAVEN_WAREHOUSE\", ConstUtils.MAVEN_WAREHOUSE);\n\n\n        // 报警相关配置\n        ConstUtils.EMAILS = MapUtils.getString(configMap, \"cachecloud.owner.email\", ConstUtils.DEFAULT_EMAILS);\n        logger.info(\"{}: {}\", \"ConstUtils.EMAILS\", ConstUtils.EMAILS);\n\n        ConstUtils.PHONES = MapUtils.getString(configMap, \"cachecloud.owner.phone\", ConstUtils.DEFAULT_PHONES);\n        logger.info(\"{}: {}\", \"ConstUtils.PHONES\", ConstUtils.PHONES);\n\n\n        // ssh相关配置\n        ConstUtils.USERNAME = MapUtils.getString(configMap, \"cachecloud.machine.ssh.name\", ConstUtils.DEFAULT_USERNAME);\n        logger.info(\"{}: {}\", \"ConstUtils.USERNAME\", ConstUtils.USERNAME);\n\n        \n        ConstUtils.PASSWORD = MapUtils.getString(configMap, \"cachecloud.machine.ssh.password\",\n                ConstUtils.DEFAULT_PASSWORD);\n        logger.info(\"{}: {}\", \"ConstUtils.PASSWORD\", ConstUtils.PASSWORD);\n\n        \n        ConstUtils.SSH_PORT_DEFAULT = Integer.parseInt(MapUtils.getString(configMap, \"cachecloud.machine.ssh.port\",\n                String.valueOf(ConstUtils.DEFAULT_SSH_PORT_DEFAULT)));\n        logger.info(\"{}: {}\", \"ConstUtils.SSH_PORT_DEFAULT\", ConstUtils.SSH_PORT_DEFAULT);\n\n\n        // 管理员相关配置\n        ConstUtils.SUPER_ADMIN_NAME = MapUtils.getString(configMap, \"cachecloud.admin.user.name\",\n                ConstUtils.DEFAULT_SUPER_ADMIN_NAME);\n        logger.info(\"{}: {}\", \"ConstUtils.SUPER_ADMIN_NAME\", ConstUtils.SUPER_ADMIN_NAME);\n\n        \n        ConstUtils.SUPER_ADMIN_PASS = MapUtils.getString(configMap, \"cachecloud.admin.user.password\",\n                ConstUtils.DEFAULT_SUPER_ADMIN_PASS);\n        logger.info(\"{}: {}\", \"ConstUtils.SUPER_ADMIN_PASS\", ConstUtils.SUPER_ADMIN_PASS);\n\n        \n        ConstUtils.SUPER_ADMINS = MapUtils.getString(configMap, \"cachecloud.superAdmin\",\n                ConstUtils.DEFAULT_SUPER_ADMINS);\n        logger.info(\"{}: {}\", \"ConstUtils.SUPER_ADMINS\", ConstUtils.SUPER_ADMINS);\n\n        \n        ConstUtils.SUPER_MANAGER = Arrays.asList(ConstUtils.SUPER_ADMINS.split(\",\"));\n        logger.info(\"{}: {}\", \"ConstUtils.SUPER_MANAGER\", ConstUtils.SUPER_MANAGER);\n\n\n        // 机器报警阀值\n        ConstUtils.CPU_USAGE_RATIO_THRESHOLD = MapUtils.getDoubleValue(configMap, \"machine.cpu.alert.ratio\",\n                ConstUtils.DEFAULT_CPU_USAGE_RATIO_THRESHOLD);\n        logger.info(\"{}: {}\", \"ConstUtils.CPU_USAGE_RATIO_THRESHOLD\", ConstUtils.CPU_USAGE_RATIO_THRESHOLD);\n\n        ConstUtils.MEMORY_USAGE_RATIO_THRESHOLD = MapUtils.getDoubleValue(configMap, \"machine.mem.alert.ratio\",\n                ConstUtils.DEFAULT_MEMORY_USAGE_RATIO_THRESHOLD);\n        logger.info(\"{}: {}\", \"ConstUtils.MEMORY_USAGE_RATIO_THRESHOLD\", ConstUtils.MEMORY_USAGE_RATIO_THRESHOLD);\n        \n        ConstUtils.LOAD_THRESHOLD = MapUtils.getDoubleValue(configMap, \"machine.load.alert.ratio\",\n                ConstUtils.DEFAULT_LOAD_THRESHOLD);\n        logger.info(\"{}: {}\", \"ConstUtils.LOAD_THRESHOLD\", ConstUtils.LOAD_THRESHOLD);\n\n        \n\n        // 客户端版本\n        ConstUtils.GOOD_CLIENT_VERSIONS = MapUtils.getString(configMap, \"cachecloud.good.client\",\n                ConstUtils.DEFAULT_GOOD_CLIENT_VERSIONS);\n        logger.info(\"{}: {}\", \"ConstUtils.GOOD_CLIENT_VERSIONS\", ConstUtils.GOOD_CLIENT_VERSIONS);\n        \n        ConstUtils.WARN_CLIENT_VERSIONS = MapUtils.getString(configMap, \"cachecloud.warn.client\",\n                ConstUtils.DEFAULT_WARN_CLIENT_VERSIONS);\n        logger.info(\"{}: {}\", \"ConstUtils.WARN_CLIENT_VERSIONS\", ConstUtils.WARN_CLIENT_VERSIONS);\n\n        ConstUtils.ERROR_CLIENT_VERSIONS = MapUtils.getString(configMap, \"cachecloud.error.client\",\n                ConstUtils.DEFAULT_ERROR_CLIENT_VERSIONS);\n        logger.info(\"{}: {}\", \"ConstUtils.ERROR_CLIENT_VERSIONS\", ConstUtils.ERROR_CLIENT_VERSIONS);\n\n        //redis-migrate-tool安装路径\n        ConstUtils.REDIS_MIGRATE_TOOL_HOME = MapUtils.getString(configMap, \"redis.migrate.tool.home\",\n                ConstUtils.DEFAULT_REDIS_MIGRATE_TOOL_HOME);\n        logger.info(\"{}: {}\", \"ConstUtils.REDIS_MIGRATE_TOOL_HOME\", ConstUtils.REDIS_MIGRATE_TOOL_HOME);\n        \n        //用户登录状态方式\n        ConstUtils.USER_LOGIN_TYPE = MapUtils.getIntValue(configMap, \"cachecloud.user.login.type\", ConstUtils.DEFAULT_USER_LOGIN_TYPE);\n        UserLoginTypeEnum userLoginTypeEnum = UserLoginTypeEnum.getLoginTypeEnum(ConstUtils.USER_LOGIN_TYPE);\n        logger.info(\"{}: {}, {}\", \"ConstUtils.USER_LOGIN_TYPE\", userLoginTypeEnum.getType(), userLoginTypeEnum.getDesc());\n        \n        //cookie登录方式所需要的domain\n        ConstUtils.COOKIE_DOMAIN = MapUtils.getString(configMap, \"cachecloud.cookie.domain\", ConstUtils.DEFAULT_COOKIE_DOMAIN);\n        logger.info(\"{}: {}\", \"ConstUtils.COOKIE_DOMAIN\", ConstUtils.COOKIE_DOMAIN);\n        \n        //cachecloud根目录\n        ConstUtils.CACHECLOUD_BASE_DIR = MapUtils.getString(configMap, \"cachecloud.base.dir\", ConstUtils.DEFAULT_CACHECLOUD_BASE_DIR);\n        logger.info(\"{}: {}\", \"ConstUtils.CACHECLOUD_BASE_DIR\", ConstUtils.CACHECLOUD_BASE_DIR);\n        \n        //应用客户端连接报警阀值\n        ConstUtils.APP_CLIENT_CONN_THRESHOLD = MapUtils.getIntValue(configMap, \"cachecloud.app.client.conn.threshold\", ConstUtils.DEFAULT_APP_CLIENT_CONN_THRESHOLD);\n        logger.info(\"{}: {}\", \"ConstUtils.APP_CLIENT_CONN_THRESHOLD\", ConstUtils.APP_CLIENT_CONN_THRESHOLD);\n        \n        //邮件报警接口\n        ConstUtils.EMAIL_ALERT_INTERFACE = MapUtils.getString(configMap, \"cachecloud.email.alert.interface\", ConstUtils.DEFAULT_EMAIL_ALERT_INTERFACE);\n        logger.info(\"{}: {}\", \"ConstUtils.EMAIL_ALERT_INTERFACE\", ConstUtils.EMAIL_ALERT_INTERFACE);\n        \n        //短信报警接口\n        ConstUtils.MOBILE_ALERT_INTERFACE = MapUtils.getString(configMap, \"cachecloud.mobile.alert.interface\", ConstUtils.DEFAULT_MOBILE_ALERT_INTERFACE);\n        logger.info(\"{}: {}\", \"ConstUtils.MOBILE_ALERT_INTERFACE\", ConstUtils.MOBILE_ALERT_INTERFACE);\n        \n        //LDAP登录地址\n        ConstUtils.LDAP_URL = MapUtils.getString(configMap, \"cachecloud.ldap.url\", ConstUtils.DEFAULT_LDAP_URL);\n        logger.info(\"{}: {}\", \"ConstUtils.LDAP_URL\", ConstUtils.LDAP_URL);\n        \n        //是否定期清理各种统计数据(详见CleanUpStatisticsJob)\n        ConstUtils.WHETHER_SCHEDULE_CLEAN_DATA = MapUtils.getBooleanValue(configMap, \"cachecloud.whether.schedule.clean.data\", ConstUtils.DEFAULT_WHETHER_SCHEDULE_CLEAN_DATA);\n        logger.info(\"{}: {}\", \"ConstUtils.WHETHER_SCHEDULE_CLEAN_DATA\", ConstUtils.WHETHER_SCHEDULE_CLEAN_DATA);\n        \n        // app secret key\n        ConstUtils.APP_SECRET_BASE_KEY = MapUtils.getString(configMap, \"cachecloud.app.secret.base.key\", ConstUtils.DEFAULT_APP_SECRET_BASE_KEY);\n        logger.info(\"{}: {}\", \"ConstUtils.APP_SECRET_KEY\", ConstUtils.APP_SECRET_BASE_KEY);\n        \n        // 机器性能统计周期(分钟)\n        ConstUtils.MACHINE_STATS_CRON_MINUTE = MapUtils.getIntValue(configMap, \"cachecloud.machine.stats.cron.minute\", ConstUtils.DEFAULT_MACHINE_STATS_CRON_MINUTE);\n        logger.info(\"{}: {}\", \"ConstUtils.MACHINE_STATS_CRON_MINUTE\", ConstUtils.MACHINE_STATS_CRON_MINUTE);\n        \n        \n        logger.info(\"===========ConfigServiceImpl reload config end============\");\n    }\n    \n    @Override\n    public SuccessEnum updateConfig(Map<String, String> configMap) {\n        for (Entry<String, String> entry : configMap.entrySet()) {\n            String configKey = entry.getKey();\n            String configValue = entry.getValue();\n            try {\n                configDao.update(configKey, configValue);\n            } catch (Exception e) {\n                logger.error(\"key {} value {} update faily\" + e.getMessage(), configKey, configValue, e);\n                return SuccessEnum.FAIL;\n            }\n        }\n        return SuccessEnum.SUCCESS;\n    }\n\n    @Override\n    public List<SystemConfig> getConfigList(int status) {\n        try {\n            return configDao.getConfigList(status);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return Collections.emptyList();\n        }\n    }\n\n    /**\n     * 获取所有配置的key-value\n     * \n     * @return\n     */\n    private Map<String, String> getConfigMap() {\n        Map<String, String> configMap = new LinkedHashMap<String, String>();\n        List<SystemConfig> systemConfigList = getConfigList(1);\n        for (SystemConfig systemConfig : systemConfigList) {\n            configMap.put(systemConfig.getConfigKey(), systemConfig.getConfigValue());\n        }\n        return configMap;\n    }\n\n    public void setConfigDao(ConfigDao configDao) {\n        this.configDao = configDao;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/service/impl/MemFaultServiceImpl.java",
    "content": "package com.sohu.cache.web.service.impl;\n\nimport java.util.List;\n\nimport com.sohu.cache.dao.MemFaultDao;\nimport com.sohu.cache.entity.InstanceFault;\nimport com.sohu.cache.web.service.MemFaultService;\n\n/**\n * 故障服务\n * @author leifu\n * @Date 2015-6-6\n * @Time 下午10:03:59\n */\npublic class MemFaultServiceImpl implements MemFaultService {\n\n    /**\n     * 故障Dao\n     */\n    private MemFaultDao memFaultDao;\n\n    @Override\n    public List<InstanceFault> getFaultList() {\n        return memFaultDao.getMemFaultList();\n    }\n\n    public void setMemFaultDao(MemFaultDao memFaultDao) {\n        this.memFaultDao = memFaultDao;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/service/impl/ServerDataServiceImpl.java",
    "content": "package com.sohu.cache.web.service.impl;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.sohu.cache.dao.ServerStatusDao;\nimport com.sohu.cache.entity.ServerInfo;\nimport com.sohu.cache.entity.ServerStatus;\nimport com.sohu.cache.server.data.Server;\nimport com.sohu.cache.web.service.ServerDataService;\n\npublic class ServerDataServiceImpl implements ServerDataService {\n\tprivate static final Logger logger = LoggerFactory.getLogger(ServerDataServiceImpl.class);\n\t//持久化接口\n\tprivate ServerStatusDao serverStatusDao;\n\t\n\t@Override\n\tpublic ServerInfo queryServerInfo(String ip) {\n\t\ttry {\n\t\t\treturn serverStatusDao.queryServerInfo(ip);\n\t\t} catch (Exception e) {\n\t\t\tlogger.error(\"query err:\"+ip, e);\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void saveServerInfo(String ip, String dist) {\n\t\tif(dist == null) {\n\t\t\treturn;\n\t\t}\n\t\tdist = dist.trim();\n\t\tif(dist.length() == 0) {\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tserverStatusDao.saveServerInfo(ip, dist);\n\t\t} catch (Exception e) {\n\t\t\tlogger.error(\"saveServerInfo err:\"+ip+\" dist=\"+dist, e);\n\t\t}\n\t}\n\n\tpublic Integer saveAndUpdateServerInfo(Server server) {\n\t\tif(server.getHost() == null || server.getNmon() == null || server.getCpus() == 0 || \n\t\t   server.getCpuModel() == null || server.getKernel() == null || server.getUlimit() == null) {\n\t\t\treturn null;\n\t\t}\n\t\ttry {\n\t\t\treturn serverStatusDao.saveAndUpdateServerInfo(server);\n\t\t} catch (Exception e) {\n\t\t\tlogger.error(\"saveAndUpdateServerInfo err server=\"+server, e);\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic List<ServerStatus> queryServerStatus(String ip, String date) {\n\t\ttry {\n\t\t\treturn serverStatusDao.queryServerStatus(ip, date);\n\t\t} catch (Exception e) {\n\t\t\tlogger.error(\"queryServerStatus err ip=\"+ip+\" date=\"+date, e);\n\t\t}\n\t\treturn new ArrayList<ServerStatus>(0);\n\t}\n\n\t@Override\n\tpublic List<ServerStatus> queryServerOverview(String ip, String date) {\n\t\ttry {\n\t\t\treturn serverStatusDao.queryServerOverview(ip, date);\n\t\t} catch (Exception e) {\n\t\t\tlogger.error(\"queryServerOverview err ip=\"+ip+\" date=\"+date, e);\n\t\t}\n\t\treturn new ArrayList<ServerStatus>(0);\n\t}\n\n\t@Override\n\tpublic List<ServerStatus> queryServerCpu(String ip, String date) {\n\t\ttry {\n\t\t\treturn serverStatusDao.queryServerCpu(ip, date);\n\t\t} catch (Exception e) {\n\t\t\tlogger.error(\"queryServerCpu err ip=\"+ip+\" date=\"+date, e);\n\t\t}\n\t\treturn new ArrayList<ServerStatus>(0);\n\t}\n\n\t@Override\n\tpublic List<ServerStatus> queryServerNet(String ip, String date) {\n\t\ttry {\n\t\t\treturn serverStatusDao.queryServerNet(ip, date);\n\t\t} catch (Exception e) {\n\t\t\tlogger.error(\"queryServerNet err ip=\"+ip+\" date=\"+date, e);\n\t\t}\n\t\treturn new ArrayList<ServerStatus>(0);\n\t}\n\n\t@Override\n\tpublic List<ServerStatus> queryServerDisk(String ip, String date) {\n\t\ttry {\n\t\t\treturn serverStatusDao.queryServerDisk(ip, date);\n\t\t} catch (Exception e) {\n\t\t\tlogger.error(\"queryServerDisk err ip=\"+ip+\" date=\"+date, e);\n\t\t}\n\t\treturn new ArrayList<ServerStatus>(0);\n\t}\n\n\t@Override\n\tpublic void saveServerStat(Server server) {\n\t\tif(server == null || server.getDateTime() == null) {\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tserverStatusDao.saveServerStat(server);\n\t\t} catch (Exception e) {\n\t\t\tlogger.error(\"saveServerStat err server=\"+server, e);\n\t\t}\n\t}\n\n\tpublic void setServerStatusDao(ServerStatusDao serverStatusDao) {\n\t\tthis.serverStatusDao = serverStatusDao;\n\t}\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/service/impl/UserLoginStatusCookieServiceImpl.java",
    "content": "package com.sohu.cache.web.service.impl;\n\nimport javax.servlet.http.Cookie;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\nimport org.apache.commons.lang.math.NumberUtils;\n\nimport com.sohu.cache.util.ConstUtils;\nimport com.sohu.cache.web.service.UserLoginStatusService;\n\n/**\n * cookie保护登录状态\n * @author leifu\n * @Date 2016年6月15日\n * @Time 下午1:31:17\n */\npublic class UserLoginStatusCookieServiceImpl implements UserLoginStatusService {\n\n    @Override\n    public long getUserIdFromLoginStatus(HttpServletRequest request) {\n        Cookie[] cookies = request.getCookies();\n        String cookiesId = null;\n        if (cookies != null) {\n            for (Cookie cookie : cookies) {\n                if (LOGIN_USER_STATUS_NAME.equals(cookie.getName())) {\n                    cookiesId = cookie.getValue();\n                }\n            }\n        }\n        return NumberUtils.toLong(cookiesId, -1);\n    }\n\n    @Override\n    public void addLoginStatus(HttpServletRequest request, HttpServletResponse response, String userId) {\n        Cookie cookie = new Cookie(LOGIN_USER_STATUS_NAME, userId);\n        cookie.setDomain(ConstUtils.COOKIE_DOMAIN);\n        cookie.setPath(\"/\");\n        cookie.setMaxAge(-1);\n        response.addCookie(cookie);\n    }\n\n    @Override\n    public void removeLoginStatus(HttpServletRequest request, HttpServletResponse response) {\n        addLoginStatus(request, response, \"\");\n    }\n\n    \n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/service/impl/UserLoginStatusSessionServiceImpl.java",
    "content": "package com.sohu.cache.web.service.impl;\n\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport javax.servlet.http.HttpSession;\n\nimport org.apache.commons.lang.math.NumberUtils;\n\nimport com.sohu.cache.web.service.UserLoginStatusService;\n\n\n/**\n * session保护登录状态\n * @author leifu\n * @Date 2016年6月15日\n * @Time 下午1:31:05\n */\npublic class UserLoginStatusSessionServiceImpl implements UserLoginStatusService {\n\n    @Override\n    public long getUserIdFromLoginStatus(HttpServletRequest request) {\n        HttpSession session = request.getSession(true);\n        Object object = session.getAttribute(LOGIN_USER_STATUS_NAME);\n        return object == null ? -1 : NumberUtils.toLong(object.toString());\n    }\n\n    @Override\n    public void addLoginStatus(HttpServletRequest request, HttpServletResponse response, String userId) {\n        request.getSession().setAttribute(LOGIN_USER_STATUS_NAME, userId);\n    }\n\n    @Override\n    public void removeLoginStatus(HttpServletRequest request, HttpServletResponse response) {\n        request.getSession().removeAttribute(LOGIN_USER_STATUS_NAME);\n    }\n\n    \n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/service/impl/UserServiceImpl.java",
    "content": "package com.sohu.cache.web.service.impl;\n\nimport java.util.*;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.sohu.cache.dao.AppToUserDao;\nimport com.sohu.cache.dao.AppUserDao;\nimport com.sohu.cache.entity.AppToUser;\nimport com.sohu.cache.entity.AppUser;\nimport com.sohu.cache.web.enums.SuccessEnum;\nimport com.sohu.cache.web.service.UserService;\n\n/**\n * 用户管理实现\n * @author leifu\n * @Date 2014年10月27日\n * @Time 上午9:57:43\n */\npublic class UserServiceImpl implements UserService {\n    private Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);\n\n    /**\n     * 用户dao\n     */\n    private AppUserDao appUserDao;\n\n    /**\n     * 用户应用关系dao\n     */\n    private AppToUserDao appToUserDao;\n\n    @Override\n    public AppUser get(Long userId) {\n        return appUserDao.get(userId);\n    }\n\n    @Override\n    public List<AppUser> getUserList(String chName) {\n        return appUserDao.getUserList(chName);\n    }\n\n    @Override\n    public List<AppUser> getByAppId(Long appId) {\n        if (appId == null || appId < 0) {\n            return Collections.emptyList();\n        }\n        List<AppUser> resultList = new ArrayList<AppUser>();\n        List<AppToUser> appToUsers = appToUserDao.getByAppId(appId);\n        if (appToUsers != null && appToUsers.size() > 0) {\n            for (AppToUser appToUser : appToUsers) {\n                Long userId = appToUser.getUserId();\n                if (userId == null) {\n                    continue;\n                }\n                AppUser user = appUserDao.get(userId);\n                if (user == null) {\n                    continue;\n                }\n                resultList.add(user);\n            }\n        }\n        return resultList;\n    }\n\n    @Override\n    public AppUser getByName(String name) {\n        try {\n            return appUserDao.getByName(name);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return null;\n        }\n    }\n\n    @Override\n    public SuccessEnum save(AppUser appUser) {\n        try {\n            appUserDao.save(appUser);\n            return SuccessEnum.SUCCESS;\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return SuccessEnum.FAIL;\n        }\n    }\n\n    @Override\n    public SuccessEnum update(AppUser appUser) {\n        try {\n            appUserDao.update(appUser);\n            return SuccessEnum.SUCCESS;\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return SuccessEnum.FAIL;\n        }\n    }\n\n    @Override\n    public SuccessEnum delete(Long userId) {\n        try {\n            appUserDao.delete(userId);\n            return SuccessEnum.SUCCESS;\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n            return SuccessEnum.FAIL;\n        }\n    }\n\n    public void setAppUserDao(AppUserDao appUserDao) {\n        this.appUserDao = appUserDao;\n    }\n\n    public void setAppToUserDao(AppToUserDao appToUserDao) {\n        this.appToUserDao = appToUserDao;\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/util/AppEmailUtil.java",
    "content": "package com.sohu.cache.web.util;\n\nimport com.sohu.cache.constant.AppAuditType;\nimport com.sohu.cache.constant.AppCheckEnum;\nimport com.sohu.cache.constant.RedisConfigTemplateChangeEnum;\nimport com.sohu.cache.entity.AppAudit;\nimport com.sohu.cache.entity.AppDailyData;\nimport com.sohu.cache.entity.AppDesc;\nimport com.sohu.cache.entity.AppUser;\nimport com.sohu.cache.entity.InstanceAlertValueResult;\nimport com.sohu.cache.entity.InstanceConfig;\nimport com.sohu.cache.stats.app.AppStatsCenter;\nimport com.sohu.cache.util.ConstUtils;\nimport com.sohu.cache.web.component.EmailComponent;\nimport com.sohu.cache.web.enums.SuccessEnum;\nimport com.sohu.cache.web.service.UserService;\nimport com.sohu.cache.web.vo.AppDetailVO;\n\nimport org.apache.commons.collections.CollectionUtils;\nimport org.apache.commons.collections.MapUtils;\nimport org.apache.commons.lang.StringUtils;\nimport org.apache.log4j.Logger;\nimport org.apache.velocity.app.VelocityEngine;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.LinkedHashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.Set;\n\n/**\n * 邮件通知应用的申请流程(方法内是具体的文案)\n *\n * @author leifu\n * @Time 2014年10月16日\n */\npublic class AppEmailUtil {\n\n    private EmailComponent emailComponent;\n\n    private UserService userService;\n\n    private VelocityEngine velocityEngine;\n    \n    private AppStatsCenter appStatsCenter;\n    \n    private Logger logger = Logger.getLogger(AppEmailUtil.class);\n\n    \n    /**\n     * 应用状态通知\n     * @param appDesc\n     * @param appAudit\n     */\n    public void noticeAppResult(AppDesc appDesc, AppAudit appAudit) {\n        List<String> ccEmailList = getCCEmailList(appDesc, appAudit);\n        String mailContent = VelocityUtils.createText(velocityEngine, appDesc, appAudit, new AppDailyData(), new ArrayList<InstanceAlertValueResult>(), \"appAudit.vm\", \"UTF-8\");\n        AppUser appUser = userService.get(appDesc.getUserId());\n        emailComponent.sendMail(\"【CacheCloud】状态通知\", mailContent, Arrays.asList(appUser.getEmail()), ccEmailList);\n    }\n    \n    /**\n     * 重要应用抄送\n     * @param appDesc\n     * @param appAudit\n     * @return\n     */\n    private List<String> getCCEmailList(AppDesc appDesc, AppAudit appAudit) {\n        Set<String> ccEmailSet = new LinkedHashSet<String>();\n        for (String email : emailComponent.getAdminEmail().split(ConstUtils.COMMA)) {\n            ccEmailSet.add(email);\n        }\n        //S级别，且是开通邮件\n        if (appDesc.isSuperImportant() && AppAuditType.APP_AUDIT.getValue() == appAudit.getType()) {\n            ccEmailSet.addAll(ConstUtils.LEADER_EMAIL_LIST);\n        }\n        return new ArrayList<String>(ccEmailSet);\n    }\n\n    /**\n     * 贡献者通知\n     * @param groupName\n     * @param applyReason\n     * @param appUser\n     */\n    public void noticeBecomeContributor(String groupName, String applyReason, AppUser appUser) {\n        StringBuffer mailContent = new StringBuffer();\n        mailContent.append(appUser.getChName() + \"(项目组:\"+groupName+\")申请成为CacheCloud贡献者<br/>\");\n        mailContent.append(\"申请理由:<br/>\" + applyReason);\n        emailComponent.sendMail(\"【CacheCloud】状态通知\", mailContent.toString(), Arrays.asList(appUser.getEmail()), Arrays.asList(emailComponent.getAdminEmail().split(ConstUtils.COMMA)));\n    }\n    \n    /**\n     * 注册用户通知\n     * @param appUser\n     * @param appAudit\n     */\n    public void noticeUserResult(AppUser appUser, AppAudit appAudit) {\n        if(appAudit == null){\n            return;\n        }\n        StringBuffer mailContent = new StringBuffer();\n        if (AppCheckEnum.APP_WATING_CHECK.value().equals(appAudit.getStatus())) {\n            mailContent.append(appUser.getChName() + \"申请想成为CacheCloud用户，请管理员帮忙处理！<br/>\");\n        } else if (AppCheckEnum.APP_PASS.value().equals(appAudit.getStatus())) {\n            mailContent.append(\"您的用户申请已经审批通过，您可以登录正常Cachecloud了！<br/>\");\n        } else if (AppCheckEnum.APP_REJECT.value().equals(appAudit.getStatus())) {\n            mailContent.append(\"您的用户申请被驳回，原因是: \" + appAudit.getRefuseReason());\n        }\n        emailComponent.sendMail(\"【CacheCloud】状态通知\", mailContent.toString(), Arrays.asList(appUser.getEmail()), Arrays.asList(emailComponent.getAdminEmail().split(ConstUtils.COMMA)));\n    }\n    \n    /**\n     * 下线应用通知\n     * @param appUser\n     * @param appId\n     * @param isSuccess\n     */\n    public void noticeOfflineApp(AppUser appUser, Long appId, boolean isSuccess) {\n        AppDetailVO appDetailVO = appStatsCenter.getAppDetail(appId);\n        StringBuilder mailContent = new StringBuilder();\n        mailContent.append(appUser.getChName()).append(\",对应用appid=\").append(appId);\n        mailContent.append(\"进行下线,操作结果是\").append(isSuccess?\"成功\":\"失败\");\n        mailContent.append(\",请知晓!\");\n        emailComponent.sendMail(\"【CacheCloud】状态通知\", mailContent.toString(), appDetailVO.getEmailList(), Arrays.asList(emailComponent.getAdminEmail().split(ConstUtils.COMMA)));\n    }\n    \n    public void sendRedisConfigTemplateChangeEmail(AppUser appUser, InstanceConfig instanceConfig,\n            SuccessEnum successEnum, RedisConfigTemplateChangeEnum redisConfigTemplateChangeEnum) {\n        String mailTitle = \"【CacheCloud】-Redis配置模板修改通知\";\n        String mailContent = String.format(\"%s 对Redis配置模板 进行了%s,操作结果是%s,具体为(key=%s,value=%s,状态为%s)\",\n                appUser.getChName(),\n                redisConfigTemplateChangeEnum.getInfo(), successEnum.info(), instanceConfig.getConfigKey(),\n                instanceConfig.getConfigValue(), instanceConfig.getStatusDesc());\n        emailComponent.sendMail(mailTitle, mailContent.toString(), Arrays.asList(emailComponent.getAdminEmail().split(ConstUtils.COMMA)));\n        \n    }\n    \n    public void sendSystemConfigDifEmail(AppUser appUser, Map<String, String> systemDifConfigMap,\n            SuccessEnum successEnum) {\n        if (MapUtils.isEmpty(systemDifConfigMap)) {\n            return;\n        }\n        String mailTitle = \"【CacheCloud】-系统配置修改通知\";\n        StringBuffer mailContent = new StringBuffer();\n        mailContent.append(appUser.getChName() + \"修改了系统配置，修改结果:\" + successEnum.info() + \"<br/>\");\n        mailContent.append(\"具体配置如下:<br/>\");\n        for(Entry<String, String> entry : systemDifConfigMap.entrySet()) {\n            mailContent.append(entry.getKey() + \"-->\" + entry.getValue() + \"<br/>\");\n        }\n        emailComponent.sendMail(mailTitle, mailContent.toString(), Arrays.asList(emailComponent.getAdminEmail().split(ConstUtils.COMMA)));\n    }\n    \n    /**\n     * 系统通知\n     * @param noticeContent\n     * @return\n     */\n    public boolean noticeAllUser(String noticeContent) {\n        if (StringUtils.isBlank(noticeContent)) {\n            return false;\n        }\n        try {\n            String mailTitle = \"【CacheCloud】-系统通知\";\n            StringBuffer mailContent = new StringBuffer();\n            String[] noticeArray = noticeContent.split(ConstUtils.NEXT_LINE);\n            for(String noticeLine : noticeArray) {\n                mailContent.append(noticeLine).append(\"<br/>\");\n            }\n            List<String> emailList = new ArrayList<String>();\n            List<AppUser> appUserList = userService.getUserList(null);\n            if (CollectionUtils.isEmpty(appUserList)) {\n                return false;\n            }\n            for (AppUser appUser: appUserList) {\n                String email = appUser.getEmail();\n                if (StringUtils.isBlank(email)) {\n                    continue;\n                }\n                emailList.add(email);\n            }\n            return emailComponent.sendMail(mailTitle, mailContent.toString(), emailList, Arrays.asList(emailComponent.getAdminEmail().split(ConstUtils.COMMA))); \n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n        return false;\n    }\n\n    public void setEmailComponent(EmailComponent emailComponent) {\n        this.emailComponent = emailComponent;\n    }\n\n    public void setUserService(UserService userService) {\n        this.userService = userService;\n    }\n\n    public void setVelocityEngine(VelocityEngine velocityEngine) {\n        this.velocityEngine = velocityEngine;\n    }\n\n    public void setAppStatsCenter(AppStatsCenter appStatsCenter) {\n        this.appStatsCenter = appStatsCenter;\n    }\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/util/DateUtil.java",
    "content": "package com.sohu.cache.web.util;\n\nimport java.text.ParseException;\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * @author leifu\n * @Time 2014年8月31日\n */\npublic class DateUtil {\n    private final static Logger logger = LoggerFactory.getLogger(DateUtil.class);\n    \n    /*\n     * yyyyMMddHHmm格式format\n     */\n    public static String formatYYYYMMddHHMM(Date date) {\n        SimpleDateFormat sdf = new SimpleDateFormat(\"yyyyMMddHHmm\");\n        return sdf.format(date);\n    }\n\n    /*\n     * yyyy-MM-dd HH:mm:ss格式format\n     */\n    public static String formatYYYYMMddHHMMSS(Date date) {\n        if(date == null){\n            return null;\n        }\n        SimpleDateFormat sdf = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n        return sdf.format(date);\n    }\n\n    /*\n     * yyyyMMddHHmm格式parse\n     */\n    public static Date parse(String dateStr, String format) throws ParseException {\n        SimpleDateFormat sdf = new SimpleDateFormat(format);\n        return sdf.parse(dateStr);\n    }\n    \n    /*\n     * yyyyMMddHHmm格式parse\n     */\n    public static Date parseYYYYMMddHHMM(String dateStr) throws ParseException {\n        return parse(dateStr, \"yyyyMMddHHmm\");\n    }\n\n    /**\n     * yyyyMMddHH格式parse\n     *\n     * @throws ParseException\n     */\n    public static Date parseYYYYMMddHH(String dateStr) throws ParseException {\n        return parse(dateStr, \"yyyyMMddHH\");\n    }\n\n\n    /*\n     * yyyy-MM-dd格式parse\n     */\n    public static Date parseYYYY_MM_dd(String dateStr) throws ParseException {\n        return parse(dateStr, \"yyyy-MM-dd\");\n    }\n\n    /**\n     * yyyyMMdd格式parse\n     */\n    public static Date parseYYYYMMdd(String dateStr) throws ParseException {\n        return parse(dateStr, \"yyyyMMdd\");\n    }\n\n\n    public static Date getDateByFormat(String date, String format) {\n        SimpleDateFormat sf = new SimpleDateFormat(format);\n        Date result = null;\n        try {\n            result = sf.parse(date);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n        return result;\n    }\n\n    public static String formatDate(Date date, String format) {\n        SimpleDateFormat sf = new SimpleDateFormat(format);\n        return sf.format(date);\n    }\n\n\n    public static String formatYYYYMMdd(Date date) {\n        SimpleDateFormat sf = new SimpleDateFormat(\"yyyyMMdd\");\n        return sf.format(date);\n    }\n\n    public static String formatHHMM(Date date) {\n        SimpleDateFormat sf = new SimpleDateFormat(\"HHmm\");\n        return sf.format(date);\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/util/IpUtil.java",
    "content": "package com.sohu.cache.web.util;\n\nimport javax.servlet.http.HttpServletRequest;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * ip工具\n * \n * @author leifu\n * @Date 2015年2月2日\n * @Time 上午10:16:29\n */\npublic class IpUtil {\n    public static Logger logger = LoggerFactory.getLogger(IpUtil.class);\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        }\n        return ip;\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/util/Page.java",
    "content": "package com.sohu.cache.web.util;\n\n/**\n * 分页对象\n * @author leifu\n * @Date 2015年2月10日\n * @Time 下午6:38:18\n */\npublic class Page implements java.io.Serializable {\n    private static final long serialVersionUID = 7887139614696114877L;\n    \n\n    /**\n     * 当前页数\n     */\n    private int pageNo;\n    \n    /**\n     * 每页的记录数\n     */\n    private int pageSize;\n    \n    /**\n     * 总记录数\n     */\n    private int totalCount;\n    \n    public Page(int pageNo, int pageSize, int totalCount) {\n        this.pageNo = pageNo;\n        this.pageSize = pageSize;\n        this.totalCount = totalCount;\n    }\n\n    /**\n     * 取总页数\n     */\n    public int getTotalPages() {\n        if (totalCount % pageSize == 0)\n            return totalCount / pageSize;\n        else\n            return totalCount / pageSize + 1;\n    }\n\n    /**\n     * 获取任一页第一条数据的位置,startIndex从0开始\n     */\n    public int getStart() {\n        return (pageNo - 1) * pageSize;\n    }\n    \n    public int getNumberOfPages() {\n        int totalPageCount = getTotalPages();\n        return totalPageCount >= 10 ? 10 : totalPageCount;\n    }\n\n    public int getPageNo() {\n        return pageNo;\n    }\n\n    public void setPageNo(int pageNo) {\n        this.pageNo = pageNo;\n    }\n\n    public int getPageSize() {\n        return pageSize;\n    }\n\n    public void setPageSize(int pageSize) {\n        this.pageSize = pageSize;\n    }\n\n    public int getTotalCount() {\n        return totalCount;\n    }\n\n    public void setTotalCount(int totalCount) {\n        this.totalCount = totalCount;\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/util/SimpleFileUtil.java",
    "content": "package com.sohu.cache.web.util;\n\nimport java.io.BufferedReader;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.sohu.cache.web.controller.AppController;\n\n/**\n * 简单文件读取\n * @author leifu\n * @Date 2015年3月2日\n * @Time 下午2:12:15\n */\npublic class SimpleFileUtil {\n    private static final Logger logger = LoggerFactory.getLogger(SimpleFileUtil.class);\n\n    /**\n     * 从class环境读取文件成List<String>\n     * @param fileName\n     * @return\n     */\n    public static List<String> getListFromFile(String fileName, String encoding) {\n        List<String> list = new ArrayList<String>();\n\n        InputStream is = null;\n        BufferedReader br = null;\n        try {\n            is = AppController.class.getClassLoader().getResourceAsStream(fileName);\n            br = new BufferedReader(new InputStreamReader(is, encoding));\n            String line = null;\n            while ((line = br.readLine()) != null) {\n                list.add(line);\n            }\n        } catch (IOException e) {\n            logger.error(e.getMessage(), e);\n        } finally {\n            if (is != null) {\n                try {\n                    is.close();\n                } catch (IOException e) {\n                    logger.error(e.getMessage(), e);\n                }\n            }\n            if (br != null) {\n                try {\n                    br.close();\n                } catch (IOException e) {\n                    logger.error(e.getMessage(), e);\n                }\n            }\n        }\n        return list;\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/util/VelocityUtils.java",
    "content": "/**\n * Copyright (c) 2013 Sohu. All Rights Reserved\n */\npackage com.sohu.cache.web.util;\n\nimport com.sohu.cache.entity.AppAudit;\nimport com.sohu.cache.entity.AppDailyData;\nimport com.sohu.cache.entity.AppDesc;\nimport com.sohu.cache.entity.InstanceAlertValueResult;\nimport com.sohu.cache.util.ConstUtils;\n\nimport org.apache.commons.lang.StringUtils;\nimport org.apache.velocity.Template;\nimport org.apache.velocity.VelocityContext;\nimport org.apache.velocity.app.Velocity;\nimport org.apache.velocity.app.VelocityEngine;\nimport org.apache.velocity.exception.MethodInvocationException;\nimport org.apache.velocity.exception.ParseErrorException;\nimport org.apache.velocity.exception.ResourceNotFoundException;\nimport org.apache.velocity.tools.generic.NumberTool;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.core.io.ClassPathResource;\n\nimport java.io.FileOutputStream;\nimport java.io.IOException;\nimport java.io.StringWriter;\nimport java.text.DecimalFormat;\nimport java.util.List;\nimport java.util.Properties;\n\n\npublic class VelocityUtils {\n\n    public static String charset = \"UTF-8\";\n    public static int lineBreakPos = -1;\n    public static boolean munge = true;\n    public static boolean verbose = false;\n    public static boolean preserveAllSemiColons = false;\n    public static boolean disableOptimizations = true;\n\n    protected static final Logger logger = LoggerFactory.getLogger(VelocityUtils.class);\n\n    /**\n     * 邮件模板\n     *\n     * @param appDesc       应用信息\n     * @param appAudit      处理信息\n     * @param templatePath  模板路径\n     * @param customCharset 编码\n     */\n    public synchronized static String createText(VelocityEngine engine, AppDesc appDesc, AppAudit appAudit, AppDailyData appDailyData, \n            List<InstanceAlertValueResult> instanceAlertValueResultList, String templatePath, String customCharset) {\n        if (!StringUtils.isEmpty(customCharset)) {\n            charset = customCharset;\n        }\n        Properties p = new Properties();\n        p.setProperty(\"file.resource.loader.path\", Thread.currentThread().getContextClassLoader().getResource(\"\").getPath());\n        p.setProperty(Velocity.ENCODING_DEFAULT, \"UTF-8\");\n        p.setProperty(Velocity.INPUT_ENCODING, \"UTF-8\");\n        p.setProperty(Velocity.OUTPUT_ENCODING, \"UTF-8\");\n        Velocity.init(p);\n\n        logger.info(\"velocity: init done.\");\n        VelocityContext context = new VelocityContext();\n        context.put(\"appDesc\", appDesc);\n        context.put(\"appAudit\", appAudit);\n        context.put(\"appDailyData\", appDailyData);\n        context.put(\"instanceAlertValueResultList\", instanceAlertValueResultList);\n        context.put(\"numberTool\", new NumberTool());\n        context.put(\"ccDomain\", ConstUtils.CC_DOMAIN);\n        context.put(\"decimalFormat\", new DecimalFormat(\"###,###\"));\n        context.put(\"StringUtils\", StringUtils.class);\n        FileOutputStream fos = null;\n        StringWriter writer = null;\n        try {\n            Template template = engine.getTemplate(templatePath);\n            writer = new StringWriter();\n            template.merge(context, writer);\n        } catch (ResourceNotFoundException ex) {\n            logger.error(\"error: velocity vm resource not found.\", ex);\n        } catch (ParseErrorException ex) {\n            logger.error(\"error: velocity parse vm file error.\", ex);\n        } catch (MethodInvocationException ex) {\n            logger.error(\"error: velocity template merge.\", ex);\n        } catch (Exception ex) {\n            logger.error(\"error\", ex);\n        } finally {\n            try {\n                if (writer != null) {\n                    writer.close();\n                }\n            } catch (IOException e) {\n                logger.error(\"error: close writer\", e);\n            }\n            try {\n                if (fos != null) {\n                    fos.close();\n                }\n            } catch (IOException e) {\n                logger.error(\"error: close output stream.\", e);\n            }\n        }\n        logger.info(\"velocity: create text done.\");\n        if (writer != null) {\n            return writer.toString();\n        }\n        return null;\n    }\n\n    public static void main(String[] args) throws Exception{\n        ClassPathResource resource = new ClassPathResource(\"classpath:templates/appAudit.vm\");\n        logger.info(\"VelocityUtils: {}\",resource.getFile().getPath());\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/vo/AppDetailVO.java",
    "content": "package com.sohu.cache.web.vo;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.apache.commons.collections.CollectionUtils;\nimport org.apache.commons.lang.StringUtils;\n\nimport com.sohu.cache.entity.AppDesc;\nimport com.sohu.cache.entity.AppUser;\n\n/**\n * 应用详情\n * @author leifu\n * @Time 2014年8月29日\n */\npublic class AppDetailVO {\n\n    private AppDesc appDesc;\n\n    /**\n     * 内存空间\n     */\n    private long mem;\n\n    /**\n     * 当前内存\n     */\n    private long currentMem;\n\n    /**\n     * 机器数\n     */\n    private int machineNum;\n\n    /**\n     * 主节点数\n     */\n    private int masterNum;\n\n    /**\n     * 从节点数\n     */\n    private int slaveNum;\n\n    /**\n     * 当前对象数\n     */\n    private long currentObjNum;\n    \n    /**\n     * 当前连接数\n     */\n    private int conn;\n\n    /**\n     * 内存使用报警\n     */\n    private double memUseThreshold;\n\n    /**\n     * 命中率使用报警\n     */\n    private double hitPercentThreshold;\n\n    /**\n     * 内存使用率\n     */\n    private double memUsePercent;\n\n    /**\n     * 命中率\n     */\n    private double hitPercent;\n    \n    /**\n     * 应用对应的用户\n     */\n    private List<AppUser> appUsers;\n\n    public AppDesc getAppDesc() {\n        return appDesc;\n    }\n\n    public void setAppDesc(AppDesc appDesc) {\n        this.appDesc = appDesc;\n    }\n\n    public long getMem() {\n        return mem;\n    }\n\n    public void setMem(long mem) {\n        this.mem = mem;\n    }\n\n    public long getCurrentMem() {\n        return currentMem;\n    }\n\n    public void setCurrentMem(long currentMem) {\n        this.currentMem = currentMem;\n    }\n\n    public int getMachineNum() {\n        return machineNum;\n    }\n\n    public void setMachineNum(int machineNum) {\n        this.machineNum = machineNum;\n    }\n\n    public int getMasterNum() {\n        return masterNum;\n    }\n\n    public void setMasterNum(int masterNum) {\n        this.masterNum = masterNum;\n    }\n\n    public int getSlaveNum() {\n        return slaveNum;\n    }\n\n    public void setSlaveNum(int slaveNum) {\n        this.slaveNum = slaveNum;\n    }\n\n    public long getCurrentObjNum() {\n        return currentObjNum;\n    }\n\n    public void setCurrentObjNum(long currentObjNum) {\n        this.currentObjNum = currentObjNum;\n    }\n\n    public int getConn() {\n        return conn;\n    }\n\n    public void setConn(int conn) {\n        this.conn = conn;\n    }\n\n    public double getMemUseThreshold() {\n        return memUseThreshold;\n    }\n\n    public void setMemUseThreshold(double memUseThreshold) {\n        this.memUseThreshold = memUseThreshold;\n    }\n\n    public double getHitPercentThreshold() {\n        return hitPercentThreshold;\n    }\n\n    public void setHitPercentThreshold(double hitPercentThreshold) {\n        this.hitPercentThreshold = hitPercentThreshold;\n    }\n\n    public double getMemUsePercent() {\n        return memUsePercent;\n    }\n\n    public void setMemUsePercent(double memUsePercent) {\n        this.memUsePercent = memUsePercent;\n    }\n\n    public double getHitPercent() {\n        return hitPercent;\n    }\n\n    public void setHitPercent(double hitPercent) {\n        this.hitPercent = hitPercent;\n    }\n\n    public List<AppUser> getAppUsers() {\n\t\treturn appUsers;\n\t}\n\n\tpublic void setAppUsers(List<AppUser> appUsers) {\n\t\tthis.appUsers = appUsers;\n\t}\n\t\n\tpublic List<String> getPhoneList(){\n\t    List<String> phoneList = new ArrayList<String>();\n\t    if(CollectionUtils.isNotEmpty(appUsers)){\n\t        for(AppUser appUser : appUsers){\n\t            String mobile = appUser.getMobile();\n\t            if(StringUtils.isNotBlank(mobile)){\n\t                phoneList.add(appUser.getMobile());\n\t            }\n\t        }\n\t    }\n\t    return phoneList;\n\t}\n\t\n\tpublic List<String> getEmailList(){\n        List<String> emailList = new ArrayList<String>();\n        if(CollectionUtils.isNotEmpty(appUsers)){\n            for(AppUser appUser : appUsers){\n                String email = appUser.getEmail();\n                if(StringUtils.isNotBlank(email)){\n                    emailList.add(appUser.getEmail());\n                }\n            }\n        }\n        return emailList;\n    }\n\n\t@Override\n    public String toString() {\n        return \"AppDetailVO{\" +\n                \"appDesc=\" + appDesc +\n                \", mem=\" + mem +\n                \", currentMem=\" + currentMem +\n                \", machineNum=\" + machineNum +\n                \", masterNum=\" + masterNum +\n                \", slaveNum=\" + slaveNum +\n                \", currentObjNum=\" + currentObjNum +\n                \", conn=\" + conn +\n                \", memUsePercent=\" + memUsePercent +\n                \", hitPercent=\" + hitPercent +\n                \", appUsers=\" + appUsers + \n                '}';\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/java/com/sohu/cache/web/vo/RedisSlowLog.java",
    "content": "package com.sohu.cache.web.vo;\n\nimport java.util.Date;\n\n\n/**\n * Created by yijunzhang on 14-10-14.\n */\npublic class RedisSlowLog {\n\n    /**\n     * 慢查询id\n     */\n    private long id;\n\n    /**\n     * 执行时间点\n     */\n    private String timeStamp;\n\n    /**\n     * 慢查询执行时间(微秒)\n     */\n    private long executionTime;\n\n    private String command;\n    \n    /**\n     * 执行日期时间\n     */\n    private Date date;\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 getTimeStamp() {\n        return timeStamp;\n    }\n\n    public void setTimeStamp(String timeStamp) {\n        this.timeStamp = timeStamp;\n    }\n\n    public long getExecutionTime() {\n        return executionTime;\n    }\n\n    public void setExecutionTime(long executionTime) {\n        this.executionTime = executionTime;\n    }\n\n    public String getCommand() {\n        return command;\n    }\n\n    public void setCommand(String command) {\n        this.command = command;\n    }\n\n    public Date getDate() {\n        return date;\n    }\n\n    public void setDate(Date date) {\n        this.date = date;\n    }\n\n    @Override\n    public String toString() {\n        return \"RedisSlowLog [id=\" + id + \", timeStamp=\" + timeStamp + \", executionTime=\" + executionTime\n                + \", command=\" + command + \", date=\" + date + \"]\";\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/application.properties",
    "content": "# sys config\nisDebug = ${isDebug}\napplication.message=CacheCloud\n\nserver.port=${web.port}\nserver.sessionTimeout= 3600\nserver.contextPath=\n\n# tomcat config\nserver.tomcat.compression=2048 # is compression enabled (off, on, or an integer content length limit)\nserver.tomcat.compressable-mime-types=text/html,text/xml,text/plain,text/javascript,application/json,application/xml\ntomcat.accessLogEnabled= false\ntomcat.protocolHeader=x-forwarded-proto\ntomcat.remoteIpHeader=x-forwarded-for\ntomcat.basedir=\ntomcat.backgroundProcessorDelay=30 # secs\nserver.tomcat.max-threads = 500\nserver.tomcat.uri-encoding = UTF-8\n\ncachecloud.db.url = ${cachecloud.db.url}\ncachecloud.db.user = ${cachecloud.db.user}\ncachecloud.db.password = ${cachecloud.db.password}\ncachecloud.maxPoolSize = ${cachecloud.maxPoolSize}\njdbc.driver = com.mysql.jdbc.Driver\njdbc.validationQuery = select 1 from dual\n\nspring.http.encoding.charset=UTF-8\nspring.http.encoding.enabled=true\nspring.http.encoding.force=true\n\n#classpath中存在velocity 忽略spring-boot的VelocityAutoConfiguration\nspring.velocity.enabled=false\nspring.velocity.checkTemplateLocation=true\n\n# maven配置\nproject.name=${project.build.finalName}\nproject.package=${project.packaging}\n\n# endpoints 配置\nendpoints.enabled=true\nendpoints.shutdown.id=shutdown\nendpoints.shutdown.sensitive=true\nendpoints.shutdown.enabled=false\nendpoints.trace.id=trace\nendpoints.trace.sensitive=true\nendpoints.trace.enabled=false\n\n# RemoteShell\n# Authentication type. Auto-detected according to the environment.\nshell.auth=simple\n# JAAS domain.\nshell.auth.jaas.domain=my-domain\n# Path to the authentication key. This should point to a valid \".pem\" file.\nshell.auth.key.path=\nshell.auth.simple.user.name=cachecloud\nshell.auth.simple.user.password=\n# Comma-separated list of required roles to login to the CRaSH console.\nshell.auth.spring.roles=ADMIN\n# Patterns to use to look for commands.\nshell.command-path-patterns=classpath*:/commands/**,classpath*:/crash/commands/**\n# Scan for changes and update the command if necessary (in seconds).\nshell.command-refresh-interval=-1\n# Patterns to use to look for configurations.\nshell.config-path-patterns=classpath*:/crash/*\n# Comma-separated list of commands to disable.\nshell.disabled-commands=jpa*,jdbc*,jndi*\nshell.ssh.enabled=true\nshell.ssh.idle-timeout = 300000\nshell.ssh.port=2000\nshell.telnet.enabled=false\nshell.telnet.port=5000\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/cachecloud-web.conf",
    "content": "PID_FOLDER=/data/cachecloud-web\nLOG_FOLDER=/data/cachecloud-web/logs\nLOG_FILENAME=cachecloud-web.log\nAPP_NAME=cachecloud-web\nRUN_ARGS=\nJAVA_HOME=/usr/local/jdk\nJAVA_OPTS=\"-server -Xmx4g -Xms4g -Xss256k -XX:MaxDirectMemorySize=1G -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:G1ReservePercent=25 -XX:InitiatingHeapOccupancyPercent=40 -XX:+PrintGCDateStamps -Xloggc:/opt/cachecloud-web/logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/cachecloud-web/logs/java.hprof -XX:+DisableExplicitGC -XX:-OmitStackTraceInFastThrow -XX:+PrintCommandLineFlags -XX:+UnlockCommercialFeatures -XX:+FlightRecorder -Djava.awt.headless=true -Djava.net.preferIPv4Stack=true -Djava.util.Arrays.useLegacyMergeSort=true -Dfile.encoding=UTF-8 -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=22099 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false\""
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/logback.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n  Example LOGBACK Configuration File\n  http://logback.qos.ch/manual/configuration.html\n  -->\n<configuration  scan=\"true\" scanPeriod=\"30 seconds\">\n    <property name=\"log_base\" value=\"${log_base}\"/>\n\n    <appender name=\"console\" class=\"ch.qos.logback.core.ConsoleAppender\">\n        <encoder class=\"ch.qos.logback.classic.encoder.PatternLayoutEncoder\">\n            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} {%thread} %-5level %logger{50} - %msg%n</pattern>\n        </encoder>\n    </appender>\n\n    <appender name=\"stdout\" class=\"ch.qos.logback.core.rolling.RollingFileAppender\">\n        <file>${log_base}/stdout.log</file>\n        <encoder class=\"ch.qos.logback.classic.encoder.PatternLayoutEncoder\">\n            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} {%thread} %-5level %logger{50} - %msg%n</pattern>\n        </encoder>\n\n        <filter class=\"ch.qos.logback.classic.filter.ThresholdFilter\">\n            <level>${log.level}</level>\n        </filter>\n\n        <rollingPolicy class=\"ch.qos.logback.core.rolling.TimeBasedRollingPolicy\">\n            <FileNamePattern>${log_base}/otherdays/stdout.%d{yyyy-MM-dd}.log</FileNamePattern>\n            <MaxHistory>30</MaxHistory>\n        </rollingPolicy>\n    </appender>\n\n    <appender name=\"stderr\" class=\"ch.qos.logback.core.rolling.RollingFileAppender\">\n        <file>${log_base}/stderr.log</file>\n        <encoder class=\"ch.qos.logback.classic.encoder.PatternLayoutEncoder\">\n            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} {%thread} %-5level %logger{50} - %msg%n</pattern>\n        </encoder>\n\n        <filter class=\"ch.qos.logback.classic.filter.ThresholdFilter\">\n            <level>ERROR</level>\n        </filter>\n\n        <rollingPolicy class=\"ch.qos.logback.core.rolling.TimeBasedRollingPolicy\">\n            <FileNamePattern>${log_base}/otherdays/stderr.%d{yyyy-MM-dd}.log</FileNamePattern>\n            <MaxHistory>30</MaxHistory>\n        </rollingPolicy>\n    </appender>\n    \n    \n    <appender name=\"managerAppender\" class=\"ch.qos.logback.core.rolling.RollingFileAppender\">\n        <file>${log_base}/manager/cachecloud_manager.log</file>\n        <rollingPolicy class=\"ch.qos.logback.core.rolling.TimeBasedRollingPolicy\">\n            <fileNamePattern>${log_base}/manager/cachecloud_manager.log.%d{yyyyMMddHH}\n            </fileNamePattern>\n            <maxHistory>365</maxHistory>\n        </rollingPolicy>\n        <encoder>\n            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>\n        </encoder>\n    </appender>\n\n    <!--<logger name=\"org.cache.dao\" level=\"DEBUG\">-->\n        <!--<appender-ref ref=\"console\"/>-->\n    <!--</logger>-->\n\n    <root level=\"${log.level}\">\n        <appender-ref ref=\"console\"/>\n        <appender-ref ref=\"stdout\"/>\n        <appender-ref ref=\"stderr\"/>\n    </root>\n\n    <logger name=\"com.sohu.cache.web.controller.AppManageController\" level=\"WARN\">\n        <appender-ref ref=\"managerAppender\"/>\n    </logger>\n    \n    <logger name=\"com.sohu.cache.web.controller.InstanceManageController\" level=\"WARN\">\n        <appender-ref ref=\"managerAppender\"/>\n    </logger>\n\n</configuration>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/mapper/AppAuditDao.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.sohu.cache.dao.AppAuditDao\">\n    <sql id=\"columns\">\n    \tapp_id,user_id,user_name,type,param1,param2,param3,info,status,modify_time\n    </sql>\n\n    <select id=\"selectWaitAppAudits\" resultType=\"com.sohu.cache.entity.AppAudit\">\n        select id,<include refid=\"columns\"/>,create_time\n        from app_audit\n        <where>\n            <choose>\n                <when test=\"status != null\">status=#{status}</when>\n                <otherwise>status in (0,2)</otherwise>\n            </choose>\n        </where>\n        order by id desc\n    </select>\n\n    <select id=\"getAppAudit\" resultType=\"com.sohu.cache.entity.AppAudit\">\n        select id,<include refid=\"columns\"/>,create_time,refuse_reason\n        from app_audit\n        where id=#{id}\n    </select>\n\n    <insert id=\"insertAppAudit\" parameterType=\"com.sohu.cache.entity.AppAudit\" keyProperty=\"id\" useGeneratedKeys=\"true\">\n        insert into app_audit(<include refid=\"columns\"/>)\n        values(#{appId},#{userId},#{userName},#{type},#{param1},#{param2},#{param3},#{info},#{status},#{modifyTime})\n    </insert>\n\n    <update id=\"updateAppAudit\" parameterType=\"com.sohu.cache.entity.AppAudit\">\n        update app_audit\n        set\n          status = #{status},\n         modify_time = current_timestamp()\n        where id=#{id}\n    </update>\n    \n    <update id=\"updateRefuseReason\" parameterType=\"com.sohu.cache.entity.AppAudit\">\n        update app_audit\n        set\n          refuse_reason = #{refuseReason}, modify_time = current_timestamp()\n        where id=#{id}\n    </update>\n    \n    <select id=\"getAppAuditByAppId\" resultType=\"com.sohu.cache.entity.AppAudit\">\n        select id,<include refid=\"columns\"/>,create_time,refuse_reason\n        from app_audit\n        where app_id=#{appId}\n    </select>\n    \n</mapper>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/mapper/AppAuditLogDao.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n\n<mapper namespace=\"com.sohu.cache.dao.AppAuditLogDao\">\n    <sql id=\"app_audit_log_column\">\n    \tapp_id,user_id,info,create_time,type,app_audit_id\n    </sql>\n    \n    <insert id=\"save\" parameterType=\"AppAuditLog\"  keyProperty=\"id\" useGeneratedKeys=\"true\" >\n    \tinsert into app_audit_log\n    \t\t(<include refid=\"app_audit_log_column\"/>)\n\t\tvalues\n\t\t\t(#{appId},#{userId},#{info},#{createTime},#{type},#{appAuditId})    \t\n    </insert>\n    \n    <select id=\"getAuditByType\" resultType=\"AppAuditLog\">\n        select id,<include refid=\"app_audit_log_column\"/>\n        from app_audit_log\n        where app_audit_id=#{appAuditId} and type=#{type}\n    </select>\n    \n</mapper>\n\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/mapper/AppClientCostTimeStatDao.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.sohu.cache.dao.AppClientCostTimeStatDao\">\n\t<sql id=\"columns\">\n\t\tapp_id,collect_time,client_ip,report_time,create_time,command,\n\t\tmedian,mean,ninety_percent_max,ninety_nine_percent_max,hundred_max,\n\t\tcount,instance_host,instance_port,instance_id\n\t</sql>\n\n\t<insert id=\"save\" parameterType=\"AppClientCostTimeStat\"\n\t\tkeyProperty=\"id\" useGeneratedKeys=\"true\">\n\t\tinsert into app_client_costtime_minute_stat(<include refid=\"columns\"/>)\n\t\tvalues(#{appId},#{collectTime},#{clientIp},#{reportTime},#{createTime},#{command},\n\t\t       #{median},#{mean},#{ninetyPercentMax},#{ninetyNinePercentMax},#{hundredMax},\n\t\t       #{count},#{instanceHost},#{instancePort},#{instanceId})\n\t</insert>\n\t\n\t<insert id=\"batchSave\">\n\t\tinsert into app_client_costtime_minute_stat(<include refid=\"columns\" />)\n\t\tvalues\n\t\t<foreach collection=\"appClientCostTimeStatList\" item=\"clientCostTime\" separator=\",\">\n\t\t\t(#{clientCostTime.appId},#{clientCostTime.collectTime},#{clientCostTime.clientIp},#{clientCostTime.reportTime},#{clientCostTime.createTime},#{clientCostTime.command},\n\t\t       #{clientCostTime.median},#{clientCostTime.mean},#{clientCostTime.ninetyPercentMax},#{clientCostTime.ninetyNinePercentMax},#{clientCostTime.hundredMax},\n\t\t       #{clientCostTime.count},#{clientCostTime.instanceHost},#{clientCostTime.instancePort},#{clientCostTime.instanceId})\n\t    </foreach>\n\t</insert>\n\t\n    <select id=\"getAppCommandClientToInstanceStat\" resultType=\"AppClientCostTimeStat\">\n    \tselect id,<include refid=\"columns\"/>\n    \tfrom app_client_costtime_minute_stat\n    \twhere app_id=#{appId} and instance_id=#{instanceId} and client_ip=#{clientIp} and collect_time between #{startTime} and #{endTime} and command=#{command};\n    </select>\n    \n    <select id=\"getTableMinimumId\" resultType=\"long\">\n    \tselect id from app_client_costtime_minute_stat order by id limit 1\n    </select>\n    \n    <select id=\"getMinimumIdByCollectTime\" resultType=\"long\">\n    \tselect id from app_client_costtime_minute_stat where collect_time = #{collectTime} order by id limit 1\n    </select>\n    \n    <delete id=\"deleteByIds\">\n    \tdelete from app_client_costtime_minute_stat where id>=#{startId} and id &lt;#{endId}\n    </delete>\n\n</mapper>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/mapper/AppClientCostTimeTotalStatDao.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.sohu.cache.dao.AppClientCostTimeTotalStatDao\">\n\t<sql id=\"columns\">\n\t\tapp_id,collect_time,create_time,command,mean,median,ninety_percent_max,ninety_nine_percent_max,\n\t\thundred_max,total_cost,total_count,max_instance_host,max_instance_port,max_instance_id,max_client_ip,accumulation\n\t</sql>\n\t\n\t<insert id=\"save\" parameterType=\"AppClientCostTimeTotalStat\" keyProperty=\"id\" useGeneratedKeys=\"true\">\n\t\t insert into app_client_costtime_minute_stat_total\n\t\t (<include refid=\"columns\"/>)\n        values\n          (#{appId},#{collectTime},#{createTime},#{command},${mean},#{median},\n          #{ninetyPercentMax},#{ninetyNinePercentMax},#{hundredMax},#{totalCost},#{totalCount},#{maxInstanceHost},#{maxInstancePort},#{maxInstanceId},#{maxClientIp}, 1)\n        on duplicate key update\n          total_cost = total_cost + #{totalCost},\n          total_count = total_count + #{totalCount},\n          median = if(median>#{median},median,#{median}),\n          ninety_percent_max = if(ninety_percent_max>#{ninetyPercentMax},ninety_percent_max,#{ninetyPercentMax}),\n          ninety_nine_percent_max = if(ninety_nine_percent_max>#{ninetyNinePercentMax},ninety_nine_percent_max,#{ninetyNinePercentMax}),\n          hundred_max = if(hundred_max>#{hundredMax},hundred_max,#{hundredMax}),\n          max_instance_host = if(hundred_max>#{hundredMax},max_instance_host,#{maxInstanceHost}),\n          max_instance_port = if(hundred_max>#{hundredMax},max_instance_port,#{maxInstancePort}),\n          max_instance_id =   if(hundred_max>#{hundredMax},max_instance_id,#{maxInstanceId}),\n          max_client_ip =     if(hundred_max>#{hundredMax},max_client_ip,#{maxClientIp}),\n          mean = format(total_cost/total_count,2),\n          create_time = now(),\n          accumulation = accumulation + 1;\n\t</insert>\n\t\n\t<insert id=\"batchSave\">\n\t\tinsert into app_client_costtime_minute_stat_total(<include refid=\"columns\"/>)\n\t\tvalues\n\t\t<foreach collection=\"appClientCostTimeTotalStatList\" item=\"clientCostTime\" separator=\",\">\n\t\t\t (#{clientCostTime.appId},#{clientCostTime.collectTime},#{clientCostTime.createTime},#{clientCostTime.command},${clientCostTime.mean},#{clientCostTime.median},\n          #{clientCostTime.ninetyPercentMax},#{clientCostTime.ninetyNinePercentMax},#{clientCostTime.hundredMax},#{clientCostTime.totalCost},#{clientCostTime.totalCount},#{clientCostTime.maxInstanceHost},#{clientCostTime.maxInstancePort},#{clientCostTime.maxInstanceId},#{clientCostTime.maxClientIp}, 1)\n\t    </foreach>\n\t    on duplicate key update\n          total_cost = total_cost + #{clientCostTime.totalCost},\n          total_count = total_count + #{clientCostTime.totalCount},\n          median = if(median>#{clientCostTime.median},median,#{clientCostTime.median}),\n          ninety_percent_max = if(ninety_percent_max>#{clientCostTime.ninetyPercentMax},ninety_percent_max,#{clientCostTime.ninetyPercentMax}),\n          ninety_nine_percent_max = if(ninety_nine_percent_max>#{clientCostTime.ninetyNinePercentMax},ninety_nine_percent_max,#{clientCostTime.ninetyNinePercentMax}),\n          hundred_max = if(hundred_max>#{clientCostTime.hundredMax},hundred_max,#{clientCostTime.hundredMax}),\n          max_instance_host = if(hundred_max>#{clientCostTime.hundredMax},max_instance_host,#{clientCostTime.maxInstanceHost}),\n          max_instance_port = if(hundred_max>#{clientCostTime.hundredMax},max_instance_port,#{clientCostTime.maxInstancePort}),\n          max_instance_id =   if(hundred_max>#{clientCostTime.hundredMax},max_instance_id,#{clientCostTime.maxInstanceId}),\n          max_client_ip =     if(hundred_max>#{clientCostTime.hundredMax},max_client_ip,#{clientCostTime.maxClientIp}),\n          mean = format(total_cost/total_count,2),\n          create_time = now(),\n          accumulation = accumulation + 1;\n\t</insert>\n\t\n    <select id=\"getAppDistinctCommand\" resultType=\"string\">\n   \t\tselect command from app_client_costtime_minute_stat_total where app_id=#{appId} and collect_time between #{startTime} and #{endTime} group by command order by sum(total_count) desc;\n    </select>\n    \n    <select id=\"getAppClientCommandStat\" resultType=\"AppClientCostTimeTotalStat\">\n    \tselect id,<include refid=\"columns\"/> from app_client_costtime_minute_stat_total\n    \twhere app_id=#{appId} and collect_time between #{startTime} and #{endTime} and command=#{command}\n    </select>\n\n</mapper>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/mapper/AppClientExceptionStatDao.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.sohu.cache.dao.AppClientExceptionStatDao\">\n\t<sql id=\"columns\">\n\t\tapp_id,collect_time,client_ip,report_time,create_time,exception_class,exception_count,instance_host,instance_port,instance_id,type\n\t</sql>\n\t\n\t<insert id=\"save\" parameterType=\"AppClientExceptionStat\"\n\t\tkeyProperty=\"id\" useGeneratedKeys=\"true\">\n\t\tinsert into app_client_exception_minute_stat(<include refid=\"columns\" />)\n\t\tvalues(#{appId},#{collectTime},#{clientIp},#{reportTime},#{createTime},#{exceptionClass},#{exceptionCount},#{instanceHost},#{instancePort},#{instanceId},#{type})\n\t</insert>\n\t\n\t<insert id=\"batchSave\">\n\t\tinsert into app_client_exception_minute_stat(<include refid=\"columns\" />)\n\t\tvalues\n\t\t<foreach collection=\"appClientExceptionStatList\" item=\"clientException\" separator=\",\">\n\t\t\t(#{clientException.appId},#{clientException.collectTime},#{clientException.clientIp},#{clientException.reportTime},#{clientException.createTime},\n\t\t\t#{clientException.exceptionClass},#{clientException.exceptionCount},#{clientException.instanceHost},#{clientException.instancePort},#{clientException.instanceId},#{clientException.type})\n\t    </foreach>\n\t</insert>\n\t\n\t<select id=\"getAppExceptionList\" resultType=\"AppClientExceptionStat\">\n    \tselect id,<include refid=\"columns\" />\n    \tfrom app_client_exception_minute_stat\n    \twhere app_id=#{appId} and collect_time between #{startTime} and #{endTime}\n    \t<choose>\n        \t<when test=\"type > 0\">\n        \t \tand type=#{type}\n        \t</when>\n        </choose>\n        <choose>\n        \t<when test=\"clientIp != '' and clientIp != null\">\n        \t \tand client_ip=#{clientIp}\n        \t</when>\n        </choose>\n        order by collect_time desc\n        <choose>\n        \t<when test=\"page != null\">\n        \t\t<choose>\n\t\t        \t<when test=\"page.totalCount > page.pageSize\">\n            \t\t\tlimit #{page.start},#{page.pageSize};\n\t\t        \t</when>\n\t\t        \t<otherwise>\n\t\t        \t    limit #{page.totalCount}\n\t\t        \t</otherwise>\n\t\t        </choose>\n        \t</when>\n        </choose>\n    </select>\n    \n    <select id=\"getAppExceptionCount\" resultType=\"int\">\n    \tselect count(*)\n    \tfrom app_client_exception_minute_stat\n    \twhere app_id=#{appId} and collect_time between #{startTime} and #{endTime}\n    \t<choose>\n        \t<when test=\"type > 0\">\n        \t \tand type=#{type}\n        \t</when>\n        </choose>\n        <choose>\n        \t<when test=\"clientIp != '' and clientIp != null\">\n        \t \tand client_ip=#{clientIp}\n        \t</when>\n        </choose>\n    </select>\n    \n    \n    <select id=\"getInstanceExceptionStat\" resultType=\"ClientInstanceException\">\n    \tselect app_id,instance_id,instance_host,instance_port,count(1) as exceptionCount from app_client_exception_minute_stat \n    \t<where>\n\t    \t<choose>\n\t        \t<when test=\"collectTime > 0\">\n\t        \t \tand collect_time>=#{collectTime}\n\t        \t</when>\n\t        </choose>\n\t        <choose>\n\t        \t<when test=\"ip != '' and ip != null\">\n\t        \t \tand instance_host=#{ip}\n\t        \t</when>\n\t        </choose>\n    \t</where>\n    \tgroup by instance_id order by exceptionCount desc;\n    </select>\n    \n    \n\n</mapper>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/mapper/AppClientReportDataSizeDao.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.sohu.cache.dao.AppClientReportDataSizeDao\">\n\t<sql id=\"columns\">\n\t\tcollect_time,client_ip,report_time,create_time,cost_map_size,value_map_size,exception_map_size,collect_map_size\n\t</sql>\n\n\t<insert id=\"save\" parameterType=\"AppClientDataSizeStat\"\n\t\tkeyProperty=\"id\" useGeneratedKeys=\"true\">\n\t\tinsert into app_client_datasize_minute_stat(<include refid=\"columns\" />)\n\t\tvalues(#{collectTime},#{clientIp},#{reportTime},#{createTime},#{costMapSize},\n\t\t#{valueMapSize},#{exceptionMapSize},#{collectMapSize})\n\t</insert>\n\n</mapper>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/mapper/AppClientValueStatDao.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.sohu.cache.dao.AppClientValueStatDao\">\n\t<sql id=\"columns\">\n\t\tapp_id,collect_time,update_time,command,distribute_type,count\n\t</sql>\n\n\t<insert id=\"batchSave\">\n\t\tinsert into app_client_value_minute_stats(<include refid=\"columns\" />)\n\t\tvalues\n\t\t<foreach collection=\"appClientValueDistriStatTotalList\" item=\"valueDistri\" separator=\",\">\n        \t(#{valueDistri.appId},#{valueDistri.collectTime},#{valueDistri.updateTime},#{valueDistri.command},#{valueDistri.distributeType},#{valueDistri.count})\n\t    </foreach>\n\t    on duplicate key update\n\t    count = count + #{valueDistri.count}, update_time=now()\n\t</insert>\n\t\n\t<insert id=\"save\">\n\t\tinsert into app_client_value_minute_stats(<include refid=\"columns\" />)\n\t\tvalues(#{appId},#{collectTime},#{updateTime},#{command},#{distributeType},#{count})\n\t    on duplicate key update\n\t    count = count + #{count}, update_time=now()\n\t</insert>\n\t\n\t<select id=\"getAppValueDistriList\" resultType=\"AppClientValueDistriSimple\">\n    \tselect distribute_type, sum(count) as count\n    \tfrom app_client_value_minute_stats\n    \twhere app_id=#{appId} and collect_time between #{startTime} and #{endTime}\n        group by distribute_type order by distribute_type\n    </select>\n    \n    <delete id=\"deleteBeforeCollectTime\">\n    \tdelete from app_client_value_minute_stats where collect_time &lt;#{collectTime}\n    </delete>\n    \n\n</mapper>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/mapper/AppClientVersionDao.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.sohu.cache.dao.AppClientVersionDao\">\n\t<sql id=\"columns\">\n\t\tapp_id,client_ip,client_version,report_time\n\t</sql>\n\n\t<insert id=\"saveOrUpdateClientVersion\" parameterType=\"AppClientVersion\" keyProperty=\"id\"\n\t\tuseGeneratedKeys=\"true\">\n\t\tinsert into app_client_version_statistic(<include refid=\"columns\"/>)\n\t\tvalues(#{appId},#{clientIp},#{clientVersion},#{reportTime})\n\t\ton duplicate key\n\t\tupdate client_version=#{clientVersion},report_time=#{reportTime}\n\t</insert>\n\t\n\t<select id=\"getByClientIp\" resultType=\"AppClientVersion\">\n\t\tselect id,<include refid=\"columns\"/> from app_client_version_statistic where client_ip=#{clientIp}\n\t</select>\n\t\n\t<select id=\"getAppAllClientVersion\" resultType=\"AppClientVersion\">\n\t\tselect id,<include refid=\"columns\"/> from app_client_version_statistic where app_id=#{appId}\n\t</select>\n\t\n\t<select id=\"getAll\" resultType=\"AppClientVersion\">\n\t\tselect id,<include refid=\"columns\"/> from app_client_version_statistic where 1=1\n\t\t<choose>\n        \t<when test=\"appId > 0\">\n        \t \tand app_id=#{appId}\n        \t</when>\n        </choose>\n\t</select>\n\n</mapper>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/mapper/AppDailyDao.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n\n<mapper namespace=\"com.sohu.cache.dao.AppDailyDao\">\n\t<sql id=\"app_daily_column\">\n\t\tapp_id,date,create_time,slow_log_count,client_exception_count,max_minute_client_count,\n\t\tavg_minute_client_count,max_minute_command_count,avg_minute_command_count,avg_hit_ratio,\n\t\tmin_minute_hit_ratio,max_minute_hit_ratio,avg_used_memory,max_used_memory,expired_keys_count,\n\t\tevicted_keys_count,avg_minute_net_input_byte,max_minute_net_input_byte,avg_minute_net_output_byte,\n\t\tmax_minute_net_output_byte,avg_object_size,max_object_size,big_key_times,big_key_info\n    </sql>\n    \n    <insert id=\"save\" parameterType=\"AppDailyData\" keyProperty=\"id\" useGeneratedKeys=\"true\">\n    \tinsert into app_daily\n    \t\t(<include refid=\"app_daily_column\"/>)\n\t\tvalues\n\t\t(#{appId},#{date},now(),#{slowLogCount},#{clientExceptionCount},#{maxMinuteClientCount},\n\t\t#{avgMinuteClientCount},#{maxMinuteCommandCount},#{avgMinuteCommandCount},#{avgHitRatio},\n\t\t#{minMinuteHitRatio},#{maxMinuteHitRatio},#{avgUsedMemory},#{maxUsedMemory},#{expiredKeysCount},\n\t\t#{evictedKeysCount},#{avgMinuteNetInputByte},#{maxMinuteNetInputByte},#{avgMinuteNetOutputByte}\n\t\t,#{maxMinuteNetOutputByte},#{avgObjectSize},#{maxObjectSize},#{bigKeyTimes},#{bigKeyInfo})\n    </insert>\n    \n    <select id=\"getAppDaily\" resultType=\"AppDailyData\">\n\t\tselect id,<include refid=\"app_daily_column\"/> from app_daily where app_id=#{appId} and date =#{date}\n\t</select>\n    \n</mapper>\n\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/mapper/AppDao.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n\n<mapper namespace=\"com.sohu.cache.dao.AppDao\">\n    <sql id=\"app_desc_fields\">\n        app_id,name,user_id,status,intro,create_time,passed_time,type,officer,\n        ver_id,is_test,has_back_store,need_persistence,need_hot_back_up,forecase_qps,\n        forecast_obj_num,mem_alert_value,client_machine_room,app_key,client_conn_alert_value,important_level,password\n    </sql>\n    <!--通过appId查询app的信息-->\n    <select id=\"getAppDescById\" resultType=\"AppDesc\" parameterType=\"long\">\n        SELECT\n            <include refid=\"app_desc_fields\"/>\n        FROM app_desc\n        WHERE app_id = #{appId};\n    </select>\n    \n    <!-- 根据应用名查询app信息 -->\n    <select id=\"getByAppName\" resultType=\"AppDesc\" parameterType=\"string\">\n        SELECT\n            <include refid=\"app_desc_fields\"/>\n        FROM app_desc\n        WHERE name = #{appName};\n    </select>\n    \n    \n    <insert id=\"save\" parameterType=\"AppDesc\"  keyProperty=\"appId\" useGeneratedKeys=\"true\" >\n    \tinsert into app_desc\n    \t\t(<include refid=\"app_desc_fields\"/>)\n\t\tvalues\n\t\t\t(#{appId},#{name},#{userId},#{status},#{intro},#{createTime},#{passedTime},\n\t\t\t#{type},#{officer},#{verId},#{isTest},#{hasBackStore},#{needPersistence},\n\t\t\t#{needHotBackUp},#{forecaseQps},#{forecastObjNum},#{memAlertValue},#{clientMachineRoom},#{appKey},#{clientConnAlertValue},#{importantLevel},#{password})    \t\n    </insert>\n    \n    <update id=\"update\" parameterType=\"AppDesc\">\n    \tupdate app_desc \n    \t\tset name=#{name}, user_id=#{userId}, status=#{status}, intro=#{intro}, create_time=#{createTime},\n    \t\t\tpassed_time=#{passedTime},type=#{type},\n    \t\t\tofficer=#{officer},ver_id=#{verId},mem_alert_value=#{memAlertValue},client_conn_alert_value=#{clientConnAlertValue},important_level=#{importantLevel},password=#{password}\n    \twhere app_id=#{appId}\n    </update>\n    \n    <sql id=\"app_desc_select_column\">\n    \tapp_desc.app_id,name,app_desc.user_id,status,intro,create_time,passed_time,type,officer,ver_id,app_key,password\n    </sql>\n    <select id=\"getAppDescList\" resultType=\"AppDesc\" parameterType=\"long\">\n    \tselect           \n        \t<include refid=\"app_desc_select_column\"/>\n        from app_desc,app_to_user where app_to_user.user_id=#{userId} and app_to_user.app_id=app_desc.app_id\n    </select>\n    \n    <select id=\"getUserAppCount\" resultType=\"int\" parameterType=\"long\">\n    \tselect count(app_desc.app_id) from app_desc,app_to_user where app_to_user.user_id=#{userId} and app_to_user.app_id=app_desc.app_id\n    </select>\n    \n    <select id=\"getAllAppCount\" resultType=\"int\" parameterType=\"AppSearch\">\n    \tselect count(app_id) from app_desc where 1=1\n        <choose>\n            <when test=\"appName != null and appName != ''\">\n            \tand name like '${appName}%'\n       \t \t</when>\n        </choose>\n        <choose>\n            <when test=\"appType != null and appType > 0\">\n            \tand type = ${appType}\n       \t \t</when>\n        </choose>\n        <choose>\n            <when test=\"appStatus != null and appStatus >= 0\">\n            \tand status = ${appStatus}\n       \t \t</when>\n        </choose>\n        <choose>\n            <when test=\"appId != null and appId > 0\">\n            \tand app_id = ${appId}\n       \t \t</when>\n        </choose>\n        <choose>\n            <when test=\"importantLevel != null and importantLevel > 0\">\n            \tand important_level = ${importantLevel}\n       \t \t</when>\n        </choose>\n    </select>\n    \n    <select id=\"getAllAppDescList\" resultType=\"AppDesc\" parameterType=\"AppSearch\">\n    \tselect           \n        \t<include refid=\"app_desc_fields\"/>\n        from app_desc where 1=1\n        <choose>\n            <when test=\"appName != null and appName != ''\">\n            \tand name like '${appName}%'\n       \t \t</when>\n        </choose>\n        <choose>\n            <when test=\"appType != null and appType > 0\">\n            \tand type = ${appType}\n       \t \t</when>\n        </choose>\n        <choose>\n            <when test=\"appStatus != null and appStatus >= 0\">\n            \tand status = ${appStatus}\n       \t \t</when>\n        </choose>\n        <choose>\n            <when test=\"appId != null and appId > 0\">\n            \tand app_id = ${appId}\n       \t \t</when>\n        </choose>\n        <choose>\n            <when test=\"importantLevel != null and importantLevel > 0\">\n            \tand important_level = ${importantLevel}\n       \t \t</when>\n        </choose>\n        <choose>\n        \t<when test=\"page != null\">\n        \t\t<choose>\n\t\t        \t<when test=\"page.totalCount > page.pageSize\">\n            \t\t\tlimit #{page.start},#{page.pageSize};\n\t\t        \t</when>\n\t\t        \t<otherwise>\n\t\t        \t    limit #{page.totalCount}\n\t\t        \t</otherwise>\n\t\t        </choose>\n        \t</when>\n        </choose>\n    </select>\n    \n    <update id=\"updateAppKey\">\n    \tupdate app_desc set app_key=#{appKey} where app_id=#{appId}\n    </update>\n    \n</mapper>\n\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/mapper/AppDataMigrateStatusDao.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n\n<mapper namespace=\"com.sohu.cache.dao.AppDataMigrateStatusDao\">\n    <sql id=\"migrate_data_status_fields\">\n        migrate_machine_ip,migrate_machine_port,source_migrate_type,source_servers,target_migrate_type,target_servers,\n        source_app_id,target_app_id,user_id,status,start_time,end_time,log_path,config_path\n    </sql>\n    \n    <insert id=\"save\" parameterType=\"AppDataMigrateStatus\" keyProperty=\"id\" useGeneratedKeys=\"true\" >\n    \tinsert into app_data_migrate_status\n    \t\t(<include refid=\"migrate_data_status_fields\"/>)\n\t\tvalues\n\t\t\t(#{migrateMachineIp},#{migrateMachinePort},#{sourceMigrateType},#{sourceServers},#{targetMigrateType},#{targetServers},\n\t\t\t#{sourceAppId},#{targetAppId},#{userId},#{status},#{startTime},#{endTime},#{logPath},#{configPath})    \t\n    </insert>\n    \n    \n    <select id=\"search\" resultType=\"AppDataMigrateStatus\">\n    \tselect id,<include refid=\"migrate_data_status_fields\"/>\n        from app_data_migrate_status where 1=1\n        <choose>\n            <when test=\"appDataMigrateSearch.sourceAppId != null and appDataMigrateSearch.sourceAppId > 0\">\n            \tand source_app_id = #{appDataMigrateSearch.sourceAppId}\n       \t \t</when>\n        </choose>\n        <choose>\n            <when test=\"appDataMigrateSearch.targetAppId != null and appDataMigrateSearch.targetAppId > 0\">\n            \tand target_app_id = #{appDataMigrateSearch.targetAppId}\n       \t \t</when>\n        </choose>\n        \n        <choose>\n            <when test=\"appDataMigrateSearch.sourceInstanceIp != null and appDataMigrateSearch.sourceInstanceIp != ''\">\n            \tand source_servers like '%${appDataMigrateSearch.sourceInstanceIp}%'\n       \t \t</when>\n        </choose>\n        <choose>\n            <when test=\"appDataMigrateSearch.targetInstanceIp != null and appDataMigrateSearch.targetInstanceIp != ''\">\n            \tand target_servers like '%${appDataMigrateSearch.targetInstanceIp}%'\n       \t \t</when>\n        </choose>\n        \n        <choose>\n            <when test=\"appDataMigrateSearch.startDate != null and appDataMigrateSearch.startDate != ''\">\n            \tand start_time > #{appDataMigrateSearch.startDate} \n       \t \t</when>\n        </choose>\n        <choose>\n            <when test=\"appDataMigrateSearch.endDate != null and appDataMigrateSearch.endDate != ''\">\n            \tand end_time &lt;#{appDataMigrateSearch.endDate} \n       \t \t</when>\n        </choose>\n        <choose>\n            <when test=\"appDataMigrateSearch.status >= 0\">\n            \tand status = #{appDataMigrateSearch.status} \n       \t \t</when>\n        </choose>\n    </select>\n    \n    <select id=\"getMigrateMachineStatCount\" resultType=\"int\">\n    \tselect count(*)\n        from app_data_migrate_status where migrate_machine_ip=#{migrateMachineIp} and status = #{status}\n    </select>\n    \n    <select id=\"get\" resultType=\"AppDataMigrateStatus\">\n    \tselect id,<include refid=\"migrate_data_status_fields\"/>\n        from app_data_migrate_status where id = #{id}\n    </select>\n    \n    <update id=\"updateStatus\">\n    \tupdate app_data_migrate_status set status = #{status}, end_time=now() where id = #{id}\n    </update>\n    \n</mapper>\n\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/mapper/AppInstanceClientRelationDao.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.sohu.cache.dao.AppInstanceClientRelationDao\">\n\t<sql id=\"columns\">\n\t\tapp_id,client_ip,instance_host,instance_port,instance_id,day\n\t</sql>\n\t\n\t<insert id=\"save\" parameterType=\"AppInstanceClientRelation\" keyProperty=\"id\" useGeneratedKeys=\"true\">\n\t\tinsert ignore into app_client_instance(<include refid=\"columns\"/>)\n\t\tvalues(#{appId},#{clientIp},#{instanceHost},#{instancePort},#{instanceId},#{day})\n\t</insert>\n\t\n\t<insert id=\"batchSave\">\n\t\tinsert ignore into app_client_instance(<include refid=\"columns\" />)\n\t\tvalues\n\t\t<foreach collection=\"appInstanceClientRelationList\" item=\"appInstanceClientRelation\" separator=\",\">\n\t\t\t(#{appInstanceClientRelation.appId},#{appInstanceClientRelation.clientIp},#{appInstanceClientRelation.instanceHost},#{appInstanceClientRelation.instancePort},#{appInstanceClientRelation.instanceId},#{appInstanceClientRelation.day})\n\t    </foreach>\n\t</insert>\n\t\n\t<select id=\"isExist\" resultType=\"int\">\n\t\tselect count(*) from app_client_instance where app_id=#{appId} and day=#{day} and client_ip=#{clientIp} and instance_id=#{instanceId}\n\t</select>\n\t\n\t<select id=\"getAppInstanceClientRelationList\" resultType=\"AppInstanceClientRelation\">\n\t\tselect <include refid=\"columns\"/> from app_client_instance where app_id=#{appId} and day=date(#{day})\n\t</select>\n\t\n</mapper>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/mapper/AppStatsDao.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.sohu.cache.dao.AppStatsDao\">\n    <!--\n        字典sql\n        set @tn='app_minute_command_statistics';\n        select\n            group_concat(column_name)\n        from\n            information_schema.columns\n        where\n            table_schema = 'cache-cloud' and table_name = @tn;\n\n        select\n            group_concat(case when locate('_',column_name)>0 then concat(replace(column_name , concat('_',@shortChar:=substring(column_name,locate('_',column_name)+1,1)),upper(@shortChar))) else column_name end)\n        from\n            information_schema.columns\n        where\n            table_schema = 'cache-cloud' and table_name = @tn;\n\n        select\n            group_concat(concat('#{',replace(column_name , concat('_',@shortChar:=substring(column_name,locate('_',column_name)+1,1)), upper(@shortChar) ),'}'))\n        from\n            information_schema.columns\n        where\n            table_schema = 'cache-cloud' and table_name = @tn;\n\n    -->\n    <sql id=\"app_minute_statistics_columns\">\n        app_id,collect_time,hits,misses,command_count,used_memory,\n        expired_keys,evicted_keys,net_input_byte,net_output_byte,\n        connected_clients,object_size,modify_time,accumulation\n    </sql>\n\n    <sql id=\"select_table\">\n        <choose>\n            <when test=\"td.dimensionality ==0\"> app_minute_command_statistics </when>\n            <otherwise> app_hour_command_statistics </otherwise>\n        </choose>\n    </sql>\n    \n     <sql id=\"select_stat_table\">\n        <choose>\n            <when test=\"td.dimensionality ==0\"> app_minute_statistics </when>\n            <otherwise> app_hour_statistics </otherwise>\n        </choose>\n    </sql>\n\n    <sql id=\"app_minute_command_statistics_columns\">\n        app_id,collect_time,command_name,command_count,modify_time\n    </sql>\n\n    <insert id=\"mergeMinuteAppStats\" parameterType=\"AppStats\">\n        insert into app_minute_statistics\n          (<include refid=\"app_minute_statistics_columns\"/>)\n        values\n          (#{appId},#{collectTime},#{hits},#{misses},${commandCount},#{usedMemory},\n          #{expiredKeys},#{evictedKeys},#{netInputByte},#{netOutputByte},\n          #{connectedClients},#{objectSize},#{modifyTime},1)\n        on duplicate key update\n          hits = hits + #{hits},\n          misses = misses + #{misses},\n          command_count = command_count + #{commandCount},\n          used_memory = used_memory + #{usedMemory},\n          expired_keys = expired_keys + #{expiredKeys},\n          evicted_keys = evicted_keys + #{evictedKeys},\n          net_input_byte = net_input_byte + #{netInputByte},\n          net_output_byte = net_output_byte + #{netOutputByte},\n          connected_clients = connected_clients + #{connectedClients},\n          object_size = object_size + #{objectSize},\n          modify_time = #{modifyTime},\n          accumulation = accumulation + 1\n    </insert>\n\n    <insert id=\"mergeMinuteCommandStatus\" parameterType=\"AppCommandStats\">\n        insert into app_minute_command_statistics\n        (<include refid=\"app_minute_command_statistics_columns\" />)\n        values\n        (#{appId},#{collectTime},#{commandName},#{commandCount},#{modifyTime})\n        on duplicate key update\n        command_count = command_count + #{commandCount},\n        modify_time = #{modifyTime}\n    </insert>\n\n    <insert id=\"mergeHourAppStats\" parameterType=\"AppStats\">\n        insert into app_hour_statistics\n        (<include refid=\"app_minute_statistics_columns\"/>)\n        values\n        (#{appId},substring(#{collectTime}, 1, 10),#{hits},#{misses},${commandCount},#{usedMemory},#{expiredKeys},\n        #{evictedKeys},#{netInputByte},#{netOutputByte},#{connectedClients},#{objectSize},#{modifyTime},1)\n        on duplicate key update\n        hits = hits + #{hits},\n        misses = misses + #{misses},\n        command_count = command_count + #{commandCount},\n        used_memory = used_memory + #{usedMemory},\n        expired_keys = expired_keys + #{expiredKeys},\n        evicted_keys = evicted_keys + #{evictedKeys},\n        net_input_byte = net_input_byte + #{netInputByte},\n        net_output_byte = net_output_byte + #{netOutputByte},\n        connected_clients = connected_clients + #{connectedClients},\n        object_size = object_size + #{objectSize},\n        modify_time = #{modifyTime},\n        accumulation = accumulation + 1\n    </insert>\n\n    <insert id=\"mergeHourCommandStatus\" parameterType=\"AppCommandStats\">\n        insert into app_hour_command_statistics\n        (<include refid=\"app_minute_command_statistics_columns\" />)\n        values\n        (#{appId},substring(#{collectTime}, 1, 10),#{commandName},#{commandCount},#{modifyTime})\n        on duplicate key update\n        command_count = command_count + #{commandCount},\n        modify_time = #{modifyTime}\n    </insert>\n    \n     <select id=\"getAppStatsList\" resultType=\"AppStats\">\n        select\n          <include refid=\"app_minute_statistics_columns\"/> , create_time\n        from <include refid=\"select_stat_table\"/>\n        where\n          app_id = #{appId} and collect_time between #{td.begin} and #{td.end}\n    </select>\n\n    <select id=\"getAppStatsByMinute\" resultType=\"AppStats\">\n        select\n          <include refid=\"app_minute_statistics_columns\"/> , create_time\n        from app_minute_statistics\n        where\n          app_id = #{appId} and collect_time between #{beginTime} and #{endTime}\n    </select>\n    \n    \n    <select id=\"getAppStatsByHour\" resultType=\"AppStats\">\n        select\n          <include refid=\"app_minute_statistics_columns\"/> , create_time\n        from app_hour_statistics\n        where\n          app_id = #{appId} and collect_time between #{beginTime} and #{endTime}\n    </select>\n    \n    \n    <select id=\"getAppCommandStatsList\" resultType=\"AppCommandStats\">\n        select\n          <include refid=\"app_minute_command_statistics_columns\"/> , create_time\n        from <include refid=\"select_table\"/>\n        where\n          app_id = #{appId}\n          and command_name = #{commandName}\n          and collect_time between #{td.begin} and #{td.end}\n    </select>\n    \n    <select id=\"getAppAllCommandStatsListByMinute\" resultType=\"AppCommandStats\">\n        select\n        app_id,\n        collect_time,\n        'commands' command_name,\n        command_count,\n        create_time,\n        modify_time\n        from app_minute_statistics\n        where\n          app_id = #{appId}\n          and collect_time between #{beginTime} and #{endTime}\n    </select>\n    \n    \n    <select id=\"getAppAllCommandStatsListByHour\" resultType=\"AppCommandStats\">\n        select\n        app_id,\n        collect_time,\n        'commands' command_name,\n        command_count,\n        create_time,\n        modify_time\n        from app_hour_statistics\n        where\n          app_id = #{appId}\n          and collect_time between #{beginTime} and #{endTime}\n    </select>\n    \n    <select id=\"getAppCommandStatsListByMinuteWithCommand\" resultType=\"AppCommandStats\">\n        select\n          <include refid=\"app_minute_command_statistics_columns\"/> , create_time\n        from app_minute_command_statistics\n        where\n          app_id = #{appId}\n          and command_name = #{commandName}\n          and collect_time between #{beginTime} and #{endTime}\n    </select>\n    \n    \n    <select id=\"getAppCommandStatsListByHourWithCommand\" resultType=\"AppCommandStats\">\n        select\n          <include refid=\"app_minute_command_statistics_columns\"/> , create_time\n        from app_hour_command_statistics\n        where\n          app_id = #{appId}\n          and command_name = #{commandName}\n          and collect_time between #{beginTime} and #{endTime}\n    </select>\n    \n\n    <select id=\"getAppAllCommandStatsList\" resultType=\"AppCommandStats\">\n        select\n        app_id,\n        collect_time,\n        'commands' command_name,\n        command_count,\n        create_time,\n        modify_time\n        from <include refid=\"select_stat_table\"/>\n        where\n        app_id = #{appId}\n        and collect_time between #{td.begin} and #{td.end}\n    </select>\n\n\t<!-- 获取应用命令调用次数分布 -->\n    <select id=\"getAppCommandGroup\" resultType=\"AppCommandGroup\">\n        select\n          command_name,sum(command_count) as count\n        from <include refid=\"select_table\"/>\n        where\n          app_id = #{appId}\n          and collect_time between #{td.begin} and #{td.end}\n          group by command_name\n    </select>\n\n    <!--查询一天中应用的命令执行次数的top-->\n    <select id=\"getTopAppCommandStatsList\" resultType=\"AppCommandStats\">\n        select\n          app_id, command_name , max(collect_time) collect_time, sum(command_count) command_count ,\n          max(modify_time) modify_time, max(create_time) create_time\n        from <include refid=\"select_table\"/>\n        where app_id = #{appId}\n        and collect_time between #{td.begin} and #{td.end}\n        group by app_id,command_name\n        order by command_count desc , modify_time desc\n        limit #{top};\n    </select>\n    \n    \n    <select id=\"getTopAppCommandGroupSum\" resultType=\"AppCommandStats\">\n        select\n          app_id,collect_time,command_name,sum(command_count) as command_count,modify_time, create_time\n        from <include refid=\"select_table\"/>\n        where app_id = #{appId}\n        and collect_time between #{td.begin} and #{td.end}\n        group by command_name\n        order by sum(command_count) desc\n        limit #{top};\n    </select>\n\n    <select id=\"getCommandClimax\" resultType=\"AppCommandStats\">\n        select t2.*\n        from (select app_id, command_name, max(command_count) command_count\n            from\n        <include refid=\"select_table\"/>\n            where\n              app_id = #{appId}\n              and command_name = #{commandName}\n              and collect_time between #{td.begin} and #{td.end}\n              group by app_id,command_name) t1 , <include refid=\"select_table\"/> t2\n        where t1.app_id = t2.app_id\n        and t1.command_name=t2.command_name\n        and t1.command_count=t2.command_count\n        and t2.collect_time between #{td.begin} and #{td.end}\n        limit 1;\n    </select>\n    \n    <select id=\"getCommandClimaxCount\" resultType=\"AppCommandStats\">\n        select max(command_count) as command_count\n        from <include refid=\"select_table\"/> \n        where app_id = #{appId} and collect_time between #{td.begin} and #{td.end} and command_name = #{commandName}\n    </select>\n    \n    <select id=\"getCommandClimaxCreateTime\" resultType=\"AppCommandStats\">\n        select create_time \n        from <include refid=\"select_table\"/> \n        where app_id = #{appId} and collect_time between #{td.begin} and #{td.end} and command_name = #{commandName} and command_count=${commandCount} limit 1\n    </select>\n    \n    <select id=\"getAppMinuteStat\" resultType=\"hashmap\">\n        select \n        \tavg(connected_clients) as avgClientCount,\n        \tmax(connected_clients) as maxClientCount,\n        \tavg(command_count) as avgCommandCount, \n        \tmax(command_count) as maxCommandCount,\n            sum(hits)/sum(command_count) as avgHitRatio,\n\t        max(hits/command_count) as maxHitRatio,\n\t        min(hits/command_count) as minHitRatio,\n\t        avg(used_memory) as avgUsedMemory,\n\t        max(used_memory) as maxUsedMemory,\n\t        sum(expired_keys) as expiredKeys,\n\t        sum(evicted_keys) as evictedKeys,\n\t        avg(net_input_byte) as avgNetInputByte,\n\t        max(net_input_byte) as maxNetInputByte,\n\t        avg(net_output_byte) as avgNetOutputByte,\n\t        max(net_output_byte) as maxNetOutputByte,\n\t        avg(object_size) as avgObjectSize,\n\t        max(object_size) as maxObjectSize\n        from app_minute_statistics\n        where app_id = #{appId} and collect_time between #{beginTime} and #{endTime}\n    </select>\n    \n\n</mapper>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/mapper/AppToUserDao.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n\n<mapper namespace=\"com.sohu.cache.dao.AppToUserDao\">\n    <sql id=\"app_to_user_column\">\n    \tid,user_id,app_id\n    </sql>\n    \n    <insert id=\"save\" parameterType=\"AppToUser\">\n    \tinsert into app_to_user\n    \t\t(<include refid=\"app_to_user_column\"/>)\n\t\tvalues\n\t\t\t(#{id},#{userId},#{appId})    \t\n    </insert>\n    \n    <!-- 获取用户的app -->\n    <select id=\"getByUserId\" resultType=\"AppToUser\" parameterType=\"long\">\n    \tselect           \n        \t<include refid=\"app_to_user_column\"/>\n        from app_to_user where user_id=#{userId}\n    </select>\n    \n    <!-- 获取app的用户 -->\n    <select id=\"getByAppId\" resultType=\"AppToUser\" parameterType=\"long\">\n    \tselect           \n        \t<include refid=\"app_to_user_column\"/>\n        from app_to_user where app_id=#{appId}\n    </select>\n    \n    \n    <delete id=\"deleteByAppId\" parameterType=\"long\">\n    \tdelete from app_to_user where app_id=#{appId}\n    </delete>\n    \n    <select id=\"deleteAppToUser\" parameterType=\"AppToUser\">\n        delete from app_to_user where app_id=#{appId} and user_id=#{userId}\n    </select>\n    \n</mapper>\n\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/mapper/AppUserDao.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n\n<mapper namespace=\"com.sohu.cache.dao.AppUserDao\">\n\t<!-- \n\t字典sql\n        set @tn='app_user';\n        select\n            group_concat(column_name)\n        from\n            information_schema.columns\n        where\n            table_schema = 'cache-cloud' and table_name = @tn;\n\t-->\n\t<sql id=\"user_column\">\n\t\tid,name,ch_name,email,mobile,type\n    </sql>\n    \n    <select id=\"get\" resultType=\"AppUser\" parameterType=\"long\">\n        select           \n        \t<include refid=\"user_column\"/>\n        from app_user\n        where id = #{id};\n    </select>\n    \n    <select id=\"getByName\" resultType=\"AppUser\" parameterType=\"string\">\n        select           \n        \t<include refid=\"user_column\"/>\n        from app_user\n        where name = #{name};\n    </select>\n    \n    <insert id=\"save\" parameterType=\"AppUser\" keyProperty=\"id\" useGeneratedKeys=\"true\">\n    \tinsert into app_user\n    \t\t(<include refid=\"user_column\"/>)\n\t\tvalues\n\t\t\t(#{id},#{name},#{chName},#{email},#{mobile},#{type})    \t\n    </insert>\n    \n    <delete id=\"delete\" parameterType=\"long\">\n    \tdelete from app_user where id=#{id}\n    </delete>\n    \n    <update id=\"update\" parameterType=\"AppUser\">\n    \tupdate app_user \n    \t\tset name=#{name}, ch_name=#{chName}, email=#{email}, mobile=#{mobile},type=#{type} \n    \twhere id=#{id}\n    </update>\n    \n    <select id=\"getUserList\" resultType=\"AppUser\" parameterType=\"string\">\n    \tselect           \n        \t<include refid=\"user_column\"/>\n        from app_user where 1=1\n        <choose>\n        \t<when test=\"chName != '' and chName != null\">\n        \t \tand ch_name=#{chName}\n        \t</when>\n        </choose>\n    </select>\n    \n    \n</mapper>\n\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/mapper/ConfigDao.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.sohu.cache.dao.ConfigDao\">\n\t<sql id=\"columns\">\n\t\tconfig_key,config_value ,info,status,order_id\n\t</sql>\n\n\t<select id=\"getConfigList\" resultType=\"com.sohu.cache.entity.SystemConfig\">\n\t\tselect\n\t\t<include refid=\"columns\" />\n\t\tfrom system_config where status=#{status} order by order_id\n\t</select>\n\n\t<update id=\"update\">\n\t\tupdate system_config set config_value = #{configValue} where config_key=#{configKey}\n\t</update>\n\n</mapper>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/mapper/InstanceAlertConfigDao.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.sohu.cache.dao.InstanceAlertConfigDao\">\n\n    <sql id=\"instance_alert_config_column\">\n    \talert_config,alert_value,config_info,type,instance_id,status,compare_type,\n    \tcheck_cycle,update_time,last_check_time\n    </sql>\n    \n    <insert id=\"save\" parameterType=\"InstanceAlertConfig\"  keyProperty=\"id\" useGeneratedKeys=\"true\">\n\t\tinsert into instance_alert_configs(<include refid=\"instance_alert_config_column\" />)\n\t\tvalues(#{alertConfig},#{alertValue},#{configInfo},#{type},#{instanceId},#{status},#{compareType},\n\t\t#{checkCycle},#{updateTime},#{lastCheckTime})\n\t\ton duplicate key update \n\t\talert_value = #{alertValue},check_cycle = #{checkCycle}, update_time = now(),status = #{status},last_check_time=now()      \t\n\t</insert>\n    \n    <select id=\"getAll\" resultType=\"InstanceAlertConfig\">\n        select id,<include refid=\"instance_alert_config_column\"/> from instance_alert_configs\n    </select>\n    \n    <select id=\"get\" resultType=\"InstanceAlertConfig\">\n        select id,<include refid=\"instance_alert_config_column\"/> from instance_alert_configs where id = #{id}\n    </select>\n\t\n\t<delete id=\"remove\">\n\t\tdelete from instance_alert_configs where id = #{id}\n\t</delete>\n\t\n\t<select id=\"getByType\" resultType=\"InstanceAlertConfig\">\n        select id,<include refid=\"instance_alert_config_column\"/> from instance_alert_configs where type = #{type}\n    </select>\n    \n    <select id=\"getByAlertConfig\" resultType=\"InstanceAlertConfig\">\n        select id,<include refid=\"instance_alert_config_column\"/> from instance_alert_configs where alert_config = #{alertConfig}\n    </select>\n    \n    <update id=\"update\">\n    \t\tupdate instance_alert_configs set alert_value = #{alertValue}, check_cycle = #{checkCycle} where id = #{id}\n    </update>\n    \n    <update id=\"updateLastCheckTime\">\n    \t\tupdate instance_alert_configs set last_check_time = #{lastCheckTime} where id = #{id}\n    </update>\n\n</mapper>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/mapper/InstanceConfigDao.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.sohu.cache.dao.InstanceConfigDao\">\n    <sql id=\"columns\">\n    \tconfig_key, config_value, info, update_time, type, status\n    </sql>\n\n    <select id=\"getByType\" resultType=\"com.sohu.cache.entity.InstanceConfig\">\n        select id,<include refid=\"columns\"/> from instance_config where type = #{type}\n    </select>\n    \n    <select id=\"getById\" resultType=\"com.sohu.cache.entity.InstanceConfig\">\n        select id,<include refid=\"columns\"/> from instance_config where id = #{id}\n    </select>\n    \n    <select id=\"getByConfigKeyAndType\" resultType=\"com.sohu.cache.entity.InstanceConfig\">\n        select id,<include refid=\"columns\"/> from instance_config where config_key = #{configKey} and type = #{type}\n    </select>\n    \n    <select id=\"getAllInstanceConfig\" resultType=\"com.sohu.cache.entity.InstanceConfig\">\n        select id,<include refid=\"columns\"/> from instance_config\n    </select>\n    \n    \n    <insert id=\"saveOrUpdate\">\n\t\tinsert into instance_config(<include refid=\"columns\" />)\n\t\tvalues(#{configKey},#{configValue},#{info},now(),#{type},#{status})\n\t    on duplicate key update\n\t    config_value = #{configValue}, info = #{info}, \n\t    update_time = now(),status = #{status} \n\t</insert>\n\t\n\t<update id=\"updateStatus\">\n\t\tupdate instance_config set status = #{status} where id = #{id}\n\t</update>\n\t\n\t<delete id=\"remove\">\n\t\tdelete from instance_config where id = #{id}\n\t</delete>\n\n</mapper>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/mapper/InstanceDao.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n\n<mapper namespace=\"com.sohu.cache.dao.InstanceDao\">\n    <sql id=\"instance_info_columns\">\n        id, app_id, host_id, ip, port, status, mem, conn, cmd, type\n    </sql>\n\n    <!--通过type查询实例列表-->\n    <select id=\"getInstListByType\" resultType=\"InstanceInfo\" parameterType=\"int\">\n        SELECT\n        <include refid=\"instance_info_columns\"/>\n        FROM instance_info\n        WHERE type = #{type} and status=1\n        ORDER BY id;\n    </select>\n\n    <!--通过appId查询实例列表-->\n    <select id=\"getInstListByAppId\" resultType=\"InstanceInfo\" parameterType=\"long\">\n        SELECT\n        <include refid=\"instance_info_columns\"/>\n        FROM instance_info\n        WHERE app_id = #{appId}\n        ORDER BY id;\n    </select>\n\n    <select id=\"getMemoryByHost\" resultType=\"int\">\n        select ifnull(sum(mem),0)\n        from instance_info\n        where ip = #{host} and status in (0,1)\n    </select>\n\n    <!--通过host和port查询一个实例信息-->\n    <select id=\"getInstByIpAndPort\" resultType=\"InstanceInfo\">\n        SELECT\n        <include refid=\"instance_info_columns\"/>\n        FROM instance_info\n        WHERE ip = #{ip} AND port = #{port} AND status = 1\n    </select>\n\n    <select id=\"getAllInstByIpAndPort\" resultType=\"InstanceInfo\">\n        SELECT\n        <include refid=\"instance_info_columns\"/>\n        FROM instance_info\n        WHERE ip = #{ip} AND port = #{port}\n    </select>\n\n    <!--通过host和port查询一个实例信息-->\n    <select id=\"getAllInsts\" resultType=\"InstanceInfo\">\n        SELECT\n        <include refid=\"instance_info_columns\"/>\n        FROM instance_info\n        WHERE status in (0,1)\n    </select>\n\n    <!--通过host和port查询一个实例数-->\n    <select id=\"getCountByIpAndPort\" resultType=\"int\">\n        SELECT count(*)\n        FROM instance_info\n        WHERE ip = #{ip} AND port = #{port}\n    </select>\n\n    <!--通过id查询一个实例信息-->\n    <select id=\"getInstanceInfoById\" resultType=\"InstanceInfo\">\n        SELECT\n        <include refid=\"instance_info_columns\"/>\n        FROM instance_info\n        WHERE id = #{id}\n    </select>\n\n    <!--保存实例-->\n    <insert id=\"saveInstance\" parameterType=\"InstanceInfo\" keyColumn=\"id\" keyProperty=\"id\" useGeneratedKeys=\"true\">\n        INSERT INTO instance_info (app_id, host_id, ip, port, status, mem, conn, cmd, type)\n        VALUE(#{appId}, #{hostId}, #{ip}, #{port}, #{status}, #{mem}, #{conn}, #{cmd}, #{type});\n    </insert>\n\n    <update id=\"update\" parameterType=\"InstanceInfo\">\n        update instance_info\n        set\n        <if test=\"appId != null\">app_id=#{appId},</if>\n        <if test=\"hostId != null\">host_id=#{hostId},</if>\n        <if test=\"ip != null\">ip=#{ip},</if>\n        <if test=\"port != null\">port=#{port},</if>\n        <if test=\"mem != null\">mem=#{mem},</if>\n        <if test=\"conn != null\">conn=#{conn},</if>\n        <if test=\"cmd != null\">cmd=#{cmd},</if>\n        status=#{status}\n        where\n        id=#{id}\n    </update>\n\n    <select id=\"getAppInstanceInfo\" parameterType=\"long\" resultType=\"InstanceInfo\">\n        select\n        <include refid=\"instance_info_columns\"/>\n        from instance_info where app_id=#{appId} and status=1\n    </select>\n\n    <select id=\"getInstanceTypeCount\" resultType=\"int\">\n        select count(*)\n        from instance_info\n        where ip = #{ip} and type = #{type}\n    </select>\n    \n    <!--通过机器ip查询实例列表-->\n    <select id=\"getInstListByIp\" resultType=\"InstanceInfo\" parameterType=\"string\">\n        SELECT\n        <include refid=\"instance_info_columns\"/>\n        FROM instance_info\n        WHERE ip = #{ip} and status != 2\n        ORDER BY id;\n    </select>\n    \n    <select id=\"getMachineInstanceCountMap\" resultType=\"hashmap\">\n    \tselect ip, count(*) as count from instance_info where status=1 group by ip;\n    </select>\n\n\n</mapper>\n\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/mapper/InstanceFaultDao.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n\n<mapper namespace=\"com.sohu.cache.dao.InstanceFaultDao\">\n    <sql id=\"instance_fault_column\">\n\t\tapp_id,inst_id,ip,port,status,create_time,type,reason\n    </sql>\n\n    <insert id=\"insert\" parameterType=\"InstanceFault\" keyColumn=\"id\" keyProperty=\"id\" useGeneratedKeys=\"true\">\n        insert into instance_fault(app_id,inst_id,ip,port,status,create_time,type,reason)\n        VALUE (#{appId},#{instId},#{ip},#{port},#{status},#{createTime},#{type},#{reason})\n    </insert>\n\n    <select id=\"getListByInstId\" resultType=\"InstanceFault\">\n        select\n          id, <include refid=\"instance_fault_column\"/>\n        from instance_fault\n        where inst_id = #{instId}\n        order by create_time desc\n    </select>\n\n    <select id=\"getListByAppId\" resultType=\"InstanceFault\">\n        select\n        id, <include refid=\"instance_fault_column\"/>\n        from instance_fault\n        where app_id = #{appId}\n        order by create_time desc\n    </select>\n\n\n</mapper>\n\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/mapper/InstanceReshardProcessDao.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.sohu.cache.dao.InstanceReshardProcessDao\">\n\n    <sql id=\"instance_reshard_process_column\">\n\t    \tapp_id,audit_id,source_instance_id,target_instance_id,start_slot,end_slot,\n\t    \tmigrating_slot,is_pipeline,finish_slot_num,status,start_time,end_time,create_time,update_time\n    </sql>\n    \n    <insert id=\"save\" parameterType=\"InstanceReshardProcess\"  keyProperty=\"id\" useGeneratedKeys=\"true\">\n\t\tinsert into instance_reshard_process(<include refid=\"instance_reshard_process_column\" />)\n\t\tvalues(#{appId},#{auditId},#{sourceInstanceId},#{targetInstanceId},#{startSlot},#{endSlot},\n\t\t#{migratingSlot},#{isPipeline},#{finishSlotNum},#{status},#{startTime},#{endTime},#{createTime},#{updateTime})\n\t</insert>\n    \n    <select id=\"getByAuditId\" resultType=\"InstanceReshardProcess\">\n        select id,<include refid=\"instance_reshard_process_column\"/> from instance_reshard_process where audit_id = #{auditId}\n    </select>\n    \n    <select id=\"get\" resultType=\"InstanceReshardProcess\">\n        select id,<include refid=\"instance_reshard_process_column\"/> from instance_reshard_process where id = #{id}\n    </select>\n\t\n    <update id=\"updateStatus\">\n    \t\tupdate instance_reshard_process set status = #{status} where id = #{id}\n    </update>\n    \n    <update id=\"updateEndTime\">\n    \t\tupdate instance_reshard_process set end_time = #{endTime} where id = #{id}\n    </update>\n    \n    <update id=\"increaseFinishSlotNum\">\n    \t\tupdate instance_reshard_process set finish_slot_num = finish_slot_num + 1 where id = #{id}\n    </update>\n    \n    <update id=\"updateMigratingSlot\">\n    \t\tupdate instance_reshard_process set migrating_slot = #{migratingSlot} where id = #{id}\n    </update>\n\n</mapper>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/mapper/InstanceSlowLogDao.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.sohu.cache.dao.InstanceSlowLogDao\">\n\n    <sql id=\"instance_slow_log_columns\">\n        instance_id,app_id,ip,port,slow_log_id,cost_time,command,execute_time,create_time\n    </sql>\n\n    <insert id=\"batchSave\">\n        insert ignore into instance_slow_log(<include refid=\"instance_slow_log_columns\"/>)\n        values\n        <foreach collection=\"instanceSlowLogList\" item=\"instanceSlowLog\" separator=\",\">\n        \t(#{instanceSlowLog.instanceId},#{instanceSlowLog.appId},#{instanceSlowLog.ip},#{instanceSlowLog.port},#{instanceSlowLog.slowLogId},#{instanceSlowLog.costTime},#{instanceSlowLog.command},#{instanceSlowLog.executeTime},#{instanceSlowLog.createTime})\n\t    </foreach>\n    </insert>\n    \n    <select id=\"getByAppId\" resultType=\"InstanceSlowLog\">\n        select id,<include refid=\"instance_slow_log_columns\"/>\n        from instance_slow_log where app_id = #{appId}\n    </select>\n    \n    \n    <select id=\"search\" resultType=\"InstanceSlowLog\">\n        select id,<include refid=\"instance_slow_log_columns\"/>\n        from instance_slow_log where app_id = #{appId} and create_time between DATE_FORMAT(#{startDate}, '%Y-%m-%d') and DATE_FORMAT(#{endDate}, '%Y-%m-%d') order by execute_time desc\n    </select>\n    \n    <select id=\"getInstanceSlowLogCountMapByAppId\" resultType=\"hashmap\">\n        select concat(ip,\":\",port) as hostPort,count(*) as count\n        from instance_slow_log where app_id = #{appId} and create_time between DATE_FORMAT(#{startDate}, '%Y-%m-%d') and DATE_FORMAT(#{endDate}, '%Y-%m-%d') group by hostPort order by count desc\n    </select>\n    \n    <select id=\"getAppSlowLogCount\" resultType=\"int\">\n        select count(*) as count\n        from instance_slow_log where app_id = #{appId} and execute_time between DATE_FORMAT(#{startDate}, '%Y-%m-%d') and DATE_FORMAT(#{endDate}, '%Y-%m-%d')\n    </select>\n\n</mapper>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/mapper/InstanceStatsDao.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.sohu.cache.dao.InstanceStatsDao\">\n\n    <sql id=\"instance_statistics_columns\">\n        inst_id,app_id,host_id,ip,port,role,max_memory,used_memory,curr_items,curr_connections,misses,hits,modify_time,mem_fragmentation_ratio,aof_delayed_fsync\n    </sql>\n\n    <insert id=\"updateInstanceStats\" parameterType=\"InstanceStats\">\n        INSERT INTO instance_statistics\n          (<include refid=\"instance_statistics_columns\"/>)\n        VALUES (#{instId},#{appId},#{hostId},#{ip},#{port},#{role},#{maxMemory},#{usedMemory},#{currItems},#{currConnections},#{misses},#{hits},\n                  #{modifyTime},#{memFragmentationRatio},#{aofDelayedFsync})\n        ON DUPLICATE KEY UPDATE\n          inst_id = #{instId},\n          host_id = #{hostId},\n          role = #{role},\n          max_memory = #{maxMemory},\n          used_memory = #{usedMemory},\n          curr_items = #{currItems},\n          curr_connections = #{currConnections},\n          misses = #{misses},\n          hits = #{hits},\n          modify_time = #{modifyTime},\n          mem_fragmentation_ratio = #{memFragmentationRatio},\n          aof_delayed_fsync = #{aofDelayedFsync}\n    </insert>\n\n    <select id=\"getInstanceStatsByHost\" resultType=\"InstanceStats\">\n        select id,<include refid=\"instance_statistics_columns\"/>\n        from instance_statistics\n        where ip = #{ip} and port = #{port}\n    </select>\n\n    <select id=\"getInstanceStatsByIp\" resultType=\"InstanceStats\">\n        select id,<include refid=\"instance_statistics_columns\"/>\n        from instance_statistics\n        where ip = #{ip}\n    </select>\n\n    <select id=\"getInstanceStatsByInsId\" resultType=\"InstanceStats\">\n        select id,<include refid=\"instance_statistics_columns\"/>\n        from instance_statistics\n        where inst_id = #{id}\n    </select>\n\n    <select id=\"getInstanceStatsByAppId\" resultType=\"InstanceStats\">\n        select id,<include refid=\"instance_statistics_columns\"/>\n        from instance_statistics\n        where app_id = #{appId}\n    </select>\n\n    <select id=\"getInstanceStats\" resultType=\"InstanceStats\">\n        select id,<include refid=\"instance_statistics_columns\"/>\n        from instance_statistics\n    </select>\n\n    <insert id=\"mergeStandardStats\" parameterType=\"StandardStats\">\n        replace into standard_statistics(collect_time,ip,port,db_type,info_json,diff_json,cluster_info_json)\n        values (#{collectTime},#{ip},#{port},#{dbType},#{infoJson},#{diffJson},#{clusterInfoJson})\n    </insert>\n\n    <select id=\"getStandardStats\" resultType=\"StandardStats\">\n        select id,collect_time,ip,port,db_type,info_json,diff_json,cluster_info_json,created_time\n        from standard_statistics\n        where  ip=#{ip} and port=#{port} and db_type=#{dbType}\n          and collect_time = #{collectTime}\n    </select>\n\n    <select id=\"getDiffJsonList\" resultType=\"StandardStats\">\n        select collect_time,diff_json\n        from standard_statistics\n        where  ip=#{ip} and port=#{port} and db_type=#{dbType}\n        and collect_time between #{beginTime} and #{endTime}\n    </select>\n\n    <delete id=\"deleteStandardStatsByCreatedTime\">\n        delete\n        from standard_statistics\n        where <![CDATA[ created_time <=  #{createdTime}]]>\n    </delete>\n\n    <delete id=\"deleteStandardStatsByScanTime\">\n        DELETE FROM standard_statistics\n        where created_time BETWEEN #{startTime} AND #{endTime}\n    </delete>\n    \n    <select id=\"getStandardStatsByCreateTime\" resultType=\"StandardStats\">\n        select id,collect_time,ip,port,db_type,info_json,diff_json,cluster_info_json,created_time\n        from standard_statistics\n        where created_time between #{beginTime} and #{endTime} and db_type=#{dbType}\n    </select>\n    \n\n</mapper>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/mapper/MachineDao.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.sohu.cache.dao.MachineDao\">\n    <sql id=\"machine_info_columns\">\n        ssh_user,ssh_passwd,ip,room,mem,cpu,`virtual`,real_ip,service_time,fault_count,warn,available,type,groupId,extra_desc,collect\n    </sql>\n\n    <sql id=\"machine_info_fields\">\n        #{sshUser},#{sshPasswd},#{ip},#{room},#{mem},#{cpu},#{virtual},#{realIp},#{serviceTime},\n        #{faultCount},#{warn},#{available},#{type},#{groupId},#{extraDesc},#{collect}\n    </sql>\n\n    <!--返回所有可用的机器资源-->\n    <select id=\"getAllMachines\" resultType=\"MachineInfo\">\n        select\n        id, modify_time, <include refid=\"machine_info_columns\"/>\n        from machine_info\n        where available = 1\n    </select>\n\n    <!--通过ip查找机器-->\n    <select id=\"getMachineInfoByIp\" resultType=\"MachineInfo\">\n        select\n          id, modify_time, <include refid=\"machine_info_columns\"/>\n        from machine_info\n        where ip = #{ip};\n    </select>\n    \n    <!--通过ip查找机器-->\n    <select id=\"getMachineInfoByLikeIp\" resultType=\"MachineInfo\">\n        select\n          id, modify_time, <include refid=\"machine_info_columns\"/>\n        from machine_info where available = 1\n        <choose>\n            <when test=\"ipLike != '' and ipLike != null\">\n                and ip like '%${ipLike}%'\n            </when>\n        </choose>\n    </select>\n\n    <!--保存机器信息-->\n    <insert id=\"saveMachineInfo\" parameterType=\"MachineInfo\">\n        insert into machine_info\n          (<include refid=\"machine_info_columns\"/>)\n        values\n          (<include refid=\"machine_info_fields\"/>)\n        on duplicate key \n        update ssh_user=#{sshUser},ssh_passwd=#{sshPasswd},room=#{room},mem=#{mem},cpu=#{cpu},\n        `virtual`=#{virtual},real_ip=#{realIp},service_time=#{serviceTime},fault_count=#{faultCount},\n        warn=#{warn},available=#{available},type=#{type},groupId=#{groupId},extra_desc=#{extraDesc},collect=#{collect}\n    </insert>\n    \n    <!--根据ip删除一台机器的信息:置无效-->\n    <update id=\"removeMachineInfoByIp\" parameterType=\"string\">\n        update machine_info set available = 0 WHERE ip = #{ip}\n    </update>\n    \n    <!--通过type查找机器-->\n    <select id=\"getMachineInfoByType\" resultType=\"MachineInfo\">\n        select\n          id, modify_time, <include refid=\"machine_info_columns\"/>\n        from machine_info where type = #{type} and available = 1\n    </select>\n    \n    <!-- 更新机器类型 -->\n    <update id=\"updateMachineType\">\n    \tupdate machine_info set type = #{type} where id = #{id}\n    </update>\n    \n</mapper>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/mapper/MachineStatsDao.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.sohu.cache.dao.MachineStatsDao\">\n\n    <sql id=\"machine_statistics_columns\">\n        ip,host_id,cpu_usage,`load`,traffic,memory_usage_ratio,memory_free,memory_total,modify_time\n    </sql>\n\n    <sql id=\"instance_info_columns\">\n        instance.id, instance.parent_id, instance.app_id, instance.host_id, instance.ip, instance.PORT, instance.STATUS, instance.mem, instance.conn, instance.cmd, instance.type\n    </sql>\n\n    <!--保存机器当前最新的统计信息-->\n    <insert id=\"mergeMachineStats\" parameterType=\"MachineStats\">\n        insert into machine_statistics\n          (<include refid=\"machine_statistics_columns\"/>)\n        values\n          (#{ip},#{hostId},#{cpuUsage},#{load},#{traffic},#{memoryUsageRatio},#{memoryFree},#{memoryTotal},#{modifyTime})\n        on duplicate key update\n           host_id = #{hostId},\n           cpu_usage = #{cpuUsage},\n           `load` = #{load},\n           traffic = #{traffic},\n           memory_usage_ratio = #{memoryUsageRatio},\n           memory_free = #{memoryFree},\n           memory_total = #{memoryTotal},\n           modify_time = #{modifyTime}\n    </insert>\n\n    <!--查询机器下的所有实例的静态信息-->\n    <select id=\"getInstInfoOfMachine\" resultType=\"InstanceInfo\">\n        SELECT\n           <include refid=\"instance_info_columns\"/>\n        FROM\n            machine_info AS machine,\n            instance_info AS instance\n        WHERE\n            machine.id = instance.host_id\n        AND machine.ip = instance.ip\n        AND machine.available = 1\n        AND machine.ip = #{ip}\n    </select>\n\n    <!--查询机器下的所有实例的最新状态信息-->\n    <select id=\"getInstStatOfMachine\" resultType=\"InstanceStats\" parameterType=\"long\">\n        SELECT istat.*\n        FROM machine_statistics as mstat, instance_statistics AS istat\n        WHERE mstat.host_id = #{hostId}\n        AND mstat.host_id = istat.host_id\n        ORDER BY istat.max_memory DESC;\n    </select>\n\n    <!--查询当前机器资源池中所有有效的机器-->\n    <!--<select id=\"getAllMachines\" resultType=\"MachineInfo\">-->\n        <!--SELECT minfo.*-->\n        <!--FROM machine_info as minfo-->\n        <!--WHERE minfo.available = 1;-->\n    <!--</select>-->\n\n    <select id=\"getMachineStats\" resultType=\"MachineStats\">\n        select\n          id,<include refid=\"machine_statistics_columns\"/>\n        from machine_statistics\n        <choose>\n            <when test=\"ipLike != '' and ipLike != null\">\n                where ip like '%${ipLike}%'\n            </when>\n        </choose>\n    </select>\n    \n    <select id=\"getAllMachineStats\" resultType=\"MachineStats\">\n        select\n          id,<include refid=\"machine_statistics_columns\"/>\n        from machine_statistics\n    </select>\n\n    <!--根据机器的ip查询机器的最新状态信息-->\n    <select id=\"getMachineStatsByIp\" resultType=\"MachineStats\">\n        select\n          id,<include refid=\"machine_statistics_columns\"/>\n        from machine_statistics\n        where ip = #{ip};\n    </select>\n\n    <!--根据机器的hostId查询机器的最新状态信息-->\n    <select id=\"getMachineStatsByHostId\" resultType=\"MachineStats\" parameterType=\"long\">\n        select\n          id,<include refid=\"machine_statistics_columns\"/>\n        from machine_statistics\n        where host_id = #{hostId};\n    </select>\n    \n    <!-- 删除机器统计信息 -->\n    <delete id=\"deleteMachineStatsByIp\" parameterType=\"string\">\n    \tdelete from machine_statistics where ip = #{ip};\n    </delete>\n\n\n</mapper>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/mapper/QuartzDao.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n\n<mapper namespace=\"com.sohu.cache.dao.QuartzDao\">\n    <sql id=\"quartz_triggers_columns\">\n        t.SCHED_NAME,t.TRIGGER_NAME,t.TRIGGER_GROUP,t.JOB_NAME,t.JOB_GROUP,t.DESCRIPTION,t.NEXT_FIRE_TIME,t.PREV_FIRE_TIME,t.PRIORITY,\n        t.TRIGGER_STATE,t.TRIGGER_TYPE,t.START_TIME,t.END_TIME,t.CALENDAR_NAME,t.MISFIRE_INSTR\n    </sql>\n\n    <!--查询job分组下的所有trigger-->\n    <select id=\"getTriggersByJobGroup\" resultType=\"TriggerInfo\" parameterType=\"String\">\n        SELECT <include refid=\"quartz_triggers_columns\"/>\n        FROM QRTZ_TRIGGERS t\n        WHERE JOB_GROUP = #{jobGroup};\n    </select>\n\n    <!--返回所有trigger-->\n    <select id=\"getAllTriggers\" resultType=\"TriggerInfo\">\n        SELECT <include refid=\"quartz_triggers_columns\"/>, ifnull(ct.CRON_EXPRESSION,'') cron\n        FROM QRTZ_TRIGGERS t\n        LEFT JOIN QRTZ_CRON_TRIGGERS ct\n        on (t.SCHED_NAME = ct.SCHED_NAME and t.TRIGGER_NAME = ct.TRIGGER_NAME and t.TRIGGER_GROUP=ct.TRIGGER_GROUP)\n    </select>\n\n    <!--查询trigger：模糊匹配trigger name或trigger group-->\n    <select id=\"searchTriggerByNameOrGroup\" resultType=\"TriggerInfo\" parameterType=\"String\">\n        SELECT <include refid=\"quartz_triggers_columns\"/>, ifnull(ct.CRON_EXPRESSION,'') cron\n        FROM QRTZ_TRIGGERS t\n        LEFT JOIN QRTZ_CRON_TRIGGERS ct\n        on (t.SCHED_NAME = ct.SCHED_NAME and t.TRIGGER_NAME = ct.TRIGGER_NAME and t.TRIGGER_GROUP=ct.TRIGGER_GROUP)\n        WHERE t.TRIGGER_NAME REGEXP #{queryString}\n        OR t.TRIGGER_GROUP REGEXP #{queryString};\n    </select>\n\n</mapper>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/mapper/ServerStatusDao.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n\n<mapper namespace=\"com.sohu.cache.dao.ServerStatusDao\">\n\t\n\t<!-- 获取服务器信息 -->\n    <select id=\"queryServerInfo\" resultType=\"ServerInfo\">\n    \tselect ip,host,nmon,cpus,cpu_model cpuModel,dist,kernel,ulimit\n        from server where ip=#{ip}\n    </select>\n    \n    <!-- 保存服务器发行版信息 -->\n    <insert id=\"saveServerInfo\">\n    \tinsert ignore into server(ip,dist) values (#{ip},#{dist})\n    </insert>\n    \n    <!-- 删除服务器信息 -->\n    <select id=\"deleteServerInfo\">\n    \tdelete from server where ip=#{ip}\n    </select>\n    \n    <!-- 保存/更新服务器信息 -->\n    <insert id=\"saveAndUpdateServerInfo\">\n    \tinsert into server (ip,host,nmon,cpus,cpu_model,kernel,ulimit) \n\t\tvalues (#{server.ip},#{server.host},#{server.nmon},#{server.cpus},#{server.cpuModel},#{server.kernel},#{server.ulimit})\n\t\ton duplicate key update host=values(host), nmon=values(nmon), cpus=values(cpus),\n\t\tcpu_model=values(cpu_model), kernel=values(kernel), ulimit=values(ulimit)\n    </insert>\n    \n    <!-- 获取服务器状态 -->\n    <select id=\"queryServerOverview\" resultType=\"ServerStatus\">\n    \tselect ip,cdate,ctime,cuser,csys,cwio,cload1,cload5,cload15,\n\t\t\t   mtotal,mfree,mcache,mbuffer,mswap,mswap_free mswapFree,\n\t\t\t   nin,nout,tuse,torphan,twait,\n\t\t\t   dread,dwrite,diops,dbusy\n\t\tfrom server_stat\n\t\twhere ip=#{ip} and cdate=#{cdate}\n    </select>\n    \n    <!-- 获取服务器cpu状态 -->\n    <select id=\"queryServerCpu\" resultType=\"ServerStatus\">\n    \tselect ctime, c_ext cExt\n\t\tfrom server_stat\n\t\twhere ip=#{ip} and cdate=#{cdate}\n    </select>\n    \n    <!-- 获取服务器net状态 -->\n    <select id=\"queryServerNet\" resultType=\"ServerStatus\">\n    \tselect ctime, nin_ext ninExt,nout_ext noutExt\n\t\tfrom server_stat\n\t\twhere ip=#{ip} and cdate=#{cdate}\n    </select>\n    \n    <!-- 获取服务器disk状态 -->\n    <select id=\"queryServerDisk\" resultType=\"ServerStatus\">\n    \tselect ctime, d_ext dExt,dspace\n\t\tfrom server_stat\n\t\twhere ip=#{ip} and cdate=#{cdate}\n    </select>\n    \n    <!-- 获取服务器状态 -->\n    <select id=\"queryServerStat\" resultType=\"ServerStatus\">\n    \tselect ip,cdate,ctime,cuser,csys,cwio,c_ext cExt,cload1,cload5,cload15,\n\t\t\t   mtotal,mfree,mcache,mbuffer,mswap,mswap_free mswapFree,\n\t\t\t   nin,nout,nin_ext ninExt,nout_ext noutExt,tuse,torphan,twait,\n\t\t\t   dread,dwrite,diops,dbusy,d_ext dExt,dspace\"\n\t\tfrom server_stat\n\t\twhere ip=#{ip} and cdate=#{cdate}\n    </select>\n    \n    <!-- 保存服务器状态-->\n    <insert id=\"saveServerStat\">\n    \tinsert ignore into server_stat(ip,cdate,ctime,cuser,csys,cwio,c_ext,\n    \t\t   cload1,cload5,cload15,\n    \t\t   mtotal,mfree,mcache,mbuffer,mswap,mswap_free,\n    \t\t   nin,nout,nin_ext,nout_ext,\n    \t\t   tuse,torphan,twait,\n    \t\t   dread,dwrite,diops,dbusy,d_ext,dspace)\n     \tvalues(#{server.ip},#{server.collectTime},#{server.time},\n     \t\t   #{server.cpu.user},#{server.cpu.sys},#{server.cpu.wait},#{server.cpu.ext},\n     \t\t   #{server.load.load1},#{server.load.load5},#{server.load.load15},\n     \t\t   #{server.mem.total},#{server.mem.totalFree},#{server.mem.cache},\n     \t\t   #{server.mem.buffer},#{server.mem.swap},#{server.mem.swapFree},\n     \t\t   #{server.net.nin},#{server.net.nout},#{server.net.ninDetail},#{server.net.noutDetail},\n     \t\t   #{server.connection.established},#{server.connection.orphan},#{server.connection.timeWait},\n     \t\t   #{server.disk.read},#{server.disk.write},#{server.disk.iops},#{server.disk.busy},\n     \t\t   #{server.disk.ext},#{server.disk.space})\n    </insert>\n</mapper>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/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\"\n        \"http://mybatis.org/dtd/mybatis-3-config.dtd\">\n\n<configuration>\n\n    <!--数据库的字段名到pojo类的属性名的自动映射-->\n    <settings>\n        <!-- 使用jdbc的getGeneratedKeys自动获取主键主键策略:默认false -->\n        <setting name=\"useGeneratedKeys\" value=\"true\"/>\n        <!-- 使用列别名代替列名,默认true -->\n        <setting name=\"useColumnLabel\" value=\"true\"/>\n        <!-- 开启自动驼峰-下划线命名规则,默认false: Table(create_time) -> Entity(createTime) -->\n        <setting name=\"mapUnderscoreToCamelCase\" value=\"true\"/>\n    </settings>\n\n</configuration>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/spring/spring-alert.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\n        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd\n        \" default-autowire=\"byName\">\n\n\t<bean id=\"baseAlertService\" class=\"com.sohu.cache.alert.impl.BaseAlertService\"/>\n\n\t<!-- 应用报警 -->\n    <bean id=\"appAlertService\" class=\"com.sohu.cache.alert.impl.AppAlertServiceImpl\" parent=\"baseAlertService\"/>\n\n\t<!-- 实例报警 -->\n    <bean id=\"instanceAlertService\" class=\"com.sohu.cache.alert.impl.InstanceAlertServiceImpl\" parent=\"baseAlertService\"/>\n\n</beans>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/spring/spring-client-report.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<beans xmlns=\"http://www.springframework.org/schema/beans\"\n\txmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:util=\"http://www.springframework.org/schema/util\"\n\txsi:schemaLocation=\"http://www.springframework.org/schema/beans\n                     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd\"\n\tdefault-autowire=\"byName\">\n\t\n\t<!-- 处理上报数据接口 -->\n\t<bean id=\"clientReportDataService\"\n\t\tclass=\"com.sohu.cache.client.service.impl.ClientReportDataServiceImpl\"\n\t\tinit-method=\"init\" />\n\n\t<!-- 耗时分布  -->\n\t<bean id=\"clientReportCostDistriService\"\n\t\tclass=\"com.sohu.cache.client.service.impl.ClientReportCostDistriServiceImpl\" />\n\t<!-- 客户端异常 -->\n\t<bean id=\"clientReportExceptionService\"\n\t\tclass=\"com.sohu.cache.client.service.impl.ClientReportExceptionServiceImpl\" />\n\t<!-- 值分布 -->\n\t<bean id=\"clientReportValueDistriService\"\n\t\tclass=\"com.sohu.cache.client.service.impl.ClientReportValueDistriServiceImplV2\" />\n\t<!-- 客户端统计map大小统计，防止内存泄露 -->\n\t<bean id=\"clientReportDataSizeService\"\n\t\tclass=\"com.sohu.cache.client.service.impl.ClientReportDataSizeServiceImpl\"/>\n\t\t\n\t<!-- 客户端版本收集 -->\n\t<bean id=\"clientVersionService\" class=\"com.sohu.cache.client.service.impl.ClientVersionServiceImpl\"/>\n\t\n\t<!-- 应用下节点和客户端对应关系 -->\n\t<bean id=\"appInstanceClientRelationService\" class=\"com.sohu.cache.client.service.impl.AppInstanceClientRelationServiceImpl\"/>\n\t\n\t<bean id=\"clientReportInstanceService\" class=\"com.sohu.cache.client.service.impl.ClientReportInstanceServiceImpl\"/>\n\n</beans>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/spring/spring-config.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\n        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd\n        \" default-autowire=\"byName\">\n\n\t<bean id=\"configService\" class=\"com.sohu.cache.web.service.impl.ConfigServiceImpl\" init-method=\"init\"/>\n\t\n</beans>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/spring/spring-data.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\n        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd\" default-autowire=\"byName\">\n\n\n    <bean id=\"jdbcTemplate\" class=\"org.springframework.jdbc.core.JdbcTemplate\">\n        <property name=\"dataSource\" ref=\"cacheCloudDB\"/>\n    </bean>\n\n    <bean name=\"transactionManager\" class=\"org.springframework.jdbc.datasource.DataSourceTransactionManager\">\n        <property name=\"dataSource\" ref=\"cacheCloudDB\"/>\n    </bean>\n\n</beans>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/spring/spring-inspector.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\n        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd\" default-autowire=\"byName\">\n\n    <bean id=\"hostInspectHandler\" class=\"com.sohu.cache.inspect.impl.HostInspectHandler\" init-method=\"init\">\n        <property name=\"inspectorList\">\n            <list>\n                <bean class=\"com.sohu.cache.inspect.impl.InstanceRunInspector\"/>\n                <bean class=\"com.sohu.cache.inspect.impl.RedisIsolationPersistenceInspector\"/>\n            </list>\n        </property>\n    </bean>\n\n    <bean id=\"appInspectHandler\" class=\"com.sohu.cache.inspect.impl.AppInspectHandler\" init-method=\"init\">\n        <property name=\"inspectorList\">\n        \t<list>\n        \t\t<bean class=\"com.sohu.cache.inspect.impl.AppMemInspector\"/>\n            \t<bean class=\"com.sohu.cache.inspect.impl.AppClientConnInspector\"/>\n        \t</list>\n        </property>\n    </bean>\n\n</beans>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/spring/spring-jmx.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:util=\"http://www.springframework.org/schema/util\"\n       xsi:schemaLocation=\"http://www.springframework.org/schema/beans\n                     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd\n                     http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd\"\n       default-autowire=\"byName\">\n\n\t<!-- mbeanServer用于注册mbean -->\n    <bean id=\"mbeanServer\" class=\"org.springframework.jmx.support.MBeanServerFactoryBean\">\n        <property name=\"locateExistingServerIfPossible\" value=\"true\"/>\n    </bean>\n\t\n\t<!-- 异常统计 -->\n    <bean id=\"errorLoggerWatcher\" class=\"com.sohu.cache.jmx.ErrorLoggerWatcher\" init-method=\"init\"/>\n          \n    <!-- cachecloud数据监控 -->\n    <bean id=\"cachecloudDataWatcher\" class=\"com.sohu.tv.cache.client.common.jmx.CachecloudDataWatcher\"/>\n    \n    <!-- 客户端上报jmx -->\n    <bean id=\"clientReportAsyncThreadPoolStatistics\" class=\"com.sohu.cache.jmx.ThreadPoolStatisticsImpl\">\n        <constructor-arg index=\"0\">\n            <util:constant static-field=\"com.sohu.cache.async.AsyncThreadPoolFactory.CLIENT_REPORT_THREAD_POOL\"/>\n        </constructor-arg>\n    </bean>\n    \n    <!-- 实例慢查询jmx -->\n    <bean id=\"redisSlowlogAsyncThreadPoolStatistics\" class=\"com.sohu.cache.jmx.ThreadPoolStatisticsImpl\">\n        <constructor-arg index=\"0\">\n            <util:constant static-field=\"com.sohu.cache.async.AsyncThreadPoolFactory.REDIS_SLOWLOG_THREAD_POOL\"/>\n        </constructor-arg>\n    </bean>\n\n\t<!-- mbeanServerExporter -->\n    <bean id=\"mbeanServerExporter\" class=\"org.springframework.jmx.export.MBeanExporter\">\n        <property name=\"beans\">\n            <map>\n                <entry key=\"cacheCloudJMX:myjavaobj=errorLoggerWatcher\" value-ref=\"errorLoggerWatcher\"/>\n                <entry key=\"cacheCloudJMX:myjavaobj=cachecloudDataWatcher\" value-ref=\"cachecloudDataWatcher\"/>\n                <entry key=\"cacheCloudJMX:myjavaobj=clientReportAsyncThreadPoolStatistics\" value-ref=\"clientReportAsyncThreadPoolStatistics\"/>\n                <entry key=\"cacheCloudJMX:myjavaobj=redisSlowlogAsyncThreadPoolStatistics\" value-ref=\"redisSlowlogAsyncThreadPoolStatistics\"/>\n            </map>\n        </property>\n        <property name=\"server\" ref=\"mbeanServer\"/>\n        <property name=\"assembler\" ref=\"assembler\"/>\n    </bean>\n\n\t<!-- 接口集合 -->\n    <bean id=\"assembler\" class=\"org.springframework.jmx.export.assembler.InterfaceBasedMBeanInfoAssembler\">\n        <property name=\"managedInterfaces\">\n            <list>\n                <value>com.sohu.cache.jmx.ErrorLoggerWatcherMBean</value>\n                <value>com.sohu.tv.cache.client.common.jmx.CachecloudDataWatcherMBean</value>\n                <value>com.sohu.cache.jmx.ThreadPoolStatisticsMBean</value>\n            </list>\n        </property>\n    </bean>\n\n</beans>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/spring/spring-load.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\n        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd\n        \" default-autowire=\"byName\">\n\n    <!--初始化加载已有实例，测试时禁用-->\n    <bean class=\"com.sohu.cache.init.RedisInitLoad\" init-method=\"init\" />\n    <bean class=\"com.sohu.cache.init.MachineInitLoad\" init-method=\"init\" />\n</beans>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/spring/spring-local.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\n        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd\">\n    <import resource=\"classpath:spring/spring-config.xml\"/>\n    <import resource=\"classpath:spring/spring-quartz.xml\"/>\n    <import resource=\"classpath:spring/spring-mybatis.xml\"/>\n    <import resource=\"classpath:spring/spring-service.xml\"/>\n    <import resource=\"classpath:spring/spring-data.xml\"/>\n    <import resource=\"classpath:spring/spring-manage.xml\"/>\n    <import resource=\"classpath:spring/spring-mvc.xml\"/>\n\t<import resource=\"classpath:spring/spring-jmx.xml\"/>\n\t<import resource=\"classpath:spring/spring-alert.xml\"/>\n\t<import resource=\"classpath:spring/spring-client-report.xml\"/>\n\t<import resource=\"classpath:spring/spring-inspector.xml\"/>\n</beans>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/spring/spring-manage.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:util=\"http://www.springframework.org/schema/util\"\n       xsi:schemaLocation=\"http://www.springframework.org/schema/beans\n                     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd\"\n       default-autowire=\"byName\">\n\n    <bean id=\"appService\" class=\"com.sohu.cache.web.service.impl.AppServiceImpl\"/>\n\n    <bean id=\"memFaultService\" class=\"com.sohu.cache.web.service.impl.MemFaultServiceImpl\"/>\n\n    <bean id=\"userService\" class=\"com.sohu.cache.web.service.impl.UserServiceImpl\"/>\n\n\t<!-- 邮件报警 -->\n    <bean id=\"emailComponent\" class=\"com.sohu.cache.web.component.EmailComponentImpl\"/>\n\n\t<!-- 短信报警 -->\n\t<bean id=\"mobileAlertComponent\" class=\"com.sohu.cache.web.component.MobileAlertComponentImpl\"/>\n\t\n\t<!-- 应用相关审核变更通知 -->\n    <bean id=\"appEmailUtil\" class=\"com.sohu.cache.web.util.AppEmailUtil\"/>\n    \n    <!-- 登录状态相关cookie和session根据配置切换 -->\n    <bean id=\"userLoginStatusSessionService\" class=\"com.sohu.cache.web.service.impl.UserLoginStatusSessionServiceImpl\"/>\n    <bean id=\"userLoginStatusCookieService\" class=\"com.sohu.cache.web.service.impl.UserLoginStatusCookieServiceImpl\"/>\n    \n    <util:map id=\"userloginTypeMap\" key-type=\"com.sohu.cache.constant.UserLoginTypeEnum\" value-type=\"com.sohu.cache.web.service.UserLoginStatusService\">\n        <entry key=\"SESSION\" value-ref=\"userLoginStatusSessionService\"/>\n        <entry key=\"COOKIE\" value-ref=\"userLoginStatusCookieService\"/>\n    </util:map>\n    <bean id=\"userLoginStatusFactory\" class=\"com.sohu.cache.web.factory.UserLoginStatusFactory\">\n    \t<property name=\"userloginTypeMap\" ref=\"userloginTypeMap\"></property>\n    </bean>\n    <bean id=\"userLoginStatusService\" factory-bean=\"userLoginStatusFactory\" factory-method=\"getUserLoginStatusService\"/>\n\t\n\t<bean id=\"appDailyDataCenter\" class=\"com.sohu.cache.stats.app.impl.AppDailyDataCenterImpl\"/>\n\t\n</beans>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/spring/spring-mvc.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       xmlns:mvc=\"http://www.springframework.org/schema/mvc\"\n       xsi:schemaLocation=\"http://www.springframework.org/schema/beans\n        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd\n        http://www.springframework.org/schema/context\n        http://www.springframework.org/schema/context/spring-context-3.0.xsd\n        http://www.springframework.org/schema/mvc\n        http://www.springframework.org/schema/mvc/spring-mvc.xsd\" default-autowire=\"byName\">\n\n    <mvc:annotation-driven/>\n\n    <mvc:resources mapping=\"/resources/**\" location=\"/WEB-INF/resources/\"/>\n    <mvc:resources mapping=\"/assets/flash/**\" location=\"/WEB-INF/resources/assets/flash/\"/>\n\n    <!--\n    <mvc:annotation-driven/>\n    <mvc:default-servlet-handler default-servlet-name=\"default\"/>\n    <mvc:resources mapping=\"/resources/**\" location=\"/resources/\"/>\n    <bean class=\"org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter\"/>\n    <mvc:resources mapping=\"/assets/flash/**\" location=\"/resources/assets/flash/\"/>\n    -->\n\n    <mvc:interceptors>\n        <!-- 前台验证 -->\n        <mvc:interceptor>\n            <mvc:mapping path=\"/admin/app/*\"/>\n            <mvc:mapping path=\"/admin/instance/*\"/>\n            <mvc:mapping path=\"/client/show/*\"/>\n            <mvc:mapping path=\"/server/*\"/>\n            <bean class=\"com.sohu.cache.interceptor.FrontUserLoginInterceptor\"/>\n        </mvc:interceptor>\n        <!-- 后台管理员验证 -->\n        <mvc:interceptor>\n            <mvc:mapping path=\"/manage/app/*\"/>\n            <mvc:mapping path=\"/manage/instance/*\"/>\n            <mvc:mapping path=\"/manage/user/*\"/>\n            <mvc:mapping path=\"/manage/quartz/*\"/>\n            <mvc:mapping path=\"/manage/total/*\"/>\n            <mvc:mapping path=\"/manage/machine/*\"/>\n            <mvc:mapping path=\"/manage/notice/*\"/>\n            <mvc:mapping path=\"/import/app/*\"/>\n            <mvc:mapping path=\"/manage/config/*\"/>\n            <mvc:mapping path=\"/data/migrate/*\"/>\n            <mvc:mapping path=\"/manage/redisConfig/*\"/>\n            <mvc:mapping path=\"/manage/instanceAlert/*\"/>\n            <bean class=\"com.sohu.cache.interceptor.ManageUserLoginInterceptor\"/>\n        </mvc:interceptor>\n        <!-- 应用和实例权限验证 -->\n        <mvc:interceptor>\n            <mvc:mapping path=\"/admin/app/*\"/>\n            <mvc:mapping path=\"/admin/instance/*\"/>\n            <bean class=\"com.sohu.cache.interceptor.AppAndInstanceAuthorityInterceptor\"/>\n        </mvc:interceptor>\n    </mvc:interceptors>\n\n    <bean class=\"org.springframework.web.servlet.view.ContentNegotiatingViewResolver\">\n        <property name=\"order\" value=\"1\"/>\n        <property name=\"contentNegotiationManager\">\n            <bean class=\"org.springframework.web.accept.ContentNegotiationManager\">\n                <constructor-arg>\n                    <bean class=\"org.springframework.web.accept.PathExtensionContentNegotiationStrategy\">\n                        <constructor-arg>\n                            <map>\n                                <entry key=\"json\" value=\"application/json\"/>\n                            </map>\n                        </constructor-arg>\n                    </bean>\n                </constructor-arg>\n            </bean>\n        </property>\n        <property name=\"defaultViews\">\n            <list>\n                <bean class=\"org.springframework.web.servlet.view.json.MappingJackson2JsonView\"/>\n            </list>\n        </property>\n    </bean>\n\n    <bean class=\"org.springframework.web.servlet.view.InternalResourceViewResolver\">\n        <property name=\"order\" value=\"2\"/>\n        <property name=\"viewClass\" value=\"org.springframework.web.servlet.view.JstlView\"/>\n        <property name=\"prefix\" value=\"/WEB-INF/jsp/\"/>\n        <property name=\"suffix\" value=\".jsp\"/>\n    </bean>\n\n    <context:component-scan base-package=\"com.sohu.cache.client.heartbeat,com.sohu.cache.web.controller\"/>\n\n\n\n</beans>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/spring/spring-mybatis.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\n                     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd\n                     http://www.springframework.org/schema/context\n                     http://www.springframework.org/schema/context/spring-context.xsd\">\n\n    <context:property-placeholder location=\"classpath:application.properties\"/>\n\n    <!--cache data source-->\n    <bean name=\"cacheCloudDB\" class=\"com.mchange.v2.c3p0.ComboPooledDataSource\">\n        <property name=\"driverClass\" value=\"${jdbc.driver}\"/>\n        <property name=\"jdbcUrl\" value=\"${cachecloud.db.url}\"/>\n        <property name=\"user\" value=\"${cachecloud.db.user}\"/>\n        <property name=\"password\" value=\"${cachecloud.db.password}\"/>\n        <property name=\"initialPoolSize\" value=\"10\"/>\n        <property name=\"maxPoolSize\" value=\"${cachecloud.maxPoolSize}\"/>\n        <property name=\"testConnectionOnCheckin\" value=\"false\"/>\n        <property name=\"testConnectionOnCheckout\" value=\"true\"/>\n        <property name=\"preferredTestQuery\" value=\"${jdbc.validationQuery}\"/>\n    </bean>\n\n    <bean id=\"mysqlSessionFactory\" class=\"com.sohu.cache.app.AliasesResourceSqlSessionFactoryBean\">\n        <property name=\"dataSource\" ref=\"cacheCloudDB\"/>\n        <!-- mybatis配置文件的位置 -->\n        <property name=\"configLocation\" value=\"classpath:mybatis-config.xml\"/>\n        <!-- domain的包路径，类似MyBatis的typeAliases配置 -->\n        <property name=\"typeAliasesPackage\" value=\"com.sohu.cache.entity\"/>\n        <property name=\"typeAliasesClassResources\">\n            <array>\n                <value>classpath:com/sohu/cache/entity/*</value>\n            </array>\n        </property>\n        <!-- mapper配置文件的路径，类似MyBatis的mappers配置 -->\n        <property name=\"mapperLocations\" value=\"classpath:mapper/*.xml\"/>\n    </bean>\n\n    <!-- 扫描接口类的包路径 -->\n    <bean class=\"org.mybatis.spring.mapper.MapperScannerConfigurer\">\n        <property name=\"sqlSessionFactoryBeanName\" value=\"mysqlSessionFactory\"/>\n        <property name=\"basePackage\" value=\"com.sohu.cache.dao\"/>\n    </bean>\n</beans>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/spring/spring-online.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\n        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd\">\n    <import resource=\"classpath:spring/spring-config.xml\"/>\n    <import resource=\"classpath:spring/spring-quartz.xml\"/>\n\t<import resource=\"classpath:spring/spring-load.xml\"/>\n    <import resource=\"classpath:spring/spring-mybatis.xml\"/>\n    <import resource=\"classpath:spring/spring-service.xml\"/>\n    <import resource=\"classpath:spring/spring-data.xml\"/>\n    <import resource=\"classpath:spring/spring-manage.xml\"/>\n    <import resource=\"classpath:spring/spring-mvc.xml\"/>\n\t<import resource=\"classpath:spring/spring-jmx.xml\"/>\n\t<import resource=\"classpath:spring/spring-alert.xml\"/>\n\t<import resource=\"classpath:spring/spring-client-report.xml\"/>\n\t<import resource=\"classpath:spring/spring-inspector.xml\"/>\n</beans>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/spring/spring-quartz.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\n                     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd\"\n       default-autowire=\"byName\">\n       \n    <!-- 非分布式模式 -->\n    <bean id=\"jvmQuartzScheduler\" name=\"jvmQuartzScheduler\" lazy-init=\"false\" class=\"org.springframework.scheduling.quartz.SchedulerFactoryBean\">\n        <property name=\"quartzProperties\">\n            <props>\n                <prop key=\"org.quartz.scheduler.instanceName\">cachecloudJvmScheduler</prop>\n                <prop key=\"org.quartz.jobStore.class\">org.quartz.simpl.RAMJobStore</prop>\n                <prop key=\"org.quartz.scheduler.instanceId\">AUTO</prop>\n                <prop key=\"org.quartz.threadPool.class\">org.quartz.simpl.SimpleThreadPool</prop>\n                <prop key=\"org.quartz.threadPool.threadCount\">10</prop>\n                <prop key=\"org.quartz.threadPool.threadPriority\">5</prop>\n                <prop key=\"org.quartz.scheduler.jmx.export\">true</prop>\n                <prop key=\"org.quartz.plugin.shutdownHook.class\">org.quartz.plugins.management.ShutdownHookPlugin</prop>\n                <prop key=\"org.quartz.plugin.shutdownHook.cleanShutdown\">true</prop>\n                <prop key=\"org.quartz.plugin.triggHistory.class\">org.quartz.plugins.history.LoggingJobHistoryPlugin\n                </prop>\n            </props>\n        </property>\n        <property name=\"startupDelay\" value=\"10\"/>\n        <property name=\"applicationContextSchedulerContextKey\" value=\"applicationContext\"/>\n        <property name=\"overwriteExistingJobs\" value=\"true\"/>\n        <property name=\"autoStartup\" value=\"true\"/>\n\n        <property name=\"triggers\">\n            <array>\n                <ref bean=\"errorStatisticsTrigger\"/>\n                <ref bean=\"systemConfigRefreshTrigger\"/>\n            </array>\n        </property>\n\n        <property name=\"jobDetails\">\n            <array>\n                <ref bean=\"errorStatisticsJobDetail\"/>\n                <ref bean=\"systemConfigRefreshJobDetail\"/>\n            </array>\n        </property>\n    </bean>\n    \n\n    <!-- quartz线程池 -->\n    <bean id=\"quartzThreadPool\" class=\"org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor\">\n        <!-- 核心线程数  -->\n        <property name=\"corePoolSize\" value=\"100\"/>\n        <!-- 最大线程数 -->\n        <property name=\"maxPoolSize\" value=\"200\"/>\n        <!-- 队列最大长度 >=mainExecutor.maxSize -->\n        <property name=\"queueCapacity\" value=\"10\"/>\n        <!-- 线程池维护线程所允许的空闲时间 -->\n        <property name=\"keepAliveSeconds\" value=\"300\"/>\n        <!-- 拒绝任务策略:被拒绝后直接在调用者线程中运行当前被放弃任务 -->\n        <property name=\"rejectedExecutionHandler\">\n            <bean class=\"java.util.concurrent.ThreadPoolExecutor$AbortPolicy\"/>\n        </property>\n    </bean>\n \n    <!-- 分布式QuartzScheduler -->\n    <bean id=\"clusterScheduler\" name=\"clusterScheduler\" lazy-init=\"false\" class=\"org.springframework.scheduling.quartz.SchedulerFactoryBean\">\n        <property name=\"dataSource\" ref=\"cacheCloudDB\"></property>\n        <property name=\"taskExecutor\" ref=\"quartzThreadPool\"/>\n        <!--\n        <property name=\"transactionManager\" ref=\"transactionManager\"/>\n        -->\n        <property name=\"quartzProperties\">\n            <props>\n                <prop key=\"org.quartz.scheduler.instanceName\">CacheCloudScheduler</prop>\n                <prop key=\"org.quartz.scheduler.instanceId\">AUTO</prop>\n                <prop key=\"org.quartz.jobStore.class\">org.quartz.impl.jdbcjobstore.JobStoreTX</prop>\n                <prop key=\"org.quartz.jobStore.driverDelegateClass\">org.quartz.impl.jdbcjobstore.StdJDBCDelegate</prop>\n                <!-- 表名前缀 -->\n                <prop key=\"org.quartz.jobStore.tablePrefix\">QRTZ_</prop>\n                <prop key=\"org.quartz.jobStore.isClustered\">${isClustered}</prop>\n                <prop key=\"org.quartz.jobStore.clusterCheckinInterval\">15000</prop>\n                <prop key=\"org.quartz.jobStore.maxMisfiresToHandleAtATime\">120</prop>\n                <prop key=\"org.quartz.jobStore.misfireThreshold\">60000</prop>\n                <!-- 打开JMX 配置 -->\n                <prop key=\"org.quartz.scheduler.jmx.export\">true</prop>\n                <prop key=\"org.quartz.plugin.shutdownHook.class\">org.quartz.plugins.management.ShutdownHookPlugin</prop>\n                <prop key=\"org.quartz.plugin.shutdownHook.cleanShutdown\">true</prop>\n                <prop key=\"org.terracotta.quartz.skipUpdateCheck\">true</prop>\n                <!--<prop key=\"org.quartz.plugin.triggHistory.class\">org.quartz.plugins.history.LoggingJobHistoryPlugin</prop>-->\n\n            </props>\n        </property>\n        <property name=\"schedulerName\" value=\"CacheCloudScheduler\"/>\n        <property name=\"applicationContextSchedulerContextKey\" value=\"applicationContext\"/>\n        <property name=\"overwriteExistingJobs\" value=\"true\"/>\n        <property name=\"waitForJobsToCompleteOnShutdown\" value=\"false\"/>\n        <property name=\"startupDelay\" value=\"10\"/>\n        <property name=\"autoStartup\" value=\"true\"/>\n        <property name=\"triggers\">\n            <array>\n                <ref bean=\"cleanUpStatisticsTrigger\"/>\n                <ref bean=\"hostInspectorTrigger\"/>\n                <ref bean=\"appInspectorTrigger\"/>\n                <ref bean=\"appDailyTrigger\"/>\n                <ref bean=\"instanceAlertValueTrigger\"/>\n            </array>\n        </property>\n        <property name=\"jobDetails\">\n            <array>\n                <ref bean=\"redisJobDetail\"/>\n                <ref bean=\"machineJobDetail\"/>\n                <ref bean=\"serverJobDetail\"/>\n                <ref bean=\"machineMonitorJobDetail\"/>\n                <ref bean=\"redisSlowLogJobDetail\"/>\n                <ref bean=\"cleanUpStatisticsJobDetail\"/>\n                <ref bean=\"inspectorJobDetail\"/>\n                <ref bean=\"appDailyJobDetail\"/>\n                <ref bean=\"instanceAlertValueJobDetail\"/>\n            </array>\n        </property>\n\n    </bean>\n\n    <bean id=\"redisJobDetail\" class=\"org.springframework.scheduling.quartz.JobDetailFactoryBean\">\n        <property name=\"name\" value=\"redisJob\"></property>\n        <property name=\"group\" value=\"redis\"></property>\n        <property name=\"jobClass\" value=\"com.sohu.cache.schedule.jobs.RedisJob\"></property>\n        <property name=\"durability\" value=\"true\"/>\n    </bean>\n\n    <bean id=\"machineJobDetail\" class=\"org.springframework.scheduling.quartz.JobDetailFactoryBean\">\n        <property name=\"name\" value=\"machineJob\"/>\n        <property name=\"group\" value=\"machine\"/>\n        <property name=\"jobClass\" value=\"com.sohu.cache.schedule.jobs.MachineJob\"/>\n        <property name=\"durability\" value=\"true\"/>\n    </bean>\n    <bean id=\"serverJobDetail\" class=\"org.springframework.scheduling.quartz.JobDetailFactoryBean\">\n        <property name=\"name\" value=\"serverJob\"/>\n        <property name=\"group\" value=\"server\"/>\n        <property name=\"jobClass\" value=\"com.sohu.cache.schedule.jobs.ServerJob\"/>\n        <property name=\"durability\" value=\"true\"/>\n    </bean>\n\n    <bean id=\"machineMonitorJobDetail\" class=\"org.springframework.scheduling.quartz.JobDetailFactoryBean\">\n        <property name=\"name\" value=\"machineMonitorJob\"/>\n        <property name=\"group\" value=\"machineMonitor\"/>\n        <property name=\"jobClass\" value=\"com.sohu.cache.schedule.jobs.MachineMonitorJob\"/>\n        <property name=\"durability\" value=\"true\"/>\n    </bean>\n    \n    <bean id=\"redisSlowLogJobDetail\" class=\"org.springframework.scheduling.quartz.JobDetailFactoryBean\">\n        <property name=\"name\" value=\"redisSlowLogJob\"/>\n        <property name=\"group\" value=\"redisSlowLog\"/>\n        <property name=\"jobClass\" value=\"com.sohu.cache.schedule.jobs.RedisSlowLogJob\"/>\n        <property name=\"durability\" value=\"true\"/>\n    </bean>\n    \n    <bean id=\"cleanUpStatisticsJobDetail\" class=\"org.springframework.scheduling.quartz.JobDetailFactoryBean\">\n        <property name=\"name\" value=\"cleanUpStatisticsJobDetail\"></property>\n        <property name=\"group\" value=\"cleanUpStatisticsGroup\"></property>\n        <property name=\"jobClass\" value=\"com.sohu.cache.schedule.jobs.CleanUpStatisticsJob\"></property>\n        <property name=\"durability\" value=\"true\" />\n    </bean>\n\n    <bean id=\"errorStatisticsJobDetail\" class=\"org.springframework.scheduling.quartz.JobDetailFactoryBean\">\n        <property name=\"name\" value=\"errorStatisticsJobDetail\"></property>\n        <property name=\"group\" value=\"errorStatisticsGroup\"></property>\n        <property name=\"jobClass\" value=\"com.sohu.cache.schedule.jobs.ErrorStatisticsJob\"></property>\n        <property name=\"durability\" value=\"true\" />\n    </bean>\n\n    <bean id=\"cleanUpStatisticsTrigger\" class=\"org.springframework.scheduling.quartz.CronTriggerFactoryBean\">\n        <property name=\"name\" value=\"cleanUpStatisticsTrigger\"/>\n        <property name=\"group\" value=\"cleanUp\"/>\n        <property name=\"jobDetail\" ref=\"cleanUpStatisticsJobDetail\"/>\n        <!-- 每天执行一次 -->\n        <property name=\"cronExpression\" value=\"0 0 12 * * ?\"/>\n    </bean>\n\n    <bean id=\"inspectorJobDetail\" class=\"org.springframework.scheduling.quartz.JobDetailFactoryBean\">\n        <property name=\"name\" value=\"inspectorJob\"></property>\n        <property name=\"group\" value=\"inspector\"></property>\n        <property name=\"jobClass\" value=\"com.sohu.cache.inspect.InspectorJob\"></property>\n        <property name=\"durability\" value=\"true\"/>\n    </bean>\n\n    <bean id=\"hostInspectorTrigger\" class=\"org.springframework.scheduling.quartz.CronTriggerFactoryBean\">\n        <property name=\"name\" value=\"hostInspectorTrigger\"/>\n        <property name=\"group\" value=\"inspector\"/>\n        <property name=\"jobDetail\" ref=\"inspectorJobDetail\"/>\n        <!-- 5分钟执行一次 -->\n        <property name=\"cronExpression\" value=\"0 0/5 * ? * *\"/>\n        <property name=\"jobDataAsMap\">\n            <map>\n                <entry key=\"inspectorType\" value=\"host\"/>\n            </map>\n        </property>\n    </bean>\n\n    <bean id=\"appInspectorTrigger\" class=\"org.springframework.scheduling.quartz.CronTriggerFactoryBean\">\n        <property name=\"name\" value=\"appInspectorTrigger\"/>\n        <property name=\"group\" value=\"inspector\"/>\n        <property name=\"jobDetail\" ref=\"inspectorJobDetail\"/>\n        <!-- 20分钟执行一次 -->\n        <property name=\"cronExpression\" value=\"0 0/20 * ? * *\"/>\n        <property name=\"jobDataAsMap\">\n            <map>\n                <entry key=\"inspectorType\" value=\"app\"/>\n            </map>\n        </property>\n    </bean>\n    \n    <bean id=\"errorStatisticsTrigger\" class=\"org.springframework.scheduling.quartz.CronTriggerFactoryBean\">\n        <property name=\"name\" value=\"errorStatisticsTrigger\"/>\n        <property name=\"group\" value=\"errorStatisticsGroup\"/>\n        <property name=\"jobDetail\" ref=\"errorStatisticsJobDetail\"/>\n        <property name=\"cronExpression\" value=\"0 0 10 * * ?\"/>\n    </bean>\n    \n    <bean id=\"systemConfigRefreshJobDetail\" class=\"org.springframework.scheduling.quartz.JobDetailFactoryBean\">\n        <property name=\"name\" value=\"systemConfigRefreshJobDetail\"></property>\n        <property name=\"group\" value=\"systemConfigRefreshGroup\"></property>\n        <property name=\"jobClass\" value=\"com.sohu.cache.schedule.jobs.SystemConfigRefreshJob\"></property>\n        <property name=\"durability\" value=\"true\" />\n    </bean>\n    \n    <bean id=\"systemConfigRefreshTrigger\" class=\"org.springframework.scheduling.quartz.CronTriggerFactoryBean\">\n        <property name=\"name\" value=\"systemConfigRefreshTrigger\"/>\n        <property name=\"group\" value=\"systemConfigRefreshGroup\"/>\n        <property name=\"jobDetail\" ref=\"systemConfigRefreshJobDetail\"/>\n        <property name=\"cronExpression\" value=\"0/30 * * ? * *\"/>\n    </bean>\n    \n    \n    <bean id=\"appDailyJobDetail\" class=\"org.springframework.scheduling.quartz.JobDetailFactoryBean\">\n        <property name=\"name\" value=\"appDailyJob\"></property>\n        <property name=\"group\" value=\"appDaily\"></property>\n        <property name=\"jobClass\" value=\"com.sohu.cache.schedule.jobs.AppDailyJob\"></property>\n        <property name=\"durability\" value=\"true\"/>\n    </bean>\n\n    <bean id=\"appDailyTrigger\" class=\"org.springframework.scheduling.quartz.CronTriggerFactoryBean\">\n        <property name=\"name\" value=\"appDailyTrigger\"/>\n        <property name=\"group\" value=\"appDaily\"/>\n        <property name=\"jobDetail\" ref=\"appDailyJobDetail\"/>\n        <property name=\"cronExpression\" value=\"0 0 10 * * ?\"/>\n    </bean>\n    \n    \n    <bean id=\"instanceAlertValueJobDetail\" class=\"org.springframework.scheduling.quartz.JobDetailFactoryBean\">\n        <property name=\"name\" value=\"instanceAlertValueJob\"></property>\n        <property name=\"group\" value=\"instanceAlertValue\"></property>\n        <property name=\"jobClass\" value=\"com.sohu.cache.schedule.jobs.InstanceAlertValueJob\"></property>\n        <property name=\"durability\" value=\"true\"/>\n    </bean>\n    \n    <bean id=\"instanceAlertValueTrigger\" class=\"org.springframework.scheduling.quartz.CronTriggerFactoryBean\">\n        <property name=\"name\" value=\"instanceAlertValueTrigger\"/>\n        <property name=\"group\" value=\"instanceAlertValue\"/>\n        <property name=\"jobDetail\" ref=\"instanceAlertValueJobDetail\"/>\n        <property name=\"cronExpression\" value=\"0 0/1 * ? * *\"/>\n    </bean>\n    \n\n</beans>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/spring/spring-service.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\n        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd\n        \" default-autowire=\"byName\">\n\n    <!--redis调度接口-->\n    <bean id=\"redisCenter\" class=\"com.sohu.cache.redis.impl.RedisCenterImpl\" init-method=\"init\" destroy-method=\"destory\"/>\n\n    <!--machine调度接口-->\n    <bean id=\"machineCenter\" class=\"com.sohu.cache.machine.impl.MachineCenterImpl\"  init-method=\"init\"/>\n\n    <!--quartz调度接口-->\n    <bean id=\"schedulerCenter\" class=\"com.sohu.cache.schedule.impl.SchedulerCenterImpl\" />\n\n    <!--trigger管理接口-->\n    <bean id=\"triggerCenter\" class=\"com.sohu.cache.schedule.impl.TriggerCenterImpl\"/>\n\n    <!--异步接口-->\n    <bean id=\"asyncService\" class=\"com.sohu.cache.async.impl.AsyncServiceImpl\" destroy-method=\"destory\"/>\n\n    <!--app service接口-->\n    <bean id=\"appStatsCenter\" class=\"com.sohu.cache.stats.app.impl.AppStatsCenterImpl\"/>\n\n    <!--app deloy接口-->\n    <bean id=\"appDeployCenter\" class=\"com.sohu.cache.stats.app.impl.AppDeployCenterImpl\"/>\n\n    <bean id=\"redisDeployCenter\" class=\"com.sohu.cache.redis.impl.RedisDeployCenterImpl\"/>\n\n    <bean id=\"machineDeployCenter\" class=\"com.sohu.cache.machine.impl.MachineDeployCenterImpl\"/>\n\n    <bean id=\"instanceStatsCenter\" class=\"com.sohu.cache.stats.instance.impl.InstanceStatsCenterImpl\"/>\n\n    <bean id=\"instanceDeployCenter\" class=\"com.sohu.cache.stats.instance.impl.InstanceDeployCenterImpl\"/>\n    \n    <bean id=\"importAppCenter\" class=\"com.sohu.cache.stats.app.impl.ImportAppCenterImpl\"/>\n    \n    <bean id=\"appDataMigrateCenter\" class=\"com.sohu.cache.stats.app.impl.AppDataMigrateCenterImpl\"/>\n    \n    <bean id=\"redisConfigTemplateService\" class=\"com.sohu.cache.redis.impl.RedisConfigTemplateServiceImpl\"/>\n\n    <!-- 服务器状况服务 -->\n    <bean id=\"nmonService\" class=\"com.sohu.cache.server.nmon.NMONService\"/>\n    \n    <bean id=\"sshTemplate\" class=\"com.sohu.cache.ssh.SSHTemplate\"/>\n    \n    <bean id=\"serverStatusCollector\" class=\"com.sohu.cache.server.ServerStatusCollector\" init-method=\"init\"/>\n    \n    <bean id=\"serverDataService\" class=\"com.sohu.cache.web.service.impl.ServerDataServiceImpl\"/>\n    \n    <bean id=\"instanceAlertConfigService\" class=\"com.sohu.cache.stats.instance.impl.InstanceAlertConfigServiceImpl\"/>\n\n</beans>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/spring/spring.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\n        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd\" default-autowire=\"byName\">\n    <import resource=\"${spring-file}\"/>\n</beans>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/templates/appAudit.vm",
    "content": "<!DOCTYPE html>\n<head>\n    <meta charset=UTF-8/>\n    <title>CacheCloud审核邮件</title>\n</head>\n<body>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n<p>\n<table style=\"width:100%; font-size:12px;\" width=\"100%\" cellpadding=\"0\" cellspacing=\"0\">\n    <colgroup>\n        <col style=\"width: 5px;\">\n    </colgroup>\n    <tr>\n        <td style=\"width:5px;\"></td>\n        <td style=\"color:#3f3f3f; font-weight: bold;font-size:12px; font-family: '宋体'; padding: 5px 0 15px 0\">\n            $appAudit.userName，您好，欢迎使用CacheCloud平台，您的申请处理进度如下：\n        </td>\n    </tr>\n    <tr>\n        <td></td>\n        <td style=\"padding-top:20px; padding-left:27px;\">\n            <ul>\n                <li><span style=\"font-weight: bold; padding-top:20px; color:#3f3f3f;\">申请处理信息：</span></li>\n            </ul>\n            <table style=\"table-layout:fixed;width: 872px;border-collapse: collapse;word-break: break-all;word-wrap:break-word;border-top: 1px dotted #676767;text-align: center;color: #000; font-family:'宋体'; font-size:12px; margin-top:10px; margin-left: 24px\">\n                <tr>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767;text-align: left; height:33px; width: 50px;\">\n                        申请类型：\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px;\">\n                        ##1:申请应用,2:应用扩容,3:修改配置\n                        $appAudit.typeDesc\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; text-align: left;height:33px; width: 50px;\">\n                        申请描述：\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px;\">\n                        $!appAudit.info\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; text-align: left;height:33px; width: 50px;\">\n                        申请时间：\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px;\">\n                        $!appAudit.createTimeFormat\n                    </td>\n\n                </tr>\n##                <tr>\n##                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767;text-align: left; height:33px; width: 50px;\">\n##                        预留参数1：\n##                    </td>\n##                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px;\">\n##                        $!appAudit.param1\n##                    </td>\n##                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767;text-align: left; height:33px; width: 50px;\">\n##                        预留参数2：\n##                    </td>\n##                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px;\">\n##                        $!appAudit.param2\n##                    </td>\n##                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767;text-align: left; height:33px; width: 50px;\">\n##                        预留参数3：\n##                    </td>\n##                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px;\">\n##                        $!appAudit.param3\n##                    </td>\n##                </tr>\n                <tr>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767;text-align: left; height:33px; width: 50px;\">\n                        处理状态：\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px; color: red;\">\n                        $!appAudit.statusDesc\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767;text-align: left; height:33px; width: 50px;\">\n                        处理描述：\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px; color: red;\">\n                        $!appAudit.refuseReason\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767;text-align: left; height:33px; width: 50px;\">\n                        处理时间：\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px;\">\n                        $!appAudit.modifyTimeFormat\n                    </td>\n                </tr>\n            </table>\n            <br/>\n            <ul>\n                <li><span style=\"font-weight: bold; padding-top:20px; color:#3f3f3f;\">应用详细信息：</span></li>\n            </ul>\n            <table style=\"table-layout:fixed;width: 872px;border-collapse: collapse;word-break: break-all;word-wrap:break-word;border-top: 1px dotted #676767;text-align: center;color: #000; font-family:'宋体'; font-size:12px; margin-top:10px; margin-left: 24px\">\n                <tr>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767;text-align: left; height:33px; width: 50px;\">\n                        应用名称：\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px;\">\n                        $!appDesc.name\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767;text-align: left; height:33px; width: 50px;\">\n                        应用类型：\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px;\">\n                        $!appDesc.typeDesc\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767;text-align: left; height:33px; width: 50px;\">\n                        应用状态：\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px; color: red;\">\n                        $!appDesc.statusDesc\n                    </td>\n                </tr>\n                <tr>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767;text-align: left; height:33px; width: 50px;\">\n                        是否测试：\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px;\">\n                        #if($appDesc.isTest == 1)\n                            是\n                        #else\n                            否\n                        #end\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767;text-align: left; height:33px; width: 50px;\">\n                        是否持久化：\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px;\">\n                        #if($appDesc.needPersistence == 1)\n                            是\n                        #else\n                            否\n                        #end\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767;text-align: left; height:33px; width: 50px;\">\n                        是否有后端数据源：\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px;\">\n                        #if($appDesc.hasBackStore == 1)\n                            是\n                        #else\n                            否\n                        #end\n                    </td>\n                </tr>\n                <tr>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767;text-align: left; height:33px; width: 50px;\">\n                        应用描述：\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px;\">\n                        $!appDesc.intro\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767;text-align: left; height:33px; width: 50px;\">\n                        应用负责人：\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px;\">\n                        $!appDesc.officer\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767;text-align: left; height:33px; width: 50px;\">\n                        应用申请时间：\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px;\">\n                        $!appDesc.createTimeFormat\n                    </td>\n                </tr>\n            </table>\n        </td>\n    </tr>\n\n</table>\n</p>\n</body>\n</html>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/templates/appDaily.vm",
    "content": "<!DOCTYPE html>\n<head>\n    <meta charset=UTF-8/>\n    <title>CacheCloud应用日报</title>\n</head>\n<body>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n<p>\n<table style=\"width:100%; font-size:12px;\" width=\"100%\" cellpadding=\"0\" cellspacing=\"0\">\n    <colgroup>\n        <col style=\"width: 5px;\">\n    </colgroup>\n    <tr>\n        <td></td>\n        <td style=\"padding-top:20px; padding-left:27px;\">\n        \t<ul>\n                <li><span style=\"font-weight: bold; padding-top:20px; color:#3f3f3f;\">应用详细信息：$!appDesc.appId</span></li>\n            </ul>\n            <table style=\"table-layout:fixed;width: 872px;border-collapse: collapse;word-break: break-all;word-wrap:break-word;border-top: 1px dotted #676767;text-align: center;color: #000; font-family:'宋体'; font-size:12px; margin-top:10px; margin-left: 24px\">\n                <tr>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767;text-align: left; height:33px; width: 50px;\">\n                        应用名称：\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px;\">\n                        $!appDesc.name\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767;text-align: left; height:33px; width: 50px;\">\n                        应用类型：\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px;\">\n                        $!appDesc.typeDesc\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767;text-align: left; height:33px; width: 50px;\">\n                        应用状态：\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px;\">\n                        $!appDesc.statusDesc\n                    </td>\n                </tr>\n                <tr>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767;text-align: left; height:33px; width: 50px;\">\n                        应用描述：\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px;\">\n                        $!appDesc.intro\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767;text-align: left; height:33px; width: 50px;\">\n                        应用负责人：\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px;\">\n                        $!appDesc.officer\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767;text-align: left; height:33px; width: 50px;\">\n                        应用申请时间：\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px;\">\n                        $!appDesc.createTimeFormat\n                    </td>\n                </tr>\n            </table>\n        \n            <ul>\n                <li><span style=\"font-weight: bold; padding-top:20px; color:#3f3f3f;\">客户端相关(确保使用有客户端统计的版本):</span></li>\n            </ul>\n            <table style=\"table-layout:fixed;width: 872px;border-collapse: collapse;word-break: break-all;word-wrap:break-word;border-top: 1px dotted #676767;text-align: center;color: #000; font-family:'宋体'; font-size:12px; margin-top:10px; margin-left: 24px\">\n                <tr>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767;text-align: left; height:33px; width: 50px;\">\n                        客户端值分布(全天):\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px;\">\n\t\t\t\t\t\t$!appDailyData.valueSizeDistributeCountDesc                        \n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; text-align: left;height:33px; width: 50px;\">\n                       客户端异常个数(全天)：\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px;\">\n                        $!appDailyData.clientExceptionCount\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; text-align: left;height:33px; width: 50px;\">\n                        客户端连接数(每分钟)：\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px;\">\n                        最大值:$!appDailyData.maxMinuteClientCount <br/>\n                        平均值:$!appDailyData.avgMinuteClientCount\n                    </td>\n                </tr>\n            </table>\n            <br/>\n            \n            <ul>\n                <li><span style=\"font-weight: bold; padding-top:20px; color:#3f3f3f;\">服务端相关:</span></li>\n            </ul>\n            <table style=\"table-layout:fixed;width: 872px;border-collapse: collapse;word-break: break-all;word-wrap:break-word;border-top: 1px dotted #676767;text-align: center;color: #000; font-family:'宋体'; font-size:12px; margin-top:10px; margin-left: 24px\">\n                <tr>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767;text-align: left; height:33px; width: 50px;\">\n                        慢查询个数(全天)：\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px;\">\n                        $!appDailyData.slowLogCount\n                    </td>\n\t\t\t\t\t<td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767;text-align: left; height:33px; width: 50px;\">\n                        命令次数(每分钟)：\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px;\">\n                       \t 最大值:$!appDailyData.maxMinuteCommandCount <br/>\n                       \t 平均值:$!appDailyData.avgMinuteCommandCount\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767;text-align: left; height:33px; width: 50px;\">\n                        命中率(每分钟)：\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px;\">\n                       \t 最大值:$!appDailyData.maxMinuteHitRatio% <br/>\n                       \t 最小值:$!appDailyData.minMinuteHitRatio% <br/>\n                       \t 平均值:$!appDailyData.avgHitRatio%\n                    </td>\n                </tr>\n                \n                <tr>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767;text-align: left; height:33px; width: 50px;\">\n                        内存使用量(全天)：\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px;\">\n                        平均使用量:$!appDailyData.avgUsedMemory M<br/>\n                        最大使用量:$!appDailyData.maxUsedMemory M\n                    </td>\n\t\t\t\t\t<td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767;text-align: left; height:33px; width: 50px;\">\n                        过期键数(全天)：\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px;\">\n                       \t $!appDailyData.expiredKeysCount\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767;text-align: left; height:33px; width: 50px;\">\n                        剔除键数(全天)：\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px;\">\n                       \t $!appDailyData.evictedKeysCount\n                    </td>\n                </tr>\n                \n                <tr>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767;text-align: left; height:33px; width: 50px;\">\n                       键个数(全天)：\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px;\">\n                        平均值:$!appDailyData.avgObjectSize<br/>\n                        最大值:$!appDailyData.maxObjectSize\n                    </td>\n\t\t\t\t\t<td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767;text-align: left; height:33px; width: 50px;\">\n         input流量(每分钟)：\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px;\">\n                       \t 平均值:$!appDailyData.avgMinuteNetInputByte M<br/>\n                       \t 最大值:$!appDailyData.maxMinuteNetInputByte M<br/>\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767;text-align: left; height:33px; width: 50px;\">\n        output流量(每分钟)：\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px;\">\n                       \t 平均:$!appDailyData.avgMinuteNetOutputByte M<br/>\n                       \t 最大:$!appDailyData.maxMinuteNetOutputByte M<br/>\n                    </td>\n                </tr>\n                \n                \n            </table>\n            <br/>\n            \n        </td>\n    </tr>\n\n</table>\n</p>\n</body>\n</html>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/resources/templates/instanceAlert.vm",
    "content": "<!DOCTYPE html>\n<head>\n    <meta charset=UTF-8/>\n    <title>Redis实例分钟报警</title>\n</head>\n<body>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n<p>\n<table style=\"width:100%; font-size:12px;\" width=\"100%\" cellpadding=\"0\" cellspacing=\"0\">\n    <colgroup>\n        <col style=\"width: 5px;\">\n    </colgroup>\n    <tr>\n        <td></td>\n        <td style=\"padding-top:20px; padding-left:27px;\">\n        \t<ul>\n                <li><span style=\"font-weight: bold; padding-top:20px; color:#3f3f3f;\">Redis实例分钟报警：</span></li>\n            </ul>\n            <table style=\"table-layout:fixed;width: 872px;border-collapse: collapse;word-break: break-all;word-wrap:break-word;border-top: 1px dotted #676767;text-align: center;color: #000; font-family:'宋体'; font-size:12px; margin-top:10px; margin-left: 24px\">\n                <tr>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 50px;\">\n                        \t应用id\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 50px;\">\n                        \t应用名\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 50px;\">\n                        \t负责人\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 50px;\">\n                        \tip\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 50px;\">\n                    \t\tport\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px;\">\n                    \t\t属性值\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px;\">\n                    \t\t说明\n                    </td>\n                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px;\">\n                    \t\t其他信息\n                    </td>\n                </tr>\n                #foreach($!item in $!instanceAlertValueResultList)\n                \t<tr>\n\t                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 50px;\">\n\t                    \t\t<a href='${ccDomain}/admin/app/index?appId=$!item.appId'>${item.appId}</a>\n\t                    </td>\n\t                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 50px;\">\n\t                        \t$!item.appDesc.name\n\t                    </td>\n\t                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 50px;\">\n\t                        \t$!item.appDesc.officer\n\t                    </td>\n\t                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 50px;\">\n\t                        \t$!item.instanceInfo.ip\n\t                    </td>\n\t                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 50px;\">\n\t                    \t\t$!item.instanceInfo.port\n\t                    </td>\n\t                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px;\">\n\t                    \t\t$!item.instanceAlertConfig.alertConfig\n\t                    </td>\n\t                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px;\">\n\t                    \t\t$!item.alertMessage\n\t                    </td>\n\t                    <td style=\"border-right: 1px dotted #676767; border-bottom: 1px dotted #676767; height:33px; width: 140px;\">\n\t                    \t\t$!item.otherInfo\n\t                    </td>\n\t                </tr>\n                #end\n            </table>\n        </td>\n    </tr>\n\n</table>\n</p>\n</body>\n</html>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/swap/local.properties",
    "content": "cachecloud.db.url=jdbc:mysql://130.75.131.211:3306/cache-cloud\ncachecloud.db.user=root\ncachecloud.db.password=1q2w3e4r\ncachecloud.maxPoolSize=20\n\nisClustered=true\nisDebug=true\nspring-file=classpath:spring/spring-local.xml\nlog_base=/opt/cachecloud-web/logs\nweb.port=9999\nlog.level=INFO"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/swap/online.properties",
    "content": "cachecloud.db.url = jdbc:mysql://130.75.131.211:3306/cache-cloud\ncachecloud.db.user = root\ncachecloud.db.password = 1q2w3e4r\ncachecloud.maxPoolSize = 20\n\nisClustered = true\nisDebug = false\nspring-file=classpath:spring/spring-online.xml\nlog_base=/opt/cachecloud-web/logs\nweb.port=8585\nlog.level=WARN"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/include/contact.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%@page import=\"com.sohu.cache.util.ConstUtils\"%>   \n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<%=ConstUtils.CONTACT %>\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/include/foot.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<script type=\"text/javascript\" src=\"/resources/bootstrap/bootstrap3/js/bootstrap.js\"></script>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/include/head.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<!-- ie8 -->\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<link href=\"/resources/bootstrap/bootstrap3/css/bootstrap.min.css\" rel=\"stylesheet\">\n<link href=\"/resources/bootstrap/bootstrap3/css/bootstrap-theme.min.css\" rel=\"stylesheet\"/>\n<link href=\"/resources/css/mem-cloud.css\" rel=\"stylesheet\"/>\n<link href=\"/resources/css/docs.min.css\" rel=\"stylesheet\"/>\n\n<!-- date picker -->\n<script type=\"text/javascript\" src=\"/resources/My97DatePicker/WdatePicker.js\"></script>\n<script type=\"text/javascript\" src=\"/resources/widgets/jscalendar/calendar.js\"></script>\n<script type=\"text/javascript\" src=\"/resources/widgets/jscalendar/calendar-setup.js\"></script>\n<script type=\"text/javascript\" src=\"/resources/widgets/jscalendar/lang/calendar-en.js\"></script>\n<script type=\"text/javascript\" src=\"/resources/widgets/jscalendar/lang/calendar-zh.js\"></script>\n\n<!-- ie8 -->\n<script type=\"text/javascript\" src=\"/resources/bootstrap/res/respond.src.js\"></script>\n<script type=\"text/javascript\" src=\"/resources/bootstrap/jquery/jquery-1.11.0.min.js\"></script>\n<script type=\"text/javascript\" src=\"/resources/highchart3/js/highcharts.js\"></script>\n<script type=\"text/javascript\" src=\"/resources/highchart3/js/modules/exporting.js\"></script>\n\n<!-- user manage -->\n<script type=\"text/javascript\" src=\"/resources/manage/manage/machineManage.js?<%=System.currentTimeMillis()%>\"></script>\n<script type=\"text/javascript\" src=\"/resources/js/appDetail.js\"></script>\n<script type=\"text/javascript\" src=\"/resources/js/appInit.js?<%=System.currentTimeMillis()%>\"></script>\n<script type=\"text/javascript\" src=\"/resources/js/appStat.js\"></script>\n<script type=\"text/javascript\" src=\"/resources/js/myhighchart.js?<%=System.currentTimeMillis()%>\"></script>\n\n<link href=\"/resources/js/prettify.css\" rel=\"stylesheet\"/>\n<script type=\"text/javascript\" src=\"/resources/js/prettify.js\"></script>\n<%--<script type=\"text/javascript\" src=\"/resources/js/run_prettify.js\"></script>--%>\n\n\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/include/headAdmin.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<div class=\"header navbar navbar-inverse navbar-fixed-top\">\n\t<div class=\"header-inner\">\n\t\t<div class=\"navbar-header\">\n\t\t\t<a class=\"navbar-brand\" href=\"/manage/total/list.do\">\n\t\t\t\t<img src=\"/resources/manage/img/logo_new.png\" alt=\"logo\" class=\"img-responsive\" />\n\t\t\t</a>\n        </div>\n\t\t\n\t\t<ul class=\"nav navbar-nav pull-right\">\n\t\t\t<li class=\"dropdown user\">\n\t\t\t\t<a href=\"#\" class=\"dropdown-toggle\" data-toggle=\"dropdown\" data-hover=\"dropdown\" data-close-others=\"true\">\n\t\t\t\t<span class=\"username\">${userInfo.chName}</span>\n\t\t\t\t<i class=\"fa fa-angle-down\"></i>\n\t\t\t\t</a>\n\t\t\t\t<ul class=\"dropdown-menu\">\n\t\t\t\t\t<li><a target=\"_blank\" href=\"/admin/app/list.do\"><i class=\"fa fa-user\"></i>应用前台页面</a></li>\n\t\t\t\t\t<li><a href=\"/manage/logout.do\"><i class=\"fa fa-user\"></i>注销</a></li>\n\t\t\t\t</ul>\n\t\t\t</li>\n\t\t</ul>\n\t</div>\n</div>\n<div class=\"clearfix\"></div>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/include/headMenu.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%@page import=\"com.sohu.cache.util.ConstUtils\"%>   \n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<div class=\"navbar navbar-inverse navbar-fixed-top\" role=\"navigation\">\n    <div class=\"container\">\n        <div class=\"navbar-header\">\n            <a class=\"navbar-brand\" href=\"/admin/app/list.do\">CacheCloud</a>\n        </div>\n        <div class=\"navbar-collapse collapse\">\n            <ul class=\"nav navbar-nav navbar-right\">\n                <li class=\"dropdown\">\n                    <a href=\"#\" class=\"dropdown-toggle\" data-toggle=\"dropdown\"><font color='white'>${userInfo.chName}</font><b class=\"caret\"></b>\n\t\t\t\t\t<i class=\"fa fa-angle-down\"></i>\n\t\t\t\t\t</a>\n\t\t\t\t\t<ul class=\"dropdown-menu\">\n\t\t\t\t\t\t<!-- \n\t\t\t\t\t\t<li><a href=\"javascript;\" data-target=\"#addUserModal${userInfo.id}\" data-toggle=\"modal\"><i class=\"fa fa-user\"></i>修改资料</a></li>\n\t\t\t\t\t\t-->\n\t\t\t\t\t\t<c:if test=\"${userInfo.type == 0}\">\n\t\t\t\t\t\t\t<li><a target=\"_blank\" href=\"/manage/total/list.do\"><i class=\"fa fa-user\"></i>管理后台</a></li>\n\t\t\t\t\t\t\t<li><a target=\"_blank\" href=\"/import/app/init\"><i class=\"fa fa-user\"></i>导入应用</a></li>\n\t\t\t\t\t\t\t<li><a target=\"_blank\" href=\"/data/migrate/list\"><i class=\"fa fa-user\"></i>迁移数据工具</a></li>\n\t\t\t\t\t\t</c:if>\n\t\t\t\t\t\t<li><a href=\"/admin/app/list.do\"><i class=\"fa fa-user\"></i>应用列表</a></li>\n\t\t\t\t\t\t<li><a href=\"/admin/app/init.do\"><i class=\"fa fa-user\"></i>应用申请</a></li>\n\t\t\t\t\t\t<li><a href=\"javascript:alert('CacheCloud <%=ConstUtils.CACHECLOUD_VERSION%>版本')\" ><i class=\"fa fa-user\"></i>关于</a></li>\n\t\t\t\t\t\t<li><a href=\"/manage/logout.do\"><i class=\"fa fa-user\"></i>注销</a></li>\n\t\t\t\t\t</ul>\n                </li>\n            </ul>\n            \n            <ul class=\"nav navbar-nav navbar-left\">\n                <li>\n                    <a href=\"<%=ConstUtils.DOCUMENT_URL%>\"><font color='white'>CacheCloud文档</font>\n\t\t\t\t\t</a>\n                </li>\n            </ul>\n            \n            \n            <ul class=\"nav navbar-nav navbar-left\">\n                <li>\n                    <a href=\"/admin/app/initBecomeContributor.do\"><font color='white'>成为CacheCloud贡献者</font>\n\t\t\t\t\t</a>\n                </li>\n            </ul>\n            \n            <ul class=\"nav navbar-nav navbar-left\">\n                <li>\n                    <a href=\"/daily.jsp\"><font color='white'>值班电话</font>\n\t\t\t\t\t</a>\n                </li>\n            </ul>\n            \n            \n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/app/appCommand.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<div class=\"row\">\n    <div id=\"console\" class=\"console\"></div>\n    <script type=\"text/javascript\">\n        $(document).ready(function () {\n            var console = $('#console');\n            var controller = console.console({\n                promptLabel: 'appId:${appId}> ',\n                commandValidate: function (line) {\n                    if (line == \"\") return false;\n                    else return true;\n                },\n                commandHandle: function (line,report) {\n                    $.ajax({\n                        url: \"/admin/app/commandExecute.json\",\n                        data: {appId: $('#appId').val(), command: line},\n                        dataType: \"json\",\n                        success: function (result) {\n                            report([\n                                {msg: result.result,\n                                    className: \"jquery-console-message-value\"}\n                            ]);\n                        }\n                    });\n                },\n                autofocus: true,\n                animateScroll: true,\n                promptHistory: true\n            });\n        });\n    </script>\n    <center><h4><font color='red'>注意：非测试应用只可以执行只读命令，如有需要清理数据请联系管理员！</font></h4></center>\n\n    <input type=\"hidden\" id=\"appId\" value=\"${appId}\">\n\n</div>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/app/appCommandAnalysis.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n\n<script type=\"text/javascript\">\nvar firstCommand = '${firstCommand}';\nvar startDate = '${startDate}';\nvar endDate = '${endDate}';\nvar yesterDate = '${yesterDay}';\nvar betweenOneDay = '${betweenOneDay}';\nvar appId = '${appId}'; \nvar chartParams = \"&startDate=\"+startDate+\"&endDate=\"+endDate;\nvar chartParamsCompare = \"&startDate=\"+yesterDate+\"&endDate=\"+startDate;\nvar betweenParams = \"&startDate=\"+yesterDate+\"&endDate=\"+endDate;\nHighcharts.setOptions({\n\tglobal : {\n\t\tuseUTC : false\n\t}\n});\nHighcharts.setOptions({\n\tcolors : ['#2f7ed8', '#E3170D', '#0d233a', '#8bbc21', '#1aadce',\n\t\t\t'#492970', '#804000', '#f28f43', '#77a1e5',\n\t\t\t'#c42525', '#a6c96a']\n});\n\nfunction changeCommandChart(value){\n\tdocument.getElementById(\"firstCommand\").value = value;\n\tdocument.getElementById(\"formSingCommand\").submit();\n}\n</script>\n\n<div class=\"container\">\n\t<br/>\n\t<form method=\"post\" action=\"/admin/app/index.do\" id=\"formSingCommand\">\n\t\t<div class=\"row\">\n\t\t\t<div style=\"float:right\">\n\t\t\t\t\t<label style=\"font-weight:bold;text-align:left;\">\n\t\t\t\t\t \t开始日期:&nbsp;&nbsp;\n\t\t\t\t\t</label>\n\t\t\t\t\t<input type=\"text\" size=\"21\" name=\"startDate\" id=\"startDate\" value=\"${startDate}\" onFocus=\"WdatePicker({startDate:'%y-%M-01',dateFmt:'yyyy-MM-dd',alwaysUseStartDate:true})\"/>\n\t\t\t\t\t<label style=\"font-weight:bold;text-align:left;\">\n\t\t\t\t\t \t结束日期:\n\t\t\t\t\t</label>\n\t\t\t\t\t<input type=\"text\" size=\"20\" name=\"endDate\" id=\"endDate\" value=\"${endDate}\" onFocus=\"WdatePicker({startDate:'%y-%M-01',dateFmt:'yyyy-MM-dd',alwaysUseStartDate:true})\"/>\n\t\t\t\t\t<input type=\"hidden\" name=\"appId\" value=\"${appDetail.appDesc.appId}\">\n\t\t\t\t\t<input type=\"hidden\" name=\"tabTag\" value=\"app_command_analysis\">\n\t\t\t\t\t<input type=\"hidden\" id=\"firstCommand\" name=\"firstCommand\" value=\"${firstCommand}\">\n\t\t\t\t\t<label>&nbsp;<input type=\"submit\" class=\"btn-4\" value=\"查询\"/></label>\n\t\t\t</div>\n\t\t</div>\n\t\t<div class=\"row\">\n\t\t\t\t<c:set var=\"needSelect\" value=\"0\"></c:set>\n\t\t\t\t&nbsp;&nbsp;Top5命令:\n\t\t\t\t<c:forEach items=\"${allCommands}\" var=\"item\" varStatus=\"stat\">\n\t\t\t\t\t<c:choose>\n\t\t\t\t\t\t<c:when test=\"${stat.index < 5}\">\n\t\t\t\t\t\t\t\t<input type=\"radio\" name=\"optionsRadios\" value=\"${item.commandName}\" \n\t\t\t\t\t\t\t\t<c:if test=\"${firstCommand == item.commandName}\">checked=\"checked\"</c:if>\n\t\t\t\t\t\t\t\t onchange=\"changeCommandChart(this.value)\" />\n\t\t\t\t\t\t\t\t${item.commandName}\n\t\t\t\t\t\t</c:when>\n\t\t\t\t\t\t<c:otherwise>\n\t\t\t\t\t\t\t<c:set var=\"needSelect\" value=\"1\"></c:set>\n\t\t\t\t\t\t</c:otherwise>\n\t\t\t\t\t</c:choose>\n\t\t\t\t</c:forEach>\n\t\t\t\t<c:if test=\"${needSelect == 1}\">\n\t\t\t\t\t&nbsp;&nbsp;&nbsp;其余命令:\n\t\t\t\t\t<select name=\"optionsRadios\" onchange=\"changeCommandChart(this.value)\">\n\t\t\t\t\t\t<option>请选择</option>\n\t\t\t\t\t\t<c:forEach items=\"${allCommands}\" var=\"item\" varStatus=\"stat\">\n\t\t\t\t\t\t\t<c:choose>\n\t\t\t\t\t\t\t\t<c:when test=\"${stat.index >= 5}\">\n\t\t\t\t\t\t\t\t\t<label>\n\t\t\t\t\t\t\t\t\t\t<option value=\"${item.commandName}\" <c:if test=\"${firstCommand == item.commandName}\">selected</c:if>>\n\t\t\t\t\t\t\t         \t\t${item.commandName}\n\t\t\t\t\t\t\t        \t</option>\n\t\t\t\t\t\t\t\t\t</label>\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t</c:when>\n\t\t\t\t\t\t\t</c:choose>\n\t\t\t\t\t\t</c:forEach>\n\t\t\t\t\t</select>\n\t\t\t\t</c:if>\n\t\t\t\t\n\t\t</div>\n\t</form>\n\t<script type=\"text/javascript\">\n\t\tvar title = \"<b>\"+firstCommand+\"命令</b>\";\n\t\tif(betweenOneDay == 1){\n\t\t\t$(document).ready(\n\t\t\t\tfunction() {\n\t\t\t\t\tvar options = getOption(\"containerSingleCommand\", \"<b>全命令统计</b>\", \"次数\");\n\t\t\t\t\tvar commandsUrl = \"/admin/app/getMutiDatesCommandStats.json?appId=\" + appId + \"&commandName=\" + firstCommand + betweenParams;\n\t\t\t\t\t$.ajax({\n\t\t\t\t\t\ttype : \"get\",\n\t\t\t\t\t\turl : commandsUrl,\n\t\t\t\t\t\tasync : true,\n\t\t\t\t\t\tsuccess : function(data) {\n\t\t\t\t\t\t\tvar dates = new Array();\n\t\t\t\t\t\t\tdates.push(startDate); \n\t\t\t\t\t\t\tdates.push(yesterDate);\n\t\t\t\t\t\t\tpushOptionSeries(options, data, dates, \"命令趋势图\");\n\t\t\t\t\t\t\tnew Highcharts.Chart(options);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t });\n\t\t}else{\n\t\t\t$(document).ready(\n\t\t\t\tfunction() {\n\t\t\t\t\tvar options = getOption(\"containerSingleCommand\", title, \"次数\");\n\t\t\t\t\tvar commandsUrl = \"/admin/app/getCommandStats.do?appId=\" + appId + \"&commandName=\" + firstCommand + chartParams;\n\t\t\t\t\t$.ajax({\n\t\t\t\t\t\ttype : \"get\",\n\t\t\t\t\t\turl : commandsUrl,\n\t\t\t\t\t\tasync : false,\n\t\t\t\t\t\tsuccess : function(data) {\n\t\t\t\t\t\t\tvar nameLegend = firstCommand + \"命令趋势图\";\n\t\t\t\t\t\t\tvar finalPoints = getSeriesPoints(data, nameLegend);\n\t\t\t\t\t\t\toptions.series.push(finalPoints);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tnew Highcharts.Chart(options);\n\t\t\t });\n\t\t}\n\t</script>\n\t\n\t\n\t<div id=\"containerSingleCommand\"\n\t\tstyle=\"min-width: 310px; height: 350px; margin: 0 auto\"></div>\n\n</div>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/app/appDaily.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n\n<div class=\"container\">\n\n\t<br/>\n    <form method=\"get\" action=\"/admin/app/index.do\">\n\t\t<div class=\"row\">\n\t\t\t<div style=\"float:right\">\n\t\t\t\t<label style=\"font-weight:bold;text-align:left;\">\n\t\t\t\t \t&nbsp;日期:&nbsp;&nbsp;\n\t\t\t\t</label>\n\t\t\t\t<input type=\"text\" size=\"21\" name=\"dailyDate\" id=\"dailyDate\" value=\"${dailyDate}\" onFocus=\"WdatePicker({startDate:'%y-%M-01',dateFmt:'yyyy-MM-dd',alwaysUseStartDate:true})\"/>\n\t\t\t\t\n\t\t\t\t<input type=\"hidden\" name=\"appId\" value=\"${appDesc.appId}\">\n\t\t\t\t<input type=\"hidden\" name=\"tabTag\" value=\"app_daily\">\n\t\t\t\t<label>&nbsp;<input type=\"submit\" class=\"btn-4\" value=\"查询\"/></label>\n\t\t\t</div>\n\t\t</div>\n\t</form>\n\n\n    <div class=\"row\">\n        <div class=\"page-header\">\n            <h4>客户端相关</h4> \n        </div>\n        <table class=\"table table-striped table-hover\">\n            <tbody>\n             <tr>\n                 <td>客户端值分布(全天)</td>\n                 <td>${appDailyData.valueSizeDistributeCountDescHtml}</td>\n                 <td>客户端异常个数(全天)</td>\n                 <td>${appDailyData.clientExceptionCount}</td>\n                 <td>客户端连接数(每分钟)</td>\n                 <td>\n                  最大值:${appDailyData.maxMinuteClientCount} <br/>\n                     平均值:${appDailyData.avgMinuteClientCount}\n                 </td>\n             </tr>\n            </tbody>\n        </table>\n    </div>\n    \n    <div class=\"row\">\n        <div class=\"page-header\">\n            <h4>服务端相关</h4> \n        </div>\n        <table class=\"table table-striped table-hover\">\n            <tbody>\n\t             <tr>\n\t                 <td>慢查询个数(全天)</td>\n\t                 <td>${appDailyData.slowLogCount}</td>\n\t                 <td>命令次数(每分钟)</td>\n\t                 <td>\n\t                 \t最大值:${appDailyData.maxMinuteCommandCount} <br/>\n\t                    平均值:${appDailyData.avgMinuteCommandCount}\n\t                 </td>\n\t                 <td>命中率(每分钟)</td>\n\t                 <td>\n\t                  \t最大值:${appDailyData.maxMinuteHitRatio}% <br/>\n\t                    最小值:${appDailyData.minMinuteHitRatio}% <br/>\n\t                    平均值:${appDailyData.avgHitRatio}%\n\t                 </td>\n\t             </tr>\n\t             \n\t             <tr>\n\t                 <td>内存使用量(全天)</td>\n\t                 <td>\n\t                 \t平均使用量:${appDailyData.avgUsedMemory} M<br/>\n                        最大使用量:${appDailyData.maxUsedMemory} M\n\t                 </td>\n\t                 <td>过期键数(全天)</td>\n\t                 <td>\n\t                 \t${appDailyData.expiredKeysCount}\n\t                 </td>\n\t                 <td>剔除键数(全天)</td>\n\t                 <td>\n\t                  \t${appDailyData.evictedKeysCount}\n\t                 </td>\n\t             </tr>\n\t             \n\t             \n\t             <tr>\n\t                 <td>键个数(全天)</td>\n\t                 <td>\n\t                 \t平均值:${appDailyData.avgObjectSize}<br/>\n                        最大值:${appDailyData.maxObjectSize}\n\t                 </td>\n\t                 <td>input流量(每分钟)</td>\n\t                 <td>\n\t                 \t平均值:${appDailyData.avgMinuteNetInputByte} M<br/>\n                       \t 最大值:${appDailyData.maxMinuteNetInputByte} M\n\t                 </td>\n\t                 <td>output流量(每分钟)</td>\n\t                 <td>\n\t                  \t 平均:${appDailyData.avgMinuteNetOutputByte} M<br/>\n                       \t 最大:${appDailyData.maxMinuteNetOutputByte} M<br/>\n\t                 </td>\n\t             </tr>\n\t             \n            </tbody>\n        </table>\n    </div>\n    \n    \n    <br/><br/><br/>\n</div>\n\n\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/app/appDemo.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\" %>\n<div class=\"row\">\n    <br/>\n    \n    Maven Dependency：\n    <div id=\"dependency\" class=\"highlight\">\n        <pre class=\"prettyprint\">\n            <c:forEach var=\"line\" items=\"${dependency}\">\n            ${line}<br/>\n            </c:forEach>\n        </pre>\n    </div>\n\n\tDemo Code：\n    <div id=\"code\" class=\"highlight\">\n        <pre class=\"prettyprint\">\n        <c:forEach var=\"line\" items=\"${code}\">\n            ${line}<br/>\n        </c:forEach>\n        </pre>\n    </div>\n    \n    Rest API：\n    <div id=\"code\" class=\"highlight\">\n        <pre class=\"prettyprint\">\n            ${restApi}<br/>\n        </pre>\n    </div>\n    \n    <c:if test=\"${springConfig != null}\">\n    \tSpring Config Demo：\n\t    <div id=\"springConfig\" class=\"highlight\">\n\t        <pre class=\"prettyprint\">\n\t        <c:forEach var=\"line\" items=\"${springConfig}\">\n\t            ${line}<br/>\n\t        </c:forEach>\n\t        </pre>\n\t    </div>\n    </c:if>\n    \n</div>\n<script>\n    prettyPrint();\n</script>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/app/appDetail.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n\n<div class=\"container\">\n    <div class=\"row\">\n        <div class=\"col-md-8\">\n            <div class=\"page-header\">\n                                        应用详情&nbsp;&nbsp;&nbsp;\n                <button type=\"button\" class=\"btn default\" data-target=\"#updateAppDetailModal\" data-toggle=\"modal\">修改应用信息</button>\n            </div>\n            <table class=\"table table-striped table-hover\">\n                <tbody>\n                <tr>\n                    <td>应用id</td>\n                    <td>${appDetail.appDesc.appId}</td>\n                    <td>应用名称</td>\n                    <td>${appDetail.appDesc.name}</td>\n                </tr>\n                <tr>\n                    <td>应用申请人</td>\n                    <td>${appDetail.appDesc.officer}</td>\n                    <td>应用类型</td>\n                    <td>\n                    \t<c:choose>\n        \t\t            <c:when test=\"${appDetail.appDesc.type == 2}\">redis-cluster</c:when>\n\t\t        \t\t    <c:when test=\"${appDetail.appDesc.type == 5}\">redis-sentinel</c:when>\n\t\t        \t\t    <c:when test=\"${appDetail.appDesc.type == 6}\">redis-standalone</c:when>\n                    \t</c:choose>\n                    </td>\n                </tr>\n                <tr>\n                    <td>报警用户</td>\n                    <td>\n                    \t<c:forEach items=\"${appDetail.appUsers}\" var=\"appUser\" varStatus=\"stat\">\n                    \t\t<c:if test=\"${stat.index != 0}\">\n                    \t\t\t;\n                    \t\t</c:if>\n                    \t\t${appUser.chName}(${appUser.name})\n                    \t</c:forEach>\n                    </td>\n                    <td>负责人</td>\n                    <td>${appDetail.appDesc.officer}</td>\n                </tr>\n                <tr>\n                    <td>内存空间</td>\n                    <td><fmt:formatNumber value=\"${appDetail.mem / 1024 * 1.0}\" pattern=\"0.00\"/>G</td>\n                    <td>分布机器数</td>\n                    <td>${appDetail.machineNum}</td>\n                </tr>\n                <tr>\n                    <td>主节点数</td>\n                    <td>${appDetail.masterNum}</td>\n                    <td>从节点数</td>\n                    <td>${appDetail.slaveNum}</td>\n                </tr>\n                <tr>\n                    <td>appKey</td>\n                    <td>\n\t                    <c:choose>\n\t\t                    \t<c:when test=\"${appDetail.appDesc.appKey == null || appDetail.appDesc.appKey == ''}\">\n\t\t                    \t\t暂无\n\t\t                    \t</c:when>\n\t\t                    \t<c:otherwise>\n\t\t                    \t\t${appDetail.appDesc.appKey}\n\t\t                    \t</c:otherwise>\n\t                    </c:choose>\n                    </td>\n                    <td>redis密码</td>\n                    <td>\n                    \t\t<c:choose>\n\t        \t\t            <c:when test=\"${appDetail.appDesc.password != ''}\">${appDetail.appDesc.password}</c:when>\n\t        \t\t            <c:otherwise>无</c:otherwise>\n\t                    \t</c:choose>\n                    </td>\n                </tr>\n                </tbody>\n            </table>\n        </div>\n        \n        <div class=\"col-md-4\">\n            <div class=\"page-header\">\n                <h4>\n                \t\t报警指标\n                \t\t<button type=\"button\" class=\"btn default\" data-target=\"#appAlertConfigModal\" data-toggle=\"modal\">应用报警配置</button>\n                </h4>\n            </div>\n            <table class=\"table table-striped table-hover\">\n                <thead>\n\t                <tr>\n\t                    <td>id</td>\n\t                    <td>报警key</td>\n\t                    <td>阀值</td>\n\t                    <td>周期</td>\n\t                </tr>\n                </thead>\n                <tbody>\n\t                <tr>\n\t                    <td>1</td>\n\t                    <td>内存使用率大于</td>\n\t                    <td>${appDetail.appDesc.memAlertValue}%</td>\n\t                    <td>每20分钟</td>\n\t                </tr>\n\t                 <tr>\n\t                    <td>2</td>\n\t                    <td>客户端连接数大于</td>\n\t                    <td>${appDetail.appDesc.clientConnAlertValue}</td>\n\t                    <td>每20分钟</td>\n\t                </tr>\n                </tbody>\n            </table>\n        </div>\n    </div>\n    \n    <div class=\"row\">\n   \t \t<div class=\"col-md-12 page-header\">\n            <h4>\n            \t用户管理&nbsp;&nbsp;&nbsp;\n            \t<button type=\"button\" class=\"btn default\" data-target=\"#appAddUserModal\" data-toggle=\"modal\">添加用户</button>\n            </h4>\n        </div>\n   \t\t<div class=\"col-md-12\">\n   \t\t  \t<table class=\"table table-striped table-hover\">\n\t   \t\t\t<thead>\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t<td>id</td>\n\t\t\t\t\t\t<td>域账户</td>\n\t\t\t\t\t\t<td>中文名</td>\n\t\t\t\t\t\t<td>邮箱</td>\n\t\t\t\t\t\t<td>手机</td>\n\t\t\t\t\t\t<td>操作</td>\n\t\t\t\t\t</tr>\n\t\t\t\t</thead>\n\t\t\t\t<tbody>\n\t\t\t\t\t<c:forEach items=\"${appDetail.appUsers}\" var=\"user\">\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td>${user.id}</td>\n\t\t\t\t\t\t\t<td>${user.name}</td>\n\t\t\t\t\t\t\t<td>${user.chName}</td>\n\t\t\t\t\t\t\t<td>${user.email}</td>\n\t\t\t\t\t\t\t<td>${user.mobile}</td>\n\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t<a href=\"javascript;\" data-target=\"#addUserModal${user.id}\" data-toggle=\"modal\">[修改]</a>\n\t\t\t\t\t\t\t&nbsp;\n\t\t\t\t\t\t\t<a href=\"javascript:void(0);\" onclick=\"deleteAppUser('${user.id}','${appDetail.appDesc.appId}')\">[删除]</a>\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t</c:forEach>\n\t\t\t\t</tbody>\n\t\t\t</table>\n   \t\t</div>\n    </div>\n\n    <br/><br/><br/>\n    <br/><br/><br/>\n\t\n</div>\n\n<div id=\"appAddUserModal\" class=\"modal fade\" tabindex=\"-1\" data-width=\"400\">\n\t<div class=\"modal-dialog\">\n\t\t<div class=\"modal-content\">\n\t\t\n\t\t\t<div class=\"modal-header\">\n\t\t\t\t<button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\"></button>\n\t\t\t\t<h4 class=\"modal-title\">添加用户</h4>\n\t\t\t</div>\n\t\t\t\n\t\t\t<form class=\"form-horizontal form-bordered form-row-stripped\">\n\t\t\t\t<div class=\"modal-body\">\n\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t<!-- 控件开始 -->\n\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t<!-- form-body开始 -->\n\t\t\t\t\t\t\t<div class=\"form-body\">\n\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-4\">\n\t\t\t\t\t\t\t\t\t\t用户名(邮箱前缀):\n\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t<div class=\"col-md-6\">\n\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"userName\" id=\"userName\" placeholder=\"用户名\" class=\"form-control\" />\n\t\t\t\t\t\t\t\t\t\t<span class=\"help-block\">请确保用户已经申请cachecloud权限</span>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<!-- form-body 结束 -->\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div id=\"appAddUserInfo\"></div>\n\t\t\t\t\t\t<!-- 控件结束 -->\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t\n\t\t\t\t<div class=\"modal-footer\">\n\t\t\t\t\t<button type=\"button\" data-dismiss=\"modal\" class=\"btn\" >Close</button>\n\t\t\t\t\t<button type=\"button\" id=\"appAddUserBtn\" class=\"btn red\" onclick=\"appAddUser('${appDetail.appDesc.appId}')\">Ok</button>\n\t\t\t\t</div>\n\t\t\t\n\t\t\t</form>\n\t\t</div>\n\t</div>\n</div>\n\n\n<div id=\"appAlertConfigModal\" class=\"modal fade\" tabindex=\"-1\" data-width=\"400\">\n\t<div class=\"modal-dialog\">\n\t\t<div class=\"modal-content\">\n\t\t\n\t\t\t<div class=\"modal-header\">\n\t\t\t\t<button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\"></button>\n\t\t\t\t<h4 class=\"modal-title\">应用报警修改</h4>\n\t\t\t</div>\n\t\t\t\n\t\t\t<form class=\"form-horizontal form-bordered form-row-stripped\">\n\t\t\t\t<div class=\"modal-body\">\n\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t<!-- 控件开始 -->\n\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t<!-- form-body开始 -->\n\t\t\t\t\t\t\t<div class=\"form-body\">\n\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">内存报警阀值:</label>\n\t\t\t\t\t\t\t\t\t<div class=\"col-md-7\">\n\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"memAlertValue\" value=\"${appDetail.appDesc.memAlertValue}\" id=\"memAlertValue\" placeholder=\"内存报警阀值\" class=\"form-control\" onchange=\"testisNum(this.id)\">\n\t\t\t\t\t\t\t\t\t\t<span class=\"help-block\">例如:如果想内存使用率超过90%报警，填写90<br/><font color=\"red\">(如果不需要报警请填写100以上的数字)</font></span>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">客户端连接数报警阀值:</label>\n\t\t\t\t\t\t\t\t\t<div class=\"col-md-7\">\n\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"clientConnAlertValue\" value=\"${appDetail.appDesc.clientConnAlertValue}\" id=\"clientConnAlertValue\" placeholder=\"客户端连接数报警阀值\" class=\"form-control\" onchange=\"testisNum(this.id)\">\n\t\t\t\t\t\t\t\t\t\t<span class=\"help-block\">例如:如果想客户端连接数率超过2000报警，填写2000</span>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<!-- form-body 结束 -->\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div id=\"appConfigChangeInfo\"></div>\n\t\t\t\t\t\t<!-- 控件结束 -->\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t\n\t\t\t\t<div class=\"modal-footer\">\n\t\t\t\t\t<button type=\"button\" data-dismiss=\"modal\" class=\"btn\" >Close</button>\n\t\t\t\t\t<button type=\"button\" id=\"appConfigChangeBtn\" class=\"btn red\" onclick=\"appAlertConfigChange('${appDetail.appDesc.appId}')\">Ok</button>\n\t\t\t\t</div>\n\t\t\t\n\t\t\t</form>\n\t\t</div>\n\t</div>\n</div>\n\n\n<div id=\"updateAppDetailModal\" class=\"modal fade\" tabindex=\"-1\" data-width=\"400\">\n\t<div class=\"modal-dialog\">\n\t\t<div class=\"modal-content\">\n\t\t\n\t\t\t<div class=\"modal-header\">\n\t\t\t\t<button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\"></button>\n\t\t\t\t<h4 class=\"modal-title\">应用信息修改</h4>\n\t\t\t</div>\n\t\t\t\n\t\t\t<form class=\"form-horizontal form-bordered form-row-stripped\">\n\t\t\t\t<div class=\"modal-body\">\n\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t<!-- 控件开始 -->\n\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t<!-- form-body开始 -->\n\t\t\t\t\t\t\t<div class=\"form-body\">\n\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">应用名:</label>\n\t\t\t\t\t\t\t\t\t<div class=\"col-md-7\">\n\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"appDescName\" value=\"${appDetail.appDesc.name}\" id=\"appDescName\" class=\"form-control\">\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">应用描述:</label>\n\t\t\t\t\t\t\t\t\t<div class=\"col-md-7\">\n\t\t\t\t\t\t\t\t\t\t<textarea class=\"form-control\" name=\"appDescIntro\" rows=\"3\" id=\"appDescIntro\" placeholder=\"应用描述\">${appDetail.appDesc.intro}</textarea>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">负责人:</label>\n\t\t\t\t\t\t\t\t\t<div class=\"col-md-7\">\n\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"officer\" value=\"${appDetail.appDesc.officer}\" id=\"officer\" class=\"form-control\">\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<!-- form-body 结束 -->\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div id=\"updateAppDetailInfo\"></div>\n\t\t\t\t\t\t<!-- 控件结束 -->\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t\n\t\t\t\t<div class=\"modal-footer\">\n\t\t\t\t\t<button type=\"button\" data-dismiss=\"modal\" class=\"btn\" >Close</button>\n\t\t\t\t\t<button type=\"button\" id=\"updateAppDetailBtn\" class=\"btn red\" onclick=\"updateAppDetailChange('${appDetail.appDesc.appId}')\">Ok</button>\n\t\t\t\t</div>\n\t\t\t\n\t\t\t</form>\n\t\t</div>\n\t</div>\n</div>\n\n\n<c:forEach items=\"${appDetail.appUsers}\" var=\"user\">\n\t<div id=\"addUserModal${user.id}\" class=\"modal fade\" tabindex=\"-1\" data-width=\"400\">\n\t\t<div class=\"modal-dialog\">\n\t\t\t<div class=\"modal-content\">\n\t\t\t\n\t\t\t\t<div class=\"modal-header\">\n\t\t\t\t\t<button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\"></button>\n\t\t\t\t\t<h4 class=\"modal-title\">管理用户</h4>\n\t\t\t\t</div>\n\t\t\t\t\n\t\t\t\t<form class=\"form-horizontal form-bordered form-row-stripped\">\n\t\t\t\t\t<div class=\"modal-body\">\n\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t<!-- 控件开始 -->\n\t\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t\t<!-- form-body开始 -->\n\t\t\t\t\t\t\t\t<div class=\"form-body\">\n\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t域账户名:\n\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"name\" id=\"name${user.id}\"\n\t\t\t\t\t\t\t\t\t\t\t\tvalue=\"${user.name}\" placeholder=\"域账户名(邮箱前缀)\"\n\t\t\t\t\t\t\t\t\t\t\t\tclass=\"form-control\" />\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t中文名:\n\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"chName\" id=\"chName${user.id}\"\n\t\t\t\t\t\t\t\t\t\t\t\tvalue=\"${user.chName}\" placeholder=\"中文名\"\n\t\t\t\t\t\t\t\t\t\t\t\tclass=\"form-control\" />\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t邮箱:\n\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"email\" id=\"email${user.id}\"\n\t\t\t\t\t\t\t\t\t\t\t\tvalue=\"${user.email}\" placeholder=\"邮箱\"\n\t\t\t\t\t\t\t\t\t\t\t\tclass=\"form-control\" />\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t手机:\n\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"mobile\" id=\"mobile${user.id}\"\n\t\t\t\t\t\t\t\t\t\t\t\tvalue=\"${user.mobile}\" placeholder=\"手机\"\n\t\t\t\t\t\t\t\t\t\t\t\tclass=\"form-control\" />\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t<input type=\"hidden\" id=\"type${user.id}\" value=\"${user.type}\">\n\t\t\t\t\t\t\t\t\t<input type=\"hidden\" id=\"userId${user.id}\" name=\"userId\" value=\"${user.id}\"/>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<!-- form-body 结束 -->\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div id=\"info${user.id}\"></div>\n\t\t\t\t\t\t\t<!-- 控件结束 -->\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t\n\t\t\t\t\t<div class=\"modal-footer\">\n\t\t\t\t\t\t<button type=\"button\" data-dismiss=\"modal\" class=\"btn\" >Close</button>\n\t\t\t\t\t\t<button type=\"button\" class=\"btn red\" onclick=\"saveOrUpdateUser('${user.id}')\">Ok</button>\n\t\t\t\t\t</div>\n\t\t\t\t</form>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</c:forEach>\n\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/app/appInit.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <title>申请应用</title>\n    <jsp:include page=\"/WEB-INF/include/head.jsp\"/>\n</head>\n<body role=\"document\">\n\t<div class=\"container\">\n\t    <jsp:include page=\"/WEB-INF/include/headMenu.jsp\"/>\n\t    <div id=\"systemAlert\">\n\t    </div>\n\t\t<div class=\"page-content\">\n\t\t\t<div class=\"row\">\n\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t<h3 class=\"page-header\">\n\t\t\t\t\t\t申请应用\n\t\t\t\t\t\t<font color='red' size=\"4\">\n\t\t\t\t\t\t\t<c:choose>\n\t\t\t\t\t\t\t\t<c:when test=\"${success == 1}\">(更新成功)</c:when>\n\t\t\t\t\t\t\t</c:choose>\n\t\t\t\t\t\t</font>\n\t\t\t\t\t</h3>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"row\">\n\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t<div class=\"portlet box light-grey\">\n\t\t\t\t\t\t<div class=\"portlet-body\">\n\t\t\t\t\t\t\t<div class=\"form\">\n\t\t\t\t\t\t\t\t\t<!-- BEGIN FORM-->\n\t\t\t\t\t\t\t\t\t<form action=\"/admin/app/add.do\" method=\"post\"\n\t\t\t\t\t\t\t\t\t\tclass=\"form-horizontal form-bordered form-row-stripped\" onsubmit=\"return saveAppDesc()\">\n\t\t\t\t\t\t\t\t\t\t<div class=\"form-body\">\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t应用名称<font color='red'>(*)</font>:\n\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"name\" id=\"appName\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tclass=\"form-control\" onchange=\"checkAppNameExist()\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"help-block\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t应用名称（必填，全局唯一，以字母开头的4~32个字符序列，不能含中文，可以是大小写字符，数字，下划线，连接线，点）\n\t\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t应用描述<font color='red'>(*)</font>:\n\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<textarea class=\"form-control\" name=\"intro\" \n\t\t\t\t\t\t\t\t\t\t\t\t\t\trows=\"3\" id=\"appIntro\" placeholder=\"应用描述\"></textarea>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"help-block\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t应用描述（必填，不超过128个字符，可以包含中文）\n\t\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t存储种类:\n\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<select name=\"type\" class=\"form-control select2_category\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"2\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tRedis-cluster\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tRedis-sentinel\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"6\">\n                                                            Redis-standalone\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t内存总量<font color='red'>(*)</font>:\n\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"memSize\" id=\"memSize\" placeholder=\"内存总量\" class=\"form-control\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"help-block\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t例如填写：512M,1G,2G..32G等\n\t\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t项目负责人<font color='red'>(*)</font>:\n\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"officer\" id=\"officer\" placeholder=\"项目负责人(中文必填)\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tclass=\"form-control\" />\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t测试:\n\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<select id=\"isTest\" name=\"isTest\" class=\"form-control\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t否\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"1\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t是\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t后端是否有数据源:\n\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<select id=\"hasBackStore\" name=\"hasBackStore\" class=\"form-control\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"1\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t是\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t否\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t是否需要持久化:\n\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<select id=\"needPersistence\" name=\"needPersistence\" class=\"form-control\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"1\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t是\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t否\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t是否需要热备:\n\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<select id=\"needHotBackUp\" name=\"needHotBackUp\" class=\"form-control\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"1\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t是\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t否\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t预估QPS<font color='red'>(*)</font>:\n\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"forecaseQps\" id=\"forecaseQps\" placeholder=\"预估QPS(如填写:800)\" class=\"form-control\" onchange=\"testisNum(this.id)\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t预估条目数量:<font color='red'>(*)</font>:\n\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"forecastObjNum\" id=\"forecastObjNum\" placeholder=\"预估条目数量(如填写:100000)\" class=\"form-control\" onchange=\"testisNum(this.id)\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t客户端机房:<font color='red'>(*)</font>:\n\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"clientMachineRoom\" id=\"clientMachineRoom\" placeholder=\"例如北显、兆维、或者北显和兆维\" class=\"form-control\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t内存报警阀值<font color='red'>(*)</font>:\n\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"memAlertValue\" id=\"memAlertValue\" placeholder=\"内存报警阀值\" class=\"form-control\" onchange=\"testisNum(this.id)\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"help-block\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t例如内存使用率超过90%就报警，请填写90(<font color=\"red\">如果不需要报警请填写100以上的数字</font>)\n\t\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t客户端连接数报警阀值<font color='red'>(*)</font>:\n\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"clientConnAlertValue\" id=\"clientConnAlertValue\" placeholder=\"客户端连接数报警阀值\" class=\"form-control\" onchange=\"testisNum(this.id)\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"help-block\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t例如:如果想客户端连接数率超过2000报警，填写2000\n\t\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t<input name=\"userId\" id=\"userId\" value=\"${userInfo.id}\" type=\"hidden\" />\n\t\t\t\t\t\t\t\t\t\t\t<input id=\"appExist\" value=\"0\" type=\"hidden\" />\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-actions fluid\">\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-offset-3 col-md-9\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<button type=\"submit\" class=\"btn green\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-check\"></i>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t提交申请\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</form>\n\t\t\t\t\t\t\t\t\t<!-- END FORM-->\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<!-- END TABLE PORTLET-->\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t<br/><br/><br/><br/><br/><br/><br/>\n\t<jsp:include page=\"/WEB-INF/include/foot.jsp\"/>\n</body>\n</html>\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/app/appInstanceNetStat.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<jsp:include page=\"/WEB-INF/include/head.jsp\"/>\n<script type=\"text/javascript\" src=\"/resources/js/jquery-console.js\"></script>\n<script type=\"text/javascript\" src=\"/resources/js/chart.js\"></script>\n<script type=\"text/javascript\" src=\"/resources/js/appClient.js\"></script>\n\n<script type=\"text/javascript\">\nvar startDate = '${startDate}';\nvar endDate = '${endDate}';\nvar appId = '${appId}'; \nvar chartParams = \"&startDate=\"+startDate+\"&endDate=\"+endDate;\nHighcharts.setOptions({\n\tglobal : {\n\t\tuseUTC : false\n\t}\n});\nHighcharts.setOptions({\n\tcolors : ['#2f7ed8', '#E3170D', '#0d233a', '#8bbc21', '#1aadce',\n\t\t\t'#492970', '#804000', '#f28f43', '#77a1e5',\n\t\t\t'#c42525', '#a6c96a']\n});\n\nfunction search() {\n    var startDate = document.getElementById(\"startDate\").value;\n    var endDate = document.getElementById(\"endDate\").value;\n\tvar difTime = calDateWidgetDifMs(startDate, endDate);\n\tvar oneDayTime = 86400000;\n\tif (difTime > oneDayTime) {\n\t\talert(\"由于数据量较大,耗时查询暂不支持跨天查询!\");\n\t} else {\n\t\tdocument.getElementById(\"appInstanceNetStatForm\").submit();\n\t}\n}\n\n</script>\n\n<div class=\"container\">\n\t<jsp:include page=\"/WEB-INF/include/headMenu.jsp\"/>\n\t<div class=\"page-header\">\n\t\t<h4>\n\t\t\t应用(<a target=\"_blank\" href=\"/admin/app/index.do?appId=${appDesc.appId}\">${appDesc.name}</a>)实例流量统计\n\t\t</h4>\n\t</div>\n\t<br/>\n\t<form method=\"get\" action=\"/admin/app/appInstanceNetStat.do\" id=\"appInstanceNetStatForm\">\n\t\t<div class=\"row\">\n\t\t\t<div style=\"float:right\">\n\t\t\t\t\t<label style=\"font-weight:bold;text-align:left;\">\n\t\t\t\t\t \t开始日期:&nbsp;&nbsp;\n\t\t\t\t\t</label>\n\t\t\t\t\t<input type=\"text\" size=\"21\" name=\"startDate\" id=\"startDate\" value=\"${startDate}\" onFocus=\"WdatePicker({startDate:'%y-%M-01',dateFmt:'yyyy-MM-dd',alwaysUseStartDate:true})\"/>\n\t\t\t\t\t<label style=\"font-weight:bold;text-align:left;\">\n\t\t\t\t\t \t结束日期:\n\t\t\t\t\t</label>\n\t\t\t\t\t<input type=\"text\" size=\"20\" name=\"endDate\" id=\"endDate\" value=\"${endDate}\" onFocus=\"WdatePicker({startDate:'%y-%M-01',dateFmt:'yyyy-MM-dd',alwaysUseStartDate:true})\"/>\n\t\t\t\t\t<input type=\"hidden\" name=\"appId\" value=\"${appId}\">\n\t\t\t\t\t<label>&nbsp;<input type=\"button\" class=\"btn-4\" value=\"查询\" onclick=\"search()\"/></label>\n\t\t\t</div>\n\t\t</div>\n\t</form>\n\t<script type=\"text/javascript\">\n\t\t\n\t\tfunction genDetailContainer(i) {\n\t\t\tvar mainContainer = document.getElementById(\"allInstanceContainers\");\n\t\t\tvar divNode = document.createElement(\"div\");\n\t\t\tdivNode.setAttribute('id', \"appInstanceNetContainer\" + i);\n\t\t\tdivNode.setAttribute(\"style\",\"min-width: 550px; height: 350px; margin: 0 auto;\");\n\t\t\tmainContainer.appendChild(divNode);\n\t\t}\n\t\t\n\t\tfunction fillDetailTable(instanceInfo, index) {\n\t\t    var tb =document.getElementById('instanceNetDetailTable');\n\t\t    var newTr = tb.insertRow(-1);\n\t\t    newTr.align='center';\n\t\t    var indexTd = newTr.insertCell();\n\t\t    var instanceTd = newTr.insertCell();\n\t\t    indexTd.innerHTML = (index+1);\n\t\t    instanceTd.innerHTML = instanceInfo;\n\t\t }\n\n\t\t$(document).ready(\n\t\t\t\tfunction() {\n\t\t\t\t\tvar url = \"/admin/app/getAppInstancesNetStat.json?appId=\" + appId + chartParams;\n\t\t\t\t\t$.ajax({\n\t\t\t\t\t\ttype : \"get\",\n\t\t\t\t\t\turl : url,\n\t\t\t\t\t\tasync : false,\n\t\t\t\t\t\tsuccess : function(data) {\n\t\t\t\t\t\t\tvar dataArr = eval(\"(\" + data + \")\");\n\t\t\t\t\t\t\tvar length = dataArr.length;\n\t\t\t\t\t\t\tfor (var i = 0; i < length; i++) {\n\t\t\t\t\t\t\t\tvar instance = dataArr[i];\n\t\t\t\t\t\t\t\tvar instanceNetStatMapList = instance.instanceNetStatMapList;\n\t\t\t\t\t\t\t\tif(instanceNetStatMapList.length == 0) {\n\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tgenDetailContainer(i);\n\t\t\t\t\t\t\t\tvar title = \"<b>实例(\"+instance.instanceInfo+\")网络流量</b>\";\n\t\t\t\t\t\t\t\tvar options = getOption(\"appInstanceNetContainer\" + i, title,\"次数\");\n\t\t\t\t\t\t\t\tvar inPoints = getInstanceNetPoints(instance, \"net_input\", \"i\");\n\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\toptions.yAxis.title.text = inPoints.unitTxt;\n\t\t\t\t\t\t\t\tvar unit = inPoints.unit;\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tvar outPoints = getInstanceNetPoints(instance, \"net_output\", \"o\", unit);\n\t\t\t\t\t\t\t\toptions.series.push(inPoints);\n\t\t\t\t\t\t\t\toptions.series.push(outPoints);\n\t\t\t\t\t\t\t\tnew Highcharts.Chart(options);\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</script>\n\t\n\t\n\t\n\t<div id=\"allInstanceContainers\">\n\t\t\n\t</div>\n\t\n</div>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/app/appList.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" import=\"com.sohu.cache.web.enums.AppOrderByEnum\" %>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/appConstants.jsp\"%>\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <title>CacheCloud应用列表</title>\n    <jsp:include page=\"/WEB-INF/include/head.jsp\"/>\n    <script type=\"text/javascript\">\n  \t//改变内存阀值\n    function cleanAppData(appId){\n    \tvar appCleanDataBtn = document.getElementById(\"appCleanDataBtn\" + appId);\n    \tappCleanDataBtn.disabled = true;\n    \t\n    \t$.post(\n    \t\t'/admin/app/cleanAppData.do',\n    \t\t{\n    \t\t\tappId: appId\n    \t\t},\n            function(data){\n                if(data==1){\n                    alert(\"appId:\" + appId + \"清除数据成功！\");\n                }else{\n                    alert(\"appId:\" + appId + \"清除数据失败,请联系管理员查看原因！\");\n                }\n            \tappCleanDataBtn.disabled = false;\n            }\n         );\n    }\n    </script>\n</head>\n<body role=\"document\">\n<div class=\"container\">\n    <jsp:include page=\"/WEB-INF/include/headMenu.jsp\"/>\n    <div id=\"systemAlert\">\n    </div>\n    <div class=\"row\">\n        <div class=\"col-md-8\">\n            <div class=\"page-header\">\n                <h4>全局信息</h4>\n            </div>\n            <table class=\"table table-striped table-hover\">\n                <tbody>\n                <tr>\n                    <td>总应用数</td>\n                    <td>${totalApps}个 </td>\n                    <td>总申请内存</td>\n                    <td>\n                    \t<fmt:formatNumber value=\"${totalApplyMem / 1024.0}\" pattern=\"0.00\"/>G\n                    </td>\n                </tr>\n                <tr>\n                    <td>已使用内存</td>\n                    <td>\n                    \t<fmt:formatNumber value=\"${totalUsedMem / 1024.0}\" pattern=\"0.00\"/>G\n                    </td>\n                    <td></td>\n                    <td></td>\n                </tr>\n                </tbody>\n            </table>\n        </div>\n        <div class=\"col-md-4\">\n            <div class=\"page-header\">\n                <h4>联系我们: </h4>\n            </div>\n            <div id=\"contact\" class=\"page-body\">\n            \t<jsp:include page=\"/WEB-INF/include/contact.jsp\"/>\n            </div>\n        </div>\n    </div>\n    \n    \n    \n    <div class=\"row\">\n        <div class=\"col-md-12\">\n            <div class=\"page-header\">\n                <h4>应用列表</h4>\n            </div>\n            <c:if test=\"${currentUser.type == 0}\">\n\t\t\t\t<div style=\"float:right\">\n\t\t\t\t\t<form class=\"form-inline\" method=\"post\" action=\"/admin/app/list.do\" id=\"appList\" name=\"ec\">\n\t\t\t\t\t  <div class=\"form-group\">\n\t\t\t\t\t    <input type=\"text\" class=\"form-control\" id=\"appId\" name=\"appId\" value=\"${appSearch.appId}\" placeholder=\"应用ID\" onchange=\"testisNum(this.id)\">\n\t\t\t\t\t  </div>\n\t\t\t\t\t  <div class=\"form-group\">\n\t\t\t\t\t    <input type=\"text\" class=\"form-control\" id=\"appName\" name=\"appName\" value=\"${appSearch.appName}\" placeholder=\"应用名\">\n\t\t\t\t\t  </div>\n\t\t\t\t\t  <div class=\"form-group\">\n\t\t\t\t\t\t<select name=\"appType\" class=\"form-control\">\n\t\t\t\t\t\t\t<option value=\"\">\n\t\t\t\t\t\t\t\t全部类型\n\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t<option value=\"2\" <c:if test=\"${appSearch.appType == 2}\">selected</c:if>>\n\t\t\t\t\t\t\t\tRedis-cluster\n\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t<option value=\"5\" <c:if test=\"${appSearch.appType == 5}\">selected</c:if>>\n\t\t\t\t\t\t\t\tredis-sentinel\n\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t<option value=\"6\" <c:if test=\"${appSearch.appType == 6}\">selected</c:if>>\n\t\t\t\t\t\t\t\tredis-standalone\n\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t</select>\n\t\t\t\t\t </div>\n\t\t\t\t\t <div class=\"form-group\">\n\t\t\t\t\t\t<select name=\"appStatus\" class=\"form-control\">\n\t\t\t\t\t\t\t<option value=\"-1\">\n\t\t\t\t\t\t\t\t全部状态\n\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t<option value=\"0\" <c:if test=\"${appSearch.appStatus == 0}\">selected</c:if>>\n\t\t\t\t\t\t\t\t未分配\n\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t<option value=\"1\" <c:if test=\"${appSearch.appStatus == 1}\">selected</c:if>>\n\t\t\t\t\t\t\t\t申请中\n\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t<option value=\"2\" <c:if test=\"${appSearch.appStatus == 2}\">selected</c:if>>\n\t\t\t\t\t\t\t\t运行中\n\t\t\t\t\t\t\t</option>\n\t\t                    <option value=\"3\" <c:if test=\"${appSearch.appStatus == 3}\">selected</c:if>>\n\t\t                       \t 已下线\n\t\t                    </option>\n\t\t                    <option value=\"4\" <c:if test=\"${appSearch.appStatus == 4}\">selected</c:if>>\n\t\t                       \t 驳回\n\t\t                    </option>\n\t\t\t\t\t\t</select>\n\t\t\t\t\t </div>\n\t\t\t\t\t <div class=\"form-group\">\n\t\t\t\t\t\t<select name=\"importantLevel\" class=\"form-control\">\n\t\t\t\t\t\t\t<option value=\"\">\n\t\t\t\t\t\t\t\t全部级别\n\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t<option value=\"1\" <c:if test=\"${appSearch.importantLevel == 1}\">selected</c:if>>\n\t\t\t\t\t\t\t\tS级\n\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t<option value=\"2\" <c:if test=\"${appSearch.importantLevel == 2}\">selected</c:if>>\n\t\t\t\t\t\t\t\tA级\n\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t<option value=\"3\" <c:if test=\"${appSearch.importantLevel == 3}\">selected</c:if>>\n\t\t\t\t\t\t\t\tB级\n\t\t\t\t\t\t\t</option>\n\t\t                    <option value=\"4\" <c:if test=\"${appSearch.importantLevel == 4}\">selected</c:if>>\n\t\t                       \tC级\n\t\t                    </option>\n\t\t\t\t\t\t</select>\n\t\t\t\t\t </div>\n\t\t\t\t\t \n\t\t\t\t\t <div class=\"form-group\">\n\t\t\t\t\t\t<select name=\"pageSize\" class=\"form-control\">\n\t\t\t\t\t\t\t<option value=\"10\" <c:if test=\"${page.pageSize == 10}\">selected</c:if>>\n\t\t\t\t\t\t\t\t10行\n\t\t\t\t\t\t\t</option>\n\t\t                    <option value=\"20\" <c:if test=\"${page.pageSize == 20}\">selected</c:if>>\n\t\t                       \t 20行\n\t\t                    </option>\n\t\t                    <option value=\"50\" <c:if test=\"${page.pageSize == 50}\">selected</c:if>>\n\t\t                       \t 50行\n\t\t                    </option>\n\t\t                    <option value=\"100\" <c:if test=\"${page.pageSize == 100}\">selected</c:if>>\n\t\t                       \t 100行\n\t\t                    </option>\n\t\t\t\t\t\t</select>\n\t\t\t\t\t </div>\n\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t\t  <input type=\"hidden\" name=\"pageNo\" id=\"pageNo\">\n\t\t\t\t\t  <button type=\"submit\" class=\"btn btn-default\">查询</button>\n\t\t\t\t\t</form>\n\t\t\t\t</div>\n\t\t    </c:if>\n\t\t</div>\n\t</div>\n\t<div class=\"row\">\n\t\t\t<br/>\n\t\t\t<div class=\"col-md-12\">\n\t            <table class=\"table table-striped table-hover\" style=\"margin-top: 0px\">\n\t                <thead>\n\t\t                <tr>\n\t\t                    <td>应用ID</td>\n\t\t                    <td>应用名</td>\n\t\t                    <td>应用类型</td>\n\t\t                    <td>内存详情</td>\n\t\t                    <td>命中率</td>\n\t\t                    <td>已运行时间</td>\n\t\t                    <td>申请状态</td>\n\t\t                    <td>操作</td>\n\t\t                </tr>\n\t                </thead>\n\t                <tbody>\n\t                \t<c:forEach items=\"${appDetailList}\" var=\"appDetail\">\n\t                \t\t <tr>\n\t\t\t                    <td>\n\t\t\t                    \t<c:choose>\n\t\t\t                    \t\t<c:when test=\"${appDetail.appDesc.status == 0 or appDetail.appDesc.status == 1}\">\n\t\t\t                   \t\t\t\t${appDetail.appDesc.appId}\n\t\t\t                    \t\t</c:when>\n\t\t\t                    \t\t<c:when test=\"${appDetail.appDesc.status == 2 or appDetail.appDesc.status == 3 or appDetail.appDesc.status == 4}\">\n\t\t\t                    \t\t\t<a title=\"${appDetail.appDesc.intro}\" target=\"_blank\" href=\"/admin/app/index.do?appId=${appDetail.appDesc.appId}\">${appDetail.appDesc.appId}</a>\n\t\t\t                    \t\t</c:when>\n\t\t\t                    \t</c:choose>\n\t\t\t                    </td>\n\t\t\t                    <td>\n\t\t\t                    \t<c:choose>\n\t\t\t                    \t\t<c:when test=\"${appDetail.appDesc.status == 0 or appDetail.appDesc.status == 1}\">\n\t\t\t                    \t\t\t${appDetail.appDesc.name}\n\t\t\t                    \t\t</c:when>\n\t\t\t                    \t\t<c:when test=\"${appDetail.appDesc.status == 2 or appDetail.appDesc.status == 3 or appDetail.appDesc.status == 4}\">\n\t\t\t                    \t\t\t<a target=\"_blank\" href=\"/admin/app/index.do?appId=${appDetail.appDesc.appId}\">${appDetail.appDesc.name}</a>\n\t\t\t                    \t\t</c:when>\n\t\t\t                    \t</c:choose>\n\t\t\t                    </td>\n\t\t\t                    <td>\n\t\t\t                    \t<c:choose>\n\t\t\t        \t\t            <c:when test=\"${appDetail.appDesc.type == 2}\">redis-cluster</c:when>\n\t    \t\t        \t\t        <c:when test=\"${appDetail.appDesc.type == 5}\">redis-sentinel</c:when>\n\t    \t\t        \t\t        <c:when test=\"${appDetail.appDesc.type == 6}\">redis-standalone</c:when>\n\t\t\t                    \t</c:choose>\n\t\t\t                    </td>\n\t\t\t                    <td>\n\t\t\t                        <div class=\"progress margin-custom-bottom0\">\n\t\t\t                        \t<c:choose>\n\t\t\t                        \t\t<c:when test=\"${appDetail.memUsePercent >= 80}\">\n\t\t\t\t\t\t\t\t\t\t\t\t<c:set var=\"progressBarStatus\" value=\"progress-bar-danger\"/>\n\t\t\t                        \t\t</c:when>\n\t\t\t                        \t\t<c:otherwise>\n\t\t\t\t\t\t\t\t\t\t\t\t<c:set var=\"progressBarStatus\" value=\"progress-bar-success\"/>\n\t\t\t                        \t\t</c:otherwise>\n\t\t\t                        \t</c:choose>\n\t\t\t\t\t\t\t\t\t\t<div class=\"progress-bar ${progressBarStatus}\"\n\t\t\t\t\t\t\t\t\t\t\trole=\"progressbar\" aria-valuenow=\"${appDetail.memUsePercent}\" aria-valuemax=\"100\"\n\t\t\t\t\t\t\t\t\t\t\taria-valuemin=\"0\" style=\"width: ${appDetail.memUsePercent}%\">\n\t\t\t\t\t\t\t\t\t\t\t<label style=\"color: #000000\">\n\t\t\t\t\t\t\t\t\t\t\t\t<fmt:formatNumber value=\"${appDetail.mem * appDetail.memUsePercent / 100 / 1024}\" pattern=\"0.00\"/>G&nbsp;&nbsp;Used/<fmt:formatNumber value=\"${appDetail.mem / 1024 * 1.0}\" pattern=\"0.00\"/>G&nbsp;&nbsp;Total\n\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t                    </td>\n\t\t\t                    <td>\n\t\t\t                    \t<c:choose>\n\t\t\t                    \t\t<c:when test=\"${appDetail.hitPercent <= 0}\">\n\t\t\t                    \t\t\t无\n\t\t\t                    \t\t</c:when>\n\t\t\t                    \t\t<c:when test=\"${appDetail.hitPercent <= 30}\">\n\t\t\t                    \t\t\t<label class=\"label label-danger\">${appDetail.hitPercent}%</label>\n\t\t\t                    \t\t</c:when>\n\t\t\t                    \t\t<c:when test=\"${appDetail.hitPercent >= 30 && appDetail.hitPercent < 50}\">\n\t\t\t                    \t\t\t<label class=\"label label-warning\">${appDetail.hitPercent}%</label>\n\t\t\t                    \t\t</c:when>\n\t\t\t                    \t\t<c:when test=\"${appDetail.hitPercent >= 50 && appDetail.hitPercent < 90}\">\n\t\t\t                    \t\t\t<label class=\"label label-info\">${appDetail.hitPercent}%</label>\n\t\t\t                    \t\t</c:when>\n\t\t\t                    \t\t<c:otherwise>\n\t\t\t                    \t\t\t<label class=\"label label-success\">${appDetail.hitPercent}%</label>\n\t\t\t                    \t\t</c:otherwise>\n\t\t\t                    \t</c:choose>\n\t\t\t                    \t\n\t\t\t                    </td>\n\t\t\t                    <td>${appDetail.appDesc.appRunDays}天</td>\n\t\t\t                    <td>\n\t\t\t                    \t<c:choose>\n\t\t\t                    \t\t<c:when test=\"${appDetail.appDesc.status == 0}\">\n\t\t\t                    \t\t\t<font color=\"red\">未申请</font>\n\t\t\t                    \t\t</c:when>\n\t\t\t                    \t\t<c:when test=\"${appDetail.appDesc.status == 1}\">\n\t\t\t                    \t\t\t<font color=\"red\">申请中</font>\n\t\t\t                    \t\t</c:when>\n\t\t\t                    \t\t<c:when test=\"${appDetail.appDesc.status == 2}\">\n\t\t\t                    \t\t\t运行中\n\t\t\t                    \t\t</c:when>\n\t                                    <c:when test=\"${appDetail.appDesc.status == 3}\">\n\t                                        <font color=\"red\">已下线</font>\n\t                                    </c:when>\n\t                                    <c:when test=\"${appDetail.appDesc.status == 4}\">\n\t                                        <font color=\"red\">驳回</font>\n\t                                    </c:when>\n\t\t\t                    \t</c:choose>\n\t\t\t                    </td>\n\t\t\t                    <td>\n\t\t\t                    \t<c:choose>\n\t\t\t                    \t\t<c:when test=\"${appDetail.appDesc.status == 2 && appDetail.appDesc.isTest == 1}\">\n\t\t\t                    \t\t\t<button type=\"button\" id=\"appCleanDataBtn${appDetail.appDesc.appId}\" onclick=\"if(window.confirm('确认要清除应用appid=${appDetail.appDesc.appId}的数据?!')){cleanAppData('${appDetail.appDesc.appId}');return true;}else{return false;}\">清空数据</button>\n\t\t\t                    \t\t</c:when>\n\t\t\t                    \t</c:choose>\n\t\t\t                    </td>\n\t\t\t                </tr>\n\t                \t</c:forEach>\n\t                </tbody>\n\t            </table>\n            </div>\n            <div style=\"margin-bottom: 10px;float: right;margin-right: 15px\">\n\t\t\t\t<span>\n\t\t\t\t\t<ul id='ccPagenitor' style=\"margin-bottom: 0px;margin-top: 0px\"></ul>\n\t\t\t\t\t<div id=\"pageDetail\" style=\"float:right;padding-top:7px;padding-left:8px;color:#4A64A4;display: none\">共${page.totalPages}页,${page.totalCount}条</div>\t\t\n\t\t\t\t</span>\n\t\t\t</div>\n        </div>\n    </div>\n\n<jsp:include page=\"/WEB-INF/include/foot.jsp\"/>\n\n<script type=\"text/javascript\" src=\"/resources/js/mem-cloud.js\"></script>\n\n<script src=\"/resources/bootstrap/paginator/bootstrap-paginator.js\"></script>\n<script src=\"/resources/bootstrap/paginator/custom-pagenitor.js\"></script>\n<script type=\"text/javascript\">\n    $(function(){\n    \tvar userType = '${currentUser.type}';\n    \tif (userType == 0) {\n    \t\t//分页点击函数\n        \tvar pageClickedFunc = function (e, originalEvent, type, page){\n        \t\t//form传参用pageSize\n        \t\tdocument.getElementById(\"pageNo\").value=page;\n        \t\tdocument.getElementById(\"appList\").submit();\n        \t};\n        \t//分页组件\n            var element = $('#ccPagenitor');\n            //当前page号码\n            var pageNo = '${page.pageNo}';\n            //总页数\n            var totalPages = '${page.totalPages}';\n            //显示总页数\n            var numberOfPages = '${page.numberOfPages}';\n    \t\tvar options = generatePagenitorOption(pageNo, numberOfPages, totalPages, pageClickedFunc);\n    \t\tif(totalPages > 0){\n    \t\t\telement.bootstrapPaginator(options);\n    \t\t\tdocument.getElementById(\"pageDetail\").style.display = \"\";\n    \t\t}else{\n    \t\t\telement.html(\"未查询到相关记录！\");\n    \t\t}\n    \t}\n    \t\n    });\n</script>\n\n\n</body>\n</html>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/app/appMachineInstancesTopology.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<link href=\"http://www.bootcss.com/p/buttons/css/buttons.css\" rel=\"stylesheet\">\n<div class=\"row\">\n    <div class=\"page-header\">\n        <a target=\"_blank\" data-container=\"body\" class='button button-caution button-square button-small'> </a>\n        <label>代表master节点</label>\n        <a target=\"_blank\" data-container=\"body\" class='button button-caution button-square button-small button-border'> </a>\n        <label>代表slave节点</label>\n        <c:if test=\"${appDesc.type == 5}\">\n        \t<a target=\"_blank\" data-container=\"body\" class='button button-action button-square button-small'> </a>\n        \t<label>代表Sentinel节点</label>\n        </c:if>\n    </div>\n    <div style=\"margin-top: 20px\">\n        <table class=\"table table-striped table-hover\">\n            <thead>\n            <tr>\n                <td  style='vertical-align: middle;text-align: center;'>机器</td>\n                <c:forEach var=\"instanceIndex\" begin=\"1\" end=\"${instancePairCount}\"> \n                \t<td  style='vertical-align: middle;text-align: center;'>实例对${instanceIndex}</td>\n               \t</c:forEach>\n            </tr>\n            </thead>\n            <tbody>\n            <c:forEach var=\"machineInstanceEntry\" items=\"${machineInstanceMap}\" varStatus=\"status\">\n                <tr>\n                \t<td  style='vertical-align: middle;text-align: center;'>${machineInstanceEntry.key}</td>\n                \t<c:forEach var=\"instanceIndex\" begin=\"1\" end=\"${instancePairCount}\">\n                \t    <td style='vertical-align: middle;text-align: center;'>\n\t                \t\t<c:forEach var=\"instance\" items=\"${machineInstanceEntry.value}\" varStatus=\"status\">\n\t                \t\t\t<c:set var=\"instanceNodeTypeStyle\" value=\"button-caution\"/>\n\t                \t\t\t<c:if test=\"${instance.type == 5}\">\n\t                \t\t\t\t<c:set var=\"instanceNodeTypeStyle\" value=\"button-action\"/>\n\t                \t\t\t</c:if>\n\t            \t\t\t\t<c:if test=\"${instance.groupId == instanceIndex}\">\n\t            \t\t\t\t\t<a target=\"_blank\" data-container=\"body\" data-toggle=\"popover\" data-placement=\"top\" data-content=\"<a target='_blank' href='/admin/instance/index.do?instanceId=${instance.id}'>${instance.ip}:${instance.port}</a>\" href=\"/admin/instance/index.do?instanceId=${instance.id}\" class='button ${instanceNodeTypeStyle} button-square button-small <c:if test=\"${instance.masterInstanceId > 0}\">button-border</c:if>'>${instance.groupId}</a>\n\t\t            \t\t\t\t<c:if test=\"${instance.status == 0}\">\n\t\t            \t\t\t\t\t(心跳停止)\n\t\t            \t\t\t\t</c:if>\n\t            \t\t\t\t</c:if>\n\t            \t\t\t\t\n\t                \t\t</c:forEach>\n                \t\t</td>\n                \t</c:forEach>\n                </tr>\n            </c:forEach>\n            </tbody>\n        </table>\n    </div>\n    \n</div>\n<script type=\"text/javascript\" src=\"/resources/js/myPopover.js\"></script>\n\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/app/appScaleApply.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\" pageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<c:forEach items=\"${apps}\" var=\"item\">\n\t<div id=\"appScaleApply${item.appId}\" class=\"modal fade\" tabindex=\"-1\" data-width=\"400\">\n\t\t<div class=\"modal-dialog\">\n\t\t\t<div class=\"modal-content\">\n\t\t\t\n\t\t\t\t<div class=\"modal-header\">\n\t\t\t\t\t<button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\"></button>\n\t\t\t\t\t<h4 class=\"modal-title\">申请扩容</h4>\n\t\t\t\t</div>\n\t\t\t\t\n\t\t\t\t<form class=\"form-horizontal form-bordered form-row-stripped\">\n\t\t\t\t\t<div class=\"modal-body\">\n\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t<!-- 控件开始 -->\n\t\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t\t<!-- form-body开始 -->\n\t\t\t\t\t\t\t\t<div class=\"form-body\">\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t每个分片容量:\n\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"memSize\" id=\"memSize${item.appId}\"\n\t\t\t\t\t\t\t\t\t\t\t\tvalue=\"${memSize}\"  placeholder=\"每个分片容量\"\n\t\t\t\t\t\t\t\t\t\t\t\tclass=\"form-control\" />\n\t\t\t\t\t\t\t\t\t\t\t<span class=\"help-block\">\n\t\t\t\t\t\t\t\t\t\t\t\t追加的单位容量（256，512，1024）\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t<input type=\"hidden\" id=\"appId\" name=\"appId\" value=\"${item.appId}\"/>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<!-- form-body 结束 -->\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div id=\"info${item.appId}\"></div>\n\t\t\t\t\t\t\t<!-- 控件结束 -->\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t\n\t\t\t\t\t<div class=\"modal-footer\">\n\t\t\t\t\t\t<button type=\"button\" data-dismiss=\"modal\" class=\"btn\" >Close</button>\n\t\t\t\t\t\t<button type=\"button\" class=\"btn red\" onclick=\"appScaleApply('${item.appId}')\">Ok</button>\n\t\t\t\t\t</div>\n\t\t\t\t\n\t\t\t\t</form>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</c:forEach>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/app/appStat.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n\n<script type=\"text/javascript\">\nvar startDate = '${startDate}';\nvar endDate = '${endDate}';\nvar yesterDate = '${yesterDay}';\nvar betweenOneDay = '${betweenOneDay}';\nvar appId = '${appId}';\nvar chartType = 'line';\nvar chartParams = \"&startDate=\"+startDate+\"&endDate=\"+endDate;\nvar chartParamsCompare = \"&startDate=\"+yesterDate+\"&endDate=\"+startDate;\nvar betweenParams = \"&startDate=\"+yesterDate+\"&endDate=\"+endDate;\nvar appTotalMem = '${appDetail.mem}';\nHighcharts.setOptions({\n\tglobal : {\n\t\tuseUTC : false\n\t}\n});\nHighcharts.setOptions({\n\tcolors : [ '#2f7ed8', '#E3170D', '#0d233a', '#8bbc21', '#1aadce',\n\t\t\t'#492970', '#804000', '#f28f43', '#77a1e5',\n\t\t\t'#c42525', '#a6c96a' ]\n});\n\n</script>\n\n<div class=\"container\">\n\t<br/>\n\t<div class=\"row\">\n\t\t<div style=\"float:right\">\n\t\t\t<form method=\"post\" action=\"/admin/app/index.do\" id=\"ec\" name=\"ec\">\n\t\t\t\t<label style=\"font-weight:bold;text-align:left;\">\n\t\t\t\t \t开始日期:&nbsp;&nbsp;\n\t\t\t\t</label>\n\t\t\t\t<input type=\"text\" size=\"21\" name=\"startDate\" id=\"startDate\" value=\"${startDate}\" onFocus=\"WdatePicker({startDate:'%y-%M-01',dateFmt:'yyyy-MM-dd',alwaysUseStartDate:true})\"/>\n\t\t\t\t<label style=\"font-weight:bold;text-align:left;\">\n\t\t\t\t \t结束日期:\n\t\t\t\t</label>\n\t\t\t\t<input type=\"text\" size=\"20\" name=\"endDate\" id=\"endDate\" value=\"${endDate}\" onFocus=\"WdatePicker({startDate:'%y-%M-01',dateFmt:'yyyy-MM-dd',alwaysUseStartDate:true})\"/>\n\t\t\t\t<input type=\"hidden\" name=\"appId\" value=\"${appDetail.appDesc.appId}\">\n\t\t\t\t<label>&nbsp;<input type=\"submit\" class=\"btn-4\" value=\"查询\"/></label>\n\t\t\t</form>\n\t\t</div>\n\t</div>\n\t<div class=\"row\">\n\t\t<div class=\"col-md-6\">\n\t\t\t<div class=\"page-header\">\n\t\t\t\t<h4>\n\t\t\t\t全局信息&nbsp;&nbsp;&nbsp;\n\t\t\t\t<button type=\"button\" id=\"appScaleApplyBtn\" class=\"btn btn-info\" data-target=\"#appScaleApplyModal\" data-toggle=\"modal\">申请扩容</button>\n\t\t\t\t<button type=\"button\" class=\"btn btn-info\" data-target=\"#appConfigChangeModal\" data-toggle=\"modal\" href=\"#\">申请修改配置</button>\n\t\t\t\t<a target=\"_blank\" href=\"/client/show/index.do?appId=${appId}\" class=\"btn btn-info\" role=\"button\">客户端统计</a>\n\t\t\t\t</h4>\n\t\t\t</div>\n\t\t\t<table class=\"table table-striped table-hover\">\n\t\t\t\t<tbody>\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t<td>内存使用率</td>\n\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t<div class=\"progress margin-custom-bottom0\">\n\t\t\t\t\t\t\t\t<c:choose>\n\t\t                    \t\t<c:when test=\"${appDetail.memUsePercent >= 80.00}\">\n\t\t\t\t\t\t\t\t\t\t<div class=\"progress-bar progress-bar-danger\"\n\t\t\t\t\t\t\t\t\t\t\trole=\"progressbar\" aria-valuenow=\"${appDetail.memUsePercent}\" aria-valuemax=\"100\"\n\t\t\t\t\t\t\t\t\t\t\taria-valuemin=\"0\" style=\"width: ${appDetail.memUsePercent}%\">\n\t\t\t                    \t</c:when>\n\t\t                    \t\t<c:otherwise>\n\t\t\t\t\t\t\t\t\t\t<div class=\"progress-bar progress-bar-success\"\n\t\t\t\t\t\t\t\t\t\t\trole=\"progressbar\" aria-valuenow=\"${appDetail.memUsePercent}\" aria-valuemax=\"100\"\n\t\t\t\t\t\t\t\t\t\t\taria-valuemin=\"0\" style=\"width: ${appDetail.memUsePercent}%\">\t\t\t\t                    \t\t</c:otherwise>\n\t\t                    \t</c:choose>\n\t\t\t\t\t\t\t\t\t<label style=\"color: #000000\">\n\t\t\t\t\t\t\t\t\t\t<fmt:formatNumber value=\"${appDetail.mem  * appDetail.memUsePercent / 100 / 1024}\" pattern=\"0.00\"/>G&nbsp;&nbsp;Used/<fmt:formatNumber value=\"${appDetail.mem / 1024 * 1.0}\" pattern=\"0.00\"/>G&nbsp;&nbsp;Total\n\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</td>\n\t\t\t\t\t\t<td>当前连接数</td>\n\t\t\t\t\t\t<td>${appDetail.conn}</td>\n\t\t\t\t\t</tr>\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t<td>应用主节点数</td>\n\t\t\t\t\t\t<td>${appDetail.masterNum}</td>\n\t\t\t\t\t\t<td>应用从节点数</td>\n\t\t\t\t\t\t<td>${appDetail.slaveNum}</td>\n\t\t\t\t\t</tr>\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t<td>应用命中率</td>\n\t\t\t\t\t\t<td>${appDetail.hitPercent}%</td>\n\t\t\t\t\t\t<td>当前对象数</td>\n\t\t\t\t\t\t<td><fmt:formatNumber value=\"${appDetail.currentObjNum}\" pattern=\"#,#00\"/></td>\n\t\t\t\t\t</tr>\n                    <tr>\n                        <td>应用当前状态</td>\n                        <td>${appDetail.appDesc.statusDesc}</td>\n                        <td>应用分布机器节点数</td>\n                        <td>${appDetail.machineNum}</td>\n                    </tr>\n\t\t\t\t</tbody>\n\t\t\t</table>\n\n\t\t\t<div class=\"page-header\">\n\t\t\t\t<h4>各命令峰值信息</h4>\n\t\t\t</div>\n\t\t\t<table class=\"table table-striped table-hover\">\n\t\t\t\t<tbody>\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t<td>命令</td>\n\t\t\t\t\t\t<td>峰值QPM</td>\n\t\t\t\t\t\t<td>峰值产生时间</td>\n\t\t\t\t\t</tr>\n\t\t\t\t\t<c:forEach items=\"${top5ClimaxList}\" var=\"command\">\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td>${command.commandName}</td>\n\t\t\t\t\t\t\t<td><fmt:formatNumber value=\"${command.commandCount}\" pattern=\"#,#00\"/></td>\n\t\t\t\t\t\t\t<td><fmt:formatDate value=\"${command.createTime}\" pattern=\"yyyy-MM-dd HH:mm:ss\"/></td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t</c:forEach>\n\t\t\t\t</tbody>\n\t\t\t</table>\n\n\t\t</div>\n\t\t<div class=\"col-md-6\">\n\t\t\t<div class=\"page-header\">\n\t\t\t\t<h4>命令统计</h4>\n\t\t\t</div>\n\t\t\t<div id=\"containerTop5\"\n\t\t\t\tstyle=\"min-width: 310px; height: 400px; margin: 0 auto\"></div>\n\t\t</div>\n\t</div>\n\t<script type=\"text/javascript\">\n\t\t$(document).ready(\n\t\t\tfunction() {\n\t\t\t    var title =  \"<b>命令分布</b>\";\n\t\t\t    var chartType = \"pie\";\n\t\t\t   \tvar options = {\n\t\t\t\t\tchart: {\n\t\t\t\t\t\trenderTo:'containerTop5',\n\t\t\t\t\t\tanimation: Highcharts.svg,\n\t\t\t\t\t\tbackgroundColor: '#E6F1F5',\n\t\t\t\t\t\tplotBackgroundColor:'#FFFFFF',\n\t\t\t\t\t\ttype: chartType,\n\t\t\t\t\t\tmarginRight: 10\n\t\t\t\t\t},\n\t\t            title: {\n\t\t            \tuseHTML:true,\n\t\t                text: title\n\t\t            },\n\t\t            xAxis: {\n\t\t                type: 'category'\n\t\t            },\n\t\t            yAxis: {\n\t\t            \ttitle: {\n                    \t\ttext: ''\n                \t\t},\n\t\t                plotLines: [{\n\t\t                    value: 0,\n\t\t                    width: 1,\n\t\t                    color: '#808080'\n\t\t                }]\n\t\t            },\n\t\t            plotOptions: {\n\t\t                line: {\n\t\t                    dataLabels: {\n\t\t                        enabled: true\n\t\t                    }\n\t\t                },\n\t\t                series: {\n\t\t\t                cursor: 'pointer'\n\t\t\t            }\n\t\t            },\n\t\t            tooltip: {\n\t\t                formatter: function() {\n\t\t                        return '<b>'+ this.point.name +'</b><br/>'\n\t\t                }\n\t\t            },\n\t\t            legend: {\n\t\t                enabled: true\n\t\t            },\n\t\t            credits:{\n\t\t            \tenabled: false\n\t\t            },\n\t\t            exporting: {\n\t\t                enabled: true\n\t\t            },\n\t\t            series: []\n\t\t        };\n\t            var pieUrl = \"/admin/app/getTop5Commands.do?appId=\"+appId+chartParams;\n\t\t    \t$.ajax({  \n\t\t          type : \"get\",  \n\t\t          url : pieUrl,  \n\t\t          async : true,  \n\t\t          success : function(data){\n\t\t          \tvar dataArr = eval(\"(\"+data+\")\");\n\t    \t\t\tvar length = dataArr.length;\n\t    \t\t\tvar legendName = \"命令分布统计\";\n\t    \t\t\tvar arr = [];\n\t                \n\t                for (var i = 0; i <length; i++) {\n\t                    var data = dataArr[i];\n                  \t\tvar pointName = data.commandName + \":\" + data.y;\n\t                    var point = {\n\t                    \tname:pointName,\n\t                        y: data.y\n\t                    };\n\t                    arr.push(point);\n\t                }\n             \t    var series={\n\t    \t\t\t\tname:legendName,\n\t    \t\t\t\tdata:arr\n\t    \t\t\t};\n\t    \t\t\toptions.series.push(series);\n     \t\t        new Highcharts.Chart(options); \n\t\t          }\n\t\t    \t});\n\t\t    });\n\t</script>\n\t\n\t<!-- 命令相关 -->\n\t<script type=\"text/javascript\">\n\t\t//查询一天出每分钟数据\n\t\tif(betweenOneDay == 1){\n\t\t\t$(document).ready(\n\t\t\t\tfunction() {\n\t\t\t\t\tvar options = getOption(\"containerCommands\", \"<b>全命令统计</b>\", \"次数\");\n\t\t\t\t\tvar commandsUrl = \"/admin/app/getMutiDatesCommandStats.json?appId=\" + appId + betweenParams;\n\t\t\t\t\t$.ajax({\n\t\t\t\t\t\ttype : \"get\",\n\t\t\t\t\t\turl : commandsUrl,\n\t\t\t\t\t\tasync : true,\n\t\t\t\t\t\tsuccess : function(data) {\n\t\t\t\t\t\t\tvar dates = new Array();\n\t\t\t\t\t\t\tdates.push(startDate); \n\t\t\t\t\t\t\tdates.push(yesterDate);\n\t\t\t\t\t\t\tpushOptionSeries(options, data, dates, \"命令趋势图\");\n\t\t\t\t\t\t\tnew Highcharts.Chart(options);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\t\n\t\t\t });\n\t\t}else{\n\t\t\t$(document).ready(\n\t\t\t\tfunction() {\n\t\t\t\t\tvar options = getOption(\"containerCommands\", \"<b>全命令统计</b>\", \"次数\");\n\t\t\t\t\tvar commandsUrl = \"/admin/app/getCommandStats.do?appId=\" + appId + chartParams;\n\t\t\t\t\t$.ajax({\n\t\t\t\t\t\ttype : \"get\",\n\t\t\t\t\t\turl : commandsUrl,\n\t\t\t\t\t\tasync : true,\n\t\t\t\t\t\tsuccess : function(data) {\n\t\t\t\t\t\t\tvar nameLegend = \"命令趋势图\";\n\t\t\t\t\t\t\tvar finalPoints = getSeriesPoints(data, nameLegend);\n\t\t\t\t\t\t\toptions.series.push(finalPoints);\n\t\t\t\t\t\t\tnew Highcharts.Chart(options);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t });\n\t\t}\n\t</script>\n\t<div id=\"containerCommands\"\n\t\tstyle=\"min-width: 310px; height: 350px; margin: 0 auto\"></div>\n\n\t\n\t\n\t<!-- 命中相关 -->\n\t<script type=\"text/javascript\">\n\t\t//查询一天出每分钟数据\n\t\tif(betweenOneDay == 1){\n\t\t\t$(document).ready(\n\t\t\t\tfunction() {\n\t\t\t\t\tvar options = getOption(\"containerHits\", \"<b>命中统计</b>\", \"次数\");\n\t\t\t\t\tvar commandsUrl = \"/admin/app/getMutiDatesAppStats.json?appId=\" + appId + \"&statName=hits\"+betweenParams;\n\t\t\t\t\t$.ajax({\n\t\t\t\t\t\ttype : \"get\",\n\t\t\t\t\t\turl : commandsUrl,\n\t\t\t\t\t\tasync : true,\n\t\t\t\t\t\tsuccess : function(data) {\n\t\t\t\t\t\t\tvar dates = new Array();\n\t\t\t\t\t\t\tdates.push(startDate); \n\t\t\t\t\t\t\tdates.push(yesterDate);\n\t\t\t\t\t\t\tpushOptionSeries(options, data, dates, \"命中趋势图\");\n\t\t\t\t\t\t\tnew Highcharts.Chart(options);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t });\n\t\t}else{\n\t\t\t$(document).ready(\n\t\t\t\tfunction() {\n\t\t\t\t\tvar options = getOption(\"containerHits\", \"<b>命中统计</b>\", \"次数\");\n\t\t\t\t\tvar commandsUrl = \"/admin/app/getAppStats.json?appId=\" + appId + \"&statName=hits\"+chartParams + \"&timeDimensionalityIndex=1\";\n\t\t\t\t\t$.ajax({\n\t\t\t\t\t\ttype : \"get\",\n\t\t\t\t\t\turl : commandsUrl,\n\t\t\t\t\t\tasync : true,\n\t\t\t\t\t\tsuccess : function(data) {\n\t\t\t\t\t\t\tvar nameLegend = \"命中趋势图\";\n\t\t\t\t\t\t\tvar finalPoints = getSeriesPoints(data, nameLegend);\n\t\t\t\t\t\t\toptions.series.push(finalPoints);\n\t\t\t\t\t\t\tnew Highcharts.Chart(options);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t });\n\t\t}\n\t</script>\n\t<div id=\"containerHits\"\n\t\tstyle=\"min-width: 310px; height: 350px; margin: 0 auto\"></div>\n\t\n\t<!-- 网络流量 -->\n\t<script type=\"text/javascript\">\n\t\tvar allInstanceNetStatUrl = \"/admin/app/appInstanceNetStat?appId=\" + appId +chartParams; \n\t\t\t$(document).ready(\n\t\t\t\tfunction() {\n\t\t\t\t\tvar options = getOption(\"containerNet\", \"网络流量<a href='\"+allInstanceNetStatUrl+\"' target='_blank'>(查看实例流量)</a>\", \"\");\n\t\t\t\t\t//网络流量\n\t\t\t\t\tvar netUrl = \"/admin/app/getMutiStatAppStats.json?appId=\" + appId + \"&statName=netInput,netOutput\" + chartParams;\n\t\t\t\t\t$.ajax({\n\t\t\t\t\t\ttype : \"get\",\n\t\t\t\t\t\turl : netUrl,\n\t\t\t\t\t\tasync : true,\n\t\t\t\t\t\tsuccess : function(data) {\n\n\t\t\t\t\t\t\tvar dataObject = eval(\"(\" + data.data + \")\");\n\t\t\t\t\t\t\tvar inputDataArr = dataObject[\"netInput\"];\n\n\t\t\t\t\t\t\t//1.input\n\t\t\t\t\t\t\tvar inputPoints = getNetPoints(inputDataArr, \"net_input\");\n\t\t\t\t\t\t\t//确认单位\n\t\t\t\t\t\t\toptions.yAxis.title.text = inputPoints.unitTxt;\n\t\t\t\t\t\t\tvar unit = inputPoints.unit;\n\t\t\t\t\t\t\toptions.series.push(inputPoints);\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t//2.output\n\t\t\t\t\t\t\tvar outputDataArr = dataObject[\"netOutput\"];\n\t\t\t\t\t\t\tvar outputPoints = getNetPoints(outputDataArr, \"net_output\", unit);\n\t\t\t\t\t\t\toptions.series.push(outputPoints);\n\n\t\t\t\t\t\t\tnew Highcharts.Chart(options);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t });\n\t</script>\n\t<div id=\"containerNet\"\n\t\tstyle=\"min-width: 310px; height: 350px; margin: 0 auto\"></div>\n\t\t\n\t<!-- 内存变化相关 -->\n\t<script type=\"text/javascript\">\n\t\t//查询一天出每分钟数据\n\t\t\n\t\t/*if(betweenOneDay == 1){*/\n\t\t\t\n\t\t\t$(document).ready(\n\t\t\t\tfunction() {\n\t\t\t\t\tvar options = getOption(\"containerMemory\", \"<b>内存使用量</b>\", \"M\");\n\t\t\t\t\tvar commandsUrl = \"/admin/app/getAppStats.do?appId=\" + appId + \"&statName=usedMemory\"+chartParams;\n\t\t\t\t\t$.ajax({\n\t\t\t\t\t\ttype : \"get\",\n\t\t\t\t\t\turl : commandsUrl,\n\t\t\t\t\t\tasync : true,\n\t\t\t\t\t\tsuccess : function(data) {\n\t\t\t\t\t\t\tvar nameLegend = \"内存使用量(\" + startDate + \")\";\n\t\t\t\t\t\t\tvar finalPoints = getSeriesPoints(data, nameLegend, \"M\");\n\t\t\t\t\t\t\toptions.series.push(finalPoints);\n\t\t\t\t\t\t\tvar maxMemoryPoints = getSeriesPoints(data, \"应用总内存\", \"M\", parseInt(appTotalMem));\n\t\t\t\t\t\t\toptions.series.push(maxMemoryPoints);\n\t\t\t\t\t\t\tnew Highcharts.Chart(options);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t });\n\t\t/*}*/\n\t\t/*\n\t\telse{\n\t\t\t$(document).ready(\n\t\t\t\tfunction() {\n\t\t\t\t\tvar options = getOption(\"containerMemory\", \"<b>内存使用量</b>\", \"字节\");\n\t\t\t\t\tvar commandsUrl = \"/admin/app/getAppStats.do?appId=\" + appId + \"&statName=usedMemory\"+chartParams;\n\t\t\t\t\t$.ajax({\n\t\t\t\t\t\ttype : \"get\",\n\t\t\t\t\t\turl : commandsUrl,\n\t\t\t\t\t\tasync : false,\n\t\t\t\t\t\tsuccess : function(data) {\n\t\t\t\t\t\t\tvar nameLegend = \"内存使用量\";\n\t\t\t\t\t\t\tvar finalPoints = getSeriesPoints(data, nameLegend, \"M\");\n\t\t\t\t\t\t\toptions.series.push(finalPoints);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tnew Highcharts.Chart(options);\n\t\t\t });\n\t\t}\n\t\t*/\n\t\t\n\t</script>\n\t<div id=\"containerMemory\"\n\t\tstyle=\"min-width: 310px; height: 350px; margin: 0 auto\"></div>\n\t\n\t\n\t<!-- 客户端连接数相关 -->\n\t<script type=\"text/javascript\">\n\t\t//查询一天出每分钟数据\n\t\t\t$(document).ready(\n\t\t\t\tfunction() {\n\t\t\t\t\tvar options = getOption(\"containerClients\", \"<b>客户端连接统计</b>\", \"个\");\n\t\t\t\t\tvar commandsUrl = \"/admin/app/getMutiDatesAppStats.json?appId=\" + appId + \"&statName=connectedClient\"+betweenParams;\n\t\t\t\t\t$.ajax({\n\t\t\t\t\t\ttype : \"get\",\n\t\t\t\t\t\turl : commandsUrl,\n\t\t\t\t\t\tasync : true,\n\t\t\t\t\t\tsuccess : function(data) {\n\t\t\t\t\t\t\tvar dates = new Array();\n\t\t\t\t\t\t\tdates.push(startDate); \n\t\t\t\t\t\t\tdates.push(yesterDate);\n\t\t\t\t\t\t\tpushOptionSeries(options, data, dates, \"客户端连接趋势图\", \"个\");\n\t\t\t\t\t\t\tnew Highcharts.Chart(options);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t });\n\t</script>\n\t<div id=\"containerClients\"\n\t\tstyle=\"min-width: 310px; height: 350px; margin: 0 auto\"></div>\n\t\n\t\n\t<!-- bsize相关 -->\n\t<script type=\"text/javascript\">\n\t\t//查询一天出每分钟数据\n\t\t\t$(document).ready(\n\t\t\t\tfunction() {\n\t\t\t\t\tvar options = getOption(\"containerDbsize\", \"<b>键个数统计</b>\", \"个\");\n\t\t\t\t\tvar commandsUrl = \"/admin/app/getMutiDatesAppStats.json?appId=\" + appId + \"&statName=objectSize\"+betweenParams;\n\t\t\t\t\t$.ajax({\n\t\t\t\t\t\ttype : \"get\",\n\t\t\t\t\t\turl : commandsUrl,\n\t\t\t\t\t\tasync : true,\n\t\t\t\t\t\tsuccess : function(data) {\n\t\t\t\t\t\t\tvar dates = new Array();\n\t\t\t\t\t\t\tdates.push(startDate); \n\t\t\t\t\t\t\tdates.push(yesterDate);\n\t\t\t\t\t\t\tpushOptionSeries(options, data, dates, \"键个数趋势图\", \"个\");\n\t\t\t\t\t\t\tnew Highcharts.Chart(options);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t });\n\t</script>\n\t<div id=\"containerDbsize\"\n\t\tstyle=\"min-width: 310px; height: 350px; margin: 0 auto\"></div>\n\t\n\t<br/>\n\t<br/>\n\t<br/>\n</div>\n\n<!-- 扩容申请 -->\n<div id=\"appScaleApplyModal\" class=\"modal fade\" tabindex=\"-1\" data-width=\"400\">\n\t<div class=\"modal-dialog\">\n\t\t<div class=\"modal-content\">\n\t\t\n\t\t\t<div class=\"modal-header\">\n\t\t\t\t<button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\"></button>\n\t\t\t\t<h4 class=\"modal-title\">申请扩容</h4>\n\t\t\t</div>\n\t\t\t\n\t\t\t<form class=\"form-horizontal form-bordered form-row-stripped\">\n\t\t\t\t<div class=\"modal-body\">\n\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t<!-- 控件开始 -->\n\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t<!-- form-body开始 -->\n\t\t\t\t\t\t\t<div class=\"form-body\">\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">申请容量:</label>\n\t\t\t\t\t\t\t\t\t<div class=\"col-md-7\">\n\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"applyMemSize\" id=\"applyMemSize\" placeholder=\"申请扩容容量\" class=\"form-control\"/>\n\t\t\t\t\t\t\t\t\t\t<span class=\"help-block\">例如填写: 512M,1G,2G..20G</span>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">申请原因:</label>\n\t\t\t\t\t\t\t\t\t<div class=\"col-md-7\">\n\t\t\t\t\t\t\t\t\t\t<textarea rows=\"5\"  name=\"appScaleReason\" id=\"appScaleReason\" placeholder=\"申请扩容原因\" class=\"form-control\"></textarea>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<!-- form-body 结束 -->\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div id=\"appScaleApplyInfo\"></div>\n\t\t\t\t\t\t<!-- 控件结束 -->\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t\n\t\t\t\t<div class=\"modal-footer\">\n\t\t\t\t\t<button type=\"button\" data-dismiss=\"modal\" class=\"btn\" >Close</button>\n\t\t\t\t\t<button type=\"button\" class=\"btn red\" onclick=\"appScaleApply('${appDetail.appDesc.appId}')\">Ok</button>\n\t\t\t\t</div>\n\t\t\t\n\t\t\t</form>\n\t\t</div>\n\t</div>\n</div>\n\n<div id=\"appConfigChangeModal\" class=\"modal fade\" tabindex=\"-1\" data-width=\"400\">\n\t<div class=\"modal-dialog\">\n\t\t<div class=\"modal-content\">\n\t\t\n\t\t\t<div class=\"modal-header\">\n\t\t\t\t<button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\"></button>\n\t\t\t\t<h4 class=\"modal-title\">应用配置修改</h4>\n\t\t\t</div>\n\t\t\t\n\t\t\t<form class=\"form-horizontal form-bordered form-row-stripped\">\n\t\t\t\t<div class=\"modal-body\">\n\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t<!-- 控件开始 -->\n\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t<!-- form-body开始 -->\n\t\t\t\t\t\t\t<div class=\"form-body\">\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">配置项:</label>\n\t\t\t\t\t\t\t\t\t<div class=\"col-md-8\">\n\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"appConfigKey\" id=\"appConfigKey\" placeholder=\"例如:maxclients\" class=\"form-control\" />\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">配置值:</label>\n\t\t\t\t\t\t\t\t\t<div class=\"col-md-8\">\n\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"appConfigValue\" id=\"appConfigValue\" placeholder=\"例如:15000\" class=\"form-control\">\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\n                                <div class=\"form-group\">\n                                    <label class=\"control-label col-md-3\">修改原因:</label>\n                                    <div class=\"col-md-8\">\n                                        <textarea name=\"appConfigReason\" id=\"appConfigReason\" placeholder=\"例如：修改原因:1.需要更多的连接数。\" class=\"form-control\"></textarea>\n                                        <%--<input type=\"text\" name=\"appConfigReason\" id=\"appConfigReason\" placeholder=\"例如：修改原因:1.需要更多的连接数。\" class=\"form-control\">--%>\n                                    </div>\n                                </div>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<!-- form-body 结束 -->\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div id=\"appConfigChangeInfo\"></div>\n\t\t\t\t\t\t<!-- 控件结束 -->\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t\n\t\t\t\t<div class=\"modal-footer\">\n\t\t\t\t\t<button type=\"button\" data-dismiss=\"modal\" class=\"btn\" >Close</button>\n\t\t\t\t\t<button type=\"button\" id=\"appConfigChangeBtn\" class=\"btn red\" onclick=\"appConfigChange('${appId}','${instanceId}')\">Ok</button>\n\t\t\t\t</div>\n\t\t\t\n\t\t\t</form>\n\t\t</div>\n\t</div>\n</div>\n\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/app/appTopology.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n\n<div class=\"row\">\n    <div class=\"page-header\">\n        <h4>应用拓扑结构-<a href=\"/admin/app/index.do?appId=${appDesc.appId}\">${appDesc.name}</a></h4>\n    </div>\n    <div style=\"margin-top: 20px\">\n        <table class=\"table table-bordered table-striped table-hover\">\n            <thead>\n            <tr>\n                <td>ID</td>\n                <td>实例</td>\n                <td>实例状态</td>\n                <td>内存使用</td>\n                <td>对象数</td>\n                <td>连接数</td>\n                <td>命中率</td>\n                <td>碎片率</td>\n                <td>角色</td>\n                <td>主实例ID</td>\n            </tr>\n            </thead>\n            <tbody>\n            <c:forEach var=\"instance\" items=\"${instanceList}\" varStatus=\"status\">\n            \t<c:set var=\"instanceStatsMapKey\" value=\"${instance.ip}:${instance.port}\"></c:set>\n                <tr>\n                    <td>\n                    \t <a href=\"/admin/instance/index.do?instanceId=${instance.id}\" target=\"_blank\">${instance.id}</a>\n                    \t <c:if test=\"${instance.masterInstanceId == 0 && instance.status != 2}\">\n\t\t\t\t\t\t\t<span class=\"glyphicon glyphicon-star\"></span>\t                         \n\t                     </c:if>\n                    </td>\n                    <td><a href=\"/server/index.do?ip=${instance.ip}\" target=\"_blank\">${instance.ip}</a>:${instance.port}</td>\n                    <td>${instance.statusDesc}</td>\n\t\t\t\t\t<td>\n\t\t\t\t\t\t<c:choose>\n\t\t\t\t\t\t\t<c:when test=\"${(instanceStatsMap[instanceStatsMapKey]).memUsePercent >= 80}\">\n\t\t\t\t\t\t\t\t<c:set var=\"progressBarStatus\" value=\"progress-bar-danger\"/>\n\t\t\t\t\t\t\t</c:when>\n\t\t\t\t\t\t\t<c:otherwise>\n\t\t\t\t\t\t\t\t<c:set var=\"progressBarStatus\" value=\"progress-bar-success\"/>\n\t\t\t\t\t\t\t</c:otherwise>\n\t\t\t\t\t\t</c:choose>\n\t\t\t\t\t\n                         <div class=\"progress margin-custom-bottom0\">\n                               <div class=\"progress-bar ${progressBarStatus}\"\n                                    role=\"progressbar\"\n                                    aria-valuenow=\"${(instanceStatsMap[instanceStatsMapKey]).memUsePercent}\"\n                                    aria-valuemax=\"100\"\n                                    aria-valuemin=\"0\"\n                                    style=\"width: ${(instanceStatsMap[instanceStatsMapKey]).memUsePercent}%\">\n                                    \n\t                               \t<label style=\"color: #000000\">\n\t                                   <fmt:formatNumber value=\"${(instanceStatsMap[instanceStatsMapKey]).usedMemory / 1024 / 1024 / 1024}\" pattern=\"0.00\"/>G&nbsp;&nbsp;Used/<fmt:formatNumber value=\"${(instanceStatsMap[instanceStatsMapKey]).maxMemory / 1024 / 1024 / 1024}\" pattern=\"0.00\"/>G&nbsp;&nbsp;Total\n\t                               \t</label>\n                                </div>\n                         </div>\n                  </td>\n                  <td>\n                  ${(instanceStatsMap[instanceStatsMapKey]).currItems}\n                  </td>\n                  <td>${(instanceStatsMap[instanceStatsMapKey]).currConnections}</td>\n                  <td>${(instanceStatsMap[instanceStatsMapKey]).hitPercent}</td>\n                  <td>\n\t                  <c:set var=\"memFragmentationRatio\" value=\"${(instanceStatsMap[instanceStatsMapKey]).memFragmentationRatio}\"/>\n\t                  <c:choose>\n\t                \t\t<c:when test=\"${memFragmentationRatio > 5 && (instanceStatsMap[instanceStatsMapKey]).usedMemory > 1024 * 1024 * 100}\">\n\t                \t\t\t  <c:set var=\"memFragmentationRatioLabel\" value=\"label-danger\"/>\n\t                \t\t</c:when>\n\t                \t\t<c:when test=\"${memFragmentationRatio >= 3 && memFragmentationRatio < 5 && (instanceStatsMap[instanceStatsMapKey]).usedMemory > 1024 * 1024 * 100}\">\n\t                \t\t\t  <c:set var=\"memFragmentationRatioLabel\" value=\"label-warning\"/>\n\t                \t\t</c:when>\n\t                \t\t<c:otherwise>\n\t                \t\t\t  <c:set var=\"memFragmentationRatioLabel\" value=\"label-success\"/>\n\t                 \t\t</c:otherwise>\n\t                  </c:choose>\n\t                  <label class=\"label ${memFragmentationRatioLabel}\">${memFragmentationRatio}</label>\n                  </td>\n                  <td>${instance.roleDesc}</td>\n                  <c:choose>\n                     <c:when test=\"${instance.masterInstanceId >0}\">\n                         <td>\n                             <a href=\"/admin/instance/index.do?instanceId=${instance.masterInstanceId}\" target=\"_blank\">${instance.masterInstanceId}</a>\n                         </td>\n                     </c:when>\n                     <c:otherwise>\n                         <td></td>\n                     </c:otherwise>\n                 </c:choose>\n                </tr>\n            </c:forEach>\n            </tbody>\n        </table>\n    </div>\n</div>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/app/initBecomeContributor.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <title>成为cachecloud贡献者</title>\n    <jsp:include page=\"/WEB-INF/include/head.jsp\"/>\n    <script type=\"text/javascript\">\n    \tfunction applyBecomeContributor(){\n    \t\tvar groupName = document.getElementById(\"groupName\");\n    \t\tif(groupName.value == \"\"){\n    \t\t\talert(\"请填写所在项目组!\");\n    \t\t\tgroupName.focus();\n    \t\t\treturn false;\n    \t\t}\n    \t\t\n    \t\tvar checked = false;\n    \t\tvar reason = \"\";\n    \t\tvar arr = document.getElementsByName(\"applyReason\");\n    \t\tvar i; \n    \t\tfor(i=0;i<arr.length;i++) { \n    \t\t\tif(arr[i].type=='checkbox' && arr[i].checked==true) {\n    \t\t\t\tchecked = true;\n    \t\t\t\treason = reason + arr[i].value + \"<br/>\";\n    \t\t\t} \n    \t\t}\n    \t\tif(checked == false){\n    \t\t\talert(\"请填写申请原因!\");\n    \t\t\treturn false;\n    \t\t}\n    \t\t \n    \t\t$.post(\n    \t\t\t'/admin/app/addBecomeContributor.json',\n    \t\t\t{\n    \t\t\t\tgroupName: groupName.value,\n    \t\t\t\tapplyReason: reason\n    \t\t\t},\n    \t        function(data){\n    \t            if(data.success==1){\n    \t                alert(\"申请成功,请在邮件中关注申请状况.\");\n    \t            }\n    \t        }\n    \t     );\n    \t}\n    </script>\n</head>\n<body>\n\t<div class=\"container\">\n\t    <jsp:include page=\"/WEB-INF/include/headMenu.jsp\"/>\n\t    <div id=\"systemAlert\">\n\t    </div>\n\t\t<div class=\"page-content\">\n\t\t\t<div class=\"row\">\n\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t<h3 class=\"page-header\">\n\t\t\t\t\t\t成为Cachecloud贡献者\n\t\t\t\t\t</h3>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"row\">\n\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t<div class=\"portlet box light-grey\">\n\t\t\t\t\t\t<div class=\"portlet-body\">\n\t\t\t\t\t\t\t<div class=\"form\">\n\t\t\t\t\t\t\t\t\t<!-- BEGIN FORM-->\n\t\t\t\t\t\t\t\t\t<form action=\"/admin/app/applyBecomeContributor.do\" method=\"post\"\n\t\t\t\t\t\t\t\t\t\tclass=\"form-horizontal form-bordered form-row-stripped\">\n\t\t\t\t\t\t\t\t\t\t<div class=\"form-body\">\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t项目组<font color='red'>(*)</font>:\n\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"groupName\" id=\"groupName\" placeholder=\"项目组\" class=\"form-control\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"help-block\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t(必填，所在项目组)\n\t\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t \t希望得到<font color='red'>(*)</font>:\n\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<input type=\"checkbox\" name=\"applyReason\" value=\"提升DevOps的能力\"/>提升DevOps的能力<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<input type=\"checkbox\" name=\"applyReason\" value=\"云产品的开发经验和思维方式\"/>云产品的开发经验和思维方式<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<input type=\"checkbox\" name=\"applyReason\" value=\"体验到自动化带来的好处,体现到自己的系统中\"/>体验到自动化带来的好处,体现到自己的系统中<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<input type=\"checkbox\" name=\"applyReason\" value=\"Redis深入掌握\"/>Redis深入掌握 <br/>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t<input name=\"userId\" id=\"userId\" value=\"${userInfo.id}\" type=\"hidden\" />\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-actions fluid\">\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-offset-4 col-md-9\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<button type=\"button\" id=\"applyBecomeContributorBtn\" class=\"btn green\" onclick=\"applyBecomeContributor()\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-check\"></i>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t提交申请\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t&nbsp;&nbsp;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<button type=\"reset\" class=\"btn green\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-check\"></i>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t&nbsp;&nbsp;重&nbsp;&nbsp;&nbsp;置&nbsp;&nbsp;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</form>\n\t\t\t\t\t\t\t\t\t<!-- END FORM-->\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<!-- END TABLE PORTLET-->\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t<br/><br/><br/><br/><br/><br/><br/>\n\t<jsp:include page=\"/WEB-INF/include/foot.jsp\"/>\n</body>\n</html>\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/app/manageUser.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<div id=\"manageUser\" class=\"modal fade\" tabindex=\"-1\" data-width=\"400\">\n\t<div class=\"modal-dialog\">\n\t\t<div class=\"modal-content\">\n\t\t\n\t\t\t<div class=\"modal-header\">\n\t\t\t\t<button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\"></button>\n\t\t\t\t<h4 class=\"modal-title\">添加用户</h4>\n\t\t\t</div>\n\t\t\t\n\t\t\t<form action=\"/user/add.do\" method=\"post\" class=\"form-horizontal form-bordered form-row-stripped\">\n\t\t\t\t<div class=\"modal-body\">\n\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t<!-- 控件开始 -->\n\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t<div class=\"form-body\">\n\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t用户名:\n\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"name\" id=\"user.name\"\n\t\t\t\t\t\t\t\t\t\t\tvalue=\"${user.name}\" placeholder=\"用户名\"\n\t\t\t\t\t\t\t\t\t\t\tclass=\"form-control\" />\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t邮箱:\n\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"email\" id=\"user.email\"\n\t\t\t\t\t\t\t\t\t\t\tvalue=\"${user.email}\" placeholder=\"邮箱\"\n\t\t\t\t\t\t\t\t\t\t\tclass=\"form-control\" />\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t手机:\n\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"mobile\" id=\"user.mobile\"\n\t\t\t\t\t\t\t\t\t\t\tvalue=\"${user.mobile}\" placeholder=\"手机\"\n\t\t\t\t\t\t\t\t\t\t\tclass=\"form-control\" />\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<!-- 控件结束 -->\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t\n\t\t\t\t<div class=\"modal-footer\">\n\t\t\t\t\t<button type=\"button\" data-dismiss=\"modal\" class=\"btn\">Close</button>\n\t\t\t\t\t<button type=\"submit\" class=\"btn red\">Ok</button>\n\t\t\t\t</div>\n\t\t\t\n\t\t\t</form>\n\t\t</div>\n\t</div>\n</div>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/app/slowLog.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n\n\n<script type=\"text/javascript\">\n\nfunction calDateWidgetDifMs(start, end) {\n\tvar startTime = start.replace(/-/g, \"/\"); \n\tvar endTime = end.replace(/-/g,\"/\");\n\tvar startDate = new Date(Date.parse(startTime)).getTime();\n\tvar endDate = new Date(Date.parse(endTime)).getTime();\n\t//毫秒差\n\treturn (endDate - startDate);\n}\n\nfunction search() {\n    var slowLogStartDate = document.getElementById(\"slowLogStartDate\").value;\n    var slowLogEndDate = document.getElementById(\"slowLogEndDate\").value;\n\tvar difTime = calDateWidgetDifMs(slowLogStartDate, slowLogEndDate);\n\tif (difTime > 86400000 * 30) {\n\t\talert(\"日期跨度最大为一个月，请重新选择!\");\n\t} else {\n\t\tdocument.getElementById(\"appSlowLogForm\").submit();\n\t}\n}\n</script>\n<div class=\"container\">\n\t<br/>\n    <form method=\"get\" action=\"/admin/app/index.do\" id=\"appSlowLogForm\">\n\t\t<div class=\"row\">\n\t\t\t<div style=\"float:right\">\n\t\t\t\t\t<label style=\"font-weight:bold;text-align:left;\">\n\t\t\t\t\t \t&nbsp;开始日期:&nbsp;&nbsp;\n\t\t\t\t\t</label>\n\t\t\t\t\t<input type=\"text\" size=\"21\" name=\"slowLogStartDate\" id=\"slowLogStartDate\" value=\"${slowLogStartDate}\" onFocus=\"WdatePicker({startDate:'%y-%M-01',dateFmt:'yyyy-MM-dd',alwaysUseStartDate:true})\"/>\n\t\t\t\t\t\n\t\t\t\t\t<label style=\"font-weight:bold;text-align:left;\">\n\t\t\t\t\t \t结束日期:\n\t\t\t\t\t</label>\n\t\t\t\t\t<input type=\"text\" size=\"20\" name=\"slowLogEndDate\" id=\"slowLogEndDate\" value=\"${slowLogEndDate}\" onFocus=\"WdatePicker({startDate:'%y-%M-01',dateFmt:'yyyy-MM-dd',alwaysUseStartDate:true})\"/>\n\t\t\t\t\t\n\t\t\t\t\t<input type=\"hidden\" name=\"appId\" value=\"${appDesc.appId}\">\n\t\t\t\t\t<input type=\"hidden\" name=\"tabTag\" value=\"app_slow_log\">\n\t\t\t\t\t<label>&nbsp;<input type=\"button\" class=\"btn-4\" value=\"查询\" onclick=\"search()\"/></label>\n\t\t\t</div>\n\t\t</div>\n\t</form>\n\t\n\t<div class=\"row\">\n        <div class=\"col-md-12\">\n\t\t\t<div class=\"page-header\">\n                <h4>\n                    <label class=\"label label-success\">一共${fn:length(appInstanceSlowLogList)}次慢查询</label>\n                </h4>\n            </div>\n\n            <table class=\"table table-striped table-hover\">\n                <thead>\n                <tr>\n                    <td>序号</td>\n                    <td>实例信息</td>\n                    <td>个数</td>\n                </tr>\n                </thead>\n                <tbody>\n\t                <c:forEach items=\"${appInstanceSlowLogCountMap}\" var=\"item\" varStatus=\"stats\">\n\t                    <tr>\n\t                        <td>${stats.index + 1}</td>\n\t                        <td>\n\t                            <a href=\"#${item.key}\">${item.key}</a>\n\t                        </td>\n\t                        <td>${item.value}</td>\n\t                    </tr>\n\t                </c:forEach>\n                </tbody>\n            </table>\n        </div>\n    </div>\n    \n    <c:forEach items=\"${instaceSlowLogMap}\" var=\"item\" varStatus=\"stats\">\n\t    <div style=\"margin-top: 20px\">\n\t    \t<div class=\"page-header\" id=\"${item.key}\">\n                <h4>${item.key}</h4>\n            </div>\n\t        <table class=\"table table-bordered table-striped table-hover\">\n\t            <thead>\n\t\t            <tr>\n\t\t                <td>实例</td>\n\t\t                <td>ip</td>\n\t\t                <td>port</td>\n\t\t                <td>慢查询id</td>\n\t\t                <td>耗时(单位:微秒)</td>\n\t\t                <td>命令</td>\n\t\t                <td>发生时间</td>\n\t\t            </tr>\n\t            </thead>\n\t            <tbody>\n\t\t            <c:forEach var=\"slowLog\" items=\"${item.value}\" varStatus=\"status\">\n\t\t                <tr>\n\t\t                  <td>\n\t\t                  \t<a href=\"/admin/instance/index.do?instanceId=${slowLog.instanceId}\" target=\"_blank\">${slowLog.instanceId}</a>\n\t\t                  </td>\n\t\t                  <td>${slowLog.ip}</td>\n\t\t                  <td>${slowLog.port}</td>\n\t\t                  <td>${slowLog.slowLogId}</td>\n\t\t                  <td><fmt:formatNumber value=\"${slowLog.costTime}\" pattern=\"#,#00\"/></td>\n\t\t                  <td>${slowLog.command}</td>\n\t\t                  <td>${slowLog.executeTime}</td>\n\t\t                </tr>\n\t\t            </c:forEach>\n\t            </tbody>\n\t        </table>\n\t    </div>\t\n    </c:forEach>\n    \n</div>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/app/userAppsIndex.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\" %>\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <title>CacheCloud应用统计信息</title>\n    <jsp:include page=\"/WEB-INF/include/head.jsp\"/>\n    <script type=\"text/javascript\" src=\"/resources/js/jquery-console.js\"></script>\n    <script type=\"text/javascript\" src=\"/resources/js/chart.js\"></script>\n\n</head>\n<body role=\"document\">\n<div class=\"container\">\n    <jsp:include page=\"/WEB-INF/include/headMenu.jsp\"/>\n    <div id=\"systemAlert\">\n    </div>\n    <div class=\"tabbable-custom\">\n        <ul class=\"nav nav-tabs\" id=\"app_tabs\">\n            <li class=\"active\"><a href=\"#app_stat\"\n                                  data-url=\"/admin/app/stat.do?appId=${appId}&startDate=${startDate}&endDate=${endDate}\"\n                                  data-toggle=\"tab\">应用统计信息</a></li>\n            <!-- \n            <li><a href=\"#app_fault\" data-url=\"/admin/app/fault.do?appId=${appId}\" data-toggle=\"tab\">故障报警</a></li>\n            -->\n            <li><a href=\"#app_topology\" data-url=\"/admin/app/topology.do?appId=${appId}\" data-toggle=\"tab\">实例列表</a></li>\n            <li><a href=\"#app_detail\" data-url=\"/admin/app/detail.do?appId=${appId}\" data-toggle=\"tab\">应用详情</a></li>\n            <li><a href=\"#app_command_analysis\"\n                   data-url=\"/admin/app/commandAnalysis.do?appId=${appId}&startDate=${startDate}&endDate=${endDate}&firstCommand=${firstCommand}\"\n                   data-toggle=\"tab\">命令曲线</a></li>\n            <li><a href=\"#app_command\" data-url=\"/admin/app/command.html?appId=${appId}\"\n                   data-toggle=\"tab\">命令执行</a>\n            </li>\n            <li><a href=\"#app_demo\" data-url=\"/admin/app/demo.html?appId=${appId}\"\n                   data-toggle=\"tab\">接入代码</a>\n            </li>\n            <li><a href=\"#app_slow_log\" data-url=\"/admin/app/slowLog?appId=${appId}&slowLogStartDate=${slowLogStartDate}&slowLogEndDate=${slowLogEndDate}\"\n                   data-toggle=\"tab\">慢查询</a>\n            </li>\n            <li><a href=\"#app_top_pic\" data-url=\"/admin/app/machineInstancesTopology.do?appId=${appId}\" data-toggle=\"tab\">应用拓扑</a></li>\n            <li><a href=\"#app_daily\" data-url=\"/admin/app/daily?appId=${appId}&dailyDate=${dailyDate}\"\n                   data-toggle=\"tab\">日报统计</a>\n            </li>\n        </ul>\n        <div class=\"tab-content\">\n            <div class=\"tab-pane active\" id=\"app_stat\">\n            </div>\n            <!-- \n             <div class=\"tab-pane\" id=\"app_fault\">\n            </div>\n            -->\n            <div class=\"tab-pane\" id=\"app_topology\">\n            </div>\n            <div class=\"tab-pane\" id=\"app_detail\">\n            </div>\n            <div class=\"tab-pane\" id=\"app_command_analysis\">\n            </div>\n            <div class=\"tab-pane\" id=\"app_command\">\n            </div>\n            <div class=\"tab-pane\" id=\"app_demo\">\n            </div>\n            <div class=\"tab-pane\" id=\"app_slow_log\">\n            </div>\n            <div class=\"tab-pane\" id=\"app_top_pic\">\n            </div>\n            <div class=\"tab-pane\" id=\"app_daily\">\n            </div>\n        </div>\n    </div>\n</div>\n<jsp:include page=\"/WEB-INF/include/foot.jsp\"/>\n<script type=\"text/javascript\">\n    $('#app_tabs a').click(function (e) {\n        e.preventDefault();\n\n        var url = $(this).attr(\"data-url\");\n        var href = this.hash;\n        var pane = $(this);\n        var id = $(href).attr(\"id\");\n        // ajax load from data-url\n        $(href).load(url, function (result) {\n            pane.tab('show');\n            initChart(id);\n        });\n    });\n\n    var tabTag = \"${tabTag}\";\n    if (tabTag.length > 0 && $('#' + tabTag).length > 0) {\n        var tabId = '#' + tabTag;\n        $(\"a[href=\" + tabId + \"]\").click();\n    } else {\n        $(\"a[href=#app_stat]\").click();\n    }\n\n</script>\n<script type=\"text/javascript\" src=\"/resources/js/mem-cloud.js\"></script>\n<script type=\"text/javascript\" src=\"/resources/js/docs.min.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/client/appClientIndex.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\" %>\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <title>CacheCloud客户端信息</title>\n    <jsp:include page=\"/WEB-INF/include/head.jsp\"/>\n    <script type=\"text/javascript\" src=\"/resources/js/jquery-console.js\"></script>\n    <script type=\"text/javascript\" src=\"/resources/js/chart.js\"></script>\n    <script type=\"text/javascript\" src=\"/resources/js/appClient.js\"></script>\n\n</head>\n<body role=\"document\">\n\t<div class=\"container\">\n\t    <jsp:include page=\"/WEB-INF/include/headMenu.jsp\"/>\n\t    <div class=\"tabbable-custom\">\n\t        <ul class=\"nav nav-tabs\" id=\"app_tabs\">\n\t            <li class=\"active\"><a href=\"#app_client_cost_distribute\" data-url=\"/client/show/costDistribute.do?appId=${appId}&costDistriStartDate=${costDistriStartDate}&costDistriEndDate=${costDistriEndDate}&firstCommand=${firstCommand}&timeDimensionality=${timeDimensionality}\" data-toggle=\"tab\">耗时统计</a></li>\n\t            <li><a href=\"#app_client_value_distribute\" data-url=\"/client/show/valueDistribute.do?appId=${appId}&valueDistriStartDate=${valueDistriStartDate}&valueDistriEndDate=${valueDistriEndDate}\" data-toggle=\"tab\">值分布统计</a></li>\n\t            <li><a href=\"#app_client_exception\" data-url=\"/client/show/exception.do?appId=${appId}&exceptionStartDate=${exceptionStartDate}&exceptionEndDate=${exceptionEndDate}&type=${type}&clientIp=${clientIp}&pageNo=${pageNo}\" data-toggle=\"tab\">异常统计</a></li>\n\t        </ul>\n\t        <div class=\"tab-content\">\n\t            <div class=\"tab-pane active\" id=\"app_client_cost_distribute\">\n\t            </div>\n\t            <div class=\"tab-pane\" id=\"app_client_value_distribute\">\n\t            </div>\n\t            <div class=\"tab-pane\" id=\"app_client_exception\">\n\t            </div>\n\t        </div>\n\t    </div>\n\t</div>\n\t<jsp:include page=\"/WEB-INF/include/foot.jsp\"/>\n\t<script type=\"text/javascript\">\n\t    $('#app_tabs a').click(function (e) {\n\t        e.preventDefault();\n\t\n\t        var url = $(this).attr(\"data-url\");\n\t        var href = this.hash;\n\t        var pane = $(this);\n\t        var id = $(href).attr(\"id\");\n\t        // ajax load from data-url\n\t        $(href).load(url, function (result) {\n\t            pane.tab('show');\n\t        });\n\t    });\n\t\n\t    var tabTag = \"${tabTag}\";\n\t    if (tabTag.length > 0 && $('#' + tabTag).length > 0) {\n\t        var tabId = '#' + tabTag;\n\t        $(\"a[href=\" + tabId + \"]\").click();\n\t    } else {\n\t        $(\"a[href=#app_client_cost_distribute]\").click();\n\t    }\n\t</script>\n\t<script type=\"text/javascript\" src=\"/resources/js/docs.min.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/client/clientCostDistribute.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n\n<style>\n#clientInstanceDetailModal .modal-dialog\n{\n    width: 1000px; /* your width */\n}\n</style>\n\n<script type=\"text/javascript\">\n\nfunction search() {\n    var costDistriStartDate = document.getElementById(\"costDistriStartDate\").value;\n    var costDistriEndDate = document.getElementById(\"costDistriEndDate\").value;\n\tvar difTime = calDateWidgetDifMs(costDistriStartDate, costDistriEndDate);\n\tvar oneDayTime = 86400000;\n\tif (difTime > oneDayTime) {\n\t\talert(\"由于数据量较大,耗时查询暂不支持跨天查询!\");\n\t} else {\n\t\tdocument.getElementById(\"clientCostForm\").submit();\n\t}\n}\n</script>\n\n<div class=\"container\" id=\"mainClientCostContainer\">\n\t<br/>\n\t<form method=\"get\" action=\"/client/show/index.do\" id=\"clientCostForm\">\n\t\t<div class=\"row\">\n\t\t\t<div style=\"float:right\">\n\t\t\t\t\t<label style=\"font-weight:bold;text-align:left;\">\n\t\t\t\t\t \t&nbsp;开始日期:&nbsp;&nbsp;\n\t\t\t\t\t</label>\n\t\t\t\t\t<input type=\"text\" size=\"21\" name=\"costDistriStartDate\" id=\"costDistriStartDate\" value=\"${costDistriStartDate}\" onFocus=\"WdatePicker({startDate:'%y-%M-01',dateFmt:'yyyy-MM-dd',alwaysUseStartDate:true})\"/>\n\t\t\t\t\t\n\t\t\t\t\t<label style=\"font-weight:bold;text-align:left;\">\n\t\t\t\t\t \t结束日期:\n\t\t\t\t\t</label>\n\t\t\t\t\t<input type=\"text\" size=\"20\" name=\"costDistriEndDate\" id=\"costDistriEndDate\" value=\"${costDistriEndDate}\" onFocus=\"WdatePicker({startDate:'%y-%M-01',dateFmt:'yyyy-MM-dd',alwaysUseStartDate:true})\"/>\n\t\t\t\t\t\n\t\t\t\t\t<input type=\"hidden\" name=\"appId\" value=\"${appDesc.appId}\">\n\t\t\t\t\t<input type=\"hidden\" name=\"tabTag\" value=\"app_client_cost_distribute\">\n\t\t\t\t\t<input type=\"hidden\" id=\"firstCommand\" name=\"firstCommand\" value=\"${firstCommand}\">\n\t\t\t\t\t<label>&nbsp;<input type=\"button\" class=\"btn-4\" value=\"查询\" onclick=\"search()\"/></label>\n\t\t\t</div>\n\t\t</div>\n\t\t<div class=\"row\">\n\t\t\t\t<c:set var=\"needSelect\" value=\"0\"></c:set>\n\t\t\t\t&nbsp;&nbsp;Top5命令:\n\t\t\t\t<c:forEach items=\"${allCommands}\" var=\"item\" varStatus=\"stat\">\n\t\t\t\t\t<c:choose>\n\t\t\t\t\t\t<c:when test=\"${stat.index < 5}\">\n\t\t\t\t\t\t\t\t<input type=\"radio\" name=\"optionsRadios\" value=\"${item}\" \n\t\t\t\t\t\t\t\t<c:if test=\"${firstCommand == item}\">checked=\"checked\"</c:if>\n\t\t\t\t\t\t\t\t onchange=\"changeCommandChart(this.value)\" />\n\t\t\t\t\t\t\t\t${item}\n\t\t\t\t\t\t</c:when>\n\t\t\t\t\t\t<c:otherwise>\n\t\t\t\t\t\t\t<c:set var=\"needSelect\" value=\"1\"></c:set>\n\t\t\t\t\t\t</c:otherwise>\n\t\t\t\t\t</c:choose>\n\t\t\t\t</c:forEach>\n\t\t\t\t<c:if test=\"${needSelect == 1}\">\n\t\t\t\t\t&nbsp;&nbsp;&nbsp;其余命令:\n\t\t\t\t\t<select name=\"optionsRadios\" onchange=\"changeCommandChart(this.value)\">\n\t\t\t\t\t\t<option>请选择</option>\n\t\t\t\t\t\t<c:forEach items=\"${allCommands}\" var=\"item\" varStatus=\"stat\">\n\t\t\t\t\t\t\t<c:choose>\n\t\t\t\t\t\t\t\t<c:when test=\"${stat.index >= 5}\">\n\t\t\t\t\t\t\t\t\t<label>\n\t\t\t\t\t\t\t\t\t\t<option value=\"${item}\" <c:if test=\"${firstCommand == item}\">selected</c:if>>\n\t\t\t\t\t\t\t         \t\t${item}\n\t\t\t\t\t\t\t        \t</option>\n\t\t\t\t\t\t\t\t\t</label>\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t</c:when>\n\t\t\t\t\t\t\t</c:choose>\n\t\t\t\t\t\t</c:forEach>\n\t\t\t\t\t</select>\n\t\t\t\t</c:if>\n\t\t</div>\n\t</form>\n\t<script type=\"text/javascript\">\n\t\tvar firstCommand = '${firstCommand}';\n\t\tvar costDistriStartDate = '${costDistriStartDate}';\n\t\tvar costDistriEndDate = '${costDistriEndDate}';\n\t\tvar appId = '${appId}'; \n\t\tvar chartParams = \"&costDistriStartDate=\"+costDistriStartDate+\"&costDistriEndDate=\"+costDistriEndDate+\"&firstCommand=\"+firstCommand;\n\t\t//应用下客户端和实例的全局耗时\n\t\tvar appChartStatListJson = '${appChartStatListJson}';\n\t\t\n\t\tHighcharts.setOptions({\n\t\t\tglobal : {\n\t\t\t\tuseUTC : false\n\t\t\t}\n\t\t});\n\t\tHighcharts.setOptions({\n\t\t\tcolors : [ '#2f7ed8', '#E3170D', '#0d233a', '#8bbc21', '#1aadce',\n\t\t\t\t\t'#492970', '#804000', '#f28f43', '#77a1e5',\n\t\t\t\t\t'#c42525', '#a6c96a' ]\n\t\t});\n\t\tfunction changeCommandChart(value){\n\t\t\tdocument.getElementById(\"firstCommand\").value = value;\n\t\t\tdocument.getElementById(\"clientCostForm\").submit();\n\t\t}\n\t\t$(document).ready(\n\t\t\tfunction() {\n\t\t\t\tvar unit = \"毫秒\";\n\t\t\t\tvar dataArr = eval(\"(\"+appChartStatListJson+\")\");\n\t\t\t\tvar appTotalOptions = getOption(\"clientCostContainer\", \"<b>\"+firstCommand+\"命令-客户端耗时统计</b>\", unit);\n\t\t\t\tvar appTotalData = dataArr.app;\n\t\t\t\tvar appTotalTags = new Array(\"mean\", \"平均值\", \"median\", \"中位值\",\"max90\",\"90%最大值\",\"max99\", \"99%最大值\", \"max100\", \"最大值\");\n\t\t\t\t//appTotalOptions.plotOptions.series.animation = false;\n\t\t\t\tappTotalOptions.series = getClientCostSeriesPoints(1, appTotalData, appTotalTags, unit);\n\t\t\t\tvar appTotalchart = new Highcharts.Chart(appTotalOptions);\n\t\t\t\tif (appTotalchart.series.length >= 5) {\n\t\t\t\t\tappTotalchart.series[1].hide();\n\t\t\t\t\tappTotalchart.series[2].hide();\n\t\t\t\t\tappTotalchart.series[3].hide();\n\t\t\t\t}\n\t\t });\n\t\t\n\t\tfunction showDetailChart(instanceHost, instancePort, instanceId, clientIp){\n\t\t\tvar unit = \"毫秒\";\n\t\t\tvar url = \"/client/show/getAppClientInstanceCommandCost?appId=\" + appId + \"&instanceId=\" + instanceId + \"&clientIp=\" + clientIp + chartParams;\n\t\t\t$.ajax({\n\t\t\t\ttype : \"get\",\n\t\t\t\turl : url,\n\t\t\t\tasync : false,\n\t\t\t\tsuccess : function(data) {\n\t\t\t\t\tvar title = \"(\" + clientIp + \"--\" + instanceHost + \":\" + instancePort + \")\";\n\t\t\t\t\tvar dataArr = eval(\"(\"+data+\")\");\n\t\t\t\t\tvar clientInstanceOptions = getOption(\"detailContainer\", \"<b>\"+firstCommand+\"命令-客户端实例耗时统计\"+title+\"</b>\", unit);\n\t\t\t\t\tvar clientInstanceData = dataArr.clientInstanceStat;\n\t\t\t\t\tvar clientInstanceTags = new Array(\"mean\", \"平均值\", \"median\", \"中位值\",\"max90\",\"90%最大值\",\"max99\", \"99%最大值\", \"max100\", \"最大值\");\n\t\t\t\t\t//clientInstanceOptions.plotOptions.series.animation = false;\n\t\t\t\t\tclientInstanceOptions.series = getClientCostSeriesPoints(0, clientInstanceData, clientInstanceTags, unit);\n\t\t\t\t\tvar clientInstancechart = new Highcharts.Chart(clientInstanceOptions);\n\t\t\t\t\tif (clientInstancechart.series.length >= 5) {\n\t\t\t\t\t\tclientInstancechart.series[1].hide();\n\t\t\t\t\t\tclientInstancechart.series[2].hide();\n\t\t\t\t\t\tclientInstancechart.series[4].hide();\n\t\t\t\t\t}\n\t\t\t\t\t//标题\n\t\t\t\t\tdocument.getElementById(\"detailInstanceAndClient\").innerHTML = title;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\t\n\t\t\n\t</script>\n\t<div class=\"page-header\">\n\t\t<h4>\n\t\t\t应用耗时&nbsp;&nbsp;&nbsp;\n\t\t</h4>\n\t</div>\n\t<div id=\"clientCostContainer\"\n\t\tstyle=\"min-width: 310px; height: 350px; margin: 0 auto\"></div>\n\t<br/>\n\t<div class=\"page-header\">\n\t\t<h4>\n\t\t\t(客户端--redis实例)关系表\n\t\t</h4>\n\t</div>\n\t<table id=\"clientInstanceDetailTable\" class=\"table table-striped table-hover table-bordered\" style=\"margin-top: 0px\">\n \t\t<thead>\n\t\t\t<tr>\n\t\t\t\t<td>序号</td>\n\t\t\t\t<td>客户端</td>\n\t\t\t\t<td>redis实例</td>\n\t\t\t\t<td>图表</td>\n\t\t\t</tr>\n\t\t</thead>\n\t\t<tbody>\n\t\t\t<c:forEach items=\"${appInstanceClientRelationList}\" var=\"item\" varStatus=\"stat\">\n\t\t\t\t<tr>\n\t\t\t\t\t<td>${stat.index}</td>\n\t\t\t\t\t<td>${item.clientIp}</td>\n\t\t\t\t\t<td>${item.instanceHost}:${item.instancePort}</td>\n\t\t\t\t\t<td>\n\t\t\t\t\t\t<button type='button' class='btn btn-small btn-success' onclick=\"showDetailChart('${item.instanceHost}', '${item.instancePort}', '${item.instanceId}', '${item.clientIp}')\" data-target='#clientInstanceDetailModal' data-toggle='modal'>chart</button>\n\t\t\t\t\t</td>\n\t\t\t\t</tr>\n\t\t\t</c:forEach>\n\t\t</tbody>\n\t</table>\n\t\n\t<br/><br/><br/><br/><br/><br/><br/><br/>\n\t\n\t\n</div>\n\n<div id=\"clientInstanceDetailModal\" class=\"modal fade\" tabindex=\"-1\" data-width=\"1200\">\n\t<div class=\"modal-dialog\">\n\t\t<div class=\"modal-content\">\n\t\t\t\t<div class=\"modal-header\">\n\t\t\t\t\t<button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\"></button>\n\t\t\t\t\t<h4 class=\"modal-title\">\n\t\t\t\t\t客户端-redis实例耗时\n\t\t\t\t\t\t<span id=\"detailInstanceAndClient\"></span>\n\t\t\t\t\t</h4>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"modal-body\">\n\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t<div id=\"detailContainer\" style=\"width: 700px; height: 350px; margin: 0 auto\"></div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/client/clientException.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n\n<script type=\"text/javascript\">\nfunction search() {\n    var exceptionStartDate = document.getElementById(\"exceptionStartDate\").value;\n    var exceptionEndDate = document.getElementById(\"exceptionEndDate\").value;\n\tvar difTime = calDateWidgetDifMs(exceptionStartDate, exceptionEndDate);\n\tif (difTime > 86400000 * 7) {\n\t\talert(\"日期跨度最大为一个星期，请重新选择!\");\n\t} else {\n\t\tdocument.getElementById(\"searchExceptionForm\").submit();\n\t}\n}\n</script>\n\n<div class=\"container\">\n\t<div class=\"row\">\n\t\t<div class=\"col-md-12\"></div>\n\t</div>\n    <div class=\"row\">\n        <div class=\"col-md-12\">\n        \t<form method=\"get\" action=\"/client/show/index.do\" id=\"searchExceptionForm\">\n\t\t\t\t<div style=\"float:right\">\n\t\t\t\t\t\t<label style=\"font-weight:bold;text-align:left;\">\n\t\t\t\t\t\t \t客户端ip:\n\t\t\t\t\t\t</label>\n\t\t\t\t\t\t<input type=\"text\" value=\"${clientIp}\" name=\"clientIp\" size=\"12\">\n\t\t\t\t\t\t\n\t\t\t\t\t\t<label style=\"font-weight:bold;text-align:left;\">\n\t\t\t\t\t\t \t&nbsp;异常类型:\n\t\t\t\t\t\t</label>\n\t\t\t\t\t\t<select name=\"type\" style=\"height:26px\">\n\t\t\t\t\t\t\t<option value=\"\">全部</option>\n\t\t\t\t\t\t\t<option <c:if test=\"${type == 1}\">selected=\"selected\"</c:if> value=\"1\">redis异常</option>\n\t\t\t\t\t\t\t<option <c:if test=\"${type == 2}\">selected=\"selected\"</c:if> value=\"2\">客户端异常</option>\n\t\t\t\t\t\t\t<c:if test=\"${appDesc.type == 2}\">\n\t\t\t\t\t\t\t\t<option <c:if test=\"${type == 3}\">selected=\"selected\"</c:if> value=\"3\">Redis-Cluster异常</option>\n\t\t\t\t\t\t\t</c:if>\n\t\t\t\t\t\t</select>\n\t\t\t\t\n\t\t\t\t\t\t<label style=\"font-weight:bold;text-align:left;\">\n\t\t\t\t\t\t \t&nbsp;开始日期:&nbsp;&nbsp;\n\t\t\t\t\t\t</label>\n\t\t\t\t\t\t<input type=\"text\" size=\"21\" name=\"exceptionStartDate\" id=\"exceptionStartDate\" value=\"${exceptionStartDate}\" onFocus=\"WdatePicker({startDate:'%y-%M-01',dateFmt:'yyyy-MM-dd',alwaysUseStartDate:true})\"/>\n\t\t\t\t\t\t\n\t\t\t\t\t\t<label style=\"font-weight:bold;text-align:left;\">\n\t\t\t\t\t\t \t结束日期:\n\t\t\t\t\t\t</label>\n\t\t\t\t\t\t<input type=\"text\" size=\"20\" name=\"exceptionEndDate\" id=\"exceptionEndDate\" value=\"${exceptionEndDate}\" onFocus=\"WdatePicker({startDate:'%y-%M-01',dateFmt:'yyyy-MM-dd',alwaysUseStartDate:true})\"/>\n\t\t\t\t\t\t\n\t\t\t\t\t\t<input type=\"hidden\" name=\"appId\" value=\"${appDesc.appId}\">\n\t\t\t\t\t\t<input type=\"hidden\" name=\"tabTag\" value=\"app_client_exception\">\n\t\t\t\t\t\t<input type=\"hidden\" name=\"pageNo\" id=\"pageNo\">\n\t\t\t\t\t\t<label>&nbsp;<input type=\"button\" class=\"btn-4\" value=\"查询\" onclick=\"search()\"/></label>\n\t\t\t\t</div>\n\t\t\t</form>\n        </div>\n    </div>\n    \n    <div class=\"row\">\n\t\t<div style=\"margin-bottom: 10px;float: right;margin-right: 15px\">\n\t\t\t<ul id='ccPagenitor' style=\"margin-bottom: 0px\"></ul>\n\t\t\t<div id=\"pageDetail\" style=\"float:right;padding-top:28px;padding-left:8px;color:#4A64A4;display: none\">共${page.totalPages}页,${page.totalCount}条</div>\t\t\n\t\t</div>\n        <div class=\"col-md-12\">\n        \t<table class=\"table table-striped table-hover table-bordered\" style=\"margin-top: 0px\">\n\t   \t\t\t<thead>\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t<td style=\"text-align:center\">id</td>\n\t\t\t\t\t\t<td style=\"text-align:center\">异常类型</td>\n\t\t\t\t\t\t<td style=\"text-align:center\">收集时间</td>\n\t\t\t\t\t\t<td style=\"text-align:center\">客户端ip</td>\n\t\t\t\t\t\t<td style=\"text-align:center\">异常类</td>\n\t\t\t\t\t\t<td style=\"text-align:center\">次数</td>\n\t\t\t\t\t\t<td style=\"text-align:center\">实例地址</td>\n\t\t\t\t\t</tr>\n\t\t\t\t</thead>\n\t\t\t\t<tbody>\n\t\t\t\t\t<c:forEach items=\"${appClientExceptionList}\" var=\"appClientException\">\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td style=\"text-align:center\">${appClientException.id}</td>\n\t\t\t\t\t\t\t<td style=\"text-align:center\">\n\t\t\t\t\t\t\t\t<c:choose>\n\t\t\t\t\t\t\t\t\t<c:when test=\"${appClientException.type == 1}\">redis异常</c:when>\n\t\t\t\t\t\t\t\t\t<c:when test=\"${appClientException.type == 2}\">客户端异常</c:when>\n\t\t\t\t\t\t\t\t\t<c:when test=\"${appClientException.type == 3}\">redis-cluster异常</c:when>\n\t\t\t\t\t\t\t\t</c:choose>\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t<td style=\"text-align:center\">${appClientException.collectTimeFormat}</td>\n\t\t\t\t\t\t\t<td style=\"text-align:center\">${appClientException.clientIp}</td>\n\t\t\t\t\t\t\t<td style=\"text-align:center\">${appClientException.exceptionClass}</td>\n\t\t\t\t\t\t\t<td style=\"text-align:center\">${appClientException.exceptionCount}</td>\n\t\t\t\t\t\t\t<td style=\"text-align:center\">\n\t\t\t\t\t\t\t\t<c:choose>\n\t\t\t\t\t\t\t\t\t<c:when test=\"${appClientException.type == 1}\">\n\t\t\t\t\t\t\t\t\t\t${appClientException.instanceHost}:${appClientException.instancePort}\n\t\t\t\t\t\t\t\t\t</c:when>\n\t\t\t\t\t\t\t\t\t<c:when test=\"${appClientException.type == 2}\">无</c:when>\n\t\t\t\t\t\t\t\t\t<c:when test=\"${appClientException.type == 3}\">无</c:when>\n\t\t\t\t\t\t\t\t</c:choose>\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t</c:forEach>\n\t\t\t\t</tbody>\n\t\t\t</table>\n        </div>\n    </div>      \t\t\n</div>\n<script src=\"/resources/bootstrap/paginator/bootstrap-paginator.js\"></script>\n<script src=\"/resources/bootstrap/paginator/custom-pagenitor.js\"></script>\n<script type=\"text/javascript\">\n    $(function(){\n    \t//分页点击函数\n    \tvar pageClickedFunc = function (e, originalEvent, type, page){\n    \t\t//form传参用\n    \t\tdocument.getElementById(\"pageNo\").value=page;\n    \t\tdocument.getElementById(\"searchExceptionForm\").submit();\n    \t};\n    \t//分页组件\n        var element = $('#ccPagenitor');\n        //当前page号码\n        var pageNo = '${page.pageNo}';\n        //总页数\n        var totalPages = '${page.totalPages}';\n        //显示总页数\n        var numberOfPages = '${page.numberOfPages}';\n\t\tvar options = generatePagenitorOption(pageNo, numberOfPages, totalPages, pageClickedFunc);\n\t\tif(totalPages > 0){\n\t\t\telement.bootstrapPaginator(options);\n\t\t\tdocument.getElementById(\"pageDetail\").style.display = \"\";\n\t\t}else{\n\t\t\telement.html(\"未查询到相关记录！\");\n\t\t}\n    });\n</script>\n\n\n\n\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/client/clientValueDistribute.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n\n<script type=\"text/javascript\">\nfunction search() {\n    var valueDistriStartDate = document.getElementById(\"valueDistriStartDate\").value;\n    var valueDistriEndDate = document.getElementById(\"valueDistriEndDate\").value;\n\tvar difTime = calDateWidgetDifMs(valueDistriStartDate, valueDistriEndDate);\n\tvar oneDayTime = 86400000;\n\tif (difTime > oneDayTime) {\n\t\talert(\"由于数据量较大,值区间查询暂不支持跨天查询!\");\n\t} else {\n\t\tdocument.getElementById(\"clientValueForm\").submit();\n\t}\n}\n</script>\n\n<div class=\"container\">\n\t<div class=\"row\">\n\t\t<div class=\"col-md-12\"></div>\n\t</div>\n    <div class=\"row\">\n        <div class=\"col-md-12\">\n        \t<form method=\"get\" action=\"/client/show/index.do\" id=\"clientValueForm\">\n\t\t\t\t<div style=\"float:right\">\n\t\t\t\t\t\t<label style=\"font-weight:bold;text-align:left;\">\n\t\t\t\t\t\t \t&nbsp;开始日期:&nbsp;&nbsp;\n\t\t\t\t\t\t</label>\n\t\t\t\t\t\t<input type=\"text\" size=\"21\" name=\"valueDistriStartDate\" id=\"valueDistriStartDate\" value=\"${valueDistriStartDate}\" onFocus=\"WdatePicker({startDate:'%y-%M-01',dateFmt:'yyyy-MM-dd',alwaysUseStartDate:true})\"/>\n\t\t\t\t\t\t\n\t\t\t\t\t\t<label style=\"font-weight:bold;text-align:left;\">\n\t\t\t\t\t\t \t结束日期:\n\t\t\t\t\t\t</label>\n\t\t\t\t\t\t<input type=\"text\" size=\"20\" name=\"valueDistriEndDate\" id=\"valueDistriEndDate\" value=\"${valueDistriEndDate}\" onFocus=\"WdatePicker({startDate:'%y-%M-01',dateFmt:'yyyy-MM-dd',alwaysUseStartDate:true})\"/>\n\t\t\t\t\t\t\n\t\t\t\t\t\t<input type=\"hidden\" name=\"appId\" value=\"${appDesc.appId}\">\n\t\t\t\t\t\t<input type=\"hidden\" name=\"tabTag\" value=\"app_client_value_distribute\">\n\t\t\t\t\t\t<label>&nbsp;<input type=\"button\" class=\"btn-4\" value=\"查询\" onclick=\"search()\"/></label>\n\t\t\t\t</div>\n\t\t\t</form>\n        </div>\n    </div>\n    \n    <div class=\"row\">\n        <div class=\"col-md-12\">\n        \t<div class=\"page-header\">\n\t\t\t\t<h4>\n\t\t\t\t\tredis值分布统计图表\n\t\t\t\t</h4>\n\t\t\t</div>\n\t\t\t<script type=\"text/javascript\">\n\t\t\t\t$(document).ready(\n\t\t\t\t\tfunction() {\n\t\t\t\t\t    var title =  \"<b>值分布</b>\";\n\t\t\t\t\t    var chartType = \"pie\";\n\t\t\t\t\t   \tvar options = {\n\t\t\t\t\t\t\tchart: {\n\t\t\t\t\t\t\t\trenderTo:'valueDistriContainer',\n\t\t\t\t\t\t\t\tanimation: Highcharts.svg,\n\t\t\t\t\t\t\t\tbackgroundColor: '#E6F1F5',\n\t\t\t\t\t\t\t\tplotBackgroundColor:'#FFFFFF',\n\t\t\t\t\t\t\t\ttype: chartType,\n\t\t\t\t\t\t\t\tmarginRight: 10\n\t\t\t\t\t\t\t},\n\t\t\t\t            title: {\n\t\t\t\t            \tuseHTML:true,\n\t\t\t\t                text: title\n\t\t\t\t            },\n\t\t\t\t            xAxis: {\n\t\t\t\t                type: 'category'\n\t\t\t\t            },\n\t\t\t\t            yAxis: {\n\t\t\t\t            \ttitle: {\n\t\t                    \t\ttext: ''\n\t\t                \t\t},\n\t\t\t\t                plotLines: [{\n\t\t\t\t                    value: 0,\n\t\t\t\t                    width: 1,\n\t\t\t\t                    color: '#808080'\n\t\t\t\t                }]\n\t\t\t\t            },\n\t\t\t\t            plotOptions: {\n\t\t\t\t                line: {\n\t\t\t\t                    dataLabels: {\n\t\t\t\t                        enabled: true\n\t\t\t\t                    }\n\t\t\t\t                },\n\t\t\t\t                series: {\n\t\t\t\t\t                cursor: 'pointer'\n\t\t\t\t\t            }\n\t\t\t\t            },\n\t\t\t\t            tooltip: {\n\t\t\t\t                formatter: function() {\n\t\t\t\t                        return '<b>'+ this.point.name +'</b><br/>'\n\t\t\t\t                }\n\t\t\t\t            },\n\t\t\t\t            legend: {\n\t\t\t\t                enabled: true\n\t\t\t\t            },\n\t\t\t\t            credits:{\n\t\t\t\t            \tenabled: false\n\t\t\t\t            },\n\t\t\t\t            exporting: {\n\t\t\t\t                enabled: true\n\t\t\t\t            },\n\t\t\t\t            series: []\n\t\t\t\t        };\n\t\t\t\t\t   \tvar data = '${appClientValueDistriSimpleListJson}';\n\t\t\t          \tvar dataArr = eval(\"(\"+data+\")\");\n\t\t    \t\t\tvar length = dataArr.length;\n\t\t    \t\t\tvar legendName = \"值分布统计\";\n\t\t    \t\t\tvar arr = [];\n\t\t                \n\t\t                for (var i = 0; i <length; i++) {\n\t\t                    var data = dataArr[i];\n\t                  \t\tvar pointName = data.distributeDesc + \":\" + data.count + \"次\";\n\t\t                    var point = {\n\t\t                    \tname:pointName,\n\t\t                        y: data.count\n\t\t                    };\n\t\t                    arr.push(point);\n\t\t                }\n\t             \t    var series={\n\t\t    \t\t\t\tname:legendName,\n\t\t    \t\t\t\tdata:arr\n\t\t    \t\t\t};\n\t\t    \t\t\toptions.series.push(series);\n\t     \t\t        new Highcharts.Chart(options); \n\t\t\t\t    });\n\t\t\t</script>\n\t\t\t\n\t\t\t<div id=\"valueDistriContainer\" style=\"min-width: 310px; height: 350px; margin: 0 auto\"></div>\n        </div>\n    </div>\n    \n    <br/>\n    \n    <div class=\"row\">\n        <div class=\"col-md-12\">\n        \t<div class=\"page-header\">\n\t\t\t\t<h4>\n\t\t\t\t\tredis值分布统计列表\n\t\t\t\t</h4>\n\t\t\t</div>\n        \t<table class=\"table table-striped table-hover table-bordered\" style=\"margin-top: 0px\">\n\t   \t\t\t<thead>\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t<td style=\"text-align:center\">值区间</td>\n\t\t\t\t\t\t<td style=\"text-align:center\">总次数</td>\n\t\t\t\t</thead>\n\t\t\t\t<tbody>\n\t\t\t\t\t<c:forEach items=\"${appClientValueDistriSimpleList}\" var=\"appClientValueDistriSimple\">\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td style=\"text-align:center\">${appClientValueDistriSimple.distributeDesc}</td>\n\t\t\t\t\t\t\t<td style=\"text-align:center\">${appClientValueDistriSimple.count}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t</c:forEach>\n\t\t\t\t</tbody>\n\t\t\t</table>\n        </div>\n    </div>\n    \n    <br/><br/><br/><br/>\n     \n</div>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/import/init.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <title>应用导入</title>\n    <jsp:include page=\"/WEB-INF/include/head.jsp\"/>\n    <script type=\"text/javascript\">\n    \tfunction checkAppInstanceFormat() {\n    \t\t//应用名\n    \t\tvar appName = document.getElementById(\"appName\");\n    \t\tif(appName.value == \"\"){\n    \t\t\talert(\"应用名不能为空\");\n    \t\t\tappName.focus();\n    \t\t\treturn false;\n    \t\t}\n    \t\t\n    \t\t//应用描述\n    \t\tvar appIntro = document.getElementById(\"appIntro\");\n    \t\tif(appIntro.value == \"\"){\n    \t\t\talert(\"应用描述不能为空\");\n    \t\t\tappIntro.focus();\n    \t\t\treturn false;\n    \t\t}\n    \t\t\n    \t\t//项目负责人\n    \t\tvar officer = document.getElementById(\"officer\");\n    \t\tif(officer.value == \"\"){\n    \t\t\talert(\"项目负责人不能为空\");\n    \t\t\tofficer.focus();\n    \t\t\treturn false;\n    \t\t}\n    \t\t\n    \t\t//内存报警阀值\n    \t\tvar memAlertValue = document.getElementById(\"memAlertValue\");\n    \t\tif(memAlertValue.value == \"\"){\n    \t\t\talert(\"内存报警阀值不能为空\");\n    \t\t\tmemAlertValue.focus();\n    \t\t\treturn false;\n    \t\t}\n    \t\t\n    \t\tvar appInstanceInfo = document.getElementById(\"appInstanceInfo\");\n    \t\tif(appInstanceInfo.value == \"\"){\n    \t\t\talert(\"实例详情不能为空\");\n    \t\t\tappInstanceInfo.focus();\n    \t\t\treturn false;\n    \t\t}\n    \t\tvar password = document.getElementById(\"password\");\n    \t\t\n    \t\t$.post(\n    \t\t\t'/import/app/check.json',\n    \t\t\t{\n    \t\t\t\tname: appName.value,\n    \t\t\t\tpassword: password.value,\n    \t\t\t\tappInstanceInfo: appInstanceInfo.value\n    \t\t\t},\n    \t        function(data){\n    \t\t\t\tvar status = data.status;\n    \t\t\t\talert(data.message);\n    \t\t\t\tif (status == 1) {\n    \t\t\t\t\tvar submitButton = document.getElementById(\"submitButton\");\n    \t\t    \t\tsubmitButton.disabled = false;\n    \t\t    \t\t\n    \t\t    \t\tvar checkButton = document.getElementById(\"checkButton\");\n    \t\t    \t\tcheckButton.disabled = true;\n    \t\t\t\t}\n    \t        }\n    \t     );\n    \t}\n    \t\n    \tfunction importApp() {\n    \t\t//应用名\n    \t\tvar appName = document.getElementById(\"appName\").value;\n    \t\t//应用描述\n    \t\tvar appIntro = document.getElementById(\"appIntro\").value;\n    \t\t//项目负责人\n    \t\tvar officer = document.getElementById(\"officer\").value;\n    \t\t//内存报警阀值\n    \t\tvar memAlertValue = document.getElementById(\"memAlertValue\").value;\n    \t\t//redis密码\n    \t\tvar password = document.getElementById(\"password\").value;\n    \t\t//实例详情\n    \t\tvar appInstanceInfo = document.getElementById(\"appInstanceInfo\").value;\n    \t\t//应用类型\n    \t\tvar appType = document.getElementById(\"appType\").value;\n    \t\t//是否测试\n    \t\tvar isTest = document.getElementById(\"isTest\").value;\n    \t\t\n    \t\tvar submitButton = document.getElementById(\"submitButton\");\n    \t\tsubmitButton.disabled = true;\n    \t\t\n    \t\t$.post(\n    \t\t\t'/import/app/add.json',\n    \t\t\t{\n    \t\t\t\tname: appName,\n    \t\t\t\tintro: appIntro,\n    \t\t\t\tofficer: officer,\n    \t\t\t\tmemAlertValue: memAlertValue,\n    \t\t\t\tpassword: password,\n    \t\t\t\ttype: appType,\n    \t\t\t\tisTest: isTest,\n    \t\t\t\tappInstanceInfo: appInstanceInfo\n    \t\t\t},\n    \t        function(data){\n    \t\t\t\tvar status = data.status;\n    \t\t\t\tif (status == 1) {\n    \t\t\t\t\talert(\"应用导入成功，请查看应用列表!\");\n    \t\t\t\t\tlocation.href = \"/admin/app/list\";\n    \t\t\t\t} else {\n    \t\t\t\t\talert(\"应用导入失败!\");\n    \t\t\t\t}\n\t\t    \t\t\n\t\t    \t\tvar checkButton = document.getElementById(\"checkButton\");\n\t\t    \t\tcheckButton.disabled = true;\n\t\t    \t\t\n    \t        }\n    \t     );\n    \t}\n    \t\n    </script>\n    \n</head>\n<body role=\"document\">\n\t<div class=\"container\">\n\t    <jsp:include page=\"/WEB-INF/include/headMenu.jsp\"/>\n\t    <div id=\"systemAlert\">\n\t    </div>\n\t\t<div class=\"page-content\">\n\t\t\t<div class=\"row\">\n\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t<h3 class=\"page-header\">\n\t\t\t\t\t\t应用导入\n\t\t\t\t\t\t<font color='red' size=\"4\">\n\t\t\t\t\t\t\t<c:choose>\n\t\t\t\t\t\t\t\t<c:when test=\"${success == 1}\">(更新成功)</c:when>\n\t\t\t\t\t\t\t</c:choose>\n\t\t\t\t\t\t</font>\n\t\t\t\t\t</h3>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"row\">\n\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t<div class=\"portlet box light-grey\">\n\t\t\t\t\t\t<div class=\"portlet-body\">\n\t\t\t\t\t\t\t<div class=\"form\">\n\t\t\t\t\t\t\t\t\t<!-- BEGIN FORM-->\n\t\t\t\t\t\t\t\t\t<form action=\"/import/app/add\" method=\"post\"\n\t\t\t\t\t\t\t\t\t\tclass=\"form-horizontal form-bordered form-row-stripped\">\n\t\t\t\t\t\t\t\t\t\t<div class=\"form-body\">\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t应用名称<font color='red'>(*)</font>:\n\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"name\" id=\"appName\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tclass=\"form-control\" onchange=\"checkAppNameExist()\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t应用描述<font color='red'>(*)</font>:\n\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<textarea class=\"form-control\" name=\"intro\" \n\t\t\t\t\t\t\t\t\t\t\t\t\t\trows=\"3\" id=\"appIntro\" placeholder=\"应用描述\"></textarea>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"help-block\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t应用描述（必填，不超过128个字符，可以包含中文）\n\t\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t存储种类:\n\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<select id=\"appType\" name=\"type\" class=\"form-control select2_category\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"2\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tRedis-cluster\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tRedis-sentinel\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"6\">\n                                                            Redis-standalone\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t项目负责人<font color='red'>(*)</font>:\n\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"officer\" id=\"officer\" placeholder=\"项目负责人(中文必填)\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tclass=\"form-control\" />\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t测试:\n\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<select id=\"isTest\" name=\"isTest\" class=\"form-control\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t否\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"1\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t是\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t\tredis密码:\n\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"password\" id=\"password\" placeholder=\"redis密码\" class=\"form-control\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"help-block\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tredis密码，如果没有则为空\n\t\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t内存报警阀值<font color='red'>(*)</font>:\n\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"memAlertValue\" id=\"memAlertValue\" placeholder=\"内存报警阀值\" class=\"form-control\" onchange=\"testisNum(this.id)\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"help-block\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t例如内存使用率超过90%就报警，请填写90(<font color=\"red\">如果不需要报警请填写100以上的数字</font>)\n\t\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t实例详情:<font color='red'>(*)</font>:\n\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<textarea rows=\"10\" name=\"appInstanceInfo\" id=\"appInstanceInfo\" placeholder=\"节点详情\" class=\"form-control\"></textarea>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"help-block\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t每行格式都是:&nbsp;&nbsp;ip:port:maxMemory(单位:M)或者masterName}<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t1. standalone类型：<br/> \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&nbsp;&nbsp;&nbsp;&nbsp;masterIp:masterPort:maxMemory(例如：10.10.xx.xx:6379:2048)<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t2. sentinel类型：<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&nbsp;&nbsp;&nbsp;&nbsp;masterIp:masterPort:maxMemory<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&nbsp;&nbsp;&nbsp;&nbsp;slaveIp:slavePort:maxMemory<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t(可以是多个slave)<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&nbsp;&nbsp;&nbsp;&nbsp;sentinelIp1:sentinelPor1:masterName<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&nbsp;&nbsp;&nbsp;&nbsp;sentinelIp2:sentinelPor2:masterName<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&nbsp;&nbsp;&nbsp;&nbsp;sentinelIp3:sentinelPor3:masterName<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t(可以是多个sentinel)<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t3. cluster类型：<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&nbsp;&nbsp;&nbsp;&nbsp;masterIp1:masterPort1:maxMemory1<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&nbsp;&nbsp;&nbsp;&nbsp;slaveIp1:slavePort1:maxMemory1<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&nbsp;&nbsp;&nbsp;&nbsp;masterIp2:masterPort2:maxMemory2<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&nbsp;&nbsp;&nbsp;&nbsp;slaveIp2:slavePort2:maxMemory2<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t(可以是多对主从，只要把所有的cluster节点都按照格式写就可以，程序会自动判断)<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t<input name=\"userId\" id=\"userId\" value=\"${userInfo.id}\" type=\"hidden\" />\n\t\t\t\t\t\t\t\t\t\t\t<input id=\"appExist\" value=\"0\" type=\"hidden\" />\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-actions fluid\">\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-offset-3 col-md-9\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<button id=\"submitButton\" type=\"button\" onclick=\"importApp()\" class=\"btn green\" disabled=\"disabled\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-check\"></i>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t开始导入\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<button id=\"checkButton\" type=\"button\" class=\"btn green\" onclick=\"checkAppInstanceFormat()\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-check\"></i>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t检查格式\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</form>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<!-- END TABLE PORTLET-->\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t<br/><br/><br/><br/><br/><br/><br/>\n\t<jsp:include page=\"/WEB-INF/include/foot.jsp\"/>\n</body>\n</html>\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/instance/instanceAdvancedAnalysis.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%@ taglib prefix=\"c\" uri=\"http://java.sun.com/jsp/jstl/core\" %>\n<script>\n    var instance_advancedAnalysis_c_cu = {\n    <c:forEach items=\"${appCommandStats}\" var=\"appCommand\" varStatus=\"status\">${appCommand.commandName}:\n    '/admin/instance/getCommandStatsV2.json?instanceId=${instanceInfo.id}&commandName=${appCommand.commandName}&startDate=${startDate}&endDate=${endDate}'<c:if test=\"${!status.last}\">,\n    </c:if></c:forEach>\n    }\n    var instance_advancedAnalysis_c_o = {\n    <c:forEach items=\"${appCommandStats}\" var=\"appCommand\" varStatus=\"status\">${appCommand.commandName}:\n    {\n        plotOptions: {\n            area:{\n                marker: {\n                    enabled: false,\n                    symbol: 'circle',\n                    radius: 0,\n                    states:{\n                        hover: {\n                            enabled: true\n                        }\n                    }\n                }\n            }\n        }\n//    ,\n//        scrollbar: {\n//            enabled: true/*,\n//             barBackgroundColor: 'gray',\n//             barBorderRadius: 7,\n//             barBorderWidth: 0,\n//             buttonBackgroundColor: 'gray',\n//             buttonBorderWidth: 0,\n//             buttonArrowColor: 'yellow',\n//             buttonBorderRadius: 7,\n//             rifleColor: 'yellow',\n//             trackBackgroundColor: 'white',\n//             trackBorderWidth: 1,\n//             trackBorderColor: 'silver',\n//             trackBorderRadius: 7\n//             */\n//        }\n    }\n    <c:if test=\"${!status.last}\">,</c:if></c:forEach>\n    }\n</script>\n<div class=\"container\">\n    <br/>\n    <div class=\"row\">\n        <div style=\"float:right\">\n            <form method=\"get\" action=\"/admin/instance/index.do\" id=\"ec\" name=\"ec\">\n                <label style=\"font-weight:bold;text-align:left;\">\n                    开始日期:&nbsp;&nbsp;\n                </label>\n                <input type=\"text\" size=\"21\" name=\"startDate\" id=\"startDate\" value=\"${startDate}\"\n                       onFocus=\"WdatePicker({startDate:'%y%M%d',dateFmt:'yyyyMMdd',alwaysUseStartDate:true})\"/>\n                <label style=\"font-weight:bold;text-align:left;\">\n                    结束日期:\n                </label>\n                <input type=\"text\" size=\"20\" name=\"endDate\" id=\"endDate\" value=\"${endDate}\"\n                       onFocus=\"WdatePicker({startDate:'%y%M%d',dateFmt:'yyyyMMdd',alwaysUseStartDate:true})\"/>\n                <input type=\"hidden\" name=\"instanceId\" value=\"${instanceInfo.id}\">\n                <input type=\"hidden\" name=\"tabTag\" value=\"instance_advancedAnalysis\">\n                <label>&nbsp;<input type=\"submit\" class=\"btn-4\" value=\"查询\"/></label>\n            </form>\n        </div>\n    </div>\n\n    <div class=\"row\">\n        <div class=\"col-md-12\">\n            <div class=\"page-header\">\n                <h4>TOP的命令执行趋势比较</h4>\n            </div>\n            <c:forEach items=\"${appCommandStats}\" var=\"appCommand\">\n                <div id=\"${appCommand.commandName}\" class=\"page-body\">\n                </div>\n                <br/>\n            </c:forEach>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/instance/instanceClientList.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%@ taglib prefix=\"fn\" uri=\"http://java.sun.com/jsp/jstl/functions\" %>\n<%@ taglib prefix=\"c\" uri=\"http://java.sun.com/jsp/jstl/core\" %>\n<%@ taglib prefix=\"fmt\" uri=\"http://java.sun.com/jsp/jstl/fmt\" %>\n<div class=\"container\">\n<br/>\n<div class=\"row\">\n    <div class=\"col-md-12\">\n        <div class=\"page-header\">\n            <h4>当前客户端连接信息</h4>\n        </div>\n        <table class=\"table table-striped table-hover\">\n            <thead>\n            <tr>\n                <td>连接信息</td>\n            </tr>\n            </thead>\n            <tbody>\n            <c:forEach items=\"${clientList}\" var=\"clientInfo\" varStatus=\"status\">\n                <tr>\n                    <td>${clientInfo}</td>\n                </tr>\n            </c:forEach>\n            </tbody>\n        </table>\n    </div>\n</div>\n</div>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/instance/instanceCommand.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<div class=\"row\">\n    <br />\n    <div id=\"console\" class=\"col-md-12 console\"></div>\n    <script type=\"text/javascript\">\n        $(document).ready(function () {\n            var console = $('#console');\n            var controller = console.console({\n                welcomeMessage: '欢迎使用缓存云平台控制台',\n                promptLabel: 'instanceId:${instanceId}> ',\n                commandValidate: function (line) {\n                    if (line == \"\") return false;\n                    else return true;\n                },\n                commandHandle: function (line, report) {\n                    $.ajax({\n                        url: \"/admin/instance/commandExecute.json\",\n                        data: {instanceId: $('#instanceId').val(), command: line},\n                        dataType: \"json\",\n                        success: function (result) {\n                            report([\n                                {msg: result.result,\n                                    className: \"jquery-console-message-value\"}\n                            ]);\n                        }\n                    });\n                },\n                autofocus: true,\n                animateScroll: true,\n                promptHistory: true\n            });\n        });\n    </script>\n\n    <input type=\"hidden\" id=\"instanceId\" value=\"${instanceId}\">\n\n\n</div>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/instance/instanceConfigSelect.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%@ taglib prefix=\"fn\" uri=\"http://java.sun.com/jsp/jstl/functions\" %>\n<%@ taglib prefix=\"c\" uri=\"http://java.sun.com/jsp/jstl/core\" %>\n<%@ taglib prefix=\"fmt\" uri=\"http://java.sun.com/jsp/jstl/fmt\" %>\n<script type=\"text/javascript\">\n\tfunction reloadInstanceDetailPage(appId,instanceId){\n\t\tlocation.href = \"/admin/instance/index.do?instanceId=\"+instanceId + \"&appId=\"+appId + \"&tabTag=instance_configSelect\";\n\t}\n\tfunction instanceConfigChange(appId, instanceId){\n\t\tvar instanceConfigKey = document.getElementById(\"instanceConfigKey\");\n\t\tif(instanceConfigKey.value == \"\"){\n\t\t\talert(\"配置项不能为空\");\n\t\t\tinstanceConfigKey.focus();\n\t\t\treturn false;\n\t\t}\n\t\t\n\t\tvar instanceConfigValue = document.getElementById(\"instanceConfigValue\");\n\t\tif(instanceConfigValue.value == \"\"){\n\t\t\talert(\"配置值不能为空\");\n\t\t\tinstanceConfigValue.focus();\n\t\t\treturn false;\n\t\t}\n\n        var instanceConfigReason = document.getElementById(\"instanceConfigReason\");\n        if(instanceConfigReason.value == \"\"){\n            alert(\"配置原因不能为空\");\n            instanceConfigReason.focus();\n            return false;\n        }\n        \n        var instanceConfigChangeBtn = document.getElementById(\"instanceConfigChangeBtn\");\n        instanceConfigChangeBtn.disabled = true;\n\t\t\n\t\t$.post(\n\t\t\t'/admin/app/changeInstanceConfig.do',\n\t\t\t{\n\t\t\t\tappId: appId,\n\t\t\t\tinstanceId: instanceId,\n\t\t\t\tinstanceConfigKey: instanceConfigKey.value,\n\t\t\t\tinstanceConfigValue: instanceConfigValue.value,\n                instanceConfigReason: instanceConfigReason.value\n\t\t\t},\n\t        function(data){\n\t            if(data==1){\n\t                alert(\"申请成功，请在邮件中关注申请状况.\");\n\t            \t$(\"#instanceConfigChangeInfo\").html(\"<div class='alert alert-error' ><button class='close' data-dismiss='alert'>×</button><strong>Success!</strong>更新成功，窗口会自动关闭</div>\");\n\t                setTimeout(\"$('instanceConfigChangeModal').modal('hide');reloadInstanceDetailPage(\"+appId+\",\"+instanceId+\");\",1000);\n\t            }else{\n\t            \tinstanceConfigChangeBtn.disabled = false;\n\t                $(\"#instanceConfigChangeInfo\").html(\"<div class='alert alert-error' ><button class='close' data-dismiss='alert'>×</button><strong>Error!</strong>更新失败！</div>\");\n\t            }\n\t        }\n\t     );\n\t}\n</script>\n<div class=\"container\">\n    <br/>\n    <div class=\"row\">\n        <div class=\"col-md-12\">\n            <div class=\"page-header\">\n                <h4>\n               \t\t 实例当前配置信息\n                     <button type=\"button\" class=\"btn btn-info\" data-target=\"#instanceConfigChangeModal\" data-toggle=\"modal\" href=\"#\">配置修改申请(当前实例)</button>\n                </h4>\n                <h6>\n                </h6>\n            </div>\n            <table class=\"table table-striped table-hover\">\n                <thead>\n                <tr>\n                    <td>配置项</td>\n                    <td>配置值</td>\n                </tr>\n                </thead>\n                <tbody>\n                <c:forEach items=\"${redisConfigList}\" var=\"redisConfig\" varStatus=\"status\">\n                    <tr>\n                        <td>${redisConfig.key}</td>\n                        <td>${redisConfig.value}</td>\n                    </tr>\n                </c:forEach>\n                </tbody>\n            </table>\n        </div>\n    </div>\n</div>\n\n<div id=\"instanceConfigChangeModal\" class=\"modal fade\" tabindex=\"-1\" data-width=\"400\">\n\t<div class=\"modal-dialog\">\n\t\t<div class=\"modal-content\">\n\t\t\n\t\t\t<div class=\"modal-header\">\n\t\t\t\t<button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\"></button>\n\t\t\t\t<h4 class=\"modal-title\">实例id=${instanceId}配置修改</h4>\n\t\t\t</div>\n\t\t\t\n\t\t\t<form class=\"form-horizontal form-bordered form-row-stripped\">\n\t\t\t\t<div class=\"modal-body\">\n\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t<!-- 控件开始 -->\n\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t<!-- form-body开始 -->\n\t\t\t\t\t\t\t<div class=\"form-body\">\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">配置项:</label>\n\t\t\t\t\t\t\t\t\t<div class=\"col-md-8\">\n\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"instanceConfigKey\" id=\"instanceConfigKey\" placeholder=\"例如:maxclients\" class=\"form-control\" />\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">配置值:</label>\n\t\t\t\t\t\t\t\t\t<div class=\"col-md-8\">\n\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"instanceConfigValue\" id=\"instanceConfigValue\" placeholder=\"例如:15000\" class=\"form-control\">\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\n                                <div class=\"form-group\">\n                                    <label class=\"control-label col-md-3\">修改原因:</label>\n                                    <div class=\"col-md-8\">\n                                        <textarea name=\"instanceConfigReason\" id=\"instanceConfigReason\" placeholder=\"例如：修改原因:1.需要更多的连接数。\" class=\"form-control\"></textarea>\n                                    </div>\n                                </div>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<!-- form-body 结束 -->\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div id=\"instanceConfigChangeInfo\"></div>\n\t\t\t\t\t\t<!-- 控件结束 -->\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t\n\t\t\t\t<div class=\"modal-footer\">\n\t\t\t\t\t<button type=\"button\" data-dismiss=\"modal\" class=\"btn\" >Close</button>\n\t\t\t\t\t<button type=\"button\" id=\"instanceConfigChangeBtn\" class=\"btn red\" onclick=\"instanceConfigChange('${appId}','${instanceId}')\">Ok</button>\n\t\t\t\t</div>\n\t\t\t\n\t\t\t</form>\n\t\t</div>\n\t</div>\n</div>\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/instance/instanceFault.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<div class=\"row\">\n    <div class=\"col-md-12 page-header\">\n    \t实例故障情况\n    </div>\n    <div style=\"margin-top: 20px\">\n        <table class=\"table table-bordered table-striped table-hover\">\n            <thead>\n            <tr>\n                <td>应用ID</td>\n                <td>实例ip:port</td>\n                <td>实例状态</td>\n                <td>类型</td>\n                <td>触发时间</td>\n            </tr>\n            </thead>\n            <tbody>\n            <c:forEach var=\"instance\" items=\"${list}\" varStatus=\"status\">\n                <tr>\n                    <td>\n                        <a href=\"/admin/app/index.do?appId=${instance.appId}\" target=\"_blank\">${instance.appId}</a>\n                    </td>\n                    <td>\n                        <a href=\"/admin/instance/index.do?instanceId=${instance.instId}\" target=\"_blank\">${instance.ip}:${instance.port}</a>\n                    </td>\n                    <td>${instance.statusDesc}</td>\n                    <td>${instance.typeDesc}</td>\n                    <td><fmt:formatDate value=\"${instance.createTime}\" pattern=\"yyyy-MM-dd HH:mm:ss\"/></td>\n                </tr>\n            </c:forEach>\n            </tbody>\n        </table>\n    </div>\n</div>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/instance/instanceIndex.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%@ taglib prefix=\"c\" uri=\"http://java.sun.com/jsp/jstl/core\" %>\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <title>实例统计信息</title>\n    <jsp:include page=\"/WEB-INF/include/head.jsp\"/>\n    <script type=\"text/javascript\" src=\"/resources/js/jquery-console.js\"></script>\n</head>\n<body role=\"document\">\n<div class=\"container\">\n    <jsp:include page=\"/WEB-INF/include/headMenu.jsp\"/>\n    <div id=\"systemAlert\">\n    </div>\n    <div class=\"tabbable-custom\">\n        <ul class=\"nav nav-tabs\" id=\"instance_tabs\">\n            <li class=\"active\"><a href=\"#instance_stat\"\n                                  data-url=\"/admin/instance/stat.html?instanceId=${instanceId}&startDate=${startDate}&endDate=${endDate}\"\n                                  data-toggle=\"tab\">实例统计信息</a></li>\n            <li><a href=\"#app_topology\" data-url=\"/admin/app/topology.html?appId=${appId}\"\n                   data-toggle=\"tab\">拓扑结构</a>\n            </li>\n            <c:if test=\"${type == 2 or type == 6}\">\n            <li><a href=\"#instance_slowSelect\" data-url=\"/admin/instance/slowSelect.html?instanceId=${instanceId}\"\n                   data-toggle=\"tab\">慢查询分析</a>\n            </li>\n            <li><a href=\"#instance_configSelect\" data-url=\"/admin/instance/configSelect.html?instanceId=${instanceId}&appId=${appId}\"\n                   data-toggle=\"tab\">配置查询</a>\n            </li>\n            <li><a href=\"#instance_clientList\" data-url=\"/admin/instance/clientList.html?instanceId=${instanceId}\"\n                   data-toggle=\"tab\">连接信息</a>\n            </li>\n            </c:if>\n            <li><a href=\"#instance_fault\"\n                   data-url=\"/admin/instance/fault.html?instanceId=${instanceId}&startDate=${startDate}&endDate=${endDate}\"\n                   data-toggle=\"tab\">故障报警</a>\n            </li>\n            <li><a href=\"#instance_advancedAnalysis\" data-url=\"/admin/instance/advancedAnalysis.html?instanceId=${instanceId}&startDate=${startDate}&endDate=${endDate}\"\n                   data-toggle=\"tab\">命令曲线</a>\n            </li>\n            <li><a href=\"#instance_command\" data-url=\"/admin/instance/command.html?instanceId=${instanceId}\"\n                   data-toggle=\"tab\">命令执行</a>\n            </li>\n        </ul>\n        <div class=\"tab-content\">\n            <div class=\"tab-pane active\" id=\"instance_stat\">\n            </div>\n            <div class=\"tab-pane\" id=\"app_topology\">\n            </div>\n\n            <div class=\"tab-pane\" id=\"instance_slowSelect\">\n            </div>\n            <div class=\"tab-pane\" id=\"instance_configSelect\">\n            </div>\n            <div class=\"tab-pane\" id=\"instance_clientList\">\n\n            </div>\n            <div class=\"tab-pane\" id=\"instance_fault\">\n            </div>\n            <div class=\"tab-pane\" id=\"instance_advancedAnalysis\">\n            </div>\n            <div class=\"tab-pane\" id=\"instance_command\">\n            </div>\n        </div>\n    </div>\n</div>\n<jsp:include page=\"/WEB-INF/include/foot.jsp\"/>\n<script src=\"/resources/js/chart.js\"></script>\n<script type=\"text/javascript\" src=\"/resources/js/mem-cloud.js\"></script>\n<script type=\"text/javascript\">\n    $('#instance_tabs a').click(function (e) {\n        e.preventDefault();\n        var url = $(this).attr(\"data-url\");\n        var href = this.hash;\n        var pane = $(this);\n        var id = $(href).attr(\"id\");\n        // ajax load from data-url\n        $(href).load(url, function (result) {\n            pane.tab('show');\n            initChart(id);\n        });\n    });\n\n    // load first tab content\n    var tabTag = \"${tabTag}\";\n    if (tabTag.length > 0 && $('#' + tabTag).length > 0) {\n        var tabId = '#' + tabTag;\n        $(\"a[href=\" + tabId + \"]\").click();\n    } else {\n        $(\"a[href=#instance_stat]\").click();\n    }\n\n\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/instance/instanceSlowSelect.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%@ taglib prefix=\"fn\" uri=\"http://java.sun.com/jsp/jstl/functions\"%>\n<%@ taglib prefix=\"c\" uri=\"http://java.sun.com/jsp/jstl/core\"%>\n<%@ taglib prefix=\"fmt\" uri=\"http://java.sun.com/jsp/jstl/fmt\"%>\n<div class=\"container\">\n    <br/>\n\n    <div class=\"row\">\n        <div class=\"col-md-12\">\n            <div class=\"page-header\">\n                <h4>慢查询列表</h4>\n            </div>\n            <table class=\"table table-striped table-hover\">\n                <thead>\n                <tr>\n                    <td>id</td>\n                    <td>时间</td>\n                    <td>执行耗时(微秒)</td>\n                    <td>命令</td>\n                </tr>\n                </thead>\n                <tbody>\n                <c:forEach items=\"${redisSlowLogs}\" varStatus=\"status\" var=\"redisSlowLog\">\n                    <tr>\n                        <td>${redisSlowLog.id}</td>\n                        <td>${redisSlowLog.timeStamp}</td>\n                        <td><fmt:formatNumber value=\"${redisSlowLog.executionTime}\" pattern=\"#,#00\"/></td>\n                        <td>${redisSlowLog.command}</td>\n                    </tr>\n                </c:forEach>\n                </tbody>\n            </table>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/instance/instanceStat.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%@ taglib prefix=\"fn\" uri=\"http://java.sun.com/jsp/jstl/functions\"%>\n<%@ taglib prefix=\"c\" uri=\"http://java.sun.com/jsp/jstl/core\"%>\n<%@ taglib prefix=\"fmt\" uri=\"http://java.sun.com/jsp/jstl/fmt\"%>\n<div class=\"container\">\n    <br/>\n\n    <div class=\"row\">\n        <div class=\"col-md-8\">\n            <div class=\"page-header\">\n                <h4>实例信息-所属应用<a href=\"/admin/app/index.do?appId=${appDetail.appDesc.appId}\" target=\"_blank\">【${appDetail.appDesc.name}】</a></h4>\n            </div>\n            <table class=\"table table-striped table-hover\">\n                <tbody>\n                <tr>\n                    <td>内存使用率</td>\n                    <td>\n                        <div class=\"progress margin-custom-bottom0\">\n                            <c:choose>\n                            <c:when test=\"${instanceStats.memUsePercent >= 80}\">\n                            <div class=\"progress-bar progress-bar-danger\"\n                                 role=\"progressbar\" aria-valuenow=\"${instanceStats.memUsePercent}\" aria-valuemax=\"100\"\n                                 aria-valuemin=\"0\" style=\"width: ${instanceStats.memUsePercent}%\">\n                                </c:when>\n                                <c:otherwise>\n                                <div class=\"progress-bar progress-bar-success\"\n                                     role=\"progressbar\" aria-valuenow=\"${instanceStats.memUsePercent}\" aria-valuemax=\"100\"\n                                     aria-valuemin=\"0\" style=\"width: ${instanceStats.memUsePercent}%\">\t\t\t\t                    \t\t</c:otherwise>\n                                    </c:choose>\n                                    <label style=\"color: #000000\">\n                                        <fmt:formatNumber value=\"${instanceInfo.mem  * instanceStats.memUsePercent / 100 / 1024}\" pattern=\"0.00\"/>G&nbsp;&nbsp;Used/${instanceInfo.mem / 1024 * 1.0}G&nbsp;&nbsp;Total\n                                    </label>\n                                </div>\n                            </div>\n                    </td>\n                    <!--\n                     <td>${instanceInfo.mem}M</td>\n                     <td>已用内存TODO</td>\n                     <td><fmt:formatNumber value=\"${instanceStats.usedMemory/1024/1024}\" pattern=\"#,#00\"/>M</td>\n                     -->\n                    <td>命中率</td>\n                    <c:choose>\n                        <c:when test=\"${instanceStats.misses+instanceStats.hits==0}\">\n                            <td>无操作数据</td>\n                        </c:when>\n                        <c:otherwise>\n                            <td><fmt:formatNumber value=\"${instanceStats.hits/(instanceStats.misses+instanceStats.hits)}\" type=\"percent\" maxFractionDigits=\"2\"></fmt:formatNumber></td>\n                        </c:otherwise>\n                    </c:choose>\n\n                    <td>实例角色</td>\n                    <td>\n                        <c:if test=\"${instanceStats.role == 1}\">master</c:if>\n                        <c:if test=\"${instanceStats.role == 2}\">slave</c:if>\n                    </td>\n                </tr>\n                <tr>\n                    <td>当前对象数</td>\n                    <td><fmt:formatNumber value=\"${instanceStats.currItems}\" pattern=\"#,#00\"/></td>\n                    <td>实例类型</td>\n                    <td>${instanceInfo.typeDesc}</td>\n                    <td>当前连接数</td>\n                    <td>${instanceStats.currConnections}</td>\n                </tr>\n                <tr>\n                    <td>实例地址</td>\n                    <td>${instanceInfo.ip}:${instanceInfo.port}</td>\n                    <td>运行状态</td>\n                    <td>${instanceInfo.statusDesc}</td>\n                    <td>运行天数</td>\n                    <td>\n                    <c:choose>\n                        <c:when test=\"${instanceInfo.type == 1}\">\n                            <fmt:formatNumber value=\"${instanceStats.infoMap['stats'].uptime/60/60/24}\" pattern=\"0.0\"/>\n                        </c:when>\n                        <c:otherwise>${instanceStats.infoMap['Server'].uptime_in_days}</c:otherwise>\n                    </c:choose>\n                    </td>\n                </tr>\n                </tbody>\n            </table>\n        </div>\n        <div class=\"col-md-4\">\n            <div class=\"page-header\">\n                <h4>联系我们:</h4>\n            </div>\n            <div id=\"contact\" class=\"page-body\">\n                 <jsp:include page=\"/WEB-INF/include/contact.jsp\"/>\n            </div>\n        </div>\n    </div>\n    <div class=\"row\">\n        <c:choose>\n            <c:when test=\"${instanceInfo.type == 1}\">\n                <div class=\"page-header\">\n                    <h4>实时状态</h4>\n                </div>\n                <table class=\"table table-bordered table-striped table-hover\">\n                    <thead>\n                    <tr>\n                        <td>分组</td>\n                        <td>键值</td>\n                        <td>值</td>\n                    </tr>\n                    </thead>\n                    <tbody>\n                    <c:forEach items=\"${instanceStats.infoMap['stats']}\" var=\"info\" varStatus=\"status\">\n                        <c:if test=\"${status.last}\">\n                            <c:set var=\"rows\" value=\"${status.count}\" scope=\"page\"></c:set>\n                        </c:if>\n                    </c:forEach>\n                    <c:forEach items=\"${instanceStats.infoMap['stats']}\" var=\"info\" varStatus=\"status\">\n                        <tr>\n                            <c:if test=\"${status.first}\">\n                                <td rowspan=\"${rows}\">stats</td>\n                            </c:if>\n                            <td>${info.key}</td>\n                            <td>${info.value}</td>\n                        </tr>\n                    </c:forEach>\n                    </tbody>\n                </table>\n\n                <div class=\"page-header\">\n                    <h4>实例的item状态</h4>\n                </div>\n                <table class=\"table table-bordered table-striped table-hover\">\n                    <thead>\n                    <tr>\n                        <td>item号</td>\n                        <td>evicted_nonzero</td>\n                        <td>outofmemory</td>\n                        <td>reclaimed</td>\n                        <td>age</td>\n                        <td>evicted_time</td>\n                        <td>number</td>\n                        <td>tailrepairs</td>\n                        <td>evicted</td>\n                    </tr>\n                    </thead>\n                    <tbody>\n                    <c:forEach items=\"${instanceStats.infoMap['itemsVo']}\" var=\"item\" varStatus=\"status\">\n                        <tr>\n                            <td>${item.key}</td>\n                            <td>${item.value.evictedNonzero}</td>\n                            <td>${item.value.outOfMemory}</td>\n                            <td>${item.value.reclaimed}</td>\n                            <td>${item.value.age}</td>\n                            <td>${item.value.evictedTime}</td>\n                            <td>${item.value.number}</td>\n                            <td>${item.value.tailRepairs}</td>\n                            <td>${item.value.evicted}</td>\n                        </tr>\n                    </c:forEach>\n                    </tbody>\n                </table>\n\n                <div class=\"page-header\">\n                    <h4>实例的slab状态</h4>\n                </div>\n                <table class=\"table table-bordered table-striped table-hover\">\n                    <thead>\n                    <tr>\n                        <td>slab号</td>\n                        <td>free_<br/>chunks</td>\n                        <td>incr_hits</td>\n                        <td>delete_hits</td>\n                        <td>cmd_set</td>\n                        <td>get_hits</td>\n                        <td>chunk_size</td>\n                        <td>decr_hits</td>\n                        <td>chunks_<br/>per_page</td>\n                        <td>free_chunks_end</td>\n                        <td>used_<br/>chunks</td>\n                        <td>total_pages</td>\n                        <%--<td>cas_hits</td>--%>\n                        <td>mem_requested</td>\n                        <%--<td>cas_badval</td>--%>\n                        <td>total_<br/>chunks</td>\n\n                    </tr>\n                    </thead>\n                    <tbody>\n                    <c:forEach items=\"${instanceStats.infoMap['slabsVo']}\" var=\"slab\" varStatus=\"status\">\n                        <tr>\n                            <td>${slab.key}</td>\n                            <td>${slab.value.freeChunks}</td>\n                            <td>${slab.value.incrHits}</td>\n                            <td>${slab.value.deleteHits}</td>\n                            <td>${slab.value.cmdSet}</td>\n                            <td>${slab.value.getHits}</td>\n                            <td>${slab.value.chunkSize}</td>\n                            <td>${slab.value.decrHits}</td>\n                            <td>${slab.value.chunksPerPage}</td>\n                            <td>${slab.value.freeChunksEnd}</td>\n                            <td>${slab.value.usedChunks}</td>\n                            <td>${slab.value.totalPages}</td>\n                            <%--<td>${slab.value.casHits}</td>--%>\n                            <td>${slab.value.memRequested}</td>\n                            <%--<td>${slab.value.casBadval}</td>--%>\n                            <td>${slab.value.totalChunks}</td>\n\n                        </tr>\n                    </c:forEach>\n                    </tbody>\n                </table>\n            </c:when>\n            <c:when test=\"${instanceInfo.type == 2 or instanceInfo.type == 5 or instanceInfo.type == 6}\">\n                <div class=\"page-header\">\n                    <h4>实时状态</h4>\n                </div>\n                <table class=\"table table-bordered table-striped table-hover\">\n                    <thead>\n                    <tr>\n                        <td>分组</td>\n                        <td>键值</td>\n                        <td>值</td>\n                    </tr>\n                    </thead>\n                    <tbody>\n                    <c:forEach items=\"${instanceStats.infoMap}\" var=\"infoMap\">\n                        <c:forEach items=\"${infoMap.value}\" var=\"info\" varStatus=\"status\">\n                            <c:if test=\"${status.last}\">\n                                <c:set var=\"rows\" value=\"${status.count}\" scope=\"page\"></c:set>\n                            </c:if>\n                        </c:forEach>\n                        <c:forEach items=\"${infoMap.value}\" var=\"info\" varStatus=\"status\">\n                            <tr>\n                                <c:if test=\"${status.first}\">\n                                    <td rowspan=\"${rows}\">${infoMap.key}</td>\n                                </c:if>\n                                <td>${info.key}</td>\n                                <td>${info.value}</td>\n                            </tr>\n                        </c:forEach>\n                    </c:forEach>\n                    </tbody>\n                </table>\n            </c:when>\n        </c:choose>\n    </div>\n</div>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/appAudit/addAudit.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\" pageEncoding=\"UTF-8\"%>\n<div id=\"appRefuseModal${item.id}\" class=\"modal fade\" tabindex=\"-1\" data-width=\"400\">\n\t<div class=\"modal-dialog\">\n\t\t<div class=\"modal-content\">\n\t\t\n\t\t\t<div class=\"modal-header\">\n\t\t\t\t<button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\"></button>\n\t\t\t\t<h4 class=\"modal-title\">审批驳回意见</h4>\n\t\t\t</div>\n\t\t\t\n\t\t\t<form class=\"form-horizontal form-bordered form-row-stripped\">\n\t\t\t\t<div class=\"modal-body\">\n\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t<!-- 控件开始 -->\n\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t<!-- form-body开始 -->\n\t\t\t\t\t\t\t<div class=\"form-body\">\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">驳回原因:</label>\n\t\t\t\t\t\t\t\t\t<div class=\"col-md-7\">\n\t\t\t\t\t\t\t\t\t\t<textarea rows=\"5\"  name=\"refuseReason${item.id}\" id=\"refuseReason${item.id}\" placeholder=\"驳回原因 \" class=\"form-control\"></textarea>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<!-- form-body 结束 -->\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div id=\"appRefuseInfo${item.id}\"></div>\n\t\t\t\t\t\t<!-- 控件结束 -->\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t\n\t\t\t\t<div class=\"modal-footer\">\n\t\t\t\t\t<button type=\"button\" data-dismiss=\"modal\" class=\"btn\" >Close</button>\n\t\t\t\t\t<button type=\"button\" id=\"appRefuseBtn${item.id}\" class=\"btn red\" onclick=\"appRefuse('${item.id}', '${item.type}')\">提交</button>\n\t\t\t\t</div>\n\t\t\t\n\t\t\t</form>\n\t\t</div>\n\t</div>\n</div>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/appAudit/appAuditList.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\" pageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n\n<div class=\"page-container\">\n\t<div class=\"page-content\">\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-md-12\">\n\t\t\t\t<h3 class=\"page-title\">\n\t\t\t\t\t应用审批列表\n\t\t\t\t</h3>\n\t\t\t</div>\n\t\t</div>\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-md-12\">\n\t\t\t\t<div class=\"portlet box light-grey\">\n\t\t\t\t\t<div class=\"portlet-title\">\n\t\t\t\t\t\t<div class=\"caption\"><i class=\"fa fa-globe\"></i>审批列表</div>\n\t\t\t\t\t\t<div class=\"tools\">\n\t\t\t\t\t\t\t<a href=\"javascript:;\" class=\"collapse\"></a>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"portlet-body\">\n\t\t\t\t\t\t<div class=\"table-toolbar\">\n\t\t\t\t\t\t\t<div class=\"btn-group\" style=\"float:right\">\n\t\t\t\t\t\t\t\t<form action=\"/manage/app/auditList.do\" method=\"post\" class=\"form-horizontal form-bordered form-row-stripped\">\n\t\t\t\t\t\t\t\t\t<label class=\"control-label\">\n\t\t\t\t\t\t\t\t\t\t审核状态:\n\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t<select name=\"status\">\n\t\t\t\t\t\t\t\t\t\t<option value=\"0\" <c:if test=\"${status == 0}\">selected=\"selected\"</c:if>>\n\t\t\t\t\t\t\t\t\t\t\t待处理列表\n\t\t\t\t\t\t\t\t\t\t</option>\n                                        <option value=\"2\" <c:if test=\"${status == 2}\">selected=\"selected\"</c:if>>\n                                                                                                              审核已处理列表\n                                        </option>\n\t\t\t\t\t\t\t\t\t\t<option value=\"1\" <c:if test=\"${status == 1}\">selected=\"selected\"</c:if>>\n\t\t\t\t\t\t\t\t\t\t\t通过列表\n\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t<option value=\"-1\" <c:if test=\"${status == -1}\">selected=\"selected\"</c:if>>\n\t\t\t\t\t\t\t\t\t\t\t驳回列表\n\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t&nbsp;<button type=\"submit\" class=\"btn blue btn-sm\">查询</button>\n\t\t\t\t\t\t\t\t</form>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<table class=\"table table-striped table-bordered table-hover\" id=\"tableDataList\">\n\t\t\t\t\t\t\t<thead>\n\t\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t\t<th>appID</th>\n\t\t\t\t\t\t\t\t\t<th>应用名</th>\n\t\t\t\t\t\t\t\t\t<th>申请人</th>\n\t\t\t\t\t\t\t\t\t<th>审核状态</th>\n\t\t\t\t\t\t\t\t\t<th>申请类型</th>\n\t\t\t\t\t\t\t\t\t<th>申请描述</th>\n\t\t\t\t\t\t\t\t\t<th>申请时间</th>\n\t\t\t\t\t\t\t\t\t<th>操作</th>\n\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t</thead>\n\t\t\t\t\t\t\t<tbody>\n\t\t\t\t\t\t\t\t<c:forEach items=\"${list}\" var=\"item\">\n\t\t\t\t\t\t\t\t\t<tr class=\"odd gradeX\">\n\t\t\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t\t\t<c:choose>\n\t\t\t\t\t\t\t\t\t\t\t\t<c:when test=\"${item.type == 3}\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t无\n\t\t\t\t\t\t\t\t\t\t\t\t</c:when>\n\t\t\t\t\t\t\t\t\t\t\t\t<c:otherwise>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<a target=\"_blank\" href=\"/admin/app/index.do?appId=${item.appId}\">${item.appId}</a>\n\t\t\t\t\t\t\t\t\t\t\t\t</c:otherwise>\n\t\t\t\t\t\t\t\t\t\t\t</c:choose>\t\n\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t\t\t<c:choose>\n\t\t\t\t\t\t\t\t\t\t\t\t<c:when test=\"${item.type == 3}\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t无\n\t\t\t\t\t\t\t\t\t\t\t\t</c:when>\n\t\t\t\t\t\t\t\t\t\t\t\t<c:otherwise>\n\t\t\t\t\t\t\t\t\t\t\t\t\t${item.appDesc.name}\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t</c:otherwise>\n\t\t\t\t\t\t\t\t\t\t\t</c:choose>\t\n\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t\t<td>${item.userName}</td>\n\t\t\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t\t\t<c:choose>\n\t\t\t\t\t\t\t\t\t\t\t\t<c:when test=\"${item.status == 0}\">待审</c:when>\n\t\t\t\t\t\t\t\t\t\t\t\t<c:when test=\"${item.status == 1}\">通过</c:when>\n\t\t\t\t\t\t\t\t\t\t\t\t<c:when test=\"${item.status == 2}\">审核已处理</c:when>\n\t\t\t\t\t\t\t\t\t\t\t\t<c:when test=\"${item.status == -1}\">驳回</c:when>\n\t\t\t\t\t\t\t\t\t\t\t</c:choose>\n\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t\t\t<c:choose>\n\t\t\t\t\t\t\t\t\t\t\t\t<c:when test=\"${item.type == 0}\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t应用申请\n\t\t\t\t\t\t\t\t\t\t\t\t</c:when>\n\t\t\t\t\t\t\t\t\t\t\t\t<c:when test=\"${item.type == 1}\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t应用扩容\n\t\t\t\t\t\t\t\t\t\t\t\t</c:when>\n\t\t\t\t\t\t\t\t\t\t\t\t<c:when test=\"${item.type == 2}\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t应用配置修改\n\t\t\t\t\t\t\t\t\t\t\t\t</c:when>\n\t\t\t\t\t\t\t\t\t\t\t\t<c:when test=\"${item.type == 3}\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t注册用户申请\n\t\t\t\t\t\t\t\t\t\t\t\t</c:when>\n\t\t\t\t\t\t\t\t\t\t\t\t<c:when test=\"${item.type == 4}\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t实例配置修改\n\t\t\t\t\t\t\t\t\t\t\t\t</c:when>\n\t\t\t\t\t\t\t\t\t\t\t</c:choose>\t\n\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t\t<td>${item.info}</td>\n\t\t\t\t\t\t\t\t\t\t<td><fmt:formatDate pattern=\"yyyy-MM-dd HH:mm:ss\" value=\"${item.createTime}\"/></td>\n\t\t\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t\t\t<c:choose>\n\t\t\t\t\t\t\t\t\t\t\t\t<c:when test=\"${item.type == 3}\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<a onclick=\"if(window.confirm('确认要通过该申请请求吗?')){return true;}else{return false;}\" href=\"/manage/user/addAuditStatus.do?status=1&appAuditId=${item.id}\">[通过]</a>\n\t\t\t\t\t\t\t\t\t\t\t\t</c:when>\n\t\t\t\t\t\t\t\t\t\t\t\t<c:otherwise>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<c:set var=\"auditUrl\" value=\"/manage/app/addAuditStatus.do?status=1&appAuditId=${item.id}\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t</c:otherwise>\n\t\t\t\t\t\t\t\t\t\t\t</c:choose>\t\n\t\t\t\t\t\t\t\t\t\t\t<c:choose>\n\t\t\t\t\t\t\t\t\t\t\t\t<c:when test=\"${item.status == 2}\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<a onclick=\"if(window.confirm('确认要通过该申请请求吗?')){return true;}else{return false;}\" href=\"${auditUrl}\">[通过]</a>\n\t\t\t\t\t\t\t\t\t\t\t\t</c:when>\n\t\t\t\t\t\t\t\t\t\t\t</c:choose>\n\t\t\t\t\t\t\t\t\t\t\t<c:choose>\n\t\t\t\t\t\t\t\t\t\t\t\t<c:when test=\"${item.status == 0}\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<a href=\"javascript:void(0);\" data-target=\"#appRefuseModal${item.id}\" data-toggle=\"modal\">[驳回]</a>\n\t\t\t\t\t\t\t\t\t\t\t\t</c:when>\n\t\t\t\t\t\t\t\t\t\t\t</c:choose>\n\t\t\t\t\t\t\t\t\t\t\t&nbsp;\n\t\t\t\t\t\t\t\t\t\t\t<c:choose>\n\t\t\t\t\t\t\t\t\t\t\t\t<c:when test=\"${item.type == 0}\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<c:set var=\"auditDealUrl\" value=\"/manage/app/initAppDeploy.do?appAuditId=${item.id}\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t</c:when>\n\t\t\t\t\t\t\t\t\t\t\t\t<c:when test=\"${item.type == 1}\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<c:set var=\"auditDealUrl\" value=\"/manage/app/initAppScaleApply.do?appAuditId=${item.id}\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t</c:when>\n\t\t\t\t\t\t\t\t\t\t\t\t<c:when test=\"${item.type == 2}\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<c:set var=\"auditDealUrl\" value=\"/manage/app/initAppConfigChange.do?appAuditId=${item.id}\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t</c:when>\n\t\t\t\t\t\t\t\t\t\t\t\t<c:when test=\"${item.type == 4}\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<c:set var=\"auditDealUrl\" value=\"/manage/instance/initInstanceConfigChange.do?appAuditId=${item.id}\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t</c:when>\n\t\t\t\t\t\t\t\t\t\t\t</c:choose>\n\t\t\t\t\t\t\t\t\t\t\t<c:choose>\n\t\t\t\t\t\t\t\t\t\t\t\t<c:when test=\"${item.status == 0 && item.type != 3}\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<a href=\"${auditDealUrl}\">[审批处理]</a>\n\t\t\t\t\t\t\t\t\t\t\t\t</c:when>\n\t\t\t\t\t\t\t\t\t\t\t</c:choose>\n\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t\t</c:forEach>\n\t\t\t\t\t\t\t</tbody>\n\t\t\t\t\t\t</table>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t<!-- END EXAMPLE TABLE PORTLET-->\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n\n<c:forEach items=\"${list}\" var=\"item\">\n\t<%@include file=\"addAudit.jsp\" %>\n</c:forEach>\n\n\n\n\n\n\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/appAudit/appConfigChangeDetail.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\" pageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n\n\n<div class=\"page-container\">\n\t<div class=\"page-content\">\n\t\t\n\t\t<%@include file=\"instanceConfig.jsp\" %>\n\t\t\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-md-12\">\n\t\t\t\t<h3 class=\"page-title\">\n\t\t\t\t\t配置修改(<font color=\"red\">${appAudit.info}</font>)\n\t\t\t\t</h3>\n\t\t\t</div>\n\t\t</div>\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-md-12\">\n\t\t\t\t<div class=\"portlet box light-grey\">\n\t\t\t\t\t<div class=\"portlet-title\">\n\t\t\t\t\t\t<div class=\"caption\">\n\t\t\t\t\t\t\t<i class=\"fa fa-globe\"></i>\n\t\t\t\t\t\t\t配置\n\t\t\t\t\t\t\t&nbsp;\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"tools\">\n\t\t\t\t\t\t\t<a href=\"javascript:;\" class=\"collapse\"></a>\n\t\t\t\t\t\t\t<a href=\"javascript:;\" class=\"remove\"></a>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"portlet-body\">\n\t\t\t\t\t\t<div class=\"form\">\n\t\t\t\t\t\t\t\t<!-- BEGIN FORM-->\n\t\t\t\t\t\t\t\t<form action=\"/manage/app/addAppConfigChange.do\" method=\"post\"\n\t\t\t\t\t\t\t\t\tclass=\"form-horizontal form-bordered form-row-stripped\" onsubmit=\"return checkAppConfig();\">\n\t\t\t\t\t\t\t\t\t\t<div class=\"form-body\">\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">配置项:</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"appConfigKey\" id=\"appConfigKey\" value=\"${appConfigKey}\" class=\"form-control\" />\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">配置值:</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"appConfigValue\" id=\"appConfigValue\" value=\"${appConfigValue}\" class=\"form-control\">\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t<input type=\"hidden\" name=\"appId\" value=\"${appId}\">\n\t\t\t\t\t\t\t\t\t\t\t<input type=\"hidden\" name=\"appAuditId\" value=\"${appAuditId}\">\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-actions fluid\">\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-offset-3 col-md-9\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<button type=\"submit\" class=\"btn green\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-check\"></i>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t确认\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</form>\n\t\t\t\t\t\t\t\t<!-- END FORM-->\n\t\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<!-- END EXAMPLE TABLE PORTLET-->\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/appAudit/appDeploy.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\"\n    pageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n\t<title>CacheCloud管理后台</title>\n\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n\t\n\t<%@include file=\"/WEB-INF/jsp/manage/include/cache_cloud_main_css.jsp\" %>\n\t\t\n</head>\n\n<body class=\"page-header-fixed\">\n\t<%@include file=\"/WEB-INF/jsp/manage/include/head.jsp\" %>\n\n\t<%@include file=\"/WEB-INF/jsp/manage/include/left.jsp\" %>\n\t\n\t<%@include file=\"appDeployDetail.jsp\" %>\n\t\n\t<%@include file=\"/WEB-INF/jsp/manage/include/foot.jsp\" %>\n\n\t<%@include file=\"/WEB-INF/jsp/manage/include/cache_cloud_main_js.jsp\" %>\n\t\n</body>\n</html>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/appAudit/appDeployDetail.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\" pageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<script type=\"text/javascript\">\n\tfunction updateAppImportantLevel() {\n\t\tvar importantLevel = document.getElementById(\"importantLevel\");\n\t\tvar appId = document.getElementById(\"hiddenAppId\");\n\t\t$.get(\n   \t\t\t'/manage/app/updateAppImportantLevel.json',\n   \t\t\t{\n   \t\t\t\timportantLevel: importantLevel.value,\n   \t\t\t\tappId: appId.value\n   \t\t\t},\n   \t        function(data){\n   \t\t\t\tvar status = data.status;\n   \t\t\t\tif (status == 1) {\n   \t\t\t\t\talert(\"更新成功!\");\n   \t\t\t\t} else {\n   \t\t\t\t\talert(\"更新失败!\");\n   \t\t\t\t}\n   \t        }\n   \t     );\n\t}\n\tfunction updateAppPassword() {\n\t\tvar password = document.getElementById(\"password\");\n\t\tvar appId = document.getElementById(\"hiddenAppId\");\n\t\t$.get(\n   \t\t\t'/manage/app/updateAppPassword.json',\n   \t\t\t{\n   \t\t\t\tpassword: password.value,\n   \t\t\t\tappId: appId.value\n   \t\t\t},\n   \t        function(data){\n   \t\t\t\tvar status = data.status;\n   \t\t\t\tif (status == 1) {\n   \t\t\t\t\talert(\"设置成功!\");\n   \t\t\t\t} else {\n   \t\t\t\t\talert(\"设置失败!\");\n   \t\t\t\t}\n   \t        }\n   \t     );\n\t}\n</script>\n<div class=\"page-container\">\n\t<div class=\"page-content\">\n\t\n\t\t<%@include file=\"machineReferList.jsp\" %>\n\t\t\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-md-12\">\n\t\t\t\t<h3 class=\"page-title\">\n\t\t\t\t\t应用申请详情\n\t\t\t\t</h3>\n\t\t\t</div>\n\t\t</div>\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-md-12\">\n\t\t\t\t<div class=\"portlet box light-grey\">\n\t\t\t\t\t<div class=\"portlet-title\">\n\t\t\t\t\t\t<div class=\"caption\"><i class=\"fa fa-globe\"></i>应用申请详情</div>\n\t\t\t\t\t\t<div class=\"tools\">\n\t\t\t\t\t\t\t<a href=\"javascript:;\" class=\"collapse\"></a>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"portlet-body\">\n\t\t\t\t\t\t<table class=\"table table-striped table-bordered table-hover\" id=\"tableDataList\">\n\t\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t                <td>应用id</td>\n\t\t\t\t\t                <td>${appDesc.appId}</td>\n\t\t\t\t\t                <td>应用名称</td>\n\t\t\t\t\t                <td>${appDesc.name}</td>\n\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t                <td>存储种类</td>\n\t\t\t\t\t                <td>\n\t\t\t\t\t\t                <c:choose>\n\t\t\t\t        \t\t            <c:when test=\"${appDesc.type == 2}\">redis-cluster</c:when>\n\t\t    \t\t        \t\t        <c:when test=\"${appDesc.type == 5}\">redis-sentinel</c:when>\n\t\t    \t\t        \t\t        <c:when test=\"${appDesc.type == 6}\">redis-standalone</c:when>\n\t\t\t\t                    \t</c:choose>\n\t\t\t\t\t                </td>\n\t\t\t\t\t                <td>内存申请详情</td>\n\t\t\t\t\t                <td><font color=\"red\">${appAudit.info}</font></td>\n\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t\t<td>是否需要热备</td>\n\t\t\t\t\t                <td>\n\t\t\t\t\t                \t<c:choose>\n\t\t\t\t                    \t\t<c:when test=\"${appDesc.needHotBackUp == 1}\">是</c:when>\n\t\t\t\t        \t\t            <c:when test=\"${appDesc.needHotBackUp == 0}\">否</c:when>\n\t\t\t\t                    \t</c:choose>\n\t\t\t\t\t                </td>\n\t\t\t\t\t                <td>是否有后端数据源</td>\n\t\t\t\t\t                <td>\n\t\t\t\t\t                \t<c:choose>\n\t\t\t\t                    \t\t<c:when test=\"${appDesc.hasBackStore == 1}\">有</c:when>\n\t\t\t\t        \t\t            <c:when test=\"${appDesc.hasBackStore == 0}\">无</c:when>\n\t\t\t\t                    \t</c:choose>\n\t\t\t\t\t                </td>\n\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t                <td>是否测试</td>\n\t\t\t\t\t                <td>\n\t\t\t\t\t                \t<c:choose>\n\t\t\t\t                    \t\t<c:when test=\"${appDesc.isTest == 1}\">是</c:when>\n\t\t\t\t        \t\t            <c:when test=\"${appDesc.isTest == 0}\">否</c:when>\n\t\t\t\t                    \t</c:choose>\n\t\t\t\t\t                </td>\n\t\t\t\t\t                <td>是否需要持久化</td>\n\t\t\t\t\t                <td>\n\t\t\t\t\t                \t<c:choose>\n\t\t\t\t                    \t\t<c:when test=\"${appDesc.needPersistence == 1}\">是</c:when>\n\t\t\t\t        \t\t            <c:when test=\"${appDesc.needPersistence == 0}\">否</c:when>\n\t\t\t\t                    \t</c:choose>\n\t\t\t\t\t                </td>\n\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t                <td>预估QPS</td>\n\t\t\t\t\t                <td>${appDesc.forecaseQps}</td>\n\t\t\t\t\t                <td>预估条目数量</td>\n\t\t\t\t\t                <td>${appDesc.forecastObjNum}</td>\n\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t                <td>客户端机房信息</td>\n\t\t\t\t\t                <td>${appDesc.clientMachineRoom}</td>\n\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t</table>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t\t\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-md-12\">\n\t\t\t\t<h3 class=\"page-header\">\n\t\t\t\t\t应用评级(已经默认是B，如无调整无需提交)\n\t\t\t\t</h3>\n\t\t\t</div>\n\t\t</div>\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-md-12\">\n\t\t\t\t<div class=\"portlet box light-grey\">\n\t\t\t\t\t<div class=\"portlet-title\">\n\t\t\t\t\t\t<div class=\"caption\"><i class=\"fa fa-globe\"></i>应用评级</div>\n\t\t\t\t\t\t<div class=\"tools\">\n\t\t\t\t\t\t\t<a href=\"javascript:;\" class=\"collapse\"></a>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"portlet-body\">\n\t\t\t\t\t\t<div class=\"form\">\n\t\t\t\t\t\t\t\t<!-- BEGIN FORM-->\n\t\t\t\t\t\t\t\t<form class=\"form-horizontal form-bordered form-row-stripped\">\n\t\t\t\t\t\t\t\t\t<div class=\"form-body\">\n\t\t\t\t\t\t\t\t\t\t<input type=\"hidden\" id=\"hiddenAppId\" name=\"hiddenAppId\" value=\"${appId}\">\n\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t级别\n\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t<select id=\"importantLevel\" name=\"importantLevel\" class=\"form-control\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<option <c:if test=\"${appDesc.importantLevel == 1}\">selected</c:if> value=\"1\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tS\n\t\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<option <c:if test=\"${appDesc.importantLevel == 2}\">selected</c:if> value=\"2\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tA\n\t\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<option <c:if test=\"${appDesc.importantLevel == 3}\">selected</c:if> value=\"3\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tB\n\t\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<option <c:if test=\"${appDesc.importantLevel == 4}\">selected</c:if> value=\"4\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tC\n\t\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-2\">\n\t\t\t\t\t\t\t\t\t\t\t\t<button type=\"button\" class=\"btn green\" onclick=\"updateAppImportantLevel()\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t更新\n\t\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</form>\n\t\t\t\t\t\t\t\t<!-- END FORM-->\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<!-- END TABLE PORTLET-->\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-md-12\">\n\t\t\t\t<h3 class=\"page-header\">\n\t\t\t\t\tredis密码(默认是空，如无调整无需提交)\n\t\t\t\t</h3>\n\t\t\t</div>\n\t\t</div>\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-md-12\">\n\t\t\t\t<div class=\"portlet box light-grey\">\n\t\t\t\t\t<div class=\"portlet-title\">\n\t\t\t\t\t\t<div class=\"caption\"><i class=\"fa fa-globe\"></i>redis密码</div>\n\t\t\t\t\t\t<div class=\"tools\">\n\t\t\t\t\t\t\t<a href=\"javascript:;\" class=\"collapse\"></a>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"portlet-body\">\n\t\t\t\t\t\t<div class=\"form\">\n\t\t\t\t\t\t\t<!-- BEGIN FORM-->\n\t\t\t\t\t\t\t<form class=\"form-horizontal form-bordered form-row-stripped\">\n\t\t\t\t\t\t\t\t<div class=\"form-body\">\n\t\t\t\t\t\t\t\t\t<input type=\"hidden\" id=\"hiddenAppId\" name=\"hiddenAppId\" value=\"${appId}\">\n\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\tredis密码\n\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"password\" id=\"password\" class=\"form-control\"/>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-2\">\n\t\t\t\t\t\t\t\t\t\t\t<button type=\"button\" class=\"btn green\" onclick=\"updateAppPassword()\">\n\t\t\t\t\t\t\t\t\t\t\t\t更新\n\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</form>\n\t\t\t\t\t\t\t<!-- END FORM-->\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\t<!-- END TABLE PORTLET-->\n\t\t\t</div>\n\t\t</div>\n\t\t\n\t\t\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-md-12\">\n\t\t\t\t<h3 class=\"page-title\">\n\t\t\t\t\t应用部署\n\t\t\t\t</h3>\n\t\t\t</div>\n\t\t</div>\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-md-12\">\n\t\t\t\t<div class=\"portlet box light-grey\">\n\t\t\t\t\t<div class=\"portlet-title\">\n\t\t\t\t\t\t<div class=\"caption\">\n\t\t\t\t\t\t\t<i class=\"fa fa-globe\"></i>\n\t\t\t\t\t\t\t填写应用部署信息\n\t\t\t\t\t\t\t&nbsp;\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"tools\">\n\t\t\t\t\t\t\t<a href=\"javascript:;\" class=\"collapse\"></a>\n\t\t\t\t\t\t\t<a href=\"javascript:;\" class=\"remove\"></a>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"portlet-body\">\n\t\t\t\t\t\t<div class=\"form\">\n\t\t\t\t\t\t\t\t<!-- BEGIN FORM-->\n\t\t\t\t\t\t\t\t<form action=\"/manage/app/addAppDeploy.do\" method=\"post\"\n\t\t\t\t\t\t\t\t\tclass=\"form-horizontal form-bordered form-row-stripped\">\n\t\t\t\t\t\t\t\t\t<div class=\"form-body\">\n\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t部署详情:<font color='red'>(*)</font>:\n\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t<textarea rows=\"10\" name=\"appDeployText\" id=\"appDeployText\" placeholder=\"部署详情\" class=\"form-control\"></textarea>\n\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"help-block\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t具体规则如下:<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t1. standalone类型：<br/> \n\t\t\t\t\t\t\t\t\t\t\t\t\t&nbsp;&nbsp;&nbsp;&nbsp;masterIp:memSize(M)(例如：10.10.xx.xx:2048)<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t2. sentinel类型：<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t&nbsp;&nbsp;&nbsp;&nbsp;masterIp:memSize(M):slaveIp<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t&nbsp;&nbsp;&nbsp;&nbsp;sentinelIp1<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t&nbsp;&nbsp;&nbsp;&nbsp;sentinelIp2<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t&nbsp;&nbsp;&nbsp;&nbsp;sentinelIp3<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t3. cluster类型：<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t&nbsp;&nbsp;&nbsp;&nbsp;masterIp1:memSize(M):slaveIp1<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t&nbsp;&nbsp;&nbsp;&nbsp;masterIp2:memSize(M):slaveIp2<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t&nbsp;&nbsp;&nbsp;&nbsp;masterIp3:memSize(M):slaveIp3<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t<input type=\"hidden\" name=\"appId\" value=\"${appId}\">\n\t\t\t\t\t\t\t\t\t\t<input type=\"hidden\" id=\"appAuditId\" name=\"appAuditId\" value=\"${appAuditId}\">\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t<div class=\"form-actions fluid\">\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-offset-3 col-md-9\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<button id=\"appDeployBtn\" type=\"button\" class=\"btn green\" disabled=\"disabled\" onclick=\"addAppDeployText()\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-check\"></i>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t开始部署\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<button id=\"appCheckBtn\" type=\"button\" class=\"btn green\" onclick=\"checkAppDeployText()\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-check\"></i>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t格式检查\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<label id=\"startDeployLabel\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</form>\n\t\t\t\t\t\t\t\t<!-- END FORM-->\n\t\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<!-- END EXAMPLE TABLE PORTLET-->\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/appAudit/appIntanceReferList.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\" pageEncoding=\"UTF-8\" %>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\" %>\n\n<div class=\"row\">\n    <div class=\"col-md-12\">\n        <h3 class=\"page-title\">\n           \t 应用(id=${appId})实例列表\n        </h3>\n    </div>\n</div>\n<div class=\"row\">\n    <div class=\"col-md-12\">\n        <div class=\"portlet box light-grey\">\n            <div class=\"portlet-title\">\n                <div class=\"caption\"><i class=\"fa fa-globe\"></i>实例列表</div>\n                <div class=\"tools\">\n                    <a href=\"javascript:;\" class=\"collapse\"></a>\n                </div>\n            </div>\n            <div class=\"portlet-body\">\n                <table class=\"table table-striped table-bordered table-hover\" id=\"tableDataList\">\n                    <thead>\n                    <tr>\n                        <td>ID</td>\n                        <td>服务器ip:port</td>\n                        <td>实例空间使用情况</td>\n                        <td>角色</td>\n                        <%--<td>主实例ID</td>--%>\n                        <td>实例所在机器信息可用内存</td>\n                        <td>对象数</td>\n                        <td>slot分布</td>\n                    </tr>\n                    </thead>\n                    <tbody>\n                    <c:forEach var=\"instance\" items=\"${instanceList}\" varStatus=\"status\">\n                        <tr>\n                            <td><a href=\"/admin/instance/index.do?instanceId=${instance.id}\"\n                                   target=\"_blank\">${instance.id}</a></td>\n                            <td>${instance.ip}:${instance.port}</td>\n                            <td>\n                                <c:set var=\"instanceStatsMapKey\" value=\"${instance.ip}:${instance.port}\"></c:set>\n                                <div class=\"progress margin-custom-bottom0\">\n                                \t<c:choose>\n\t\t                        \t\t<c:when test=\"${(instanceStatsMap[instanceStatsMapKey]).memUsePercent >= 80}\">\n\t\t\t\t\t\t\t\t\t\t\t<c:set var=\"progressBarStatus\" value=\"progress-bar-danger\"/>\n\t\t                        \t\t</c:when>\n\t\t                        \t\t<c:otherwise>\n\t\t\t\t\t\t\t\t\t\t\t<c:set var=\"progressBarStatus\" value=\"progress-bar-success\"/>\n\t\t                        \t\t</c:otherwise>\n\t\t                        \t</c:choose>\n                                    <div class=\"progress-bar ${progressBarStatus}\"\n                                         role=\"progressbar\"\n                                         aria-valuenow=\"${(instanceStatsMap[instanceStatsMapKey]).memUsePercent }\"\n                                         aria-valuemax=\"100\"\n                                         aria-valuemin=\"0\"\n                                         style=\"width: ${(instanceStatsMap[instanceStatsMapKey]).memUsePercent }%\">\n                                            <label style=\"color: #000000\">\n                                                <fmt:formatNumber\n                                                        value=\"${(instanceStatsMap[instanceStatsMapKey]).usedMemory / 1024 / 1024 / 1024}\"\n                                                        pattern=\"0.00\"/>G&nbsp;&nbsp;Used/<fmt:formatNumber value=\"${(instanceStatsMap[instanceStatsMapKey]).maxMemory / 1024 / 1024 / 1024}\" pattern=\"0.00\"/>G&nbsp;&nbsp;Total\n                                            </label>\n                                     </div>\n                                </div>\n                            </td>\n                            <td>${instance.roleDesc}</td>\n                            <td><fmt:formatNumber\n                                    value=\"${(machineCanUseMem[instance.ip])/1024/1024/1024}\"\n                                    pattern=\"0.00\"/>G\n                            </td>\n                            <td>\n                            \t${instanceStatsMap[instanceStatsMapKey].currItems}\n                            </td>\n                            <td>\n                            \t${clusterSlotsMap[instanceStatsMapKey].slotDistributeList}\n                            </td>\n                        </tr>\n                    </c:forEach>\n                    </tbody>\n                </table>\n                <br/>\n                <table class=\"table table-striped table-bordered table-hover\" id=\"tableDataList\">\n                    <tbody>\n                    <tr>\n                        <td>申请人：</td>\n                        <td>${appAudit.userName}</td>\n                        <td>appId:</td>\n                        <td>${appAudit.appId}</td>\n                    </tr>\n                    <tr>\n                        <td>申请原因：</td>\n                        <td>${appAudit.info}</td>\n                        <td>申请时间：</td>\n                        <td><fmt:formatDate value=\"${appAudit.createTime}\" pattern=\"yyyy-MM-dd HH:mm:ss\"/></td>\n                    </tr>\n                    </tbody>\n                </table>\n            </div>\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/appAudit/appScaleApplyDetail.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\" pageEncoding=\"UTF-8\" %>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\" %>\n\n\n<div class=\"page-container\">\n    <div class=\"page-content\">\n        <%@include file=\"appIntanceReferList.jsp\" %>\n\n        <div class=\"row\">\n            <div class=\"col-md-12\">\n                <div class=\"portlet box light-grey\">\n                    <div class=\"portlet-title\">\n                        <div class=\"caption\">\n                            <i class=\"fa fa-globe\"></i>\n                            \t填写扩容配置\n                            &nbsp;\n                        </div>\n                        <div class=\"tools\">\n                            <a href=\"javascript:;\" class=\"collapse\"></a>\n                            <a href=\"javascript:;\" class=\"remove\"></a>\n                        </div>\n                    </div>\n                    <div class=\"portlet-body\">\n                        <div class=\"form\">\n                            <!-- BEGIN FORM-->\n                            <form action=\"/manage/app/addAppScaleApply.do\" method=\"post\"\n                                  class=\"form-horizontal form-bordered form-row-stripped\"\n                                  onsubmit=\"return checkAppScaleText();\">\n                                <div class=\"form-body\">\n                                    <div class=\"form-group\">\n                                        <label class=\"control-label col-md-3\">\n                                            \t扩容配置:<font color='red'>(*)</font>:\n                                        </label>\n\n                                        <div class=\"col-md-5\">\n                                            <textarea rows=\"1\" name=\"appScaleText\" id=\"appScaleText\"\n                                                      placeholder=\"请输入扩容后单实例最大内存（填写数字即可，单位MB）\"\n                                                      class=\"form-control\"></textarea>\n                                        </div>\n                                    </div>\n                                    <input type=\"hidden\" name=\"appId\" value=\"${appId}\">\n                                    <input type=\"hidden\" name=\"appAuditId\" value=\"${appAuditId}\">\n\n                                    <div class=\"form-actions fluid\">\n                                        <div class=\"row\">\n                                            <div class=\"col-md-12\">\n                                                <div class=\"col-md-offset-3 col-md-3\">\n                                                    <button type=\"submit\" class=\"btn green\">\n                                                        <i class=\"fa fa-check\"></i>\n                                                       \t 确认\n                                                    </button>\n\n                                                </div>\n                                                <c:if test=\"${appDesc.type == 2}\">\n                                                \t<div class=\"col-md-6 \">\n\t                                                    <a class=\"btn btn-info\" href=\"/manage/app/initHorizontalScaleApply?appAuditId=${appAuditId}\">水平扩容</a>\n\t                                                </div>\n                                                </c:if>\n                                            </div>\n                                        </div>\n                                    </div>\n\n\n                                </div>\n                            </form>\n                            <!-- END FORM-->\n                        </div>\n                    </div>\n                </div>\n                <!-- END EXAMPLE TABLE PORTLET-->\n            </div>\n        </div>\n    </div>\n</div>\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/appAudit/handleHorizontalScale.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\"\n    pageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n\t<title>CacheCloud管理后台</title>\n\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n\t\n\t<%@include file=\"/WEB-INF/jsp/manage/include/cache_cloud_main_css.jsp\" %>\n\t\t\n</head>\n\n<body class=\"page-header-fixed\">\n\t<%@include file=\"/WEB-INF/jsp/manage/include/head.jsp\" %>\n\n\t<%@include file=\"/WEB-INF/jsp/manage/include/left.jsp\" %>\n\t\n\t<%@include file=\"handleHorizontalScaleDetail.jsp\" %>\n\t\n\t<%@include file=\"/WEB-INF/jsp/manage/include/foot.jsp\" %>\n\n\t<%@include file=\"/WEB-INF/jsp/manage/include/cache_cloud_main_js.jsp\" %>\n\t\n</body>\n</html>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/appAudit/handleHorizontalScaleDetail.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\" pageEncoding=\"UTF-8\" %>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\" %>\n\n\n<div class=\"page-container\">\n    <div class=\"page-content\">\n    \n        <%@include file=\"appIntanceReferList.jsp\" %>\n    \t<%@include file=\"horizontalScaleProcessList.jsp\" %>\n\n\t\t<div class=\"row\">\n\t\t    <div class=\"col-md-12\">\n\t\t        <h3 class=\"page-title\">\n\t\t        \t迁移计划\n\t\t        </h3>\n\t\t    </div>\n\t\t</div>\n\n        <div class=\"row\">\n            <div class=\"col-md-12\">\n                <div class=\"portlet box light-grey\">\n                    <div class=\"portlet-title\">\n                        <div class=\"caption\">\n                            <i class=\"fa fa-globe\"></i>\n                            \t填写迁移计划\n                            &nbsp;\n                        </div>\n                        <div class=\"tools\">\n                            <a href=\"javascript:;\" class=\"collapse\"></a>\n                            <a href=\"javascript:;\" class=\"remove\"></a>\n                        </div>\n                    </div>\n                    <div class=\"portlet-body\">\n                        <div class=\"form\">\n                            <!-- BEGIN FORM-->\n                            <form class=\"form-horizontal form-bordered form-row-stripped\">\n                                <div class=\"form-body\">\n                                    <div class=\"form-group\">\n                                        <label class=\"control-label col-md-3\">\n                                            \t源实例ID:<font color='red'>(*)</font>:\n                                        </label>\n                                        <div class=\"col-md-5\">\n                                            <input type=\"text\" name=\"sourceId\" id=\"sourceId\" class=\"form-control\" onchange=\"testisNum(this.id)\"/>\n                                        </div>\n                                    </div>\n                                    \n                                    <div class=\"form-group\">\n                                        <label class=\"control-label col-md-3\">\n                                            \t目标实例ID:<font color='red'>(*)</font>:\n                                        </label>\n                                        <div class=\"col-md-5\">\n                                            <input type=\"text\" name=\"targetId\" id=\"targetId\" class=\"form-control\" onchange=\"testisNum(this.id)\"/>\n                                        </div>\n                                    </div>\n                                    \n                                    <div class=\"form-group\">\n                                        <label class=\"control-label col-md-3\">\n                                            \t开始slot:<font color='red'>(*)</font>:\n                                        </label>\n                                        <div class=\"col-md-5\">\n                                            <input type=\"text\" name=\"startSlot\" id=\"startSlot\" class=\"form-control\" onchange=\"testisNum(this.id)\"/>\n                                        </div>\n                                    </div>\n                                    \n                                    <div class=\"form-group\">\n                                        <label class=\"control-label col-md-3\">\n                                            \t结束slot:<font color='red'>(*)</font>:\n                                        </label>\n                                        <div class=\"col-md-5\">\n                                            <input type=\"text\" name=\"endSlot\" id=\"endSlot\" class=\"form-control\" onchange=\"testisNum(this.id)\"/>\n                                        </div>\n                                    </div>\n                                    \n                                    <div class=\"form-group\">\n                                        <label class=\"control-label col-md-3\">\n                                             \t批量migrate<font color='red'>(*)</font>:\n                                        </label>\n                                        <div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t<select id=\"migrateType\" name=\"migrateType\" class=\"form-control select2_category\">\n\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t否\n\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"1\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t是\n\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\t\t\t\t</div>\n                                    </div>\n                                    \n                                    <input type=\"hidden\" name=\"appId\" id=\"appId\" value=\"${appAudit.appId}\">\n                                    <input type=\"hidden\" name=\"appAuditId\" id=\"appAuditId\" value=\"${appAudit.id}\">\n\n                                    <div class=\"form-actions fluid\">\n                                        <div class=\"row\">\n                                            <div class=\"col-md-12\">\n                                                <div class=\"col-md-offset-3 col-md-3\">\n                                                    <button id=\"submitButton\" disabled=\"disabled\" type=\"button\" class=\"btn green\" onclick=\"startHorizontalScale()\">\n                                                        <i class=\"fa fa-check\"></i>\n                                                        \t开始迁移\t\n                                                    </button>\n                                                    <button id=\"checkButton\" type=\"button\" class=\"btn green\" onclick=\"checkHorizontalScale()\">\n                                                        <i class=\"fa fa-check\"></i>\n                                                        \t验证格式\n                                                    </button>\n                                                </div>\n                                            </div>\n                                        </div>\n                                    </div>\n                                </div>\n                            </form>\n                            <!-- END FORM-->\n                        </div>\n                    </div>\n                </div>\n                <!-- END EXAMPLE TABLE PORTLET-->\n            </div>\n        </div>\n        \n        <!-- 下线 -->\n        <!--\n        <div class=\"row\">\n            <div class=\"col-md-12\">\n                <div class=\"portlet box light-grey\">\n                    <div class=\"portlet-title\">\n                        <div class=\"caption\">\n                            <i class=\"fa fa-globe\"></i>\n                            \t填写下线配置\n                            &nbsp;\n                        </div>\n                        <div class=\"tools\">\n                            <a href=\"javascript:;\" class=\"collapse\"></a>\n                            <a href=\"javascript:;\" class=\"remove\"></a>\n                        </div>\n                    </div>\n                    <div class=\"portlet-body\">\n                        <div class=\"form\">\n                            <form action=\"/manage/app/offLineHorizontalShard.do\" method=\"post\"\n                                  class=\"form-horizontal form-bordered form-row-stripped\"\n                                  onsubmit=\"return checkOffLineInstanceParam();\">\n                                <div class=\"form-body\">\n                                    <div class=\"form-group\">\n                                        <label class=\"control-label col-md-3\">\n                                            \tip:<font color='red'>(*)</font>:\n                                        </label>\n                                        <div class=\"col-md-5\">\n                                            <input type=\"text\" name=\"ip\" id=\"dropIp\" value=\"${dropIp}\" class=\"form-control\"/>\n                                        </div>\n                                    </div>\n                                    \n                                    <div class=\"form-group\">\n                                        <label class=\"control-label col-md-3\">\n                                            \tport:<font color='red'>(*)</font>:\n                                        </label>\n                                        <div class=\"col-md-5\">\n                                            <input type=\"text\" name=\"port\" id=\"dropPort\" value=\"${dropPort}\" class=\"form-control\"/>\n                                        </div>\n                                    </div>\n                                    \n                                    <input type=\"hidden\" name=\"appId\" value=\"${appAudit.appId}\">\n                                    <input type=\"hidden\" name=\"appAuditId\" value=\"${appAudit.id}\">\n\n                                    <div class=\"form-actions fluid\">\n                                        <div class=\"row\">\n                                            <div class=\"col-md-12\">\n                                                <div class=\"col-md-offset-3 col-md-3\">\n                                                    <button type=\"submit\" class=\"btn green\">\n                                                        <i class=\"fa fa-check\"></i>\n                                                        \t提交\n                                                    </button>\n                                                </div>\n                                            </div>\n                                        </div>\n                                    </div>\n                                </div>\n                            </form>\n                        </div>\n                    </div>\n                </div>\n            </div>\n        </div>\n        -->\n        \n        \n    </div>\n</div>\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/appAudit/horizontalScaleApplyDetail.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\" pageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<script type=\"text/javascript\">\n\tfunction checkNodes(){\n\t\tvar masterSizeSlave = document.getElementById(\"masterSizeSlave\");\n\t\tif(masterSizeSlave.value == \"\"){\n\t\t\talert(\"节点信息不能为空\");\n\t\t\tmasterSizeSlave.focus();\n\t\t\treturn false;\n\t\t}\n\t\tvar appAuditId = document.getElementById(\"appAuditId\");\n\t\t$.get(\n\t\t\t'/manage/app/checkHorizontalNodes.json',\n\t\t\t{\n\t\t\t\tappAuditId: appAuditId.value,\n\t\t\t\tmasterSizeSlave: masterSizeSlave.value\n\t\t\t},\n\t        function(data){\n\t\t\t\tvar status = data.status;\n\t\t\t\talert(data.message);\n\t\t\t\tif (status == 1) {\n\t\t\t\t\tvar nodeDeployBtn = document.getElementById(\"nodeDeployBtn\");\n\t\t\t\t\tnodeDeployBtn.disabled = false;\n\t\t    \t\t\n\t\t    \t\tvar nodeCheckBtn = document.getElementById(\"nodeCheckBtn\");\n\t\t    \t\tnodeCheckBtn.disabled = true;\n\t\t    \t\t\n\t\t    \t\tmasterSizeSlave.disabled = true;\n\t\t\t\t} else {\n\t\t\t\t\tmasterSizeSlave.focus();\n\t\t\t\t}\n\t        }\n\t     );\n\t}\n\t\n\tfunction deployNodes(){\n\t\tvar masterSizeSlave = document.getElementById(\"masterSizeSlave\");\n\t\tvar appAuditId = document.getElementById(\"appAuditId\");\n\t\t\n\t\tvar nodeDeployBtn = document.getElementById(\"nodeDeployBtn\");\n\t\tnodeDeployBtn.disabled = true;\n\t\t\n\t\t$.get(\n\t\t\t'/manage/app/addHorizontalNodes.json',\n\t\t\t{\n\t\t\t\tappAuditId: appAuditId.value,\n\t\t\t\tmasterSizeSlave: masterSizeSlave.value\n\t\t\t},\n\t\t\tfunction(data){\n\t\t\t\tvar status = data.status;\n\t\t\t\tif (status == 1) {\n\t\t\t\t\talert(\"添加部署成功,确认后将跳转到ReShard页面!\");\n\t\t\t\t\twindow.location.href=\"/manage/app/handleHorizontalScale?appAuditId=\" + appAuditId.value;\n\t\t\t\t} else {\n\t\t\t\t\talert(\"节点部署失败,请查看系统日志确认相关原因!\");\n\t\t\t\t}\n\t        }\n\t     );\n\t}\n\n</script>\n\n<div class=\"page-container\">\n\t<div class=\"page-content\">\n\t\t\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-md-12\">\n\t\t\t\t<h3 class=\"page-title\">\n\t\t\t\t添加新的节点(不分配slot，只meet到集群)\n\t\t\t\t</h3>\n\t\t\t</div>\n\t\t</div>\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-md-12\">\n\t\t\t\t<div class=\"portlet box light-grey\">\n\t\t\t\t\t<div class=\"portlet-title\">\n\t\t\t\t\t\t<div class=\"caption\">\n\t\t\t\t\t\t\t<i class=\"fa fa-globe\"></i>\n\t\t\t\t\t\t\t填写扩容配置:\n\t\t\t\t\t\t\t&nbsp;\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"tools\">\n\t\t\t\t\t\t\t<a href=\"javascript:;\" class=\"collapse\"></a>\n\t\t\t\t\t\t\t<a href=\"javascript:;\" class=\"remove\"></a>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"portlet-body\">\n\t\t\t\t\t\t<div class=\"form\">\n\t\t\t\t\t\t\t\t<!-- BEGIN FORM-->\n\t\t\t\t\t\t\t\t<form class=\"form-horizontal form-bordered form-row-stripped\">\n\t\t\t\t\t\t\t\t\t<div class=\"form-body\">\n\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">主从分片配置:</label>\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"masterSizeSlave\" id=\"masterSizeSlave\" placeholder=\"materIp:memSize:slaveIp\" class=\"form-control\">\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t<input type=\"hidden\" id=\"appAuditId\" name=\"appAuditId\" value=\"${appAudit.id}\">\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t<div class=\"form-actions fluid\">\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-offset-3 col-md-6\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<button disabled=\"disabled\" id=\"nodeDeployBtn\" type=\"button\" class=\"btn green\" onclick=\"deployNodes()\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-check\"></i>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t部署节点\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<button type=\"button\" id=\"nodeCheckBtn\" class=\"btn green\" onclick=\"checkNodes()\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-check\"></i>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t验证格式\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<a target=\"_blank\" class=\"btn green\" href=\"/manage/app/handleHorizontalScale?appAuditId=${appAudit.id}\">ReShard页面</a>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</form>\n\t\t\t\t\t\t\t\t<!-- END FORM-->\n\t\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<!-- END EXAMPLE TABLE PORTLET-->\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/appAudit/horizontalScaleProcessList.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\" pageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n\n<div class=\"row\">\n    <div class=\"col-md-12\">\n        <h3 class=\"page-title\">\n        \t迁移进度\n        </h3>\n    </div>\n</div>\n<div class=\"row\">\n    <div class=\"col-md-12\">\n        <div class=\"portlet box light-grey\">\n            <div class=\"portlet-title\">\n                <div class=\"caption\"><i class=\"fa fa-globe\"></i>扩容进度</div>\n                <div class=\"tools\">\n                    <a href=\"javascript:;\" class=\"collapse\"></a>\n                </div>\n            </div>\n            <div class=\"portlet-body\">\n                <table class=\"table table-striped table-bordered table-hover\" id=\"tableDataList\">\n                    <thead>\n                    <tr>\n                        <td>id</td>\n                        <td>slot迁移进度</td>\n                        <td>目标源实例</td>\n                        <td>开始结束slot</td>\n                        <td>正在迁移的slot</td>\n                        <td>状态</td>\n                        <td>开始时间</td>\n                        <td>结束时间</td>\n                        <td>操作</td>\n                    </tr>\n                    </thead>\n                    <tbody>\n\t                    <c:forEach var=\"instanceReshardProcess\" items=\"${instanceReshardProcessList}\">\n\t                        <tr>\n\t                            <td>${instanceReshardProcess.id}</td>\n\t                            <td>\n\t\t                          <div class=\"progress margin-custom-bottom0\">\n\t\t\t\t\t\t\t      \t  <div id=\"reshardSlotProgress${instanceReshardProcess.id}\" class=\"progress-bar progress-bar-success\"\n\t\t\t\t\t\t\t           role=\"progressbar\" aria-valuenow=\"${instanceReshardProcess.finishSlotNum}\" aria-valuemax=\"${instanceReshardProcess.totalSlot}\"\n\t\t\t\t\t\t\t           aria-valuemin=\"0\" style=\"width: ${instanceReshardProcess.finishSlotNum / instanceReshardProcess.totalSlot}\">\n\t\t\t\t\t\t\t             <label style=\"color: #000000\">\n\t\t\t\t\t\t\t                 <span id=\"finishSlotNum${instanceReshardProcess.id}\">${instanceReshardProcess.finishSlotNum}</span>&nbsp;&nbsp;Finish/<span id=\"totalSlot${instanceReshardProcess.id}\">${instanceReshardProcess.totalSlot}</span>&nbsp;&nbsp;Total\n\t\t\t\t\t\t\t             </label>\n\t\t\t\t\t\t\t           </div>\n\t\t\t\t\t\t\t       </div>\n\t                            </td>\n\t                            <td id=\"sourceTargetInstance${instanceReshardProcess.id}\">\n\t                                ${instanceReshardProcess.sourceInstanceId}(${instanceInfoMap[instanceReshardProcess.sourceInstanceId].ip}:${instanceInfoMap[instanceReshardProcess.sourceInstanceId].port})\n\t                            \t\t-->\n\t                            \t\t${instanceReshardProcess.targetInstanceId}(${instanceInfoMap[instanceReshardProcess.targetInstanceId].ip}:${instanceInfoMap[instanceReshardProcess.targetInstanceId].port})\n\t                            </td>\n\t                            <td id=\"startEndSlot${instanceReshardProcess.id}\">\n\t                            \t\t${instanceReshardProcess.startSlot} \n\t                            \t\t-->\n\t                            \t\t${instanceReshardProcess.endSlot} \n\t                            </td>\n\t                            <td id=\"migratingSlot${instanceReshardProcess.id}\">\n\t                            \t\t${instanceReshardProcess.migratingSlot} \n\t                            </td>\n\t                            <td id=\"statusDesc${instanceReshardProcess.id}\">\n\t\t                            \t<c:choose>\n\t\t                            \t\t<c:when test=\"${instanceReshardProcess.status == 0}\">运行中</c:when>\n\t\t                            \t\t<c:when test=\"${instanceReshardProcess.status == 1}\">完成</c:when>\n\t\t                            \t\t<c:when test=\"${instanceReshardProcess.status == 2}\">出错</c:when>\n\t\t                            \t</c:choose>\n\t                            </td>\n\t                            <td>\n\t                            \t\t<fmt:formatDate value=\"${instanceReshardProcess.startTime}\" type=\"time\" timeStyle=\"full\" pattern=\"yyyy-MM-dd HH:mm:ss\"/>\n\t                            </td>\n\t                            <td id=\"endTime${instanceReshardProcess.id}\">\n\t                            \t\t<c:if test=\"${instanceReshardProcess.status == 1}\">\n\t                            \t\t\t<fmt:formatDate value=\"${instanceReshardProcess.endTime}\" type=\"time\" timeStyle=\"full\" pattern=\"yyyy-MM-dd HH:mm:ss\"/>\n\t                            \t\t</c:if>\n\t                            </td>\n\t                            <td>\n\t                            \t   <c:if test=\"${instanceReshardProcess.status == 2}\">\n\t\t                            \t   <button id=\"retryBtn${instanceReshardProcess.id}\"  type=\"button\" class=\"btn btn-small\" onclick=\"retryHorizontalScale('${instanceReshardProcess.id}')\">\n\t                                        \t重试\n\t                                    </button>\n\t                            \t   </c:if>\n\t                            </td>\n\t                        </tr>\n\t                    </c:forEach>\n                    </tbody>\n                </table>\n            </div>\n        </div>\n    </div>\n</div>\n<script type=\"text/javascript\">\n\t$(function(){\n\t\tfunction show(){\n\t\t   var auditId = document.getElementById(\"appAuditId\").value\n\t\t   var url = \"/manage/app/showReshardProcess.json?auditId=\" + auditId;\n\t\t   $.get(url, function(data) {\n  \t\t\t\tvar dataArr = eval(\"(\" + data + \")\");\n  \t\t\t\tvar length = dataArr.length;\n\n  \t\t\t\tfor (var i = 0; i < length; i++) {\n  \t\t\t\t\tvar data = dataArr[i];\n  \t\t\t\t\tvar id = data.id;\n  \t\t\t\t\tvar appId = data.appId;\n  \t\t\t\t\tvar finishSlotNum = data.finishSlotNum;\n  \t\t\t\t\tvar totalSlot = data.totalSlot;\n  \t\t\t\t\tvar status = data.status;\n  \t\t\t\t\tvar statusDesc = data.statusDesc;\n  \t\t\t\t\tvar migratingSlot = data.migratingSlot;\n  \t\t\t\t\tvar endTimeFormat = data.endTimeFormat;\n  \t\t\t\t\tdocument.getElementById(\"finishSlotNum\" + id).innerHTML = finishSlotNum;\n  \t\t\t\t\tdocument.getElementById(\"totalSlot\" + id).innerHTML = totalSlot;\n  \t\t\t\t\tdocument.getElementById(\"reshardSlotProgress\" + id).style.width = (finishSlotNum * 100 / totalSlot ) + \"%\";\n  \t\t\t\t\tdocument.getElementById(\"statusDesc\" + id).innerHTML = statusDesc;\n  \t\t\t\t\tdocument.getElementById(\"migratingSlot\" + id).innerHTML = migratingSlot;\n  \t\t\t\t\t//如果完成显示结束时间\n  \t\t\t\t\tif (status == 1) {\n  \t  \t\t\t\t\tdocument.getElementById(\"endTime\" + id).innerHTML = endTimeFormat;\n  \t\t\t\t\t}\n  \t\t\t\t\t//非出错不显示\n  \t\t\t\t\tif (status != 2) {\n  \t  \t\t\t\t\tvar retryBtn = document.getElementById(\"retryBtn\" + id);\n  \t  \t\t\t\t\tif (retryBtn != null) {\n  \t  \t\t\t\t\t\tretryBtn.style.display = \"none\";\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\tsetInterval(show,2000);// 注意函数名没有引号和括弧！\n\t\t// 使用setInterval(\"show()\",3000);会报“缺少对象”\n\t});\n</script>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/appAudit/initAppConfigChange.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\"\n    pageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n\t<title>CacheCloud管理后台</title>\n\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n\t\n\t<%@include file=\"/WEB-INF/jsp/manage/include/cache_cloud_main_css.jsp\" %>\n\t\t\n</head>\n\n<body class=\"page-header-fixed\">\n\t<%@include file=\"/WEB-INF/jsp/manage/include/head.jsp\" %>\n\n\t<%@include file=\"/WEB-INF/jsp/manage/include/left.jsp\" %>\n\t\n\t<%@include file=\"appConfigChangeDetail.jsp\" %>\n\t\n\t<%@include file=\"/WEB-INF/jsp/manage/include/foot.jsp\" %>\n\n\t<%@include file=\"/WEB-INF/jsp/manage/include/cache_cloud_main_js.jsp\" %>\n\t\n</body>\n</html>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/appAudit/initAppDeploy.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\"\n    pageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n\t<title>CacheCloud管理后台</title>\n\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n\t\n\t<%@include file=\"/WEB-INF/jsp/manage/include/cache_cloud_main_css.jsp\" %>\n\t\t\n</head>\n\n<body class=\"page-header-fixed\">\n\t<%@include file=\"/WEB-INF/jsp/manage/include/head.jsp\" %>\n\n\t<%@include file=\"/WEB-INF/jsp/manage/include/left.jsp\" %>\n\t\n\t<%@include file=\"appDeployDetail.jsp\" %>\n\t\n\t<%@include file=\"/WEB-INF/jsp/manage/include/foot.jsp\" %>\n\n\t<%@include file=\"/WEB-INF/jsp/manage/include/cache_cloud_main_js.jsp\" %>\n\t\n</body>\n</html>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/appAudit/initAppScaleApply.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\"\n    pageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n\t<title>CacheCloud管理后台</title>\n\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n\t\n\t<%@include file=\"/WEB-INF/jsp/manage/include/cache_cloud_main_css.jsp\" %>\n\t\t\n</head>\n\n<body class=\"page-header-fixed\">\n\t<%@include file=\"/WEB-INF/jsp/manage/include/head.jsp\" %>\n\n\t<%@include file=\"/WEB-INF/jsp/manage/include/left.jsp\" %>\n\t\n\t<%@include file=\"appScaleApplyDetail.jsp\" %>\n\t\n\t<%@include file=\"/WEB-INF/jsp/manage/include/foot.jsp\" %>\n\n\t<%@include file=\"/WEB-INF/jsp/manage/include/cache_cloud_main_js.jsp\" %>\n\t\n</body>\n</html>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/appAudit/initHorizontalScaleApply.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\"\n    pageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n\t<title>CacheCloud管理后台</title>\n\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n\t\n\t<%@include file=\"/WEB-INF/jsp/manage/include/cache_cloud_main_css.jsp\" %>\n\t\t\n</head>\n\n<body class=\"page-header-fixed\">\n\t<%@include file=\"/WEB-INF/jsp/manage/include/head.jsp\" %>\n\n\t<%@include file=\"/WEB-INF/jsp/manage/include/left.jsp\" %>\n\t\n\t<%@include file=\"horizontalScaleApplyDetail.jsp\" %>\n\t\n\t<%@include file=\"/WEB-INF/jsp/manage/include/foot.jsp\" %>\n\n\t<%@include file=\"/WEB-INF/jsp/manage/include/cache_cloud_main_js.jsp\" %>\n\t\n</body>\n</html>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/appAudit/initInstanceConfigChange.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\"\n    pageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n\t<title>CacheCloud管理后台</title>\n\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n\t\n\t<%@include file=\"/WEB-INF/jsp/manage/include/cache_cloud_main_css.jsp\" %>\n\t\t\n</head>\n\n<body class=\"page-header-fixed\">\n\t<%@include file=\"/WEB-INF/jsp/manage/include/head.jsp\" %>\n\n\t<%@include file=\"/WEB-INF/jsp/manage/include/left.jsp\" %>\n\t\n\t<%@include file=\"instanceConfigChangeDetail.jsp\" %>\n\t\n\t<%@include file=\"/WEB-INF/jsp/manage/include/foot.jsp\" %>\n\n\t<%@include file=\"/WEB-INF/jsp/manage/include/cache_cloud_main_js.jsp\" %>\n\t\n</body>\n</html>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/appAudit/instanceConfig.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\" pageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n\n<div class=\"row\">\n\t<div class=\"col-md-12\">\n\t\t<h3 class=\"page-title\">\n\t\t\t配置信息\n\t\t</h3>\n\t</div>\n</div>\n<div class=\"row\">\n\t<div class=\"col-md-12\">\n\t\t<div class=\"portlet box light-grey\">\n\t\t\t<div class=\"portlet-title\">\n\t\t\t\t<div class=\"caption\"><i class=\"fa fa-globe\"></i>配置信息列表</div>\n\t\t\t\t<div class=\"tools\">\n\t\t\t\t\t<a href=\"javascript:;\" class=\"collapse\"></a>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"portlet-body\">\n\t\t\t\t<table class=\"table table-striped table-bordered table-hover\" id=\"tableDataList\">\n\t\t\t\t\t<thead>\n\t\t\t\t\t\t<tr>\n\t\t\t                <td>配置项</td>\n\t\t\t                <td>配置值</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t</thead>\n\t\t\t\t\t<tbody>\n            \t\t\t<c:forEach items=\"${redisConfigList}\" var=\"redisConfig\" varStatus=\"status\">\n\t\t\t                <tr>\n\t\t\t                    <td>${redisConfig.key}</td>\n\t\t\t                    <td>${redisConfig.value}</td>\n\t\t\t                </tr>\n\t\t\t            </c:forEach>\n\t\t\t\t\t</tbody>\n\t\t\t\t</table>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/appAudit/instanceConfigChangeDetail.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\" pageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n\n\n<div class=\"page-container\">\n\t<div class=\"page-content\">\n\t\t\n\t\t<%@include file=\"instanceConfig.jsp\" %>\n\t\t\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-md-12\">\n\t\t\t\t<h3 class=\"page-title\">\n\t\t\t\t\t配置修改(<font color=\"red\">${appAudit.info}</font>)\n\t\t\t\t</h3>\n\t\t\t</div>\n\t\t</div>\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-md-12\">\n\t\t\t\t<div class=\"portlet box light-grey\">\n\t\t\t\t\t<div class=\"portlet-title\">\n\t\t\t\t\t\t<div class=\"caption\">\n\t\t\t\t\t\t\t<i class=\"fa fa-globe\"></i>\n\t\t\t\t\t\t\t配置\n\t\t\t\t\t\t\t&nbsp;\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"tools\">\n\t\t\t\t\t\t\t<a href=\"javascript:;\" class=\"collapse\"></a>\n\t\t\t\t\t\t\t<a href=\"javascript:;\" class=\"remove\"></a>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"portlet-body\">\n\t\t\t\t\t\t<div class=\"form\">\n\t\t\t\t\t\t\t\t<!-- BEGIN FORM-->\n\t\t\t\t\t\t\t\t<form action=\"/manage/instance/addInstanceConfigChange\" method=\"post\"\n\t\t\t\t\t\t\t\t\tclass=\"form-horizontal form-bordered form-row-stripped\" onsubmit=\"return checkInstanceConfig();\">\n\t\t\t\t\t\t\t\t\t\t<div class=\"form-body\">\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">配置项:</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"instanceConfigKey\" id=\"instanceConfigKey\" value=\"${instanceConfigKey}\" class=\"form-control\" />\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">配置值:</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"instanceConfigValue\" id=\"instanceConfigValue\" value=\"${instanceConfigValue}\" class=\"form-control\">\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t<input type=\"hidden\" name=\"host\" value=\"${instanceInfo.ip}\">\n\t\t\t\t\t\t\t\t\t\t\t<input type=\"hidden\" name=\"port\" value=\"${instanceInfo.port}\">\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t<input type=\"hidden\" name=\"appId\" value=\"${appId}\">\n\t\t\t\t\t\t\t\t\t\t\t<input type=\"hidden\" name=\"appAuditId\" value=\"${appAuditId}\">\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-actions fluid\">\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-offset-3 col-md-9\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<button type=\"submit\" class=\"btn green\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-check\"></i>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t确认\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</form>\n\t\t\t\t\t\t\t\t<!-- END FORM-->\n\t\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<!-- END EXAMPLE TABLE PORTLET-->\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/appAudit/list.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\"\n    pageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n\t<title>CacheCloud管理后台</title>\n\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n\t\n\t<%@include file=\"/WEB-INF/jsp/manage/include/cache_cloud_main_css.jsp\" %>\n\t\t\n</head>\n\n<body class=\"page-header-fixed\">\n\t<%@include file=\"/WEB-INF/jsp/manage/include/head.jsp\" %>\n\n\t<%@include file=\"/WEB-INF/jsp/manage/include/left.jsp\" %>\n\t\n\t<%@include file=\"appAuditList.jsp\" %>\n\t\n\t<%@include file=\"/WEB-INF/jsp/manage/include/foot.jsp\" %>\n\n\t<%@include file=\"/WEB-INF/jsp/manage/include/cache_cloud_main_js.jsp\" %>\n\t\n</body>\n</html>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/appAudit/machineForHorizontalScaleList.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\" pageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<div class=\"row\">\n\t<div class=\"col-md-12\">\n\t\t<h3 class=\"page-title\">\n\t\t\t机器列表\n\t\t</h3>\n\t</div>\n</div>\n<div class=\"row\">\n\t<div class=\"col-md-12\">\n\t\t<div class=\"portlet box light-grey\">\n\t\t\t<div class=\"portlet-title\">\n\t\t\t\t<div class=\"caption\"><i class=\"fa fa-globe\"></i>机器列表</div>\n\t\t\t\t<div class=\"tools\">\n\t\t\t\t\t<a href=\"javascript:;\" class=\"collapse\"></a>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"portlet-body\">\n\t\t\t\t<table class=\"table table-striped table-bordered table-hover\"  id=\"tableDataList\">\n\t\t\t\t\t<thead>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<th>ip</th>\n\t\t\t\t\t\t\t<th>内存使用率</th>\n\t\t\t\t\t\t\t<th>已分配内存</th>\n                            <th>可用内存(G)</th>\n                            <th>总内存(G)</th>\n                            <th>可分配内存(G)</th>\n\t\t\t\t\t\t\t<th>CPU使用率</th>\n\t\t\t\t\t\t\t<th>网络流量</th>\n\t\t\t\t\t\t\t<th>机器负载</th>\n\t\t\t\t\t\t\t<th>最后统计时间</th>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t</thead>\n\t\t\t\t\t<tbody>\n\t\t\t\t\t\t<c:forEach items=\"${machineList}\" var=\"machine\" varStatus=\"stat\">\n\t\t\t\t\t\t\t<tr class=\"odd gradeX\">\n\t\t\t\t\t\t\t\t<td <c:if test=\"${stat.index < appMachineSize}\">style=\"background-color: red\"</c:if>>${machine.ip}\n\t\t\t\t\t\t\t\t\t<br/>\n\t\t\t\t\t\t\t\t\t<c:if test=\"${stat.index < appMachineSize}\">应用id:${appId}</c:if>\n\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t<span style=\"display:none\"><fmt:formatNumber value=\"${machine.memoryUsageRatio / 100}\" pattern=\"0.00\"/></span>\n                                    <div class=\"progress margin-custom-bottom0\">\n                                        <fmt:formatNumber var=\"fmtMemoryUsageRatio\" value=\"${machine.memoryUsageRatio}\" pattern=\"0\"/>\n                                        <c:choose>\n                                        <c:when test=\"${fmtMemoryUsageRatio >= 80}\">\n                                        <div class=\"progress-bar progress-bar-danger\"\n                                             role=\"progressbar\" aria-valuenow=\"${machine.memoryUsageRatio}\" aria-valuemax=\"100\"\n                                             aria-valuemin=\"0\" style=\"width: ${machine.memoryUsageRatio}%\">\n                                        </c:when>\n                                        <c:otherwise>\n                                            <div class=\"progress-bar progress-bar-success\"\n                                                 role=\"progressbar\" aria-valuenow=\"${machine.memoryUsageRatio}\" aria-valuemax=\"100\"\n                                                 aria-valuemin=\"0\" style=\"width: ${machine.memoryUsageRatio}%\">\t\t\t\t                    \t\t</c:otherwise>\n                                        </c:choose>\n                                            <label style=\"color: #000000\">\n                                                <fmt:formatNumber value=\"${((machine.memoryTotal-machine.memoryFree)/1024/1024/1024)}\" pattern=\"0.00\"/>\n                                                G&nbsp;&nbsp;Used/\n                                                <fmt:formatNumber value=\"${ machine.memoryTotal/1024/1024/1024}\" pattern=\"0.00\"/>G&nbsp;&nbsp;Total\n                                            </label>\n                                        </div>\n                                    </div>\n\t\t\t\t\t\t\t\t</td>\n                                <td>\n                                    <fmt:formatNumber var=\"fmtMemoryAllocatedRatio\" value=\"${((machine.memoryAllocated)/1024)*100.0/(machine.memoryTotal/1024/1024/1024)}\" pattern=\"0.00\"/>\n                                \t<span  style=\"display:none\"><fmt:formatNumber value=\"${fmtMemoryAllocatedRatio / 100}\" pattern=\"0.00\"/></span>\n                                    <div class=\"progress margin-custom-bottom0\">\n                                        <c:choose>\n                                        <c:when test=\"${fmtMemoryAllocatedRatio >= 80.00}\">\n                                        <div class=\"progress-bar progress-bar-danger\"\n                                             role=\"progressbar\" aria-valuenow=\"${fmtMemoryAllocatedRatio}\" aria-valuemax=\"100\"\n                                             aria-valuemin=\"0\" style=\"width: ${fmtMemoryAllocatedRatio}%\">\n                                            </c:when>\n                                            <c:otherwise>\n                                            <div class=\"progress-bar progress-bar-success\"\n                                                 role=\"progressbar\" aria-valuenow=\"${fmtMemoryAllocatedRatio}\" aria-valuemax=\"100\"\n                                                 aria-valuemin=\"0\" style=\"width: ${fmtMemoryAllocatedRatio}%\">\t\t\t\t                    \t\t</c:otherwise>\n                                                </c:choose>\n                                                <label style=\"color: #000000\">\n                                                    <fmt:formatNumber value=\"${((machine.memoryAllocated)/1024)}\" pattern=\"0.00\"/>G&nbsp;&nbsp;Used/\n                                                    <fmt:formatNumber value=\"${ machine.memoryTotal/1024/1024/1024}\" pattern=\"0.00\"/>G&nbsp;&nbsp;Total\n                                                </label>\n                                            </div>\n                                        </div>\n                                </td>\n                                <td><fmt:formatNumber value=\"${(machine.memoryFree/1024/1024/1024)}\" pattern=\"0.00\"/></td>\n                                <td><fmt:formatNumber value=\"${(machine.memoryTotal/1024/1024/1024)}\" pattern=\"0.00\"/></td>\n                                <td><fmt:formatNumber value=\"${((machine.memoryFree - machine.machineMemInfo.lockedMem)/1024/1024/1024)}\" pattern=\"0.00\"/></td>\n\t\t\t\t\t\t\t\t<td>${machine.cpuUsage}</td>\n\t\t\t\t\t\t\t\t<td>${machine.traffic}</td>\n\t\t\t\t\t\t\t\t<td>${machine.load}</td>\n\t\t\t\t\t\t\t\t<td><fmt:formatDate value=\"${machine.modifyTime}\" type=\"time\" timeStyle=\"full\" pattern=\"yyyy-MM-dd HH:mm\"/></td>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t</c:forEach>\n\t\t\t\t\t</tbody>\n\t\t\t\t</table>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/appAudit/machineReferList.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\" pageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<div class=\"row\">\n\t<div class=\"col-md-12\">\n\t\t<h3 class=\"page-title\">\n\t\t\t机器列表\n\t\t</h3>\n\t</div>\n</div>\n<div class=\"row\">\n\t<div class=\"col-md-12\">\n\t\t<div class=\"portlet box light-grey\">\n\t\t\t<div class=\"portlet-title\">\n\t\t\t\t<div class=\"caption\"><i class=\"fa fa-globe\"></i>机器列表</div>\n\t\t\t\t<div class=\"tools\">\n\t\t\t\t\t<a href=\"javascript:;\" class=\"collapse\"></a>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"portlet-body\">\n\t\t\t\t<table class=\"table table-striped table-bordered table-hover\" id=\"tableDataList\">\n\t\t\t\t\t<thead>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<th>ip</th>\n\t\t\t\t\t\t\t<th>内存使用率</th>\n\t\t\t\t\t\t\t<th>已分配内存</th>\n\t\t\t\t\t\t\t<th>CPU使用率</th>\n\t\t\t\t\t\t\t<th>网络流量</th>\n\t\t\t\t\t\t\t<th>机器负载</th>\n\t\t\t\t\t\t\t<th>是否是虚机</th>\n\t\t\t\t\t\t\t<th>额外说明</th>\n\t\t\t\t\t\t\t<th>机房</th>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t</thead>\n\t\t\t\t\t<tbody>\n\t\t\t\t\t\t<c:forEach items=\"${machineList}\" var=\"machine\">\n\t\t\t\t\t\t\t<tr class=\"odd gradeX\">\n\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t<a target=\"_blank\" href=\"/manage/machine/machineInstances.do?ip=${machine.ip}\">${machine.ip}</a>\n\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t<span style=\"display:none\"><fmt:formatNumber value=\"${machine.memoryUsageRatio / 100}\" pattern=\"0.00\"/></span>\n                                          \n                                          <div class=\"progress margin-custom-bottom0\">\n                                              <fmt:formatNumber var=\"fmtMemoryUsageRatio\" value=\"${machine.memoryUsageRatio}\" pattern=\"0.00\"/>\n                                              <c:choose>\n                                                  <c:when test=\"${fmtMemoryUsageRatio >= 80.00}\">\n                                              <div class=\"progress-bar progress-bar-danger\"\n                                                           role=\"progressbar\" aria-valuenow=\"${machine.memoryUsageRatio}\" aria-valuemax=\"100\"\n                                                           aria-valuemin=\"0\" style=\"width: ${machine.memoryUsageRatio}%\">\n                                                      </c:when>\n                                                      <c:otherwise>\n                                              <div class=\"progress-bar progress-bar-success\"\n                                                               role=\"progressbar\" aria-valuenow=\"${machine.memoryUsageRatio}\" aria-valuemax=\"100\"\n                                                               aria-valuemin=\"0\" style=\"width: ${machine.memoryUsageRatio}%\">\n                                                      </c:otherwise>\n                                              </c:choose>\n                                                  <label style=\"color: #000000\">\n                                                      <fmt:formatNumber value=\"${((machine.memoryTotal-machine.memoryFree)/1024/1024/1024)}\" pattern=\"0.00\"/>G&nbsp;&nbsp;Used/\n                                                      <fmt:formatNumber value=\"${ machine.memoryTotal/1024/1024/1024}\" pattern=\"0.00\"/>G&nbsp;&nbsp;Total\n                                                  </label>\n                                            </div>\n                                            \n\t\t\t\t\t\t\t\t</td>\n                                <td>\n                                    <fmt:formatNumber var=\"fmtMemoryAllocatedRatio\" value=\"${((machine.memoryAllocated)/1024)*100.0/(machine.memoryTotal/1024/1024/1024)}\" pattern=\"0.00\"/>\n                                \t<span  style=\"display:none\"><fmt:formatNumber value=\"${fmtMemoryAllocatedRatio / 100}\" pattern=\"0.00\"/></span>\n                                    <div class=\"progress margin-custom-bottom0\">\n                                        <c:choose>\n                                        <c:when test=\"${fmtMemoryAllocatedRatio >= 80.00}\">\n                                        <div class=\"progress-bar progress-bar-danger\"\n                                             role=\"progressbar\" aria-valuenow=\"${fmtMemoryAllocatedRatio}\" aria-valuemax=\"100\"\n                                             aria-valuemin=\"0\" style=\"width: ${fmtMemoryAllocatedRatio}%\">\n                                            </c:when>\n                                            <c:otherwise>\n                                            <div class=\"progress-bar progress-bar-success\"\n                                                 role=\"progressbar\" aria-valuenow=\"${fmtMemoryAllocatedRatio}\" aria-valuemax=\"100\"\n                                                 aria-valuemin=\"0\" style=\"width: ${fmtMemoryAllocatedRatio}%\">\t\t\t\t                    \t\t</c:otherwise>\n                                                </c:choose>\n                                                <label style=\"color: #000000\">\n                                                    <fmt:formatNumber value=\"${((machine.memoryAllocated)/1024)}\" pattern=\"0.00\"/>G&nbsp;&nbsp;Used/\n                                                    <fmt:formatNumber value=\"${ machine.memoryTotal/1024/1024/1024}\" pattern=\"0.00\"/>G&nbsp;&nbsp;Total\n                                                </label>\n                                            </div>\n                                        </div>\n                                </td>\n\t\t\t\t\t\t\t\t<td>${machine.cpuUsage}</td>\n\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t<fmt:formatNumber value=\"${machine.traffic / 1024 / 1024}\" pattern=\"0.00\"/>M\n\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t<td>${machine.load}</td>\n                                <td>\n                                \t<c:choose>\n                                \t\t<c:when test=\"${machine.info.virtual == 1}\">\n                                \t\t\t是\n                                \t\t\t<br/>\n                                \t\t\t物理机:${machine.info.realIp}\n                                \t\t</c:when>\n                                \t\t<c:otherwise>\n                                \t\t\t否\n                                \t\t</c:otherwise>\n                                \t</c:choose>\n                                </td>\n\t\t\t\t\t\t\t\t<td>${machine.info.extraDesc}</td>\n\t\t\t\t\t\t\t\t<td>${machine.info.room}</td>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t</c:forEach>\n\t\t\t\t\t</tbody>\n\t\t\t\t</table>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/appOps/appInfoAndAudit.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<div class=\"container\">\n    <div class=\"row\">\n        <div class=\"col-md-12\">\n            <div class=\"page-header\">\n                <h4>应用详情-\n                ${appDesc.name}\n                (${appDesc.typeDesc})\n                </h4>\n            </div>\n            <table class=\"table table-striped table-hover table-bordered\">\n                <tbody>\n\t                <tr>\n\t                    <td>应用id</td>\n\t                    <td>${appDesc.appId}</td>\n\t                    <td>应用名称</td>\n\t                    <td>${appDesc.name}</td>\n\t                </tr>\n\t                <tr>\n\t                    <td>应用申请人</td>\n\t                    <td>${appDesc.officer}</td>\n\t                    <td>应用类型</td>\n\t                    <td>\n\t                    \t<c:choose>\n\t        \t\t            <c:when test=\"${appDesc.type == 2}\">redis-cluster</c:when>\n\t\t\t        \t\t    <c:when test=\"${appDesc.type == 5}\">redis-sentinel</c:when>\n\t\t\t        \t\t    <c:when test=\"${appDesc.type == 6}\">redis-standalone</c:when>\n\t                    \t</c:choose>\n\t                    </td>\n\t                </tr>\n\t                <tr>\n\t                    <td>负责人</td>\n\t                    <td>${appDesc.officer}</td>\n\t                    <td>详情</td>\n\t                    <td>${appDesc.intro}</td>\n\t                </tr>\n\t                <tr>\n\t                    <td>创建时间</td>\n\t                    <td><fmt:formatDate pattern=\"yyyy-MM-dd HH:mm:ss\" value=\"${appDesc.createTime}\"/></td>\n\t                    <td>审批通过时间</td>\n\t                    <td><fmt:formatDate pattern=\"yyyy-MM-dd HH:mm:ss\" value=\"${appDesc.passedTime}\"/></td>\n\t                </tr>\n\t                <tr>\n\t                    <td>测试</td>\n\t                    <td>\n\t                    \t<c:choose>\n\t                    \t\t<c:when test=\"${appDesc.isTest == 0}\">否</c:when>\n\t                    \t\t<c:when test=\"${appDesc.isTest == 1}\">是</c:when>\n\t                    \t</c:choose>\n\t                    </td>\n\t                    <td>后端是否有数据源</td>\n\t                    <td>\n\t                    \t<c:choose>\n\t                    \t\t<c:when test=\"${appDesc.hasBackStore == 0}\">有</c:when>\n\t                    \t\t<c:when test=\"${appDesc.hasBackStore == 1}\">无</c:when>\n\t                    \t</c:choose>\n\t                    </td>\n\t                </tr>\n\t                <tr>\n\t                    <td>是否需要持久化</td>\n\t                    <td>\n\t                    \t<c:choose>\n\t                    \t\t<c:when test=\"${appDesc.needPersistence == 0}\">不需要</c:when>\n\t                    \t\t<c:when test=\"${appDesc.needPersistence == 1}\">需要</c:when>\n\t                    \t</c:choose>\n\t                    </td>\n\t                    <td>预计对象数</td>\n\t                    <td>${appDesc.forecastObjNum}</td>\n\t                </tr>\n\t                <tr>\n\t                \t<td>预计QPS</td>\n\t                \t<td>${appDesc.forecaseQps}</td>\n\t                \t<td>是否需要热备</td>\n\t                \t<td>\n\t                \t\t<c:choose>\n\t                    \t\t<c:when test=\"${appDesc.needHotBackUp == 0}\">不需要</c:when>\n\t                    \t\t<c:when test=\"${appDesc.needHotBackUp == 1}\">需要</c:when>\n\t                    \t</c:choose>\n\t                \t</td>\n\t                </tr>\n\t                <tr>\n\t                \t<td>内存报警阀值</td>\n\t                \t<td>${appDesc.memAlertValue}%</td>\n\t                </tr>\n                </tbody>\n            </table>\n        </div>\n    </div>\n    \n    <div class=\"row\">\n   \t \t<div class=\"col-md-12 page-header\">\n            <h4>申请记录</h4>\n        </div>\n   \t\t<div class=\"col-md-12\">\n   \t\t  \t<table class=\"table table-striped table-hover table-bordered\">\n\t   \t\t\t<thead>\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t<th>审批id</th>\n\t\t\t\t\t\t<th>申请人</th>\n\t\t\t\t\t\t<th>申请类型</th>\n\t\t\t\t\t\t<th>申请详情</th>\n\t\t\t\t\t\t<th>申请时间</th>\n\t\t\t\t\t\t<th>审批时间</th>\n\t\t\t\t\t\t<th>审批人</th>\n\t\t\t\t\t\t<th>审批结果</th>\n\t\t\t\t\t\t<th>审批意见</th>\n\t\t\t\t\t</tr>\n\t\t\t\t</thead>\n\t\t\t\t<tbody>\n\t\t\t\t\t<c:forEach items=\"${appAuditList}\" var=\"appAudit\">\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td>${appAudit.id}</td>\n\t\t\t\t\t\t\t<td>${appAudit.userName}</td>\n\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t<c:choose>\n\t\t\t\t\t\t\t\t\t<c:when test=\"${appAudit.type == 0}\">申请应用</c:when>\n\t\t\t\t\t\t\t\t\t<c:when test=\"${appAudit.type == 1}\">应用扩容</c:when>\n\t\t\t\t\t\t\t\t\t<c:when test=\"${appAudit.type == 2}\">修改配置</c:when>\n\t\t\t\t\t\t\t\t</c:choose>\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t<td>${appAudit.info}</td>\n\t\t\t\t\t\t\t<td><fmt:formatDate pattern=\"yyyy-MM-dd HH:mm:ss\" value=\"${appAudit.createTime}\"/></td>\n\t\t\t\t\t\t\t<td><fmt:formatDate pattern=\"yyyy-MM-dd HH:mm:ss\" value=\"${appAudit.modifyTime}\"/></td>\n\t\t\t\t\t\t\t<td>${appAudit.appAuditLog.appUser.name}</td>\n\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t<c:choose>\n\t\t\t\t\t\t\t\t\t<c:when test=\"${appAudit.status == 1}\">审批通过</c:when>\n\t\t\t\t\t\t\t\t\t<c:when test=\"${appAudit.status == -1}\">驳回</c:when>\n\t\t\t\t\t\t\t\t</c:choose>\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t<td>${appAudit.refuseReason}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t</c:forEach>\n\t\t\t\t</tbody>\n\t\t\t</table>\n   \t\t</div>\n    </div>\n\n    <br/><br/><br/>\n\t\n</div>\n\n\n\n\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/appOps/appInstance.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<script type=\"text/javascript\">\n\n\tfunction startInstance(appId, instanceId){\n\t\tif(confirm(\"确认要开启\"+instanceId+\"实例吗?\")){\n\t\t\t$.ajax({\n\t            type: \"get\",\n\t            url: \"/manage/instance/startInstance.json\",\n\t            data: \n\t            {\n\t            \tappId: appId,\n\t            \tinstanceId: instanceId\n\t            },\n\t            success: function (result) {\n\t            \tif(result.success == 1){\n\t            \t\talert(\"开启成功!\");\n\t            \t}else{\n\t            \t\talert(\"开启失败, msg: \" + result.message);\n\t            \t}\n\t                window.location.reload();\n\t            }\n\t        });\n\t    }\n\t}\n\n\tfunction shutdownInstance(appId, instanceId){\n\t\tif(confirm(\"确认要下线\"+instanceId+\"实例吗?\")){\n\t\t\t$.ajax({\n\t            type: \"get\",\n\t            url: \"/manage/instance/shutdownInstance.json\",\n\t            data: \n\t            {\n\t            \tappId: appId,\n\t            \tinstanceId: instanceId\n\t            },\n\t            success: function (result) {\n\t            \tif(result.success == 1){\n\t            \t\talert(\"关闭成功!\");\n\t            \t}else{\n\t            \t\talert(\"关闭失败, msg: \" + result.message);\n\t            \t}\n\t                window.location.reload();\n\t            }\n\t        });\n\t    }\n\t}\n\n\n\tfunction redisClusterFailOverManual(appId, instanceId){\n\t\tvar redisClusterFailOverManualBtn = document.getElementById(\"redisClusterFailOverManualBtn\" + instanceId);\n\t\tredisClusterFailOverManualBtn.disabled = true;\n\t\t$.post(\n\t\t\t'/manage/app/clusterSlaveFailOver.do',\n\t\t\t{\n\t\t\t\tappId: appId,\n\t\t\t\tslaveInstanceId: instanceId,\n\t\t\t\tfailoverParam: ''\n\t\t\t},\n\t        function(data){\n\t            if(data==1){\n\t                alert(\"执行成功!\");\n\t            \t\t$(\"#redisClusterFailOverManualInfo\" + instanceId).html(\"<div class='alert alert-error' ><button class='close' data-dismiss='alert'>×</button><strong>Success!</strong>执行成功，应用的拓扑结构要1分钟之后生效，请耐心等待</div>\");\n\t                var targetId = \"#redisClusterFailOverManualModal\" + instanceId;\n\t            \t\tsetTimeout(\"$('\" + targetId +\"').modal('hide');window.location.reload();\",1000);\n\t            }else{\n\t            \t\tredisClusterFailOverManualBtn.disabled = false;\n\t                $(\"#redisClusterFailOverManualInfo\" + instanceId).html(\"<div class='alert alert-error' ><button class='close' data-dismiss='alert'>×</button><strong>Error!</strong>执行失败，请查找原因！</div>\");\n\t            }\n\t        }\n\t     );\n\t}\n\t\n\tfunction redisClusterFailOverForce(appId, instanceId){\n\t\tvar redisClusterFailOverForceBtn = document.getElementById(\"redisClusterFailOverForceBtn\" + instanceId);\n\t\tredisClusterFailOverForceBtn.disabled = true;\n\t\t$.post(\n\t\t\t'/manage/app/clusterSlaveFailOver.do',\n\t\t\t{\n\t\t\t\tappId: appId,\n\t\t\t\tslaveInstanceId: instanceId,\n\t\t\t\tfailoverParam: 'force'\n\t\t\t},\n\t        function(data){\n\t            if(data==1){\n\t                alert(\"执行成功!\");\n\t            \t\t$(\"#redisClusterFailOverForceInfo\" + instanceId).html(\"<div class='alert alert-error' ><button class='close' data-dismiss='alert'>×</button><strong>Success!</strong>执行成功，应用的拓扑结构要1分钟之后生效，请耐心等待</div>\");\n\t                var targetId = \"#redisClusterFailOverForceModal\" + instanceId;\n\t            \t\tsetTimeout(\"$('\" + targetId +\"').modal('hide');window.location.reload();\",1000);\n\t            }else{\n\t            \t\tredisClusterFailOverForceBtn.disabled = false;\n\t                $(\"#redisClusterFailOverForceInfo\" + instanceId).html(\"<div class='alert alert-error' ><button class='close' data-dismiss='alert'>×</button><strong>Error!</strong>执行失败，请查找原因！</div>\");\n\t            }\n\t        }\n\t     );\n\t}\n\t\n\tfunction redisClusterFailOverTakeOver(appId, instanceId){\n\t\tvar redisClusterFailOverTakeOverBtn = document.getElementById(\"redisClusterFailOverTakeOverBtn\" + instanceId);\n\t\tredisClusterFailOverTakeOverBtn.disabled = true;\n\t\t$.post(\n\t\t\t'/manage/app/clusterSlaveFailOver.do',\n\t\t\t{\n\t\t\t\tappId: appId,\n\t\t\t\tslaveInstanceId: instanceId,\n\t\t\t\tfailoverParam: 'takeover'\n\t\t\t},\n\t        function(data){\n\t            if(data==1){\n\t                alert(\"执行成功!\");\n\t            \t\t$(\"#redisClusterFailOverTakeOverInfo\" + instanceId).html(\"<div class='alert alert-error' ><button class='close' data-dismiss='alert'>×</button><strong>Success!</strong>执行成功，应用的拓扑结构要1分钟之后生效，请耐心等待</div>\");\n\t                var targetId = \"#redisClusterFailOverTakeOverModal\" + instanceId;\n\t            \t\tsetTimeout(\"$('\" + targetId +\"').modal('hide');window.location.reload();\",1000);\n\t            }else{\n\t            \t\tredisClusterFailOverTakeOverBtn.disabled = false;\n\t                $(\"#redisClusterFailOverTakeOverInfo\" + instanceId).html(\"<div class='alert alert-error' ><button class='close' data-dismiss='alert'>×</button><strong>Error!</strong>执行失败，请查找原因！</div>\");\n\t            }\n\t        }\n\t     );\n\t}\n\t\n\tfunction redisClusterDelNode(appId, instanceId){\n\t\tvar redisClusterDelNodeBtn = document.getElementById(\"redisClusterDelNodeBtn\" + instanceId);\n\t\tredisClusterDelNodeBtn.disabled = true;\n\t\t$.post(\n\t\t\t'/manage/app/clusterDelNode.json',\n\t\t\t{\n\t\t\t\tappId: appId,\n\t\t\t\tdelNodeInstanceId: instanceId,\n\t\t\t},\n\t        function(data){\n\t\t\t\tvar success = data.success;\n\t\t\t\tvar message = data.message;\n\t            if(success==1){\n\t                alert(\"执行成功!\");\n\t            \t\t$(\"#redisClusterDelNodeInfo\" + instanceId).html(\"<div class='alert alert-error' ><button class='close' data-dismiss='alert'>×</button><strong>Success!</strong>执行成功，应用的拓扑结构要1分钟之后生效，请耐心等待</div>\");\n\t                var targetId = \"#redisClusterDelNodeModal\" + instanceId;\n\t            \t\tsetTimeout(\"$('\" + targetId +\"').modal('hide');window.location.reload();\",1000);\n\t            }else{\n\t            \t    alert(message);\n\t            \t\tredisClusterDelNodeBtn.disabled = false;\n\t                $(\"#redisClusterDelNodeInfo\" + instanceId).html(\"<div class='alert alert-error' ><button class='close' data-dismiss='alert'>×</button><strong>Error!</strong>执行失败，请查找原因！</div>\");\n\t            }\n\t        }\n\t     );\n\t}\n\t\n\tfunction redisClusterAddSlave(appId, instanceId){\n\t\tvar slaveIp = document.getElementById(\"slaveIp\" + instanceId);\n\t\tif(slaveIp.value == \"\"){\n\t\t\talert(\"从节点Ip不能为空\");\n\t\t\tslaveIp.focus();\n\t\t\treturn false;\n\t\t}\n\t\tvar redisClusterAddSlaveBtn = document.getElementById(\"redisClusterAddSlaveBtn\" + instanceId);\n\t\tredisClusterAddSlaveBtn.disabled = true;\n\t\t$.post(\n\t\t\t'/manage/app/addSlave.do',\n\t\t\t{\n\t\t\t\tappId: appId,\n\t\t\t\tmasterInstanceId: instanceId,\n\t\t\t\tslaveHost: slaveIp.value\n\t\t\t},\n\t        function(data){\n\t            if(data==1){\n\t                alert(\"执行成功!\");\n\t            \t$(\"#redisClusterAddSlaveInfo\" + instanceId).html(\"<div class='alert alert-error' ><button class='close' data-dismiss='alert'>×</button><strong>Success!</strong>添加成功!</div>\");\n\t                var targetId = \"#redisClusterAddSlaveModal\" + instanceId;\n\t                setTimeout(\"$('\" + targetId +\"').modal('hide');window.location.reload();\",1000);\n\t            }else{\n\t            \tredisClusterAddSlaveBtn.disabled = false;\n\t                $(\"#redisClusterAddSlaveInfo\" + instanceId).html(\"<div class='alert alert-error' ><button class='close' data-dismiss='alert'>×</button><strong>Error!</strong>执行失败，请查找原因！</div>\");\n\t            }\n\t        }\n\t     );\n\t}\n\t\n\tfunction redisSentinelAddSlave(appId, instanceId){\n\t\tvar slaveIp = document.getElementById(\"sentinelSlaveIp\" + instanceId);\n\t\tif(slaveIp.value == \"\"){\n\t\t\talert(\"从节点Ip不能为空\");\n\t\t\tslaveIp.focus();\n\t\t\treturn false;\n\t\t}\n\t\tvar redisSentinelAddSlaveBtn = document.getElementById(\"redisSentinelAddSlaveBtn\" + instanceId);\n\t\tredisSentinelAddSlaveBtn.disabled = true;\n\t\t$.post(\n\t\t\t'/manage/app/addSlave.do',\n\t\t\t{\n\t\t\t\tappId: appId,\n\t\t\t\tmasterInstanceId: instanceId,\n\t\t\t\tslaveHost: slaveIp.value\n\t\t\t},\n\t        function(data){\n\t            if(data==1){\n\t                alert(\"执行成功!\");\n\t            \t$(\"#redisSentinelAddSlaveInfo\" + instanceId).html(\"<div class='alert alert-error' ><button class='close' data-dismiss='alert'>×</button><strong>Success!</strong>添加成功!</div>\");\n\t                var targetId = \"#redisSentinelAddSlaveModal\" + instanceId;\n\t                setTimeout(\"$('\" + targetId +\"').modal('hide');window.location.reload();\",1000);\n\t            }else{\n\t            \tredisSentinelAddSlaveBtn.disabled = false;\n\t                $(\"#redisSentinelAddSlaveInfo\" + instanceId).html(\"<div class='alert alert-error' ><button class='close' data-dismiss='alert'>×</button><strong>Error!</strong>执行失败，请查找原因！</div>\");\n\t            }\n\t        }\n\t     );\n\t}\n\t\n\t\n\tfunction redisSentinelFailOver(appId){\n\t\tvar redisSentinelFailOverBtn = document.getElementById(\"redisSentinelFailOverBtn\");\n\t\tredisSentinelFailOverBtn.disabled = true;\n\t\t$.post(\n\t\t\t'/manage/app/sentinelFailOver.do',\n\t\t\t{\n\t\t\t\tappId: appId\n\t\t\t},\n\t        function(data){\n\t            if(data==1){\n\t                alert(\"执行成功!\");\n\t            \t$(\"#redisSentinelFailOverInfo\").html(\"<div class='alert alert-error' ><button class='close' data-dismiss='alert'>×</button><strong>Success!</strong>执行成功，应用的拓扑结构要1分钟之后生效，请耐心等待</div>\");\n\t                var targetId = \"#redisSentinelFailOverModal\";\n\t            \tsetTimeout(\"$('\" + targetId +\"').modal('hide');window.location.reload();\",1000);\n\t            }else{\n\t            \tredisSentinelFailOverBtn.disabled = false;\n\t                $(\"#redisSentinelFailOverInfo\").html(\"<div class='alert alert-error' ><button class='close' data-dismiss='alert'>×</button><strong>Error!</strong>执行失败，请查找原因！</div>\");\n\t            }\n\t        }\n\t     );\n\t}\n\t\n\tfunction redisAddFailSlotsMaster(appId, instanceId){\n\t\tvar failSlotsMasterHost = document.getElementById(\"failSlotsMasterHost\" + instanceId);\n\t\tvar redisAddFailSlotsMasterBtn = document.getElementById(\"redisAddFailSlotsMasterBtn\" + instanceId);\n\t\tredisAddFailSlotsMasterBtn.disabled = true;\n\t\t$.post(\n\t\t\t'/manage/app/addFailSlotsMaster.do',\n\t\t\t{\n\t\t\t\tappId: appId,\n\t\t\t\tfailSlotsMasterHost: failSlotsMasterHost.value,\n\t\t\t\tinstanceId: instanceId\n\t\t\t},\n\t        function(data){\n\t            if(data==1 || data==2){\n\t            \tif (data == 1) {\n\t\t                alert(\"执行成功!\");\n\t            \t} else {\n\t\t                alert(\"集群所有slots已经分配，无需补充！\");\n\t            \t}\n\t            \t$(\"#redisAddFailSlotsMasterInfo\" + instanceId).html(\"<div class='alert alert-error' ><button class='close' data-dismiss='alert'>×</button><strong>Success!</strong>执行成功，应用的拓扑结构要1分钟之后生效，请耐心等待</div>\");\n\t                var targetId = \"#redisAddFailSlotsMasterModal\" + instanceId;\n\t            \tsetTimeout(\"$('\" + targetId +\"').modal('hide');window.location.reload();\",1000);\n\t            } else{\n\t            \tredisAddFailSlotsMasterBtn.disabled = false;\n\t                $(\"#redisAddFailSlotsMasterInfo\" + instanceId).html(\"<div class='alert alert-error' ><button class='close' data-dismiss='alert'>×</button><strong>Error!</strong>执行失败，请查找原因！</div>\");\n\t            }\n\t        }\n\t     );\n\t}\n\t\n\tfunction redisAddSentinel(appId){\n\t\tvar sentinelIp = document.getElementById(\"sentinelIp\");\n\t\tif(sentinelIp.value == \"\"){\n\t\t\talert(\"sentinel Ip不能为空\");\n\t\t\tslaveIp.focus();\n\t\t\treturn false;\n\t\t}\n\t\tvar redisAddSentinelBtn = document.getElementById(\"redisAddSentinelBtn\");\n\t\tredisAddSentinelBtn.disabled = true;\n\t\t$.post(\n\t\t\t'/manage/app/addSentinel.do',\n\t\t\t{\n\t\t\t\tappId: appId,\n\t\t\t\tsentinelHost: sentinelIp.value\n\t\t\t},\n\t        function(data){\n\t            if(data==1){\n\t                alert(\"执行成功!\");\n\t            \t$(\"#redisAddSentinelInfo\").html(\"<div class='alert alert-error' ><button class='close' data-dismiss='alert'>×</button><strong>Success!</strong>添加成功!</div>\");\n\t                var targetId = \"#redisAddSentinelModal\";\n\t                setTimeout(\"$('\" + targetId +\"').modal('hide');window.location.reload();\",1000);\n\t            }else{\n\t            \tredisAddSentinelBtn.disabled = false;\n\t                $(\"#redisAddSentinelInfo\").html(\"<div class='alert alert-error' ><button class='close' data-dismiss='alert'>×</button><strong>Error!</strong>执行失败，请查找原因！</div>\");\n\t            }\n\t        }\n\t     );\n\t}\n\t\n</script>\n<div class=\"row\">\n    <div class=\"page-header\">\n        <h4>\n        \t应用实例管理-${appDesc.name}(${appDesc.typeDesc})\n        \t<c:choose>\n\t            <c:when test=\"${appDesc.type == 2}\">\n\t            \t<c:if test=\"${lossSlotsSegmentMap != null && lossSlotsSegmentMap != '' && lossSlotsSegmentMap.size() > 0}\">\n\t            \t\t<font color=\"red\">丢失的slots:${lossSlotsSegmentMap}</font>\n\t            \t</c:if>\n\t            </c:when>\n\t  \t\t    <c:when test=\"${appDesc.type == 5}\">\n\t\t  \t\t    <button type=\"button\" class=\"btn btn-small btn-primary\" data-target=\"#redisAddSentinelModal\" data-toggle=\"modal\">添加sentinel节点</button>\n\t\t  \t\t    <button type=\"button\" class=\"btn btn-small btn-primary\" data-target=\"#redisSentinelFailOverModal\" data-toggle=\"modal\">&nbsp;FailOver&nbsp;</button>\n\t  \t\t    </c:when>\n           \t</c:choose>\n        </h4>\n    </div>\n    <div style=\"margin-top: 20px\">\n        <table class=\"table table-bordered table-striped table-hover\">\n            <thead>\n\t            <tr>\n\t                <th>ID</th>\n\t                <th>实例</th>\n\t                <th>实例状态</th>\n\t                <th>角色</th>\n\t                <th>主实例ID</th>\n\t                <th>内存使用</th>\n\t                <th>对象数</th>\n\t                <th>连接数</th>\n\t                <th>命中率</th>\n\t                <th>碎片率</th>\n\t                <th>日志</th>\n\t                <th>节点运维</th>\n\t                \t<th>故障转移</th>\n\t            </tr>\n            </thead>\n            <tbody>\n\t            <c:forEach var=\"instance\" items=\"${instanceList}\" varStatus=\"status\">\n\t            \t<c:set var=\"instanceStatsMapKey\" value=\"${instance.ip}:${instance.port}\"></c:set>\n\t                <tr>\n\t                    <td>\n\t                    \t <a href=\"/admin/instance/index.do?instanceId=${instance.id}\" target=\"_blank\">${instance.id}</a>\n\t                    </td>\n\t                    <td>${instance.ip}:${instance.port}</td>\n\t                    <td>${instance.statusDesc}</td>\n                        <td>${instance.roleDesc}</td>\n\t                    <c:choose>\n\t                        <c:when test=\"${instance.masterInstanceId >0}\">\n\t                            <td>\n\t                                <a href=\"/admin/instance/index.do?instanceId=${instance.masterInstanceId}\" target=\"_blank\">${instance.masterInstanceId}</a>\n\t                            </td>\n\t                        </c:when>\n\t                        <c:otherwise>\n                                <td></td>\n\t                        </c:otherwise>\n\t                    </c:choose>\n\t                    <td>\n                            <div class=\"progress margin-custom-bottom0\">\n                            \t<c:choose>\n                                \t<c:when test=\"${(instanceStatsMap[instanceStatsMapKey]).memUsePercent >= 80}\">\n\t\t\t\t\t\t\t\t\t\t<c:set var=\"progressBarStatus\" value=\"progress-bar-danger\"/>\n                                    </c:when>\n                                    <c:otherwise>\n                                    \t<c:set var=\"progressBarStatus\" value=\"progress-bar-success\"/>\n                                    </c:otherwise>\n                               </c:choose>\n                               <div class=\"progress-bar ${progressBarStatus}\"\n                                    role=\"progressbar\"\n                                    aria-valuenow=\"${(instanceStatsMap[instanceStatsMapKey]).memUsePercent}\"\n                                    aria-valuemax=\"100\"\n                                    aria-valuemin=\"0\"\n                                    style=\"width: ${(instanceStatsMap[instanceStatsMapKey]).memUsePercent}%\">\n                                    \n                                \t<label style=\"color: #000000\">\n\t                                \t<fmt:formatNumber value=\"${(instanceStatsMap[instanceStatsMapKey]).usedMemory / 1024 / 1024 / 1024}\" pattern=\"0.00\"/>G&nbsp;&nbsp;Used/<fmt:formatNumber value=\"${(instanceStatsMap[instanceStatsMapKey]).maxMemory / 1024 / 1024 / 1024}\" pattern=\"0.00\"/>G&nbsp;&nbsp;Total\n\t                            \t</label>\n                                </div>\n                            </div>\n\t                    </td>\n\t                    <td>\n\t                    ${(instanceStatsMap[instanceStatsMapKey]).currItems}\n\t                    </td>\n\t                    <td>${(instanceStatsMap[instanceStatsMapKey]).currConnections}</td>\n\t                    <td>${(instanceStatsMap[instanceStatsMapKey]).hitPercent}</td>\n\t                    <td>\n\t\t                  <c:set var=\"memFragmentationRatio\" value=\"${(instanceStatsMap[instanceStatsMapKey]).memFragmentationRatio}\"/>\n\t\t                  <c:choose>\n\t\t                \t\t<c:when test=\"${memFragmentationRatio > 5 && (instanceStatsMap[instanceStatsMapKey]).usedMemory > 1024 * 1024 * 100}\">\n\t\t                \t\t\t  <c:set var=\"memFragmentationRatioLabel\" value=\"label-danger\"/>\n\t\t                \t\t</c:when>\n\t\t                \t\t<c:when test=\"${memFragmentationRatio >= 3 && memFragmentationRatio < 5 && (instanceStatsMap[instanceStatsMapKey]).usedMemory > 1024 * 1024 * 100}\">\n\t\t                \t\t\t  <c:set var=\"memFragmentationRatioLabel\" value=\"label-warning\"/>\n\t\t                \t\t</c:when>\n\t\t                \t\t<c:otherwise>\n\t\t                \t\t\t  <c:set var=\"memFragmentationRatioLabel\" value=\"label-success\"/>\n\t\t                 \t\t</c:otherwise>\n\t\t                  </c:choose>\n\t\t                  <label class=\"label ${memFragmentationRatioLabel}\">${memFragmentationRatio}</label>\n\t                    </td>\n\t                    <td>\n\t                    \t<a target=\"_blank\" href=\"/manage/instance/log?instanceId=${instance.id}\">查看</a>\n\t                    </td>\n\t                    <td>\n\t                    \t<div>\n                                <c:choose>\n                                   <c:when test=\"${instance.status ==2}\">\n                                     <button type=\"button\" class=\"btn btn-small btn-success\" onclick=\"startInstance('${appDesc.appId}','${instance.id}')\">\n                                        \t&nbsp;启动实例&nbsp;\n                                     </button>\n                                   </c:when>\n                                    <c:when test=\"${instance.status ==0}\">\n                                        <button type=\"button\" class=\"btn btn-small btn-success\" onclick=\"startInstance('${appDesc.appId}','${instance.id}')\">\n                                            \t&nbsp;启动实例&nbsp;\n                                        </button>\n                                        <br/><br/>\n                                        <button type=\"button\" class=\"btn btn-small btn-danger\" onclick=\"shutdownInstance('${appDesc.appId}','${instance.id}')\">\n                                            \t&nbsp;下线实例&nbsp;\n                                        </button>\n                                        <c:choose>\n\t\t                                   <c:when test=\"${instance.masterInstanceId == 0 && appDesc.type == 2 && lossSlotsSegmentMap[instanceStatsMapKey] != null && lossSlotsSegmentMap[instanceStatsMapKey] != ''}\">\n\t\t                                      <button type=\"button\" class=\"btn btn-small btn-primary\" data-target=\"#redisAddFailSlotsMasterModal${instance.id}\" data-toggle=\"modal\">修复slot丢失数据</button>\n\t\t                                   </c:when>\n\t\t                                </c:choose>\n                                    </c:when>\n                                   <c:when test=\"${instance.status == 1}\">\n                                   \t  <button type=\"button\" class=\"btn btn-small btn-danger\" onclick=\"shutdownInstance('${appDesc.appId}', '${instance.id}')\">\n\t                                        &nbsp;下线实例&nbsp;\n\t                                   </button>\n\t                                   \n                                       <c:if test=\"${instance.masterInstanceId == 0 and instance.type != 5}\">\n                                       \t  <br/><br/>\n                                           <button type=\"button\" class=\"btn btn-small btn-primary\" data-target=\"#redisClusterAddSlaveModal${instance.id}\" data-toggle=\"modal\">添加Slave</button>\n                                       </c:if>\n                                       \n                                       \n                                       \n                                   </c:when>\n                                </c:choose>\n\t                    \t</div>\n\t                    </td>\n\t                    <td>\n\t                    \t\t<div>\n                                <c:choose>\n                                   <c:when test=\"${instance.status == 1}\">\n                                       <c:if test=\"${instance.masterInstanceId > 0 and instance.type == 2}\">\n                                           <button type=\"button\" class=\"btn btn-small btn-success\" data-target=\"#redisClusterFailOverManualModal${instance.id}\" data-toggle=\"modal\">&nbsp;&nbsp;Manual&nbsp;</button><br/><br/>\n                                           <button type=\"button\" class=\"btn btn-small btn-primary\" data-target=\"#redisClusterFailOverForceModal${instance.id}\" data-toggle=\"modal\">&nbsp;&nbsp;&nbsp;Force&nbsp;&nbsp;</button><br/><br/>\n                                           <button type=\"button\" class=\"btn btn-small btn-danger\" data-target=\"#redisClusterFailOverTakeOverModal${instance.id}\" data-toggle=\"modal\">TakeOver</button><br/>\n                                       </c:if>\n                                   </c:when>\n                                </c:choose>\n\t                    \t\t</div>\n\t                    </td>\n\t                </tr>\n\t            </c:forEach>\n            </tbody>\n        </table>\n    </div>\n</div>\n\n\n\n<div id=\"redisAddSentinelModal\" class=\"modal fade\" tabindex=\"-1\" data-width=\"400\">\n\t<div class=\"modal-dialog\">\n\t\t<div class=\"modal-content\">\n\t\n\t\t\t<div class=\"modal-header\">\n\t\t\t\t<button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\"></button>\n\t\t\t\t<h4 class=\"modal-title\">添加sentinel节点</h4>\n\t\t\t</div>\n\t\t\n\t\t\t<form class=\"form-horizontal form-bordered form-row-stripped\">\n\t\t\t\t<div class=\"modal-body\">\n\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t<!-- 控件开始 -->\n\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t<!-- form-body开始 -->\n\t\t\t\t\t\t\t<div class=\"form-body\">\n\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">sentinel节点Ip:</label>\n\t\t\t\t\t\t\t\t\t<div class=\"col-md-7\">\n\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"sentinelIp\" id=\"sentinelIp\" placeholder=\"sentinel节点Ip\" class=\"form-control\">\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<!-- form-body 结束 -->\n\t\t\t\t\t\t\t<div id=\"redisAddSentinelInfo\"></div>\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\n\t\t\t\t<div class=\"modal-footer\">\n\t\t\t\t\t<button type=\"button\" data-dismiss=\"modal\" class=\"btn\" >Close</button>\n\t\t\t\t\t<button type=\"button\" id=\"redisAddSentinelBtn\" class=\"btn red\" onclick=\"redisAddSentinel('${appDesc.appId}')\">Ok</button>\n\t\t\t\t</div>\n\t\t\t</form>\n\t\t</div>\n\t</div>\n</div>\n\n\n\n\n\n<div id=\"redisSentinelFailOverModal\" class=\"modal fade\" tabindex=\"-1\" data-width=\"400\">\n\t\t<div class=\"modal-dialog\">\n\t\t\t<div class=\"modal-content\">\n\t\t\t\t<div class=\"modal-header\">\n\t\t\t\t\t<button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\"></button>\n\t\t\t\t\t<h4 class=\"modal-title\">redis-Sentinel从节点FailOver操作</h4>\n\t\t\t\t</div>\n\t\t\t\t\n\t\t\t\t<div class=\"modal-body\">\n\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t<!-- 控件开始 -->\n\t\t\t\t\t\t<div class=\"container\">\n\t\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t\t<div>你确定执行failOver操作?</div>\n\t\t\t\t\t\t\t\t<div id=\"redisSentinelFailOverInfo\"></div>\n\t\t\t\t\t\t\t</div>\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\n\t\t\t\t<div class=\"modal-footer\">\n\t\t\t\t\t<button type=\"button\" data-dismiss=\"modal\" class=\"btn\" >Close</button>\n\t\t\t\t\t<button type=\"button\" id=\"redisSentinelFailOverBtn\" class=\"btn red\" onclick=\"redisSentinelFailOver('${appDesc.appId}')\">Ok</button>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\n\n<c:forEach var=\"instance\" items=\"${instanceList}\" varStatus=\"status\">\n\t<div id=\"redisClusterFailOverManualModal${instance.id}\" class=\"modal fade\" tabindex=\"-1\" data-width=\"400\">\n\t\t<div class=\"modal-dialog\">\n\t\t\t<div class=\"modal-content\">\n\t\t\t\t<div class=\"modal-header\">\n\t\t\t\t\t<button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\"></button>\n\t\t\t\t\t<h4 class=\"modal-title\">redis-Cluster从节点FailOver Manual操作</h4>\n\t\t\t\t</div>\n\t\t\t\t\n\t\t\t\t<div class=\"modal-body\">\n\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t<!-- 控件开始 -->\n\t\t\t\t\t\t<div class=\"container\">\n\t\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t\t<div>你确定对实例${instance.id}执行FailOver Manual操作?</div>\n\t\t\t\t\t\t\t\t<div id=\"redisClusterFailOverManualInfo${instance.id}\"></div>\n\t\t\t\t\t\t\t</div>\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\n\t\t\t\t<div class=\"modal-footer\">\n\t\t\t\t\t<button type=\"button\" data-dismiss=\"modal\" class=\"btn\" >Close</button>\n\t\t\t\t\t<button type=\"button\" id=\"redisClusterFailOverManualBtn${instance.id}\" class=\"btn red\" onclick=\"redisClusterFailOverManual('${appDesc.appId}', '${instance.id}')\">Ok</button>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t\n\t<div id=\"redisClusterFailOverForceModal${instance.id}\" class=\"modal fade\" tabindex=\"-1\" data-width=\"400\">\n\t\t<div class=\"modal-dialog\">\n\t\t\t<div class=\"modal-content\">\n\t\t\t\t<div class=\"modal-header\">\n\t\t\t\t\t<button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\"></button>\n\t\t\t\t\t<h4 class=\"modal-title\">redis-Cluster从节点FailOver Force操作</h4>\n\t\t\t\t</div>\n\t\t\t\t\n\t\t\t\t<div class=\"modal-body\">\n\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t<!-- 控件开始 -->\n\t\t\t\t\t\t<div class=\"container\">\n\t\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t\t<div>你确定对实例${instance.id}执行FailOver Force操作?</div>\n\t\t\t\t\t\t\t\t<div id=\"redisClusterFailOverForceInfo${instance.id}\"></div>\n\t\t\t\t\t\t\t</div>\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\n\t\t\t\t<div class=\"modal-footer\">\n\t\t\t\t\t<button type=\"button\" data-dismiss=\"modal\" class=\"btn\" >Close</button>\n\t\t\t\t\t<button type=\"button\" id=\"redisClusterFailOverForceBtn${instance.id}\" class=\"btn red\" onclick=\"redisClusterFailOverForce('${appDesc.appId}', '${instance.id}')\">Ok</button>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t\n\t\n\t<div id=\"redisClusterFailOverTakeOverModal${instance.id}\" class=\"modal fade\" tabindex=\"-1\" data-width=\"400\">\n\t\t<div class=\"modal-dialog\">\n\t\t\t<div class=\"modal-content\">\n\t\t\t\t<div class=\"modal-header\">\n\t\t\t\t\t<button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\"></button>\n\t\t\t\t\t<h4 class=\"modal-title\">redis-Cluster从节点FailOver TakeOver操作</h4>\n\t\t\t\t</div>\n\t\t\t\t\n\t\t\t\t<div class=\"modal-body\">\n\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t<!-- 控件开始 -->\n\t\t\t\t\t\t<div class=\"container\">\n\t\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t\t<div>你确定对实例${instance.id}执行FailOver TakeOver操作?</div>\n\t\t\t\t\t\t\t\t<div id=\"redisClusterFailOverTakeOverInfo${instance.id}\"></div>\n\t\t\t\t\t\t\t</div>\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\n\t\t\t\t<div class=\"modal-footer\">\n\t\t\t\t\t<button type=\"button\" data-dismiss=\"modal\" class=\"btn\" >Close</button>\n\t\t\t\t\t<button type=\"button\" id=\"redisClusterFailOverTakeOverBtn${instance.id}\" class=\"btn red\" onclick=\"redisClusterFailOverTakeOver('${appDesc.appId}', '${instance.id}')\">Ok</button>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t\n\t\n\t<div id=\"redisClusterDelNodeModal${instance.id}\" class=\"modal fade\" tabindex=\"-1\" data-width=\"400\">\n\t\t<div class=\"modal-dialog\">\n\t\t\t<div class=\"modal-content\">\n\t\t\t\t<div class=\"modal-header\">\n\t\t\t\t\t<button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\"></button>\n\t\t\t\t\t<h4 class=\"modal-title\">redis-Cluster节点删除操作</h4>\n\t\t\t\t</div>\n\t\t\t\t\n\t\t\t\t<div class=\"modal-body\">\n\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t<div class=\"container\">\n\t\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t\t<div>你确定对实例${instance.id}执行删除操作?</div>\n\t\t\t\t\t\t\t\t<div id=\"redisClusterDelNodeInfo${instance.id}\"></div>\n\t\t\t\t\t\t\t</div>\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\n\t\t\t\t<div class=\"modal-footer\">\n\t\t\t\t\t<button type=\"button\" data-dismiss=\"modal\" class=\"btn\" >Close</button>\n\t\t\t\t\t<button type=\"button\" id=\"redisClusterDelNodeBtn${instance.id}\" class=\"btn red\" onclick=\"redisClusterDelNode('${appDesc.appId}', '${instance.id}')\">Ok</button>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t\n\t<div id=\"redisClusterAddSlaveModal${instance.id}\" class=\"modal fade\" tabindex=\"-1\" data-width=\"400\">\n\t\t<div class=\"modal-dialog\">\n\t\t\t<div class=\"modal-content\">\n\t\t\n\t\t\t\t<div class=\"modal-header\">\n\t\t\t\t\t<button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\"></button>\n\t\t\t\t\t<h4 class=\"modal-title\">添加slave节点(主节点:${instance.id}, ${instance.ip}:${instance.port})</h4>\n\t\t\t\t</div>\n\t\t\t\n\t\t\t\t<form class=\"form-horizontal form-bordered form-row-stripped\">\n\t\t\t\t\t<div class=\"modal-body\">\n\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t<!-- 控件开始 -->\n\t\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t\t<!-- form-body开始 -->\n\t\t\t\t\t\t\t\t<div class=\"form-body\">\n\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">Slave节点Ip:</label>\n\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-7\">\n\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"slaveIp\" id=\"slaveIp${instance.id}\" placeholder=\"Slave节点Ip\" class=\"form-control\">\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<!-- form-body 结束 -->\n\t\t\t\t\t\t\t\t<div id=\"redisClusterAddSlaveInfo${instance.id}\"></div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t\n\t\t\t\t\t<div class=\"modal-footer\">\n\t\t\t\t\t\t<button type=\"button\" data-dismiss=\"modal\" class=\"btn\" >Close</button>\n\t\t\t\t\t\t<button type=\"button\" id=\"redisClusterAddSlaveBtn${instance.id}\" class=\"btn red\" onclick=\"redisClusterAddSlave('${appDesc.appId}', '${instance.id}')\">Ok</button>\n\t\t\t\t\t</div>\n\t\t\t\t</form>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t\n\t<div id=\"redisSentinelAddSlaveModal${instance.id}\" class=\"modal fade\" tabindex=\"-1\" data-width=\"400\">\n\t\t<div class=\"modal-dialog\">\n\t\t\t<div class=\"modal-content\">\n\t\t\n\t\t\t\t<div class=\"modal-header\">\n\t\t\t\t\t<button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\"></button>\n\t\t\t\t\t<h4 class=\"modal-title\">添加slave节点(主节点:${instance.id}, ${instance.ip}:${instance.port})</h4>\n\t\t\t\t</div>\n\t\t\t\n\t\t\t\t<form class=\"form-horizontal form-bordered form-row-stripped\">\n\t\t\t\t\t<div class=\"modal-body\">\n\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t<!-- 控件开始 -->\n\t\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t\t<!-- form-body开始 -->\n\t\t\t\t\t\t\t\t<div class=\"form-body\">\n\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">Slave节点Ip:</label>\n\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-7\">\n\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"sentinelSlaveIp\" id=\"sentinelSlaveIp${instance.id}\" placeholder=\"Slave节点Ip\" class=\"form-control\">\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<!-- form-body 结束 -->\n\t\t\t\t\t\t\t\t<div id=\"redisSentinelAddSlaveInfo${instance.id}\"></div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t\n\t\t\t\t\t<div class=\"modal-footer\">\n\t\t\t\t\t\t<button type=\"button\" data-dismiss=\"modal\" class=\"btn\" >Close</button>\n\t\t\t\t\t\t<button type=\"button\" id=\"redisSentinelAddSlaveBtn${instance.id}\" class=\"btn red\" onclick=\"redisSentinelAddSlave('${appDesc.appId}', '${instance.id}')\">Ok</button>\n\t\t\t\t\t</div>\n\t\t\t\t</form>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t\n\t<div id=\"redisAddFailSlotsMasterModal${instance.id}\" class=\"modal fade\" tabindex=\"-1\" data-width=\"400\">\n\t\t<div class=\"modal-dialog\">\n\t\t\t<div class=\"modal-content\">\n\t\t\n\t\t\t\t<div class=\"modal-header\">\n\t\t\t\t\t<button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\"></button>\n\t\t\t\t\t<h4 class=\"modal-title\">修复failslots</h4>\n\t\t\t\t</div>\n\t\t\t\n\t\t\t\t<form class=\"form-horizontal form-bordered form-row-stripped\">\n\t\t\t\t\t<div class=\"modal-body\">\n\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t<!-- 控件开始 -->\n\t\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t\t<!-- form-body开始 -->\n\t\t\t\t\t\t\t\t<div class=\"form-body\">\n\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">节点Ip:</label>\n\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-7\">\n\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"failSlotsMasterHost\" id=\"failSlotsMasterHost${instance.id}\" placeholder=\"failSlotsMasterHost\" class=\"form-control\">\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<!-- form-body 结束 -->\n\t\t\t\t\t\t\t\t<div id=\"redisAddFailSlotsMasterInfo${instance.id}\"></div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t\n\t\t\t\t\t<div class=\"modal-footer\">\n\t\t\t\t\t\t<button type=\"button\" data-dismiss=\"modal\" class=\"btn\" >Close</button>\n\t\t\t\t\t\t<button type=\"button\" id=\"redisAddFailSlotsMasterBtn${instance.id}\" class=\"btn red\" onclick=\"redisAddFailSlotsMaster('${appDesc.appId}', '${instance.id}')\">Ok</button>\n\t\t\t\t\t</div>\n\t\t\t\t</form>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t\n\t\n</c:forEach>\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/appOps/appMachine.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<div class=\"container\">\n    <div class=\"row\">\n   \t \t<div class=\"col-md-12 page-header\">\n            <h4>应用机器列表-${appDesc.name}(${appDesc.typeDesc})</h4>\n        </div>\n   \t\t<div class=\"col-md-12\">\n   \t\t\t<table class=\"table table-striped table-bordered table-hover\">\n\t\t\t\t<thead>\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t<th>ip</th>\n\t\t\t\t\t\t<th>内存使用率</th>\n\t\t\t\t\t\t<th>已分配内存</th>\n\t\t\t\t\t\t<th>CPU使用率</th>\n\t\t\t\t\t\t<th>网络流量</th>\n\t\t\t\t\t\t<th>机器负载</th>\n\t\t\t\t\t\t<th>最后统计时间</th>\n\t\t\t\t\t\t<th>是否虚机</th>\n\t\t\t\t\t\t<th>机房</th>\n\t\t\t\t\t</tr>\n\t\t\t\t</thead>\n\t\t\t\t<tbody>\n\t\t\t\t\t<c:forEach items=\"${appMachineList}\" var=\"machine\">\n\t\t\t\t\t\t<tr class=\"odd gradeX\">\n\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t<a target=\"_blank\" href=\"/manage/machine/machineInstances.do?ip=${machine.ip}\">${machine.ip}</a>\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t<span style=\"display:none\"><fmt:formatNumber value=\"${machine.memoryUsageRatio / 100}\" pattern=\"0.00\"/></span>\n                                <div class=\"progress margin-custom-bottom0\">\n                                    <fmt:formatNumber var=\"fmtMemoryUsageRatio\" value=\"${machine.memoryUsageRatio}\" pattern=\"0.00\"/>\n                                    <c:choose>\n                                        <c:when test=\"${fmtMemoryUsageRatio >= 80.00}\">\n\t\t                                    <div class=\"progress-bar progress-bar-danger\"\n\t\t                                                 role=\"progressbar\" aria-valuenow=\"${machine.memoryUsageRatio}\" aria-valuemax=\"100\"\n\t\t                                                 aria-valuemin=\"0\" style=\"width: ${machine.memoryUsageRatio}%\">\n\t\t                                    \t<label style=\"color: #000000\">\n\t\t\t                                        <fmt:formatNumber value=\"${((machine.memoryTotal-machine.memoryFree)/1024/1024/1024)}\" pattern=\"0.00\"/>G&nbsp;&nbsp;Used/<fmt:formatNumber value=\"${ machine.memoryTotal/1024/1024/1024}\" pattern=\"0.00\"/>G&nbsp;&nbsp;Total\n\t\t\t                                    </label>\n\t\t                                    </div>\n                                        </c:when>\n                                        <c:otherwise>\n\t\t                                    <div class=\"progress-bar progress-bar-success\"\n\t\t                                                     role=\"progressbar\" aria-valuenow=\"${machine.memoryUsageRatio}\" aria-valuemax=\"100\"\n\t\t                                                     aria-valuemin=\"0\" style=\"width: ${machine.memoryUsageRatio}%\">\n\t\t\t                                    <label style=\"color: #000000\">\n\t\t\t                                        <fmt:formatNumber value=\"${((machine.memoryTotal-machine.memoryFree)/1024/1024/1024)}\" pattern=\"0.00\"/>G&nbsp;&nbsp;Used/<fmt:formatNumber value=\"${ machine.memoryTotal/1024/1024/1024}\" pattern=\"0.00\"/>G&nbsp;&nbsp;Total\n\t\t\t                                    </label>\n\t\t                                    </div>\n                                        </c:otherwise>\n                                    </c:choose>\n                                  </div>\n\t\t\t\t\t\t\t</td>\n\t                        <td>\n\t                            <fmt:formatNumber var=\"fmtMemoryAllocatedRatio\" value=\"${((machine.memoryAllocated)/1024)*100.0/(machine.memoryTotal/1024/1024/1024)}\" pattern=\"0.00\"/>\n\t                        \t<span  style=\"display:none\"><fmt:formatNumber value=\"${fmtMemoryAllocatedRatio / 100}\" pattern=\"0.00\"/></span>\n\t                            <div class=\"progress margin-custom-bottom0\">\n\t                                <c:choose>\n\t\t                                <c:when test=\"${fmtMemoryAllocatedRatio >= 80.00}\">\n\t\t\t                                <div class=\"progress-bar progress-bar-danger\"\n\t\t\t                                     role=\"progressbar\" aria-valuenow=\"${fmtMemoryAllocatedRatio}\" aria-valuemax=\"100\"\n\t\t\t                                     aria-valuemin=\"0\" style=\"width: ${fmtMemoryAllocatedRatio}%\">\n\t\t\t                                     <label style=\"color: #000000\">\n\t\t\t                                        <fmt:formatNumber value=\"${((machine.memoryAllocated)/1024)}\" pattern=\"0.00\"/>G&nbsp;&nbsp;Used/<fmt:formatNumber value=\"${ machine.memoryTotal/1024/1024/1024}\" pattern=\"0.00\"/>G&nbsp;&nbsp;Total\n\t\t\t                                     </label>\n\t\t\t                                </div>\n\t                                    </c:when>\n\t                                    <c:otherwise>\n\t                                    \t<div class=\"progress-bar progress-bar-success\"\n\t                                         role=\"progressbar\" aria-valuenow=\"${fmtMemoryAllocatedRatio}\" aria-valuemax=\"100\"\n\t                                         aria-valuemin=\"0\" style=\"width: ${fmtMemoryAllocatedRatio}%\">\n\t                                         \t <label style=\"color: #000000\">\n\t\t\t                                        <fmt:formatNumber value=\"${((machine.memoryAllocated)/1024)}\" pattern=\"0.00\"/>G&nbsp;&nbsp;Used/<fmt:formatNumber value=\"${ machine.memoryTotal/1024/1024/1024}\" pattern=\"0.00\"/>G&nbsp;&nbsp;Total\n\t\t\t                                     </label>\n\t                                         </div>\t\t\n\t                                    </c:otherwise>\n\t                                </c:choose>\n                                    \n\t                             </div>\n\t                        </td>\n\t\t\t\t\t\t\t<td>${machine.cpuUsage}</td>\n\t\t\t\t\t\t\t<td>${machine.traffic}</td>\n\t\t\t\t\t\t\t<td>${machine.load}</td>\n\t\t\t\t\t\t\t<td><fmt:formatDate value=\"${machine.modifyTime}\" type=\"time\" timeStyle=\"full\" pattern=\"yyyy-MM-dd HH:mm\"/></td>\n                            <td>\n                            \t<c:choose>\n                            \t\t<c:when test=\"${machine.info.virtual == 1}\">\n                            \t\t\t是\n                            \t\t\t<br/>\n                            \t\t\t物理机:${machine.info.realIp}\n                            \t\t</c:when>\n                            \t\t<c:otherwise>\n                            \t\t\t否\n                            \t\t</c:otherwise>\n                            \t</c:choose>\n                            </td>\n\t\t\t\t\t\t\t<td>${machine.info.room}</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t</c:forEach>\n\t\t\t\t</tbody>\n\t\t\t</table>\n\t\t</div>\n\t </div>\n    <br/><br/><br/>\n    <br/><br/><br/>\n</div>\n\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/appOps/appOpsIndex.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\" %>\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <title>CacheCloud应用运维</title>\n    <jsp:include page=\"/WEB-INF/include/head.jsp\"/>\n    <script type=\"text/javascript\" src=\"/resources/js/jquery-console.js\"></script>\n\n</head>\n<body role=\"document\">\n<div class=\"container\">\n    <jsp:include page=\"/WEB-INF/include/headAdmin.jsp\"/>\n    <div class=\"tabbable-custom\">\n        <ul class=\"nav nav-tabs\" id=\"app_tabs\">\n            <li class=\"active\"><a href=\"#app_ops_instance\" data-url=\"/manage/app/instance.do?appId=${appId}\" data-toggle=\"tab\">应用实例</a></li>\n            <li><a href=\"#app_ops_machine\" data-url=\"/manage/app/machine.do?appId=${appId}\" data-toggle=\"tab\">应用机器列表</a></li>\n            <li><a href=\"#app_ops_detail\" data-url=\"/manage/app/detail.do?appId=${appId}\" data-toggle=\"tab\">应用详情和审批列表</a></li>\n        </ul>\n        <div class=\"tab-content\">\n            <div class=\"tab-pane active\" id=\"app_ops_instance\">\n            </div>\n            <div class=\"tab-pane\" id=\"app_ops_machine\">\n            </div>\n            <div class=\"tab-pane\" id=\"app_ops_detail\">\n            </div>\n        </div>\n    </div>\n</div>\n<jsp:include page=\"/WEB-INF/include/foot.jsp\"/>\n<script type=\"text/javascript\">\n    $('#app_tabs a').click(function (e) {\n        e.preventDefault();\n\n        var url = $(this).attr(\"data-url\");\n        var href = this.hash;\n        var pane = $(this);\n        var id = $(href).attr(\"id\");\n        // ajax load from data-url\n        $(href).load(url, function (result) {\n            pane.tab('show');\n        });\n    });\n\n    var tabTag = \"${tabTag}\";\n    if (tabTag.length > 0 && $('#' + tabTag).length > 0) {\n        var tabId = '#' + tabTag;\n        $(\"a[href=\" + tabId + \"]\").click();\n    } else {\n        $(\"a[href=#app_ops_instance]\").click();\n    }\n\n</script>\n<script type=\"text/javascript\" src=\"/resources/js/docs.min.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/client/exception/list.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\"\n    pageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n\t<title>CacheCloud管理后台</title>\n\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n\t\n\t<%@include file=\"/WEB-INF/jsp/manage/include/cache_cloud_main_css.jsp\" %>\n\n</head>\n\n<body class=\"page-header-fixed\">\n\t<%@include file=\"/WEB-INF/jsp/manage/include/head.jsp\" %>\n\n\t<%@include file=\"/WEB-INF/jsp/manage/include/left.jsp\" %>\n\n\t<%@include file=\"statList.jsp\" %>\n\t\n\t<%@include file=\"/WEB-INF/jsp/manage/include/foot.jsp\" %>\n\n\t<script src=\"/resources/manage/plugins/jquery-1.10.2.min.js\" type=\"text/javascript\"></script>\n\t<script src=\"/resources/manage/plugins/bootstrap/js/bootstrap.min.js\" type=\"text/javascript\"></script>\n\t<script src=\"/resources/manage/plugins/data-tables/jquery.dataTables.js\" type=\"text/javascript\"></script>\n\t<script src=\"/resources/manage/plugins/data-tables/DT_bootstrap.js\" type=\"text/javascript\"></script>\n\t<script src=\"/resources/manage/scripts/app.js\" type=\"text/javascript\"></script>\n\t     \n\t<script>\n\t\tjQuery(document).ready(function() {    \n\t\t   App.init(); // initlayout and core plugins\n\t\t   TableManaged.init();\n\t\t});\n\t\t\n\t</script>\n\t\n</body>\n</html>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/client/exception/statList.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\" pageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<div class=\"page-container\">\n\t<div class=\"page-content\">\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-md-12\">\n\t\t\t\t<h3 class=\"page-title\">\n\t\t\t\t\t近一个月客户端异常统计\n\t\t\t\t</h3>\n\t\t\t</div>\n\t\t</div>\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-md-12\">\n\t\t\t\t<div class=\"portlet box light-grey\">\n\t\t\t\t\t<div class=\"portlet-title\">\n\t\t\t\t\t\t<div class=\"caption\"><i class=\"fa fa-globe\"></i>客户端异常统计</div>\n\t\t\t\t\t\t<div class=\"tools\">\n\t\t\t\t\t\t\t<a href=\"javascript:;\" class=\"collapse\"></a>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"portlet-body\">\n                        <div class=\"table-toolbar\">\n                            <div class=\"btn-group\" style=\"float:right\">\n                                <form action=\"/manage/client/exception\" method=\"post\" class=\"form-horizontal form-bordered form-row-stripped\">\n                                    <label class=\"control-label\">\n                                        \t机器ip:\n                                    </label>\n                                    &nbsp;<input type=\"text\" name=\"ip\" id=\"ip\" value=\"${ip}\" placeholder=\"机器ip\"/>\n                                    &nbsp;<button type=\"submit\" class=\"btn blue btn-sm\">查询</button>\n                                </form>\n                            </div>\n                        </div>\n\t\t\t\t\t\t<table class=\"table table-striped table-bordered table-hover\" id=\"tableDataList\">\n\t\t\t\t\t\t\t<thead>\n\t\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t\t<th>应用id</th>\n\t\t\t\t\t\t\t\t\t<th>实例id</th>\n\t\t\t\t\t\t\t\t\t<th>实例ip</th>\n\t\t\t\t\t\t\t\t\t<th>实例port</th>\n\t\t\t\t\t\t\t\t\t<th>异常数</th>\n\t\t\t\t\t\t\t\t\t<th>应用负责人</th>\n\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t</thead>\n\t\t\t\t\t\t\t<tbody>\n\t\t\t\t\t\t\t\t<c:forEach items=\"${clientInstanceExceptionList}\" var=\"clientInstanceException\">\n\t\t\t\t\t\t\t\t\t<tr class=\"odd gradeX\">\n\t\t\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t\t\t<a target=\"_blank\" href=\"/admin/app/index.do?appId=${clientInstanceException.appId}\">${clientInstanceException.appId}</a>\n\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t\t\t<a href=\"/admin/instance/index.do?instanceId=${clientInstanceException.instanceId}\" target=\"_blank\">${clientInstanceException.instanceId}</a>\n\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t\t<td>${clientInstanceException.instanceHost}</td>\n\t\t\t\t\t\t\t\t\t\t<td>${clientInstanceException.instancePort}</td>\n\t\t\t\t\t\t\t\t\t\t<td>${clientInstanceException.exceptionCount}</td>\n\t\t\t\t\t\t\t\t\t\t<td>${appIdOwnerMap[clientInstanceException.appId]}</td>\n\t\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t\t</c:forEach>\n\t\t\t\t\t\t\t</tbody>\n\t\t\t\t\t\t</table>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/client/version/list.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\"\n    pageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n\t<title>CacheCloud管理后台</title>\n\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n\t\n\t<%@include file=\"/WEB-INF/jsp/manage/include/cache_cloud_main_css.jsp\" %>\n\n</head>\n\n<body class=\"page-header-fixed\">\n\t<%@include file=\"/WEB-INF/jsp/manage/include/head.jsp\" %>\n\n\t<%@include file=\"/WEB-INF/jsp/manage/include/left.jsp\" %>\n\n\t<%@include file=\"statList.jsp\" %>\n\t\n\t<%@include file=\"/WEB-INF/jsp/manage/include/foot.jsp\" %>\n\n\t<%@include file=\"/WEB-INF/jsp/manage/include/cache_cloud_main_js.jsp\" %>\n\t\n</body>\n</html>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/client/version/statList.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\" pageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<div class=\"page-container\">\n\t<div class=\"page-content\">\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-md-12\">\n\t\t\t\t<h3 class=\"page-title\">\n\t\t\t\t\t客户端版本统计\n\t\t\t\t</h3>\n\t\t\t</div>\n\t\t</div>\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-md-12\">\n\t\t\t\t<div class=\"portlet box light-grey\">\n\t\t\t\t\t<div class=\"portlet-title\">\n\t\t\t\t\t\t<div class=\"caption\"><i class=\"fa fa-globe\"></i>客户端版本统计</div>\n\t\t\t\t\t\t<div class=\"tools\">\n\t\t\t\t\t\t\t<a href=\"javascript:;\" class=\"collapse\"></a>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"portlet-body\">\n\t\t\t\t\t\t<div class=\"table-toolbar\">\n                            <div class=\"btn-group\" style=\"float:right\">\n                                <form action=\"/manage/client/version\" method=\"post\" class=\"form-horizontal form-bordered form-row-stripped\">\n                                    <label class=\"control-label\">\n                                        \t应用id:\n                                    </label>\n                                    &nbsp;<input type=\"text\" name=\"appId\" id=\"appId\" value=\"${appId}\" placeholder=\"应用id\"/>\n                                    &nbsp;<button type=\"submit\" class=\"btn blue btn-sm\">查询</button>\n                                </form>\n                            </div>\n                        </div>\n\t\t\t\t\t\t<table class=\"table table-striped table-bordered table-hover\" id=\"tableDataList\">\n\t\t\t\t\t\t\t<thead>\n\t\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t\t<th>应用id</th>\n\t\t\t\t\t\t\t\t\t<th>应用名</th>\n\t\t\t\t\t\t\t\t\t<th>客户端ip</th>\n\t\t\t\t\t\t\t\t\t<th>客户端版本</th>\n\t\t\t\t\t\t\t\t\t<th>上报时间</th>\n\t\t\t\t\t\t\t\t\t<th>应用负责人</th>\n\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t</thead>\n\t\t\t\t\t\t\t<tbody>\n\t\t\t\t\t\t\t\t<c:forEach items=\"${appClientVersionList}\" var=\"appClientVersion\">\n\t\t\t\t\t\t\t\t\t<tr class=\"odd gradeX\">\n\t\t\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t\t\t<a target=\"_blank\" href=\"/admin/app/index.do?appId=${appClientVersion.appId}\">${appClientVersion.appId}</a>\n\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t\t\t${appIdNameMap[appClientVersion.appId]}\n\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t\t<td>${appClientVersion.clientIp}</td>\n\t\t\t\t\t\t\t\t\t\t<td>${appClientVersion.clientVersion}</td>\n\t\t\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t\t\t<fmt:formatDate value=\"${appClientVersion.reportTime}\" type=\"time\" timeStyle=\"full\" pattern=\"yyyy-MM-dd HH:mm\"/></td>\n\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t\t<td>${appIdOwnerMap[appClientVersion.appId]}</td>\n\t\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t\t</c:forEach>\n\t\t\t\t\t\t\t</tbody>\n\t\t\t\t\t\t</table>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/commons/appConstants.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" import=\"com.sohu.cache.web.enums.AppOrderByEnum\" %>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n\n<c:set var=\"constant_hit_percentage_high_to_low\" value=\"<%=AppOrderByEnum.HIT_PERCENTAGE_HIGH_TO_LOW.getValue()%>\"/>\n<c:set var=\"constant_hit_percentage_low_to_high\" value=\"<%=AppOrderByEnum.HIT_PERCENTAGE_LOW_TO_HIGH.getValue()%>\"/>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/commons/taglibs.jsp",
    "content": "<%@ taglib prefix=\"fn\" uri=\"http://java.sun.com/jsp/jstl/functions\"%>\n<%@ taglib prefix=\"c\" uri=\"http://java.sun.com/jsp/jstl/core\"%>\n<%@ taglib prefix=\"fmt\" uri=\"http://java.sun.com/jsp/jstl/fmt\"%>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/config/init.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\"\n    pageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n\t<title>CacheCloud管理后台</title>\n\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n\t\n\t<%@include file=\"/WEB-INF/jsp/manage/include/cache_cloud_main_css.jsp\" %>\n\n</head>\n\n<body class=\"page-header-fixed\">\n\t<%@include file=\"/WEB-INF/jsp/manage/include/head.jsp\" %>\n\n\t<%@include file=\"/WEB-INF/jsp/manage/include/left.jsp\" %>\n\n\t<%@include file=\"initConfigDetail.jsp\" %>\n\t\n\t<%@include file=\"/WEB-INF/jsp/manage/include/foot.jsp\" %>\n\n\t<%@include file=\"/WEB-INF/jsp/manage/include/cache_cloud_main_js.jsp\" %>\n\t\n</body>\n</html>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/config/initConfigDetail.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\" pageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<div class=\"page-container\">\n\t<div class=\"page-content\">\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-md-12\">\n\t\t\t\t<h3 class=\"page-title\">\n\t\t\t\t\t配置修改 \n\t\t\t\t\t<c:choose>\n\t\t\t\t\t\t<c:when test=\"${success == 1}\">\n\t\t\t\t\t\t\t<font color=\"red\">更新成功</font>\n\t\t\t\t\t\t</c:when>\n\t\t\t\t\t\t<c:when test=\"${success == 0}\">\n\t\t\t\t\t\t\t<font color=\"red\">更新失败</font>\n\t\t\t\t\t\t</c:when>\n\t\t\t\t\t</c:choose>\n\t\t\t\t</h3>\n\t\t\t</div>\n\t\t</div>\n\t\t\n\t\t<div class=\"row\">\n\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t<div class=\"portlet box light-grey\">\n\t\t\t\t\t\t\t<div class=\"portlet-title\">\n\t\t\t\t\t\t\t\t<div class=\"caption\">\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-globe\"></i>\n\t\t\t\t\t\t\t\t\t填写配置:\n\t\t\t\t\t\t\t\t\t&nbsp;\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"tools\">\n\t\t\t\t\t\t\t\t\t<a href=\"javascript:;\" class=\"collapse\"></a>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t<div class=\"form\">\n\t\t\t\t\t\t\t\t\t<!-- BEGIN FORM-->\n\t\t\t\t\t\t\t\t\t<form action=\"/manage/config/update.do\" method=\"post\" class=\"form-horizontal form-bordered form-row-stripped\">\n\t\t\t\t\t\t\t\t\t\t<div class=\"form-body\">\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t<c:forEach items=\"${configList}\" var=\"config\" varStatus=\"stats\">\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t${config.info}<font color='red'>(*)</font>:\n\t\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<c:choose>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<c:when test=\"${config.configKey == 'cachecloud.whether.schedule.clean.data'}\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<select name=\"${config.configKey}\" class=\"form-control\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"false\" <c:if test=\"${config.configValue == 'false'}\">selected</c:if>>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t否\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"true\" <c:if test=\"${config.configValue == 'true'}\">selected</c:if>>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t是\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</c:when>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<c:when test=\"${config.configKey == 'cachecloud.user.login.type'}\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<select name=\"${config.configKey}\" class=\"form-control\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"1\" <c:if test=\"${config.configValue == '1'}\">selected</c:if>>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsession\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"2\" <c:if test=\"${config.configValue == '2'}\">selected</c:if>>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcookie\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</c:when>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<c:otherwise>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"${config.configKey}\" class=\"form-control\" value=\"${config.configValue}\" />\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</c:otherwise>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</c:choose>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</c:forEach>\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-actions fluid\">\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-offset-3 col-md-9\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<button type=\"submit\" class=\"btn green\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-check\"></i>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t确认修改\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</form>\n\t\t\t\t\t\t\t\t\t<!-- END FORM-->\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<!-- END TABLE PORTLET-->\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\n\t</div>\n</div>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/fault/list.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\"\n    pageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n\t<title>CacheCloud管理后台</title>\n\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n\t\n\t<%@include file=\"/WEB-INF/jsp/manage/include/cache_cloud_main_css.jsp\" %>\n\t\t\n</head>\n\n<body class=\"page-header-fixed\">\n\t<%@include file=\"/WEB-INF/jsp/manage/include/head.jsp\" %>\n\n\t<%@include file=\"/WEB-INF/jsp/manage/include/left.jsp\" %>\n\t\n\t<%@include file=\"memFaultList.jsp\" %>\n\t\n\t<%@include file=\"/WEB-INF/jsp/manage/include/foot.jsp\" %>\n\n\t<%@include file=\"/WEB-INF/jsp/manage/include/cache_cloud_main_js.jsp\" %>\n\t\n</body>\n</html>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/fault/memFaultList.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\" pageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<div class=\"page-container\">\n\t<div class=\"page-content\">\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-md-12\">\n\t\t\t\t<div class=\"portlet box light-grey\">\n\t\t\t\t\t<div class=\"portlet-title\">\n\t\t\t\t\t\t<div class=\"caption\"><i class=\"fa fa-globe\"></i>故障列表</div>\n\t\t\t\t\t\t<div class=\"tools\">\n\t\t\t\t\t\t\t<a href=\"javascript:;\" class=\"collapse\"></a>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"portlet-body\">\n\t\t\t\t\t\t<table class=\"table table-striped table-bordered table-hover\" id=\"tableDataList\">\n\t\t\t\t\t\t\t<thead>\n\t\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t\t<th>AppID</th>\n\t\t\t\t\t\t\t\t\t<th>名称</th>\n\t\t\t\t\t\t\t\t\t<th>IP</th>\n\t\t\t\t\t\t\t\t\t<th>PORT</th>\n\t\t\t\t\t\t\t\t\t<th>M/S</th>\n\t\t\t\t\t\t\t\t\t<th>Time</th>\n\t\t\t\t\t\t\t\t\t<th>联系人</th>\n\t\t\t\t\t\t\t\t\t<th>IsMemCloud</th>\n\t\t\t\t\t\t\t\t\t<th>IsRecover</th>\n\t\t\t\t\t\t\t\t\t<th>原因</th>\n\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t</thead>\n\t\t\t\t\t\t\t<tbody>\n\t\t\t\t\t\t\t\t<c:forEach items=\"${faults}\" var=\"item\">\n\t\t\t\t\t\t\t\t\t<tr class=\"odd gradeX\">\n\t\t\t\t\t\t\t\t\t\t<td>${item.appId}</td>\n\t\t\t\t\t\t\t\t\t\t<td>2</td>\n\t\t\t\t\t\t\t\t\t\t<td>${item.ip}</td>\n\t\t\t\t\t\t\t\t\t\t<td>${item.port}</td>\n\t\t\t\t\t\t\t\t\t\t<td>5</td>\n\t\t\t\t\t\t\t\t\t\t<td>${item.createTime}</td>\n\t\t\t\t\t\t\t\t\t\t<td>7</td>\n\t\t\t\t\t\t\t\t\t\t<td>${item.isMemcloud}</td>\n\t\t\t\t\t\t\t\t\t\t<td>7</td>\n\t\t\t\t\t\t\t\t\t\t<td>${item.reason}</td>\n\t\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t\t</c:forEach>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t</tbody>\n\t\t\t\t\t\t</table>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t<!-- END EXAMPLE TABLE PORTLET-->\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/include/cache_cloud_main_css.jsp",
    "content": "<link href=\"/resources/manage/plugins/font-awesome/css/font-awesome.min.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"/resources/manage/plugins/bootstrap/css/bootstrap.min.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"/resources/manage/css/style-metronic.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"/resources/manage/css/style.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"/resources/manage/css/style-responsive.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"/resources/manage/css/plugins.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"/resources/manage/css/themes/default.css\" rel=\"stylesheet\" type=\"text/css\" id=\"style_color\"/>\n<link href=\"/resources/manage/plugins/data-tables/DT_bootstrap.css\" rel=\"stylesheet\" type=\"text/css\"/>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/include/cache_cloud_main_js.jsp",
    "content": "<script src=\"/resources/manage/plugins/jquery-1.10.2.min.js\" type=\"text/javascript\"></script>\n<script src=\"/resources/manage/plugins/bootstrap/js/bootstrap.min.js\" type=\"text/javascript\"></script>\n<script src=\"/resources/manage/plugins/data-tables/jquery.dataTables.js\" type=\"text/javascript\"></script>\n<script src=\"/resources/manage/plugins/data-tables/DT_bootstrap.js\" type=\"text/javascript\"></script>\n<script src=\"/resources/manage/scripts/app.js\" type=\"text/javascript\"></script>\n<script src=\"/resources/manage/scripts/table-managed.js\" type=\"text/javascript\"></script>\n<script src=\"/resources/manage/manage/userManage.js\" type=\"text/javascript\"></script>     \n<script src=\"/resources/manage/manage/machineManage.js\" type=\"text/javascript\"></script>\n<script src=\"/resources/manage/manage/auditManage.js?<%=System.currentTimeMillis()%>\" type=\"text/javascript\"></script>\n     \n<script>\n\tjQuery(document).ready(function() {    \n\t   App.init(); // initlayout and core plugins\n\t   TableManaged.init();\n\t});\n\t\n</script>\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/include/foot.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\" pageEncoding=\"UTF-8\"%>\n<div class=\"footer\">\n\t<div class=\"footer-inner\">\n\t\t2014 &copy; CacheCloud.\n\t</div>\n\t<div class=\"footer-tools\">\n\t\t<span class=\"go-top\">\n\t\t<i class=\"fa fa-angle-up\"></i>\n\t\t</span>\n\t</div>\n</div>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/include/head.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\" pageEncoding=\"UTF-8\"%>\n<div class=\"header navbar navbar-inverse navbar-fixed-top\">\n\t<div class=\"header-inner\">\n\t\t<a class=\"navbar-brand\" href=\"/manage/total/list.do\">\n\t\t\t<img src=\"/resources/manage/img/logo_new.png\" alt=\"logo\" class=\"img-responsive\" />\n\t\t</a>\n\t\t\n\t\t<a href=\"javascript:;\" class=\"navbar-toggle\" data-toggle=\"collapse\" data-target=\".navbar-collapse\">\n\t\t\t<img src=\"/resources/manage/img/menu-toggler.png\" alt=\"\" />\n\t\t</a>\n\t\t\n\t\t<ul class=\"nav navbar-nav pull-right\">\n\t\t\t<li class=\"dropdown user\">\n\t\t\t\t<a href=\"#\" class=\"dropdown-toggle\" data-toggle=\"dropdown\" data-hover=\"dropdown\" data-close-others=\"true\">\n\t\t\t\t<span class=\"username\">${userInfo.chName}</span>\n\t\t\t\t<i class=\"fa fa-angle-down\"></i>\n\t\t\t\t</a>\n\t\t\t\t<ul class=\"dropdown-menu\">\n\t\t\t\t\t<li><a target=\"_blank\" href=\"/admin/app/list.do\"><i class=\"fa fa-user\"></i>应用前台页面</a></li>\n\t\t\t\t\t<li><a href=\"javascript;\" data-target=\"#addUserModal${userInfo.id}\" data-toggle=\"modal\"><i class=\"fa fa-user\"></i>修改资料</a></li>\n\t\t\t\t\t<li><a href=\"/manage/logout.do\"><i class=\"fa fa-user\"></i>注销</a></li>\n\t\t\t\t</ul>\n\t\t\t</li>\n\t\t</ul>\n\t</div>\n</div>\n<div class=\"clearfix\"></div>\n\n<c:set var=\"user\" value=\"${userInfo}\"/>\n<%@include file=\"../user/addUser.jsp\" %>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/include/left.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\" pageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<script src=\"/resources/manage/plugins/jquery-1.10.2.min.js\" type=\"text/javascript\"></script>\n<div id=\"leftMenu\" class=\"page-sidebar navbar-collapse collapse\">\n\t<ul class=\"page-sidebar-menu\">\n\t\t<li>\n\t\t\t<div class=\"sidebar-toggler hidden-phone\"></div>\n\t\t</li>\n\t\t\n\t\t<li <c:if test=\"${totalActive == 1}\">class=\"active\"</c:if>>\n\t\t\t<a href=\"/manage/total/list.do\">\n\t\t\t\t<i class=\"fa fa-map-marker\"></i> \n\t\t\t\t<span class=\"title\">全局统计</span>\n\t\t\t\t<c:if test=\"${totalActive == 1}\">\n\t\t\t\t\t<span class=\"selected\"></span>\n\t\t\t\t\t<span class=\"arrow\"></span>\n\t\t\t\t</c:if>\n\t\t\t</a>\n\t\t</li>\n\t\t\n\t\t<li <c:if test=\"${checkActive == 1}\">class=\"active\"</c:if>>\n\t\t\t<a href=\"/manage/app/auditList.do\">\n\t\t\t\t<i class=\"fa fa-map-marker\"></i> \n\t\t\t\t<span class=\"title\">流程审批</span>\n\t\t\t\t<c:if test=\"${checkActive == 1}\">\n\t\t\t\t\t<span class=\"selected\"></span>\n\t\t\t\t\t<span class=\"arrow\"></span>\n\t\t\t\t</c:if>\n\t\t\t</a>\n\t\t</li>\n\t\t<li <c:if test=\"${userActive == 1}\">class=\"active\"</c:if>>\n\t\t\t<a href=\"/manage/user/list.do\">\n\t\t\t\t<i class=\"fa fa-map-marker\"></i> \n\t\t\t\t<span class=\"title\">用户管理</span>\n\t\t\t\t<c:if test=\"${userActive == 1}\">\n\t\t\t\t\t<span class=\"selected\"></span>\n\t\t\t\t\t<span class=\"arrow\"></span>\n\t\t\t\t</c:if>\n\t\t\t</a>\n\t\t</li>\n\t\t<li <c:if test=\"${quartzActive == 1}\">class=\"active\"</c:if>>\n\t\t\t<a href=\"/manage/quartz/list.do\">\n\t\t\t\t<i class=\"fa fa-map-marker\"></i> \n\t\t\t\t<span class=\"title\">Quartz管理</span>\n\t\t\t\t<c:if test=\"${quartzActive == 1}\">\n\t\t\t\t\t<span class=\"selected\"></span>\n\t\t\t\t\t<span class=\"arrow\"></span>\n\t\t\t\t</c:if>\n\t\t\t</a>\n\t\t</li>\n\t\t<li <c:if test=\"${machineActive == 1}\">class=\"active\"</c:if>>\n\t\t\t<a href=\"/manage/machine/list.do\">\n\t\t\t\t<i class=\"fa fa-map-marker\"></i> \n\t\t\t\t<span class=\"title\">机器管理</span>\n\t\t\t\t<c:if test=\"${machineActive == 1}\">\n\t\t\t\t\t<span class=\"selected\"></span>\n\t\t\t\t\t<span class=\"arrow\"></span>\n\t\t\t\t</c:if>\n\t\t\t</a>\n\t\t</li>\n\t\t\n\t\t<li <c:if test=\"${clientExceptionActive == 1}\">class=\"active\"</c:if>>\n\t\t\t<a href=\"/manage/client/exception\">\n\t\t\t\t<i class=\"fa fa-map-marker\"></i> \n\t\t\t\t<span class=\"title\">客户端异常统计</span>\n\t\t\t\t<c:if test=\"${clientExceptionActive == 1}\">\n\t\t\t\t\t<span class=\"selected\"></span>\n\t\t\t\t\t<span class=\"arrow\"></span>\n\t\t\t\t</c:if>\n\t\t\t</a>\n\t\t</li>\n\t\t\n\t\t<li <c:if test=\"${clientVersionActive == 1}\">class=\"active\"</c:if>>\n\t\t\t<a href=\"/manage/client/version\">\n\t\t\t\t<i class=\"fa fa-map-marker\"></i> \n\t\t\t\t<span class=\"title\">客户端版本统计</span>\n\t\t\t\t<c:if test=\"${clientVersionActive == 1}\">\n\t\t\t\t\t<span class=\"selected\"></span>\n\t\t\t\t\t<span class=\"arrow\"></span>\n\t\t\t\t</c:if>\n\t\t\t</a>\n\t\t</li>\n\t\t\n\t\t<li <c:if test=\"${noticeActive == 1}\">class=\"active\"</c:if>>\n\t\t\t<a href=\"/manage/notice/initNotice.do\">\n\t\t\t\t<i class=\"fa fa-map-marker\"></i> \n\t\t\t\t<span class=\"title\">系统通知</span>\n\t\t\t\t<c:if test=\"${noticeActive == 1}\">\n\t\t\t\t\t<span class=\"selected\"></span>\n\t\t\t\t\t<span class=\"arrow\"></span>\n\t\t\t\t</c:if>\n\t\t\t</a>\n\t\t</li>\n\t\t\n\t\t<li <c:if test=\"${redisConfigActive == 1}\">class=\"active\"</c:if>>\n\t\t\t<a href=\"/manage/redisConfig/init.do\">\n\t\t\t\t<i class=\"fa fa-map-marker\"></i> \n\t\t\t\t<span class=\"title\">Redis配置模板管理</span>\n\t\t\t\t<c:if test=\"${redisConfigActive == 1}\">\n\t\t\t\t\t<span class=\"selected\"></span>\n\t\t\t\t\t<span class=\"arrow\"></span>\n\t\t\t\t</c:if>\n\t\t\t</a>\n\t\t</li>\n\t\t\n\t\t<li <c:if test=\"${instanceAlertValueActive == 1}\">class=\"active\"</c:if>>\n\t\t\t<a href=\"/manage/instanceAlert/init.do\">\n\t\t\t\t<i class=\"fa fa-map-marker\"></i> \n\t\t\t\t<span class=\"title\">Redis报警阀值</span>\n\t\t\t\t<c:if test=\"${instanceAlertValueActive == 1}\">\n\t\t\t\t\t<span class=\"selected\"></span>\n\t\t\t\t\t<span class=\"arrow\"></span>\n\t\t\t\t</c:if>\n\t\t\t</a>\n\t\t</li>\n\t\t\n\t\t<li <c:if test=\"${configActive == 1}\">class=\"active\"</c:if>>\n\t\t\t<a href=\"/manage/config/init.do\">\n\t\t\t\t<i class=\"fa fa-map-marker\"></i> \n\t\t\t\t<span class=\"title\">系统配置管理</span>\n\t\t\t\t<c:if test=\"${configActive == 1}\">\n\t\t\t\t\t<span class=\"selected\"></span>\n\t\t\t\t\t<span class=\"arrow\"></span>\n\t\t\t\t</c:if>\n\t\t\t</a>\n\t\t</li>\n\t\t\n\t</ul>\n</div>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/instance/log.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n\t<title>Redis日志</title>\n</head>\n\t<body STYLE=\"BACKGROUND-COLOR:#000;color:#FFF\">\n\t\t<c:forEach items=\"${instanceLogList}\" var=\"line\">\n\t\t\t<c:set var=\"targetColor\" value=\"white\"></c:set>\n\t\t\t<c:if test='${fn:indexOf(line,\"#\") > 0}'>\n\t\t\t\t<c:set var=\"targetColor\" value=\"red\"></c:set>\n\t\t\t</c:if>\n\t\t\t<font color=\"${targetColor}\">${line}</font><br/>\n\t\t</c:forEach>\n\t</body>\n</html>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/instanceAlert/init.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\"\n    pageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n\t<title>CacheCloud管理后台</title>\n\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n\t\n\t<%@include file=\"/WEB-INF/jsp/manage/include/cache_cloud_main_css.jsp\" %>\n\n</head>\n\n<body class=\"page-header-fixed\">\n\t<%@include file=\"/WEB-INF/jsp/manage/include/head.jsp\" %>\n\n\t<%@include file=\"/WEB-INF/jsp/manage/include/left.jsp\" %>\n\n\t<%@include file=\"initConfigDetail.jsp\" %>\n\t\n\t<%@include file=\"/WEB-INF/jsp/manage/include/foot.jsp\" %>\n\n\t<%@include file=\"/WEB-INF/jsp/manage/include/cache_cloud_main_js.jsp\" %>\n\t\n</body>\n</html>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/instanceAlert/initConfigDetail.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\" pageEncoding=\"UTF-8\"%>\n<%@page import=\"com.sohu.cache.redis.enums.RedisAlertConfigEnum\"%>\n<%@page import=\"com.sohu.cache.redis.enums.InstanceAlertCompareTypeEnum\"%>\n<%@page import=\"com.sohu.cache.redis.enums.InstanceAlertCheckCycleEnum\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n\n<script type=\"text/javascript\">\n\n//查看实例是否存在\nfunction checkInstanceExist(){\n\tvar instanceHostPort = document.getElementById(\"instanceHostPort\").value;\n\tif(instanceHostPort != ''){\n\t\t$.post(\n\t\t\t'/manage/instanceAlert/checkInstanceHostPort.json',\n\t\t\t{\n\t\t\t\tinstanceHostPort: instanceHostPort,\n\t\t\t},\n\t        function(data){\n\t\t\t\tvar success = data.status;\n\t            if(success==0){\n\t            \t\talert(data.message);\n\t            \t\tdocument.getElementById(\"instanceHostPort\").focus();\n\t            }\n\t        }\n\t     );\n\t}\n}\n\nfunction removeAlertConfig(id) {\n\t$.get(\n\t\t'/manage/instanceAlert/remove.json',\n\t\t{\n\t\t\tid: id\n\t\t},\n        function(data){\n\t\t\tvar status = data.status;\n\t\t\tif (status == 1) {\n           \t\talert(\"删除成功!\");\n\t\t\t} else {\n           \t\talert(\"删除失败, msg: \" + result.message);\n\t\t\t}\n               window.location.reload();\n        }\n     );\n}\n\nfunction changeAlertConfig(id) {\n\tvar alertValue = document.getElementById(\"alertValue\" + id);\n\tvar checkCycle = document.getElementById(\"checkCycle\" + id);\n\t$.get(\n\t\t'/manage/instanceAlert/update.json',\n\t\t{\n\t\t\tid: id,\n\t\t\talertValue: alertValue.value,\n\t\t\tcheckCycle: checkCycle.value\n\t\t},\n        function(data){\n\t\t\tvar status = data.status;\n\t\t\tif (status == 1) {\n\t\t\t\talert(\"修改成功！\");\n                window.location.reload();\n\t\t\t} else {\n\t\t\t\talert(\"修改失败！\" + data.message);\n\t\t\t}\n\t\t\t\n        }\n     );\n}\n\nfunction saveInstanceAlertConfig() {\n\tvar alertConfig = document.getElementById(\"alertConfig\");\n\tvar alertValue = document.getElementById(\"alertValue\");\n\tif (alertValue.value == \"\"){\n\t\talert(\"请填写阈值\");\n\t\talertValue.focus();\n\t\treturn false;\n\t}\n\tvar compareType = document.getElementById(\"compareType\");\n\tvar checkCycle = document.getElementById(\"checkCycle\");\n\tvar instanceHostPort = document.getElementById(\"instanceHostPort\");\n\tvar type = 1;\n\tif (instanceHostPort.value != null && instanceHostPort.value != '') {\n\t\ttype = 2;\n\t}\n\t$.get(\n\t\t'/manage/instanceAlert/add.json',\n\t\t{\n\t\t\talertConfig: alertConfig.value,\n\t\t\talertValue: alertValue.value,\n\t\t\tcompareType: compareType.value,\n\t\t\tcheckCycle: checkCycle.value,\n\t\t\tinstanceHostPort: instanceHostPort.value,\n\t\t\ttype: type\n\t\t},\n        function(data){\n\t\t\tvar status = data.status;\n\t\t\tif (status == 1) {\n\t\t\t\talert(\"添加成功！\");\n\t\t\t} else {\n\t\t\t\talert(\"添加失败！\" + data.message);\n\t\t\t}\n            window.location.reload();\n        }\n     );\n}\n</script>\n\n<div class=\"page-container\">\n\t<div class=\"page-content\">\n\t\t<div class=\"table-toolbar\">\n\t\t\t<div class=\"btn-group\">\n\t\t\t\t<button id=\"sample_editable_1_new\" class=\"btn green\" data-target=\"#addInstanceAlertModal\" data-toggle=\"modal\">\n\t\t\t\t添加新实例报警项 <i class=\"fa fa-plus\"></i>\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t</div>\n\t\t\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-md-12\">\n\t\t\t\t<div class=\"portlet box light-grey\">\n\t\t\t\t\t\t<div class=\"portlet-title\">\n\t\t\t\t\t\t\t<div class=\"caption\">\n\t\t\t\t\t\t\t\t<i class=\"fa fa-globe\"></i>\n\t\t\t\t\t\t\t\t全局实例报警项:\n\t\t\t\t\t\t\t\t&nbsp;\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div class=\"tools\">\n\t\t\t\t\t\t\t\t<a href=\"javascript:;\" class=\"collapse\"></a>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\n\t\t\t\t\t\t<div class=\"portlet-body\">\n\t                        <div class=\"table-toolbar\">\n\t\t\t\t\t\t\t\t<table class=\"table table-striped table-bordered table-hover\" id=\"tableDataList\">\n\t\t\t\t\t\t\t\t\t<thead>\n\t\t\t\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t\t\t\t<th>id</th>\n\t\t\t\t\t\t\t\t\t\t\t<th>配置名</th>\n\t\t\t\t\t\t\t\t\t\t\t<th>配置说明</th>\n\t\t\t\t\t\t\t\t\t\t\t<th>关系</th>\n\t\t\t\t\t\t\t\t\t\t\t<th>阀值</th>\n\t\t\t\t\t\t\t\t\t\t\t<th>周期</th>\n\t\t\t\t\t\t\t\t\t\t\t<th>最近检测时间</th>\n\t\t\t\t\t\t\t\t\t\t\t<th>操作</th>\n\t\t\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t\t\t</thead>\n\t\t\t\t\t\t\t\t\t<tbody>\n\t\t\t\t\t\t\t\t\t\t<c:forEach items=\"${instanceAlertAllList}\" var=\"config\">\n\t\t\t\t\t\t\t\t\t\t\t<tr class=\"odd gradeX\">\n\t\t\t\t\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t\t\t\t\t${config.id}\n\t\t\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t\t\t\t\t${config.alertConfig}\n\t\t\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t\t\t\t\t${config.configInfo}\n\t\t\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<c:forEach items=\"${instanceAlertCompareTypeEnumList}\" var=\"instanceAlertCompareTypeEnum\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<c:if test=\"${config.compareType == instanceAlertCompareTypeEnum.value}\">${instanceAlertCompareTypeEnum.info}</c:if>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</c:forEach>\n\t\t\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t\t\t\t\t${config.alertValue}\n\t\t\t\t\t\t\t\t\t\t\t\t</td>\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<c:forEach items=\"${instanceAlertCheckCycleEnumList}\" var=\"instanceAlertCheckCycleEnum\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<c:if test=\"${config.checkCycle == instanceAlertCheckCycleEnum.value}\">${instanceAlertCheckCycleEnum.info}</c:if>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</c:forEach>\n\t\t\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t\t\t\t<td>\n\t\t                    \t\t\t\t\t\t\t<fmt:formatDate value=\"${config.lastCheckTime}\" pattern=\"yyyy-MM-dd HH:mm:ss\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<button type=\"button\" class=\"btn btn-info\" data-target=\"#changeInstanceAlertModal${config.id}\" data-toggle=\"modal\" href=\"#\">修改</button>\n\t\t\t                    \t\t\t\t\t\t<button type=\"button\" class=\"btn btn-info\" onclick=\"if(window.confirm('确认要清除id=${config.id}的配置?!')){removeAlertConfig('${config.id}');return true;}else{return false;}\">删除</button>\n\t\t\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t\t\t\t</c:forEach>\n\t\t\t\t\t\t\t\t\t</tbody>\n\t\t\t\t\t\t\t\t</table>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<!-- END TABLE PORTLET-->\n\t\t\t</div>\n\t\t</div>\n\t\t\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-md-12\">\n\t\t\t\t<div class=\"portlet box light-grey\">\n\t\t\t\t\t\t<div class=\"portlet-title\">\n\t\t\t\t\t\t\t<div class=\"caption\">\n\t\t\t\t\t\t\t\t<i class=\"fa fa-globe\"></i>\n\t\t\t\t\t\t\t\t特殊实例报警:\n\t\t\t\t\t\t\t\t&nbsp;\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div class=\"tools\">\n\t\t\t\t\t\t\t\t<a href=\"javascript:;\" class=\"collapse\"></a>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\n\t\t\t\t\t\t<div class=\"portlet-body\">\n\t                        <div class=\"table-toolbar\">\n\t\t\t\t\t\t\t\t<table class=\"table table-striped table-bordered table-hover\" id=\"tableDataList\">\n\t\t\t\t\t\t\t\t\t<thead>\n\t\t\t\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t\t\t\t<th>id</th>\n\t\t\t\t\t\t\t\t\t\t\t<th>实例信息</th>\n\t\t\t\t\t\t\t\t\t\t\t<th>配置名</th>\n\t\t\t\t\t\t\t\t\t\t\t<th>配置说明</th>\n\t\t\t\t\t\t\t\t\t\t\t<th>关系</th>\n\t\t\t\t\t\t\t\t\t\t\t<th>阀值</th>\n\t\t\t\t\t\t\t\t\t\t\t<th>周期</th>\n\t\t\t\t\t\t\t\t\t\t\t<th>最近检测时间</th>\n\t\t\t\t\t\t\t\t\t\t\t<th>操作</th>\n\t\t\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t\t\t</thead>\n\t\t\t\t\t\t\t\t\t<tbody>\n\t\t\t\t\t\t\t\t\t\t<c:forEach items=\"${instanceAlertSpecialList}\" var=\"config\">\n\t\t\t\t\t\t\t\t\t\t\t<tr class=\"odd gradeX\">\n\t\t\t\t\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t\t\t\t\t${config.id}\n\t\t\t\t\t\t\t\t\t\t\t\t</td>\n\t\t                \t\t\t\t\t\t\t<c:set var=\"instanceId\" value=\"${config.instanceId}\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t\t\t\t\t${config.instanceInfo.hostPort}\n\t\t\t\t\t\t\t\t\t\t\t\t\t<a target=\"_blank\" href=\"/admin/app/index.do?appId=${config.instanceInfo.appId}\">(${config.instanceInfo.appId})</a>\n\t\t\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t\t\t\t\t${config.alertConfig}\n\t\t\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t\t\t\t\t${config.configInfo}\n\t\t\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<c:forEach items=\"${instanceAlertCompareTypeEnumList}\" var=\"instanceAlertCompareTypeEnum\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<c:if test=\"${config.compareType == instanceAlertCompareTypeEnum.value}\">${instanceAlertCompareTypeEnum.info}</c:if>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</c:forEach>\n\t\t\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t\t\t\t\t${config.alertValue}\n\t\t\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<c:forEach items=\"${instanceAlertCheckCycleEnumList}\" var=\"instanceAlertCheckCycleEnum\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<c:if test=\"${config.checkCycle == instanceAlertCheckCycleEnum.value}\">${instanceAlertCheckCycleEnum.info}</c:if>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</c:forEach>\n\t\t\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t\t\t\t<td>\n\t\t                    \t\t\t\t\t\t\t<fmt:formatDate value=\"${config.lastCheckTime}\" pattern=\"yyyy-MM-dd HH:mm:ss\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<button type=\"button\" class=\"btn btn-info\" data-target=\"#changeInstanceAlertModal${config.id}\" data-toggle=\"modal\" href=\"#\">修改</button>\n\t\t\t                    \t\t\t\t\t\t<button type=\"button\" class=\"btn btn-info\" onclick=\"if(window.confirm('确认要清除id=${config.id}的配置?!')){removeAlertConfig('${config.id}');return true;}else{return false;}\">删除</button>\n\t\t\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t\t\t\t</c:forEach>\n\t\t\t\t\t\t\t\t\t</tbody>\n\t\t\t\t\t\t\t\t</table>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<!-- END TABLE PORTLET-->\n\t\t\t</div>\n\t\t</div>\n\t\t\n\t</div>\n</div>\n\n<div id=\"addInstanceAlertModal\" class=\"modal fade\" tabindex=\"-1\" data-width=\"400\">\n\t<div class=\"modal-dialog\">\n\t\t<div class=\"modal-content\">\n\t\t\n\t\t\t<div class=\"modal-header\">\n\t\t\t\t<button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\"></button>\n\t\t\t\t<h4 class=\"modal-title\">添加实例报警项</h4>\n\t\t\t</div>\n\t\t\t\n\t\t\t<form class=\"form-horizontal form-bordered form-row-stripped\">\n\t\t\t\t<div class=\"modal-body\">\n\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t<!-- 控件开始 -->\n\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t<!-- form-body开始 -->\n\t\t\t\t\t\t\t<div class=\"form-body\">\n\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t配置名:\n\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t<select name=\"alertConfig\" id=\"alertConfig\" class=\"form-control select2_category\">\n\t\t\t\t\t\t\t\t\t\t\t<c:forEach items=\"${redisAlertConfigEnumList}\" var=\"redisAlertConfig\">\n\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"${redisAlertConfig.value}\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t${redisAlertConfig.info}\n\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t</c:forEach>\n\t\t\t\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t比较:\n\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t<select name=\"compareType\" id=\"compareType\" class=\"form-control select2_category\">\n\t\t\t\t\t\t\t\t\t\t\t<c:forEach items=\"${instanceAlertCompareTypeEnumList}\" var=\"instanceAlertCompareTypeEnum\">\n\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"${instanceAlertCompareTypeEnum.value}\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t${instanceAlertCompareTypeEnum.info}\n\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t</c:forEach>\n\t\t\t\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t阀值:\n\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"alertValue\" id=\"alertValue\"\n\t\t\t\t\t\t\t\t\t\t\tclass=\"form-control\" />\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t实例:\n\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"instanceHostPort\" id=\"instanceHostPort\"\n\t\t\t\t\t\t\t\t\t\t\tclass=\"form-control\" placeholder=\"全部则为空,单个实例ip:port\" onchange=\"checkInstanceExist()\"/>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t周期:\n\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t<select name=\"checkCycle\" id=\"checkCycle\" class=\"form-control select2_category\">\n\t\t\t\t\t\t\t\t\t\t\t<c:forEach items=\"${instanceAlertCheckCycleEnumList}\" var=\"instanceAlertCheckCycleEnum\">\n\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"${instanceAlertCheckCycleEnum.value}\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t${instanceAlertCheckCycleEnum.info}\n\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t</c:forEach>\n\t\t\t\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<!-- form-body 结束 -->\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\n\t\t\t\t<div class=\"modal-footer\">\n\t\t\t\t\t<button type=\"button\" data-dismiss=\"modal\" class=\"btn\" >Close</button>\n\t\t\t\t\t<button type=\"button\" id=\"configBtn\" class=\"btn red\" onclick=\"saveInstanceAlertConfig()\">Ok</button>\n\t\t\t\t</div>\n\t\t\t</form>\n\t\t</div>\n\t</div>\n</div>\n\n<c:forEach items=\"${instanceAlertList}\" var=\"config\">\n\t<div id=\"changeInstanceAlertModal${config.id}\" class=\"modal fade\" tabindex=\"-1\" data-width=\"400\">\n\t\t<div class=\"modal-dialog\">\n\t\t\t<div class=\"modal-content\">\n\t\t\t\n\t\t\t\t<div class=\"modal-header\">\n\t\t\t\t\t<button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\"></button>\n\t\t\t\t\t<h4 class=\"modal-title\">修改实例报警项</h4>\n\t\t\t\t</div>\n\t\t\t\t\n\t\t\t\t<form class=\"form-horizontal form-bordered form-row-stripped\">\n\t\t\t\t\t<div class=\"modal-body\">\n\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t<!-- 控件开始 -->\n\t\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t\t<!-- form-body开始 -->\n\t\t\t\t\t\t\t\t<div class=\"form-body\">\n\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t阀值:\n\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"alertValue${config.id}\" id=\"alertValue${config.id}\" value=\"${config.alertValue}\"\n\t\t\t\t\t\t\t\t\t\t\t\tclass=\"form-control\" />\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t周期:\n\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t<select name=\"checkCycle${config.id}\" id=\"checkCycle${config.id}\" class=\"form-control select2_category\">\n\t\t\t\t\t\t\t\t\t\t\t\t<c:forEach items=\"${instanceAlertCheckCycleEnumList}\" var=\"instanceAlertCheckCycleEnum\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"${instanceAlertCheckCycleEnum.value}\" <c:if test=\"${config.checkCycle == instanceAlertCheckCycleEnum.value}\">selected</c:if>>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t${instanceAlertCheckCycleEnum.info}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t\t</c:forEach>\n\t\t\t\t\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<!-- form-body 结束 -->\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t\n\t\t\t\t\t<div class=\"modal-footer\">\n\t\t\t\t\t\t<button type=\"button\" data-dismiss=\"modal\" class=\"btn\" >Close</button>\n\t\t\t\t\t\t<button type=\"button\" id=\"configBtn${config.id}\" class=\"btn red\" onclick=\"changeAlertConfig('${config.id}')\">Ok</button>\n\t\t\t\t\t</div>\n\t\t\t\t</form>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</c:forEach>\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/login.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\"\n\tpageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n<head>\n\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">\n\t<title>CacheCloud系统</title>\n\t<link rel=\"stylesheet\" type=\"text/css\" href=\"/resources/css/login.css\">\n\t<script type=\"text/javascript\" src=\"/resources/bootstrap/jquery/jquery-1.11.0.min.js\"></script>\n\t<script type=\"text/javascript\">\n\t\tfunction loginIn() {\n\t\t\tvar userName = document.getElementById(\"userName\");\n\t\t\tvar password = document.getElementById(\"password\");\n\t\t\tvar redirectUrl = document.getElementById(\"redirectUrl\").value;\n\t\t\tif(userName.value == \"\"){\n\t        \talert(\"用户名不能为空!\");\n\t        \tuserName.focus();\n\t\t\t\treturn false;\n\t        }\n\t\t\tif(password.value == \"\"){\n\t        \talert(\"密码不能为空!\");\n\t\t\t\tpassword.focus();\n\t\t\t\treturn false;\n\t        }\n\t\t\t$.post(\n\t\t\t\t'/manage/loginIn.json',\n\t\t\t\t{\n\t\t\t\t\tuserName: userName.value,\n\t\t\t\t\tpassword: password.value,\n\t\t\t\t\tisAdmin: false\n\t\t\t\t},\n\t            function(data){\n\t\t\t\t\tvar success = data.success;\n\t\t\t\t\tvar admin = data.admin;\n\t                if(success==1){\n\t                \tif (redirectUrl != \"\") {\n\t\t                \twindow.location = redirectUrl;\n\t                \t} else {\n\t                \t\tif(admin == 1){\n\t\t\t                \twindow.location = \"/manage/total/list.do\";\n\t\t                \t}else{\n\t\t\t                \twindow.location = \"/admin/app/list.do\";\n\t\t                \t}\n\t                \t}\n\t                }else if(success == 0){\n\t                \talert(\"用户名或者密码错误，请重新输入!\");\n\t                }else if(success == -1){\n\t                \talert(\"系统不存在该用户名，请确认该用户申请了cachecloud权限!\");\n\t                }else if(success == -2){\n\t                \talert(\"您不是超级管理员!\");\n\t                }\n\t            }\n\t         );\n\t\t}\n\t</script>\n</head>\n\t<body>\n\t\t<div class=\"img\"><img src=\"/resources/img/bg.png\"></div>\n\t\t<div class=\"container\">\n\t\t    <div class=\"logo\">\n\t\t        <img class=\"logo-pic\" src=\"/resources/img/logo.png\">\n\t\t    </div>\n\t\t    <div class=\"info\">\n\t\t        <form method=\"post\" name=\"login\" autocomplete=\"off\">\n\t\t            <div class=\"input\">\n\t\t                <span class=\"info-user\">用户名</span><input type=\"text\" id=\"userName\" name=\"userName\" autocomplete=\"off\">\n\t\t            </div>\n\t\t\n\t\t            <div class=\"input\">\n\t\t                <span class=\"info-user\">密码</span><input type=\"password\" id=\"password\" name=\"password\" autocomplete=\"off\">\n\t\t            </div>\n\t\t            \n\t\t            <input type=\"hidden\" value=\"${redirectUrl}\" id=\"redirectUrl\" name=\"redirectUrl\">\n\t\t            \n\t\t            <div class=\"input login\">\n\t\t                <input type=\"button\" value=\"登 录\" onclick=\"loginIn()\">\n\t\t            </div>\n\t\t\n\t\t        </form>\n\t\t        <a class=\"register\" href=\"/user/register\">新用户注册</a>\n\t\t    </div>\n\t\t</div>\n\t\t<script src=\"/resources/img/pv.gif\"></script>\n\t</body>\n</html>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/machine/addMachine.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\" pageEncoding=\"UTF-8\"%>\n<div id=\"addMachineModal${machine.info.id}\" class=\"modal fade\" tabindex=\"-1\" data-width=\"400\">\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<button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\"></button>\n\t\t\t\t<h4 class=\"modal-title\">管理机器</h4>\n\t\t\t</div>\n\t\t\t\n\t\t\t<form class=\"form-horizontal form-bordered form-row-stripped\">\n\t\t\t\t<div class=\"modal-body\">\n\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t<!-- 控件开始 -->\n\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t<!-- form-body开始 -->\n\t\t\t\t\t\t\t<div class=\"form-body\">\n\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t机器ip:\n\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"ip\" id=\"ip${machine.info.id}\"\n\t\t\t\t\t\t\t\t\t\t\tvalue=\"${machine.info.ip}\" placeholder=\"机器ip\"\n\t\t\t\t\t\t\t\t\t\t\tclass=\"form-control\" />\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\n                                <div class=\"form-group\">\n                                    <label class=\"control-label col-md-3\">\n                                        机房:\n                                    </label>\n                                    <div class=\"col-md-5\">\n                                        <input type=\"text\" name=\"room\" id=\"room${machine.info.id}\"\n                                               value=\"${machine.info.room}\" placeholder=\"机器所在机房\"\n                                               class=\"form-control\" />\n                                    </div>\n                                </div>\n\n                                <div class=\"form-group\">\n                                    <label class=\"control-label col-md-3\">\n                                        内存（单位G）:\n                                    </label>\n                                    <div class=\"col-md-5\">\n                                        <input type=\"text\" name=\"mem\" id=\"mem${machine.info.id}\"\n                                               value=\"${machine.info.mem}\" placeholder=\"机器内存\"\n                                               class=\"form-control\" />\n                                    </div>\n                                </div>\n\n                                <div class=\"form-group\">\n                                    <label class=\"control-label col-md-3\">\n                                        cpu:\n                                    </label>\n                                    <div class=\"col-md-5\">\n                                        <input type=\"text\" name=\"cpu\" id=\"cpu${machine.info.id}\"\n                                               value=\"${machine.info.cpu}\" placeholder=\"机器CPU核数\"\n                                               class=\"form-control\" />\n                                    </div>\n                                </div>\n\n                                <div class=\"form-group\">\n                                    <label class=\"control-label col-md-3\">\n                                        是否虚机:\n                                    </label>\n                                    <div class=\"col-md-5\">\n                                        <select name=\"virtual\" id=\"virtual${machine.info.id}\" class=\"form-control select2_category\">\n                                            <option value=\"0\" <c:if test=\"${machine.info.virtual == 0}\">selected=\"selected\"</c:if>>\n                                                否\n                                            </option>\n                                            <option value=\"1\" <c:if test=\"${machine.info.virtual == 2}\">selected=\"selected\"</c:if>>\n                                                是\n                                            </option>\n                                        </select>\n                                    </div>\n                                </div>\n\n                                <div class=\"form-group\">\n                                    <label class=\"control-label col-md-3\">\n                                        宿主机ip（虚机需要填写）:\n                                    </label>\n                                    <div class=\"col-md-5\">\n                                        <input type=\"text\" name=\"realIp\" id=\"realIp${machine.info.id}\"\n                                               value=\"${machine.info.realIp}\" placeholder=\"宿主机ip（虚机需要填写）\"\n                                               class=\"form-control\" />\n                                    </div>\n                                </div>\n                                \n                                <div class=\"form-group\">\n                                    <label class=\"control-label col-md-3\">\n                                        \t机器类型:\n                                    </label>\n                                    <div class=\"col-md-5\">\n                                        <select name=\"machineType\" id=\"machineType${machine.info.id}\" class=\"form-control select2_category\">\n                                            <option value=\"0\" <c:if test=\"${machine.info.type == 0}\">selected=\"selected\"</c:if>>\n                                                \tRedis机器(默认)\n                                            </option>\n                                            <option value=\"2\" <c:if test=\"${machine.info.type == 2}\">selected=\"selected\"</c:if>>\n                                                \tRedis迁移工具机器\n                                            </option>\n                                        </select>\n                                    </div>\n                                </div>\n                                \n                                <div class=\"form-group\">\n                                    <label class=\"control-label col-md-3\">\n                                      \t  额外说明:\n                                    </label>\n                                    <div class=\"col-md-5\">\n                                        <input type=\"text\" name=\"extraDesc\" id=\"extraDesc${machine.info.id}\"\n                                               value=\"${machine.info.extraDesc}\" placeholder=\"额外说明(可以不填)\"\n                                               class=\"form-control\" />\n                                    </div>\n                                </div>\n                                \n                               <div class=\"form-group\">\n                                    <label class=\"control-label col-md-3\">\n                                        状态收集:\n                                    </label>\n                                    <div class=\"col-md-5\">\n                                        <select name=\"collect\" id=\"collect${machine.info.id}\" class=\"form-control select2_category\">\n                                            <option value=\"0\" <c:if test=\"${machine.info.collect == 0}\">selected=\"selected\"</c:if>>\n                                                关闭\n                                            </option>\n                                            <option value=\"1\" <c:if test=\"${machine.info.collect == 1 || empty machine.info.id}\">selected=\"selected\"</c:if>>\n                                                开启\n                                            </option>\n                                        </select>\n                                    </div>\n                                </div>\n\n\n\n\t\t\t\t\t\t\t\t<input type=\"hidden\" id=\"machineId${machine.info.id}\" name=\"machineId\" value=\"${machine.info.id}\"/>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<!-- form-body 结束 -->\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div id=\"machineInfo${machine.info.id}\"></div>\n\t\t\t\t\t\t<!-- 控件结束 -->\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t\n\t\t\t\t<div class=\"modal-footer\">\n\t\t\t\t\t<button type=\"button\" data-dismiss=\"modal\" class=\"btn\" >Close</button>\n\t\t\t\t\t<button type=\"button\" id=\"addMachineBtn${machine.info.id}\" class=\"btn red\" onclick=\"saveOrUpdateMachine('${machine.info.id}')\">Ok</button>\n\t\t\t\t</div>\n\t\t\t\n\t\t\t</form>\n\t\t</div>\n\t</div>\n</div>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/machine/list.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\"\n    pageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n\t<title>CacheCloud管理后台</title>\n\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n\t\n\t<%@include file=\"/WEB-INF/jsp/manage/include/cache_cloud_main_css.jsp\" %>\n\n</head>\n\n<body class=\"page-header-fixed\">\n\t<%@include file=\"/WEB-INF/jsp/manage/include/head.jsp\" %>\n\n\t<%@include file=\"/WEB-INF/jsp/manage/include/left.jsp\" %>\n\n\t<%@include file=\"machineList.jsp\" %>\n\t\n\t<%@include file=\"/WEB-INF/jsp/manage/include/foot.jsp\" %>\n\n\t<%@include file=\"/WEB-INF/jsp/manage/include/cache_cloud_main_js.jsp\" %>\n\t\n</body>\n</html>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/machine/machineInstances.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\"\n    pageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n\t<title>CacheCloud管理后台</title>\n\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n\t\n\t<%@include file=\"/WEB-INF/jsp/manage/include/cache_cloud_main_css.jsp\" %>\n\n</head>\n\n<body class=\"page-header-fixed\">\n\t<%@include file=\"/WEB-INF/jsp/manage/include/head.jsp\" %>\n\n\t<%@include file=\"/WEB-INF/jsp/manage/include/left.jsp\" %>\n\n\t<%@include file=\"machineInstancesDetail.jsp\" %>\n\t\n\t<%@include file=\"/WEB-INF/jsp/manage/include/foot.jsp\" %>\n\n\t<%@include file=\"/WEB-INF/jsp/manage/include/cache_cloud_main_js.jsp\" %>\n\t\n</body>\n</html>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/machine/machineInstancesDetail.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\" pageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<script type=\"text/javascript\">\n\tfunction startInstance(appId, instanceId){\n\t\tif(confirm(\"确认要开启\"+instanceId+\"实例吗?\")){\n\t\t\t$.ajax({\n                type: \"get\",\n                url: \"/manage/instance/startInstance.json\",\n                data: \n                {\n                \tappId: appId,\n                \tinstanceId: instanceId\n                },\n                success: function (result) {\n                \tif(result.success == 1){\n                \t\talert(\"开启成功!\");\n                \t}else{\n                \t\talert(\"开启失败, msg: \" + result.message)\n                \t}\n                    window.location.reload();\n                }\n            });\n        }\n\t}\n\t\n\tfunction shutdownInstance(appId, instanceId){\n\t\tif(confirm(\"确认要下线\"+instanceId+\"实例吗?\")){\n\t\t\t$.ajax({\n                type: \"get\",\n                url: \"/manage/instance/shutdownInstance.json\",\n                data: \n                {\n                \tappId: appId,\n                \tinstanceId: instanceId\n                },\n                success: function (result) {\n                \tif(result.success == 1){\n                \t\talert(\"关闭成功!\");\n                \t}else{\n                \t\talert(\"关闭失败, msg: \" + result.message)\n                \t}\n                    window.location.reload();\n                }\n            });\n        }\n\t}\t\n\t\n</script>\n<div class=\"page-container\">\n    <div class=\"page-content\">\n        <div class=\"row\">\n\t\t    <div class=\"col-md-12\">\n\t\t        <h3 class=\"page-title\">\n\t\t           \t 机器(ip=${machineInfo.ip})实例列表\n\t\t        </h3>\n\t\t    </div>\n\t\t</div>\n\t\t<div class=\"row\">\n\t\t    <div class=\"col-md-12\">\n\t\t        <div class=\"portlet box light-grey\">\n\t\t            <div class=\"portlet-title\">\n\t\t                <div class=\"caption\"><i class=\"fa fa-globe\"></i>实例列表</div>\n\t\t                <div class=\"tools\">\n\t\t                    <a href=\"javascript:;\" class=\"collapse\"></a>\n\t\t                </div>\n\t\t            </div>\n\t\t            <div class=\"portlet-body\">\n\t\t                <table class=\"table table-striped table-bordered table-hover\" id=\"tableDataList\">\n\t\t                    <thead>\n\t\t                    <tr>\n\t\t                        <td>ID</td>\n\t\t                        <th>应用ID</th>\n\t\t                        <th>应用名</th>\n\t\t                        <th>负责人</th>\n\t\t                        <td>服务器ip:port</td>\n\t\t                        <td>实例空间使用情况</td>\n\t\t                        <td>连接数</td>\n\t\t                        <td>角色</td>\n\t\t                        <td>实例所在机器信息可用内存(G)</td>\n\t\t                        <td>实例操作</td>\n\t\t                    </tr>\n\t\t                    </thead>\n\t\t                    <tbody>\n\t\t                    <c:forEach var=\"instance\" items=\"${instanceList}\" varStatus=\"status\">\n\t\t                        <tr>\n\t\t                            <td><a href=\"/admin/instance/index.do?instanceId=${instance.id}\"\n\t\t                                   target=\"_blank\">${instance.id}</a></td>\n\t\t                            <c:set var=\"instanceStatsMapKey\" value=\"${instance.ip}:${instance.port}\"></c:set>\n\t\t                            <c:set var=\"curAppId\" value=\"${(instanceStatsMap[instanceStatsMapKey]).appId}\"></c:set>\n\t\t                            <td>\n\t\t                            \t<c:if test=\"${curAppId > 0}\">\n\t\t\t                            \t<a target=\"_blank\" href=\"/admin/app/index.do?appId=${curAppId}\">\n\t\t\t                            \t\t${curAppId}\n\t\t\t                            \t</a>\n\t\t                            \t</c:if>\n\t\t                            </td>\n\t\t                            <td>${(appInfoMap[curAppId]).name}</td>\n\t\t                            <td>${(appInfoMap[curAppId]).officer}</td>\n\t\t                            <td>${instance.ip}:${instance.port}</td>\n\t\t                            <td>\n\t\t                                <div class=\"progress margin-custom-bottom0\">\n\t\t                                \t<c:choose>\n\t\t\t\t                        \t\t<c:when test=\"${(instanceStatsMap[instanceStatsMapKey]).memUsePercent >= 80}\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<c:set var=\"progressBarStatus\" value=\"progress-bar-danger\"/>\n\t\t\t\t                        \t\t</c:when>\n\t\t\t\t                        \t\t<c:otherwise>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<c:set var=\"progressBarStatus\" value=\"progress-bar-success\"/>\n\t\t\t\t                        \t\t</c:otherwise>\n\t\t\t\t                        \t</c:choose>\n\t\t                                    <div class=\"progress-bar ${progressBarStatus}\"\n\t\t                                         role=\"progressbar\"\n\t\t                                         aria-valuenow=\"${(instanceStatsMap[instanceStatsMapKey]).memUsePercent }\"\n\t\t                                         aria-valuemax=\"100\"\n\t\t                                         aria-valuemin=\"0\"\n\t\t                                         style=\"width: ${(instanceStatsMap[instanceStatsMapKey]).memUsePercent }%\">\n\t\t                                            <label style=\"color: #000000\">\n\t\t                                                <fmt:formatNumber\n\t\t                                                        value=\"${(instanceStatsMap[instanceStatsMapKey]).usedMemory / 1024 / 1024 / 1024}\"\n\t\t                                                        pattern=\"0.00\"/>G&nbsp;&nbsp;Used/<fmt:formatNumber value=\"${(instanceStatsMap[instanceStatsMapKey]).maxMemory / 1024 / 1024 / 1024}\" pattern=\"0.00\"/>G&nbsp;&nbsp;Total\n\t\t                                            </label>\n\t\t                                     </div>\n\t\t                                </div>\n\t\t                            </td>\n                            \t\t   <td>${(instanceStatsMap[instanceStatsMapKey]).currConnections}</td>\n                            \t\t   <td>${instance.roleDesc}</td>\n\t\t                            <td><fmt:formatNumber\n\t\t                                    value=\"${(machineCanUseMem[instance.ip])/1024/1024/1024}\"\n\t\t                                    pattern=\"0.00\"/>\n\t\t                            </td>\n\t\t                            <td>\n                                        <c:choose>\n                                            <c:when test=\"${instance.status == 2}\">\n                                                <a target=\"_blank\" onclick=\"startInstance('${curAppId}', '${instance.id}')\" class=\"btn btn-success\">\n                                                 \t启动实例\n                                                </a>\n                                            </c:when>\n                                            <c:otherwise>\n                                                <a target=\"_blank\" onclick=\"shutdownInstance('${curAppId}', '${instance.id}')\" class=\"btn btn-danger\">\n                                                    下线实例\n                                                </a>\n                                            </c:otherwise>\n                                        </c:choose>\n\t\t                            </td>\n\t\t                        </tr>\n\t\t                    </c:forEach>\n\t\t                    </tbody>\n\t\t                </table>\n\t\t            </div>\n\t\t        </div>\n\t\t    </div>\n\t\t</div>\n    </div>\n</div>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/machine/machineList.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\" pageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<div class=\"page-container\">\n\t<div class=\"page-content\">\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-md-12\">\n\t\t\t\t<h3 class=\"page-title\">\n\t\t\t\t\t机器管理\n\t\t\t\t</h3>\n\t\t\t</div>\n\t\t</div>\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-md-12\">\n\t\t\t\t<div class=\"portlet box light-grey\">\n\t\t\t\t\t<div class=\"portlet-title\">\n\t\t\t\t\t\t<div class=\"caption\"><i class=\"fa fa-globe\"></i>机器列表</div>\n\t\t\t\t\t\t<div class=\"tools\">\n\t\t\t\t\t\t\t<a href=\"javascript:;\" class=\"collapse\"></a>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"portlet-body\">\n                        <div class=\"table-toolbar\">\n                            <div class=\"btn-group\">\n                                <button id=\"sample_editable_1_new\" class=\"btn green\" data-target=\"#addMachineModal\" data-toggle=\"modal\">\n                                    \t添加新机器 <i class=\"fa fa-plus\"></i>\n                                </button>\n                            </div>\n                            <div class=\"btn-group\" style=\"float:right\">\n                                <form action=\"/manage/machine/list.do\" method=\"post\" class=\"form-horizontal form-bordered form-row-stripped\">\n                                    <label class=\"control-label\">\n                                        \t机器ip:\n                                    </label>\n                                    &nbsp;<input type=\"text\" name=\"ipLike\" id=\"ipLike\" value=\"${ipLike}\" placeholder=\"机器ip\"/>\n                                    &nbsp;<button type=\"submit\" class=\"btn blue btn-sm\">查询</button>\n                                </form>\n                            </div>\n                        </div>\n\t\t\t\t\t\t<table class=\"table table-striped table-bordered table-hover\" id=\"tableDataList\">\n\t\t\t\t\t\t\t<thead>\n\t\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t\t<th>ip</th>\n\t\t\t\t\t\t\t\t\t<th>内存使用率</th>\n\t\t\t\t\t\t\t\t\t<th>已分配内存</th>\n\t\t\t\t\t\t\t\t\t<th>CPU使用率</th>\n\t\t\t\t\t\t\t\t\t<th>网络流量</th>\n\t\t\t\t\t\t\t\t\t<th>机器负载</th>\n\t\t\t\t\t\t\t\t\t<th>实例数/核数</th>\n\t\t\t\t\t\t\t\t\t<th>最后统计时间</th>\n\t\t\t\t\t\t\t\t\t<th>是否虚机</th>\n\t\t\t\t\t\t\t\t\t<th>机房</th>\n\t\t\t\t\t\t\t\t\t<th>额外说明</th>\n\t\t\t\t\t\t\t\t\t<th>状态收集</th>\n                                    <th>操作</th>\n\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t</thead>\n\t\t\t\t\t\t\t<tbody>\n\t\t\t\t\t\t\t\t<c:forEach items=\"${list}\" var=\"machine\">\n\t\t\t\t\t\t\t\t\t<tr class=\"odd gradeX\">\n\t\t\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t\t\t<a target=\"_blank\" href=\"/manage/machine/machineInstances.do?ip=${machine.info.ip}\">${machine.info.ip}</a>\n\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t\t\t<c:choose>\n\t\t\t\t\t\t\t\t\t\t\t\t<c:when test=\"${machine.memoryUsageRatio == null || machine.memoryUsageRatio == ''}\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t收集中..${collectAlert}\n\t\t\t\t\t\t\t\t\t\t\t\t</c:when>\n\t\t\t\t\t\t\t\t\t\t\t\t<c:otherwise>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span style=\"display:none\"><fmt:formatNumber value=\"${machine.memoryUsageRatio / 100}\" pattern=\"0.00\"/></span>\n\t\t                                            <div class=\"progress margin-custom-bottom0\">\n\t\t\t                                            <c:choose>\n\t\t\t\t\t\t\t                        \t\t<c:when test=\"${fmtMemoryUsageRatio >= 80.00}\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<c:set var=\"memUsedProgressBarStatus\" value=\"progress-bar-danger\"/>\n\t\t\t\t\t\t\t                        \t\t</c:when>\n\t\t\t\t\t\t\t                        \t\t<c:otherwise>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<c:set var=\"memUsedProgressBarStatus\" value=\"progress-bar-success\"/>\n\t\t\t\t\t\t\t                        \t\t</c:otherwise>\n\t\t\t\t\t\t\t                        \t</c:choose>\n\t\t                                                <fmt:formatNumber var=\"fmtMemoryUsageRatio\" value=\"${machine.memoryUsageRatio}\" pattern=\"0.00\"/>\n\t\t                                                <div class=\"progress-bar ${memUsedProgressBarStatus}\"\n\t\t                                                             role=\"progressbar\" aria-valuenow=\"${machine.memoryUsageRatio}\" aria-valuemax=\"100\"\n\t\t                                                             aria-valuemin=\"0\" style=\"width: ${machine.memoryUsageRatio}%\">\n\t\t                                                    <label style=\"color: #000000\">\n\t\t                                                        <fmt:formatNumber value=\"${((machine.memoryTotal-machine.memoryFree)/1024/1024/1024)}\" pattern=\"0.00\"/>G&nbsp;&nbsp;Used/\n\t\t                                                        <fmt:formatNumber value=\"${ machine.memoryTotal/1024/1024/1024}\" pattern=\"0.00\"/>G&nbsp;&nbsp;Total\n\t\t                                                    </label>\n\t\t                                              \t</div>\n\t\t                                             </div>\n\t\t\t\t\t\t\t\t\t\t\t\t</c:otherwise>\n\t\t\t\t\t\t\t\t\t\t\t</c:choose>\n\t\t\t\t\t\t\t\t\t\t\t\n                                              \n\t\t\t\t\t\t\t\t\t\t</td>\n                                        <td>\n                                        <c:choose>\n\t\t\t\t\t\t\t\t\t\t\t<c:when test=\"${machine.memoryUsageRatio == null || machine.memoryUsageRatio == ''}\">\n\t\t\t\t\t\t\t\t\t\t\t\t收集中..${collectAlert}\n\t\t\t\t\t\t\t\t\t\t\t</c:when>\n\t\t\t\t\t\t\t\t\t\t\t<c:otherwise>\n\t\t\t\t\t\t\t\t\t\t\t\t<fmt:formatNumber var=\"fmtMemoryAllocatedRatio\" value=\"${((machine.memoryAllocated)/1024)*100.0/(machine.memoryTotal/1024/1024/1024)}\" pattern=\"0.00\"/>\n\t                                        \t<span  style=\"display:none\"><fmt:formatNumber value=\"${fmtMemoryAllocatedRatio / 100}\" pattern=\"0.00\"/></span>\n\t                                            <div class=\"progress margin-custom-bottom0\">\n\t                                            \t<c:choose>\n\t\t\t\t\t\t                        \t\t<c:when test=\"${fmtMemoryAllocatedRatio >= 80.00}\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<c:set var=\"memAllocateProgressBarStatus\" value=\"progress-bar-danger\"/>\n\t\t\t\t\t\t                        \t\t</c:when>\n\t\t\t\t\t\t                        \t\t<c:otherwise>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<c:set var=\"memAllocateProgressBarStatus\" value=\"progress-bar-success\"/>\n\t\t\t\t\t\t                        \t\t</c:otherwise>\n\t\t\t\t\t\t                        \t</c:choose>\n\t                                                    <div class=\"progress-bar ${memAllocateProgressBarStatus}\"\n\t                                                         role=\"progressbar\" aria-valuenow=\"${fmtMemoryAllocatedRatio}\" aria-valuemax=\"100\"\n\t                                                         aria-valuemin=\"0\" style=\"width: ${fmtMemoryAllocatedRatio}%\">\n\t                                                        <label style=\"color: #000000\">\n\t                                                            <fmt:formatNumber value=\"${((machine.memoryAllocated)/1024)}\" pattern=\"0.00\"/>G&nbsp;&nbsp;Used/\n\t                                                            <fmt:formatNumber value=\"${ machine.memoryTotal/1024/1024/1024}\" pattern=\"0.00\"/>G&nbsp;&nbsp;Total\n\t                                                        </label>\n\t                                                    </div>\n\t                                                </div>\n\t\t\t\t\t\t\t\t\t\t\t</c:otherwise>\n\t\t\t\t\t\t\t\t\t\t</c:choose>\n                                            \n                                        </td>\n\t\t\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t\t\t<c:choose>\n\t\t\t\t\t\t\t\t\t\t\t\t<c:when test=\"${machine.cpuUsage == null || machine.cpuUsage == ''}\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t收集中..${collectAlert}\n\t\t\t\t\t\t\t\t\t\t\t\t</c:when>\n\t\t\t\t\t\t\t\t\t\t\t\t<c:otherwise>\n\t\t\t\t\t\t\t\t\t\t\t\t\t${machine.cpuUsage}\n\t\t\t\t\t\t\t\t\t\t\t\t</c:otherwise>\n\t\t\t\t\t\t\t\t\t\t\t</c:choose>\n\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t\t\t<fmt:formatNumber value=\"${machine.traffic / 1024 / 1024}\" pattern=\"0.00\"/>M\n\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t\t\t<c:choose>\n\t\t\t\t\t\t\t\t\t\t\t\t<c:when test=\"${machine.load == null || machine.load == ''}\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t收集中..${collectAlert}\n\t\t\t\t\t\t\t\t\t\t\t\t</c:when>\n\t\t\t\t\t\t\t\t\t\t\t\t<c:otherwise>\n\t\t\t\t\t\t\t\t\t\t\t\t\t${machine.load}\n\t\t\t\t\t\t\t\t\t\t\t\t</c:otherwise>\n\t\t\t\t\t\t\t\t\t\t\t</c:choose>\n\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t\t\t<fmt:formatNumber var=\"fmtInstanceCpuRatio\" value=\"${machineInstanceCountMap[machine.info.ip] * 100.0 /machine.info.cpu}\" pattern=\"0.00\"/>\n\t                                        \t<span style=\"display:none\"><fmt:formatNumber value=\"${fmtInstanceCpuRatio / 100}\" pattern=\"0.00\"/></span>\n\t                                            <div class=\"progress margin-custom-bottom0\">\n\t                                            \t<c:choose>\n\t\t\t\t\t\t                        \t\t<c:when test=\"${fmtInstanceCpuRatio >= 80.00}\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<c:set var=\"instanceCpuProgressBarStatus\" value=\"progress-bar-danger\"/>\n\t\t\t\t\t\t                        \t\t</c:when>\n\t\t\t\t\t\t                        \t\t<c:otherwise>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<c:set var=\"instanceCpuProgressBarStatus\" value=\"progress-bar-success\"/>\n\t\t\t\t\t\t                        \t\t</c:otherwise>\n\t\t\t\t\t\t                        \t</c:choose>\n\t\t\t\t\t\t                        \t<c:choose>\n\t\t\t\t\t\t                        \t\t<c:when test=\"${fmtInstanceCpuRatio == 0.00}\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<c:set var=\"instanceCount\" value=\"0\"/>\n\t\t\t\t\t\t                        \t\t</c:when>\n\t\t\t\t\t\t                        \t\t<c:otherwise>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<c:set var=\"instanceCount\" value=\"${machineInstanceCountMap[machine.info.ip]}\"/>\n\t\t\t\t\t\t                        \t\t</c:otherwise>\n\t\t\t\t\t\t                        \t</c:choose>\n\t                                                    <div class=\"progress-bar ${instanceCpuProgressBarStatus}\"\n\t                                                         role=\"progressbar\" aria-valuenow=\"${fmtInstanceCpuRatio}\" aria-valuemax=\"100\"\n\t                                                         aria-valuemin=\"0\" style=\"width: ${fmtInstanceCpuRatio}%\">\n\t                                                        <label style=\"color: #000000\">\n\t                                                            <fmt:formatNumber value=\"${instanceCount}\"/>&nbsp;&nbsp;/\n\t                                                            <fmt:formatNumber value=\"${machine.info.cpu}\"/>&nbsp;&nbsp;\n\t                                                        </label>\n\t                                                    </div>\n\t                                                </div>\n\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t\t<td><fmt:formatDate value=\"${machine.modifyTime}\" type=\"time\" timeStyle=\"full\" pattern=\"yyyy-MM-dd HH:mm\"/></td>\n                                        <th>\n                                        \t<c:choose>\n                                        \t\t<c:when test=\"${machine.info.virtual == 1}\">\n                                        \t\t\t是\n                                        \t\t\t<br/>\n                                        \t\t\t物理机:${machine.info.realIp}\n                                        \t\t</c:when>\n                                        \t\t<c:otherwise>\n                                        \t\t\t否\n                                        \t\t</c:otherwise>\n                                        \t</c:choose>\n                                        </th>\n\t\t\t\t\t\t\t\t\t\t<th>${machine.info.room}</th>\n\t\t\t\t\t\t\t\t\t\t<th>\n\t\t\t\t\t\t\t\t\t\t${machine.info.extraDesc}\n\t\t\t\t\t\t\t\t\t\t<c:if test=\"${machine.info.type == 2}\">\n\t\t\t\t\t\t\t\t\t\t\t<font color='red'>(迁移工具机器)</font>\n\t\t\t\t\t\t\t\t\t\t</c:if>\n\t\t\t\t\t\t\t\t\t\t</th>\n                                       \t<c:choose>\n                                       \t\t<c:when test=\"${machine.info.collect == 1}\">\n                                       \t\t\t<td>开启</td>\n                                       \t\t</c:when>\n                                       \t\t<c:otherwise>\n                                       \t\t\t<th>关闭</th>\n                                       \t\t</c:otherwise>\n                                       \t</c:choose>\n                                        <td>\n                                        \t<a href=\"/server/index.do?ip=${machine.info.ip}\" class=\"btn btn-info\" target=\"_blank\">监控</a>\n                                        \t&nbsp;\n                                            <a href=\"javascript;\" data-target=\"#addMachineModal${machine.info.id}\" class=\"btn btn-info\" data-toggle=\"modal\">修改</a>\n                                            &nbsp;\n                                            \n                                            <button id=\"removeMachineBtn${machine.info.id}\" onclick=\"removeMachine(this.id,'${machine.info.ip}')\" type=\"button\" class=\"btn btn-info\">删除</button>               \n                                            \n                                            \n                                        </td>\n\t\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t\t</c:forEach>\n\t\t\t\t\t\t\t</tbody>\n\t\t\t\t\t\t</table>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n    <c:forEach items=\"${list}\" var=\"machine\">\n        <%@include file=\"addMachine.jsp\" %>\n    </c:forEach>\n    <%@include file=\"addMachine.jsp\"%>\n</div>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/notice/initNotice.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\"\n    pageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n\t<title>CacheCloud管理后台</title>\n\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n\t\n\t<%@include file=\"/WEB-INF/jsp/manage/include/cache_cloud_main_css.jsp\" %>\n\n</head>\n\n<body class=\"page-header-fixed\">\n\t<%@include file=\"/WEB-INF/jsp/manage/include/head.jsp\" %>\n\n\t<%@include file=\"/WEB-INF/jsp/manage/include/left.jsp\" %>\n\n\t<%@include file=\"initNoticeDetail.jsp\" %>\n\t\n\t<%@include file=\"/WEB-INF/jsp/manage/include/foot.jsp\" %>\n\n\t<%@include file=\"/WEB-INF/jsp/manage/include/cache_cloud_main_js.jsp\" %>\n\t\n</body>\n</html>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/notice/initNoticeDetail.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\" pageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<script type=\"text/javascript\">\n\tfunction checkNoticeText(){\n\t\tvar notice = document.getElementById(\"notice\");\n\t\tif(notice.value == \"\"){\n\t\t\talert(\"系统通知不能为空!\");\n\t\t\tnotice.focus();\n\t\t\treturn false;\n\t\t}\n\t\t$.post(\n\t\t\t'/manage/notice/add.json',\n\t\t\t{\n\t\t\t\tnotice: notice.value,\n\t\t\t},\n\t        function(data){\n\t            if(data.success==1){\n\t            \talert(\"更新成功!\");\n\t            }else{\n\t            \talert(\"更新失败!\");\n\t            }\n\t            window.location.reload();\n\t        }\n\t     );\n\t\t\n\t}\n</script>\n<div class=\"page-container\">\n\t<div class=\"page-content\">\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-md-12\">\n\t\t\t\t<h3 class=\"page-title\">\n\t\t\t\t\t系统通知管理\n\t\t\t\t\t<c:choose>\n\t\t\t\t\t\t<c:when test=\"${success == 1}\">\n\t\t\t\t\t\t\t<font color=\"red\">更新成功</font>\n\t\t\t\t\t\t</c:when>\n\t\t\t\t\t\t<c:when test=\"${success == 0}\">\n\t\t\t\t\t\t\t<font color=\"red\">更新失败</font>\n\t\t\t\t\t\t</c:when>\n\t\t\t\t\t</c:choose>\n\t\t\t\t</h3>\n\t\t\t</div>\n\t\t</div>\n\t\t\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-md-12\">\n\t\t\t\t<div class=\"portlet box light-grey\">\n\t\t\t\t\t<div class=\"portlet-title\">\n\t\t\t\t\t\t<div class=\"caption\">\n\t\t\t\t\t\t\t<i class=\"fa fa-globe\"></i>\n\t\t\t\t\t\t\t填写系统通知:\n\t\t\t\t\t\t\t&nbsp;\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"tools\">\n\t\t\t\t\t\t\t<a href=\"javascript:;\" class=\"collapse\"></a>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"portlet-body\">\n\t\t\t\t\t\t<div class=\"form\">\n\t\t\t\t\t\t\t\t<!-- BEGIN FORM-->\n\t\t\t\t\t\t\t\t<form action=\"/manage/notice/add.do\" method=\"post\"\n\t\t\t\t\t\t\t\t\tclass=\"form-horizontal form-bordered form-row-stripped\">\n\t\t\t\t\t\t\t\t\t<div class=\"form-body\">\n\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t系统通知:<font color='red'>(*)</font>:\n\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t<textarea rows=\"10\" name=\"notice\" id=\"notice\" placeholder=\"系统通知\" class=\"form-control\">${notice}</textarea>\n\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"help-block\">\n\t\t\t\t\t\t\t\t\t\t\t\t例如:<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t1.CacheCloud相关文档可以在菜单栏查询(2014-12-16)<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t2.接入代码模块加入了Protostuff序列化的演示。(2014-12-19)\n\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t<div class=\"form-actions fluid\">\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-offset-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<button type=\"button\" class=\"btn green\" onclick=\"checkNoticeText()\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-check\"></i>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t提交\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</form>\n\t\t\t\t\t\t\t\t<!-- END FORM-->\n\t\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<!-- END EXAMPLE TABLE PORTLET-->\n\t\t\t</div>\n\t\t\n\t\t</div>\n\t</div>\n</div>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/quartz/list.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\"\n    pageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n\t<title>CacheCloud管理后台</title>\n\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n\t\n\t<%@include file=\"/WEB-INF/jsp/manage/include/cache_cloud_main_css.jsp\" %>\n\n</head>\n\n<body class=\"page-header-fixed\">\n\t<%@include file=\"/WEB-INF/jsp/manage/include/head.jsp\" %>\n\n\t<%@include file=\"/WEB-INF/jsp/manage/include/left.jsp\" %>\n\n\t<%@include file=\"quartzList.jsp\" %>\n\t\n\t<%@include file=\"/WEB-INF/jsp/manage/include/foot.jsp\" %>\n\n\t<%@include file=\"/WEB-INF/jsp/manage/include/cache_cloud_main_js.jsp\" %>\n\t\n</body>\n</html>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/quartz/quartzList.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\" pageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<div class=\"page-container\">\n\t<div class=\"page-content\">\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-md-12\">\n\t\t\t\t<h3 class=\"page-title\">\n\t\t\t\t\tQuartz管理\n\t\t\t\t</h3>\n\t\t\t</div>\n\t\t</div>\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-md-12\">\n\t\t\t\t<div class=\"portlet box light-grey\">\n\t\t\t\t\t<div class=\"portlet-title\">\n\t\t\t\t\t\t<div class=\"caption\"><i class=\"fa fa-globe\"></i>trigger列表</div>\n\t\t\t\t\t\t<div class=\"tools\">\n\t\t\t\t\t\t\t<a href=\"javascript:;\" class=\"collapse\"></a>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"portlet-body\">\n                        <div class=\"table-toolbar\">\n                            <div class=\"btn-group\" style=\"float:right\">\n                                <form action=\"/manage/quartz/list.do\" method=\"post\" class=\"form-horizontal form-bordered form-row-stripped\">\n                                    <label class=\"control-label\">\n                                        查询:\n                                    </label>\n                                    &nbsp;<input type=\"text\" name=\"query\" id=\"ipLike\" value=\"${query}\" placeholder=\"\"/>\n                                    &nbsp;<button type=\"submit\" class=\"btn blue btn-sm\">查询</button>\n                                </form>\n                            </div>\n                        </div>\n\t\t\t\t\t\t<table class=\"table table-striped table-bordered table-hover\" id=\"tableDataList\">\n\t\t\t\t\t\t\t<thead>\n\t\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t\t<th>triggerName</th>\n\t\t\t\t\t\t\t\t\t<th>triggerGroup</th>\n                                    <th>cron</th>\n                                    <th>nextFireDate</th>\n\t\t\t\t\t\t\t\t\t<th>prevFireDate</th>\n                                    <th>startDate</th>\n\t\t\t\t\t\t\t\t\t<th>triggerState</th>\n\t\t\t\t\t\t\t\t\t<th>操作</th>\n\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t</thead>\n\t\t\t\t\t\t\t<tbody>\n\t\t\t\t\t\t\t\t<c:forEach items=\"${triggerList}\" var=\"t\">\n\t\t\t\t\t\t\t\t\t<tr class=\"odd gradeX\">\n\t\t\t\t\t\t\t\t\t\t<td>${t.triggerName}</td>\n\t\t\t\t\t\t\t\t\t\t<td>${t.triggerGroup}</td>\n                                        <td>${t.cron}</td>\n                                        <td>${t.nextFireDate}</td>\n\t\t\t\t\t\t\t\t\t\t<td>${t.prevFireDate}</td>\n                                        <td>${t.startDate}</td>\n\t\t\t\t\t\t\t\t\t\t<td>${t.triggerState}</td>\n\t\t\t\t\t\t\t\t\t\t<td>\n                                        <c:if test=\"${t.triggerState == 'PAUSED'}\">\n                                            <a onclick=\"if(window.confirm('确认恢复吗?!')){return true;}else{return false;}\"\n                                               href=\"/manage/quartz/resume.do?name=${t.triggerName}&group=${t.triggerGroup}\">[恢复]\n                                            </a>\n                                        </c:if>\n                                        <c:if test=\"${t.triggerState != 'PAUSED'}\">\n                                            <a onclick=\"if(window.confirm('确认暂停吗?!')){return true;}else{return false;}\"\n                                               href=\"/manage/quartz/pause.do?name=${t.triggerName}&group=${t.triggerGroup}\">[暂停]\n                                            </a>\n                                        </c:if>\n                                        <a onclick=\"if(window.confirm('确认删除吗?!')){return true;}else{return false;}\"\n                                               href=\"/manage/quartz/remove.do?name=${t.triggerName}&group=${t.triggerGroup}\">[删除]\n                                        </a>\n\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t\t</c:forEach>\n\t\t\t\t\t\t\t</tbody>\n\t\t\t\t\t\t</table>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/redisConfig/init.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\"\n    pageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n\t<title>CacheCloud管理后台</title>\n\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n\t\n\t<%@include file=\"/WEB-INF/jsp/manage/include/cache_cloud_main_css.jsp\" %>\n\n</head>\n\n<body class=\"page-header-fixed\">\n\t<%@include file=\"/WEB-INF/jsp/manage/include/head.jsp\" %>\n\n\t<%@include file=\"/WEB-INF/jsp/manage/include/left.jsp\" %>\n\n\t<%@include file=\"initConfigDetail.jsp\" %>\n\t\n\t<%@include file=\"/WEB-INF/jsp/manage/include/foot.jsp\" %>\n\n\t<%@include file=\"/WEB-INF/jsp/manage/include/cache_cloud_main_js.jsp\" %>\n\t\n</body>\n</html>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/redisConfig/initConfigDetail.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\" pageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n\n<script type=\"text/javascript\">\n\nfunction removeConfig(id, configKey) {\n\tif (confirm(\"确认要删除key=\"+configKey+\"配置?\")) {\n\t\t$.get(\n\t\t\t'/manage/redisConfig/remove.json',\n\t\t\t{\n\t\t\t\tid: id\n\t\t\t},\n\t        function(data){\n\t\t\t\tvar status = data.status;\n\t\t\t\tif (status == 1) {\n            \t\talert(\"删除成功!\");\n\t\t\t\t} else {\n            \t\talert(\"删除失败, msg: \" + result.message);\n\t\t\t\t}\n                window.location.reload();\n\t        }\n\t     );\n\t\t\n    }\n}\n\nfunction changeConfig(id, configKey) {\n\tvar configValue = document.getElementById(\"configValue\" + id);\n\tvar info = document.getElementById(\"info\" + id);\n\tvar status = document.getElementById(\"status\" + id);\n\t$.get(\n\t\t'/manage/redisConfig/update.json',\n\t\t{\n\t\t\tid: id,\n\t\t\tconfigKey: configKey,\n\t\t\tconfigValue: configValue.value,\n\t\t\tinfo: info.value,\n\t\t\tstatus: status.value\n\t\t},\n        function(data){\n\t\t\tvar status = data.status;\n\t\t\tif (status == 1) {\n\t\t\t\talert(\"修改成功！\");\n                window.location.reload();\n\t\t\t} else {\n\t\t\t\talert(\"修改失败！\" + data.message);\n\t\t\t}\n\t\t\t\n        }\n     );\n}\n\nfunction saveRedisConfig() {\n\tvar configKey = document.getElementById(\"configKey\");\n\tif (configKey.value == \"\"){\n\t\talert(\"请填写配置名\");\n\t\tconfigKey.focus();\n\t\treturn false;\n\t}\n\tvar configValue = document.getElementById(\"configValue\");\n\tvar info = document.getElementById(\"info\");\n\tif (info.value == \"\") {\n\t\talert(\"请填写配置说明\");\n\t\tinfo.focus();\n\t\treturn false;\n\t}\n\tvar type = document.getElementById(\"type\");\n\t$.get(\n\t\t'/manage/redisConfig/add.json',\n\t\t{\n\t\t\tconfigKey: configKey.value,\n\t\t\tconfigValue: configValue.value,\n\t\t\tinfo: info.value,\n\t\t\ttype: type.value\n\t\t},\n        function(data){\n\t\t\tvar status = data.status;\n\t\t\tif (status == 1) {\n\t\t\t\talert(\"添加成功！\");\n\t\t\t} else {\n\t\t\t\talert(\"添加失败！\" + data.message);\n\t\t\t}\n            window.location.reload();\n        }\n     );\n}\n</script>\n\n<div class=\"page-container\">\n\t<div class=\"page-content\">\n\t\t<div class=\"table-toolbar\">\n\t\t\t<div class=\"btn-group\">\n\t\t\t\t<button id=\"sample_editable_1_new\" class=\"btn green\" data-target=\"#addRedisConfigModal\" data-toggle=\"modal\">\n\t\t\t\t添加新配置 <i class=\"fa fa-plus\"></i>\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t\t<div class=\"btn-group\" style=\"float:right\">\n\t\t\t\t<form action=\"/manage/redisConfig/init.do\" method=\"post\" class=\"form-horizontal form-bordered form-row-stripped\">\n\t\t\t\t\t<label class=\"control-label\">\n\t\t\t\t\t\tRedis类型:\n\t\t\t\t\t</label>\n\t\t\t\t\t<select name=\"type\">\n\t\t\t\t\t\t<option value=\"2\" <c:if test=\"${type == 2}\">selected</c:if>>\n\t\t\t\t\t\t\tRedis-cluster\n\t\t\t\t\t\t</option>\n\t\t\t\t\t\t<option value=\"5\" <c:if test=\"${type == 5}\">selected</c:if>>\n\t\t\t\t\t\t\tRedis-sentinel\n\t\t\t\t\t\t</option>\n\t\t\t\t\t\t<option value=\"6\" <c:if test=\"${type == 6}\">selected</c:if>>\n\t                       Redis-standalone\n\t\t\t\t\t\t</option>\n\t\t\t\t\t</select>\n\t\t\t\t\t&nbsp;<button type=\"submit\" class=\"btn green btn-sm\">查询</button>\n\t\t\t\t</form>\n\t\t\t</div>\n\t\t</div>\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-md-12\">\n\t\t\t\t<h3 class=\"page-title\">\n\t\t\t\t\t<c:choose>\n\t\t\t\t\t\t<c:when test=\"${type==6}\">Redis普通配置</c:when>\n\t\t\t\t\t\t<c:when test=\"${type==2}\">Redis Cluster</c:when>\n\t\t\t\t\t\t<c:when test=\"${type==5}\">Redis Sentinel</c:when>\n\t\t\t\t\t</c:choose>\n\t\t\t\t\t<a target=\"_blank\" href=\"/manage/redisConfig/preview?type=${type}\" class=\"btn btn-info\" role=\"button\">配置模板 预览</a>\n\t\t\t\t\t\n\t\t\t\t</h3>\n\t\t\t</div>\n\t\t</div>\n\t\t<div class=\"alert alert-warning\" role=\"alert\">\n\t\t        1. 此功能是Redis全局配置模板(每次开启应用时用到)，请谨慎修改.<br/>\n\t\t        2. 配置中的%d,%s代表Cachecloud会动态配置，最好不要修改.<br/>\n\t\t        3. 使用方法详见<a target=\"_blank\" href='http://cachecloud.github.io/2016/07/13/1.2.%20Redis%E9%85%8D%E7%BD%AE%E6%A8%A1%E6%9D%BF%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95/'>Redis配置模板使用方法</a>\n\t\t</div>\n\t\t\n\t\t\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-md-12\">\n\t\t\t\t<div class=\"portlet box light-grey\">\n\t\t\t\t\t\t<div class=\"portlet-title\">\n\t\t\t\t\t\t\t<div class=\"caption\">\n\t\t\t\t\t\t\t\t<i class=\"fa fa-globe\"></i>\n\t\t\t\t\t\t\t\t填写配置:\n\t\t\t\t\t\t\t\t&nbsp;\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div class=\"tools\">\n\t\t\t\t\t\t\t\t<a href=\"javascript:;\" class=\"collapse\"></a>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t<c:forEach items=\"${redisConfigList}\" var=\"config\" varStatus=\"stats\">\n\t\t\t\t\t\t\t<div class=\"form\">\n\t\t\t\t\t\t\t\t<form class=\"form-horizontal form-bordered form-row-stripped\">\n\t\t\t\t\t\t\t\t\t<div class=\"form-body\">\n\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t<c:choose>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<c:when test=\"${config.status == 0}\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<font color='red'>（无效配置）</font>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</c:when>\n\t\t\t\t\t\t\t\t\t\t\t\t</c:choose>\n\t\t\t\t\t\t\t\t\t\t\t\t${config.configKey}:\n\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-2\">\n\t\t\t\t\t\t\t\t\t\t\t\t<input id=\"configValue${config.id}\" type=\"text\" name=\"configValue\" class=\"form-control\" value=\"${config.configValue}\" />\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t<input id=\"info${config.id}\" type=\"text\" name=\"info\" class=\"form-control\" value=\"${config.info}\" />\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-2\">\n\t\t\t\t\t\t\t\t\t\t\t\t<select id=\"status${config.id}\" name=\"status\" class=\"form-control\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"1\" <c:if test=\"${config.status == 1}\">selected</c:if>>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t有效\n\t\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"0\" <c:if test=\"${config.status == 0}\">selected</c:if>>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t无效\n\t\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-2\">\n\t\t\t\t\t\t\t\t\t\t\t\t<button type=\"button\" class=\"btn btn-small\" onclick=\"changeConfig('${config.id}','${config.configKey}')\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t修改\n\t\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t\t\t<button type=\"button\" class=\"btn btn-small\" onclick=\"removeConfig('${config.id}','${config.configKey}')\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t删除\n\t\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t<input type=\"hidden\" name=\"configKey\" value=\"${config.configKey}\">\n\t\t\t\t\t\t\t\t\t<input type=\"hidden\" name=\"id\" value=\"${config.id}\">\n\t\t\t\t\t\t\t\t</form>\n\t\t\t\t\t\t\t\t<!-- END FORM-->\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</c:forEach>\n\t\t\t\t\t</div>\n\t\t\t\t\t<!-- END TABLE PORTLET-->\n\t\t\t\t</div>\n\t\t\t</div>\n\t</div>\n</div>\n\n<div id=\"addRedisConfigModal\" class=\"modal fade\" tabindex=\"-1\" data-width=\"400\">\n\t<div class=\"modal-dialog\">\n\t\t<div class=\"modal-content\">\n\t\t\n\t\t\t<div class=\"modal-header\">\n\t\t\t\t<button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\"></button>\n\t\t\t\t<h4 class=\"modal-title\">添加Redis配置</h4>\n\t\t\t</div>\n\t\t\t\n\t\t\t<form class=\"form-horizontal form-bordered form-row-stripped\">\n\t\t\t\t<div class=\"modal-body\">\n\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t<!-- 控件开始 -->\n\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t<!-- form-body开始 -->\n\t\t\t\t\t\t\t<div class=\"form-body\">\n\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t配置名:\n\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"configKey\" id=\"configKey\"\n\t\t\t\t\t\t\t\t\t\t\tclass=\"form-control\" />\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t配置值:\n\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"configValue\" id=\"configValue\"\n\t\t\t\t\t\t\t\t\t\t\tclass=\"form-control\" />\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t配置说明:\n\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"info\" id=\"info\"\n\t\t\t\t\t\t\t\t\t\t\tclass=\"form-control\" />\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\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<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t类型:\n\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t<select name=\"type\" id=\"type\" class=\"form-control select2_category\">\n\t\t\t\t\t\t\t\t\t\t\t<option value=\"6\">\n\t\t\t\t\t\t\t\t\t\t\t\tRedis普通配置\n\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t<option value=\"2\">\n\t\t\t\t\t\t\t\t\t\t\t\tRedis Cluster配置\n\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t<option value=\"5\" >\n\t\t\t\t\t\t\t\t\t\t\t\tRedis Sentinel配置\n\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<!-- form-body 结束 -->\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div id=\"info\"></div>\n\t\t\t\t\t\t<!-- 控件结束 -->\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t\n\t\t\t\t<div class=\"modal-footer\">\n\t\t\t\t\t<button type=\"button\" data-dismiss=\"modal\" class=\"btn\" >Close</button>\n\t\t\t\t\t<button type=\"button\" id=\"configBtn\" class=\"btn red\" onclick=\"saveRedisConfig()\">Ok</button>\n\t\t\t\t</div>\n\t\t\t\n\t\t\t</form>\n\t\t</div>\n\t</div>\n</div>\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/redisConfig/preview.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n\t<title>配置预览</title>\n</head>\n\t<body STYLE=\"BACKGROUND-COLOR:#000;color:#FFF\">\n\t\t<c:choose>\n\t\t\t<c:when test=\"${type == 2}\">\n\t\t\t\tRedis Cluster配置，所用参数port=${port}\n\t\t\t</c:when>\n\t\t\t<c:when test=\"${type == 5}\">\n\t\t\t\tRedis Sentinel配置，所用参数masterName=${masterName},host:port=${host}:${port}, sentinelPort=${sentinelPort}\n\t\t\t</c:when>\n\t\t\t<c:when test=\"${type == 6}\">\n\t\t\t\tRedis普通节点配置，所用参数port=${port},maxmemory=${maxMemory}\n\t\t\t</c:when>\n\t\t</c:choose>\n\t\t\n\t\t<br/><br/>配置模板预览:<br/>\n\t\n\t\t<c:forEach items=\"${configList}\" var=\"line\">\n\t\t\t<font color=\"white\">${line}</font><br/>\n\t\t</c:forEach>\n\t</body>\n</html>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/total/list.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\"\n    pageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n\t<title>CacheCloud管理后台</title>\n\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n\t\n\t<%@include file=\"/WEB-INF/jsp/manage/include/cache_cloud_main_css.jsp\" %>\n\n</head>\n\n<body class=\"page-header-fixed\">\n\t<%@include file=\"/WEB-INF/jsp/manage/include/head.jsp\" %>\n\n\t<%@include file=\"/WEB-INF/jsp/manage/include/left.jsp\" %>\n\n\t<%@include file=\"totalList.jsp\" %>\n\t\n\t<%@include file=\"/WEB-INF/jsp/manage/include/foot.jsp\" %>\n\n\t<%@include file=\"/WEB-INF/jsp/manage/include/cache_cloud_main_js.jsp\" %>\n\t\n</body>\n</html>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/total/totalList.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\" pageEncoding=\"UTF-8\" %>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\" %>\n<div class=\"page-container\">\n    <div class=\"page-content\">\n        <div class=\"row\">\n            <div class=\"col-md-12\">\n                <h3 class=\"page-title\">\n                    \t全局统计\n                </h3>\n            </div>\n        </div>\n        <div class=\"row\">\n            <div class=\"col-md-12\">\n                <div class=\"portlet box light-grey\">\n                    <div class=\"portlet-title\">\n                        <div class=\"caption\"><i class=\"fa fa-globe\"></i>全局统计</div>\n                        <div class=\"tools\">\n                            <a href=\"javascript:;\" class=\"collapse\"></a>\n                        </div>\n                    </div>\n                    <div class=\"portlet-body\">\n\n                        <div class=\"table-toolbar\">\n                            <table class=\"table table-striped table-bordered table-hover\">\n                                <tr>\n                                    <td>机器总内存</td>\n                                    <td><fmt:formatNumber value=\"${totalMachineMem/1024/1024/1024}\" pattern=\"0.00\"/>G\n                                    </td>\n                                    <td>机器空闲内存</td>\n                                    <td><fmt:formatNumber value=\"${totalFreeMachineMem/1024/1024/1024}\" pattern=\"0.00\"/>G</td>\n                                    <td>实例总内存</td>\n                                    <td><fmt:formatNumber value=\"${totalInstanceMem/1024/1024/1024}\" pattern=\"0.00\"/>G\n                                    </td>\n                                    <td>实例总使用内存</td>\n                                    <td><fmt:formatNumber value=\"${totalUseInstanceMem/1024/1024/1024}\" pattern=\"0.00\"/>G</td>\n                                </tr>\n                                <tr>\n                                    <td>应用总数</td>\n                                    <td>${totalApps}</td>\n                                    <td>运行中应用数</td>\n                                    <td>${totalRunningApps}</td>\n                                    <td>应用总申请内存</td>\n                                    <td><fmt:formatNumber value=\"${totalApplyMem/1024}\" pattern=\"0.00\"/>G</td>\n                                    <td>应用已使用内存</td>\n                                    <td><fmt:formatNumber value=\"${totalUsedMem/1024}\" pattern=\"0.00\"/>G</td>\n                                </tr>\n\n                            </table>\n                            <br/>\n                            <h3>集群当前可对外提供空间：<fmt:formatNumber\n                                value=\"${(totalFreeMachineMem-(totalInstanceMem-totalUseInstanceMem))/1024/1024/1024}\"\n                                pattern=\"0.00\"/>G</h3>\n                        </div>\n                        <table class=\"table table-striped table-bordered table-hover\" id=\"tableDataList\">\n                            <thead>\n                            <tr>\n                                <td>应用ID</td>\n                                <td>应用名</td>\n                                <td>应用类型</td>\n                                <td>内存详情</td>\n                                <td>命中率</td>\n                                <td>已运行时间(天)</td>\n                                <td>申请状态</td>\n                                <td>操作</td>\n                            </tr>\n                            </thead>\n                            <tbody>\n                            <c:forEach items=\"${appDetailList}\" var=\"appDetail\">\n                                <tr class=\"odd gradeX\">\n                                    <td>\n                                        <c:choose>\n                                            <c:when test=\"${appDetail.appDesc.status == 0 or appDetail.appDesc.status == 1}\">\n                                                ${appDetail.appDesc.appId}\n                                            </c:when>\n                                            <c:when test=\"${appDetail.appDesc.status == 2 or appDetail.appDesc.status == 3 or appDetail.appDesc.status == 4}\">\n                                                <a target=\"_blank\"\n                                                   href=\"/manage/app/index.do?appId=${appDetail.appDesc.appId}\">${appDetail.appDesc.appId}</a>\n                                            </c:when>\n                                        </c:choose>\n                                    </td>\n                                    <td>\n                                        <c:choose>\n                                            <c:when test=\"${appDetail.appDesc.status == 0 or appDetail.appDesc.status == 1}\">\n                                                ${appDetail.appDesc.name}\n                                            </c:when>\n                                            <c:when test=\"${appDetail.appDesc.status == 2 or appDetail.appDesc.status == 3 or appDetail.appDesc.status == 4}\">\n                                                <a target=\"_blank\"\n                                                   href=\"/admin/app/index.do?appId=${appDetail.appDesc.appId}\">${appDetail.appDesc.name}</a>\n                                            </c:when>\n                                        </c:choose>\n                                    </td>\n                                    <td>\n                                        ${appDetail.appDesc.typeDesc}\n                                    </td>\n                                    <td>\n                                    \t<span style=\"display:none\"><fmt:formatNumber value=\"${appDetail.memUsePercent / 100}\" pattern=\"0.00\"/></span>\n                                        <div class=\"progress margin-custom-bottom0\">\n                                        \t<c:choose>\n\t\t\t\t                        \t\t<c:when test=\"${appDetail.memUsePercent >= 80}\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<c:set var=\"progressBarStatus\" value=\"progress-bar-danger\"/>\n\t\t\t\t                        \t\t</c:when>\n\t\t\t\t                        \t\t<c:otherwise>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<c:set var=\"progressBarStatus\" value=\"progress-bar-success\"/>\n\t\t\t\t                        \t\t</c:otherwise>\n\t\t\t\t                        \t</c:choose>\n                                            <div class=\"progress-bar ${progressBarStatus}\"\n                                                 role=\"progressbar\" aria-valuenow=\"${appDetail.memUsePercent}\"\n                                                 aria-valuemax=\"100\"\n                                                 aria-valuemin=\"0\" style=\"width: ${appDetail.memUsePercent}%\">\n                                                    <label style=\"color: #000000\">\n                                                        <fmt:formatNumber\n                                                                value=\"${appDetail.mem  * appDetail.memUsePercent / 100 / 1024}\"\n                                                                pattern=\"0.00\"/>G&nbsp;&nbsp;Used/<fmt:formatNumber value=\"${appDetail.mem / 1024 * 1.0}\" pattern=\"0.00\"/>G&nbsp;&nbsp;Total\n                                                    </label>\n                                            </div>\n                                        </div>\n                                    </td>\n                                    <td>\n                                    \t<span style=\"display:none\"><fmt:formatNumber value=\"${appDetail.hitPercent / 100}\" pattern=\"0.00\"/></span>\n                                        <c:choose>\n                                            <c:when test=\"${appDetail.hitPercent <= 0}\">\n                                                \t无\n                                            </c:when>\n                                            <c:when test=\"${appDetail.hitPercent <= 30}\">\n                                                <label class=\"label label-danger\">${appDetail.hitPercent}%</label>\n                                            </c:when>\n                                            <c:when test=\"${appDetail.hitPercent >= 30 && appDetail.hitPercent < 50}\">\n                                                <label class=\"label label-warning\">${appDetail.hitPercent}%</label>\n                                            </c:when>\n                                            <c:when test=\"${appDetail.hitPercent >= 50 && appDetail.hitPercent < 90}\">\n                                                <label class=\"label label-info\">${appDetail.hitPercent}%</label>\n                                            </c:when>\n                                            <c:otherwise>\n                                                <label class=\"label label-success\">${appDetail.hitPercent}%</label>\n                                            </c:otherwise>\n                                        </c:choose>\n                                    </td>\n                                    <td>${appDetail.appDesc.appRunDays}</td>\n                                    <td>\n                                        <c:choose>\n                                            <c:when test=\"${appDetail.appDesc.status == 0}\">\n                                                <font color=\"red\">未申请</font>\n                                            </c:when>\n                                            <c:when test=\"${appDetail.appDesc.status == 1}\">\n                                                <font color=\"red\">申请中</font>\n                                            </c:when>\n                                            <c:when test=\"${appDetail.appDesc.status == 2}\">\n                                                                                                                        运行中\n                                            </c:when>\n                                            <c:when test=\"${appDetail.appDesc.status == 3}\">\n                                                <font color=\"red\">已下线</font>\n                                            </c:when>\n                                            <c:when test=\"${appDetail.appDesc.status == 4}\">\n                                                <font color=\"red\">驳回</font>\n                                            </c:when>\n                                        </c:choose>\n                                    </td>\n                                    <td>\n                                        <c:choose>\n                                            <c:when test=\"${appDetail.appDesc.status == 2}\">\n                                                <button type=\"button\" class=\"btn btn-small btn-primary\" id=\"offline${appDetail.appDesc.appId}\"\n                                                        onclick=\"offLine(${appDetail.appDesc.appId})\">应用下线\n                                                </button>\n                                                \n                                                <a target=\"_blank\" type=\"button\" class=\"btn btn-small btn-primary\" href=\"/manage/app/index.do?appId=${appDetail.appDesc.appId}\">应用运维</a>\n                                                \n                                            </c:when>\n                                        </c:choose>\n                                    </td>\n                                </tr>\n                            </c:forEach>\n                            </tbody>\n                        </table>\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>\n<script type=\"text/javascript\">\n    function offLine(appId) {\n    \tif(confirm(\"确认要下线该应用？应用id=\"+appId)){\n            $.ajax({\n                type: \"get\",\n                url: \"/manage/app/offLine.json\",\n                data: {appId: appId},\n                success: function (result) {\n                    alert(result.msg);\n                    window.location.reload();\n                }\n            });\n        }\n    }\n</script>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/user/addUser.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\" pageEncoding=\"UTF-8\"%>\n<div id=\"addUserModal${user.id}\" class=\"modal fade\" tabindex=\"-1\" data-width=\"400\">\n\t<div class=\"modal-dialog\">\n\t\t<div class=\"modal-content\">\n\t\t\n\t\t\t<div class=\"modal-header\">\n\t\t\t\t<button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\"></button>\n\t\t\t\t<h4 class=\"modal-title\">管理用户</h4>\n\t\t\t</div>\n\t\t\t\n\t\t\t<form class=\"form-horizontal form-bordered form-row-stripped\">\n\t\t\t\t<div class=\"modal-body\">\n\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t<!-- 控件开始 -->\n\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t<!-- form-body开始 -->\n\t\t\t\t\t\t\t<div class=\"form-body\">\n\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t域账户名:\n\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"name\" id=\"name${user.id}\"\n\t\t\t\t\t\t\t\t\t\t\tvalue=\"${user.name}\" placeholder=\"域账户名(邮箱前缀)\"\n\t\t\t\t\t\t\t\t\t\t\tclass=\"form-control\" />\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t中文名:\n\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"chName\" id=\"chName${user.id}\"\n\t\t\t\t\t\t\t\t\t\t\tvalue=\"${user.chName}\" placeholder=\"中文名\"\n\t\t\t\t\t\t\t\t\t\t\tclass=\"form-control\" />\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t邮箱:\n\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"email\" id=\"email${user.id}\"\n\t\t\t\t\t\t\t\t\t\t\tvalue=\"${user.email}\" placeholder=\"邮箱\"\n\t\t\t\t\t\t\t\t\t\t\tclass=\"form-control\" />\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t手机:\n\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"mobile\" id=\"mobile${user.id}\"\n\t\t\t\t\t\t\t\t\t\t\tvalue=\"${user.mobile}\" placeholder=\"手机\"\n\t\t\t\t\t\t\t\t\t\t\tclass=\"form-control\" />\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t类型:\n\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t<select name=\"type\" id=\"type${user.id}\" class=\"form-control select2_category\">\n\t\t\t\t\t\t\t\t\t\t\t<option value=\"0\" <c:if test=\"${user.type == 0}\">selected=\"selected\"</c:if>>\n\t\t\t\t\t\t\t\t\t\t\t\t管理员\n\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t<option value=\"2\" <c:if test=\"${user.type == 2}\">selected=\"selected\"</c:if>>\n\t\t\t\t\t\t\t\t\t\t\t\t普通用户\n\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<input type=\"hidden\" id=\"userId${user.id}\" name=\"userId\" value=\"${user.id}\"/>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<!-- form-body 结束 -->\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div id=\"info${user.id}\"></div>\n\t\t\t\t\t\t<!-- 控件结束 -->\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t\n\t\t\t\t<div class=\"modal-footer\">\n\t\t\t\t\t<button type=\"button\" data-dismiss=\"modal\" class=\"btn\" >Close</button>\n\t\t\t\t\t<button type=\"button\" id=\"userBtn${user.id}\" class=\"btn red\" onclick=\"saveOrUpdateUser('${user.id}')\">Ok</button>\n\t\t\t\t</div>\n\t\t\t\n\t\t\t</form>\n\t\t</div>\n\t</div>\n</div>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/user/initUser.jsp",
    "content": ""
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/user/list.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\"\n    pageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n\t<title>CacheCloud管理后台</title>\n\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n\t\n\t<%@include file=\"/WEB-INF/jsp/manage/include/cache_cloud_main_css.jsp\" %>\n\n</head>\n\n<body class=\"page-header-fixed\">\n\t<%@include file=\"/WEB-INF/jsp/manage/include/head.jsp\" %>\n\n\t<%@include file=\"/WEB-INF/jsp/manage/include/left.jsp\" %>\n\n\t<%@include file=\"userList.jsp\" %>\n\t\n\t<%@include file=\"addUser.jsp\" %>\n\t\n\t<%@include file=\"/WEB-INF/jsp/manage/include/foot.jsp\" %>\n\n\t<%@include file=\"/WEB-INF/jsp/manage/include/cache_cloud_main_js.jsp\" %>\n\t\n</body>\n</html>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/manage/user/userList.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\" pageEncoding=\"UTF-8\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<div class=\"page-container\">\n\t<div class=\"page-content\">\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-md-12\">\n\t\t\t\t<h3 class=\"page-title\">\n\t\t\t\t\t用户管理\n\t\t\t\t</h3>\n\t\t\t</div>\n\t\t</div>\n\t\t<div class=\"row\">\n\t\t\t<div class=\"col-md-12\">\n\t\t\t\t<div class=\"portlet box light-grey\">\n\t\t\t\t\t<div class=\"portlet-title\">\n\t\t\t\t\t\t<div class=\"caption\"><i class=\"fa fa-globe\"></i>用户列表</div>\n\t\t\t\t\t\t<div class=\"tools\">\n\t\t\t\t\t\t\t<a href=\"javascript:;\" class=\"collapse\"></a>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"portlet-body\">\n\t\t\t\t\t\t<div class=\"table-toolbar\">\n\t\t\t\t\t\t\t<div class=\"btn-group\">\n\t\t\t\t\t\t\t\t<button id=\"sample_editable_1_new\" class=\"btn green\" data-target=\"#addUserModal\" data-toggle=\"modal\">\n\t\t\t\t\t\t\t\t添加新用户 <i class=\"fa fa-plus\"></i>\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div class=\"btn-group\" style=\"float:right\">\n\t\t\t\t\t\t\t\t<form action=\"/manage/user/list.do\" method=\"post\" class=\"form-horizontal form-bordered form-row-stripped\">\n\t\t\t\t\t\t\t\t\t<label class=\"control-label\">\n\t\t\t\t\t\t\t\t\t\t用户名:\n\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t&nbsp;<input type=\"text\" name=\"searchChName\" id=\"searchChName\" value=\"${searchChName}\" placeholder=\"中文名\"/>\n\t\t\t\t\t\t\t\t\t&nbsp;<button type=\"submit\" class=\"btn blue btn-sm\">查询</button>\n\t\t\t\t\t\t\t\t</form>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<table class=\"table table-striped table-bordered table-hover\" id=\"tableDataList\">\n\t\t\t\t\t\t\t<thead>\n\t\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t\t<th>id</th>\n\t\t\t\t\t\t\t\t\t<th>域账户</th>\n\t\t\t\t\t\t\t\t\t<th>中文名</th>\n\t\t\t\t\t\t\t\t\t<th>邮箱</th>\n\t\t\t\t\t\t\t\t\t<th>手机</th>\n\t\t\t\t\t\t\t\t\t<th>类型</th>\n\t\t\t\t\t\t\t\t\t<th>操作</th>\n\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t</thead>\n\t\t\t\t\t\t\t<tbody>\n\t\t\t\t\t\t\t\t<c:forEach items=\"${users}\" var=\"user\">\n\t\t\t\t\t\t\t\t\t<tr class=\"odd gradeX\">\n\t\t\t\t\t\t\t\t\t\t<td>${user.id}</td>\n\t\t\t\t\t\t\t\t\t\t<td>${user.name}</td>\n\t\t\t\t\t\t\t\t\t\t<td>${user.chName}</td>\n\t\t\t\t\t\t\t\t\t\t<td>${user.email}</td>\n\t\t\t\t\t\t\t\t\t\t<td>${user.mobile}</td>\n\t\t\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t\t\t<c:choose>\n\t\t\t\t\t\t\t\t\t\t\t\t<c:when test=\"${user.type == 0 }\">管理员</c:when>\n\t\t\t\t\t\t\t\t\t\t\t\t<c:when test=\"${user.type == 2 }\">普通用户</c:when>\n\t\t\t\t\t\t\t\t\t\t\t</c:choose>\n\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t\t<a href=\"javascript;\" data-target=\"#addUserModal${user.id}\" data-toggle=\"modal\">[修改]</a>\n\t\t\t\t\t\t\t\t\t\t&nbsp;\n\t\t\t\t\t\t\t\t\t\t<a onclick=\"if(window.confirm('确认要删除该用户吗?!')){return true;}else{return false;}\" href=\"/manage/user/delete.do?userId=${user.id}\">[删除]</a>\n\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t\t</c:forEach>\n\t\t\t\t\t\t\t</tbody>\n\t\t\t\t\t\t</table>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n\n\n<c:forEach items=\"${users}\" var=\"user\">\n\t<%@include file=\"addUser.jsp\" %>\n</c:forEach>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/migrate/checkData.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n\t<title>采样校验源数据和目标数据</title>\n</head>\n\t<body STYLE=\"BACKGROUND-COLOR:#000;color:#FFF\">\n\t\t<c:forEach items=\"${checkDataResultList}\" var=\"line\">\n\t\t\t<font color=\"white\">${line}</font><br/>\n\t\t</c:forEach>\n\t\t<br/>\n\t\t如果发现不一致的情况，可以在目标机器执行${checkDataCommand}来看一下详细的key不一致情况\n\t</body>\n</html>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/migrate/config.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n\t<title>迁移配置</title>\n</head>\n\t<body STYLE=\"BACKGROUND-COLOR:#000;color:#FFF\">\n\t\t<c:forEach items=\"${configList}\" var=\"line\">\n\t\t\t<font color=\"white\">${line}</font><br/>\n\t\t</c:forEach>\n\t</body>\n</html>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/migrate/init.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <title>迁移数据</title>\n    <jsp:include page=\"/WEB-INF/include/head.jsp\"/>\n    <script type=\"text/javascript\" src=\"/resources/js/myPopover.js\"></script>\n    <script type=\"text/javascript\">\n    \n    \tfunction changeDataType(appIdId,serversId, choose) {\n    \t\tvar dataType = choose.options[choose.selectedIndex].value;\n    \t\tvar appId = document.getElementById(appIdId);\n    \t\tvar servers = document.getElementById(serversId);\n    \t\tif (dataType == 0) {\n    \t\t\tappId.disabled = true;\n    \t\t\tservers.disabled = false;\n    \t\t} else if(dataType == 1) {\n    \t\t\tappId.disabled = false;\n    \t\t\tservers.disabled = true;\n    \t\t}\n    \t}\n    \t\n    \tfunction fillAppInstanceList(instanceDetailId,redisMigrateIndexId,appIdInputId) {\n    \t\tvar appId = document.getElementById(appIdInputId).value;\n    \t\tif (appId == \"\") {\n    \t\t\t//不能为空\n    \t\t\treturn;\n    \t\t}\n    \t\tvar instanceDetail = document.getElementById(instanceDetailId);\n    \t\t$.get(\n       \t\t\t'/data/migrate/appInstanceList.json',\n       \t\t\t{\n       \t\t\t\tappId: appId,\n       \t\t\t},\n       \t        function(data){\n       \t\t\t\tvar instances = data.instances;\n       \t\t\t\tinstanceDetail.value = instances;\n       \t\t\t\t\n       \t\t\t\tvar appType = data.appType;\n       \t\t\t\tvar redisMigrateIndex = document.getElementById(redisMigrateIndexId);\n       \t\t\t\t//修改select\n       \t\t\t\tif (appType == 2) {\n       \t\t\t\t\tvar options = redisMigrateIndex.options;\n       \t\t\t\t\tfor(var i = 0;i < options.length; i++){\n       \t\t\t\t\t\tif (1 == options[i].value){\n       \t\t\t\t\t\t\toptions[i].selected = 'selected';\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} else if(appType == 5 || appType == 6) {\n       \t\t\t\t\tvar options = redisMigrateIndex.options;\n       \t\t\t\t\tfor(var i = 0;i < options.length; i++){\n       \t\t\t\t\t\tif (0 == options[i].value){\n       \t\t\t\t\t\t\toptions[i].selected = 'selected';\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\t\n       \t        }\n       \t     );\n    \t\t\n    \t}\n    \n    \tfunction checkMigrateFormat() {\n    \t\tvar sourceRedisMigrateIndex = document.getElementById(\"sourceRedisMigrateIndex\").value;\n    \t\tvar targetRedisMigrateIndex = document.getElementById(\"targetRedisMigrateIndex\").value;\n    \t\tvar sourceServers = document.getElementById(\"sourceServers\");\n    \t\tvar sourceAppId = document.getElementById(\"sourceAppId\");\n    \t\tvar sourceDataType = document.getElementById(\"sourceDataType\").value;\n    \t\tvar migrateMachineIp = document.getElementById(\"migrateMachineIp\").value;\n    \t\tvar redisSourcePass = document.getElementById(\"redisSourcePass\");\n    \t\tvar redisTargetPass = document.getElementById(\"redisTargetPass\");\n\n    \t\t\n\t\t\t//非cachecloud\n    \t\tif (sourceDataType == 0 && sourceServers.value == \"\") {\n   \t\t\t\talert(\"源实例信息不能为空!\");\n   \t\t\t\tsourceServers.focus();\n   \t\t\t\treturn false;\n    \t\t//cachecloud\n    \t\t} else if(sourceDataType == 1 && sourceAppId.value == \"\") {\n   \t\t\t\talert(\"源appId不能为空!\");\n   \t\t\t\tsourceAppId.focus();\n   \t\t\t\treturn false;\n    \t\t} else if(sourceDataType == 1 && sourceServers.value == \"\") {\n   \t\t\t\talert(\"请确保appId=\" + sourceAppId.value + \"下有实例信息\");\n   \t\t\t\tsourceAppId.focus();\n   \t\t\t\treturn false;\n    \t\t}\n    \t\t\n    \t\tvar targetAppId = document.getElementById(\"targetAppId\");\n    \t\tvar targetServers = document.getElementById(\"targetServers\");\n    \t\tvar targetDataType = document.getElementById(\"targetDataType\").value;\n\t\t\t//非cachecloud\n    \t\tif(targetDataType == 1 && targetAppId.value == \"\") {\n   \t\t\t\talert(\"目标appId不能为空!\");\n   \t\t\t\ttargetAppId.focus();\n   \t\t\t\treturn false;\n    \t\t} else if(targetDataType == 1 && targetServers.value == \"\") {\n   \t\t\t\talert(\"请确保appId=\" + targetAppId.value + \"下有实例信息\");\n   \t\t\t\ttargetAppId.focus();\n   \t\t\t\treturn false;\n    \t\t}\n    \t\t\n    \t\t$.get(\n    \t\t\t'/data/migrate/check.json',\n    \t\t\t{\n    \t\t\t\tsourceRedisMigrateIndex: sourceRedisMigrateIndex,\n    \t\t\t\ttargetRedisMigrateIndex: targetRedisMigrateIndex,\n    \t\t\t\tsourceServers:sourceServers.value,\n    \t\t\t\ttargetServers:targetServers.value,\n    \t\t\t\tmigrateMachineIp:migrateMachineIp,\n    \t\t\t\tredisSourcePass:redisSourcePass.value,\n    \t\t\t\tredisTargetPass:redisTargetPass.value\n    \t\t\t},\n    \t        function(data){\n    \t\t\t\tvar status = data.status;\n    \t\t\t\talert(data.message);\n    \t\t\t\tif (status == 1) {\n    \t\t\t\t\tvar submitButton = document.getElementById(\"submitButton\");\n    \t\t    \t\tsubmitButton.disabled = false;\n    \t\t    \t\t\n    \t\t    \t\tvar checkButton = document.getElementById(\"checkButton\");\n    \t\t    \t\tcheckButton.disabled = true;\n    \t\t\t\t}\n    \t        }\n    \t     );\n    \t}\n    \t\n    \tfunction startMigrate() {\n    \t\tvar sourceRedisMigrateIndex = document.getElementById(\"sourceRedisMigrateIndex\").value;\n    \t\tvar targetRedisMigrateIndex = document.getElementById(\"targetRedisMigrateIndex\").value;\n    \t\tvar sourceServers = document.getElementById(\"sourceServers\");\n    \t\tvar targetServers = document.getElementById(\"targetServers\");\n    \t\tvar migrateMachineIp = document.getElementById(\"migrateMachineIp\").value;\n    \t\tvar sourceAppId = document.getElementById(\"sourceAppId\");\n    \t\tvar targetAppId = document.getElementById(\"targetAppId\");\n    \t\tvar redisSourcePass = document.getElementById(\"redisSourcePass\");\n    \t\tvar redisTargetPass = document.getElementById(\"redisTargetPass\");\n\n    \t\t$.get(\n    \t\t\t'/data/migrate/start.json',\n    \t\t\t{\n    \t\t\t\tsourceRedisMigrateIndex: sourceRedisMigrateIndex,\n    \t\t\t\ttargetRedisMigrateIndex: targetRedisMigrateIndex,\n    \t\t\t\tsourceServers: sourceServers.value,\n    \t\t\t\ttargetServers: targetServers.value,\n    \t\t\t\tmigrateMachineIp: migrateMachineIp,\n    \t\t\t\tsourceAppId: sourceAppId.value,\n    \t\t\t\ttargetAppId: targetAppId.value,\n    \t\t\t\tredisSourcePass: redisSourcePass.value,\n    \t\t\t\tredisTargetPass:redisTargetPass.value\n    \t\t\t},\n    \t        function(data){\n    \t\t\t\tvar status = data.status;\n    \t\t\t\tif (status == 1) {\n    \t\t\t\t\talert(\"迁移程序已经启动，请返回迁移列表关注迁移进度!\");\n    \t\t\t\t\tlocation.href = \"/data/migrate/list\";\n    \t\t\t\t} else {\n    \t\t\t\t\talert(\"迁移失败,请查看日志分析原因!\");\n    \t\t\t\t}\n\t\t    \t\t\n\t\t    \t\tvar checkButton = document.getElementById(\"checkButton\");\n\t\t    \t\tcheckButton.disabled = true;\n    \t        }\n    \t     );\n    \t}\n    \t\n    </script>\n    \n</head>\n<body role=\"document\">\n\t<div class=\"container\">\n\t    <jsp:include page=\"/WEB-INF/include/headMenu.jsp\"/>\n\t    <div id=\"systemAlert\">\n\t    </div>\n\t\t<div class=\"page-content\">\n\t\t\t<div class=\"portlet box light-grey\">\n\t\t\t\t<div class=\"portlet-body\">\n\t\t\t\t\t<div class=\"form\">\n\t\t\t\t\t\t<form action=\"\" method=\"post\"\n\t\t\t\t\t\t\tclass=\"form-horizontal form-bordered form-row-stripped\">\n\t\t\t\t\t\t\t<div class=\"form-body\">\n\t\t\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t\t\t\t<h4 class=\"page-header\">\n\t\t\t\t\t\t\t\t\t\t\t迁移工具配置\n\t\t\t\t\t\t\t\t\t\t\t<button class=\"btn btn-success btn-sm\" \n\t\t\t\t\t\t\t\t\t\t      data-container=\"body\" data-toggle=\"popover\" data-placement=\"top\" \n\t\t\t\t\t\t\t\t\t\t      data-content=\"<a href='http://cachecloud.github.io/2016/06/28/1.2.%20%E8%BF%81%E7%A7%BB%E5%B7%A5%E5%85%B7%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E/'>使用文档</a>\" style=\"border-radius:100%\">\n\t\t\t\t\t\t\t\t\t\t      ?\n\t\t\t\t\t\t\t\t\t\t   </button>\n\t\t\t\t\t\t\t\t\t\t</h4>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-6\">\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t迁移工具机器:\n\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<select id=\"migrateMachineIp\" name=\"migrateMachineIp\" class=\"form-control select2_category\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<c:forEach items=\"${machineInfoList}\" var=\"machineInfo\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"${machineInfo.ip}\">\n\t                                                            ${machineInfo.ip}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</c:forEach>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t\t\t\t<h4 class=\"page-header\">\n\t\t\t\t\t\t\t\t\t\t\t源和目标配置\n\t\t\t\t\t\t\t\t\t\t</h4>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-6\">\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t源类型:\n\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<select id=\"sourceRedisMigrateIndex\" name=\"sourceRedisMigrateIndex\" class=\"form-control select2_category\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tRedis普通节点\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"1\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tRedis-cluster\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"2\">\n                                                            RDB-file\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"4\">\n                                                            AOF-file\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-6\">\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t目标类型:\n\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<select id=\"targetRedisMigrateIndex\" name=\"targetRedisMigrateIndex\" class=\"form-control select2_category\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tRedis普通节点\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"1\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tRedis-cluster\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"2\">\n                                                            RDB-file\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-6\">\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t数据源:\n\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<select id=\"sourceDataType\" name=\"sourceDataType\" class=\"form-control select2_category\" onchange=\"changeDataType('sourceAppId','sourceServers',this)\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"0\" selected=\"selected\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t非cachecloud\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"1\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcachecloud\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-6\">\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t数据源:\n\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<select id=\"targetDataType\" name=\"targetDataType\" class=\"form-control select2_category\" onchange=\"changeDataType('targetAppId','targetServers',this)\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"1\" selected=\"selected\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcachecloud\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t非cachecloud\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-6\">\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\" id=\"sourceAppIdDiv\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t源appId:\n\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<input disabled=\"disabled\" type=\"text\" id=\"sourceAppId\" class=\"form-control\" onchange=\"fillAppInstanceList('sourceServers', 'sourceRedisMigrateIndex',this.id)\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-6\">\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\" id=\"targetAppIdDiv\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t目标appId:\n\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" id=\"targetAppId\" class=\"form-control\"  onchange=\"fillAppInstanceList('targetServers', 'targetRedisMigrateIndex',this.id)\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-6\">\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t源密码:\n\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" id=\"redisSourcePass\" name=\"redisSourcePass\" placeholder=\"没有无需填写\" class=\"form-control\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-6\">\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t目标密码:\n\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" id=\"redisTargetPass\" name=\"redisTargetPass\" placeholder=\"没有无需填写\" class=\"form-control\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-6\">\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\" id=\"sourceServersDiv\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t源实例详情:\n\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-8\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<textarea rows=\"10\" name=\"sourceServers\" id=\"sourceServers\" placeholder=\"节点详情\" class=\"form-control\"></textarea>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"help-block\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t每行格式都是:&nbsp;&nbsp;ip:port(例如：10.10.xx.xx:6379)<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t1. standalone类型：<br/> \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&nbsp;&nbsp;&nbsp;&nbsp;masterIp:masterPort<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t2. sentinel类型：<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&nbsp;&nbsp;&nbsp;&nbsp;masterIp:masterPort<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t3. cluster类型：<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&nbsp;&nbsp;&nbsp;&nbsp;masterIp1:masterPort1<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&nbsp;&nbsp;&nbsp;&nbsp;slaveIp1:slavePort1<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&nbsp;&nbsp;&nbsp;&nbsp;masterIp2:masterPort2<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&nbsp;&nbsp;&nbsp;&nbsp;slaveIp2:slavePort2<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t(可以是多对主从，只要把所有的cluster节点都按照格式写就可以，程序会自动判断)<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-6\">\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\" id=\"targetServersDiv\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t目标实例详情:\n\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-8\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<textarea disabled=\"disabled\" rows=\"10\" name=\"targetServers\" id=\"targetServers\" placeholder=\"节点详情\" class=\"form-control\"></textarea>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"help-block\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t每行格式都是:&nbsp;&nbsp;ip:port(例如：10.10.xx.xx:6379)<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t1. standalone类型：<br/> \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&nbsp;&nbsp;&nbsp;&nbsp;masterIp:masterPort<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t2. sentinel类型：<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&nbsp;&nbsp;&nbsp;&nbsp;masterIp:masterPort<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t3. cluster类型：<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&nbsp;&nbsp;&nbsp;&nbsp;masterIp1:masterPort1<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&nbsp;&nbsp;&nbsp;&nbsp;slaveIp1:slavePort1<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&nbsp;&nbsp;&nbsp;&nbsp;masterIp2:masterPort2<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&nbsp;&nbsp;&nbsp;&nbsp;slaveIp2:slavePort2<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t(可以是多对主从，只要把所有的cluster节点都按照格式写就可以，程序会自动判断)<br/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t<div class=\"form-actions fluid\">\n\t\t\t\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-offset-5 col-md-9\">\n\t\t\t\t\t\t\t\t\t\t\t\t<button id=\"submitButton\" type=\"button\" onclick=\"startMigrate()\" class=\"btn green\" disabled=\"disabled\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-check\"></i>\n\t\t\t\t\t\t\t\t\t\t\t\t\t开始迁移\n\t\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t\t\t<button id=\"checkButton\" type=\"button\" class=\"btn green\" onclick=\"checkMigrateFormat()\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-check\"></i>\n\t\t\t\t\t\t\t\t\t\t\t\t\t检查格式\n\t\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</form>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t<br/><br/><br/><br/><br/><br/><br/>\n\t<jsp:include page=\"/WEB-INF/include/foot.jsp\"/>\n</body>\n</html>\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/migrate/list.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <title>迁移数据记录列表</title>\n    <jsp:include page=\"/WEB-INF/include/head.jsp\"/>\n    <script type=\"text/javascript\">\n    \tfunction stopMigrate(id) {\n    \t\tif(window.confirm(\"确认要停掉id=\"+id+\"的迁移任务吗?\")) {\n    \t\t\t$.get(\n \t       \t\t\t'/data/migrate/stop.json',\n \t       \t\t\t{\n \t       \t\t\t\tid: id,\n \t       \t\t\t},\n \t       \t        function(data){\n \t       \t\t\t\tvar status = data.status;\n \t       \t\t\t\talert(data.message);\n\t    \t\t\t\tlocation.href = \"/data/migrate/list\";\n \t       \t        }\n \t       \t     );\n    \t\t}\n    \t}\n    </script>\n</head>\n<body role=\"document\">\n\t<div class=\"container\">\n\t    <jsp:include page=\"/WEB-INF/include/headMenu.jsp\"/>\n\t    <div id=\"systemAlert\">\n\t    </div>\n\t    \n\t    <div class=\"row\">\n        <div class=\"col-md-12\">\n        \t<form method=\"post\" action=\"/data/migrate/list\">\n\t\t\t\t<div style=\"float:right\">\n\t\t\t\t\t\t<label style=\"font-weight:bold;text-align:left;\">\n\t\t\t\t\t\t \t源appId:\n\t\t\t\t\t\t</label>\n\t\t\t\t\t\t<input type=\"text\" value=\"${appDataMigrateSearch.sourceAppId}\" name=\"sourceAppId\" size=\"4\">\n\t\t\t\t\t\t\n\t\t\t\t\t\t<label style=\"font-weight:bold;text-align:left;\">\n\t\t\t\t\t\t \t目标appId:\n\t\t\t\t\t\t</label>\n\t\t\t\t\t\t<input type=\"text\" value=\"${appDataMigrateSearch.targetAppId}\" name=\"targetAppId\" size=\"4\">\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t<label style=\"font-weight:bold;text-align:left;\">\n\t\t\t\t\t\t \t源实例ip:\n\t\t\t\t\t\t</label>\n\t\t\t\t\t\t<input type=\"text\" value=\"${appDataMigrateSearch.sourceInstanceIp}\" name=\"sourceInstanceIp\" size=\"9\">\n\t\t\t\t\t\t\n\t\t\t\t\t\t<label style=\"font-weight:bold;text-align:left;\">\n\t\t\t\t\t\t \t目标实例ip:\n\t\t\t\t\t\t</label>\n\t\t\t\t\t\t<input type=\"text\" value=\"${appDataMigrateSearch.targetInstanceIp}\" name=\"targetInstanceIp\" size=\"9\">\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t<label style=\"font-weight:bold;text-align:left;\">\n\t\t\t\t\t\t \t&nbsp;开始日期:&nbsp;&nbsp;\n\t\t\t\t\t\t</label>\n\t\t\t\t\t\t<input type=\"text\" size=\"9\" name=\"startDate\" id=\"startDate\" value=\"${appDataMigrateSearch.startDate}\" onFocus=\"WdatePicker({startDate:'%y-%M-01',dateFmt:'yyyy-MM-dd',alwaysUseStartDate:true})\"/>\n\t\t\t\t\t\t\n\t\t\t\t\t\t<label style=\"font-weight:bold;text-align:left;\">\n\t\t\t\t\t\t \t结束日期:\n\t\t\t\t\t\t</label>\n\t\t\t\t\t\t<input type=\"text\" size=\"9\" name=\"endDate\" id=\"endDate\" value=\"${appDataMigrateSearch.endDate}\" onFocus=\"WdatePicker({startDate:'%y-%M-01',dateFmt:'yyyy-MM-dd',alwaysUseStartDate:true})\"/>\n\t\t\t\t\t\t\n\t\t\t\t\t\t<label style=\"font-weight:bold;text-align:left;\">\n\t\t\t\t\t\t \t状态:\n\t\t\t\t\t\t</label>\n\t\t\t\t\t\t<select name=\"status\">\n\t\t\t\t\t\t\t<option value=\"-2\">\n\t\t\t\t\t\t\t\t全部\n\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t<option value=\"0\" <c:if test=\"${appDataMigrateSearch.status == 0}\">selected</c:if>>\n\t\t\t\t\t\t\t\t开始\n\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t<option value=\"1\" <c:if test=\"${appDataMigrateSearch.status == 1}\">selected</c:if>>\n\t\t\t\t\t\t\t\t结束\n\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\n\t\t\t\t\t\t<label>&nbsp;<input type=\"submit\" class=\"btn-4\" value=\"查询\"/></label>\n\t\t\t\t</div>\n\t\t\t</form>\n        </div>\n    </div>\n\t    \n\t    <div class=\"row\">\n\t        <div class=\"col-md-12\">\n\t            <div class=\"page-header\">\n\t                <h4>\n\t                \t迁移数据记录列表\n\t                \t<a target=\"_blank\" href=\"/data/migrate/init\" class=\"btn btn-info btn-success\" role=\"button\">添加新的迁移</a>\n\t                </h4>\n\t            </div>\n\t\t\t</div>\n\t\t</div>\n\t\t<div class=\"row\">\n\t\t\t<br/>\n\t\t\t<div class=\"col-md-12\">\n\t            <table class=\"table table-bordered table-striped table-hover\" style=\"margin-top: 0px\">\n\t                <thead>\n\t\t                <tr>\n\t\t                    <th>id</th>\n\t\t                    <th>迁移工具</th>\n\t\t                    <th>源数据</th>\n\t\t                    <th>目标数据</th>\n\t\t                    <th>操作人</th>\n\t\t                    <th>开始时间</th>\n\t\t                    <th>结束时间</th>\n\t\t                    <th>状态</th>\n\t\t                    <th>查看</th>\n\t\t                    <th>操作</th>\n\t\t                    <th>校验数据</th>\n\t\t                </tr>\n\t                </thead>\n\t                <tbody>\n\t                \t<c:forEach items=\"${appDataMigrateStatusList}\" var=\"appDataMigrateStatus\">\n\t                \t\t <tr>\n\t\t\t                    <td>${appDataMigrateStatus.id}</td>\n\t\t\t                    <td>${appDataMigrateStatus.migrateMachineIp}:${appDataMigrateStatus.migrateMachinePort}</td>\n\t\t\t                    <td>\n\t\t\t                    \t<c:choose>\n\t\t\t                    \t\t<c:when test=\"${appDataMigrateStatus.sourceAppId <= 0}\">\n\t\t\t                    \t\t\t非cachecloud\n\t\t\t                    \t\t</c:when>\n\t\t\t                    \t\t<c:otherwise>\n\t\t\t                    \t\t\tcachecloud:<a target=\"_blank\" href=\"/admin/app/index.do?appId=${appDataMigrateStatus.sourceAppId}\">${appDataMigrateStatus.sourceAppId}</a>\n\t\t\t                    \t\t</c:otherwise>\n\t\t\t                    \t</c:choose>\n\t\t\t                    \t<br/>\n\t\t\t                    \t${appDataMigrateStatus.sourceServers}<br/>\n\t\t\t                    \t${appDataMigrateStatus.sourceMigrateTypeDesc}\n\t\t\t                    </td>\n\t\t\t                    <td>\n\t\t\t                    \t<c:choose>\n\t\t\t                    \t\t<c:when test=\"${appDataMigrateStatus.targetAppId <= 0}\">\n\t\t\t                    \t\t\t非cachecloud\n\t\t\t                    \t\t</c:when>\n\t\t\t                    \t\t<c:otherwise>\n\t\t\t                    \t\t\tcachecloud:<a target=\"_blank\" href=\"/admin/app/index.do?appId=${appDataMigrateStatus.targetAppId}\">${appDataMigrateStatus.targetAppId}</a>\n\t\t\t                    \t\t</c:otherwise>\n\t\t\t                    \t</c:choose>\n\t\t\t                    \t<br/>\n\t\t\t                    \t${appDataMigrateStatus.targetServers}<br/>\n\t\t\t                    \t${appDataMigrateStatus.targetMigrateTypeDesc}\n\t\t\t                    </td>\n\t\t\t                    <td>${appDataMigrateStatus.userId}</td>\n   \t\t\t                    <td>${appDataMigrateStatus.startTimeFormat}</td>\n   \t\t\t                    <td>${appDataMigrateStatus.endTimeFormat}</td>\n   \t\t\t                    <td>${appDataMigrateStatus.statusDesc}</td>\n   \t\t\t                    <td>\n   \t\t\t                        <a target=\"_blank\" href=\"/data/migrate/log?id=${appDataMigrateStatus.id}\">日志|</a>\n   \t\t\t                        <a target=\"_blank\" href=\"/data/migrate/config?id=${appDataMigrateStatus.id}\">配置|</a>\n   \t\t\t                        <c:choose>\n   \t\t\t                        \t<c:when test=\"${appDataMigrateStatus.status == 1}\">\n   \t\t\t                        \t\t进度\n   \t\t\t                        \t</c:when>\n   \t\t\t                        \t<c:otherwise>\n   \t\t\t                       \t\t\t<a target=\"_blank\" href=\"/data/migrate/process?id=${appDataMigrateStatus.id}\">进度</a>\n   \t\t\t                        \t</c:otherwise>\n   \t\t\t                        </c:choose>\n   \t\t\t                    </td>\n   \t\t\t                    <td>\n\t                                <button <c:if test='${appDataMigrateStatus.status == 1}'>disabled=\"disabled\"</c:if> onclick=\"stopMigrate(${appDataMigrateStatus.id})\" type=\"button\" class=\"btn btn-info\">停止</button>               \n   \t\t\t                    </td>\n   \t\t\t                    <td>\n   \t\t\t                    \t<c:choose>\n   \t\t\t                        \t<c:when test=\"${appDataMigrateStatus.status == 1}\">\n\t                                \t\t<button disabled=\"disabled\" type=\"button\" class=\"btn btn-info\">采样校验</button>               \n   \t\t\t                        \t</c:when>\n   \t\t\t                        \t<c:otherwise>\n   \t\t\t                    \t\t\t<a target=\"_blank\" href=\"/data/migrate/checkData?id=${appDataMigrateStatus.id}\" class=\"btn btn-info\" role=\"button\">采样校验</a>\n   \t\t\t                        \t</c:otherwise>\n   \t\t\t                        </c:choose>\n   \t\t\t                    </td>\n\t\t\t                </tr>\n\t                \t</c:forEach>\n\t                </tbody>\n\t            </table>\n            </div>\n        </div>\n\t    \n\t    \n\t</div>\n\t<br/><br/><br/><br/><br/><br/><br/>\n\t<jsp:include page=\"/WEB-INF/include/foot.jsp\"/>\n</body>\n</html>\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/migrate/log.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n\t<title>迁移日志</title>\n</head>\n\t<body STYLE=\"BACKGROUND-COLOR:#000;color:#FFF\">\n\t\t<c:forEach items=\"${logList}\" var=\"line\">\n\t\t\t<font color=\"white\">${line}</font><br/>\n\t\t</c:forEach>\n\t</body>\n</html>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/migrate/process.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <title>迁移工具执行状态</title>\n    <jsp:include page=\"/WEB-INF/include/head.jsp\"/>\n    <script type=\"text/javascript\">\n    \n    </script>\n    \n</head>\n<body role=\"document\">\n\t<div class=\"container\">\n\t    <jsp:include page=\"/WEB-INF/include/headMenu.jsp\"/>\n\t    <div id=\"systemAlert\">\n\t    </div>\n\t    \n\t    <div class=\"row\">\n\t        <div class=\"col-md-12\">\n\t            <div class=\"page-header\">\n\t                <h3>迁移工具执行状态</h3>\n\t            </div>\n\t\t\t</div>\n\t\t</div>\n\t\t<div class=\"row\">\n\t\t\t<c:forEach items=\"${migrateToolStatMap}\" var=\"entry\">\n\t\t\t\t<div class=\"col-md-12\">\n\t\t            <div class=\"page-header\">\n\t\t                <h4>${entry.key}</h4>\n\t\t            </div>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col-md-12\">\n\t\t            <table class=\"table table-striped table-hover\" style=\"margin-top: 0px\">\n\t\t                <thead>\n\t\t\t                <tr>\n\t\t\t                    <td>key</td>\n\t\t\t                    <td>value</td>\n\t\t\t                </tr>\n\t\t                </thead>\n\t\t                <tbody>\n\t\t                \t<c:forEach items=\"${entry.value}\" var=\"entry2\">\n\t\t                \t\t <tr>\n\t\t\t\t                    <td>${entry2.key}</td>\n\t\t\t\t                    <td>${entry2.value}</td>\n\t\t\t\t                </tr>\n\t\t                \t</c:forEach>\n\t\t                </tbody>\n\t\t            </table>\n\t            </div>\n\t\t\t</c:forEach>\n        </div>\n\t    \n\t</div>\n\t<br/><br/><br/><br/><br/><br/><br/>\n\t<jsp:include page=\"/WEB-INF/include/foot.jsp\"/>\n</body>\n</html>\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/server/cpu.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<c:if test=\"${empty cpu}\">\n\tno data\n</c:if>\n<c:forEach items=\"${cpu}\" var=\"item\" varStatus=\"stat\">\n\t<div class=\"col-md-6\">\n\t\t<div id=\"container${item.name}\"\n\t\t\tstyle=\"min-width: 310px; height: 400px; margin: 0 auto\"></div>\n\t</div>\n</c:forEach>\n\t\n<script type=\"text/javascript\">\n\t$(document).ready(function() {\n\t\tinitSubCpuChart();\n\t});\n\t\n\tfunction initSubCpuChart(){\n\t\t<c:forEach items=\"${cpu}\" var=\"item\" varStatus=\"stat\">\n\t\t\tvar options = getOptions(\"${item.name}\", \"container${item.name}\");\n\t\t\toptions.subtitle.text = \"max user:${item.maxUser}% sys:${item.maxSys}% wa:${item.maxWa}% avg user:${item.avgUser}% sys:${item.avgSys}% wa:${item.avgWa}%\";\n\t\t\toptions.series.push(${item.userSeries.toJson()});\n\t\t\toptions.series.push(${item.sysSeries.toJson()});\n\t\t\toptions.series.push(${item.waSeries.toJson()});\n\t\t    new Highcharts.Chart(options); \n\t\t</c:forEach>\n\t}\n</script>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/server/disk.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<div class=\"col-md-6\">\n\t<div id=\"containerRead\"\n\t\tstyle=\"min-width: 310px; height: 400px; margin: 0 auto\"></div>\n</div>\n<div class=\"col-md-6\">\n\t<div id=\"containerWrite\"\n\t\tstyle=\"min-width: 310px; height: 400px; margin: 0 auto\"></div>\n</div>\n<div class=\"col-md-6\">\n\t<div id=\"containerBusy\"\n\t\tstyle=\"min-width: 310px; height: 400px; margin: 0 auto\"></div>\n</div>\n<div class=\"col-md-6\">\n\t<div id=\"containerIops\"\n\t\tstyle=\"min-width: 310px; height: 400px; margin: 0 auto\"></div>\n</div>\n<div class=\"col-md-6\">\n\t<div id=\"containerSpace\"\n\t\tstyle=\"min-width: 310px; height: 400px; margin: 0 auto\"></div>\n</div>\n\t\n<script type=\"text/javascript\">\n\t$(document).ready(function() {\n\t\tinitReadChart();\n\t\tinitWriteChart();\n\t\tinitBusyChart();\n\t\tinitIopsChart();\n\t\tinitSpaceChart();\n\t});\n\t\n\tfunction initReadChart(){\n\t\tvar options = getOptions(\"read\", \"containerRead\");\n\t\toptions.subtitle.text = \"max:${read.max}k/s avg:${read.avg}k/s\";\n\t\t<c:forEach items=\"${read.series}\" var=\"item\" varStatus=\"stat\">\n\t\t\toptions.series.push(${item.toJson()});\n\t\t</c:forEach>\n\t    new Highcharts.Chart(options); \n\t}\n\tfunction initWriteChart(){\n\t\tvar options = getOptions(\"write\", \"containerWrite\");\n\t\toptions.subtitle.text = \"max:${write.max}k/s avg:${write.avg}k/s\";\n\t\t<c:forEach items=\"${write.series}\" var=\"item\" varStatus=\"stat\">\n\t\t\toptions.series.push(${item.toJson()});\n\t\t</c:forEach>\n\t    new Highcharts.Chart(options); \n\t}\n\tfunction initBusyChart(){\n\t\tvar options = getOptions(\"busy\", \"containerBusy\");\n\t\toptions.subtitle.text = \"max:${busy.max}% avg:${busy.avg}%\";\n\t\t<c:forEach items=\"${busy.series}\" var=\"item\" varStatus=\"stat\">\n\t\t\toptions.series.push(${item.toJson()});\n\t\t</c:forEach>\n\t    new Highcharts.Chart(options); \n\t}\n\tfunction initIopsChart(){\n\t\tvar options = getOptions(\"iops\", \"containerIops\");\n\t\toptions.subtitle.text = \"max:${iops.max}次/s avg:${iops.avg}次/s\";\n\t\t<c:forEach items=\"${iops.series}\" var=\"item\" varStatus=\"stat\">\n\t\t\toptions.series.push(${item.toJson()});\n\t\t</c:forEach>\n\t    new Highcharts.Chart(options); \n\t}\n\tfunction initSpaceChart(){\n\t\tvar options = getOptions(\"space use\", \"containerSpace\");\n\t\toptions.subtitle.text = \"max:${space.max}% avg:${space.avg}%\";\n\t\t<c:forEach items=\"${space.series}\" var=\"item\" varStatus=\"stat\">\n\t\t\toptions.series.push(${item.toJson()});\n\t\t</c:forEach>\n\t    new Highcharts.Chart(options); \n\t}\n</script>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/server/index.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\" %>\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <title>CacheCloud服务器状态</title>\n    <jsp:include page=\"/WEB-INF/include/head.jsp\"/>\n    <script type=\"text/javascript\" src=\"/resources/js/chart.js\"></script>\n\n</head>\n<body role=\"document\">\n\t<div class=\"container\">\n    \t<jsp:include page=\"/WEB-INF/include/headMenu.jsp\"/>\n\t    <div class=\"tabbable-custom\">\n\t        <ul class=\"nav nav-tabs\" id=\"app_tabs\">\n\t            <li class=\"active\"><a href=\"#overview\" data-url=\"/server/overview.do?ip=${ip}&date=${date}\" data-toggle=\"tab\">概览</a></li>\n\t            <li><a href=\"#cpu\" data-url=\"/server/cpu.do?ip=${ip}&date=${date}\" data-toggle=\"tab\">cpu</a></li>\n\t            <li><a href=\"#net\" data-url=\"/server/net.do?ip=${ip}&date=${date}\" data-toggle=\"tab\">net</a></li>\n\t        \t<li><a href=\"#disk\" data-url=\"/server/disk.do?ip=${ip}&date=${date}\" data-toggle=\"tab\">disk</a></li>\n\t        </ul>\n\t        <div class=\"tab-content\">\n\t            <div class=\"tab-pane active\" id=\"overview\">\n\t            </div>\n\t            <div class=\"tab-pane\" id=\"cpu\">\n\t            </div>\n\t            <div class=\"tab-pane\" id=\"net\">\n\t            </div>\n\t            <div class=\"tab-pane\" id=\"disk\">\n\t            </div>\n\t        </div>\n\t    </div>\n\t</div>\n\t<jsp:include page=\"/WEB-INF/include/foot.jsp\"/>\n\t<script type=\"text/javascript\">\n\t    $('#app_tabs a').click(function (e) {\n\t        e.preventDefault();\n\t\n\t        var url = $(this).attr(\"data-url\");\n\t        var href = this.hash;\n\t        var pane = $(this);\n\t        var id = $(href).attr(\"id\");\n\t        // ajax load from data-url\n\t        $(href).load(url, function (result) {\n\t            pane.tab('show');\n\t        });\n\t    });\n\t\n\t    var tabTag = \"${tabTag}\";\n\t    if (tabTag.length > 0 && $('#' + tabTag).length > 0) {\n\t        var tabId = '#' + tabTag;\n\t        $(\"a[href=\" + tabId + \"]\").click();\n\t    } else {\n\t        $(\"a[href=#overview]\").click();\n\t    }\n\t</script>\n\t<script type=\"text/javascript\" src=\"/resources/js/docs.min.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/server/net.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<c:if test=\"${empty cpu}\">\n\tno data\n</c:if>\n<c:forEach items=\"${net}\" var=\"item\" varStatus=\"stat\">\n\t<div class=\"col-md-6\">\n\t\t<div id=\"container${item.name}\"\n\t\t\tstyle=\"min-width: 310px; height: 400px; margin: 0 auto\"></div>\n\t</div>\n</c:forEach>\n\t\n<script type=\"text/javascript\">\n\t$(document).ready(function() {\n\t\tinitSubNetChart();\n\t});\n\t\n\tfunction initSubNetChart(){\n\t\t<c:forEach items=\"${net}\" var=\"item\" varStatus=\"stat\">\n\t\t\tvar options = getOptions(\"${item.name}\", \"container${item.name}\");\n\t\t\toptions.subtitle.text = \"max in:${item.maxIn}k/s out:${item.maxOut}k/s avg in:${item.avgIn}k/s out:${item.avgOut}k/s\";\n\t\t\toptions.series.push(${item.inSeries.toJson()});\n\t\t\toptions.series.push(${item.outSeries.toJson()});\n\t\t    new Highcharts.Chart(options); \n\t\t</c:forEach>\n\t}\n</script>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/server/overview.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\"%>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<div class=\"col-md-6\">\n\t<div class=\"page-header\">\n\t\t<h4>\n\t\t服务器信息\n\t\t</h4>\n\t</div>\n\t<div class=\"tabbable-custom\">\n\t\t<table class=\"table table-striped table-hover\">\n\t\t\t<tr>\n\t\t\t    <td>ip&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>\n\t\t\t    <td>${info.ip}</td>\n\t\t\t</tr>\n\t\t\t<tr>\n\t\t\t    <td>host</td>\n\t\t\t    <td>${info.host}</td>\n\t\t\t</tr>\n\t\t\t<tr>\n\t\t\t    <td>cpu核数</td>\n\t\t\t    <td>${info.cpus}</td>\n\t\t\t</tr>\n\t\t\t<tr>\n\t\t\t    <td>nmon版本</td>\n\t\t\t    <td>${info.nmon}</td>\n\t\t\t</tr>\n\t\t\t<tr>\n\t\t\t    <td>max file</td>\n\t\t\t    <td>${file}</td>\n\t\t\t</tr>\n\t\t\t<tr>\n\t\t\t    <td>max procs</td>\n\t\t\t    <td>${process}</td>\n\t\t\t</tr>\n\t\t\t<tr>\n\t\t\t\t<td>cpu型号</td>\n\t\t\t    <td>${info.cpuModel}</td>\n\t\t\t</tr>\n\t\t\t<tr>\n\t\t\t    <td>发行版本</td>\n\t\t\t    <td>${info.dist}</td>\n\t\t\t</tr>\n\t\t\t<tr>\n\t\t\t   <td>内核版本</td>\n\t\t\t   <td>${info.kernel}</td>\n\t\t\t</tr>\n\t\t</table>\n\t</div>\n</div>\n<div class=\"col-md-6\">\n\t<div class=\"page-header\">\n\t\t<div style=\"float:right\">\n\t\t\t<form method=\"post\" action=\"/server/index.do\" id=\"ec\" name=\"ec\">\n\t\t\t\t<label style=\"font-weight:bold;text-align:left;\">\n\t\t\t\t \t日期:&nbsp;&nbsp;\n\t\t\t\t</label>\n\t\t\t\t<input type=\"text\" size=\"21\" name=\"date\" id=\"startDate\" readonly=\"readonly\" value=\"${date}\" onFocus=\"WdatePicker({startDate:'%y-%M-01',dateFmt:'yyyy-MM-dd',alwaysUseStartDate:true})\"/>\n\t\t\t\t<input type=\"hidden\" name=\"ip\" value=\"${info.ip}\">\n\t\t\t\t<label>&nbsp;<input type=\"submit\" class=\"btn-4\" value=\"查询\"/></label>\n\t\t\t</form>\n\t\t</div>\n\t\t<h4>load</h4>\n\t</div>\n\t<div id=\"containerLoad\"\n\t\tstyle=\"min-width: 310px; height: 400px; margin: 0 auto\"></div>\n</div>\n<div class=\"col-md-6\">\n\t<div class=\"page-header\">\n\t\t<h4>cpu</h4>\n\t</div>\n\t<div id=\"containerCpu\"\n\t\tstyle=\"min-width: 310px; height: 400px; margin: 0 auto\"></div>\n</div>\n<div class=\"col-md-6\">\n\t<div class=\"page-header\">\n\t\t<h4>memory</h4>\n\t</div>\n\t<div id=\"containerMemory\"\n\t\tstyle=\"min-width: 310px; height: 400px; margin: 0 auto\"></div>\n</div>\n<div class=\"col-md-6\">\n\t<div class=\"page-header\">\n\t\t<h4>swap</h4>\n\t</div>\n\t<div id=\"containerSwap\"\n\t\tstyle=\"min-width: 310px; height: 400px; margin: 0 auto\"></div>\n</div>\n<div class=\"col-md-6\">\n\t<div class=\"page-header\">\n\t\t<h4>net</h4>\n\t</div>\n\t<div id=\"containerNet\"\n\t\tstyle=\"min-width: 310px; height: 400px; margin: 0 auto\"></div>\n</div>\n<div class=\"col-md-6\">\n\t<div class=\"page-header\">\n\t\t<h4>tcp connection</h4>\n\t</div>\n\t<div id=\"containerTcp\"\n\t\tstyle=\"min-width: 310px; height: 400px; margin: 0 auto\"></div>\n</div>\n<div class=\"col-md-6\">\n\t<div class=\"page-header\">\n\t\t<h4>disk</h4>\n\t</div>\n\t<div id=\"containerDisk\"\n\t\tstyle=\"min-width: 310px; height: 400px; margin: 0 auto\"></div>\n</div>\n<script type=\"text/javascript\">\n\t$(document).ready(\n\t\tfunction() {\n\t\t\tinitLoadChart();\n\t\t\tinitCpuChart();\n\t\t\tinitMemoryChart();\n\t\t\tinitSwapChart();\n\t\t\tinitNetChart();\n\t\t\tinitTcpChart();\n\t\t\tinitDiskChart();\n\t});\n\t\n\tfunction initLoadChart(){\n\t\tvar title = \"1-min-max:${maxLoad1} 1-min-avg:${avgLoad1}\";\n\t\tvar options = getOptions(title, \"containerLoad\");\n\t\tpush(options.series, ${load1});\n\t\tpush(options.series, ${load5});\n\t\tpush(options.series, ${load15});\n\t    new Highcharts.Chart(options); \n\t}\n\t\n\tfunction initCpuChart(){\n\t\tvar title = \"max user:${maxUser}% sys:${maxSys}% wa:${maxWa}%\";\n\t\tvar options = getOptions(title, \"containerCpu\");\n\t\tpush(options.series, ${user});\n\t\tpush(options.series, ${sys});\n\t\tpush(options.series, ${wa});\n\t    new Highcharts.Chart(options); \n\t}\n\t\n\tfunction initMemoryChart(){\n\t\tvar title = \"now free:${curFree}G max use:${maxUse}G cache:${maxCache}G buffer:${maxBuffer}G\";\n\t\tvar options = getOptions(title, \"containerMemory\", \"area\");\n\t\tpush(options.series, ${mtotal});\n\t\tpush(options.series, ${muse});\n\t\tpush(options.series, ${mcache});\n\t\tpush(options.series, ${mbuffer});\n\t    new Highcharts.Chart(options); \n\t}\n\t\n\tfunction initSwapChart(){\n\t\tvar title = \"max use:${maxSwap}M\";\n\t\tvar options = getOptions(title, \"containerSwap\");\n\t\tpush(options.series, ${mswap});\n\t\tpush(options.series, ${mswapUse});\n\t    new Highcharts.Chart(options); \n\t}\n\t\n\tfunction initNetChart(){\n\t\tvar title = \"max in:${maxNetIn}M/s out:${maxNetOut}M/s\";\n\t\tvar options = getOptions(title, \"containerNet\");\n\t\tpush(options.series, ${nin});\n\t\tpush(options.series, ${nout});\n\t    new Highcharts.Chart(options); \n\t}\n\t\n\tfunction initTcpChart(){\n\t\tvar title = \"max estab:${maxConn} tw:${maxWait} orphan:${maxOrphan}\";\n\t\tvar options = getOptions(title, \"containerTcp\");\n\t\tpush(options.series, ${testab});\n\t\tpush(options.series, ${twait});\n\t\tpush(options.series, ${torph});\n\t    new Highcharts.Chart(options); \n\t}\n\t\n\tfunction initDiskChart(){\n\t\tvar title = \"max read:${maxRead}M/s write:${maxWrite}M/s busy:${maxBusy}% iops:${maxIops}次/s\";\n\t\tvar options = getOptions(title, \"containerDisk\");\n\t\toptions.yAxis = [{title:{text:\"\"}},{opposite: true},{opposite: true}];\n\t\tvar dread = eval(${dread});\n\t\tdread.tooltip = {\n            valueSuffix: 'k/s'\n        };\n\t\tpush(options.series, dread);\n\t\tvar dwrite = eval(${dwrite});\n\t\tdwrite.tooltip = {\n            valueSuffix: 'k/s'\n        };\n\t\tpush(options.series, dwrite);\n\t\tvar dbusy = eval(${dbusy});\n\t\tdbusy.tooltip = {\n            valueSuffix: '%'\n        };\n\t\tpush(options.series, dbusy);\n\t\tvar diops = eval(${diops});\n\t\tdiops.tooltip = {\n            valueSuffix: '次/s'\n        };\n\t\tpush(options.series, diops);\n\t    new Highcharts.Chart(options); \n\t}\n\t\n\tfunction push(series, value){\n\t\tif(value){\n\t\t\tseries.push(value);\n\t\t}\n\t}\n\t\n\tfunction getOptions(title, renderTo, chartType){\n\t\tvar showTitle = title;\n\t    if(!chartType){\n\t    \tchartType = \"\";\n\t    }\n\t    var marginRight = 10;\n\t    if(renderTo.indexOf(\"Disk\") != -1){\n\t    \tmarginRight = 30;\n\t    }\n\t   \tvar options = {\n\t\t\tchart: {\n\t\t\t\trenderTo: renderTo,\n\t\t\t\tanimation: Highcharts.svg,\n\t\t\t\tbackgroundColor: '#E6F1F5',\n\t\t\t\tplotBackgroundColor:'#FFFFFF',\n\t\t\t\tzoomType: \"x\",\n\t\t\t\ttype: chartType,\n\t\t\t\tmarginRight: marginRight\n\t\t\t},\n            title: {\n            \tuseHTML:true,\n                text: showTitle\n            },\n            subtitle: {\n                text: ''\n            },\n            xAxis: {\n            \tcategories: ${xAxis},\n            \ttickInterval: 24\n            },\n            yAxis: {\n            \ttitle: {\n               \t\ttext: ''\n           \t\t},\n                plotLines: [{\n                    value: 0,\n                    width: 1,\n                    color: '#808080'\n                }],\n                min: 0\n            },\n            plotOptions: {\n                line: {\n                    dataLabels: {\n                        enabled: true\n                    }\n                },\n                series: {\n\t                cursor: 'pointer',\n\t                marker: {\n                \t\tenabled: false\n                \t}\n\t            }\n            },\n            tooltip: {\n                shared:true\n            },\n            legend: {\n                enabled: true\n            },\n            credits:{\n            \tenabled: false\n            },\n            exporting: {\n                enabled: true\n            },\n            series: []\n        };\n\t   \tif(renderTo.indexOf(\"Cpu\") != -1 || renderTo.indexOf(\"CPU\") != -1 || renderTo.indexOf(\"Busy\") != -1 || renderTo.indexOf(\"Space\") != -1){\n\t   \t\toptions.tooltip.pointFormat = \"<span>{series.name}</span>:{point.y:,.f}%<br/>\";\n\t    }\n\t   \tif(renderTo.indexOf(\"Memory\") != -1 || renderTo.indexOf(\"Swap\") != -1){\n\t   \t\toptions.tooltip.pointFormat = \"<span>{series.name}</span>:{point.y:,.f}M<br/>\";\n\t    }\n\t   \tif(renderTo.indexOf(\"Net\") != -1 || renderTo.indexOf(\"eth\") != -1 || renderTo.indexOf(\"Read\") != -1 || renderTo.indexOf(\"Write\") != -1){\n\t   \t\toptions.tooltip.pointFormat = \"<span>{series.name}</span>:{point.y:,.f}k/s<br/>\";\n\t    }\n\t   \tif(renderTo.indexOf(\"Iops\") != -1){\n\t   \t\toptions.tooltip.pointFormat = \"<span>{series.name}</span>:{point.y:,.f}次/s<br/>\";\n\t    }\n\t   \treturn options;\n\t}\n</script>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/jsp/user/userRegister.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <title>CacheCloud用户申请</title>\n    <script type=\"text/javascript\">\n    //验证邮箱格式\n    var valEmails=/^(([a-zA-Z0-9]+[_|\\_|\\.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|\\_|\\.|\\-]?)*[a-zA-Z0-9]+\\.[a-zA-Z]{2,3};){0,6}([a-zA-Z0-9]+[_|\\_|\\.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|\\_|\\.|\\-]?)*[a-zA-Z0-9]+\\.[a-zA-Z]{2,3}$/;\n    function checkUser(){\n    \tvar name = document.getElementById(\"name\");\n    \tvar chName = document.getElementById(\"chName\");\n    \tvar email = document.getElementById(\"email\");\n    \tvar mobile = document.getElementById(\"mobile\");\n    \tif(name.value == \"\"){\n        \talert(\"域账户名不能为空!\");\n    \t\tname.focus();\n    \t\treturn false;\n        }\n    \tif(chName.value == \"\"){\n        \talert(\"中文名不能为空!\");\n    \t\tchName.focus();\n    \t\treturn false;\n        }\n    \tif(email.value == \"\"){\n    \t\talert(\"邮箱不能为空!\");\n    \t\temail.focus();\n    \t\treturn false;\n    \t}\n    \tif(!valEmails.test(email.value)){\n    \t\talert(\"邮箱格式错误!\");\n    \t\temail.focus();\n    \t\treturn false;\n    \t}\n    \tif(mobile.value == \"\"){\n    \t\talert(\"手机号不能为空!\");\n    \t\tmobile.focus();\n    \t\treturn false;\n    \t}\n    \treturn true;\n    }\n    function checkUserNameExist(id) {\n    \tvar userName = document.getElementById(id).value;\n    \tif(userName != ''){\n    \t\t$.post(\n    \t\t\t'/user/checkUserNameExist',\n    \t\t\t{\n    \t\t\t\tuserName: userName,\n    \t\t\t},\n    \t        function(data){\n    \t            if(data==1){\n    \t            \talert(\"用户名已经存在，请修改或者联系管理员\");\n    \t            \tdocument.getElementById(id).focus();\n    \t            \tdocument.getElementById(id).value=\"\";\n    \t            }\n    \t        }\n    \t     );\n    \t}\n    }\n    \n    \n    </script>\n    <jsp:include page=\"/WEB-INF/include/head.jsp\"/>\n</head>\n<body role=\"document\">\n\t<div class=\"container\">\n\t    <jsp:include page=\"/WEB-INF/include/headMenu.jsp\"/>\n\t    <div id=\"systemAlert\">\n\t    </div>\n\t\t<div class=\"page-content\">\n\t\t\t<div class=\"row\">\n\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t<h3 class=\"page-header\">\n\t\t\t\t\t\tCacheCloud用户申请\n\t\t\t\t\t\t<font color='red' size=\"4\">\n\t\t\t\t\t\t\t<c:choose>\n\t\t\t\t\t\t\t\t<c:when test=\"${success == 1}\">(申请成功，请关注邮件中审批进度)</c:when>\n\t\t\t\t\t\t\t</c:choose>\n\t\t\t\t\t\t</font>\n\t\t\t\t\t</h3>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"row\">\n\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t<div class=\"portlet box light-grey\">\n\t\t\t\t\t\t<div class=\"portlet-body\">\n\t\t\t\t\t\t\t<div class=\"form\">\n\t\t\t\t\t\t\t\t\t<!-- BEGIN FORM-->\n\t\t\t\t\t\t\t\t\t<form action=\"/user/apply.do\" method=\"post\"\n\t\t\t\t\t\t\t\t\t\tclass=\"form-horizontal form-bordered form-row-stripped\" onsubmit=\"return checkUser()\">\n\t\t\t\t\t\t\t\t\t\t<div class=\"form-body\">\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t域账户名:\n\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"name\" id=\"name\" placeholder=\"域账户名(邮箱前缀)\" class=\"form-control\" onchange=\"checkUserNameExist(this.id)\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t中文名:\n\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"chName\" id=\"chName\" placeholder=\"中文名\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tclass=\"form-control\" />\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t邮箱:\n\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" name=\"email\" id=\"email\" placeholder=\"邮箱\" class=\"form-control\" />\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label class=\"control-label col-md-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t手机:\n\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<input type=\"text\" id=\"mobile\" name=\"mobile\" placeholder=\"手机\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tclass=\"form-control\" />\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t<input type=\"hidden\" name=\"type\" value=\"-1\">\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"form-actions fluid\">\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-12\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"col-md-offset-4 col-md-9\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<button type=\"submit\" class=\"btn green\" onclick=\"\"  <c:if test=\"${success == 1}\">disabled=\"disabled\"</c:if>>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-check\"></i>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t提交申请\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<button type=\"reset\" class=\"btn green\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-check\"></i>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t&nbsp;&nbsp;重&nbsp;&nbsp;&nbsp;置&nbsp;&nbsp;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</form>\n\t\t\t\t\t\t\t\t\t<!-- END FORM-->\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<!-- END TABLE PORTLET-->\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t<br/><br/><br/><br/><br/><br/><br/>\n\t<jsp:include page=\"/WEB-INF/include/foot.jsp\"/>\n</body>\n</html>\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/My97DatePicker/My97DatePicker.htm",
    "content": "<html>\n<head>\n<meta http-equiv=\"content-type\" content=\"text/xml; charset=utf-8\" />\n<title>My97DatePicker</title>\n<script type=\"text/javascript\" src=\"config.js\"></script>\n<script>\nif(parent==window)\n\tlocation.href = 'http://www.my97.net';\nvar $d, $dp, $pdp = parent.$dp, $dt, $tdt, $sdt, $IE=$pdp.ie, $FF = $pdp.ff,$OPERA=$pdp.opera, $ny, $cMark = false;\nif ($pdp.eCont) {\n\t$dp = {};\n\tfor (var p in $pdp) {\n\t\t$dp[p] = $pdp[p];\n\t}\n}\nelse\n\t$dp = $pdp;\n\t\n$dp.getLangIndex = function(name){\n\tvar arr = langList;\n\tfor (var i = 0; i < arr.length; i++) {\n\t\tif (arr[i].name == name) {\n\t\t\treturn i;\n\t\t}\n\t}\n\treturn -1;\n}\n\n$dp.getLang = function(name){\n\tvar index = $dp.getLangIndex(name);\n\tif (index == -1) {\n\t\tindex = 0;\n\t}\n\treturn langList[index];\n}\n \n$dp.realLang = $dp.getLang($dp.lang);\ndocument.write(\"<script src='lang/\" + $dp.realLang.name + \".js' charset='\" + $dp.realLang.charset + \"'><\\/script>\");\n\nfor (var i = 0; i < skinList.length; i++) {\n    document.write('<link rel=\"stylesheet\" type=\"text/css\" href=\"skin/' + skinList[i].name + '/datepicker.css\" title=\"' + skinList[i].name + '\" charset=\"' + skinList[i].charset + '\" disabled=\"true\"/>');\n}\n</script>\n<script type=\"text/javascript\" src=\"calendar.js\"></script>\n</head>\n<body leftmargin=\"0\" topmargin=\"0\" onload=\"$c.autoSize()\" tabindex=0>\n</body>\n</html>\n<script>new My97DP();</script>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/My97DatePicker/WdatePicker.js",
    "content": "/*\n * My97 DatePicker 4.72 Release\n * License: http://www.my97.net/dp/license.asp\n */\nvar $dp,WdatePicker;(function(){var _={\n$wdate:true,\n$dpPath:\"\",\n$crossFrame:true,\ndoubleCalendar:false,\nenableKeyboard:true,\nenableInputMask:true,\nautoUpdateOnChanged:null,\nwhichDayIsfirstWeek:4,\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,\n\nspecialDates:null,specialDays:null,disabledDates:null,disabledDays:null,opposite:false,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,errMsg:\"\",quickSel:[],has:{}};WdatePicker=U;var X=window,O=\"document\",J=\"documentElement\",C=\"getElementsByTagName\",V,A,T,I,b;switch(navigator.appName){case\"Microsoft Internet Explorer\":T=true;break;case\"Opera\":b=true;break;default:I=true;break}A=L();if(_.$wdate)M(A+\"skin/WdatePicker.css\");V=X;if(_.$crossFrame){try{while(V.parent&&V.parent[O]!=V[O]&&V.parent[O][C](\"frameset\").length==0)V=V.parent}catch(P){}}if(!V.$dp)V.$dp={ff:I,ie:T,opera:b,el:null,win:X,status:0,defMinDate:_.minDate,defMaxDate:_.maxDate,flatCfgs:[]};B();if($dp.status==0)Z(X,function(){U(null,true)});if(!X[O].docMD){E(X[O],\"onmousedown\",D);X[O].docMD=true}if(!V[O].docMD){E(V[O],\"onmousedown\",D);V[O].docMD=true}E(X,\"onunload\",function(){if($dp.dd)Q($dp.dd,\"none\")});function B(){V.$dp=V.$dp||{};obj={$:function($){return(typeof $==\"string\")?X[O].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[O].getElementsByTagName(\"div\"),$=100000;for(var B=0;B<A.length;B++){var _=parseInt(A[B].style.zIndex);if(_>$)$=_}this.dd.style.zIndex=$+2;Q(this.dd,\"block\")},hide:function(){Q(this.dd,\"none\")},attachEvent:E};for(var $ in obj)V.$dp[$]=obj[$];$dp=V.$dp;$dp.dd=V[O].getElementById(\"_my97DP\")}function E(A,$,_){if(T)A.attachEvent($,_);else if(_){var B=$.replace(/on/,\"\");_._ieEmuEventHandler=function($){return _($)};A.addEventListener(B,_._ieEmuEventHandler,false)}}function L(){var _,A,$=X[O][C](\"script\");for(var B=0;B<$.length;B++){_=$[B].src.substring(0,$[B].src.toLowerCase().indexOf(\"wdatepicker.js\"));A=_.lastIndexOf(\"/\");if(A>0)_=_.substring(0,A+1);if(_)break}return _}function F(F){var E,C;if(F.substring(0,1)!=\"/\"&&F.indexOf(\"://\")==-1){E=V.location.href;C=location.href;if(E.indexOf(\"?\")>-1)E=E.substring(0,E.indexOf(\"?\"));if(C.indexOf(\"?\")>-1)C=C.substring(0,C.indexOf(\"?\"));var G,I,$=\"\",D=\"\",A=\"\",J,H,B=\"\";for(J=0;J<Math.max(E.length,C.length);J++){G=E.charAt(J).toLowerCase();I=C.charAt(J).toLowerCase();if(G==I){if(G==\"/\")H=J}else{$=E.substring(H+1,E.length);$=$.substring(0,$.lastIndexOf(\"/\"));D=C.substring(H+1,C.length);D=D.substring(0,D.lastIndexOf(\"/\"));break}}if($!=\"\")for(J=0;J<$.split(\"/\").length;J++)B+=\"../\";if(D!=\"\")B+=D+\"/\";F=E.substring(0,E.lastIndexOf(\"/\")+1)+B+F}_.$dpPath=F}function M(A,$,B){var D=X[O][C](\"HEAD\").item(0),_=X[O].createElement(\"link\");if(D){_.href=A;_.rel=\"stylesheet\";_.type=\"text/css\";if($)_.title=$;if(B)_.charset=B;D.appendChild(_)}}function Z($,_){E($,\"onload\",_)}function G($){$=$||V;var A=0,_=0;while($!=V){var D=$.parent[O][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(F){if(F.getBoundingClientRect)return F.getBoundingClientRect();else{var A={ROOT_TAG:/^body|html$/i,OP_SCROLL:/^(?:inline|table-row)$/i},E=false,H=null,_=F.offsetTop,G=F.offsetLeft,D=F.offsetWidth,B=F.offsetHeight,C=F.offsetParent;if(C!=F)while(C){G+=C.offsetLeft;_+=C.offsetTop;if(S(C,\"position\").toLowerCase()==\"fixed\")E=true;else if(C.tagName.toLowerCase()==\"body\")H=C.ownerDocument.defaultView;C=C.offsetParent}C=F.parentNode;while(C.tagName&&!A.ROOT_TAG.test(C.tagName)){if(C.scrollTop||C.scrollLeft)if(!A.OP_SCROLL.test(Q(C)))if(!b||C.style.overflow!==\"visible\"){G-=C.scrollLeft;_-=C.scrollTop}C=C.parentNode}if(!E){var $=a(H);G-=$.left;_-=$.top}D+=G;B+=_;return{\"left\":G,\"top\":_,\"right\":D,\"bottom\":B}}}function N($){$=$||V;var B=$[O],A=($.innerWidth)?$.innerWidth:(B[J]&&B[J].clientWidth)?B[J].clientWidth:B.body.offsetWidth,_=($.innerHeight)?$.innerHeight:(B[J]&&B[J].clientHeight)?B[J].clientHeight:B.body.offsetHeight;return{\"width\":A,\"height\":_}}function a($){$=$||V;var B=$[O],A=B[J],_=B.body;B=(A&&A.scrollTop!=null&&(A.scrollTop>_.scrollTop||A.scrollLeft>_.scrollLeft))?A:_;return{\"top\":B.scrollTop,\"left\":B.scrollLeft}}function D($){var _=$?($.srcElement||$.target):null;try{if($dp.cal&&!$dp.eCont&&$dp.dd&&_!=$dp.el&&$dp.dd.style.display==\"block\")$dp.cal.close()}catch($){}}function Y(){$dp.status=2;H()}function H(){if($dp.flatCfgs.length>0){var $=$dp.flatCfgs.shift();$.el={innerHTML:\"\"};$.autoPickDate=true;$.qsEnabled=false;K($)}}var R,$;function U(J,C){$dp.win=X;B();J=J||{};if(C){if(!G()){$=$||setInterval(function(){if(V[O].readyState==\"complete\")clearInterval($);U(null,true)},50);return}if($dp.status==0){$dp.status=1;K({el:{innerHTML:\"\"}},true)}else return}else if(J.eCont){J.eCont=$dp.$(J.eCont);$dp.flatCfgs.push(J);if($dp.status==2)H()}else{if($dp.status==0){U(null,true);return}if($dp.status!=2)return;var F=D();if(F){$dp.srcEl=F.srcElement||F.target;F.cancelBubble=true}$dp.el=J.el=$dp.$(J.el||$dp.srcEl);if(!$dp.el||$dp.el[\"My97Mark\"]===true||$dp.el.disabled||($dp.el==$dp.el&&Q($dp.dd)!=\"none\"&&$dp.dd.style.left!=\"-1970px\")){$dp.el[\"My97Mark\"]=false;return}K(J);if(F&&$dp.el.nodeType==1&&$dp.el[\"My97Mark\"]===undefined){$dp.el[\"My97Mark\"]=false;var _,A;if(F.type==\"focus\"){_=\"onclick\";A=\"onfocus\"}else{_=\"onfocus\";A=\"onclick\"}E($dp.el,_,$dp.el[A])}}function G(){if(T&&V!=X&&V[O].readyState!=\"complete\")return false;return true}function D(){if(I){func=D.caller;while(func!=null){var $=func.arguments[0];if($&&($+\"\").indexOf(\"Event\")>=0)return $;func=func.caller}return null}return event}}function S(_,$){return _.currentStyle?_.currentStyle[$]:document.defaultView.getComputedStyle(_,false)[$]}function Q(_,$){if(_)if($!=null)_.style.display=$;else return S(_,\"display\")}function K(H,$){for(var D in _)if(D.substring(0,1)!=\"$\")$dp[D]=_[D];for(D in H)if($dp[D]!==undefined)$dp[D]=H[D];var E=$dp.el?$dp.el.nodeName:\"INPUT\";if($||$dp.eCont||new RegExp(/input|textarea|div|span|p|a/ig).test(E))$dp.elProp=E==\"INPUT\"?\"value\":\"innerHTML\";else return;if($dp.lang==\"auto\")$dp.lang=T?navigator.browserLanguage.toLowerCase():navigator.language.toLowerCase();if(!$dp.dd||$dp.eCont||($dp.lang&&$dp.realLang&&$dp.realLang.name!=$dp.lang&&$dp.getLangIndex&&$dp.getLangIndex($dp.lang)>=0)){if($dp.dd&&!$dp.eCont)V[O].body.removeChild($dp.dd);if(_.$dpPath==\"\")F(A);var B=\"<iframe style=\\\"width:1px;height:1px\\\" src=\\\"\"+_.$dpPath+\"My97DatePicker.htm\\\" frameborder=\\\"0\\\" border=\\\"0\\\" scrolling=\\\"no\\\"></iframe>\";if($dp.eCont){$dp.eCont.innerHTML=B;Z($dp.eCont.childNodes[0],Y)}else{$dp.dd=V[O].createElement(\"DIV\");$dp.dd.id=\"_my97DP\";$dp.dd.style.cssText=\"position:absolute\";$dp.dd.innerHTML=B;V[O].body.appendChild($dp.dd);Z($dp.dd.childNodes[0],Y);if($)$dp.dd.style.left=$dp.dd.style.top=\"-1970px\";else{$dp.show();C()}}}else if($dp.cal){$dp.show();$dp.cal.init();if(!$dp.eCont)C()}function C(){var F=$dp.position.left,B=$dp.position.top,C=$dp.el;if(C!=$dp.srcEl&&(Q(C)==\"none\"||C.type==\"hidden\"))C=$dp.srcEl;var H=W(C),$=G(X),D=N(V),A=a(V),E=$dp.dd.offsetHeight,_=$dp.dd.offsetWidth;if(isNaN(B)){if(B==\"above\"||(B!=\"under\"&&(($.topM+H.bottom+E>D.height)&&($.topM+H.top-E>0))))B=A.top+$.topM+H.top-E-2;else B=A.top+$.topM+Math.min(H.bottom,D.height-E)+2}else B+=A.top+$.topM;if(isNaN(F))F=A.left+Math.min($.leftM+H.left,D.width-_-5)-(T?2:0);else F+=A.left+$.leftM;$dp.dd.style.top=B+\"px\";$dp.dd.style.left=F+\"px\"}}})()"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/My97DatePicker/calendar.js",
    "content": "/*\n * My97 DatePicker 4.72 Release\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;}('o $c;k($5u){5Q.2X.7n(\"6G\",l($){k(!$)h.25();t $});5Q.2X.7e(\"6w\",l(){o $=h.6t;3i($.5M!=1)$=$.7g;t $});7f.2X.2I=l($,b){o A=$.1l(/6p/,\"\");b.5R=l($){6L.1Y=$;t b()};h.7t(A,b.5R,1m)}}l 5H(){$c=h;h.2Y=[];$d=1Q.7q(\"x\");$d.1d=\"4d\";$d.1L=\"<x 1D=6Y><x Y=\\\\\"3H 6W\\\\\"><a 3W=\\\\\"###\\\\\"></a></x><x Y=\\\\\"3H 76\\\\\"><a 3W=\\\\\"###\\\\\"></a></x><x 1c=\\\\\"3g:2v\\\\\"><x Y=\\\\\"33 7a\\\\\"></x><1v Y=3M></x><x 1c=\\\\\"3g:2v\\\\\"><x Y=\\\\\"33 81\\\\\"></x><1v Y=3M></x><x Y=\\\\\"3H 83\\\\\"><a 3W=\\\\\"###\\\\\"></a></x><x Y=\\\\\"3H 84\\\\\"><a 3W=\\\\\"###\\\\\"></a></x><x 1c=\\\\\"3g:5i\\\\\"></x></x><x 1c=\\\\\"86:85;7B:6A\\\\\"></x><x></x><x 1D=7x><x Y=\\\\\"33 7A\\\\\"></x><x Y=\\\\\"33 7M\\\\\"></x><x Y=\\\\\"33 7P\\\\\"></x><1x 2o=0 2m=0 2u=0><1j><18 7J=2><4h 1D=7L></4h>&4B;<1v Y=7o 4b=2><1v 1g=\\\\\":\\\\\" Y=5P 5N><1v Y=5O 4b=2><1v 1g=\\\\\":\\\\\" Y=5P 5N><1v Y=5O 4b=2></18><18><1O 1D=7I></1O></18></1j><1j><18><1O 1D=7Q></1O></18></1j></1x></x><x 1D=7O></x><x 1D=7N><1v Y=4e 1D=7G 3o=1O><1v Y=4e 1D=7z 3o=1O><1v Y=4e 1D=7E 3o=1O></x>\";6M($d,l(){3t()});A();$f.1W=[1Q,$d.1M,$d.1t,$d.2V,$d.3r,$d.3I,$d.2S,$d.28,$d.1U];1b(o B=0;B<$f.1W.u;B++){o b=$f.1W[B];b.3q=B==$f.1W.u-1?$f.1W[1]:$f.1W[B+1];$f.2I(b,\"4c\",4R)}h.5F();$();4Q(\"y,M,H,m,s\");$d.5S.1q=l(){4Z(1)};$d.5T.1q=l(){4Z(-1)};$d.4i.1q=l(){k($d.1E.1c.2h!=\"6K\"){$c.4p();3w($d.1E)}q 1n($d.1E)};1Q.6N.4q($d);l A(){o b=$(\"a\");1r=$(\"x\"),1I=$(\"1v\"),4g=$(\"1O\"),5G=$(\"4h\");$d.3y=b[0];$d.3V=b[1];$d.42=b[3];$d.3Y=b[2];$d.3K=1r[9];$d.1M=1I[0];$d.1t=1I[1];$d.4k=1r[0];$d.3T=1r[4];$d.2J=1r[6];$d.1E=1r[10];$d.2T=1r[11];$d.2H=1r[12];$d.6R=1r[13];$d.6Q=1r[14];$d.6O=1r[15];$d.4i=1r[16];$d.3z=1r[17];$d.2V=1I[2];$d.3r=1I[4];$d.3I=1I[6];$d.2S=1I[7];$d.28=1I[8];$d.1U=1I[9];$d.5S=4g[0];$d.5T=4g[1];$d.5L=5G[0];l $($){t $d.4o($)}}l $(){$d.3y.1q=l(){$1P=$1P<=0?$1P-1:-1;k($1P%5==0){$d.1t.2d();t}$d.1t.1g=$n.y-1;$d.1t.2n()};$d.3V.1q=l(){$n.2C(\"M\",-1);$d.1M.2n()};$d.42.1q=l(){$n.2C(\"M\",1);$d.1M.2n()};$d.3Y.1q=l(){$1P=$1P>=0?$1P+1:1;k($1P%5==0){$d.1t.2d();t}$d.1t.1g=$n.y+1;$d.1t.2n()}}}5H.2X={5F:l(){$1P=0;$f.5K=h;k($f.3N&&$f.z.3N!=1i){$f.z.3N=19;$f.z.4w()}$();h.5j();$n=h.6f=1a 1C();$1B=1a 1C();$1w=h.2w=1a 1C();h.1y=h.34($f.1y);h.2P=$f.2P==1i?($f.Z.2a&&$f.Z.2a?1m:19):$f.2P;$f.2z=$f.2z==1i?($f.4j&&$f.Z.d?1m:19):$f.2z;h.49=h.3f(\"8a\");h.68=h.3f(\"8b\");h.64=h.3f(\"89\");h.5C=h.3f(\"87\");h.1X=h.3P($f.1X,$f.1X!=$f.5D?$f.1S:$f.3j,$f.5D);h.1Z=h.3P($f.1Z,$f.1Z!=$f.5E?$f.1S:$f.3j,$f.5E);k(h.1X.2r(h.1Z)>0)$f.4f=$1k.7V;k(h.1R()){h.5J();h.3O=$f.z[$f.1z]}q h.3m(1m,2);4u($n);$d.5L.1L=$1k.7R;$d.2S.1g=$1k.7S;$d.28.1g=$1k.7Z;$d.1U.1g=$1k.80;$d.1U.1N=!$c.1u($1w);h.5c();h.6l();k($f.4f)7Y($f.4f);h.4C();k($f.z.5M==1&&$f.z[\"4m\"]===4Y){$f.2I($f.z,\"4c\",4R);$f.2I($f.z,\"2n\",l(){k($f.1K.1c.2h==\"2E\"){$c.3Q();k($f.5K.3O!=$f.z[$f.1z]&&$f.z.75)4I($f.z,\"73\")}})}$c.1f=$f.z;3t();l $(){o b,$;1b(b=0;($=1Q.4o(\"71\")[b]);b++)k($[\"72\"].1o(\"1c\")!=-1&&$[\"5I\"]){$.1N=19;k($[\"5I\"]==$f.79)$.1N=1m}}},5J:l(){o b=h.2L();k(b!=0){o $;k(b>0)$=h.1Z;q $=h.1X;k($f.Z.3u){$n.y=$.y;$n.M=$.M;$n.d=$.d}k($f.Z.2a){$n.H=$.H;$n.m=$.m;$n.s=$.s}}},3b:l(J,C,Q,E,B,G,F,K,L){o $;k(J&&J.1R)$=J;q{$=1a 1C();k(J!=\"\"){C=C||$f.1y;o H,P=0,O,A=/3a|2l|36|y|2A|2Z|3U|M|1K|d|%2k|4J|H|4K|m|4G|s|3c|D|4H|W|w/g,b=C.35(A);A.2x=0;k(L)O=J.4O(/\\\\W+/);q{o D=0,M=\"^\";3i((O=A.3h(C))!==1i){k(D>=0)M+=C.1F(D,O.3x);D=A.2x;2G(O[0]){1e\"3a\":M+=\"(\\\\\\\\d{4})\";1h;1e\"2l\":M+=\"(\\\\\\\\d{3})\";1h;1e\"2A\":1e\"2Z\":1e\"3c\":1e\"D\":M+=\"(\\\\\\\\D+)\";1h;5X:M+=\"(\\\\\\\\d\\\\\\\\d?)\";1h}}M+=\".*$\";O=1a 4r(M).3h(J);P=1}k(O){1b(H=0;H<b.u;H++){o I=O[H+P];k(I)2G(b[H]){1e\"2A\":1e\"2Z\":$.M=N(b[H],I);1h;1e\"y\":1e\"36\":I=3E(I,0);k(I<50)I+=5z;q I+=78;$.y=I;1h;1e\"2l\":$.y=3E(I,0)+$f.5p;1h;5X:$[b[H].4T(-1)]=I;1h}}}q $.d=32}}$.6r(Q,E,B,G,F,K);t $;l N(A,$){o b=A==\"2A\"?$1k.5m:$1k.29;1b(o B=0;B<12;B++)k(b[B].3X()==$.77(0,b[B].u).3X())t B+1;t-1}},3f:l(b){o B,$=$f[b],A=\"(?:\";k($){1b(B=0;B<$.u;B++){A+=h.34($[B]);k(B!=$.u-1)A+=\"|\"}A=1a 4r(A+\")\")}q A=1i;t A},2p:l(){o $=h.4s();k($f.z[$f.1z]!=$)$f.z[$f.1z]=$;h.3R()},3R:l($){o b=$f.$($f.6V),$=2K($,h.4s($f.1S));k(b)b.1g=$;$f.z[\"3v\"]=$},34:l(s){o 3D=\"2N\",1s,2B,6c=/#?\\\\{(.*?)\\\\}/;s=s+\"\";1b(o i=0;i<3D.u;i++)s=s.1l(\"%\"+3D.1J(i),h.1V(3D.1J(i),1i,$1B));k(s.1F(0,3)==\"#F{\"){s=s.1F(3,s.u-1);k(s.1o(\"t \")<0)s=\"t \"+s;s=$f.4N.2W(\"1a 6S(\\\\\"\"+s+\"\\\\\");\");s=s()}q 3i((1s=6c.3h(s))!=1i){1s.2x=1s.3x+1s[1].u+1s[0].u-1s[1].u-1;2B=2e(2W(1s[1]));k(2B<0)2B=\"2b\"+(-2B);s=s.1F(0,1s.3x)+2B+s.1F(1s.2x+1)}t s},3P:l(A,B,b){o $;A=h.34(A);k(!A||A==\"\")A=b;k(6Z A==\"70\")$=A;q{$=h.3b(A,B,1i,1i,1,0,0,0,19);$.y=(\"\"+$.y).1l(/^2b/,\"-\");$.M=(\"\"+$.M).1l(/^2b/,\"-\");$.d=(\"\"+$.d).1l(/^2b/,\"-\");$.H=(\"\"+$.H).1l(/^2b/,\"-\");$.m=(\"\"+$.m).1l(/^2b/,\"-\");$.s=(\"\"+$.s).1l(/^2b/,\"-\");k(A.1o(\"%2k\")>=0){A=A.1l(/%2k/g,\"0\");$.d=0;$.M=2e($.M)+1}$.20()}t $},1R:l(){o b,$;k($f.7b||($f.6b!=\"\"&&$f.z[$f.1z]==\"\")){b=h.34($f.6b);$=$f.1S}q{b=$f.z[$f.1z];$=h.1y}$n.2c(h.3b(b,$));k(b!=\"\"){o A=1;k($f.Z.3u&&!h.44($n)){$n.y=$1B.y;$n.M=$1B.M;$n.d=$1B.d;A=0}k($f.Z.2a&&!h.4a($n)){$n.H=$1B.H;$n.m=$1B.m;$n.s=$1B.s;A=0}t A&&h.1u($n)}t 1},44:l($){k($.y!=1i)$=3n($.y,4)+\"-\"+$.M+\"-\"+$.d;t $.35(/^((\\\\d{2}(([69][7p])|([6a][26]))[\\\\-\\\\/\\\\s]?((((0?[6h])|(1[6i]))[\\\\-\\\\/\\\\s]?((0?[1-9])|([1-2][0-9])|(3[6g])))|(((0?[6e])|(11))[\\\\-\\\\/\\\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\\\-\\\\/\\\\s]?((0?[1-9])|([1-2][0-9])))))|(\\\\d{2}(([69][74])|([6a][7u]))[\\\\-\\\\/\\\\s]?((((0?[6h])|(1[6i]))[\\\\-\\\\/\\\\s]?((0?[1-9])|([1-2][0-9])|(3[6g])))|(((0?[6e])|(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])))))?$/)},4a:l($){k($.H!=1i)$=$.H+\":\"+$.m+\":\"+$.s;t $.35(/^([0-9]|([0-1][0-9])|([2][0-3])):([0-9]|([0-5][0-9])):([0-9]|([0-5][0-9]))$/)},2L:l($,A){$=$||$n;o b=$.2r(h.1X,A);k(b>0){b=$.2r(h.1Z,A);k(b<0)b=0}t b},1u:l($,A,B){A=A||$f.Z.3A;o b=h.2L($,A);k(b==0){b=1;k(A==\"d\"&&B==1i)B=2y.5Y((1a 1G($.y,$.M-1,$.d).21()-$f.41)%7);b=!h.67(B)&&!h.5Z($,A)}q b=0;t b},62:l(){o b=$f.z,A=h,$=$f.z[$f.1z];k($!=1i){k($!=\"\")A.2w.2c(A.3b($,A.1y));k($==\"\"||(A.44(A.2w)&&A.4a(A.2w)&&A.1u(A.2w))){k($!=\"\"){A.6f.2c(A.2w);A.2p()}q A.3R(\"\")}q t 1m}t 19},3Q:l($){3t();k(h.62()){h.3m(19);$f.1n()}q{k($){3k($);h.3m(1m,2)}q h.3m(1m);$f.24()}},3F:l(){o E,C,D,K,A,H=1a 2s(),F=$1k.5y,G=$f.41,I=\"\",$=\"\",b=1a 1C($n.y,$n.M,$n.d,0,0,0),J=b.y,B=b.M;A=1-1a 1G(J,B-1,1).21()+G;k(A>1)A-=7;H.a(\"<1x Y=5g 2U=3p% 2u=0 2o=0 2m=0>\");H.a(\"<1j Y=5f 4A=5h>\");k($f.61)H.a(\"<18>\"+F[0]+\"</18>\");1b(E=0;E<7;E++)H.a(\"<18>\"+F[(G+E)%7+1]+\"</18>\");H.a(\"</1j>\");1b(E=1,C=A;E<7;E++){H.a(\"<1j>\");1b(D=0;D<7;D++){b.1R(J,B,C++);b.20();k(b.M==B){K=19;k(b.2r($1w,\"d\")==0)I=\"7s\";q k(b.2r($1B,\"d\")==0)I=\"7d\";q I=($f.63&&(0==(G+D)%7||6==(G+D)%7)?\"7k\":\"7l\");$=($f.63&&(0==(G+D)%7||6==(G+D)%7)?\"7i\":\"7j\")}q k($f.5s){K=19;I=\"7c\";$=\"8L\"}q K=1m;k($f.61&&D==0&&(E<4||K))H.a(\"<18 Y=8H>\"+4t(b,$f.41==0?1:0)+\"</18>\");H.a(\"<18 \");k(K){k(h.1u(b,\"d\",D)){k(h.65(2y.5Y((1a 1G(b.y,b.M-1,b.d).21()-$f.41)%7))||h.66(b))I=\"8K\";H.a(\"1q=\\\\\"2O(\"+b.y+\",\"+b.M+\",\"+b.d+\");\\\\\" \");H.a(\"2t=\\\\\"h.1d=\\'\"+$+\"\\'\\\\\" \");H.a(\"2q=\\\\\"h.1d=\\'\"+I+\"\\'\\\\\" \")}q I=\"8M\";H.a(\"Y=\"+I);H.a(\">\"+b.d+\"</18>\")}q H.a(\"></18>\")}H.a(\"</1j>\")}H.a(\"</1x>\");t H.j()},5Z:l(b,A){o $=h.47(b,h.49,A);t(h.49&&$f.5e)?!$:$},67:l($){t h.4x($,h.68)},66:l($){t h.47($,h.64)},65:l($){t h.4x($,h.5C)},47:l($,B,A){o b=A==\"d\"?$f.4l:$f.1S;t B?B.4P(h.3S(b,$)):0},4x:l(b,$){t $?$.4P(b):0},2R:l(p,c,r,e,2j){o s=1a 2s(),4y=2j?\"r\"+p:p;5b=$n[p];s.a(\"<1x 2o=0 2m=3 2u=0\");1b(o i=0;i<r;i++){s.a(\"<1j 3d=\\\\\"3d\\\\\">\");1b(o j=0;j<c;j++){s.a(\"<18 3d \");$n[p]=2W(e);k(($f.5e&&h.2L($n,p)==0)||h.1u($n,p)){s.a(\"Y=\\'1A\\' 2t=\\\\\"h.1d=\\'3e\\'\\\\\" 2q=\\\\\"h.1d=\\'1A\\'\\\\\" 3Z=\\\\\"\");s.a(\"1n($d.\"+p+\"D);$d.\"+4y+\"I.1g=\"+$n[p]+\";$d.\"+4y+\"I.4w();\\\\\"\")}q s.a(\"Y=\\'4z\\'\");s.a(\">\"+(p==\"M\"?$1k.29[$n[p]-1]:$n[p])+\"</18>\")}s.a(\"</1j>\")}s.a(\"</1x>\");$n[p]=5b;t s.j()},4E:l($,b){k($){o A=$.8Q;k($6m)A=$.8V().2v;b.1c.2v=A}},8E:l($){h.4E($,$d.3T);$d.3T.1L=h.2R(\"M\",2,6,\"i+j*6+1\",$==$d.2i)},4v:l(b,A){o $=1a 2s();A=2K(A,$n.y-5);$.a(h.2R(\"y\",2,5,A+\"+i+j*5\",b==$d.2D));$.a(\"<1x 2o=0 2m=3 2u=0 4A=5h><1j><18 \");$.a(h.1X.y<A?\"Y=\\'1A\\' 2t=\\\\\"h.1d=\\'3e\\'\\\\\" 2q=\\\\\"h.1d=\\'1A\\'\\\\\" 3Z=\\'k(1Y.25)1Y.25();1Y.4S=19;$c.4v(0,\"+(A-10)+\")\\'\":\"Y=\\'4z\\'\");$.a(\">\\\\8l</18><18 Y=\\'1A\\' 2t=\\\\\"h.1d=\\'3e\\'\\\\\" 2q=\\\\\"h.1d=\\'1A\\'\\\\\" 3Z=\\\\\"1n($d.2J);$d.1t.4w();\\\\\">\\\\5l</18><18 \");$.a(h.1Z.y>A+10?\"Y=\\'1A\\' 2t=\\\\\"h.1d=\\'3e\\'\\\\\" 2q=\\\\\"h.1d=\\'1A\\'\\\\\" 3Z=\\'k(1Y.25)1Y.25();1Y.4S=19;$c.4v(0,\"+(A+10)+\")\\'\":\"Y=\\'4z\\'\");$.a(\">\\\\8p</18></1j></1x>\");h.4E(b,$d.2J);$d.2J.1L=$.j()},3C:l(A,b,$){$d[A+\"D\"].1L=h.2R(A,6,b,$)},8n:l(){h.3C(\"H\",4,\"i * 6 + j\")},8e:l(){h.3C(\"m\",2,\"i * 30 + j * 5\")},8c:l(){h.3C(\"s\",1,\"j * 10\")},4p:l(A){h.6F();o b=h.2Y,C=b.1c,$=1a 2s();$.a(\"<1x Y=5g 2U=3p% 2f=3p% 2u=0 2o=0 2m=0>\");$.a(\"<1j Y=5f><18><x 1c=\\\\\"3g:2v\\\\\">\"+$1k.8g+\"</x>\");k(!A)$.a(\"<x 1c=\\\\\"3g:5i;8z:8y\\\\\" 1q=\\\\\"1n($d.1E);\\\\\">\\\\5l</x>\");$.a(\"</18></1j>\");1b(o B=0;B<b.u;B++)k(b[B]){$.a(\"<1j><18 1c=\\'55-4A:2v\\' 3d=\\'3d\\' Y=\\'1A\\' 2t=\\\\\"h.1d=\\'3e\\'\\\\\" 2q=\\\\\"h.1d=\\'1A\\'\\\\\" 1q=\\\\\"\");$.a(\"2O(\"+b[B].y+\", \"+b[B].M+\", \"+b[B].d+\",\"+b[B].H+\",\"+b[B].m+\",\"+b[B].s+\");\\\\\">\");$.a(\"&4B;\"+h.3S(1i,b[B]));$.a(\"</18></1j>\")}q $.a(\"<1j><18 Y=\\'1A\\'>&4B;</18></1j>\");$.a(\"</1x>\");$d.1E.1L=$.j()},5j:l(){$(/w/);$(/4H|W/);$(/3c|D/);$(/3a|2l|36|y/);$(/2A|2Z|3U|M/);$(/1K|d/);$(/4J|H/);$(/4K|m/);$(/4G|s/);$f.Z.3u=($f.Z.y||$f.Z.M||$f.Z.d)?19:1m;$f.Z.2a=($f.Z.H||$f.Z.m||$f.Z.s)?19:1m;$f.3j=$f.3j.1l(/%1G/,$f.4l).1l(/%8w/,$f.5d);k($f.Z.3u){k($f.Z.2a)$f.1S=$f.3j;q $f.1S=$f.4l}q $f.1S=$f.5d;l $(b){o $=(b+\"\").4T(1,2);$f.Z[$]=b.3h($f.1y)?($f.Z.3A=$,19):1m}},5c:l(){o $=0;$f.Z.y?($=1,24($d.1t,$d.3y,$d.3Y)):1n($d.1t,$d.3y,$d.3Y);$f.Z.M?($=1,24($d.1M,$d.3V,$d.42)):1n($d.1M,$d.3V,$d.42);$?24($d.4k):1n($d.4k);k($f.Z.2a){24($d.2H);3G($d.2V,$f.Z.H);3G($d.3r,$f.Z.m);3G($d.3I,$f.Z.s)}q 1n($d.2H);2M($d.2S,$f.5w);2M($d.28,$f.5x);2M($d.1U,$f.4j);2M($d.4i,!$f.5n&&$f.Z.d&&$f.8t);k($f.6v||!($f.5w||$f.5x||$f.4j))1n($d.3z);q 24($d.3z)},3m:l(B,D){o A=$f.z,b=$5u?\"Y\":\"1d\";k(B)C(A);q{k(D==1i)D=$f.8s;2G(D){1e 0:k(8B($1k.8C)){A[$f.1z]=h.3O;C(A)}q $(A);1h;1e 1:A[$f.1z]=h.3O;C(A);1h;1e 2:$(A);1h}}l C(A){o B=A.1d;k(B){o $=B.1l(/5B/g,\"\");k(B!=$)A.5A(b,$)}}l $($){$.5A(b,$.1d+\" 5B\")}},1V:l(D,b,$){$=$||$1w;o H,C=[D+D,D],E,A=$[D],F=l($){t 3n(A,$.u)};2G(D){1e\"w\":A=21($);1h;1e\"D\":o G=21($)+1;F=l($){t $.u==2?$1k.8A[G]:$1k.5y[G]};1h;1e\"W\":A=4t($);1h;1e\"y\":C=[\"3a\",\"2l\",\"36\",\"y\"];b=b||C[0];F=l(b){t 3n((b.u<4)?(b.u<3?$.y%3p:($.y+5z-$f.5p)%8x):A,b.u)};1h;1e\"M\":C=[\"2A\",\"2Z\",\"3U\",\"M\"];F=l($){t($.u==4)?$1k.5m[A-1]:($.u==3)?$1k.29[A-1]:3n(A,$.u)};1h}b=b||D+D;k(\"2N\".1o(D)>-1&&D!=\"y\"&&!$f.Z[D])k(\"8h\".1o(D)>-1)A=0;q A=1;o B=[];1b(H=0;H<C.u;H++){E=C[H];k(b.1o(E)>=0){B[H]=F(E);b=b.1l(E,\"{\"+H+\"}\")}}1b(H=0;H<B.u;H++)b=b.1l(1a 4r(\"\\\\\\\\{\"+H+\"\\\\\\\\}\",\"g\"),B[H]);t b},3S:l(b,$){$=$||h.3b($f.z[$f.1z],h.1y)||$1w;b=b||h.1y;k(b.1o(\"%2k\")>=0){o A=1a 1C();A.2c($);A.d=0;A.M=2e(A.M)+1;A.20();b=b.1l(/%2k/g,A.d)}o B=\"8d\";1b(o D=0;D<B.u;D++){o C=B.1J(D);b=h.1V(C,b,$)}k($f.Z[\"D\"]){b=b.1l(/3c/g,\"%1K\").1l(/D/g,\"%d\");b=h.1V(\"M\",b,$);b=b.1l(/\\\\%1K/g,h.1V(\"D\",\"3c\")).1l(/\\\\%d/g,h.1V(\"D\",\"D\"))}q b=h.1V(\"M\",b,$);t b},8o:l(b,$){t h.1V(b,$,$n)},4s:l($){t h.3S($,$n)},4C:l(){$d.3K.1L=\"\";k($f.5n){$c.2P=19;$f.5s=1m;$d.1d=\"4d 8T\";o $=1a 2s();$.a(\"<1x Y=8R 2U=3p% 2o=0 2m=0 2u=1><1j><18 5q=5r>\");$.a(h.3F());$.a(\"</18><18 5q=5r>\");$n.2C(\"M\",1);$.a(h.3F());$d.2i=$d.1M.5o(19);$d.2D=$d.1t.5o(19);$d.3K.4q($d.2i);$d.3K.4q($d.2D);$d.2i.1g=$1k.29[$n.M-1];$d.2i[\"3v\"]=$n.M;$d.2D.1g=$n.y;4Q(\"6H,6E\");$d.2i.1d=$d.2D.1d=\"3M\";$n.2C(\"M\",-1);$.a(\"</18></1j></1x>\");$d.2T.1L=$.j()}q{$d.1d=\"4d\";$d.2T.1L=h.3F()}k(!$f.Z.d||$f.8J){h.4p(19);3w($d.1E)}q 1n($d.1E);h.6P()},6P:l(){o b=8W.1Q.4o(\"8k\");1b(o C=0;C<b.u;C++){o $=$d.1c.2f;$d.1c.2f=\"\";o A=$d.3l;k(b[C].8j==6L&&A){b[C].1c.2U=$d.6q+\"6s\";o B=$d.2H.3l;k(B&&$d.3z.1c.2h==\"2E\"&&$d.2H.1c.2h!=\"2E\"&&1Q.6N.8f-A>=B){A+=B;$d.1c.2f=A}q $d.1c.2f=$;b[C].1c.2f=2y.5v(A,$d.3l)+\"6s\"}}$d.1E.1c.2U=$d.2T.6q;$d.1E.1c.2f=$d.2T.3l},4W:l(){$n.d=2y.8D(1a 1G($n.y,$n.M,0).2F(),$n.d);$1w.2c($n);h.2p();k(!$f.6v)k(h.1u($n)){4n();1n($f.1K)}k($f.6u)2g(\"6u\")},6l:l(){$d.2S.1q=l(){k(!2g(\"8q\")){$f.z[$f.1z]=\"\";$c.3R(\"\");4n();1n($f.1K);k($f.6n)2g(\"6n\")}};$d.1U.1q=l(){2O()};k(h.1u($1B)){$d.28.1N=1m;$d.28.1q=l(){$n.2c($1B);2O()}}q $d.28.1N=19},6F:l(){o H,G,A,F,C=[],$=5,E=$f.6I.u,b=$f.Z.3A;k(E>$)E=$;q k(b==\"m\"||b==\"s\")C=[-60,-30,0,30,60,-15,15,-45,45];q 1b(H=0;H<$;H++)C[H]=$n[b]-2+H;1b(H=G=0;H<E;H++){A=h.3P($f.6I[H]);k(h.1u(A))h.2Y[G++]=A}o B=\"2N\",D=[1,1,1,0,0,0];1b(H=0;H<=B.1o(b);H++)D[H]=$n[B.1J(H)];1b(H=0;G<$;H++)k(H<C.u){A=1a 1C(D[0],D[1],D[2],D[3],D[4],D[5]);A[b]=C[H];A.20();k(h.1u(A))h.2Y[G++]=A}q h.2Y[G++]=1i}};l 4n(){o b=$f.z;8F{k(b.1c.2h!=\"2E\"&&b.3o!=\"6A\"&&(b.6D.3X()==\"1v\"||b.6D.3X()==\"8G\")){k($f.8N==b)$f.z[\"4m\"]=19;$f.z.2d();t}}8O($){}b[\"4m\"]=1m}l 2s(){h.s=1a 7h();h.i=0;h.a=l($){h.s[h.i++]=$};h.j=l(){t h.s.7r(\"\")}}l 4t($,B){B=B||0;o b=1a 1G($.y,$.M-1,$.d+B);b.6z(b.2F()-(b.21()+6)%7+$f.7v-1);o A=b.6J();b.7m(0);b.6z(4);t 2y.6X((A-b.6J())/(7*6T))+1}l 21($){o b=1a 1G($.y,$.M-1,$.d);t b.21()}l 24(){3s(2Q,\"\")}l 3w(){3s(2Q,\"6K\")}l 1n(){3s(2Q,\"2E\")}l 3s(b,$){1b(i=0;i<b.u;i++)b[i].1c.2h=$}l 2M(b,$){$?24(b):1n(b)}l 3G(b,$){k($)b.1N=1m;q{b.1N=19;b.1g=\"7T\"}}l c(p,1H){k(p==\"M\")1H=43(1H,1,12);q k(p==\"H\")1H=43(1H,0,23);q k(\"5k\".1o(p)>=0)1H=43(1H,0,59);k($1w[p]!=1H&&!2g(p+\"7U\")){o 6o=\"1T(\\\\\"\"+p+\"\\\\\",\"+1H+\")\",3B=$c.2L();k(3B==0)2W(6o);q k(3B<0)4D($c.1X);q k(3B>0)4D($c.1Z);$d.1U.1N=!$c.1u($1w);k(\"7C\".1o(p)>=0)$c.4C();2g(p+\"7D\")}l 4D($){4u($c.1u($)?$:$1w)}}l 4u($){1T(\"y\",$.y);1T(\"M\",$.M);1T(\"d\",$.d);1T(\"H\",$.H);1T(\"m\",$.m);1T(\"s\",$.s)}l 2O(F,B,b,D,C,A){o $=1a 1C($n.y,$n.M,$n.d,$n.H,$n.m,$n.s);$n.1R(F,B,b,D,C,A);k(!2g(\"7H\")){o E=$.y==F&&$.M==B&&$.d==b;k(!E&&2Q.u!=0){c(\"y\",F);c(\"M\",B);c(\"d\",b);$c.1f=$f.z;k($f.2z)$c.2p()}k($c.2P||E||2Q.u==0)$c.4W()}q $n=$}l 2g($){o b;k($f[$])b=$f[$].4V($f.z,$f);t b}l 1T(b,$){k($==1i)$=$n[b];$1w[b]=$n[b]=$;k(\"7K\".1o(b)>=0)$d[b+\"I\"].1g=$;k(b==\"M\"){$d.1M[\"3v\"]=$;$d.1M.1g=$1k.29[$-1]}}l 43(b,$,A){k(b<$)b=$;q k(b>A)b=A;t b}l 6M($,b){$.2I(\"4c\",l(){o $=1Y,A=($.4M==4Y)?$.4F:$.4M;k(A==9)b()})}l 3n($,b){$=$+\"\";3i($.u<b)$=\"0\"+$;t $}l 3t(){1n($d.2J,$d.3T,$d.6R,$d.6Q,$d.6O)}l 4Z($){k($c.1f==4Y)$c.1f=$d.2V;2G($c.1f){1e $d.2V:c(\"H\",$n.H+$);1h;1e $d.3r:c(\"m\",$n.m+$);1h;1e $d.3I:c(\"s\",$n.s+$);1h}k($f.2z)$c.2p()}l 1C(D,A,$,C,B,b){h.1R(D,A,$,C,B,b)}1C.2X={1R:l(E,B,b,D,C,A){o $=1a 1G();h.y=1p(E,h.y,$.52());h.M=1p(B,h.M,$.5a()+1);h.d=$f.Z.d?1p(b,h.d,$.2F()):1;h.H=1p(D,h.H,$.54());h.m=1p(C,h.m,$.53());h.s=1p(A,h.s,$.56())},2c:l($){k($)h.1R($.y,$.M,$.d,$.H,$.m,$.s)},6r:l(E,B,b,D,C,A){o $=1a 1G();h.y=1p(h.y,E,$.52());h.M=1p(h.M,B,$.5a()+1);h.d=$f.Z.d?1p(h.d,b,$.2F()):1;h.H=1p(h.H,D,$.54());h.m=1p(h.m,C,$.53());h.s=1p(h.s,A,$.56())},2r:l($,C){o A=\"2N\",b,B;C=A.1o(C);C=C>=0?C:5;1b(o D=0;D<=C;D++){B=A.1J(D);b=h[B]-$[B];k(b>0)t 1;q k(b<0)t-1}t 0},20:l(){o $=1a 1G(h.y,h.M-1,h.d,h.H,h.m,h.s);h.y=$.52();h.M=$.5a()+1;h.d=$.2F();h.H=$.54();h.m=$.53();h.s=$.56();t!6j(h.y)},2C:l(b,$){k(\"2N\".1o(b)>=0){o A=h.d;k(b==\"M\")h.d=1;h[b]+=$;h.20();h.d=A}}};l 2e($){t 7F($,10)}l 3E($,b){t 2K(2e($),b)}l 1p($,A,b){t 3E($,2K(A,b))}l 2K($,b){t $==1i||6j($)?b:$}l 4I(A,$){k($6m)A.4I(\"6p\"+$);q{o b=1Q.82(\"88\");b.7W($,19,19);A.7X(b)}}l 3J($){o A,B,b=\"y,M,H,m,s,6E,6H\".4O(\",\");1b(B=0;B<b.u;B++){A=b[B];k($d[A+\"I\"]==$)t A.4T(A.u-1,A.u)}t 0}l 6k($){o b=3J(h);k(!b)t;$c.1f=h;k(b==\"y\")h.1d=\"6x\";q k(b==\"M\"){h.1d=\"6x\";h.1g=h[\"3v\"]}h.4U();$c[\"2R\"+b](h);3w($d[b+\"D\"])}l 3L(6y){o p=3J(h),2j,51,v=h.1g,6C=$n[p];k(p==0)t;$n[p]=6B(v)>=0?6B(v):$n[p];k(p==\"y\"){2j=h==$d.2D;k(2j&&$n.M==12)$n.y-=1}q k(p==\"M\"){2j=h==$d.2i;k(2j){51=$1k.29[$n[p]-1];k(6C==12)$n.y+=1;$n.2C(\"M\",-1)}k($1w.M==$n.M)h.1g=51||$1k.29[$n[p]-1];k(($1w.y!=$n.y))c(\"y\",$n.y)}2W(\"c(\\\\\"\"+p+\"\\\\\",\"+$n[p]+\")\");k(6y!==19){k(p==\"y\"||p==\"M\")h.1d=\"3M\";1n($d[p+\"D\"])}k($f.2z)$c.2p()}l 3k($){k($.25){$.25();$.8i()}q{$.4S=19;$.6G=1m}k($5t)$.4F=0}l 4Q($){o A=$.4O(\",\");1b(o B=0;B<A.u;B++){o b=A[B]+\"I\";$d[b].8u=6k;$d[b].2n=3L}}l 4R(M){o H=M.6w||M.6t,Q=M.4M||M.4F;58=$f.1K.1c.2h!=\"2E\";k(Q>=8m&&Q<=8U)Q-=48;k($f.8I&&58){k(!H.3q){H.3q=$f.1W[1];$c.1f=$f.z}k(H==$f.z)$c.1f=$f.z;k(Q==27)k(H==$f.z){$c.3Q();t}q $f.z.2d();k(Q>=37&&Q<=40){o U;k($c.1f==$f.z||$c.1f==$d.1U)k($f.Z.d){U=\"d\";k(Q==38)$n[U]-=7;q k(Q==39)$n[U]+=1;q k(Q==37)$n[U]-=1;q $n[U]+=7;$n.20();c(\"y\",$n[\"y\"]);c(\"M\",$n[\"M\"]);c(\"d\",$n[U]);3k(M);t}q{U=$f.Z.3A;$d[U+\"I\"].2d()}U=U||3J($c.1f);k(U){k(Q==38||Q==39)$n[U]+=1;q $n[U]-=1;$n.20();$c.1f.1g=$n[U];3L.4V($c.1f,19);$c.1f.4U()}}q k(Q==9){o D=H.3q;1b(o R=0;R<$f.1W.u;R++)k(D.1N==19||D.3l==0)D=D.3q;q 1h;k($c.1f!=D){$c.1f=D;D.2d()}}q k(Q==13){3L.4V($c.1f);k($c.1f.3o==\"1O\")$c.1f.8P();q $c.4W();$c.1f=$f.z}}q k(Q==9&&H==$f.z)$c.3Q();k($f.8S&&!$5t&&!$f.3N&&$c.1f==$f.z&&(Q>=48&&Q<=57)){o T=$f.z,S=T.1g,F=E(T),I={22:\"\",1s:[]},R=0,K,N=0,X=0,O=0,J,b=/3a|2l|36|y|3U|M|1K|d|%2k|4J|H|4K|m|4G|s|4H|W|w/g,L=$f.1y.35(b),B,A,$,V,W,G,J=0;k(S!=\"\"){O=S.35(/[0-9]/g);O=O==1i?0:O.u;1b(R=0;R<L.u;R++)O-=2y.5v(L[R].u,2);O=O>=0?1:0;k(O==1&&F>=S.u)F=S.u-1}S=S.1F(0,F)+8r.8v(Q)+S.1F(F+O);F++;1b(R=0;R<S.u;R++){o C=S.1J(R);k(/[0-9]/.4P(C))I.22+=C;q I.1s[R]=1}S=\"\";b.2x=0;3i((K=b.3h($f.1y))!==1i){X=K.3x-(K[0]==\"%2k\"?1:0);k(N>=0){S+=$f.1y.1F(N,X);k(F>=N+J&&F<=X+J)F+=X-N}N=b.2x;G=N-X;B=I.22.1F(0,G);A=K[0].1J(0);$=2e(B.1J(0));k(I.22.u>1){V=I.22.1J(1);W=$*10+2e(V)}q{V=\"\";W=$}k(I.1s[X+1]||A==\"M\"&&W>12||A==\"d\"&&W>31||A==\"H\"&&W>23||\"5k\".1o(A)>=0&&W>59){k(K[0].u==2)B=\"0\"+$;q B=$;F++}q k(G==1){B=W;G++;J++}S+=B;I.22=I.22.1F(G);k(I.22==\"\")1h}T.1g=S;P(T,F);3k(M)}k(58&&$c.1f!=$f.z&&!((Q>=48&&Q<=57)||Q==8||Q==46))3k(M);l E(A){o b=0;k($f.4N.1Q.6d){o B=$f.4N.1Q.6d.6U(),$=B.55.u;B.5V(\"4X\",-A.1g.u);b=B.55.u-$}q k(A.4L||A.4L==\"0\")b=A.4L;t b}l P(b,A){k(b.5U){b.2d();b.5U(A,A)}q k(b.5W){o $=b.5W();$.7w(19);$.7y(\"4X\",A);$.5V(\"4X\",A);$.4U()}}}',62,555,'|||||||||||_||||dp||this|||if|function||dt|var||else|||return|length|||div||el|||||||||||||||||||||||||class|has|||||||||td|true|new|for|style|className|case|currFocus|value|break|null|tr|lang|replace|false|hide|indexOf|pInt3|onclick|divs|arr|yI|checkValid|input|sdt|table|dateFmt|elProp|menu|tdt|DPDate|id|qsDivSel|substring|Date|pv|ipts|charAt|dd|innerHTML|MI|disabled|button|ny|document|loadDate|realFmt|sv|okI|getP|focusArr|minDate|event|maxDate|refresh|getDay|str||show|preventDefault|||todayI|aMonStr|st|9700|loadFromDate|focus|pInt|height|callFunc|display|rMI|isR|ld|yyy|cellpadding|onblur|cellspacing|update|onmouseout|compareWith|sb|onmouseover|border|left|date|lastIndex|Math|autoUpdateOnChanged|MMMM|tmpEval|attr|ryI|none|getDate|switch|tDiv|attachEvent|yD|rtn|checkRange|shorH|yMdHms|day_Click|autoPickDate|arguments|_f|clearI|dDiv|width|HI|eval|prototype|QS|MMM||||menuSel|doExp|match|yy||||yyyy|splitDate|DD|nowrap|menuOn|_initRe|float|exec|while|realFullFmt|_cancelKey|offsetHeight|mark|doStr|type|100|nextCtrl|mI|setDisp|hideSel|sd|realValue|showB|index|navLeftImg|bDiv|minUnit|rv|_fHMS|ps|pInt2|_fd|disHMS|navImg|sI|_foundInput|rMD|_blur|yminput|readOnly|oldValue|doCustomDate|close|setRealValue|getDateStr|MD|MM|leftImg|href|toLowerCase|navRightImg|onmousedown||firstDayOfWeek|rightImg|makeInRange|isDate|||testDate||ddateRe|isTime|maxlength|onkeydown|WdateDiv|dpButton|errMsg|btns|span|qsDiv|isShowOK|titleDiv|realDateFmt|My97Mark|elFocus|getElementsByTagName|_fillQS|appendChild|RegExp|getNewDateStr|getWeek|_setAll|_fy|blur|testDay|fp|invalidMenu|align|nbsp|draw|_setFrom|_fMyPos|keyCode|ss|WW|fireEvent|HH|mm|selectionStart|which|win|split|test|_inputBindEvent|_tab|cancelBubble|slice|select|call|pickDate|character|undefined|updownEvent||mStr|getFullYear|getMinutes|getHours|text|getSeconds||isShow||getMonth|bak|initShowAndHide|realTimeFmt|opposite|MTitle|WdayTable|center|right|_dealFmt|ms|xd7|aLongMonStr|doubleCalendar|cloneNode|yearOffset|valign|top|isShowOthers|OPERA|FF|max|isShowClear|isShowToday|aWeekStr|2000|setAttribute|WdateFmtErr|sdayRe|defMinDate|defMaxDate|init|spans|My97DP|title|_makeDateInRange|cal|timeSpan|nodeType|readonly|tE|tm|Event|_ieEmuEventHandler|upButton|downButton|setSelectionRange|moveStart|createTextRange|default|abs|testDisDate||isShowWeek|checkAndUpdate|highLineWeekDay|sdateRe|testSpeDay|testSpeDate|testDisDay|ddayRe|02468|13579|startDate|re|selection|469|newdate|01|13578|02|isNaN|_focus|initBtn|IE|oncleared|func|on|offsetWidth|coverDate|px|target|onpicked|eCont|srcElement|yminputfocus|showDiv|setDate|hidden|Number|oldv|nodeName|ry|initQS|returnValue|rM|quickSel|valueOf|block|window|attachTabEvent|body|sD|autoSize|mD|HD|Function|86400000|createRange|vel|NavImgll|round|dpTitle|typeof|object|link|rel|change|1235679|onchange|NavImgl|substr|1900|skin|MMenu|alwaysUseStartDate|WotherDay|Wtoday|__defineGetter__|HTMLElement|parentNode|Array|WwdayOn|WdayOn|Wwday|Wday|setMonth|__defineSetter__|tB|048|createElement|join|Wselday|addEventListener|01345789|whichDayIsfirstWeek|collapse|dpTime|moveEnd|dpTodayInput|hhMenu|overflow|yMd|changed|dpOkInput|parseInt|dpClearInput|onpicking|dpTimeUp|rowspan|yHms|dpTimeStr|mmMenu|dpControl|dpQS|ssMenu|dpTimeDown|timeStr|clearStr|00|changing|err_1|initEvent|dispatchEvent|alert|todayStr|okStr|YMenu|createEvent|NavImgrr|NavImgr|absolute|position|specialDays|HTMLEvents|specialDates|disabledDates|disabledDays|_fs|ydHmswW|_fm|scrollHeight|quickStr|Hms|stopPropagation|contentWindow|iframe|u2190|96|_fH|getNewP|u2192|onclearing|String|errDealMode|qsEnabled|onfocus|fromCharCode|Time|1000|pointer|cursor|aLongWeekStr|confirm|errAlertMsg|min|_fM|try|textarea|Wweek|enableKeyboard|autoShowQS|WspecialDay|WotherDayOn|WinvalidDay|srcEl|catch|click|offsetLeft|WdayTable2|enableInputMask|WdateDiv2|105|getBoundingClientRect|parent'.split('|'),0,{}))"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/My97DatePicker/config.js",
    "content": "var langList = \n[\n\t{name:'en',\tcharset:'UTF-8'},\n\t{name:'zh-cn',\tcharset:'UTF-8'},\n\t{name:'zh-tw',\tcharset:'UTF-8'}\n];\n\nvar skinList = \n[\n\t{name:'default',\tcharset:'UTF-8'},\n\t{name:'whyGreen',\tcharset:'UTF-8'}\n];"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/My97DatePicker/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": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/My97DatePicker/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": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/My97DatePicker/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": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/My97DatePicker/skin/WdatePicker.css",
    "content": ".Wdate{\n\tborder:#999 1px solid;\n\theight:20px;\n\tbackground:#fff url(datePicker.gif) no-repeat right;\n}\n\n.WdateFmtErr{\n\tfont-weight:bold;\n\tcolor:red;\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/My97DatePicker/skin/default/datepicker.css",
    "content": "/* \n * My97 DatePicker 4.7\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:#ccc 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:#BDEBEE 1px solid;\n }\n\n.WdateDiv .MTitle{\n\tbackground-color:#BDEBEE;\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:#C0EBEF;\n}\n\n.WdateDiv .Wwday{\n\tcursor:pointer;\n\tcolor:#FF2F2F;\n}\n\n.WdateDiv .WwdayOn{\n\tcursor:pointer;\n\tcolor:#000;\n\tbackground-color:#C0EBEF;\n}\n.WdateDiv .Wtoday{\n\tcursor:pointer;\n\tcolor:blue;\n}\n.WdateDiv .Wselday{\n\tbackground-color:#A9E4E9;\n}\n.WdateDiv .WspecialDay{\n\tbackground-color:#66F4DF;\n}\n\n.WdateDiv .WotherDay{ \n\tcursor:pointer;\n\tcolor:#6A6AFF;\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}\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": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/My97DatePicker/skin/whyGreen/datepicker.css",
    "content": "/* \n * My97 DatePicker 4.7 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": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/My97DatePicker/test_02.html",
    "content": "<HTML>\n<HEAD>\n<META http-equiv='Content-Type' content='text/html; charset=gb2312'>\n<TITLE></TITLE>\n<script src=\"WdatePicker.js\" type=\"text/javascript\"></script>\n</HEAD>\n<BODY>\n<form action=\"\" name=\"myform\">\n<input type=\"text\" id=\"d241\" onfocus=\"WdatePicker({dateFmt:'yyyy-MM-dd HH:mm:ss'})\" class=\"Wdate\" style=\"width:300px\"/>\n</form>\n</BODY>\n</HTML>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/bootstrap/bootstrap3/css/bootstrap-theme.css",
    "content": "/*!\n * Bootstrap v3.0.3 (http://getbootstrap.com)\n * Copyright 2013 Twitter, Inc.\n * Licensed under http://www.apache.org/licenses/LICENSE-2.0\n */\n\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.btn-default:active,\n.btn-primary:active,\n.btn-success:active,\n.btn-info:active,\n.btn-warning:active,\n.btn-danger:active,\n.btn-default.active,\n.btn-primary.active,\n.btn-success.active,\n.btn-info.active,\n.btn-warning.active,\n.btn-danger.active {\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:active,\n.btn.active {\n  background-image: none;\n}\n\n.btn-default {\n  text-shadow: 0 1px 0 #fff;\n  background-image: -webkit-linear-gradient(top, #ffffff 0%, #e0e0e0 100%);\n  background-image: linear-gradient(to bottom, #ffffff 0%, #e0e0e0 100%);\n  background-repeat: repeat-x;\n  border-color: #dbdbdb;\n  border-color: #ccc;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-default:hover,\n.btn-default:focus {\n  background-color: #e0e0e0;\n  background-position: 0 -15px;\n}\n\n.btn-default:active,\n.btn-default.active {\n  background-color: #e0e0e0;\n  border-color: #dbdbdb;\n}\n\n.btn-primary {\n  background-image: -webkit-linear-gradient(top, #428bca 0%, #2d6ca2 100%);\n  background-image: linear-gradient(to bottom, #428bca 0%, #2d6ca2 100%);\n  background-repeat: repeat-x;\n  border-color: #2b669a;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-primary:hover,\n.btn-primary:focus {\n  background-color: #2d6ca2;\n  background-position: 0 -15px;\n}\n\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #2d6ca2;\n  border-color: #2b669a;\n}\n\n.btn-success {\n  background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);\n  background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);\n  background-repeat: repeat-x;\n  border-color: #3e8f3e;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-success:hover,\n.btn-success:focus {\n  background-color: #419641;\n  background-position: 0 -15px;\n}\n\n.btn-success:active,\n.btn-success.active {\n  background-color: #419641;\n  border-color: #3e8f3e;\n}\n\n.btn-warning {\n  background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);\n  background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);\n  background-repeat: repeat-x;\n  border-color: #e38d13;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-warning:hover,\n.btn-warning:focus {\n  background-color: #eb9316;\n  background-position: 0 -15px;\n}\n\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #eb9316;\n  border-color: #e38d13;\n}\n\n.btn-danger {\n  background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);\n  background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);\n  background-repeat: repeat-x;\n  border-color: #b92c28;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-danger:hover,\n.btn-danger:focus {\n  background-color: #c12e2a;\n  background-position: 0 -15px;\n}\n\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #c12e2a;\n  border-color: #b92c28;\n}\n\n.btn-info {\n  background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);\n  background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);\n  background-repeat: repeat-x;\n  border-color: #28a4c9;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.btn-info:hover,\n.btn-info:focus {\n  background-color: #2aabd2;\n  background-position: 0 -15px;\n}\n\n.btn-info:active,\n.btn-info.active {\n  background-color: #2aabd2;\n  border-color: #28a4c9;\n}\n\n.thumbnail,\n.img-thumbnail {\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n}\n\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n  background-color: #e8e8e8;\n  background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n  background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);\n}\n\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n  background-color: #357ebd;\n  background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%);\n  background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);\n}\n\n.navbar-default {\n  background-image: -webkit-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);\n  background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%);\n  background-repeat: repeat-x;\n  border-radius: 4px;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);\n}\n\n.navbar-default .navbar-nav > .active > a {\n  background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f3f3f3 100%);\n  background-image: linear-gradient(to bottom, #ebebeb 0%, #f3f3f3 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0);\n  -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);\n}\n\n.navbar-brand,\n.navbar-nav > li > a {\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);\n}\n\n.navbar-inverse {\n  background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222222 100%);\n  background-image: linear-gradient(to bottom, #3c3c3c 0%, #222222 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.navbar-inverse .navbar-nav > .active > a {\n  background-image: -webkit-linear-gradient(top, #222222 0%, #282828 100%);\n  background-image: linear-gradient(to bottom, #222222 0%, #282828 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0);\n  -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);\n          box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);\n}\n\n.navbar-inverse .navbar-brand,\n.navbar-inverse .navbar-nav > li > a {\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  border-radius: 0;\n}\n\n.alert {\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.alert-success {\n  background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);\n  background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);\n  background-repeat: repeat-x;\n  border-color: #b2dba1;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);\n}\n\n.alert-info {\n  background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);\n  background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);\n  background-repeat: repeat-x;\n  border-color: #9acfea;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);\n}\n\n.alert-warning {\n  background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);\n  background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);\n  background-repeat: repeat-x;\n  border-color: #f5e79e;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);\n}\n\n.alert-danger {\n  background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);\n  background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);\n  background-repeat: repeat-x;\n  border-color: #dca7a7;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);\n}\n\n.progress {\n  background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);\n  background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);\n}\n\n.progress-bar {\n  background-image: -webkit-linear-gradient(top, #428bca 0%, #3071a9 100%);\n  background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0);\n}\n\n.progress-bar-success {\n  background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);\n  background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);\n}\n\n.progress-bar-info {\n  background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);\n  background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);\n}\n\n.progress-bar-warning {\n  background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);\n  background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);\n}\n\n.progress-bar-danger {\n  background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);\n  background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);\n}\n\n.list-group {\n  border-radius: 4px;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n}\n\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n  text-shadow: 0 -1px 0 #3071a9;\n  background-image: -webkit-linear-gradient(top, #428bca 0%, #3278b3 100%);\n  background-image: linear-gradient(to bottom, #428bca 0%, #3278b3 100%);\n  background-repeat: repeat-x;\n  border-color: #3278b3;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0);\n}\n\n.panel {\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.panel-default > .panel-heading {\n  background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n  background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);\n}\n\n.panel-primary > .panel-heading {\n  background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%);\n  background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);\n}\n\n.panel-success > .panel-heading {\n  background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);\n  background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);\n}\n\n.panel-info > .panel-heading {\n  background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);\n  background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);\n}\n\n.panel-warning > .panel-heading {\n  background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);\n  background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);\n}\n\n.panel-danger > .panel-heading {\n  background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);\n  background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);\n}\n\n.well {\n  background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);\n  background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);\n  background-repeat: repeat-x;\n  border-color: #dcdcdc;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);\n          box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/bootstrap/bootstrap3/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v3.0.3 (http://getbootstrap.com)\n * Copyright 2013 Twitter, Inc.\n * Licensed under http://www.apache.org/licenses/LICENSE-2.0\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;\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\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\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: #8a6d3b;\n}\n\n.text-warning:hover {\n  color: #66512c;\n}\n\n.text-danger {\n  color: #a94442;\n}\n\n.text-danger:hover {\n  color: #843534;\n}\n\n.text-success {\n  color: #3c763d;\n}\n\n.text-success:hover {\n  color: #2b542c;\n}\n\n.text-info {\n  color: #31708f;\n}\n\n.text-info:hover {\n  color: #245269;\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\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-top: 0;\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\n.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,\nblockquote .small {\n  display: block;\n  line-height: 1.428571429;\n  color: #999999;\n}\n\nblockquote small:before,\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: Menlo, Monaco, 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@media (min-width: 768px) {\n  .container {\n    width: 750px;\n  }\n}\n\n@media (min-width: 992px) {\n  .container {\n    width: 970px;\n  }\n}\n\n@media (min-width: 1200px) {\n  .container {\n    width: 1170px;\n  }\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.col-xs-12 {\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  .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  .col-sm-12 {\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  .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  .col-md-12 {\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  .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  .col-lg-12 {\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  position: static;\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 > .active,\n.table > tbody > tr > .active,\n.table > tfoot > tr > .active,\n.table > thead > .active > td,\n.table > tbody > .active > td,\n.table > tfoot > .active > td,\n.table > thead > .active > th,\n.table > tbody > .active > th,\n.table > tfoot > .active > th {\n  background-color: #f5f5f5;\n}\n\n.table-hover > tbody > tr > .active:hover,\n.table-hover > tbody > .active:hover > td,\n.table-hover > tbody > .active:hover > th {\n  background-color: #e8e8e8;\n}\n\n.table > thead > tr > .success,\n.table > tbody > tr > .success,\n.table > tfoot > tr > .success,\n.table > thead > .success > td,\n.table > tbody > .success > td,\n.table > tfoot > .success > td,\n.table > thead > .success > th,\n.table > tbody > .success > th,\n.table > tfoot > .success > th {\n  background-color: #dff0d8;\n}\n\n.table-hover > tbody > tr > .success:hover,\n.table-hover > tbody > .success:hover > td,\n.table-hover > tbody > .success:hover > th {\n  background-color: #d0e9c6;\n}\n\n.table > thead > tr > .danger,\n.table > tbody > tr > .danger,\n.table > tfoot > tr > .danger,\n.table > thead > .danger > td,\n.table > tbody > .danger > td,\n.table > tfoot > .danger > td,\n.table > thead > .danger > th,\n.table > tbody > .danger > th,\n.table > tfoot > .danger > th {\n  background-color: #f2dede;\n}\n\n.table-hover > tbody > tr > .danger:hover,\n.table-hover > tbody > .danger:hover > td,\n.table-hover > tbody > .danger:hover > th {\n  background-color: #ebcccc;\n}\n\n.table > thead > tr > .warning,\n.table > tbody > tr > .warning,\n.table > tfoot > tr > .warning,\n.table > thead > .warning > td,\n.table > tbody > .warning > td,\n.table > tfoot > .warning > td,\n.table > thead > .warning > th,\n.table > tbody > .warning > th,\n.table > tfoot > .warning > th {\n  background-color: #fcf8e3;\n}\n\n.table-hover > tbody > tr > .warning:hover,\n.table-hover > tbody > .warning:hover > td,\n.table-hover > tbody > .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;\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  opacity: 1;\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: 46px;\n  padding: 10px 16px;\n  font-size: 18px;\n  line-height: 1.33;\n  border-radius: 6px;\n}\n\nselect.input-lg {\n  height: 46px;\n  line-height: 46px;\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: #8a6d3b;\n}\n\n.has-warning .form-control {\n  border-color: #8a6d3b;\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: #66512c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;\n}\n\n.has-warning .input-group-addon {\n  color: #8a6d3b;\n  background-color: #fcf8e3;\n  border-color: #8a6d3b;\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: #a94442;\n}\n\n.has-error .form-control {\n  border-color: #a94442;\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: #843534;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;\n}\n\n.has-error .input-group-addon {\n  color: #a94442;\n  background-color: #f2dede;\n  border-color: #a94442;\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: #3c763d;\n}\n\n.has-success .form-control {\n  border-color: #3c763d;\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: #2b542c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;\n}\n\n.has-success .input-group-addon {\n  color: #3c763d;\n  background-color: #dff0d8;\n  border-color: #3c763d;\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 select.form-control {\n    width: auto;\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 .radio,\n.form-horizontal .checkbox {\n  min-height: 27px;\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;\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-default .badge {\n  color: #ffffff;\n  background-color: #fff;\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-primary .badge {\n  color: #428bca;\n  background-color: #fff;\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-warning .badge {\n  color: #f0ad4e;\n  background-color: #fff;\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-danger .badge {\n  color: #d9534f;\n  background-color: #fff;\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-success .badge {\n  color: #5cb85c;\n  background-color: #fff;\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-info .badge {\n  color: #5bc0de;\n  background-color: #fff;\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  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  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\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;\n  border-right: 4px solid transparent;\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;\n  border-bottom: 4px solid;\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-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: 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.btn-group-vertical > .btn-group > .btn {\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.btn-group-justified > .btn-group {\n  display: table-cell;\n  float: none;\n  width: 1%;\n}\n\n.btn-group-justified > .btn-group .btn {\n  width: 100%;\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[class*=\"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: 46px;\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: 46px;\n  line-height: 46px;\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 .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-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-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: visible;\n  }\n  .navbar-fixed-top .navbar-collapse,\n  .navbar-static-top .navbar-collapse,\n  .navbar-fixed-bottom .navbar-collapse {\n    padding-right: 0;\n    padding-left: 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  background-image: none;\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  .navbar-nav.navbar-right:last-child {\n    margin-right: -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 select.form-control {\n    width: auto;\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  .navbar-form.navbar-right:last-child {\n    margin-right: -15px;\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-btn.btn-sm {\n  margin-top: 10px;\n  margin-bottom: 10px;\n}\n\n.navbar-btn.btn-xs {\n  margin-top: 14px;\n  margin-bottom: 14px;\n}\n\n.navbar-text {\n  margin-top: 15px;\n  margin-bottom: 15px;\n}\n\n@media (min-width: 768px) {\n  .navbar-text {\n    float: left;\n    margin-right: 15px;\n    margin-left: 15px;\n  }\n  .navbar-text.navbar-right:last-child {\n    margin-right: 0;\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 > .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@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@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 .divider {\n    background-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.btn .label {\n  position: relative;\n  top: -1px;\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\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\na.badge:hover,\na.badge:focus {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\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.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.jumbotron .container {\n  max-width: 100%;\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  .jumbotron .h1 {\n    font-size: 63px;\n  }\n}\n\n.thumbnail {\n  display: block;\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.thumbnail a > 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: #3c763d;\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: #2b542c;\n}\n\n.alert-info {\n  color: #31708f;\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: #245269;\n}\n\n.alert-warning {\n  color: #8a6d3b;\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: #66512c;\n}\n\n.alert-danger {\n  color: #a94442;\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: #843534;\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@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-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-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-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-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-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 > .table {\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 > tbody:first-child th,\n.panel > .table > tbody:first-child td {\n  border-top: 0;\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 > .table-responsive {\n  margin-bottom: 0;\n  border: 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  color: inherit;\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-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-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: #3c763d;\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-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: #8a6d3b;\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-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: #a94442;\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-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: #31708f;\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-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  margin: 10px;\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    margin: 30px auto;\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-linear-gradient(left, color-stop(rgba(0, 0, 0, 0.5) 0), color-stop(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-linear-gradient(left, color-stop(rgba(0, 0, 0, 0.0001) 0), color-stop(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  outline: 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  table.visible-xs {\n    display: table;\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  table.visible-xs.visible-sm {\n    display: table;\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  table.visible-xs.visible-md {\n    display: table;\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  table.visible-xs.visible-lg {\n    display: table;\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  table.visible-sm.visible-xs {\n    display: table;\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  table.visible-sm {\n    display: table;\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  table.visible-sm.visible-md {\n    display: table;\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  table.visible-sm.visible-lg {\n    display: table;\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  table.visible-md.visible-xs {\n    display: table;\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  table.visible-md.visible-sm {\n    display: table;\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  table.visible-md {\n    display: table;\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  table.visible-md.visible-lg {\n    display: table;\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  table.visible-lg.visible-xs {\n    display: table;\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  table.visible-lg.visible-sm {\n    display: table;\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  table.visible-lg.visible-md {\n    display: table;\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  table.visible-lg {\n    display: table;\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\ntable.hidden-xs {\n  display: table;\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\ntable.hidden-sm {\n  display: table;\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\ntable.hidden-md {\n  display: table;\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\ntable.hidden-lg {\n  display: table;\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  table.visible-print {\n    display: table;\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": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/bootstrap/bootstrap3/js/bootstrap.js",
    "content": "/*!\n * Bootstrap v3.0.3 (http://getbootstrap.com)\n * Copyright 2013 Twitter, Inc.\n * Licensed under http://www.apache.org/licenses/LICENSE-2.0\n */\n\nif (typeof jQuery === \"undefined\") { throw new Error(\"Bootstrap requires jQuery\") }\n\n/* ========================================================================\n * Bootstrap: transition.js v3.0.3\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.3\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.3\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    var changed = true\n\n    if ($parent.length) {\n      var $input = this.$element.find('input')\n      if ($input.prop('type') === 'radio') {\n        // see if clicking on current one\n        if ($input.prop('checked') && this.$element.hasClass('active'))\n          changed = false\n        else\n          $parent.find('.active').removeClass('active')\n      }\n      if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change')\n    }\n\n    if (changed) 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.3\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.bs.carousel', 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.bs.carousel', 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.bs.carousel') }, 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.bs.carousel')\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.3\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.3\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    $(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 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('bs.dropdown')\n\n      if (!data) $this.data('bs.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.3\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.3\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.3\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.3\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.bs.scrollspy')\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.3\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.3\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": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/bootstrap/jquery/jquery-1.11.0.js",
    "content": "/*!\n * jQuery JavaScript Library v1.11.0\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: 2014-01-23T21:02Z\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 is present,\n\t\t// execute the factory and get jQuery\n\t\t// For environments that do not inherently posses a window with a document\n\t\t// (such as Node.js), expose a jQuery-making 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// 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//\n\nvar deletedIds = [];\n\nvar slice = deletedIds.slice;\n\nvar concat = deletedIds.concat;\n\nvar push = deletedIds.push;\n\nvar indexOf = deletedIds.indexOf;\n\nvar class2type = {};\n\nvar toString = class2type.toString;\n\nvar hasOwn = class2type.hasOwnProperty;\n\nvar trim = \"\".trim;\n\nvar support = {};\n\n\n\nvar\n\tversion = \"1.11.0\",\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// 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// 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 a 'clean' array\n\t\t\t( num < 0 ? this[ num + this.length ] : this[ num ] ) :\n\n\t\t\t// Return just the object\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: deletedIds.sort,\n\tsplice: deletedIds.splice\n};\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\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\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\t/* jshint eqeqeq: false */\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\treturn obj - parseFloat( obj ) >= 0;\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\tisPlainObject: function( obj ) {\n\t\tvar key;\n\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!hasOwn.call(obj, \"constructor\") &&\n\t\t\t\t!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// Support: IE<9\n\t\t// Handle iteration over inherited properties before own properties.\n\t\tif ( support.ownLast ) {\n\t\t\tfor ( key in obj ) {\n\t\t\t\treturn hasOwn.call( obj, key );\n\t\t\t}\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\t\tfor ( key in obj ) {}\n\n\t\treturn key === undefined || hasOwn.call( obj, key );\n\t},\n\n\ttype: function( obj ) {\n\t\tif ( obj == null ) {\n\t\t\treturn obj + \"\";\n\t\t}\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\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: trim && !trim.call(\"\\uFEFF\\xA0\") ?\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\ttrim.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\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\tvar len;\n\n\t\tif ( arr ) {\n\t\t\tif ( indexOf ) {\n\t\t\t\treturn 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 len = +second.length,\n\t\t\tj = 0,\n\t\t\ti = first.length;\n\n\t\twhile ( j < len ) {\n\t\t\tfirst[ i++ ] = second[ j++ ];\n\t\t}\n\n\t\t// Support: IE<9\n\t\t// Workaround casting of .length to NaN on otherwise arraylike objects (e.g., NodeLists)\n\t\tif ( len !== len ) {\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, 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 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 = 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: function() {\n\t\treturn +( new Date() );\n\t},\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\tvar length = 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 v1.10.16\n * http://sizzlejs.com/\n *\n * Copyright 2013 jQuery Foundation, Inc. and other contributors\n * Released under the MIT license\n * http://jquery.org/license\n *\n * Date: 2014-01-13\n */\n(function( window ) {\n\nvar i,\n\tsupport,\n\tExpr,\n\tgetText,\n\tisXML,\n\tcompile,\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\" + -(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\tstrundefined = typeof undefined,\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 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\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// Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors\n\tattributes = \"\\\\[\" + whitespace + \"*(\" + characterEncoding + \")\" + whitespace +\n\t\t\"*(?:([*^$|!~]?=)\" + 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 + \"*([>+~]|\" + 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\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// 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\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 ( documentIsHTML && !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 (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 && context.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 === 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 ) && 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 !== strundefined && 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,\n\t\tdoc = node ? node.ownerDocument || node : preferredDoc,\n\t\tparent = doc.defaultView;\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\tdocumentIsHTML = !isXML( doc );\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\", function() {\n\t\t\t\tsetDocument();\n\t\t\t}, false );\n\t\t} else if ( parent.attachEvent ) {\n\t\t\tparent.attachEvent( \"onunload\", function() {\n\t\t\t\tsetDocument();\n\t\t\t});\n\t\t}\n\t}\n\n\t/* Attributes\n\t---------------------------------------------------------------------- */\n\n\t// Support: IE<8\n\t// Verify that getAttribute really returns attributes and not properties (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// Check if getElementsByClassName can be trusted\n\tsupport.getElementsByClassName = rnative.test( doc.getElementsByClassName ) && assert(function( div ) {\n\t\tdiv.innerHTML = \"<div class='a'></div><div class='a i'></div>\";\n\n\t\t// Support: Safari<4\n\t\t// Catch class over-caching\n\t\tdiv.firstChild.className = \"i\";\n\t\t// Support: Opera<10\n\t\t// Catch gEBCN failure to find non-leading classes\n\t\treturn div.getElementsByClassName(\"i\").length === 2;\n\t});\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 !== strundefined && 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 !== 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.getElementsByTagName ?\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// Class\n\tExpr.find[\"CLASS\"] = support.getElementsByClassName && function( className, context ) {\n\t\tif ( typeof context.getElementsByClassName !== strundefined && 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\tdiv.innerHTML = \"<select t=''><option selected=''></option></select>\";\n\n\t\t\t// Support: IE8, Opera 10-12\n\t\t\t// Nothing should be selected when empty strings follow ^= or $= or *=\n\t\t\tif ( div.querySelectorAll(\"[t^='']\").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// 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\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.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.call( sortInput, a ) - indexOf.call( 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.call( sortInput, a ) - indexOf.call( 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[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[3] && match[4] !== undefined ) {\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( 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 !== 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 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\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 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 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(\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, 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\tsupport.getById && context.nodeType === 9 && documentIsHTML &&\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\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 ) && testContext( 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, seed );\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\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\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 ( jQuery.inArray( elem, qualifier ) >= 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\tret = [],\n\t\t\tself = this,\n\t\t\tlen = self.length;\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// Use the correct document accordingly with window argument (sandbox)\n\tdocument = window.document,\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.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\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// 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 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\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\njQuery.fn.extend({\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\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\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\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\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 ( name.slice( -5 ) !== \"Until\" ) {\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\tif ( this.length > 1 ) {\n\t\t\t// Remove duplicates\n\t\t\tif ( !guaranteedUnique[ name ] ) {\n\t\t\t\tret = jQuery.unique( ret );\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\tret = ret.reverse();\n\t\t\t}\n\t\t}\n\n\t\treturn this.pushStack( ret );\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 // 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\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\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// 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\n/**\n * Clean-up method for dom ready events\n */\nfunction detach() {\n\tif ( document.addEventListener ) {\n\t\tdocument.removeEventListener( \"DOMContentLoaded\", completed, false );\n\t\twindow.removeEventListener( \"load\", completed, false );\n\n\t} else {\n\t\tdocument.detachEvent( \"onreadystatechange\", completed );\n\t\twindow.detachEvent( \"onload\", completed );\n\t}\n}\n\n/**\n * The ready event handler and self cleanup method\n */\nfunction completed() {\n\t// readyState === \"complete\" is good enough for us to call the dom ready in oldIE\n\tif ( document.addEventListener || event.type === \"load\" || document.readyState === \"complete\" ) {\n\t\tdetach();\n\t\tjQuery.ready();\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\nvar strundefined = typeof undefined;\n\n\n\n// Support: IE<9\n// Iteration over object's inherited properties before its own\nvar i;\nfor ( i in jQuery( support ) ) {\n\tbreak;\n}\nsupport.ownLast = i !== \"0\";\n\n// Note: most support tests are defined in their respective modules.\n// false until the test is run\nsupport.inlineBlockNeedsLayout = false;\n\njQuery(function() {\n\t// We need to execute this one support test ASAP because we need to know\n\t// if body.style.zoom needs to be set.\n\n\tvar container, div,\n\t\tbody = document.getElementsByTagName(\"body\")[0];\n\n\tif ( !body ) {\n\t\t// Return for frameset docs that don't have a body\n\t\treturn;\n\t}\n\n\t// Setup\n\tcontainer = document.createElement( \"div\" );\n\tcontainer.style.cssText = \"border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px\";\n\n\tdiv = document.createElement( \"div\" );\n\tbody.appendChild( container ).appendChild( div );\n\n\tif ( typeof div.style.zoom !== strundefined ) {\n\t\t// Support: IE<8\n\t\t// Check if natively block-level elements act like inline-block\n\t\t// elements when setting their display to 'inline' and giving\n\t\t// them layout\n\t\tdiv.style.cssText = \"border:0;margin:0;width:1px;padding:1px;display:inline;zoom:1\";\n\n\t\tif ( (support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 )) ) {\n\t\t\t// Prevent IE 6 from affecting layout for positioned elements #11048\n\t\t\t// Prevent IE from shrinking the body in IE 7 mode #12869\n\t\t\t// Support: IE<8\n\t\t\tbody.style.zoom = 1;\n\t\t}\n\t}\n\n\tbody.removeChild( container );\n\n\t// Null elements to avoid leaks in IE\n\tcontainer = div = null;\n});\n\n\n\n\n(function() {\n\tvar div = document.createElement( \"div\" );\n\n\t// Execute the test only if not already executed in another module.\n\tif (support.deleteExpando == null) {\n\t\t// Support: IE<9\n\t\tsupport.deleteExpando = true;\n\t\ttry {\n\t\t\tdelete div.test;\n\t\t} catch( e ) {\n\t\t\tsupport.deleteExpando = false;\n\t\t}\n\t}\n\n\t// Null elements to avoid leaks in IE.\n\tdiv = null;\n})();\n\n\n/**\n * Determines whether an object can have data\n */\njQuery.acceptData = function( elem ) {\n\tvar noData = jQuery.noData[ (elem.nodeName + \" \").toLowerCase() ],\n\t\tnodeType = +elem.nodeType || 1;\n\n\t// Do not set data on non-element DOM nodes because it will not be cleared (#8335).\n\treturn nodeType !== 1 && nodeType !== 9 ?\n\t\tfalse :\n\n\t\t// Nodes accept data unless otherwise specified; rejection can be conditional\n\t\t!noData || noData !== true && elem.getAttribute(\"classid\") === noData;\n};\n\n\nvar rbrace = /^(?:\\{[\\w\\W]*\\}|\\[[\\w\\W]*\\])$/,\n\trmultiDash = /([A-Z])/g;\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\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}\n\nfunction internalData( elem, name, data, pvt /* Internal Use Only */ ) {\n\tif ( !jQuery.acceptData( elem ) ) {\n\t\treturn;\n\t}\n\n\tvar ret, thisCache,\n\t\tinternalKey = jQuery.expando,\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)) && data === undefined && typeof name === \"string\" ) {\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\tid = elem[ internalKey ] = 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\t// Avoid exposing jQuery metadata on plain JS objects when the object\n\t\t// is serialized using JSON.stringify\n\t\tcache[ id ] = isNode ? {} : { toJSON: jQuery.noop };\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 ( typeof name === \"string\" ) {\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 thisCache, i,\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\ti = name.length;\n\t\t\twhile ( 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(thisCache) : !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/* jshint eqeqeq: false */\n\t} else if ( support.deleteExpando || cache != cache.window ) {\n\t\t/* jshint eqeqeq: true */\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// The following elements (space-suffixed to avoid Object.prototype collisions)\n\t// throw uncatchable exceptions if you attempt to set expando properties\n\tnoData: {\n\t\t\"applet \": true,\n\t\t\"embed \": true,\n\t\t// ...but Flash objects (which have this classid) *can* handle expandos\n\t\t\"object \": \"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"\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\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// Special expections of .data basically thwart jQuery.access,\n\t\t// so implement the relevant behavior ourselves\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\ti = attrs.length;\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tname = attrs[i].name;\n\n\t\t\t\t\t\tif ( name.indexOf(\"data-\") === 0 ) {\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 arguments.length > 1 ?\n\n\t\t\t// Sets one value\n\t\t\tthis.each(function() {\n\t\t\t\tjQuery.data( this, key, value );\n\t\t\t}) :\n\n\t\t\t// Gets one value\n\t\t\t// Try to fetch any internally stored data first\n\t\t\telem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : undefined;\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\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\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\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 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\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\tlength = 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 < length; 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\tlength ? fn( elems[0], key ) : emptyGet;\n};\nvar rcheckableType = (/^(?:checkbox|radio)$/i);\n\n\n\n(function() {\n\tvar fragment = document.createDocumentFragment(),\n\t\tdiv = document.createElement(\"div\"),\n\t\tinput = document.createElement(\"input\");\n\n\t// Setup\n\tdiv.setAttribute( \"className\", \"t\" );\n\tdiv.innerHTML = \"  <link/><table></table><a href='/a'>a</a>\";\n\n\t// IE strips leading whitespace when .innerHTML is used\n\tsupport.leadingWhitespace = div.firstChild.nodeType === 3;\n\n\t// Make sure that tbody elements aren't automatically inserted\n\t// IE will insert them into empty tables\n\tsupport.tbody = !div.getElementsByTagName( \"tbody\" ).length;\n\n\t// Make sure that link elements get serialized correctly by innerHTML\n\t// This requires a wrapper element in IE\n\tsupport.htmlSerialize = !!div.getElementsByTagName( \"link\" ).length;\n\n\t// Makes sure cloning an html5 element does not cause problems\n\t// Where outerHTML is undefined, this still works\n\tsupport.html5Clone =\n\t\tdocument.createElement( \"nav\" ).cloneNode( true ).outerHTML !== \"<:nav></:nav>\";\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\tinput.type = \"checkbox\";\n\tinput.checked = true;\n\tfragment.appendChild( input );\n\tsupport.appendChecked = input.checked;\n\n\t// Make sure textarea (and checkbox) defaultValue is properly cloned\n\t// Support: IE6-IE11+\n\tdiv.innerHTML = \"<textarea>x</textarea>\";\n\tsupport.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;\n\n\t// #11217 - WebKit loses check when the name is after the checked attribute\n\tfragment.appendChild( div );\n\tdiv.innerHTML = \"<input type='radio' checked='checked' name='t'/>\";\n\n\t// Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3\n\t// old WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = div.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\tsupport.noCloneEvent = true;\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// Execute the test only if not already executed in another module.\n\tif (support.deleteExpando == null) {\n\t\t// Support: IE<9\n\t\tsupport.deleteExpando = true;\n\t\ttry {\n\t\t\tdelete div.test;\n\t\t} catch( e ) {\n\t\t\tsupport.deleteExpando = false;\n\t\t}\n\t}\n\n\t// Null elements to avoid leaks in IE.\n\tfragment = div = input = null;\n})();\n\n\n(function() {\n\tvar i, eventName,\n\t\tdiv = document.createElement( \"div\" );\n\n\t// Support: IE<9 (lack submit/change bubble), Firefox 23+ (lack focusin event)\n\tfor ( i in { submit: true, change: true, focusin: true }) {\n\t\teventName = \"on\" + i;\n\n\t\tif ( !(support[ i + \"Bubbles\" ] = eventName in window) ) {\n\t\t\t// Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP)\n\t\t\tdiv.setAttribute( eventName, \"t\" );\n\t\t\tsupport[ i + \"Bubbles\" ] = div.attributes[ eventName ].expando === false;\n\t\t}\n\t}\n\n\t// Null elements to avoid leaks in IE.\n\tdiv = null;\n})();\n\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\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\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 !== 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\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/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( 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 = 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 = ( 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 && 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// 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 = 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\t/* jshint eqeqeq: false */\n\t\t\tfor ( ; cur != this; cur = cur.parentNode || this ) {\n\t\t\t\t/* jshint eqeqeq: true */\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\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\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 === 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 ( 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\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// 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{\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 = 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 ] === 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 ||\n\t\t\t\tsrc.defaultPrevented === undefined && (\n\t\t\t\t// Support: IE < 9\n\t\t\t\tsrc.returnValue === false ||\n\t\t\t\t// Support: Android < 4.0\n\t\t\t\tsrc.getPreventDefault && src.getPreventDefault() ) ?\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\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 ( !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 ( !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 ( !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 = jQuery._data( 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\tjQuery._data( 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 = jQuery._data( 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\tjQuery._removeData( doc, fix );\n\t\t\t\t} else {\n\t\t\t\t\tjQuery._data( 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 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\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\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\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: 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\nfunction getAll( context, tag ) {\n\tvar elems, elem,\n\t\ti = 0,\n\t\tfound = typeof context.getElementsByTagName !== strundefined ? context.getElementsByTagName( tag || \"*\" ) :\n\t\t\ttypeof context.querySelectorAll !== 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 ( rcheckableType.test( elem.type ) ) {\n\t\telem.defaultChecked = elem.checked;\n\t}\n}\n\n// Support: IE<8\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 = (jQuery.find.attr( elem, \"type\" ) !== null) + \"/\" + 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 ( !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 ( 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\" && 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.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 ( 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 ( (!support.noCloneEvent || !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 ( !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 ( !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 ( !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 = support.deleteExpando,\n\t\t\tspecial = jQuery.event.special;\n\n\t\tfor ( ; (elem = elems[i]) != null; i++ ) {\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 !== 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\tdeletedIds.push( id );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\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().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );\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\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\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 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( support.htmlSerialize || !rnoshimcache.test( value )  ) &&\n\t\t\t\t( 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() {\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 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 ||\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\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!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// 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.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\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\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 elem = 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 ?\n\n\t\t\t// Use of this method is a temporary fix (more like optmization) until something better comes along,\n\t\t\t// since it was removed from specification and supported only in FF\n\t\t\twindow.getDefaultComputedStyle( elem[ 0 ] ).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 ].contentWindow || iframe[ 0 ].contentDocument ).document;\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}\n\n\n(function() {\n\tvar a, shrinkWrapBlocksVal,\n\t\tdiv = document.createElement( \"div\" ),\n\t\tdivReset =\n\t\t\t\"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;\" +\n\t\t\t\"display:block;padding:0;margin:0;border:0\";\n\n\t// Setup\n\tdiv.innerHTML = \"  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>\";\n\ta = div.getElementsByTagName( \"a\" )[ 0 ];\n\n\ta.style.cssText = \"float:left;opacity:.5\";\n\n\t// Make sure that element opacity exists\n\t// (IE uses filter instead)\n\t// Use a regex to work around a WebKit issue. See #5145\n\tsupport.opacity = /^0.5/.test( a.style.opacity );\n\n\t// Verify style float existence\n\t// (IE uses styleFloat instead of cssFloat)\n\tsupport.cssFloat = !!a.style.cssFloat;\n\n\tdiv.style.backgroundClip = \"content-box\";\n\tdiv.cloneNode( true ).style.backgroundClip = \"\";\n\tsupport.clearCloneStyle = div.style.backgroundClip === \"content-box\";\n\n\t// Null elements to avoid leaks in IE.\n\ta = div = null;\n\n\tsupport.shrinkWrapBlocks = function() {\n\t\tvar body, container, div, containerStyles;\n\n\t\tif ( shrinkWrapBlocksVal == null ) {\n\t\t\tbody = document.getElementsByTagName( \"body\" )[ 0 ];\n\t\t\tif ( !body ) {\n\t\t\t\t// Test fired too early or in an unsupported environment, exit.\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tcontainerStyles = \"border:0;width:0;height:0;position:absolute;top:0;left:-9999px\";\n\t\t\tcontainer = document.createElement( \"div\" );\n\t\t\tdiv = document.createElement( \"div\" );\n\n\t\t\tbody.appendChild( container ).appendChild( div );\n\n\t\t\t// Will be changed later if needed.\n\t\t\tshrinkWrapBlocksVal = false;\n\n\t\t\tif ( typeof div.style.zoom !== strundefined ) {\n\t\t\t\t// Support: IE6\n\t\t\t\t// Check if elements with layout shrink-wrap their children\n\t\t\t\tdiv.style.cssText = divReset + \";width:1px;padding:1px;zoom:1\";\n\t\t\t\tdiv.innerHTML = \"<div></div>\";\n\t\t\t\tdiv.firstChild.style.width = \"5px\";\n\t\t\t\tshrinkWrapBlocksVal = div.offsetWidth !== 3;\n\t\t\t}\n\n\t\t\tbody.removeChild( container );\n\n\t\t\t// Null elements to avoid leaks in IE.\n\t\t\tbody = container = div = null;\n\t\t}\n\n\t\treturn shrinkWrapBlocksVal;\n\t};\n\n})();\nvar rmargin = (/^margin/);\n\nvar rnumnonpx = new RegExp( \"^(\" + pnum + \")(?!px)[a-z%]+$\", \"i\" );\n\n\n\nvar getStyles, curCSS,\n\trposition = /^(top|right|bottom|left)$/;\n\nif ( window.getComputedStyle ) {\n\tgetStyles = function( elem ) {\n\t\treturn elem.ownerDocument.defaultView.getComputedStyle( elem, null );\n\t};\n\n\tcurCSS = function( elem, name, computed ) {\n\t\tvar width, minWidth, maxWidth, ret,\n\t\t\tstyle = elem.style;\n\n\t\tcomputed = computed || getStyles( elem );\n\n\t\t// getPropertyValue is only needed for .css('filter') in IE9, see #12537\n\t\tret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined;\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\t// Support: IE\n\t\t// IE returns zIndex value as an integer.\n\t\treturn ret === undefined ?\n\t\t\tret :\n\t\t\tret + \"\";\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, ret,\n\t\t\tstyle = elem.style;\n\n\t\tcomputed = computed || getStyles( elem );\n\t\tret = computed ? computed[ name ] : undefined;\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\t// Support: IE\n\t\t// IE returns zIndex value as an integer.\n\t\treturn ret === undefined ?\n\t\t\tret :\n\t\t\tret + \"\" || \"auto\";\n\t};\n}\n\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\tvar condition = conditionFn();\n\n\t\t\tif ( condition == null ) {\n\t\t\t\t// The test was not ready at this point; screw the hook this time\n\t\t\t\t// but check again when needed next time.\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( condition ) {\n\t\t\t\t// Hook not needed (or it's not possible to use it due to missing dependency),\n\t\t\t\t// remove it.\n\t\t\t\t// Since there are no other hooks for marginRight, remove the whole object.\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\n\t\t\treturn (this.get = hookFn).apply( this, arguments );\n\t\t}\n\t};\n}\n\n\n(function() {\n\tvar a, reliableHiddenOffsetsVal, boxSizingVal, boxSizingReliableVal,\n\t\tpixelPositionVal, reliableMarginRightVal,\n\t\tdiv = document.createElement( \"div\" ),\n\t\tcontainerStyles = \"border:0;width:0;height:0;position:absolute;top:0;left:-9999px\",\n\t\tdivReset =\n\t\t\t\"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;\" +\n\t\t\t\"display:block;padding:0;margin:0;border:0\";\n\n\t// Setup\n\tdiv.innerHTML = \"  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>\";\n\ta = div.getElementsByTagName( \"a\" )[ 0 ];\n\n\ta.style.cssText = \"float:left;opacity:.5\";\n\n\t// Make sure that element opacity exists\n\t// (IE uses filter instead)\n\t// Use a regex to work around a WebKit issue. See #5145\n\tsupport.opacity = /^0.5/.test( a.style.opacity );\n\n\t// Verify style float existence\n\t// (IE uses styleFloat instead of cssFloat)\n\tsupport.cssFloat = !!a.style.cssFloat;\n\n\tdiv.style.backgroundClip = \"content-box\";\n\tdiv.cloneNode( true ).style.backgroundClip = \"\";\n\tsupport.clearCloneStyle = div.style.backgroundClip === \"content-box\";\n\n\t// Null elements to avoid leaks in IE.\n\ta = div = null;\n\n\tjQuery.extend(support, {\n\t\treliableHiddenOffsets: function() {\n\t\t\tif ( reliableHiddenOffsetsVal != null ) {\n\t\t\t\treturn reliableHiddenOffsetsVal;\n\t\t\t}\n\n\t\t\tvar container, tds, isSupported,\n\t\t\t\tdiv = document.createElement( \"div\" ),\n\t\t\t\tbody = document.getElementsByTagName( \"body\" )[ 0 ];\n\n\t\t\tif ( !body ) {\n\t\t\t\t// Return for frameset docs that don't have a body\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Setup\n\t\t\tdiv.setAttribute( \"className\", \"t\" );\n\t\t\tdiv.innerHTML = \"  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>\";\n\n\t\t\tcontainer = document.createElement( \"div\" );\n\t\t\tcontainer.style.cssText = containerStyles;\n\n\t\t\tbody.appendChild( container ).appendChild( div );\n\n\t\t\t// Support: IE8\n\t\t\t// Check if table cells still have offsetWidth/Height when they are set\n\t\t\t// to display:none and there are still other visible table cells in a\n\t\t\t// table row; if so, offsetWidth/Height are not reliable for use when\n\t\t\t// determining if an element has been hidden directly using\n\t\t\t// display:none (it is still safe to use offsets if a parent element is\n\t\t\t// hidden; don safety goggles and see bug #4512 for more information).\n\t\t\tdiv.innerHTML = \"<table><tr><td></td><td>t</td></tr></table>\";\n\t\t\ttds = div.getElementsByTagName( \"td\" );\n\t\t\ttds[ 0 ].style.cssText = \"padding:0;margin:0;border:0;display:none\";\n\t\t\tisSupported = ( tds[ 0 ].offsetHeight === 0 );\n\n\t\t\ttds[ 0 ].style.display = \"\";\n\t\t\ttds[ 1 ].style.display = \"none\";\n\n\t\t\t// Support: IE8\n\t\t\t// Check if empty table cells still have offsetWidth/Height\n\t\t\treliableHiddenOffsetsVal = isSupported && ( tds[ 0 ].offsetHeight === 0 );\n\n\t\t\tbody.removeChild( container );\n\n\t\t\t// Null elements to avoid leaks in IE.\n\t\t\tdiv = body = null;\n\n\t\t\treturn reliableHiddenOffsetsVal;\n\t\t},\n\n\t\tboxSizing: function() {\n\t\t\tif ( boxSizingVal == null ) {\n\t\t\t\tcomputeStyleTests();\n\t\t\t}\n\t\t\treturn boxSizingVal;\n\t\t},\n\n\t\tboxSizingReliable: function() {\n\t\t\tif ( boxSizingReliableVal == null ) {\n\t\t\t\tcomputeStyleTests();\n\t\t\t}\n\t\t\treturn boxSizingReliableVal;\n\t\t},\n\n\t\tpixelPosition: function() {\n\t\t\tif ( pixelPositionVal == null ) {\n\t\t\t\tcomputeStyleTests();\n\t\t\t}\n\t\t\treturn pixelPositionVal;\n\t\t},\n\n\t\treliableMarginRight: function() {\n\t\t\tvar body, container, div, marginDiv;\n\n\t\t\t// Use window.getComputedStyle because jsdom on node.js will break without it.\n\t\t\tif ( reliableMarginRightVal == null && window.getComputedStyle ) {\n\t\t\t\tbody = document.getElementsByTagName( \"body\" )[ 0 ];\n\t\t\t\tif ( !body ) {\n\t\t\t\t\t// Test fired too early or in an unsupported environment, exit.\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tcontainer = document.createElement( \"div\" );\n\t\t\t\tdiv = document.createElement( \"div\" );\n\t\t\t\tcontainer.style.cssText = containerStyles;\n\n\t\t\t\tbody.appendChild( container ).appendChild( div );\n\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// Fails in WebKit before Feb 2011 nightlies\n\t\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\t\tmarginDiv = div.appendChild( document.createElement( \"div\" ) );\n\t\t\t\tmarginDiv.style.cssText = div.style.cssText = divReset;\n\t\t\t\tmarginDiv.style.marginRight = marginDiv.style.width = \"0\";\n\t\t\t\tdiv.style.width = \"1px\";\n\n\t\t\t\treliableMarginRightVal =\n\t\t\t\t\t!parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight );\n\n\t\t\t\tbody.removeChild( container );\n\t\t\t}\n\n\t\t\treturn reliableMarginRightVal;\n\t\t}\n\t});\n\n\tfunction computeStyleTests() {\n\t\tvar container, div,\n\t\t\tbody = document.getElementsByTagName( \"body\" )[ 0 ];\n\n\t\tif ( !body ) {\n\t\t\t// Test fired too early or in an unsupported environment, exit.\n\t\t\treturn;\n\t\t}\n\n\t\tcontainer = document.createElement( \"div\" );\n\t\tdiv = document.createElement( \"div\" );\n\t\tcontainer.style.cssText = containerStyles;\n\n\t\tbody.appendChild( container ).appendChild( div );\n\n\t\tdiv.style.cssText =\n\t\t\t\"-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;\" +\n\t\t\t\t\"position:absolute;display:block;padding:1px;border:1px;width:4px;\" +\n\t\t\t\t\"margin-top:1%;top:1%\";\n\n\t\t// Workaround failing boxSizing test due to offsetWidth returning wrong value\n\t\t// with some non-1 values of body zoom, ticket #13543\n\t\tjQuery.swap( body, body.style.zoom != null ? { zoom: 1 } : {}, function() {\n\t\t\tboxSizingVal = div.offsetWidth === 4;\n\t\t});\n\n\t\t// Will be changed later if needed.\n\t\tboxSizingReliableVal = true;\n\t\tpixelPositionVal = false;\n\t\treliableMarginRightVal = true;\n\n\t\t// Use window.getComputedStyle because jsdom on node.js will break without it.\n\t\tif ( window.getComputedStyle ) {\n\t\t\tpixelPositionVal = ( window.getComputedStyle( div, null ) || {} ).top !== \"1%\";\n\t\t\tboxSizingReliableVal =\n\t\t\t\t( window.getComputedStyle( div, null ) || { width: \"4px\" } ).width === \"4px\";\n\t\t}\n\n\t\tbody.removeChild( container );\n\n\t\t// Null elements to avoid leaks in IE.\n\t\tdiv = body = null;\n\t}\n\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\tralpha = /alpha\\([^)]*\\)/i,\n\tropacity = /opacity\\s*=\\s*([^)]*)/,\n\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\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 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\", 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\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 = 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 && ( 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\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// 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\"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// normalize float css property\n\t\t\"float\": 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 null and NaN values aren't set. See: #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 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 ( !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// Support: IE\n\t\t\t\t// Swallow errors from 'invalid' CSS values (#5509)\n\t\t\t\ttry {\n\t\t\t\t\t// Support: Chrome, Safari\n\t\t\t\t\t// Setting style to blank string required to delete \"style: x !important;\"\n\t\t\t\t\tstyle[ name ] = \"\";\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\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\tsupport.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 ( !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\njQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight,\n\tfunction( elem, computed ) {\n\t\tif ( computed ) {\n\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\t// Work around by temporarily setting element display to inline-block\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// 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// Support: IE <=9\n// Panic based approach 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.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 a string for doubling factor 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// And breaking 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\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\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, dDisplay,\n\t\tanim = this,\n\t\torig = {},\n\t\tstyle = elem.style,\n\t\thidden = elem.nodeType && isHidden( elem ),\n\t\tdataShow = jQuery._data( 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// 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\tdisplay = jQuery.css( elem, \"display\" );\n\t\tdDisplay = defaultDisplay( elem.nodeName );\n\t\tif ( display === \"none\" ) {\n\t\t\tdisplay = dDisplay;\n\t\t}\n\t\tif ( 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 ( !support.inlineBlockNeedsLayout || dDisplay === \"inline\" ) {\n\t\t\t\tstyle.display = \"inline-block\";\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 ( !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\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\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 = jQuery._data( 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\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 ( 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\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 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\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\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\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 || 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.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\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\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 a, input, select, opt,\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\ta = div.getElementsByTagName(\"a\")[ 0 ];\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\";\n\n\t// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)\n\tsupport.getSetAttribute = div.className !== \"t\";\n\n\t// Get the style information from getAttribute\n\t// (IE uses .cssText instead)\n\tsupport.style = /top/.test( a.getAttribute(\"style\") );\n\n\t// Make sure that URLs aren't manipulated\n\t// (IE normalizes it by default)\n\tsupport.hrefNormalized = a.getAttribute(\"href\") === \"/a\";\n\n\t// Check the default checkbox/radio value (\"\" on WebKit; \"on\" elsewhere)\n\tsupport.checkOn = !!input.value;\n\n\t// Make sure that a selected-by-default option has a working selected property.\n\t// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)\n\tsupport.optSelected = opt.selected;\n\n\t// Tests for enctype support on a form (#6743)\n\tsupport.enctype = !!document.createElement(\"form\").enctype;\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: IE8 only\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// Null elements to avoid leaks in IE.\n\ta = input = select = opt = div = null;\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\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\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\tjQuery.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// 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( 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\n\t\t\t\t\tif ( jQuery.inArray( jQuery.valHooks.option.get( option ), values ) >= 0 ) {\n\n\t\t\t\t\t\t// Support: IE6\n\t\t\t\t\t\t// When new option element is added to select box we need to\n\t\t\t\t\t\t// force reflow of newly added node in order to workaround delay\n\t\t\t\t\t\t// of initialization properties\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\toption.selected = optionSet = true;\n\n\t\t\t\t\t\t} catch ( _ ) {\n\n\t\t\t\t\t\t\t// Will be executed only in IE6\n\t\t\t\t\t\t\toption.scrollHeight;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\toption.selected = false;\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\n\t\t\t\treturn options;\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\t// Support: Webkit\n\t\t\t// \"\" is returned instead of \"on\" if a value isn't specified\n\t\t\treturn elem.getAttribute(\"value\") === null ? \"on\" : elem.value;\n\t\t};\n\t}\n});\n\n\n\n\nvar nodeHook, boolHook,\n\tattrHandle = jQuery.expr.attrHandle,\n\truseDefault = /^(?:checked|selected)$/i,\n\tgetSetAttribute = support.getSetAttribute,\n\tgetSetInput = support.input;\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\tif ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {\n\t\t\t\t\t\telem[ propName ] = false;\n\t\t\t\t\t// Support: IE<9\n\t\t\t\t\t// Also clear defaultChecked/defaultSelected (if appropriate)\n\t\t\t\t\t} else {\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}\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 ( !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\n// Hook 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 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// Retrieve booleans specially\njQuery.each( jQuery.expr.match.bool.source.match( /\\w+/g ), function( i, name ) {\n\n\tvar getter = attrHandle[ name ] || jQuery.find.attr;\n\n\tattrHandle[ name ] = getSetInput && getSetAttribute || !ruseDefault.test( name ) ?\n\t\tfunction( elem, name, isXML ) {\n\t\t\tvar ret, handle;\n\t\t\tif ( !isXML ) {\n\t\t\t\t// Avoid an infinite loop by temporarily removing this function from the getter\n\t\t\t\thandle = attrHandle[ name ];\n\t\t\t\tattrHandle[ name ] = ret;\n\t\t\t\tret = getter( elem, name, isXML ) != null ?\n\t\t\t\t\tname.toLowerCase() :\n\t\t\t\t\tnull;\n\t\t\t\tattrHandle[ name ] = handle;\n\t\t\t}\n\t\t\treturn ret;\n\t\t} :\n\t\tfunction( elem, name, isXML ) {\n\t\t\tif ( !isXML ) {\n\t\t\t\treturn elem[ jQuery.camelCase( \"default-\" + name ) ] ?\n\t\t\t\t\tname.toLowerCase() :\n\t\t\t\t\tnull;\n\t\t\t}\n\t\t};\n});\n\n// fix oldIE attroperties\nif ( !getSetInput || !getSetAttribute ) {\n\tjQuery.attrHooks.value = {\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 = {\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\tif ( name === \"value\" || value === elem.getAttribute( name ) ) {\n\t\t\t\treturn value;\n\t\t\t}\n\t\t}\n\t};\n\n\t// Some attributes are constructed with empty-string values when not defined\n\tattrHandle.id = attrHandle.name = attrHandle.coords =\n\t\tfunction( elem, name, isXML ) {\n\t\t\tvar ret;\n\t\t\tif ( !isXML ) {\n\t\t\t\treturn (ret = elem.getAttributeNode( name )) && ret.value !== \"\" ?\n\t\t\t\t\tret.value :\n\t\t\t\t\tnull;\n\t\t\t}\n\t\t};\n\n\t// Fixing value retrieval on a button requires this module\n\tjQuery.valHooks.button = {\n\t\tget: function( elem, name ) {\n\t\t\tvar ret = elem.getAttributeNode( name );\n\t\t\tif ( ret && ret.specified ) {\n\t\t\t\treturn ret.value;\n\t\t\t}\n\t\t},\n\t\tset: nodeHook.set\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\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 ] = {\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\nif ( !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\n\n\nvar rfocusable = /^(?:input|select|textarea|button|object)$/i,\n\trclickable = /^(?:a|area)$/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\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\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\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\t// Use proper attribute retrieval(#12072)\n\t\t\t\tvar tabindex = jQuery.find.attr( elem, \"tabindex\" );\n\n\t\t\t\treturn tabindex ?\n\t\t\t\t\tparseInt( tabindex, 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\t-1;\n\t\t\t}\n\t\t}\n\t}\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 ( !support.hrefNormalized ) {\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\n// Support: Safari, IE9+\n// mis-reports the default selected property of an option\n// Accessing the parent's selectedIndex property fixes it\nif ( !support.optSelected ) {\n\tjQuery.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\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// IE6/7 call enctype encoding\nif ( !support.enctype ) {\n\tjQuery.propFix.enctype = \"encoding\";\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\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( 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\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( 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\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\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\nvar rvalidtokens = /(,)|(\\[|{)|(}|])|\"(?:[^\"\\\\\\r\\n]|\\\\[\"\\\\\\/bfnrt]|\\\\u[\\da-fA-F]{4})*\"\\s*:?|true|false|null|-?(?!0\\d)\\d+(?:\\.\\d+|)(?:[eE][+-]?\\d+|)/g;\n\njQuery.parseJSON = function( data ) {\n\t// Attempt to parse using the native JSON parser first\n\tif ( window.JSON && window.JSON.parse ) {\n\t\t// Support: Android 2.3\n\t\t// Workaround failure to string-cast null input\n\t\treturn window.JSON.parse( data + \"\" );\n\t}\n\n\tvar requireNonComma,\n\t\tdepth = null,\n\t\tstr = jQuery.trim( data + \"\" );\n\n\t// Guard against invalid (and possibly dangerous) input by ensuring that nothing remains\n\t// after removing valid tokens\n\treturn str && !jQuery.trim( str.replace( rvalidtokens, function( token, comma, open, close ) {\n\n\t\t// Force termination if we see a misplaced comma\n\t\tif ( requireNonComma && comma ) {\n\t\t\tdepth = 0;\n\t\t}\n\n\t\t// Perform no more replacements after returning to outermost depth\n\t\tif ( depth === 0 ) {\n\t\t\treturn token;\n\t\t}\n\n\t\t// Commas must not follow \"[\", \"{\", or \",\"\n\t\trequireNonComma = open || comma;\n\n\t\t// Determine new depth\n\t\t// array/object open (\"[\" or \"{\"): depth += true - false (increment)\n\t\t// array/object close (\"]\" or \"}\"): depth += false - true (decrement)\n\t\t// other cases (\",\" or primitive): depth += true - true (numeric cast)\n\t\tdepth += !close - !open;\n\n\t\t// Remove this token\n\t\treturn \"\";\n\t}) ) ?\n\t\t( Function( \"return \" + str ) )() :\n\t\tjQuery.error( \"Invalid JSON: \" + 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\ttry {\n\t\tif ( window.DOMParser ) { // Standard\n\t\t\ttmp = new DOMParser();\n\t\t\txml = tmp.parseFromString( data, \"text/xml\" );\n\t\t} else { // IE\n\t\t\txml = new ActiveXObject( \"Microsoft.XMLDOM\" );\n\t\t\txml.async = \"false\";\n\t\t\txml.loadXML( data );\n\t\t}\n\t} catch( e ) {\n\t\txml = undefined;\n\t}\n\tif ( !xml || !xml.documentElement || xml.getElementsByTagName( \"parsererror\" ).length ) {\n\t\tjQuery.error( \"Invalid XML: \" + data );\n\t}\n\treturn xml;\n};\n\n\nvar\n\t// Document location\n\tajaxLocParts,\n\tajaxLocation,\n\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/* 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( 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.charAt( 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\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\tvar firstDataType, ct, finalDataType, type,\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\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 // 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( 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 += ( 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// 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\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// 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\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\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\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\t\t(!support.reliableHiddenOffsets() &&\n\t\t\t((elem.style && elem.style.display) || jQuery.css( elem, \"display\" )) === \"none\");\n};\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\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\n// Create the request object\n// (This is still attached to ajaxSettings for backward compatibility)\njQuery.ajaxSettings.xhr = window.ActiveXObject !== undefined ?\n\t// Support: IE6+\n\tfunction() {\n\n\t\t// XHR cannot access local files, always use ActiveX for that case\n\t\treturn !this.isLocal &&\n\n\t\t\t// Support: IE7-8\n\t\t\t// oldIE XHR does not support non-RFC2616 methods (#13240)\n\t\t\t// See http://msdn.microsoft.com/en-us/library/ie/ms536648(v=vs.85).aspx\n\t\t\t// and http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9\n\t\t\t// Although this check for six methods instead of eight\n\t\t\t// since IE also does not support \"trace\" and \"connect\"\n\t\t\t/^(get|post|head|put|delete|options)$/i.test( this.type ) &&\n\n\t\t\tcreateStandardXHR() || createActiveXHR();\n\t} :\n\t// For all other browsers, use the standard XMLHttpRequest object\n\tcreateStandardXHR;\n\nvar xhrId = 0,\n\txhrCallbacks = {},\n\txhrSupported = jQuery.ajaxSettings.xhr();\n\n// Support: IE<10\n// Open requests must be manually aborted on unload (#5280)\nif ( window.ActiveXObject ) {\n\tjQuery( window ).on( \"unload\", function() {\n\t\tfor ( var key in xhrCallbacks ) {\n\t\t\txhrCallbacks[ key ]( undefined, true );\n\t\t}\n\t});\n}\n\n// Determine support properties\nsupport.cors = !!xhrSupported && ( \"withCredentials\" in xhrSupported );\nxhrSupported = support.ajax = !!xhrSupported;\n\n// Create transport if the browser can provide an xhr\nif ( xhrSupported ) {\n\n\tjQuery.ajaxTransport(function( options ) {\n\t\t// Cross domain only allowed if supported through XMLHttpRequest\n\t\tif ( !options.crossDomain || support.cors ) {\n\n\t\t\tvar callback;\n\n\t\t\treturn {\n\t\t\t\tsend: function( headers, complete ) {\n\t\t\t\t\tvar i,\n\t\t\t\t\t\txhr = options.xhr(),\n\t\t\t\t\t\tid = ++xhrId;\n\n\t\t\t\t\t// Open the socket\n\t\t\t\t\txhr.open( options.type, options.url, options.async, options.username, options.password );\n\n\t\t\t\t\t// Apply custom fields if provided\n\t\t\t\t\tif ( options.xhrFields ) {\n\t\t\t\t\t\tfor ( i in options.xhrFields ) {\n\t\t\t\t\t\t\txhr[ i ] = options.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 ( options.mimeType && xhr.overrideMimeType ) {\n\t\t\t\t\t\txhr.overrideMimeType( options.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 ( !options.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// Set headers\n\t\t\t\t\tfor ( i in headers ) {\n\t\t\t\t\t\t// Support: IE<9\n\t\t\t\t\t\t// IE's ActiveXObject throws a 'Type Mismatch' exception when setting\n\t\t\t\t\t\t// request header to a null-value.\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// To keep consistent with other XHR implementations, cast the value\n\t\t\t\t\t\t// to string and ignore `undefined`.\n\t\t\t\t\t\tif ( headers[ i ] !== undefined ) {\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}\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( ( options.hasContent && options.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, statusText, responses;\n\n\t\t\t\t\t\t// Was never called and is aborted or complete\n\t\t\t\t\t\tif ( callback && ( isAbort || xhr.readyState === 4 ) ) {\n\t\t\t\t\t\t\t// Clean up\n\t\t\t\t\t\t\tdelete xhrCallbacks[ id ];\n\t\t\t\t\t\t\tcallback = undefined;\n\t\t\t\t\t\t\txhr.onreadystatechange = jQuery.noop;\n\n\t\t\t\t\t\t\t// Abort manually if needed\n\t\t\t\t\t\t\tif ( isAbort ) {\n\t\t\t\t\t\t\t\tif ( xhr.readyState !== 4 ) {\n\t\t\t\t\t\t\t\t\txhr.abort();\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\tresponses = {};\n\t\t\t\t\t\t\t\tstatus = xhr.status;\n\n\t\t\t\t\t\t\t\t// Support: IE<10\n\t\t\t\t\t\t\t\t// Accessing binary-data responseText throws an exception\n\t\t\t\t\t\t\t\t// (#11426)\n\t\t\t\t\t\t\t\tif ( typeof xhr.responseText === \"string\" ) {\n\t\t\t\t\t\t\t\t\tresponses.text = xhr.responseText;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// Firefox throws an exception when accessing\n\t\t\t\t\t\t\t\t// statusText for faulty cross-domain requests\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tstatusText = xhr.statusText;\n\t\t\t\t\t\t\t\t} catch( e ) {\n\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\tstatusText = \"\";\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// Filter status for non standard behaviors\n\n\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// (success with no data won't get notified, that's the best we\n\t\t\t\t\t\t\t\t// can do given current implementations)\n\t\t\t\t\t\t\t\tif ( !status && options.isLocal && !options.crossDomain ) {\n\t\t\t\t\t\t\t\t\tstatus = responses.text ? 200 : 404;\n\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} else if ( status === 1223 ) {\n\t\t\t\t\t\t\t\t\tstatus = 204;\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// Call complete if needed\n\t\t\t\t\t\tif ( responses ) {\n\t\t\t\t\t\t\tcomplete( status, statusText, responses, xhr.getAllResponseHeaders() );\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\tif ( !options.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\t// Add to the list of active xhr callbacks\n\t\t\t\t\t\txhr.onreadystatechange = xhrCallbacks[ id ] = 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}\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\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 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});\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, 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\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\n\nvar docElem = window.document.documentElement;\n\n/**\n * Gets a window from an element\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\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\tjQuery.inArray(\"auto\", [ curCSSTop, curCSSLeft ] ) > -1;\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\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\tbox = { top: 0, left: 0 },\n\t\t\telem = this[ 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// If we don't have gBCR, just use 0,0 rather than error\n\t\t// BlackBerry 5, iOS 3 (original iPhone)\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.scrollTop )  - ( docElem.clientTop  || 0 ),\n\t\t\tleft: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )\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\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 its 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 || 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\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 = /Y/.test( 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 ? (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\n// Add the top/left cssHooks using jQuery.fn.position\n// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084\n// getComputedStyle returns percent when specified for top/left/bottom/right\n// rather than make the css module depend on the offset module, we 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], 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\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.\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\n// AMD (#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"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/bootstrap/paginator/bootstrap-paginator.js",
    "content": "/**\n * bootstrap-paginator.js v0.5\n * --\n * Copyright 2013 Yun Lai <lyonlai1984@gmail.com>\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(function ($) {\n\n    \"use strict\"; // jshint ;_;\n\n\n    /* Paginator PUBLIC CLASS DEFINITION\n     * ================================= */\n\n    /**\n     * Boostrap Paginator Constructor\n     *\n     * @param element element of the paginator\n     * @param options the options to config the paginator\n     *\n     * */\n    var BootstrapPaginator = function (element, options) {\n        this.init(element, options);\n    },\n        old = null;\n\n    BootstrapPaginator.prototype = {\n\n        /**\n         * Initialization function of the paginator, accepting an element and the options as parameters\n         *\n         * @param element element of the paginator\n         * @param options the options to config the paginator\n         *\n         * */\n        init: function (element, options) {\n\n            this.$element = $(element);\n\n            var version = (options && options.bootstrapMajorVersion) ? options.bootstrapMajorVersion : $.fn.bootstrapPaginator.defaults.bootstrapMajorVersion,\n                id = this.$element.attr(\"id\");\n\n            if (version === 2 && !this.$element.is(\"div\")) {\n\n                throw \"in Bootstrap version 2 the pagination must be a div element. Or if you are using Bootstrap pagination 3. Please specify it in bootstrapMajorVersion in the option\";\n            } else if (version > 2 && !this.$element.is(\"ul\")) {\n                throw \"in Bootstrap version 3 the pagination root item must be an ul element.\"\n            }\n\n\n\n            this.currentPage = 1;\n\n            this.lastPage = 1;\n\n            this.setOptions(options);\n\n            this.initialized = true;\n        },\n\n        /**\n         * Update the properties of the paginator element\n         *\n         * @param options options to config the paginator\n         * */\n        setOptions: function (options) {\n\n            this.options = $.extend({}, (this.options || $.fn.bootstrapPaginator.defaults), options);\n\n            this.totalPages = parseInt(this.options.totalPages, 10);  //setup the total pages property.\n            this.numberOfPages = parseInt(this.options.numberOfPages, 10); //setup the numberOfPages to be shown\n\n            //move the set current page after the setting of total pages. otherwise it will cause out of page exception.\n            if (options && typeof (options.currentPage)  !== 'undefined') {\n\n                this.setCurrentPage(options.currentPage);\n            }\n\n            this.listen();\n\n            //render the paginator\n            this.render();\n\n            if (!this.initialized && this.lastPage !== this.currentPage) {\n                this.$element.trigger(\"page-changed\", [this.lastPage, this.currentPage]);\n            }\n\n        },\n\n        /**\n         * Sets up the events listeners. Currently the pageclicked and pagechanged events are linked if available.\n         *\n         * */\n        listen: function () {\n\n            this.$element.off(\"page-clicked\");\n\n            this.$element.off(\"page-changed\");// unload the events for the element\n\n            if (typeof (this.options.onPageClicked) === \"function\") {\n                this.$element.bind(\"page-clicked\", this.options.onPageClicked);\n            }\n\n            if (typeof (this.options.onPageChanged) === \"function\") {\n                this.$element.on(\"page-changed\", this.options.onPageChanged);\n            }\n\n            this.$element.bind(\"page-clicked\", this.onPageClicked);\n        },\n\n\n        /**\n         *\n         *  Destroys the paginator element, it unload the event first, then empty the content inside.\n         *\n         * */\n        destroy: function () {\n\n            this.$element.off(\"page-clicked\");\n\n            this.$element.off(\"page-changed\");\n\n            this.$element.removeData('bootstrapPaginator');\n\n            this.$element.empty();\n\n        },\n\n        /**\n         * Shows the page\n         *\n         * */\n        show: function (page) {\n\n            this.setCurrentPage(page);\n\n            this.render();\n\n            if (this.lastPage !== this.currentPage) {\n                this.$element.trigger(\"page-changed\", [this.lastPage, this.currentPage]);\n            }\n        },\n\n        /**\n         * Shows the next page\n         *\n         * */\n        showNext: function () {\n            var pages = this.getPages();\n\n            if (pages.next) {\n                this.show(pages.next);\n            }\n\n        },\n\n        /**\n         * Shows the previous page\n         *\n         * */\n        showPrevious: function () {\n            var pages = this.getPages();\n\n            if (pages.prev) {\n                this.show(pages.prev);\n            }\n\n        },\n\n        /**\n         * Shows the first page\n         *\n         * */\n        showFirst: function () {\n            var pages = this.getPages();\n\n            if (pages.first) {\n                this.show(pages.first);\n            }\n\n        },\n\n        /**\n         * Shows the last page\n         *\n         * */\n        showLast: function () {\n            var pages = this.getPages();\n\n            if (pages.last) {\n                this.show(pages.last);\n            }\n\n        },\n\n        /**\n         * Internal on page item click handler, when the page item is clicked, change the current page to the corresponding page and\n         * trigger the pageclick event for the listeners.\n         *\n         *\n         * */\n        onPageItemClicked: function (event) {\n\n            var type = event.data.type,\n                page = event.data.page;\n\n            this.$element.trigger(\"page-clicked\", [event, type, page]);\n\n        },\n\n        onPageClicked: function (event, originalEvent, type, page) {\n\n            //show the corresponding page and retrieve the newly built item related to the page clicked before for the event return\n\n            var currentTarget = $(event.currentTarget);\n\n            switch (type) {\n            case \"first\":\n                currentTarget.bootstrapPaginator(\"showFirst\");\n                break;\n            case \"prev\":\n                currentTarget.bootstrapPaginator(\"showPrevious\");\n                break;\n            case \"next\":\n                currentTarget.bootstrapPaginator(\"showNext\");\n                break;\n            case \"last\":\n                currentTarget.bootstrapPaginator(\"showLast\");\n                break;\n            case \"page\":\n                currentTarget.bootstrapPaginator(\"show\", page);\n                break;\n            }\n\n        },\n\n        /**\n         * Renders the paginator according to the internal properties and the settings.\n         *\n         *\n         * */\n        render: function () {\n\n            //fetch the container class and add them to the container\n            var containerClass = this.getValueFromOption(this.options.containerClass, this.$element),\n                size = this.options.size || \"normal\",\n                alignment = this.options.alignment || \"left\",\n                pages = this.getPages(),\n                listContainer = this.options.bootstrapMajorVersion === 2 ? $(\"<ul></ul>\") : this.$element,\n                listContainerClass = this.options.bootstrapMajorVersion === 2 ? this.getValueFromOption(this.options.listContainerClass, listContainer) : null,\n                first = null,\n                prev = null,\n                next = null,\n                last = null,\n                p = null,\n                i = 0;\n\n\n            this.$element.prop(\"class\", \"\");\n\n            this.$element.addClass(\"pagination\");\n\n            switch (size.toLowerCase()) {\n            case \"large\":\n            case \"small\":\n            case \"mini\":\n                this.$element.addClass($.fn.bootstrapPaginator.sizeArray[this.options.bootstrapMajorVersion][size.toLowerCase()]);\n                break;\n            default:\n                break;\n            }\n\n            if (this.options.bootstrapMajorVersion === 2) {\n                switch (alignment.toLowerCase()) {\n                case \"center\":\n                    this.$element.addClass(\"pagination-centered\");\n                    break;\n                case \"right\":\n                    this.$element.addClass(\"pagination-right\");\n                    break;\n                default:\n                    break;\n                }\n            }\n\n\n            this.$element.addClass(containerClass);\n\n            //empty the outter most container then add the listContainer inside.\n            this.$element.empty();\n\n            if (this.options.bootstrapMajorVersion === 2) {\n                this.$element.append(listContainer);\n\n                listContainer.addClass(listContainerClass);\n            }\n\n            //update the page element reference\n            this.pageRef = [];\n\n            if (pages.first) {//if the there is first page element\n                first = this.buildPageItem(\"first\", pages.first);\n\n                if (first) {\n                    listContainer.append(first);\n                }\n\n            }\n\n            if (pages.prev) {//if the there is previous page element\n\n                prev = this.buildPageItem(\"prev\", pages.prev);\n\n                if (prev) {\n                    listContainer.append(prev);\n                }\n\n            }\n\n\n            for (i = 0; i < pages.length; i = i + 1) {//fill the numeric pages.\n\n                p = this.buildPageItem(\"page\", pages[i]);\n\n                if (p) {\n                    listContainer.append(p);\n                }\n            }\n\n            if (pages.next) {//if there is next page\n\n                next = this.buildPageItem(\"next\", pages.next);\n\n                if (next) {\n                    listContainer.append(next);\n                }\n            }\n\n            if (pages.last) {//if there is last page\n\n                last = this.buildPageItem(\"last\", pages.last);\n\n                if (last) {\n                    listContainer.append(last);\n                }\n            }\n        },\n\n        /**\n         *\n         * Creates a page item base on the type and page number given.\n         *\n         * @param page page number\n         * @param type type of the page, whether it is the first, prev, page, next, last\n         *\n         * @return Object the constructed page element\n         * */\n        buildPageItem: function (type, page) {\n\n            var itemContainer = $(\"<li></li>\"),//creates the item container\n                itemContent = $(\"<a></a>\"),//creates the item content\n                text = \"\",\n                title = \"\",\n                itemContainerClass = this.options.itemContainerClass(type, page, this.currentPage),\n                itemContentClass = this.getValueFromOption(this.options.itemContentClass, type, page, this.currentPage),\n                tooltipOpts = null;\n\n\n            switch (type) {\n\n            case \"first\":\n                if (!this.getValueFromOption(this.options.shouldShowPage, type, page, this.currentPage)) { return; }\n                text = this.options.itemTexts(type, page, this.currentPage);\n                title = this.options.tooltipTitles(type, page, this.currentPage);\n                break;\n            case \"last\":\n                if (!this.getValueFromOption(this.options.shouldShowPage, type, page, this.currentPage)) { return; }\n                text = this.options.itemTexts(type, page, this.currentPage);\n                title = this.options.tooltipTitles(type, page, this.currentPage);\n                break;\n            case \"prev\":\n                if (!this.getValueFromOption(this.options.shouldShowPage, type, page, this.currentPage)) { return; }\n                text = this.options.itemTexts(type, page, this.currentPage);\n                title = this.options.tooltipTitles(type, page, this.currentPage);\n                break;\n            case \"next\":\n                if (!this.getValueFromOption(this.options.shouldShowPage, type, page, this.currentPage)) { return; }\n                text = this.options.itemTexts(type, page, this.currentPage);\n                title = this.options.tooltipTitles(type, page, this.currentPage);\n                break;\n            case \"page\":\n                if (!this.getValueFromOption(this.options.shouldShowPage, type, page, this.currentPage)) { return; }\n                text = this.options.itemTexts(type, page, this.currentPage);\n                title = this.options.tooltipTitles(type, page, this.currentPage);\n                break;\n            }\n\n            itemContainer.addClass(itemContainerClass).append(itemContent);\n\n            itemContent.addClass(itemContentClass).html(text).on(\"click\", null, {type: type, page: page}, $.proxy(this.onPageItemClicked, this));\n\n            if (this.options.pageUrl) {\n                itemContent.attr(\"href\", this.getValueFromOption(this.options.pageUrl, type, page, this.currentPage));\n            }\n\n            if (this.options.useBootstrapTooltip) {\n                tooltipOpts = $.extend({}, this.options.bootstrapTooltipOptions, {title: title});\n\n                itemContent.tooltip(tooltipOpts);\n            } else {\n                itemContent.attr(\"title\", title);\n            }\n\n            return itemContainer;\n\n        },\n\n        setCurrentPage: function (page) {\n            if (page > this.totalPages || page < 1) {// if the current page is out of range, throw exception.\n\n                throw \"Page out of range\";\n\n            }\n\n            this.lastPage = this.currentPage;\n\n            this.currentPage = parseInt(page, 10);\n\n        },\n\n        /**\n         * Gets an array that represents the current status of the page object. Numeric pages can be access via array mode. length attributes describes how many numeric pages are there. First, previous, next and last page can be accessed via attributes first, prev, next and last. Current attribute marks the current page within the pages.\n         *\n         * @return object output objects that has first, prev, next, last and also the number of pages in between.\n         * */\n        getPages: function () {\n\n            var totalPages = this.totalPages,// get or calculate the total pages via the total records\n                pageStart = (this.currentPage % this.numberOfPages === 0) ? (parseInt(this.currentPage / this.numberOfPages, 10) - 1) * this.numberOfPages + 1 : parseInt(this.currentPage / this.numberOfPages, 10) * this.numberOfPages + 1,//calculates the start page.\n                output = [],\n                i = 0,\n                counter = 0;\n\n            pageStart = pageStart < 1 ? 1 : pageStart;//check the range of the page start to see if its less than 1.\n\n            for (i = pageStart, counter = 0; counter < this.numberOfPages && i <= totalPages; i = i + 1, counter = counter + 1) {//fill the pages\n                output.push(i);\n            }\n\n            output.first = 1;//add the first when the current page leaves the 1st page.\n\n            if (this.currentPage > 1) {// add the previous when the current page leaves the 1st page\n                output.prev = this.currentPage - 1;\n            } else {\n                output.prev = 1;\n            }\n\n            if (this.currentPage < totalPages) {// add the next page when the current page doesn't reach the last page\n                output.next = this.currentPage + 1;\n            } else {\n                output.next = totalPages;\n            }\n\n            output.last = totalPages;// add the last page when the current page doesn't reach the last page\n\n            output.current = this.currentPage;//mark the current page.\n\n            output.total = totalPages;\n\n            output.numberOfPages = this.options.numberOfPages;\n\n            return output;\n\n        },\n\n        /**\n         * Gets the value from the options, this is made to handle the situation where value is the return value of a function.\n         *\n         * @return mixed value that depends on the type of parameters, if the given parameter is a function, then the evaluated result is returned. Otherwise the parameter itself will get returned.\n         * */\n        getValueFromOption: function (value) {\n\n            var output = null,\n                args = Array.prototype.slice.call(arguments, 1);\n\n            if (typeof value === 'function') {\n                output = value.apply(this, args);\n            } else {\n                output = value;\n            }\n\n            return output;\n\n        }\n\n    };\n\n\n    /* TYPEAHEAD PLUGIN DEFINITION\n     * =========================== */\n\n    old = $.fn.bootstrapPaginator;\n\n    $.fn.bootstrapPaginator = function (option) {\n\n        var args = arguments,\n            result = null;\n\n        $(this).each(function (index, item) {\n            var $this = $(item),\n                data = $this.data('bootstrapPaginator'),\n                options = (typeof option !== 'object') ? null : option;\n\n            if (!data) {\n                data = new BootstrapPaginator(this, options);\n\n                $this = $(data.$element);\n\n                $this.data('bootstrapPaginator', data);\n\n                return;\n            }\n\n            if (typeof option === 'string') {\n\n                if (data[option]) {\n                    result = data[option].apply(data, Array.prototype.slice.call(args, 1));\n                } else {\n                    throw \"Method \" + option + \" does not exist\";\n                }\n\n            } else {\n                result = data.setOptions(option);\n            }\n        });\n\n        return result;\n\n    };\n\n    $.fn.bootstrapPaginator.sizeArray = {\n\n        \"2\": {\n            \"large\": \"pagination-large\",\n            \"small\": \"pagination-small\",\n            \"mini\": \"pagination-mini\"\n        },\n        \"3\": {\n            \"large\": \"pagination-lg\",\n            \"small\": \"pagination-sm\",\n            \"mini\": \"\"\n        }\n\n    };\n\n    $.fn.bootstrapPaginator.defaults = {\n        containerClass: \"\",\n        size: \"normal\",\n        alignment: \"left\",\n        bootstrapMajorVersion: 2,\n        listContainerClass: \"\",\n        itemContainerClass: function (type, page, current) {\n            return (page === current) ? \"active\" : \"\";\n        },\n        itemContentClass: function (type, page, current) {\n            return \"\";\n        },\n        currentPage: 1,\n        numberOfPages: 5,\n        totalPages: 1,\n        pageUrl: function (type, page, current) {\n            return null;\n        },\n        onPageClicked: null,\n        onPageChanged: null,\n        useBootstrapTooltip: false,\n        shouldShowPage: function (type, page, current) {\n\n            var result = true;\n\n            switch (type) {\n            case \"first\":\n                result = (current !== 1);\n                break;\n            case \"prev\":\n                result = (current !== 1);\n                break;\n            case \"next\":\n                result = (current !== this.totalPages);\n                break;\n            case \"last\":\n                result = (current !== this.totalPages);\n                break;\n            case \"page\":\n                result = true;\n                break;\n            }\n\n            return result;\n\n        },\n        itemTexts: function (type, page, current) {\n            switch (type) {\n            case \"first\":\n                return \"&lt;&lt;\";\n            case \"prev\":\n                return \"&lt;\";\n            case \"next\":\n                return \"&gt;\";\n            case \"last\":\n                return \"&gt;&gt;\";\n            case \"page\":\n                return page;\n            }\n        },\n        tooltipTitles: function (type, page, current) {\n\n            switch (type) {\n            case \"first\":\n                return \"Go to first page\";\n            case \"prev\":\n                return \"Go to previous page\";\n            case \"next\":\n                return \"Go to next page\";\n            case \"last\":\n                return \"Go to last page\";\n            case \"page\":\n                return (page === current) ? \"Current page is \" + page : \"Go to page \" + page;\n            }\n        },\n        bootstrapTooltipOptions: {\n            animation: true,\n            html: true,\n            placement: 'top',\n            selector: false,\n            title: \"\",\n            container: false\n        }\n    };\n\n    $.fn.bootstrapPaginator.Constructor = BootstrapPaginator;\n\n\n\n}(window.jQuery));\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/bootstrap/paginator/custom-pagenitor.js",
    "content": "function generatePagenitorOption(pageNo, numberOfPages, totalPages, pageClickedFunc){\n\tvar options = {\n\t\t//small mini normal large\n\t\tsize:\"normal\",\n\t\tbootstrapMajorVersion:3,\n\t\tcurrentPage: pageNo,\n\t\tnumberOfPages: numberOfPages,\n\t\ttotalPages: totalPages,\n\t\titemContainerClass: function (type, page, current) {\n            return (page === current) ? \"active\" : \"pointer-cursor\";\n        },\n\t\tshouldShowPage:function(type, page, current){\n\t\t\treturn true;\n        },\n\t\tonPageClicked: pageClickedFunc\n\t};\n\treturn options;\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/bootstrap/res/respond.matchmedia.addListener.src.js",
    "content": "/*! Respond.js v1.4.2: min/max-width media query polyfill\n * Copyright 2014 Scott Jehl\n * Licensed under MIT\n * http://j.mp/respondjs */\n\n/*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */\n/*! NOTE: If you're already including a window.matchMedia polyfill via Modernizr or otherwise, you don't need this part */\n(function(w) {\n  \"use strict\";\n  w.matchMedia = w.matchMedia || function(doc, undefined) {\n    var bool, docElem = doc.documentElement, refNode = docElem.firstElementChild || docElem.firstChild, fakeBody = doc.createElement(\"body\"), div = doc.createElement(\"div\");\n    div.id = \"mq-test-1\";\n    div.style.cssText = \"position:absolute;top:-100em\";\n    fakeBody.style.background = \"none\";\n    fakeBody.appendChild(div);\n    return function(q) {\n      div.innerHTML = '&shy;<style media=\"' + q + '\"> #mq-test-1 { width: 42px; }</style>';\n      docElem.insertBefore(fakeBody, refNode);\n      bool = div.offsetWidth === 42;\n      docElem.removeChild(fakeBody);\n      return {\n        matches: bool,\n        media: q\n      };\n    };\n  }(w.document);\n})(this);\n\n/*! matchMedia() polyfill addListener/removeListener extension. Author & copyright (c) 2012: Scott Jehl. Dual MIT/BSD license */\n(function(w) {\n  \"use strict\";\n  if (w.matchMedia && w.matchMedia(\"all\").addListener) {\n    return false;\n  }\n  var localMatchMedia = w.matchMedia, hasMediaQueries = localMatchMedia(\"only all\").matches, isListening = false, timeoutID = 0, queries = [], handleChange = function(evt) {\n    w.clearTimeout(timeoutID);\n    timeoutID = w.setTimeout(function() {\n      for (var i = 0, il = queries.length; i < il; i++) {\n        var mql = queries[i].mql, listeners = queries[i].listeners || [], matches = localMatchMedia(mql.media).matches;\n        if (matches !== mql.matches) {\n          mql.matches = matches;\n          for (var j = 0, jl = listeners.length; j < jl; j++) {\n            listeners[j].call(w, mql);\n          }\n        }\n      }\n    }, 30);\n  };\n  w.matchMedia = function(media) {\n    var mql = localMatchMedia(media), listeners = [], index = 0;\n    mql.addListener = function(listener) {\n      if (!hasMediaQueries) {\n        return;\n      }\n      if (!isListening) {\n        isListening = true;\n        w.addEventListener(\"resize\", handleChange, true);\n      }\n      if (index === 0) {\n        index = queries.push({\n          mql: mql,\n          listeners: listeners\n        });\n      }\n      listeners.push(listener);\n    };\n    mql.removeListener = function(listener) {\n      for (var i = 0, il = listeners.length; i < il; i++) {\n        if (listeners[i] === listener) {\n          listeners.splice(i, 1);\n        }\n      }\n    };\n    return mql;\n  };\n})(this);\n\n(function(w) {\n  \"use strict\";\n  var respond = {};\n  w.respond = respond;\n  respond.update = function() {};\n  var requestQueue = [], xmlHttp = function() {\n    var xmlhttpmethod = false;\n    try {\n      xmlhttpmethod = new w.XMLHttpRequest();\n    } catch (e) {\n      xmlhttpmethod = new w.ActiveXObject(\"Microsoft.XMLHTTP\");\n    }\n    return function() {\n      return xmlhttpmethod;\n    };\n  }(), ajax = function(url, callback) {\n    var req = xmlHttp();\n    if (!req) {\n      return;\n    }\n    req.open(\"GET\", url, true);\n    req.onreadystatechange = function() {\n      if (req.readyState !== 4 || req.status !== 200 && req.status !== 304) {\n        return;\n      }\n      callback(req.responseText);\n    };\n    if (req.readyState === 4) {\n      return;\n    }\n    req.send(null);\n  }, isUnsupportedMediaQuery = function(query) {\n    return query.replace(respond.regex.minmaxwh, \"\").match(respond.regex.other);\n  };\n  respond.ajax = ajax;\n  respond.queue = requestQueue;\n  respond.unsupportedmq = isUnsupportedMediaQuery;\n  respond.regex = {\n    media: /@media[^\\{]+\\{([^\\{\\}]*\\{[^\\}\\{]*\\})+/gi,\n    keyframes: /@(?:\\-(?:o|moz|webkit)\\-)?keyframes[^\\{]+\\{(?:[^\\{\\}]*\\{[^\\}\\{]*\\})+[^\\}]*\\}/gi,\n    comments: /\\/\\*[^*]*\\*+([^/][^*]*\\*+)*\\//gi,\n    urls: /(url\\()['\"]?([^\\/\\)'\"][^:\\)'\"]+)['\"]?(\\))/g,\n    findStyles: /@media *([^\\{]+)\\{([\\S\\s]+?)$/,\n    only: /(only\\s+)?([a-zA-Z]+)\\s?/,\n    minw: /\\(\\s*min\\-width\\s*:\\s*(\\s*[0-9\\.]+)(px|em)\\s*\\)/,\n    maxw: /\\(\\s*max\\-width\\s*:\\s*(\\s*[0-9\\.]+)(px|em)\\s*\\)/,\n    minmaxwh: /\\(\\s*m(in|ax)\\-(height|width)\\s*:\\s*(\\s*[0-9\\.]+)(px|em)\\s*\\)/gi,\n    other: /\\([^\\)]*\\)/g\n  };\n  respond.mediaQueriesSupported = w.matchMedia && w.matchMedia(\"only all\") !== null && w.matchMedia(\"only all\").matches;\n  if (respond.mediaQueriesSupported) {\n    return;\n  }\n  var doc = w.document, docElem = doc.documentElement, mediastyles = [], rules = [], appendedEls = [], parsedSheets = {}, resizeThrottle = 30, head = doc.getElementsByTagName(\"head\")[0] || docElem, base = doc.getElementsByTagName(\"base\")[0], links = head.getElementsByTagName(\"link\"), lastCall, resizeDefer, eminpx, getEmValue = function() {\n    var ret, div = doc.createElement(\"div\"), body = doc.body, originalHTMLFontSize = docElem.style.fontSize, originalBodyFontSize = body && body.style.fontSize, fakeUsed = false;\n    div.style.cssText = \"position:absolute;font-size:1em;width:1em\";\n    if (!body) {\n      body = fakeUsed = doc.createElement(\"body\");\n      body.style.background = \"none\";\n    }\n    docElem.style.fontSize = \"100%\";\n    body.style.fontSize = \"100%\";\n    body.appendChild(div);\n    if (fakeUsed) {\n      docElem.insertBefore(body, docElem.firstChild);\n    }\n    ret = div.offsetWidth;\n    if (fakeUsed) {\n      docElem.removeChild(body);\n    } else {\n      body.removeChild(div);\n    }\n    docElem.style.fontSize = originalHTMLFontSize;\n    if (originalBodyFontSize) {\n      body.style.fontSize = originalBodyFontSize;\n    }\n    ret = eminpx = parseFloat(ret);\n    return ret;\n  }, applyMedia = function(fromResize) {\n    var name = \"clientWidth\", docElemProp = docElem[name], currWidth = doc.compatMode === \"CSS1Compat\" && docElemProp || doc.body[name] || docElemProp, styleBlocks = {}, lastLink = links[links.length - 1], now = new Date().getTime();\n    if (fromResize && lastCall && now - lastCall < resizeThrottle) {\n      w.clearTimeout(resizeDefer);\n      resizeDefer = w.setTimeout(applyMedia, resizeThrottle);\n      return;\n    } else {\n      lastCall = now;\n    }\n    for (var i in mediastyles) {\n      if (mediastyles.hasOwnProperty(i)) {\n        var thisstyle = mediastyles[i], min = thisstyle.minw, max = thisstyle.maxw, minnull = min === null, maxnull = max === null, em = \"em\";\n        if (!!min) {\n          min = parseFloat(min) * (min.indexOf(em) > -1 ? eminpx || getEmValue() : 1);\n        }\n        if (!!max) {\n          max = parseFloat(max) * (max.indexOf(em) > -1 ? eminpx || getEmValue() : 1);\n        }\n        if (!thisstyle.hasquery || (!minnull || !maxnull) && (minnull || currWidth >= min) && (maxnull || currWidth <= max)) {\n          if (!styleBlocks[thisstyle.media]) {\n            styleBlocks[thisstyle.media] = [];\n          }\n          styleBlocks[thisstyle.media].push(rules[thisstyle.rules]);\n        }\n      }\n    }\n    for (var j in appendedEls) {\n      if (appendedEls.hasOwnProperty(j)) {\n        if (appendedEls[j] && appendedEls[j].parentNode === head) {\n          head.removeChild(appendedEls[j]);\n        }\n      }\n    }\n    appendedEls.length = 0;\n    for (var k in styleBlocks) {\n      if (styleBlocks.hasOwnProperty(k)) {\n        var ss = doc.createElement(\"style\"), css = styleBlocks[k].join(\"\\n\");\n        ss.type = \"text/css\";\n        ss.media = k;\n        head.insertBefore(ss, lastLink.nextSibling);\n        if (ss.styleSheet) {\n          ss.styleSheet.cssText = css;\n        } else {\n          ss.appendChild(doc.createTextNode(css));\n        }\n        appendedEls.push(ss);\n      }\n    }\n  }, translate = function(styles, href, media) {\n    var qs = styles.replace(respond.regex.comments, \"\").replace(respond.regex.keyframes, \"\").match(respond.regex.media), ql = qs && qs.length || 0;\n    href = href.substring(0, href.lastIndexOf(\"/\"));\n    var repUrls = function(css) {\n      return css.replace(respond.regex.urls, \"$1\" + href + \"$2$3\");\n    }, useMedia = !ql && media;\n    if (href.length) {\n      href += \"/\";\n    }\n    if (useMedia) {\n      ql = 1;\n    }\n    for (var i = 0; i < ql; i++) {\n      var fullq, thisq, eachq, eql;\n      if (useMedia) {\n        fullq = media;\n        rules.push(repUrls(styles));\n      } else {\n        fullq = qs[i].match(respond.regex.findStyles) && RegExp.$1;\n        rules.push(RegExp.$2 && repUrls(RegExp.$2));\n      }\n      eachq = fullq.split(\",\");\n      eql = eachq.length;\n      for (var j = 0; j < eql; j++) {\n        thisq = eachq[j];\n        if (isUnsupportedMediaQuery(thisq)) {\n          continue;\n        }\n        mediastyles.push({\n          media: thisq.split(\"(\")[0].match(respond.regex.only) && RegExp.$2 || \"all\",\n          rules: rules.length - 1,\n          hasquery: thisq.indexOf(\"(\") > -1,\n          minw: thisq.match(respond.regex.minw) && parseFloat(RegExp.$1) + (RegExp.$2 || \"\"),\n          maxw: thisq.match(respond.regex.maxw) && parseFloat(RegExp.$1) + (RegExp.$2 || \"\")\n        });\n      }\n    }\n    applyMedia();\n  }, makeRequests = function() {\n    if (requestQueue.length) {\n      var thisRequest = requestQueue.shift();\n      ajax(thisRequest.href, function(styles) {\n        translate(styles, thisRequest.href, thisRequest.media);\n        parsedSheets[thisRequest.href] = true;\n        w.setTimeout(function() {\n          makeRequests();\n        }, 0);\n      });\n    }\n  }, ripCSS = function() {\n    for (var i = 0; i < links.length; i++) {\n      var sheet = links[i], href = sheet.href, media = sheet.media, isCSS = sheet.rel && sheet.rel.toLowerCase() === \"stylesheet\";\n      if (!!href && isCSS && !parsedSheets[href]) {\n        if (sheet.styleSheet && sheet.styleSheet.rawCssText) {\n          translate(sheet.styleSheet.rawCssText, href, media);\n          parsedSheets[href] = true;\n        } else {\n          if (!/^([a-zA-Z:]*\\/\\/)/.test(href) && !base || href.replace(RegExp.$1, \"\").split(\"/\")[0] === w.location.host) {\n            if (href.substring(0, 2) === \"//\") {\n              href = w.location.protocol + href;\n            }\n            requestQueue.push({\n              href: href,\n              media: media\n            });\n          }\n        }\n      }\n    }\n    makeRequests();\n  };\n  ripCSS();\n  respond.update = ripCSS;\n  respond.getEmValue = getEmValue;\n  function callMedia() {\n    applyMedia(true);\n  }\n  if (w.addEventListener) {\n    w.addEventListener(\"resize\", callMedia, false);\n  } else if (w.attachEvent) {\n    w.attachEvent(\"onresize\", callMedia);\n  }\n})(this);"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/bootstrap/res/respond.src.js",
    "content": "/*! Respond.js v1.4.2: min/max-width media query polyfill\n * Copyright 2014 Scott Jehl\n * Licensed under MIT\n * http://j.mp/respondjs */\n\n/*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */\n/*! NOTE: If you're already including a window.matchMedia polyfill via Modernizr or otherwise, you don't need this part */\n(function(w) {\n  \"use strict\";\n  w.matchMedia = w.matchMedia || function(doc, undefined) {\n    var bool, docElem = doc.documentElement, refNode = docElem.firstElementChild || docElem.firstChild, fakeBody = doc.createElement(\"body\"), div = doc.createElement(\"div\");\n    div.id = \"mq-test-1\";\n    div.style.cssText = \"position:absolute;top:-100em\";\n    fakeBody.style.background = \"none\";\n    fakeBody.appendChild(div);\n    return function(q) {\n      div.innerHTML = '&shy;<style media=\"' + q + '\"> #mq-test-1 { width: 42px; }</style>';\n      docElem.insertBefore(fakeBody, refNode);\n      bool = div.offsetWidth === 42;\n      docElem.removeChild(fakeBody);\n      return {\n        matches: bool,\n        media: q\n      };\n    };\n  }(w.document);\n})(this);\n\n(function(w) {\n  \"use strict\";\n  var respond = {};\n  w.respond = respond;\n  respond.update = function() {};\n  var requestQueue = [], xmlHttp = function() {\n    var xmlhttpmethod = false;\n    try {\n      xmlhttpmethod = new w.XMLHttpRequest();\n    } catch (e) {\n      xmlhttpmethod = new w.ActiveXObject(\"Microsoft.XMLHTTP\");\n    }\n    return function() {\n      return xmlhttpmethod;\n    };\n  }(), ajax = function(url, callback) {\n    var req = xmlHttp();\n    if (!req) {\n      return;\n    }\n    req.open(\"GET\", url, true);\n    req.onreadystatechange = function() {\n      if (req.readyState !== 4 || req.status !== 200 && req.status !== 304) {\n        return;\n      }\n      callback(req.responseText);\n    };\n    if (req.readyState === 4) {\n      return;\n    }\n    req.send(null);\n  }, isUnsupportedMediaQuery = function(query) {\n    return query.replace(respond.regex.minmaxwh, \"\").match(respond.regex.other);\n  };\n  respond.ajax = ajax;\n  respond.queue = requestQueue;\n  respond.unsupportedmq = isUnsupportedMediaQuery;\n  respond.regex = {\n    media: /@media[^\\{]+\\{([^\\{\\}]*\\{[^\\}\\{]*\\})+/gi,\n    keyframes: /@(?:\\-(?:o|moz|webkit)\\-)?keyframes[^\\{]+\\{(?:[^\\{\\}]*\\{[^\\}\\{]*\\})+[^\\}]*\\}/gi,\n    comments: /\\/\\*[^*]*\\*+([^/][^*]*\\*+)*\\//gi,\n    urls: /(url\\()['\"]?([^\\/\\)'\"][^:\\)'\"]+)['\"]?(\\))/g,\n    findStyles: /@media *([^\\{]+)\\{([\\S\\s]+?)$/,\n    only: /(only\\s+)?([a-zA-Z]+)\\s?/,\n    minw: /\\(\\s*min\\-width\\s*:\\s*(\\s*[0-9\\.]+)(px|em)\\s*\\)/,\n    maxw: /\\(\\s*max\\-width\\s*:\\s*(\\s*[0-9\\.]+)(px|em)\\s*\\)/,\n    minmaxwh: /\\(\\s*m(in|ax)\\-(height|width)\\s*:\\s*(\\s*[0-9\\.]+)(px|em)\\s*\\)/gi,\n    other: /\\([^\\)]*\\)/g\n  };\n  respond.mediaQueriesSupported = w.matchMedia && w.matchMedia(\"only all\") !== null && w.matchMedia(\"only all\").matches;\n  if (respond.mediaQueriesSupported) {\n    return;\n  }\n  var doc = w.document, docElem = doc.documentElement, mediastyles = [], rules = [], appendedEls = [], parsedSheets = {}, resizeThrottle = 30, head = doc.getElementsByTagName(\"head\")[0] || docElem, base = doc.getElementsByTagName(\"base\")[0], links = head.getElementsByTagName(\"link\"), lastCall, resizeDefer, eminpx, getEmValue = function() {\n    var ret, div = doc.createElement(\"div\"), body = doc.body, originalHTMLFontSize = docElem.style.fontSize, originalBodyFontSize = body && body.style.fontSize, fakeUsed = false;\n    div.style.cssText = \"position:absolute;font-size:1em;width:1em\";\n    if (!body) {\n      body = fakeUsed = doc.createElement(\"body\");\n      body.style.background = \"none\";\n    }\n    docElem.style.fontSize = \"100%\";\n    body.style.fontSize = \"100%\";\n    body.appendChild(div);\n    if (fakeUsed) {\n      docElem.insertBefore(body, docElem.firstChild);\n    }\n    ret = div.offsetWidth;\n    if (fakeUsed) {\n      docElem.removeChild(body);\n    } else {\n      body.removeChild(div);\n    }\n    docElem.style.fontSize = originalHTMLFontSize;\n    if (originalBodyFontSize) {\n      body.style.fontSize = originalBodyFontSize;\n    }\n    ret = eminpx = parseFloat(ret);\n    return ret;\n  }, applyMedia = function(fromResize) {\n    var name = \"clientWidth\", docElemProp = docElem[name], currWidth = doc.compatMode === \"CSS1Compat\" && docElemProp || doc.body[name] || docElemProp, styleBlocks = {}, lastLink = links[links.length - 1], now = new Date().getTime();\n    if (fromResize && lastCall && now - lastCall < resizeThrottle) {\n      w.clearTimeout(resizeDefer);\n      resizeDefer = w.setTimeout(applyMedia, resizeThrottle);\n      return;\n    } else {\n      lastCall = now;\n    }\n    for (var i in mediastyles) {\n      if (mediastyles.hasOwnProperty(i)) {\n        var thisstyle = mediastyles[i], min = thisstyle.minw, max = thisstyle.maxw, minnull = min === null, maxnull = max === null, em = \"em\";\n        if (!!min) {\n          min = parseFloat(min) * (min.indexOf(em) > -1 ? eminpx || getEmValue() : 1);\n        }\n        if (!!max) {\n          max = parseFloat(max) * (max.indexOf(em) > -1 ? eminpx || getEmValue() : 1);\n        }\n        if (!thisstyle.hasquery || (!minnull || !maxnull) && (minnull || currWidth >= min) && (maxnull || currWidth <= max)) {\n          if (!styleBlocks[thisstyle.media]) {\n            styleBlocks[thisstyle.media] = [];\n          }\n          styleBlocks[thisstyle.media].push(rules[thisstyle.rules]);\n        }\n      }\n    }\n    for (var j in appendedEls) {\n      if (appendedEls.hasOwnProperty(j)) {\n        if (appendedEls[j] && appendedEls[j].parentNode === head) {\n          head.removeChild(appendedEls[j]);\n        }\n      }\n    }\n    appendedEls.length = 0;\n    for (var k in styleBlocks) {\n      if (styleBlocks.hasOwnProperty(k)) {\n        var ss = doc.createElement(\"style\"), css = styleBlocks[k].join(\"\\n\");\n        ss.type = \"text/css\";\n        ss.media = k;\n        head.insertBefore(ss, lastLink.nextSibling);\n        if (ss.styleSheet) {\n          ss.styleSheet.cssText = css;\n        } else {\n          ss.appendChild(doc.createTextNode(css));\n        }\n        appendedEls.push(ss);\n      }\n    }\n  }, translate = function(styles, href, media) {\n    var qs = styles.replace(respond.regex.comments, \"\").replace(respond.regex.keyframes, \"\").match(respond.regex.media), ql = qs && qs.length || 0;\n    href = href.substring(0, href.lastIndexOf(\"/\"));\n    var repUrls = function(css) {\n      return css.replace(respond.regex.urls, \"$1\" + href + \"$2$3\");\n    }, useMedia = !ql && media;\n    if (href.length) {\n      href += \"/\";\n    }\n    if (useMedia) {\n      ql = 1;\n    }\n    for (var i = 0; i < ql; i++) {\n      var fullq, thisq, eachq, eql;\n      if (useMedia) {\n        fullq = media;\n        rules.push(repUrls(styles));\n      } else {\n        fullq = qs[i].match(respond.regex.findStyles) && RegExp.$1;\n        rules.push(RegExp.$2 && repUrls(RegExp.$2));\n      }\n      eachq = fullq.split(\",\");\n      eql = eachq.length;\n      for (var j = 0; j < eql; j++) {\n        thisq = eachq[j];\n        if (isUnsupportedMediaQuery(thisq)) {\n          continue;\n        }\n        mediastyles.push({\n          media: thisq.split(\"(\")[0].match(respond.regex.only) && RegExp.$2 || \"all\",\n          rules: rules.length - 1,\n          hasquery: thisq.indexOf(\"(\") > -1,\n          minw: thisq.match(respond.regex.minw) && parseFloat(RegExp.$1) + (RegExp.$2 || \"\"),\n          maxw: thisq.match(respond.regex.maxw) && parseFloat(RegExp.$1) + (RegExp.$2 || \"\")\n        });\n      }\n    }\n    applyMedia();\n  }, makeRequests = function() {\n    if (requestQueue.length) {\n      var thisRequest = requestQueue.shift();\n      ajax(thisRequest.href, function(styles) {\n        translate(styles, thisRequest.href, thisRequest.media);\n        parsedSheets[thisRequest.href] = true;\n        w.setTimeout(function() {\n          makeRequests();\n        }, 0);\n      });\n    }\n  }, ripCSS = function() {\n    for (var i = 0; i < links.length; i++) {\n      var sheet = links[i], href = sheet.href, media = sheet.media, isCSS = sheet.rel && sheet.rel.toLowerCase() === \"stylesheet\";\n      if (!!href && isCSS && !parsedSheets[href]) {\n        if (sheet.styleSheet && sheet.styleSheet.rawCssText) {\n          translate(sheet.styleSheet.rawCssText, href, media);\n          parsedSheets[href] = true;\n        } else {\n          if (!/^([a-zA-Z:]*\\/\\/)/.test(href) && !base || href.replace(RegExp.$1, \"\").split(\"/\")[0] === w.location.host) {\n            if (href.substring(0, 2) === \"//\") {\n              href = w.location.protocol + href;\n            }\n            requestQueue.push({\n              href: href,\n              media: media\n            });\n          }\n        }\n      }\n    }\n    makeRequests();\n  };\n  ripCSS();\n  respond.update = ripCSS;\n  respond.getEmValue = getEmValue;\n  function callMedia() {\n    applyMedia(true);\n  }\n  if (w.addEventListener) {\n    w.addEventListener(\"resize\", callMedia, false);\n  } else if (w.attachEvent) {\n    w.attachEvent(\"onresize\", callMedia);\n  }\n})(this);"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/css/login.css",
    "content": "body{background:#fff;color:#999;font:12px/1.5 hiragino sans gb,microsoft yahei,simsun;}\nbody,form,ul,ol,li,p,dl,dt,dd,h1,h2,h3,h4,h5,h6{margin:0;padding:0;}\nh1,h2,h3,h4,h5,h6,input,textarea{font-size:12px;font-weight:normal;}\nli{list-style:none;}\nimg{border:0;vertical-align:top;}\nem{font-style:normal;}\ntextarea{resize:none;}\na{outline:none; text-decoration:none;}\ninput{outline: none}\nhtml{height: 100%}\nbody{ /* background: url(images/bg.png) no-repeat; background-size: 100% 100%*/}\n.container{width: 330px;  margin: 0 auto;}\n.img{position:fixed;top:0;left:0;bottom:0;right:0;z-index:-1; height: 100%;}\n.img img{width: 100%; height: 100%; outline: 0}\n.logo .logo-pic{ width: 330px; height: 100px; margin-top: 100px;}\n.info{ margin-top: 50px; }\n.info .input{margin-top: 20px;}\n.info .input input{ border: 0; background-color: transparent; border-bottom: 1px solid #a3a8ae;\n    height: 35px; line-height: 35px; width: 280px; color: #616365;\n    -webkit-appearance: none}\n\ninput:-webkit-autofill { \n\n-webkit-box-shadow: 0 0 0px 1000px #D7ECF1 inset; \nborder: 0; \nbackground-color: transparent;\n}\n.info .info-user{float:left; cursor: default; height: 37px; *height:38px; line-height: 35px; display: block; width:45px; border-bottom: 1px solid #a3a8ae;}\n.info .login{background-color: #d25156; margin-top: 40px; }\n.info .login input{color: #f8e6e6; padding-left: 43px; font-size: 14px;}\n.info .register{margin-bottom: 80px; color:#616365;text-align: center; font-size: 14px; line-height: 20px; margin-top: 14px; display: block;}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/css/mem-cloud.css",
    "content": "body {\n    padding-top: 70px;\n}\n\ntable, td{\n    font:100% Arial, Helvetica, sans-serif;\n}\ntable{width:100%;border-collapse:collapse;margin:1em 0;}\nth, td{text-align:left;padding:.5em;border:1px solid #fff;}\nth{background:#328aa4 url(tr_back.gif) repeat-x;color:#fff;}\ntd{background:#e5f1f4;}\n/* tablecloth styles */\ntr.even td{background:#e5f1f4;}\ntr.odd td{background:#f8fbfc;}\n\n\nth.over, tr.even th.over, tr.odd th.over{background:#4a98af;}\nth.down, tr.even th.down, tr.odd th.down{background:#bce774;}\nth.selected, tr.even th.selected, tr.odd th.selected{}\n\n\ntd.over, tr.even td.over, tr.odd td.over{background:#ecfbd4;}\ntd.down, tr.even td.down, tr.odd td.down{background:#bce774;color:#fff;}\ntd.selected, tr.even td.selected, tr.odd td.selected{background:#bce774;color:#555;}\n\n\n/* use this if you want to apply different styling to empty table cells*/\ntd.empty, tr.odd td.empty, tr.even td.empty{background:#fff;}\n\n\n\n\n.margin-custom-bottom0{\n    margin-bottom:0px;\n    padding: 0px 0px;\n}\n.margin-custom-top10{\n    margin-top: 10px;\n}\n\n\ndiv.console { font-size: 14px; word-wrap: break-word;}\ndiv.console div.jquery-console-inner\n{ width:100%; height:400px; background:#333; padding:0.5em;\n    overflow:auto }\ndiv.console div.jquery-console-prompt-box\n{ color:#fff; font-family:monospace; }\ndiv.console div.jquery-console-focus span.jquery-console-cursor\n{ background:#fefefe; color:#333; font-weight:bold }\ndiv.console div.jquery-console-message-error\n{ color:#ef0505; font-family:sans-serif; font-weight:bold;\n    padding:0.1em; }\ndiv.console div.jquery-console-message-value\n{ color:#1ad027; font-family:monospace;\n    padding:0.1em; }\ndiv.console div.jquery-console-message-type\n{ color:#52666f; font-family:monospace;\n    padding:0.1em; }\ndiv.console span.jquery-console-prompt-label { font-weight:bold }"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/error/noPower.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\"\n\tpageEncoding=\"UTF-8\"%>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>Insert title here</title>\n</head>\n<body>\n\t您没有应用<%=request.getParameter(\"appId\")%>的使用权限\n</body>\n</html>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/highchart3/js/adapters/mootools-adapter.js",
    "content": "/*\n Highcharts JS v3.0.3 (2013-07-31)\n MooTools adapter\n\n (c) 2010-2013 Torstein Hønsi\n\n License: www.highcharts.com/license\n*/\n(function(){var e=window,h=document,f=e.MooTools.version.substring(0,3),i=f===\"1.2\"||f===\"1.1\",j=i||f===\"1.3\",g=e.$extend||function(){return Object.append.apply(Object,arguments)};e.HighchartsAdapter={init:function(a){var b=Fx.prototype,c=b.start,d=Fx.Morph.prototype,e=d.compute;b.start=function(b,d){var e=this.element;if(b.d)this.paths=a.init(e,e.d,this.toD);c.apply(this,arguments);return this};d.compute=function(b,c,d){var f=this.paths;if(f)this.element.attr(\"d\",a.step(f[0],f[1],d,this.toD));else return e.apply(this,\narguments)}},adapterRun:function(a,b){if(b===\"width\"||b===\"height\")return parseInt($(a).getStyle(b),10)},getScript:function(a,b){var c=h.getElementsByTagName(\"head\")[0],d=h.createElement(\"script\");d.type=\"text/javascript\";d.src=a;d.onload=b;c.appendChild(d)},animate:function(a,b,c){var d=a.attr,f=c&&c.complete;if(d&&!a.setStyle)a.getStyle=a.attr,a.setStyle=function(){var a=arguments;this.attr.call(this,a[0],a[1][0])},a.$family=function(){return!0};e.HighchartsAdapter.stop(a);c=new Fx.Morph(d?a:$(a),\ng({transition:Fx.Transitions.Quad.easeInOut},c));if(d)c.element=a;if(b.d)c.toD=b.d;f&&c.addEvent(\"complete\",f);c.start(b);a.fx=c},each:function(a,b){return i?$each(a,b):Array.each(a,b)},map:function(a,b){return a.map(b)},grep:function(a,b){return a.filter(b)},inArray:function(a,b,c){return b?b.indexOf(a,c):-1},offset:function(a){a=a.getPosition();return{left:a.x,top:a.y}},extendWithEvents:function(a){a.addEvent||(a.nodeName?$(a):g(a,new Events))},addEvent:function(a,b,c){typeof b===\"string\"&&(b===\n\"unload\"&&(b=\"beforeunload\"),e.HighchartsAdapter.extendWithEvents(a),a.addEvent(b,c))},removeEvent:function(a,b,c){typeof a!==\"string\"&&a.addEvent&&(b?(b===\"unload\"&&(b=\"beforeunload\"),c?a.removeEvent(b,c):a.removeEvents&&a.removeEvents(b)):a.removeEvents())},fireEvent:function(a,b,c,d){b={type:b,target:a};b=j?new Event(b):new DOMEvent(b);b=g(b,c);if(!b.target&&b.event)b.target=b.event.target;b.preventDefault=function(){d=null};a.fireEvent&&a.fireEvent(b.type,b);d&&d(b)},washMouseEvent:function(a){if(a.page)a.pageX=\na.page.x,a.pageY=a.page.y;return a},stop:function(a){a.fx&&a.fx.cancel()}}})();\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/highchart3/js/adapters/mootools-adapter.src.js",
    "content": "/**\n * @license Highcharts JS v3.0.3 (2013-07-31)\n * MooTools adapter\n *\n * (c) 2010-2013 Torstein Hønsi\n *\n * License: www.highcharts.com/license\n */\n\n// JSLint options:\n/*global Fx, $, $extend, $each, $merge, Events, Event, DOMEvent */\n\n(function () {\n\nvar win = window,\n\tdoc = document,\n\tmooVersion = win.MooTools.version.substring(0, 3), // Get the first three characters of the version number\n\tlegacy = mooVersion === '1.2' || mooVersion === '1.1', // 1.1 && 1.2 considered legacy, 1.3 is not.\n\tlegacyEvent = legacy || mooVersion === '1.3', // In versions 1.1 - 1.3 the event class is named Event, in newer versions it is named DOMEvent.\n\t$extend = win.$extend || function () {\n\t\treturn Object.append.apply(Object, arguments);\n\t};\n\nwin.HighchartsAdapter = {\n\t/**\n\t * Initialize the adapter. This is run once as Highcharts is first run.\n\t * @param {Object} pathAnim The helper object to do animations across adapters.\n\t */\n\tinit: function (pathAnim) {\n\t\tvar fxProto = Fx.prototype,\n\t\t\tfxStart = fxProto.start,\n\t\t\tmorphProto = Fx.Morph.prototype,\n\t\t\tmorphCompute = morphProto.compute;\n\n\t\t// override Fx.start to allow animation of SVG element wrappers\n\t\t/*jslint unparam: true*//* allow unused parameters in fx functions */\n\t\tfxProto.start = function (from, to) {\n\t\t\tvar fx = this,\n\t\t\t\telem = fx.element;\n\n\t\t\t// special for animating paths\n\t\t\tif (from.d) {\n\t\t\t\t//this.fromD = this.element.d.split(' ');\n\t\t\t\tfx.paths = pathAnim.init(\n\t\t\t\t\telem,\n\t\t\t\t\telem.d,\n\t\t\t\t\tfx.toD\n\t\t\t\t);\n\t\t\t}\n\t\t\tfxStart.apply(fx, arguments);\n\n\t\t\treturn this; // chainable\n\t\t};\n\n\t\t// override Fx.step to allow animation of SVG element wrappers\n\t\tmorphProto.compute = function (from, to, delta) {\n\t\t\tvar fx = this,\n\t\t\t\tpaths = fx.paths;\n\n\t\t\tif (paths) {\n\t\t\t\tfx.element.attr(\n\t\t\t\t\t'd',\n\t\t\t\t\tpathAnim.step(paths[0], paths[1], delta, fx.toD)\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\treturn morphCompute.apply(fx, arguments);\n\t\t\t}\n\t\t};\n\t\t/*jslint unparam: false*/\n\t},\n\t\n\t/**\n\t * Run a general method on the framework, following jQuery syntax\n\t * @param {Object} el The HTML element\n\t * @param {String} method Which method to run on the wrapped element\n\t */\n\tadapterRun: function (el, method) {\n\t\t\n\t\t// This currently works for getting inner width and height. If adding\n\t\t// more methods later, we need a conditional implementation for each.\n\t\tif (method === 'width' || method === 'height') {\n\t\t\treturn parseInt($(el).getStyle(method), 10);\n\t\t}\n\t},\n\n\t/**\n\t * Downloads a script and executes a callback when done.\n\t * @param {String} scriptLocation\n\t * @param {Function} callback\n\t */\n\tgetScript: function (scriptLocation, callback) {\n\t\t// We cannot assume that Assets class from mootools-more is available so instead insert a script tag to download script.\n\t\tvar head = doc.getElementsByTagName('head')[0];\n\t\tvar script = doc.createElement('script');\n\n\t\tscript.type = 'text/javascript';\n\t\tscript.src = scriptLocation;\n\t\tscript.onload = callback;\n\n\t\thead.appendChild(script);\n\t},\n\n\t/**\n\t * Animate a HTML element or SVG element wrapper\n\t * @param {Object} el\n\t * @param {Object} params\n\t * @param {Object} options jQuery-like animation options: duration, easing, callback\n\t */\n\tanimate: function (el, params, options) {\n\t\tvar isSVGElement = el.attr,\n\t\t\teffect,\n\t\t\tcomplete = options && options.complete;\n\n\t\tif (isSVGElement && !el.setStyle) {\n\t\t\t// add setStyle and getStyle methods for internal use in Moo\n\t\t\tel.getStyle = el.attr;\n\t\t\tel.setStyle = function () { // property value is given as array in Moo - break it down\n\t\t\t\tvar args = arguments;\n\t\t\t\tthis.attr.call(this, args[0], args[1][0]);\n\t\t\t};\n\t\t\t// dirty hack to trick Moo into handling el as an element wrapper\n\t\t\tel.$family = function () { return true; };\n\t\t}\n\n\t\t// stop running animations\n\t\twin.HighchartsAdapter.stop(el);\n\n\t\t// define and run the effect\n\t\teffect = new Fx.Morph(\n\t\t\tisSVGElement ? el : $(el),\n\t\t\t$extend({\n\t\t\t\ttransition: Fx.Transitions.Quad.easeInOut\n\t\t\t}, options)\n\t\t);\n\n\t\t// Make sure that the element reference is set when animating svg elements\n\t\tif (isSVGElement) {\n\t\t\teffect.element = el;\n\t\t}\n\n\t\t// special treatment for paths\n\t\tif (params.d) {\n\t\t\teffect.toD = params.d;\n\t\t}\n\n\t\t// jQuery-like events\n\t\tif (complete) {\n\t\t\teffect.addEvent('complete', complete);\n\t\t}\n\n\t\t// run\n\t\teffect.start(params);\n\n\t\t// record for use in stop method\n\t\tel.fx = effect;\n\t},\n\n\t/**\n\t * MooTool's each function\n\t *\n\t */\n\teach: function (arr, fn) {\n\t\treturn legacy ?\n\t\t\t$each(arr, fn) :\n\t\t\tArray.each(arr, fn);\n\t},\n\n\t/**\n\t * Map an array\n\t * @param {Array} arr\n\t * @param {Function} fn\n\t */\n\tmap: function (arr, fn) {\n\t\treturn arr.map(fn);\n\t},\n\n\t/**\n\t * Grep or filter an array\n\t * @param {Array} arr\n\t * @param {Function} fn\n\t */\n\tgrep: function (arr, fn) {\n\t\treturn arr.filter(fn);\n\t},\n\t\n\t/**\n\t * Return the index of an item in an array, or -1 if not matched\n\t */\n\tinArray: function (item, arr, from) {\n\t\treturn arr ? arr.indexOf(item, from) : -1;\n\t},\n\n\t/**\n\t * Get the offset of an element relative to the top left corner of the web page\n\t */\n\toffset: function (el) {\n\t\tvar offsets = el.getPosition(); // #1496\n\t\treturn {\n\t\t\tleft: offsets.x,\n\t\t\ttop: offsets.y\n\t\t};\n\t},\n\n\t/**\n\t * Extends an object with Events, if its not done\n\t */\n\textendWithEvents: function (el) {\n\t\t// if the addEvent method is not defined, el is a custom Highcharts object\n\t\t// like series or point\n\t\tif (!el.addEvent) {\n\t\t\tif (el.nodeName) {\n\t\t\t\tel = $(el); // a dynamically generated node\n\t\t\t} else {\n\t\t\t\t$extend(el, new Events()); // a custom object\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Add an event listener\n\t * @param {Object} el HTML element or custom object\n\t * @param {String} type Event type\n\t * @param {Function} fn Event handler\n\t */\n\taddEvent: function (el, type, fn) {\n\t\tif (typeof type === 'string') { // chart broke due to el being string, type function\n\n\t\t\tif (type === 'unload') { // Moo self destructs before custom unload events\n\t\t\t\ttype = 'beforeunload';\n\t\t\t}\n\n\t\t\twin.HighchartsAdapter.extendWithEvents(el);\n\n\t\t\tel.addEvent(type, fn);\n\t\t}\n\t},\n\n\tremoveEvent: function (el, type, fn) {\n\t\tif (typeof el === 'string') {\n\t\t\t// el.removeEvents below apperantly calls this method again. Do not quite understand why, so for now just bail out.\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tif (el.addEvent) { // If el doesn't have an addEvent method, there are no events to remove\n\t\t\tif (type) {\n\t\t\t\tif (type === 'unload') { // Moo self destructs before custom unload events\n\t\t\t\t\ttype = 'beforeunload';\n\t\t\t\t}\n\t\n\t\t\t\tif (fn) {\n\t\t\t\t\tel.removeEvent(type, fn);\n\t\t\t\t} else if (el.removeEvents) { // #958\n\t\t\t\t\tel.removeEvents(type);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tel.removeEvents();\n\t\t\t}\n\t\t}\n\t},\n\n\tfireEvent: function (el, event, eventArguments, defaultFunction) {\n\t\tvar eventArgs = {\n\t\t\ttype: event,\n\t\t\ttarget: el\n\t\t};\n\t\t// create an event object that keeps all functions\n\t\tevent = legacyEvent ? new Event(eventArgs) : new DOMEvent(eventArgs);\n\t\tevent = $extend(event, eventArguments);\n\n\t\t// When running an event on the Chart.prototype, MooTools nests the target in event.event\n\t\tif (!event.target && event.event) {\n\t\t\tevent.target = event.event.target;\n\t\t}\n\n\t\t// override the preventDefault function to be able to use\n\t\t// this for custom events\n\t\tevent.preventDefault = function () {\n\t\t\tdefaultFunction = null;\n\t\t};\n\t\t// if fireEvent is not available on the object, there hasn't been added\n\t\t// any events to it above\n\t\tif (el.fireEvent) {\n\t\t\tel.fireEvent(event.type, event);\n\t\t}\n\n\t\t// fire the default if it is passed and it is not prevented above\n\t\tif (defaultFunction) {\n\t\t\tdefaultFunction(event);\n\t\t}\n\t},\n\t\n\t/**\n\t * Set back e.pageX and e.pageY that MooTools has abstracted away. #1165, #1346.\n\t */\n\twashMouseEvent: function (e) {\n\t\tif (e.page) {\n\t\t\te.pageX = e.page.x;\n\t\t\te.pageY = e.page.y;\n\t\t}\n\t\treturn e;\n\t},\n\n\t/**\n\t * Stop running animations on the object\n\t */\n\tstop: function (el) {\n\t\tif (el.fx) {\n\t\t\tel.fx.cancel();\n\t\t}\n\t}\n};\n\n}());\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/highchart3/js/adapters/prototype-adapter.js",
    "content": "/*\n Highcharts JS v3.0.3 (2013-07-31)\n Prototype adapter\n\n @author Michael Nelson, Torstein Hønsi.\n\n Feel free to use and modify this script.\n Highcharts license: www.highcharts.com/license.\n*/\nvar HighchartsAdapter=function(){var f=typeof Effect!==\"undefined\";return{init:function(a){if(f)Effect.HighchartsTransition=Class.create(Effect.Base,{initialize:function(b,c,d,g){var e;this.element=b;this.key=c;e=b.attr?b.attr(c):$(b).getStyle(c);if(c===\"d\")this.paths=a.init(b,b.d,d),this.toD=d,e=0,d=1;this.start(Object.extend(g||{},{from:e,to:d,attribute:c}))},setup:function(){HighchartsAdapter._extend(this.element);if(!this.element._highchart_animation)this.element._highchart_animation={};this.element._highchart_animation[this.key]=\nthis},update:function(b){var c=this.paths,d=this.element;c&&(b=a.step(c[0],c[1],b,this.toD));d.attr?d.element&&d.attr(this.options.attribute,b):(c={},c[this.options.attribute]=b,$(d).setStyle(c))},finish:function(){this.element&&this.element._highchart_animation&&delete this.element._highchart_animation[this.key]}})},adapterRun:function(a,b){return parseInt($(a).getStyle(b),10)},getScript:function(a,b){var c=$$(\"head\")[0];c&&c.appendChild((new Element(\"script\",{type:\"text/javascript\",src:a})).observe(\"load\",\nb))},addNS:function(a){var b=/^(?:click|mouse(?:down|up|over|move|out))$/;return/^(?:load|unload|abort|error|select|change|submit|reset|focus|blur|resize|scroll)$/.test(a)||b.test(a)?a:\"h:\"+a},addEvent:function(a,b,c){a.addEventListener||a.attachEvent?Event.observe($(a),HighchartsAdapter.addNS(b),c):(HighchartsAdapter._extend(a),a._highcharts_observe(b,c))},animate:function(a,b,c){var d,c=c||{};c.delay=0;c.duration=(c.duration||500)/1E3;c.afterFinish=c.complete;if(f)for(d in b)new Effect.HighchartsTransition($(a),\nd,b[d],c);else{if(a.attr)for(d in b)a.attr(d,b[d]);c.complete&&c.complete()}a.attr||$(a).setStyle(b)},stop:function(a){var b;if(a._highcharts_extended&&a._highchart_animation)for(b in a._highchart_animation)a._highchart_animation[b].cancel()},each:function(a,b){$A(a).each(b)},inArray:function(a,b,c){return b?b.indexOf(a,c):-1},offset:function(a){return $(a).cumulativeOffset()},fireEvent:function(a,b,c,d){a.fire?a.fire(HighchartsAdapter.addNS(b),c):a._highcharts_extended&&(c=c||{},a._highcharts_fire(b,\nc));c&&c.defaultPrevented&&(d=null);d&&d(c)},removeEvent:function(a,b,c){$(a).stopObserving&&(b&&(b=HighchartsAdapter.addNS(b)),$(a).stopObserving(b,c));window===a?Event.stopObserving(a,b,c):(HighchartsAdapter._extend(a),a._highcharts_stop_observing(b,c))},washMouseEvent:function(a){return a},grep:function(a,b){return a.findAll(b)},map:function(a,b){return a.map(b)},_extend:function(a){a._highcharts_extended||Object.extend(a,{_highchart_events:{},_highchart_animation:null,_highcharts_extended:!0,\n_highcharts_observe:function(b,a){this._highchart_events[b]=[this._highchart_events[b],a].compact().flatten()},_highcharts_stop_observing:function(b,a){b?a?this._highchart_events[b]=[this._highchart_events[b]].compact().flatten().without(a):delete this._highchart_events[b]:this._highchart_events={}},_highcharts_fire:function(a,c){var d=this;(this._highchart_events[a]||[]).each(function(a){if(!c.stopped)c.preventDefault=function(){c.defaultPrevented=!0},c.target=d,a.bind(this)(c)===!1&&c.preventDefault()}.bind(this))}})}}}();\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/highchart3/js/adapters/prototype-adapter.src.js",
    "content": "/**\n * @license Highcharts JS v3.0.3 (2013-07-31)\n * Prototype adapter\n *\n * @author Michael Nelson, Torstein Hønsi.\n *\n * Feel free to use and modify this script.\n * Highcharts license: www.highcharts.com/license.\n */\n\n// JSLint options:\n/*global Effect, Class, Event, Element, $, $$, $A */\n\n// Adapter interface between prototype and the Highcharts charting library\nvar HighchartsAdapter = (function () {\n\nvar hasEffect = typeof Effect !== 'undefined';\n\nreturn {\n\n\t/**\n\t * Initialize the adapter. This is run once as Highcharts is first run.\n\t * @param {Object} pathAnim The helper object to do animations across adapters.\n\t */\n\tinit: function (pathAnim) {\n\t\tif (hasEffect) {\n\t\t\t/**\n\t\t\t * Animation for Highcharts SVG element wrappers only\n\t\t\t * @param {Object} element\n\t\t\t * @param {Object} attribute\n\t\t\t * @param {Object} to\n\t\t\t * @param {Object} options\n\t\t\t */\n\t\t\tEffect.HighchartsTransition = Class.create(Effect.Base, {\n\t\t\t\tinitialize: function (element, attr, to, options) {\n\t\t\t\t\tvar from,\n\t\t\t\t\t\topts;\n\n\t\t\t\t\tthis.element = element;\n\t\t\t\t\tthis.key = attr;\n\t\t\t\t\tfrom = element.attr ? element.attr(attr) : $(element).getStyle(attr);\n\n\t\t\t\t\t// special treatment for paths\n\t\t\t\t\tif (attr === 'd') {\n\t\t\t\t\t\tthis.paths = pathAnim.init(\n\t\t\t\t\t\t\telement,\n\t\t\t\t\t\t\telement.d,\n\t\t\t\t\t\t\tto\n\t\t\t\t\t\t);\n\t\t\t\t\t\tthis.toD = to;\n\n\n\t\t\t\t\t\t// fake values in order to read relative position as a float in update\n\t\t\t\t\t\tfrom = 0;\n\t\t\t\t\t\tto = 1;\n\t\t\t\t\t}\n\n\t\t\t\t\topts = Object.extend((options || {}), {\n\t\t\t\t\t\tfrom: from,\n\t\t\t\t\t\tto: to,\n\t\t\t\t\t\tattribute: attr\n\t\t\t\t\t});\n\t\t\t\t\tthis.start(opts);\n\t\t\t\t},\n\t\t\t\tsetup: function () {\n\t\t\t\t\tHighchartsAdapter._extend(this.element);\n\t\t\t\t\t// If this is the first animation on this object, create the _highcharts_animation helper that\n\t\t\t\t\t// contain pointers to the animation objects.\n\t\t\t\t\tif (!this.element._highchart_animation) {\n\t\t\t\t\t\tthis.element._highchart_animation = {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Store a reference to this animation instance.\n\t\t\t\t\tthis.element._highchart_animation[this.key] = this;\n\t\t\t\t},\n\t\t\t\tupdate: function (position) {\n\t\t\t\t\tvar paths = this.paths,\n\t\t\t\t\t\telement = this.element,\n\t\t\t\t\t\tobj;\n\n\t\t\t\t\tif (paths) {\n\t\t\t\t\t\tposition = pathAnim.step(paths[0], paths[1], position, this.toD);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (element.attr) { // SVGElement\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (element.element) { // If not, it has been destroyed (#1405)\n\t\t\t\t\t\t\telement.attr(this.options.attribute, position);\n\t\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t} else { // HTML, #409\n\t\t\t\t\t\tobj = {};\n\t\t\t\t\t\tobj[this.options.attribute] = position;\n\t\t\t\t\t\t$(element).setStyle(obj);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t},\n\t\t\t\tfinish: function () {\n\t\t\t\t\t// Delete the property that holds this animation now that it is finished.\n\t\t\t\t\t// Both canceled animations and complete ones gets a 'finish' call.\n\t\t\t\t\tif (this.element && this.element._highchart_animation) { // #1405\n\t\t\t\t\t\tdelete this.element._highchart_animation[this.key];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t},\n\t\n\t/**\n\t * Run a general method on the framework, following jQuery syntax\n\t * @param {Object} el The HTML element\n\t * @param {String} method Which method to run on the wrapped element\n\t */\n\tadapterRun: function (el, method) {\n\t\t\n\t\t// This currently works for getting inner width and height. If adding\n\t\t// more methods later, we need a conditional implementation for each.\n\t\treturn parseInt($(el).getStyle(method), 10);\n\t\t\n\t},\n\n\t/**\n\t * Downloads a script and executes a callback when done.\n\t * @param {String} scriptLocation\n\t * @param {Function} callback\n\t */\n\tgetScript: function (scriptLocation, callback) {\n\t\tvar head = $$('head')[0]; // Returns an array, so pick the first element.\n\t\tif (head) {\n\t\t\t// Append a new 'script' element, set its type and src attributes, add a 'load' handler that calls the callback\n\t\t\thead.appendChild(new Element('script', { type: 'text/javascript', src: scriptLocation}).observe('load', callback));\n\t\t}\n\t},\n\n\t/**\n\t * Custom events in prototype needs to be namespaced. This method adds a namespace 'h:' in front of\n\t * events that are not recognized as native.\n\t */\n\taddNS: function (eventName) {\n\t\tvar HTMLEvents = /^(?:load|unload|abort|error|select|change|submit|reset|focus|blur|resize|scroll)$/,\n\t\t\tMouseEvents = /^(?:click|mouse(?:down|up|over|move|out))$/;\n\t\treturn (HTMLEvents.test(eventName) || MouseEvents.test(eventName)) ?\n\t\t\teventName :\n\t\t\t'h:' + eventName;\n\t},\n\n\t// el needs an event to be attached. el is not necessarily a dom element\n\taddEvent: function (el, event, fn) {\n\t\tif (el.addEventListener || el.attachEvent) {\n\t\t\tEvent.observe($(el), HighchartsAdapter.addNS(event), fn);\n\n\t\t} else {\n\t\t\tHighchartsAdapter._extend(el);\n\t\t\tel._highcharts_observe(event, fn);\n\t\t}\n\t},\n\n\t// motion makes things pretty. use it if effects is loaded, if not... still get to the end result.\n\tanimate: function (el, params, options) {\n\t\tvar key,\n\t\t\tfx;\n\n\t\t// default options\n\t\toptions = options || {};\n\t\toptions.delay = 0;\n\t\toptions.duration = (options.duration || 500) / 1000;\n\t\toptions.afterFinish = options.complete;\n\n\t\t// animate wrappers and DOM elements\n\t\tif (hasEffect) {\n\t\t\tfor (key in params) {\n\t\t\t\t// The fx variable is seemingly thrown away here, but the Effect.setup will add itself to the _highcharts_animation object\n\t\t\t\t// on the element itself so its not really lost.\n\t\t\t\tfx = new Effect.HighchartsTransition($(el), key, params[key], options);\n\t\t\t}\n\t\t} else {\n\t\t\tif (el.attr) { // #409 without effects\n\t\t\t\tfor (key in params) {\n\t\t\t\t\tel.attr(key, params[key]);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (options.complete) {\n\t\t\t\toptions.complete();\n\t\t\t}\n\t\t}\n\n\t\tif (!el.attr) { // HTML element, #409\n\t\t\t$(el).setStyle(params);\n\t\t}\n\t},\n\n\t// this only occurs in higcharts 2.0+\n\tstop: function (el) {\n\t\tvar key;\n\t\tif (el._highcharts_extended && el._highchart_animation) {\n\t\t\tfor (key in el._highchart_animation) {\n\t\t\t\t// Cancel the animation\n\t\t\t\t// The 'finish' function in the Effect object will remove the reference\n\t\t\t\tel._highchart_animation[key].cancel();\n\t\t\t}\n\t\t}\n\t},\n\n\t// um.. each\n\teach: function (arr, fn) {\n\t\t$A(arr).each(fn);\n\t},\n\t\n\tinArray: function (item, arr, from) {\n\t\treturn arr ? arr.indexOf(item, from) : -1;\n\t},\n\n\t/**\n\t * Get the cumulative offset relative to the top left of the page. This method, unlike its\n\t * jQuery and MooTools counterpart, still suffers from issue #208 regarding the position\n\t * of a chart within a fixed container.\n\t */\n\toffset: function (el) {\n\t\treturn $(el).cumulativeOffset();\n\t},\n\n\t// fire an event based on an event name (event) and an object (el).\n\t// again, el may not be a dom element\n\tfireEvent: function (el, event, eventArguments, defaultFunction) {\n\t\tif (el.fire) {\n\t\t\tel.fire(HighchartsAdapter.addNS(event), eventArguments);\n\t\t} else if (el._highcharts_extended) {\n\t\t\teventArguments = eventArguments || {};\n\t\t\tel._highcharts_fire(event, eventArguments);\n\t\t}\n\n\t\tif (eventArguments && eventArguments.defaultPrevented) {\n\t\t\tdefaultFunction = null;\n\t\t}\n\n\t\tif (defaultFunction) {\n\t\t\tdefaultFunction(eventArguments);\n\t\t}\n\t},\n\n\tremoveEvent: function (el, event, handler) {\n\t\tif ($(el).stopObserving) {\n\t\t\tif (event) {\n\t\t\t\tevent = HighchartsAdapter.addNS(event);\n\t\t\t}\n\t\t\t$(el).stopObserving(event, handler);\n\t\t} if (window === el) {\n\t\t\tEvent.stopObserving(el, event, handler);\n\t\t} else {\n\t\t\tHighchartsAdapter._extend(el);\n\t\t\tel._highcharts_stop_observing(event, handler);\n\t\t}\n\t},\n\t\n\twashMouseEvent: function (e) {\n\t\treturn e;\n\t},\n\n\t// um, grep\n\tgrep: function (arr, fn) {\n\t\treturn arr.findAll(fn);\n\t},\n\n\t// um, map\n\tmap: function (arr, fn) {\n\t\treturn arr.map(fn);\n\t},\n\n\t// extend an object to handle highchart events (highchart objects, not svg elements).\n\t// this is a very simple way of handling events but whatever, it works (i think)\n\t_extend: function (object) {\n\t\tif (!object._highcharts_extended) {\n\t\t\tObject.extend(object, {\n\t\t\t\t_highchart_events: {},\n\t\t\t\t_highchart_animation: null,\n\t\t\t\t_highcharts_extended: true,\n\t\t\t\t_highcharts_observe: function (name, fn) {\n\t\t\t\t\tthis._highchart_events[name] = [this._highchart_events[name], fn].compact().flatten();\n\t\t\t\t},\n\t\t\t\t_highcharts_stop_observing: function (name, fn) {\n\t\t\t\t\tif (name) {\n\t\t\t\t\t\tif (fn) {\n\t\t\t\t\t\t\tthis._highchart_events[name] = [this._highchart_events[name]].compact().flatten().without(fn);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tdelete this._highchart_events[name];\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis._highchart_events = {};\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t_highcharts_fire: function (name, args) {\n\t\t\t\t\tvar target = this;\n\t\t\t\t\t(this._highchart_events[name] || []).each(function (fn) {\n\t\t\t\t\t\t// args is never null here\n\t\t\t\t\t\tif (args.stopped) {\n\t\t\t\t\t\t\treturn; // \"throw $break\" wasn't working. i think because of the scope of 'this'.\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Attach a simple preventDefault function to skip default handler if called\n\t\t\t\t\t\targs.preventDefault = function () {\n\t\t\t\t\t\t\targs.defaultPrevented = true;\n\t\t\t\t\t\t};\n\t\t\t\t\t\targs.target = target;\n\n\t\t\t\t\t\t// If the event handler return false, prevent the default handler from executing\n\t\t\t\t\t\tif (fn.bind(this)(args) === false) {\n\t\t\t\t\t\t\targs.preventDefault();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n.bind(this));\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n};\n}());\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/highchart3/js/highcharts-more.js",
    "content": "/*\n Highcharts JS v3.0.3 (2013-07-31)\n\n (c) 2009-2013 Torstein Hønsi\n\n License: www.highcharts.com/license\n*/\n(function(l,C){function J(a,b,c){this.init.call(this,a,b,c)}function K(a,b,c){a.call(this,b,c);if(this.chart.polar)this.closeSegment=function(a){var c=this.xAxis.center;a.push(\"L\",c[0],c[1])},this.closedStacks=!0}function L(a,b){var c=this.chart,d=this.options.animation,g=this.group,f=this.markerGroup,e=this.xAxis.center,i=c.plotLeft,o=c.plotTop;if(c.polar){if(c.renderer.isSVG)if(d===!0&&(d={}),b){if(c={translateX:e[0]+i,translateY:e[1]+o,scaleX:0.001,scaleY:0.001},g.attr(c),f)f.attrSetters=g.attrSetters,\nf.attr(c)}else c={translateX:i,translateY:o,scaleX:1,scaleY:1},g.animate(c,d),f&&f.animate(c,d),this.animate=null}else a.call(this,b)}var P=l.arrayMin,Q=l.arrayMax,r=l.each,F=l.extend,p=l.merge,R=l.map,q=l.pick,v=l.pInt,m=l.getOptions().plotOptions,h=l.seriesTypes,x=l.extendClass,M=l.splat,n=l.wrap,N=l.Axis,u=l.Tick,z=l.Series,t=h.column.prototype,s=Math,D=s.round,A=s.floor,S=s.max,w=function(){};F(J.prototype,{init:function(a,b,c){var d=this,g=d.defaultOptions;d.chart=b;if(b.angular)g.background=\n{};d.options=a=p(g,a);(a=a.background)&&r([].concat(M(a)).reverse(),function(a){var b=a.backgroundColor,a=p(d.defaultBackgroundOptions,a);if(b)a.backgroundColor=b;a.color=a.backgroundColor;c.options.plotBands.unshift(a)})},defaultOptions:{center:[\"50%\",\"50%\"],size:\"85%\",startAngle:0},defaultBackgroundOptions:{shape:\"circle\",borderWidth:1,borderColor:\"silver\",backgroundColor:{linearGradient:{x1:0,y1:0,x2:0,y2:1},stops:[[0,\"#FFF\"],[1,\"#DDD\"]]},from:Number.MIN_VALUE,innerRadius:0,to:Number.MAX_VALUE,\nouterRadius:\"105%\"}});var G=N.prototype,u=u.prototype,T={getOffset:w,redraw:function(){this.isDirty=!1},render:function(){this.isDirty=!1},setScale:w,setCategories:w,setTitle:w},O={isRadial:!0,defaultRadialGaugeOptions:{labels:{align:\"center\",x:0,y:null},minorGridLineWidth:0,minorTickInterval:\"auto\",minorTickLength:10,minorTickPosition:\"inside\",minorTickWidth:1,plotBands:[],tickLength:10,tickPosition:\"inside\",tickWidth:2,title:{rotation:0},zIndex:2},defaultRadialXOptions:{gridLineWidth:1,labels:{align:null,\ndistance:15,x:0,y:null},maxPadding:0,minPadding:0,plotBands:[],showLastLabel:!1,tickLength:0},defaultRadialYOptions:{gridLineInterpolation:\"circle\",labels:{align:\"right\",x:-3,y:-2},plotBands:[],showLastLabel:!1,title:{x:4,text:null,rotation:90}},setOptions:function(a){this.options=p(this.defaultOptions,this.defaultRadialOptions,a)},getOffset:function(){G.getOffset.call(this);this.chart.axisOffset[this.side]=0;this.center=this.pane.center=h.pie.prototype.getCenter.call(this.pane)},getLinePath:function(a,\nb){var c=this.center,b=q(b,c[2]/2-this.offset);return this.chart.renderer.symbols.arc(this.left+c[0],this.top+c[1],b,b,{start:this.startAngleRad,end:this.endAngleRad,open:!0,innerR:0})},setAxisTranslation:function(){G.setAxisTranslation.call(this);if(this.center&&(this.transA=this.isCircular?(this.endAngleRad-this.startAngleRad)/(this.max-this.min||1):this.center[2]/2/(this.max-this.min||1),this.isXAxis))this.minPixelPadding=this.transA*this.minPointOffset+(this.reversed?(this.endAngleRad-this.startAngleRad)/\n4:0)},beforeSetTickPositions:function(){this.autoConnect&&(this.max+=this.categories&&1||this.pointRange||this.closestPointRange)},setAxisSize:function(){G.setAxisSize.call(this);if(this.center)this.len=this.width=this.height=this.isCircular?this.center[2]*(this.endAngleRad-this.startAngleRad)/2:this.center[2]/2},getPosition:function(a,b){if(!this.isCircular)b=this.translate(a),a=this.min;return this.postTranslate(this.translate(a),q(b,this.center[2]/2)-this.offset)},postTranslate:function(a,b){var c=\nthis.chart,d=this.center,a=this.startAngleRad+a;return{x:c.plotLeft+d[0]+Math.cos(a)*b,y:c.plotTop+d[1]+Math.sin(a)*b}},getPlotBandPath:function(a,b,c){var d=this.center,g=this.startAngleRad,f=d[2]/2,e=[q(c.outerRadius,\"100%\"),c.innerRadius,q(c.thickness,10)],i=/%$/,o,k=this.isCircular;this.options.gridLineInterpolation===\"polygon\"?d=this.getPlotLinePath(a).concat(this.getPlotLinePath(b,!0)):(k||(e[0]=this.translate(a),e[1]=this.translate(b)),e=R(e,function(a){i.test(a)&&(a=v(a,10)*f/100);return a}),\nc.shape===\"circle\"||!k?(a=-Math.PI/2,b=Math.PI*1.5,o=!0):(a=g+this.translate(a),b=g+this.translate(b)),d=this.chart.renderer.symbols.arc(this.left+d[0],this.top+d[1],e[0],e[0],{start:a,end:b,innerR:q(e[1],e[0]-e[2]),open:o}));return d},getPlotLinePath:function(a,b){var c=this.center,d=this.chart,g=this.getPosition(a),f,e,i;this.isCircular?i=[\"M\",c[0]+d.plotLeft,c[1]+d.plotTop,\"L\",g.x,g.y]:this.options.gridLineInterpolation===\"circle\"?(a=this.translate(a))&&(i=this.getLinePath(0,a)):(f=d.xAxis[0],\ni=[],a=this.translate(a),c=f.tickPositions,f.autoConnect&&(c=c.concat([c[0]])),b&&(c=[].concat(c).reverse()),r(c,function(c,b){e=f.getPosition(c,a);i.push(b?\"L\":\"M\",e.x,e.y)}));return i},getTitlePosition:function(){var a=this.center,b=this.chart,c=this.options.title;return{x:b.plotLeft+a[0]+(c.x||0),y:b.plotTop+a[1]-{high:0.5,middle:0.25,low:0}[c.align]*a[2]+(c.y||0)}}};n(G,\"init\",function(a,b,c){var j;var d=b.angular,g=b.polar,f=c.isX,e=d&&f,i,o;o=b.options;var k=c.pane||0;if(d){if(F(this,e?T:O),\ni=!f)this.defaultRadialOptions=this.defaultRadialGaugeOptions}else if(g)F(this,O),this.defaultRadialOptions=(i=f)?this.defaultRadialXOptions:p(this.defaultYAxisOptions,this.defaultRadialYOptions);a.call(this,b,c);if(!e&&(d||g)){a=this.options;if(!b.panes)b.panes=[];this.pane=(j=b.panes[k]=b.panes[k]||new J(M(o.pane)[k],b,this),k=j);k=k.options;b.inverted=!1;o.chart.zoomType=null;this.startAngleRad=b=(k.startAngle-90)*Math.PI/180;this.endAngleRad=o=(q(k.endAngle,k.startAngle+360)-90)*Math.PI/180;this.offset=\na.offset||0;if((this.isCircular=i)&&c.max===C&&o-b===2*Math.PI)this.autoConnect=!0}});n(u,\"getPosition\",function(a,b,c,d,g){var f=this.axis;return f.getPosition?f.getPosition(c):a.call(this,b,c,d,g)});n(u,\"getLabelPosition\",function(a,b,c,d,g,f,e,i,o){var k=this.axis,j=f.y,h=f.align,l=(k.translate(this.pos)+k.startAngleRad+Math.PI/2)/Math.PI*180%360;k.isRadial?(a=k.getPosition(this.pos,k.center[2]/2+q(f.distance,-25)),f.rotation===\"auto\"?d.attr({rotation:l}):j===null&&(j=v(d.styles.lineHeight)*0.9-\nd.getBBox().height/2),h===null&&(h=k.isCircular?l>20&&l<160?\"left\":l>200&&l<340?\"right\":\"center\":\"center\",d.attr({align:h})),a.x+=f.x,a.y+=j):a=a.call(this,b,c,d,g,f,e,i,o);return a});n(u,\"getMarkPath\",function(a,b,c,d,g,f,e){var i=this.axis;i.isRadial?(a=i.getPosition(this.pos,i.center[2]/2+d),b=[\"M\",b,c,\"L\",a.x,a.y]):b=a.call(this,b,c,d,g,f,e);return b});m.arearange=p(m.area,{lineWidth:1,marker:null,threshold:null,tooltip:{pointFormat:'<span style=\"color:{series.color}\">{series.name}</span>: <b>{point.low}</b> - <b>{point.high}</b><br/>'},\ntrackByArea:!0,dataLabels:{verticalAlign:null,xLow:0,xHigh:0,yLow:0,yHigh:0}});h.arearange=l.extendClass(h.area,{type:\"arearange\",pointArrayMap:[\"low\",\"high\"],toYData:function(a){return[a.low,a.high]},pointValKey:\"low\",getSegments:function(){var a=this;r(a.points,function(b){if(!a.options.connectNulls&&(b.low===null||b.high===null))b.y=null;else if(b.low===null&&b.high!==null)b.y=b.high});z.prototype.getSegments.call(this)},translate:function(){var a=this.yAxis;h.area.prototype.translate.apply(this);\nr(this.points,function(b){var c=b.low,d=b.high,g=b.plotY;d===null&&c===null?b.y=null:c===null?(b.plotLow=b.plotY=null,b.plotHigh=a.translate(d,0,1,0,1)):d===null?(b.plotLow=g,b.plotHigh=null):(b.plotLow=g,b.plotHigh=a.translate(d,0,1,0,1))})},getSegmentPath:function(a){var b,c=[],d=a.length,g=z.prototype.getSegmentPath,f,e;e=this.options;var i=e.step;for(b=HighchartsAdapter.grep(a,function(a){return a.plotLow!==null});d--;)f=a[d],f.plotHigh!==null&&c.push({plotX:f.plotX,plotY:f.plotHigh});a=g.call(this,\nb);if(i)i===!0&&(i=\"left\"),e.step={left:\"right\",center:\"center\",right:\"left\"}[i];c=g.call(this,c);e.step=i;e=[].concat(a,c);c[0]=\"L\";this.areaPath=this.areaPath.concat(a,c);return e},drawDataLabels:function(){var a=this.data,b=a.length,c,d=[],g=z.prototype,f=this.options.dataLabels,e,i=this.chart.inverted;if(f.enabled||this._hasPointLabels){for(c=b;c--;)e=a[c],e.y=e.high,e.plotY=e.plotHigh,d[c]=e.dataLabel,e.dataLabel=e.dataLabelUpper,e.below=!1,i?(f.align=\"left\",f.x=f.xHigh):f.y=f.yHigh;g.drawDataLabels.apply(this,\narguments);for(c=b;c--;)e=a[c],e.dataLabelUpper=e.dataLabel,e.dataLabel=d[c],e.y=e.low,e.plotY=e.plotLow,e.below=!0,i?(f.align=\"right\",f.x=f.xLow):f.y=f.yLow;g.drawDataLabels.apply(this,arguments)}},alignDataLabel:h.column.prototype.alignDataLabel,getSymbol:h.column.prototype.getSymbol,drawPoints:w});m.areasplinerange=p(m.arearange);h.areasplinerange=x(h.arearange,{type:\"areasplinerange\",getPointSpline:h.spline.prototype.getPointSpline});m.columnrange=p(m.column,m.arearange,{lineWidth:1,pointRange:null});\nh.columnrange=x(h.arearange,{type:\"columnrange\",translate:function(){var a=this,b=a.yAxis,c;t.translate.apply(a);r(a.points,function(d){var g=d.shapeArgs,f=a.options.minPointLength,e;d.plotHigh=c=b.translate(d.high,0,1,0,1);d.plotLow=d.plotY;e=c;d=d.plotY-c;d<f&&(f-=d,d+=f,e-=f/2);g.height=d;g.y=e})},trackerGroups:[\"group\",\"dataLabels\"],drawGraph:w,pointAttrToOptions:t.pointAttrToOptions,drawPoints:t.drawPoints,drawTracker:t.drawTracker,animate:t.animate,getColumnMetrics:t.getColumnMetrics});m.gauge=\np(m.line,{dataLabels:{enabled:!0,y:15,borderWidth:1,borderColor:\"silver\",borderRadius:3,style:{fontWeight:\"bold\"},verticalAlign:\"top\",zIndex:2},dial:{},pivot:{},tooltip:{headerFormat:\"\"},showInLegend:!1});u={type:\"gauge\",pointClass:l.extendClass(l.Point,{setState:function(a){this.state=a}}),angular:!0,drawGraph:w,trackerGroups:[\"group\",\"dataLabels\"],translate:function(){var a=this.yAxis,b=this.options,c=a.center;this.generatePoints();r(this.points,function(d){var g=p(b.dial,d.dial),f=v(q(g.radius,\n80))*c[2]/200,e=v(q(g.baseLength,70))*f/100,i=v(q(g.rearLength,10))*f/100,o=g.baseWidth||3,k=g.topWidth||1,j=a.startAngleRad+a.translate(d.y,null,null,null,!0);b.wrap===!1&&(j=Math.max(a.startAngleRad,Math.min(a.endAngleRad,j)));j=j*180/Math.PI;d.shapeType=\"path\";d.shapeArgs={d:g.path||[\"M\",-i,-o/2,\"L\",e,-o/2,f,-k/2,f,k/2,e,o/2,-i,o/2,\"z\"],translateX:c[0],translateY:c[1],rotation:j};d.plotX=c[0];d.plotY=c[1]})},drawPoints:function(){var a=this,b=a.yAxis.center,c=a.pivot,d=a.options,g=d.pivot,f=a.chart.renderer;\nr(a.points,function(c){var b=c.graphic,g=c.shapeArgs,k=g.d,j=p(d.dial,c.dial);b?(b.animate(g),g.d=k):c.graphic=f[c.shapeType](g).attr({stroke:j.borderColor||\"none\",\"stroke-width\":j.borderWidth||0,fill:j.backgroundColor||\"black\",rotation:g.rotation}).add(a.group)});c?c.animate({translateX:b[0],translateY:b[1]}):a.pivot=f.circle(0,0,q(g.radius,5)).attr({\"stroke-width\":g.borderWidth||0,stroke:g.borderColor||\"silver\",fill:g.backgroundColor||\"black\"}).translate(b[0],b[1]).add(a.group)},animate:function(a){var b=\nthis;if(!a)r(b.points,function(a){var d=a.graphic;d&&(d.attr({rotation:b.yAxis.startAngleRad*180/Math.PI}),d.animate({rotation:a.shapeArgs.rotation},b.options.animation))}),b.animate=null},render:function(){this.group=this.plotGroup(\"group\",\"series\",this.visible?\"visible\":\"hidden\",this.options.zIndex,this.chart.seriesGroup);h.pie.prototype.render.call(this);this.group.clip(this.chart.clipRect)},setData:h.pie.prototype.setData,drawTracker:h.column.prototype.drawTracker};h.gauge=l.extendClass(h.line,\nu);m.boxplot=p(m.column,{fillColor:\"#FFFFFF\",lineWidth:1,medianWidth:2,states:{hover:{brightness:-0.3}},threshold:null,tooltip:{pointFormat:'<span style=\"color:{series.color};font-weight:bold\">{series.name}</span><br/>Maximum: {point.high}<br/>Upper quartile: {point.q3}<br/>Median: {point.median}<br/>Lower quartile: {point.q1}<br/>Minimum: {point.low}<br/>'},whiskerLength:\"50%\",whiskerWidth:2});h.boxplot=x(h.column,{type:\"boxplot\",pointArrayMap:[\"low\",\"q1\",\"median\",\"q3\",\"high\"],toYData:function(a){return[a.low,\na.q1,a.median,a.q3,a.high]},pointValKey:\"high\",pointAttrToOptions:{fill:\"fillColor\",stroke:\"color\",\"stroke-width\":\"lineWidth\"},drawDataLabels:w,translate:function(){var a=this.yAxis,b=this.pointArrayMap;h.column.prototype.translate.apply(this);r(this.points,function(c){r(b,function(b){c[b]!==null&&(c[b+\"Plot\"]=a.translate(c[b],0,1,0,1))})})},drawPoints:function(){var a=this,b=a.points,c=a.options,d=a.chart.renderer,g,f,e,i,o,k,j,h,l,m,n,H,p,E,I,t,w,s,v,u,z,y,x=a.doQuartiles!==!1,B=parseInt(a.options.whiskerLength,\n10)/100;r(b,function(b){l=b.graphic;z=b.shapeArgs;n={};E={};t={};y=b.color||a.color;if(b.plotY!==C)if(g=b.pointAttr[b.selected?\"selected\":\"\"],w=z.width,s=A(z.x),v=s+w,u=D(w/2),f=A(x?b.q1Plot:b.lowPlot),e=A(x?b.q3Plot:b.lowPlot),i=A(b.highPlot),o=A(b.lowPlot),n.stroke=b.stemColor||c.stemColor||y,n[\"stroke-width\"]=q(b.stemWidth,c.stemWidth,c.lineWidth),n.dashstyle=b.stemDashStyle||c.stemDashStyle,E.stroke=b.whiskerColor||c.whiskerColor||y,E[\"stroke-width\"]=q(b.whiskerWidth,c.whiskerWidth,c.lineWidth),\nt.stroke=b.medianColor||c.medianColor||y,t[\"stroke-width\"]=q(b.medianWidth,c.medianWidth,c.lineWidth),j=n[\"stroke-width\"]%2/2,h=s+u+j,m=[\"M\",h,e,\"L\",h,i,\"M\",h,f,\"L\",h,o,\"z\"],x&&(j=g[\"stroke-width\"]%2/2,h=A(h)+j,f=A(f)+j,e=A(e)+j,s+=j,v+=j,H=[\"M\",s,e,\"L\",s,f,\"L\",v,f,\"L\",v,e,\"L\",s,e,\"z\"]),B&&(j=E[\"stroke-width\"]%2/2,i+=j,o+=j,p=[\"M\",h-u*B,i,\"L\",h+u*B,i,\"M\",h-u*B,o,\"L\",h+u*B,o]),j=t[\"stroke-width\"]%2/2,k=D(b.medianPlot)+j,I=[\"M\",s,k,\"L\",v,k,\"z\"],l)b.stem.animate({d:m}),B&&b.whiskers.animate({d:p}),x&&\nb.box.animate({d:H}),b.medianShape.animate({d:I});else{b.graphic=l=d.g().add(a.group);b.stem=d.path(m).attr(n).add(l);if(B)b.whiskers=d.path(p).attr(E).add(l);if(x)b.box=d.path(H).attr(g).add(l);b.medianShape=d.path(I).attr(t).add(l)}})}});m.errorbar=p(m.boxplot,{color:\"#000000\",grouping:!1,linkedTo:\":previous\",tooltip:{pointFormat:m.arearange.tooltip.pointFormat},whiskerWidth:null});h.errorbar=x(h.boxplot,{type:\"errorbar\",pointArrayMap:[\"low\",\"high\"],toYData:function(a){return[a.low,a.high]},pointValKey:\"high\",\ndoQuartiles:!1,getColumnMetrics:function(){return this.linkedParent&&this.linkedParent.columnMetrics||h.column.prototype.getColumnMetrics.call(this)}});m.waterfall=p(m.column,{lineWidth:1,lineColor:\"#333\",dashStyle:\"dot\",borderColor:\"#333\"});h.waterfall=x(h.column,{type:\"waterfall\",upColorProp:\"fill\",pointArrayMap:[\"low\",\"y\"],pointValKey:\"y\",init:function(a,b){b.stacking=!0;h.column.prototype.init.call(this,a,b)},translate:function(){var a=this.options,b=this.yAxis,c,d,g,f,e,i,o,k,j;c=a.threshold;\na=a.borderWidth%2/2;h.column.prototype.translate.apply(this);k=c;g=this.points;for(d=0,c=g.length;d<c;d++){f=g[d];e=f.shapeArgs;i=this.getStack(d);j=i.points[this.index];if(isNaN(f.y))f.y=this.yData[d];o=S(k,k+f.y)+j[0];e.y=b.translate(o,0,1);f.isSum||f.isIntermediateSum?(e.y=b.translate(j[1],0,1),e.height=b.translate(j[0],0,1)-e.y):k+=i.total;e.height<0&&(e.y+=e.height,e.height*=-1);f.plotY=e.y=D(e.y)-a;e.height=D(e.height);f.yBottom=e.y+e.height}},processData:function(a){var b=this.yData,c=this.points,\nd,g=b.length,f=this.options.threshold||0,e,i,h,k,j,l;i=e=h=k=f;for(l=0;l<g;l++)j=b[l],d=c?c[l]:{},j===\"sum\"||d.isSum?b[l]=i:j===\"intermediateSum\"||d.isIntermediateSum?(b[l]=e,e=f):(i+=j,e+=j),h=Math.min(i,h),k=Math.max(i,k);z.prototype.processData.call(this,a);this.dataMin=h;this.dataMax=k},toYData:function(a){if(a.isSum)return\"sum\";else if(a.isIntermediateSum)return\"intermediateSum\";return a.y},getAttribs:function(){h.column.prototype.getAttribs.apply(this,arguments);var a=this.options,b=a.states,\nc=a.upColor||this.color,a=l.Color(c).brighten(0.1).get(),d=p(this.pointAttr),g=this.upColorProp;d[\"\"][g]=c;d.hover[g]=b.hover.upColor||a;d.select[g]=b.select.upColor||c;r(this.points,function(a){if(a.y>0&&!a.color)a.pointAttr=d,a.color=c})},getGraphPath:function(){var a=this.data,b=a.length,c=D(this.options.lineWidth+this.options.borderWidth)%2/2,d=[],g,f,e;for(e=1;e<b;e++)f=a[e].shapeArgs,g=a[e-1].shapeArgs,f=[\"M\",g.x+g.width,g.y+c,\"L\",f.x,g.y+c],a[e-1].y<0&&(f[2]+=g.height,f[5]+=g.height),d=d.concat(f);\nreturn d},getExtremes:w,getStack:function(a){var b=this.yAxis.stacks,c=this.stackKey;this.processedYData[a]<this.options.threshold&&(c=\"-\"+c);return b[c][a]},drawGraph:z.prototype.drawGraph});m.bubble=p(m.scatter,{dataLabels:{inside:!0,style:{color:\"white\",textShadow:\"0px 0px 3px black\"},verticalAlign:\"middle\"},marker:{lineColor:null,lineWidth:1},minSize:8,maxSize:\"20%\",tooltip:{pointFormat:\"({point.x}, {point.y}), Size: {point.z}\"},turboThreshold:0,zThreshold:0});h.bubble=x(h.scatter,{type:\"bubble\",\npointArrayMap:[\"y\",\"z\"],trackerGroups:[\"group\",\"dataLabelsGroup\"],pointAttrToOptions:{stroke:\"lineColor\",\"stroke-width\":\"lineWidth\",fill:\"fillColor\"},applyOpacity:function(a){var b=this.options.marker,c=q(b.fillOpacity,0.5),a=a||b.fillColor||this.color;c!==1&&(a=l.Color(a).setOpacity(c).get(\"rgba\"));return a},convertAttribs:function(){var a=z.prototype.convertAttribs.apply(this,arguments);a.fill=this.applyOpacity(a.fill);return a},getRadii:function(a,b,c,d){var g,f,e,i=this.zData,h=[];for(f=0,g=i.length;f<\ng;f++)e=b-a,e=e>0?(i[f]-a)/(b-a):0.5,h.push(s.ceil(c+e*(d-c))/2);this.radii=h},animate:function(a){var b=this.options.animation;if(!a)r(this.points,function(a){var d=a.graphic,a=a.shapeArgs;d&&a&&(d.attr(\"r\",1),d.animate({r:a.r},b))}),this.animate=null},translate:function(){var a,b=this.data,c,d,g=this.radii;h.scatter.prototype.translate.call(this);for(a=b.length;a--;)c=b[a],d=g?g[a]:0,c.negative=c.z<(this.options.zThreshold||0),d>=this.minPxSize/2?(c.shapeType=\"circle\",c.shapeArgs={x:c.plotX,y:c.plotY,\nr:d},c.dlBox={x:c.plotX-d,y:c.plotY-d,width:2*d,height:2*d}):c.shapeArgs=c.plotY=c.dlBox=C},drawLegendSymbol:function(a,b){var c=v(a.itemStyle.fontSize)/2;b.legendSymbol=this.chart.renderer.circle(c,a.baseline-c,c).attr({zIndex:3}).add(b.legendGroup);b.legendSymbol.isMarker=!0},drawPoints:h.column.prototype.drawPoints,alignDataLabel:h.column.prototype.alignDataLabel});N.prototype.beforePadding=function(){var a=this,b=this.len,c=this.chart,d=0,g=b,f=this.isXAxis,e=f?\"xData\":\"yData\",i=this.min,h={},\nk=s.min(c.plotWidth,c.plotHeight),j=Number.MAX_VALUE,l=-Number.MAX_VALUE,m=this.max-i,n=b/m,p=[];this.tickPositions&&(r(this.series,function(b){var c=b.options;if(b.type===\"bubble\"&&b.visible&&(a.allowZoomOutside=!0,p.push(b),f))r([\"minSize\",\"maxSize\"],function(a){var b=c[a],d=/%$/.test(b),b=v(b);h[a]=d?k*b/100:b}),b.minPxSize=h.minSize,b=b.zData,b.length&&(j=s.min(j,s.max(P(b),c.displayNegative===!1?c.zThreshold:-Number.MAX_VALUE)),l=s.max(l,Q(b)))}),r(p,function(a){var b=a[e],c=b.length,k;f&&a.getRadii(j,\nl,h.minSize,h.maxSize);if(m>0)for(;c--;)k=a.radii[c],d=Math.min((b[c]-i)*n-k,d),g=Math.max((b[c]-i)*n+k,g)}),m>0&&q(this.options.min,this.userMin)===C&&q(this.options.max,this.userMax)===C&&(g-=b,n*=(b+d-g)/b,this.min+=d/n,this.max+=g/n))};var y=z.prototype,m=l.Pointer.prototype;y.toXY=function(a){var b,c=this.chart;b=a.plotX;var d=a.plotY;a.rectPlotX=b;a.rectPlotY=d;a.clientX=(b/Math.PI*180+this.xAxis.pane.options.startAngle)%360;b=this.xAxis.postTranslate(a.plotX,this.yAxis.len-d);a.plotX=a.polarPlotX=\nb.x-c.plotLeft;a.plotY=a.polarPlotY=b.y-c.plotTop};y.orderTooltipPoints=function(a){if(this.chart.polar)a.sort(function(a,c){return a.clientX-c.clientX}),a[0].wrappedClientX=a[0].clientX+360,a.push(a[0])};n(h.area.prototype,\"init\",K);n(h.areaspline.prototype,\"init\",K);n(h.spline.prototype,\"getPointSpline\",function(a,b,c,d){var g,f,e,i,h,k,j;if(this.chart.polar){g=c.plotX;f=c.plotY;a=b[d-1];e=b[d+1];this.connectEnds&&(a||(a=b[b.length-2]),e||(e=b[1]));if(a&&e)i=a.plotX,h=a.plotY,b=e.plotX,k=e.plotY,\ni=(1.5*g+i)/2.5,h=(1.5*f+h)/2.5,e=(1.5*g+b)/2.5,j=(1.5*f+k)/2.5,b=Math.sqrt(Math.pow(i-g,2)+Math.pow(h-f,2)),k=Math.sqrt(Math.pow(e-g,2)+Math.pow(j-f,2)),i=Math.atan2(h-f,i-g),h=Math.atan2(j-f,e-g),j=Math.PI/2+(i+h)/2,Math.abs(i-j)>Math.PI/2&&(j-=Math.PI),i=g+Math.cos(j)*b,h=f+Math.sin(j)*b,e=g+Math.cos(Math.PI+j)*k,j=f+Math.sin(Math.PI+j)*k,c.rightContX=e,c.rightContY=j;d?(c=[\"C\",a.rightContX||a.plotX,a.rightContY||a.plotY,i||g,h||f,g,f],a.rightContX=a.rightContY=null):c=[\"M\",g,f]}else c=a.call(this,\nb,c,d);return c});n(y,\"translate\",function(a){a.call(this);if(this.chart.polar&&!this.preventPostTranslate)for(var a=this.points,b=a.length;b--;)this.toXY(a[b])});n(y,\"getSegmentPath\",function(a,b){var c=this.points;if(this.chart.polar&&this.options.connectEnds!==!1&&b[b.length-1]===c[c.length-1]&&c[0].y!==null)this.connectEnds=!0,b=[].concat(b,[c[0]]);return a.call(this,b)});n(y,\"animate\",L);n(t,\"animate\",L);n(y,\"setTooltipPoints\",function(a,b){this.chart.polar&&F(this.xAxis,{tooltipLen:360});return a.call(this,\nb)});n(t,\"translate\",function(a){var b=this.xAxis,c=this.yAxis.len,d=b.center,g=b.startAngleRad,f=this.chart.renderer,e,h;this.preventPostTranslate=!0;a.call(this);if(b.isRadial){b=this.points;for(h=b.length;h--;)e=b[h],a=e.barX+g,e.shapeType=\"path\",e.shapeArgs={d:f.symbols.arc(d[0],d[1],c-e.plotY,null,{start:a,end:a+e.pointWidth,innerR:c-q(e.yBottom,c)})},this.toXY(e)}});n(t,\"alignDataLabel\",function(a,b,c,d,g,f){if(this.chart.polar){a=b.rectPlotX/Math.PI*180;if(d.align===null)d.align=a>20&&a<160?\n\"left\":a>200&&a<340?\"right\":\"center\";if(d.verticalAlign===null)d.verticalAlign=a<45||a>315?\"bottom\":a>135&&a<225?\"top\":\"middle\";y.alignDataLabel.call(this,b,c,d,g,f)}else a.call(this,b,c,d,g,f)});n(m,\"getIndex\",function(a,b){var c,d=this.chart,g;d.polar?(g=d.xAxis[0].center,c=b.chartX-g[0]-d.plotLeft,d=b.chartY-g[1]-d.plotTop,c=180-Math.round(Math.atan2(c,d)/Math.PI*180)):c=a.call(this,b);return c});n(m,\"getCoordinates\",function(a,b){var c=this.chart,d={xAxis:[],yAxis:[]};c.polar?r(c.axes,function(a){var f=\na.isXAxis,e=a.center,h=b.chartX-e[0]-c.plotLeft,e=b.chartY-e[1]-c.plotTop;d[f?\"xAxis\":\"yAxis\"].push({axis:a,value:a.translate(f?Math.PI-Math.atan2(h,e):Math.sqrt(Math.pow(h,2)+Math.pow(e,2)),!0)})}):d=a.call(this,b);return d})})(Highcharts);\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/highchart3/js/highcharts-more.src.js",
    "content": "// ==ClosureCompiler==\n// @compilation_level SIMPLE_OPTIMIZATIONS\n\n/**\n * @license Highcharts JS v3.0.3 (2013-07-31)\n *\n * (c) 2009-2013 Torstein Hønsi\n *\n * License: www.highcharts.com/license\n */\n\n// JSLint options:\n/*global Highcharts, HighchartsAdapter, document, window, navigator, setInterval, clearInterval, clearTimeout, setTimeout, location, jQuery, $, console */\n\n(function (Highcharts, UNDEFINED) {\nvar arrayMin = Highcharts.arrayMin,\n\tarrayMax = Highcharts.arrayMax,\n\teach = Highcharts.each,\n\textend = Highcharts.extend,\n\tmerge = Highcharts.merge,\n\tmap = Highcharts.map,\n\tpick = Highcharts.pick,\n\tpInt = Highcharts.pInt,\n\tdefaultPlotOptions = Highcharts.getOptions().plotOptions,\n\tseriesTypes = Highcharts.seriesTypes,\n\textendClass = Highcharts.extendClass,\n\tsplat = Highcharts.splat,\n\twrap = Highcharts.wrap,\n\tAxis = Highcharts.Axis,\n\tTick = Highcharts.Tick,\n\tSeries = Highcharts.Series,\n\tcolProto = seriesTypes.column.prototype,\n\tmath = Math,\n\tmathRound = math.round,\n\tmathFloor = math.floor,\n\tmathMax = math.max,\n\tnoop = function () {};/**\n * The Pane object allows options that are common to a set of X and Y axes.\n * \n * In the future, this can be extended to basic Highcharts and Highstock.\n */\nfunction Pane(options, chart, firstAxis) {\n\tthis.init.call(this, options, chart, firstAxis);\n}\n\n// Extend the Pane prototype\nextend(Pane.prototype, {\n\t\n\t/**\n\t * Initiate the Pane object\n\t */\n\tinit: function (options, chart, firstAxis) {\n\t\tvar pane = this,\n\t\t\tbackgroundOption,\n\t\t\tdefaultOptions = pane.defaultOptions;\n\t\t\n\t\tpane.chart = chart;\n\t\t\n\t\t// Set options\n\t\tif (chart.angular) { // gauges\n\t\t\tdefaultOptions.background = {}; // gets extended by this.defaultBackgroundOptions\n\t\t}\n\t\tpane.options = options = merge(defaultOptions, options);\n\t\t\n\t\tbackgroundOption = options.background;\n\t\t\n\t\t// To avoid having weighty logic to place, update and remove the backgrounds,\n\t\t// push them to the first axis' plot bands and borrow the existing logic there.\n\t\tif (backgroundOption) {\n\t\t\teach([].concat(splat(backgroundOption)).reverse(), function (config) {\n\t\t\t\tvar backgroundColor = config.backgroundColor; // if defined, replace the old one (specific for gradients)\n\t\t\t\tconfig = merge(pane.defaultBackgroundOptions, config);\n\t\t\t\tif (backgroundColor) {\n\t\t\t\t\tconfig.backgroundColor = backgroundColor;\n\t\t\t\t}\n\t\t\t\tconfig.color = config.backgroundColor; // due to naming in plotBands\n\t\t\t\tfirstAxis.options.plotBands.unshift(config);\n\t\t\t});\n\t\t}\n\t},\n\t\n\t/**\n\t * The default options object\n\t */\n\tdefaultOptions: {\n\t\t// background: {conditional},\n\t\tcenter: ['50%', '50%'],\n\t\tsize: '85%',\n\t\tstartAngle: 0\n\t\t//endAngle: startAngle + 360\n\t},\t\n\t\n\t/**\n\t * The default background options\n\t */\n\tdefaultBackgroundOptions: {\n\t\tshape: 'circle',\n\t\tborderWidth: 1,\n\t\tborderColor: 'silver',\n\t\tbackgroundColor: {\n\t\t\tlinearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },\n\t\t\tstops: [\n\t\t\t\t[0, '#FFF'],\n\t\t\t\t[1, '#DDD']\n\t\t\t]\n\t\t},\n\t\tfrom: Number.MIN_VALUE, // corrected to axis min\n\t\tinnerRadius: 0,\n\t\tto: Number.MAX_VALUE, // corrected to axis max\n\t\touterRadius: '105%'\n\t}\n\t\n});\nvar axisProto = Axis.prototype,\n\ttickProto = Tick.prototype;\n\t\n/**\n * Augmented methods for the x axis in order to hide it completely, used for the X axis in gauges\n */\nvar hiddenAxisMixin = {\n\tgetOffset: noop,\n\tredraw: function () {\n\t\tthis.isDirty = false; // prevent setting Y axis dirty\n\t},\n\trender: function () {\n\t\tthis.isDirty = false; // prevent setting Y axis dirty\n\t},\n\tsetScale: noop,\n\tsetCategories: noop,\n\tsetTitle: noop\n};\n\n/**\n * Augmented methods for the value axis\n */\n/*jslint unparam: true*/\nvar radialAxisMixin = {\n\tisRadial: true,\n\t\n\t/**\n\t * The default options extend defaultYAxisOptions\n\t */\n\tdefaultRadialGaugeOptions: {\n\t\tlabels: {\n\t\t\talign: 'center',\n\t\t\tx: 0,\n\t\t\ty: null // auto\n\t\t},\n\t\tminorGridLineWidth: 0,\n\t\tminorTickInterval: 'auto',\n\t\tminorTickLength: 10,\n\t\tminorTickPosition: 'inside',\n\t\tminorTickWidth: 1,\n\t\tplotBands: [],\n\t\ttickLength: 10,\n\t\ttickPosition: 'inside',\n\t\ttickWidth: 2,\n\t\ttitle: {\n\t\t\trotation: 0\n\t\t},\n\t\tzIndex: 2 // behind dials, points in the series group\n\t},\n\t\n\t// Circular axis around the perimeter of a polar chart\n\tdefaultRadialXOptions: {\n\t\tgridLineWidth: 1, // spokes\n\t\tlabels: {\n\t\t\talign: null, // auto\n\t\t\tdistance: 15,\n\t\t\tx: 0,\n\t\t\ty: null // auto\n\t\t},\n\t\tmaxPadding: 0,\n\t\tminPadding: 0,\n\t\tplotBands: [],\n\t\tshowLastLabel: false, \n\t\ttickLength: 0\n\t},\n\t\n\t// Radial axis, like a spoke in a polar chart\n\tdefaultRadialYOptions: {\n\t\tgridLineInterpolation: 'circle',\n\t\tlabels: {\n\t\t\talign: 'right',\n\t\t\tx: -3,\n\t\t\ty: -2\n\t\t},\n\t\tplotBands: [],\n\t\tshowLastLabel: false,\n\t\ttitle: {\n\t\t\tx: 4,\n\t\t\ttext: null,\n\t\t\trotation: 90\n\t\t}\n\t},\n\t\n\t/**\n\t * Merge and set options\n\t */\n\tsetOptions: function (userOptions) {\n\t\t\n\t\tthis.options = merge(\n\t\t\tthis.defaultOptions,\n\t\t\tthis.defaultRadialOptions,\n\t\t\tuserOptions\n\t\t);\n\t\t\n\t},\n\t\n\t/**\n\t * Wrap the getOffset method to return zero offset for title or labels in a radial \n\t * axis\n\t */\n\tgetOffset: function () {\n\t\t// Call the Axis prototype method (the method we're in now is on the instance)\n\t\taxisProto.getOffset.call(this);\n\t\t\n\t\t// Title or label offsets are not counted\n\t\tthis.chart.axisOffset[this.side] = 0;\n\t\t\n\t\t// Set the center array\n\t\tthis.center = this.pane.center = seriesTypes.pie.prototype.getCenter.call(this.pane);\n\t},\n\n\n\t/**\n\t * Get the path for the axis line. This method is also referenced in the getPlotLinePath\n\t * method.\n\t */\n\tgetLinePath: function (lineWidth, radius) {\n\t\tvar center = this.center;\n\t\tradius = pick(radius, center[2] / 2 - this.offset);\n\t\t\n\t\treturn this.chart.renderer.symbols.arc(\n\t\t\tthis.left + center[0],\n\t\t\tthis.top + center[1],\n\t\t\tradius,\n\t\t\tradius, \n\t\t\t{\n\t\t\t\tstart: this.startAngleRad,\n\t\t\t\tend: this.endAngleRad,\n\t\t\t\topen: true,\n\t\t\t\tinnerR: 0\n\t\t\t}\n\t\t);\n\t},\n\n\t/**\n\t * Override setAxisTranslation by setting the translation to the difference\n\t * in rotation. This allows the translate method to return angle for \n\t * any given value.\n\t */\n\tsetAxisTranslation: function () {\n\t\t\n\t\t// Call uber method\t\t\n\t\taxisProto.setAxisTranslation.call(this);\n\t\t\t\n\t\t// Set transA and minPixelPadding\n\t\tif (this.center) { // it's not defined the first time\n\t\t\tif (this.isCircular) {\n\t\t\t\t\n\t\t\t\tthis.transA = (this.endAngleRad - this.startAngleRad) / \n\t\t\t\t\t((this.max - this.min) || 1);\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t} else { \n\t\t\t\tthis.transA = (this.center[2] / 2) / ((this.max - this.min) || 1);\n\t\t\t}\n\t\t\t\n\t\t\tif (this.isXAxis) {\n\t\t\t\tthis.minPixelPadding = this.transA * this.minPointOffset +\n\t\t\t\t\t(this.reversed ? (this.endAngleRad - this.startAngleRad) / 4 : 0); // ???\n\t\t\t}\n\t\t}\n\t},\n\t\n\t/**\n\t * In case of auto connect, add one closestPointRange to the max value right before\n\t * tickPositions are computed, so that ticks will extend passed the real max.\n\t */\n\tbeforeSetTickPositions: function () {\n\t\tif (this.autoConnect) {\n\t\t\tthis.max += (this.categories && 1) || this.pointRange || this.closestPointRange; // #1197\n\t\t}\n\t},\n\t\n\t/**\n\t * Override the setAxisSize method to use the arc's circumference as length. This\n\t * allows tickPixelInterval to apply to pixel lengths along the perimeter\n\t */\n\tsetAxisSize: function () {\n\t\t\n\t\taxisProto.setAxisSize.call(this);\n\t\t\n\t\tif (this.center) { // it's not defined the first time\n\t\t\tthis.len = this.width = this.height = this.isCircular ?\n\t\t\t\tthis.center[2] * (this.endAngleRad - this.startAngleRad) / 2 :\n\t\t\t\tthis.center[2] / 2;\n\t\t}\n\t},\n\t\n\t/**\n\t * Returns the x, y coordinate of a point given by a value and a pixel distance\n\t * from center\n\t */\n\tgetPosition: function (value, length) {\n\t\tif (!this.isCircular) {\n\t\t\tlength = this.translate(value);\n\t\t\tvalue = this.min;\t\n\t\t}\n\t\t\n\t\treturn this.postTranslate(\n\t\t\tthis.translate(value),\n\t\t\tpick(length, this.center[2] / 2) - this.offset\n\t\t);\t\t\n\t},\n\t\n\t/**\n\t * Translate from intermediate plotX (angle), plotY (axis.len - radius) to final chart coordinates. \n\t */\n\tpostTranslate: function (angle, radius) {\n\t\t\n\t\tvar chart = this.chart,\n\t\t\tcenter = this.center;\n\t\t\t\n\t\tangle = this.startAngleRad + angle;\n\t\t\n\t\treturn {\n\t\t\tx: chart.plotLeft + center[0] + Math.cos(angle) * radius,\n\t\t\ty: chart.plotTop + center[1] + Math.sin(angle) * radius\n\t\t}; \n\t\t\n\t},\n\t\n\t/**\n\t * Find the path for plot bands along the radial axis\n\t */\n\tgetPlotBandPath: function (from, to, options) {\n\t\tvar center = this.center,\n\t\t\tstartAngleRad = this.startAngleRad,\n\t\t\tfullRadius = center[2] / 2,\n\t\t\tradii = [\n\t\t\t\tpick(options.outerRadius, '100%'),\n\t\t\t\toptions.innerRadius,\n\t\t\t\tpick(options.thickness, 10)\n\t\t\t],\n\t\t\tpercentRegex = /%$/,\n\t\t\tstart,\n\t\t\tend,\n\t\t\topen,\n\t\t\tisCircular = this.isCircular, // X axis in a polar chart\n\t\t\tret;\n\t\t\t\n\t\t// Polygonal plot bands\n\t\tif (this.options.gridLineInterpolation === 'polygon') {\n\t\t\tret = this.getPlotLinePath(from).concat(this.getPlotLinePath(to, true));\n\t\t\n\t\t// Circular grid bands\n\t\t} else {\n\t\t\t\n\t\t\t// Plot bands on Y axis (radial axis) - inner and outer radius depend on to and from\n\t\t\tif (!isCircular) {\n\t\t\t\tradii[0] = this.translate(from);\n\t\t\t\tradii[1] = this.translate(to);\n\t\t\t}\n\t\t\t\n\t\t\t// Convert percentages to pixel values\n\t\t\tradii = map(radii, function (radius) {\n\t\t\t\tif (percentRegex.test(radius)) {\n\t\t\t\t\tradius = (pInt(radius, 10) * fullRadius) / 100;\n\t\t\t\t}\n\t\t\t\treturn radius;\n\t\t\t});\n\t\t\t\n\t\t\t// Handle full circle\n\t\t\tif (options.shape === 'circle' || !isCircular) {\n\t\t\t\tstart = -Math.PI / 2;\n\t\t\t\tend = Math.PI * 1.5;\n\t\t\t\topen = true;\n\t\t\t} else {\n\t\t\t\tstart = startAngleRad + this.translate(from);\n\t\t\t\tend = startAngleRad + this.translate(to);\n\t\t\t}\n\t\t\n\t\t\n\t\t\tret = this.chart.renderer.symbols.arc(\n\t\t\t\tthis.left + center[0],\n\t\t\t\tthis.top + center[1],\n\t\t\t\tradii[0],\n\t\t\t\tradii[0],\n\t\t\t\t{\n\t\t\t\t\tstart: start,\n\t\t\t\t\tend: end,\n\t\t\t\t\tinnerR: pick(radii[1], radii[0] - radii[2]),\n\t\t\t\t\topen: open\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t\t \n\t\treturn ret;\n\t},\n\t\n\t/**\n\t * Find the path for plot lines perpendicular to the radial axis.\n\t */\n\tgetPlotLinePath: function (value, reverse) {\n\t\tvar axis = this,\n\t\t\tcenter = axis.center,\n\t\t\tchart = axis.chart,\n\t\t\tend = axis.getPosition(value),\n\t\t\txAxis,\n\t\t\txy,\n\t\t\ttickPositions,\n\t\t\tret;\n\t\t\n\t\t// Spokes\n\t\tif (axis.isCircular) {\n\t\t\tret = ['M', center[0] + chart.plotLeft, center[1] + chart.plotTop, 'L', end.x, end.y];\n\t\t\n\t\t// Concentric circles\t\t\t\n\t\t} else if (axis.options.gridLineInterpolation === 'circle') {\n\t\t\tvalue = axis.translate(value);\n\t\t\tif (value) { // a value of 0 is in the center\n\t\t\t\tret = axis.getLinePath(0, value);\n\t\t\t}\n\t\t// Concentric polygons \n\t\t} else {\n\t\t\txAxis = chart.xAxis[0];\n\t\t\tret = [];\n\t\t\tvalue = axis.translate(value);\n\t\t\ttickPositions = xAxis.tickPositions;\n\t\t\tif (xAxis.autoConnect) {\n\t\t\t\ttickPositions = tickPositions.concat([tickPositions[0]]);\n\t\t\t}\n\t\t\t// Reverse the positions for concatenation of polygonal plot bands\n\t\t\tif (reverse) {\n\t\t\t\ttickPositions = [].concat(tickPositions).reverse();\n\t\t\t}\n\t\t\t\t\n\t\t\teach(tickPositions, function (pos, i) {\n\t\t\t\txy = xAxis.getPosition(pos, value);\n\t\t\t\tret.push(i ? 'L' : 'M', xy.x, xy.y);\n\t\t\t});\n\t\t\t\n\t\t}\n\t\treturn ret;\n\t},\n\t\n\t/**\n\t * Find the position for the axis title, by default inside the gauge\n\t */\n\tgetTitlePosition: function () {\n\t\tvar center = this.center,\n\t\t\tchart = this.chart,\n\t\t\ttitleOptions = this.options.title;\n\t\t\n\t\treturn { \n\t\t\tx: chart.plotLeft + center[0] + (titleOptions.x || 0), \n\t\t\ty: chart.plotTop + center[1] - ({ high: 0.5, middle: 0.25, low: 0 }[titleOptions.align] * \n\t\t\t\tcenter[2]) + (titleOptions.y || 0)  \n\t\t};\n\t}\n\t\n};\n/*jslint unparam: false*/\n\n/**\n * Override axisProto.init to mix in special axis instance functions and function overrides\n */\nwrap(axisProto, 'init', function (proceed, chart, userOptions) {\n\tvar axis = this,\n\t\tangular = chart.angular,\n\t\tpolar = chart.polar,\n\t\tisX = userOptions.isX,\n\t\tisHidden = angular && isX,\n\t\tisCircular,\n\t\tstartAngleRad,\n\t\tendAngleRad,\n\t\toptions,\n\t\tchartOptions = chart.options,\n\t\tpaneIndex = userOptions.pane || 0,\n\t\tpane,\n\t\tpaneOptions;\n\t\t\n\t// Before prototype.init\n\tif (angular) {\n\t\textend(this, isHidden ? hiddenAxisMixin : radialAxisMixin);\n\t\tisCircular =  !isX;\n\t\tif (isCircular) {\n\t\t\tthis.defaultRadialOptions = this.defaultRadialGaugeOptions;\n\t\t}\n\t\t\n\t} else if (polar) {\n\t\t//extend(this, userOptions.isX ? radialAxisMixin : radialAxisMixin);\n\t\textend(this, radialAxisMixin);\n\t\tisCircular = isX;\n\t\tthis.defaultRadialOptions = isX ? this.defaultRadialXOptions : merge(this.defaultYAxisOptions, this.defaultRadialYOptions);\n\t\t\n\t}\n\t\n\t// Run prototype.init\n\tproceed.call(this, chart, userOptions);\n\t\n\tif (!isHidden && (angular || polar)) {\n\t\toptions = this.options;\n\t\t\n\t\t// Create the pane and set the pane options.\n\t\tif (!chart.panes) {\n\t\t\tchart.panes = [];\n\t\t}\n\t\tthis.pane = pane = chart.panes[paneIndex] = chart.panes[paneIndex] || new Pane(\n\t\t\tsplat(chartOptions.pane)[paneIndex],\n\t\t\tchart,\n\t\t\taxis\n\t\t);\n\t\tpaneOptions = pane.options;\n\t\t\n\t\t\t\n\t\t// Disable certain features on angular and polar axes\n\t\tchart.inverted = false;\n\t\tchartOptions.chart.zoomType = null;\n\t\t\n\t\t// Start and end angle options are\n\t\t// given in degrees relative to top, while internal computations are\n\t\t// in radians relative to right (like SVG).\n\t\tthis.startAngleRad = startAngleRad = (paneOptions.startAngle - 90) * Math.PI / 180;\n\t\tthis.endAngleRad = endAngleRad = (pick(paneOptions.endAngle, paneOptions.startAngle + 360)  - 90) * Math.PI / 180;\n\t\tthis.offset = options.offset || 0;\n\t\t\n\t\tthis.isCircular = isCircular;\n\t\t\n\t\t// Automatically connect grid lines?\n\t\tif (isCircular && userOptions.max === UNDEFINED && endAngleRad - startAngleRad === 2 * Math.PI) {\n\t\t\tthis.autoConnect = true;\n\t\t}\n\t}\n\t\n});\n\n/**\n * Add special cases within the Tick class' methods for radial axes.\n */\t\nwrap(tickProto, 'getPosition', function (proceed, horiz, pos, tickmarkOffset, old) {\n\tvar axis = this.axis;\n\t\n\treturn axis.getPosition ? \n\t\taxis.getPosition(pos) :\n\t\tproceed.call(this, horiz, pos, tickmarkOffset, old);\t\n});\n\n/**\n * Wrap the getLabelPosition function to find the center position of the label\n * based on the distance option\n */\t\nwrap(tickProto, 'getLabelPosition', function (proceed, x, y, label, horiz, labelOptions, tickmarkOffset, index, step) {\n\tvar axis = this.axis,\n\t\toptionsY = labelOptions.y,\n\t\tret,\n\t\talign = labelOptions.align,\n\t\tangle = ((axis.translate(this.pos) + axis.startAngleRad + Math.PI / 2) / Math.PI * 180) % 360;\n\t\n\tif (axis.isRadial) {\n\t\tret = axis.getPosition(this.pos, (axis.center[2] / 2) + pick(labelOptions.distance, -25));\n\t\t\n\t\t// Automatically rotated\n\t\tif (labelOptions.rotation === 'auto') {\n\t\t\tlabel.attr({ \n\t\t\t\trotation: angle\n\t\t\t});\n\t\t\n\t\t// Vertically centered\n\t\t} else if (optionsY === null) {\n\t\t\toptionsY = pInt(label.styles.lineHeight) * 0.9 - label.getBBox().height / 2;\n\t\t\n\t\t}\n\t\t\n\t\t// Automatic alignment\n\t\tif (align === null) {\n\t\t\tif (axis.isCircular) {\n\t\t\t\tif (angle > 20 && angle < 160) {\n\t\t\t\t\talign = 'left'; // right hemisphere\n\t\t\t\t} else if (angle > 200 && angle < 340) {\n\t\t\t\t\talign = 'right'; // left hemisphere\n\t\t\t\t} else {\n\t\t\t\t\talign = 'center'; // top or bottom\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\talign = 'center';\n\t\t\t}\n\t\t\tlabel.attr({\n\t\t\t\talign: align\n\t\t\t});\n\t\t}\n\t\t\n\t\tret.x += labelOptions.x;\n\t\tret.y += optionsY;\n\t\t\n\t} else {\n\t\tret = proceed.call(this, x, y, label, horiz, labelOptions, tickmarkOffset, index, step);\n\t}\n\treturn ret;\n});\n\n/**\n * Wrap the getMarkPath function to return the path of the radial marker\n */\nwrap(tickProto, 'getMarkPath', function (proceed, x, y, tickLength, tickWidth, horiz, renderer) {\n\tvar axis = this.axis,\n\t\tendPoint,\n\t\tret;\n\t\t\n\tif (axis.isRadial) {\n\t\tendPoint = axis.getPosition(this.pos, axis.center[2] / 2 + tickLength);\n\t\tret = [\n\t\t\t'M',\n\t\t\tx,\n\t\t\ty,\n\t\t\t'L',\n\t\t\tendPoint.x,\n\t\t\tendPoint.y\n\t\t];\n\t} else {\n\t\tret = proceed.call(this, x, y, tickLength, tickWidth, horiz, renderer);\n\t}\n\treturn ret;\n});/* \n * The AreaRangeSeries class\n * \n */\n\n/**\n * Extend the default options with map options\n */\ndefaultPlotOptions.arearange = merge(defaultPlotOptions.area, {\n\tlineWidth: 1,\n\tmarker: null,\n\tthreshold: null,\n\ttooltip: {\n\t\tpointFormat: '<span style=\"color:{series.color}\">{series.name}</span>: <b>{point.low}</b> - <b>{point.high}</b><br/>' \n\t},\n\ttrackByArea: true,\n\tdataLabels: {\n\t\tverticalAlign: null,\n\t\txLow: 0,\n\t\txHigh: 0,\n\t\tyLow: 0,\n\t\tyHigh: 0\t\n\t}\n});\n\n/**\n * Add the series type\n */\nseriesTypes.arearange = Highcharts.extendClass(seriesTypes.area, {\n\ttype: 'arearange',\n\tpointArrayMap: ['low', 'high'],\n\ttoYData: function (point) {\n\t\treturn [point.low, point.high];\n\t},\n\tpointValKey: 'low',\n\t\n\t/**\n\t * Extend getSegments to force null points if the higher value is null. #1703.\n\t */\n\tgetSegments: function () {\n\t\tvar series = this;\n\n\t\teach(series.points, function (point) {\n\t\t\tif (!series.options.connectNulls && (point.low === null || point.high === null)) {\n\t\t\t\tpoint.y = null;\n\t\t\t} else if (point.low === null && point.high !== null) {\n\t\t\t\tpoint.y = point.high;\n\t\t\t}\n\t\t});\n\t\tSeries.prototype.getSegments.call(this);\n\t},\n\t\n\t/**\n\t * Translate data points from raw values x and y to plotX and plotY\n\t */\n\ttranslate: function () {\n\t\tvar series = this,\n\t\t\tyAxis = series.yAxis;\n\n\t\tseriesTypes.area.prototype.translate.apply(series);\n\n\t\t// Set plotLow and plotHigh\n\t\teach(series.points, function (point) {\n\n\t\t\tvar low = point.low,\n\t\t\t\thigh = point.high,\n\t\t\t\tplotY = point.plotY;\n\n\t\t\tif (high === null && low === null) {\n\t\t\t\tpoint.y = null;\n\t\t\t} else if (low === null) {\n\t\t\t\tpoint.plotLow = point.plotY = null;\n\t\t\t\tpoint.plotHigh = yAxis.translate(high, 0, 1, 0, 1);\n\t\t\t} else if (high === null) {\n\t\t\t\tpoint.plotLow = plotY;\n\t\t\t\tpoint.plotHigh = null;\n\t\t\t} else {\n\t\t\t\tpoint.plotLow = plotY;\n\t\t\t\tpoint.plotHigh = yAxis.translate(high, 0, 1, 0, 1);\n\t\t\t}\n\t\t});\n\t},\n\t\n\t/**\n\t * Extend the line series' getSegmentPath method by applying the segment\n\t * path to both lower and higher values of the range\n\t */\n\tgetSegmentPath: function (segment) {\n\t\t\n\t\tvar lowSegment,\n\t\t\thighSegment = [],\n\t\t\ti = segment.length,\n\t\t\tbaseGetSegmentPath = Series.prototype.getSegmentPath,\n\t\t\tpoint,\n\t\t\tlinePath,\n\t\t\tlowerPath,\n\t\t\toptions = this.options,\n\t\t\tstep = options.step,\n\t\t\thigherPath;\n\t\t\t\n\t\t// Remove nulls from low segment\n\t\tlowSegment = HighchartsAdapter.grep(segment, function (point) {\n\t\t\treturn point.plotLow !== null;\n\t\t});\n\t\t\n\t\t// Make a segment with plotX and plotY for the top values\n\t\twhile (i--) {\n\t\t\tpoint = segment[i];\n\t\t\tif (point.plotHigh !== null) {\n\t\t\t\thighSegment.push({\n\t\t\t\t\tplotX: point.plotX,\n\t\t\t\t\tplotY: point.plotHigh\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\t\n\t\t// Get the paths\n\t\tlowerPath = baseGetSegmentPath.call(this, lowSegment);\n\t\tif (step) {\n\t\t\tif (step === true) {\n\t\t\t\tstep = 'left';\n\t\t\t}\n\t\t\toptions.step = { left: 'right', center: 'center', right: 'left' }[step]; // swap for reading in getSegmentPath\n\t\t}\n\t\thigherPath = baseGetSegmentPath.call(this, highSegment);\n\t\toptions.step = step;\n\t\t\n\t\t// Create a line on both top and bottom of the range\n\t\tlinePath = [].concat(lowerPath, higherPath);\n\t\t\n\t\t// For the area path, we need to change the 'move' statement into 'lineTo' or 'curveTo'\n\t\thigherPath[0] = 'L'; // this probably doesn't work for spline\t\t\t\n\t\tthis.areaPath = this.areaPath.concat(lowerPath, higherPath);\n\t\t\n\t\treturn linePath;\n\t},\n\t\n\t/**\n\t * Extend the basic drawDataLabels method by running it for both lower and higher\n\t * values.\n\t */\n\tdrawDataLabels: function () {\n\t\t\n\t\tvar data = this.data,\n\t\t\tlength = data.length,\n\t\t\ti,\n\t\t\toriginalDataLabels = [],\n\t\t\tseriesProto = Series.prototype,\n\t\t\tdataLabelOptions = this.options.dataLabels,\n\t\t\tpoint,\n\t\t\tinverted = this.chart.inverted;\n\t\t\t\n\t\tif (dataLabelOptions.enabled || this._hasPointLabels) {\n\t\t\t\n\t\t\t// Step 1: set preliminary values for plotY and dataLabel and draw the upper labels\n\t\t\ti = length;\n\t\t\twhile (i--) {\n\t\t\t\tpoint = data[i];\n\t\t\t\t\n\t\t\t\t// Set preliminary values\n\t\t\t\tpoint.y = point.high;\n\t\t\t\tpoint.plotY = point.plotHigh;\n\t\t\t\t\n\t\t\t\t// Store original data labels and set preliminary label objects to be picked up \n\t\t\t\t// in the uber method\n\t\t\t\toriginalDataLabels[i] = point.dataLabel;\n\t\t\t\tpoint.dataLabel = point.dataLabelUpper;\n\t\t\t\t\n\t\t\t\t// Set the default offset\n\t\t\t\tpoint.below = false;\n\t\t\t\tif (inverted) {\n\t\t\t\t\tdataLabelOptions.align = 'left';\n\t\t\t\t\tdataLabelOptions.x = dataLabelOptions.xHigh;\t\t\t\t\t\t\t\t\n\t\t\t\t} else {\n\t\t\t\t\tdataLabelOptions.y = dataLabelOptions.yHigh;\n\t\t\t\t}\n\t\t\t}\n\t\t\tseriesProto.drawDataLabels.apply(this, arguments); // #1209\n\t\t\t\n\t\t\t// Step 2: reorganize and handle data labels for the lower values\n\t\t\ti = length;\n\t\t\twhile (i--) {\n\t\t\t\tpoint = data[i];\n\t\t\t\t\n\t\t\t\t// Move the generated labels from step 1, and reassign the original data labels\n\t\t\t\tpoint.dataLabelUpper = point.dataLabel;\n\t\t\t\tpoint.dataLabel = originalDataLabels[i];\n\t\t\t\t\n\t\t\t\t// Reset values\n\t\t\t\tpoint.y = point.low;\n\t\t\t\tpoint.plotY = point.plotLow;\n\t\t\t\t\n\t\t\t\t// Set the default offset\n\t\t\t\tpoint.below = true;\n\t\t\t\tif (inverted) {\n\t\t\t\t\tdataLabelOptions.align = 'right';\n\t\t\t\t\tdataLabelOptions.x = dataLabelOptions.xLow;\n\t\t\t\t} else {\n\t\t\t\t\tdataLabelOptions.y = dataLabelOptions.yLow;\n\t\t\t\t}\n\t\t\t}\n\t\t\tseriesProto.drawDataLabels.apply(this, arguments);\n\t\t}\n\t\n\t},\n\t\n\talignDataLabel: seriesTypes.column.prototype.alignDataLabel,\n\t\n\tgetSymbol: seriesTypes.column.prototype.getSymbol,\n\t\n\tdrawPoints: noop\n});/**\n * The AreaSplineRangeSeries class\n */\n\ndefaultPlotOptions.areasplinerange = merge(defaultPlotOptions.arearange);\n\n/**\n * AreaSplineRangeSeries object\n */\nseriesTypes.areasplinerange = extendClass(seriesTypes.arearange, {\n\ttype: 'areasplinerange',\n\tgetPointSpline: seriesTypes.spline.prototype.getPointSpline\n});/**\n * The ColumnRangeSeries class\n */\ndefaultPlotOptions.columnrange = merge(defaultPlotOptions.column, defaultPlotOptions.arearange, {\n\tlineWidth: 1,\n\tpointRange: null\n});\n\n/**\n * ColumnRangeSeries object\n */\nseriesTypes.columnrange = extendClass(seriesTypes.arearange, {\n\ttype: 'columnrange',\n\t/**\n\t * Translate data points from raw values x and y to plotX and plotY\n\t */\n\ttranslate: function () {\n\t\tvar series = this,\n\t\t\tyAxis = series.yAxis,\n\t\t\tplotHigh;\n\n\t\tcolProto.translate.apply(series);\n\n\t\t// Set plotLow and plotHigh\n\t\teach(series.points, function (point) {\n\t\t\tvar shapeArgs = point.shapeArgs,\n\t\t\t\tminPointLength = series.options.minPointLength,\n\t\t\t\theightDifference,\n\t\t\t\theight,\n\t\t\t\ty;\n\n\t\t\tpoint.plotHigh = plotHigh = yAxis.translate(point.high, 0, 1, 0, 1);\n\t\t\tpoint.plotLow = point.plotY;\n\n\t\t\t// adjust shape\n\t\t\ty = plotHigh;\n\t\t\theight = point.plotY - plotHigh;\n\n\t\t\tif (height < minPointLength) {\n\t\t\t\theightDifference = (minPointLength - height);\n\t\t\t\theight += heightDifference;\n\t\t\t\ty -= heightDifference / 2;\n\t\t\t}\n\t\t\tshapeArgs.height = height;\n\t\t\tshapeArgs.y = y;\n\t\t});\n\t},\n\ttrackerGroups: ['group', 'dataLabels'],\n\tdrawGraph: noop,\n\tpointAttrToOptions: colProto.pointAttrToOptions,\n\tdrawPoints: colProto.drawPoints,\n\tdrawTracker: colProto.drawTracker,\n\tanimate: colProto.animate,\n\tgetColumnMetrics: colProto.getColumnMetrics\n});\n/* \n * The GaugeSeries class\n */\n\n\n\n/**\n * Extend the default options\n */\ndefaultPlotOptions.gauge = merge(defaultPlotOptions.line, {\n\tdataLabels: {\n\t\tenabled: true,\n\t\ty: 15,\n\t\tborderWidth: 1,\n\t\tborderColor: 'silver',\n\t\tborderRadius: 3,\n\t\tstyle: {\n\t\t\tfontWeight: 'bold'\n\t\t},\n\t\tverticalAlign: 'top',\n\t\tzIndex: 2\n\t},\n\tdial: {\n\t\t// radius: '80%',\n\t\t// backgroundColor: 'black',\n\t\t// borderColor: 'silver',\n\t\t// borderWidth: 0,\n\t\t// baseWidth: 3,\n\t\t// topWidth: 1,\n\t\t// baseLength: '70%' // of radius\n\t\t// rearLength: '10%'\n\t},\n\tpivot: {\n\t\t//radius: 5,\n\t\t//borderWidth: 0\n\t\t//borderColor: 'silver',\n\t\t//backgroundColor: 'black'\n\t},\n\ttooltip: {\n\t\theaderFormat: ''\n\t},\n\tshowInLegend: false\n});\n\n/**\n * Extend the point object\n */\nvar GaugePoint = Highcharts.extendClass(Highcharts.Point, {\n\t/**\n\t * Don't do any hover colors or anything\n\t */\n\tsetState: function (state) {\n\t\tthis.state = state;\n\t}\n});\n\n\n/**\n * Add the series type\n */\nvar GaugeSeries = {\n\ttype: 'gauge',\n\tpointClass: GaugePoint,\n\t\n\t// chart.angular will be set to true when a gauge series is present, and this will\n\t// be used on the axes\n\tangular: true, \n\tdrawGraph: noop,\n\ttrackerGroups: ['group', 'dataLabels'],\n\t\n\t/**\n\t * Calculate paths etc\n\t */\n\ttranslate: function () {\n\t\t\n\t\tvar series = this,\n\t\t\tyAxis = series.yAxis,\n\t\t\toptions = series.options,\n\t\t\tcenter = yAxis.center;\n\t\t\t\n\t\tseries.generatePoints();\n\t\t\n\t\teach(series.points, function (point) {\n\t\t\t\n\t\t\tvar dialOptions = merge(options.dial, point.dial),\n\t\t\t\tradius = (pInt(pick(dialOptions.radius, 80)) * center[2]) / 200,\n\t\t\t\tbaseLength = (pInt(pick(dialOptions.baseLength, 70)) * radius) / 100,\n\t\t\t\trearLength = (pInt(pick(dialOptions.rearLength, 10)) * radius) / 100,\n\t\t\t\tbaseWidth = dialOptions.baseWidth || 3,\n\t\t\t\ttopWidth = dialOptions.topWidth || 1,\n\t\t\t\trotation = yAxis.startAngleRad + yAxis.translate(point.y, null, null, null, true);\n\n\t\t\t// Handle the wrap option\n\t\t\tif (options.wrap === false) {\n\t\t\t\trotation = Math.max(yAxis.startAngleRad, Math.min(yAxis.endAngleRad, rotation));\n\t\t\t}\n\t\t\trotation = rotation * 180 / Math.PI;\n\t\t\t\t\n\t\t\tpoint.shapeType = 'path';\n\t\t\tpoint.shapeArgs = {\n\t\t\t\td: dialOptions.path || [\n\t\t\t\t\t'M', \n\t\t\t\t\t-rearLength, -baseWidth / 2, \n\t\t\t\t\t'L', \n\t\t\t\t\tbaseLength, -baseWidth / 2,\n\t\t\t\t\tradius, -topWidth / 2,\n\t\t\t\t\tradius, topWidth / 2,\n\t\t\t\t\tbaseLength, baseWidth / 2,\n\t\t\t\t\t-rearLength, baseWidth / 2,\n\t\t\t\t\t'z'\n\t\t\t\t],\n\t\t\t\ttranslateX: center[0],\n\t\t\t\ttranslateY: center[1],\n\t\t\t\trotation: rotation\n\t\t\t};\n\t\t\t\n\t\t\t// Positions for data label\n\t\t\tpoint.plotX = center[0];\n\t\t\tpoint.plotY = center[1];\n\t\t});\n\t},\n\t\n\t/**\n\t * Draw the points where each point is one needle\n\t */\n\tdrawPoints: function () {\n\t\t\n\t\tvar series = this,\n\t\t\tcenter = series.yAxis.center,\n\t\t\tpivot = series.pivot,\n\t\t\toptions = series.options,\n\t\t\tpivotOptions = options.pivot,\n\t\t\trenderer = series.chart.renderer;\n\t\t\n\t\teach(series.points, function (point) {\n\t\t\t\n\t\t\tvar graphic = point.graphic,\n\t\t\t\tshapeArgs = point.shapeArgs,\n\t\t\t\td = shapeArgs.d,\n\t\t\t\tdialOptions = merge(options.dial, point.dial); // #1233\n\t\t\t\n\t\t\tif (graphic) {\n\t\t\t\tgraphic.animate(shapeArgs);\n\t\t\t\tshapeArgs.d = d; // animate alters it\n\t\t\t} else {\n\t\t\t\tpoint.graphic = renderer[point.shapeType](shapeArgs)\n\t\t\t\t\t.attr({\n\t\t\t\t\t\tstroke: dialOptions.borderColor || 'none',\n\t\t\t\t\t\t'stroke-width': dialOptions.borderWidth || 0,\n\t\t\t\t\t\tfill: dialOptions.backgroundColor || 'black',\n\t\t\t\t\t\trotation: shapeArgs.rotation // required by VML when animation is false\n\t\t\t\t\t})\n\t\t\t\t\t.add(series.group);\n\t\t\t}\n\t\t});\n\t\t\n\t\t// Add or move the pivot\n\t\tif (pivot) {\n\t\t\tpivot.animate({ // #1235\n\t\t\t\ttranslateX: center[0],\n\t\t\t\ttranslateY: center[1]\n\t\t\t});\n\t\t} else {\n\t\t\tseries.pivot = renderer.circle(0, 0, pick(pivotOptions.radius, 5))\n\t\t\t\t.attr({\n\t\t\t\t\t'stroke-width': pivotOptions.borderWidth || 0,\n\t\t\t\t\tstroke: pivotOptions.borderColor || 'silver',\n\t\t\t\t\tfill: pivotOptions.backgroundColor || 'black'\n\t\t\t\t})\n\t\t\t\t.translate(center[0], center[1])\n\t\t\t\t.add(series.group);\n\t\t}\n\t},\n\t\n\t/**\n\t * Animate the arrow up from startAngle\n\t */\n\tanimate: function (init) {\n\t\tvar series = this;\n\n\t\tif (!init) {\n\t\t\teach(series.points, function (point) {\n\t\t\t\tvar graphic = point.graphic;\n\n\t\t\t\tif (graphic) {\n\t\t\t\t\t// start value\n\t\t\t\t\tgraphic.attr({\n\t\t\t\t\t\trotation: series.yAxis.startAngleRad * 180 / Math.PI\n\t\t\t\t\t});\n\n\t\t\t\t\t// animate\n\t\t\t\t\tgraphic.animate({\n\t\t\t\t\t\trotation: point.shapeArgs.rotation\n\t\t\t\t\t}, series.options.animation);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// delete this function to allow it only once\n\t\t\tseries.animate = null;\n\t\t}\n\t},\n\t\n\trender: function () {\n\t\tthis.group = this.plotGroup(\n\t\t\t'group', \n\t\t\t'series', \n\t\t\tthis.visible ? 'visible' : 'hidden', \n\t\t\tthis.options.zIndex, \n\t\t\tthis.chart.seriesGroup\n\t\t);\n\t\tseriesTypes.pie.prototype.render.call(this);\n\t\tthis.group.clip(this.chart.clipRect);\n\t},\n\t\n\tsetData: seriesTypes.pie.prototype.setData,\n\tdrawTracker: seriesTypes.column.prototype.drawTracker\n};\nseriesTypes.gauge = Highcharts.extendClass(seriesTypes.line, GaugeSeries);/* ****************************************************************************\n * Start Box plot series code\t\t\t\t\t\t\t\t\t\t\t      *\n *****************************************************************************/\n\n// Set default options\ndefaultPlotOptions.boxplot = merge(defaultPlotOptions.column, {\n\tfillColor: '#FFFFFF',\n\tlineWidth: 1,\n\t//medianColor: null,\n\tmedianWidth: 2,\n\tstates: {\n\t\thover: {\n\t\t\tbrightness: -0.3\n\t\t}\n\t},\n\t//stemColor: null,\n\t//stemDashStyle: 'solid'\n\t//stemWidth: null,\n\tthreshold: null,\n\ttooltip: {\n\t\tpointFormat: '<span style=\"color:{series.color};font-weight:bold\">{series.name}</span><br/>' +\n\t\t\t'Maximum: {point.high}<br/>' +\n\t\t\t'Upper quartile: {point.q3}<br/>' +\n\t\t\t'Median: {point.median}<br/>' +\n\t\t\t'Lower quartile: {point.q1}<br/>' +\n\t\t\t'Minimum: {point.low}<br/>'\n\t\t\t\n\t},\n\t//whiskerColor: null,\n\twhiskerLength: '50%',\n\twhiskerWidth: 2\n});\n\n// Create the series object\nseriesTypes.boxplot = extendClass(seriesTypes.column, {\n\ttype: 'boxplot',\n\tpointArrayMap: ['low', 'q1', 'median', 'q3', 'high'], // array point configs are mapped to this\n\ttoYData: function (point) { // return a plain array for speedy calculation\n\t\treturn [point.low, point.q1, point.median, point.q3, point.high];\n\t},\n\tpointValKey: 'high', // defines the top of the tracker\n\t\n\t/**\n\t * One-to-one mapping from options to SVG attributes\n\t */\n\tpointAttrToOptions: { // mapping between SVG attributes and the corresponding options\n\t\tfill: 'fillColor',\n\t\tstroke: 'color',\n\t\t'stroke-width': 'lineWidth'\n\t},\n\t\n\t/**\n\t * Disable data labels for box plot\n\t */\n\tdrawDataLabels: noop,\n\n\t/**\n\t * Translate data points from raw values x and y to plotX and plotY\n\t */\n\ttranslate: function () {\n\t\tvar series = this,\n\t\t\tyAxis = series.yAxis,\n\t\t\tpointArrayMap = series.pointArrayMap;\n\n\t\tseriesTypes.column.prototype.translate.apply(series);\n\n\t\t// do the translation on each point dimension\n\t\teach(series.points, function (point) {\n\t\t\teach(pointArrayMap, function (key) {\n\t\t\t\tif (point[key] !== null) {\n\t\t\t\t\tpoint[key + 'Plot'] = yAxis.translate(point[key], 0, 1, 0, 1);\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t},\n\n\t/**\n\t * Draw the data points\n\t */\n\tdrawPoints: function () {\n\t\tvar series = this,  //state = series.state,\n\t\t\tpoints = series.points,\n\t\t\toptions = series.options,\n\t\t\tchart = series.chart,\n\t\t\trenderer = chart.renderer,\n\t\t\tpointAttr,\n\t\t\tq1Plot,\n\t\t\tq3Plot,\n\t\t\thighPlot,\n\t\t\tlowPlot,\n\t\t\tmedianPlot,\n\t\t\tcrispCorr,\n\t\t\tcrispX,\n\t\t\tgraphic,\n\t\t\tstemPath,\n\t\t\tstemAttr,\n\t\t\tboxPath,\n\t\t\twhiskersPath,\n\t\t\twhiskersAttr,\n\t\t\tmedianPath,\n\t\t\tmedianAttr,\n\t\t\twidth,\n\t\t\tleft,\n\t\t\tright,\n\t\t\thalfWidth,\n\t\t\tshapeArgs,\n\t\t\tcolor,\n\t\t\tdoQuartiles = series.doQuartiles !== false, // error bar inherits this series type but doesn't do quartiles\n\t\t\twhiskerLength = parseInt(series.options.whiskerLength, 10) / 100;\n\n\n\t\teach(points, function (point) {\n\n\t\t\tgraphic = point.graphic;\n\t\t\tshapeArgs = point.shapeArgs; // the box\n\t\t\tstemAttr = {};\n\t\t\twhiskersAttr = {};\n\t\t\tmedianAttr = {};\n\t\t\tcolor = point.color || series.color;\n\t\t\t\n\t\t\tif (point.plotY !== UNDEFINED) {\n\n\t\t\t\tpointAttr = point.pointAttr[point.selected ? 'selected' : ''];\n\n\t\t\t\t// crisp vector coordinates\n\t\t\t\twidth = shapeArgs.width;\n\t\t\t\tleft = mathFloor(shapeArgs.x);\n\t\t\t\tright = left + width;\n\t\t\t\thalfWidth = mathRound(width / 2);\n\t\t\t\t//crispX = mathRound(left + halfWidth) + crispCorr;\n\t\t\t\tq1Plot = mathFloor(doQuartiles ? point.q1Plot : point.lowPlot);// + crispCorr;\n\t\t\t\tq3Plot = mathFloor(doQuartiles ? point.q3Plot : point.lowPlot);// + crispCorr;\n\t\t\t\thighPlot = mathFloor(point.highPlot);// + crispCorr;\n\t\t\t\tlowPlot = mathFloor(point.lowPlot);// + crispCorr;\n\t\t\t\t\n\t\t\t\t// Stem attributes\n\t\t\t\tstemAttr.stroke = point.stemColor || options.stemColor || color;\n\t\t\t\tstemAttr['stroke-width'] = pick(point.stemWidth, options.stemWidth, options.lineWidth);\n\t\t\t\tstemAttr.dashstyle = point.stemDashStyle || options.stemDashStyle;\n\t\t\t\t\n\t\t\t\t// Whiskers attributes\n\t\t\t\twhiskersAttr.stroke = point.whiskerColor || options.whiskerColor || color;\n\t\t\t\twhiskersAttr['stroke-width'] = pick(point.whiskerWidth, options.whiskerWidth, options.lineWidth);\n\t\t\t\t\n\t\t\t\t// Median attributes\n\t\t\t\tmedianAttr.stroke = point.medianColor || options.medianColor || color;\n\t\t\t\tmedianAttr['stroke-width'] = pick(point.medianWidth, options.medianWidth, options.lineWidth);\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t// The stem\n\t\t\t\tcrispCorr = (stemAttr['stroke-width'] % 2) / 2;\n\t\t\t\tcrispX = left + halfWidth + crispCorr;\t\t\t\t\n\t\t\t\tstemPath = [\n\t\t\t\t\t// stem up\n\t\t\t\t\t'M',\n\t\t\t\t\tcrispX, q3Plot,\n\t\t\t\t\t'L',\n\t\t\t\t\tcrispX, highPlot,\n\t\t\t\t\t\n\t\t\t\t\t// stem down\n\t\t\t\t\t'M',\n\t\t\t\t\tcrispX, q1Plot,\n\t\t\t\t\t'L',\n\t\t\t\t\tcrispX, lowPlot,\n\t\t\t\t\t'z'\n\t\t\t\t];\n\t\t\t\t\n\t\t\t\t// The box\n\t\t\t\tif (doQuartiles) {\n\t\t\t\t\tcrispCorr = (pointAttr['stroke-width'] % 2) / 2;\n\t\t\t\t\tcrispX = mathFloor(crispX) + crispCorr;\n\t\t\t\t\tq1Plot = mathFloor(q1Plot) + crispCorr;\n\t\t\t\t\tq3Plot = mathFloor(q3Plot) + crispCorr;\n\t\t\t\t\tleft += crispCorr;\n\t\t\t\t\tright += crispCorr;\n\t\t\t\t\tboxPath = [\n\t\t\t\t\t\t'M',\n\t\t\t\t\t\tleft, q3Plot,\n\t\t\t\t\t\t'L',\n\t\t\t\t\t\tleft, q1Plot,\n\t\t\t\t\t\t'L',\n\t\t\t\t\t\tright, q1Plot,\n\t\t\t\t\t\t'L',\n\t\t\t\t\t\tright, q3Plot,\n\t\t\t\t\t\t'L',\n\t\t\t\t\t\tleft, q3Plot,\n\t\t\t\t\t\t'z'\n\t\t\t\t\t];\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// The whiskers\n\t\t\t\tif (whiskerLength) {\n\t\t\t\t\tcrispCorr = (whiskersAttr['stroke-width'] % 2) / 2;\n\t\t\t\t\thighPlot = highPlot + crispCorr;\n\t\t\t\t\tlowPlot = lowPlot + crispCorr;\n\t\t\t\t\twhiskersPath = [\n\t\t\t\t\t\t// High whisker\n\t\t\t\t\t\t'M',\n\t\t\t\t\t\tcrispX - halfWidth * whiskerLength, \n\t\t\t\t\t\thighPlot,\n\t\t\t\t\t\t'L',\n\t\t\t\t\t\tcrispX + halfWidth * whiskerLength, \n\t\t\t\t\t\thighPlot,\n\t\t\t\t\t\t\n\t\t\t\t\t\t// Low whisker\n\t\t\t\t\t\t'M',\n\t\t\t\t\t\tcrispX - halfWidth * whiskerLength, \n\t\t\t\t\t\tlowPlot,\n\t\t\t\t\t\t'L',\n\t\t\t\t\t\tcrispX + halfWidth * whiskerLength, \n\t\t\t\t\t\tlowPlot\n\t\t\t\t\t];\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// The median\n\t\t\t\tcrispCorr = (medianAttr['stroke-width'] % 2) / 2;\t\t\t\t\n\t\t\t\tmedianPlot = mathRound(point.medianPlot) + crispCorr;\n\t\t\t\tmedianPath = [\n\t\t\t\t\t'M',\n\t\t\t\t\tleft, \n\t\t\t\t\tmedianPlot,\n\t\t\t\t\t'L',\n\t\t\t\t\tright, \n\t\t\t\t\tmedianPlot,\n\t\t\t\t\t'z'\n\t\t\t\t];\n\t\t\t\t\n\t\t\t\t// Create or update the graphics\n\t\t\t\tif (graphic) { // update\n\t\t\t\t\t\n\t\t\t\t\tpoint.stem.animate({ d: stemPath });\n\t\t\t\t\tif (whiskerLength) {\n\t\t\t\t\t\tpoint.whiskers.animate({ d: whiskersPath });\n\t\t\t\t\t}\n\t\t\t\t\tif (doQuartiles) {\n\t\t\t\t\t\tpoint.box.animate({ d: boxPath });\n\t\t\t\t\t}\n\t\t\t\t\tpoint.medianShape.animate({ d: medianPath });\n\t\t\t\t\t\n\t\t\t\t} else { // create new\n\t\t\t\t\tpoint.graphic = graphic = renderer.g()\n\t\t\t\t\t\t.add(series.group);\n\t\t\t\t\t\n\t\t\t\t\tpoint.stem = renderer.path(stemPath)\n\t\t\t\t\t\t.attr(stemAttr)\n\t\t\t\t\t\t.add(graphic);\n\t\t\t\t\t\t\n\t\t\t\t\tif (whiskerLength) {\n\t\t\t\t\t\tpoint.whiskers = renderer.path(whiskersPath) \n\t\t\t\t\t\t\t.attr(whiskersAttr)\n\t\t\t\t\t\t\t.add(graphic);\n\t\t\t\t\t}\n\t\t\t\t\tif (doQuartiles) {\n\t\t\t\t\t\tpoint.box = renderer.path(boxPath)\n\t\t\t\t\t\t\t.attr(pointAttr)\n\t\t\t\t\t\t\t.add(graphic);\n\t\t\t\t\t}\t\n\t\t\t\t\tpoint.medianShape = renderer.path(medianPath)\n\t\t\t\t\t\t.attr(medianAttr)\n\t\t\t\t\t\t.add(graphic);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t}\n\n\n});\n\n/* ****************************************************************************\n * End Box plot series code\t\t\t\t\t\t\t\t\t\t\t\t*\n *****************************************************************************/\n/* ****************************************************************************\n * Start error bar series code                                                *\n *****************************************************************************/\n\n// 1 - set default options\ndefaultPlotOptions.errorbar = merge(defaultPlotOptions.boxplot, {\n\tcolor: '#000000',\n\tgrouping: false,\n\tlinkedTo: ':previous',\n\ttooltip: {\n\t\tpointFormat: defaultPlotOptions.arearange.tooltip.pointFormat\n\t},\n\twhiskerWidth: null\n});\n\n// 2 - Create the series object\nseriesTypes.errorbar = extendClass(seriesTypes.boxplot, {\n\ttype: 'errorbar',\n\tpointArrayMap: ['low', 'high'], // array point configs are mapped to this\n\ttoYData: function (point) { // return a plain array for speedy calculation\n\t\treturn [point.low, point.high];\n\t},\n\tpointValKey: 'high', // defines the top of the tracker\n\tdoQuartiles: false,\n\n\t/**\n\t * Get the width and X offset, either on top of the linked series column\n\t * or standalone\n\t */\n\tgetColumnMetrics: function () {\n\t\treturn (this.linkedParent && this.linkedParent.columnMetrics) || \n\t\t\tseriesTypes.column.prototype.getColumnMetrics.call(this);\n\t}\n});\n\n/* ****************************************************************************\n * End error bar series code                                                  *\n *****************************************************************************/\n/* ****************************************************************************\n * Start Waterfall series code                                                *\n *****************************************************************************/\n\n// 1 - set default options\ndefaultPlotOptions.waterfall = merge(defaultPlotOptions.column, {\n\tlineWidth: 1,\n\tlineColor: '#333',\n\tdashStyle: 'dot',\n\tborderColor: '#333'\n});\n\n\n// 2 - Create the series object\nseriesTypes.waterfall = extendClass(seriesTypes.column, {\n\ttype: 'waterfall',\n\n\tupColorProp: 'fill',\n\n\tpointArrayMap: ['low', 'y'],\n\n\tpointValKey: 'y',\n\n\t/**\n\t * Init waterfall series, force stacking\n\t */\n\tinit: function (chart, options) {\n\t\t// force stacking\n\t\toptions.stacking = true;\n\n\t\tseriesTypes.column.prototype.init.call(this, chart, options);\n\t},\n\n\n\t/**\n\t * Translate data points from raw values\n\t */\n\ttranslate: function () {\n\t\tvar series = this,\n\t\t\toptions = series.options,\n\t\t\taxis = series.yAxis,\n\t\t\tlen,\n\t\t\ti,\n\t\t\tpoints,\n\t\t\tpoint,\n\t\t\tshapeArgs,\n\t\t\tstack,\n\t\t\ty,\n\t\t\tpreviousY,\n\t\t\tstackPoint,\n\t\t\tthreshold = options.threshold,\n\t\t\tcrispCorr = (options.borderWidth % 2) / 2;\n\n\t\t// run column series translate\n\t\tseriesTypes.column.prototype.translate.apply(this);\n\n\t\tpreviousY = threshold;\n\t\tpoints = series.points;\n\n\t\tfor (i = 0, len = points.length; i < len; i++) {\n\t\t\t// cache current point object\n\t\t\tpoint = points[i];\n\t\t\tshapeArgs = point.shapeArgs;\n\n\t\t\t// get current stack\n\t\t\tstack = series.getStack(i);\n\t\t\tstackPoint = stack.points[series.index];\n\n\t\t\t// override point value for sums\n\t\t\tif (isNaN(point.y)) {\n\t\t\t\tpoint.y = series.yData[i];\n\t\t\t}\n\n\t\t\t// up points\n\t\t\ty = mathMax(previousY, previousY + point.y) + stackPoint[0];\n\t\t\tshapeArgs.y = axis.translate(y, 0, 1);\n\n\n\t\t\t// sum points\n\t\t\tif (point.isSum || point.isIntermediateSum) {\n\t\t\t\tshapeArgs.y = axis.translate(stackPoint[1], 0, 1);\n\t\t\t\tshapeArgs.height = axis.translate(stackPoint[0], 0, 1) - shapeArgs.y;\n\n\t\t\t// if it's not the sum point, update previous stack end position\n\t\t\t} else {\n\t\t\t\tpreviousY += stack.total;\n\t\t\t}\n\n\t\t\t// negative points\n\t\t\tif (shapeArgs.height < 0) {\n\t\t\t\tshapeArgs.y += shapeArgs.height;\n\t\t\t\tshapeArgs.height *= -1;\n\t\t\t}\n\n\t\t\tpoint.plotY = shapeArgs.y = mathRound(shapeArgs.y) - crispCorr;\n\t\t\tshapeArgs.height = mathRound(shapeArgs.height);\n\t\t\tpoint.yBottom = shapeArgs.y + shapeArgs.height;\n\t\t}\n\t},\n\n\t/**\n\t * Call default processData then override yData to reflect waterfall's extremes on yAxis\n\t */\n\tprocessData: function (force) {\n\t\tvar series = this,\n\t\t\toptions = series.options,\n\t\t\tyData = series.yData,\n\t\t\tpoints = series.points,\n\t\t\tpoint,\n\t\t\tdataLength = yData.length,\n\t\t\tthreshold = options.threshold || 0,\n\t\t\tsubSum,\n\t\t\tsum,\n\t\t\tdataMin,\n\t\t\tdataMax,\n\t\t\ty,\n\t\t\ti;\n\n\t\tsum = subSum = dataMin = dataMax = threshold;\n\n\t\tfor (i = 0; i < dataLength; i++) {\n\t\t\ty = yData[i];\n\t\t\tpoint = points ? points[i] : {};\n\n\t\t\tif (y === \"sum\" || point.isSum) {\n\t\t\t\tyData[i] = sum;\n\t\t\t} else if (y === \"intermediateSum\" || point.isIntermediateSum) {\n\t\t\t\tyData[i] = subSum;\n\t\t\t\tsubSum = threshold;\n\t\t\t} else {\n\t\t\t\tsum += y;\n\t\t\t\tsubSum += y;\n\t\t\t}\n\t\t\tdataMin = Math.min(sum, dataMin);\n\t\t\tdataMax = Math.max(sum, dataMax);\n\t\t}\n\n\t\tSeries.prototype.processData.call(this, force);\n\n\t\t// Record extremes\n\t\tseries.dataMin = dataMin;\n\t\tseries.dataMax = dataMax;\n\t},\n\n\t/**\n\t * Return y value or string if point is sum\n\t */\n\ttoYData: function (pt) {\n\t\tif (pt.isSum) {\n\t\t\treturn \"sum\";\n\t\t} else if (pt.isIntermediateSum) {\n\t\t\treturn \"intermediateSum\";\n\t\t}\n\n\t\treturn pt.y;\n\t},\n\n\t/**\n\t * Postprocess mapping between options and SVG attributes\n\t */\n\tgetAttribs: function () {\n\t\tseriesTypes.column.prototype.getAttribs.apply(this, arguments);\n\n\t\tvar series = this,\n\t\t\toptions = series.options,\n\t\t\tstateOptions = options.states,\n\t\t\tupColor = options.upColor || series.color,\n\t\t\thoverColor = Highcharts.Color(upColor).brighten(0.1).get(),\n\t\t\tseriesDownPointAttr = merge(series.pointAttr),\n\t\t\tupColorProp = series.upColorProp;\n\n\t\tseriesDownPointAttr[''][upColorProp] = upColor;\n\t\tseriesDownPointAttr.hover[upColorProp] = stateOptions.hover.upColor || hoverColor;\n\t\tseriesDownPointAttr.select[upColorProp] = stateOptions.select.upColor || upColor;\n\n\t\teach(series.points, function (point) {\n\t\t\tif (point.y > 0 && !point.color) {\n\t\t\t\tpoint.pointAttr = seriesDownPointAttr;\n\t\t\t\tpoint.color = upColor;\n\t\t\t}\n\t\t});\n\t},\n\n\t/**\n\t * Draw columns' connector lines\n\t */\n\tgetGraphPath: function () {\n\n\t\tvar data = this.data,\n\t\t\tlength = data.length,\n\t\t\tlineWidth = this.options.lineWidth + this.options.borderWidth,\n\t\t\tnormalizer = mathRound(lineWidth) % 2 / 2,\n\t\t\tpath = [],\n\t\t\tM = 'M',\n\t\t\tL = 'L',\n\t\t\tprevArgs,\n\t\t\tpointArgs,\n\t\t\ti,\n\t\t\td;\n\n\t\tfor (i = 1; i < length; i++) {\n\t\t\tpointArgs = data[i].shapeArgs;\n\t\t\tprevArgs = data[i - 1].shapeArgs;\n\n\t\t\td = [\n\t\t\t\tM,\n\t\t\t\tprevArgs.x + prevArgs.width, prevArgs.y + normalizer,\n\t\t\t\tL,\n\t\t\t\tpointArgs.x, prevArgs.y + normalizer\n\t\t\t];\n\n\t\t\tif (data[i - 1].y < 0) {\n\t\t\t\td[2] += prevArgs.height;\n\t\t\t\td[5] += prevArgs.height;\n\t\t\t}\n\n\t\t\tpath = path.concat(d);\n\t\t}\n\n\t\treturn path;\n\t},\n\n\t/**\n\t * Extremes are recorded in processData\n\t */\n\tgetExtremes: noop,\n\n\t/**\n\t * Return stack for given index\n\t */\n\tgetStack: function (i) {\n\t\tvar axis = this.yAxis,\n\t\t\tstacks = axis.stacks,\n\t\t\tkey = this.stackKey;\n\n\t\tif (this.processedYData[i] < this.options.threshold) {\n\t\t\tkey = '-' + key;\n\t\t}\n\n\t\treturn stacks[key][i];\n\t},\n\n\tdrawGraph: Series.prototype.drawGraph\n});\n\n/* ****************************************************************************\n * End Waterfall series code                                                  *\n *****************************************************************************/\n/* ****************************************************************************\n * Start Bubble series code\t\t\t\t\t\t\t\t\t\t\t          *\n *****************************************************************************/\n\n// 1 - set default options\ndefaultPlotOptions.bubble = merge(defaultPlotOptions.scatter, {\n\tdataLabels: {\n\t\tinside: true,\n\t\tstyle: {\n\t\t\tcolor: 'white',\n\t\t\ttextShadow: '0px 0px 3px black'\n\t\t},\n\t\tverticalAlign: 'middle'\n\t},\n\t// displayNegative: true,\n\tmarker: {\n\t\t// fillOpacity: 0.5,\n\t\tlineColor: null, // inherit from series.color\n\t\tlineWidth: 1\n\t},\n\tminSize: 8,\n\tmaxSize: '20%',\n\t// negativeColor: null,\n\ttooltip: {\n\t\tpointFormat: '({point.x}, {point.y}), Size: {point.z}'\n\t},\n\tturboThreshold: 0, // docs: exclude from bubbles\n\tzThreshold: 0\n});\n\n// 2 - Create the series object\nseriesTypes.bubble = extendClass(seriesTypes.scatter, {\n\ttype: 'bubble',\n\tpointArrayMap: ['y', 'z'],\n\ttrackerGroups: ['group', 'dataLabelsGroup'],\n\t\n\t/**\n\t * Mapping between SVG attributes and the corresponding options\n\t */\n\tpointAttrToOptions: { \n\t\tstroke: 'lineColor',\n\t\t'stroke-width': 'lineWidth',\n\t\tfill: 'fillColor'\n\t},\n\t\n\t/**\n\t * Apply the fillOpacity to all fill positions\n\t */\n\tapplyOpacity: function (fill) {\n\t\tvar markerOptions = this.options.marker,\n\t\t\tfillOpacity = pick(markerOptions.fillOpacity, 0.5);\n\t\t\n\t\t// When called from Legend.colorizeItem, the fill isn't predefined\n\t\tfill = fill || markerOptions.fillColor || this.color; \n\t\t\n\t\tif (fillOpacity !== 1) {\n\t\t\tfill = Highcharts.Color(fill).setOpacity(fillOpacity).get('rgba');\n\t\t}\n\t\treturn fill;\n\t},\n\t\n\t/**\n\t * Extend the convertAttribs method by applying opacity to the fill\n\t */\n\tconvertAttribs: function () {\n\t\tvar obj = Series.prototype.convertAttribs.apply(this, arguments);\n\t\t\n\t\tobj.fill = this.applyOpacity(obj.fill);\n\t\t\n\t\treturn obj;\n\t},\n\n\t/**\n\t * Get the radius for each point based on the minSize, maxSize and each point's Z value. This\n\t * must be done prior to Series.translate because the axis needs to add padding in \n\t * accordance with the point sizes.\n\t */\n\tgetRadii: function (zMin, zMax, minSize, maxSize) {\n\t\tvar len,\n\t\t\ti,\n\t\t\tpos,\n\t\t\tzData = this.zData,\n\t\t\tradii = [],\n\t\t\tzRange;\n\t\t\n\t\t// Set the shape type and arguments to be picked up in drawPoints\n\t\tfor (i = 0, len = zData.length; i < len; i++) {\n\t\t\tzRange = zMax - zMin;\n\t\t\tpos = zRange > 0 ? // relative size, a number between 0 and 1\n\t\t\t\t(zData[i] - zMin) / (zMax - zMin) : \n\t\t\t\t0.5;\n\t\t\tradii.push(math.ceil(minSize + pos * (maxSize - minSize)) / 2);\n\t\t}\n\t\tthis.radii = radii;\n\t},\n\t\n\t/**\n\t * Perform animation on the bubbles\n\t */\n\tanimate: function (init) {\n\t\tvar animation = this.options.animation;\n\t\t\n\t\tif (!init) { // run the animation\n\t\t\teach(this.points, function (point) {\n\t\t\t\tvar graphic = point.graphic,\n\t\t\t\t\tshapeArgs = point.shapeArgs;\n\n\t\t\t\tif (graphic && shapeArgs) {\n\t\t\t\t\t// start values\n\t\t\t\t\tgraphic.attr('r', 1);\n\n\t\t\t\t\t// animate\n\t\t\t\t\tgraphic.animate({\n\t\t\t\t\t\tr: shapeArgs.r\n\t\t\t\t\t}, animation);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// delete this function to allow it only once\n\t\t\tthis.animate = null;\n\t\t}\n\t},\n\t\n\t/**\n\t * Extend the base translate method to handle bubble size\n\t */\n\ttranslate: function () {\n\t\t\n\t\tvar i,\n\t\t\tdata = this.data,\n\t\t\tpoint,\n\t\t\tradius,\n\t\t\tradii = this.radii;\n\t\t\n\t\t// Run the parent method\n\t\tseriesTypes.scatter.prototype.translate.call(this);\n\t\t\n\t\t// Set the shape type and arguments to be picked up in drawPoints\n\t\ti = data.length;\n\t\t\n\t\twhile (i--) {\n\t\t\tpoint = data[i];\n\t\t\tradius = radii ? radii[i] : 0; // #1737\n\n\t\t\t// Flag for negativeColor to be applied in Series.js\n\t\t\tpoint.negative = point.z < (this.options.zThreshold || 0);\n\t\t\t\n\t\t\tif (radius >= this.minPxSize / 2) {\n\t\t\t\t// Shape arguments\n\t\t\t\tpoint.shapeType = 'circle';\n\t\t\t\tpoint.shapeArgs = {\n\t\t\t\t\tx: point.plotX,\n\t\t\t\t\ty: point.plotY,\n\t\t\t\t\tr: radius\n\t\t\t\t};\n\t\t\t\t\n\t\t\t\t// Alignment box for the data label\n\t\t\t\tpoint.dlBox = {\n\t\t\t\t\tx: point.plotX - radius,\n\t\t\t\t\ty: point.plotY - radius,\n\t\t\t\t\twidth: 2 * radius,\n\t\t\t\t\theight: 2 * radius\n\t\t\t\t};\n\t\t\t} else { // below zThreshold\n\t\t\t\tpoint.shapeArgs = point.plotY = point.dlBox = UNDEFINED; // #1691\n\t\t\t}\n\t\t}\n\t},\n\t\n\t/**\n\t * Get the series' symbol in the legend\n\t * \n\t * @param {Object} legend The legend object\n\t * @param {Object} item The series (this) or point\n\t */\n\tdrawLegendSymbol: function (legend, item) {\n\t\tvar radius = pInt(legend.itemStyle.fontSize) / 2;\n\t\t\n\t\titem.legendSymbol = this.chart.renderer.circle(\n\t\t\tradius,\n\t\t\tlegend.baseline - radius,\n\t\t\tradius\n\t\t).attr({\n\t\t\tzIndex: 3\n\t\t}).add(item.legendGroup);\n\t\titem.legendSymbol.isMarker = true;\t\n\t\t\n\t},\n\t\n\tdrawPoints: seriesTypes.column.prototype.drawPoints,\n\talignDataLabel: seriesTypes.column.prototype.alignDataLabel\n});\n\n/**\n * Add logic to pad each axis with the amount of pixels\n * necessary to avoid the bubbles to overflow.\n */\nAxis.prototype.beforePadding = function () {\n\tvar axis = this,\n\t\taxisLength = this.len,\n\t\tchart = this.chart,\n\t\tpxMin = 0, \n\t\tpxMax = axisLength,\n\t\tisXAxis = this.isXAxis,\n\t\tdataKey = isXAxis ? 'xData' : 'yData',\n\t\tmin = this.min,\n\t\textremes = {},\n\t\tsmallestSize = math.min(chart.plotWidth, chart.plotHeight),\n\t\tzMin = Number.MAX_VALUE,\n\t\tzMax = -Number.MAX_VALUE,\n\t\trange = this.max - min,\n\t\ttransA = axisLength / range,\n\t\tactiveSeries = [];\n\n\t// Handle padding on the second pass, or on redraw\n\tif (this.tickPositions) {\n\t\teach(this.series, function (series) {\n\n\t\t\tvar seriesOptions = series.options,\n\t\t\t\tzData;\n\n\t\t\tif (series.type === 'bubble' && series.visible) {\n\n\t\t\t\t// Correction for #1673\n\t\t\t\taxis.allowZoomOutside = true;\n\n\t\t\t\t// Cache it\n\t\t\t\tactiveSeries.push(series);\n\n\t\t\t\tif (isXAxis) { // because X axis is evaluated first\n\t\t\t\t\n\t\t\t\t\t// For each series, translate the size extremes to pixel values\n\t\t\t\t\teach(['minSize', 'maxSize'], function (prop) {\n\t\t\t\t\t\tvar length = seriesOptions[prop],\n\t\t\t\t\t\t\tisPercent = /%$/.test(length);\n\t\t\t\t\t\t\n\t\t\t\t\t\tlength = pInt(length);\n\t\t\t\t\t\textremes[prop] = isPercent ?\n\t\t\t\t\t\t\tsmallestSize * length / 100 :\n\t\t\t\t\t\t\tlength;\n\t\t\t\t\t\t\n\t\t\t\t\t});\n\t\t\t\t\tseries.minPxSize = extremes.minSize;\n\t\t\t\t\t\n\t\t\t\t\t// Find the min and max Z\n\t\t\t\t\tzData = series.zData;\n\t\t\t\t\tif (zData.length) { // #1735\n\t\t\t\t\t\tzMin = math.min(\n\t\t\t\t\t\t\tzMin,\n\t\t\t\t\t\t\tmath.max(\n\t\t\t\t\t\t\t\tarrayMin(zData), \n\t\t\t\t\t\t\t\tseriesOptions.displayNegative === false ? seriesOptions.zThreshold : -Number.MAX_VALUE\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t);\n\t\t\t\t\t\tzMax = math.max(zMax, arrayMax(zData));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\teach(activeSeries, function (series) {\n\n\t\t\tvar data = series[dataKey],\n\t\t\t\ti = data.length,\n\t\t\t\tradius;\n\n\t\t\tif (isXAxis) {\n\t\t\t\tseries.getRadii(zMin, zMax, extremes.minSize, extremes.maxSize);\n\t\t\t}\n\t\t\t\n\t\t\tif (range > 0) {\n\t\t\t\twhile (i--) {\n\t\t\t\t\tradius = series.radii[i];\n\t\t\t\t\tpxMin = Math.min(((data[i] - min) * transA) - radius, pxMin);\n\t\t\t\t\tpxMax = Math.max(((data[i] - min) * transA) + radius, pxMax);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\t\n\t\tif (range > 0 && pick(this.options.min, this.userMin) === UNDEFINED && pick(this.options.max, this.userMax) === UNDEFINED) {\n\t\t\tpxMax -= axisLength;\n\t\t\ttransA *= (axisLength + pxMin - pxMax) / axisLength;\n\t\t\tthis.min += pxMin / transA;\n\t\t\tthis.max += pxMax / transA;\n\t\t}\n\t}\n};\n\n/* ****************************************************************************\n * End Bubble series code                                                     *\n *****************************************************************************/\n/**\n * Extensions for polar charts. Additionally, much of the geometry required for polar charts is\n * gathered in RadialAxes.js.\n * \n */\n\nvar seriesProto = Series.prototype,\n\tpointerProto = Highcharts.Pointer.prototype;\n\n\n\n/**\n * Translate a point's plotX and plotY from the internal angle and radius measures to \n * true plotX, plotY coordinates\n */\nseriesProto.toXY = function (point) {\n\tvar xy,\n\t\tchart = this.chart,\n\t\tplotX = point.plotX,\n\t\tplotY = point.plotY;\n\t\n\t// Save rectangular plotX, plotY for later computation\n\tpoint.rectPlotX = plotX;\n\tpoint.rectPlotY = plotY;\n\t\n\t// Record the angle in degrees for use in tooltip\n\tpoint.clientX = ((plotX / Math.PI * 180) + this.xAxis.pane.options.startAngle) % 360;\n\t\n\t// Find the polar plotX and plotY\n\txy = this.xAxis.postTranslate(point.plotX, this.yAxis.len - plotY);\n\tpoint.plotX = point.polarPlotX = xy.x - chart.plotLeft;\n\tpoint.plotY = point.polarPlotY = xy.y - chart.plotTop;\n};\n\n/** \n * Order the tooltip points to get the mouse capture ranges correct. #1915. \n */\nseriesProto.orderTooltipPoints = function (points) {\n\tif (this.chart.polar) {\n\t\tpoints.sort(function (a, b) {\n\t\t\treturn a.clientX - b.clientX;\n\t\t});\n\n\t\t// Wrap mouse tracking around to capture movement on the segment to the left\n\t\t// of the north point (#1469).\n\t\tpoints[0].wrappedClientX = points[0].clientX + 360;\n\t\tpoints.push(points[0]);\n\t}\n};\n\n\n/**\n * Add some special init logic to areas and areasplines\n */\nfunction initArea(proceed, chart, options) {\n\tproceed.call(this, chart, options);\n\tif (this.chart.polar) {\n\t\t\n\t\t/**\n\t\t * Overridden method to close a segment path. While in a cartesian plane the area \n\t\t * goes down to the threshold, in the polar chart it goes to the center.\n\t\t */\n\t\tthis.closeSegment = function (path) {\n\t\t\tvar center = this.xAxis.center;\n\t\t\tpath.push(\n\t\t\t\t'L',\n\t\t\t\tcenter[0],\n\t\t\t\tcenter[1]\n\t\t\t);\t\t\t\n\t\t};\n\t\t\n\t\t// Instead of complicated logic to draw an area around the inner area in a stack,\n\t\t// just draw it behind\n\t\tthis.closedStacks = true;\n\t}\n}\nwrap(seriesTypes.area.prototype, 'init', initArea);\nwrap(seriesTypes.areaspline.prototype, 'init', initArea);\n\t\t\n\n/**\n * Overridden method for calculating a spline from one point to the next\n */\nwrap(seriesTypes.spline.prototype, 'getPointSpline', function (proceed, segment, point, i) {\n\t\n\tvar ret,\n\t\tsmoothing = 1.5, // 1 means control points midway between points, 2 means 1/3 from the point, 3 is 1/4 etc;\n\t\tdenom = smoothing + 1,\n\t\tplotX, \n\t\tplotY,\n\t\tlastPoint,\n\t\tnextPoint,\n\t\tlastX,\n\t\tlastY,\n\t\tnextX,\n\t\tnextY,\n\t\tleftContX,\n\t\tleftContY,\n\t\trightContX,\n\t\trightContY,\n\t\tdistanceLeftControlPoint,\n\t\tdistanceRightControlPoint,\n\t\tleftContAngle,\n\t\trightContAngle,\n\t\tjointAngle;\n\t\t\n\t\t\n\tif (this.chart.polar) {\n\t\t\n\t\tplotX = point.plotX;\n\t\tplotY = point.plotY;\n\t\tlastPoint = segment[i - 1];\n\t\tnextPoint = segment[i + 1];\n\t\t\t\n\t\t// Connect ends\n\t\tif (this.connectEnds) {\n\t\t\tif (!lastPoint) {\n\t\t\t\tlastPoint = segment[segment.length - 2]; // not the last but the second last, because the segment is already connected\n\t\t\t}\n\t\t\tif (!nextPoint) {\n\t\t\t\tnextPoint = segment[1];\n\t\t\t}\t\n\t\t}\n\n\t\t// find control points\n\t\tif (lastPoint && nextPoint) {\n\t\t\n\t\t\tlastX = lastPoint.plotX;\n\t\t\tlastY = lastPoint.plotY;\n\t\t\tnextX = nextPoint.plotX;\n\t\t\tnextY = nextPoint.plotY;\n\t\t\tleftContX = (smoothing * plotX + lastX) / denom;\n\t\t\tleftContY = (smoothing * plotY + lastY) / denom;\n\t\t\trightContX = (smoothing * plotX + nextX) / denom;\n\t\t\trightContY = (smoothing * plotY + nextY) / denom;\n\t\t\tdistanceLeftControlPoint = Math.sqrt(Math.pow(leftContX - plotX, 2) + Math.pow(leftContY - plotY, 2));\n\t\t\tdistanceRightControlPoint = Math.sqrt(Math.pow(rightContX - plotX, 2) + Math.pow(rightContY - plotY, 2));\n\t\t\tleftContAngle = Math.atan2(leftContY - plotY, leftContX - plotX);\n\t\t\trightContAngle = Math.atan2(rightContY - plotY, rightContX - plotX);\n\t\t\tjointAngle = (Math.PI / 2) + ((leftContAngle + rightContAngle) / 2);\n\t\t\t\t\n\t\t\t\t\n\t\t\t// Ensure the right direction, jointAngle should be in the same quadrant as leftContAngle\n\t\t\tif (Math.abs(leftContAngle - jointAngle) > Math.PI / 2) {\n\t\t\t\tjointAngle -= Math.PI;\n\t\t\t}\n\t\t\t\n\t\t\t// Find the corrected control points for a spline straight through the point\n\t\t\tleftContX = plotX + Math.cos(jointAngle) * distanceLeftControlPoint;\n\t\t\tleftContY = plotY + Math.sin(jointAngle) * distanceLeftControlPoint;\n\t\t\trightContX = plotX + Math.cos(Math.PI + jointAngle) * distanceRightControlPoint;\n\t\t\trightContY = plotY + Math.sin(Math.PI + jointAngle) * distanceRightControlPoint;\n\t\t\t\n\t\t\t// Record for drawing in next point\n\t\t\tpoint.rightContX = rightContX;\n\t\t\tpoint.rightContY = rightContY;\n\n\t\t}\n\t\t\n\t\t\n\t\t// moveTo or lineTo\n\t\tif (!i) {\n\t\t\tret = ['M', plotX, plotY];\n\t\t} else { // curve from last point to this\n\t\t\tret = [\n\t\t\t\t'C',\n\t\t\t\tlastPoint.rightContX || lastPoint.plotX,\n\t\t\t\tlastPoint.rightContY || lastPoint.plotY,\n\t\t\t\tleftContX || plotX,\n\t\t\t\tleftContY || plotY,\n\t\t\t\tplotX,\n\t\t\t\tplotY\n\t\t\t];\n\t\t\tlastPoint.rightContX = lastPoint.rightContY = null; // reset for updating series later\n\t\t}\n\t\t\n\t\t\n\t} else {\n\t\tret = proceed.call(this, segment, point, i);\n\t}\n\treturn ret;\n});\n\n/**\n * Extend translate. The plotX and plotY values are computed as if the polar chart were a\n * cartesian plane, where plotX denotes the angle in radians and (yAxis.len - plotY) is the pixel distance from\n * center. \n */\nwrap(seriesProto, 'translate', function (proceed) {\n\t\t\n\t// Run uber method\n\tproceed.call(this);\n\t\n\t// Postprocess plot coordinates\n\tif (this.chart.polar && !this.preventPostTranslate) {\n\t\tvar points = this.points,\n\t\t\ti = points.length;\n\t\twhile (i--) {\n\t\t\t// Translate plotX, plotY from angle and radius to true plot coordinates\n\t\t\tthis.toXY(points[i]);\n\t\t}\n\t}\n});\n\n/** \n * Extend getSegmentPath to allow connecting ends across 0 to provide a closed circle in \n * line-like series.\n */\nwrap(seriesProto, 'getSegmentPath', function (proceed, segment) {\n\t\t\n\tvar points = this.points;\n\t\n\t// Connect the path\n\tif (this.chart.polar && this.options.connectEnds !== false && \n\t\t\tsegment[segment.length - 1] === points[points.length - 1] && points[0].y !== null) {\n\t\tthis.connectEnds = true; // re-used in splines\n\t\tsegment = [].concat(segment, [points[0]]);\n\t}\n\t\n\t// Run uber method\n\treturn proceed.call(this, segment);\n\t\n});\n\n\nfunction polarAnimate(proceed, init) {\n\tvar chart = this.chart,\n\t\tanimation = this.options.animation,\n\t\tgroup = this.group,\n\t\tmarkerGroup = this.markerGroup,\n\t\tcenter = this.xAxis.center,\n\t\tplotLeft = chart.plotLeft,\n\t\tplotTop = chart.plotTop,\n\t\tattribs;\n\n\t// Specific animation for polar charts\n\tif (chart.polar) {\n\t\t\n\t\t// Enable animation on polar charts only in SVG. In VML, the scaling is different, plus animation\n\t\t// would be so slow it would't matter.\n\t\tif (chart.renderer.isSVG) {\n\n\t\t\tif (animation === true) {\n\t\t\t\tanimation = {};\n\t\t\t}\n\t\n\t\t\t// Initialize the animation\n\t\t\tif (init) {\n\t\t\t\t\n\t\t\t\t// Scale down the group and place it in the center\n\t\t\t\tattribs = {\n\t\t\t\t\ttranslateX: center[0] + plotLeft,\n\t\t\t\t\ttranslateY: center[1] + plotTop,\n\t\t\t\t\tscaleX: 0.001, // #1499\n\t\t\t\t\tscaleY: 0.001\n\t\t\t\t};\n\t\t\t\t\t\n\t\t\t\tgroup.attr(attribs);\n\t\t\t\tif (markerGroup) {\n\t\t\t\t\tmarkerGroup.attrSetters = group.attrSetters;\n\t\t\t\t\tmarkerGroup.attr(attribs);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t// Run the animation\n\t\t\t} else {\n\t\t\t\tattribs = {\n\t\t\t\t\ttranslateX: plotLeft,\n\t\t\t\t\ttranslateY: plotTop,\n\t\t\t\t\tscaleX: 1,\n\t\t\t\t\tscaleY: 1\n\t\t\t\t};\n\t\t\t\tgroup.animate(attribs, animation);\n\t\t\t\tif (markerGroup) {\n\t\t\t\t\tmarkerGroup.animate(attribs, animation);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// Delete this function to allow it only once\n\t\t\t\tthis.animate = null;\n\t\t\t}\n\t\t}\n\t\n\t// For non-polar charts, revert to the basic animation\n\t} else {\n\t\tproceed.call(this, init);\n\t} \n}\n\n// Define the animate method for both regular series and column series and their derivatives\nwrap(seriesProto, 'animate', polarAnimate);\nwrap(colProto, 'animate', polarAnimate);\n\n\n/**\n * Throw in a couple of properties to let setTooltipPoints know we're indexing the points\n * in degrees (0-360), not plot pixel width.\n */\nwrap(seriesProto, 'setTooltipPoints', function (proceed, renew) {\n\t\t\n\tif (this.chart.polar) {\n\t\textend(this.xAxis, {\n\t\t\ttooltipLen: 360 // degrees are the resolution unit of the tooltipPoints array\n\t\t});\t\n\t}\n\t\n\t// Run uber method\n\treturn proceed.call(this, renew);\n});\n\n\n/**\n * Extend the column prototype's translate method\n */\nwrap(colProto, 'translate', function (proceed) {\n\t\t\n\tvar xAxis = this.xAxis,\n\t\tlen = this.yAxis.len,\n\t\tcenter = xAxis.center,\n\t\tstartAngleRad = xAxis.startAngleRad,\n\t\trenderer = this.chart.renderer,\n\t\tstart,\n\t\tpoints,\n\t\tpoint,\n\t\ti;\n\t\n\tthis.preventPostTranslate = true;\n\t\n\t// Run uber method\n\tproceed.call(this);\n\t\n\t// Postprocess plot coordinates\n\tif (xAxis.isRadial) {\n\t\tpoints = this.points;\n\t\ti = points.length;\n\t\twhile (i--) {\n\t\t\tpoint = points[i];\n\t\t\tstart = point.barX + startAngleRad;\n\t\t\tpoint.shapeType = 'path';\n\t\t\tpoint.shapeArgs = {\n\t\t\t\td: renderer.symbols.arc(\n\t\t\t\t\tcenter[0],\n\t\t\t\t\tcenter[1],\n\t\t\t\t\tlen - point.plotY,\n\t\t\t\t\tnull, \n\t\t\t\t\t{\n\t\t\t\t\t\tstart: start,\n\t\t\t\t\t\tend: start + point.pointWidth,\n\t\t\t\t\t\tinnerR: len - pick(point.yBottom, len)\n\t\t\t\t\t}\n\t\t\t\t)\n\t\t\t};\n\t\t\tthis.toXY(point); // provide correct plotX, plotY for tooltip\n\t\t}\n\t}\n});\n\n\n/**\n * Align column data labels outside the columns. #1199.\n */\nwrap(colProto, 'alignDataLabel', function (proceed, point, dataLabel, options, alignTo, isNew) {\n\t\n\tif (this.chart.polar) {\n\t\tvar angle = point.rectPlotX / Math.PI * 180,\n\t\t\talign,\n\t\t\tverticalAlign;\n\t\t\n\t\t// Align nicely outside the perimeter of the columns\n\t\tif (options.align === null) {\n\t\t\tif (angle > 20 && angle < 160) {\n\t\t\t\talign = 'left'; // right hemisphere\n\t\t\t} else if (angle > 200 && angle < 340) {\n\t\t\t\talign = 'right'; // left hemisphere\n\t\t\t} else {\n\t\t\t\talign = 'center'; // top or bottom\n\t\t\t}\n\t\t\toptions.align = align;\n\t\t}\n\t\tif (options.verticalAlign === null) {\n\t\t\tif (angle < 45 || angle > 315) {\n\t\t\t\tverticalAlign = 'bottom'; // top part\n\t\t\t} else if (angle > 135 && angle < 225) {\n\t\t\t\tverticalAlign = 'top'; // bottom part\n\t\t\t} else {\n\t\t\t\tverticalAlign = 'middle'; // left or right\n\t\t\t}\n\t\t\toptions.verticalAlign = verticalAlign;\n\t\t}\n\t\t\n\t\tseriesProto.alignDataLabel.call(this, point, dataLabel, options, alignTo, isNew);\n\t} else {\n\t\tproceed.call(this, point, dataLabel, options, alignTo, isNew);\n\t}\n\t\n});\n\n/**\n * Extend the mouse tracker to return the tooltip position index in terms of\n * degrees rather than pixels\n */\nwrap(pointerProto, 'getIndex', function (proceed, e) {\n\tvar ret,\n\t\tchart = this.chart,\n\t\tcenter,\n\t\tx,\n\t\ty;\n\t\n\tif (chart.polar) {\n\t\tcenter = chart.xAxis[0].center;\n\t\tx = e.chartX - center[0] - chart.plotLeft;\n\t\ty = e.chartY - center[1] - chart.plotTop;\n\t\t\n\t\tret = 180 - Math.round(Math.atan2(x, y) / Math.PI * 180);\n\t\n\t} else {\n\t\n\t\t// Run uber method\n\t\tret = proceed.call(this, e);\n\t}\n\treturn ret;\n});\n\n/**\n * Extend getCoordinates to prepare for polar axis values\n */\nwrap(pointerProto, 'getCoordinates', function (proceed, e) {\n\tvar chart = this.chart,\n\t\tret = {\n\t\t\txAxis: [],\n\t\t\tyAxis: []\n\t\t};\n\t\n\tif (chart.polar) {\t\n\n\t\teach(chart.axes, function (axis) {\n\t\t\tvar isXAxis = axis.isXAxis,\n\t\t\t\tcenter = axis.center,\n\t\t\t\tx = e.chartX - center[0] - chart.plotLeft,\n\t\t\t\ty = e.chartY - center[1] - chart.plotTop;\n\t\t\t\n\t\t\tret[isXAxis ? 'xAxis' : 'yAxis'].push({\n\t\t\t\taxis: axis,\n\t\t\t\tvalue: axis.translate(\n\t\t\t\t\tisXAxis ?\n\t\t\t\t\t\tMath.PI - Math.atan2(x, y) : // angle \n\t\t\t\t\t\tMath.sqrt(Math.pow(x, 2) + Math.pow(y, 2)), // distance from center\n\t\t\t\t\ttrue\n\t\t\t\t)\n\t\t\t});\n\t\t});\n\t\t\n\t} else {\n\t\tret = proceed.call(this, e);\n\t}\n\t\n\treturn ret;\n});\n}(Highcharts));\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/highchart3/js/highcharts.js",
    "content": "/*\n Highcharts JS v3.0.3 (2013-07-31)\n\n (c) 2009-2013 Torstein Hønsi\n\n License: www.highcharts.com/license\n*/\n(function(){function r(a,b){var c;a||(a={});for(c in b)a[c]=b[c];return a}function w(){var a,b=arguments.length,c={},d=function(a,b){var c,h;typeof a!==\"object\"&&(a={});for(h in b)b.hasOwnProperty(h)&&(c=b[h],a[h]=c&&typeof c===\"object\"&&Object.prototype.toString.call(c)!==\"[object Array]\"&&typeof c.nodeType!==\"number\"?d(a[h]||{},c):b[h]);return a};for(a=0;a<b;a++)c=d(c,arguments[a]);return c}function A(a,b){return parseInt(a,b||10)}function da(a){return typeof a===\"string\"}function U(a){return typeof a===\n\"object\"}function Ha(a){return Object.prototype.toString.call(a)===\"[object Array]\"}function pa(a){return typeof a===\"number\"}function ma(a){return N.log(a)/N.LN10}function ea(a){return N.pow(10,a)}function fa(a,b){for(var c=a.length;c--;)if(a[c]===b){a.splice(c,1);break}}function s(a){return a!==v&&a!==null}function x(a,b,c){var d,e;if(da(b))s(c)?a.setAttribute(b,c):a&&a.getAttribute&&(e=a.getAttribute(b));else if(s(b)&&U(b))for(d in b)a.setAttribute(d,b[d]);return e}function ha(a){return Ha(a)?\na:[a]}function n(){var a=arguments,b,c,d=a.length;for(b=0;b<d;b++)if(c=a[b],typeof c!==\"undefined\"&&c!==null)return c}function M(a,b){if(qa&&b&&b.opacity!==v)b.filter=\"alpha(opacity=\"+b.opacity*100+\")\";r(a.style,b)}function T(a,b,c,d,e){a=y.createElement(a);b&&r(a,b);e&&M(a,{padding:0,border:R,margin:0});c&&M(a,c);d&&d.appendChild(a);return a}function ga(a,b){var c=function(){};c.prototype=new a;r(c.prototype,b);return c}function za(a,b,c,d){var e=O.lang,a=+a||0,f=b===-1?(a.toString().split(\".\")[1]||\n\"\").length:isNaN(b=P(b))?2:b,b=c===void 0?e.decimalPoint:c,d=d===void 0?e.thousandsSep:d,e=a<0?\"-\":\"\",c=String(A(a=P(a).toFixed(f))),g=c.length>3?c.length%3:0;return e+(g?c.substr(0,g)+d:\"\")+c.substr(g).replace(/(\\d{3})(?=\\d)/g,\"$1\"+d)+(f?b+P(a-c).toFixed(f).slice(2):\"\")}function Aa(a,b){return Array((b||2)+1-String(a).length).join(0)+a}function Ab(a,b,c){var d=a[b];a[b]=function(){var a=Array.prototype.slice.call(arguments);a.unshift(d);return c.apply(this,a)}}function Ba(a,b){for(var c=\"{\",d=!1,\ne,f,g,h,i,j=[];(c=a.indexOf(c))!==-1;){e=a.slice(0,c);if(d){f=e.split(\":\");g=f.shift().split(\".\");i=g.length;e=b;for(h=0;h<i;h++)e=e[g[h]];if(f.length)f=f.join(\":\"),g=/\\.([0-9])/,h=O.lang,i=void 0,/f$/.test(f)?(i=(i=f.match(g))?i[1]:-1,e=za(e,i,h.decimalPoint,f.indexOf(\",\")>-1?h.thousandsSep:\"\")):e=Xa(f,e)}j.push(e);a=a.slice(c+1);c=(d=!d)?\"}\":\"{\"}j.push(a);return j.join(\"\")}function kb(a){return N.pow(10,S(N.log(a)/N.LN10))}function lb(a,b,c,d){var e,c=n(c,1);e=a/c;b||(b=[1,2,2.5,5,10],d&&d.allowDecimals===\n!1&&(c===1?b=[1,2,5,10]:c<=0.1&&(b=[1/c])));for(d=0;d<b.length;d++)if(a=b[d],e<=(b[d]+(b[d+1]||b[d]))/2)break;a*=c;return a}function Bb(a,b){var c=b||[[Cb,[1,2,5,10,20,25,50,100,200,500]],[mb,[1,2,5,10,15,30]],[Ya,[1,2,5,10,15,30]],[Qa,[1,2,3,4,6,8,12]],[ra,[1,2]],[Za,[1,2]],[Ra,[1,2,3,4,6]],[sa,null]],d=c[c.length-1],e=z[d[0]],f=d[1],g;for(g=0;g<c.length;g++)if(d=c[g],e=z[d[0]],f=d[1],c[g+1]&&a<=(e*f[f.length-1]+z[c[g+1][0]])/2)break;e===z[sa]&&a<5*e&&(f=[1,2,5]);e===z[sa]&&a<5*e&&(f=[1,2,5]);c=\nlb(a/e,f,d[0]===sa?kb(a/e):1);return{unitRange:e,count:c,unitName:d[0]}}function Db(a,b,c,d){var e=[],f={},g=O.global.useUTC,h,i=new Date(b),j=a.unitRange,k=a.count;if(s(b)){j>=z[mb]&&(i.setMilliseconds(0),i.setSeconds(j>=z[Ya]?0:k*S(i.getSeconds()/k)));if(j>=z[Ya])i[Eb](j>=z[Qa]?0:k*S(i[nb]()/k));if(j>=z[Qa])i[Fb](j>=z[ra]?0:k*S(i[ob]()/k));if(j>=z[ra])i[pb](j>=z[Ra]?1:k*S(i[Sa]()/k));j>=z[Ra]&&(i[Gb](j>=z[sa]?0:k*S(i[$a]()/k)),h=i[ab]());j>=z[sa]&&(h-=h%k,i[Hb](h));if(j===z[Za])i[pb](i[Sa]()-i[qb]()+\nn(d,1));b=1;h=i[ab]();for(var d=i.getTime(),l=i[$a](),m=i[Sa](),p=g?0:(864E5+i.getTimezoneOffset()*6E4)%864E5;d<c;)e.push(d),j===z[sa]?d=bb(h+b*k,0):j===z[Ra]?d=bb(h,l+b*k):!g&&(j===z[ra]||j===z[Za])?d=bb(h,l,m+b*k*(j===z[ra]?1:7)):d+=j*k,b++;e.push(d);o(rb(e,function(a){return j<=z[Qa]&&a%z[ra]===p}),function(a){f[a]=ra})}e.info=r(a,{higherRanks:f,totalRange:j*k});return e}function Ib(){this.symbol=this.color=0}function Jb(a,b){var c=a.length,d,e;for(e=0;e<c;e++)a[e].ss_i=e;a.sort(function(a,c){d=\nb(a,c);return d===0?a.ss_i-c.ss_i:d});for(e=0;e<c;e++)delete a[e].ss_i}function Ia(a){for(var b=a.length,c=a[0];b--;)a[b]<c&&(c=a[b]);return c}function ta(a){for(var b=a.length,c=a[0];b--;)a[b]>c&&(c=a[b]);return c}function Ja(a,b){for(var c in a)a[c]&&a[c]!==b&&a[c].destroy&&a[c].destroy(),delete a[c]}function Ta(a){cb||(cb=T(Ca));a&&cb.appendChild(a);cb.innerHTML=\"\"}function ua(a,b){var c=\"Highcharts error #\"+a+\": www.highcharts.com/errors/\"+a;if(b)throw c;else E.console&&console.log(c)}function ia(a){return parseFloat(a.toPrecision(14))}\nfunction Ka(a,b){Da=n(a,b.animation)}function Kb(){var a=O.global.useUTC,b=a?\"getUTC\":\"get\",c=a?\"setUTC\":\"set\";bb=a?Date.UTC:function(a,b,c,g,h,i){return(new Date(a,b,n(c,1),n(g,0),n(h,0),n(i,0))).getTime()};nb=b+\"Minutes\";ob=b+\"Hours\";qb=b+\"Day\";Sa=b+\"Date\";$a=b+\"Month\";ab=b+\"FullYear\";Eb=c+\"Minutes\";Fb=c+\"Hours\";pb=c+\"Date\";Gb=c+\"Month\";Hb=c+\"FullYear\"}function va(){}function La(a,b,c,d){this.axis=a;this.pos=b;this.type=c||\"\";this.isNew=!0;!c&&!d&&this.addLabel()}function sb(a,b){this.axis=a;if(b)this.options=\nb,this.id=b.id}function Lb(a,b,c,d,e,f){var g=a.chart.inverted;this.axis=a;this.isNegative=c;this.options=b;this.x=d;this.total=0;this.points={};this.stack=e;this.percent=f===\"percent\";this.alignOptions={align:b.align||(g?c?\"left\":\"right\":\"center\"),verticalAlign:b.verticalAlign||(g?\"middle\":c?\"bottom\":\"top\"),y:n(b.y,g?4:c?14:-6),x:n(b.x,g?c?-6:6:0)};this.textAlign=b.textAlign||(g?c?\"right\":\"left\":\"center\")}function db(){this.init.apply(this,arguments)}function tb(){this.init.apply(this,arguments)}\nfunction ub(a,b){this.init(a,b)}function vb(a,b){this.init(a,b)}function wb(){this.init.apply(this,arguments)}var v,y=document,E=window,N=Math,t=N.round,S=N.floor,ja=N.ceil,u=N.max,I=N.min,P=N.abs,V=N.cos,ba=N.sin,Ma=N.PI,Ua=Ma*2/360,Ea=navigator.userAgent,Mb=E.opera,qa=/msie/i.test(Ea)&&!Mb,eb=y.documentMode===8,fb=/AppleWebKit/.test(Ea),gb=/Firefox/.test(Ea),Nb=/(Mobile|Android|Windows Phone)/.test(Ea),wa=\"http://www.w3.org/2000/svg\",Y=!!y.createElementNS&&!!y.createElementNS(wa,\"svg\").createSVGRect,\nUb=gb&&parseInt(Ea.split(\"Firefox/\")[1],10)<4,Z=!Y&&!qa&&!!y.createElement(\"canvas\").getContext,Va,hb=y.documentElement.ontouchstart!==v,Ob={},xb=0,cb,O,Xa,Da,yb,z,xa=function(){},Fa=[],Ca=\"div\",R=\"none\",Pb=\"rgba(192,192,192,\"+(Y?1.0E-4:0.002)+\")\",Cb=\"millisecond\",mb=\"second\",Ya=\"minute\",Qa=\"hour\",ra=\"day\",Za=\"week\",Ra=\"month\",sa=\"year\",Qb=\"stroke-width\",bb,nb,ob,qb,Sa,$a,ab,Eb,Fb,pb,Gb,Hb,$={};E.Highcharts=E.Highcharts?ua(16,!0):{};Xa=function(a,b,c){if(!s(b)||isNaN(b))return\"Invalid date\";var a=\nn(a,\"%Y-%m-%d %H:%M:%S\"),d=new Date(b),e,f=d[ob](),g=d[qb](),h=d[Sa](),i=d[$a](),j=d[ab](),k=O.lang,l=k.weekdays,d=r({a:l[g].substr(0,3),A:l[g],d:Aa(h),e:h,b:k.shortMonths[i],B:k.months[i],m:Aa(i+1),y:j.toString().substr(2,2),Y:j,H:Aa(f),I:Aa(f%12||12),l:f%12||12,M:Aa(d[nb]()),p:f<12?\"AM\":\"PM\",P:f<12?\"am\":\"pm\",S:Aa(d.getSeconds()),L:Aa(t(b%1E3),3)},Highcharts.dateFormats);for(e in d)for(;a.indexOf(\"%\"+e)!==-1;)a=a.replace(\"%\"+e,typeof d[e]===\"function\"?d[e](b):d[e]);return c?a.substr(0,1).toUpperCase()+\na.substr(1):a};Ib.prototype={wrapColor:function(a){if(this.color>=a)this.color=0},wrapSymbol:function(a){if(this.symbol>=a)this.symbol=0}};z=function(){for(var a=0,b=arguments,c=b.length,d={};a<c;a++)d[b[a++]]=b[a];return d}(Cb,1,mb,1E3,Ya,6E4,Qa,36E5,ra,864E5,Za,6048E5,Ra,26784E5,sa,31556952E3);yb={init:function(a,b,c){var b=b||\"\",d=a.shift,e=b.indexOf(\"C\")>-1,f=e?7:3,g,b=b.split(\" \"),c=[].concat(c),h,i,j=function(a){for(g=a.length;g--;)a[g]===\"M\"&&a.splice(g+1,0,a[g+1],a[g+2],a[g+1],a[g+2])};e&&\n(j(b),j(c));a.isArea&&(h=b.splice(b.length-6,6),i=c.splice(c.length-6,6));if(d<=c.length/f)for(;d--;)c=[].concat(c).splice(0,f).concat(c);a.shift=0;if(b.length)for(a=c.length;b.length<a;)d=[].concat(b).splice(b.length-f,f),e&&(d[f-6]=d[f-2],d[f-5]=d[f-1]),b=b.concat(d);h&&(b=b.concat(h),c=c.concat(i));return[b,c]},step:function(a,b,c,d){var e=[],f=a.length;if(c===1)e=d;else if(f===b.length&&c<1)for(;f--;)d=parseFloat(a[f]),e[f]=isNaN(d)?a[f]:c*parseFloat(b[f]-d)+d;else e=b;return e}};(function(a){E.HighchartsAdapter=\nE.HighchartsAdapter||a&&{init:function(b){var c=a.fx,d=c.step,e,f=a.Tween,g=f&&f.propHooks;e=a.cssHooks.opacity;a.extend(a.easing,{easeOutQuad:function(a,b,c,d,e){return-d*(b/=e)*(b-2)+c}});a.each([\"cur\",\"_default\",\"width\",\"height\",\"opacity\"],function(a,b){var e=d,k,l;b===\"cur\"?e=c.prototype:b===\"_default\"&&f&&(e=g[b],b=\"set\");(k=e[b])&&(e[b]=function(c){c=a?c:this;l=c.elem;return l.attr?l.attr(c.prop,b===\"cur\"?v:c.now):k.apply(this,arguments)})});Ab(e,\"get\",function(a,b,c){return b.attr?b.opacity||\n0:a.call(this,b,c)});e=function(a){var c=a.elem,d;if(!a.started)d=b.init(c,c.d,c.toD),a.start=d[0],a.end=d[1],a.started=!0;c.attr(\"d\",b.step(a.start,a.end,a.pos,c.toD))};f?g.d={set:e}:d.d=e;this.each=Array.prototype.forEach?function(a,b){return Array.prototype.forEach.call(a,b)}:function(a,b){for(var c=0,d=a.length;c<d;c++)if(b.call(a[c],a[c],c,a)===!1)return c};a.fn.highcharts=function(){var a=\"Chart\",b=arguments,c,d;da(b[0])&&(a=b[0],b=Array.prototype.slice.call(b,1));c=b[0];if(c!==v)c.chart=c.chart||\n{},c.chart.renderTo=this[0],new Highcharts[a](c,b[1]),d=this;c===v&&(d=Fa[x(this[0],\"data-highcharts-chart\")]);return d}},getScript:a.getScript,inArray:a.inArray,adapterRun:function(b,c){return a(b)[c]()},grep:a.grep,map:function(a,c){for(var d=[],e=0,f=a.length;e<f;e++)d[e]=c.call(a[e],a[e],e,a);return d},offset:function(b){return a(b).offset()},addEvent:function(b,c,d){a(b).bind(c,d)},removeEvent:function(b,c,d){var e=y.removeEventListener?\"removeEventListener\":\"detachEvent\";y[e]&&b&&!b[e]&&(b[e]=\nfunction(){});a(b).unbind(c,d)},fireEvent:function(b,c,d,e){var f=a.Event(c),g=\"detached\"+c,h;!qa&&d&&(delete d.layerX,delete d.layerY);r(f,d);b[c]&&(b[g]=b[c],b[c]=null);a.each([\"preventDefault\",\"stopPropagation\"],function(a,b){var c=f[b];f[b]=function(){try{c.call(f)}catch(a){b===\"preventDefault\"&&(h=!0)}}});a(b).trigger(f);b[g]&&(b[c]=b[g],b[g]=null);e&&!f.isDefaultPrevented()&&!h&&e(f)},washMouseEvent:function(a){var c=a.originalEvent||a;if(c.pageX===v)c.pageX=a.pageX,c.pageY=a.pageY;return c},\nanimate:function(b,c,d){var e=a(b);if(!b.style)b.style={};if(c.d)b.toD=c.d,c.d=1;e.stop();e.animate(c,d)},stop:function(b){a(b).stop()}}})(E.jQuery);var W=E.HighchartsAdapter,L=W||{};W&&W.init.call(W,yb);var ib=L.adapterRun,Vb=L.getScript,na=L.inArray,o=L.each,rb=L.grep,Wb=L.offset,Na=L.map,J=L.addEvent,aa=L.removeEvent,B=L.fireEvent,Rb=L.washMouseEvent,zb=L.animate,Wa=L.stop,L={enabled:!0,x:0,y:15,style:{color:\"#666\",cursor:\"default\",fontSize:\"11px\",lineHeight:\"14px\"}};O={colors:\"#2f7ed8,#0d233a,#8bbc21,#910000,#1aadce,#492970,#f28f43,#77a1e5,#c42525,#a6c96a\".split(\",\"),\nsymbols:[\"circle\",\"diamond\",\"square\",\"triangle\",\"triangle-down\"],lang:{loading:\"Loading...\",months:\"January,February,March,April,May,June,July,August,September,October,November,December\".split(\",\"),shortMonths:\"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec\".split(\",\"),weekdays:\"Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday\".split(\",\"),decimalPoint:\".\",numericSymbols:\"k,M,G,T,P,E\".split(\",\"),resetZoom:\"Reset zoom\",resetZoomTitle:\"Reset zoom level 1:1\",thousandsSep:\",\"},global:{useUTC:!0,\ncanvasToolsURL:\"http://code.highcharts.com/3.0.3/modules/canvas-tools.js\",VMLRadialGradientURL:\"http://code.highcharts.com/3.0.3/gfx/vml-radial-gradient.png\"},chart:{borderColor:\"#4572A7\",borderRadius:5,defaultSeriesType:\"line\",ignoreHiddenSeries:!0,spacingTop:10,spacingRight:10,spacingBottom:15,spacingLeft:10,style:{fontFamily:'\"Lucida Grande\", \"Lucida Sans Unicode\", Verdana, Arial, Helvetica, sans-serif',fontSize:\"12px\"},backgroundColor:\"#FFFFFF\",plotBorderColor:\"#C0C0C0\",resetZoomButton:{theme:{zIndex:20},\nposition:{align:\"right\",x:-10,y:10}}},title:{text:\"Chart title\",align:\"center\",margin:15,style:{color:\"#274b6d\",fontSize:\"16px\"}},subtitle:{text:\"\",align:\"center\",style:{color:\"#4d759e\"}},plotOptions:{line:{allowPointSelect:!1,showCheckbox:!1,animation:{duration:1E3},events:{},lineWidth:2,marker:{enabled:!0,lineWidth:0,radius:4,lineColor:\"#FFFFFF\",states:{hover:{enabled:!0},select:{fillColor:\"#FFFFFF\",lineColor:\"#000000\",lineWidth:2}}},point:{events:{}},dataLabels:w(L,{align:\"center\",enabled:!1,formatter:function(){return this.y===\nnull?\"\":za(this.y,-1)},verticalAlign:\"bottom\",y:0}),cropThreshold:300,pointRange:0,showInLegend:!0,states:{hover:{marker:{}},select:{marker:{}}},stickyTracking:!0}},labels:{style:{position:\"absolute\",color:\"#3E576F\"}},legend:{enabled:!0,align:\"center\",layout:\"horizontal\",labelFormatter:function(){return this.name},borderWidth:1,borderColor:\"#909090\",borderRadius:5,navigation:{activeColor:\"#274b6d\",inactiveColor:\"#CCC\"},shadow:!1,itemStyle:{cursor:\"pointer\",color:\"#274b6d\",fontSize:\"12px\"},itemHoverStyle:{color:\"#000\"},\nitemHiddenStyle:{color:\"#CCC\"},itemCheckboxStyle:{position:\"absolute\",width:\"13px\",height:\"13px\"},symbolWidth:16,symbolPadding:5,verticalAlign:\"bottom\",x:0,y:0,title:{style:{fontWeight:\"bold\"}}},loading:{labelStyle:{fontWeight:\"bold\",position:\"relative\",top:\"1em\"},style:{position:\"absolute\",backgroundColor:\"white\",opacity:0.5,textAlign:\"center\"}},tooltip:{enabled:!0,animation:Y,backgroundColor:\"rgba(255, 255, 255, .85)\",borderWidth:1,borderRadius:3,dateTimeLabelFormats:{millisecond:\"%A, %b %e, %H:%M:%S.%L\",\nsecond:\"%A, %b %e, %H:%M:%S\",minute:\"%A, %b %e, %H:%M\",hour:\"%A, %b %e, %H:%M\",day:\"%A, %b %e, %Y\",week:\"Week from %A, %b %e, %Y\",month:\"%B %Y\",year:\"%Y\"},headerFormat:'<span style=\"font-size: 10px\">{point.key}</span><br/>',pointFormat:'<span style=\"color:{series.color}\">{series.name}</span>: <b>{point.y}</b><br/>',shadow:!0,snap:Nb?25:10,style:{color:\"#333333\",cursor:\"default\",fontSize:\"12px\",padding:\"8px\",whiteSpace:\"nowrap\"}},credits:{enabled:!0,text:\"\",href:\"http://www.highcharts.com\",\nposition:{align:\"right\",x:-10,verticalAlign:\"bottom\",y:-5},style:{cursor:\"pointer\",color:\"#909090\",fontSize:\"9px\"}}};var X=O.plotOptions,W=X.line;Kb();var oa=function(a){var b=[],c,d;(function(a){a&&a.stops?d=Na(a.stops,function(a){return oa(a[1])}):(c=/rgba\\(\\s*([0-9]{1,3})\\s*,\\s*([0-9]{1,3})\\s*,\\s*([0-9]{1,3})\\s*,\\s*([0-9]?(?:\\.[0-9]+)?)\\s*\\)/.exec(a))?b=[A(c[1]),A(c[2]),A(c[3]),parseFloat(c[4],10)]:(c=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(a))?b=[A(c[1],16),A(c[2],16),A(c[3],\n16),1]:(c=/rgb\\(\\s*([0-9]{1,3})\\s*,\\s*([0-9]{1,3})\\s*,\\s*([0-9]{1,3})\\s*\\)/.exec(a))&&(b=[A(c[1]),A(c[2]),A(c[3]),1])})(a);return{get:function(c){var f;d?(f=w(a),f.stops=[].concat(f.stops),o(d,function(a,b){f.stops[b]=[f.stops[b][0],a.get(c)]})):f=b&&!isNaN(b[0])?c===\"rgb\"?\"rgb(\"+b[0]+\",\"+b[1]+\",\"+b[2]+\")\":c===\"a\"?b[3]:\"rgba(\"+b.join(\",\")+\")\":a;return f},brighten:function(a){if(d)o(d,function(b){b.brighten(a)});else if(pa(a)&&a!==0){var c;for(c=0;c<3;c++)b[c]+=A(a*255),b[c]<0&&(b[c]=0),b[c]>255&&\n(b[c]=255)}return this},rgba:b,setOpacity:function(a){b[3]=a;return this}}};va.prototype={init:function(a,b){this.element=b===\"span\"?T(b):y.createElementNS(wa,b);this.renderer=a;this.attrSetters={}},opacity:1,animate:function(a,b,c){b=n(b,Da,!0);Wa(this);if(b){b=w(b);if(c)b.complete=c;zb(this,a,b)}else this.attr(a),c&&c()},attr:function(a,b){var c,d,e,f,g=this.element,h=g.nodeName.toLowerCase(),i=this.renderer,j,k=this.attrSetters,l=this.shadows,m,p,q=this;da(a)&&s(b)&&(c=a,a={},a[c]=b);if(da(a))c=\na,h===\"circle\"?c={x:\"cx\",y:\"cy\"}[c]||c:c===\"strokeWidth\"&&(c=\"stroke-width\"),q=x(g,c)||this[c]||0,c!==\"d\"&&c!==\"visibility\"&&(q=parseFloat(q));else{for(c in a)if(j=!1,d=a[c],e=k[c]&&k[c].call(this,d,c),e!==!1){e!==v&&(d=e);if(c===\"d\")d&&d.join&&(d=d.join(\" \")),/(NaN| {2}|^$)/.test(d)&&(d=\"M 0 0\");else if(c===\"x\"&&h===\"text\")for(e=0;e<g.childNodes.length;e++)f=g.childNodes[e],x(f,\"x\")===x(g,\"x\")&&x(f,\"x\",d);else if(this.rotation&&(c===\"x\"||c===\"y\"))p=!0;else if(c===\"fill\")d=i.color(d,g,c);else if(h===\n\"circle\"&&(c===\"x\"||c===\"y\"))c={x:\"cx\",y:\"cy\"}[c]||c;else if(h===\"rect\"&&c===\"r\")x(g,{rx:d,ry:d}),j=!0;else if(c===\"translateX\"||c===\"translateY\"||c===\"rotation\"||c===\"verticalAlign\"||c===\"scaleX\"||c===\"scaleY\")j=p=!0;else if(c===\"stroke\")d=i.color(d,g,c);else if(c===\"dashstyle\")if(c=\"stroke-dasharray\",d=d&&d.toLowerCase(),d===\"solid\")d=R;else{if(d){d=d.replace(\"shortdashdotdot\",\"3,1,1,1,1,1,\").replace(\"shortdashdot\",\"3,1,1,1\").replace(\"shortdot\",\"1,1,\").replace(\"shortdash\",\"3,1,\").replace(\"longdash\",\n\"8,3,\").replace(/dot/g,\"1,3,\").replace(\"dash\",\"4,3,\").replace(/,$/,\"\").split(\",\");for(e=d.length;e--;)d[e]=A(d[e])*n(a[\"stroke-width\"],this[\"stroke-width\"]);d=d.join(\",\")}}else if(c===\"width\")d=A(d);else if(c===\"align\")c=\"text-anchor\",d={left:\"start\",center:\"middle\",right:\"end\"}[d];else if(c===\"title\")e=g.getElementsByTagName(\"title\")[0],e||(e=y.createElementNS(wa,\"title\"),g.appendChild(e)),e.textContent=d;c===\"strokeWidth\"&&(c=\"stroke-width\");if(c===\"stroke-width\"||c===\"stroke\"){this[c]=d;if(this.stroke&&\nthis[\"stroke-width\"])x(g,\"stroke\",this.stroke),x(g,\"stroke-width\",this[\"stroke-width\"]),this.hasStroke=!0;else if(c===\"stroke-width\"&&d===0&&this.hasStroke)g.removeAttribute(\"stroke\"),this.hasStroke=!1;j=!0}this.symbolName&&/^(x|y|width|height|r|start|end|innerR|anchorX|anchorY)/.test(c)&&(m||(this.symbolAttr(a),m=!0),j=!0);if(l&&/^(width|height|visibility|x|y|d|transform|cx|cy|r)$/.test(c))for(e=l.length;e--;)x(l[e],c,c===\"height\"?u(d-(l[e].cutHeight||0),0):d);if((c===\"width\"||c===\"height\")&&h===\n\"rect\"&&d<0)d=0;this[c]=d;c===\"text\"?(d!==this.textStr&&delete this.bBox,this.textStr=d,this.added&&i.buildText(this)):j||x(g,c,d)}p&&this.updateTransform()}return q},addClass:function(a){var b=this.element,c=x(b,\"class\")||\"\";c.indexOf(a)===-1&&x(b,\"class\",c+\" \"+a);return this},symbolAttr:function(a){var b=this;o(\"x,y,r,start,end,width,height,innerR,anchorX,anchorY\".split(\",\"),function(c){b[c]=n(a[c],b[c])});b.attr({d:b.renderer.symbols[b.symbolName](b.x,b.y,b.width,b.height,b)})},clip:function(a){return this.attr(\"clip-path\",\na?\"url(\"+this.renderer.url+\"#\"+a.id+\")\":R)},crisp:function(a,b,c,d,e){var f,g={},h={},i,a=a||this.strokeWidth||this.attr&&this.attr(\"stroke-width\")||0;i=t(a)%2/2;h.x=S(b||this.x||0)+i;h.y=S(c||this.y||0)+i;h.width=S((d||this.width||0)-2*i);h.height=S((e||this.height||0)-2*i);h.strokeWidth=a;for(f in h)this[f]!==h[f]&&(this[f]=g[f]=h[f]);return g},css:function(a){var b=this.element,c=a&&a.width&&b.nodeName.toLowerCase()===\"text\",d,e=\"\",f=function(a,b){return\"-\"+b.toLowerCase()};if(a&&a.color)a.fill=\na.color;this.styles=a=r(this.styles,a);Z&&c&&delete a.width;if(qa&&!Y)c&&delete a.width,M(this.element,a);else{for(d in a)e+=d.replace(/([A-Z])/g,f)+\":\"+a[d]+\";\";x(b,\"style\",e)}c&&this.added&&this.renderer.buildText(this);return this},on:function(a,b){var c=this.element;if(hb&&a===\"click\")c.ontouchstart=function(a){a.preventDefault();b.call(c,a)};c[\"on\"+a]=b;return this},setRadialReference:function(a){this.element.radialReference=a;return this},translate:function(a,b){return this.attr({translateX:a,\ntranslateY:b})},invert:function(){this.inverted=!0;this.updateTransform();return this},htmlCss:function(a){var b=this.element;if(b=a&&b.tagName===\"SPAN\"&&a.width)delete a.width,this.textWidth=b,this.updateTransform();this.styles=r(this.styles,a);M(this.element,a);return this},htmlGetBBox:function(){var a=this.element,b=this.bBox;if(!b){if(a.nodeName===\"text\")a.style.position=\"absolute\";b=this.bBox={x:a.offsetLeft,y:a.offsetTop,width:a.offsetWidth,height:a.offsetHeight}}return b},htmlUpdateTransform:function(){if(this.added){var a=\nthis.renderer,b=this.element,c=this.translateX||0,d=this.translateY||0,e=this.x||0,f=this.y||0,g=this.textAlign||\"left\",h={left:0,center:0.5,right:1}[g],i=g&&g!==\"left\",j=this.shadows;M(b,{marginLeft:c,marginTop:d});j&&o(j,function(a){M(a,{marginLeft:c+1,marginTop:d+1})});this.inverted&&o(b.childNodes,function(c){a.invertChild(c,b)});if(b.tagName===\"SPAN\"){var k,l,j=this.rotation,m;k=0;var p=1,q=0,ka;m=A(this.textWidth);var C=this.xCorr||0,F=this.yCorr||0,Sb=[j,g,b.innerHTML,this.textWidth].join(\",\");\nif(Sb!==this.cTT){s(j)&&(k=j*Ua,p=V(k),q=ba(k),this.setSpanRotation(j,q,p));k=n(this.elemWidth,b.offsetWidth);l=n(this.elemHeight,b.offsetHeight);if(k>m&&/[ \\-]/.test(b.textContent||b.innerText))M(b,{width:m+\"px\",display:\"block\",whiteSpace:\"normal\"}),k=m;m=a.fontMetrics(b.style.fontSize).b;C=p<0&&-k;F=q<0&&-l;ka=p*q<0;C+=q*m*(ka?1-h:h);F-=p*m*(j?ka?h:1-h:1);i&&(C-=k*h*(p<0?-1:1),j&&(F-=l*h*(q<0?-1:1)),M(b,{textAlign:g}));this.xCorr=C;this.yCorr=F}M(b,{left:e+C+\"px\",top:f+F+\"px\"});if(fb)l=b.offsetHeight;\nthis.cTT=Sb}}else this.alignOnAdd=!0},setSpanRotation:function(a){var b={};b[qa?\"-ms-transform\":fb?\"-webkit-transform\":gb?\"MozTransform\":Mb?\"-o-transform\":\"\"]=b.transform=\"rotate(\"+a+\"deg)\";M(this.element,b)},updateTransform:function(){var a=this.translateX||0,b=this.translateY||0,c=this.scaleX,d=this.scaleY,e=this.inverted,f=this.rotation;e&&(a+=this.attr(\"width\"),b+=this.attr(\"height\"));a=[\"translate(\"+a+\",\"+b+\")\"];e?a.push(\"rotate(90) scale(-1,1)\"):f&&a.push(\"rotate(\"+f+\" \"+(this.x||0)+\" \"+(this.y||\n0)+\")\");(s(c)||s(d))&&a.push(\"scale(\"+n(c,1)+\" \"+n(d,1)+\")\");a.length&&x(this.element,\"transform\",a.join(\" \"))},toFront:function(){var a=this.element;a.parentNode.appendChild(a);return this},align:function(a,b,c){var d,e,f,g,h={};e=this.renderer;f=e.alignedObjects;if(a){if(this.alignOptions=a,this.alignByTranslate=b,!c||da(c))this.alignTo=d=c||\"renderer\",fa(f,this),f.push(this),c=null}else a=this.alignOptions,b=this.alignByTranslate,d=this.alignTo;c=n(c,e[d],e);d=a.align;e=a.verticalAlign;f=(c.x||\n0)+(a.x||0);g=(c.y||0)+(a.y||0);if(d===\"right\"||d===\"center\")f+=(c.width-(a.width||0))/{right:1,center:2}[d];h[b?\"translateX\":\"x\"]=t(f);if(e===\"bottom\"||e===\"middle\")g+=(c.height-(a.height||0))/({bottom:1,middle:2}[e]||1);h[b?\"translateY\":\"y\"]=t(g);this[this.placed?\"animate\":\"attr\"](h);this.placed=!0;this.alignAttr=h;return this},getBBox:function(){var a=this.bBox,b=this.renderer,c,d=this.rotation;c=this.element;var e=this.styles,f=d*Ua;if(!a){if(c.namespaceURI===wa||b.forExport){try{a=c.getBBox?\nr({},c.getBBox()):{width:c.offsetWidth,height:c.offsetHeight}}catch(g){}if(!a||a.width<0)a={width:0,height:0}}else a=this.htmlGetBBox();if(b.isSVG){b=a.width;c=a.height;if(qa&&e&&e.fontSize===\"11px\"&&c.toPrecision(3)===\"22.7\")a.height=c=14;if(d)a.width=P(c*ba(f))+P(b*V(f)),a.height=P(c*V(f))+P(b*ba(f))}this.bBox=a}return a},show:function(){return this.attr({visibility:\"visible\"})},hide:function(){return this.attr({visibility:\"hidden\"})},fadeOut:function(a){var b=this;b.animate({opacity:0},{duration:a||\n150,complete:function(){b.hide()}})},add:function(a){var b=this.renderer,c=a||b,d=c.element||b.box,e=d.childNodes,f=this.element,g=x(f,\"zIndex\"),h;if(a)this.parentGroup=a;this.parentInverted=a&&a.inverted;this.textStr!==void 0&&b.buildText(this);if(g)c.handleZ=!0,g=A(g);if(c.handleZ)for(c=0;c<e.length;c++)if(a=e[c],b=x(a,\"zIndex\"),a!==f&&(A(b)>g||!s(g)&&s(b))){d.insertBefore(f,a);h=!0;break}h||d.appendChild(f);this.added=!0;B(this,\"add\");return this},safeRemoveChild:function(a){var b=a.parentNode;\nb&&b.removeChild(a)},destroy:function(){var a=this,b=a.element||{},c=a.shadows,d=a.renderer.isSVG&&b.nodeName===\"SPAN\"&&b.parentNode,e,f;b.onclick=b.onmouseout=b.onmouseover=b.onmousemove=b.point=null;Wa(a);if(a.clipPath)a.clipPath=a.clipPath.destroy();if(a.stops){for(f=0;f<a.stops.length;f++)a.stops[f]=a.stops[f].destroy();a.stops=null}a.safeRemoveChild(b);for(c&&o(c,function(b){a.safeRemoveChild(b)});d&&d.childNodes.length===0;)b=d.parentNode,a.safeRemoveChild(d),d=b;a.alignTo&&fa(a.renderer.alignedObjects,\na);for(e in a)delete a[e];return null},shadow:function(a,b,c){var d=[],e,f,g=this.element,h,i,j,k;if(a){i=n(a.width,3);j=(a.opacity||0.15)/i;k=this.parentInverted?\"(-1,-1)\":\"(\"+n(a.offsetX,1)+\", \"+n(a.offsetY,1)+\")\";for(e=1;e<=i;e++){f=g.cloneNode(0);h=i*2+1-2*e;x(f,{isShadow:\"true\",stroke:a.color||\"black\",\"stroke-opacity\":j*e,\"stroke-width\":h,transform:\"translate\"+k,fill:R});if(c)x(f,\"height\",u(x(f,\"height\")-h,0)),f.cutHeight=h;b?b.element.appendChild(f):g.parentNode.insertBefore(f,g);d.push(f)}this.shadows=\nd}return this}};var Ga=function(){this.init.apply(this,arguments)};Ga.prototype={Element:va,init:function(a,b,c,d){var e=location,f,g;f=this.createElement(\"svg\").attr({version:\"1.1\"});g=f.element;a.appendChild(g);a.innerHTML.indexOf(\"xmlns\")===-1&&x(g,\"xmlns\",wa);this.isSVG=!0;this.box=g;this.boxWrapper=f;this.alignedObjects=[];this.url=(gb||fb)&&y.getElementsByTagName(\"base\").length?e.href.replace(/#.*?$/,\"\").replace(/([\\('\\)])/g,\"\\\\$1\").replace(/ /g,\"%20\"):\"\";this.createElement(\"desc\").add().element.appendChild(y.createTextNode(\"Created with Highcharts 3.0.3\"));\nthis.defs=this.createElement(\"defs\").add();this.forExport=d;this.gradients={};this.setSize(b,c,!1);var h;if(gb&&a.getBoundingClientRect)this.subPixelFix=b=function(){M(a,{left:0,top:0});h=a.getBoundingClientRect();M(a,{left:ja(h.left)-h.left+\"px\",top:ja(h.top)-h.top+\"px\"})},b(),J(E,\"resize\",b)},isHidden:function(){return!this.boxWrapper.getBBox().width},destroy:function(){var a=this.defs;this.box=null;this.boxWrapper=this.boxWrapper.destroy();Ja(this.gradients||{});this.gradients=null;if(a)this.defs=\na.destroy();this.subPixelFix&&aa(E,\"resize\",this.subPixelFix);return this.alignedObjects=null},createElement:function(a){var b=new this.Element;b.init(this,a);return b},draw:function(){},buildText:function(a){for(var b=a.element,c=this,d=c.forExport,e=n(a.textStr,\"\").toString().replace(/<(b|strong)>/g,'<span style=\"font-weight:bold\">').replace(/<(i|em)>/g,'<span style=\"font-style:italic\">').replace(/<a/g,\"<span\").replace(/<\\/(b|strong|i|em|a)>/g,\"</span>\").split(/<br.*?>/g),f=b.childNodes,g=/style=\"([^\"]+)\"/,\nh=/href=\"(http[^\"]+)\"/,i=x(b,\"x\"),j=a.styles,k=j&&j.width&&A(j.width),l=j&&j.lineHeight,m=f.length;m--;)b.removeChild(f[m]);k&&!a.added&&this.box.appendChild(b);e[e.length-1]===\"\"&&e.pop();o(e,function(e,f){var m,n=0,e=e.replace(/<span/g,\"|||<span\").replace(/<\\/span>/g,\"</span>|||\");m=e.split(\"|||\");o(m,function(e){if(e!==\"\"||m.length===1){var p={},o=y.createElementNS(wa,\"tspan\"),s;g.test(e)&&(s=e.match(g)[1].replace(/(;| |^)color([ :])/,\"$1fill$2\"),x(o,\"style\",s));h.test(e)&&!d&&(x(o,\"onclick\",'location.href=\"'+\ne.match(h)[1]+'\"'),M(o,{cursor:\"pointer\"}));e=(e.replace(/<(.|\\n)*?>/g,\"\")||\" \").replace(/&lt;/g,\"<\").replace(/&gt;/g,\">\");if(e!==\" \"&&(o.appendChild(y.createTextNode(e)),n?p.dx=0:p.x=i,x(o,p),!n&&f&&(!Y&&d&&M(o,{display:\"block\"}),x(o,\"dy\",l||c.fontMetrics(/px$/.test(o.style.fontSize)?o.style.fontSize:j.fontSize).h,fb&&o.offsetHeight)),b.appendChild(o),n++,k))for(var e=e.replace(/([^\\^])-/g,\"$1- \").split(\" \"),u,t=[];e.length||t.length;)delete a.bBox,u=a.getBBox().width,p=u>k,!p||e.length===1?(e=t,\nt=[],e.length&&(o=y.createElementNS(wa,\"tspan\"),x(o,{dy:l||16,x:i}),s&&x(o,\"style\",s),b.appendChild(o),u>k&&(k=u))):(o.removeChild(o.firstChild),t.unshift(e.pop())),e.length&&o.appendChild(y.createTextNode(e.join(\" \").replace(/- /g,\"-\")))}})})},button:function(a,b,c,d,e,f,g){var h=this.label(a,b,c,null,null,null,null,null,\"button\"),i=0,j,k,l,m,p,a={x1:0,y1:0,x2:0,y2:1},e=w({\"stroke-width\":1,stroke:\"#CCCCCC\",fill:{linearGradient:a,stops:[[0,\"#FEFEFE\"],[1,\"#F6F6F6\"]]},r:2,padding:5,style:{color:\"black\"}},\ne);l=e.style;delete e.style;f=w(e,{stroke:\"#68A\",fill:{linearGradient:a,stops:[[0,\"#FFF\"],[1,\"#ACF\"]]}},f);m=f.style;delete f.style;g=w(e,{stroke:\"#68A\",fill:{linearGradient:a,stops:[[0,\"#9BD\"],[1,\"#CDF\"]]}},g);p=g.style;delete g.style;J(h.element,qa?\"mouseover\":\"mouseenter\",function(){h.attr(f).css(m)});J(h.element,qa?\"mouseout\":\"mouseleave\",function(){j=[e,f,g][i];k=[l,m,p][i];h.attr(j).css(k)});h.setState=function(a){(i=a)?a===2&&h.attr(g).css(p):h.attr(e).css(l)};return h.on(\"click\",function(){d.call(h)}).attr(e).css(r({cursor:\"default\"},\nl))},crispLine:function(a,b){a[1]===a[4]&&(a[1]=a[4]=t(a[1])-b%2/2);a[2]===a[5]&&(a[2]=a[5]=t(a[2])+b%2/2);return a},path:function(a){var b={fill:R};Ha(a)?b.d=a:U(a)&&r(b,a);return this.createElement(\"path\").attr(b)},circle:function(a,b,c){a=U(a)?a:{x:a,y:b,r:c};return this.createElement(\"circle\").attr(a)},arc:function(a,b,c,d,e,f){if(U(a))b=a.y,c=a.r,d=a.innerR,e=a.start,f=a.end,a=a.x;a=this.symbol(\"arc\",a||0,b||0,c||0,c||0,{innerR:d||0,start:e||0,end:f||0});a.r=c;return a},rect:function(a,b,c,d,\ne,f){e=U(a)?a.r:e;e=this.createElement(\"rect\").attr({rx:e,ry:e,fill:R});return e.attr(U(a)?a:e.crisp(f,a,b,u(c,0),u(d,0)))},setSize:function(a,b,c){var d=this.alignedObjects,e=d.length;this.width=a;this.height=b;for(this.boxWrapper[n(c,!0)?\"animate\":\"attr\"]({width:a,height:b});e--;)d[e].align()},g:function(a){var b=this.createElement(\"g\");return s(a)?b.attr({\"class\":\"highcharts-\"+a}):b},image:function(a,b,c,d,e){var f={preserveAspectRatio:R};arguments.length>1&&r(f,{x:b,y:c,width:d,height:e});f=this.createElement(\"image\").attr(f);\nf.element.setAttributeNS?f.element.setAttributeNS(\"http://www.w3.org/1999/xlink\",\"href\",a):f.element.setAttribute(\"hc-svg-href\",a);return f},symbol:function(a,b,c,d,e,f){var g,h=this.symbols[a],h=h&&h(t(b),t(c),d,e,f),i=/^url\\((.*?)\\)$/,j,k;if(h)g=this.path(h),r(g,{symbolName:a,x:b,y:c,width:d,height:e}),f&&r(g,f);else if(i.test(a))k=function(a,b){a.element&&(a.attr({width:b[0],height:b[1]}),a.alignByTranslate||a.translate(t((d-b[0])/2),t((e-b[1])/2)))},j=a.match(i)[1],a=Ob[j],g=this.image(j).attr({x:b,\ny:c}),g.isImg=!0,a?k(g,a):(g.attr({width:0,height:0}),T(\"img\",{onload:function(){k(g,Ob[j]=[this.width,this.height])},src:j}));return g},symbols:{circle:function(a,b,c,d){var e=0.166*c;return[\"M\",a+c/2,b,\"C\",a+c+e,b,a+c+e,b+d,a+c/2,b+d,\"C\",a-e,b+d,a-e,b,a+c/2,b,\"Z\"]},square:function(a,b,c,d){return[\"M\",a,b,\"L\",a+c,b,a+c,b+d,a,b+d,\"Z\"]},triangle:function(a,b,c,d){return[\"M\",a+c/2,b,\"L\",a+c,b+d,a,b+d,\"Z\"]},\"triangle-down\":function(a,b,c,d){return[\"M\",a,b,\"L\",a+c,b,a+c/2,b+d,\"Z\"]},diamond:function(a,\nb,c,d){return[\"M\",a+c/2,b,\"L\",a+c,b+d/2,a+c/2,b+d,a,b+d/2,\"Z\"]},arc:function(a,b,c,d,e){var f=e.start,c=e.r||c||d,g=e.end-0.001,d=e.innerR,h=e.open,i=V(f),j=ba(f),k=V(g),g=ba(g),e=e.end-f<Ma?0:1;return[\"M\",a+c*i,b+c*j,\"A\",c,c,0,e,1,a+c*k,b+c*g,h?\"M\":\"L\",a+d*k,b+d*g,\"A\",d,d,0,e,0,a+d*i,b+d*j,h?\"\":\"Z\"]}},clipRect:function(a,b,c,d){var e=\"highcharts-\"+xb++,f=this.createElement(\"clipPath\").attr({id:e}).add(this.defs),a=this.rect(a,b,c,d,0).add(f);a.id=e;a.clipPath=f;return a},color:function(a,b,c){var d=\nthis,e,f=/^rgba/,g,h,i,j,k,l,m,p=[];a&&a.linearGradient?g=\"linearGradient\":a&&a.radialGradient&&(g=\"radialGradient\");if(g){c=a[g];h=d.gradients;j=a.stops;b=b.radialReference;Ha(c)&&(a[g]=c={x1:c[0],y1:c[1],x2:c[2],y2:c[3],gradientUnits:\"userSpaceOnUse\"});g===\"radialGradient\"&&b&&!s(c.gradientUnits)&&(c=w(c,{cx:b[0]-b[2]/2+c.cx*b[2],cy:b[1]-b[2]/2+c.cy*b[2],r:c.r*b[2],gradientUnits:\"userSpaceOnUse\"}));for(m in c)m!==\"id\"&&p.push(m,c[m]);for(m in j)p.push(j[m]);p=p.join(\",\");h[p]?a=h[p].id:(c.id=a=\n\"highcharts-\"+xb++,h[p]=i=d.createElement(g).attr(c).add(d.defs),i.stops=[],o(j,function(a){f.test(a[1])?(e=oa(a[1]),k=e.get(\"rgb\"),l=e.get(\"a\")):(k=a[1],l=1);a=d.createElement(\"stop\").attr({offset:a[0],\"stop-color\":k,\"stop-opacity\":l}).add(i);i.stops.push(a)}));return\"url(\"+d.url+\"#\"+a+\")\"}else return f.test(a)?(e=oa(a),x(b,c+\"-opacity\",e.get(\"a\")),e.get(\"rgb\")):(b.removeAttribute(c+\"-opacity\"),a)},text:function(a,b,c,d){var e=O.chart.style,f=Z||!Y&&this.forExport;if(d&&!this.forExport)return this.html(a,\nb,c);b=t(n(b,0));c=t(n(c,0));a=this.createElement(\"text\").attr({x:b,y:c,text:a}).css({fontFamily:e.fontFamily,fontSize:e.fontSize});f&&a.css({position:\"absolute\"});a.x=b;a.y=c;return a},html:function(a,b,c){var d=O.chart.style,e=this.createElement(\"span\"),f=e.attrSetters,g=e.element,h=e.renderer;f.text=function(a){a!==g.innerHTML&&delete this.bBox;g.innerHTML=a;return!1};f.x=f.y=f.align=function(a,b){b===\"align\"&&(b=\"textAlign\");e[b]=a;e.htmlUpdateTransform();return!1};e.attr({text:a,x:t(b),y:t(c)}).css({position:\"absolute\",\nwhiteSpace:\"nowrap\",fontFamily:d.fontFamily,fontSize:d.fontSize});e.css=e.htmlCss;if(h.isSVG)e.add=function(a){var b,c=h.box.parentNode,d=[];if(a){if(b=a.div,!b){for(;a;)d.push(a),a=a.parentGroup;o(d.reverse(),function(a){var d;b=a.div=a.div||T(Ca,{className:x(a.element,\"class\")},{position:\"absolute\",left:(a.translateX||0)+\"px\",top:(a.translateY||0)+\"px\"},b||c);d=b.style;r(a.attrSetters,{translateX:function(a){d.left=a+\"px\"},translateY:function(a){d.top=a+\"px\"},visibility:function(a,b){d[b]=a}})})}}else b=\nc;b.appendChild(g);e.added=!0;e.alignOnAdd&&e.htmlUpdateTransform();return e};return e},fontMetrics:function(a){var a=A(a||11),a=a<24?a+4:t(a*1.2),b=t(a*0.8);return{h:a,b:b}},label:function(a,b,c,d,e,f,g,h,i){function j(){var a,b;a=n.element.style;F=(Oa===void 0||D===void 0||q.styles.textAlign)&&n.getBBox();q.width=(Oa||F.width||0)+2*ca+jb;q.height=(D||F.height||0)+2*ca;A=ca+p.fontMetrics(a&&a.fontSize).b;if(y){if(!C)a=t(-u*ca),b=h?-A:0,q.box=C=d?p.symbol(d,a,b,q.width,q.height):p.rect(a,b,q.width,\nq.height,0,x[Qb]),C.add(q);C.isImg||C.attr(w({width:q.width,height:q.height},x));x=null}}function k(){var a=q.styles,a=a&&a.textAlign,b=jb+ca*(1-u),c;c=h?0:A;if(s(Oa)&&(a===\"center\"||a===\"right\"))b+={center:0.5,right:1}[a]*(Oa-F.width);(b!==n.x||c!==n.y)&&n.attr({x:b,y:c});n.x=b;n.y=c}function l(a,b){C?C.attr(a,b):x[a]=b}function m(){n.add(q);q.attr({text:a,x:b,y:c});C&&s(e)&&q.attr({anchorX:e,anchorY:f})}var p=this,q=p.g(i),n=p.text(\"\",0,0,g).attr({zIndex:1}),C,F,u=0,ca=3,jb=0,Oa,D,H,ya,G=0,x={},\nA,g=q.attrSetters,y;J(q,\"add\",m);g.width=function(a){Oa=a;return!1};g.height=function(a){D=a;return!1};g.padding=function(a){s(a)&&a!==ca&&(ca=a,k());return!1};g.paddingLeft=function(a){s(a)&&a!==jb&&(jb=a,k());return!1};g.align=function(a){u={left:0,center:0.5,right:1}[a];return!1};g.text=function(a,b){n.attr(b,a);j();k();return!1};g[Qb]=function(a,b){y=!0;G=a%2/2;l(b,a);return!1};g.stroke=g.fill=g.r=function(a,b){b===\"fill\"&&(y=!0);l(b,a);return!1};g.anchorX=function(a,b){e=a;l(b,a+G-H);return!1};\ng.anchorY=function(a,b){f=a;l(b,a-ya);return!1};g.x=function(a){q.x=a;a-=u*((Oa||F.width)+ca);H=t(a);q.attr(\"translateX\",H);return!1};g.y=function(a){ya=q.y=t(a);q.attr(\"translateY\",ya);return!1};var z=q.css;return r(q,{css:function(a){if(a){var b={},a=w(a);o(\"fontSize,fontWeight,fontFamily,color,lineHeight,width,textDecoration\".split(\",\"),function(c){a[c]!==v&&(b[c]=a[c],delete a[c])});n.css(b)}return z.call(q,a)},getBBox:function(){return{width:F.width+2*ca,height:F.height+2*ca,x:F.x-ca,y:F.y-ca}},\nshadow:function(a){C&&C.shadow(a);return q},destroy:function(){aa(q,\"add\",m);aa(q.element,\"mouseenter\");aa(q.element,\"mouseleave\");n&&(n=n.destroy());C&&(C=C.destroy());va.prototype.destroy.call(q);q=p=j=k=l=m=null}})}};Va=Ga;var K;if(!Y&&!Z){Highcharts.VMLElement=K={init:function(a,b){var c=[\"<\",b,' filled=\"f\" stroked=\"f\"'],d=[\"position: \",\"absolute\",\";\"],e=b===Ca;(b===\"shape\"||e)&&d.push(\"left:0;top:0;width:1px;height:1px;\");d.push(\"visibility: \",e?\"hidden\":\"visible\");c.push(' style=\"',d.join(\"\"),\n'\"/>');if(b)c=e||b===\"span\"||b===\"img\"?c.join(\"\"):a.prepVML(c),this.element=T(c);this.renderer=a;this.attrSetters={}},add:function(a){var b=this.renderer,c=this.element,d=b.box,d=a?a.element||a:d;a&&a.inverted&&b.invertChild(c,d);d.appendChild(c);this.added=!0;this.alignOnAdd&&!this.deferUpdateTransform&&this.updateTransform();B(this,\"add\");return this},updateTransform:va.prototype.htmlUpdateTransform,setSpanRotation:function(a,b,c){M(this.element,{filter:a?[\"progid:DXImageTransform.Microsoft.Matrix(M11=\",\nc,\", M12=\",-b,\", M21=\",b,\", M22=\",c,\", sizingMethod='auto expand')\"].join(\"\"):R})},attr:function(a,b){var c,d,e,f=this.element||{},g=f.style,h=f.nodeName,i=this.renderer,j=this.symbolName,k,l=this.shadows,m,p=this.attrSetters,q=this;da(a)&&s(b)&&(c=a,a={},a[c]=b);if(da(a))c=a,q=c===\"strokeWidth\"||c===\"stroke-width\"?this.strokeweight:this[c];else for(c in a)if(d=a[c],m=!1,e=p[c]&&p[c].call(this,d,c),e!==!1&&d!==null){e!==v&&(d=e);if(j&&/^(x|y|r|start|end|width|height|innerR|anchorX|anchorY)/.test(c))k||\n(this.symbolAttr(a),k=!0),m=!0;else if(c===\"d\"){d=d||[];this.d=d.join(\" \");e=d.length;m=[];for(var n;e--;)if(pa(d[e]))m[e]=t(d[e]*10)-5;else if(d[e]===\"Z\")m[e]=\"x\";else if(m[e]=d[e],d.isArc&&(d[e]===\"wa\"||d[e]===\"at\"))n=d[e]===\"wa\"?1:-1,m[e+5]===m[e+7]&&(m[e+7]-=n),m[e+6]===m[e+8]&&(m[e+8]-=n);d=m.join(\" \")||\"x\";f.path=d;if(l)for(e=l.length;e--;)l[e].path=l[e].cutOff?this.cutOffPath(d,l[e].cutOff):d;m=!0}else if(c===\"visibility\"){if(l)for(e=l.length;e--;)l[e].style[c]=d;h===\"DIV\"&&(d=d===\"hidden\"?\n\"-999em\":0,eb||(g[c]=d?\"visible\":\"hidden\"),c=\"top\");g[c]=d;m=!0}else if(c===\"zIndex\")d&&(g[c]=d),m=!0;else if(na(c,[\"x\",\"y\",\"width\",\"height\"])!==-1)this[c]=d,c===\"x\"||c===\"y\"?c={x:\"left\",y:\"top\"}[c]:d=u(0,d),this.updateClipping?(this[c]=d,this.updateClipping()):g[c]=d,m=!0;else if(c===\"class\"&&h===\"DIV\")f.className=d;else if(c===\"stroke\")d=i.color(d,f,c),c=\"strokecolor\";else if(c===\"stroke-width\"||c===\"strokeWidth\")f.stroked=d?!0:!1,c=\"strokeweight\",this[c]=d,pa(d)&&(d+=\"px\");else if(c===\"dashstyle\")(f.getElementsByTagName(\"stroke\")[0]||\nT(i.prepVML([\"<stroke/>\"]),null,null,f))[c]=d||\"solid\",this.dashstyle=d,m=!0;else if(c===\"fill\")if(h===\"SPAN\")g.color=d;else{if(h!==\"IMG\")f.filled=d!==R?!0:!1,d=i.color(d,f,c,this),c=\"fillcolor\"}else if(c===\"opacity\")m=!0;else if(h===\"shape\"&&c===\"rotation\")this[c]=f.style[c]=d,f.style.left=-t(ba(d*Ua)+1)+\"px\",f.style.top=t(V(d*Ua))+\"px\";else if(c===\"translateX\"||c===\"translateY\"||c===\"rotation\")this[c]=d,this.updateTransform(),m=!0;else if(c===\"text\")this.bBox=null,f.innerHTML=d,m=!0;m||(eb?f[c]=\nd:x(f,c,d))}return q},clip:function(a){var b=this,c;a?(c=a.members,fa(c,b),c.push(b),b.destroyClip=function(){fa(c,b)},a=a.getCSS(b)):(b.destroyClip&&b.destroyClip(),a={clip:eb?\"inherit\":\"rect(auto)\"});return b.css(a)},css:va.prototype.htmlCss,safeRemoveChild:function(a){a.parentNode&&Ta(a)},destroy:function(){this.destroyClip&&this.destroyClip();return va.prototype.destroy.apply(this)},on:function(a,b){this.element[\"on\"+a]=function(){var a=E.event;a.target=a.srcElement;b(a)};return this},cutOffPath:function(a,\nb){var c,a=a.split(/[ ,]/);c=a.length;if(c===9||c===11)a[c-4]=a[c-2]=A(a[c-2])-10*b;return a.join(\" \")},shadow:function(a,b,c){var d=[],e,f=this.element,g=this.renderer,h,i=f.style,j,k=f.path,l,m,p,q;k&&typeof k.value!==\"string\"&&(k=\"x\");m=k;if(a){p=n(a.width,3);q=(a.opacity||0.15)/p;for(e=1;e<=3;e++){l=p*2+1-2*e;c&&(m=this.cutOffPath(k.value,l+0.5));j=['<shape isShadow=\"true\" strokeweight=\"',l,'\" filled=\"false\" path=\"',m,'\" coordsize=\"10 10\" style=\"',f.style.cssText,'\" />'];h=T(g.prepVML(j),null,\n{left:A(i.left)+n(a.offsetX,1),top:A(i.top)+n(a.offsetY,1)});if(c)h.cutOff=l+1;j=['<stroke color=\"',a.color||\"black\",'\" opacity=\"',q*e,'\"/>'];T(g.prepVML(j),null,null,h);b?b.element.appendChild(h):f.parentNode.insertBefore(h,f);d.push(h)}this.shadows=d}return this}};K=ga(va,K);var la={Element:K,isIE8:Ea.indexOf(\"MSIE 8.0\")>-1,init:function(a,b,c){var d,e;this.alignedObjects=[];d=this.createElement(Ca);e=d.element;e.style.position=\"relative\";a.appendChild(d.element);this.isVML=!0;this.box=e;this.boxWrapper=\nd;this.setSize(b,c,!1);if(!y.namespaces.hcv)y.namespaces.add(\"hcv\",\"urn:schemas-microsoft-com:vml\"),y.createStyleSheet().cssText=\"hcv\\\\:fill, hcv\\\\:path, hcv\\\\:shape, hcv\\\\:stroke{ behavior:url(#default#VML); display: inline-block; } \"},isHidden:function(){return!this.box.offsetWidth},clipRect:function(a,b,c,d){var e=this.createElement(),f=U(a);return r(e,{members:[],left:f?a.x:a,top:f?a.y:b,width:f?a.width:c,height:f?a.height:d,getCSS:function(a){var b=a.element,c=b.nodeName,a=a.inverted,d=this.top-\n(c===\"shape\"?b.offsetTop:0),e=this.left,b=e+this.width,f=d+this.height,d={clip:\"rect(\"+t(a?e:d)+\"px,\"+t(a?f:b)+\"px,\"+t(a?b:f)+\"px,\"+t(a?d:e)+\"px)\"};!a&&eb&&c===\"DIV\"&&r(d,{width:b+\"px\",height:f+\"px\"});return d},updateClipping:function(){o(e.members,function(a){a.css(e.getCSS(a))})}})},color:function(a,b,c,d){var e=this,f,g=/^rgba/,h,i,j=R;a&&a.linearGradient?i=\"gradient\":a&&a.radialGradient&&(i=\"pattern\");if(i){var k,l,m=a.linearGradient||a.radialGradient,p,q,n,C,F,u=\"\",a=a.stops,s,t=[],v=function(){h=\n['<fill colors=\"'+t.join(\",\")+'\" opacity=\"',n,'\" o:opacity2=\"',q,'\" type=\"',i,'\" ',u,'focus=\"100%\" method=\"any\" />'];T(e.prepVML(h),null,null,b)};p=a[0];s=a[a.length-1];p[0]>0&&a.unshift([0,p[1]]);s[0]<1&&a.push([1,s[1]]);o(a,function(a,b){g.test(a[1])?(f=oa(a[1]),k=f.get(\"rgb\"),l=f.get(\"a\")):(k=a[1],l=1);t.push(a[0]*100+\"% \"+k);b?(n=l,C=k):(q=l,F=k)});if(c===\"fill\")if(i===\"gradient\")c=m.x1||m[0]||0,a=m.y1||m[1]||0,p=m.x2||m[2]||0,m=m.y2||m[3]||0,u='angle=\"'+(90-N.atan((m-a)/(p-c))*180/Ma)+'\"',v();\nelse{var j=m.r,D=j*2,H=j*2,r=m.cx,G=m.cy,x=b.radialReference,w,j=function(){x&&(w=d.getBBox(),r+=(x[0]-w.x)/w.width-0.5,G+=(x[1]-w.y)/w.height-0.5,D*=x[2]/w.width,H*=x[2]/w.height);u='src=\"'+O.global.VMLRadialGradientURL+'\" size=\"'+D+\",\"+H+'\" origin=\"0.5,0.5\" position=\"'+r+\",\"+G+'\" color2=\"'+F+'\" ';v()};d.added?j():J(d,\"add\",j);j=C}else j=k}else if(g.test(a)&&b.tagName!==\"IMG\")f=oa(a),h=[\"<\",c,' opacity=\"',f.get(\"a\"),'\"/>'],T(this.prepVML(h),null,null,b),j=f.get(\"rgb\");else{j=b.getElementsByTagName(c);\nif(j.length)j[0].opacity=1,j[0].type=\"solid\";j=a}return j},prepVML:function(a){var b=this.isIE8,a=a.join(\"\");b?(a=a.replace(\"/>\",' xmlns=\"urn:schemas-microsoft-com:vml\" />'),a=a.indexOf('style=\"')===-1?a.replace(\"/>\",' style=\"display:inline-block;behavior:url(#default#VML);\" />'):a.replace('style=\"','style=\"display:inline-block;behavior:url(#default#VML);')):a=a.replace(\"<\",\"<hcv:\");return a},text:Ga.prototype.html,path:function(a){var b={coordsize:\"10 10\"};Ha(a)?b.d=a:U(a)&&r(b,a);return this.createElement(\"shape\").attr(b)},\ncircle:function(a,b,c){var d=this.symbol(\"circle\");if(U(a))c=a.r,b=a.y,a=a.x;d.isCircle=!0;return d.attr({x:a,y:b,width:2*c,height:2*c})},g:function(a){var b;a&&(b={className:\"highcharts-\"+a,\"class\":\"highcharts-\"+a});return this.createElement(Ca).attr(b)},image:function(a,b,c,d,e){var f=this.createElement(\"img\").attr({src:a});arguments.length>1&&f.attr({x:b,y:c,width:d,height:e});return f},rect:function(a,b,c,d,e,f){if(U(a))b=a.y,c=a.width,d=a.height,f=a.strokeWidth,a=a.x;var g=this.symbol(\"rect\");\ng.r=e;return g.attr(g.crisp(f,a,b,u(c,0),u(d,0)))},invertChild:function(a,b){var c=b.style;M(a,{flip:\"x\",left:A(c.width)-1,top:A(c.height)-1,rotation:-90})},symbols:{arc:function(a,b,c,d,e){var f=e.start,g=e.end,h=e.r||c||d,c=e.innerR,d=V(f),i=ba(f),j=V(g),k=ba(g);if(g-f===0)return[\"x\"];f=[\"wa\",a-h,b-h,a+h,b+h,a+h*d,b+h*i,a+h*j,b+h*k];e.open&&!c&&f.push(\"e\",\"M\",a,b);f.push(\"at\",a-c,b-c,a+c,b+c,a+c*j,b+c*k,a+c*d,b+c*i,\"x\",\"e\");f.isArc=!0;return f},circle:function(a,b,c,d,e){e&&e.isCircle&&(a-=c/2,\nb-=d/2);return[\"wa\",a,b,a+c,b+d,a+c,b+d/2,a+c,b+d/2,\"e\"]},rect:function(a,b,c,d,e){var f=a+c,g=b+d,h;!s(e)||!e.r?f=Ga.prototype.symbols.square.apply(0,arguments):(h=I(e.r,c,d),f=[\"M\",a+h,b,\"L\",f-h,b,\"wa\",f-2*h,b,f,b+2*h,f-h,b,f,b+h,\"L\",f,g-h,\"wa\",f-2*h,g-2*h,f,g,f,g-h,f-h,g,\"L\",a+h,g,\"wa\",a,g-2*h,a+2*h,g,a+h,g,a,g-h,\"L\",a,b+h,\"wa\",a,b,a+2*h,b+2*h,a,b+h,a+h,b,\"x\",\"e\"]);return f}}};Highcharts.VMLRenderer=K=function(){this.init.apply(this,arguments)};K.prototype=w(Ga.prototype,la);Va=K}var Tb;if(Z)Highcharts.CanVGRenderer=\nK=function(){wa=\"http://www.w3.org/1999/xhtml\"},K.prototype.symbols={},Tb=function(){function a(){var a=b.length,d;for(d=0;d<a;d++)b[d]();b=[]}var b=[];return{push:function(c,d){b.length===0&&Vb(d,a);b.push(c)}}}(),Va=K;La.prototype={addLabel:function(){var a=this.axis,b=a.options,c=a.chart,d=a.horiz,e=a.categories,f=a.series[0]&&a.series[0].names,g=this.pos,h=b.labels,i=a.tickPositions,d=d&&e&&!h.step&&!h.staggerLines&&!h.rotation&&c.plotWidth/i.length||!d&&(c.optionsMarginLeft||c.chartWidth*0.33),\nj=g===i[0],k=g===i[i.length-1],f=e?n(e[g],f&&f[g],g):g,e=this.label,i=i.info,l;a.isDatetimeAxis&&i&&(l=b.dateTimeLabelFormats[i.higherRanks[g]||i.unitName]);this.isFirst=j;this.isLast=k;b=a.labelFormatter.call({axis:a,chart:c,isFirst:j,isLast:k,dateTimeLabelFormat:l,value:a.isLog?ia(ea(f)):f});g=d&&{width:u(1,t(d-2*(h.padding||10)))+\"px\"};g=r(g,h.style);if(s(e))e&&e.attr({text:b}).css(g);else{d={align:a.labelAlign};if(pa(h.rotation))d.rotation=h.rotation;this.label=s(b)&&h.enabled?c.renderer.text(b,\n0,0,h.useHTML).attr(d).css(g).add(a.labelGroup):null}},getLabelSize:function(){var a=this.label,b=this.axis;return a?(this.labelBBox=a.getBBox())[b.horiz?\"height\":\"width\"]:0},getLabelSides:function(){var a=this.axis,b=this.labelBBox.width,a=b*{left:0,center:0.5,right:1}[a.labelAlign]-a.options.labels.x;return[-a,b-a]},handleOverflow:function(a,b){var c=!0,d=this.axis,e=d.chart,f=this.isFirst,g=this.isLast,h=b.x,i=d.reversed,j=d.tickPositions;if(f||g){var k=this.getLabelSides(),l=k[0],k=k[1],e=e.plotLeft,\nm=e+d.len,j=(d=d.ticks[j[a+(f?1:-1)]])&&d.label.xy&&d.label.xy.x+d.getLabelSides()[f?0:1];f&&!i||g&&i?h+l<e&&(h=e-l,d&&h+k>j&&(c=!1)):h+k>m&&(h=m-k,d&&h+l<j&&(c=!1));b.x=h}return c},getPosition:function(a,b,c,d){var e=this.axis,f=e.chart,g=d&&f.oldChartHeight||f.chartHeight;return{x:a?e.translate(b+c,null,null,d)+e.transB:e.left+e.offset+(e.opposite?(d&&f.oldChartWidth||f.chartWidth)-e.right-e.left:0),y:a?g-e.bottom+e.offset-(e.opposite?e.height:0):g-e.translate(b+c,null,null,d)-e.transB}},getLabelPosition:function(a,\nb,c,d,e,f,g,h){var i=this.axis,j=i.transA,k=i.reversed,l=i.staggerLines,m=i.chart.renderer.fontMetrics(e.style.fontSize).b,p=e.rotation,a=a+e.x-(f&&d?f*j*(k?-1:1):0),b=b+e.y-(f&&!d?f*j*(k?1:-1):0);p&&i.side===2&&(b-=m-m*V(p*Ua));!s(e.y)&&!p&&(b+=m-c.getBBox().height/2);l&&(b+=g/(h||1)%l*(i.labelOffset/l));return{x:a,y:b}},getMarkPath:function(a,b,c,d,e,f){return f.crispLine([\"M\",a,b,\"L\",a+(e?0:-c),b+(e?c:0)],d)},render:function(a,b,c){var d=this.axis,e=d.options,f=d.chart.renderer,g=d.horiz,h=this.type,\ni=this.label,j=this.pos,k=e.labels,l=this.gridLine,m=h?h+\"Grid\":\"grid\",p=h?h+\"Tick\":\"tick\",q=e[m+\"LineWidth\"],o=e[m+\"LineColor\"],C=e[m+\"LineDashStyle\"],F=e[p+\"Length\"],m=e[p+\"Width\"]||0,u=e[p+\"Color\"],s=e[p+\"Position\"],p=this.mark,t=k.step,r=!0,D=d.tickmarkOffset,H=this.getPosition(g,j,D,b),w=H.x,H=H.y,G=g&&w===d.pos||!g&&H===d.pos+d.len?-1:1,x=d.staggerLines;this.isActive=!0;if(q){j=d.getPlotLinePath(j+D,q*G,b,!0);if(l===v){l={stroke:o,\"stroke-width\":q};if(C)l.dashstyle=C;if(!h)l.zIndex=1;if(b)l.opacity=\n0;this.gridLine=l=q?f.path(j).attr(l).add(d.gridGroup):null}if(!b&&l&&j)l[this.isNew?\"attr\":\"animate\"]({d:j,opacity:c})}if(m&&F)s===\"inside\"&&(F=-F),d.opposite&&(F=-F),b=this.getMarkPath(w,H,F,m*G,g,f),p?p.animate({d:b,opacity:c}):this.mark=f.path(b).attr({stroke:u,\"stroke-width\":m,opacity:c}).add(d.axisGroup);if(i&&!isNaN(w))i.xy=H=this.getLabelPosition(w,H,i,g,k,D,a,t),this.isFirst&&!n(e.showFirstLabel,1)||this.isLast&&!n(e.showLastLabel,1)?r=!1:!x&&g&&k.overflow===\"justify\"&&!this.handleOverflow(a,\nH)&&(r=!1),t&&a%t&&(r=!1),r&&!isNaN(H.y)?(H.opacity=c,i[this.isNew?\"attr\":\"animate\"](H),this.isNew=!1):i.attr(\"y\",-9999)},destroy:function(){Ja(this,this.axis)}};sb.prototype={render:function(){var a=this,b=a.axis,c=b.horiz,d=(b.pointRange||0)/2,e=a.options,f=e.label,g=a.label,h=e.width,i=e.to,j=e.from,k=s(j)&&s(i),l=e.value,m=e.dashStyle,p=a.svgElem,q=[],o,C=e.color,F=e.zIndex,t=e.events,r=b.chart.renderer;b.isLog&&(j=ma(j),i=ma(i),l=ma(l));if(h){if(q=b.getPlotLinePath(l,h),d={stroke:C,\"stroke-width\":h},\nm)d.dashstyle=m}else if(k){if(j=u(j,b.min-d),i=I(i,b.max+d),q=b.getPlotBandPath(j,i,e),d={fill:C},e.borderWidth)d.stroke=e.borderColor,d[\"stroke-width\"]=e.borderWidth}else return;if(s(F))d.zIndex=F;if(p)q?p.animate({d:q},null,p.onGetPath):(p.hide(),p.onGetPath=function(){p.show()});else if(q&&q.length&&(a.svgElem=p=r.path(q).attr(d).add(),t))for(o in e=function(b){p.on(b,function(c){t[b].apply(a,[c])})},t)e(o);if(f&&s(f.text)&&q&&q.length&&b.width>0&&b.height>0){f=w({align:c&&k&&\"center\",x:c?!k&&\n4:10,verticalAlign:!c&&k&&\"middle\",y:c?k?16:10:k?6:-4,rotation:c&&!k&&90},f);if(!g)a.label=g=r.text(f.text,0,0,f.useHTML).attr({align:f.textAlign||f.align,rotation:f.rotation,zIndex:F}).css(f.style).add();b=[q[1],q[4],n(q[6],q[1])];q=[q[2],q[5],n(q[7],q[2])];c=Ia(b);k=Ia(q);g.align(f,!1,{x:c,y:k,width:ta(b)-c,height:ta(q)-k});g.show()}else g&&g.hide();return a},destroy:function(){fa(this.axis.plotLinesAndBands,this);Ja(this,this.axis)}};Lb.prototype={destroy:function(){Ja(this,this.axis)},setTotal:function(a){this.cum=\nthis.total=a},addValue:function(a){this.setTotal(ia(this.total+a))},render:function(a){var b=this.options,c=b.format,c=c?Ba(c,this):b.formatter.call(this);this.label?this.label.attr({text:c,visibility:\"hidden\"}):this.label=this.axis.chart.renderer.text(c,0,0,b.useHTML).css(b.style).attr({align:this.textAlign,rotation:b.rotation,visibility:\"hidden\"}).add(a)},cacheExtremes:function(a,b){this.points[a.index]=b},setOffset:function(a,b){var c=this.axis,d=c.chart,e=d.inverted,f=this.isNegative,g=c.translate(this.percent?\n100:this.total,0,0,0,1),c=c.translate(0),c=P(g-c),h=d.xAxis[0].translate(this.x)+a,i=d.plotHeight,f={x:e?f?g:g-c:h,y:e?i-h-b:f?i-g-c:i-g,width:e?c:b,height:e?b:c};if(e=this.label)e.align(this.alignOptions,null,f),f=e.alignAttr,e.attr({visibility:this.options.crop===!1||d.isInsidePlot(f.x,f.y)?Y?\"inherit\":\"visible\":\"hidden\"})}};db.prototype={defaultOptions:{dateTimeLabelFormats:{millisecond:\"%H:%M:%S.%L\",second:\"%H:%M:%S\",minute:\"%H:%M\",hour:\"%H:%M\",day:\"%e. %b\",week:\"%e. %b\",month:\"%b '%y\",year:\"%Y\"},\nendOnTick:!1,gridLineColor:\"#C0C0C0\",labels:L,lineColor:\"#C0D0E0\",lineWidth:1,minPadding:0.01,maxPadding:0.01,minorGridLineColor:\"#E0E0E0\",minorGridLineWidth:1,minorTickColor:\"#A0A0A0\",minorTickLength:2,minorTickPosition:\"outside\",startOfWeek:1,startOnTick:!1,tickColor:\"#C0D0E0\",tickLength:5,tickmarkPlacement:\"between\",tickPixelInterval:100,tickPosition:\"outside\",tickWidth:1,title:{align:\"middle\",style:{color:\"#4d759e\",fontWeight:\"bold\"}},type:\"linear\"},defaultYAxisOptions:{endOnTick:!0,gridLineWidth:1,\ntickPixelInterval:72,showLastLabel:!0,labels:{x:-8,y:3},lineWidth:0,maxPadding:0.05,minPadding:0.05,startOnTick:!0,tickWidth:0,title:{rotation:270,text:\"Values\"},stackLabels:{enabled:!1,formatter:function(){return za(this.total,-1)},style:L.style}},defaultLeftAxisOptions:{labels:{x:-8,y:null},title:{rotation:270}},defaultRightAxisOptions:{labels:{x:8,y:null},title:{rotation:90}},defaultBottomAxisOptions:{labels:{x:0,y:14},title:{rotation:0}},defaultTopAxisOptions:{labels:{x:0,y:-5},title:{rotation:0}},\ninit:function(a,b){var c=b.isX;this.horiz=a.inverted?!c:c;this.xOrY=(this.isXAxis=c)?\"x\":\"y\";this.opposite=b.opposite;this.side=this.horiz?this.opposite?0:2:this.opposite?1:3;this.setOptions(b);var d=this.options,e=d.type;this.labelFormatter=d.labels.formatter||this.defaultLabelFormatter;this.userOptions=b;this.minPixelPadding=0;this.chart=a;this.reversed=d.reversed;this.zoomEnabled=d.zoomEnabled!==!1;this.categories=d.categories||e===\"category\";this.isLog=e===\"logarithmic\";this.isDatetimeAxis=e===\n\"datetime\";this.isLinked=s(d.linkedTo);this.tickmarkOffset=this.categories&&d.tickmarkPlacement===\"between\"?0.5:0;this.ticks={};this.minorTicks={};this.plotLinesAndBands=[];this.alternateBands={};this.len=0;this.minRange=this.userMinRange=d.minRange||d.maxZoom;this.range=d.range;this.offset=d.offset||0;this.stacks={};this.oldStacks={};this.stacksMax={};this._stacksTouched=0;this.min=this.max=null;var f,d=this.options.events;na(this,a.axes)===-1&&(a.axes.push(this),a[c?\"xAxis\":\"yAxis\"].push(this));\nthis.series=this.series||[];if(a.inverted&&c&&this.reversed===v)this.reversed=!0;this.removePlotLine=this.removePlotBand=this.removePlotBandOrLine;for(f in d)J(this,f,d[f]);if(this.isLog)this.val2lin=ma,this.lin2val=ea},setOptions:function(a){this.options=w(this.defaultOptions,this.isXAxis?{}:this.defaultYAxisOptions,[this.defaultTopAxisOptions,this.defaultRightAxisOptions,this.defaultBottomAxisOptions,this.defaultLeftAxisOptions][this.side],w(O[this.isXAxis?\"xAxis\":\"yAxis\"],a))},update:function(a,\nb){var c=this.chart,a=c.options[this.xOrY+\"Axis\"][this.options.index]=w(this.userOptions,a);this.destroy(!0);this._addedPlotLB=!1;this.init(c,r(a,{events:v}));c.isDirtyBox=!0;n(b,!0)&&c.redraw()},remove:function(a){var b=this.chart,c=this.xOrY+\"Axis\";o(this.series,function(a){a.remove(!1)});fa(b.axes,this);fa(b[c],this);b.options[c].splice(this.options.index,1);o(b[c],function(a,b){a.options.index=b});this.destroy();b.isDirtyBox=!0;n(a,!0)&&b.redraw()},defaultLabelFormatter:function(){var a=this.axis,\nb=this.value,c=a.categories,d=this.dateTimeLabelFormat,e=O.lang.numericSymbols,f=e&&e.length,g,h=a.options.labels.format,a=a.isLog?b:a.tickInterval;if(h)g=Ba(h,this);else if(c)g=b;else if(d)g=Xa(d,b);else if(f&&a>=1E3)for(;f--&&g===v;)c=Math.pow(1E3,f+1),a>=c&&e[f]!==null&&(g=za(b/c,-1)+e[f]);g===v&&(g=b>=1E3?za(b,0):za(b,-1));return g},getSeriesExtremes:function(){var a=this,b=a.chart;a.hasVisibleSeries=!1;a.dataMin=a.dataMax=null;a.stacksMax={};a.buildStacks();o(a.series,function(c){if(c.visible||\n!b.options.chart.ignoreHiddenSeries){var d=c.options,e;e=d.threshold;a.hasVisibleSeries=!0;a.isLog&&e<=0&&(e=null);if(a.isXAxis){if(e=c.xData,e.length)a.dataMin=I(n(a.dataMin,e[0]),Ia(e)),a.dataMax=u(n(a.dataMax,e[0]),ta(e))}else{d=d.stacking;a.usePercentage=d===\"percent\";if(a.usePercentage)a.dataMin=0,a.dataMax=99;c.getExtremes();d=c.dataMax;c=c.dataMin;if(!a.usePercentage&&s(c)&&s(d))a.dataMin=I(n(a.dataMin,c),c),a.dataMax=u(n(a.dataMax,d),d);if(s(e))if(a.dataMin>=e)a.dataMin=e,a.ignoreMinPadding=\n!0;else if(a.dataMax<e)a.dataMax=e,a.ignoreMaxPadding=!0}}})},translate:function(a,b,c,d,e,f){var g=this.len,h=1,i=0,j=d?this.oldTransA:this.transA,d=d?this.oldMin:this.min,k=this.minPixelPadding,e=(this.options.ordinal||this.isLog&&e)&&this.lin2val;if(!j)j=this.transA;c&&(h*=-1,i=g);this.reversed&&(h*=-1,i-=h*g);b?(a=a*h+i,a-=k,a=a/j+d,e&&(a=this.lin2val(a))):(e&&(a=this.val2lin(a)),f===\"between\"&&(f=0.5),a=h*(a-d)*j+i+h*k+(pa(f)?j*f*this.pointRange:0));return a},toPixels:function(a,b){return this.translate(a,\n!1,!this.horiz,null,!0)+(b?0:this.pos)},toValue:function(a,b){return this.translate(a-(b?0:this.pos),!0,!this.horiz,null,!0)},getPlotLinePath:function(a,b,c,d){var e=this.chart,f=this.left,g=this.top,h,i,j,a=this.translate(a,null,null,c),k=c&&e.oldChartHeight||e.chartHeight,l=c&&e.oldChartWidth||e.chartWidth,m;h=this.transB;c=i=t(a+h);h=j=t(k-a-h);if(isNaN(a))m=!0;else if(this.horiz){if(h=g,j=k-this.bottom,c<f||c>f+this.width)m=!0}else if(c=f,i=l-this.right,h<g||h>g+this.height)m=!0;return m&&!d?\nnull:e.renderer.crispLine([\"M\",c,h,\"L\",i,j],b||0)},getPlotBandPath:function(a,b){var c=this.getPlotLinePath(b),d=this.getPlotLinePath(a);d&&c?d.push(c[4],c[5],c[1],c[2]):d=null;return d},getLinearTickPositions:function(a,b,c){for(var d,b=ia(S(b/a)*a),c=ia(ja(c/a)*a),e=[];b<=c;){e.push(b);b=ia(b+a);if(b===d)break;d=b}return e},getLogTickPositions:function(a,b,c,d){var e=this.options,f=this.len,g=[];if(!d)this._minorAutoInterval=null;if(a>=0.5)a=t(a),g=this.getLinearTickPositions(a,b,c);else if(a>=\n0.08)for(var f=S(b),h,i,j,k,l,e=a>0.3?[1,2,4]:a>0.15?[1,2,4,6,8]:[1,2,3,4,5,6,7,8,9];f<c+1&&!l;f++){i=e.length;for(h=0;h<i&&!l;h++)j=ma(ea(f)*e[h]),j>b&&(!d||k<=c)&&g.push(k),k>c&&(l=!0),k=j}else if(b=ea(b),c=ea(c),a=e[d?\"minorTickInterval\":\"tickInterval\"],a=n(a===\"auto\"?null:a,this._minorAutoInterval,(c-b)*(e.tickPixelInterval/(d?5:1))/((d?f/this.tickPositions.length:f)||1)),a=lb(a,null,kb(a)),g=Na(this.getLinearTickPositions(a,b,c),ma),!d)this._minorAutoInterval=a/5;if(!d)this.tickInterval=a;return g},\ngetMinorTickPositions:function(){var a=this.options,b=this.tickPositions,c=this.minorTickInterval,d=[],e;if(this.isLog){e=b.length;for(a=1;a<e;a++)d=d.concat(this.getLogTickPositions(c,b[a-1],b[a],!0))}else if(this.isDatetimeAxis&&a.minorTickInterval===\"auto\")d=d.concat(Db(Bb(c),this.min,this.max,a.startOfWeek)),d[0]<this.min&&d.shift();else for(b=this.min+(b[0]-this.min)%c;b<=this.max;b+=c)d.push(b);return d},adjustForMinRange:function(){var a=this.options,b=this.min,c=this.max,d,e=this.dataMax-\nthis.dataMin>=this.minRange,f,g,h,i,j;if(this.isXAxis&&this.minRange===v&&!this.isLog)s(a.min)||s(a.max)?this.minRange=null:(o(this.series,function(a){i=a.xData;for(g=j=a.xIncrement?1:i.length-1;g>0;g--)if(h=i[g]-i[g-1],f===v||h<f)f=h}),this.minRange=I(f*5,this.dataMax-this.dataMin));if(c-b<this.minRange){var k=this.minRange;d=(k-c+b)/2;d=[b-d,n(a.min,b-d)];if(e)d[2]=this.dataMin;b=ta(d);c=[b+k,n(a.max,b+k)];if(e)c[2]=this.dataMax;c=Ia(c);c-b<k&&(d[0]=c-k,d[1]=n(a.min,c-k),b=ta(d))}this.min=b;this.max=\nc},setAxisTranslation:function(a){var b=this.max-this.min,c=0,d,e=0,f=0,g=this.linkedParent,h=this.transA;if(this.isXAxis)g?(e=g.minPointOffset,f=g.pointRangePadding):o(this.series,function(a){var g=a.pointRange,h=a.options.pointPlacement,l=a.closestPointRange;g>b&&(g=0);c=u(c,g);e=u(e,da(h)?0:g/2);f=u(f,h===\"on\"?0:g);!a.noSharedTooltip&&s(l)&&(d=s(d)?I(d,l):l)}),g=this.ordinalSlope&&d?this.ordinalSlope/d:1,this.minPointOffset=e*=g,this.pointRangePadding=f*=g,this.pointRange=I(c,b),this.closestPointRange=\nd;if(a)this.oldTransA=h;this.translationSlope=this.transA=h=this.len/(b+f||1);this.transB=this.horiz?this.left:this.bottom;this.minPixelPadding=h*e},setTickPositions:function(a){var b=this,c=b.chart,d=b.options,e=b.isLog,f=b.isDatetimeAxis,g=b.isXAxis,h=b.isLinked,i=b.options.tickPositioner,j=d.maxPadding,k=d.minPadding,l=d.tickInterval,m=d.minTickInterval,p=d.tickPixelInterval,q=b.categories;h?(b.linkedParent=c[g?\"xAxis\":\"yAxis\"][d.linkedTo],c=b.linkedParent.getExtremes(),b.min=n(c.min,c.dataMin),\nb.max=n(c.max,c.dataMax),d.type!==b.linkedParent.options.type&&ua(11,1)):(b.min=n(b.userMin,d.min,b.dataMin),b.max=n(b.userMax,d.max,b.dataMax));if(e)!a&&I(b.min,n(b.dataMin,b.min))<=0&&ua(10,1),b.min=ia(ma(b.min)),b.max=ia(ma(b.max));if(b.range&&(b.userMin=b.min=u(b.min,b.max-b.range),b.userMax=b.max,a))b.range=null;b.beforePadding&&b.beforePadding();b.adjustForMinRange();if(!q&&!b.usePercentage&&!h&&s(b.min)&&s(b.max)&&(c=b.max-b.min)){if(!s(d.min)&&!s(b.userMin)&&k&&(b.dataMin<0||!b.ignoreMinPadding))b.min-=\nc*k;if(!s(d.max)&&!s(b.userMax)&&j&&(b.dataMax>0||!b.ignoreMaxPadding))b.max+=c*j}b.tickInterval=b.min===b.max||b.min===void 0||b.max===void 0?1:h&&!l&&p===b.linkedParent.options.tickPixelInterval?b.linkedParent.tickInterval:n(l,q?1:(b.max-b.min)*p/(b.len||1));g&&!a&&o(b.series,function(a){a.processData(b.min!==b.oldMin||b.max!==b.oldMax)});b.setAxisTranslation(!0);b.beforeSetTickPositions&&b.beforeSetTickPositions();if(b.postProcessTickInterval)b.tickInterval=b.postProcessTickInterval(b.tickInterval);\nif(b.pointRange)b.tickInterval=u(b.pointRange,b.tickInterval);if(!l&&b.tickInterval<m)b.tickInterval=m;if(!f&&!e&&!l)b.tickInterval=lb(b.tickInterval,null,kb(b.tickInterval),d);b.minorTickInterval=d.minorTickInterval===\"auto\"&&b.tickInterval?b.tickInterval/5:d.minorTickInterval;b.tickPositions=a=d.tickPositions?[].concat(d.tickPositions):i&&i.apply(b,[b.min,b.max]);if(!a)a=f?(b.getNonLinearTimeTicks||Db)(Bb(b.tickInterval,d.units),b.min,b.max,d.startOfWeek,b.ordinalPositions,b.closestPointRange,!0):\ne?b.getLogTickPositions(b.tickInterval,b.min,b.max):b.getLinearTickPositions(b.tickInterval,b.min,b.max),b.tickPositions=a;if(!h)e=a[0],f=a[a.length-1],h=b.minPointOffset||0,d.startOnTick?b.min=e:b.min-h>e&&a.shift(),d.endOnTick?b.max=f:b.max+h<f&&a.pop(),a.length===1&&(b.min-=0.001,b.max+=0.001)},setMaxTicks:function(){var a=this.chart,b=a.maxTicks||{},c=this.tickPositions,d=this._maxTicksKey=[this.xOrY,this.pos,this.len].join(\"-\");if(!this.isLinked&&!this.isDatetimeAxis&&c&&c.length>(b[d]||0)&&\nthis.options.alignTicks!==!1)b[d]=c.length;a.maxTicks=b},adjustTickAmount:function(){var a=this._maxTicksKey,b=this.tickPositions,c=this.chart.maxTicks;if(c&&c[a]&&!this.isDatetimeAxis&&!this.categories&&!this.isLinked&&this.options.alignTicks!==!1){var d=this.tickAmount,e=b.length;this.tickAmount=a=c[a];if(e<a){for(;b.length<a;)b.push(ia(b[b.length-1]+this.tickInterval));this.transA*=(e-1)/(a-1);this.max=b[b.length-1]}if(s(d)&&a!==d)this.isDirty=!0}},setScale:function(){var a=this.stacks,b,c,d,e;\nthis.oldMin=this.min;this.oldMax=this.max;this.oldAxisLength=this.len;this.setAxisSize();e=this.len!==this.oldAxisLength;o(this.series,function(a){if(a.isDirtyData||a.isDirty||a.xAxis.isDirty)d=!0});if(e||d||this.isLinked||this.forceRedraw||this.userMin!==this.oldUserMin||this.userMax!==this.oldUserMax){if(!this.isXAxis)for(b in a)for(c in a[b])a[b][c].total=null;this.forceRedraw=!1;this.getSeriesExtremes();this.setTickPositions();this.oldUserMin=this.userMin;this.oldUserMax=this.userMax;if(!this.isDirty)this.isDirty=\ne||this.min!==this.oldMin||this.max!==this.oldMax}else if(!this.isXAxis){if(this.oldStacks)a=this.stacks=this.oldStacks;for(b in a)for(c in a[b])a[b][c].cum=a[b][c].total}this.setMaxTicks()},setExtremes:function(a,b,c,d,e){var f=this,g=f.chart,c=n(c,!0),e=r(e,{min:a,max:b});B(f,\"setExtremes\",e,function(){f.userMin=a;f.userMax=b;f.isDirtyExtremes=!0;c&&g.redraw(d)})},zoom:function(a,b){this.allowZoomOutside||(s(this.dataMin)&&a<=this.dataMin&&(a=v),s(this.dataMax)&&b>=this.dataMax&&(b=v));this.displayBtn=\na!==v||b!==v;this.setExtremes(a,b,!1,v,{trigger:\"zoom\"});return!0},setAxisSize:function(){var a=this.chart,b=this.options,c=b.offsetLeft||0,d=b.offsetRight||0,e=this.horiz,f,g;this.left=g=n(b.left,a.plotLeft+c);this.top=f=n(b.top,a.plotTop);this.width=c=n(b.width,a.plotWidth-c+d);this.height=b=n(b.height,a.plotHeight);this.bottom=a.chartHeight-b-f;this.right=a.chartWidth-c-g;this.len=u(e?c:b,0);this.pos=e?g:f},getExtremes:function(){var a=this.isLog;return{min:a?ia(ea(this.min)):this.min,max:a?ia(ea(this.max)):\nthis.max,dataMin:this.dataMin,dataMax:this.dataMax,userMin:this.userMin,userMax:this.userMax}},getThreshold:function(a){var b=this.isLog,c=b?ea(this.min):this.min,b=b?ea(this.max):this.max;c>a||a===null?a=c:b<a&&(a=b);return this.translate(a,0,1,0,1)},addPlotBand:function(a){this.addPlotBandOrLine(a,\"plotBands\")},addPlotLine:function(a){this.addPlotBandOrLine(a,\"plotLines\")},addPlotBandOrLine:function(a,b){var c=(new sb(this,a)).render(),d=this.userOptions;b&&(d[b]=d[b]||[],d[b].push(a));this.plotLinesAndBands.push(c);\nreturn c},autoLabelAlign:function(a){a=(n(a,0)-this.side*90+720)%360;return a>15&&a<165?\"right\":a>195&&a<345?\"left\":\"center\"},getOffset:function(){var a=this,b=a.chart,c=b.renderer,d=a.options,e=a.tickPositions,f=a.ticks,g=a.horiz,h=a.side,i=b.inverted?[1,0,3,2][h]:h,j,k=0,l,m=0,p=d.title,q=d.labels,ka=0,C=b.axisOffset,F=b.clipOffset,t=[-1,1,1,-1][h],r,w=1,x=n(q.maxStaggerLines,5),D,H,ya;a.hasData=j=a.hasVisibleSeries||s(a.min)&&s(a.max)&&!!e;a.showAxis=b=j||n(d.showEmpty,!0);a.staggerLines=a.horiz&&\nq.staggerLines;if(!a.axisGroup)a.gridGroup=c.g(\"grid\").attr({zIndex:d.gridZIndex||1}).add(),a.axisGroup=c.g(\"axis\").attr({zIndex:d.zIndex||2}).add(),a.labelGroup=c.g(\"axis-labels\").attr({zIndex:q.zIndex||7}).add();if(j||a.isLinked){a.labelAlign=n(q.align||a.autoLabelAlign(q.rotation));o(e,function(b){f[b]?f[b].addLabel():f[b]=new La(a,b)});if(a.horiz&&!a.staggerLines&&x&&!q.rotation){for(;w<x;){r=[];j=!1;for(q=0;q<e.length;q++)D=e[q],H=(H=f[D].label&&f[D].label.bBox)?H.width:0,ya=q%w,H&&(D=a.translate(D),\nr[ya]!==v&&D<r[ya]&&(j=!0),r[ya]=D+H);if(j)w++;else break}if(w>1)a.staggerLines=w}o(e,function(b){if(h===0||h===2||{1:\"left\",3:\"right\"}[h]===a.labelAlign)ka=u(f[b].getLabelSize(),ka)});if(a.staggerLines)ka*=a.staggerLines,a.labelOffset=ka}else for(r in f)f[r].destroy(),delete f[r];if(p&&p.text&&p.enabled!==!1){if(!a.axisTitle)a.axisTitle=c.text(p.text,0,0,p.useHTML).attr({zIndex:7,rotation:p.rotation||0,align:p.textAlign||{low:\"left\",middle:\"center\",high:\"right\"}[p.align]}).css(p.style).add(a.axisGroup),\na.axisTitle.isNew=!0;if(b)k=a.axisTitle.getBBox()[g?\"height\":\"width\"],m=n(p.margin,g?5:10),l=p.offset;a.axisTitle[b?\"show\":\"hide\"]()}a.offset=t*n(d.offset,C[h]);a.axisTitleMargin=n(l,ka+m+(h!==2&&ka&&t*d.labels[g?\"y\":\"x\"]));C[h]=u(C[h],a.axisTitleMargin+k+t*a.offset);F[i]=u(F[i],d.lineWidth)},getLinePath:function(a){var b=this.chart,c=this.opposite,d=this.offset,e=this.horiz,f=this.left+(c?this.width:0)+d;this.lineTop=d=b.chartHeight-this.bottom-(c?this.height:0)+d;c||(a*=-1);return b.renderer.crispLine([\"M\",\ne?this.left:f,e?d:this.top,\"L\",e?b.chartWidth-this.right:f,e?d:b.chartHeight-this.bottom],a)},getTitlePosition:function(){var a=this.horiz,b=this.left,c=this.top,d=this.len,e=this.options.title,f=a?b:c,g=this.opposite,h=this.offset,i=A(e.style.fontSize||12),d={low:f+(a?0:d),middle:f+d/2,high:f+(a?d:0)}[e.align],b=(a?c+this.height:b)+(a?1:-1)*(g?-1:1)*this.axisTitleMargin+(this.side===2?i:0);return{x:a?d:b+(g?this.width:0)+h+(e.x||0),y:a?b-(g?this.height:0)+h:d+(e.y||0)}},render:function(){var a=this,\nb=a.chart,c=b.renderer,d=a.options,e=a.isLog,f=a.isLinked,g=a.tickPositions,h=a.axisTitle,i=a.stacks,j=a.ticks,k=a.minorTicks,l=a.alternateBands,m=d.stackLabels,p=d.alternateGridColor,q=a.tickmarkOffset,n=d.lineWidth,C,F=b.hasRendered&&s(a.oldMin)&&!isNaN(a.oldMin);C=a.hasData;var u=a.showAxis,t,r;o([j,k,l],function(a){for(var b in a)a[b].isActive=!1});if(C||f)if(a.minorTickInterval&&!a.categories&&o(a.getMinorTickPositions(),function(b){k[b]||(k[b]=new La(a,b,\"minor\"));F&&k[b].isNew&&k[b].render(null,\n!0);k[b].render(null,!1,1)}),g.length&&(o(g.slice(1).concat([g[0]]),function(b,c){c=c===g.length-1?0:c+1;if(!f||b>=a.min&&b<=a.max)j[b]||(j[b]=new La(a,b)),F&&j[b].isNew&&j[b].render(c,!0),j[b].render(c,!1,1)}),q&&a.min===0&&(j[-1]||(j[-1]=new La(a,-1,null,!0)),j[-1].render(-1))),p&&o(g,function(b,c){if(c%2===0&&b<a.max)l[b]||(l[b]=new sb(a)),t=b+q,r=g[c+1]!==v?g[c+1]+q:a.max,l[b].options={from:e?ea(t):t,to:e?ea(r):r,color:p},l[b].render(),l[b].isActive=!0}),!a._addedPlotLB)o((d.plotLines||[]).concat(d.plotBands||\n[]),function(b){a.addPlotBandOrLine(b)}),a._addedPlotLB=!0;o([j,k,l],function(a){var c,d,e=[],f=Da?Da.duration||500:0,g=function(){for(d=e.length;d--;)a[e[d]]&&!a[e[d]].isActive&&(a[e[d]].destroy(),delete a[e[d]])};for(c in a)if(!a[c].isActive)a[c].render(c,!1,0),a[c].isActive=!1,e.push(c);a===l||!b.hasRendered||!f?g():f&&setTimeout(g,f)});if(n)C=a.getLinePath(n),a.axisLine?a.axisLine.animate({d:C}):a.axisLine=c.path(C).attr({stroke:d.lineColor,\"stroke-width\":n,zIndex:7}).add(a.axisGroup),a.axisLine[u?\n\"show\":\"hide\"]();if(h&&u)h[h.isNew?\"attr\":\"animate\"](a.getTitlePosition()),h.isNew=!1;if(m&&m.enabled){var w,D,d=a.stackTotalGroup;if(!d)a.stackTotalGroup=d=c.g(\"stack-labels\").attr({visibility:\"visible\",zIndex:6}).add();d.translate(b.plotLeft,b.plotTop);for(w in i)for(D in c=i[w],c)c[D].render(d)}a.isDirty=!1},removePlotBandOrLine:function(a){for(var b=this.plotLinesAndBands,c=this.options,d=this.userOptions,e=b.length;e--;)b[e].id===a&&b[e].destroy();o([c.plotLines||[],d.plotLines||[],c.plotBands||\n[],d.plotBands||[]],function(b){for(e=b.length;e--;)b[e].id===a&&fa(b,b[e])})},setTitle:function(a,b){this.update({title:a},b)},redraw:function(){var a=this.chart.pointer;a.reset&&a.reset(!0);this.render();o(this.plotLinesAndBands,function(a){a.render()});o(this.series,function(a){a.isDirty=!0})},buildStacks:function(){if(!this.isXAxis){var a=this.series,b=a.length-1;o(a,function(a,d){a.setStackedPoints(d===b)})}},setCategories:function(a,b){this.update({categories:a},b)},destroy:function(a){var b=\nthis,c=b.stacks,d;a||aa(b);for(d in c)Ja(c[d]),c[d]=null;o([b.ticks,b.minorTicks,b.alternateBands,b.plotLinesAndBands],function(a){Ja(a)});o(\"stackTotalGroup,axisLine,axisGroup,gridGroup,labelGroup,axisTitle\".split(\",\"),function(a){b[a]&&(b[a]=b[a].destroy())})}};tb.prototype={init:function(a,b){var c=b.borderWidth,d=b.style,e=A(d.padding);this.chart=a;this.options=b;this.crosshairs=[];this.now={x:0,y:0};this.isHidden=!0;this.label=a.renderer.label(\"\",0,0,b.shape,null,null,b.useHTML,null,\"tooltip\").attr({padding:e,\nfill:b.backgroundColor,\"stroke-width\":c,r:b.borderRadius,zIndex:8}).css(d).css({padding:0}).hide().add();Z||this.label.shadow(b.shadow);this.shared=b.shared},destroy:function(){o(this.crosshairs,function(a){a&&a.destroy()});if(this.label)this.label=this.label.destroy();clearTimeout(this.hideTimer);clearTimeout(this.tooltipTimeout)},move:function(a,b,c,d){var e=this,f=e.now,g=e.options.animation!==!1&&!e.isHidden;r(f,{x:g?(2*f.x+a)/3:a,y:g?(f.y+b)/2:b,anchorX:g?(2*f.anchorX+c)/3:c,anchorY:g?(f.anchorY+\nd)/2:d});e.label.attr(f);if(g&&(P(a-f.x)>1||P(b-f.y)>1))clearTimeout(this.tooltipTimeout),this.tooltipTimeout=setTimeout(function(){e&&e.move(a,b,c,d)},32)},hide:function(){var a=this,b;clearTimeout(this.hideTimer);if(!this.isHidden)b=this.chart.hoverPoints,this.hideTimer=setTimeout(function(){a.label.fadeOut();a.isHidden=!0},n(this.options.hideDelay,500)),b&&o(b,function(a){a.setState()}),this.chart.hoverPoints=null},hideCrosshairs:function(){o(this.crosshairs,function(a){a&&a.hide()})},getAnchor:function(a,\nb){var c,d=this.chart,e=d.inverted,f=d.plotTop,g=0,h=0,i,a=ha(a);c=a[0].tooltipPos;this.followPointer&&b&&(b.chartX===v&&(b=d.pointer.normalize(b)),c=[b.chartX-d.plotLeft,b.chartY-f]);c||(o(a,function(a){i=a.series.yAxis;g+=a.plotX;h+=(a.plotLow?(a.plotLow+a.plotHigh)/2:a.plotY)+(!e&&i?i.top-f:0)}),g/=a.length,h/=a.length,c=[e?d.plotWidth-h:g,this.shared&&!e&&a.length>1&&b?b.chartY-f:e?d.plotHeight-g:h]);return Na(c,t)},getPosition:function(a,b,c){var d=this.chart,e=d.plotLeft,f=d.plotTop,g=d.plotWidth,\nh=d.plotHeight,i=n(this.options.distance,12),j=c.plotX,c=c.plotY,d=j+e+(d.inverted?i:-a-i),k=c-b+f+15,l;d<7&&(d=e+u(j,0)+i);d+a>e+g&&(d-=d+a-(e+g),k=c-b+f-i,l=!0);k<f+5&&(k=f+5,l&&c>=k&&c<=k+b&&(k=c+f+i));k+b>f+h&&(k=u(f,f+h-b-i));return{x:d,y:k}},defaultFormatter:function(a){var b=this.points||ha(this),c=b[0].series,d;d=[c.tooltipHeaderFormatter(b[0])];o(b,function(a){c=a.series;d.push(c.tooltipFormatter&&c.tooltipFormatter(a)||a.point.tooltipFormatter(c.tooltipOptions.pointFormat))});d.push(a.options.footerFormat||\n\"\");return d.join(\"\")},refresh:function(a,b){var c=this.chart,d=this.label,e=this.options,f,g,h,i={},j,k=[];j=e.formatter||this.defaultFormatter;var i=c.hoverPoints,l,m=e.crosshairs;h=this.shared;clearTimeout(this.hideTimer);this.followPointer=ha(a)[0].series.tooltipOptions.followPointer;g=this.getAnchor(a,b);f=g[0];g=g[1];h&&(!a.series||!a.series.noSharedTooltip)?(c.hoverPoints=a,i&&o(i,function(a){a.setState()}),o(a,function(a){a.setState(\"hover\");k.push(a.getLabelConfig())}),i={x:a[0].category,\ny:a[0].y},i.points=k,a=a[0]):i=a.getLabelConfig();j=j.call(i,this);i=a.series;h=h||!i.isCartesian||i.tooltipOutsidePlot||c.isInsidePlot(f,g);j===!1||!h?this.hide():(this.isHidden&&(Wa(d),d.attr(\"opacity\",1).show()),d.attr({text:j}),l=e.borderColor||a.color||i.color||\"#606060\",d.attr({stroke:l}),this.updatePosition({plotX:f,plotY:g}),this.isHidden=!1);if(m){m=ha(m);for(d=m.length;d--;)if(i=a.series,e=i[d?\"yAxis\":\"xAxis\"],m[d]&&e)if(h=d?n(a.stackY,a.y):a.x,e.isLog&&(h=ma(h)),i.modifyValue&&(h=i.modifyValue(h)),\ne=e.getPlotLinePath(h,1),this.crosshairs[d])this.crosshairs[d].attr({d:e,visibility:\"visible\"});else{h={\"stroke-width\":m[d].width||1,stroke:m[d].color||\"#C0C0C0\",zIndex:m[d].zIndex||2};if(m[d].dashStyle)h.dashstyle=m[d].dashStyle;this.crosshairs[d]=c.renderer.path(e).attr(h).add()}}B(c,\"tooltipRefresh\",{text:j,x:f+c.plotLeft,y:g+c.plotTop,borderColor:l})},updatePosition:function(a){var b=this.chart,c=this.label,c=(this.options.positioner||this.getPosition).call(this,c.width,c.height,a);this.move(t(c.x),\nt(c.y),a.plotX+b.plotLeft,a.plotY+b.plotTop)}};ub.prototype={init:function(a,b){var c=Z?\"\":b.chart.zoomType,d=a.inverted,e;this.options=b;this.chart=a;this.zoomX=e=/x/.test(c);this.zoomY=c=/y/.test(c);this.zoomHor=e&&!d||c&&d;this.zoomVert=c&&!d||e&&d;this.pinchDown=[];this.lastValidTouch={};if(b.tooltip.enabled)a.tooltip=new tb(a,b.tooltip);this.setDOMEvents()},normalize:function(a){var b,c,a=a||E.event;if(!a.target)a.target=a.srcElement;a=Rb(a);c=a.touches?a.touches.item(0):a;this.chartPosition=\nb=Wb(this.chart.container);return r(a,{chartX:t(n(c.pageX,c.clientX)-b.left),chartY:t(n(c.pageY,c.clientY)-b.top)})},getCoordinates:function(a){var b={xAxis:[],yAxis:[]};o(this.chart.axes,function(c){b[c.isXAxis?\"xAxis\":\"yAxis\"].push({axis:c,value:c.toValue(a[c.horiz?\"chartX\":\"chartY\"])})});return b},getIndex:function(a){var b=this.chart;return b.inverted?b.plotHeight+b.plotTop-a.chartY:a.chartX-b.plotLeft},runPointActions:function(a){var b=this.chart,c=b.series,d=b.tooltip,e,f=b.hoverPoint,g=b.hoverSeries,\nh,i,j=b.chartWidth,k=this.getIndex(a);if(d&&this.options.tooltip.shared&&(!g||!g.noSharedTooltip)){e=[];h=c.length;for(i=0;i<h;i++)if(c[i].visible&&c[i].options.enableMouseTracking!==!1&&!c[i].noSharedTooltip&&c[i].tooltipPoints.length&&(b=c[i].tooltipPoints[k],b.series))b._dist=P(k-b.clientX),j=I(j,b._dist),e.push(b);for(h=e.length;h--;)e[h]._dist>j&&e.splice(h,1);if(e.length&&e[0].clientX!==this.hoverX)d.refresh(e,a),this.hoverX=e[0].clientX}if(g&&g.tracker){if((b=g.tooltipPoints[k])&&b!==f)b.onMouseOver(a)}else d&&\nd.followPointer&&!d.isHidden&&(a=d.getAnchor([{}],a),d.updatePosition({plotX:a[0],plotY:a[1]}))},reset:function(a){var b=this.chart,c=b.hoverSeries,d=b.hoverPoint,e=b.tooltip,b=e&&e.shared?b.hoverPoints:d;(a=a&&e&&b)&&ha(b)[0].plotX===v&&(a=!1);if(a)e.refresh(b);else{if(d)d.onMouseOut();if(c)c.onMouseOut();e&&(e.hide(),e.hideCrosshairs());this.hoverX=null}},scaleGroups:function(a,b){var c=this.chart,d;o(c.series,function(e){d=a||e.getPlotBox();e.xAxis&&e.xAxis.zoomEnabled&&(e.group.attr(d),e.markerGroup&&\n(e.markerGroup.attr(d),e.markerGroup.clip(b?c.clipRect:null)),e.dataLabelsGroup&&e.dataLabelsGroup.attr(d))});c.clipRect.attr(b||c.clipBox)},pinchTranslateDirection:function(a,b,c,d,e,f,g){var h=this.chart,i=a?\"x\":\"y\",j=a?\"X\":\"Y\",k=\"chart\"+j,l=a?\"width\":\"height\",m=h[\"plot\"+(a?\"Left\":\"Top\")],p,q,n=1,o=h.inverted,u=h.bounds[a?\"h\":\"v\"],t=b.length===1,s=b[0][k],r=c[0][k],w=!t&&b[1][k],v=!t&&c[1][k],x,c=function(){!t&&P(s-w)>20&&(n=P(r-v)/P(s-w));q=(m-r)/n+s;p=h[\"plot\"+(a?\"Width\":\"Height\")]/n};c();b=q;\nb<u.min?(b=u.min,x=!0):b+p>u.max&&(b=u.max-p,x=!0);x?(r-=0.8*(r-g[i][0]),t||(v-=0.8*(v-g[i][1])),c()):g[i]=[r,v];o||(f[i]=q-m,f[l]=p);f=o?1/n:n;e[l]=p;e[i]=b;d[o?a?\"scaleY\":\"scaleX\":\"scale\"+j]=n;d[\"translate\"+j]=f*m+(r-f*s)},pinch:function(a){var b=this,c=b.chart,d=b.pinchDown,e=c.tooltip&&c.tooltip.options.followTouchMove,f=a.touches,g=f.length,h=b.lastValidTouch,i=b.zoomHor||b.pinchHor,j=b.zoomVert||b.pinchVert,k=i||j,l=b.selectionMarker,m={},p={};a.type===\"touchstart\"&&(e||k)&&a.preventDefault();\nNa(f,function(a){return b.normalize(a)});if(a.type===\"touchstart\")o(f,function(a,b){d[b]={chartX:a.chartX,chartY:a.chartY}}),h.x=[d[0].chartX,d[1]&&d[1].chartX],h.y=[d[0].chartY,d[1]&&d[1].chartY],o(c.axes,function(a){if(a.zoomEnabled){var b=c.bounds[a.horiz?\"h\":\"v\"],d=a.minPixelPadding,e=a.toPixels(a.dataMin),f=a.toPixels(a.dataMax),g=I(e,f),e=u(e,f);b.min=I(a.pos,g-d);b.max=u(a.pos+a.len,e+d)}});else if(d.length){if(!l)b.selectionMarker=l=r({destroy:xa},c.plotBox);i&&b.pinchTranslateDirection(!0,\nd,f,m,l,p,h);j&&b.pinchTranslateDirection(!1,d,f,m,l,p,h);b.hasPinched=k;b.scaleGroups(m,p);!k&&e&&g===1&&this.runPointActions(b.normalize(a))}},dragStart:function(a){var b=this.chart;b.mouseIsDown=a.type;b.cancelClick=!1;b.mouseDownX=this.mouseDownX=a.chartX;this.mouseDownY=a.chartY},drag:function(a){var b=this.chart,c=b.options.chart,d=a.chartX,a=a.chartY,e=this.zoomHor,f=this.zoomVert,g=b.plotLeft,h=b.plotTop,i=b.plotWidth,j=b.plotHeight,k,l=this.mouseDownX,m=this.mouseDownY;d<g?d=g:d>g+i&&(d=\ng+i);a<h?a=h:a>h+j&&(a=h+j);this.hasDragged=Math.sqrt(Math.pow(l-d,2)+Math.pow(m-a,2));if(this.hasDragged>10){k=b.isInsidePlot(l-g,m-h);if(b.hasCartesianSeries&&(this.zoomX||this.zoomY)&&k&&!this.selectionMarker)this.selectionMarker=b.renderer.rect(g,h,e?1:i,f?1:j,0).attr({fill:c.selectionMarkerFill||\"rgba(69,114,167,0.25)\",zIndex:7}).add();this.selectionMarker&&e&&(e=d-l,this.selectionMarker.attr({width:P(e),x:(e>0?0:e)+l}));this.selectionMarker&&f&&(e=a-m,this.selectionMarker.attr({height:P(e),\ny:(e>0?0:e)+m}));k&&!this.selectionMarker&&c.panning&&b.pan(d)}},drop:function(a){var b=this.chart,c=this.hasPinched;if(this.selectionMarker){var d={xAxis:[],yAxis:[],originalEvent:a.originalEvent||a},e=this.selectionMarker,f=e.x,g=e.y,h;if(this.hasDragged||c)o(b.axes,function(a){if(a.zoomEnabled){var b=a.horiz,c=a.toValue(b?f:g),b=a.toValue(b?f+e.width:g+e.height);!isNaN(c)&&!isNaN(b)&&(d[a.xOrY+\"Axis\"].push({axis:a,min:I(c,b),max:u(c,b)}),h=!0)}}),h&&B(b,\"selection\",d,function(a){b.zoom(r(a,c?{animation:!1}:\nnull))});this.selectionMarker=this.selectionMarker.destroy();c&&this.scaleGroups()}if(b)M(b.container,{cursor:b._cursor}),b.cancelClick=this.hasDragged>10,b.mouseIsDown=this.hasDragged=this.hasPinched=!1,this.pinchDown=[]},onContainerMouseDown:function(a){a=this.normalize(a);a.preventDefault&&a.preventDefault();this.dragStart(a)},onDocumentMouseUp:function(a){this.drop(a)},onDocumentMouseMove:function(a){var b=this.chart,c=this.chartPosition,d=b.hoverSeries,a=Rb(a);c&&d&&d.isCartesian&&!b.isInsidePlot(a.pageX-\nc.left-b.plotLeft,a.pageY-c.top-b.plotTop)&&this.reset()},onContainerMouseLeave:function(){this.reset();this.chartPosition=null},onContainerMouseMove:function(a){var b=this.chart,a=this.normalize(a);a.returnValue=!1;b.mouseIsDown===\"mousedown\"&&this.drag(a);b.isInsidePlot(a.chartX-b.plotLeft,a.chartY-b.plotTop)&&!b.openMenu&&this.runPointActions(a)},inClass:function(a,b){for(var c;a;){if(c=x(a,\"class\"))if(c.indexOf(b)!==-1)return!0;else if(c.indexOf(\"highcharts-container\")!==-1)return!1;a=a.parentNode}},\nonTrackerMouseOut:function(a){var b=this.chart.hoverSeries;if(b&&!b.options.stickyTracking&&!this.inClass(a.toElement||a.relatedTarget,\"highcharts-tooltip\"))b.onMouseOut()},onContainerClick:function(a){var b=this.chart,c=b.hoverPoint,d=b.plotLeft,e=b.plotTop,f=b.inverted,g,h,i,a=this.normalize(a);a.cancelBubble=!0;if(!b.cancelClick)c&&this.inClass(a.target,\"highcharts-tracker\")?(g=this.chartPosition,h=c.plotX,i=c.plotY,r(c,{pageX:g.left+d+(f?b.plotWidth-i:h),pageY:g.top+e+(f?b.plotHeight-h:i)}),B(c.series,\n\"click\",r(a,{point:c})),b.hoverPoint&&c.firePointEvent(\"click\",a)):(r(a,this.getCoordinates(a)),b.isInsidePlot(a.chartX-d,a.chartY-e)&&B(b,\"click\",a))},onContainerTouchStart:function(a){var b=this.chart;a.touches.length===1?(a=this.normalize(a),b.isInsidePlot(a.chartX-b.plotLeft,a.chartY-b.plotTop)?(this.runPointActions(a),this.pinch(a)):this.reset()):a.touches.length===2&&this.pinch(a)},onContainerTouchMove:function(a){(a.touches.length===1||a.touches.length===2)&&this.pinch(a)},onDocumentTouchEnd:function(a){this.drop(a)},\nsetDOMEvents:function(){var a=this,b=a.chart.container,c;this._events=c=[[b,\"onmousedown\",\"onContainerMouseDown\"],[b,\"onmousemove\",\"onContainerMouseMove\"],[b,\"onclick\",\"onContainerClick\"],[b,\"mouseleave\",\"onContainerMouseLeave\"],[y,\"mousemove\",\"onDocumentMouseMove\"],[y,\"mouseup\",\"onDocumentMouseUp\"]];hb&&c.push([b,\"ontouchstart\",\"onContainerTouchStart\"],[b,\"ontouchmove\",\"onContainerTouchMove\"],[y,\"touchend\",\"onDocumentTouchEnd\"]);o(c,function(b){a[\"_\"+b[2]]=function(c){a[b[2]](c)};b[1].indexOf(\"on\")===\n0?b[0][b[1]]=a[\"_\"+b[2]]:J(b[0],b[1],a[\"_\"+b[2]])})},destroy:function(){var a=this;o(a._events,function(b){b[1].indexOf(\"on\")===0?b[0][b[1]]=null:aa(b[0],b[1],a[\"_\"+b[2]])});delete a._events;clearInterval(a.tooltipTimeout)}};vb.prototype={init:function(a,b){var c=this,d=b.itemStyle,e=n(b.padding,8),f=b.itemMarginTop||0;this.options=b;if(b.enabled)c.baseline=A(d.fontSize)+3+f,c.itemStyle=d,c.itemHiddenStyle=w(d,b.itemHiddenStyle),c.itemMarginTop=f,c.padding=e,c.initialItemX=e,c.initialItemY=e-5,c.maxItemWidth=\n0,c.chart=a,c.itemHeight=0,c.lastLineHeight=0,c.render(),J(c.chart,\"endResize\",function(){c.positionCheckboxes()})},colorizeItem:function(a,b){var c=this.options,d=a.legendItem,e=a.legendLine,f=a.legendSymbol,g=this.itemHiddenStyle.color,c=b?c.itemStyle.color:g,h=b?a.color:g,g=a.options&&a.options.marker,i={stroke:h,fill:h},j;d&&d.css({fill:c,color:c});e&&e.attr({stroke:h});if(f){if(g&&f.isMarker)for(j in g=a.convertAttribs(g),g)d=g[j],d!==v&&(i[j]=d);f.attr(i)}},positionItem:function(a){var b=this.options,\nc=b.symbolPadding,b=!b.rtl,d=a._legendItemPos,e=d[0],d=d[1],f=a.checkbox;a.legendGroup&&a.legendGroup.translate(b?e:this.legendWidth-e-2*c-4,d);if(f)f.x=e,f.y=d},destroyItem:function(a){var b=a.checkbox;o([\"legendItem\",\"legendLine\",\"legendSymbol\",\"legendGroup\"],function(b){a[b]&&(a[b]=a[b].destroy())});b&&Ta(a.checkbox)},destroy:function(){var a=this.group,b=this.box;if(b)this.box=b.destroy();if(a)this.group=a.destroy()},positionCheckboxes:function(a){var b=this.group.alignAttr,c,d=this.clipHeight||\nthis.legendHeight;if(b)c=b.translateY,o(this.allItems,function(e){var f=e.checkbox,g;f&&(g=c+f.y+(a||0)+3,M(f,{left:b.translateX+e.legendItemWidth+f.x-20+\"px\",top:g+\"px\",display:g>c-6&&g<c+d-6?\"\":R}))})},renderTitle:function(){var a=this.padding,b=this.options.title,c=0;if(b.text){if(!this.title)this.title=this.chart.renderer.label(b.text,a-3,a-4,null,null,null,null,null,\"legend-title\").attr({zIndex:1}).css(b.style).add(this.group);a=this.title.getBBox();c=a.height;this.offsetWidth=a.width;this.contentGroup.attr({translateY:c})}this.titleHeight=\nc},renderItem:function(a){var C;var b=this,c=b.chart,d=c.renderer,e=b.options,f=e.layout===\"horizontal\",g=e.symbolWidth,h=e.symbolPadding,i=b.itemStyle,j=b.itemHiddenStyle,k=b.padding,l=f?n(e.itemDistance,8):0,m=!e.rtl,p=e.width,q=e.itemMarginBottom||0,o=b.itemMarginTop,t=b.initialItemX,s=a.legendItem,r=a.series||a,v=r.options,x=v.showCheckbox,A=e.useHTML;if(!s&&(a.legendGroup=d.g(\"legend-item\").attr({zIndex:1}).add(b.scrollGroup),r.drawLegendSymbol(b,a),a.legendItem=s=d.text(e.labelFormat?Ba(e.labelFormat,\na):e.labelFormatter.call(a),m?g+h:-h,b.baseline,A).css(w(a.visible?i:j)).attr({align:m?\"left\":\"right\",zIndex:2}).add(a.legendGroup),(A?s:a.legendGroup).on(\"mouseover\",function(){a.setState(\"hover\");s.css(b.options.itemHoverStyle)}).on(\"mouseout\",function(){s.css(a.visible?i:j);a.setState()}).on(\"click\",function(b){var c=function(){a.setVisible()},b={browserEvent:b};a.firePointEvent?a.firePointEvent(\"legendItemClick\",b,c):B(a,\"legendItemClick\",b,c)}),b.colorizeItem(a,a.visible),v&&x))a.checkbox=T(\"input\",\n{type:\"checkbox\",checked:a.selected,defaultChecked:a.selected},e.itemCheckboxStyle,c.container),J(a.checkbox,\"click\",function(b){B(a,\"checkboxClick\",{checked:b.target.checked},function(){a.select()})});d=s.getBBox();C=a.legendItemWidth=e.itemWidth||g+h+d.width+l+(x?20:0),e=C;b.itemHeight=g=d.height;if(f&&b.itemX-t+e>(p||c.chartWidth-2*k-t))b.itemX=t,b.itemY+=o+b.lastLineHeight+q,b.lastLineHeight=0;b.maxItemWidth=u(b.maxItemWidth,e);b.lastItemY=o+b.itemY+q;b.lastLineHeight=u(g,b.lastLineHeight);a._legendItemPos=\n[b.itemX,b.itemY];f?b.itemX+=e:(b.itemY+=o+g+q,b.lastLineHeight=g);b.offsetWidth=p||u((f?b.itemX-t-l:e)+k,b.offsetWidth)},render:function(){var a=this,b=a.chart,c=b.renderer,d=a.group,e,f,g,h,i=a.box,j=a.options,k=a.padding,l=j.borderWidth,m=j.backgroundColor;a.itemX=a.initialItemX;a.itemY=a.initialItemY;a.offsetWidth=0;a.lastItemY=0;if(!d)a.group=d=c.g(\"legend\").attr({zIndex:7}).add(),a.contentGroup=c.g().attr({zIndex:1}).add(d),a.scrollGroup=c.g().add(a.contentGroup);a.renderTitle();e=[];o(b.series,\nfunction(a){var b=a.options;b.showInLegend&&!s(b.linkedTo)&&(e=e.concat(a.legendItems||(b.legendType===\"point\"?a.data:a)))});Jb(e,function(a,b){return(a.options&&a.options.legendIndex||0)-(b.options&&b.options.legendIndex||0)});j.reversed&&e.reverse();a.allItems=e;a.display=f=!!e.length;o(e,function(b){a.renderItem(b)});g=j.width||a.offsetWidth;h=a.lastItemY+a.lastLineHeight+a.titleHeight;h=a.handleOverflow(h);if(l||m){g+=k;h+=k;if(i){if(g>0&&h>0)i[i.isNew?\"attr\":\"animate\"](i.crisp(null,null,null,\ng,h)),i.isNew=!1}else a.box=i=c.rect(0,0,g,h,j.borderRadius,l||0).attr({stroke:j.borderColor,\"stroke-width\":l||0,fill:m||R}).add(d).shadow(j.shadow),i.isNew=!0;i[f?\"show\":\"hide\"]()}a.legendWidth=g;a.legendHeight=h;o(e,function(b){a.positionItem(b)});f&&d.align(r({width:g,height:h},j),!0,\"spacingBox\");b.isResizing||this.positionCheckboxes()},handleOverflow:function(a){var b=this,c=this.chart,d=c.renderer,e=this.options,f=e.y,f=c.spacingBox.height+(e.verticalAlign===\"top\"?-f:f)-this.padding,g=e.maxHeight,\nh=this.clipRect,i=e.navigation,j=n(i.animation,!0),k=i.arrowSize||12,l=this.nav;e.layout===\"horizontal\"&&(f/=2);g&&(f=I(f,g));if(a>f&&!e.useHTML){this.clipHeight=c=f-20-this.titleHeight;this.pageCount=ja(a/c);this.currentPage=n(this.currentPage,1);this.fullHeight=a;if(!h)h=b.clipRect=d.clipRect(0,0,9999,0),b.contentGroup.clip(h);h.attr({height:c});if(!l)this.nav=l=d.g().attr({zIndex:1}).add(this.group),this.up=d.symbol(\"triangle\",0,0,k,k).on(\"click\",function(){b.scroll(-1,j)}).add(l),this.pager=d.text(\"\",\n15,10).css(i.style).add(l),this.down=d.symbol(\"triangle-down\",0,0,k,k).on(\"click\",function(){b.scroll(1,j)}).add(l);b.scroll(0);a=f}else if(l)h.attr({height:c.chartHeight}),l.hide(),this.scrollGroup.attr({translateY:1}),this.clipHeight=0;return a},scroll:function(a,b){var c=this.pageCount,d=this.currentPage+a,e=this.clipHeight,f=this.options.navigation,g=f.activeColor,h=f.inactiveColor,f=this.pager,i=this.padding;d>c&&(d=c);if(d>0)b!==v&&Ka(b,this.chart),this.nav.attr({translateX:i,translateY:e+7+\nthis.titleHeight,visibility:\"visible\"}),this.up.attr({fill:d===1?h:g}).css({cursor:d===1?\"default\":\"pointer\"}),f.attr({text:d+\"/\"+this.pageCount}),this.down.attr({x:18+this.pager.getBBox().width,fill:d===c?h:g}).css({cursor:d===c?\"default\":\"pointer\"}),e=-I(e*(d-1),this.fullHeight-e+i)+1,this.scrollGroup.animate({translateY:e}),f.attr({text:d+\"/\"+c}),this.currentPage=d,this.positionCheckboxes(e)}};wb.prototype={init:function(a,b){var c,d=a.series;a.series=null;c=w(O,a);c.series=a.series=d;var d=c.chart,\ne=d.margin,e=U(e)?e:[e,e,e,e];this.optionsMarginTop=n(d.marginTop,e[0]);this.optionsMarginRight=n(d.marginRight,e[1]);this.optionsMarginBottom=n(d.marginBottom,e[2]);this.optionsMarginLeft=n(d.marginLeft,e[3]);e=d.events;this.bounds={h:{},v:{}};this.callback=b;this.isResizing=0;this.options=c;this.axes=[];this.series=[];this.hasCartesianSeries=d.showAxes;var f=this,g;f.index=Fa.length;Fa.push(f);d.reflow!==!1&&J(f,\"load\",function(){f.initReflow()});if(e)for(g in e)J(f,g,e[g]);f.xAxis=[];f.yAxis=[];\nf.animation=Z?!1:n(d.animation,!0);f.pointCount=0;f.counters=new Ib;f.firstRender()},initSeries:function(a){var b=this.options.chart;(b=$[a.type||b.type||b.defaultSeriesType])||ua(17,!0);b=new b;b.init(this,a);return b},addSeries:function(a,b,c){var d,e=this;a&&(b=n(b,!0),B(e,\"addSeries\",{options:a},function(){d=e.initSeries(a);e.isDirtyLegend=!0;b&&e.redraw(c)}));return d},addAxis:function(a,b,c,d){var e=b?\"xAxis\":\"yAxis\",f=this.options;new db(this,w(a,{index:this[e].length,isX:b}));f[e]=ha(f[e]||\n{});f[e].push(a);n(c,!0)&&this.redraw(d)},isInsidePlot:function(a,b,c){var d=c?b:a,a=c?a:b;return d>=0&&d<=this.plotWidth&&a>=0&&a<=this.plotHeight},adjustTickAmounts:function(){this.options.chart.alignTicks!==!1&&o(this.axes,function(a){a.adjustTickAmount()});this.maxTicks=null},redraw:function(a){var b=this.axes,c=this.series,d=this.pointer,e=this.legend,f=this.isDirtyLegend,g,h,i=this.isDirtyBox,j=c.length,k=j,l=this.renderer,m=l.isHidden(),p=[];Ka(a,this);m&&this.cloneRenderTo();for(this.layOutTitles();k--;)if(a=\nc[k],a.options.stacking&&(g=!0,a.isDirty)){h=!0;break}if(h)for(k=j;k--;)if(a=c[k],a.options.stacking)a.isDirty=!0;o(c,function(a){a.isDirty&&a.options.legendType===\"point\"&&(f=!0)});if(f&&e.options.enabled)e.render(),this.isDirtyLegend=!1;g&&this.getStacks();if(this.hasCartesianSeries)this.isResizing?o(b,function(a){a.buildStacks()}):(this.maxTicks=null,o(b,function(a){a.setScale()})),this.adjustTickAmounts(),this.getMargins(),o(b,function(a){if(a.isDirtyExtremes)a.isDirtyExtremes=!1,p.push(function(){B(a,\n\"afterSetExtremes\",a.getExtremes())});if(a.isDirty||i||g)a.redraw(),i=!0});i&&this.drawChartBox();o(c,function(a){a.isDirty&&a.visible&&(!a.isCartesian||a.xAxis)&&a.redraw()});d&&d.reset&&d.reset(!0);l.draw();B(this,\"redraw\");m&&this.cloneRenderTo(!0);o(p,function(a){a.call()})},showLoading:function(a){var b=this.options,c=this.loadingDiv,d=b.loading;if(!c)this.loadingDiv=c=T(Ca,{className:\"highcharts-loading\"},r(d.style,{zIndex:10,display:R}),this.container),this.loadingSpan=T(\"span\",null,d.labelStyle,\nc);this.loadingSpan.innerHTML=a||b.lang.loading;if(!this.loadingShown)M(c,{opacity:0,display:\"\",left:this.plotLeft+\"px\",top:this.plotTop+\"px\",width:this.plotWidth+\"px\",height:this.plotHeight+\"px\"}),zb(c,{opacity:d.style.opacity},{duration:d.showDuration||0}),this.loadingShown=!0},hideLoading:function(){var a=this.options,b=this.loadingDiv;b&&zb(b,{opacity:0},{duration:a.loading.hideDuration||100,complete:function(){M(b,{display:R})}});this.loadingShown=!1},get:function(a){var b=this.axes,c=this.series,\nd,e;for(d=0;d<b.length;d++)if(b[d].options.id===a)return b[d];for(d=0;d<c.length;d++)if(c[d].options.id===a)return c[d];for(d=0;d<c.length;d++){e=c[d].points||[];for(b=0;b<e.length;b++)if(e[b].id===a)return e[b]}return null},getAxes:function(){var a=this,b=this.options,c=b.xAxis=ha(b.xAxis||{}),b=b.yAxis=ha(b.yAxis||{});o(c,function(a,b){a.index=b;a.isX=!0});o(b,function(a,b){a.index=b});c=c.concat(b);o(c,function(b){new db(a,b)});a.adjustTickAmounts()},getSelectedPoints:function(){var a=[];o(this.series,\nfunction(b){a=a.concat(rb(b.points||[],function(a){return a.selected}))});return a},getSelectedSeries:function(){return rb(this.series,function(a){return a.selected})},getStacks:function(){var a=this;o(a.yAxis,function(a){if(a.stacks&&a.hasVisibleSeries)a.oldStacks=a.stacks});o(a.series,function(b){if(b.options.stacking&&(b.visible===!0||a.options.chart.ignoreHiddenSeries===!1))b.stackKey=b.type+n(b.options.stack,\"\")})},showResetZoom:function(){var a=this,b=O.lang,c=a.options.chart.resetZoomButton,\nd=c.theme,e=d.states,f=c.relativeTo===\"chart\"?null:\"plotBox\";this.resetZoomButton=a.renderer.button(b.resetZoom,null,null,function(){a.zoomOut()},d,e&&e.hover).attr({align:c.position.align,title:b.resetZoomTitle}).add().align(c.position,!1,f)},zoomOut:function(){var a=this;B(a,\"selection\",{resetSelection:!0},function(){a.zoom()})},zoom:function(a){var b,c=this.pointer,d=!1,e;!a||a.resetSelection?o(this.axes,function(a){b=a.zoom()}):o(a.xAxis.concat(a.yAxis),function(a){var e=a.axis,h=e.isXAxis;if(c[h?\n\"zoomX\":\"zoomY\"]||c[h?\"pinchX\":\"pinchY\"])b=e.zoom(a.min,a.max),e.displayBtn&&(d=!0)});e=this.resetZoomButton;if(d&&!e)this.showResetZoom();else if(!d&&U(e))this.resetZoomButton=e.destroy();b&&this.redraw(n(this.options.chart.animation,a&&a.animation,this.pointCount<100))},pan:function(a){var b=this.xAxis[0],c=this.mouseDownX,d=b.pointRange/2,e=b.getExtremes(),f=b.translate(c-a,!0)+d,c=b.translate(c+this.plotWidth-a,!0)-d;(d=this.hoverPoints)&&o(d,function(a){a.setState()});b.series.length&&f>I(e.dataMin,\ne.min)&&c<u(e.dataMax,e.max)&&b.setExtremes(f,c,!0,!1,{trigger:\"pan\"});this.mouseDownX=a;M(this.container,{cursor:\"move\"})},setTitle:function(a,b){var f;var c=this,d=c.options,e;e=d.title=w(d.title,a);f=d.subtitle=w(d.subtitle,b),d=f;o([[\"title\",a,e],[\"subtitle\",b,d]],function(a){var b=a[0],d=c[b],e=a[1],a=a[2];d&&e&&(c[b]=d=d.destroy());a&&a.text&&!d&&(c[b]=c.renderer.text(a.text,0,0,a.useHTML).attr({align:a.align,\"class\":\"highcharts-\"+b,zIndex:a.zIndex||4}).css(a.style).add())});c.layOutTitles()},\nlayOutTitles:function(){var a=0,b=this.title,c=this.subtitle,d=this.options,e=d.title,d=d.subtitle,f=this.spacingBox.width-44;if(b&&(b.css({width:(e.width||f)+\"px\"}).align(r({y:15},e),!1,\"spacingBox\"),!e.floating&&!e.verticalAlign))a=b.getBBox().height,a>=18&&a<=25&&(a=15);c&&(c.css({width:(d.width||f)+\"px\"}).align(r({y:a+e.margin},d),!1,\"spacingBox\"),!d.floating&&!d.verticalAlign&&(a=ja(a+c.getBBox().height)));this.titleOffset=a},getChartSize:function(){var a=this.options.chart,b=this.renderToClone||\nthis.renderTo;this.containerWidth=ib(b,\"width\");this.containerHeight=ib(b,\"height\");this.chartWidth=u(0,a.width||this.containerWidth||600);this.chartHeight=u(0,n(a.height,this.containerHeight>19?this.containerHeight:400))},cloneRenderTo:function(a){var b=this.renderToClone,c=this.container;a?b&&(this.renderTo.appendChild(c),Ta(b),delete this.renderToClone):(c&&c.parentNode===this.renderTo&&this.renderTo.removeChild(c),this.renderToClone=b=this.renderTo.cloneNode(0),M(b,{position:\"absolute\",top:\"-9999px\",\ndisplay:\"block\"}),y.body.appendChild(b),c&&b.appendChild(c))},getContainer:function(){var a,b=this.options.chart,c,d,e;this.renderTo=a=b.renderTo;e=\"highcharts-\"+xb++;if(da(a))this.renderTo=a=y.getElementById(a);a||ua(13,!0);c=A(x(a,\"data-highcharts-chart\"));!isNaN(c)&&Fa[c]&&Fa[c].destroy();x(a,\"data-highcharts-chart\",this.index);a.innerHTML=\"\";a.offsetWidth||this.cloneRenderTo();this.getChartSize();c=this.chartWidth;d=this.chartHeight;this.container=a=T(Ca,{className:\"highcharts-container\"+(b.className?\n\" \"+b.className:\"\"),id:e},r({position:\"relative\",overflow:\"hidden\",width:c+\"px\",height:d+\"px\",textAlign:\"left\",lineHeight:\"normal\",zIndex:0,\"-webkit-tap-highlight-color\":\"rgba(0,0,0,0)\"},b.style),this.renderToClone||a);this._cursor=a.style.cursor;this.renderer=b.forExport?new Ga(a,c,d,!0):new Va(a,c,d);Z&&this.renderer.create(this,a,c,d)},getMargins:function(){var a=this.options.chart,b=a.spacingTop,c=a.spacingRight,d=a.spacingBottom,a=a.spacingLeft,e,f=this.legend,g=this.optionsMarginTop,h=this.optionsMarginLeft,\ni=this.optionsMarginRight,j=this.optionsMarginBottom,k=this.options.legend,l=n(k.margin,10),m=k.x,p=k.y,q=k.align,t=k.verticalAlign,r=this.titleOffset;this.resetMargins();e=this.axisOffset;if(r&&!s(g))this.plotTop=u(this.plotTop,r+this.options.title.margin+b);if(f.display&&!k.floating)if(q===\"right\"){if(!s(i))this.marginRight=u(this.marginRight,f.legendWidth-m+l+c)}else if(q===\"left\"){if(!s(h))this.plotLeft=u(this.plotLeft,f.legendWidth+m+l+a)}else if(t===\"top\"){if(!s(g))this.plotTop=u(this.plotTop,\nf.legendHeight+p+l+b)}else if(t===\"bottom\"&&!s(j))this.marginBottom=u(this.marginBottom,f.legendHeight-p+l+d);this.extraBottomMargin&&(this.marginBottom+=this.extraBottomMargin);this.extraTopMargin&&(this.plotTop+=this.extraTopMargin);this.hasCartesianSeries&&o(this.axes,function(a){a.getOffset()});s(h)||(this.plotLeft+=e[3]);s(g)||(this.plotTop+=e[0]);s(j)||(this.marginBottom+=e[2]);s(i)||(this.marginRight+=e[1]);this.setChartSize()},initReflow:function(){function a(a){var g=c.width||ib(d,\"width\"),\nh=c.height||ib(d,\"height\"),a=a?a.target:E;if(!b.hasUserSize&&g&&h&&(a===E||a===y)){if(g!==b.containerWidth||h!==b.containerHeight)clearTimeout(e),b.reflowTimeout=e=setTimeout(function(){if(b.container)b.setSize(g,h,!1),b.hasUserSize=null},100);b.containerWidth=g;b.containerHeight=h}}var b=this,c=b.options.chart,d=b.renderTo,e;J(E,\"resize\",a);J(b,\"destroy\",function(){aa(E,\"resize\",a)})},setSize:function(a,b,c){var d=this,e,f,g;d.isResizing+=1;g=function(){d&&B(d,\"endResize\",null,function(){d.isResizing-=\n1})};Ka(c,d);d.oldChartHeight=d.chartHeight;d.oldChartWidth=d.chartWidth;if(s(a))d.chartWidth=e=u(0,t(a)),d.hasUserSize=!!e;if(s(b))d.chartHeight=f=u(0,t(b));M(d.container,{width:e+\"px\",height:f+\"px\"});d.setChartSize(!0);d.renderer.setSize(e,f,c);d.maxTicks=null;o(d.axes,function(a){a.isDirty=!0;a.setScale()});o(d.series,function(a){a.isDirty=!0});d.isDirtyLegend=!0;d.isDirtyBox=!0;d.getMargins();d.redraw(c);d.oldChartHeight=null;B(d,\"resize\");Da===!1?g():setTimeout(g,Da&&Da.duration||500)},setChartSize:function(a){var b=\nthis.inverted,c=this.renderer,d=this.chartWidth,e=this.chartHeight,f=this.options.chart,g=f.spacingTop,h=f.spacingRight,i=f.spacingBottom,j=f.spacingLeft,k=this.clipOffset,l,m,p,n;this.plotLeft=l=t(this.plotLeft);this.plotTop=m=t(this.plotTop);this.plotWidth=p=u(0,t(d-l-this.marginRight));this.plotHeight=n=u(0,t(e-m-this.marginBottom));this.plotSizeX=b?n:p;this.plotSizeY=b?p:n;this.plotBorderWidth=b=f.plotBorderWidth||0;this.spacingBox=c.spacingBox={x:j,y:g,width:d-j-h,height:e-g-i};this.plotBox=\nc.plotBox={x:l,y:m,width:p,height:n};c=ja(u(b,k[3])/2);d=ja(u(b,k[0])/2);this.clipBox={x:c,y:d,width:S(this.plotSizeX-u(b,k[1])/2-c),height:S(this.plotSizeY-u(b,k[2])/2-d)};a||o(this.axes,function(a){a.setAxisSize();a.setAxisTranslation()})},resetMargins:function(){var a=this.options.chart,b=a.spacingRight,c=a.spacingBottom,d=a.spacingLeft;this.plotTop=n(this.optionsMarginTop,a.spacingTop);this.marginRight=n(this.optionsMarginRight,b);this.marginBottom=n(this.optionsMarginBottom,c);this.plotLeft=\nn(this.optionsMarginLeft,d);this.axisOffset=[0,0,0,0];this.clipOffset=[0,0,0,0]},drawChartBox:function(){var a=this.options.chart,b=this.renderer,c=this.chartWidth,d=this.chartHeight,e=this.chartBackground,f=this.plotBackground,g=this.plotBorder,h=this.plotBGImage,i=a.borderWidth||0,j=a.backgroundColor,k=a.plotBackgroundColor,l=a.plotBackgroundImage,m=a.plotBorderWidth||0,p,n=this.plotLeft,o=this.plotTop,t=this.plotWidth,s=this.plotHeight,u=this.plotBox,r=this.clipRect,w=this.clipBox;p=i+(a.shadow?\n8:0);if(i||j)if(e)e.animate(e.crisp(null,null,null,c-p,d-p));else{e={fill:j||R};if(i)e.stroke=a.borderColor,e[\"stroke-width\"]=i;this.chartBackground=b.rect(p/2,p/2,c-p,d-p,a.borderRadius,i).attr(e).add().shadow(a.shadow)}if(k)f?f.animate(u):this.plotBackground=b.rect(n,o,t,s,0).attr({fill:k}).add().shadow(a.plotShadow);if(l)h?h.animate(u):this.plotBGImage=b.image(l,n,o,t,s).add();r?r.animate({width:w.width,height:w.height}):this.clipRect=b.clipRect(w);if(m)g?g.animate(g.crisp(null,n,o,t,s)):this.plotBorder=\nb.rect(n,o,t,s,0,m).attr({stroke:a.plotBorderColor,\"stroke-width\":m,zIndex:1}).add();this.isDirtyBox=!1},propFromSeries:function(){var a=this,b=a.options.chart,c,d=a.options.series,e,f;o([\"inverted\",\"angular\",\"polar\"],function(g){c=$[b.type||b.defaultSeriesType];f=a[g]||b[g]||c&&c.prototype[g];for(e=d&&d.length;!f&&e--;)(c=$[d[e].type])&&c.prototype[g]&&(f=!0);a[g]=f})},render:function(){var a=this,b=a.axes,c=a.renderer,d=a.options,e=d.labels,f=d.credits,g;a.setTitle();a.legend=new vb(a,d.legend);\na.getStacks();o(b,function(a){a.setScale()});a.getMargins();a.maxTicks=null;o(b,function(a){a.setTickPositions(!0);a.setMaxTicks()});a.adjustTickAmounts();a.getMargins();a.drawChartBox();a.hasCartesianSeries&&o(b,function(a){a.render()});if(!a.seriesGroup)a.seriesGroup=c.g(\"series-group\").attr({zIndex:3}).add();o(a.series,function(a){a.translate();a.setTooltipPoints();a.render()});e.items&&o(e.items,function(b){var d=r(e.style,b.style),f=A(d.left)+a.plotLeft,g=A(d.top)+a.plotTop+12;delete d.left;\ndelete d.top;c.text(b.html,f,g).attr({zIndex:2}).css(d).add()});if(f.enabled&&!a.credits)g=f.href,a.credits=c.text(f.text,0,0).on(\"click\",function(){if(g)location.href=g}).attr({align:f.position.align,zIndex:8}).css(f.style).add().align(f.position);a.hasRendered=!0},destroy:function(){var a=this,b=a.axes,c=a.series,d=a.container,e,f=d&&d.parentNode;B(a,\"destroy\");Fa[a.index]=v;a.renderTo.removeAttribute(\"data-highcharts-chart\");aa(a);for(e=b.length;e--;)b[e]=b[e].destroy();for(e=c.length;e--;)c[e]=\nc[e].destroy();o(\"title,subtitle,chartBackground,plotBackground,plotBGImage,plotBorder,seriesGroup,clipRect,credits,pointer,scroller,rangeSelector,legend,resetZoomButton,tooltip,renderer\".split(\",\"),function(b){var c=a[b];c&&c.destroy&&(a[b]=c.destroy())});if(d)d.innerHTML=\"\",aa(d),f&&Ta(d);for(e in a)delete a[e]},isReadyToRender:function(){var a=this;return!Y&&E==E.top&&y.readyState!==\"complete\"||Z&&!E.canvg?(Z?Tb.push(function(){a.firstRender()},a.options.global.canvasToolsURL):y.attachEvent(\"onreadystatechange\",\nfunction(){y.detachEvent(\"onreadystatechange\",a.firstRender);y.readyState===\"complete\"&&a.firstRender()}),!1):!0},firstRender:function(){var a=this,b=a.options,c=a.callback;if(a.isReadyToRender())a.getContainer(),B(a,\"init\"),a.resetMargins(),a.setChartSize(),a.propFromSeries(),a.getAxes(),o(b.series||[],function(b){a.initSeries(b)}),B(a,\"beforeRender\"),a.pointer=new ub(a,b),a.render(),a.renderer.draw(),c&&c.apply(a,[a]),o(a.callbacks,function(b){b.apply(a,[a])}),a.cloneRenderTo(!0),B(a,\"load\")}};\nwb.prototype.callbacks=[];var Pa=function(){};Pa.prototype={init:function(a,b,c){this.series=a;this.applyOptions(b,c);this.pointAttr={};if(a.options.colorByPoint&&(b=a.options.colors||a.chart.options.colors,this.color=this.color||b[a.colorCounter++],a.colorCounter===b.length))a.colorCounter=0;a.chart.pointCount++;return this},applyOptions:function(a,b){var c=this.series,d=c.pointValKey,a=Pa.prototype.optionsToObject.call(this,a);r(this,a);this.options=this.options?r(this.options,a):a;if(d)this.y=\nthis[d];if(this.x===v&&c)this.x=b===v?c.autoIncrement():b;return this},optionsToObject:function(a){var b,c=this.series,d=c.pointArrayMap||[\"y\"],e=d.length,f=0,g=0;if(typeof a===\"number\"||a===null)b={y:a};else if(Ha(a)){b={};if(a.length>e){c=typeof a[0];if(c===\"string\")b.name=a[0];else if(c===\"number\")b.x=a[0];f++}for(;g<e;)b[d[g++]]=a[f++]}else if(typeof a===\"object\"){b=a;if(a.dataLabels)c._hasPointLabels=!0;if(a.marker)c._hasPointMarkers=!0}return b},destroy:function(){var a=this.series.chart,b=\na.hoverPoints,c;a.pointCount--;if(b&&(this.setState(),fa(b,this),!b.length))a.hoverPoints=null;if(this===a.hoverPoint)this.onMouseOut();if(this.graphic||this.dataLabel)aa(this),this.destroyElements();this.legendItem&&a.legend.destroyItem(this);for(c in this)this[c]=null},destroyElements:function(){for(var a=\"graphic,dataLabel,dataLabelUpper,group,connector,shadowGroup\".split(\",\"),b,c=6;c--;)b=a[c],this[b]&&(this[b]=this[b].destroy())},getLabelConfig:function(){return{x:this.category,y:this.y,key:this.name||\nthis.category,series:this.series,point:this,percentage:this.percentage,total:this.total||this.stackTotal}},select:function(a,b){var c=this,d=c.series,e=d.chart,a=n(a,!c.selected);c.firePointEvent(a?\"select\":\"unselect\",{accumulate:b},function(){c.selected=c.options.selected=a;d.options.data[na(c,d.data)]=c.options;c.setState(a&&\"select\");b||o(e.getSelectedPoints(),function(a){if(a.selected&&a!==c)a.selected=a.options.selected=!1,d.options.data[na(a,d.data)]=a.options,a.setState(\"\"),a.firePointEvent(\"unselect\")})})},\nonMouseOver:function(a){var b=this.series,c=b.chart,d=c.tooltip,e=c.hoverPoint;if(e&&e!==this)e.onMouseOut();this.firePointEvent(\"mouseOver\");d&&(!d.shared||b.noSharedTooltip)&&d.refresh(this,a);this.setState(\"hover\");c.hoverPoint=this},onMouseOut:function(){var a=this.series.chart,b=a.hoverPoints;if(!b||na(this,b)===-1)this.firePointEvent(\"mouseOut\"),this.setState(),a.hoverPoint=null},tooltipFormatter:function(a){var b=this.series,c=b.tooltipOptions,d=n(c.valueDecimals,\"\"),e=c.valuePrefix||\"\",f=\nc.valueSuffix||\"\";o(b.pointArrayMap||[\"y\"],function(b){b=\"{point.\"+b;if(e||f)a=a.replace(b+\"}\",e+b+\"}\"+f);a=a.replace(b+\"}\",b+\":,.\"+d+\"f}\")});return Ba(a,{point:this,series:this.series})},update:function(a,b,c){var d=this,e=d.series,f=d.graphic,g,h=e.data,i=e.chart,j=e.options,b=n(b,!0);d.firePointEvent(\"update\",{options:a},function(){d.applyOptions(a);U(a)&&(e.getAttribs(),f&&f.attr(d.pointAttr[e.state]));g=na(d,h);e.xData[g]=d.x;e.yData[g]=e.toYData?e.toYData(d):d.y;e.zData[g]=d.z;j.data[g]=d.options;\ne.isDirty=e.isDirtyData=i.isDirtyBox=!0;j.legendType===\"point\"&&i.legend.destroyItem(d);b&&i.redraw(c)})},remove:function(a,b){var c=this,d=c.series,e=d.chart,f,g=d.data;Ka(b,e);a=n(a,!0);c.firePointEvent(\"remove\",null,function(){f=na(c,g);g.splice(f,1);d.options.data.splice(f,1);d.xData.splice(f,1);d.yData.splice(f,1);d.zData.splice(f,1);c.destroy();d.isDirty=!0;d.isDirtyData=!0;a&&e.redraw()})},firePointEvent:function(a,b,c){var d=this,e=this.series.options;(e.point.events[a]||d.options&&d.options.events&&\nd.options.events[a])&&this.importEvents();a===\"click\"&&e.allowPointSelect&&(c=function(a){d.select(null,a.ctrlKey||a.metaKey||a.shiftKey)});B(this,a,b,c)},importEvents:function(){if(!this.hasImportedEvents){var a=w(this.series.options.point,this.options).events,b;this.events=a;for(b in a)J(this,b,a[b]);this.hasImportedEvents=!0}},setState:function(a){var b=this.plotX,c=this.plotY,d=this.series,e=d.options.states,f=X[d.type].marker&&d.options.marker,g=f&&!f.enabled,h=f&&f.states[a],i=h&&h.enabled===\n!1,j=d.stateMarkerGraphic,k=this.marker||{},l=d.chart,m=this.pointAttr,a=a||\"\";if(!(a===this.state||this.selected&&a!==\"select\"||e[a]&&e[a].enabled===!1||a&&(i||g&&!h.enabled))){if(this.graphic)e=f&&this.graphic.symbolName&&m[a].r,this.graphic.attr(w(m[a],e?{x:b-e,y:c-e,width:2*e,height:2*e}:{}));else{if(a&&h)e=h.radius,k=k.symbol||d.symbol,j&&j.currentSymbol!==k&&(j=j.destroy()),j?j.attr({x:b-e,y:c-e}):(d.stateMarkerGraphic=j=l.renderer.symbol(k,b-e,c-e,2*e,2*e).attr(m[a]).add(d.markerGroup),j.currentSymbol=\nk);if(j)j[a&&l.isInsidePlot(b,c)?\"show\":\"hide\"]()}this.state=a}}};var Q=function(){};Q.prototype={isCartesian:!0,type:\"line\",pointClass:Pa,sorted:!0,requireSorting:!0,pointAttrToOptions:{stroke:\"lineColor\",\"stroke-width\":\"lineWidth\",fill:\"fillColor\",r:\"radius\"},colorCounter:0,init:function(a,b){var c,d,e=a.series;this.chart=a;this.options=b=this.setOptions(b);this.bindAxes();r(this,{name:b.name,state:\"\",pointAttr:{},visible:b.visible!==!1,selected:b.selected===!0});if(Z)b.animation=!1;d=b.events;\nfor(c in d)J(this,c,d[c]);if(d&&d.click||b.point&&b.point.events&&b.point.events.click||b.allowPointSelect)a.runTrackerClick=!0;this.getColor();this.getSymbol();this.setData(b.data,!1);if(this.isCartesian)a.hasCartesianSeries=!0;e.push(this);this._i=e.length-1;Jb(e,function(a,b){return n(a.options.index,a._i)-n(b.options.index,a._i)});o(e,function(a,b){a.index=b;a.name=a.name||\"Series \"+(b+1)});c=b.linkedTo;this.linkedSeries=[];if(da(c)&&(c=c===\":previous\"?e[this.index-1]:a.get(c)))c.linkedSeries.push(this),\nthis.linkedParent=c},bindAxes:function(){var a=this,b=a.options,c=a.chart,d;a.isCartesian&&o([\"xAxis\",\"yAxis\"],function(e){o(c[e],function(c){d=c.options;if(b[e]===d.index||b[e]!==v&&b[e]===d.id||b[e]===v&&d.index===0)c.series.push(a),a[e]=c,c.isDirty=!0});a[e]||ua(18,!0)})},autoIncrement:function(){var a=this.options,b=this.xIncrement,b=n(b,a.pointStart,0);this.pointInterval=n(this.pointInterval,a.pointInterval,1);this.xIncrement=b+this.pointInterval;return b},getSegments:function(){var a=-1,b=[],\nc,d=this.points,e=d.length;if(e)if(this.options.connectNulls){for(c=e;c--;)d[c].y===null&&d.splice(c,1);d.length&&(b=[d])}else o(d,function(c,g){c.y===null?(g>a+1&&b.push(d.slice(a+1,g)),a=g):g===e-1&&b.push(d.slice(a+1,g+1))});this.segments=b},setOptions:function(a){var b=this.chart.options,c=b.plotOptions,d=c[this.type];this.userOptions=a;a=w(d,c.series,a);this.tooltipOptions=w(b.tooltip,a.tooltip);d.marker===null&&delete a.marker;return a},getColor:function(){var a=this.options,b=this.userOptions,\nc=this.chart.options.colors,d=this.chart.counters,e;e=a.color||X[this.type].color;if(!e&&!a.colorByPoint)s(b._colorIndex)?a=b._colorIndex:(b._colorIndex=d.color,a=d.color++),e=c[a];this.color=e;d.wrapColor(c.length)},getSymbol:function(){var a=this.userOptions,b=this.options.marker,c=this.chart,d=c.options.symbols,c=c.counters;this.symbol=b.symbol;if(!this.symbol)s(a._symbolIndex)?a=a._symbolIndex:(a._symbolIndex=c.symbol,a=c.symbol++),this.symbol=d[a];if(/^url/.test(this.symbol))b.radius=0;c.wrapSymbol(d.length)},\ndrawLegendSymbol:function(a){var b=this.options,c=b.marker,d=a.options,e;e=d.symbolWidth;var f=this.chart.renderer,g=this.legendGroup,a=a.baseline-t(f.fontMetrics(d.itemStyle.fontSize).b*0.3);if(b.lineWidth){d={\"stroke-width\":b.lineWidth};if(b.dashStyle)d.dashstyle=b.dashStyle;this.legendLine=f.path([\"M\",0,a,\"L\",e,a]).attr(d).add(g)}if(c&&c.enabled)b=c.radius,this.legendSymbol=e=f.symbol(this.symbol,e/2-b,a-b,2*b,2*b).add(g),e.isMarker=!0},addPoint:function(a,b,c,d){var e=this.options,f=this.data,\ng=this.graph,h=this.area,i=this.chart,j=this.xData,k=this.yData,l=this.zData,m=this.names,p=g&&g.shift||0,q=e.data;Ka(d,i);c&&o([g,h,this.graphNeg,this.areaNeg],function(a){if(a)a.shift=p+1});if(h)h.isArea=!0;b=n(b,!0);d={series:this};this.pointClass.prototype.applyOptions.apply(d,[a]);j.push(d.x);k.push(this.toYData?this.toYData(d):d.y);l.push(d.z);if(m)m[d.x]=d.name;q.push(a);e.legendType===\"point\"&&this.generatePoints();c&&(f[0]&&f[0].remove?f[0].remove(!1):(f.shift(),j.shift(),k.shift(),l.shift(),\nq.shift()));this.isDirtyData=this.isDirty=!0;b&&(this.getAttribs(),i.redraw())},setData:function(a,b){var c=this.points,d=this.options,e=this.chart,f=null,g=this.xAxis,h=g&&g.categories&&!g.categories.length?[]:null,i;this.xIncrement=null;this.pointRange=g&&g.categories?1:d.pointRange;this.colorCounter=0;var j=[],k=[],l=[],m=a?a.length:[];i=n(d.turboThreshold,1E3);var p=this.pointArrayMap,p=p&&p.length,o=!!this.toYData;if(i&&m>i){for(i=0;f===null&&i<m;)f=a[i],i++;if(pa(f)){f=n(d.pointStart,0);d=n(d.pointInterval,\n1);for(i=0;i<m;i++)j[i]=f,k[i]=a[i],f+=d;this.xIncrement=f}else if(Ha(f))if(p)for(i=0;i<m;i++)d=a[i],j[i]=d[0],k[i]=d.slice(1,p+1);else for(i=0;i<m;i++)d=a[i],j[i]=d[0],k[i]=d[1]}else for(i=0;i<m;i++)if(a[i]!==v&&(d={series:this},this.pointClass.prototype.applyOptions.apply(d,[a[i]]),j[i]=d.x,k[i]=o?this.toYData(d):d.y,l[i]=d.z,h&&d.name))h[d.x]=d.name;da(k[0])&&ua(14,!0);this.data=[];this.options.data=a;this.xData=j;this.yData=k;this.zData=l;this.names=h;for(i=c&&c.length||0;i--;)c[i]&&c[i].destroy&&\nc[i].destroy();if(g)g.minRange=g.userMinRange;this.isDirty=this.isDirtyData=e.isDirtyBox=!0;n(b,!0)&&e.redraw(!1)},remove:function(a,b){var c=this,d=c.chart,a=n(a,!0);if(!c.isRemoving)c.isRemoving=!0,B(c,\"remove\",null,function(){c.destroy();d.isDirtyLegend=d.isDirtyBox=!0;a&&d.redraw(b)});c.isRemoving=!1},processData:function(a){var b=this.xData,c=this.yData,d=b.length,e;e=0;var f,g,h=this.xAxis,i=this.options,j=i.cropThreshold,k=this.isCartesian;if(k&&!this.isDirty&&!h.isDirty&&!this.yAxis.isDirty&&\n!a)return!1;if(k&&this.sorted&&(!j||d>j||this.forceCrop))if(a=h.min,h=h.max,b[d-1]<a||b[0]>h)b=[],c=[];else if(b[0]<a||b[d-1]>h)e=this.cropData(this.xData,this.yData,a,h),b=e.xData,c=e.yData,e=e.start,f=!0;for(h=b.length-1;h>=0;h--)d=b[h]-b[h-1],d>0&&(g===v||d<g)?g=d:d<0&&this.requireSorting&&ua(15);this.cropped=f;this.cropStart=e;this.processedXData=b;this.processedYData=c;if(i.pointRange===null)this.pointRange=g||1;this.closestPointRange=g},cropData:function(a,b,c,d){var e=a.length,f=0,g=e,h;for(h=\n0;h<e;h++)if(a[h]>=c){f=u(0,h-1);break}for(;h<e;h++)if(a[h]>d){g=h+1;break}return{xData:a.slice(f,g),yData:b.slice(f,g),start:f,end:g}},generatePoints:function(){var a=this.options.data,b=this.data,c,d=this.processedXData,e=this.processedYData,f=this.pointClass,g=d.length,h=this.cropStart||0,i,j=this.hasGroupedData,k,l=[],m;if(!b&&!j)b=[],b.length=a.length,b=this.data=b;for(m=0;m<g;m++)i=h+m,j?l[m]=(new f).init(this,[d[m]].concat(ha(e[m]))):(b[i]?k=b[i]:a[i]!==v&&(b[i]=k=(new f).init(this,a[i],d[m])),\nl[m]=k);if(b&&(g!==(c=b.length)||j))for(m=0;m<c;m++)if(m===h&&!j&&(m+=g),b[m])b[m].destroyElements(),b[m].plotX=v;this.data=b;this.points=l},setStackedPoints:function(){if(this.options.stacking&&!(this.visible!==!0&&this.chart.options.chart.ignoreHiddenSeries!==!1)){var a=this.processedXData,b=this.processedYData,c=b.length,d=this.options,e=d.threshold,f=d.stack,d=d.stacking,g=this.stackKey,h=\"-\"+g,i=this.yAxis,j=i.stacks,k=i.oldStacks,l=i.stacksMax,m,p,n,o,t,s;for(t=0;t<c;t++)if(p=a[t],s=b[t],o=\n(m=s<e)?h:g,l[o]||(l[o]=s),j[o]||(j[o]={}),k[o]&&k[o][p]?(j[o][p]=k[o][p],j[o][p].total=null):j[o][p]||(j[o][p]=new Lb(i,i.options.stackLabels,m,p,f,d)),n=j[o][p],p=n.total,n.addValue(s),n.cacheExtremes(this,[p,p+s]),n.total>l[o]&&!m)l[o]=n.total;else if(n.total<l[o]&&m)l[o]=n.total;i.oldStacks={}}},getExtremes:function(){var a=this.xAxis,b=this.yAxis,c=this.stackKey,d=this.options,e=d.threshold,f=this.processedXData,g=this.processedYData,h=g.length,i=[],j=0,k=a.min,a=a.max,l,m,p;d.stacking&&(m=b.stacksMax[\"-\"+\nc]||e,p=b.stacksMax[c]||e);if(!s(m)||!s(p)){for(d=0;d<h;d++)if(l=f[d],c=g[d],e=c!==null&&c!==v&&(!b.isLog||c.length||c>0),l=this.getExtremesFromAll||this.cropped||(f[d+1]||l)>=k&&(f[d-1]||l)<=a,e&&l)if(e=c.length)for(;e--;)c[e]!==null&&(i[j++]=c[e]);else i[j++]=c;m=n(m,Ia(i));p=n(p,ta(i))}this.dataMin=m;this.dataMax=p},translate:function(){this.processedXData||this.processData();this.generatePoints();for(var a=this.options,b=a.stacking,c=this.xAxis,d=c.categories,e=this.yAxis,f=this.points,g=f.length,\nh=!!this.modifyValue,i=a.pointPlacement,j=i===\"between\"||pa(i),k=a.threshold,a=0;a<g;a++){var l=f[a],m=l.x,p=l.y,o=l.low,u=e.stacks[(p<k?\"-\":\"\")+this.stackKey],r;if(e.isLog&&p<=0)l.y=p=null;l.plotX=c.translate(m,0,0,0,1,i);if(b&&this.visible&&u&&u[m])u=u[m],r=u.total,u.cum=o=u.cum-p,p=o+p,u.cum===0&&(o=n(k,e.min)),e.isLog&&o<=0&&(o=null),b===\"percent\"&&(o=r?o*100/r:0,p=r?p*100/r:0),l.percentage=r?l.y*100/r:0,l.total=l.stackTotal=r,l.stackY=p,u.setOffset(this.pointXOffset||0,this.barW||0);l.yBottom=\ns(o)?e.translate(o,0,1,0,1):null;h&&(p=this.modifyValue(p,l));l.plotY=typeof p===\"number\"&&p!==Infinity?t(e.translate(p,0,1,0,1)*10)/10:v;l.clientX=j?c.translate(m,0,0,0,1):l.plotX;l.negative=l.y<(k||0);l.category=d&&d[l.x]!==v?d[l.x]:l.x}this.getSegments()},setTooltipPoints:function(a){var b=[],c,d,e=(c=this.xAxis)?c.tooltipLen||c.len:this.chart.plotSizeX,f,g,h,i=[];if(this.options.enableMouseTracking!==!1){if(a)this.tooltipPoints=null;o(this.segments||this.points,function(a){b=b.concat(a)});c&&\nc.reversed&&(b=b.reverse());this.orderTooltipPoints&&this.orderTooltipPoints(b);a=b.length;for(h=0;h<a;h++){f=b[h];g=b[h+1];c=b[h-1]?d+1:0;for(d=b[h+1]?I(u(0,S((f.clientX+(g?g.wrappedClientX||g.clientX:e))/2)),e):e;c>=0&&c<=d;)i[c++]=f}this.tooltipPoints=i}},tooltipHeaderFormatter:function(a){var b=this.tooltipOptions,c=b.xDateFormat,d=b.dateTimeLabelFormats,e=this.xAxis,f=e&&e.options.type===\"datetime\",b=b.headerFormat,e=e&&e.closestPointRange,g;if(f&&!c)if(e)for(g in z){if(z[g]>=e){c=d[g];break}}else c=\nd.day;f&&c&&pa(a.key)&&(b=b.replace(\"{point.key}\",\"{point.key:\"+c+\"}\"));return Ba(b,{point:a,series:this})},onMouseOver:function(){var a=this.chart,b=a.hoverSeries;if(b&&b!==this)b.onMouseOut();this.options.events.mouseOver&&B(this,\"mouseOver\");this.setState(\"hover\");a.hoverSeries=this},onMouseOut:function(){var a=this.options,b=this.chart,c=b.tooltip,d=b.hoverPoint;if(d)d.onMouseOut();this&&a.events.mouseOut&&B(this,\"mouseOut\");c&&!a.stickyTracking&&(!c.shared||this.noSharedTooltip)&&c.hide();this.setState();\nb.hoverSeries=null},animate:function(a){var b=this,c=b.chart,d=c.renderer,e;e=b.options.animation;var f=c.clipBox,g=c.inverted,h;if(e&&!U(e))e=X[b.type].animation;h=\"_sharedClip\"+e.duration+e.easing;if(a)a=c[h],e=c[h+\"m\"],a||(c[h]=a=d.clipRect(r(f,{width:0})),c[h+\"m\"]=e=d.clipRect(-99,g?-c.plotLeft:-c.plotTop,99,g?c.chartWidth:c.chartHeight)),b.group.clip(a),b.markerGroup.clip(e),b.sharedClipKey=h;else{if(a=c[h])a.animate({width:c.plotSizeX},e),c[h+\"m\"].animate({width:c.plotSizeX+99},e);b.animate=\nnull;b.animationTimeout=setTimeout(function(){b.afterAnimate()},e.duration)}},afterAnimate:function(){var a=this.chart,b=this.sharedClipKey,c=this.group;c&&this.options.clip!==!1&&(c.clip(a.clipRect),this.markerGroup.clip());setTimeout(function(){b&&a[b]&&(a[b]=a[b].destroy(),a[b+\"m\"]=a[b+\"m\"].destroy())},100)},drawPoints:function(){var a,b=this.points,c=this.chart,d,e,f,g,h,i,j,k,l=this.options.marker,m,p=this.markerGroup;if(l.enabled||this._hasPointMarkers)for(f=b.length;f--;)if(g=b[f],d=S(g.plotX),\ne=g.plotY,k=g.graphic,i=g.marker||{},a=l.enabled&&i.enabled===v||i.enabled,m=c.isInsidePlot(t(d),e,c.inverted),a&&e!==v&&!isNaN(e)&&g.y!==null)if(a=g.pointAttr[g.selected?\"select\":\"\"],h=a.r,i=n(i.symbol,this.symbol),j=i.indexOf(\"url\")===0,k)k.attr({visibility:m?Y?\"inherit\":\"visible\":\"hidden\"}).animate(r({x:d-h,y:e-h},k.symbolName?{width:2*h,height:2*h}:{}));else{if(m&&(h>0||j))g.graphic=c.renderer.symbol(i,d-h,e-h,2*h,2*h).attr(a).add(p)}else if(k)g.graphic=k.destroy()},convertAttribs:function(a,\nb,c,d){var e=this.pointAttrToOptions,f,g,h={},a=a||{},b=b||{},c=c||{},d=d||{};for(f in e)g=e[f],h[f]=n(a[g],b[f],c[f],d[f]);return h},getAttribs:function(){var a=this,b=a.options,c=X[a.type].marker?b.marker:b,d=c.states,e=d.hover,f,g=a.color,h={stroke:g,fill:g},i=a.points||[],j=[],k,l=a.pointAttrToOptions,m=b.negativeColor,p;b.marker?(e.radius=e.radius||c.radius+2,e.lineWidth=e.lineWidth||c.lineWidth+1):e.color=e.color||oa(e.color||g).brighten(e.brightness).get();j[\"\"]=a.convertAttribs(c,h);o([\"hover\",\n\"select\"],function(b){j[b]=a.convertAttribs(d[b],j[\"\"])});a.pointAttr=j;for(g=i.length;g--;){h=i[g];if((c=h.options&&h.options.marker||h.options)&&c.enabled===!1)c.radius=0;if(h.negative&&m)h.color=h.fillColor=m;f=b.colorByPoint||h.color;if(h.options)for(p in l)s(c[l[p]])&&(f=!0);if(f){c=c||{};k=[];d=c.states||{};f=d.hover=d.hover||{};if(!b.marker)f.color=oa(f.color||h.color).brighten(f.brightness||e.brightness).get();k[\"\"]=a.convertAttribs(r({color:h.color},c),j[\"\"]);k.hover=a.convertAttribs(d.hover,\nj.hover,k[\"\"]);k.select=a.convertAttribs(d.select,j.select,k[\"\"]);if(h.negative&&b.marker&&m)k[\"\"].fill=k.hover.fill=k.select.fill=a.convertAttribs({fillColor:m}).fill}else k=j;h.pointAttr=k}},update:function(a,b){var c=this.chart,d=this.type,a=w(this.userOptions,{animation:!1,index:this.index,pointStart:this.xData[0]},{data:this.options.data},a);this.remove(!1);r(this,$[a.type||d].prototype);this.init(c,a);n(b,!0)&&c.redraw(!1)},destroy:function(){var a=this,b=a.chart,c=/AppleWebKit\\/533/.test(Ea),\nd,e,f=a.data||[],g,h,i;B(a,\"destroy\");aa(a);o([\"xAxis\",\"yAxis\"],function(b){if(i=a[b])fa(i.series,a),i.isDirty=i.forceRedraw=!0});a.legendItem&&a.chart.legend.destroyItem(a);for(e=f.length;e--;)(g=f[e])&&g.destroy&&g.destroy();a.points=null;clearTimeout(a.animationTimeout);o(\"area,graph,dataLabelsGroup,group,markerGroup,tracker,graphNeg,areaNeg,posClip,negClip\".split(\",\"),function(b){a[b]&&(d=c&&b===\"group\"?\"hide\":\"destroy\",a[b][d]())});if(b.hoverSeries===a)b.hoverSeries=null;fa(b.series,a);for(h in a)delete a[h]},\ndrawDataLabels:function(){var a=this,b=a.options.dataLabels,c=a.points,d,e,f,g;if(b.enabled||a._hasPointLabels)a.dlProcessOptions&&a.dlProcessOptions(b),g=a.plotGroup(\"dataLabelsGroup\",\"data-labels\",a.visible?\"visible\":\"hidden\",b.zIndex||6),e=b,o(c,function(c){var i,j=c.dataLabel,k,l,m=c.connector,p=!0;d=c.options&&c.options.dataLabels;i=e.enabled||d&&d.enabled;if(j&&!i)c.dataLabel=j.destroy();else if(i){b=w(e,d);i=b.rotation;k=c.getLabelConfig();f=b.format?Ba(b.format,k):b.formatter.call(k,b);b.style.color=\nn(b.color,b.style.color,a.color,\"black\");if(j)if(s(f))j.attr({text:f}),p=!1;else{if(c.dataLabel=j=j.destroy(),m)c.connector=m.destroy()}else if(s(f)){j={fill:b.backgroundColor,stroke:b.borderColor,\"stroke-width\":b.borderWidth,r:b.borderRadius||0,rotation:i,padding:b.padding,zIndex:1};for(l in j)j[l]===v&&delete j[l];j=c.dataLabel=a.chart.renderer[i?\"text\":\"label\"](f,0,-999,null,null,null,b.useHTML).attr(j).css(b.style).add(g).shadow(b.shadow)}j&&a.alignDataLabel(c,j,b,null,p)}})},alignDataLabel:function(a,\nb,c,d,e){var f=this.chart,g=f.inverted,h=n(a.plotX,-999),i=n(a.plotY,-999),a=b.getBBox(),d=r({x:g?f.plotWidth-i:h,y:t(g?f.plotHeight-h:i),width:0,height:0},d);r(c,{width:a.width,height:a.height});c.rotation?(d={align:c.align,x:d.x+c.x+d.width/2,y:d.y+c.y+d.height/2},b[e?\"attr\":\"animate\"](d)):(b.align(c,null,d),d=b.alignAttr);b.attr({visibility:c.crop===!1||f.isInsidePlot(d.x,d.y)&&f.isInsidePlot(d.x+a.width,d.y+a.height)?f.renderer.isSVG?\"inherit\":\"visible\":\"hidden\"})},getSegmentPath:function(a){var b=\nthis,c=[],d=b.options.step;o(a,function(e,f){var g=e.plotX,h=e.plotY,i;b.getPointSpline?c.push.apply(c,b.getPointSpline(a,e,f)):(c.push(f?\"L\":\"M\"),d&&f&&(i=a[f-1],d===\"right\"?c.push(i.plotX,h):d===\"center\"?c.push((i.plotX+g)/2,i.plotY,(i.plotX+g)/2,h):c.push(g,i.plotY)),c.push(e.plotX,e.plotY))});return c},getGraphPath:function(){var a=this,b=[],c,d=[];o(a.segments,function(e){c=a.getSegmentPath(e);e.length>1?b=b.concat(c):d.push(e[0])});a.singlePoints=d;return a.graphPath=b},drawGraph:function(){var a=\nthis,b=this.options,c=[[\"graph\",b.lineColor||this.color]],d=b.lineWidth,e=b.dashStyle,f=this.getGraphPath(),g=b.negativeColor;g&&c.push([\"graphNeg\",g]);o(c,function(c,g){var j=c[0],k=a[j];if(k)Wa(k),k.animate({d:f});else if(d&&f.length){k={stroke:c[1],\"stroke-width\":d,zIndex:1};if(e)k.dashstyle=e;a[j]=a.chart.renderer.path(f).attr(k).add(a.group).shadow(!g&&b.shadow)}})},clipNeg:function(){var a=this.options,b=this.chart,c=b.renderer,d=a.negativeColor||a.negativeFillColor,e,f=this.graph,g=this.area,\nh=this.posClip,i=this.negClip;e=b.chartWidth;var j=b.chartHeight,k=u(e,j),l=this.yAxis;if(d&&(f||g)){d=t(l.toPixels(a.threshold||0,!0));a={x:0,y:0,width:k,height:d};k={x:0,y:d,width:k,height:k};if(b.inverted)a.height=k.y=b.plotWidth-d,c.isVML&&(a={x:b.plotWidth-d-b.plotLeft,y:0,width:e,height:j},k={x:d+b.plotLeft-e,y:0,width:b.plotLeft+d,height:e});l.reversed?(b=k,e=a):(b=a,e=k);h?(h.animate(b),i.animate(e)):(this.posClip=h=c.clipRect(b),this.negClip=i=c.clipRect(e),f&&this.graphNeg&&(f.clip(h),this.graphNeg.clip(i)),\ng&&(g.clip(h),this.areaNeg.clip(i)))}},invertGroups:function(){function a(){var a={width:b.yAxis.len,height:b.xAxis.len};o([\"group\",\"markerGroup\"],function(c){b[c]&&b[c].attr(a).invert()})}var b=this,c=b.chart;if(b.xAxis)J(c,\"resize\",a),J(b,\"destroy\",function(){aa(c,\"resize\",a)}),a(),b.invertGroups=a},plotGroup:function(a,b,c,d,e){var f=this[a],g=!f;g&&(this[a]=f=this.chart.renderer.g(b).attr({visibility:c,zIndex:d||0.1}).add(e));f[g?\"attr\":\"animate\"](this.getPlotBox());return f},getPlotBox:function(){return{translateX:this.xAxis?\nthis.xAxis.left:this.chart.plotLeft,translateY:this.yAxis?this.yAxis.top:this.chart.plotTop,scaleX:1,scaleY:1}},render:function(){var a=this.chart,b,c=this.options,d=c.animation&&!!this.animate&&a.renderer.isSVG,e=this.visible?\"visible\":\"hidden\",f=c.zIndex,g=this.hasRendered,h=a.seriesGroup;b=this.plotGroup(\"group\",\"series\",e,f,h);this.markerGroup=this.plotGroup(\"markerGroup\",\"markers\",e,f,h);d&&this.animate(!0);this.getAttribs();b.inverted=this.isCartesian?a.inverted:!1;this.drawGraph&&(this.drawGraph(),\nthis.clipNeg());this.drawDataLabels();this.drawPoints();this.options.enableMouseTracking!==!1&&this.drawTracker();a.inverted&&this.invertGroups();c.clip!==!1&&!this.sharedClipKey&&!g&&b.clip(a.clipRect);d?this.animate():g||this.afterAnimate();this.isDirty=this.isDirtyData=!1;this.hasRendered=!0},redraw:function(){var a=this.chart,b=this.isDirtyData,c=this.group,d=this.xAxis,e=this.yAxis;c&&(a.inverted&&c.attr({width:a.plotWidth,height:a.plotHeight}),c.animate({translateX:n(d&&d.left,a.plotLeft),translateY:n(e&&\ne.top,a.plotTop)}));this.translate();this.setTooltipPoints(!0);this.render();b&&B(this,\"updatedData\")},setState:function(a){var b=this.options,c=this.graph,d=this.graphNeg,e=b.states,b=b.lineWidth,a=a||\"\";if(this.state!==a)this.state=a,e[a]&&e[a].enabled===!1||(a&&(b=e[a].lineWidth||b+1),c&&!c.dashstyle&&(a={\"stroke-width\":b},c.attr(a),d&&d.attr(a)))},setVisible:function(a,b){var c=this,d=c.chart,e=c.legendItem,f,g=d.options.chart.ignoreHiddenSeries,h=c.visible;f=(c.visible=a=c.userOptions.visible=\na===v?!h:a)?\"show\":\"hide\";o([\"group\",\"dataLabelsGroup\",\"markerGroup\",\"tracker\"],function(a){if(c[a])c[a][f]()});if(d.hoverSeries===c)c.onMouseOut();e&&d.legend.colorizeItem(c,a);c.isDirty=!0;c.options.stacking&&o(d.series,function(a){if(a.options.stacking&&a.visible)a.isDirty=!0});o(c.linkedSeries,function(b){b.setVisible(a,!1)});if(g)d.isDirtyBox=!0;b!==!1&&d.redraw();B(c,f)},show:function(){this.setVisible(!0)},hide:function(){this.setVisible(!1)},select:function(a){this.selected=a=a===v?!this.selected:\na;if(this.checkbox)this.checkbox.checked=a;B(this,a?\"select\":\"unselect\")},drawTracker:function(){var a=this,b=a.options,c=b.trackByArea,d=[].concat(c?a.areaPath:a.graphPath),e=d.length,f=a.chart,g=f.pointer,h=f.renderer,i=f.options.tooltip.snap,j=a.tracker,k=b.cursor,k=k&&{cursor:k},l=a.singlePoints,m,p=function(){if(f.hoverSeries!==a)a.onMouseOver()};if(e&&!c)for(m=e+1;m--;)d[m]===\"M\"&&d.splice(m+1,0,d[m+1]-i,d[m+2],\"L\"),(m&&d[m]===\"M\"||m===e)&&d.splice(m,0,\"L\",d[m-2]+i,d[m-1]);for(m=0;m<l.length;m++)e=\nl[m],d.push(\"M\",e.plotX-i,e.plotY,\"L\",e.plotX+i,e.plotY);if(j)j.attr({d:d});else if(a.tracker=j=h.path(d).attr({\"class\":\"highcharts-tracker\",\"stroke-linejoin\":\"round\",visibility:a.visible?\"visible\":\"hidden\",stroke:Pb,fill:c?Pb:R,\"stroke-width\":b.lineWidth+(c?0:2*i),zIndex:2}).addClass(\"highcharts-tracker\").on(\"mouseover\",p).on(\"mouseout\",function(a){g.onTrackerMouseOut(a)}).css(k).add(a.markerGroup),hb)j.on(\"touchstart\",p)}};L=ga(Q);$.line=L;X.area=w(W,{threshold:0});L=ga(Q,{type:\"area\",getSegments:function(){var a=\n[],b=[],c=[],d=this.xAxis,e=this.yAxis,f=e.stacks[this.stackKey],g={},h,i,j=this.points,k,l,m;if(this.options.stacking&&!this.cropped){for(l=0;l<j.length;l++)g[j[l].x]=j[l];for(m in f)c.push(+m);c.sort(function(a,b){return a-b});o(c,function(a){g[a]?b.push(g[a]):(h=d.translate(a),k=f[a].percent?f[a].total?f[a].cum*100/f[a].total:0:f[a].cum,i=e.toPixels(k,!0),b.push({y:null,plotX:h,clientX:h,plotY:i,yBottom:i,onMouseOver:xa}))});b.length&&a.push(b)}else Q.prototype.getSegments.call(this),a=this.segments;\nthis.segments=a},getSegmentPath:function(a){var b=Q.prototype.getSegmentPath.call(this,a),c=[].concat(b),d,e=this.options;b.length===3&&c.push(\"L\",b[1],b[2]);if(e.stacking&&!this.closedStacks)for(d=a.length-1;d>=0;d--)d<a.length-1&&e.step&&c.push(a[d+1].plotX,a[d].yBottom),c.push(a[d].plotX,a[d].yBottom);else this.closeSegment(c,a);this.areaPath=this.areaPath.concat(c);return b},closeSegment:function(a,b){var c=this.yAxis.getThreshold(this.options.threshold);a.push(\"L\",b[b.length-1].plotX,c,\"L\",b[0].plotX,\nc)},drawGraph:function(){this.areaPath=[];Q.prototype.drawGraph.apply(this);var a=this,b=this.areaPath,c=this.options,d=c.negativeColor,e=c.negativeFillColor,f=[[\"area\",this.color,c.fillColor]];(d||e)&&f.push([\"areaNeg\",d,e]);o(f,function(d){var e=d[0],f=a[e];f?f.animate({d:b}):a[e]=a.chart.renderer.path(b).attr({fill:n(d[2],oa(d[1]).setOpacity(n(c.fillOpacity,0.75)).get()),zIndex:0}).add(a.group)})},drawLegendSymbol:function(a,b){b.legendSymbol=this.chart.renderer.rect(0,a.baseline-11,a.options.symbolWidth,\n12,2).attr({zIndex:3}).add(b.legendGroup)}});$.area=L;X.spline=w(W);K=ga(Q,{type:\"spline\",getPointSpline:function(a,b,c){var d=b.plotX,e=b.plotY,f=a[c-1],g=a[c+1],h,i,j,k;if(f&&g){a=f.plotY;j=g.plotX;var g=g.plotY,l;h=(1.5*d+f.plotX)/2.5;i=(1.5*e+a)/2.5;j=(1.5*d+j)/2.5;k=(1.5*e+g)/2.5;l=(k-i)*(j-d)/(j-h)+e-k;i+=l;k+=l;i>a&&i>e?(i=u(a,e),k=2*e-i):i<a&&i<e&&(i=I(a,e),k=2*e-i);k>g&&k>e?(k=u(g,e),i=2*e-k):k<g&&k<e&&(k=I(g,e),i=2*e-k);b.rightContX=j;b.rightContY=k}c?(b=[\"C\",f.rightContX||f.plotX,f.rightContY||\nf.plotY,h||d,i||e,d,e],f.rightContX=f.rightContY=null):b=[\"M\",d,e];return b}});$.spline=K;X.areaspline=w(X.area);la=L.prototype;K=ga(K,{type:\"areaspline\",closedStacks:!0,getSegmentPath:la.getSegmentPath,closeSegment:la.closeSegment,drawGraph:la.drawGraph,drawLegendSymbol:la.drawLegendSymbol});$.areaspline=K;X.column=w(W,{borderColor:\"#FFFFFF\",borderWidth:1,borderRadius:0,groupPadding:0.2,marker:null,pointPadding:0.1,minPointLength:0,cropThreshold:50,pointRange:null,states:{hover:{brightness:0.1,shadow:!1},\nselect:{color:\"#C0C0C0\",borderColor:\"#000000\",shadow:!1}},dataLabels:{align:null,verticalAlign:null,y:null},stickyTracking:!1,threshold:0});K=ga(Q,{type:\"column\",tooltipOutsidePlot:!0,pointAttrToOptions:{stroke:\"borderColor\",\"stroke-width\":\"borderWidth\",fill:\"color\",r:\"borderRadius\"},trackerGroups:[\"group\",\"dataLabelsGroup\"],init:function(){Q.prototype.init.apply(this,arguments);var a=this,b=a.chart;b.hasRendered&&o(b.series,function(b){if(b.type===a.type)b.isDirty=!0})},getColumnMetrics:function(){var a=\nthis,b=a.options,c=this.xAxis,d=c.reversed,e,f={},g,h=0;b.grouping===!1?h=1:o(a.yAxis.series,function(b){var c=b.options;if(b.type===a.type&&b.visible&&a.options.group===c.group)c.stacking?(e=b.stackKey,f[e]===v&&(f[e]=h++),g=f[e]):c.grouping!==!1&&(g=h++),b.columnIndex=g});var c=I(P(c.transA)*(c.ordinalSlope||b.pointRange||c.closestPointRange||1),c.len),i=c*b.groupPadding,j=(c-2*i)/h,k=b.pointWidth,b=s(k)?(j-k)/2:j*b.pointPadding,k=n(k,j-2*b);return a.columnMetrics={width:k,offset:b+(i+((d?h-(a.columnIndex||\n0):a.columnIndex)||0)*j-c/2)*(d?-1:1)}},translate:function(){var a=this.chart,b=this.options,c=b.borderWidth,d=this.yAxis,e=this.translatedThreshold=d.getThreshold(b.threshold),f=n(b.minPointLength,5),b=this.getColumnMetrics(),g=b.width,h=this.barW=ja(u(g,1+2*c)),i=this.pointXOffset=b.offset;Q.prototype.translate.apply(this);o(this.points,function(b){var k=I(u(-999,b.plotY),d.len+999),l=n(b.yBottom,e),m=b.plotX+i,o=ja(I(k,l)),k=ja(u(k,l)-o);P(k)<f&&f&&(k=f,o=t(P(o-e)>f?l-f:e-(d.translate(b.y,0,1,\n0,1)<=e?f:0)));b.barX=m;b.pointWidth=g;b.shapeType=\"rect\";b.shapeArgs=b=a.renderer.Element.prototype.crisp.call(0,c,m,o,h,k);c%2&&(b.y-=1,b.height+=1)})},getSymbol:xa,drawLegendSymbol:L.prototype.drawLegendSymbol,drawGraph:xa,drawPoints:function(){var a=this,b=a.options,c=a.chart.renderer,d;o(a.points,function(e){var f=e.plotY,g=e.graphic;if(f!==v&&!isNaN(f)&&e.y!==null)d=e.shapeArgs,g?(Wa(g),g.animate(w(d))):e.graphic=c[e.shapeType](d).attr(e.pointAttr[e.selected?\"select\":\"\"]).add(a.group).shadow(b.shadow,\nnull,b.stacking&&!b.borderRadius);else if(g)e.graphic=g.destroy()})},drawTracker:function(){var a=this,b=a.chart,c=b.pointer,d=a.options.cursor,e=d&&{cursor:d},f=function(c){var d=c.target,e;if(b.hoverSeries!==a)a.onMouseOver();for(;d&&!e;)e=d.point,d=d.parentNode;if(e!==v&&e!==b.hoverPoint)e.onMouseOver(c)};o(a.points,function(a){if(a.graphic)a.graphic.element.point=a;if(a.dataLabel)a.dataLabel.element.point=a});a._hasTracking?a._hasTracking=!0:o(a.trackerGroups,function(b){if(a[b]&&(a[b].addClass(\"highcharts-tracker\").on(\"mouseover\",\nf).on(\"mouseout\",function(a){c.onTrackerMouseOut(a)}).css(e),hb))a[b].on(\"touchstart\",f)})},alignDataLabel:function(a,b,c,d,e){var f=this.chart,g=f.inverted,h=a.dlBox||a.shapeArgs,i=a.below||a.plotY>n(this.translatedThreshold,f.plotSizeY),j=n(c.inside,!!this.options.stacking);if(h&&(d=w(h),g&&(d={x:f.plotWidth-d.y-d.height,y:f.plotHeight-d.x-d.width,width:d.height,height:d.width}),!j))g?(d.x+=i?0:d.width,d.width=0):(d.y+=i?d.height:0,d.height=0);c.align=n(c.align,!g||j?\"center\":i?\"right\":\"left\");\nc.verticalAlign=n(c.verticalAlign,g||j?\"middle\":i?\"top\":\"bottom\");Q.prototype.alignDataLabel.call(this,a,b,c,d,e)},animate:function(a){var b=this.yAxis,c=this.options,d=this.chart.inverted,e={};if(Y)a?(e.scaleY=0.001,a=I(b.pos+b.len,u(b.pos,b.toPixels(c.threshold))),d?e.translateX=a-b.len:e.translateY=a,this.group.attr(e)):(e.scaleY=1,e[d?\"translateX\":\"translateY\"]=b.pos,this.group.animate(e,this.options.animation),this.animate=null)},remove:function(){var a=this,b=a.chart;b.hasRendered&&o(b.series,\nfunction(b){if(b.type===a.type)b.isDirty=!0});Q.prototype.remove.apply(a,arguments)}});$.column=K;X.bar=w(X.column);la=ga(K,{type:\"bar\",inverted:!0});$.bar=la;X.scatter=w(W,{lineWidth:0,tooltip:{headerFormat:'<span style=\"font-size: 10px; color:{series.color}\">{series.name}</span><br/>',pointFormat:\"x: <b>{point.x}</b><br/>y: <b>{point.y}</b><br/>\",followPointer:!0},stickyTracking:!1});la=ga(Q,{type:\"scatter\",sorted:!1,requireSorting:!1,noSharedTooltip:!0,trackerGroups:[\"markerGroup\"],drawTracker:K.prototype.drawTracker,\nsetTooltipPoints:xa});$.scatter=la;X.pie=w(W,{borderColor:\"#FFFFFF\",borderWidth:1,center:[null,null],clip:!1,colorByPoint:!0,dataLabels:{distance:30,enabled:!0,formatter:function(){return this.point.name}},ignoreHiddenPoint:!0,legendType:\"point\",marker:null,size:null,showInLegend:!1,slicedOffset:10,states:{hover:{brightness:0.1,shadow:!1}},stickyTracking:!1,tooltip:{followPointer:!0}});W={type:\"pie\",isCartesian:!1,pointClass:ga(Pa,{init:function(){Pa.prototype.init.apply(this,arguments);var a=this,\nb;if(a.y<0)a.y=null;r(a,{visible:a.visible!==!1,name:n(a.name,\"Slice\")});b=function(b){a.slice(b.type===\"select\")};J(a,\"select\",b);J(a,\"unselect\",b);return a},setVisible:function(a){var b=this,c=b.series,d=c.chart,e;b.visible=b.options.visible=a=a===v?!b.visible:a;c.options.data[na(b,c.data)]=b.options;e=a?\"show\":\"hide\";o([\"graphic\",\"dataLabel\",\"connector\",\"shadowGroup\"],function(a){if(b[a])b[a][e]()});b.legendItem&&d.legend.colorizeItem(b,a);if(!c.isDirty&&c.options.ignoreHiddenPoint)c.isDirty=!0,\nd.redraw()},slice:function(a,b,c){var d=this.series;Ka(c,d.chart);n(b,!0);this.sliced=this.options.sliced=a=s(a)?a:!this.sliced;d.options.data[na(this,d.data)]=this.options;a=a?this.slicedTranslation:{translateX:0,translateY:0};this.graphic.animate(a);this.shadowGroup&&this.shadowGroup.animate(a)}}),requireSorting:!1,noSharedTooltip:!0,trackerGroups:[\"group\",\"dataLabelsGroup\"],pointAttrToOptions:{stroke:\"borderColor\",\"stroke-width\":\"borderWidth\",fill:\"color\"},getColor:xa,animate:function(a){var b=\nthis,c=b.points,d=b.startAngleRad;if(!a)o(c,function(a){var c=a.graphic,a=a.shapeArgs;c&&(c.attr({r:b.center[3]/2,start:d,end:d}),c.animate({r:a.r,start:a.start,end:a.end},b.options.animation))}),b.animate=null},setData:function(a,b){Q.prototype.setData.call(this,a,!1);this.processData();this.generatePoints();n(b,!0)&&this.chart.redraw()},generatePoints:function(){var a,b=0,c,d,e,f=this.options.ignoreHiddenPoint;Q.prototype.generatePoints.call(this);c=this.points;d=c.length;for(a=0;a<d;a++)e=c[a],\nb+=f&&!e.visible?0:e.y;this.total=b;for(a=0;a<d;a++)e=c[a],e.percentage=e.y/b*100,e.total=b},getCenter:function(){var a=this.options,b=this.chart,c=2*(a.slicedOffset||0),d,e=b.plotWidth-2*c,f=b.plotHeight-2*c,b=a.center,a=[n(b[0],\"50%\"),n(b[1],\"50%\"),a.size||\"100%\",a.innerSize||0],g=I(e,f),h;return Na(a,function(a,b){h=/%$/.test(a);d=b<2||b===2&&h;return(h?[e,f,g,g][b]*A(a)/100:a)+(d?c:0)})},translate:function(a){this.generatePoints();var b=0,c=this.options,d=c.slicedOffset,e=d+c.borderWidth,f,g,\nh,i=this.startAngleRad=Ma/180*((c.startAngle||0)%360-90),j=this.points,k=2*Ma,l=c.dataLabels.distance,c=c.ignoreHiddenPoint,m,o=j.length,n;if(!a)this.center=a=this.getCenter();this.getX=function(b,c){h=N.asin((b-a[1])/(a[2]/2+l));return a[0]+(c?-1:1)*V(h)*(a[2]/2+l)};for(m=0;m<o;m++){n=j[m];f=t((i+b*k)*1E3)/1E3;if(!c||n.visible)b+=n.percentage/100;g=t((i+b*k)*1E3)/1E3;n.shapeType=\"arc\";n.shapeArgs={x:a[0],y:a[1],r:a[2]/2,innerR:a[3]/2,start:f,end:g};h=(g+f)/2;h>0.75*k&&(h-=2*Ma);n.slicedTranslation=\n{translateX:t(V(h)*d),translateY:t(ba(h)*d)};f=V(h)*a[2]/2;g=ba(h)*a[2]/2;n.tooltipPos=[a[0]+f*0.7,a[1]+g*0.7];n.half=h<k/4?0:1;n.angle=h;e=I(e,l/2);n.labelPos=[a[0]+f+V(h)*l,a[1]+g+ba(h)*l,a[0]+f+V(h)*e,a[1]+g+ba(h)*e,a[0]+f,a[1]+g,l<0?\"center\":n.half?\"right\":\"left\",h]}this.setTooltipPoints()},drawGraph:null,drawPoints:function(){var a=this,b=a.chart.renderer,c,d,e=a.options.shadow,f,g;if(e&&!a.shadowGroup)a.shadowGroup=b.g(\"shadow\").add(a.group);o(a.points,function(h){d=h.graphic;g=h.shapeArgs;\nf=h.shadowGroup;if(e&&!f)f=h.shadowGroup=b.g(\"shadow\").add(a.shadowGroup);c=h.sliced?h.slicedTranslation:{translateX:0,translateY:0};f&&f.attr(c);d?d.animate(r(g,c)):h.graphic=d=b.arc(g).setRadialReference(a.center).attr(h.pointAttr[h.selected?\"select\":\"\"]).attr({\"stroke-linejoin\":\"round\"}).attr(c).add(a.group).shadow(e,f);h.visible===!1&&h.setVisible(!1)})},drawDataLabels:function(){var a=this,b=a.data,c,d=a.chart,e=a.options.dataLabels,f=n(e.connectorPadding,10),g=n(e.connectorWidth,1),h=d.plotWidth,\nd=d.plotHeight,i,j,k=n(e.softConnector,!0),l=e.distance,m=a.center,p=m[2]/2,q=m[1],s=l>0,r,w,v,x,A=[[],[]],y,D,H,z,G,B=[0,0,0,0],I=function(a,b){return b.y-a.y},M=function(a,b){a.sort(function(a,c){return a.angle!==void 0&&(c.angle-a.angle)*b})};if(a.visible&&(e.enabled||a._hasPointLabels)){Q.prototype.drawDataLabels.apply(a);o(b,function(a){a.dataLabel&&A[a.half].push(a)});for(z=0;!x&&b[z];)x=b[z]&&b[z].dataLabel&&(b[z].dataLabel.getBBox().height||21),z++;for(z=2;z--;){var b=[],L=[],J=A[z],K=J.length,\nE;M(J,z-0.5);if(l>0){for(G=q-p-l;G<=q+p+l;G+=x)b.push(G);w=b.length;if(K>w){c=[].concat(J);c.sort(I);for(G=K;G--;)c[G].rank=G;for(G=K;G--;)J[G].rank>=w&&J.splice(G,1);K=J.length}for(G=0;G<K;G++){c=J[G];v=c.labelPos;c=9999;var O,N;for(N=0;N<w;N++)O=P(b[N]-v[1]),O<c&&(c=O,E=N);if(E<G&&b[G]!==null)E=G;else for(w<K-G+E&&b[G]!==null&&(E=w-K+G);b[E]===null;)E++;L.push({i:E,y:b[E]});b[E]=null}L.sort(I)}for(G=0;G<K;G++){c=J[G];v=c.labelPos;r=c.dataLabel;H=c.visible===!1?\"hidden\":\"visible\";c=v[1];if(l>0){if(w=\nL.pop(),E=w.i,D=w.y,c>D&&b[E+1]!==null||c<D&&b[E-1]!==null)D=c}else D=c;y=e.justify?m[0]+(z?-1:1)*(p+l):a.getX(E===0||E===b.length-1?c:D,z);r._attr={visibility:H,align:v[6]};r._pos={x:y+e.x+({left:f,right:-f}[v[6]]||0),y:D+e.y-10};r.connX=y;r.connY=D;if(this.options.size===null)w=r.width,y-w<f?B[3]=u(t(w-y+f),B[3]):y+w>h-f&&(B[1]=u(t(y+w-h+f),B[1])),D-x/2<0?B[0]=u(t(-D+x/2),B[0]):D+x/2>d&&(B[2]=u(t(D+x/2-d),B[2]))}}if(ta(B)===0||this.verifyDataLabelOverflow(B))this.placeDataLabels(),s&&g&&o(this.points,\nfunction(b){i=b.connector;v=b.labelPos;if((r=b.dataLabel)&&r._pos)H=r._attr.visibility,y=r.connX,D=r.connY,j=k?[\"M\",y+(v[6]===\"left\"?5:-5),D,\"C\",y,D,2*v[2]-v[4],2*v[3]-v[5],v[2],v[3],\"L\",v[4],v[5]]:[\"M\",y+(v[6]===\"left\"?5:-5),D,\"L\",v[2],v[3],\"L\",v[4],v[5]],i?(i.animate({d:j}),i.attr(\"visibility\",H)):b.connector=i=a.chart.renderer.path(j).attr({\"stroke-width\":g,stroke:e.connectorColor||b.color||\"#606060\",visibility:H}).add(a.group);else if(i)b.connector=i.destroy()})}},verifyDataLabelOverflow:function(a){var b=\nthis.center,c=this.options,d=c.center,e=c=c.minSize||80,f;d[0]!==null?e=u(b[2]-u(a[1],a[3]),c):(e=u(b[2]-a[1]-a[3],c),b[0]+=(a[3]-a[1])/2);d[1]!==null?e=u(I(e,b[2]-u(a[0],a[2])),c):(e=u(I(e,b[2]-a[0]-a[2]),c),b[1]+=(a[0]-a[2])/2);e<b[2]?(b[2]=e,this.translate(b),o(this.points,function(a){if(a.dataLabel)a.dataLabel._pos=null}),this.drawDataLabels()):f=!0;return f},placeDataLabels:function(){o(this.points,function(a){var a=a.dataLabel,b;if(a)(b=a._pos)?(a.attr(a._attr),a[a.moved?\"animate\":\"attr\"](b),\na.moved=!0):a&&a.attr({y:-999})})},alignDataLabel:xa,drawTracker:K.prototype.drawTracker,drawLegendSymbol:L.prototype.drawLegendSymbol,getSymbol:xa};W=ga(Q,W);$.pie=W;r(Highcharts,{Axis:db,Chart:wb,Color:oa,Legend:vb,Pointer:ub,Point:Pa,Tick:La,Tooltip:tb,Renderer:Va,Series:Q,SVGElement:va,SVGRenderer:Ga,arrayMin:Ia,arrayMax:ta,charts:Fa,dateFormat:Xa,format:Ba,pathAnim:yb,getOptions:function(){return O},hasBidiBug:Ub,isTouchDevice:Nb,numberFormat:za,seriesTypes:$,setOptions:function(a){O=w(O,a);\nKb();return O},addEvent:J,removeEvent:aa,createElement:T,discardElement:Ta,css:M,each:o,extend:r,map:Na,merge:w,pick:n,splat:ha,extendClass:ga,pInt:A,wrap:Ab,svg:Y,canvas:Z,vml:!Y&&!Z,product:\"Highcharts\",version:\"3.0.3\"})})();\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/highchart3/js/highcharts.src.js",
    "content": "// ==ClosureCompiler==\n// @compilation_level SIMPLE_OPTIMIZATIONS\n\n/**\n * @license Highcharts JS v3.0.3 (2013-07-31)\n *\n * (c) 2009-2013 Torstein Hønsi\n *\n * License: www.highcharts.com/license\n */\n\n// JSLint options:\n/*global Highcharts, document, window, navigator, setInterval, clearInterval, clearTimeout, setTimeout, location, jQuery, $, console, each, grep */\n\n(function () {\n// encapsulated variables\nvar UNDEFINED,\n\tdoc = document,\n\twin = window,\n\tmath = Math,\n\tmathRound = math.round,\n\tmathFloor = math.floor,\n\tmathCeil = math.ceil,\n\tmathMax = math.max,\n\tmathMin = math.min,\n\tmathAbs = math.abs,\n\tmathCos = math.cos,\n\tmathSin = math.sin,\n\tmathPI = math.PI,\n\tdeg2rad = mathPI * 2 / 360,\n\n\n\t// some variables\n\tuserAgent = navigator.userAgent,\n\tisOpera = win.opera,\n\tisIE = /msie/i.test(userAgent) && !isOpera,\n\tdocMode8 = doc.documentMode === 8,\n\tisWebKit = /AppleWebKit/.test(userAgent),\n\tisFirefox = /Firefox/.test(userAgent),\n\tisTouchDevice = /(Mobile|Android|Windows Phone)/.test(userAgent),\n\tSVG_NS = 'http://www.w3.org/2000/svg',\n\thasSVG = !!doc.createElementNS && !!doc.createElementNS(SVG_NS, 'svg').createSVGRect,\n\thasBidiBug = isFirefox && parseInt(userAgent.split('Firefox/')[1], 10) < 4, // issue #38\n\tuseCanVG = !hasSVG && !isIE && !!doc.createElement('canvas').getContext,\n\tRenderer,\n\thasTouch = doc.documentElement.ontouchstart !== UNDEFINED,\n\tsymbolSizes = {},\n\tidCounter = 0,\n\tgarbageBin,\n\tdefaultOptions,\n\tdateFormat, // function\n\tglobalAnimation,\n\tpathAnim,\n\ttimeUnits,\n\tnoop = function () {},\n\tcharts = [],\n\tPRODUCT = 'Highcharts',\n\tVERSION = '3.0.3',\n\n\t// some constants for frequently used strings\n\tDIV = 'div',\n\tABSOLUTE = 'absolute',\n\tRELATIVE = 'relative',\n\tHIDDEN = 'hidden',\n\tPREFIX = 'highcharts-',\n\tVISIBLE = 'visible',\n\tPX = 'px',\n\tNONE = 'none',\n\tM = 'M',\n\tL = 'L',\n\t/*\n\t * Empirical lowest possible opacities for TRACKER_FILL\n\t * IE6: 0.002\n\t * IE7: 0.002\n\t * IE8: 0.002\n\t * IE9: 0.00000000001 (unlimited)\n\t * IE10: 0.0001 (exporting only)\n\t * FF: 0.00000000001 (unlimited)\n\t * Chrome: 0.000001\n\t * Safari: 0.000001\n\t * Opera: 0.00000000001 (unlimited)\n\t */\n\tTRACKER_FILL = 'rgba(192,192,192,' + (hasSVG ? 0.0001 : 0.002) + ')', // invisible but clickable\n\t//TRACKER_FILL = 'rgba(192,192,192,0.5)',\n\tNORMAL_STATE = '',\n\tHOVER_STATE = 'hover',\n\tSELECT_STATE = 'select',\n\tMILLISECOND = 'millisecond',\n\tSECOND = 'second',\n\tMINUTE = 'minute',\n\tHOUR = 'hour',\n\tDAY = 'day',\n\tWEEK = 'week',\n\tMONTH = 'month',\n\tYEAR = 'year',\n\n\t// constants for attributes\n\tLINEAR_GRADIENT = 'linearGradient',\n\tSTOPS = 'stops',\n\tSTROKE_WIDTH = 'stroke-width',\n\n\t// time methods, changed based on whether or not UTC is used\n\tmakeTime,\n\tgetMinutes,\n\tgetHours,\n\tgetDay,\n\tgetDate,\n\tgetMonth,\n\tgetFullYear,\n\tsetMinutes,\n\tsetHours,\n\tsetDate,\n\tsetMonth,\n\tsetFullYear,\n\n\n\t// lookup over the types and the associated classes\n\tseriesTypes = {};\n\n// The Highcharts namespace\nwin.Highcharts = win.Highcharts ? error(16, true) : {};\n\n/**\n * Extend an object with the members of another\n * @param {Object} a The object to be extended\n * @param {Object} b The object to add to the first one\n */\nfunction extend(a, b) {\n\tvar n;\n\tif (!a) {\n\t\ta = {};\n\t}\n\tfor (n in b) {\n\t\ta[n] = b[n];\n\t}\n\treturn a;\n}\n\t\n/**\n * Deep merge two or more objects and return a third object.\n * Previously this function redirected to jQuery.extend(true), but this had two limitations.\n * First, it deep merged arrays, which lead to workarounds in Highcharts. Second,\n * it copied properties from extended prototypes. \n */\nfunction merge() {\n\tvar i,\n\t\tlen = arguments.length,\n\t\tret = {},\n\t\tdoCopy = function (copy, original) {\n\t\t\tvar value, key;\n\n\t\t\t// An object is replacing a primitive\n\t\t\tif (typeof copy !== 'object') {\n\t\t\t\tcopy = {};\n\t\t\t}\n\n\t\t\tfor (key in original) {\n\t\t\t\tif (original.hasOwnProperty(key)) {\n\t\t\t\t\tvalue = original[key];\n\n\t\t\t\t\t// Copy the contents of objects, but not arrays or DOM nodes\n\t\t\t\t\tif (value && typeof value === 'object' && Object.prototype.toString.call(value) !== '[object Array]'\n\t\t\t\t\t\t\t&& typeof value.nodeType !== 'number') {\n\t\t\t\t\t\tcopy[key] = doCopy(copy[key] || {}, value);\n\t\t\t\t\n\t\t\t\t\t// Primitives and arrays are copied over directly\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcopy[key] = original[key];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn copy;\n\t\t};\n\n\t// For each argument, extend the return\n\tfor (i = 0; i < len; i++) {\n\t\tret = doCopy(ret, arguments[i]);\n\t}\n\n\treturn ret;\n}\n\n/**\n * Take an array and turn into a hash with even number arguments as keys and odd numbers as\n * values. Allows creating constants for commonly used style properties, attributes etc.\n * Avoid it in performance critical situations like looping\n */\nfunction hash() {\n\tvar i = 0,\n\t\targs = arguments,\n\t\tlength = args.length,\n\t\tobj = {};\n\tfor (; i < length; i++) {\n\t\tobj[args[i++]] = args[i];\n\t}\n\treturn obj;\n}\n\n/**\n * Shortcut for parseInt\n * @param {Object} s\n * @param {Number} mag Magnitude\n */\nfunction pInt(s, mag) {\n\treturn parseInt(s, mag || 10);\n}\n\n/**\n * Check for string\n * @param {Object} s\n */\nfunction isString(s) {\n\treturn typeof s === 'string';\n}\n\n/**\n * Check for object\n * @param {Object} obj\n */\nfunction isObject(obj) {\n\treturn typeof obj === 'object';\n}\n\n/**\n * Check for array\n * @param {Object} obj\n */\nfunction isArray(obj) {\n\treturn Object.prototype.toString.call(obj) === '[object Array]';\n}\n\n/**\n * Check for number\n * @param {Object} n\n */\nfunction isNumber(n) {\n\treturn typeof n === 'number';\n}\n\nfunction log2lin(num) {\n\treturn math.log(num) / math.LN10;\n}\nfunction lin2log(num) {\n\treturn math.pow(10, num);\n}\n\n/**\n * Remove last occurence of an item from an array\n * @param {Array} arr\n * @param {Mixed} item\n */\nfunction erase(arr, item) {\n\tvar i = arr.length;\n\twhile (i--) {\n\t\tif (arr[i] === item) {\n\t\t\tarr.splice(i, 1);\n\t\t\tbreak;\n\t\t}\n\t}\n\t//return arr;\n}\n\n/**\n * Returns true if the object is not null or undefined. Like MooTools' $.defined.\n * @param {Object} obj\n */\nfunction defined(obj) {\n\treturn obj !== UNDEFINED && obj !== null;\n}\n\n/**\n * Set or get an attribute or an object of attributes. Can't use jQuery attr because\n * it attempts to set expando properties on the SVG element, which is not allowed.\n *\n * @param {Object} elem The DOM element to receive the attribute(s)\n * @param {String|Object} prop The property or an abject of key-value pairs\n * @param {String} value The value if a single property is set\n */\nfunction attr(elem, prop, value) {\n\tvar key,\n\t\tsetAttribute = 'setAttribute',\n\t\tret;\n\n\t// if the prop is a string\n\tif (isString(prop)) {\n\t\t// set the value\n\t\tif (defined(value)) {\n\n\t\t\telem[setAttribute](prop, value);\n\n\t\t// get the value\n\t\t} else if (elem && elem.getAttribute) { // elem not defined when printing pie demo...\n\t\t\tret = elem.getAttribute(prop);\n\t\t}\n\n\t// else if prop is defined, it is a hash of key/value pairs\n\t} else if (defined(prop) && isObject(prop)) {\n\t\tfor (key in prop) {\n\t\t\telem[setAttribute](key, prop[key]);\n\t\t}\n\t}\n\treturn ret;\n}\n/**\n * Check if an element is an array, and if not, make it into an array. Like\n * MooTools' $.splat.\n */\nfunction splat(obj) {\n\treturn isArray(obj) ? obj : [obj];\n}\n\n\n/**\n * Return the first value that is defined. Like MooTools' $.pick.\n */\nfunction pick() {\n\tvar args = arguments,\n\t\ti,\n\t\targ,\n\t\tlength = args.length;\n\tfor (i = 0; i < length; i++) {\n\t\targ = args[i];\n\t\tif (typeof arg !== 'undefined' && arg !== null) {\n\t\t\treturn arg;\n\t\t}\n\t}\n}\n\n/**\n * Set CSS on a given element\n * @param {Object} el\n * @param {Object} styles Style object with camel case property names\n */\nfunction css(el, styles) {\n\tif (isIE) {\n\t\tif (styles && styles.opacity !== UNDEFINED) {\n\t\t\tstyles.filter = 'alpha(opacity=' + (styles.opacity * 100) + ')';\n\t\t}\n\t}\n\textend(el.style, styles);\n}\n\n/**\n * Utility function to create element with attributes and styles\n * @param {Object} tag\n * @param {Object} attribs\n * @param {Object} styles\n * @param {Object} parent\n * @param {Object} nopad\n */\nfunction createElement(tag, attribs, styles, parent, nopad) {\n\tvar el = doc.createElement(tag);\n\tif (attribs) {\n\t\textend(el, attribs);\n\t}\n\tif (nopad) {\n\t\tcss(el, {padding: 0, border: NONE, margin: 0});\n\t}\n\tif (styles) {\n\t\tcss(el, styles);\n\t}\n\tif (parent) {\n\t\tparent.appendChild(el);\n\t}\n\treturn el;\n}\n\n/**\n * Extend a prototyped class by new members\n * @param {Object} parent\n * @param {Object} members\n */\nfunction extendClass(parent, members) {\n\tvar object = function () {};\n\tobject.prototype = new parent();\n\textend(object.prototype, members);\n\treturn object;\n}\n\n/**\n * Format a number and return a string based on input settings\n * @param {Number} number The input number to format\n * @param {Number} decimals The amount of decimals\n * @param {String} decPoint The decimal point, defaults to the one given in the lang options\n * @param {String} thousandsSep The thousands separator, defaults to the one given in the lang options\n */\nfunction numberFormat(number, decimals, decPoint, thousandsSep) {\n\tvar lang = defaultOptions.lang,\n\t\t// http://kevin.vanzonneveld.net/techblog/article/javascript_equivalent_for_phps_number_format/\n\t\tn = +number || 0,\n\t\tc = decimals === -1 ?\n\t\t\t(n.toString().split('.')[1] || '').length : // preserve decimals\n\t\t\t(isNaN(decimals = mathAbs(decimals)) ? 2 : decimals),\n\t\td = decPoint === undefined ? lang.decimalPoint : decPoint,\n\t\tt = thousandsSep === undefined ? lang.thousandsSep : thousandsSep,\n\t\ts = n < 0 ? \"-\" : \"\",\n\t\ti = String(pInt(n = mathAbs(n).toFixed(c))),\n\t\tj = i.length > 3 ? i.length % 3 : 0;\n\n\treturn s + (j ? i.substr(0, j) + t : \"\") + i.substr(j).replace(/(\\d{3})(?=\\d)/g, \"$1\" + t) +\n\t\t(c ? d + mathAbs(n - i).toFixed(c).slice(2) : \"\");\n}\n\n/**\n * Pad a string to a given length by adding 0 to the beginning\n * @param {Number} number\n * @param {Number} length\n */\nfunction pad(number, length) {\n\t// Create an array of the remaining length +1 and join it with 0's\n\treturn new Array((length || 2) + 1 - String(number).length).join(0) + number;\n}\n\n/**\n * Wrap a method with extended functionality, preserving the original function\n * @param {Object} obj The context object that the method belongs to \n * @param {String} method The name of the method to extend\n * @param {Function} func A wrapper function callback. This function is called with the same arguments\n * as the original function, except that the original function is unshifted and passed as the first \n * argument. \n */\nfunction wrap(obj, method, func) {\n\tvar proceed = obj[method];\n\tobj[method] = function () {\n\t\tvar args = Array.prototype.slice.call(arguments);\n\t\targs.unshift(proceed);\n\t\treturn func.apply(this, args);\n\t};\n}\n\n/**\n * Based on http://www.php.net/manual/en/function.strftime.php\n * @param {String} format\n * @param {Number} timestamp\n * @param {Boolean} capitalize\n */\ndateFormat = function (format, timestamp, capitalize) {\n\tif (!defined(timestamp) || isNaN(timestamp)) {\n\t\treturn 'Invalid date';\n\t}\n\tformat = pick(format, '%Y-%m-%d %H:%M:%S');\n\n\tvar date = new Date(timestamp),\n\t\tkey, // used in for constuct below\n\t\t// get the basic time values\n\t\thours = date[getHours](),\n\t\tday = date[getDay](),\n\t\tdayOfMonth = date[getDate](),\n\t\tmonth = date[getMonth](),\n\t\tfullYear = date[getFullYear](),\n\t\tlang = defaultOptions.lang,\n\t\tlangWeekdays = lang.weekdays,\n\n\t\t// List all format keys. Custom formats can be added from the outside. \n\t\treplacements = extend({\n\n\t\t\t// Day\n\t\t\t'a': langWeekdays[day].substr(0, 3), // Short weekday, like 'Mon'\n\t\t\t'A': langWeekdays[day], // Long weekday, like 'Monday'\n\t\t\t'd': pad(dayOfMonth), // Two digit day of the month, 01 to 31\n\t\t\t'e': dayOfMonth, // Day of the month, 1 through 31\n\n\t\t\t// Week (none implemented)\n\t\t\t//'W': weekNumber(),\n\n\t\t\t// Month\n\t\t\t'b': lang.shortMonths[month], // Short month, like 'Jan'\n\t\t\t'B': lang.months[month], // Long month, like 'January'\n\t\t\t'm': pad(month + 1), // Two digit month number, 01 through 12\n\n\t\t\t// Year\n\t\t\t'y': fullYear.toString().substr(2, 2), // Two digits year, like 09 for 2009\n\t\t\t'Y': fullYear, // Four digits year, like 2009\n\n\t\t\t// Time\n\t\t\t'H': pad(hours), // Two digits hours in 24h format, 00 through 23\n\t\t\t'I': pad((hours % 12) || 12), // Two digits hours in 12h format, 00 through 11\n\t\t\t'l': (hours % 12) || 12, // Hours in 12h format, 1 through 12\n\t\t\t'M': pad(date[getMinutes]()), // Two digits minutes, 00 through 59\n\t\t\t'p': hours < 12 ? 'AM' : 'PM', // Upper case AM or PM\n\t\t\t'P': hours < 12 ? 'am' : 'pm', // Lower case AM or PM\n\t\t\t'S': pad(date.getSeconds()), // Two digits seconds, 00 through  59\n\t\t\t'L': pad(mathRound(timestamp % 1000), 3) // Milliseconds (naming from Ruby)\n\t\t}, Highcharts.dateFormats);\n\n\n\t// do the replaces\n\tfor (key in replacements) {\n\t\twhile (format.indexOf('%' + key) !== -1) { // regex would do it in one line, but this is faster\n\t\t\tformat = format.replace('%' + key, typeof replacements[key] === 'function' ? replacements[key](timestamp) : replacements[key]);\n\t\t}\n\t}\n\n\t// Optionally capitalize the string and return\n\treturn capitalize ? format.substr(0, 1).toUpperCase() + format.substr(1) : format;\n};\n\n/** \n * Format a single variable. Similar to sprintf, without the % prefix.\n */\nfunction formatSingle(format, val) {\n\tvar floatRegex = /f$/,\n\t\tdecRegex = /\\.([0-9])/,\n\t\tlang = defaultOptions.lang,\n\t\tdecimals;\n\n\tif (floatRegex.test(format)) { // float\n\t\tdecimals = format.match(decRegex);\n\t\tdecimals = decimals ? decimals[1] : -1;\n\t\tval = numberFormat(\n\t\t\tval,\n\t\t\tdecimals,\n\t\t\tlang.decimalPoint,\n\t\t\tformat.indexOf(',') > -1 ? lang.thousandsSep : ''\n\t\t);\n\t} else {\n\t\tval = dateFormat(format, val);\n\t}\n\treturn val;\n}\n\n/**\n * Format a string according to a subset of the rules of Python's String.format method.\n */\nfunction format(str, ctx) {\n\tvar splitter = '{',\n\t\tisInside = false,\n\t\tsegment,\n\t\tvalueAndFormat,\n\t\tpath,\n\t\ti,\n\t\tlen,\n\t\tret = [],\n\t\tval,\n\t\tindex;\n\t\n\twhile ((index = str.indexOf(splitter)) !== -1) {\n\t\t\n\t\tsegment = str.slice(0, index);\n\t\tif (isInside) { // we're on the closing bracket looking back\n\t\t\t\n\t\t\tvalueAndFormat = segment.split(':');\n\t\t\tpath = valueAndFormat.shift().split('.'); // get first and leave format\n\t\t\tlen = path.length;\n\t\t\tval = ctx;\n\n\t\t\t// Assign deeper paths\n\t\t\tfor (i = 0; i < len; i++) {\n\t\t\t\tval = val[path[i]];\n\t\t\t}\n\n\t\t\t// Format the replacement\n\t\t\tif (valueAndFormat.length) {\n\t\t\t\tval = formatSingle(valueAndFormat.join(':'), val);\n\t\t\t}\n\n\t\t\t// Push the result and advance the cursor\n\t\t\tret.push(val);\n\t\t\t\n\t\t} else {\n\t\t\tret.push(segment);\n\t\t\t\n\t\t}\n\t\tstr = str.slice(index + 1); // the rest\n\t\tisInside = !isInside; // toggle\n\t\tsplitter = isInside ? '}' : '{'; // now look for next matching bracket\n\t}\n\tret.push(str);\n\treturn ret.join('');\n}\n\n/**\n * Get the magnitude of a number\n */\nfunction getMagnitude(num) {\n\treturn math.pow(10, mathFloor(math.log(num) / math.LN10));\n}\n\n/**\n * Take an interval and normalize it to multiples of 1, 2, 2.5 and 5\n * @param {Number} interval\n * @param {Array} multiples\n * @param {Number} magnitude\n * @param {Object} options\n */\nfunction normalizeTickInterval(interval, multiples, magnitude, options) {\n\tvar normalized, i;\n\n\t// round to a tenfold of 1, 2, 2.5 or 5\n\tmagnitude = pick(magnitude, 1);\n\tnormalized = interval / magnitude;\n\n\t// multiples for a linear scale\n\tif (!multiples) {\n\t\tmultiples = [1, 2, 2.5, 5, 10];\n\n\t\t// the allowDecimals option\n\t\tif (options && options.allowDecimals === false) {\n\t\t\tif (magnitude === 1) {\n\t\t\t\tmultiples = [1, 2, 5, 10];\n\t\t\t} else if (magnitude <= 0.1) {\n\t\t\t\tmultiples = [1 / magnitude];\n\t\t\t}\n\t\t}\n\t}\n\n\t// normalize the interval to the nearest multiple\n\tfor (i = 0; i < multiples.length; i++) {\n\t\tinterval = multiples[i];\n\t\tif (normalized <= (multiples[i] + (multiples[i + 1] || multiples[i])) / 2) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// multiply back to the correct magnitude\n\tinterval *= magnitude;\n\n\treturn interval;\n}\n\n/**\n * Get a normalized tick interval for dates. Returns a configuration object with\n * unit range (interval), count and name. Used to prepare data for getTimeTicks. \n * Previously this logic was part of getTimeTicks, but as getTimeTicks now runs\n * of segments in stock charts, the normalizing logic was extracted in order to \n * prevent it for running over again for each segment having the same interval. \n * #662, #697.\n */\nfunction normalizeTimeTickInterval(tickInterval, unitsOption) {\n\tvar units = unitsOption || [[\n\t\t\t\tMILLISECOND, // unit name\n\t\t\t\t[1, 2, 5, 10, 20, 25, 50, 100, 200, 500] // allowed multiples\n\t\t\t], [\n\t\t\t\tSECOND,\n\t\t\t\t[1, 2, 5, 10, 15, 30]\n\t\t\t], [\n\t\t\t\tMINUTE,\n\t\t\t\t[1, 2, 5, 10, 15, 30]\n\t\t\t], [\n\t\t\t\tHOUR,\n\t\t\t\t[1, 2, 3, 4, 6, 8, 12]\n\t\t\t], [\n\t\t\t\tDAY,\n\t\t\t\t[1, 2]\n\t\t\t], [\n\t\t\t\tWEEK,\n\t\t\t\t[1, 2]\n\t\t\t], [\n\t\t\t\tMONTH,\n\t\t\t\t[1, 2, 3, 4, 6]\n\t\t\t], [\n\t\t\t\tYEAR,\n\t\t\t\tnull\n\t\t\t]],\n\t\tunit = units[units.length - 1], // default unit is years\n\t\tinterval = timeUnits[unit[0]],\n\t\tmultiples = unit[1],\n\t\tcount,\n\t\ti;\n\t\t\n\t// loop through the units to find the one that best fits the tickInterval\n\tfor (i = 0; i < units.length; i++) {\n\t\tunit = units[i];\n\t\tinterval = timeUnits[unit[0]];\n\t\tmultiples = unit[1];\n\n\n\t\tif (units[i + 1]) {\n\t\t\t// lessThan is in the middle between the highest multiple and the next unit.\n\t\t\tvar lessThan = (interval * multiples[multiples.length - 1] +\n\t\t\t\t\t\ttimeUnits[units[i + 1][0]]) / 2;\n\n\t\t\t// break and keep the current unit\n\t\t\tif (tickInterval <= lessThan) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// prevent 2.5 years intervals, though 25, 250 etc. are allowed\n\tif (interval === timeUnits[YEAR] && tickInterval < 5 * interval) {\n\t\tmultiples = [1, 2, 5];\n\t}\n\t\n\t// prevent 2.5 years intervals, though 25, 250 etc. are allowed\n\tif (interval === timeUnits[YEAR] && tickInterval < 5 * interval) {\n\t\tmultiples = [1, 2, 5];\n\t}\n\n\t// get the count\n\tcount = normalizeTickInterval(\n\t\ttickInterval / interval, \n\t\tmultiples,\n\t\tunit[0] === YEAR ? getMagnitude(tickInterval / interval) : 1 // #1913\n\t);\n\t\n\treturn {\n\t\tunitRange: interval,\n\t\tcount: count,\n\t\tunitName: unit[0]\n\t};\n}\n\n/**\n * Set the tick positions to a time unit that makes sense, for example\n * on the first of each month or on every Monday. Return an array\n * with the time positions. Used in datetime axes as well as for grouping\n * data on a datetime axis.\n *\n * @param {Object} normalizedInterval The interval in axis values (ms) and the count\n * @param {Number} min The minimum in axis values\n * @param {Number} max The maximum in axis values\n * @param {Number} startOfWeek\n */\nfunction getTimeTicks(normalizedInterval, min, max, startOfWeek) {\n\tvar tickPositions = [],\n\t\ti,\n\t\thigherRanks = {},\n\t\tuseUTC = defaultOptions.global.useUTC,\n\t\tminYear, // used in months and years as a basis for Date.UTC()\n\t\tminDate = new Date(min),\n\t\tinterval = normalizedInterval.unitRange,\n\t\tcount = normalizedInterval.count;\n\n\tif (defined(min)) { // #1300\n\t\tif (interval >= timeUnits[SECOND]) { // second\n\t\t\tminDate.setMilliseconds(0);\n\t\t\tminDate.setSeconds(interval >= timeUnits[MINUTE] ? 0 :\n\t\t\t\tcount * mathFloor(minDate.getSeconds() / count));\n\t\t}\n\t\n\t\tif (interval >= timeUnits[MINUTE]) { // minute\n\t\t\tminDate[setMinutes](interval >= timeUnits[HOUR] ? 0 :\n\t\t\t\tcount * mathFloor(minDate[getMinutes]() / count));\n\t\t}\n\t\n\t\tif (interval >= timeUnits[HOUR]) { // hour\n\t\t\tminDate[setHours](interval >= timeUnits[DAY] ? 0 :\n\t\t\t\tcount * mathFloor(minDate[getHours]() / count));\n\t\t}\n\t\n\t\tif (interval >= timeUnits[DAY]) { // day\n\t\t\tminDate[setDate](interval >= timeUnits[MONTH] ? 1 :\n\t\t\t\tcount * mathFloor(minDate[getDate]() / count));\n\t\t}\n\t\n\t\tif (interval >= timeUnits[MONTH]) { // month\n\t\t\tminDate[setMonth](interval >= timeUnits[YEAR] ? 0 :\n\t\t\t\tcount * mathFloor(minDate[getMonth]() / count));\n\t\t\tminYear = minDate[getFullYear]();\n\t\t}\n\t\n\t\tif (interval >= timeUnits[YEAR]) { // year\n\t\t\tminYear -= minYear % count;\n\t\t\tminDate[setFullYear](minYear);\n\t\t}\n\t\n\t\t// week is a special case that runs outside the hierarchy\n\t\tif (interval === timeUnits[WEEK]) {\n\t\t\t// get start of current week, independent of count\n\t\t\tminDate[setDate](minDate[getDate]() - minDate[getDay]() +\n\t\t\t\tpick(startOfWeek, 1));\n\t\t}\n\t\n\t\n\t\t// get tick positions\n\t\ti = 1;\n\t\tminYear = minDate[getFullYear]();\n\t\tvar time = minDate.getTime(),\n\t\t\tminMonth = minDate[getMonth](),\n\t\t\tminDateDate = minDate[getDate](),\n\t\t\ttimezoneOffset = useUTC ? \n\t\t\t\t0 : \n\t\t\t\t(24 * 3600 * 1000 + minDate.getTimezoneOffset() * 60 * 1000) % (24 * 3600 * 1000); // #950\n\t\n\t\t// iterate and add tick positions at appropriate values\n\t\twhile (time < max) {\n\t\t\ttickPositions.push(time);\n\t\n\t\t\t// if the interval is years, use Date.UTC to increase years\n\t\t\tif (interval === timeUnits[YEAR]) {\n\t\t\t\ttime = makeTime(minYear + i * count, 0);\n\t\n\t\t\t// if the interval is months, use Date.UTC to increase months\n\t\t\t} else if (interval === timeUnits[MONTH]) {\n\t\t\t\ttime = makeTime(minYear, minMonth + i * count);\n\t\n\t\t\t// if we're using global time, the interval is not fixed as it jumps\n\t\t\t// one hour at the DST crossover\n\t\t\t} else if (!useUTC && (interval === timeUnits[DAY] || interval === timeUnits[WEEK])) {\n\t\t\t\ttime = makeTime(minYear, minMonth, minDateDate +\n\t\t\t\t\ti * count * (interval === timeUnits[DAY] ? 1 : 7));\n\t\n\t\t\t// else, the interval is fixed and we use simple addition\n\t\t\t} else {\n\t\t\t\ttime += interval * count;\n\t\t\t}\n\t\n\t\t\ti++;\n\t\t}\n\t\n\t\t// push the last time\n\t\ttickPositions.push(time);\n\n\n\t\t// mark new days if the time is dividible by day (#1649, #1760)\n\t\teach(grep(tickPositions, function (time) {\n\t\t\treturn interval <= timeUnits[HOUR] && time % timeUnits[DAY] === timezoneOffset;\n\t\t}), function (time) {\n\t\t\thigherRanks[time] = DAY;\n\t\t});\n\t}\n\n\n\t// record information on the chosen unit - for dynamic label formatter\n\ttickPositions.info = extend(normalizedInterval, {\n\t\thigherRanks: higherRanks,\n\t\ttotalRange: interval * count\n\t});\n\n\treturn tickPositions;\n}\n\n/**\n * Helper class that contains variuos counters that are local to the chart.\n */\nfunction ChartCounters() {\n\tthis.color = 0;\n\tthis.symbol = 0;\n}\n\nChartCounters.prototype =  {\n\t/**\n\t * Wraps the color counter if it reaches the specified length.\n\t */\n\twrapColor: function (length) {\n\t\tif (this.color >= length) {\n\t\t\tthis.color = 0;\n\t\t}\n\t},\n\n\t/**\n\t * Wraps the symbol counter if it reaches the specified length.\n\t */\n\twrapSymbol: function (length) {\n\t\tif (this.symbol >= length) {\n\t\t\tthis.symbol = 0;\n\t\t}\n\t}\n};\n\n\n/**\n * Utility method that sorts an object array and keeping the order of equal items.\n * ECMA script standard does not specify the behaviour when items are equal.\n */\nfunction stableSort(arr, sortFunction) {\n\tvar length = arr.length,\n\t\tsortValue,\n\t\ti;\n\n\t// Add index to each item\n\tfor (i = 0; i < length; i++) {\n\t\tarr[i].ss_i = i; // stable sort index\n\t}\n\n\tarr.sort(function (a, b) {\n\t\tsortValue = sortFunction(a, b);\n\t\treturn sortValue === 0 ? a.ss_i - b.ss_i : sortValue;\n\t});\n\n\t// Remove index from items\n\tfor (i = 0; i < length; i++) {\n\t\tdelete arr[i].ss_i; // stable sort index\n\t}\n}\n\n/**\n * Non-recursive method to find the lowest member of an array. Math.min raises a maximum\n * call stack size exceeded error in Chrome when trying to apply more than 150.000 points. This\n * method is slightly slower, but safe.\n */\nfunction arrayMin(data) {\n\tvar i = data.length,\n\t\tmin = data[0];\n\n\twhile (i--) {\n\t\tif (data[i] < min) {\n\t\t\tmin = data[i];\n\t\t}\n\t}\n\treturn min;\n}\n\n/**\n * Non-recursive method to find the lowest member of an array. Math.min raises a maximum\n * call stack size exceeded error in Chrome when trying to apply more than 150.000 points. This\n * method is slightly slower, but safe.\n */\nfunction arrayMax(data) {\n\tvar i = data.length,\n\t\tmax = data[0];\n\n\twhile (i--) {\n\t\tif (data[i] > max) {\n\t\t\tmax = data[i];\n\t\t}\n\t}\n\treturn max;\n}\n\n/**\n * Utility method that destroys any SVGElement or VMLElement that are properties on the given object.\n * It loops all properties and invokes destroy if there is a destroy method. The property is\n * then delete'ed.\n * @param {Object} The object to destroy properties on\n * @param {Object} Exception, do not destroy this property, only delete it.\n */\nfunction destroyObjectProperties(obj, except) {\n\tvar n;\n\tfor (n in obj) {\n\t\t// If the object is non-null and destroy is defined\n\t\tif (obj[n] && obj[n] !== except && obj[n].destroy) {\n\t\t\t// Invoke the destroy\n\t\t\tobj[n].destroy();\n\t\t}\n\n\t\t// Delete the property from the object.\n\t\tdelete obj[n];\n\t}\n}\n\n\n/**\n * Discard an element by moving it to the bin and delete\n * @param {Object} The HTML node to discard\n */\nfunction discardElement(element) {\n\t// create a garbage bin element, not part of the DOM\n\tif (!garbageBin) {\n\t\tgarbageBin = createElement(DIV);\n\t}\n\n\t// move the node and empty bin\n\tif (element) {\n\t\tgarbageBin.appendChild(element);\n\t}\n\tgarbageBin.innerHTML = '';\n}\n\n/**\n * Provide error messages for debugging, with links to online explanation \n */\nfunction error(code, stop) {\n\tvar msg = 'Highcharts error #' + code + ': www.highcharts.com/errors/' + code;\n\tif (stop) {\n\t\tthrow msg;\n\t} else if (win.console) {\n\t\tconsole.log(msg);\n\t}\n}\n\n/**\n * Fix JS round off float errors\n * @param {Number} num\n */\nfunction correctFloat(num) {\n\treturn parseFloat(\n\t\tnum.toPrecision(14)\n\t);\n}\n\n/**\n * Set the global animation to either a given value, or fall back to the\n * given chart's animation option\n * @param {Object} animation\n * @param {Object} chart\n */\nfunction setAnimation(animation, chart) {\n\tglobalAnimation = pick(animation, chart.animation);\n}\n\n/**\n * The time unit lookup\n */\n/*jslint white: true*/\ntimeUnits = hash(\n\tMILLISECOND, 1,\n\tSECOND, 1000,\n\tMINUTE, 60000,\n\tHOUR, 3600000,\n\tDAY, 24 * 3600000,\n\tWEEK, 7 * 24 * 3600000,\n\tMONTH, 31 * 24 * 3600000,\n\tYEAR, 31556952000\n);\n/*jslint white: false*/\n/**\n * Path interpolation algorithm used across adapters\n */\npathAnim = {\n\t/**\n\t * Prepare start and end values so that the path can be animated one to one\n\t */\n\tinit: function (elem, fromD, toD) {\n\t\tfromD = fromD || '';\n\t\tvar shift = elem.shift,\n\t\t\tbezier = fromD.indexOf('C') > -1,\n\t\t\tnumParams = bezier ? 7 : 3,\n\t\t\tendLength,\n\t\t\tslice,\n\t\t\ti,\n\t\t\tstart = fromD.split(' '),\n\t\t\tend = [].concat(toD), // copy\n\t\t\tstartBaseLine,\n\t\t\tendBaseLine,\n\t\t\tsixify = function (arr) { // in splines make move points have six parameters like bezier curves\n\t\t\t\ti = arr.length;\n\t\t\t\twhile (i--) {\n\t\t\t\t\tif (arr[i] === M) {\n\t\t\t\t\t\tarr.splice(i + 1, 0, arr[i + 1], arr[i + 2], arr[i + 1], arr[i + 2]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\n\t\tif (bezier) {\n\t\t\tsixify(start);\n\t\t\tsixify(end);\n\t\t}\n\n\t\t// pull out the base lines before padding\n\t\tif (elem.isArea) {\n\t\t\tstartBaseLine = start.splice(start.length - 6, 6);\n\t\t\tendBaseLine = end.splice(end.length - 6, 6);\n\t\t}\n\n\t\t// if shifting points, prepend a dummy point to the end path\n\t\tif (shift <= end.length / numParams) {\n\t\t\twhile (shift--) {\n\t\t\t\tend = [].concat(end).splice(0, numParams).concat(end);\n\t\t\t}\n\t\t}\n\t\telem.shift = 0; // reset for following animations\n\n\t\t// copy and append last point until the length matches the end length\n\t\tif (start.length) {\n\t\t\tendLength = end.length;\n\t\t\twhile (start.length < endLength) {\n\n\t\t\t\t//bezier && sixify(start);\n\t\t\t\tslice = [].concat(start).splice(start.length - numParams, numParams);\n\t\t\t\tif (bezier) { // disable first control point\n\t\t\t\t\tslice[numParams - 6] = slice[numParams - 2];\n\t\t\t\t\tslice[numParams - 5] = slice[numParams - 1];\n\t\t\t\t}\n\t\t\t\tstart = start.concat(slice);\n\t\t\t}\n\t\t}\n\n\t\tif (startBaseLine) { // append the base lines for areas\n\t\t\tstart = start.concat(startBaseLine);\n\t\t\tend = end.concat(endBaseLine);\n\t\t}\n\t\treturn [start, end];\n\t},\n\n\t/**\n\t * Interpolate each value of the path and return the array\n\t */\n\tstep: function (start, end, pos, complete) {\n\t\tvar ret = [],\n\t\t\ti = start.length,\n\t\t\tstartVal;\n\n\t\tif (pos === 1) { // land on the final path without adjustment points appended in the ends\n\t\t\tret = complete;\n\n\t\t} else if (i === end.length && pos < 1) {\n\t\t\twhile (i--) {\n\t\t\t\tstartVal = parseFloat(start[i]);\n\t\t\t\tret[i] =\n\t\t\t\t\tisNaN(startVal) ? // a letter instruction like M or L\n\t\t\t\t\t\tstart[i] :\n\t\t\t\t\t\tpos * (parseFloat(end[i] - startVal)) + startVal;\n\n\t\t\t}\n\t\t} else { // if animation is finished or length not matching, land on right value\n\t\t\tret = end;\n\t\t}\n\t\treturn ret;\n\t}\n};\n\n(function ($) {\n\t/**\n\t * The default HighchartsAdapter for jQuery\n\t */\n\twin.HighchartsAdapter = win.HighchartsAdapter || ($ && {\n\t\t\n\t\t/**\n\t\t * Initialize the adapter by applying some extensions to jQuery\n\t\t */\n\t\tinit: function (pathAnim) {\n\t\t\t\n\t\t\t// extend the animate function to allow SVG animations\n\t\t\tvar Fx = $.fx,\n\t\t\t\tStep = Fx.step,\n\t\t\t\tdSetter,\n\t\t\t\tTween = $.Tween,\n\t\t\t\tpropHooks = Tween && Tween.propHooks,\n\t\t\t\topacityHook = $.cssHooks.opacity;\n\t\t\t\n\t\t\t/*jslint unparam: true*//* allow unused param x in this function */\n\t\t\t$.extend($.easing, {\n\t\t\t\teaseOutQuad: function (x, t, b, c, d) {\n\t\t\t\t\treturn -c * (t /= d) * (t - 2) + b;\n\t\t\t\t}\n\t\t\t});\n\t\t\t/*jslint unparam: false*/\n\t\t\n\t\t\t// extend some methods to check for elem.attr, which means it is a Highcharts SVG object\n\t\t\t$.each(['cur', '_default', 'width', 'height', 'opacity'], function (i, fn) {\n\t\t\t\tvar obj = Step,\n\t\t\t\t\tbase,\n\t\t\t\t\telem;\n\t\t\t\t\t\n\t\t\t\t// Handle different parent objects\n\t\t\t\tif (fn === 'cur') {\n\t\t\t\t\tobj = Fx.prototype; // 'cur', the getter, relates to Fx.prototype\n\t\t\t\t\n\t\t\t\t} else if (fn === '_default' && Tween) { // jQuery 1.8 model\n\t\t\t\t\tobj = propHooks[fn];\n\t\t\t\t\tfn = 'set';\n\t\t\t\t}\n\t\t\n\t\t\t\t// Overwrite the method\n\t\t\t\tbase = obj[fn];\n\t\t\t\tif (base) { // step.width and step.height don't exist in jQuery < 1.7\n\t\t\n\t\t\t\t\t// create the extended function replacement\n\t\t\t\t\tobj[fn] = function (fx) {\n\t\t\n\t\t\t\t\t\t// Fx.prototype.cur does not use fx argument\n\t\t\t\t\t\tfx = i ? fx : this;\n\t\t\n\t\t\t\t\t\t// shortcut\n\t\t\t\t\t\telem = fx.elem;\n\t\t\n\t\t\t\t\t\t// Fx.prototype.cur returns the current value. The other ones are setters\n\t\t\t\t\t\t// and returning a value has no effect.\n\t\t\t\t\t\treturn elem.attr ? // is SVG element wrapper\n\t\t\t\t\t\t\telem.attr(fx.prop, fn === 'cur' ? UNDEFINED : fx.now) : // apply the SVG wrapper's method\n\t\t\t\t\t\t\tbase.apply(this, arguments); // use jQuery's built-in method\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// Extend the opacity getter, needed for fading opacity with IE9 and jQuery 1.10+\n\t\t\twrap(opacityHook, 'get', function (proceed, elem, computed) {\n\t\t\t\treturn elem.attr ? (elem.opacity || 0) : proceed.call(this, elem, computed);\n\t\t\t});\n\t\t\t\n\t\t\t\n\t\t\t// Define the setter function for d (path definitions)\n\t\t\tdSetter = function (fx) {\n\t\t\t\tvar elem = fx.elem,\n\t\t\t\t\tends;\n\t\t\n\t\t\t\t// Normally start and end should be set in state == 0, but sometimes,\n\t\t\t\t// for reasons unknown, this doesn't happen. Perhaps state == 0 is skipped\n\t\t\t\t// in these cases\n\t\t\t\tif (!fx.started) {\n\t\t\t\t\tends = pathAnim.init(elem, elem.d, elem.toD);\n\t\t\t\t\tfx.start = ends[0];\n\t\t\t\t\tfx.end = ends[1];\n\t\t\t\t\tfx.started = true;\n\t\t\t\t}\n\t\t\n\t\t\n\t\t\t\t// interpolate each value of the path\n\t\t\t\telem.attr('d', pathAnim.step(fx.start, fx.end, fx.pos, elem.toD));\n\t\t\t};\n\t\t\t\n\t\t\t// jQuery 1.8 style\n\t\t\tif (Tween) {\n\t\t\t\tpropHooks.d = {\n\t\t\t\t\tset: dSetter\n\t\t\t\t};\n\t\t\t// pre 1.8\n\t\t\t} else {\n\t\t\t\t// animate paths\n\t\t\t\tStep.d = dSetter;\n\t\t\t}\n\t\t\t\n\t\t\t/**\n\t\t\t * Utility for iterating over an array. Parameters are reversed compared to jQuery.\n\t\t\t * @param {Array} arr\n\t\t\t * @param {Function} fn\n\t\t\t */\n\t\t\tthis.each = Array.prototype.forEach ?\n\t\t\t\tfunction (arr, fn) { // modern browsers\n\t\t\t\t\treturn Array.prototype.forEach.call(arr, fn);\n\t\t\t\t\t\n\t\t\t\t} : \n\t\t\t\tfunction (arr, fn) { // legacy\n\t\t\t\t\tvar i = 0, \n\t\t\t\t\t\tlen = arr.length;\n\t\t\t\t\tfor (; i < len; i++) {\n\t\t\t\t\t\tif (fn.call(arr[i], arr[i], i, arr) === false) {\n\t\t\t\t\t\t\treturn i;\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/**\n\t\t\t * Register Highcharts as a plugin in the respective framework\n\t\t\t */\n\t\t\t$.fn.highcharts = function () {\n\t\t\t\tvar constr = 'Chart', // default constructor\n\t\t\t\t\targs = arguments,\n\t\t\t\t\toptions,\n\t\t\t\t\tret,\n\t\t\t\t\tchart;\n\n\t\t\t\tif (isString(args[0])) {\n\t\t\t\t\tconstr = args[0];\n\t\t\t\t\targs = Array.prototype.slice.call(args, 1); \n\t\t\t\t}\n\t\t\t\toptions = args[0];\n\n\t\t\t\t// Create the chart\n\t\t\t\tif (options !== UNDEFINED) {\n\t\t\t\t\t/*jslint unused:false*/\n\t\t\t\t\toptions.chart = options.chart || {};\n\t\t\t\t\toptions.chart.renderTo = this[0];\n\t\t\t\t\tchart = new Highcharts[constr](options, args[1]);\n\t\t\t\t\tret = this;\n\t\t\t\t\t/*jslint unused:true*/\n\t\t\t\t}\n\n\t\t\t\t// When called without parameters or with the return argument, get a predefined chart\n\t\t\t\tif (options === UNDEFINED) {\n\t\t\t\t\tret = charts[attr(this[0], 'data-highcharts-chart')];\n\t\t\t\t}\t\n\n\t\t\t\treturn ret;\n\t\t\t};\n\n\t\t},\n\n\t\t\n\t\t/**\n\t\t * Downloads a script and executes a callback when done.\n\t\t * @param {String} scriptLocation\n\t\t * @param {Function} callback\n\t\t */\n\t\tgetScript: $.getScript,\n\t\t\n\t\t/**\n\t\t * Return the index of an item in an array, or -1 if not found\n\t\t */\n\t\tinArray: $.inArray,\n\t\t\n\t\t/**\n\t\t * A direct link to jQuery methods. MooTools and Prototype adapters must be implemented for each case of method.\n\t\t * @param {Object} elem The HTML element\n\t\t * @param {String} method Which method to run on the wrapped element\n\t\t */\n\t\tadapterRun: function (elem, method) {\n\t\t\treturn $(elem)[method]();\n\t\t},\n\t\n\t\t/**\n\t\t * Filter an array\n\t\t */\n\t\tgrep: $.grep,\n\t\n\t\t/**\n\t\t * Map an array\n\t\t * @param {Array} arr\n\t\t * @param {Function} fn\n\t\t */\n\t\tmap: function (arr, fn) {\n\t\t\t//return jQuery.map(arr, fn);\n\t\t\tvar results = [],\n\t\t\t\ti = 0,\n\t\t\t\tlen = arr.length;\n\t\t\tfor (; i < len; i++) {\n\t\t\t\tresults[i] = fn.call(arr[i], arr[i], i, arr);\n\t\t\t}\n\t\t\treturn results;\n\t\n\t\t},\n\t\n\t\t/**\n\t\t * Get the position of an element relative to the top left of the page\n\t\t */\n\t\toffset: function (el) {\n\t\t\treturn $(el).offset();\n\t\t},\n\t\n\t\t/**\n\t\t * Add an event listener\n\t\t * @param {Object} el A HTML element or custom object\n\t\t * @param {String} event The event type\n\t\t * @param {Function} fn The event handler\n\t\t */\n\t\taddEvent: function (el, event, fn) {\n\t\t\t$(el).bind(event, fn);\n\t\t},\n\t\n\t\t/**\n\t\t * Remove event added with addEvent\n\t\t * @param {Object} el The object\n\t\t * @param {String} eventType The event type. Leave blank to remove all events.\n\t\t * @param {Function} handler The function to remove\n\t\t */\n\t\tremoveEvent: function (el, eventType, handler) {\n\t\t\t// workaround for jQuery issue with unbinding custom events:\n\t\t\t// http://forum.jQuery.com/topic/javascript-error-when-unbinding-a-custom-event-using-jQuery-1-4-2\n\t\t\tvar func = doc.removeEventListener ? 'removeEventListener' : 'detachEvent';\n\t\t\tif (doc[func] && el && !el[func]) {\n\t\t\t\tel[func] = function () {};\n\t\t\t}\n\t\n\t\t\t$(el).unbind(eventType, handler);\n\t\t},\n\t\n\t\t/**\n\t\t * Fire an event on a custom object\n\t\t * @param {Object} el\n\t\t * @param {String} type\n\t\t * @param {Object} eventArguments\n\t\t * @param {Function} defaultFunction\n\t\t */\n\t\tfireEvent: function (el, type, eventArguments, defaultFunction) {\n\t\t\tvar event = $.Event(type),\n\t\t\t\tdetachedType = 'detached' + type,\n\t\t\t\tdefaultPrevented;\n\t\n\t\t\t// Remove warnings in Chrome when accessing layerX and layerY. Although Highcharts\n\t\t\t// never uses these properties, Chrome includes them in the default click event and\n\t\t\t// raises the warning when they are copied over in the extend statement below.\n\t\t\t//\n\t\t\t// To avoid problems in IE (see #1010) where we cannot delete the properties and avoid\n\t\t\t// testing if they are there (warning in chrome) the only option is to test if running IE.\n\t\t\tif (!isIE && eventArguments) {\n\t\t\t\tdelete eventArguments.layerX;\n\t\t\t\tdelete eventArguments.layerY;\n\t\t\t}\n\t\n\t\t\textend(event, eventArguments);\n\t\n\t\t\t// Prevent jQuery from triggering the object method that is named the\n\t\t\t// same as the event. For example, if the event is 'select', jQuery\n\t\t\t// attempts calling el.select and it goes into a loop.\n\t\t\tif (el[type]) {\n\t\t\t\tel[detachedType] = el[type];\n\t\t\t\tel[type] = null;\n\t\t\t}\n\t\n\t\t\t// Wrap preventDefault and stopPropagation in try/catch blocks in\n\t\t\t// order to prevent JS errors when cancelling events on non-DOM\n\t\t\t// objects. #615.\n\t\t\t/*jslint unparam: true*/\n\t\t\t$.each(['preventDefault', 'stopPropagation'], function (i, fn) {\n\t\t\t\tvar base = event[fn];\n\t\t\t\tevent[fn] = function () {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tbase.call(event);\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tif (fn === 'preventDefault') {\n\t\t\t\t\t\t\tdefaultPrevented = true;\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/*jslint unparam: false*/\n\t\n\t\t\t// trigger it\n\t\t\t$(el).trigger(event);\n\t\n\t\t\t// attach the method\n\t\t\tif (el[detachedType]) {\n\t\t\t\tel[type] = el[detachedType];\n\t\t\t\tel[detachedType] = null;\n\t\t\t}\n\t\n\t\t\tif (defaultFunction && !event.isDefaultPrevented() && !defaultPrevented) {\n\t\t\t\tdefaultFunction(event);\n\t\t\t}\n\t\t},\n\t\t\n\t\t/**\n\t\t * Extension method needed for MooTools\n\t\t */\n\t\twashMouseEvent: function (e) {\n\t\t\tvar ret = e.originalEvent || e;\n\t\t\t\n\t\t\t// computed by jQuery, needed by IE8\n\t\t\tif (ret.pageX === UNDEFINED) { // #1236\n\t\t\t\tret.pageX = e.pageX;\n\t\t\t\tret.pageY = e.pageY;\n\t\t\t}\n\t\t\t\n\t\t\treturn ret;\n\t\t},\n\t\n\t\t/**\n\t\t * Animate a HTML element or SVG element wrapper\n\t\t * @param {Object} el\n\t\t * @param {Object} params\n\t\t * @param {Object} options jQuery-like animation options: duration, easing, callback\n\t\t */\n\t\tanimate: function (el, params, options) {\n\t\t\tvar $el = $(el);\n\t\t\tif (!el.style) {\n\t\t\t\tel.style = {}; // #1881\n\t\t\t}\n\t\t\tif (params.d) {\n\t\t\t\tel.toD = params.d; // keep the array form for paths, used in $.fx.step.d\n\t\t\t\tparams.d = 1; // because in jQuery, animating to an array has a different meaning\n\t\t\t}\n\t\n\t\t\t$el.stop();\n\t\t\t$el.animate(params, options);\n\t\n\t\t},\n\t\t/**\n\t\t * Stop running animation\n\t\t */\n\t\tstop: function (el) {\n\t\t\t$(el).stop();\n\t\t}\n\t});\n}(win.jQuery));\n\n\n// check for a custom HighchartsAdapter defined prior to this file\nvar globalAdapter = win.HighchartsAdapter,\n\tadapter = globalAdapter || {};\n\t\n// Initialize the adapter\nif (globalAdapter) {\n\tglobalAdapter.init.call(globalAdapter, pathAnim);\n}\n\n\n// Utility functions. If the HighchartsAdapter is not defined, adapter is an empty object\n// and all the utility functions will be null. In that case they are populated by the\n// default adapters below.\nvar adapterRun = adapter.adapterRun,\n\tgetScript = adapter.getScript,\n\tinArray = adapter.inArray,\n\teach = adapter.each,\n\tgrep = adapter.grep,\n\toffset = adapter.offset,\n\tmap = adapter.map,\n\taddEvent = adapter.addEvent,\n\tremoveEvent = adapter.removeEvent,\n\tfireEvent = adapter.fireEvent,\n\twashMouseEvent = adapter.washMouseEvent,\n\tanimate = adapter.animate,\n\tstop = adapter.stop;\n\n\n\n/* ****************************************************************************\n * Handle the options                                                         *\n *****************************************************************************/\nvar\n\ndefaultLabelOptions = {\n\tenabled: true,\n\t// rotation: 0,\n\t// align: 'center',\n\tx: 0,\n\ty: 15,\n\t/*formatter: function () {\n\t\treturn this.value;\n\t},*/\n\tstyle: {\n\t\tcolor: '#666',\n\t\tcursor: 'default',\n\t\tfontSize: '11px',\n\t\tlineHeight: '14px'\n\t}\n};\n\ndefaultOptions = {\n\tcolors: ['#2f7ed8', '#0d233a', '#8bbc21', '#910000', '#1aadce', '#492970',\n\t\t'#f28f43', '#77a1e5', '#c42525', '#a6c96a'],\n\tsymbols: ['circle', 'diamond', 'square', 'triangle', 'triangle-down'],\n\tlang: {\n\t\tloading: 'Loading...',\n\t\tmonths: ['January', 'February', 'March', 'April', 'May', 'June', 'July',\n\t\t\t\t'August', 'September', 'October', 'November', 'December'],\n\t\tshortMonths: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],\n\t\tweekdays: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],\n\t\tdecimalPoint: '.',\n\t\tnumericSymbols: ['k', 'M', 'G', 'T', 'P', 'E'], // SI prefixes used in axis labels\n\t\tresetZoom: 'Reset zoom',\n\t\tresetZoomTitle: 'Reset zoom level 1:1',\n\t\tthousandsSep: ','\n\t},\n\tglobal: {\n\t\tuseUTC: true,\n\t\tcanvasToolsURL: 'http://code.highcharts.com/3.0.3/modules/canvas-tools.js',\n\t\tVMLRadialGradientURL: 'http://code.highcharts.com/3.0.3/gfx/vml-radial-gradient.png'\n\t},\n\tchart: {\n\t\t//animation: true,\n\t\t//alignTicks: false,\n\t\t//reflow: true,\n\t\t//className: null,\n\t\t//events: { load, selection },\n\t\t//margin: [null],\n\t\t//marginTop: null,\n\t\t//marginRight: null,\n\t\t//marginBottom: null,\n\t\t//marginLeft: null,\n\t\tborderColor: '#4572A7',\n\t\t//borderWidth: 0,\n\t\tborderRadius: 5,\n\t\tdefaultSeriesType: 'line',\n\t\tignoreHiddenSeries: true,\n\t\t//inverted: false,\n\t\t//shadow: false,\n\t\tspacingTop: 10,\n\t\tspacingRight: 10,\n\t\tspacingBottom: 15,\n\t\tspacingLeft: 10,\n\t\tstyle: {\n\t\t\tfontFamily: '\"Lucida Grande\", \"Lucida Sans Unicode\", Verdana, Arial, Helvetica, sans-serif', // default font\n\t\t\tfontSize: '12px'\n\t\t},\n\t\tbackgroundColor: '#FFFFFF',\n\t\t//plotBackgroundColor: null,\n\t\tplotBorderColor: '#C0C0C0',\n\t\t//plotBorderWidth: 0,\n\t\t//plotShadow: false,\n\t\t//zoomType: ''\n\t\tresetZoomButton: {\n\t\t\ttheme: {\n\t\t\t\tzIndex: 20\n\t\t\t},\n\t\t\tposition: {\n\t\t\t\talign: 'right',\n\t\t\t\tx: -10,\n\t\t\t\t//verticalAlign: 'top',\n\t\t\t\ty: 10\n\t\t\t}\n\t\t\t// relativeTo: 'plot'\n\t\t}\n\t},\n\ttitle: {\n\t\ttext: 'Chart title',\n\t\talign: 'center',\n\t\t// floating: false,\n\t\tmargin: 15,\n\t\t// x: 0,\n\t\t// verticalAlign: 'top',\n\t\t// y: null,\n\t\tstyle: {\n\t\t\tcolor: '#274b6d',//#3E576F',\n\t\t\tfontSize: '16px'\n\t\t}\n\n\t},\n\tsubtitle: {\n\t\ttext: '',\n\t\talign: 'center',\n\t\t// floating: false\n\t\t// x: 0,\n\t\t// verticalAlign: 'top',\n\t\t// y: null,\n\t\tstyle: {\n\t\t\tcolor: '#4d759e'\n\t\t}\n\t},\n\n\tplotOptions: {\n\t\tline: { // base series options\n\t\t\tallowPointSelect: false,\n\t\t\tshowCheckbox: false,\n\t\t\tanimation: {\n\t\t\t\tduration: 1000\n\t\t\t},\n\t\t\t//connectNulls: false,\n\t\t\t//cursor: 'default',\n\t\t\t//clip: true,\n\t\t\t//dashStyle: null,\n\t\t\t//enableMouseTracking: true,\n\t\t\tevents: {},\n\t\t\t//legendIndex: 0,\n\t\t\tlineWidth: 2,\n\t\t\t//shadow: false,\n\t\t\t// stacking: null,\n\t\t\tmarker: {\n\t\t\t\tenabled: true,\n\t\t\t\t//symbol: null,\n\t\t\t\tlineWidth: 0,\n\t\t\t\tradius: 4,\n\t\t\t\tlineColor: '#FFFFFF',\n\t\t\t\t//fillColor: null,\n\t\t\t\tstates: { // states for a single point\n\t\t\t\t\thover: {\n\t\t\t\t\t\tenabled: true\n\t\t\t\t\t\t//radius: base + 2\n\t\t\t\t\t},\n\t\t\t\t\tselect: {\n\t\t\t\t\t\tfillColor: '#FFFFFF',\n\t\t\t\t\t\tlineColor: '#000000',\n\t\t\t\t\t\tlineWidth: 2\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\tpoint: {\n\t\t\t\tevents: {}\n\t\t\t},\n\t\t\tdataLabels: merge(defaultLabelOptions, {\n\t\t\t\talign: 'center',\n\t\t\t\tenabled: false,\n\t\t\t\tformatter: function () {\n\t\t\t\t\treturn this.y === null ? '' : numberFormat(this.y, -1);\n\t\t\t\t},\n\t\t\t\tverticalAlign: 'bottom', // above singular point\n\t\t\t\ty: 0\n\t\t\t\t// backgroundColor: undefined,\n\t\t\t\t// borderColor: undefined,\n\t\t\t\t// borderRadius: undefined,\n\t\t\t\t// borderWidth: undefined,\n\t\t\t\t// padding: 3,\n\t\t\t\t// shadow: false\n\t\t\t}),\n\t\t\tcropThreshold: 300, // draw points outside the plot area when the number of points is less than this\n\t\t\tpointRange: 0,\n\t\t\t//pointStart: 0,\n\t\t\t//pointInterval: 1,\n\t\t\tshowInLegend: true,\n\t\t\tstates: { // states for the entire series\n\t\t\t\thover: {\n\t\t\t\t\t//enabled: false,\n\t\t\t\t\t//lineWidth: base + 1,\n\t\t\t\t\tmarker: {\n\t\t\t\t\t\t// lineWidth: base + 1,\n\t\t\t\t\t\t// radius: base + 1\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tselect: {\n\t\t\t\t\tmarker: {}\n\t\t\t\t}\n\t\t\t},\n\t\t\tstickyTracking: true\n\t\t\t//tooltip: {\n\t\t\t\t//pointFormat: '<span style=\"color:{series.color}\">{series.name}</span>: <b>{point.y}</b>'\n\t\t\t\t//valueDecimals: null,\n\t\t\t\t//xDateFormat: '%A, %b %e, %Y',\n\t\t\t\t//valuePrefix: '',\n\t\t\t\t//ySuffix: ''\t\t\t\t\n\t\t\t//}\n\t\t\t// turboThreshold: 1000\n\t\t\t// zIndex: null\n\t\t}\n\t},\n\tlabels: {\n\t\t//items: [],\n\t\tstyle: {\n\t\t\t//font: defaultFont,\n\t\t\tposition: ABSOLUTE,\n\t\t\tcolor: '#3E576F'\n\t\t}\n\t},\n\tlegend: {\n\t\tenabled: true,\n\t\talign: 'center',\n\t\t//floating: false,\n\t\tlayout: 'horizontal',\n\t\tlabelFormatter: function () {\n\t\t\treturn this.name;\n\t\t},\n\t\tborderWidth: 1,\n\t\tborderColor: '#909090',\n\t\tborderRadius: 5,\n\t\tnavigation: {\n\t\t\t// animation: true,\n\t\t\tactiveColor: '#274b6d',\n\t\t\t// arrowSize: 12\n\t\t\tinactiveColor: '#CCC'\n\t\t\t// style: {} // text styles\n\t\t},\n\t\t// margin: 10,\n\t\t// reversed: false,\n\t\tshadow: false,\n\t\t// backgroundColor: null,\n\t\t/*style: {\n\t\t\tpadding: '5px'\n\t\t},*/\n\t\titemStyle: {\n\t\t\tcursor: 'pointer',\n\t\t\tcolor: '#274b6d',\n\t\t\tfontSize: '12px'\n\t\t},\n\t\titemHoverStyle: {\n\t\t\t//cursor: 'pointer', removed as of #601\n\t\t\tcolor: '#000'\n\t\t},\n\t\titemHiddenStyle: {\n\t\t\tcolor: '#CCC'\n\t\t},\n\t\titemCheckboxStyle: {\n\t\t\tposition: ABSOLUTE,\n\t\t\twidth: '13px', // for IE precision\n\t\t\theight: '13px'\n\t\t},\n\t\t// itemWidth: undefined,\n\t\tsymbolWidth: 16,\n\t\tsymbolPadding: 5,\n\t\tverticalAlign: 'bottom',\n\t\t// width: undefined,\n\t\tx: 0,\n\t\ty: 0,\n\t\ttitle: {\n\t\t\t//text: null,\n\t\t\tstyle: {\n\t\t\t\tfontWeight: 'bold'\n\t\t\t}\n\t\t}\t\t\t\n\t},\n\n\tloading: {\n\t\t// hideDuration: 100,\n\t\tlabelStyle: {\n\t\t\tfontWeight: 'bold',\n\t\t\tposition: RELATIVE,\n\t\t\ttop: '1em'\n\t\t},\n\t\t// showDuration: 0,\n\t\tstyle: {\n\t\t\tposition: ABSOLUTE,\n\t\t\tbackgroundColor: 'white',\n\t\t\topacity: 0.5,\n\t\t\ttextAlign: 'center'\n\t\t}\n\t},\n\n\ttooltip: {\n\t\tenabled: true,\n\t\tanimation: hasSVG,\n\t\t//crosshairs: null,\n\t\tbackgroundColor: 'rgba(255, 255, 255, .85)',\n\t\tborderWidth: 1,\n\t\tborderRadius: 3,\n\t\tdateTimeLabelFormats: { \n\t\t\tmillisecond: '%A, %b %e, %H:%M:%S.%L',\n\t\t\tsecond: '%A, %b %e, %H:%M:%S',\n\t\t\tminute: '%A, %b %e, %H:%M',\n\t\t\thour: '%A, %b %e, %H:%M',\n\t\t\tday: '%A, %b %e, %Y',\n\t\t\tweek: 'Week from %A, %b %e, %Y',\n\t\t\tmonth: '%B %Y',\n\t\t\tyear: '%Y'\n\t\t},\n\t\t//formatter: defaultFormatter,\n\t\theaderFormat: '<span style=\"font-size: 10px\">{point.key}</span><br/>',\n\t\tpointFormat: '<span style=\"color:{series.color}\">{series.name}</span>: <b>{point.y}</b><br/>',\n\t\tshadow: true,\n\t\t//shared: false,\n\t\tsnap: isTouchDevice ? 25 : 10,\n\t\tstyle: {\n\t\t\tcolor: '#333333',\n\t\t\tcursor: 'default',\n\t\t\tfontSize: '12px',\n\t\t\tpadding: '8px',\n\t\t\twhiteSpace: 'nowrap'\n\t\t}\n\t\t//xDateFormat: '%A, %b %e, %Y',\n\t\t//valueDecimals: null,\n\t\t//valuePrefix: '',\n\t\t//valueSuffix: ''\n\t},\n\n\tcredits: {\n\t\tenabled: true,\n\t\ttext: 'Highcharts.com',\n\t\thref: 'http://www.highcharts.com',\n\t\tposition: {\n\t\t\talign: 'right',\n\t\t\tx: -10,\n\t\t\tverticalAlign: 'bottom',\n\t\t\ty: -5\n\t\t},\n\t\tstyle: {\n\t\t\tcursor: 'pointer',\n\t\t\tcolor: '#909090',\n\t\t\tfontSize: '9px'\n\t\t}\n\t}\n};\n\n\n\n\n// Series defaults\nvar defaultPlotOptions = defaultOptions.plotOptions,\n\tdefaultSeriesOptions = defaultPlotOptions.line;\n\n// set the default time methods\nsetTimeMethods();\n\n\n\n/**\n * Set the time methods globally based on the useUTC option. Time method can be either\n * local time or UTC (default).\n */\nfunction setTimeMethods() {\n\tvar useUTC = defaultOptions.global.useUTC,\n\t\tGET = useUTC ? 'getUTC' : 'get',\n\t\tSET = useUTC ? 'setUTC' : 'set';\n\n\tmakeTime = useUTC ? Date.UTC : function (year, month, date, hours, minutes, seconds) {\n\t\treturn new Date(\n\t\t\tyear,\n\t\t\tmonth,\n\t\t\tpick(date, 1),\n\t\t\tpick(hours, 0),\n\t\t\tpick(minutes, 0),\n\t\t\tpick(seconds, 0)\n\t\t).getTime();\n\t};\n\tgetMinutes =  GET + 'Minutes';\n\tgetHours =    GET + 'Hours';\n\tgetDay =      GET + 'Day';\n\tgetDate =     GET + 'Date';\n\tgetMonth =    GET + 'Month';\n\tgetFullYear = GET + 'FullYear';\n\tsetMinutes =  SET + 'Minutes';\n\tsetHours =    SET + 'Hours';\n\tsetDate =     SET + 'Date';\n\tsetMonth =    SET + 'Month';\n\tsetFullYear = SET + 'FullYear';\n\n}\n\n/**\n * Merge the default options with custom options and return the new options structure\n * @param {Object} options The new custom options\n */\nfunction setOptions(options) {\n\t\n\t// Pull out axis options and apply them to the respective default axis options \n\t/*defaultXAxisOptions = merge(defaultXAxisOptions, options.xAxis);\n\tdefaultYAxisOptions = merge(defaultYAxisOptions, options.yAxis);\n\toptions.xAxis = options.yAxis = UNDEFINED;*/\n\t\n\t// Merge in the default options\n\tdefaultOptions = merge(defaultOptions, options);\n\t\n\t// Apply UTC\n\tsetTimeMethods();\n\n\treturn defaultOptions;\n}\n\n/**\n * Get the updated default options. Merely exposing defaultOptions for outside modules\n * isn't enough because the setOptions method creates a new object.\n */\nfunction getOptions() {\n\treturn defaultOptions;\n}\n\n\n/**\n * Handle color operations. The object methods are chainable.\n * @param {String} input The input color in either rbga or hex format\n */\nvar Color = function (input) {\n\t// declare variables\n\tvar rgba = [], result, stops;\n\n\t/**\n\t * Parse the input color to rgba array\n\t * @param {String} input\n\t */\n\tfunction init(input) {\n\n\t\t// Gradients\n\t\tif (input && input.stops) {\n\t\t\tstops = map(input.stops, function (stop) {\n\t\t\t\treturn Color(stop[1]);\n\t\t\t});\n\n\t\t// Solid colors\n\t\t} else {\n\t\t\t// rgba\n\t\t\tresult = /rgba\\(\\s*([0-9]{1,3})\\s*,\\s*([0-9]{1,3})\\s*,\\s*([0-9]{1,3})\\s*,\\s*([0-9]?(?:\\.[0-9]+)?)\\s*\\)/.exec(input);\n\t\t\tif (result) {\n\t\t\t\trgba = [pInt(result[1]), pInt(result[2]), pInt(result[3]), parseFloat(result[4], 10)];\n\t\t\t} else { \n\t\t\t\t// hex\n\t\t\t\tresult = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(input);\n\t\t\t\tif (result) {\n\t\t\t\t\trgba = [pInt(result[1], 16), pInt(result[2], 16), pInt(result[3], 16), 1];\n\t\t\t\t} else {\n\t\t\t\t\t// rgb\n\t\t\t\t\tresult = /rgb\\(\\s*([0-9]{1,3})\\s*,\\s*([0-9]{1,3})\\s*,\\s*([0-9]{1,3})\\s*\\)/.exec(input);\n\t\t\t\t\tif (result) {\n\t\t\t\t\t\trgba = [pInt(result[1]), pInt(result[2]), pInt(result[3]), 1];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\t\t\n\n\t}\n\t/**\n\t * Return the color a specified format\n\t * @param {String} format\n\t */\n\tfunction get(format) {\n\t\tvar ret;\n\n\t\tif (stops) {\n\t\t\tret = merge(input);\n\t\t\tret.stops = [].concat(ret.stops);\n\t\t\teach(stops, function (stop, i) {\n\t\t\t\tret.stops[i] = [ret.stops[i][0], stop.get(format)];\n\t\t\t});\n\n\t\t// it's NaN if gradient colors on a column chart\n\t\t} else if (rgba && !isNaN(rgba[0])) {\n\t\t\tif (format === 'rgb') {\n\t\t\t\tret = 'rgb(' + rgba[0] + ',' + rgba[1] + ',' + rgba[2] + ')';\n\t\t\t} else if (format === 'a') {\n\t\t\t\tret = rgba[3];\n\t\t\t} else {\n\t\t\t\tret = 'rgba(' + rgba.join(',') + ')';\n\t\t\t}\n\t\t} else {\n\t\t\tret = input;\n\t\t}\n\t\treturn ret;\n\t}\n\n\t/**\n\t * Brighten the color\n\t * @param {Number} alpha\n\t */\n\tfunction brighten(alpha) {\n\t\tif (stops) {\n\t\t\teach(stops, function (stop) {\n\t\t\t\tstop.brighten(alpha);\n\t\t\t});\n\t\t\n\t\t} else if (isNumber(alpha) && alpha !== 0) {\n\t\t\tvar i;\n\t\t\tfor (i = 0; i < 3; i++) {\n\t\t\t\trgba[i] += pInt(alpha * 255);\n\n\t\t\t\tif (rgba[i] < 0) {\n\t\t\t\t\trgba[i] = 0;\n\t\t\t\t}\n\t\t\t\tif (rgba[i] > 255) {\n\t\t\t\t\trgba[i] = 255;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t}\n\t/**\n\t * Set the color's opacity to a given alpha value\n\t * @param {Number} alpha\n\t */\n\tfunction setOpacity(alpha) {\n\t\trgba[3] = alpha;\n\t\treturn this;\n\t}\n\n\t// initialize: parse the input\n\tinit(input);\n\n\t// public methods\n\treturn {\n\t\tget: get,\n\t\tbrighten: brighten,\n\t\trgba: rgba,\n\t\tsetOpacity: setOpacity\n\t};\n};\n\n\n/**\n * A wrapper object for SVG elements\n */\nfunction SVGElement() {}\n\nSVGElement.prototype = {\n\t/**\n\t * Initialize the SVG renderer\n\t * @param {Object} renderer\n\t * @param {String} nodeName\n\t */\n\tinit: function (renderer, nodeName) {\n\t\tvar wrapper = this;\n\t\twrapper.element = nodeName === 'span' ?\n\t\t\tcreateElement(nodeName) :\n\t\t\tdoc.createElementNS(SVG_NS, nodeName);\n\t\twrapper.renderer = renderer;\n\t\t/**\n\t\t * A collection of attribute setters. These methods, if defined, are called right before a certain\n\t\t * attribute is set on an element wrapper. Returning false prevents the default attribute\n\t\t * setter to run. Returning a value causes the default setter to set that value. Used in\n\t\t * Renderer.label.\n\t\t */\n\t\twrapper.attrSetters = {};\n\t},\n\t/**\n\t * Default base for animation\n\t */\n\topacity: 1,\n\t/**\n\t * Animate a given attribute\n\t * @param {Object} params\n\t * @param {Number} options The same options as in jQuery animation\n\t * @param {Function} complete Function to perform at the end of animation\n\t */\n\tanimate: function (params, options, complete) {\n\t\tvar animOptions = pick(options, globalAnimation, true);\n\t\tstop(this); // stop regardless of animation actually running, or reverting to .attr (#607)\n\t\tif (animOptions) {\n\t\t\tanimOptions = merge(animOptions);\n\t\t\tif (complete) { // allows using a callback with the global animation without overwriting it\n\t\t\t\tanimOptions.complete = complete;\n\t\t\t}\n\t\t\tanimate(this, params, animOptions);\n\t\t} else {\n\t\t\tthis.attr(params);\n\t\t\tif (complete) {\n\t\t\t\tcomplete();\n\t\t\t}\n\t\t}\n\t},\n\t/**\n\t * Set or get a given attribute\n\t * @param {Object|String} hash\n\t * @param {Mixed|Undefined} val\n\t */\n\tattr: function (hash, val) {\n\t\tvar wrapper = this,\n\t\t\tkey,\n\t\t\tvalue,\n\t\t\tresult,\n\t\t\ti,\n\t\t\tchild,\n\t\t\telement = wrapper.element,\n\t\t\tnodeName = element.nodeName.toLowerCase(), // Android2 requires lower for \"text\"\n\t\t\trenderer = wrapper.renderer,\n\t\t\tskipAttr,\n\t\t\ttitleNode,\n\t\t\tattrSetters = wrapper.attrSetters,\n\t\t\tshadows = wrapper.shadows,\n\t\t\thasSetSymbolSize,\n\t\t\tdoTransform,\n\t\t\tret = wrapper;\n\n\t\t// single key-value pair\n\t\tif (isString(hash) && defined(val)) {\n\t\t\tkey = hash;\n\t\t\thash = {};\n\t\t\thash[key] = val;\n\t\t}\n\n\t\t// used as a getter: first argument is a string, second is undefined\n\t\tif (isString(hash)) {\n\t\t\tkey = hash;\n\t\t\tif (nodeName === 'circle') {\n\t\t\t\tkey = { x: 'cx', y: 'cy' }[key] || key;\n\t\t\t} else if (key === 'strokeWidth') {\n\t\t\t\tkey = 'stroke-width';\n\t\t\t}\n\t\t\tret = attr(element, key) || wrapper[key] || 0;\n\t\t\tif (key !== 'd' && key !== 'visibility') { // 'd' is string in animation step\n\t\t\t\tret = parseFloat(ret);\n\t\t\t}\n\n\t\t// setter\n\t\t} else {\n\n\t\t\tfor (key in hash) {\n\t\t\t\tskipAttr = false; // reset\n\t\t\t\tvalue = hash[key];\n\n\t\t\t\t// check for a specific attribute setter\n\t\t\t\tresult = attrSetters[key] && attrSetters[key].call(wrapper, value, key);\n\n\t\t\t\tif (result !== false) {\n\t\t\t\t\tif (result !== UNDEFINED) {\n\t\t\t\t\t\tvalue = result; // the attribute setter has returned a new value to set\n\t\t\t\t\t}\n\n\t\t\t\t\n\t\t\t\t\t// paths\n\t\t\t\t\tif (key === 'd') {\n\t\t\t\t\t\tif (value && value.join) { // join path\n\t\t\t\t\t\t\tvalue = value.join(' ');\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (/(NaN| {2}|^$)/.test(value)) {\n\t\t\t\t\t\t\tvalue = 'M 0 0';\n\t\t\t\t\t\t}\n\t\t\t\t\t\t//wrapper.d = value; // shortcut for animations\n\n\t\t\t\t\t// update child tspans x values\n\t\t\t\t\t} else if (key === 'x' && nodeName === 'text') {\n\t\t\t\t\t\tfor (i = 0; i < element.childNodes.length; i++) {\n\t\t\t\t\t\t\tchild = element.childNodes[i];\n\t\t\t\t\t\t\t// if the x values are equal, the tspan represents a linebreak\n\t\t\t\t\t\t\tif (attr(child, 'x') === attr(element, 'x')) {\n\t\t\t\t\t\t\t\t//child.setAttribute('x', value);\n\t\t\t\t\t\t\t\tattr(child, 'x', value);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if (wrapper.rotation && (key === 'x' || key === 'y')) {\n\t\t\t\t\t\tdoTransform = true;\n\n\t\t\t\t\t// apply gradients\n\t\t\t\t\t} else if (key === 'fill') {\n\t\t\t\t\t\tvalue = renderer.color(value, element, key);\n\n\t\t\t\t\t// circle x and y\n\t\t\t\t\t} else if (nodeName === 'circle' && (key === 'x' || key === 'y')) {\n\t\t\t\t\t\tkey = { x: 'cx', y: 'cy' }[key] || key;\n\n\t\t\t\t\t// rectangle border radius\n\t\t\t\t\t} else if (nodeName === 'rect' && key === 'r') {\n\t\t\t\t\t\tattr(element, {\n\t\t\t\t\t\t\trx: value,\n\t\t\t\t\t\t\try: value\n\t\t\t\t\t\t});\n\t\t\t\t\t\tskipAttr = true;\n\n\t\t\t\t\t// translation and text rotation\n\t\t\t\t\t} else if (key === 'translateX' || key === 'translateY' || key === 'rotation' || \n\t\t\t\t\t\t\tkey === 'verticalAlign' || key === 'scaleX' || key === 'scaleY') {\n\t\t\t\t\t\tdoTransform = true;\n\t\t\t\t\t\tskipAttr = true;\n\n\t\t\t\t\t// apply opacity as subnode (required by legacy WebKit and Batik)\n\t\t\t\t\t} else if (key === 'stroke') {\n\t\t\t\t\t\tvalue = renderer.color(value, element, key);\n\n\t\t\t\t\t// emulate VML's dashstyle implementation\n\t\t\t\t\t} else if (key === 'dashstyle') {\n\t\t\t\t\t\tkey = 'stroke-dasharray';\n\t\t\t\t\t\tvalue = value && value.toLowerCase();\n\t\t\t\t\t\tif (value === 'solid') {\n\t\t\t\t\t\t\tvalue = NONE;\n\t\t\t\t\t\t} else if (value) {\n\t\t\t\t\t\t\tvalue = value\n\t\t\t\t\t\t\t\t.replace('shortdashdotdot', '3,1,1,1,1,1,')\n\t\t\t\t\t\t\t\t.replace('shortdashdot', '3,1,1,1')\n\t\t\t\t\t\t\t\t.replace('shortdot', '1,1,')\n\t\t\t\t\t\t\t\t.replace('shortdash', '3,1,')\n\t\t\t\t\t\t\t\t.replace('longdash', '8,3,')\n\t\t\t\t\t\t\t\t.replace(/dot/g, '1,3,')\n\t\t\t\t\t\t\t\t.replace('dash', '4,3,')\n\t\t\t\t\t\t\t\t.replace(/,$/, '')\n\t\t\t\t\t\t\t\t.split(','); // ending comma\n\n\t\t\t\t\t\t\ti = value.length;\n\t\t\t\t\t\t\twhile (i--) {\n\t\t\t\t\t\t\t\tvalue[i] = pInt(value[i]) * pick(hash['stroke-width'], wrapper['stroke-width']);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tvalue = value.join(',');\n\t\t\t\t\t\t}\n\n\t\t\t\t\t// IE9/MooTools combo: MooTools returns objects instead of numbers and IE9 Beta 2\n\t\t\t\t\t// is unable to cast them. Test again with final IE9.\n\t\t\t\t\t} else if (key === 'width') {\n\t\t\t\t\t\tvalue = pInt(value);\n\n\t\t\t\t\t// Text alignment\n\t\t\t\t\t} else if (key === 'align') {\n\t\t\t\t\t\tkey = 'text-anchor';\n\t\t\t\t\t\tvalue = { left: 'start', center: 'middle', right: 'end' }[value];\n\n\t\t\t\t\t// Title requires a subnode, #431\n\t\t\t\t\t} else if (key === 'title') {\n\t\t\t\t\t\ttitleNode = element.getElementsByTagName('title')[0];\n\t\t\t\t\t\tif (!titleNode) {\n\t\t\t\t\t\t\ttitleNode = doc.createElementNS(SVG_NS, 'title');\n\t\t\t\t\t\t\telement.appendChild(titleNode);\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttitleNode.textContent = value;\n\t\t\t\t\t}\n\n\t\t\t\t\t// jQuery animate changes case\n\t\t\t\t\tif (key === 'strokeWidth') {\n\t\t\t\t\t\tkey = 'stroke-width';\n\t\t\t\t\t}\n\n\t\t\t\t\t// In Chrome/Win < 6 as well as Batik, the stroke attribute can't be set when the stroke-\n\t\t\t\t\t// width is 0. #1369\n\t\t\t\t\tif (key === 'stroke-width' || key === 'stroke') {\n\t\t\t\t\t\twrapper[key] = value;\n\t\t\t\t\t\t// Only apply the stroke attribute if the stroke width is defined and larger than 0\n\t\t\t\t\t\tif (wrapper.stroke && wrapper['stroke-width']) {\n\t\t\t\t\t\t\tattr(element, 'stroke', wrapper.stroke);\n\t\t\t\t\t\t\tattr(element, 'stroke-width', wrapper['stroke-width']);\n\t\t\t\t\t\t\twrapper.hasStroke = true;\n\t\t\t\t\t\t} else if (key === 'stroke-width' && value === 0 && wrapper.hasStroke) {\n\t\t\t\t\t\t\telement.removeAttribute('stroke');\n\t\t\t\t\t\t\twrapper.hasStroke = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tskipAttr = true;\n\t\t\t\t\t}\n\n\t\t\t\t\t// symbols\n\t\t\t\t\tif (wrapper.symbolName && /^(x|y|width|height|r|start|end|innerR|anchorX|anchorY)/.test(key)) {\n\n\n\t\t\t\t\t\tif (!hasSetSymbolSize) {\n\t\t\t\t\t\t\twrapper.symbolAttr(hash);\n\t\t\t\t\t\t\thasSetSymbolSize = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tskipAttr = true;\n\t\t\t\t\t}\n\n\t\t\t\t\t// let the shadow follow the main element\n\t\t\t\t\tif (shadows && /^(width|height|visibility|x|y|d|transform|cx|cy|r)$/.test(key)) {\n\t\t\t\t\t\ti = shadows.length;\n\t\t\t\t\t\twhile (i--) {\n\t\t\t\t\t\t\tattr(\n\t\t\t\t\t\t\t\tshadows[i], \n\t\t\t\t\t\t\t\tkey, \n\t\t\t\t\t\t\t\tkey === 'height' ? \n\t\t\t\t\t\t\t\t\tmathMax(value - (shadows[i].cutHeight || 0), 0) :\n\t\t\t\t\t\t\t\t\tvalue\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// validate heights\n\t\t\t\t\tif ((key === 'width' || key === 'height') && nodeName === 'rect' && value < 0) {\n\t\t\t\t\t\tvalue = 0;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Record for animation and quick access without polling the DOM\n\t\t\t\t\twrapper[key] = value;\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\tif (key === 'text') {\n\t\t\t\t\t\t// Delete bBox memo when the text changes\n\t\t\t\t\t\tif (value !== wrapper.textStr) {\n\t\t\t\t\t\t\tdelete wrapper.bBox;\n\t\t\t\t\t\t}\n\t\t\t\t\t\twrapper.textStr = value;\n\t\t\t\t\t\tif (wrapper.added) {\n\t\t\t\t\t\t\trenderer.buildText(wrapper);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (!skipAttr) {\n\t\t\t\t\t\tattr(element, key, value);\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t// Update transform. Do this outside the loop to prevent redundant updating for batch setting\n\t\t\t// of attributes.\n\t\t\tif (doTransform) {\n\t\t\t\twrapper.updateTransform();\n\t\t\t}\n\n\t\t}\n\t\t\n\t\treturn ret;\n\t},\n\n\t \n\t/**\n\t * Add a class name to an element\n\t */\n\taddClass: function (className) {\n\t\tvar element = this.element,\n\t\t\tcurrentClassName = attr(element, 'class') || '';\n\n\t\tif (currentClassName.indexOf(className) === -1) {\n\t\t\tattr(element, 'class', currentClassName + ' ' + className);\n\t\t}\n\t\treturn this;\n\t},\n\t/* hasClass and removeClass are not (yet) needed\n\thasClass: function (className) {\n\t\treturn attr(this.element, 'class').indexOf(className) !== -1;\n\t},\n\tremoveClass: function (className) {\n\t\tattr(this.element, 'class', attr(this.element, 'class').replace(className, ''));\n\t\treturn this;\n\t},\n\t*/\n\n\t/**\n\t * If one of the symbol size affecting parameters are changed,\n\t * check all the others only once for each call to an element's\n\t * .attr() method\n\t * @param {Object} hash\n\t */\n\tsymbolAttr: function (hash) {\n\t\tvar wrapper = this;\n\n\t\teach(['x', 'y', 'r', 'start', 'end', 'width', 'height', 'innerR', 'anchorX', 'anchorY'], function (key) {\n\t\t\twrapper[key] = pick(hash[key], wrapper[key]);\n\t\t});\n\n\t\twrapper.attr({\n\t\t\td: wrapper.renderer.symbols[wrapper.symbolName](\n\t\t\t\twrapper.x, \n\t\t\t\twrapper.y, \n\t\t\t\twrapper.width, \n\t\t\t\twrapper.height, \n\t\t\t\twrapper\n\t\t\t)\n\t\t});\n\t},\n\n\t/**\n\t * Apply a clipping path to this object\n\t * @param {String} id\n\t */\n\tclip: function (clipRect) {\n\t\treturn this.attr('clip-path', clipRect ? 'url(' + this.renderer.url + '#' + clipRect.id + ')' : NONE);\n\t},\n\n\t/**\n\t * Calculate the coordinates needed for drawing a rectangle crisply and return the\n\t * calculated attributes\n\t * @param {Number} strokeWidth\n\t * @param {Number} x\n\t * @param {Number} y\n\t * @param {Number} width\n\t * @param {Number} height\n\t */\n\tcrisp: function (strokeWidth, x, y, width, height) {\n\n\t\tvar wrapper = this,\n\t\t\tkey,\n\t\t\tattribs = {},\n\t\t\tvalues = {},\n\t\t\tnormalizer;\n\n\t\tstrokeWidth = strokeWidth || wrapper.strokeWidth || (wrapper.attr && wrapper.attr('stroke-width')) || 0;\n\t\tnormalizer = mathRound(strokeWidth) % 2 / 2; // mathRound because strokeWidth can sometimes have roundoff errors\n\n\t\t// normalize for crisp edges\n\t\tvalues.x = mathFloor(x || wrapper.x || 0) + normalizer;\n\t\tvalues.y = mathFloor(y || wrapper.y || 0) + normalizer;\n\t\tvalues.width = mathFloor((width || wrapper.width || 0) - 2 * normalizer);\n\t\tvalues.height = mathFloor((height || wrapper.height || 0) - 2 * normalizer);\n\t\tvalues.strokeWidth = strokeWidth;\n\n\t\tfor (key in values) {\n\t\t\tif (wrapper[key] !== values[key]) { // only set attribute if changed\n\t\t\t\twrapper[key] = attribs[key] = values[key];\n\t\t\t}\n\t\t}\n\n\t\treturn attribs;\n\t},\n\n\t/**\n\t * Set styles for the element\n\t * @param {Object} styles\n\t */\n\tcss: function (styles) {\n\t\t/*jslint unparam: true*//* allow unused param a in the regexp function below */\n\t\tvar elemWrapper = this,\n\t\t\telem = elemWrapper.element,\n\t\t\ttextWidth = styles && styles.width && elem.nodeName.toLowerCase() === 'text',\n\t\t\tn,\n\t\t\tserializedCss = '',\n\t\t\thyphenate = function (a, b) { return '-' + b.toLowerCase(); };\n\t\t/*jslint unparam: false*/\n\n\t\t// convert legacy\n\t\tif (styles && styles.color) {\n\t\t\tstyles.fill = styles.color;\n\t\t}\n\n\t\t// Merge the new styles with the old ones\n\t\tstyles = extend(\n\t\t\telemWrapper.styles,\n\t\t\tstyles\n\t\t);\n\n\t\t// store object\n\t\telemWrapper.styles = styles;\n\t\t\n\t\t\n\t\t// Don't handle line wrap on canvas\n\t\tif (useCanVG && textWidth) {\n\t\t\tdelete styles.width;\n\t\t}\n\t\t\t\n\t\t// serialize and set style attribute\n\t\tif (isIE && !hasSVG) { // legacy IE doesn't support setting style attribute\n\t\t\tif (textWidth) {\n\t\t\t\tdelete styles.width;\n\t\t\t}\n\t\t\tcss(elemWrapper.element, styles);\n\t\t} else {\n\t\t\tfor (n in styles) {\n\t\t\t\tserializedCss += n.replace(/([A-Z])/g, hyphenate) + ':' + styles[n] + ';';\n\t\t\t}\n\t\t\tattr(elem, 'style', serializedCss); // #1881\n\t\t}\n\n\n\t\t// re-build text\n\t\tif (textWidth && elemWrapper.added) {\n\t\t\telemWrapper.renderer.buildText(elemWrapper);\n\t\t}\n\n\t\treturn elemWrapper;\n\t},\n\n\t/**\n\t * Add an event listener\n\t * @param {String} eventType\n\t * @param {Function} handler\n\t */\n\ton: function (eventType, handler) {\n\t\tvar element = this.element;\n\t\t// touch\n\t\tif (hasTouch && eventType === 'click') {\n\t\t\telement.ontouchstart = function (e) {\n\t\t\t\te.preventDefault();\n\t\t\t\thandler.call(element, e);\n\t\t\t};\n\t\t}\n\t\t// simplest possible event model for internal use\n\t\telement['on' + eventType] = handler;\n\t\treturn this;\n\t},\n\t\n\t/**\n\t * Set the coordinates needed to draw a consistent radial gradient across\n\t * pie slices regardless of positioning inside the chart. The format is\n\t * [centerX, centerY, diameter] in pixels.\n\t */\n\tsetRadialReference: function (coordinates) {\n\t\tthis.element.radialReference = coordinates;\n\t\treturn this;\n\t},\n\n\t/**\n\t * Move an object and its children by x and y values\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\ttranslate: function (x, y) {\n\t\treturn this.attr({\n\t\t\ttranslateX: x,\n\t\t\ttranslateY: y\n\t\t});\n\t},\n\n\t/**\n\t * Invert a group, rotate and flip\n\t */\n\tinvert: function () {\n\t\tvar wrapper = this;\n\t\twrapper.inverted = true;\n\t\twrapper.updateTransform();\n\t\treturn wrapper;\n\t},\n\n\t/**\n\t * Apply CSS to HTML elements. This is used in text within SVG rendering and\n\t * by the VML renderer\n\t */\n\thtmlCss: function (styles) {\n\t\tvar wrapper = this,\n\t\t\telement = wrapper.element,\n\t\t\ttextWidth = styles && element.tagName === 'SPAN' && styles.width;\n\n\t\tif (textWidth) {\n\t\t\tdelete styles.width;\n\t\t\twrapper.textWidth = textWidth;\n\t\t\twrapper.updateTransform();\n\t\t}\n\n\t\twrapper.styles = extend(wrapper.styles, styles);\n\t\tcss(wrapper.element, styles);\n\n\t\treturn wrapper;\n\t},\n\n\n\n\t/**\n\t * VML and useHTML method for calculating the bounding box based on offsets\n\t * @param {Boolean} refresh Whether to force a fresh value from the DOM or to\n\t * use the cached value\n\t *\n\t * @return {Object} A hash containing values for x, y, width and height\n\t */\n\n\thtmlGetBBox: function () {\n\t\tvar wrapper = this,\n\t\t\telement = wrapper.element,\n\t\t\tbBox = wrapper.bBox;\n\n\t\t// faking getBBox in exported SVG in legacy IE\n\t\tif (!bBox) {\n\t\t\t// faking getBBox in exported SVG in legacy IE (is this a duplicate of the fix for #1079?)\n\t\t\tif (element.nodeName === 'text') {\n\t\t\t\telement.style.position = ABSOLUTE;\n\t\t\t}\n\n\t\t\tbBox = wrapper.bBox = {\n\t\t\t\tx: element.offsetLeft,\n\t\t\t\ty: element.offsetTop,\n\t\t\t\twidth: element.offsetWidth,\n\t\t\t\theight: element.offsetHeight\n\t\t\t};\n\t\t}\n\n\t\treturn bBox;\n\t},\n\n\t/**\n\t * VML override private method to update elements based on internal\n\t * properties based on SVG transform\n\t */\n\thtmlUpdateTransform: function () {\n\t\t// aligning non added elements is expensive\n\t\tif (!this.added) {\n\t\t\tthis.alignOnAdd = true;\n\t\t\treturn;\n\t\t}\n\n\t\tvar wrapper = this,\n\t\t\trenderer = wrapper.renderer,\n\t\t\telem = wrapper.element,\n\t\t\ttranslateX = wrapper.translateX || 0,\n\t\t\ttranslateY = wrapper.translateY || 0,\n\t\t\tx = wrapper.x || 0,\n\t\t\ty = wrapper.y || 0,\n\t\t\talign = wrapper.textAlign || 'left',\n\t\t\talignCorrection = { left: 0, center: 0.5, right: 1 }[align],\n\t\t\tnonLeft = align && align !== 'left',\n\t\t\tshadows = wrapper.shadows;\n\n\t\t// apply translate\n\t\tcss(elem, {\n\t\t\tmarginLeft: translateX,\n\t\t\tmarginTop: translateY\n\t\t});\n\t\tif (shadows) { // used in labels/tooltip\n\t\t\teach(shadows, function (shadow) {\n\t\t\t\tcss(shadow, {\n\t\t\t\t\tmarginLeft: translateX + 1,\n\t\t\t\t\tmarginTop: translateY + 1\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\n\t\t// apply inversion\n\t\tif (wrapper.inverted) { // wrapper is a group\n\t\t\teach(elem.childNodes, function (child) {\n\t\t\t\trenderer.invertChild(child, elem);\n\t\t\t});\n\t\t}\n\n\t\tif (elem.tagName === 'SPAN') {\n\n\t\t\tvar width, height,\n\t\t\t\trotation = wrapper.rotation,\n\t\t\t\tbaseline,\n\t\t\t\tradians = 0,\n\t\t\t\tcostheta = 1,\n\t\t\t\tsintheta = 0,\n\t\t\t\tquad,\n\t\t\t\ttextWidth = pInt(wrapper.textWidth),\n\t\t\t\txCorr = wrapper.xCorr || 0,\n\t\t\t\tyCorr = wrapper.yCorr || 0,\n\t\t\t\tcurrentTextTransform = [rotation, align, elem.innerHTML, wrapper.textWidth].join(',');\n\n\t\t\tif (currentTextTransform !== wrapper.cTT) { // do the calculations and DOM access only if properties changed\n\n\t\t\t\tif (defined(rotation)) {\n\t\t\t\t\t\n\t\t\t\t\tradians = rotation * deg2rad; // deg to rad\n\t\t\t\t\tcostheta = mathCos(radians);\n\t\t\t\t\tsintheta = mathSin(radians);\n\t\n\t\t\t\t\twrapper.setSpanRotation(rotation, sintheta, costheta);\n\t\t\t\t\t\n\t\t\t\t}\n\n\t\t\t\twidth = pick(wrapper.elemWidth, elem.offsetWidth);\n\t\t\t\theight = pick(wrapper.elemHeight, elem.offsetHeight);\n\n\t\t\t\t// update textWidth\n\t\t\t\tif (width > textWidth && /[ \\-]/.test(elem.textContent || elem.innerText)) { // #983, #1254\n\t\t\t\t\tcss(elem, {\n\t\t\t\t\t\twidth: textWidth + PX,\n\t\t\t\t\t\tdisplay: 'block',\n\t\t\t\t\t\twhiteSpace: 'normal'\n\t\t\t\t\t});\n\t\t\t\t\twidth = textWidth;\n\t\t\t\t}\n\n\t\t\t\t// correct x and y\n\t\t\t\tbaseline = renderer.fontMetrics(elem.style.fontSize).b;\n\t\t\t\txCorr = costheta < 0 && -width;\n\t\t\t\tyCorr = sintheta < 0 && -height;\n\n\t\t\t\t// correct for baseline and corners spilling out after rotation\n\t\t\t\tquad = costheta * sintheta < 0;\n\t\t\t\txCorr += sintheta * baseline * (quad ? 1 - alignCorrection : alignCorrection);\n\t\t\t\tyCorr -= costheta * baseline * (rotation ? (quad ? alignCorrection : 1 - alignCorrection) : 1);\n\n\t\t\t\t// correct for the length/height of the text\n\t\t\t\tif (nonLeft) {\n\t\t\t\t\txCorr -= width * alignCorrection * (costheta < 0 ? -1 : 1);\n\t\t\t\t\tif (rotation) {\n\t\t\t\t\t\tyCorr -= height * alignCorrection * (sintheta < 0 ? -1 : 1);\n\t\t\t\t\t}\n\t\t\t\t\tcss(elem, {\n\t\t\t\t\t\ttextAlign: align\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// record correction\n\t\t\t\twrapper.xCorr = xCorr;\n\t\t\t\twrapper.yCorr = yCorr;\n\t\t\t}\n\n\t\t\t// apply position with correction\n\t\t\tcss(elem, {\n\t\t\t\tleft: (x + xCorr) + PX,\n\t\t\t\ttop: (y + yCorr) + PX\n\t\t\t});\n\t\t\t\n\t\t\t// force reflow in webkit to apply the left and top on useHTML element (#1249)\n\t\t\tif (isWebKit) {\n\t\t\t\theight = elem.offsetHeight; // assigned to height for JSLint purpose\n\t\t\t}\n\n\t\t\t// record current text transform\n\t\t\twrapper.cTT = currentTextTransform;\n\t\t}\n\t},\n\n\t/**\n\t * Set the rotation of an individual HTML span\n\t */\n\tsetSpanRotation: function (rotation) {\n\t\tvar rotationStyle = {},\n\t\t\tcssTransformKey = isIE ? '-ms-transform' : isWebKit ? '-webkit-transform' : isFirefox ? 'MozTransform' : isOpera ? '-o-transform' : '';\n\t\t\n\t\trotationStyle[cssTransformKey] = rotationStyle.transform = 'rotate(' + rotation + 'deg)';\n\t\tcss(this.element, rotationStyle);\n\t},\n\n\t/**\n\t * Private method to update the transform attribute based on internal\n\t * properties\n\t */\n\tupdateTransform: function () {\n\t\tvar wrapper = this,\n\t\t\ttranslateX = wrapper.translateX || 0,\n\t\t\ttranslateY = wrapper.translateY || 0,\n\t\t\tscaleX = wrapper.scaleX,\n\t\t\tscaleY = wrapper.scaleY,\n\t\t\tinverted = wrapper.inverted,\n\t\t\trotation = wrapper.rotation,\n\t\t\ttransform;\n\n\t\t// flipping affects translate as adjustment for flipping around the group's axis\n\t\tif (inverted) {\n\t\t\ttranslateX += wrapper.attr('width');\n\t\t\ttranslateY += wrapper.attr('height');\n\t\t}\n\n\t\t// Apply translate. Nearly all transformed elements have translation, so instead\n\t\t// of checking for translate = 0, do it always (#1767, #1846).\n\t\ttransform = ['translate(' + translateX + ',' + translateY + ')'];\n\n\t\t// apply rotation\n\t\tif (inverted) {\n\t\t\ttransform.push('rotate(90) scale(-1,1)');\n\t\t} else if (rotation) { // text rotation\n\t\t\ttransform.push('rotate(' + rotation + ' ' + (wrapper.x || 0) + ' ' + (wrapper.y || 0) + ')');\n\t\t}\n\n\t\t// apply scale\n\t\tif (defined(scaleX) || defined(scaleY)) {\n\t\t\ttransform.push('scale(' + pick(scaleX, 1) + ' ' + pick(scaleY, 1) + ')');\n\t\t}\n\n\t\tif (transform.length) {\n\t\t\tattr(wrapper.element, 'transform', transform.join(' '));\n\t\t}\n\t},\n\t/**\n\t * Bring the element to the front\n\t */\n\ttoFront: function () {\n\t\tvar element = this.element;\n\t\telement.parentNode.appendChild(element);\n\t\treturn this;\n\t},\n\n\n\t/**\n\t * Break down alignment options like align, verticalAlign, x and y\n\t * to x and y relative to the chart.\n\t *\n\t * @param {Object} alignOptions\n\t * @param {Boolean} alignByTranslate\n\t * @param {String[Object} box The box to align to, needs a width and height. When the\n\t *        box is a string, it refers to an object in the Renderer. For example, when \n\t *        box is 'spacingBox', it refers to Renderer.spacingBox which holds width, height\n\t *        x and y properties.\n\t *\n\t */\n\talign: function (alignOptions, alignByTranslate, box) {\n\t\tvar align,\n\t\t\tvAlign,\n\t\t\tx,\n\t\t\ty,\n\t\t\tattribs = {},\n\t\t\talignTo,\n\t\t\trenderer = this.renderer,\n\t\t\talignedObjects = renderer.alignedObjects;\n\n\t\t// First call on instanciate\n\t\tif (alignOptions) {\n\t\t\tthis.alignOptions = alignOptions;\n\t\t\tthis.alignByTranslate = alignByTranslate;\n\t\t\tif (!box || isString(box)) { // boxes other than renderer handle this internally\n\t\t\t\tthis.alignTo = alignTo = box || 'renderer';\n\t\t\t\terase(alignedObjects, this); // prevent duplicates, like legendGroup after resize\n\t\t\t\talignedObjects.push(this);\n\t\t\t\tbox = null; // reassign it below\n\t\t\t}\n\t\t\n\t\t// When called on resize, no arguments are supplied\n\t\t} else {\n\t\t\talignOptions = this.alignOptions;\n\t\t\talignByTranslate = this.alignByTranslate;\n\t\t\talignTo = this.alignTo;\n\t\t}\n\n\t\tbox = pick(box, renderer[alignTo], renderer);\n\n\t\t// Assign variables\n\t\talign = alignOptions.align;\n\t\tvAlign = alignOptions.verticalAlign;\n\t\tx = (box.x || 0) + (alignOptions.x || 0); // default: left align\n\t\ty = (box.y || 0) + (alignOptions.y || 0); // default: top align\n\n\t\t// Align\n\t\tif (align === 'right' || align === 'center') {\n\t\t\tx += (box.width - (alignOptions.width || 0)) /\n\t\t\t\t\t{ right: 1, center: 2 }[align];\n\t\t}\n\t\tattribs[alignByTranslate ? 'translateX' : 'x'] = mathRound(x);\n\n\n\t\t// Vertical align\n\t\tif (vAlign === 'bottom' || vAlign === 'middle') {\n\t\t\ty += (box.height - (alignOptions.height || 0)) /\n\t\t\t\t\t({ bottom: 1, middle: 2 }[vAlign] || 1);\n\n\t\t}\n\t\tattribs[alignByTranslate ? 'translateY' : 'y'] = mathRound(y);\n\n\t\t// Animate only if already placed\n\t\tthis[this.placed ? 'animate' : 'attr'](attribs);\n\t\tthis.placed = true;\n\t\tthis.alignAttr = attribs;\n\n\t\treturn this;\n\t},\n\n\t/**\n\t * Get the bounding box (width, height, x and y) for the element\n\t */\n\tgetBBox: function () {\n\t\tvar wrapper = this,\n\t\t\tbBox = wrapper.bBox,\n\t\t\trenderer = wrapper.renderer,\n\t\t\twidth,\n\t\t\theight,\n\t\t\trotation = wrapper.rotation,\n\t\t\telement = wrapper.element,\n\t\t\tstyles = wrapper.styles,\n\t\t\trad = rotation * deg2rad;\n\t\t\t\n\t\tif (!bBox) {\n\t\t\t// SVG elements\n\t\t\tif (element.namespaceURI === SVG_NS || renderer.forExport) {\n\t\t\t\ttry { // Fails in Firefox if the container has display: none.\n\t\t\t\t\t\n\t\t\t\t\tbBox = element.getBBox ?\n\t\t\t\t\t\t// SVG: use extend because IE9 is not allowed to change width and height in case\n\t\t\t\t\t\t// of rotation (below)\n\t\t\t\t\t\textend({}, element.getBBox()) :\n\t\t\t\t\t\t// Canvas renderer and legacy IE in export mode\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\twidth: element.offsetWidth,\n\t\t\t\t\t\t\theight: element.offsetHeight\n\t\t\t\t\t\t};\n\t\t\t\t} catch (e) {}\n\t\t\t\t\n\t\t\t\t// If the bBox is not set, the try-catch block above failed. The other condition\n\t\t\t\t// is for Opera that returns a width of -Infinity on hidden elements.\n\t\t\t\tif (!bBox || bBox.width < 0) {\n\t\t\t\t\tbBox = { width: 0, height: 0 };\n\t\t\t\t}\n\t\t\t\t\n\t\n\t\t\t// VML Renderer or useHTML within SVG\n\t\t\t} else {\n\t\t\t\t\n\t\t\t\tbBox = wrapper.htmlGetBBox();\n\t\t\t\t\n\t\t\t}\n\t\t\t\n\t\t\t// True SVG elements as well as HTML elements in modern browsers using the .useHTML option\n\t\t\t// need to compensated for rotation\n\t\t\tif (renderer.isSVG) {\n\t\t\t\twidth = bBox.width;\n\t\t\t\theight = bBox.height;\n\t\t\t\t\n\t\t\t\t// Workaround for wrong bounding box in IE9 and IE10 (#1101, #1505, #1669)\n\t\t\t\tif (isIE && styles && styles.fontSize === '11px' && height.toPrecision(3) === '22.7') {\n\t\t\t\t\tbBox.height = height = 14;\n\t\t\t\t}\n\t\t\t\n\t\t\t\t// Adjust for rotated text\n\t\t\t\tif (rotation) {\n\t\t\t\t\tbBox.width = mathAbs(height * mathSin(rad)) + mathAbs(width * mathCos(rad));\n\t\t\t\t\tbBox.height = mathAbs(height * mathCos(rad)) + mathAbs(width * mathSin(rad));\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\twrapper.bBox = bBox;\n\t\t}\n\t\treturn bBox;\n\t},\n\n\t/**\n\t * Show the element\n\t */\n\tshow: function () {\n\t\treturn this.attr({ visibility: VISIBLE });\n\t},\n\n\t/**\n\t * Hide the element\n\t */\n\thide: function () {\n\t\treturn this.attr({ visibility: HIDDEN });\n\t},\n\t\n\tfadeOut: function (duration) {\n\t\tvar elemWrapper = this;\n\t\telemWrapper.animate({\n\t\t\topacity: 0\n\t\t}, {\n\t\t\tduration: duration || 150,\n\t\t\tcomplete: function () {\n\t\t\t\telemWrapper.hide();\n\t\t\t}\n\t\t});\n\t},\n\t\n\t/**\n\t * Add the element\n\t * @param {Object|Undefined} parent Can be an element, an element wrapper or undefined\n\t *    to append the element to the renderer.box.\n\t */\n\tadd: function (parent) {\n\n\t\tvar renderer = this.renderer,\n\t\t\tparentWrapper = parent || renderer,\n\t\t\tparentNode = parentWrapper.element || renderer.box,\n\t\t\tchildNodes = parentNode.childNodes,\n\t\t\telement = this.element,\n\t\t\tzIndex = attr(element, 'zIndex'),\n\t\t\totherElement,\n\t\t\totherZIndex,\n\t\t\ti,\n\t\t\tinserted;\n\t\t\t\n\t\tif (parent) {\n\t\t\tthis.parentGroup = parent;\n\t\t}\n\n\t\t// mark as inverted\n\t\tthis.parentInverted = parent && parent.inverted;\n\n\t\t// build formatted text\n\t\tif (this.textStr !== undefined) {\n\t\t\trenderer.buildText(this);\n\t\t}\n\n\t\t// mark the container as having z indexed children\n\t\tif (zIndex) {\n\t\t\tparentWrapper.handleZ = true;\n\t\t\tzIndex = pInt(zIndex);\n\t\t}\n\n\t\t// insert according to this and other elements' zIndex\n\t\tif (parentWrapper.handleZ) { // this element or any of its siblings has a z index\n\t\t\tfor (i = 0; i < childNodes.length; i++) {\n\t\t\t\totherElement = childNodes[i];\n\t\t\t\totherZIndex = attr(otherElement, 'zIndex');\n\t\t\t\tif (otherElement !== element && (\n\t\t\t\t\t\t// insert before the first element with a higher zIndex\n\t\t\t\t\t\tpInt(otherZIndex) > zIndex ||\n\t\t\t\t\t\t// if no zIndex given, insert before the first element with a zIndex\n\t\t\t\t\t\t(!defined(zIndex) && defined(otherZIndex))\n\n\t\t\t\t\t\t)) {\n\t\t\t\t\tparentNode.insertBefore(element, otherElement);\n\t\t\t\t\tinserted = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// default: append at the end\n\t\tif (!inserted) {\n\t\t\tparentNode.appendChild(element);\n\t\t}\n\n\t\t// mark as added\n\t\tthis.added = true;\n\n\t\t// fire an event for internal hooks\n\t\tfireEvent(this, 'add');\n\n\t\treturn this;\n\t},\n\n\t/**\n\t * Removes a child either by removeChild or move to garbageBin.\n\t * Issue 490; in VML removeChild results in Orphaned nodes according to sIEve, discardElement does not.\n\t */\n\tsafeRemoveChild: function (element) {\n\t\tvar parentNode = element.parentNode;\n\t\tif (parentNode) {\n\t\t\tparentNode.removeChild(element);\n\t\t}\n\t},\n\n\t/**\n\t * Destroy the element and element wrapper\n\t */\n\tdestroy: function () {\n\t\tvar wrapper = this,\n\t\t\telement = wrapper.element || {},\n\t\t\tshadows = wrapper.shadows,\n\t\t\tparentToClean = wrapper.renderer.isSVG && element.nodeName === 'SPAN' && element.parentNode,\n\t\t\tgrandParent,\n\t\t\tkey,\n\t\t\ti;\n\n\t\t// remove events\n\t\telement.onclick = element.onmouseout = element.onmouseover = element.onmousemove = element.point = null;\n\t\tstop(wrapper); // stop running animations\n\n\t\tif (wrapper.clipPath) {\n\t\t\twrapper.clipPath = wrapper.clipPath.destroy();\n\t\t}\n\n\t\t// Destroy stops in case this is a gradient object\n\t\tif (wrapper.stops) {\n\t\t\tfor (i = 0; i < wrapper.stops.length; i++) {\n\t\t\t\twrapper.stops[i] = wrapper.stops[i].destroy();\n\t\t\t}\n\t\t\twrapper.stops = null;\n\t\t}\n\n\t\t// remove element\n\t\twrapper.safeRemoveChild(element);\n\n\t\t// destroy shadows\n\t\tif (shadows) {\n\t\t\teach(shadows, function (shadow) {\n\t\t\t\twrapper.safeRemoveChild(shadow);\n\t\t\t});\n\t\t}\n\n\t\t// In case of useHTML, clean up empty containers emulating SVG groups (#1960).\n\t\twhile (parentToClean && parentToClean.childNodes.length === 0) {\n\t\t\tgrandParent = parentToClean.parentNode;\n\t\t\twrapper.safeRemoveChild(parentToClean);\n\t\t\tparentToClean = grandParent;\n\t\t}\n\n\t\t// remove from alignObjects\n\t\tif (wrapper.alignTo) {\n\t\t\terase(wrapper.renderer.alignedObjects, wrapper);\n\t\t}\n\n\t\tfor (key in wrapper) {\n\t\t\tdelete wrapper[key];\n\t\t}\n\n\t\treturn null;\n\t},\n\n\t/**\n\t * Add a shadow to the element. Must be done after the element is added to the DOM\n\t * @param {Boolean|Object} shadowOptions\n\t */\n\tshadow: function (shadowOptions, group, cutOff) {\n\t\tvar shadows = [],\n\t\t\ti,\n\t\t\tshadow,\n\t\t\telement = this.element,\n\t\t\tstrokeWidth,\n\t\t\tshadowWidth,\n\t\t\tshadowElementOpacity,\n\n\t\t\t// compensate for inverted plot area\n\t\t\ttransform;\n\n\n\t\tif (shadowOptions) {\n\t\t\tshadowWidth = pick(shadowOptions.width, 3);\n\t\t\tshadowElementOpacity = (shadowOptions.opacity || 0.15) / shadowWidth;\n\t\t\ttransform = this.parentInverted ? \n\t\t\t\t'(-1,-1)' : \n\t\t\t\t'(' + pick(shadowOptions.offsetX, 1) + ', ' + pick(shadowOptions.offsetY, 1) + ')';\n\t\t\tfor (i = 1; i <= shadowWidth; i++) {\n\t\t\t\tshadow = element.cloneNode(0);\n\t\t\t\tstrokeWidth = (shadowWidth * 2) + 1 - (2 * i);\n\t\t\t\tattr(shadow, {\n\t\t\t\t\t'isShadow': 'true',\n\t\t\t\t\t'stroke': shadowOptions.color || 'black',\n\t\t\t\t\t'stroke-opacity': shadowElementOpacity * i,\n\t\t\t\t\t'stroke-width': strokeWidth,\n\t\t\t\t\t'transform': 'translate' + transform,\n\t\t\t\t\t'fill': NONE\n\t\t\t\t});\n\t\t\t\tif (cutOff) {\n\t\t\t\t\tattr(shadow, 'height', mathMax(attr(shadow, 'height') - strokeWidth, 0));\n\t\t\t\t\tshadow.cutHeight = strokeWidth;\n\t\t\t\t}\n\n\t\t\t\tif (group) {\n\t\t\t\t\tgroup.element.appendChild(shadow);\n\t\t\t\t} else {\n\t\t\t\t\telement.parentNode.insertBefore(shadow, element);\n\t\t\t\t}\n\n\t\t\t\tshadows.push(shadow);\n\t\t\t}\n\n\t\t\tthis.shadows = shadows;\n\t\t}\n\t\treturn this;\n\n\t}\n};\n\n\n/**\n * The default SVG renderer\n */\nvar SVGRenderer = function () {\n\tthis.init.apply(this, arguments);\n};\nSVGRenderer.prototype = {\n\tElement: SVGElement,\n\n\t/**\n\t * Initialize the SVGRenderer\n\t * @param {Object} container\n\t * @param {Number} width\n\t * @param {Number} height\n\t * @param {Boolean} forExport\n\t */\n\tinit: function (container, width, height, forExport) {\n\t\tvar renderer = this,\n\t\t\tloc = location,\n\t\t\tboxWrapper,\n\t\t\telement,\n\t\t\tdesc;\n\n\t\tboxWrapper = renderer.createElement('svg')\n\t\t\t.attr({\n\t\t\t\tversion: '1.1'\n\t\t\t});\n\t\telement = boxWrapper.element;\n\t\tcontainer.appendChild(element);\n\n\t\t// For browsers other than IE, add the namespace attribute (#1978)\n\t\tif (container.innerHTML.indexOf('xmlns') === -1) {\n\t\t\tattr(element, 'xmlns', SVG_NS);\n\t\t}\n\n\t\t// object properties\n\t\trenderer.isSVG = true;\n\t\trenderer.box = element;\n\t\trenderer.boxWrapper = boxWrapper;\n\t\trenderer.alignedObjects = [];\n\t\t\n\t\t// Page url used for internal references. #24, #672, #1070\n\t\trenderer.url = (isFirefox || isWebKit) && doc.getElementsByTagName('base').length ? \n\t\t\tloc.href\n\t\t\t\t.replace(/#.*?$/, '') // remove the hash\n\t\t\t\t.replace(/([\\('\\)])/g, '\\\\$1') // escape parantheses and quotes\n\t\t\t\t.replace(/ /g, '%20') : // replace spaces (needed for Safari only)\n\t\t\t''; \n\t\t\t\n\t\t// Add description\n\t\tdesc = this.createElement('desc').add();\n\t\tdesc.element.appendChild(doc.createTextNode('Created with ' + PRODUCT + ' ' + VERSION));\n\n\t\t\n\t\trenderer.defs = this.createElement('defs').add();\n\t\trenderer.forExport = forExport;\n\t\trenderer.gradients = {}; // Object where gradient SvgElements are stored\n\n\t\trenderer.setSize(width, height, false);\n\n\n\n\t\t// Issue 110 workaround:\n\t\t// In Firefox, if a div is positioned by percentage, its pixel position may land\n\t\t// between pixels. The container itself doesn't display this, but an SVG element\n\t\t// inside this container will be drawn at subpixel precision. In order to draw\n\t\t// sharp lines, this must be compensated for. This doesn't seem to work inside\n\t\t// iframes though (like in jsFiddle).\n\t\tvar subPixelFix, rect;\n\t\tif (isFirefox && container.getBoundingClientRect) {\n\t\t\trenderer.subPixelFix = subPixelFix = function () {\n\t\t\t\tcss(container, { left: 0, top: 0 });\n\t\t\t\trect = container.getBoundingClientRect();\n\t\t\t\tcss(container, {\n\t\t\t\t\tleft: (mathCeil(rect.left) - rect.left) + PX,\n\t\t\t\t\ttop: (mathCeil(rect.top) - rect.top) + PX\n\t\t\t\t});\n\t\t\t};\n\n\t\t\t// run the fix now\n\t\t\tsubPixelFix();\n\n\t\t\t// run it on resize\n\t\t\taddEvent(win, 'resize', subPixelFix);\n\t\t}\n\t},\n\n\t/**\n\t * Detect whether the renderer is hidden. This happens when one of the parent elements\n\t * has display: none. #608.\n\t */\n\tisHidden: function () {\n\t\treturn !this.boxWrapper.getBBox().width;\t\t\t\n\t},\n\n\t/**\n\t * Destroys the renderer and its allocated members.\n\t */\n\tdestroy: function () {\n\t\tvar renderer = this,\n\t\t\trendererDefs = renderer.defs;\n\t\trenderer.box = null;\n\t\trenderer.boxWrapper = renderer.boxWrapper.destroy();\n\n\t\t// Call destroy on all gradient elements\n\t\tdestroyObjectProperties(renderer.gradients || {});\n\t\trenderer.gradients = null;\n\n\t\t// Defs are null in VMLRenderer\n\t\t// Otherwise, destroy them here.\n\t\tif (rendererDefs) {\n\t\t\trenderer.defs = rendererDefs.destroy();\n\t\t}\n\n\t\t// Remove sub pixel fix handler\n\t\t// We need to check that there is a handler, otherwise all functions that are registered for event 'resize' are removed\n\t\t// See issue #982\n\t\tif (renderer.subPixelFix) {\n\t\t\tremoveEvent(win, 'resize', renderer.subPixelFix);\n\t\t}\n\n\t\trenderer.alignedObjects = null;\n\n\t\treturn null;\n\t},\n\n\t/**\n\t * Create a wrapper for an SVG element\n\t * @param {Object} nodeName\n\t */\n\tcreateElement: function (nodeName) {\n\t\tvar wrapper = new this.Element();\n\t\twrapper.init(this, nodeName);\n\t\treturn wrapper;\n\t},\n\n\t/**\n\t * Dummy function for use in canvas renderer\n\t */\n\tdraw: function () {},\n\n\t/**\n\t * Parse a simple HTML string into SVG tspans\n\t *\n\t * @param {Object} textNode The parent text SVG node\n\t */\n\tbuildText: function (wrapper) {\n\t\tvar textNode = wrapper.element,\n\t\t\trenderer = this,\n\t\t\tforExport = renderer.forExport,\n\t\t\tlines = pick(wrapper.textStr, '').toString()\n\t\t\t\t.replace(/<(b|strong)>/g, '<span style=\"font-weight:bold\">')\n\t\t\t\t.replace(/<(i|em)>/g, '<span style=\"font-style:italic\">')\n\t\t\t\t.replace(/<a/g, '<span')\n\t\t\t\t.replace(/<\\/(b|strong|i|em|a)>/g, '</span>')\n\t\t\t\t.split(/<br.*?>/g),\n\t\t\tchildNodes = textNode.childNodes,\n\t\t\tstyleRegex = /style=\"([^\"]+)\"/,\n\t\t\threfRegex = /href=\"(http[^\"]+)\"/,\n\t\t\tparentX = attr(textNode, 'x'),\n\t\t\ttextStyles = wrapper.styles,\n\t\t\twidth = textStyles && textStyles.width && pInt(textStyles.width),\n\t\t\ttextLineHeight = textStyles && textStyles.lineHeight,\n\t\t\ti = childNodes.length;\n\n\t\t/// remove old text\n\t\twhile (i--) {\n\t\t\ttextNode.removeChild(childNodes[i]);\n\t\t}\n\n\t\tif (width && !wrapper.added) {\n\t\t\tthis.box.appendChild(textNode); // attach it to the DOM to read offset width\n\t\t}\n\n\t\t// remove empty line at end\n\t\tif (lines[lines.length - 1] === '') {\n\t\t\tlines.pop();\n\t\t}\n\n\t\t// build the lines\n\t\teach(lines, function (line, lineNo) {\n\t\t\tvar spans, spanNo = 0;\n\n\t\t\tline = line.replace(/<span/g, '|||<span').replace(/<\\/span>/g, '</span>|||');\n\t\t\tspans = line.split('|||');\n\n\t\t\teach(spans, function (span) {\n\t\t\t\tif (span !== '' || spans.length === 1) {\n\t\t\t\t\tvar attributes = {},\n\t\t\t\t\t\ttspan = doc.createElementNS(SVG_NS, 'tspan'),\n\t\t\t\t\t\tspanStyle; // #390\n\t\t\t\t\tif (styleRegex.test(span)) {\n\t\t\t\t\t\tspanStyle = span.match(styleRegex)[1].replace(/(;| |^)color([ :])/, '$1fill$2');\n\t\t\t\t\t\tattr(tspan, 'style', spanStyle);\n\t\t\t\t\t}\n\t\t\t\t\tif (hrefRegex.test(span) && !forExport) { // Not for export - #1529\n\t\t\t\t\t\tattr(tspan, 'onclick', 'location.href=\\\"' + span.match(hrefRegex)[1] + '\\\"');\n\t\t\t\t\t\tcss(tspan, { cursor: 'pointer' });\n\t\t\t\t\t}\n\n\t\t\t\t\tspan = (span.replace(/<(.|\\n)*?>/g, '') || ' ')\n\t\t\t\t\t\t.replace(/&lt;/g, '<')\n\t\t\t\t\t\t.replace(/&gt;/g, '>');\n\n\t\t\t\t\t// Nested tags aren't supported, and cause crash in Safari (#1596)\n\t\t\t\t\tif (span !== ' ') {\n\t\t\t\t\t\n\t\t\t\t\t\t// add the text node\n\t\t\t\t\t\ttspan.appendChild(doc.createTextNode(span));\n\n\t\t\t\t\t\tif (!spanNo) { // first span in a line, align it to the left\n\t\t\t\t\t\t\tattributes.x = parentX;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tattributes.dx = 0; // #16\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// add attributes\n\t\t\t\t\t\tattr(tspan, attributes);\n\n\t\t\t\t\t\t// first span on subsequent line, add the line height\n\t\t\t\t\t\tif (!spanNo && lineNo) {\n\n\t\t\t\t\t\t\t// allow getting the right offset height in exporting in IE\n\t\t\t\t\t\t\tif (!hasSVG && forExport) {\n\t\t\t\t\t\t\t\tcss(tspan, { display: 'block' });\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Set the line height based on the font size of either \n\t\t\t\t\t\t\t// the text element or the tspan element\n\t\t\t\t\t\t\tattr(\n\t\t\t\t\t\t\t\ttspan, \n\t\t\t\t\t\t\t\t'dy',\n\t\t\t\t\t\t\t\ttextLineHeight || renderer.fontMetrics(\n\t\t\t\t\t\t\t\t\t/px$/.test(tspan.style.fontSize) ?\n\t\t\t\t\t\t\t\t\t\ttspan.style.fontSize : \n\t\t\t\t\t\t\t\t\t\ttextStyles.fontSize\n\t\t\t\t\t\t\t\t).h,\n\t\t\t\t\t\t\t\t// Safari 6.0.2 - too optimized for its own good (#1539)\n\t\t\t\t\t\t\t\t// TODO: revisit this with future versions of Safari\n\t\t\t\t\t\t\t\tisWebKit && tspan.offsetHeight\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Append it\n\t\t\t\t\t\ttextNode.appendChild(tspan);\n\n\t\t\t\t\t\tspanNo++;\n\n\t\t\t\t\t\t// check width and apply soft breaks\n\t\t\t\t\t\tif (width) {\n\t\t\t\t\t\t\tvar words = span.replace(/([^\\^])-/g, '$1- ').split(' '), // #1273\n\t\t\t\t\t\t\t\ttooLong,\n\t\t\t\t\t\t\t\tactualWidth,\n\t\t\t\t\t\t\t\trest = [];\n\n\t\t\t\t\t\t\twhile (words.length || rest.length) {\n\t\t\t\t\t\t\t\tdelete wrapper.bBox; // delete cache\n\t\t\t\t\t\t\t\tactualWidth = wrapper.getBBox().width;\n\t\t\t\t\t\t\t\ttooLong = actualWidth > width;\n\t\t\t\t\t\t\t\tif (!tooLong || words.length === 1) { // new line needed\n\t\t\t\t\t\t\t\t\twords = rest;\n\t\t\t\t\t\t\t\t\trest = [];\n\t\t\t\t\t\t\t\t\tif (words.length) {\n\t\t\t\t\t\t\t\t\t\ttspan = doc.createElementNS(SVG_NS, 'tspan');\n\t\t\t\t\t\t\t\t\t\tattr(tspan, {\n\t\t\t\t\t\t\t\t\t\t\tdy: textLineHeight || 16,\n\t\t\t\t\t\t\t\t\t\t\tx: parentX\n\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\tif (spanStyle) { // #390\n\t\t\t\t\t\t\t\t\t\t\tattr(tspan, 'style', spanStyle);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\ttextNode.appendChild(tspan);\n\n\t\t\t\t\t\t\t\t\t\tif (actualWidth > width) { // a single word is pressing it out\n\t\t\t\t\t\t\t\t\t\t\twidth = actualWidth;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else { // append to existing line tspan\n\t\t\t\t\t\t\t\t\ttspan.removeChild(tspan.firstChild);\n\t\t\t\t\t\t\t\t\trest.unshift(words.pop());\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (words.length) {\n\t\t\t\t\t\t\t\t\ttspan.appendChild(doc.createTextNode(words.join(' ').replace(/- /g, '-')));\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});\n\t\t});\n\t},\n\n\t/**\n\t * Create a button with preset states\n\t * @param {String} text\n\t * @param {Number} x\n\t * @param {Number} y\n\t * @param {Function} callback\n\t * @param {Object} normalState\n\t * @param {Object} hoverState\n\t * @param {Object} pressedState\n\t */\n\tbutton: function (text, x, y, callback, normalState, hoverState, pressedState) {\n\t\tvar label = this.label(text, x, y, null, null, null, null, null, 'button'),\n\t\t\tcurState = 0,\n\t\t\tstateOptions,\n\t\t\tstateStyle,\n\t\t\tnormalStyle,\n\t\t\thoverStyle,\n\t\t\tpressedStyle,\n\t\t\tSTYLE = 'style',\n\t\t\tverticalGradient = { x1: 0, y1: 0, x2: 0, y2: 1 };\n\n\t\t// Normal state - prepare the attributes\n\t\tnormalState = merge({\n\t\t\t'stroke-width': 1,\n\t\t\tstroke: '#CCCCCC',\n\t\t\tfill: {\n\t\t\t\tlinearGradient: verticalGradient,\n\t\t\t\tstops: [\n\t\t\t\t\t[0, '#FEFEFE'],\n\t\t\t\t\t[1, '#F6F6F6']\n\t\t\t\t]\n\t\t\t},\n\t\t\tr: 2,\n\t\t\tpadding: 5,\n\t\t\tstyle: {\n\t\t\t\tcolor: 'black'\n\t\t\t}\n\t\t}, normalState);\n\t\tnormalStyle = normalState[STYLE];\n\t\tdelete normalState[STYLE];\n\n\t\t// Hover state\n\t\thoverState = merge(normalState, {\n\t\t\tstroke: '#68A',\n\t\t\tfill: {\n\t\t\t\tlinearGradient: verticalGradient,\n\t\t\t\tstops: [\n\t\t\t\t\t[0, '#FFF'],\n\t\t\t\t\t[1, '#ACF']\n\t\t\t\t]\n\t\t\t}\n\t\t}, hoverState);\n\t\thoverStyle = hoverState[STYLE];\n\t\tdelete hoverState[STYLE];\n\n\t\t// Pressed state\n\t\tpressedState = merge(normalState, {\n\t\t\tstroke: '#68A',\n\t\t\tfill: {\n\t\t\t\tlinearGradient: verticalGradient,\n\t\t\t\tstops: [\n\t\t\t\t\t[0, '#9BD'],\n\t\t\t\t\t[1, '#CDF']\n\t\t\t\t]\n\t\t\t}\n\t\t}, pressedState);\n\t\tpressedStyle = pressedState[STYLE];\n\t\tdelete pressedState[STYLE];\n\n\t\t// Add the events. IE9 and IE10 need mouseover and mouseout to funciton (#667).\n\t\taddEvent(label.element, isIE ? 'mouseover' : 'mouseenter', function () {\n\t\t\tlabel.attr(hoverState)\n\t\t\t\t.css(hoverStyle);\n\t\t});\n\t\taddEvent(label.element, isIE ? 'mouseout' : 'mouseleave', function () {\n\t\t\tstateOptions = [normalState, hoverState, pressedState][curState];\n\t\t\tstateStyle = [normalStyle, hoverStyle, pressedStyle][curState];\n\t\t\tlabel.attr(stateOptions)\n\t\t\t\t.css(stateStyle);\n\t\t});\n\n\t\tlabel.setState = function (state) {\n\t\t\tcurState = state;\n\t\t\tif (!state) {\n\t\t\t\tlabel.attr(normalState)\n\t\t\t\t\t.css(normalStyle);\n\t\t\t} else if (state === 2) {\n\t\t\t\tlabel.attr(pressedState)\n\t\t\t\t\t.css(pressedStyle);\n\t\t\t}\n\t\t};\n\n\t\treturn label\n\t\t\t.on('click', function () {\n\t\t\t\tcallback.call(label);\n\t\t\t})\n\t\t\t.attr(normalState)\n\t\t\t.css(extend({ cursor: 'default' }, normalStyle));\n\t},\n\n\t/**\n\t * Make a straight line crisper by not spilling out to neighbour pixels\n\t * @param {Array} points\n\t * @param {Number} width\n\t */\n\tcrispLine: function (points, width) {\n\t\t// points format: [M, 0, 0, L, 100, 0]\n\t\t// normalize to a crisp line\n\t\tif (points[1] === points[4]) {\n\t\t\t// Substract due to #1129. Now bottom and left axis gridlines behave the same.\n\t\t\tpoints[1] = points[4] = mathRound(points[1]) - (width % 2 / 2); \n\t\t}\n\t\tif (points[2] === points[5]) {\n\t\t\tpoints[2] = points[5] = mathRound(points[2]) + (width % 2 / 2);\n\t\t}\n\t\treturn points;\n\t},\n\n\n\t/**\n\t * Draw a path\n\t * @param {Array} path An SVG path in array form\n\t */\n\tpath: function (path) {\n\t\tvar attr = {\n\t\t\tfill: NONE\n\t\t};\n\t\tif (isArray(path)) {\n\t\t\tattr.d = path;\n\t\t} else if (isObject(path)) { // attributes\n\t\t\textend(attr, path);\n\t\t}\n\t\treturn this.createElement('path').attr(attr);\n\t},\n\n\t/**\n\t * Draw and return an SVG circle\n\t * @param {Number} x The x position\n\t * @param {Number} y The y position\n\t * @param {Number} r The radius\n\t */\n\tcircle: function (x, y, r) {\n\t\tvar attr = isObject(x) ?\n\t\t\tx :\n\t\t\t{\n\t\t\t\tx: x,\n\t\t\t\ty: y,\n\t\t\t\tr: r\n\t\t\t};\n\n\t\treturn this.createElement('circle').attr(attr);\n\t},\n\n\t/**\n\t * Draw and return an arc\n\t * @param {Number} x X position\n\t * @param {Number} y Y position\n\t * @param {Number} r Radius\n\t * @param {Number} innerR Inner radius like used in donut charts\n\t * @param {Number} start Starting angle\n\t * @param {Number} end Ending angle\n\t */\n\tarc: function (x, y, r, innerR, start, end) {\n\t\tvar arc;\n\n\t\tif (isObject(x)) {\n\t\t\ty = x.y;\n\t\t\tr = x.r;\n\t\t\tinnerR = x.innerR;\n\t\t\tstart = x.start;\n\t\t\tend = x.end;\n\t\t\tx = x.x;\n\t\t}\n\t\t\n\t\t// Arcs are defined as symbols for the ability to set\n\t\t// attributes in attr and animate\n\t\tarc = this.symbol('arc', x || 0, y || 0, r || 0, r || 0, {\n\t\t\tinnerR: innerR || 0,\n\t\t\tstart: start || 0,\n\t\t\tend: end || 0\n\t\t});\n\t\tarc.r = r; // #959\n\t\treturn arc;\n\t},\n\t\n\t/**\n\t * Draw and return a rectangle\n\t * @param {Number} x Left position\n\t * @param {Number} y Top position\n\t * @param {Number} width\n\t * @param {Number} height\n\t * @param {Number} r Border corner radius\n\t * @param {Number} strokeWidth A stroke width can be supplied to allow crisp drawing\n\t */\n\trect: function (x, y, width, height, r, strokeWidth) {\n\t\t\n\t\tr = isObject(x) ? x.r : r;\n\t\t\n\t\tvar wrapper = this.createElement('rect').attr({\n\t\t\t\trx: r,\n\t\t\t\try: r,\n\t\t\t\tfill: NONE\n\t\t\t});\n\t\treturn wrapper.attr(\n\t\t\t\tisObject(x) ? \n\t\t\t\t\tx : \n\t\t\t\t\t// do not crispify when an object is passed in (as in column charts)\n\t\t\t\t\twrapper.crisp(strokeWidth, x, y, mathMax(width, 0), mathMax(height, 0))\n\t\t\t);\n\t},\n\n\t/**\n\t * Resize the box and re-align all aligned elements\n\t * @param {Object} width\n\t * @param {Object} height\n\t * @param {Boolean} animate\n\t *\n\t */\n\tsetSize: function (width, height, animate) {\n\t\tvar renderer = this,\n\t\t\talignedObjects = renderer.alignedObjects,\n\t\t\ti = alignedObjects.length;\n\n\t\trenderer.width = width;\n\t\trenderer.height = height;\n\n\t\trenderer.boxWrapper[pick(animate, true) ? 'animate' : 'attr']({\n\t\t\twidth: width,\n\t\t\theight: height\n\t\t});\n\n\t\twhile (i--) {\n\t\t\talignedObjects[i].align();\n\t\t}\n\t},\n\n\t/**\n\t * Create a group\n\t * @param {String} name The group will be given a class name of 'highcharts-{name}'.\n\t *     This can be used for styling and scripting.\n\t */\n\tg: function (name) {\n\t\tvar elem = this.createElement('g');\n\t\treturn defined(name) ? elem.attr({ 'class': PREFIX + name }) : elem;\n\t},\n\n\t/**\n\t * Display an image\n\t * @param {String} src\n\t * @param {Number} x\n\t * @param {Number} y\n\t * @param {Number} width\n\t * @param {Number} height\n\t */\n\timage: function (src, x, y, width, height) {\n\t\tvar attribs = {\n\t\t\t\tpreserveAspectRatio: NONE\n\t\t\t},\n\t\t\telemWrapper;\n\n\t\t// optional properties\n\t\tif (arguments.length > 1) {\n\t\t\textend(attribs, {\n\t\t\t\tx: x,\n\t\t\t\ty: y,\n\t\t\t\twidth: width,\n\t\t\t\theight: height\n\t\t\t});\n\t\t}\n\n\t\telemWrapper = this.createElement('image').attr(attribs);\n\n\t\t// set the href in the xlink namespace\n\t\tif (elemWrapper.element.setAttributeNS) {\n\t\t\telemWrapper.element.setAttributeNS('http://www.w3.org/1999/xlink',\n\t\t\t\t'href', src);\n\t\t} else {\n\t\t\t// could be exporting in IE\n\t\t\t// using href throws \"not supported\" in ie7 and under, requries regex shim to fix later\n\t\t\telemWrapper.element.setAttribute('hc-svg-href', src);\n\t}\n\n\t\treturn elemWrapper;\n\t},\n\n\t/**\n\t * Draw a symbol out of pre-defined shape paths from the namespace 'symbol' object.\n\t *\n\t * @param {Object} symbol\n\t * @param {Object} x\n\t * @param {Object} y\n\t * @param {Object} radius\n\t * @param {Object} options\n\t */\n\tsymbol: function (symbol, x, y, width, height, options) {\n\n\t\tvar obj,\n\n\t\t\t// get the symbol definition function\n\t\t\tsymbolFn = this.symbols[symbol],\n\n\t\t\t// check if there's a path defined for this symbol\n\t\t\tpath = symbolFn && symbolFn(\n\t\t\t\tmathRound(x),\n\t\t\t\tmathRound(y),\n\t\t\t\twidth,\n\t\t\t\theight,\n\t\t\t\toptions\n\t\t\t),\n\n\t\t\timageElement,\n\t\t\timageRegex = /^url\\((.*?)\\)$/,\n\t\t\timageSrc,\n\t\t\timageSize,\n\t\t\tcenterImage;\n\n\t\tif (path) {\n\n\t\t\tobj = this.path(path);\n\t\t\t// expando properties for use in animate and attr\n\t\t\textend(obj, {\n\t\t\t\tsymbolName: symbol,\n\t\t\t\tx: x,\n\t\t\t\ty: y,\n\t\t\t\twidth: width,\n\t\t\t\theight: height\n\t\t\t});\n\t\t\tif (options) {\n\t\t\t\textend(obj, options);\n\t\t\t}\n\n\n\t\t// image symbols\n\t\t} else if (imageRegex.test(symbol)) {\n\n\t\t\t// On image load, set the size and position\n\t\t\tcenterImage = function (img, size) {\n\t\t\t\tif (img.element) { // it may be destroyed in the meantime (#1390)\n\t\t\t\t\timg.attr({\n\t\t\t\t\t\twidth: size[0],\n\t\t\t\t\t\theight: size[1]\n\t\t\t\t\t});\n\n\t\t\t\t\tif (!img.alignByTranslate) { // #185\n\t\t\t\t\t\timg.translate(\n\t\t\t\t\t\t\tmathRound((width - size[0]) / 2), // #1378\n\t\t\t\t\t\t\tmathRound((height - size[1]) / 2)\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\timageSrc = symbol.match(imageRegex)[1];\n\t\t\timageSize = symbolSizes[imageSrc];\n\n\t\t\t// Ireate the image synchronously, add attribs async\n\t\t\tobj = this.image(imageSrc)\n\t\t\t\t.attr({\n\t\t\t\t\tx: x,\n\t\t\t\t\ty: y\n\t\t\t\t});\n\t\t\tobj.isImg = true;\n\n\t\t\tif (imageSize) {\n\t\t\t\tcenterImage(obj, imageSize);\n\t\t\t} else {\n\t\t\t\t// Initialize image to be 0 size so export will still function if there's no cached sizes.\n\t\t\t\t// \n\t\t\t\tobj.attr({ width: 0, height: 0 });\n\n\t\t\t\t// Create a dummy JavaScript image to get the width and height. Due to a bug in IE < 8,\n\t\t\t\t// the created element must be assigned to a variable in order to load (#292).\n\t\t\t\timageElement = createElement('img', {\n\t\t\t\t\tonload: function () {\n\t\t\t\t\t\tcenterImage(obj, symbolSizes[imageSrc] = [this.width, this.height]);\n\t\t\t\t\t},\n\t\t\t\t\tsrc: imageSrc\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn obj;\n\t},\n\n\t/**\n\t * An extendable collection of functions for defining symbol paths.\n\t */\n\tsymbols: {\n\t\t'circle': function (x, y, w, h) {\n\t\t\tvar cpw = 0.166 * w;\n\t\t\treturn [\n\t\t\t\tM, x + w / 2, y,\n\t\t\t\t'C', x + w + cpw, y, x + w + cpw, y + h, x + w / 2, y + h,\n\t\t\t\t'C', x - cpw, y + h, x - cpw, y, x + w / 2, y,\n\t\t\t\t'Z'\n\t\t\t];\n\t\t},\n\n\t\t'square': function (x, y, w, h) {\n\t\t\treturn [\n\t\t\t\tM, x, y,\n\t\t\t\tL, x + w, y,\n\t\t\t\tx + w, y + h,\n\t\t\t\tx, y + h,\n\t\t\t\t'Z'\n\t\t\t];\n\t\t},\n\n\t\t'triangle': function (x, y, w, h) {\n\t\t\treturn [\n\t\t\t\tM, x + w / 2, y,\n\t\t\t\tL, x + w, y + h,\n\t\t\t\tx, y + h,\n\t\t\t\t'Z'\n\t\t\t];\n\t\t},\n\n\t\t'triangle-down': function (x, y, w, h) {\n\t\t\treturn [\n\t\t\t\tM, x, y,\n\t\t\t\tL, x + w, y,\n\t\t\t\tx + w / 2, y + h,\n\t\t\t\t'Z'\n\t\t\t];\n\t\t},\n\t\t'diamond': function (x, y, w, h) {\n\t\t\treturn [\n\t\t\t\tM, x + w / 2, y,\n\t\t\t\tL, x + w, y + h / 2,\n\t\t\t\tx + w / 2, y + h,\n\t\t\t\tx, y + h / 2,\n\t\t\t\t'Z'\n\t\t\t];\n\t\t},\n\t\t'arc': function (x, y, w, h, options) {\n\t\t\tvar start = options.start,\n\t\t\t\tradius = options.r || w || h,\n\t\t\t\tend = options.end - 0.001, // to prevent cos and sin of start and end from becoming equal on 360 arcs (related: #1561)\n\t\t\t\tinnerRadius = options.innerR,\n\t\t\t\topen = options.open,\n\t\t\t\tcosStart = mathCos(start),\n\t\t\t\tsinStart = mathSin(start),\n\t\t\t\tcosEnd = mathCos(end),\n\t\t\t\tsinEnd = mathSin(end),\n\t\t\t\tlongArc = options.end - start < mathPI ? 0 : 1;\n\n\t\t\treturn [\n\t\t\t\tM,\n\t\t\t\tx + radius * cosStart,\n\t\t\t\ty + radius * sinStart,\n\t\t\t\t'A', // arcTo\n\t\t\t\tradius, // x radius\n\t\t\t\tradius, // y radius\n\t\t\t\t0, // slanting\n\t\t\t\tlongArc, // long or short arc\n\t\t\t\t1, // clockwise\n\t\t\t\tx + radius * cosEnd,\n\t\t\t\ty + radius * sinEnd,\n\t\t\t\topen ? M : L,\n\t\t\t\tx + innerRadius * cosEnd,\n\t\t\t\ty + innerRadius * sinEnd,\n\t\t\t\t'A', // arcTo\n\t\t\t\tinnerRadius, // x radius\n\t\t\t\tinnerRadius, // y radius\n\t\t\t\t0, // slanting\n\t\t\t\tlongArc, // long or short arc\n\t\t\t\t0, // clockwise\n\t\t\t\tx + innerRadius * cosStart,\n\t\t\t\ty + innerRadius * sinStart,\n\n\t\t\t\topen ? '' : 'Z' // close\n\t\t\t];\n\t\t}\n\t},\n\n\t/**\n\t * Define a clipping rectangle\n\t * @param {String} id\n\t * @param {Number} x\n\t * @param {Number} y\n\t * @param {Number} width\n\t * @param {Number} height\n\t */\n\tclipRect: function (x, y, width, height) {\n\t\tvar wrapper,\n\t\t\tid = PREFIX + idCounter++,\n\n\t\t\tclipPath = this.createElement('clipPath').attr({\n\t\t\t\tid: id\n\t\t\t}).add(this.defs);\n\n\t\twrapper = this.rect(x, y, width, height, 0).add(clipPath);\n\t\twrapper.id = id;\n\t\twrapper.clipPath = clipPath;\n\n\t\treturn wrapper;\n\t},\n\n\n\t/**\n\t * Take a color and return it if it's a string, make it a gradient if it's a\n\t * gradient configuration object. Prior to Highstock, an array was used to define\n\t * a linear gradient with pixel positions relative to the SVG. In newer versions\n\t * we change the coordinates to apply relative to the shape, using coordinates\n\t * 0-1 within the shape. To preserve backwards compatibility, linearGradient\n\t * in this definition is an object of x1, y1, x2 and y2.\n\t *\n\t * @param {Object} color The color or config object\n\t */\n\tcolor: function (color, elem, prop) {\n\t\tvar renderer = this,\n\t\t\tcolorObject,\n\t\t\tregexRgba = /^rgba/,\n\t\t\tgradName, \n\t\t\tgradAttr,\n\t\t\tgradients,\n\t\t\tgradientObject,\n\t\t\tstops,\n\t\t\tstopColor,\n\t\t\tstopOpacity,\n\t\t\tradialReference,\n\t\t\tn,\n\t\t\tid,\n\t\t\tkey = [];\n\t\t\n\t\t// Apply linear or radial gradients\n\t\tif (color && color.linearGradient) {\n\t\t\tgradName = 'linearGradient';\n\t\t} else if (color && color.radialGradient) {\n\t\t\tgradName = 'radialGradient';\n\t\t}\n\t\t\n\t\tif (gradName) {\n\t\t\tgradAttr = color[gradName];\n\t\t\tgradients = renderer.gradients;\n\t\t\tstops = color.stops;\n\t\t\tradialReference = elem.radialReference;\n\t\t\t\n\t\t\t// Keep < 2.2 kompatibility\n\t\t\tif (isArray(gradAttr)) {\n\t\t\t\tcolor[gradName] = gradAttr = {\n\t\t\t\t\tx1: gradAttr[0],\n\t\t\t\t\ty1: gradAttr[1],\n\t\t\t\t\tx2: gradAttr[2],\n\t\t\t\t\ty2: gradAttr[3],\n\t\t\t\t\tgradientUnits: 'userSpaceOnUse'\n\t\t\t\t};\t\t\t\t\n\t\t\t}\n\t\t\t\n\t\t\t// Correct the radial gradient for the radial reference system\n\t\t\tif (gradName === 'radialGradient' && radialReference && !defined(gradAttr.gradientUnits)) {\n\t\t\t\tgradAttr = merge(gradAttr, {\n\t\t\t\t\tcx: (radialReference[0] - radialReference[2] / 2) + gradAttr.cx * radialReference[2],\n\t\t\t\t\tcy: (radialReference[1] - radialReference[2] / 2) + gradAttr.cy * radialReference[2],\n\t\t\t\t\tr: gradAttr.r * radialReference[2],\n\t\t\t\t\tgradientUnits: 'userSpaceOnUse'\n\t\t\t\t});\n\t\t\t}\n\t\t\t\n\t\t\t// Build the unique key to detect whether we need to create a new element (#1282)\n\t\t\tfor (n in gradAttr) {\n\t\t\t\tif (n !== 'id') {\n\t\t\t\t\tkey.push(n, gradAttr[n]);\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (n in stops) {\n\t\t\t\tkey.push(stops[n]);\n\t\t\t}\n\t\t\tkey = key.join(',');\n\t\t\t\n\t\t\t// Check if a gradient object with the same config object is created within this renderer\n\t\t\tif (gradients[key]) {\n\t\t\t\tid = gradients[key].id;\n\t\t\t\t\n\t\t\t} else {\n\n\t\t\t\t// Set the id and create the element\n\t\t\t\tgradAttr.id = id = PREFIX + idCounter++;\n\t\t\t\tgradients[key] = gradientObject = renderer.createElement(gradName)\n\t\t\t\t\t.attr(gradAttr)\n\t\t\t\t\t.add(renderer.defs);\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t// The gradient needs to keep a list of stops to be able to destroy them\n\t\t\t\tgradientObject.stops = [];\n\t\t\t\teach(stops, function (stop) {\n\t\t\t\t\tvar stopObject;\n\t\t\t\t\tif (regexRgba.test(stop[1])) {\n\t\t\t\t\t\tcolorObject = Color(stop[1]);\n\t\t\t\t\t\tstopColor = colorObject.get('rgb');\n\t\t\t\t\t\tstopOpacity = colorObject.get('a');\n\t\t\t\t\t} else {\n\t\t\t\t\t\tstopColor = stop[1];\n\t\t\t\t\t\tstopOpacity = 1;\n\t\t\t\t\t}\n\t\t\t\t\tstopObject = renderer.createElement('stop').attr({\n\t\t\t\t\t\toffset: stop[0],\n\t\t\t\t\t\t'stop-color': stopColor,\n\t\t\t\t\t\t'stop-opacity': stopOpacity\n\t\t\t\t\t}).add(gradientObject);\n\n\t\t\t\t\t// Add the stop element to the gradient\n\t\t\t\t\tgradientObject.stops.push(stopObject);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Return the reference to the gradient object\n\t\t\treturn 'url(' + renderer.url + '#' + id + ')';\n\t\t\t\n\t\t// Webkit and Batik can't show rgba.\n\t\t} else if (regexRgba.test(color)) {\n\t\t\tcolorObject = Color(color);\n\t\t\tattr(elem, prop + '-opacity', colorObject.get('a'));\n\n\t\t\treturn colorObject.get('rgb');\n\n\n\t\t} else {\n\t\t\t// Remove the opacity attribute added above. Does not throw if the attribute is not there.\n\t\t\telem.removeAttribute(prop + '-opacity');\n\n\t\t\treturn color;\n\t\t}\n\n\t},\n\n\n\t/**\n\t * Add text to the SVG object\n\t * @param {String} str\n\t * @param {Number} x Left position\n\t * @param {Number} y Top position\n\t * @param {Boolean} useHTML Use HTML to render the text\n\t */\n\ttext: function (str, x, y, useHTML) {\n\n\t\t// declare variables\n\t\tvar renderer = this,\n\t\t\tdefaultChartStyle = defaultOptions.chart.style,\n\t\t\tfakeSVG = useCanVG || (!hasSVG && renderer.forExport),\n\t\t\twrapper;\n\n\t\tif (useHTML && !renderer.forExport) {\n\t\t\treturn renderer.html(str, x, y);\n\t\t}\n\n\t\tx = mathRound(pick(x, 0));\n\t\ty = mathRound(pick(y, 0));\n\n\t\twrapper = renderer.createElement('text')\n\t\t\t.attr({\n\t\t\t\tx: x,\n\t\t\t\ty: y,\n\t\t\t\ttext: str\n\t\t\t})\n\t\t\t.css({\n\t\t\t\tfontFamily: defaultChartStyle.fontFamily,\n\t\t\t\tfontSize: defaultChartStyle.fontSize\n\t\t\t});\n\t\t\n\t\t// Prevent wrapping from creating false offsetWidths in export in legacy IE (#1079, #1063)\t\n\t\tif (fakeSVG) {\n\t\t\twrapper.css({\n\t\t\t\tposition: ABSOLUTE\n\t\t\t});\n\t\t}\n\n\t\twrapper.x = x;\n\t\twrapper.y = y;\n\t\treturn wrapper;\n\t},\n\n\n\t/**\n\t * Create HTML text node. This is used by the VML renderer as well as the SVG\n\t * renderer through the useHTML option.\n\t *\n\t * @param {String} str\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\thtml: function (str, x, y) {\n\t\tvar defaultChartStyle = defaultOptions.chart.style,\n\t\t\twrapper = this.createElement('span'),\n\t\t\tattrSetters = wrapper.attrSetters,\n\t\t\telement = wrapper.element,\n\t\t\trenderer = wrapper.renderer;\n\n\t\t// Text setter\n\t\tattrSetters.text = function (value) {\n\t\t\tif (value !== element.innerHTML) {\n\t\t\t\tdelete this.bBox;\n\t\t\t}\n\t\t\telement.innerHTML = value;\n\t\t\treturn false;\n\t\t};\n\n\t\t// Various setters which rely on update transform\n\t\tattrSetters.x = attrSetters.y = attrSetters.align = function (value, key) {\n\t\t\tif (key === 'align') {\n\t\t\t\tkey = 'textAlign'; // Do not overwrite the SVGElement.align method. Same as VML.\n\t\t\t}\n\t\t\twrapper[key] = value;\n\t\t\twrapper.htmlUpdateTransform();\n\t\t\treturn false;\n\t\t};\n\n\t\t// Set the default attributes\n\t\twrapper.attr({\n\t\t\t\ttext: str,\n\t\t\t\tx: mathRound(x),\n\t\t\t\ty: mathRound(y)\n\t\t\t})\n\t\t\t.css({\n\t\t\t\tposition: ABSOLUTE,\n\t\t\t\twhiteSpace: 'nowrap',\n\t\t\t\tfontFamily: defaultChartStyle.fontFamily,\n\t\t\t\tfontSize: defaultChartStyle.fontSize\n\t\t\t});\n\n\t\t// Use the HTML specific .css method\n\t\twrapper.css = wrapper.htmlCss;\n\n\t\t// This is specific for HTML within SVG\n\t\tif (renderer.isSVG) {\n\t\t\twrapper.add = function (svgGroupWrapper) {\n\n\t\t\t\tvar htmlGroup,\n\t\t\t\t\tcontainer = renderer.box.parentNode,\n\t\t\t\t\tparentGroup,\n\t\t\t\t\tparents = [];\n\n\t\t\t\t// Create a mock group to hold the HTML elements\n\t\t\t\tif (svgGroupWrapper) {\n\t\t\t\t\thtmlGroup = svgGroupWrapper.div;\n\t\t\t\t\tif (!htmlGroup) {\n\t\t\t\t\t\t\n\t\t\t\t\t\t// Read the parent chain into an array and read from top down\n\t\t\t\t\t\tparentGroup = svgGroupWrapper;\n\t\t\t\t\t\twhile (parentGroup) {\n\t\t\t\t\t\t\n\t\t\t\t\t\t\tparents.push(parentGroup);\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t// Move up to the next parent group\n\t\t\t\t\t\t\tparentGroup = parentGroup.parentGroup;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\t// Ensure dynamically updating position when any parent is translated\n\t\t\t\t\t\teach(parents.reverse(), function (parentGroup) {\n\t\t\t\t\t\t\tvar htmlGroupStyle;\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t// Create a HTML div and append it to the parent div to emulate \n\t\t\t\t\t\t\t// the SVG group structure\n\t\t\t\t\t\t\thtmlGroup = parentGroup.div = parentGroup.div || createElement(DIV, {\n\t\t\t\t\t\t\t\tclassName: attr(parentGroup.element, 'class')\n\t\t\t\t\t\t\t}, {\n\t\t\t\t\t\t\t\tposition: ABSOLUTE,\n\t\t\t\t\t\t\t\tleft: (parentGroup.translateX || 0) + PX,\n\t\t\t\t\t\t\t\ttop: (parentGroup.translateY || 0) + PX\n\t\t\t\t\t\t\t}, htmlGroup || container); // the top group is appended to container\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t// Shortcut\n\t\t\t\t\t\t\thtmlGroupStyle = htmlGroup.style;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t// Set listeners to update the HTML div's position whenever the SVG group\n\t\t\t\t\t\t\t// position is changed\n\t\t\t\t\t\t\textend(parentGroup.attrSetters, {\n\t\t\t\t\t\t\t\ttranslateX: function (value) {\n\t\t\t\t\t\t\t\t\thtmlGroupStyle.left = value + PX;\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\ttranslateY: function (value) {\n\t\t\t\t\t\t\t\t\thtmlGroupStyle.top = value + PX;\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tvisibility: function (value, key) {\n\t\t\t\t\t\t\t\t\thtmlGroupStyle[key] = value;\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}\n\t\t\t\t} else {\n\t\t\t\t\thtmlGroup = container;\n\t\t\t\t}\n\n\t\t\t\thtmlGroup.appendChild(element);\n\n\t\t\t\t// Shared with VML:\n\t\t\t\twrapper.added = true;\n\t\t\t\tif (wrapper.alignOnAdd) {\n\t\t\t\t\twrapper.htmlUpdateTransform();\n\t\t\t\t}\n\n\t\t\t\treturn wrapper;\n\t\t\t};\n\t\t}\n\t\treturn wrapper;\n\t},\n\n\t/**\n\t * Utility to return the baseline offset and total line height from the font size\n\t */\n\tfontMetrics: function (fontSize) {\n\t\tfontSize = pInt(fontSize || 11);\n\t\t\n\t\t// Empirical values found by comparing font size and bounding box height.\n\t\t// Applies to the default font family. http://jsfiddle.net/highcharts/7xvn7/\n\t\tvar lineHeight = fontSize < 24 ? fontSize + 4 : mathRound(fontSize * 1.2),\n\t\t\tbaseline = mathRound(lineHeight * 0.8);\n\t\t\n\t\treturn {\n\t\t\th: lineHeight, \n\t\t\tb: baseline\n\t\t};\n\t},\n\n\t/**\n\t * Add a label, a text item that can hold a colored or gradient background\n\t * as well as a border and shadow.\n\t * @param {string} str\n\t * @param {Number} x\n\t * @param {Number} y\n\t * @param {String} shape\n\t * @param {Number} anchorX In case the shape has a pointer, like a flag, this is the\n\t *    coordinates it should be pinned to\n\t * @param {Number} anchorY\n\t * @param {Boolean} baseline Whether to position the label relative to the text baseline,\n\t *    like renderer.text, or to the upper border of the rectangle. \n\t * @param {String} className Class name for the group \n\t */\n\tlabel: function (str, x, y, shape, anchorX, anchorY, useHTML, baseline, className) {\n\n\t\tvar renderer = this,\n\t\t\twrapper = renderer.g(className),\n\t\t\ttext = renderer.text('', 0, 0, useHTML)\n\t\t\t\t.attr({\n\t\t\t\t\tzIndex: 1\n\t\t\t\t}),\n\t\t\t\t//.add(wrapper),\n\t\t\tbox,\n\t\t\tbBox,\n\t\t\talignFactor = 0,\n\t\t\tpadding = 3,\n\t\t\tpaddingLeft = 0,\n\t\t\twidth,\n\t\t\theight,\n\t\t\twrapperX,\n\t\t\twrapperY,\n\t\t\tcrispAdjust = 0,\n\t\t\tdeferredAttr = {},\n\t\t\tbaselineOffset,\n\t\t\tattrSetters = wrapper.attrSetters,\n\t\t\tneedsBox;\n\n\t\t/**\n\t\t * This function runs after the label is added to the DOM (when the bounding box is\n\t\t * available), and after the text of the label is updated to detect the new bounding\n\t\t * box and reflect it in the border box.\n\t\t */\n\t\tfunction updateBoxSize() {\n\t\t\tvar boxX,\n\t\t\t\tboxY,\n\t\t\t\tstyle = text.element.style;\n\t\t\t\t\n\t\t\tbBox = (width === undefined || height === undefined || wrapper.styles.textAlign) &&\n\t\t\t\ttext.getBBox();\n\t\t\twrapper.width = (width || bBox.width || 0) + 2 * padding + paddingLeft;\n\t\t\twrapper.height = (height || bBox.height || 0) + 2 * padding;\n\t\t\t\n\t\t\t// update the label-scoped y offset\n\t\t\tbaselineOffset = padding + renderer.fontMetrics(style && style.fontSize).b;\n\t\t\t\t\n\t\t\tif (needsBox) {\n\t\t\t\t\n\t\t\t\t// create the border box if it is not already present\n\t\t\t\tif (!box) {\n\t\t\t\t\tboxX = mathRound(-alignFactor * padding);\n\t\t\t\t\tboxY = baseline ? -baselineOffset : 0;\n\t\t\t\t\n\t\t\t\t\twrapper.box = box = shape ?\n\t\t\t\t\t\trenderer.symbol(shape, boxX, boxY, wrapper.width, wrapper.height) :\n\t\t\t\t\t\trenderer.rect(boxX, boxY, wrapper.width, wrapper.height, 0, deferredAttr[STROKE_WIDTH]);\n\t\t\t\t\tbox.add(wrapper);\n\t\t\t\t}\n\t\n\t\t\t\t// apply the box attributes\n\t\t\t\tif (!box.isImg) { // #1630\n\t\t\t\t\tbox.attr(merge({\n\t\t\t\t\t\twidth: wrapper.width,\n\t\t\t\t\t\theight: wrapper.height\n\t\t\t\t\t}, deferredAttr));\n\t\t\t\t}\n\t\t\t\tdeferredAttr = null;\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * This function runs after setting text or padding, but only if padding is changed\n\t\t */\n\t\tfunction updateTextPadding() {\n\t\t\tvar styles = wrapper.styles,\n\t\t\t\ttextAlign = styles && styles.textAlign,\n\t\t\t\tx = paddingLeft + padding * (1 - alignFactor),\n\t\t\t\ty;\n\t\t\t\n\t\t\t// determin y based on the baseline\n\t\t\ty = baseline ? 0 : baselineOffset;\n\n\t\t\t// compensate for alignment\n\t\t\tif (defined(width) && (textAlign === 'center' || textAlign === 'right')) {\n\t\t\t\tx += { center: 0.5, right: 1 }[textAlign] * (width - bBox.width);\n\t\t\t}\n\n\t\t\t// update if anything changed\n\t\t\tif (x !== text.x || y !== text.y) {\n\t\t\t\ttext.attr({\n\t\t\t\t\tx: x,\n\t\t\t\t\ty: y\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// record current values\n\t\t\ttext.x = x;\n\t\t\ttext.y = y;\n\t\t}\n\n\t\t/**\n\t\t * Set a box attribute, or defer it if the box is not yet created\n\t\t * @param {Object} key\n\t\t * @param {Object} value\n\t\t */\n\t\tfunction boxAttr(key, value) {\n\t\t\tif (box) {\n\t\t\t\tbox.attr(key, value);\n\t\t\t} else {\n\t\t\t\tdeferredAttr[key] = value;\n\t\t\t}\n\t\t}\n\n\t\tfunction getSizeAfterAdd() {\n\t\t\ttext.add(wrapper);\n\t\t\twrapper.attr({\n\t\t\t\ttext: str, // alignment is available now\n\t\t\t\tx: x,\n\t\t\t\ty: y\n\t\t\t});\n\t\t\t\n\t\t\tif (box && defined(anchorX)) {\n\t\t\t\twrapper.attr({\n\t\t\t\t\tanchorX: anchorX,\n\t\t\t\t\tanchorY: anchorY\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * After the text element is added, get the desired size of the border box\n\t\t * and add it before the text in the DOM.\n\t\t */\n\t\taddEvent(wrapper, 'add', getSizeAfterAdd);\n\n\t\t/*\n\t\t * Add specific attribute setters.\n\t\t */\n\n\t\t// only change local variables\n\t\tattrSetters.width = function (value) {\n\t\t\twidth = value;\n\t\t\treturn false;\n\t\t};\n\t\tattrSetters.height = function (value) {\n\t\t\theight = value;\n\t\t\treturn false;\n\t\t};\n\t\tattrSetters.padding =  function (value) {\n\t\t\tif (defined(value) && value !== padding) {\n\t\t\t\tpadding = value;\n\t\t\t\tupdateTextPadding();\n\t\t\t}\n\t\t\treturn false;\n\t\t};\n\t\tattrSetters.paddingLeft =  function (value) {\n\t\t\tif (defined(value) && value !== paddingLeft) {\n\t\t\t\tpaddingLeft = value;\n\t\t\t\tupdateTextPadding();\n\t\t\t}\n\t\t\treturn false;\n\t\t};\n\t\t\n\n\t\t// change local variable and set attribue as well\n\t\tattrSetters.align = function (value) {\n\t\t\talignFactor = { left: 0, center: 0.5, right: 1 }[value];\n\t\t\treturn false; // prevent setting text-anchor on the group\n\t\t};\n\t\t\n\t\t// apply these to the box and the text alike\n\t\tattrSetters.text = function (value, key) {\n\t\t\ttext.attr(key, value);\n\t\t\tupdateBoxSize();\n\t\t\tupdateTextPadding();\n\t\t\treturn false;\n\t\t};\n\n\t\t// apply these to the box but not to the text\n\t\tattrSetters[STROKE_WIDTH] = function (value, key) {\n\t\t\tneedsBox = true;\n\t\t\tcrispAdjust = value % 2 / 2;\n\t\t\tboxAttr(key, value);\n\t\t\treturn false;\n\t\t};\n\t\tattrSetters.stroke = attrSetters.fill = attrSetters.r = function (value, key) {\n\t\t\tif (key === 'fill') {\n\t\t\t\tneedsBox = true;\n\t\t\t}\n\t\t\tboxAttr(key, value);\n\t\t\treturn false;\n\t\t};\n\t\tattrSetters.anchorX = function (value, key) {\n\t\t\tanchorX = value;\n\t\t\tboxAttr(key, value + crispAdjust - wrapperX);\n\t\t\treturn false;\n\t\t};\n\t\tattrSetters.anchorY = function (value, key) {\n\t\t\tanchorY = value;\n\t\t\tboxAttr(key, value - wrapperY);\n\t\t\treturn false;\n\t\t};\n\t\t\n\t\t// rename attributes\n\t\tattrSetters.x = function (value) {\n\t\t\twrapper.x = value; // for animation getter\n\t\t\tvalue -= alignFactor * ((width || bBox.width) + padding);\n\t\t\twrapperX = mathRound(value); \n\t\t\t\n\t\t\twrapper.attr('translateX', wrapperX);\n\t\t\treturn false;\n\t\t};\n\t\tattrSetters.y = function (value) {\n\t\t\twrapperY = wrapper.y = mathRound(value);\n\t\t\twrapper.attr('translateY', wrapperY);\n\t\t\treturn false;\n\t\t};\n\n\t\t// Redirect certain methods to either the box or the text\n\t\tvar baseCss = wrapper.css;\n\t\treturn extend(wrapper, {\n\t\t\t/**\n\t\t\t * Pick up some properties and apply them to the text instead of the wrapper\n\t\t\t */\n\t\t\tcss: function (styles) {\n\t\t\t\tif (styles) {\n\t\t\t\t\tvar textStyles = {};\n\t\t\t\t\tstyles = merge(styles); // create a copy to avoid altering the original object (#537)\n\t\t\t\t\teach(['fontSize', 'fontWeight', 'fontFamily', 'color', 'lineHeight', 'width', 'textDecoration'], function (prop) {\n\t\t\t\t\t\tif (styles[prop] !== UNDEFINED) {\n\t\t\t\t\t\t\ttextStyles[prop] = styles[prop];\n\t\t\t\t\t\t\tdelete styles[prop];\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\ttext.css(textStyles);\n\t\t\t\t}\n\t\t\t\treturn baseCss.call(wrapper, styles);\n\t\t\t},\n\t\t\t/**\n\t\t\t * Return the bounding box of the box, not the group\n\t\t\t */\n\t\t\tgetBBox: function () {\n\t\t\t\treturn {\n\t\t\t\t\twidth: bBox.width + 2 * padding,\n\t\t\t\t\theight: bBox.height + 2 * padding,\n\t\t\t\t\tx: bBox.x - padding,\n\t\t\t\t\ty: bBox.y - padding\n\t\t\t\t};\n\t\t\t},\n\t\t\t/**\n\t\t\t * Apply the shadow to the box\n\t\t\t */\n\t\t\tshadow: function (b) {\n\t\t\t\tif (box) {\n\t\t\t\t\tbox.shadow(b);\n\t\t\t\t}\n\t\t\t\treturn wrapper;\n\t\t\t},\n\t\t\t/**\n\t\t\t * Destroy and release memory.\n\t\t\t */\n\t\t\tdestroy: function () {\n\t\t\t\tremoveEvent(wrapper, 'add', getSizeAfterAdd);\n\n\t\t\t\t// Added by button implementation\n\t\t\t\tremoveEvent(wrapper.element, 'mouseenter');\n\t\t\t\tremoveEvent(wrapper.element, 'mouseleave');\n\n\t\t\t\tif (text) {\n\t\t\t\t\ttext = text.destroy();\n\t\t\t\t}\n\t\t\t\tif (box) {\n\t\t\t\t\tbox = box.destroy();\n\t\t\t\t}\n\t\t\t\t// Call base implementation to destroy the rest\n\t\t\t\tSVGElement.prototype.destroy.call(wrapper);\n\t\t\t\t\n\t\t\t\t// Release local pointers (#1298)\n\t\t\t\twrapper = renderer = updateBoxSize = updateTextPadding = boxAttr = getSizeAfterAdd = null;\n\t\t\t}\n\t\t});\n\t}\n}; // end SVGRenderer\n\n\n// general renderer\nRenderer = SVGRenderer;\n\n\n/* ****************************************************************************\n *                                                                            *\n * START OF INTERNET EXPLORER <= 8 SPECIFIC CODE                              *\n *                                                                            *\n * For applications and websites that don't need IE support, like platform    *\n * targeted mobile apps and web apps, this code can be removed.               *\n *                                                                            *\n *****************************************************************************/\n\n/**\n * @constructor\n */\nvar VMLRenderer, VMLElement;\nif (!hasSVG && !useCanVG) {\n\n/**\n * The VML element wrapper.\n */\nHighcharts.VMLElement = VMLElement = {\n\n\t/**\n\t * Initialize a new VML element wrapper. It builds the markup as a string\n\t * to minimize DOM traffic.\n\t * @param {Object} renderer\n\t * @param {Object} nodeName\n\t */\n\tinit: function (renderer, nodeName) {\n\t\tvar wrapper = this,\n\t\t\tmarkup =  ['<', nodeName, ' filled=\"f\" stroked=\"f\"'],\n\t\t\tstyle = ['position: ', ABSOLUTE, ';'],\n\t\t\tisDiv = nodeName === DIV;\n\n\t\t// divs and shapes need size\n\t\tif (nodeName === 'shape' || isDiv) {\n\t\t\tstyle.push('left:0;top:0;width:1px;height:1px;');\n\t\t}\n\t\tstyle.push('visibility: ', isDiv ? HIDDEN : VISIBLE);\n\t\t\n\t\tmarkup.push(' style=\"', style.join(''), '\"/>');\n\n\t\t// create element with default attributes and style\n\t\tif (nodeName) {\n\t\t\tmarkup = isDiv || nodeName === 'span' || nodeName === 'img' ?\n\t\t\t\tmarkup.join('')\n\t\t\t\t: renderer.prepVML(markup);\n\t\t\twrapper.element = createElement(markup);\n\t\t}\n\n\t\twrapper.renderer = renderer;\n\t\twrapper.attrSetters = {};\n\t},\n\n\t/**\n\t * Add the node to the given parent\n\t * @param {Object} parent\n\t */\n\tadd: function (parent) {\n\t\tvar wrapper = this,\n\t\t\trenderer = wrapper.renderer,\n\t\t\telement = wrapper.element,\n\t\t\tbox = renderer.box,\n\t\t\tinverted = parent && parent.inverted,\n\n\t\t\t// get the parent node\n\t\t\tparentNode = parent ?\n\t\t\t\tparent.element || parent :\n\t\t\t\tbox;\n\n\n\t\t// if the parent group is inverted, apply inversion on all children\n\t\tif (inverted) { // only on groups\n\t\t\trenderer.invertChild(element, parentNode);\n\t\t}\n\n\t\t// append it\n\t\tparentNode.appendChild(element);\n\n\t\t// align text after adding to be able to read offset\n\t\twrapper.added = true;\n\t\tif (wrapper.alignOnAdd && !wrapper.deferUpdateTransform) {\n\t\t\twrapper.updateTransform();\n\t\t}\n\t\t\n\t\t// fire an event for internal hooks\n\t\tfireEvent(wrapper, 'add');\n\n\t\treturn wrapper;\n\t},\n\n\t/**\n\t * VML always uses htmlUpdateTransform\n\t */\n\tupdateTransform: SVGElement.prototype.htmlUpdateTransform,\n\n\t/**\n\t * Set the rotation of a span with oldIE's filter\n\t */\n\tsetSpanRotation: function (rotation, sintheta, costheta) {\n\t\t// Adjust for alignment and rotation. Rotation of useHTML content is not yet implemented\n\t\t// but it can probably be implemented for Firefox 3.5+ on user request. FF3.5+\n\t\t// has support for CSS3 transform. The getBBox method also needs to be updated\n\t\t// to compensate for the rotation, like it currently does for SVG.\n\t\t// Test case: http://highcharts.com/tests/?file=text-rotation\n\t\tcss(this.element, {\n\t\t\tfilter: rotation ? ['progid:DXImageTransform.Microsoft.Matrix(M11=', costheta,\n\t\t\t\t', M12=', -sintheta, ', M21=', sintheta, ', M22=', costheta,\n\t\t\t\t', sizingMethod=\\'auto expand\\')'].join('') : NONE\n\t\t});\n\t},\n\n\t/**\n\t * Get or set attributes\n\t */\n\tattr: function (hash, val) {\n\t\tvar wrapper = this,\n\t\t\tkey,\n\t\t\tvalue,\n\t\t\ti,\n\t\t\tresult,\n\t\t\telement = wrapper.element || {},\n\t\t\telemStyle = element.style,\n\t\t\tnodeName = element.nodeName,\n\t\t\trenderer = wrapper.renderer,\n\t\t\tsymbolName = wrapper.symbolName,\n\t\t\thasSetSymbolSize,\n\t\t\tshadows = wrapper.shadows,\n\t\t\tskipAttr,\n\t\t\tattrSetters = wrapper.attrSetters,\n\t\t\tret = wrapper;\n\n\t\t// single key-value pair\n\t\tif (isString(hash) && defined(val)) {\n\t\t\tkey = hash;\n\t\t\thash = {};\n\t\t\thash[key] = val;\n\t\t}\n\n\t\t// used as a getter, val is undefined\n\t\tif (isString(hash)) {\n\t\t\tkey = hash;\n\t\t\tif (key === 'strokeWidth' || key === 'stroke-width') {\n\t\t\t\tret = wrapper.strokeweight;\n\t\t\t} else {\n\t\t\t\tret = wrapper[key];\n\t\t\t}\n\n\t\t// setter\n\t\t} else {\n\t\t\tfor (key in hash) {\n\t\t\t\tvalue = hash[key];\n\t\t\t\tskipAttr = false;\n\n\t\t\t\t// check for a specific attribute setter\n\t\t\t\tresult = attrSetters[key] && attrSetters[key].call(wrapper, value, key);\n\n\t\t\t\tif (result !== false && value !== null) { // #620\n\n\t\t\t\t\tif (result !== UNDEFINED) {\n\t\t\t\t\t\tvalue = result; // the attribute setter has returned a new value to set\n\t\t\t\t\t}\n\n\n\t\t\t\t\t// prepare paths\n\t\t\t\t\t// symbols\n\t\t\t\t\tif (symbolName && /^(x|y|r|start|end|width|height|innerR|anchorX|anchorY)/.test(key)) {\n\t\t\t\t\t\t// if one of the symbol size affecting parameters are changed,\n\t\t\t\t\t\t// check all the others only once for each call to an element's\n\t\t\t\t\t\t// .attr() method\n\t\t\t\t\t\tif (!hasSetSymbolSize) {\n\t\t\t\t\t\t\twrapper.symbolAttr(hash);\n\n\t\t\t\t\t\t\thasSetSymbolSize = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tskipAttr = true;\n\n\t\t\t\t\t} else if (key === 'd') {\n\t\t\t\t\t\tvalue = value || [];\n\t\t\t\t\t\twrapper.d = value.join(' '); // used in getter for animation\n\n\t\t\t\t\t\t// convert paths\n\t\t\t\t\t\ti = value.length;\n\t\t\t\t\t\tvar convertedPath = [],\n\t\t\t\t\t\t\tclockwise;\n\t\t\t\t\t\twhile (i--) {\n\n\t\t\t\t\t\t\t// Multiply by 10 to allow subpixel precision.\n\t\t\t\t\t\t\t// Substracting half a pixel seems to make the coordinates\n\t\t\t\t\t\t\t// align with SVG, but this hasn't been tested thoroughly\n\t\t\t\t\t\t\tif (isNumber(value[i])) {\n\t\t\t\t\t\t\t\tconvertedPath[i] = mathRound(value[i] * 10) - 5;\n\t\t\t\t\t\t\t} else if (value[i] === 'Z') { // close the path\n\t\t\t\t\t\t\t\tconvertedPath[i] = 'x';\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tconvertedPath[i] = value[i];\n\n\t\t\t\t\t\t\t\t// When the start X and end X coordinates of an arc are too close,\n\t\t\t\t\t\t\t\t// they are rounded to the same value above. In this case, substract 1 from the end X\n\t\t\t\t\t\t\t\t// position. #760, #1371. \n\t\t\t\t\t\t\t\tif (value.isArc && (value[i] === 'wa' || value[i] === 'at')) {\n\t\t\t\t\t\t\t\t\tclockwise = value[i] === 'wa' ? 1 : -1; // #1642\n\t\t\t\t\t\t\t\t\tif (convertedPath[i + 5] === convertedPath[i + 7]) {\n\t\t\t\t\t\t\t\t\t\tconvertedPath[i + 7] -= clockwise;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t// Start and end Y (#1410)\n\t\t\t\t\t\t\t\t\tif (convertedPath[i + 6] === convertedPath[i + 8]) {\n\t\t\t\t\t\t\t\t\t\tconvertedPath[i + 8] -= clockwise;\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\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvalue = convertedPath.join(' ') || 'x';\n\t\t\t\t\t\telement.path = value;\n\n\t\t\t\t\t\t// update shadows\n\t\t\t\t\t\tif (shadows) {\n\t\t\t\t\t\t\ti = shadows.length;\n\t\t\t\t\t\t\twhile (i--) {\n\t\t\t\t\t\t\t\tshadows[i].path = shadows[i].cutOff ? this.cutOffPath(value, shadows[i].cutOff) : value;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tskipAttr = true;\n\n\t\t\t\t\t// handle visibility\n\t\t\t\t\t} else if (key === 'visibility') {\n\n\t\t\t\t\t\t// let the shadow follow the main element\n\t\t\t\t\t\tif (shadows) {\n\t\t\t\t\t\t\ti = shadows.length;\n\t\t\t\t\t\t\twhile (i--) {\n\t\t\t\t\t\t\t\tshadows[i].style[key] = value;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\t// Instead of toggling the visibility CSS property, move the div out of the viewport. \n\t\t\t\t\t\t// This works around #61 and #586\t\t\t\t\t\t\t\n\t\t\t\t\t\tif (nodeName === 'DIV') {\n\t\t\t\t\t\t\tvalue = value === HIDDEN ? '-999em' : 0;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t// In order to redraw, IE7 needs the div to be visible when tucked away\n\t\t\t\t\t\t\t// outside the viewport. So the visibility is actually opposite of \n\t\t\t\t\t\t\t// the expected value. This applies to the tooltip only. \n\t\t\t\t\t\t\tif (!docMode8) {\n\t\t\t\t\t\t\t\telemStyle[key] = value ? VISIBLE : HIDDEN;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tkey = 'top';\n\t\t\t\t\t\t}\n\t\t\t\t\t\telemStyle[key] = value;\t\n\t\t\t\t\t\tskipAttr = true;\n\n\t\t\t\t\t// directly mapped to css\n\t\t\t\t\t} else if (key === 'zIndex') {\n\n\t\t\t\t\t\tif (value) {\n\t\t\t\t\t\t\telemStyle[key] = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tskipAttr = true;\n\n\t\t\t\t\t// x, y, width, height\n\t\t\t\t\t} else if (inArray(key, ['x', 'y', 'width', 'height']) !== -1) {\n\t\t\t\t\t\t\n\t\t\t\t\t\twrapper[key] = value; // used in getter\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (key === 'x' || key === 'y') {\n\t\t\t\t\t\t\tkey = { x: 'left', y: 'top' }[key];\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tvalue = mathMax(0, value); // don't set width or height below zero (#311)\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\t// clipping rectangle special\n\t\t\t\t\t\tif (wrapper.updateClipping) {\n\t\t\t\t\t\t\twrapper[key] = value; // the key is now 'left' or 'top' for 'x' and 'y'\n\t\t\t\t\t\t\twrapper.updateClipping();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// normal\n\t\t\t\t\t\t\telemStyle[key] = value;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tskipAttr = true;\t\t\t\t\t\t\n\n\t\t\t\t\t// class name\n\t\t\t\t\t} else if (key === 'class' && nodeName === 'DIV') {\n\t\t\t\t\t\t// IE8 Standards mode has problems retrieving the className\n\t\t\t\t\t\telement.className = value;\t\t\t\t\t\t\n\n\t\t\t\t\t// stroke\n\t\t\t\t\t} else if (key === 'stroke') {\n\n\t\t\t\t\t\tvalue = renderer.color(value, element, key);\n\n\t\t\t\t\t\tkey = 'strokecolor';\n\n\t\t\t\t\t// stroke width\n\t\t\t\t\t} else if (key === 'stroke-width' || key === 'strokeWidth') {\n\t\t\t\t\t\telement.stroked = value ? true : false;\n\t\t\t\t\t\tkey = 'strokeweight';\n\t\t\t\t\t\twrapper[key] = value; // used in getter, issue #113\n\t\t\t\t\t\tif (isNumber(value)) {\n\t\t\t\t\t\t\tvalue += PX;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t// dashStyle\n\t\t\t\t\t} else if (key === 'dashstyle') {\n\t\t\t\t\t\tvar strokeElem = element.getElementsByTagName('stroke')[0] ||\n\t\t\t\t\t\t\tcreateElement(renderer.prepVML(['<stroke/>']), null, null, element);\n\t\t\t\t\t\tstrokeElem[key] = value || 'solid';\n\t\t\t\t\t\twrapper.dashstyle = value; /* because changing stroke-width will change the dash length\n\t\t\t\t\t\t\tand cause an epileptic effect */\n\t\t\t\t\t\tskipAttr = true;\n\n\t\t\t\t\t// fill\n\t\t\t\t\t} else if (key === 'fill') {\n\n\t\t\t\t\t\tif (nodeName === 'SPAN') { // text color\n\t\t\t\t\t\t\telemStyle.color = value;\n\t\t\t\t\t\t} else if (nodeName !== 'IMG') { // #1336\n\t\t\t\t\t\t\telement.filled = value !== NONE ? true : false;\n\n\t\t\t\t\t\t\tvalue = renderer.color(value, element, key, wrapper);\n\n\t\t\t\t\t\t\tkey = 'fillcolor';\n\t\t\t\t\t\t}\n\n\t\t\t\t\t// opacity: don't bother - animation is too slow and filters introduce artifacts\n\t\t\t\t\t} else if (key === 'opacity') {\n\t\t\t\t\t\t/*css(element, {\n\t\t\t\t\t\t\topacity: value\n\t\t\t\t\t\t});*/\n\t\t\t\t\t\tskipAttr = true;\n\t\t\t\t\t\t\n\t\t\t\t\t// rotation on VML elements\n\t\t\t\t\t} else if (nodeName === 'shape' && key === 'rotation') {\n\t\t\t\t\t\t\n\t\t\t\t\t\twrapper[key] = element.style[key] = value; // style is for #1873\n\n\t\t\t\t\t\t// Correction for the 1x1 size of the shape container. Used in gauge needles.\n\t\t\t\t\t\telement.style.left = -mathRound(mathSin(value * deg2rad) + 1) + PX;\n\t\t\t\t\t\telement.style.top = mathRound(mathCos(value * deg2rad)) + PX;\n\n\t\t\t\t\t// translation for animation\n\t\t\t\t\t} else if (key === 'translateX' || key === 'translateY' || key === 'rotation') {\n\t\t\t\t\t\twrapper[key] = value;\n\t\t\t\t\t\twrapper.updateTransform();\n\n\t\t\t\t\t\tskipAttr = true;\n\n\t\t\t\t\t// text for rotated and non-rotated elements\n\t\t\t\t\t} else if (key === 'text') {\n\t\t\t\t\t\tthis.bBox = null;\n\t\t\t\t\t\telement.innerHTML = value;\n\t\t\t\t\t\tskipAttr = true;\n\t\t\t\t\t} \n\n\n\t\t\t\t\tif (!skipAttr) {\n\t\t\t\t\t\tif (docMode8) { // IE8 setAttribute bug\n\t\t\t\t\t\t\telement[key] = value;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tattr(element, key, value);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn ret;\n\t},\n\n\t/**\n\t * Set the element's clipping to a predefined rectangle\n\t *\n\t * @param {String} id The id of the clip rectangle\n\t */\n\tclip: function (clipRect) {\n\t\tvar wrapper = this,\n\t\t\tclipMembers,\n\t\t\tcssRet;\n\n\t\tif (clipRect) {\n\t\t\tclipMembers = clipRect.members;\n\t\t\terase(clipMembers, wrapper); // Ensure unique list of elements (#1258)\n\t\t\tclipMembers.push(wrapper);\n\t\t\twrapper.destroyClip = function () {\n\t\t\t\terase(clipMembers, wrapper);\n\t\t\t};\n\t\t\tcssRet = clipRect.getCSS(wrapper);\n\t\t\t\n\t\t} else {\n\t\t\tif (wrapper.destroyClip) {\n\t\t\t\twrapper.destroyClip();\n\t\t\t}\n\t\t\tcssRet = { clip: docMode8 ? 'inherit' : 'rect(auto)' }; // #1214\n\t\t}\n\t\t\n\t\treturn wrapper.css(cssRet);\n\t\t\t\n\t},\n\n\t/**\n\t * Set styles for the element\n\t * @param {Object} styles\n\t */\n\tcss: SVGElement.prototype.htmlCss,\n\n\t/**\n\t * Removes a child either by removeChild or move to garbageBin.\n\t * Issue 490; in VML removeChild results in Orphaned nodes according to sIEve, discardElement does not.\n\t */\n\tsafeRemoveChild: function (element) {\n\t\t// discardElement will detach the node from its parent before attaching it\n\t\t// to the garbage bin. Therefore it is important that the node is attached and have parent.\n\t\tif (element.parentNode) {\n\t\t\tdiscardElement(element);\n\t\t}\n\t},\n\n\t/**\n\t * Extend element.destroy by removing it from the clip members array\n\t */\n\tdestroy: function () {\n\t\tif (this.destroyClip) {\n\t\t\tthis.destroyClip();\n\t\t}\n\n\t\treturn SVGElement.prototype.destroy.apply(this);\n\t},\n\n\t/**\n\t * Add an event listener. VML override for normalizing event parameters.\n\t * @param {String} eventType\n\t * @param {Function} handler\n\t */\n\ton: function (eventType, handler) {\n\t\t// simplest possible event model for internal use\n\t\tthis.element['on' + eventType] = function () {\n\t\t\tvar evt = win.event;\n\t\t\tevt.target = evt.srcElement;\n\t\t\thandler(evt);\n\t\t};\n\t\treturn this;\n\t},\n\t\n\t/**\n\t * In stacked columns, cut off the shadows so that they don't overlap\n\t */\n\tcutOffPath: function (path, length) {\n\t\t\n\t\tvar len;\n\t\t\n\t\tpath = path.split(/[ ,]/);\n\t\tlen = path.length;\n\t\t\n\t\tif (len === 9 || len === 11) {\n\t\t\tpath[len - 4] = path[len - 2] = pInt(path[len - 2]) - 10 * length;\n\t\t}\n\t\treturn path.join(' ');\t\t\n\t},\n\n\t/**\n\t * Apply a drop shadow by copying elements and giving them different strokes\n\t * @param {Boolean|Object} shadowOptions\n\t */\n\tshadow: function (shadowOptions, group, cutOff) {\n\t\tvar shadows = [],\n\t\t\ti,\n\t\t\telement = this.element,\n\t\t\trenderer = this.renderer,\n\t\t\tshadow,\n\t\t\telemStyle = element.style,\n\t\t\tmarkup,\n\t\t\tpath = element.path,\n\t\t\tstrokeWidth,\n\t\t\tmodifiedPath,\n\t\t\tshadowWidth,\n\t\t\tshadowElementOpacity;\n\n\t\t// some times empty paths are not strings\n\t\tif (path && typeof path.value !== 'string') {\n\t\t\tpath = 'x';\n\t\t}\n\t\tmodifiedPath = path;\n\n\t\tif (shadowOptions) {\n\t\t\tshadowWidth = pick(shadowOptions.width, 3);\n\t\t\tshadowElementOpacity = (shadowOptions.opacity || 0.15) / shadowWidth;\n\t\t\tfor (i = 1; i <= 3; i++) {\n\t\t\t\t\n\t\t\t\tstrokeWidth = (shadowWidth * 2) + 1 - (2 * i);\n\t\t\t\t\n\t\t\t\t// Cut off shadows for stacked column items\n\t\t\t\tif (cutOff) {\n\t\t\t\t\tmodifiedPath = this.cutOffPath(path.value, strokeWidth + 0.5);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tmarkup = ['<shape isShadow=\"true\" strokeweight=\"', strokeWidth,\n\t\t\t\t\t'\" filled=\"false\" path=\"', modifiedPath,\n\t\t\t\t\t'\" coordsize=\"10 10\" style=\"', element.style.cssText, '\" />'];\n\t\t\t\t\n\t\t\t\tshadow = createElement(renderer.prepVML(markup),\n\t\t\t\t\tnull, {\n\t\t\t\t\t\tleft: pInt(elemStyle.left) + pick(shadowOptions.offsetX, 1),\n\t\t\t\t\t\ttop: pInt(elemStyle.top) + pick(shadowOptions.offsetY, 1)\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t\tif (cutOff) {\n\t\t\t\t\tshadow.cutOff = strokeWidth + 1;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// apply the opacity\n\t\t\t\tmarkup = ['<stroke color=\"', shadowOptions.color || 'black', '\" opacity=\"', shadowElementOpacity * i, '\"/>'];\n\t\t\t\tcreateElement(renderer.prepVML(markup), null, null, shadow);\n\n\n\t\t\t\t// insert it\n\t\t\t\tif (group) {\n\t\t\t\t\tgroup.element.appendChild(shadow);\n\t\t\t\t} else {\n\t\t\t\t\telement.parentNode.insertBefore(shadow, element);\n\t\t\t\t}\n\n\t\t\t\t// record it\n\t\t\t\tshadows.push(shadow);\n\n\t\t\t}\n\n\t\t\tthis.shadows = shadows;\n\t\t}\n\t\treturn this;\n\n\t}\n};\nVMLElement = extendClass(SVGElement, VMLElement);\n\n/**\n * The VML renderer\n */\nvar VMLRendererExtension = { // inherit SVGRenderer\n\n\tElement: VMLElement,\n\tisIE8: userAgent.indexOf('MSIE 8.0') > -1,\n\n\n\t/**\n\t * Initialize the VMLRenderer\n\t * @param {Object} container\n\t * @param {Number} width\n\t * @param {Number} height\n\t */\n\tinit: function (container, width, height) {\n\t\tvar renderer = this,\n\t\t\tboxWrapper,\n\t\t\tbox;\n\n\t\trenderer.alignedObjects = [];\n\n\t\tboxWrapper = renderer.createElement(DIV);\n\t\tbox = boxWrapper.element;\n\t\tbox.style.position = RELATIVE; // for freeform drawing using renderer directly\n\t\tcontainer.appendChild(boxWrapper.element);\n\n\n\t\t// generate the containing box\n\t\trenderer.isVML = true;\n\t\trenderer.box = box;\n\t\trenderer.boxWrapper = boxWrapper;\n\n\n\t\trenderer.setSize(width, height, false);\n\n\t\t// The only way to make IE6 and IE7 print is to use a global namespace. However,\n\t\t// with IE8 the only way to make the dynamic shapes visible in screen and print mode\n\t\t// seems to be to add the xmlns attribute and the behaviour style inline.\n\t\tif (!doc.namespaces.hcv) {\n\n\t\t\tdoc.namespaces.add('hcv', 'urn:schemas-microsoft-com:vml');\n\n\t\t\t// setup default css\n\t\t\tdoc.createStyleSheet().cssText =\n\t\t\t\t'hcv\\\\:fill, hcv\\\\:path, hcv\\\\:shape, hcv\\\\:stroke' +\n\t\t\t\t'{ behavior:url(#default#VML); display: inline-block; } ';\n\n\t\t}\n\t},\n\t\n\t\n\t/**\n\t * Detect whether the renderer is hidden. This happens when one of the parent elements\n\t * has display: none\n\t */\n\tisHidden: function () {\n\t\treturn !this.box.offsetWidth;\t\t\t\n\t},\n\n\t/**\n\t * Define a clipping rectangle. In VML it is accomplished by storing the values\n\t * for setting the CSS style to all associated members.\n\t *\n\t * @param {Number} x\n\t * @param {Number} y\n\t * @param {Number} width\n\t * @param {Number} height\n\t */\n\tclipRect: function (x, y, width, height) {\n\n\t\t// create a dummy element\n\t\tvar clipRect = this.createElement(),\n\t\t\tisObj = isObject(x);\n\t\t\n\t\t// mimic a rectangle with its style object for automatic updating in attr\n\t\treturn extend(clipRect, {\n\t\t\tmembers: [],\n\t\t\tleft: isObj ? x.x : x,\n\t\t\ttop: isObj ? x.y : y,\n\t\t\twidth: isObj ? x.width : width,\n\t\t\theight: isObj ? x.height : height,\n\t\t\tgetCSS: function (wrapper) {\n\t\t\t\tvar element = wrapper.element,\n\t\t\t\t\tnodeName = element.nodeName,\n\t\t\t\t\tisShape = nodeName === 'shape',\n\t\t\t\t\tinverted = wrapper.inverted,\n\t\t\t\t\trect = this,\n\t\t\t\t\ttop = rect.top - (isShape ? element.offsetTop : 0),\n\t\t\t\t\tleft = rect.left,\n\t\t\t\t\tright = left + rect.width,\n\t\t\t\t\tbottom = top + rect.height,\n\t\t\t\t\tret = {\n\t\t\t\t\t\tclip: 'rect(' +\n\t\t\t\t\t\t\tmathRound(inverted ? left : top) + 'px,' +\n\t\t\t\t\t\t\tmathRound(inverted ? bottom : right) + 'px,' +\n\t\t\t\t\t\t\tmathRound(inverted ? right : bottom) + 'px,' +\n\t\t\t\t\t\t\tmathRound(inverted ? top : left) + 'px)'\n\t\t\t\t\t};\n\n\t\t\t\t// issue 74 workaround\n\t\t\t\tif (!inverted && docMode8 && nodeName === 'DIV') {\n\t\t\t\t\textend(ret, {\n\t\t\t\t\t\twidth: right + PX,\n\t\t\t\t\t\theight: bottom + PX\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn ret;\n\t\t\t},\n\n\t\t\t// used in attr and animation to update the clipping of all members\n\t\t\tupdateClipping: function () {\n\t\t\t\teach(clipRect.members, function (member) {\n\t\t\t\t\tmember.css(clipRect.getCSS(member));\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\n\t},\n\n\n\t/**\n\t * Take a color and return it if it's a string, make it a gradient if it's a\n\t * gradient configuration object, and apply opacity.\n\t *\n\t * @param {Object} color The color or config object\n\t */\n\tcolor: function (color, elem, prop, wrapper) {\n\t\tvar renderer = this,\n\t\t\tcolorObject,\n\t\t\tregexRgba = /^rgba/,\n\t\t\tmarkup,\n\t\t\tfillType,\n\t\t\tret = NONE;\n\n\t\t// Check for linear or radial gradient\n\t\tif (color && color.linearGradient) {\n\t\t\tfillType = 'gradient';\n\t\t} else if (color && color.radialGradient) {\n\t\t\tfillType = 'pattern';\n\t\t}\n\t\t\n\t\t\n\t\tif (fillType) {\n\n\t\t\tvar stopColor,\n\t\t\t\tstopOpacity,\n\t\t\t\tgradient = color.linearGradient || color.radialGradient,\n\t\t\t\tx1,\n\t\t\t\ty1, \n\t\t\t\tx2,\n\t\t\t\ty2,\n\t\t\t\topacity1,\n\t\t\t\topacity2,\n\t\t\t\tcolor1,\n\t\t\t\tcolor2,\n\t\t\t\tfillAttr = '',\n\t\t\t\tstops = color.stops,\n\t\t\t\tfirstStop,\n\t\t\t\tlastStop,\n\t\t\t\tcolors = [],\n\t\t\t\taddFillNode = function () {\n\t\t\t\t\t// Add the fill subnode. When colors attribute is used, the meanings of opacity and o:opacity2\n\t\t\t\t\t// are reversed.\n\t\t\t\t\tmarkup = ['<fill colors=\"' + colors.join(',') + '\" opacity=\"', opacity2, '\" o:opacity2=\"', opacity1,\n\t\t\t\t\t\t'\" type=\"', fillType, '\" ', fillAttr, 'focus=\"100%\" method=\"any\" />'];\n\t\t\t\t\tcreateElement(renderer.prepVML(markup), null, null, elem);\n\t\t\t\t};\n\t\t\t\n\t\t\t// Extend from 0 to 1\n\t\t\tfirstStop = stops[0];\n\t\t\tlastStop = stops[stops.length - 1];\n\t\t\tif (firstStop[0] > 0) {\n\t\t\t\tstops.unshift([\n\t\t\t\t\t0,\n\t\t\t\t\tfirstStop[1]\n\t\t\t\t]);\n\t\t\t}\n\t\t\tif (lastStop[0] < 1) {\n\t\t\t\tstops.push([\n\t\t\t\t\t1,\n\t\t\t\t\tlastStop[1]\n\t\t\t\t]);\n\t\t\t}\n\n\t\t\t// Compute the stops\n\t\t\teach(stops, function (stop, i) {\n\t\t\t\tif (regexRgba.test(stop[1])) {\n\t\t\t\t\tcolorObject = Color(stop[1]);\n\t\t\t\t\tstopColor = colorObject.get('rgb');\n\t\t\t\t\tstopOpacity = colorObject.get('a');\n\t\t\t\t} else {\n\t\t\t\t\tstopColor = stop[1];\n\t\t\t\t\tstopOpacity = 1;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// Build the color attribute\n\t\t\t\tcolors.push((stop[0] * 100) + '% ' + stopColor); \n\n\t\t\t\t// Only start and end opacities are allowed, so we use the first and the last\n\t\t\t\tif (!i) {\n\t\t\t\t\topacity1 = stopOpacity;\n\t\t\t\t\tcolor2 = stopColor;\n\t\t\t\t} else {\n\t\t\t\t\topacity2 = stopOpacity;\n\t\t\t\t\tcolor1 = stopColor;\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t\t// Apply the gradient to fills only.\n\t\t\tif (prop === 'fill') {\n\t\t\t\t\n\t\t\t\t// Handle linear gradient angle\n\t\t\t\tif (fillType === 'gradient') {\n\t\t\t\t\tx1 = gradient.x1 || gradient[0] || 0;\n\t\t\t\t\ty1 = gradient.y1 || gradient[1] || 0;\n\t\t\t\t\tx2 = gradient.x2 || gradient[2] || 0;\n\t\t\t\t\ty2 = gradient.y2 || gradient[3] || 0;\n\t\t\t\t\tfillAttr = 'angle=\"' + (90  - math.atan(\n\t\t\t\t\t\t(y2 - y1) / // y vector\n\t\t\t\t\t\t(x2 - x1) // x vector\n\t\t\t\t\t\t) * 180 / mathPI) + '\"';\n\t\t\t\t\t\t\n\t\t\t\t\taddFillNode();\n\t\t\t\t\t\n\t\t\t\t// Radial (circular) gradient\n\t\t\t\t} else { \n\t\t\t\t\t\n\t\t\t\t\tvar r = gradient.r,\n\t\t\t\t\t\tsizex = r * 2,\n\t\t\t\t\t\tsizey = r * 2,\n\t\t\t\t\t\tcx = gradient.cx,\n\t\t\t\t\t\tcy = gradient.cy,\n\t\t\t\t\t\tradialReference = elem.radialReference,\n\t\t\t\t\t\tbBox,\n\t\t\t\t\t\tapplyRadialGradient = function () {\n\t\t\t\t\t\t\tif (radialReference) {\n\t\t\t\t\t\t\t\tbBox = wrapper.getBBox();\n\t\t\t\t\t\t\t\tcx += (radialReference[0] - bBox.x) / bBox.width - 0.5;\n\t\t\t\t\t\t\t\tcy += (radialReference[1] - bBox.y) / bBox.height - 0.5;\n\t\t\t\t\t\t\t\tsizex *= radialReference[2] / bBox.width;\n\t\t\t\t\t\t\t\tsizey *= radialReference[2] / bBox.height;\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tfillAttr = 'src=\"' + defaultOptions.global.VMLRadialGradientURL + '\" ' +\n\t\t\t\t\t\t\t\t'size=\"' + sizex + ',' + sizey + '\" ' +\n\t\t\t\t\t\t\t\t'origin=\"0.5,0.5\" ' +\n\t\t\t\t\t\t\t\t'position=\"' + cx + ',' + cy + '\" ' +\n\t\t\t\t\t\t\t\t'color2=\"' + color2 + '\" ';\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\taddFillNode();\n\t\t\t\t\t\t};\n\t\t\t\t\t\n\t\t\t\t\t// Apply radial gradient\n\t\t\t\t\tif (wrapper.added) {\n\t\t\t\t\t\tapplyRadialGradient();\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// We need to know the bounding box to get the size and position right\n\t\t\t\t\t\taddEvent(wrapper, 'add', applyRadialGradient);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t// The fill element's color attribute is broken in IE8 standards mode, so we\n\t\t\t\t\t// need to set the parent shape's fillcolor attribute instead.\n\t\t\t\t\tret = color1;\n\t\t\t\t}\n\t\t\t\n\t\t\t// Gradients are not supported for VML stroke, return the first color. #722.\n\t\t\t} else {\n\t\t\t\tret = stopColor;\n\t\t\t}\n\n\t\t// if the color is an rgba color, split it and add a fill node\n\t\t// to hold the opacity component\n\t\t} else if (regexRgba.test(color) && elem.tagName !== 'IMG') {\n\n\t\t\tcolorObject = Color(color);\n\n\t\t\tmarkup = ['<', prop, ' opacity=\"', colorObject.get('a'), '\"/>'];\n\t\t\tcreateElement(this.prepVML(markup), null, null, elem);\n\n\t\t\tret = colorObject.get('rgb');\n\n\n\t\t} else {\n\t\t\tvar propNodes = elem.getElementsByTagName(prop); // 'stroke' or 'fill' node\n\t\t\tif (propNodes.length) {\n\t\t\t\tpropNodes[0].opacity = 1;\n\t\t\t\tpropNodes[0].type = 'solid';\n\t\t\t}\n\t\t\tret = color;\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\t/**\n\t * Take a VML string and prepare it for either IE8 or IE6/IE7.\n\t * @param {Array} markup A string array of the VML markup to prepare\n\t */\n\tprepVML: function (markup) {\n\t\tvar vmlStyle = 'display:inline-block;behavior:url(#default#VML);',\n\t\t\tisIE8 = this.isIE8;\n\n\t\tmarkup = markup.join('');\n\n\t\tif (isIE8) { // add xmlns and style inline\n\t\t\tmarkup = markup.replace('/>', ' xmlns=\"urn:schemas-microsoft-com:vml\" />');\n\t\t\tif (markup.indexOf('style=\"') === -1) {\n\t\t\t\tmarkup = markup.replace('/>', ' style=\"' + vmlStyle + '\" />');\n\t\t\t} else {\n\t\t\t\tmarkup = markup.replace('style=\"', 'style=\"' + vmlStyle);\n\t\t\t}\n\n\t\t} else { // add namespace\n\t\t\tmarkup = markup.replace('<', '<hcv:');\n\t\t}\n\n\t\treturn markup;\n\t},\n\n\t/**\n\t * Create rotated and aligned text\n\t * @param {String} str\n\t * @param {Number} x\n\t * @param {Number} y\n\t */\n\ttext: SVGRenderer.prototype.html,\n\n\t/**\n\t * Create and return a path element\n\t * @param {Array} path\n\t */\n\tpath: function (path) {\n\t\tvar attr = {\n\t\t\t// subpixel precision down to 0.1 (width and height = 1px)\n\t\t\tcoordsize: '10 10'\n\t\t};\n\t\tif (isArray(path)) {\n\t\t\tattr.d = path;\n\t\t} else if (isObject(path)) { // attributes\n\t\t\textend(attr, path);\n\t\t}\n\t\t// create the shape\n\t\treturn this.createElement('shape').attr(attr);\n\t},\n\n\t/**\n\t * Create and return a circle element. In VML circles are implemented as\n\t * shapes, which is faster than v:oval\n\t * @param {Number} x\n\t * @param {Number} y\n\t * @param {Number} r\n\t */\n\tcircle: function (x, y, r) {\n\t\tvar circle = this.symbol('circle');\n\t\tif (isObject(x)) {\n\t\t\tr = x.r;\n\t\t\ty = x.y;\n\t\t\tx = x.x;\n\t\t}\n\t\tcircle.isCircle = true; // Causes x and y to mean center (#1682)\n\t\treturn circle.attr({ x: x, y: y, width: 2 * r, height: 2 * r });\n\t},\n\n\t/**\n\t * Create a group using an outer div and an inner v:group to allow rotating\n\t * and flipping. A simple v:group would have problems with positioning\n\t * child HTML elements and CSS clip.\n\t *\n\t * @param {String} name The name of the group\n\t */\n\tg: function (name) {\n\t\tvar wrapper,\n\t\t\tattribs;\n\n\t\t// set the class name\n\t\tif (name) {\n\t\t\tattribs = { 'className': PREFIX + name, 'class': PREFIX + name };\n\t\t}\n\n\t\t// the div to hold HTML and clipping\n\t\twrapper = this.createElement(DIV).attr(attribs);\n\n\t\treturn wrapper;\n\t},\n\n\t/**\n\t * VML override to create a regular HTML image\n\t * @param {String} src\n\t * @param {Number} x\n\t * @param {Number} y\n\t * @param {Number} width\n\t * @param {Number} height\n\t */\n\timage: function (src, x, y, width, height) {\n\t\tvar obj = this.createElement('img')\n\t\t\t.attr({ src: src });\n\n\t\tif (arguments.length > 1) {\n\t\t\tobj.attr({\n\t\t\t\tx: x,\n\t\t\t\ty: y,\n\t\t\t\twidth: width,\n\t\t\t\theight: height\n\t\t\t});\n\t\t}\n\t\treturn obj;\n\t},\n\n\t/**\n\t * VML uses a shape for rect to overcome bugs and rotation problems\n\t */\n\trect: function (x, y, width, height, r, strokeWidth) {\n\n\t\tif (isObject(x)) {\n\t\t\ty = x.y;\n\t\t\twidth = x.width;\n\t\t\theight = x.height;\n\t\t\tstrokeWidth = x.strokeWidth;\n\t\t\tx = x.x;\n\t\t}\n\t\tvar wrapper = this.symbol('rect');\n\t\twrapper.r = r;\n\n\t\treturn wrapper.attr(wrapper.crisp(strokeWidth, x, y, mathMax(width, 0), mathMax(height, 0)));\n\t},\n\n\t/**\n\t * In the VML renderer, each child of an inverted div (group) is inverted\n\t * @param {Object} element\n\t * @param {Object} parentNode\n\t */\n\tinvertChild: function (element, parentNode) {\n\t\tvar parentStyle = parentNode.style;\n\t\tcss(element, {\n\t\t\tflip: 'x',\n\t\t\tleft: pInt(parentStyle.width) - 1,\n\t\t\ttop: pInt(parentStyle.height) - 1,\n\t\t\trotation: -90\n\t\t});\n\t},\n\n\t/**\n\t * Symbol definitions that override the parent SVG renderer's symbols\n\t *\n\t */\n\tsymbols: {\n\t\t// VML specific arc function\n\t\tarc: function (x, y, w, h, options) {\n\t\t\tvar start = options.start,\n\t\t\t\tend = options.end,\n\t\t\t\tradius = options.r || w || h,\n\t\t\t\tinnerRadius = options.innerR,\n\t\t\t\tcosStart = mathCos(start),\n\t\t\t\tsinStart = mathSin(start),\n\t\t\t\tcosEnd = mathCos(end),\n\t\t\t\tsinEnd = mathSin(end),\n\t\t\t\tret;\n\n\t\t\tif (end - start === 0) { // no angle, don't show it.\n\t\t\t\treturn ['x'];\n\t\t\t}\n\n\t\t\tret = [\n\t\t\t\t'wa', // clockwise arc to\n\t\t\t\tx - radius, // left\n\t\t\t\ty - radius, // top\n\t\t\t\tx + radius, // right\n\t\t\t\ty + radius, // bottom\n\t\t\t\tx + radius * cosStart, // start x\n\t\t\t\ty + radius * sinStart, // start y\n\t\t\t\tx + radius * cosEnd, // end x\n\t\t\t\ty + radius * sinEnd  // end y\n\t\t\t];\n\n\t\t\tif (options.open && !innerRadius) {\n\t\t\t\tret.push(\n\t\t\t\t\t'e',\n\t\t\t\t\tM, \n\t\t\t\t\tx,// - innerRadius, \n\t\t\t\t\ty// - innerRadius\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tret.push(\n\t\t\t\t'at', // anti clockwise arc to\n\t\t\t\tx - innerRadius, // left\n\t\t\t\ty - innerRadius, // top\n\t\t\t\tx + innerRadius, // right\n\t\t\t\ty + innerRadius, // bottom\n\t\t\t\tx + innerRadius * cosEnd, // start x\n\t\t\t\ty + innerRadius * sinEnd, // start y\n\t\t\t\tx + innerRadius * cosStart, // end x\n\t\t\t\ty + innerRadius * sinStart, // end y\n\t\t\t\t'x', // finish path\n\t\t\t\t'e' // close\n\t\t\t);\n\t\t\t\n\t\t\tret.isArc = true;\n\t\t\treturn ret;\n\n\t\t},\n\t\t// Add circle symbol path. This performs significantly faster than v:oval.\n\t\tcircle: function (x, y, w, h, wrapper) {\n\t\t\t// Center correction, #1682\n\t\t\tif (wrapper && wrapper.isCircle) {\n\t\t\t\tx -= w / 2;\n\t\t\t\ty -= h / 2;\n\t\t\t}\n\n\t\t\t// Return the path\n\t\t\treturn [\n\t\t\t\t'wa', // clockwisearcto\n\t\t\t\tx, // left\n\t\t\t\ty, // top\n\t\t\t\tx + w, // right\n\t\t\t\ty + h, // bottom\n\t\t\t\tx + w, // start x\n\t\t\t\ty + h / 2,     // start y\n\t\t\t\tx + w, // end x\n\t\t\t\ty + h / 2,     // end y\n\t\t\t\t//'x', // finish path\n\t\t\t\t'e' // close\n\t\t\t];\n\t\t},\n\t\t/**\n\t\t * Add rectangle symbol path which eases rotation and omits arcsize problems\n\t\t * compared to the built-in VML roundrect shape\n\t\t *\n\t\t * @param {Number} left Left position\n\t\t * @param {Number} top Top position\n\t\t * @param {Number} r Border radius\n\t\t * @param {Object} options Width and height\n\t\t */\n\n\t\trect: function (left, top, width, height, options) {\n\t\t\t\n\t\t\tvar right = left + width,\n\t\t\t\tbottom = top + height,\n\t\t\t\tret,\n\t\t\t\tr;\n\n\t\t\t// No radius, return the more lightweight square\n\t\t\tif (!defined(options) || !options.r) {\n\t\t\t\tret = SVGRenderer.prototype.symbols.square.apply(0, arguments);\n\t\t\t\t\n\t\t\t// Has radius add arcs for the corners\n\t\t\t} else {\n\t\t\t\n\t\t\t\tr = mathMin(options.r, width, height);\n\t\t\t\tret = [\n\t\t\t\t\tM,\n\t\t\t\t\tleft + r, top,\n\t\n\t\t\t\t\tL,\n\t\t\t\t\tright - r, top,\n\t\t\t\t\t'wa',\n\t\t\t\t\tright - 2 * r, top,\n\t\t\t\t\tright, top + 2 * r,\n\t\t\t\t\tright - r, top,\n\t\t\t\t\tright, top + r,\n\t\n\t\t\t\t\tL,\n\t\t\t\t\tright, bottom - r,\n\t\t\t\t\t'wa',\n\t\t\t\t\tright - 2 * r, bottom - 2 * r,\n\t\t\t\t\tright, bottom,\n\t\t\t\t\tright, bottom - r,\n\t\t\t\t\tright - r, bottom,\n\t\n\t\t\t\t\tL,\n\t\t\t\t\tleft + r, bottom,\n\t\t\t\t\t'wa',\n\t\t\t\t\tleft, bottom - 2 * r,\n\t\t\t\t\tleft + 2 * r, bottom,\n\t\t\t\t\tleft + r, bottom,\n\t\t\t\t\tleft, bottom - r,\n\t\n\t\t\t\t\tL,\n\t\t\t\t\tleft, top + r,\n\t\t\t\t\t'wa',\n\t\t\t\t\tleft, top,\n\t\t\t\t\tleft + 2 * r, top + 2 * r,\n\t\t\t\t\tleft, top + r,\n\t\t\t\t\tleft + r, top,\n\t\n\t\n\t\t\t\t\t'x',\n\t\t\t\t\t'e'\n\t\t\t\t];\n\t\t\t}\n\t\t\treturn ret;\n\t\t}\n\t}\n};\nHighcharts.VMLRenderer = VMLRenderer = function () {\n\tthis.init.apply(this, arguments);\n};\nVMLRenderer.prototype = merge(SVGRenderer.prototype, VMLRendererExtension);\n\n\t// general renderer\n\tRenderer = VMLRenderer;\n}\n\n/* ****************************************************************************\n *                                                                            *\n * END OF INTERNET EXPLORER <= 8 SPECIFIC CODE                                *\n *                                                                            *\n *****************************************************************************/\n/* ****************************************************************************\n *                                                                            *\n * START OF ANDROID < 3 SPECIFIC CODE. THIS CAN BE REMOVED IF YOU'RE NOT      *\n * TARGETING THAT SYSTEM.                                                     *\n *                                                                            *\n *****************************************************************************/\nvar CanVGRenderer,\n\tCanVGController;\n\nif (useCanVG) {\n\t/**\n\t * The CanVGRenderer is empty from start to keep the source footprint small.\n\t * When requested, the CanVGController downloads the rest of the source packaged\n\t * together with the canvg library.\n\t */\n\tHighcharts.CanVGRenderer = CanVGRenderer = function () {\n\t\t// Override the global SVG namespace to fake SVG/HTML that accepts CSS\n\t\tSVG_NS = 'http://www.w3.org/1999/xhtml';\n\t};\n\n\t/**\n\t * Start with an empty symbols object. This is needed when exporting is used (exporting.src.js will add a few symbols), but \n\t * the implementation from SvgRenderer will not be merged in until first render.\n\t */\n\tCanVGRenderer.prototype.symbols = {};\n\n\t/**\n\t * Handles on demand download of canvg rendering support.\n\t */\n\tCanVGController = (function () {\n\t\t// List of renderering calls\n\t\tvar deferredRenderCalls = [];\n\n\t\t/**\n\t\t * When downloaded, we are ready to draw deferred charts.\n\t\t */\n\t\tfunction drawDeferred() {\n\t\t\tvar callLength = deferredRenderCalls.length,\n\t\t\t\tcallIndex;\n\n\t\t\t// Draw all pending render calls\n\t\t\tfor (callIndex = 0; callIndex < callLength; callIndex++) {\n\t\t\t\tdeferredRenderCalls[callIndex]();\n\t\t\t}\n\t\t\t// Clear the list\n\t\t\tdeferredRenderCalls = [];\n\t\t}\n\n\t\treturn {\n\t\t\tpush: function (func, scriptLocation) {\n\t\t\t\t// Only get the script once\n\t\t\t\tif (deferredRenderCalls.length === 0) {\n\t\t\t\t\tgetScript(scriptLocation, drawDeferred);\n\t\t\t\t}\n\t\t\t\t// Register render call\n\t\t\t\tdeferredRenderCalls.push(func);\n\t\t\t}\n\t\t};\n\t}());\n\n\tRenderer = CanVGRenderer;\n} // end CanVGRenderer\n\n/* ****************************************************************************\n *                                                                            *\n * END OF ANDROID < 3 SPECIFIC CODE                                           *\n *                                                                            *\n *****************************************************************************/\n\n/**\n * The Tick class\n */\nfunction Tick(axis, pos, type, noLabel) {\n\tthis.axis = axis;\n\tthis.pos = pos;\n\tthis.type = type || '';\n\tthis.isNew = true;\n\n\tif (!type && !noLabel) {\n\t\tthis.addLabel();\n\t}\n}\n\nTick.prototype = {\n\t/**\n\t * Write the tick label\n\t */\n\taddLabel: function () {\n\t\tvar tick = this,\n\t\t\taxis = tick.axis,\n\t\t\toptions = axis.options,\n\t\t\tchart = axis.chart,\n\t\t\thoriz = axis.horiz,\n\t\t\tcategories = axis.categories,\n\t\t\tnames = axis.series[0] && axis.series[0].names,\n\t\t\tpos = tick.pos,\n\t\t\tlabelOptions = options.labels,\n\t\t\tstr,\n\t\t\ttickPositions = axis.tickPositions,\n\t\t\twidth = (horiz && categories &&\n\t\t\t\t!labelOptions.step && !labelOptions.staggerLines &&\n\t\t\t\t!labelOptions.rotation &&\n\t\t\t\tchart.plotWidth / tickPositions.length) ||\n\t\t\t\t(!horiz && (chart.optionsMarginLeft || chart.chartWidth * 0.33)), // #1580, #1931\n\t\t\tisFirst = pos === tickPositions[0],\n\t\t\tisLast = pos === tickPositions[tickPositions.length - 1],\n\t\t\tcss,\n\t\t\tattr,\n\t\t\tvalue = categories ?\n\t\t\t\tpick(categories[pos], names && names[pos], pos) : \n\t\t\t\tpos,\n\t\t\tlabel = tick.label,\n\t\t\ttickPositionInfo = tickPositions.info,\n\t\t\tdateTimeLabelFormat;\n\n\t\t// Set the datetime label format. If a higher rank is set for this position, use that. If not,\n\t\t// use the general format.\n\t\tif (axis.isDatetimeAxis && tickPositionInfo) {\n\t\t\tdateTimeLabelFormat = options.dateTimeLabelFormats[tickPositionInfo.higherRanks[pos] || tickPositionInfo.unitName];\n\t\t}\n\n\t\t// set properties for access in render method\n\t\ttick.isFirst = isFirst;\n\t\ttick.isLast = isLast;\n\n\t\t// get the string\n\t\tstr = axis.labelFormatter.call({\n\t\t\taxis: axis,\n\t\t\tchart: chart,\n\t\t\tisFirst: isFirst,\n\t\t\tisLast: isLast,\n\t\t\tdateTimeLabelFormat: dateTimeLabelFormat,\n\t\t\tvalue: axis.isLog ? correctFloat(lin2log(value)) : value\n\t\t});\n\n\t\t// prepare CSS\n\t\tcss = width && { width: mathMax(1, mathRound(width - 2 * (labelOptions.padding || 10))) + PX };\n\t\tcss = extend(css, labelOptions.style);\n\n\t\t// first call\n\t\tif (!defined(label)) {\n\t\t\tattr = {\n\t\t\t\talign: axis.labelAlign\n\t\t\t};\n\t\t\tif (isNumber(labelOptions.rotation)) {\n\t\t\t\tattr.rotation = labelOptions.rotation;\n\t\t\t}\t\t\t\n\t\t\ttick.label =\n\t\t\t\tdefined(str) && labelOptions.enabled ?\n\t\t\t\t\tchart.renderer.text(\n\t\t\t\t\t\t\tstr,\n\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\tlabelOptions.useHTML\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.attr(attr)\n\t\t\t\t\t\t// without position absolute, IE export sometimes is wrong\n\t\t\t\t\t\t.css(css)\n\t\t\t\t\t\t.add(axis.labelGroup) :\n\t\t\t\t\tnull;\n\n\t\t// update\n\t\t} else if (label) {\n\t\t\tlabel.attr({\n\t\t\t\t\ttext: str\n\t\t\t\t})\n\t\t\t\t.css(css);\n\t\t}\n\t},\n\n\t/**\n\t * Get the offset height or width of the label\n\t */\n\tgetLabelSize: function () {\n\t\tvar label = this.label,\n\t\t\taxis = this.axis;\n\t\treturn label ?\n\t\t\t((this.labelBBox = label.getBBox()))[axis.horiz ? 'height' : 'width'] :\n\t\t\t0;\n\t},\n\n\t/**\n\t * Find how far the labels extend to the right and left of the tick's x position. Used for anti-collision\n\t * detection with overflow logic.\n\t */\n\tgetLabelSides: function () {\n\t\tvar bBox = this.labelBBox, // assume getLabelSize has run at this point\n\t\t\taxis = this.axis,\n\t\t\toptions = axis.options,\n\t\t\tlabelOptions = options.labels,\n\t\t\twidth = bBox.width,\n\t\t\tleftSide = width * { left: 0, center: 0.5, right: 1 }[axis.labelAlign] - labelOptions.x;\n\n\t\treturn [-leftSide, width - leftSide];\n\t},\n\n\t/**\n\t * Handle the label overflow by adjusting the labels to the left and right edge, or\n\t * hide them if they collide into the neighbour label.\n\t */\n\thandleOverflow: function (index, xy) {\n\t\tvar show = true,\n\t\t\taxis = this.axis,\n\t\t\tchart = axis.chart,\n\t\t\tisFirst = this.isFirst,\n\t\t\tisLast = this.isLast,\n\t\t\tx = xy.x,\n\t\t\treversed = axis.reversed,\n\t\t\ttickPositions = axis.tickPositions;\n\n\t\tif (isFirst || isLast) {\n\n\t\t\tvar sides = this.getLabelSides(),\n\t\t\t\tleftSide = sides[0],\n\t\t\t\trightSide = sides[1],\n\t\t\t\tplotLeft = chart.plotLeft,\n\t\t\t\tplotRight = plotLeft + axis.len,\n\t\t\t\tneighbour = axis.ticks[tickPositions[index + (isFirst ? 1 : -1)]],\n\t\t\t\tneighbourEdge = neighbour && neighbour.label.xy && neighbour.label.xy.x + neighbour.getLabelSides()[isFirst ? 0 : 1];\n\n\t\t\tif ((isFirst && !reversed) || (isLast && reversed)) {\n\t\t\t\t// Is the label spilling out to the left of the plot area?\n\t\t\t\tif (x + leftSide < plotLeft) {\n\n\t\t\t\t\t// Align it to plot left\n\t\t\t\t\tx = plotLeft - leftSide;\n\n\t\t\t\t\t// Hide it if it now overlaps the neighbour label\n\t\t\t\t\tif (neighbour && x + rightSide > neighbourEdge) {\n\t\t\t\t\t\tshow = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\t// Is the label spilling out to the right of the plot area?\n\t\t\t\tif (x + rightSide > plotRight) {\n\n\t\t\t\t\t// Align it to plot right\n\t\t\t\t\tx = plotRight - rightSide;\n\n\t\t\t\t\t// Hide it if it now overlaps the neighbour label\n\t\t\t\t\tif (neighbour && x + leftSide < neighbourEdge) {\n\t\t\t\t\t\tshow = false;\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the modified x position of the label\n\t\t\txy.x = x;\n\t\t}\n\t\treturn show;\n\t},\n\n\t/**\n\t * Get the x and y position for ticks and labels\n\t */\n\tgetPosition: function (horiz, pos, tickmarkOffset, old) {\n\t\tvar axis = this.axis,\n\t\t\tchart = axis.chart,\n\t\t\tcHeight = (old && chart.oldChartHeight) || chart.chartHeight;\n\t\t\n\t\treturn {\n\t\t\tx: horiz ?\n\t\t\t\taxis.translate(pos + tickmarkOffset, null, null, old) + axis.transB :\n\t\t\t\taxis.left + axis.offset + (axis.opposite ? ((old && chart.oldChartWidth) || chart.chartWidth) - axis.right - axis.left : 0),\n\n\t\t\ty: horiz ?\n\t\t\t\tcHeight - axis.bottom + axis.offset - (axis.opposite ? axis.height : 0) :\n\t\t\t\tcHeight - axis.translate(pos + tickmarkOffset, null, null, old) - axis.transB\n\t\t};\n\t\t\n\t},\n\t\n\t/**\n\t * Get the x, y position of the tick label\n\t */\n\tgetLabelPosition: function (x, y, label, horiz, labelOptions, tickmarkOffset, index, step) {\n\t\tvar axis = this.axis,\n\t\t\ttransA = axis.transA,\n\t\t\treversed = axis.reversed,\n\t\t\tstaggerLines = axis.staggerLines,\n\t\t\tbaseline = axis.chart.renderer.fontMetrics(labelOptions.style.fontSize).b,\n\t\t\trotation = labelOptions.rotation;\n\t\t\t\n\t\tx = x + labelOptions.x - (tickmarkOffset && horiz ?\n\t\t\ttickmarkOffset * transA * (reversed ? -1 : 1) : 0);\n\t\ty = y + labelOptions.y - (tickmarkOffset && !horiz ?\n\t\t\ttickmarkOffset * transA * (reversed ? 1 : -1) : 0);\n\n\t\t// Correct for rotation (#1764)\n\t\tif (rotation && axis.side === 2) {\n\t\t\ty -= baseline - baseline * mathCos(rotation * deg2rad);\n\t\t}\n\t\t\n\t\t// Vertically centered\n\t\tif (!defined(labelOptions.y) && !rotation) { // #1951\n\t\t\ty += baseline - label.getBBox().height / 2;\n\t\t}\n\t\t\n\t\t// Correct for staggered labels\n\t\tif (staggerLines) {\n\t\t\ty += (index / (step || 1) % staggerLines) * (axis.labelOffset / staggerLines);\n\t\t}\n\t\t\n\t\treturn {\n\t\t\tx: x,\n\t\t\ty: y\n\t\t};\n\t},\n\t\n\t/**\n\t * Extendible method to return the path of the marker\n\t */\n\tgetMarkPath: function (x, y, tickLength, tickWidth, horiz, renderer) {\n\t\treturn renderer.crispLine([\n\t\t\t\tM,\n\t\t\t\tx,\n\t\t\t\ty,\n\t\t\t\tL,\n\t\t\t\tx + (horiz ? 0 : -tickLength),\n\t\t\t\ty + (horiz ? tickLength : 0)\n\t\t\t], tickWidth);\n\t},\n\n\t/**\n\t * Put everything in place\n\t *\n\t * @param index {Number}\n\t * @param old {Boolean} Use old coordinates to prepare an animation into new position\n\t */\n\trender: function (index, old, opacity) {\n\t\tvar tick = this,\n\t\t\taxis = tick.axis,\n\t\t\toptions = axis.options,\n\t\t\tchart = axis.chart,\n\t\t\trenderer = chart.renderer,\n\t\t\thoriz = axis.horiz,\n\t\t\ttype = tick.type,\n\t\t\tlabel = tick.label,\n\t\t\tpos = tick.pos,\n\t\t\tlabelOptions = options.labels,\n\t\t\tgridLine = tick.gridLine,\n\t\t\tgridPrefix = type ? type + 'Grid' : 'grid',\n\t\t\ttickPrefix = type ? type + 'Tick' : 'tick',\n\t\t\tgridLineWidth = options[gridPrefix + 'LineWidth'],\n\t\t\tgridLineColor = options[gridPrefix + 'LineColor'],\n\t\t\tdashStyle = options[gridPrefix + 'LineDashStyle'],\n\t\t\ttickLength = options[tickPrefix + 'Length'],\n\t\t\ttickWidth = options[tickPrefix + 'Width'] || 0,\n\t\t\ttickColor = options[tickPrefix + 'Color'],\n\t\t\ttickPosition = options[tickPrefix + 'Position'],\n\t\t\tgridLinePath,\n\t\t\tmark = tick.mark,\n\t\t\tmarkPath,\n\t\t\tstep = labelOptions.step,\n\t\t\tattribs,\n\t\t\tshow = true,\n\t\t\ttickmarkOffset = axis.tickmarkOffset,\n\t\t\txy = tick.getPosition(horiz, pos, tickmarkOffset, old),\n\t\t\tx = xy.x,\n\t\t\ty = xy.y,\n\t\t\treverseCrisp = ((horiz && x === axis.pos) || (!horiz && y === axis.pos + axis.len)) ? -1 : 1, // #1480\n\t\t\tstaggerLines = axis.staggerLines;\n\n\t\tthis.isActive = true;\n\t\t\n\t\t// create the grid line\n\t\tif (gridLineWidth) {\n\t\t\tgridLinePath = axis.getPlotLinePath(pos + tickmarkOffset, gridLineWidth * reverseCrisp, old, true);\n\n\t\t\tif (gridLine === UNDEFINED) {\n\t\t\t\tattribs = {\n\t\t\t\t\tstroke: gridLineColor,\n\t\t\t\t\t'stroke-width': gridLineWidth\n\t\t\t\t};\n\t\t\t\tif (dashStyle) {\n\t\t\t\t\tattribs.dashstyle = dashStyle;\n\t\t\t\t}\n\t\t\t\tif (!type) {\n\t\t\t\t\tattribs.zIndex = 1;\n\t\t\t\t}\n\t\t\t\tif (old) {\n\t\t\t\t\tattribs.opacity = 0;\n\t\t\t\t}\n\t\t\t\ttick.gridLine = gridLine =\n\t\t\t\t\tgridLineWidth ?\n\t\t\t\t\t\trenderer.path(gridLinePath)\n\t\t\t\t\t\t\t.attr(attribs).add(axis.gridGroup) :\n\t\t\t\t\t\tnull;\n\t\t\t}\n\n\t\t\t// If the parameter 'old' is set, the current call will be followed\n\t\t\t// by another call, therefore do not do any animations this time\n\t\t\tif (!old && gridLine && gridLinePath) {\n\t\t\t\tgridLine[tick.isNew ? 'attr' : 'animate']({\n\t\t\t\t\td: gridLinePath,\n\t\t\t\t\topacity: opacity\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t// create the tick mark\n\t\tif (tickWidth && tickLength) {\n\n\t\t\t// negate the length\n\t\t\tif (tickPosition === 'inside') {\n\t\t\t\ttickLength = -tickLength;\n\t\t\t}\n\t\t\tif (axis.opposite) {\n\t\t\t\ttickLength = -tickLength;\n\t\t\t}\n\n\t\t\tmarkPath = tick.getMarkPath(x, y, tickLength, tickWidth * reverseCrisp, horiz, renderer);\n\n\t\t\tif (mark) { // updating\n\t\t\t\tmark.animate({\n\t\t\t\t\td: markPath,\n\t\t\t\t\topacity: opacity\n\t\t\t\t});\n\t\t\t} else { // first time\n\t\t\t\ttick.mark = renderer.path(\n\t\t\t\t\tmarkPath\n\t\t\t\t).attr({\n\t\t\t\t\tstroke: tickColor,\n\t\t\t\t\t'stroke-width': tickWidth,\n\t\t\t\t\topacity: opacity\n\t\t\t\t}).add(axis.axisGroup);\n\t\t\t}\n\t\t}\n\n\t\t// the label is created on init - now move it into place\n\t\tif (label && !isNaN(x)) {\n\t\t\tlabel.xy = xy = tick.getLabelPosition(x, y, label, horiz, labelOptions, tickmarkOffset, index, step);\n\n\t\t\t// apply show first and show last\n\t\t\tif ((tick.isFirst && !pick(options.showFirstLabel, 1)) ||\n\t\t\t\t\t(tick.isLast && !pick(options.showLastLabel, 1))) {\n\t\t\t\tshow = false;\n\n\t\t\t// Handle label overflow and show or hide accordingly\n\t\t\t} else if (!staggerLines && horiz && labelOptions.overflow === 'justify' && !tick.handleOverflow(index, xy)) {\n\t\t\t\tshow = false;\n\t\t\t}\n\n\t\t\t// apply step\n\t\t\tif (step && index % step) {\n\t\t\t\t// show those indices dividable by step\n\t\t\t\tshow = false;\n\t\t\t}\n\n\t\t\t// Set the new position, and show or hide\n\t\t\tif (show && !isNaN(xy.y)) {\n\t\t\t\txy.opacity = opacity;\n\t\t\t\tlabel[tick.isNew ? 'attr' : 'animate'](xy);\n\t\t\t\ttick.isNew = false;\n\t\t\t} else {\n\t\t\t\tlabel.attr('y', -9999); // #1338\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Destructor for the tick prototype\n\t */\n\tdestroy: function () {\n\t\tdestroyObjectProperties(this, this.axis);\n\t}\n};\n\n/**\n * The object wrapper for plot lines and plot bands\n * @param {Object} options\n */\nfunction PlotLineOrBand(axis, options) {\n\tthis.axis = axis;\n\n\tif (options) {\n\t\tthis.options = options;\n\t\tthis.id = options.id;\n\t}\n}\n\nPlotLineOrBand.prototype = {\n\t\n\t/**\n\t * Render the plot line or plot band. If it is already existing,\n\t * move it.\n\t */\n\trender: function () {\n\t\tvar plotLine = this,\n\t\t\taxis = plotLine.axis,\n\t\t\thoriz = axis.horiz,\n\t\t\thalfPointRange = (axis.pointRange || 0) / 2,\n\t\t\toptions = plotLine.options,\n\t\t\toptionsLabel = options.label,\n\t\t\tlabel = plotLine.label,\n\t\t\twidth = options.width,\n\t\t\tto = options.to,\n\t\t\tfrom = options.from,\n\t\t\tisBand = defined(from) && defined(to),\n\t\t\tvalue = options.value,\n\t\t\tdashStyle = options.dashStyle,\n\t\t\tsvgElem = plotLine.svgElem,\n\t\t\tpath = [],\n\t\t\taddEvent,\n\t\t\teventType,\n\t\t\txs,\n\t\t\tys,\n\t\t\tx,\n\t\t\ty,\n\t\t\tcolor = options.color,\n\t\t\tzIndex = options.zIndex,\n\t\t\tevents = options.events,\n\t\t\tattribs,\n\t\t\trenderer = axis.chart.renderer;\n\n\t\t// logarithmic conversion\n\t\tif (axis.isLog) {\n\t\t\tfrom = log2lin(from);\n\t\t\tto = log2lin(to);\n\t\t\tvalue = log2lin(value);\n\t\t}\n\n\t\t// plot line\n\t\tif (width) {\n\t\t\tpath = axis.getPlotLinePath(value, width);\n\t\t\tattribs = {\n\t\t\t\tstroke: color,\n\t\t\t\t'stroke-width': width\n\t\t\t};\n\t\t\tif (dashStyle) {\n\t\t\t\tattribs.dashstyle = dashStyle;\n\t\t\t}\n\t\t} else if (isBand) { // plot band\n\t\t\t\n\t\t\t// keep within plot area\n\t\t\tfrom = mathMax(from, axis.min - halfPointRange);\n\t\t\tto = mathMin(to, axis.max + halfPointRange);\n\t\t\t\n\t\t\tpath = axis.getPlotBandPath(from, to, options);\n\t\t\tattribs = {\n\t\t\t\tfill: color\n\t\t\t};\n\t\t\tif (options.borderWidth) {\n\t\t\t\tattribs.stroke = options.borderColor;\n\t\t\t\tattribs['stroke-width'] = options.borderWidth;\n\t\t\t}\n\t\t} else {\n\t\t\treturn;\n\t\t}\n\t\t// zIndex\n\t\tif (defined(zIndex)) {\n\t\t\tattribs.zIndex = zIndex;\n\t\t}\n\n\t\t// common for lines and bands\n\t\tif (svgElem) {\n\t\t\tif (path) {\n\t\t\t\tsvgElem.animate({\n\t\t\t\t\td: path\n\t\t\t\t}, null, svgElem.onGetPath);\n\t\t\t} else {\n\t\t\t\tsvgElem.hide();\n\t\t\t\tsvgElem.onGetPath = function () {\n\t\t\t\t\tsvgElem.show();\n\t\t\t\t};\n\t\t\t}\n\t\t} else if (path && path.length) {\n\t\t\tplotLine.svgElem = svgElem = renderer.path(path)\n\t\t\t\t.attr(attribs).add();\n\n\t\t\t// events\n\t\t\tif (events) {\n\t\t\t\taddEvent = function (eventType) {\n\t\t\t\t\tsvgElem.on(eventType, function (e) {\n\t\t\t\t\t\tevents[eventType].apply(plotLine, [e]);\n\t\t\t\t\t});\n\t\t\t\t};\n\t\t\t\tfor (eventType in events) {\n\t\t\t\t\taddEvent(eventType);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// the plot band/line label\n\t\tif (optionsLabel && defined(optionsLabel.text) && path && path.length && axis.width > 0 && axis.height > 0) {\n\t\t\t// apply defaults\n\t\t\toptionsLabel = merge({\n\t\t\t\talign: horiz && isBand && 'center',\n\t\t\t\tx: horiz ? !isBand && 4 : 10,\n\t\t\t\tverticalAlign : !horiz && isBand && 'middle',\n\t\t\t\ty: horiz ? isBand ? 16 : 10 : isBand ? 6 : -4,\n\t\t\t\trotation: horiz && !isBand && 90\n\t\t\t}, optionsLabel);\n\n\t\t\t// add the SVG element\n\t\t\tif (!label) {\n\t\t\t\tplotLine.label = label = renderer.text(\n\t\t\t\t\t\toptionsLabel.text,\n\t\t\t\t\t\t0,\n\t\t\t\t\t\t0,\n\t\t\t\t\t\toptionsLabel.useHTML // docs: useHTML for plotLines and plotBands\n\t\t\t\t\t)\n\t\t\t\t\t.attr({\n\t\t\t\t\t\talign: optionsLabel.textAlign || optionsLabel.align,\n\t\t\t\t\t\trotation: optionsLabel.rotation,\n\t\t\t\t\t\tzIndex: zIndex\n\t\t\t\t\t})\n\t\t\t\t\t.css(optionsLabel.style)\n\t\t\t\t\t.add();\n\t\t\t}\n\n\t\t\t// get the bounding box and align the label\n\t\t\txs = [path[1], path[4], pick(path[6], path[1])];\n\t\t\tys = [path[2], path[5], pick(path[7], path[2])];\n\t\t\tx = arrayMin(xs);\n\t\t\ty = arrayMin(ys);\n\n\t\t\tlabel.align(optionsLabel, false, {\n\t\t\t\tx: x,\n\t\t\t\ty: y,\n\t\t\t\twidth: arrayMax(xs) - x,\n\t\t\t\theight: arrayMax(ys) - y\n\t\t\t});\n\t\t\tlabel.show();\n\n\t\t} else if (label) { // move out of sight\n\t\t\tlabel.hide();\n\t\t}\n\n\t\t// chainable\n\t\treturn plotLine;\n\t},\n\n\t/**\n\t * Remove the plot line or band\n\t */\n\tdestroy: function () {\n\t\tvar plotLine = this,\n\t\t\taxis = plotLine.axis;\n\n\t\t// remove it from the lookup\n\t\terase(axis.plotLinesAndBands, plotLine);\n\n\t\tdestroyObjectProperties(plotLine, this.axis);\n\t}\n};\n/**\n * The class for stack items\n */\nfunction StackItem(axis, options, isNegative, x, stackOption, stacking) {\n\t\n\tvar inverted = axis.chart.inverted;\n\n\tthis.axis = axis;\n\n\t// Tells if the stack is negative\n\tthis.isNegative = isNegative;\n\n\t// Save the options to be able to style the label\n\tthis.options = options;\n\n\t// Save the x value to be able to position the label later\n\tthis.x = x;\n\n\t// Initialize total value\n\tthis.total = 0;\n\n\t// This will keep each points' extremes stored by series.index\n\tthis.points = {};\n\n\t// Save the stack option on the series configuration object, and whether to treat it as percent\n\tthis.stack = stackOption;\n\tthis.percent = stacking === 'percent';\n\n\t// The align options and text align varies on whether the stack is negative and\n\t// if the chart is inverted or not.\n\t// First test the user supplied value, then use the dynamic.\n\tthis.alignOptions = {\n\t\talign: options.align || (inverted ? (isNegative ? 'left' : 'right') : 'center'),\n\t\tverticalAlign: options.verticalAlign || (inverted ? 'middle' : (isNegative ? 'bottom' : 'top')),\n\t\ty: pick(options.y, inverted ? 4 : (isNegative ? 14 : -6)),\n\t\tx: pick(options.x, inverted ? (isNegative ? -6 : 6) : 0)\n\t};\n\n\tthis.textAlign = options.textAlign || (inverted ? (isNegative ? 'right' : 'left') : 'center');\n}\n\nStackItem.prototype = {\n\tdestroy: function () {\n\t\tdestroyObjectProperties(this, this.axis);\n\t},\n\n\t/**\n\t * Sets the total of this stack. Should be called when a serie is hidden or shown\n\t * since that will affect the total of other stacks.\n\t */\n\tsetTotal: function (total) {\n\t\tthis.total = total;\n\t\tthis.cum = total;\n\t},\n\n\t/**\n\t * Adds value to stack total, this method takes care of correcting floats\n\t */\n\taddValue: function (y) {\n\t\tthis.setTotal(correctFloat(this.total + y));\n\t},\n\n\t/**\n\t * Renders the stack total label and adds it to the stack label group.\n\t */\n\trender: function (group) {\n\t\tvar options = this.options,\n\t\t\tformatOption = options.format,\n\t\t\tstr = formatOption ?\n\t\t\t\tformat(formatOption, this) : \n\t\t\t\toptions.formatter.call(this);  // format the text in the label\n\n\t\t// Change the text to reflect the new total and set visibility to hidden in case the serie is hidden\n\t\tif (this.label) {\n\t\t\tthis.label.attr({text: str, visibility: HIDDEN});\n\t\t// Create new label\n\t\t} else {\n\t\t\tthis.label =\n\t\t\t\tthis.axis.chart.renderer.text(str, 0, 0, options.useHTML)\t\t// dummy positions, actual position updated with setOffset method in columnseries\n\t\t\t\t\t.css(options.style)\t\t\t\t// apply style\n\t\t\t\t\t.attr({\n\t\t\t\t\t\talign: this.textAlign,\t\t\t\t// fix the text-anchor\n\t\t\t\t\t\trotation: options.rotation,\t// rotation\n\t\t\t\t\t\tvisibility: HIDDEN\t\t\t\t\t// hidden until setOffset is called\n\t\t\t\t\t})\t\t\t\t\n\t\t\t\t\t.add(group);\t\t\t\t\t\t\t// add to the labels-group\n\t\t}\n\t},\n\n\tcacheExtremes: function (series, extremes) {\n\t\tthis.points[series.index] = extremes;\n\t},\n\n\t/**\n\t * Sets the offset that the stack has from the x value and repositions the label.\n\t */\n\tsetOffset: function (xOffset, xWidth) {\n\t\tvar stackItem = this,\n\t\t\taxis = stackItem.axis,\n\t\t\tchart = axis.chart,\n\t\t\tinverted = chart.inverted,\n\t\t\tneg = this.isNegative,\t\t\t\t\t\t\t// special treatment is needed for negative stacks\n\t\t\ty = axis.translate(this.percent ? 100 : this.total, 0, 0, 0, 1), // stack value translated mapped to chart coordinates\n\t\t\tyZero = axis.translate(0),\t\t\t\t\t\t// stack origin\n\t\t\th = mathAbs(y - yZero),\t\t\t\t\t\t\t// stack height\n\t\t\tx = chart.xAxis[0].translate(this.x) + xOffset,\t// stack x position\n\t\t\tplotHeight = chart.plotHeight,\n\t\t\tstackBox = {\t// this is the box for the complete stack\n\t\t\t\tx: inverted ? (neg ? y : y - h) : x,\n\t\t\t\ty: inverted ? plotHeight - x - xWidth : (neg ? (plotHeight - y - h) : plotHeight - y),\n\t\t\t\twidth: inverted ? h : xWidth,\n\t\t\t\theight: inverted ? xWidth : h\n\t\t\t},\n\t\t\tlabel = this.label,\n\t\t\talignAttr;\n\t\t\n\t\tif (label) {\n\t\t\tlabel.align(this.alignOptions, null, stackBox);\t// align the label to the box\n\t\t\t\t\n\t\t\t// Set visibility (#678)\n\t\t\talignAttr = label.alignAttr;\n\t\t\tlabel.attr({ \n\t\t\t\tvisibility: this.options.crop === false || chart.isInsidePlot(alignAttr.x, alignAttr.y) ? \n\t\t\t\t\t(hasSVG ? 'inherit' : VISIBLE) : \n\t\t\t\t\tHIDDEN\n\t\t\t});\n\t\t}\n\t}\n};\n/**\n * Create a new axis object\n * @param {Object} chart\n * @param {Object} options\n */\nfunction Axis() {\n\tthis.init.apply(this, arguments);\n}\n\nAxis.prototype = {\n\t\n\t/**\n\t * Default options for the X axis - the Y axis has extended defaults \n\t */\n\tdefaultOptions: {\n\t\t// allowDecimals: null,\n\t\t// alternateGridColor: null,\n\t\t// categories: [],\n\t\tdateTimeLabelFormats: {\n\t\t\tmillisecond: '%H:%M:%S.%L',\n\t\t\tsecond: '%H:%M:%S',\n\t\t\tminute: '%H:%M',\n\t\t\thour: '%H:%M',\n\t\t\tday: '%e. %b',\n\t\t\tweek: '%e. %b',\n\t\t\tmonth: '%b \\'%y',\n\t\t\tyear: '%Y'\n\t\t},\n\t\tendOnTick: false,\n\t\tgridLineColor: '#C0C0C0',\n\t\t// gridLineDashStyle: 'solid',\n\t\t// gridLineWidth: 0,\n\t\t// reversed: false,\n\t\n\t\tlabels: defaultLabelOptions,\n\t\t\t// { step: null },\n\t\tlineColor: '#C0D0E0',\n\t\tlineWidth: 1,\n\t\t//linkedTo: null,\n\t\t//max: undefined,\n\t\t//min: undefined,\n\t\tminPadding: 0.01,\n\t\tmaxPadding: 0.01,\n\t\t//minRange: null,\n\t\tminorGridLineColor: '#E0E0E0',\n\t\t// minorGridLineDashStyle: null,\n\t\tminorGridLineWidth: 1,\n\t\tminorTickColor: '#A0A0A0',\n\t\t//minorTickInterval: null,\n\t\tminorTickLength: 2,\n\t\tminorTickPosition: 'outside', // inside or outside\n\t\t//minorTickWidth: 0,\n\t\t//opposite: false,\n\t\t//offset: 0,\n\t\t//plotBands: [{\n\t\t//\tevents: {},\n\t\t//\tzIndex: 1,\n\t\t//\tlabels: { align, x, verticalAlign, y, style, rotation, textAlign }\n\t\t//}],\n\t\t//plotLines: [{\n\t\t//\tevents: {}\n\t\t//  dashStyle: {}\n\t\t//\tzIndex:\n\t\t//\tlabels: { align, x, verticalAlign, y, style, rotation, textAlign }\n\t\t//}],\n\t\t//reversed: false,\n\t\t// showFirstLabel: true,\n\t\t// showLastLabel: true,\n\t\tstartOfWeek: 1,\n\t\tstartOnTick: false,\n\t\ttickColor: '#C0D0E0',\n\t\t//tickInterval: null,\n\t\ttickLength: 5,\n\t\ttickmarkPlacement: 'between', // on or between\n\t\ttickPixelInterval: 100,\n\t\ttickPosition: 'outside',\n\t\ttickWidth: 1,\n\t\ttitle: {\n\t\t\t//text: null,\n\t\t\talign: 'middle', // low, middle or high\n\t\t\t//margin: 0 for horizontal, 10 for vertical axes,\n\t\t\t//rotation: 0,\n\t\t\t//side: 'outside',\n\t\t\tstyle: {\n\t\t\t\tcolor: '#4d759e',\n\t\t\t\t//font: defaultFont.replace('normal', 'bold')\n\t\t\t\tfontWeight: 'bold'\n\t\t\t}\n\t\t\t//x: 0,\n\t\t\t//y: 0\n\t\t},\n\t\ttype: 'linear' // linear, logarithmic or datetime\n\t},\n\t\n\t/**\n\t * This options set extends the defaultOptions for Y axes\n\t */\n\tdefaultYAxisOptions: {\n\t\tendOnTick: true,\n\t\tgridLineWidth: 1,\n\t\ttickPixelInterval: 72,\n\t\tshowLastLabel: true,\n\t\tlabels: {\n\t\t\tx: -8,\n\t\t\ty: 3\n\t\t},\n\t\tlineWidth: 0,\n\t\tmaxPadding: 0.05,\n\t\tminPadding: 0.05,\n\t\tstartOnTick: true,\n\t\ttickWidth: 0,\n\t\ttitle: {\n\t\t\trotation: 270,\n\t\t\ttext: 'Values'\n\t\t},\n\t\tstackLabels: {\n\t\t\tenabled: false,\n\t\t\t//align: dynamic,\n\t\t\t//y: dynamic,\n\t\t\t//x: dynamic,\n\t\t\t//verticalAlign: dynamic,\n\t\t\t//textAlign: dynamic,\n\t\t\t//rotation: 0,\n\t\t\tformatter: function () {\n\t\t\t\treturn numberFormat(this.total, -1);\n\t\t\t},\n\t\t\tstyle: defaultLabelOptions.style\n\t\t}\n\t},\n\t\n\t/**\n\t * These options extend the defaultOptions for left axes\n\t */\n\tdefaultLeftAxisOptions: {\n\t\tlabels: {\n\t\t\tx: -8,\n\t\t\ty: null\n\t\t},\n\t\ttitle: {\n\t\t\trotation: 270\n\t\t}\n\t},\n\t\n\t/**\n\t * These options extend the defaultOptions for right axes\n\t */\n\tdefaultRightAxisOptions: {\n\t\tlabels: {\n\t\t\tx: 8,\n\t\t\ty: null\n\t\t},\n\t\ttitle: {\n\t\t\trotation: 90\n\t\t}\n\t},\n\t\n\t/**\n\t * These options extend the defaultOptions for bottom axes\n\t */\n\tdefaultBottomAxisOptions: {\n\t\tlabels: {\n\t\t\tx: 0,\n\t\t\ty: 14\n\t\t\t// overflow: undefined,\n\t\t\t// staggerLines: null\n\t\t},\n\t\ttitle: {\n\t\t\trotation: 0\n\t\t}\n\t},\n\t/**\n\t * These options extend the defaultOptions for left axes\n\t */\n\tdefaultTopAxisOptions: {\n\t\tlabels: {\n\t\t\tx: 0,\n\t\t\ty: -5\n\t\t\t// overflow: undefined\n\t\t\t// staggerLines: null\n\t\t},\n\t\ttitle: {\n\t\t\trotation: 0\n\t\t}\n\t},\n\t\n\t/**\n\t * Initialize the axis\n\t */\n\tinit: function (chart, userOptions) {\n\t\t\t\n\t\t\n\t\tvar isXAxis = userOptions.isX,\n\t\t\taxis = this;\n\t\n\t\t// Flag, is the axis horizontal\n\t\taxis.horiz = chart.inverted ? !isXAxis : isXAxis;\n\t\t\n\t\t// Flag, isXAxis\n\t\taxis.isXAxis = isXAxis;\n\t\taxis.xOrY = isXAxis ? 'x' : 'y';\n\t\n\t\n\t\taxis.opposite = userOptions.opposite; // needed in setOptions\n\t\taxis.side = axis.horiz ?\n\t\t\t\t(axis.opposite ? 0 : 2) : // top : bottom\n\t\t\t\t(axis.opposite ? 1 : 3);  // right : left\n\t\n\t\taxis.setOptions(userOptions);\n\t\t\n\t\n\t\tvar options = this.options,\n\t\t\ttype = options.type,\n\t\t\tisDatetimeAxis = type === 'datetime';\n\t\n\t\taxis.labelFormatter = options.labels.formatter || axis.defaultLabelFormatter; // can be overwritten by dynamic format\n\t\n\t\n\t\t// Flag, stagger lines or not\n\t\taxis.userOptions = userOptions;\n\t\n\t\t//axis.axisTitleMargin = UNDEFINED,// = options.title.margin,\n\t\taxis.minPixelPadding = 0;\n\t\t//axis.ignoreMinPadding = UNDEFINED; // can be set to true by a column or bar series\n\t\t//axis.ignoreMaxPadding = UNDEFINED;\n\t\n\t\taxis.chart = chart;\n\t\taxis.reversed = options.reversed;\n\t\taxis.zoomEnabled = options.zoomEnabled !== false;\n\t\n\t\t// Initial categories\n\t\taxis.categories = options.categories || type === 'category';\n\t\n\t\t// Elements\n\t\t//axis.axisGroup = UNDEFINED;\n\t\t//axis.gridGroup = UNDEFINED;\n\t\t//axis.axisTitle = UNDEFINED;\n\t\t//axis.axisLine = UNDEFINED;\n\t\n\t\t// Shorthand types\n\t\taxis.isLog = type === 'logarithmic';\n\t\taxis.isDatetimeAxis = isDatetimeAxis;\n\t\n\t\t// Flag, if axis is linked to another axis\n\t\taxis.isLinked = defined(options.linkedTo);\n\t\t// Linked axis.\n\t\t//axis.linkedParent = UNDEFINED;\n\t\n\t\n\t\t// Flag if percentage mode\n\t\t//axis.usePercentage = UNDEFINED;\n\t\n\t\t\n\t\t// Tick positions\n\t\t//axis.tickPositions = UNDEFINED; // array containing predefined positions\n\t\t// Tick intervals\n\t\t//axis.tickInterval = UNDEFINED;\n\t\t//axis.minorTickInterval = UNDEFINED;\n\t\t\n\t\taxis.tickmarkOffset = (axis.categories && options.tickmarkPlacement === 'between') ? 0.5 : 0;\n\t\n\t\t// Major ticks\n\t\taxis.ticks = {};\n\t\t// Minor ticks\n\t\taxis.minorTicks = {};\n\t\t//axis.tickAmount = UNDEFINED;\n\t\n\t\t// List of plotLines/Bands\n\t\taxis.plotLinesAndBands = [];\n\t\n\t\t// Alternate bands\n\t\taxis.alternateBands = {};\n\t\n\t\t// Axis metrics\n\t\t//axis.left = UNDEFINED;\n\t\t//axis.top = UNDEFINED;\n\t\t//axis.width = UNDEFINED;\n\t\t//axis.height = UNDEFINED;\n\t\t//axis.bottom = UNDEFINED;\n\t\t//axis.right = UNDEFINED;\n\t\t//axis.transA = UNDEFINED;\n\t\t//axis.transB = UNDEFINED;\n\t\t//axis.oldTransA = UNDEFINED;\n\t\taxis.len = 0;\n\t\t//axis.oldMin = UNDEFINED;\n\t\t//axis.oldMax = UNDEFINED;\n\t\t//axis.oldUserMin = UNDEFINED;\n\t\t//axis.oldUserMax = UNDEFINED;\n\t\t//axis.oldAxisLength = UNDEFINED;\n\t\taxis.minRange = axis.userMinRange = options.minRange || options.maxZoom;\n\t\taxis.range = options.range;\n\t\taxis.offset = options.offset || 0;\n\t\n\t\n\t\t// Dictionary for stacks\n\t\taxis.stacks = {};\n\t\taxis.oldStacks = {};\n\n\t\t// Dictionary for stacks max values\n\t\taxis.stacksMax = {};\n\n\t\taxis._stacksTouched = 0;\n\n\t\t// Min and max in the data\n\t\t//axis.dataMin = UNDEFINED,\n\t\t//axis.dataMax = UNDEFINED,\n\t\n\t\t// The axis range\n\t\taxis.max = null;\n\t\taxis.min = null;\n\t\n\t\t// User set min and max\n\t\t//axis.userMin = UNDEFINED,\n\t\t//axis.userMax = UNDEFINED,\n\n\t\t// Run Axis\n\t\t\n\t\tvar eventType,\n\t\t\tevents = axis.options.events;\n\n\t\t// Register\n\t\tif (inArray(axis, chart.axes) === -1) { // don't add it again on Axis.update()\n\t\t\tchart.axes.push(axis);\n\t\t\tchart[isXAxis ? 'xAxis' : 'yAxis'].push(axis);\n\t\t}\n\n\t\taxis.series = axis.series || []; // populated by Series\n\n\t\t// inverted charts have reversed xAxes as default\n\t\tif (chart.inverted && isXAxis && axis.reversed === UNDEFINED) {\n\t\t\taxis.reversed = true;\n\t\t}\n\n\t\taxis.removePlotBand = axis.removePlotBandOrLine;\n\t\taxis.removePlotLine = axis.removePlotBandOrLine;\n\n\n\t\t// register event listeners\n\t\tfor (eventType in events) {\n\t\t\taddEvent(axis, eventType, events[eventType]);\n\t\t}\n\n\t\t// extend logarithmic axis\n\t\tif (axis.isLog) {\n\t\t\taxis.val2lin = log2lin;\n\t\t\taxis.lin2val = lin2log;\n\t\t}\n\t},\n\t\n\t/**\n\t * Merge and set options\n\t */\n\tsetOptions: function (userOptions) {\n\t\tthis.options = merge(\n\t\t\tthis.defaultOptions,\n\t\t\tthis.isXAxis ? {} : this.defaultYAxisOptions,\n\t\t\t[this.defaultTopAxisOptions, this.defaultRightAxisOptions,\n\t\t\t\tthis.defaultBottomAxisOptions, this.defaultLeftAxisOptions][this.side],\n\t\t\tmerge(\n\t\t\t\tdefaultOptions[this.isXAxis ? 'xAxis' : 'yAxis'], // if set in setOptions (#1053)\n\t\t\t\tuserOptions\n\t\t\t)\n\t\t);\n\t},\n\n\t/**\n\t * Update the axis with a new options structure\n\t */\n\tupdate: function (newOptions, redraw) {\n\t\tvar chart = this.chart;\n\n\t\tnewOptions = chart.options[this.xOrY + 'Axis'][this.options.index] = merge(this.userOptions, newOptions);\n\n\t\tthis.destroy(true);\n\t\tthis._addedPlotLB = false; // #1611\n\n\t\tthis.init(chart, extend(newOptions, { events: UNDEFINED }));\n\n\t\tchart.isDirtyBox = true;\n\t\tif (pick(redraw, true)) {\n\t\t\tchart.redraw();\n\t\t}\n\t},\t\n\t\n\t/**\n     * Remove the axis from the chart\n     */\n\tremove: function (redraw) {\n\t\tvar chart = this.chart,\n\t\t\tkey = this.xOrY + 'Axis'; // xAxis or yAxis\n\n\t\t// Remove associated series\n\t\teach(this.series, function (series) {\n\t\t\tseries.remove(false);\n\t\t});\n\n\t\t// Remove the axis\n\t\terase(chart.axes, this);\n\t\terase(chart[key], this);\n\t\tchart.options[key].splice(this.options.index, 1);\n\t\teach(chart[key], function (axis, i) { // Re-index, #1706\n\t\t\taxis.options.index = i;\n\t\t});\n\t\tthis.destroy();\n\t\tchart.isDirtyBox = true;\n\n\t\tif (pick(redraw, true)) {\n\t\t\tchart.redraw();\n\t\t}\n\t},\n\t\n\t/** \n\t * The default label formatter. The context is a special config object for the label.\n\t */\n\tdefaultLabelFormatter: function () {\n\t\tvar axis = this.axis,\n\t\t\tvalue = this.value,\n\t\t\tcategories = axis.categories, \n\t\t\tdateTimeLabelFormat = this.dateTimeLabelFormat,\n\t\t\tnumericSymbols = defaultOptions.lang.numericSymbols,\n\t\t\ti = numericSymbols && numericSymbols.length,\n\t\t\tmulti,\n\t\t\tret,\n\t\t\tformatOption = axis.options.labels.format,\n\t\t\t\n\t\t\t// make sure the same symbol is added for all labels on a linear axis\n\t\t\tnumericSymbolDetector = axis.isLog ? value : axis.tickInterval;\n\n\t\tif (formatOption) {\n\t\t\tret = format(formatOption, this);\n\t\t\n\t\t} else if (categories) {\n\t\t\tret = value;\n\t\t\n\t\t} else if (dateTimeLabelFormat) { // datetime axis\n\t\t\tret = dateFormat(dateTimeLabelFormat, value);\n\t\t\n\t\t} else if (i && numericSymbolDetector >= 1000) {\n\t\t\t// Decide whether we should add a numeric symbol like k (thousands) or M (millions).\n\t\t\t// If we are to enable this in tooltip or other places as well, we can move this\n\t\t\t// logic to the numberFormatter and enable it by a parameter.\n\t\t\twhile (i-- && ret === UNDEFINED) {\n\t\t\t\tmulti = Math.pow(1000, i + 1);\n\t\t\t\tif (numericSymbolDetector >= multi && numericSymbols[i] !== null) {\n\t\t\t\t\tret = numberFormat(value / multi, -1) + numericSymbols[i];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\tif (ret === UNDEFINED) {\n\t\t\tif (value >= 1000) { // add thousands separators\n\t\t\t\tret = numberFormat(value, 0);\n\n\t\t\t} else { // small numbers\n\t\t\t\tret = numberFormat(value, -1);\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn ret;\n\t},\n\n\t/**\n\t * Get the minimum and maximum for the series of each axis\n\t */\n\tgetSeriesExtremes: function () {\n\t\tvar axis = this,\n\t\t\tchart = axis.chart;\n\n\t\taxis.hasVisibleSeries = false;\n\n\t\t// reset dataMin and dataMax in case we're redrawing\n\t\taxis.dataMin = axis.dataMax = null;\n\n\t\t// reset cached stacking extremes\n\t\taxis.stacksMax = {};\n\n\t\taxis.buildStacks();\n\n\t\t// loop through this axis' series\n\t\teach(axis.series, function (series) {\n\n\t\t\tif (series.visible || !chart.options.chart.ignoreHiddenSeries) {\n\n\t\t\t\tvar seriesOptions = series.options,\n\t\t\t\t\tstacking,\n\t\t\t\t\txData,\n\t\t\t\t\tthreshold = seriesOptions.threshold,\n\t\t\t\t\tseriesDataMin,\n\t\t\t\t\tseriesDataMax;\n\n\t\t\t\taxis.hasVisibleSeries = true;\n\n\t\t\t\t// Validate threshold in logarithmic axes\n\t\t\t\tif (axis.isLog && threshold <= 0) {\n\t\t\t\t\tthreshold = null;\n\t\t\t\t}\n\n\t\t\t\t// Get dataMin and dataMax for X axes\n\t\t\t\tif (axis.isXAxis) {\n\t\t\t\t\txData = series.xData;\n\t\t\t\t\tif (xData.length) {\n\t\t\t\t\t\taxis.dataMin = mathMin(pick(axis.dataMin, xData[0]), arrayMin(xData));\n\t\t\t\t\t\taxis.dataMax = mathMax(pick(axis.dataMax, xData[0]), arrayMax(xData));\n\t\t\t\t\t}\n\n\t\t\t\t// Get dataMin and dataMax for Y axes, as well as handle stacking and processed data\n\t\t\t\t} else {\n\n\t\t\t\t\t// Handle stacking\n\t\t\t\t\tstacking = seriesOptions.stacking;\n\t\t\t\t\taxis.usePercentage = stacking === 'percent';\n\n\t\t\t\t\t// create a stack for this particular series type\n\t\t\t\t\tif (axis.usePercentage) {\n\t\t\t\t\t\taxis.dataMin = 0;\n\t\t\t\t\t\taxis.dataMax = 99;\n\t\t\t\t\t}\n\n\t\t\t\t\t\n\t\t\t\t\t// get this particular series extremes\n\t\t\t\t\tseries.getExtremes();\n\t\t\t\t\tseriesDataMax = series.dataMax;\n\t\t\t\t\tseriesDataMin = series.dataMin;\n\n\t\t\t\t\t// Get the dataMin and dataMax so far. If percentage is used, the min and max are\n\t\t\t\t\t// always 0 and 100. If seriesDataMin and seriesDataMax is null, then series\n\t\t\t\t\t// doesn't have active y data, we continue with nulls\n\t\t\t\t\tif (!axis.usePercentage && defined(seriesDataMin) && defined(seriesDataMax)) {\n\t\t\t\t\t\taxis.dataMin = mathMin(pick(axis.dataMin, seriesDataMin), seriesDataMin);\n\t\t\t\t\t\taxis.dataMax = mathMax(pick(axis.dataMax, seriesDataMax), seriesDataMax);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Adjust to threshold\n\t\t\t\t\tif (defined(threshold)) {\n\t\t\t\t\t\tif (axis.dataMin >= threshold) {\n\t\t\t\t\t\t\taxis.dataMin = threshold;\n\t\t\t\t\t\t\taxis.ignoreMinPadding = true;\n\t\t\t\t\t\t} else if (axis.dataMax < threshold) {\n\t\t\t\t\t\t\taxis.dataMax = threshold;\n\t\t\t\t\t\t\taxis.ignoreMaxPadding = true;\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\t/**\n\t * Translate from axis value to pixel position on the chart, or back\n\t *\n\t */\n\ttranslate: function (val, backwards, cvsCoord, old, handleLog, pointPlacement) {\n\t\tvar axis = this,\n\t\t\taxisLength = axis.len,\n\t\t\tsign = 1,\n\t\t\tcvsOffset = 0,\n\t\t\tlocalA = old ? axis.oldTransA : axis.transA,\n\t\t\tlocalMin = old ? axis.oldMin : axis.min,\n\t\t\treturnValue,\n\t\t\tminPixelPadding = axis.minPixelPadding,\n\t\t\tpostTranslate = (axis.options.ordinal || (axis.isLog && handleLog)) && axis.lin2val;\n\n\t\tif (!localA) {\n\t\t\tlocalA = axis.transA;\n\t\t}\n\n\t\t// In vertical axes, the canvas coordinates start from 0 at the top like in \n\t\t// SVG. \n\t\tif (cvsCoord) {\n\t\t\tsign *= -1; // canvas coordinates inverts the value\n\t\t\tcvsOffset = axisLength;\n\t\t}\n\n\t\t// Handle reversed axis\n\t\tif (axis.reversed) { \n\t\t\tsign *= -1;\n\t\t\tcvsOffset -= sign * axisLength;\n\t\t}\n\n\t\t// From pixels to value\n\t\tif (backwards) { // reverse translation\n\t\t\t\n\t\t\tval = val * sign + cvsOffset;\n\t\t\tval -= minPixelPadding;\n\t\t\treturnValue = val / localA + localMin; // from chart pixel to value\n\t\t\tif (postTranslate) { // log and ordinal axes\n\t\t\t\treturnValue = axis.lin2val(returnValue);\n\t\t\t}\n\n\t\t// From value to pixels\n\t\t} else {\n\t\t\tif (postTranslate) { // log and ordinal axes\n\t\t\t\tval = axis.val2lin(val);\n\t\t\t}\n\t\t\tif (pointPlacement === 'between') {\n\t\t\t\tpointPlacement = 0.5;\n\t\t\t}\n\t\t\treturnValue = sign * (val - localMin) * localA + cvsOffset + (sign * minPixelPadding) +\n\t\t\t\t(isNumber(pointPlacement) ? localA * pointPlacement * axis.pointRange : 0);\n\t\t}\n\n\t\treturn returnValue;\n\t},\n\n\t/**\n\t * Utility method to translate an axis value to pixel position. \n\t * @param {Number} value A value in terms of axis units\n\t * @param {Boolean} paneCoordinates Whether to return the pixel coordinate relative to the chart\n\t *        or just the axis/pane itself.\n\t */\n\ttoPixels: function (value, paneCoordinates) {\n\t\treturn this.translate(value, false, !this.horiz, null, true) + (paneCoordinates ? 0 : this.pos);\n\t},\n\n\t/*\n\t * Utility method to translate a pixel position in to an axis value\n\t * @param {Number} pixel The pixel value coordinate\n\t * @param {Boolean} paneCoordiantes Whether the input pixel is relative to the chart or just the\n\t *        axis/pane itself.\n\t */\n\ttoValue: function (pixel, paneCoordinates) {\n\t\treturn this.translate(pixel - (paneCoordinates ? 0 : this.pos), true, !this.horiz, null, true);\n\t},\n\n\t/**\n\t * Create the path for a plot line that goes from the given value on\n\t * this axis, across the plot to the opposite side\n\t * @param {Number} value\n\t * @param {Number} lineWidth Used for calculation crisp line\n\t * @param {Number] old Use old coordinates (for resizing and rescaling)\n\t */\n\tgetPlotLinePath: function (value, lineWidth, old, force) {\n\t\tvar axis = this,\n\t\t\tchart = axis.chart,\n\t\t\taxisLeft = axis.left,\n\t\t\taxisTop = axis.top,\n\t\t\tx1,\n\t\t\ty1,\n\t\t\tx2,\n\t\t\ty2,\n\t\t\ttranslatedValue = axis.translate(value, null, null, old),\n\t\t\tcHeight = (old && chart.oldChartHeight) || chart.chartHeight,\n\t\t\tcWidth = (old && chart.oldChartWidth) || chart.chartWidth,\n\t\t\tskip,\n\t\t\ttransB = axis.transB;\n\n\t\tx1 = x2 = mathRound(translatedValue + transB);\n\t\ty1 = y2 = mathRound(cHeight - translatedValue - transB);\n\n\t\tif (isNaN(translatedValue)) { // no min or max\n\t\t\tskip = true;\n\n\t\t} else if (axis.horiz) {\n\t\t\ty1 = axisTop;\n\t\t\ty2 = cHeight - axis.bottom;\n\t\t\tif (x1 < axisLeft || x1 > axisLeft + axis.width) {\n\t\t\t\tskip = true;\n\t\t\t}\n\t\t} else {\n\t\t\tx1 = axisLeft;\n\t\t\tx2 = cWidth - axis.right;\n\n\t\t\tif (y1 < axisTop || y1 > axisTop + axis.height) {\n\t\t\t\tskip = true;\n\t\t\t}\n\t\t}\n\t\treturn skip && !force ?\n\t\t\tnull :\n\t\t\tchart.renderer.crispLine([M, x1, y1, L, x2, y2], lineWidth || 0);\n\t},\n\t\n\t/**\n\t * Create the path for a plot band\n\t */\n\tgetPlotBandPath: function (from, to) {\n\n\t\tvar toPath = this.getPlotLinePath(to),\n\t\t\tpath = this.getPlotLinePath(from);\n\t\t\t\n\t\tif (path && toPath) {\n\t\t\tpath.push(\n\t\t\t\ttoPath[4],\n\t\t\t\ttoPath[5],\n\t\t\t\ttoPath[1],\n\t\t\t\ttoPath[2]\n\t\t\t);\n\t\t} else { // outside the axis area\n\t\t\tpath = null;\n\t\t}\n\t\t\n\t\treturn path;\n\t},\n\t\n\t/**\n\t * Set the tick positions of a linear axis to round values like whole tens or every five.\n\t */\n\tgetLinearTickPositions: function (tickInterval, min, max) {\n\t\tvar pos,\n\t\t\tlastPos,\n\t\t\troundedMin = correctFloat(mathFloor(min / tickInterval) * tickInterval),\n\t\t\troundedMax = correctFloat(mathCeil(max / tickInterval) * tickInterval),\n\t\t\ttickPositions = [];\n\n\t\t// Populate the intermediate values\n\t\tpos = roundedMin;\n\t\twhile (pos <= roundedMax) {\n\n\t\t\t// Place the tick on the rounded value\n\t\t\ttickPositions.push(pos);\n\n\t\t\t// Always add the raw tickInterval, not the corrected one.\n\t\t\tpos = correctFloat(pos + tickInterval);\n\n\t\t\t// If the interval is not big enough in the current min - max range to actually increase\n\t\t\t// the loop variable, we need to break out to prevent endless loop. Issue #619\n\t\t\tif (pos === lastPos) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// Record the last value\n\t\t\tlastPos = pos;\n\t\t}\n\t\treturn tickPositions;\n\t},\n\t\n\t/**\n\t * Set the tick positions of a logarithmic axis\n\t */\n\tgetLogTickPositions: function (interval, min, max, minor) {\n\t\tvar axis = this,\n\t\t\toptions = axis.options,\n\t\t\taxisLength = axis.len,\n\t\t\t// Since we use this method for both major and minor ticks,\n\t\t\t// use a local variable and return the result\n\t\t\tpositions = []; \n\t\t\n\t\t// Reset\n\t\tif (!minor) {\n\t\t\taxis._minorAutoInterval = null;\n\t\t}\n\t\t\n\t\t// First case: All ticks fall on whole logarithms: 1, 10, 100 etc.\n\t\tif (interval >= 0.5) {\n\t\t\tinterval = mathRound(interval);\n\t\t\tpositions = axis.getLinearTickPositions(interval, min, max);\n\t\t\t\n\t\t// Second case: We need intermediary ticks. For example \n\t\t// 1, 2, 4, 6, 8, 10, 20, 40 etc. \n\t\t} else if (interval >= 0.08) {\n\t\t\tvar roundedMin = mathFloor(min),\n\t\t\t\tintermediate,\n\t\t\t\ti,\n\t\t\t\tj,\n\t\t\t\tlen,\n\t\t\t\tpos,\n\t\t\t\tlastPos,\n\t\t\t\tbreak2;\n\t\t\t\t\n\t\t\tif (interval > 0.3) {\n\t\t\t\tintermediate = [1, 2, 4];\n\t\t\t} else if (interval > 0.15) { // 0.2 equals five minor ticks per 1, 10, 100 etc\n\t\t\t\tintermediate = [1, 2, 4, 6, 8];\n\t\t\t} else { // 0.1 equals ten minor ticks per 1, 10, 100 etc\n\t\t\t\tintermediate = [1, 2, 3, 4, 5, 6, 7, 8, 9];\n\t\t\t}\n\t\t\t\n\t\t\tfor (i = roundedMin; i < max + 1 && !break2; i++) {\n\t\t\t\tlen = intermediate.length;\n\t\t\t\tfor (j = 0; j < len && !break2; j++) {\n\t\t\t\t\tpos = log2lin(lin2log(i) * intermediate[j]);\n\t\t\t\t\t\n\t\t\t\t\tif (pos > min && (!minor || lastPos <= max)) { // #1670\n\t\t\t\t\t\tpositions.push(lastPos);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif (lastPos > max) {\n\t\t\t\t\t\tbreak2 = true;\n\t\t\t\t\t}\n\t\t\t\t\tlastPos = pos;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t// Third case: We are so deep in between whole logarithmic values that\n\t\t// we might as well handle the tick positions like a linear axis. For\n\t\t// example 1.01, 1.02, 1.03, 1.04.\n\t\t} else {\n\t\t\tvar realMin = lin2log(min),\n\t\t\t\trealMax = lin2log(max),\n\t\t\t\ttickIntervalOption = options[minor ? 'minorTickInterval' : 'tickInterval'],\n\t\t\t\tfilteredTickIntervalOption = tickIntervalOption === 'auto' ? null : tickIntervalOption,\n\t\t\t\ttickPixelIntervalOption = options.tickPixelInterval / (minor ? 5 : 1),\n\t\t\t\ttotalPixelLength = minor ? axisLength / axis.tickPositions.length : axisLength;\n\t\t\t\n\t\t\tinterval = pick(\n\t\t\t\tfilteredTickIntervalOption,\n\t\t\t\taxis._minorAutoInterval,\n\t\t\t\t(realMax - realMin) * tickPixelIntervalOption / (totalPixelLength || 1)\n\t\t\t);\n\t\t\t\n\t\t\tinterval = normalizeTickInterval(\n\t\t\t\tinterval, \n\t\t\t\tnull, \n\t\t\t\tgetMagnitude(interval)\n\t\t\t);\n\t\t\t\n\t\t\tpositions = map(axis.getLinearTickPositions(\n\t\t\t\tinterval, \n\t\t\t\trealMin,\n\t\t\t\trealMax\t\n\t\t\t), log2lin);\n\t\t\t\n\t\t\tif (!minor) {\n\t\t\t\taxis._minorAutoInterval = interval / 5;\n\t\t\t}\n\t\t}\n\t\t\n\t\t// Set the axis-level tickInterval variable \n\t\tif (!minor) {\n\t\t\taxis.tickInterval = interval;\n\t\t}\n\t\treturn positions;\n\t},\n\n\t/**\n\t * Return the minor tick positions. For logarithmic axes, reuse the same logic\n\t * as for major ticks.\n\t */\n\tgetMinorTickPositions: function () {\n\t\tvar axis = this,\n\t\t\toptions = axis.options,\n\t\t\ttickPositions = axis.tickPositions,\n\t\t\tminorTickInterval = axis.minorTickInterval,\n\t\t\tminorTickPositions = [],\n\t\t\tpos,\n\t\t\ti,\n\t\t\tlen;\n\t\t\n\t\tif (axis.isLog) {\n\t\t\tlen = tickPositions.length;\n\t\t\tfor (i = 1; i < len; i++) {\n\t\t\t\tminorTickPositions = minorTickPositions.concat(\n\t\t\t\t\taxis.getLogTickPositions(minorTickInterval, tickPositions[i - 1], tickPositions[i], true)\n\t\t\t\t);\t\n\t\t\t}\n\t\t} else if (axis.isDatetimeAxis && options.minorTickInterval === 'auto') { // #1314\n\t\t\tminorTickPositions = minorTickPositions.concat(\n\t\t\t\tgetTimeTicks(\n\t\t\t\t\tnormalizeTimeTickInterval(minorTickInterval),\n\t\t\t\t\taxis.min,\n\t\t\t\t\taxis.max,\n\t\t\t\t\toptions.startOfWeek\n\t\t\t\t)\n\t\t\t);\n\t\t\tif (minorTickPositions[0] < axis.min) {\n\t\t\t\tminorTickPositions.shift();\n\t\t\t}\n\t\t} else {\t\t\t\n\t\t\tfor (pos = axis.min + (tickPositions[0] - axis.min) % minorTickInterval; pos <= axis.max; pos += minorTickInterval) {\n\t\t\t\tminorTickPositions.push(pos);\n\t\t\t}\n\t\t}\n\t\treturn minorTickPositions;\n\t},\n\n\t/**\n\t * Adjust the min and max for the minimum range. Keep in mind that the series data is \n\t * not yet processed, so we don't have information on data cropping and grouping, or \n\t * updated axis.pointRange or series.pointRange. The data can't be processed until\n\t * we have finally established min and max.\n\t */\n\tadjustForMinRange: function () {\n\t\tvar axis = this,\n\t\t\toptions = axis.options,\n\t\t\tmin = axis.min,\n\t\t\tmax = axis.max,\n\t\t\tzoomOffset,\n\t\t\tspaceAvailable = axis.dataMax - axis.dataMin >= axis.minRange,\n\t\t\tclosestDataRange,\n\t\t\ti,\n\t\t\tdistance,\n\t\t\txData,\n\t\t\tloopLength,\n\t\t\tminArgs,\n\t\t\tmaxArgs;\n\n\t\t// Set the automatic minimum range based on the closest point distance\n\t\tif (axis.isXAxis && axis.minRange === UNDEFINED && !axis.isLog) {\n\n\t\t\tif (defined(options.min) || defined(options.max)) {\n\t\t\t\taxis.minRange = null; // don't do this again\n\n\t\t\t} else {\n\n\t\t\t\t// Find the closest distance between raw data points, as opposed to\n\t\t\t\t// closestPointRange that applies to processed points (cropped and grouped)\n\t\t\t\teach(axis.series, function (series) {\n\t\t\t\t\txData = series.xData;\n\t\t\t\t\tloopLength = series.xIncrement ? 1 : xData.length - 1;\n\t\t\t\t\tfor (i = loopLength; i > 0; i--) {\n\t\t\t\t\t\tdistance = xData[i] - xData[i - 1];\n\t\t\t\t\t\tif (closestDataRange === UNDEFINED || distance < closestDataRange) {\n\t\t\t\t\t\t\tclosestDataRange = distance;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\taxis.minRange = mathMin(closestDataRange * 5, axis.dataMax - axis.dataMin);\n\t\t\t}\n\t\t}\n\n\t\t// if minRange is exceeded, adjust\n\t\tif (max - min < axis.minRange) {\n\t\t\tvar minRange = axis.minRange;\n\t\t\tzoomOffset = (minRange - max + min) / 2;\n\n\t\t\t// if min and max options have been set, don't go beyond it\n\t\t\tminArgs = [min - zoomOffset, pick(options.min, min - zoomOffset)];\n\t\t\tif (spaceAvailable) { // if space is available, stay within the data range\n\t\t\t\tminArgs[2] = axis.dataMin;\n\t\t\t}\n\t\t\tmin = arrayMax(minArgs);\n\n\t\t\tmaxArgs = [min + minRange, pick(options.max, min + minRange)];\n\t\t\tif (spaceAvailable) { // if space is availabe, stay within the data range\n\t\t\t\tmaxArgs[2] = axis.dataMax;\n\t\t\t}\n\n\t\t\tmax = arrayMin(maxArgs);\n\n\t\t\t// now if the max is adjusted, adjust the min back\n\t\t\tif (max - min < minRange) {\n\t\t\t\tminArgs[0] = max - minRange;\n\t\t\t\tminArgs[1] = pick(options.min, max - minRange);\n\t\t\t\tmin = arrayMax(minArgs);\n\t\t\t}\n\t\t}\n\t\t\n\t\t// Record modified extremes\n\t\taxis.min = min;\n\t\taxis.max = max;\n\t},\n\n\t/**\n\t * Update translation information\n\t */\n\tsetAxisTranslation: function (saveOld) {\n\t\tvar axis = this,\n\t\t\trange = axis.max - axis.min,\n\t\t\tpointRange = 0,\n\t\t\tclosestPointRange,\n\t\t\tminPointOffset = 0,\n\t\t\tpointRangePadding = 0,\n\t\t\tlinkedParent = axis.linkedParent,\n\t\t\tordinalCorrection,\n\t\t\ttransA = axis.transA;\n\n\t\t// adjust translation for padding\n\t\tif (axis.isXAxis) {\n\t\t\tif (linkedParent) {\n\t\t\t\tminPointOffset = linkedParent.minPointOffset;\n\t\t\t\tpointRangePadding = linkedParent.pointRangePadding;\n\t\t\t\t\n\t\t\t} else {\n\t\t\t\teach(axis.series, function (series) {\n\t\t\t\t\tvar seriesPointRange = series.pointRange,\n\t\t\t\t\t\tpointPlacement = series.options.pointPlacement,\n\t\t\t\t\t\tseriesClosestPointRange = series.closestPointRange;\n\n\t\t\t\t\tif (seriesPointRange > range) { // #1446\n\t\t\t\t\t\tseriesPointRange = 0;\n\t\t\t\t\t}\n\t\t\t\t\tpointRange = mathMax(pointRange, seriesPointRange);\n\t\t\t\t\t\n\t\t\t\t\t// minPointOffset is the value padding to the left of the axis in order to make\n\t\t\t\t\t// room for points with a pointRange, typically columns. When the pointPlacement option\n\t\t\t\t\t// is 'between' or 'on', this padding does not apply.\n\t\t\t\t\tminPointOffset = mathMax(\n\t\t\t\t\t\tminPointOffset, \n\t\t\t\t\t\tisString(pointPlacement) ? 0 : seriesPointRange / 2\n\t\t\t\t\t);\n\t\t\t\t\t\n\t\t\t\t\t// Determine the total padding needed to the length of the axis to make room for the \n\t\t\t\t\t// pointRange. If the series' pointPlacement is 'on', no padding is added.\n\t\t\t\t\tpointRangePadding = mathMax(\n\t\t\t\t\t\tpointRangePadding,\n\t\t\t\t\t\tpointPlacement === 'on' ? 0 : seriesPointRange\n\t\t\t\t\t);\n\n\t\t\t\t\t// Set the closestPointRange\n\t\t\t\t\tif (!series.noSharedTooltip && defined(seriesClosestPointRange)) {\n\t\t\t\t\t\tclosestPointRange = defined(closestPointRange) ?\n\t\t\t\t\t\t\tmathMin(closestPointRange, seriesClosestPointRange) :\n\t\t\t\t\t\t\tseriesClosestPointRange;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\t\n\t\t\t// Record minPointOffset and pointRangePadding\n\t\t\tordinalCorrection = axis.ordinalSlope && closestPointRange ? axis.ordinalSlope / closestPointRange : 1; // #988, #1853\n\t\t\taxis.minPointOffset = minPointOffset = minPointOffset * ordinalCorrection;\n\t\t\taxis.pointRangePadding = pointRangePadding = pointRangePadding * ordinalCorrection;\n\n\t\t\t// pointRange means the width reserved for each point, like in a column chart\n\t\t\taxis.pointRange = mathMin(pointRange, range);\n\n\t\t\t// closestPointRange means the closest distance between points. In columns\n\t\t\t// it is mostly equal to pointRange, but in lines pointRange is 0 while closestPointRange\n\t\t\t// is some other value\n\t\t\taxis.closestPointRange = closestPointRange;\n\t\t}\n\n\t\t// Secondary values\n\t\tif (saveOld) {\n\t\t\taxis.oldTransA = transA;\n\t\t}\n\t\taxis.translationSlope = axis.transA = transA = axis.len / ((range + pointRangePadding) || 1);\n\t\taxis.transB = axis.horiz ? axis.left : axis.bottom; // translation addend\n\t\taxis.minPixelPadding = transA * minPointOffset;\n\t},\n\n\t/**\n\t * Set the tick positions to round values and optionally extend the extremes\n\t * to the nearest tick\n\t */\n\tsetTickPositions: function (secondPass) {\n\t\tvar axis = this,\n\t\t\tchart = axis.chart,\n\t\t\toptions = axis.options,\n\t\t\tisLog = axis.isLog,\n\t\t\tisDatetimeAxis = axis.isDatetimeAxis,\n\t\t\tisXAxis = axis.isXAxis,\n\t\t\tisLinked = axis.isLinked,\n\t\t\ttickPositioner = axis.options.tickPositioner,\n\t\t\tmaxPadding = options.maxPadding,\n\t\t\tminPadding = options.minPadding,\n\t\t\tlength,\n\t\t\tlinkedParentExtremes,\n\t\t\ttickIntervalOption = options.tickInterval,\n\t\t\tminTickIntervalOption = options.minTickInterval,\n\t\t\ttickPixelIntervalOption = options.tickPixelInterval,\n\t\t\ttickPositions,\n\t\t\tcategories = axis.categories;\n\n\t\t// linked axis gets the extremes from the parent axis\n\t\tif (isLinked) {\n\t\t\taxis.linkedParent = chart[isXAxis ? 'xAxis' : 'yAxis'][options.linkedTo];\n\t\t\tlinkedParentExtremes = axis.linkedParent.getExtremes();\n\t\t\taxis.min = pick(linkedParentExtremes.min, linkedParentExtremes.dataMin);\n\t\t\taxis.max = pick(linkedParentExtremes.max, linkedParentExtremes.dataMax);\n\t\t\tif (options.type !== axis.linkedParent.options.type) {\n\t\t\t\terror(11, 1); // Can't link axes of different type\n\t\t\t}\n\t\t} else { // initial min and max from the extreme data values\n\t\t\taxis.min = pick(axis.userMin, options.min, axis.dataMin);\n\t\t\taxis.max = pick(axis.userMax, options.max, axis.dataMax);\n\t\t}\n\n\t\tif (isLog) {\n\t\t\tif (!secondPass && mathMin(axis.min, pick(axis.dataMin, axis.min)) <= 0) { // #978\n\t\t\t\terror(10, 1); // Can't plot negative values on log axis\n\t\t\t}\n\t\t\taxis.min = correctFloat(log2lin(axis.min)); // correctFloat cures #934\n\t\t\taxis.max = correctFloat(log2lin(axis.max));\n\t\t}\n\n\t\t// handle zoomed range\n\t\tif (axis.range) {\n\t\t\taxis.userMin = axis.min = mathMax(axis.min, axis.max - axis.range); // #618\n\t\t\taxis.userMax = axis.max;\n\t\t\tif (secondPass) {\n\t\t\t\taxis.range = null;  // don't use it when running setExtremes\n\t\t\t}\n\t\t}\n\t\t\n\t\t// Hook for adjusting this.min and this.max. Used by bubble series.\n\t\tif (axis.beforePadding) {\n\t\t\taxis.beforePadding();\n\t\t}\n\n\t\t// adjust min and max for the minimum range\n\t\taxis.adjustForMinRange();\n\t\t\n\t\t// Pad the values to get clear of the chart's edges. To avoid tickInterval taking the padding\n\t\t// into account, we do this after computing tick interval (#1337).\n\t\tif (!categories && !axis.usePercentage && !isLinked && defined(axis.min) && defined(axis.max)) {\n\t\t\tlength = axis.max - axis.min;\n\t\t\tif (length) {\n\t\t\t\tif (!defined(options.min) && !defined(axis.userMin) && minPadding && (axis.dataMin < 0 || !axis.ignoreMinPadding)) {\n\t\t\t\t\taxis.min -= length * minPadding;\n\t\t\t\t}\n\t\t\t\tif (!defined(options.max) && !defined(axis.userMax)  && maxPadding && (axis.dataMax > 0 || !axis.ignoreMaxPadding)) {\n\t\t\t\t\taxis.max += length * maxPadding;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// get tickInterval\n\t\tif (axis.min === axis.max || axis.min === undefined || axis.max === undefined) {\n\t\t\taxis.tickInterval = 1;\n\t\t} else if (isLinked && !tickIntervalOption &&\n\t\t\t\ttickPixelIntervalOption === axis.linkedParent.options.tickPixelInterval) {\n\t\t\taxis.tickInterval = axis.linkedParent.tickInterval;\n\t\t} else {\n\t\t\taxis.tickInterval = pick(\n\t\t\t\ttickIntervalOption,\n\t\t\t\tcategories ? // for categoried axis, 1 is default, for linear axis use tickPix\n\t\t\t\t\t1 :\n\t\t\t\t\t(axis.max - axis.min) * tickPixelIntervalOption / (axis.len || 1)\n\t\t\t);\n\t\t}\n\n\t\t// Now we're finished detecting min and max, crop and group series data. This\n\t\t// is in turn needed in order to find tick positions in ordinal axes. \n\t\tif (isXAxis && !secondPass) {\n\t\t\teach(axis.series, function (series) {\n\t\t\t\tseries.processData(axis.min !== axis.oldMin || axis.max !== axis.oldMax);\n\t\t\t});\n\t\t}\n\n\t\t// set the translation factor used in translate function\n\t\taxis.setAxisTranslation(true);\n\n\t\t// hook for ordinal axes and radial axes\n\t\tif (axis.beforeSetTickPositions) {\n\t\t\taxis.beforeSetTickPositions();\n\t\t}\n\t\t\n\t\t// hook for extensions, used in Highstock ordinal axes\n\t\tif (axis.postProcessTickInterval) {\n\t\t\taxis.tickInterval = axis.postProcessTickInterval(axis.tickInterval);\n\t\t}\n\n\t\t// In column-like charts, don't cramp in more ticks than there are points (#1943)\n\t\tif (axis.pointRange) {\n\t\t\taxis.tickInterval = mathMax(axis.pointRange, axis.tickInterval);\n\t\t}\n\t\t\n\t\t// Before normalizing the tick interval, handle minimum tick interval. This applies only if tickInterval is not defined.\n\t\tif (!tickIntervalOption && axis.tickInterval < minTickIntervalOption) {\n\t\t\taxis.tickInterval = minTickIntervalOption;\n\t\t}\n\n\t\t// for linear axes, get magnitude and normalize the interval\n\t\tif (!isDatetimeAxis && !isLog) { // linear\n\t\t\tif (!tickIntervalOption) {\n\t\t\t\taxis.tickInterval = normalizeTickInterval(axis.tickInterval, null, getMagnitude(axis.tickInterval), options);\n\t\t\t}\n\t\t}\n\n\t\t// get minorTickInterval\n\t\taxis.minorTickInterval = options.minorTickInterval === 'auto' && axis.tickInterval ?\n\t\t\t\taxis.tickInterval / 5 : options.minorTickInterval;\n\n\t\t// find the tick positions\n\t\taxis.tickPositions = tickPositions = options.tickPositions ?\n\t\t\t[].concat(options.tickPositions) : // Work on a copy (#1565)\n\t\t\t(tickPositioner && tickPositioner.apply(axis, [axis.min, axis.max]));\n\t\tif (!tickPositions) {\n\t\t\tif (isDatetimeAxis) {\n\t\t\t\ttickPositions = (axis.getNonLinearTimeTicks || getTimeTicks)(\n\t\t\t\t\tnormalizeTimeTickInterval(axis.tickInterval, options.units),\n\t\t\t\t\taxis.min,\n\t\t\t\t\taxis.max,\n\t\t\t\t\toptions.startOfWeek,\n\t\t\t\t\taxis.ordinalPositions,\n\t\t\t\t\taxis.closestPointRange,\n\t\t\t\t\ttrue\n\t\t\t\t);\n\t\t\t} else if (isLog) {\n\t\t\t\ttickPositions = axis.getLogTickPositions(axis.tickInterval, axis.min, axis.max);\n\t\t\t} else {\n\t\t\t\ttickPositions = axis.getLinearTickPositions(axis.tickInterval, axis.min, axis.max);\n\t\t\t}\n\t\t\taxis.tickPositions = tickPositions;\n\t\t}\n\n\t\tif (!isLinked) {\n\n\t\t\t// reset min/max or remove extremes based on start/end on tick\n\t\t\tvar roundedMin = tickPositions[0],\n\t\t\t\troundedMax = tickPositions[tickPositions.length - 1],\n\t\t\t\tminPointOffset = axis.minPointOffset || 0,\n\t\t\t\tsinglePad;\n\n\t\t\tif (options.startOnTick) {\n\t\t\t\taxis.min = roundedMin;\n\t\t\t} else if (axis.min - minPointOffset > roundedMin) {\n\t\t\t\ttickPositions.shift();\n\t\t\t}\n\n\t\t\tif (options.endOnTick) {\n\t\t\t\taxis.max = roundedMax;\n\t\t\t} else if (axis.max + minPointOffset < roundedMax) {\n\t\t\t\ttickPositions.pop();\n\t\t\t}\n\t\t\t\n\t\t\t// When there is only one point, or all points have the same value on this axis, then min\n\t\t\t// and max are equal and tickPositions.length is 1. In this case, add some padding\n\t\t\t// in order to center the point, but leave it with one tick. #1337.\n\t\t\tif (tickPositions.length === 1) {\n\t\t\t\tsinglePad = 0.001; // The lowest possible number to avoid extra padding on columns\n\t\t\t\taxis.min -= singlePad;\n\t\t\t\taxis.max += singlePad;\n\t\t\t}\n\t\t}\n\t},\n\t\n\t/**\n\t * Set the max ticks of either the x and y axis collection\n\t */\n\tsetMaxTicks: function () {\n\t\t\n\t\tvar chart = this.chart,\n\t\t\tmaxTicks = chart.maxTicks || {},\n\t\t\ttickPositions = this.tickPositions,\n\t\t\tkey = this._maxTicksKey = [this.xOrY, this.pos, this.len].join('-');\n\t\t\n\t\tif (!this.isLinked && !this.isDatetimeAxis && tickPositions && tickPositions.length > (maxTicks[key] || 0) && this.options.alignTicks !== false) {\n\t\t\tmaxTicks[key] = tickPositions.length;\n\t\t}\n\t\tchart.maxTicks = maxTicks;\n\t},\n\n\t/**\n\t * When using multiple axes, adjust the number of ticks to match the highest\n\t * number of ticks in that group\n\t */\n\tadjustTickAmount: function () {\n\t\tvar axis = this,\n\t\t\tchart = axis.chart,\n\t\t\tkey = axis._maxTicksKey,\n\t\t\ttickPositions = axis.tickPositions,\n\t\t\tmaxTicks = chart.maxTicks;\n\n\t\tif (maxTicks && maxTicks[key] && !axis.isDatetimeAxis && !axis.categories && !axis.isLinked && axis.options.alignTicks !== false) { // only apply to linear scale\n\t\t\tvar oldTickAmount = axis.tickAmount,\n\t\t\t\tcalculatedTickAmount = tickPositions.length,\n\t\t\t\ttickAmount;\n\n\t\t\t// set the axis-level tickAmount to use below\n\t\t\taxis.tickAmount = tickAmount = maxTicks[key];\n\n\t\t\tif (calculatedTickAmount < tickAmount) {\n\t\t\t\twhile (tickPositions.length < tickAmount) {\n\t\t\t\t\ttickPositions.push(correctFloat(\n\t\t\t\t\t\ttickPositions[tickPositions.length - 1] + axis.tickInterval\n\t\t\t\t\t));\n\t\t\t\t}\n\t\t\t\taxis.transA *= (calculatedTickAmount - 1) / (tickAmount - 1);\n\t\t\t\taxis.max = tickPositions[tickPositions.length - 1];\n\n\t\t\t}\n\t\t\tif (defined(oldTickAmount) && tickAmount !== oldTickAmount) {\n\t\t\t\taxis.isDirty = true;\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Set the scale based on data min and max, user set min and max or options\n\t *\n\t */\n\tsetScale: function () {\n\t\tvar axis = this,\n\t\t\tstacks = axis.stacks,\n\t\t\ttype,\n\t\t\ti,\n\t\t\tisDirtyData,\n\t\t\tisDirtyAxisLength;\n\n\t\taxis.oldMin = axis.min;\n\t\taxis.oldMax = axis.max;\n\t\taxis.oldAxisLength = axis.len;\n\n\t\t// set the new axisLength\n\t\taxis.setAxisSize();\n\t\t//axisLength = horiz ? axisWidth : axisHeight;\n\t\tisDirtyAxisLength = axis.len !== axis.oldAxisLength;\n\n\t\t// is there new data?\n\t\teach(axis.series, function (series) {\n\t\t\tif (series.isDirtyData || series.isDirty ||\n\t\t\t\t\tseries.xAxis.isDirty) { // when x axis is dirty, we need new data extremes for y as well\n\t\t\t\tisDirtyData = true;\n\t\t\t}\n\t\t});\n\n\n\t\t// do we really need to go through all this?\n\t\tif (isDirtyAxisLength || isDirtyData || axis.isLinked || axis.forceRedraw ||\n\t\t\taxis.userMin !== axis.oldUserMin || axis.userMax !== axis.oldUserMax) {\n\t\t\t\n\t\t\t// reset stacks\n\t\t\tif (!axis.isXAxis) {\n\t\t\t\tfor (type in stacks) {\n\t\t\t\t\tfor (i in stacks[type]) {\n\t\t\t\t\t\tstacks[type][i].total = null;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\taxis.forceRedraw = false;\n\n\t\t\t// get data extremes if needed\n\t\t\taxis.getSeriesExtremes();\n\n\t\t\t// get fixed positions based on tickInterval\n\t\t\taxis.setTickPositions();\n\n\t\t\t// record old values to decide whether a rescale is necessary later on (#540)\n\t\t\taxis.oldUserMin = axis.userMin;\n\t\t\taxis.oldUserMax = axis.userMax;\n\n\t\t\t// Mark as dirty if it is not already set to dirty and extremes have changed. #595.\n\t\t\tif (!axis.isDirty) {\n\t\t\t\taxis.isDirty = isDirtyAxisLength || axis.min !== axis.oldMin || axis.max !== axis.oldMax;\n\t\t\t}\n\t\t} else if (!axis.isXAxis) {\n\t\t\tif (axis.oldStacks) {\n\t\t\t\tstacks = axis.stacks = axis.oldStacks;\n\t\t\t}\n\n\t\t\t// reset stacks\n\t\t\tfor (type in stacks) {\n\t\t\t\tfor (i in stacks[type]) {\n\t\t\t\t\tstacks[type][i].cum = stacks[type][i].total;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\t// Set the maximum tick amount\n\t\taxis.setMaxTicks();\n\t},\n\n\t/**\n\t * Set the extremes and optionally redraw\n\t * @param {Number} newMin\n\t * @param {Number} newMax\n\t * @param {Boolean} redraw\n\t * @param {Boolean|Object} animation Whether to apply animation, and optionally animation\n\t *    configuration\n\t * @param {Object} eventArguments \n\t *\n\t */\n\tsetExtremes: function (newMin, newMax, redraw, animation, eventArguments) {\n\t\tvar axis = this,\n\t\t\tchart = axis.chart;\n\n\t\tredraw = pick(redraw, true); // defaults to true\n\n\t\t// Extend the arguments with min and max\n\t\teventArguments = extend(eventArguments, {\n\t\t\tmin: newMin,\n\t\t\tmax: newMax\n\t\t});\n\n\t\t// Fire the event\n\t\tfireEvent(axis, 'setExtremes', eventArguments, function () { // the default event handler\n\n\t\t\taxis.userMin = newMin;\n\t\t\taxis.userMax = newMax;\n\n\t\t\t// Mark for running afterSetExtremes\n\t\t\taxis.isDirtyExtremes = true;\n\n\t\t\t// redraw\n\t\t\tif (redraw) {\n\t\t\t\tchart.redraw(animation);\n\t\t\t}\n\t\t});\n\t},\n\t\n\t/**\n\t * Overridable method for zooming chart. Pulled out in a separate method to allow overriding\n\t * in stock charts.\n\t */\n\tzoom: function (newMin, newMax) {\n\n\t\t// Prevent pinch zooming out of range. Check for defined is for #1946.\n\t\tif (!this.allowZoomOutside) {\n\t\t\tif (defined(this.dataMin) && newMin <= this.dataMin) {\n\t\t\t\tnewMin = UNDEFINED;\n\t\t\t}\n\t\t\tif (defined(this.dataMax) && newMax >= this.dataMax) {\n\t\t\t\tnewMax = UNDEFINED;\n\t\t\t}\n\t\t}\n\n\t\t// In full view, displaying the reset zoom button is not required\n\t\tthis.displayBtn = newMin !== UNDEFINED || newMax !== UNDEFINED;\n\t\t\n\t\t// Do it\n\t\tthis.setExtremes(\n\t\t\tnewMin,\n\t\t\tnewMax,\n\t\t\tfalse, \n\t\t\tUNDEFINED, \n\t\t\t{ trigger: 'zoom' }\n\t\t);\n\t\treturn true;\n\t},\n\t\n\t/**\n\t * Update the axis metrics\n\t */\n\tsetAxisSize: function () {\n\t\tvar chart = this.chart,\n\t\t\toptions = this.options,\n\t\t\toffsetLeft = options.offsetLeft || 0,\n\t\t\toffsetRight = options.offsetRight || 0,\n\t\t\thoriz = this.horiz,\n\t\t\twidth,\n\t\t\theight,\n\t\t\ttop,\n\t\t\tleft;\n\n\t\t// Expose basic values to use in Series object and navigator\n\t\tthis.left = left = pick(options.left, chart.plotLeft + offsetLeft);\n\t\tthis.top = top = pick(options.top, chart.plotTop);\n\t\tthis.width = width = pick(options.width, chart.plotWidth - offsetLeft + offsetRight);\n\t\tthis.height = height = pick(options.height, chart.plotHeight);\n\t\tthis.bottom = chart.chartHeight - height - top;\n\t\tthis.right = chart.chartWidth - width - left;\n\n\t\t// Direction agnostic properties\n\t\tthis.len = mathMax(horiz ? width : height, 0); // mathMax fixes #905\n\t\tthis.pos = horiz ? left : top; // distance from SVG origin\n\t},\n\n\t/**\n\t * Get the actual axis extremes\n\t */\n\tgetExtremes: function () {\n\t\tvar axis = this,\n\t\t\tisLog = axis.isLog;\n\n\t\treturn {\n\t\t\tmin: isLog ? correctFloat(lin2log(axis.min)) : axis.min,\n\t\t\tmax: isLog ? correctFloat(lin2log(axis.max)) : axis.max,\n\t\t\tdataMin: axis.dataMin,\n\t\t\tdataMax: axis.dataMax,\n\t\t\tuserMin: axis.userMin,\n\t\t\tuserMax: axis.userMax\n\t\t};\n\t},\n\n\t/**\n\t * Get the zero plane either based on zero or on the min or max value.\n\t * Used in bar and area plots\n\t */\n\tgetThreshold: function (threshold) {\n\t\tvar axis = this,\n\t\t\tisLog = axis.isLog;\n\n\t\tvar realMin = isLog ? lin2log(axis.min) : axis.min,\n\t\t\trealMax = isLog ? lin2log(axis.max) : axis.max;\n\t\t\n\t\tif (realMin > threshold || threshold === null) {\n\t\t\tthreshold = realMin;\n\t\t} else if (realMax < threshold) {\n\t\t\tthreshold = realMax;\n\t\t}\n\n\t\treturn axis.translate(threshold, 0, 1, 0, 1);\n\t},\n\n\taddPlotBand: function (options) {\n\t\tthis.addPlotBandOrLine(options, 'plotBands');\n\t},\n\t\n\taddPlotLine: function (options) {\n\t\tthis.addPlotBandOrLine(options, 'plotLines');\n\t},\n\n\t/**\n\t * Add a plot band or plot line after render time\n\t *\n\t * @param options {Object} The plotBand or plotLine configuration object\n\t */\n\taddPlotBandOrLine: function (options, coll) {\n\t\tvar obj = new PlotLineOrBand(this, options).render(),\n\t\t\tuserOptions = this.userOptions;\n\n\t\t// Add it to the user options for exporting and Axis.update\n\t\tif (coll) {\n\t\t\tuserOptions[coll] = userOptions[coll] || [];\n\t\t\tuserOptions[coll].push(options); \n\t\t}\n\t\t\n\t\tthis.plotLinesAndBands.push(obj); \n\t\t\n\t\treturn obj;\n\t},\n\n\t/**\n\t * Compute auto alignment for the axis label based on which side the axis is on \n\t * and the given rotation for the label\n\t */\n\tautoLabelAlign: function (rotation) {\n\t\tvar ret, \n\t\t\tangle = (pick(rotation, 0) - (this.side * 90) + 720) % 360;\n\n\t\tif (angle > 15 && angle < 165) {\n\t\t\tret = 'right';\n\t\t} else if (angle > 195 && angle < 345) {\n\t\t\tret = 'left';\n\t\t} else {\n\t\t\tret = 'center';\n\t\t}\n\t\treturn ret;\n\t},\n\n\t/**\n\t * Render the tick labels to a preliminary position to get their sizes\n\t */\n\tgetOffset: function () {\n\t\tvar axis = this,\n\t\t\tchart = axis.chart,\n\t\t\trenderer = chart.renderer,\n\t\t\toptions = axis.options,\n\t\t\ttickPositions = axis.tickPositions,\n\t\t\tticks = axis.ticks,\n\t\t\thoriz = axis.horiz,\n\t\t\tside = axis.side,\n\t\t\tinvertedSide = chart.inverted ? [1, 0, 3, 2][side] : side,\n\t\t\thasData,\n\t\t\tshowAxis,\n\t\t\ttitleOffset = 0,\n\t\t\ttitleOffsetOption,\n\t\t\ttitleMargin = 0,\n\t\t\taxisTitleOptions = options.title,\n\t\t\tlabelOptions = options.labels,\n\t\t\tlabelOffset = 0, // reset\n\t\t\taxisOffset = chart.axisOffset,\n\t\t\tclipOffset = chart.clipOffset,\n\t\t\tdirectionFactor = [-1, 1, 1, -1][side],\n\t\t\tn,\n\t\t\ti,\n\t\t\tautoStaggerLines = 1,\n\t\t\tmaxStaggerLines = pick(labelOptions.maxStaggerLines, 5), // docs\n\t\t\tlastRight,\n\t\t\toverlap,\n\t\t\tpos,\n\t\t\tbBox,\n\t\t\tx,\n\t\t\tw,\n\t\t\tlineNo;\n\t\t\t\n\t\t// For reuse in Axis.render\n\t\taxis.hasData = hasData = (axis.hasVisibleSeries || (defined(axis.min) && defined(axis.max) && !!tickPositions));\n\t\taxis.showAxis = showAxis = hasData || pick(options.showEmpty, true);\n\n\t\t// Set/reset staggerLines\n\t\taxis.staggerLines = axis.horiz && labelOptions.staggerLines;\n\t\t\n\t\t// Create the axisGroup and gridGroup elements on first iteration\n\t\tif (!axis.axisGroup) {\n\t\t\taxis.gridGroup = renderer.g('grid')\n\t\t\t\t.attr({ zIndex: options.gridZIndex || 1 })\n\t\t\t\t.add();\n\t\t\taxis.axisGroup = renderer.g('axis')\n\t\t\t\t.attr({ zIndex: options.zIndex || 2 })\n\t\t\t\t.add();\n\t\t\taxis.labelGroup = renderer.g('axis-labels')\n\t\t\t\t.attr({ zIndex: labelOptions.zIndex || 7 })\n\t\t\t\t.add();\n\t\t}\n\n\t\tif (hasData || axis.isLinked) {\n\t\t\t\n\t\t\t// Set the explicit or automatic label alignment\n\t\t\taxis.labelAlign = pick(labelOptions.align || axis.autoLabelAlign(labelOptions.rotation));\n\n\t\t\teach(tickPositions, function (pos) {\n\t\t\t\tif (!ticks[pos]) {\n\t\t\t\t\tticks[pos] = new Tick(axis, pos);\n\t\t\t\t} else {\n\t\t\t\t\tticks[pos].addLabel(); // update labels depending on tick interval\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// Handle automatic stagger lines\n\t\t\tif (axis.horiz && !axis.staggerLines && maxStaggerLines && !labelOptions.rotation) {\n\t\t\t\twhile (autoStaggerLines < maxStaggerLines) {\n\t\t\t\t\tlastRight = [];\n\t\t\t\t\toverlap = false;\n\t\t\t\t\t\n\t\t\t\t\tfor (i = 0; i < tickPositions.length; i++) {\n\t\t\t\t\t\tpos = tickPositions[i];\n\t\t\t\t\t\tbBox = ticks[pos].label && ticks[pos].label.bBox;\n\t\t\t\t\t\tw = bBox ? bBox.width : 0;\n\t\t\t\t\t\tlineNo = i % autoStaggerLines;\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (w) {\n\t\t\t\t\t\t\tx = axis.translate(pos); // don't handle log\n\t\t\t\t\t\t\tif (lastRight[lineNo] !== UNDEFINED && x < lastRight[lineNo]) {\n\t\t\t\t\t\t\t\toverlap = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tlastRight[lineNo] = x + w;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (overlap) {\n\t\t\t\t\t\tautoStaggerLines++;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (autoStaggerLines > 1) {\n\t\t\t\t\taxis.staggerLines = autoStaggerLines;\n\t\t\t\t}\n\t\t\t}\n\n\n\t\t\teach(tickPositions, function (pos) {\n\t\t\t\t// left side must be align: right and right side must have align: left for labels\n\t\t\t\tif (side === 0 || side === 2 || { 1: 'left', 3: 'right' }[side] === axis.labelAlign) {\n\n\t\t\t\t\t// get the highest offset\n\t\t\t\t\tlabelOffset = mathMax(\n\t\t\t\t\t\tticks[pos].getLabelSize(),\n\t\t\t\t\t\tlabelOffset\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t});\n\t\t\tif (axis.staggerLines) {\n\t\t\t\tlabelOffset *= axis.staggerLines;\n\t\t\t\taxis.labelOffset = labelOffset;\n\t\t\t}\n\t\t\t\n\n\t\t} else { // doesn't have data\n\t\t\tfor (n in ticks) {\n\t\t\t\tticks[n].destroy();\n\t\t\t\tdelete ticks[n];\n\t\t\t}\n\t\t}\n\n\t\tif (axisTitleOptions && axisTitleOptions.text && axisTitleOptions.enabled !== false) { \n\t\t\tif (!axis.axisTitle) {\n\t\t\t\taxis.axisTitle = renderer.text(\n\t\t\t\t\taxisTitleOptions.text,\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t\taxisTitleOptions.useHTML\n\t\t\t\t)\n\t\t\t\t.attr({\n\t\t\t\t\tzIndex: 7,\n\t\t\t\t\trotation: axisTitleOptions.rotation || 0,\n\t\t\t\t\talign:\n\t\t\t\t\t\taxisTitleOptions.textAlign ||\n\t\t\t\t\t\t{ low: 'left', middle: 'center', high: 'right' }[axisTitleOptions.align]\n\t\t\t\t})\n\t\t\t\t.css(axisTitleOptions.style)\n\t\t\t\t.add(axis.axisGroup);\n\t\t\t\taxis.axisTitle.isNew = true;\n\t\t\t}\n\n\t\t\tif (showAxis) {\n\t\t\t\ttitleOffset = axis.axisTitle.getBBox()[horiz ? 'height' : 'width'];\n\t\t\t\ttitleMargin = pick(axisTitleOptions.margin, horiz ? 5 : 10);\n\t\t\t\ttitleOffsetOption = axisTitleOptions.offset;\n\t\t\t}\n\n\t\t\t// hide or show the title depending on whether showEmpty is set\n\t\t\taxis.axisTitle[showAxis ? 'show' : 'hide']();\n\t\t}\n\t\t\n\t\t// handle automatic or user set offset\n\t\taxis.offset = directionFactor * pick(options.offset, axisOffset[side]);\n\t\t\n\t\taxis.axisTitleMargin =\n\t\t\tpick(titleOffsetOption,\n\t\t\t\tlabelOffset + titleMargin +\n\t\t\t\t(side !== 2 && labelOffset && directionFactor * options.labels[horiz ? 'y' : 'x'])\n\t\t\t);\n\n\t\taxisOffset[side] = mathMax(\n\t\t\taxisOffset[side],\n\t\t\taxis.axisTitleMargin + titleOffset + directionFactor * axis.offset\n\t\t);\n\t\tclipOffset[invertedSide] = mathMax(clipOffset[invertedSide], options.lineWidth);\n\n\t},\n\t\n\t/**\n\t * Get the path for the axis line\n\t */\n\tgetLinePath: function (lineWidth) {\n\t\tvar chart = this.chart,\n\t\t\topposite = this.opposite,\n\t\t\toffset = this.offset,\n\t\t\thoriz = this.horiz,\n\t\t\tlineLeft = this.left + (opposite ? this.width : 0) + offset,\n\t\t\tlineTop = chart.chartHeight - this.bottom - (opposite ? this.height : 0) + offset;\n\t\t\t\n\t\tthis.lineTop = lineTop; // used by flag series\n\t\tif (!opposite) {\n\t\t\tlineWidth *= -1; // crispify the other way - #1480\n\t\t}\n\n\t\treturn chart.renderer.crispLine([\n\t\t\t\tM,\n\t\t\t\thoriz ?\n\t\t\t\t\tthis.left :\n\t\t\t\t\tlineLeft,\n\t\t\t\thoriz ?\n\t\t\t\t\tlineTop :\n\t\t\t\t\tthis.top,\n\t\t\t\tL,\n\t\t\t\thoriz ?\n\t\t\t\t\tchart.chartWidth - this.right :\n\t\t\t\t\tlineLeft,\n\t\t\t\thoriz ?\n\t\t\t\t\tlineTop :\n\t\t\t\t\tchart.chartHeight - this.bottom\n\t\t\t], lineWidth);\n\t},\n\t\n\t/**\n\t * Position the title\n\t */\n\tgetTitlePosition: function () {\n\t\t// compute anchor points for each of the title align options\n\t\tvar horiz = this.horiz,\n\t\t\taxisLeft = this.left,\n\t\t\taxisTop = this.top,\n\t\t\taxisLength = this.len,\n\t\t\taxisTitleOptions = this.options.title,\t\t\t\n\t\t\tmargin = horiz ? axisLeft : axisTop,\n\t\t\topposite = this.opposite,\n\t\t\toffset = this.offset,\n\t\t\tfontSize = pInt(axisTitleOptions.style.fontSize || 12),\n\t\t\t\n\t\t\t// the position in the length direction of the axis\n\t\t\talongAxis = {\n\t\t\t\tlow: margin + (horiz ? 0 : axisLength),\n\t\t\t\tmiddle: margin + axisLength / 2,\n\t\t\t\thigh: margin + (horiz ? axisLength : 0)\n\t\t\t}[axisTitleOptions.align],\n\t\n\t\t\t// the position in the perpendicular direction of the axis\n\t\t\toffAxis = (horiz ? axisTop + this.height : axisLeft) +\n\t\t\t\t(horiz ? 1 : -1) * // horizontal axis reverses the margin\n\t\t\t\t(opposite ? -1 : 1) * // so does opposite axes\n\t\t\t\tthis.axisTitleMargin +\n\t\t\t\t(this.side === 2 ? fontSize : 0);\n\n\t\treturn {\n\t\t\tx: horiz ?\n\t\t\t\talongAxis :\n\t\t\t\toffAxis + (opposite ? this.width : 0) + offset +\n\t\t\t\t\t(axisTitleOptions.x || 0), // x\n\t\t\ty: horiz ?\n\t\t\t\toffAxis - (opposite ? this.height : 0) + offset :\n\t\t\t\talongAxis + (axisTitleOptions.y || 0) // y\n\t\t};\n\t},\n\t\n\t/**\n\t * Render the axis\n\t */\n\trender: function () {\n\t\tvar axis = this,\n\t\t\tchart = axis.chart,\n\t\t\trenderer = chart.renderer,\n\t\t\toptions = axis.options,\n\t\t\tisLog = axis.isLog,\n\t\t\tisLinked = axis.isLinked,\n\t\t\ttickPositions = axis.tickPositions,\n\t\t\taxisTitle = axis.axisTitle,\n\t\t\tstacks = axis.stacks,\n\t\t\tticks = axis.ticks,\n\t\t\tminorTicks = axis.minorTicks,\n\t\t\talternateBands = axis.alternateBands,\n\t\t\tstackLabelOptions = options.stackLabels,\n\t\t\talternateGridColor = options.alternateGridColor,\n\t\t\ttickmarkOffset = axis.tickmarkOffset,\n\t\t\tlineWidth = options.lineWidth,\n\t\t\tlinePath,\n\t\t\thasRendered = chart.hasRendered,\n\t\t\tslideInTicks = hasRendered && defined(axis.oldMin) && !isNaN(axis.oldMin),\n\t\t\thasData = axis.hasData,\n\t\t\tshowAxis = axis.showAxis,\n\t\t\tfrom,\n\t\t\tto;\n\n\t\t// Mark all elements inActive before we go over and mark the active ones\n\t\teach([ticks, minorTicks, alternateBands], function (coll) {\n\t\t\tvar pos;\n\t\t\tfor (pos in coll) {\n\t\t\t\tcoll[pos].isActive = false;\n\t\t\t}\n\t\t});\n\n\t\t// If the series has data draw the ticks. Else only the line and title\n\t\tif (hasData || isLinked) {\n\n\t\t\t// minor ticks\n\t\t\tif (axis.minorTickInterval && !axis.categories) {\n\t\t\t\teach(axis.getMinorTickPositions(), function (pos) {\n\t\t\t\t\tif (!minorTicks[pos]) {\n\t\t\t\t\t\tminorTicks[pos] = new Tick(axis, pos, 'minor');\n\t\t\t\t\t}\n\n\t\t\t\t\t// render new ticks in old position\n\t\t\t\t\tif (slideInTicks && minorTicks[pos].isNew) {\n\t\t\t\t\t\tminorTicks[pos].render(null, true);\n\t\t\t\t\t}\n\n\t\t\t\t\tminorTicks[pos].render(null, false, 1);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Major ticks. Pull out the first item and render it last so that\n\t\t\t// we can get the position of the neighbour label. #808.\n\t\t\tif (tickPositions.length) { // #1300\n\t\t\t\teach(tickPositions.slice(1).concat([tickPositions[0]]), function (pos, i) {\n\t\n\t\t\t\t\t// Reorganize the indices\n\t\t\t\t\ti = (i === tickPositions.length - 1) ? 0 : i + 1;\n\t\n\t\t\t\t\t// linked axes need an extra check to find out if\n\t\t\t\t\tif (!isLinked || (pos >= axis.min && pos <= axis.max)) {\n\t\n\t\t\t\t\t\tif (!ticks[pos]) {\n\t\t\t\t\t\t\tticks[pos] = new Tick(axis, pos);\n\t\t\t\t\t\t}\n\t\n\t\t\t\t\t\t// render new ticks in old position\n\t\t\t\t\t\tif (slideInTicks && ticks[pos].isNew) {\n\t\t\t\t\t\t\tticks[pos].render(i, true);\n\t\t\t\t\t\t}\n\t\n\t\t\t\t\t\tticks[pos].render(i, false, 1);\n\t\t\t\t\t}\n\t\n\t\t\t\t});\n\t\t\t\t// In a categorized axis, the tick marks are displayed between labels. So\n\t\t\t\t// we need to add a tick mark and grid line at the left edge of the X axis.\n\t\t\t\tif (tickmarkOffset && axis.min === 0) {\n\t\t\t\t\tif (!ticks[-1]) {\n\t\t\t\t\t\tticks[-1] = new Tick(axis, -1, null, true);\n\t\t\t\t\t}\n\t\t\t\t\tticks[-1].render(-1);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t}\n\n\t\t\t// alternate grid color\n\t\t\tif (alternateGridColor) {\n\t\t\t\teach(tickPositions, function (pos, i) {\n\t\t\t\t\tif (i % 2 === 0 && pos < axis.max) {\n\t\t\t\t\t\tif (!alternateBands[pos]) {\n\t\t\t\t\t\t\talternateBands[pos] = new PlotLineOrBand(axis);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfrom = pos + tickmarkOffset; // #949\n\t\t\t\t\t\tto = tickPositions[i + 1] !== UNDEFINED ? tickPositions[i + 1] + tickmarkOffset : axis.max;\n\t\t\t\t\t\talternateBands[pos].options = {\n\t\t\t\t\t\t\tfrom: isLog ? lin2log(from) : from,\n\t\t\t\t\t\t\tto: isLog ? lin2log(to) : to,\n\t\t\t\t\t\t\tcolor: alternateGridColor\n\t\t\t\t\t\t};\n\t\t\t\t\t\talternateBands[pos].render();\n\t\t\t\t\t\talternateBands[pos].isActive = true;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// custom plot lines and bands\n\t\t\tif (!axis._addedPlotLB) { // only first time\n\t\t\t\teach((options.plotLines || []).concat(options.plotBands || []), function (plotLineOptions) {\n\t\t\t\t\taxis.addPlotBandOrLine(plotLineOptions);\n\t\t\t\t});\n\t\t\t\taxis._addedPlotLB = true;\n\t\t\t}\n\n\t\t} // end if hasData\n\n\t\t// Remove inactive ticks\n\t\teach([ticks, minorTicks, alternateBands], function (coll) {\n\t\t\tvar pos, \n\t\t\t\ti,\n\t\t\t\tforDestruction = [],\n\t\t\t\tdelay = globalAnimation ? globalAnimation.duration || 500 : 0,\n\t\t\t\tdestroyInactiveItems = function () {\n\t\t\t\t\ti = forDestruction.length;\n\t\t\t\t\twhile (i--) {\n\t\t\t\t\t\t// When resizing rapidly, the same items may be destroyed in different timeouts,\n\t\t\t\t\t\t// or the may be reactivated\n\t\t\t\t\t\tif (coll[forDestruction[i]] && !coll[forDestruction[i]].isActive) {\n\t\t\t\t\t\t\tcoll[forDestruction[i]].destroy();\n\t\t\t\t\t\t\tdelete coll[forDestruction[i]];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t};\n\n\t\t\tfor (pos in coll) {\n\n\t\t\t\tif (!coll[pos].isActive) {\n\t\t\t\t\t// Render to zero opacity\n\t\t\t\t\tcoll[pos].render(pos, false, 0);\n\t\t\t\t\tcoll[pos].isActive = false;\n\t\t\t\t\tforDestruction.push(pos);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// When the objects are finished fading out, destroy them\n\t\t\tif (coll === alternateBands || !chart.hasRendered || !delay) {\n\t\t\t\tdestroyInactiveItems();\n\t\t\t} else if (delay) {\n\t\t\t\tsetTimeout(destroyInactiveItems, delay);\n\t\t\t}\n\t\t});\n\n\t\t// Static items. As the axis group is cleared on subsequent calls\n\t\t// to render, these items are added outside the group.\n\t\t// axis line\n\t\tif (lineWidth) {\n\t\t\tlinePath = axis.getLinePath(lineWidth);\n\t\t\tif (!axis.axisLine) {\n\t\t\t\taxis.axisLine = renderer.path(linePath)\n\t\t\t\t\t.attr({\n\t\t\t\t\t\tstroke: options.lineColor,\n\t\t\t\t\t\t'stroke-width': lineWidth,\n\t\t\t\t\t\tzIndex: 7\n\t\t\t\t\t})\n\t\t\t\t\t.add(axis.axisGroup);\n\t\t\t} else {\n\t\t\t\taxis.axisLine.animate({ d: linePath });\n\t\t\t}\n\n\t\t\t// show or hide the line depending on options.showEmpty\n\t\t\taxis.axisLine[showAxis ? 'show' : 'hide']();\n\t\t}\n\n\t\tif (axisTitle && showAxis) {\n\t\t\t\n\t\t\taxisTitle[axisTitle.isNew ? 'attr' : 'animate'](\n\t\t\t\taxis.getTitlePosition()\n\t\t\t);\n\t\t\taxisTitle.isNew = false;\n\t\t}\n\n\t\t// Stacked totals:\n\t\tif (stackLabelOptions && stackLabelOptions.enabled) {\n\t\t\tvar stackKey, oneStack, stackCategory,\n\t\t\t\tstackTotalGroup = axis.stackTotalGroup;\n\n\t\t\t// Create a separate group for the stack total labels\n\t\t\tif (!stackTotalGroup) {\n\t\t\t\taxis.stackTotalGroup = stackTotalGroup =\n\t\t\t\t\trenderer.g('stack-labels')\n\t\t\t\t\t\t.attr({\n\t\t\t\t\t\t\tvisibility: VISIBLE,\n\t\t\t\t\t\t\tzIndex: 6\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.add();\n\t\t\t}\n\n\t\t\t// plotLeft/Top will change when y axis gets wider so we need to translate the\n\t\t\t// stackTotalGroup at every render call. See bug #506 and #516\n\t\t\tstackTotalGroup.translate(chart.plotLeft, chart.plotTop);\n\n\t\t\t// Render each stack total\n\t\t\tfor (stackKey in stacks) {\n\t\t\t\toneStack = stacks[stackKey];\n\t\t\t\tfor (stackCategory in oneStack) {\n\t\t\t\t\toneStack[stackCategory].render(stackTotalGroup);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// End stacked totals\n\n\t\taxis.isDirty = false;\n\t},\n\n\t/**\n\t * Remove a plot band or plot line from the chart by id\n\t * @param {Object} id\n\t */\n\tremovePlotBandOrLine: function (id) {\n\t\tvar plotLinesAndBands = this.plotLinesAndBands,\n\t\t\toptions = this.options,\n\t\t\tuserOptions = this.userOptions,\n\t\t\ti = plotLinesAndBands.length;\n\t\twhile (i--) {\n\t\t\tif (plotLinesAndBands[i].id === id) {\n\t\t\t\tplotLinesAndBands[i].destroy();\n\t\t\t}\n\t\t}\n\t\teach([options.plotLines || [], userOptions.plotLines || [], options.plotBands || [], userOptions.plotBands || []], function (arr) {\n\t\t\ti = arr.length;\n\t\t\twhile (i--) {\n\t\t\t\tif (arr[i].id === id) {\n\t\t\t\t\terase(arr, arr[i]);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t},\n\n\t/**\n\t * Update the axis title by options\n\t */\n\tsetTitle: function (newTitleOptions, redraw) {\n\t\tthis.update({ title: newTitleOptions }, redraw);\n\t},\n\n\t/**\n\t * Redraw the axis to reflect changes in the data or axis extremes\n\t */\n\tredraw: function () {\n\t\tvar axis = this,\n\t\t\tchart = axis.chart,\n\t\t\tpointer = chart.pointer;\n\n\t\t// hide tooltip and hover states\n\t\tif (pointer.reset) {\n\t\t\tpointer.reset(true);\n\t\t}\n\n\t\t// render the axis\n\t\taxis.render();\n\n\t\t// move plot lines and bands\n\t\teach(axis.plotLinesAndBands, function (plotLine) {\n\t\t\tplotLine.render();\n\t\t});\n\n\t\t// mark associated series as dirty and ready for redraw\n\t\teach(axis.series, function (series) {\n\t\t\tseries.isDirty = true;\n\t\t});\n\n\t},\n\n\t/**\n\t *\n\t */\n\tbuildStacks: function () {\n\t\tif (this.isXAxis) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar series = this.series,\n\t\t\t\tlast = series.length - 1;\n\n\t\teach(series, function (serie, i) {\n\t\t\tserie.setStackedPoints(i === last);\n\t\t});\n\t},\n\n\t/**\n\t * Set new axis categories and optionally redraw\n\t * @param {Array} categories\n\t * @param {Boolean} redraw\n\t */\n\tsetCategories: function (categories, redraw) {\n\t\tthis.update({ categories: categories }, redraw);\n\t},\n\n\t/**\n\t * Destroys an Axis instance.\n\t */\n\tdestroy: function (keepEvents) {\n\t\tvar axis = this,\n\t\t\tstacks = axis.stacks,\n\t\t\tstackKey;\n\n\t\t// Remove the events\n\t\tif (!keepEvents) {\n\t\t\tremoveEvent(axis);\n\t\t}\n\n\t\t// Destroy each stack total\n\t\tfor (stackKey in stacks) {\n\t\t\tdestroyObjectProperties(stacks[stackKey]);\n\n\t\t\tstacks[stackKey] = null;\n\t\t}\n\n\t\t// Destroy collections\n\t\teach([axis.ticks, axis.minorTicks, axis.alternateBands, axis.plotLinesAndBands], function (coll) {\n\t\t\tdestroyObjectProperties(coll);\n\t\t});\n\n\t\t// Destroy local variables\n\t\teach(['stackTotalGroup', 'axisLine', 'axisGroup', 'gridGroup', 'labelGroup', 'axisTitle'], function (prop) {\n\t\t\tif (axis[prop]) {\n\t\t\t\taxis[prop] = axis[prop].destroy();\n\t\t\t}\n\t\t});\n\t}\n\n\t\n}; // end Axis\n\n/**\n * The tooltip object\n * @param {Object} chart The chart instance\n * @param {Object} options Tooltip options\n */\nfunction Tooltip() {\n\tthis.init.apply(this, arguments);\n}\n\nTooltip.prototype = {\n\n\tinit: function (chart, options) {\n\n\t\tvar borderWidth = options.borderWidth,\n\t\t\tstyle = options.style,\n\t\t\tpadding = pInt(style.padding);\n\n\t\t// Save the chart and options\n\t\tthis.chart = chart;\n\t\tthis.options = options;\n\n\t\t// Keep track of the current series\n\t\t//this.currentSeries = UNDEFINED;\n\n\t\t// List of crosshairs\n\t\tthis.crosshairs = [];\n\n\t\t// Current values of x and y when animating\n\t\tthis.now = { x: 0, y: 0 };\n\n\t\t// The tooltip is initially hidden\n\t\tthis.isHidden = true;\n\n\n\t\t// create the label\n\t\tthis.label = chart.renderer.label('', 0, 0, options.shape, null, null, options.useHTML, null, 'tooltip')\n\t\t\t.attr({\n\t\t\t\tpadding: padding,\n\t\t\t\tfill: options.backgroundColor,\n\t\t\t\t'stroke-width': borderWidth,\n\t\t\t\tr: options.borderRadius,\n\t\t\t\tzIndex: 8\n\t\t\t})\n\t\t\t.css(style)\n\t\t\t.css({ padding: 0 }) // Remove it from VML, the padding is applied as an attribute instead (#1117)\n\t\t\t.hide()\n\t\t\t.add();\n\n\t\t// When using canVG the shadow shows up as a gray circle\n\t\t// even if the tooltip is hidden.\n\t\tif (!useCanVG) {\n\t\t\tthis.label.shadow(options.shadow);\n\t\t}\n\n\t\t// Public property for getting the shared state.\n\t\tthis.shared = options.shared;\n\t},\n\n\t/**\n\t * Destroy the tooltip and its elements.\n\t */\n\tdestroy: function () {\n\t\teach(this.crosshairs, function (crosshair) {\n\t\t\tif (crosshair) {\n\t\t\t\tcrosshair.destroy();\n\t\t\t}\n\t\t});\n\n\t\t// Destroy and clear local variables\n\t\tif (this.label) {\n\t\t\tthis.label = this.label.destroy();\n\t\t}\n\t\tclearTimeout(this.hideTimer);\n\t\tclearTimeout(this.tooltipTimeout);\n\t},\n\n\t/**\n\t * Provide a soft movement for the tooltip\n\t *\n\t * @param {Number} x\n\t * @param {Number} y\n\t * @private\n\t */\n\tmove: function (x, y, anchorX, anchorY) {\n\t\tvar tooltip = this,\n\t\t\tnow = tooltip.now,\n\t\t\tanimate = tooltip.options.animation !== false && !tooltip.isHidden;\n\n\t\t// get intermediate values for animation\n\t\textend(now, {\n\t\t\tx: animate ? (2 * now.x + x) / 3 : x,\n\t\t\ty: animate ? (now.y + y) / 2 : y,\n\t\t\tanchorX: animate ? (2 * now.anchorX + anchorX) / 3 : anchorX,\n\t\t\tanchorY: animate ? (now.anchorY + anchorY) / 2 : anchorY\n\t\t});\n\n\t\t// move to the intermediate value\n\t\ttooltip.label.attr(now);\n\n\t\t\n\t\t// run on next tick of the mouse tracker\n\t\tif (animate && (mathAbs(x - now.x) > 1 || mathAbs(y - now.y) > 1)) {\n\t\t\n\t\t\t// never allow two timeouts\n\t\t\tclearTimeout(this.tooltipTimeout);\n\t\t\t\n\t\t\t// set the fixed interval ticking for the smooth tooltip\n\t\t\tthis.tooltipTimeout = setTimeout(function () {\n\t\t\t\t// The interval function may still be running during destroy, so check that the chart is really there before calling.\n\t\t\t\tif (tooltip) {\n\t\t\t\t\ttooltip.move(x, y, anchorX, anchorY);\n\t\t\t\t}\n\t\t\t}, 32);\n\t\t\t\n\t\t}\n\t},\n\n\t/**\n\t * Hide the tooltip\n\t */\n\thide: function () {\n\t\tvar tooltip = this,\n\t\t\thoverPoints;\n\t\t\n\t\tclearTimeout(this.hideTimer); // disallow duplicate timers (#1728, #1766)\n\t\tif (!this.isHidden) {\n\t\t\thoverPoints = this.chart.hoverPoints;\n\n\t\t\tthis.hideTimer = setTimeout(function () {\n\t\t\t\ttooltip.label.fadeOut();\n\t\t\t\ttooltip.isHidden = true;\n\t\t\t}, pick(this.options.hideDelay, 500));\n\n\t\t\t// hide previous hoverPoints and set new\n\t\t\tif (hoverPoints) {\n\t\t\t\teach(hoverPoints, function (point) {\n\t\t\t\t\tpoint.setState();\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tthis.chart.hoverPoints = null;\n\t\t}\n\t},\n\n\t/**\n\t * Hide the crosshairs\n\t */\n\thideCrosshairs: function () {\n\t\teach(this.crosshairs, function (crosshair) {\n\t\t\tif (crosshair) {\n\t\t\t\tcrosshair.hide();\n\t\t\t}\n\t\t});\n\t},\n\t\n\t/** \n\t * Extendable method to get the anchor position of the tooltip\n\t * from a point or set of points\n\t */\n\tgetAnchor: function (points, mouseEvent) {\n\t\tvar ret,\n\t\t\tchart = this.chart,\n\t\t\tinverted = chart.inverted,\n\t\t\tplotTop = chart.plotTop,\n\t\t\tplotX = 0,\n\t\t\tplotY = 0,\n\t\t\tyAxis;\n\t\t\n\t\tpoints = splat(points);\n\t\t\n\t\t// Pie uses a special tooltipPos\n\t\tret = points[0].tooltipPos;\n\t\t\n\t\t// When tooltip follows mouse, relate the position to the mouse\n\t\tif (this.followPointer && mouseEvent) {\n\t\t\tif (mouseEvent.chartX === UNDEFINED) {\n\t\t\t\tmouseEvent = chart.pointer.normalize(mouseEvent);\n\t\t\t}\n\t\t\tret = [\n\t\t\t\tmouseEvent.chartX - chart.plotLeft,\n\t\t\t\tmouseEvent.chartY - plotTop\n\t\t\t];\n\t\t}\n\t\t// When shared, use the average position\n\t\tif (!ret) {\n\t\t\teach(points, function (point) {\n\t\t\t\tyAxis = point.series.yAxis;\n\t\t\t\tplotX += point.plotX;\n\t\t\t\tplotY += (point.plotLow ? (point.plotLow + point.plotHigh) / 2 : point.plotY) +\n\t\t\t\t\t(!inverted && yAxis ? yAxis.top - plotTop : 0); // #1151\n\t\t\t});\n\t\t\t\n\t\t\tplotX /= points.length;\n\t\t\tplotY /= points.length;\n\t\t\t\n\t\t\tret = [\n\t\t\t\tinverted ? chart.plotWidth - plotY : plotX,\n\t\t\t\tthis.shared && !inverted && points.length > 1 && mouseEvent ? \n\t\t\t\t\tmouseEvent.chartY - plotTop : // place shared tooltip next to the mouse (#424)\n\t\t\t\t\tinverted ? chart.plotHeight - plotX : plotY\n\t\t\t];\n\t\t}\n\n\t\treturn map(ret, mathRound);\n\t},\n\t\n\t/**\n\t * Place the tooltip in a chart without spilling over\n\t * and not covering the point it self.\n\t */\n\tgetPosition: function (boxWidth, boxHeight, point) {\n\t\t\n\t\t// Set up the variables\n\t\tvar chart = this.chart,\n\t\t\tplotLeft = chart.plotLeft,\n\t\t\tplotTop = chart.plotTop,\n\t\t\tplotWidth = chart.plotWidth,\n\t\t\tplotHeight = chart.plotHeight,\n\t\t\tdistance = pick(this.options.distance, 12),\n\t\t\tpointX = point.plotX,\n\t\t\tpointY = point.plotY,\n\t\t\tx = pointX + plotLeft + (chart.inverted ? distance : -boxWidth - distance),\n\t\t\ty = pointY - boxHeight + plotTop + 15, // 15 means the point is 15 pixels up from the bottom of the tooltip\n\t\t\talignedRight;\n\t\n\t\t// It is too far to the left, adjust it\n\t\tif (x < 7) {\n\t\t\tx = plotLeft + mathMax(pointX, 0) + distance;\n\t\t}\n\t\n\t\t// Test to see if the tooltip is too far to the right,\n\t\t// if it is, move it back to be inside and then up to not cover the point.\n\t\tif ((x + boxWidth) > (plotLeft + plotWidth)) {\n\t\t\tx -= (x + boxWidth) - (plotLeft + plotWidth);\n\t\t\ty = pointY - boxHeight + plotTop - distance;\n\t\t\talignedRight = true;\n\t\t}\n\t\n\t\t// If it is now above the plot area, align it to the top of the plot area\n\t\tif (y < plotTop + 5) {\n\t\t\ty = plotTop + 5;\n\t\n\t\t\t// If the tooltip is still covering the point, move it below instead\n\t\t\tif (alignedRight && pointY >= y && pointY <= (y + boxHeight)) {\n\t\t\t\ty = pointY + plotTop + distance; // below\n\t\t\t}\n\t\t} \n\t\n\t\t// Now if the tooltip is below the chart, move it up. It's better to cover the\n\t\t// point than to disappear outside the chart. #834.\n\t\tif (y + boxHeight > plotTop + plotHeight) {\n\t\t\ty = mathMax(plotTop, plotTop + plotHeight - boxHeight - distance); // below\n\t\t}\n\t\n\t\treturn {x: x, y: y};\n\t},\n\n\t/**\n\t * In case no user defined formatter is given, this will be used. Note that the context\n\t * here is an object holding point, series, x, y etc.\n\t */\n\tdefaultFormatter: function (tooltip) {\n\t\tvar items = this.points || splat(this),\n\t\t\tseries = items[0].series,\n\t\t\ts;\n\n\t\t// build the header\n\t\ts = [series.tooltipHeaderFormatter(items[0])];\n\n\t\t// build the values\n\t\teach(items, function (item) {\n\t\t\tseries = item.series;\n\t\t\ts.push((series.tooltipFormatter && series.tooltipFormatter(item)) ||\n\t\t\t\titem.point.tooltipFormatter(series.tooltipOptions.pointFormat));\n\t\t});\n\n\t\t// footer\n\t\ts.push(tooltip.options.footerFormat || '');\n\n\t\treturn s.join('');\n\t},\n\n\t/**\n\t * Refresh the tooltip's text and position.\n\t * @param {Object} point\n\t */\n\trefresh: function (point, mouseEvent) {\n\t\tvar tooltip = this,\n\t\t\tchart = tooltip.chart,\n\t\t\tlabel = tooltip.label,\n\t\t\toptions = tooltip.options,\n\t\t\tx,\n\t\t\ty,\n\t\t\tshow,\n\t\t\tanchor,\n\t\t\ttextConfig = {},\n\t\t\ttext,\n\t\t\tpointConfig = [],\n\t\t\tformatter = options.formatter || tooltip.defaultFormatter,\n\t\t\thoverPoints = chart.hoverPoints,\n\t\t\tborderColor,\n\t\t\tcrosshairsOptions = options.crosshairs,\n\t\t\tshared = tooltip.shared,\n\t\t\tcurrentSeries;\n\t\t\t\n\t\tclearTimeout(this.hideTimer);\n\t\t\n\t\t// get the reference point coordinates (pie charts use tooltipPos)\n\t\ttooltip.followPointer = splat(point)[0].series.tooltipOptions.followPointer;\n\t\tanchor = tooltip.getAnchor(point, mouseEvent);\n\t\tx = anchor[0];\n\t\ty = anchor[1];\n\n\t\t// shared tooltip, array is sent over\n\t\tif (shared && !(point.series && point.series.noSharedTooltip)) {\n\t\t\t\n\t\t\t// hide previous hoverPoints and set new\n\t\t\t\n\t\t\tchart.hoverPoints = point;\n\t\t\tif (hoverPoints) {\n\t\t\t\teach(hoverPoints, function (point) {\n\t\t\t\t\tpoint.setState();\n\t\t\t\t});\n\t\t\t}\n\n\t\t\teach(point, function (item) {\n\t\t\t\titem.setState(HOVER_STATE);\n\n\t\t\t\tpointConfig.push(item.getLabelConfig());\n\t\t\t});\n\n\t\t\ttextConfig = {\n\t\t\t\tx: point[0].category,\n\t\t\t\ty: point[0].y\n\t\t\t};\n\t\t\ttextConfig.points = pointConfig;\n\t\t\tpoint = point[0];\n\n\t\t// single point tooltip\n\t\t} else {\n\t\t\ttextConfig = point.getLabelConfig();\n\t\t}\n\t\ttext = formatter.call(textConfig, tooltip);\n\n\t\t// register the current series\n\t\tcurrentSeries = point.series;\n\n\n\t\t// For line type series, hide tooltip if the point falls outside the plot\n\t\tshow = shared || !currentSeries.isCartesian || currentSeries.tooltipOutsidePlot || chart.isInsidePlot(x, y);\n\n\t\t// update the inner HTML\n\t\tif (text === false || !show) {\n\t\t\tthis.hide();\n\t\t} else {\n\n\t\t\t// show it\n\t\t\tif (tooltip.isHidden) {\n\t\t\t\tstop(label);\n\t\t\t\tlabel.attr('opacity', 1).show();\n\t\t\t}\n\n\t\t\t// update text\n\t\t\tlabel.attr({\n\t\t\t\ttext: text\n\t\t\t});\n\n\t\t\t// set the stroke color of the box\n\t\t\tborderColor = options.borderColor || point.color || currentSeries.color || '#606060';\n\t\t\tlabel.attr({\n\t\t\t\tstroke: borderColor\n\t\t\t});\n\t\t\t\n\t\t\ttooltip.updatePosition({ plotX: x, plotY: y });\n\t\t\n\t\t\tthis.isHidden = false;\n\t\t}\n\n\t\t// crosshairs\n\t\tif (crosshairsOptions) {\n\t\t\tcrosshairsOptions = splat(crosshairsOptions); // [x, y]\n\n\t\t\tvar path,\n\t\t\t\ti = crosshairsOptions.length,\n\t\t\t\tattribs,\n\t\t\t\taxis,\n\t\t\t\tval,\n\t\t\t\tseries;\n\n\t\t\twhile (i--) {\n\t\t\t\tseries = point.series;\n\t\t\t\taxis = series[i ? 'yAxis' : 'xAxis'];\n\t\t\t\tif (crosshairsOptions[i] && axis) {\n\t\t\t\t\tval = i ? pick(point.stackY, point.y) : point.x; // #814\n\t\t\t\t\tif (axis.isLog) { // #1671\n\t\t\t\t\t\tval = log2lin(val);\n\t\t\t\t\t}\n\t\t\t\t\tif (series.modifyValue) { // #1205\n\t\t\t\t\t\tval = series.modifyValue(val);\n\t\t\t\t\t}\n\n\t\t\t\t\tpath = axis.getPlotLinePath(\n\t\t\t\t\t\tval,\n\t\t\t\t\t\t1\n\t\t\t\t\t);\n\n\t\t\t\t\tif (tooltip.crosshairs[i]) {\n\t\t\t\t\t\ttooltip.crosshairs[i].attr({ d: path, visibility: VISIBLE });\n\t\t\t\t\t} else {\n\t\t\t\t\t\tattribs = {\n\t\t\t\t\t\t\t'stroke-width': crosshairsOptions[i].width || 1,\n\t\t\t\t\t\t\tstroke: crosshairsOptions[i].color || '#C0C0C0',\n\t\t\t\t\t\t\tzIndex: crosshairsOptions[i].zIndex || 2\n\t\t\t\t\t\t};\n\t\t\t\t\t\tif (crosshairsOptions[i].dashStyle) {\n\t\t\t\t\t\t\tattribs.dashstyle = crosshairsOptions[i].dashStyle;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttooltip.crosshairs[i] = chart.renderer.path(path)\n\t\t\t\t\t\t\t.attr(attribs)\n\t\t\t\t\t\t\t.add();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfireEvent(chart, 'tooltipRefresh', {\n\t\t\t\ttext: text,\n\t\t\t\tx: x + chart.plotLeft,\n\t\t\t\ty: y + chart.plotTop,\n\t\t\t\tborderColor: borderColor\n\t\t\t});\n\t},\n\t\n\t/**\n\t * Find the new position and perform the move\n\t */\n\tupdatePosition: function (point) {\n\t\tvar chart = this.chart,\n\t\t\tlabel = this.label, \n\t\t\tpos = (this.options.positioner || this.getPosition).call(\n\t\t\t\tthis,\n\t\t\t\tlabel.width,\n\t\t\t\tlabel.height,\n\t\t\t\tpoint\n\t\t\t);\n\n\t\t// do the move\n\t\tthis.move(\n\t\t\tmathRound(pos.x), \n\t\t\tmathRound(pos.y), \n\t\t\tpoint.plotX + chart.plotLeft, \n\t\t\tpoint.plotY + chart.plotTop\n\t\t);\n\t}\n};\n/**\n * The mouse tracker object. All methods starting with \"on\" are primary DOM event handlers. \n * Subsequent methods should be named differently from what they are doing.\n * @param {Object} chart The Chart instance\n * @param {Object} options The root options object\n */\nfunction Pointer(chart, options) {\n\tthis.init(chart, options);\n}\n\nPointer.prototype = {\n\t/**\n\t * Initialize Pointer\n\t */\n\tinit: function (chart, options) {\n\t\t\n\t\tvar zoomType = useCanVG ? '' : options.chart.zoomType,\n\t\t\tinverted = chart.inverted,\n\t\t\tzoomX,\n\t\t\tzoomY;\n\n\t\t// Store references\n\t\tthis.options = options;\n\t\tthis.chart = chart;\n\t\t\n\t\t// Zoom status\n\t\tthis.zoomX = zoomX = /x/.test(zoomType);\n\t\tthis.zoomY = zoomY = /y/.test(zoomType);\n\t\tthis.zoomHor = (zoomX && !inverted) || (zoomY && inverted);\n\t\tthis.zoomVert = (zoomY && !inverted) || (zoomX && inverted);\n\n\t\tthis.pinchDown = [];\n\t\tthis.lastValidTouch = {};\n\n\t\tif (options.tooltip.enabled) {\n\t\t\tchart.tooltip = new Tooltip(chart, options.tooltip);\n\t\t}\n\n\t\tthis.setDOMEvents();\n\t}, \n\n\t/**\n\t * Add crossbrowser support for chartX and chartY\n\t * @param {Object} e The event object in standard browsers\n\t */\n\tnormalize: function (e) {\n\t\tvar chartPosition,\n\t\t\tePos;\n\n\t\t// common IE normalizing\n\t\te = e || win.event;\n\t\tif (!e.target) {\n\t\t\te.target = e.srcElement;\n\t\t}\n\n\t\t// Framework specific normalizing (#1165)\n\t\te = washMouseEvent(e);\n\t\t\n\t\t// iOS\n\t\tePos = e.touches ? e.touches.item(0) : e;\n\n\t\t// get mouse position\n\t\tthis.chartPosition = chartPosition = offset(this.chart.container);\n\n\t\t// Old IE and compatibility mode use clientX. #886, #2005.\n\t\treturn extend(e, {\n\t\t\tchartX: mathRound(pick(ePos.pageX, ePos.clientX) - chartPosition.left),\n\t\t\tchartY: mathRound(pick(ePos.pageY, ePos.clientY) - chartPosition.top)\n\t\t});\n\t},\n\n\t/**\n\t * Get the click position in terms of axis values.\n\t *\n\t * @param {Object} e A pointer event\n\t */\n\tgetCoordinates: function (e) {\n\t\tvar coordinates = {\n\t\t\t\txAxis: [],\n\t\t\t\tyAxis: []\n\t\t\t};\n\n\t\teach(this.chart.axes, function (axis) {\n\t\t\tcoordinates[axis.isXAxis ? 'xAxis' : 'yAxis'].push({\n\t\t\t\taxis: axis,\n\t\t\t\tvalue: axis.toValue(e[axis.horiz ? 'chartX' : 'chartY'])\n\t\t\t});\n\t\t});\n\t\treturn coordinates;\n\t},\n\t\n\t/**\n\t * Return the index in the tooltipPoints array, corresponding to pixel position in \n\t * the plot area.\n\t */\n\tgetIndex: function (e) {\n\t\tvar chart = this.chart;\n\t\treturn chart.inverted ? \n\t\t\tchart.plotHeight + chart.plotTop - e.chartY : \n\t\t\te.chartX - chart.plotLeft;\n\t},\n\n\t/**\n\t * With line type charts with a single tracker, get the point closest to the mouse.\n\t * Run Point.onMouseOver and display tooltip for the point or points.\n\t */\n\trunPointActions: function (e) {\n\t\tvar pointer = this,\n\t\t\tchart = pointer.chart,\n\t\t\tseries = chart.series,\n\t\t\ttooltip = chart.tooltip,\n\t\t\tpoint,\n\t\t\tpoints,\n\t\t\thoverPoint = chart.hoverPoint,\n\t\t\thoverSeries = chart.hoverSeries,\n\t\t\ti,\n\t\t\tj,\n\t\t\tdistance = chart.chartWidth,\n\t\t\tindex = pointer.getIndex(e),\n\t\t\tanchor;\n\n\t\t// shared tooltip\n\t\tif (tooltip && pointer.options.tooltip.shared && !(hoverSeries && hoverSeries.noSharedTooltip)) {\n\t\t\tpoints = [];\n\n\t\t\t// loop over all series and find the ones with points closest to the mouse\n\t\t\ti = series.length;\n\t\t\tfor (j = 0; j < i; j++) {\n\t\t\t\tif (series[j].visible &&\n\t\t\t\t\t\tseries[j].options.enableMouseTracking !== false &&\n\t\t\t\t\t\t!series[j].noSharedTooltip && series[j].tooltipPoints.length) {\n\t\t\t\t\tpoint = series[j].tooltipPoints[index];\n\t\t\t\t\tif (point.series) { // not a dummy point, #1544\n\t\t\t\t\t\tpoint._dist = mathAbs(index - point.clientX);\n\t\t\t\t\t\tdistance = mathMin(distance, point._dist);\n\t\t\t\t\t\tpoints.push(point);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// remove furthest points\n\t\t\ti = points.length;\n\t\t\twhile (i--) {\n\t\t\t\tif (points[i]._dist > distance) {\n\t\t\t\t\tpoints.splice(i, 1);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// refresh the tooltip if necessary\n\t\t\tif (points.length && (points[0].clientX !== pointer.hoverX)) {\n\t\t\t\ttooltip.refresh(points, e);\n\t\t\t\tpointer.hoverX = points[0].clientX;\n\t\t\t}\n\t\t}\n\n\t\t// separate tooltip and general mouse events\n\t\tif (hoverSeries && hoverSeries.tracker) { // only use for line-type series with common tracker\n\n\t\t\t// get the point\n\t\t\tpoint = hoverSeries.tooltipPoints[index];\n\n\t\t\t// a new point is hovered, refresh the tooltip\n\t\t\tif (point && point !== hoverPoint) {\n\n\t\t\t\t// trigger the events\n\t\t\t\tpoint.onMouseOver(e);\n\n\t\t\t}\n\t\t\t\n\t\t} else if (tooltip && tooltip.followPointer && !tooltip.isHidden) {\n\t\t\tanchor = tooltip.getAnchor([{}], e);\n\t\t\ttooltip.updatePosition({ plotX: anchor[0], plotY: anchor[1] });\n\t\t}\n\t},\n\n\n\n\t/**\n\t * Reset the tracking by hiding the tooltip, the hover series state and the hover point\n\t * \n\t * @param allowMove {Boolean} Instead of destroying the tooltip altogether, allow moving it if possible\n\t */\n\treset: function (allowMove) {\n\t\tvar pointer = this,\n\t\t\tchart = pointer.chart,\n\t\t\thoverSeries = chart.hoverSeries,\n\t\t\thoverPoint = chart.hoverPoint,\n\t\t\ttooltip = chart.tooltip,\n\t\t\ttooltipPoints = tooltip && tooltip.shared ? chart.hoverPoints : hoverPoint;\n\t\t\t\n\t\t// Narrow in allowMove\n\t\tallowMove = allowMove && tooltip && tooltipPoints;\n\t\t\t\n\t\t// Check if the points have moved outside the plot area, #1003\n\t\tif (allowMove && splat(tooltipPoints)[0].plotX === UNDEFINED) {\n\t\t\tallowMove = false;\n\t\t}\t\n\n\t\t// Just move the tooltip, #349\n\t\tif (allowMove) {\n\t\t\ttooltip.refresh(tooltipPoints);\n\n\t\t// Full reset\n\t\t} else {\n\n\t\t\tif (hoverPoint) {\n\t\t\t\thoverPoint.onMouseOut();\n\t\t\t}\n\n\t\t\tif (hoverSeries) {\n\t\t\t\thoverSeries.onMouseOut();\n\t\t\t}\n\n\t\t\tif (tooltip) {\n\t\t\t\ttooltip.hide();\n\t\t\t\ttooltip.hideCrosshairs();\n\t\t\t}\n\n\t\t\tpointer.hoverX = null;\n\n\t\t}\n\t},\n\n\t/**\n\t * Scale series groups to a certain scale and translation\n\t */\n\tscaleGroups: function (attribs, clip) {\n\n\t\tvar chart = this.chart,\n\t\t\tseriesAttribs;\n\n\t\t// Scale each series\n\t\teach(chart.series, function (series) {\n\t\t\tseriesAttribs = attribs || series.getPlotBox(); // #1701\n\t\t\tif (series.xAxis && series.xAxis.zoomEnabled) {\n\t\t\t\tseries.group.attr(seriesAttribs);\n\t\t\t\tif (series.markerGroup) {\n\t\t\t\t\tseries.markerGroup.attr(seriesAttribs);\n\t\t\t\t\tseries.markerGroup.clip(clip ? chart.clipRect : null);\n\t\t\t\t}\n\t\t\t\tif (series.dataLabelsGroup) {\n\t\t\t\t\tseries.dataLabelsGroup.attr(seriesAttribs);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\t\n\t\t// Clip\n\t\tchart.clipRect.attr(clip || chart.clipBox);\n\t},\n\n\t/**\n\t * Run translation operations for each direction (horizontal and vertical) independently\n\t */\n\tpinchTranslateDirection: function (horiz, pinchDown, touches, transform, selectionMarker, clip, lastValidTouch) {\n\t\tvar chart = this.chart,\n\t\t\txy = horiz ? 'x' : 'y',\n\t\t\tXY = horiz ? 'X' : 'Y',\n\t\t\tsChartXY = 'chart' + XY,\n\t\t\twh = horiz ? 'width' : 'height',\n\t\t\tplotLeftTop = chart['plot' + (horiz ? 'Left' : 'Top')],\n\t\t\tselectionWH,\n\t\t\tselectionXY,\n\t\t\tclipXY,\n\t\t\tscale = 1,\n\t\t\tinverted = chart.inverted,\n\t\t\tbounds = chart.bounds[horiz ? 'h' : 'v'],\n\t\t\tsingleTouch = pinchDown.length === 1,\n\t\t\ttouch0Start = pinchDown[0][sChartXY],\n\t\t\ttouch0Now = touches[0][sChartXY],\n\t\t\ttouch1Start = !singleTouch && pinchDown[1][sChartXY],\n\t\t\ttouch1Now = !singleTouch && touches[1][sChartXY],\n\t\t\toutOfBounds,\n\t\t\ttransformScale,\n\t\t\tscaleKey,\n\t\t\tsetScale = function () {\n\t\t\t\tif (!singleTouch && mathAbs(touch0Start - touch1Start) > 20) { // Don't zoom if fingers are too close on this axis\n\t\t\t\t\tscale = mathAbs(touch0Now - touch1Now) / mathAbs(touch0Start - touch1Start);\t\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tclipXY = ((plotLeftTop - touch0Now) / scale) + touch0Start;\n\t\t\t\tselectionWH = chart['plot' + (horiz ? 'Width' : 'Height')] / scale;\n\t\t\t};\n\n\t\t// Set the scale, first pass\n\t\tsetScale();\n\n\t\tselectionXY = clipXY; // the clip position (x or y) is altered if out of bounds, the selection position is not\n\n\t\t// Out of bounds\n\t\tif (selectionXY < bounds.min) {\n\t\t\tselectionXY = bounds.min;\n\t\t\toutOfBounds = true;\n\t\t} else if (selectionXY + selectionWH > bounds.max) {\n\t\t\tselectionXY = bounds.max - selectionWH;\n\t\t\toutOfBounds = true;\n\t\t}\n\t\t\n\t\t// Is the chart dragged off its bounds, determined by dataMin and dataMax?\n\t\tif (outOfBounds) {\n\n\t\t\t// Modify the touchNow position in order to create an elastic drag movement. This indicates\n\t\t\t// to the user that the chart is responsive but can't be dragged further.\n\t\t\ttouch0Now -= 0.8 * (touch0Now - lastValidTouch[xy][0]);\n\t\t\tif (!singleTouch) {\n\t\t\t\ttouch1Now -= 0.8 * (touch1Now - lastValidTouch[xy][1]);\n\t\t\t}\n\n\t\t\t// Set the scale, second pass to adapt to the modified touchNow positions\n\t\t\tsetScale();\n\n\t\t} else {\n\t\t\tlastValidTouch[xy] = [touch0Now, touch1Now];\n\t\t}\n\n\t\t\n\t\t// Set geometry for clipping, selection and transformation\n\t\tif (!inverted) { // TODO: implement clipping for inverted charts\n\t\t\tclip[xy] = clipXY - plotLeftTop;\n\t\t\tclip[wh] = selectionWH;\n\t\t}\n\t\tscaleKey = inverted ? (horiz ? 'scaleY' : 'scaleX') : 'scale' + XY;\n\t\ttransformScale = inverted ? 1 / scale : scale;\n\n\t\tselectionMarker[wh] = selectionWH;\n\t\tselectionMarker[xy] = selectionXY;\n\t\ttransform[scaleKey] = scale;\n\t\ttransform['translate' + XY] = (transformScale * plotLeftTop) + (touch0Now - (transformScale * touch0Start));\n\t},\n\t\n\t/**\n\t * Handle touch events with two touches\n\t */\n\tpinch: function (e) {\n\n\t\tvar self = this,\n\t\t\tchart = self.chart,\n\t\t\tpinchDown = self.pinchDown,\n\t\t\tfollowTouchMove = chart.tooltip && chart.tooltip.options.followTouchMove,\n\t\t\ttouches = e.touches,\n\t\t\ttouchesLength = touches.length,\n\t\t\tlastValidTouch = self.lastValidTouch,\n\t\t\tzoomHor = self.zoomHor || self.pinchHor,\n\t\t\tzoomVert = self.zoomVert || self.pinchVert,\n\t\t\thasZoom = zoomHor || zoomVert,\n\t\t\tselectionMarker = self.selectionMarker,\n\t\t\ttransform = {},\n\t\t\tclip = {};\n\n\t\t// On touch devices, only proceed to trigger click if a handler is defined\n\t\tif (e.type === 'touchstart') {\n\t\t\tif (followTouchMove || hasZoom) {\n\t\t\t\te.preventDefault();\n\t\t\t}\n\t\t}\n\t\t\t\n\t\t// Normalize each touch\n\t\tmap(touches, function (e) {\n\t\t\treturn self.normalize(e);\n\t\t});\n\t\t\t\n\t\t// Register the touch start position\n\t\tif (e.type === 'touchstart') {\n\t\t\teach(touches, function (e, i) {\n\t\t\t\tpinchDown[i] = { chartX: e.chartX, chartY: e.chartY };\n\t\t\t});\n\t\t\tlastValidTouch.x = [pinchDown[0].chartX, pinchDown[1] && pinchDown[1].chartX];\n\t\t\tlastValidTouch.y = [pinchDown[0].chartY, pinchDown[1] && pinchDown[1].chartY];\n\n\t\t\t// Identify the data bounds in pixels\n\t\t\teach(chart.axes, function (axis) {\n\t\t\t\tif (axis.zoomEnabled) {\n\t\t\t\t\tvar bounds = chart.bounds[axis.horiz ? 'h' : 'v'],\n\t\t\t\t\t\tminPixelPadding = axis.minPixelPadding,\n\t\t\t\t\t\tmin = axis.toPixels(axis.dataMin),\n\t\t\t\t\t\tmax = axis.toPixels(axis.dataMax),\n\t\t\t\t\t\tabsMin = mathMin(min, max),\n\t\t\t\t\t\tabsMax = mathMax(min, max);\n\n\t\t\t\t\t// Store the bounds for use in the touchmove handler\n\t\t\t\t\tbounds.min = mathMin(axis.pos, absMin - minPixelPadding);\n\t\t\t\t\tbounds.max = mathMax(axis.pos + axis.len, absMax + minPixelPadding);\n\t\t\t\t}\n\t\t\t});\n\t\t\n\t\t// Event type is touchmove, handle panning and pinching\n\t\t} else if (pinchDown.length) { // can be 0 when releasing, if touchend fires first\n\t\t\t\n\n\t\t\t// Set the marker\n\t\t\tif (!selectionMarker) {\n\t\t\t\tself.selectionMarker = selectionMarker = extend({\n\t\t\t\t\tdestroy: noop\n\t\t\t\t}, chart.plotBox);\n\t\t\t}\n\n\t\t\t\n\n\t\t\tif (zoomHor) {\n\t\t\t\tself.pinchTranslateDirection(true, pinchDown, touches, transform, selectionMarker, clip, lastValidTouch);\n\t\t\t}\n\t\t\tif (zoomVert) {\n\t\t\t\tself.pinchTranslateDirection(false, pinchDown, touches, transform, selectionMarker, clip, lastValidTouch);\n\t\t\t}\n\n\t\t\tself.hasPinched = hasZoom;\n\n\t\t\t// Scale and translate the groups to provide visual feedback during pinching\n\t\t\tself.scaleGroups(transform, clip);\n\t\t\t\n\t\t\t// Optionally move the tooltip on touchmove\n\t\t\tif (!hasZoom && followTouchMove && touchesLength === 1) {\n\t\t\t\tthis.runPointActions(self.normalize(e));\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Start a drag operation\n\t */\n\tdragStart: function (e) {\n\t\tvar chart = this.chart;\n\n\t\t// Record the start position\n\t\tchart.mouseIsDown = e.type;\n\t\tchart.cancelClick = false;\n\t\tchart.mouseDownX = this.mouseDownX = e.chartX;\n\t\tthis.mouseDownY = e.chartY;\n\t},\n\n\t/**\n\t * Perform a drag operation in response to a mousemove event while the mouse is down\n\t */\n\tdrag: function (e) {\n\n\t\tvar chart = this.chart,\n\t\t\tchartOptions = chart.options.chart,\n\t\t\tchartX = e.chartX,\n\t\t\tchartY = e.chartY,\n\t\t\tzoomHor = this.zoomHor,\n\t\t\tzoomVert = this.zoomVert,\n\t\t\tplotLeft = chart.plotLeft,\n\t\t\tplotTop = chart.plotTop,\n\t\t\tplotWidth = chart.plotWidth,\n\t\t\tplotHeight = chart.plotHeight,\n\t\t\tclickedInside,\n\t\t\tsize,\n\t\t\tmouseDownX = this.mouseDownX,\n\t\t\tmouseDownY = this.mouseDownY;\n\n\t\t// If the mouse is outside the plot area, adjust to cooordinates\n\t\t// inside to prevent the selection marker from going outside\n\t\tif (chartX < plotLeft) {\n\t\t\tchartX = plotLeft;\n\t\t} else if (chartX > plotLeft + plotWidth) {\n\t\t\tchartX = plotLeft + plotWidth;\n\t\t}\n\n\t\tif (chartY < plotTop) {\n\t\t\tchartY = plotTop;\n\t\t} else if (chartY > plotTop + plotHeight) {\n\t\t\tchartY = plotTop + plotHeight;\n\t\t}\n\t\t\n\t\t// determine if the mouse has moved more than 10px\n\t\tthis.hasDragged = Math.sqrt(\n\t\t\tMath.pow(mouseDownX - chartX, 2) +\n\t\t\tMath.pow(mouseDownY - chartY, 2)\n\t\t);\n\t\tif (this.hasDragged > 10) {\n\t\t\tclickedInside = chart.isInsidePlot(mouseDownX - plotLeft, mouseDownY - plotTop);\n\n\t\t\t// make a selection\n\t\t\tif (chart.hasCartesianSeries && (this.zoomX || this.zoomY) && clickedInside) {\n\t\t\t\tif (!this.selectionMarker) {\n\t\t\t\t\tthis.selectionMarker = chart.renderer.rect(\n\t\t\t\t\t\tplotLeft,\n\t\t\t\t\t\tplotTop,\n\t\t\t\t\t\tzoomHor ? 1 : plotWidth,\n\t\t\t\t\t\tzoomVert ? 1 : plotHeight,\n\t\t\t\t\t\t0\n\t\t\t\t\t)\n\t\t\t\t\t.attr({\n\t\t\t\t\t\tfill: chartOptions.selectionMarkerFill || 'rgba(69,114,167,0.25)',\n\t\t\t\t\t\tzIndex: 7\n\t\t\t\t\t})\n\t\t\t\t\t.add();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// adjust the width of the selection marker\n\t\t\tif (this.selectionMarker && zoomHor) {\n\t\t\t\tsize = chartX - mouseDownX;\n\t\t\t\tthis.selectionMarker.attr({\n\t\t\t\t\twidth: mathAbs(size),\n\t\t\t\t\tx: (size > 0 ? 0 : size) + mouseDownX\n\t\t\t\t});\n\t\t\t}\n\t\t\t// adjust the height of the selection marker\n\t\t\tif (this.selectionMarker && zoomVert) {\n\t\t\t\tsize = chartY - mouseDownY;\n\t\t\t\tthis.selectionMarker.attr({\n\t\t\t\t\theight: mathAbs(size),\n\t\t\t\t\ty: (size > 0 ? 0 : size) + mouseDownY\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// panning\n\t\t\tif (clickedInside && !this.selectionMarker && chartOptions.panning) {\n\t\t\t\tchart.pan(chartX);\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * On mouse up or touch end across the entire document, drop the selection.\n\t */\n\tdrop: function (e) {\n\t\tvar chart = this.chart,\n\t\t\thasPinched = this.hasPinched;\n\n\t\tif (this.selectionMarker) {\n\t\t\tvar selectionData = {\n\t\t\t\t\txAxis: [],\n\t\t\t\t\tyAxis: [],\n\t\t\t\t\toriginalEvent: e.originalEvent || e\n\t\t\t\t},\n\t\t\t\tselectionBox = this.selectionMarker,\n\t\t\t\tselectionLeft = selectionBox.x,\n\t\t\t\tselectionTop = selectionBox.y,\n\t\t\t\trunZoom;\n\t\t\t// a selection has been made\n\t\t\tif (this.hasDragged || hasPinched) {\n\n\t\t\t\t// record each axis' min and max\n\t\t\t\teach(chart.axes, function (axis) {\n\t\t\t\t\tif (axis.zoomEnabled) {\n\t\t\t\t\t\tvar horiz = axis.horiz,\n\t\t\t\t\t\t\tselectionMin = axis.toValue((horiz ? selectionLeft : selectionTop)),\n\t\t\t\t\t\t\tselectionMax = axis.toValue((horiz ? selectionLeft + selectionBox.width : selectionTop + selectionBox.height));\n\n\t\t\t\t\t\tif (!isNaN(selectionMin) && !isNaN(selectionMax)) { // #859\n\t\t\t\t\t\t\tselectionData[axis.xOrY + 'Axis'].push({\n\t\t\t\t\t\t\t\taxis: axis,\n\t\t\t\t\t\t\t\tmin: mathMin(selectionMin, selectionMax), // for reversed axes,\n\t\t\t\t\t\t\t\tmax: mathMax(selectionMin, selectionMax)\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\trunZoom = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tif (runZoom) {\n\t\t\t\t\tfireEvent(chart, 'selection', selectionData, function (args) { \n\t\t\t\t\t\tchart.zoom(extend(args, hasPinched ? { animation: false } : null)); \n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t}\n\t\t\tthis.selectionMarker = this.selectionMarker.destroy();\n\n\t\t\t// Reset scaling preview\n\t\t\tif (hasPinched) {\n\t\t\t\tthis.scaleGroups();\n\t\t\t}\n\t\t}\n\n\t\t// Reset all\n\t\tif (chart) { // it may be destroyed on mouse up - #877\n\t\t\tcss(chart.container, { cursor: chart._cursor });\n\t\t\tchart.cancelClick = this.hasDragged > 10; // #370\n\t\t\tchart.mouseIsDown = this.hasDragged = this.hasPinched = false;\n\t\t\tthis.pinchDown = [];\n\t\t}\n\t},\n\n\tonContainerMouseDown: function (e) {\n\n\t\te = this.normalize(e);\n\n\t\t// issue #295, dragging not always working in Firefox\n\t\tif (e.preventDefault) {\n\t\t\te.preventDefault();\n\t\t}\n\t\t\n\t\tthis.dragStart(e);\n\t},\n\n\t\n\n\tonDocumentMouseUp: function (e) {\n\t\tthis.drop(e);\n\t},\n\n\t/**\n\t * Special handler for mouse move that will hide the tooltip when the mouse leaves the plotarea.\n\t * Issue #149 workaround. The mouseleave event does not always fire. \n\t */\n\tonDocumentMouseMove: function (e) {\n\t\tvar chart = this.chart,\n\t\t\tchartPosition = this.chartPosition,\n\t\t\thoverSeries = chart.hoverSeries;\n\n\t\t// Get e.pageX and e.pageY back in MooTools\n\t\te = washMouseEvent(e);\n\n\t\t// If we're outside, hide the tooltip\n\t\tif (chartPosition && hoverSeries && hoverSeries.isCartesian &&\n\t\t\t!chart.isInsidePlot(e.pageX - chartPosition.left - chart.plotLeft,\n\t\t\te.pageY - chartPosition.top - chart.plotTop)) {\n\t\t\t\tthis.reset();\n\t\t}\n\t},\n\n\t/**\n\t * When mouse leaves the container, hide the tooltip.\n\t */\n\tonContainerMouseLeave: function () {\n\t\tthis.reset();\n\t\tthis.chartPosition = null; // also reset the chart position, used in #149 fix\n\t},\n\n\t// The mousemove, touchmove and touchstart event handler\n\tonContainerMouseMove: function (e) {\n\n\t\tvar chart = this.chart;\n\n\t\t// normalize\n\t\te = this.normalize(e);\n\n\t\t// #295\n\t\te.returnValue = false;\n\t\t\n\t\t\n\t\tif (chart.mouseIsDown === 'mousedown') {\n\t\t\tthis.drag(e);\n\t\t} \n\t\t\n\t\t// Show the tooltip and run mouse over events (#977)\n\t\tif (chart.isInsidePlot(e.chartX - chart.plotLeft, e.chartY - chart.plotTop) && !chart.openMenu) {\n\t\t\tthis.runPointActions(e);\n\t\t}\n\t},\n\n\t/**\n\t * Utility to detect whether an element has, or has a parent with, a specific\n\t * class name. Used on detection of tracker objects and on deciding whether\n\t * hovering the tooltip should cause the active series to mouse out.\n\t */\n\tinClass: function (element, className) {\n\t\tvar elemClassName;\n\t\twhile (element) {\n\t\t\telemClassName = attr(element, 'class');\n\t\t\tif (elemClassName) {\n\t\t\t\tif (elemClassName.indexOf(className) !== -1) {\n\t\t\t\t\treturn true;\n\t\t\t\t} else if (elemClassName.indexOf(PREFIX + 'container') !== -1) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\telement = element.parentNode;\n\t\t}\t\t\n\t},\n\n\tonTrackerMouseOut: function (e) {\n\t\tvar series = this.chart.hoverSeries;\n\t\tif (series && !series.options.stickyTracking && !this.inClass(e.toElement || e.relatedTarget, PREFIX + 'tooltip')) {\n\t\t\tseries.onMouseOut();\n\t\t}\n\t},\n\n\tonContainerClick: function (e) {\n\t\tvar chart = this.chart,\n\t\t\thoverPoint = chart.hoverPoint, \n\t\t\tplotLeft = chart.plotLeft,\n\t\t\tplotTop = chart.plotTop,\n\t\t\tinverted = chart.inverted,\n\t\t\tchartPosition,\n\t\t\tplotX,\n\t\t\tplotY;\n\t\t\n\t\te = this.normalize(e);\n\t\te.cancelBubble = true; // IE specific\n\n\t\tif (!chart.cancelClick) {\n\t\t\t\n\t\t\t// On tracker click, fire the series and point events. #783, #1583\n\t\t\tif (hoverPoint && this.inClass(e.target, PREFIX + 'tracker')) {\n\t\t\t\tchartPosition = this.chartPosition;\n\t\t\t\tplotX = hoverPoint.plotX;\n\t\t\t\tplotY = hoverPoint.plotY;\n\n\t\t\t\t// add page position info\n\t\t\t\textend(hoverPoint, {\n\t\t\t\t\tpageX: chartPosition.left + plotLeft +\n\t\t\t\t\t\t(inverted ? chart.plotWidth - plotY : plotX),\n\t\t\t\t\tpageY: chartPosition.top + plotTop +\n\t\t\t\t\t\t(inverted ? chart.plotHeight - plotX : plotY)\n\t\t\t\t});\n\t\t\t\n\t\t\t\t// the series click event\n\t\t\t\tfireEvent(hoverPoint.series, 'click', extend(e, {\n\t\t\t\t\tpoint: hoverPoint\n\t\t\t\t}));\n\n\t\t\t\t// the point click event\n\t\t\t\tif (chart.hoverPoint) { // it may be destroyed (#1844)\n\t\t\t\t\thoverPoint.firePointEvent('click', e);\n\t\t\t\t}\n\n\t\t\t// When clicking outside a tracker, fire a chart event\n\t\t\t} else {\n\t\t\t\textend(e, this.getCoordinates(e));\n\n\t\t\t\t// fire a click event in the chart\n\t\t\t\tif (chart.isInsidePlot(e.chartX - plotLeft, e.chartY - plotTop)) {\n\t\t\t\t\tfireEvent(chart, 'click', e);\n\t\t\t\t}\n\t\t\t}\n\n\n\t\t}\n\t},\n\n\tonContainerTouchStart: function (e) {\n\t\tvar chart = this.chart;\n\n\t\tif (e.touches.length === 1) {\n\n\t\t\te = this.normalize(e);\n\n\t\t\tif (chart.isInsidePlot(e.chartX - chart.plotLeft, e.chartY - chart.plotTop)) {\n\n\t\t\t\t// Prevent the click pseudo event from firing unless it is set in the options\n\t\t\t\t/*if (!chart.runChartClick) {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t}*/\n\t\t\t\n\t\t\t\t// Run mouse events and display tooltip etc\n\t\t\t\tthis.runPointActions(e);\n\n\t\t\t\tthis.pinch(e);\n\n\t\t\t} else {\n\t\t\t\t// Hide the tooltip on touching outside the plot area (#1203)\n\t\t\t\tthis.reset();\n\t\t\t}\n\n\t\t} else if (e.touches.length === 2) {\n\t\t\tthis.pinch(e);\t\n\t\t}\t\t\n\t},\n\n\tonContainerTouchMove: function (e) {\n\t\tif (e.touches.length === 1 || e.touches.length === 2) {\n\t\t\tthis.pinch(e);\n\t\t}\n\t},\n\n\tonDocumentTouchEnd: function (e) {\n\t\tthis.drop(e);\n\t},\n\n\t/**\n\t * Set the JS DOM events on the container and document. This method should contain\n\t * a one-to-one assignment between methods and their handlers. Any advanced logic should\n\t * be moved to the handler reflecting the event's name.\n\t */\n\tsetDOMEvents: function () {\n\n\t\tvar pointer = this,\n\t\t\tcontainer = pointer.chart.container,\n\t\t\tevents;\n\n\t\tthis._events = events = [\n\t\t\t[container, 'onmousedown', 'onContainerMouseDown'],\n\t\t\t[container, 'onmousemove', 'onContainerMouseMove'],\n\t\t\t[container, 'onclick', 'onContainerClick'],\n\t\t\t[container, 'mouseleave', 'onContainerMouseLeave'],\n\t\t\t[doc, 'mousemove', 'onDocumentMouseMove'],\n\t\t\t[doc, 'mouseup', 'onDocumentMouseUp']\n\t\t];\n\n\t\tif (hasTouch) {\n\t\t\tevents.push(\n\t\t\t\t[container, 'ontouchstart', 'onContainerTouchStart'],\n\t\t\t\t[container, 'ontouchmove', 'onContainerTouchMove'],\n\t\t\t\t[doc, 'touchend', 'onDocumentTouchEnd']\n\t\t\t);\n\t\t}\n\n\t\teach(events, function (eventConfig) {\n\n\t\t\t// First, create the callback function that in turn calls the method on Pointer\n\t\t\tpointer['_' + eventConfig[2]] = function (e) {\n\t\t\t\tpointer[eventConfig[2]](e);\n\t\t\t};\n\n\t\t\t// Now attach the function, either as a direct property or through addEvent\n\t\t\tif (eventConfig[1].indexOf('on') === 0) {\n\t\t\t\teventConfig[0][eventConfig[1]] = pointer['_' + eventConfig[2]];\n\t\t\t} else {\n\t\t\t\taddEvent(eventConfig[0], eventConfig[1], pointer['_' + eventConfig[2]]);\n\t\t\t}\n\t\t});\n\n\t\t\n\t},\n\n\t/**\n\t * Destroys the Pointer object and disconnects DOM events.\n\t */\n\tdestroy: function () {\n\t\tvar pointer = this;\n\n\t\t// Release all DOM events\n\t\teach(pointer._events, function (eventConfig) {\t\n\t\t\tif (eventConfig[1].indexOf('on') === 0) {\n\t\t\t\teventConfig[0][eventConfig[1]] = null; // delete breaks oldIE\n\t\t\t} else {\t\t\n\t\t\t\tremoveEvent(eventConfig[0], eventConfig[1], pointer['_' + eventConfig[2]]);\n\t\t\t}\n\t\t});\n\t\tdelete pointer._events;\n\n\t\t// memory and CPU leak\n\t\tclearInterval(pointer.tooltipTimeout);\n\t}\n};\n/**\n * The overview of the chart's series\n */\nfunction Legend(chart, options) {\n\tthis.init(chart, options);\n}\n\nLegend.prototype = {\n\t\n\t/**\n\t * Initialize the legend\n\t */\n\tinit: function (chart, options) {\n\t\t\n\t\tvar legend = this,\n\t\t\titemStyle = options.itemStyle,\n\t\t\tpadding = pick(options.padding, 8),\n\t\t\titemMarginTop = options.itemMarginTop || 0;\n\t\n\t\tthis.options = options;\n\n\t\tif (!options.enabled) {\n\t\t\treturn;\n\t\t}\n\t\n\t\tlegend.baseline = pInt(itemStyle.fontSize) + 3 + itemMarginTop; // used in Series prototype\n\t\tlegend.itemStyle = itemStyle;\n\t\tlegend.itemHiddenStyle = merge(itemStyle, options.itemHiddenStyle);\n\t\tlegend.itemMarginTop = itemMarginTop;\n\t\tlegend.padding = padding;\n\t\tlegend.initialItemX = padding;\n\t\tlegend.initialItemY = padding - 5; // 5 is the number of pixels above the text\n\t\tlegend.maxItemWidth = 0;\n\t\tlegend.chart = chart;\n\t\tlegend.itemHeight = 0;\n\t\tlegend.lastLineHeight = 0;\n\n\t\t// Render it\n\t\tlegend.render();\n\n\t\t// move checkboxes\n\t\taddEvent(legend.chart, 'endResize', function () { \n\t\t\tlegend.positionCheckboxes();\n\t\t});\n\n\t},\n\n\t/**\n\t * Set the colors for the legend item\n\t * @param {Object} item A Series or Point instance\n\t * @param {Object} visible Dimmed or colored\n\t */\n\tcolorizeItem: function (item, visible) {\n\t\tvar legend = this,\n\t\t\toptions = legend.options,\n\t\t\tlegendItem = item.legendItem,\n\t\t\tlegendLine = item.legendLine,\n\t\t\tlegendSymbol = item.legendSymbol,\n\t\t\thiddenColor = legend.itemHiddenStyle.color,\n\t\t\ttextColor = visible ? options.itemStyle.color : hiddenColor,\n\t\t\tsymbolColor = visible ? item.color : hiddenColor,\n\t\t\tmarkerOptions = item.options && item.options.marker,\n\t\t\tsymbolAttr = {\n\t\t\t\tstroke: symbolColor,\n\t\t\t\tfill: symbolColor\n\t\t\t},\n\t\t\tkey,\n\t\t\tval;\n\t\t\n\t\tif (legendItem) {\n\t\t\tlegendItem.css({ fill: textColor, color: textColor }); // color for #1553, oldIE\n\t\t}\n\t\tif (legendLine) {\n\t\t\tlegendLine.attr({ stroke: symbolColor });\n\t\t}\n\t\t\n\t\tif (legendSymbol) {\n\t\t\t\n\t\t\t// Apply marker options\n\t\t\tif (markerOptions && legendSymbol.isMarker) { // #585\n\t\t\t\tmarkerOptions = item.convertAttribs(markerOptions);\n\t\t\t\tfor (key in markerOptions) {\n\t\t\t\t\tval = markerOptions[key];\n\t\t\t\t\tif (val !== UNDEFINED) {\n\t\t\t\t\t\tsymbolAttr[key] = val;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlegendSymbol.attr(symbolAttr);\n\t\t}\n\t},\n\n\t/**\n\t * Position the legend item\n\t * @param {Object} item A Series or Point instance\n\t */\n\tpositionItem: function (item) {\n\t\tvar legend = this,\n\t\t\toptions = legend.options,\n\t\t\tsymbolPadding = options.symbolPadding,\n\t\t\tltr = !options.rtl,\n\t\t\tlegendItemPos = item._legendItemPos,\n\t\t\titemX = legendItemPos[0],\n\t\t\titemY = legendItemPos[1],\n\t\t\tcheckbox = item.checkbox;\n\n\t\tif (item.legendGroup) {\n\t\t\titem.legendGroup.translate(\n\t\t\t\tltr ? itemX : legend.legendWidth - itemX - 2 * symbolPadding - 4,\n\t\t\t\titemY\n\t\t\t);\n\t\t}\n\n\t\tif (checkbox) {\n\t\t\tcheckbox.x = itemX;\n\t\t\tcheckbox.y = itemY;\n\t\t}\n\t},\n\n\t/**\n\t * Destroy a single legend item\n\t * @param {Object} item The series or point\n\t */\n\tdestroyItem: function (item) {\n\t\tvar checkbox = item.checkbox;\n\n\t\t// destroy SVG elements\n\t\teach(['legendItem', 'legendLine', 'legendSymbol', 'legendGroup'], function (key) {\n\t\t\tif (item[key]) {\n\t\t\t\titem[key] = item[key].destroy();\n\t\t\t}\n\t\t});\n\n\t\tif (checkbox) {\n\t\t\tdiscardElement(item.checkbox);\n\t\t}\n\t},\n\n\t/**\n\t * Destroys the legend.\n\t */\n\tdestroy: function () {\n\t\tvar legend = this,\n\t\t\tlegendGroup = legend.group,\n\t\t\tbox = legend.box;\n\n\t\tif (box) {\n\t\t\tlegend.box = box.destroy();\n\t\t}\n\n\t\tif (legendGroup) {\n\t\t\tlegend.group = legendGroup.destroy();\n\t\t}\n\t},\n\n\t/**\n\t * Position the checkboxes after the width is determined\n\t */\n\tpositionCheckboxes: function (scrollOffset) {\n\t\tvar alignAttr = this.group.alignAttr,\n\t\t\ttranslateY,\n\t\t\tclipHeight = this.clipHeight || this.legendHeight;\n\n\t\tif (alignAttr) {\n\t\t\ttranslateY = alignAttr.translateY;\n\t\t\teach(this.allItems, function (item) {\n\t\t\t\tvar checkbox = item.checkbox,\n\t\t\t\t\ttop;\n\t\t\t\t\n\t\t\t\tif (checkbox) {\n\t\t\t\t\ttop = (translateY + checkbox.y + (scrollOffset || 0) + 3);\n\t\t\t\t\tcss(checkbox, {\n\t\t\t\t\t\tleft: (alignAttr.translateX + item.legendItemWidth + checkbox.x - 20) + PX,\n\t\t\t\t\t\ttop: top + PX,\n\t\t\t\t\t\tdisplay: top > translateY - 6 && top < translateY + clipHeight - 6 ? '' : NONE\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t},\n\t\n\t/**\n\t * Render the legend title on top of the legend\n\t */\n\trenderTitle: function () {\n\t\tvar options = this.options,\n\t\t\tpadding = this.padding,\n\t\t\ttitleOptions = options.title,\n\t\t\ttitleHeight = 0,\n\t\t\tbBox;\n\t\t\n\t\tif (titleOptions.text) {\n\t\t\tif (!this.title) {\n\t\t\t\tthis.title = this.chart.renderer.label(titleOptions.text, padding - 3, padding - 4, null, null, null, null, null, 'legend-title')\n\t\t\t\t\t.attr({ zIndex: 1 })\n\t\t\t\t\t.css(titleOptions.style)\n\t\t\t\t\t.add(this.group);\n\t\t\t}\n\t\t\tbBox = this.title.getBBox();\n\t\t\ttitleHeight = bBox.height;\n\t\t\tthis.offsetWidth = bBox.width; // #1717\n\t\t\tthis.contentGroup.attr({ translateY: titleHeight });\n\t\t}\n\t\tthis.titleHeight = titleHeight;\n\t},\n\n\t/**\n\t * Render a single specific legend item\n\t * @param {Object} item A series or point\n\t */\n\trenderItem: function (item) {\n\t\tvar legend = this,\n\t\t\tchart = legend.chart,\n\t\t\trenderer = chart.renderer,\n\t\t\toptions = legend.options,\n\t\t\thorizontal = options.layout === 'horizontal',\n\t\t\tsymbolWidth = options.symbolWidth,\n\t\t\tsymbolPadding = options.symbolPadding,\n\t\t\titemStyle = legend.itemStyle,\n\t\t\titemHiddenStyle = legend.itemHiddenStyle,\n\t\t\tpadding = legend.padding,\n\t\t\titemDistance = horizontal ? pick(options.itemDistance, 8) : 0, // docs\n\t\t\tltr = !options.rtl,\n\t\t\titemHeight,\n\t\t\twidthOption = options.width,\n\t\t\titemMarginBottom = options.itemMarginBottom || 0,\n\t\t\titemMarginTop = legend.itemMarginTop,\n\t\t\tinitialItemX = legend.initialItemX,\n\t\t\tbBox,\n\t\t\titemWidth,\n\t\t\tli = item.legendItem,\n\t\t\tseries = item.series || item,\n\t\t\titemOptions = series.options,\n\t\t\tshowCheckbox = itemOptions.showCheckbox,\n\t\t\tuseHTML = options.useHTML;\n\n\t\tif (!li) { // generate it once, later move it\n\n\t\t\t// Generate the group box\n\t\t\t// A group to hold the symbol and text. Text is to be appended in Legend class.\n\t\t\titem.legendGroup = renderer.g('legend-item')\n\t\t\t\t.attr({ zIndex: 1 })\n\t\t\t\t.add(legend.scrollGroup);\n\n\t\t\t// Draw the legend symbol inside the group box\n\t\t\tseries.drawLegendSymbol(legend, item);\n\n\t\t\t// Generate the list item text and add it to the group\n\t\t\titem.legendItem = li = renderer.text(\n\t\t\t\t\toptions.labelFormat ? format(options.labelFormat, item) : options.labelFormatter.call(item),\n\t\t\t\t\tltr ? symbolWidth + symbolPadding : -symbolPadding,\n\t\t\t\t\tlegend.baseline,\n\t\t\t\t\tuseHTML\n\t\t\t\t)\n\t\t\t\t.css(merge(item.visible ? itemStyle : itemHiddenStyle)) // merge to prevent modifying original (#1021)\n\t\t\t\t.attr({\n\t\t\t\t\talign: ltr ? 'left' : 'right',\n\t\t\t\t\tzIndex: 2\n\t\t\t\t})\n\t\t\t\t.add(item.legendGroup);\n\n\t\t\t// Set the events on the item group, or in case of useHTML, the item itself (#1249)\n\t\t\t(useHTML ? li : item.legendGroup).on('mouseover', function () {\n\t\t\t\t\titem.setState(HOVER_STATE);\n\t\t\t\t\tli.css(legend.options.itemHoverStyle);\n\t\t\t\t})\n\t\t\t\t.on('mouseout', function () {\n\t\t\t\t\tli.css(item.visible ? itemStyle : itemHiddenStyle);\n\t\t\t\t\titem.setState();\n\t\t\t\t})\n\t\t\t\t.on('click', function (event) {\n\t\t\t\t\tvar strLegendItemClick = 'legendItemClick',\n\t\t\t\t\t\tfnLegendItemClick = function () {\n\t\t\t\t\t\t\titem.setVisible();\n\t\t\t\t\t\t};\n\t\t\t\t\t\t\n\t\t\t\t\t// Pass over the click/touch event. #4.\n\t\t\t\t\tevent = {\n\t\t\t\t\t\tbrowserEvent: event\n\t\t\t\t\t};\n\n\t\t\t\t\t// click the name or symbol\n\t\t\t\t\tif (item.firePointEvent) { // point\n\t\t\t\t\t\titem.firePointEvent(strLegendItemClick, event, fnLegendItemClick);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfireEvent(item, strLegendItemClick, event, fnLegendItemClick);\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t// Colorize the items\n\t\t\tlegend.colorizeItem(item, item.visible);\n\n\t\t\t// add the HTML checkbox on top\n\t\t\tif (itemOptions && showCheckbox) {\n\t\t\t\titem.checkbox = createElement('input', {\n\t\t\t\t\ttype: 'checkbox',\n\t\t\t\t\tchecked: item.selected,\n\t\t\t\t\tdefaultChecked: item.selected // required by IE7\n\t\t\t\t}, options.itemCheckboxStyle, chart.container);\n\n\t\t\t\taddEvent(item.checkbox, 'click', function (event) {\n\t\t\t\t\tvar target = event.target;\n\t\t\t\t\tfireEvent(item, 'checkboxClick', {\n\t\t\t\t\t\t\tchecked: target.checked\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfunction () {\n\t\t\t\t\t\t\titem.select();\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// calculate the positions for the next line\n\t\tbBox = li.getBBox();\n\n\t\titemWidth = item.legendItemWidth =\n\t\t\toptions.itemWidth || symbolWidth + symbolPadding + bBox.width + itemDistance +\n\t\t\t(showCheckbox ? 20 : 0);\n\t\tlegend.itemHeight = itemHeight = bBox.height;\n\n\t\t// if the item exceeds the width, start a new line\n\t\tif (horizontal && legend.itemX - initialItemX + itemWidth >\n\t\t\t\t(widthOption || (chart.chartWidth - 2 * padding - initialItemX))) {\n\t\t\tlegend.itemX = initialItemX;\n\t\t\tlegend.itemY += itemMarginTop + legend.lastLineHeight + itemMarginBottom;\n\t\t\tlegend.lastLineHeight = 0; // reset for next line\n\t\t}\n\n\t\t// If the item exceeds the height, start a new column\n\t\t/*if (!horizontal && legend.itemY + options.y + itemHeight > chart.chartHeight - spacingTop - spacingBottom) {\n\t\t\tlegend.itemY = legend.initialItemY;\n\t\t\tlegend.itemX += legend.maxItemWidth;\n\t\t\tlegend.maxItemWidth = 0;\n\t\t}*/\n\n\t\t// Set the edge positions\n\t\tlegend.maxItemWidth = mathMax(legend.maxItemWidth, itemWidth);\n\t\tlegend.lastItemY = itemMarginTop + legend.itemY + itemMarginBottom;\n\t\tlegend.lastLineHeight = mathMax(itemHeight, legend.lastLineHeight); // #915\n\n\t\t// cache the position of the newly generated or reordered items\n\t\titem._legendItemPos = [legend.itemX, legend.itemY];\n\n\t\t// advance\n\t\tif (horizontal) {\n\t\t\tlegend.itemX += itemWidth;\n\n\t\t} else {\n\t\t\tlegend.itemY += itemMarginTop + itemHeight + itemMarginBottom;\n\t\t\tlegend.lastLineHeight = itemHeight;\n\t\t}\n\n\t\t// the width of the widest item\n\t\tlegend.offsetWidth = widthOption || mathMax(\n\t\t\t(horizontal ? legend.itemX - initialItemX - itemDistance : itemWidth) + padding,\n\t\t\tlegend.offsetWidth\n\t\t);\n\t},\n\n\t/**\n\t * Render the legend. This method can be called both before and after\n\t * chart.render. If called after, it will only rearrange items instead\n\t * of creating new ones.\n\t */\n\trender: function () {\n\t\tvar legend = this,\n\t\t\tchart = legend.chart,\n\t\t\trenderer = chart.renderer,\n\t\t\tlegendGroup = legend.group,\n\t\t\tallItems,\n\t\t\tdisplay,\n\t\t\tlegendWidth,\n\t\t\tlegendHeight,\n\t\t\tbox = legend.box,\n\t\t\toptions = legend.options,\n\t\t\tpadding = legend.padding,\n\t\t\tlegendBorderWidth = options.borderWidth,\n\t\t\tlegendBackgroundColor = options.backgroundColor;\n\n\t\tlegend.itemX = legend.initialItemX;\n\t\tlegend.itemY = legend.initialItemY;\n\t\tlegend.offsetWidth = 0;\n\t\tlegend.lastItemY = 0;\n\n\t\tif (!legendGroup) {\n\t\t\tlegend.group = legendGroup = renderer.g('legend')\n\t\t\t\t.attr({ zIndex: 7 }) \n\t\t\t\t.add();\n\t\t\tlegend.contentGroup = renderer.g()\n\t\t\t\t.attr({ zIndex: 1 }) // above background\n\t\t\t\t.add(legendGroup);\n\t\t\tlegend.scrollGroup = renderer.g()\n\t\t\t\t.add(legend.contentGroup);\n\t\t}\n\t\t\n\t\tlegend.renderTitle();\n\n\t\t// add each series or point\n\t\tallItems = [];\n\t\teach(chart.series, function (serie) {\n\t\t\tvar seriesOptions = serie.options;\n\n\t\t\tif (!seriesOptions.showInLegend || defined(seriesOptions.linkedTo)) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// use points or series for the legend item depending on legendType\n\t\t\tallItems = allItems.concat(\n\t\t\t\t\tserie.legendItems ||\n\t\t\t\t\t(seriesOptions.legendType === 'point' ?\n\t\t\t\t\t\t\tserie.data :\n\t\t\t\t\t\t\tserie)\n\t\t\t);\n\t\t});\n\n\t\t// sort by legendIndex\n\t\tstableSort(allItems, function (a, b) {\n\t\t\treturn ((a.options && a.options.legendIndex) || 0) - ((b.options && b.options.legendIndex) || 0);\n\t\t});\n\n\t\t// reversed legend\n\t\tif (options.reversed) {\n\t\t\tallItems.reverse();\n\t\t}\n\n\t\tlegend.allItems = allItems;\n\t\tlegend.display = display = !!allItems.length;\n\n\t\t// render the items\n\t\teach(allItems, function (item) {\n\t\t\tlegend.renderItem(item); \n\t\t});\n\n\t\t// Draw the border\n\t\tlegendWidth = options.width || legend.offsetWidth;\n\t\tlegendHeight = legend.lastItemY + legend.lastLineHeight + legend.titleHeight;\n\t\t\n\t\t\n\t\tlegendHeight = legend.handleOverflow(legendHeight);\n\n\t\tif (legendBorderWidth || legendBackgroundColor) {\n\t\t\tlegendWidth += padding;\n\t\t\tlegendHeight += padding;\n\n\t\t\tif (!box) {\n\t\t\t\tlegend.box = box = renderer.rect(\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t\tlegendWidth,\n\t\t\t\t\tlegendHeight,\n\t\t\t\t\toptions.borderRadius,\n\t\t\t\t\tlegendBorderWidth || 0\n\t\t\t\t).attr({\n\t\t\t\t\tstroke: options.borderColor,\n\t\t\t\t\t'stroke-width': legendBorderWidth || 0,\n\t\t\t\t\tfill: legendBackgroundColor || NONE\n\t\t\t\t})\n\t\t\t\t.add(legendGroup)\n\t\t\t\t.shadow(options.shadow);\n\t\t\t\tbox.isNew = true;\n\n\t\t\t} else if (legendWidth > 0 && legendHeight > 0) {\n\t\t\t\tbox[box.isNew ? 'attr' : 'animate'](\n\t\t\t\t\tbox.crisp(null, null, null, legendWidth, legendHeight)\n\t\t\t\t);\n\t\t\t\tbox.isNew = false;\n\t\t\t}\n\n\t\t\t// hide the border if no items\n\t\t\tbox[display ? 'show' : 'hide']();\n\t\t}\n\t\t\n\t\tlegend.legendWidth = legendWidth;\n\t\tlegend.legendHeight = legendHeight;\n\n\t\t// Now that the legend width and height are established, put the items in the \n\t\t// final position\n\t\teach(allItems, function (item) {\n\t\t\tlegend.positionItem(item);\n\t\t});\n\n\t\t// 1.x compatibility: positioning based on style\n\t\t/*var props = ['left', 'right', 'top', 'bottom'],\n\t\t\tprop,\n\t\t\ti = 4;\n\t\twhile (i--) {\n\t\t\tprop = props[i];\n\t\t\tif (options.style[prop] && options.style[prop] !== 'auto') {\n\t\t\t\toptions[i < 2 ? 'align' : 'verticalAlign'] = prop;\n\t\t\t\toptions[i < 2 ? 'x' : 'y'] = pInt(options.style[prop]) * (i % 2 ? -1 : 1);\n\t\t\t}\n\t\t}*/\n\n\t\tif (display) {\n\t\t\tlegendGroup.align(extend({\n\t\t\t\twidth: legendWidth,\n\t\t\t\theight: legendHeight\n\t\t\t}, options), true, 'spacingBox');\n\t\t}\n\n\t\tif (!chart.isResizing) {\n\t\t\tthis.positionCheckboxes();\n\t\t}\n\t},\n\t\n\t/**\n\t * Set up the overflow handling by adding navigation with up and down arrows below the\n\t * legend.\n\t */\n\thandleOverflow: function (legendHeight) {\n\t\tvar legend = this,\n\t\t\tchart = this.chart,\n\t\t\trenderer = chart.renderer,\n\t\t\tpageCount,\n\t\t\toptions = this.options,\n\t\t\toptionsY = options.y,\n\t\t\talignTop = options.verticalAlign === 'top',\n\t\t\tspaceHeight = chart.spacingBox.height + (alignTop ? -optionsY : optionsY) - this.padding,\n\t\t\tmaxHeight = options.maxHeight,\n\t\t\tclipHeight,\n\t\t\tclipRect = this.clipRect,\n\t\t\tnavOptions = options.navigation,\n\t\t\tanimation = pick(navOptions.animation, true),\n\t\t\tarrowSize = navOptions.arrowSize || 12,\n\t\t\tnav = this.nav;\n\t\t\t\n\t\t// Adjust the height\n\t\tif (options.layout === 'horizontal') {\n\t\t\tspaceHeight /= 2;\n\t\t}\n\t\tif (maxHeight) {\n\t\t\tspaceHeight = mathMin(spaceHeight, maxHeight);\n\t\t}\n\t\t\n\t\t// Reset the legend height and adjust the clipping rectangle\n\t\tif (legendHeight > spaceHeight && !options.useHTML) {\n\n\t\t\tthis.clipHeight = clipHeight = spaceHeight - 20 - this.titleHeight;\n\t\t\tthis.pageCount = pageCount = mathCeil(legendHeight / clipHeight);\n\t\t\tthis.currentPage = pick(this.currentPage, 1);\n\t\t\tthis.fullHeight = legendHeight;\n\t\t\t\n\t\t\t// Only apply clipping if needed. Clipping causes blurred legend in PDF export (#1787)\n\t\t\tif (!clipRect) {\n\t\t\t\tclipRect = legend.clipRect = renderer.clipRect(0, 0, 9999, 0);\n\t\t\t\tlegend.contentGroup.clip(clipRect);\n\t\t\t}\n\t\t\tclipRect.attr({\n\t\t\t\theight: clipHeight\n\t\t\t});\n\t\t\t\n\t\t\t// Add navigation elements\n\t\t\tif (!nav) {\n\t\t\t\tthis.nav = nav = renderer.g().attr({ zIndex: 1 }).add(this.group);\n\t\t\t\tthis.up = renderer.symbol('triangle', 0, 0, arrowSize, arrowSize)\n\t\t\t\t\t.on('click', function () {\n\t\t\t\t\t\tlegend.scroll(-1, animation);\n\t\t\t\t\t})\n\t\t\t\t\t.add(nav);\n\t\t\t\tthis.pager = renderer.text('', 15, 10)\n\t\t\t\t\t.css(navOptions.style)\n\t\t\t\t\t.add(nav);\n\t\t\t\tthis.down = renderer.symbol('triangle-down', 0, 0, arrowSize, arrowSize)\n\t\t\t\t\t.on('click', function () {\n\t\t\t\t\t\tlegend.scroll(1, animation);\n\t\t\t\t\t})\n\t\t\t\t\t.add(nav);\n\t\t\t}\n\t\t\t\n\t\t\t// Set initial position\n\t\t\tlegend.scroll(0);\n\t\t\t\n\t\t\tlegendHeight = spaceHeight;\n\t\t\t\n\t\t} else if (nav) {\n\t\t\tclipRect.attr({\n\t\t\t\theight: chart.chartHeight\n\t\t\t});\n\t\t\tnav.hide();\n\t\t\tthis.scrollGroup.attr({\n\t\t\t\ttranslateY: 1\n\t\t\t});\n\t\t\tthis.clipHeight = 0; // #1379\n\t\t}\n\t\t\n\t\treturn legendHeight;\n\t},\n\t\n\t/**\n\t * Scroll the legend by a number of pages\n\t * @param {Object} scrollBy\n\t * @param {Object} animation\n\t */\n\tscroll: function (scrollBy, animation) {\n\t\tvar pageCount = this.pageCount,\n\t\t\tcurrentPage = this.currentPage + scrollBy,\n\t\t\tclipHeight = this.clipHeight,\n\t\t\tnavOptions = this.options.navigation,\n\t\t\tactiveColor = navOptions.activeColor,\n\t\t\tinactiveColor = navOptions.inactiveColor,\n\t\t\tpager = this.pager,\n\t\t\tpadding = this.padding,\n\t\t\tscrollOffset;\n\t\t\n\t\t// When resizing while looking at the last page\n\t\tif (currentPage > pageCount) {\n\t\t\tcurrentPage = pageCount;\n\t\t}\n\t\t\n\t\tif (currentPage > 0) {\n\t\t\t\n\t\t\tif (animation !== UNDEFINED) {\n\t\t\t\tsetAnimation(animation, this.chart);\n\t\t\t}\n\t\t\t\n\t\t\tthis.nav.attr({\n\t\t\t\ttranslateX: padding,\n\t\t\t\ttranslateY: clipHeight + 7 + this.titleHeight,\n\t\t\t\tvisibility: VISIBLE\n\t\t\t});\n\t\t\tthis.up.attr({\n\t\t\t\t\tfill: currentPage === 1 ? inactiveColor : activeColor\n\t\t\t\t})\n\t\t\t\t.css({\n\t\t\t\t\tcursor: currentPage === 1 ? 'default' : 'pointer'\n\t\t\t\t});\n\t\t\tpager.attr({\n\t\t\t\ttext: currentPage + '/' + this.pageCount\n\t\t\t});\n\t\t\tthis.down.attr({\n\t\t\t\t\tx: 18 + this.pager.getBBox().width, // adjust to text width\n\t\t\t\t\tfill: currentPage === pageCount ? inactiveColor : activeColor\n\t\t\t\t})\n\t\t\t\t.css({\n\t\t\t\t\tcursor: currentPage === pageCount ? 'default' : 'pointer'\n\t\t\t\t});\n\t\t\t\n\t\t\tscrollOffset = -mathMin(clipHeight * (currentPage - 1), this.fullHeight - clipHeight + padding) + 1;\n\t\t\tthis.scrollGroup.animate({\n\t\t\t\ttranslateY: scrollOffset\n\t\t\t});\n\t\t\tpager.attr({\n\t\t\t\ttext: currentPage + '/' + pageCount\n\t\t\t});\n\t\t\t\n\t\t\t\n\t\t\tthis.currentPage = currentPage;\n\t\t\tthis.positionCheckboxes(scrollOffset);\n\t\t}\n\t\t\t\n\t}\n\t\n};\n\n/**\n * The chart class\n * @param {Object} options\n * @param {Function} callback Function to run when the chart has loaded\n */\nfunction Chart() {\n\tthis.init.apply(this, arguments);\n}\n\nChart.prototype = {\n\n\t/**\n\t * Initialize the chart\n\t */\n\tinit: function (userOptions, callback) {\n\n\t\t// Handle regular options\n\t\tvar options,\n\t\t\tseriesOptions = userOptions.series; // skip merging data points to increase performance\n\n\t\tuserOptions.series = null;\n\t\toptions = merge(defaultOptions, userOptions); // do the merge\n\t\toptions.series = userOptions.series = seriesOptions; // set back the series data\n\n\t\tvar optionsChart = options.chart,\n\t\t\toptionsMargin = optionsChart.margin,\n\t\t\tmargin = isObject(optionsMargin) ?\n\t\t\t\toptionsMargin :\n\t\t\t\t[optionsMargin, optionsMargin, optionsMargin, optionsMargin];\n\n\t\tthis.optionsMarginTop = pick(optionsChart.marginTop, margin[0]);\n\t\tthis.optionsMarginRight = pick(optionsChart.marginRight, margin[1]);\n\t\tthis.optionsMarginBottom = pick(optionsChart.marginBottom, margin[2]);\n\t\tthis.optionsMarginLeft = pick(optionsChart.marginLeft, margin[3]);\n\n\t\tvar chartEvents = optionsChart.events;\n\n\t\t//this.runChartClick = chartEvents && !!chartEvents.click;\n\t\tthis.bounds = { h: {}, v: {} }; // Pixel data bounds for touch zoom\n\n\t\tthis.callback = callback;\n\t\tthis.isResizing = 0;\n\t\tthis.options = options;\n\t\t//chartTitleOptions = UNDEFINED;\n\t\t//chartSubtitleOptions = UNDEFINED;\n\n\t\tthis.axes = [];\n\t\tthis.series = [];\n\t\tthis.hasCartesianSeries = optionsChart.showAxes;\n\t\t//this.axisOffset = UNDEFINED;\n\t\t//this.maxTicks = UNDEFINED; // handle the greatest amount of ticks on grouped axes\n\t\t//this.inverted = UNDEFINED;\n\t\t//this.loadingShown = UNDEFINED;\n\t\t//this.container = UNDEFINED;\n\t\t//this.chartWidth = UNDEFINED;\n\t\t//this.chartHeight = UNDEFINED;\n\t\t//this.marginRight = UNDEFINED;\n\t\t//this.marginBottom = UNDEFINED;\n\t\t//this.containerWidth = UNDEFINED;\n\t\t//this.containerHeight = UNDEFINED;\n\t\t//this.oldChartWidth = UNDEFINED;\n\t\t//this.oldChartHeight = UNDEFINED;\n\n\t\t//this.renderTo = UNDEFINED;\n\t\t//this.renderToClone = UNDEFINED;\n\n\t\t//this.spacingBox = UNDEFINED\n\n\t\t//this.legend = UNDEFINED;\n\n\t\t// Elements\n\t\t//this.chartBackground = UNDEFINED;\n\t\t//this.plotBackground = UNDEFINED;\n\t\t//this.plotBGImage = UNDEFINED;\n\t\t//this.plotBorder = UNDEFINED;\n\t\t//this.loadingDiv = UNDEFINED;\n\t\t//this.loadingSpan = UNDEFINED;\n\n\t\tvar chart = this,\n\t\t\teventType;\n\n\t\t// Add the chart to the global lookup\n\t\tchart.index = charts.length;\n\t\tcharts.push(chart);\n\n\t\t// Set up auto resize\n\t\tif (optionsChart.reflow !== false) {\n\t\t\taddEvent(chart, 'load', function () {\n\t\t\t\tchart.initReflow();\n\t\t\t});\n\t\t}\n\n\t\t// Chart event handlers\n\t\tif (chartEvents) {\n\t\t\tfor (eventType in chartEvents) {\n\t\t\t\taddEvent(chart, eventType, chartEvents[eventType]);\n\t\t\t}\n\t\t}\n\n\t\tchart.xAxis = [];\n\t\tchart.yAxis = [];\n\n\t\t// Expose methods and variables\n\t\tchart.animation = useCanVG ? false : pick(optionsChart.animation, true);\n\t\tchart.pointCount = 0;\n\t\tchart.counters = new ChartCounters();\n\n\t\tchart.firstRender();\n\t},\n\n\t/**\n\t * Initialize an individual series, called internally before render time\n\t */\n\tinitSeries: function (options) {\n\t\tvar chart = this,\n\t\t\toptionsChart = chart.options.chart,\n\t\t\ttype = options.type || optionsChart.type || optionsChart.defaultSeriesType,\n\t\t\tseries,\n\t\t\tconstr = seriesTypes[type];\n\n\t\t// No such series type\n\t\tif (!constr) {\n\t\t\terror(17, true);\n\t\t}\n\n\t\tseries = new constr();\n\t\tseries.init(this, options);\n\t\treturn series;\n\t},\n\n\t/**\n\t * Add a series dynamically after  time\n\t *\n\t * @param {Object} options The config options\n\t * @param {Boolean} redraw Whether to redraw the chart after adding. Defaults to true.\n\t * @param {Boolean|Object} animation Whether to apply animation, and optionally animation\n\t *    configuration\n\t *\n\t * @return {Object} series The newly created series object\n\t */\n\taddSeries: function (options, redraw, animation) {\n\t\tvar series,\n\t\t\tchart = this;\n\n\t\tif (options) {\n\t\t\tredraw = pick(redraw, true); // defaults to true\n\n\t\t\tfireEvent(chart, 'addSeries', { options: options }, function () {\n\t\t\t\tseries = chart.initSeries(options);\n\t\t\t\t\n\t\t\t\tchart.isDirtyLegend = true; // the series array is out of sync with the display\n\t\t\t\tif (redraw) {\n\t\t\t\t\tchart.redraw(animation);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\treturn series;\n\t},\n\n\t/**\n     * Add an axis to the chart\n     * @param {Object} options The axis option\n     * @param {Boolean} isX Whether it is an X axis or a value axis\n     */\n\taddAxis: function (options, isX, redraw, animation) {\n\t\tvar key = isX ? 'xAxis' : 'yAxis',\n\t\t\tchartOptions = this.options,\n\t\t\taxis;\n\n\t\t/*jslint unused: false*/\n\t\taxis = new Axis(this, merge(options, {\n\t\t\tindex: this[key].length,\n\t\t\tisX: isX\n\t\t}));\n\t\t/*jslint unused: true*/\n\n\t\t// Push the new axis options to the chart options\n\t\tchartOptions[key] = splat(chartOptions[key] || {});\n\t\tchartOptions[key].push(options);\n\n\t\tif (pick(redraw, true)) {\n\t\t\tthis.redraw(animation);\n\t\t}\n\t},\n\n\t/**\n\t * Check whether a given point is within the plot area\n\t *\n\t * @param {Number} plotX Pixel x relative to the plot area\n\t * @param {Number} plotY Pixel y relative to the plot area\n\t * @param {Boolean} inverted Whether the chart is inverted\n\t */\n\tisInsidePlot: function (plotX, plotY, inverted) {\n\t\tvar x = inverted ? plotY : plotX,\n\t\t\ty = inverted ? plotX : plotY;\n\t\t\t\n\t\treturn x >= 0 &&\n\t\t\tx <= this.plotWidth &&\n\t\t\ty >= 0 &&\n\t\t\ty <= this.plotHeight;\n\t},\n\n\t/**\n\t * Adjust all axes tick amounts\n\t */\n\tadjustTickAmounts: function () {\n\t\tif (this.options.chart.alignTicks !== false) {\n\t\t\teach(this.axes, function (axis) {\n\t\t\t\taxis.adjustTickAmount();\n\t\t\t});\n\t\t}\n\t\tthis.maxTicks = null;\n\t},\n\n\t/**\n\t * Redraw legend, axes or series based on updated data\n\t *\n\t * @param {Boolean|Object} animation Whether to apply animation, and optionally animation\n\t *    configuration\n\t */\n\tredraw: function (animation) {\n\t\tvar chart = this,\n\t\t\taxes = chart.axes,\n\t\t\tseries = chart.series,\n\t\t\tpointer = chart.pointer,\n\t\t\tlegend = chart.legend,\n\t\t\tredrawLegend = chart.isDirtyLegend,\n\t\t\thasStackedSeries,\n\t\t\thasDirtyStacks,\n\t\t\tisDirtyBox = chart.isDirtyBox, // todo: check if it has actually changed?\n\t\t\tseriesLength = series.length,\n\t\t\ti = seriesLength,\n\t\t\tserie,\n\t\t\trenderer = chart.renderer,\n\t\t\tisHiddenChart = renderer.isHidden(),\n\t\t\tafterRedraw = [];\n\t\t\t\n\t\tsetAnimation(animation, chart);\n\t\t\n\t\tif (isHiddenChart) {\n\t\t\tchart.cloneRenderTo();\n\t\t}\n\n\t\t// Adjust title layout (reflow multiline text)\n\t\tchart.layOutTitles();\n\n\t\t// link stacked series\n\t\twhile (i--) {\n\t\t\tserie = series[i];\n\n\t\t\tif (serie.options.stacking) {\n\t\t\t\thasStackedSeries = true;\n\t\t\t\t\n\t\t\t\tif (serie.isDirty) {\n\t\t\t\t\thasDirtyStacks = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (hasDirtyStacks) { // mark others as dirty\n\t\t\ti = seriesLength;\n\t\t\twhile (i--) {\n\t\t\t\tserie = series[i];\n\t\t\t\tif (serie.options.stacking) {\n\t\t\t\t\tserie.isDirty = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// handle updated data in the series\n\t\teach(series, function (serie) {\n\t\t\tif (serie.isDirty) { // prepare the data so axis can read it\n\t\t\t\tif (serie.options.legendType === 'point') {\n\t\t\t\t\tredrawLegend = true;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\t// handle added or removed series\n\t\tif (redrawLegend && legend.options.enabled) { // series or pie points are added or removed\n\t\t\t// draw legend graphics\n\t\t\tlegend.render();\n\n\t\t\tchart.isDirtyLegend = false;\n\t\t}\n\n\t\t// reset stacks\n\t\tif (hasStackedSeries) {\n\t\t\tchart.getStacks();\n\t\t}\n\n\n\t\tif (chart.hasCartesianSeries) {\n\t\t\tif (!chart.isResizing) {\n\n\t\t\t\t// reset maxTicks\n\t\t\t\tchart.maxTicks = null;\n\n\t\t\t\t// set axes scales\n\t\t\t\teach(axes, function (axis) {\n\t\t\t\t\taxis.setScale();\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\t// build stacks\n\t\t\t\teach(axes, function (axis) {\n\t\t\t\t\taxis.buildStacks();\n\t\t\t\t});\n\t\t\t}\n\t\t\tchart.adjustTickAmounts();\n\t\t\tchart.getMargins();\n\n\t\t\t// redraw axes\n\t\t\teach(axes, function (axis) {\n\t\t\t\t\n\t\t\t\t// Fire 'afterSetExtremes' only if extremes are set\n\t\t\t\tif (axis.isDirtyExtremes) { // #821\n\t\t\t\t\taxis.isDirtyExtremes = false;\n\t\t\t\t\tafterRedraw.push(function () { // prevent a recursive call to chart.redraw() (#1119)\n\t\t\t\t\t\tfireEvent(axis, 'afterSetExtremes', axis.getExtremes()); // #747, #751\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\t\t\t\t\t\n\t\t\t\tif (axis.isDirty || isDirtyBox || hasStackedSeries) {\n\t\t\t\t\taxis.redraw();\n\t\t\t\t\tisDirtyBox = true; // #792\n\t\t\t\t}\n\t\t\t});\n\n\n\t\t}\n\t\t// the plot areas size has changed\n\t\tif (isDirtyBox) {\n\t\t\tchart.drawChartBox();\n\t\t}\n\n\n\t\t// redraw affected series\n\t\teach(series, function (serie) {\n\t\t\tif (serie.isDirty && serie.visible &&\n\t\t\t\t\t(!serie.isCartesian || serie.xAxis)) { // issue #153\n\t\t\t\tserie.redraw();\n\t\t\t}\n\t\t});\n\n\t\t// move tooltip or reset\n\t\tif (pointer && pointer.reset) {\n\t\t\tpointer.reset(true);\n\t\t}\n\n\t\t// redraw if canvas\n\t\trenderer.draw();\n\n\t\t// fire the event\n\t\tfireEvent(chart, 'redraw'); // jQuery breaks this when calling it from addEvent. Overwrites chart.redraw\n\t\t\n\t\tif (isHiddenChart) {\n\t\t\tchart.cloneRenderTo(true);\n\t\t}\n\t\t\n\t\t// Fire callbacks that are put on hold until after the redraw\n\t\teach(afterRedraw, function (callback) {\n\t\t\tcallback.call();\n\t\t});\n\t},\n\n\n\n\t/**\n\t * Dim the chart and show a loading text or symbol\n\t * @param {String} str An optional text to show in the loading label instead of the default one\n\t */\n\tshowLoading: function (str) {\n\t\tvar chart = this,\n\t\t\toptions = chart.options,\n\t\t\tloadingDiv = chart.loadingDiv;\n\n\t\tvar loadingOptions = options.loading;\n\n\t\t// create the layer at the first call\n\t\tif (!loadingDiv) {\n\t\t\tchart.loadingDiv = loadingDiv = createElement(DIV, {\n\t\t\t\tclassName: PREFIX + 'loading'\n\t\t\t}, extend(loadingOptions.style, {\n\t\t\t\tzIndex: 10,\n\t\t\t\tdisplay: NONE\n\t\t\t}), chart.container);\n\n\t\t\tchart.loadingSpan = createElement(\n\t\t\t\t'span',\n\t\t\t\tnull,\n\t\t\t\tloadingOptions.labelStyle,\n\t\t\t\tloadingDiv\n\t\t\t);\n\n\t\t}\n\n\t\t// update text\n\t\tchart.loadingSpan.innerHTML = str || options.lang.loading;\n\n\t\t// show it\n\t\tif (!chart.loadingShown) {\n\t\t\tcss(loadingDiv, { \n\t\t\t\topacity: 0, \n\t\t\t\tdisplay: '',\n\t\t\t\tleft: chart.plotLeft + PX,\n\t\t\t\ttop: chart.plotTop + PX,\n\t\t\t\twidth: chart.plotWidth + PX,\n\t\t\t\theight: chart.plotHeight + PX\n\t\t\t});\n\t\t\tanimate(loadingDiv, {\n\t\t\t\topacity: loadingOptions.style.opacity\n\t\t\t}, {\n\t\t\t\tduration: loadingOptions.showDuration || 0\n\t\t\t});\n\t\t\tchart.loadingShown = true;\n\t\t}\n\t},\n\n\t/**\n\t * Hide the loading layer\n\t */\n\thideLoading: function () {\n\t\tvar options = this.options,\n\t\t\tloadingDiv = this.loadingDiv;\n\n\t\tif (loadingDiv) {\n\t\t\tanimate(loadingDiv, {\n\t\t\t\topacity: 0\n\t\t\t}, {\n\t\t\t\tduration: options.loading.hideDuration || 100,\n\t\t\t\tcomplete: function () {\n\t\t\t\t\tcss(loadingDiv, { display: NONE });\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\tthis.loadingShown = false;\n\t},\n\n\t/**\n\t * Get an axis, series or point object by id.\n\t * @param id {String} The id as given in the configuration options\n\t */\n\tget: function (id) {\n\t\tvar chart = this,\n\t\t\taxes = chart.axes,\n\t\t\tseries = chart.series;\n\n\t\tvar i,\n\t\t\tj,\n\t\t\tpoints;\n\n\t\t// search axes\n\t\tfor (i = 0; i < axes.length; i++) {\n\t\t\tif (axes[i].options.id === id) {\n\t\t\t\treturn axes[i];\n\t\t\t}\n\t\t}\n\n\t\t// search series\n\t\tfor (i = 0; i < series.length; i++) {\n\t\t\tif (series[i].options.id === id) {\n\t\t\t\treturn series[i];\n\t\t\t}\n\t\t}\n\n\t\t// search points\n\t\tfor (i = 0; i < series.length; i++) {\n\t\t\tpoints = series[i].points || [];\n\t\t\tfor (j = 0; j < points.length; j++) {\n\t\t\t\tif (points[j].id === id) {\n\t\t\t\t\treturn points[j];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t},\n\n\t/**\n\t * Create the Axis instances based on the config options\n\t */\n\tgetAxes: function () {\n\t\tvar chart = this,\n\t\t\toptions = this.options,\n\t\t\txAxisOptions = options.xAxis = splat(options.xAxis || {}),\n\t\t\tyAxisOptions = options.yAxis = splat(options.yAxis || {}),\n\t\t\toptionsArray,\n\t\t\taxis;\n\n\t\t// make sure the options are arrays and add some members\n\t\teach(xAxisOptions, function (axis, i) {\n\t\t\taxis.index = i;\n\t\t\taxis.isX = true;\n\t\t});\n\n\t\teach(yAxisOptions, function (axis, i) {\n\t\t\taxis.index = i;\n\t\t});\n\n\t\t// concatenate all axis options into one array\n\t\toptionsArray = xAxisOptions.concat(yAxisOptions);\n\n\t\teach(optionsArray, function (axisOptions) {\n\t\t\taxis = new Axis(chart, axisOptions);\n\t\t});\n\n\t\tchart.adjustTickAmounts();\n\t},\n\n\n\t/**\n\t * Get the currently selected points from all series\n\t */\n\tgetSelectedPoints: function () {\n\t\tvar points = [];\n\t\teach(this.series, function (serie) {\n\t\t\tpoints = points.concat(grep(serie.points || [], function (point) {\n\t\t\t\treturn point.selected;\n\t\t\t}));\n\t\t});\n\t\treturn points;\n\t},\n\n\t/**\n\t * Get the currently selected series\n\t */\n\tgetSelectedSeries: function () {\n\t\treturn grep(this.series, function (serie) {\n\t\t\treturn serie.selected;\n\t\t});\n\t},\n\n\t/**\n\t * Generate stacks for each series and calculate stacks total values\n\t */\n\tgetStacks: function () {\n\t\tvar chart = this;\n\n\t\t// reset stacks for each yAxis\n\t\teach(chart.yAxis, function (axis) {\n\t\t\tif (axis.stacks && axis.hasVisibleSeries) {\n\t\t\t\taxis.oldStacks = axis.stacks;\n\t\t\t}\n\t\t});\n\n\t\teach(chart.series, function (series) {\n\t\t\tif (series.options.stacking && (series.visible === true || chart.options.chart.ignoreHiddenSeries === false)) {\n\t\t\t\tseries.stackKey = series.type + pick(series.options.stack, '');\n\t\t\t}\n\t\t});\n\t},\n\n\t/**\n\t * Display the zoom button\n\t */\n\tshowResetZoom: function () {\n\t\tvar chart = this,\n\t\t\tlang = defaultOptions.lang,\n\t\t\tbtnOptions = chart.options.chart.resetZoomButton,\n\t\t\ttheme = btnOptions.theme,\n\t\t\tstates = theme.states,\n\t\t\talignTo = btnOptions.relativeTo === 'chart' ? null : 'plotBox';\n\t\t\t\n\t\tthis.resetZoomButton = chart.renderer.button(lang.resetZoom, null, null, function () { chart.zoomOut(); }, theme, states && states.hover)\n\t\t\t.attr({\n\t\t\t\talign: btnOptions.position.align,\n\t\t\t\ttitle: lang.resetZoomTitle\n\t\t\t})\n\t\t\t.add()\n\t\t\t.align(btnOptions.position, false, alignTo);\n\t\t\t\n\t},\n\n\t/**\n\t * Zoom out to 1:1\n\t */\n\tzoomOut: function () {\n\t\tvar chart = this;\n\t\tfireEvent(chart, 'selection', { resetSelection: true }, function () { \n\t\t\tchart.zoom();\n\t\t});\n\t},\n\n\t/**\n\t * Zoom into a given portion of the chart given by axis coordinates\n\t * @param {Object} event\n\t */\n\tzoom: function (event) {\n\t\tvar chart = this,\n\t\t\thasZoomed,\n\t\t\tpointer = chart.pointer,\n\t\t\tdisplayButton = false,\n\t\t\tresetZoomButton;\n\n\t\t// If zoom is called with no arguments, reset the axes\n\t\tif (!event || event.resetSelection) {\n\t\t\teach(chart.axes, function (axis) {\n\t\t\t\thasZoomed = axis.zoom();\n\t\t\t});\n\t\t} else { // else, zoom in on all axes\n\t\t\teach(event.xAxis.concat(event.yAxis), function (axisData) {\n\t\t\t\tvar axis = axisData.axis,\n\t\t\t\t\tisXAxis = axis.isXAxis;\n\n\t\t\t\t// don't zoom more than minRange\n\t\t\t\tif (pointer[isXAxis ? 'zoomX' : 'zoomY'] || pointer[isXAxis ? 'pinchX' : 'pinchY']) {\n\t\t\t\t\thasZoomed = axis.zoom(axisData.min, axisData.max);\n\t\t\t\t\tif (axis.displayBtn) {\n\t\t\t\t\t\tdisplayButton = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\t\n\t\t// Show or hide the Reset zoom button\n\t\tresetZoomButton = chart.resetZoomButton;\n\t\tif (displayButton && !resetZoomButton) {\n\t\t\tchart.showResetZoom();\n\t\t} else if (!displayButton && isObject(resetZoomButton)) {\n\t\t\tchart.resetZoomButton = resetZoomButton.destroy();\n\t\t}\n\t\t\n\n\t\t// Redraw\n\t\tif (hasZoomed) {\n\t\t\tchart.redraw(\n\t\t\t\tpick(chart.options.chart.animation, event && event.animation, chart.pointCount < 100) // animation\n\t\t\t);\n\t\t}\n\t},\n\n\t/**\n\t * Pan the chart by dragging the mouse across the pane. This function is called\n\t * on mouse move, and the distance to pan is computed from chartX compared to\n\t * the first chartX position in the dragging operation.\n\t */\n\tpan: function (chartX) {\n\t\tvar chart = this,\n\t\t\txAxis = chart.xAxis[0],\n\t\t\tmouseDownX = chart.mouseDownX,\n\t\t\thalfPointRange = xAxis.pointRange / 2,\n\t\t\textremes = xAxis.getExtremes(),\n\t\t\tnewMin = xAxis.translate(mouseDownX - chartX, true) + halfPointRange,\n\t\t\tnewMax = xAxis.translate(mouseDownX + chart.plotWidth - chartX, true) - halfPointRange,\n\t\t\thoverPoints = chart.hoverPoints;\n\n\t\t// remove active points for shared tooltip\n\t\tif (hoverPoints) {\n\t\t\teach(hoverPoints, function (point) {\n\t\t\t\tpoint.setState();\n\t\t\t});\n\t\t}\n\n\t\tif (xAxis.series.length && newMin > mathMin(extremes.dataMin, extremes.min) && newMax < mathMax(extremes.dataMax, extremes.max)) {\n\t\t\txAxis.setExtremes(newMin, newMax, true, false, { trigger: 'pan' });\n\t\t}\n\n\t\tchart.mouseDownX = chartX; // set new reference for next run\n\t\tcss(chart.container, { cursor: 'move' });\n\t},\n\n\t/**\n\t * Show the title and subtitle of the chart\n\t *\n\t * @param titleOptions {Object} New title options\n\t * @param subtitleOptions {Object} New subtitle options\n\t *\n\t */\n\tsetTitle: function (titleOptions, subtitleOptions) {\n\t\tvar chart = this,\n\t\t\toptions = chart.options,\n\t\t\tchartTitleOptions,\n\t\t\tchartSubtitleOptions;\n\n\t\tchartTitleOptions = options.title = merge(options.title, titleOptions);\n\t\tchartSubtitleOptions = options.subtitle = merge(options.subtitle, subtitleOptions);\n\n\t\t// add title and subtitle\n\t\teach([\n\t\t\t['title', titleOptions, chartTitleOptions],\n\t\t\t['subtitle', subtitleOptions, chartSubtitleOptions]\n\t\t], function (arr) {\n\t\t\tvar name = arr[0],\n\t\t\t\ttitle = chart[name],\n\t\t\t\ttitleOptions = arr[1],\n\t\t\t\tchartTitleOptions = arr[2];\n\n\t\t\tif (title && titleOptions) {\n\t\t\t\tchart[name] = title = title.destroy(); // remove old\n\t\t\t}\n\t\t\t\n\t\t\tif (chartTitleOptions && chartTitleOptions.text && !title) {\n\t\t\t\tchart[name] = chart.renderer.text(\n\t\t\t\t\tchartTitleOptions.text,\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t\tchartTitleOptions.useHTML\n\t\t\t\t)\n\t\t\t\t.attr({\n\t\t\t\t\talign: chartTitleOptions.align,\n\t\t\t\t\t'class': PREFIX + name,\n\t\t\t\t\tzIndex: chartTitleOptions.zIndex || 4\n\t\t\t\t})\n\t\t\t\t.css(chartTitleOptions.style)\n\t\t\t\t.add();\n\t\t\t}\t\n\t\t});\n\t\tchart.layOutTitles();\n\t},\n\n\t/**\n\t * Lay out the chart titles and cache the full offset height for use in getMargins\n\t */\n\tlayOutTitles: function () {\n\t\tvar titleOffset = 0,\n\t\t\ttitle = this.title,\n\t\t\tsubtitle = this.subtitle,\n\t\t\toptions = this.options,\n\t\t\ttitleOptions = options.title,\n\t\t\tsubtitleOptions = options.subtitle,\n\t\t\tautoWidth = this.spacingBox.width - 44; // 44 makes room for default context button\n\n\t\tif (title) {\n\t\t\ttitle\n\t\t\t\t.css({ width: (titleOptions.width || autoWidth) + PX })\n\t\t\t\t.align(extend({ y: 15 }, titleOptions), false, 'spacingBox');\n\t\t\t\n\t\t\tif (!titleOptions.floating && !titleOptions.verticalAlign) {\n\t\t\t\ttitleOffset = title.getBBox().height;\n\n\t\t\t\t// Adjust for browser consistency + backwards compat after #776 fix\n\t\t\t\tif (titleOffset >= 18 && titleOffset <= 25) {\n\t\t\t\t\ttitleOffset = 15; \n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (subtitle) {\n\t\t\tsubtitle\n\t\t\t\t.css({ width: (subtitleOptions.width || autoWidth) + PX })\n\t\t\t\t.align(extend({ y: titleOffset + titleOptions.margin }, subtitleOptions), false, 'spacingBox');\n\t\t\t\n\t\t\tif (!subtitleOptions.floating && !subtitleOptions.verticalAlign) {\n\t\t\t\ttitleOffset = mathCeil(titleOffset + subtitle.getBBox().height);\n\t\t\t}\n\t\t}\n\n\t\tthis.titleOffset = titleOffset; // used in getMargins\n\t},\n\n\t/**\n\t * Get chart width and height according to options and container size\n\t */\n\tgetChartSize: function () {\n\t\tvar chart = this,\n\t\t\toptionsChart = chart.options.chart,\n\t\t\trenderTo = chart.renderToClone || chart.renderTo;\n\n\t\t// get inner width and height from jQuery (#824)\n\t\tchart.containerWidth = adapterRun(renderTo, 'width');\n\t\tchart.containerHeight = adapterRun(renderTo, 'height');\n\t\t\n\t\tchart.chartWidth = mathMax(0, optionsChart.width || chart.containerWidth || 600); // #1393, 1460\n\t\tchart.chartHeight = mathMax(0, pick(optionsChart.height,\n\t\t\t// the offsetHeight of an empty container is 0 in standard browsers, but 19 in IE7:\n\t\t\tchart.containerHeight > 19 ? chart.containerHeight : 400));\n\t},\n\n\t/**\n\t * Create a clone of the chart's renderTo div and place it outside the viewport to allow\n\t * size computation on chart.render and chart.redraw\n\t */\n\tcloneRenderTo: function (revert) {\n\t\tvar clone = this.renderToClone,\n\t\t\tcontainer = this.container;\n\t\t\n\t\t// Destroy the clone and bring the container back to the real renderTo div\n\t\tif (revert) {\n\t\t\tif (clone) {\n\t\t\t\tthis.renderTo.appendChild(container);\n\t\t\t\tdiscardElement(clone);\n\t\t\t\tdelete this.renderToClone;\n\t\t\t}\n\t\t\n\t\t// Set up the clone\n\t\t} else {\n\t\t\tif (container && container.parentNode === this.renderTo) {\n\t\t\t\tthis.renderTo.removeChild(container); // do not clone this\n\t\t\t}\n\t\t\tthis.renderToClone = clone = this.renderTo.cloneNode(0);\n\t\t\tcss(clone, {\n\t\t\t\tposition: ABSOLUTE,\n\t\t\t\ttop: '-9999px',\n\t\t\t\tdisplay: 'block' // #833\n\t\t\t});\n\t\t\tdoc.body.appendChild(clone);\n\t\t\tif (container) {\n\t\t\t\tclone.appendChild(container);\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Get the containing element, determine the size and create the inner container\n\t * div to hold the chart\n\t */\n\tgetContainer: function () {\n\t\tvar chart = this,\n\t\t\tcontainer,\n\t\t\toptionsChart = chart.options.chart,\n\t\t\tchartWidth,\n\t\t\tchartHeight,\n\t\t\trenderTo,\n\t\t\tindexAttrName = 'data-highcharts-chart',\n\t\t\toldChartIndex,\n\t\t\tcontainerId;\n\n\t\tchart.renderTo = renderTo = optionsChart.renderTo;\n\t\tcontainerId = PREFIX + idCounter++;\n\n\t\tif (isString(renderTo)) {\n\t\t\tchart.renderTo = renderTo = doc.getElementById(renderTo);\n\t\t}\n\t\t\n\t\t// Display an error if the renderTo is wrong\n\t\tif (!renderTo) {\n\t\t\terror(13, true);\n\t\t}\n\t\t\n\t\t// If the container already holds a chart, destroy it\n\t\toldChartIndex = pInt(attr(renderTo, indexAttrName));\n\t\tif (!isNaN(oldChartIndex) && charts[oldChartIndex]) {\n\t\t\tcharts[oldChartIndex].destroy();\n\t\t}\t\t\n\t\t\n\t\t// Make a reference to the chart from the div\n\t\tattr(renderTo, indexAttrName, chart.index);\n\n\t\t// remove previous chart\n\t\trenderTo.innerHTML = '';\n\n\t\t// If the container doesn't have an offsetWidth, it has or is a child of a node\n\t\t// that has display:none. We need to temporarily move it out to a visible\n\t\t// state to determine the size, else the legend and tooltips won't render\n\t\t// properly\n\t\tif (!renderTo.offsetWidth) {\n\t\t\tchart.cloneRenderTo();\n\t\t}\n\n\t\t// get the width and height\n\t\tchart.getChartSize();\n\t\tchartWidth = chart.chartWidth;\n\t\tchartHeight = chart.chartHeight;\n\n\t\t// create the inner container\n\t\tchart.container = container = createElement(DIV, {\n\t\t\t\tclassName: PREFIX + 'container' +\n\t\t\t\t\t(optionsChart.className ? ' ' + optionsChart.className : ''),\n\t\t\t\tid: containerId\n\t\t\t}, extend({\n\t\t\t\tposition: RELATIVE,\n\t\t\t\toverflow: HIDDEN, // needed for context menu (avoid scrollbars) and\n\t\t\t\t\t// content overflow in IE\n\t\t\t\twidth: chartWidth + PX,\n\t\t\t\theight: chartHeight + PX,\n\t\t\t\ttextAlign: 'left',\n\t\t\t\tlineHeight: 'normal', // #427\n\t\t\t\tzIndex: 0, // #1072\n\t\t\t\t'-webkit-tap-highlight-color': 'rgba(0,0,0,0)'\n\t\t\t}, optionsChart.style),\n\t\t\tchart.renderToClone || renderTo\n\t\t);\n\n\t\t// cache the cursor (#1650)\n\t\tchart._cursor = container.style.cursor;\n\n\t\tchart.renderer =\n\t\t\toptionsChart.forExport ? // force SVG, used for SVG export\n\t\t\t\tnew SVGRenderer(container, chartWidth, chartHeight, true) :\n\t\t\t\tnew Renderer(container, chartWidth, chartHeight);\n\n\t\tif (useCanVG) {\n\t\t\t// If we need canvg library, extend and configure the renderer\n\t\t\t// to get the tracker for translating mouse events\n\t\t\tchart.renderer.create(chart, container, chartWidth, chartHeight);\n\t\t}\n\t},\n\n\t/**\n\t * Calculate margins by rendering axis labels in a preliminary position. Title,\n\t * subtitle and legend have already been rendered at this stage, but will be\n\t * moved into their final positions\n\t */\n\tgetMargins: function () {\n\t\tvar chart = this,\n\t\t\toptionsChart = chart.options.chart,\n\t\t\tspacingTop = optionsChart.spacingTop,\n\t\t\tspacingRight = optionsChart.spacingRight,\n\t\t\tspacingBottom = optionsChart.spacingBottom,\n\t\t\tspacingLeft = optionsChart.spacingLeft,\n\t\t\taxisOffset,\n\t\t\tlegend = chart.legend,\n\t\t\toptionsMarginTop = chart.optionsMarginTop,\n\t\t\toptionsMarginLeft = chart.optionsMarginLeft,\n\t\t\toptionsMarginRight = chart.optionsMarginRight,\n\t\t\toptionsMarginBottom = chart.optionsMarginBottom,\n\t\t\tlegendOptions = chart.options.legend,\n\t\t\tlegendMargin = pick(legendOptions.margin, 10),\n\t\t\tlegendX = legendOptions.x,\n\t\t\tlegendY = legendOptions.y,\n\t\t\talign = legendOptions.align,\n\t\t\tverticalAlign = legendOptions.verticalAlign,\n\t\t\ttitleOffset = chart.titleOffset;\n\n\t\tchart.resetMargins();\n\t\taxisOffset = chart.axisOffset;\n\n\t\t// Adjust for title and subtitle\n\t\tif (titleOffset && !defined(optionsMarginTop)) {\n\t\t\tchart.plotTop = mathMax(chart.plotTop, titleOffset + chart.options.title.margin + spacingTop);\n\t\t}\n\t\t\n\t\t// Adjust for legend\n\t\tif (legend.display && !legendOptions.floating) {\n\t\t\tif (align === 'right') { // horizontal alignment handled first\n\t\t\t\tif (!defined(optionsMarginRight)) {\n\t\t\t\t\tchart.marginRight = mathMax(\n\t\t\t\t\t\tchart.marginRight,\n\t\t\t\t\t\tlegend.legendWidth - legendX + legendMargin + spacingRight\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} else if (align === 'left') {\n\t\t\t\tif (!defined(optionsMarginLeft)) {\n\t\t\t\t\tchart.plotLeft = mathMax(\n\t\t\t\t\t\tchart.plotLeft,\n\t\t\t\t\t\tlegend.legendWidth + legendX + legendMargin + spacingLeft\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t} else if (verticalAlign === 'top') {\n\t\t\t\tif (!defined(optionsMarginTop)) {\n\t\t\t\t\tchart.plotTop = mathMax(\n\t\t\t\t\t\tchart.plotTop,\n\t\t\t\t\t\tlegend.legendHeight + legendY + legendMargin + spacingTop\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t} else if (verticalAlign === 'bottom') {\n\t\t\t\tif (!defined(optionsMarginBottom)) {\n\t\t\t\t\tchart.marginBottom = mathMax(\n\t\t\t\t\t\tchart.marginBottom,\n\t\t\t\t\t\tlegend.legendHeight - legendY + legendMargin + spacingBottom\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// adjust for scroller\n\t\tif (chart.extraBottomMargin) {\n\t\t\tchart.marginBottom += chart.extraBottomMargin;\n\t\t}\n\t\tif (chart.extraTopMargin) {\n\t\t\tchart.plotTop += chart.extraTopMargin;\n\t\t}\n\n\t\t// pre-render axes to get labels offset width\n\t\tif (chart.hasCartesianSeries) {\n\t\t\teach(chart.axes, function (axis) {\n\t\t\t\taxis.getOffset();\n\t\t\t});\n\t\t}\n\t\t\n\t\tif (!defined(optionsMarginLeft)) {\n\t\t\tchart.plotLeft += axisOffset[3];\n\t\t}\n\t\tif (!defined(optionsMarginTop)) {\n\t\t\tchart.plotTop += axisOffset[0];\n\t\t}\n\t\tif (!defined(optionsMarginBottom)) {\n\t\t\tchart.marginBottom += axisOffset[2];\n\t\t}\n\t\tif (!defined(optionsMarginRight)) {\n\t\t\tchart.marginRight += axisOffset[1];\n\t\t}\n\n\t\tchart.setChartSize();\n\n\t},\n\n\t/**\n\t * Add the event handlers necessary for auto resizing\n\t *\n\t */\n\tinitReflow: function () {\n\t\tvar chart = this,\n\t\t\toptionsChart = chart.options.chart,\n\t\t\trenderTo = chart.renderTo,\n\t\t\treflowTimeout;\n\t\t\t\n\t\tfunction reflow(e) {\n\t\t\tvar width = optionsChart.width || adapterRun(renderTo, 'width'),\n\t\t\t\theight = optionsChart.height || adapterRun(renderTo, 'height'),\n\t\t\t\ttarget = e ? e.target : win; // #805 - MooTools doesn't supply e\n\t\t\t\t\n\t\t\t// Width and height checks for display:none. Target is doc in IE8 and Opera,\n\t\t\t// win in Firefox, Chrome and IE9.\n\t\t\tif (!chart.hasUserSize && width && height && (target === win || target === doc)) {\n\t\t\t\t\n\t\t\t\tif (width !== chart.containerWidth || height !== chart.containerHeight) {\n\t\t\t\t\tclearTimeout(reflowTimeout);\n\t\t\t\t\tchart.reflowTimeout = reflowTimeout = setTimeout(function () {\n\t\t\t\t\t\tif (chart.container) { // It may have been destroyed in the meantime (#1257)\n\t\t\t\t\t\t\tchart.setSize(width, height, false);\n\t\t\t\t\t\t\tchart.hasUserSize = null;\n\t\t\t\t\t\t}\n\t\t\t\t\t}, 100);\n\t\t\t\t}\n\t\t\t\tchart.containerWidth = width;\n\t\t\t\tchart.containerHeight = height;\n\t\t\t}\n\t\t}\n\t\taddEvent(win, 'resize', reflow);\n\t\taddEvent(chart, 'destroy', function () {\n\t\t\tremoveEvent(win, 'resize', reflow);\n\t\t});\n\t},\n\n\t/**\n\t * Resize the chart to a given width and height\n\t * @param {Number} width\n\t * @param {Number} height\n\t * @param {Object|Boolean} animation\n\t */\n\tsetSize: function (width, height, animation) {\n\t\tvar chart = this,\n\t\t\tchartWidth,\n\t\t\tchartHeight,\n\t\t\tfireEndResize;\n\n\t\t// Handle the isResizing counter\n\t\tchart.isResizing += 1;\n\t\tfireEndResize = function () {\n\t\t\tif (chart) {\n\t\t\t\tfireEvent(chart, 'endResize', null, function () {\n\t\t\t\t\tchart.isResizing -= 1;\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\n\t\t// set the animation for the current process\n\t\tsetAnimation(animation, chart);\n\n\t\tchart.oldChartHeight = chart.chartHeight;\n\t\tchart.oldChartWidth = chart.chartWidth;\n\t\tif (defined(width)) {\n\t\t\tchart.chartWidth = chartWidth = mathMax(0, mathRound(width));\n\t\t\tchart.hasUserSize = !!chartWidth;\n\t\t}\n\t\tif (defined(height)) {\n\t\t\tchart.chartHeight = chartHeight = mathMax(0, mathRound(height));\n\t\t}\n\n\t\tcss(chart.container, {\n\t\t\twidth: chartWidth + PX,\n\t\t\theight: chartHeight + PX\n\t\t});\n\t\tchart.setChartSize(true);\n\t\tchart.renderer.setSize(chartWidth, chartHeight, animation);\n\n\t\t// handle axes\n\t\tchart.maxTicks = null;\n\t\teach(chart.axes, function (axis) {\n\t\t\taxis.isDirty = true;\n\t\t\taxis.setScale();\n\t\t});\n\n\t\t// make sure non-cartesian series are also handled\n\t\teach(chart.series, function (serie) {\n\t\t\tserie.isDirty = true;\n\t\t});\n\n\t\tchart.isDirtyLegend = true; // force legend redraw\n\t\tchart.isDirtyBox = true; // force redraw of plot and chart border\n\n\t\tchart.getMargins();\n\n\t\tchart.redraw(animation);\n\n\n\t\tchart.oldChartHeight = null;\n\t\tfireEvent(chart, 'resize');\n\n\t\t// fire endResize and set isResizing back\n\t\t// If animation is disabled, fire without delay\n\t\tif (globalAnimation === false) {\n\t\t\tfireEndResize();\n\t\t} else { // else set a timeout with the animation duration\n\t\t\tsetTimeout(fireEndResize, (globalAnimation && globalAnimation.duration) || 500);\n\t\t}\n\t},\n\n\t/**\n\t * Set the public chart properties. This is done before and after the pre-render\n\t * to determine margin sizes\n\t */\n\tsetChartSize: function (skipAxes) {\n\t\tvar chart = this,\n\t\t\tinverted = chart.inverted,\n\t\t\trenderer = chart.renderer,\n\t\t\tchartWidth = chart.chartWidth,\n\t\t\tchartHeight = chart.chartHeight,\n\t\t\toptionsChart = chart.options.chart,\n\t\t\tspacingTop = optionsChart.spacingTop,\n\t\t\tspacingRight = optionsChart.spacingRight,\n\t\t\tspacingBottom = optionsChart.spacingBottom,\n\t\t\tspacingLeft = optionsChart.spacingLeft,\n\t\t\tclipOffset = chart.clipOffset,\n\t\t\tclipX,\n\t\t\tclipY,\n\t\t\tplotLeft,\n\t\t\tplotTop,\n\t\t\tplotWidth,\n\t\t\tplotHeight,\n\t\t\tplotBorderWidth;\n\n\t\tchart.plotLeft = plotLeft = mathRound(chart.plotLeft);\n\t\tchart.plotTop = plotTop = mathRound(chart.plotTop);\n\t\tchart.plotWidth = plotWidth = mathMax(0, mathRound(chartWidth - plotLeft - chart.marginRight));\n\t\tchart.plotHeight = plotHeight = mathMax(0, mathRound(chartHeight - plotTop - chart.marginBottom));\n\n\t\tchart.plotSizeX = inverted ? plotHeight : plotWidth;\n\t\tchart.plotSizeY = inverted ? plotWidth : plotHeight;\n\t\t\n\t\tchart.plotBorderWidth = plotBorderWidth = optionsChart.plotBorderWidth || 0;\n\n\t\t// Set boxes used for alignment\n\t\tchart.spacingBox = renderer.spacingBox = {\n\t\t\tx: spacingLeft,\n\t\t\ty: spacingTop,\n\t\t\twidth: chartWidth - spacingLeft - spacingRight,\n\t\t\theight: chartHeight - spacingTop - spacingBottom\n\t\t};\n\t\tchart.plotBox = renderer.plotBox = {\n\t\t\tx: plotLeft,\n\t\t\ty: plotTop,\n\t\t\twidth: plotWidth,\n\t\t\theight: plotHeight\n\t\t};\n\t\tclipX = mathCeil(mathMax(plotBorderWidth, clipOffset[3]) / 2);\n\t\tclipY = mathCeil(mathMax(plotBorderWidth, clipOffset[0]) / 2);\n\t\tchart.clipBox = {\n\t\t\tx: clipX, \n\t\t\ty: clipY, \n\t\t\twidth: mathFloor(chart.plotSizeX - mathMax(plotBorderWidth, clipOffset[1]) / 2 - clipX), \n\t\t\theight: mathFloor(chart.plotSizeY - mathMax(plotBorderWidth, clipOffset[2]) / 2 - clipY)\n\t\t};\n\n\t\tif (!skipAxes) {\n\t\t\teach(chart.axes, function (axis) {\n\t\t\t\taxis.setAxisSize();\n\t\t\t\taxis.setAxisTranslation();\n\t\t\t});\n\t\t}\n\t},\n\n\t/**\n\t * Initial margins before auto size margins are applied\n\t */\n\tresetMargins: function () {\n\t\tvar chart = this,\n\t\t\toptionsChart = chart.options.chart,\n\t\t\tspacingTop = optionsChart.spacingTop,\n\t\t\tspacingRight = optionsChart.spacingRight,\n\t\t\tspacingBottom = optionsChart.spacingBottom,\n\t\t\tspacingLeft = optionsChart.spacingLeft;\n\n\t\tchart.plotTop = pick(chart.optionsMarginTop, spacingTop);\n\t\tchart.marginRight = pick(chart.optionsMarginRight, spacingRight);\n\t\tchart.marginBottom = pick(chart.optionsMarginBottom, spacingBottom);\n\t\tchart.plotLeft = pick(chart.optionsMarginLeft, spacingLeft);\n\t\tchart.axisOffset = [0, 0, 0, 0]; // top, right, bottom, left\n\t\tchart.clipOffset = [0, 0, 0, 0];\n\t},\n\n\t/**\n\t * Draw the borders and backgrounds for chart and plot area\n\t */\n\tdrawChartBox: function () {\n\t\tvar chart = this,\n\t\t\toptionsChart = chart.options.chart,\n\t\t\trenderer = chart.renderer,\n\t\t\tchartWidth = chart.chartWidth,\n\t\t\tchartHeight = chart.chartHeight,\n\t\t\tchartBackground = chart.chartBackground,\n\t\t\tplotBackground = chart.plotBackground,\n\t\t\tplotBorder = chart.plotBorder,\n\t\t\tplotBGImage = chart.plotBGImage,\n\t\t\tchartBorderWidth = optionsChart.borderWidth || 0,\n\t\t\tchartBackgroundColor = optionsChart.backgroundColor,\n\t\t\tplotBackgroundColor = optionsChart.plotBackgroundColor,\n\t\t\tplotBackgroundImage = optionsChart.plotBackgroundImage,\n\t\t\tplotBorderWidth = optionsChart.plotBorderWidth || 0,\n\t\t\tmgn,\n\t\t\tbgAttr,\n\t\t\tplotLeft = chart.plotLeft,\n\t\t\tplotTop = chart.plotTop,\n\t\t\tplotWidth = chart.plotWidth,\n\t\t\tplotHeight = chart.plotHeight,\n\t\t\tplotBox = chart.plotBox,\n\t\t\tclipRect = chart.clipRect,\n\t\t\tclipBox = chart.clipBox;\n\n\t\t// Chart area\n\t\tmgn = chartBorderWidth + (optionsChart.shadow ? 8 : 0);\n\n\t\tif (chartBorderWidth || chartBackgroundColor) {\n\t\t\tif (!chartBackground) {\n\t\t\t\t\n\t\t\t\tbgAttr = {\n\t\t\t\t\tfill: chartBackgroundColor || NONE\n\t\t\t\t};\n\t\t\t\tif (chartBorderWidth) { // #980\n\t\t\t\t\tbgAttr.stroke = optionsChart.borderColor;\n\t\t\t\t\tbgAttr['stroke-width'] = chartBorderWidth;\n\t\t\t\t}\n\t\t\t\tchart.chartBackground = renderer.rect(mgn / 2, mgn / 2, chartWidth - mgn, chartHeight - mgn,\n\t\t\t\t\t\toptionsChart.borderRadius, chartBorderWidth)\n\t\t\t\t\t.attr(bgAttr)\n\t\t\t\t\t.add()\n\t\t\t\t\t.shadow(optionsChart.shadow);\n\n\t\t\t} else { // resize\n\t\t\t\tchartBackground.animate(\n\t\t\t\t\tchartBackground.crisp(null, null, null, chartWidth - mgn, chartHeight - mgn)\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\n\t\t// Plot background\n\t\tif (plotBackgroundColor) {\n\t\t\tif (!plotBackground) {\n\t\t\t\tchart.plotBackground = renderer.rect(plotLeft, plotTop, plotWidth, plotHeight, 0)\n\t\t\t\t\t.attr({\n\t\t\t\t\t\tfill: plotBackgroundColor\n\t\t\t\t\t})\n\t\t\t\t\t.add()\n\t\t\t\t\t.shadow(optionsChart.plotShadow);\n\t\t\t} else {\n\t\t\t\tplotBackground.animate(plotBox);\n\t\t\t}\n\t\t}\n\t\tif (plotBackgroundImage) {\n\t\t\tif (!plotBGImage) {\n\t\t\t\tchart.plotBGImage = renderer.image(plotBackgroundImage, plotLeft, plotTop, plotWidth, plotHeight)\n\t\t\t\t\t.add();\n\t\t\t} else {\n\t\t\t\tplotBGImage.animate(plotBox);\n\t\t\t}\n\t\t}\n\t\t\n\t\t// Plot clip\n\t\tif (!clipRect) {\n\t\t\tchart.clipRect = renderer.clipRect(clipBox);\n\t\t} else {\n\t\t\tclipRect.animate({\n\t\t\t\twidth: clipBox.width,\n\t\t\t\theight: clipBox.height\n\t\t\t});\n\t\t}\n\n\t\t// Plot area border\n\t\tif (plotBorderWidth) {\n\t\t\tif (!plotBorder) {\n\t\t\t\tchart.plotBorder = renderer.rect(plotLeft, plotTop, plotWidth, plotHeight, 0, plotBorderWidth)\n\t\t\t\t\t.attr({\n\t\t\t\t\t\tstroke: optionsChart.plotBorderColor,\n\t\t\t\t\t\t'stroke-width': plotBorderWidth,\n\t\t\t\t\t\tzIndex: 1\n\t\t\t\t\t})\n\t\t\t\t\t.add();\n\t\t\t} else {\n\t\t\t\tplotBorder.animate(\n\t\t\t\t\tplotBorder.crisp(null, plotLeft, plotTop, plotWidth, plotHeight)\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// reset\n\t\tchart.isDirtyBox = false;\n\t},\n\n\t/**\n\t * Detect whether a certain chart property is needed based on inspecting its options\n\t * and series. This mainly applies to the chart.invert property, and in extensions to \n\t * the chart.angular and chart.polar properties.\n\t */\n\tpropFromSeries: function () {\n\t\tvar chart = this,\n\t\t\toptionsChart = chart.options.chart,\n\t\t\tklass,\n\t\t\tseriesOptions = chart.options.series,\n\t\t\ti,\n\t\t\tvalue;\n\t\t\t\n\t\t\t\n\t\teach(['inverted', 'angular', 'polar'], function (key) {\n\t\t\t\n\t\t\t// The default series type's class\n\t\t\tklass = seriesTypes[optionsChart.type || optionsChart.defaultSeriesType];\n\t\t\t\n\t\t\t// Get the value from available chart-wide properties\n\t\t\tvalue = (\n\t\t\t\tchart[key] || // 1. it is set before\n\t\t\t\toptionsChart[key] || // 2. it is set in the options\n\t\t\t\t(klass && klass.prototype[key]) // 3. it's default series class requires it\n\t\t\t);\n\t\n\t\t\t// 4. Check if any the chart's series require it\n\t\t\ti = seriesOptions && seriesOptions.length;\n\t\t\twhile (!value && i--) {\n\t\t\t\tklass = seriesTypes[seriesOptions[i].type];\n\t\t\t\tif (klass && klass.prototype[key]) {\n\t\t\t\t\tvalue = true;\n\t\t\t\t}\n\t\t\t}\n\t\n\t\t\t// Set the chart property\n\t\t\tchart[key] = value;\t\n\t\t});\n\t\t\n\t},\n\n\t/**\n\t * Render all graphics for the chart\n\t */\n\trender: function () {\n\t\tvar chart = this,\n\t\t\taxes = chart.axes,\n\t\t\trenderer = chart.renderer,\n\t\t\toptions = chart.options;\n\n\t\tvar labels = options.labels,\n\t\t\tcredits = options.credits,\n\t\t\tcreditsHref;\n\n\t\t// Title\n\t\tchart.setTitle();\n\n\n\t\t// Legend\n\t\tchart.legend = new Legend(chart, options.legend);\n\n\t\tchart.getStacks(); // render stacks\n\n\t\t// Get margins by pre-rendering axes\n\t\t// set axes scales\n\t\teach(axes, function (axis) {\n\t\t\taxis.setScale();\n\t\t});\n\n\t\tchart.getMargins();\n\n\t\tchart.maxTicks = null; // reset for second pass\n\t\teach(axes, function (axis) {\n\t\t\taxis.setTickPositions(true); // update to reflect the new margins\n\t\t\taxis.setMaxTicks();\n\t\t});\n\t\tchart.adjustTickAmounts();\n\t\tchart.getMargins(); // second pass to check for new labels\n\n\n\t\t// Draw the borders and backgrounds\n\t\tchart.drawChartBox();\t\t\n\n\n\t\t// Axes\n\t\tif (chart.hasCartesianSeries) {\n\t\t\teach(axes, function (axis) {\n\t\t\t\taxis.render();\n\t\t\t});\n\t\t}\n\n\t\t// The series\n\t\tif (!chart.seriesGroup) {\n\t\t\tchart.seriesGroup = renderer.g('series-group')\n\t\t\t\t.attr({ zIndex: 3 })\n\t\t\t\t.add();\n\t\t}\n\t\teach(chart.series, function (serie) {\n\t\t\tserie.translate();\n\t\t\tserie.setTooltipPoints();\n\t\t\tserie.render();\n\t\t});\n\n\t\t// Labels\n\t\tif (labels.items) {\n\t\t\teach(labels.items, function (label) {\n\t\t\t\tvar style = extend(labels.style, label.style),\n\t\t\t\t\tx = pInt(style.left) + chart.plotLeft,\n\t\t\t\t\ty = pInt(style.top) + chart.plotTop + 12;\n\n\t\t\t\t// delete to prevent rewriting in IE\n\t\t\t\tdelete style.left;\n\t\t\t\tdelete style.top;\n\n\t\t\t\trenderer.text(\n\t\t\t\t\tlabel.html,\n\t\t\t\t\tx,\n\t\t\t\t\ty\n\t\t\t\t)\n\t\t\t\t.attr({ zIndex: 2 })\n\t\t\t\t.css(style)\n\t\t\t\t.add();\n\n\t\t\t});\n\t\t}\n\n\t\t// Credits\n\t\tif (credits.enabled && !chart.credits) {\n\t\t\tcreditsHref = credits.href;\n\t\t\tchart.credits = renderer.text(\n\t\t\t\tcredits.text,\n\t\t\t\t0,\n\t\t\t\t0\n\t\t\t)\n\t\t\t.on('click', function () {\n\t\t\t\tif (creditsHref) {\n\t\t\t\t\tlocation.href = creditsHref;\n\t\t\t\t}\n\t\t\t})\n\t\t\t.attr({\n\t\t\t\talign: credits.position.align,\n\t\t\t\tzIndex: 8\n\t\t\t})\n\t\t\t.css(credits.style)\n\t\t\t.add()\n\t\t\t.align(credits.position);\n\t\t}\n\n\t\t// Set flag\n\t\tchart.hasRendered = true;\n\n\t},\n\n\t/**\n\t * Clean up memory usage\n\t */\n\tdestroy: function () {\n\t\tvar chart = this,\n\t\t\taxes = chart.axes,\n\t\t\tseries = chart.series,\n\t\t\tcontainer = chart.container,\n\t\t\ti,\n\t\t\tparentNode = container && container.parentNode;\n\t\t\t\n\t\t// fire the chart.destoy event\n\t\tfireEvent(chart, 'destroy');\n\t\t\n\t\t// Delete the chart from charts lookup array\n\t\tcharts[chart.index] = UNDEFINED;\n\t\tchart.renderTo.removeAttribute('data-highcharts-chart');\n\n\t\t// remove events\n\t\tremoveEvent(chart);\n\n\t\t// ==== Destroy collections:\n\t\t// Destroy axes\n\t\ti = axes.length;\n\t\twhile (i--) {\n\t\t\taxes[i] = axes[i].destroy();\n\t\t}\n\n\t\t// Destroy each series\n\t\ti = series.length;\n\t\twhile (i--) {\n\t\t\tseries[i] = series[i].destroy();\n\t\t}\n\n\t\t// ==== Destroy chart properties:\n\t\teach(['title', 'subtitle', 'chartBackground', 'plotBackground', 'plotBGImage', \n\t\t\t\t'plotBorder', 'seriesGroup', 'clipRect', 'credits', 'pointer', 'scroller', \n\t\t\t\t'rangeSelector', 'legend', 'resetZoomButton', 'tooltip', 'renderer'], function (name) {\n\t\t\tvar prop = chart[name];\n\n\t\t\tif (prop && prop.destroy) {\n\t\t\t\tchart[name] = prop.destroy();\n\t\t\t}\n\t\t});\n\n\t\t// remove container and all SVG\n\t\tif (container) { // can break in IE when destroyed before finished loading\n\t\t\tcontainer.innerHTML = '';\n\t\t\tremoveEvent(container);\n\t\t\tif (parentNode) {\n\t\t\t\tdiscardElement(container);\n\t\t\t}\n\n\t\t}\n\n\t\t// clean it all up\n\t\tfor (i in chart) {\n\t\t\tdelete chart[i];\n\t\t}\n\n\t},\n\n\n\t/**\n\t * VML namespaces can't be added until after complete. Listening\n\t * for Perini's doScroll hack is not enough.\n\t */\n\tisReadyToRender: function () {\n\t\tvar chart = this;\n\n\t\t// Note: in spite of JSLint's complaints, win == win.top is required\n\t\t/*jslint eqeq: true*/\n\t\tif ((!hasSVG && (win == win.top && doc.readyState !== 'complete')) || (useCanVG && !win.canvg)) {\n\t\t/*jslint eqeq: false*/\n\t\t\tif (useCanVG) {\n\t\t\t\t// Delay rendering until canvg library is downloaded and ready\n\t\t\t\tCanVGController.push(function () { chart.firstRender(); }, chart.options.global.canvasToolsURL);\n\t\t\t} else {\n\t\t\t\tdoc.attachEvent('onreadystatechange', function () {\n\t\t\t\t\tdoc.detachEvent('onreadystatechange', chart.firstRender);\n\t\t\t\t\tif (doc.readyState === 'complete') {\n\t\t\t\t\t\tchart.firstRender();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\t/**\n\t * Prepare for first rendering after all data are loaded\n\t */\n\tfirstRender: function () {\n\t\tvar chart = this,\n\t\t\toptions = chart.options,\n\t\t\tcallback = chart.callback;\n\n\t\t// Check whether the chart is ready to render\n\t\tif (!chart.isReadyToRender()) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Create the container\n\t\tchart.getContainer();\n\n\t\t// Run an early event after the container and renderer are established\n\t\tfireEvent(chart, 'init');\n\n\t\t\n\t\tchart.resetMargins();\n\t\tchart.setChartSize();\n\n\t\t// Set the common chart properties (mainly invert) from the given series\n\t\tchart.propFromSeries();\n\n\t\t// get axes\n\t\tchart.getAxes();\n\n\t\t// Initialize the series\n\t\teach(options.series || [], function (serieOptions) {\n\t\t\tchart.initSeries(serieOptions);\n\t\t});\n\n\t\t// Run an event after axes and series are initialized, but before render. At this stage,\n\t\t// the series data is indexed and cached in the xData and yData arrays, so we can access\n\t\t// those before rendering. Used in Highstock. \n\t\tfireEvent(chart, 'beforeRender'); \n\n\t\t// depends on inverted and on margins being set\n\t\tchart.pointer = new Pointer(chart, options);\n\n\t\tchart.render();\n\n\t\t// add canvas\n\t\tchart.renderer.draw();\n\t\t// run callbacks\n\t\tif (callback) {\n\t\t\tcallback.apply(chart, [chart]);\n\t\t}\n\t\teach(chart.callbacks, function (fn) {\n\t\t\tfn.apply(chart, [chart]);\n\t\t});\n\t\t\n\t\t\n\t\t// If the chart was rendered outside the top container, put it back in\n\t\tchart.cloneRenderTo(true);\n\n\t\tfireEvent(chart, 'load');\n\n\t}\n}; // end Chart\n\n// Hook for exporting module\nChart.prototype.callbacks = [];\n/**\n * The Point object and prototype. Inheritable and used as base for PiePoint\n */\nvar Point = function () {};\nPoint.prototype = {\n\n\t/**\n\t * Initialize the point\n\t * @param {Object} series The series object containing this point\n\t * @param {Object} options The data in either number, array or object format\n\t */\n\tinit: function (series, options, x) {\n\n\t\tvar point = this,\n\t\t\tcolors;\n\t\tpoint.series = series;\n\t\tpoint.applyOptions(options, x);\n\t\tpoint.pointAttr = {};\n\n\t\tif (series.options.colorByPoint) {\n\t\t\tcolors = series.options.colors || series.chart.options.colors;\n\t\t\tpoint.color = point.color || colors[series.colorCounter++];\n\t\t\t// loop back to zero\n\t\t\tif (series.colorCounter === colors.length) {\n\t\t\t\tseries.colorCounter = 0;\n\t\t\t}\n\t\t}\n\n\t\tseries.chart.pointCount++;\n\t\treturn point;\n\t},\n\t/**\n\t * Apply the options containing the x and y data and possible some extra properties.\n\t * This is called on point init or from point.update.\n\t *\n\t * @param {Object} options\n\t */\n\tapplyOptions: function (options, x) {\n\t\tvar point = this,\n\t\t\tseries = point.series,\n\t\t\tpointValKey = series.pointValKey;\n\n\t\toptions = Point.prototype.optionsToObject.call(this, options);\n\n\t\t// copy options directly to point\n\t\textend(point, options);\n\t\tpoint.options = point.options ? extend(point.options, options) : options;\n\t\t\t\n\t\t// For higher dimension series types. For instance, for ranges, point.y is mapped to point.low.\n\t\tif (pointValKey) {\n\t\t\tpoint.y = point[pointValKey];\n\t\t}\n\t\t\n\t\t// If no x is set by now, get auto incremented value. All points must have an\n\t\t// x value, however the y value can be null to create a gap in the series\n\t\tif (point.x === UNDEFINED && series) {\n\t\t\tpoint.x = x === UNDEFINED ? series.autoIncrement() : x;\n\t\t}\n\t\t\n\t\treturn point;\n\t},\n\n\t/**\n\t * Transform number or array configs into objects\n\t */\n\toptionsToObject: function (options) {\n\t\tvar ret,\n\t\t\tseries = this.series,\n\t\t\tpointArrayMap = series.pointArrayMap || ['y'],\n\t\t\tvalueCount = pointArrayMap.length,\n\t\t\tfirstItemType,\n\t\t\ti = 0,\n\t\t\tj = 0;\n\n\t\tif (typeof options === 'number' || options === null) {\n\t\t\tret = { y: options };\n\n\t\t} else if (isArray(options)) {\n\t\t\tret = {};\n\t\t\t// with leading x value\n\t\t\tif (options.length > valueCount) {\n\t\t\t\tfirstItemType = typeof options[0];\n\t\t\t\tif (firstItemType === 'string') {\n\t\t\t\t\tret.name = options[0];\n\t\t\t\t} else if (firstItemType === 'number') {\n\t\t\t\t\tret.x = options[0];\n\t\t\t\t}\n\t\t\t\ti++;\n\t\t\t}\n\t\t\twhile (j < valueCount) {\n\t\t\t\tret[pointArrayMap[j++]] = options[i++];\n\t\t\t}\t\t\t\n\t\t} else if (typeof options === 'object') {\n\t\t\tret = options;\n\n\t\t\t// This is the fastest way to detect if there are individual point dataLabels that need \n\t\t\t// to be considered in drawDataLabels. These can only occur in object configs.\n\t\t\tif (options.dataLabels) {\n\t\t\t\tseries._hasPointLabels = true;\n\t\t\t}\n\n\t\t\t// Same approach as above for markers\n\t\t\tif (options.marker) {\n\t\t\t\tseries._hasPointMarkers = true;\n\t\t\t}\n\t\t}\n\t\treturn ret;\n\t},\n\n\t/**\n\t * Destroy a point to clear memory. Its reference still stays in series.data.\n\t */\n\tdestroy: function () {\n\t\tvar point = this,\n\t\t\tseries = point.series,\n\t\t\tchart = series.chart,\n\t\t\thoverPoints = chart.hoverPoints,\n\t\t\tprop;\n\n\t\tchart.pointCount--;\n\n\t\tif (hoverPoints) {\n\t\t\tpoint.setState();\n\t\t\terase(hoverPoints, point);\n\t\t\tif (!hoverPoints.length) {\n\t\t\t\tchart.hoverPoints = null;\n\t\t\t}\n\n\t\t}\n\t\tif (point === chart.hoverPoint) {\n\t\t\tpoint.onMouseOut();\n\t\t}\n\t\t\n\t\t// remove all events\n\t\tif (point.graphic || point.dataLabel) { // removeEvent and destroyElements are performance expensive\n\t\t\tremoveEvent(point);\n\t\t\tpoint.destroyElements();\n\t\t}\n\n\t\tif (point.legendItem) { // pies have legend items\n\t\t\tchart.legend.destroyItem(point);\n\t\t}\n\n\t\tfor (prop in point) {\n\t\t\tpoint[prop] = null;\n\t\t}\n\n\n\t},\n\n\t/**\n\t * Destroy SVG elements associated with the point\n\t */\n\tdestroyElements: function () {\n\t\tvar point = this,\n\t\t\tprops = ['graphic', 'dataLabel', 'dataLabelUpper', 'group', 'connector', 'shadowGroup'],\n\t\t\tprop,\n\t\t\ti = 6;\n\t\twhile (i--) {\n\t\t\tprop = props[i];\n\t\t\tif (point[prop]) {\n\t\t\t\tpoint[prop] = point[prop].destroy();\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Return the configuration hash needed for the data label and tooltip formatters\n\t */\n\tgetLabelConfig: function () {\n\t\tvar point = this;\n\t\treturn {\n\t\t\tx: point.category,\n\t\t\ty: point.y,\n\t\t\tkey: point.name || point.category,\n\t\t\tseries: point.series,\n\t\t\tpoint: point,\n\t\t\tpercentage: point.percentage,\n\t\t\ttotal: point.total || point.stackTotal\n\t\t};\n\t},\n\n\t/**\n\t * Toggle the selection status of a point\n\t * @param {Boolean} selected Whether to select or unselect the point.\n\t * @param {Boolean} accumulate Whether to add to the previous selection. By default,\n\t *     this happens if the control key (Cmd on Mac) was pressed during clicking.\n\t */\n\tselect: function (selected, accumulate) {\n\t\tvar point = this,\n\t\t\tseries = point.series,\n\t\t\tchart = series.chart;\n\n\t\tselected = pick(selected, !point.selected);\n\n\t\t// fire the event with the defalut handler\n\t\tpoint.firePointEvent(selected ? 'select' : 'unselect', { accumulate: accumulate }, function () {\n\t\t\tpoint.selected = point.options.selected = selected;\n\t\t\tseries.options.data[inArray(point, series.data)] = point.options;\n\t\t\t\n\t\t\tpoint.setState(selected && SELECT_STATE);\n\n\t\t\t// unselect all other points unless Ctrl or Cmd + click\n\t\t\tif (!accumulate) {\n\t\t\t\teach(chart.getSelectedPoints(), function (loopPoint) {\n\t\t\t\t\tif (loopPoint.selected && loopPoint !== point) {\n\t\t\t\t\t\tloopPoint.selected = loopPoint.options.selected = false;\n\t\t\t\t\t\tseries.options.data[inArray(loopPoint, series.data)] = loopPoint.options;\n\t\t\t\t\t\tloopPoint.setState(NORMAL_STATE);\n\t\t\t\t\t\tloopPoint.firePointEvent('unselect');\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t},\n\n\t/**\n\t * Runs on mouse over the point\n\t */\n\tonMouseOver: function (e) {\n\t\tvar point = this,\n\t\t\tseries = point.series,\n\t\t\tchart = series.chart,\n\t\t\ttooltip = chart.tooltip,\n\t\t\thoverPoint = chart.hoverPoint;\n\n\t\t// set normal state to previous series\n\t\tif (hoverPoint && hoverPoint !== point) {\n\t\t\thoverPoint.onMouseOut();\n\t\t}\n\n\t\t// trigger the event\n\t\tpoint.firePointEvent('mouseOver');\n\n\t\t// update the tooltip\n\t\tif (tooltip && (!tooltip.shared || series.noSharedTooltip)) {\n\t\t\ttooltip.refresh(point, e);\n\t\t}\n\n\t\t// hover this\n\t\tpoint.setState(HOVER_STATE);\n\t\tchart.hoverPoint = point;\n\t},\n\t\n\t/**\n\t * Runs on mouse out from the point\n\t */\n\tonMouseOut: function () {\n\t\tvar chart = this.series.chart,\n\t\t\thoverPoints = chart.hoverPoints;\n\t\t\n\t\tif (!hoverPoints || inArray(this, hoverPoints) === -1) { // #887\n\t\t\tthis.firePointEvent('mouseOut');\n\t\n\t\t\tthis.setState();\n\t\t\tchart.hoverPoint = null;\n\t\t}\n\t},\n\n\t/**\n\t * Extendable method for formatting each point's tooltip line\n\t *\n\t * @return {String} A string to be concatenated in to the common tooltip text\n\t */\n\ttooltipFormatter: function (pointFormat) {\n\t\t\n\t\t// Insert options for valueDecimals, valuePrefix, and valueSuffix\n\t\tvar series = this.series,\n\t\t\tseriesTooltipOptions = series.tooltipOptions,\n\t\t\tvalueDecimals = pick(seriesTooltipOptions.valueDecimals, ''),\n\t\t\tvaluePrefix = seriesTooltipOptions.valuePrefix || '',\n\t\t\tvalueSuffix = seriesTooltipOptions.valueSuffix || '';\n\t\t\t\n\t\t// Loop over the point array map and replace unformatted values with sprintf formatting markup\n\t\teach(series.pointArrayMap || ['y'], function (key) {\n\t\t\tkey = '{point.' + key; // without the closing bracket\n\t\t\tif (valuePrefix || valueSuffix) {\n\t\t\t\tpointFormat = pointFormat.replace(key + '}', valuePrefix + key + '}' + valueSuffix);\n\t\t\t}\n\t\t\tpointFormat = pointFormat.replace(key + '}', key + ':,.' + valueDecimals + 'f}');\n\t\t});\n\t\t\n\t\treturn format(pointFormat, {\n\t\t\tpoint: this,\n\t\t\tseries: this.series\n\t\t});\n\t},\n\n\t/**\n\t * Update the point with new options (typically x/y data) and optionally redraw the series.\n\t *\n\t * @param {Object} options Point options as defined in the series.data array\n\t * @param {Boolean} redraw Whether to redraw the chart or wait for an explicit call\n\t * @param {Boolean|Object} animation Whether to apply animation, and optionally animation\n\t *    configuration\n\t *\n\t */\n\tupdate: function (options, redraw, animation) {\n\t\tvar point = this,\n\t\t\tseries = point.series,\n\t\t\tgraphic = point.graphic,\n\t\t\ti,\n\t\t\tdata = series.data,\n\t\t\tchart = series.chart,\n\t\t\tseriesOptions = series.options;\n\n\t\tredraw = pick(redraw, true);\n\n\t\t// fire the event with a default handler of doing the update\n\t\tpoint.firePointEvent('update', { options: options }, function () {\n\n\t\t\tpoint.applyOptions(options);\n\n\t\t\t// update visuals\n\t\t\tif (isObject(options)) {\n\t\t\t\tseries.getAttribs();\n\t\t\t\tif (graphic) {\n\t\t\t\t\tgraphic.attr(point.pointAttr[series.state]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// record changes in the parallel arrays\n\t\t\ti = inArray(point, data);\n\t\t\tseries.xData[i] = point.x;\n\t\t\tseries.yData[i] = series.toYData ? series.toYData(point) : point.y;\n\t\t\tseries.zData[i] = point.z;\n\t\t\tseriesOptions.data[i] = point.options;\n\n\t\t\t// redraw\n\t\t\tseries.isDirty = series.isDirtyData = chart.isDirtyBox = true;\n\t\t\tif (seriesOptions.legendType === 'point') { // #1831, #1885\n\t\t\t\tchart.legend.destroyItem(point);\n\t\t\t}\n\t\t\tif (redraw) {\n\t\t\t\tchart.redraw(animation);\n\t\t\t}\n\t\t});\n\t},\n\n\t/**\n\t * Remove a point and optionally redraw the series and if necessary the axes\n\t * @param {Boolean} redraw Whether to redraw the chart or wait for an explicit call\n\t * @param {Boolean|Object} animation Whether to apply animation, and optionally animation\n\t *    configuration\n\t */\n\tremove: function (redraw, animation) {\n\t\tvar point = this,\n\t\t\tseries = point.series,\n\t\t\tchart = series.chart,\n\t\t\ti,\n\t\t\tdata = series.data;\n\n\t\tsetAnimation(animation, chart);\n\t\tredraw = pick(redraw, true);\n\n\t\t// fire the event with a default handler of removing the point\n\t\tpoint.firePointEvent('remove', null, function () {\n\n\t\t\t// splice all the parallel arrays\n\t\t\ti = inArray(point, data);\n\t\t\tdata.splice(i, 1);\n\t\t\tseries.options.data.splice(i, 1);\n\t\t\tseries.xData.splice(i, 1);\n\t\t\tseries.yData.splice(i, 1);\n\t\t\tseries.zData.splice(i, 1);\n\n\t\t\tpoint.destroy();\n\n\n\t\t\t// redraw\n\t\t\tseries.isDirty = true;\n\t\t\tseries.isDirtyData = true;\n\t\t\tif (redraw) {\n\t\t\t\tchart.redraw();\n\t\t\t}\n\t\t});\n\n\n\t},\n\n\t/**\n\t * Fire an event on the Point object. Must not be renamed to fireEvent, as this\n\t * causes a name clash in MooTools\n\t * @param {String} eventType\n\t * @param {Object} eventArgs Additional event arguments\n\t * @param {Function} defaultFunction Default event handler\n\t */\n\tfirePointEvent: function (eventType, eventArgs, defaultFunction) {\n\t\tvar point = this,\n\t\t\tseries = this.series,\n\t\t\tseriesOptions = series.options;\n\n\t\t// load event handlers on demand to save time on mouseover/out\n\t\tif (seriesOptions.point.events[eventType] || (point.options && point.options.events && point.options.events[eventType])) {\n\t\t\tthis.importEvents();\n\t\t}\n\n\t\t// add default handler if in selection mode\n\t\tif (eventType === 'click' && seriesOptions.allowPointSelect) {\n\t\t\tdefaultFunction = function (event) {\n\t\t\t\t// Control key is for Windows, meta (= Cmd key) for Mac, Shift for Opera\n\t\t\t\tpoint.select(null, event.ctrlKey || event.metaKey || event.shiftKey);\n\t\t\t};\n\t\t}\n\n\t\tfireEvent(this, eventType, eventArgs, defaultFunction);\n\t},\n\t/**\n\t * Import events from the series' and point's options. Only do it on\n\t * demand, to save processing time on hovering.\n\t */\n\timportEvents: function () {\n\t\tif (!this.hasImportedEvents) {\n\t\t\tvar point = this,\n\t\t\t\toptions = merge(point.series.options.point, point.options),\n\t\t\t\tevents = options.events,\n\t\t\t\teventType;\n\n\t\t\tpoint.events = events;\n\n\t\t\tfor (eventType in events) {\n\t\t\t\taddEvent(point, eventType, events[eventType]);\n\t\t\t}\n\t\t\tthis.hasImportedEvents = true;\n\n\t\t}\n\t},\n\n\t/**\n\t * Set the point's state\n\t * @param {String} state\n\t */\n\tsetState: function (state) {\n\t\tvar point = this,\n\t\t\tplotX = point.plotX,\n\t\t\tplotY = point.plotY,\n\t\t\tseries = point.series,\n\t\t\tstateOptions = series.options.states,\n\t\t\tmarkerOptions = defaultPlotOptions[series.type].marker && series.options.marker,\n\t\t\tnormalDisabled = markerOptions && !markerOptions.enabled,\n\t\t\tmarkerStateOptions = markerOptions && markerOptions.states[state],\n\t\t\tstateDisabled = markerStateOptions && markerStateOptions.enabled === false,\n\t\t\tstateMarkerGraphic = series.stateMarkerGraphic,\n\t\t\tpointMarker = point.marker || {},\n\t\t\tchart = series.chart,\n\t\t\tradius,\n\t\t\tnewSymbol,\n\t\t\tpointAttr = point.pointAttr;\n\n\t\tstate = state || NORMAL_STATE; // empty string\n\n\t\tif (\n\t\t\t\t// already has this state\n\t\t\t\tstate === point.state ||\n\t\t\t\t// selected points don't respond to hover\n\t\t\t\t(point.selected && state !== SELECT_STATE) ||\n\t\t\t\t// series' state options is disabled\n\t\t\t\t(stateOptions[state] && stateOptions[state].enabled === false) ||\n\t\t\t\t// point marker's state options is disabled\n\t\t\t\t(state && (stateDisabled || (normalDisabled && !markerStateOptions.enabled)))\n\n\t\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\t// apply hover styles to the existing point\n\t\tif (point.graphic) {\n\t\t\tradius = markerOptions && point.graphic.symbolName && pointAttr[state].r;\n\t\t\tpoint.graphic.attr(merge(\n\t\t\t\tpointAttr[state],\n\t\t\t\tradius ? { // new symbol attributes (#507, #612)\n\t\t\t\t\tx: plotX - radius,\n\t\t\t\t\ty: plotY - radius,\n\t\t\t\t\twidth: 2 * radius,\n\t\t\t\t\theight: 2 * radius\n\t\t\t\t} : {}\n\t\t\t));\n\t\t} else {\n\t\t\t// if a graphic is not applied to each point in the normal state, create a shared\n\t\t\t// graphic for the hover state\n\t\t\tif (state && markerStateOptions) {\n\t\t\t\tradius = markerStateOptions.radius;\n\t\t\t\tnewSymbol = pointMarker.symbol || series.symbol;\n\n\t\t\t\t// If the point has another symbol than the previous one, throw away the \n\t\t\t\t// state marker graphic and force a new one (#1459)\n\t\t\t\tif (stateMarkerGraphic && stateMarkerGraphic.currentSymbol !== newSymbol) {\t\t\t\t\n\t\t\t\t\tstateMarkerGraphic = stateMarkerGraphic.destroy();\n\t\t\t\t}\n\n\t\t\t\t// Add a new state marker graphic\n\t\t\t\tif (!stateMarkerGraphic) {\n\t\t\t\t\tseries.stateMarkerGraphic = stateMarkerGraphic = chart.renderer.symbol(\n\t\t\t\t\t\tnewSymbol,\n\t\t\t\t\t\tplotX - radius,\n\t\t\t\t\t\tplotY - radius,\n\t\t\t\t\t\t2 * radius,\n\t\t\t\t\t\t2 * radius\n\t\t\t\t\t)\n\t\t\t\t\t.attr(pointAttr[state])\n\t\t\t\t\t.add(series.markerGroup);\n\t\t\t\t\tstateMarkerGraphic.currentSymbol = newSymbol;\n\t\t\t\t\n\t\t\t\t// Move the existing graphic\n\t\t\t\t} else {\n\t\t\t\t\tstateMarkerGraphic.attr({ // #1054\n\t\t\t\t\t\tx: plotX - radius,\n\t\t\t\t\t\ty: plotY - radius\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (stateMarkerGraphic) {\n\t\t\t\tstateMarkerGraphic[state && chart.isInsidePlot(plotX, plotY) ? 'show' : 'hide']();\n\t\t\t}\n\t\t}\n\n\t\tpoint.state = state;\n\t}\n};\n\n/**\n * @classDescription The base function which all other series types inherit from. The data in the series is stored\n * in various arrays.\n *\n * - First, series.options.data contains all the original config options for\n * each point whether added by options or methods like series.addPoint.\n * - Next, series.data contains those values converted to points, but in case the series data length\n * exceeds the cropThreshold, or if the data is grouped, series.data doesn't contain all the points. It\n * only contains the points that have been created on demand.\n * - Then there's series.points that contains all currently visible point objects. In case of cropping,\n * the cropped-away points are not part of this array. The series.points array starts at series.cropStart\n * compared to series.data and series.options.data. If however the series data is grouped, these can't\n * be correlated one to one.\n * - series.xData and series.processedXData contain clean x values, equivalent to series.data and series.points.\n * - series.yData and series.processedYData contain clean x values, equivalent to series.data and series.points.\n *\n * @param {Object} chart\n * @param {Object} options\n */\nvar Series = function () {};\n\nSeries.prototype = {\n\n\tisCartesian: true,\n\ttype: 'line',\n\tpointClass: Point,\n\tsorted: true, // requires the data to be sorted\n\trequireSorting: true,\n\tpointAttrToOptions: { // mapping between SVG attributes and the corresponding options\n\t\tstroke: 'lineColor',\n\t\t'stroke-width': 'lineWidth',\n\t\tfill: 'fillColor',\n\t\tr: 'radius'\n\t},\n\tcolorCounter: 0,\n\tinit: function (chart, options) {\n\t\tvar series = this,\n\t\t\teventType,\n\t\t\tevents,\n\t\t\tlinkedTo,\n\t\t\tchartSeries = chart.series;\n\n\t\tseries.chart = chart;\n\t\tseries.options = options = series.setOptions(options); // merge with plotOptions\n\n\t\t// bind the axes\n\t\tseries.bindAxes();\n\n\t\t// set some variables\n\t\textend(series, {\n\t\t\tname: options.name,\n\t\t\tstate: NORMAL_STATE,\n\t\t\tpointAttr: {},\n\t\t\tvisible: options.visible !== false, // true by default\n\t\t\tselected: options.selected === true // false by default\n\t\t});\n\t\t\n\t\t// special\n\t\tif (useCanVG) {\n\t\t\toptions.animation = false;\n\t\t}\n\n\t\t// register event listeners\n\t\tevents = options.events;\n\t\tfor (eventType in events) {\n\t\t\taddEvent(series, eventType, events[eventType]);\n\t\t}\n\t\tif (\n\t\t\t(events && events.click) ||\n\t\t\t(options.point && options.point.events && options.point.events.click) ||\n\t\t\toptions.allowPointSelect\n\t\t) {\n\t\t\tchart.runTrackerClick = true;\n\t\t}\n\n\t\tseries.getColor();\n\t\tseries.getSymbol();\n\n\t\t// set the data\n\t\tseries.setData(options.data, false);\n\t\t\n\t\t// Mark cartesian\n\t\tif (series.isCartesian) {\n\t\t\tchart.hasCartesianSeries = true;\n\t\t}\n\n\t\t// Register it in the chart\n\t\tchartSeries.push(series);\n\t\tseries._i = chartSeries.length - 1;\n\t\t\n\t\t// Sort series according to index option (#248, #1123)\n\t\tstableSort(chartSeries, function (a, b) {\n\t\t\treturn pick(a.options.index, a._i) - pick(b.options.index, a._i);\n\t\t});\n\t\teach(chartSeries, function (series, i) {\n\t\t\tseries.index = i;\n\t\t\tseries.name = series.name || 'Series ' + (i + 1);\n\t\t});\n\n\t\t// Linked series\n\t\tlinkedTo = options.linkedTo;\n\t\tseries.linkedSeries = [];\n\t\tif (isString(linkedTo)) {\n\t\t\tif (linkedTo === ':previous') {\n\t\t\t\tlinkedTo = chartSeries[series.index - 1];\n\t\t\t} else {\n\t\t\t\tlinkedTo = chart.get(linkedTo);\n\t\t\t}\n\t\t\tif (linkedTo) {\n\t\t\t\tlinkedTo.linkedSeries.push(series);\n\t\t\t\tseries.linkedParent = linkedTo;\n\t\t\t}\n\t\t}\n\t},\n\t\n\t/**\n\t * Set the xAxis and yAxis properties of cartesian series, and register the series\n\t * in the axis.series array\n\t */\n\tbindAxes: function () {\n\t\tvar series = this,\n\t\t\tseriesOptions = series.options,\n\t\t\tchart = series.chart,\n\t\t\taxisOptions;\n\t\t\t\n\t\tif (series.isCartesian) {\n\t\t\t\n\t\t\teach(['xAxis', 'yAxis'], function (AXIS) { // repeat for xAxis and yAxis\n\t\t\t\t\n\t\t\t\teach(chart[AXIS], function (axis) { // loop through the chart's axis objects\n\t\t\t\t\t\n\t\t\t\t\taxisOptions = axis.options;\n\t\t\t\t\t\n\t\t\t\t\t// apply if the series xAxis or yAxis option mathches the number of the \n\t\t\t\t\t// axis, or if undefined, use the first axis\n\t\t\t\t\tif ((seriesOptions[AXIS] === axisOptions.index) ||\n\t\t\t\t\t\t\t(seriesOptions[AXIS] !== UNDEFINED && seriesOptions[AXIS] === axisOptions.id) ||\n\t\t\t\t\t\t\t(seriesOptions[AXIS] === UNDEFINED && axisOptions.index === 0)) {\n\t\t\t\t\t\t\n\t\t\t\t\t\t// register this series in the axis.series lookup\n\t\t\t\t\t\taxis.series.push(series);\n\t\t\t\t\t\t\n\t\t\t\t\t\t// set this series.xAxis or series.yAxis reference\n\t\t\t\t\t\tseries[AXIS] = axis;\n\t\t\t\t\t\t\n\t\t\t\t\t\t// mark dirty for redraw\n\t\t\t\t\t\taxis.isDirty = true;\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\t// The series needs an X and an Y axis\n\t\t\t\tif (!series[AXIS]) {\n\t\t\t\t\terror(18, true);\n\t\t\t\t}\n\n\t\t\t});\n\t\t}\n\t},\n\n\n\t/**\n\t * Return an auto incremented x value based on the pointStart and pointInterval options.\n\t * This is only used if an x value is not given for the point that calls autoIncrement.\n\t */\n\tautoIncrement: function () {\n\t\tvar series = this,\n\t\t\toptions = series.options,\n\t\t\txIncrement = series.xIncrement;\n\n\t\txIncrement = pick(xIncrement, options.pointStart, 0);\n\n\t\tseries.pointInterval = pick(series.pointInterval, options.pointInterval, 1);\n\n\t\tseries.xIncrement = xIncrement + series.pointInterval;\n\t\treturn xIncrement;\n\t},\n\n\t/**\n\t * Divide the series data into segments divided by null values.\n\t */\n\tgetSegments: function () {\n\t\tvar series = this,\n\t\t\tlastNull = -1,\n\t\t\tsegments = [],\n\t\t\ti,\n\t\t\tpoints = series.points,\n\t\t\tpointsLength = points.length;\n\n\t\tif (pointsLength) { // no action required for []\n\t\t\t\n\t\t\t// if connect nulls, just remove null points\n\t\t\tif (series.options.connectNulls) {\n\t\t\t\ti = pointsLength;\n\t\t\t\twhile (i--) {\n\t\t\t\t\tif (points[i].y === null) {\n\t\t\t\t\t\tpoints.splice(i, 1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (points.length) {\n\t\t\t\t\tsegments = [points];\n\t\t\t\t}\n\t\t\t\t\n\t\t\t// else, split on null points\n\t\t\t} else {\n\t\t\t\teach(points, function (point, i) {\n\t\t\t\t\tif (point.y === null) {\n\t\t\t\t\t\tif (i > lastNull + 1) {\n\t\t\t\t\t\t\tsegments.push(points.slice(lastNull + 1, i));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tlastNull = i;\n\t\t\t\t\t} else if (i === pointsLength - 1) { // last value\n\t\t\t\t\t\tsegments.push(points.slice(lastNull + 1, i + 1));\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\t\n\t\t// register it\n\t\tseries.segments = segments;\n\t},\n\t\n\t/**\n\t * Set the series options by merging from the options tree\n\t * @param {Object} itemOptions\n\t */\n\tsetOptions: function (itemOptions) {\n\t\tvar chart = this.chart,\n\t\t\tchartOptions = chart.options,\n\t\t\tplotOptions = chartOptions.plotOptions,\n\t\t\ttypeOptions = plotOptions[this.type],\n\t\t\toptions;\n\n\t\tthis.userOptions = itemOptions;\n\n\t\toptions = merge(\n\t\t\ttypeOptions,\n\t\t\tplotOptions.series,\n\t\t\titemOptions\n\t\t);\n\t\t\n\t\t// the tooltip options are merged between global and series specific options\n\t\tthis.tooltipOptions = merge(chartOptions.tooltip, options.tooltip);\n\t\t\n\t\t// Delte marker object if not allowed (#1125)\n\t\tif (typeOptions.marker === null) {\n\t\t\tdelete options.marker;\n\t\t}\n\t\t\n\t\treturn options;\n\n\t},\n\t/**\n\t * Get the series' color\n\t */\n\tgetColor: function () {\n\t\tvar options = this.options,\n\t\t\tuserOptions = this.userOptions,\n\t\t\tdefaultColors = this.chart.options.colors,\n\t\t\tcounters = this.chart.counters,\n\t\t\tcolor,\n\t\t\tcolorIndex;\n\n\t\tcolor = options.color || defaultPlotOptions[this.type].color;\n\n\t\tif (!color && !options.colorByPoint) {\n\t\t\tif (defined(userOptions._colorIndex)) { // after Series.update()\n\t\t\t\tcolorIndex = userOptions._colorIndex;\n\t\t\t} else {\n\t\t\t\tuserOptions._colorIndex = counters.color;\n\t\t\t\tcolorIndex = counters.color++;\n\t\t\t}\n\t\t\tcolor = defaultColors[colorIndex];\n\t\t}\n\t\t\n\t\tthis.color = color;\n\t\tcounters.wrapColor(defaultColors.length);\n\t},\n\t/**\n\t * Get the series' symbol\n\t */\n\tgetSymbol: function () {\n\t\tvar series = this,\n\t\t\tuserOptions = series.userOptions,\n\t\t\tseriesMarkerOption = series.options.marker,\n\t\t\tchart = series.chart,\n\t\t\tdefaultSymbols = chart.options.symbols,\n\t\t\tcounters = chart.counters,\n\t\t\tsymbolIndex;\n\n\t\tseries.symbol = seriesMarkerOption.symbol;\n\t\tif (!series.symbol) {\n\t\t\tif (defined(userOptions._symbolIndex)) { // after Series.update()\n\t\t\t\tsymbolIndex = userOptions._symbolIndex;\n\t\t\t} else {\n\t\t\t\tuserOptions._symbolIndex = counters.symbol;\n\t\t\t\tsymbolIndex = counters.symbol++;\n\t\t\t}\n\t\t\tseries.symbol = defaultSymbols[symbolIndex];\n\t\t}\n\n\t\t// don't substract radius in image symbols (#604)\n\t\tif (/^url/.test(series.symbol)) {\n\t\t\tseriesMarkerOption.radius = 0;\n\t\t}\n\t\tcounters.wrapSymbol(defaultSymbols.length);\n\t},\n\n\t/**\n\t * Get the series' symbol in the legend. This method should be overridable to create custom \n\t * symbols through Highcharts.seriesTypes[type].prototype.drawLegendSymbols.\n\t * \n\t * @param {Object} legend The legend object\n\t */\n\tdrawLegendSymbol: function (legend) {\n\t\t\n\t\tvar options = this.options,\n\t\t\tmarkerOptions = options.marker,\n\t\t\tradius,\n\t\t\tlegendOptions = legend.options,\n\t\t\tlegendSymbol,\n\t\t\tsymbolWidth = legendOptions.symbolWidth,\n\t\t\trenderer = this.chart.renderer,\n\t\t\tlegendItemGroup = this.legendGroup,\n\t\t\tverticalCenter = legend.baseline - mathRound(renderer.fontMetrics(legendOptions.itemStyle.fontSize).b * 0.3),\n\t\t\tattr;\n\t\t\t\n\t\t// Draw the line\n\t\tif (options.lineWidth) {\n\t\t\tattr = {\n\t\t\t\t'stroke-width': options.lineWidth\n\t\t\t};\n\t\t\tif (options.dashStyle) {\n\t\t\t\tattr.dashstyle = options.dashStyle;\n\t\t\t}\n\t\t\tthis.legendLine = renderer.path([\n\t\t\t\tM,\n\t\t\t\t0,\n\t\t\t\tverticalCenter,\n\t\t\t\tL,\n\t\t\t\tsymbolWidth,\n\t\t\t\tverticalCenter\n\t\t\t])\n\t\t\t.attr(attr)\n\t\t\t.add(legendItemGroup);\n\t\t}\n\t\t\n\t\t// Draw the marker\n\t\tif (markerOptions && markerOptions.enabled) {\n\t\t\tradius = markerOptions.radius;\n\t\t\tthis.legendSymbol = legendSymbol = renderer.symbol(\n\t\t\t\tthis.symbol,\n\t\t\t\t(symbolWidth / 2) - radius,\n\t\t\t\tverticalCenter - radius,\n\t\t\t\t2 * radius,\n\t\t\t\t2 * radius\n\t\t\t)\n\t\t\t.add(legendItemGroup);\n\t\t\tlegendSymbol.isMarker = true;\n\t\t}\n\t},\n\n\t/**\n\t * Add a point dynamically after chart load time\n\t * @param {Object} options Point options as given in series.data\n\t * @param {Boolean} redraw Whether to redraw the chart or wait for an explicit call\n\t * @param {Boolean} shift If shift is true, a point is shifted off the start\n\t *    of the series as one is appended to the end.\n\t * @param {Boolean|Object} animation Whether to apply animation, and optionally animation\n\t *    configuration\n\t */\n\taddPoint: function (options, redraw, shift, animation) {\n\t\tvar series = this,\n\t\t\tseriesOptions = series.options,\n\t\t\tdata = series.data,\n\t\t\tgraph = series.graph,\n\t\t\tarea = series.area,\n\t\t\tchart = series.chart,\n\t\t\txData = series.xData,\n\t\t\tyData = series.yData,\n\t\t\tzData = series.zData,\n\t\t\tnames = series.names,\n\t\t\tcurrentShift = (graph && graph.shift) || 0,\n\t\t\tdataOptions = seriesOptions.data,\n\t\t\tpoint;\n\n\t\tsetAnimation(animation, chart);\n\n\t\t// Make graph animate sideways\n\t\tif (shift) {\n\t\t\teach([graph, area, series.graphNeg, series.areaNeg], function (shape) {\n\t\t\t\tif (shape) {\n\t\t\t\t\tshape.shift = currentShift + 1;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\tif (area) {\n\t\t\tarea.isArea = true; // needed in animation, both with and without shift\n\t\t}\n\t\t\n\t\t// Optional redraw, defaults to true\n\t\tredraw = pick(redraw, true);\n\n\t\t// Get options and push the point to xData, yData and series.options. In series.generatePoints\n\t\t// the Point instance will be created on demand and pushed to the series.data array.\n\t\tpoint = { series: series };\n\t\tseries.pointClass.prototype.applyOptions.apply(point, [options]);\n\t\txData.push(point.x);\n\t\tyData.push(series.toYData ? series.toYData(point) : point.y);\n\t\tzData.push(point.z);\n\t\tif (names) {\n\t\t\tnames[point.x] = point.name;\n\t\t}\n\t\tdataOptions.push(options);\n\n\t\t// Generate points to be added to the legend (#1329) \n\t\tif (seriesOptions.legendType === 'point') {\n\t\t\tseries.generatePoints();\n\t\t}\n\n\t\t// Shift the first point off the parallel arrays\n\t\t// todo: consider series.removePoint(i) method\n\t\tif (shift) {\n\t\t\tif (data[0] && data[0].remove) {\n\t\t\t\tdata[0].remove(false);\n\t\t\t} else {\n\t\t\t\tdata.shift();\n\t\t\t\txData.shift();\n\t\t\t\tyData.shift();\n\t\t\t\tzData.shift();\n\t\t\t\tdataOptions.shift();\n\t\t\t}\n\t\t}\n\n\t\t// redraw\n\t\tseries.isDirty = true;\n\t\tseries.isDirtyData = true;\n\t\tif (redraw) {\n\t\t\tseries.getAttribs(); // #1937\n\t\t\tchart.redraw();\n\t\t}\n\t},\n\n\t/**\n\t * Replace the series data with a new set of data\n\t * @param {Object} data\n\t * @param {Object} redraw\n\t */\n\tsetData: function (data, redraw) {\n\t\tvar series = this,\n\t\t\toldData = series.points,\n\t\t\toptions = series.options,\n\t\t\tchart = series.chart,\n\t\t\tfirstPoint = null,\n\t\t\txAxis = series.xAxis,\n\t\t\tnames = xAxis && xAxis.categories && !xAxis.categories.length ? [] : null,\n\t\t\ti;\n\n\t\t// reset properties\n\t\tseries.xIncrement = null;\n\t\tseries.pointRange = xAxis && xAxis.categories ? 1 : options.pointRange;\n\n\t\tseries.colorCounter = 0; // for series with colorByPoint (#1547)\n\t\t\n\t\t// parallel arrays\n\t\tvar xData = [],\n\t\t\tyData = [],\n\t\t\tzData = [],\n\t\t\tdataLength = data ? data.length : [],\n\t\t\tturboThreshold = pick(options.turboThreshold, 1000), // docs: 0 to disable\n\t\t\tpt,\n\t\t\tpointArrayMap = series.pointArrayMap,\n\t\t\tvalueCount = pointArrayMap && pointArrayMap.length,\n\t\t\thasToYData = !!series.toYData;\n\n\t\t// In turbo mode, only one- or twodimensional arrays of numbers are allowed. The\n\t\t// first value is tested, and we assume that all the rest are defined the same\n\t\t// way. Although the 'for' loops are similar, they are repeated inside each\n\t\t// if-else conditional for max performance.\n\t\tif (turboThreshold && dataLength > turboThreshold) { \n\t\t\t\n\t\t\t// find the first non-null point\n\t\t\ti = 0;\n\t\t\twhile (firstPoint === null && i < dataLength) {\n\t\t\t\tfirstPoint = data[i];\n\t\t\t\ti++;\n\t\t\t}\n\t\t\n\t\t\n\t\t\tif (isNumber(firstPoint)) { // assume all points are numbers\n\t\t\t\tvar x = pick(options.pointStart, 0),\n\t\t\t\t\tpointInterval = pick(options.pointInterval, 1);\n\n\t\t\t\tfor (i = 0; i < dataLength; i++) {\n\t\t\t\t\txData[i] = x;\n\t\t\t\t\tyData[i] = data[i];\n\t\t\t\t\tx += pointInterval;\n\t\t\t\t}\n\t\t\t\tseries.xIncrement = x;\n\t\t\t} else if (isArray(firstPoint)) { // assume all points are arrays\n\t\t\t\tif (valueCount) { // [x, low, high] or [x, o, h, l, c]\n\t\t\t\t\tfor (i = 0; i < dataLength; i++) {\n\t\t\t\t\t\tpt = data[i];\n\t\t\t\t\t\txData[i] = pt[0];\n\t\t\t\t\t\tyData[i] = pt.slice(1, valueCount + 1);\n\t\t\t\t\t}\n\t\t\t\t} else { // [x, y]\n\t\t\t\t\tfor (i = 0; i < dataLength; i++) {\n\t\t\t\t\t\tpt = data[i];\n\t\t\t\t\t\txData[i] = pt[0];\n\t\t\t\t\t\tyData[i] = pt[1];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} /* else {\n\t\t\t\terror(12); // Highcharts expects configs to be numbers or arrays in turbo mode\n\t\t\t}*/\n\t\t} else {\n\t\t\tfor (i = 0; i < dataLength; i++) {\n\t\t\t\tif (data[i] !== UNDEFINED) { // stray commas in oldIE\n\t\t\t\t\tpt = { series: series };\n\t\t\t\t\tseries.pointClass.prototype.applyOptions.apply(pt, [data[i]]);\n\t\t\t\t\txData[i] = pt.x;\n\t\t\t\t\tyData[i] = hasToYData ? series.toYData(pt) : pt.y;\n\t\t\t\t\tzData[i] = pt.z;\n\t\t\t\t\tif (names && pt.name) {\n\t\t\t\t\t\tnames[pt.x] = pt.name; // #2046\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\t// Forgetting to cast strings to numbers is a common caveat when handling CSV or JSON\t\t\n\t\tif (isString(yData[0])) {\n\t\t\terror(14, true);\n\t\t} \n\n\t\tseries.data = [];\n\t\tseries.options.data = data;\n\t\tseries.xData = xData;\n\t\tseries.yData = yData;\n\t\tseries.zData = zData;\n\t\tseries.names = names;\n\n\t\t// destroy old points\n\t\ti = (oldData && oldData.length) || 0;\n\t\twhile (i--) {\n\t\t\tif (oldData[i] && oldData[i].destroy) {\n\t\t\t\toldData[i].destroy();\n\t\t\t}\n\t\t}\n\n\t\t// reset minRange (#878)\n\t\tif (xAxis) {\n\t\t\txAxis.minRange = xAxis.userMinRange;\n\t\t}\n\n\t\t// redraw\n\t\tseries.isDirty = series.isDirtyData = chart.isDirtyBox = true;\n\t\tif (pick(redraw, true)) {\n\t\t\tchart.redraw(false);\n\t\t}\n\t},\n\n\t/**\n\t * Remove a series and optionally redraw the chart\n\t *\n\t * @param {Boolean} redraw Whether to redraw the chart or wait for an explicit call\n\t * @param {Boolean|Object} animation Whether to apply animation, and optionally animation\n\t *    configuration\n\t */\n\n\tremove: function (redraw, animation) {\n\t\tvar series = this,\n\t\t\tchart = series.chart;\n\t\tredraw = pick(redraw, true);\n\n\t\tif (!series.isRemoving) {  /* prevent triggering native event in jQuery\n\t\t\t\t(calling the remove function from the remove event) */\n\t\t\tseries.isRemoving = true;\n\n\t\t\t// fire the event with a default handler of removing the point\n\t\t\tfireEvent(series, 'remove', null, function () {\n\n\n\t\t\t\t// destroy elements\n\t\t\t\tseries.destroy();\n\n\n\t\t\t\t// redraw\n\t\t\t\tchart.isDirtyLegend = chart.isDirtyBox = true;\n\t\t\t\tif (redraw) {\n\t\t\t\t\tchart.redraw(animation);\n\t\t\t\t}\n\t\t\t});\n\n\t\t}\n\t\tseries.isRemoving = false;\n\t},\n\n\t/**\n\t * Process the data by cropping away unused data points if the series is longer\n\t * than the crop threshold. This saves computing time for lage series.\n\t */\n\tprocessData: function (force) {\n\t\tvar series = this,\n\t\t\tprocessedXData = series.xData, // copied during slice operation below\n\t\t\tprocessedYData = series.yData,\n\t\t\tdataLength = processedXData.length,\n\t\t\tcroppedData,\n\t\t\tcropStart = 0,\n\t\t\tcropped,\n\t\t\tdistance,\n\t\t\tclosestPointRange,\n\t\t\txAxis = series.xAxis,\n\t\t\ti, // loop variable\n\t\t\toptions = series.options,\n\t\t\tcropThreshold = options.cropThreshold,\n\t\t\tisCartesian = series.isCartesian;\n\n\t\t// If the series data or axes haven't changed, don't go through this. Return false to pass\n\t\t// the message on to override methods like in data grouping. \n\t\tif (isCartesian && !series.isDirty && !xAxis.isDirty && !series.yAxis.isDirty && !force) {\n\t\t\treturn false;\n\t\t}\n\t\t\n\n\t\t// optionally filter out points outside the plot area\n\t\tif (isCartesian && series.sorted && (!cropThreshold || dataLength > cropThreshold || series.forceCrop)) {\n\t\t\tvar min = xAxis.min,\n\t\t\t\tmax = xAxis.max;\n\n\t\t\t// it's outside current extremes\n\t\t\tif (processedXData[dataLength - 1] < min || processedXData[0] > max) {\n\t\t\t\tprocessedXData = [];\n\t\t\t\tprocessedYData = [];\n\t\t\t\n\t\t\t// only crop if it's actually spilling out\n\t\t\t} else if (processedXData[0] < min || processedXData[dataLength - 1] > max) {\n\t\t\t\tcroppedData = this.cropData(series.xData, series.yData, min, max);\n\t\t\t\tprocessedXData = croppedData.xData;\n\t\t\t\tprocessedYData = croppedData.yData;\n\t\t\t\tcropStart = croppedData.start;\n\t\t\t\tcropped = true;\n\t\t\t}\n\t\t}\n\t\t\n\t\t\n\t\t// Find the closest distance between processed points\n\t\tfor (i = processedXData.length - 1; i >= 0; i--) {\n\t\t\tdistance = processedXData[i] - processedXData[i - 1];\n\t\t\tif (distance > 0 && (closestPointRange === UNDEFINED || distance < closestPointRange)) {\n\t\t\t\tclosestPointRange = distance;\n\n\t\t\t// Unsorted data is not supported by the line tooltip, as well as data grouping and \n\t\t\t// navigation in Stock charts (#725) and width calculation of columns (#1900)\n\t\t\t} else if (distance < 0 && series.requireSorting) {\n\t\t\t\terror(15);\n\t\t\t}\n\t\t}\n\n\t\t// Record the properties\n\t\tseries.cropped = cropped; // undefined or true\n\t\tseries.cropStart = cropStart;\n\t\tseries.processedXData = processedXData;\n\t\tseries.processedYData = processedYData;\n\n\t\tif (options.pointRange === null) { // null means auto, as for columns, candlesticks and OHLC\n\t\t\tseries.pointRange = closestPointRange || 1;\n\t\t}\n\t\tseries.closestPointRange = closestPointRange;\n\t\t\n\t},\n\n\t/**\n\t * Iterate over xData and crop values between min and max. Returns object containing crop start/end\n\t * cropped xData with corresponding part of yData, dataMin and dataMax within the cropped range\n\t */\n\tcropData: function (xData, yData, min, max) {\n\t\tvar dataLength = xData.length,\n\t\t\tcropStart = 0,\n\t\t\tcropEnd = dataLength,\n\t\t\ti;\n\n\t\t// iterate up to find slice start\n\t\tfor (i = 0; i < dataLength; i++) {\n\t\t\tif (xData[i] >= min) {\n\t\t\t\tcropStart = mathMax(0, i - 1);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// proceed to find slice end\n\t\tfor (; i < dataLength; i++) {\n\t\t\tif (xData[i] > max) {\n\t\t\t\tcropEnd = i + 1;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\txData: xData.slice(cropStart, cropEnd),\n\t\t\tyData: yData.slice(cropStart, cropEnd),\n\t\t\tstart: cropStart,\n\t\t\tend: cropEnd\n\t\t};\n\t},\n\n\n\t/**\n\t * Generate the data point after the data has been processed by cropping away\n\t * unused points and optionally grouped in Highcharts Stock.\n\t */\n\tgeneratePoints: function () {\n\t\tvar series = this,\n\t\t\toptions = series.options,\n\t\t\tdataOptions = options.data,\n\t\t\tdata = series.data,\n\t\t\tdataLength,\n\t\t\tprocessedXData = series.processedXData,\n\t\t\tprocessedYData = series.processedYData,\n\t\t\tpointClass = series.pointClass,\n\t\t\tprocessedDataLength = processedXData.length,\n\t\t\tcropStart = series.cropStart || 0,\n\t\t\tcursor,\n\t\t\thasGroupedData = series.hasGroupedData,\n\t\t\tpoint,\n\t\t\tpoints = [],\n\t\t\ti;\n\n\t\tif (!data && !hasGroupedData) {\n\t\t\tvar arr = [];\n\t\t\tarr.length = dataOptions.length;\n\t\t\tdata = series.data = arr;\n\t\t}\n\n\t\tfor (i = 0; i < processedDataLength; i++) {\n\t\t\tcursor = cropStart + i;\n\t\t\tif (!hasGroupedData) {\n\t\t\t\tif (data[cursor]) {\n\t\t\t\t\tpoint = data[cursor];\n\t\t\t\t} else if (dataOptions[cursor] !== UNDEFINED) { // #970\n\t\t\t\t\tdata[cursor] = point = (new pointClass()).init(series, dataOptions[cursor], processedXData[i]);\n\t\t\t\t}\n\t\t\t\tpoints[i] = point;\n\t\t\t} else {\n\t\t\t\t// splat the y data in case of ohlc data array\n\t\t\t\tpoints[i] = (new pointClass()).init(series, [processedXData[i]].concat(splat(processedYData[i])));\n\t\t\t}\n\t\t}\n\n\t\t// Hide cropped-away points - this only runs when the number of points is above cropThreshold, or when\n\t\t// swithching view from non-grouped data to grouped data (#637)\t\n\t\tif (data && (processedDataLength !== (dataLength = data.length) || hasGroupedData)) {\n\t\t\tfor (i = 0; i < dataLength; i++) {\n\t\t\t\tif (i === cropStart && !hasGroupedData) { // when has grouped data, clear all points\n\t\t\t\t\ti += processedDataLength;\n\t\t\t\t}\n\t\t\t\tif (data[i]) {\n\t\t\t\t\tdata[i].destroyElements();\n\t\t\t\t\tdata[i].plotX = UNDEFINED; // #1003\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tseries.data = data;\n\t\tseries.points = points;\n\t},\n\n\t/**\n\t * Adds series' points value to corresponding stack\n\t */\n\tsetStackedPoints: function () {\n\t\tif (!this.options.stacking || (this.visible !== true && this.chart.options.chart.ignoreHiddenSeries !== false)) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar series = this,\n\t\t\txData = series.processedXData,\n\t\t\tyData = series.processedYData,\n\t\t\tyDataLength = yData.length,\n\t\t\tseriesOptions = series.options,\n\t\t\tthreshold = seriesOptions.threshold,\n\t\t\tstackOption = seriesOptions.stack,\n\t\t\tstacking = seriesOptions.stacking,\n\t\t\tstackKey = series.stackKey,\n\t\t\tnegKey = '-' + stackKey,\n\t\t\tyAxis = series.yAxis,\n\t\t\tstacks = yAxis.stacks,\n\t\t\toldStacks = yAxis.oldStacks,\n\t\t\tstacksMax = yAxis.stacksMax,\n\t\t\tisNegative,\n\t\t\ttotal,\n\t\t\tstack,\n\t\t\tkey,\n\t\t\ti,\n\t\t\tx,\n\t\t\ty;\n\n\t\t// loop over the non-null y values and read them into a local array\n\t\tfor (i = 0; i < yDataLength; i++) {\n\t\t\tx = xData[i];\n\t\t\ty = yData[i];\n\n\t\t\t// Read stacked values into a stack based on the x value,\n\t\t\t// the sign of y and the stack key. Stacking is also handled for null values (#739)\n\t\t\tisNegative = y < threshold;\n\t\t\tkey = isNegative ? negKey : stackKey;\n\n\t\t\t// Set default stacksMax value for this stack\n\t\t\tif (!stacksMax[key]) {\n\t\t\t\tstacksMax[key] = y;\n\t\t\t}\n\n\t\t\t// Create empty object for this stack if it doesn't exist yet\n\t\t\tif (!stacks[key]) {\n\t\t\t\tstacks[key] = {};\n\t\t\t}\n\n\t\t\t// Initialize StackItem for this x\n\t\t\tif (oldStacks[key] && oldStacks[key][x]) {\n\t\t\t\tstacks[key][x] = oldStacks[key][x];\n\t\t\t\tstacks[key][x].total = null;\n\t\t\t} else if (!stacks[key][x]) {\n\t\t\t\tstacks[key][x] = new StackItem(yAxis, yAxis.options.stackLabels, isNegative, x, stackOption, stacking);\n\t\t\t}\n\n\t\t\t// If the StackItem doesn't exist, create it first\n\t\t\tstack = stacks[key][x];\n\t\t\ttotal = stack.total;\n\n\n\t\t\t// add value to the stack total\n\t\t\tstack.addValue(y);\n\n\t\t\tstack.cacheExtremes(series, [total, total + y]);\n\n\n\t\t\tif (stack.total > stacksMax[key] && !isNegative) {\n\t\t\t\tstacksMax[key] = stack.total;\n\t\t\t} else if (stack.total < stacksMax[key] && isNegative) {\n\t\t\t\tstacksMax[key] = stack.total;\n\t\t\t}\n\t\t}\n\n\t\t// reset old stacks\n\t\tyAxis.oldStacks = {};\n\t},\n\n\t/**\n\t * Calculate x and y extremes for visible data\n\t */\n\tgetExtremes: function () {\n\t\tvar xAxis = this.xAxis,\n\t\t\tyAxis = this.yAxis,\n\t\t\tstackKey = this.stackKey,\n\t\t\toptions = this.options,\n\t\t\tthreshold = options.threshold,\n\t\t\txData = this.processedXData,\n\t\t\tyData = this.processedYData,\n\t\t\tyDataLength = yData.length,\n\t\t\tactiveYData = [],\n\t\t\tactiveCounter = 0,\n\t\t\txMin = xAxis.min,\n\t\t\txMax = xAxis.max,\n\t\t\tvalidValue,\n\t\t\twithinRange,\n\t\t\tdataMin,\n\t\t\tdataMax,\n\t\t\tx,\n\t\t\ty,\n\t\t\ti,\n\t\t\tj;\n\n\t\t// For stacked series, get the value from the stack\n\t\tif (options.stacking) {\n\t\t\tdataMin = yAxis.stacksMax['-' + stackKey] || threshold;\n\t\t\tdataMax = yAxis.stacksMax[stackKey] || threshold;\n\t\t}\n\n\t\t// If not stacking or threshold is null, iterate over values that are within the visible range\n\t\tif (!defined(dataMin) || !defined(dataMax)) {\n\n\t\t\tfor (i = 0; i < yDataLength; i++) {\n\t\t\t\t\n\t\t\t\tx = xData[i];\n\t\t\t\ty = yData[i];\n\n\t\t\t\t// For points within the visible range, including the first point outside the\n\t\t\t\t// visible range, consider y extremes\n\t\t\t\tvalidValue = y !== null && y !== UNDEFINED && (!yAxis.isLog || (y.length || y > 0));\n\t\t\t\twithinRange = this.getExtremesFromAll || this.cropped || ((xData[i + 1] || x) >= xMin && \n\t\t\t\t\t(xData[i - 1] || x) <= xMax);\n\n\t\t\t\tif (validValue && withinRange) {\n\n\t\t\t\t\tj = y.length;\n\t\t\t\t\tif (j) { // array, like ohlc or range data\n\t\t\t\t\t\twhile (j--) {\n\t\t\t\t\t\t\tif (y[j] !== null) {\n\t\t\t\t\t\t\t\tactiveYData[activeCounter++] = y[j];\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\tactiveYData[activeCounter++] = y;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tdataMin = pick(dataMin, arrayMin(activeYData));\n\t\t\tdataMax = pick(dataMax, arrayMax(activeYData));\n\t\t}\n\n\t\t// Set\n\t\tthis.dataMin = dataMin;\n\t\tthis.dataMax = dataMax;\n\t},\n\n\t/**\n\t * Translate data points from raw data values to chart specific positioning data\n\t * needed later in drawPoints, drawGraph and drawTracker.\n\t */\n\ttranslate: function () {\n\t\tif (!this.processedXData) { // hidden series\n\t\t\tthis.processData();\n\t\t}\n\t\tthis.generatePoints();\n\t\tvar series = this,\n\t\t\toptions = series.options,\n\t\t\tstacking = options.stacking,\n\t\t\txAxis = series.xAxis,\n\t\t\tcategories = xAxis.categories,\n\t\t\tyAxis = series.yAxis,\n\t\t\tpoints = series.points,\n\t\t\tdataLength = points.length,\n\t\t\thasModifyValue = !!series.modifyValue,\n\t\t\ti,\n\t\t\tpointPlacement = options.pointPlacement, // docs: accept numbers\n\t\t\tdynamicallyPlaced = pointPlacement === 'between' || isNumber(pointPlacement),\n\t\t\tthreshold = options.threshold;\n\n\t\t\n\t\t// Translate each point\n\t\tfor (i = 0; i < dataLength; i++) {\n\t\t\tvar point = points[i],\n\t\t\t\txValue = point.x,\n\t\t\t\tyValue = point.y,\n\t\t\t\tyBottom = point.low,\n\t\t\t\tstack = yAxis.stacks[(yValue < threshold ? '-' : '') + series.stackKey],\n\t\t\t\tpointStack,\n\t\t\t\tpointStackTotal;\n\n\t\t\t// Discard disallowed y values for log axes\n\t\t\tif (yAxis.isLog && yValue <= 0) {\n\t\t\t\tpoint.y = yValue = null;\n\t\t\t}\n\t\t\t\n\t\t\t// Get the plotX translation\n\t\t\tpoint.plotX = xAxis.translate(xValue, 0, 0, 0, 1, pointPlacement); // Math.round fixes #591\n\n\t\t\t// Calculate the bottom y value for stacked series\n\t\t\tif (stacking && series.visible && stack && stack[xValue]) {\n\n\n\t\t\t\tpointStack = stack[xValue];\n\t\t\t\tpointStackTotal = pointStack.total;\n\t\t\t\tpointStack.cum = yBottom = pointStack.cum - yValue; // start from top\n\t\t\t\tyValue = yBottom + yValue;\n\t\t\t\t\n\t\t\t\tif (pointStack.cum === 0) {\n\t\t\t\t\tyBottom = pick(threshold, yAxis.min);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (yAxis.isLog && yBottom <= 0) { // #1200, #1232\n\t\t\t\t\tyBottom = null;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (stacking === 'percent') {\n\t\t\t\t\tyBottom = pointStackTotal ? yBottom * 100 / pointStackTotal : 0;\n\t\t\t\t\tyValue = pointStackTotal ? yValue * 100 / pointStackTotal : 0;\n\t\t\t\t}\n\n\t\t\t\tpoint.percentage = pointStackTotal ? point.y * 100 / pointStackTotal : 0;\n\t\t\t\tpoint.total = point.stackTotal = pointStackTotal;\n\t\t\t\tpoint.stackY = yValue;\n\n\t\t\t\t// Place the stack label\n\t\t\t\tpointStack.setOffset(series.pointXOffset || 0, series.barW || 0);\n\t\t\t\t\n\t\t\t}\n\n\t\t\t// Set translated yBottom or remove it\n\t\t\tpoint.yBottom = defined(yBottom) ? \n\t\t\t\tyAxis.translate(yBottom, 0, 1, 0, 1) :\n\t\t\t\tnull;\n\t\t\t\n\t\t\t// general hook, used for Highstock compare mode\n\t\t\tif (hasModifyValue) {\n\t\t\t\tyValue = series.modifyValue(yValue, point);\n\t\t\t}\n\n\t\t\t// Set the the plotY value, reset it for redraws\n\t\t\tpoint.plotY = (typeof yValue === 'number' && yValue !== Infinity) ? \n\t\t\t\tmathRound(yAxis.translate(yValue, 0, 1, 0, 1) * 10) / 10 : // Math.round fixes #591\n\t\t\t\tUNDEFINED;\n\t\t\t\n\t\t\t// Set client related positions for mouse tracking\n\t\t\tpoint.clientX = dynamicallyPlaced ? xAxis.translate(xValue, 0, 0, 0, 1) : point.plotX; // #1514\n\t\t\t\t\n\t\t\tpoint.negative = point.y < (threshold || 0);\n\n\t\t\t// some API data\n\t\t\tpoint.category = categories && categories[point.x] !== UNDEFINED ?\n\t\t\t\tcategories[point.x] : point.x;\n\n\n\t\t}\n\n\t\t// now that we have the cropped data, build the segments\n\t\tseries.getSegments();\n\t},\n\t/**\n\t * Memoize tooltip texts and positions\n\t */\n\tsetTooltipPoints: function (renew) {\n\t\tvar series = this,\n\t\t\tpoints = [],\n\t\t\tpointsLength,\n\t\t\tlow,\n\t\t\thigh,\n\t\t\txAxis = series.xAxis,\n\t\t\taxisLength = xAxis ? (xAxis.tooltipLen || xAxis.len) : series.chart.plotSizeX, // tooltipLen and tooltipPosName used in polar\n\t\t\tpoint,\n\t\t\tnextPoint,\n\t\t\ti,\n\t\t\ttooltipPoints = []; // a lookup array for each pixel in the x dimension\n\n\t\t// don't waste resources if tracker is disabled\n\t\tif (series.options.enableMouseTracking === false) {\n\t\t\treturn;\n\t\t}\n\n\t\t// renew\n\t\tif (renew) {\n\t\t\tseries.tooltipPoints = null;\n\t\t}\n\n\t\t// concat segments to overcome null values\n\t\teach(series.segments || series.points, function (segment) {\n\t\t\tpoints = points.concat(segment);\n\t\t});\n\n\t\t// Reverse the points in case the X axis is reversed\n\t\tif (xAxis && xAxis.reversed) {\n\t\t\tpoints = points.reverse();\n\t\t}\n\n\t\t// Polar needs additional shaping\n\t\tif (series.orderTooltipPoints) {\n\t\t\tseries.orderTooltipPoints(points);\n\t\t}\n\n\t\t// Assign each pixel position to the nearest point\n\t\tpointsLength = points.length;\n\t\tfor (i = 0; i < pointsLength; i++) {\n\t\t\tpoint = points[i];\n\t\t\tnextPoint = points[i + 1];\n\t\t\t\n\t\t\t// Set this range's low to the last range's high plus one\n\t\t\tlow = points[i - 1] ? high + 1 : 0;\n\t\t\t// Now find the new high\n\t\t\thigh = points[i + 1] ?\n\t\t\t\tmathMin(mathMax(0, mathFloor( // #2070\n\t\t\t\t\t(point.clientX + (nextPoint ? (nextPoint.wrappedClientX || nextPoint.clientX) : axisLength)) / 2\n\t\t\t\t)), axisLength) :\n\t\t\t\taxisLength;\n\n\t\t\twhile (low >= 0 && low <= high) {\n\t\t\t\ttooltipPoints[low++] = point;\n\t\t\t}\n\t\t}\n\t\tseries.tooltipPoints = tooltipPoints;\n\t},\n\n\t/**\n\t * Format the header of the tooltip\n\t */\n\ttooltipHeaderFormatter: function (point) {\n\t\tvar series = this,\n\t\t\ttooltipOptions = series.tooltipOptions,\n\t\t\txDateFormat = tooltipOptions.xDateFormat,\n\t\t\tdateTimeLabelFormats = tooltipOptions.dateTimeLabelFormats,\n\t\t\txAxis = series.xAxis,\n\t\t\tisDateTime = xAxis && xAxis.options.type === 'datetime',\n\t\t\theaderFormat = tooltipOptions.headerFormat,\n\t\t\tclosestPointRange = xAxis && xAxis.closestPointRange,\n\t\t\tn;\n\t\t\t\n\t\t// Guess the best date format based on the closest point distance (#568)\n\t\tif (isDateTime && !xDateFormat) {\n\t\t\tif (closestPointRange) {\n\t\t\t\tfor (n in timeUnits) {\n\t\t\t\t\tif (timeUnits[n] >= closestPointRange) {\n\t\t\t\t\t\txDateFormat = dateTimeLabelFormats[n];\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\txDateFormat = dateTimeLabelFormats.day;\n\t\t\t}\n\t\t}\n\t\t\n\t\t// Insert the header date format if any\n\t\tif (isDateTime && xDateFormat && isNumber(point.key)) {\n\t\t\theaderFormat = headerFormat.replace('{point.key}', '{point.key:' + xDateFormat + '}');\n\t\t}\n\t\t\n\t\treturn format(headerFormat, {\n\t\t\tpoint: point,\n\t\t\tseries: series\n\t\t});\n\t},\n\n\t/**\n\t * Series mouse over handler\n\t */\n\tonMouseOver: function () {\n\t\tvar series = this,\n\t\t\tchart = series.chart,\n\t\t\thoverSeries = chart.hoverSeries;\n\n\t\t// set normal state to previous series\n\t\tif (hoverSeries && hoverSeries !== series) {\n\t\t\thoverSeries.onMouseOut();\n\t\t}\n\n\t\t// trigger the event, but to save processing time,\n\t\t// only if defined\n\t\tif (series.options.events.mouseOver) {\n\t\t\tfireEvent(series, 'mouseOver');\n\t\t}\n\n\t\t// hover this\n\t\tseries.setState(HOVER_STATE);\n\t\tchart.hoverSeries = series;\n\t},\n\n\t/**\n\t * Series mouse out handler\n\t */\n\tonMouseOut: function () {\n\t\t// trigger the event only if listeners exist\n\t\tvar series = this,\n\t\t\toptions = series.options,\n\t\t\tchart = series.chart,\n\t\t\ttooltip = chart.tooltip,\n\t\t\thoverPoint = chart.hoverPoint;\n\n\t\t// trigger mouse out on the point, which must be in this series\n\t\tif (hoverPoint) {\n\t\t\thoverPoint.onMouseOut();\n\t\t}\n\n\t\t// fire the mouse out event\n\t\tif (series && options.events.mouseOut) {\n\t\t\tfireEvent(series, 'mouseOut');\n\t\t}\n\n\n\t\t// hide the tooltip\n\t\tif (tooltip && !options.stickyTracking && (!tooltip.shared || series.noSharedTooltip)) {\n\t\t\ttooltip.hide();\n\t\t}\n\n\t\t// set normal state\n\t\tseries.setState();\n\t\tchart.hoverSeries = null;\n\t},\n\n\t/**\n\t * Animate in the series\n\t */\n\tanimate: function (init) {\n\t\tvar series = this,\n\t\t\tchart = series.chart,\n\t\t\trenderer = chart.renderer,\n\t\t\tclipRect,\n\t\t\tmarkerClipRect,\n\t\t\tanimation = series.options.animation,\n\t\t\tclipBox = chart.clipBox,\n\t\t\tinverted = chart.inverted,\n\t\t\tsharedClipKey;\n\n\t\t// Animation option is set to true\n\t\tif (animation && !isObject(animation)) {\n\t\t\tanimation = defaultPlotOptions[series.type].animation;\n\t\t}\n\t\tsharedClipKey = '_sharedClip' + animation.duration + animation.easing;\n\n\t\t// Initialize the animation. Set up the clipping rectangle.\n\t\tif (init) { \n\t\t\t\n\t\t\t// If a clipping rectangle with the same properties is currently present in the chart, use that. \n\t\t\tclipRect = chart[sharedClipKey];\n\t\t\tmarkerClipRect = chart[sharedClipKey + 'm'];\n\t\t\tif (!clipRect) {\n\t\t\t\tchart[sharedClipKey] = clipRect = renderer.clipRect(\n\t\t\t\t\textend(clipBox, { width: 0 })\n\t\t\t\t);\n\t\t\t\t\n\t\t\t\tchart[sharedClipKey + 'm'] = markerClipRect = renderer.clipRect(\n\t\t\t\t\t-99, // include the width of the first marker\n\t\t\t\t\tinverted ? -chart.plotLeft : -chart.plotTop, \n\t\t\t\t\t99,\n\t\t\t\t\tinverted ? chart.chartWidth : chart.chartHeight\n\t\t\t\t);\n\t\t\t}\n\t\t\tseries.group.clip(clipRect);\n\t\t\tseries.markerGroup.clip(markerClipRect);\n\t\t\tseries.sharedClipKey = sharedClipKey;\n\n\t\t// Run the animation\n\t\t} else { \n\t\t\tclipRect = chart[sharedClipKey];\n\t\t\tif (clipRect) {\n\t\t\t\tclipRect.animate({\n\t\t\t\t\twidth: chart.plotSizeX\n\t\t\t\t}, animation);\n\t\t\t\tchart[sharedClipKey + 'm'].animate({\n\t\t\t\t\twidth: chart.plotSizeX + 99\n\t\t\t\t}, animation);\n\t\t\t}\n\n\t\t\t// Delete this function to allow it only once\n\t\t\tseries.animate = null;\n\t\t\t\n\t\t\t// Call the afterAnimate function on animation complete (but don't overwrite the animation.complete option\n\t\t\t// which should be available to the user).\n\t\t\tseries.animationTimeout = setTimeout(function () {\n\t\t\t\tseries.afterAnimate();\n\t\t\t}, animation.duration);\n\t\t}\n\t},\n\t\n\t/**\n\t * This runs after animation to land on the final plot clipping\n\t */\n\tafterAnimate: function () {\n\t\tvar chart = this.chart,\n\t\t\tsharedClipKey = this.sharedClipKey,\n\t\t\tgroup = this.group;\n\t\t\t\n\t\tif (group && this.options.clip !== false) {\n\t\t\tgroup.clip(chart.clipRect);\n\t\t\tthis.markerGroup.clip(); // no clip\n\t\t}\n\t\t\n\t\t// Remove the shared clipping rectancgle when all series are shown\t\t\n\t\tsetTimeout(function () {\n\t\t\tif (sharedClipKey && chart[sharedClipKey]) {\n\t\t\t\tchart[sharedClipKey] = chart[sharedClipKey].destroy();\n\t\t\t\tchart[sharedClipKey + 'm'] = chart[sharedClipKey + 'm'].destroy();\n\t\t\t}\n\t\t}, 100);\n\t},\n\n\t/**\n\t * Draw the markers\n\t */\n\tdrawPoints: function () {\n\t\tvar series = this,\n\t\t\tpointAttr,\n\t\t\tpoints = series.points,\n\t\t\tchart = series.chart,\n\t\t\tplotX,\n\t\t\tplotY,\n\t\t\ti,\n\t\t\tpoint,\n\t\t\tradius,\n\t\t\tsymbol,\n\t\t\tisImage,\n\t\t\tgraphic,\n\t\t\toptions = series.options,\n\t\t\tseriesMarkerOptions = options.marker,\n\t\t\tpointMarkerOptions,\n\t\t\tenabled,\n\t\t\tisInside,\n\t\t\tmarkerGroup = series.markerGroup;\n\n\t\tif (seriesMarkerOptions.enabled || series._hasPointMarkers) {\n\t\t\t\n\t\t\ti = points.length;\n\t\t\twhile (i--) {\n\t\t\t\tpoint = points[i];\n\t\t\t\tplotX = mathFloor(point.plotX); // #1843\n\t\t\t\tplotY = point.plotY;\n\t\t\t\tgraphic = point.graphic;\n\t\t\t\tpointMarkerOptions = point.marker || {};\n\t\t\t\tenabled = (seriesMarkerOptions.enabled && pointMarkerOptions.enabled === UNDEFINED) || pointMarkerOptions.enabled;\n\t\t\t\tisInside = chart.isInsidePlot(mathRound(plotX), plotY, chart.inverted); // #1858\n\t\t\t\t\n\t\t\t\t// only draw the point if y is defined\n\t\t\t\tif (enabled && plotY !== UNDEFINED && !isNaN(plotY) && point.y !== null) {\n\n\t\t\t\t\t// shortcuts\n\t\t\t\t\tpointAttr = point.pointAttr[point.selected ? SELECT_STATE : NORMAL_STATE];\n\t\t\t\t\tradius = pointAttr.r;\n\t\t\t\t\tsymbol = pick(pointMarkerOptions.symbol, series.symbol);\n\t\t\t\t\tisImage = symbol.indexOf('url') === 0;\n\n\t\t\t\t\tif (graphic) { // update\n\t\t\t\t\t\tgraphic\n\t\t\t\t\t\t\t.attr({ // Since the marker group isn't clipped, each individual marker must be toggled\n\t\t\t\t\t\t\t\tvisibility: isInside ? (hasSVG ? 'inherit' : VISIBLE) : HIDDEN\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t.animate(extend({\n\t\t\t\t\t\t\t\tx: plotX - radius,\n\t\t\t\t\t\t\t\ty: plotY - radius\n\t\t\t\t\t\t\t}, graphic.symbolName ? { // don't apply to image symbols #507\n\t\t\t\t\t\t\t\twidth: 2 * radius,\n\t\t\t\t\t\t\t\theight: 2 * radius\n\t\t\t\t\t\t\t} : {}));\n\t\t\t\t\t} else if (isInside && (radius > 0 || isImage)) {\n\t\t\t\t\t\tpoint.graphic = graphic = chart.renderer.symbol(\n\t\t\t\t\t\t\tsymbol,\n\t\t\t\t\t\t\tplotX - radius,\n\t\t\t\t\t\t\tplotY - radius,\n\t\t\t\t\t\t\t2 * radius,\n\t\t\t\t\t\t\t2 * radius\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.attr(pointAttr)\n\t\t\t\t\t\t.add(markerGroup);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t} else if (graphic) {\n\t\t\t\t\tpoint.graphic = graphic.destroy(); // #1269\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t},\n\n\t/**\n\t * Convert state properties from API naming conventions to SVG attributes\n\t *\n\t * @param {Object} options API options object\n\t * @param {Object} base1 SVG attribute object to inherit from\n\t * @param {Object} base2 Second level SVG attribute object to inherit from\n\t */\n\tconvertAttribs: function (options, base1, base2, base3) {\n\t\tvar conversion = this.pointAttrToOptions,\n\t\t\tattr,\n\t\t\toption,\n\t\t\tobj = {};\n\n\t\toptions = options || {};\n\t\tbase1 = base1 || {};\n\t\tbase2 = base2 || {};\n\t\tbase3 = base3 || {};\n\n\t\tfor (attr in conversion) {\n\t\t\toption = conversion[attr];\n\t\t\tobj[attr] = pick(options[option], base1[attr], base2[attr], base3[attr]);\n\t\t}\n\t\treturn obj;\n\t},\n\n\t/**\n\t * Get the state attributes. Each series type has its own set of attributes\n\t * that are allowed to change on a point's state change. Series wide attributes are stored for\n\t * all series, and additionally point specific attributes are stored for all\n\t * points with individual marker options. If such options are not defined for the point,\n\t * a reference to the series wide attributes is stored in point.pointAttr.\n\t */\n\tgetAttribs: function () {\n\t\tvar series = this,\n\t\t\tseriesOptions = series.options,\n\t\t\tnormalOptions = defaultPlotOptions[series.type].marker ? seriesOptions.marker : seriesOptions,\n\t\t\tstateOptions = normalOptions.states,\n\t\t\tstateOptionsHover = stateOptions[HOVER_STATE],\n\t\t\tpointStateOptionsHover,\n\t\t\tseriesColor = series.color,\n\t\t\tnormalDefaults = {\n\t\t\t\tstroke: seriesColor,\n\t\t\t\tfill: seriesColor\n\t\t\t},\n\t\t\tpoints = series.points || [], // #927\n\t\t\ti,\n\t\t\tpoint,\n\t\t\tseriesPointAttr = [],\n\t\t\tpointAttr,\n\t\t\tpointAttrToOptions = series.pointAttrToOptions,\n\t\t\thasPointSpecificOptions,\n\t\t\tnegativeColor = seriesOptions.negativeColor,\n\t\t\tkey;\n\n\t\t// series type specific modifications\n\t\tif (seriesOptions.marker) { // line, spline, area, areaspline, scatter\n\n\t\t\t// if no hover radius is given, default to normal radius + 2\n\t\t\tstateOptionsHover.radius = stateOptionsHover.radius || normalOptions.radius + 2;\n\t\t\tstateOptionsHover.lineWidth = stateOptionsHover.lineWidth || normalOptions.lineWidth + 1;\n\t\t\t\n\t\t} else { // column, bar, pie\n\n\t\t\t// if no hover color is given, brighten the normal color\n\t\t\tstateOptionsHover.color = stateOptionsHover.color ||\n\t\t\t\tColor(stateOptionsHover.color || seriesColor)\n\t\t\t\t\t.brighten(stateOptionsHover.brightness).get();\n\t\t}\n\n\t\t// general point attributes for the series normal state\n\t\tseriesPointAttr[NORMAL_STATE] = series.convertAttribs(normalOptions, normalDefaults);\n\n\t\t// HOVER_STATE and SELECT_STATE states inherit from normal state except the default radius\n\t\teach([HOVER_STATE, SELECT_STATE], function (state) {\n\t\t\tseriesPointAttr[state] =\n\t\t\t\t\tseries.convertAttribs(stateOptions[state], seriesPointAttr[NORMAL_STATE]);\n\t\t});\n\n\t\t// set it\n\t\tseries.pointAttr = seriesPointAttr;\n\n\n\t\t// Generate the point-specific attribute collections if specific point\n\t\t// options are given. If not, create a referance to the series wide point\n\t\t// attributes\n\t\ti = points.length;\n\t\twhile (i--) {\n\t\t\tpoint = points[i];\n\t\t\tnormalOptions = (point.options && point.options.marker) || point.options;\n\t\t\tif (normalOptions && normalOptions.enabled === false) {\n\t\t\t\tnormalOptions.radius = 0;\n\t\t\t}\n\t\t\t\n\t\t\tif (point.negative && negativeColor) {\n\t\t\t\tpoint.color = point.fillColor = negativeColor;\n\t\t\t}\n\t\t\t\n\t\t\thasPointSpecificOptions = seriesOptions.colorByPoint || point.color; // #868\n\t\t\t\n\t\t\t// check if the point has specific visual options\n\t\t\tif (point.options) {\n\t\t\t\tfor (key in pointAttrToOptions) {\n\t\t\t\t\tif (defined(normalOptions[pointAttrToOptions[key]])) {\n\t\t\t\t\t\thasPointSpecificOptions = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// a specific marker config object is defined for the individual point:\n\t\t\t// create it's own attribute collection\n\t\t\tif (hasPointSpecificOptions) {\n\t\t\t\tnormalOptions = normalOptions || {};\n\t\t\t\tpointAttr = [];\n\t\t\t\tstateOptions = normalOptions.states || {}; // reassign for individual point\n\t\t\t\tpointStateOptionsHover = stateOptions[HOVER_STATE] = stateOptions[HOVER_STATE] || {};\n\n\t\t\t\t// Handle colors for column and pies\n\t\t\t\tif (!seriesOptions.marker) { // column, bar, point\n\t\t\t\t\t// if no hover color is given, brighten the normal color\n\t\t\t\t\tpointStateOptionsHover.color =\n\t\t\t\t\t\tColor(pointStateOptionsHover.color || point.color)\n\t\t\t\t\t\t\t.brighten(pointStateOptionsHover.brightness ||\n\t\t\t\t\t\t\t\tstateOptionsHover.brightness).get();\n\n\t\t\t\t}\n\n\t\t\t\t// normal point state inherits series wide normal state\n\t\t\t\tpointAttr[NORMAL_STATE] = series.convertAttribs(extend({\n\t\t\t\t\tcolor: point.color // #868\n\t\t\t\t}, normalOptions), seriesPointAttr[NORMAL_STATE]);\n\n\t\t\t\t// inherit from point normal and series hover\n\t\t\t\tpointAttr[HOVER_STATE] = series.convertAttribs(\n\t\t\t\t\tstateOptions[HOVER_STATE],\n\t\t\t\t\tseriesPointAttr[HOVER_STATE],\n\t\t\t\t\tpointAttr[NORMAL_STATE]\n\t\t\t\t);\n\t\t\t\t\n\t\t\t\t// inherit from point normal and series hover\n\t\t\t\tpointAttr[SELECT_STATE] = series.convertAttribs(\n\t\t\t\t\tstateOptions[SELECT_STATE],\n\t\t\t\t\tseriesPointAttr[SELECT_STATE],\n\t\t\t\t\tpointAttr[NORMAL_STATE]\n\t\t\t\t);\n\n\t\t\t\t// Force the fill to negativeColor on markers\n\t\t\t\tif (point.negative && seriesOptions.marker && negativeColor) {\n\t\t\t\t\tpointAttr[NORMAL_STATE].fill = pointAttr[HOVER_STATE].fill = pointAttr[SELECT_STATE].fill = \n\t\t\t\t\t\tseries.convertAttribs({ fillColor: negativeColor }).fill;\n\t\t\t\t}\n\n\n\t\t\t// no marker config object is created: copy a reference to the series-wide\n\t\t\t// attribute collection\n\t\t\t} else {\n\t\t\t\tpointAttr = seriesPointAttr;\n\t\t\t}\n\n\t\t\tpoint.pointAttr = pointAttr;\n\n\t\t}\n\n\t},\n\t/**\n\t * Update the series with a new set of options\n\t */\n\tupdate: function (newOptions, redraw) {\n\t\tvar chart = this.chart,\n\t\t\t// must use user options when changing type because this.options is merged\n\t\t\t// in with type specific plotOptions\n\t\t\toldOptions = this.userOptions,\n\t\t\toldType = this.type;\n\n\t\t// Do the merge, with some forced options\n\t\tnewOptions = merge(oldOptions, {\n\t\t\tanimation: false,\n\t\t\tindex: this.index,\n\t\t\tpointStart: this.xData[0] // when updating after addPoint\n\t\t}, { data: this.options.data }, newOptions);\n\n\t\t// Destroy the series and reinsert methods from the type prototype\n\t\tthis.remove(false);\n\t\textend(this, seriesTypes[newOptions.type || oldType].prototype);\n\t\t\n\n\t\tthis.init(chart, newOptions);\n\t\tif (pick(redraw, true)) {\n\t\t\tchart.redraw(false);\n\t\t}\n\t},\n\n\t/**\n\t * Clear DOM objects and free up memory\n\t */\n\tdestroy: function () {\n\t\tvar series = this,\n\t\t\tchart = series.chart,\n\t\t\tissue134 = /AppleWebKit\\/533/.test(userAgent),\n\t\t\tdestroy,\n\t\t\ti,\n\t\t\tdata = series.data || [],\n\t\t\tpoint,\n\t\t\tprop,\n\t\t\taxis;\n\n\t\t// add event hook\n\t\tfireEvent(series, 'destroy');\n\n\t\t// remove all events\n\t\tremoveEvent(series);\n\t\t\n\t\t// erase from axes\n\t\teach(['xAxis', 'yAxis'], function (AXIS) {\n\t\t\taxis = series[AXIS];\n\t\t\tif (axis) {\n\t\t\t\terase(axis.series, series);\n\t\t\t\taxis.isDirty = axis.forceRedraw = true;\n\t\t\t}\n\t\t});\n\n\t\t// remove legend items\n\t\tif (series.legendItem) {\n\t\t\tseries.chart.legend.destroyItem(series);\n\t\t}\n\n\t\t// destroy all points with their elements\n\t\ti = data.length;\n\t\twhile (i--) {\n\t\t\tpoint = data[i];\n\t\t\tif (point && point.destroy) {\n\t\t\t\tpoint.destroy();\n\t\t\t}\n\t\t}\n\t\tseries.points = null;\n\n\t\t// Clear the animation timeout if we are destroying the series during initial animation\n\t\tclearTimeout(series.animationTimeout);\n\n\t\t// destroy all SVGElements associated to the series\n\t\teach(['area', 'graph', 'dataLabelsGroup', 'group', 'markerGroup', 'tracker',\n\t\t\t\t'graphNeg', 'areaNeg', 'posClip', 'negClip'], function (prop) {\n\t\t\tif (series[prop]) {\n\n\t\t\t\t// issue 134 workaround\n\t\t\t\tdestroy = issue134 && prop === 'group' ?\n\t\t\t\t\t'hide' :\n\t\t\t\t\t'destroy';\n\n\t\t\t\tseries[prop][destroy]();\n\t\t\t}\n\t\t});\n\n\t\t// remove from hoverSeries\n\t\tif (chart.hoverSeries === series) {\n\t\t\tchart.hoverSeries = null;\n\t\t}\n\t\terase(chart.series, series);\n\n\t\t// clear all members\n\t\tfor (prop in series) {\n\t\t\tdelete series[prop];\n\t\t}\n\t},\n\n\t/**\n\t * Draw the data labels\n\t */\n\tdrawDataLabels: function () {\n\t\t\n\t\tvar series = this,\n\t\t\tseriesOptions = series.options,\n\t\t\toptions = seriesOptions.dataLabels,\n\t\t\tpoints = series.points,\n\t\t\tpointOptions,\n\t\t\tgeneralOptions,\n\t\t\tstr,\n\t\t\tdataLabelsGroup;\n\t\t\n\t\tif (options.enabled || series._hasPointLabels) {\n\t\t\t\t\t\t\n\t\t\t// Process default alignment of data labels for columns\n\t\t\tif (series.dlProcessOptions) {\n\t\t\t\tseries.dlProcessOptions(options);\n\t\t\t}\n\n\t\t\t// Create a separate group for the data labels to avoid rotation\n\t\t\tdataLabelsGroup = series.plotGroup(\n\t\t\t\t'dataLabelsGroup', \n\t\t\t\t'data-labels', \n\t\t\t\tseries.visible ? VISIBLE : HIDDEN, \n\t\t\t\toptions.zIndex || 6\n\t\t\t);\n\t\t\t\n\t\t\t// Make the labels for each point\n\t\t\tgeneralOptions = options;\n\t\t\teach(points, function (point) {\n\t\t\t\t\n\t\t\t\tvar enabled,\n\t\t\t\t\tdataLabel = point.dataLabel,\n\t\t\t\t\tlabelConfig,\n\t\t\t\t\tattr,\n\t\t\t\t\tname,\n\t\t\t\t\trotation,\n\t\t\t\t\tconnector = point.connector,\n\t\t\t\t\tisNew = true;\n\t\t\t\t\n\t\t\t\t// Determine if each data label is enabled\n\t\t\t\tpointOptions = point.options && point.options.dataLabels;\n\t\t\t\tenabled = generalOptions.enabled || (pointOptions && pointOptions.enabled);\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t// If the point is outside the plot area, destroy it. #678, #820\n\t\t\t\tif (dataLabel && !enabled) {\n\t\t\t\t\tpoint.dataLabel = dataLabel.destroy();\n\t\t\t\t\n\t\t\t\t// Individual labels are disabled if the are explicitly disabled \n\t\t\t\t// in the point options, or if they fall outside the plot area.\n\t\t\t\t} else if (enabled) {\n\t\t\t\t\t\n\t\t\t\t\t// Create individual options structure that can be extended without \n\t\t\t\t\t// affecting others\n\t\t\t\t\toptions = merge(generalOptions, pointOptions);\n\n\t\t\t\t\trotation = options.rotation;\n\t\t\t\t\t\n\t\t\t\t\t// Get the string\n\t\t\t\t\tlabelConfig = point.getLabelConfig();\n\t\t\t\t\tstr = options.format ?\n\t\t\t\t\t\tformat(options.format, labelConfig) : \n\t\t\t\t\t\toptions.formatter.call(labelConfig, options);\n\t\t\t\t\t\n\t\t\t\t\t// Determine the color\n\t\t\t\t\toptions.style.color = pick(options.color, options.style.color, series.color, 'black');\n\t\n\t\t\t\t\t\n\t\t\t\t\t// update existing label\n\t\t\t\t\tif (dataLabel) {\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (defined(str)) {\n\t\t\t\t\t\t\tdataLabel\n\t\t\t\t\t\t\t\t.attr({\n\t\t\t\t\t\t\t\t\ttext: str\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tisNew = false;\n\t\t\t\t\t\t\n\t\t\t\t\t\t} else { // #1437 - the label is shown conditionally\n\t\t\t\t\t\t\tpoint.dataLabel = dataLabel = dataLabel.destroy();\n\t\t\t\t\t\t\tif (connector) {\n\t\t\t\t\t\t\t\tpoint.connector = connector.destroy();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t// create new label\n\t\t\t\t\t} else if (defined(str)) {\n\t\t\t\t\t\tattr = {\n\t\t\t\t\t\t\t//align: align,\n\t\t\t\t\t\t\tfill: options.backgroundColor,\n\t\t\t\t\t\t\tstroke: options.borderColor,\n\t\t\t\t\t\t\t'stroke-width': options.borderWidth,\n\t\t\t\t\t\t\tr: options.borderRadius || 0,\n\t\t\t\t\t\t\trotation: rotation,\n\t\t\t\t\t\t\tpadding: options.padding,\n\t\t\t\t\t\t\tzIndex: 1\n\t\t\t\t\t\t};\n\t\t\t\t\t\t// Remove unused attributes (#947)\n\t\t\t\t\t\tfor (name in attr) {\n\t\t\t\t\t\t\tif (attr[name] === UNDEFINED) {\n\t\t\t\t\t\t\t\tdelete attr[name];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tdataLabel = point.dataLabel = series.chart.renderer[rotation ? 'text' : 'label']( // labels don't support rotation\n\t\t\t\t\t\t\tstr,\n\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t-999,\n\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\toptions.useHTML\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.attr(attr)\n\t\t\t\t\t\t.css(options.style)\n\t\t\t\t\t\t.add(dataLabelsGroup)\n\t\t\t\t\t\t.shadow(options.shadow);\n\t\t\t\t\t\t\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif (dataLabel) {\n\t\t\t\t\t\t// Now the data label is created and placed at 0,0, so we need to align it\n\t\t\t\t\t\tseries.alignDataLabel(point, dataLabel, options, null, isNew);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t},\n\t\n\t/**\n\t * Align each individual data label\n\t */\n\talignDataLabel: function (point, dataLabel, options, alignTo, isNew) {\n\t\tvar chart = this.chart,\n\t\t\tinverted = chart.inverted,\n\t\t\tplotX = pick(point.plotX, -999),\n\t\t\tplotY = pick(point.plotY, -999),\n\t\t\tbBox = dataLabel.getBBox(),\n\t\t\talignAttr; // the final position;\n\t\t\t\t\n\t\t// The alignment box is a singular point\n\t\talignTo = extend({\n\t\t\tx: inverted ? chart.plotWidth - plotY : plotX,\n\t\t\ty: mathRound(inverted ? chart.plotHeight - plotX : plotY),\n\t\t\twidth: 0,\n\t\t\theight: 0\n\t\t}, alignTo);\n\t\t\n\t\t// Add the text size for alignment calculation\n\t\textend(options, {\n\t\t\twidth: bBox.width,\n\t\t\theight: bBox.height\n\t\t});\n\n\t\t// Allow a hook for changing alignment in the last moment, then do the alignment\n\t\tif (options.rotation) { // Fancy box alignment isn't supported for rotated text\n\t\t\talignAttr = {\n\t\t\t\talign: options.align,\n\t\t\t\tx: alignTo.x + options.x + alignTo.width / 2,\n\t\t\t\ty: alignTo.y + options.y + alignTo.height / 2\n\t\t\t};\n\t\t\tdataLabel[isNew ? 'attr' : 'animate'](alignAttr);\n\t\t} else {\n\t\t\tdataLabel.align(options, null, alignTo);\n\t\t\talignAttr = dataLabel.alignAttr;\n\t\t}\n\t\t\n\t\t// Show or hide based on the final aligned position\n\t\tdataLabel.attr({\n\t\t\tvisibility: options.crop === false ||\n\t\t\t\t\t(chart.isInsidePlot(alignAttr.x, alignAttr.y) && chart.isInsidePlot(alignAttr.x + bBox.width, alignAttr.y + bBox.height)) ?\n\t\t\t\t(chart.renderer.isSVG ? 'inherit' : VISIBLE) : \n\t\t\t\tHIDDEN\n\t\t});\n\t\t\t\t\n\t},\n\t\n\t/**\n\t * Return the graph path of a segment\n\t */\n\tgetSegmentPath: function (segment) {\t\t\n\t\tvar series = this,\n\t\t\tsegmentPath = [],\n\t\t\tstep = series.options.step;\n\t\t\t\n\t\t// build the segment line\n\t\teach(segment, function (point, i) {\n\t\t\t\n\t\t\tvar plotX = point.plotX,\n\t\t\t\tplotY = point.plotY,\n\t\t\t\tlastPoint;\n\n\t\t\tif (series.getPointSpline) { // generate the spline as defined in the SplineSeries object\n\t\t\t\tsegmentPath.push.apply(segmentPath, series.getPointSpline(segment, point, i));\n\n\t\t\t} else {\n\n\t\t\t\t// moveTo or lineTo\n\t\t\t\tsegmentPath.push(i ? L : M);\n\n\t\t\t\t// step line?\n\t\t\t\tif (step && i) {\n\t\t\t\t\tlastPoint = segment[i - 1];\n\t\t\t\t\tif (step === 'right') {\n\t\t\t\t\t\tsegmentPath.push(\n\t\t\t\t\t\t\tlastPoint.plotX,\n\t\t\t\t\t\t\tplotY\n\t\t\t\t\t\t);\n\t\t\t\t\t\t\n\t\t\t\t\t} else if (step === 'center') {\n\t\t\t\t\t\tsegmentPath.push(\n\t\t\t\t\t\t\t(lastPoint.plotX + plotX) / 2,\n\t\t\t\t\t\t\tlastPoint.plotY,\n\t\t\t\t\t\t\t(lastPoint.plotX + plotX) / 2,\n\t\t\t\t\t\t\tplotY\n\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\tsegmentPath.push(\n\t\t\t\t\t\t\tplotX,\n\t\t\t\t\t\t\tlastPoint.plotY\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// normal line to next point\n\t\t\t\tsegmentPath.push(\n\t\t\t\t\tpoint.plotX,\n\t\t\t\t\tpoint.plotY\n\t\t\t\t);\n\t\t\t}\n\t\t});\n\t\t\n\t\treturn segmentPath;\n\t},\n\n\t/**\n\t * Get the graph path\n\t */\n\tgetGraphPath: function () {\n\t\tvar series = this,\n\t\t\tgraphPath = [],\n\t\t\tsegmentPath,\n\t\t\tsinglePoints = []; // used in drawTracker\n\n\t\t// Divide into segments and build graph and area paths\n\t\teach(series.segments, function (segment) {\n\t\t\t\n\t\t\tsegmentPath = series.getSegmentPath(segment);\n\t\t\t\n\t\t\t// add the segment to the graph, or a single point for tracking\n\t\t\tif (segment.length > 1) {\n\t\t\t\tgraphPath = graphPath.concat(segmentPath);\n\t\t\t} else {\n\t\t\t\tsinglePoints.push(segment[0]);\n\t\t\t}\n\t\t});\n\n\t\t// Record it for use in drawGraph and drawTracker, and return graphPath\n\t\tseries.singlePoints = singlePoints;\n\t\tseries.graphPath = graphPath;\n\t\t\n\t\treturn graphPath;\n\t\t\n\t},\n\t\n\t/**\n\t * Draw the actual graph\n\t */\n\tdrawGraph: function () {\n\t\tvar series = this,\n\t\t\toptions = this.options,\n\t\t\tprops = [['graph', options.lineColor || this.color]],\n\t\t\tlineWidth = options.lineWidth,\n\t\t\tdashStyle =  options.dashStyle,\n\t\t\tgraphPath = this.getGraphPath(),\n\t\t\tnegativeColor = options.negativeColor;\n\t\t\t\n\t\tif (negativeColor) {\n\t\t\tprops.push(['graphNeg', negativeColor]);\n\t\t}\n\t\t\n\t\t// draw the graph\n\t\teach(props, function (prop, i) {\n\t\t\tvar graphKey = prop[0],\n\t\t\t\tgraph = series[graphKey],\n\t\t\t\tattribs;\n\t\t\t\n\t\t\tif (graph) {\n\t\t\t\tstop(graph); // cancel running animations, #459\n\t\t\t\tgraph.animate({ d: graphPath });\n\t\n\t\t\t} else if (lineWidth && graphPath.length) { // #1487\n\t\t\t\tattribs = {\n\t\t\t\t\tstroke: prop[1],\n\t\t\t\t\t'stroke-width': lineWidth,\n\t\t\t\t\tzIndex: 1 // #1069\n\t\t\t\t};\n\t\t\t\tif (dashStyle) {\n\t\t\t\t\tattribs.dashstyle = dashStyle;\n\t\t\t\t}\n\n\t\t\t\tseries[graphKey] = series.chart.renderer.path(graphPath)\n\t\t\t\t\t.attr(attribs)\n\t\t\t\t\t.add(series.group)\n\t\t\t\t\t.shadow(!i && options.shadow);\n\t\t\t}\n\t\t});\n\t},\n\t\n\t/**\n\t * Clip the graphs into the positive and negative coloured graphs\n\t */\n\tclipNeg: function () {\n\t\tvar options = this.options,\n\t\t\tchart = this.chart,\n\t\t\trenderer = chart.renderer,\n\t\t\tnegativeColor = options.negativeColor || options.negativeFillColor,\n\t\t\ttranslatedThreshold,\n\t\t\tposAttr,\n\t\t\tnegAttr,\n\t\t\tgraph = this.graph,\n\t\t\tarea = this.area,\n\t\t\tposClip = this.posClip,\n\t\t\tnegClip = this.negClip,\n\t\t\tchartWidth = chart.chartWidth,\n\t\t\tchartHeight = chart.chartHeight,\n\t\t\tchartSizeMax = mathMax(chartWidth, chartHeight),\n\t\t\tyAxis = this.yAxis,\n\t\t\tabove,\n\t\t\tbelow;\n\t\t\n\t\tif (negativeColor && (graph || area)) {\n\t\t\ttranslatedThreshold = mathRound(yAxis.toPixels(options.threshold || 0, true));\n\t\t\tabove = {\n\t\t\t\tx: 0,\n\t\t\t\ty: 0,\n\t\t\t\twidth: chartSizeMax,\n\t\t\t\theight: translatedThreshold\n\t\t\t};\n\t\t\tbelow = {\n\t\t\t\tx: 0,\n\t\t\t\ty: translatedThreshold,\n\t\t\t\twidth: chartSizeMax,\n\t\t\t\theight: chartSizeMax\n\t\t\t};\n\t\t\t\n\t\t\tif (chart.inverted) {\n\n\t\t\t\tabove.height = below.y = chart.plotWidth - translatedThreshold;\n\t\t\t\tif (renderer.isVML) {\n\t\t\t\t\tabove = {\n\t\t\t\t\t\tx: chart.plotWidth - translatedThreshold - chart.plotLeft,\n\t\t\t\t\t\ty: 0,\n\t\t\t\t\t\twidth: chartWidth,\n\t\t\t\t\t\theight: chartHeight\n\t\t\t\t\t};\n\t\t\t\t\tbelow = {\n\t\t\t\t\t\tx: translatedThreshold + chart.plotLeft - chartWidth,\n\t\t\t\t\t\ty: 0,\n\t\t\t\t\t\twidth: chart.plotLeft + translatedThreshold,\n\t\t\t\t\t\theight: chartWidth\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif (yAxis.reversed) {\n\t\t\t\tposAttr = below;\n\t\t\t\tnegAttr = above;\n\t\t\t} else {\n\t\t\t\tposAttr = above;\n\t\t\t\tnegAttr = below;\n\t\t\t}\n\t\t\n\t\t\tif (posClip) { // update\n\t\t\t\tposClip.animate(posAttr);\n\t\t\t\tnegClip.animate(negAttr);\n\t\t\t} else {\n\t\t\t\t\n\t\t\t\tthis.posClip = posClip = renderer.clipRect(posAttr);\n\t\t\t\tthis.negClip = negClip = renderer.clipRect(negAttr);\n\t\t\t\t\n\t\t\t\tif (graph && this.graphNeg) {\n\t\t\t\t\tgraph.clip(posClip);\n\t\t\t\t\tthis.graphNeg.clip(negClip);\t\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (area) {\n\t\t\t\t\tarea.clip(posClip);\n\t\t\t\t\tthis.areaNeg.clip(negClip);\n\t\t\t\t} \n\t\t\t} \n\t\t}\t\n\t},\n\n\t/**\n\t * Initialize and perform group inversion on series.group and series.markerGroup\n\t */\n\tinvertGroups: function () {\n\t\tvar series = this,\n\t\t\tchart = series.chart;\n\n\t\t// Pie, go away (#1736)\n\t\tif (!series.xAxis) {\n\t\t\treturn;\n\t\t}\n\t\t\n\t\t// A fixed size is needed for inversion to work\n\t\tfunction setInvert() {\t\t\t\n\t\t\tvar size = {\n\t\t\t\twidth: series.yAxis.len,\n\t\t\t\theight: series.xAxis.len\n\t\t\t};\n\t\t\t\n\t\t\teach(['group', 'markerGroup'], function (groupName) {\n\t\t\t\tif (series[groupName]) {\n\t\t\t\t\tseries[groupName].attr(size).invert();\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\taddEvent(chart, 'resize', setInvert); // do it on resize\n\t\taddEvent(series, 'destroy', function () {\n\t\t\tremoveEvent(chart, 'resize', setInvert);\n\t\t});\n\n\t\t// Do it now\n\t\tsetInvert(); // do it now\n\t\t\n\t\t// On subsequent render and redraw, just do setInvert without setting up events again\n\t\tseries.invertGroups = setInvert;\n\t},\n\t\n\t/**\n\t * General abstraction for creating plot groups like series.group, series.dataLabelsGroup and \n\t * series.markerGroup. On subsequent calls, the group will only be adjusted to the updated plot size.\n\t */\n\tplotGroup: function (prop, name, visibility, zIndex, parent) {\n\t\tvar group = this[prop],\n\t\t\tisNew = !group;\n\t\t\n\t\t// Generate it on first call\n\t\tif (isNew) {\t\n\t\t\tthis[prop] = group = this.chart.renderer.g(name)\n\t\t\t\t.attr({\n\t\t\t\t\tvisibility: visibility,\n\t\t\t\t\tzIndex: zIndex || 0.1 // IE8 needs this\n\t\t\t\t})\n\t\t\t\t.add(parent);\n\t\t}\n\t\t// Place it on first and subsequent (redraw) calls\n\t\tgroup[isNew ? 'attr' : 'animate'](this.getPlotBox());\n\t\treturn group;\t\t\n\t},\n\n\t/**\n\t * Get the translation and scale for the plot area of this series\n\t */\n\tgetPlotBox: function () {\n\t\treturn {\n\t\t\ttranslateX: this.xAxis ? this.xAxis.left : this.chart.plotLeft, \n\t\t\ttranslateY: this.yAxis ? this.yAxis.top : this.chart.plotTop,\n\t\t\tscaleX: 1, // #1623\n\t\t\tscaleY: 1\n\t\t};\n\t},\n\t\n\t/**\n\t * Render the graph and markers\n\t */\n\trender: function () {\n\t\tvar series = this,\n\t\t\tchart = series.chart,\n\t\t\tgroup,\n\t\t\toptions = series.options,\n\t\t\tanimation = options.animation,\n\t\t\tdoAnimation = animation && !!series.animate && \n\t\t\t\tchart.renderer.isSVG, // this animation doesn't work in IE8 quirks when the group div is hidden,\n\t\t\t\t// and looks bad in other oldIE\n\t\t\tvisibility = series.visible ? VISIBLE : HIDDEN,\n\t\t\tzIndex = options.zIndex,\n\t\t\thasRendered = series.hasRendered,\n\t\t\tchartSeriesGroup = chart.seriesGroup;\n\t\t\n\t\t// the group\n\t\tgroup = series.plotGroup(\n\t\t\t'group', \n\t\t\t'series', \n\t\t\tvisibility, \n\t\t\tzIndex, \n\t\t\tchartSeriesGroup\n\t\t);\n\t\t\n\t\tseries.markerGroup = series.plotGroup(\n\t\t\t'markerGroup', \n\t\t\t'markers', \n\t\t\tvisibility, \n\t\t\tzIndex, \n\t\t\tchartSeriesGroup\n\t\t);\n\t\t\n\t\t// initiate the animation\n\t\tif (doAnimation) {\n\t\t\tseries.animate(true);\n\t\t}\n\n\t\t// cache attributes for shapes\n\t\tseries.getAttribs();\n\n\t\t// SVGRenderer needs to know this before drawing elements (#1089, #1795)\n\t\tgroup.inverted = series.isCartesian ? chart.inverted : false;\n\t\t\n\t\t// draw the graph if any\n\t\tif (series.drawGraph) {\n\t\t\tseries.drawGraph();\n\t\t\tseries.clipNeg();\n\t\t}\n\n\t\t// draw the data labels (inn pies they go before the points)\n\t\tseries.drawDataLabels();\n\t\t\n\t\t// draw the points\n\t\tseries.drawPoints();\n\n\n\t\t// draw the mouse tracking area\n\t\tif (series.options.enableMouseTracking !== false) {\n\t\t\tseries.drawTracker();\n\t\t}\n\t\t\n\t\t// Handle inverted series and tracker groups\n\t\tif (chart.inverted) {\n\t\t\tseries.invertGroups();\n\t\t}\n\t\t\n\t\t// Initial clipping, must be defined after inverting groups for VML\n\t\tif (options.clip !== false && !series.sharedClipKey && !hasRendered) {\n\t\t\tgroup.clip(chart.clipRect);\n\t\t}\n\n\t\t// Run the animation\n\t\tif (doAnimation) {\n\t\t\tseries.animate();\n\t\t} else if (!hasRendered) {\n\t\t\tseries.afterAnimate();\n\t\t}\n\n\t\tseries.isDirty = series.isDirtyData = false; // means data is in accordance with what you see\n\t\t// (See #322) series.isDirty = series.isDirtyData = false; // means data is in accordance with what you see\n\t\tseries.hasRendered = true;\n\t},\n\t\n\t/**\n\t * Redraw the series after an update in the axes.\n\t */\n\tredraw: function () {\n\t\tvar series = this,\n\t\t\tchart = series.chart,\n\t\t\twasDirtyData = series.isDirtyData, // cache it here as it is set to false in render, but used after\n\t\t\tgroup = series.group,\n\t\t\txAxis = series.xAxis,\n\t\t\tyAxis = series.yAxis;\n\n\t\t// reposition on resize\n\t\tif (group) {\n\t\t\tif (chart.inverted) {\n\t\t\t\tgroup.attr({\n\t\t\t\t\twidth: chart.plotWidth,\n\t\t\t\t\theight: chart.plotHeight\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tgroup.animate({\n\t\t\t\ttranslateX: pick(xAxis && xAxis.left, chart.plotLeft),\n\t\t\t\ttranslateY: pick(yAxis && yAxis.top, chart.plotTop)\n\t\t\t});\n\t\t}\n\n\t\tseries.translate();\n\t\tseries.setTooltipPoints(true);\n\n\t\tseries.render();\n\t\tif (wasDirtyData) {\n\t\t\tfireEvent(series, 'updatedData');\n\t\t}\n\t},\n\n\t/**\n\t * Set the state of the graph\n\t */\n\tsetState: function (state) {\n\t\tvar series = this,\n\t\t\toptions = series.options,\n\t\t\tgraph = series.graph,\n\t\t\tgraphNeg = series.graphNeg,\n\t\t\tstateOptions = options.states,\n\t\t\tlineWidth = options.lineWidth,\n\t\t\tattribs;\n\n\t\tstate = state || NORMAL_STATE;\n\n\t\tif (series.state !== state) {\n\t\t\tseries.state = state;\n\n\t\t\tif (stateOptions[state] && stateOptions[state].enabled === false) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (state) {\n\t\t\t\tlineWidth = stateOptions[state].lineWidth || lineWidth + 1;\n\t\t\t}\n\n\t\t\tif (graph && !graph.dashstyle) { // hover is turned off for dashed lines in VML\n\t\t\t\tattribs = {\n\t\t\t\t\t'stroke-width': lineWidth\n\t\t\t\t};\n\t\t\t\t// use attr because animate will cause any other animation on the graph to stop\n\t\t\t\tgraph.attr(attribs);\n\t\t\t\tif (graphNeg) {\n\t\t\t\t\tgraphNeg.attr(attribs);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Set the visibility of the graph\n\t *\n\t * @param vis {Boolean} True to show the series, false to hide. If UNDEFINED,\n\t *        the visibility is toggled.\n\t */\n\tsetVisible: function (vis, redraw) {\n\t\tvar series = this,\n\t\t\tchart = series.chart,\n\t\t\tlegendItem = series.legendItem,\n\t\t\tshowOrHide,\n\t\t\tignoreHiddenSeries = chart.options.chart.ignoreHiddenSeries,\n\t\t\toldVisibility = series.visible;\n\n\t\t// if called without an argument, toggle visibility\n\t\tseries.visible = vis = series.userOptions.visible = vis === UNDEFINED ? !oldVisibility : vis;\n\t\tshowOrHide = vis ? 'show' : 'hide';\n\n\t\t// show or hide elements\n\t\teach(['group', 'dataLabelsGroup', 'markerGroup', 'tracker'], function (key) {\n\t\t\tif (series[key]) {\n\t\t\t\tseries[key][showOrHide]();\n\t\t\t}\n\t\t});\n\n\t\t\n\t\t// hide tooltip (#1361)\n\t\tif (chart.hoverSeries === series) {\n\t\t\tseries.onMouseOut();\n\t\t}\n\n\n\t\tif (legendItem) {\n\t\t\tchart.legend.colorizeItem(series, vis);\n\t\t}\n\n\n\t\t// rescale or adapt to resized chart\n\t\tseries.isDirty = true;\n\t\t// in a stack, all other series are affected\n\t\tif (series.options.stacking) {\n\t\t\teach(chart.series, function (otherSeries) {\n\t\t\t\tif (otherSeries.options.stacking && otherSeries.visible) {\n\t\t\t\t\totherSeries.isDirty = true;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\t// show or hide linked series\n\t\teach(series.linkedSeries, function (otherSeries) {\n\t\t\totherSeries.setVisible(vis, false);\n\t\t});\n\n\t\tif (ignoreHiddenSeries) {\n\t\t\tchart.isDirtyBox = true;\n\t\t}\n\t\tif (redraw !== false) {\n\t\t\tchart.redraw();\n\t\t}\n\n\t\tfireEvent(series, showOrHide);\n\t},\n\n\t/**\n\t * Show the graph\n\t */\n\tshow: function () {\n\t\tthis.setVisible(true);\n\t},\n\n\t/**\n\t * Hide the graph\n\t */\n\thide: function () {\n\t\tthis.setVisible(false);\n\t},\n\n\n\t/**\n\t * Set the selected state of the graph\n\t *\n\t * @param selected {Boolean} True to select the series, false to unselect. If\n\t *        UNDEFINED, the selection state is toggled.\n\t */\n\tselect: function (selected) {\n\t\tvar series = this;\n\t\t// if called without an argument, toggle\n\t\tseries.selected = selected = (selected === UNDEFINED) ? !series.selected : selected;\n\n\t\tif (series.checkbox) {\n\t\t\tseries.checkbox.checked = selected;\n\t\t}\n\n\t\tfireEvent(series, selected ? 'select' : 'unselect');\n\t},\n\n\t/**\n\t * Draw the tracker object that sits above all data labels and markers to\n\t * track mouse events on the graph or points. For the line type charts\n\t * the tracker uses the same graphPath, but with a greater stroke width\n\t * for better control.\n\t */\n\tdrawTracker: function () {\n\t\tvar series = this,\n\t\t\toptions = series.options,\n\t\t\ttrackByArea = options.trackByArea,\n\t\t\ttrackerPath = [].concat(trackByArea ? series.areaPath : series.graphPath),\n\t\t\ttrackerPathLength = trackerPath.length,\n\t\t\tchart = series.chart,\n\t\t\tpointer = chart.pointer,\n\t\t\trenderer = chart.renderer,\n\t\t\tsnap = chart.options.tooltip.snap,\n\t\t\ttracker = series.tracker,\n\t\t\tcursor = options.cursor,\n\t\t\tcss = cursor && { cursor: cursor },\n\t\t\tsinglePoints = series.singlePoints,\n\t\t\tsinglePoint,\n\t\t\ti,\n\t\t\tonMouseOver = function () {\n\t\t\t\tif (chart.hoverSeries !== series) {\n\t\t\t\t\tseries.onMouseOver();\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Extend end points. A better way would be to use round linecaps,\n\t\t// but those are not clickable in VML.\n\t\tif (trackerPathLength && !trackByArea) {\n\t\t\ti = trackerPathLength + 1;\n\t\t\twhile (i--) {\n\t\t\t\tif (trackerPath[i] === M) { // extend left side\n\t\t\t\t\ttrackerPath.splice(i + 1, 0, trackerPath[i + 1] - snap, trackerPath[i + 2], L);\n\t\t\t\t}\n\t\t\t\tif ((i && trackerPath[i] === M) || i === trackerPathLength) { // extend right side\n\t\t\t\t\ttrackerPath.splice(i, 0, L, trackerPath[i - 2] + snap, trackerPath[i - 1]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// handle single points\n\t\tfor (i = 0; i < singlePoints.length; i++) {\n\t\t\tsinglePoint = singlePoints[i];\n\t\t\ttrackerPath.push(M, singlePoint.plotX - snap, singlePoint.plotY,\n\t\t\t\tL, singlePoint.plotX + snap, singlePoint.plotY);\n\t\t}\n\t\t\n\t\t\n\n\t\t// draw the tracker\n\t\tif (tracker) {\n\t\t\ttracker.attr({ d: trackerPath });\n\n\t\t} else { // create\n\t\t\t\t\n\t\t\tseries.tracker = tracker = renderer.path(trackerPath)\n\t\t\t\t.attr({\n\t\t\t\t\t'class': PREFIX + 'tracker',\n\t\t\t\t\t'stroke-linejoin': 'round', // #1225\n\t\t\t\t\tvisibility: series.visible ? VISIBLE : HIDDEN,\n\t\t\t\t\tstroke: TRACKER_FILL,\n\t\t\t\t\tfill: trackByArea ? TRACKER_FILL : NONE,\n\t\t\t\t\t'stroke-width' : options.lineWidth + (trackByArea ? 0 : 2 * snap),\n\t\t\t\t\tzIndex: 2\n\t\t\t\t})\n\t\t\t\t.addClass(PREFIX + 'tracker')\n\t\t\t\t.on('mouseover', onMouseOver)\n\t\t\t\t.on('mouseout', function (e) { pointer.onTrackerMouseOut(e); })\n\t\t\t\t.css(css)\n\t\t\t\t.add(series.markerGroup);\n\t\t\t\t\n\t\t\tif (hasTouch) {\n\t\t\t\ttracker.on('touchstart', onMouseOver);\n\t\t\t} \n\t\t}\n\n\t}\n\n}; // end Series prototype\n\n\n/**\n * LineSeries object\n */\nvar LineSeries = extendClass(Series);\nseriesTypes.line = LineSeries;\n\n/**\n * Set the default options for area\n */\ndefaultPlotOptions.area = merge(defaultSeriesOptions, {\n\tthreshold: 0\n\t// trackByArea: false,\n\t// lineColor: null, // overrides color, but lets fillColor be unaltered\n\t// fillOpacity: 0.75,\n\t// fillColor: null\n});\n\n/**\n * AreaSeries object\n */\nvar AreaSeries = extendClass(Series, {\n\ttype: 'area',\n\t\n\t/**\n\t * For stacks, don't split segments on null values. Instead, draw null values with \n\t * no marker. Also insert dummy points for any X position that exists in other series\n\t * in the stack.\n\t */ \n\tgetSegments: function () {\n\t\tvar segments = [],\n\t\t\tsegment = [],\n\t\t\tkeys = [],\n\t\t\txAxis = this.xAxis,\n\t\t\tyAxis = this.yAxis,\n\t\t\tstack = yAxis.stacks[this.stackKey],\n\t\t\tpointMap = {},\n\t\t\tplotX,\n\t\t\tplotY,\n\t\t\tpoints = this.points,\n\t\t\tval,\n\t\t\ti,\n\t\t\tx;\n\n\t\tif (this.options.stacking && !this.cropped) { // cropped causes artefacts in Stock, and perf issue\n\t\t\t// Create a map where we can quickly look up the points by their X value.\n\t\t\tfor (i = 0; i < points.length; i++) {\n\t\t\t\tpointMap[points[i].x] = points[i];\n\t\t\t}\n\n\t\t\t// Sort the keys (#1651)\n\t\t\tfor (x in stack) {\n\t\t\t\tkeys.push(+x);\n\t\t\t}\n\t\t\tkeys.sort(function (a, b) {\n\t\t\t\treturn a - b;\n\t\t\t});\n\n\t\t\teach(keys, function (x) {\n\t\t\t\t// The point exists, push it to the segment\n\t\t\t\tif (pointMap[x]) {\n\t\t\t\t\tsegment.push(pointMap[x]);\n\n\t\t\t\t// There is no point for this X value in this series, so we \n\t\t\t\t// insert a dummy point in order for the areas to be drawn\n\t\t\t\t// correctly.\n\t\t\t\t} else {\n\t\t\t\t\tplotX = xAxis.translate(x);\n\t\t\t\t\tval = stack[x].percent ? (stack[x].total ? stack[x].cum * 100 / stack[x].total : 0) : stack[x].cum; // #1991\n\t\t\t\t\tplotY = yAxis.toPixels(val, true);\n\t\t\t\t\tsegment.push({ \n\t\t\t\t\t\ty: null, \n\t\t\t\t\t\tplotX: plotX,\n\t\t\t\t\t\tclientX: plotX, \n\t\t\t\t\t\tplotY: plotY, \n\t\t\t\t\t\tyBottom: plotY,\n\t\t\t\t\t\tonMouseOver: noop\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tif (segment.length) {\n\t\t\t\tsegments.push(segment);\n\t\t\t}\n\n\t\t} else {\n\t\t\tSeries.prototype.getSegments.call(this);\n\t\t\tsegments = this.segments;\n\t\t}\n\n\t\tthis.segments = segments;\n\t},\n\t\n\t/**\n\t * Extend the base Series getSegmentPath method by adding the path for the area.\n\t * This path is pushed to the series.areaPath property.\n\t */\n\tgetSegmentPath: function (segment) {\n\t\t\n\t\tvar segmentPath = Series.prototype.getSegmentPath.call(this, segment), // call base method\n\t\t\tareaSegmentPath = [].concat(segmentPath), // work on a copy for the area path\n\t\t\ti,\n\t\t\toptions = this.options,\n\t\t\tsegLength = segmentPath.length;\n\t\t\n\t\tif (segLength === 3) { // for animation from 1 to two points\n\t\t\tareaSegmentPath.push(L, segmentPath[1], segmentPath[2]);\n\t\t}\n\t\tif (options.stacking && !this.closedStacks) {\n\t\t\t\n\t\t\t// Follow stack back. Todo: implement areaspline. A general solution could be to \n\t\t\t// reverse the entire graphPath of the previous series, though may be hard with\n\t\t\t// splines and with series with different extremes\n\t\t\tfor (i = segment.length - 1; i >= 0; i--) {\n\t\t\t\n\t\t\t\t// step line?\n\t\t\t\tif (i < segment.length - 1 && options.step) {\n\t\t\t\t\tareaSegmentPath.push(segment[i + 1].plotX, segment[i].yBottom);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tareaSegmentPath.push(segment[i].plotX, segment[i].yBottom);\n\t\t\t}\n\n\t\t} else { // follow zero line back\n\t\t\tthis.closeSegment(areaSegmentPath, segment);\n\t\t}\n\t\tthis.areaPath = this.areaPath.concat(areaSegmentPath);\n\t\t\n\t\treturn segmentPath;\n\t},\n\t\n\t/**\n\t * Extendable method to close the segment path of an area. This is overridden in polar \n\t * charts.\n\t */\n\tcloseSegment: function (path, segment) {\n\t\tvar translatedThreshold = this.yAxis.getThreshold(this.options.threshold);\n\t\tpath.push(\n\t\t\tL,\n\t\t\tsegment[segment.length - 1].plotX,\n\t\t\ttranslatedThreshold,\n\t\t\tL,\n\t\t\tsegment[0].plotX,\n\t\t\ttranslatedThreshold\n\t\t);\n\t},\n\t\n\t/**\n\t * Draw the graph and the underlying area. This method calls the Series base\n\t * function and adds the area. The areaPath is calculated in the getSegmentPath\n\t * method called from Series.prototype.drawGraph.\n\t */\n\tdrawGraph: function () {\n\t\t\n\t\t// Define or reset areaPath\n\t\tthis.areaPath = [];\n\t\t\n\t\t// Call the base method\n\t\tSeries.prototype.drawGraph.apply(this);\n\t\t\n\t\t// Define local variables\n\t\tvar series = this,\n\t\t\tareaPath = this.areaPath,\n\t\t\toptions = this.options,\n\t\t\tnegativeColor = options.negativeColor,\n\t\t\tnegativeFillColor = options.negativeFillColor,\n\t\t\tprops = [['area', this.color, options.fillColor]]; // area name, main color, fill color\n\t\t\n\t\tif (negativeColor || negativeFillColor) {\n\t\t\tprops.push(['areaNeg', negativeColor, negativeFillColor]);\n\t\t}\n\t\t\n\t\teach(props, function (prop) {\n\t\t\tvar areaKey = prop[0],\n\t\t\t\tarea = series[areaKey];\n\t\t\t\t\n\t\t\t// Create or update the area\n\t\t\tif (area) { // update\n\t\t\t\tarea.animate({ d: areaPath });\n\t\n\t\t\t} else { // create\n\t\t\t\tseries[areaKey] = series.chart.renderer.path(areaPath)\n\t\t\t\t\t.attr({\n\t\t\t\t\t\tfill: pick(\n\t\t\t\t\t\t\tprop[2],\n\t\t\t\t\t\t\tColor(prop[1]).setOpacity(pick(options.fillOpacity, 0.75)).get()\n\t\t\t\t\t\t),\n\t\t\t\t\t\tzIndex: 0 // #1069\n\t\t\t\t\t}).add(series.group);\n\t\t\t}\n\t\t});\n\t},\n\t\n\t/**\n\t * Get the series' symbol in the legend\n\t * \n\t * @param {Object} legend The legend object\n\t * @param {Object} item The series (this) or point\n\t */\n\tdrawLegendSymbol: function (legend, item) {\n\t\t\n\t\titem.legendSymbol = this.chart.renderer.rect(\n\t\t\t0,\n\t\t\tlegend.baseline - 11,\n\t\t\tlegend.options.symbolWidth,\n\t\t\t12,\n\t\t\t2\n\t\t).attr({\n\t\t\tzIndex: 3\n\t\t}).add(item.legendGroup);\t\t\n\t\t\n\t}\n});\n\nseriesTypes.area = AreaSeries;/**\n * Set the default options for spline\n */\ndefaultPlotOptions.spline = merge(defaultSeriesOptions);\n\n/**\n * SplineSeries object\n */\nvar SplineSeries = extendClass(Series, {\n\ttype: 'spline',\n\n\t/**\n\t * Get the spline segment from a given point's previous neighbour to the given point\n\t */\n\tgetPointSpline: function (segment, point, i) {\n\t\tvar smoothing = 1.5, // 1 means control points midway between points, 2 means 1/3 from the point, 3 is 1/4 etc\n\t\t\tdenom = smoothing + 1,\n\t\t\tplotX = point.plotX,\n\t\t\tplotY = point.plotY,\n\t\t\tlastPoint = segment[i - 1],\n\t\t\tnextPoint = segment[i + 1],\n\t\t\tleftContX,\n\t\t\tleftContY,\n\t\t\trightContX,\n\t\t\trightContY,\n\t\t\tret;\n\n\t\t// find control points\n\t\tif (lastPoint && nextPoint) {\n\t\t\n\t\t\tvar lastX = lastPoint.plotX,\n\t\t\t\tlastY = lastPoint.plotY,\n\t\t\t\tnextX = nextPoint.plotX,\n\t\t\t\tnextY = nextPoint.plotY,\n\t\t\t\tcorrection;\n\n\t\t\tleftContX = (smoothing * plotX + lastX) / denom;\n\t\t\tleftContY = (smoothing * plotY + lastY) / denom;\n\t\t\trightContX = (smoothing * plotX + nextX) / denom;\n\t\t\trightContY = (smoothing * plotY + nextY) / denom;\n\n\t\t\t// have the two control points make a straight line through main point\n\t\t\tcorrection = ((rightContY - leftContY) * (rightContX - plotX)) /\n\t\t\t\t(rightContX - leftContX) + plotY - rightContY;\n\n\t\t\tleftContY += correction;\n\t\t\trightContY += correction;\n\n\t\t\t// to prevent false extremes, check that control points are between\n\t\t\t// neighbouring points' y values\n\t\t\tif (leftContY > lastY && leftContY > plotY) {\n\t\t\t\tleftContY = mathMax(lastY, plotY);\n\t\t\t\trightContY = 2 * plotY - leftContY; // mirror of left control point\n\t\t\t} else if (leftContY < lastY && leftContY < plotY) {\n\t\t\t\tleftContY = mathMin(lastY, plotY);\n\t\t\t\trightContY = 2 * plotY - leftContY;\n\t\t\t}\n\t\t\tif (rightContY > nextY && rightContY > plotY) {\n\t\t\t\trightContY = mathMax(nextY, plotY);\n\t\t\t\tleftContY = 2 * plotY - rightContY;\n\t\t\t} else if (rightContY < nextY && rightContY < plotY) {\n\t\t\t\trightContY = mathMin(nextY, plotY);\n\t\t\t\tleftContY = 2 * plotY - rightContY;\n\t\t\t}\n\n\t\t\t// record for drawing in next point\n\t\t\tpoint.rightContX = rightContX;\n\t\t\tpoint.rightContY = rightContY;\n\n\t\t}\n\t\t\n\t\t// Visualize control points for debugging\n\t\t/*\n\t\tif (leftContX) {\n\t\t\tthis.chart.renderer.circle(leftContX + this.chart.plotLeft, leftContY + this.chart.plotTop, 2)\n\t\t\t\t.attr({\n\t\t\t\t\tstroke: 'red',\n\t\t\t\t\t'stroke-width': 1,\n\t\t\t\t\tfill: 'none'\n\t\t\t\t})\n\t\t\t\t.add();\n\t\t\tthis.chart.renderer.path(['M', leftContX + this.chart.plotLeft, leftContY + this.chart.plotTop,\n\t\t\t\t'L', plotX + this.chart.plotLeft, plotY + this.chart.plotTop])\n\t\t\t\t.attr({\n\t\t\t\t\tstroke: 'red',\n\t\t\t\t\t'stroke-width': 1\n\t\t\t\t})\n\t\t\t\t.add();\n\t\t\tthis.chart.renderer.circle(rightContX + this.chart.plotLeft, rightContY + this.chart.plotTop, 2)\n\t\t\t\t.attr({\n\t\t\t\t\tstroke: 'green',\n\t\t\t\t\t'stroke-width': 1,\n\t\t\t\t\tfill: 'none'\n\t\t\t\t})\n\t\t\t\t.add();\n\t\t\tthis.chart.renderer.path(['M', rightContX + this.chart.plotLeft, rightContY + this.chart.plotTop,\n\t\t\t\t'L', plotX + this.chart.plotLeft, plotY + this.chart.plotTop])\n\t\t\t\t.attr({\n\t\t\t\t\tstroke: 'green',\n\t\t\t\t\t'stroke-width': 1\n\t\t\t\t})\n\t\t\t\t.add();\n\t\t}\n\t\t*/\n\n\t\t// moveTo or lineTo\n\t\tif (!i) {\n\t\t\tret = [M, plotX, plotY];\n\t\t} else { // curve from last point to this\n\t\t\tret = [\n\t\t\t\t'C',\n\t\t\t\tlastPoint.rightContX || lastPoint.plotX,\n\t\t\t\tlastPoint.rightContY || lastPoint.plotY,\n\t\t\t\tleftContX || plotX,\n\t\t\t\tleftContY || plotY,\n\t\t\t\tplotX,\n\t\t\t\tplotY\n\t\t\t];\n\t\t\tlastPoint.rightContX = lastPoint.rightContY = null; // reset for updating series later\n\t\t}\n\t\treturn ret;\n\t}\n});\nseriesTypes.spline = SplineSeries;\n\n/**\n * Set the default options for areaspline\n */\ndefaultPlotOptions.areaspline = merge(defaultPlotOptions.area);\n\n/**\n * AreaSplineSeries object\n */\nvar areaProto = AreaSeries.prototype,\n\tAreaSplineSeries = extendClass(SplineSeries, {\n\t\ttype: 'areaspline',\n\t\tclosedStacks: true, // instead of following the previous graph back, follow the threshold back\n\t\t\n\t\t// Mix in methods from the area series\n\t\tgetSegmentPath: areaProto.getSegmentPath,\n\t\tcloseSegment: areaProto.closeSegment,\n\t\tdrawGraph: areaProto.drawGraph,\n\t\tdrawLegendSymbol: areaProto.drawLegendSymbol\n\t});\nseriesTypes.areaspline = AreaSplineSeries;\n\n/**\n * Set the default options for column\n */\ndefaultPlotOptions.column = merge(defaultSeriesOptions, {\n\tborderColor: '#FFFFFF',\n\tborderWidth: 1,\n\tborderRadius: 0,\n\t//colorByPoint: undefined,\n\tgroupPadding: 0.2,\n\t//grouping: true,\n\tmarker: null, // point options are specified in the base options\n\tpointPadding: 0.1,\n\t//pointWidth: null,\n\tminPointLength: 0,\n\tcropThreshold: 50, // when there are more points, they will not animate out of the chart on xAxis.setExtremes\n\tpointRange: null, // null means auto, meaning 1 in a categorized axis and least distance between points if not categories\n\tstates: {\n\t\thover: {\n\t\t\tbrightness: 0.1,\n\t\t\tshadow: false\n\t\t},\n\t\tselect: {\n\t\t\tcolor: '#C0C0C0',\n\t\t\tborderColor: '#000000',\n\t\t\tshadow: false\n\t\t}\n\t},\n\tdataLabels: {\n\t\talign: null, // auto\n\t\tverticalAlign: null, // auto\n\t\ty: null\n\t},\n\tstickyTracking: false,\n\tthreshold: 0\n});\n\n/**\n * ColumnSeries object\n */\nvar ColumnSeries = extendClass(Series, {\n\ttype: 'column',\n\ttooltipOutsidePlot: true,\n\tpointAttrToOptions: { // mapping between SVG attributes and the corresponding options\n\t\tstroke: 'borderColor',\n\t\t'stroke-width': 'borderWidth',\n\t\tfill: 'color',\n\t\tr: 'borderRadius'\n\t},\n\ttrackerGroups: ['group', 'dataLabelsGroup'],\n\t\n\t/**\n\t * Initialize the series\n\t */\n\tinit: function () {\n\t\tSeries.prototype.init.apply(this, arguments);\n\n\t\tvar series = this,\n\t\t\tchart = series.chart;\n\n\t\t// if the series is added dynamically, force redraw of other\n\t\t// series affected by a new column\n\t\tif (chart.hasRendered) {\n\t\t\teach(chart.series, function (otherSeries) {\n\t\t\t\tif (otherSeries.type === series.type) {\n\t\t\t\t\totherSeries.isDirty = true;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t},\n\n\t/**\n\t * Return the width and x offset of the columns adjusted for grouping, groupPadding, pointPadding,\n\t * pointWidth etc. \n\t */\n\tgetColumnMetrics: function () {\n\n\t\tvar series = this,\n\t\t\toptions = series.options,\n\t\t\txAxis = this.xAxis,\n\t\t\treversedXAxis = xAxis.reversed,\n\t\t\tstackKey,\n\t\t\tstackGroups = {},\n\t\t\tcolumnIndex,\n\t\t\tcolumnCount = 0;\n\n\t\t// Get the total number of column type series.\n\t\t// This is called on every series. Consider moving this logic to a\n\t\t// chart.orderStacks() function and call it on init, addSeries and removeSeries\n\t\tif (options.grouping === false) {\n\t\t\tcolumnCount = 1;\n\t\t} else {\n\t\t\teach(series.yAxis.series, function (otherSeries) { // use Y axes separately, #642\n\t\t\t\tvar otherOptions = otherSeries.options;\n\t\t\t\tif (otherSeries.type === series.type && otherSeries.visible &&\n\t\t\t\t\t\tseries.options.group === otherOptions.group) { // used in Stock charts navigator series\n\t\t\t\t\tif (otherOptions.stacking) {\n\t\t\t\t\t\tstackKey = otherSeries.stackKey;\n\t\t\t\t\t\tif (stackGroups[stackKey] === UNDEFINED) {\n\t\t\t\t\t\t\tstackGroups[stackKey] = columnCount++;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcolumnIndex = stackGroups[stackKey];\n\t\t\t\t\t} else if (otherOptions.grouping !== false) { // #1162\n\t\t\t\t\t\tcolumnIndex = columnCount++;\n\t\t\t\t\t}\n\t\t\t\t\totherSeries.columnIndex = columnIndex;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tvar categoryWidth = mathMin(\n\t\t\t\tmathAbs(xAxis.transA) * (xAxis.ordinalSlope || options.pointRange || xAxis.closestPointRange || 1), \n\t\t\t\txAxis.len // #1535\n\t\t\t),\n\t\t\tgroupPadding = categoryWidth * options.groupPadding,\n\t\t\tgroupWidth = categoryWidth - 2 * groupPadding,\n\t\t\tpointOffsetWidth = groupWidth / columnCount,\n\t\t\toptionPointWidth = options.pointWidth,\n\t\t\tpointPadding = defined(optionPointWidth) ? (pointOffsetWidth - optionPointWidth) / 2 :\n\t\t\t\tpointOffsetWidth * options.pointPadding,\n\t\t\tpointWidth = pick(optionPointWidth, pointOffsetWidth - 2 * pointPadding), // exact point width, used in polar charts\n\t\t\tcolIndex = (reversedXAxis ? \n\t\t\t\tcolumnCount - (series.columnIndex || 0) : // #1251\n\t\t\t\tseries.columnIndex) || 0,\n\t\t\tpointXOffset = pointPadding + (groupPadding + colIndex *\n\t\t\t\tpointOffsetWidth - (categoryWidth / 2)) *\n\t\t\t\t(reversedXAxis ? -1 : 1);\n\n\t\t// Save it for reading in linked series (Error bars particularly)\n\t\treturn (series.columnMetrics = { \n\t\t\twidth: pointWidth, \n\t\t\toffset: pointXOffset \n\t\t});\n\t\t\t\n\t},\n\n\t/**\n\t * Translate each point to the plot area coordinate system and find shape positions\n\t */\n\ttranslate: function () {\n\t\tvar series = this,\n\t\t\tchart = series.chart,\n\t\t\toptions = series.options,\n\t\t\tborderWidth = options.borderWidth,\n\t\t\tyAxis = series.yAxis,\n\t\t\tthreshold = options.threshold,\n\t\t\ttranslatedThreshold = series.translatedThreshold = yAxis.getThreshold(threshold),\n\t\t\tminPointLength = pick(options.minPointLength, 5),\n\t\t\tmetrics = series.getColumnMetrics(),\n\t\t\tpointWidth = metrics.width,\n\t\t\tbarW = series.barW = mathCeil(mathMax(pointWidth, 1 + 2 * borderWidth)), // rounded and postprocessed for border width\n\t\t\tpointXOffset = series.pointXOffset = metrics.offset;\n\n\t\tSeries.prototype.translate.apply(series);\n\n\t\t// record the new values\n\t\teach(series.points, function (point) {\n\t\t\tvar plotY = mathMin(mathMax(-999, point.plotY), yAxis.len + 999), // Don't draw too far outside plot area (#1303)\n\t\t\t\tyBottom = pick(point.yBottom, translatedThreshold),\n\t\t\t\tbarX = point.plotX + pointXOffset,\n\t\t\t\tbarY = mathCeil(mathMin(plotY, yBottom)),\n\t\t\t\tbarH = mathCeil(mathMax(plotY, yBottom) - barY),\n\t\t\t\tshapeArgs;\n\n\t\t\t// handle options.minPointLength\n\t\t\tif (mathAbs(barH) < minPointLength) {\n\t\t\t\tif (minPointLength) {\n\t\t\t\t\tbarH = minPointLength;\n\t\t\t\t\tbarY =\n\t\t\t\t\t\tmathRound(mathAbs(barY - translatedThreshold) > minPointLength ? // stacked\n\t\t\t\t\t\t\tyBottom - minPointLength : // keep position\n\t\t\t\t\t\t\ttranslatedThreshold - (yAxis.translate(point.y, 0, 1, 0, 1) <= translatedThreshold ? minPointLength : 0)); // use exact yAxis.translation (#1485)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tpoint.barX = barX;\n\t\t\tpoint.pointWidth = pointWidth;\n\n\t\t\t// create shape type and shape args that are reused in drawPoints and drawTracker\n\t\t\tpoint.shapeType = 'rect';\n\t\t\tpoint.shapeArgs = shapeArgs = chart.renderer.Element.prototype.crisp.call(0, borderWidth, barX, barY, barW, barH); \n\t\t\t\n\t\t\tif (borderWidth % 2) { // correct for shorting in crisp method, visible in stacked columns with 1px border\n\t\t\t\tshapeArgs.y -= 1;\n\t\t\t\tshapeArgs.height += 1;\n\t\t\t}\n\n\t\t});\n\n\t},\n\n\tgetSymbol: noop,\n\t\n\t/**\n\t * Use a solid rectangle like the area series types\n\t */\n\tdrawLegendSymbol: AreaSeries.prototype.drawLegendSymbol,\n\t\n\t\n\t/**\n\t * Columns have no graph\n\t */\n\tdrawGraph: noop,\n\n\t/**\n\t * Draw the columns. For bars, the series.group is rotated, so the same coordinates\n\t * apply for columns and bars. This method is inherited by scatter series.\n\t *\n\t */\n\tdrawPoints: function () {\n\t\tvar series = this,\n\t\t\toptions = series.options,\n\t\t\trenderer = series.chart.renderer,\n\t\t\tshapeArgs;\n\n\n\t\t// draw the columns\n\t\teach(series.points, function (point) {\n\t\t\tvar plotY = point.plotY,\n\t\t\t\tgraphic = point.graphic;\n\n\t\t\tif (plotY !== UNDEFINED && !isNaN(plotY) && point.y !== null) {\n\t\t\t\tshapeArgs = point.shapeArgs;\n\t\t\t\t\n\t\t\t\tif (graphic) { // update\n\t\t\t\t\tstop(graphic);\n\t\t\t\t\tgraphic.animate(merge(shapeArgs));\n\n\t\t\t\t} else {\n\t\t\t\t\tpoint.graphic = graphic = renderer[point.shapeType](shapeArgs)\n\t\t\t\t\t\t.attr(point.pointAttr[point.selected ? SELECT_STATE : NORMAL_STATE])\n\t\t\t\t\t\t.add(series.group)\n\t\t\t\t\t\t.shadow(options.shadow, null, options.stacking && !options.borderRadius);\n\t\t\t\t}\n\n\t\t\t} else if (graphic) {\n\t\t\t\tpoint.graphic = graphic.destroy(); // #1269\n\t\t\t}\n\t\t});\n\t},\n\n\t/**\n\t * Add tracking event listener to the series group, so the point graphics\n\t * themselves act as trackers\n\t */\n\tdrawTracker: function () {\n\t\tvar series = this,\n\t\t\tchart = series.chart,\n\t\t\tpointer = chart.pointer,\n\t\t\tcursor = series.options.cursor,\n\t\t\tcss = cursor && { cursor: cursor },\n\t\t\tonMouseOver = function (e) {\n\t\t\t\tvar target = e.target,\n\t\t\t\t\tpoint;\n\n\t\t\t\tif (chart.hoverSeries !== series) {\n\t\t\t\t\tseries.onMouseOver();\n\t\t\t\t}\n\t\t\t\twhile (target && !point) {\n\t\t\t\t\tpoint = target.point;\n\t\t\t\t\ttarget = target.parentNode;\n\t\t\t\t}\n\t\t\t\tif (point !== UNDEFINED && point !== chart.hoverPoint) { // undefined on graph in scatterchart\n\t\t\t\t\tpoint.onMouseOver(e);\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Add reference to the point\n\t\teach(series.points, function (point) {\n\t\t\tif (point.graphic) {\n\t\t\t\tpoint.graphic.element.point = point;\n\t\t\t}\n\t\t\tif (point.dataLabel) {\n\t\t\t\tpoint.dataLabel.element.point = point;\n\t\t\t}\n\t\t});\n\n\t\t// Add the event listeners, we need to do this only once\n\t\tif (!series._hasTracking) {\n\t\t\teach(series.trackerGroups, function (key) {\n\t\t\t\tif (series[key]) { // we don't always have dataLabelsGroup\n\t\t\t\t\tseries[key]\n\t\t\t\t\t\t.addClass(PREFIX + 'tracker')\n\t\t\t\t\t\t.on('mouseover', onMouseOver)\n\t\t\t\t\t\t.on('mouseout', function (e) { pointer.onTrackerMouseOut(e); })\n\t\t\t\t\t\t.css(css);\n\t\t\t\t\tif (hasTouch) {\n\t\t\t\t\t\tseries[key].on('touchstart', onMouseOver);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t} else {\n\t\t\tseries._hasTracking = true;\n\t\t}\n\t},\n\t\n\t/** \n\t * Override the basic data label alignment by adjusting for the position of the column\n\t */\n\talignDataLabel: function (point, dataLabel, options,  alignTo, isNew) {\n\t\tvar chart = this.chart,\n\t\t\tinverted = chart.inverted,\n\t\t\tdlBox = point.dlBox || point.shapeArgs, // data label box for alignment\n\t\t\tbelow = point.below || (point.plotY > pick(this.translatedThreshold, chart.plotSizeY)),\n\t\t\tinside = pick(options.inside, !!this.options.stacking); // draw it inside the box?\n\t\t\n\t\t// Align to the column itself, or the top of it\n\t\tif (dlBox) { // Area range uses this method but not alignTo\n\t\t\talignTo = merge(dlBox);\n\t\t\tif (inverted) {\n\t\t\t\talignTo = {\n\t\t\t\t\tx: chart.plotWidth - alignTo.y - alignTo.height,\n\t\t\t\t\ty: chart.plotHeight - alignTo.x - alignTo.width,\n\t\t\t\t\twidth: alignTo.height,\n\t\t\t\t\theight: alignTo.width\n\t\t\t\t};\n\t\t\t}\n\t\t\t\t\n\t\t\t// Compute the alignment box\n\t\t\tif (!inside) {\n\t\t\t\tif (inverted) {\n\t\t\t\t\talignTo.x += below ? 0 : alignTo.width;\n\t\t\t\t\talignTo.width = 0;\n\t\t\t\t} else {\n\t\t\t\t\talignTo.y += below ? alignTo.height : 0;\n\t\t\t\t\talignTo.height = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\t// When alignment is undefined (typically columns and bars), display the individual \n\t\t// point below or above the point depending on the threshold\n\t\toptions.align = pick(\n\t\t\toptions.align, \n\t\t\t!inverted || inside ? 'center' : below ? 'right' : 'left'\n\t\t);\n\t\toptions.verticalAlign = pick(\n\t\t\toptions.verticalAlign, \n\t\t\tinverted || inside ? 'middle' : below ? 'top' : 'bottom'\n\t\t);\n\t\t\n\t\t// Call the parent method\n\t\tSeries.prototype.alignDataLabel.call(this, point, dataLabel, options, alignTo, isNew);\n\t},\n\n\n\t/**\n\t * Animate the column heights one by one from zero\n\t * @param {Boolean} init Whether to initialize the animation or run it\n\t */\n\tanimate: function (init) {\n\t\tvar series = this,\n\t\t\tyAxis = this.yAxis,\n\t\t\toptions = series.options,\n\t\t\tinverted = this.chart.inverted,\n\t\t\tattr = {},\n\t\t\ttranslatedThreshold;\n\n\t\tif (hasSVG) { // VML is too slow anyway\n\t\t\tif (init) {\n\t\t\t\tattr.scaleY = 0.001;\n\t\t\t\ttranslatedThreshold = mathMin(yAxis.pos + yAxis.len, mathMax(yAxis.pos, yAxis.toPixels(options.threshold)));\n\t\t\t\tif (inverted) {\n\t\t\t\t\tattr.translateX = translatedThreshold - yAxis.len;\n\t\t\t\t} else {\n\t\t\t\t\tattr.translateY = translatedThreshold;\n\t\t\t\t}\n\t\t\t\tseries.group.attr(attr);\n\n\t\t\t} else { // run the animation\n\t\t\t\t\n\t\t\t\tattr.scaleY = 1;\n\t\t\t\tattr[inverted ? 'translateX' : 'translateY'] = yAxis.pos;\n\t\t\t\tseries.group.animate(attr, series.options.animation);\n\n\t\t\t\t// delete this function to allow it only once\n\t\t\t\tseries.animate = null;\n\t\t\t}\n\t\t}\n\t},\n\t\n\t/**\n\t * Remove this series from the chart\n\t */\n\tremove: function () {\n\t\tvar series = this,\n\t\t\tchart = series.chart;\n\n\t\t// column and bar series affects other series of the same type\n\t\t// as they are either stacked or grouped\n\t\tif (chart.hasRendered) {\n\t\t\teach(chart.series, function (otherSeries) {\n\t\t\t\tif (otherSeries.type === series.type) {\n\t\t\t\t\totherSeries.isDirty = true;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tSeries.prototype.remove.apply(series, arguments);\n\t}\n});\nseriesTypes.column = ColumnSeries;\n/**\n * Set the default options for bar\n */\ndefaultPlotOptions.bar = merge(defaultPlotOptions.column);\n/**\n * The Bar series class\n */\nvar BarSeries = extendClass(ColumnSeries, {\n\ttype: 'bar',\n\tinverted: true\n});\nseriesTypes.bar = BarSeries;\n\n/**\n * Set the default options for scatter\n */\ndefaultPlotOptions.scatter = merge(defaultSeriesOptions, {\n\tlineWidth: 0,\n\ttooltip: {\n\t\theaderFormat: '<span style=\"font-size: 10px; color:{series.color}\">{series.name}</span><br/>',\n\t\tpointFormat: 'x: <b>{point.x}</b><br/>y: <b>{point.y}</b><br/>',\n\t\tfollowPointer: true\n\t},\n\tstickyTracking: false\n});\n\n/**\n * The scatter series class\n */\nvar ScatterSeries = extendClass(Series, {\n\ttype: 'scatter',\n\tsorted: false,\n\trequireSorting: false,\n\tnoSharedTooltip: true,\n\ttrackerGroups: ['markerGroup'],\n\n\tdrawTracker: ColumnSeries.prototype.drawTracker,\n\t\n\tsetTooltipPoints: noop\n});\nseriesTypes.scatter = ScatterSeries;\n\n/**\n * Set the default options for pie\n */\ndefaultPlotOptions.pie = merge(defaultSeriesOptions, {\n\tborderColor: '#FFFFFF',\n\tborderWidth: 1,\n\tcenter: [null, null],\n\tclip: false,\n\tcolorByPoint: true, // always true for pies\n\tdataLabels: {\n\t\t// align: null,\n\t\t// connectorWidth: 1,\n\t\t// connectorColor: point.color,\n\t\t// connectorPadding: 5,\n\t\tdistance: 30,\n\t\tenabled: true,\n\t\tformatter: function () {\n\t\t\treturn this.point.name;\n\t\t}\n\t\t// softConnector: true,\n\t\t//y: 0\n\t},\n\tignoreHiddenPoint: true,\n\t//innerSize: 0,\n\tlegendType: 'point',\n\tmarker: null, // point options are specified in the base options\n\tsize: null,\n\tshowInLegend: false,\n\tslicedOffset: 10,\n\tstates: {\n\t\thover: {\n\t\t\tbrightness: 0.1,\n\t\t\tshadow: false\n\t\t}\n\t},\n\tstickyTracking: false,\n\ttooltip: {\n\t\tfollowPointer: true\n\t}\n});\n\n/**\n * Extended point object for pies\n */\nvar PiePoint = extendClass(Point, {\n\t/**\n\t * Initiate the pie slice\n\t */\n\tinit: function () {\n\n\t\tPoint.prototype.init.apply(this, arguments);\n\n\t\tvar point = this,\n\t\t\ttoggleSlice;\n\n\t\t// Disallow negative values (#1530)\n\t\tif (point.y < 0) {\n\t\t\tpoint.y = null;\n\t\t}\n\n\t\t//visible: options.visible !== false,\n\t\textend(point, {\n\t\t\tvisible: point.visible !== false,\n\t\t\tname: pick(point.name, 'Slice')\n\t\t});\n\n\t\t// add event listener for select\n\t\ttoggleSlice = function (e) {\n\t\t\tpoint.slice(e.type === 'select');\n\t\t};\n\t\taddEvent(point, 'select', toggleSlice);\n\t\taddEvent(point, 'unselect', toggleSlice);\n\n\t\treturn point;\n\t},\n\n\t/**\n\t * Toggle the visibility of the pie slice\n\t * @param {Boolean} vis Whether to show the slice or not. If undefined, the\n\t *    visibility is toggled\n\t */\n\tsetVisible: function (vis) {\n\t\tvar point = this,\n\t\t\tseries = point.series,\n\t\t\tchart = series.chart,\n\t\t\tmethod;\n\n\t\t// if called without an argument, toggle visibility\n\t\tpoint.visible = point.options.visible = vis = vis === UNDEFINED ? !point.visible : vis;\n\t\tseries.options.data[inArray(point, series.data)] = point.options; // update userOptions.data\n\t\t\n\t\tmethod = vis ? 'show' : 'hide';\n\n\t\t// Show and hide associated elements\n\t\teach(['graphic', 'dataLabel', 'connector', 'shadowGroup'], function (key) {\n\t\t\tif (point[key]) {\n\t\t\t\tpoint[key][method]();\n\t\t\t}\n\t\t});\n\n\t\tif (point.legendItem) {\n\t\t\tchart.legend.colorizeItem(point, vis);\n\t\t}\n\t\t\n\t\t// Handle ignore hidden slices\n\t\tif (!series.isDirty && series.options.ignoreHiddenPoint) {\n\t\t\tseries.isDirty = true;\n\t\t\tchart.redraw();\n\t\t}\n\t},\n\n\t/**\n\t * Set or toggle whether the slice is cut out from the pie\n\t * @param {Boolean} sliced When undefined, the slice state is toggled\n\t * @param {Boolean} redraw Whether to redraw the chart. True by default.\n\t */\n\tslice: function (sliced, redraw, animation) {\n\t\tvar point = this,\n\t\t\tseries = point.series,\n\t\t\tchart = series.chart,\n\t\t\ttranslation;\n\n\t\tsetAnimation(animation, chart);\n\n\t\t// redraw is true by default\n\t\tredraw = pick(redraw, true);\n\n\t\t// if called without an argument, toggle\n\t\tpoint.sliced = point.options.sliced = sliced = defined(sliced) ? sliced : !point.sliced;\n\t\tseries.options.data[inArray(point, series.data)] = point.options; // update userOptions.data\n\n\t\ttranslation = sliced ? point.slicedTranslation : {\n\t\t\ttranslateX: 0,\n\t\t\ttranslateY: 0\n\t\t};\n\n\t\tpoint.graphic.animate(translation);\n\t\t\n\t\tif (point.shadowGroup) {\n\t\t\tpoint.shadowGroup.animate(translation);\n\t\t}\n\n\t}\n});\n\n/**\n * The Pie series class\n */\nvar PieSeries = {\n\ttype: 'pie',\n\tisCartesian: false,\n\tpointClass: PiePoint,\n\trequireSorting: false,\n\tnoSharedTooltip: true,\n\ttrackerGroups: ['group', 'dataLabelsGroup'],\n\tpointAttrToOptions: { // mapping between SVG attributes and the corresponding options\n\t\tstroke: 'borderColor',\n\t\t'stroke-width': 'borderWidth',\n\t\tfill: 'color'\n\t},\n\n\t/**\n\t * Pies have one color each point\n\t */\n\tgetColor: noop,\n\n\t/**\n\t * Animate the pies in\n\t */\n\tanimate: function (init) {\n\t\tvar series = this,\n\t\t\tpoints = series.points,\n\t\t\tstartAngleRad = series.startAngleRad;\n\n\t\tif (!init) {\n\t\t\teach(points, function (point) {\n\t\t\t\tvar graphic = point.graphic,\n\t\t\t\t\targs = point.shapeArgs;\n\n\t\t\t\tif (graphic) {\n\t\t\t\t\t// start values\n\t\t\t\t\tgraphic.attr({\n\t\t\t\t\t\tr: series.center[3] / 2, // animate from inner radius (#779)\n\t\t\t\t\t\tstart: startAngleRad,\n\t\t\t\t\t\tend: startAngleRad\n\t\t\t\t\t});\n\n\t\t\t\t\t// animate\n\t\t\t\t\tgraphic.animate({\n\t\t\t\t\t\tr: args.r,\n\t\t\t\t\t\tstart: args.start,\n\t\t\t\t\t\tend: args.end\n\t\t\t\t\t}, series.options.animation);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// delete this function to allow it only once\n\t\t\tseries.animate = null;\n\t\t}\n\t},\n\n\t/**\n\t * Extend the basic setData method by running processData and generatePoints immediately,\n\t * in order to access the points from the legend.\n\t */\n\tsetData: function (data, redraw) {\n\t\tSeries.prototype.setData.call(this, data, false);\n\t\tthis.processData();\n\t\tthis.generatePoints();\n\t\tif (pick(redraw, true)) {\n\t\t\tthis.chart.redraw();\n\t\t} \n\t},\n\n\t/**\n\t * Extend the generatePoints method by adding total and percentage properties to each point\n\t */\n\tgeneratePoints: function () {\n\t\tvar i,\n\t\t\ttotal = 0,\n\t\t\tpoints,\n\t\t\tlen,\n\t\t\tpoint,\n\t\t\tignoreHiddenPoint = this.options.ignoreHiddenPoint;\n\n\t\tSeries.prototype.generatePoints.call(this);\n\n\t\t// Populate local vars\n\t\tpoints = this.points;\n\t\tlen = points.length;\n\t\t\n\t\t// Get the total sum\n\t\tfor (i = 0; i < len; i++) {\n\t\t\tpoint = points[i];\n\t\t\ttotal += (ignoreHiddenPoint && !point.visible) ? 0 : point.y;\n\t\t}\n\t\tthis.total = total;\n\n\t\t// Set each point's properties\n\t\tfor (i = 0; i < len; i++) {\n\t\t\tpoint = points[i];\n\t\t\tpoint.percentage = (point.y / total) * 100;\n\t\t\tpoint.total = total;\n\t\t}\n\t\t\n\t},\n\t\n\t/**\n\t * Get the center of the pie based on the size and center options relative to the  \n\t * plot area. Borrowed by the polar and gauge series types.\n\t */\n\tgetCenter: function () {\n\t\t\n\t\tvar options = this.options,\n\t\t\tchart = this.chart,\n\t\t\tslicingRoom = 2 * (options.slicedOffset || 0),\n\t\t\thandleSlicingRoom,\n\t\t\tplotWidth = chart.plotWidth - 2 * slicingRoom,\n\t\t\tplotHeight = chart.plotHeight - 2 * slicingRoom,\n\t\t\tcenterOption = options.center,\n\t\t\tpositions = [pick(centerOption[0], '50%'), pick(centerOption[1], '50%'), options.size || '100%', options.innerSize || 0],\n\t\t\tsmallestSize = mathMin(plotWidth, plotHeight),\n\t\t\tisPercent;\n\t\t\n\t\treturn map(positions, function (length, i) {\n\t\t\tisPercent = /%$/.test(length);\n\t\t\thandleSlicingRoom = i < 2 || (i === 2 && isPercent);\n\t\t\treturn (isPercent ?\n\t\t\t\t// i == 0: centerX, relative to width\n\t\t\t\t// i == 1: centerY, relative to height\n\t\t\t\t// i == 2: size, relative to smallestSize\n\t\t\t\t// i == 4: innerSize, relative to smallestSize\n\t\t\t\t[plotWidth, plotHeight, smallestSize, smallestSize][i] *\n\t\t\t\t\tpInt(length) / 100 :\n\t\t\t\tlength) + (handleSlicingRoom ? slicingRoom : 0);\n\t\t});\n\t},\n\t\n\t/**\n\t * Do translation for pie slices\n\t */\n\ttranslate: function (positions) {\n\t\tthis.generatePoints();\n\t\t\n\t\tvar series = this,\n\t\t\tcumulative = 0,\n\t\t\tprecision = 1000, // issue #172\n\t\t\toptions = series.options,\n\t\t\tslicedOffset = options.slicedOffset,\n\t\t\tconnectorOffset = slicedOffset + options.borderWidth,\n\t\t\tstart,\n\t\t\tend,\n\t\t\tangle,\n\t\t\tstartAngleRad = series.startAngleRad = mathPI / 180 * ((options.startAngle || 0) % 360 - 90),\n\t\t\tpoints = series.points,\n\t\t\tcirc = 2 * mathPI,\n\t\t\tradiusX, // the x component of the radius vector for a given point\n\t\t\tradiusY,\n\t\t\tlabelDistance = options.dataLabels.distance,\n\t\t\tignoreHiddenPoint = options.ignoreHiddenPoint,\n\t\t\ti,\n\t\t\tlen = points.length,\n\t\t\tpoint;\n\n\t\t// Get positions - either an integer or a percentage string must be given.\n\t\t// If positions are passed as a parameter, we're in a recursive loop for adjusting\n\t\t// space for data labels.\n\t\tif (!positions) {\n\t\t\tseries.center = positions = series.getCenter();\n\t\t}\n\n\t\t// utility for getting the x value from a given y, used for anticollision logic in data labels\n\t\tseries.getX = function (y, left) {\n\n\t\t\tangle = math.asin((y - positions[1]) / (positions[2] / 2 + labelDistance));\n\n\t\t\treturn positions[0] +\n\t\t\t\t(left ? -1 : 1) *\n\t\t\t\t(mathCos(angle) * (positions[2] / 2 + labelDistance));\n\t\t};\n\n\t\t// Calculate the geometry for each point\n\t\tfor (i = 0; i < len; i++) {\n\t\t\t\n\t\t\tpoint = points[i];\n\t\t\t\n\t\t\t// set start and end angle\n\t\t\tstart = mathRound((startAngleRad + (cumulative * circ)) * precision) / precision;\n\t\t\tif (!ignoreHiddenPoint || point.visible) {\n\t\t\t\tcumulative += point.percentage / 100;\n\t\t\t}\n\t\t\tend = mathRound((startAngleRad + (cumulative * circ)) * precision) / precision;\n\n\t\t\t// set the shape\n\t\t\tpoint.shapeType = 'arc';\n\t\t\tpoint.shapeArgs = {\n\t\t\t\tx: positions[0],\n\t\t\t\ty: positions[1],\n\t\t\t\tr: positions[2] / 2,\n\t\t\t\tinnerR: positions[3] / 2,\n\t\t\t\tstart: start,\n\t\t\t\tend: end\n\t\t\t};\n\n\t\t\t// center for the sliced out slice\n\t\t\tangle = (end + start) / 2;\n\t\t\tif (angle > 0.75 * circ) {\n\t\t\t\tangle -= 2 * mathPI;\n\t\t\t}\n\t\t\tpoint.slicedTranslation = {\n\t\t\t\ttranslateX: mathRound(mathCos(angle) * slicedOffset),\n\t\t\t\ttranslateY: mathRound(mathSin(angle) * slicedOffset)\n\t\t\t};\n\n\t\t\t// set the anchor point for tooltips\n\t\t\tradiusX = mathCos(angle) * positions[2] / 2;\n\t\t\tradiusY = mathSin(angle) * positions[2] / 2;\n\t\t\tpoint.tooltipPos = [\n\t\t\t\tpositions[0] + radiusX * 0.7,\n\t\t\t\tpositions[1] + radiusY * 0.7\n\t\t\t];\n\t\t\t\n\t\t\tpoint.half = angle < circ / 4 ? 0 : 1;\n\t\t\tpoint.angle = angle;\n\n\t\t\t// set the anchor point for data labels\n\t\t\tconnectorOffset = mathMin(connectorOffset, labelDistance / 2); // #1678\n\t\t\tpoint.labelPos = [\n\t\t\t\tpositions[0] + radiusX + mathCos(angle) * labelDistance, // first break of connector\n\t\t\t\tpositions[1] + radiusY + mathSin(angle) * labelDistance, // a/a\n\t\t\t\tpositions[0] + radiusX + mathCos(angle) * connectorOffset, // second break, right outside pie\n\t\t\t\tpositions[1] + radiusY + mathSin(angle) * connectorOffset, // a/a\n\t\t\t\tpositions[0] + radiusX, // landing point for connector\n\t\t\t\tpositions[1] + radiusY, // a/a\n\t\t\t\tlabelDistance < 0 ? // alignment\n\t\t\t\t\t'center' :\n\t\t\t\t\tpoint.half ? 'right' : 'left', // alignment\n\t\t\t\tangle // center angle\n\t\t\t];\n\n\t\t}\n\n\n\t\tthis.setTooltipPoints();\n\t},\n\n\tdrawGraph: null,\n\n\t/**\n\t * Draw the data points\n\t */\n\tdrawPoints: function () {\n\t\tvar series = this,\n\t\t\tchart = series.chart,\n\t\t\trenderer = chart.renderer,\n\t\t\tgroupTranslation,\n\t\t\t//center,\n\t\t\tgraphic,\n\t\t\t//group,\n\t\t\tshadow = series.options.shadow,\n\t\t\tshadowGroup,\n\t\t\tshapeArgs;\n\n\t\tif (shadow && !series.shadowGroup) {\n\t\t\tseries.shadowGroup = renderer.g('shadow')\n\t\t\t\t.add(series.group);\n\t\t}\n\n\t\t// draw the slices\n\t\teach(series.points, function (point) {\n\t\t\tgraphic = point.graphic;\n\t\t\tshapeArgs = point.shapeArgs;\n\t\t\tshadowGroup = point.shadowGroup;\n\n\t\t\t// put the shadow behind all points\n\t\t\tif (shadow && !shadowGroup) {\n\t\t\t\tshadowGroup = point.shadowGroup = renderer.g('shadow')\n\t\t\t\t\t.add(series.shadowGroup);\n\t\t\t}\n\n\t\t\t// if the point is sliced, use special translation, else use plot area traslation\n\t\t\tgroupTranslation = point.sliced ? point.slicedTranslation : {\n\t\t\t\ttranslateX: 0,\n\t\t\t\ttranslateY: 0\n\t\t\t};\n\n\t\t\t//group.translate(groupTranslation[0], groupTranslation[1]);\n\t\t\tif (shadowGroup) {\n\t\t\t\tshadowGroup.attr(groupTranslation);\n\t\t\t}\n\n\t\t\t// draw the slice\n\t\t\tif (graphic) {\n\t\t\t\tgraphic.animate(extend(shapeArgs, groupTranslation));\n\t\t\t} else {\n\t\t\t\tpoint.graphic = graphic = renderer.arc(shapeArgs)\n\t\t\t\t\t.setRadialReference(series.center)\n\t\t\t\t\t.attr(\n\t\t\t\t\t\tpoint.pointAttr[point.selected ? SELECT_STATE : NORMAL_STATE]\n\t\t\t\t\t)\n\t\t\t\t\t.attr({ 'stroke-linejoin': 'round' })\n\t\t\t\t\t.attr(groupTranslation)\n\t\t\t\t\t.add(series.group)\n\t\t\t\t\t.shadow(shadow, shadowGroup);\t\n\t\t\t}\n\n\t\t\t// detect point specific visibility\n\t\t\tif (point.visible === false) {\n\t\t\t\tpoint.setVisible(false);\n\t\t\t}\n\n\t\t});\n\n\t},\n\n\t/**\n\t * Override the base drawDataLabels method by pie specific functionality\n\t */\n\tdrawDataLabels: function () {\n\t\tvar series = this,\n\t\t\tdata = series.data,\n\t\t\tpoint,\n\t\t\tchart = series.chart,\n\t\t\toptions = series.options.dataLabels,\n\t\t\tconnectorPadding = pick(options.connectorPadding, 10),\n\t\t\tconnectorWidth = pick(options.connectorWidth, 1),\n\t\t\tplotWidth = chart.plotWidth,\n\t\t\tplotHeight = chart.plotHeight,\n\t\t\tconnector,\n\t\t\tconnectorPath,\n\t\t\tsoftConnector = pick(options.softConnector, true),\n\t\t\tdistanceOption = options.distance,\n\t\t\tseriesCenter = series.center,\n\t\t\tradius = seriesCenter[2] / 2,\n\t\t\tcenterY = seriesCenter[1],\n\t\t\toutside = distanceOption > 0,\n\t\t\tdataLabel,\n\t\t\tdataLabelWidth,\n\t\t\tlabelPos,\n\t\t\tlabelHeight,\n\t\t\thalves = [// divide the points into right and left halves for anti collision\n\t\t\t\t[], // right\n\t\t\t\t[]  // left\n\t\t\t],\n\t\t\tx,\n\t\t\ty,\n\t\t\tvisibility,\n\t\t\trankArr,\n\t\t\ti,\n\t\t\tj,\n\t\t\toverflow = [0, 0, 0, 0], // top, right, bottom, left\n\t\t\tsort = function (a, b) {\n\t\t\t\treturn b.y - a.y;\n\t\t\t},\n\t\t\tsortByAngle = function (points, sign) {\n\t\t\t\tpoints.sort(function (a, b) {\n\t\t\t\t\treturn a.angle !== undefined && (b.angle - a.angle) * sign;\n\t\t\t\t});\n\t\t\t};\n\n\t\t// get out if not enabled\n\t\tif (!series.visible || (!options.enabled && !series._hasPointLabels)) {\n\t\t\treturn;\n\t\t}\n\n\t\t// run parent method\n\t\tSeries.prototype.drawDataLabels.apply(series);\n\n\t\t// arrange points for detection collision\n\t\teach(data, function (point) {\n\t\t\tif (point.dataLabel) { // it may have been cancelled in the base method (#407)\n\t\t\t\thalves[point.half].push(point);\n\t\t\t}\n\t\t});\n\n\t\t// assume equal label heights\n\t\ti = 0;\n\t\twhile (!labelHeight && data[i]) { // #1569\n\t\t\tlabelHeight = data[i] && data[i].dataLabel && (data[i].dataLabel.getBBox().height || 21); // 21 is for #968\n\t\t\ti++;\n\t\t}\n\n\t\t/* Loop over the points in each half, starting from the top and bottom\n\t\t * of the pie to detect overlapping labels.\n\t\t */\n\t\ti = 2;\n\t\twhile (i--) {\n\n\t\t\tvar slots = [],\n\t\t\t\tslotsLength,\n\t\t\t\tusedSlots = [],\n\t\t\t\tpoints = halves[i],\n\t\t\t\tpos,\n\t\t\t\tlength = points.length,\n\t\t\t\tslotIndex;\n\t\t\t\t\n\t\t\t// Sort by angle\n\t\t\tsortByAngle(points, i - 0.5);\n\n\t\t\t// Only do anti-collision when we are outside the pie and have connectors (#856)\n\t\t\tif (distanceOption > 0) {\n\t\t\t\t\n\t\t\t\t// build the slots\n\t\t\t\tfor (pos = centerY - radius - distanceOption; pos <= centerY + radius + distanceOption; pos += labelHeight) {\n\t\t\t\t\tslots.push(pos);\n\t\t\t\t\t\n\t\t\t\t\t// visualize the slot\n\t\t\t\t\t/*\n\t\t\t\t\tvar slotX = series.getX(pos, i) + chart.plotLeft - (i ? 100 : 0),\n\t\t\t\t\t\tslotY = pos + chart.plotTop;\n\t\t\t\t\tif (!isNaN(slotX)) {\n\t\t\t\t\t\tchart.renderer.rect(slotX, slotY - 7, 100, labelHeight, 1)\n\t\t\t\t\t\t\t.attr({\n\t\t\t\t\t\t\t\t'stroke-width': 1,\n\t\t\t\t\t\t\t\tstroke: 'silver'\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t.add();\n\t\t\t\t\t\tchart.renderer.text('Slot '+ (slots.length - 1), slotX, slotY + 4)\n\t\t\t\t\t\t\t.attr({\n\t\t\t\t\t\t\t\tfill: 'silver'\n\t\t\t\t\t\t\t}).add();\n\t\t\t\t\t}\n\t\t\t\t\t*/\n\t\t\t\t}\n\t\t\t\tslotsLength = slots.length;\n\t\n\t\t\t\t// if there are more values than available slots, remove lowest values\n\t\t\t\tif (length > slotsLength) {\n\t\t\t\t\t// create an array for sorting and ranking the points within each quarter\n\t\t\t\t\trankArr = [].concat(points);\n\t\t\t\t\trankArr.sort(sort);\n\t\t\t\t\tj = length;\n\t\t\t\t\twhile (j--) {\n\t\t\t\t\t\trankArr[j].rank = j;\n\t\t\t\t\t}\n\t\t\t\t\tj = length;\n\t\t\t\t\twhile (j--) {\n\t\t\t\t\t\tif (points[j].rank >= slotsLength) {\n\t\t\t\t\t\t\tpoints.splice(j, 1);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tlength = points.length;\n\t\t\t\t}\n\t\n\t\t\t\t// The label goes to the nearest open slot, but not closer to the edge than\n\t\t\t\t// the label's index.\n\t\t\t\tfor (j = 0; j < length; j++) {\n\t\n\t\t\t\t\tpoint = points[j];\n\t\t\t\t\tlabelPos = point.labelPos;\n\t\n\t\t\t\t\tvar closest = 9999,\n\t\t\t\t\t\tdistance,\n\t\t\t\t\t\tslotI;\n\t\n\t\t\t\t\t// find the closest slot index\n\t\t\t\t\tfor (slotI = 0; slotI < slotsLength; slotI++) {\n\t\t\t\t\t\tdistance = mathAbs(slots[slotI] - labelPos[1]);\n\t\t\t\t\t\tif (distance < closest) {\n\t\t\t\t\t\t\tclosest = distance;\n\t\t\t\t\t\t\tslotIndex = slotI;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\n\t\t\t\t\t// if that slot index is closer to the edges of the slots, move it\n\t\t\t\t\t// to the closest appropriate slot\n\t\t\t\t\tif (slotIndex < j && slots[j] !== null) { // cluster at the top\n\t\t\t\t\t\tslotIndex = j;\n\t\t\t\t\t} else if (slotsLength  < length - j + slotIndex && slots[j] !== null) { // cluster at the bottom\n\t\t\t\t\t\tslotIndex = slotsLength - length + j;\n\t\t\t\t\t\twhile (slots[slotIndex] === null) { // make sure it is not taken\n\t\t\t\t\t\t\tslotIndex++;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Slot is taken, find next free slot below. In the next run, the next slice will find the\n\t\t\t\t\t\t// slot above these, because it is the closest one\n\t\t\t\t\t\twhile (slots[slotIndex] === null) { // make sure it is not taken\n\t\t\t\t\t\t\tslotIndex++;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\n\t\t\t\t\tusedSlots.push({ i: slotIndex, y: slots[slotIndex] });\n\t\t\t\t\tslots[slotIndex] = null; // mark as taken\n\t\t\t\t}\n\t\t\t\t// sort them in order to fill in from the top\n\t\t\t\tusedSlots.sort(sort);\n\t\t\t}\n\n\t\t\t// now the used slots are sorted, fill them up sequentially\n\t\t\tfor (j = 0; j < length; j++) {\n\t\t\t\t\n\t\t\t\tvar slot, naturalY;\n\n\t\t\t\tpoint = points[j];\n\t\t\t\tlabelPos = point.labelPos;\n\t\t\t\tdataLabel = point.dataLabel;\n\t\t\t\tvisibility = point.visible === false ? HIDDEN : VISIBLE;\n\t\t\t\tnaturalY = labelPos[1];\n\t\t\t\t\n\t\t\t\tif (distanceOption > 0) {\n\t\t\t\t\tslot = usedSlots.pop();\n\t\t\t\t\tslotIndex = slot.i;\n\n\t\t\t\t\t// if the slot next to currrent slot is free, the y value is allowed\n\t\t\t\t\t// to fall back to the natural position\n\t\t\t\t\ty = slot.y;\n\t\t\t\t\tif ((naturalY > y && slots[slotIndex + 1] !== null) ||\n\t\t\t\t\t\t\t(naturalY < y &&  slots[slotIndex - 1] !== null)) {\n\t\t\t\t\t\ty = naturalY;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t} else {\n\t\t\t\t\ty = naturalY;\n\t\t\t\t}\n\n\t\t\t\t// get the x - use the natural x position for first and last slot, to prevent the top\n\t\t\t\t// and botton slice connectors from touching each other on either side\n\t\t\t\tx = options.justify ? \n\t\t\t\t\tseriesCenter[0] + (i ? -1 : 1) * (radius + distanceOption) :\n\t\t\t\t\tseries.getX(slotIndex === 0 || slotIndex === slots.length - 1 ? naturalY : y, i);\n\t\t\t\t\n\t\t\t\n\t\t\t\t// Record the placement and visibility\n\t\t\t\tdataLabel._attr = {\n\t\t\t\t\tvisibility: visibility,\n\t\t\t\t\talign: labelPos[6]\n\t\t\t\t};\n\t\t\t\tdataLabel._pos = {\n\t\t\t\t\tx: x + options.x +\n\t\t\t\t\t\t({ left: connectorPadding, right: -connectorPadding }[labelPos[6]] || 0),\n\t\t\t\t\ty: y + options.y - 10 // 10 is for the baseline (label vs text)\n\t\t\t\t};\n\t\t\t\tdataLabel.connX = x;\n\t\t\t\tdataLabel.connY = y;\n\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t// Detect overflowing data labels\n\t\t\t\tif (this.options.size === null) {\n\t\t\t\t\tdataLabelWidth = dataLabel.width;\n\t\t\t\t\t// Overflow left\n\t\t\t\t\tif (x - dataLabelWidth < connectorPadding) {\n\t\t\t\t\t\toverflow[3] = mathMax(mathRound(dataLabelWidth - x + connectorPadding), overflow[3]);\n\t\t\t\t\t\t\n\t\t\t\t\t// Overflow right\n\t\t\t\t\t} else if (x + dataLabelWidth > plotWidth - connectorPadding) {\n\t\t\t\t\t\toverflow[1] = mathMax(mathRound(x + dataLabelWidth - plotWidth + connectorPadding), overflow[1]);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t// Overflow top\n\t\t\t\t\tif (y - labelHeight / 2 < 0) {\n\t\t\t\t\t\toverflow[0] = mathMax(mathRound(-y + labelHeight / 2), overflow[0]);\n\t\t\t\t\t\t\n\t\t\t\t\t// Overflow left\n\t\t\t\t\t} else if (y + labelHeight / 2 > plotHeight) {\n\t\t\t\t\t\toverflow[2] = mathMax(mathRound(y + labelHeight / 2 - plotHeight), overflow[2]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} // for each point\n\t\t} // for each half\n\t\t\n\t\t// Do not apply the final placement and draw the connectors until we have verified\n\t\t// that labels are not spilling over. \n\t\tif (arrayMax(overflow) === 0 || this.verifyDataLabelOverflow(overflow)) {\n\t\t\t\n\t\t\t// Place the labels in the final position\n\t\t\tthis.placeDataLabels();\n\t\t\t\n\t\t\t// Draw the connectors\n\t\t\tif (outside && connectorWidth) {\n\t\t\t\teach(this.points, function (point) {\n\t\t\t\t\tconnector = point.connector;\n\t\t\t\t\tlabelPos = point.labelPos;\n\t\t\t\t\tdataLabel = point.dataLabel;\n\t\t\t\t\t\n\t\t\t\t\tif (dataLabel && dataLabel._pos) {\n\t\t\t\t\t\tvisibility = dataLabel._attr.visibility;\n\t\t\t\t\t\tx = dataLabel.connX;\n\t\t\t\t\t\ty = dataLabel.connY;\n\t\t\t\t\t\tconnectorPath = softConnector ? [\n\t\t\t\t\t\t\tM,\n\t\t\t\t\t\t\tx + (labelPos[6] === 'left' ? 5 : -5), y, // end of the string at the label\n\t\t\t\t\t\t\t'C',\n\t\t\t\t\t\t\tx, y, // first break, next to the label\n\t\t\t\t\t\t\t2 * labelPos[2] - labelPos[4], 2 * labelPos[3] - labelPos[5],\n\t\t\t\t\t\t\tlabelPos[2], labelPos[3], // second break\n\t\t\t\t\t\t\tL,\n\t\t\t\t\t\t\tlabelPos[4], labelPos[5] // base\n\t\t\t\t\t\t] : [\n\t\t\t\t\t\t\tM,\n\t\t\t\t\t\t\tx + (labelPos[6] === 'left' ? 5 : -5), y, // end of the string at the label\n\t\t\t\t\t\t\tL,\n\t\t\t\t\t\t\tlabelPos[2], labelPos[3], // second break\n\t\t\t\t\t\t\tL,\n\t\t\t\t\t\t\tlabelPos[4], labelPos[5] // base\n\t\t\t\t\t\t];\n\t\t\n\t\t\t\t\t\tif (connector) {\n\t\t\t\t\t\t\tconnector.animate({ d: connectorPath });\n\t\t\t\t\t\t\tconnector.attr('visibility', visibility);\n\t\t\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tpoint.connector = connector = series.chart.renderer.path(connectorPath).attr({\n\t\t\t\t\t\t\t\t'stroke-width': connectorWidth,\n\t\t\t\t\t\t\t\tstroke: options.connectorColor || point.color || '#606060',\n\t\t\t\t\t\t\t\tvisibility: visibility\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t.add(series.group);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (connector) {\n\t\t\t\t\t\tpoint.connector = connector.destroy();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\t\t\t\n\t\t}\n\t},\n\t\n\t/**\n\t * Verify whether the data labels are allowed to draw, or we should run more translation and data\n\t * label positioning to keep them inside the plot area. Returns true when data labels are ready \n\t * to draw.\n\t */\n\tverifyDataLabelOverflow: function (overflow) {\n\t\t\n\t\tvar center = this.center,\n\t\t\toptions = this.options,\n\t\t\tcenterOption = options.center,\n\t\t\tminSize = options.minSize || 80,\n\t\t\tnewSize = minSize,\n\t\t\tret;\n\t\t\t\n\t\t// Handle horizontal size and center\n\t\tif (centerOption[0] !== null) { // Fixed center\n\t\t\tnewSize = mathMax(center[2] - mathMax(overflow[1], overflow[3]), minSize);\n\t\t\t\n\t\t} else { // Auto center\n\t\t\tnewSize = mathMax(\n\t\t\t\tcenter[2] - overflow[1] - overflow[3], // horizontal overflow\t\t\t\t\t\n\t\t\t\tminSize\n\t\t\t);\n\t\t\tcenter[0] += (overflow[3] - overflow[1]) / 2; // horizontal center\n\t\t}\n\t\t\n\t\t// Handle vertical size and center\n\t\tif (centerOption[1] !== null) { // Fixed center\n\t\t\tnewSize = mathMax(mathMin(newSize, center[2] - mathMax(overflow[0], overflow[2])), minSize);\n\t\t\t\n\t\t} else { // Auto center\n\t\t\tnewSize = mathMax(\n\t\t\t\tmathMin(\n\t\t\t\t\tnewSize,\t\t\n\t\t\t\t\tcenter[2] - overflow[0] - overflow[2] // vertical overflow\n\t\t\t\t),\n\t\t\t\tminSize\n\t\t\t);\n\t\t\tcenter[1] += (overflow[0] - overflow[2]) / 2; // vertical center\n\t\t}\n\t\t\n\t\t// If the size must be decreased, we need to run translate and drawDataLabels again\n\t\tif (newSize < center[2]) {\n\t\t\tcenter[2] = newSize;\n\t\t\tthis.translate(center);\n\t\t\teach(this.points, function (point) {\n\t\t\t\tif (point.dataLabel) {\n\t\t\t\t\tpoint.dataLabel._pos = null; // reset\n\t\t\t\t}\n\t\t\t});\n\t\t\tthis.drawDataLabels();\n\t\t\t\n\t\t// Else, return true to indicate that the pie and its labels is within the plot area\n\t\t} else {\n\t\t\tret = true;\n\t\t}\n\t\treturn ret;\n\t},\n\t\n\t/**\n\t * Perform the final placement of the data labels after we have verified that they\n\t * fall within the plot area.\n\t */\n\tplaceDataLabels: function () {\n\t\teach(this.points, function (point) {\n\t\t\tvar dataLabel = point.dataLabel,\n\t\t\t\t_pos;\n\t\t\t\n\t\t\tif (dataLabel) {\n\t\t\t\t_pos = dataLabel._pos;\n\t\t\t\tif (_pos) {\n\t\t\t\t\tdataLabel.attr(dataLabel._attr);\t\t\t\n\t\t\t\t\tdataLabel[dataLabel.moved ? 'animate' : 'attr'](_pos);\n\t\t\t\t\tdataLabel.moved = true;\n\t\t\t\t} else if (dataLabel) {\n\t\t\t\t\tdataLabel.attr({ y: -999 });\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n\t\n\talignDataLabel: noop,\n\n\t/**\n\t * Draw point specific tracker objects. Inherit directly from column series.\n\t */\n\tdrawTracker: ColumnSeries.prototype.drawTracker,\n\n\t/**\n\t * Use a simple symbol from column prototype\n\t */\n\tdrawLegendSymbol: AreaSeries.prototype.drawLegendSymbol,\n\n\t/**\n\t * Pies don't have point marker symbols\n\t */\n\tgetSymbol: noop\n\n};\nPieSeries = extendClass(Series, PieSeries);\nseriesTypes.pie = PieSeries;\n\n\n// global variables\nextend(Highcharts, {\n\t\n\t// Constructors\n\tAxis: Axis,\n\tChart: Chart,\n\tColor: Color,\n\tLegend: Legend,\n\tPointer: Pointer,\n\tPoint: Point,\n\tTick: Tick,\n\tTooltip: Tooltip,\n\tRenderer: Renderer,\n\tSeries: Series,\n\tSVGElement: SVGElement,\n\tSVGRenderer: SVGRenderer,\n\t\n\t// Various\n\tarrayMin: arrayMin,\n\tarrayMax: arrayMax,\n\tcharts: charts,\n\tdateFormat: dateFormat,\n\tformat: format,\n\tpathAnim: pathAnim,\n\tgetOptions: getOptions,\n\thasBidiBug: hasBidiBug,\n\tisTouchDevice: isTouchDevice,\n\tnumberFormat: numberFormat,\n\tseriesTypes: seriesTypes,\n\tsetOptions: setOptions,\n\taddEvent: addEvent,\n\tremoveEvent: removeEvent,\n\tcreateElement: createElement,\n\tdiscardElement: discardElement,\n\tcss: css,\n\teach: each,\n\textend: extend,\n\tmap: map,\n\tmerge: merge,\n\tpick: pick,\n\tsplat: splat,\n\textendClass: extendClass,\n\tpInt: pInt,\n\twrap: wrap,\n\tsvg: hasSVG,\n\tcanvas: useCanVG,\n\tvml: !hasSVG && !useCanVG,\n\tproduct: PRODUCT,\n\tversion: VERSION\n});\n}());\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/highchart3/js/modules/annotations.js",
    "content": "(function(i,C){function m(a){return typeof a===\"number\"}function n(a){return a!==D&&a!==null}var D,p,r,s=i.Chart,t=i.extend,z=i.each;r=[\"path\",\"rect\",\"circle\"];p={top:0,left:0,center:0.5,middle:0.5,bottom:1,right:1};var u=C.inArray,A=i.merge,B=function(){this.init.apply(this,arguments)};B.prototype={init:function(a,d){var c=d.shape&&d.shape.type;this.chart=a;var b,f;f={xAxis:0,yAxis:0,title:{style:{},text:\"\",x:0,y:0},shape:{params:{stroke:\"#000000\",fill:\"transparent\",strokeWidth:2}}};b={circle:{params:{x:0,\ny:0}}};if(b[c])f.shape=A(f.shape,b[c]);this.options=A({},f,d)},render:function(a){var d=this.chart,c=this.chart.renderer,b=this.group,f=this.title,e=this.shape,h=this.options,i=h.title,l=h.shape;if(!b)b=this.group=c.g();if(!e&&l&&u(l.type,r)!==-1)e=this.shape=c[h.shape.type](l.params),e.add(b);if(!f&&i)f=this.title=c.label(i),f.add(b);b.add(d.annotations.group);this.linkObjects();a!==!1&&this.redraw()},redraw:function(){var a=this.options,d=this.chart,c=this.group,b=this.title,f=this.shape,e=this.linkedObject,\nh=d.xAxis[a.xAxis],v=d.yAxis[a.yAxis],l=a.width,w=a.height,x=p[a.anchorY],y=p[a.anchorX],j,o,g,q;if(e)j=e instanceof i.Point?\"point\":e instanceof i.Series?\"series\":null,j===\"point\"?(a.xValue=e.x,a.yValue=e.y,o=e.series):j===\"series\"&&(o=e),c.visibility!==o.group.visibility&&c.attr({visibility:o.group.visibility});e=n(a.xValue)?h.toPixels(a.xValue+h.minPointOffset)-h.minPixelPadding:a.x;j=n(a.yValue)?v.toPixels(a.yValue):a.y;if(!isNaN(e)&&!isNaN(j)&&m(e)&&m(j)){b&&(b.attr(a.title),b.css(a.title.style));\nif(f){b=t({},a.shape.params);if(a.units===\"values\"){for(g in b)u(g,[\"width\",\"x\"])>-1?b[g]=h.translate(b[g]):u(g,[\"height\",\"y\"])>-1&&(b[g]=v.translate(b[g]));b.width&&(b.width-=h.toPixels(0)-h.left);b.x&&(b.x+=h.minPixelPadding);if(a.shape.type===\"path\"){g=b.d;o=e;for(var r=j,s=g.length,k=0;k<s;)typeof g[k]===\"number\"&&typeof g[k+1]===\"number\"?(g[k]=h.toPixels(g[k])-o,g[k+1]=v.toPixels(g[k+1])-r,k+=2):k+=1}}a.shape.type===\"circle\"&&(b.x+=b.r,b.y+=b.r);f.attr(b)}c.bBox=null;if(!m(l))q=c.getBBox(),l=\nq.width;if(!m(w))q||(q=c.getBBox()),w=q.height;if(!m(y))y=p.center;if(!m(x))x=p.center;e-=l*y;j-=w*x;d.animation&&n(c.translateX)&&n(c.translateY)?c.animate({translateX:e,translateY:j}):c.translate(e,j)}},destroy:function(){var a=this,d=this.chart.annotations.allItems,c=d.indexOf(a);c>-1&&d.splice(c,1);z([\"title\",\"shape\",\"group\"],function(b){a[b]&&(a[b].destroy(),a[b]=null)});a.group=a.title=a.shape=a.chart=a.options=null},update:function(a,d){t(this.options,a);this.linkObjects();this.render(d)},\nlinkObjects:function(){var a=this.chart,d=this.linkedObject,c=d&&(d.id||d.options.id),b=this.options.linkedTo;if(n(b)){if(!n(d)||b!==c)this.linkedObject=a.get(b)}else this.linkedObject=null}};t(s.prototype,{annotations:{add:function(a,d){var c=this.allItems,b=this.chart,f,e;Object.prototype.toString.call(a)===\"[object Array]\"||(a=[a]);for(e=a.length;e--;)f=new B(b,a[e]),c.push(f),f.render(d)},redraw:function(){z(this.allItems,function(a){a.redraw()})}}});s.prototype.callbacks.push(function(a){var d=\na.options.annotations,c;c=a.renderer.g(\"annotations\");c.attr({zIndex:7});c.add();a.annotations.allItems=[];a.annotations.chart=a;a.annotations.group=c;Object.prototype.toString.call(d)===\"[object Array]\"&&d.length>0&&a.annotations.add(a.options.annotations);i.addEvent(a,\"redraw\",function(){a.annotations.redraw()})})})(Highcharts,HighchartsAdapter);\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/highchart3/js/modules/annotations.src.js",
    "content": "(function (Highcharts, HighchartsAdapter) {\n\nvar UNDEFINED,\n\tALIGN_FACTOR,\n\tALLOWED_SHAPES,\n\tChart = Highcharts.Chart,\n\textend = Highcharts.extend,\n\teach = Highcharts.each;\n\nALLOWED_SHAPES = [\"path\", \"rect\", \"circle\"];\n\nALIGN_FACTOR = {\n\ttop: 0,\n\tleft: 0,\n\tcenter: 0.5,\n\tmiddle: 0.5,\n\tbottom: 1,\n\tright: 1\n};\n\n\n// Highcharts helper methods\nvar inArray = HighchartsAdapter.inArray,\n\tmerge = Highcharts.merge;\n\nfunction defaultOptions(shapeType) {\n\tvar shapeOptions,\n\t\toptions;\n\n\toptions = {\n\t\txAxis: 0,\n\t\tyAxis: 0,\n\t\ttitle: {\n\t\t\tstyle: {},\n\t\t\ttext: \"\",\n\t\t\tx: 0,\n\t\t\ty: 0\n\t\t},\n\t\tshape: {\n\t\t\tparams: {\n\t\t\t\tstroke: \"#000000\",\n\t\t\t\tfill: \"transparent\",\n\t\t\t\tstrokeWidth: 2\n\t\t\t}\n\t\t}\n\t};\n\n\tshapeOptions = {\n\t\tcircle: {\n\t\t\tparams: {\n\t\t\t\tx: 0,\n\t\t\t\ty: 0\n\t\t\t}\n\t\t}\n\t};\n\n\tif (shapeOptions[shapeType]) {\n\t\toptions.shape = merge(options.shape, shapeOptions[shapeType]);\n\t}\n\n\treturn options;\n}\n\nfunction isArray(obj) {\n\treturn Object.prototype.toString.call(obj) === '[object Array]';\n}\n\nfunction isNumber(n) {\n\treturn typeof n === 'number';\n}\n\nfunction defined(obj) {\n\treturn obj !== UNDEFINED && obj !== null;\n}\n\nfunction translatePath(d, xAxis, yAxis, xOffset, yOffset) {\n\tvar len = d.length,\n\t\ti = 0;\n\n\twhile (i < len) {\n\t\tif (typeof d[i] === 'number' && typeof d[i + 1] === 'number') {\n\t\t\td[i] = xAxis.toPixels(d[i]) - xOffset;\n\t\t\td[i + 1] = yAxis.toPixels(d[i + 1]) - yOffset;\n\t\t\ti += 2;\n\t\t} else {\n\t\t\ti += 1;\n\t\t}\n\t}\n\n\treturn d;\n}\n\n\n// Define annotation prototype\nvar Annotation = function () {\n\tthis.init.apply(this, arguments);\n};\nAnnotation.prototype = {\n\t/* \n\t * Initialize the annotation\n\t */\n\tinit: function (chart, options) {\n\t\tvar shapeType = options.shape && options.shape.type;\n\n\t\tthis.chart = chart;\n\t\tthis.options = merge({}, defaultOptions(shapeType), options);\n\t},\n\n\t/*\n\t * Render the annotation\n\t */\n\trender: function (redraw) {\n\t\tvar annotation = this,\n\t\t\tchart = this.chart,\n\t\t\trenderer = annotation.chart.renderer,\n\t\t\tgroup = annotation.group,\n\t\t\ttitle = annotation.title,\n\t\t\tshape = annotation.shape,\n\t\t\toptions = annotation.options,\n\t\t\ttitleOptions = options.title,\n\t\t\tshapeOptions = options.shape;\n\n\t\tif (!group) {\n\t\t\tgroup = annotation.group = renderer.g();\n\t\t}\n\n\n\t\tif (!shape && shapeOptions && inArray(shapeOptions.type, ALLOWED_SHAPES) !== -1) {\n\t\t\tshape = annotation.shape = renderer[options.shape.type](shapeOptions.params);\n\t\t\tshape.add(group);\n\t\t}\n\n\t\tif (!title && titleOptions) {\n\t\t\ttitle = annotation.title = renderer.label(titleOptions);\n\t\t\ttitle.add(group);\n\t\t}\n\n\t\tgroup.add(chart.annotations.group);\n\n\t\t// link annotations to point or series\n\t\tannotation.linkObjects();\n\n\t\tif (redraw !== false) {\n\t\t\tannotation.redraw();\n\t\t}\n\t},\n\n\t/*\n\t * Redraw the annotation title or shape after options update\n\t */\n\tredraw: function () {\n\t\tvar options = this.options,\n\t\t\tchart = this.chart,\n\t\t\tgroup = this.group,\n\t\t\ttitle = this.title,\n\t\t\tshape = this.shape,\n\t\t\tlinkedTo = this.linkedObject,\n\t\t\txAxis = chart.xAxis[options.xAxis],\n\t\t\tyAxis = chart.yAxis[options.yAxis],\n\t\t\twidth = options.width,\n\t\t\theight = options.height,\n\t\t\tanchorY = ALIGN_FACTOR[options.anchorY],\n\t\t\tanchorX = ALIGN_FACTOR[options.anchorX],\n\t\t\tresetBBox = false,\n\t\t\tshapeParams,\n\t\t\tlinkType,\n\t\t\tseries,\n\t\t\tparam,\n\t\t\tbbox,\n\t\t\tx,\n\t\t\ty;\n\n\t\tif (linkedTo) {\n\t\t\tlinkType = (linkedTo instanceof Highcharts.Point) ? 'point' :\n\t\t\t\t\t\t(linkedTo instanceof Highcharts.Series) ? 'series' : null;\n\n\t\t\tif (linkType === 'point') {\n\t\t\t\toptions.xValue = linkedTo.x;\n\t\t\t\toptions.yValue = linkedTo.y;\n\t\t\t\tseries = linkedTo.series;\n\t\t\t} else if (linkType === 'series') {\n\t\t\t\tseries = linkedTo;\n\t\t\t}\n\n\t\t\tif (group.visibility !== series.group.visibility) {\n\t\t\t\tgroup.attr({\n\t\t\t\t\tvisibility: series.group.visibility\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\n\t\t// Based on given options find annotation pixel position\n\t\tx = (defined(options.xValue) ? xAxis.toPixels(options.xValue + xAxis.minPointOffset) - xAxis.minPixelPadding : options.x);\n\t\ty = defined(options.yValue) ? yAxis.toPixels(options.yValue) : options.y;\n\n\t\tif (isNaN(x) || isNaN(y) || !isNumber(x) || !isNumber(y)) {\n\t\t\treturn;\n\t\t}\n\n\n\t\tif (title) {\n\t\t\ttitle.attr(options.title);\n\t\t\ttitle.css(options.title.style);\n\t\t\tresetBBox = true;\n\t\t}\n\n\t\tif (shape) {\n\t\t\tshapeParams = extend({}, options.shape.params);\n\n\t\t\tif (options.units === 'values') {\n\t\t\t\tfor (param in shapeParams) {\n\t\t\t\t\tif (inArray(param, ['width', 'x']) > -1) {\n\t\t\t\t\t\tshapeParams[param] = xAxis.translate(shapeParams[param]);\n\t\t\t\t\t} else if (inArray(param, ['height', 'y']) > -1) {\n\t\t\t\t\t\tshapeParams[param] = yAxis.translate(shapeParams[param]);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (shapeParams.width) {\n\t\t\t\t\tshapeParams.width -= xAxis.toPixels(0) - xAxis.left;\n\t\t\t\t}\n\n\t\t\t\tif (shapeParams.x) {\n\t\t\t\t\tshapeParams.x += xAxis.minPixelPadding;\n\t\t\t\t}\n\n\t\t\t\tif (options.shape.type === 'path') {\n\t\t\t\t\ttranslatePath(shapeParams.d, xAxis, yAxis, x, y);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// move the center of the circle to shape x/y\n\t\t\tif (options.shape.type === 'circle') {\n\t\t\t\tshapeParams.x += shapeParams.r;\n\t\t\t\tshapeParams.y += shapeParams.r;\n\t\t\t}\n\n\t\t\tresetBBox = true;\n\t\t\tshape.attr(shapeParams);\n\t\t}\n\n\t\tgroup.bBox = null;\n\n\t\t// If annotation width or height is not defined in options use bounding box size\n\t\tif (!isNumber(width)) {\n\t\t\tbbox = group.getBBox();\n\t\t\twidth = bbox.width;\n\t\t}\n\n\t\tif (!isNumber(height)) {\n\t\t\t// get bbox only if it wasn't set before\n\t\t\tif (!bbox) {\n\t\t\t\tbbox = group.getBBox();\n\t\t\t}\n\n\t\t\theight = bbox.height;\n\t\t}\n\n\t\t// Calculate anchor point\n\t\tif (!isNumber(anchorX)) {\n\t\t\tanchorX = ALIGN_FACTOR.center;\n\t\t}\n\n\t\tif (!isNumber(anchorY)) {\n\t\t\tanchorY = ALIGN_FACTOR.center;\n\t\t}\n\n\t\t// Translate group according to its dimension and anchor point\n\t\tx = x - width * anchorX;\n\t\ty = y - height * anchorY;\n\n\t\tif (chart.animation && defined(group.translateX) && defined(group.translateY)) {\n\t\t\tgroup.animate({\n\t\t\t\ttranslateX: x,\n\t\t\t\ttranslateY: y\n\t\t\t});\n\t\t} else {\n\t\t\tgroup.translate(x, y);\n\t\t}\n\t},\n\n\t/*\n\t * Destroy the annotation\n\t */\n\tdestroy: function () {\n\t\tvar annotation = this,\n\t\t\tchart = this.chart,\n\t\t\tallItems = chart.annotations.allItems,\n\t\t\tindex = allItems.indexOf(annotation);\n\n\t\tif (index > -1) {\n\t\t\tallItems.splice(index, 1);\n\t\t}\n\n\t\teach(['title', 'shape', 'group'], function (element) {\n\t\t\tif (annotation[element]) {\n\t\t\t\tannotation[element].destroy();\n\t\t\t\tannotation[element] = null;\n\t\t\t}\n\t\t});\n\n\t\tannotation.group = annotation.title = annotation.shape = annotation.chart = annotation.options = null;\n\t},\n\n\t/*\n\t * Update the annotation with a given options\n\t */\n\tupdate: function (options, redraw) {\n\t\textend(this.options, options);\n\n\t\t// update link to point or series\n\t\tthis.linkObjects();\n\n\t\tthis.render(redraw);\n\t},\n\n\tlinkObjects: function () {\n\t\tvar annotation = this,\n\t\t\tchart = annotation.chart,\n\t\t\tlinkedTo = annotation.linkedObject,\n\t\t\tlinkedId = linkedTo && (linkedTo.id || linkedTo.options.id),\n\t\t\toptions = annotation.options,\n\t\t\tid = options.linkedTo;\n\n\t\tif (!defined(id)) {\n\t\t\tannotation.linkedObject = null;\n\t\t} else if (!defined(linkedTo) || id !== linkedId) {\n\t\t\tannotation.linkedObject = chart.get(id);\n\t\t}\n\t}\n};\n\n\n// Add annotations methods to chart prototype\nextend(Chart.prototype, {\n\tannotations: {\n\t\t/*\n\t\t * Unified method for adding annotations to the chart\n\t\t */\n\t\tadd: function (options, redraw) {\n\t\t\tvar annotations = this.allItems,\n\t\t\t\tchart = this.chart,\n\t\t\t\titem,\n\t\t\t\tlen;\n\n\t\t\tif (!isArray(options)) {\n\t\t\t\toptions = [options];\n\t\t\t}\n\n\t\t\tlen = options.length;\n\n\t\t\twhile (len--) {\n\t\t\t\titem = new Annotation(chart, options[len]);\n\t\t\t\tannotations.push(item);\n\t\t\t\titem.render(redraw);\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Redraw all annotations, method used in chart events\n\t\t */\n\t\tredraw: function () {\n\t\t\teach(this.allItems, function (annotation) {\n\t\t\t\tannotation.redraw();\n\t\t\t});\n\t\t}\n\t}\n});\n\n\n// Initialize on chart load\nChart.prototype.callbacks.push(function (chart) {\n\tvar options = chart.options.annotations,\n\t\tgroup;\n\n\tgroup = chart.renderer.g(\"annotations\");\n\tgroup.attr({\n\t\tzIndex: 7\n\t});\n\tgroup.add();\n\n\t// initialize empty array for annotations\n\tchart.annotations.allItems = [];\n\n\t// link chart object to annotations\n\tchart.annotations.chart = chart;\n\n\t// link annotations group element to the chart\n\tchart.annotations.group = group;\n\n\tif (isArray(options) && options.length > 0) {\n\t\tchart.annotations.add(chart.options.annotations);\n\t}\n\n\t// update annotations after chart redraw\n\tHighcharts.addEvent(chart, 'redraw', function () {\n\t\tchart.annotations.redraw();\n\t});\n});\n}(Highcharts, HighchartsAdapter));\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/highchart3/js/modules/canvas-tools.js",
    "content": "/*\n A class to parse color values\n @author Stoyan Stefanov <sstoo@gmail.com>\n @link   http://www.phpied.com/rgb-color-parser-in-javascript/\n Use it if you like it\n\n canvg.js - Javascript SVG parser and renderer on Canvas\n MIT Licensed \n Gabe Lerner (gabelerner@gmail.com)\n http://code.google.com/p/canvg/\n\n Requires: rgbcolor.js - http://www.phpied.com/rgb-color-parser-in-javascript/\n\n Highcharts JS v3.0.3 (2013-07-31)\n CanVGRenderer Extension module\n\n (c) 2011-2012 Torstein Hønsi, Erik Olsson\n\n License: www.highcharts.com/license\n*/\nfunction RGBColor(m){this.ok=!1;m.charAt(0)==\"#\"&&(m=m.substr(1,6));var m=m.replace(/ /g,\"\"),m=m.toLowerCase(),a={aliceblue:\"f0f8ff\",antiquewhite:\"faebd7\",aqua:\"00ffff\",aquamarine:\"7fffd4\",azure:\"f0ffff\",beige:\"f5f5dc\",bisque:\"ffe4c4\",black:\"000000\",blanchedalmond:\"ffebcd\",blue:\"0000ff\",blueviolet:\"8a2be2\",brown:\"a52a2a\",burlywood:\"deb887\",cadetblue:\"5f9ea0\",chartreuse:\"7fff00\",chocolate:\"d2691e\",coral:\"ff7f50\",cornflowerblue:\"6495ed\",cornsilk:\"fff8dc\",crimson:\"dc143c\",cyan:\"00ffff\",darkblue:\"00008b\",\ndarkcyan:\"008b8b\",darkgoldenrod:\"b8860b\",darkgray:\"a9a9a9\",darkgreen:\"006400\",darkkhaki:\"bdb76b\",darkmagenta:\"8b008b\",darkolivegreen:\"556b2f\",darkorange:\"ff8c00\",darkorchid:\"9932cc\",darkred:\"8b0000\",darksalmon:\"e9967a\",darkseagreen:\"8fbc8f\",darkslateblue:\"483d8b\",darkslategray:\"2f4f4f\",darkturquoise:\"00ced1\",darkviolet:\"9400d3\",deeppink:\"ff1493\",deepskyblue:\"00bfff\",dimgray:\"696969\",dodgerblue:\"1e90ff\",feldspar:\"d19275\",firebrick:\"b22222\",floralwhite:\"fffaf0\",forestgreen:\"228b22\",fuchsia:\"ff00ff\",\ngainsboro:\"dcdcdc\",ghostwhite:\"f8f8ff\",gold:\"ffd700\",goldenrod:\"daa520\",gray:\"808080\",green:\"008000\",greenyellow:\"adff2f\",honeydew:\"f0fff0\",hotpink:\"ff69b4\",indianred:\"cd5c5c\",indigo:\"4b0082\",ivory:\"fffff0\",khaki:\"f0e68c\",lavender:\"e6e6fa\",lavenderblush:\"fff0f5\",lawngreen:\"7cfc00\",lemonchiffon:\"fffacd\",lightblue:\"add8e6\",lightcoral:\"f08080\",lightcyan:\"e0ffff\",lightgoldenrodyellow:\"fafad2\",lightgrey:\"d3d3d3\",lightgreen:\"90ee90\",lightpink:\"ffb6c1\",lightsalmon:\"ffa07a\",lightseagreen:\"20b2aa\",lightskyblue:\"87cefa\",\nlightslateblue:\"8470ff\",lightslategray:\"778899\",lightsteelblue:\"b0c4de\",lightyellow:\"ffffe0\",lime:\"00ff00\",limegreen:\"32cd32\",linen:\"faf0e6\",magenta:\"ff00ff\",maroon:\"800000\",mediumaquamarine:\"66cdaa\",mediumblue:\"0000cd\",mediumorchid:\"ba55d3\",mediumpurple:\"9370d8\",mediumseagreen:\"3cb371\",mediumslateblue:\"7b68ee\",mediumspringgreen:\"00fa9a\",mediumturquoise:\"48d1cc\",mediumvioletred:\"c71585\",midnightblue:\"191970\",mintcream:\"f5fffa\",mistyrose:\"ffe4e1\",moccasin:\"ffe4b5\",navajowhite:\"ffdead\",navy:\"000080\",\noldlace:\"fdf5e6\",olive:\"808000\",olivedrab:\"6b8e23\",orange:\"ffa500\",orangered:\"ff4500\",orchid:\"da70d6\",palegoldenrod:\"eee8aa\",palegreen:\"98fb98\",paleturquoise:\"afeeee\",palevioletred:\"d87093\",papayawhip:\"ffefd5\",peachpuff:\"ffdab9\",peru:\"cd853f\",pink:\"ffc0cb\",plum:\"dda0dd\",powderblue:\"b0e0e6\",purple:\"800080\",red:\"ff0000\",rosybrown:\"bc8f8f\",royalblue:\"4169e1\",saddlebrown:\"8b4513\",salmon:\"fa8072\",sandybrown:\"f4a460\",seagreen:\"2e8b57\",seashell:\"fff5ee\",sienna:\"a0522d\",silver:\"c0c0c0\",skyblue:\"87ceeb\",slateblue:\"6a5acd\",\nslategray:\"708090\",snow:\"fffafa\",springgreen:\"00ff7f\",steelblue:\"4682b4\",tan:\"d2b48c\",teal:\"008080\",thistle:\"d8bfd8\",tomato:\"ff6347\",turquoise:\"40e0d0\",violet:\"ee82ee\",violetred:\"d02090\",wheat:\"f5deb3\",white:\"ffffff\",whitesmoke:\"f5f5f5\",yellow:\"ffff00\",yellowgreen:\"9acd32\"},c;for(c in a)m==c&&(m=a[c]);var d=[{re:/^rgb\\((\\d{1,3}),\\s*(\\d{1,3}),\\s*(\\d{1,3})\\)$/,example:[\"rgb(123, 234, 45)\",\"rgb(255,234,245)\"],process:function(b){return[parseInt(b[1]),parseInt(b[2]),parseInt(b[3])]}},{re:/^(\\w{2})(\\w{2})(\\w{2})$/,\nexample:[\"#00ff00\",\"336699\"],process:function(b){return[parseInt(b[1],16),parseInt(b[2],16),parseInt(b[3],16)]}},{re:/^(\\w{1})(\\w{1})(\\w{1})$/,example:[\"#fb0\",\"f0f\"],process:function(b){return[parseInt(b[1]+b[1],16),parseInt(b[2]+b[2],16),parseInt(b[3]+b[3],16)]}}];for(c=0;c<d.length;c++){var b=d[c].process,k=d[c].re.exec(m);if(k)channels=b(k),this.r=channels[0],this.g=channels[1],this.b=channels[2],this.ok=!0}this.r=this.r<0||isNaN(this.r)?0:this.r>255?255:this.r;this.g=this.g<0||isNaN(this.g)?0:\nthis.g>255?255:this.g;this.b=this.b<0||isNaN(this.b)?0:this.b>255?255:this.b;this.toRGB=function(){return\"rgb(\"+this.r+\", \"+this.g+\", \"+this.b+\")\"};this.toHex=function(){var b=this.r.toString(16),a=this.g.toString(16),d=this.b.toString(16);b.length==1&&(b=\"0\"+b);a.length==1&&(a=\"0\"+a);d.length==1&&(d=\"0\"+d);return\"#\"+b+a+d};this.getHelpXML=function(){for(var b=[],k=0;k<d.length;k++)for(var c=d[k].example,j=0;j<c.length;j++)b[b.length]=c[j];for(var h in a)b[b.length]=h;c=document.createElement(\"ul\");\nc.setAttribute(\"id\",\"rgbcolor-examples\");for(k=0;k<b.length;k++)try{var l=document.createElement(\"li\"),o=new RGBColor(b[k]),n=document.createElement(\"div\");n.style.cssText=\"margin: 3px; border: 1px solid black; background:\"+o.toHex()+\"; color:\"+o.toHex();n.appendChild(document.createTextNode(\"test\"));var q=document.createTextNode(\" \"+b[k]+\" -> \"+o.toRGB()+\" -> \"+o.toHex());l.appendChild(n);l.appendChild(q);c.appendChild(l)}catch(p){}return c}}\nif(!window.console)window.console={},window.console.log=function(){},window.console.dir=function(){};if(!Array.prototype.indexOf)Array.prototype.indexOf=function(m){for(var a=0;a<this.length;a++)if(this[a]==m)return a;return-1};\n(function(){function m(){var a={FRAMERATE:30,MAX_VIRTUAL_PIXELS:3E4};a.init=function(c){a.Definitions={};a.Styles={};a.Animations=[];a.Images=[];a.ctx=c;a.ViewPort=new function(){this.viewPorts=[];this.Clear=function(){this.viewPorts=[]};this.SetCurrent=function(a,b){this.viewPorts.push({width:a,height:b})};this.RemoveCurrent=function(){this.viewPorts.pop()};this.Current=function(){return this.viewPorts[this.viewPorts.length-1]};this.width=function(){return this.Current().width};this.height=function(){return this.Current().height};\nthis.ComputeSize=function(a){return a!=null&&typeof a==\"number\"?a:a==\"x\"?this.width():a==\"y\"?this.height():Math.sqrt(Math.pow(this.width(),2)+Math.pow(this.height(),2))/Math.sqrt(2)}}};a.init();a.ImagesLoaded=function(){for(var c=0;c<a.Images.length;c++)if(!a.Images[c].loaded)return!1;return!0};a.trim=function(a){return a.replace(/^\\s+|\\s+$/g,\"\")};a.compressSpaces=function(a){return a.replace(/[\\s\\r\\t\\n]+/gm,\" \")};a.ajax=function(a){var d;return(d=window.XMLHttpRequest?new XMLHttpRequest:new ActiveXObject(\"Microsoft.XMLHTTP\"))?\n(d.open(\"GET\",a,!1),d.send(null),d.responseText):null};a.parseXml=function(a){if(window.DOMParser)return(new DOMParser).parseFromString(a,\"text/xml\");else{var a=a.replace(/<!DOCTYPE svg[^>]*>/,\"\"),d=new ActiveXObject(\"Microsoft.XMLDOM\");d.async=\"false\";d.loadXML(a);return d}};a.Property=function(c,d){this.name=c;this.value=d;this.hasValue=function(){return this.value!=null&&this.value!==\"\"};this.numValue=function(){if(!this.hasValue())return 0;var b=parseFloat(this.value);(this.value+\"\").match(/%$/)&&\n(b/=100);return b};this.valueOrDefault=function(b){return this.hasValue()?this.value:b};this.numValueOrDefault=function(b){return this.hasValue()?this.numValue():b};var b=this;this.Color={addOpacity:function(d){var c=b.value;if(d!=null&&d!=\"\"){var f=new RGBColor(b.value);f.ok&&(c=\"rgba(\"+f.r+\", \"+f.g+\", \"+f.b+\", \"+d+\")\")}return new a.Property(b.name,c)}};this.Definition={getDefinition:function(){var d=b.value.replace(/^(url\\()?#([^\\)]+)\\)?$/,\"$2\");return a.Definitions[d]},isUrl:function(){return b.value.indexOf(\"url(\")==\n0},getFillStyle:function(b){var d=this.getDefinition();return d!=null&&d.createGradient?d.createGradient(a.ctx,b):d!=null&&d.createPattern?d.createPattern(a.ctx,b):null}};this.Length={DPI:function(){return 96},EM:function(b){var d=12,c=new a.Property(\"fontSize\",a.Font.Parse(a.ctx.font).fontSize);c.hasValue()&&(d=c.Length.toPixels(b));return d},toPixels:function(d){if(!b.hasValue())return 0;var c=b.value+\"\";return c.match(/em$/)?b.numValue()*this.EM(d):c.match(/ex$/)?b.numValue()*this.EM(d)/2:c.match(/px$/)?\nb.numValue():c.match(/pt$/)?b.numValue()*1.25:c.match(/pc$/)?b.numValue()*15:c.match(/cm$/)?b.numValue()*this.DPI(d)/2.54:c.match(/mm$/)?b.numValue()*this.DPI(d)/25.4:c.match(/in$/)?b.numValue()*this.DPI(d):c.match(/%$/)?b.numValue()*a.ViewPort.ComputeSize(d):b.numValue()}};this.Time={toMilliseconds:function(){if(!b.hasValue())return 0;var a=b.value+\"\";if(a.match(/s$/))return b.numValue()*1E3;a.match(/ms$/);return b.numValue()}};this.Angle={toRadians:function(){if(!b.hasValue())return 0;var a=b.value+\n\"\";return a.match(/deg$/)?b.numValue()*(Math.PI/180):a.match(/grad$/)?b.numValue()*(Math.PI/200):a.match(/rad$/)?b.numValue():b.numValue()*(Math.PI/180)}}};a.Font=new function(){this.Styles=[\"normal\",\"italic\",\"oblique\",\"inherit\"];this.Variants=[\"normal\",\"small-caps\",\"inherit\"];this.Weights=\"normal,bold,bolder,lighter,100,200,300,400,500,600,700,800,900,inherit\".split(\",\");this.CreateFont=function(d,b,c,e,f,g){g=g!=null?this.Parse(g):this.CreateFont(\"\",\"\",\"\",\"\",\"\",a.ctx.font);return{fontFamily:f||\ng.fontFamily,fontSize:e||g.fontSize,fontStyle:d||g.fontStyle,fontWeight:c||g.fontWeight,fontVariant:b||g.fontVariant,toString:function(){return[this.fontStyle,this.fontVariant,this.fontWeight,this.fontSize,this.fontFamily].join(\" \")}}};var c=this;this.Parse=function(d){for(var b={},d=a.trim(a.compressSpaces(d||\"\")).split(\" \"),k=!1,e=!1,f=!1,g=!1,j=\"\",h=0;h<d.length;h++)if(!e&&c.Styles.indexOf(d[h])!=-1){if(d[h]!=\"inherit\")b.fontStyle=d[h];e=!0}else if(!g&&c.Variants.indexOf(d[h])!=-1){if(d[h]!=\"inherit\")b.fontVariant=\nd[h];e=g=!0}else if(!f&&c.Weights.indexOf(d[h])!=-1){if(d[h]!=\"inherit\")b.fontWeight=d[h];e=g=f=!0}else if(k)d[h]!=\"inherit\"&&(j+=d[h]);else{if(d[h]!=\"inherit\")b.fontSize=d[h].split(\"/\")[0];e=g=f=k=!0}if(j!=\"\")b.fontFamily=j;return b}};a.ToNumberArray=function(c){for(var c=a.trim(a.compressSpaces((c||\"\").replace(/,/g,\" \"))).split(\" \"),d=0;d<c.length;d++)c[d]=parseFloat(c[d]);return c};a.Point=function(a,d){this.x=a;this.y=d;this.angleTo=function(b){return Math.atan2(b.y-this.y,b.x-this.x)};this.applyTransform=\nfunction(b){var a=this.x*b[1]+this.y*b[3]+b[5];this.x=this.x*b[0]+this.y*b[2]+b[4];this.y=a}};a.CreatePoint=function(c){c=a.ToNumberArray(c);return new a.Point(c[0],c[1])};a.CreatePath=function(c){for(var c=a.ToNumberArray(c),d=[],b=0;b<c.length;b+=2)d.push(new a.Point(c[b],c[b+1]));return d};a.BoundingBox=function(a,d,b,k){this.y2=this.x2=this.y1=this.x1=Number.NaN;this.x=function(){return this.x1};this.y=function(){return this.y1};this.width=function(){return this.x2-this.x1};this.height=function(){return this.y2-\nthis.y1};this.addPoint=function(b,a){if(b!=null){if(isNaN(this.x1)||isNaN(this.x2))this.x2=this.x1=b;if(b<this.x1)this.x1=b;if(b>this.x2)this.x2=b}if(a!=null){if(isNaN(this.y1)||isNaN(this.y2))this.y2=this.y1=a;if(a<this.y1)this.y1=a;if(a>this.y2)this.y2=a}};this.addX=function(b){this.addPoint(b,null)};this.addY=function(b){this.addPoint(null,b)};this.addBoundingBox=function(b){this.addPoint(b.x1,b.y1);this.addPoint(b.x2,b.y2)};this.addQuadraticCurve=function(b,a,d,c,k,l){d=b+2/3*(d-b);c=a+2/3*(c-\na);this.addBezierCurve(b,a,d,d+1/3*(k-b),c,c+1/3*(l-a),k,l)};this.addBezierCurve=function(b,a,d,c,k,l,o,n){var q=[b,a],p=[d,c],t=[k,l],m=[o,n];this.addPoint(q[0],q[1]);this.addPoint(m[0],m[1]);for(i=0;i<=1;i++)b=function(b){return Math.pow(1-b,3)*q[i]+3*Math.pow(1-b,2)*b*p[i]+3*(1-b)*Math.pow(b,2)*t[i]+Math.pow(b,3)*m[i]},a=6*q[i]-12*p[i]+6*t[i],d=-3*q[i]+9*p[i]-9*t[i]+3*m[i],c=3*p[i]-3*q[i],d==0?a!=0&&(a=-c/a,0<a&&a<1&&(i==0&&this.addX(b(a)),i==1&&this.addY(b(a)))):(c=Math.pow(a,2)-4*c*d,c<0||(k=\n(-a+Math.sqrt(c))/(2*d),0<k&&k<1&&(i==0&&this.addX(b(k)),i==1&&this.addY(b(k))),a=(-a-Math.sqrt(c))/(2*d),0<a&&a<1&&(i==0&&this.addX(b(a)),i==1&&this.addY(b(a)))))};this.isPointInBox=function(b,a){return this.x1<=b&&b<=this.x2&&this.y1<=a&&a<=this.y2};this.addPoint(a,d);this.addPoint(b,k)};a.Transform=function(c){var d=this;this.Type={};this.Type.translate=function(b){this.p=a.CreatePoint(b);this.apply=function(b){b.translate(this.p.x||0,this.p.y||0)};this.applyToPoint=function(b){b.applyTransform([1,\n0,0,1,this.p.x||0,this.p.y||0])}};this.Type.rotate=function(b){b=a.ToNumberArray(b);this.angle=new a.Property(\"angle\",b[0]);this.cx=b[1]||0;this.cy=b[2]||0;this.apply=function(b){b.translate(this.cx,this.cy);b.rotate(this.angle.Angle.toRadians());b.translate(-this.cx,-this.cy)};this.applyToPoint=function(b){var a=this.angle.Angle.toRadians();b.applyTransform([1,0,0,1,this.p.x||0,this.p.y||0]);b.applyTransform([Math.cos(a),Math.sin(a),-Math.sin(a),Math.cos(a),0,0]);b.applyTransform([1,0,0,1,-this.p.x||\n0,-this.p.y||0])}};this.Type.scale=function(b){this.p=a.CreatePoint(b);this.apply=function(b){b.scale(this.p.x||1,this.p.y||this.p.x||1)};this.applyToPoint=function(b){b.applyTransform([this.p.x||0,0,0,this.p.y||0,0,0])}};this.Type.matrix=function(b){this.m=a.ToNumberArray(b);this.apply=function(b){b.transform(this.m[0],this.m[1],this.m[2],this.m[3],this.m[4],this.m[5])};this.applyToPoint=function(b){b.applyTransform(this.m)}};this.Type.SkewBase=function(b){this.base=d.Type.matrix;this.base(b);this.angle=\nnew a.Property(\"angle\",b)};this.Type.SkewBase.prototype=new this.Type.matrix;this.Type.skewX=function(b){this.base=d.Type.SkewBase;this.base(b);this.m=[1,0,Math.tan(this.angle.Angle.toRadians()),1,0,0]};this.Type.skewX.prototype=new this.Type.SkewBase;this.Type.skewY=function(b){this.base=d.Type.SkewBase;this.base(b);this.m=[1,Math.tan(this.angle.Angle.toRadians()),0,1,0,0]};this.Type.skewY.prototype=new this.Type.SkewBase;this.transforms=[];this.apply=function(b){for(var a=0;a<this.transforms.length;a++)this.transforms[a].apply(b)};\nthis.applyToPoint=function(b){for(var a=0;a<this.transforms.length;a++)this.transforms[a].applyToPoint(b)};for(var c=a.trim(a.compressSpaces(c)).split(/\\s(?=[a-z])/),b=0;b<c.length;b++){var k=c[b].split(\"(\")[0],e=c[b].split(\"(\")[1].replace(\")\",\"\");this.transforms.push(new this.Type[k](e))}};a.AspectRatio=function(c,d,b,k,e,f,g,j,h,l){var d=a.compressSpaces(d),d=d.replace(/^defer\\s/,\"\"),o=d.split(\" \")[0]||\"xMidYMid\",d=d.split(\" \")[1]||\"meet\",n=b/k,q=e/f,p=Math.min(n,q),m=Math.max(n,q);d==\"meet\"&&(k*=\np,f*=p);d==\"slice\"&&(k*=m,f*=m);h=new a.Property(\"refX\",h);l=new a.Property(\"refY\",l);h.hasValue()&&l.hasValue()?c.translate(-p*h.Length.toPixels(\"x\"),-p*l.Length.toPixels(\"y\")):(o.match(/^xMid/)&&(d==\"meet\"&&p==q||d==\"slice\"&&m==q)&&c.translate(b/2-k/2,0),o.match(/YMid$/)&&(d==\"meet\"&&p==n||d==\"slice\"&&m==n)&&c.translate(0,e/2-f/2),o.match(/^xMax/)&&(d==\"meet\"&&p==q||d==\"slice\"&&m==q)&&c.translate(b-k,0),o.match(/YMax$/)&&(d==\"meet\"&&p==n||d==\"slice\"&&m==n)&&c.translate(0,e-f));o==\"none\"?c.scale(n,\nq):d==\"meet\"?c.scale(p,p):d==\"slice\"&&c.scale(m,m);c.translate(g==null?0:-g,j==null?0:-j)};a.Element={};a.Element.ElementBase=function(c){this.attributes={};this.styles={};this.children=[];this.attribute=function(b,d){var c=this.attributes[b];if(c!=null)return c;c=new a.Property(b,\"\");d==!0&&(this.attributes[b]=c);return c};this.style=function(b,d){var c=this.styles[b];if(c!=null)return c;c=this.attribute(b);if(c!=null&&c.hasValue())return c;c=this.parent;if(c!=null&&(c=c.style(b),c!=null&&c.hasValue()))return c;\nc=new a.Property(b,\"\");d==!0&&(this.styles[b]=c);return c};this.render=function(b){if(this.style(\"display\").value!=\"none\"&&this.attribute(\"visibility\").value!=\"hidden\"){b.save();this.setContext(b);if(this.attribute(\"mask\").hasValue()){var a=this.attribute(\"mask\").Definition.getDefinition();a!=null&&a.apply(b,this)}else this.style(\"filter\").hasValue()?(a=this.style(\"filter\").Definition.getDefinition(),a!=null&&a.apply(b,this)):this.renderChildren(b);this.clearContext(b);b.restore()}};this.setContext=\nfunction(){};this.clearContext=function(){};this.renderChildren=function(b){for(var a=0;a<this.children.length;a++)this.children[a].render(b)};this.addChild=function(b,d){var c=b;d&&(c=a.CreateElement(b));c.parent=this;this.children.push(c)};if(c!=null&&c.nodeType==1){for(var d=0;d<c.childNodes.length;d++){var b=c.childNodes[d];b.nodeType==1&&this.addChild(b,!0)}for(d=0;d<c.attributes.length;d++)b=c.attributes[d],this.attributes[b.nodeName]=new a.Property(b.nodeName,b.nodeValue);b=a.Styles[c.nodeName];\nif(b!=null)for(var k in b)this.styles[k]=b[k];if(this.attribute(\"class\").hasValue())for(var d=a.compressSpaces(this.attribute(\"class\").value).split(\" \"),e=0;e<d.length;e++){b=a.Styles[\".\"+d[e]];if(b!=null)for(k in b)this.styles[k]=b[k];b=a.Styles[c.nodeName+\".\"+d[e]];if(b!=null)for(k in b)this.styles[k]=b[k]}if(this.attribute(\"style\").hasValue()){b=this.attribute(\"style\").value.split(\";\");for(d=0;d<b.length;d++)a.trim(b[d])!=\"\"&&(c=b[d].split(\":\"),k=a.trim(c[0]),c=a.trim(c[1]),this.styles[k]=new a.Property(k,\nc))}this.attribute(\"id\").hasValue()&&a.Definitions[this.attribute(\"id\").value]==null&&(a.Definitions[this.attribute(\"id\").value]=this)}};a.Element.RenderedElementBase=function(c){this.base=a.Element.ElementBase;this.base(c);this.setContext=function(d){if(this.style(\"fill\").Definition.isUrl()){var b=this.style(\"fill\").Definition.getFillStyle(this);if(b!=null)d.fillStyle=b}else if(this.style(\"fill\").hasValue())b=this.style(\"fill\"),this.style(\"fill-opacity\").hasValue()&&(b=b.Color.addOpacity(this.style(\"fill-opacity\").value)),\nd.fillStyle=b.value==\"none\"?\"rgba(0,0,0,0)\":b.value;if(this.style(\"stroke\").Definition.isUrl()){if(b=this.style(\"stroke\").Definition.getFillStyle(this),b!=null)d.strokeStyle=b}else if(this.style(\"stroke\").hasValue())b=this.style(\"stroke\"),this.style(\"stroke-opacity\").hasValue()&&(b=b.Color.addOpacity(this.style(\"stroke-opacity\").value)),d.strokeStyle=b.value==\"none\"?\"rgba(0,0,0,0)\":b.value;if(this.style(\"stroke-width\").hasValue())d.lineWidth=this.style(\"stroke-width\").Length.toPixels();if(this.style(\"stroke-linecap\").hasValue())d.lineCap=\nthis.style(\"stroke-linecap\").value;if(this.style(\"stroke-linejoin\").hasValue())d.lineJoin=this.style(\"stroke-linejoin\").value;if(this.style(\"stroke-miterlimit\").hasValue())d.miterLimit=this.style(\"stroke-miterlimit\").value;if(typeof d.font!=\"undefined\")d.font=a.Font.CreateFont(this.style(\"font-style\").value,this.style(\"font-variant\").value,this.style(\"font-weight\").value,this.style(\"font-size\").hasValue()?this.style(\"font-size\").Length.toPixels()+\"px\":\"\",this.style(\"font-family\").value).toString();\nthis.attribute(\"transform\").hasValue()&&(new a.Transform(this.attribute(\"transform\").value)).apply(d);this.attribute(\"clip-path\").hasValue()&&(b=this.attribute(\"clip-path\").Definition.getDefinition(),b!=null&&b.apply(d));if(this.style(\"opacity\").hasValue())d.globalAlpha=this.style(\"opacity\").numValue()}};a.Element.RenderedElementBase.prototype=new a.Element.ElementBase;a.Element.PathElementBase=function(c){this.base=a.Element.RenderedElementBase;this.base(c);this.path=function(d){d!=null&&d.beginPath();\nreturn new a.BoundingBox};this.renderChildren=function(d){this.path(d);a.Mouse.checkPath(this,d);d.fillStyle!=\"\"&&d.fill();d.strokeStyle!=\"\"&&d.stroke();var b=this.getMarkers();if(b!=null){if(this.style(\"marker-start\").Definition.isUrl()){var c=this.style(\"marker-start\").Definition.getDefinition();c.render(d,b[0][0],b[0][1])}if(this.style(\"marker-mid\").Definition.isUrl())for(var c=this.style(\"marker-mid\").Definition.getDefinition(),e=1;e<b.length-1;e++)c.render(d,b[e][0],b[e][1]);this.style(\"marker-end\").Definition.isUrl()&&\n(c=this.style(\"marker-end\").Definition.getDefinition(),c.render(d,b[b.length-1][0],b[b.length-1][1]))}};this.getBoundingBox=function(){return this.path()};this.getMarkers=function(){return null}};a.Element.PathElementBase.prototype=new a.Element.RenderedElementBase;a.Element.svg=function(c){this.base=a.Element.RenderedElementBase;this.base(c);this.baseClearContext=this.clearContext;this.clearContext=function(d){this.baseClearContext(d);a.ViewPort.RemoveCurrent()};this.baseSetContext=this.setContext;\nthis.setContext=function(d){d.strokeStyle=\"rgba(0,0,0,0)\";d.lineCap=\"butt\";d.lineJoin=\"miter\";d.miterLimit=4;this.baseSetContext(d);this.attribute(\"x\").hasValue()&&this.attribute(\"y\").hasValue()&&d.translate(this.attribute(\"x\").Length.toPixels(\"x\"),this.attribute(\"y\").Length.toPixels(\"y\"));var b=a.ViewPort.width(),c=a.ViewPort.height();if(typeof this.root==\"undefined\"&&this.attribute(\"width\").hasValue()&&this.attribute(\"height\").hasValue()){var b=this.attribute(\"width\").Length.toPixels(\"x\"),c=this.attribute(\"height\").Length.toPixels(\"y\"),\ne=0,f=0;this.attribute(\"refX\").hasValue()&&this.attribute(\"refY\").hasValue()&&(e=-this.attribute(\"refX\").Length.toPixels(\"x\"),f=-this.attribute(\"refY\").Length.toPixels(\"y\"));d.beginPath();d.moveTo(e,f);d.lineTo(b,f);d.lineTo(b,c);d.lineTo(e,c);d.closePath();d.clip()}a.ViewPort.SetCurrent(b,c);if(this.attribute(\"viewBox\").hasValue()){var e=a.ToNumberArray(this.attribute(\"viewBox\").value),f=e[0],g=e[1],b=e[2],c=e[3];a.AspectRatio(d,this.attribute(\"preserveAspectRatio\").value,a.ViewPort.width(),b,a.ViewPort.height(),\nc,f,g,this.attribute(\"refX\").value,this.attribute(\"refY\").value);a.ViewPort.RemoveCurrent();a.ViewPort.SetCurrent(e[2],e[3])}}};a.Element.svg.prototype=new a.Element.RenderedElementBase;a.Element.rect=function(c){this.base=a.Element.PathElementBase;this.base(c);this.path=function(d){var b=this.attribute(\"x\").Length.toPixels(\"x\"),c=this.attribute(\"y\").Length.toPixels(\"y\"),e=this.attribute(\"width\").Length.toPixels(\"x\"),f=this.attribute(\"height\").Length.toPixels(\"y\"),g=this.attribute(\"rx\").Length.toPixels(\"x\"),\nj=this.attribute(\"ry\").Length.toPixels(\"y\");this.attribute(\"rx\").hasValue()&&!this.attribute(\"ry\").hasValue()&&(j=g);this.attribute(\"ry\").hasValue()&&!this.attribute(\"rx\").hasValue()&&(g=j);d!=null&&(d.beginPath(),d.moveTo(b+g,c),d.lineTo(b+e-g,c),d.quadraticCurveTo(b+e,c,b+e,c+j),d.lineTo(b+e,c+f-j),d.quadraticCurveTo(b+e,c+f,b+e-g,c+f),d.lineTo(b+g,c+f),d.quadraticCurveTo(b,c+f,b,c+f-j),d.lineTo(b,c+j),d.quadraticCurveTo(b,c,b+g,c),d.closePath());return new a.BoundingBox(b,c,b+e,c+f)}};a.Element.rect.prototype=\nnew a.Element.PathElementBase;a.Element.circle=function(c){this.base=a.Element.PathElementBase;this.base(c);this.path=function(d){var b=this.attribute(\"cx\").Length.toPixels(\"x\"),c=this.attribute(\"cy\").Length.toPixels(\"y\"),e=this.attribute(\"r\").Length.toPixels();d!=null&&(d.beginPath(),d.arc(b,c,e,0,Math.PI*2,!0),d.closePath());return new a.BoundingBox(b-e,c-e,b+e,c+e)}};a.Element.circle.prototype=new a.Element.PathElementBase;a.Element.ellipse=function(c){this.base=a.Element.PathElementBase;this.base(c);\nthis.path=function(d){var b=4*((Math.sqrt(2)-1)/3),c=this.attribute(\"rx\").Length.toPixels(\"x\"),e=this.attribute(\"ry\").Length.toPixels(\"y\"),f=this.attribute(\"cx\").Length.toPixels(\"x\"),g=this.attribute(\"cy\").Length.toPixels(\"y\");d!=null&&(d.beginPath(),d.moveTo(f,g-e),d.bezierCurveTo(f+b*c,g-e,f+c,g-b*e,f+c,g),d.bezierCurveTo(f+c,g+b*e,f+b*c,g+e,f,g+e),d.bezierCurveTo(f-b*c,g+e,f-c,g+b*e,f-c,g),d.bezierCurveTo(f-c,g-b*e,f-b*c,g-e,f,g-e),d.closePath());return new a.BoundingBox(f-c,g-e,f+c,g+e)}};a.Element.ellipse.prototype=\nnew a.Element.PathElementBase;a.Element.line=function(c){this.base=a.Element.PathElementBase;this.base(c);this.getPoints=function(){return[new a.Point(this.attribute(\"x1\").Length.toPixels(\"x\"),this.attribute(\"y1\").Length.toPixels(\"y\")),new a.Point(this.attribute(\"x2\").Length.toPixels(\"x\"),this.attribute(\"y2\").Length.toPixels(\"y\"))]};this.path=function(d){var b=this.getPoints();d!=null&&(d.beginPath(),d.moveTo(b[0].x,b[0].y),d.lineTo(b[1].x,b[1].y));return new a.BoundingBox(b[0].x,b[0].y,b[1].x,b[1].y)};\nthis.getMarkers=function(){var a=this.getPoints(),b=a[0].angleTo(a[1]);return[[a[0],b],[a[1],b]]}};a.Element.line.prototype=new a.Element.PathElementBase;a.Element.polyline=function(c){this.base=a.Element.PathElementBase;this.base(c);this.points=a.CreatePath(this.attribute(\"points\").value);this.path=function(d){var b=new a.BoundingBox(this.points[0].x,this.points[0].y);d!=null&&(d.beginPath(),d.moveTo(this.points[0].x,this.points[0].y));for(var c=1;c<this.points.length;c++)b.addPoint(this.points[c].x,\nthis.points[c].y),d!=null&&d.lineTo(this.points[c].x,this.points[c].y);return b};this.getMarkers=function(){for(var a=[],b=0;b<this.points.length-1;b++)a.push([this.points[b],this.points[b].angleTo(this.points[b+1])]);a.push([this.points[this.points.length-1],a[a.length-1][1]]);return a}};a.Element.polyline.prototype=new a.Element.PathElementBase;a.Element.polygon=function(c){this.base=a.Element.polyline;this.base(c);this.basePath=this.path;this.path=function(a){var b=this.basePath(a);a!=null&&(a.lineTo(this.points[0].x,\nthis.points[0].y),a.closePath());return b}};a.Element.polygon.prototype=new a.Element.polyline;a.Element.path=function(c){this.base=a.Element.PathElementBase;this.base(c);c=this.attribute(\"d\").value;c=c.replace(/,/gm,\" \");c=c.replace(/([MmZzLlHhVvCcSsQqTtAa])([MmZzLlHhVvCcSsQqTtAa])/gm,\"$1 $2\");c=c.replace(/([MmZzLlHhVvCcSsQqTtAa])([MmZzLlHhVvCcSsQqTtAa])/gm,\"$1 $2\");c=c.replace(/([MmZzLlHhVvCcSsQqTtAa])([^\\s])/gm,\"$1 $2\");c=c.replace(/([^\\s])([MmZzLlHhVvCcSsQqTtAa])/gm,\"$1 $2\");c=c.replace(/([0-9])([+\\-])/gm,\n\"$1 $2\");c=c.replace(/(\\.[0-9]*)(\\.)/gm,\"$1 $2\");c=c.replace(/([Aa](\\s+[0-9]+){3})\\s+([01])\\s*([01])/gm,\"$1 $3 $4 \");c=a.compressSpaces(c);c=a.trim(c);this.PathParser=new function(d){this.tokens=d.split(\" \");this.reset=function(){this.i=-1;this.previousCommand=this.command=\"\";this.start=new a.Point(0,0);this.control=new a.Point(0,0);this.current=new a.Point(0,0);this.points=[];this.angles=[]};this.isEnd=function(){return this.i>=this.tokens.length-1};this.isCommandOrEnd=function(){return this.isEnd()?\n!0:this.tokens[this.i+1].match(/^[A-Za-z]$/)!=null};this.isRelativeCommand=function(){return this.command==this.command.toLowerCase()};this.getToken=function(){this.i+=1;return this.tokens[this.i]};this.getScalar=function(){return parseFloat(this.getToken())};this.nextCommand=function(){this.previousCommand=this.command;this.command=this.getToken()};this.getPoint=function(){return this.makeAbsolute(new a.Point(this.getScalar(),this.getScalar()))};this.getAsControlPoint=function(){var b=this.getPoint();\nreturn this.control=b};this.getAsCurrentPoint=function(){var b=this.getPoint();return this.current=b};this.getReflectedControlPoint=function(){return this.previousCommand.toLowerCase()!=\"c\"&&this.previousCommand.toLowerCase()!=\"s\"?this.current:new a.Point(2*this.current.x-this.control.x,2*this.current.y-this.control.y)};this.makeAbsolute=function(b){if(this.isRelativeCommand())b.x=this.current.x+b.x,b.y=this.current.y+b.y;return b};this.addMarker=function(b,a,d){d!=null&&this.angles.length>0&&this.angles[this.angles.length-\n1]==null&&(this.angles[this.angles.length-1]=this.points[this.points.length-1].angleTo(d));this.addMarkerAngle(b,a==null?null:a.angleTo(b))};this.addMarkerAngle=function(b,a){this.points.push(b);this.angles.push(a)};this.getMarkerPoints=function(){return this.points};this.getMarkerAngles=function(){for(var b=0;b<this.angles.length;b++)if(this.angles[b]==null)for(var a=b+1;a<this.angles.length;a++)if(this.angles[a]!=null){this.angles[b]=this.angles[a];break}return this.angles}}(c);this.path=function(d){var b=\nthis.PathParser;b.reset();var c=new a.BoundingBox;for(d!=null&&d.beginPath();!b.isEnd();)switch(b.nextCommand(),b.command.toUpperCase()){case \"M\":var e=b.getAsCurrentPoint();b.addMarker(e);c.addPoint(e.x,e.y);d!=null&&d.moveTo(e.x,e.y);for(b.start=b.current;!b.isCommandOrEnd();)e=b.getAsCurrentPoint(),b.addMarker(e,b.start),c.addPoint(e.x,e.y),d!=null&&d.lineTo(e.x,e.y);break;case \"L\":for(;!b.isCommandOrEnd();){var f=b.current,e=b.getAsCurrentPoint();b.addMarker(e,f);c.addPoint(e.x,e.y);d!=null&&\nd.lineTo(e.x,e.y)}break;case \"H\":for(;!b.isCommandOrEnd();)e=new a.Point((b.isRelativeCommand()?b.current.x:0)+b.getScalar(),b.current.y),b.addMarker(e,b.current),b.current=e,c.addPoint(b.current.x,b.current.y),d!=null&&d.lineTo(b.current.x,b.current.y);break;case \"V\":for(;!b.isCommandOrEnd();)e=new a.Point(b.current.x,(b.isRelativeCommand()?b.current.y:0)+b.getScalar()),b.addMarker(e,b.current),b.current=e,c.addPoint(b.current.x,b.current.y),d!=null&&d.lineTo(b.current.x,b.current.y);break;case \"C\":for(;!b.isCommandOrEnd();){var g=\nb.current,f=b.getPoint(),j=b.getAsControlPoint(),e=b.getAsCurrentPoint();b.addMarker(e,j,f);c.addBezierCurve(g.x,g.y,f.x,f.y,j.x,j.y,e.x,e.y);d!=null&&d.bezierCurveTo(f.x,f.y,j.x,j.y,e.x,e.y)}break;case \"S\":for(;!b.isCommandOrEnd();)g=b.current,f=b.getReflectedControlPoint(),j=b.getAsControlPoint(),e=b.getAsCurrentPoint(),b.addMarker(e,j,f),c.addBezierCurve(g.x,g.y,f.x,f.y,j.x,j.y,e.x,e.y),d!=null&&d.bezierCurveTo(f.x,f.y,j.x,j.y,e.x,e.y);break;case \"Q\":for(;!b.isCommandOrEnd();)g=b.current,j=b.getAsControlPoint(),\ne=b.getAsCurrentPoint(),b.addMarker(e,j,j),c.addQuadraticCurve(g.x,g.y,j.x,j.y,e.x,e.y),d!=null&&d.quadraticCurveTo(j.x,j.y,e.x,e.y);break;case \"T\":for(;!b.isCommandOrEnd();)g=b.current,j=b.getReflectedControlPoint(),b.control=j,e=b.getAsCurrentPoint(),b.addMarker(e,j,j),c.addQuadraticCurve(g.x,g.y,j.x,j.y,e.x,e.y),d!=null&&d.quadraticCurveTo(j.x,j.y,e.x,e.y);break;case \"A\":for(;!b.isCommandOrEnd();){var g=b.current,h=b.getScalar(),l=b.getScalar(),f=b.getScalar()*(Math.PI/180),o=b.getScalar(),j=b.getScalar(),\ne=b.getAsCurrentPoint(),n=new a.Point(Math.cos(f)*(g.x-e.x)/2+Math.sin(f)*(g.y-e.y)/2,-Math.sin(f)*(g.x-e.x)/2+Math.cos(f)*(g.y-e.y)/2),q=Math.pow(n.x,2)/Math.pow(h,2)+Math.pow(n.y,2)/Math.pow(l,2);q>1&&(h*=Math.sqrt(q),l*=Math.sqrt(q));o=(o==j?-1:1)*Math.sqrt((Math.pow(h,2)*Math.pow(l,2)-Math.pow(h,2)*Math.pow(n.y,2)-Math.pow(l,2)*Math.pow(n.x,2))/(Math.pow(h,2)*Math.pow(n.y,2)+Math.pow(l,2)*Math.pow(n.x,2)));isNaN(o)&&(o=0);var p=new a.Point(o*h*n.y/l,o*-l*n.x/h),g=new a.Point((g.x+e.x)/2+Math.cos(f)*\np.x-Math.sin(f)*p.y,(g.y+e.y)/2+Math.sin(f)*p.x+Math.cos(f)*p.y),m=function(b,a){return(b[0]*a[0]+b[1]*a[1])/(Math.sqrt(Math.pow(b[0],2)+Math.pow(b[1],2))*Math.sqrt(Math.pow(a[0],2)+Math.pow(a[1],2)))},s=function(b,a){return(b[0]*a[1]<b[1]*a[0]?-1:1)*Math.acos(m(b,a))},o=s([1,0],[(n.x-p.x)/h,(n.y-p.y)/l]),q=[(n.x-p.x)/h,(n.y-p.y)/l],p=[(-n.x-p.x)/h,(-n.y-p.y)/l],n=s(q,p);if(m(q,p)<=-1)n=Math.PI;m(q,p)>=1&&(n=0);j==0&&n>0&&(n-=2*Math.PI);j==1&&n<0&&(n+=2*Math.PI);q=new a.Point(g.x-h*Math.cos((o+n)/\n2),g.y-l*Math.sin((o+n)/2));b.addMarkerAngle(q,(o+n)/2+(j==0?1:-1)*Math.PI/2);b.addMarkerAngle(e,n+(j==0?1:-1)*Math.PI/2);c.addPoint(e.x,e.y);d!=null&&(m=h>l?h:l,e=h>l?1:h/l,h=h>l?l/h:1,d.translate(g.x,g.y),d.rotate(f),d.scale(e,h),d.arc(0,0,m,o,o+n,1-j),d.scale(1/e,1/h),d.rotate(-f),d.translate(-g.x,-g.y))}break;case \"Z\":d!=null&&d.closePath(),b.current=b.start}return c};this.getMarkers=function(){for(var a=this.PathParser.getMarkerPoints(),b=this.PathParser.getMarkerAngles(),c=[],e=0;e<a.length;e++)c.push([a[e],\nb[e]]);return c}};a.Element.path.prototype=new a.Element.PathElementBase;a.Element.pattern=function(c){this.base=a.Element.ElementBase;this.base(c);this.createPattern=function(d){var b=new a.Element.svg;b.attributes.viewBox=new a.Property(\"viewBox\",this.attribute(\"viewBox\").value);b.attributes.x=new a.Property(\"x\",this.attribute(\"x\").value);b.attributes.y=new a.Property(\"y\",this.attribute(\"y\").value);b.attributes.width=new a.Property(\"width\",this.attribute(\"width\").value);b.attributes.height=new a.Property(\"height\",\nthis.attribute(\"height\").value);b.children=this.children;var c=document.createElement(\"canvas\");c.width=this.attribute(\"width\").Length.toPixels(\"x\");c.height=this.attribute(\"height\").Length.toPixels(\"y\");b.render(c.getContext(\"2d\"));return d.createPattern(c,\"repeat\")}};a.Element.pattern.prototype=new a.Element.ElementBase;a.Element.marker=function(c){this.base=a.Element.ElementBase;this.base(c);this.baseRender=this.render;this.render=function(d,b,c){d.translate(b.x,b.y);this.attribute(\"orient\").valueOrDefault(\"auto\")==\n\"auto\"&&d.rotate(c);this.attribute(\"markerUnits\").valueOrDefault(\"strokeWidth\")==\"strokeWidth\"&&d.scale(d.lineWidth,d.lineWidth);d.save();var e=new a.Element.svg;e.attributes.viewBox=new a.Property(\"viewBox\",this.attribute(\"viewBox\").value);e.attributes.refX=new a.Property(\"refX\",this.attribute(\"refX\").value);e.attributes.refY=new a.Property(\"refY\",this.attribute(\"refY\").value);e.attributes.width=new a.Property(\"width\",this.attribute(\"markerWidth\").value);e.attributes.height=new a.Property(\"height\",\nthis.attribute(\"markerHeight\").value);e.attributes.fill=new a.Property(\"fill\",this.attribute(\"fill\").valueOrDefault(\"black\"));e.attributes.stroke=new a.Property(\"stroke\",this.attribute(\"stroke\").valueOrDefault(\"none\"));e.children=this.children;e.render(d);d.restore();this.attribute(\"markerUnits\").valueOrDefault(\"strokeWidth\")==\"strokeWidth\"&&d.scale(1/d.lineWidth,1/d.lineWidth);this.attribute(\"orient\").valueOrDefault(\"auto\")==\"auto\"&&d.rotate(-c);d.translate(-b.x,-b.y)}};a.Element.marker.prototype=\nnew a.Element.ElementBase;a.Element.defs=function(c){this.base=a.Element.ElementBase;this.base(c);this.render=function(){}};a.Element.defs.prototype=new a.Element.ElementBase;a.Element.GradientBase=function(c){this.base=a.Element.ElementBase;this.base(c);this.gradientUnits=this.attribute(\"gradientUnits\").valueOrDefault(\"objectBoundingBox\");this.stops=[];for(c=0;c<this.children.length;c++)this.stops.push(this.children[c]);this.getGradient=function(){};this.createGradient=function(d,b){var c=this;this.attribute(\"xlink:href\").hasValue()&&\n(c=this.attribute(\"xlink:href\").Definition.getDefinition());for(var e=this.getGradient(d,b),f=0;f<c.stops.length;f++)e.addColorStop(c.stops[f].offset,c.stops[f].color);if(this.attribute(\"gradientTransform\").hasValue()){c=a.ViewPort.viewPorts[0];f=new a.Element.rect;f.attributes.x=new a.Property(\"x\",-a.MAX_VIRTUAL_PIXELS/3);f.attributes.y=new a.Property(\"y\",-a.MAX_VIRTUAL_PIXELS/3);f.attributes.width=new a.Property(\"width\",a.MAX_VIRTUAL_PIXELS);f.attributes.height=new a.Property(\"height\",a.MAX_VIRTUAL_PIXELS);\nvar g=new a.Element.g;g.attributes.transform=new a.Property(\"transform\",this.attribute(\"gradientTransform\").value);g.children=[f];f=new a.Element.svg;f.attributes.x=new a.Property(\"x\",0);f.attributes.y=new a.Property(\"y\",0);f.attributes.width=new a.Property(\"width\",c.width);f.attributes.height=new a.Property(\"height\",c.height);f.children=[g];g=document.createElement(\"canvas\");g.width=c.width;g.height=c.height;c=g.getContext(\"2d\");c.fillStyle=e;f.render(c);return c.createPattern(g,\"no-repeat\")}return e}};\na.Element.GradientBase.prototype=new a.Element.ElementBase;a.Element.linearGradient=function(c){this.base=a.Element.GradientBase;this.base(c);this.getGradient=function(a,b){var c=b.getBoundingBox(),e=this.gradientUnits==\"objectBoundingBox\"?c.x()+c.width()*this.attribute(\"x1\").numValue():this.attribute(\"x1\").Length.toPixels(\"x\"),f=this.gradientUnits==\"objectBoundingBox\"?c.y()+c.height()*this.attribute(\"y1\").numValue():this.attribute(\"y1\").Length.toPixels(\"y\"),g=this.gradientUnits==\"objectBoundingBox\"?\nc.x()+c.width()*this.attribute(\"x2\").numValue():this.attribute(\"x2\").Length.toPixels(\"x\"),c=this.gradientUnits==\"objectBoundingBox\"?c.y()+c.height()*this.attribute(\"y2\").numValue():this.attribute(\"y2\").Length.toPixels(\"y\");return a.createLinearGradient(e,f,g,c)}};a.Element.linearGradient.prototype=new a.Element.GradientBase;a.Element.radialGradient=function(c){this.base=a.Element.GradientBase;this.base(c);this.getGradient=function(a,b){var c=b.getBoundingBox(),e=this.gradientUnits==\"objectBoundingBox\"?\nc.x()+c.width()*this.attribute(\"cx\").numValue():this.attribute(\"cx\").Length.toPixels(\"x\"),f=this.gradientUnits==\"objectBoundingBox\"?c.y()+c.height()*this.attribute(\"cy\").numValue():this.attribute(\"cy\").Length.toPixels(\"y\"),g=e,j=f;this.attribute(\"fx\").hasValue()&&(g=this.gradientUnits==\"objectBoundingBox\"?c.x()+c.width()*this.attribute(\"fx\").numValue():this.attribute(\"fx\").Length.toPixels(\"x\"));this.attribute(\"fy\").hasValue()&&(j=this.gradientUnits==\"objectBoundingBox\"?c.y()+c.height()*this.attribute(\"fy\").numValue():\nthis.attribute(\"fy\").Length.toPixels(\"y\"));c=this.gradientUnits==\"objectBoundingBox\"?(c.width()+c.height())/2*this.attribute(\"r\").numValue():this.attribute(\"r\").Length.toPixels();return a.createRadialGradient(g,j,0,e,f,c)}};a.Element.radialGradient.prototype=new a.Element.GradientBase;a.Element.stop=function(c){this.base=a.Element.ElementBase;this.base(c);this.offset=this.attribute(\"offset\").numValue();c=this.style(\"stop-color\");this.style(\"stop-opacity\").hasValue()&&(c=c.Color.addOpacity(this.style(\"stop-opacity\").value));\nthis.color=c.value};a.Element.stop.prototype=new a.Element.ElementBase;a.Element.AnimateBase=function(c){this.base=a.Element.ElementBase;this.base(c);a.Animations.push(this);this.duration=0;this.begin=this.attribute(\"begin\").Time.toMilliseconds();this.maxDuration=this.begin+this.attribute(\"dur\").Time.toMilliseconds();this.getProperty=function(){var a=this.attribute(\"attributeType\").value,b=this.attribute(\"attributeName\").value;return a==\"CSS\"?this.parent.style(b,!0):this.parent.attribute(b,!0)};this.initialValue=\nnull;this.removed=!1;this.calcValue=function(){return\"\"};this.update=function(a){if(this.initialValue==null)this.initialValue=this.getProperty().value;if(this.duration>this.maxDuration)if(this.attribute(\"repeatCount\").value==\"indefinite\")this.duration=0;else return this.attribute(\"fill\").valueOrDefault(\"remove\")==\"remove\"&&!this.removed?(this.removed=!0,this.getProperty().value=this.initialValue,!0):!1;this.duration+=a;a=!1;if(this.begin<this.duration)a=this.calcValue(),this.attribute(\"type\").hasValue()&&\n(a=this.attribute(\"type\").value+\"(\"+a+\")\"),this.getProperty().value=a,a=!0;return a};this.progress=function(){return(this.duration-this.begin)/(this.maxDuration-this.begin)}};a.Element.AnimateBase.prototype=new a.Element.ElementBase;a.Element.animate=function(c){this.base=a.Element.AnimateBase;this.base(c);this.calcValue=function(){var a=this.attribute(\"from\").numValue(),b=this.attribute(\"to\").numValue();return a+(b-a)*this.progress()}};a.Element.animate.prototype=new a.Element.AnimateBase;a.Element.animateColor=\nfunction(c){this.base=a.Element.AnimateBase;this.base(c);this.calcValue=function(){var a=new RGBColor(this.attribute(\"from\").value),b=new RGBColor(this.attribute(\"to\").value);if(a.ok&&b.ok){var c=a.r+(b.r-a.r)*this.progress(),e=a.g+(b.g-a.g)*this.progress(),a=a.b+(b.b-a.b)*this.progress();return\"rgb(\"+parseInt(c,10)+\",\"+parseInt(e,10)+\",\"+parseInt(a,10)+\")\"}return this.attribute(\"from\").value}};a.Element.animateColor.prototype=new a.Element.AnimateBase;a.Element.animateTransform=function(c){this.base=\na.Element.animate;this.base(c)};a.Element.animateTransform.prototype=new a.Element.animate;a.Element.font=function(c){this.base=a.Element.ElementBase;this.base(c);this.horizAdvX=this.attribute(\"horiz-adv-x\").numValue();this.isArabic=this.isRTL=!1;this.missingGlyph=this.fontFace=null;this.glyphs=[];for(c=0;c<this.children.length;c++){var d=this.children[c];if(d.type==\"font-face\")this.fontFace=d,d.style(\"font-family\").hasValue()&&(a.Definitions[d.style(\"font-family\").value]=this);else if(d.type==\"missing-glyph\")this.missingGlyph=\nd;else if(d.type==\"glyph\")d.arabicForm!=\"\"?(this.isArabic=this.isRTL=!0,typeof this.glyphs[d.unicode]==\"undefined\"&&(this.glyphs[d.unicode]=[]),this.glyphs[d.unicode][d.arabicForm]=d):this.glyphs[d.unicode]=d}};a.Element.font.prototype=new a.Element.ElementBase;a.Element.fontface=function(c){this.base=a.Element.ElementBase;this.base(c);this.ascent=this.attribute(\"ascent\").value;this.descent=this.attribute(\"descent\").value;this.unitsPerEm=this.attribute(\"units-per-em\").numValue()};a.Element.fontface.prototype=\nnew a.Element.ElementBase;a.Element.missingglyph=function(c){this.base=a.Element.path;this.base(c);this.horizAdvX=0};a.Element.missingglyph.prototype=new a.Element.path;a.Element.glyph=function(c){this.base=a.Element.path;this.base(c);this.horizAdvX=this.attribute(\"horiz-adv-x\").numValue();this.unicode=this.attribute(\"unicode\").value;this.arabicForm=this.attribute(\"arabic-form\").value};a.Element.glyph.prototype=new a.Element.path;a.Element.text=function(c){this.base=a.Element.RenderedElementBase;\nthis.base(c);if(c!=null){this.children=[];for(var d=0;d<c.childNodes.length;d++){var b=c.childNodes[d];b.nodeType==1?this.addChild(b,!0):b.nodeType==3&&this.addChild(new a.Element.tspan(b),!1)}}this.baseSetContext=this.setContext;this.setContext=function(b){this.baseSetContext(b);if(this.style(\"dominant-baseline\").hasValue())b.textBaseline=this.style(\"dominant-baseline\").value;if(this.style(\"alignment-baseline\").hasValue())b.textBaseline=this.style(\"alignment-baseline\").value};this.renderChildren=\nfunction(b){for(var a=this.style(\"text-anchor\").valueOrDefault(\"start\"),c=this.attribute(\"x\").Length.toPixels(\"x\"),d=this.attribute(\"y\").Length.toPixels(\"y\"),j=0;j<this.children.length;j++){var h=this.children[j];h.attribute(\"x\").hasValue()?h.x=h.attribute(\"x\").Length.toPixels(\"x\"):(h.attribute(\"dx\").hasValue()&&(c+=h.attribute(\"dx\").Length.toPixels(\"x\")),h.x=c);c=h.measureText(b);if(a!=\"start\"&&(j==0||h.attribute(\"x\").hasValue())){for(var l=c,o=j+1;o<this.children.length;o++){var n=this.children[o];\nif(n.attribute(\"x\").hasValue())break;l+=n.measureText(b)}h.x-=a==\"end\"?l:l/2}c=h.x+c;h.attribute(\"y\").hasValue()?h.y=h.attribute(\"y\").Length.toPixels(\"y\"):(h.attribute(\"dy\").hasValue()&&(d+=h.attribute(\"dy\").Length.toPixels(\"y\")),h.y=d);d=h.y;h.render(b)}}};a.Element.text.prototype=new a.Element.RenderedElementBase;a.Element.TextElementBase=function(c){this.base=a.Element.RenderedElementBase;this.base(c);this.getGlyph=function(a,b,c){var e=b[c],f=null;if(a.isArabic){var g=\"isolated\";if((c==0||b[c-\n1]==\" \")&&c<b.length-2&&b[c+1]!=\" \")g=\"terminal\";c>0&&b[c-1]!=\" \"&&c<b.length-2&&b[c+1]!=\" \"&&(g=\"medial\");if(c>0&&b[c-1]!=\" \"&&(c==b.length-1||b[c+1]==\" \"))g=\"initial\";typeof a.glyphs[e]!=\"undefined\"&&(f=a.glyphs[e][g],f==null&&a.glyphs[e].type==\"glyph\"&&(f=a.glyphs[e]))}else f=a.glyphs[e];if(f==null)f=a.missingGlyph;return f};this.renderChildren=function(c){var b=this.parent.style(\"font-family\").Definition.getDefinition();if(b!=null){var k=this.parent.style(\"font-size\").numValueOrDefault(a.Font.Parse(a.ctx.font).fontSize),\ne=this.parent.style(\"font-style\").valueOrDefault(a.Font.Parse(a.ctx.font).fontStyle),f=this.getText();b.isRTL&&(f=f.split(\"\").reverse().join(\"\"));for(var g=a.ToNumberArray(this.parent.attribute(\"dx\").value),j=0;j<f.length;j++){var h=this.getGlyph(b,f,j),l=k/b.fontFace.unitsPerEm;c.translate(this.x,this.y);c.scale(l,-l);var o=c.lineWidth;c.lineWidth=c.lineWidth*b.fontFace.unitsPerEm/k;e==\"italic\"&&c.transform(1,0,0.4,1,0,0);h.render(c);e==\"italic\"&&c.transform(1,0,-0.4,1,0,0);c.lineWidth=o;c.scale(1/\nl,-1/l);c.translate(-this.x,-this.y);this.x+=k*(h.horizAdvX||b.horizAdvX)/b.fontFace.unitsPerEm;typeof g[j]!=\"undefined\"&&!isNaN(g[j])&&(this.x+=g[j])}}else c.strokeStyle!=\"\"&&c.strokeText(a.compressSpaces(this.getText()),this.x,this.y),c.fillStyle!=\"\"&&c.fillText(a.compressSpaces(this.getText()),this.x,this.y)};this.getText=function(){};this.measureText=function(c){var b=this.parent.style(\"font-family\").Definition.getDefinition();if(b!=null){var c=this.parent.style(\"font-size\").numValueOrDefault(a.Font.Parse(a.ctx.font).fontSize),\nk=0,e=this.getText();b.isRTL&&(e=e.split(\"\").reverse().join(\"\"));for(var f=a.ToNumberArray(this.parent.attribute(\"dx\").value),g=0;g<e.length;g++){var j=this.getGlyph(b,e,g);k+=(j.horizAdvX||b.horizAdvX)*c/b.fontFace.unitsPerEm;typeof f[g]!=\"undefined\"&&!isNaN(f[g])&&(k+=f[g])}return k}b=a.compressSpaces(this.getText());if(!c.measureText)return b.length*10;c.save();this.setContext(c);b=c.measureText(b).width;c.restore();return b}};a.Element.TextElementBase.prototype=new a.Element.RenderedElementBase;\na.Element.tspan=function(c){this.base=a.Element.TextElementBase;this.base(c);this.text=c.nodeType==3?c.nodeValue:c.childNodes.length>0?c.childNodes[0].nodeValue:c.text;this.getText=function(){return this.text}};a.Element.tspan.prototype=new a.Element.TextElementBase;a.Element.tref=function(c){this.base=a.Element.TextElementBase;this.base(c);this.getText=function(){var a=this.attribute(\"xlink:href\").Definition.getDefinition();if(a!=null)return a.children[0].getText()}};a.Element.tref.prototype=new a.Element.TextElementBase;\na.Element.a=function(c){this.base=a.Element.TextElementBase;this.base(c);this.hasText=!0;for(var d=0;d<c.childNodes.length;d++)if(c.childNodes[d].nodeType!=3)this.hasText=!1;this.text=this.hasText?c.childNodes[0].nodeValue:\"\";this.getText=function(){return this.text};this.baseRenderChildren=this.renderChildren;this.renderChildren=function(b){if(this.hasText){this.baseRenderChildren(b);var c=new a.Property(\"fontSize\",a.Font.Parse(a.ctx.font).fontSize);a.Mouse.checkBoundingBox(this,new a.BoundingBox(this.x,\nthis.y-c.Length.toPixels(\"y\"),this.x+this.measureText(b),this.y))}else c=new a.Element.g,c.children=this.children,c.parent=this,c.render(b)};this.onclick=function(){window.open(this.attribute(\"xlink:href\").value)};this.onmousemove=function(){a.ctx.canvas.style.cursor=\"pointer\"}};a.Element.a.prototype=new a.Element.TextElementBase;a.Element.image=function(c){this.base=a.Element.RenderedElementBase;this.base(c);a.Images.push(this);this.img=document.createElement(\"img\");this.loaded=!1;var d=this;this.img.onload=\nfunction(){d.loaded=!0};this.img.src=this.attribute(\"xlink:href\").value;this.renderChildren=function(b){var c=this.attribute(\"x\").Length.toPixels(\"x\"),d=this.attribute(\"y\").Length.toPixels(\"y\"),f=this.attribute(\"width\").Length.toPixels(\"x\"),g=this.attribute(\"height\").Length.toPixels(\"y\");f==0||g==0||(b.save(),b.translate(c,d),a.AspectRatio(b,this.attribute(\"preserveAspectRatio\").value,f,this.img.width,g,this.img.height,0,0),b.drawImage(this.img,0,0),b.restore())}};a.Element.image.prototype=new a.Element.RenderedElementBase;\na.Element.g=function(c){this.base=a.Element.RenderedElementBase;this.base(c);this.getBoundingBox=function(){for(var c=new a.BoundingBox,b=0;b<this.children.length;b++)c.addBoundingBox(this.children[b].getBoundingBox());return c}};a.Element.g.prototype=new a.Element.RenderedElementBase;a.Element.symbol=function(c){this.base=a.Element.RenderedElementBase;this.base(c);this.baseSetContext=this.setContext;this.setContext=function(c){this.baseSetContext(c);if(this.attribute(\"viewBox\").hasValue()){var b=\na.ToNumberArray(this.attribute(\"viewBox\").value),k=b[0],e=b[1];width=b[2];height=b[3];a.AspectRatio(c,this.attribute(\"preserveAspectRatio\").value,this.attribute(\"width\").Length.toPixels(\"x\"),width,this.attribute(\"height\").Length.toPixels(\"y\"),height,k,e);a.ViewPort.SetCurrent(b[2],b[3])}}};a.Element.symbol.prototype=new a.Element.RenderedElementBase;a.Element.style=function(c){this.base=a.Element.ElementBase;this.base(c);for(var c=c.childNodes[0].nodeValue+(c.childNodes.length>1?c.childNodes[1].nodeValue:\n\"\"),c=c.replace(/(\\/\\*([^*]|[\\r\\n]|(\\*+([^*\\/]|[\\r\\n])))*\\*+\\/)|(^[\\s]*\\/\\/.*)/gm,\"\"),c=a.compressSpaces(c),c=c.split(\"}\"),d=0;d<c.length;d++)if(a.trim(c[d])!=\"\")for(var b=c[d].split(\"{\"),k=b[0].split(\",\"),b=b[1].split(\";\"),e=0;e<k.length;e++){var f=a.trim(k[e]);if(f!=\"\"){for(var g={},j=0;j<b.length;j++){var h=b[j].indexOf(\":\"),l=b[j].substr(0,h),h=b[j].substr(h+1,b[j].length-h);l!=null&&h!=null&&(g[a.trim(l)]=new a.Property(a.trim(l),a.trim(h)))}a.Styles[f]=g;if(f==\"@font-face\"){f=g[\"font-family\"].value.replace(/\"/g,\n\"\");g=g.src.value.split(\",\");for(j=0;j<g.length;j++)if(g[j].indexOf('format(\"svg\")')>0){l=g[j].indexOf(\"url\");h=g[j].indexOf(\")\",l);l=g[j].substr(l+5,h-l-6);l=a.parseXml(a.ajax(l)).getElementsByTagName(\"font\");for(h=0;h<l.length;h++){var o=a.CreateElement(l[h]);a.Definitions[f]=o}}}}}};a.Element.style.prototype=new a.Element.ElementBase;a.Element.use=function(c){this.base=a.Element.RenderedElementBase;this.base(c);this.baseSetContext=this.setContext;this.setContext=function(a){this.baseSetContext(a);\nthis.attribute(\"x\").hasValue()&&a.translate(this.attribute(\"x\").Length.toPixels(\"x\"),0);this.attribute(\"y\").hasValue()&&a.translate(0,this.attribute(\"y\").Length.toPixels(\"y\"))};this.getDefinition=function(){var a=this.attribute(\"xlink:href\").Definition.getDefinition();if(this.attribute(\"width\").hasValue())a.attribute(\"width\",!0).value=this.attribute(\"width\").value;if(this.attribute(\"height\").hasValue())a.attribute(\"height\",!0).value=this.attribute(\"height\").value;return a};this.path=function(a){var b=\nthis.getDefinition();b!=null&&b.path(a)};this.renderChildren=function(a){var b=this.getDefinition();b!=null&&b.render(a)}};a.Element.use.prototype=new a.Element.RenderedElementBase;a.Element.mask=function(c){this.base=a.Element.ElementBase;this.base(c);this.apply=function(a,b){var c=this.attribute(\"x\").Length.toPixels(\"x\"),e=this.attribute(\"y\").Length.toPixels(\"y\"),f=this.attribute(\"width\").Length.toPixels(\"x\"),g=this.attribute(\"height\").Length.toPixels(\"y\"),j=b.attribute(\"mask\").value;b.attribute(\"mask\").value=\n\"\";var h=document.createElement(\"canvas\");h.width=c+f;h.height=e+g;var l=h.getContext(\"2d\");this.renderChildren(l);var o=document.createElement(\"canvas\");o.width=c+f;o.height=e+g;var n=o.getContext(\"2d\");b.render(n);n.globalCompositeOperation=\"destination-in\";n.fillStyle=l.createPattern(h,\"no-repeat\");n.fillRect(0,0,c+f,e+g);a.fillStyle=n.createPattern(o,\"no-repeat\");a.fillRect(0,0,c+f,e+g);b.attribute(\"mask\").value=j};this.render=function(){}};a.Element.mask.prototype=new a.Element.ElementBase;a.Element.clipPath=\nfunction(c){this.base=a.Element.ElementBase;this.base(c);this.apply=function(a){for(var b=0;b<this.children.length;b++)this.children[b].path&&(this.children[b].path(a),a.clip())};this.render=function(){}};a.Element.clipPath.prototype=new a.Element.ElementBase;a.Element.filter=function(c){this.base=a.Element.ElementBase;this.base(c);this.apply=function(a,b){var c=b.getBoundingBox(),e=this.attribute(\"x\").Length.toPixels(\"x\"),f=this.attribute(\"y\").Length.toPixels(\"y\");if(e==0||f==0)e=c.x1,f=c.y1;var g=\nthis.attribute(\"width\").Length.toPixels(\"x\"),j=this.attribute(\"height\").Length.toPixels(\"y\");if(g==0||j==0)g=c.width(),j=c.height();c=b.style(\"filter\").value;b.style(\"filter\").value=\"\";var h=0.2*g,l=0.2*j,o=document.createElement(\"canvas\");o.width=g+2*h;o.height=j+2*l;var n=o.getContext(\"2d\");n.translate(-e+h,-f+l);b.render(n);for(var q=0;q<this.children.length;q++)this.children[q].apply(n,0,0,g+2*h,j+2*l);a.drawImage(o,0,0,g+2*h,j+2*l,e-h,f-l,g+2*h,j+2*l);b.style(\"filter\",!0).value=c};this.render=\nfunction(){}};a.Element.filter.prototype=new a.Element.ElementBase;a.Element.feGaussianBlur=function(c){function d(a,c,d,f,g){for(var j=0;j<g;j++)for(var h=0;h<f;h++)for(var l=a[j*f*4+h*4+3]/255,o=0;o<4;o++){for(var n=d[0]*(l==0?255:a[j*f*4+h*4+o])*(l==0||o==3?1:l),q=1;q<d.length;q++){var p=Math.max(h-q,0),m=a[j*f*4+p*4+3]/255,p=Math.min(h+q,f-1),p=a[j*f*4+p*4+3]/255,s=d[q],r;m==0?r=255:(r=Math.max(h-q,0),r=a[j*f*4+r*4+o]);m=r*(m==0||o==3?1:m);p==0?r=255:(r=Math.min(h+q,f-1),r=a[j*f*4+r*4+o]);n+=\ns*(m+r*(p==0||o==3?1:p))}c[h*g*4+j*4+o]=n}}this.base=a.Element.ElementBase;this.base(c);this.apply=function(a,c,e,f,g){var e=this.attribute(\"stdDeviation\").numValue(),c=a.getImageData(0,0,f,g),e=Math.max(e,0.01),j=Math.ceil(e*4)+1;mask=[];for(var h=0;h<j;h++)mask[h]=Math.exp(-0.5*(h/e)*(h/e));e=mask;j=0;for(h=1;h<e.length;h++)j+=Math.abs(e[h]);j=2*j+Math.abs(e[0]);for(h=0;h<e.length;h++)e[h]/=j;tmp=[];d(c.data,tmp,e,f,g);d(tmp,c.data,e,g,f);a.clearRect(0,0,f,g);a.putImageData(c,0,0)}};a.Element.filter.prototype=\nnew a.Element.feGaussianBlur;a.Element.title=function(){};a.Element.title.prototype=new a.Element.ElementBase;a.Element.desc=function(){};a.Element.desc.prototype=new a.Element.ElementBase;a.Element.MISSING=function(a){console.log(\"ERROR: Element '\"+a.nodeName+\"' not yet implemented.\")};a.Element.MISSING.prototype=new a.Element.ElementBase;a.CreateElement=function(c){var d=c.nodeName.replace(/^[^:]+:/,\"\"),d=d.replace(/\\-/g,\"\"),b=null,b=typeof a.Element[d]!=\"undefined\"?new a.Element[d](c):new a.Element.MISSING(c);\nb.type=c.nodeName;return b};a.load=function(c,d){a.loadXml(c,a.ajax(d))};a.loadXml=function(c,d){a.loadXmlDoc(c,a.parseXml(d))};a.loadXmlDoc=function(c,d){a.init(c);var b=function(a){for(var b=c.canvas;b;)a.x-=b.offsetLeft,a.y-=b.offsetTop,b=b.offsetParent;window.scrollX&&(a.x+=window.scrollX);window.scrollY&&(a.y+=window.scrollY);return a};if(a.opts.ignoreMouse!=!0)c.canvas.onclick=function(c){c=b(new a.Point(c!=null?c.clientX:event.clientX,c!=null?c.clientY:event.clientY));a.Mouse.onclick(c.x,c.y)},\nc.canvas.onmousemove=function(c){c=b(new a.Point(c!=null?c.clientX:event.clientX,c!=null?c.clientY:event.clientY));a.Mouse.onmousemove(c.x,c.y)};var k=a.CreateElement(d.documentElement),e=k.root=!0,f=function(){a.ViewPort.Clear();c.canvas.parentNode&&a.ViewPort.SetCurrent(c.canvas.parentNode.clientWidth,c.canvas.parentNode.clientHeight);if(a.opts.ignoreDimensions!=!0){if(k.style(\"width\").hasValue())c.canvas.width=k.style(\"width\").Length.toPixels(\"x\"),c.canvas.style.width=c.canvas.width+\"px\";if(k.style(\"height\").hasValue())c.canvas.height=\nk.style(\"height\").Length.toPixels(\"y\"),c.canvas.style.height=c.canvas.height+\"px\"}var b=c.canvas.clientWidth||c.canvas.width,d=c.canvas.clientHeight||c.canvas.height;a.ViewPort.SetCurrent(b,d);if(a.opts!=null&&a.opts.offsetX!=null)k.attribute(\"x\",!0).value=a.opts.offsetX;if(a.opts!=null&&a.opts.offsetY!=null)k.attribute(\"y\",!0).value=a.opts.offsetY;if(a.opts!=null&&a.opts.scaleWidth!=null&&a.opts.scaleHeight!=null){var f=1,g=1;k.attribute(\"width\").hasValue()&&(f=k.attribute(\"width\").Length.toPixels(\"x\")/\na.opts.scaleWidth);k.attribute(\"height\").hasValue()&&(g=k.attribute(\"height\").Length.toPixels(\"y\")/a.opts.scaleHeight);k.attribute(\"width\",!0).value=a.opts.scaleWidth;k.attribute(\"height\",!0).value=a.opts.scaleHeight;k.attribute(\"viewBox\",!0).value=\"0 0 \"+b*f+\" \"+d*g;k.attribute(\"preserveAspectRatio\",!0).value=\"none\"}a.opts.ignoreClear!=!0&&c.clearRect(0,0,b,d);k.render(c);e&&(e=!1,a.opts!=null&&typeof a.opts.renderCallback==\"function\"&&a.opts.renderCallback())},g=!0;a.ImagesLoaded()&&(g=!1,f());\na.intervalID=setInterval(function(){var b=!1;g&&a.ImagesLoaded()&&(g=!1,b=!0);a.opts.ignoreMouse!=!0&&(b|=a.Mouse.hasEvents());if(a.opts.ignoreAnimation!=!0)for(var c=0;c<a.Animations.length;c++)b|=a.Animations[c].update(1E3/a.FRAMERATE);a.opts!=null&&typeof a.opts.forceRedraw==\"function\"&&a.opts.forceRedraw()==!0&&(b=!0);b&&(f(),a.Mouse.runEvents())},1E3/a.FRAMERATE)};a.stop=function(){a.intervalID&&clearInterval(a.intervalID)};a.Mouse=new function(){this.events=[];this.hasEvents=function(){return this.events.length!=\n0};this.onclick=function(a,d){this.events.push({type:\"onclick\",x:a,y:d,run:function(a){if(a.onclick)a.onclick()}})};this.onmousemove=function(a,d){this.events.push({type:\"onmousemove\",x:a,y:d,run:function(a){if(a.onmousemove)a.onmousemove()}})};this.eventElements=[];this.checkPath=function(a,d){for(var b=0;b<this.events.length;b++){var k=this.events[b];d.isPointInPath&&d.isPointInPath(k.x,k.y)&&(this.eventElements[b]=a)}};this.checkBoundingBox=function(a,d){for(var b=0;b<this.events.length;b++){var k=\nthis.events[b];d.isPointInBox(k.x,k.y)&&(this.eventElements[b]=a)}};this.runEvents=function(){a.ctx.canvas.style.cursor=\"\";for(var c=0;c<this.events.length;c++)for(var d=this.events[c],b=this.eventElements[c];b;)d.run(b),b=b.parent;this.events=[];this.eventElements=[]}};return a}this.canvg=function(a,c,d){if(a==null&&c==null&&d==null)for(var c=document.getElementsByTagName(\"svg\"),b=0;b<c.length;b++){a=c[b];d=document.createElement(\"canvas\");d.width=a.clientWidth;d.height=a.clientHeight;a.parentNode.insertBefore(d,\na);a.parentNode.removeChild(a);var k=document.createElement(\"div\");k.appendChild(a);canvg(d,k.innerHTML)}else d=d||{},typeof a==\"string\"&&(a=document.getElementById(a)),a.svg==null?(b=m(),a.svg=b):(b=a.svg,b.stop()),b.opts=d,a=a.getContext(\"2d\"),typeof c.documentElement!=\"undefined\"?b.loadXmlDoc(a,c):c.substr(0,1)==\"<\"?b.loadXml(a,c):b.load(a,c)}})();\nif(CanvasRenderingContext2D)CanvasRenderingContext2D.prototype.drawSvg=function(m,a,c,d,b){canvg(this.canvas,m,{ignoreMouse:!0,ignoreAnimation:!0,ignoreDimensions:!0,ignoreClear:!0,offsetX:a,offsetY:c,scaleWidth:d,scaleHeight:b})};\n(function(m){var a=m.css,c=m.CanVGRenderer,d=m.SVGRenderer,b=m.extend,k=m.merge,e=m.addEvent,f=m.createElement,g=m.discardElement;b(c.prototype,d.prototype);b(c.prototype,{create:function(a,b,c,d){this.setContainer(b,c,d);this.configure(a)},setContainer:function(a,b,c){var d=a.style,e=a.parentNode,g=d.left,d=d.top,k=a.offsetWidth,m=a.offsetHeight,s={visibility:\"hidden\",position:\"absolute\"};this.init.apply(this,[a,b,c]);this.canvas=f(\"canvas\",{width:k,height:m},{position:\"relative\",left:g,top:d},a);\nthis.ttLine=f(\"div\",null,s,e);this.ttDiv=f(\"div\",null,s,e);this.ttTimer=void 0;this.hiddenSvg=a=f(\"div\",{width:k,height:m},{visibility:\"hidden\",left:g,top:d},e);a.appendChild(this.box)},configure:function(b){var c=this,d=b.options.tooltip,f=d.borderWidth,g=c.ttDiv,m=d.style,p=c.ttLine,t=parseInt(m.padding,10),m=k(m,{padding:t+\"px\",\"background-color\":d.backgroundColor,\"border-style\":\"solid\",\"border-width\":f+\"px\",\"border-radius\":d.borderRadius+\"px\"});d.shadow&&(m=k(m,{\"box-shadow\":\"1px 1px 3px gray\",\n\"-webkit-box-shadow\":\"1px 1px 3px gray\"}));a(g,m);a(p,{\"border-left\":\"1px solid darkgray\"});e(b,\"tooltipRefresh\",function(d){var e=b.container,f=e.offsetLeft,e=e.offsetTop,k;g.innerHTML=d.text;k=b.tooltip.getPosition(g.offsetWidth,g.offsetHeight,{plotX:d.x,plotY:d.y});a(g,{visibility:\"visible\",left:k.x+\"px\",top:k.y+\"px\",\"border-color\":d.borderColor});a(p,{visibility:\"visible\",left:f+d.x+\"px\",top:e+b.plotTop+\"px\",height:b.plotHeight+\"px\"});c.ttTimer!==void 0&&clearTimeout(c.ttTimer);c.ttTimer=setTimeout(function(){a(g,\n{visibility:\"hidden\"});a(p,{visibility:\"hidden\"})},3E3)})},destroy:function(){g(this.canvas);this.ttTimer!==void 0&&clearTimeout(this.ttTimer);g(this.ttLine);g(this.ttDiv);g(this.hiddenSvg);return d.prototype.destroy.apply(this)},color:function(a,b,c){a&&a.linearGradient&&(a=a.stops[a.stops.length-1][1]);return d.prototype.color.call(this,a,b,c)},draw:function(){window.canvg(this.canvas,this.hiddenSvg.innerHTML)}})})(Highcharts);\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/highchart3/js/modules/canvas-tools.src.js",
    "content": "/**\n * @license A class to parse color values\n * @author Stoyan Stefanov <sstoo@gmail.com>\n * @link   http://www.phpied.com/rgb-color-parser-in-javascript/\n * Use it if you like it\n *\n */\nfunction RGBColor(color_string)\n{\n    this.ok = false;\n\n    // strip any leading #\n    if (color_string.charAt(0) == '#') { // remove # if any\n        color_string = color_string.substr(1,6);\n    }\n\n    color_string = color_string.replace(/ /g,'');\n    color_string = color_string.toLowerCase();\n\n    // before getting into regexps, try simple matches\n    // and overwrite the input\n    var simple_colors = {\n        aliceblue: 'f0f8ff',\n        antiquewhite: 'faebd7',\n        aqua: '00ffff',\n        aquamarine: '7fffd4',\n        azure: 'f0ffff',\n        beige: 'f5f5dc',\n        bisque: 'ffe4c4',\n        black: '000000',\n        blanchedalmond: 'ffebcd',\n        blue: '0000ff',\n        blueviolet: '8a2be2',\n        brown: 'a52a2a',\n        burlywood: 'deb887',\n        cadetblue: '5f9ea0',\n        chartreuse: '7fff00',\n        chocolate: 'd2691e',\n        coral: 'ff7f50',\n        cornflowerblue: '6495ed',\n        cornsilk: 'fff8dc',\n        crimson: 'dc143c',\n        cyan: '00ffff',\n        darkblue: '00008b',\n        darkcyan: '008b8b',\n        darkgoldenrod: 'b8860b',\n        darkgray: 'a9a9a9',\n        darkgreen: '006400',\n        darkkhaki: 'bdb76b',\n        darkmagenta: '8b008b',\n        darkolivegreen: '556b2f',\n        darkorange: 'ff8c00',\n        darkorchid: '9932cc',\n        darkred: '8b0000',\n        darksalmon: 'e9967a',\n        darkseagreen: '8fbc8f',\n        darkslateblue: '483d8b',\n        darkslategray: '2f4f4f',\n        darkturquoise: '00ced1',\n        darkviolet: '9400d3',\n        deeppink: 'ff1493',\n        deepskyblue: '00bfff',\n        dimgray: '696969',\n        dodgerblue: '1e90ff',\n        feldspar: 'd19275',\n        firebrick: 'b22222',\n        floralwhite: 'fffaf0',\n        forestgreen: '228b22',\n        fuchsia: 'ff00ff',\n        gainsboro: 'dcdcdc',\n        ghostwhite: 'f8f8ff',\n        gold: 'ffd700',\n        goldenrod: 'daa520',\n        gray: '808080',\n        green: '008000',\n        greenyellow: 'adff2f',\n        honeydew: 'f0fff0',\n        hotpink: 'ff69b4',\n        indianred : 'cd5c5c',\n        indigo : '4b0082',\n        ivory: 'fffff0',\n        khaki: 'f0e68c',\n        lavender: 'e6e6fa',\n        lavenderblush: 'fff0f5',\n        lawngreen: '7cfc00',\n        lemonchiffon: 'fffacd',\n        lightblue: 'add8e6',\n        lightcoral: 'f08080',\n        lightcyan: 'e0ffff',\n        lightgoldenrodyellow: 'fafad2',\n        lightgrey: 'd3d3d3',\n        lightgreen: '90ee90',\n        lightpink: 'ffb6c1',\n        lightsalmon: 'ffa07a',\n        lightseagreen: '20b2aa',\n        lightskyblue: '87cefa',\n        lightslateblue: '8470ff',\n        lightslategray: '778899',\n        lightsteelblue: 'b0c4de',\n        lightyellow: 'ffffe0',\n        lime: '00ff00',\n        limegreen: '32cd32',\n        linen: 'faf0e6',\n        magenta: 'ff00ff',\n        maroon: '800000',\n        mediumaquamarine: '66cdaa',\n        mediumblue: '0000cd',\n        mediumorchid: 'ba55d3',\n        mediumpurple: '9370d8',\n        mediumseagreen: '3cb371',\n        mediumslateblue: '7b68ee',\n        mediumspringgreen: '00fa9a',\n        mediumturquoise: '48d1cc',\n        mediumvioletred: 'c71585',\n        midnightblue: '191970',\n        mintcream: 'f5fffa',\n        mistyrose: 'ffe4e1',\n        moccasin: 'ffe4b5',\n        navajowhite: 'ffdead',\n        navy: '000080',\n        oldlace: 'fdf5e6',\n        olive: '808000',\n        olivedrab: '6b8e23',\n        orange: 'ffa500',\n        orangered: 'ff4500',\n        orchid: 'da70d6',\n        palegoldenrod: 'eee8aa',\n        palegreen: '98fb98',\n        paleturquoise: 'afeeee',\n        palevioletred: 'd87093',\n        papayawhip: 'ffefd5',\n        peachpuff: 'ffdab9',\n        peru: 'cd853f',\n        pink: 'ffc0cb',\n        plum: 'dda0dd',\n        powderblue: 'b0e0e6',\n        purple: '800080',\n        red: 'ff0000',\n        rosybrown: 'bc8f8f',\n        royalblue: '4169e1',\n        saddlebrown: '8b4513',\n        salmon: 'fa8072',\n        sandybrown: 'f4a460',\n        seagreen: '2e8b57',\n        seashell: 'fff5ee',\n        sienna: 'a0522d',\n        silver: 'c0c0c0',\n        skyblue: '87ceeb',\n        slateblue: '6a5acd',\n        slategray: '708090',\n        snow: 'fffafa',\n        springgreen: '00ff7f',\n        steelblue: '4682b4',\n        tan: 'd2b48c',\n        teal: '008080',\n        thistle: 'd8bfd8',\n        tomato: 'ff6347',\n        turquoise: '40e0d0',\n        violet: 'ee82ee',\n        violetred: 'd02090',\n        wheat: 'f5deb3',\n        white: 'ffffff',\n        whitesmoke: 'f5f5f5',\n        yellow: 'ffff00',\n        yellowgreen: '9acd32'\n    };\n    for (var key in simple_colors) {\n        if (color_string == key) {\n            color_string = simple_colors[key];\n        }\n    }\n    // emd of simple type-in colors\n\n    // array of color definition objects\n    var color_defs = [\n        {\n            re: /^rgb\\((\\d{1,3}),\\s*(\\d{1,3}),\\s*(\\d{1,3})\\)$/,\n            example: ['rgb(123, 234, 45)', 'rgb(255,234,245)'],\n            process: function (bits){\n                return [\n                    parseInt(bits[1]),\n                    parseInt(bits[2]),\n                    parseInt(bits[3])\n                ];\n            }\n        },\n        {\n            re: /^(\\w{2})(\\w{2})(\\w{2})$/,\n            example: ['#00ff00', '336699'],\n            process: function (bits){\n                return [\n                    parseInt(bits[1], 16),\n                    parseInt(bits[2], 16),\n                    parseInt(bits[3], 16)\n                ];\n            }\n        },\n        {\n            re: /^(\\w{1})(\\w{1})(\\w{1})$/,\n            example: ['#fb0', 'f0f'],\n            process: function (bits){\n                return [\n                    parseInt(bits[1] + bits[1], 16),\n                    parseInt(bits[2] + bits[2], 16),\n                    parseInt(bits[3] + bits[3], 16)\n                ];\n            }\n        }\n    ];\n\n    // search through the definitions to find a match\n    for (var i = 0; i < color_defs.length; i++) {\n        var re = color_defs[i].re;\n        var processor = color_defs[i].process;\n        var bits = re.exec(color_string);\n        if (bits) {\n            channels = processor(bits);\n            this.r = channels[0];\n            this.g = channels[1];\n            this.b = channels[2];\n            this.ok = true;\n        }\n\n    }\n\n    // validate/cleanup values\n    this.r = (this.r < 0 || isNaN(this.r)) ? 0 : ((this.r > 255) ? 255 : this.r);\n    this.g = (this.g < 0 || isNaN(this.g)) ? 0 : ((this.g > 255) ? 255 : this.g);\n    this.b = (this.b < 0 || isNaN(this.b)) ? 0 : ((this.b > 255) ? 255 : this.b);\n\n    // some getters\n    this.toRGB = function () {\n        return 'rgb(' + this.r + ', ' + this.g + ', ' + this.b + ')';\n    }\n    this.toHex = function () {\n        var r = this.r.toString(16);\n        var g = this.g.toString(16);\n        var b = this.b.toString(16);\n        if (r.length == 1) r = '0' + r;\n        if (g.length == 1) g = '0' + g;\n        if (b.length == 1) b = '0' + b;\n        return '#' + r + g + b;\n    }\n\n    // help\n    this.getHelpXML = function () {\n\n        var examples = new Array();\n        // add regexps\n        for (var i = 0; i < color_defs.length; i++) {\n            var example = color_defs[i].example;\n            for (var j = 0; j < example.length; j++) {\n                examples[examples.length] = example[j];\n            }\n        }\n        // add type-in colors\n        for (var sc in simple_colors) {\n            examples[examples.length] = sc;\n        }\n\n        var xml = document.createElement('ul');\n        xml.setAttribute('id', 'rgbcolor-examples');\n        for (var i = 0; i < examples.length; i++) {\n            try {\n                var list_item = document.createElement('li');\n                var list_color = new RGBColor(examples[i]);\n                var example_div = document.createElement('div');\n                example_div.style.cssText =\n                        'margin: 3px; '\n                        + 'border: 1px solid black; '\n                        + 'background:' + list_color.toHex() + '; '\n                        + 'color:' + list_color.toHex()\n                ;\n                example_div.appendChild(document.createTextNode('test'));\n                var list_item_value = document.createTextNode(\n                    ' ' + examples[i] + ' -> ' + list_color.toRGB() + ' -> ' + list_color.toHex()\n                );\n                list_item.appendChild(example_div);\n                list_item.appendChild(list_item_value);\n                xml.appendChild(list_item);\n\n            } catch(e){}\n        }\n        return xml;\n\n    }\n\n}\n\n/**\n * @license canvg.js - Javascript SVG parser and renderer on Canvas\n * MIT Licensed \n * Gabe Lerner (gabelerner@gmail.com)\n * http://code.google.com/p/canvg/\n *\n * Requires: rgbcolor.js - http://www.phpied.com/rgb-color-parser-in-javascript/\n *\n */\nif(!window.console) {\n\twindow.console = {};\n\twindow.console.log = function(str) {};\n\twindow.console.dir = function(str) {};\n}\n\nif(!Array.prototype.indexOf){\n\tArray.prototype.indexOf = function(obj){\n\t\tfor(var i=0; i<this.length; i++){\n\t\t\tif(this[i]==obj){\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\t\treturn -1;\n\t}\n}\n\n(function(){\n\t// canvg(target, s)\n\t// empty parameters: replace all 'svg' elements on page with 'canvas' elements\n\t// target: canvas element or the id of a canvas element\n\t// s: svg string, url to svg file, or xml document\n\t// opts: optional hash of options\n\t//\t\t ignoreMouse: true => ignore mouse events\n\t//\t\t ignoreAnimation: true => ignore animations\n\t//\t\t ignoreDimensions: true => does not try to resize canvas\n\t//\t\t ignoreClear: true => does not clear canvas\n\t//\t\t offsetX: int => draws at a x offset\n\t//\t\t offsetY: int => draws at a y offset\n\t//\t\t scaleWidth: int => scales horizontally to width\n\t//\t\t scaleHeight: int => scales vertically to height\n\t//\t\t renderCallback: function => will call the function after the first render is completed\n\t//\t\t forceRedraw: function => will call the function on every frame, if it returns true, will redraw\n\tthis.canvg = function (target, s, opts) {\n\t\t// no parameters\n\t\tif (target == null && s == null && opts == null) {\n\t\t\tvar svgTags = document.getElementsByTagName('svg');\n\t\t\tfor (var i=0; i<svgTags.length; i++) {\n\t\t\t\tvar svgTag = svgTags[i];\n\t\t\t\tvar c = document.createElement('canvas');\n\t\t\t\tc.width = svgTag.clientWidth;\n\t\t\t\tc.height = svgTag.clientHeight;\n\t\t\t\tsvgTag.parentNode.insertBefore(c, svgTag);\n\t\t\t\tsvgTag.parentNode.removeChild(svgTag);\n\t\t\t\tvar div = document.createElement('div');\n\t\t\t\tdiv.appendChild(svgTag);\n\t\t\t\tcanvg(c, div.innerHTML);\n\t\t\t}\n\t\t\treturn;\n\t\t}\t\n\t\topts = opts || {};\n\t\n\t\tif (typeof target == 'string') {\n\t\t\ttarget = document.getElementById(target);\n\t\t}\n\t\t\n\t\t// reuse class per canvas\n\t\tvar svg;\n\t\tif (target.svg == null) {\n\t\t\tsvg = build();\n\t\t\ttarget.svg = svg;\n\t\t}\n\t\telse {\n\t\t\tsvg = target.svg;\n\t\t\tsvg.stop();\n\t\t}\n\t\tsvg.opts = opts;\n\t\t\n\t\tvar ctx = target.getContext('2d');\n\t\tif (typeof(s.documentElement) != 'undefined') {\n\t\t\t// load from xml doc\n\t\t\tsvg.loadXmlDoc(ctx, s);\n\t\t}\n\t\telse if (s.substr(0,1) == '<') {\n\t\t\t// load from xml string\n\t\t\tsvg.loadXml(ctx, s);\n\t\t}\n\t\telse {\n\t\t\t// load from url\n\t\t\tsvg.load(ctx, s);\n\t\t}\n\t}\n\n\tfunction build() {\n\t\tvar svg = { };\n\t\t\n\t\tsvg.FRAMERATE = 30;\n\t\tsvg.MAX_VIRTUAL_PIXELS = 30000;\n\t\t\n\t\t// globals\n\t\tsvg.init = function(ctx) {\n\t\t\tsvg.Definitions = {};\n\t\t\tsvg.Styles = {};\n\t\t\tsvg.Animations = [];\n\t\t\tsvg.Images = [];\n\t\t\tsvg.ctx = ctx;\n\t\t\tsvg.ViewPort = new (function () {\n\t\t\t\tthis.viewPorts = [];\n\t\t\t\tthis.Clear = function() { this.viewPorts = []; }\n\t\t\t\tthis.SetCurrent = function(width, height) { this.viewPorts.push({ width: width, height: height }); }\n\t\t\t\tthis.RemoveCurrent = function() { this.viewPorts.pop(); }\n\t\t\t\tthis.Current = function() { return this.viewPorts[this.viewPorts.length - 1]; }\n\t\t\t\tthis.width = function() { return this.Current().width; }\n\t\t\t\tthis.height = function() { return this.Current().height; }\n\t\t\t\tthis.ComputeSize = function(d) {\n\t\t\t\t\tif (d != null && typeof(d) == 'number') return d;\n\t\t\t\t\tif (d == 'x') return this.width();\n\t\t\t\t\tif (d == 'y') return this.height();\n\t\t\t\t\treturn Math.sqrt(Math.pow(this.width(), 2) + Math.pow(this.height(), 2)) / Math.sqrt(2);\t\t\t\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\tsvg.init();\n\t\t\n\t\t// images loaded\n\t\tsvg.ImagesLoaded = function() { \n\t\t\tfor (var i=0; i<svg.Images.length; i++) {\n\t\t\t\tif (!svg.Images[i].loaded) return false;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\n\t\t// trim\n\t\tsvg.trim = function(s) { return s.replace(/^\\s+|\\s+$/g, ''); }\n\t\t\n\t\t// compress spaces\n\t\tsvg.compressSpaces = function(s) { return s.replace(/[\\s\\r\\t\\n]+/gm,' '); }\n\t\t\n\t\t// ajax\n\t\tsvg.ajax = function(url) {\n\t\t\tvar AJAX;\n\t\t\tif(window.XMLHttpRequest){AJAX=new XMLHttpRequest();}\n\t\t\telse{AJAX=new ActiveXObject('Microsoft.XMLHTTP');}\n\t\t\tif(AJAX){\n\t\t\t   AJAX.open('GET',url,false);\n\t\t\t   AJAX.send(null);\n\t\t\t   return AJAX.responseText;\n\t\t\t}\n\t\t\treturn null;\n\t\t} \n\t\t\n\t\t// parse xml\n\t\tsvg.parseXml = function(xml) {\n\t\t\tif (window.DOMParser)\n\t\t\t{\n\t\t\t\tvar parser = new DOMParser();\n\t\t\t\treturn parser.parseFromString(xml, 'text/xml');\n\t\t\t}\n\t\t\telse \n\t\t\t{\n\t\t\t\txml = xml.replace(/<!DOCTYPE svg[^>]*>/, '');\n\t\t\t\tvar xmlDoc = new ActiveXObject('Microsoft.XMLDOM');\n\t\t\t\txmlDoc.async = 'false';\n\t\t\t\txmlDoc.loadXML(xml); \n\t\t\t\treturn xmlDoc;\n\t\t\t}\t\t\n\t\t}\n\t\t\n\t\tsvg.Property = function(name, value) {\n\t\t\tthis.name = name;\n\t\t\tthis.value = value;\n\t\t\t\n\t\t\tthis.hasValue = function() {\n\t\t\t\treturn (this.value != null && this.value !== '');\n\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t// return the numerical value of the property\n\t\t\tthis.numValue = function() {\n\t\t\t\tif (!this.hasValue()) return 0;\n\t\t\t\t\n\t\t\t\tvar n = parseFloat(this.value);\n\t\t\t\tif ((this.value + '').match(/%$/)) {\n\t\t\t\t\tn = n / 100.0;\n\t\t\t\t}\n\t\t\t\treturn n;\n\t\t\t}\n\t\t\t\n\t\t\tthis.valueOrDefault = function(def) {\n\t\t\t\tif (this.hasValue()) return this.value;\n\t\t\t\treturn def;\n\t\t\t}\n\t\t\t\n\t\t\tthis.numValueOrDefault = function(def) {\n\t\t\t\tif (this.hasValue()) return this.numValue();\n\t\t\t\treturn def;\n\t\t\t}\n\t\t\t\n\t\t\t/* EXTENSIONS */\n\t\t\tvar that = this;\n\t\t\t\n\t\t\t// color extensions\n\t\t\tthis.Color = {\n\t\t\t\t// augment the current color value with the opacity\n\t\t\t\taddOpacity: function(opacity) {\n\t\t\t\t\tvar newValue = that.value;\n\t\t\t\t\tif (opacity != null && opacity != '') {\n\t\t\t\t\t\tvar color = new RGBColor(that.value);\n\t\t\t\t\t\tif (color.ok) {\n\t\t\t\t\t\t\tnewValue = 'rgba(' + color.r + ', ' + color.g + ', ' + color.b + ', ' + opacity + ')';\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn new svg.Property(that.name, newValue);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t// definition extensions\n\t\t\tthis.Definition = {\n\t\t\t\t// get the definition from the definitions table\n\t\t\t\tgetDefinition: function() {\n\t\t\t\t\tvar name = that.value.replace(/^(url\\()?#([^\\)]+)\\)?$/, '$2');\n\t\t\t\t\treturn svg.Definitions[name];\n\t\t\t\t},\n\t\t\t\t\n\t\t\t\tisUrl: function() {\n\t\t\t\t\treturn that.value.indexOf('url(') == 0\n\t\t\t\t},\n\t\t\t\t\n\t\t\t\tgetFillStyle: function(e) {\n\t\t\t\t\tvar def = this.getDefinition();\n\t\t\t\t\t\n\t\t\t\t\t// gradient\n\t\t\t\t\tif (def != null && def.createGradient) {\n\t\t\t\t\t\treturn def.createGradient(svg.ctx, e);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t// pattern\n\t\t\t\t\tif (def != null && def.createPattern) {\n\t\t\t\t\t\treturn def.createPattern(svg.ctx, e);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t// length extensions\n\t\t\tthis.Length = {\n\t\t\t\tDPI: function(viewPort) {\n\t\t\t\t\treturn 96.0; // TODO: compute?\n\t\t\t\t},\n\t\t\t\t\n\t\t\t\tEM: function(viewPort) {\n\t\t\t\t\tvar em = 12;\n\t\t\t\t\t\n\t\t\t\t\tvar fontSize = new svg.Property('fontSize', svg.Font.Parse(svg.ctx.font).fontSize);\n\t\t\t\t\tif (fontSize.hasValue()) em = fontSize.Length.toPixels(viewPort);\n\t\t\t\t\t\n\t\t\t\t\treturn em;\n\t\t\t\t},\n\t\t\t\n\t\t\t\t// get the length as pixels\n\t\t\t\ttoPixels: function(viewPort) {\n\t\t\t\t\tif (!that.hasValue()) return 0;\n\t\t\t\t\tvar s = that.value+'';\n\t\t\t\t\tif (s.match(/em$/)) return that.numValue() * this.EM(viewPort);\n\t\t\t\t\tif (s.match(/ex$/)) return that.numValue() * this.EM(viewPort) / 2.0;\n\t\t\t\t\tif (s.match(/px$/)) return that.numValue();\n\t\t\t\t\tif (s.match(/pt$/)) return that.numValue() * 1.25;\n\t\t\t\t\tif (s.match(/pc$/)) return that.numValue() * 15;\n\t\t\t\t\tif (s.match(/cm$/)) return that.numValue() * this.DPI(viewPort) / 2.54;\n\t\t\t\t\tif (s.match(/mm$/)) return that.numValue() * this.DPI(viewPort) / 25.4;\n\t\t\t\t\tif (s.match(/in$/)) return that.numValue() * this.DPI(viewPort);\n\t\t\t\t\tif (s.match(/%$/)) return that.numValue() * svg.ViewPort.ComputeSize(viewPort);\n\t\t\t\t\treturn that.numValue();\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t// time extensions\n\t\t\tthis.Time = {\n\t\t\t\t// get the time as milliseconds\n\t\t\t\ttoMilliseconds: function() {\n\t\t\t\t\tif (!that.hasValue()) return 0;\n\t\t\t\t\tvar s = that.value+'';\n\t\t\t\t\tif (s.match(/s$/)) return that.numValue() * 1000;\n\t\t\t\t\tif (s.match(/ms$/)) return that.numValue();\n\t\t\t\t\treturn that.numValue();\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t// angle extensions\n\t\t\tthis.Angle = {\n\t\t\t\t// get the angle as radians\n\t\t\t\ttoRadians: function() {\n\t\t\t\t\tif (!that.hasValue()) return 0;\n\t\t\t\t\tvar s = that.value+'';\n\t\t\t\t\tif (s.match(/deg$/)) return that.numValue() * (Math.PI / 180.0);\n\t\t\t\t\tif (s.match(/grad$/)) return that.numValue() * (Math.PI / 200.0);\n\t\t\t\t\tif (s.match(/rad$/)) return that.numValue();\n\t\t\t\t\treturn that.numValue() * (Math.PI / 180.0);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\t// fonts\n\t\tsvg.Font = new (function() {\n\t\t\tthis.Styles = ['normal','italic','oblique','inherit'];\n\t\t\tthis.Variants = ['normal','small-caps','inherit'];\n\t\t\tthis.Weights = ['normal','bold','bolder','lighter','100','200','300','400','500','600','700','800','900','inherit'];\n\t\t\t\n\t\t\tthis.CreateFont = function(fontStyle, fontVariant, fontWeight, fontSize, fontFamily, inherit) { \n\t\t\t\tvar f = inherit != null ? this.Parse(inherit) : this.CreateFont('', '', '', '', '', svg.ctx.font);\n\t\t\t\treturn { \n\t\t\t\t\tfontFamily: fontFamily || f.fontFamily, \n\t\t\t\t\tfontSize: fontSize || f.fontSize, \n\t\t\t\t\tfontStyle: fontStyle || f.fontStyle, \n\t\t\t\t\tfontWeight: fontWeight || f.fontWeight, \n\t\t\t\t\tfontVariant: fontVariant || f.fontVariant,\n\t\t\t\t\ttoString: function () { return [this.fontStyle, this.fontVariant, this.fontWeight, this.fontSize, this.fontFamily].join(' ') } \n\t\t\t\t} \n\t\t\t}\n\t\t\t\n\t\t\tvar that = this;\n\t\t\tthis.Parse = function(s) {\n\t\t\t\tvar f = {};\n\t\t\t\tvar d = svg.trim(svg.compressSpaces(s || '')).split(' ');\n\t\t\t\tvar set = { fontSize: false, fontStyle: false, fontWeight: false, fontVariant: false }\n\t\t\t\tvar ff = '';\n\t\t\t\tfor (var i=0; i<d.length; i++) {\n\t\t\t\t\tif (!set.fontStyle && that.Styles.indexOf(d[i]) != -1) { if (d[i] != 'inherit') f.fontStyle = d[i]; set.fontStyle = true; }\n\t\t\t\t\telse if (!set.fontVariant && that.Variants.indexOf(d[i]) != -1) { if (d[i] != 'inherit') f.fontVariant = d[i]; set.fontStyle = set.fontVariant = true;\t}\n\t\t\t\t\telse if (!set.fontWeight && that.Weights.indexOf(d[i]) != -1) {\tif (d[i] != 'inherit') f.fontWeight = d[i]; set.fontStyle = set.fontVariant = set.fontWeight = true; }\n\t\t\t\t\telse if (!set.fontSize) { if (d[i] != 'inherit') f.fontSize = d[i].split('/')[0]; set.fontStyle = set.fontVariant = set.fontWeight = set.fontSize = true; }\n\t\t\t\t\telse { if (d[i] != 'inherit') ff += d[i]; }\n\t\t\t\t} if (ff != '') f.fontFamily = ff;\n\t\t\t\treturn f;\n\t\t\t}\n\t\t});\n\t\t\n\t\t// points and paths\n\t\tsvg.ToNumberArray = function(s) {\n\t\t\tvar a = svg.trim(svg.compressSpaces((s || '').replace(/,/g, ' '))).split(' ');\n\t\t\tfor (var i=0; i<a.length; i++) {\n\t\t\t\ta[i] = parseFloat(a[i]);\n\t\t\t}\n\t\t\treturn a;\n\t\t}\t\t\n\t\tsvg.Point = function(x, y) {\n\t\t\tthis.x = x;\n\t\t\tthis.y = y;\n\t\t\t\n\t\t\tthis.angleTo = function(p) {\n\t\t\t\treturn Math.atan2(p.y - this.y, p.x - this.x);\n\t\t\t}\n\t\t\t\n\t\t\tthis.applyTransform = function(v) {\n\t\t\t\tvar xp = this.x * v[0] + this.y * v[2] + v[4];\n\t\t\t\tvar yp = this.x * v[1] + this.y * v[3] + v[5];\n\t\t\t\tthis.x = xp;\n\t\t\t\tthis.y = yp;\n\t\t\t}\n\t\t}\n\t\tsvg.CreatePoint = function(s) {\n\t\t\tvar a = svg.ToNumberArray(s);\n\t\t\treturn new svg.Point(a[0], a[1]);\n\t\t}\n\t\tsvg.CreatePath = function(s) {\n\t\t\tvar a = svg.ToNumberArray(s);\n\t\t\tvar path = [];\n\t\t\tfor (var i=0; i<a.length; i+=2) {\n\t\t\t\tpath.push(new svg.Point(a[i], a[i+1]));\n\t\t\t}\n\t\t\treturn path;\n\t\t}\n\t\t\n\t\t// bounding box\n\t\tsvg.BoundingBox = function(x1, y1, x2, y2) { // pass in initial points if you want\n\t\t\tthis.x1 = Number.NaN;\n\t\t\tthis.y1 = Number.NaN;\n\t\t\tthis.x2 = Number.NaN;\n\t\t\tthis.y2 = Number.NaN;\n\t\t\t\n\t\t\tthis.x = function() { return this.x1; }\n\t\t\tthis.y = function() { return this.y1; }\n\t\t\tthis.width = function() { return this.x2 - this.x1; }\n\t\t\tthis.height = function() { return this.y2 - this.y1; }\n\t\t\t\n\t\t\tthis.addPoint = function(x, y) {\t\n\t\t\t\tif (x != null) {\n\t\t\t\t\tif (isNaN(this.x1) || isNaN(this.x2)) {\n\t\t\t\t\t\tthis.x1 = x;\n\t\t\t\t\t\tthis.x2 = x;\n\t\t\t\t\t}\n\t\t\t\t\tif (x < this.x1) this.x1 = x;\n\t\t\t\t\tif (x > this.x2) this.x2 = x;\n\t\t\t\t}\n\t\t\t\n\t\t\t\tif (y != null) {\n\t\t\t\t\tif (isNaN(this.y1) || isNaN(this.y2)) {\n\t\t\t\t\t\tthis.y1 = y;\n\t\t\t\t\t\tthis.y2 = y;\n\t\t\t\t\t}\n\t\t\t\t\tif (y < this.y1) this.y1 = y;\n\t\t\t\t\tif (y > this.y2) this.y2 = y;\n\t\t\t\t}\n\t\t\t}\t\t\t\n\t\t\tthis.addX = function(x) { this.addPoint(x, null); }\n\t\t\tthis.addY = function(y) { this.addPoint(null, y); }\n\t\t\t\n\t\t\tthis.addBoundingBox = function(bb) {\n\t\t\t\tthis.addPoint(bb.x1, bb.y1);\n\t\t\t\tthis.addPoint(bb.x2, bb.y2);\n\t\t\t}\n\t\t\t\n\t\t\tthis.addQuadraticCurve = function(p0x, p0y, p1x, p1y, p2x, p2y) {\n\t\t\t\tvar cp1x = p0x + 2/3 * (p1x - p0x); // CP1 = QP0 + 2/3 *(QP1-QP0)\n\t\t\t\tvar cp1y = p0y + 2/3 * (p1y - p0y); // CP1 = QP0 + 2/3 *(QP1-QP0)\n\t\t\t\tvar cp2x = cp1x + 1/3 * (p2x - p0x); // CP2 = CP1 + 1/3 *(QP2-QP0)\n\t\t\t\tvar cp2y = cp1y + 1/3 * (p2y - p0y); // CP2 = CP1 + 1/3 *(QP2-QP0)\n\t\t\t\tthis.addBezierCurve(p0x, p0y, cp1x, cp2x, cp1y,\tcp2y, p2x, p2y);\n\t\t\t}\n\t\t\t\n\t\t\tthis.addBezierCurve = function(p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y) {\n\t\t\t\t// from http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html\n\t\t\t\tvar p0 = [p0x, p0y], p1 = [p1x, p1y], p2 = [p2x, p2y], p3 = [p3x, p3y];\n\t\t\t\tthis.addPoint(p0[0], p0[1]);\n\t\t\t\tthis.addPoint(p3[0], p3[1]);\n\t\t\t\t\n\t\t\t\tfor (i=0; i<=1; i++) {\n\t\t\t\t\tvar f = function(t) { \n\t\t\t\t\t\treturn Math.pow(1-t, 3) * p0[i]\n\t\t\t\t\t\t+ 3 * Math.pow(1-t, 2) * t * p1[i]\n\t\t\t\t\t\t+ 3 * (1-t) * Math.pow(t, 2) * p2[i]\n\t\t\t\t\t\t+ Math.pow(t, 3) * p3[i];\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tvar b = 6 * p0[i] - 12 * p1[i] + 6 * p2[i];\n\t\t\t\t\tvar a = -3 * p0[i] + 9 * p1[i] - 9 * p2[i] + 3 * p3[i];\n\t\t\t\t\tvar c = 3 * p1[i] - 3 * p0[i];\n\t\t\t\t\t\n\t\t\t\t\tif (a == 0) {\n\t\t\t\t\t\tif (b == 0) continue;\n\t\t\t\t\t\tvar t = -c / b;\n\t\t\t\t\t\tif (0 < t && t < 1) {\n\t\t\t\t\t\t\tif (i == 0) this.addX(f(t));\n\t\t\t\t\t\t\tif (i == 1) this.addY(f(t));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tvar b2ac = Math.pow(b, 2) - 4 * c * a;\n\t\t\t\t\tif (b2ac < 0) continue;\n\t\t\t\t\tvar t1 = (-b + Math.sqrt(b2ac)) / (2 * a);\n\t\t\t\t\tif (0 < t1 && t1 < 1) {\n\t\t\t\t\t\tif (i == 0) this.addX(f(t1));\n\t\t\t\t\t\tif (i == 1) this.addY(f(t1));\n\t\t\t\t\t}\n\t\t\t\t\tvar t2 = (-b - Math.sqrt(b2ac)) / (2 * a);\n\t\t\t\t\tif (0 < t2 && t2 < 1) {\n\t\t\t\t\t\tif (i == 0) this.addX(f(t2));\n\t\t\t\t\t\tif (i == 1) this.addY(f(t2));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tthis.isPointInBox = function(x, y) {\n\t\t\t\treturn (this.x1 <= x && x <= this.x2 && this.y1 <= y && y <= this.y2);\n\t\t\t}\n\t\t\t\n\t\t\tthis.addPoint(x1, y1);\n\t\t\tthis.addPoint(x2, y2);\n\t\t}\n\t\t\n\t\t// transforms\n\t\tsvg.Transform = function(v) {\t\n\t\t\tvar that = this;\n\t\t\tthis.Type = {}\n\t\t\n\t\t\t// translate\n\t\t\tthis.Type.translate = function(s) {\n\t\t\t\tthis.p = svg.CreatePoint(s);\t\t\t\n\t\t\t\tthis.apply = function(ctx) {\n\t\t\t\t\tctx.translate(this.p.x || 0.0, this.p.y || 0.0);\n\t\t\t\t}\n\t\t\t\tthis.applyToPoint = function(p) {\n\t\t\t\t\tp.applyTransform([1, 0, 0, 1, this.p.x || 0.0, this.p.y || 0.0]);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t// rotate\n\t\t\tthis.Type.rotate = function(s) {\n\t\t\t\tvar a = svg.ToNumberArray(s);\n\t\t\t\tthis.angle = new svg.Property('angle', a[0]);\n\t\t\t\tthis.cx = a[1] || 0;\n\t\t\t\tthis.cy = a[2] || 0;\n\t\t\t\tthis.apply = function(ctx) {\n\t\t\t\t\tctx.translate(this.cx, this.cy);\n\t\t\t\t\tctx.rotate(this.angle.Angle.toRadians());\n\t\t\t\t\tctx.translate(-this.cx, -this.cy);\n\t\t\t\t}\n\t\t\t\tthis.applyToPoint = function(p) {\n\t\t\t\t\tvar a = this.angle.Angle.toRadians();\n\t\t\t\t\tp.applyTransform([1, 0, 0, 1, this.p.x || 0.0, this.p.y || 0.0]);\n\t\t\t\t\tp.applyTransform([Math.cos(a), Math.sin(a), -Math.sin(a), Math.cos(a), 0, 0]);\n\t\t\t\t\tp.applyTransform([1, 0, 0, 1, -this.p.x || 0.0, -this.p.y || 0.0]);\n\t\t\t\t}\t\t\t\n\t\t\t}\n\t\t\t\n\t\t\tthis.Type.scale = function(s) {\n\t\t\t\tthis.p = svg.CreatePoint(s);\n\t\t\t\tthis.apply = function(ctx) {\n\t\t\t\t\tctx.scale(this.p.x || 1.0, this.p.y || this.p.x || 1.0);\n\t\t\t\t}\n\t\t\t\tthis.applyToPoint = function(p) {\n\t\t\t\t\tp.applyTransform([this.p.x || 0.0, 0, 0, this.p.y || 0.0, 0, 0]);\n\t\t\t\t}\t\t\t\t\n\t\t\t}\n\t\t\t\n\t\t\tthis.Type.matrix = function(s) {\n\t\t\t\tthis.m = svg.ToNumberArray(s);\n\t\t\t\tthis.apply = function(ctx) {\n\t\t\t\t\tctx.transform(this.m[0], this.m[1], this.m[2], this.m[3], this.m[4], this.m[5]);\n\t\t\t\t}\n\t\t\t\tthis.applyToPoint = function(p) {\n\t\t\t\t\tp.applyTransform(this.m);\n\t\t\t\t}\t\t\t\t\t\n\t\t\t}\n\t\t\t\n\t\t\tthis.Type.SkewBase = function(s) {\n\t\t\t\tthis.base = that.Type.matrix;\n\t\t\t\tthis.base(s);\n\t\t\t\tthis.angle = new svg.Property('angle', s);\n\t\t\t}\n\t\t\tthis.Type.SkewBase.prototype = new this.Type.matrix;\n\t\t\t\n\t\t\tthis.Type.skewX = function(s) {\n\t\t\t\tthis.base = that.Type.SkewBase;\n\t\t\t\tthis.base(s);\n\t\t\t\tthis.m = [1, 0, Math.tan(this.angle.Angle.toRadians()), 1, 0, 0];\n\t\t\t}\n\t\t\tthis.Type.skewX.prototype = new this.Type.SkewBase;\n\t\t\t\n\t\t\tthis.Type.skewY = function(s) {\n\t\t\t\tthis.base = that.Type.SkewBase;\n\t\t\t\tthis.base(s);\n\t\t\t\tthis.m = [1, Math.tan(this.angle.Angle.toRadians()), 0, 1, 0, 0];\n\t\t\t}\n\t\t\tthis.Type.skewY.prototype = new this.Type.SkewBase;\n\t\t\n\t\t\tthis.transforms = [];\n\t\t\t\n\t\t\tthis.apply = function(ctx) {\n\t\t\t\tfor (var i=0; i<this.transforms.length; i++) {\n\t\t\t\t\tthis.transforms[i].apply(ctx);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tthis.applyToPoint = function(p) {\n\t\t\t\tfor (var i=0; i<this.transforms.length; i++) {\n\t\t\t\t\tthis.transforms[i].applyToPoint(p);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tvar data = svg.trim(svg.compressSpaces(v)).split(/\\s(?=[a-z])/);\n\t\t\tfor (var i=0; i<data.length; i++) {\n\t\t\t\tvar type = data[i].split('(')[0];\n\t\t\t\tvar s = data[i].split('(')[1].replace(')','');\n\t\t\t\tvar transform = new this.Type[type](s);\n\t\t\t\tthis.transforms.push(transform);\n\t\t\t}\n\t\t}\n\t\t\n\t\t// aspect ratio\n\t\tsvg.AspectRatio = function(ctx, aspectRatio, width, desiredWidth, height, desiredHeight, minX, minY, refX, refY) {\n\t\t\t// aspect ratio - http://www.w3.org/TR/SVG/coords.html#PreserveAspectRatioAttribute\n\t\t\taspectRatio = svg.compressSpaces(aspectRatio);\n\t\t\taspectRatio = aspectRatio.replace(/^defer\\s/,''); // ignore defer\n\t\t\tvar align = aspectRatio.split(' ')[0] || 'xMidYMid';\n\t\t\tvar meetOrSlice = aspectRatio.split(' ')[1] || 'meet';\t\t\t\t\t\n\t\n\t\t\t// calculate scale\n\t\t\tvar scaleX = width / desiredWidth;\n\t\t\tvar scaleY = height / desiredHeight;\n\t\t\tvar scaleMin = Math.min(scaleX, scaleY);\n\t\t\tvar scaleMax = Math.max(scaleX, scaleY);\n\t\t\tif (meetOrSlice == 'meet') { desiredWidth *= scaleMin; desiredHeight *= scaleMin; }\n\t\t\tif (meetOrSlice == 'slice') { desiredWidth *= scaleMax; desiredHeight *= scaleMax; }\t\n\t\t\t\n\t\t\trefX = new svg.Property('refX', refX);\n\t\t\trefY = new svg.Property('refY', refY);\n\t\t\tif (refX.hasValue() && refY.hasValue()) {\t\t\t\t\n\t\t\t\tctx.translate(-scaleMin * refX.Length.toPixels('x'), -scaleMin * refY.Length.toPixels('y'));\n\t\t\t} \n\t\t\telse {\t\t\t\t\t\n\t\t\t\t// align\n\t\t\t\tif (align.match(/^xMid/) && ((meetOrSlice == 'meet' && scaleMin == scaleY) || (meetOrSlice == 'slice' && scaleMax == scaleY))) ctx.translate(width / 2.0 - desiredWidth / 2.0, 0); \n\t\t\t\tif (align.match(/YMid$/) && ((meetOrSlice == 'meet' && scaleMin == scaleX) || (meetOrSlice == 'slice' && scaleMax == scaleX))) ctx.translate(0, height / 2.0 - desiredHeight / 2.0); \n\t\t\t\tif (align.match(/^xMax/) && ((meetOrSlice == 'meet' && scaleMin == scaleY) || (meetOrSlice == 'slice' && scaleMax == scaleY))) ctx.translate(width - desiredWidth, 0); \n\t\t\t\tif (align.match(/YMax$/) && ((meetOrSlice == 'meet' && scaleMin == scaleX) || (meetOrSlice == 'slice' && scaleMax == scaleX))) ctx.translate(0, height - desiredHeight); \n\t\t\t}\n\t\t\t\n\t\t\t// scale\n\t\t\tif (align == 'none') ctx.scale(scaleX, scaleY);\n\t\t\telse if (meetOrSlice == 'meet') ctx.scale(scaleMin, scaleMin); \n\t\t\telse if (meetOrSlice == 'slice') ctx.scale(scaleMax, scaleMax); \t\n\t\t\t\n\t\t\t// translate\n\t\t\tctx.translate(minX == null ? 0 : -minX, minY == null ? 0 : -minY);\t\t\t\n\t\t}\n\t\t\n\t\t// elements\n\t\tsvg.Element = {}\n\t\t\n\t\tsvg.Element.ElementBase = function(node) {\t\n\t\t\tthis.attributes = {};\n\t\t\tthis.styles = {};\n\t\t\tthis.children = [];\n\t\t\t\n\t\t\t// get or create attribute\n\t\t\tthis.attribute = function(name, createIfNotExists) {\n\t\t\t\tvar a = this.attributes[name];\n\t\t\t\tif (a != null) return a;\n\t\t\t\t\t\t\t\n\t\t\t\ta = new svg.Property(name, '');\n\t\t\t\tif (createIfNotExists == true) this.attributes[name] = a;\n\t\t\t\treturn a;\n\t\t\t}\n\t\t\t\n\t\t\t// get or create style, crawls up node tree\n\t\t\tthis.style = function(name, createIfNotExists) {\n\t\t\t\tvar s = this.styles[name];\n\t\t\t\tif (s != null) return s;\n\t\t\t\t\n\t\t\t\tvar a = this.attribute(name);\n\t\t\t\tif (a != null && a.hasValue()) {\n\t\t\t\t\treturn a;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tvar p = this.parent;\n\t\t\t\tif (p != null) {\n\t\t\t\t\tvar ps = p.style(name);\n\t\t\t\t\tif (ps != null && ps.hasValue()) {\n\t\t\t\t\t\treturn ps;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\ts = new svg.Property(name, '');\n\t\t\t\tif (createIfNotExists == true) this.styles[name] = s;\n\t\t\t\treturn s;\n\t\t\t}\n\t\t\t\n\t\t\t// base render\n\t\t\tthis.render = function(ctx) {\n\t\t\t\t// don't render display=none\n\t\t\t\tif (this.style('display').value == 'none') return;\n\t\t\t\t\n\t\t\t\t// don't render visibility=hidden\n\t\t\t\tif (this.attribute('visibility').value == 'hidden') return;\n\t\t\t\n\t\t\t\tctx.save();\n\t\t\t\t\tthis.setContext(ctx);\n\t\t\t\t\t\t// mask\n\t\t\t\t\t\tif (this.attribute('mask').hasValue()) {\n\t\t\t\t\t\t\tvar mask = this.attribute('mask').Definition.getDefinition();\n\t\t\t\t\t\t\tif (mask != null) mask.apply(ctx, this);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (this.style('filter').hasValue()) {\n\t\t\t\t\t\t\tvar filter = this.style('filter').Definition.getDefinition();\n\t\t\t\t\t\t\tif (filter != null) filter.apply(ctx, this);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse this.renderChildren(ctx);\t\t\t\t\n\t\t\t\t\tthis.clearContext(ctx);\n\t\t\t\tctx.restore();\n\t\t\t}\n\t\t\t\n\t\t\t// base set context\n\t\t\tthis.setContext = function(ctx) {\n\t\t\t\t// OVERRIDE ME!\n\t\t\t}\n\t\t\t\n\t\t\t// base clear context\n\t\t\tthis.clearContext = function(ctx) {\n\t\t\t\t// OVERRIDE ME!\n\t\t\t}\t\t\t\n\t\t\t\n\t\t\t// base render children\n\t\t\tthis.renderChildren = function(ctx) {\n\t\t\t\tfor (var i=0; i<this.children.length; i++) {\n\t\t\t\t\tthis.children[i].render(ctx);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tthis.addChild = function(childNode, create) {\n\t\t\t\tvar child = childNode;\n\t\t\t\tif (create) child = svg.CreateElement(childNode);\n\t\t\t\tchild.parent = this;\n\t\t\t\tthis.children.push(child);\t\t\t\n\t\t\t}\n\t\t\t\t\n\t\t\tif (node != null && node.nodeType == 1) { //ELEMENT_NODE\n\t\t\t\t// add children\n\t\t\t\tfor (var i=0; i<node.childNodes.length; i++) {\n\t\t\t\t\tvar childNode = node.childNodes[i];\n\t\t\t\t\tif (childNode.nodeType == 1) this.addChild(childNode, true); //ELEMENT_NODE\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// add attributes\n\t\t\t\tfor (var i=0; i<node.attributes.length; i++) {\n\t\t\t\t\tvar attribute = node.attributes[i];\n\t\t\t\t\tthis.attributes[attribute.nodeName] = new svg.Property(attribute.nodeName, attribute.nodeValue);\n\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t// add tag styles\n\t\t\t\tvar styles = svg.Styles[node.nodeName];\n\t\t\t\tif (styles != null) {\n\t\t\t\t\tfor (var name in styles) {\n\t\t\t\t\t\tthis.styles[name] = styles[name];\n\t\t\t\t\t}\n\t\t\t\t}\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t// add class styles\n\t\t\t\tif (this.attribute('class').hasValue()) {\n\t\t\t\t\tvar classes = svg.compressSpaces(this.attribute('class').value).split(' ');\n\t\t\t\t\tfor (var j=0; j<classes.length; j++) {\n\t\t\t\t\t\tstyles = svg.Styles['.'+classes[j]];\n\t\t\t\t\t\tif (styles != null) {\n\t\t\t\t\t\t\tfor (var name in styles) {\n\t\t\t\t\t\t\t\tthis.styles[name] = styles[name];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tstyles = svg.Styles[node.nodeName+'.'+classes[j]];\n\t\t\t\t\t\tif (styles != null) {\n\t\t\t\t\t\t\tfor (var name in styles) {\n\t\t\t\t\t\t\t\tthis.styles[name] = styles[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}\n\t\t\t\t\n\t\t\t\t// add inline styles\n\t\t\t\tif (this.attribute('style').hasValue()) {\n\t\t\t\t\tvar styles = this.attribute('style').value.split(';');\n\t\t\t\t\tfor (var i=0; i<styles.length; i++) {\n\t\t\t\t\t\tif (svg.trim(styles[i]) != '') {\n\t\t\t\t\t\t\tvar style = styles[i].split(':');\n\t\t\t\t\t\t\tvar name = svg.trim(style[0]);\n\t\t\t\t\t\t\tvar value = svg.trim(style[1]);\n\t\t\t\t\t\t\tthis.styles[name] = new svg.Property(name, value);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\t\n\n\t\t\t\t// add id\n\t\t\t\tif (this.attribute('id').hasValue()) {\n\t\t\t\t\tif (svg.Definitions[this.attribute('id').value] == null) {\n\t\t\t\t\t\tsvg.Definitions[this.attribute('id').value] = this;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\tsvg.Element.RenderedElementBase = function(node) {\n\t\t\tthis.base = svg.Element.ElementBase;\n\t\t\tthis.base(node);\n\t\t\t\n\t\t\tthis.setContext = function(ctx) {\n\t\t\t\t// fill\n\t\t\t\tif (this.style('fill').Definition.isUrl()) {\n\t\t\t\t\tvar fs = this.style('fill').Definition.getFillStyle(this);\n\t\t\t\t\tif (fs != null) ctx.fillStyle = fs;\n\t\t\t\t}\n\t\t\t\telse if (this.style('fill').hasValue()) {\n\t\t\t\t\tvar fillStyle = this.style('fill');\n\t\t\t\t\tif (this.style('fill-opacity').hasValue()) fillStyle = fillStyle.Color.addOpacity(this.style('fill-opacity').value);\n\t\t\t\t\tctx.fillStyle = (fillStyle.value == 'none' ? 'rgba(0,0,0,0)' : fillStyle.value);\n\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t// stroke\n\t\t\t\tif (this.style('stroke').Definition.isUrl()) {\n\t\t\t\t\tvar fs = this.style('stroke').Definition.getFillStyle(this);\n\t\t\t\t\tif (fs != null) ctx.strokeStyle = fs;\n\t\t\t\t}\n\t\t\t\telse if (this.style('stroke').hasValue()) {\n\t\t\t\t\tvar strokeStyle = this.style('stroke');\n\t\t\t\t\tif (this.style('stroke-opacity').hasValue()) strokeStyle = strokeStyle.Color.addOpacity(this.style('stroke-opacity').value);\n\t\t\t\t\tctx.strokeStyle = (strokeStyle.value == 'none' ? 'rgba(0,0,0,0)' : strokeStyle.value);\n\t\t\t\t}\n\t\t\t\tif (this.style('stroke-width').hasValue()) ctx.lineWidth = this.style('stroke-width').Length.toPixels();\n\t\t\t\tif (this.style('stroke-linecap').hasValue()) ctx.lineCap = this.style('stroke-linecap').value;\n\t\t\t\tif (this.style('stroke-linejoin').hasValue()) ctx.lineJoin = this.style('stroke-linejoin').value;\n\t\t\t\tif (this.style('stroke-miterlimit').hasValue()) ctx.miterLimit = this.style('stroke-miterlimit').value;\n\n\t\t\t\t// font\n\t\t\t\tif (typeof(ctx.font) != 'undefined') {\n\t\t\t\t\tctx.font = svg.Font.CreateFont( \n\t\t\t\t\t\tthis.style('font-style').value, \n\t\t\t\t\t\tthis.style('font-variant').value, \n\t\t\t\t\t\tthis.style('font-weight').value, \n\t\t\t\t\t\tthis.style('font-size').hasValue() ? this.style('font-size').Length.toPixels() + 'px' : '', \n\t\t\t\t\t\tthis.style('font-family').value).toString();\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// transform\n\t\t\t\tif (this.attribute('transform').hasValue()) { \n\t\t\t\t\tvar transform = new svg.Transform(this.attribute('transform').value);\n\t\t\t\t\ttransform.apply(ctx);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// clip\n\t\t\t\tif (this.attribute('clip-path').hasValue()) {\n\t\t\t\t\tvar clip = this.attribute('clip-path').Definition.getDefinition();\n\t\t\t\t\tif (clip != null) clip.apply(ctx);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// opacity\n\t\t\t\tif (this.style('opacity').hasValue()) {\n\t\t\t\t\tctx.globalAlpha = this.style('opacity').numValue();\n\t\t\t\t}\n\t\t\t}\t\t\n\t\t}\n\t\tsvg.Element.RenderedElementBase.prototype = new svg.Element.ElementBase;\n\t\t\n\t\tsvg.Element.PathElementBase = function(node) {\n\t\t\tthis.base = svg.Element.RenderedElementBase;\n\t\t\tthis.base(node);\n\t\t\t\n\t\t\tthis.path = function(ctx) {\n\t\t\t\tif (ctx != null) ctx.beginPath();\n\t\t\t\treturn new svg.BoundingBox();\n\t\t\t}\n\t\t\t\n\t\t\tthis.renderChildren = function(ctx) {\n\t\t\t\tthis.path(ctx);\n\t\t\t\tsvg.Mouse.checkPath(this, ctx);\n\t\t\t\tif (ctx.fillStyle != '') ctx.fill();\n\t\t\t\tif (ctx.strokeStyle != '') ctx.stroke();\n\t\t\t\t\n\t\t\t\tvar markers = this.getMarkers();\n\t\t\t\tif (markers != null) {\n\t\t\t\t\tif (this.style('marker-start').Definition.isUrl()) {\n\t\t\t\t\t\tvar marker = this.style('marker-start').Definition.getDefinition();\n\t\t\t\t\t\tmarker.render(ctx, markers[0][0], markers[0][1]);\n\t\t\t\t\t}\n\t\t\t\t\tif (this.style('marker-mid').Definition.isUrl()) {\n\t\t\t\t\t\tvar marker = this.style('marker-mid').Definition.getDefinition();\n\t\t\t\t\t\tfor (var i=1;i<markers.length-1;i++) {\n\t\t\t\t\t\t\tmarker.render(ctx, markers[i][0], markers[i][1]);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (this.style('marker-end').Definition.isUrl()) {\n\t\t\t\t\t\tvar marker = this.style('marker-end').Definition.getDefinition();\n\t\t\t\t\t\tmarker.render(ctx, markers[markers.length-1][0], markers[markers.length-1][1]);\n\t\t\t\t\t}\n\t\t\t\t}\t\t\t\t\t\n\t\t\t}\n\t\t\t\n\t\t\tthis.getBoundingBox = function() {\n\t\t\t\treturn this.path();\n\t\t\t}\n\t\t\t\n\t\t\tthis.getMarkers = function() {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\t\tsvg.Element.PathElementBase.prototype = new svg.Element.RenderedElementBase;\n\t\t\n\t\t// svg element\n\t\tsvg.Element.svg = function(node) {\n\t\t\tthis.base = svg.Element.RenderedElementBase;\n\t\t\tthis.base(node);\n\t\t\t\n\t\t\tthis.baseClearContext = this.clearContext;\n\t\t\tthis.clearContext = function(ctx) {\n\t\t\t\tthis.baseClearContext(ctx);\n\t\t\t\tsvg.ViewPort.RemoveCurrent();\n\t\t\t}\n\t\t\t\n\t\t\tthis.baseSetContext = this.setContext;\n\t\t\tthis.setContext = function(ctx) {\n\t\t\t\t// initial values\n\t\t\t\tctx.strokeStyle = 'rgba(0,0,0,0)';\n\t\t\t\tctx.lineCap = 'butt';\n\t\t\t\tctx.lineJoin = 'miter';\n\t\t\t\tctx.miterLimit = 4;\t\t\t\n\t\t\t\n\t\t\t\tthis.baseSetContext(ctx);\n\t\t\t\t\n\t\t\t\t// create new view port\n\t\t\t\tif (this.attribute('x').hasValue() && this.attribute('y').hasValue()) {\n\t\t\t\t\tctx.translate(this.attribute('x').Length.toPixels('x'), this.attribute('y').Length.toPixels('y'));\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tvar width = svg.ViewPort.width();\n\t\t\t\tvar height = svg.ViewPort.height();\n\t\t\t\tif (typeof(this.root) == 'undefined' && this.attribute('width').hasValue() && this.attribute('height').hasValue()) {\n\t\t\t\t\twidth = this.attribute('width').Length.toPixels('x');\n\t\t\t\t\theight = this.attribute('height').Length.toPixels('y');\n\t\t\t\t\t\n\t\t\t\t\tvar x = 0;\n\t\t\t\t\tvar y = 0;\n\t\t\t\t\tif (this.attribute('refX').hasValue() && this.attribute('refY').hasValue()) {\n\t\t\t\t\t\tx = -this.attribute('refX').Length.toPixels('x');\n\t\t\t\t\t\ty = -this.attribute('refY').Length.toPixels('y');\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tctx.beginPath();\n\t\t\t\t\tctx.moveTo(x, y);\n\t\t\t\t\tctx.lineTo(width, y);\n\t\t\t\t\tctx.lineTo(width, height);\n\t\t\t\t\tctx.lineTo(x, height);\n\t\t\t\t\tctx.closePath();\n\t\t\t\t\tctx.clip();\n\t\t\t\t}\n\t\t\t\tsvg.ViewPort.SetCurrent(width, height);\t\n\t\t\t\t\t\t\n\t\t\t\t// viewbox\n\t\t\t\tif (this.attribute('viewBox').hasValue()) {\t\t\t\t\n\t\t\t\t\tvar viewBox = svg.ToNumberArray(this.attribute('viewBox').value);\n\t\t\t\t\tvar minX = viewBox[0];\n\t\t\t\t\tvar minY = viewBox[1];\n\t\t\t\t\twidth = viewBox[2];\n\t\t\t\t\theight = viewBox[3];\n\t\t\t\t\t\n\t\t\t\t\tsvg.AspectRatio(ctx,\n\t\t\t\t\t\t\t\t\tthis.attribute('preserveAspectRatio').value, \n\t\t\t\t\t\t\t\t\tsvg.ViewPort.width(), \n\t\t\t\t\t\t\t\t\twidth,\n\t\t\t\t\t\t\t\t\tsvg.ViewPort.height(),\n\t\t\t\t\t\t\t\t\theight,\n\t\t\t\t\t\t\t\t\tminX,\n\t\t\t\t\t\t\t\t\tminY,\n\t\t\t\t\t\t\t\t\tthis.attribute('refX').value,\n\t\t\t\t\t\t\t\t\tthis.attribute('refY').value);\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\tsvg.ViewPort.RemoveCurrent();\t\n\t\t\t\t\tsvg.ViewPort.SetCurrent(viewBox[2], viewBox[3]);\t\t\t\t\t\t\n\t\t\t\t}\t\t\t\t\n\t\t\t}\n\t\t}\n\t\tsvg.Element.svg.prototype = new svg.Element.RenderedElementBase;\n\n\t\t// rect element\n\t\tsvg.Element.rect = function(node) {\n\t\t\tthis.base = svg.Element.PathElementBase;\n\t\t\tthis.base(node);\n\t\t\t\n\t\t\tthis.path = function(ctx) {\n\t\t\t\tvar x = this.attribute('x').Length.toPixels('x');\n\t\t\t\tvar y = this.attribute('y').Length.toPixels('y');\n\t\t\t\tvar width = this.attribute('width').Length.toPixels('x');\n\t\t\t\tvar height = this.attribute('height').Length.toPixels('y');\n\t\t\t\tvar rx = this.attribute('rx').Length.toPixels('x');\n\t\t\t\tvar ry = this.attribute('ry').Length.toPixels('y');\n\t\t\t\tif (this.attribute('rx').hasValue() && !this.attribute('ry').hasValue()) ry = rx;\n\t\t\t\tif (this.attribute('ry').hasValue() && !this.attribute('rx').hasValue()) rx = ry;\n\t\t\t\t\n\t\t\t\tif (ctx != null) {\n\t\t\t\t\tctx.beginPath();\n\t\t\t\t\tctx.moveTo(x + rx, y);\n\t\t\t\t\tctx.lineTo(x + width - rx, y);\n\t\t\t\t\tctx.quadraticCurveTo(x + width, y, x + width, y + ry)\n\t\t\t\t\tctx.lineTo(x + width, y + height - ry);\n\t\t\t\t\tctx.quadraticCurveTo(x + width, y + height, x + width - rx, y + height)\n\t\t\t\t\tctx.lineTo(x + rx, y + height);\n\t\t\t\t\tctx.quadraticCurveTo(x, y + height, x, y + height - ry)\n\t\t\t\t\tctx.lineTo(x, y + ry);\n\t\t\t\t\tctx.quadraticCurveTo(x, y, x + rx, y)\n\t\t\t\t\tctx.closePath();\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\treturn new svg.BoundingBox(x, y, x + width, y + height);\n\t\t\t}\n\t\t}\n\t\tsvg.Element.rect.prototype = new svg.Element.PathElementBase;\n\t\t\n\t\t// circle element\n\t\tsvg.Element.circle = function(node) {\n\t\t\tthis.base = svg.Element.PathElementBase;\n\t\t\tthis.base(node);\n\t\t\t\n\t\t\tthis.path = function(ctx) {\n\t\t\t\tvar cx = this.attribute('cx').Length.toPixels('x');\n\t\t\t\tvar cy = this.attribute('cy').Length.toPixels('y');\n\t\t\t\tvar r = this.attribute('r').Length.toPixels();\n\t\t\t\n\t\t\t\tif (ctx != null) {\n\t\t\t\t\tctx.beginPath();\n\t\t\t\t\tctx.arc(cx, cy, r, 0, Math.PI * 2, true); \n\t\t\t\t\tctx.closePath();\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\treturn new svg.BoundingBox(cx - r, cy - r, cx + r, cy + r);\n\t\t\t}\n\t\t}\n\t\tsvg.Element.circle.prototype = new svg.Element.PathElementBase;\t\n\n\t\t// ellipse element\n\t\tsvg.Element.ellipse = function(node) {\n\t\t\tthis.base = svg.Element.PathElementBase;\n\t\t\tthis.base(node);\n\t\t\t\n\t\t\tthis.path = function(ctx) {\n\t\t\t\tvar KAPPA = 4 * ((Math.sqrt(2) - 1) / 3);\n\t\t\t\tvar rx = this.attribute('rx').Length.toPixels('x');\n\t\t\t\tvar ry = this.attribute('ry').Length.toPixels('y');\n\t\t\t\tvar cx = this.attribute('cx').Length.toPixels('x');\n\t\t\t\tvar cy = this.attribute('cy').Length.toPixels('y');\n\t\t\t\t\n\t\t\t\tif (ctx != null) {\n\t\t\t\t\tctx.beginPath();\n\t\t\t\t\tctx.moveTo(cx, cy - ry);\n\t\t\t\t\tctx.bezierCurveTo(cx + (KAPPA * rx), cy - ry,  cx + rx, cy - (KAPPA * ry), cx + rx, cy);\n\t\t\t\t\tctx.bezierCurveTo(cx + rx, cy + (KAPPA * ry), cx + (KAPPA * rx), cy + ry, cx, cy + ry);\n\t\t\t\t\tctx.bezierCurveTo(cx - (KAPPA * rx), cy + ry, cx - rx, cy + (KAPPA * ry), cx - rx, cy);\n\t\t\t\t\tctx.bezierCurveTo(cx - rx, cy - (KAPPA * ry), cx - (KAPPA * rx), cy - ry, cx, cy - ry);\n\t\t\t\t\tctx.closePath();\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\treturn new svg.BoundingBox(cx - rx, cy - ry, cx + rx, cy + ry);\n\t\t\t}\n\t\t}\n\t\tsvg.Element.ellipse.prototype = new svg.Element.PathElementBase;\t\t\t\n\t\t\n\t\t// line element\n\t\tsvg.Element.line = function(node) {\n\t\t\tthis.base = svg.Element.PathElementBase;\n\t\t\tthis.base(node);\n\t\t\t\n\t\t\tthis.getPoints = function() {\n\t\t\t\treturn [\n\t\t\t\t\tnew svg.Point(this.attribute('x1').Length.toPixels('x'), this.attribute('y1').Length.toPixels('y')),\n\t\t\t\t\tnew svg.Point(this.attribute('x2').Length.toPixels('x'), this.attribute('y2').Length.toPixels('y'))];\n\t\t\t}\n\t\t\t\t\t\t\t\t\n\t\t\tthis.path = function(ctx) {\n\t\t\t\tvar points = this.getPoints();\n\t\t\t\t\n\t\t\t\tif (ctx != null) {\n\t\t\t\t\tctx.beginPath();\n\t\t\t\t\tctx.moveTo(points[0].x, points[0].y);\n\t\t\t\t\tctx.lineTo(points[1].x, points[1].y);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\treturn new svg.BoundingBox(points[0].x, points[0].y, points[1].x, points[1].y);\n\t\t\t}\n\t\t\t\n\t\t\tthis.getMarkers = function() {\n\t\t\t\tvar points = this.getPoints();\t\n\t\t\t\tvar a = points[0].angleTo(points[1]);\n\t\t\t\treturn [[points[0], a], [points[1], a]];\n\t\t\t}\n\t\t}\n\t\tsvg.Element.line.prototype = new svg.Element.PathElementBase;\t\t\n\t\t\t\t\n\t\t// polyline element\n\t\tsvg.Element.polyline = function(node) {\n\t\t\tthis.base = svg.Element.PathElementBase;\n\t\t\tthis.base(node);\n\t\t\t\n\t\t\tthis.points = svg.CreatePath(this.attribute('points').value);\n\t\t\tthis.path = function(ctx) {\n\t\t\t\tvar bb = new svg.BoundingBox(this.points[0].x, this.points[0].y);\n\t\t\t\tif (ctx != null) {\n\t\t\t\t\tctx.beginPath();\n\t\t\t\t\tctx.moveTo(this.points[0].x, this.points[0].y);\n\t\t\t\t}\n\t\t\t\tfor (var i=1; i<this.points.length; i++) {\n\t\t\t\t\tbb.addPoint(this.points[i].x, this.points[i].y);\n\t\t\t\t\tif (ctx != null) ctx.lineTo(this.points[i].x, this.points[i].y);\n\t\t\t\t}\n\t\t\t\treturn bb;\n\t\t\t}\n\t\t\t\n\t\t\tthis.getMarkers = function() {\n\t\t\t\tvar markers = [];\n\t\t\t\tfor (var i=0; i<this.points.length - 1; i++) {\n\t\t\t\t\tmarkers.push([this.points[i], this.points[i].angleTo(this.points[i+1])]);\n\t\t\t\t}\n\t\t\t\tmarkers.push([this.points[this.points.length-1], markers[markers.length-1][1]]);\n\t\t\t\treturn markers;\n\t\t\t}\t\t\t\n\t\t}\n\t\tsvg.Element.polyline.prototype = new svg.Element.PathElementBase;\t\t\t\t\n\t\t\t\t\n\t\t// polygon element\n\t\tsvg.Element.polygon = function(node) {\n\t\t\tthis.base = svg.Element.polyline;\n\t\t\tthis.base(node);\n\t\t\t\n\t\t\tthis.basePath = this.path;\n\t\t\tthis.path = function(ctx) {\n\t\t\t\tvar bb = this.basePath(ctx);\n\t\t\t\tif (ctx != null) {\n\t\t\t\t\tctx.lineTo(this.points[0].x, this.points[0].y);\n\t\t\t\t\tctx.closePath();\n\t\t\t\t}\n\t\t\t\treturn bb;\n\t\t\t}\n\t\t}\n\t\tsvg.Element.polygon.prototype = new svg.Element.polyline;\n\n\t\t// path element\n\t\tsvg.Element.path = function(node) {\n\t\t\tthis.base = svg.Element.PathElementBase;\n\t\t\tthis.base(node);\n\t\t\t\t\t\n\t\t\tvar d = this.attribute('d').value;\n\t\t\t// TODO: convert to real lexer based on http://www.w3.org/TR/SVG11/paths.html#PathDataBNF\n\t\t\td = d.replace(/,/gm,' '); // get rid of all commas\n\t\t\td = d.replace(/([MmZzLlHhVvCcSsQqTtAa])([MmZzLlHhVvCcSsQqTtAa])/gm,'$1 $2'); // separate commands from commands\n\t\t\td = d.replace(/([MmZzLlHhVvCcSsQqTtAa])([MmZzLlHhVvCcSsQqTtAa])/gm,'$1 $2'); // separate commands from commands\n\t\t\td = d.replace(/([MmZzLlHhVvCcSsQqTtAa])([^\\s])/gm,'$1 $2'); // separate commands from points\n\t\t\td = d.replace(/([^\\s])([MmZzLlHhVvCcSsQqTtAa])/gm,'$1 $2'); // separate commands from points\n\t\t\td = d.replace(/([0-9])([+\\-])/gm,'$1 $2'); // separate digits when no comma\n\t\t\td = d.replace(/(\\.[0-9]*)(\\.)/gm,'$1 $2'); // separate digits when no comma\n\t\t\td = d.replace(/([Aa](\\s+[0-9]+){3})\\s+([01])\\s*([01])/gm,'$1 $3 $4 '); // shorthand elliptical arc path syntax\n\t\t\td = svg.compressSpaces(d); // compress multiple spaces\n\t\t\td = svg.trim(d);\n\t\t\tthis.PathParser = new (function(d) {\n\t\t\t\tthis.tokens = d.split(' ');\n\t\t\t\t\n\t\t\t\tthis.reset = function() {\n\t\t\t\t\tthis.i = -1;\n\t\t\t\t\tthis.command = '';\n\t\t\t\t\tthis.previousCommand = '';\n\t\t\t\t\tthis.start = new svg.Point(0, 0);\n\t\t\t\t\tthis.control = new svg.Point(0, 0);\n\t\t\t\t\tthis.current = new svg.Point(0, 0);\n\t\t\t\t\tthis.points = [];\n\t\t\t\t\tthis.angles = [];\n\t\t\t\t}\n\t\t\t\t\t\t\t\t\n\t\t\t\tthis.isEnd = function() {\n\t\t\t\t\treturn this.i >= this.tokens.length - 1;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tthis.isCommandOrEnd = function() {\n\t\t\t\t\tif (this.isEnd()) return true;\n\t\t\t\t\treturn this.tokens[this.i + 1].match(/^[A-Za-z]$/) != null;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tthis.isRelativeCommand = function() {\n\t\t\t\t\treturn this.command == this.command.toLowerCase();\n\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\tthis.getToken = function() {\n\t\t\t\t\tthis.i = this.i + 1;\n\t\t\t\t\treturn this.tokens[this.i];\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tthis.getScalar = function() {\n\t\t\t\t\treturn parseFloat(this.getToken());\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tthis.nextCommand = function() {\n\t\t\t\t\tthis.previousCommand = this.command;\n\t\t\t\t\tthis.command = this.getToken();\n\t\t\t\t}\t\t\t\t\n\t\t\t\t\n\t\t\t\tthis.getPoint = function() {\n\t\t\t\t\tvar p = new svg.Point(this.getScalar(), this.getScalar());\n\t\t\t\t\treturn this.makeAbsolute(p);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tthis.getAsControlPoint = function() {\n\t\t\t\t\tvar p = this.getPoint();\n\t\t\t\t\tthis.control = p;\n\t\t\t\t\treturn p;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tthis.getAsCurrentPoint = function() {\n\t\t\t\t\tvar p = this.getPoint();\n\t\t\t\t\tthis.current = p;\n\t\t\t\t\treturn p;\t\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tthis.getReflectedControlPoint = function() {\n\t\t\t\t\tif (this.previousCommand.toLowerCase() != 'c' && this.previousCommand.toLowerCase() != 's') {\n\t\t\t\t\t\treturn this.current;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t// reflect point\n\t\t\t\t\tvar p = new svg.Point(2 * this.current.x - this.control.x, 2 * this.current.y - this.control.y);\t\t\t\t\t\n\t\t\t\t\treturn p;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tthis.makeAbsolute = function(p) {\n\t\t\t\t\tif (this.isRelativeCommand()) {\n\t\t\t\t\t\tp.x = this.current.x + p.x;\n\t\t\t\t\t\tp.y = this.current.y + p.y;\n\t\t\t\t\t}\n\t\t\t\t\treturn p;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tthis.addMarker = function(p, from, priorTo) {\n\t\t\t\t\t// if the last angle isn't filled in because we didn't have this point yet ...\n\t\t\t\t\tif (priorTo != null && this.angles.length > 0 && this.angles[this.angles.length-1] == null) {\n\t\t\t\t\t\tthis.angles[this.angles.length-1] = this.points[this.points.length-1].angleTo(priorTo);\n\t\t\t\t\t}\n\t\t\t\t\tthis.addMarkerAngle(p, from == null ? null : from.angleTo(p));\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tthis.addMarkerAngle = function(p, a) {\n\t\t\t\t\tthis.points.push(p);\n\t\t\t\t\tthis.angles.push(a);\n\t\t\t\t}\t\t\t\t\n\t\t\t\t\n\t\t\t\tthis.getMarkerPoints = function() { return this.points; }\n\t\t\t\tthis.getMarkerAngles = function() {\n\t\t\t\t\tfor (var i=0; i<this.angles.length; i++) {\n\t\t\t\t\t\tif (this.angles[i] == null) {\n\t\t\t\t\t\t\tfor (var j=i+1; j<this.angles.length; j++) {\n\t\t\t\t\t\t\t\tif (this.angles[j] != null) {\n\t\t\t\t\t\t\t\t\tthis.angles[i] = this.angles[j];\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\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn this.angles;\n\t\t\t\t}\n\t\t\t})(d);\n\n\t\t\tthis.path = function(ctx) {\n\t\t\t\tvar pp = this.PathParser;\n\t\t\t\tpp.reset();\n\n\t\t\t\tvar bb = new svg.BoundingBox();\n\t\t\t\tif (ctx != null) ctx.beginPath();\n\t\t\t\twhile (!pp.isEnd()) {\n\t\t\t\t\tpp.nextCommand();\n\t\t\t\t\tswitch (pp.command.toUpperCase()) {\n\t\t\t\t\tcase 'M':\n\t\t\t\t\t\tvar p = pp.getAsCurrentPoint();\n\t\t\t\t\t\tpp.addMarker(p);\n\t\t\t\t\t\tbb.addPoint(p.x, p.y);\n\t\t\t\t\t\tif (ctx != null) ctx.moveTo(p.x, p.y);\n\t\t\t\t\t\tpp.start = pp.current;\n\t\t\t\t\t\twhile (!pp.isCommandOrEnd()) {\n\t\t\t\t\t\t\tvar p = pp.getAsCurrentPoint();\n\t\t\t\t\t\t\tpp.addMarker(p, pp.start);\n\t\t\t\t\t\t\tbb.addPoint(p.x, p.y);\n\t\t\t\t\t\t\tif (ctx != null) ctx.lineTo(p.x, p.y);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'L':\n\t\t\t\t\t\twhile (!pp.isCommandOrEnd()) {\n\t\t\t\t\t\t\tvar c = pp.current;\n\t\t\t\t\t\t\tvar p = pp.getAsCurrentPoint();\n\t\t\t\t\t\t\tpp.addMarker(p, c);\n\t\t\t\t\t\t\tbb.addPoint(p.x, p.y);\n\t\t\t\t\t\t\tif (ctx != null) ctx.lineTo(p.x, p.y);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'H':\n\t\t\t\t\t\twhile (!pp.isCommandOrEnd()) {\n\t\t\t\t\t\t\tvar newP = new svg.Point((pp.isRelativeCommand() ? pp.current.x : 0) + pp.getScalar(), pp.current.y);\n\t\t\t\t\t\t\tpp.addMarker(newP, pp.current);\n\t\t\t\t\t\t\tpp.current = newP;\n\t\t\t\t\t\t\tbb.addPoint(pp.current.x, pp.current.y);\n\t\t\t\t\t\t\tif (ctx != null) ctx.lineTo(pp.current.x, pp.current.y);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'V':\n\t\t\t\t\t\twhile (!pp.isCommandOrEnd()) {\n\t\t\t\t\t\t\tvar newP = new svg.Point(pp.current.x, (pp.isRelativeCommand() ? pp.current.y : 0) + pp.getScalar());\n\t\t\t\t\t\t\tpp.addMarker(newP, pp.current);\n\t\t\t\t\t\t\tpp.current = newP;\n\t\t\t\t\t\t\tbb.addPoint(pp.current.x, pp.current.y);\n\t\t\t\t\t\t\tif (ctx != null) ctx.lineTo(pp.current.x, pp.current.y);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'C':\n\t\t\t\t\t\twhile (!pp.isCommandOrEnd()) {\n\t\t\t\t\t\t\tvar curr = pp.current;\n\t\t\t\t\t\t\tvar p1 = pp.getPoint();\n\t\t\t\t\t\t\tvar cntrl = pp.getAsControlPoint();\n\t\t\t\t\t\t\tvar cp = pp.getAsCurrentPoint();\n\t\t\t\t\t\t\tpp.addMarker(cp, cntrl, p1);\n\t\t\t\t\t\t\tbb.addBezierCurve(curr.x, curr.y, p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);\n\t\t\t\t\t\t\tif (ctx != null) ctx.bezierCurveTo(p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'S':\n\t\t\t\t\t\twhile (!pp.isCommandOrEnd()) {\n\t\t\t\t\t\t\tvar curr = pp.current;\n\t\t\t\t\t\t\tvar p1 = pp.getReflectedControlPoint();\n\t\t\t\t\t\t\tvar cntrl = pp.getAsControlPoint();\n\t\t\t\t\t\t\tvar cp = pp.getAsCurrentPoint();\n\t\t\t\t\t\t\tpp.addMarker(cp, cntrl, p1);\n\t\t\t\t\t\t\tbb.addBezierCurve(curr.x, curr.y, p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);\n\t\t\t\t\t\t\tif (ctx != null) ctx.bezierCurveTo(p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'Q':\n\t\t\t\t\t\twhile (!pp.isCommandOrEnd()) {\n\t\t\t\t\t\t\tvar curr = pp.current;\n\t\t\t\t\t\t\tvar cntrl = pp.getAsControlPoint();\n\t\t\t\t\t\t\tvar cp = pp.getAsCurrentPoint();\n\t\t\t\t\t\t\tpp.addMarker(cp, cntrl, cntrl);\n\t\t\t\t\t\t\tbb.addQuadraticCurve(curr.x, curr.y, cntrl.x, cntrl.y, cp.x, cp.y);\n\t\t\t\t\t\t\tif (ctx != null) ctx.quadraticCurveTo(cntrl.x, cntrl.y, cp.x, cp.y);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'T':\n\t\t\t\t\t\twhile (!pp.isCommandOrEnd()) {\n\t\t\t\t\t\t\tvar curr = pp.current;\n\t\t\t\t\t\t\tvar cntrl = pp.getReflectedControlPoint();\n\t\t\t\t\t\t\tpp.control = cntrl;\n\t\t\t\t\t\t\tvar cp = pp.getAsCurrentPoint();\n\t\t\t\t\t\t\tpp.addMarker(cp, cntrl, cntrl);\n\t\t\t\t\t\t\tbb.addQuadraticCurve(curr.x, curr.y, cntrl.x, cntrl.y, cp.x, cp.y);\n\t\t\t\t\t\t\tif (ctx != null) ctx.quadraticCurveTo(cntrl.x, cntrl.y, cp.x, cp.y);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'A':\n\t\t\t\t\t\twhile (!pp.isCommandOrEnd()) {\n\t\t\t\t\t\t    var curr = pp.current;\n\t\t\t\t\t\t\tvar rx = pp.getScalar();\n\t\t\t\t\t\t\tvar ry = pp.getScalar();\n\t\t\t\t\t\t\tvar xAxisRotation = pp.getScalar() * (Math.PI / 180.0);\n\t\t\t\t\t\t\tvar largeArcFlag = pp.getScalar();\n\t\t\t\t\t\t\tvar sweepFlag = pp.getScalar();\n\t\t\t\t\t\t\tvar cp = pp.getAsCurrentPoint();\n\n\t\t\t\t\t\t\t// Conversion from endpoint to center parameterization\n\t\t\t\t\t\t\t// http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes\n\t\t\t\t\t\t\t// x1', y1'\n\t\t\t\t\t\t\tvar currp = new svg.Point(\n\t\t\t\t\t\t\t\tMath.cos(xAxisRotation) * (curr.x - cp.x) / 2.0 + Math.sin(xAxisRotation) * (curr.y - cp.y) / 2.0,\n\t\t\t\t\t\t\t\t-Math.sin(xAxisRotation) * (curr.x - cp.x) / 2.0 + Math.cos(xAxisRotation) * (curr.y - cp.y) / 2.0\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t// adjust radii\n\t\t\t\t\t\t\tvar l = Math.pow(currp.x,2)/Math.pow(rx,2)+Math.pow(currp.y,2)/Math.pow(ry,2);\n\t\t\t\t\t\t\tif (l > 1) {\n\t\t\t\t\t\t\t\trx *= Math.sqrt(l);\n\t\t\t\t\t\t\t\try *= Math.sqrt(l);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// cx', cy'\n\t\t\t\t\t\t\tvar s = (largeArcFlag == sweepFlag ? -1 : 1) * Math.sqrt(\n\t\t\t\t\t\t\t\t((Math.pow(rx,2)*Math.pow(ry,2))-(Math.pow(rx,2)*Math.pow(currp.y,2))-(Math.pow(ry,2)*Math.pow(currp.x,2))) /\n\t\t\t\t\t\t\t\t(Math.pow(rx,2)*Math.pow(currp.y,2)+Math.pow(ry,2)*Math.pow(currp.x,2))\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (isNaN(s)) s = 0;\n\t\t\t\t\t\t\tvar cpp = new svg.Point(s * rx * currp.y / ry, s * -ry * currp.x / rx);\n\t\t\t\t\t\t\t// cx, cy\n\t\t\t\t\t\t\tvar centp = new svg.Point(\n\t\t\t\t\t\t\t\t(curr.x + cp.x) / 2.0 + Math.cos(xAxisRotation) * cpp.x - Math.sin(xAxisRotation) * cpp.y,\n\t\t\t\t\t\t\t\t(curr.y + cp.y) / 2.0 + Math.sin(xAxisRotation) * cpp.x + Math.cos(xAxisRotation) * cpp.y\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t// vector magnitude\n\t\t\t\t\t\t\tvar m = function(v) { return Math.sqrt(Math.pow(v[0],2) + Math.pow(v[1],2)); }\n\t\t\t\t\t\t\t// ratio between two vectors\n\t\t\t\t\t\t\tvar r = function(u, v) { return (u[0]*v[0]+u[1]*v[1]) / (m(u)*m(v)) }\n\t\t\t\t\t\t\t// angle between two vectors\n\t\t\t\t\t\t\tvar a = function(u, v) { return (u[0]*v[1] < u[1]*v[0] ? -1 : 1) * Math.acos(r(u,v)); }\n\t\t\t\t\t\t\t// initial angle\n\t\t\t\t\t\t\tvar a1 = a([1,0], [(currp.x-cpp.x)/rx,(currp.y-cpp.y)/ry]);\n\t\t\t\t\t\t\t// angle delta\n\t\t\t\t\t\t\tvar u = [(currp.x-cpp.x)/rx,(currp.y-cpp.y)/ry];\n\t\t\t\t\t\t\tvar v = [(-currp.x-cpp.x)/rx,(-currp.y-cpp.y)/ry];\n\t\t\t\t\t\t\tvar ad = a(u, v);\n\t\t\t\t\t\t\tif (r(u,v) <= -1) ad = Math.PI;\n\t\t\t\t\t\t\tif (r(u,v) >= 1) ad = 0;\n\n\t\t\t\t\t\t\tif (sweepFlag == 0 && ad > 0) ad = ad - 2 * Math.PI;\n\t\t\t\t\t\t\tif (sweepFlag == 1 && ad < 0) ad = ad + 2 * Math.PI;\n\n\t\t\t\t\t\t\t// for markers\n\t\t\t\t\t\t\tvar halfWay = new svg.Point(\n\t\t\t\t\t\t\t\tcentp.x - rx * Math.cos((a1 + ad) / 2),\n\t\t\t\t\t\t\t\tcentp.y - ry * Math.sin((a1 + ad) / 2)\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tpp.addMarkerAngle(halfWay, (a1 + ad) / 2 + (sweepFlag == 0 ? 1 : -1) * Math.PI / 2);\n\t\t\t\t\t\t\tpp.addMarkerAngle(cp, ad + (sweepFlag == 0 ? 1 : -1) * Math.PI / 2);\n\n\t\t\t\t\t\t\tbb.addPoint(cp.x, cp.y); // TODO: this is too naive, make it better\n\t\t\t\t\t\t\tif (ctx != null) {\n\t\t\t\t\t\t\t\tvar r = rx > ry ? rx : ry;\n\t\t\t\t\t\t\t\tvar sx = rx > ry ? 1 : rx / ry;\n\t\t\t\t\t\t\t\tvar sy = rx > ry ? ry / rx : 1;\n\n\t\t\t\t\t\t\t\tctx.translate(centp.x, centp.y);\n\t\t\t\t\t\t\t\tctx.rotate(xAxisRotation);\n\t\t\t\t\t\t\t\tctx.scale(sx, sy);\n\t\t\t\t\t\t\t\tctx.arc(0, 0, r, a1, a1 + ad, 1 - sweepFlag);\n\t\t\t\t\t\t\t\tctx.scale(1/sx, 1/sy);\n\t\t\t\t\t\t\t\tctx.rotate(-xAxisRotation);\n\t\t\t\t\t\t\t\tctx.translate(-centp.x, -centp.y);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'Z':\n\t\t\t\t\t\tif (ctx != null) ctx.closePath();\n\t\t\t\t\t\tpp.current = pp.start;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn bb;\n\t\t\t}\n\n\t\t\tthis.getMarkers = function() {\n\t\t\t\tvar points = this.PathParser.getMarkerPoints();\n\t\t\t\tvar angles = this.PathParser.getMarkerAngles();\n\t\t\t\t\n\t\t\t\tvar markers = [];\n\t\t\t\tfor (var i=0; i<points.length; i++) {\n\t\t\t\t\tmarkers.push([points[i], angles[i]]);\n\t\t\t\t}\n\t\t\t\treturn markers;\n\t\t\t}\n\t\t}\n\t\tsvg.Element.path.prototype = new svg.Element.PathElementBase;\n\t\t\n\t\t// pattern element\n\t\tsvg.Element.pattern = function(node) {\n\t\t\tthis.base = svg.Element.ElementBase;\n\t\t\tthis.base(node);\n\t\t\t\n\t\t\tthis.createPattern = function(ctx, element) {\n\t\t\t\t// render me using a temporary svg element\n\t\t\t\tvar tempSvg = new svg.Element.svg();\n\t\t\t\ttempSvg.attributes['viewBox'] = new svg.Property('viewBox', this.attribute('viewBox').value);\n\t\t\t\ttempSvg.attributes['x'] = new svg.Property('x', this.attribute('x').value);\n\t\t\t\ttempSvg.attributes['y'] = new svg.Property('y', this.attribute('y').value);\n\t\t\t\ttempSvg.attributes['width'] = new svg.Property('width', this.attribute('width').value);\n\t\t\t\ttempSvg.attributes['height'] = new svg.Property('height', this.attribute('height').value);\n\t\t\t\ttempSvg.children = this.children;\n\t\t\t\t\n\t\t\t\tvar c = document.createElement('canvas');\n\t\t\t\tc.width = this.attribute('width').Length.toPixels('x');\n\t\t\t\tc.height = this.attribute('height').Length.toPixels('y');\n\t\t\t\ttempSvg.render(c.getContext('2d'));\t\t\n\t\t\t\treturn ctx.createPattern(c, 'repeat');\n\t\t\t}\n\t\t}\n\t\tsvg.Element.pattern.prototype = new svg.Element.ElementBase;\n\t\t\n\t\t// marker element\n\t\tsvg.Element.marker = function(node) {\n\t\t\tthis.base = svg.Element.ElementBase;\n\t\t\tthis.base(node);\n\t\t\t\n\t\t\tthis.baseRender = this.render;\n\t\t\tthis.render = function(ctx, point, angle) {\n\t\t\t\tctx.translate(point.x, point.y);\n\t\t\t\tif (this.attribute('orient').valueOrDefault('auto') == 'auto') ctx.rotate(angle);\n\t\t\t\tif (this.attribute('markerUnits').valueOrDefault('strokeWidth') == 'strokeWidth') ctx.scale(ctx.lineWidth, ctx.lineWidth);\n\t\t\t\tctx.save();\n\t\t\t\t\t\t\t\n\t\t\t\t// render me using a temporary svg element\n\t\t\t\tvar tempSvg = new svg.Element.svg();\n\t\t\t\ttempSvg.attributes['viewBox'] = new svg.Property('viewBox', this.attribute('viewBox').value);\n\t\t\t\ttempSvg.attributes['refX'] = new svg.Property('refX', this.attribute('refX').value);\n\t\t\t\ttempSvg.attributes['refY'] = new svg.Property('refY', this.attribute('refY').value);\n\t\t\t\ttempSvg.attributes['width'] = new svg.Property('width', this.attribute('markerWidth').value);\n\t\t\t\ttempSvg.attributes['height'] = new svg.Property('height', this.attribute('markerHeight').value);\n\t\t\t\ttempSvg.attributes['fill'] = new svg.Property('fill', this.attribute('fill').valueOrDefault('black'));\n\t\t\t\ttempSvg.attributes['stroke'] = new svg.Property('stroke', this.attribute('stroke').valueOrDefault('none'));\n\t\t\t\ttempSvg.children = this.children;\n\t\t\t\ttempSvg.render(ctx);\n\t\t\t\t\n\t\t\t\tctx.restore();\n\t\t\t\tif (this.attribute('markerUnits').valueOrDefault('strokeWidth') == 'strokeWidth') ctx.scale(1/ctx.lineWidth, 1/ctx.lineWidth);\n\t\t\t\tif (this.attribute('orient').valueOrDefault('auto') == 'auto') ctx.rotate(-angle);\n\t\t\t\tctx.translate(-point.x, -point.y);\n\t\t\t}\n\t\t}\n\t\tsvg.Element.marker.prototype = new svg.Element.ElementBase;\n\t\t\n\t\t// definitions element\n\t\tsvg.Element.defs = function(node) {\n\t\t\tthis.base = svg.Element.ElementBase;\n\t\t\tthis.base(node);\t\n\t\t\t\n\t\t\tthis.render = function(ctx) {\n\t\t\t\t// NOOP\n\t\t\t}\n\t\t}\n\t\tsvg.Element.defs.prototype = new svg.Element.ElementBase;\n\t\t\n\t\t// base for gradients\n\t\tsvg.Element.GradientBase = function(node) {\n\t\t\tthis.base = svg.Element.ElementBase;\n\t\t\tthis.base(node);\n\t\t\t\n\t\t\tthis.gradientUnits = this.attribute('gradientUnits').valueOrDefault('objectBoundingBox');\n\t\t\t\n\t\t\tthis.stops = [];\t\t\t\n\t\t\tfor (var i=0; i<this.children.length; i++) {\n\t\t\t\tvar child = this.children[i];\n\t\t\t\tthis.stops.push(child);\n\t\t\t}\t\n\t\t\t\n\t\t\tthis.getGradient = function() {\n\t\t\t\t// OVERRIDE ME!\n\t\t\t}\t\t\t\n\n\t\t\tthis.createGradient = function(ctx, element) {\n\t\t\t\tvar stopsContainer = this;\n\t\t\t\tif (this.attribute('xlink:href').hasValue()) {\n\t\t\t\t\tstopsContainer = this.attribute('xlink:href').Definition.getDefinition();\n\t\t\t\t}\n\t\t\t\n\t\t\t\tvar g = this.getGradient(ctx, element);\n\t\t\t\tfor (var i=0; i<stopsContainer.stops.length; i++) {\n\t\t\t\t\tg.addColorStop(stopsContainer.stops[i].offset, stopsContainer.stops[i].color);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (this.attribute('gradientTransform').hasValue()) {\n\t\t\t\t\t// render as transformed pattern on temporary canvas\n\t\t\t\t\tvar rootView = svg.ViewPort.viewPorts[0];\n\t\t\t\t\t\n\t\t\t\t\tvar rect = new svg.Element.rect();\n\t\t\t\t\trect.attributes['x'] = new svg.Property('x', -svg.MAX_VIRTUAL_PIXELS/3.0);\n\t\t\t\t\trect.attributes['y'] = new svg.Property('y', -svg.MAX_VIRTUAL_PIXELS/3.0);\n\t\t\t\t\trect.attributes['width'] = new svg.Property('width', svg.MAX_VIRTUAL_PIXELS);\n\t\t\t\t\trect.attributes['height'] = new svg.Property('height', svg.MAX_VIRTUAL_PIXELS);\n\t\t\t\t\t\n\t\t\t\t\tvar group = new svg.Element.g();\n\t\t\t\t\tgroup.attributes['transform'] = new svg.Property('transform', this.attribute('gradientTransform').value);\n\t\t\t\t\tgroup.children = [ rect ];\n\t\t\t\t\t\n\t\t\t\t\tvar tempSvg = new svg.Element.svg();\n\t\t\t\t\ttempSvg.attributes['x'] = new svg.Property('x', 0);\n\t\t\t\t\ttempSvg.attributes['y'] = new svg.Property('y', 0);\n\t\t\t\t\ttempSvg.attributes['width'] = new svg.Property('width', rootView.width);\n\t\t\t\t\ttempSvg.attributes['height'] = new svg.Property('height', rootView.height);\n\t\t\t\t\ttempSvg.children = [ group ];\n\t\t\t\t\t\n\t\t\t\t\tvar c = document.createElement('canvas');\n\t\t\t\t\tc.width = rootView.width;\n\t\t\t\t\tc.height = rootView.height;\n\t\t\t\t\tvar tempCtx = c.getContext('2d');\n\t\t\t\t\ttempCtx.fillStyle = g;\n\t\t\t\t\ttempSvg.render(tempCtx);\t\t\n\t\t\t\t\treturn tempCtx.createPattern(c, 'no-repeat');\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\treturn g;\t\t\t\t\n\t\t\t}\n\t\t}\n\t\tsvg.Element.GradientBase.prototype = new svg.Element.ElementBase;\n\t\t\n\t\t// linear gradient element\n\t\tsvg.Element.linearGradient = function(node) {\n\t\t\tthis.base = svg.Element.GradientBase;\n\t\t\tthis.base(node);\n\t\t\t\n\t\t\tthis.getGradient = function(ctx, element) {\n\t\t\t\tvar bb = element.getBoundingBox();\n\t\t\t\t\n\t\t\t\tvar x1 = (this.gradientUnits == 'objectBoundingBox' \n\t\t\t\t\t? bb.x() + bb.width() * this.attribute('x1').numValue() \n\t\t\t\t\t: this.attribute('x1').Length.toPixels('x'));\n\t\t\t\tvar y1 = (this.gradientUnits == 'objectBoundingBox' \n\t\t\t\t\t? bb.y() + bb.height() * this.attribute('y1').numValue()\n\t\t\t\t\t: this.attribute('y1').Length.toPixels('y'));\n\t\t\t\tvar x2 = (this.gradientUnits == 'objectBoundingBox' \n\t\t\t\t\t? bb.x() + bb.width() * this.attribute('x2').numValue()\n\t\t\t\t\t: this.attribute('x2').Length.toPixels('x'));\n\t\t\t\tvar y2 = (this.gradientUnits == 'objectBoundingBox' \n\t\t\t\t\t? bb.y() + bb.height() * this.attribute('y2').numValue()\n\t\t\t\t\t: this.attribute('y2').Length.toPixels('y'));\n\n\t\t\t\treturn ctx.createLinearGradient(x1, y1, x2, y2);\n\t\t\t}\n\t\t}\n\t\tsvg.Element.linearGradient.prototype = new svg.Element.GradientBase;\n\t\t\n\t\t// radial gradient element\n\t\tsvg.Element.radialGradient = function(node) {\n\t\t\tthis.base = svg.Element.GradientBase;\n\t\t\tthis.base(node);\n\t\t\t\n\t\t\tthis.getGradient = function(ctx, element) {\n\t\t\t\tvar bb = element.getBoundingBox();\n\t\t\t\t\n\t\t\t\tvar cx = (this.gradientUnits == 'objectBoundingBox' \n\t\t\t\t\t? bb.x() + bb.width() * this.attribute('cx').numValue() \n\t\t\t\t\t: this.attribute('cx').Length.toPixels('x'));\n\t\t\t\tvar cy = (this.gradientUnits == 'objectBoundingBox' \n\t\t\t\t\t? bb.y() + bb.height() * this.attribute('cy').numValue() \n\t\t\t\t\t: this.attribute('cy').Length.toPixels('y'));\n\t\t\t\t\n\t\t\t\tvar fx = cx;\n\t\t\t\tvar fy = cy;\n\t\t\t\tif (this.attribute('fx').hasValue()) {\n\t\t\t\t\tfx = (this.gradientUnits == 'objectBoundingBox' \n\t\t\t\t\t? bb.x() + bb.width() * this.attribute('fx').numValue() \n\t\t\t\t\t: this.attribute('fx').Length.toPixels('x'));\n\t\t\t\t}\n\t\t\t\tif (this.attribute('fy').hasValue()) {\n\t\t\t\t\tfy = (this.gradientUnits == 'objectBoundingBox' \n\t\t\t\t\t? bb.y() + bb.height() * this.attribute('fy').numValue() \n\t\t\t\t\t: this.attribute('fy').Length.toPixels('y'));\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tvar r = (this.gradientUnits == 'objectBoundingBox' \n\t\t\t\t\t? (bb.width() + bb.height()) / 2.0 * this.attribute('r').numValue()\n\t\t\t\t\t: this.attribute('r').Length.toPixels());\n\t\t\t\t\n\t\t\t\treturn ctx.createRadialGradient(fx, fy, 0, cx, cy, r);\n\t\t\t}\n\t\t}\n\t\tsvg.Element.radialGradient.prototype = new svg.Element.GradientBase;\n\t\t\n\t\t// gradient stop element\n\t\tsvg.Element.stop = function(node) {\n\t\t\tthis.base = svg.Element.ElementBase;\n\t\t\tthis.base(node);\n\t\t\t\n\t\t\tthis.offset = this.attribute('offset').numValue();\n\t\t\t\n\t\t\tvar stopColor = this.style('stop-color');\n\t\t\tif (this.style('stop-opacity').hasValue()) stopColor = stopColor.Color.addOpacity(this.style('stop-opacity').value);\n\t\t\tthis.color = stopColor.value;\n\t\t}\n\t\tsvg.Element.stop.prototype = new svg.Element.ElementBase;\n\t\t\n\t\t// animation base element\n\t\tsvg.Element.AnimateBase = function(node) {\n\t\t\tthis.base = svg.Element.ElementBase;\n\t\t\tthis.base(node);\n\t\t\t\n\t\t\tsvg.Animations.push(this);\n\t\t\t\n\t\t\tthis.duration = 0.0;\n\t\t\tthis.begin = this.attribute('begin').Time.toMilliseconds();\n\t\t\tthis.maxDuration = this.begin + this.attribute('dur').Time.toMilliseconds();\n\t\t\t\n\t\t\tthis.getProperty = function() {\n\t\t\t\tvar attributeType = this.attribute('attributeType').value;\n\t\t\t\tvar attributeName = this.attribute('attributeName').value;\n\t\t\t\t\n\t\t\t\tif (attributeType == 'CSS') {\n\t\t\t\t\treturn this.parent.style(attributeName, true);\n\t\t\t\t}\n\t\t\t\treturn this.parent.attribute(attributeName, true);\t\t\t\n\t\t\t};\n\t\t\t\n\t\t\tthis.initialValue = null;\n\t\t\tthis.removed = false;\t\t\t\n\n\t\t\tthis.calcValue = function() {\n\t\t\t\t// OVERRIDE ME!\n\t\t\t\treturn '';\n\t\t\t}\n\t\t\t\n\t\t\tthis.update = function(delta) {\t\n\t\t\t\t// set initial value\n\t\t\t\tif (this.initialValue == null) {\n\t\t\t\t\tthis.initialValue = this.getProperty().value;\n\t\t\t\t}\n\t\t\t\n\t\t\t\t// if we're past the end time\n\t\t\t\tif (this.duration > this.maxDuration) {\n\t\t\t\t\t// loop for indefinitely repeating animations\n\t\t\t\t\tif (this.attribute('repeatCount').value == 'indefinite') {\n\t\t\t\t\t\tthis.duration = 0.0\n\t\t\t\t\t}\n\t\t\t\t\telse if (this.attribute('fill').valueOrDefault('remove') == 'remove' && !this.removed) {\n\t\t\t\t\t\tthis.removed = true;\n\t\t\t\t\t\tthis.getProperty().value = this.initialValue;\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\treturn false; // no updates made\n\t\t\t\t\t}\n\t\t\t\t}\t\t\t\n\t\t\t\tthis.duration = this.duration + delta;\n\t\t\t\n\t\t\t\t// if we're past the begin time\n\t\t\t\tvar updated = false;\n\t\t\t\tif (this.begin < this.duration) {\n\t\t\t\t\tvar newValue = this.calcValue(); // tween\n\t\t\t\t\t\n\t\t\t\t\tif (this.attribute('type').hasValue()) {\n\t\t\t\t\t\t// for transform, etc.\n\t\t\t\t\t\tvar type = this.attribute('type').value;\n\t\t\t\t\t\tnewValue = type + '(' + newValue + ')';\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tthis.getProperty().value = newValue;\n\t\t\t\t\tupdated = true;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\treturn updated;\n\t\t\t}\n\t\t\t\n\t\t\t// fraction of duration we've covered\n\t\t\tthis.progress = function() {\n\t\t\t\treturn ((this.duration - this.begin) / (this.maxDuration - this.begin));\n\t\t\t}\t\t\t\n\t\t}\n\t\tsvg.Element.AnimateBase.prototype = new svg.Element.ElementBase;\n\t\t\n\t\t// animate element\n\t\tsvg.Element.animate = function(node) {\n\t\t\tthis.base = svg.Element.AnimateBase;\n\t\t\tthis.base(node);\n\t\t\t\n\t\t\tthis.calcValue = function() {\n\t\t\t\tvar from = this.attribute('from').numValue();\n\t\t\t\tvar to = this.attribute('to').numValue();\n\t\t\t\t\n\t\t\t\t// tween value linearly\n\t\t\t\treturn from + (to - from) * this.progress(); \n\t\t\t};\n\t\t}\n\t\tsvg.Element.animate.prototype = new svg.Element.AnimateBase;\n\t\t\t\n\t\t// animate color element\n\t\tsvg.Element.animateColor = function(node) {\n\t\t\tthis.base = svg.Element.AnimateBase;\n\t\t\tthis.base(node);\n\n\t\t\tthis.calcValue = function() {\n\t\t\t\tvar from = new RGBColor(this.attribute('from').value);\n\t\t\t\tvar to = new RGBColor(this.attribute('to').value);\n\t\t\t\t\n\t\t\t\tif (from.ok && to.ok) {\n\t\t\t\t\t// tween color linearly\n\t\t\t\t\tvar r = from.r + (to.r - from.r) * this.progress();\n\t\t\t\t\tvar g = from.g + (to.g - from.g) * this.progress();\n\t\t\t\t\tvar b = from.b + (to.b - from.b) * this.progress();\n\t\t\t\t\treturn 'rgb('+parseInt(r,10)+','+parseInt(g,10)+','+parseInt(b,10)+')';\n\t\t\t\t}\n\t\t\t\treturn this.attribute('from').value;\n\t\t\t};\n\t\t}\n\t\tsvg.Element.animateColor.prototype = new svg.Element.AnimateBase;\n\t\t\n\t\t// animate transform element\n\t\tsvg.Element.animateTransform = function(node) {\n\t\t\tthis.base = svg.Element.animate;\n\t\t\tthis.base(node);\n\t\t}\n\t\tsvg.Element.animateTransform.prototype = new svg.Element.animate;\n\t\t\n\t\t// font element\n\t\tsvg.Element.font = function(node) {\n\t\t\tthis.base = svg.Element.ElementBase;\n\t\t\tthis.base(node);\n\n\t\t\tthis.horizAdvX = this.attribute('horiz-adv-x').numValue();\t\t\t\n\t\t\t\n\t\t\tthis.isRTL = false;\n\t\t\tthis.isArabic = false;\n\t\t\tthis.fontFace = null;\n\t\t\tthis.missingGlyph = null;\n\t\t\tthis.glyphs = [];\t\t\t\n\t\t\tfor (var i=0; i<this.children.length; i++) {\n\t\t\t\tvar child = this.children[i];\n\t\t\t\tif (child.type == 'font-face') {\n\t\t\t\t\tthis.fontFace = child;\n\t\t\t\t\tif (child.style('font-family').hasValue()) {\n\t\t\t\t\t\tsvg.Definitions[child.style('font-family').value] = this;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (child.type == 'missing-glyph') this.missingGlyph = child;\n\t\t\t\telse if (child.type == 'glyph') {\n\t\t\t\t\tif (child.arabicForm != '') {\n\t\t\t\t\t\tthis.isRTL = true;\n\t\t\t\t\t\tthis.isArabic = true;\n\t\t\t\t\t\tif (typeof(this.glyphs[child.unicode]) == 'undefined') this.glyphs[child.unicode] = [];\n\t\t\t\t\t\tthis.glyphs[child.unicode][child.arabicForm] = child;\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tthis.glyphs[child.unicode] = child;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\t\n\t\t}\n\t\tsvg.Element.font.prototype = new svg.Element.ElementBase;\n\t\t\n\t\t// font-face element\n\t\tsvg.Element.fontface = function(node) {\n\t\t\tthis.base = svg.Element.ElementBase;\n\t\t\tthis.base(node);\t\n\t\t\t\n\t\t\tthis.ascent = this.attribute('ascent').value;\n\t\t\tthis.descent = this.attribute('descent').value;\n\t\t\tthis.unitsPerEm = this.attribute('units-per-em').numValue();\t\t\t\t\n\t\t}\n\t\tsvg.Element.fontface.prototype = new svg.Element.ElementBase;\n\t\t\n\t\t// missing-glyph element\n\t\tsvg.Element.missingglyph = function(node) {\n\t\t\tthis.base = svg.Element.path;\n\t\t\tthis.base(node);\t\n\t\t\t\n\t\t\tthis.horizAdvX = 0;\n\t\t}\n\t\tsvg.Element.missingglyph.prototype = new svg.Element.path;\n\t\t\n\t\t// glyph element\n\t\tsvg.Element.glyph = function(node) {\n\t\t\tthis.base = svg.Element.path;\n\t\t\tthis.base(node);\t\n\t\t\t\n\t\t\tthis.horizAdvX = this.attribute('horiz-adv-x').numValue();\n\t\t\tthis.unicode = this.attribute('unicode').value;\n\t\t\tthis.arabicForm = this.attribute('arabic-form').value;\n\t\t}\n\t\tsvg.Element.glyph.prototype = new svg.Element.path;\n\t\t\n\t\t// text element\n\t\tsvg.Element.text = function(node) {\n\t\t\tthis.base = svg.Element.RenderedElementBase;\n\t\t\tthis.base(node);\n\t\t\t\n\t\t\tif (node != null) {\n\t\t\t\t// add children\n\t\t\t\tthis.children = [];\n\t\t\t\tfor (var i=0; i<node.childNodes.length; i++) {\n\t\t\t\t\tvar childNode = node.childNodes[i];\n\t\t\t\t\tif (childNode.nodeType == 1) { // capture tspan and tref nodes\n\t\t\t\t\t\tthis.addChild(childNode, true);\n\t\t\t\t\t}\n\t\t\t\t\telse if (childNode.nodeType == 3) { // capture text\n\t\t\t\t\t\tthis.addChild(new svg.Element.tspan(childNode), false);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tthis.baseSetContext = this.setContext;\n\t\t\tthis.setContext = function(ctx) {\n\t\t\t\tthis.baseSetContext(ctx);\n\t\t\t\tif (this.style('dominant-baseline').hasValue()) ctx.textBaseline = this.style('dominant-baseline').value;\n\t\t\t\tif (this.style('alignment-baseline').hasValue()) ctx.textBaseline = this.style('alignment-baseline').value;\n\t\t\t}\n\t\t\t\n\t\t\tthis.renderChildren = function(ctx) {\n\t\t\t\tvar textAnchor = this.style('text-anchor').valueOrDefault('start');\n\t\t\t\tvar x = this.attribute('x').Length.toPixels('x');\n\t\t\t\tvar y = this.attribute('y').Length.toPixels('y');\n\t\t\t\tfor (var i=0; i<this.children.length; i++) {\n\t\t\t\t\tvar child = this.children[i];\n\t\t\t\t\n\t\t\t\t\tif (child.attribute('x').hasValue()) {\n\t\t\t\t\t\tchild.x = child.attribute('x').Length.toPixels('x');\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tif (child.attribute('dx').hasValue()) x += child.attribute('dx').Length.toPixels('x');\n\t\t\t\t\t\tchild.x = x;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tvar childLength = child.measureText(ctx);\n\t\t\t\t\tif (textAnchor != 'start' && (i==0 || child.attribute('x').hasValue())) { // new group?\n\t\t\t\t\t\t// loop through rest of children\n\t\t\t\t\t\tvar groupLength = childLength;\n\t\t\t\t\t\tfor (var j=i+1; j<this.children.length; j++) {\n\t\t\t\t\t\t\tvar childInGroup = this.children[j];\n\t\t\t\t\t\t\tif (childInGroup.attribute('x').hasValue()) break; // new group\n\t\t\t\t\t\t\tgroupLength += childInGroup.measureText(ctx);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tchild.x -= (textAnchor == 'end' ? groupLength : groupLength / 2.0);\n\t\t\t\t\t}\n\t\t\t\t\tx = child.x + childLength;\n\t\t\t\t\t\n\t\t\t\t\tif (child.attribute('y').hasValue()) {\n\t\t\t\t\t\tchild.y = child.attribute('y').Length.toPixels('y');\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tif (child.attribute('dy').hasValue()) y += child.attribute('dy').Length.toPixels('y');\n\t\t\t\t\t\tchild.y = y;\n\t\t\t\t\t}\t\n\t\t\t\t\ty = child.y;\n\t\t\t\t\t\n\t\t\t\t\tchild.render(ctx);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tsvg.Element.text.prototype = new svg.Element.RenderedElementBase;\n\t\t\n\t\t// text base\n\t\tsvg.Element.TextElementBase = function(node) {\n\t\t\tthis.base = svg.Element.RenderedElementBase;\n\t\t\tthis.base(node);\n\t\t\t\n\t\t\tthis.getGlyph = function(font, text, i) {\n\t\t\t\tvar c = text[i];\n\t\t\t\tvar glyph = null;\n\t\t\t\tif (font.isArabic) {\n\t\t\t\t\tvar arabicForm = 'isolated';\n\t\t\t\t\tif ((i==0 || text[i-1]==' ') && i<text.length-2 && text[i+1]!=' ') arabicForm = 'terminal'; \n\t\t\t\t\tif (i>0 && text[i-1]!=' ' && i<text.length-2 && text[i+1]!=' ') arabicForm = 'medial';\n\t\t\t\t\tif (i>0 && text[i-1]!=' ' && (i == text.length-1 || text[i+1]==' ')) arabicForm = 'initial';\n\t\t\t\t\tif (typeof(font.glyphs[c]) != 'undefined') {\n\t\t\t\t\t\tglyph = font.glyphs[c][arabicForm];\n\t\t\t\t\t\tif (glyph == null && font.glyphs[c].type == 'glyph') glyph = font.glyphs[c];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tglyph = font.glyphs[c];\n\t\t\t\t}\n\t\t\t\tif (glyph == null) glyph = font.missingGlyph;\n\t\t\t\treturn glyph;\n\t\t\t}\n\t\t\t\n\t\t\tthis.renderChildren = function(ctx) {\n\t\t\t\tvar customFont = this.parent.style('font-family').Definition.getDefinition();\n\t\t\t\tif (customFont != null) {\n\t\t\t\t\tvar fontSize = this.parent.style('font-size').numValueOrDefault(svg.Font.Parse(svg.ctx.font).fontSize);\n\t\t\t\t\tvar fontStyle = this.parent.style('font-style').valueOrDefault(svg.Font.Parse(svg.ctx.font).fontStyle);\n\t\t\t\t\tvar text = this.getText();\n\t\t\t\t\tif (customFont.isRTL) text = text.split(\"\").reverse().join(\"\");\n\t\t\t\t\t\n\t\t\t\t\tvar dx = svg.ToNumberArray(this.parent.attribute('dx').value);\n\t\t\t\t\tfor (var i=0; i<text.length; i++) {\n\t\t\t\t\t\tvar glyph = this.getGlyph(customFont, text, i);\n\t\t\t\t\t\tvar scale = fontSize / customFont.fontFace.unitsPerEm;\n\t\t\t\t\t\tctx.translate(this.x, this.y);\n\t\t\t\t\t\tctx.scale(scale, -scale);\n\t\t\t\t\t\tvar lw = ctx.lineWidth;\n\t\t\t\t\t\tctx.lineWidth = ctx.lineWidth * customFont.fontFace.unitsPerEm / fontSize;\n\t\t\t\t\t\tif (fontStyle == 'italic') ctx.transform(1, 0, .4, 1, 0, 0);\n\t\t\t\t\t\tglyph.render(ctx);\n\t\t\t\t\t\tif (fontStyle == 'italic') ctx.transform(1, 0, -.4, 1, 0, 0);\n\t\t\t\t\t\tctx.lineWidth = lw;\n\t\t\t\t\t\tctx.scale(1/scale, -1/scale);\n\t\t\t\t\t\tctx.translate(-this.x, -this.y);\t\n\t\t\t\t\t\t\n\t\t\t\t\t\tthis.x += fontSize * (glyph.horizAdvX || customFont.horizAdvX) / customFont.fontFace.unitsPerEm;\n\t\t\t\t\t\tif (typeof(dx[i]) != 'undefined' && !isNaN(dx[i])) {\n\t\t\t\t\t\t\tthis.x += dx[i];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\n\t\t\t\tif (ctx.strokeStyle != '') ctx.strokeText(svg.compressSpaces(this.getText()), this.x, this.y);\n\t\t\t\tif (ctx.fillStyle != '') ctx.fillText(svg.compressSpaces(this.getText()), this.x, this.y);\n\t\t\t}\n\t\t\t\n\t\t\tthis.getText = function() {\n\t\t\t\t// OVERRIDE ME\n\t\t\t}\n\t\t\t\n\t\t\tthis.measureText = function(ctx) {\n\t\t\t\tvar customFont = this.parent.style('font-family').Definition.getDefinition();\n\t\t\t\tif (customFont != null) {\n\t\t\t\t\tvar fontSize = this.parent.style('font-size').numValueOrDefault(svg.Font.Parse(svg.ctx.font).fontSize);\n\t\t\t\t\tvar measure = 0;\n\t\t\t\t\tvar text = this.getText();\n\t\t\t\t\tif (customFont.isRTL) text = text.split(\"\").reverse().join(\"\");\n\t\t\t\t\tvar dx = svg.ToNumberArray(this.parent.attribute('dx').value);\n\t\t\t\t\tfor (var i=0; i<text.length; i++) {\n\t\t\t\t\t\tvar glyph = this.getGlyph(customFont, text, i);\n\t\t\t\t\t\tmeasure += (glyph.horizAdvX || customFont.horizAdvX) * fontSize / customFont.fontFace.unitsPerEm;\n\t\t\t\t\t\tif (typeof(dx[i]) != 'undefined' && !isNaN(dx[i])) {\n\t\t\t\t\t\t\tmeasure += dx[i];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn measure;\n\t\t\t\t}\n\t\t\t\n\t\t\t\tvar textToMeasure = svg.compressSpaces(this.getText());\n\t\t\t\tif (!ctx.measureText) return textToMeasure.length * 10;\n\t\t\t\t\n\t\t\t\tctx.save();\n\t\t\t\tthis.setContext(ctx);\n\t\t\t\tvar width = ctx.measureText(textToMeasure).width;\n\t\t\t\tctx.restore();\n\t\t\t\treturn width;\n\t\t\t}\n\t\t}\n\t\tsvg.Element.TextElementBase.prototype = new svg.Element.RenderedElementBase;\n\t\t\n\t\t// tspan \n\t\tsvg.Element.tspan = function(node) {\n\t\t\tthis.base = svg.Element.TextElementBase;\n\t\t\tthis.base(node);\n\t\t\t\n\t\t\tthis.text = node.nodeType == 3 ? node.nodeValue : // text\n\t\t\t\t\t\tnode.childNodes.length > 0 ? node.childNodes[0].nodeValue : // element\n\t\t\t\t\t\tnode.text;\n\t\t\tthis.getText = function() {\n\t\t\t\treturn this.text;\n\t\t\t}\n\t\t}\n\t\tsvg.Element.tspan.prototype = new svg.Element.TextElementBase;\n\t\t\n\t\t// tref\n\t\tsvg.Element.tref = function(node) {\n\t\t\tthis.base = svg.Element.TextElementBase;\n\t\t\tthis.base(node);\n\t\t\t\n\t\t\tthis.getText = function() {\n\t\t\t\tvar element = this.attribute('xlink:href').Definition.getDefinition();\n\t\t\t\tif (element != null) return element.children[0].getText();\n\t\t\t}\n\t\t}\n\t\tsvg.Element.tref.prototype = new svg.Element.TextElementBase;\t\t\n\t\t\n\t\t// a element\n\t\tsvg.Element.a = function(node) {\n\t\t\tthis.base = svg.Element.TextElementBase;\n\t\t\tthis.base(node);\n\t\t\t\n\t\t\tthis.hasText = true;\n\t\t\tfor (var i=0; i<node.childNodes.length; i++) {\n\t\t\t\tif (node.childNodes[i].nodeType != 3) this.hasText = false;\n\t\t\t}\n\t\t\t\n\t\t\t// this might contain text\n\t\t\tthis.text = this.hasText ? node.childNodes[0].nodeValue : '';\n\t\t\tthis.getText = function() {\n\t\t\t\treturn this.text;\n\t\t\t}\t\t\n\n\t\t\tthis.baseRenderChildren = this.renderChildren;\n\t\t\tthis.renderChildren = function(ctx) {\n\t\t\t\tif (this.hasText) {\n\t\t\t\t\t// render as text element\n\t\t\t\t\tthis.baseRenderChildren(ctx);\n\t\t\t\t\tvar fontSize = new svg.Property('fontSize', svg.Font.Parse(svg.ctx.font).fontSize);\n\t\t\t\t\tsvg.Mouse.checkBoundingBox(this, new svg.BoundingBox(this.x, this.y - fontSize.Length.toPixels('y'), this.x + this.measureText(ctx), this.y));\t\t\t\t\t\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t// render as temporary group\n\t\t\t\t\tvar g = new svg.Element.g();\n\t\t\t\t\tg.children = this.children;\n\t\t\t\t\tg.parent = this;\n\t\t\t\t\tg.render(ctx);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tthis.onclick = function() {\n\t\t\t\twindow.open(this.attribute('xlink:href').value);\n\t\t\t}\n\t\t\t\n\t\t\tthis.onmousemove = function() {\n\t\t\t\tsvg.ctx.canvas.style.cursor = 'pointer';\n\t\t\t}\n\t\t}\n\t\tsvg.Element.a.prototype = new svg.Element.TextElementBase;\t\t\n\t\t\n\t\t// image element\n\t\tsvg.Element.image = function(node) {\n\t\t\tthis.base = svg.Element.RenderedElementBase;\n\t\t\tthis.base(node);\n\t\t\t\n\t\t\tsvg.Images.push(this);\n\t\t\tthis.img = document.createElement('img');\n\t\t\tthis.loaded = false;\n\t\t\tvar that = this;\n\t\t\tthis.img.onload = function() { that.loaded = true; }\n\t\t\tthis.img.src = this.attribute('xlink:href').value;\n\t\t\t\n\t\t\tthis.renderChildren = function(ctx) {\n\t\t\t\tvar x = this.attribute('x').Length.toPixels('x');\n\t\t\t\tvar y = this.attribute('y').Length.toPixels('y');\n\t\t\t\t\n\t\t\t\tvar width = this.attribute('width').Length.toPixels('x');\n\t\t\t\tvar height = this.attribute('height').Length.toPixels('y');\t\t\t\n\t\t\t\tif (width == 0 || height == 0) return;\n\t\t\t\n\t\t\t\tctx.save();\n\t\t\t\tctx.translate(x, y);\n\t\t\t\tsvg.AspectRatio(ctx,\n\t\t\t\t\t\t\t\tthis.attribute('preserveAspectRatio').value,\n\t\t\t\t\t\t\t\twidth,\n\t\t\t\t\t\t\t\tthis.img.width,\n\t\t\t\t\t\t\t\theight,\n\t\t\t\t\t\t\t\tthis.img.height,\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\t0);\t\n\t\t\t\tctx.drawImage(this.img, 0, 0);\t\t\t\n\t\t\t\tctx.restore();\n\t\t\t}\n\t\t}\n\t\tsvg.Element.image.prototype = new svg.Element.RenderedElementBase;\n\t\t\n\t\t// group element\n\t\tsvg.Element.g = function(node) {\n\t\t\tthis.base = svg.Element.RenderedElementBase;\n\t\t\tthis.base(node);\n\t\t\t\n\t\t\tthis.getBoundingBox = function() {\n\t\t\t\tvar bb = new svg.BoundingBox();\n\t\t\t\tfor (var i=0; i<this.children.length; i++) {\n\t\t\t\t\tbb.addBoundingBox(this.children[i].getBoundingBox());\n\t\t\t\t}\n\t\t\t\treturn bb;\n\t\t\t};\n\t\t}\n\t\tsvg.Element.g.prototype = new svg.Element.RenderedElementBase;\n\n\t\t// symbol element\n\t\tsvg.Element.symbol = function(node) {\n\t\t\tthis.base = svg.Element.RenderedElementBase;\n\t\t\tthis.base(node);\n\t\t\t\n\t\t\tthis.baseSetContext = this.setContext;\n\t\t\tthis.setContext = function(ctx) {\t\t\n\t\t\t\tthis.baseSetContext(ctx);\n\t\t\t\t\n\t\t\t\t// viewbox\n\t\t\t\tif (this.attribute('viewBox').hasValue()) {\t\t\t\t\n\t\t\t\t\tvar viewBox = svg.ToNumberArray(this.attribute('viewBox').value);\n\t\t\t\t\tvar minX = viewBox[0];\n\t\t\t\t\tvar minY = viewBox[1];\n\t\t\t\t\twidth = viewBox[2];\n\t\t\t\t\theight = viewBox[3];\n\t\t\t\t\t\n\t\t\t\t\tsvg.AspectRatio(ctx,\n\t\t\t\t\t\t\t\t\tthis.attribute('preserveAspectRatio').value, \n\t\t\t\t\t\t\t\t\tthis.attribute('width').Length.toPixels('x'),\n\t\t\t\t\t\t\t\t\twidth,\n\t\t\t\t\t\t\t\t\tthis.attribute('height').Length.toPixels('y'),\n\t\t\t\t\t\t\t\t\theight,\n\t\t\t\t\t\t\t\t\tminX,\n\t\t\t\t\t\t\t\t\tminY);\n\n\t\t\t\t\tsvg.ViewPort.SetCurrent(viewBox[2], viewBox[3]);\t\t\t\t\t\t\n\t\t\t\t}\n\t\t\t}\t\t\t\n\t\t}\n\t\tsvg.Element.symbol.prototype = new svg.Element.RenderedElementBase;\t\t\n\t\t\t\n\t\t// style element\n\t\tsvg.Element.style = function(node) { \n\t\t\tthis.base = svg.Element.ElementBase;\n\t\t\tthis.base(node);\n\t\t\t\n\t\t\t// text, or spaces then CDATA\n\t\t\tvar css = node.childNodes[0].nodeValue + (node.childNodes.length > 1 ? node.childNodes[1].nodeValue : '');\n\t\t\tcss = css.replace(/(\\/\\*([^*]|[\\r\\n]|(\\*+([^*\\/]|[\\r\\n])))*\\*+\\/)|(^[\\s]*\\/\\/.*)/gm, ''); // remove comments\n\t\t\tcss = svg.compressSpaces(css); // replace whitespace\n\t\t\tvar cssDefs = css.split('}');\n\t\t\tfor (var i=0; i<cssDefs.length; i++) {\n\t\t\t\tif (svg.trim(cssDefs[i]) != '') {\n\t\t\t\t\tvar cssDef = cssDefs[i].split('{');\n\t\t\t\t\tvar cssClasses = cssDef[0].split(',');\n\t\t\t\t\tvar cssProps = cssDef[1].split(';');\n\t\t\t\t\tfor (var j=0; j<cssClasses.length; j++) {\n\t\t\t\t\t\tvar cssClass = svg.trim(cssClasses[j]);\n\t\t\t\t\t\tif (cssClass != '') {\n\t\t\t\t\t\t\tvar props = {};\n\t\t\t\t\t\t\tfor (var k=0; k<cssProps.length; k++) {\n\t\t\t\t\t\t\t\tvar prop = cssProps[k].indexOf(':');\n\t\t\t\t\t\t\t\tvar name = cssProps[k].substr(0, prop);\n\t\t\t\t\t\t\t\tvar value = cssProps[k].substr(prop + 1, cssProps[k].length - prop);\n\t\t\t\t\t\t\t\tif (name != null && value != null) {\n\t\t\t\t\t\t\t\t\tprops[svg.trim(name)] = new svg.Property(svg.trim(name), svg.trim(value));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tsvg.Styles[cssClass] = props;\n\t\t\t\t\t\t\tif (cssClass == '@font-face') {\n\t\t\t\t\t\t\t\tvar fontFamily = props['font-family'].value.replace(/\"/g,'');\n\t\t\t\t\t\t\t\tvar srcs = props['src'].value.split(',');\n\t\t\t\t\t\t\t\tfor (var s=0; s<srcs.length; s++) {\n\t\t\t\t\t\t\t\t\tif (srcs[s].indexOf('format(\"svg\")') > 0) {\n\t\t\t\t\t\t\t\t\t\tvar urlStart = srcs[s].indexOf('url');\n\t\t\t\t\t\t\t\t\t\tvar urlEnd = srcs[s].indexOf(')', urlStart);\n\t\t\t\t\t\t\t\t\t\tvar url = srcs[s].substr(urlStart + 5, urlEnd - urlStart - 6);\n\t\t\t\t\t\t\t\t\t\tvar doc = svg.parseXml(svg.ajax(url));\n\t\t\t\t\t\t\t\t\t\tvar fonts = doc.getElementsByTagName('font');\n\t\t\t\t\t\t\t\t\t\tfor (var f=0; f<fonts.length; f++) {\n\t\t\t\t\t\t\t\t\t\t\tvar font = svg.CreateElement(fonts[f]);\n\t\t\t\t\t\t\t\t\t\t\tsvg.Definitions[fontFamily] = font;\n\t\t\t\t\t\t\t\t\t\t}\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}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tsvg.Element.style.prototype = new svg.Element.ElementBase;\n\t\t\n\t\t// use element \n\t\tsvg.Element.use = function(node) {\n\t\t\tthis.base = svg.Element.RenderedElementBase;\n\t\t\tthis.base(node);\n\t\t\t\n\t\t\tthis.baseSetContext = this.setContext;\n\t\t\tthis.setContext = function(ctx) {\n\t\t\t\tthis.baseSetContext(ctx);\n\t\t\t\tif (this.attribute('x').hasValue()) ctx.translate(this.attribute('x').Length.toPixels('x'), 0);\n\t\t\t\tif (this.attribute('y').hasValue()) ctx.translate(0, this.attribute('y').Length.toPixels('y'));\n\t\t\t}\n\t\t\t\n\t\t\tthis.getDefinition = function() {\n\t\t\t\tvar element = this.attribute('xlink:href').Definition.getDefinition();\n\t\t\t\tif (this.attribute('width').hasValue()) element.attribute('width', true).value = this.attribute('width').value;\n\t\t\t\tif (this.attribute('height').hasValue()) element.attribute('height', true).value = this.attribute('height').value;\n\t\t\t\treturn element;\n\t\t\t}\n\t\t\t\n\t\t\tthis.path = function(ctx) {\n\t\t\t\tvar element = this.getDefinition();\n\t\t\t\tif (element != null) element.path(ctx);\n\t\t\t}\n\t\t\t\n\t\t\tthis.renderChildren = function(ctx) {\n\t\t\t\tvar element = this.getDefinition();\n\t\t\t\tif (element != null) element.render(ctx);\n\t\t\t}\n\t\t}\n\t\tsvg.Element.use.prototype = new svg.Element.RenderedElementBase;\n\t\t\n\t\t// mask element\n\t\tsvg.Element.mask = function(node) {\n\t\t\tthis.base = svg.Element.ElementBase;\n\t\t\tthis.base(node);\n\t\t\t\t\t\t\n\t\t\tthis.apply = function(ctx, element) {\n\t\t\t\t// render as temp svg\t\n\t\t\t\tvar x = this.attribute('x').Length.toPixels('x');\n\t\t\t\tvar y = this.attribute('y').Length.toPixels('y');\n\t\t\t\tvar width = this.attribute('width').Length.toPixels('x');\n\t\t\t\tvar height = this.attribute('height').Length.toPixels('y');\n\t\t\t\t\n\t\t\t\t// temporarily remove mask to avoid recursion\n\t\t\t\tvar mask = element.attribute('mask').value;\n\t\t\t\telement.attribute('mask').value = '';\n\t\t\t\t\n\t\t\t\t\tvar cMask = document.createElement('canvas');\n\t\t\t\t\tcMask.width = x + width;\n\t\t\t\t\tcMask.height = y + height;\n\t\t\t\t\tvar maskCtx = cMask.getContext('2d');\n\t\t\t\t\tthis.renderChildren(maskCtx);\n\t\t\t\t\n\t\t\t\t\tvar c = document.createElement('canvas');\n\t\t\t\t\tc.width = x + width;\n\t\t\t\t\tc.height = y + height;\n\t\t\t\t\tvar tempCtx = c.getContext('2d');\n\t\t\t\t\telement.render(tempCtx);\n\t\t\t\t\ttempCtx.globalCompositeOperation = 'destination-in';\n\t\t\t\t\ttempCtx.fillStyle = maskCtx.createPattern(cMask, 'no-repeat');\n\t\t\t\t\ttempCtx.fillRect(0, 0, x + width, y + height);\n\t\t\t\t\t\n\t\t\t\t\tctx.fillStyle = tempCtx.createPattern(c, 'no-repeat');\n\t\t\t\t\tctx.fillRect(0, 0, x + width, y + height);\n\t\t\t\t\t\n\t\t\t\t// reassign mask\n\t\t\t\telement.attribute('mask').value = mask;\t\n\t\t\t}\n\t\t\t\n\t\t\tthis.render = function(ctx) {\n\t\t\t\t// NO RENDER\n\t\t\t}\n\t\t}\n\t\tsvg.Element.mask.prototype = new svg.Element.ElementBase;\n\t\t\n\t\t// clip element\n\t\tsvg.Element.clipPath = function(node) {\n\t\t\tthis.base = svg.Element.ElementBase;\n\t\t\tthis.base(node);\n\t\t\t\n\t\t\tthis.apply = function(ctx) {\n\t\t\t\tfor (var i=0; i<this.children.length; i++) {\n\t\t\t\t\tif (this.children[i].path) {\n\t\t\t\t\t\tthis.children[i].path(ctx);\n\t\t\t\t\t\tctx.clip();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tthis.render = function(ctx) {\n\t\t\t\t// NO RENDER\n\t\t\t}\n\t\t}\n\t\tsvg.Element.clipPath.prototype = new svg.Element.ElementBase;\n\n\t\t// filters\n\t\tsvg.Element.filter = function(node) {\n\t\t\tthis.base = svg.Element.ElementBase;\n\t\t\tthis.base(node);\n\t\t\t\t\t\t\n\t\t\tthis.apply = function(ctx, element) {\n\t\t\t\t// render as temp svg\t\n\t\t\t\tvar bb = element.getBoundingBox();\n\t\t\t\tvar x = this.attribute('x').Length.toPixels('x');\n\t\t\t\tvar y = this.attribute('y').Length.toPixels('y');\n\t\t\t\tif (x == 0 || y == 0) {\n\t\t\t\t\tx = bb.x1;\n\t\t\t\t\ty = bb.y1;\n\t\t\t\t}\n\t\t\t\tvar width = this.attribute('width').Length.toPixels('x');\n\t\t\t\tvar height = this.attribute('height').Length.toPixels('y');\n\t\t\t\tif (width == 0 || height == 0) {\n\t\t\t\t\twidth = bb.width();\n\t\t\t\t\theight = bb.height();\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// temporarily remove filter to avoid recursion\n\t\t\t\tvar filter = element.style('filter').value;\n\t\t\t\telement.style('filter').value = '';\n\t\t\t\t\n\t\t\t\t// max filter distance\n\t\t\t\tvar extraPercent = .20;\n\t\t\t\tvar px = extraPercent * width;\n\t\t\t\tvar py = extraPercent * height;\n\t\t\t\t\n\t\t\t\tvar c = document.createElement('canvas');\n\t\t\t\tc.width = width + 2*px;\n\t\t\t\tc.height = height + 2*py;\n\t\t\t\tvar tempCtx = c.getContext('2d');\n\t\t\t\ttempCtx.translate(-x + px, -y + py);\n\t\t\t\telement.render(tempCtx);\n\t\t\t\n\t\t\t\t// apply filters\n\t\t\t\tfor (var i=0; i<this.children.length; i++) {\n\t\t\t\t\tthis.children[i].apply(tempCtx, 0, 0, width + 2*px, height + 2*py);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// render on me\n\t\t\t\tctx.drawImage(c, 0, 0, width + 2*px, height + 2*py, x - px, y - py, width + 2*px, height + 2*py);\n\t\t\t\t\n\t\t\t\t// reassign filter\n\t\t\t\telement.style('filter', true).value = filter;\t\n\t\t\t}\n\t\t\t\n\t\t\tthis.render = function(ctx) {\n\t\t\t\t// NO RENDER\n\t\t\t}\t\t\n\t\t}\n\t\tsvg.Element.filter.prototype = new svg.Element.ElementBase;\n\t\t\n\t\tsvg.Element.feGaussianBlur = function(node) {\n\t\t\tthis.base = svg.Element.ElementBase;\n\t\t\tthis.base(node);\t\n\t\t\t\n\t\t\tfunction make_fgauss(sigma) {\n\t\t\t\tsigma = Math.max(sigma, 0.01);\t\t\t      \n\t\t\t\tvar len = Math.ceil(sigma * 4.0) + 1;                     \n\t\t\t\tmask = [];                               \n\t\t\t\tfor (var i = 0; i < len; i++) {                             \n\t\t\t\t\tmask[i] = Math.exp(-0.5 * (i / sigma) * (i / sigma));                                           \n\t\t\t\t}                                                           \n\t\t\t\treturn mask; \n\t\t\t}\n\t\t\t\n\t\t\tfunction normalize(mask) {\n\t\t\t\tvar sum = 0;\n\t\t\t\tfor (var i = 1; i < mask.length; i++) {\n\t\t\t\t\tsum += Math.abs(mask[i]);\n\t\t\t\t}\n\t\t\t\tsum = 2 * sum + Math.abs(mask[0]);\n\t\t\t\tfor (var i = 0; i < mask.length; i++) {\n\t\t\t\t\tmask[i] /= sum;\n\t\t\t\t}\n\t\t\t\treturn mask;\n\t\t\t}\n\t\t\t\n\t\t\tfunction convolve_even(src, dst, mask, width, height) {\n\t\t\t  for (var y = 0; y < height; y++) {\n\t\t\t\tfor (var x = 0; x < width; x++) {\n\t\t\t\t  var a = imGet(src, x, y, width, height, 3)/255;\n\t\t\t\t  for (var rgba = 0; rgba < 4; rgba++) {\t\t\t\t\t  \n\t\t\t\t\t  var sum = mask[0] * (a==0?255:imGet(src, x, y, width, height, rgba)) * (a==0||rgba==3?1:a);\n\t\t\t\t\t  for (var i = 1; i < mask.length; i++) {\n\t\t\t\t\t\tvar a1 = imGet(src, Math.max(x-i,0), y, width, height, 3)/255;\n\t\t\t\t\t    var a2 = imGet(src, Math.min(x+i, width-1), y, width, height, 3)/255;\n\t\t\t\t\t\tsum += mask[i] * \n\t\t\t\t\t\t  ((a1==0?255:imGet(src, Math.max(x-i,0), y, width, height, rgba)) * (a1==0||rgba==3?1:a1) + \n\t\t\t\t\t\t   (a2==0?255:imGet(src, Math.min(x+i, width-1), y, width, height, rgba)) * (a2==0||rgba==3?1:a2));\n\t\t\t\t\t  }\n\t\t\t\t\t  imSet(dst, y, x, height, width, rgba, sum);\n\t\t\t\t  }\t\t\t  \n\t\t\t\t}\n\t\t\t  }\n\t\t\t}\t\t\n\n\t\t\tfunction imGet(img, x, y, width, height, rgba) {\n\t\t\t\treturn img[y*width*4 + x*4 + rgba];\n\t\t\t}\n\t\t\t\n\t\t\tfunction imSet(img, x, y, width, height, rgba, val) {\n\t\t\t\timg[y*width*4 + x*4 + rgba] = val;\n\t\t\t}\n\t\t\t\t\t\t\n\t\t\tfunction blur(ctx, width, height, sigma)\n\t\t\t{\n\t\t\t\tvar srcData = ctx.getImageData(0, 0, width, height);\n\t\t\t\tvar mask = make_fgauss(sigma);\n\t\t\t\tmask = normalize(mask);\n\t\t\t\ttmp = [];\n\t\t\t\tconvolve_even(srcData.data, tmp, mask, width, height);\n\t\t\t\tconvolve_even(tmp, srcData.data, mask, height, width);\n\t\t\t\tctx.clearRect(0, 0, width, height);\n\t\t\t\tctx.putImageData(srcData, 0, 0);\n\t\t\t}\t\t\t\n\t\t\n\t\t\tthis.apply = function(ctx, x, y, width, height) {\n\t\t\t\t// assuming x==0 && y==0 for now\n\t\t\t\tblur(ctx, width, height, this.attribute('stdDeviation').numValue());\n\t\t\t}\n\t\t}\n\t\tsvg.Element.filter.prototype = new svg.Element.feGaussianBlur;\n\t\t\n\t\t// title element, do nothing\n\t\tsvg.Element.title = function(node) {\n\t\t}\n\t\tsvg.Element.title.prototype = new svg.Element.ElementBase;\n\n\t\t// desc element, do nothing\n\t\tsvg.Element.desc = function(node) {\n\t\t}\n\t\tsvg.Element.desc.prototype = new svg.Element.ElementBase;\t\t\n\t\t\n\t\tsvg.Element.MISSING = function(node) {\n\t\t\tconsole.log('ERROR: Element \\'' + node.nodeName + '\\' not yet implemented.');\n\t\t}\n\t\tsvg.Element.MISSING.prototype = new svg.Element.ElementBase;\n\t\t\n\t\t// element factory\n\t\tsvg.CreateElement = function(node) {\t\n\t\t\tvar className = node.nodeName.replace(/^[^:]+:/,''); // remove namespace\n\t\t\tclassName = className.replace(/\\-/g,''); // remove dashes\n\t\t\tvar e = null;\n\t\t\tif (typeof(svg.Element[className]) != 'undefined') {\n\t\t\t\te = new svg.Element[className](node);\n\t\t\t}\n\t\t\telse {\n\t\t\t\te = new svg.Element.MISSING(node);\n\t\t\t}\n\n\t\t\te.type = node.nodeName;\n\t\t\treturn e;\n\t\t}\n\t\t\t\t\n\t\t// load from url\n\t\tsvg.load = function(ctx, url) {\n\t\t\tsvg.loadXml(ctx, svg.ajax(url));\n\t\t}\n\t\t\n\t\t// load from xml\n\t\tsvg.loadXml = function(ctx, xml) {\n\t\t\tsvg.loadXmlDoc(ctx, svg.parseXml(xml));\n\t\t}\n\t\t\n\t\tsvg.loadXmlDoc = function(ctx, dom) {\n\t\t\tsvg.init(ctx);\n\t\t\t\n\t\t\tvar mapXY = function(p) {\n\t\t\t\tvar e = ctx.canvas;\n\t\t\t\twhile (e) {\n\t\t\t\t\tp.x -= e.offsetLeft;\n\t\t\t\t\tp.y -= e.offsetTop;\n\t\t\t\t\te = e.offsetParent;\n\t\t\t\t}\n\t\t\t\tif (window.scrollX) p.x += window.scrollX;\n\t\t\t\tif (window.scrollY) p.y += window.scrollY;\n\t\t\t\treturn p;\n\t\t\t}\n\t\t\t\n\t\t\t// bind mouse\n\t\t\tif (svg.opts['ignoreMouse'] != true) {\n\t\t\t\tctx.canvas.onclick = function(e) {\n\t\t\t\t\tvar p = mapXY(new svg.Point(e != null ? e.clientX : event.clientX, e != null ? e.clientY : event.clientY));\n\t\t\t\t\tsvg.Mouse.onclick(p.x, p.y);\n\t\t\t\t};\n\t\t\t\tctx.canvas.onmousemove = function(e) {\n\t\t\t\t\tvar p = mapXY(new svg.Point(e != null ? e.clientX : event.clientX, e != null ? e.clientY : event.clientY));\n\t\t\t\t\tsvg.Mouse.onmousemove(p.x, p.y);\n\t\t\t\t};\n\t\t\t}\n\t\t\n\t\t\tvar e = svg.CreateElement(dom.documentElement);\n\t\t\te.root = true;\n\t\t\t\t\t\n\t\t\t// render loop\n\t\t\tvar isFirstRender = true;\n\t\t\tvar draw = function() {\n\t\t\t\tsvg.ViewPort.Clear();\n\t\t\t\tif (ctx.canvas.parentNode) svg.ViewPort.SetCurrent(ctx.canvas.parentNode.clientWidth, ctx.canvas.parentNode.clientHeight);\n\t\t\t\n\t\t\t\tif (svg.opts['ignoreDimensions'] != true) {\n\t\t\t\t\t// set canvas size\n\t\t\t\t\tif (e.style('width').hasValue()) {\n\t\t\t\t\t\tctx.canvas.width = e.style('width').Length.toPixels('x');\n\t\t\t\t\t\tctx.canvas.style.width = ctx.canvas.width + 'px';\n\t\t\t\t\t}\n\t\t\t\t\tif (e.style('height').hasValue()) {\n\t\t\t\t\t\tctx.canvas.height = e.style('height').Length.toPixels('y');\n\t\t\t\t\t\tctx.canvas.style.height = ctx.canvas.height + 'px';\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tvar cWidth = ctx.canvas.clientWidth || ctx.canvas.width;\n\t\t\t\tvar cHeight = ctx.canvas.clientHeight || ctx.canvas.height;\n\t\t\t\tsvg.ViewPort.SetCurrent(cWidth, cHeight);\t\t\n\t\t\t\t\n\t\t\t\tif (svg.opts != null && svg.opts['offsetX'] != null) e.attribute('x', true).value = svg.opts['offsetX'];\n\t\t\t\tif (svg.opts != null && svg.opts['offsetY'] != null) e.attribute('y', true).value = svg.opts['offsetY'];\n\t\t\t\tif (svg.opts != null && svg.opts['scaleWidth'] != null && svg.opts['scaleHeight'] != null) {\n\t\t\t\t\tvar xRatio = 1, yRatio = 1;\n\t\t\t\t\tif (e.attribute('width').hasValue()) xRatio = e.attribute('width').Length.toPixels('x') / svg.opts['scaleWidth'];\n\t\t\t\t\tif (e.attribute('height').hasValue()) yRatio = e.attribute('height').Length.toPixels('y') / svg.opts['scaleHeight'];\n\t\t\t\t\n\t\t\t\t\te.attribute('width', true).value = svg.opts['scaleWidth'];\n\t\t\t\t\te.attribute('height', true).value = svg.opts['scaleHeight'];\t\t\t\n\t\t\t\t\te.attribute('viewBox', true).value = '0 0 ' + (cWidth * xRatio) + ' ' + (cHeight * yRatio);\n\t\t\t\t\te.attribute('preserveAspectRatio', true).value = 'none';\n\t\t\t\t}\n\t\t\t\n\t\t\t\t// clear and render\n\t\t\t\tif (svg.opts['ignoreClear'] != true) {\n\t\t\t\t\tctx.clearRect(0, 0, cWidth, cHeight);\n\t\t\t\t}\n\t\t\t\te.render(ctx);\n\t\t\t\tif (isFirstRender) {\n\t\t\t\t\tisFirstRender = false;\n\t\t\t\t\tif (svg.opts != null && typeof(svg.opts['renderCallback']) == 'function') svg.opts['renderCallback']();\n\t\t\t\t}\t\t\t\n\t\t\t}\n\t\t\t\n\t\t\tvar waitingForImages = true;\n\t\t\tif (svg.ImagesLoaded()) {\n\t\t\t\twaitingForImages = false;\n\t\t\t\tdraw();\n\t\t\t}\n\t\t\tsvg.intervalID = setInterval(function() { \n\t\t\t\tvar needUpdate = false;\n\t\t\t\t\n\t\t\t\tif (waitingForImages && svg.ImagesLoaded()) {\n\t\t\t\t\twaitingForImages = false;\n\t\t\t\t\tneedUpdate = true;\n\t\t\t\t}\n\t\t\t\n\t\t\t\t// need update from mouse events?\n\t\t\t\tif (svg.opts['ignoreMouse'] != true) {\n\t\t\t\t\tneedUpdate = needUpdate | svg.Mouse.hasEvents();\n\t\t\t\t}\n\t\t\t\n\t\t\t\t// need update from animations?\n\t\t\t\tif (svg.opts['ignoreAnimation'] != true) {\n\t\t\t\t\tfor (var i=0; i<svg.Animations.length; i++) {\n\t\t\t\t\t\tneedUpdate = needUpdate | svg.Animations[i].update(1000 / svg.FRAMERATE);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// need update from redraw?\n\t\t\t\tif (svg.opts != null && typeof(svg.opts['forceRedraw']) == 'function') {\n\t\t\t\t\tif (svg.opts['forceRedraw']() == true) needUpdate = true;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// render if needed\n\t\t\t\tif (needUpdate) {\n\t\t\t\t\tdraw();\t\t\t\t\n\t\t\t\t\tsvg.Mouse.runEvents(); // run and clear our events\n\t\t\t\t}\n\t\t\t}, 1000 / svg.FRAMERATE);\n\t\t}\n\t\t\n\t\tsvg.stop = function() {\n\t\t\tif (svg.intervalID) {\n\t\t\t\tclearInterval(svg.intervalID);\n\t\t\t}\n\t\t}\n\t\t\n\t\tsvg.Mouse = new (function() {\n\t\t\tthis.events = [];\n\t\t\tthis.hasEvents = function() { return this.events.length != 0; }\n\t\t\n\t\t\tthis.onclick = function(x, y) {\n\t\t\t\tthis.events.push({ type: 'onclick', x: x, y: y, \n\t\t\t\t\trun: function(e) { if (e.onclick) e.onclick(); }\n\t\t\t\t});\n\t\t\t}\n\t\t\t\n\t\t\tthis.onmousemove = function(x, y) {\n\t\t\t\tthis.events.push({ type: 'onmousemove', x: x, y: y,\n\t\t\t\t\trun: function(e) { if (e.onmousemove) e.onmousemove(); }\n\t\t\t\t});\n\t\t\t}\t\t\t\n\t\t\t\n\t\t\tthis.eventElements = [];\n\t\t\t\n\t\t\tthis.checkPath = function(element, ctx) {\n\t\t\t\tfor (var i=0; i<this.events.length; i++) {\n\t\t\t\t\tvar e = this.events[i];\n\t\t\t\t\tif (ctx.isPointInPath && ctx.isPointInPath(e.x, e.y)) this.eventElements[i] = element;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tthis.checkBoundingBox = function(element, bb) {\n\t\t\t\tfor (var i=0; i<this.events.length; i++) {\n\t\t\t\t\tvar e = this.events[i];\n\t\t\t\t\tif (bb.isPointInBox(e.x, e.y)) this.eventElements[i] = element;\n\t\t\t\t}\t\t\t\n\t\t\t}\n\t\t\t\n\t\t\tthis.runEvents = function() {\n\t\t\t\tsvg.ctx.canvas.style.cursor = '';\n\t\t\t\t\n\t\t\t\tfor (var i=0; i<this.events.length; i++) {\n\t\t\t\t\tvar e = this.events[i];\n\t\t\t\t\tvar element = this.eventElements[i];\n\t\t\t\t\twhile (element) {\n\t\t\t\t\t\te.run(element);\n\t\t\t\t\t\telement = element.parent;\n\t\t\t\t\t}\n\t\t\t\t}\t\t\n\t\t\t\n\t\t\t\t// done running, clear\n\t\t\t\tthis.events = []; \n\t\t\t\tthis.eventElements = [];\n\t\t\t}\n\t\t});\n\t\t\n\t\treturn svg;\n\t}\n})();\n\nif (CanvasRenderingContext2D) {\n\tCanvasRenderingContext2D.prototype.drawSvg = function(s, dx, dy, dw, dh) {\n\t\tcanvg(this.canvas, s, { \n\t\t\tignoreMouse: true, \n\t\t\tignoreAnimation: true, \n\t\t\tignoreDimensions: true, \n\t\t\tignoreClear: true, \n\t\t\toffsetX: dx, \n\t\t\toffsetY: dy, \n\t\t\tscaleWidth: dw, \n\t\t\tscaleHeight: dh\n\t\t});\n\t}\n}/**\n * @license Highcharts JS v3.0.3 (2013-07-31)\n * CanVGRenderer Extension module\n *\n * (c) 2011-2012 Torstein Hønsi, Erik Olsson\n *\n * License: www.highcharts.com/license\n */\n\n// JSLint options:\n/*global Highcharts */\n\n(function (Highcharts) { // encapsulate\n\tvar UNDEFINED,\n\t\tDIV = 'div',\n\t\tABSOLUTE = 'absolute',\n\t\tRELATIVE = 'relative',\n\t\tHIDDEN = 'hidden',\n\t\tVISIBLE = 'visible',\n\t\tPX = 'px',\n\t\tcss = Highcharts.css,\n\t\tCanVGRenderer = Highcharts.CanVGRenderer,\n\t\tSVGRenderer = Highcharts.SVGRenderer,\n\t\textend = Highcharts.extend,\n\t\tmerge = Highcharts.merge,\n\t\taddEvent = Highcharts.addEvent,\n\t\tcreateElement = Highcharts.createElement,\n\t\tdiscardElement = Highcharts.discardElement;\n\n\t// Extend CanVG renderer on demand, inherit from SVGRenderer\n\textend(CanVGRenderer.prototype, SVGRenderer.prototype);\n\n\t// Add additional functionality:\n\textend(CanVGRenderer.prototype, {\n\t\tcreate: function (chart, container, chartWidth, chartHeight) {\n\t\t\tthis.setContainer(container, chartWidth, chartHeight);\n\t\t\tthis.configure(chart);\n\t\t},\n\t\tsetContainer: function (container, chartWidth, chartHeight) {\n\t\t\tvar containerStyle = container.style,\n\t\t\t\tcontainerParent = container.parentNode,\n\t\t\t\tcontainerLeft = containerStyle.left,\n\t\t\t\tcontainerTop = containerStyle.top,\n\t\t\t\tcontainerOffsetWidth = container.offsetWidth,\n\t\t\t\tcontainerOffsetHeight = container.offsetHeight,\n\t\t\t\tcanvas,\n\t\t\t\tinitialHiddenStyle = { visibility: HIDDEN, position: ABSOLUTE };\n\n\t\t\tthis.init.apply(this, [container, chartWidth, chartHeight]);\n\n\t\t\t// add the canvas above it\n\t\t\tcanvas = createElement('canvas', {\n\t\t\t\twidth: containerOffsetWidth,\n\t\t\t\theight: containerOffsetHeight\n\t\t\t}, {\n\t\t\t\tposition: RELATIVE,\n\t\t\t\tleft: containerLeft,\n\t\t\t\ttop: containerTop\n\t\t\t}, container);\n\t\t\tthis.canvas = canvas;\n\n\t\t\t// Create the tooltip line and div, they are placed as siblings to\n\t\t\t// the container (and as direct childs to the div specified in the html page)\n\t\t\tthis.ttLine = createElement(DIV, null, initialHiddenStyle, containerParent);\n\t\t\tthis.ttDiv = createElement(DIV, null, initialHiddenStyle, containerParent);\n\t\t\tthis.ttTimer = UNDEFINED;\n\n\t\t\t// Move away the svg node to a new div inside the container's parent so we can hide it.\n\t\t\tvar hiddenSvg = createElement(DIV, {\n\t\t\t\twidth: containerOffsetWidth,\n\t\t\t\theight: containerOffsetHeight\n\t\t\t}, {\n\t\t\t\tvisibility: HIDDEN,\n\t\t\t\tleft: containerLeft,\n\t\t\t\ttop: containerTop\n\t\t\t}, containerParent);\n\t\t\tthis.hiddenSvg = hiddenSvg;\n\t\t\thiddenSvg.appendChild(this.box);\n\t\t},\n\n\t\t/**\n\t\t * Configures the renderer with the chart. Attach a listener to the event tooltipRefresh.\n\t\t **/\n\t\tconfigure: function (chart) {\n\t\t\tvar renderer = this,\n\t\t\t\toptions = chart.options.tooltip,\n\t\t\t\tborderWidth = options.borderWidth,\n\t\t\t\ttooltipDiv = renderer.ttDiv,\n\t\t\t\ttooltipDivStyle = options.style,\n\t\t\t\ttooltipLine = renderer.ttLine,\n\t\t\t\tpadding = parseInt(tooltipDivStyle.padding, 10);\n\n\t\t\t// Add border styling from options to the style\n\t\t\ttooltipDivStyle = merge(tooltipDivStyle, {\n\t\t\t\tpadding: padding + PX,\n\t\t\t\t'background-color': options.backgroundColor,\n\t\t\t\t'border-style': 'solid',\n\t\t\t\t'border-width': borderWidth + PX,\n\t\t\t\t'border-radius': options.borderRadius + PX\n\t\t\t});\n\n\t\t\t// Optionally add shadow\n\t\t\tif (options.shadow) {\n\t\t\t\ttooltipDivStyle = merge(tooltipDivStyle, {\n\t\t\t\t\t'box-shadow': '1px 1px 3px gray', // w3c\n\t\t\t\t\t'-webkit-box-shadow': '1px 1px 3px gray' // webkit\n\t\t\t\t});\n\t\t\t}\n\t\t\tcss(tooltipDiv, tooltipDivStyle);\n\n\t\t\t// Set simple style on the line\n\t\t\tcss(tooltipLine, {\n\t\t\t\t'border-left': '1px solid darkgray'\n\t\t\t});\n\n\t\t\t// This event is triggered when a new tooltip should be shown\n\t\t\taddEvent(chart, 'tooltipRefresh', function (args) {\n\t\t\t\tvar chartContainer = chart.container,\n\t\t\t\t\toffsetLeft = chartContainer.offsetLeft,\n\t\t\t\t\toffsetTop = chartContainer.offsetTop,\n\t\t\t\t\tposition;\n\n\t\t\t\t// Set the content of the tooltip\n\t\t\t\ttooltipDiv.innerHTML = args.text;\n\n\t\t\t\t// Compute the best position for the tooltip based on the divs size and container size.\n\t\t\t\tposition = chart.tooltip.getPosition(tooltipDiv.offsetWidth, tooltipDiv.offsetHeight, {plotX: args.x, plotY: args.y});\n\n\t\t\t\tcss(tooltipDiv, {\n\t\t\t\t\tvisibility: VISIBLE,\n\t\t\t\t\tleft: position.x + PX,\n\t\t\t\t\ttop: position.y + PX,\n\t\t\t\t\t'border-color': args.borderColor\n\t\t\t\t});\n\n\t\t\t\t// Position the tooltip line\n\t\t\t\tcss(tooltipLine, {\n\t\t\t\t\tvisibility: VISIBLE,\n\t\t\t\t\tleft: offsetLeft + args.x + PX,\n\t\t\t\t\ttop: offsetTop + chart.plotTop + PX,\n\t\t\t\t\theight: chart.plotHeight  + PX\n\t\t\t\t});\n\n\t\t\t\t// This timeout hides the tooltip after 3 seconds\n\t\t\t\t// First clear any existing timer\n\t\t\t\tif (renderer.ttTimer !== UNDEFINED) {\n\t\t\t\t\tclearTimeout(renderer.ttTimer);\n\t\t\t\t}\n\n\t\t\t\t// Start a new timer that hides tooltip and line\n\t\t\t\trenderer.ttTimer = setTimeout(function () {\n\t\t\t\t\tcss(tooltipDiv, { visibility: HIDDEN });\n\t\t\t\t\tcss(tooltipLine, { visibility: HIDDEN });\n\t\t\t\t}, 3000);\n\t\t\t});\n\t\t},\n\n\t\t/**\n\t\t * Extend SVGRenderer.destroy to also destroy the elements added by CanVGRenderer.\n\t\t */\n\t\tdestroy: function () {\n\t\t\tvar renderer = this;\n\n\t\t\t// Remove the canvas\n\t\t\tdiscardElement(renderer.canvas);\n\n\t\t\t// Kill the timer\n\t\t\tif (renderer.ttTimer !== UNDEFINED) {\n\t\t\t\tclearTimeout(renderer.ttTimer);\n\t\t\t}\n\n\t\t\t// Remove the divs for tooltip and line\n\t\t\tdiscardElement(renderer.ttLine);\n\t\t\tdiscardElement(renderer.ttDiv);\n\t\t\tdiscardElement(renderer.hiddenSvg);\n\n\t\t\t// Continue with base class\n\t\t\treturn SVGRenderer.prototype.destroy.apply(renderer);\n\t\t},\n\n\t\t/**\n\t\t * Take a color and return it if it's a string, do not make it a gradient even if it is a\n\t\t * gradient. Currently canvg cannot render gradients (turns out black),\n\t\t * see: http://code.google.com/p/canvg/issues/detail?id=104\n\t\t *\n\t\t * @param {Object} color The color or config object\n\t\t */\n\t\tcolor: function (color, elem, prop) {\n\t\t\tif (color && color.linearGradient) {\n\t\t\t\t// Pick the end color and forward to base implementation\n\t\t\t\tcolor = color.stops[color.stops.length - 1][1];\n\t\t\t}\n\t\t\treturn SVGRenderer.prototype.color.call(this, color, elem, prop);\n\t\t},\n\n\t\t/**\n\t\t * Draws the SVG on the canvas or adds a draw invokation to the deferred list.\n\t\t */\n\t\tdraw: function () {\n\t\t\tvar renderer = this;\n\t\t\twindow.canvg(renderer.canvas, renderer.hiddenSvg.innerHTML);\n\t\t}\n\t});\n}(Highcharts));\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/highchart3/js/modules/data.js",
    "content": "/*\n Data plugin for Highcharts\n\n (c) 2012-2013 Torstein Hønsi\n Last revision 2013-06-07\n\n License: www.highcharts.com/license\n*/\n(function(h){var k=h.each,m=function(b,a){this.init(b,a)};h.extend(m.prototype,{init:function(b,a){this.options=b;this.chartOptions=a;this.columns=b.columns||this.rowsToColumns(b.rows)||[];this.columns.length?this.dataFound():(this.parseCSV(),this.parseTable(),this.parseGoogleSpreadsheet())},getColumnDistribution:function(){var b=this.chartOptions,a=b&&b.chart&&b.chart.type,c=[];k(b&&b.series||[],function(b){c.push((h.seriesTypes[b.type||a||\"line\"].prototype.pointArrayMap||[0]).length)});this.valueCount=\n{global:(h.seriesTypes[a||\"line\"].prototype.pointArrayMap||[0]).length,individual:c}},dataFound:function(){this.parseTypes();this.findHeaderRow();this.parsed();this.complete()},parseCSV:function(){var b=this,a=this.options,c=a.csv,d=this.columns,f=a.startRow||0,i=a.endRow||Number.MAX_VALUE,j=a.startColumn||0,e=a.endColumn||Number.MAX_VALUE,g=0;c&&(c=c.replace(/\\r\\n/g,\"\\n\").replace(/\\r/g,\"\\n\").split(a.lineDelimiter||\"\\n\"),k(c,function(c,h){var n=b.trim(c),p=n.indexOf(\"#\")===0;h>=f&&h<=i&&!p&&n!==\"\"&&\n(n=c.split(a.itemDelimiter||\",\"),k(n,function(b,a){a>=j&&a<=e&&(d[a-j]||(d[a-j]=[]),d[a-j][g]=b)}),g+=1)}),this.dataFound())},parseTable:function(){var b=this.options,a=b.table,c=this.columns,d=b.startRow||0,f=b.endRow||Number.MAX_VALUE,i=b.startColumn||0,j=b.endColumn||Number.MAX_VALUE,e;a&&(typeof a===\"string\"&&(a=document.getElementById(a)),k(a.getElementsByTagName(\"tr\"),function(a,b){e=0;b>=d&&b<=f&&k(a.childNodes,function(a){if((a.tagName===\"TD\"||a.tagName===\"TH\")&&e>=i&&e<=j)c[e]||(c[e]=[]),\nc[e][b-d]=a.innerHTML,e+=1})}),this.dataFound())},parseGoogleSpreadsheet:function(){var b=this,a=this.options,c=a.googleSpreadsheetKey,d=this.columns,f=a.startRow||0,i=a.endRow||Number.MAX_VALUE,j=a.startColumn||0,e=a.endColumn||Number.MAX_VALUE,g,h;c&&jQuery.getJSON(\"https://spreadsheets.google.com/feeds/cells/\"+c+\"/\"+(a.googleSpreadsheetWorksheet||\"od6\")+\"/public/values?alt=json-in-script&callback=?\",function(a){var a=a.feed.entry,c,k=a.length,m=0,o=0,l;for(l=0;l<k;l++)c=a[l],m=Math.max(m,c.gs$cell.col),\no=Math.max(o,c.gs$cell.row);for(l=0;l<m;l++)if(l>=j&&l<=e)d[l-j]=[],d[l-j].length=Math.min(o,i-f);for(l=0;l<k;l++)if(c=a[l],g=c.gs$cell.row-1,h=c.gs$cell.col-1,h>=j&&h<=e&&g>=f&&g<=i)d[h-j][g-f]=c.content.$t;b.dataFound()})},findHeaderRow:function(){k(this.columns,function(){});this.headerRow=0},trim:function(b){return typeof b===\"string\"?b.replace(/^\\s+|\\s+$/g,\"\"):b},parseTypes:function(){for(var b=this.columns,a=b.length,c,d,f,i;a--;)for(c=b[a].length;c--;)d=b[a][c],f=parseFloat(d),i=this.trim(d),\ni==f?(b[a][c]=f,f>31536E6?b[a].isDatetime=!0:b[a].isNumeric=!0):(d=this.parseDate(d),a===0&&typeof d===\"number\"&&!isNaN(d)?(b[a][c]=d,b[a].isDatetime=!0):b[a][c]=i===\"\"?null:i)},dateFormats:{\"YYYY-mm-dd\":{regex:\"^([0-9]{4})-([0-9]{2})-([0-9]{2})$\",parser:function(b){return Date.UTC(+b[1],b[2]-1,+b[3])}}},parseDate:function(b){var a=this.options.parseDate,c,d,f;a&&(c=a(b));if(typeof b===\"string\")for(d in this.dateFormats)a=this.dateFormats[d],(f=b.match(a.regex))&&(c=a.parser(f));return c},rowsToColumns:function(b){var a,\nc,d,f,i;if(b){i=[];c=b.length;for(a=0;a<c;a++){f=b[a].length;for(d=0;d<f;d++)i[d]||(i[d]=[]),i[d][a]=b[a][d]}}return i},parsed:function(){this.options.parsed&&this.options.parsed.call(this,this.columns)},complete:function(){var b=this.columns,a,c,d=this.options,f,i,j,e,g,k;if(d.complete){this.getColumnDistribution();b.length>1&&(a=b.shift(),this.headerRow===0&&a.shift(),a.isDatetime?c=\"datetime\":a.isNumeric||(c=\"category\"));for(e=0;e<b.length;e++)if(this.headerRow===0)b[e].name=b[e].shift();i=[];\nfor(e=0,k=0;e<b.length;k++){f=h.pick(this.valueCount.individual[k],this.valueCount.global);j=[];for(g=0;g<b[e].length;g++)j[g]=[a[g],b[e][g]!==void 0?b[e][g]:null],f>1&&j[g].push(b[e+1][g]!==void 0?b[e+1][g]:null),f>2&&j[g].push(b[e+2][g]!==void 0?b[e+2][g]:null),f>3&&j[g].push(b[e+3][g]!==void 0?b[e+3][g]:null),f>4&&j[g].push(b[e+4][g]!==void 0?b[e+4][g]:null);i[k]={name:b[e].name,data:j};e+=f}d.complete({xAxis:{type:c},series:i})}}});h.Data=m;h.data=function(b,a){return new m(b,a)};h.wrap(h.Chart.prototype,\n\"init\",function(b,a,c){var d=this;a&&a.data?h.data(h.extend(a.data,{complete:function(f){a.series&&k(a.series,function(b,c){a.series[c]=h.merge(b,f.series[c])});a=h.merge(f,a);b.call(d,a,c)}}),a):b.call(d,a,c)})})(Highcharts);\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/highchart3/js/modules/data.src.js",
    "content": "/**\n * @license Data plugin for Highcharts\n *\n * (c) 2012-2013 Torstein Hønsi\n * Last revision 2013-06-07\n *\n * License: www.highcharts.com/license\n */\n\n/*\n * The Highcharts Data plugin is a utility to ease parsing of input sources like\n * CSV, HTML tables or grid views into basic configuration options for use \n * directly in the Highcharts constructor.\n *\n * Demo: http://jsfiddle.net/highcharts/SnLFj/\n *\n * --- OPTIONS ---\n *\n * - columns : Array<Array<Mixed>>\n * A two-dimensional array representing the input data on tabular form. This input can\n * be used when the data is already parsed, for example from a grid view component.\n * Each cell can be a string or number. If not switchRowsAndColumns is set, the columns\n * are interpreted as series. See also the rows option.\n *\n * - complete : Function(chartOptions)\n * The callback that is evaluated when the data is finished loading, optionally from an \n * external source, and parsed. The first argument passed is a finished chart options\n * object, containing series and an xAxis with categories if applicable. Thise options\n * can be extended with additional options and passed directly to the chart constructor.\n *\n * - csv : String\n * A comma delimited string to be parsed. Related options are startRow, endRow, startColumn\n * and endColumn to delimit what part of the table is used. The lineDelimiter and \n * itemDelimiter options define the CSV delimiter formats.\n * \n * - endColumn : Integer\n * In tabular input data, the first row (indexed by 0) to use. Defaults to the last \n * column containing data.\n *\n * - endRow : Integer\n * In tabular input data, the last row (indexed by 0) to use. Defaults to the last row\n * containing data.\n *\n * - googleSpreadsheetKey : String \n * A Google Spreadsheet key. See https://developers.google.com/gdata/samples/spreadsheet_sample\n * for general information on GS.\n *\n * - googleSpreadsheetWorksheet : String \n * The Google Spreadsheet worksheet. The available id's can be read from \n * https://spreadsheets.google.com/feeds/worksheets/{key}/public/basic\n *\n * - itemDelimiter : String\n * Item or cell delimiter for parsing CSV. Defaults to \",\".\n *\n * - lineDelimiter : String\n * Line delimiter for parsing CSV. Defaults to \"\\n\".\n *\n * - parsed : Function\n * A callback function to access the parsed columns, the two-dimentional input data\n * array directly, before they are interpreted into series data and categories.\n *\n * - parseDate : Function\n * A callback function to parse string representations of dates into JavaScript timestamps.\n * Return an integer on success.\n *\n * - rows : Array<Array<Mixed>>\n * The same as the columns input option, but defining rows intead of columns.\n *\n * - startColumn : Integer\n * In tabular input data, the first column (indexed by 0) to use. \n *\n * - startRow : Integer\n * In tabular input data, the first row (indexed by 0) to use.\n *\n * - table : String|HTMLElement\n * A HTML table or the id of such to be parsed as input data. Related options ara startRow,\n * endRow, startColumn and endColumn to delimit what part of the table is used.\n */\n\n// JSLint options:\n/*global jQuery */\n\n(function (Highcharts) {\t\n\t\n\t// Utilities\n\tvar each = Highcharts.each;\n\t\n\t\n\t// The Data constructor\n\tvar Data = function (dataOptions, chartOptions) {\n\t\tthis.init(dataOptions, chartOptions);\n\t};\n\t\n\t// Set the prototype properties\n\tHighcharts.extend(Data.prototype, {\n\t\t\n\t/**\n\t * Initialize the Data object with the given options\n\t */\n\tinit: function (options, chartOptions) {\n\t\tthis.options = options;\n\t\tthis.chartOptions = chartOptions;\n\t\tthis.columns = options.columns || this.rowsToColumns(options.rows) || [];\n\n\t\t// No need to parse or interpret anything\n\t\tif (this.columns.length) {\n\t\t\tthis.dataFound();\n\n\t\t// Parse and interpret\n\t\t} else {\n\n\t\t\t// Parse a CSV string if options.csv is given\n\t\t\tthis.parseCSV();\n\t\t\t\n\t\t\t// Parse a HTML table if options.table is given\n\t\t\tthis.parseTable();\n\n\t\t\t// Parse a Google Spreadsheet \n\t\t\tthis.parseGoogleSpreadsheet();\t\n\t\t}\n\n\t},\n\n\t/**\n\t * Get the column distribution. For example, a line series takes a single column for \n\t * Y values. A range series takes two columns for low and high values respectively,\n\t * and an OHLC series takes four columns.\n\t */\n\tgetColumnDistribution: function () {\n\t\tvar chartOptions = this.chartOptions,\n\t\t\tgetValueCount = function (type) {\n\t\t\t\treturn (Highcharts.seriesTypes[type || 'line'].prototype.pointArrayMap || [0]).length;\n\t\t\t},\n\t\t\tglobalType = chartOptions && chartOptions.chart && chartOptions.chart.type,\n\t\t\tindividualCounts = [];\n\n\t\teach((chartOptions && chartOptions.series) || [], function (series) {\n\t\t\tindividualCounts.push(getValueCount(series.type || globalType));\n\t\t});\n\n\t\tthis.valueCount = {\n\t\t\tglobal: getValueCount(globalType),\n\t\t\tindividual: individualCounts\n\t\t};\n\t},\n\n\n\tdataFound: function () {\n\t\t// Interpret the values into right types\n\t\tthis.parseTypes();\n\t\t\n\t\t// Use first row for series names?\n\t\tthis.findHeaderRow();\n\t\t\n\t\t// Handle columns if a handleColumns callback is given\n\t\tthis.parsed();\n\t\t\n\t\t// Complete if a complete callback is given\n\t\tthis.complete();\n\t\t\n\t},\n\t\n\t/**\n\t * Parse a CSV input string\n\t */\n\tparseCSV: function () {\n\t\tvar self = this,\n\t\t\toptions = this.options,\n\t\t\tcsv = options.csv,\n\t\t\tcolumns = this.columns,\n\t\t\tstartRow = options.startRow || 0,\n\t\t\tendRow = options.endRow || Number.MAX_VALUE,\n\t\t\tstartColumn = options.startColumn || 0,\n\t\t\tendColumn = options.endColumn || Number.MAX_VALUE,\n\t\t\tlines,\n\t\t\tactiveRowNo = 0;\n\t\t\t\n\t\tif (csv) {\n\t\t\t\n\t\t\tlines = csv\n\t\t\t\t.replace(/\\r\\n/g, \"\\n\") // Unix\n\t\t\t\t.replace(/\\r/g, \"\\n\") // Mac\n\t\t\t\t.split(options.lineDelimiter || \"\\n\");\n\t\t\t\n\t\t\teach(lines, function (line, rowNo) {\n\t\t\t\tvar trimmed = self.trim(line),\n\t\t\t\t\tisComment = trimmed.indexOf('#') === 0,\n\t\t\t\t\tisBlank = trimmed === '',\n\t\t\t\t\titems;\n\t\t\t\t\n\t\t\t\tif (rowNo >= startRow && rowNo <= endRow && !isComment && !isBlank) {\n\t\t\t\t\titems = line.split(options.itemDelimiter || ',');\n\t\t\t\t\teach(items, function (item, colNo) {\n\t\t\t\t\t\tif (colNo >= startColumn && colNo <= endColumn) {\n\t\t\t\t\t\t\tif (!columns[colNo - startColumn]) {\n\t\t\t\t\t\t\t\tcolumns[colNo - startColumn] = [];\t\t\t\t\t\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tcolumns[colNo - startColumn][activeRowNo] = item;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tactiveRowNo += 1;\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tthis.dataFound();\n\t\t}\n\t},\n\t\n\t/**\n\t * Parse a HTML table\n\t */\n\tparseTable: function () {\n\t\tvar options = this.options,\n\t\t\ttable = options.table,\n\t\t\tcolumns = this.columns,\n\t\t\tstartRow = options.startRow || 0,\n\t\t\tendRow = options.endRow || Number.MAX_VALUE,\n\t\t\tstartColumn = options.startColumn || 0,\n\t\t\tendColumn = options.endColumn || Number.MAX_VALUE,\n\t\t\tcolNo;\n\t\t\t\n\t\tif (table) {\n\t\t\t\n\t\t\tif (typeof table === 'string') {\n\t\t\t\ttable = document.getElementById(table);\n\t\t\t}\n\t\t\t\n\t\t\teach(table.getElementsByTagName('tr'), function (tr, rowNo) {\n\t\t\t\tcolNo = 0; \n\t\t\t\tif (rowNo >= startRow && rowNo <= endRow) {\n\t\t\t\t\teach(tr.childNodes, function (item) {\n\t\t\t\t\t\tif ((item.tagName === 'TD' || item.tagName === 'TH') && colNo >= startColumn && colNo <= endColumn) {\n\t\t\t\t\t\t\tif (!columns[colNo]) {\n\t\t\t\t\t\t\t\tcolumns[colNo] = [];\t\t\t\t\t\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcolumns[colNo][rowNo - startRow] = item.innerHTML;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tcolNo += 1;\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\tthis.dataFound(); // continue\n\t\t}\n\t},\n\n\t/**\n\t * TODO: \n\t * - switchRowsAndColumns\n\t */\n\tparseGoogleSpreadsheet: function () {\n\t\tvar self = this,\n\t\t\toptions = this.options,\n\t\t\tgoogleSpreadsheetKey = options.googleSpreadsheetKey,\n\t\t\tcolumns = this.columns,\n\t\t\tstartRow = options.startRow || 0,\n\t\t\tendRow = options.endRow || Number.MAX_VALUE,\n\t\t\tstartColumn = options.startColumn || 0,\n\t\t\tendColumn = options.endColumn || Number.MAX_VALUE,\n\t\t\tgr, // google row\n\t\t\tgc; // google column\n\n\t\tif (googleSpreadsheetKey) {\n\t\t\tjQuery.getJSON('https://spreadsheets.google.com/feeds/cells/' + \n\t\t\t\t  googleSpreadsheetKey + '/' + (options.googleSpreadsheetWorksheet || 'od6') +\n\t\t\t\t\t  '/public/values?alt=json-in-script&callback=?',\n\t\t\t\t\t  function (json) {\n\t\t\t\t\t\n\t\t\t\t// Prepare the data from the spreadsheat\n\t\t\t\tvar cells = json.feed.entry,\n\t\t\t\t\tcell,\n\t\t\t\t\tcellCount = cells.length,\n\t\t\t\t\tcolCount = 0,\n\t\t\t\t\trowCount = 0,\n\t\t\t\t\ti;\n\t\t\t\n\t\t\t\t// First, find the total number of columns and rows that \n\t\t\t\t// are actually filled with data\n\t\t\t\tfor (i = 0; i < cellCount; i++) {\n\t\t\t\t\tcell = cells[i];\n\t\t\t\t\tcolCount = Math.max(colCount, cell.gs$cell.col);\n\t\t\t\t\trowCount = Math.max(rowCount, cell.gs$cell.row);\t\t\t\n\t\t\t\t}\n\t\t\t\n\t\t\t\t// Set up arrays containing the column data\n\t\t\t\tfor (i = 0; i < colCount; i++) {\n\t\t\t\t\tif (i >= startColumn && i <= endColumn) {\n\t\t\t\t\t\t// Create new columns with the length of either end-start or rowCount\n\t\t\t\t\t\tcolumns[i - startColumn] = [];\n\n\t\t\t\t\t\t// Setting the length to avoid jslint warning\n\t\t\t\t\t\tcolumns[i - startColumn].length = Math.min(rowCount, endRow - startRow);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// Loop over the cells and assign the value to the right\n\t\t\t\t// place in the column arrays\n\t\t\t\tfor (i = 0; i < cellCount; i++) {\n\t\t\t\t\tcell = cells[i];\n\t\t\t\t\tgr = cell.gs$cell.row - 1; // rows start at 1\n\t\t\t\t\tgc = cell.gs$cell.col - 1; // columns start at 1\n\n\t\t\t\t\t// If both row and col falls inside start and end\n\t\t\t\t\t// set the transposed cell value in the newly created columns\n\t\t\t\t\tif (gc >= startColumn && gc <= endColumn &&\n\t\t\t\t\t\tgr >= startRow && gr <= endRow) {\n\t\t\t\t\t\tcolumns[gc - startColumn][gr - startRow] = cell.content.$t;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tself.dataFound();\n\t\t\t});\n\t\t}\n\t},\n\t\n\t/**\n\t * Find the header row. For now, we just check whether the first row contains\n\t * numbers or strings. Later we could loop down and find the first row with \n\t * numbers.\n\t */\n\tfindHeaderRow: function () {\n\t\tvar headerRow = 0;\n\t\teach(this.columns, function (column) {\n\t\t\tif (typeof column[0] !== 'string') {\n\t\t\t\theaderRow = null;\n\t\t\t}\n\t\t});\n\t\tthis.headerRow = 0;\t\t\t\n\t},\n\t\n\t/**\n\t * Trim a string from whitespace\n\t */\n\ttrim: function (str) {\n\t\treturn typeof str === 'string' ? str.replace(/^\\s+|\\s+$/g, '') : str;\n\t},\n\t\n\t/**\n\t * Parse numeric cells in to number types and date types in to true dates.\n\t * @param {Object} columns\n\t */\n\tparseTypes: function () {\n\t\tvar columns = this.columns,\n\t\t\tcol = columns.length, \n\t\t\trow,\n\t\t\tval,\n\t\t\tfloatVal,\n\t\t\ttrimVal,\n\t\t\tdateVal;\n\t\t\t\n\t\twhile (col--) {\n\t\t\trow = columns[col].length;\n\t\t\twhile (row--) {\n\t\t\t\tval = columns[col][row];\n\t\t\t\tfloatVal = parseFloat(val);\n\t\t\t\ttrimVal = this.trim(val);\n\n\t\t\t\t/*jslint eqeq: true*/\n\t\t\t\tif (trimVal == floatVal) { // is numeric\n\t\t\t\t/*jslint eqeq: false*/\n\t\t\t\t\tcolumns[col][row] = floatVal;\n\t\t\t\t\t\n\t\t\t\t\t// If the number is greater than milliseconds in a year, assume datetime\n\t\t\t\t\tif (floatVal > 365 * 24 * 3600 * 1000) {\n\t\t\t\t\t\tcolumns[col].isDatetime = true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcolumns[col].isNumeric = true;\n\t\t\t\t\t}\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t} else { // string, continue to determine if it is a date string or really a string\n\t\t\t\t\tdateVal = this.parseDate(val);\n\t\t\t\t\t\n\t\t\t\t\tif (col === 0 && typeof dateVal === 'number' && !isNaN(dateVal)) { // is date\n\t\t\t\t\t\tcolumns[col][row] = dateVal;\n\t\t\t\t\t\tcolumns[col].isDatetime = true;\n\t\t\t\t\t\n\t\t\t\t\t} else { // string\n\t\t\t\t\t\tcolumns[col][row] = trimVal === '' ? null : trimVal;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t}\n\t\t}\n\t},\n\t//*\n\tdateFormats: {\n\t\t'YYYY-mm-dd': {\n\t\t\tregex: '^([0-9]{4})-([0-9]{2})-([0-9]{2})$',\n\t\t\tparser: function (match) {\n\t\t\t\treturn Date.UTC(+match[1], match[2] - 1, +match[3]);\n\t\t\t}\n\t\t}\n\t},\n\t// */\n\t/**\n\t * Parse a date and return it as a number. Overridable through options.parseDate.\n\t */\n\tparseDate: function (val) {\n\t\tvar parseDate = this.options.parseDate,\n\t\t\tret,\n\t\t\tkey,\n\t\t\tformat,\n\t\t\tmatch;\n\n\t\tif (parseDate) {\n\t\t\tret = parseDate(val);\n\t\t}\n\t\t\t\n\t\tif (typeof val === 'string') {\n\t\t\tfor (key in this.dateFormats) {\n\t\t\t\tformat = this.dateFormats[key];\n\t\t\t\tmatch = val.match(format.regex);\n\t\t\t\tif (match) {\n\t\t\t\t\tret = format.parser(match);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn ret;\n\t},\n\t\n\t/**\n\t * Reorganize rows into columns\n\t */\n\trowsToColumns: function (rows) {\n\t\tvar row,\n\t\t\trowsLength,\n\t\t\tcol,\n\t\t\tcolsLength,\n\t\t\tcolumns;\n\n\t\tif (rows) {\n\t\t\tcolumns = [];\n\t\t\trowsLength = rows.length;\n\t\t\tfor (row = 0; row < rowsLength; row++) {\n\t\t\t\tcolsLength = rows[row].length;\n\t\t\t\tfor (col = 0; col < colsLength; col++) {\n\t\t\t\t\tif (!columns[col]) {\n\t\t\t\t\t\tcolumns[col] = [];\n\t\t\t\t\t}\n\t\t\t\t\tcolumns[col][row] = rows[row][col];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn columns;\n\t},\n\t\n\t/**\n\t * A hook for working directly on the parsed columns\n\t */\n\tparsed: function () {\n\t\tif (this.options.parsed) {\n\t\t\tthis.options.parsed.call(this, this.columns);\n\t\t}\n\t},\n\t\n\t/**\n\t * If a complete callback function is provided in the options, interpret the \n\t * columns into a Highcharts options object.\n\t */\n\tcomplete: function () {\n\t\t\n\t\tvar columns = this.columns,\n\t\t\tfirstCol,\n\t\t\ttype,\n\t\t\toptions = this.options,\n\t\t\tvalueCount,\n\t\t\tseries,\n\t\t\tdata,\n\t\t\ti,\n\t\t\tj,\n\t\t\tseriesIndex;\n\t\t\t\n\t\t\n\t\tif (options.complete) {\n\n\t\t\tthis.getColumnDistribution();\n\t\t\t\n\t\t\t// Use first column for X data or categories?\n\t\t\tif (columns.length > 1) {\n\t\t\t\tfirstCol = columns.shift();\n\t\t\t\tif (this.headerRow === 0) {\n\t\t\t\t\tfirstCol.shift(); // remove the first cell\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t\n\t\t\t\tif (firstCol.isDatetime) {\n\t\t\t\t\ttype = 'datetime';\n\t\t\t\t} else if (!firstCol.isNumeric) {\n\t\t\t\t\ttype = 'category';\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Get the names and shift the top row\n\t\t\tfor (i = 0; i < columns.length; i++) {\n\t\t\t\tif (this.headerRow === 0) {\n\t\t\t\t\tcolumns[i].name = columns[i].shift();\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t// Use the next columns for series\n\t\t\tseries = [];\n\t\t\tfor (i = 0, seriesIndex = 0; i < columns.length; seriesIndex++) {\n\n\t\t\t\t// This series' value count\n\t\t\t\tvalueCount = Highcharts.pick(this.valueCount.individual[seriesIndex], this.valueCount.global);\n\t\t\t\t\n\t\t\t\t// Iterate down the cells of each column and add data to the series\n\t\t\t\tdata = [];\n\t\t\t\tfor (j = 0; j < columns[i].length; j++) {\n\t\t\t\t\tdata[j] = [\n\t\t\t\t\t\tfirstCol[j], \n\t\t\t\t\t\tcolumns[i][j] !== undefined ? columns[i][j] : null\n\t\t\t\t\t];\n\t\t\t\t\tif (valueCount > 1) {\n\t\t\t\t\t\tdata[j].push(columns[i + 1][j] !== undefined ? columns[i + 1][j] : null);\n\t\t\t\t\t}\n\t\t\t\t\tif (valueCount > 2) {\n\t\t\t\t\t\tdata[j].push(columns[i + 2][j] !== undefined ? columns[i + 2][j] : null);\n\t\t\t\t\t}\n\t\t\t\t\tif (valueCount > 3) {\n\t\t\t\t\t\tdata[j].push(columns[i + 3][j] !== undefined ? columns[i + 3][j] : null);\n\t\t\t\t\t}\n\t\t\t\t\tif (valueCount > 4) {\n\t\t\t\t\t\tdata[j].push(columns[i + 4][j] !== undefined ? columns[i + 4][j] : null);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Add the series\n\t\t\t\tseries[seriesIndex] = {\n\t\t\t\t\tname: columns[i].name,\n\t\t\t\t\tdata: data\n\t\t\t\t};\n\n\t\t\t\ti += valueCount;\n\t\t\t}\n\t\t\t\n\t\t\t// Do the callback\n\t\t\toptions.complete({\n\t\t\t\txAxis: {\n\t\t\t\t\ttype: type\n\t\t\t\t},\n\t\t\t\tseries: series\n\t\t\t});\n\t\t}\n\t}\n\t});\n\t\n\t// Register the Data prototype and data function on Highcharts\n\tHighcharts.Data = Data;\n\tHighcharts.data = function (options, chartOptions) {\n\t\treturn new Data(options, chartOptions);\n\t};\n\n\t// Extend Chart.init so that the Chart constructor accepts a new configuration\n\t// option group, data.\n\tHighcharts.wrap(Highcharts.Chart.prototype, 'init', function (proceed, userOptions, callback) {\n\t\tvar chart = this;\n\n\t\tif (userOptions && userOptions.data) {\n\t\t\tHighcharts.data(Highcharts.extend(userOptions.data, {\n\t\t\t\tcomplete: function (dataOptions) {\n\t\t\t\t\t\n\t\t\t\t\t// Merge series configs\n\t\t\t\t\tif (userOptions.series) {\n\t\t\t\t\t\teach(userOptions.series, function (series, i) {\n\t\t\t\t\t\t\tuserOptions.series[i] = Highcharts.merge(series, dataOptions.series[i]);\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\t// Do the merge\n\t\t\t\t\tuserOptions = Highcharts.merge(dataOptions, userOptions);\n\n\t\t\t\t\tproceed.call(chart, userOptions, callback);\n\t\t\t\t}\n\t\t\t}), userOptions);\n\t\t} else {\n\t\t\tproceed.call(chart, userOptions, callback);\n\t\t}\n\t});\n\n}(Highcharts));\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/highchart3/js/modules/exporting.js",
    "content": "/*\n Highcharts JS v3.0.3 (2013-07-31)\n Exporting module\n\n (c) 2010-2013 Torstein Hønsi\n\n License: www.highcharts.com/license\n*/\n(function(e){var y=e.Chart,v=e.addEvent,B=e.removeEvent,m=e.createElement,j=e.discardElement,t=e.css,k=e.merge,r=e.each,p=e.extend,C=Math.max,i=document,z=window,D=e.isTouchDevice,E=e.Renderer.prototype.symbols,s=e.getOptions(),w;p(s.lang,{printChart:\"Print chart\",downloadPNG:\"Download PNG image\",downloadJPEG:\"Download JPEG image\",downloadPDF:\"Download PDF document\",downloadSVG:\"Download SVG vector image\",contextButtonTitle:\"Chart context menu\"});s.navigation={menuStyle:{border:\"1px solid #A0A0A0\",\nbackground:\"#FFFFFF\",padding:\"5px 0\"},menuItemStyle:{padding:\"0 10px\",background:\"none\",color:\"#303030\",fontSize:D?\"14px\":\"11px\"},menuItemHoverStyle:{background:\"#4572A5\",color:\"#FFFFFF\"},buttonOptions:{symbolFill:\"#E0E0E0\",symbolSize:14,symbolStroke:\"#666\",symbolStrokeWidth:3,symbolX:12.5,symbolY:10.5,align:\"right\",buttonSpacing:3,height:22,theme:{fill:\"white\",stroke:\"none\"},verticalAlign:\"top\",width:24}};s.exporting={type:\"image/png\",url:\"http://export.highcharts.com/\",buttons:{contextButton:{symbol:\"menu\",\n_titleKey:\"contextButtonTitle\",menuItems:[{textKey:\"printChart\",onclick:function(){this.print()}},{separator:!0},{textKey:\"downloadPNG\",onclick:function(){this.exportChart()}},{textKey:\"downloadJPEG\",onclick:function(){this.exportChart({type:\"image/jpeg\"})}},{textKey:\"downloadPDF\",onclick:function(){this.exportChart({type:\"application/pdf\"})}},{textKey:\"downloadSVG\",onclick:function(){this.exportChart({type:\"image/svg+xml\"})}}]}}};e.post=function(a,b){var c,d;d=m(\"form\",{method:\"post\",action:a,enctype:\"multipart/form-data\"},\n{display:\"none\"},i.body);for(c in b)m(\"input\",{type:\"hidden\",name:c,value:b[c]},null,d);d.submit();j(d)};p(y.prototype,{getSVG:function(a){var b=this,c,d,x,g,f=k(b.options,a);if(!i.createElementNS)i.createElementNS=function(a,b){return i.createElement(b)};a=m(\"div\",null,{position:\"absolute\",top:\"-9999em\",width:b.chartWidth+\"px\",height:b.chartHeight+\"px\"},i.body);d=b.renderTo.style.width;g=b.renderTo.style.height;d=f.exporting.sourceWidth||f.chart.width||/px$/.test(d)&&parseInt(d,10)||600;g=f.exporting.sourceHeight||\nf.chart.height||/px$/.test(g)&&parseInt(g,10)||400;p(f.chart,{animation:!1,renderTo:a,forExport:!0,width:d,height:g});f.exporting.enabled=!1;f.series=[];r(b.series,function(a){x=k(a.options,{animation:!1,showCheckbox:!1,visible:a.visible});x.isInternal||f.series.push(x)});c=new e.Chart(f,b.callback);r([\"xAxis\",\"yAxis\"],function(a){r(b[a],function(b,f){var d=c[a][f],e=b.getExtremes(),g=e.userMin,e=e.userMax;d&&(g!==void 0||e!==void 0)&&d.setExtremes(g,e,!0,!1)})});d=c.container.innerHTML;f=null;c.destroy();\nj(a);d=d.replace(/zIndex=\"[^\"]+\"/g,\"\").replace(/isShadow=\"[^\"]+\"/g,\"\").replace(/symbolName=\"[^\"]+\"/g,\"\").replace(/jQuery[0-9]+=\"[^\"]+\"/g,\"\").replace(/url\\([^#]+#/g,\"url(#\").replace(/<svg /,'<svg xmlns:xlink=\"http://www.w3.org/1999/xlink\" ').replace(/ href=/g,\" xlink:href=\").replace(/\\n/,\" \").replace(/<\\/svg>.*?$/,\"</svg>\").replace(/&nbsp;/g,\" \").replace(/&shy;/g,\"­\").replace(/<IMG /g,\"<image \").replace(/height=([^\" ]+)/g,'height=\"$1\"').replace(/width=([^\" ]+)/g,'width=\"$1\"').replace(/hc-svg-href=\"([^\"]+)\">/g,\n'xlink:href=\"$1\"/>').replace(/id=([^\" >]+)/g,'id=\"$1\"').replace(/class=([^\" >]+)/g,'class=\"$1\"').replace(/ transform /g,\" \").replace(/:(path|rect)/g,\"$1\").replace(/style=\"([^\"]+)\"/g,function(a){return a.toLowerCase()});return d=d.replace(/(url\\(#highcharts-[0-9]+)&quot;/g,\"$1\").replace(/&quot;/g,\"'\")},exportChart:function(a,b){var a=a||{},c=this.options.exporting,c=this.getSVG(k({chart:{borderRadius:0}},c.chartOptions,b,{exporting:{sourceWidth:a.sourceWidth||c.sourceWidth,sourceHeight:a.sourceHeight||\nc.sourceHeight}})),a=k(this.options.exporting,a);e.post(a.url,{filename:a.filename||\"chart\",type:a.type,width:a.width||0,scale:a.scale||2,svg:c})},print:function(){var a=this,b=a.container,c=[],d=b.parentNode,e=i.body,g=e.childNodes;if(!a.isPrinting)a.isPrinting=!0,r(g,function(a,b){if(a.nodeType===1)c[b]=a.style.display,a.style.display=\"none\"}),e.appendChild(b),z.focus(),z.print(),setTimeout(function(){d.appendChild(b);r(g,function(a,b){if(a.nodeType===1)a.style.display=c[b]});a.isPrinting=!1},1E3)},\ncontextMenu:function(a,b,c,d,e,g,f){var h=this,q=h.options.navigation,n=q.menuItemStyle,o=h.chartWidth,i=h.chartHeight,A=\"cache-\"+a,l=h[A],k=C(e,g),u,j,s;if(!l)h[A]=l=m(\"div\",{className:\"highcharts-\"+a},{position:\"absolute\",zIndex:1E3,padding:k+\"px\"},h.container),u=m(\"div\",null,p({MozBoxShadow:\"3px 3px 10px #888\",WebkitBoxShadow:\"3px 3px 10px #888\",boxShadow:\"3px 3px 10px #888\"},q.menuStyle),l),j=function(){t(l,{display:\"none\"});f&&f.setState(0);h.openMenu=!1},v(l,\"mouseleave\",function(){s=setTimeout(j,\n500)}),v(l,\"mouseenter\",function(){clearTimeout(s)}),r(b,function(a){if(a){var b=a.separator?m(\"hr\",null,null,u):m(\"div\",{onmouseover:function(){t(this,q.menuItemHoverStyle)},onmouseout:function(){t(this,n)},onclick:function(){j();a.onclick.apply(h,arguments)},innerHTML:a.text||h.options.lang[a.textKey]},p({cursor:\"pointer\"},n),u);h.exportDivElements.push(b)}}),h.exportDivElements.push(u,l),h.exportMenuWidth=l.offsetWidth,h.exportMenuHeight=l.offsetHeight;a={display:\"block\"};c+h.exportMenuWidth>o?\na.right=o-c-e-k+\"px\":a.left=c-k+\"px\";d+g+h.exportMenuHeight>i&&f.alignOptions.verticalAlign!==\"top\"?a.bottom=i-d-k+\"px\":a.top=d+g-k+\"px\";t(l,a);h.openMenu=!0},addButton:function(a){var b=this,c=b.renderer,a=k(b.options.navigation.buttonOptions,a),d=a.onclick,i=a.menuItems,g,f,h={stroke:a.symbolStroke,fill:a.symbolFill},q=a.symbolSize||12;if(!b.btnCount)b.btnCount=0;b.btnCount++;if(!b.exportDivElements)b.exportDivElements=[],b.exportSVGElements=[];if(a.enabled!==!1){var n=a.theme,o=n.states,m=o&&o.hover,\no=o&&o.select,j;delete n.states;d?j=function(){d.apply(b,arguments)}:i&&(j=function(){b.contextMenu(\"contextmenu\",i,f.translateX,f.translateY,f.width,f.height,f);f.setState(2)});a.text&&a.symbol?n.paddingLeft=e.pick(n.paddingLeft,25):a.text||p(n,{width:a.width,height:a.height,padding:0});f=c.button(a.text,0,0,j,n,m,o).attr({title:b.options.lang[a._titleKey],\"stroke-linecap\":\"round\"});a.symbol&&(g=c.symbol(a.symbol,a.symbolX-q/2,a.symbolY-q/2,q,q).attr(p(h,{\"stroke-width\":a.symbolStrokeWidth||1,zIndex:1})).add(f));\nf.add().align(p(a,{width:f.width,x:e.pick(a.x,w)}),!0,\"spacingBox\");w+=(f.width+a.buttonSpacing)*(a.align===\"right\"?-1:1);b.exportSVGElements.push(f,g)}},destroyExport:function(a){var a=a.target,b,c;for(b=0;b<a.exportSVGElements.length;b++)if(c=a.exportSVGElements[b])c.onclick=c.ontouchstart=null,a.exportSVGElements[b]=c.destroy();for(b=0;b<a.exportDivElements.length;b++)c=a.exportDivElements[b],B(c,\"mouseleave\"),a.exportDivElements[b]=c.onmouseout=c.onmouseover=c.ontouchstart=c.onclick=null,j(c)}});\nE.menu=function(a,b,c,d){return[\"M\",a,b+2.5,\"L\",a+c,b+2.5,\"M\",a,b+d/2+0.5,\"L\",a+c,b+d/2+0.5,\"M\",a,b+d-1.5,\"L\",a+c,b+d-1.5]};y.prototype.callbacks.push(function(a){var b,c=a.options.exporting,d=c.buttons;w=0;if(c.enabled!==!1){for(b in d)a.addButton(d[b]);v(a,\"destroy\",a.destroyExport)}})})(Highcharts);\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/highchart3/js/modules/exporting.src.js",
    "content": "/**\n * @license Highcharts JS v3.0.3 (2013-07-31)\n * Exporting module\n *\n * (c) 2010-2013 Torstein Hønsi\n *\n * License: www.highcharts.com/license\n */\n\n// JSLint options:\n/*global Highcharts, document, window, Math, setTimeout */\n\n(function (Highcharts) { // encapsulate\n\n// create shortcuts\nvar Chart = Highcharts.Chart,\n\taddEvent = Highcharts.addEvent,\n\tremoveEvent = Highcharts.removeEvent,\n\tcreateElement = Highcharts.createElement,\n\tdiscardElement = Highcharts.discardElement,\n\tcss = Highcharts.css,\n\tmerge = Highcharts.merge,\n\teach = Highcharts.each,\n\textend = Highcharts.extend,\n\tmath = Math,\n\tmathMax = math.max,\n\tdoc = document,\n\twin = window,\n\tisTouchDevice = Highcharts.isTouchDevice,\n\tM = 'M',\n\tL = 'L',\n\tDIV = 'div',\n\tHIDDEN = 'hidden',\n\tNONE = 'none',\n\tPREFIX = 'highcharts-',\n\tABSOLUTE = 'absolute',\n\tPX = 'px',\n\tUNDEFINED,\n\tsymbols = Highcharts.Renderer.prototype.symbols,\n\tdefaultOptions = Highcharts.getOptions(),\n\tbuttonOffset;\n\n\t// Add language\n\textend(defaultOptions.lang, {\n\t\tprintChart: 'Print chart',\n\t\tdownloadPNG: 'Download PNG image',\n\t\tdownloadJPEG: 'Download JPEG image',\n\t\tdownloadPDF: 'Download PDF document',\n\t\tdownloadSVG: 'Download SVG vector image',\n\t\tcontextButtonTitle: 'Chart context menu'\n\t});\n\n// Buttons and menus are collected in a separate config option set called 'navigation'.\n// This can be extended later to add control buttons like zoom and pan right click menus.\ndefaultOptions.navigation = {\n\tmenuStyle: {\n\t\tborder: '1px solid #A0A0A0',\n\t\tbackground: '#FFFFFF',\n\t\tpadding: '5px 0'\n\t},\n\tmenuItemStyle: {\n\t\tpadding: '0 10px',\n\t\tbackground: NONE,\n\t\tcolor: '#303030',\n\t\tfontSize: isTouchDevice ? '14px' : '11px'\n\t},\n\tmenuItemHoverStyle: {\n\t\tbackground: '#4572A5',\n\t\tcolor: '#FFFFFF'\n\t},\n\n\tbuttonOptions: {\n\t\tsymbolFill: '#E0E0E0',\n\t\tsymbolSize: 14,\n\t\tsymbolStroke: '#666',\n\t\tsymbolStrokeWidth: 3,\n\t\tsymbolX: 12.5,\n\t\tsymbolY: 10.5,\n\t\talign: 'right',\n\t\tbuttonSpacing: 3, \n\t\theight: 22,\n\t\t// text: null,\n\t\ttheme: {\n\t\t\tfill: 'white', // capture hover\n\t\t\tstroke: 'none'\n\t\t},\n\t\tverticalAlign: 'top',\n\t\twidth: 24\n\t}\n};\n\n\n\n// Add the export related options\ndefaultOptions.exporting = {\n\t//enabled: true,\n\t//filename: 'chart',\n\ttype: 'image/png',\n\turl: 'http://export.highcharts.com/',\n\t//width: undefined,\n\t//scale: 2\n\tbuttons: {\n\t\tcontextButton: {\n\t\t\t//x: -10,\n\t\t\tsymbol: 'menu',\n\t\t\t_titleKey: 'contextButtonTitle',\n\t\t\tmenuItems: [{\n\t\t\t\ttextKey: 'printChart',\n\t\t\t\tonclick: function () {\n\t\t\t\t\tthis.print();\n\t\t\t\t}\n\t\t\t}, {\n\t\t\t\tseparator: true\n\t\t\t}, {\n\t\t\t\ttextKey: 'downloadPNG',\n\t\t\t\tonclick: function () {\n\t\t\t\t\tthis.exportChart();\n\t\t\t\t}\n\t\t\t}, {\n\t\t\t\ttextKey: 'downloadJPEG',\n\t\t\t\tonclick: function () {\n\t\t\t\t\tthis.exportChart({\n\t\t\t\t\t\ttype: 'image/jpeg'\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}, {\n\t\t\t\ttextKey: 'downloadPDF',\n\t\t\t\tonclick: function () {\n\t\t\t\t\tthis.exportChart({\n\t\t\t\t\t\ttype: 'application/pdf'\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}, {\n\t\t\t\ttextKey: 'downloadSVG',\n\t\t\t\tonclick: function () {\n\t\t\t\t\tthis.exportChart({\n\t\t\t\t\t\ttype: 'image/svg+xml'\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Enable this block to add \"View SVG\" to the dropdown menu\n\t\t\t/*\n\t\t\t,{\n\n\t\t\t\ttext: 'View SVG',\n\t\t\t\tonclick: function () {\n\t\t\t\t\tvar svg = this.getSVG()\n\t\t\t\t\t\t.replace(/</g, '\\n&lt;')\n\t\t\t\t\t\t.replace(/>/g, '&gt;');\n\n\t\t\t\t\tdoc.body.innerHTML = '<pre>' + svg + '</pre>';\n\t\t\t\t}\n\t\t\t} // */\n\t\t\t]\n\t\t}\n\t}\n};\n\n// Add the Highcharts.post utility\nHighcharts.post = function (url, data) {\n\tvar name,\n\t\tform;\n\t\n\t// create the form\n\tform = createElement('form', {\n\t\tmethod: 'post',\n\t\taction: url,\n\t\tenctype: 'multipart/form-data'\n\t}, {\n\t\tdisplay: NONE\n\t}, doc.body);\n\n\t// add the data\n\tfor (name in data) {\n\t\tcreateElement('input', {\n\t\t\ttype: HIDDEN,\n\t\t\tname: name,\n\t\t\tvalue: data[name]\n\t\t}, null, form);\n\t}\n\n\t// submit\n\tform.submit();\n\n\t// clean up\n\tdiscardElement(form);\n};\n\nextend(Chart.prototype, {\n\n\t/**\n\t * Return an SVG representation of the chart\n\t *\n\t * @param additionalOptions {Object} Additional chart options for the generated SVG representation\n\t */\n\tgetSVG: function (additionalOptions) {\n\t\tvar chart = this,\n\t\t\tchartCopy,\n\t\t\tsandbox,\n\t\t\tsvg,\n\t\t\tseriesOptions,\n\t\t\tsourceWidth,\n\t\t\tsourceHeight,\n\t\t\tcssWidth,\n\t\t\tcssHeight,\n\t\t\toptions = merge(chart.options, additionalOptions); // copy the options and add extra options\n\n\t\t// IE compatibility hack for generating SVG content that it doesn't really understand\n\t\tif (!doc.createElementNS) {\n\t\t\t/*jslint unparam: true*//* allow unused parameter ns in function below */\n\t\t\tdoc.createElementNS = function (ns, tagName) {\n\t\t\t\treturn doc.createElement(tagName);\n\t\t\t};\n\t\t\t/*jslint unparam: false*/\n\t\t}\n\n\t\t// create a sandbox where a new chart will be generated\n\t\tsandbox = createElement(DIV, null, {\n\t\t\tposition: ABSOLUTE,\n\t\t\ttop: '-9999em',\n\t\t\twidth: chart.chartWidth + PX,\n\t\t\theight: chart.chartHeight + PX\n\t\t}, doc.body);\n\t\t\n\t\t// get the source size\n\t\tcssWidth = chart.renderTo.style.width;\n\t\tcssHeight = chart.renderTo.style.height;\n\t\tsourceWidth = options.exporting.sourceWidth ||\n\t\t\toptions.chart.width ||\n\t\t\t(/px$/.test(cssWidth) && parseInt(cssWidth, 10)) ||\n\t\t\t600;\n\t\tsourceHeight = options.exporting.sourceHeight ||\n\t\t\toptions.chart.height ||\n\t\t\t(/px$/.test(cssHeight) && parseInt(cssHeight, 10)) ||\n\t\t\t400;\n\n\t\t// override some options\n\t\textend(options.chart, {\n\t\t\tanimation: false,\n\t\t\trenderTo: sandbox,\n\t\t\tforExport: true,\n\t\t\twidth: sourceWidth,\n\t\t\theight: sourceHeight\n\t\t});\n\t\toptions.exporting.enabled = false; // hide buttons in print\n\t\t\n\t\t// prepare for replicating the chart\n\t\toptions.series = [];\n\t\teach(chart.series, function (serie) {\n\t\t\tseriesOptions = merge(serie.options, {\n\t\t\t\tanimation: false, // turn off animation\n\t\t\t\tshowCheckbox: false,\n\t\t\t\tvisible: serie.visible\n\t\t\t});\n\n\t\t\tif (!seriesOptions.isInternal) { // used for the navigator series that has its own option set\n\t\t\t\toptions.series.push(seriesOptions);\n\t\t\t}\n\t\t});\n\n\t\t// generate the chart copy\n\t\tchartCopy = new Highcharts.Chart(options, chart.callback);\n\n\t\t// reflect axis extremes in the export\n\t\teach(['xAxis', 'yAxis'], function (axisType) {\n\t\t\teach(chart[axisType], function (axis, i) {\n\t\t\t\tvar axisCopy = chartCopy[axisType][i],\n\t\t\t\t\textremes = axis.getExtremes(),\n\t\t\t\t\tuserMin = extremes.userMin,\n\t\t\t\t\tuserMax = extremes.userMax;\n\n\t\t\t\tif (axisCopy && (userMin !== UNDEFINED || userMax !== UNDEFINED)) {\n\t\t\t\t\taxisCopy.setExtremes(userMin, userMax, true, false);\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\n\t\t// get the SVG from the container's innerHTML\n\t\tsvg = chartCopy.container.innerHTML;\n\n\t\t// free up memory\n\t\toptions = null;\n\t\tchartCopy.destroy();\n\t\tdiscardElement(sandbox);\n\n\t\t// sanitize\n\t\tsvg = svg\n\t\t\t.replace(/zIndex=\"[^\"]+\"/g, '')\n\t\t\t.replace(/isShadow=\"[^\"]+\"/g, '')\n\t\t\t.replace(/symbolName=\"[^\"]+\"/g, '')\n\t\t\t.replace(/jQuery[0-9]+=\"[^\"]+\"/g, '')\n\t\t\t.replace(/url\\([^#]+#/g, 'url(#')\n\t\t\t.replace(/<svg /, '<svg xmlns:xlink=\"http://www.w3.org/1999/xlink\" ')\n\t\t\t.replace(/ href=/g, ' xlink:href=')\n\t\t\t.replace(/\\n/, ' ')\n\t\t\t.replace(/<\\/svg>.*?$/, '</svg>') // any HTML added to the container after the SVG (#894)\n\t\t\t/* This fails in IE < 8\n\t\t\t.replace(/([0-9]+)\\.([0-9]+)/g, function(s1, s2, s3) { // round off to save weight\n\t\t\t\treturn s2 +'.'+ s3[0];\n\t\t\t})*/\n\n\t\t\t// Replace HTML entities, issue #347\n\t\t\t.replace(/&nbsp;/g, '\\u00A0') // no-break space\n\t\t\t.replace(/&shy;/g,  '\\u00AD') // soft hyphen\n\n\t\t\t// IE specific\n\t\t\t.replace(/<IMG /g, '<image ')\n\t\t\t.replace(/height=([^\" ]+)/g, 'height=\"$1\"')\n\t\t\t.replace(/width=([^\" ]+)/g, 'width=\"$1\"')\n\t\t\t.replace(/hc-svg-href=\"([^\"]+)\">/g, 'xlink:href=\"$1\"/>')\n\t\t\t.replace(/id=([^\" >]+)/g, 'id=\"$1\"')\n\t\t\t.replace(/class=([^\" >]+)/g, 'class=\"$1\"')\n\t\t\t.replace(/ transform /g, ' ')\n\t\t\t.replace(/:(path|rect)/g, '$1')\n\t\t\t.replace(/style=\"([^\"]+)\"/g, function (s) {\n\t\t\t\treturn s.toLowerCase();\n\t\t\t});\n\n\t\t// IE9 beta bugs with innerHTML. Test again with final IE9.\n\t\tsvg = svg.replace(/(url\\(#highcharts-[0-9]+)&quot;/g, '$1')\n\t\t\t.replace(/&quot;/g, \"'\");\n\n\t\treturn svg;\n\t},\n\n\t/**\n\t * Submit the SVG representation of the chart to the server\n\t * @param {Object} options Exporting options. Possible members are url, type and width.\n\t * @param {Object} chartOptions Additional chart options for the SVG representation of the chart\n\t */\n\texportChart: function (options, chartOptions) {\n\t\toptions = options || {};\n\t\t\n\t\tvar chart = this,\n\t\t\tchartExportingOptions = chart.options.exporting,\n\t\t\tsvg = chart.getSVG(merge(\n\t\t\t\t{ chart: { borderRadius: 0 } },\n\t\t\t\tchartExportingOptions.chartOptions,\n\t\t\t\tchartOptions, \n\t\t\t\t{\n\t\t\t\t\texporting: {\n\t\t\t\t\t\tsourceWidth: options.sourceWidth || chartExportingOptions.sourceWidth,\n\t\t\t\t\t\tsourceHeight: options.sourceHeight || chartExportingOptions.sourceHeight\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t));\n\n\t\t// merge the options\n\t\toptions = merge(chart.options.exporting, options);\n\t\t\n\t\t// do the post\n\t\tHighcharts.post(options.url, {\n\t\t\tfilename: options.filename || 'chart',\n\t\t\ttype: options.type,\n\t\t\twidth: options.width || 0, // IE8 fails to post undefined correctly, so use 0\n\t\t\tscale: options.scale || 2,\n\t\t\tsvg: svg\n\t\t});\n\n\t},\n\t\n\t/**\n\t * Print the chart\n\t */\n\tprint: function () {\n\n\t\tvar chart = this,\n\t\t\tcontainer = chart.container,\n\t\t\torigDisplay = [],\n\t\t\torigParent = container.parentNode,\n\t\t\tbody = doc.body,\n\t\t\tchildNodes = body.childNodes;\n\n\t\tif (chart.isPrinting) { // block the button while in printing mode\n\t\t\treturn;\n\t\t}\n\n\t\tchart.isPrinting = true;\n\n\t\t// hide all body content\n\t\teach(childNodes, function (node, i) {\n\t\t\tif (node.nodeType === 1) {\n\t\t\t\torigDisplay[i] = node.style.display;\n\t\t\t\tnode.style.display = NONE;\n\t\t\t}\n\t\t});\n\n\t\t// pull out the chart\n\t\tbody.appendChild(container);\n\n\t\t// print\n\t\twin.focus(); // #1510\n\t\twin.print();\n\n\t\t// allow the browser to prepare before reverting\n\t\tsetTimeout(function () {\n\n\t\t\t// put the chart back in\n\t\t\torigParent.appendChild(container);\n\n\t\t\t// restore all body content\n\t\t\teach(childNodes, function (node, i) {\n\t\t\t\tif (node.nodeType === 1) {\n\t\t\t\t\tnode.style.display = origDisplay[i];\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tchart.isPrinting = false;\n\n\t\t}, 1000);\n\n\t},\n\n\t/**\n\t * Display a popup menu for choosing the export type\n\t *\n\t * @param {String} name An identifier for the menu\n\t * @param {Array} items A collection with text and onclicks for the items\n\t * @param {Number} x The x position of the opener button\n\t * @param {Number} y The y position of the opener button\n\t * @param {Number} width The width of the opener button\n\t * @param {Number} height The height of the opener button\n\t */\n\tcontextMenu: function (name, items, x, y, width, height, button) {\n\t\tvar chart = this,\n\t\t\tnavOptions = chart.options.navigation,\n\t\t\tmenuItemStyle = navOptions.menuItemStyle,\n\t\t\tchartWidth = chart.chartWidth,\n\t\t\tchartHeight = chart.chartHeight,\n\t\t\tcacheName = 'cache-' + name,\n\t\t\tmenu = chart[cacheName],\n\t\t\tmenuPadding = mathMax(width, height), // for mouse leave detection\n\t\t\tboxShadow = '3px 3px 10px #888',\n\t\t\tinnerMenu,\n\t\t\thide,\n\t\t\thideTimer,\n\t\t\tmenuStyle;\n\n\t\t// create the menu only the first time\n\t\tif (!menu) {\n\n\t\t\t// create a HTML element above the SVG\n\t\t\tchart[cacheName] = menu = createElement(DIV, {\n\t\t\t\tclassName: PREFIX + name\n\t\t\t}, {\n\t\t\t\tposition: ABSOLUTE,\n\t\t\t\tzIndex: 1000,\n\t\t\t\tpadding: menuPadding + PX\n\t\t\t}, chart.container);\n\n\t\t\tinnerMenu = createElement(DIV, null,\n\t\t\t\textend({\n\t\t\t\t\tMozBoxShadow: boxShadow,\n\t\t\t\t\tWebkitBoxShadow: boxShadow,\n\t\t\t\t\tboxShadow: boxShadow\n\t\t\t\t}, navOptions.menuStyle), menu);\n\n\t\t\t// hide on mouse out\n\t\t\thide = function () {\n\t\t\t\tcss(menu, { display: NONE });\n\t\t\t\tif (button) {\n\t\t\t\t\tbutton.setState(0);\n\t\t\t\t}\n\t\t\t\tchart.openMenu = false;\n\t\t\t};\n\n\t\t\t// Hide the menu some time after mouse leave (#1357)\n\t\t\taddEvent(menu, 'mouseleave', function () {\n\t\t\t\thideTimer = setTimeout(hide, 500);\n\t\t\t});\n\t\t\taddEvent(menu, 'mouseenter', function () {\n\t\t\t\tclearTimeout(hideTimer);\n\t\t\t});\n\n\n\t\t\t// create the items\n\t\t\teach(items, function (item) {\n\t\t\t\tif (item) {\n\t\t\t\t\tvar element = item.separator ? \n\t\t\t\t\t\tcreateElement('hr', null, null, innerMenu) :\n\t\t\t\t\t\tcreateElement(DIV, {\n\t\t\t\t\t\t\tonmouseover: function () {\n\t\t\t\t\t\t\t\tcss(this, navOptions.menuItemHoverStyle);\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tonmouseout: function () {\n\t\t\t\t\t\t\t\tcss(this, menuItemStyle);\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tonclick: function () {\n\t\t\t\t\t\t\t\thide();\n\t\t\t\t\t\t\t\titem.onclick.apply(chart, arguments);\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tinnerHTML: item.text || chart.options.lang[item.textKey]\n\t\t\t\t\t\t}, extend({\n\t\t\t\t\t\t\tcursor: 'pointer'\n\t\t\t\t\t\t}, menuItemStyle), innerMenu);\n\n\n\t\t\t\t\t// Keep references to menu divs to be able to destroy them\n\t\t\t\t\tchart.exportDivElements.push(element);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// Keep references to menu and innerMenu div to be able to destroy them\n\t\t\tchart.exportDivElements.push(innerMenu, menu);\n\n\t\t\tchart.exportMenuWidth = menu.offsetWidth;\n\t\t\tchart.exportMenuHeight = menu.offsetHeight;\n\t\t}\n\n\t\tmenuStyle = { display: 'block' };\n\n\t\t// if outside right, right align it\n\t\tif (x + chart.exportMenuWidth > chartWidth) {\n\t\t\tmenuStyle.right = (chartWidth - x - width - menuPadding) + PX;\n\t\t} else {\n\t\t\tmenuStyle.left = (x - menuPadding) + PX;\n\t\t}\n\t\t// if outside bottom, bottom align it\n\t\tif (y + height + chart.exportMenuHeight > chartHeight && button.alignOptions.verticalAlign !== 'top') {\n\t\t\tmenuStyle.bottom = (chartHeight - y - menuPadding)  + PX;\n\t\t} else {\n\t\t\tmenuStyle.top = (y + height - menuPadding) + PX;\n\t\t}\n\n\t\tcss(menu, menuStyle);\n\t\tchart.openMenu = true;\n\t},\n\n\t/**\n\t * Add the export button to the chart\n\t */\n\taddButton: function (options) {\n\t\tvar chart = this,\n\t\t\trenderer = chart.renderer,\n\t\t\tbtnOptions = merge(chart.options.navigation.buttonOptions, options),\n\t\t\tonclick = btnOptions.onclick,\n\t\t\tmenuItems = btnOptions.menuItems,\n\t\t\tsymbol,\n\t\t\tbutton,\n\t\t\tsymbolAttr = {\n\t\t\t\tstroke: btnOptions.symbolStroke,\n\t\t\t\tfill: btnOptions.symbolFill\n\t\t\t},\n\t\t\tsymbolSize = btnOptions.symbolSize || 12,\n\t\t\tmenuKey;\n\n\t\tif (!chart.btnCount) {\n\t\t\tchart.btnCount = 0;\n\t\t}\n\t\tmenuKey = chart.btnCount++;\n\n\t\t// Keeps references to the button elements\n\t\tif (!chart.exportDivElements) {\n\t\t\tchart.exportDivElements = [];\n\t\t\tchart.exportSVGElements = [];\n\t\t}\n\n\t\tif (btnOptions.enabled === false) {\n\t\t\treturn;\n\t\t}\n\n\n\t\tvar attr = btnOptions.theme,\n\t\t\tstates = attr.states,\n\t\t\thover = states && states.hover,\n\t\t\tselect = states && states.select,\n\t\t\tcallback;\n\n\t\tdelete attr.states;\n\n\t\tif (onclick) {\n\t\t\tcallback = function () {\n\t\t\t\tonclick.apply(chart, arguments);\n\t\t\t};\n\n\t\t} else if (menuItems) {\n\t\t\tcallback = function () {\n\t\t\t\tchart.contextMenu(\n\t\t\t\t\t'contextmenu', \n\t\t\t\t\tmenuItems, \n\t\t\t\t\tbutton.translateX, \n\t\t\t\t\tbutton.translateY, \n\t\t\t\t\tbutton.width, \n\t\t\t\t\tbutton.height,\n\t\t\t\t\tbutton\n\t\t\t\t);\n\t\t\t\tbutton.setState(2);\n\t\t\t};\n\t\t}\n\n\n\t\tif (btnOptions.text && btnOptions.symbol) {\n\t\t\tattr.paddingLeft = Highcharts.pick(attr.paddingLeft, 25);\n\t\t\n\t\t} else if (!btnOptions.text) {\n\t\t\textend(attr, {\n\t\t\t\twidth: btnOptions.width,\n\t\t\t\theight: btnOptions.height,\n\t\t\t\tpadding: 0\n\t\t\t});\n\t\t}\n\n\t\tbutton = renderer.button(btnOptions.text, 0, 0, callback, attr, hover, select)\n\t\t\t.attr({\n\t\t\t\ttitle: chart.options.lang[btnOptions._titleKey],\n\t\t\t\t'stroke-linecap': 'round'\n\t\t\t});\n\n\t\tif (btnOptions.symbol) {\n\t\t\tsymbol = renderer.symbol(\n\t\t\t\t\tbtnOptions.symbol,\n\t\t\t\t\tbtnOptions.symbolX - (symbolSize / 2),\n\t\t\t\t\tbtnOptions.symbolY - (symbolSize / 2),\n\t\t\t\t\tsymbolSize,\t\t\t\t\n\t\t\t\t\tsymbolSize\n\t\t\t\t)\n\t\t\t\t.attr(extend(symbolAttr, {\n\t\t\t\t\t'stroke-width': btnOptions.symbolStrokeWidth || 1,\n\t\t\t\t\tzIndex: 1\n\t\t\t\t})).add(button);\n\t\t}\n\n\t\tbutton.add()\n\t\t\t.align(extend(btnOptions, {\n\t\t\t\twidth: button.width,\n\t\t\t\tx: Highcharts.pick(btnOptions.x, buttonOffset) // #1654\n\t\t\t}), true, 'spacingBox');\n\n\t\tbuttonOffset += (button.width + btnOptions.buttonSpacing) * (btnOptions.align === 'right' ? -1 : 1);\n\n\t\tchart.exportSVGElements.push(button, symbol);\n\n\t},\n\n\t/**\n\t * Destroy the buttons.\n\t */\n\tdestroyExport: function (e) {\n\t\tvar chart = e.target,\n\t\t\ti,\n\t\t\telem;\n\n\t\t// Destroy the extra buttons added\n\t\tfor (i = 0; i < chart.exportSVGElements.length; i++) {\n\t\t\telem = chart.exportSVGElements[i];\n\t\t\t\n\t\t\t// Destroy and null the svg/vml elements\n\t\t\tif (elem) { // #1822\n\t\t\t\telem.onclick = elem.ontouchstart = null;\n\t\t\t\tchart.exportSVGElements[i] = elem.destroy();\n\t\t\t}\n\t\t}\n\n\t\t// Destroy the divs for the menu\n\t\tfor (i = 0; i < chart.exportDivElements.length; i++) {\n\t\t\telem = chart.exportDivElements[i];\n\n\t\t\t// Remove the event handler\n\t\t\tremoveEvent(elem, 'mouseleave');\n\n\t\t\t// Remove inline events\n\t\t\tchart.exportDivElements[i] = elem.onmouseout = elem.onmouseover = elem.ontouchstart = elem.onclick = null;\n\n\t\t\t// Destroy the div by moving to garbage bin\n\t\t\tdiscardElement(elem);\n\t\t}\n\t}\n});\n\n\nsymbols.menu = function (x, y, width, height) {\n\tvar arr = [\n\t\tM, x, y + 2.5,\n\t\tL, x + width, y + 2.5,\n\t\tM, x, y + height / 2 + 0.5,\n\t\tL, x + width, y + height / 2 + 0.5,\n\t\tM, x, y + height - 1.5,\n\t\tL, x + width, y + height - 1.5\n\t];\n\treturn arr;\n};\n\n// Add the buttons on chart load\nChart.prototype.callbacks.push(function (chart) {\n\tvar n,\n\t\texportingOptions = chart.options.exporting,\n\t\tbuttons = exportingOptions.buttons;\n\n\tbuttonOffset = 0;\n\n\tif (exportingOptions.enabled !== false) {\n\n\t\tfor (n in buttons) {\n\t\t\tchart.addButton(buttons[n]);\n\t\t}\n\n\t\t// Destroy the export elements at chart destroy\n\t\taddEvent(chart, 'destroy', chart.destroyExport);\n\t}\n\n});\n\n\n}(Highcharts));\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/highchart3/js/modules/funnel.js",
    "content": "/*\n \n Highcharts funnel module, Beta\n\n (c) 2010-2012 Torstein Hønsi\n\n License: www.highcharts.com/license\n*/\n(function(d){var u=d.getOptions().plotOptions,p=d.seriesTypes,D=d.merge,B=function(){},z=d.each;u.funnel=D(u.pie,{center:[\"50%\",\"50%\"],width:\"90%\",neckWidth:\"30%\",height:\"100%\",neckHeight:\"25%\",dataLabels:{connectorWidth:1,connectorColor:\"#606060\"},size:!0,states:{select:{color:\"#C0C0C0\",borderColor:\"#000000\",shadow:!1}}});p.funnel=d.extendClass(p.pie,{type:\"funnel\",animate:B,translate:function(){var a=function(k,a){return/%$/.test(k)?a*parseInt(k,10)/100:parseInt(k,10)},g=0,e=this.chart,f=e.plotWidth,\ne=e.plotHeight,h=0,c=this.options,C=c.center,b=a(C[0],f),d=a(C[0],e),p=a(c.width,f),i,q,j=a(c.height,e),r=a(c.neckWidth,f),s=a(c.neckHeight,e),v=j-s,a=this.data,w,x,u=c.dataLabels.position===\"left\"?1:0,y,m,A,n,l,t,o;this.getWidthAt=q=function(k){return k>j-s||j===s?r:r+(p-r)*((j-s-k)/(j-s))};this.getX=function(k,a){return b+(a?-1:1)*(q(k)/2+c.dataLabels.distance)};this.center=[b,d,j];this.centerX=b;z(a,function(a){g+=a.y});z(a,function(a){o=null;x=g?a.y/g:0;m=d-j/2+h*j;l=m+x*j;i=q(m);y=b-i/2;A=y+\ni;i=q(l);n=b-i/2;t=n+i;m>v?(y=n=b-r/2,A=t=b+r/2):l>v&&(o=l,i=q(v),n=b-i/2,t=n+i,l=v);w=[\"M\",y,m,\"L\",A,m,t,l];o&&w.push(t,o,n,o);w.push(n,l,\"Z\");a.shapeType=\"path\";a.shapeArgs={d:w};a.percentage=x*100;a.plotX=b;a.plotY=(m+(o||l))/2;a.tooltipPos=[b,a.plotY];a.slice=B;a.half=u;h+=x});this.setTooltipPoints()},drawPoints:function(){var a=this,g=a.options,e=a.chart.renderer;z(a.data,function(f){var h=f.graphic,c=f.shapeArgs;h?h.animate(c):f.graphic=e.path(c).attr({fill:f.color,stroke:g.borderColor,\"stroke-width\":g.borderWidth}).add(a.group)})},\ndrawDataLabels:function(){var a=this.data,g=this.options.dataLabels.distance,e,f,h,c=a.length,d,b;for(this.center[2]-=2*g;c--;)h=a[c],f=(e=h.half)?1:-1,b=h.plotY,d=this.getX(b,e),h.labelPos=[0,b,d+(g-5)*f,b,d+g*f,b,e?\"right\":\"left\",0];p.pie.prototype.drawDataLabels.call(this)}})})(Highcharts);\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/highchart3/js/modules/funnel.src.js",
    "content": "/**\n * @license \n * Highcharts funnel module, Beta\n *\n * (c) 2010-2012 Torstein Hønsi\n *\n * License: www.highcharts.com/license\n */\n\n/*global Highcharts */\n(function (Highcharts) {\n\t\n'use strict';\n\n// create shortcuts\nvar defaultOptions = Highcharts.getOptions(),\n\tdefaultPlotOptions = defaultOptions.plotOptions,\n\tseriesTypes = Highcharts.seriesTypes,\n\tmerge = Highcharts.merge,\n\tnoop = function () {},\n\teach = Highcharts.each;\n\n// set default options\ndefaultPlotOptions.funnel = merge(defaultPlotOptions.pie, {\n\tcenter: ['50%', '50%'],\n\twidth: '90%',\n\tneckWidth: '30%',\n\theight: '100%',\n\tneckHeight: '25%',\n\n\tdataLabels: {\n\t\t//position: 'right',\n\t\tconnectorWidth: 1,\n\t\tconnectorColor: '#606060'\n\t},\n\tsize: true, // to avoid adapting to data label size in Pie.drawDataLabels\n\tstates: {\n\t\tselect: {\n\t\t\tcolor: '#C0C0C0',\n\t\t\tborderColor: '#000000',\n\t\t\tshadow: false\n\t\t}\n\t}\t\n});\n\n\nseriesTypes.funnel = Highcharts.extendClass(seriesTypes.pie, {\n\t\n\ttype: 'funnel',\n\tanimate: noop,\n\n\t/**\n\t * Overrides the pie translate method\n\t */\n\ttranslate: function () {\n\t\t\n\t\tvar \n\t\t\t// Get positions - either an integer or a percentage string must be given\n\t\t\tgetLength = function (length, relativeTo) {\n\t\t\t\treturn (/%$/).test(length) ?\n\t\t\t\t\trelativeTo * parseInt(length, 10) / 100 :\n\t\t\t\t\tparseInt(length, 10);\n\t\t\t},\n\t\t\t\n\t\t\tsum = 0,\n\t\t\tseries = this,\n\t\t\tchart = series.chart,\n\t\t\tplotWidth = chart.plotWidth,\n\t\t\tplotHeight = chart.plotHeight,\n\t\t\tcumulative = 0, // start at top\n\t\t\toptions = series.options,\n\t\t\tcenter = options.center,\n\t\t\tcenterX = getLength(center[0], plotWidth),\n\t\t\tcenterY = getLength(center[0], plotHeight),\n\t\t\twidth = getLength(options.width, plotWidth),\n\t\t\ttempWidth,\n\t\t\tgetWidthAt,\n\t\t\theight = getLength(options.height, plotHeight),\n\t\t\tneckWidth = getLength(options.neckWidth, plotWidth),\n\t\t\tneckHeight = getLength(options.neckHeight, plotHeight),\n\t\t\tneckY = height - neckHeight,\n\t\t\tdata = series.data,\n\t\t\tpath,\n\t\t\tfraction,\n\t\t\thalf = options.dataLabels.position === 'left' ? 1 : 0,\n\n\t\t\tx1, \n\t\t\ty1, \n\t\t\tx2, \n\t\t\tx3, \n\t\t\ty3, \n\t\t\tx4, \n\t\t\ty5;\n\n\t\t// Return the width at a specific y coordinate\n\t\tseries.getWidthAt = getWidthAt = function (y) {\n\t\t\treturn y > height - neckHeight || height === neckHeight ?\n\t\t\t\tneckWidth :\n\t\t\t\tneckWidth + (width - neckWidth) * ((height - neckHeight - y) / (height - neckHeight));\n\t\t};\n\t\tseries.getX = function (y, half) {\n\t\t\treturn centerX + (half ? -1 : 1) * ((getWidthAt(y) / 2) + options.dataLabels.distance);\n\t\t};\n\n\t\t// Expose\n\t\tseries.center = [centerX, centerY, height];\n\t\tseries.centerX = centerX;\n\n\t\t/*\n\t\t * Individual point coordinate naming:\n\t\t *\n\t\t * x1,y1 _________________ x2,y1\n\t\t *  \\                         /\n\t\t *   \\                       /\n\t\t *    \\                     /\n\t\t *     \\                   /\n\t\t *      \\                 /\n\t\t *     x3,y3 _________ x4,y3\n\t\t *\n\t\t * Additional for the base of the neck:\n\t\t *\n\t\t *       |               |\n\t\t *       |               |\n\t\t *       |               |\n\t\t *     x3,y5 _________ x4,y5\n\t\t */\n\n\n\n\n\t\t// get the total sum\n\t\teach(data, function (point) {\n\t\t\tsum += point.y;\n\t\t});\n\n\t\teach(data, function (point) {\n\t\t\t// set start and end positions\n\t\t\ty5 = null;\n\t\t\tfraction = sum ? point.y / sum : 0;\n\t\t\ty1 = centerY - height / 2 + cumulative * height;\n\t\t\ty3 = y1 + fraction * height;\n\t\t\t//tempWidth = neckWidth + (width - neckWidth) * ((height - neckHeight - y1) / (height - neckHeight));\n\t\t\ttempWidth = getWidthAt(y1);\n\t\t\tx1 = centerX - tempWidth / 2;\n\t\t\tx2 = x1 + tempWidth;\n\t\t\ttempWidth = getWidthAt(y3);\n\t\t\tx3 = centerX - tempWidth / 2;\n\t\t\tx4 = x3 + tempWidth;\n\n\t\t\t// the entire point is within the neck\n\t\t\tif (y1 > neckY) {\n\t\t\t\tx1 = x3 = centerX - neckWidth / 2;\n\t\t\t\tx2 = x4 = centerX + neckWidth / 2;\n\t\t\t\n\t\t\t// the base of the neck\n\t\t\t} else if (y3 > neckY) {\n\t\t\t\ty5 = y3;\n\n\t\t\t\ttempWidth = getWidthAt(neckY);\n\t\t\t\tx3 = centerX - tempWidth / 2;\n\t\t\t\tx4 = x3 + tempWidth;\n\n\t\t\t\ty3 = neckY;\n\t\t\t}\n\n\t\t\t// save the path\n\t\t\tpath = [\n\t\t\t\t'M',\n\t\t\t\tx1, y1,\n\t\t\t\t'L',\n\t\t\t\tx2, y1,\n\t\t\t\tx4, y3\n\t\t\t];\n\t\t\tif (y5) {\n\t\t\t\tpath.push(x4, y5, x3, y5);\n\t\t\t}\n\t\t\tpath.push(x3, y3, 'Z');\n\n\t\t\t// prepare for using shared dr\n\t\t\tpoint.shapeType = 'path';\n\t\t\tpoint.shapeArgs = { d: path };\n\n\n\t\t\t// for tooltips and data labels\n\t\t\tpoint.percentage = fraction * 100;\n\t\t\tpoint.plotX = centerX;\n\t\t\tpoint.plotY = (y1 + (y5 || y3)) / 2;\n\n\t\t\t// Placement of tooltips and data labels\n\t\t\tpoint.tooltipPos = [\n\t\t\t\tcenterX,\n\t\t\t\tpoint.plotY\n\t\t\t];\n\n\t\t\t// Slice is a noop on funnel points\n\t\t\tpoint.slice = noop;\n\t\t\t\n\t\t\t// Mimicking pie data label placement logic\n\t\t\tpoint.half = half;\n\n\t\t\tcumulative += fraction;\n\t\t});\n\n\n\t\tseries.setTooltipPoints();\n\t},\n\t/**\n\t * Draw a single point (wedge)\n\t * @param {Object} point The point object\n\t * @param {Object} color The color of the point\n\t * @param {Number} brightness The brightness relative to the color\n\t */\n\tdrawPoints: function () {\n\t\tvar series = this,\n\t\t\toptions = series.options,\n\t\t\tchart = series.chart,\n\t\t\trenderer = chart.renderer;\n\n\t\teach(series.data, function (point) {\n\t\t\t\n\t\t\tvar graphic = point.graphic,\n\t\t\t\tshapeArgs = point.shapeArgs;\n\n\t\t\tif (!graphic) { // Create the shapes\n\t\t\t\tpoint.graphic = renderer.path(shapeArgs).\n\t\t\t\t\tattr({\n\t\t\t\t\t\tfill: point.color,\n\t\t\t\t\t\tstroke: options.borderColor,\n\t\t\t\t\t\t'stroke-width': options.borderWidth\n\t\t\t\t\t}).\n\t\t\t\t\tadd(series.group);\n\t\t\t\t\t\n\t\t\t} else { // Update the shapes\n\t\t\t\tgraphic.animate(shapeArgs);\n\t\t\t}\n\t\t});\n\t},\n\t\n\t/**\n\t * Extend the pie data label method\n\t */\n\tdrawDataLabels: function () {\n\t\tvar data = this.data,\n\t\t\tlabelDistance = this.options.dataLabels.distance,\n\t\t\tleftSide,\n\t\t\tsign,\n\t\t\tpoint,\n\t\t\ti = data.length,\n\t\t\tx,\n\t\t\ty;\n\t\t\n\t\t// In the original pie label anticollision logic, the slots are distributed\n\t\t// from one labelDistance above to one labelDistance below the pie. In funnels\n\t\t// we don't want this.\n\t\tthis.center[2] -= 2 * labelDistance;\n\t\t\n\t\t// Set the label position array for each point.\n\t\twhile (i--) {\n\t\t\tpoint = data[i];\n\t\t\tleftSide = point.half;\n\t\t\tsign = leftSide ? 1 : -1;\n\t\t\ty = point.plotY;\n\t\t\tx = this.getX(y, leftSide);\n\t\t\t\t\n\t\t\t// set the anchor point for data labels\n\t\t\tpoint.labelPos = [\n\t\t\t\t0, // first break of connector\n\t\t\t\ty, // a/a\n\t\t\t\tx + (labelDistance - 5) * sign, // second break, right outside point shape\n\t\t\t\ty, // a/a\n\t\t\t\tx + labelDistance * sign, // landing point for connector\n\t\t\t\ty, // a/a\n\t\t\t\tleftSide ? 'right' : 'left', // alignment\n\t\t\t\t0 // center angle\n\t\t\t];\n\t\t}\n\t\t\n\t\tseriesTypes.pie.prototype.drawDataLabels.call(this);\n\t}\n\n});\n\n\n}(Highcharts));\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/highchart3/js/modules/heatmap.js",
    "content": "(function(a){var j=a.seriesTypes,k=a.each;j.heatmap=a.extendClass(j.map,{colorKey:\"z\",pointArrayMap:[\"y\",\"z\"],translate:function(){var c=this,a=Number.MAX_VALUE,i=Number.MIN_VALUE;c.generatePoints();k(c.data,function(b){var e=b.x,f=b.y,d=b.z,g=(c.options.colsize||1)/2,h=(c.options.rowsize||1)/2;b.path=[\"M\",e-g,f-h,\"L\",e+g,f-h,\"L\",e+g,f+h,\"L\",e-g,f+h,\"Z\"];b.shapeType=\"path\";b.shapeArgs={d:c.translatePath(b.path)};typeof d===\"number\"&&(d>i?i=d:d<a&&(a=d))});c.translateColors(a,i)},getBox:function(){}})})(Highcharts);\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/highchart3/js/modules/heatmap.src.js",
    "content": "(function (Highcharts) {\n\tvar seriesTypes = Highcharts.seriesTypes,\n\t\teach = Highcharts.each;\n\t\n\tseriesTypes.heatmap = Highcharts.extendClass(seriesTypes.map, {\n\t\tcolorKey: 'z',\n\t\tpointArrayMap: ['y', 'z'],\n\t\ttranslate: function () {\n\t\t\tvar series = this,\n\t\t\t\toptions = series.options,\n\t\t\t\tdataMin = Number.MAX_VALUE,\n\t\t\t\tdataMax = Number.MIN_VALUE,\n\t\t\t\topacity,\n\t\t\t\tminOpacity = options.minOpacity,\n\t\t\t\tpath,\n\t\t\t\tcolor;\n\t\t\t\n\n\t\t\tseries.generatePoints();\n\t\n\t\t\teach(series.data, function (point) {\n\t\t\t\tvar x = point.x,\n\t\t\t\t\ty = point.y,\n\t\t\t\t\tvalue = point.z,\n\t\t\t\t\txPad = (series.options.colsize || 1) / 2,\n\t\t\t\t\tyPad = (series.options.rowsize || 1) / 2;\n\n\t\t\t\tpoint.path = [\n\t\t\t\t\t'M', x - xPad, y - yPad,\n\t\t\t\t\t'L', x + xPad, y - yPad,\n\t\t\t\t\t'L', x + xPad, y + yPad,\n\t\t\t\t\t'L', x - xPad, y + yPad,\n\t\t\t\t\t'Z'\n\t\t\t\t];\n\t\t\t\t\n\t\t\t\tpoint.shapeType = 'path';\n\t\t\t\tpoint.shapeArgs = {\n\t\t\t\t\td: series.translatePath(point.path)\n\t\t\t\t};\n\t\t\t\t\n\t\t\t\tif (typeof value === 'number') {\n\t\t\t\t\tif (value > dataMax) {\n\t\t\t\t\t\tdataMax = value;\n\t\t\t\t\t} else if (value < dataMin) {\n\t\t\t\t\t\tdataMin = value;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t\tseries.translateColors(dataMin, dataMax);\n\t\t},\n\t\t\n\t\tgetBox: function () {}\n\t\t\t\n\t});\n\t\n}(Highcharts));\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/highchart3/js/modules/map.js",
    "content": "/*\n Map plugin v0.1 for Highcharts\n\n (c) 2011-2013 Torstein Hønsi\n\n License: www.highcharts.com/license\n*/\n(function(c){var r=c.Axis,o=c.each,w=c.extend,p=c.merge,s=c.pick,t=c.numberFormat,u=c.getOptions().plotOptions,v=c.Color,q=function(){};c.pathToArray=function(a){var b,a=a.replace(/([A-Za-z])/g,\" $1 \"),a=a.replace(/^\\s*/,\"\").replace(/\\s*$/,\"\"),a=a.split(/[ ,]+/);for(b=0;b<a.length;b++)/[a-zA-Z]/.test(a[b])||(a[b]=parseFloat(a[b]));return a};c.wrap(r.prototype,\"init\",function(a,b,d){b.options.chart.type===\"map\"&&w(this,{getSeriesExtremes:function(){var a=this.isXAxis,b=Number.MAX_VALUE,d=Number.MIN_VALUE;\no(this.series,function(g){b=Math.min(b,g[a?\"minX\":\"minY\"]);d=Math.max(d,g[a?\"maxX\":\"maxY\"])});this.dataMin=b;this.dataMax=d},setAxisTranslation:function(){var a=this.chart,b,d=a.plotWidth/a.plotHeight;b=this.isXAxis;a=a.xAxis[0];r.prototype.setAxisTranslation.call(this);if(!b&&a.transA!==void 0)this.transA=a.transA=Math.min(this.transA,a.transA),b=(a.max-a.min)/(this.max-this.min),b=b>d?this:a,d=(b.max-b.min)*b.transA,b.minPixelPadding=(b.len-d)/2}});return a.call(this,b,d)});u.map=p(u.scatter,{animation:!1,\nminOpacity:0.2,nullColor:\"#F8F8F8\",borderColor:\"silver\",borderWidth:1,marker:null,stickyTracking:!1,tooltip:{followPointer:!0,headerFormat:'<span style=\"font-size:10px\">{point.key}</span><br/>',pointFormat:\"{series.name}: {point.y}<br/>\"}});c.seriesTypes.map=c.extendClass(c.seriesTypes.scatter,{type:\"map\",pointAttrToOptions:{stroke:\"borderColor\",\"stroke-width\":\"borderWidth\",fill:\"color\"},colorKey:\"y\",trackerGroups:[\"group\",\"markerGroup\"],getSymbol:q,getExtremesFromAll:!0,init:function(a){var b=this,\nd=a.options.legend.valueDecimals,j=[],h,f,g,m,e,k,l;l=a.options.legend.layout===\"horizontal\";c.Series.prototype.init.apply(this,arguments);e=b.options.colorRange;if(b.options.valueRanges)o(b.options.valueRanges,function(a){f=a.from;g=a.to;h=\"\";f===void 0?h=\"< \":g===void 0&&(h=\"> \");f!==void 0&&(h+=t(f,d));f!==void 0&&g!==void 0&&(h+=\" - \");g!==void 0&&(h+=t(g,d));j.push(c.extend({chart:b.chart,name:h,options:{},drawLegendSymbol:c.seriesTypes.area.prototype.drawLegendSymbol,visible:!0,setState:function(){},\nsetVisible:function(){}},a))}),b.legendItems=j;else if(e)f=e.from,g=e.to,m=e.fromLabel,e=e.toLabel,k=l?[0,0,1,0]:[0,1,0,0],l||(l=m,m=e,e=l),k={linearGradient:{x1:k[0],y1:k[1],x2:k[2],y2:k[3]},stops:[[0,f],[1,g]]},j=[{chart:b.chart,options:{},fromLabel:m,toLabel:e,color:k,drawLegendSymbol:this.drawLegendSymbol,visible:!0,setState:function(){},setVisible:function(){}}],b.legendItems=j},drawLegendSymbol:function(a,b){var d=a.options.symbolPadding,j=s(a.options.padding,8),h,f,g=this.chart.renderer.fontMetrics(a.options.itemStyle.fontSize).h,\nc=a.options.layout===\"horizontal\",e;e=s(a.options.rectangleLength,200);c?(h=-(d/2),f=0):(h=-e+a.baseline-d/2,f=j+g);b.fromText=this.chart.renderer.text(b.fromLabel,f,h).attr({zIndex:2}).add(b.legendGroup);f=b.fromText.getBBox();b.legendSymbol=this.chart.renderer.rect(c?f.x+f.width+d:f.x-g-d,f.y,c?e:g,c?g:e,2).attr({zIndex:1}).add(b.legendGroup);e=b.legendSymbol.getBBox();b.toText=this.chart.renderer.text(b.toLabel,e.x+e.width+d,c?h:e.y+e.height-d).attr({zIndex:2}).add(b.legendGroup);h=b.toText.getBBox();\nc?(a.offsetWidth=f.width+e.width+h.width+d*2+j,a.itemY=g+j):(a.offsetWidth=Math.max(f.width,h.width)+d+e.width+j,a.itemY=e.height+j,a.itemX=d)},getBox:function(){var a=-Math.pow(2,31),b=Math.pow(2,31)-1,d=-Math.pow(2,31),j=Math.pow(2,31)-1;o(this.options.data,function(c){for(var c=c.path,f=c.length,g=!1;f--;)typeof c[f]===\"number\"&&(g?(a=Math.max(a,c[f]),b=Math.min(b,c[f])):(d=Math.max(d,c[f]),j=Math.min(j,c[f])),g=!g)});this.minY=j;this.maxY=d;this.minX=b;this.maxX=a},translatePath:function(a){var b=\n!1,d=this.xAxis,c=this.yAxis,a=[].concat(a);for(i=a.length;i--;)typeof a[i]===\"number\"&&(a[i]=b?Math.round(d.translate(a[i])):Math.round(c.len-c.translate(a[i])),b=!b);return a},setData:function(){c.Series.prototype.setData.apply(this,arguments);this.getBox()},translate:function(){var a=this,b=Number.MAX_VALUE,d=Number.MIN_VALUE;a.generatePoints();o(a.data,function(c){c.shapeType=\"path\";c.shapeArgs={d:a.translatePath(c.path)};if(typeof c.y===\"number\")if(c.y>d)d=c.y;else if(c.y<b)b=c.y});a.translateColors(b,\nd)},translateColors:function(a,b){var d=this.options,c=d.valueRanges,h=d.colorRange,f=this.colorKey;o(this.data,function(d){var m=d[f],e=[],k,l,n;if(c)for(n=c.length;n--;){if(e=c[n],k=e.from,l=e.to,(k===void 0||m>=k)&&(l===void 0||m<=l)){d.options.color=e.color;break}}else if(h&&m!==void 0){k=v(h.from);l=v(h.to);m=(b-m)/(b-a);for(n=4;n--;)e[n]=Math.round(l.rgba[n]+(k.rgba[n]-l.rgba[n])*m);d.options.color=\"rgba(\"+e.join(\",\")+\")\"}})},drawGraph:q,drawDataLabels:q,drawPoints:function(){var a,b=this.colorKey;\no(this.data,function(a){a.plotY=1;if(a[b]===null)a[b]=0,a.isNull=!0});c.seriesTypes.column.prototype.drawPoints.apply(this);o(this.data,function(c){a=c.graphic.getBBox();c.tooltipPos=[a.x+a.width/2,a.y+a.height/2];c.plotX=c.tooltipPos[0];c.plotY=c.tooltipPos[1];c.isNull&&(c[b]=null)});c.Series.prototype.drawDataLabels.call(this)}});c.Map=function(a,b){var d={endOnTick:!1,gridLineWidth:0,labels:{enabled:!1},lineWidth:0,minPadding:0,maxPadding:0,startOnTick:!1,tickWidth:0,title:null};seriesOptions=\na.series;a.series=null;a=p({chart:{type:\"map\"},xAxis:d,yAxis:p(d,{reversed:!0})},a,{chart:{inverted:!1}});a.series=seriesOptions;return new c.Chart(a,b)}})(Highcharts);\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/highchart3/js/modules/map.src.js",
    "content": "/**\n * @license Map plugin v0.1 for Highcharts\n *\n * (c) 2011-2013 Torstein Hønsi\n *\n * License: www.highcharts.com/license\n */\n\n/* \n * See www.highcharts.com/studies/world-map.htm for use case.\n *\n * To do:\n * - Optimize long variable names and alias adapter methods and Highcharts namespace variables\n * - Zoom and pan GUI\n */\n(function (Highcharts) {\n\tvar UNDEFINED,\n\t\tAxis = Highcharts.Axis,\n\t\teach = Highcharts.each,\n\t\textend = Highcharts.extend,\n\t\tmerge = Highcharts.merge,\n\t\tpick = Highcharts.pick,\n\t\tnumberFormat = Highcharts.numberFormat,\n\t\tplotOptions = Highcharts.getOptions().plotOptions,\n\t\tColor = Highcharts.Color,\n\t\tnoop = function () {};\n\t\n\t/**\n\t * Utility for reading SVG paths directly.\n\t * \n\t * @todo This is moved to the Data plugin. Make sure it is deleted here.\n\t */\n\tHighcharts.pathToArray = function (path) {\n\t\tvar i;\n\n\t\t// Move letters apart\n\t\tpath = path.replace(/([A-Za-z])/g, ' $1 ');\n\t\t// Trim\n\t\tpath = path.replace(/^\\s*/, \"\").replace(/\\s*$/, \"\");\n\t\t\n\t\t// Split on spaces and commas\n\t\tpath = path.split(/[ ,]+/);\n\t\t\n\t\tfor (i = 0; i < path.length; i++) {\n\t\t\tif (!/[a-zA-Z]/.test(path[i])) {\n\t\t\t\tpath[i] = parseFloat(path[i]);\n\t\t\t}\n\t\t}\n\t\treturn path;\n\t};\n\t\n\t/**\n\t * Extend the Axis object with methods specific to maps\n\t */\n\tHighcharts.wrap(Axis.prototype, 'init', function (proceed, chart, userOptions) {\n\t\t\n\t\tif (chart.options.chart.type === 'map') {\n\t\t\textend(this, {\n\t\t\t\t\n\t\t\t\t/**\n\t\t\t\t * Override to use the extreme coordinates from the SVG shape, not the\n\t\t\t\t * data values\n\t\t\t\t */\n\t\t\t\tgetSeriesExtremes: function () {\n\t\t\t\t\tvar isXAxis = this.isXAxis,\n\t\t\t\t\t\tdataMin = Number.MAX_VALUE,\n\t\t\t\t\t\tdataMax = Number.MIN_VALUE;\n\t\t\t\t\teach(this.series, function (series) {\n\t\t\t\t\t\tdataMin = Math.min(dataMin, series[isXAxis ? 'minX' : 'minY']);\n\t\t\t\t\t\tdataMax = Math.max(dataMax, series[isXAxis ? 'maxX' : 'maxY']);\n\t\t\t\t\t});\n\t\t\t\t\tthis.dataMin = dataMin;\n\t\t\t\t\tthis.dataMax = dataMax;\n\t\t\t\t},\n\t\t\t\t\n\t\t\t\t/**\n\t\t\t\t * Override axis translation to make sure the aspect ratio is always kept\n\t\t\t\t */\n\t\t\t\tsetAxisTranslation: function () {\n\t\t\t\t\tvar chart = this.chart,\n\t\t\t\t\t\tmapRatio,\n\t\t\t\t\t\tplotRatio = chart.plotWidth / chart.plotHeight,\n\t\t\t\t\t\tisXAxis = this.isXAxis,\n\t\t\t\t\t\tadjustedAxisLength,\n\t\t\t\t\t\txAxis = chart.xAxis[0],\n\t\t\t\t\t\tpadAxis;\n\t\t\t\t\t\n\t\t\t\t\t// Run the parent method\n\t\t\t\t\tAxis.prototype.setAxisTranslation.call(this);\n\t\t\t\t\t\n\t\t\t\t\t// On Y axis, handle both\n\t\t\t\t\tif (!isXAxis && xAxis.transA !== UNDEFINED) {\n\t\t\t\t\t\t\n\t\t\t\t\t\t// Use the same translation for both axes\n\t\t\t\t\t\tthis.transA = xAxis.transA = Math.min(this.transA, xAxis.transA);\n\t\t\t\t\t\t\n\t\t\t\t\t\tmapRatio = (xAxis.max - xAxis.min) / (this.max - this.min);\n\t\t\t\t\t\t\n\t\t\t\t\t\t// What axis to pad to put the map in the middle\n\t\t\t\t\t\tpadAxis = mapRatio > plotRatio ? this : xAxis;\n\t\t\t\t\t\t\n\t\t\t\t\t\t// Pad it\n\t\t\t\t\t\tadjustedAxisLength = (padAxis.max - padAxis.min) * padAxis.transA;\n\t\t\t\t\t\tpadAxis.minPixelPadding = (padAxis.len - adjustedAxisLength) / 2;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t}\n\t\t\t});\n\t\t}\t\n\t\t\n\t\treturn proceed.call(this, chart, userOptions);\n\t});\n\t\n\t/**\n\t * Extend the default options with map options\n\t */\n\tplotOptions.map = merge(\n\t\tplotOptions.scatter, \n\t\t{\n\t\t\tanimation: false, // makes the complex shapes slow\n\t\t\tminOpacity: 0.2,\n\t\t\tnullColor: '#F8F8F8',\n\t\t\tborderColor: 'silver',\n\t\t\tborderWidth: 1,\n\t\t\tmarker: null,\n\t\t\tstickyTracking: false,\n\t\t\ttooltip: {\n\t\t\t\tfollowPointer: true,\n\t\t\t\theaderFormat: '<span style=\"font-size:10px\">{point.key}</span><br/>',\n\t\t\t\tpointFormat: '{series.name}: {point.y}<br/>'\n\t\t\t}\n\t\t}\n\t);\n\t\n\t/**\n\t * Add the series type\n\t */\n\tHighcharts.seriesTypes.map = Highcharts.extendClass(Highcharts.seriesTypes.scatter, {\n\t\ttype: 'map',\n\t\tpointAttrToOptions: { // mapping between SVG attributes and the corresponding options\n\t\t\tstroke: 'borderColor',\n\t\t\t'stroke-width': 'borderWidth',\n\t\t\tfill: 'color'\n\t\t},\n\t\tcolorKey: 'y',\n\t\ttrackerGroups: ['group', 'markerGroup'],\n\t\tgetSymbol: noop,\n\t\tgetExtremesFromAll: true,\n\t\tinit: function (chart) {\n\t\t\tvar series = this,\n\t\t\t\tvalueDecimals = chart.options.legend.valueDecimals,\n\t\t\t\tlegendItems = [],\n\t\t\t\tname,\n\t\t\t\tfrom,\n\t\t\t\tto,\n\t\t\t\tfromLabel,\n\t\t\t\ttoLabel,\n\t\t\t\tcolorRange,\n\t\t\t\tgradientColor,\n\t\t\t\tgrad,\n\t\t\t\ttmpLabel,\n\t\t\t\thorizontal = chart.options.legend.layout === 'horizontal';\n\n\t\t\t\n\t\t\tHighcharts.Series.prototype.init.apply(this, arguments);\n\t\t\tcolorRange = series.options.colorRange;\n\n\t\t\tif (series.options.valueRanges) {\n\t\t\t\teach(series.options.valueRanges, function (range) {\n\t\t\t\t\tfrom = range.from;\n\t\t\t\t\tto = range.to;\n\t\t\t\t\t\n\t\t\t\t\t// Assemble the default name. This can be overridden by legend.options.labelFormatter\n\t\t\t\t\tname = '';\n\t\t\t\t\tif (from === UNDEFINED) {\n\t\t\t\t\t\tname = '< ';\n\t\t\t\t\t} else if (to === UNDEFINED) {\n\t\t\t\t\t\tname = '> ';\n\t\t\t\t\t}\n\t\t\t\t\tif (from !== UNDEFINED) {\n\t\t\t\t\t\tname += numberFormat(from, valueDecimals);\n\t\t\t\t\t}\n\t\t\t\t\tif (from !== UNDEFINED && to !== UNDEFINED) {\n\t\t\t\t\t\tname += ' - ';\n\t\t\t\t\t}\n\t\t\t\t\tif (to !== UNDEFINED) {\n\t\t\t\t\t\tname += numberFormat(to, valueDecimals);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t// Add a mock object to the legend items\n\t\t\t\t\tlegendItems.push(Highcharts.extend({\n\t\t\t\t\t\tchart: series.chart,\n\t\t\t\t\t\tname: name,\n\t\t\t\t\t\toptions: {},\n\t\t\t\t\t\tdrawLegendSymbol: Highcharts.seriesTypes.area.prototype.drawLegendSymbol,\n\t\t\t\t\t\tvisible: true,\n\t\t\t\t\t\tsetState: function () {},\n\t\t\t\t\t\tsetVisible: function () {}\n\t\t\t\t\t}, range));\n\t\t\t\t});\n\t\t\t\tseries.legendItems = legendItems;\n\n\t\t\t} else if (colorRange) {\n\n\t\t\t\tfrom = colorRange.from;\n\t\t\t\tto = colorRange.to;\n\t\t\t\tfromLabel = colorRange.fromLabel;\n\t\t\t\ttoLabel = colorRange.toLabel;\n\n\t\t\t\t// Flips linearGradient variables and label text.\n\t\t\t\tgrad = horizontal ? [0, 0, 1, 0] : [0, 1, 0, 0]; \n\t\t\t\tif (!horizontal) {\n\t\t\t\t\ttmpLabel = fromLabel;\n\t\t\t\t\tfromLabel = toLabel;\n\t\t\t\t\ttoLabel = tmpLabel;\n\t\t\t\t} \n\n\t\t\t\t// Creates color gradient.\n\t\t\t\tgradientColor = {\n\t\t\t\t\tlinearGradient: { x1: grad[0], y1: grad[1], x2: grad[2], y2: grad[3] },\n\t\t\t\t\tstops: \n\t\t\t\t\t[\n\t\t\t\t\t\t[0, from],\n\t\t\t\t\t\t[1, to]\n\t\t\t\t\t]\n\t\t\t\t};\n\n\t\t\t\t// Add a mock object to the legend items.\n\t\t\t\tlegendItems = [{\n\t\t\t\t\tchart: series.chart,\n\t\t\t\t\toptions: {},\n\t\t\t\t\tfromLabel: fromLabel,\n\t\t\t\t\ttoLabel: toLabel,\n\t\t\t\t\tcolor: gradientColor,\n\t\t\t\t\tdrawLegendSymbol: this.drawLegendSymbol,\n\t\t\t\t\tvisible: true,\n\t\t\t\t\tsetState: function () {},\n\t\t\t\t\tsetVisible: function () {}\n\t\t\t\t}];\n\n\t\t\t\tseries.legendItems = legendItems;\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Gets the series' symbol in the legend and extended legend with more information.\n\t\t * \n\t\t * @param {Object} legend The legend object\n\t\t * @param {Object} item The series (this) or point\n\t\t */\n\t\tdrawLegendSymbol: function (legend, item) {\n\t\t\t\n\t\t\tvar spacing = legend.options.symbolPadding,\n\t\t\t\tpadding = pick(legend.options.padding, 8),\n\t\t\t\tpositionY,\n\t\t\t\tpositionX,\n\t\t\t\tgradientSize = this.chart.renderer.fontMetrics(legend.options.itemStyle.fontSize).h,\n\t\t\t\thorizontal = legend.options.layout === 'horizontal',\n\t\t\t\tbox1,\n\t\t\t\tbox2,\n\t\t\t\tbox3,\n\t\t\t\trectangleLength = pick(legend.options.rectangleLength, 200);\n\n\t\t\t// Set local variables based on option.\n\t\t\tif (horizontal) {\n\t\t\t\tpositionY = -(spacing / 2);\n\t\t\t\tpositionX = 0;\n\t\t\t} else {\n\t\t\t\tpositionY = -rectangleLength + legend.baseline - (spacing / 2);\n\t\t\t\tpositionX = padding + gradientSize;\n\t\t\t}\n\n\t\t\t// Creates the from text.\n\t\t\titem.fromText = this.chart.renderer.text(\n\t\t\t\t\titem.fromLabel,\t// Text.\n\t\t\t\t\tpositionX,\t\t// Lower left x.\n\t\t\t\t\tpositionY\t\t// Lower left y.\n\t\t\t\t).attr({\n\t\t\t\t\tzIndex: 2\n\t\t\t\t}).add(item.legendGroup);\n\t\t\tbox1 = item.fromText.getBBox();\n\n\t\t\t// Creates legend symbol.\n\t\t\t// Ternary changes variables based on option.\n\t\t\titem.legendSymbol = this.chart.renderer.rect(\n\t\t\t\thorizontal ? box1.x + box1.width + spacing : box1.x - gradientSize - spacing,\t\t// Upper left x.\n\t\t\t\tbox1.y,\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Upper left y.\n\t\t\t\thorizontal ? rectangleLength : gradientSize,\t\t\t\t\t\t\t\t\t\t\t// Width.\n\t\t\t\thorizontal ? gradientSize : rectangleLength,\t\t\t\t\t\t\t\t\t\t// Height.\n\t\t\t\t2\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Corner radius.\n\t\t\t).attr({\n\t\t\t\tzIndex: 1\n\t\t\t}).add(item.legendGroup);\n\t\t\tbox2 = item.legendSymbol.getBBox();\n\n\t\t\t// Creates the to text.\n\t\t\t// Vertical coordinate changed based on option.\n\t\t\titem.toText = this.chart.renderer.text(\n\t\t\t\t\titem.toLabel,\n\t\t\t\t\tbox2.x + box2.width + spacing,\n\t\t\t\t\thorizontal ? positionY : box2.y + box2.height - spacing\n\t\t\t\t).attr({\n\t\t\t\t\tzIndex: 2\n\t\t\t\t}).add(item.legendGroup);\n\t\t\tbox3 = item.toText.getBBox();\n\n\t\t\t// Changes legend box settings based on option.\n\t\t\tif (horizontal) {\n\t\t\t\tlegend.offsetWidth = box1.width + box2.width + box3.width + (spacing * 2) + padding;\n\t\t\t\tlegend.itemY = gradientSize + padding;\n\t\t\t} else {\n\t\t\t\tlegend.offsetWidth = Math.max(box1.width, box3.width) + (spacing) + box2.width + padding;\n\t\t\t\tlegend.itemY = box2.height + padding;\n\t\t\t\tlegend.itemX = spacing;\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Get the bounding box of all paths in the map combined.\n\t\t */\n\t\tgetBox: function () {\n\t\t\tvar chart = this.chart,\n\t\t\t\tmaxX = -Math.pow(2, 31), \n\t\t\t\tminX =  Math.pow(2, 31) - 1, \n\t\t\t\tmaxY = -Math.pow(2, 31), \n\t\t\t\tminY =  Math.pow(2, 31) - 1,\n\t\t\t\txyRatio,\n\t\t\t\tratioCorrection,\n\t\t\t\tplotWidth = chart.plotWidth, \n\t\t\t\tplotHeight = chart.plotHeight,\n\t\t\t\tpad;\n\t\t\t\n\t\t\t\n\t\t\t// Find the bounding box\n\t\t\teach(this.options.data, function (point) {\n\t\t\t\tvar path = point.path,\n\t\t\t\t\ti = path.length,\n\t\t\t\t\teven = false; // while loop reads from the end\n\t\t\t\t\t\n\t\t\t\twhile (i--) {\n\t\t\t\t\tif (typeof path[i] === 'number') {\n\t\t\t\t\t\tif (even) { // even = x\n\t\t\t\t\t\t\tmaxX = Math.max(maxX, path[i]);\n\t\t\t\t\t\t\tminX = Math.min(minX, path[i]);\n\t\t\t\t\t\t} else { // odd = Y\n\t\t\t\t\t\t\tmaxY = Math.max(maxY, path[i]);\n\t\t\t\t\t\t\tminY = Math.min(minY, path[i]);\n\t\t\t\t\t\t}\n\t\t\t\t\t\teven = !even;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\tthis.minY = minY;\n\t\t\tthis.maxY = maxY;\n\t\t\tthis.minX = minX;\n\t\t\tthis.maxX = maxX;\n\t\t\t\n\t\t},\n\t\t\n\t\t\n\t\t\n\t\t/**\n\t\t * Translate the path so that it automatically fits into the plot area box\n\t\t * @param {Object} path\n\t\t */\n\t\ttranslatePath: function (path) {\n\t\t\t\n\t\t\tvar series = this,\n\t\t\t\tchart = series.chart,\n\t\t\t\teven = false, // while loop reads from the end\n\t\t\t\txAxis = series.xAxis,\n\t\t\t\tyAxis = series.yAxis;\n\t\t\t\t\n\t\t\t// Preserve the original\n\t\t\tpath = [].concat(path);\n\t\t\t\t\n\t\t\t// Do the translation\n\t\t\ti = path.length;\n\t\t\twhile (i--) {\n\t\t\t\tif (typeof path[i] === 'number') {\n\t\t\t\t\tif (even) { // even = x\n\t\t\t\t\t\tpath[i] = Math.round(xAxis.translate(path[i]));\n\t\t\t\t\t} else { // odd = Y\n\t\t\t\t\t\tpath[i] = Math.round(yAxis.len - yAxis.translate(path[i]));\n\t\t\t\t\t}\n\t\t\t\t\teven = !even;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn path;\n\t\t},\n\t\t\n\t\tsetData: function () {\n\t\t\tHighcharts.Series.prototype.setData.apply(this, arguments);\n\t\t\tthis.getBox();\n\t\t},\n\t\t\n\t\t/**\n\t\t * Add the path option for data points. Find the max value for color calculation.\n\t\t */\n\t\ttranslate: function () {\n\t\t\tvar series = this,\n\t\t\t\toptions = series.options,\n\t\t\t\tdataMin = Number.MAX_VALUE,\n\t\t\t\tdataMax = Number.MIN_VALUE,\n\t\t\t\topacity,\n\t\t\t\tminOpacity = options.minOpacity,\n\t\t\t\tpath,\n\t\t\t\tcolor;\n\t\n\t\t\tseries.generatePoints();\n\t\n\t\t\teach(series.data, function (point) {\n\t\t\t\t\n\t\t\t\tpoint.shapeType = 'path';\n\t\t\t\tpoint.shapeArgs = {\n\t\t\t\t\td: series.translatePath(point.path)\n\t\t\t\t};\n\t\t\t\t\n\t\t\t\t// TODO: do point colors in drawPoints instead of point.init\n\t\t\t\tif (typeof point.y === 'number') {\n\t\t\t\t\tif (point.y > dataMax) {\n\t\t\t\t\t\tdataMax = point.y;\n\t\t\t\t\t} else if (point.y < dataMin) {\n\t\t\t\t\t\tdataMin = point.y;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t\tseries.translateColors(dataMin, dataMax);\n\t\t},\n\t\t\n\t\t/**\n\t\t * In choropleth maps, the color is a result of the value, so this needs translation tood\n\t\t */\n\t\ttranslateColors: function (dataMin, dataMax) {\n\t\t\t\n\t\t\tvar seriesOptions = this.options,\n\t\t\t\tvalueRanges = seriesOptions.valueRanges,\n\t\t\t\tcolorRange = seriesOptions.colorRange,\n\t\t\t\tcolorKey = this.colorKey;\n\t\t\t\n\t\t\teach(this.data, function (point) {\n\t\t\t\tvar value = point[colorKey],\n\t\t\t\t\trgba = [],\n\t\t\t\t\trange,\n\t\t\t\t\tfrom,\n\t\t\t\t\tto,\n\t\t\t\t\ti,\n\t\t\t\t\tpos;\n\n\t\t\t\tif (valueRanges) {\n\t\t\t\t\ti = valueRanges.length;\n\t\t\t\t\twhile (i--) {\n\t\t\t\t\t\trange = valueRanges[i];\n\t\t\t\t\t\tfrom = range.from;\n\t\t\t\t\t\tto = range.to;\n\t\t\t\t\t\tif ((from === UNDEFINED || value >= from) && (to === UNDEFINED || value <= to)) {\n\t\t\t\t\t\t\tpoint.options.color = range.color;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t}\n\t\t\t\t} else if (colorRange && value !== undefined) {\n\t\t\t\t\tfrom = Color(colorRange.from);\n\t\t\t\t\tto = Color(colorRange.to);\n\t\t\t\t\tpos = (dataMax - value) / (dataMax - dataMin);\n\t\t\t\t\ti = 4;\n\t\t\t\t\twhile (i--) {\n\t\t\t\t\t\trgba[i] = Math.round(\n\t\t\t\t\t\t\tto.rgba[i] + (from.rgba[i] - to.rgba[i]) * pos\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tpoint.options.color = 'rgba(' + rgba.join(',') + ')';\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\t\t\n\t\tdrawGraph: noop,\n\t\t\n\t\t/**\n\t\t * We need the points' bounding boxes in order to draw the data labels, so \n\t\t * we skip it now and call if from drawPoints instead.\n\t\t */\n\t\tdrawDataLabels: noop,\n\t\t\n\t\t/** \n\t\t * Use the drawPoints method of column, that is able to handle simple shapeArgs.\n\t\t * Extend it by assigning the tooltip position.\n\t\t */\n\t\tdrawPoints: function () {\n\t\t\tvar series = this,\n\t\t\t\tchart = series.chart,\n\t\t\t\tsaturation,\n\t\t\t\tbBox,\n\t\t\t\tcolorKey = series.colorKey;\n\t\t\t\n\t\t\t// Make points pass test in drawing\n\t\t\teach(series.data, function (point) {\n\t\t\t\tpoint.plotY = 1; // pass null test in column.drawPoints\n\t\t\t\tif (point[colorKey] === null) {\n\t\t\t\t\tpoint[colorKey] = 0;\n\t\t\t\t\tpoint.isNull = true;\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t\t// Draw them\n\t\t\tHighcharts.seriesTypes.column.prototype.drawPoints.apply(series);\n\t\t\t\n\t\t\teach(series.data, function (point) {\n\t\t\t\t\n\t\t\t\tbBox = point.graphic.getBBox();\n\t\t\t\t// for tooltip\n\t\t\t\tpoint.tooltipPos = [\n\t\t\t\t\tbBox.x + bBox.width / 2,\n\t\t\t\t\tbBox.y + bBox.height / 2\n\t\t\t\t];\n\t\t\t\t// for data labels\n\t\t\t\tpoint.plotX = point.tooltipPos[0];\n\t\t\t\tpoint.plotY = point.tooltipPos[1]; \n\t\t\t\t\n\t\t\t\t// Reset escaped null points\n\t\t\t\tif (point.isNull) {\n\t\t\t\t\tpoint[colorKey] = null;\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// Now draw the data labels\n\t\t\tHighcharts.Series.prototype.drawDataLabels.call(series);\n\t\t\t\n\t\t}\n\t});\n\t\n\t/**\n\t * A wrapper for Chart with all the default values for a Map\n\t */\n\tHighcharts.Map = function (options, callback) {\n\t\t\n\t\tvar hiddenAxis = {\n\t\t\tendOnTick: false,\n\t\t\tgridLineWidth: 0,\n\t\t\tlabels: {\n\t\t\t\tenabled: false\n\t\t\t},\n\t\t\tlineWidth: 0,\n\t\t\tminPadding: 0,\n\t\t\tmaxPadding: 0,\n\t\t\tstartOnTick: false,\n\t\t\ttickWidth: 0,\n\t\t\ttitle: null\n\t\t};\n\t\t\n\t\t// Don't merge the data\n\t\tseriesOptions = options.series;\n\t\toptions.series = null;\n\t\t\n\t\toptions = merge({\n\t\t\tchart: {\n\t\t\t\ttype: 'map'\n\t\t\t},\n\t\t\txAxis: hiddenAxis,\n\t\t\tyAxis: merge(hiddenAxis, { reversed: true })\t\n\t\t},\n\t\toptions, // user's options\n\t\n\t\t{ // forced options\n\t\t\tchart: {\n\t\t\t\tinverted: false\n\t\t\t}\n\t\t});\n\t\n\t\toptions.series = seriesOptions;\n\t\n\t\n\t\treturn new Highcharts.Chart(options, callback);\n\t};\n}(Highcharts));\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/highchart3/js/themes/dark-blue.js",
    "content": "/**\n * Dark blue theme for Highcharts JS\n * @author Torstein Hønsi\n */\n\nHighcharts.theme = {\n\tcolors: [\"#DDDF0D\", \"#55BF3B\", \"#DF5353\", \"#7798BF\", \"#aaeeee\", \"#ff0066\", \"#eeaaee\",\n\t\t\"#55BF3B\", \"#DF5353\", \"#7798BF\", \"#aaeeee\"],\n\tchart: {\n\t\tbackgroundColor: {\n\t\t\tlinearGradient: { x1: 0, y1: 0, x2: 1, y2: 1 },\n\t\t\tstops: [\n\t\t\t\t[0, 'rgb(48, 48, 96)'],\n\t\t\t\t[1, 'rgb(0, 0, 0)']\n\t\t\t]\n\t\t},\n\t\tborderColor: '#000000',\n\t\tborderWidth: 2,\n\t\tclassName: 'dark-container',\n\t\tplotBackgroundColor: 'rgba(255, 255, 255, .1)',\n\t\tplotBorderColor: '#CCCCCC',\n\t\tplotBorderWidth: 1\n\t},\n\ttitle: {\n\t\tstyle: {\n\t\t\tcolor: '#C0C0C0',\n\t\t\tfont: 'bold 16px \"Trebuchet MS\", Verdana, sans-serif'\n\t\t}\n\t},\n\tsubtitle: {\n\t\tstyle: {\n\t\t\tcolor: '#666666',\n\t\t\tfont: 'bold 12px \"Trebuchet MS\", Verdana, sans-serif'\n\t\t}\n\t},\n\txAxis: {\n\t\tgridLineColor: '#333333',\n\t\tgridLineWidth: 1,\n\t\tlabels: {\n\t\t\tstyle: {\n\t\t\t\tcolor: '#A0A0A0'\n\t\t\t}\n\t\t},\n\t\tlineColor: '#A0A0A0',\n\t\ttickColor: '#A0A0A0',\n\t\ttitle: {\n\t\t\tstyle: {\n\t\t\t\tcolor: '#CCC',\n\t\t\t\tfontWeight: 'bold',\n\t\t\t\tfontSize: '12px',\n\t\t\t\tfontFamily: 'Trebuchet MS, Verdana, sans-serif'\n\n\t\t\t}\n\t\t}\n\t},\n\tyAxis: {\n\t\tgridLineColor: '#333333',\n\t\tlabels: {\n\t\t\tstyle: {\n\t\t\t\tcolor: '#A0A0A0'\n\t\t\t}\n\t\t},\n\t\tlineColor: '#A0A0A0',\n\t\tminorTickInterval: null,\n\t\ttickColor: '#A0A0A0',\n\t\ttickWidth: 1,\n\t\ttitle: {\n\t\t\tstyle: {\n\t\t\t\tcolor: '#CCC',\n\t\t\t\tfontWeight: 'bold',\n\t\t\t\tfontSize: '12px',\n\t\t\t\tfontFamily: 'Trebuchet MS, Verdana, sans-serif'\n\t\t\t}\n\t\t}\n\t},\n\ttooltip: {\n\t\tbackgroundColor: 'rgba(0, 0, 0, 0.75)',\n\t\tstyle: {\n\t\t\tcolor: '#F0F0F0'\n\t\t}\n\t},\n\ttoolbar: {\n\t\titemStyle: {\n\t\t\tcolor: 'silver'\n\t\t}\n\t},\n\tplotOptions: {\n\t\tline: {\n\t\t\tdataLabels: {\n\t\t\t\tcolor: '#CCC'\n\t\t\t},\n\t\t\tmarker: {\n\t\t\t\tlineColor: '#333'\n\t\t\t}\n\t\t},\n\t\tspline: {\n\t\t\tmarker: {\n\t\t\t\tlineColor: '#333'\n\t\t\t}\n\t\t},\n\t\tscatter: {\n\t\t\tmarker: {\n\t\t\t\tlineColor: '#333'\n\t\t\t}\n\t\t},\n\t\tcandlestick: {\n\t\t\tlineColor: 'white'\n\t\t}\n\t},\n\tlegend: {\n\t\titemStyle: {\n\t\t\tfont: '9pt Trebuchet MS, Verdana, sans-serif',\n\t\t\tcolor: '#A0A0A0'\n\t\t},\n\t\titemHoverStyle: {\n\t\t\tcolor: '#FFF'\n\t\t},\n\t\titemHiddenStyle: {\n\t\t\tcolor: '#444'\n\t\t}\n\t},\n\tcredits: {\n\t\tstyle: {\n\t\t\tcolor: '#666'\n\t\t}\n\t},\n\tlabels: {\n\t\tstyle: {\n\t\t\tcolor: '#CCC'\n\t\t}\n\t},\n\n\tnavigation: {\n\t\tbuttonOptions: {\n\t\t\tsymbolStroke: '#DDDDDD',\n\t\t\thoverSymbolStroke: '#FFFFFF',\n\t\t\ttheme: {\n\t\t\t\tfill: {\n\t\t\t\t\tlinearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },\n\t\t\t\t\tstops: [\n\t\t\t\t\t\t[0.4, '#606060'],\n\t\t\t\t\t\t[0.6, '#333333']\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\tstroke: '#000000'\n\t\t\t}\n\t\t}\n\t},\n\n\t// scroll charts\n\trangeSelector: {\n\t\tbuttonTheme: {\n\t\t\tfill: {\n\t\t\t\tlinearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },\n\t\t\t\tstops: [\n\t\t\t\t\t[0.4, '#888'],\n\t\t\t\t\t[0.6, '#555']\n\t\t\t\t]\n\t\t\t},\n\t\t\tstroke: '#000000',\n\t\t\tstyle: {\n\t\t\t\tcolor: '#CCC',\n\t\t\t\tfontWeight: 'bold'\n\t\t\t},\n\t\t\tstates: {\n\t\t\t\thover: {\n\t\t\t\t\tfill: {\n\t\t\t\t\t\tlinearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },\n\t\t\t\t\t\tstops: [\n\t\t\t\t\t\t\t[0.4, '#BBB'],\n\t\t\t\t\t\t\t[0.6, '#888']\n\t\t\t\t\t\t]\n\t\t\t\t\t},\n\t\t\t\t\tstroke: '#000000',\n\t\t\t\t\tstyle: {\n\t\t\t\t\t\tcolor: 'white'\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tselect: {\n\t\t\t\t\tfill: {\n\t\t\t\t\t\tlinearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },\n\t\t\t\t\t\tstops: [\n\t\t\t\t\t\t\t[0.1, '#000'],\n\t\t\t\t\t\t\t[0.3, '#333']\n\t\t\t\t\t\t]\n\t\t\t\t\t},\n\t\t\t\t\tstroke: '#000000',\n\t\t\t\t\tstyle: {\n\t\t\t\t\t\tcolor: 'yellow'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tinputStyle: {\n\t\t\tbackgroundColor: '#333',\n\t\t\tcolor: 'silver'\n\t\t},\n\t\tlabelStyle: {\n\t\t\tcolor: 'silver'\n\t\t}\n\t},\n\n\tnavigator: {\n\t\thandles: {\n\t\t\tbackgroundColor: '#666',\n\t\t\tborderColor: '#AAA'\n\t\t},\n\t\toutlineColor: '#CCC',\n\t\tmaskFill: 'rgba(16, 16, 16, 0.5)',\n\t\tseries: {\n\t\t\tcolor: '#7798BF',\n\t\t\tlineColor: '#A6C7ED'\n\t\t}\n\t},\n\n\tscrollbar: {\n\t\tbarBackgroundColor: {\n\t\t\t\tlinearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },\n\t\t\t\tstops: [\n\t\t\t\t\t[0.4, '#888'],\n\t\t\t\t\t[0.6, '#555']\n\t\t\t\t]\n\t\t\t},\n\t\tbarBorderColor: '#CCC',\n\t\tbuttonArrowColor: '#CCC',\n\t\tbuttonBackgroundColor: {\n\t\t\t\tlinearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },\n\t\t\t\tstops: [\n\t\t\t\t\t[0.4, '#888'],\n\t\t\t\t\t[0.6, '#555']\n\t\t\t\t]\n\t\t\t},\n\t\tbuttonBorderColor: '#CCC',\n\t\trifleColor: '#FFF',\n\t\ttrackBackgroundColor: {\n\t\t\tlinearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },\n\t\t\tstops: [\n\t\t\t\t[0, '#000'],\n\t\t\t\t[1, '#333']\n\t\t\t]\n\t\t},\n\t\ttrackBorderColor: '#666'\n\t},\n\n\t// special colors for some of the\n\tlegendBackgroundColor: 'rgba(0, 0, 0, 0.5)',\n\tlegendBackgroundColorSolid: 'rgb(35, 35, 70)',\n\tdataLabelsColor: '#444',\n\ttextColor: '#C0C0C0',\n\tmaskColor: 'rgba(255,255,255,0.3)'\n};\n\n// Apply the theme\nvar highchartsOptions = Highcharts.setOptions(Highcharts.theme);\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/highchart3/js/themes/dark-green.js",
    "content": "/**\n * Dark blue theme for Highcharts JS\n * @author Torstein Hønsi\n */\n\nHighcharts.theme = {\n\tcolors: [\"#DDDF0D\", \"#55BF3B\", \"#DF5353\", \"#7798BF\", \"#aaeeee\", \"#ff0066\", \"#eeaaee\",\n\t\t\"#55BF3B\", \"#DF5353\", \"#7798BF\", \"#aaeeee\"],\n\tchart: {\n\t\tbackgroundColor: {\n\t\t\tlinearGradient: [0, 0, 250, 500],\n\t\t\tstops: [\n\t\t\t\t[0, 'rgb(48, 96, 48)'],\n\t\t\t\t[1, 'rgb(0, 0, 0)']\n\t\t\t]\n\t\t},\n\t\tborderColor: '#000000',\n\t\tborderWidth: 2,\n\t\tclassName: 'dark-container',\n\t\tplotBackgroundColor: 'rgba(255, 255, 255, .1)',\n\t\tplotBorderColor: '#CCCCCC',\n\t\tplotBorderWidth: 1\n\t},\n\ttitle: {\n\t\tstyle: {\n\t\t\tcolor: '#C0C0C0',\n\t\t\tfont: 'bold 16px \"Trebuchet MS\", Verdana, sans-serif'\n\t\t}\n\t},\n\tsubtitle: {\n\t\tstyle: {\n\t\t\tcolor: '#666666',\n\t\t\tfont: 'bold 12px \"Trebuchet MS\", Verdana, sans-serif'\n\t\t}\n\t},\n\txAxis: {\n\t\tgridLineColor: '#333333',\n\t\tgridLineWidth: 1,\n\t\tlabels: {\n\t\t\tstyle: {\n\t\t\t\tcolor: '#A0A0A0'\n\t\t\t}\n\t\t},\n\t\tlineColor: '#A0A0A0',\n\t\ttickColor: '#A0A0A0',\n\t\ttitle: {\n\t\t\tstyle: {\n\t\t\t\tcolor: '#CCC',\n\t\t\t\tfontWeight: 'bold',\n\t\t\t\tfontSize: '12px',\n\t\t\t\tfontFamily: 'Trebuchet MS, Verdana, sans-serif'\n\n\t\t\t}\n\t\t}\n\t},\n\tyAxis: {\n\t\tgridLineColor: '#333333',\n\t\tlabels: {\n\t\t\tstyle: {\n\t\t\t\tcolor: '#A0A0A0'\n\t\t\t}\n\t\t},\n\t\tlineColor: '#A0A0A0',\n\t\tminorTickInterval: null,\n\t\ttickColor: '#A0A0A0',\n\t\ttickWidth: 1,\n\t\ttitle: {\n\t\t\tstyle: {\n\t\t\t\tcolor: '#CCC',\n\t\t\t\tfontWeight: 'bold',\n\t\t\t\tfontSize: '12px',\n\t\t\t\tfontFamily: 'Trebuchet MS, Verdana, sans-serif'\n\t\t\t}\n\t\t}\n\t},\n\ttooltip: {\n\t\tbackgroundColor: 'rgba(0, 0, 0, 0.75)',\n\t\tstyle: {\n\t\t\tcolor: '#F0F0F0'\n\t\t}\n\t},\n\ttoolbar: {\n\t\titemStyle: {\n\t\t\tcolor: 'silver'\n\t\t}\n\t},\n\tplotOptions: {\n\t\tline: {\n\t\t\tdataLabels: {\n\t\t\t\tcolor: '#CCC'\n\t\t\t},\n\t\t\tmarker: {\n\t\t\t\tlineColor: '#333'\n\t\t\t}\n\t\t},\n\t\tspline: {\n\t\t\tmarker: {\n\t\t\t\tlineColor: '#333'\n\t\t\t}\n\t\t},\n\t\tscatter: {\n\t\t\tmarker: {\n\t\t\t\tlineColor: '#333'\n\t\t\t}\n\t\t},\n\t\tcandlestick: {\n\t\t\tlineColor: 'white'\n\t\t}\n\t},\n\tlegend: {\n\t\titemStyle: {\n\t\t\tfont: '9pt Trebuchet MS, Verdana, sans-serif',\n\t\t\tcolor: '#A0A0A0'\n\t\t},\n\t\titemHoverStyle: {\n\t\t\tcolor: '#FFF'\n\t\t},\n\t\titemHiddenStyle: {\n\t\t\tcolor: '#444'\n\t\t}\n\t},\n\tcredits: {\n\t\tstyle: {\n\t\t\tcolor: '#666'\n\t\t}\n\t},\n\tlabels: {\n\t\tstyle: {\n\t\t\tcolor: '#CCC'\n\t\t}\n\t},\n\n\n\tnavigation: {\n\t\tbuttonOptions: {\n\t\t\tsymbolStroke: '#DDDDDD',\n\t\t\thoverSymbolStroke: '#FFFFFF',\n\t\t\ttheme: {\n\t\t\t\tfill: {\n\t\t\t\t\tlinearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },\n\t\t\t\t\tstops: [\n\t\t\t\t\t\t[0.4, '#606060'],\n\t\t\t\t\t\t[0.6, '#333333']\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\tstroke: '#000000'\n\t\t\t}\n\t\t}\n\t},\n\n\t// scroll charts\n\trangeSelector: {\n\t\tbuttonTheme: {\n\t\t\tfill: {\n\t\t\t\tlinearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },\n\t\t\t\tstops: [\n\t\t\t\t\t[0.4, '#888'],\n\t\t\t\t\t[0.6, '#555']\n\t\t\t\t]\n\t\t\t},\n\t\t\tstroke: '#000000',\n\t\t\tstyle: {\n\t\t\t\tcolor: '#CCC',\n\t\t\t\tfontWeight: 'bold'\n\t\t\t},\n\t\t\tstates: {\n\t\t\t\thover: {\n\t\t\t\t\tfill: {\n\t\t\t\t\t\tlinearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },\n\t\t\t\t\t\tstops: [\n\t\t\t\t\t\t\t[0.4, '#BBB'],\n\t\t\t\t\t\t\t[0.6, '#888']\n\t\t\t\t\t\t]\n\t\t\t\t\t},\n\t\t\t\t\tstroke: '#000000',\n\t\t\t\t\tstyle: {\n\t\t\t\t\t\tcolor: 'white'\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tselect: {\n\t\t\t\t\tfill: {\n\t\t\t\t\t\tlinearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },\n\t\t\t\t\t\tstops: [\n\t\t\t\t\t\t\t[0.1, '#000'],\n\t\t\t\t\t\t\t[0.3, '#333']\n\t\t\t\t\t\t]\n\t\t\t\t\t},\n\t\t\t\t\tstroke: '#000000',\n\t\t\t\t\tstyle: {\n\t\t\t\t\t\tcolor: 'yellow'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tinputStyle: {\n\t\t\tbackgroundColor: '#333',\n\t\t\tcolor: 'silver'\n\t\t},\n\t\tlabelStyle: {\n\t\t\tcolor: 'silver'\n\t\t}\n\t},\n\n\tnavigator: {\n\t\thandles: {\n\t\t\tbackgroundColor: '#666',\n\t\t\tborderColor: '#AAA'\n\t\t},\n\t\toutlineColor: '#CCC',\n\t\tmaskFill: 'rgba(16, 16, 16, 0.5)',\n\t\tseries: {\n\t\t\tcolor: '#7798BF',\n\t\t\tlineColor: '#A6C7ED'\n\t\t}\n\t},\n\n\tscrollbar: {\n\t\tbarBackgroundColor: {\n\t\t\t\tlinearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },\n\t\t\t\tstops: [\n\t\t\t\t\t[0.4, '#888'],\n\t\t\t\t\t[0.6, '#555']\n\t\t\t\t]\n\t\t\t},\n\t\tbarBorderColor: '#CCC',\n\t\tbuttonArrowColor: '#CCC',\n\t\tbuttonBackgroundColor: {\n\t\t\t\tlinearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },\n\t\t\t\tstops: [\n\t\t\t\t\t[0.4, '#888'],\n\t\t\t\t\t[0.6, '#555']\n\t\t\t\t]\n\t\t\t},\n\t\tbuttonBorderColor: '#CCC',\n\t\trifleColor: '#FFF',\n\t\ttrackBackgroundColor: {\n\t\t\tlinearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },\n\t\t\tstops: [\n\t\t\t\t[0, '#000'],\n\t\t\t\t[1, '#333']\n\t\t\t]\n\t\t},\n\t\ttrackBorderColor: '#666'\n\t},\n\n\t// special colors for some of the\n\tlegendBackgroundColor: 'rgba(0, 0, 0, 0.5)',\n\tlegendBackgroundColorSolid: 'rgb(35, 35, 70)',\n\tdataLabelsColor: '#444',\n\ttextColor: '#C0C0C0',\n\tmaskColor: 'rgba(255,255,255,0.3)'\n};\n\n// Apply the theme\nvar highchartsOptions = Highcharts.setOptions(Highcharts.theme);\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/highchart3/js/themes/gray.js",
    "content": "/**\n * Gray theme for Highcharts JS\n * @author Torstein Hønsi\n */\n\nHighcharts.theme = {\n\tcolors: [\"#DDDF0D\", \"#7798BF\", \"#55BF3B\", \"#DF5353\", \"#aaeeee\", \"#ff0066\", \"#eeaaee\",\n\t\t\"#55BF3B\", \"#DF5353\", \"#7798BF\", \"#aaeeee\"],\n\tchart: {\n\t\tbackgroundColor: {\n\t\t\tlinearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },\n\t\t\tstops: [\n\t\t\t\t[0, 'rgb(96, 96, 96)'],\n\t\t\t\t[1, 'rgb(16, 16, 16)']\n\t\t\t]\n\t\t},\n\t\tborderWidth: 0,\n\t\tborderRadius: 15,\n\t\tplotBackgroundColor: null,\n\t\tplotShadow: false,\n\t\tplotBorderWidth: 0\n\t},\n\ttitle: {\n\t\tstyle: {\n\t\t\tcolor: '#FFF',\n\t\t\tfont: '16px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif'\n\t\t}\n\t},\n\tsubtitle: {\n\t\tstyle: {\n\t\t\tcolor: '#DDD',\n\t\t\tfont: '12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif'\n\t\t}\n\t},\n\txAxis: {\n\t\tgridLineWidth: 0,\n\t\tlineColor: '#999',\n\t\ttickColor: '#999',\n\t\tlabels: {\n\t\t\tstyle: {\n\t\t\t\tcolor: '#999',\n\t\t\t\tfontWeight: 'bold'\n\t\t\t}\n\t\t},\n\t\ttitle: {\n\t\t\tstyle: {\n\t\t\t\tcolor: '#AAA',\n\t\t\t\tfont: 'bold 12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif'\n\t\t\t}\n\t\t}\n\t},\n\tyAxis: {\n\t\talternateGridColor: null,\n\t\tminorTickInterval: null,\n\t\tgridLineColor: 'rgba(255, 255, 255, .1)',\n\t\tminorGridLineColor: 'rgba(255,255,255,0.07)',\n\t\tlineWidth: 0,\n\t\ttickWidth: 0,\n\t\tlabels: {\n\t\t\tstyle: {\n\t\t\t\tcolor: '#999',\n\t\t\t\tfontWeight: 'bold'\n\t\t\t}\n\t\t},\n\t\ttitle: {\n\t\t\tstyle: {\n\t\t\t\tcolor: '#AAA',\n\t\t\t\tfont: 'bold 12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif'\n\t\t\t}\n\t\t}\n\t},\n\tlegend: {\n\t\titemStyle: {\n\t\t\tcolor: '#CCC'\n\t\t},\n\t\titemHoverStyle: {\n\t\t\tcolor: '#FFF'\n\t\t},\n\t\titemHiddenStyle: {\n\t\t\tcolor: '#333'\n\t\t}\n\t},\n\tlabels: {\n\t\tstyle: {\n\t\t\tcolor: '#CCC'\n\t\t}\n\t},\n\ttooltip: {\n\t\tbackgroundColor: {\n\t\t\tlinearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },\n\t\t\tstops: [\n\t\t\t\t[0, 'rgba(96, 96, 96, .8)'],\n\t\t\t\t[1, 'rgba(16, 16, 16, .8)']\n\t\t\t]\n\t\t},\n\t\tborderWidth: 0,\n\t\tstyle: {\n\t\t\tcolor: '#FFF'\n\t\t}\n\t},\n\n\n\tplotOptions: {\n\t\tseries: {\n\t\t\tshadow: true\n\t\t},\n\t\tline: {\n\t\t\tdataLabels: {\n\t\t\t\tcolor: '#CCC'\n\t\t\t},\n\t\t\tmarker: {\n\t\t\t\tlineColor: '#333'\n\t\t\t}\n\t\t},\n\t\tspline: {\n\t\t\tmarker: {\n\t\t\t\tlineColor: '#333'\n\t\t\t}\n\t\t},\n\t\tscatter: {\n\t\t\tmarker: {\n\t\t\t\tlineColor: '#333'\n\t\t\t}\n\t\t},\n\t\tcandlestick: {\n\t\t\tlineColor: 'white'\n\t\t}\n\t},\n\n\ttoolbar: {\n\t\titemStyle: {\n\t\t\tcolor: '#CCC'\n\t\t}\n\t},\n\n\tnavigation: {\n\t\tbuttonOptions: {\n\t\t\tsymbolStroke: '#DDDDDD',\n\t\t\thoverSymbolStroke: '#FFFFFF',\n\t\t\ttheme: {\n\t\t\t\tfill: {\n\t\t\t\t\tlinearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },\n\t\t\t\t\tstops: [\n\t\t\t\t\t\t[0.4, '#606060'],\n\t\t\t\t\t\t[0.6, '#333333']\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\tstroke: '#000000'\n\t\t\t}\n\t\t}\n\t},\n\n\t// scroll charts\n\trangeSelector: {\n\t\tbuttonTheme: {\n\t\t\tfill: {\n\t\t\t\tlinearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },\n\t\t\t\tstops: [\n\t\t\t\t\t[0.4, '#888'],\n\t\t\t\t\t[0.6, '#555']\n\t\t\t\t]\n\t\t\t},\n\t\t\tstroke: '#000000',\n\t\t\tstyle: {\n\t\t\t\tcolor: '#CCC',\n\t\t\t\tfontWeight: 'bold'\n\t\t\t},\n\t\t\tstates: {\n\t\t\t\thover: {\n\t\t\t\t\tfill: {\n\t\t\t\t\t\tlinearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },\n\t\t\t\t\t\tstops: [\n\t\t\t\t\t\t\t[0.4, '#BBB'],\n\t\t\t\t\t\t\t[0.6, '#888']\n\t\t\t\t\t\t]\n\t\t\t\t\t},\n\t\t\t\t\tstroke: '#000000',\n\t\t\t\t\tstyle: {\n\t\t\t\t\t\tcolor: 'white'\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tselect: {\n\t\t\t\t\tfill: {\n\t\t\t\t\t\tlinearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },\n\t\t\t\t\t\tstops: [\n\t\t\t\t\t\t\t[0.1, '#000'],\n\t\t\t\t\t\t\t[0.3, '#333']\n\t\t\t\t\t\t]\n\t\t\t\t\t},\n\t\t\t\t\tstroke: '#000000',\n\t\t\t\t\tstyle: {\n\t\t\t\t\t\tcolor: 'yellow'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tinputStyle: {\n\t\t\tbackgroundColor: '#333',\n\t\t\tcolor: 'silver'\n\t\t},\n\t\tlabelStyle: {\n\t\t\tcolor: 'silver'\n\t\t}\n\t},\n\n\tnavigator: {\n\t\thandles: {\n\t\t\tbackgroundColor: '#666',\n\t\t\tborderColor: '#AAA'\n\t\t},\n\t\toutlineColor: '#CCC',\n\t\tmaskFill: 'rgba(16, 16, 16, 0.5)',\n\t\tseries: {\n\t\t\tcolor: '#7798BF',\n\t\t\tlineColor: '#A6C7ED'\n\t\t}\n\t},\n\n\tscrollbar: {\n\t\tbarBackgroundColor: {\n\t\t\t\tlinearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },\n\t\t\t\tstops: [\n\t\t\t\t\t[0.4, '#888'],\n\t\t\t\t\t[0.6, '#555']\n\t\t\t\t]\n\t\t\t},\n\t\tbarBorderColor: '#CCC',\n\t\tbuttonArrowColor: '#CCC',\n\t\tbuttonBackgroundColor: {\n\t\t\t\tlinearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },\n\t\t\t\tstops: [\n\t\t\t\t\t[0.4, '#888'],\n\t\t\t\t\t[0.6, '#555']\n\t\t\t\t]\n\t\t\t},\n\t\tbuttonBorderColor: '#CCC',\n\t\trifleColor: '#FFF',\n\t\ttrackBackgroundColor: {\n\t\t\tlinearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },\n\t\t\tstops: [\n\t\t\t\t[0, '#000'],\n\t\t\t\t[1, '#333']\n\t\t\t]\n\t\t},\n\t\ttrackBorderColor: '#666'\n\t},\n\n\t// special colors for some of the demo examples\n\tlegendBackgroundColor: 'rgba(48, 48, 48, 0.8)',\n\tlegendBackgroundColorSolid: 'rgb(70, 70, 70)',\n\tdataLabelsColor: '#444',\n\ttextColor: '#E0E0E0',\n\tmaskColor: 'rgba(255,255,255,0.3)'\n};\n\n// Apply the theme\nvar highchartsOptions = Highcharts.setOptions(Highcharts.theme);\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/highchart3/js/themes/grid.js",
    "content": "/**\n * Grid theme for Highcharts JS\n * @author Torstein Hønsi\n */\n\nHighcharts.theme = {\n\tcolors: ['#058DC7', '#50B432', '#ED561B', '#DDDF00', '#24CBE5', '#64E572', '#FF9655', '#FFF263', '#6AF9C4'],\n\tchart: {\n\t\tbackgroundColor: {\n\t\t\tlinearGradient: { x1: 0, y1: 0, x2: 1, y2: 1 },\n\t\t\tstops: [\n\t\t\t\t[0, 'rgb(255, 255, 255)'],\n\t\t\t\t[1, 'rgb(240, 240, 255)']\n\t\t\t]\n\t\t},\n\t\tborderWidth: 2,\n\t\tplotBackgroundColor: 'rgba(255, 255, 255, .9)',\n\t\tplotShadow: true,\n\t\tplotBorderWidth: 1\n\t},\n\ttitle: {\n\t\tstyle: {\n\t\t\tcolor: '#000',\n\t\t\tfont: 'bold 16px \"Trebuchet MS\", Verdana, sans-serif'\n\t\t}\n\t},\n\tsubtitle: {\n\t\tstyle: {\n\t\t\tcolor: '#666666',\n\t\t\tfont: 'bold 12px \"Trebuchet MS\", Verdana, sans-serif'\n\t\t}\n\t},\n\txAxis: {\n\t\tgridLineWidth: 1,\n\t\tlineColor: '#000',\n\t\ttickColor: '#000',\n\t\tlabels: {\n\t\t\tstyle: {\n\t\t\t\tcolor: '#000',\n\t\t\t\tfont: '11px Trebuchet MS, Verdana, sans-serif'\n\t\t\t}\n\t\t},\n\t\ttitle: {\n\t\t\tstyle: {\n\t\t\t\tcolor: '#333',\n\t\t\t\tfontWeight: 'bold',\n\t\t\t\tfontSize: '12px',\n\t\t\t\tfontFamily: 'Trebuchet MS, Verdana, sans-serif'\n\n\t\t\t}\n\t\t}\n\t},\n\tyAxis: {\n\t\tminorTickInterval: 'auto',\n\t\tlineColor: '#000',\n\t\tlineWidth: 1,\n\t\ttickWidth: 1,\n\t\ttickColor: '#000',\n\t\tlabels: {\n\t\t\tstyle: {\n\t\t\t\tcolor: '#000',\n\t\t\t\tfont: '11px Trebuchet MS, Verdana, sans-serif'\n\t\t\t}\n\t\t},\n\t\ttitle: {\n\t\t\tstyle: {\n\t\t\t\tcolor: '#333',\n\t\t\t\tfontWeight: 'bold',\n\t\t\t\tfontSize: '12px',\n\t\t\t\tfontFamily: 'Trebuchet MS, Verdana, sans-serif'\n\t\t\t}\n\t\t}\n\t},\n\tlegend: {\n\t\titemStyle: {\n\t\t\tfont: '9pt Trebuchet MS, Verdana, sans-serif',\n\t\t\tcolor: 'black'\n\n\t\t},\n\t\titemHoverStyle: {\n\t\t\tcolor: '#039'\n\t\t},\n\t\titemHiddenStyle: {\n\t\t\tcolor: 'gray'\n\t\t}\n\t},\n\tlabels: {\n\t\tstyle: {\n\t\t\tcolor: '#99b'\n\t\t}\n\t},\n\n\tnavigation: {\n\t\tbuttonOptions: {\n\t\t\ttheme: {\n\t\t\t\tstroke: '#CCCCCC'\n\t\t\t}\n\t\t}\n\t}\n};\n\n// Apply the theme\nvar highchartsOptions = Highcharts.setOptions(Highcharts.theme);\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/highchart3/js/themes/skies.js",
    "content": "/**\n * Skies theme for Highcharts JS\n * @author Torstein Hønsi\n */\n\nHighcharts.theme = {\n\tcolors: [\"#514F78\", \"#42A07B\", \"#9B5E4A\", \"#72727F\", \"#1F949A\", \"#82914E\", \"#86777F\", \"#42A07B\"],\n\tchart: {\n\t\tclassName: 'skies',\n\t\tborderWidth: 0,\n\t\tplotShadow: true,\n\t\tplotBackgroundImage: '/demo/gfx/skies.jpg',\n\t\tplotBackgroundColor: {\n\t\t\tlinearGradient: [0, 0, 250, 500],\n\t\t\tstops: [\n\t\t\t\t[0, 'rgba(255, 255, 255, 1)'],\n\t\t\t\t[1, 'rgba(255, 255, 255, 0)']\n\t\t\t]\n\t\t},\n\t\tplotBorderWidth: 1\n\t},\n\ttitle: {\n\t\tstyle: {\n\t\t\tcolor: '#3E576F',\n\t\t\tfont: '16px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif'\n\t\t}\n\t},\n\tsubtitle: {\n\t\tstyle: {\n\t\t\tcolor: '#6D869F',\n\t\t\tfont: '12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif'\n\t\t}\n\t},\n\txAxis: {\n\t\tgridLineWidth: 0,\n\t\tlineColor: '#C0D0E0',\n\t\ttickColor: '#C0D0E0',\n\t\tlabels: {\n\t\t\tstyle: {\n\t\t\t\tcolor: '#666',\n\t\t\t\tfontWeight: 'bold'\n\t\t\t}\n\t\t},\n\t\ttitle: {\n\t\t\tstyle: {\n\t\t\t\tcolor: '#666',\n\t\t\t\tfont: '12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif'\n\t\t\t}\n\t\t}\n\t},\n\tyAxis: {\n\t\talternateGridColor: 'rgba(255, 255, 255, .5)',\n\t\tlineColor: '#C0D0E0',\n\t\ttickColor: '#C0D0E0',\n\t\ttickWidth: 1,\n\t\tlabels: {\n\t\t\tstyle: {\n\t\t\t\tcolor: '#666',\n\t\t\t\tfontWeight: 'bold'\n\t\t\t}\n\t\t},\n\t\ttitle: {\n\t\t\tstyle: {\n\t\t\t\tcolor: '#666',\n\t\t\t\tfont: '12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif'\n\t\t\t}\n\t\t}\n\t},\n\tlegend: {\n\t\titemStyle: {\n\t\t\tfont: '9pt Trebuchet MS, Verdana, sans-serif',\n\t\t\tcolor: '#3E576F'\n\t\t},\n\t\titemHoverStyle: {\n\t\t\tcolor: 'black'\n\t\t},\n\t\titemHiddenStyle: {\n\t\t\tcolor: 'silver'\n\t\t}\n\t},\n\tlabels: {\n\t\tstyle: {\n\t\t\tcolor: '#3E576F'\n\t\t}\n\t}\n};\n\n// Apply the theme\nvar highchartsOptions = Highcharts.setOptions(Highcharts.theme);\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/js/appClient.js",
    "content": "//Date类的扩充\nDate.prototype.format = function(format) //author: meizz \n{ \n  var o = { \n    \"M+\" : this.getMonth()+1, //month \n    \"d+\" : this.getDate(),    //day \n    \"h+\" : this.getHours(),   //hour \n    \"m+\" : this.getMinutes(), //minute \n    \"s+\" : this.getSeconds(), //second \n    \"q+\" : Math.floor((this.getMonth()+3)/3),  //quarter \n    \"S\" : this.getMilliseconds() //millisecond \n  } \n  if(/(y+)/.test(format)) format=format.replace(RegExp.$1, \n    (this.getFullYear()+\"\").substr(4 - RegExp.$1.length)); \n  for(var k in o)if(new RegExp(\"(\"+ k +\")\").test(format)) \n    format = format.replace(RegExp.$1, \n      RegExp.$1.length==1 ? o[k] : \n        (\"00\"+ o[k]).substr((\"\"+ o[k]).length)); \n  return format; \n}\n\nfunction calDateWidgetDifMs(start, end) {\n\tvar startTime = start.replace(/-/g, \"/\"); \n\tvar endTime = end.replace(/-/g,\"/\");\n\tvar startDate = new Date(Date.parse(startTime)).getTime();\n\tvar endDate = new Date(Date.parse(endTime)).getTime();\n\t//毫秒差\n\treturn (endDate - startDate);\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/js/appDetail.js",
    "content": "\n//重新加载appDetail页面\nfunction reloadAppDetailPage(appId){\n\tlocation.href = \"/admin/app/index.do?appId=\" + appId + \"&tabTag=app_detail\";\n}\n\n//appDetail页面删除用户\nfunction deleteAppUser(userId,appId){\n\tif(window.confirm('确认要删除该用户吗?!')){\n\t\tvar url = \"/admin/app/deleteAppToUser.do?userId=\"+userId+\"&appId=\"+appId;\n\t\t$.ajax({\n\t\t\ttype : \"get\",\n\t\t\turl : url,\n\t\t\tasync : false,\n\t\t\tsuccess : function(data) {\n\t\t\t\talert(\"删除成功\");\n\t\t\t\treloadAppDetailPage(appId);\n\t\t\t}\n\t\t});\n\t}\n\treturn false;\n}\n\n\n//改变应用信息\nfunction updateAppDetailChange(appId){\n\tvar appDescName = document.getElementById(\"appDescName\");\n\tif(appDescName.value == \"\"){\n\t\talert(\"应用名不能为空\");\n\t\tappDescName.focus();\n\t\treturn false;\n\t}\n\tvar appDescIntro = document.getElementById(\"appDescIntro\");\n\tif(appDescIntro.value == \"\"){\n\t\talert(\"应用描述不能为空\");\n\t\tappDescIntro.focus();\n\t\treturn false;\n\t}\n\tvar officer = document.getElementById(\"officer\");\n\tif(officer.value == \"\"){\n\t\talert(\"负责人不能为空\");\n\t\tofficer.focus();\n\t\treturn false;\n\t}\n\tvar updateAppDetailBtn = document.getElementById(\"updateAppDetailBtn\");\n\tupdateAppDetailBtn.disabled = true;\n\t$.post(\n\t\t'/admin/app/updateAppDetail.do',\n\t\t{\n\t\t\tappId: appId,\n\t\t\tappDescName: appDescName.value,\n\t\t\tappDescIntro: appDescIntro.value,\n\t\t\tofficer: officer.value\n\t\t},\n        function(data){\n            if(data==1){\n                alert(\"修改成功！\");\n            \t$(\"#updateAppDetailInfo\").html(\"<div class='alert alert-error' ><button class='close' data-dismiss='alert'>×</button><strong>Success!</strong>更新成功，窗口会自动关闭</div>\");\n                setTimeout(\"$('updateAppDetailModal').modal('hide');reloadAppDetailPage(\"+appId+\");\",1000);\n            }else{\n            \tupdateAppDetailBtn.disabled = false;\n                $(\"#updateAppDetailInfo\").html(\"<div class='alert alert-error' ><button class='close' data-dismiss='alert'>×</button><strong>Error!</strong>更新失败！</div>\");\n            }\n        }\n     );\n}\n\n\n//改变内存阀值\nfunction appAlertConfigChange(appId){\n\tvar memAlertValue = document.getElementById(\"memAlertValue\");\n\tif(memAlertValue.value == \"\"){\n\t\talert(\"内存报警阀值不能为空\");\n\t\tmemAlertValue.focus();\n\t\treturn false;\n\t}\n\tvar clientConnAlertValue = document.getElementById(\"clientConnAlertValue\");\n\tif(clientConnAlertValue.value == \"\"){\n\t\talert(\"客户端连接数报警阀值不能为空\");\n\t\tclientConnAlertValue.focus();\n\t\treturn false;\n\t}\n\tvar appConfigChangeBtn = document.getElementById(\"appConfigChangeBtn\");\n\tappConfigChangeBtn.disabled = true;\n\t$.post(\n\t\t'/admin/app/changeAppAlertConfig.do',\n\t\t{\n\t\t\tappId: appId,\n\t\t\tmemAlertValue: memAlertValue.value,\n\t\t\tclientConnAlertValue: clientConnAlertValue.value\n\t\t},\n        function(data){\n            if(data==1){\n                alert(\"修改成功！\");\n            \t$(\"#appConfigChangeInfo\").html(\"<div class='alert alert-error' ><button class='close' data-dismiss='alert'>×</button><strong>Success!</strong>更新成功，窗口会自动关闭</div>\");\n                setTimeout(\"$('appScaleApplyModal').modal('hide');reloadAppDetailPage(\"+appId+\");\",1000);\n            }else{\n            \tappConfigChangeBtn.disabled = false;\n                $(\"#appConfigChangeInfo\").html(\"<div class='alert alert-error' ><button class='close' data-dismiss='alert'>×</button><strong>Error!</strong>更新失败！</div>\");\n            }\n        }\n     );\n}\n\n//添加应用用户\nfunction appAddUser(appId){\n\tvar userName = document.getElementById(\"userName\").value;\n\tif(userName == \"\"){\n\t\talert(\"用户名不能为空\");\n\t\treturn false;\n\t}\n\tvar appAddUserBtn = document.getElementById(\"appAddUserBtn\");\n\tappAddUserBtn.disabled = true;\n\t$.post(\n\t\t'/admin/app/addAppToUser.do',\n\t\t{\n\t\t\tappId: appId,\n\t\t\tuserName: userName\n\t\t},\n        function(data){\n            if(data==1){\n                alert(\"用户添加成功!\");\n            \t$(\"#appAddUserInfo\").html(\"<div class='alert alert-error' ><button class='close' data-dismiss='alert'>×</button><strong>Success!</strong>更新成功，窗口会自动关闭</div>\");\n                setTimeout(\"$('appAddUserModal').modal('hide');reloadAppDetailPage(\"+appId+\");\",1000);\n            }else{\n            \tappAddUserBtn.disabled = false;\n            \talert(\"cachecloud中不存在该用户，只能添加有cachecloud权限的用户\");\n                $(\"#appAddUserInfo\").html(\"<div class='alert alert-error' ><button class='close' data-dismiss='alert'>×</button><strong>Error!</strong>添加失败,cachecloud中不存在该用户，只能添加有cachecloud权限的用户！</div>\");\n            }\n        }\n     );\n}\n\n//验证手机号格式\nvar valPhones=/^(1[3|5|8][0-9]\\d{4,8};){0,6}(1[3|5|8][0-9]\\d{4,8})$/; \n//验证邮箱格式\nvar valEmails=/^(([a-zA-Z0-9]+[_|\\_|\\.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|\\_|\\.|\\-]?)*[a-zA-Z0-9]+\\.[a-zA-Z]{2,3};){0,6}([a-zA-Z0-9]+[_|\\_|\\.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|\\_|\\.|\\-]?)*[a-zA-Z0-9]+\\.[a-zA-Z]{2,3}$/;\nfunction saveOrUpdateUser(userId){\n\tvar name = document.getElementById(\"name\" + userId);\n\tvar chName = document.getElementById(\"chName\" + userId);\n\tvar email = document.getElementById(\"email\" + userId);\n\tvar mobile = document.getElementById(\"mobile\" + userId);\n\tvar type = document.getElementById(\"type\" + userId);\n\tif(name.value == \"\"){\n    \talert(\"域账户名不能为空!\");\n\t\tname.focus();\n\t\treturn false;\n    }\n\tif(chName.value == \"\"){\n    \talert(\"中文名不能为空!\");\n\t\tchName.focus();\n\t\treturn false;\n    }\n\tif(email.value == \"\"){\n\t\talert(\"邮箱不能为空!\");\n\t\temail.focus();\n\t\treturn false;\n\t}\n\tif(!valEmails.test(email.value)){\n\t\talert(\"邮箱格式错误!\");\n\t\temail.focus();\n\t\treturn false;\n\t}\n\tif(mobile.value == \"\"){\n\t\talert(\"手机号不能为空!\");\n\t\tmobile.focus();\n\t\treturn false;\n\t}\n\tif(!valPhones.test(mobile.value)){\n\t\talert(\"手机号格式错误!\");\n\t\tmobile.focus();\n\t\treturn false;\n\t}\n\t$.post(\n\t\t'/admin/app/changeAppUserInfo.do',\n\t\t{\n\t\t\tname: name.value,\n\t\t\tchName: chName.value,\n\t\t\temail: email.value,\n\t\t\tmobile: mobile.value,\n\t\t\ttype: type.value,\n\t\t\tuserId: userId\n\t\t},\n        function(data){\n            if(data==1){\n                $(\"#info\" + userId).html(\"<div class='alert alert-error' ><button class='close' data-dismiss='alert'>×</button><strong>Success!</strong>更新成功，窗口会自动关闭</div>\");\n                var targetId = \"#addUserModal\" + userId;\n                setTimeout(\"$('\" + targetId +\"').modal('hide');reloadAppDetailPage(\"+appId+\")\",1000);\n            }else{\n                $(\"#info\" + userId).html(\"<div class='alert alert-error' ><button class='close' data-dismiss='alert'>×</button><strong>Error!</strong>更新失败！</div>\");\n            }\n        }\n     );\n}\n\n\n\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/js/appInit.js",
    "content": "\n//验证是数字\nfunction testisNum(id){\n   var value =document.getElementById(id).value;\n   if(value != \"\" && isNaN(value)){\n      alert(\"请输入数字类型!\");\n      document.getElementById(id).value=\"\";\n      document.getElementById(id).focus();\n   }\n}\n\n//保存应用\nfunction saveAppDesc(){\n\t//应用名\n\tvar appName = document.getElementById(\"appName\");\n\tif(appName.value == \"\"){\n\t\talert(\"应用名不能为空\");\n\t\tappName.focus();\n\t\treturn false;\n\t}\n\t\n\tvar appExist = document.getElementById(\"appExist\");\n\tif(appExist.value == 1){\n\t\talert(\"应用名已经存在,请修改!\");\n\t\tappName.focus();\n\t\treturn false;\n\t}\n\t\n\t//应用描述\n\tvar appIntro = document.getElementById(\"appIntro\");\n\tif(appIntro.value == \"\"){\n\t\talert(\"应用描述不能为空\");\n\t\tappIntro.focus();\n\t\treturn false;\n\t}\n\t\n\t//应用描述\n\tvar memSize = document.getElementById(\"memSize\");\n\tif(memSize.value == \"\"){\n\t\talert(\"内容容量不能为空\");\n\t\tmemSize.focus();\n\t\treturn false;\n\t}\n\t\n\t//项目负责人\n\tvar officer = document.getElementById(\"officer\");\n\tif(officer.value == \"\"){\n\t\talert(\"项目负责人不能为空\");\n\t\tofficer.focus();\n\t\treturn false;\n\t}\n\t\n\t//预估QPS\n\tvar forecaseQps = document.getElementById(\"forecaseQps\");\n\tif(forecaseQps.value == \"\"){\n\t\talert(\"预估QPS不能为空\");\n\t\tforecaseQps.focus();\n\t\treturn false;\n\t}\n\t\n\t//预估条目数量\n\tvar forecastObjNum = document.getElementById(\"forecastObjNum\");\n\tif(forecastObjNum.value == \"\"){\n\t\talert(\"预估条目数量不能为空\");\n\t\tforecastObjNum.focus();\n\t\treturn false;\n\t}\n\t\n\t//客户端机房信息\n\tvar clientMachineRoom = document.getElementById(\"clientMachineRoom\");\n\tif(clientMachineRoom.value == \"\"){\n\t\talert(\"客户端机房信息不能为空\");\n\t\tclientMachineRoom.focus();\n\t\treturn false;\n\t}\n\t\n\t//内存报警阀值\n\tvar memAlertValue = document.getElementById(\"memAlertValue\");\n\tif(memAlertValue.value == \"\"){\n\t\talert(\"内存报警阀值不能为空\");\n\t\tmemAlertValue.focus();\n\t\treturn false;\n\t}\n\t\n\t//客户端连接数报警阀值\n\tvar clientConnAlertValue = document.getElementById(\"clientConnAlertValue\");\n\tif(clientConnAlertValue.value == \"\"){\n\t\talert(\"客户端连接数报警阀值不能为空\");\n\t\tclientConnAlertValue.focus();\n\t\treturn false;\n\t}\n\t\n\treturn true;\t\n}\n\n//查看应用名是否已经存在\nfunction checkAppNameExist(){\n\tvar appName = document.getElementById(\"appName\").value;\n\tif(appName != ''){\n\t\t$.post(\n\t\t\t'/admin/app/checkAppNameExist.do',\n\t\t\t{\n\t\t\t\tappName: appName,\n\t\t\t},\n\t        function(data){\n\t            if(data==1){\n\t            \talert(\"应用名已经存在，请修改\");\n\t            \tdocument.getElementById(\"appName\").focus();\n\t            \tdocument.getElementById(\"appExist\").value = 1;\n\t            }else{\n\t            \tdocument.getElementById(\"appExist\").value = 0;\n\t            }\n\t        }\n\t     );\n\t}\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/js/appStat.js",
    "content": "\n//重新加载appDetail页面\nfunction reloadAppStatPage(appId){\n\tlocation.href = \"/admin/app/index.do?appId=\" + appId + \"&tabTag=app_stat\";\n}\n\nfunction appConfigChange(appId, instanceId){\n\tvar appConfigKey = document.getElementById(\"appConfigKey\");\n\tif(appConfigKey.value == \"\"){\n\t\talert(\"配置项不能为空\");\n\t\tappConfigKey.focus();\n\t\treturn false;\n\t}\n\t\n\tvar appConfigValue = document.getElementById(\"appConfigValue\");\n\tif(appConfigValue.value == \"\"){\n\t\talert(\"配置值不能为空\");\n\t\tappConfigValue.focus();\n\t\treturn false;\n\t}\n\n    var appConfigReason = document.getElementById(\"appConfigReason\");\n    if(appConfigReason.value == \"\"){\n        alert(\"配置原因不能为空\");\n        appConfigReason.focus();\n        return false;\n    }\n    \n    var appConfigChangeBtn = document.getElementById(\"appConfigChangeBtn\");\n    appConfigChangeBtn.disabled = true;\n\t\n\t$.post(\n\t\t'/admin/app/changeAppConfig.do',\n\t\t{\n\t\t\tappId: appId,\n\t\t\tinstanceId: instanceId,\n\t\t\tappConfigKey: appConfigKey.value,\n\t\t\tappConfigValue: appConfigValue.value,\n            appConfigReason: appConfigReason.value\n\t\t},\n        function(data){\n            if(data==1){\n                alert(\"申请成功，请在邮件中关注申请状况.\");\n            \t$(\"#appConfigChangeInfo\").html(\"<div class='alert alert-error' ><button class='close' data-dismiss='alert'>×</button><strong>Success!</strong>更新成功，窗口会自动关闭</div>\");\n                setTimeout(\"$('appConfigChangeModal').modal('hide');reloadAppStatPage(\"+appId+\");\",1000);\n\n            }else{\n            \tappConfigChangeBtn.disabled = false;\n                $(\"#appConfigChangeInfo\").html(\"<div class='alert alert-error' ><button class='close' data-dismiss='alert'>×</button><strong>Error!</strong>更新失败！</div>\");\n            }\n        }\n     );\n}\n\n\n//申请应用扩容\nfunction appScaleApply(appId){\n\tvar applyMemSize = document.getElementById(\"applyMemSize\");\n\tif(applyMemSize.value == \"\"){\n\t\talert(\"请填写要扩容的容量!\");\n\t\tapplyMemSize.focus();\n\t\treturn false;\n\t}\n\t\n\tvar appScaleReason = document.getElementById(\"appScaleReason\");\n\tif(appScaleReason.value == \"\"){\n\t\talert(\"请填写申请扩容的原因!\");\n\t\tappScaleReason.focus();\n\t\treturn false;\n\t}\n\tvar appScaleApplyBtn = document.getElementById(\"appScaleApplyBtn\");\n\tappScaleApplyBtn.disabled = true;\n\t\n\t$.post(\n\t\t'/admin/app/scale.do',\n\t\t{\n\t\t\tappId: appId,\n\t\t\tapplyMemSize: applyMemSize.value,\n\t\t\tappScaleReason: appScaleReason.value\n\t\t},\n        function(data){\n            if(data==1){\n                alert(\"申请成功，请在邮件中关注申请状况.\");\n            \t$(\"#appScaleApplyInfo\").html(\"<div class='alert alert-error' ><button class='close' data-dismiss='alert'>×</button><strong>Success!</strong>更新成功，窗口会自动关闭</div>\");\n                setTimeout(\"$('appScaleApplyModal').modal('hide');reloadAppStatPage(\"+appId+\");\",1000);\n            }else{\n            \tappScaleApplyBtn.disabled = false;\n                $(\"#appScaleApplyInfo\").html(\"<div class='alert alert-error' ><button class='close' data-dismiss='alert'>×</button><strong>Error!</strong>更新失败！</div>\");\n            }\n        }\n     );\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/js/chart.js",
    "content": "var chart_options = {\n    t: \"t\"\n};\n\nvar refreshChartByTool = function (url, param, option_user) {\n    $.get(url, param, function (data) {\n        var options = data.chart;\n        if (typeof options.tooltip != undefined && typeof options.tooltip.formatter != null) {\n            options.tooltip.formatter = eval('(' + options.tooltip.formatter + ')');\n        }\n\n        for (var o in options) {\n            console.log(o);\n            if (options.hasOwnProperty(o)) {\n                $.extend(options[o], options[o]);\n            } else {\n                options[o] = options[o];\n            }\n\n        }\n\n        for (var o in option_user) {\n            console.log(o);\n            if (options.hasOwnProperty(o)) {\n                $.extend(options[o], option_user[o]);\n            } else {\n                options[o] = option_user[o];\n            }\n        }\n        new Highcharts.Chart(options);\n    }, 'json');\n}\n\nvar initChart = function (pre) {\n    var _c_cu = eval(pre + '_c_cu');\n    var _c_o = eval(pre + '_c_o');\n//    console.log(instance_stat_c_cu);\n    if (typeof (_c_cu) != 'undefined' && typeof (_c_o) != 'undefined') {\n        for (var index in _c_cu) {\n            var container = index;\n            var url = _c_cu[index];\n            var param = {};\n            param['container'] = container;\n//            console.log(container);\n            refreshChartByTool(url, param, _c_o[index]);\n        }\n    }\n};\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/js/instanceExecute.js",
    "content": "var execute = function () {\n    var command = $('#command').value;\n    $.ajax({\n        url: \"/admin/instance/commandExecute.json\",\n        data: {instanceId: $('#instanceId').val(), command: $('#command').val()},\n        dataType: \"json\",\n        success: function (result) {\n            $('#result').append('<p>' + $('#command').val() + '</p>');\n            $('#result').append('<p>' + result.result + '</p>');\n        }\n    });\n};"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/js/jquery-console.js",
    "content": "// JQuery Console 1.0\n// Sun Feb 21 20:28:47 GMT 2010\n//\n// Copyright 2010 Chris Done, Simon David Pratt. 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\n// are met:\n//\n//    1. Redistributions of source code must retain the above\n//       copyright notice, this list of conditions and the following\n//       disclaimer.\n//\n//    2. Redistributions in binary form must reproduce the above\n//       copyright notice, this list of conditions and the following\n//       disclaimer in the documentation and/or other materials\n//       provided with the distribution.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n// \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS\n// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\n// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\n// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\n// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\n// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n// POSSIBILITY OF SUCH DAMAGE.\n\n// TESTED ON\n//   Internet Explorer 6\n//   Opera 10.01\n//   Chromium 4.0.237.0 (Ubuntu build 31094)\n//   Firefox 3.5.8, 3.6.2 (Mac)\n//   Safari 4.0.5 (6531.22.7) (Mac)\n//   Google Chrome 5.0.375.55 (Mac)\n\n(function($){\n    var isWebkit = !!~navigator.userAgent.indexOf(' AppleWebKit/');\n\n    $.fn.console = function(config){\n        ////////////////////////////////////////////////////////////////////////\n        // Constants\n        // Some are enums, data types, others just for optimisation\n        var keyCodes = {\n            // left\n            37: moveBackward,\n            // right\n            39: moveForward,\n            // up\n            38: previousHistory,\n            // down\n            40: nextHistory,\n            // backspace\n            8:  backDelete,\n            // delete\n            46: forwardDelete,\n            // end\n            35: moveToEnd,\n            // start\n            36: moveToStart,\n            // return\n            13: commandTrigger,\n            // tab\n            18: doNothing,\n            // tab\n            9: doComplete\n        };\n        var ctrlCodes = {\n            // C-a\n            65: moveToStart,\n            // C-e\n            69: moveToEnd,\n            // C-d\n            68: forwardDelete,\n            // C-n\n            78: nextHistory,\n            // C-p\n            80: previousHistory,\n            // C-b\n            66: moveBackward,\n            // C-f\n            70: moveForward,\n            // C-k\n            75: deleteUntilEnd\n        };\n        if(config.ctrlCodes) {\n            $.extend(ctrlCodes, config.ctrlCodes);\n        }\n        var altCodes = {\n            // M-f\n            70: moveToNextWord,\n            // M-b\n            66: moveToPreviousWord,\n            // M-d\n            68: deleteNextWord\n        };\n        var shiftCodes = {\n            // return\n            13: newLine\n        };\n        var cursor = '<span class=\"jquery-console-cursor\">&nbsp;</span>';\n\n        ////////////////////////////////////////////////////////////////////////\n        // Globals\n        var container = $(this);\n        var inner = $('<div class=\"jquery-console-inner\"></div>');\n        // erjiang: changed this from a text input to a textarea so we\n        // can get pasted newlines\n        var typer = $('<textarea class=\"jquery-console-typer\"></textarea>');\n        // Prompt\n        var promptBox;\n        var prompt;\n        var continuedPromptLabel = config && config.continuedPromptLabel?\n            config.continuedPromptLabel : \"> \";\n        var column = 0;\n        var promptText = '';\n        var restoreText = '';\n        var continuedText = '';\n        var fadeOnReset = config.fadeOnReset !== undefined ? config.fadeOnReset : true;\n        // Prompt history stack\n        var history = [];\n        var ringn = 0;\n        // For reasons unknown to The Sword of Michael himself, Opera\n        // triggers and sends a key character when you hit various\n        // keys like PgUp, End, etc. So there is no way of knowing\n        // when a user has typed '#' or End. My solution is in the\n        // typer.keydown and typer.keypress functions; I use the\n        // variable below to ignore the keypress event if the keydown\n        // event succeeds.\n        var cancelKeyPress = 0;\n        // When this value is false, the prompt will not respond to input\n        var acceptInput = true;\n        // When this value is true, the command has been canceled\n        var cancelCommand = false;\n\n        // External exports object\n        var extern = {};\n\n        ////////////////////////////////////////////////////////////////////////\n        // Main entry point\n        (function(){\n            extern.promptLabel = config && config.promptLabel? config.promptLabel : \"> \";\n            container.append(inner);\n            inner.append(typer);\n            typer.css({position:'absolute',top:0,left:'-9999px'});\n            if (config.welcomeMessage)\n                message(config.welcomeMessage,'jquery-console-welcome');\n            newPromptBox();\n            if (config.autofocus) {\n                inner.addClass('jquery-console-focus');\n                typer.focus();\n                setTimeout(function(){\n                    inner.addClass('jquery-console-focus');\n                    typer.focus();\n                },100);\n            }\n            extern.inner = inner;\n            extern.typer = typer;\n            extern.scrollToBottom = scrollToBottom;\n            extern.report = report;\n        })();\n\n        ////////////////////////////////////////////////////////////////////////\n        // Reset terminal\n        extern.reset = function(){\n            var welcome = (typeof config.welcomeMessage != 'undefined');\n\n            var removeElements = function() {\n                inner.find('div').each(function(){\n                    if (!welcome) {\n                        $(this).remove();\n                    } else {\n                        welcome = false;\n                    }\n                });\n            };\n\n            if (fadeOnReset) {\n                inner.parent().fadeOut(function() {\n                    removeElements();\n                    newPromptBox();\n                    inner.parent().fadeIn(focusConsole);\n                });\n            }\n            else {\n                removeElements();\n                newPromptBox();\n                focusConsole();\n            }\n        };\n\n        var focusConsole = function() {\n            inner.addClass('jquery-console-focus');\n            typer.focus();\n        };\n\n        extern.focus = function(){\n            focusConsole();\n        }\n\n        ////////////////////////////////////////////////////////////////////////\n        // Reset terminal\n        extern.notice = function(msg,style){\n            var n = $('<div class=\"notice\"></div>').append($('<div></div>').text(msg))\n                .css({visibility:'hidden'});\n            container.append(n);\n            var focused = true;\n            if (style=='fadeout')\n                setTimeout(function(){\n                    n.fadeOut(function(){\n                        n.remove();\n                    });\n                },4000);\n            else if (style=='prompt') {\n                var a = $('<br/><div class=\"action\"><a href=\"javascript:\">OK</a><div class=\"clear\"></div></div>');\n                n.append(a);\n                focused = false;\n                a.click(function(){ n.fadeOut(function(){ n.remove();inner.css({opacity:1}) }); });\n            }\n            var h = n.height();\n            n.css({height:'0px',visibility:'visible'})\n                .animate({height:h+'px'},function(){\n                    if (!focused) inner.css({opacity:0.5});\n                });\n            n.css('cursor','default');\n            return n;\n        };\n\n        ////////////////////////////////////////////////////////////////////////\n        // Make a new prompt box\n        function newPromptBox() {\n            column = 0;\n            promptText = '';\n            ringn = 0; // Reset the position of the history ring\n            enableInput();\n            promptBox = $('<div class=\"jquery-console-prompt-box\"></div>');\n            var label = $('<span class=\"jquery-console-prompt-label\"></span>');\n            var labelText = extern.continuedPrompt? continuedPromptLabel : extern.promptLabel;\n            promptBox.append(label.text(labelText).show());\n            label.html(label.html().replace(' ','&nbsp;'));\n            prompt = $('<span class=\"jquery-console-prompt\"></span>');\n            promptBox.append(prompt);\n            inner.append(promptBox);\n            updatePromptDisplay();\n        };\n\n        ////////////////////////////////////////////////////////////////////////\n        // Handle setting focus\n        container.click(function(){\n            // Don't mess with the focus if there is an active selection\n            if (window.getSelection().toString()) {\n                return false;\n            }\n\n            inner.addClass('jquery-console-focus');\n            inner.removeClass('jquery-console-nofocus');\n            if (isWebkit) {\n                typer.focusWithoutScrolling();\n            } else {\n                typer.css('position', 'fixed').focus();\n            }\n            scrollToBottom();\n            return false;\n        });\n\n        ////////////////////////////////////////////////////////////////////////\n        // Handle losing focus\n        typer.blur(function(){\n            inner.removeClass('jquery-console-focus');\n            inner.addClass('jquery-console-nofocus');\n        });\n\n        ////////////////////////////////////////////////////////////////////////\n        // Bind to the paste event of the input box so we know when we\n        // get pasted data\n        typer.bind('paste', function(e) {\n            // wipe typer input clean just in case\n            typer.val(\"\");\n            // this timeout is required because the onpaste event is\n            // fired *before* the text is actually pasted\n            setTimeout(function() {\n                typer.consoleInsert(typer.val());\n                typer.val(\"\");\n            }, 0);\n        });\n\n        ////////////////////////////////////////////////////////////////////////\n        // Handle key hit before translation\n        // For picking up control characters like up/left/down/right\n\n        typer.keydown(function(e){\n            cancelKeyPress = 0;\n            var keyCode = e.keyCode;\n            // C-c: cancel the execution\n            if(e.ctrlKey && keyCode == 67) {\n                cancelKeyPress = keyCode;\n                cancelExecution();\n                return false;\n            }\n            if (acceptInput) {\n                if (e.shiftKey && keyCode in shiftCodes) {\n                    cancelKeyPress = keyCode;\n                    (shiftCodes[keyCode])();\n                    return false;\n                } else if (e.altKey  && keyCode in altCodes) {\n                    cancelKeyPress = keyCode;\n                    (altCodes[keyCode])();\n                    return false;\n                } else if (e.ctrlKey && keyCode in ctrlCodes) {\n                    cancelKeyPress = keyCode;\n                    (ctrlCodes[keyCode])();\n                    return false;\n                } else if (keyCode in keyCodes) {\n                    cancelKeyPress = keyCode;\n                    (keyCodes[keyCode])();\n                    return false;\n                }\n            }\n        });\n\n        ////////////////////////////////////////////////////////////////////////\n        // Handle key press\n        typer.keypress(function(e){\n            var keyCode = e.keyCode || e.which;\n            if (isIgnorableKey(e)) {\n                return false;\n            }\n            // C-v: don't insert on paste event\n            if ((e.ctrlKey || e.metaKey) && String.fromCharCode(keyCode).toLowerCase() == 'v') {\n                return true;\n            }\n            if (acceptInput && cancelKeyPress != keyCode && keyCode >= 32){\n                if (cancelKeyPress) return false;\n                if (\n                    typeof config.charInsertTrigger == 'undefined' || (\n                    typeof config.charInsertTrigger == 'function' &&\n                    config.charInsertTrigger(keyCode,promptText)\n                    )\n                    ){\n                    typer.consoleInsert(keyCode);\n                }\n            }\n            if (isWebkit) return false;\n        });\n\n        function isIgnorableKey(e) {\n            // for now just filter alt+tab that we receive on some platforms when\n            // user switches windows (goes away from the browser)\n            return ((e.keyCode == keyCodes.tab || e.keyCode == 192) && e.altKey);\n        };\n\n        ////////////////////////////////////////////////////////////////////////\n        // Rotate through the command history\n        function rotateHistory(n){\n            if (history.length == 0) return;\n            ringn += n;\n            if (ringn < 0) ringn = history.length;\n            else if (ringn > history.length) ringn = 0;\n            var prevText = promptText;\n            if (ringn == 0) {\n                promptText = restoreText;\n            } else {\n                promptText = history[ringn - 1];\n            }\n            if (config.historyPreserveColumn) {\n                if (promptText.length < column + 1) {\n                    column = promptText.length;\n                } else if (column == 0) {\n                    column = promptText.length;\n                }\n            } else {\n                column = promptText.length;\n            }\n            updatePromptDisplay();\n        };\n\n        function previousHistory() {\n            rotateHistory(-1);\n        };\n\n        function nextHistory() {\n            rotateHistory(1);\n        };\n\n        // Add something to the history ring\n        function addToHistory(line){\n            history.push(line);\n            restoreText = '';\n        };\n\n        // Delete the character at the current position\n        function deleteCharAtPos(){\n            if (column < promptText.length){\n                promptText =\n                    promptText.substring(0,column) +\n                    promptText.substring(column+1);\n                restoreText = promptText;\n                return true;\n            } else return false;\n        };\n\n        function backDelete() {\n            if (moveColumn(-1)){\n                deleteCharAtPos();\n                updatePromptDisplay();\n            }\n        };\n\n        function forwardDelete() {\n            if (deleteCharAtPos()){\n                updatePromptDisplay();\n            }\n        };\n\n        function deleteUntilEnd() {\n            while(deleteCharAtPos()) {\n                updatePromptDisplay();\n            }\n        };\n\n        function deleteNextWord() {\n            // A word is defined within this context as a series of alphanumeric\n            // characters.\n            // Delete up to the next alphanumeric character\n            while(\n                column < promptText.length &&\n                !isCharAlphanumeric(promptText[column])\n                ) {\n                deleteCharAtPos();\n                updatePromptDisplay();\n            }\n            // Then, delete until the next non-alphanumeric character\n            while(\n                column < promptText.length &&\n                isCharAlphanumeric(promptText[column])\n                ) {\n                deleteCharAtPos();\n                updatePromptDisplay();\n            }\n        };\n\n        function newLine() {\n            var lines = promptText.split(\"\\n\");\n            var last_line = lines.slice(-1)[0];\n            var spaces = last_line.match(/^(\\s*)/g)[0];\n            var new_line = \"\\n\" + spaces;\n            promptText += new_line;\n            moveColumn(new_line.length);\n            updatePromptDisplay();\n        };\n\n        ////////////////////////////////////////////////////////////////////////\n        // Validate command and trigger it if valid, or show a validation error\n        function commandTrigger() {\n            var line = promptText;\n            if (typeof config.commandValidate == 'function') {\n                var ret = config.commandValidate(line);\n                if (ret == true || ret == false) {\n                    if (ret) {\n                        handleCommand();\n                    }\n                } else {\n                    commandResult(ret,\"jquery-console-message-error\");\n                }\n            } else {\n                handleCommand();\n            }\n        };\n\n        // Scroll to the bottom of the view\n        function scrollToBottom() {\n            var version = jQuery.fn.jquery.split('.');\n            var major = parseInt(version[0]);\n            var minor = parseInt(version[1]);\n\n            // check if we're using jquery > 1.6\n            if ((major == 1 && minor > 6) || major > 1) {\n                inner.prop({ scrollTop: inner.prop(\"scrollHeight\") });\n            }\n            else {\n                inner.attr({ scrollTop: inner.attr(\"scrollHeight\") });\n            }\n        };\n\n        function cancelExecution() {\n            if(typeof config.cancelHandle == 'function') {\n                config.cancelHandle();\n            }\n        }\n\n        ////////////////////////////////////////////////////////////////////////\n        // Handle a command\n        function handleCommand() {\n            if (typeof config.commandHandle == 'function') {\n                disableInput();\n                addToHistory(promptText);\n                var text = promptText;\n                if (extern.continuedPrompt) {\n                    if (continuedText)\n                        continuedText += '\\n' + promptText;\n                    else continuedText = promptText;\n                } else continuedText = undefined;\n                if (continuedText) text = continuedText;\n                var ret = config.commandHandle(text,function(msgs){\n                    commandResult(msgs);\n                });\n                if (extern.continuedPrompt && !continuedText)\n                    continuedText = promptText;\n                if (typeof ret == 'boolean') {\n                    if (ret) {\n                        // Command succeeded without a result.\n                        commandResult();\n                    } else {\n                        commandResult(\n                            'Command failed.',\n                            \"jquery-console-message-error\"\n                        );\n                    }\n                } else if (typeof ret == \"string\") {\n                    commandResult(ret,\"jquery-console-message-success\");\n                } else if (typeof ret == 'object' && ret.length) {\n                    commandResult(ret);\n                } else if (extern.continuedPrompt) {\n                    commandResult();\n                }\n            }\n        };\n\n        ////////////////////////////////////////////////////////////////////////\n        // Disable input\n        function disableInput() {\n            acceptInput = false;\n        };\n\n        // Enable input\n        function enableInput() {\n            acceptInput = true;\n        }\n\n        ////////////////////////////////////////////////////////////////////////\n        // Reset the prompt in invalid command\n        function commandResult(msg,className) {\n            column = -1;\n            updatePromptDisplay();\n            if (typeof msg == 'string') {\n                message(msg,className);\n            } else if ($.isArray(msg)) {\n                for (var x in msg) {\n                    var ret = msg[x];\n                    message(ret.msg,ret.className);\n                }\n            } else { // Assume it's a DOM node or jQuery object.\n                inner.append(msg);\n            }\n            newPromptBox();\n        };\n\n        ////////////////////////////////////////////////////////////////////////\n        // Report some message into the console\n        function report(msg,className) {\n            var text = promptText;\n            promptBox.remove();\n            commandResult(msg,className);\n            extern.promptText(text);\n        };\n\n        ////////////////////////////////////////////////////////////////////////\n        // Display a message\n        function message(msg,className) {\n            var mesg = $('<div class=\"jquery-console-message\"></div>');\n            if (className) mesg.addClass(className);\n            mesg.filledText(msg).hide();\n            inner.append(mesg);\n            mesg.show();\n        };\n\n        ////////////////////////////////////////////////////////////////////////\n        // Handle normal character insertion\n        // data can either be a number, which will be interpreted as the\n        // numeric value of a single character, or a string\n        typer.consoleInsert = function(data){\n            // TODO: remove redundant indirection\n            var text = (typeof data == 'number') ? String.fromCharCode(data) : data;\n            var before = promptText.substring(0,column);\n            var after = promptText.substring(column);\n            promptText = before + text + after;\n            moveColumn(text.length);\n            restoreText = promptText;\n            updatePromptDisplay();\n        };\n\n        ////////////////////////////////////////////////////////////////////////\n        // Move to another column relative to this one\n        // Negative means go back, positive means go forward.\n        function moveColumn(n){\n            if (column + n >= 0 && column + n <= promptText.length){\n                column += n;\n                return true;\n            } else return false;\n        };\n\n        function moveForward() {\n            if(moveColumn(1)) {\n                updatePromptDisplay();\n                return true;\n            }\n            return false;\n        };\n\n        function moveBackward() {\n            if(moveColumn(-1)) {\n                updatePromptDisplay();\n                return true;\n            }\n            return false;\n        };\n\n        function moveToStart() {\n            if (moveColumn(-column))\n                updatePromptDisplay();\n        };\n\n        function moveToEnd() {\n            if (moveColumn(promptText.length-column))\n                updatePromptDisplay();\n        };\n\n        function moveToNextWord() {\n            while(\n                column < promptText.length &&\n                !isCharAlphanumeric(promptText[column]) &&\n                moveForward()\n                ) {}\n            while(\n                column < promptText.length &&\n                isCharAlphanumeric(promptText[column]) &&\n                moveForward()\n                ) {}\n        };\n\n        function moveToPreviousWord() {\n            // Move backward until we find the first alphanumeric\n            while(\n                column -1 >= 0 &&\n                !isCharAlphanumeric(promptText[column-1]) &&\n                moveBackward()\n                ) {}\n            // Move until we find the first non-alphanumeric\n            while(\n                column -1 >= 0 &&\n                isCharAlphanumeric(promptText[column-1]) &&\n                moveBackward()\n                ) {}\n        };\n\n        function isCharAlphanumeric(charToTest) {\n            if(typeof charToTest == 'string') {\n                var code = charToTest.charCodeAt();\n                return (code >= 'A'.charCodeAt() && code <= 'Z'.charCodeAt()) ||\n                    (code >= 'a'.charCodeAt() && code <= 'z'.charCodeAt()) ||\n                    (code >= '0'.charCodeAt() && code <= '9'.charCodeAt());\n            }\n            return false;\n        };\n\n        function doComplete() {\n            if(typeof config.completeHandle == 'function') {\n                var completions = config.completeHandle(promptText);\n                var len = completions.length;\n                if (len === 1) {\n                    extern.promptText(promptText + completions[0]);\n                } else if (len > 1 && config.cols) {\n                    var prompt = promptText;\n                    // Compute the number of rows that will fit in the width\n                    var max = 0;\n                    for (var i = 0;i < len;i++) {\n                        max = Math.max(max, completions[i].length);\n                    }\n                    max += 2;\n                    var n = Math.floor(config.cols / max);\n                    var buffer = \"\";\n                    var col = 0;\n                    for (i = 0;i < len;i++) {\n                        var completion = completions[i];\n                        buffer += completions[i];\n                        for (var j = completion.length;j < max;j++) {\n                            buffer += \" \";\n                        }\n                        if (++col >= n) {\n                            buffer += \"\\n\";\n                            col = 0;\n                        }\n                    }\n                    commandResult(buffer,\"jquery-console-message-value\");\n                    extern.promptText(prompt);\n                }\n            }\n        };\n\n        function doNothing() {};\n\n        extern.promptText = function(text){\n            if (typeof text === 'string') {\n                promptText = text;\n                column = promptText.length;\n                updatePromptDisplay();\n            }\n            return promptText;\n        };\n\n        ////////////////////////////////////////////////////////////////////////\n        // Update the prompt display\n        function updatePromptDisplay(){\n            var line = promptText;\n            var html = '';\n            if (column > 0 && line == ''){\n                // When we have an empty line just display a cursor.\n                html = cursor;\n            } else if (column == promptText.length){\n                // We're at the end of the line, so we need to display\n                // the text *and* cursor.\n                html = htmlEncode(line) + cursor;\n            } else {\n                // Grab the current character, if there is one, and\n                // make it the current cursor.\n                var before = line.substring(0, column);\n                var current = line.substring(column,column+1);\n                if (current){\n                    current =\n                        '<span class=\"jquery-console-cursor\">' +\n                        htmlEncode(current) +\n                        '</span>';\n                }\n                var after = line.substring(column+1);\n                html = htmlEncode(before) + current + htmlEncode(after);\n            }\n            prompt.html(html);\n            scrollToBottom();\n        };\n\n        // Simple HTML encoding\n        // Simply replace '<', '>' and '&'\n        // TODO: Use jQuery's .html() trick, or grab a proper, fast\n        // HTML encoder.\n        function htmlEncode(text){\n            return (\n                text.replace(/&/g,'&amp;')\n                    .replace(/</g,'&lt;')\n                    .replace(/</g,'&lt;')\n                    .replace(/ /g,'&nbsp;')\n                    .replace(/\\n/g,'<br />')\n                );\n        };\n\n        return extern;\n    };\n    // Simple utility for printing messages\n    $.fn.filledText = function(txt){\n        $(this).text(txt);\n        $(this).html($(this).html().replace(/\\n/g,'<br/>'));\n        return this;\n    };\n\n    // Alternative method for focus without scrolling\n    $.fn.focusWithoutScrolling = function(){\n        var x = window.scrollX, y = window.scrollY;\n        $(this).focus();\n        window.scrollTo(x, y);\n    };\n})(jQuery);"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/js/mem-cloud.js",
    "content": "$(document).ready(function () {\n    if (typeof (alert) != 'undefined') {\n        if (alert.isAlert == 0) {\n            return;\n        }\n        $.get(\"/manage/notice/get.json\", {}, function (data) {\n            console.log(data);\n            if (data.status == 1) {\n                var alertDiv = $('<div class=\"alert alert-warning alert-dismissable\"></div>');\n                $('<button type=\"button\" class=\"close\" data-dismiss=\"alert\" aria-hidden=\"true\">&times;</button>').appendTo(alertDiv);\n                $('<p><strong>系统提醒：</strong></p>').appendTo(alertDiv);\n                var i = 0;\n                list = data.data;\n                for (var value in list) {\n                    i++;\n                    $('<p>' + list[value] + '</p>').appendTo(alertDiv);\n                }\n                alertDiv.appendTo($('#systemAlert'));\n            }\n        });\n    }\n\n\n\n\n});"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/js/myPopover.js",
    "content": "$(function () \n { $(\"[data-toggle='popover']\").popover(\n\t{\n\t\ttrigger : 'manual',\n\t\tplacement : 'right',\n\t\thtml : 'true',\n\t\tcontent : \"<div id='popOverBox'>正在加载，请稍候...</div>\",\n\t\tanimation : false\n\t}).on(\n\t\"mouseenter\",\n\tfunction() {\n\t\tvar _this = this;\n\t\t$(this).popover(\"show\");\n\t\t$(this).siblings(\".popover\").on(\"mouseleave\",\n\t\t\t\tfunction() {\n\t\t\t\t\t$(_this).popover('hide');\n\t\t\t\t});\n\t}).on(\"mouseleave\", function() {\n\t\tvar _this = this;\n\t\tsetTimeout(function() {\n\t\t\tif (!$(\".popover:hover\").length) {\n\t\t\t\t$(_this).popover(\"hide\");\n\t\t\t}\n\t\t}, 100);\n\t});\n });"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/js/myhighchart.js",
    "content": "function getClientCostSeriesPoints(dataType, dataArr, tags, unit){\n\tvar length = dataArr.length;\n\tvar finalPoints = [];\n\tfor (var k = 0; k < tags.length; k+=2) {\n\t\tvar tag = tags[k];\n\t\tvar tagName = tags[k+1];\n\t\tvar dataSeries = [];\n\t\tfor (var i = 0; i < length; i++) {\n\t\t\tvar data = dataArr[i];\n\t\t\tvar count = data[tag];\n\t\t\tvar pointName =  tagName + \":\"  + count + unit;\n\t\t\tpointName = pointName + \"<br/>调用量: \" + data.count;\n\t\t\tif (dataType == 1 && tag == \"max100\") {\n\t\t\t\tpointName = pointName \n\t\t\t\t            + \"<br/>实例: \" + data.maxInst\n\t\t\t\t            + \"<br/>客户端: \" + data.maxClient;\n\t\t\t}\n\t\t\tvar dataPoint = {\n\t\t\t\tname : pointName,\n\t\t\t\tx : data.timeStamp,\n\t\t\t\ty : count,\n\t\t\t};\n\t\t\tdataSeries.push(dataPoint);\n\t\t}\n\t\tvar seriesPoints = {\n\t\t\tname : tagName,\n\t\t\tdata : dataSeries,\n\t\t\tmarker : {\n\t\t\t\tradius : 1, // 曲线点半径，默认是4\n\t\t\t}\n\t\t};\n\t\tfinalPoints.push(seriesPoints);\n\t}\n\treturn finalPoints;\n}\n\nfunction pushOptionSeries(options, data, dates, nameLegendPrefix, unit, defaultCount) {\n\tif (typeof(unit) == \"undefined\") { \n\t\tunit = \"次\";\n\t}  \n\tvar dataObject = eval(\"(\" + data.data + \")\");\n\tfor(var t=0;t<dates.length;t++){\n\t\tdate = dates[t];\n\t\tvar dataArr = dataObject[date];\n\t\tvar length = dataArr.length;\n\t\tvar dataSeries = [];\n\t\tvar count;\n\t\tfor (var i = 0; i < length - 1; i++) {\n\t\t\tvar data = dataArr[i];\n\t\t\tcount = data.y;\n\t\t\tif (defaultCount > 0) { \n\t\t\t\tcount = defaultCount;\n\t\t\t}\n\t  \t\tvar pointName = data.date + \":  \" + count + unit;\n\t\t\tvar dataPoint = {\n\t            name : pointName,\n\t\t\t\tx : data.x,\n\t\t\t\ty : count,\n\t\t\t};\n\t\t\tdataSeries.push(dataPoint);\n\t\t}\n\n\t\tvar seriesPoints = {\n\t\t\tname : nameLegendPrefix + \"(\" + date + \")\",\n\t\t\tdata : dataSeries,\n\t\t\tmarker: {\n\t            radius: 1,  //曲线点半径，默认是4\n\t        }\n\t\t};\n\t\toptions.series.push(seriesPoints);\n\t}\n\t\n}\n\nfunction getSeriesPoints(data,nameLegend, unit, defaultCount){\n\tif (typeof(unit) == \"undefined\") { \n\t\tunit = \"次\";\n\t}  \n\tvar dataArr = eval(\"(\" + data + \")\");\n\tvar length = dataArr.length;\n\tvar dataSeries = [];\n\n\tvar count;\n\tfor (var i = 0; i < length - 1; i++) {\n\t\tvar data = dataArr[i];\n\t\tcount = data.y;\n\t\tif (defaultCount > 0) { \n\t\t\tcount = defaultCount;\n\t\t} \n  \t\tvar pointName = data.date + \":  \" + count + unit;\n\t\tvar dataPoint = {\n            name : pointName,\n\t\t\tx : data.x,\n\t\t\ty : count,\n\t\t};\n\t\tdataSeries.push(dataPoint);\n\t}\n\n\tvar seriesPoints = {\n\t\tname : nameLegend,\n\t\tdata : dataSeries,\n\t\tmarker: {\n            radius: 1,  //曲线点半径，默认是4\n        }\n\t};\n\treturn seriesPoints;\n}\n\nfunction getInstanceNetPoints(instanceNetData,nameLegend, command, unit){\n\tvar dataArr = instanceNetData.instanceNetStatMapList;\n\tvar length = dataArr.length;\n\t//i,o,t\n\tvar dataSeries = [];\n\n\tvar unitTxt = \"\";\n\tif (typeof(unit) == \"undefined\") { \n\t\tvar byteCounter = 0;\n\t\tvar kbCounter = 0;\n\t\tvar mbCounter = 0;\n\t\tfor (var i = 0; i < length - 1; i++) {\n\t\t\tvar data = dataArr[i];\n\t\t\tvar count = data[command];\n\t\t\tif (count < 1024){\n\t\t\t\tbyteCounter = byteCounter + 1;\n\t\t\t}else if (count >= 1024 && count < 1024 * 1024) {\n\t\t\t\tkbCounter = kbCounter + 1;\n\t\t\t}else {\n\t\t\t\tmbCounter = mbCounter + 1;\n\t\t\t}\n\t\t}\n\t\tif (byteCounter > kbCounter) {\n\t\t\tif (byteCounter > mbCounter) {\n\t\t\t\tunit = 1;\n\t\t\t\tunitTxt = \"byte\";\n\t\t\t} else {\n\t\t\t\tunit = 1024 * 1024;\n\t\t\t\tunitTxt = \"Mb\";\n\t\t\t}\n\t\t}else {\n\t\t\tif (kbCounter > mbCounter){\n\t\t\t\tunit = 1024;\n\t\t\t\tunitTxt = \"Kb\";\n\t\t\t} else {\n\t\t\t\tunit = 1024 * 1024;\n\t\t\t\tunitTxt = \"Mb\";\n\t\t\t}\n\t\t}\n\t} else {\n\t\tif (unit == 1) {\n\t\t\tunitTxt = \"byte\";\n\t\t}else if (unit == 1024) {\n\t\t\tunitTxt = \"Kb\";\n\t\t}else if (unit == 1024 * 1024){\n\t\t\tunitTxt = \"Mb\";\n\t\t}\n\t}\n\tfor (var i = 0; i < length - 1; i++) {\n\t\tvar data = dataArr[i];\n\t\tvar count = Math.round(data[command] / unit);\n  \t\tvar pointName = count + unitTxt;\n\t\tvar dataPoint = {\n            name : pointName,\n\t\t\tx : data.t,\n\t\t\ty : count,\n\t\t};\n\t\tdataSeries.push(dataPoint);\n\t}\n\n\tvar seriesPoints = {\n\t\tname : nameLegend,\n\t\tdata : dataSeries,\n\t\tunit: unit,\n\t\tunitTxt: unitTxt\n\t};\n\treturn seriesPoints;\n}\n\nfunction getNetPoints(dataArr,nameLegend, unit){\n\tvar length = dataArr.length;\n\tvar dataSeries = [];\n\n\tvar unitTxt = \"\";\n\tif (typeof(unit) == \"undefined\") { \n\t\tvar byteCounter = 0;\n\t\tvar kbCounter = 0;\n\t\tvar mbCounter = 0;\n\t\tfor (var i = 0; i < length - 1; i++) {\n\t\t\tvar data = dataArr[i];\n\t\t\tvar count = data.y;\n\t\t\tif (count < 1024){\n\t\t\t\tbyteCounter = byteCounter + 1;\n\t\t\t}else if (count >= 1024 && count < 1024 * 1024) {\n\t\t\t\tkbCounter = kbCounter + 1;\n\t\t\t}else {\n\t\t\t\tmbCounter = mbCounter + 1;\n\t\t\t}\n\t\t}\n\t\tif (byteCounter > kbCounter) {\n\t\t\tif (byteCounter > mbCounter) {\n\t\t\t\tunit = 1;\n\t\t\t\tunitTxt = \"byte\";\n\t\t\t} else {\n\t\t\t\tunit = 1024 * 1024;\n\t\t\t\tunitTxt = \"Mb\";\n\t\t\t}\n\t\t}else {\n\t\t\tif (kbCounter > mbCounter){\n\t\t\t\tunit = 1024;\n\t\t\t\tunitTxt = \"Kb\";\n\t\t\t} else {\n\t\t\t\tunit = 1024 * 1024;\n\t\t\t\tunitTxt = \"Mb\";\n\t\t\t}\n\t\t}\n\t} else {\n\t\tif (unit == 1) {\n\t\t\tunitTxt = \"byte\";\n\t\t}else if (unit == 1024) {\n\t\t\tunitTxt = \"Kb\";\n\t\t}else if (unit == 1024 * 1024){\n\t\t\tunitTxt = \"Mb\";\n\t\t}\n\t}\n\tfor (var i = 0; i < length - 1; i++) {\n\t\tvar data = dataArr[i];\n\t\tvar count = Math.round(data.y / unit);\n  \t\tvar pointName = data.date + \":  \" + count + unitTxt;\n\t\tvar dataPoint = {\n            name : pointName,\n\t\t\tx : data.x,\n\t\t\ty : count,\n\t\t};\n\t\tdataSeries.push(dataPoint);\n\t}\n\n\tvar seriesPoints = {\n\t\tname : nameLegend,\n\t\tdata : dataSeries,\n\t\tunit: unit,\n\t\tunitTxt: unitTxt\n\t};\n\treturn seriesPoints;\n}\n\n\nfunction getOption(container, title, titleText){\n\tvar chartOption = {\n\t\t\tchart : {\n\t\t\t\trenderTo : container,\n\t\t\t\tanimation : Highcharts.svg,\n\t\t\t\tbackgroundColor : '#E6F1F5',\n\t\t\t\tplotBackgroundColor : '#FFFFFF',\n\t\t\t\tzoomType : 'x',\n\t\t\t\ttype : 'line',\n\t\t\t\tmarginRight : 10\n\t\t\t},\n\t\t\ttitle : {\n\t\t\t\tuseHTML : true,\n\t\t\t\ttext : title\n\t\t\t},\n\t\t\txAxis : {\n\t\t\t\ttype : 'datetime',\n\t\t\t},\n\t\t\tyAxis : {\n\t\t\t\ttitle : {\n\t\t\t\t\ttext : titleText\n\t\t\t\t},\n\t\t\t\tmin:0\n\t\t\t},\n\t\t\tplotOptions: {\n\t            line: {\n\t                dataLabels: {\n\t                    enabled: false\n\t                },\n\t                enableMouseTracking: true\n\t            },\n\t\t\t\tseries: {\n\t\t\t\t\t//默认只能显示1000个点,如果为0就没有这个限制\n\t\t\t\t\tturboThreshold: 0,\n\t                marker: {\n\t                    enabled: false\n\t                }\t\t\t\t\n\t            }\n\t        },\n\t\t\ttooltip : {\n\t\t\t\tformatter: function() {\n                    return '<b>'+ this.point.name +'</b><br/>';\n\t\t\t\t}\n\t\t\t},\n\t\t\tlegend : {\n\t\t\t\tenabled : true\n\t\t\t},\n\t\t\tcredits:{\n            \tenabled: false\n            },\n\t\t\texporting : {\n\t\t\t\tenabled : true\n\t\t\t},\n\t\t\tseries : []\n\t\t};\n\treturn chartOption;\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/js/prettify.css",
    "content": "/* Pretty printing styles. Used with prettify.js. */\n\n/* SPAN elements with the classes below are added by prettyprint. */\n.pln { color: #000 }  /* plain text */\n\n@media screen {\n  .str { color: #080 }  /* string content */\n  .kwd { color: #008 }  /* a keyword */\n  .com { color: #800 }  /* a comment */\n  .typ { color: #606 }  /* a type name */\n  .lit { color: #066 }  /* a literal value */\n  /* punctuation, lisp open bracket, lisp close bracket */\n  .pun, .opn, .clo { color: #660 }\n  .tag { color: #008 }  /* a markup tag name */\n  .atn { color: #606 }  /* a markup attribute name */\n  .atv { color: #080 }  /* a markup attribute value */\n  .dec, .var { color: #606 }  /* a declaration; a variable name */\n  .fun { color: red }  /* a function name */\n}\n\n/* Use higher contrast and text-weight for printable form. */\n@media print, projection {\n  .str { color: #060 }\n  .kwd { color: #006; font-weight: bold }\n  .com { color: #600; font-style: italic }\n  .typ { color: #404; font-weight: bold }\n  .lit { color: #044 }\n  .pun, .opn, .clo { color: #440 }\n  .tag { color: #006; font-weight: bold }\n  .atn { color: #404 }\n  .atv { color: #060 }\n}\n\n/* Put a border around prettyprinted code snippets. */\npre.prettyprint { padding: 2px; border: 1px solid #888 }\n\n/* Specify class=linenums on a pre to get line numbering */\nol.linenums { margin-top: 0; margin-bottom: 0 } /* IE indents via margin-left */\nli.L0,\nli.L1,\nli.L2,\nli.L3,\nli.L5,\nli.L6,\nli.L7,\nli.L8 { list-style-type: none }\n/* Alternate shading for lines */\nli.L1,\nli.L3,\nli.L5,\nli.L7,\nli.L9 { background: #eee }\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/js/prettify.js",
    "content": "// Copyright (C) 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/**\n * @fileoverview\n * some functions for browser-side pretty printing of code contained in html.\n *\n * <p>\n * For a fairly comprehensive set of languages see the\n * <a href=\"http://google-code-prettify.googlecode.com/svn/trunk/README.html#langs\">README</a>\n * file that came with this source.  At a minimum, the lexer should work on a\n * number of languages including C and friends, Java, Python, Bash, SQL, HTML,\n * XML, CSS, Javascript, and Makefiles.  It works passably on Ruby, PHP and Awk\n * and a subset of Perl, but, because of commenting conventions, doesn't work on\n * Smalltalk, Lisp-like, or CAML-like languages without an explicit lang class.\n * <p>\n * Usage: <ol>\n * <li> include this source file in an html page via\n *   {@code <script type=\"text/javascript\" src=\"/path/to/prettify.js\"></script>}\n * <li> define style rules.  See the example page for examples.\n * <li> mark the {@code <pre>} and {@code <code>} tags in your source with\n *    {@code class=prettyprint.}\n *    You can also use the (html deprecated) {@code <xmp>} tag, but the pretty\n *    printer needs to do more substantial DOM manipulations to support that, so\n *    some css styles may not be preserved.\n * </ol>\n * That's it.  I wanted to keep the API as simple as possible, so there's no\n * need to specify which language the code is in, but if you wish, you can add\n * another class to the {@code <pre>} or {@code <code>} element to specify the\n * language, as in {@code <pre class=\"prettyprint lang-java\">}.  Any class that\n * starts with \"lang-\" followed by a file extension, specifies the file type.\n * See the \"lang-*.js\" files in this directory for code that implements\n * per-language file handlers.\n * <p>\n * Change log:<br>\n * cbeust, 2006/08/22\n * <blockquote>\n *   Java annotations (start with \"@\") are now captured as literals (\"lit\")\n * </blockquote>\n * @requires console\n */\n\n// JSLint declarations\n/*global console, document, navigator, setTimeout, window, define */\n\n/** @define {boolean} */\nvar IN_GLOBAL_SCOPE = true;\n\n/**\n * Split {@code prettyPrint} into multiple timeouts so as not to interfere with\n * UI events.\n * If set to {@code false}, {@code prettyPrint()} is synchronous.\n */\nwindow['PR_SHOULD_USE_CONTINUATION'] = true;\n\n/**\n * Pretty print a chunk of code.\n * @param {string} sourceCodeHtml The HTML to pretty print.\n * @param {string} opt_langExtension The language name to use.\n *     Typically, a filename extension like 'cpp' or 'java'.\n * @param {number|boolean} opt_numberLines True to number lines,\n *     or the 1-indexed number of the first line in sourceCodeHtml.\n * @return {string} code as html, but prettier\n */\nvar prettyPrintOne;\n/**\n * Find all the {@code <pre>} and {@code <code>} tags in the DOM with\n * {@code class=prettyprint} and prettify them.\n *\n * @param {Function} opt_whenDone called when prettifying is done.\n * @param {HTMLElement|HTMLDocument} opt_root an element or document\n *   containing all the elements to pretty print.\n *   Defaults to {@code document.body}.\n */\nvar prettyPrint;\n\n\n(function () {\n  var win = window;\n  // Keyword lists for various languages.\n  // We use things that coerce to strings to make them compact when minified\n  // and to defeat aggressive optimizers that fold large string constants.\n  var FLOW_CONTROL_KEYWORDS = [\"break,continue,do,else,for,if,return,while\"];\n  var C_KEYWORDS = [FLOW_CONTROL_KEYWORDS,\"auto,case,char,const,default,\" + \n      \"double,enum,extern,float,goto,inline,int,long,register,short,signed,\" +\n      \"sizeof,static,struct,switch,typedef,union,unsigned,void,volatile\"];\n  var COMMON_KEYWORDS = [C_KEYWORDS,\"catch,class,delete,false,import,\" +\n      \"new,operator,private,protected,public,this,throw,true,try,typeof\"];\n  var CPP_KEYWORDS = [COMMON_KEYWORDS,\"alignof,align_union,asm,axiom,bool,\" +\n      \"concept,concept_map,const_cast,constexpr,decltype,delegate,\" +\n      \"dynamic_cast,explicit,export,friend,generic,late_check,\" +\n      \"mutable,namespace,nullptr,property,reinterpret_cast,static_assert,\" +\n      \"static_cast,template,typeid,typename,using,virtual,where\"];\n  var JAVA_KEYWORDS = [COMMON_KEYWORDS,\n      \"abstract,assert,boolean,byte,extends,final,finally,implements,import,\" +\n      \"instanceof,interface,null,native,package,strictfp,super,synchronized,\" +\n      \"throws,transient\"];\n  var CSHARP_KEYWORDS = [JAVA_KEYWORDS,\n      \"as,base,by,checked,decimal,delegate,descending,dynamic,event,\" +\n      \"fixed,foreach,from,group,implicit,in,internal,into,is,let,\" +\n      \"lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,\" +\n      \"sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,\" +\n      \"var,virtual,where\"];\n  var COFFEE_KEYWORDS = \"all,and,by,catch,class,else,extends,false,finally,\" +\n      \"for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,\" +\n      \"throw,true,try,unless,until,when,while,yes\";\n  var JSCRIPT_KEYWORDS = [COMMON_KEYWORDS,\n      \"debugger,eval,export,function,get,null,set,undefined,var,with,\" +\n      \"Infinity,NaN\"];\n  var PERL_KEYWORDS = \"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,\" +\n      \"goto,if,import,last,local,my,next,no,our,print,package,redo,require,\" +\n      \"sub,undef,unless,until,use,wantarray,while,BEGIN,END\";\n  var PYTHON_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"and,as,assert,class,def,del,\" +\n      \"elif,except,exec,finally,from,global,import,in,is,lambda,\" +\n      \"nonlocal,not,or,pass,print,raise,try,with,yield,\" +\n      \"False,True,None\"];\n  var RUBY_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"alias,and,begin,case,class,\" +\n      \"def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,\" +\n      \"rescue,retry,self,super,then,true,undef,unless,until,when,yield,\" +\n      \"BEGIN,END\"];\n   var RUST_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"as,assert,const,copy,drop,\" +\n      \"enum,extern,fail,false,fn,impl,let,log,loop,match,mod,move,mut,priv,\" +\n      \"pub,pure,ref,self,static,struct,true,trait,type,unsafe,use\"];\n  var SH_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"case,done,elif,esac,eval,fi,\" +\n      \"function,in,local,set,then,until\"];\n  var ALL_KEYWORDS = [\n      CPP_KEYWORDS, CSHARP_KEYWORDS, JSCRIPT_KEYWORDS, PERL_KEYWORDS,\n      PYTHON_KEYWORDS, RUBY_KEYWORDS, SH_KEYWORDS];\n  var C_TYPES = /^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\\d*)\\b/;\n\n  // token style names.  correspond to css classes\n  /**\n   * token style for a string literal\n   * @const\n   */\n  var PR_STRING = 'str';\n  /**\n   * token style for a keyword\n   * @const\n   */\n  var PR_KEYWORD = 'kwd';\n  /**\n   * token style for a comment\n   * @const\n   */\n  var PR_COMMENT = 'com';\n  /**\n   * token style for a type\n   * @const\n   */\n  var PR_TYPE = 'typ';\n  /**\n   * token style for a literal value.  e.g. 1, null, true.\n   * @const\n   */\n  var PR_LITERAL = 'lit';\n  /**\n   * token style for a punctuation string.\n   * @const\n   */\n  var PR_PUNCTUATION = 'pun';\n  /**\n   * token style for plain text.\n   * @const\n   */\n  var PR_PLAIN = 'pln';\n\n  /**\n   * token style for an sgml tag.\n   * @const\n   */\n  var PR_TAG = 'tag';\n  /**\n   * token style for a markup declaration such as a DOCTYPE.\n   * @const\n   */\n  var PR_DECLARATION = 'dec';\n  /**\n   * token style for embedded source.\n   * @const\n   */\n  var PR_SOURCE = 'src';\n  /**\n   * token style for an sgml attribute name.\n   * @const\n   */\n  var PR_ATTRIB_NAME = 'atn';\n  /**\n   * token style for an sgml attribute value.\n   * @const\n   */\n  var PR_ATTRIB_VALUE = 'atv';\n\n  /**\n   * A class that indicates a section of markup that is not code, e.g. to allow\n   * embedding of line numbers within code listings.\n   * @const\n   */\n  var PR_NOCODE = 'nocode';\n\n  \n  \n  /**\n   * A set of tokens that can precede a regular expression literal in\n   * javascript\n   * http://web.archive.org/web/20070717142515/http://www.mozilla.org/js/language/js20/rationale/syntax.html\n   * has the full list, but I've removed ones that might be problematic when\n   * seen in languages that don't support regular expression literals.\n   *\n   * <p>Specifically, I've removed any keywords that can't precede a regexp\n   * literal in a syntactically legal javascript program, and I've removed the\n   * \"in\" keyword since it's not a keyword in many languages, and might be used\n   * as a count of inches.\n   *\n   * <p>The link above does not accurately describe EcmaScript rules since\n   * it fails to distinguish between (a=++/b/i) and (a++/b/i) but it works\n   * very well in practice.\n   *\n   * @private\n   * @const\n   */\n  var REGEXP_PRECEDER_PATTERN = '(?:^^\\\\.?|[+-]|[!=]=?=?|\\\\#|%=?|&&?=?|\\\\(|\\\\*=?|[+\\\\-]=|->|\\\\/=?|::?|<<?=?|>>?>?=?|,|;|\\\\?|@|\\\\[|~|{|\\\\^\\\\^?=?|\\\\|\\\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\\\s*';\n  \n  // CAVEAT: this does not properly handle the case where a regular\n  // expression immediately follows another since a regular expression may\n  // have flags for case-sensitivity and the like.  Having regexp tokens\n  // adjacent is not valid in any language I'm aware of, so I'm punting.\n  // TODO: maybe style special characters inside a regexp as punctuation.\n\n  /**\n   * Given a group of {@link RegExp}s, returns a {@code RegExp} that globally\n   * matches the union of the sets of strings matched by the input RegExp.\n   * Since it matches globally, if the input strings have a start-of-input\n   * anchor (/^.../), it is ignored for the purposes of unioning.\n   * @param {Array.<RegExp>} regexs non multiline, non-global regexs.\n   * @return {RegExp} a global regex.\n   */\n  function combinePrefixPatterns(regexs) {\n    var capturedGroupIndex = 0;\n  \n    var needToFoldCase = false;\n    var ignoreCase = false;\n    for (var i = 0, n = regexs.length; i < n; ++i) {\n      var regex = regexs[i];\n      if (regex.ignoreCase) {\n        ignoreCase = true;\n      } else if (/[a-z]/i.test(regex.source.replace(\n                     /\\\\u[0-9a-f]{4}|\\\\x[0-9a-f]{2}|\\\\[^ux]/gi, ''))) {\n        needToFoldCase = true;\n        ignoreCase = false;\n        break;\n      }\n    }\n  \n    var escapeCharToCodeUnit = {\n      'b': 8,\n      't': 9,\n      'n': 0xa,\n      'v': 0xb,\n      'f': 0xc,\n      'r': 0xd\n    };\n  \n    function decodeEscape(charsetPart) {\n      var cc0 = charsetPart.charCodeAt(0);\n      if (cc0 !== 92 /* \\\\ */) {\n        return cc0;\n      }\n      var c1 = charsetPart.charAt(1);\n      cc0 = escapeCharToCodeUnit[c1];\n      if (cc0) {\n        return cc0;\n      } else if ('0' <= c1 && c1 <= '7') {\n        return parseInt(charsetPart.substring(1), 8);\n      } else if (c1 === 'u' || c1 === 'x') {\n        return parseInt(charsetPart.substring(2), 16);\n      } else {\n        return charsetPart.charCodeAt(1);\n      }\n    }\n  \n    function encodeEscape(charCode) {\n      if (charCode < 0x20) {\n        return (charCode < 0x10 ? '\\\\x0' : '\\\\x') + charCode.toString(16);\n      }\n      var ch = String.fromCharCode(charCode);\n      return (ch === '\\\\' || ch === '-' || ch === ']' || ch === '^')\n          ? \"\\\\\" + ch : ch;\n    }\n  \n    function caseFoldCharset(charSet) {\n      var charsetParts = charSet.substring(1, charSet.length - 1).match(\n          new RegExp(\n              '\\\\\\\\u[0-9A-Fa-f]{4}'\n              + '|\\\\\\\\x[0-9A-Fa-f]{2}'\n              + '|\\\\\\\\[0-3][0-7]{0,2}'\n              + '|\\\\\\\\[0-7]{1,2}'\n              + '|\\\\\\\\[\\\\s\\\\S]'\n              + '|-'\n              + '|[^-\\\\\\\\]',\n              'g'));\n      var ranges = [];\n      var inverse = charsetParts[0] === '^';\n  \n      var out = ['['];\n      if (inverse) { out.push('^'); }\n  \n      for (var i = inverse ? 1 : 0, n = charsetParts.length; i < n; ++i) {\n        var p = charsetParts[i];\n        if (/\\\\[bdsw]/i.test(p)) {  // Don't muck with named groups.\n          out.push(p);\n        } else {\n          var start = decodeEscape(p);\n          var end;\n          if (i + 2 < n && '-' === charsetParts[i + 1]) {\n            end = decodeEscape(charsetParts[i + 2]);\n            i += 2;\n          } else {\n            end = start;\n          }\n          ranges.push([start, end]);\n          // If the range might intersect letters, then expand it.\n          // This case handling is too simplistic.\n          // It does not deal with non-latin case folding.\n          // It works for latin source code identifiers though.\n          if (!(end < 65 || start > 122)) {\n            if (!(end < 65 || start > 90)) {\n              ranges.push([Math.max(65, start) | 32, Math.min(end, 90) | 32]);\n            }\n            if (!(end < 97 || start > 122)) {\n              ranges.push([Math.max(97, start) & ~32, Math.min(end, 122) & ~32]);\n            }\n          }\n        }\n      }\n  \n      // [[1, 10], [3, 4], [8, 12], [14, 14], [16, 16], [17, 17]]\n      // -> [[1, 12], [14, 14], [16, 17]]\n      ranges.sort(function (a, b) { return (a[0] - b[0]) || (b[1]  - a[1]); });\n      var consolidatedRanges = [];\n      var lastRange = [];\n      for (var i = 0; i < ranges.length; ++i) {\n        var range = ranges[i];\n        if (range[0] <= lastRange[1] + 1) {\n          lastRange[1] = Math.max(lastRange[1], range[1]);\n        } else {\n          consolidatedRanges.push(lastRange = range);\n        }\n      }\n  \n      for (var i = 0; i < consolidatedRanges.length; ++i) {\n        var range = consolidatedRanges[i];\n        out.push(encodeEscape(range[0]));\n        if (range[1] > range[0]) {\n          if (range[1] + 1 > range[0]) { out.push('-'); }\n          out.push(encodeEscape(range[1]));\n        }\n      }\n      out.push(']');\n      return out.join('');\n    }\n  \n    function allowAnywhereFoldCaseAndRenumberGroups(regex) {\n      // Split into character sets, escape sequences, punctuation strings\n      // like ('(', '(?:', ')', '^'), and runs of characters that do not\n      // include any of the above.\n      var parts = regex.source.match(\n          new RegExp(\n              '(?:'\n              + '\\\\[(?:[^\\\\x5C\\\\x5D]|\\\\\\\\[\\\\s\\\\S])*\\\\]'  // a character set\n              + '|\\\\\\\\u[A-Fa-f0-9]{4}'  // a unicode escape\n              + '|\\\\\\\\x[A-Fa-f0-9]{2}'  // a hex escape\n              + '|\\\\\\\\[0-9]+'  // a back-reference or octal escape\n              + '|\\\\\\\\[^ux0-9]'  // other escape sequence\n              + '|\\\\(\\\\?[:!=]'  // start of a non-capturing group\n              + '|[\\\\(\\\\)\\\\^]'  // start/end of a group, or line start\n              + '|[^\\\\x5B\\\\x5C\\\\(\\\\)\\\\^]+'  // run of other characters\n              + ')',\n              'g'));\n      var n = parts.length;\n  \n      // Maps captured group numbers to the number they will occupy in\n      // the output or to -1 if that has not been determined, or to\n      // undefined if they need not be capturing in the output.\n      var capturedGroups = [];\n  \n      // Walk over and identify back references to build the capturedGroups\n      // mapping.\n      for (var i = 0, groupIndex = 0; i < n; ++i) {\n        var p = parts[i];\n        if (p === '(') {\n          // groups are 1-indexed, so max group index is count of '('\n          ++groupIndex;\n        } else if ('\\\\' === p.charAt(0)) {\n          var decimalValue = +p.substring(1);\n          if (decimalValue) {\n            if (decimalValue <= groupIndex) {\n              capturedGroups[decimalValue] = -1;\n            } else {\n              // Replace with an unambiguous escape sequence so that\n              // an octal escape sequence does not turn into a backreference\n              // to a capturing group from an earlier regex.\n              parts[i] = encodeEscape(decimalValue);\n            }\n          }\n        }\n      }\n  \n      // Renumber groups and reduce capturing groups to non-capturing groups\n      // where possible.\n      for (var i = 1; i < capturedGroups.length; ++i) {\n        if (-1 === capturedGroups[i]) {\n          capturedGroups[i] = ++capturedGroupIndex;\n        }\n      }\n      for (var i = 0, groupIndex = 0; i < n; ++i) {\n        var p = parts[i];\n        if (p === '(') {\n          ++groupIndex;\n          if (!capturedGroups[groupIndex]) {\n            parts[i] = '(?:';\n          }\n        } else if ('\\\\' === p.charAt(0)) {\n          var decimalValue = +p.substring(1);\n          if (decimalValue && decimalValue <= groupIndex) {\n            parts[i] = '\\\\' + capturedGroups[decimalValue];\n          }\n        }\n      }\n  \n      // Remove any prefix anchors so that the output will match anywhere.\n      // ^^ really does mean an anchored match though.\n      for (var i = 0; i < n; ++i) {\n        if ('^' === parts[i] && '^' !== parts[i + 1]) { parts[i] = ''; }\n      }\n  \n      // Expand letters to groups to handle mixing of case-sensitive and\n      // case-insensitive patterns if necessary.\n      if (regex.ignoreCase && needToFoldCase) {\n        for (var i = 0; i < n; ++i) {\n          var p = parts[i];\n          var ch0 = p.charAt(0);\n          if (p.length >= 2 && ch0 === '[') {\n            parts[i] = caseFoldCharset(p);\n          } else if (ch0 !== '\\\\') {\n            // TODO: handle letters in numeric escapes.\n            parts[i] = p.replace(\n                /[a-zA-Z]/g,\n                function (ch) {\n                  var cc = ch.charCodeAt(0);\n                  return '[' + String.fromCharCode(cc & ~32, cc | 32) + ']';\n                });\n          }\n        }\n      }\n  \n      return parts.join('');\n    }\n  \n    var rewritten = [];\n    for (var i = 0, n = regexs.length; i < n; ++i) {\n      var regex = regexs[i];\n      if (regex.global || regex.multiline) { throw new Error('' + regex); }\n      rewritten.push(\n          '(?:' + allowAnywhereFoldCaseAndRenumberGroups(regex) + ')');\n    }\n  \n    return new RegExp(rewritten.join('|'), ignoreCase ? 'gi' : 'g');\n  }\n\n  /**\n   * Split markup into a string of source code and an array mapping ranges in\n   * that string to the text nodes in which they appear.\n   *\n   * <p>\n   * The HTML DOM structure:</p>\n   * <pre>\n   * (Element   \"p\"\n   *   (Element \"b\"\n   *     (Text  \"print \"))       ; #1\n   *   (Text    \"'Hello '\")      ; #2\n   *   (Element \"br\")            ; #3\n   *   (Text    \"  + 'World';\")) ; #4\n   * </pre>\n   * <p>\n   * corresponds to the HTML\n   * {@code <p><b>print </b>'Hello '<br>  + 'World';</p>}.</p>\n   *\n   * <p>\n   * It will produce the output:</p>\n   * <pre>\n   * {\n   *   sourceCode: \"print 'Hello '\\n  + 'World';\",\n   *   //                     1          2\n   *   //           012345678901234 5678901234567\n   *   spans: [0, #1, 6, #2, 14, #3, 15, #4]\n   * }\n   * </pre>\n   * <p>\n   * where #1 is a reference to the {@code \"print \"} text node above, and so\n   * on for the other text nodes.\n   * </p>\n   *\n   * <p>\n   * The {@code} spans array is an array of pairs.  Even elements are the start\n   * indices of substrings, and odd elements are the text nodes (or BR elements)\n   * that contain the text for those substrings.\n   * Substrings continue until the next index or the end of the source.\n   * </p>\n   *\n   * @param {Node} node an HTML DOM subtree containing source-code.\n   * @param {boolean} isPreformatted true if white-space in text nodes should\n   *    be considered significant.\n   * @return {Object} source code and the text nodes in which they occur.\n   */\n  function extractSourceSpans(node, isPreformatted) {\n    var nocode = /(?:^|\\s)nocode(?:\\s|$)/;\n  \n    var chunks = [];\n    var length = 0;\n    var spans = [];\n    var k = 0;\n  \n    function walk(node) {\n      var type = node.nodeType;\n      if (type == 1) {  // Element\n        if (nocode.test(node.className)) { return; }\n        for (var child = node.firstChild; child; child = child.nextSibling) {\n          walk(child);\n        }\n        var nodeName = node.nodeName.toLowerCase();\n        if ('br' === nodeName || 'li' === nodeName) {\n          chunks[k] = '\\n';\n          spans[k << 1] = length++;\n          spans[(k++ << 1) | 1] = node;\n        }\n      } else if (type == 3 || type == 4) {  // Text\n        var text = node.nodeValue;\n        if (text.length) {\n          if (!isPreformatted) {\n            text = text.replace(/[ \\t\\r\\n]+/g, ' ');\n          } else {\n            text = text.replace(/\\r\\n?/g, '\\n');  // Normalize newlines.\n          }\n          // TODO: handle tabs here?\n          chunks[k] = text;\n          spans[k << 1] = length;\n          length += text.length;\n          spans[(k++ << 1) | 1] = node;\n        }\n      }\n    }\n  \n    walk(node);\n  \n    return {\n      sourceCode: chunks.join('').replace(/\\n$/, ''),\n      spans: spans\n    };\n  }\n\n  /**\n   * Apply the given language handler to sourceCode and add the resulting\n   * decorations to out.\n   * @param {number} basePos the index of sourceCode within the chunk of source\n   *    whose decorations are already present on out.\n   */\n  function appendDecorations(basePos, sourceCode, langHandler, out) {\n    if (!sourceCode) { return; }\n    var job = {\n      sourceCode: sourceCode,\n      basePos: basePos\n    };\n    langHandler(job);\n    out.push.apply(out, job.decorations);\n  }\n\n  var notWs = /\\S/;\n\n  /**\n   * Given an element, if it contains only one child element and any text nodes\n   * it contains contain only space characters, return the sole child element.\n   * Otherwise returns undefined.\n   * <p>\n   * This is meant to return the CODE element in {@code <pre><code ...>} when\n   * there is a single child element that contains all the non-space textual\n   * content, but not to return anything where there are multiple child elements\n   * as in {@code <pre><code>...</code><code>...</code></pre>} or when there\n   * is textual content.\n   */\n  function childContentWrapper(element) {\n    var wrapper = undefined;\n    for (var c = element.firstChild; c; c = c.nextSibling) {\n      var type = c.nodeType;\n      wrapper = (type === 1)  // Element Node\n          ? (wrapper ? element : c)\n          : (type === 3)  // Text Node\n          ? (notWs.test(c.nodeValue) ? element : wrapper)\n          : wrapper;\n    }\n    return wrapper === element ? undefined : wrapper;\n  }\n\n  /** Given triples of [style, pattern, context] returns a lexing function,\n    * The lexing function interprets the patterns to find token boundaries and\n    * returns a decoration list of the form\n    * [index_0, style_0, index_1, style_1, ..., index_n, style_n]\n    * where index_n is an index into the sourceCode, and style_n is a style\n    * constant like PR_PLAIN.  index_n-1 <= index_n, and style_n-1 applies to\n    * all characters in sourceCode[index_n-1:index_n].\n    *\n    * The stylePatterns is a list whose elements have the form\n    * [style : string, pattern : RegExp, DEPRECATED, shortcut : string].\n    *\n    * Style is a style constant like PR_PLAIN, or can be a string of the\n    * form 'lang-FOO', where FOO is a language extension describing the\n    * language of the portion of the token in $1 after pattern executes.\n    * E.g., if style is 'lang-lisp', and group 1 contains the text\n    * '(hello (world))', then that portion of the token will be passed to the\n    * registered lisp handler for formatting.\n    * The text before and after group 1 will be restyled using this decorator\n    * so decorators should take care that this doesn't result in infinite\n    * recursion.  For example, the HTML lexer rule for SCRIPT elements looks\n    * something like ['lang-js', /<[s]cript>(.+?)<\\/script>/].  This may match\n    * '<script>foo()<\\/script>', which would cause the current decorator to\n    * be called with '<script>' which would not match the same rule since\n    * group 1 must not be empty, so it would be instead styled as PR_TAG by\n    * the generic tag rule.  The handler registered for the 'js' extension would\n    * then be called with 'foo()', and finally, the current decorator would\n    * be called with '<\\/script>' which would not match the original rule and\n    * so the generic tag rule would identify it as a tag.\n    *\n    * Pattern must only match prefixes, and if it matches a prefix, then that\n    * match is considered a token with the same style.\n    *\n    * Context is applied to the last non-whitespace, non-comment token\n    * recognized.\n    *\n    * Shortcut is an optional string of characters, any of which, if the first\n    * character, gurantee that this pattern and only this pattern matches.\n    *\n    * @param {Array} shortcutStylePatterns patterns that always start with\n    *   a known character.  Must have a shortcut string.\n    * @param {Array} fallthroughStylePatterns patterns that will be tried in\n    *   order if the shortcut ones fail.  May have shortcuts.\n    *\n    * @return {function (Object)} a\n    *   function that takes source code and returns a list of decorations.\n    */\n  function createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns) {\n    var shortcuts = {};\n    var tokenizer;\n    (function () {\n      var allPatterns = shortcutStylePatterns.concat(fallthroughStylePatterns);\n      var allRegexs = [];\n      var regexKeys = {};\n      for (var i = 0, n = allPatterns.length; i < n; ++i) {\n        var patternParts = allPatterns[i];\n        var shortcutChars = patternParts[3];\n        if (shortcutChars) {\n          for (var c = shortcutChars.length; --c >= 0;) {\n            shortcuts[shortcutChars.charAt(c)] = patternParts;\n          }\n        }\n        var regex = patternParts[1];\n        var k = '' + regex;\n        if (!regexKeys.hasOwnProperty(k)) {\n          allRegexs.push(regex);\n          regexKeys[k] = null;\n        }\n      }\n      allRegexs.push(/[\\0-\\uffff]/);\n      tokenizer = combinePrefixPatterns(allRegexs);\n    })();\n\n    var nPatterns = fallthroughStylePatterns.length;\n\n    /**\n     * Lexes job.sourceCode and produces an output array job.decorations of\n     * style classes preceded by the position at which they start in\n     * job.sourceCode in order.\n     *\n     * @param {Object} job an object like <pre>{\n     *    sourceCode: {string} sourceText plain text,\n     *    basePos: {int} position of job.sourceCode in the larger chunk of\n     *        sourceCode.\n     * }</pre>\n     */\n    var decorate = function (job) {\n      var sourceCode = job.sourceCode, basePos = job.basePos;\n      /** Even entries are positions in source in ascending order.  Odd enties\n        * are style markers (e.g., PR_COMMENT) that run from that position until\n        * the end.\n        * @type {Array.<number|string>}\n        */\n      var decorations = [basePos, PR_PLAIN];\n      var pos = 0;  // index into sourceCode\n      var tokens = sourceCode.match(tokenizer) || [];\n      var styleCache = {};\n\n      for (var ti = 0, nTokens = tokens.length; ti < nTokens; ++ti) {\n        var token = tokens[ti];\n        var style = styleCache[token];\n        var match = void 0;\n\n        var isEmbedded;\n        if (typeof style === 'string') {\n          isEmbedded = false;\n        } else {\n          var patternParts = shortcuts[token.charAt(0)];\n          if (patternParts) {\n            match = token.match(patternParts[1]);\n            style = patternParts[0];\n          } else {\n            for (var i = 0; i < nPatterns; ++i) {\n              patternParts = fallthroughStylePatterns[i];\n              match = token.match(patternParts[1]);\n              if (match) {\n                style = patternParts[0];\n                break;\n              }\n            }\n\n            if (!match) {  // make sure that we make progress\n              style = PR_PLAIN;\n            }\n          }\n\n          isEmbedded = style.length >= 5 && 'lang-' === style.substring(0, 5);\n          if (isEmbedded && !(match && typeof match[1] === 'string')) {\n            isEmbedded = false;\n            style = PR_SOURCE;\n          }\n\n          if (!isEmbedded) { styleCache[token] = style; }\n        }\n\n        var tokenStart = pos;\n        pos += token.length;\n\n        if (!isEmbedded) {\n          decorations.push(basePos + tokenStart, style);\n        } else {  // Treat group 1 as an embedded block of source code.\n          var embeddedSource = match[1];\n          var embeddedSourceStart = token.indexOf(embeddedSource);\n          var embeddedSourceEnd = embeddedSourceStart + embeddedSource.length;\n          if (match[2]) {\n            // If embeddedSource can be blank, then it would match at the\n            // beginning which would cause us to infinitely recurse on the\n            // entire token, so we catch the right context in match[2].\n            embeddedSourceEnd = token.length - match[2].length;\n            embeddedSourceStart = embeddedSourceEnd - embeddedSource.length;\n          }\n          var lang = style.substring(5);\n          // Decorate the left of the embedded source\n          appendDecorations(\n              basePos + tokenStart,\n              token.substring(0, embeddedSourceStart),\n              decorate, decorations);\n          // Decorate the embedded source\n          appendDecorations(\n              basePos + tokenStart + embeddedSourceStart,\n              embeddedSource,\n              langHandlerForExtension(lang, embeddedSource),\n              decorations);\n          // Decorate the right of the embedded section\n          appendDecorations(\n              basePos + tokenStart + embeddedSourceEnd,\n              token.substring(embeddedSourceEnd),\n              decorate, decorations);\n        }\n      }\n      job.decorations = decorations;\n    };\n    return decorate;\n  }\n\n  /** returns a function that produces a list of decorations from source text.\n    *\n    * This code treats \", ', and ` as string delimiters, and \\ as a string\n    * escape.  It does not recognize perl's qq() style strings.\n    * It has no special handling for double delimiter escapes as in basic, or\n    * the tripled delimiters used in python, but should work on those regardless\n    * although in those cases a single string literal may be broken up into\n    * multiple adjacent string literals.\n    *\n    * It recognizes C, C++, and shell style comments.\n    *\n    * @param {Object} options a set of optional parameters.\n    * @return {function (Object)} a function that examines the source code\n    *     in the input job and builds the decoration list.\n    */\n  function sourceDecorator(options) {\n    var shortcutStylePatterns = [], fallthroughStylePatterns = [];\n    if (options['tripleQuotedStrings']) {\n      // '''multi-line-string''', 'single-line-string', and double-quoted\n      shortcutStylePatterns.push(\n          [PR_STRING,  /^(?:\\'\\'\\'(?:[^\\'\\\\]|\\\\[\\s\\S]|\\'{1,2}(?=[^\\']))*(?:\\'\\'\\'|$)|\\\"\\\"\\\"(?:[^\\\"\\\\]|\\\\[\\s\\S]|\\\"{1,2}(?=[^\\\"]))*(?:\\\"\\\"\\\"|$)|\\'(?:[^\\\\\\']|\\\\[\\s\\S])*(?:\\'|$)|\\\"(?:[^\\\\\\\"]|\\\\[\\s\\S])*(?:\\\"|$))/,\n           null, '\\'\"']);\n    } else if (options['multiLineStrings']) {\n      // 'multi-line-string', \"multi-line-string\"\n      shortcutStylePatterns.push(\n          [PR_STRING,  /^(?:\\'(?:[^\\\\\\']|\\\\[\\s\\S])*(?:\\'|$)|\\\"(?:[^\\\\\\\"]|\\\\[\\s\\S])*(?:\\\"|$)|\\`(?:[^\\\\\\`]|\\\\[\\s\\S])*(?:\\`|$))/,\n           null, '\\'\"`']);\n    } else {\n      // 'single-line-string', \"single-line-string\"\n      shortcutStylePatterns.push(\n          [PR_STRING,\n           /^(?:\\'(?:[^\\\\\\'\\r\\n]|\\\\.)*(?:\\'|$)|\\\"(?:[^\\\\\\\"\\r\\n]|\\\\.)*(?:\\\"|$))/,\n           null, '\"\\'']);\n    }\n    if (options['verbatimStrings']) {\n      // verbatim-string-literal production from the C# grammar.  See issue 93.\n      fallthroughStylePatterns.push(\n          [PR_STRING, /^@\\\"(?:[^\\\"]|\\\"\\\")*(?:\\\"|$)/, null]);\n    }\n    var hc = options['hashComments'];\n    if (hc) {\n      if (options['cStyleComments']) {\n        if (hc > 1) {  // multiline hash comments\n          shortcutStylePatterns.push(\n              [PR_COMMENT, /^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/, null, '#']);\n        } else {\n          // Stop C preprocessor declarations at an unclosed open comment\n          shortcutStylePatterns.push(\n              [PR_COMMENT, /^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\\b|[^\\r\\n]*)/,\n               null, '#']);\n        }\n        // #include <stdio.h>\n        fallthroughStylePatterns.push(\n            [PR_STRING,\n             /^<(?:(?:(?:\\.\\.\\/)*|\\/?)(?:[\\w-]+(?:\\/[\\w-]+)+)?[\\w-]+\\.h(?:h|pp|\\+\\+)?|[a-z]\\w*)>/,\n             null]);\n      } else {\n        shortcutStylePatterns.push([PR_COMMENT, /^#[^\\r\\n]*/, null, '#']);\n      }\n    }\n    if (options['cStyleComments']) {\n      fallthroughStylePatterns.push([PR_COMMENT, /^\\/\\/[^\\r\\n]*/, null]);\n      fallthroughStylePatterns.push(\n          [PR_COMMENT, /^\\/\\*[\\s\\S]*?(?:\\*\\/|$)/, null]);\n    }\n    var regexLiterals = options['regexLiterals'];\n    if (regexLiterals) {\n      /**\n       * @const\n       */\n      var regexExcls = regexLiterals > 1\n        ? ''  // Multiline regex literals\n        : '\\n\\r';\n      /**\n       * @const\n       */\n      var regexAny = regexExcls ? '.' : '[\\\\S\\\\s]';\n      /**\n       * @const\n       */\n      var REGEX_LITERAL = (\n          // A regular expression literal starts with a slash that is\n          // not followed by * or / so that it is not confused with\n          // comments.\n          '/(?=[^/*' + regexExcls + '])'\n          // and then contains any number of raw characters,\n          + '(?:[^/\\\\x5B\\\\x5C' + regexExcls + ']'\n          // escape sequences (\\x5C),\n          +    '|\\\\x5C' + regexAny\n          // or non-nesting character sets (\\x5B\\x5D);\n          +    '|\\\\x5B(?:[^\\\\x5C\\\\x5D' + regexExcls + ']'\n          +             '|\\\\x5C' + regexAny + ')*(?:\\\\x5D|$))+'\n          // finally closed by a /.\n          + '/');\n      fallthroughStylePatterns.push(\n          ['lang-regex',\n           RegExp('^' + REGEXP_PRECEDER_PATTERN + '(' + REGEX_LITERAL + ')')\n           ]);\n    }\n\n    var types = options['types'];\n    if (types) {\n      fallthroughStylePatterns.push([PR_TYPE, types]);\n    }\n\n    var keywords = (\"\" + options['keywords']).replace(/^ | $/g, '');\n    if (keywords.length) {\n      fallthroughStylePatterns.push(\n          [PR_KEYWORD,\n           new RegExp('^(?:' + keywords.replace(/[\\s,]+/g, '|') + ')\\\\b'),\n           null]);\n    }\n\n    shortcutStylePatterns.push([PR_PLAIN,       /^\\s+/, null, ' \\r\\n\\t\\xA0']);\n\n    var punctuation =\n      // The Bash man page says\n\n      // A word is a sequence of characters considered as a single\n      // unit by GRUB. Words are separated by metacharacters,\n      // which are the following plus space, tab, and newline: { }\n      // | & $ ; < >\n      // ...\n      \n      // A word beginning with # causes that word and all remaining\n      // characters on that line to be ignored.\n\n      // which means that only a '#' after /(?:^|[{}|&$;<>\\s])/ starts a\n      // comment but empirically\n      // $ echo {#}\n      // {#}\n      // $ echo \\$#\n      // $#\n      // $ echo }#\n      // }#\n\n      // so /(?:^|[|&;<>\\s])/ is more appropriate.\n\n      // http://gcc.gnu.org/onlinedocs/gcc-2.95.3/cpp_1.html#SEC3\n      // suggests that this definition is compatible with a\n      // default mode that tries to use a single token definition\n      // to recognize both bash/python style comments and C\n      // preprocessor directives.\n\n      // This definition of punctuation does not include # in the list of\n      // follow-on exclusions, so # will not be broken before if preceeded\n      // by a punctuation character.  We could try to exclude # after\n      // [|&;<>] but that doesn't seem to cause many major problems.\n      // If that does turn out to be a problem, we should change the below\n      // when hc is truthy to include # in the run of punctuation characters\n      // only when not followint [|&;<>].\n      '^.[^\\\\s\\\\w.$@\\'\"`/\\\\\\\\]*';\n    if (options['regexLiterals']) {\n      punctuation += '(?!\\s*\\/)';\n    }\n\n    fallthroughStylePatterns.push(\n        // TODO(mikesamuel): recognize non-latin letters and numerals in idents\n        [PR_LITERAL,     /^@[a-z_$][a-z_$@0-9]*/i, null],\n        [PR_TYPE,        /^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\\w+_t\\b)/, null],\n        [PR_PLAIN,       /^[a-z_$][a-z_$@0-9]*/i, null],\n        [PR_LITERAL,\n         new RegExp(\n             '^(?:'\n             // A hex number\n             + '0x[a-f0-9]+'\n             // or an octal or decimal number,\n             + '|(?:\\\\d(?:_\\\\d+)*\\\\d*(?:\\\\.\\\\d*)?|\\\\.\\\\d\\\\+)'\n             // possibly in scientific notation\n             + '(?:e[+\\\\-]?\\\\d+)?'\n             + ')'\n             // with an optional modifier like UL for unsigned long\n             + '[a-z]*', 'i'),\n         null, '0123456789'],\n        // Don't treat escaped quotes in bash as starting strings.\n        // See issue 144.\n        [PR_PLAIN,       /^\\\\[\\s\\S]?/, null],\n        [PR_PUNCTUATION, new RegExp(punctuation), null]);\n\n    return createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns);\n  }\n\n  var decorateSource = sourceDecorator({\n        'keywords': ALL_KEYWORDS,\n        'hashComments': true,\n        'cStyleComments': true,\n        'multiLineStrings': true,\n        'regexLiterals': true\n      });\n\n  /**\n   * Given a DOM subtree, wraps it in a list, and puts each line into its own\n   * list item.\n   *\n   * @param {Node} node modified in place.  Its content is pulled into an\n   *     HTMLOListElement, and each line is moved into a separate list item.\n   *     This requires cloning elements, so the input might not have unique\n   *     IDs after numbering.\n   * @param {boolean} isPreformatted true iff white-space in text nodes should\n   *     be treated as significant.\n   */\n  function numberLines(node, opt_startLineNum, isPreformatted) {\n    var nocode = /(?:^|\\s)nocode(?:\\s|$)/;\n    var lineBreak = /\\r\\n?|\\n/;\n  \n    var document = node.ownerDocument;\n  \n    var li = document.createElement('li');\n    while (node.firstChild) {\n      li.appendChild(node.firstChild);\n    }\n    // An array of lines.  We split below, so this is initialized to one\n    // un-split line.\n    var listItems = [li];\n  \n    function walk(node) {\n      var type = node.nodeType;\n      if (type == 1 && !nocode.test(node.className)) {  // Element\n        if ('br' === node.nodeName) {\n          breakAfter(node);\n          // Discard the <BR> since it is now flush against a </LI>.\n          if (node.parentNode) {\n            node.parentNode.removeChild(node);\n          }\n        } else {\n          for (var child = node.firstChild; child; child = child.nextSibling) {\n            walk(child);\n          }\n        }\n      } else if ((type == 3 || type == 4) && isPreformatted) {  // Text\n        var text = node.nodeValue;\n        var match = text.match(lineBreak);\n        if (match) {\n          var firstLine = text.substring(0, match.index);\n          node.nodeValue = firstLine;\n          var tail = text.substring(match.index + match[0].length);\n          if (tail) {\n            var parent = node.parentNode;\n            parent.insertBefore(\n              document.createTextNode(tail), node.nextSibling);\n          }\n          breakAfter(node);\n          if (!firstLine) {\n            // Don't leave blank text nodes in the DOM.\n            node.parentNode.removeChild(node);\n          }\n        }\n      }\n    }\n  \n    // Split a line after the given node.\n    function breakAfter(lineEndNode) {\n      // If there's nothing to the right, then we can skip ending the line\n      // here, and move root-wards since splitting just before an end-tag\n      // would require us to create a bunch of empty copies.\n      while (!lineEndNode.nextSibling) {\n        lineEndNode = lineEndNode.parentNode;\n        if (!lineEndNode) { return; }\n      }\n  \n      function breakLeftOf(limit, copy) {\n        // Clone shallowly if this node needs to be on both sides of the break.\n        var rightSide = copy ? limit.cloneNode(false) : limit;\n        var parent = limit.parentNode;\n        if (parent) {\n          // We clone the parent chain.\n          // This helps us resurrect important styling elements that cross lines.\n          // E.g. in <i>Foo<br>Bar</i>\n          // should be rewritten to <li><i>Foo</i></li><li><i>Bar</i></li>.\n          var parentClone = breakLeftOf(parent, 1);\n          // Move the clone and everything to the right of the original\n          // onto the cloned parent.\n          var next = limit.nextSibling;\n          parentClone.appendChild(rightSide);\n          for (var sibling = next; sibling; sibling = next) {\n            next = sibling.nextSibling;\n            parentClone.appendChild(sibling);\n          }\n        }\n        return rightSide;\n      }\n  \n      var copiedListItem = breakLeftOf(lineEndNode.nextSibling, 0);\n  \n      // Walk the parent chain until we reach an unattached LI.\n      for (var parent;\n           // Check nodeType since IE invents document fragments.\n           (parent = copiedListItem.parentNode) && parent.nodeType === 1;) {\n        copiedListItem = parent;\n      }\n      // Put it on the list of lines for later processing.\n      listItems.push(copiedListItem);\n    }\n  \n    // Split lines while there are lines left to split.\n    for (var i = 0;  // Number of lines that have been split so far.\n         i < listItems.length;  // length updated by breakAfter calls.\n         ++i) {\n      walk(listItems[i]);\n    }\n  \n    // Make sure numeric indices show correctly.\n    if (opt_startLineNum === (opt_startLineNum|0)) {\n      listItems[0].setAttribute('value', opt_startLineNum);\n    }\n  \n    var ol = document.createElement('ol');\n    ol.className = 'linenums';\n    var offset = Math.max(0, ((opt_startLineNum - 1 /* zero index */)) | 0) || 0;\n    for (var i = 0, n = listItems.length; i < n; ++i) {\n      li = listItems[i];\n      // Stick a class on the LIs so that stylesheets can\n      // color odd/even rows, or any other row pattern that\n      // is co-prime with 10.\n      li.className = 'L' + ((i + offset) % 10);\n      if (!li.firstChild) {\n        li.appendChild(document.createTextNode('\\xA0'));\n      }\n      ol.appendChild(li);\n    }\n  \n    node.appendChild(ol);\n  }\n  /**\n   * Breaks {@code job.sourceCode} around style boundaries in\n   * {@code job.decorations} and modifies {@code job.sourceNode} in place.\n   * @param {Object} job like <pre>{\n   *    sourceCode: {string} source as plain text,\n   *    sourceNode: {HTMLElement} the element containing the source,\n   *    spans: {Array.<number|Node>} alternating span start indices into source\n   *       and the text node or element (e.g. {@code <BR>}) corresponding to that\n   *       span.\n   *    decorations: {Array.<number|string} an array of style classes preceded\n   *       by the position at which they start in job.sourceCode in order\n   * }</pre>\n   * @private\n   */\n  function recombineTagsAndDecorations(job) {\n    var isIE8OrEarlier = /\\bMSIE\\s(\\d+)/.exec(navigator.userAgent);\n    isIE8OrEarlier = isIE8OrEarlier && +isIE8OrEarlier[1] <= 8;\n    var newlineRe = /\\n/g;\n  \n    var source = job.sourceCode;\n    var sourceLength = source.length;\n    // Index into source after the last code-unit recombined.\n    var sourceIndex = 0;\n  \n    var spans = job.spans;\n    var nSpans = spans.length;\n    // Index into spans after the last span which ends at or before sourceIndex.\n    var spanIndex = 0;\n  \n    var decorations = job.decorations;\n    var nDecorations = decorations.length;\n    // Index into decorations after the last decoration which ends at or before\n    // sourceIndex.\n    var decorationIndex = 0;\n  \n    // Remove all zero-length decorations.\n    decorations[nDecorations] = sourceLength;\n    var decPos, i;\n    for (i = decPos = 0; i < nDecorations;) {\n      if (decorations[i] !== decorations[i + 2]) {\n        decorations[decPos++] = decorations[i++];\n        decorations[decPos++] = decorations[i++];\n      } else {\n        i += 2;\n      }\n    }\n    nDecorations = decPos;\n  \n    // Simplify decorations.\n    for (i = decPos = 0; i < nDecorations;) {\n      var startPos = decorations[i];\n      // Conflate all adjacent decorations that use the same style.\n      var startDec = decorations[i + 1];\n      var end = i + 2;\n      while (end + 2 <= nDecorations && decorations[end + 1] === startDec) {\n        end += 2;\n      }\n      decorations[decPos++] = startPos;\n      decorations[decPos++] = startDec;\n      i = end;\n    }\n  \n    nDecorations = decorations.length = decPos;\n  \n    var sourceNode = job.sourceNode;\n    var oldDisplay;\n    if (sourceNode) {\n      oldDisplay = sourceNode.style.display;\n      sourceNode.style.display = 'none';\n    }\n    try {\n      var decoration = null;\n      while (spanIndex < nSpans) {\n        var spanStart = spans[spanIndex];\n        var spanEnd = spans[spanIndex + 2] || sourceLength;\n  \n        var decEnd = decorations[decorationIndex + 2] || sourceLength;\n  \n        var end = Math.min(spanEnd, decEnd);\n  \n        var textNode = spans[spanIndex + 1];\n        var styledText;\n        if (textNode.nodeType !== 1  // Don't muck with <BR>s or <LI>s\n            // Don't introduce spans around empty text nodes.\n            && (styledText = source.substring(sourceIndex, end))) {\n          // This may seem bizarre, and it is.  Emitting LF on IE causes the\n          // code to display with spaces instead of line breaks.\n          // Emitting Windows standard issue linebreaks (CRLF) causes a blank\n          // space to appear at the beginning of every line but the first.\n          // Emitting an old Mac OS 9 line separator makes everything spiffy.\n          if (isIE8OrEarlier) {\n            styledText = styledText.replace(newlineRe, '\\r');\n          }\n          textNode.nodeValue = styledText;\n          var document = textNode.ownerDocument;\n          var span = document.createElement('span');\n          span.className = decorations[decorationIndex + 1];\n          var parentNode = textNode.parentNode;\n          parentNode.replaceChild(span, textNode);\n          span.appendChild(textNode);\n          if (sourceIndex < spanEnd) {  // Split off a text node.\n            spans[spanIndex + 1] = textNode\n                // TODO: Possibly optimize by using '' if there's no flicker.\n                = document.createTextNode(source.substring(end, spanEnd));\n            parentNode.insertBefore(textNode, span.nextSibling);\n          }\n        }\n  \n        sourceIndex = end;\n  \n        if (sourceIndex >= spanEnd) {\n          spanIndex += 2;\n        }\n        if (sourceIndex >= decEnd) {\n          decorationIndex += 2;\n        }\n      }\n    } finally {\n      if (sourceNode) {\n        sourceNode.style.display = oldDisplay;\n      }\n    }\n  }\n\n  /** Maps language-specific file extensions to handlers. */\n  var langHandlerRegistry = {};\n  /** Register a language handler for the given file extensions.\n    * @param {function (Object)} handler a function from source code to a list\n    *      of decorations.  Takes a single argument job which describes the\n    *      state of the computation.   The single parameter has the form\n    *      {@code {\n    *        sourceCode: {string} as plain text.\n    *        decorations: {Array.<number|string>} an array of style classes\n    *                     preceded by the position at which they start in\n    *                     job.sourceCode in order.\n    *                     The language handler should assigned this field.\n    *        basePos: {int} the position of source in the larger source chunk.\n    *                 All positions in the output decorations array are relative\n    *                 to the larger source chunk.\n    *      } }\n    * @param {Array.<string>} fileExtensions\n    */\n  function registerLangHandler(handler, fileExtensions) {\n    for (var i = fileExtensions.length; --i >= 0;) {\n      var ext = fileExtensions[i];\n      if (!langHandlerRegistry.hasOwnProperty(ext)) {\n        langHandlerRegistry[ext] = handler;\n      } else if (win['console']) {\n        console['warn']('cannot override language handler %s', ext);\n      }\n    }\n  }\n  function langHandlerForExtension(extension, source) {\n    if (!(extension && langHandlerRegistry.hasOwnProperty(extension))) {\n      // Treat it as markup if the first non whitespace character is a < and\n      // the last non-whitespace character is a >.\n      extension = /^\\s*</.test(source)\n          ? 'default-markup'\n          : 'default-code';\n    }\n    return langHandlerRegistry[extension];\n  }\n  registerLangHandler(decorateSource, ['default-code']);\n  registerLangHandler(\n      createSimpleLexer(\n          [],\n          [\n           [PR_PLAIN,       /^[^<?]+/],\n           [PR_DECLARATION, /^<!\\w[^>]*(?:>|$)/],\n           [PR_COMMENT,     /^<\\!--[\\s\\S]*?(?:-\\->|$)/],\n           // Unescaped content in an unknown language\n           ['lang-',        /^<\\?([\\s\\S]+?)(?:\\?>|$)/],\n           ['lang-',        /^<%([\\s\\S]+?)(?:%>|$)/],\n           [PR_PUNCTUATION, /^(?:<[%?]|[%?]>)/],\n           ['lang-',        /^<xmp\\b[^>]*>([\\s\\S]+?)<\\/xmp\\b[^>]*>/i],\n           // Unescaped content in javascript.  (Or possibly vbscript).\n           ['lang-js',      /^<script\\b[^>]*>([\\s\\S]*?)(<\\/script\\b[^>]*>)/i],\n           // Contains unescaped stylesheet content\n           ['lang-css',     /^<style\\b[^>]*>([\\s\\S]*?)(<\\/style\\b[^>]*>)/i],\n           ['lang-in.tag',  /^(<\\/?[a-z][^<>]*>)/i]\n          ]),\n      ['default-markup', 'htm', 'html', 'mxml', 'xhtml', 'xml', 'xsl']);\n  registerLangHandler(\n      createSimpleLexer(\n          [\n           [PR_PLAIN,        /^[\\s]+/, null, ' \\t\\r\\n'],\n           [PR_ATTRIB_VALUE, /^(?:\\\"[^\\\"]*\\\"?|\\'[^\\']*\\'?)/, null, '\\\"\\'']\n           ],\n          [\n           [PR_TAG,          /^^<\\/?[a-z](?:[\\w.:-]*\\w)?|\\/?>$/i],\n           [PR_ATTRIB_NAME,  /^(?!style[\\s=]|on)[a-z](?:[\\w:-]*\\w)?/i],\n           ['lang-uq.val',   /^=\\s*([^>\\'\\\"\\s]*(?:[^>\\'\\\"\\s\\/]|\\/(?=\\s)))/],\n           [PR_PUNCTUATION,  /^[=<>\\/]+/],\n           ['lang-js',       /^on\\w+\\s*=\\s*\\\"([^\\\"]+)\\\"/i],\n           ['lang-js',       /^on\\w+\\s*=\\s*\\'([^\\']+)\\'/i],\n           ['lang-js',       /^on\\w+\\s*=\\s*([^\\\"\\'>\\s]+)/i],\n           ['lang-css',      /^style\\s*=\\s*\\\"([^\\\"]+)\\\"/i],\n           ['lang-css',      /^style\\s*=\\s*\\'([^\\']+)\\'/i],\n           ['lang-css',      /^style\\s*=\\s*([^\\\"\\'>\\s]+)/i]\n           ]),\n      ['in.tag']);\n  registerLangHandler(\n      createSimpleLexer([], [[PR_ATTRIB_VALUE, /^[\\s\\S]+/]]), ['uq.val']);\n  registerLangHandler(sourceDecorator({\n          'keywords': CPP_KEYWORDS,\n          'hashComments': true,\n          'cStyleComments': true,\n          'types': C_TYPES\n        }), ['c', 'cc', 'cpp', 'cxx', 'cyc', 'm']);\n  registerLangHandler(sourceDecorator({\n          'keywords': 'null,true,false'\n        }), ['json']);\n  registerLangHandler(sourceDecorator({\n          'keywords': CSHARP_KEYWORDS,\n          'hashComments': true,\n          'cStyleComments': true,\n          'verbatimStrings': true,\n          'types': C_TYPES\n        }), ['cs']);\n  registerLangHandler(sourceDecorator({\n          'keywords': JAVA_KEYWORDS,\n          'cStyleComments': true\n        }), ['java']);\n  registerLangHandler(sourceDecorator({\n          'keywords': SH_KEYWORDS,\n          'hashComments': true,\n          'multiLineStrings': true\n        }), ['bash', 'bsh', 'csh', 'sh']);\n  registerLangHandler(sourceDecorator({\n          'keywords': PYTHON_KEYWORDS,\n          'hashComments': true,\n          'multiLineStrings': true,\n          'tripleQuotedStrings': true\n        }), ['cv', 'py', 'python']);\n  registerLangHandler(sourceDecorator({\n          'keywords': PERL_KEYWORDS,\n          'hashComments': true,\n          'multiLineStrings': true,\n          'regexLiterals': 2  // multiline regex literals\n        }), ['perl', 'pl', 'pm']);\n  registerLangHandler(sourceDecorator({\n          'keywords': RUBY_KEYWORDS,\n          'hashComments': true,\n          'multiLineStrings': true,\n          'regexLiterals': true\n        }), ['rb', 'ruby']);\n  registerLangHandler(sourceDecorator({\n          'keywords': JSCRIPT_KEYWORDS,\n          'cStyleComments': true,\n          'regexLiterals': true\n        }), ['javascript', 'js']);\n  registerLangHandler(sourceDecorator({\n          'keywords': COFFEE_KEYWORDS,\n          'hashComments': 3,  // ### style block comments\n          'cStyleComments': true,\n          'multilineStrings': true,\n          'tripleQuotedStrings': true,\n          'regexLiterals': true\n        }), ['coffee']);\n  registerLangHandler(sourceDecorator({\n          'keywords': RUST_KEYWORDS,\n          'cStyleComments': true,\n          'multilineStrings': true\n        }), ['rc', 'rs', 'rust']);\n  registerLangHandler(\n      createSimpleLexer([], [[PR_STRING, /^[\\s\\S]+/]]), ['regex']);\n\n  function applyDecorator(job) {\n    var opt_langExtension = job.langExtension;\n\n    try {\n      // Extract tags, and convert the source code to plain text.\n      var sourceAndSpans = extractSourceSpans(job.sourceNode, job.pre);\n      /** Plain text. @type {string} */\n      var source = sourceAndSpans.sourceCode;\n      job.sourceCode = source;\n      job.spans = sourceAndSpans.spans;\n      job.basePos = 0;\n\n      // Apply the appropriate language handler\n      langHandlerForExtension(opt_langExtension, source)(job);\n\n      // Integrate the decorations and tags back into the source code,\n      // modifying the sourceNode in place.\n      recombineTagsAndDecorations(job);\n    } catch (e) {\n      if (win['console']) {\n        console['log'](e && e['stack'] || e);\n      }\n    }\n  }\n\n  /**\n   * Pretty print a chunk of code.\n   * @param sourceCodeHtml {string} The HTML to pretty print.\n   * @param opt_langExtension {string} The language name to use.\n   *     Typically, a filename extension like 'cpp' or 'java'.\n   * @param opt_numberLines {number|boolean} True to number lines,\n   *     or the 1-indexed number of the first line in sourceCodeHtml.\n   */\n  function $prettyPrintOne(sourceCodeHtml, opt_langExtension, opt_numberLines) {\n    var container = document.createElement('div');\n    // This could cause images to load and onload listeners to fire.\n    // E.g. <img onerror=\"alert(1337)\" src=\"nosuchimage.png\">.\n    // We assume that the inner HTML is from a trusted source.\n    // The pre-tag is required for IE8 which strips newlines from innerHTML\n    // when it is injected into a <pre> tag.\n    // http://stackoverflow.com/questions/451486/pre-tag-loses-line-breaks-when-setting-innerhtml-in-ie\n    // http://stackoverflow.com/questions/195363/inserting-a-newline-into-a-pre-tag-ie-javascript\n    container.innerHTML = '<pre>' + sourceCodeHtml + '</pre>';\n    container = container.firstChild;\n    if (opt_numberLines) {\n      numberLines(container, opt_numberLines, true);\n    }\n\n    var job = {\n      langExtension: opt_langExtension,\n      numberLines: opt_numberLines,\n      sourceNode: container,\n      pre: 1\n    };\n    applyDecorator(job);\n    return container.innerHTML;\n  }\n\n   /**\n    * Find all the {@code <pre>} and {@code <code>} tags in the DOM with\n    * {@code class=prettyprint} and prettify them.\n    *\n    * @param {Function} opt_whenDone called when prettifying is done.\n    * @param {HTMLElement|HTMLDocument} opt_root an element or document\n    *   containing all the elements to pretty print.\n    *   Defaults to {@code document.body}.\n    */\n  function $prettyPrint(opt_whenDone, opt_root) {\n    var root = opt_root || document.body;\n    var doc = root.ownerDocument || document;\n    function byTagName(tn) { return root.getElementsByTagName(tn); }\n    // fetch a list of nodes to rewrite\n    var codeSegments = [byTagName('pre'), byTagName('code'), byTagName('xmp')];\n    var elements = [];\n    for (var i = 0; i < codeSegments.length; ++i) {\n      for (var j = 0, n = codeSegments[i].length; j < n; ++j) {\n        elements.push(codeSegments[i][j]);\n      }\n    }\n    codeSegments = null;\n\n    var clock = Date;\n    if (!clock['now']) {\n      clock = { 'now': function () { return +(new Date); } };\n    }\n\n    // The loop is broken into a series of continuations to make sure that we\n    // don't make the browser unresponsive when rewriting a large page.\n    var k = 0;\n    var prettyPrintingJob;\n\n    var langExtensionRe = /\\blang(?:uage)?-([\\w.]+)(?!\\S)/;\n    var prettyPrintRe = /\\bprettyprint\\b/;\n    var prettyPrintedRe = /\\bprettyprinted\\b/;\n    var preformattedTagNameRe = /pre|xmp/i;\n    var codeRe = /^code$/i;\n    var preCodeXmpRe = /^(?:pre|code|xmp)$/i;\n    var EMPTY = {};\n\n    function doWork() {\n      var endTime = (win['PR_SHOULD_USE_CONTINUATION'] ?\n                     clock['now']() + 250 /* ms */ :\n                     Infinity);\n      for (; k < elements.length && clock['now']() < endTime; k++) {\n        var cs = elements[k];\n\n        // Look for a preceding comment like\n        // <?prettify lang=\"...\" linenums=\"...\"?>\n        var attrs = EMPTY;\n        {\n          for (var preceder = cs; (preceder = preceder.previousSibling);) {\n            var nt = preceder.nodeType;\n            // <?foo?> is parsed by HTML 5 to a comment node (8)\n            // like <!--?foo?-->, but in XML is a processing instruction\n            var value = (nt === 7 || nt === 8) && preceder.nodeValue;\n            if (value\n                ? !/^\\??prettify\\b/.test(value)\n                : (nt !== 3 || /\\S/.test(preceder.nodeValue))) {\n              // Skip over white-space text nodes but not others.\n              break;\n            }\n            if (value) {\n              attrs = {};\n              value.replace(\n                  /\\b(\\w+)=([\\w:.%+-]+)/g,\n                function (_, name, value) { attrs[name] = value; });\n              break;\n            }\n          }\n        }\n\n        var className = cs.className;\n        if ((attrs !== EMPTY || prettyPrintRe.test(className))\n            // Don't redo this if we've already done it.\n            // This allows recalling pretty print to just prettyprint elements\n            // that have been added to the page since last call.\n            && !prettyPrintedRe.test(className)) {\n\n          // make sure this is not nested in an already prettified element\n          var nested = false;\n          for (var p = cs.parentNode; p; p = p.parentNode) {\n            var tn = p.tagName;\n            if (preCodeXmpRe.test(tn)\n                && p.className && prettyPrintRe.test(p.className)) {\n              nested = true;\n              break;\n            }\n          }\n          if (!nested) {\n            // Mark done.  If we fail to prettyprint for whatever reason,\n            // we shouldn't try again.\n            cs.className += ' prettyprinted';\n\n            // If the classes includes a language extensions, use it.\n            // Language extensions can be specified like\n            //     <pre class=\"prettyprint lang-cpp\">\n            // the language extension \"cpp\" is used to find a language handler\n            // as passed to PR.registerLangHandler.\n            // HTML5 recommends that a language be specified using \"language-\"\n            // as the prefix instead.  Google Code Prettify supports both.\n            // http://dev.w3.org/html5/spec-author-view/the-code-element.html\n            var langExtension = attrs['lang'];\n            if (!langExtension) {\n              langExtension = className.match(langExtensionRe);\n              // Support <pre class=\"prettyprint\"><code class=\"language-c\">\n              var wrapper;\n              if (!langExtension && (wrapper = childContentWrapper(cs))\n                  && codeRe.test(wrapper.tagName)) {\n                langExtension = wrapper.className.match(langExtensionRe);\n              }\n\n              if (langExtension) { langExtension = langExtension[1]; }\n            }\n\n            var preformatted;\n            if (preformattedTagNameRe.test(cs.tagName)) {\n              preformatted = 1;\n            } else {\n              var currentStyle = cs['currentStyle'];\n              var defaultView = doc.defaultView;\n              var whitespace = (\n                  currentStyle\n                  ? currentStyle['whiteSpace']\n                  : (defaultView\n                     && defaultView.getComputedStyle)\n                  ? defaultView.getComputedStyle(cs, null)\n                  .getPropertyValue('white-space')\n                  : 0);\n              preformatted = whitespace\n                  && 'pre' === whitespace.substring(0, 3);\n            }\n\n            // Look for a class like linenums or linenums:<n> where <n> is the\n            // 1-indexed number of the first line.\n            var lineNums = attrs['linenums'];\n            if (!(lineNums = lineNums === 'true' || +lineNums)) {\n              lineNums = className.match(/\\blinenums\\b(?::(\\d+))?/);\n              lineNums =\n                lineNums\n                ? lineNums[1] && lineNums[1].length\n                  ? +lineNums[1] : true\n                : false;\n            }\n            if (lineNums) { numberLines(cs, lineNums, preformatted); }\n\n            // do the pretty printing\n            prettyPrintingJob = {\n              langExtension: langExtension,\n              sourceNode: cs,\n              numberLines: lineNums,\n              pre: preformatted\n            };\n            applyDecorator(prettyPrintingJob);\n          }\n        }\n      }\n      if (k < elements.length) {\n        // finish up in a continuation\n        setTimeout(doWork, 250);\n      } else if ('function' === typeof opt_whenDone) {\n        opt_whenDone();\n      }\n    }\n\n    doWork();\n  }\n\n  /**\n   * Contains functions for creating and registering new language handlers.\n   * @type {Object}\n   */\n  var PR = win['PR'] = {\n        'createSimpleLexer': createSimpleLexer,\n        'registerLangHandler': registerLangHandler,\n        'sourceDecorator': sourceDecorator,\n        'PR_ATTRIB_NAME': PR_ATTRIB_NAME,\n        'PR_ATTRIB_VALUE': PR_ATTRIB_VALUE,\n        'PR_COMMENT': PR_COMMENT,\n        'PR_DECLARATION': PR_DECLARATION,\n        'PR_KEYWORD': PR_KEYWORD,\n        'PR_LITERAL': PR_LITERAL,\n        'PR_NOCODE': PR_NOCODE,\n        'PR_PLAIN': PR_PLAIN,\n        'PR_PUNCTUATION': PR_PUNCTUATION,\n        'PR_SOURCE': PR_SOURCE,\n        'PR_STRING': PR_STRING,\n        'PR_TAG': PR_TAG,\n        'PR_TYPE': PR_TYPE,\n        'prettyPrintOne':\n           IN_GLOBAL_SCOPE\n             ? (win['prettyPrintOne'] = $prettyPrintOne)\n             : (prettyPrintOne = $prettyPrintOne),\n        'prettyPrint': prettyPrint =\n           IN_GLOBAL_SCOPE\n             ? (win['prettyPrint'] = $prettyPrint)\n             : (prettyPrint = $prettyPrint)\n      };\n\n  // Make PR available via the Asynchronous Module Definition (AMD) API.\n  // Per https://github.com/amdjs/amdjs-api/wiki/AMD:\n  // The Asynchronous Module Definition (AMD) API specifies a\n  // mechanism for defining modules such that the module and its\n  // dependencies can be asynchronously loaded.\n  // ...\n  // To allow a clear indicator that a global define function (as\n  // needed for script src browser loading) conforms to the AMD API,\n  // any global define function SHOULD have a property called \"amd\"\n  // whose value is an object. This helps avoid conflict with any\n  // other existing JavaScript code that could have defined a define()\n  // function that does not conform to the AMD API.\n  if (typeof define === \"function\" && define['amd']) {\n    define(\"google-code-prettify\", [], function () {\n      return PR; \n    });\n  }\n})();\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/js/run_prettify.js",
    "content": "// Copyright (C) 2013 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// Looks at query parameters to decide which language handlers and style-sheets\n// to load.\n\n// Query Parameter     Format           Effect                        Default\n// +------------------+---------------+------------------------------+--------+\n// | autorun=         | true | false  | If true then prettyPrint()   | \"true\" |\n// |                  |               | is called on page load.      |        |\n// +------------------+---------------+------------------------------+--------+\n// | lang=            | language name | Loads the language handler   | Can    |\n// |                  |               | named \"lang-<NAME>.js\".      | appear |\n// |                  |               | See available handlers at    | many   |\n// |                  |               | http://code.google.com/p/    | times. |\n// |                  |               | google-code-prettify/source/ |        |\n// |                  |               | browse/trunk/src             |        |\n// +------------------+---------------+------------------------------+--------+\n// | skin=            | skin name     | Loads the skin stylesheet    | none.  |\n// |                  |               | named \"<NAME>.css\".          |        |\n// |                  |               | http://code.google.com/p/    |        |\n// |                  |               | google-code-prettify/source/ |        |\n// |                  |               | browse/trunk/styles          |        |\n// +------------------+---------------+------------------------------+--------+\n// | callback=        | JS identifier | When \"prettyPrint\" finishes  | none   |\n// |                  |               | window.exports[js_ident] is  |        |\n// |                  |               | called.                      |        |\n// |                  |               | The callback must be under   |        |\n// |                  |               | exports to reduce the risk   |        |\n// |                  |               | of XSS via query parameter   |        |\n// |                  |               | injection.                   |        |\n// +------------------+---------------+------------------------------+--------+\n\n// Exmaples\n// .../prettify.js?lang=css&skin=sunburst\n//   1. Loads the CSS language handler which can be used to prettify CSS\n//      stylesheets, HTML <style> element bodies and style=\"...\" attributes\n//      values.\n//   2. Loads the sunburst.css stylesheet instead of the default prettify.css\n//      stylesheet.\n//      A gallery of stylesheets is available at\n//      https://google-code-prettify.googlecode.com/svn/trunk/styles/index.html\n//   3. Since autorun=false is not specified, calls prettyPrint() on page load.\n\n\n/** @define {boolean} */\nvar IN_GLOBAL_SCOPE = false;\n\n(function () {\n  \"use strict\";\n\n  var win = window;\n  var setTimeout = win.setTimeout;\n  var doc = document;\n  var root = doc.documentElement;\n  var head = doc['head'] || doc.getElementsByTagName(\"head\")[0] || root;\n\n  // From http://javascript.nwbox.com/ContentLoaded/contentloaded.js\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  function contentLoaded(callback) {\n    var addEventListener = doc['addEventListener'];\n    var done = false, top = true,\n        add = addEventListener ? 'addEventListener' : 'attachEvent',\n        rem = addEventListener ? 'removeEventListener' : 'detachEvent',\n        pre = addEventListener ? '' : 'on',\n\n        init = function(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)) { callback.call(win, e.type || e); }\n        },\n\n        poll = function() {\n          try {\n            root.doScroll('left');\n          } catch(e) {\n            setTimeout(poll, 50);\n            return;\n          }\n          init('poll');\n        };\n\n    if (doc.readyState == 'complete') {\n      callback.call(win, 'lazy');\n    } else {\n      if (doc.createEventObject && root.doScroll) {\n        try { top = !win.frameElement; } catch(e) { }\n        if (top) { poll(); }\n      }\n      doc[add](pre + 'DOMContentLoaded', init, false);\n      doc[add](pre + 'readystatechange', init, false);\n      win[add](pre + 'load', init, false);\n    }\n  }\n\n  // Given a list of URLs to stylesheets, loads the first that loads without\n  // triggering an error event.\n  function loadStylesheetsFallingBack(stylesheets) {\n    var n = stylesheets.length;\n    function load(i) {\n      if (i === n) { return; }\n      var link = doc.createElement('link');\n      link.rel = 'stylesheet';\n      link.type = 'text/css';\n      if (i + 1 < n) {\n        // http://pieisgood.org/test/script-link-events/ indicates that many\n        // versions of IE do not support onerror on <link>s, though\n        // http://msdn.microsoft.com/en-us/library/ie/ms535848(v=vs.85).aspx\n        // indicates that recent IEs do support error.\n        link.error = link.onerror = function () { load(i + 1); };\n      }\n      link.href = stylesheets[i];\n      head.appendChild(link);\n    }\n    load(0);\n  }\n\n  var scriptQuery = '';\n  // Look for the <script> node that loads this script to get its parameters.\n  // This starts looking at the end instead of just considering the last\n  // because deferred and async scripts run out of order.\n  // If the script is loaded twice, then this will run in reverse order.\n  for (var scripts = doc.scripts, i = scripts.length; --i >= 0;) {\n    var script = scripts[i];\n    var match = script.src.match(\n        /^[^?#]*\\/run_prettify\\.js(\\?[^#]*)?(?:#.*)?$/);\n    if (match) {\n      scriptQuery = match[1] || '';\n      // Remove the script from the DOM so that multiple runs at least run\n      // multiple times even if parameter sets are interpreted in reverse\n      // order.\n      script.parentNode.removeChild(script);\n      break;\n    }\n  }\n\n  // Pull parameters into local variables.\n  var autorun = true;\n  var langs = [];\n  var skins = [];\n  var callbacks = [];\n  scriptQuery.replace(\n      /[?&]([^&=]+)=([^&]+)/g,\n      function (_, name, value) {\n        value = decodeURIComponent(value);\n        name = decodeURIComponent(name);\n        if (name == 'autorun')   { autorun = !/^[0fn]/i.test(value); } else\n        if (name == 'lang')      { langs.push(value);                } else\n        if (name == 'skin')      { skins.push(value);                } else\n        if (name == 'callback')  { callbacks.push(value);            }\n      });\n\n  // Use https to avoid mixed content warnings in client pages and to\n  // prevent a MITM from rewrite prettify mid-flight.\n  // This only works if this script is loaded via https : something\n  // over which we exercise no control.\n  var LOADER_BASE_URL =\n     'https://google-code-prettify.googlecode.com/svn/loader';\n\n  for (var i = 0, n = langs.length; i < n; ++i) (function (lang) {\n    var script = doc.createElement(\"script\");\n\n    // Excerpted from jQuery.ajaxTransport(\"script\") to fire events when\n    // a script is finished loading.\n    // Attach handlers for each script\n    script.onload = script.onerror = script.onreadystatechange = function () {\n      if (script && (\n            !script.readyState || /loaded|complete/.test(script.readyState))) {\n        // Handle memory leak in IE\n        script.onerror = script.onload = script.onreadystatechange = null;\n\n        --pendingLanguages;\n        checkPendingLanguages();\n\n        // Remove the script\n        if (script.parentNode) {\n          script.parentNode.removeChild(script);\n        }\n\n        script = null;\n      }\n    };\n\n    script.type = 'text/javascript';\n    script.src = LOADER_BASE_URL\n      + '/lang-' + encodeURIComponent(langs[i]) + '.js';\n\n    // Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending\n    head.insertBefore(script, head.firstChild);\n  })(langs[i]);\n\n  var pendingLanguages = langs.length;\n  function checkPendingLanguages() {\n    if (!pendingLanguages) {\n      setTimeout(onLangsLoaded, 0);\n    }\n  }\n\n  var skinUrls = [];\n  for (var i = 0, n = skins.length; i < n; ++i) {\n    skinUrls.push(LOADER_BASE_URL\n        + '/skins/' + encodeURIComponent(skins[i]) + '.css');\n  }\n  skinUrls.push(LOADER_BASE_URL + '/prettify.css');\n  loadStylesheetsFallingBack(skinUrls);\n\n  var prettyPrint = (function () {\n    // Copyright (C) 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    /**\n     * @fileoverview\n     * some functions for browser-side pretty printing of code contained in html.\n     *\n     * <p>\n     * For a fairly comprehensive set of languages see the\n     * <a href=\"http://google-code-prettify.googlecode.com/svn/trunk/README.html#langs\">README</a>\n     * file that came with this source.  At a minimum, the lexer should work on a\n     * number of languages including C and friends, Java, Python, Bash, SQL, HTML,\n     * XML, CSS, Javascript, and Makefiles.  It works passably on Ruby, PHP and Awk\n     * and a subset of Perl, but, because of commenting conventions, doesn't work on\n     * Smalltalk, Lisp-like, or CAML-like languages without an explicit lang class.\n     * <p>\n     * Usage: <ol>\n     * <li> include this source file in an html page via\n     *   {@code <script type=\"text/javascript\" src=\"/path/to/prettify.js\"></script>}\n     * <li> define style rules.  See the example page for examples.\n     * <li> mark the {@code <pre>} and {@code <code>} tags in your source with\n     *    {@code class=prettyprint.}\n     *    You can also use the (html deprecated) {@code <xmp>} tag, but the pretty\n     *    printer needs to do more substantial DOM manipulations to support that, so\n     *    some css styles may not be preserved.\n     * </ol>\n     * That's it.  I wanted to keep the API as simple as possible, so there's no\n     * need to specify which language the code is in, but if you wish, you can add\n     * another class to the {@code <pre>} or {@code <code>} element to specify the\n     * language, as in {@code <pre class=\"prettyprint lang-java\">}.  Any class that\n     * starts with \"lang-\" followed by a file extension, specifies the file type.\n     * See the \"lang-*.js\" files in this directory for code that implements\n     * per-language file handlers.\n     * <p>\n     * Change log:<br>\n     * cbeust, 2006/08/22\n     * <blockquote>\n     *   Java annotations (start with \"@\") are now captured as literals (\"lit\")\n     * </blockquote>\n     * @requires console\n     */\n    \n    // JSLint declarations\n    /*global console, document, navigator, setTimeout, window, define */\n    \n    /**\n     * Split {@code prettyPrint} into multiple timeouts so as not to interfere with\n     * UI events.\n     * If set to {@code false}, {@code prettyPrint()} is synchronous.\n     */\n    window['PR_SHOULD_USE_CONTINUATION'] = true;\n    \n    /**\n     * Pretty print a chunk of code.\n     * @param {string} sourceCodeHtml The HTML to pretty print.\n     * @param {string} opt_langExtension The language name to use.\n     *     Typically, a filename extension like 'cpp' or 'java'.\n     * @param {number|boolean} opt_numberLines True to number lines,\n     *     or the 1-indexed number of the first line in sourceCodeHtml.\n     * @return {string} code as html, but prettier\n     */\n    var prettyPrintOne;\n    /**\n     * Find all the {@code <pre>} and {@code <code>} tags in the DOM with\n     * {@code class=prettyprint} and prettify them.\n     *\n     * @param {Function} opt_whenDone called when prettifying is done.\n     * @param {HTMLElement|HTMLDocument} opt_root an element or document\n     *   containing all the elements to pretty print.\n     *   Defaults to {@code document.body}.\n     */\n    var prettyPrint;\n    \n    \n    (function () {\n      var win = window;\n      // Keyword lists for various languages.\n      // We use things that coerce to strings to make them compact when minified\n      // and to defeat aggressive optimizers that fold large string constants.\n      var FLOW_CONTROL_KEYWORDS = [\"break,continue,do,else,for,if,return,while\"];\n      var C_KEYWORDS = [FLOW_CONTROL_KEYWORDS,\"auto,case,char,const,default,\" + \n          \"double,enum,extern,float,goto,inline,int,long,register,short,signed,\" +\n          \"sizeof,static,struct,switch,typedef,union,unsigned,void,volatile\"];\n      var COMMON_KEYWORDS = [C_KEYWORDS,\"catch,class,delete,false,import,\" +\n          \"new,operator,private,protected,public,this,throw,true,try,typeof\"];\n      var CPP_KEYWORDS = [COMMON_KEYWORDS,\"alignof,align_union,asm,axiom,bool,\" +\n          \"concept,concept_map,const_cast,constexpr,decltype,delegate,\" +\n          \"dynamic_cast,explicit,export,friend,generic,late_check,\" +\n          \"mutable,namespace,nullptr,property,reinterpret_cast,static_assert,\" +\n          \"static_cast,template,typeid,typename,using,virtual,where\"];\n      var JAVA_KEYWORDS = [COMMON_KEYWORDS,\n          \"abstract,assert,boolean,byte,extends,final,finally,implements,import,\" +\n          \"instanceof,interface,null,native,package,strictfp,super,synchronized,\" +\n          \"throws,transient\"];\n      var CSHARP_KEYWORDS = [JAVA_KEYWORDS,\n          \"as,base,by,checked,decimal,delegate,descending,dynamic,event,\" +\n          \"fixed,foreach,from,group,implicit,in,internal,into,is,let,\" +\n          \"lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,\" +\n          \"sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,\" +\n          \"var,virtual,where\"];\n      var COFFEE_KEYWORDS = \"all,and,by,catch,class,else,extends,false,finally,\" +\n          \"for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,\" +\n          \"throw,true,try,unless,until,when,while,yes\";\n      var JSCRIPT_KEYWORDS = [COMMON_KEYWORDS,\n          \"debugger,eval,export,function,get,null,set,undefined,var,with,\" +\n          \"Infinity,NaN\"];\n      var PERL_KEYWORDS = \"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,\" +\n          \"goto,if,import,last,local,my,next,no,our,print,package,redo,require,\" +\n          \"sub,undef,unless,until,use,wantarray,while,BEGIN,END\";\n      var PYTHON_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"and,as,assert,class,def,del,\" +\n          \"elif,except,exec,finally,from,global,import,in,is,lambda,\" +\n          \"nonlocal,not,or,pass,print,raise,try,with,yield,\" +\n          \"False,True,None\"];\n      var RUBY_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"alias,and,begin,case,class,\" +\n          \"def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,\" +\n          \"rescue,retry,self,super,then,true,undef,unless,until,when,yield,\" +\n          \"BEGIN,END\"];\n       var RUST_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"as,assert,const,copy,drop,\" +\n          \"enum,extern,fail,false,fn,impl,let,log,loop,match,mod,move,mut,priv,\" +\n          \"pub,pure,ref,self,static,struct,true,trait,type,unsafe,use\"];\n      var SH_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"case,done,elif,esac,eval,fi,\" +\n          \"function,in,local,set,then,until\"];\n      var ALL_KEYWORDS = [\n          CPP_KEYWORDS, CSHARP_KEYWORDS, JSCRIPT_KEYWORDS, PERL_KEYWORDS,\n          PYTHON_KEYWORDS, RUBY_KEYWORDS, SH_KEYWORDS];\n      var C_TYPES = /^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\\d*)\\b/;\n    \n      // token style names.  correspond to css classes\n      /**\n       * token style for a string literal\n       * @const\n       */\n      var PR_STRING = 'str';\n      /**\n       * token style for a keyword\n       * @const\n       */\n      var PR_KEYWORD = 'kwd';\n      /**\n       * token style for a comment\n       * @const\n       */\n      var PR_COMMENT = 'com';\n      /**\n       * token style for a type\n       * @const\n       */\n      var PR_TYPE = 'typ';\n      /**\n       * token style for a literal value.  e.g. 1, null, true.\n       * @const\n       */\n      var PR_LITERAL = 'lit';\n      /**\n       * token style for a punctuation string.\n       * @const\n       */\n      var PR_PUNCTUATION = 'pun';\n      /**\n       * token style for plain text.\n       * @const\n       */\n      var PR_PLAIN = 'pln';\n    \n      /**\n       * token style for an sgml tag.\n       * @const\n       */\n      var PR_TAG = 'tag';\n      /**\n       * token style for a markup declaration such as a DOCTYPE.\n       * @const\n       */\n      var PR_DECLARATION = 'dec';\n      /**\n       * token style for embedded source.\n       * @const\n       */\n      var PR_SOURCE = 'src';\n      /**\n       * token style for an sgml attribute name.\n       * @const\n       */\n      var PR_ATTRIB_NAME = 'atn';\n      /**\n       * token style for an sgml attribute value.\n       * @const\n       */\n      var PR_ATTRIB_VALUE = 'atv';\n    \n      /**\n       * A class that indicates a section of markup that is not code, e.g. to allow\n       * embedding of line numbers within code listings.\n       * @const\n       */\n      var PR_NOCODE = 'nocode';\n    \n      \n      \n      /**\n       * A set of tokens that can precede a regular expression literal in\n       * javascript\n       * http://web.archive.org/web/20070717142515/http://www.mozilla.org/js/language/js20/rationale/syntax.html\n       * has the full list, but I've removed ones that might be problematic when\n       * seen in languages that don't support regular expression literals.\n       *\n       * <p>Specifically, I've removed any keywords that can't precede a regexp\n       * literal in a syntactically legal javascript program, and I've removed the\n       * \"in\" keyword since it's not a keyword in many languages, and might be used\n       * as a count of inches.\n       *\n       * <p>The link above does not accurately describe EcmaScript rules since\n       * it fails to distinguish between (a=++/b/i) and (a++/b/i) but it works\n       * very well in practice.\n       *\n       * @private\n       * @const\n       */\n      var REGEXP_PRECEDER_PATTERN = '(?:^^\\\\.?|[+-]|[!=]=?=?|\\\\#|%=?|&&?=?|\\\\(|\\\\*=?|[+\\\\-]=|->|\\\\/=?|::?|<<?=?|>>?>?=?|,|;|\\\\?|@|\\\\[|~|{|\\\\^\\\\^?=?|\\\\|\\\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\\\s*';\n      \n      // CAVEAT: this does not properly handle the case where a regular\n      // expression immediately follows another since a regular expression may\n      // have flags for case-sensitivity and the like.  Having regexp tokens\n      // adjacent is not valid in any language I'm aware of, so I'm punting.\n      // TODO: maybe style special characters inside a regexp as punctuation.\n    \n      /**\n       * Given a group of {@link RegExp}s, returns a {@code RegExp} that globally\n       * matches the union of the sets of strings matched by the input RegExp.\n       * Since it matches globally, if the input strings have a start-of-input\n       * anchor (/^.../), it is ignored for the purposes of unioning.\n       * @param {Array.<RegExp>} regexs non multiline, non-global regexs.\n       * @return {RegExp} a global regex.\n       */\n      function combinePrefixPatterns(regexs) {\n        var capturedGroupIndex = 0;\n      \n        var needToFoldCase = false;\n        var ignoreCase = false;\n        for (var i = 0, n = regexs.length; i < n; ++i) {\n          var regex = regexs[i];\n          if (regex.ignoreCase) {\n            ignoreCase = true;\n          } else if (/[a-z]/i.test(regex.source.replace(\n                         /\\\\u[0-9a-f]{4}|\\\\x[0-9a-f]{2}|\\\\[^ux]/gi, ''))) {\n            needToFoldCase = true;\n            ignoreCase = false;\n            break;\n          }\n        }\n      \n        var escapeCharToCodeUnit = {\n          'b': 8,\n          't': 9,\n          'n': 0xa,\n          'v': 0xb,\n          'f': 0xc,\n          'r': 0xd\n        };\n      \n        function decodeEscape(charsetPart) {\n          var cc0 = charsetPart.charCodeAt(0);\n          if (cc0 !== 92 /* \\\\ */) {\n            return cc0;\n          }\n          var c1 = charsetPart.charAt(1);\n          cc0 = escapeCharToCodeUnit[c1];\n          if (cc0) {\n            return cc0;\n          } else if ('0' <= c1 && c1 <= '7') {\n            return parseInt(charsetPart.substring(1), 8);\n          } else if (c1 === 'u' || c1 === 'x') {\n            return parseInt(charsetPart.substring(2), 16);\n          } else {\n            return charsetPart.charCodeAt(1);\n          }\n        }\n      \n        function encodeEscape(charCode) {\n          if (charCode < 0x20) {\n            return (charCode < 0x10 ? '\\\\x0' : '\\\\x') + charCode.toString(16);\n          }\n          var ch = String.fromCharCode(charCode);\n          return (ch === '\\\\' || ch === '-' || ch === ']' || ch === '^')\n              ? \"\\\\\" + ch : ch;\n        }\n      \n        function caseFoldCharset(charSet) {\n          var charsetParts = charSet.substring(1, charSet.length - 1).match(\n              new RegExp(\n                  '\\\\\\\\u[0-9A-Fa-f]{4}'\n                  + '|\\\\\\\\x[0-9A-Fa-f]{2}'\n                  + '|\\\\\\\\[0-3][0-7]{0,2}'\n                  + '|\\\\\\\\[0-7]{1,2}'\n                  + '|\\\\\\\\[\\\\s\\\\S]'\n                  + '|-'\n                  + '|[^-\\\\\\\\]',\n                  'g'));\n          var ranges = [];\n          var inverse = charsetParts[0] === '^';\n      \n          var out = ['['];\n          if (inverse) { out.push('^'); }\n      \n          for (var i = inverse ? 1 : 0, n = charsetParts.length; i < n; ++i) {\n            var p = charsetParts[i];\n            if (/\\\\[bdsw]/i.test(p)) {  // Don't muck with named groups.\n              out.push(p);\n            } else {\n              var start = decodeEscape(p);\n              var end;\n              if (i + 2 < n && '-' === charsetParts[i + 1]) {\n                end = decodeEscape(charsetParts[i + 2]);\n                i += 2;\n              } else {\n                end = start;\n              }\n              ranges.push([start, end]);\n              // If the range might intersect letters, then expand it.\n              // This case handling is too simplistic.\n              // It does not deal with non-latin case folding.\n              // It works for latin source code identifiers though.\n              if (!(end < 65 || start > 122)) {\n                if (!(end < 65 || start > 90)) {\n                  ranges.push([Math.max(65, start) | 32, Math.min(end, 90) | 32]);\n                }\n                if (!(end < 97 || start > 122)) {\n                  ranges.push([Math.max(97, start) & ~32, Math.min(end, 122) & ~32]);\n                }\n              }\n            }\n          }\n      \n          // [[1, 10], [3, 4], [8, 12], [14, 14], [16, 16], [17, 17]]\n          // -> [[1, 12], [14, 14], [16, 17]]\n          ranges.sort(function (a, b) { return (a[0] - b[0]) || (b[1]  - a[1]); });\n          var consolidatedRanges = [];\n          var lastRange = [];\n          for (var i = 0; i < ranges.length; ++i) {\n            var range = ranges[i];\n            if (range[0] <= lastRange[1] + 1) {\n              lastRange[1] = Math.max(lastRange[1], range[1]);\n            } else {\n              consolidatedRanges.push(lastRange = range);\n            }\n          }\n      \n          for (var i = 0; i < consolidatedRanges.length; ++i) {\n            var range = consolidatedRanges[i];\n            out.push(encodeEscape(range[0]));\n            if (range[1] > range[0]) {\n              if (range[1] + 1 > range[0]) { out.push('-'); }\n              out.push(encodeEscape(range[1]));\n            }\n          }\n          out.push(']');\n          return out.join('');\n        }\n      \n        function allowAnywhereFoldCaseAndRenumberGroups(regex) {\n          // Split into character sets, escape sequences, punctuation strings\n          // like ('(', '(?:', ')', '^'), and runs of characters that do not\n          // include any of the above.\n          var parts = regex.source.match(\n              new RegExp(\n                  '(?:'\n                  + '\\\\[(?:[^\\\\x5C\\\\x5D]|\\\\\\\\[\\\\s\\\\S])*\\\\]'  // a character set\n                  + '|\\\\\\\\u[A-Fa-f0-9]{4}'  // a unicode escape\n                  + '|\\\\\\\\x[A-Fa-f0-9]{2}'  // a hex escape\n                  + '|\\\\\\\\[0-9]+'  // a back-reference or octal escape\n                  + '|\\\\\\\\[^ux0-9]'  // other escape sequence\n                  + '|\\\\(\\\\?[:!=]'  // start of a non-capturing group\n                  + '|[\\\\(\\\\)\\\\^]'  // start/end of a group, or line start\n                  + '|[^\\\\x5B\\\\x5C\\\\(\\\\)\\\\^]+'  // run of other characters\n                  + ')',\n                  'g'));\n          var n = parts.length;\n      \n          // Maps captured group numbers to the number they will occupy in\n          // the output or to -1 if that has not been determined, or to\n          // undefined if they need not be capturing in the output.\n          var capturedGroups = [];\n      \n          // Walk over and identify back references to build the capturedGroups\n          // mapping.\n          for (var i = 0, groupIndex = 0; i < n; ++i) {\n            var p = parts[i];\n            if (p === '(') {\n              // groups are 1-indexed, so max group index is count of '('\n              ++groupIndex;\n            } else if ('\\\\' === p.charAt(0)) {\n              var decimalValue = +p.substring(1);\n              if (decimalValue) {\n                if (decimalValue <= groupIndex) {\n                  capturedGroups[decimalValue] = -1;\n                } else {\n                  // Replace with an unambiguous escape sequence so that\n                  // an octal escape sequence does not turn into a backreference\n                  // to a capturing group from an earlier regex.\n                  parts[i] = encodeEscape(decimalValue);\n                }\n              }\n            }\n          }\n      \n          // Renumber groups and reduce capturing groups to non-capturing groups\n          // where possible.\n          for (var i = 1; i < capturedGroups.length; ++i) {\n            if (-1 === capturedGroups[i]) {\n              capturedGroups[i] = ++capturedGroupIndex;\n            }\n          }\n          for (var i = 0, groupIndex = 0; i < n; ++i) {\n            var p = parts[i];\n            if (p === '(') {\n              ++groupIndex;\n              if (!capturedGroups[groupIndex]) {\n                parts[i] = '(?:';\n              }\n            } else if ('\\\\' === p.charAt(0)) {\n              var decimalValue = +p.substring(1);\n              if (decimalValue && decimalValue <= groupIndex) {\n                parts[i] = '\\\\' + capturedGroups[decimalValue];\n              }\n            }\n          }\n      \n          // Remove any prefix anchors so that the output will match anywhere.\n          // ^^ really does mean an anchored match though.\n          for (var i = 0; i < n; ++i) {\n            if ('^' === parts[i] && '^' !== parts[i + 1]) { parts[i] = ''; }\n          }\n      \n          // Expand letters to groups to handle mixing of case-sensitive and\n          // case-insensitive patterns if necessary.\n          if (regex.ignoreCase && needToFoldCase) {\n            for (var i = 0; i < n; ++i) {\n              var p = parts[i];\n              var ch0 = p.charAt(0);\n              if (p.length >= 2 && ch0 === '[') {\n                parts[i] = caseFoldCharset(p);\n              } else if (ch0 !== '\\\\') {\n                // TODO: handle letters in numeric escapes.\n                parts[i] = p.replace(\n                    /[a-zA-Z]/g,\n                    function (ch) {\n                      var cc = ch.charCodeAt(0);\n                      return '[' + String.fromCharCode(cc & ~32, cc | 32) + ']';\n                    });\n              }\n            }\n          }\n      \n          return parts.join('');\n        }\n      \n        var rewritten = [];\n        for (var i = 0, n = regexs.length; i < n; ++i) {\n          var regex = regexs[i];\n          if (regex.global || regex.multiline) { throw new Error('' + regex); }\n          rewritten.push(\n              '(?:' + allowAnywhereFoldCaseAndRenumberGroups(regex) + ')');\n        }\n      \n        return new RegExp(rewritten.join('|'), ignoreCase ? 'gi' : 'g');\n      }\n    \n      /**\n       * Split markup into a string of source code and an array mapping ranges in\n       * that string to the text nodes in which they appear.\n       *\n       * <p>\n       * The HTML DOM structure:</p>\n       * <pre>\n       * (Element   \"p\"\n       *   (Element \"b\"\n       *     (Text  \"print \"))       ; #1\n       *   (Text    \"'Hello '\")      ; #2\n       *   (Element \"br\")            ; #3\n       *   (Text    \"  + 'World';\")) ; #4\n       * </pre>\n       * <p>\n       * corresponds to the HTML\n       * {@code <p><b>print </b>'Hello '<br>  + 'World';</p>}.</p>\n       *\n       * <p>\n       * It will produce the output:</p>\n       * <pre>\n       * {\n       *   sourceCode: \"print 'Hello '\\n  + 'World';\",\n       *   //                     1          2\n       *   //           012345678901234 5678901234567\n       *   spans: [0, #1, 6, #2, 14, #3, 15, #4]\n       * }\n       * </pre>\n       * <p>\n       * where #1 is a reference to the {@code \"print \"} text node above, and so\n       * on for the other text nodes.\n       * </p>\n       *\n       * <p>\n       * The {@code} spans array is an array of pairs.  Even elements are the start\n       * indices of substrings, and odd elements are the text nodes (or BR elements)\n       * that contain the text for those substrings.\n       * Substrings continue until the next index or the end of the source.\n       * </p>\n       *\n       * @param {Node} node an HTML DOM subtree containing source-code.\n       * @param {boolean} isPreformatted true if white-space in text nodes should\n       *    be considered significant.\n       * @return {Object} source code and the text nodes in which they occur.\n       */\n      function extractSourceSpans(node, isPreformatted) {\n        var nocode = /(?:^|\\s)nocode(?:\\s|$)/;\n      \n        var chunks = [];\n        var length = 0;\n        var spans = [];\n        var k = 0;\n      \n        function walk(node) {\n          var type = node.nodeType;\n          if (type == 1) {  // Element\n            if (nocode.test(node.className)) { return; }\n            for (var child = node.firstChild; child; child = child.nextSibling) {\n              walk(child);\n            }\n            var nodeName = node.nodeName.toLowerCase();\n            if ('br' === nodeName || 'li' === nodeName) {\n              chunks[k] = '\\n';\n              spans[k << 1] = length++;\n              spans[(k++ << 1) | 1] = node;\n            }\n          } else if (type == 3 || type == 4) {  // Text\n            var text = node.nodeValue;\n            if (text.length) {\n              if (!isPreformatted) {\n                text = text.replace(/[ \\t\\r\\n]+/g, ' ');\n              } else {\n                text = text.replace(/\\r\\n?/g, '\\n');  // Normalize newlines.\n              }\n              // TODO: handle tabs here?\n              chunks[k] = text;\n              spans[k << 1] = length;\n              length += text.length;\n              spans[(k++ << 1) | 1] = node;\n            }\n          }\n        }\n      \n        walk(node);\n      \n        return {\n          sourceCode: chunks.join('').replace(/\\n$/, ''),\n          spans: spans\n        };\n      }\n    \n      /**\n       * Apply the given language handler to sourceCode and add the resulting\n       * decorations to out.\n       * @param {number} basePos the index of sourceCode within the chunk of source\n       *    whose decorations are already present on out.\n       */\n      function appendDecorations(basePos, sourceCode, langHandler, out) {\n        if (!sourceCode) { return; }\n        var job = {\n          sourceCode: sourceCode,\n          basePos: basePos\n        };\n        langHandler(job);\n        out.push.apply(out, job.decorations);\n      }\n    \n      var notWs = /\\S/;\n    \n      /**\n       * Given an element, if it contains only one child element and any text nodes\n       * it contains contain only space characters, return the sole child element.\n       * Otherwise returns undefined.\n       * <p>\n       * This is meant to return the CODE element in {@code <pre><code ...>} when\n       * there is a single child element that contains all the non-space textual\n       * content, but not to return anything where there are multiple child elements\n       * as in {@code <pre><code>...</code><code>...</code></pre>} or when there\n       * is textual content.\n       */\n      function childContentWrapper(element) {\n        var wrapper = undefined;\n        for (var c = element.firstChild; c; c = c.nextSibling) {\n          var type = c.nodeType;\n          wrapper = (type === 1)  // Element Node\n              ? (wrapper ? element : c)\n              : (type === 3)  // Text Node\n              ? (notWs.test(c.nodeValue) ? element : wrapper)\n              : wrapper;\n        }\n        return wrapper === element ? undefined : wrapper;\n      }\n    \n      /** Given triples of [style, pattern, context] returns a lexing function,\n        * The lexing function interprets the patterns to find token boundaries and\n        * returns a decoration list of the form\n        * [index_0, style_0, index_1, style_1, ..., index_n, style_n]\n        * where index_n is an index into the sourceCode, and style_n is a style\n        * constant like PR_PLAIN.  index_n-1 <= index_n, and style_n-1 applies to\n        * all characters in sourceCode[index_n-1:index_n].\n        *\n        * The stylePatterns is a list whose elements have the form\n        * [style : string, pattern : RegExp, DEPRECATED, shortcut : string].\n        *\n        * Style is a style constant like PR_PLAIN, or can be a string of the\n        * form 'lang-FOO', where FOO is a language extension describing the\n        * language of the portion of the token in $1 after pattern executes.\n        * E.g., if style is 'lang-lisp', and group 1 contains the text\n        * '(hello (world))', then that portion of the token will be passed to the\n        * registered lisp handler for formatting.\n        * The text before and after group 1 will be restyled using this decorator\n        * so decorators should take care that this doesn't result in infinite\n        * recursion.  For example, the HTML lexer rule for SCRIPT elements looks\n        * something like ['lang-js', /<[s]cript>(.+?)<\\/script>/].  This may match\n        * '<script>foo()<\\/script>', which would cause the current decorator to\n        * be called with '<script>' which would not match the same rule since\n        * group 1 must not be empty, so it would be instead styled as PR_TAG by\n        * the generic tag rule.  The handler registered for the 'js' extension would\n        * then be called with 'foo()', and finally, the current decorator would\n        * be called with '<\\/script>' which would not match the original rule and\n        * so the generic tag rule would identify it as a tag.\n        *\n        * Pattern must only match prefixes, and if it matches a prefix, then that\n        * match is considered a token with the same style.\n        *\n        * Context is applied to the last non-whitespace, non-comment token\n        * recognized.\n        *\n        * Shortcut is an optional string of characters, any of which, if the first\n        * character, gurantee that this pattern and only this pattern matches.\n        *\n        * @param {Array} shortcutStylePatterns patterns that always start with\n        *   a known character.  Must have a shortcut string.\n        * @param {Array} fallthroughStylePatterns patterns that will be tried in\n        *   order if the shortcut ones fail.  May have shortcuts.\n        *\n        * @return {function (Object)} a\n        *   function that takes source code and returns a list of decorations.\n        */\n      function createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns) {\n        var shortcuts = {};\n        var tokenizer;\n        (function () {\n          var allPatterns = shortcutStylePatterns.concat(fallthroughStylePatterns);\n          var allRegexs = [];\n          var regexKeys = {};\n          for (var i = 0, n = allPatterns.length; i < n; ++i) {\n            var patternParts = allPatterns[i];\n            var shortcutChars = patternParts[3];\n            if (shortcutChars) {\n              for (var c = shortcutChars.length; --c >= 0;) {\n                shortcuts[shortcutChars.charAt(c)] = patternParts;\n              }\n            }\n            var regex = patternParts[1];\n            var k = '' + regex;\n            if (!regexKeys.hasOwnProperty(k)) {\n              allRegexs.push(regex);\n              regexKeys[k] = null;\n            }\n          }\n          allRegexs.push(/[\\0-\\uffff]/);\n          tokenizer = combinePrefixPatterns(allRegexs);\n        })();\n    \n        var nPatterns = fallthroughStylePatterns.length;\n    \n        /**\n         * Lexes job.sourceCode and produces an output array job.decorations of\n         * style classes preceded by the position at which they start in\n         * job.sourceCode in order.\n         *\n         * @param {Object} job an object like <pre>{\n         *    sourceCode: {string} sourceText plain text,\n         *    basePos: {int} position of job.sourceCode in the larger chunk of\n         *        sourceCode.\n         * }</pre>\n         */\n        var decorate = function (job) {\n          var sourceCode = job.sourceCode, basePos = job.basePos;\n          /** Even entries are positions in source in ascending order.  Odd enties\n            * are style markers (e.g., PR_COMMENT) that run from that position until\n            * the end.\n            * @type {Array.<number|string>}\n            */\n          var decorations = [basePos, PR_PLAIN];\n          var pos = 0;  // index into sourceCode\n          var tokens = sourceCode.match(tokenizer) || [];\n          var styleCache = {};\n    \n          for (var ti = 0, nTokens = tokens.length; ti < nTokens; ++ti) {\n            var token = tokens[ti];\n            var style = styleCache[token];\n            var match = void 0;\n    \n            var isEmbedded;\n            if (typeof style === 'string') {\n              isEmbedded = false;\n            } else {\n              var patternParts = shortcuts[token.charAt(0)];\n              if (patternParts) {\n                match = token.match(patternParts[1]);\n                style = patternParts[0];\n              } else {\n                for (var i = 0; i < nPatterns; ++i) {\n                  patternParts = fallthroughStylePatterns[i];\n                  match = token.match(patternParts[1]);\n                  if (match) {\n                    style = patternParts[0];\n                    break;\n                  }\n                }\n    \n                if (!match) {  // make sure that we make progress\n                  style = PR_PLAIN;\n                }\n              }\n    \n              isEmbedded = style.length >= 5 && 'lang-' === style.substring(0, 5);\n              if (isEmbedded && !(match && typeof match[1] === 'string')) {\n                isEmbedded = false;\n                style = PR_SOURCE;\n              }\n    \n              if (!isEmbedded) { styleCache[token] = style; }\n            }\n    \n            var tokenStart = pos;\n            pos += token.length;\n    \n            if (!isEmbedded) {\n              decorations.push(basePos + tokenStart, style);\n            } else {  // Treat group 1 as an embedded block of source code.\n              var embeddedSource = match[1];\n              var embeddedSourceStart = token.indexOf(embeddedSource);\n              var embeddedSourceEnd = embeddedSourceStart + embeddedSource.length;\n              if (match[2]) {\n                // If embeddedSource can be blank, then it would match at the\n                // beginning which would cause us to infinitely recurse on the\n                // entire token, so we catch the right context in match[2].\n                embeddedSourceEnd = token.length - match[2].length;\n                embeddedSourceStart = embeddedSourceEnd - embeddedSource.length;\n              }\n              var lang = style.substring(5);\n              // Decorate the left of the embedded source\n              appendDecorations(\n                  basePos + tokenStart,\n                  token.substring(0, embeddedSourceStart),\n                  decorate, decorations);\n              // Decorate the embedded source\n              appendDecorations(\n                  basePos + tokenStart + embeddedSourceStart,\n                  embeddedSource,\n                  langHandlerForExtension(lang, embeddedSource),\n                  decorations);\n              // Decorate the right of the embedded section\n              appendDecorations(\n                  basePos + tokenStart + embeddedSourceEnd,\n                  token.substring(embeddedSourceEnd),\n                  decorate, decorations);\n            }\n          }\n          job.decorations = decorations;\n        };\n        return decorate;\n      }\n    \n      /** returns a function that produces a list of decorations from source text.\n        *\n        * This code treats \", ', and ` as string delimiters, and \\ as a string\n        * escape.  It does not recognize perl's qq() style strings.\n        * It has no special handling for double delimiter escapes as in basic, or\n        * the tripled delimiters used in python, but should work on those regardless\n        * although in those cases a single string literal may be broken up into\n        * multiple adjacent string literals.\n        *\n        * It recognizes C, C++, and shell style comments.\n        *\n        * @param {Object} options a set of optional parameters.\n        * @return {function (Object)} a function that examines the source code\n        *     in the input job and builds the decoration list.\n        */\n      function sourceDecorator(options) {\n        var shortcutStylePatterns = [], fallthroughStylePatterns = [];\n        if (options['tripleQuotedStrings']) {\n          // '''multi-line-string''', 'single-line-string', and double-quoted\n          shortcutStylePatterns.push(\n              [PR_STRING,  /^(?:\\'\\'\\'(?:[^\\'\\\\]|\\\\[\\s\\S]|\\'{1,2}(?=[^\\']))*(?:\\'\\'\\'|$)|\\\"\\\"\\\"(?:[^\\\"\\\\]|\\\\[\\s\\S]|\\\"{1,2}(?=[^\\\"]))*(?:\\\"\\\"\\\"|$)|\\'(?:[^\\\\\\']|\\\\[\\s\\S])*(?:\\'|$)|\\\"(?:[^\\\\\\\"]|\\\\[\\s\\S])*(?:\\\"|$))/,\n               null, '\\'\"']);\n        } else if (options['multiLineStrings']) {\n          // 'multi-line-string', \"multi-line-string\"\n          shortcutStylePatterns.push(\n              [PR_STRING,  /^(?:\\'(?:[^\\\\\\']|\\\\[\\s\\S])*(?:\\'|$)|\\\"(?:[^\\\\\\\"]|\\\\[\\s\\S])*(?:\\\"|$)|\\`(?:[^\\\\\\`]|\\\\[\\s\\S])*(?:\\`|$))/,\n               null, '\\'\"`']);\n        } else {\n          // 'single-line-string', \"single-line-string\"\n          shortcutStylePatterns.push(\n              [PR_STRING,\n               /^(?:\\'(?:[^\\\\\\'\\r\\n]|\\\\.)*(?:\\'|$)|\\\"(?:[^\\\\\\\"\\r\\n]|\\\\.)*(?:\\\"|$))/,\n               null, '\"\\'']);\n        }\n        if (options['verbatimStrings']) {\n          // verbatim-string-literal production from the C# grammar.  See issue 93.\n          fallthroughStylePatterns.push(\n              [PR_STRING, /^@\\\"(?:[^\\\"]|\\\"\\\")*(?:\\\"|$)/, null]);\n        }\n        var hc = options['hashComments'];\n        if (hc) {\n          if (options['cStyleComments']) {\n            if (hc > 1) {  // multiline hash comments\n              shortcutStylePatterns.push(\n                  [PR_COMMENT, /^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/, null, '#']);\n            } else {\n              // Stop C preprocessor declarations at an unclosed open comment\n              shortcutStylePatterns.push(\n                  [PR_COMMENT, /^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\\b|[^\\r\\n]*)/,\n                   null, '#']);\n            }\n            // #include <stdio.h>\n            fallthroughStylePatterns.push(\n                [PR_STRING,\n                 /^<(?:(?:(?:\\.\\.\\/)*|\\/?)(?:[\\w-]+(?:\\/[\\w-]+)+)?[\\w-]+\\.h(?:h|pp|\\+\\+)?|[a-z]\\w*)>/,\n                 null]);\n          } else {\n            shortcutStylePatterns.push([PR_COMMENT, /^#[^\\r\\n]*/, null, '#']);\n          }\n        }\n        if (options['cStyleComments']) {\n          fallthroughStylePatterns.push([PR_COMMENT, /^\\/\\/[^\\r\\n]*/, null]);\n          fallthroughStylePatterns.push(\n              [PR_COMMENT, /^\\/\\*[\\s\\S]*?(?:\\*\\/|$)/, null]);\n        }\n        var regexLiterals = options['regexLiterals'];\n        if (regexLiterals) {\n          /**\n           * @const\n           */\n          var regexExcls = regexLiterals > 1\n            ? ''  // Multiline regex literals\n            : '\\n\\r';\n          /**\n           * @const\n           */\n          var regexAny = regexExcls ? '.' : '[\\\\S\\\\s]';\n          /**\n           * @const\n           */\n          var REGEX_LITERAL = (\n              // A regular expression literal starts with a slash that is\n              // not followed by * or / so that it is not confused with\n              // comments.\n              '/(?=[^/*' + regexExcls + '])'\n              // and then contains any number of raw characters,\n              + '(?:[^/\\\\x5B\\\\x5C' + regexExcls + ']'\n              // escape sequences (\\x5C),\n              +    '|\\\\x5C' + regexAny\n              // or non-nesting character sets (\\x5B\\x5D);\n              +    '|\\\\x5B(?:[^\\\\x5C\\\\x5D' + regexExcls + ']'\n              +             '|\\\\x5C' + regexAny + ')*(?:\\\\x5D|$))+'\n              // finally closed by a /.\n              + '/');\n          fallthroughStylePatterns.push(\n              ['lang-regex',\n               RegExp('^' + REGEXP_PRECEDER_PATTERN + '(' + REGEX_LITERAL + ')')\n               ]);\n        }\n    \n        var types = options['types'];\n        if (types) {\n          fallthroughStylePatterns.push([PR_TYPE, types]);\n        }\n    \n        var keywords = (\"\" + options['keywords']).replace(/^ | $/g, '');\n        if (keywords.length) {\n          fallthroughStylePatterns.push(\n              [PR_KEYWORD,\n               new RegExp('^(?:' + keywords.replace(/[\\s,]+/g, '|') + ')\\\\b'),\n               null]);\n        }\n    \n        shortcutStylePatterns.push([PR_PLAIN,       /^\\s+/, null, ' \\r\\n\\t\\xA0']);\n    \n        var punctuation =\n          // The Bash man page says\n    \n          // A word is a sequence of characters considered as a single\n          // unit by GRUB. Words are separated by metacharacters,\n          // which are the following plus space, tab, and newline: { }\n          // | & $ ; < >\n          // ...\n          \n          // A word beginning with # causes that word and all remaining\n          // characters on that line to be ignored.\n    \n          // which means that only a '#' after /(?:^|[{}|&$;<>\\s])/ starts a\n          // comment but empirically\n          // $ echo {#}\n          // {#}\n          // $ echo \\$#\n          // $#\n          // $ echo }#\n          // }#\n    \n          // so /(?:^|[|&;<>\\s])/ is more appropriate.\n    \n          // http://gcc.gnu.org/onlinedocs/gcc-2.95.3/cpp_1.html#SEC3\n          // suggests that this definition is compatible with a\n          // default mode that tries to use a single token definition\n          // to recognize both bash/python style comments and C\n          // preprocessor directives.\n    \n          // This definition of punctuation does not include # in the list of\n          // follow-on exclusions, so # will not be broken before if preceeded\n          // by a punctuation character.  We could try to exclude # after\n          // [|&;<>] but that doesn't seem to cause many major problems.\n          // If that does turn out to be a problem, we should change the below\n          // when hc is truthy to include # in the run of punctuation characters\n          // only when not followint [|&;<>].\n          '^.[^\\\\s\\\\w.$@\\'\"`/\\\\\\\\]*';\n        if (options['regexLiterals']) {\n          punctuation += '(?!\\s*\\/)';\n        }\n    \n        fallthroughStylePatterns.push(\n            // TODO(mikesamuel): recognize non-latin letters and numerals in idents\n            [PR_LITERAL,     /^@[a-z_$][a-z_$@0-9]*/i, null],\n            [PR_TYPE,        /^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\\w+_t\\b)/, null],\n            [PR_PLAIN,       /^[a-z_$][a-z_$@0-9]*/i, null],\n            [PR_LITERAL,\n             new RegExp(\n                 '^(?:'\n                 // A hex number\n                 + '0x[a-f0-9]+'\n                 // or an octal or decimal number,\n                 + '|(?:\\\\d(?:_\\\\d+)*\\\\d*(?:\\\\.\\\\d*)?|\\\\.\\\\d\\\\+)'\n                 // possibly in scientific notation\n                 + '(?:e[+\\\\-]?\\\\d+)?'\n                 + ')'\n                 // with an optional modifier like UL for unsigned long\n                 + '[a-z]*', 'i'),\n             null, '0123456789'],\n            // Don't treat escaped quotes in bash as starting strings.\n            // See issue 144.\n            [PR_PLAIN,       /^\\\\[\\s\\S]?/, null],\n            [PR_PUNCTUATION, new RegExp(punctuation), null]);\n    \n        return createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns);\n      }\n    \n      var decorateSource = sourceDecorator({\n            'keywords': ALL_KEYWORDS,\n            'hashComments': true,\n            'cStyleComments': true,\n            'multiLineStrings': true,\n            'regexLiterals': true\n          });\n    \n      /**\n       * Given a DOM subtree, wraps it in a list, and puts each line into its own\n       * list item.\n       *\n       * @param {Node} node modified in place.  Its content is pulled into an\n       *     HTMLOListElement, and each line is moved into a separate list item.\n       *     This requires cloning elements, so the input might not have unique\n       *     IDs after numbering.\n       * @param {boolean} isPreformatted true iff white-space in text nodes should\n       *     be treated as significant.\n       */\n      function numberLines(node, opt_startLineNum, isPreformatted) {\n        var nocode = /(?:^|\\s)nocode(?:\\s|$)/;\n        var lineBreak = /\\r\\n?|\\n/;\n      \n        var document = node.ownerDocument;\n      \n        var li = document.createElement('li');\n        while (node.firstChild) {\n          li.appendChild(node.firstChild);\n        }\n        // An array of lines.  We split below, so this is initialized to one\n        // un-split line.\n        var listItems = [li];\n      \n        function walk(node) {\n          var type = node.nodeType;\n          if (type == 1 && !nocode.test(node.className)) {  // Element\n            if ('br' === node.nodeName) {\n              breakAfter(node);\n              // Discard the <BR> since it is now flush against a </LI>.\n              if (node.parentNode) {\n                node.parentNode.removeChild(node);\n              }\n            } else {\n              for (var child = node.firstChild; child; child = child.nextSibling) {\n                walk(child);\n              }\n            }\n          } else if ((type == 3 || type == 4) && isPreformatted) {  // Text\n            var text = node.nodeValue;\n            var match = text.match(lineBreak);\n            if (match) {\n              var firstLine = text.substring(0, match.index);\n              node.nodeValue = firstLine;\n              var tail = text.substring(match.index + match[0].length);\n              if (tail) {\n                var parent = node.parentNode;\n                parent.insertBefore(\n                  document.createTextNode(tail), node.nextSibling);\n              }\n              breakAfter(node);\n              if (!firstLine) {\n                // Don't leave blank text nodes in the DOM.\n                node.parentNode.removeChild(node);\n              }\n            }\n          }\n        }\n      \n        // Split a line after the given node.\n        function breakAfter(lineEndNode) {\n          // If there's nothing to the right, then we can skip ending the line\n          // here, and move root-wards since splitting just before an end-tag\n          // would require us to create a bunch of empty copies.\n          while (!lineEndNode.nextSibling) {\n            lineEndNode = lineEndNode.parentNode;\n            if (!lineEndNode) { return; }\n          }\n      \n          function breakLeftOf(limit, copy) {\n            // Clone shallowly if this node needs to be on both sides of the break.\n            var rightSide = copy ? limit.cloneNode(false) : limit;\n            var parent = limit.parentNode;\n            if (parent) {\n              // We clone the parent chain.\n              // This helps us resurrect important styling elements that cross lines.\n              // E.g. in <i>Foo<br>Bar</i>\n              // should be rewritten to <li><i>Foo</i></li><li><i>Bar</i></li>.\n              var parentClone = breakLeftOf(parent, 1);\n              // Move the clone and everything to the right of the original\n              // onto the cloned parent.\n              var next = limit.nextSibling;\n              parentClone.appendChild(rightSide);\n              for (var sibling = next; sibling; sibling = next) {\n                next = sibling.nextSibling;\n                parentClone.appendChild(sibling);\n              }\n            }\n            return rightSide;\n          }\n      \n          var copiedListItem = breakLeftOf(lineEndNode.nextSibling, 0);\n      \n          // Walk the parent chain until we reach an unattached LI.\n          for (var parent;\n               // Check nodeType since IE invents document fragments.\n               (parent = copiedListItem.parentNode) && parent.nodeType === 1;) {\n            copiedListItem = parent;\n          }\n          // Put it on the list of lines for later processing.\n          listItems.push(copiedListItem);\n        }\n      \n        // Split lines while there are lines left to split.\n        for (var i = 0;  // Number of lines that have been split so far.\n             i < listItems.length;  // length updated by breakAfter calls.\n             ++i) {\n          walk(listItems[i]);\n        }\n      \n        // Make sure numeric indices show correctly.\n        if (opt_startLineNum === (opt_startLineNum|0)) {\n          listItems[0].setAttribute('value', opt_startLineNum);\n        }\n      \n        var ol = document.createElement('ol');\n        ol.className = 'linenums';\n        var offset = Math.max(0, ((opt_startLineNum - 1 /* zero index */)) | 0) || 0;\n        for (var i = 0, n = listItems.length; i < n; ++i) {\n          li = listItems[i];\n          // Stick a class on the LIs so that stylesheets can\n          // color odd/even rows, or any other row pattern that\n          // is co-prime with 10.\n          li.className = 'L' + ((i + offset) % 10);\n          if (!li.firstChild) {\n            li.appendChild(document.createTextNode('\\xA0'));\n          }\n          ol.appendChild(li);\n        }\n      \n        node.appendChild(ol);\n      }    \n      /**\n       * Breaks {@code job.sourceCode} around style boundaries in\n       * {@code job.decorations} and modifies {@code job.sourceNode} in place.\n       * @param {Object} job like <pre>{\n       *    sourceCode: {string} source as plain text,\n       *    sourceNode: {HTMLElement} the element containing the source,\n       *    spans: {Array.<number|Node>} alternating span start indices into source\n       *       and the text node or element (e.g. {@code <BR>}) corresponding to that\n       *       span.\n       *    decorations: {Array.<number|string} an array of style classes preceded\n       *       by the position at which they start in job.sourceCode in order\n       * }</pre>\n       * @private\n       */\n      function recombineTagsAndDecorations(job) {\n        var isIE8OrEarlier = /\\bMSIE\\s(\\d+)/.exec(navigator.userAgent);\n        isIE8OrEarlier = isIE8OrEarlier && +isIE8OrEarlier[1] <= 8;\n        var newlineRe = /\\n/g;\n      \n        var source = job.sourceCode;\n        var sourceLength = source.length;\n        // Index into source after the last code-unit recombined.\n        var sourceIndex = 0;\n      \n        var spans = job.spans;\n        var nSpans = spans.length;\n        // Index into spans after the last span which ends at or before sourceIndex.\n        var spanIndex = 0;\n      \n        var decorations = job.decorations;\n        var nDecorations = decorations.length;\n        // Index into decorations after the last decoration which ends at or before\n        // sourceIndex.\n        var decorationIndex = 0;\n      \n        // Remove all zero-length decorations.\n        decorations[nDecorations] = sourceLength;\n        var decPos, i;\n        for (i = decPos = 0; i < nDecorations;) {\n          if (decorations[i] !== decorations[i + 2]) {\n            decorations[decPos++] = decorations[i++];\n            decorations[decPos++] = decorations[i++];\n          } else {\n            i += 2;\n          }\n        }\n        nDecorations = decPos;\n      \n        // Simplify decorations.\n        for (i = decPos = 0; i < nDecorations;) {\n          var startPos = decorations[i];\n          // Conflate all adjacent decorations that use the same style.\n          var startDec = decorations[i + 1];\n          var end = i + 2;\n          while (end + 2 <= nDecorations && decorations[end + 1] === startDec) {\n            end += 2;\n          }\n          decorations[decPos++] = startPos;\n          decorations[decPos++] = startDec;\n          i = end;\n        }\n      \n        nDecorations = decorations.length = decPos;\n      \n        var sourceNode = job.sourceNode;\n        var oldDisplay;\n        if (sourceNode) {\n          oldDisplay = sourceNode.style.display;\n          sourceNode.style.display = 'none';\n        }\n        try {\n          var decoration = null;\n          while (spanIndex < nSpans) {\n            var spanStart = spans[spanIndex];\n            var spanEnd = spans[spanIndex + 2] || sourceLength;\n      \n            var decEnd = decorations[decorationIndex + 2] || sourceLength;\n      \n            var end = Math.min(spanEnd, decEnd);\n      \n            var textNode = spans[spanIndex + 1];\n            var styledText;\n            if (textNode.nodeType !== 1  // Don't muck with <BR>s or <LI>s\n                // Don't introduce spans around empty text nodes.\n                && (styledText = source.substring(sourceIndex, end))) {\n              // This may seem bizarre, and it is.  Emitting LF on IE causes the\n              // code to display with spaces instead of line breaks.\n              // Emitting Windows standard issue linebreaks (CRLF) causes a blank\n              // space to appear at the beginning of every line but the first.\n              // Emitting an old Mac OS 9 line separator makes everything spiffy.\n              if (isIE8OrEarlier) {\n                styledText = styledText.replace(newlineRe, '\\r');\n              }\n              textNode.nodeValue = styledText;\n              var document = textNode.ownerDocument;\n              var span = document.createElement('span');\n              span.className = decorations[decorationIndex + 1];\n              var parentNode = textNode.parentNode;\n              parentNode.replaceChild(span, textNode);\n              span.appendChild(textNode);\n              if (sourceIndex < spanEnd) {  // Split off a text node.\n                spans[spanIndex + 1] = textNode\n                    // TODO: Possibly optimize by using '' if there's no flicker.\n                    = document.createTextNode(source.substring(end, spanEnd));\n                parentNode.insertBefore(textNode, span.nextSibling);\n              }\n            }\n      \n            sourceIndex = end;\n      \n            if (sourceIndex >= spanEnd) {\n              spanIndex += 2;\n            }\n            if (sourceIndex >= decEnd) {\n              decorationIndex += 2;\n            }\n          }\n        } finally {\n          if (sourceNode) {\n            sourceNode.style.display = oldDisplay;\n          }\n        }\n      }\n    \n      /** Maps language-specific file extensions to handlers. */\n      var langHandlerRegistry = {};\n      /** Register a language handler for the given file extensions.\n        * @param {function (Object)} handler a function from source code to a list\n        *      of decorations.  Takes a single argument job which describes the\n        *      state of the computation.   The single parameter has the form\n        *      {@code {\n        *        sourceCode: {string} as plain text.\n        *        decorations: {Array.<number|string>} an array of style classes\n        *                     preceded by the position at which they start in\n        *                     job.sourceCode in order.\n        *                     The language handler should assigned this field.\n        *        basePos: {int} the position of source in the larger source chunk.\n        *                 All positions in the output decorations array are relative\n        *                 to the larger source chunk.\n        *      } }\n        * @param {Array.<string>} fileExtensions\n        */\n      function registerLangHandler(handler, fileExtensions) {\n        for (var i = fileExtensions.length; --i >= 0;) {\n          var ext = fileExtensions[i];\n          if (!langHandlerRegistry.hasOwnProperty(ext)) {\n            langHandlerRegistry[ext] = handler;\n          } else if (win['console']) {\n            console['warn']('cannot override language handler %s', ext);\n          }\n        }\n      }\n      function langHandlerForExtension(extension, source) {\n        if (!(extension && langHandlerRegistry.hasOwnProperty(extension))) {\n          // Treat it as markup if the first non whitespace character is a < and\n          // the last non-whitespace character is a >.\n          extension = /^\\s*</.test(source)\n              ? 'default-markup'\n              : 'default-code';\n        }\n        return langHandlerRegistry[extension];\n      }\n      registerLangHandler(decorateSource, ['default-code']);\n      registerLangHandler(\n          createSimpleLexer(\n              [],\n              [\n               [PR_PLAIN,       /^[^<?]+/],\n               [PR_DECLARATION, /^<!\\w[^>]*(?:>|$)/],\n               [PR_COMMENT,     /^<\\!--[\\s\\S]*?(?:-\\->|$)/],\n               // Unescaped content in an unknown language\n               ['lang-',        /^<\\?([\\s\\S]+?)(?:\\?>|$)/],\n               ['lang-',        /^<%([\\s\\S]+?)(?:%>|$)/],\n               [PR_PUNCTUATION, /^(?:<[%?]|[%?]>)/],\n               ['lang-',        /^<xmp\\b[^>]*>([\\s\\S]+?)<\\/xmp\\b[^>]*>/i],\n               // Unescaped content in javascript.  (Or possibly vbscript).\n               ['lang-js',      /^<script\\b[^>]*>([\\s\\S]*?)(<\\/script\\b[^>]*>)/i],\n               // Contains unescaped stylesheet content\n               ['lang-css',     /^<style\\b[^>]*>([\\s\\S]*?)(<\\/style\\b[^>]*>)/i],\n               ['lang-in.tag',  /^(<\\/?[a-z][^<>]*>)/i]\n              ]),\n          ['default-markup', 'htm', 'html', 'mxml', 'xhtml', 'xml', 'xsl']);\n      registerLangHandler(\n          createSimpleLexer(\n              [\n               [PR_PLAIN,        /^[\\s]+/, null, ' \\t\\r\\n'],\n               [PR_ATTRIB_VALUE, /^(?:\\\"[^\\\"]*\\\"?|\\'[^\\']*\\'?)/, null, '\\\"\\'']\n               ],\n              [\n               [PR_TAG,          /^^<\\/?[a-z](?:[\\w.:-]*\\w)?|\\/?>$/i],\n               [PR_ATTRIB_NAME,  /^(?!style[\\s=]|on)[a-z](?:[\\w:-]*\\w)?/i],\n               ['lang-uq.val',   /^=\\s*([^>\\'\\\"\\s]*(?:[^>\\'\\\"\\s\\/]|\\/(?=\\s)))/],\n               [PR_PUNCTUATION,  /^[=<>\\/]+/],\n               ['lang-js',       /^on\\w+\\s*=\\s*\\\"([^\\\"]+)\\\"/i],\n               ['lang-js',       /^on\\w+\\s*=\\s*\\'([^\\']+)\\'/i],\n               ['lang-js',       /^on\\w+\\s*=\\s*([^\\\"\\'>\\s]+)/i],\n               ['lang-css',      /^style\\s*=\\s*\\\"([^\\\"]+)\\\"/i],\n               ['lang-css',      /^style\\s*=\\s*\\'([^\\']+)\\'/i],\n               ['lang-css',      /^style\\s*=\\s*([^\\\"\\'>\\s]+)/i]\n               ]),\n          ['in.tag']);\n      registerLangHandler(\n          createSimpleLexer([], [[PR_ATTRIB_VALUE, /^[\\s\\S]+/]]), ['uq.val']);\n      registerLangHandler(sourceDecorator({\n              'keywords': CPP_KEYWORDS,\n              'hashComments': true,\n              'cStyleComments': true,\n              'types': C_TYPES\n            }), ['c', 'cc', 'cpp', 'cxx', 'cyc', 'm']);\n      registerLangHandler(sourceDecorator({\n              'keywords': 'null,true,false'\n            }), ['json']);\n      registerLangHandler(sourceDecorator({\n              'keywords': CSHARP_KEYWORDS,\n              'hashComments': true,\n              'cStyleComments': true,\n              'verbatimStrings': true,\n              'types': C_TYPES\n            }), ['cs']);\n      registerLangHandler(sourceDecorator({\n              'keywords': JAVA_KEYWORDS,\n              'cStyleComments': true\n            }), ['java']);\n      registerLangHandler(sourceDecorator({\n              'keywords': SH_KEYWORDS,\n              'hashComments': true,\n              'multiLineStrings': true\n            }), ['bash', 'bsh', 'csh', 'sh']);\n      registerLangHandler(sourceDecorator({\n              'keywords': PYTHON_KEYWORDS,\n              'hashComments': true,\n              'multiLineStrings': true,\n              'tripleQuotedStrings': true\n            }), ['cv', 'py', 'python']);\n      registerLangHandler(sourceDecorator({\n              'keywords': PERL_KEYWORDS,\n              'hashComments': true,\n              'multiLineStrings': true,\n              'regexLiterals': 2  // multiline regex literals\n            }), ['perl', 'pl', 'pm']);\n      registerLangHandler(sourceDecorator({\n              'keywords': RUBY_KEYWORDS,\n              'hashComments': true,\n              'multiLineStrings': true,\n              'regexLiterals': true\n            }), ['rb', 'ruby']);\n      registerLangHandler(sourceDecorator({\n              'keywords': JSCRIPT_KEYWORDS,\n              'cStyleComments': true,\n              'regexLiterals': true\n            }), ['javascript', 'js']);\n      registerLangHandler(sourceDecorator({\n              'keywords': COFFEE_KEYWORDS,\n              'hashComments': 3,  // ### style block comments\n              'cStyleComments': true,\n              'multilineStrings': true,\n              'tripleQuotedStrings': true,\n              'regexLiterals': true\n            }), ['coffee']);\n      registerLangHandler(sourceDecorator({\n              'keywords': RUST_KEYWORDS,\n              'cStyleComments': true,\n              'multilineStrings': true\n            }), ['rc', 'rs', 'rust']);\n      registerLangHandler(\n          createSimpleLexer([], [[PR_STRING, /^[\\s\\S]+/]]), ['regex']);\n    \n      function applyDecorator(job) {\n        var opt_langExtension = job.langExtension;\n    \n        try {\n          // Extract tags, and convert the source code to plain text.\n          var sourceAndSpans = extractSourceSpans(job.sourceNode, job.pre);\n          /** Plain text. @type {string} */\n          var source = sourceAndSpans.sourceCode;\n          job.sourceCode = source;\n          job.spans = sourceAndSpans.spans;\n          job.basePos = 0;\n    \n          // Apply the appropriate language handler\n          langHandlerForExtension(opt_langExtension, source)(job);\n    \n          // Integrate the decorations and tags back into the source code,\n          // modifying the sourceNode in place.\n          recombineTagsAndDecorations(job);\n        } catch (e) {\n          if (win['console']) {\n            console['log'](e && e['stack'] || e);\n          }\n        }\n      }\n    \n      /**\n       * Pretty print a chunk of code.\n       * @param sourceCodeHtml {string} The HTML to pretty print.\n       * @param opt_langExtension {string} The language name to use.\n       *     Typically, a filename extension like 'cpp' or 'java'.\n       * @param opt_numberLines {number|boolean} True to number lines,\n       *     or the 1-indexed number of the first line in sourceCodeHtml.\n       */\n      function $prettyPrintOne(sourceCodeHtml, opt_langExtension, opt_numberLines) {\n        var container = document.createElement('div');\n        // This could cause images to load and onload listeners to fire.\n        // E.g. <img onerror=\"alert(1337)\" src=\"nosuchimage.png\">.\n        // We assume that the inner HTML is from a trusted source.\n        // The pre-tag is required for IE8 which strips newlines from innerHTML\n        // when it is injected into a <pre> tag.\n        // http://stackoverflow.com/questions/451486/pre-tag-loses-line-breaks-when-setting-innerhtml-in-ie\n        // http://stackoverflow.com/questions/195363/inserting-a-newline-into-a-pre-tag-ie-javascript\n        container.innerHTML = '<pre>' + sourceCodeHtml + '</pre>';\n        container = container.firstChild;\n        if (opt_numberLines) {\n          numberLines(container, opt_numberLines, true);\n        }\n    \n        var job = {\n          langExtension: opt_langExtension,\n          numberLines: opt_numberLines,\n          sourceNode: container,\n          pre: 1\n        };\n        applyDecorator(job);\n        return container.innerHTML;\n      }\n    \n       /**\n        * Find all the {@code <pre>} and {@code <code>} tags in the DOM with\n        * {@code class=prettyprint} and prettify them.\n        *\n        * @param {Function} opt_whenDone called when prettifying is done.\n        * @param {HTMLElement|HTMLDocument} opt_root an element or document\n        *   containing all the elements to pretty print.\n        *   Defaults to {@code document.body}.\n        */\n      function $prettyPrint(opt_whenDone, opt_root) {\n        var root = opt_root || document.body;\n        var doc = root.ownerDocument || document;\n        function byTagName(tn) { return root.getElementsByTagName(tn); }\n        // fetch a list of nodes to rewrite\n        var codeSegments = [byTagName('pre'), byTagName('code'), byTagName('xmp')];\n        var elements = [];\n        for (var i = 0; i < codeSegments.length; ++i) {\n          for (var j = 0, n = codeSegments[i].length; j < n; ++j) {\n            elements.push(codeSegments[i][j]);\n          }\n        }\n        codeSegments = null;\n    \n        var clock = Date;\n        if (!clock['now']) {\n          clock = { 'now': function () { return +(new Date); } };\n        }\n    \n        // The loop is broken into a series of continuations to make sure that we\n        // don't make the browser unresponsive when rewriting a large page.\n        var k = 0;\n        var prettyPrintingJob;\n    \n        var langExtensionRe = /\\blang(?:uage)?-([\\w.]+)(?!\\S)/;\n        var prettyPrintRe = /\\bprettyprint\\b/;\n        var prettyPrintedRe = /\\bprettyprinted\\b/;\n        var preformattedTagNameRe = /pre|xmp/i;\n        var codeRe = /^code$/i;\n        var preCodeXmpRe = /^(?:pre|code|xmp)$/i;\n        var EMPTY = {};\n    \n        function doWork() {\n          var endTime = (win['PR_SHOULD_USE_CONTINUATION'] ?\n                         clock['now']() + 250 /* ms */ :\n                         Infinity);\n          for (; k < elements.length && clock['now']() < endTime; k++) {\n            var cs = elements[k];\n    \n            // Look for a preceding comment like\n            // <?prettify lang=\"...\" linenums=\"...\"?>\n            var attrs = EMPTY;\n            {\n              for (var preceder = cs; (preceder = preceder.previousSibling);) {\n                var nt = preceder.nodeType;\n                // <?foo?> is parsed by HTML 5 to a comment node (8)\n                // like <!--?foo?-->, but in XML is a processing instruction\n                var value = (nt === 7 || nt === 8) && preceder.nodeValue;\n                if (value\n                    ? !/^\\??prettify\\b/.test(value)\n                    : (nt !== 3 || /\\S/.test(preceder.nodeValue))) {\n                  // Skip over white-space text nodes but not others.\n                  break;\n                }\n                if (value) {\n                  attrs = {};\n                  value.replace(\n                      /\\b(\\w+)=([\\w:.%+-]+)/g,\n                    function (_, name, value) { attrs[name] = value; });\n                  break;\n                }\n              }\n            }\n    \n            var className = cs.className;\n            if ((attrs !== EMPTY || prettyPrintRe.test(className))\n                // Don't redo this if we've already done it.\n                // This allows recalling pretty print to just prettyprint elements\n                // that have been added to the page since last call.\n                && !prettyPrintedRe.test(className)) {\n    \n              // make sure this is not nested in an already prettified element\n              var nested = false;\n              for (var p = cs.parentNode; p; p = p.parentNode) {\n                var tn = p.tagName;\n                if (preCodeXmpRe.test(tn)\n                    && p.className && prettyPrintRe.test(p.className)) {\n                  nested = true;\n                  break;\n                }\n              }\n              if (!nested) {\n                // Mark done.  If we fail to prettyprint for whatever reason,\n                // we shouldn't try again.\n                cs.className += ' prettyprinted';\n    \n                // If the classes includes a language extensions, use it.\n                // Language extensions can be specified like\n                //     <pre class=\"prettyprint lang-cpp\">\n                // the language extension \"cpp\" is used to find a language handler\n                // as passed to PR.registerLangHandler.\n                // HTML5 recommends that a language be specified using \"language-\"\n                // as the prefix instead.  Google Code Prettify supports both.\n                // http://dev.w3.org/html5/spec-author-view/the-code-element.html\n                var langExtension = attrs['lang'];\n                if (!langExtension) {\n                  langExtension = className.match(langExtensionRe);\n                  // Support <pre class=\"prettyprint\"><code class=\"language-c\">\n                  var wrapper;\n                  if (!langExtension && (wrapper = childContentWrapper(cs))\n                      && codeRe.test(wrapper.tagName)) {\n                    langExtension = wrapper.className.match(langExtensionRe);\n                  }\n    \n                  if (langExtension) { langExtension = langExtension[1]; }\n                }\n    \n                var preformatted;\n                if (preformattedTagNameRe.test(cs.tagName)) {\n                  preformatted = 1;\n                } else {\n                  var currentStyle = cs['currentStyle'];\n                  var defaultView = doc.defaultView;\n                  var whitespace = (\n                      currentStyle\n                      ? currentStyle['whiteSpace']\n                      : (defaultView\n                         && defaultView.getComputedStyle)\n                      ? defaultView.getComputedStyle(cs, null)\n                      .getPropertyValue('white-space')\n                      : 0);\n                  preformatted = whitespace\n                      && 'pre' === whitespace.substring(0, 3);\n                }\n    \n                // Look for a class like linenums or linenums:<n> where <n> is the\n                // 1-indexed number of the first line.\n                var lineNums = attrs['linenums'];\n                if (!(lineNums = lineNums === 'true' || +lineNums)) {\n                  lineNums = className.match(/\\blinenums\\b(?::(\\d+))?/);\n                  lineNums =\n                    lineNums\n                    ? lineNums[1] && lineNums[1].length\n                      ? +lineNums[1] : true\n                    : false;\n                }\n                if (lineNums) { numberLines(cs, lineNums, preformatted); }\n    \n                // do the pretty printing\n                prettyPrintingJob = {\n                  langExtension: langExtension,\n                  sourceNode: cs,\n                  numberLines: lineNums,\n                  pre: preformatted\n                };\n                applyDecorator(prettyPrintingJob);\n              }\n            }\n          }\n          if (k < elements.length) {\n            // finish up in a continuation\n            setTimeout(doWork, 250);\n          } else if ('function' === typeof opt_whenDone) {\n            opt_whenDone();\n          }\n        }\n    \n        doWork();\n      }\n    \n      /**\n       * Contains functions for creating and registering new language handlers.\n       * @type {Object}\n       */\n      var PR = win['PR'] = {\n            'createSimpleLexer': createSimpleLexer,\n            'registerLangHandler': registerLangHandler,\n            'sourceDecorator': sourceDecorator,\n            'PR_ATTRIB_NAME': PR_ATTRIB_NAME,\n            'PR_ATTRIB_VALUE': PR_ATTRIB_VALUE,\n            'PR_COMMENT': PR_COMMENT,\n            'PR_DECLARATION': PR_DECLARATION,\n            'PR_KEYWORD': PR_KEYWORD,\n            'PR_LITERAL': PR_LITERAL,\n            'PR_NOCODE': PR_NOCODE,\n            'PR_PLAIN': PR_PLAIN,\n            'PR_PUNCTUATION': PR_PUNCTUATION,\n            'PR_SOURCE': PR_SOURCE,\n            'PR_STRING': PR_STRING,\n            'PR_TAG': PR_TAG,\n            'PR_TYPE': PR_TYPE,\n            'prettyPrintOne':\n               IN_GLOBAL_SCOPE\n                 ? (win['prettyPrintOne'] = $prettyPrintOne)\n                 : (prettyPrintOne = $prettyPrintOne),\n            'prettyPrint': prettyPrint =\n               IN_GLOBAL_SCOPE\n                 ? (win['prettyPrint'] = $prettyPrint)\n                 : (prettyPrint = $prettyPrint)\n          };\n    \n      // Make PR available via the Asynchronous Module Definition (AMD) API.\n      // Per https://github.com/amdjs/amdjs-api/wiki/AMD:\n      // The Asynchronous Module Definition (AMD) API specifies a\n      // mechanism for defining modules such that the module and its\n      // dependencies can be asynchronously loaded.\n      // ...\n      // To allow a clear indicator that a global define function (as\n      // needed for script src browser loading) conforms to the AMD API,\n      // any global define function SHOULD have a property called \"amd\"\n      // whose value is an object. This helps avoid conflict with any\n      // other existing JavaScript code that could have defined a define()\n      // function that does not conform to the AMD API.\n      if (typeof define === \"function\" && define['amd']) {\n        define(\"google-code-prettify\", [], function () {\n          return PR; \n        });\n      }\n    })();\n    return prettyPrint;\n  })();\n\n  // If this script is deferred or async and the document is already\n  // loaded we need to wait for language handlers to load before performing\n  // any autorun.\n  function onLangsLoaded() {\n    if (autorun) {\n      contentLoaded(\n        function () {\n          var n = callbacks.length;\n          var callback = n ? function () {\n            for (var i = 0; i < n; ++i) {\n              (function (i) {\n                 setTimeout(\n                   function () {\n                     win['exports'][callbacks[i]].apply(win, arguments);\n                   }, 0);\n               })(i);\n            }\n          } : void 0;\n          prettyPrint(callback);\n        });\n    }\n  }\n  checkPendingLanguages();\n\n}());\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/css/animate.css",
    "content": "@charset \"UTF-8\";\n/*\nAnimate.css - http://daneden.me/animate\nLicensed under the MIT license\n\nCopyright (c) 2013 Daniel Eden\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n*/\nbody { /* Addresses a small issue in webkit: http://bit.ly/NEdoDq */\n\t-webkit-backface-visibility: hidden;\n}\n.animated {\n\t-webkit-animation-duration: 1s;\n\t   -moz-animation-duration: 1s;\n\t     -o-animation-duration: 1s;\n\t        animation-duration: 1s;\n\t-webkit-animation-fill-mode: both;\n\t   -moz-animation-fill-mode: both;\n\t     -o-animation-fill-mode: both;\n\t        animation-fill-mode: both;\n}\n\n.animated.hinge {\n\t-webkit-animation-duration: 2s;\n\t   -moz-animation-duration: 2s;\n\t     -o-animation-duration: 2s;\n\t        animation-duration: 2s;\n}\n\n@-webkit-keyframes flash {\n\t0%, 50%, 100% {opacity: 1;}\t\n\t25%, 75% {opacity: 0;}\n}\n\n@-moz-keyframes flash {\n\t0%, 50%, 100% {opacity: 1;}\t\n\t25%, 75% {opacity: 0;}\n}\n\n@-o-keyframes flash {\n\t0%, 50%, 100% {opacity: 1;}\t\n\t25%, 75% {opacity: 0;}\n}\n\n@keyframes flash {\n\t0%, 50%, 100% {opacity: 1;}\t\n\t25%, 75% {opacity: 0;}\n}\n\n.flash {\n\t-webkit-animation-name: flash;\n\t-moz-animation-name: flash;\n\t-o-animation-name: flash;\n\tanimation-name: flash;\n}\n@-webkit-keyframes shake {\n\t0%, 100% {-webkit-transform: translateX(0);}\n\t10%, 30%, 50%, 70%, 90% {-webkit-transform: translateX(-10px);}\n\t20%, 40%, 60%, 80% {-webkit-transform: translateX(10px);}\n}\n\n@-moz-keyframes shake {\n\t0%, 100% {-moz-transform: translateX(0);}\n\t10%, 30%, 50%, 70%, 90% {-moz-transform: translateX(-10px);}\n\t20%, 40%, 60%, 80% {-moz-transform: translateX(10px);}\n}\n\n@-o-keyframes shake {\n\t0%, 100% {-o-transform: translateX(0);}\n\t10%, 30%, 50%, 70%, 90% {-o-transform: translateX(-10px);}\n\t20%, 40%, 60%, 80% {-o-transform: translateX(10px);}\n}\n\n@keyframes shake {\n\t0%, 100% {transform: translateX(0);}\n\t10%, 30%, 50%, 70%, 90% {transform: translateX(-10px);}\n\t20%, 40%, 60%, 80% {transform: translateX(10px);}\n}\n\n.shake {\n\t-webkit-animation-name: shake;\n\t-moz-animation-name: shake;\n\t-o-animation-name: shake;\n\tanimation-name: shake;\n}\n@-webkit-keyframes bounce {\n\t0%, 20%, 50%, 80%, 100% {-webkit-transform: translateY(0);}\n\t40% {-webkit-transform: translateY(-30px);}\n\t60% {-webkit-transform: translateY(-15px);}\n}\n\n@-moz-keyframes bounce {\n\t0%, 20%, 50%, 80%, 100% {-moz-transform: translateY(0);}\n\t40% {-moz-transform: translateY(-30px);}\n\t60% {-moz-transform: translateY(-15px);}\n}\n\n@-o-keyframes bounce {\n\t0%, 20%, 50%, 80%, 100% {-o-transform: translateY(0);}\n\t40% {-o-transform: translateY(-30px);}\n\t60% {-o-transform: translateY(-15px);}\n}\n@keyframes bounce {\n\t0%, 20%, 50%, 80%, 100% {transform: translateY(0);}\n\t40% {transform: translateY(-30px);}\n\t60% {transform: translateY(-15px);}\n}\n\n.bounce {\n\t-webkit-animation-name: bounce;\n\t-moz-animation-name: bounce;\n\t-o-animation-name: bounce;\n\tanimation-name: bounce;\n}\n@-webkit-keyframes tada {\n\t0% {-webkit-transform: scale(1);}\t\n\t10%, 20% {-webkit-transform: scale(0.9) rotate(-3deg);}\n\t30%, 50%, 70%, 90% {-webkit-transform: scale(1.1) rotate(3deg);}\n\t40%, 60%, 80% {-webkit-transform: scale(1.1) rotate(-3deg);}\n\t100% {-webkit-transform: scale(1) rotate(0);}\n}\n\n@-moz-keyframes tada {\n\t0% {-moz-transform: scale(1);}\t\n\t10%, 20% {-moz-transform: scale(0.9) rotate(-3deg);}\n\t30%, 50%, 70%, 90% {-moz-transform: scale(1.1) rotate(3deg);}\n\t40%, 60%, 80% {-moz-transform: scale(1.1) rotate(-3deg);}\n\t100% {-moz-transform: scale(1) rotate(0);}\n}\n\n@-o-keyframes tada {\n\t0% {-o-transform: scale(1);}\t\n\t10%, 20% {-o-transform: scale(0.9) rotate(-3deg);}\n\t30%, 50%, 70%, 90% {-o-transform: scale(1.1) rotate(3deg);}\n\t40%, 60%, 80% {-o-transform: scale(1.1) rotate(-3deg);}\n\t100% {-o-transform: scale(1) rotate(0);}\n}\n\n@keyframes tada {\n\t0% {transform: scale(1);}\t\n\t10%, 20% {transform: scale(0.9) rotate(-3deg);}\n\t30%, 50%, 70%, 90% {transform: scale(1.1) rotate(3deg);}\n\t40%, 60%, 80% {transform: scale(1.1) rotate(-3deg);}\n\t100% {transform: scale(1) rotate(0);}\n}\n\n.tada {\n\t-webkit-animation-name: tada;\n\t-moz-animation-name: tada;\n\t-o-animation-name: tada;\n\tanimation-name: tada;\n}\n@-webkit-keyframes swing {\n\t20%, 40%, 60%, 80%, 100% { -webkit-transform-origin: top center; }\n\t20% { -webkit-transform: rotate(15deg); }\t\n\t40% { -webkit-transform: rotate(-10deg); }\n\t60% { -webkit-transform: rotate(5deg); }\t\n\t80% { -webkit-transform: rotate(-5deg); }\t\n\t100% { -webkit-transform: rotate(0deg); }\n}\n\n@-moz-keyframes swing {\n\t20% { -moz-transform: rotate(15deg); }\t\n\t40% { -moz-transform: rotate(-10deg); }\n\t60% { -moz-transform: rotate(5deg); }\t\n\t80% { -moz-transform: rotate(-5deg); }\t\n\t100% { -moz-transform: rotate(0deg); }\n}\n\n@-o-keyframes swing {\n\t20% { -o-transform: rotate(15deg); }\t\n\t40% { -o-transform: rotate(-10deg); }\n\t60% { -o-transform: rotate(5deg); }\t\n\t80% { -o-transform: rotate(-5deg); }\t\n\t100% { -o-transform: rotate(0deg); }\n}\n\n@keyframes swing {\n\t20% { transform: rotate(15deg); }\t\n\t40% { transform: rotate(-10deg); }\n\t60% { transform: rotate(5deg); }\t\n\t80% { transform: rotate(-5deg); }\t\n\t100% { transform: rotate(0deg); }\n}\n\n.swing {\n\t-webkit-transform-origin: top center;\n\t-moz-transform-origin: top center;\n\t-o-transform-origin: top center;\n\ttransform-origin: top center;\n\t-webkit-animation-name: swing;\n\t-moz-animation-name: swing;\n\t-o-animation-name: swing;\n\tanimation-name: swing;\n}\n/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */\n\n@-webkit-keyframes wobble {\n  0% { -webkit-transform: translateX(0%); }\n  15% { -webkit-transform: translateX(-25%) rotate(-5deg); }\n  30% { -webkit-transform: translateX(20%) rotate(3deg); }\n  45% { -webkit-transform: translateX(-15%) rotate(-3deg); }\n  60% { -webkit-transform: translateX(10%) rotate(2deg); }\n  75% { -webkit-transform: translateX(-5%) rotate(-1deg); }\n  100% { -webkit-transform: translateX(0%); }\n}\n\n@-moz-keyframes wobble {\n  0% { -moz-transform: translateX(0%); }\n  15% { -moz-transform: translateX(-25%) rotate(-5deg); }\n  30% { -moz-transform: translateX(20%) rotate(3deg); }\n  45% { -moz-transform: translateX(-15%) rotate(-3deg); }\n  60% { -moz-transform: translateX(10%) rotate(2deg); }\n  75% { -moz-transform: translateX(-5%) rotate(-1deg); }\n  100% { -moz-transform: translateX(0%); }\n}\n\n@-o-keyframes wobble {\n  0% { -o-transform: translateX(0%); }\n  15% { -o-transform: translateX(-25%) rotate(-5deg); }\n  30% { -o-transform: translateX(20%) rotate(3deg); }\n  45% { -o-transform: translateX(-15%) rotate(-3deg); }\n  60% { -o-transform: translateX(10%) rotate(2deg); }\n  75% { -o-transform: translateX(-5%) rotate(-1deg); }\n  100% { -o-transform: translateX(0%); }\n}\n\n@keyframes wobble {\n  0% { transform: translateX(0%); }\n  15% { transform: translateX(-25%) rotate(-5deg); }\n  30% { transform: translateX(20%) rotate(3deg); }\n  45% { transform: translateX(-15%) rotate(-3deg); }\n  60% { transform: translateX(10%) rotate(2deg); }\n  75% { transform: translateX(-5%) rotate(-1deg); }\n  100% { transform: translateX(0%); }\n}\n\n.wobble {\n\t-webkit-animation-name: wobble;\n\t-moz-animation-name: wobble;\n\t-o-animation-name: wobble;\n\tanimation-name: wobble;\n}\n/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */\n\n@-webkit-keyframes pulse {\n    0% { -webkit-transform: scale(1); }\t\n\t50% { -webkit-transform: scale(1.1); }\n    100% { -webkit-transform: scale(1); }\n}\n@-moz-keyframes pulse {\n    0% { -moz-transform: scale(1); }\t\n\t50% { -moz-transform: scale(1.1); }\n    100% { -moz-transform: scale(1); }\n}\n@-o-keyframes pulse {\n    0% { -o-transform: scale(1); }\t\n\t50% { -o-transform: scale(1.1); }\n    100% { -o-transform: scale(1); }\n}\n@keyframes pulse {\n    0% { transform: scale(1); }\t\n\t50% { transform: scale(1.1); }\n    100% { transform: scale(1); }\n}\n\n.pulse {\n\t-webkit-animation-name: pulse;\n\t-moz-animation-name: pulse;\n\t-o-animation-name: pulse;\n\tanimation-name: pulse;\n}\n@-webkit-keyframes flip {\n\t0% {\n\t\t-webkit-transform: perspective(400px) rotateY(0);\n\t\t-webkit-animation-timing-function: ease-out;\n\t}\n\t40% {\n\t\t-webkit-transform: perspective(400px) translateZ(150px) rotateY(170deg);\n\t\t-webkit-animation-timing-function: ease-out;\n\t}\n\t50% {\n\t\t-webkit-transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1);\n\t\t-webkit-animation-timing-function: ease-in;\n\t}\n\t80% {\n\t\t-webkit-transform: perspective(400px) rotateY(360deg) scale(.95);\n\t\t-webkit-animation-timing-function: ease-in;\n\t}\n\t100% {\n\t\t-webkit-transform: perspective(400px) scale(1);\n\t\t-webkit-animation-timing-function: ease-in;\n\t}\n}\n@-moz-keyframes flip {\n\t0% {\n\t\t-moz-transform: perspective(400px) rotateY(0);\n\t\t-moz-animation-timing-function: ease-out;\n\t}\n\t40% {\n\t\t-moz-transform: perspective(400px) translateZ(150px) rotateY(170deg);\n\t\t-moz-animation-timing-function: ease-out;\n\t}\n\t50% {\n\t\t-moz-transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1);\n\t\t-moz-animation-timing-function: ease-in;\n\t}\n\t80% {\n\t\t-moz-transform: perspective(400px) rotateY(360deg) scale(.95);\n\t\t-moz-animation-timing-function: ease-in;\n\t}\n\t100% {\n\t\t-moz-transform: perspective(400px) scale(1);\n\t\t-moz-animation-timing-function: ease-in;\n\t}\n}\n@-o-keyframes flip {\n\t0% {\n\t\t-o-transform: perspective(400px) rotateY(0);\n\t\t-o-animation-timing-function: ease-out;\n\t}\n\t40% {\n\t\t-o-transform: perspective(400px) translateZ(150px) rotateY(170deg);\n\t\t-o-animation-timing-function: ease-out;\n\t}\n\t50% {\n\t\t-o-transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1);\n\t\t-o-animation-timing-function: ease-in;\n\t}\n\t80% {\n\t\t-o-transform: perspective(400px) rotateY(360deg) scale(.95);\n\t\t-o-animation-timing-function: ease-in;\n\t}\n\t100% {\n\t\t-o-transform: perspective(400px) scale(1);\n\t\t-o-animation-timing-function: ease-in;\n\t}\n}\n@keyframes flip {\n\t0% {\n\t\ttransform: perspective(400px) rotateY(0);\n\t\tanimation-timing-function: ease-out;\n\t}\n\t40% {\n\t\ttransform: perspective(400px) translateZ(150px) rotateY(170deg);\n\t\tanimation-timing-function: ease-out;\n\t}\n\t50% {\n\t\ttransform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1);\n\t\tanimation-timing-function: ease-in;\n\t}\n\t80% {\n\t\ttransform: perspective(400px) rotateY(360deg) scale(.95);\n\t\tanimation-timing-function: ease-in;\n\t}\n\t100% {\n\t\ttransform: perspective(400px) scale(1);\n\t\tanimation-timing-function: ease-in;\n\t}\n}\n\n.flip {\n\t-webkit-backface-visibility: visible !important;\n\t-webkit-animation-name: flip;\n\t-moz-backface-visibility: visible !important;\n\t-moz-animation-name: flip;\n\t-o-backface-visibility: visible !important;\n\t-o-animation-name: flip;\n\tbackface-visibility: visible !important;\n\tanimation-name: flip;\n}\n@-webkit-keyframes flipInX {\n    0% {\n        -webkit-transform: perspective(400px) rotateX(90deg);\n        opacity: 0;\n    }\n    \n    40% {\n        -webkit-transform: perspective(400px) rotateX(-10deg);\n    }\n    \n    70% {\n        -webkit-transform: perspective(400px) rotateX(10deg);\n    }\n    \n    100% {\n        -webkit-transform: perspective(400px) rotateX(0deg);\n        opacity: 1;\n    }\n}\n@-moz-keyframes flipInX {\n    0% {\n        -moz-transform: perspective(400px) rotateX(90deg);\n        opacity: 0;\n    }\n    \n    40% {\n        -moz-transform: perspective(400px) rotateX(-10deg);\n    }\n    \n    70% {\n        -moz-transform: perspective(400px) rotateX(10deg);\n    }\n    \n    100% {\n        -moz-transform: perspective(400px) rotateX(0deg);\n        opacity: 1;\n    }\n}\n@-o-keyframes flipInX {\n    0% {\n        -o-transform: perspective(400px) rotateX(90deg);\n        opacity: 0;\n    }\n    \n    40% {\n        -o-transform: perspective(400px) rotateX(-10deg);\n    }\n    \n    70% {\n        -o-transform: perspective(400px) rotateX(10deg);\n    }\n    \n    100% {\n        -o-transform: perspective(400px) rotateX(0deg);\n        opacity: 1;\n    }\n}\n@keyframes flipInX {\n    0% {\n        transform: perspective(400px) rotateX(90deg);\n        opacity: 0;\n    }\n    \n    40% {\n        transform: perspective(400px) rotateX(-10deg);\n    }\n    \n    70% {\n        transform: perspective(400px) rotateX(10deg);\n    }\n    \n    100% {\n        transform: perspective(400px) rotateX(0deg);\n        opacity: 1;\n    }\n}\n\n.flipInX {\n\t-webkit-backface-visibility: visible !important;\n\t-webkit-animation-name: flipInX;\n\t-moz-backface-visibility: visible !important;\n\t-moz-animation-name: flipInX;\n\t-o-backface-visibility: visible !important;\n\t-o-animation-name: flipInX;\n\tbackface-visibility: visible !important;\n\tanimation-name: flipInX;\n}\n@-webkit-keyframes flipOutX {\n    0% {\n        -webkit-transform: perspective(400px) rotateX(0deg);\n        opacity: 1;\n    }\n\t100% {\n        -webkit-transform: perspective(400px) rotateX(90deg);\n        opacity: 0;\n    }\n}\n\n@-moz-keyframes flipOutX {\n    0% {\n        -moz-transform: perspective(400px) rotateX(0deg);\n        opacity: 1;\n    }\n\t100% {\n        -moz-transform: perspective(400px) rotateX(90deg);\n        opacity: 0;\n    }\n}\n\n@-o-keyframes flipOutX {\n    0% {\n        -o-transform: perspective(400px) rotateX(0deg);\n        opacity: 1;\n    }\n\t100% {\n        -o-transform: perspective(400px) rotateX(90deg);\n        opacity: 0;\n    }\n}\n\n@keyframes flipOutX {\n    0% {\n        transform: perspective(400px) rotateX(0deg);\n        opacity: 1;\n    }\n\t100% {\n        transform: perspective(400px) rotateX(90deg);\n        opacity: 0;\n    }\n}\n\n.flipOutX {\n\t-webkit-animation-name: flipOutX;\n\t-webkit-backface-visibility: visible !important;\n\t-moz-animation-name: flipOutX;\n\t-moz-backface-visibility: visible !important;\n\t-o-animation-name: flipOutX;\n\t-o-backface-visibility: visible !important;\n\tanimation-name: flipOutX;\n\tbackface-visibility: visible !important;\n}\n@-webkit-keyframes flipInY {\n    0% {\n        -webkit-transform: perspective(400px) rotateY(90deg);\n        opacity: 0;\n    }\n    \n    40% {\n        -webkit-transform: perspective(400px) rotateY(-10deg);\n    }\n    \n    70% {\n        -webkit-transform: perspective(400px) rotateY(10deg);\n    }\n    \n    100% {\n        -webkit-transform: perspective(400px) rotateY(0deg);\n        opacity: 1;\n    }\n}\n@-moz-keyframes flipInY {\n    0% {\n        -moz-transform: perspective(400px) rotateY(90deg);\n        opacity: 0;\n    }\n    \n    40% {\n        -moz-transform: perspective(400px) rotateY(-10deg);\n    }\n    \n    70% {\n        -moz-transform: perspective(400px) rotateY(10deg);\n    }\n    \n    100% {\n        -moz-transform: perspective(400px) rotateY(0deg);\n        opacity: 1;\n    }\n}\n@-o-keyframes flipInY {\n    0% {\n        -o-transform: perspective(400px) rotateY(90deg);\n        opacity: 0;\n    }\n    \n    40% {\n        -o-transform: perspective(400px) rotateY(-10deg);\n    }\n    \n    70% {\n        -o-transform: perspective(400px) rotateY(10deg);\n    }\n    \n    100% {\n        -o-transform: perspective(400px) rotateY(0deg);\n        opacity: 1;\n    }\n}\n@keyframes flipInY {\n    0% {\n        transform: perspective(400px) rotateY(90deg);\n        opacity: 0;\n    }\n    \n    40% {\n        transform: perspective(400px) rotateY(-10deg);\n    }\n    \n    70% {\n        transform: perspective(400px) rotateY(10deg);\n    }\n    \n    100% {\n        transform: perspective(400px) rotateY(0deg);\n        opacity: 1;\n    }\n}\n\n.flipInY {\n\t-webkit-backface-visibility: visible !important;\n\t-webkit-animation-name: flipInY;\n\t-moz-backface-visibility: visible !important;\n\t-moz-animation-name: flipInY;\n\t-o-backface-visibility: visible !important;\n\t-o-animation-name: flipInY;\n\tbackface-visibility: visible !important;\n\tanimation-name: flipInY;\n}\n@-webkit-keyframes flipOutY {\n    0% {\n        -webkit-transform: perspective(400px) rotateY(0deg);\n        opacity: 1;\n    }\n\t100% {\n        -webkit-transform: perspective(400px) rotateY(90deg);\n        opacity: 0;\n    }\n}\n@-moz-keyframes flipOutY {\n    0% {\n        -moz-transform: perspective(400px) rotateY(0deg);\n        opacity: 1;\n    }\n\t100% {\n        -moz-transform: perspective(400px) rotateY(90deg);\n        opacity: 0;\n    }\n}\n@-o-keyframes flipOutY {\n    0% {\n        -o-transform: perspective(400px) rotateY(0deg);\n        opacity: 1;\n    }\n\t100% {\n        -o-transform: perspective(400px) rotateY(90deg);\n        opacity: 0;\n    }\n}\n@keyframes flipOutY {\n    0% {\n        transform: perspective(400px) rotateY(0deg);\n        opacity: 1;\n    }\n\t100% {\n        transform: perspective(400px) rotateY(90deg);\n        opacity: 0;\n    }\n}\n\n.flipOutY {\n\t-webkit-backface-visibility: visible !important;\n\t-webkit-animation-name: flipOutY;\n\t-moz-backface-visibility: visible !important;\n\t-moz-animation-name: flipOutY;\n\t-o-backface-visibility: visible !important;\n\t-o-animation-name: flipOutY;\n\tbackface-visibility: visible !important;\n\tanimation-name: flipOutY;\n}\n@-webkit-keyframes fadeIn {\n\t0% {opacity: 0;}\t\n\t100% {opacity: 1;}\n}\n\n@-moz-keyframes fadeIn {\n\t0% {opacity: 0;}\t\n\t100% {opacity: 1;}\n}\n\n@-o-keyframes fadeIn {\n\t0% {opacity: 0;}\t\n\t100% {opacity: 1;}\n}\n\n@keyframes fadeIn {\n\t0% {opacity: 0;}\t\n\t100% {opacity: 1;}\n}\n\n.fadeIn {\n\t-webkit-animation-name: fadeIn;\n\t-moz-animation-name: fadeIn;\n\t-o-animation-name: fadeIn;\n\tanimation-name: fadeIn;\n}\n@-webkit-keyframes fadeInUp {\n\t0% {\n\t\topacity: 0;\n\t\t-webkit-transform: translateY(20px);\n\t}\n\t\n\t100% {\n\t\topacity: 1;\n\t\t-webkit-transform: translateY(0);\n\t}\n}\n\n@-moz-keyframes fadeInUp {\n\t0% {\n\t\topacity: 0;\n\t\t-moz-transform: translateY(20px);\n\t}\n\t\n\t100% {\n\t\topacity: 1;\n\t\t-moz-transform: translateY(0);\n\t}\n}\n\n@-o-keyframes fadeInUp {\n\t0% {\n\t\topacity: 0;\n\t\t-o-transform: translateY(20px);\n\t}\n\t\n\t100% {\n\t\topacity: 1;\n\t\t-o-transform: translateY(0);\n\t}\n}\n\n@keyframes fadeInUp {\n\t0% {\n\t\topacity: 0;\n\t\ttransform: translateY(20px);\n\t}\n\t\n\t100% {\n\t\topacity: 1;\n\t\ttransform: translateY(0);\n\t}\n}\n\n.fadeInUp {\n\t-webkit-animation-name: fadeInUp;\n\t-moz-animation-name: fadeInUp;\n\t-o-animation-name: fadeInUp;\n\tanimation-name: fadeInUp;\n}\n@-webkit-keyframes fadeInDown {\n\t0% {\n\t\topacity: 0;\n\t\t-webkit-transform: translateY(-20px);\n\t}\n\t\n\t100% {\n\t\topacity: 1;\n\t\t-webkit-transform: translateY(0);\n\t}\n}\n\n@-moz-keyframes fadeInDown {\n\t0% {\n\t\topacity: 0;\n\t\t-moz-transform: translateY(-20px);\n\t}\n\t\n\t100% {\n\t\topacity: 1;\n\t\t-moz-transform: translateY(0);\n\t}\n}\n\n@-o-keyframes fadeInDown {\n\t0% {\n\t\topacity: 0;\n\t\t-o-transform: translateY(-20px);\n\t}\n\t\n\t100% {\n\t\topacity: 1;\n\t\t-o-transform: translateY(0);\n\t}\n}\n\n@keyframes fadeInDown {\n\t0% {\n\t\topacity: 0;\n\t\ttransform: translateY(-20px);\n\t}\n\t\n\t100% {\n\t\topacity: 1;\n\t\ttransform: translateY(0);\n\t}\n}\n\n.fadeInDown {\n\t-webkit-animation-name: fadeInDown;\n\t-moz-animation-name: fadeInDown;\n\t-o-animation-name: fadeInDown;\n\tanimation-name: fadeInDown;\n}\n@-webkit-keyframes fadeInLeft {\n\t0% {\n\t\topacity: 0;\n\t\t-webkit-transform: translateX(-20px);\n\t}\n\t\n\t100% {\n\t\topacity: 1;\n\t\t-webkit-transform: translateX(0);\n\t}\n}\n\n@-moz-keyframes fadeInLeft {\n\t0% {\n\t\topacity: 0;\n\t\t-moz-transform: translateX(-20px);\n\t}\n\t\n\t100% {\n\t\topacity: 1;\n\t\t-moz-transform: translateX(0);\n\t}\n}\n\n@-o-keyframes fadeInLeft {\n\t0% {\n\t\topacity: 0;\n\t\t-o-transform: translateX(-20px);\n\t}\n\t\n\t100% {\n\t\topacity: 1;\n\t\t-o-transform: translateX(0);\n\t}\n}\n\n@keyframes fadeInLeft {\n\t0% {\n\t\topacity: 0;\n\t\ttransform: translateX(-20px);\n\t}\n\t\n\t100% {\n\t\topacity: 1;\n\t\ttransform: translateX(0);\n\t}\n}\n\n.fadeInLeft {\n\t-webkit-animation-name: fadeInLeft;\n\t-moz-animation-name: fadeInLeft;\n\t-o-animation-name: fadeInLeft;\n\tanimation-name: fadeInLeft;\n}\n@-webkit-keyframes fadeInRight {\n\t0% {\n\t\topacity: 0;\n\t\t-webkit-transform: translateX(20px);\n\t}\n\t\n\t100% {\n\t\topacity: 1;\n\t\t-webkit-transform: translateX(0);\n\t}\n}\n\n@-moz-keyframes fadeInRight {\n\t0% {\n\t\topacity: 0;\n\t\t-moz-transform: translateX(20px);\n\t}\n\t\n\t100% {\n\t\topacity: 1;\n\t\t-moz-transform: translateX(0);\n\t}\n}\n\n@-o-keyframes fadeInRight {\n\t0% {\n\t\topacity: 0;\n\t\t-o-transform: translateX(20px);\n\t}\n\t\n\t100% {\n\t\topacity: 1;\n\t\t-o-transform: translateX(0);\n\t}\n}\n\n@keyframes fadeInRight {\n\t0% {\n\t\topacity: 0;\n\t\ttransform: translateX(20px);\n\t}\n\t\n\t100% {\n\t\topacity: 1;\n\t\ttransform: translateX(0);\n\t}\n}\n\n.fadeInRight {\n\t-webkit-animation-name: fadeInRight;\n\t-moz-animation-name: fadeInRight;\n\t-o-animation-name: fadeInRight;\n\tanimation-name: fadeInRight;\n}\n@-webkit-keyframes fadeInUpBig {\n\t0% {\n\t\topacity: 0;\n\t\t-webkit-transform: translateY(2000px);\n\t}\n\t\n\t100% {\n\t\topacity: 1;\n\t\t-webkit-transform: translateY(0);\n\t}\n}\n\n@-moz-keyframes fadeInUpBig {\n\t0% {\n\t\topacity: 0;\n\t\t-moz-transform: translateY(2000px);\n\t}\n\t\n\t100% {\n\t\topacity: 1;\n\t\t-moz-transform: translateY(0);\n\t}\n}\n\n@-o-keyframes fadeInUpBig {\n\t0% {\n\t\topacity: 0;\n\t\t-o-transform: translateY(2000px);\n\t}\n\t\n\t100% {\n\t\topacity: 1;\n\t\t-o-transform: translateY(0);\n\t}\n}\n\n@keyframes fadeInUpBig {\n\t0% {\n\t\topacity: 0;\n\t\ttransform: translateY(2000px);\n\t}\n\t\n\t100% {\n\t\topacity: 1;\n\t\ttransform: translateY(0);\n\t}\n}\n\n.fadeInUpBig {\n\t-webkit-animation-name: fadeInUpBig;\n\t-moz-animation-name: fadeInUpBig;\n\t-o-animation-name: fadeInUpBig;\n\tanimation-name: fadeInUpBig;\n}\n@-webkit-keyframes fadeInDownBig {\n\t0% {\n\t\topacity: 0;\n\t\t-webkit-transform: translateY(-2000px);\n\t}\n\t\n\t100% {\n\t\topacity: 1;\n\t\t-webkit-transform: translateY(0);\n\t}\n}\n\n@-moz-keyframes fadeInDownBig {\n\t0% {\n\t\topacity: 0;\n\t\t-moz-transform: translateY(-2000px);\n\t}\n\t\n\t100% {\n\t\topacity: 1;\n\t\t-moz-transform: translateY(0);\n\t}\n}\n\n@-o-keyframes fadeInDownBig {\n\t0% {\n\t\topacity: 0;\n\t\t-o-transform: translateY(-2000px);\n\t}\n\t\n\t100% {\n\t\topacity: 1;\n\t\t-o-transform: translateY(0);\n\t}\n}\n\n@keyframes fadeInDownBig {\n\t0% {\n\t\topacity: 0;\n\t\ttransform: translateY(-2000px);\n\t}\n\t\n\t100% {\n\t\topacity: 1;\n\t\ttransform: translateY(0);\n\t}\n}\n\n.fadeInDownBig {\n\t-webkit-animation-name: fadeInDownBig;\n\t-moz-animation-name: fadeInDownBig;\n\t-o-animation-name: fadeInDownBig;\n\tanimation-name: fadeInDownBig;\n}\n@-webkit-keyframes fadeInLeftBig {\n\t0% {\n\t\topacity: 0;\n\t\t-webkit-transform: translateX(-2000px);\n\t}\n\t\n\t100% {\n\t\topacity: 1;\n\t\t-webkit-transform: translateX(0);\n\t}\n}\n@-moz-keyframes fadeInLeftBig {\n\t0% {\n\t\topacity: 0;\n\t\t-moz-transform: translateX(-2000px);\n\t}\n\t\n\t100% {\n\t\topacity: 1;\n\t\t-moz-transform: translateX(0);\n\t}\n}\n@-o-keyframes fadeInLeftBig {\n\t0% {\n\t\topacity: 0;\n\t\t-o-transform: translateX(-2000px);\n\t}\n\t\n\t100% {\n\t\topacity: 1;\n\t\t-o-transform: translateX(0);\n\t}\n}\n@keyframes fadeInLeftBig {\n\t0% {\n\t\topacity: 0;\n\t\ttransform: translateX(-2000px);\n\t}\n\t\n\t100% {\n\t\topacity: 1;\n\t\ttransform: translateX(0);\n\t}\n}\n\n.fadeInLeftBig {\n\t-webkit-animation-name: fadeInLeftBig;\n\t-moz-animation-name: fadeInLeftBig;\n\t-o-animation-name: fadeInLeftBig;\n\tanimation-name: fadeInLeftBig;\n}\n@-webkit-keyframes fadeInRightBig {\n\t0% {\n\t\topacity: 0;\n\t\t-webkit-transform: translateX(2000px);\n\t}\n\t\n\t100% {\n\t\topacity: 1;\n\t\t-webkit-transform: translateX(0);\n\t}\n}\n\n@-moz-keyframes fadeInRightBig {\n\t0% {\n\t\topacity: 0;\n\t\t-moz-transform: translateX(2000px);\n\t}\n\t\n\t100% {\n\t\topacity: 1;\n\t\t-moz-transform: translateX(0);\n\t}\n}\n\n@-o-keyframes fadeInRightBig {\n\t0% {\n\t\topacity: 0;\n\t\t-o-transform: translateX(2000px);\n\t}\n\t\n\t100% {\n\t\topacity: 1;\n\t\t-o-transform: translateX(0);\n\t}\n}\n\n@keyframes fadeInRightBig {\n\t0% {\n\t\topacity: 0;\n\t\ttransform: translateX(2000px);\n\t}\n\t\n\t100% {\n\t\topacity: 1;\n\t\ttransform: translateX(0);\n\t}\n}\n\n.fadeInRightBig {\n\t-webkit-animation-name: fadeInRightBig;\n\t-moz-animation-name: fadeInRightBig;\n\t-o-animation-name: fadeInRightBig;\n\tanimation-name: fadeInRightBig;\n}\n@-webkit-keyframes fadeOut {\n\t0% {opacity: 1;}\n\t100% {opacity: 0;}\n}\n\n@-moz-keyframes fadeOut {\n\t0% {opacity: 1;}\n\t100% {opacity: 0;}\n}\n\n@-o-keyframes fadeOut {\n\t0% {opacity: 1;}\n\t100% {opacity: 0;}\n}\n\n@keyframes fadeOut {\n\t0% {opacity: 1;}\n\t100% {opacity: 0;}\n}\n\n.fadeOut {\n\t-webkit-animation-name: fadeOut;\n\t-moz-animation-name: fadeOut;\n\t-o-animation-name: fadeOut;\n\tanimation-name: fadeOut;\n}\n@-webkit-keyframes fadeOutUp {\n\t0% {\n\t\topacity: 1;\n\t\t-webkit-transform: translateY(0);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\t-webkit-transform: translateY(-20px);\n\t}\n}\n@-moz-keyframes fadeOutUp {\n\t0% {\n\t\topacity: 1;\n\t\t-moz-transform: translateY(0);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\t-moz-transform: translateY(-20px);\n\t}\n}\n@-o-keyframes fadeOutUp {\n\t0% {\n\t\topacity: 1;\n\t\t-o-transform: translateY(0);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\t-o-transform: translateY(-20px);\n\t}\n}\n@keyframes fadeOutUp {\n\t0% {\n\t\topacity: 1;\n\t\ttransform: translateY(0);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\ttransform: translateY(-20px);\n\t}\n}\n\n.fadeOutUp {\n\t-webkit-animation-name: fadeOutUp;\n\t-moz-animation-name: fadeOutUp;\n\t-o-animation-name: fadeOutUp;\n\tanimation-name: fadeOutUp;\n}\n@-webkit-keyframes fadeOutDown {\n\t0% {\n\t\topacity: 1;\n\t\t-webkit-transform: translateY(0);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\t-webkit-transform: translateY(20px);\n\t}\n}\n\n@-moz-keyframes fadeOutDown {\n\t0% {\n\t\topacity: 1;\n\t\t-moz-transform: translateY(0);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\t-moz-transform: translateY(20px);\n\t}\n}\n\n@-o-keyframes fadeOutDown {\n\t0% {\n\t\topacity: 1;\n\t\t-o-transform: translateY(0);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\t-o-transform: translateY(20px);\n\t}\n}\n\n@keyframes fadeOutDown {\n\t0% {\n\t\topacity: 1;\n\t\ttransform: translateY(0);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\ttransform: translateY(20px);\n\t}\n}\n\n.fadeOutDown {\n\t-webkit-animation-name: fadeOutDown;\n\t-moz-animation-name: fadeOutDown;\n\t-o-animation-name: fadeOutDown;\n\tanimation-name: fadeOutDown;\n}\n@-webkit-keyframes fadeOutLeft {\n\t0% {\n\t\topacity: 1;\n\t\t-webkit-transform: translateX(0);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\t-webkit-transform: translateX(-20px);\n\t}\n}\n\n@-moz-keyframes fadeOutLeft {\n\t0% {\n\t\topacity: 1;\n\t\t-moz-transform: translateX(0);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\t-moz-transform: translateX(-20px);\n\t}\n}\n\n@-o-keyframes fadeOutLeft {\n\t0% {\n\t\topacity: 1;\n\t\t-o-transform: translateX(0);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\t-o-transform: translateX(-20px);\n\t}\n}\n\n@keyframes fadeOutLeft {\n\t0% {\n\t\topacity: 1;\n\t\ttransform: translateX(0);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\ttransform: translateX(-20px);\n\t}\n}\n\n.fadeOutLeft {\n\t-webkit-animation-name: fadeOutLeft;\n\t-moz-animation-name: fadeOutLeft;\n\t-o-animation-name: fadeOutLeft;\n\tanimation-name: fadeOutLeft;\n}\n@-webkit-keyframes fadeOutRight {\n\t0% {\n\t\topacity: 1;\n\t\t-webkit-transform: translateX(0);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\t-webkit-transform: translateX(20px);\n\t}\n}\n\n@-moz-keyframes fadeOutRight {\n\t0% {\n\t\topacity: 1;\n\t\t-moz-transform: translateX(0);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\t-moz-transform: translateX(20px);\n\t}\n}\n\n@-o-keyframes fadeOutRight {\n\t0% {\n\t\topacity: 1;\n\t\t-o-transform: translateX(0);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\t-o-transform: translateX(20px);\n\t}\n}\n\n@keyframes fadeOutRight {\n\t0% {\n\t\topacity: 1;\n\t\ttransform: translateX(0);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\ttransform: translateX(20px);\n\t}\n}\n\n.fadeOutRight {\n\t-webkit-animation-name: fadeOutRight;\n\t-moz-animation-name: fadeOutRight;\n\t-o-animation-name: fadeOutRight;\n\tanimation-name: fadeOutRight;\n}\n@-webkit-keyframes fadeOutUpBig {\n\t0% {\n\t\topacity: 1;\n\t\t-webkit-transform: translateY(0);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\t-webkit-transform: translateY(-2000px);\n\t}\n}\n\n@-moz-keyframes fadeOutUpBig {\n\t0% {\n\t\topacity: 1;\n\t\t-moz-transform: translateY(0);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\t-moz-transform: translateY(-2000px);\n\t}\n}\n\n@-o-keyframes fadeOutUpBig {\n\t0% {\n\t\topacity: 1;\n\t\t-o-transform: translateY(0);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\t-o-transform: translateY(-2000px);\n\t}\n}\n\n@keyframes fadeOutUpBig {\n\t0% {\n\t\topacity: 1;\n\t\ttransform: translateY(0);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\ttransform: translateY(-2000px);\n\t}\n}\n\n.fadeOutUpBig {\n\t-webkit-animation-name: fadeOutUpBig;\n\t-moz-animation-name: fadeOutUpBig;\n\t-o-animation-name: fadeOutUpBig;\n\tanimation-name: fadeOutUpBig;\n}\n@-webkit-keyframes fadeOutDownBig {\n\t0% {\n\t\topacity: 1;\n\t\t-webkit-transform: translateY(0);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\t-webkit-transform: translateY(2000px);\n\t}\n}\n\n@-moz-keyframes fadeOutDownBig {\n\t0% {\n\t\topacity: 1;\n\t\t-moz-transform: translateY(0);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\t-moz-transform: translateY(2000px);\n\t}\n}\n\n@-o-keyframes fadeOutDownBig {\n\t0% {\n\t\topacity: 1;\n\t\t-o-transform: translateY(0);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\t-o-transform: translateY(2000px);\n\t}\n}\n\n@keyframes fadeOutDownBig {\n\t0% {\n\t\topacity: 1;\n\t\ttransform: translateY(0);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\ttransform: translateY(2000px);\n\t}\n}\n\n.fadeOutDownBig {\n\t-webkit-animation-name: fadeOutDownBig;\n\t-moz-animation-name: fadeOutDownBig;\n\t-o-animation-name: fadeOutDownBig;\n\tanimation-name: fadeOutDownBig;\n}\n@-webkit-keyframes fadeOutLeftBig {\n\t0% {\n\t\topacity: 1;\n\t\t-webkit-transform: translateX(0);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\t-webkit-transform: translateX(-2000px);\n\t}\n}\n\n@-moz-keyframes fadeOutLeftBig {\n\t0% {\n\t\topacity: 1;\n\t\t-moz-transform: translateX(0);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\t-moz-transform: translateX(-2000px);\n\t}\n}\n\n@-o-keyframes fadeOutLeftBig {\n\t0% {\n\t\topacity: 1;\n\t\t-o-transform: translateX(0);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\t-o-transform: translateX(-2000px);\n\t}\n}\n\n@keyframes fadeOutLeftBig {\n\t0% {\n\t\topacity: 1;\n\t\ttransform: translateX(0);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\ttransform: translateX(-2000px);\n\t}\n}\n\n.fadeOutLeftBig {\n\t-webkit-animation-name: fadeOutLeftBig;\n\t-moz-animation-name: fadeOutLeftBig;\n\t-o-animation-name: fadeOutLeftBig;\n\tanimation-name: fadeOutLeftBig;\n}\n@-webkit-keyframes fadeOutRightBig {\n\t0% {\n\t\topacity: 1;\n\t\t-webkit-transform: translateX(0);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\t-webkit-transform: translateX(2000px);\n\t}\n}\n@-moz-keyframes fadeOutRightBig {\n\t0% {\n\t\topacity: 1;\n\t\t-moz-transform: translateX(0);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\t-moz-transform: translateX(2000px);\n\t}\n}\n@-o-keyframes fadeOutRightBig {\n\t0% {\n\t\topacity: 1;\n\t\t-o-transform: translateX(0);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\t-o-transform: translateX(2000px);\n\t}\n}\n@keyframes fadeOutRightBig {\n\t0% {\n\t\topacity: 1;\n\t\ttransform: translateX(0);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\ttransform: translateX(2000px);\n\t}\n}\n\n.fadeOutRightBig {\n\t-webkit-animation-name: fadeOutRightBig;\n\t-moz-animation-name: fadeOutRightBig;\n\t-o-animation-name: fadeOutRightBig;\n\tanimation-name: fadeOutRightBig;\n}\n@-webkit-keyframes bounceIn {\n\t0% {\n\t\topacity: 0;\n\t\t-webkit-transform: scale(.3);\n\t}\n\t\n\t50% {\n\t\topacity: 1;\n\t\t-webkit-transform: scale(1.05);\n\t}\n\t\n\t70% {\n\t\t-webkit-transform: scale(.9);\n\t}\n\t\n\t100% {\n\t\t-webkit-transform: scale(1);\n\t}\n}\n\n@-moz-keyframes bounceIn {\n\t0% {\n\t\topacity: 0;\n\t\t-moz-transform: scale(.3);\n\t}\n\t\n\t50% {\n\t\topacity: 1;\n\t\t-moz-transform: scale(1.05);\n\t}\n\t\n\t70% {\n\t\t-moz-transform: scale(.9);\n\t}\n\t\n\t100% {\n\t\t-moz-transform: scale(1);\n\t}\n}\n\n@-o-keyframes bounceIn {\n\t0% {\n\t\topacity: 0;\n\t\t-o-transform: scale(.3);\n\t}\n\t\n\t50% {\n\t\topacity: 1;\n\t\t-o-transform: scale(1.05);\n\t}\n\t\n\t70% {\n\t\t-o-transform: scale(.9);\n\t}\n\t\n\t100% {\n\t\t-o-transform: scale(1);\n\t}\n}\n\n@keyframes bounceIn {\n\t0% {\n\t\topacity: 0;\n\t\ttransform: scale(.3);\n\t}\n\t\n\t50% {\n\t\topacity: 1;\n\t\ttransform: scale(1.05);\n\t}\n\t\n\t70% {\n\t\ttransform: scale(.9);\n\t}\n\t\n\t100% {\n\t\ttransform: scale(1);\n\t}\n}\n\n.bounceIn {\n\t-webkit-animation-name: bounceIn;\n\t-moz-animation-name: bounceIn;\n\t-o-animation-name: bounceIn;\n\tanimation-name: bounceIn;\n}\n@-webkit-keyframes bounceInUp {\n\t0% {\n\t\topacity: 0;\n\t\t-webkit-transform: translateY(2000px);\n\t}\n\t\n\t60% {\n\t\topacity: 1;\n\t\t-webkit-transform: translateY(-30px);\n\t}\n\t\n\t80% {\n\t\t-webkit-transform: translateY(10px);\n\t}\n\t\n\t100% {\n\t\t-webkit-transform: translateY(0);\n\t}\n}\n@-moz-keyframes bounceInUp {\n\t0% {\n\t\topacity: 0;\n\t\t-moz-transform: translateY(2000px);\n\t}\n\t\n\t60% {\n\t\topacity: 1;\n\t\t-moz-transform: translateY(-30px);\n\t}\n\t\n\t80% {\n\t\t-moz-transform: translateY(10px);\n\t}\n\t\n\t100% {\n\t\t-moz-transform: translateY(0);\n\t}\n}\n\n@-o-keyframes bounceInUp {\n\t0% {\n\t\topacity: 0;\n\t\t-o-transform: translateY(2000px);\n\t}\n\t\n\t60% {\n\t\topacity: 1;\n\t\t-o-transform: translateY(-30px);\n\t}\n\t\n\t80% {\n\t\t-o-transform: translateY(10px);\n\t}\n\t\n\t100% {\n\t\t-o-transform: translateY(0);\n\t}\n}\n\n@keyframes bounceInUp {\n\t0% {\n\t\topacity: 0;\n\t\ttransform: translateY(2000px);\n\t}\n\t\n\t60% {\n\t\topacity: 1;\n\t\ttransform: translateY(-30px);\n\t}\n\t\n\t80% {\n\t\ttransform: translateY(10px);\n\t}\n\t\n\t100% {\n\t\ttransform: translateY(0);\n\t}\n}\n\n.bounceInUp {\n\t-webkit-animation-name: bounceInUp;\n\t-moz-animation-name: bounceInUp;\n\t-o-animation-name: bounceInUp;\n\tanimation-name: bounceInUp;\n}\n@-webkit-keyframes bounceInDown {\n\t0% {\n\t\topacity: 0;\n\t\t-webkit-transform: translateY(-2000px);\n\t}\n\t\n\t60% {\n\t\topacity: 1;\n\t\t-webkit-transform: translateY(30px);\n\t}\n\t\n\t80% {\n\t\t-webkit-transform: translateY(-10px);\n\t}\n\t\n\t100% {\n\t\t-webkit-transform: translateY(0);\n\t}\n}\n\n@-moz-keyframes bounceInDown {\n\t0% {\n\t\topacity: 0;\n\t\t-moz-transform: translateY(-2000px);\n\t}\n\t\n\t60% {\n\t\topacity: 1;\n\t\t-moz-transform: translateY(30px);\n\t}\n\t\n\t80% {\n\t\t-moz-transform: translateY(-10px);\n\t}\n\t\n\t100% {\n\t\t-moz-transform: translateY(0);\n\t}\n}\n\n@-o-keyframes bounceInDown {\n\t0% {\n\t\topacity: 0;\n\t\t-o-transform: translateY(-2000px);\n\t}\n\t\n\t60% {\n\t\topacity: 1;\n\t\t-o-transform: translateY(30px);\n\t}\n\t\n\t80% {\n\t\t-o-transform: translateY(-10px);\n\t}\n\t\n\t100% {\n\t\t-o-transform: translateY(0);\n\t}\n}\n\n@keyframes bounceInDown {\n\t0% {\n\t\topacity: 0;\n\t\ttransform: translateY(-2000px);\n\t}\n\t\n\t60% {\n\t\topacity: 1;\n\t\ttransform: translateY(30px);\n\t}\n\t\n\t80% {\n\t\ttransform: translateY(-10px);\n\t}\n\t\n\t100% {\n\t\ttransform: translateY(0);\n\t}\n}\n\n.bounceInDown {\n\t-webkit-animation-name: bounceInDown;\n\t-moz-animation-name: bounceInDown;\n\t-o-animation-name: bounceInDown;\n\tanimation-name: bounceInDown;\n}\n@-webkit-keyframes bounceInLeft {\n\t0% {\n\t\topacity: 0;\n\t\t-webkit-transform: translateX(-2000px);\n\t}\n\t\n\t60% {\n\t\topacity: 1;\n\t\t-webkit-transform: translateX(30px);\n\t}\n\t\n\t80% {\n\t\t-webkit-transform: translateX(-10px);\n\t}\n\t\n\t100% {\n\t\t-webkit-transform: translateX(0);\n\t}\n}\n\n@-moz-keyframes bounceInLeft {\n\t0% {\n\t\topacity: 0;\n\t\t-moz-transform: translateX(-2000px);\n\t}\n\t\n\t60% {\n\t\topacity: 1;\n\t\t-moz-transform: translateX(30px);\n\t}\n\t\n\t80% {\n\t\t-moz-transform: translateX(-10px);\n\t}\n\t\n\t100% {\n\t\t-moz-transform: translateX(0);\n\t}\n}\n\n@-o-keyframes bounceInLeft {\n\t0% {\n\t\topacity: 0;\n\t\t-o-transform: translateX(-2000px);\n\t}\n\t\n\t60% {\n\t\topacity: 1;\n\t\t-o-transform: translateX(30px);\n\t}\n\t\n\t80% {\n\t\t-o-transform: translateX(-10px);\n\t}\n\t\n\t100% {\n\t\t-o-transform: translateX(0);\n\t}\n}\n\n@keyframes bounceInLeft {\n\t0% {\n\t\topacity: 0;\n\t\ttransform: translateX(-2000px);\n\t}\n\t\n\t60% {\n\t\topacity: 1;\n\t\ttransform: translateX(30px);\n\t}\n\t\n\t80% {\n\t\ttransform: translateX(-10px);\n\t}\n\t\n\t100% {\n\t\ttransform: translateX(0);\n\t}\n}\n\n.bounceInLeft {\n\t-webkit-animation-name: bounceInLeft;\n\t-moz-animation-name: bounceInLeft;\n\t-o-animation-name: bounceInLeft;\n\tanimation-name: bounceInLeft;\n}\n@-webkit-keyframes bounceInRight {\n\t0% {\n\t\topacity: 0;\n\t\t-webkit-transform: translateX(2000px);\n\t}\n\t\n\t60% {\n\t\topacity: 1;\n\t\t-webkit-transform: translateX(-30px);\n\t}\n\t\n\t80% {\n\t\t-webkit-transform: translateX(10px);\n\t}\n\t\n\t100% {\n\t\t-webkit-transform: translateX(0);\n\t}\n}\n\n@-moz-keyframes bounceInRight {\n\t0% {\n\t\topacity: 0;\n\t\t-moz-transform: translateX(2000px);\n\t}\n\t\n\t60% {\n\t\topacity: 1;\n\t\t-moz-transform: translateX(-30px);\n\t}\n\t\n\t80% {\n\t\t-moz-transform: translateX(10px);\n\t}\n\t\n\t100% {\n\t\t-moz-transform: translateX(0);\n\t}\n}\n\n@-o-keyframes bounceInRight {\n\t0% {\n\t\topacity: 0;\n\t\t-o-transform: translateX(2000px);\n\t}\n\t\n\t60% {\n\t\topacity: 1;\n\t\t-o-transform: translateX(-30px);\n\t}\n\t\n\t80% {\n\t\t-o-transform: translateX(10px);\n\t}\n\t\n\t100% {\n\t\t-o-transform: translateX(0);\n\t}\n}\n\n@keyframes bounceInRight {\n\t0% {\n\t\topacity: 0;\n\t\ttransform: translateX(2000px);\n\t}\n\t\n\t60% {\n\t\topacity: 1;\n\t\ttransform: translateX(-30px);\n\t}\n\t\n\t80% {\n\t\ttransform: translateX(10px);\n\t}\n\t\n\t100% {\n\t\ttransform: translateX(0);\n\t}\n}\n\n.bounceInRight {\n\t-webkit-animation-name: bounceInRight;\n\t-moz-animation-name: bounceInRight;\n\t-o-animation-name: bounceInRight;\n\tanimation-name: bounceInRight;\n}\n@-webkit-keyframes bounceOut {\n\t0% {\n\t\t-webkit-transform: scale(1);\n\t}\n\t\n\t25% {\n\t\t-webkit-transform: scale(.95);\n\t}\n\t\n\t50% {\n\t\topacity: 1;\n\t\t-webkit-transform: scale(1.1);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\t-webkit-transform: scale(.3);\n\t}\t\n}\n\n@-moz-keyframes bounceOut {\n\t0% {\n\t\t-moz-transform: scale(1);\n\t}\n\t\n\t25% {\n\t\t-moz-transform: scale(.95);\n\t}\n\t\n\t50% {\n\t\topacity: 1;\n\t\t-moz-transform: scale(1.1);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\t-moz-transform: scale(.3);\n\t}\t\n}\n\n@-o-keyframes bounceOut {\n\t0% {\n\t\t-o-transform: scale(1);\n\t}\n\t\n\t25% {\n\t\t-o-transform: scale(.95);\n\t}\n\t\n\t50% {\n\t\topacity: 1;\n\t\t-o-transform: scale(1.1);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\t-o-transform: scale(.3);\n\t}\t\n}\n\n@keyframes bounceOut {\n\t0% {\n\t\ttransform: scale(1);\n\t}\n\t\n\t25% {\n\t\ttransform: scale(.95);\n\t}\n\t\n\t50% {\n\t\topacity: 1;\n\t\ttransform: scale(1.1);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\ttransform: scale(.3);\n\t}\t\n}\n\n.bounceOut {\n\t-webkit-animation-name: bounceOut;\n\t-moz-animation-name: bounceOut;\n\t-o-animation-name: bounceOut;\n\tanimation-name: bounceOut;\n}\n@-webkit-keyframes bounceOutUp {\n\t0% {\n\t\t-webkit-transform: translateY(0);\n\t}\n\t\n\t20% {\n\t\topacity: 1;\n\t\t-webkit-transform: translateY(20px);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\t-webkit-transform: translateY(-2000px);\n\t}\n}\n\n@-moz-keyframes bounceOutUp {\n\t0% {\n\t\t-moz-transform: translateY(0);\n\t}\n\t\n\t20% {\n\t\topacity: 1;\n\t\t-moz-transform: translateY(20px);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\t-moz-transform: translateY(-2000px);\n\t}\n}\n\n@-o-keyframes bounceOutUp {\n\t0% {\n\t\t-o-transform: translateY(0);\n\t}\n\t\n\t20% {\n\t\topacity: 1;\n\t\t-o-transform: translateY(20px);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\t-o-transform: translateY(-2000px);\n\t}\n}\n\n@keyframes bounceOutUp {\n\t0% {\n\t\ttransform: translateY(0);\n\t}\n\t\n\t20% {\n\t\topacity: 1;\n\t\ttransform: translateY(20px);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\ttransform: translateY(-2000px);\n\t}\n}\n\n.bounceOutUp {\n\t-webkit-animation-name: bounceOutUp;\n\t-moz-animation-name: bounceOutUp;\n\t-o-animation-name: bounceOutUp;\n\tanimation-name: bounceOutUp;\n}\n@-webkit-keyframes bounceOutDown {\n\t0% {\n\t\t-webkit-transform: translateY(0);\n\t}\n\t\n\t20% {\n\t\topacity: 1;\n\t\t-webkit-transform: translateY(-20px);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\t-webkit-transform: translateY(2000px);\n\t}\n}\n\n@-moz-keyframes bounceOutDown {\n\t0% {\n\t\t-moz-transform: translateY(0);\n\t}\n\t\n\t20% {\n\t\topacity: 1;\n\t\t-moz-transform: translateY(-20px);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\t-moz-transform: translateY(2000px);\n\t}\n}\n\n@-o-keyframes bounceOutDown {\n\t0% {\n\t\t-o-transform: translateY(0);\n\t}\n\t\n\t20% {\n\t\topacity: 1;\n\t\t-o-transform: translateY(-20px);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\t-o-transform: translateY(2000px);\n\t}\n}\n\n@keyframes bounceOutDown {\n\t0% {\n\t\ttransform: translateY(0);\n\t}\n\t\n\t20% {\n\t\topacity: 1;\n\t\ttransform: translateY(-20px);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\ttransform: translateY(2000px);\n\t}\n}\n\n.bounceOutDown {\n\t-webkit-animation-name: bounceOutDown;\n\t-moz-animation-name: bounceOutDown;\n\t-o-animation-name: bounceOutDown;\n\tanimation-name: bounceOutDown;\n}\n@-webkit-keyframes bounceOutLeft {\n\t0% {\n\t\t-webkit-transform: translateX(0);\n\t}\n\t\n\t20% {\n\t\topacity: 1;\n\t\t-webkit-transform: translateX(20px);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\t-webkit-transform: translateX(-2000px);\n\t}\n}\n\n@-moz-keyframes bounceOutLeft {\n\t0% {\n\t\t-moz-transform: translateX(0);\n\t}\n\t\n\t20% {\n\t\topacity: 1;\n\t\t-moz-transform: translateX(20px);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\t-moz-transform: translateX(-2000px);\n\t}\n}\n\n@-o-keyframes bounceOutLeft {\n\t0% {\n\t\t-o-transform: translateX(0);\n\t}\n\t\n\t20% {\n\t\topacity: 1;\n\t\t-o-transform: translateX(20px);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\t-o-transform: translateX(-2000px);\n\t}\n}\n\n@keyframes bounceOutLeft {\n\t0% {\n\t\ttransform: translateX(0);\n\t}\n\t\n\t20% {\n\t\topacity: 1;\n\t\ttransform: translateX(20px);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\ttransform: translateX(-2000px);\n\t}\n}\n\n.bounceOutLeft {\n\t-webkit-animation-name: bounceOutLeft;\n\t-moz-animation-name: bounceOutLeft;\n\t-o-animation-name: bounceOutLeft;\n\tanimation-name: bounceOutLeft;\n}\n@-webkit-keyframes bounceOutRight {\n\t0% {\n\t\t-webkit-transform: translateX(0);\n\t}\n\t\n\t20% {\n\t\topacity: 1;\n\t\t-webkit-transform: translateX(-20px);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\t-webkit-transform: translateX(2000px);\n\t}\n}\n\n@-moz-keyframes bounceOutRight {\n\t0% {\n\t\t-moz-transform: translateX(0);\n\t}\n\t\n\t20% {\n\t\topacity: 1;\n\t\t-moz-transform: translateX(-20px);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\t-moz-transform: translateX(2000px);\n\t}\n}\n\n@-o-keyframes bounceOutRight {\n\t0% {\n\t\t-o-transform: translateX(0);\n\t}\n\t\n\t20% {\n\t\topacity: 1;\n\t\t-o-transform: translateX(-20px);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\t-o-transform: translateX(2000px);\n\t}\n}\n\n@keyframes bounceOutRight {\n\t0% {\n\t\ttransform: translateX(0);\n\t}\n\t\n\t20% {\n\t\topacity: 1;\n\t\ttransform: translateX(-20px);\n\t}\n\t\n\t100% {\n\t\topacity: 0;\n\t\ttransform: translateX(2000px);\n\t}\n}\n\n.bounceOutRight {\n\t-webkit-animation-name: bounceOutRight;\n\t-moz-animation-name: bounceOutRight;\n\t-o-animation-name: bounceOutRight;\n\tanimation-name: bounceOutRight;\n}\n@-webkit-keyframes rotateIn {\n\t0% {\n\t\t-webkit-transform-origin: center center;\n\t\t-webkit-transform: rotate(-200deg);\n\t\topacity: 0;\n\t}\n\t\n\t100% {\n\t\t-webkit-transform-origin: center center;\n\t\t-webkit-transform: rotate(0);\n\t\topacity: 1;\n\t}\n}\n@-moz-keyframes rotateIn {\n\t0% {\n\t\t-moz-transform-origin: center center;\n\t\t-moz-transform: rotate(-200deg);\n\t\topacity: 0;\n\t}\n\t\n\t100% {\n\t\t-moz-transform-origin: center center;\n\t\t-moz-transform: rotate(0);\n\t\topacity: 1;\n\t}\n}\n@-o-keyframes rotateIn {\n\t0% {\n\t\t-o-transform-origin: center center;\n\t\t-o-transform: rotate(-200deg);\n\t\topacity: 0;\n\t}\n\t\n\t100% {\n\t\t-o-transform-origin: center center;\n\t\t-o-transform: rotate(0);\n\t\topacity: 1;\n\t}\n}\n@keyframes rotateIn {\n\t0% {\n\t\ttransform-origin: center center;\n\t\ttransform: rotate(-200deg);\n\t\topacity: 0;\n\t}\n\t\n\t100% {\n\t\ttransform-origin: center center;\n\t\ttransform: rotate(0);\n\t\topacity: 1;\n\t}\n}\n\n.rotateIn {\n\t-webkit-animation-name: rotateIn;\n\t-moz-animation-name: rotateIn;\n\t-o-animation-name: rotateIn;\n\tanimation-name: rotateIn;\n}\n@-webkit-keyframes rotateInUpLeft {\n\t0% {\n\t\t-webkit-transform-origin: left bottom;\n\t\t-webkit-transform: rotate(90deg);\n\t\topacity: 0;\n\t}\n\t\n\t100% {\n\t\t-webkit-transform-origin: left bottom;\n\t\t-webkit-transform: rotate(0);\n\t\topacity: 1;\n\t}\n}\n\n@-moz-keyframes rotateInUpLeft {\n\t0% {\n\t\t-moz-transform-origin: left bottom;\n\t\t-moz-transform: rotate(90deg);\n\t\topacity: 0;\n\t}\n\t\n\t100% {\n\t\t-moz-transform-origin: left bottom;\n\t\t-moz-transform: rotate(0);\n\t\topacity: 1;\n\t}\n}\n\n@-o-keyframes rotateInUpLeft {\n\t0% {\n\t\t-o-transform-origin: left bottom;\n\t\t-o-transform: rotate(90deg);\n\t\topacity: 0;\n\t}\n\t\n\t100% {\n\t\t-o-transform-origin: left bottom;\n\t\t-o-transform: rotate(0);\n\t\topacity: 1;\n\t}\n}\n\n@keyframes rotateInUpLeft {\n\t0% {\n\t\ttransform-origin: left bottom;\n\t\ttransform: rotate(90deg);\n\t\topacity: 0;\n\t}\n\t\n\t100% {\n\t\ttransform-origin: left bottom;\n\t\ttransform: rotate(0);\n\t\topacity: 1;\n\t}\n}\n\n.rotateInUpLeft {\n\t-webkit-animation-name: rotateInUpLeft;\n\t-moz-animation-name: rotateInUpLeft;\n\t-o-animation-name: rotateInUpLeft;\n\tanimation-name: rotateInUpLeft;\n}\n@-webkit-keyframes rotateInDownLeft {\n\t0% {\n\t\t-webkit-transform-origin: left bottom;\n\t\t-webkit-transform: rotate(-90deg);\n\t\topacity: 0;\n\t}\n\t\n\t100% {\n\t\t-webkit-transform-origin: left bottom;\n\t\t-webkit-transform: rotate(0);\n\t\topacity: 1;\n\t}\n}\n\n@-moz-keyframes rotateInDownLeft {\n\t0% {\n\t\t-moz-transform-origin: left bottom;\n\t\t-moz-transform: rotate(-90deg);\n\t\topacity: 0;\n\t}\n\t\n\t100% {\n\t\t-moz-transform-origin: left bottom;\n\t\t-moz-transform: rotate(0);\n\t\topacity: 1;\n\t}\n}\n\n@-o-keyframes rotateInDownLeft {\n\t0% {\n\t\t-o-transform-origin: left bottom;\n\t\t-o-transform: rotate(-90deg);\n\t\topacity: 0;\n\t}\n\t\n\t100% {\n\t\t-o-transform-origin: left bottom;\n\t\t-o-transform: rotate(0);\n\t\topacity: 1;\n\t}\n}\n\n@keyframes rotateInDownLeft {\n\t0% {\n\t\ttransform-origin: left bottom;\n\t\ttransform: rotate(-90deg);\n\t\topacity: 0;\n\t}\n\t\n\t100% {\n\t\ttransform-origin: left bottom;\n\t\ttransform: rotate(0);\n\t\topacity: 1;\n\t}\n}\n\n.rotateInDownLeft {\n\t-webkit-animation-name: rotateInDownLeft;\n\t-moz-animation-name: rotateInDownLeft;\n\t-o-animation-name: rotateInDownLeft;\n\tanimation-name: rotateInDownLeft;\n}\n@-webkit-keyframes rotateInUpRight {\n\t0% {\n\t\t-webkit-transform-origin: right bottom;\n\t\t-webkit-transform: rotate(-90deg);\n\t\topacity: 0;\n\t}\n\t\n\t100% {\n\t\t-webkit-transform-origin: right bottom;\n\t\t-webkit-transform: rotate(0);\n\t\topacity: 1;\n\t}\n}\n\n@-moz-keyframes rotateInUpRight {\n\t0% {\n\t\t-moz-transform-origin: right bottom;\n\t\t-moz-transform: rotate(-90deg);\n\t\topacity: 0;\n\t}\n\t\n\t100% {\n\t\t-moz-transform-origin: right bottom;\n\t\t-moz-transform: rotate(0);\n\t\topacity: 1;\n\t}\n}\n\n@-o-keyframes rotateInUpRight {\n\t0% {\n\t\t-o-transform-origin: right bottom;\n\t\t-o-transform: rotate(-90deg);\n\t\topacity: 0;\n\t}\n\t\n\t100% {\n\t\t-o-transform-origin: right bottom;\n\t\t-o-transform: rotate(0);\n\t\topacity: 1;\n\t}\n}\n\n@keyframes rotateInUpRight {\n\t0% {\n\t\ttransform-origin: right bottom;\n\t\ttransform: rotate(-90deg);\n\t\topacity: 0;\n\t}\n\t\n\t100% {\n\t\ttransform-origin: right bottom;\n\t\ttransform: rotate(0);\n\t\topacity: 1;\n\t}\n}\n\n.rotateInUpRight {\n\t-webkit-animation-name: rotateInUpRight;\n\t-moz-animation-name: rotateInUpRight;\n\t-o-animation-name: rotateInUpRight;\n\tanimation-name: rotateInUpRight;\n}\n@-webkit-keyframes rotateInDownRight {\n\t0% {\n\t\t-webkit-transform-origin: right bottom;\n\t\t-webkit-transform: rotate(90deg);\n\t\topacity: 0;\n\t}\n\t\n\t100% {\n\t\t-webkit-transform-origin: right bottom;\n\t\t-webkit-transform: rotate(0);\n\t\topacity: 1;\n\t}\n}\n\n@-moz-keyframes rotateInDownRight {\n\t0% {\n\t\t-moz-transform-origin: right bottom;\n\t\t-moz-transform: rotate(90deg);\n\t\topacity: 0;\n\t}\n\t\n\t100% {\n\t\t-moz-transform-origin: right bottom;\n\t\t-moz-transform: rotate(0);\n\t\topacity: 1;\n\t}\n}\n\n@-o-keyframes rotateInDownRight {\n\t0% {\n\t\t-o-transform-origin: right bottom;\n\t\t-o-transform: rotate(90deg);\n\t\topacity: 0;\n\t}\n\t\n\t100% {\n\t\t-o-transform-origin: right bottom;\n\t\t-o-transform: rotate(0);\n\t\topacity: 1;\n\t}\n}\n\n@keyframes rotateInDownRight {\n\t0% {\n\t\ttransform-origin: right bottom;\n\t\ttransform: rotate(90deg);\n\t\topacity: 0;\n\t}\n\t\n\t100% {\n\t\ttransform-origin: right bottom;\n\t\ttransform: rotate(0);\n\t\topacity: 1;\n\t}\n}\n\n.rotateInDownRight {\n\t-webkit-animation-name: rotateInDownRight;\n\t-moz-animation-name: rotateInDownRight;\n\t-o-animation-name: rotateInDownRight;\n\tanimation-name: rotateInDownRight;\n}\n@-webkit-keyframes rotateOut {\n\t0% {\n\t\t-webkit-transform-origin: center center;\n\t\t-webkit-transform: rotate(0);\n\t\topacity: 1;\n\t}\n\t\n\t100% {\n\t\t-webkit-transform-origin: center center;\n\t\t-webkit-transform: rotate(200deg);\n\t\topacity: 0;\n\t}\n}\n\n@-moz-keyframes rotateOut {\n\t0% {\n\t\t-moz-transform-origin: center center;\n\t\t-moz-transform: rotate(0);\n\t\topacity: 1;\n\t}\n\t\n\t100% {\n\t\t-moz-transform-origin: center center;\n\t\t-moz-transform: rotate(200deg);\n\t\topacity: 0;\n\t}\n}\n\n@-o-keyframes rotateOut {\n\t0% {\n\t\t-o-transform-origin: center center;\n\t\t-o-transform: rotate(0);\n\t\topacity: 1;\n\t}\n\t\n\t100% {\n\t\t-o-transform-origin: center center;\n\t\t-o-transform: rotate(200deg);\n\t\topacity: 0;\n\t}\n}\n\n@keyframes rotateOut {\n\t0% {\n\t\ttransform-origin: center center;\n\t\ttransform: rotate(0);\n\t\topacity: 1;\n\t}\n\t\n\t100% {\n\t\ttransform-origin: center center;\n\t\ttransform: rotate(200deg);\n\t\topacity: 0;\n\t}\n}\n\n.rotateOut {\n\t-webkit-animation-name: rotateOut;\n\t-moz-animation-name: rotateOut;\n\t-o-animation-name: rotateOut;\n\tanimation-name: rotateOut;\n}\n@-webkit-keyframes rotateOutUpLeft {\n\t0% {\n\t\t-webkit-transform-origin: left bottom;\n\t\t-webkit-transform: rotate(0);\n\t\topacity: 1;\n\t}\n\t\n\t100% {\n\t\t-webkit-transform-origin: left bottom;\n\t\t-webkit-transform: rotate(-90deg);\n\t\topacity: 0;\n\t}\n}\n\n@-moz-keyframes rotateOutUpLeft {\n\t0% {\n\t\t-moz-transform-origin: left bottom;\n\t\t-moz-transform: rotate(0);\n\t\topacity: 1;\n\t}\n\t\n\t100% {\n\t\t-moz-transform-origin: left bottom;\n\t\t-moz-transform: rotate(-90deg);\n\t\topacity: 0;\n\t}\n}\n\n@-o-keyframes rotateOutUpLeft {\n\t0% {\n\t\t-o-transform-origin: left bottom;\n\t\t-o-transform: rotate(0);\n\t\topacity: 1;\n\t}\n\t\n\t100% {\n\t\t-o-transform-origin: left bottom;\n\t\t-o-transform: rotate(-90deg);\n\t\topacity: 0;\n\t}\n}\n\n@keyframes rotateOutUpLeft {\n\t0% {\n\t\ttransform-origin: left bottom;\n\t\ttransform: rotate(0);\n\t\topacity: 1;\n\t}\n\t\n\t100% {\n\t\ttransform-origin: left bottom;\n\t\ttransform: rotate(-90deg);\n\t\topacity: 0;\n\t}\n}\n\n.rotateOutUpLeft {\n\t-webkit-animation-name: rotateOutUpLeft;\n\t-moz-animation-name: rotateOutUpLeft;\n\t-o-animation-name: rotateOutUpLeft;\n\tanimation-name: rotateOutUpLeft;\n}\n@-webkit-keyframes rotateOutDownLeft {\n\t0% {\n\t\t-webkit-transform-origin: left bottom;\n\t\t-webkit-transform: rotate(0);\n\t\topacity: 1;\n\t}\n\t\n\t100% {\n\t\t-webkit-transform-origin: left bottom;\n\t\t-webkit-transform: rotate(90deg);\n\t\topacity: 0;\n\t}\n}\n\n@-moz-keyframes rotateOutDownLeft {\n\t0% {\n\t\t-moz-transform-origin: left bottom;\n\t\t-moz-transform: rotate(0);\n\t\topacity: 1;\n\t}\n\t\n\t100% {\n\t\t-moz-transform-origin: left bottom;\n\t\t-moz-transform: rotate(90deg);\n\t\topacity: 0;\n\t}\n}\n\n@-o-keyframes rotateOutDownLeft {\n\t0% {\n\t\t-o-transform-origin: left bottom;\n\t\t-o-transform: rotate(0);\n\t\topacity: 1;\n\t}\n\t\n\t100% {\n\t\t-o-transform-origin: left bottom;\n\t\t-o-transform: rotate(90deg);\n\t\topacity: 0;\n\t}\n}\n\n@keyframes rotateOutDownLeft {\n\t0% {\n\t\ttransform-origin: left bottom;\n\t\ttransform: rotate(0);\n\t\topacity: 1;\n\t}\n\t\n\t100% {\n\t\ttransform-origin: left bottom;\n\t\ttransform: rotate(90deg);\n\t\topacity: 0;\n\t}\n}\n\n.rotateOutDownLeft {\n\t-webkit-animation-name: rotateOutDownLeft;\n\t-moz-animation-name: rotateOutDownLeft;\n\t-o-animation-name: rotateOutDownLeft;\n\tanimation-name: rotateOutDownLeft;\n}\n@-webkit-keyframes rotateOutUpRight {\n\t0% {\n\t\t-webkit-transform-origin: right bottom;\n\t\t-webkit-transform: rotate(0);\n\t\topacity: 1;\n\t}\n\t\n\t100% {\n\t\t-webkit-transform-origin: right bottom;\n\t\t-webkit-transform: rotate(90deg);\n\t\topacity: 0;\n\t}\n}\n\n@-moz-keyframes rotateOutUpRight {\n\t0% {\n\t\t-moz-transform-origin: right bottom;\n\t\t-moz-transform: rotate(0);\n\t\topacity: 1;\n\t}\n\t\n\t100% {\n\t\t-moz-transform-origin: right bottom;\n\t\t-moz-transform: rotate(90deg);\n\t\topacity: 0;\n\t}\n}\n\n@-o-keyframes rotateOutUpRight {\n\t0% {\n\t\t-o-transform-origin: right bottom;\n\t\t-o-transform: rotate(0);\n\t\topacity: 1;\n\t}\n\t\n\t100% {\n\t\t-o-transform-origin: right bottom;\n\t\t-o-transform: rotate(90deg);\n\t\topacity: 0;\n\t}\n}\n\n@keyframes rotateOutUpRight {\n\t0% {\n\t\ttransform-origin: right bottom;\n\t\ttransform: rotate(0);\n\t\topacity: 1;\n\t}\n\t\n\t100% {\n\t\ttransform-origin: right bottom;\n\t\ttransform: rotate(90deg);\n\t\topacity: 0;\n\t}\n}\n\n.rotateOutUpRight {\n\t-webkit-animation-name: rotateOutUpRight;\n\t-moz-animation-name: rotateOutUpRight;\n\t-o-animation-name: rotateOutUpRight;\n\tanimation-name: rotateOutUpRight;\n}\n@-webkit-keyframes rotateOutDownRight {\n\t0% {\n\t\t-webkit-transform-origin: right bottom;\n\t\t-webkit-transform: rotate(0);\n\t\topacity: 1;\n\t}\n\t\n\t100% {\n\t\t-webkit-transform-origin: right bottom;\n\t\t-webkit-transform: rotate(-90deg);\n\t\topacity: 0;\n\t}\n}\n\n@-moz-keyframes rotateOutDownRight {\n\t0% {\n\t\t-moz-transform-origin: right bottom;\n\t\t-moz-transform: rotate(0);\n\t\topacity: 1;\n\t}\n\t\n\t100% {\n\t\t-moz-transform-origin: right bottom;\n\t\t-moz-transform: rotate(-90deg);\n\t\topacity: 0;\n\t}\n}\n\n@-o-keyframes rotateOutDownRight {\n\t0% {\n\t\t-o-transform-origin: right bottom;\n\t\t-o-transform: rotate(0);\n\t\topacity: 1;\n\t}\n\t\n\t100% {\n\t\t-o-transform-origin: right bottom;\n\t\t-o-transform: rotate(-90deg);\n\t\topacity: 0;\n\t}\n}\n\n@keyframes rotateOutDownRight {\n\t0% {\n\t\ttransform-origin: right bottom;\n\t\ttransform: rotate(0);\n\t\topacity: 1;\n\t}\n\t\n\t100% {\n\t\ttransform-origin: right bottom;\n\t\ttransform: rotate(-90deg);\n\t\topacity: 0;\n\t}\n}\n\n.rotateOutDownRight {\n\t-webkit-animation-name: rotateOutDownRight;\n\t-moz-animation-name: rotateOutDownRight;\n\t-o-animation-name: rotateOutDownRight;\n\tanimation-name: rotateOutDownRight;\n}\n@-webkit-keyframes hinge {\n\t0% { -webkit-transform: rotate(0); -webkit-transform-origin: top left; -webkit-animation-timing-function: ease-in-out; }\t\n\t20%, 60% { -webkit-transform: rotate(80deg); -webkit-transform-origin: top left; -webkit-animation-timing-function: ease-in-out; }\t\n\t40% { -webkit-transform: rotate(60deg); -webkit-transform-origin: top left; -webkit-animation-timing-function: ease-in-out; }\t\n\t80% { -webkit-transform: rotate(60deg) translateY(0); opacity: 1; -webkit-transform-origin: top left; -webkit-animation-timing-function: ease-in-out; }\t\n\t100% { -webkit-transform: translateY(700px); opacity: 0; }\n}\n\n@-moz-keyframes hinge {\n\t0% { -moz-transform: rotate(0); -moz-transform-origin: top left; -moz-animation-timing-function: ease-in-out; }\t\n\t20%, 60% { -moz-transform: rotate(80deg); -moz-transform-origin: top left; -moz-animation-timing-function: ease-in-out; }\t\n\t40% { -moz-transform: rotate(60deg); -moz-transform-origin: top left; -moz-animation-timing-function: ease-in-out; }\t\n\t80% { -moz-transform: rotate(60deg) translateY(0); opacity: 1; -moz-transform-origin: top left; -moz-animation-timing-function: ease-in-out; }\t\n\t100% { -moz-transform: translateY(700px); opacity: 0; }\n}\n\n@-o-keyframes hinge {\n\t0% { -o-transform: rotate(0); -o-transform-origin: top left; -o-animation-timing-function: ease-in-out; }\t\n\t20%, 60% { -o-transform: rotate(80deg); -o-transform-origin: top left; -o-animation-timing-function: ease-in-out; }\t\n\t40% { -o-transform: rotate(60deg); -o-transform-origin: top left; -o-animation-timing-function: ease-in-out; }\t\n\t80% { -o-transform: rotate(60deg) translateY(0); opacity: 1; -o-transform-origin: top left; -o-animation-timing-function: ease-in-out; }\t\n\t100% { -o-transform: translateY(700px); opacity: 0; }\n}\n\n@keyframes hinge {\n\t0% { transform: rotate(0); transform-origin: top left; animation-timing-function: ease-in-out; }\t\n\t20%, 60% { transform: rotate(80deg); transform-origin: top left; animation-timing-function: ease-in-out; }\t\n\t40% { transform: rotate(60deg); transform-origin: top left; animation-timing-function: ease-in-out; }\t\n\t80% { transform: rotate(60deg) translateY(0); opacity: 1; transform-origin: top left; animation-timing-function: ease-in-out; }\t\n\t100% { transform: translateY(700px); opacity: 0; }\n}\n\n.hinge {\n\t-webkit-animation-name: hinge;\n\t-moz-animation-name: hinge;\n\t-o-animation-name: hinge;\n\tanimation-name: hinge;\n}\n/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */\n\n@-webkit-keyframes rollIn {\n\t0% { opacity: 0; -webkit-transform: translateX(-100%) rotate(-120deg); }\n\t100% { opacity: 1; -webkit-transform: translateX(0px) rotate(0deg); }\n}\n\n@-moz-keyframes rollIn {\n\t0% { opacity: 0; -moz-transform: translateX(-100%) rotate(-120deg); }\n\t100% { opacity: 1; -moz-transform: translateX(0px) rotate(0deg); }\n}\n\n@-o-keyframes rollIn {\n\t0% { opacity: 0; -o-transform: translateX(-100%) rotate(-120deg); }\n\t100% { opacity: 1; -o-transform: translateX(0px) rotate(0deg); }\n}\n\n@keyframes rollIn {\n\t0% { opacity: 0; transform: translateX(-100%) rotate(-120deg); }\n\t100% { opacity: 1; transform: translateX(0px) rotate(0deg); }\n}\n\n.rollIn {\n\t-webkit-animation-name: rollIn;\n\t-moz-animation-name: rollIn;\n\t-o-animation-name: rollIn;\n\tanimation-name: rollIn;\n}\n/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */\n\n@-webkit-keyframes rollOut {\n    0% {\n\t\topacity: 1;\n\t\t-webkit-transform: translateX(0px) rotate(0deg);\n\t}\n\n    100% {\n\t\topacity: 0;\n\t\t-webkit-transform: translateX(100%) rotate(120deg);\n\t}\n}\n\n@-moz-keyframes rollOut {\n    0% {\n\t\topacity: 1;\n\t\t-moz-transform: translateX(0px) rotate(0deg);\n\t}\n\n    100% {\n\t\topacity: 0;\n\t\t-moz-transform: translateX(100%) rotate(120deg);\n\t}\n}\n\n@-o-keyframes rollOut {\n    0% {\n\t\topacity: 1;\n\t\t-o-transform: translateX(0px) rotate(0deg);\n\t}\n\n    100% {\n\t\topacity: 0;\n\t\t-o-transform: translateX(100%) rotate(120deg);\n\t}\n}\n\n@keyframes rollOut {\n    0% {\n\t\topacity: 1;\n\t\ttransform: translateX(0px) rotate(0deg);\n\t}\n\n    100% {\n\t\topacity: 0;\n\t\ttransform: translateX(100%) rotate(120deg);\n\t}\n}\n\n.rollOut {\n\t-webkit-animation-name: rollOut;\n\t-moz-animation-name: rollOut;\n\t-o-animation-name: rollOut;\n\tanimation-name: rollOut;\n}\n\n/* originally authored by Angelo Rohit - https://github.com/angelorohit */\n\n@-webkit-keyframes lightSpeedIn {\n\t0% { -webkit-transform: translateX(100%) skewX(-30deg); opacity: 0; }\n\t60% { -webkit-transform: translateX(-20%) skewX(30deg); opacity: 1; }\n\t80% { -webkit-transform: translateX(0%) skewX(-15deg); opacity: 1; }\n\t100% { -webkit-transform: translateX(0%) skewX(0deg); opacity: 1; }\n}\n\n@-moz-keyframes lightSpeedIn {\n\t0% { -moz-transform: translateX(100%) skewX(-30deg); opacity: 0; }\n\t60% { -moz-transform: translateX(-20%) skewX(30deg); opacity: 1; }\n\t80% { -moz-transform: translateX(0%) skewX(-15deg); opacity: 1; }\n\t100% { -moz-transform: translateX(0%) skewX(0deg); opacity: 1; }\n}\n\n@-o-keyframes lightSpeedIn {\n\t0% { -o-transform: translateX(100%) skewX(-30deg); opacity: 0; }\n\t60% { -o-transform: translateX(-20%) skewX(30deg); opacity: 1; }\n\t80% { -o-transform: translateX(0%) skewX(-15deg); opacity: 1; }\n\t100% { -o-transform: translateX(0%) skewX(0deg); opacity: 1; }\n}\n\n@keyframes lightSpeedIn {\n\t0% { transform: translateX(100%) skewX(-30deg); opacity: 0; }\n\t60% { transform: translateX(-20%) skewX(30deg); opacity: 1; }\n\t80% { transform: translateX(0%) skewX(-15deg); opacity: 1; }\n\t100% { transform: translateX(0%) skewX(0deg); opacity: 1; }\n}\n\n.lightSpeedIn {\n    -webkit-animation-name: lightSpeedIn;\n    -moz-animation-name: lightSpeedIn;\n    -o-animation-name: lightSpeedIn;\n    animation-name: lightSpeedIn;\n\n    -webkit-animation-timing-function: ease-out;\n    -moz-animation-timing-function: ease-out;\n    -o-animation-timing-function: ease-out;\n    animation-timing-function: ease-out;\n}\n\n.animated.lightSpeedIn {\n    -webkit-animation-duration: 0.5s;\n    -moz-animation-duration: 0.5s;\n    -o-animation-duration: 0.5s;\n    animation-duration: 0.5s;\n}\n\n/* originally authored by Angelo Rohit - https://github.com/angelorohit */\n\n@-webkit-keyframes lightSpeedOut {\n    0% { -webkit-transform: translateX(0%) skewX(0deg); opacity: 1; }\n\t100% { -webkit-transform: translateX(100%) skewX(-30deg); opacity: 0; }\n}\n\n@-moz-keyframes lightSpeedOut {\n\t0% { -moz-transform: translateX(0%) skewX(0deg); opacity: 1; }\n\t100% { -moz-transform: translateX(100%) skewX(-30deg); opacity: 0; }\n}\n\n@-o-keyframes lightSpeedOut {\n\t0% { -o-transform: translateX(0%) skewX(0deg); opacity: 1; }\n\t100% { -o-transform: translateX(100%) skewX(-30deg); opacity: 0; }\n}\n\n@keyframes lightSpeedOut {\n\t0% { transform: translateX(0%) skewX(0deg); opacity: 1; }\n\t100% { transform: translateX(100%) skewX(-30deg); opacity: 0; }\n}\n\n.lightSpeedOut {\n    -webkit-animation-name: lightSpeedOut;\n    -moz-animation-name: lightSpeedOut;\n    -o-animation-name: lightSpeedOut;\n    animation-name: lightSpeedOut;\n\n    -webkit-animation-timing-function: ease-in;\n    -moz-animation-timing-function: ease-in;\n    -o-animation-timing-function: ease-in;\n    animation-timing-function: ease-in;\n}\n\n.animated.lightSpeedOut {\n    -webkit-animation-duration: 0.25s;\n    -moz-animation-duration: 0.25s;\n    -o-animation-duration: 0.25s;\n    animation-duration: 0.25s;\n}\n\n/* originally authored by Angelo Rohit - https://github.com/angelorohit */\n\n@-webkit-keyframes wiggle {\n    0% { -webkit-transform: skewX(9deg); }\n    10% { -webkit-transform: skewX(-8deg); }\n    20% { -webkit-transform: skewX(7deg); }\n    30% { -webkit-transform: skewX(-6deg); }\n    40% { -webkit-transform: skewX(5deg); }\n    50% { -webkit-transform: skewX(-4deg); }\n    60% { -webkit-transform: skewX(3deg); }\n    70% { -webkit-transform: skewX(-2deg); }\n    80% { -webkit-transform: skewX(1deg); }\n    90% { -webkit-transform: skewX(0deg); }\n\t100% { -webkit-transform: skewX(0deg); }\n}\n\n@-moz-keyframes wiggle {\n    0% { -moz-transform: skewX(9deg); }\n    10% { -moz-transform: skewX(-8deg); }\n    20% { -moz-transform: skewX(7deg); }\n    30% { -moz-transform: skewX(-6deg); }\n    40% { -moz-transform: skewX(5deg); }\n    50% { -moz-transform: skewX(-4deg); }\n    60% { -moz-transform: skewX(3deg); }\n    70% { -moz-transform: skewX(-2deg); }\n    80% { -moz-transform: skewX(1deg); }\n    90% { -moz-transform: skewX(0deg); }\n\t100% { -moz-transform: skewX(0deg); }\n}\n\n@-o-keyframes wiggle {\n    0% { -o-transform: skewX(9deg); }\n    10% { -o-transform: skewX(-8deg); }\n    20% { -o-transform: skewX(7deg); }\n    30% { -o-transform: skewX(-6deg); }\n    40% { -o-transform: skewX(5deg); }\n    50% { -o-transform: skewX(-4deg); }\n    60% { -o-transform: skewX(3deg); }\n    70% { -o-transform: skewX(-2deg); }\n    80% { -o-transform: skewX(1deg); }\n    90% { -o-transform: skewX(0deg); }\n\t100% { -o-transform: skewX(0deg); }\n}\n\n@keyframes wiggle {\n    0% { transform: skewX(9deg); }\n    10% { transform: skewX(-8deg); }\n    20% { transform: skewX(7deg); }\n    30% { transform: skewX(-6deg); }\n    40% { transform: skewX(5deg); }\n    50% { transform: skewX(-4deg); }\n    60% { transform: skewX(3deg); }\n    70% { transform: skewX(-2deg); }\n    80% { transform: skewX(1deg); }\n    90% { transform: skewX(0deg); }\n\t100% { transform: skewX(0deg); }\n}\n\n.wiggle {\n    -webkit-animation-name: wiggle;\n    -moz-animation-name: wiggle;\n    -o-animation-name: wiggle;\n    animation-name: wiggle;\n\n    -webkit-animation-timing-function: ease-in;\n    -moz-animation-timing-function: ease-in;\n    -o-animation-timing-function: ease-in;\n    animation-timing-function: ease-in;\n}\n\n.animated.wiggle {\n    -webkit-animation-duration: 0.75s;\n    -moz-animation-duration: 0.75s;\n    -o-animation-duration: 0.75s;\n    animation-duration: 0.75s;\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/css/custom.css",
    "content": "/* here you can put your own css to customize and override the theme */"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/css/pages/about-us.css",
    "content": "/***\nAnout Us Page\n***/\n\n.meet-our-team h3 {\n  margin-bottom: 0;\n  padding: 0 10px 10px;\n  background: #fcfcfc;\n}\n\n.meet-our-team small {\n  display:block; \n  font-size:12px;\n}\n\n.meet-our-team .team-info {\n  padding: 10px;\n  overflow: hidden; \n  background: #f5f5f5;\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/css/pages/blog.css",
    "content": "/***\nBlog Page\n***/\n\n/*--Block Article--*/\n.blog-page {\n    padding-bottom: 20px;\n}\n\n.blog-page h1 {\n  margin-bottom: 20px;\n}\n\n.blog-page h2 a {\n  color: #000;\n}\n\n.blog-page h2 a:hover {\n  color: #0d638f;\n  text-decoration: none;\n}\n\n.blog-page hr {\n  margin-top: 30px !important;\n}\n\n.blog-page .article-block {\n  padding-bottom: 20px;\n}\n\n.blog-page .news-img img {\n  margin-top: 9px;\n}\n\n.blog-page .blog-tag-data ul {\n  margin-bottom: 5px;\n}\n\n.blog-page .blog-tag-data li {\n  padding: 0;\n}\n\n.blog-page .blog-tag-data li i {\n  color: #78cff8;\n}\n\n.blog-page .blog-tag-data li a {\n  padding: 0;\n  color: #555;\n  margin-right: 8px;\n}\n\n.blog-page .blog-tag-data {\n  margin-bottom: 10px;\n}\n\n.blog-page .blog-tag-data ul.blog-tags a {\n  background: #eee;\n  padding: 1px 4px;\n  margin: 0 4px 4px 0;\n  display: inline-block;\n}\n\n.blog-page .blog-tag-data ul.blog-tags a:hover {\n  background: #ddd;\n  text-decoration: none;\n}\n\n.blog-page .blog-tag-data .blog-tag-data-inner {\n  text-align: right;\n}\n\n.blog-page .blog-tag-data img {\n  margin-bottom: 12px;\n}\n\n.blog-page .blog-article {\n  padding-bottom: 20px;\n}\n\n.blog-page .blog-article h3,\n.blog-page .blog-article h2,\n.blog-page .blog-article h1,\n.blog-page .blog-article h4 {\n  margin-top: 0;\n}\n\n/*--Block Sidebar--*/\n.blog-sidebar h2 {\n  font-size: 38.5px;\n  margin-bottom: 20px;\n}\n\n/*Twitter block*/\n.blog-twitter-block {\n  padding: 5px;\n  position: relative;\n  margin-bottom: 10px;\n  border-right: solid 2px #ddd;\n}\n\n.blog-twitter-block:hover {\n  background: #fafafa;\n  border-color: #35aa47;\n}\n\n.blog-twitter-block a {\n  color: #4d90fe;\n}\n\n.blog-twitter-block p {\n  margin-bottom: 0;\n}\n\n.blog-twitter-block span {\n  color: #555;\n  display: block;\n  font-size: 12px;\n}\n\n.blog-twitter-block i.blog-twiiter-icon {\n  color: #eee;\n  right: 10px;\n  bottom: 10px;\n  font-size: 30px;\n  position: absolute;\n}\n\n/***\nBlog & News Item Page\n***/\n/*--Media Object--*/\n.blog-page .media img {\n    height: 54px;\n    position: relative;\n    top: 3px;\n    width: 54px;\n}\n\n.blog-page h4.media-heading {\n    position: relative;\n}\n\n.blog-page h4.media-heading span {\n    color: #777777;\n    font-size: 12px;\n    position: absolute;\n    right: 0;\n    top: 3px;\n}\n\n.blog-page h4.media-heading span a {\n    color: #78cff8;\n}\n\n/*Post Comment*/\n.blog-page .post-comment .color-red {\n  color: #f00;\n}\n\n/*For Responsive*/\n@media (max-width: 768px) {\n  .blog-page .blog-tag-data .blog-tag-data-inner {\n    text-align: left;\n  }  \n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/css/pages/coming-soon.css",
    "content": "/***\nComing Soon Page\n***/\nbody {\n\tbackground-color: #ddd;\n\tpadding: 0;\n\tmargin: 0;\n}\n\n.coming-soon-header {\n\tpadding: 20px;\n\tmargin-top: 80px;\n}\n\n.coming-soon-content {\n\tpadding: 20px;\n\tmargin-top: 10px;\n}\n\n.coming-soon-countdown {\n\tpadding: 20px;\n}  \n\n.coming-soon-content h1,\n.coming-soon-content p {\n\tcolor: #fff;\n}\n\n.coming-soon-content h1 {\n\tfont-size: 42px;\n\tline-height: 50px;\n\tmargin-bottom: 15px;\t\n\tfont-weight: 300;\n}\n\n.coming-soon-content p {\n\tfont-size: 13px;\n}\n\n\n.coming-soon-content input {\n\tbackground: #fff !important;\n}\n\n.coming-soon-footer {\n   text-align: left !important;\n   font-size: 12px;\n   color: #fefefe;\n   padding: 20px 20px 20px 20px;\n}\n\n/*Countdown*/\n#defaultCountdown { \n\twidth: 100%;\n\tmargin: 10px 0; \n\toverflow: hidden;\n}\n\n#defaultCountdown span.countdown_row {\n\toverflow: hidden;\n}\n\n#defaultCountdown span.countdown_row span { \n\tfont-size: 16px;\n\tfont-weight: 300;\n\tline-height: 20px;\n\tmargin-right: 2px;\n}\n\n#defaultCountdown span.countdown_row > span {\n\tfloat: left;\n}\n\n#defaultCountdown span.countdown_section {\n\tcolor: #fff;\n\tpadding: 7px 15px !important;\n\tmargin-bottom: 2px;\n\tfont-weight: 300;\n\tbackground: url(../../img/bg-white.png) repeat;\n\ttext-align: center;\n}\n\n#defaultCountdown span.countdown_amount {\n\tdisplay: inline-block;\n\tfont-size: 38px !important;\n\tpadding: 15px !important;\n\tfont-weight: 300;\n}\n\n/*Responsive*/\n@media (max-width: 1024px) {\n\t#defaultCountdown span.countdown_amount {\n\t\tpadding: 10px;\n\t}\n}\n\n@media (max-width: 767px) {\n\n\t.coming-soon-header,\n\t.coming-soon-countdown, \n\t.coming-soon-content,\n\t.coming-soon-footer {\n\t\tmargin-top: 0px;\n\t\tpadding: 10px;\n\t}  \n}\n\n@media (max-width: 320px) {\n\n\t.coming-soon-content .btn-subscribe span {\n\t\tdisplay: none;\n\t}\n\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/css/pages/email.css",
    "content": "/*** \nEmail Template Page \n***/\n.mail-template ul { \n  padding:0px;\n  margin: 0px; \n  list-style:none;\n}\n\n.mail-template li {\n  float: left;\n  padding: 0;\n  margin:0 5px 0 0;\n  cursor:pointer;\n  list-style:none;\n  border:solid 2px #fff;\n}\n\n.mail-template li:hover {\n  border:solid 2px #aaa;\n}\n\n.mail-template li a{\n  display:inline-block;\n  padding:16px 25px;\n}\n\n.mail-template li a:hover {\n\ttext-decoration: none;\n}\n\n.mail-template li.color-black {\n  background:#1f1f1f;\n}\n\n.mail-template li.color-darkblue {\n  background:#1570a6;\n}\n\n.mail-template li.color-lightblue {\n  background:#4aabf9;\n}\n\n.mail-template li.color-red {\n  background:#eb4d41;\n}\n\n.mail-template li.color-green {\n  background:#28b779;\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/css/pages/error.css",
    "content": "/***\nError Pages\n***/\n\n/* 404 page option #1 */\n\n.page-404 {\n  text-align: center;\n}\n\n.page-404 .number {\n  position: relative;\n  top: 35px;\n  display: inline-block;\n  letter-spacing: -10px;\n  margin-top: 0px;\n  margin-bottom: 10px;\n  line-height: 128px;\n  font-size: 128px;\n  font-weight: 300;\n  color: #7bbbd6;\n  text-align: right;\n}\n\n.page-404 .details {\n  margin-left: 40px;\n  display: inline-block;\n  padding-top: 0px;\n  text-align: left;\n}\n\n/* 500 page option #1 */\n.page-500 {\n  text-align: center;\n}\n\n.page-500 .number {  \n  display: inline-block;\n  letter-spacing: -10px;\n  line-height: 128px;\n  font-size: 128px;\n  font-weight: 300;\n  color: #ec8c8c;\n  text-align: right;\n}\n\n.page-500 .details {\n  margin-left: 40px;\n  display: inline-block;\n  text-align: left;\n}\n\n/* 404 page option #2*/\n.page-404-full-page {\n  overflow-x: hidden;\n  padding: 20px;\n  margin-bottom: 20px;\n  background-color: #fafafa !important;\n}\n\n.page-404-full-page .details input {\n  background-color: #ffffff;\n}\n\n.page-404-full-page .page-404 {\n  margin-top: 100px;\n}\n\n/* 500 page option #2*/\n.page-500-full-page {\n  overflow-x: hidden;\n  padding: 20px;\n  background-color: #fafafa !important;\n}\n\n.page-500-full-page .details input {\n  background-color: #ffffff;\n}\n\n.page-500-full-page .page-500 {\n  margin-top: 100px;\n}\n\n/* 404 page option #3*/\n\n.page-404-3 {\n  background: #000 !important ;\n} \n\n.page-404-3 .page-inner img {\n  right: 0;\n  bottom: 0;\n  z-index: -1;\n  position: absolute;\n}\n\n.page-404-3 .error-404 {\n  color: #fff;\n  text-align: left;\n  padding: 70px 20px 0;\n}\n\n.page-404-3 h1 {\n  color: #fff;\n  font-size: 130px;\n  line-height: 160px;\n}\n\n.page-404-3 h2 {\n  color: #fff;\n  font-size: 30px;\n  margin-bottom: 30px;\n}\n\n.page-404-3 p {\n  color: #fff;\n  font-size: 16px;\n}\n\n\n@media (max-width: 480px) { \n\n  .page-404 .number,\n  .page-500 .number,\n  .page-404 .details,\n  .page-500 .details {\n    text-align: center;\n    margin-left: 0px;\n  }\n\n  .page-404-full-page .page-404 {\n    margin-top: 30px;\n  }\n\n  .page-404-3 .error-404 {\n    text-align: left;\n    padding-top: 10px;\n  }\n\n  .page-404-3 .page-inner img {\n    right: 0;\n    bottom: 0;\n    z-index: -1;\n    position: fixed;\n  }\n\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/css/pages/image-crop.css",
    "content": "/* Apply these styles only when #preview-pane has\n   been placed within the Jcrop widget */\n#preview-pane {\n  display: block;\n  position: absolute;\n  z-index: 2000;\n  right: -200px;\n  padding: 6px;\n  border: 1px rgba(0,0,0,.4) solid;\n  background-color: white;\n\n  -webkit-border-radius: 6px;\n  -moz-border-radius: 6px;\n  border-radius: 6px;\n\n  -webkit-box-shadow: 1px 1px 5px 2px rgba(0, 0, 0, 0.2);\n  -moz-box-shadow: 1px 1px 5px 2px rgba(0, 0, 0, 0.2);\n  box-shadow: 1px 1px 5px 2px rgba(0, 0, 0, 0.2);\n}\n\n@media (max-width: 1024px) { \n  #preview-pane {\n    right: 0;\n  }\n}\n\n/* The Javascript code will set the aspect ratio of the crop\n   area based on the size of the thumbnail preview,\n   specified here */\n\n#preview-pane .preview-container {\n  width: 175px;\n  height: 150px;\n  overflow: hidden;\n}\n\n  #demo7 {\n    background-color: #eee;\n    width: 500px;\n    height: 330px;\n    font-size: 24px;\n    font-weight: 300;\n    display: block;\n  }"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/css/pages/inbox.css",
    "content": "/***\nInbox Page\n***/\n.inbox {\n  margin-bottom: 20px;\n}\n\n.inbox .inbox {\n  margin-bottom: 0px;\n}\n\n.inbox .tab-content {\n  overflow: inherit;\n}\n\n.inbox .inbox-loading {\n  display: none;\n  font-size: 22px;\n  font-weight: 300;\n}\n\n/*Imbox Menu*/\n.inbox .inbox-nav {\n  margin: 0;\n  padding: 0;\n  list-style: none;\n}\n\n.inbox .inbox-nav li {\n  position: relative;\n}\n\n.inbox .inbox-nav li a {\n  color: #4d82a3;\n  display: block;\n  font-size: 15px;\n  border-left: none;\n  text-align: left !important;\n  padding: 8px 14px;\n  margin-bottom: 1px;\n  background: #f4f9fd;\n}\n\n.inbox .inbox-nav li.active a,\n.inbox .inbox-nav li.active:hover a {\n  color: #fff;\n  border-left: none;\n  background: #169ef4 !important;\n  text-decoration: none;\n}\n\n.inbox .inbox-nav li.active b {\n  top: 0;\n  right: -4px;\n  width: 8px;\n  height: 35px;\n  position: absolute;\n  display: inline-block;\n  background: url(../../img/inbox-nav-arrow-blue.png) no-repeat;\n}\n\n.inbox .inbox-nav li:hover a {\n  color: #4d82a3;\n  background: #eef4f7 !important;\n  text-decoration: none;\n}\n\n.inbox .inbox-nav li.compose-btn a {\n  color: #fff;\n  text-shadow: none;\n  text-align: center;\n  margin-bottom: 18px;\n  background: #35aa47;\n}\n\n.inbox .inbox-nav li.compose-btn i,\n.inbox .inbox-nav li.compose-btn:hover i {\n  top: 1px;\n  color: #fff;\n  font-size: 15px;\n  position: relative;\n  background: none !important;\n}\n\n.inbox .inbox-nav li.compose-btn a:hover {\n  background-color: #1d943b !important;\n}\n\n/*Inbox Content*/\n.inbox .inbox-header {\n  overflow: hidden;\n}\n\n.inbox .inbox-header h1 {\n  margin: 0;\n  color: #666;\n  margin-bottom: 10px;\n}\n\n.inbox .pagination-control {\n  text-align: right;\n}\n\n.inbox .pagination-control .pagination-info {\n  display: inline-block;\n  padding-right: 10px;\n  font-size: 14px;\n  line-height: 14px;\n}\n\n.inbox tr {\n  color: #777;\n  font-size: 13px;\n}\n\n.inbox tr label {\n  display: inline-block;\n  margin-bottom: 0;\n}\n\n.inbox tr.unread td{\n  font-weight: 600;\n}\n\n.inbox td i.icon-paper-clip {\n  top: 2px;\n  color: #d8e0e5;\n  font-size: 17px;\n  position: relative;\n}\n\n.inbox tr i.icon-star,\n.inbox tr i.icon-trash {\n  cursor: pointer;  \n}\n\n.inbox tr i.icon-star {\n  color: #eceef0;\n}\n\n.inbox tr i.icon-star:hover {\n  color: #fd7b12;\n}\n\n.inbox tr i.inbox-started {\n  color: #fd7b12;  \n}\n\n.inbox .table th, \n.inbox .table td {\n  border: none;\n}\n\n.inbox .table th {  \n  background: #eef4f7;\n  border-bottom: solid 5px #fff;\n}\n\n.inbox th.text-right {\n  text-align: right;\n}\n\n.inbox th label.inbox-select-all {\n  color: #828f97;\n  font-size: 13px;\n  padding: 1px 4px 0;\n}\n\n.inbox ul.inbox-nav {\n  margin-bottom: 0;\n}\n\n.inbox ul.inbox-nav li {\n  padding: 0;\n}\n\n.inbox ul.inbox-nav li span {\n  color: #828f97;\n  font-size: 12px;\n  margin-right: 10px;\n}\n\n.inbox ul.inbox-nav i {\n  color: #fff;\n  padding: 1px 0;\n  font-size: 15px;\n  cursor: pointer; \n  background: #d0dde4 !important;\n}\n\n.inbox ul.inbox-nav i:hover {\n  background: #169ef4 !important;\n}\n\n.inbox td.text-right {\n  width: 100px;\n  text-align: right;\n}\n\n.inbox td.inbox-small-cells {\n  width: 10px;\n}\n\n.inbox .table-hover tbody tr:hover>td, \n.inbox .table-hover tbody tr:hover>th, \n.inbox .table-striped tbody>tr:nth-child(odd)>td, \n.inbox .table-striped tbody>tr:nth-child(odd)>th {\n  background: #f8fbfd;  \n  cursor: pointer;\n}\n\n.inbox .table-hover tbody tr:hover>td, \n.inbox .table-hover tbody tr:hover>th {\n  background: #eef4f7;\n}\n\n/*Inbox Drafts*/\n.inbox .inbox-drafts {\n  padding: 8px 0;\n  text-align: center;\n  border-top: solid 1px #eee;\n  border-bottom: solid 1px #eee;\n}\n\n/*Inbox View*/\n.inbox-view-header {\n  margin-bottom: 20px;\n}\n\n.inbox-view-header h1 {\n  color: #666;\n  font-size: 22px;\n  line-height: 24px;\n  margin-bottom: 0 !important;\n}\n\n.inbox-view-header h1 a {\n  top: -2px;\n  color: #fff;\n  cursor: pointer;\n  font-size: 13px;\n  padding: 2px 7px;\n  line-height: 16px;\n  position: relative;\n  background: #b0bcc4;\n  display: inline-block;\n}\n\n.inbox-view-header h1 a:hover {\n  background: #aab5bc;\n  text-decoration: none;\n}\n\n.inbox-view-header i.icon-print {\n  color: #94a4ab;\n  cursor: pointer;\n  font-size: 14px;\n  display: inline-block;\n  padding: 6px 8px !important;\n  background: #edf1f4 !important;\n}\n\n.inbox-view-header i.icon-print:hover {\n  background: #e7ebef !important;\n}\n\n.inbox-view-info {\n  color: #666;  \n  padding: 5px 0;\n  margin-bottom: 10px;\n  border-top: solid 1px #eee;\n  border-bottom: solid 1px #eee;\n}\n\n.inbox-view-info strong {\n  color: #666;\n  margin: 0 10px 0 5px;\n}\n\n.inbox-view-info .inbox-info-btn {\n  text-align: right;\n}\n\n.inbox-view-info .inbox-info-btn ul {\n  text-align: left;\n}\n\n.inbox-view-info button {\n  top: 2px;\n  color: #94a4ab;\n  font-size: 13px;\n  margin-left: 4px; \n  padding: 3px 10px;\n  position: relative;\n  background: #edf1f4;\n}\n\n.inbox-view-info button:hover {\n  color: #94a4ab;\n  background: #e7ebef;\n}\n\n.inbox-view {\n  color: #666;\n  padding: 15px 0 0;\n}\n\n.inbox-view a {\n  color: #169ce9;\n}\n\n.inbox-attached {\n  line-height: 16px;\n}\n\n.inbox-attached a {\n  margin: 0 2px;\n}\n\n.inbox-attached img {\n  height: auto;\n  max-width: 250px;\n  margin-bottom: 5px;\n}\n\n.inbox-attached span {\n  margin-right: 3px;\n}\n\n.inbox-attached strong {\n  color: #555;\n  display: block;\n  font-size: 13px;\n}\n\n.inbox-attached .margin-bottom-25 {\n  margin-bottom: 25px;\n}\n\n.inbox-attached .margin-bottom-15 {\n  margin-bottom: 15px;\n}\n\n\n/*Inbox Compose*/\n.inbox-compose {\n  margin-top: 1px;\n  border: solid 1px #eee;\n}\n\n.inbox-compose-btn {\n  padding: 8px 4px;\n  background: #f0f6fa;\n}\n\n.inbox-compose-attachment {\n  padding: 8px 8px;\n}\n\n.inbox-compose-attachment .btn {\n  padding: 4px 10px;\n}\n\n.inbox-compose-btn button {\n  color: #fff;\n  font-size: 14px;\n  margin-left: 4px;\n  padding: 4px 10px;\n  background: #c0cfdd;\n}\n\n.inbox-compose-btn button:hover {\n  color: #fff;\n  background: #4d90fe;\n}\n\n.inbox-compose-btn button i {\n  margin-right: 3px;\n}\n\n.inbox-compose .inbox-form-group {\n  margin-bottom: 0;\n  position: relative;\n  border-bottom: solid 1px #eee;\n}\n\n.inbox-compose .controls {\n  margin-left: 85px;\n}\n\n.inbox-compose .inbox-form-group > label {\n  width: 80px;\n  float: left;\n  color: #979797;\n  text-align: right;\n}\n\n.inbox-compose .controls > input {\n  border: none !important;\n}\n.inbox-compose .controls-to {\n  padding-right: 55px;\n}\n\n.inbox-compose .controls-cc {\n  padding-right: 20px;\n}\n\n.inbox-compose .controls-bcc {\n  padding-right: 20px;\n}\n\n.inbox-compose .inbox-form-group a.close {\n  top: 13px;\n  right: 10px;\n  position: absolute;\n}\n\n.inbox-compose .mail-to .inbox-cc-bcc {\n  display: inline-block;\n  top: 7px;\n  right: 10px;\n  color: #979797;\n  font-size: 14px;\n  cursor: pointer;\n  position: absolute;\n}\n\n.inbox-compose .mail-to .inbox-bcc {\n  margin-left: 5px;\n}\n\n.inbox-compose .mail-to inbox-cc:hover,\n.inbox-compose .mail-to inbox-bcc:hover {\n  color: #777;\n}\n\n.inbox-compose .wysihtml5 {\n  padding: 0px !important;\n  margin: 0px !important;\n  border: 0 !important;\n}\n\n.inbox-compose .wysihtml5-sandbox {\n  padding: 0px !important;\n  margin: 0px !important;\n  display: block !important;\n  border: 0 !important;\n  margin-top: 5px;\n  width: 100% !important;\n  border-left: none;\n  border-right: none;\n  border-color: #eee;\n}\n\n.inbox-compose .wysihtml5-toolbar {  \n  border: 0;\n  border-bottom: 1px solid #eee;\n}\n\n.inbox-compose .wysihtml5-toolbar > li {\n  height: 34px;\n  margin-right: 0;\n  margin-bottom: 0;\n}\n\n.inbox-compose .wysihtml5-toolbar > li > a,\n.inbox-compose .wysihtml5-toolbar > li > div > a {\n  background: #fff;\n}\n\n.inbox-compose .wysihtml5-toolbar .dropdown.open .dropdown-toggle,\nul.wysihtml5-toolbar a.btn.wysihtml5-command-active {\n  background: #eee !important;\n}\n\n@media (max-width: 480px) {\n\n  .inbox-compose .inbox-form-group > label {\n    margin-top: 7px;\n  }\n\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/css/pages/invoice.css",
    "content": "/***\nInvoice page\n***/\n.invoice table {\n  margin:30px 0 30px;\n}\n\n.invoice .invoice-logo {\n  margin-bottom:20px;\n}\n\n.invoice .invoice-logo p {\n  padding:5px 0;\n  font-size:26px;\n  line-height:28px;\n  text-align:right;\n}\n\n.invoice .invoice-logo p span {\n  display:block;\n  font-size:14px;\n}\n\n.invoice .invoice-logo-space {\n  margin-bottom:15px;\n}\n\n.invoice .invoice-payment strong {\n  margin-right:5px;\n}\n\n.invoice .invoice-block {\n  text-align:right;\n}\n\n.invoice .invoice-block .amounts {\n  margin-top: 20px;\n  font-size: 14px;\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/css/pages/lock.css",
    "content": "/***\nLock Page\n***/\nbody {\n\tbackground-color: #ddd;\n\tpadding: 0;\n\tmargin: 0;\n}\n\n.page-lock {\n   top: 50%;\n   left: 50%;\n   position: absolute;\n   margin-top: -140px;\n   margin-left: -260px;\n}\n\n.page-lock .page-logo {\n\tmargin-bottom: 15px;\n}\n\n.page-lock .page-body {\t\n   width: 500px;\n   padding: 10px;\n   background: url(../../img/bg-white-lock.png) repeat;\n}\n\n.page-lock .page-body:after,\n.page-lock .page-body:before {\n\tdisplay: table;\n\tcontent: \"\";\n\tline-height: 0;\n}\n\n.page-lock .page-body:after {\n\tclear: both;\n}\n\n.page-lock .page-footer {\n   margin-top: 10px;\n   text-align: left !important;\n   font-size: 12px;\n   color: #eaeaea;\n}\n\n.page-lock img.page-lock-img {\n\tfloat: left;\n\twidth: 200px;\n\theight: auto;\n}\n\n.page-lock .page-lock-info {\n\tpadding-left: 10px;\n\tfloat: right;\n\twidth: 280px;\n}\n\n.page-lock .page-lock-info h1 {\n\tmargin-top: -5px;\n\tfont-weight: 300;\n\tcolor: #fff;\n\tfont-size: 28px;\n\tline-height: 32px;\n\tmargin-bottom: 5px;\n}\n\n.page-lock .page-lock-info .email {\n\tcolor: #eee;\n\tdisplay: block;\n\tfont-size: 14px;\n\tline-height: 14px;\n\tmargin-bottom: 10px;\n} \n\n.page-lock .page-lock-info .locked {\n\tcolor: #333;\n\tfont-size: 14px;\t\n\tline-height: 14px;\n\tfont-style: normal;\n}\n\n.page-lock .page-lock-info form {\n\tmargin: 28px 0;\n}\n\n.page-lock .page-lock-info input {\n\tbackground: #fff;\n}\n\n.page-lock .relogin {\n\tmargin-top: 10px;\n}\n\n.page-lock .relogin a {\n\tcolor: #e1e1e1;\n}\n\n/*Responsive*/\n@media (max-width: 768px) {\n\t.page-lock {\n\t   top:0px;\n\t   width: 280px;\n\t   margin-top: 20px;\n\t   margin-left: -140px;\n\t}\t\n\n\t.page-lock .page-body {\t\n\t\tpadding: 10px;\n\t    text-align: center;\t\n\t\twidth: 280px;\n\t}\n\n\t.page-lock img.page-lock-img {\n\t\tfloat: none !important;\n\t\tdisplay: block;\n\t\tmargin: 0 auto;\n\t\ttext-align: center;\n\t\tmargin-bottom: 15px;\n\t}\n\t.page-lock .page-lock-info {\n\t\tfloat: none !important;\n\t\twidth: 260px;\t\t\n\t\tmargin: 0 auto;\n\t}\n\n\t.page-lock .page-lock-info input {\n\t\twidth: 200px !important;\n\t}\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/css/pages/login-soft.css",
    "content": "/***\nLogin page\n***/\n\n/* logo page */\n.login {\n  background-color: #666 !important;\n}\n\n.login .logo {\n  margin: 0 auto;   \n  margin-top:60px;\n  padding: 15px;\n  text-align: center;\n}  \n\n\n.login .content {\n  background: url(../../img/bg-white-lock.png) repeat;\n  width: 360px;\n  margin: 0 auto; \n  margin-bottom: 0px;\n  padding: 30px;  \n  padding-top: 20px;  \n  padding-bottom: 15px;  \n}\n\n.login .content h3 {\n  color: #eee;\n}\n.login .content h4  {\n  color: #eee;\n}\n\n.login .content p,\n.login .content label {\n  color: #fff;\n}\n\n.login .content .login-form,\n.login .content .forget-form {\n    padding: 0px;\n    margin: 0px;\n}\n\n.login .content .form-control {\n  background-color: #fff;\n}\n\n.login .content .forget-form {\n  display: none;\n}\n\n.login .content .register-form {\n  display: none;\n}\n\n.login .content .form-title {\n  font-weight: 300;\n  margin-bottom: 25px;\n}\n\n.login .content .form-actions {\n  background-color: transparent;\n  clear: both;\n  border: 0px;\n  padding: 0px 30px 25px 30px;\n  margin-left: -30px;\n  margin-right: -30px;\n}\n\n.login .content .form-actions .checkbox {\n  margin-left: 0;\n  padding-left: 0;\n}\n\n.login .content .forget-form .form-actions {\n  border: 0;\n  margin-bottom: 0;\n  padding-bottom: 20px;\n}  \n\n.login .content .register-form .form-actions {\n  border: 0;\n  margin-bottom: 0;\n  padding-bottom: 0px;\n}\n\n.login .content .form-actions .checkbox {\n  margin-top: 8px;\n  display: inline-block;\n}\n\n.login .content .form-actions .btn {\n  margin-top: 1px;\n}\n\n.login .content .forget-password {\n  margin-top: 25px;\n}\n\n.login .content .create-account {\n  border-top: 1px dotted #eee;\n  padding-top: 10px;\n  margin-top: 15px;\n}\n\n.login .content .create-account a {\n  display: inline-block;\n  margin-top: 5px;\n}\n\n/* select2 dropdowns */\n.login .content .select2-container i {\n  display: inline-block;\n  position: relative;\n  color: #ccc;\n  z-index: 1;\n  top:1px;\n  margin: 4px 4px 0px 3px; \n  width: 16px;\n  height: 16px;\n  font-size: 16px;\n  text-align: center; \n}\n\n.login .content .has-error .select2-container i {\n  color: #b94a48;\n}\n\n.login .content .select2-container a span {\n  font-size: 13px;\n}\n\n.login .content .select2-container a span img {\n  margin-left: 4px;\n}\n\n/* footer copyright */\n.login .copyright {\n  text-align: center;\n  margin: 0 auto; \n  padding: 10px;\n  color: #eee;\n  font-size: 12px;\n}\n\n@media (max-width: 480px) {\n  /***\n  Login page\n  ***/\n  .login .logo {\n    margin-top:10px;\n  }\n\n  .login .content {\n    padding: 30px; \n    width: 222px;\n  }\n\n  .login .content h3 {\n    font-size: 22px;\n  }\n\n  .login .checkbox {\n    font-size: 13px;\n  }\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/css/pages/login.css",
    "content": "/***\nLogin page\n***/\n\n/* logo page */\n.login {\n  background-color: #444 !important;\n}\n\n.login .logo {\n  margin: 0 auto;   \n  margin-top:60px;\n  padding: 15px;\n  text-align: center;\n}  \n\n.login .content {\n  background-color:#fff; \n  width: 360px;\n  margin: 0 auto; \n  margin-bottom: 0px;\n  padding: 30px;  \n  padding-top: 20px;  \n  padding-bottom: 15px;  \n}\n\n.login .content h3 {\n  color: #000;\n}\n.login .content h4  {\n  color: #555;\n}\n\n.login .content p {\n  color: #222;\n}\n\n.login .content .login-form,\n.login .content .forget-form {\n    padding: 0px;\n    margin: 0px;\n}\n\n.login .content .input-icon {\n  border-left: 2px solid #35aa47 !important;\n}\n\n.login .content .input-icon .form-control {\n  border-left: 0;\n}\n\n.login .content .forget-form {\n  display: none;\n}\n\n.login .content .register-form {\n  display: none;\n}\n\n.login .content .form-title {\n  font-weight: 300;\n  margin-bottom: 25px;\n}\n\n.login .content .form-actions {\n  background-color: #fff;\n  clear: both;\n  border: 0px;\n  border-bottom: 1px solid #eee;\n  padding: 0px 30px 25px 30px;\n  margin-left: -30px;\n  margin-right: -30px;\n}\n\n.login .content .form-actions .checkbox {\n  margin-left: 0;\n  padding-left: 0;\n}\n\n.login .content .forget-form .form-actions {\n  border: 0;\n  margin-bottom: 0;\n  padding-bottom: 20px;\n}  \n\n.login .content .register-form .form-actions {\n  border: 0;\n  margin-bottom: 0;\n  padding-bottom: 0px;\n}\n\n.login .content .form-actions .checkbox {\n  margin-top: 8px;\n  display: inline-block;\n}\n\n.login .content .form-actions .btn {\n  margin-top: 1px;\n}\n\n.login .content .forget-password {\n  margin-top: 25px;\n}\n\n.login .content .create-account {\n  border-top: 1px dotted #eee;\n  padding-top: 10px;\n  margin-top: 15px;\n}\n\n.login .content .create-account a {\n  display: inline-block;\n  margin-top: 5px;\n}\n\n/* select2 dropdowns */\n.login .content .select2-container {\n  border-left: 2px solid #35aa47 !important;\n}\n\n.login .content .select2-container .select2-choice {\n  border-left: none !important;\n}\n\n.login .content .select2-container i {\n  display: inline-block;\n  position: relative;\n  color: #ccc;\n  z-index: 1;\n  top:1px;\n  margin: 4px 4px 0px 3px; \n  width: 16px;\n  height: 16px;\n  font-size: 16px;\n  text-align: center; \n}\n\n.login .content .has-error .select2-container i {\n  color: #b94a48;\n}\n\n.login .content .select2-container a span {\n  font-size: 13px;\n}\n\n.login .content .select2-container a span img {\n  margin-left: 4px;\n}\n\n/* footer copyright */\n.login .copyright {\n  text-align: center;\n  margin: 0 auto; \n  padding: 10px;\n  color: #999;\n  font-size: 11px;\n}\n\n@media (max-width: 480px) {\n  /***\n  Login page\n  ***/\n  .login .logo {\n    margin-top:10px;\n  }\n\n  .login .content {\n    padding1: 20px; \n    width: 280px;\n  }\n\n  .login .content h3 {\n    font-size: 22px;\n  }\n\n\n  .login .checkbox {\n    font-size: 13px;\n  }\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/css/pages/news.css",
    "content": "/***\nNews Page\n***/\n\n.news-page {\n  padding-bottom: 20px;\n}\n\n.news-page h1 {\n  margin-bottom: 20px;\n}\n\n.news-page h2 {\n  font-size: 38.5px;\n  margin-bottom: 20px;\n}\n\n.news-page .top-news {\n  margin-top: 0;\n}\n\n/*News Feeds*/\n.news-blocks {\n  padding: 10px;\n  margin-bottom: 10px;\n  background: #faf6ea;\n  border-top: solid 2px #faf6ea;\n}\n\n.news-blocks:hover {\n  background: #fff;\n  border-color: #78cff8;\n  transition: all 0.4s ease-in-out 0s;\n  -moz-transition: all 0.4s ease-in-out 0s;\n  -webkit-transition: all 0.4s ease-in-out 0s;\n}\n\n.news-blocks h3 {\n  margin: 0 0 5px 0;\n  font-size: 23px;\n  line-height: 32px;\n}\n\n.news-blocks h3 a {\n  color: #000;\n}\n\n.news-blocks h3 a:hover {\n  color: #78cff8;\n  text-decoration: none;\n}\n\n.news-blocks p {\n  overflow: hidden;\n}\n\n.news-blocks a.news-block-btn {\n  color: #000;\n  display: block;\n  font-size: 14px;\n  background: none;\n  padding: 5px 10px 0;\n  text-align: right;\n  text-decoration: none;\n}\n\n.news-blocks a.news-block-btn i {\n  margin-left: 3px;\n}\n\n\n.news-blocks a.news-block-btn:hover {\n  text-decoration: none;\n}\n\n.news-blocks img.news-block-img {\n  width: 70px;\n  height: 70px;\n  margin: 5px 0px 0 10px;\n}\n\n.news-blocks .news-block-tags {\n  margin-bottom: 8px;\n}\n\n.news-blocks .news-block-tags strong {\n  margin-right: 10px;\n  font-weight: 400;\n}\n\n.news-blocks .news-block-tags em {\n  font-style: normal;\n}\n\n/*News Item Page*/\n.news-item-page {\n  padding: 10px 0;\n}\n\n.blog-tag-data ul {\n  margin-bottom: 5px;\n}\n\n.blog-tag-data li {\n  padding: 0;\n}\n\n.blog-tag-data li i {\n  color: #78cff8;\n}\n\n.blog-tag-data li a {\n  padding: 0;\n  color: #555;\n  margin-right: 8px;\n}\n\n.blog-tag-data {\n  margin-bottom: 10px;\n}\n\n.blog-tag-data img {\n  margin-bottom: 12px;\n}\n\n.blog-tag-data ul.blog-tags a {\n  background: #eee;\n  padding: 1px 4px;\n  margin: 0 4px 4px 0;\n  display: inline-block;\n}\n\n.blog-tag-data ul.blog-tags a:hover {\n  background: #ddd;\n  text-decoration: none;\n}\n\n.blog-tag-data .blog-tag-data-inner {\n  text-align: right;\n}\n\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/css/pages/portfolio.css",
    "content": " /***\nPortfolio\n***/\n/*Portfolio Filter*/\n.mix-filter {\n\tlist-style: none;\n\tmargin:0 0 20px 0;\n\tpadding: 0;\n}\n\n.mix-filter li {\n\tcolor: #555;\n\tcursor: pointer;\n\tpadding: 6px 15px;\n\tmargin-right: 2px;\n\tmargin-bottom: 5px;\n\tbackground: #eee;\n\tdisplay: inline-block;\n}\n\n.mix-filter li:hover,\n.mix-filter li.active {\n\tcolor: #fff;\n\tbackground: #0da3e2;\n}\n\n.mix-grid .mix {\n\topacity: 0;\n\tdisplay: none;\n}\n\n/*Portfolio Hover*/\n.mix-grid .mix {\n\tposition: relative;\n\toverflow: hidden;\t\n\tmargin-bottom: 15px;\n}\n\n.mix-grid .mix .mix-inner {\n\tposition: relative;\n\twidth: 100%;\n}\n\n.mix-grid .mix .mix-details {\n\tcolor: #fff;\n\twidth: 100%;\n\theight: 100%;\n\tbottom: -100%;\n\ttext-align: center;\n\tposition: absolute;\n\tbackground: #0da3e2;\n}\n\n.mix-grid .mix:hover .mix-details {\n\tbottom: 0;\n\ttransition: all 0.5s ease;\n\t-o-transition: all 0.5s ease;\n\t-ms-transition: all 0.5s ease;\n\t-moz-transition: all 0.5s ease;\n\t-webkit-transition: all 0.5s ease;\t\n}\n\n.mix-grid .mix .mix-details h4 {\n\tcolor: #fff;\t\n\tmargin-top: 30px;\n}\n\n.mix-grid .mix .mix-details p {\n\tpadding: 0 30px;\n}\n\n.mix-grid .mix .mix-details i {\n\tcolor: #fff;\n\tfont-size: 14px;\n}\n\n.mix-grid .mix a.mix-link, \n.mix-grid .mix a.mix-preview {\n\tcolor: #555;\n\tdisplay: block;\n\tcursor: pointer;\n\tmargin-top: 10px; \n\tposition: absolute;\n\tpadding: 10px 15px;\n\tbackground: #16b2f4;\n}\n\n.mix-grid .mix a.mix-preview {\n\tleft: 50%;\n\tmargin-left: 5px;\n}\n\n.mix-grid .mix a.mix-link {\n\tright: 50%;\n\tmargin-right: 5px;\n}\n\n.mix-grid .mix a.mix-link:hover,\n.mix-grid .mix a.mix-preview:hover {\n\tcolor: #fff;\n\tpadding: 9px 14px;\n\ttext-decoration: none;\n\tborder: solid 1px #eee;\n}\n\n/* Portrait tablet to landscape and desktop */\n@media (min-width: 992px) { \n\n\t.mix-grid .mix.col-md-6.col-sm-6 .mix-details {\n\t\theight: 50%;\n\t}\n\n}\n\n@media (min-width: 768px) and (max-width: 991px) { \n\t\n\t.mix-grid .mix a.mix-link,\n\t.mix-grid .mix a.mix-preview {\n\t\tmargin-top: 5px;\n\t}\n\n}\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/css/pages/pricing-tables.css",
    "content": "/***\nPricing table\n***/\n\n.pricing-table {\n  border: 3px solid transparent;\n  padding: 10px;\n  background-color: #f1f2f2;\n}\n\n.pricing-table:hover {\n  border-color: #4b8df8;\n}\n\n.pricing-table h3 {\n  margin-left: -2px;\n  padding-left: 0px;\n  font-size: 26px;\n  margin-bottom: 5px;\n  line-height: 26px;\n  color: #111;\n  margin-top: 0px;\n}\n\n.pricing-table .desc {\n  margin-bottom: 10px;\n  padding-bottom: 15px;\n  color: #666;\n  border-bottom: 1px solid #ddd;\n}\n\n.pricing-table ul {\n  margin: 0px;\n  margin-bottom: 15px;\n  padding: 0px;\n  list-style: none;\n}\n\n.pricing-table ul li {\n  padding: 6px 0px;\n  padding-left: 11px;\n  font-size: 13px;\n  line-height: 13px;\n  color: #666;\n}\n\n.pricing-table ul li i {\n  position: absolute;\n  margin-right: 0px;\n  margin-top: -2px;\n  margin-left: -17px;\n  color: #35aa47;\n  font-size: 16px;\n}\n\n.pricing-table .rate {\n  border-top: 1px solid #ddd;\n  margin-bottom: 10px; \n  padding-top: 15px;\n  clear: both;\n}\n\n.pricing-table.selected .rate {\n  border-top-color: #fff;\n}\n\n.pricing-table .rate:before,\n.pricing-table .rate:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n.pricing-table .rate:after {\n  clear: both;\n}\n\n.pricing-table .rate .price {\n  display: inline-block;\n  float: left; \n  clear: both;\n}\n\n.pricing-table .rate .btn {\n  margin-top: 3px;\n  float: right;\n  display: block;\n}\n\n.pricing-table .rate .price .currency {\n  padding-top: 4px;\n  float: left;\n  width: 50px;\n  text-align: right;\n  font-size: 13px;\n  line-height: 14px;\n  font-weight: 300;\n  margin-right: 2px;\n}\n\n.pricing-table .rate .price .amount {\n  padding-top: 4px;  \n  letter-spacing: -3px;\n  float: left;\n  text-align: right;\n  font-size: 36px;\n  line-height: 30px;\n  font-weight: 300;\n}\n\n.pricing-table.selected {\n  background-color: #4b8df8;\n}\n\n.pricing-table.selected:hover {\n  border-color: #ddd;\n}\n\n.pricing-table.selected .desc {\n  border-bottom-color: #fff;\n}\n\n.pricing-table.selected h3,\n.pricing-table.selected .desc,\n.pricing-table.selected ul li,\n.pricing-table.selected ul li i,\n.pricing-table.selected .rate {\n  color: #fff;\n}\n\n/***\nPricing table(Alternative)\n***/\n\n.pricing-table2 {\n  border: 3px solid transparent;\n  padding: 10px;\n  background-color: #f1f2f2;\n}\n\n.pricing-table2:hover {\n  border-color: #4b8df8;\n}\n\n.pricing-table2 h3 {\n  margin-left: -2px;\n  padding-left: 0px;\n  font-size: 26px;\n  margin-bottom: 5px;\n  line-height: 26px;\n  margin-top: 0px;\n  color: #111;\n}\n\n.pricing-table2 .desc {\n  margin-bottom: 10px;\n  padding-bottom: 0px;\n  color: #666;\n}\n\n.pricing-table2 ul {\n  margin: 0px;\n  margin-bottom: 0px;\n  padding: 0px;\n  list-style: none;\n}\n\n.pricing-table2 ul li {\n  padding: 6px 0px;\n  padding-left: 11px;\n  font-size: 13px;\n  line-height: 13px;\n  color: #666;\n}\n\n.pricing-table2 ul li i {\n  position: absolute;\n  margin-right: 0px;\n  margin-top: -2px;\n  margin-left: -17px;\n  color: #35aa47;\n  font-size: 16px;\n}\n\n.pricing-table2 .rate { \n  margin-bottom: 10px; \n  padding: 15px 15px;\n  margin-left: -15px;\n  margin-right: -15px;\n  background-color: #35aa47;\n  color: #fff;\n  clear: both;\n}\n\n.pricing-table2.selected .rate {\n  border-top-color: #fff;\n}\n\n.pricing-table2 .rate:before,\n.pricing-table2 .rate:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n.pricing-table2 .rate:after {\n  clear: both;\n}\n\n.pricing-table2 .rate .price {\n  display: inline-block;\n  float: left; \n  clear: both;\n}\n\n.pricing-table2 .rate .btn {\n  margin-top: 3px;\n  float: right;\n  display: block;\n}\n\n.pricing-table2 .rate .price .currency {\n  padding-top: 4px;\n  float: left;\n  width: 50px;\n  text-align: right;\n  font-size: 13px;\n  line-height: 14px;\n  font-weight: 300;\n}\n\n.pricing-table2 .rate .price .amount {\n  padding-top: 4px;\n  float: left;\n  text-align: right;\n  font-size: 36px;\n  line-height: 30px;\n  font-weight: 300;\n}\n\n.pricing-table2.selected {\n  background-color: #4b8df8;\n}\n\n.pricing-table2.selected .rate {\n  background-color: #ffb848;\n}\n\n.pricing-table2.selected:hover {\n  border-color: #ddd;\n}\n\n.pricing-table2.selected .desc {\n  border-bottom-color: #fff;\n}\n\n.pricing-table2.selected h3,\n.pricing-table2.selected .desc,\n.pricing-table2.selected ul li,\n.pricing-table2.selected ul li i,\n.pricing-table2.selected .rate .currency,\n.pricing-table2.selected .rate .amount {\n  color: #fff !important;\n}\n\n\n/***\nPricing table(Alternative 2)\n***/\n.pricing {\n  position:relative;\n  margin-bottom:15px;\n  border:3px solid #eee;\n}\n.pricing-active {\n  border:3px solid #35aa47;\n}\n.pricing:hover {\n  border:3px solid #35aa47;\n}\n.pricing:hover h4 {\n  color:#35aa47;\n}\n.pricing-head {\n  text-align:center;\n}\n.pricing-head h3,\n.pricing-head h4 {\n  margin:0;\n  line-height:normal;\n}\n.pricing-head h3 span, \n.pricing-head h4 span {\n  display:block;\n  margin-top:5px;\n  font-size:14px;\n  font-style:italic;\n}\n.pricing-head h3 {\n  font-weight: 300;\n  color:#fafafa;\n  padding:12px 0;\n  font-size:27px;\n  background:#35aa47;\n  border-bottom:solid 1px #41b91c;\n}\n.pricing-head h4 {\n  color:#bac39f;\n  padding:5px 0;\n  font-size:54px;\n  font-weight:300;\n  background:#fbfef2;\n  border-bottom:solid 1px #f5f9e7;\n}\n.pricing-head-active h4 {\n  color:#35aa47;\n}\n.pricing-head h4 i {\n  top:-8px;\n  font-size:28px;\n  font-style:normal;\n  position:relative;\n}\n.pricing-head h4 span {\n  top:-10px;\n  font-size:14px;\n  font-style:normal;\n  position:relative;\n}\n  \n/*Pricing Content*/\n.pricing-content li {\n  color:#888;\n  font-size:12px;\n  padding:7px 15px;\n  border-bottom:solid 1px #f5f9e7;\n}\n.pricing-content li i {\n  top:2px;\n  color:#35aa47;\n  font-size:16px;\n  margin-right:5px;\n  position:relative;\n}\n\n/*Pricing Footer*/\n.pricing-footer {\n  color:#777;\n  font-size:11px;\n  line-height:17px;\n  text-align:center;\n  padding:0 20px 19px;\n}\n\n/*Priceing Active*/\n.price-active,\n.pricing:hover {\n  z-index:9;\n}\n.price-active h4 {\n  color:#35aa47;\n}\n\n.no-space-pricing .pricing:hover {\n  -webkit-transition:box-shadow 0.3s ease-in-out;\n  -moz-transition:box-shadow 0.3s ease-in-out;\n  -o-transition:box-shadow 0.3s ease-in-out;\n  transition:box-shadow 0.2s ease-in-out;\n}\n.no-space-pricing .price-active .pricing-head h4,\n.no-space-pricing .pricing:hover .pricing-head h4 {\n  color:#35aa47;\n  padding:15px 0;\n  font-size:80px;\n  -webkit-transition:color 0.5s ease-in-out;\n  -moz-transition:color 0.5s ease-in-out;\n  -o-transition:color 0.5s ease-in-out;\n  transition:color 0.5s ease-in-out;\n}\n\n\n@media (min-width: 768px) and (max-width: 1280px) { \n\n  .pricing-table .rate .price,\n  .pricing-table2 .rate .price {\n    width: 100%;\n    display: block;\n    text-align: center;\n    margin-bottom: 10px;\n  }\n\n} "
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/css/pages/profile.css",
    "content": "/***\nProfile Page\n***/\n.profile {\n  position:relative;\n}\n\n.profile p {\n  color:#636363;\n  font-size:13px;\n}\n\n.profile p a {\n  color:#169ef4;\n}\n\n.profile label {\n  margin-top:10px;\n}\n\n.profile label:first-child {\n  margin-top:0;\n}\n\n/*profile info*/\n.profile-classic .profile-image {\n  position:relative;\n}\n\n.profile-classic .profile-edit {\n  top:0;\n  right:0;\n  margin:0;\n  color:#fff;\n  opacity:0.6;\n  padding:0 9px;\n  font-size:11px;\n  background:#000;\n  position:absolute;\n  filter:alpha(opacity=60); /*for ie*/\n}\n.profile-classic .profile-image img {\n  margin-bottom:15px;\n}\n\n.profile-classic li {\n  padding:8px 0;\n  font-size:13px;\n  border-top:solid 1px #f5f5f5;\n}\n\n.profile-classic li:first-child {\n  border-top:none;\n}\n\n.profile-classic li span {\n  color:#666;\n  font-size:13px;\n  margin-right:7px;\n}\n\n/*profile tabs*/\n.profile .tabbable-custom-profile .nav-tabs > li > a {\n  padding:6px 12px;\n}\n\n\n/*profile navigation*/\n.profile ul.profile-nav {\n  margin-bottom:30px;\n}\n\n.profile ul.profile-nav li {\n  position:relative;\n}\n\n.profile ul.profile-nav li a {\n  color:#557386;\n  display:block;\n  font-size:14px;\n  padding:8px 10px;\n  margin-bottom:1px;\n  background:#f0f6fa;\n  border-left:solid 2px #c4d5df;\n}\n\n.profile ul.profile-nav li a:hover {\n  color:#169ef4;\n  background:#ecf5fb;\n  text-decoration:none;\n  border-left:solid 2px #169ef4;\n}\n\n.profile ul.profile-nav li a.profile-edit {\n  top:0;\n  right:0;\n  margin:0;\n  color:#fff;\n  opacity:0.6;\n  border:none;\n  padding:3px 9px;\n  font-size:12px;\n  background:#000;\n  position:absolute;\n  filter:alpha(opacity=60); /*for ie*/\n}\n\n.profile ul.profile-nav li a.profile-edit:hover {\n  text-decoration:underline;\n}\n\n.profile ul.profile-nav a span {\n  top:0;\n  right:0;\n  color:#fff;\n  font-size:16px; \n  padding:7px 13px;\n  position:absolute;\n  background:#169ef4;\n}\n\n.profile ul.profile-nav a:hover span {\n  background:#0b94ea;\n}\n\n/*profile information*/\n.profile-info h1 {\n  color:#383839;\n  font-size:24px;\n  font-weight:400;\n  margin:0 0 10px 0;\n}\n\n.profile-info ul {\n  margin-bottom:15px;\n}\n\n.profile-info li {\n  color:#6b6b6b;\n  font-size:13px;\n  margin-right:15px;\n  margin-bottom:5px;\n  padding:0 !important;\n}\n\n.profile-info li i {\n  color:#b5c1c9;\n  font-size:15px;\n}\n\n.profile-info li:hover i {\n  color:#169ef4;\n}\n\n/*profile sales summary*/\n.sale-summary ul {\n  margin-top:-12px;\n}\n.sale-summary li {\n  padding:10px 0;\n  overflow:hidden;\n  border-top:solid 1px #eee;\n}\n\n.sale-summary li:first-child {\n  border-top:none;\n}\n\n.sale-summary li .sale-info {\n  float:left;\n  color:#646464;\n  font-size:14px;\n  text-transform:uppercase;\n}\n\n.sale-summary li .sale-num {\n  float:right;\n  color:#169ef4;\n  font-size:20px;\n  font-weight:300;\n}\n\n.sale-summary li span i {\n  top:1px;\n  width:13px;\n  height:14px;\n  margin-left:3px;\n  position:relative;\n  display:inline-block;\n}\n\n.sale-summary li i.icon-img-up {\n  background:url(../../img/icon-img-up.png) no-repeat !important;\n}\n\n.sale-summary li i.icon-img-down {\n  background:url(../../img/icon-img-down.png) no-repeat !important;\n}\n\n.sale-summary .caption h4 {\n  color:#383839;\n  font-size:18px;\n}\n\n.sale-summary .caption {\n  border-color:#c9c9c9;\n}\n\n/*latest customers table*/\n.profile .table-advance thead tr th {\n  background:#f0f6fa;\n}\n\n.profile .table-bordered th, \n.profile .table-bordered td,\n.profile .table-bordered {\n  border-color:#e5eff6;\n}\n\n.profile .table-striped tbody > tr:nth-child(2n+1) > td, \n.profile .table-striped tbody > tr:nth-child(2n+1) > th {\n  background:#fcfcfc;\n}\n\n.profile .table-hover tbody tr:hover td, \n.profile .table-hover tbody tr:hover th {\n  background:#f5fafd;\n}\n\n/*add portfolio*/\n.add-portfolio {\n  overflow:hidden;\n  margin-bottom:30px;\n  background:#f0f6fa;\n  padding: 12px 14px;\n}\n\n.add-portfolio span {\n  float: left;\n  display: inline-block;\n  font-weight: 300;\n  font-size: 22px;\n  margin-top: 0px;\n}\n\n.add-portfolio .btn {\n  margin-left: 20px;\n}\n\n/*portfolio block*/\n.portfolio-block {\n  background:#f7f7f7;\n  margin-bottom:15px;\n  overflow:hidden;\n}\n\n\n/*portfolio text*/\n.portfolio-text {\n  overflow:hidden;\n}\n\n\n.portfolio-text img {\n  float:left;\n  margin-right:15px;\n}\n\n.portfolio-text .portfolio-text-info {\n  overflow:hidden;\n}\n\n/*portfolio button*/\n.portfolio-btn a {\n  display:block;\n  padding:25px 0;\n  background:#ddd !important;\n}\n\n.portfolio-btn a:hover {\n  background:#1d943b !important;\n}\n\n.portfolio-btn span {\n  color:#fff;\n  font-size:22px;\n  font-weight:200;  \n}\n\n/*portfolio info*/\n.portfolio-info {\n  float:left;\n  color:#616161;\n  font-size:12px;\n  padding:10px 25px;\n  margin-bottom:5px;\n  text-transform:uppercase;\n}\n\n.portfolio-info span {\n  color:#16a1f2;\n  display:block;\n  font-size:28px;\n  line-height: 28px;\n  margin-top:0px;\n  font-weight:200;\n  text-transform:uppercase;\n}\n\n/*portfolio settings*/\n.profile-settings {\n  background:#fafafa;\n  padding:15px 8px 0;\n  margin-bottom:5px;\n}\n\n.profile-settings p {\n  padding-left:5px;\n  margin-bottom:3px;\n}\n\n.profile-settings .controls > .radio, \n.profile-settings .controls > .checkbox {\n  font-size:12px;\n  margin-top:2px !important;\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/css/pages/promo.css",
    "content": "/***\nPromo Page\n***/\n.page-content {\n  padding: 0;\n}\n\n.ie8 .page-content {\n  padding: 0 !important;\n}\n\n.promo-page {\n  padding-left: 0;\n  padding-right: 0;\n  min-height: 650px;\n}\n\n.promo-page h1, \n.promo-page h2 {\n  font-size: 50px;\n  line-height: 60px;\n}\n\n.promo-page .btn.xlarge {\n  font-size: 22px;\n  padding: 7px 25px;\n  margin: 5px 0; \n}\n\n.promo-page input.form-control {\n  background: #fff;\n}\n\n/*page row options*/\n\n.promo-page .block-transparent {\n  min-height: 350px;\n  padding: 50px 20px 30px 20px;\n}\n\n.promo-page .block-grey {\n  min-height: 350px;\n  padding: 50px 20px 30px 20px;\n  background: #eeedf2;\n}\n\n.promo-page .block-yellow {\n  min-height: 350px;\n  padding: 50px 20px 30px 20px;\n  background: #ffd800;\n}\n\n.promo-page .block-footer {\n  padding: 30px 20px 30px 20px;\n  background: #eeedf2;\n}\n\n/* carousel */\n\n.block-carousel .carousel-inner {\n  padding-top: 70px;\n  padding-bottom: 60px;\n}\n\n.block-carousel .carousel-control i {\n  display: none;\n  position: absolute;\n  top:40%;\n}\n\n.block-carousel .carousel-control.left i {\n  right:30%;\n}\n\n.block-carousel .carousel-control.right i {\n  left:30%;\n}\n\n.block-carousel .carousel:hover .carousel-control i {\n  display: inline-block;\n}\n\n.block-carousel .carousel-indicators li {\n  background-color: #666;\n}\n\n.block-carousel .carousel-indicators li.active {\n  background-color: #333;\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/css/pages/search.css",
    "content": "/* \nSearch Page\n***/\n\n/* general search form */\n.search-form-default {\n  margin-bottom:25px;\n  background:#f0f6fa;\n  padding:12px 14px;\n}\n\n/*search classic*/\n\n.search-classic {\n  margin-bottom:30px;\n}\n\n.search-classic h4 {\n  margin-bottom:3px;\n}\n\n.overflow-hidden {\n  overflow:hidden;\n}\n\n/*Booking Offer*/\n.booking-offer {\n  position: relative;\n}\n\n.booking-offer .booking-offer-in {\n  top: 15px;\n  left: 15px;\n  right: 15px;\n  color: #fff;\n  padding: 15px;\n  position: absolute;\n  background: url(../../img/bg-opacity.png);\n}\n\n.booking-offer .booking-offer-in em {\n  font-size: 14px;\n  font-style: normal;\n}\n\n.booking-offer .booking-offer-in p {\n  color: #fff;\n  font-size: 14px;\n  margin-bottom: 0;\n}\n\n.booking-offer .booking-offer-in span {\n  font-size: 22px;\n  display: block;\n  margin-bottom: 10px;\n}\n\n.booking-app {\n  margin-bottom: 10px;\n}\n\n.booking-app a {\n  color: #fff;\n  padding: 15px;\n  display: block;\n  overflow: hidden;\n  background: #78ccf8;  \n}\n\n.booking-app a:hover {\n  background: #4d90fe;\n  text-decoration: none;\n}\n\n.booking-app span {\n  top: 0px;\n  color: #fff;\n  font-size: 20px;\n  position: relative;\n}\n\n.booking-app i {\n  color: #fff;\n  font-size: 40px;\n  line-height: 18px;\n}\n\n/*Booking Blocks (Content)*/\n.booking-results {\n  margin-top: 20px;\n}\n\n.booking-result {\n  overflow: hidden;\n}\n\n.booking-result .booking-img {\n  display: inline-block;\n  float: left;\n  width: 140px;\n  margin-right: 10px;\n}\n\n.booking-result .booking-img .price-location li {\n  color: #777;\n}\n\n.booking-result .booking-img .price-location li i {\n  color: #78ccf8;\n  font-size: 12px;\n  margin-right: 5px;\n}\n\n.booking-result .booking-img img {\n  float: left;\n  width: 140px;\n  height: auto;\n  margin: 3px 10px 10px 0;\n}\n\n.booking-result .booking-info .stars {\n  padding: 0;\n  margin: 0 0 5px 0;\n}\n\n.booking-result .booking-info .stars li {\n  padding: 0;\n}\n\n.booking-result .booking-info .stars li i {\n  color: #f8be2c;\n  cursor: pointer;\n  font-size: 16px;\n}\n\n.booking-result .booking-info h2 {\n  margin-top: 2px;\n  font-size: 20px;\n  line-height: 20px;\n}\n\n\n\n\n@media (max-width: 768px) {\n\n  .booking-results,\n  .search-classic {\n    margin-top: 0;\n  }\n\n  .booking-result,\n  .search-classic {\n    padding-bottom: 5px;\n    border-bottom: 1px solid #ddd;\n    margin: 15px 0;\n  }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/css/pages/tasks.css",
    "content": "/***\nTasks Widget\n***/\n\n.tasks-widget .task-content:after {\n\tclear: both;\n}\n\n.tasks-widget .task-footer  { \n\tmargin-top: 5px;\n}\n\n.tasks-widget .task-footer:after,\n.tasks-widget .task-footer:before {\n\tcontent: \"\";\n\tdisplay: table;\n\tline-height: 0;\n}\n\n.tasks-widget .task-footer:after {\n\tclear: both;\n}\n\n.tasks-widget  .task-list {\n  list-style: none;\n  padding:0;\n  margin:0;\n}\n\n.tasks-widget .task-list > li {\n  position:relative;\n  padding:10px 5px;\n  border-bottom:1px solid #eaeaea;\n}\n\n.tasks-widget .task-list  li.last-line {\n  border-bottom:none;\n}\n\n.tasks-widget .task-list  li > .task-bell  {\n  margin-left:10px;\n}\n\n.tasks-widget .task-list  li > .task-checkbox {\n\tfloat:left;\n\twidth:30px;\n}\n\n.tasks-widget .task-list  li > .task-title  {\n  margin-right:10px;\n}\n\n.tasks-widget .task-list  li > .task-config {\n\tposition:absolute;\n\ttop:10px;\n\tright:10px;\n}\n\n.tasks-widget .task-list  li .task-title .task-title-sp  {\n  margin-right:5px;\n}\n\n.tasks-widget .task-list  li.task-done .task-title-sp  {\n  text-decoration:line-through;\n}\n\n.tasks-widget .task-list  li.task-done  {\n  background:#f6f6f6;\n}\n\n.tasks-widget .task-list  li.task-done:hover {\n  background:#f4f4f4;\n}\n\n.tasks-widget .task-list  li:hover  {\n  background:#f9f9f9;\n}\n\n.tasks-widget .task-list  li .task-config {\n  display:none;\n}\n\n.tasks-widget .task-list  li:hover > .task-config {\n  display:block;\n  margin-bottom:0 !important;\n}\n\n.tasks-widget .task-config-btn {\n  margin-top: -1px;\n}\n\n@media only screen and (max-width: 480px) {\n\n\t.tasks-widget .task-config-btn {\n\t\tfloat:inherit;\n\t\tdisplay:block;\n\t}\n\t\n\t.tasks-widget .task-list-projects li > .label {\n\t\tmargin-bottom:5px;\n\t}\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/css/pages/timeline.css",
    "content": "/***\nTimeline UI Base\n***/\n.timeline {\n\tmargin: 0;\n\tpadding: 0;\n\tlist-style: none;\n\tposition: relative;\n} \n\n/* The line */\n.timeline:before {\n\tcontent: '';\n\tposition: absolute;\n\ttop: 0;\n\tbottom: 0;\n\twidth: 10px;\n\tbackground: #ccc;\n\tleft: 20%;\n\tmargin-left: -10px;\n}\n\n.timeline > li {\n\tposition: relative;\n}\n\n/* The date/time */\n.timeline > li .timeline-time {\n\tdisplay: block;\n\twidth: 15%;\n\ttext-align: right;\n\tposition: absolute;\n}\n\n.timeline > li .timeline-time span {\n\tdisplay: block;\n\ttext-align: right;\n}\n\n.timeline > li .timeline-time span.date {\n\tfont-size: 12px;\n\tcolor: #aaa;\n\tdisplay: block;\n\tfont-weight: 300;\n}\n\n.timeline > li .timeline-time span.time {\n\tfont-weight: 300;\n\tfont-size: 38px;\n\tline-height: 38px;\n}\n\n/* Right content */\n\n.timeline > li .timeline-body {\n\tmargin: 0 0 15px 25%;\n\tcolor: #fff;\n\tpadding: 10px;\n\tfont-weight: 300;\n\tposition: relative;\n\tborder-radius: 5px;\n}\n\n.timeline > li .timeline-body h2 { \n\tmargin-top: 0px;\n\tpadding: 0 0 5px 0;\n\tborder-bottom: 1px solid rgba(255,255,255,0.3);\n\tfont-size: 24px;\n}\n\n.timeline > li .timeline-content { \n\tfont-size: 14px;\n}\n\n.ie8 .timeline > li .timeline-body h2 { \n\tborder-bottom: 1px solid #eee;\n}\n\n.timeline > li .timeline-body img.timeline-img { \n  width: 75px;\n  height: 75px;\n  margin: 5px 10px 0 0px;\n}\n\n.timeline > li .timeline-body img.pull-right {\n  margin-left: 10px;\n}\n\n\n.timeline > li .timeline-body a.nav-link {\n  display: inline-block;\n  margin-top: 10px;\n  color: #fff;\n  font-size: 14px;\n  padding: 0px;\n  text-align: left;\n  text-decoration: none;\n}\n\n.timeline > li .timeline-body a.nav-link:hover {\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.timeline > li .timeline-body .btn {\n  margin-top: 10px;\n}\n\n/* The triangle */\n.timeline > li .timeline-body:after {\n\tright: 100%;\n\tborder: solid transparent;\n\tcontent: \" \";\n\theight: 0;\n\twidth: 0;\n\tposition: absolute;\n\tpointer-events: none;\n\tborder-right-color: #3594cb;\n\tborder-width: 10px;\n\ttop: 19px;\n}\n\n.timeline > li .timeline-content:after,\n.timeline > li .timeline-content:before {\n\tdisplay: table;\n\tline-height: 0;\n\tcontent: \"\";\n}\n\n.timeline > li .timeline-content:after {\n\tclear: both;\n}\n\n.timeline >li .timeline-footer:after,\n.timeline >li .timeline-footer:before {\n\tcontent: \"\";\n\tdisplay: table;\n\tline-height: 0;\n}\n\n.timeline >li .timeline-footer:after {\n\tclear: both;\n}\n\n/* The icons */\n.timeline > li .timeline-icon {\n\twidth: 40px;\n\theight: 40px;\n\tspeak: none;\n\tfont-style: normal;\n\tfont-weight: normal;\n\tfont-variant: normal;\n\ttext-transform: none;\n\tfont-size: 1.4em;\n\tline-height: 40px;\n\t-webkit-font-smoothing: antialiased;\n\tposition: absolute;\n\tcolor: #fff;\n\tbackground: #aaa;  \n\tborder-radius: 50%;\n\tbox-shadow: 0 0 0 8px #ccc;\n\ttext-align: center;\n\tleft: 20%;\n\ttop: 0;\n\tmargin: 5px 0 0 -25px;\n\tpadding-bottom: 3px; \n\tpadding-right: 1px;\n\tpadding-left: 2px;\n\t-webkit-border-radius: 30px !important;\n\t   -moz-border-radius: 30px !important;\n\t\t\tborder-radius: 30px !important;\n}\n\n.timeline > li .timeline-icon > i {\n\tfont-size: 18px;\n}\n\n/* Red */\n.timeline li.timeline-red .timeline-body:after {\n\tborder-right-color: #e02222;\n}\n\n.timeline li.timeline-red .timeline-body {\n\t background: #e02222;\n}\n\n.timeline li.timeline-red .timeline-time span.time {\n\t color: #e02222; \n}\n\n/* Yellow */\n.timeline li.timeline-yellow .timeline-body:after {\n\tborder-right-color: #ffb848;\n}\n\n.timeline li.timeline-yellow .timeline-body {\n\t background: #ffb848;\n}\n\n.timeline li.timeline-yellow .timeline-time span.time {\n\t color: #ffb848; \n}\n\n/* Green */\n.timeline li.timeline-green .timeline-body:after {\n\tborder-right-color: #35aa47;\n}\n\n.timeline li.timeline-green .timeline-body {\n\t background: #35aa47;\n}\n\n.timeline li.timeline-green .timeline-time span.time {\n\t color: #35aa47; \n}\n\n/* Blue */\n.timeline li.timeline-blue .timeline-body:after {\n\tborder-right-color: #4b8df8;\n}\n\n.timeline li.timeline-blue .timeline-body {\n\t background: #4b8df8;\n}\n\n.timeline li.timeline-blue .timeline-time span.time {\n\t color: #4b8df8; \n}\n\n/* Purple */\n.timeline li.timeline-purple .timeline-body:after {\n\tborder-right-color: #852b99;\n}\n\n.timeline li.timeline-purple .timeline-body {\n\t background: #852b99;\n}\n\n.timeline li.timeline-purple .timeline-time span.time {\n\t color: #852b99; \n}\n\n/* Grey */\n.timeline li.timeline-grey .timeline-body:after {\n\tborder-right-color: #555555;\n}\n\n.timeline li.timeline-grey .timeline-body {\n\t background: #555555;\n}\n\n.timeline li.timeline-grey .timeline-time span.time {\n\t color: #555555; \n}\n\n@media (max-width: 767px) {  \n\ttimeline > li .timeline-time span.time {\n\t\tfont-size: 18px;\n\t}\n\n\t.timeline:before {\n\t\tdisplay: none;\n\t}\n\n\t.timeline > li .timeline-time {\n\t\twidth: 100%;\n\t\tposition: relative;\n\t\tpadding: 0 0 20px 0;\n\t}\n\n\t.timeline > li .timeline-time span {\n\t\ttext-align: left;\n\t}\n\n\t.timeline > li .timeline-body {\n\t\tmargin: 0 0 30px 0;\n\t\tpadding: 1em;\n\t}\n\n\t.timeline > li .timeline-body:after {\n\t\tright: auto;\n\t\tleft: 20px;\n\t\ttop: -20px;\n\t}\n\n\t.timeline > li .timeline-icon {\n\t\tposition: relative;\n\t\tfloat: right;\n\t\tleft: auto;\n\t\tmargin: -55px 5px 0 0px;\n\t}\t\n\n\t/*colors*/\n\n\n\t.timeline li.timeline-red .timeline-body:after {\n\t\tborder-right-color: transparent;\n\t\tborder-bottom-color: #e02222;\n\t}\n\n\t.timeline li.timeline-blue .timeline-body:after {\n\t\tborder-right-color: transparent;\n\t\tborder-bottom-color: #4b8df8;\n\t}\n\n\t.timeline li.timeline-green .timeline-body:after {\n\t\tborder-right-color: transparent;\n\t\tborder-bottom-color: #35aa47;\n\t}\n\n\t.timeline li.timeline-yellow .timeline-body:after {\n\t\tborder-right-color: transparent;\n\t\tborder-bottom-color: #ffb848;\n\t}\n\n\t.timeline li.timeline-purple .timeline-body:after {\n\t\tborder-right-color: transparent;\n\t\tborder-bottom-color: #852b99;\n\t}\n\n\t.timeline li.timeline-grey .timeline-body:after {\n\t\tborder-right-color: transparent;\n\t\tborder-bottom-color: #555555;\n\t}\n}\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/css/plugins.css",
    "content": "/**************************\n PLUGIN CSS CUSTOMIZATIONS \n**************************/\n\n/***\nCalendar with full calendar\n***/\n.external-event {\n  display: inline-block ;\n  cursor:move;\n  margin-bottom: 5px ;  \n  margin-left: 5px ;\n}\n\n.portlet .event-form-title {\n  font-size: 14px;\n  margin-top: 4px;\n  font-weight: 400;\n  margin-bottom: 10px;\n}\n\n.portlet.calendar .fc-button {\n  -webkit-box-shadow: none ;\n     -moz-box-shadow: none ;\n          box-shadow: none ;\n  text-shadow: none;\n  border: 0 ;\n  padding: 6px 8px 30px 8px ;\n  margin-left:2px;  \n  border-top-style: none;\n  border-bottom-style: none;\n  border-right-style: solid;\n  border-left-style: solid;\n  border-color: #ddd;\n  background: transparent;\n  color: #fff;\n  top: -46px;\n}\n\n.portlet.calendar .fc-header {\n  margin-bottom:-21px;\n}\n\n.portlet.calendar .fc-button-prev {\n  padding-right: 10px;\n  padding-left: 8px;\n}\n\n.portlet.calendar .fc-button-next {\n  padding-right: 8px;\n  padding-left: 10px;\n}\n\n.portlet.calendar .fc-button.fc-state-active,\n.portlet.calendar .fc-button.fc-state-hover {\n  color: #666 ;\n  background-color: #F9F9F9 ;\n}\n\n.portlet.calendar .fc-button.fc-state-disabled {\n  color: #ddd ;\n}\n\n.portlet.calendar .fc-text-arrow {\n  font-size: 22px;\n  font-family: \"Courier New\", Courier, monospace;\n  vertical-align: baseline; \n}\n\n/* begin: event element */\n.portlet.calendar .fc-event {\n  border: 0px;\n  background-color: #69a4e0;\n  color: #fff;\n}\n\n.portlet.calendar .fc-event-inner {\n  border: 0px;\n}\n\n.portlet.calendar .fc-event-time {\n  float: left;\n  text-align: left;\n  color: #fff;\n  font-size: 13px;\n  font-weight: 300;\n}\n\n.portlet.calendar .fc-event-title {\n  text-align: left;\n  float: left;\n  color: #fff;\n  font-size: 13px;\n  font-weight: 300;\n}\n/* end: event element */\n\n.portlet.calendar .fc-header-title h2 {\n  font-size: 14px ;\n  line-height: 20px;\n  font-weight: 400;\n  color: #111;\n}\n\n.portlet.calendar .fc-widget-header {\n  background-image: none ;\n  filter:none;\n  background-color: #eee ;\n  text-transform: uppercase;\n  font-weight: 300;\n}\n\n.portlet.calendar .mobile .fc-button {\n  margin-left: 2px ;\n}\n\n.portlet.calendar .mobile .fc-button {\n    padding: 0px 6px 20px 6px ;\n    margin-left:2px ;\n    border: 0;    \n    background-color: #ddd ;\n      background-image: none;\n      -webkit-box-shadow: none ;\n         -moz-box-shadow: none ;\n              box-shadow: none ;\n      -webkit-border-radius: 0 ;\n         -moz-border-radius: 0 ;\n              border-radius: 0 ;\n      color: #000;\n      text-shadow: none ;\n      text-align: center;\n}\n\n.portlet.calendar .mobile .fc-state-hover, \n.portlet.calendar .mobile .fc-state-active {\n  background-color: #eee ;\n}\n\n.portlet.calendar .mobile .fc-button-prev {\n  margin-right: 5px;\n  margin-top: -2px;\n}\n\n.portlet.calendar .mobile .fc-button-next {   \n  margin-right: -0px;\n  margin-top: -2px;\n}\n\n.portlet.calendar .mobile .fc-header-space {\n  margin: 0px ;\n  padding: 0px ;\n  width: 0px ;\n}\n\n  .portlet.calendar .mobile .fc-state-disabled {\n      color: #bbb ;\n  }\n\n  .portlet.calendar .mobile .fc-header-left {\n    position: absolute;\n    z-index: 10;\n  }\n    \n  .portlet.calendar .mobile .fc-header-right {\n    position: absolute;\n     z-index: 9;\n  }\n\n  .portlet.calendar .mobile .fc-header-left .fc-button { \n    top: -2px ;\n  }\n\n  .portlet.calendar .mobile .fc-header-right {\n    position: relative;\n    right:0;\n  }\n\n  .portlet.calendar .mobile .fc-header-right .fc-button { \n    top: 35px ;\n  }\n\n  .portlet.calendar .mobile .fc-content {\n    margin-top: 53px;\n  }\n\n\n/***\nForm wizard\n***/\n\n.form-wizard .progress {\n  margin-bottom: 30px;\n}\n\n.form-wizard .steps {\n  padding: 10px 0;\n  margin-bottom: 15px;\n}\n\n.form-wizard .steps {  \n  background-color: #fff ;\n  background-image: none ;\n  filter:none ;\n  border: 0px;\n  box-shadow: none ;\n}\n\n.form-wizard .steps li a {\n  background-color: #fff ;\n  background-image: none ;\n  filter:none;\n  border: 0px;\n  box-shadow: none ;\n}\n\n.form-wizard .steps li a:hover {\n  background: none;\n}\n\n.form-wizard .step:hover {\n  text-decoration: none;\n}\n\n.form-wizard .step .number {\n  background-color: #eee;\n  display: inline-block;\n  text-align: center !important;\n  font-size: 16px;\n  font-weight: 300;\n  padding: 11px 15px 13px 15px;\n  margin-right: 10px;\n  height: 45px;\n  width: 45px;\n  -webkit-border-radius: 50% !important;\n     -moz-border-radius: 50% !important;\n          border-radius: 50% !important;\n}\n\n.form-wizard .step .desc {\n  display: inline-block;\n  font-size: 16px;\n  font-weight: 300;\n}\n \n.form-wizard .active .step .number {\n  background-color: #35aa47;\n  color: #fff;\n}\n\n.form-wizard .active .step .desc {\n  color: #333;\n  font-weight: 400;\n}\n\n.form-wizard .step i {\n  display: none;\n}\n\n.form-wizard .done .step .number {\n  background-color: #f2ae43;\n  color: #fff;\n}\n\n.form-wizard .done .step .desc {\n  font-weight: 400;\n}\n\n.form-wizard .done .step i {\n  font-size: 12px;\n  font-weight: normal;\n  color: #999;\n  display: inline-block;\n}\n\n\n@media (min-width: 768px) and (max-width: 1280px) { \n  .form-wizard .step .desc {\n    margin-top: 10px;\n    display: block;\n  }\n} \n\n@media (max-width: 768px) { \n  .form-wizard .steps > li > a {\n    text-align: left;\n  }\n} \n\n/***\nGoogle Maps\n***/\n.gmaps {\n  height: 300px;\n  width: 100%;\n}\n\n/* important!  bootstrap sets max-width on img to 100% which conflicts with google map canvas*/\n.gmaps img {\n  max-width: none; \n}\n\n#gmap_static div{\n  background-repeat: no-repeat ;\n  background-position: 50% 50% ;\n  height:100%;\n  display:block;\n  height: 300px;\n}\n\n#gmap_routes_instructions {\n  margin-top: 10px;\n  margin-bottom: 0px;\n}\n\n/***\nSlimScrollBar plugins css changes\n***/\n.scroller {\n  padding: 0px ;\n  margin: 0px ;\n  padding-right: 12px ;\n  overflow: hidden;\n}\n\n.scroller-footer {\n  margin-top: 10px;\n}\n\n.scroller-footer:after,\n.scroller-footer:before {\n  content: \"\";\n  display: table;\n  line-height: 0;\n}\n\n.scroller-footer:after {\n  clear: both;\n}\n\n.portlet-body .slimScrollBar {\n  margin-right: 0px ;\n}\n\n/***\njqvmap changes\n***/\n.jqvmap-zoomin {\n  height: 16px;\n  width: 16px;\n  background-color: #666 ;\n}\n\n.jqvmap-zoomout {\n  height: 16px;\n  width: 16px;\n background-color: #666 ; \n}\n\n.vmaps {\n  position: relative; \n  overflow: hidden;\n  height: 300px;\n}\n\n\n/***\nError state for WYSIWYG Editors\n***/\n.has-error .md-editor,\n.has-error .wysihtml5-sandbox, \n.has-error .cke {\n  border: 1px solid #B94A48 !important;\n}\n\n.has-success .md-editor,\n.has-success .wysihtml5-sandbox, \n.has-success .cke {\n  border: 1px solid #468847 !important;\n}\n\n/***\nSelect2 plugin css changes\n***/\n\n/* enable form validation classes for select2 dropdowns */\n.has-error .select2-container .select2-choice {\n  border-color: #B94A48;\n}\n\n.has-error .select2-container.select2-dropdown-open .select2-choice {\n  border-color: #e5e5e5; \n}\n\n.has-error .select2-container.select2-dropdown-open .select2-choice > span {\n  color: #999999;\n}\n\n.has-success .select2-container .select2-choice {\n  border-color: #468847;\n}\n\n.has-success .select2-container.select2-dropdown-open .select2-choice {\n  border-color: #e5e5e5; \n}\n\n.has-success .select2-container.select2-dropdown-open .select2-choice > span {\n  color: #999999;\n}\n\n\n/***\nFileuploader plugin css changes\n***/\n.fileupload .btn {\n  padding: 7px 14px ;\n}\n\n.fileupload-exists {\n  padding: 0px;\n}\n\n.fileupload .fileupload-preview {\n  background-color: #fff ;\n  background-image: none ;\n  filter:none ;\n}\n\n.fileupload .close {\n  position: relative;\n  top:0px ;\n}\n\n\n/***\nWYSIWYG\n***/\n.wysihtml5-toolbar li {\n  margin: 0px;\n  height: 29px;\n}\n\n.wysihtml5-toolbar li .dropdown-menu {\n  margin-top: 5px;\n}\n\n/***\nCKEditor css changes\n***/\n.cke_bottom, \n.cke_inner, \n.cke_top, \n.cke_reset, \n.cke_dialog_title,\n.cke_dialog_footer,\n.cke_dialog {\n  background-image: none !important;\n  filter:none ; \n  border-top: 0 ;\n  border-bottom: 0 ;\n   -webkit-box-shadow: none !important;\n      -moz-box-shadow: none !important;\n           box-shadow: none !important;\n  text-shadow:none ;\n}\n\n.cke_dialog_ui_button,\n.cke_dialog_tab {\n  background-image: none !important;\n  filter:none ;\n  -webkit-box-shadow: none !important;\n  -moz-box-shadow: none !important;\n  box-shadow: none !important;\n  text-shadow:none !important;\n}\n\n.cke_dialog_ui_button:hover,\n.cke_dialog_tab:hover {\n  text-decoration: none;\n  text-shadow:none ;\n}\n\n.cke_dialog_ui_input_text {\n  background-image: none !important;\n  filter:none ;\n  -webkit-box-shadow: none !important;\n  -moz-box-shadow: none !important;\n  box-shadow: none !important;\n}\n\n.cke_combo_button, \n.cke_button, \n.cke_toolbar, \n.cke_toolgroup {\n  background-image: none !important;\n  filter:none !important;\n  border: 0 ;\n   -webkit-box-shadow: none !important;\n  -moz-box-shadow: none !important;\n  box-shadow: none !important;\n}\n\n.cke_button, \n.cke_combo_button,\n.cke_panel_grouptitle,\n.cke_hc.cke_panel_listItem a {  \n  background-image: none !important;\n  filter:none ;\n  text-shadow:none ;\n  -webkit-border-radius: 0px !important;\n  -moz-border-radius: 0px !important;\n  -ms-border-radius: 0px !important;\n  -o-border-radius: 0px !important;\n}\n\n.cke_button:hover, \n.cke_combo_button:hover {  \n  background-color: #ddd;\n}\n\n.cke_toolbar_break {\n  background-image: none !important;\n  filter:none !important;\n  border: 0 ;\n  box-shadow: none !important;\n  -webkit-box-shadow : none !important;\n  -moz-box-shadow: none !important;\n  -ms-box-shadow: none !important;\n  -o-box-shadow: none !important;\n}\n\n/***\nModify tags input plugin css\n***/\ndiv.tagsinput {\n  min-height: 35px;\n  height: auto !important;\n  margin: 0;\n  padding: 5px 5px 0px 5px;\n  overflow: auto;\n}\n\ndiv.tagsinput span.tag {\n  background: #aaa ;\n  color: #fff ;\n  border: 0 ;\n  padding: 3px 6px;\n  margin-top: 0;\n  margin-bottom: 5px;\n}\n\ndiv.tagsinput input {\n  padding: 3px 6px ; \n  width: 75px !important;\n}\n\ndiv.tagsinput span.tag a {\n  color: #fff ;\n}\n\ndiv.tagsinput .not_valid {\n  color: #fff ;\n  padding: 3px 6px ;\n  background-color: #e02222 ;\n}\n\n/***\nGritter notification modify\n***/\n\n#gritter-notice-wrapper {\n  right:1px !important;\n}\n\n.gritter-close {\n  left:auto !important;\n  right: 3px !important;\n}\n\n.gritter-title {\n  font-family:  'Open Sans' ;\n  font-size: 18px ;\n  font-weight: 300 ;\n}\n\n/***\njQuery UI Sliders(new in v1.1.1)\n***/\n.slider {\n  border: 0;\n  padding: 0;\n  display: block;\n  margin: 12px 5px;\n  min-height: 11px; \n}\n\n.ui-slider-vertical {\n  width: 11px;\n}\n\n.ui-slider-horizontal .ui-slider-handle {\n  top: -3px;\n}\n\n.ui-slider-vertical .ui-slider-handle {\n  left: -3px;\n}\n\n.ui-slider-vertical,\n.ui-slider-handle {\n  filter: none !important;\n  background-image: none !important;\n}\n\n/***\nDropzone css changes(new in v1.1.1)\n***/\n.dropzone {\n  -webkit-border-radius: 0px ;\n    -moz-border-radius: 0px ;\n         border-radius: 0px ;\n}\n\n\n/***\nDashboard Charts(new in v1.2.1)\n***/\n.easy-pie-chart,\n.sparkline-chart {\n   text-align: center;\n}\n\n.sparkline-chart {\n  margin-top: 15px;\n  position:relative ;\n}\n\n.easy-pie-chart .number {\n    font-size: 16px;\n    font-weight: 300;\n    width: 85px;\n    margin: 0 auto;\n}\n\n.sparkline-chart .number {  \n    width: 100px;\n    margin: 0 auto;\n    margin-bottom: 10px;\n}\n\n.sparkline-chart .title,\n.easy-pie-chart .title {\n    display: block;\n    text-align: center;\n    color: #333;\n    font-weight: 300;\n    font-size: 16px;\n    margin-top: 5px;\n    margin-bottom: 10px;\n}\n\n.sparkline-chart .title:hover,\n.easy-pie-chart .title:hover {\n  color: #666;\n  text-decoration: none;\n}\n\n.sparkline-chart .title > i,\n.easy-pie-chart .title > i {\n  margin-top: 5px;\n}\n\n/***\nFancy box fix overlay fix(in v1.2.4)\n***/\n.fancybox-overlay {\n  z-index: 10000 ;\n}\n\n\n/***\nDatatables Plugin(in v1.3)\n***/\n.dataTable {  \n  width: 100% !important;\n  clear: both;\n  margin-top: 5px;\n}\n\n.dataTables_filter label {\n  line-height: 32px ;\n}\n\n.dataTable .row-details {  \n  margin-top: 3px;\n  display: inline-block;\n  cursor: pointer;\n  width: 14px;\n  height: 14px;\n}\n\n.dataTable .row-details.row-details-close {\n  background: url(\"../img/datatable-row-openclose.png\") no-repeat 0 0;\n}\n\n.dataTable .row-details.row-details-open {  \n  background: url(\"../img/datatable-row-openclose.png\") no-repeat 0 -23px ;\n}\n\n.dataTable .details {\n  background-color: #eee ;\n}\n\n.dataTable .details td,\n.dataTable .details th {\n  padding: 4px;\n  background: none ;\n  border: 0;\n}\n\n.dataTable .details tr:hover td,\n.dataTable .details tr:hover th {\n  background: none ;\n}\n\n.dataTable .details tr:nth-child(odd) td,\n.dataTable .details tr:nth-child(odd) th {\n  background-color: #eee ;\n}\n\n.dataTable .details tr:nth-child(even) td,\n.dataTable .details tr:nth-child(even) th {\n  background-color: #eee ;\n}\n\n.dataTable > thead > tr > th.sorting,\n.dataTable > thead > tr > th.sorting_asc,\n.dataTable > thead > tr > th.sorting_desc {\n   padding-right: 18px;\n}\n\n.dataTable .table-checkbox {\n  width: 8px !important;\n}\n\n@media (max-width: 768px) {  \n  .dataTables_wrapper .dataTables_length .form-control,\n  .dataTables_wrapper .dataTables_filter .form-control {\n    display: inline-block;\n  }\n\n  .dataTables_wrapper .dataTables_info {\n    top: 17px;\n  }\n\n  .dataTables_wrapper .dataTables_paginate {\n    margin-top: -15px;\n  }\n}\n\n@media (max-width: 480px) {  \n  .dataTables_wrapper .dataTables_filter .form-control {\n    width: 175px !important;\n  }\n\n  .dataTables_wrapper .dataTables_paginate {\n    float: left;\n    margin-top: 20px;\n  }\n}\n\n/***\nPassword Strength(in v1.4)\n***/\n.password-strength .password-verdict {\n  display: inline-block;\n  margin-top: 6px;\n  margin-left: 5px;\n}\n\n.password-strength .progress {\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n\n.password-strength .progress-bar {\n  padding: 2px;\n}\n\n/***\nUniform disabled checkbox, radio button fix(in v1.4)\n***/\n\n.table .uniform-inline {\n  padding: 0;\n  margin: 0;\n}\n\n.checker {\n  margin-top: -2px !important;\n  margin-right: 2px !important;\n}\n\n.checker input,\n.radio input {\n  outline: none !important;\n}\n\ndiv.checker.disabled span, \ndiv.checker.disabled.active span{\n    background-position: -152px -260px; \n}\n\ndiv.checker.disabled:hover,\ndiv.radio.disabled:hover {\n    cursor: not-allowed;  \n}\n\n/***\njQuery Sparkline\n***/\n.jqstooltip {\n  width: auto !important;\n  height: auto !important;\n}\n\n\n/***\njQuery Multi Select\n***/\n\n.ms-container .ms-list {\n  border: 1px solid #e5e5e5;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n\n}\n\n.ms-container .ms-optgroup-label{\n  font-size: 14px;\n}\n\n.ms-container .ms-selectable li.ms-elem-selectable,\n.ms-container .ms-selection li.ms-elem-selection{\n  font-size: 13px;\n}\n\n.ms-container .ms-list.ms-focus {\n  border-color: #999999;\n  -webkit-box-shadow: none;\n     -moz-box-shadow: none;\n          box-shadow: none;\n}\n\n.ms-container .ms-selectable li.ms-hover,\n.ms-container .ms-selection li.ms-hover{\n  color: #333;\n  background-color: #eee;\n}\n\n.ms-container .form-control {\n  margin-bottom: 5px;\n}\n\n/***\nBootstrap Colorpicker\n***/\n.input-group.color .input-group-btn i {\n  position: absolute;\n  display: block;\n  cursor: pointer;\n  width: 20px;\n  height: 20px;\n  right: 6px;\n} \n\n.colorpicker.dropdown-menu {\n  padding: 5px;\n}\n\n/***\nBootstrap  Datetimepicker\n***/\n\n.datetimepicker table td {\n  font-weight: 300  !important;\n  font-family: 'Open Sans' !important;\n}\n\n.datetimepicker table th {\n  font-family: 'Open Sans' !important;\n  font-weight: 400  !important;\n}\n\n.datetimepicker.dropdown-menu {\n  padding: 5px;\n}\n\n.datetimepicker .active {  \n  background-color:#4b8df8 !important;\n  background-image: none !important;\n  filter: none !important;\n}\n\n\n.datetimepicker .active:hover {\n  background-color: #2678FC !important;\n  background-image: none !important;\n  filter: none !important;\n\n}\n\n/* change z-index when opened in modal */\n.modal-open .datetimepicker {\n  z-index: 10055 !important;\n}\n\n/***\nBootstrap Datepicker\n***/\n\n.datepicker.dropdown-menu {\n  padding: 5px;\n}\n\n.datepicker .selected {  \n  background-color:#909090 !important;\n  background-image: none !important;\n  filter: none !important;\n}\n\n.datepicker .active {  \n  background-color:#4b8df8 !important;\n  background-image: none !important;\n  filter: none !important;\n}\n\n.datepicker .active:hover {\n  background-color: #2678FC !important;\n  background-image: none !important;\n  filter: none !important;\n}\n\n.datepicker .input-daterange input {\n  text-align: left;\n}\n\n/* change z-index when opened in modal */\n.modal-open .datepicker {\n  z-index: 10055 !important;\n}\n\n.datepicker table td {\n  font-weight: 300  !important;\n  font-family: 'Open Sans' !important;\n}\n\n.datepicker table th {\n  font-family: 'Open Sans' !important;\n  font-weight: 400  !important;\n}\n\n\n/***\nClockface\n***/\n\n.modal-open .clockface {\n  z-index: 10055 !important;\n}\n\n.clockface .cell .inner.active,\n.clockface .cell .outer.active {\n  background-color:#4b8df8 !important;\n  background-image: none ;\n  filter:none ;\n}\n\n\n/***\nBootstrap Daterangepicker\n***/\n\n.modal-open .daterangepicker {\n  z-index: 10055 !important;\n}\n\n.daterangepicker td {\n  text-shadow: none ;\n}\n\n.daterangepicker td.active {\n  background-color: #4b8df8 ;\n  background-image: none ;\n  filter:none ;\n}\n\n.daterangepicker th {\n  font-weight: 400;\n  font-size: 14px;\n}\n\n.daterangepicker .ranges input[type=\"text\"]  {\n  width: 70px !important;\n  font-size: 11px;\n  vertical-align: middle;\n}\n\n.daterangepicker .ranges label {\n  font-weight: 300;\n  display: block;\n}\n\n.daterangepicker .ranges .btn {\n  margin-top: 10px;\n}\n\n.daterangepicker.dropdown-menu {\n  padding: 5px;\n}\n\n.daterangepicker .ranges li {\n  color: #333;\n}\n\n.daterangepicker .ranges li.active, \n.daterangepicker .ranges li:hover {\n  background: #4b8df8 !important;\n  border: 1px solid #4b8df8 !important;\n  color: #fff;\n}\n\n.daterangepicker .range_inputs input {\n  margin-bottom: 0 !important;\n}\n\n/***\nBootstrap Editable\n***/\n\n.editable-input table,\n.editable-input table th,\n.editable-input table td,\n.editable-input table tr {\n  border: 0 !important;\n}\n\n.editable-input .combodate select {\n  margin-bottom: 5px;\n}\n\n/***\nFuelUX Spinners\n***/\n\n.spinner-buttons.btn-group-vertical .btn {\n  text-align: center;\n  margin: 0;\n  height: 17px;\n  width: 22px;\n  padding-left: 6px;\n  padding-right: 6px;\n} \n\n.spinner-buttons.btn-group-vertical .btn .icon-angle-down {\n  display: inline-block;\n  position: relative;\n  top: -2px;\n}\n\n\n/***\nNoUI Range Sliders\n***/\n.noUi-handle {\n  height: 20px;\n  width: 20px;\n  margin: -3px 0 0 -20px;\n}\n\n.noUi-base {\n  height: 16px;\n}\n\n.noUi-connect {\n  background: #ffb848;\n}\n\n/***\nToastr Notifications\n***/\n.toast {\n    -webkit-box-shadow: none !important;\n     -moz-box-shadow: none !important;\n          box-shadow: none !important;\n}\n\n.toast {\n  background-color: #030303;\n}\n.toast-success {\n  background-color: #51a351;\n}\n.toast-error {\n  background-color: #bd362f;\n}\n.toast-info {\n  background-color: #2f96b4;\n}\n.toast-warning {\n  background-color: #f89406;\n}\n\n.toast .toast-close-button {\n  display: inline-block;\n  margin-top: 0px;\n  margin-right: 0px;\n  text-indent: -100000px;\n  width: 11px;\n  height: 16px;\n  background-repeat: no-repeat !important;\n  background-image: url(\"../img/portlet-remove-icon-white.png\") !important;\n}\n\n.toast-top-center {\n  top: 12px;\n  margin: 0 auto;\n  left: 50%;\n  margin-left: -150px;\n}\n\n.toast-bottom-center {\n  bottom: 12px;\n  margin: 0 auto;\n  left: 50%;\n  margin-left: -150px;\n}\n\n/***\nGoogle reCaptcha\n***/\n.form-recaptcha-img {\n  margin-bottom: 10px;\n  clear: both;\n  border: 1px solid #e5e5e5;\n  padding: 5px;\n}\n\n/***\nBootstrap Markdown\n***/\n.md-input {\n  padding: 5px !important;\n  border-bottom: 0 !important;\n}\n\n.md-editor.active {\n  border: 1px solid #999999;\n  -webkit-box-shadow: none !important;\n     -moz-box-shadow: none !important;\n          box-shadow: none !important;\n}\n\n/***\nBootstrap Datepaginator\n***/\n.datepaginator a {\n  font-family: 'Open Sans';\n  font-size: 13px;\n  font-weight: 300;\n}\n\n.datepicker .today {\n  background-image: none !important;\n  filter: none !important;\n}\n\n#dp-calendar {\n  right: 4px !important;\n}\n\n/***\nFont Awesome 4.0 Demo\n***/\n.fa-item {\n  font-size: 14px;\n  padding: 10px 10px 10px 20px;\n}\n\n.fa-item i {\n  font-size: 16px;\n  display: inline-block;\n  width: 20px;\n}\n\n.fa-item:hover {\n  cursor: pointer;\n  background: #eee;\n}\n\n/***\nBootstrap Modal\n***/\n/* fix: content shifting to the right on modal open */\n.modal-open.page-overflow .page-container,\n.modal-open.page-overflow .page-container .navbar-fixed-top,\n.modal-open.page-overflow .page-container .navbar-fixed-bottom,\n.modal-open.page-overflow .modal-scrollable {\n  overflow-y: auto !important;\n}\n\n.modal-scrollable {\n  overflow: hidden !important;\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/css/print.css",
    "content": "/***\nImport fonts\n***/\n.header {\n\tdisplay: none;\n}\n\n.page-sidebar {\n\tdisplay: none;\n}\n\n.theme-panel {\n\tdisplay: none;\n}\n\n.hidden-print {\n\tdisplay: none;\n}\n\n.footer {\n\tdisplay: none;\n}\n\n.no-page-break {\n\tpage-break-after: avoid;\n}\n\n.page-container {\n\tmargin: 0px;\n\tpadding: 0px;\n}\n\n.page-content {\n\tmin-height: auto !important;\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/css/style-metronic.css",
    "content": "/* remove rounds from all elements */\n\ndiv, \ninput, \nselect, \ntextarea, \nspan, \nimg, \ntable, \ntd, \nth, \np, \na, \nbutton, \nul,\ncode,\npre, \nli {\n  -webkit-border-radius: 0 !important;\n     -moz-border-radius: 0 !important;\n          border-radius: 0 !important;\n}\n\n/***\nButtons & Dropdown Buttons\n***/\n\n.btn {\n\tborder-width: 0;\n\tpadding: 7px 14px; \t\n  font-size: 14px;  \n\toutline: none !important;\n  -webkit-box-shadow: none !important;\n     -moz-box-shadow: none !important;\n          box-shadow: none !important;\n  -webkit-border-radius: 0 !important;\n     -moz-border-radius: 0 !important;\n          border-radius: 0 !important;\n          text-shadow: none;\n}\n\n/* fix jumping group buttons */\n.btn-group.btn-group-solid .btn + .btn,\n.btn-group.btn-group-solid .btn + .btn-group.btn-group-solid,\n.btn-group.btn-group-solid .btn-group.btn-group-solid + .btn,\n.btn-group.btn-group-solid .btn-group.btn-group-solid + .btn-group.btn-group-solid {\n  margin-left: 0px;\n}\n\n.btn-group-vertical.btn-group-solid > .btn + .btn,\n.btn-group-vertical.btn-group-solid > .btn + .btn-group,\n.btn-group-vertical.btn-group-solid > .btn-group + .btn,\n.btn-group-vertical.btn-group-solid > .btn-group + .btn-group {\n  margin-top: 0px;\n  margin-left: 0;\n}\n\n.btn-default {\n  border-width: 1px;\n  padding: 6px 13px;\n} \n\n.btn.red-stripe {\n\tborder-left: 3px solid #d84a38;\n}\n\n.btn.blue-stripe {\n\tborder-left: 3px solid #4d90fe;\n}\n\n.btn.purple-stripe {\n\tborder-left: 3px solid #852b99;\n}\n\n.btn.green-stripe {\n\tborder-left: 3px solid #35aa47;\n}\n\n.btn.yellow-stripe {\n  border-left: 3px solid #ffb848;\n}\n\n.btn.dark-stripe {\n  border-left: 3px solid #555555;\n}\n\n.btn.default {  \n  color: #333333;\n  text-shadow: none;  \n  background-color: #e5e5e5;\n}\n.btn.default:hover, \n.btn.default:focus, \n.btn.default:active, \n.btn.default.active,\n.btn.default[disabled], \n.btn.default.disabled {    \n  color: #333333;\n  background-color: #d8d8d8 !important;\n  outline: none !important;\n}\n\n/*  Red */\n.btn.red {\n  color: white;  \n  text-shadow: none;\t\n  background-color: #d84a38;\n}\n.btn.red:hover, \n.btn.red:focus, \n.btn.red:active, \n.btn.red.active,\n.btn.red[disabled], \n.btn.red.disabled {    \n  background-color: #bb2413 !important;\n  color: #fff !important;\n  outline: none !important;\n}\n\n/*  Blue */\n\n.btn.blue {\n  color: white;  \n  text-shadow: none;\t\n  background-color: #4d90fe;\n}\n.btn.blue:hover, \n.btn.blue:focus, \n.btn.blue:active,\n.btn.blue.active,\n.btn.blue[disabled],\n.btn.blue.disabled {  \n  background-color: #0362fd !important;\n  color: #fff !important;\n  outline: none !important;\n}\n\n.btn-group .btn.blue.dropdown-toggle {\n  background-color: #4d90fe !important;\n}\n.btn-group .btn.blue:hover, \n.btn-group .btn.blue:focus, \n.btn-group .btn.blue:active, \n.btn-group .btn.blue.active, \n.btn-group .btn.blue.disabled,\n.btn-group .btn.blue[disabled] { \n  background-color: #0362fd !important;\n  color: #fff !important;\n  outline: none !important;\n}\n\n/*  Green */\n.btn.green {\n  color: white;\n  text-shadow: none;\t \n  background-color: #35aa47;\n}\n.btn.green:hover, \n.btn.green:focus, \n.btn.green:active, \n.btn.green.active,\n.btn.green.disabled, \n.btn.green[disabled]{ \n  background-color: #1d943b !important;\n  color: #fff !important;\n  outline: none !important;\n}\n\n/*  Purple */\n.btn.purple {\n  color: white; \n  text-shadow: none;\t\n  background-color: #852b99;\n}\n.btn.purple:hover, \n.btn.purple:focus, \n.btn.purple:active, \n.btn.purple.active, \n.btn.purple.disabled,\n.btn.purple[disabled] { \n  background-color: #6d1b81 !important;\n  color: #fff !important;\n  outline: none !important;\n}\n\n.btn-group .btn.purple.dropdown-toggle {\n  background-color: #852b99 !important;\n}\n.btn-group .btn.purple:hover, \n.btn-group .btn.purple:focus, \n.btn-group .btn.purple:active, \n.btn-group .btn.purple.active, \n.btn-group .btn.purple.disabled,\n.btn-group .btn.purple[disabled] { \n  background-color: #6d1b81 !important;\n  color: #fff !important;\n  outline: none !important;\n}\n\n/*  Yellow */\n.btn.yellow {\n  color: white; \n  text-shadow: none;\t\n  background-color: #ffb848;\n}\n.btn.yellow:hover, \n.btn.yellow:focus, \n.btn.yellow:active, \n.btn.yellow.active, \n.btn.yellow.disabled,\n.btn.yellow[disabled] { \n  background-color: #eca22e !important;\n  color: #fff !important;\n  outline: none !important;\n}\n\n.btn-group .btn.yellow.dropdown-toggle {\n  background-color: #ffb848 !important;\n}\n.btn-group .btn.yellow:hover, \n.btn-group .btn.yellow:focus, \n.btn-group .btn.yellow:active, \n.btn-group .btn.yellow.active, \n.btn-group .btn.yellow.disabled,\n.btn-group .btn.yellow[disabled] { \n  background-color: #eca22e !important;\n  color: #fff !important;\n  outline: none !important;\n}\n\n/*  Black */\n.btn.dark {\n  color: white; \n  text-shadow: none;\t\n  background-color: #555555;\n}\n.btn.dark:hover, \n.btn.dark:focus, \n.btn.dark:active, \n.btn.dark.active, \n.btn.dark.disabled,\n.btn.dark[disabled] { \n  background-color: #222222 !important;\n  color: #fff !important;\n  outline: none !important;\n}\n\n.btn-group .btn.dark.dropdown-toggle {\n  background-color: #555555 !important;\n}\n.btn-group .btn.dark:hover, \n.btn-group .btn.dark:focus, \n.btn-group .btn.dark:active, \n.btn-group .btn.dark.active, \n.btn-group .btn.dark.disabled,\n.btn-group .btn.dark[disabled] { \n  background-color: #222222 !important;\n  color: #fff !important;\n  outline: none !important;\n}\n\n.btn-lg {\n  padding: 10px 16px;\n  font-size: 18px;\n  line-height: 1.33;\n  vertical-align: middle;\n}\n\n.btn-lg > i {\n  font-size: 18px;\n}\n\n.btn > i {\n  font-size: 14px;\n}\n\n.btn-sm,\n.btn-xs {\n  padding: 5px 10px;\n  font-size: 12px;\n  line-height: 1.5;\n}\n\n.btn-sm > i,\n.btn-xs > i {\n  font-size: 13px;\n} \n\n.btn-xs {\n  padding: 1px 5px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-left: 0;\n  padding-right: 0;\n}\n\n/***\nMetro icons\n***/\n\n[class^=\"m-icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  margin-top: 3px;\n  line-height: 14px;  \n  vertical-align: top;\n  background-image: url(../img/syncfusion-icons.png);\n  background-position: 0 0;\n  background-repeat: no-repeat; \n}\n\n[class^=\"m-icon-big-\"] {\n  display: inline-block;\n  width: 30px;\n  height: 30px; \n  margin: 6px;\n  vertical-align: middle;\n  background-image: url(../img/syncfusion-icons.png);\n  background-position: 0 0px;\n  background-repeat: no-repeat; \n}\n\n/* large icons */\n.btn.m-icon-big {\n  padding: 9px 16px 8px 16px; \n}\n\n.btn.m-icon-big.m-icon-only{\n  padding: 9px 8px 8px 0px;\n}\n\n.btn.m-icon-big [class^=\"m-icon-big-\"] {\n  margin: 0 0 0 10px;\n}\n\n.btn.m-icon-ony > i {\n  margin-left: 0px;\n}\n\n/* default icons */\n.btn.m-icon {\n  padding: 7px 14px 7px 14px; \n}\n\n.btn.m-icon [class^=\"m-icon-\"] {\n  margin: 4px 0 0 5px;\n}\n\n.btn.m-icon.m-icon-only {\n  padding: 7px 10px 7px 6px;\n}\n\n/* white icon */\n.m-icon-white {\n  background-image: url(../img/syncfusion-icons-white.png);\n}\n\n/*  Misc */\n.m-icon-swapright {\n  background-position: -27px -10px;\n}\n.m-icon-swapdown {\n  background-position: -68px -10px;\n}\n.m-icon-swapleft {\n  background-position: -8px -10px;\n}\n.m-icon-swapup {\n  background-position: -46px -10px;\n}\n.m-icon-big-swapright{\n  background-position: -42px -28px;\n}\n.m-icon-big-swapdown{\n  background-position: -115px -28px;\n}\n.m-icon-big-swapleft{\n  background-position: -6px -28px;\n}\n.m-icon-big-swapup{\n  background-position: -78px -28px;\n}\n\n\n/***\nPopover\n ***/\n.popover {\n  -webkit-box-shadow: 0 1px 8px rgba(0, 0, 0, 0.2);\n     -moz-box-shadow: 0 1px 8px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 1px 8px rgba(0, 0, 0, 0.2);  \n  padding: 0 !important;\n}\n\n.popover .popover-title {\n    -webkit-border-radius: 0 !important;\n     -moz-border-radius: 0 !important;\n          border-radius: 0 !important;\n          margin: 0 !important;\n}\n\n.info .popover .popover-title,\n.popover.info .popover-title,\n.info .popover .popover-content,\n.popover.info .popover-content {\n  color:#27a9e3;\n}\n\n.success .popover .popover-title,\n.popover.success .popover-title,\n.success .popover .popover-content,\n.popover.success .popover-content {\n  color:#468847;\n}\n\n.error .popover .popover-title,\n.popover.error .popover-title,\n.error .popover .popover-content,\n.popover.error .popover-content {\n  color:#B94A48;\n}\n\n.warning .popover .popover-title,\n.popover.warning .popover-title,\n.warning .popover .popover-content,\n.popover.warning .popover-content {\n  color:#C09853;\n}\n\n\n/***\nDropdown\n***/\n\n /*Fixing dropdown issue on mobile devices in Bootstrap 3.2.2*/\n.dropdown-backdrop {\n  position: static;\n}\n\n.dropdown:hover .caret, \n.open.dropdown .caret {\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n\n.dropdown.open .dropdown-toggle {\n  color: #08c;\n  background: #ccc;\n  background: rgba(0, 0, 0, 0.3);\n}\n\n/***\nDropdown Menu\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  list-style: none;\n  text-shadow: none;\n  padding: 0px;\n  margin:0px;\n  background-color: #ffffff;\n  -webkit-box-shadow: 0 1px 8px rgba(0, 0, 0, 0.1);\n  -moz-box-shadow: 0 1px 8px rgba(0, 0, 0, 0.1);\n  box-shadow: 0 1px 8px rgba(0, 0, 0, 0.1);  \n  font-size: 14px;\n  font-family: \"Segoe UI\",Helvetica, Arial, sans-serif;\n  border: 1px solid #ddd;\n}\n\n/* custom dropdown conetnt */\n.dropdown-content {\n  padding:5px;\n}\n\n.dropdown-content form {\n  margin:0;\n}\n\n.dropdown.inline .dropdown-menu {\n  display: inline-block;  \n  position: relative;\n}\n\n.dropdown-menu.bottom-up {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 2px;\n}\n\n.dropdown-menu li > a {\n  padding: 6px 0 6px 13px;\n  color: #333;\n  text-decoration: none;\n  display: block;\n  clear: both;\n  font-weight: normal;\n  line-height: 18px;\n  white-space: nowrap;\n}\n\n.dropdown-menu li > a:hover, \n.dropdown-menu .active > a, \n.dropdown-menu .active > a:hover {\n  text-decoration: none;\n  background-image: none;\n  background-color: #eee;\n  color: #333;\n  filter:none;\n}\n\n/* dropdown sub menu support for Bootsrap 3 */\n.dropdown-submenu {\n  position: relative;\n}\n\n.dropdown-submenu > .dropdown-menu {\n  top: 5px;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n}\n\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n\n.dropup .dropdown-submenu > .dropdown-menu {\n  top: auto;\n  bottom: 0;\n  margin-top: 0;\n  margin-bottom: -2px;\n}\n\n.dropdown-submenu > a:after {\n  position: absolute;\n  display: inline-block;\n  font-size: 14px;\n  right: 7px;\n  top: 7px;\n  font-family: FontAwesome;\n  height: auto;\n  content: \"\\f105\";\n  font-weight: 300;\n}\n\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n\n.dropdown-submenu.pull-left {\n  float: none;\n}\n\n.dropdown-submenu.pull-left > .dropdown-menu {\n  left: -100%;\n  margin-left: 10px;\n}\n\n.nav.pull-right > li > .dropdown-menu,\n.nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.nav.pull-right > li > .dropdown-menu:before,\n.nav > li > .dropdown-menu.pull-right:before {\n  right: 12px;\n  left: auto;\n}\n\n.nav.pull-right > li > .dropdown-menu:after,\n.nav > li > .dropdown-menu.pull-right:after {\n  right: 13px;\n  left: auto;\n}\n\n.nav.pull-right > li > .dropdown-menu .dropdown-menu,\n.nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  right: 100%;\n  left: auto;\n  margin-right: -1px;\n  margin-left: 0;\n  -webkit-border-radius: 6px 0 6px 6px;\n     -moz-border-radius: 6px 0 6px 6px;\n          border-radius: 6px 0 6px 6px;\n}\n\n@media (max-width: 767px) {\n\n  .navbar-nav .open .dropdown-menu {\n    position: absolute;\n    float: left;\n    width: auto;\n    margin-top: 0;\n    background-color: #ffffff;\n    border: 1px solid #ddd;\n    -webkit-box-shadow: 0 1px 8px rgba(0, 0, 0, 0.1);\n       -moz-box-shadow: 0 1px 8px rgba(0, 0, 0, 0.1);\n            box-shadow: 0 1px 8px rgba(0, 0, 0, 0.1);  \n  }\n\n  .navbar-nav .open .dropdown-menu > li > a {\n     padding: 6px 0 6px 13px;\n     color: #333 !important;\n  }\n\n  .navbar-nav .open .dropdown-menu > li > a:hover,\n  .navbar-nav .open .dropdown-menu > li > a:focus {\n    background-color: #eee !important;\n  }\n\n}\n \n/* bagin: sidebar menu badges */\n\n/***\nDropdown Checkboxes (in v1.3)\n***/\n.dropdown-checkboxes {\n  padding: 5px;\n}\n\n.dropdown-checkboxes label {\n  display: block;\n  font-weight: 300;\n  color: #333;\n  margin-bottom: 4px;\n  margin-top: 4px; \n}\n\n\n/***\nDropdown Menu Badges\n***/\n\n.dropdown-menu > li > a > .badge {\n   position: absolute;\n   margin-top: 1px;\n   right: 3px;\n   display: inline;\n   font-size: 11px;\n   font-weight: 300;\n   text-shadow:none;\n    height: 18px;\n    padding: 3px 6px 3px 6px;\n    text-align: center;\n    vertical-align: middle;\n   -webkit-border-radius: 12px !important;\n      -moz-border-radius: 12px !important;\n           border-radius: 12px !important;\n}\n\n.dropdown-menu > li > a > .badge.badge-roundless {\n   -webkit-border-radius: 0 !important;\n      -moz-border-radius: 0 !important;\n           border-radius: 0 !important;\n}\n\n/* end: sidebar menu badges */\n\n/***\nForms\n***/\ncode {\n  border: 1px solid #e1e1e1;\n    -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);\n  -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);\n  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);  \n}\nlabel {\n  font-weight: 400;\n  font-size: 14px;\n}\n\n.form-control:-moz-placeholder {\n  color: #999999;\n}\n.form-control::-moz-placeholder {\n  color: #999999;\n}\n.form-control:-ms-input-placeholder {\n  color: #999999;\n}\n.form-control::-webkit-input-placeholder {\n  color: #999999;\n}\n.form-control {  \n  font-size: 14px;\n  font-weight: normal;\n  color: #333333;\n  background-color: #ffffff;\n  border: 1px solid #e5e5e5;\n  border-radius: 0;\n  -webkit-box-shadow: none;\n  box-shadow: none;\n  -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n  transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n}\n.form-control:focus {\n  border-color: #999999;\n  outline: 0;\n  -webkit-box-shadow: none !important;\n  box-shadow: none !important;\n}\n.form-control[disabled],\n.form-control[readonly],\nfieldset[disabled] .form-control {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\n.uneditable-input {\n  padding: 6px 12px;\n  min-width: 206px;\n  font-size: 14px;\n  font-weight: normal;\n  height: 34px;\n  color: #333333;\n  background-color: #ffffff;\n  border: 1px solid #e5e5e5;\n  border-radius: 0;\n  -webkit-box-shadow: none;\n  box-shadow: none;\n  -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n  transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n}\n\nlabel.form-control {\n  display: block;\n  margin-bottom: 5px;\n}\n\ninput[disabled],\nselect[disabled],\ntextarea[disabled] {\n  cursor: not-allowed;\n  background-color: #F4F4F4 !important;\n}\n\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #F9F9F9 !important;\n}\n\n/* input  groups */\n.input-group.input-group-fixed {\n  width: auto !important;\n}\n\n.input-group-addon {\n  border-color: #e5e5e5;\n  background: #e5e5e5;\n  min-width: 39px;\n}\n\n.input-group-addon > i {\n  color: #999;\n}\n\n/* form control sizing */\n.form-control-inline {\n  display: inline-block !important;\n}\n\n.input-xsmall {\n  width: 60px !important;\n}\n\n.input-small {\n  width: 120px !important;\n}\n\n.input-medium {\n  width: 240px !important;\n}\n\n.input-large {\n  width: 320px !important;\n}\n\n.input-xlarge {\n  width: 480px !important;\n}\n\n/***\nInput spinner(in v1.4)\n***/\n\ninput[type=\"text\"].spinner,\ninput[type=\"password\"].spinner,\ninput[type=\"datetime\"].spinner,\ninput[type=\"datetime-local\"].spinner,\ninput[type=\"date\"].spinner,\ninput[type=\"month\"].spinner,\ninput[type=\"time\"].spinner,\ninput[type=\"week\"].spinner,\ninput[type=\"number\"].spinner,\ninput[type=\"email\"].spinner,\ninput[type=\"url\"].spinner,\ninput[type=\"search\"].spinner,\ninput[type=\"tel\"].spinner,\ninput[type=\"color\"].spinner {\n  background-image: url(\"../img/input-spinner.gif\") !important;\n  background-repeat: no-repeat;\n  background-position: right 8px;\n}\n\n@media (max-width: 768px) {\n\n  .input-large {\n    width: 250px !important;\n  }\n\n  .input-xlarge {\n    width: 300px !important;\n  }\n\n} \n\n/***\nError States\n***/\n\n.has-warning .help-inline,\n.has-warning .help-block,\n.has-warning .control-label {\n  color: #c09853;\n}\n\n.has-warning .form-control {\n  border-color: #c09853;\n  -webkit-box-shadow: none;\n          box-shadow: none;\n}\n\n.has-warning .form-control:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: none;\n          box-shadow: none;\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-inline,\n.has-error .help-block,\n.has-error .control-label {\n  color: #b94a48;\n}\n\n.has-error .form-control {\n  border-color: #b94a48;\n  -webkit-box-shadow: none;\n          box-shadow: none;\n}\n\n.has-error .form-control:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: none;\n          box-shadow: none;\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-inline,\n.has-success .help-block,\n.has-success .control-label {\n  color: #468847;\n}\n\n.has-success .form-control {\n  border-color: #468847;\n  -webkit-box-shadow: none;\n          box-shadow: none;\n}\n\n.has-success .form-control:focus {\n  border-color: #356635;\n  -webkit-box-shadow: none;\n          box-shadow: none;\n}\n\n.has-success .input-group-addon {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n/***\nCustom label and badges\n***/\n\n.label, \n.badge {\n  font-weight: 300;  \n  text-shadow: none !important;\n}\n\n.label {  \n  font-size: 12px;  \n  padding: 3px 6px 3px 6px;\n}\n\n.label.label-sm {  \n  font-size: 12px;\n  padding: 1px 4px 1px 4px;\n}\n\nh1 .label,\nh2 .label,\nh3 .label,\nh4 .label,\nh5 .label,\nh6 .label,\nh7 .label {\n  font-size: 75%;\n}\n\n.badge {\n  font-size: 11px !important;\n  font-weight: 300;\n  text-align: center;\n  background-color: #e02222;\n  height: 18px;\n  padding: 3px 6px 3px 6px;\n  -webkit-border-radius: 12px !important;\n     -moz-border-radius: 12px !important;\n          border-radius: 12px !important;\n  text-shadow:none !important;\n  text-align: center;\n  vertical-align: middle;\n}\n\n.badge.badge-roundless {\n   -webkit-border-radius: 0 !important;\n      -moz-border-radius: 0 !important;\n           border-radius: 0 !important;\n}\n\n.badge-default,\n.label-default  {\n  background-color: #999 !important;\n}\n\n.badge-primary,\n.label-primary {\n  background-color: #428bca !important;\n}\n\n.label-success, \n.badge-success {\n  background-color: #3cc051;\n  background-image: none !important;\n}\n\n.label-warning, \n.badge-warning {\n  background-color: #fcb322;\n  background-image: none !important;\n}\n\n.label-danger, \n.badge-danger {\n  background-color: #ed4e2a;\n  background-image: none !important;\n}\n\n.label-info, \n.badge-info {\n  background-color: #57b5e3;\n  background-image: none !important;\n}\n\n/* fix badge position for navs */\n.nav.nav-pills > li > a > .badge {\n  margin-top: -2px;\n}\n\n.nav.nav-stacked > li > a > .badge {\n  margin-top: 1px;\n  margin-bottom: 0px;\n}\n\n/***\nIconic Labels\n***/\n\n.label.label-icon {\n  padding: 4px 1px 4px 5px;\n  margin-right: 2px;\n  text-align: center !important;\n}\n\n.ie9 .label.label-icon, \n.ie10 .label.label-icon {\n  padding: 3px 0px 3px 3px;\n} \n\n.label.label-icon > i {\n  font-size: 12px;\n  text-align: center !important;\n}\n\n\n/***\nProgress Bars\n***/\n\n.progress {  \n  border: 0; \n  background-image: none !important;\n  filter: none !important;\n  -webkit-box-shadow: none !important;\n     -moz-box-shadow: none !important;\n          box-shadow: none !important;   \n\n}\n\n.progress > .progress-bar-success {\n  background-color: #3cc051;\n}\n\n.progress > .progress-bar-danger {\n  background-color: #ed4e2a;\n}\n\n.progress > .progress-bar-info {\n  background-color: #57b5e3;\n}\n\n.progress > .progress-bar-warning {\n  background-color: #fcb322;\n}\n\n\n/***\nPagination\n***/\n.pagination {\n  margin: 10px 0;\n}\n\n.pagination .active > a,\n.pagination .active > a:hover {\n  background: #eee;\n  border-color: #dddddd;\n  color: #333;\n}\n\n\n\n/***\nwells\n***/\n.well {  \n  -webkit-box-shadow: none !important;\n     -moz-box-shadow: none !important;\n          box-shadow: none !important;\n}\n\n/* Bootstrap Tabs */\n\n.dropup.open > .dropdown-toggle,\n.dropdown.open > .dropdown-toggle {\n  border-color: #ddd !important;\n}\n\n.nav-tabs > li > .dropdown-menu:after,\n.nav-pills > li > .dropdown-menu:after,\n.navbar-nav > li > .dropdown-menu:after,\n\n.nav-tabs > li > .dropdown-menu:before,\n.nav-pills > li > .dropdown-menu:before,\n.navbar-nav > li > .dropdown-menu:before {\n  display: none !important;\n}\n\n.nav-tabs > .dropdown.open > .dropdown-toggle, \n.nav-pills > .dropdown.open > .dropdown-toggle {\n  background: #eee !important;\n  color: #0d638f !important;\n}\n\n\n.nav-tabs,\n.nav-pills {\n  margin-bottom: 10px;\n}\n\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n     -moz-border-radius: 4px 0 0 4px;\n          border-radius: 4px 0 0 4px;\n}\n\n.tabs-left > .nav-tabs > li > a:hover,\n.tabs-left > .nav-tabs > li > a:focus {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover,\n.tabs-left > .nav-tabs .active > a:focus {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n     -moz-border-radius: 0 4px 4px 0;\n          border-radius: 0 4px 4px 0;\n}\n\n.tabs-right > .nav-tabs > li > a:hover,\n.tabs-right > .nav-tabs > li > a:focus {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover,\n.tabs-right > .nav-tabs .active > a:focus {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n\n.tabs-below > .nav-tabs,\n.tabs-below > .nav-pills {\n  border-bottom: 0;\n  margin-bottom: 0px;\n  margin-top: 10px;\n}\n\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n  margin-bottom: 0;\n  margin-top: 10px;\n}\n\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n     -moz-border-radius: 0 0 4px 4px;\n          border-radius: 0 0 4px 4px;\n}\n\n.tabs-below > .nav-tabs > li > a:hover,\n.tabs-below > .nav-tabs > li > a:focus {\n  border-top-color: #ddd;\n  border-bottom-color: transparent;\n}\n\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover,\n.tabs-below > .nav-tabs > .active > a:focus {\n  border-color: transparent #ddd #ddd #ddd;\n}\n\n/***\nBootstrap modal \n***/\n\n.modal {\n  z-index: 10050 !important;\n  outline: none !important;\n}\n\n.modal-header {\n  border-bottom: 1px solid #EFEFEF;\n}\n\n.modal-header h3{\n  font-weight: 300;\n}\n\n.modal-small {\n  width: 400px !important;\n}\n\n.modal-wide {\n  width: 60% !important;\n}\n\n.modal-full {\n  width: 100% !important;\n}\n\n/***\nModal header close button fix\n***/\n.modal-header .close {\n  margin-top: 0px !important;\n}\n\n.modal > .loading {\n  position: absolute;\n  top: 50%;\n  left:50%;\n  margin-top: -22px;\n  margin-left: -22px;\n}\n\n.modal-backdrop {\n  border: 0 !important;\n  outline: none !important;\n  z-index: 10049 !important;\n}\n\n.modal-backdrop, \n.modal-backdrop.fade.in {\n  background-color: #333 !important;\n}\n\n/* fix: content shifting to the right on modal open due to scrollbar closed */\n.modal {\n  overflow-y: auto !important;\n}\n\n.modal-open {\n  overflow-y: auto !important;\n}\n\n.modal-open-noscroll {\n  overflow-y: hidden !important; \n}\n\n\n/***\nImage Carousel\n***/\n.carousel.image-carousel .carousel-inner {\n  padding-top: 0;\n  padding-bottom: 0;\n}\n\n.carousel.image-carousel .carousel-control i {\n  position: absolute;\n  top:40%;\n}\n\n.carousel.image-carousel.image-carousel-hoverable .carousel-control i { \n  display: none;\n}\n\n.carousel.image-carousel.image-carousel-hoverable:hover .carousel-control i {\n  display: inline-block;\n}\n\n.carousel.image-carousel .carousel-control.left i {\n  left:10px;\n}\n\n.carousel.image-carousel .carousel-control.right i {\n  right:10px;\n}\n\n.carousel.image-carousel .carousel-indicators {\n  margin-top: 10px;\n  bottom: -7px;\n}\n\n.carousel.image-carousel .carousel-indicators li {\n  background-color: #666;\n}\n\n.carousel.image-carousel .carousel-indicators li.active {\n  background-color: #333;\n}\n\n.carousel.image-carousel .carousel-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 15px 15px 25px 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n\n.carousel.image-carousel .carousel-caption h4,\n.carousel.image-carousel .carousel-caption h3,\n.carousel.image-carousel .carousel-caption h2,\n.carousel.image-carousel .carousel-caption p {\n  text-align: left;\n  line-height: 20px;\n  color: #ffffff;\n}\n\n.carousel.image-carousel .carousel-caption h2,\n.carousel.image-carousel .carousel-caption h3,\n.carousel.image-carousel .carousel-caption h4 {\n  margin: 0 0 5px;\n}\n\n.carousel.image-carousel .carousel-caption h2 a,\n.carousel.image-carousel .carousel-caption h3 a,\n.carousel.image-carousel .carousel-caption h4 a {\n  color: #aaa;\n} \n\n.carousel.image-carousel .carousel-caption p {\n  margin-bottom: 0;\n}\n\n.carousel.image-carousel .item {\n  margin: 0;\n}\n\n/***\nBootstrap Tables\n***/\n\n.table thead > tr > th {\n  border-bottom: 0;\n}\n\n.table tbody tr.active td,\n.table tbody tr.active th {\n  background-color: #e9e9e9 !important;\n}\n\n.table tbody tr.active:hover td,\n.table tbody tr.active:hover th {\n  background-color: #e1e1e1 !important;\n}\n\n.table-striped tbody tr.active:nth-child(odd) td,\n.table-striped tbody tr.active:nth-child(odd) th {\n  background-color: #017ebc;\n}\n\n/***\nBootstrap Panel\n***/\n\n.panel {  \n  -webkit-box-shadow: none !important;\n     -moz-box-shadow: none !important;\n          box-shadow: none !important;\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/css/style-non-responsive.css",
    "content": "\t/****************\n \tBootstrap changes\n \t*****************/\n \t.container,\n\t.navbar-inner .container {\n\t\tmax-width: none !important;\n\t\twidth: 1170px !important;\n\t}\n\n\t/* Always float the navbar header */\n\t.navbar-header {\n\t  float: left;\n\t}\n\n\t/* Undo the collapsing navbar */\n\t.navbar-collapse {\n\t  display: block !important;\n\t  height: auto !important;\n\t  padding-bottom: 0;\n\t  overflow: visible !important;\n\t}\n\n\t/* Always apply the floated nav */\n\t.navbar-nav {\n\t  display: inline-block !important;\n\t  float: left;\n\t  margin: 0;\n\t}\n\t.navbar-nav > li {\n\t  float: left;\n\t}\n\t.navbar-nav > li > a {\n\t  padding: 15px;\n\t}\n\n\t/* Redeclare since we override the float above */\n\t.navbar-nav.navbar-right {\n\t  float: right;\n\t}\n\n\t/* Undo custom dropdowns */\n\t.navbar .open .dropdown-menu {\n\t  position: absolute;\n\t  float: left;\n\t  background-color: #fff;\n\t  border: 1px solid #cccccc;\n\t  border: 1px solid rgba(0, 0, 0, 0.15);\n\t  border-width: 0 1px 1px;\n\t  border-radius: 0 0 4px 4px;\n\t  -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n\t          box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n\t}\n\t.navbar .open .dropdown-menu > li > a {\n\t  color: #333;\n\t}\n\t.navbar .open .dropdown-menu > li > a:hover,\n\t.navbar .open .dropdown-menu > li > a:focus,\n\t.navbar .open .dropdown-menu > .active > a,\n\t.navbar .open .dropdown-menu > .active > a:hover,\n\t.navbar .open .dropdown-menu > .active > a:focus {\n\t  color: #fff !important;\n\t  background-color: #428bca !important;\n\t}\n\t.navbar .open .dropdown-menu > .disabled > a,\n\t.navbar .open .dropdown-menu > .disabled > a:hover,\n\t.navbar .open .dropdown-menu > .disabled > a:focus {\n\t  color: #999 !important;\n\t  background-color: transparent !important;\n\t}\n\n\t/****************\n \tTheme changes\n \t*****************/\n\n\t/***\n \tPage sidebar\n \t***/\n\n \t.page-sidebar {\n\t\tposition: absolute;\n \t\twidth: 225px;\n  \t}\n\n  \t.page-sidebar.navbar-collapse {\n  \t\tmax-height: none !important;\n  \t}\n\n\t.page-sidebar-fixed .page-sidebar {\n\t  \tposition: fixed !important;\n\t \ttop: 41px;\n\t}\n\n\t.page-sidebar-fixed ul.page-sidebar-menu > li.last {\n\t\tmargin-bottom: 15px !important;\n\t}\n\n\t.page-sidebar-fixed.page-sidebar-hover-on .page-sidebar {\n\t\tz-index: 10000;\t\t\n\t\twidth: 35px;\t\t\n\t}\n\n\t.page-sidebar-fixed.page-sidebar-hover-on .page-sidebar .selected {\n\t\tdisplay: none;\n\t}\n\n\t.page-sidebar-fixed.page-sidebar-hover-on .page-content {\n\t\tmargin-left: 35px;\n\t}\n\t.page-sidebar-fixed.page-sidebar-hover-on .footer {\n\t\tmargin-left: 35px;\n\t}\n\n\t.page-sidebar-fixed .page-sidebar-closed .page-sidebar .sidebar-search .submit,\n\t.page-sidebar-fixed .page-sidebar .sidebar-toggler {\n\t\t-webkit-transition: all  0.3s ease;\n\t     -moz-transition: all  0.3s ease;\n\t       -o-transition: all  0.3s ease;\n\t          transition: all  0.3s ease;\n\t}\n\n\t.page-sidebar-hovering {\n\t\toverflow: hidden !important;\n\t}\n\n\t.page-sidebar-hovering .sub-menu,\n\t.page-sidebar-hovering span.title,\n\t.page-sidebar-hovering span.arrow {\t\t  \n\t\tdisplay: none !important;\n\t}\n\n\t.page-sidebar-hovering .submit {\n\t\topacity: 0;\n\t\twidth: 0 !important;\n\t\theight: 0 !important;\n\t}\n\n  \t/***\n  \tPage content\n  \t***/\n  \t.page-content { \n  \t\tmargin-left: 225px; \n\t\tmargin-top: 0px;\n\t\tmin-height: 760px; \n\t\tpadding: 25px 20px 20px 20px;\n\t}\n\n\t.page-sidebar-fixed .page-content {\n\t\tmin-height: 600px; \n\t}\n\n\t.page-content.no-min-height {\n\t\tmin-height: auto;\n\t}\n\n\t/***\n\tFooter\n\t***/\n\n\t/* fixed sidebar */\n\t.page-footer-fixed .footer {\n\t  position: fixed;\n\t  left: 0;\n\t  right: 0;\n\t  z-index: 10000;\n\t  bottom: 0;\n\t  padding1: 8px 0 5px 0;\n\t}\n\n\t.page-footer-fixed .page-container {\n\t  margin-bottom: 32px;\n\t}\n\n\t.page-footer-fixed.page-sidebar-fixed .footer {\n\t  margin-left: 0 !important;\n\t}\n\t/* end: fixed footer */\n\n\t.page-boxed .footer {\n  \t\tpadding: 8px 0 5px 0; \n\t}\n\n\t.page-sidebar-fixed .footer {\n\t  margin-left: 225px;\n\t  background-color: #fff;\n\t  padding: 8px 20px 5px 20px;\n\t}\n\n\t.page-sidebar-fixed .footer .footer-inner {\n\t  color: #333;\n\t}\n\n\t.page-sidebar-fixed.page-sidebar-closed .footer {\n\t  margin-left: 35px;\n\t}\n\n\t.page-sidebar-fixed .footer .footer-tools .go-top { \n\t  background-color: #666;\n\t}\n\n\t.page-sidebar-fixed .footer .footer-tools .go-top i {\n\t  color: #ddd;\n\t}\n\n\t/* boxed layout */\n\t.page-boxed\t.header .navbar-brand {\n  \t\tmargin-left: 0px !important;\n  \t\twidth: 226px;\n\t}\n\n\t.page-boxed .header .navbar-brand img {\n\t\tmargin-left: 10px;\n\t}\n\n\t.page-boxed .header .navbar-nav {\n\t  margin-right: 0px;\n\t}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/css/style-responsive.css",
    "content": "/***\nResponsive Theme. \nBased on http://getbootstrap.com/css/#responsive-utilities-classes\n***/\n\n/***\nForm Medium Devices Up To Large Devices\n***/\n\n@media (min-width: 992px) and (max-width: 1200px) {  \n\n\t.page-boxed .header .dropdown .username {\n\t\tdisplay: none;\n\t}\t\n\n}\n\n/***\nFrom Medium Devices Up To Larger Devices\n***/\n\n@media (min-width: 992px) { \n\n \t/***\n \tPage sidebar\n \t***/\n \t.page-sidebar {\n\t\tposition: absolute;\n \t\twidth: 225px;\n  \t}\n\n  \t.page-sidebar.navbar-collapse {\n  \t\tmax-height: none !important;\n  \t}\n\n\t.page-sidebar-fixed .page-sidebar {\n\t  \tposition: fixed !important;\n\t \ttop: 41px;\n\t}\n\n\t.page-sidebar-fixed ul.page-sidebar-menu > li.last {\n\t\tmargin-bottom: 15px !important;\n\t}\n\n\t.page-sidebar-fixed.page-sidebar-hover-on .page-sidebar {\n\t\tz-index: 10000;\t\t\n\t\twidth: 35px;\t\t\n\t}\n\n\t.page-sidebar-fixed.page-sidebar-hover-on .page-sidebar .selected {\n\t\tdisplay: none;\n\t}\n\n\t.page-sidebar-fixed.page-sidebar-hover-on .page-content {\n\t\tmargin-left: 35px;\n\t}\n\t.page-sidebar-fixed.page-sidebar-hover-on .footer {\n\t\tmargin-left: 35px;\n\t}\n\n\t.page-sidebar-fixed .page-sidebar-closed .page-sidebar .sidebar-search .submit,\n\t.page-sidebar-fixed .page-sidebar .sidebar-toggler {\n\t\t-webkit-transition: all  0.3s ease;\n\t     -moz-transition: all  0.3s ease;\n\t       -o-transition: all  0.3s ease;\n\t          transition: all  0.3s ease;\n\t}\n\n\t.page-sidebar-hovering {\n\t\toverflow: hidden !important;\n\t}\n\n\t.page-sidebar-hovering .sub-menu,\n\t.page-sidebar-hovering span.title,\n\t.page-sidebar-hovering span.arrow {\t\t  \n\t\tdisplay: none !important;\n\t}\n\n\t.page-sidebar-hovering .submit {\n\t\topacity: 0;\n\t\twidth: 0 !important;\n\t\theight: 0 !important;\n\t}\n\n  \t/***\n  \tPage content\n  \t***/\n  \t.page-content { \n  \t\tmargin-left: 225px; \n\t\tmargin-top: 0px;\n\t\tmin-height: 760px; \n\t\tpadding: 25px 20px 20px 20px;\n\t}\n\n\t.page-sidebar-fixed .page-content {\n\t\tmin-height: 600px; \n\t}\n\n\t.page-content.no-min-height {\n\t\tmin-height: auto;\n\t}\n\n\t/***\n\tFooter\n\t***/\n\n\t/* fixed sidebar */\n\t.page-footer-fixed .footer {\n\t  position: fixed;\n\t  left: 0;\n\t  right: 0;\n\t  z-index: 10000;\n\t  bottom: 0;\n\t}\n\n\t.page-footer-fixed .page-container {\n\t  margin-bottom: 32px;\n\t}\n\n\t.page-footer-fixed.page-sidebar-fixed .footer {\n\t  margin-left: 0 !important;\n\t}\n\t/* end: fixed footer */\n\n\t.page-boxed .footer {\n  \t\tpadding: 8px 0 5px 0; \n\t}\n\n\t.page-sidebar-fixed .footer {\n\t  margin-left: 225px;\n\t  background-color: #fff;\n\t  padding: 8px 20px 5px 20px;\n\t}\n\n\t.page-sidebar-fixed .footer .footer-inner {\n\t  color: #333;\n\t}\n\n\t.page-sidebar-fixed.page-sidebar-closed .footer {\n\t  margin-left: 35px;\n\t}\n\n\t.page-sidebar-fixed .footer .footer-tools .go-top { \n\t  background-color: #666;\n\t}\n\n\t.page-sidebar-fixed .footer .footer-tools .go-top i {\n\t  color: #ddd;\n\t}\n\n\t/* boxed layout */\n\t.page-boxed\t.header .navbar-brand {\n  \t\tmargin-left: 0px !important;\n  \t\twidth: 226px;\n\t}\n\n\t.page-boxed .header .navbar-brand img {\n\t\tmargin-left: 10px;\n\t}\n\n\t.page-boxed .header .navbar-nav {\n\t  margin-right: 0px;\n\t}\n\n}\n\n/***\nUp To Medium Devices\n***/\n\n@media (max-width:991px) { \n\t\n\t/***\n \tPage header\n \t***/\n \t.header {\n \t\tpadding: 0 20px 0 20px;\n \t\tposition: relative;\n \t\tclear: both;\n \t}\n\n \t.header .navbar-toggle {\n \t\tdisplay: inline-block;\n \t}\n\n \t.page-sidebar.navbar-collapse {\n  \t\tmax-height: 340px;\n  \t}\n\n \t.page-sidebar.navbar-collapse.collapse {\n\t    display: none !important;\n\t}\n\n\t.page-sidebar.navbar-collapse.in {\t \t\n\t \toverflow: hidden !important;\n\t \toverflow-y: auto !important;\n\t }\n\n\t.header .nav li.dropdown i {\n\t\tdisplay: inline-block;\n\t\tposition: relative;\n\t\ttop:1px;\n\t\tright:0px;\n\t}\n\n\t.header .navbar-nav {\n\t\tdisplay: block;\n\t\tmargin-bottom: 0px !important;\n\t}\n\n\t.header .navbar-nav .open .dropdown-menu  {\n\t\tposition: absolute;\n\t}\n\n\t.header .navbar-nav {\n\t\tdisplay: inline-block;\n    \tfloat: right;\n    \tmargin: 0;\n  \t}\n  \n \t.header .navbar-nav > li {\n    \tfloat: left;\n  \t}\n\n\t.header .navbar-brand {\n  \t\tmargin-left: 0px !important;\n  \t\tpadding-left: 0px !important; \n\t}\n\n\t.header .navbar-brand img {\n\t\tmargin-left: 4px !important;\n\t}\n\n\t/***\n\tPage container\n\t***/\n\t.page-container {\n\t\tmargin: 0 !important;\n\t\tpadding: 0 !important;\n\t}\n\n\t/***\n  \tPage content\n  \t***/\n  \t.page-content {\n  \t\tmargin: 0px !important;\n  \t\tpadding: 20px 20px 20px 20px !important;  \t\t\n\t\tmin-height: 280px; \n  \t}\n\n\t/***\n\tPage sidebar\n\t***/\n\t.page-sidebar {\n\t\tborder-top: 0 !important;\n\t\tmargin: 20px;\n\t}\n\n\t.page-sidebar.in {\n\t\tborder-top: 0 !important;\n\t\tmargin: 20px;\n\t\tposition: relative;\n\t\tz-index: 5;\n\t}\n\n\t.header .sidebar-toggler,\n\t.page-sidebar .sidebar-toggler {\n\t\tdisplay: none;\n\t}\n\n\t.page-sidebar ul {\n\t\tmargin-top:0px;\n\t\twidth:100%;\n\t}\n\n\t.page-sidebar .selected {\n\t\tdisplay: none !important;\n\t}\n\n\t.page-sidebar .sidebar-search .input-box {\n\t  width: 220px;\n\t}\n\n\t/***\n\tStyler panel\n\t***/\n\t.styler-panel {\n\t\ttop:55px;\n\t\tright:20px;\n\t}\n\n\t/***\n\tBoxed Layout\n\t***/\n \t.page-boxed .header > .container,\n \t.page-boxed .footer > .container,\n \t.page-boxed > .container {\n \t\tmax-width: none !important;\n \t\tmargin: 0 !important;\n \t\tpadding: 0 !important;\n \t}\n\n}\n\n/***\nFrom Small Devices Up To Medium Devices\n***/\n \n@media (min-width: 768px) and (max-width: 991px) { \n\n\t/***\n\tBody\n\t***/\n\tbody {\n\t \tpadding-top: 0px;\n\t}\n\n\t/***\n\tPage sidebar\n\t***/\n\t.page-sidebar .btn-navbar.collapsed .arrow { \n\t\tdisplay: none;\n\t}\t\n\n\t.page-sidebar .btn-navbar .arrow {\n\t  position: absolute;\n\t  right: 25px;\n\t  width: 0; \n\t  height: 0;\n\t  top:50px;\n\t  border-bottom: 15px solid #5f646b;\n\t  border-left: 15px solid transparent; \n\t  border-right: 15px solid transparent; \n\t}\n\n} \n \n/***\nExtra Small Devices Only\n***/\n\n@media (max-width: 767px) { \n\t\n\t/***\n\tPage header\n\t***/\n\t\n\t.header {\n \t\tpadding: 0 10px 0 10px;\n \t}\n\n\t.header .top-nav .nav{  \n\t \tmargin-top: 0px;\n\t \tmargin-right: 5px;\n\t}\n\n\t.header .nav > li > .dropdown-menu.notification:after, \n\t.header .nav > li > .dropdown-menu.notification:before {\n\t\tmargin-right: 180px;\n\t}\n\n\t.header .nav > li > .dropdown-menu.notification {\n  \t\tmargin-right: -180px;\n\t}\n\n\t.header .nav > li > .dropdown-menu.inbox:after, \n\t.header .nav > li > .dropdown-menu.inbox:before {\n\t\tmargin-right: 140px;\n\t}\n\n\t.header .nav > li > .dropdown-menu.inbox {\n  \t\tmargin-right: -140px;\n\t}\n\n\t.header .nav > li > .dropdown-menu.tasks:after, \n\t.header .nav > li > .dropdown-menu.tasks:before {\n\t\tmargin-right: 90px;\n\t}\n\n\t.header .nav > li > .dropdown-menu.tasks {\n  \t\tmargin-right: -90px;\n\t}\n\n  \t/* Header logo */\n\t.header .navbar-brand {\n  \t\tmargin-left: 0px !important;\n  \t\twidth: 110px;\n\t}\n\t\n\t/***\n\tPage content\n\t***/\n\t.page-content {\n\t\tpadding: 20px 10px 10px 10px !important;\n\t\toverflow: hidden;\n\t}\n\n\t/***\n\tPage title\n\t***/\n\t.page-title {\n\t\tmargin-bottom: 20px;\n\t\tfont-size: 18px;\n\t}\n\n\t.page-title small {\n\t\tfont-size: 13px;\n\t\tpadding-top: 3px;\n\t}\n\t\n\t/***\n\tStyler pagel\n\t***/\n\t.styler-panel {\n\t\ttop:58px;\n\t\tright:12px;\n\t}\t\n\n\t/***\n\tPage breadcrumb\n\t***/\n\t.breadcrumb {\n\t\tpadding-left: 10px;\n  \t\tpadding-right: 10px;\n\t}\n\n\t/***\n\tPortlet form action\n\t***/\n\t.portlet-body.form .form-actions{\n\t  padding-left: 15px;\t\n\t} \n\n\n\t/***\n\tForm input validation states\n\t***/\n\t.input-icon .input-error, \n\t.input-icon .input-warning, \n\t.input-icon .input-success { \n\t\ttop:-27px;\n\t\tfloat: right;\n\t\tright:10px !important;\n\t}\t\n\n\t/***\n\tAdvance tables\n\t***/\n\t.table-advance tr td.highlight:first-child a {\n\t\tmargin-left: 8px;\n\t}\n\n\t/***\n\tFooter\t\n\t***/\t\n\t.footer {\n\t\tpadding-left: 10px;\n\t\tpadding-right: 10px;\t\t\n\t}\t\n\t\n\t.footer .go-top {  \n\t\tfloat: right;\n\t\tdisplay: block;\n\t\tmargin-right: 0px;\n\t}\n\n\t/***\n\tVertical inline menu\n\t***/\n\t.ver-inline-menu li.active:after {\n\t\tdisplay: none;\n\t}\n\n\t/***\n\tForm controls\n\t***/\n\t.form-horizontal .form-actions {\n  \t\tpadding-left: 180px; \t\n  \t}\n\n  \t.portlet .form-horizontal .form-actions {\n  \t\tpadding-left: 190px; \t\n  \t}\n}\n\n/***\nThe Most Extra Small Devices Landscape Mode Only\n***/\n\n@media (max-width: 480px) {\n\n\t/***\n\tHeader navbar\n\t***/\n\n\t.header .navbar-nav {\n\t\tdisplay: block !important;\n\t\tmargin-top: 0px !important;\n\t}\n\n\t.header .navbar-nav > li.dropdown .dropdown-toggle {\n  \t\tmargin-top:-1px;\n  \t\tpadding-left: 8px;\n\t  \tpadding-right: 8px;\n\t}\n\n\t.header .navbar-nav > li.dropdown.user .dropdown-toggle,\n\t.header .navbar-nav > li.dropdown.language .dropdown-toggle {\n\t\tpadding-right: 6px;\n\t\tpadding-left: 6px;\n\t}\n\n  \t.header .navbar-nav li.dropdown .dropdown-toggle .badge {\n  \t\ttop: 8px;\n  \t}\n\n  \t/***\n\tPage sidebar\n\t***/\n\t.page-sidebar,\n\t.page-sidebar.in {\n\t\tmargin: 0 10px 10px 10px;\n\t}\n\n\t/***\n\tPage title\n\t***/\n\t.page-title small {\n\t\tdisplay: block;\n\t\tclear: both;\n\t}\n\n\t/***\n\tForms\n\t***/\n  \t.portlet .form-horizontal .form-actions {\n  \t\tpadding-left: 10px; \t\n  \t}\n\n\t/***\n\tDashboard date range panel\n\t***/\n\t.page-content .breadcrumb .dashboard-date-range  {\n\t\tpadding-bottom: 8px;\n\t} \n\n\t.page-content .breadcrumb .dashboard-date-range span {\n\t\tdisplay: none;\n\t}\t\n\n  \t.page-content .breadcrumb > .btn-group span {\n  \t\tdisplay: none;\n  \t}\n\n  \t.page-content .breadcrumb > .btn-group > .btn {\n  \t\tpadding-left: 7px;\n  \t\tpadding-right: 7px;\n  \t}\n\n\t/***\n\tHidden phone\n\t***/\n\t.hidden-480 {\n\t\tdisplay: none !important;\n\t}\n}\n\n/***\nThe Most Extra Small Devices Portrait Mode Only\n***/\n\n@media (max-width: 320px) {\n\n\t/***\n\tHidden phone\n\t***/\n\t.hidden-320 {\n\t\tdisplay: none;\n\t}\n\n\t.header .navbar-brand {\n\t\twidth: 100px;\n\t}\t\n}\t"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/css/style.css",
    "content": "/*   \nTemplate Name: Metronic - Responsive Admin Dashboard Template build with Twitter Bootstrap 3.0.2\nVersion: 1.5.4\nAuthor: KeenThemes\nWebsite: http://www.keenthemes.com/\nPurchase: http://themeforest.net/item/metronic-responsive-admin-dashboard-template/4021469?ref=keentheme\n*/\n\n/*********************\n GENERAL UI COLORS \n*********************/\n\n/***\nColors\nblue:  #4b8df8\nlight blue: #bfd5fa\nred: #e02222\nyellow: #ffb848\ngreen: #35aa47\npurple: #852b99\ndark: #555555;\nlight grey: #fafafa;\n***/\n\n/*********************\n GENERAL RESET & SETUP \n*********************/\n\n/***\nImport fonts\n***/\n\n/*Load Open Sans Font from google fonts*/\n/*\n@import url(//fonts.googleapis.com/css?family=Open+Sans:400,300,600,700);\n*/\n\n/* load Open Sans Font from local */\n@import url(../fonts/font.css);\n\n/***\nReset and overrides  \n***/\n/* general body settings */\nbody { \n  color: #000; \n  font-family: 'Open Sans', sans-serif;\n  padding: 0px !important;\n  margin: 0px !important;\n  font-size:13px; \n  direction: ltr;\n}\n\n/*\nInternet Explorer 10 doesn't differentiate device width from viewport width, and thus doesn't \nproperly apply the media queries in Bootstrap's CSS. To address this, \nyou can optionally include the following CSS and JavaScript to work around this problem until Microsoft issues a fix.\n*/\n@-webkit-viewport { \n  width: device-width; \n}\n\n@-moz-viewport { \n  width: device-width; \n}\n\n@-ms-viewport { \n  width: device-width; \n}\n\n@-o-viewport { \n  width: device-width; \n}\n\n@viewport { \n  width: device-width; \n}\n\n/* Internet Explorer 10 doesn't differentiate device width from viewport width, \nand thus doesn't properly apply the media queries in Bootstrap's CSS. To address this, following CSS code applied */\n@-ms-viewport { \n  width: auto !important; \n}\n\n/***\nGeneral typography \n***/\nh1 small,\nh2 small,\nh3 small, \nh4 small, \nh5 small,\nh6 small {\n  color: #444;\n}\n\nh1, \nh2, \nh3, \nh4, \nh5, \nh6 {\n  font-family: 'Open Sans', sans-serif;\n  font-weight: 300 !important;\n}\n\nh1.block, \nh2.block, \nh3.block, \nh4.block, \nh5.block, \nh6.block {\n  padding-top: 10px;\n  padding-bottom: 10px;\n}\n\na {\n  text-shadow: none !important;\n  color: #0d638f;\n}\n\n/***\nFix link outlines after click\n***/\na,a:focus, a:hover, a:active {\n  outline: 0;\n}\n\n/***\nGeneral backgrounds. Can be applied to any block or panel\n***/\n\n.bg-blue {\n  background-image: none !important;\n  background-color: #4b8df8 !important;\n  border-color:#4b8df8 !important;\n  color: #fff !important;\n}\n\n.bg-red {\n  background-image: none !important;\n  background-color: #e02222 !important;\n  border-color: #e02222 !important;\n  color: #fff !important;\n}\n\n.bg-yellow {\n  background-image: none !important;\n  background-color: #ffb848 !important;\n  border-color: #ffb848 !important;\n  color: #fff !important;\n}\n\n.bg-green {\n  background-image: none !important;\n  background-color: #35aa47 !important;\n  border-color: #35aa47 !important;\n  color: #fff !important;\n}\n\n.bg-purple {\n  background-image: none !important;\n  background-color: #852b99 !important;\n  border-color: #852b99 !important;\n  color: #fff !important;\n}\n\n.bg-dark {\n  background-image: none !important;\n  background-color: #555555 !important;\n  border-color: #555555 !important;\n  color: #fff !important;\n}\n\n.be-grey {\n  background-image: none !important;\n  background-color: #fafafa !important;\n  border-color: #fafafa !important;\n}\n\n/***\nFont Awesome Icons\n***/\n[class^=\"fa-\"],\n[class*=\" fa-\"] {\n  display: inline-block;\n  margin-top: 1px;\n  font-size: 14px;\n  *margin-right: .3em;\n  line-height: 14px;\n}\n\n/***\nMake font awesome icons fixed width(latest version issue)\n***/\nli [class^=\"fa-\"],\nli [class*=\" fa-\"] {\n  display: inline-block;\n  width: 1.25em;\n  text-align: center;\n}\nli [class^=\"fa-\"].icon-large,\nli [class*=\" fa-\"].icon-large {\n  /* increased font size for icon-large */\n  width: 1.5625em;\n}\n\n/***\nClose icon used for modal dialog and other UI element close buttons\n***/\n.close {\n  display: inline-block;\n  margin-top: 0px;\n  margin-right: 0px;\n  width: 9px;\n  height: 9px;\n  background-repeat: no-repeat !important;\n  text-indent: -10000px;\n  outline: none;\n  background-image: url(\"../img/remove-icon-small.png\") !important;\n}\n\n/***\nGeneral HR\n***/\n\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #E0DFDF;\n  border-bottom: 1px solid #FEFEFE;\n}\n\n/***\nTools\n***/\n.display-none,\n.display-hide {\n  display: none;\n}\n\n.no-space {\n  margin: 0px !important;\n  padding: 0px !important;\n}\n\n.margin-bottom-10 {\n  margin-bottom: 10px !important;\n}\n\n.margin-top-10 {\n  margin-top: 10px !important;\n}\n\n.margin-bottom-15 {\n  margin-bottom: 15px !important;\n}\n\n.margin-bottom-20 {\n  margin-bottom: 20px !important;\n}\n\n.margin-top-20 {\n  margin-top: 20px !important;\n}\n\n.margin-bottom-25 {\n  margin-bottom: 25px !important;\n}\n\n.margin-right-10 {\n  margin-right: 10px !important;\n}\n\n.bold {\n  font-weight:600 !important;\n}\n\n.fix-margin {\n  margin-left: 0px !important\n}\n\n.border {\n  border: 1px solid red;\n}\n\n.inline {\n  display: inline;\n}\n\n/***\nie8 & ie9 modes\n***/\n.visible-ie8 {\n  display: none;\n}\n\n.ie8 .visible-ie8 {\n  display: inherit !important;\n}\n\n.visible-ie9 {\n  display: none;\n}\n\n.ie9 .visible-ie9 {\n  display: inherit !important;\n}\n\n.hidden-ie8 {\n  display: inherit;\n}\n\n.ie8 .hidden-ie8 {\n  display: none !important;\n}\n\n.hidden-ie9 {\n  display: inherit;\n}\n\n.ie9 .hidden-ie9 {\n  display: none !important;\n}\n\n/********************\n GENERAL LAYOUT \n*********************/\n\n/***\nHeader and header elements.\n***/\n\n.header {\n  width: 100%; \n  padding: 0 20px 0 20px;\n  margin: 0;\n  border: 0px;\n  padding: 0px; \n  box-shadow: none;\n  height: 42px; \n  min-height: 42px;\n}\n\n.header.navbar-fixed-top {\n  z-index: 9995 !important;\n}\n\n.header .navbar-brand {\n  display: inline-block;\n  margin-top: -1px;\n  margin-right: 0;\n  padding-left: 0;\n  padding-right: 0;\n  width: 225px;\n}\n\n.header .navbar-brand img {\n  margin-left: 20px;\n}\n\n.header .navbar-brand.text-logo {\n  padding-left: 20px;\n  padding-top: 12px;\n}\n\n.header .navbar-toggle {\n  margin: 8px 6px 4px 6px;\n  padding: 0; \n  padding-top:2px;\n  padding-bottom: 6px; \n  background-image: none;\n  filter:none;\n  box-shadow: none;\n  color: #fff;\n  border: 0;\n}\n\n.header .navbar-toggle:hover {\n  text-decoration: none;\n  background: none;\n}\n\n.header .navbar-nav {\n  margin-right: 20px;\n  display: block; \n}\n\n\n.header .navbar-nav > li {\n  margin: 0px;\n  padding: 0px;\n}\n\n.header .navbar-nav > li.dropdown, \n.header .navbar-nav > li.dropdown > a {\n  padding-left: 4px; \n  padding-right: 4px;\n}\n\n.header .navbar-nav > li.dropdown > a:last-child {\n  padding-right: 0;\n}\n\n.header .navbar-nav > li.dropdown:last-child {\n   padding-right: 2px;\n}\n\n.header .navbar-nav > li.dropdown .dropdown-toggle {\n  margin: 0px;\n  padding: 15px 10px 7px 10px;\n}\n\n.header .navbar-nav > li.dropdown .dropdown-toggle > i {\n  font-size: 18px;\n}\n\n.header .navbar-nav > li.dropdown .dropdown-menu > li > a > i {\n  font-size: 14px;\n}\n\n.header .navbar-nav > li.dropdown.user .dropdown-toggle {\n  padding: 7px 4px 6px 9px;\n}\n\n.header .navbar-nav > li.dropdown.user .dropdown-toggle:hover {\n  text-decoration: none;\n}\n\n.header .navbar-nav > li.dropdown.user .dropdown-toggle .username {\n  color: #ddd;\n}\n\n.header .navbar-nav li.dropdown.user .dropdown-toggle i {\n  display: inline-block;\n  margin-top: 5px;\n  margin: 0;\n  font-size: 16px;\n}\n\n.header .navbar-nav > li.dropdown.user .dropdown-menu i {\n  width: 15px;\n  display: inline-block;\n}\n\n.header .navbar-nav > li.dropdown .dropdown-toggle .badge {\n  position: absolute;\n  top: 8px;\n  right: 20px;\n}\n\n/* language bar */\n\n.header .navbar-nav > li.dropdown.language {\n  padding-left: 0;\n  padding-right: 0;\n  margin: 0;\n}\n\n.header .navbar-nav > li.dropdown.language > a {\n  color: #ddd;\n  font-size: 13px;\n  padding: 10px 1px 12px 5px;\n}\n\n.header .navbar-nav > li.dropdown.language > a > img {\n  margin-bottom: 2px;\n}\n\n.header .navbar-nav > li.dropdown.language > a > i {\n  font-size: 16px;\n}\n\n.header .navbar-nav > li.dropdown.language > .dropdown-menu > li > a > img {\n  margin-bottom: 2px;\n}\n\n.header .navbar-nav .dropdown-menu {\n  margin-top: 3px;\n}\n\n/***\nPage container\n***/\n.page-container {\n  margin: 0px;\n  padding: 0px;\n}\n\n.page-header-fixed .page-container {\n  margin-top: 42px;  \n}\n\n/***\nPage sidebar\n***/\n\n/* ie8 fixes */\n.ie8 .page-sidebar {\n  position: absolute;\n  width: 225px;\n}\n\n.page-sidebar.navbar-collapse {\n  padding: 0;\n}\n\n.page-sidebar-menu {\n  list-style: none;\n  margin: 0;\n  padding: 0;\n  margin: 0;\n  padding: 0; \n}\n\n.page-sidebar-menu > li {\n  display: block;\n  margin: 0;\n  padding: 0; \n  border: 0px;\n}\n\n.page-sidebar-menu > li.start > a {\n   border-top-color: transparent !important;\n}\n\n.page-sidebar-menu > li:last-child > a,\n.page-sidebar-menu > li.last > a {\n   border-bottom-color: transparent !important;\n}\n\n.page-sidebar-menu > li > a {\n  display: block;\n  position: relative;\n  margin: 0;\n  border: 0px;\n  padding: 10px 15px;\n  text-decoration: none;\n  font-size: 14px;\n  font-weight: 300;\n}\n\n.page-sidebar-fixed .page-sidebar-menu > li > a {\n  -webkit-transition: all 0.2s ease;\n     -moz-transition: all 0.2s ease;\n       -o-transition: all 0.2s ease;\n          transition: all 0.2s ease;\n}\n\n.page-sidebar-menu > li > a i {\n  font-size: 16px;\n  margin-right: 5px;\n  text-shadow:none; \n}\n\n.page-sidebar-menu > li.break {\n  margin-bottom: 20px;\n}\n\n.page-sidebar-menu > li.active > a {\n  border: none; \n  text-shadow:none;\n}  \n\n.page-sidebar-menu > li.active > a .selected {\n  display: block;\n  width: 8px;\n  height: 25px;\n  background-image: url(\"../img/sidebar-menu-arrow.png\");\n  float: right;\n  position: absolute;\n  right:0px;\n  top:8px;\n}\n\n.page-sidebar ul > li > a > .arrow:before {  \n   float: right;\n   margin-top: 0px;\n   margin-right: 5px;\n   display: inline;\n   font-size: 16px;\n   font-family: FontAwesome;\n   height: auto;\n   content: \"\\f104\";\n   font-weight: 300;\n   text-shadow:none;\n}\n\n.page-sidebar-menu > li > a > .arrow.open:before {   \n   float: right;\n   margin-top: 0px;\n   margin-right: 3px;\n   display: inline;\n   font-family: FontAwesome;\n   height: auto;\n   font-size: 16px;\n   content: \"\\f107\";\n   font-weight: 300;\n   text-shadow:none;\n}\n\n/* bagin: sidebar menu badges */\n.page-sidebar-menu li > a > .badge {\n   float: right;\n   margin-top: 1px;\n   margin-right: 13px;\n}\n\n/* end: sidebar menu badges */\n\n.page-sidebar-menu .sub-menu {\n  padding: 0;\n}\n\n.page-sidebar-menu > li > ul.sub-menu {\n  display: none;\n  list-style: none;\n  clear: both;\n  margin: 8px 0px 8px 0px;\n}\n\n.page-sidebar-menu > li.active > ul.sub-menu {\n  display: block;\n}\n\n.page-sidebar-menu > li > ul.sub-menu > li {\n  background: none;\n  margin: 0px;\n  padding: 0px;\n  margin-top: 1px !important;\n}\n\n.page-sidebar-menu > li > ul.sub-menu > li > a {\n  display: block;\n  margin: 0px 0px 0px 0px;\n  padding: 5px 0px;\n  padding-left: 44px !important;\n  text-decoration: none;\n  font-size: 14px;\n  font-weight: 300;\n  background: none;\n}\n\n/* 3rd level sub menu */\n.page-sidebar-menu > li > ul.sub-menu  > li ul.sub-menu {\n  display: none;\n  list-style: none;\n  clear: both;\n  margin: 0px 0px 0px 0px;\n}\n\n.page-sidebar-menu > li > ul.sub-menu  li > a > .arrow:before   {  \n   float: right;\n   margin-top: 1px;\n   margin-right: 20px;\n   display: inline;\n   font-size: 16px;\n   font-family: FontAwesome;\n   height: auto;\n   content: \"\\f104\";\n   font-weight: 300;\n   text-shadow:none;\n}\n\n.page-sidebar-menu > li > ul.sub-menu  li > a > .arrow.open:before {   \n   float: right;\n   margin-top: 1px;\n   margin-right: 18px;\n   display: inline;\n   font-family: FontAwesome;\n   height: auto;\n   font-size: 16px;\n   content: \"\\f107\";\n   font-weight: 300;\n   text-shadow:none;\n}\n\n.page-sidebar-menu > li.active > ul.sub-menu > li.active ul.sub-menu {\n  display: block;\n}\n\n.page-sidebar-menu > li > ul.sub-menu > li  ul.sub-menu li {\n  background: none;\n  margin: 0px;\n  padding: 0px;\n  margin-top: 1px !important;\n}\n\n.page-sidebar-menu > li > ul.sub-menu  li > ul.sub-menu > li > a {\n  display: block;\n  margin: 0px 0px 0px 0px;\n  padding: 5px 0px;\n  text-decoration: none;\n  font-size: 14px;\n  font-weight: 300;\n  background: none;\n}\n\n.page-sidebar-menu > li > ul.sub-menu > li > ul.sub-menu > li > a {  \n  padding-left: 60px;\n}\n\n.page-sidebar-menu > li > ul.sub-menu > li > ul.sub-menu > li > ul.sub-menu > li > a {  \n  padding-left: 80px;\n}\n\n.page-sidebar-menu > li.active > ul.sub-menu > li.active ul.sub-menu > li.active ul.sub-menu {\n  display: block;\n}\n\n\n.page-sidebar-menu > li > ul.sub-menu  li > ul.sub-menu > li > a > i {\n  font-size: 13px;\n}\n\n/* sidebar search */\n.page-sidebar .sidebar-search {\n  padding:0;\n  margin: 0;\n}\n\n.page-sidebar .sidebar-search .form-container {\n  margin: 15px 20px 15px 20px;\n  height: 35px;\n  padding-top: 7px;\n}\n\n.page-sidebar .sidebar-search .form-container .submit {  \n  display: block;\n  float: right;\n  margin-top: 3px;\n  width: 13px;\n  height: 15px;\n  background-repeat: no-repeat;\n  box-shadow: none;\n  border: 0px; \n  padding: 0px;\n  outline: none !important;\n}\n \n.page-sidebar .sidebar-search .form-container input[type=\"text\"] {\n  margin: 0px;\n  width: 165px;\n  border: 0px;\n  padding: 0 !important;\n  font-size: 14px !important;\n  box-shadow: none !important;\n  font-size: 14px;\n  font-weight: normal;\n}\n\n.page-sidebar .sidebar-search .form-container input[type=\"text\"]:focus {\n  outline: none !important;\n}\n\n/***\nSidebar toggler(show/hide)\n***/\n.sidebar-toggler {\n  cursor: pointer; \n  opacity: 0.5;\n  filter: alpha(opacity=50);\n  width: 29px;\n  height: 29px;\n  background-repeat: no-repeat;\n}\n\n.sidebar-toggler:hover { \n  filter: alpha(opacity=100);\n  opacity: 1;\n}\n\n.page-sidebar .sidebar-toggler {\n  margin-top: 15px;\n  margin-left: 175px;\n}\n\n.header .sidebar-toggler {\n  display: inline-block;\n  margin-top: 6px;\n  margin-left: -42px;\n}\n\n.page-sidebar-closed .page-sidebar .sidebar-toggler {  \n  margin-left: 3px;\n}\n\n.page-sidebar-closed .page-sidebar .sidebar-search .form-container {  \n  width: 29px;\n  margin-left: 3px; \n}\n\n.page-sidebar-closed .page-sidebar .sidebar-search .form-container .input-box {  \n  border-bottom: 0 !important;\n}\n\n.page-sidebar-closed .page-sidebar .sidebar-search .form-container input[type=\"text\"] {\n  display: none;\n}\n\n.page-sidebar-closed .page-sidebar .sidebar-search .form-container .submit { \n  margin-top: 5px !important;\n  margin-left: 7px !important;\n  margin-right: 7px !important;\n  display: block !important;\n}\n\n.page-sidebar-closed .page-sidebar .sidebar-search.open .form-container {\n  width: 255px;\n  position: relative;\n  z-index: 1;\n  padding-top: 0px;\n}\n\n.page-sidebar-closed .page-sidebar .sidebar-search.open .form-container input[type=\"text\"] {  \n  margin-top: 7px;\n  margin-left: 8px;\n  padding-left: 10px;\n  padding-bottom: 2px;\n  width: 185px;\n  display: inline-block !important;\n}\n\n.page-sidebar-closed .page-sidebar .sidebar-search.open .form-container .submit {\n  display: inline-block;\n  width: 13px;\n  height: 13px;\n  margin: 11px 8px 9px 6px !important;\n}\n\n.page-sidebar-closed .page-sidebar .sidebar-search.open .form-container .remove {\n  background-repeat: no-repeat;\n  width: 11px;\n  height: 11px;\n  margin: 12px 8px 9px 8px !important;\n  display: inline-block !important;\n  float: left !important;\n}\n\n.page-sidebar-closed .page-sidebar-menu > li > a .selected {\n  right: -3px !important;\n}\n\n.page-sidebar-closed .page-sidebar-menu > li > a > .title,\n.page-sidebar-closed .page-sidebar-menu > li > a > .arrow {\n  display: none !important;\n}\n\n.page-sidebar-closed .page-sidebar .sidebar-toggler {\n  margin-right: 3px;\n}\n\n.page-sidebar-closed .page-sidebar .sidebar-search {\n  margin-top: 6px;\n  margin-bottom: 6px;\n}\n\n.page-sidebar-closed .page-sidebar-menu {\n  width: 35px !important;\n}\n\n.page-sidebar-closed .page-sidebar-menu > li > a {\n  padding-left: 7px;\n}\n\n.page-sidebar-fixed.page-sidebar-closed .page-sidebar-menu > li > a {\n  -webkit-transition: all 0.2s ease;\n     -moz-transition: all 0.2s ease;\n       -o-transition: all 0.2s ease;\n          transition: all 0.2s ease;\n}\n\n.page-sidebar-closed .page-sidebar-menu > li:hover {\n  width: 236px !important;\n  position: relative !important;\n  z-index: 2000;\n  display: block !important;\n}\n\n.page-sidebar-closed .page-sidebar-menu > li:hover .selected {\n  display: none;\n}\n\n.page-sidebar-closed .page-sidebar-menu > li:hover > a > i {\n  margin-right: 10px;\n}\n\n.page-sidebar-closed .page-sidebar-menu > li:hover .title {\n  display: inline !important;\n}\n\n.page-sidebar-closed .page-sidebar-menu > li > .sub-menu {\n  display: none !important;\n}\n\n.page-sidebar-closed .page-sidebar-menu > li:hover > .sub-menu {  \n  width: 200px;\n  position: absolute;\n  z-index: 2000;\n  left: 36px;\n  margin-top: 0;\n  top: 100%;\n  display: block !important;\n}\n\n.page-sidebar-closed .page-sidebar-menu > li:hover > .sub-menu > li > .sub-menu,\n.page-sidebar-closed .page-sidebar-menu > li:hover > .sub-menu > li > .sub-menu > li > .sub-menu {\n  width: 200px;\n}\n\n/* 2rd level sub menu*/\n.page-sidebar-closed .page-sidebar-menu > li:hover > .sub-menu > li > a {\n  padding-left: 15px !important;\n}\n\n/* 3rd level sub menu*/\n.page-sidebar-closed .page-sidebar-menu > li > ul.sub-menu > li > .sub-menu > li > a {  \n  padding-left: 30px !important;\n}\n\n/* 4rd level sub menu*/\n.page-sidebar-closed .page-sidebar-menu > li > ul.sub-menu > li > .sub-menu > li > .sub-menu > li > a {  \n  padding-left: 45px !important;\n}\n\n/* sidebar container */\n \n.page-sidebar-closed  .page-sidebar {\n  width: 35px;\n}\n\n.page-sidebar-closed  .page-content {\n  margin-left: 35px !important;\n}\n\n\n/***\nPage content\n***/\n.page-content {  \n  margin-top: 0px;   \n  padding: 0px;\n  background-color: #fff; \n}\n\n.ie8 .page-content { \n    padding: 20px;\n    margin-left: 225px; \n    margin-top: 0px;\n    min-height: 760px;\n}\n\n.ie8 .page-sidebar-fixed .page-content {\n    min-height: 600px; \n}\n\n.ie8 .page-content.no-min-height {\n    min-height: auto;\n}\n\n.page-full-width .page-content {\n    margin-left: 0px !important;\n}\n\n\n/***\nPage title\n***/\n.page-title {\n  padding: 0px;\n  font-size: 30px;\n  letter-spacing: -1px;\n  display: block;\n  color: #666;\n  margin: 0px 0px 15px 0px;\n  font-weight: 300;\n  font-family: 'Open Sans', sans-serif;\n}\n\n.page-title small {\n  font-size: 14px;\n  letter-spacing: 0px;\n  font-weight: 300;\n  color: #888;\n}\n\n/***\nPage breadcrumb\n***/\n\n.ie8 .row .page-breadcrumb.breadcrumb > li {\n  margin-right: 1px;\n}\n\n.page-content .page-breadcrumb.breadcrumb {\n  -webkit-border-radius: 0px;\n     -moz-border-radius: 0px;\n          border-radius: 0px;\n  box-shadow: none;\n  padding-right: 30px;\n  padding-left: 8px;\n  margin-top: 15px;\n  margin-bottom: 25px;\n  border:0px !important;  \n  background-color: #eee;\n}\n\n.page-content .page-breadcrumb.breadcrumb > li > a, \n.page-content .page-breadcrumb.breadcrumb > li > i, \n.page-content .page-breadcrumb.breadcrumb > li > span {\n  color: #333;\n  font-size: 14px;\n  text-shadow:none;\n}\n\n.page-content .page-breadcrumb.breadcrumb > li > i {\n  color: #666;\n} \n\n.page-content .page-breadcrumb.breadcrumb > li+li:before {\n  display: none;\n}\n\n/* Dashboard breadcrumb Dropdown */\n.page-content .page-breadcrumb.breadcrumb .btn-group {\n  right: 15px;\n  position: absolute;\n  margin-top: -8px;\n}\n\n.page-content .page-breadcrumb.breadcrumb > .btn-group .btn {\n  padding-top: 8px;\n  padding-bottom: 8px;\n}\n\n/* Dashboard date range panel */\n.page-content .page-breadcrumb.breadcrumb .dashboard-date-range  {\n  position: relative;\n  top: -8px;\n  margin-right: -30px;\n  display: none;\n  padding: 9px 9px 8px 9px;\n  cursor: pointer;\n  color: #fff;\n  background-color: #e02222;\n}\n\n/* hack for chrome and safari */\n@media all and (-webkit-min-device-pixel-ratio:0) {\n  .page-content .page-breadcrumb.breadcrumb .dashboard-date-range  {\n    padding: 9px;\n  } \n}\n\n.page-content .page-breadcrumb.breadcrumb .dashboard-date-range > span {\n  font-size: 12px;\n  font-weight: 300; \n  color: #fff;\n  text-transform: uppercase;\n} \n\n.page-content .page-breadcrumb.breadcrumb .dashboard-date-range > .fa-calendar {\n  text-transform: none;\n  color: #fff;\n  margin-top: 0px;\n  font-size: 14px;\n}\n\n.page-content .page-breadcrumb.breadcrumb .dashboard-date-range > .fa-angle-down {\n  color:#fff;\n  font-size: 16px;\n}\n\n/***\nFooter\n***/\n\n.footer {\n  padding: 8px 20px 5px 20px; \n  font-size: 12px;\n}\n\n.footer:after,\n.footer:before {\n  content: \"\";\n  display: table;\n  line-height: 0;\n}\n\n.footer:after {\n  clear: both;\n}\n\n.footer .footer-inner {\n  float: left;\n  display: inline-block;\n}\n\n.footer .footer-tools {\n  float: right;\n  display: inline-block;\n}\n\n.footer .footer-tools .go-top { \n  display: block;\n  text-decoration: none;\n  cursor: pointer;\n  margin-top: -2px;\n  margin-right: 0px;\n  margin-bottom: 0px;\n  font-size: 16px;\n  padding: 0px 6px 0px 6px;\n}\n\n.footer .footer-tools .go-top i {\n  font-size: 22px;\n  margin-bottom: 5px; \n}\n\n\n/********************\n GENERAL UI ELEMENTS \n*********************/\n\n/***\nIcon stuff\n***/\ni.icon, a.icon {\n  color: #999;\n  margin-right: 5px;\n  font-weight: normal;\n  font-size: 13px;\n}\n\ni.icon-black {\n  color: #000 !important;\n}\n\na.icon:hover {\n  text-decoration: none;\n  -webkit-transition: all 0.1s ease-in-out;\n  -moz-transition: all 0.1s ease-in-out;\n  -o-transition: all 0.1s ease-in-out;\n  -ms-transition: all 0.1s ease-in-out;\n  transition: all 0.1s ease-in-out;\n  opacity: .4;\n  filter:alpha(opacity=40);\n}\n\na.icon.huge i{\n  font-size: 16px !important;\n}\n\ni.big {\n  font-size: 20px;\n}\n\ni.warning {\n  color: #d12610;\n}\n\ni.critical {\n  color: #37b7f3;\n}\n\ni.normal {\n  color: #52e136;\n}\n\n/***\nCustom wells\n***/\n.well {\n  background-color: #fafafa;\n  border: 1px solid #eee;\n  -webkit-border-radius: 0px;\n     -moz-border-radius: 0px;\n          border-radius: 0px;   \n  -webkit-box-shadow: none !important;\n     -moz-box-shadow: none !important;\n          box-shadow: none !important;        \n}\n\n.well.mini {\n  padding: 7px !important;\n}\n\n/***\nForm stuff\n***/\n\n\n/***\nBordered form layout\n***/\n\n/***\nInput icons\n***/\n\n/* input with right aligned and colored icons */\n\n/* input with left aligned icons */\n.input-icon {\n  position: relative;\n}\n\n\n.input-icon input {\n   padding-left: 33px !important;\n}\n\n.input-icon i {\n  color: #ccc;\n  display: block;\n  position: absolute;\n  margin: 11px 2px 4px 10px;\n  width: 16px;\n  height: 16px;\n  font-size: 16px;\n  text-align: center;\n}\n\n.input-icon.right input {\n   padding-left: 12px !important;\n   padding-right: 33px !important;\n}\n\n.input-icon.right i {\n   right: 8px;\n   float: right;\n}\n\n.has-success .input-icon > i {\n  color: #468847;\n}\n\n.has-warning .input-icon > i {\n  color: #c09853;\n}\n\n.has-error .input-icon > i {\n  color: #b94a48;\n}\n\n/***\nPortlets\n***/\n.portlet  {\n  clear: both;\n  margin-top: 0px;\n  margin-bottom: 25px;\n  padding: 0px;\n}\n\n.portlet > .portlet-title {  \n  margin-bottom: 15px;\n  border-bottom: 1px solid #eee;\n}\n\n.portlet > .portlet-title:after,\n.portlet > .portlet-title:before {\n  content: \"\";\n  display: table;\n  line-height: 0;\n}\n\n.portlet > .portlet-title:after {\n  clear: both;\n}\n\n.portlet > .portlet-title > .caption {\n  float: left;\n  display: inline-block;\n  font-size: 18px;\n  line-height: 18px;\n  font-weight: 400;\n  margin: 0;\n  padding: 0;\n  margin-bottom: 8px; \n}\n\n.portlet > .portlet-title > .caption > i {\n  float: left;\n  margin-top: 4px;\n  display: inline-block !important;\n  font-size: 13px;\n  margin-right: 5px;\n  color: #666;\n}\n\n.portlet.blue > .portlet-title > .caption,\n.portlet.green > .portlet-title > .caption, \n.portlet.yellow > .portlet-title > .caption,\n.portlet.red > .portlet-title > .caption, \n.portlet.purple > .portlet-title > .caption, \n.portlet.grey > .portlet-title > .caption {\n  color: #fff;\n}\n\n.portlet.box.blue > .portlet-title > .caption > i, \n.portlet.box.green > .portlet-title > .caption > i,\n.portlet.box.grey > .portlet-title > .caption > i,\n.portlet.box.yellow > .portlet-title > .caption > i, \n.portlet.box.red > .portlet-title > .caption > i,  \n.portlet.box.purple > .portlet-title > .caption > i, \n.portlet.box.light-grey > .portlet-title > .caption > i{\n  color: #fff;\n}\n\n.sortable .portlet > .portlet-title {\n  cursor: move;\n}\n\n.portlet > .portlet-title > .tools,\n.portlet > .portlet-title > .actions\n {\n  display: inline-block;\n  padding: 0;\n  margin: 0;\n  margin-top: 6px;\n  float: right;\n}\n\n.portlet > .portlet-title > .tools > a {\n  display: inline-block;\n  height: 16px;\n  margin-left:5px;\n}\n\n.portlet > .portlet-title > .actions > .dropdown-menu i {\n  color: #000 !important;\n}\n\n.portlet > .portlet-title > .tools > a.remove {\n  margin-bottom: 2px;\n  background-image:url(../img/portlet-remove-icon.png);\n  background-repeat: no-repeat;\n  width: 11px;\n}\n\n.portlet > .portlet-title > .tools > a.config {\n  margin-bottom: 2px;\n  background-image:url(../img/portlet-config-icon.png);\n  background-repeat: no-repeat;\n  width: 12px;\n}\n\n.portlet > .portlet-title > .tools > a.reload {\n  margin-bottom: 2px;\n  background-image:url(../img/portlet-reload-icon.png);\n  width: 13px;\n}\n\n.portlet > .portlet-title > .tools > a.expand {\n  margin-bottom: 2px;\n  background-image:url(../img/portlet-expand-icon.png);\n  width: 14px;\n}\n\n.portlet > .portlet-title > .tools > a.collapse {\n  margin-bottom: 2px;\n  background-image:url(../img/portlet-collapse-icon.png);\n  width: 14px;\n}\n\n.portlet > .portlet-title > .tools > a:hover {\n  text-decoration: none;\n  -webkit-transition: all 0.1s ease-in-out;\n  -moz-transition: all 0.1s ease-in-out;\n  -o-transition: all 0.1s ease-in-out;\n  -ms-transition: all 0.1s ease-in-out;\n  transition: all 0.1s ease-in-out;\n  opacity:.6;  \n  filter:'alpha(opacity=60)';\n}\n\n.portlet > .portlet-title > .actions > .btn-group {\n  margin-top: -12px;\n}\n\n.portlet > .portlet-title > .actions > .btn {\n  padding: 4px 10px;\n  margin-top: -14px;\n}\n\n.portlet > .portlet-title > .actions > .btn-group > .btn {\n  padding: 4px 10px;\n  margin-top: -1px;\n}\n\n.portlet > .portlet-title > .actions > .btn.btn-sm {\n  padding: 3px 8px;\n  margin-top: -14px;\n}\n\n.portlet > .portlet-title > .actions > .btn-group > .btn-sm {\n  padding: 3px 8px;\n  margin-top: -1px;\n}\n\n.portlet > .portlet-title > .pagination.pagination-sm {\n  float: right !important;\n  display: inline-block !important;\n  margin: 0px;\n  margin-top: -4px;\n}\n\n.portlet > .portlet-body {\n  clear: both;  \n  padding: 0;  \n}\n\n.portlet > .portlet-body.light-blue, .portlet.light-blue {\n  background-color: #bfd5fa  !important;\n}\n\n.portlet > .portlet-body.blue, .portlet.blue {\n  background-color: #4b8df8 !important;\n}\n\n.portlet > .portlet-body.red, .portlet.red {\n  background-color: #e02222 !important;\n}\n\n.portlet > .portlet-body.yellow, .portlet.yellow {\n  background-color: #ffb848 !important;\n}\n\n.portlet > .portlet-body.green, .portlet.green {\n  background-color: #35aa47 !important;\n}\n\n.portlet > .portlet-body.purple, .portlet.purple {\n  background-color: #852b99 !important;\n}\n\n.portlet > .portlet-body.light-grey, .portlet.light-grey {\n  background-color: #fafafa !important;\n}\n\n.portlet > .portlet-body.grey, .portlet.grey {\n  background-color: #555555 !important;\n}\n\n/*  draggable girds */\n\n.ui-sortable-placeholder { \n    border: 1px dotted black; \n    visibility: visible !important; \n    height: 100% !important; \n}\n  \n.ui-sortable-placeholder * { \n  visibility: hidden; \n}\n\n.sortable-box-placeholder {\n  background-color: #f5f5f5;\n  border: 1px dashed #DDDDDD;\n  display: block;\n  /* float: left;*/\n  margin-top: 0px !important;\n  margin-bottom: 24px !important;\n}\n\n.sortable-box-placeholder * {\n  visibility:hidden;\n}\n\n/***\nSolid colored portlet\n***/\n.portlet.solid {\n  padding: 10px;\n}\n\n.portlet.solid > .portlet-title > .tools {\n  margin-top: 2px;\n  border: 0px;\n}\n\n.portlet.solid > .portlet-title {\n  margin-bottom: 5px;\n  border: 0px;\n}\n\n.portlet.solid.bordered > .portlet-title {\n  margin-bottom: 15px;\n}\n\n.portlet.solid.red > .portlet-title,\n.portlet.solid.red > .portlet-title > .caption > i,\n.portlet.solid.red > .portlet-body,\n\n.portlet.solid.green > .portlet-title,\n.portlet.solid.green > .portlet-title > .caption > i,\n.portlet.solid.green > .portlet-body,\n\n.portlet.solid.yellow > .portlet-title,\n.portlet.solid.yellow > .portlet-title > .caption > i,\n.portlet.solid.yellow > .portlet-body,\n\n.portlet.solid.grey > .portlet-title,\n.portlet.solid.grey > .portlet-title > .caption > i,\n.portlet.solid.grey > .portlet-body,\n\n.portlet.solid.purple > .portlet-title,\n.portlet.solid.purple > .portlet-title > .caption > i,\n.portlet.solid.purple > .portlet-body,\n\n.portlet.solid.blue > .portlet-title,\n.portlet.solid.blue > .portlet-title > .caption > i,\n.portlet.solid.blue > .portlet-body {\n  border: 0;\n  color: #fff;\n}\n\n.portlet.bordered {\n  border-left: 2px solid #ddd;\n}\n\n/***\nBox portlet\n***/\n\n\n.portlet.box {\n   padding:0px !important\n}\n\n.portlet.box > .portlet-title {  \n   padding:8px 10px 2px 10px;\n   border-bottom: 1px solid #eee;\n   color: #fff !important;\n}\n\n.portlet.box > .portlet-title > .actions > .btn > i {\n  color: #fff !important;\n}\n\n.portlet.box > .portlet-title > .tools {\n  margin-top: 3px;\n}\n\n.portlet.box > .portlet-title > .tools > a.remove, \n.portlet.solid > .portlet-title > .tools > a.remove {\n  background-image:url(../img/portlet-remove-icon-white.png);\n}\n\n.portlet.box > .portlet-title > .tools > a.config,\n.portlet.solid > .portlet-title > .tools > a.config {\n  background-image:url(../img/portlet-config-icon-white.png);\n}\n\n.portlet.box > .portlet-title > .tools > a.reload,\n.portlet.solid > .portlet-title > .tools > a.reload {\n  background-image:url(../img/portlet-reload-icon-white.png);\n}\n\n.portlet.box > .portlet-title > .tools > a.expand,\n.portlet.solid > .portlet-title > .tools > a.expand {\n  background-image:url(../img/portlet-expand-icon-white.png);\n}\n\n.portlet.box > .portlet-title > .tools > a.collapse,\n.portlet.solid > .portlet-title > .tools > a.collapse {\n  background-image:url(../img/portlet-collapse-icon-white.png);\n}\n\n/* portlet buttons */\n.portlet.box > .portlet-body {\n  background-color: #fff;\n  padding: 10px;\n}\n\n.portlet.box > .portlet-title {  \n  margin-bottom: 0px;\n}\n\n.portlet.box.blue > .portlet-title {\n  background-color: #4b8df8;\n} \n\n.portlet.box.blue {  \n   border: 1px solid #b4cef8;\n   border-top: 0;\n}\n\n.portlet.box.red > .portlet-title {\n  background-color: #e02222;\n} \n\n.portlet.box.red {  \n   border: 1px solid #ef8476;\n   border-top: 0;\n}\n\n.portlet.box.yellow > .portlet-title {\n  background-color: #ffb848;\n} \n\n.portlet.box.yellow {  \n   border: 1px solid #fccb7e;\n   border-top: 0;\n}\n\n.portlet.box.green > .portlet-title {\n  background-color: #35aa47;\n} \n\n.portlet.box.green {  \n   border: 1px solid #77e588;\n   border-top: 0;\n}\n\n.portlet.box.purple > .portlet-title {\n  background-color: #852b99;\n} \n\n.portlet.box.purple {  \n   border: 1px solid #af5cc1;\n   border-top: 0;\n}\n\n.portlet.box.grey > .portlet-title {\n  background-color: #555555;\n} \n\n.portlet.box.grey {  \n   border: 1px solid #9d9c9c;\n   border-top: 0;\n}\n\n.portlet.box.light-grey > .portlet-title {\n  background-color: #aaa;\n} \n\n.portlet.box.light-grey {  \n   border: 1px solid #bbb;\n   border-top: 0;\n}\n\n/***\nCharts and statistics\n***/\n.chart, .pie, .bars {\n  overflow: hidden;\n  height: 300px;\n}\n\n/***\nStatistic lists\n***/\n.item-list.table .percent {\n  width: 30px;\n  float: right;\n  margin-right: 10px;\n  margin-top: 3px;\n}\n\n\n/***\nChart tooltips\n***/\n.chart-tooltip {\n  clear: both;\n  z-index: 100;\n  background-color: #736e6e !important;\n  padding: 5px !important;\n  color: #fff;\n}\n\n.chart-tooltip .label {\n  clear: both;\n  display: block;\n  margin-bottom: 2px;\n}\n\n/***\nMini chart containers\n***/\n.bar-chart {\n  display: none\n}\n\n.line-chart {\n  display: none\n}\n\n/***\nCustom icon buttons\n***/\n.icon-btn {\n  height: 60px;\n  min-width: 80px;\n  margin: 5px 5px 0 0;\n  border: 1px solid #ddd;\n  padding: 12px 0px 0px 0px;\n  background-color: #fafafa !important;\n  background-image: none !important;\n  filter:none !important;\n  -webkit-box-shadow: none !important;\n     -moz-box-shadow: none !important;\n          box-shadow: none !important;\n  display:inline-block !important;\n  color: #646464 !important;\n  text-shadow: none !important;\n  text-align: center;\n  cursor: pointer;\n  position: relative;  \n  -webkit-transition: all 0.3s ease !important;\n  -moz-transition: all 0.3s ease !important;\n  -ms-transition: all 0.3s ease !important;\n  -o-transition: all 0.3s ease !important;\n  transition: all 0.3s ease !important;\n}\n\n.icon-btn i {\n  font-size: 18px;\n}\n\n.ie8 .icon-btn:hover {\n  filter: none !important;\n} \n\n.icon-btn:hover {\n  text-decoration: none !important;\n  border-color: #999 !important;\n  color: #444 !important;\n  text-shadow: 0 1px 0px rgba(255, 255, 255, 1) !important;\n  -webkit-transition: all 0.3s ease !important;\n  -moz-transition: all 0.3s ease !important;\n  -ms-transition: all 0.3s ease !important;\n  -o-transition: all 0.3s ease !important;\n  transition: all 0.3s ease !important;\n  -webkit-box-shadow: none !important;\n  -moz-box-shadow: none !important;\n  box-shadow: none !important;\n}\n\n.icon-btn:hover .badge {\n  -webkit-transition: all 0.3s ease !important;\n  -moz-transition: all 0.3s ease !important;\n  -ms-transition: all 0.3s ease !important;\n  -o-transition: all 0.3s ease !important;\n  transition: all 0.3s ease !important;\n  -webkit-box-shadow: none !important;\n       -moz-box-shadow: none !important;\n            box-shadow: none !important;\n}\n\n.icon-btn div {\n  font-family: 'Open Sans', sans-serif;\n  margin-top: 5px;\n  margin-bottom: 20px;  \n  color: #000;\n  font-size: 12px;\n  font-weight: 300;\n}\n\n.icon-btn .badge {\n  position: absolute;\n  font-family: 'Open Sans', sans-serif;\n  font-size: 11px !important;\n  font-weight: 300;\n  top: -5px;\n  right: -5px;\n  padding: 3px 6px 3px 6px;\n  color: white !important;\n  text-shadow: none;\n  border-width: 0;\n  border-style: solid;\n  -webkit-border-radius: 12px !important;\n  -moz-border-radius: 12px !important;\n  border-radius: 12px !important;\n  -webkit-box-shadow: none;\n  -moz-box-shadow: none;\n  box-shadow: none;\n}\n\n/* extended dropdowns */\n.dropdown-menu.extended {\n  min-width: 160px !important;\n  max-width: 300px !important;\n  width: 233px !important;\n  background-color: #ffffff !important;\n}\n\n.dropdown-menu.extended:before,\n.dropdown-menu.extended:after {\n  border-bottom-color: #ddd !important;\n}\n\n.dropdown-menu.extended li a{\n  display: block;\n  padding: 5px 10px !important;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  white-space: normal !important;\n}\n\n.dropdown-menu.extended li i{\n  margin-right: 3px;\n}\n\n.dropdown-menu.extended li a{\n   font-size: 13px;\n   padding: 10px !important;\n   background-color: #ffffff;\n}\n\n.dropdown-menu.extended li a:hover {\n  background-image: none;\n  background-color: #f5f5f5;\n  color: #000;\n  filter:none;\n}\n\n.dropdown-menu.extended li p{\n  padding: 10px;\n  background-color: #eee;\n  margin: 0px;\n  font-size: 14px;\n  font-weight: 300;\n  color: #000;\n}\n\n.dropdown-menu.extended li a{\n  padding: 7px 0 5px 0px;\n  list-style: none;\n  border-bottom: 1px solid #f4f4f4 !important;\n  font-size: 12px;\n  text-shadow: none;\n}\n\n.dropdown-menu.extended li:first-child a {\n  border-top: none;\n  border-bottom: 1px solid #f4f4f4 !important;\n}\n\n.dropdown-menu.extended li:last-child a {\n  border-top: 1px solid white !important;\n  border-bottom: 1px solid #f4f4f4 !important;\n}\n\n.dropdown-menu.extended li.external > a {\n  font-size: 13px;\n  font-weight: 400;  \n}\n\n.dropdown-menu.extended li.external > a > i{\n  margin-top: 3px;\n  float: right;\n}\n\n/* header notifications dropdowns */\n.dropdown-menu .dropdown-menu-list.scroller {\n  padding-right: 0 !important;\n  padding-left: 0;\n  list-style: none;\n}\n\n.dropdown-menu.notification li > a .time {\n  font-size: 12px;\n  font-weight: 600;\n  text-align: right;\n  font-style: italic;\n}\n\n/* header inbox dropdowns */\n.dropdown-menu.inbox li > a .photo {\n  float: left;\n  padding-right: 6px;\n}\n\n.dropdown-menu.inbox li > a .photo > img {\n  height: 40px;\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: 14px;\n  font-weight: 400;\n  color: #02689b;\n}\n\n.dropdown-menu.inbox li > a .subject .time {\n  font-size: 12px;\n  font-weight: 600;\n  font-style: italic;\n  position: relative;\n  float: right;\n}\n\n.dropdown-menu.inbox li > a .message {\n  display: block !important;\n  font-size: 12px;\n}\n\n/* header tasks */\n.dropdown-menu.tasks .task {\n  margin-bottom: 5px;\n}\n\n.dropdown-menu.tasks .task .desc {\n  font-size: 13px;\n  font-weight: 300;\n}\n\n.dropdown-menu.tasks .task .percent {\n  font-size: 14px;\n  font-weight: 600;\n  font-family: 'Open Sans', sans-serif;\n  float: right;\n  display: inline-block;\n}\n\n.dropdown-menu.tasks .progress {\n  display: block;\n  height: 11px;\n  margin: 0px;\n}\n\n/***\nGeneral list for item with image\n***/\n.item-list li .img {\n  height: 50px;\n  width: 50px;\n  float: left;\n  margin-top: 3px;\n  margin-right: 5px;\n}\n\n.item-list {\n  margin: 0px;\n  list-style: none;\n}\n\n.item-list li {\n  padding: 7px 0 5px 0px;\n  list-style: none;\n  border-top: 1px solid white;\n  border-bottom: 1px solid #EBEBEB;\n  font-size: 12px;\n}\n\n.item-list li:first-child {\n  border-top: none;\n  border-bottom: 1px solid #EBEBEB;\n}\n\n.item-list li:last-child {\n  border-top: none;\n  border-bottom: none;\n}\n\n.item-list li .label {\n  margin-right: 5px;\n}\n\n.item-list.todo li .label {\n  position: absolute;\n  right: 80px;\n}\n\n.item-list.todo li .actions {\n  position: absolute;\n  right: 45px;\n}\n\n/***\nCustom tables\n***/\n.table-toolbar {\n  margin-bottom: 15px;\n}\n\n.table.table-full-width {\n  width: 100% !important;\n}\n\n.table .m-btn {\n  margin-top: 0px;\n  margin-left: 0px; \n  margin-right: 5px;\n}\n\n.table thead tr th {\n  font-size: 14px;\n  font-weight: 600;\n}\n\n.table-advance {\n  margin-bottom: 10px !important;\n}\n\n.table-advance thead { \n  color: #999; \n}\n\n.table-advance thead tr th{\n  background-color: #DDD; \n  font-size: 14px;\n  font-weight: 400; \n  color: #666;\n}\n\n.table-advance div.success, \n.table-advance div.info, \n.table-advance div.important, \n.table-advance div.warning, \n.table-advance div.danger {\n  position: absolute;\n  margin-top:-5px;\n  float: left;\n  width: 2px;\n  height: 30px;\n  margin-right: 20px !important;\n}\n\n.table-advance tr td {\n  border-left-width: 0px; \n}\n.table-advance tr td:first-child {\n  border-left-width: 1px !important; \n}\n\n.table-advance tr td.highlight:first-child a {\n  margin-left: 15px;\n}\n\n.table-advance td.highlight div.success {  \n  border-left: 2px solid #66ee66;\n}\n\n.table-advance td.highlight div.info {  \n  border-left: 2px solid #87ceeb;\n}\n\n.table-advance td.highlight div.important {  \n  border-left: 2px solid #f02c71;\n}\n\n.table-advance td.highlight div.warning {  \n  border-left: 2px solid #fdbb39;\n}\n\n.table-advance td.highlight div.danger {  \n  border-left: 2px solid #e23e29;\n}\n\n\n/***\nStar rating\n***/\n.rating {\n  unicode-bidi: bidi-override;\n  direction: rtl;\n  font-size: 30px;\n}\n\n.rating span.star {\n  font-family: FontAwesome;\n  font-weight: normal;\n  font-style: normal;\n  display: inline-block;\n}\n\n.rating span.star:hover {\n  cursor: pointer;\n}\n\n.rating span.star:before {\n  content: \"\\f006\";\n  padding-right: 5px;\n  color: #999999;\n}\n\n.rating span.star:hover:before,\n.rating span.star:hover ~ span.star:before {\n  content: \"\\f005\";\n  color: #e3cf7a;\n}\n\n\n/***\nItem block with details shown on hover\n***/\n.item {\n  overflow: hidden;\n  display: block;\n  margin-bottom: 20px;\n}\n\n.item .details {\n  width: 100%;\n  display: none;\n  background-color: #000;\n  color: #fff !important;\n  padding: 5px;\n  text-align: center;\n  position: relative;\n  bottom:30px; \n  margin-bottom:-30px; \n  overflow: hidden; \n  z-index: 6;\n}\n\n.item:hover .details {\n  display: block;\n  opacity: 0.7;\n  filter: alpha(opacity = 70);\n}\n\n.item:hover .zoom-icon{\n  opacity:0.5;  \n  filter: alpha(opacity = 50);\n}\n\n/***\nZoom icon overlay on images\n***/\n.zoom {\n  cursor: pointer;\n  width: 100%;\n  height: 100%;\n  position: relative;   \n  z-index: 5;\n}\n\n.zoom .zoom-icon {\n  background-image:url(\"../img/overlay-icon.png\");\n  background-color: #222;\n  background-repeat: no-repeat;\n  background-position: 50%;\n  position: absolute;\n  width: inherit;\n  height: inherit;\n  opacity: 0; \n  filter: alpha(opacity = 0);\n  z-index: 6;  \n  top:0;  \n}\n\n/***\nChats\n***/\n.chats {\n  margin:0;\n  padding: 0;\n  margin-top: -15px;\n}\n\n.chats li {\n  list-style: none;\n  padding: 5px 0;\n  margin: 10px auto;\n  font-size: 12px;\n}\n\n.chats li img.avatar {\n  height: 45px;\n  width: 45px;\n  -webkit-border-radius: 50% !important;\n     -moz-border-radius: 50% !important;\n          border-radius: 50% !important;\n}\n\n.chats li.in img.avatar {\n  float: left;\n  margin-right: 10px;\n}\n\n.chats li .name {\n  color:#3590c1;\n  font-size: 13px;\n  font-weight: 400;\n}\n\n.chats li .datetime {\n  color:#333;\n  font-size: 13px;\n  font-weight: 400;\n}\n\n.chats li.out img.avatar {\n  float: right;\n  margin-left: 10px;\n}\n\n.chats li .message {\n  display: block; \n  padding: 5px;\n  position: relative;\n}\n\n.chats li.in .message {\n  text-align: left;\n  border-left: 2px solid #35aa47;\n  margin-left: 65px;\n  background: #fafafa \n}\n\n.chats li.in .message .arrow {\n  display: block;\n  position: absolute;\n  top: 5px;\n  left: -8px;  \n  width: 0; \n  height: 0; \n\n  border-top: 8px solid transparent;\n  border-bottom: 8px solid transparent;  \n  border-right: 8px solid #35aa47;  \n}\n\n.chats li.out .message .arrow {\n  display: block;\n  position: absolute;\n  top: 5px;\n  right: -8px;\n  border-top: 8px solid transparent;\n  border-bottom: 8px solid transparent;  \n  border-left: 8px solid #da4a38;  \n}\n\n.chats li.out .message {\n  border-right: 2px solid #da4a38;\n  margin-right: 65px;\n  background: #fafafa;\n  text-align: right;\n}\n\n.chats li.out .name, \n.chats li.out .datetime  {  \n  text-align: right;\n}\n\n.chats li .message .body {\n  display: block; \n}\n\n.chat-form {\n  margin-top: 15px;\n  padding: 10px;\n  background-color: #e9eff3;\n  overflow: hidden;\n  clear: both;   \n}\n\n.chat-form .input-cont {\n  margin-right: 40px;\n}\n\n.chat-form .input-cont .form-control {\n  width: 100% !important;\n  margin-bottom: 0px;\n}\n\n.chat-form .input-cont input{\n  border: 1px solid #ddd;\n  width: 100%  !important;  \n  margin-top: 0;\n}\n\n.chat-form .input-cont input {\n  background-color: #fff !important;\n}\n\n.chat-form .input-cont input:focus{\n  border: 1px solid #4b8df9 !important;\n}\n\n.chat-form .btn-cont {\n  margin-top: -42px;\n  position: relative;\n  float: right;\n  width:44px;\n}\n\n.chat-form .btn-cont .arrow {\n  position: absolute;\n  top: 17px;\n  right: 43px;\n  border-top: 8px solid transparent;\n  border-bottom: 8px solid transparent;  \n  border-right: 8px solid #4d90fe;   \n    -webkit-box-sizing: border-box;\n       -moz-box-sizing: border-box;\n            box-sizing: border-box; \n}\n\n.chat-form .btn-cont:hover .arrow {\n  border-right-color: #0362fd;\n}\n\n.chat-form .btn-cont:hover .btn {\n  background-color: #0362fd;\n}\n\n.chat-form .btn-cont .btn {\n  margin-top: 8px;\n}\n\n/***\nSystem feeds\n***/\n.feeds {\n  margin: 0px;\n  padding: 0px;\n  list-style: none;\n}\n\n.feeds li {\n  background-color: #fafafa;\n  margin-bottom: 7px;   \n}\n\n.feeds li:before, \n.feeds li:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.feeds li:after {\n  clear: both;\n}\n\n.feeds li:last-child {\n  margin-bottom: 0px;\n}\n\n.feeds .col1 {\n  float:left;\n  width:100%;  \n  clear: both;\n}\n\n.feeds .col2 {\n  float:left;\n  width:75px;\n  margin-left:-75px;\n}\n\n.feeds .col1 .cont {\n  float:left;\n  margin-right:75px;\n  overflow:hidden;\n}\n\n.feeds .col1 .cont  .cont-col1 {\n  float:left;\n  margin-right:-100%;\n}\n\n.feeds .col1 .cont  .cont-col1 .label {\n  display: inline-block;\n  padding: 5px 4px 6px 5px;\n  vertical-align: middle;\n  text-align: center;\n}\n.feeds .col1 .cont  .cont-col1 .label > i {\n  text-align: center;\n  font-size: 14px;\n}\n\n.feeds .col1 .cont .cont-col2 {\n  float:left;\n  width:100%;\n}\n\n.feeds .col1 .cont .cont-col2 .desc { \n  margin-left:35px;\n  padding-top: 4px;\n  padding-bottom: 5px;\n  overflow:hidden;\n}\n\n.feeds .col2 .date {\n  padding: 4px 9px 5px 4px;\n  text-align: right;\n  font-style: italic;\n  color:#c1cbd0;\n}\n\n/***\nUsers\n***/\n.user-info {\n  margin-bottom: 10px !important;\n}\n\n.user-info img {\n  float: left;\n  margin-right: 5px;\n}\n\n.user-info .details {\n  display: inline-block;\n}\n\n.user-info .label {\n  font-weight: 300;\n  font-size: 11px;\n}\n\n/***\nAccordions\n***/\n.accordion-heading {\n  background:#eee;\n}\n\n.accordion-heading a {\n  text-decoration:none;\n}\n\n.accordion-heading a:hover {\n  text-decoration:none;\n}\n\n/***\nVertical inline menu\n***/\n.ver-inline-menu {\n  padding: 0;\n  margin: 0;\n  list-style: none;\n}\n\n.ver-inline-menu li {\n  position:relative;\n  margin-bottom:1px;\n}\n\n.ver-inline-menu li i {\n  width: 37px;\n  height: 37px;\n  display: inline-block;\n  color:#b9cbd5;\n  font-size:15px;\n  padding:12px 10px 10px 8px;\n  margin:0 8px 0 0;\n  text-align: center;\n  background:#e0eaf0 !important;\n}\n\n.ver-inline-menu li a {\n  font-size: 13px;\n  color:#557386;\n  display:block;\n  background:#f0f6fa;\n  border-left:solid 2px #c4d5df;\n}\n\n.ver-inline-menu li:hover a,\n.ver-inline-menu li:hover i {\n  background:#e0eaf0;\n  text-decoration:none;\n}\n\n.ver-inline-menu li:hover i {\n  color:#fff;\n  background:#c4d5df !important;\n}\n\n.ver-inline-menu li.active a,\n.ver-inline-menu li:hover a {\n  font-size: 13px;\n}\n\n.ver-inline-menu li.active a {\n  border-left:solid 2px #0c91e5;\n}\n\n.ver-inline-menu li.active a,\n.ver-inline-menu li.active i {\n  color:#fff;\n  background:#169ef4;\n  text-decoration:none;\n}\n\n.ver-inline-menu li.active i {\n  background:#0c91e5 !important;  \n}\n\n.ver-inline-menu li.active:after {\n  content: '';\n  display: inline-block;\n  border-bottom: 6px solid transparent;\n  border-top: 6px solid transparent;\n  border-left: 6px solid #169ef4;\n  position: absolute;\n  top: 12px;\n  right: -5px;\n}\n\n/***\nCustom tabs\n***/\n\n.tabbable-custom { \n  margin-bottom: 15px; \n  padding: 0px;  \n  overflow: hidden;\n}   \n\n.tabbable-custom > .nav-tabs { \n  border: none; \n  margin: 0px;\n}\n\n.tabbable-custom > .tab-content { \n   background-color: #fff;\n   border: 1px solid #ddd;  \n   -webkit-border-radius: 0; \n   -moz-border-radius: 0; \n   border-radius: 0; \n   padding: 10px;\n}\n\n.tabbable-custom.nav-justified .tab-content {\n  margin-top: -1px;\n}\n\n.tabs-below.tabbable-custom.nav-justified .tab-content {\n  margin-top: 0px;\n  margin-bottom: -2px;\n}\n\n.tabbable-custom.boxless > .tab-content {\n  padding:15px 0;\n  border-left:none;\n  border-right:none;\n  border-bottom:none;\n}\n\n.tabbable-custom .nav-tabs > li { \n  margin-right: 2px; \n  border-top: 2px solid transparent; \n}\n\n.tabbable-custom .nav-tabs > li > a { \n   margin-right: 0; \n }\n\n.tabbable-custom .nav-tabs > li > a:hover { \n  background: none;\n  border-color:transparent;\n}\n\n.tabbable-custom .nav-tabs > li.active { \n  border-top: 3px solid #d12610; \n  margin-top: 0; \n  position: relative; \n}\n\n.tabbable-custom .nav-tabs > li.active > a  { \n  border-top: none; \n  font-weight: 400; \n}\n\n.tabbable-custom .nav-tabs > li.active > a:hover { \n  border-top: none; \n  background: #fff; \n  border-color: #d4d4d4 #d4d4d4 transparent; \n}\n\n.tabbable-custom .nav-tabs > li { \n  margin-right: 2px; \n  border-top: 2px solid transparent; \n}\n\n/* below tabs */\n\n\n.tabs-below.tabbable-custom .nav-tabs > li > a { \n  border-top: none; \n  border-bottom: 2px solid transparent; \n  margin-top: -1px; \n}\n\n.tabs-below.tabbable-custom .nav-tabs > li.active { \n    border-top: none; \n    border-bottom: 3px solid #d12610; \n    margin-bottom: 0; \n    position: relative; \n}\n\n.tabs-below.tabbable-custom .nav-tabs > li.active > a { \n  border-bottom: none \n}\n\n.tabs-below.tabbable-custom .nav-tabs > li.active > a:hover { \n  background: #fff; \n  border-color: #d4d4d4 #d4d4d4 transparent; \n}\n    \n/*full width tabs with bigger titles */\n.tabbable-custom.tabbable-full-width > .tab-content {\n  padding:15px 0;\n  border-left:none;\n  border-right:none;\n  border-bottom:none;\n}\n\n.tabbable-custom.tabbable-full-width .nav-tabs > li > a {\n  color:#424242;\n  font-size:15px;\n  padding:9px 15px;\n}\n\n\n/***\nCustom portlet tabs\n***/\n.portlet-tabs > .nav-tabs {\n    position: relative;\n    top: -41px;\n    margin-right: 10px;\n    overflow: hidden;\n}\n\n.portlet-tabs > .nav-tabs > li {\n    float: right;\n}\n\n.portlet-tabs > .nav-tabs {\n    border-bottom: none;\n}\n\n.portlet-tabs > .nav-tabs > li > a {\n  color: #fff;\n  padding-top: 8px;\n  padding-bottom: 10px;\n  line-height: 16px;\n  margin-top: 6px;\n  margin-left: 0px;\n  margin-right: 0px;\n  border-left: 0;    \n  border-right: 0;\n     -webkit-border-radius: 0px;\n        -moz-border-radius: 0px;\n             border-radius: 0px;   \n}\n\n.portlet-tabs > .nav-tabs > li:last-child > a {\n  border-right:0;\n}\n\n.portlet-tabs > .nav-tabs > li {\n  margin-left: 1px;\n}\n\n.portlet-tabs > .nav-tabs > li.active {\n  color: #333;\n  border-top-color: transparent;\n}\n\n.portlet-tabs > .nav-tabs > li.active > a {\n  margin-bottom: 0px;\n  border-bottom: 0;\n  margin-left: 0px;\n  margin-right: 0px;\n  border-left: 0;    \n  border-right: 0;\n  border-top-color:transparent !important;\n}\n\n.portlet-tabs > .nav-tabs > li > a:hover {   \n  color: #333;\n  margin-bottom: 0;\n  border-bottom-color: transparent;\n  margin-left: 0;\n  margin-right: 0;\n  border-left: 0;    \n  border-right: 0;\n  border-top-color:transparent;\n  background-color: #fff;\n}  \n\n.portlet-tabs > .nav-tabs > .active > a  {\n  color: #555555;\n  cursor: default;\n  background-color: #fff;\n}\n\n.portlet-tabs > .nav-tabs > .active > a:hover {\n  background-color: #fff !important;\n}\n\n.portlet-tabs > .tab-content {\n  padding: 10px !important;\n  margin: 0px;\n  margin-top: -50px !important;\n}\n\n.portlet.tabbable .portlet-body {\n  padding: 0px;\n}\n\n.tab-pane > p:last-child {\n  margin-bottom: 0px;\n}\n\n/***\nDashboard container\n***/\n#dashboard {\n  overflow: hidden;\n}\n\n/***\nDashboard stats\n***/\n.dashboard-stat {\n  margin-bottom: 25px;\n}\n\n.dashboard-stat:before,\n.dashboard-stat:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n.dashboard-stat:after {\n  clear: both;\n}\n\n.dashboard-stat .visual {\n  width: 80px;\n  height:80px;\n  display: block;\n  float: left;\n  padding-top: 10px;\n  padding-left: 15px;\n  margin-bottom: 10px;\n}\n\n.dashboard-stat .visual i {\n  font-size: 65px;\n  line-height: 65px;\n  color: #fff;\n}\n\n@media (min-width: 992px) and (max-width: 1024px) {  \n\n  .dashboard-stat .visual i { \n    font-size: 28px;\n    line-height: 28px;\n  }\n\n}\n\n.dashboard-stat .details {\n  position: absolute;\n  right: 15px;\n  padding-right: 10px;  \n}\n\n.dashboard-stat .details .number {    \n  padding-top: 15px;\n  text-align: right;\n  font-size: 34px;\n  line-height: 34px;\n  letter-spacing: -1px;\n  margin-bottom: 5px;\n  font-weight: 300;\n  color: #fff;\n}\n\n.dashboard-stat .details .desc {\n  text-align: right;\n  font-size: 16px;\n  letter-spacing: 0px;\n  font-weight: 300;\n  color: #fff;  \n}\n\n.dashboard-stat .more {\n  clear: both;\n  display: block;  \n  padding: 5px 10px 5px 10px;\n  text-transform: uppercase;\n  font-weight: 300;\n  font-size: 11px;\n  color: #fff;  \n  opacity: 0.7;  \n  filter: alpha(opacity=70);\n}  \n\n.dashboard-stat .more:hover {\n  text-decoration: none;\n  opacity: 1;  \n  filter: alpha(opacity=100);\n}\n\n.dashboard-stat .more > i {\n  display: inline-block;\n  margin-top: 1px;\n  float: right;\n}\n\n.dashboard-stat.blue {\n  background-color: #27a9e3;\n}\n\n.dashboard-stat.blue .more { \n  background-color: #208dbe;\n} \n\n.dashboard-stat.green {\n  background-color: #28b779;\n}\n\n.dashboard-stat.green .more { \n  background-color: #10a062;\n} \n\n.dashboard-stat.red {\n  background-color: #e7191b;\n}\n\n.dashboard-stat.red .more { \n  background-color:#bc0d0e;\n} \n\n.dashboard-stat.yellow {\n  background-color: #ffb848;\n}\n\n.dashboard-stat.yellow .more { \n  background-color: #cb871b;\n} \n\n.dashboard-stat.purple {\n  background-color: #852b99;\n}\n\n.dashboard-stat.purple .more { \n  background-color: #6e1881;\n} \n\n\n/***\nTiles(new in v1.1.1)\n***/\n.tiles {\n  margin-right: -10px;\n}\n\n.tile {\n  display: block;\n  letter-spacing: 0.02em;\n  float: left;\n  height: 135px;\n  width: 135px !important;\n  cursor: pointer;\n  text-decoration: none;\n  color: #ffffff;\n  position: relative;\n  font-weight: 300;\n  font-size: 12px;\n  letter-spacing: 0.02em;\n  line-height: 20px;\n  overflow: hidden;\n  border: 4px solid transparent;\n  margin: 0 10px 10px 0;\n}\n\n.tile:after,\n.tile:before {\n  content: \"\";\n  float: left; \n}\n\n.tile.double {\n  width: 280px !important;\n}\n\n.tile.double-down {\n  height: 280px !important;\n}\n\n.tile:active, .tile.selected {\n  border-color: #ccc !important;\n}\n\n.tile:hover {\n  border-color: #aaa !important;\n}\n\n.tile.selected .corner:after {  \n  content: \"\";\n  display: inline-block;\n  border-left: 40px solid transparent;\n  border-bottom: 40px solid transparent;\n  border-right: 40px solid #ccc;\n  position: absolute;\n  top: -3px;\n  right: -3px;\n}\n\n.tile.selected .check:after {  \n  content: \"\";\n  font-family: FontAwesome;\n  font-size: 13px;\n  content: \"\\f00c\";\n  display: inline-block;\n  position: absolute;\n  top: 2px;\n  right: 2px;\n}\n\n.tile * {\n  color: #ffffff;\n}\n\n.tile .tile-body {\n  height: 100%;\n  vertical-align: top;\n  padding: 10px 10px;\n  overflow: hidden;\n  position: relative;\n  font-weight: 400;\n  font-size: 12px;\n  color: #000000;\n  color: #ffffff;\n  margin-bottom: 10px;\n}\n\n.tile .tile-body img {\n  float: left;\n  margin-right: 10px;\n}\n\n.tile .tile-body img.pull-right {\n  float: right !important;\n  margin-left: 10px;\n  margin-right: 0px;\n}\n\n.tile .tile-body .content {\n  display: inline-block;\n}\n\n.tile .tile-body > i {\n  margin-top: 17px;\n  display: block;\n  font-size: 56px;\n  line-height: 56px;\n  text-align: center;\n}\n\n\n.tile.double-down i {\n  margin-top: 95px;\n}\n\n.tile .tile-body h1,\n.tile .tile-body h2,\n.tile .tile-body h3,\n.tile .tile-body h4,\n.tile .tile-body h5,\n.tile .tile-body h6,\n.tile .tile-body p {\n  padding: 0;\n  margin: 0;\n  line-height: 14px;\n}\n\n.tile .tile-body h3,\n.tile .tile-body h4 {\n  margin-bottom: 5px;\n}\n\n.tile .tile-body h1:hover,\n.tile .tile-body h2:hover,\n.tile .tile-body h3:hover,\n.tile .tile-body h4:hover,\n.tile .tile-body h5:hover,\n.tile .tile-body h6:hover,\n.tile .tile-body p:hover {\n  color: #ffffff;\n}\n\n.tile .tile-body p {\n  font-weight: 400;\n  font-size: 13px;\n  color: #000000;\n  color: #ffffff;\n  line-height: 20px;\n  overflow: hidden;\n}\n\n.tile .tile-body p:hover {\n  color: rgba(0, 0, 0, 0.8);\n}\n\n.tile .tile-body p:active {\n  color: rgba(0, 0, 0, 0.4);\n}\n\n.tile .tile-body p:hover {\n  color: #ffffff;\n}\n\n.tile.icon > .tile-body {\n  padding: 0;\n}\n\n.tile .tile-object {\n  position: absolute;\n  bottom: 0;\n  left: 0;\n  right: 0;\n  min-height: 30px;\n  background-color: transparent;\n  *zoom: 1;\n}\n\n.tile .tile-object:before,\n.tile .tile-object:after {\n  display: table;\n  content: \"\";\n}\n\n.tile .tile-object:after {\n  clear: both;\n}\n\n.tile .tile-object > .name {\n  position: absolute;\n  bottom: 0;\n  left: 0;\n  margin-bottom: 5px;\n  margin-left: 10px;\n  margin-right: 15px;\n  font-weight: 400;\n  font-size: 13px;\n  color: #ffffff;\n}\n\n.tile .tile-object > .name > i {\n  vertical-align: middle;\n  display: block;\n  font-size: 24px;\n  height: 18px;\n  width: 24px;\n}\n\n.tile .tile-object > .number {\n  position: absolute;\n  bottom: 0;\n  right: 0;\n  margin-bottom: 0;\n  color: #ffffff;\n  text-align: center;\n  font-weight: 600;\n  font-size: 14px;\n  letter-spacing: 0.01em;\n  line-height: 14px;\n  margin-bottom: 8px;\n  margin-right: 10px;\n}\n\n.tile.image > .tile-body {\n  padding: 0 !important;\n}\n\n.tile.image > .tile-body > img{\n  width: 100%;\n  height: auto;\n  min-height: 100%;\n  max-width: 100%;\n}\n\n.tile.image .tile-body h3 {\n  display: inline-block;\n}\n\n/***\nTheme Panel\n***/\n\n.theme-panel {\n  width: 320px;\n  margin-top: -20px;\n  margin-right: 1px;\n  z-index: 999;\n  float: right;\n  position:relative;\n}\n\n.theme-panel > .toggler {\n  top:4px;\n  right:0;\n  padding:20px;\n  cursor:pointer;\n  position:absolute;\n  background:#c9c9c9 url(../img/icon-color.png) center no-repeat;\n}\n\n.theme-panel > .toggler:hover {\n  background-color: #3d3d3d !important;\n}\n\n.theme-panel > .toggler-close {\n  display: none;\n  top:4px;\n  right:0;\n  padding:20px;\n  cursor:pointer;\n  position:absolute;\n  background: #3d3d3d url(../img/icon-color-close.png) center no-repeat !important;\n}\n\n.theme-panel > .toggler-close:hover {\n  background-color:#222 !important;\n}\n\n.theme-panel > .theme-options {\n  top:4px;\n  right:40px;\n  display:none;\n  position:absolute;\n  background:#3d3d3d;\n}\n\n.theme-panel > .theme-options > .theme-option {\n  color:#cfcfcf;\n  padding: 15px;\n  border-top:1px solid #585858;\n  margin-top: 0px;\n  margin-bottom: 0px;\n}\n\n.theme-panel > .theme-options > .theme-option.theme-colors {\n  border-top: 0;\n}\n\n.theme-panel > .theme-options > .theme-option > span {  \n  text-transform:uppercase;\n  display: inline-block;\n  width: 85px;\n  font-size: 14px;\n}\n\n.theme-panel > .theme-options > .theme-option.theme-colors > span {\n  display: block;\n  width: auto;\n}\n\n.theme-panel > .theme-options > .theme-option > select.form-control {\n  display: inline;\n  width: 100px;\n  text-transform: lowercase;\n}\n\n.theme-panel > .theme-options > .theme-option.theme-colors > ul {\n  list-style:none;\n  padding: 0;\n  display: block;\n  margin-bottom: 1px !important;\n  margin-top: 10px;\n}\n\n.theme-panel > .theme-options > .theme-option.theme-colors > ul > li {\n  width:30px;\n  height:30px;\n  margin:0 4px;\n  cursor:pointer;\n  list-style:none;\n  float: left;\n  border:solid 1px #707070;\n}\n\n.theme-panel > .theme-options > .theme-option.theme-colors > ul > li:first-child {\n  margin-left: 0;\n}\n\n.theme-panel > .theme-options > .theme-option.theme-colors > ul > li:hover,\n.theme-panel > .theme-options > .theme-option.theme-colors > ul > li.current {\n  border:solid 2px #ebebeb;\n}\n\n.theme-panel > .theme-options > .theme-option.theme-colors > ul > li.color-black {\n  background:#333438;\n}\n\n.theme-panel > .theme-options > .theme-option.theme-colors > ul > li.color-grey {\n  background:#6d6d6d;\n}\n\n.theme-panel > .theme-options > .theme-option.theme-colors > ul > li.color-blue {\n  background:#124f94;\n}\n\n.theme-panel > .theme-options > .theme-option.theme-colors > ul > li.color-brown {\n  background:#623f18;\n}\n\n.theme-panel > .theme-options > .theme-option.theme-colors > ul > li.color-purple {\n  background:#701584;\n}\n\n.theme-panel > .theme-options > .theme-option.theme-colors > ul > li.color-white {\n  background:#fff;\n}\n\n/***\nTop bar menu\n***/\n\n/* enable arrow for dropdown menu */\n.header .nav > li > .dropdown-menu:before {\n  position: absolute;\n  top: -7px;\n  right: 9px;\n  display: inline-block !important;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-left: 7px solid transparent;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  content: '';\n}\n\n.header .nav > li > .dropdown-menu:after {\n  position: absolute;\n  top: -6px;\n  right: 10px;\n  display: inline-block !important;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #fff;\n  border-left: 6px solid transparent;\n  content: '';\n}\n\n/***\nHorezantal Menu(new in v1.2)\n***/\n\n.header .hor-menu {\n  margin: 0;\n  float: left;\n}\n\n.header .hor-menu ul.nav li a {\n  font-size: 14px;\n  padding: 11px 18px; \n}\n\n.header .hor-menu ul.nav li {\n  position: relative;\n}\n\n.header .hor-menu ul.nav li.active .selected {\n  left: 50%;\n  bottom:0;\n  position: absolute;\n  border-left: 6px solid transparent;\n  border-right: 6px solid transparent;\n  border-top: 6px solid #e02222;\n  display: inline-block;\n  margin: 0;\n  width: 0px;\n  height:0px;\n  margin-left: -7px;\n  margin-bottom:-6px;\n}\n\n/*drop-down*/\n.header .hor-menu .dropdown-menu {\n    margin-top: 0;\n    border: none;\n    box-shadow: none;\n}\n\n.header .hor-menu .dropdown-submenu > .dropdown-menu {\n  top: 0;\n}\n\n.header .hor-menu .dropdown-submenu > a:after {\n  top: 8px;\n  margin-right: 0px;\n} \n\n.header .hor-menu .dropdown-menu li > a {\n    padding: 7px 18px !important; \n    margin-bottom:1px;\n}\n\n.header .hor-menu .dropdown-menu .arrow {\n  display: none;\n}\n\n.header .hor-menu .dropdown-menu li > a:hover,\n.header .hor-menu .dropdown-menu li:hover > a,\n.header .hor-menu .dropdown-menu li.active > a {\n    filter:none !important;\n}\n\n.header .hor-menu .nav > li > .dropdown-menu:after,\n.header .hor-menu .nav > li > .dropdown-menu:before {\n    border-bottom: none !important;\n}\n\n/*search*/\n.header .hor-menu .hor-menu-search-form-toggler {\n    display: inline-block;\n    padding: 12px 22px 12px 22px !important;\n    cursor: pointer;\n    background: url(../img/hor-menu-search.png) no-repeat center;\n}\n\n.header .hor-menu .hor-menu-search-form-toggler:hover {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.header .hor-menu a.hor-menu-search-form-toggler-close {\n  display: none;\n}\n\n.header .hor-menu .search-form {\n  top:42px; \n  right:0px; \n  padding:8px; \n  display:none;\n  z-index:999; \n  position:absolute; \n}\n\n.header .hor-menu .search-form .btn {\n  padding: 7px 20px; \n  height: 32px;\n  width: 10px;\n  display: inline-block;\n}\n\n.header .hor-menu .search-form .btn:hover {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n\n.header .hor-menu .search-form form {\n  margin-bottom: 0;\n}\n\n.header .hor-menu .search-form form input {\n  background: none;\n  width: 200px;\n  border: none;\n}\n\n/***\nTop News Blocks(new in v1.2.2)\n***/\n.top-news {\n  color: #fff;\n  margin: 8px 0;\n}\n\n.top-news a,\n.top-news em,\n.top-news span {\n  display: block;\n  text-align: left;\n}\n\n.top-news a {\n  padding: 10px;\n  position: relative;\n  margin-bottom: 10px;\n}\n\n.top-news a .top-news-icon {\n  right: 8px;\n  bottom: 15px; \n  opacity:0.3; \n  font-size: 35px;\n  position: absolute;\n  filter: alpha(opacity=30); /*For IE8*/  \n}\n\n.top-news em {\n  margin-bottom: 0;\n  font-style: normal;\n}\n\n.top-news span {\n  font-size: 18px;\n  margin-bottom: 5px;\n}\n\n/***\nBlock Images(new in v1.2.2)\n***/\n.blog-images {\n  margin-bottom: 0;\n}\n\n.blog-images li {\n  padding: 0;\n  margin: 0;\n  display: inline;\n}\n\n.blog-images li a:hover {\n  text-decoration: none;\n}\n\n.blog-images li img {\n  width: 50px;\n  height: 50px;\n  opacity: 0.6;\n  margin: 0 2px 8px;\n}\n\n.blog-images li img:hover {\n  opacity: 1;\n  box-shadow: 0 0 0 4px #72c02c;\n  transition: all 0.4s ease-in-out 0s;\n  -moz-transition: all 0.4s ease-in-out 0s;\n  -webkit-transition: all 0.4s ease-in-out 0s;\n}\n\n/*Sidebar Tags*/\nul.sidebar-tags a {\n  color: #555;\n  font-size:12px;\n  padding:3px 5px;\n  background:#f7f7f7;\n  margin:0 2px 5px 0;\n  display:inline-block;\n}\n\nul.sidebar-tags a:hover,\nul.sidebar-tags a:hover i {\n  background: #EEE;\n  text-decoration:none;\n  -webkit-transition:all 0.3s ease-in-out;\n  -moz-transition:all 0.3s ease-in-out;\n  -o-transition:all 0.3s ease-in-out;\n  transition:all 0.3s ease-in-out;\n}\n\nul.sidebar-tags a i {\n  color:#777;\n}\n\nul.sidebar-tags li {\n  padding: 0;\n}\n\n/***\nSocial Icons(new in v1.2.2)\n***/\n.social-icons {\n  padding: 0;\n  margin:0;\n}\n\n.social-icons:after,\n.social-icons:before {  \n  content: \"\";\n  display: table;\n}\n\n.social-icons:after {    \n  clear: both;\n}\n\n.social-icons li {\n  float:left;\n  display:inline;\n  list-style:none;\n  margin-right:5px;\n  margin-bottom:5px;\n  text-indent:-9999px;\n}\n.social-icons li a, a.social-icon {\n  width:28px;\n  height:28px;\n  display:block;\n  background-position:0 0;\n  background-repeat:no-repeat;\n  transition: all 0.3s ease-in-out;\n  -o-transition: all 0.3s ease-in-out;\n  -ms-transition: all 0.3s ease-in-out;\n  -moz-transition: all 0.3s ease-in-out;\n  -webkit-transition: all 0.3s ease-in-out;\n}\n.social-icons li:hover a {\n  background-position:0 -38px;\n}\n\n.social-icons-color li a {\n  opacity: 0.7;\n  background-position:0 -38px !important;\n}\n\n.social-icons-color li a:hover {\n  opacity: 1;\n}\n\n.social-icons .amazon {background: url(../img/social/amazon.png) no-repeat;}\n.social-icons .behance {background: url(../img/social/behance.png) no-repeat;}\n.social-icons .blogger {background: url(../img/social/blogger.png) no-repeat;}\n.social-icons .deviantart {background: url(../img/social/deviantart.png) no-repeat;}\n.social-icons .dribbble {background: url(../img/social/dribbble.png) no-repeat;}\n.social-icons .dropbox {background: url(../img/social/dropbox.png) no-repeat;}\n.social-icons .evernote {background: url(../img/social/evernote.png) no-repeat;}\n.social-icons .facebook {background: url(../img/social/facebook.png) no-repeat;}\n.social-icons .forrst {background: url(../img/social/forrst.png) no-repeat;}\n.social-icons .github {background: url(../img/social/github.png) no-repeat;}\n.social-icons .googleplus {background: url(../img/social/googleplus.png) no-repeat;}\n.social-icons .jolicloud {background: url(../img/social/jolicloud.png) no-repeat;}\n.social-icons .last-fm {background: url(../img/social/last-fm.png) no-repeat;}\n.social-icons .linkedin {background: url(../img/social/linkedin.png) no-repeat;}\n.social-icons .picasa {background: url(../img/social/picasa.png) no-repeat;}\n.social-icons .pintrest {background: url(../img/social/pintrest.png) no-repeat;}\n.social-icons .rss {background: url(../img/social/rss.png) no-repeat;}\n.social-icons .skype {background: url(../img/social/skype.png) no-repeat;}\n.social-icons .spotify {background: url(../img/social/spotify.png) no-repeat;}\n.social-icons .stumbleupon {background: url(../img/social/stumbleupon.png) no-repeat;}\n.social-icons .tumblr {background: url(../img/social/tumblr.png) no-repeat;}\n.social-icons .twitter {background: url(../img/social/twitter.png) no-repeat;}\n.social-icons .vimeo {background: url(../img/social/vimeo.png) no-repeat;}\n.social-icons .wordpress {background: url(../img/social/wordpress.png) no-repeat;}\n.social-icons .xing {background: url(../img/social/xing.png) no-repeat;}\n.social-icons .yahoo {background: url(../img/social/yahoo.png) no-repeat;}\n.social-icons .youtube {background: url(../img/social/youtube.png) no-repeat;}\n.social-icons .vk {background: url(../img/social/vk.png) no-repeat;}\n.social-icons .instagram {background: url(../img/social/instagram.png) no-repeat;}\n.social-icons .reddit {background: url(../img/social/reddit.png) no-repeat;}\n\n/***\nInline Social Icons\n***/\n.social-icon {\n  display:inline-block !important;\n  width:28px;\n  height:28px;\n  background-position:0 0;\n  background-repeat:no-repeat;\n  transition: all 0.3s ease-in-out;\n  -o-transition: all 0.3s ease-in-out;\n  -ms-transition: all 0.3s ease-in-out;\n  -moz-transition: all 0.3s ease-in-out;\n  -webkit-transition: all 0.3s ease-in-out;\n}\n\n.social-icon.amazon {background: url(../img/social/amazon.png) no-repeat;}\n.social-icon.behance {background: url(../img/social/behance.png) no-repeat;}\n.social-icon.blogger {background: url(../img/social/blogger.png) no-repeat;}\n.social-icon.deviantart {background: url(../img/social/deviantart.png) no-repeat;}\n.social-icon.dribbble {background: url(../img/social/dribbble.png) no-repeat;}\n.social-icon.dropbox {background: url(../img/social/dropbox.png) no-repeat;}\n.social-icon.evernote {background: url(../img/social/evernote.png) no-repeat;}\n.social-icon.facebook {background: url(../img/social/facebook.png) no-repeat;}\n.social-icon.forrst {background: url(../img/social/forrst.png) no-repeat;}\n.social-icon.github {background: url(../img/social/github.png) no-repeat;}\n.social-icon.googleplus {background: url(../img/social/googleplus.png) no-repeat;}\n.social-icon.jolicloud {background: url(../img/social/jolicloud.png) no-repeat;}\n.social-icon.last-fm {background: url(../img/social/last-fm.png) no-repeat;}\n.social-icon.linkedin {background: url(../img/social/linkedin.png) no-repeat;}\n.social-icon.picasa {background: url(../img/social/picasa.png) no-repeat;}\n.social-icon.pintrest {background: url(../img/social/pintrest.png) no-repeat;}\n.social-icon.rss {background: url(../img/social/rss.png) no-repeat;}\n.social-icon.skype {background: url(../img/social/skype.png) no-repeat;}\n.social-icon.spotify {background: url(../img/social/spotify.png) no-repeat;}\n.social-icon.stumbleupon {background: url(../img/social/stumbleupon.png) no-repeat;}\n.social-icon.tumblr {background: url(../img/social/tumblr.png) no-repeat;}\n.social-icon.twitter {background: url(../img/social/twitter.png) no-repeat;}\n.social-icon.vimeo {background: url(../img/social/vimeo.png) no-repeat;}\n.social-icon.wordpress {background: url(../img/social/wordpress.png) no-repeat;}\n.social-icon.xing {background: url(../img/social/xing.png) no-repeat;}\n.social-icon.yahoo {background: url(../img/social/yahoo.png) no-repeat;}\n.social-icon.youtube {background: url(../img/social/youtube.png) no-repeat;}\n.social-icon.vk {background: url(../img/social/vk.png) no-repeat;}\n.social-icon.instagram {background: url(../img/social/instagram.png) no-repeat;}\n.social-icon.reddit {background: url(../img/social/reddit.png) no-repeat;}\n\n.social-icon:hover {\n  background-position:0 -38px;\n}\n\n.social-icon-color {\n  opacity: 0.7;\n  background-position:0 -38px !important;\n}\n\n.social-icon-color:hover {\n  opacity: 1;\n}\n\n\n/***\nNotes\n***/\n\n/* Common styles for all types */\n.note {\n  margin: 0 0 20px 0;\n  padding: 15px 30px 15px 15px;\n  border-left: 5px solid #eee;\n}\n\n.note h1,\n.note h2,\n.note h3,\n.note h4 {\n  margin-top: 0;\n}\n\n.note p:last-child {\n  margin-bottom: 0;\n}\n.note code,\n.note .highlight {\n  background-color: #fff;\n}\n\n/* Variations */\n.note-danger {\n  background-color: #FAEAE6;\n  border-color: #ed4e2a;\n}\n\n.note-warning {\n  background-color: #FCF3E1;\n  border-color: #fcb322;\n}\n\n.note-info {\n  background-color: #E8F6FC;\n  border-color: #57b5e3;\n}\n\n.note-success {\n  background-color: #EBFCEE;\n  border-color: #3cc051;\n}\n\n/***\nDemo Utils\n***/\n.scrollspy-example {\n  position: relative;\n  height: 200px;\n  margin-top: 10px;\n  overflow: auto;\n}\n\n.util-btn-margin-bottom-5 .btn {\n  margin-bottom: 5px !important;\n}\n\n.util-btn-group-margin-bottom-5 .btn-group {\n  margin-bottom: 5px !important;\n}\n\n.fontawesome-demo i {\n  font-size: 18px;\n}\n\n.fontawesome-demo li {\n  padding-top: 5px;\n  padding-bottom: 5px;\n}\n\n.glyphicons-demo ul {\n  padding-left: 0;\n  padding-bottom: 1px;\n  margin-bottom: 20px;\n  list-style: none;\n  overflow: hidden;\n}\n\n.bs-glyphicons {\n  padding-left: 0;\n  padding-bottom: 1px;\n  margin-bottom: 20px;\n  list-style: none;\n  overflow: hidden;\n}\n.glyphicons-demo ul li {\n  float: left;\n  width: 25%;\n  height: 115px;\n  padding: 10px;\n  margin: 0 -1px -1px 0;\n  font-size: 12px;\n  line-height: 1.4;\n  text-align: center;\n  border: 1px solid #ddd;\n}\n\n.glyphicons-demo .glyphicon {\n  display: block;\n  margin: 5px auto 10px;\n  font-size: 24px;\n}\n.glyphicons-demo ul li:hover {\n  background-color: rgba(86,61,124,.1);\n}\n\n@media (min-width: 768px) {\n  .glyphicons-demo ul li {\n    width: 12.5%;\n  }\n}\n\n\n/***\nForms \n****/\n\ninput.placeholder,\ntextarea.placeholder {\n  color: #aaa !important;\n}\n\n.help-block {\n margin-top: 5px;\n margin-bottom: 5px;\n}\n\n.form-inline input {\n  margin-bottom: 0px !important;\n}\n\n.control-label {\n  margin-top: 2px;\n}\n\n.form-control-static {\n  font-size: 14px;\n  padding-top: 7px;\n}\n\n.control-label .required {\n  color: #e02222;\n  font-size: 12px;\n  padding-left: 2px;\n}\n\n.switch-wrapper {\n   display: inline-block;\n}\n\n.form {\n  padding: 0 !important;\n}\n\n.form-body {\n  padding: 10px;\n}\n\n.form-actions {\n  padding: 20px 10px;\n  margin-top: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n\n.form-actions.nobg {\n  background-color: transparent;\n}\n\n.form-actions.top {\n  margin-top: 0;\n  margin-bottom: 20px;\n  border-top: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\n.form-actions.fluid {\n  padding: 20px 0;\n}\n\n.form-actions.fluid > [class^=\"col-\"] {\n  padding-left: 13px;\n}\n\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  line-height: 0;\n  content: \"\";\n}\n\n.form-actions:after {\n  clear: both;\n}\n\n.form-section {\n  margin: 30px 0px 25px 0px;\n  padding-bottom: 5px;\n  border-bottom: 1px solid #eee;\n}\n\n.form .form-section:first-child {\n  margin-top: 5px;\n}\n\n.help-inline {\n  font-size: 13px;\n  color: #737373;\n  display: inline-block;\n  padding: 5px;\n}\n\n/* left, right aligned form actions */\n.form-actions.right {\n  padding-left: 0;\n  padding-right: 10px;\n  text-align: right;\n}\n\n.form-actions.left {\n  padding-left: 10px;\n  padding-right: 0;\n  text-align: left;\n}\n\n/* Checkboxes */\n.form-group .checkbox {\n  padding-left: 0;\n}\n\n.checkbox-list > label {\n  display: block;\n}\n\n.checkbox-list > label.checkbox-inline {\n  display: inline-block;\n}\n\n.checkbox-list > label.checkbox-inline:first-child {\n  padding-left: 0;\n}\n\n/* Radios */\n\n.radio-list > label {\n  display: block;\n}\n\n.radio-list > label.radio-inline {\n  display: inline-block;\n}\n\n.radio-list > label.radio-inline:first-child {\n  padding-left: 0;\n}\n\n.form-horizontal .radio-list .radio {\n  padding-top: 1px;\n}\n\n/* Rows seperated form layout */\n.form-row-seperated .form-group {\n  margin: 0;\n  border-bottom: 1px solid #efefef;\n  padding: 10px 10px 10px 0px;\n}\n\n.form-row-seperated .form-group.last {\n  border-bottom: 0;\n  margin-bottom: 0;\n  padding-bottom: 10px;\n}\n\n.form-row-seperated .form-actions {\n  margin-top: 0;\n}\n\n.form-row-seperated .form-body {\n  padding: 0;\n  margin-top: 0;\n}\n\n.form-row-seperated .help-block {\n  margin-bottom: 0;\n}\n\n/* form bordered */\n.form-bordered .form-body {\n  margin: 0;\n  padding: 0;\n}\n\n.form-bordered .form-actions {\n  margin-top: 0;\n}\n\n.form-bordered .form-group {\n    margin: 0;\n    border-bottom: 1px solid #efefef;\n}\n\n.form-bordered .form-group.last {\n    border-bottom: 0;\n}\n\n.form-bordered .help-block {\n  margin-bottom: 0;\n}\n\n.form-bordered .control-label {\n  padding-top: 16px;\n}\n\n.form-bordered .form-group > div {  \n  padding: 10px;\n  border-left: 1px solid #efefef;\n}\n\n.form-bordered .form-actions.fluid > .row > div {\n  padding-left: 10px;\n}\n\n.form-horizontal.form-bordered.form-row-stripped .form-group:nth-child(even) {\n  background-color: #fcfcfc;\n}\n\n.form-horizontal.form-bordered.form-label-stripped .form-group:nth-child(even) {\n  background-color: #fcfcfc;\n} \n\n.form-horizontal.form-bordered.form-row-stripped .form-control {\n  background: #fff !important;\n}\n\n.form-horizontal.form-bordered.form-label-stripped .form-group:nth-child(even) > div {\n  background-color: #ffffff;  \n}\n\n/***\nBordered form layout\n***/\n\n.form-bordered .form-control {\n  margin: 0;\n}\n\n\n/***\nDisabled Menu Link\n***/\n\n.disabled-link > a > span.text,\n.disabled-link > a > span.title {\n  font-style: italic !important;\n  color: #888 !important;\n}\n\n.disabled-link > a:hover  {\n  cursor: not-allowed !important;\n}\n\n\n/***\nResponsive & Scrollable Tables\n***/\n\n.table-scrollable {\n  width: 100%;\n  overflow-x: auto;\n  overflow-y: hidden;\n  border: 1px solid #dddddd;\n  margin: 10px 0 !important;\n}\n\n.table-scrollable > .table {\n  width: 100% !important;\n  margin: 0 !important;\n  margin-bottom: 0;\n  background-color: #fff;\n}\n\n.table-scrollable > .table > thead > tr > th,\n.table-scrollable > .table > tbody > tr > th,\n.table-scrollable > .table > tfoot > tr > th,\n.table-scrollable > .table > thead > tr > td,\n.table-scrollable > .table > tbody > tr > td,\n.table-scrollable > .table > tfoot > tr > td {\n  white-space: nowrap;\n}\n\n.table-scrollable > .table-bordered {\n  border: 0;\n}\n\n.table-scrollable > .table-bordered > thead > tr > th:first-child,\n.table-scrollable > .table-bordered > tbody > tr > th:first-child,\n.table-scrollable > .table-bordered > tfoot > tr > th:first-child,\n.table-scrollable > .table-bordered > thead > tr > td:first-child,\n.table-scrollable > .table-bordered > tbody > tr > td:first-child,\n.table-scrollable > .table-bordered > tfoot > tr > td:first-child {\n  border-left: 0;\n}\n\n.table-scrollable > .table-bordered > thead > tr > th:last-child,\n.table-scrollable > .table-bordered > tbody > tr > th:last-child,\n.table-scrollable > .table-bordered > tfoot > tr > th:last-child,\n.table-scrollable > .table-bordered > thead > tr > td:last-child,\n.table-scrollable > .table-bordered > tbody > tr > td:last-child,\n.table-scrollable > .table-bordered > tfoot > tr > td:last-child {\n  border-right: 0;\n}\n\n.table-scrollable > .table-bordered > thead > tr:last-child > th,\n.table-scrollable > .table-bordered > tbody > tr:last-child > th,\n.table-scrollable > .table-bordered > tfoot > tr:last-child > th,\n.table-scrollable > .table-bordered > thead > tr:last-child > td,\n.table-scrollable > .table-bordered > tbody > tr:last-child > td,\n.table-scrollable > .table-bordered > tfoot > tr:last-child > td {\n  border-bottom: 0;\n}\n\n/***\nResponsive Flip Scroll Tables\n***/\n\n.flip-scroll table { width: 100%; }\n\n@media only screen and (max-width: 800px) {\n  \n  .flip-scroll .flip-content:after { visibility: hidden; display: block; font-size: 0; content: \" \"; clear: both; height: 0; }\n  .flip-scroll * html .flip-content { zoom: 1; }\n  .flip-scroll *:first-child+html .flip-content { zoom: 1; }\n  \n  .flip-scroll table { width: 100%; border-collapse: collapse; border-spacing: 0; }\n \n  .flip-scroll th,\n  .flip-scroll td { margin: 0; vertical-align: top; }\n  .flip-scroll th { \n    text-align: left; \n    border: 0 !important; \n    border-bottom: 1px solid #ddd !important; \n    border-right: 1px solid #ddd !important; \n    font-size: 13px !important;\n    padding: 5px;\n    width: auto !important;\n  }\n  \n  .flip-scroll table { display: block; position: relative; width: 100%; }\n  .flip-scroll thead { \n    display: block; \n    float: left; \n  }\n  .flip-scroll tbody { \n    display: block; \n    width: auto; \n    position: relative; \n    overflow-x: auto; \n    white-space: nowrap;     \n  }\n  .flip-scroll thead tr { display: block; }\n  .flip-scroll th { display: block; text-align: right; }\n  .flip-scroll tbody tr { display: inline-block; vertical-align: top; margin-left: -5px; }\n  .flip-scroll td { display: block; min-height: 1.25em; text-align: left; border-top: 0 !important; border-left: 0 !important; border-right: 0 !important} \n \n  /* sort out borders */\n \n  .flip-scroll th { border-bottom: 0; border-left: 0; }\n  .flip-scroll td { border-left: 0; border-right: 0; border-bottom: 0; }\n  .flip-scroll tbody tr { border-left: 1px solid #ddd; }\n  .flip-scroll th:last-child,\n  .flip-scroll td:last-child { border-bottom: 1px solid #ddd; }\n  \n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/css/themes/blue.css",
    "content": "/***\nBlue theme\n***/\n/***\nReset and overrides  \n***/\nbody {\n  background-color: #1570a6 !important;\n}\n/***\nPage header\n***/\n.header {\n  filter: none !important;\n  background-image: none !important;\n  background-color: #0f4e74 !important;\n}\n.header .btn-navbar {\n  background-color: #0f4e74 !important;\n}\n.header .navbar-nav .dropdown-toggle:hover,\n.header .navbar-nav .dropdown.open .dropdown-toggle {\n  color: #fff;\n  background-color: #146a9d !important;\n}\n.header .navbar-nav li.dropdown .dropdown-toggle i {\n  color: #68bbec !important;\n}\n/***\nHor menu\n***/\n.header .hor-menu ul.nav li a {\n  color: #ccc;\n}\n\n.header .hor-menu ul.nav li.open > a,\n.header .hor-menu ul.nav li > a:hover,\n.header .hor-menu ul.nav li > a:focus {\n  color: #fff;\n  background: #146a9d;\n}\n\n.header .hor-menu .dropdown-menu li:hover > a,\n.header .hor-menu ul.nav li.active > a,\n.header .hor-menu ul.nav li.active > a:hover {\n  color: #fff;\n  background: #e02222 !important; \n}\n\n.header .hor-menu .dropdown-menu {  \n    background: #146a9d;\n}\n.header .hor-menu .dropdown-menu li > a {    \n    color: #ccc;\n}\n\n.header .hor-menu .hor-menu-search-form-toggler.off {\n   background: #146a9d url(../../img/hor-menu-search-close-white.png) no-repeat center;\n}\n\n.header .hor-menu .search-form {  \n  background:#146a9d; \n}\n\n.header .hor-menu .search-form form input {\n  color: #ccc;\n}\n\n.header .hor-menu .search-form .btn {\n  color: #ccc;\n  background: url(../../img/search-icon-white.png) no-repeat center;\n}\n\n.header .hor-menu .search-form form input::-webkit-input-placeholder { /* WebKit browsers */\n    color: #ccc;\n}\n.header .hor-menu .search-form form input:-moz-placeholder { /* Mozilla Firefox 4 to 18 */\n    color: #ccc;\n}\n.header .hor-menu .search-form form input::-moz-placeholder { /* Mozilla Firefox 19+ */\n    color: #ccc;\n}\n.header .hor-menu .search-form form input:-ms-input-placeholder { /* Internet Explorer 10+ */\n    color: #ccc;\n}\n\n/***\nPage sidebar\n***/\n.page-sidebar {\n  background-color: #1570a6;\n}\nul.page-sidebar-menu > li > a {\n  border-top: 1px solid #1c95dc !important;\n  color: #ffffff !important;\n}\nul.page-sidebar-menu > li:last-child > a {\n  border-bottom: 1px solid transparent !important;\n}\nul.page-sidebar-menu > li a i {\n  color: #7fc5ef;\n}\nul.page-sidebar-menu > li.open > a,\nul.page-sidebar-menu > li > a:hover,\nul.page-sidebar-menu > li:hover > a {\n  background: #12618f;\n}\nul.page-sidebar-menu > li.active > a {\n  background: #cc1d1d !important;\n  border-top-color: transparent !important;\n  color: #ffffff;\n}\nul.page-sidebar-menu > li.active > a i {\n  color: #ffffff;\n}\nul.page-sidebar-menu > li > ul.sub-menu > li:first-child > a {\n  border-top: 0px !important;\n}\nul.page-sidebar-menu > li > ul.sub-menu > li.active > a,\nul.page-sidebar-menu > li > ul.sub-menu > li > a:hover {\n  color: #ffffff !important;\n  background: #1b8fd3 !important;\n}\nul.page-sidebar-menu > li > ul.sub-menu > li > a:hover {\n  background: #1b8fd3 !important;\n}\n/* 3rd level sub menu */\nul.page-sidebar-menu > li > ul.sub-menu li > ul.sub-menu > li.active > a,\nul.page-sidebar-menu > li > ul.sub-menu li > ul.sub-menu > li > a:hover,\nul.page-sidebar-menu > li > ul.sub-menu li.open > a {\n  color: #ffffff !important;\n  background: #1b8fd3 !important;\n}\n/* font color for all sub menu links*/\nul.page-sidebar-menu li > ul.sub-menu > li > a {\n  color: #c3e4f7;\n}\n/* menu arrows */\nul.page-sidebar-menu > li > a .arrow:before,\nul.page-sidebar-menu > li > a .arrow.open:before {\n  color: #51b1e9 !important;\n}\nul.page-sidebar-menu > li > ul.sub-menu a .arrow:before,\nul.page-sidebar-menu > li > ul.sub-menu a .arrow.open:before {\n  color: #3ba6e6 !important;\n}\nul.page-sidebar-menu > li > a > .arrow.open:before {\n  color: #68bbec !important;\n}\nul.page-sidebar-menu > li.active > a .arrow:before,\nul.page-sidebar-menu > li.active > a .arrow.open:before {\n  color: #ffffff !important;\n}\n/* sidebar search */\n.page-sidebar .sidebar-search input {\n  background-color: #0f5179 !important;\n  color: #51b1e9;\n}\n.page-sidebar .sidebar-search input::-webkit-input-placeholder {\n  color: #51b1e9 !important;\n}\n.page-sidebar .sidebar-search input:-moz-placeholder {\n  color: #51b1e9 !important;\n}\n.page-sidebar .sidebar-search input:-ms-input-placeholder {\n  color: #51b1e9 !important;\n}\n.page-sidebar .sidebar-search input {\n  background-color: #1570a6 !important;\n  color: #bfbfbf !important;\n}\n.page-sidebar .sidebar-search .input-box {\n  border-bottom: 1px solid #51b1e9 !important;\n}\n.page-sidebar .sidebar-search .submit {\n  background-image: url(../../img/search-icon-blue.png);\n}\n/***\nSidebar toggler\n***/\n.sidebar-toggler {\n  background-image: url(../../img/sidebar-toggler-blue.jpg);\n  background-color: #0f5179;\n}\n/* search box bg color on expanded */\n.page-sidebar-closed .page-sidebar .sidebar-search.open .form-container {\n  background-color: #1570a6 !important;\n}\n.page-sidebar-closed .page-sidebar .sidebar-search.open .form-container .remove {\n  background-image: url(\"../../img/sidebar-search-close-blue.png\");\n}\n/* sub menu bg color on hover menu item */\n.page-sidebar-closed ul.page-sidebar-menu > li:hover .sub-menu {\n  background-color: #1570a6;\n}\n/***\nFooter \n***/\n.footer .footer-inner {\n  color: #68bbec;\n}\n.footer .footer-tools .go-top {\n  background-color: #1985c6;\n}\n.footer .footer-tools .go-top:hover {\n  opacity: 0.7;\n  filter: alpha(opacity=70);\n}\n.footer .footer-tools .go-top i {\n  color: #68bbec;\n}\n/***\nFooter Layouts (new in v1.3)\n***/\n/* begin:fixed footer */\n.page-footer-fixed .footer {\n  background-color: #0f5179;\n}\n.page-footer-fixed .footer .footer-inner {\n  color: #68bbec;\n}\n.page-footer-fixed .footer .footer-tools .go-top {\n  background-color: #1985c6;\n}\n.page-footer-fixed .footer .footer-tools .go-top i {\n  color: #68bbec;\n}\n/* end:fixed footer */\n/***\nGritter Notifications \n***/\n.gritter-top {\n  background: url(../../plugins/gritter/images/gritter-blue.png) no-repeat left -30px !important;\n}\n.gritter-bottom {\n  background: url(../../plugins/gritter/images/gritter-blue.png) no-repeat left bottom !important;\n}\n.gritter-item {\n  display: block;\n  background: url(../../plugins/gritter/images/gritter-blue.png) no-repeat left -40px !important;\n}\n.gritter-close {\n  background: url(../../plugins/gritter/images/gritter-blue.png) no-repeat left top !important;\n}\n.gritter-title {\n  text-shadow: none !important;\n  /* Not supported by IE :( */\n\n}\n/* for the light (white) version of the gritter notice */\n.gritter-light .gritter-item,\n.gritter-light .gritter-bottom,\n.gritter-light .gritter-top,\n.gritter-light .gritter-close {\n  background-image: url(../../plugins/gritter/images/gritter-light.png) !important;\n}\n.gritter-item-wrapper a {\n  color: #18a5ed;\n}\n.gritter-item-wrapper a:hover {\n  color: #0b6694;\n}\n/* begin: boxed page */\n@media (min-width: 992px) {\n  .page-boxed {\n    background-color: #125e8b !important;\n  }\n  .page-boxed .page-container {\n    background-color: #1570a6;\n    border-left: 1px solid #1c98e1;\n    border-bottom: 1px solid #1c98e1;\n  }\n  .page-boxed.page-sidebar-fixed .page-container {\n    border-left: 0;\n    border-bottom: 0;\n  }\n  .page-boxed.page-sidebar-fixed .page-sidebar {\n    border-left: 1px solid #1c98e1;\n  }\n  .page-boxed.page-sidebar-fixed.page-footer-fixed .footer {\n    background-color: #125e8b !important;\n  }\n}\n/* end: boxed page */\n/***\nLandscape phone to portrait tablet\n***/\n@media (max-width: 991px) {\n  /***\n    page sidebar\n    ***/\n  .page-sidebar {\n    background-color: #105882 !important;\n  }\n  ul.page-sidebar-menu > li > a {\n    border-top: 1px solid #187fbd !important;\n  }\n  ul.page-sidebar-menu > li:last-child > a {\n    border-bottom: 0 !important;\n  }\n  .page-sidebar .sidebar-search input {\n    background-color: #105882 !important;\n  }\n  ul.page-sidebar-menu > li.open > a,\n  ul.page-sidebar-menu > li > a:hover,\n  ul.page-sidebar-menu > li:hover > a {\n    background: #0e4b70;\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/css/themes/brown.css",
    "content": "/***\nBrown theme\n***/\n/***\nReset and overrides  \n***/\nbody {\n  background-color: #623f18 !important;\n}\n/***\nPage header\n***/\n.header {\n  filter: none !important;\n  background-image: none !important;\n  background-color: #35220d !important;\n}\n.header .btn-navbar {\n  background-color: #35220d !important;\n}\n.header .navbar-nav .dropdown-toggle:hover,\n.header .navbar-nav .dropdown.open .dropdown-toggle {\n  background-color: #5a3a16 !important;\n}\n.header .navbar-nav li.dropdown .dropdown-toggle i {\n  color: #d18d42 !important;\n}\n/***\nHor menu\n***/\n.header .hor-menu ul.nav li a {\n  color: #ccc;\n}\n\n.header .hor-menu ul.nav li.open > a,\n.header .hor-menu ul.nav li > a:hover,\n.header .hor-menu ul.nav li > a:focus {\n  color: #fff;\n  background: #5a3a16;\n}\n\n.header .hor-menu .dropdown-menu li:hover > a,\n.header .hor-menu ul.nav li.active > a,\n.header .hor-menu ul.nav li.active > a:hover {\n  color: #fff;\n  background: #e02222 !important; \n}\n\n.header .hor-menu .dropdown-menu {  \n    background: #5a3a16;\n}\n.header .hor-menu .dropdown-menu li > a {    \n    color: #ccc;\n}\n\n.header .hor-menu .hor-menu-search-form-toggler.off {\n   background: #5a3a16 url(../../img/hor-menu-search-close-white.png) no-repeat center;\n}\n\n.header .hor-menu .search-form {  \n  background:#5a3a16; \n}\n\n.header .hor-menu .search-form form input {\n  color: #ccc;\n}\n\n.header .hor-menu .search-form .btn {\n  color: #ccc;\n  background: url(../../img/search-icon-white.png) no-repeat center;\n}\n\n.header .hor-menu .search-form form input::-webkit-input-placeholder { /* WebKit browsers */\n    color: #ccc;\n}\n.header .hor-menu .search-form form input:-moz-placeholder { /* Mozilla Firefox 4 to 18 */\n    color: #ccc;\n}\n.header .hor-menu .search-form form input::-moz-placeholder { /* Mozilla Firefox 19+ */\n    color: #ccc;\n}\n.header .hor-menu .search-form form input:-ms-input-placeholder { /* Internet Explorer 10+ */\n    color: #ccc;\n}\n/***\nPage sidebar\n***/\n.page-sidebar {\n  background-color: #623f18;\n}\nul.page-sidebar-menu > li > a {\n  border-top: 1px solid #935f24 !important;\n  color: #ffffff !important;\n}\nul.page-sidebar-menu > li:last-child > a {\n  border-bottom: 1px solid transparent !important;\n}\nul.page-sidebar-menu > li a i {\n  color: #9a6d3a;\n}\nul.page-sidebar-menu > li.open > a,\nul.page-sidebar-menu > li > a:hover,\nul.page-sidebar-menu > li:hover > a {\n  background: #4e3112;\n}\nul.page-sidebar-menu > li.active > a {\n  background: #4e3112 !important;\n  border-top-color: transparent !important;\n  color: #ffffff;\n}\nul.page-sidebar-menu > li.active > a i {\n  color: #ffffff;\n}\nul.page-sidebar-menu > li > ul.sub-menu > li:first-child > a {\n  border-top: 0px !important;\n}\nul.page-sidebar-menu > li > ul.sub-menu > li.active > a,\nul.page-sidebar-menu > li > ul.sub-menu > li > a:hover {\n  color: #ffffff !important;\n  background: #8b5922 !important;\n}\nul.page-sidebar-menu > li > ul.sub-menu > li > a:hover {\n  background: #8b5922 !important;\n}\n/* 3rd level sub menu */\nul.page-sidebar-menu > li > ul.sub-menu li > ul.sub-menu > li.active > a,\nul.page-sidebar-menu > li > ul.sub-menu li > ul.sub-menu > li > a:hover,\nul.page-sidebar-menu > li > ul.sub-menu li.open > a {\n  color: #ffffff !important;\n  background: #8b5922 !important;\n}\n/* font color for all sub menu links*/\nul.page-sidebar-menu li > ul.sub-menu > li > a {\n  color: #e5bf94;\n}\n/* menu arrows */\nul.page-sidebar-menu > li > a .arrow:before,\nul.page-sidebar-menu > li > a .arrow.open:before {\n  color: #c88131 !important;\n}\nul.page-sidebar-menu > li > ul.sub-menu a .arrow:before,\nul.page-sidebar-menu > li > ul.sub-menu a .arrow.open:before {\n  color: #b4742c !important;\n}\nul.page-sidebar-menu > li > a > .arrow.open:before {\n  color: #d18d42 !important;\n}\nul.page-sidebar-menu > li.active > a .arrow:before,\nul.page-sidebar-menu > li.active > a .arrow.open:before {\n  color: #ffffff !important;\n}\n/* sidebar search */\n.page-sidebar .sidebar-search input {\n  background-color: #39250e !important;\n  color: #b18d65;\n}\n.page-sidebar .sidebar-search input::-webkit-input-placeholder {\n  color: #b18d65 !important;\n}\n.page-sidebar .sidebar-search input:-moz-placeholder {\n  color: #b18d65 !important;\n}\n.page-sidebar .sidebar-search input:-ms-input-placeholder {\n  color: #b18d65 !important;\n}\n.page-sidebar .sidebar-search input {\n  background-color: #623f18 !important;\n  color: #b18d65 !important;\n}\n.page-sidebar .sidebar-search .input-box {\n  border-bottom: 1px solid #845f36 !important;\n}\n.page-sidebar .sidebar-search .submit {\n  background-image: url(../../img/search-icon-brown.png);\n}\n/***\nSidebar toggler\n***/\n.sidebar-toggler {\n  background-image: url(../../img/sidebar-toggler-brown.jpg);\n  background-color: #39250e;\n}\n/* search box bg color on expanded */\n.page-sidebar-closed .page-sidebar .sidebar-search.open .form-container {\n  background-color: #623f18 !important;\n}\n.page-sidebar-closed .page-sidebar .sidebar-search.open .form-container .remove {\n  background-image: url(\"../../img/sidebar-search-close-brown.png\");\n}\n/* sub menu bg color on hover menu item */\n.page-sidebar-closed ul.page-sidebar-menu > li:hover .sub-menu {\n  background-color: #623f18;\n}\n/***\nFooter \n***/\n.footer .footer-inner {\n  color: #999999;\n}\n.footer .footer-tools .go-top {\n  background-color: #7f511f;\n}\n.footer .footer-tools .go-top:hover {\n  opacity: 0.7;\n  filter: alpha(opacity=70);\n}\n.footer .footer-tools .go-top i {\n  color: #d18d42;\n}\n/***\nFooter Layouts (new in v1.3)\n***/\n/* begin:fixed footer */\n.page-footer-fixed .footer {\n  background-color: #39250e;\n}\n.page-footer-fixed .footer .footer-inner {\n  color: #999999;\n}\n.page-footer-fixed .footer .footer-tools .go-top {\n  background-color: #7f511f;\n}\n.page-footer-fixed .footer .footer-tools .go-top i {\n  color: #d18d42;\n}\n/* end:fixed footer */\n/***\nGritter Notifications \n***/\n.gritter-top {\n  background: url(../../plugins/gritter/images/gritter-brown.png) no-repeat left -30px !important;\n}\n.gritter-bottom {\n  background: url(../../plugins/gritter/images/gritter-brown.png) no-repeat left bottom !important;\n}\n.gritter-item {\n  display: block;\n  background: url(../../plugins/gritter/images/gritter-brown.png) no-repeat left -40px !important;\n}\n.gritter-close {\n  background: url(../../plugins/gritter/images/gritter-brown.png) no-repeat left top !important;\n}\n.gritter-title {\n  text-shadow: none !important;\n  /* Not supported by IE :( */\n\n}\n/* for the light (white) version of the gritter notice */\n.gritter-light .gritter-item,\n.gritter-light .gritter-bottom,\n.gritter-light .gritter-top,\n.gritter-light .gritter-close {\n  background-image: url(../../plugins/gritter/images/gritter-light.png) !important;\n}\n.gritter-item-wrapper a {\n  color: #b18d65;\n}\n.gritter-item-wrapper a:hover {\n  color: #755a3b;\n}\n/* begin: boxed page */\n@media (min-width: 992px) {\n  .page-boxed {\n    background-color: #492f12 !important;\n  }\n  .page-boxed .page-container {\n    background-color: #623f18;\n    border-left: 1px solid #976125;\n    border-bottom: 1px solid #976125;\n  }\n  .page-boxed.page-sidebar-fixed .page-container {\n    border-left: 0;\n    border-bottom: 0;\n  }\n  .page-boxed.page-sidebar-fixed .page-sidebar {\n    border-left: 1px solid #976125;\n  }\n  .page-boxed.page-sidebar-fixed.page-footer-fixed .footer {\n    background-color: #492f12 !important;\n  }\n}\n/* end: boxed page */\n/***\nLandscape phone to portrait tablet\n***/\n@media (max-width: 991px) {\n  /***\n    page sidebar\n    ***/\n  .page-sidebar {\n    background-color: #412a10 !important;\n  }\n  ul.page-sidebar-menu > li > a {\n    border-top: 1px solid #764c1d !important;\n  }\n  ul.page-sidebar-menu > li:last-child > a {\n    border-bottom: 0 !important;\n  }\n  .page-sidebar .sidebar-search input {\n    background-color: #412a10 !important;\n  }\n  ul.page-sidebar-menu > li.open > a,\n  ul.page-sidebar-menu > li > a:hover,\n  ul.page-sidebar-menu > li:hover > a {\n    background: #311f0c;\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/css/themes/default.css",
    "content": "/***\nDefault theme\n***/\n\n/***\nReset and overrides  \n***/\nbody {\n  background-color: #3d3d3d !important;\n}\n/***\nPage header\n***/\n.header {\n  filter: none !important;\n  background-image: none !important;\n  background-color: #212121 !important;\n}\n.header .btn-navbar {\n  background-color: #212121 !important;\n}\n.header .navbar-nav .dropdown-toggle:hover,\n.header .navbar-nav .dropdown.open .dropdown-toggle {\n  background-color: #383838 !important;\n}\n.header .navbar-nav li.dropdown .dropdown-toggle i {\n  color: #8a8a8a !important;\n}\n/***\nHor menu\n***/\n.header .hor-menu ul.nav li a {\n  color: #999;\n}\n\n.header .hor-menu ul.nav li.open > a,\n.header .hor-menu ul.nav li > a:hover,\n.header .hor-menu ul.nav li > a:focus {\n  color: #fff;\n  background: #383838;\n}\n\n.header .hor-menu .dropdown-menu li:hover > a,\n.header .hor-menu ul.nav li.active > a,\n.header .hor-menu ul.nav li.active > a:hover {\n  color: #fff;\n  background: #e02222 !important; \n}\n\n.header .hor-menu .dropdown-menu {  \n    background: #383838;\n}\n.header .hor-menu .dropdown-menu li > a {    \n    color: #999;\n}\n\n.header .hor-menu .hor-menu-search-form-toggler.off {\n   background: #383838 url(../../img/hor-menu-search-close.png) no-repeat center;\n}\n\n.header .hor-menu .search-form {  \n  background:#383838; \n}\n\n.header .hor-menu .search-form form input {\n  color: #999;\n}\n\n.header .hor-menu .search-form .btn {\n  color: #999;\n  background: url(../../img/search-icon.png) no-repeat center;\n}\n\n.header .hor-menu .search-form form input::-webkit-input-placeholder { /* WebKit browsers */\n    color: #999;\n}\n.header .hor-menu .search-form form input:-moz-placeholder { /* Mozilla Firefox 4 to 18 */\n    color: #999;\n}\n.header .hor-menu .search-form form input::-moz-placeholder { /* Mozilla Firefox 19+ */\n    color: #999;\n}\n.header .hor-menu .search-form form input:-ms-input-placeholder { /* Internet Explorer 10+ */\n    color: #999;\n}\n\n/***\nPage sidebar\n***/\n.page-sidebar {\n  background-color: #3d3d3d;\n}\nul.page-sidebar-menu > li > a {\n  border-top: 1px solid #5c5c5c !important;\n  color: #ffffff !important;\n}\nul.page-sidebar-menu > li:last-child > a {\n  border-bottom: 1px solid transparent !important;\n}\nul.page-sidebar-menu > li a i {\n  color: #969696;\n}\nul.page-sidebar-menu > li.open > a,\nul.page-sidebar-menu > li > a:hover,\nul.page-sidebar-menu > li:hover > a {\n  background: #303030;\n}\nul.page-sidebar-menu > li.active > a {\n  background: #e02222 !important;\n  border-top-color: transparent !important;\n  color: #ffffff;\n}\nul.page-sidebar-menu > li.active > a i {\n  color: #ffffff;\n}\nul.page-sidebar-menu > li > ul.sub-menu > li:first-child > a {\n  border-top: 0px !important;\n}\nul.page-sidebar-menu > li > ul.sub-menu > li.active > a,\nul.page-sidebar-menu > li > ul.sub-menu > li > a:hover {\n  color: #ffffff !important;\n  background: #575757 !important;\n}\nul.page-sidebar-menu > li > ul.sub-menu > li > a:hover {\n  background: #575757 !important;\n}\n/* 3rd level sub menu */\nul.page-sidebar-menu > li > ul.sub-menu li > ul.sub-menu > li.active > a,\nul.page-sidebar-menu > li > ul.sub-menu li > ul.sub-menu > li > a:hover,\nul.page-sidebar-menu > li > ul.sub-menu li.open > a {\n  color: #ffffff !important;\n  background: #575757 !important;\n}\n/* font color for all sub menu links*/\nul.page-sidebar-menu li > ul.sub-menu > li > a {\n  color: #bdbdbd;\n}\n/* menu arrows */\nul.page-sidebar-menu > li > a .arrow:before,\nul.page-sidebar-menu > li > a .arrow.open:before {\n  color: #7d7d7d !important;\n}\nul.page-sidebar-menu > li > ul.sub-menu a .arrow:before,\nul.page-sidebar-menu > li > ul.sub-menu a .arrow.open:before {\n  color: #707070 !important;\n}\nul.page-sidebar-menu > li > a > .arrow.open:before {\n  color: #8a8a8a !important;\n}\nul.page-sidebar-menu > li.active > a .arrow:before,\nul.page-sidebar-menu > li.active > a .arrow.open:before {\n  color: #ffffff !important;\n}\n/* sidebar search */\n.page-sidebar .sidebar-search input {\n  background-color: #242424 !important;\n  color: #7d7d7d;\n}\n.page-sidebar .sidebar-search input::-webkit-input-placeholder {\n  color: #7d7d7d !important;\n}\n.page-sidebar .sidebar-search input:-moz-placeholder {\n  color: #7d7d7d !important;\n}\n.page-sidebar .sidebar-search input:-ms-input-placeholder {\n  color: #7d7d7d !important;\n}\n.page-sidebar .sidebar-search input {\n  background-color: #3d3d3d !important;\n  color: #bfbfbf !important;\n}\n.page-sidebar .sidebar-search .input-box {\n  border-bottom: 1px solid #7d7d7d !important;\n}\n.page-sidebar .sidebar-search .submit {\n  background-image: url(../../img/search-icon.png);\n}\n/***\nSidebar toggler\n***/\n.sidebar-toggler {\n  background-image: url(../../img/sidebar-toggler.jpg);\n  background-color: #242424;\n}\n/* search box bg color on expanded */\n.page-sidebar-closed .page-sidebar .sidebar-search.open .form-container {\n  background-color: #3d3d3d !important;\n}\n.page-sidebar-closed .page-sidebar .sidebar-search.open .form-container .remove {\n  background-image: url(\"../../img/sidebar-search-close.png\");\n}\n/* sub menu bg color on hover menu item */\n.page-sidebar-closed ul.page-sidebar-menu > li:hover .sub-menu {\n  background-color: #3d3d3d;\n}\n/***\nFooter \n***/\n.footer .footer-inner {\n  color: #999999;\n}\n.footer .footer-tools .go-top {\n  background-color: #4f4f4f;\n}\n.footer .footer-tools .go-top:hover {\n  opacity: 0.7;\n  filter: alpha(opacity=70);\n}\n.footer .footer-tools .go-top i {\n  color: #8a8a8a;\n}\n/***\nFooter Layouts (new in v1.3)\n***/\n/* begin:fixed footer */\n.page-footer-fixed .footer {\n  background-color: #242424;\n}\n.page-footer-fixed .footer .footer-inner {\n  color: #999999;\n}\n.page-footer-fixed .footer .footer-tools .go-top {\n  background-color: #4f4f4f;\n}\n.page-footer-fixed .footer .footer-tools .go-top i {\n  color: #8a8a8a;\n}\n/* end:fixed footer */\n/***\nGritter Notifications \n***/\n.gritter-top {\n  background: url(../../plugins/gritter/images/gritter.png) no-repeat left -30px !important;\n}\n.gritter-bottom {\n  background: url(../../plugins/gritter/images/gritter.png) no-repeat left bottom !important;\n}\n.gritter-item {\n  display: block;\n  background: url(../../plugins/gritter/images/gritter.png) no-repeat left -40px !important;\n}\n.gritter-close {\n  background: url(../../plugins/gritter/images/gritter.png) no-repeat left top !important;\n}\n.gritter-title {\n  text-shadow: none !important;\n  /* Not supported by IE :( */\n\n}\n/* for the light (white) version of the gritter notice */\n.gritter-light .gritter-item,\n.gritter-light .gritter-bottom,\n.gritter-light .gritter-top,\n.gritter-light .gritter-close {\n  background-image: url(../../plugins/gritter/images/gritter-light.png) !important;\n}\n.gritter-item-wrapper a {\n  color: #18a5ed;\n}\n.gritter-item-wrapper a:hover {\n  color: #0b6694;\n}\n/* begin: boxed page */\n@media (min-width: 992px) {\n  .page-boxed {\n    background-color: #2e2e2e !important;\n  }\n  .page-boxed .page-container {\n    background-color: #3d3d3d;\n    border-left: 1px solid #5e5e5e;\n    border-bottom: 1px solid #5e5e5e;\n  }\n  .page-boxed.page-sidebar-fixed .page-container {\n    border-left: 0;\n    border-bottom: 0;\n  }\n  .page-boxed.page-sidebar-fixed .page-sidebar {\n    border-left: 1px solid #5e5e5e;\n  }\n  .page-boxed.page-sidebar-fixed.page-footer-fixed .footer {\n    background-color: #2e2e2e !important;\n  }\n}\n/* end: boxed page */\n/***\nLandscape phone to portrait tablet\n***/\n@media (max-width: 991px) {\n  /***\n    page sidebar\n    ***/\n  .page-sidebar {\n    background-color: #292929 !important;\n  }\n  ul.page-sidebar-menu > li > a {\n    border-top: 1px solid #4a4a4a !important;\n  }\n  ul.page-sidebar-menu > li:last-child > a {\n    border-bottom: 0 !important;\n  }\n  .page-sidebar .sidebar-search input {\n    background-color: #292929 !important;\n  }\n  ul.page-sidebar-menu > li.open > a,\n  ul.page-sidebar-menu > li > a:hover,\n  ul.page-sidebar-menu > li:hover > a {\n    background: #1e1e1e;\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/css/themes/grey.css",
    "content": "/***\nGrey theme\n***/\n/***\nReset and overrides  \n***/\nbody {\n  background-color: #666666 !important;\n}\n/***\nPage header\n***/\n.header {\n  filter: none !important;\n  background-image: none !important;\n  background-color: #4a4a4a !important;\n}\n.header .btn-navbar {\n  background-color: #4a4a4a !important;\n}\n.header .navbar-nav .dropdown-toggle:hover,\n.header .navbar-nav .dropdown.open .dropdown-toggle {\n  background-color: #616161 !important;\n}\n.header .navbar-nav li.dropdown .dropdown-toggle i {\n  color: #b3b3b3 !important;\n}\n/***\nHor menu\n***/\n.header .hor-menu ul.nav li a {\n  color: #ccc;\n}\n\n.header .hor-menu ul.nav li.open > a,\n.header .hor-menu ul.nav li > a:hover,\n.header .hor-menu ul.nav li > a:focus {\n  color: #fff;\n  background: #616161;\n}\n\n.header .hor-menu .dropdown-menu li:hover > a,\n.header .hor-menu ul.nav li.active > a,\n.header .hor-menu ul.nav li.active > a:hover {\n  color: #fff;\n  background: #e02222 !important; \n}\n\n.header .hor-menu .dropdown-menu {  \n    background: #616161;\n}\n.header .hor-menu .dropdown-menu li > a {    \n    color: #ccc;\n}\n\n.header .hor-menu .hor-menu-search-form-toggler.off {\n   background: #616161 url(../../img/hor-menu-search-close-white.png) no-repeat center;\n}\n\n.header .hor-menu .search-form {  \n  background:#616161; \n}\n\n.header .hor-menu .search-form form input {\n  color: #ccc;\n}\n\n.header .hor-menu .search-form .btn {\n  color: #ccc;\n  background: url(../../img/search-icon-white.png) no-repeat center;\n}\n\n.header .hor-menu .search-form form input::-webkit-input-placeholder { /* WebKit browsers */\n    color: #ccc;\n}\n.header .hor-menu .search-form form input:-moz-placeholder { /* Mozilla Firefox 4 to 18 */\n    color: #ccc;\n}\n.header .hor-menu .search-form form input::-moz-placeholder { /* Mozilla Firefox 19+ */\n    color: #ccc;\n}\n.header .hor-menu .search-form form input:-ms-input-placeholder { /* Internet Explorer 10+ */\n    color: #ccc;\n}\n/***\nPage sidebar\n***/\n.page-sidebar {\n  background-color: #666666;\n}\nul.page-sidebar-menu > li > a {\n  border-top: 1px solid #858585 !important;\n  color: #ffffff !important;\n}\nul.page-sidebar-menu > li:last-child > a {\n  border-bottom: 1px solid transparent !important;\n}\nul.page-sidebar-menu > li a i {\n  color: #bfbfbf;\n}\nul.page-sidebar-menu > li.open > a,\nul.page-sidebar-menu > li > a:hover,\nul.page-sidebar-menu > li:hover > a {\n  background: #595959;\n}\nul.page-sidebar-menu > li.active > a {\n  background: #e02222 !important;\n  border-top-color: transparent !important;\n  color: #ffffff;\n}\nul.page-sidebar-menu > li.active > a i {\n  color: #ffffff;\n}\nul.page-sidebar-menu > li > ul.sub-menu > li:first-child > a {\n  border-top: 0px !important;\n}\nul.page-sidebar-menu > li > ul.sub-menu > li.active > a,\nul.page-sidebar-menu > li > ul.sub-menu > li > a:hover {\n  color: #ffffff !important;\n  background: #808080 !important;\n}\nul.page-sidebar-menu > li > ul.sub-menu > li > a:hover {\n  background: #808080 !important;\n}\n/* 3rd level sub menu */\nul.page-sidebar-menu > li > ul.sub-menu li > ul.sub-menu > li.active > a,\nul.page-sidebar-menu > li > ul.sub-menu li > ul.sub-menu > li > a:hover,\nul.page-sidebar-menu > li > ul.sub-menu li.open > a {\n  color: #ffffff !important;\n  background: #808080 !important;\n}\n/* font color for all sub menu links*/\nul.page-sidebar-menu li > ul.sub-menu > li > a {\n  color: #e6e6e6;\n}\n/* menu arrows */\nul.page-sidebar-menu > li > a .arrow:before,\nul.page-sidebar-menu > li > a .arrow.open:before {\n  color: #a6a6a6 !important;\n}\nul.page-sidebar-menu > li > ul.sub-menu a .arrow:before,\nul.page-sidebar-menu > li > ul.sub-menu a .arrow.open:before {\n  color: #999999 !important;\n}\nul.page-sidebar-menu > li > a > .arrow.open:before {\n  color: #b3b3b3 !important;\n}\nul.page-sidebar-menu > li.active > a .arrow:before,\nul.page-sidebar-menu > li.active > a .arrow.open:before {\n  color: #ffffff !important;\n}\n/* sidebar search */\n.page-sidebar .sidebar-search input {\n  background-color: #4d4d4d !important;\n  color: #a6a6a6;\n}\n.page-sidebar .sidebar-search input::-webkit-input-placeholder {\n  color: #a6a6a6 !important;\n}\n.page-sidebar .sidebar-search input:-moz-placeholder {\n  color: #a6a6a6 !important;\n}\n.page-sidebar .sidebar-search input:-ms-input-placeholder {\n  color: #a6a6a6 !important;\n}\n.page-sidebar .sidebar-search input {\n  background-color: #666666 !important;\n  color: #bfbfbf !important;\n}\n.page-sidebar .sidebar-search .input-box {\n  border-bottom: 1px solid #a6a6a6 !important;\n}\n.page-sidebar .sidebar-search .submit {\n  background-image: url(../../img/search-icon.png);\n}\n/***\nSidebar toggler\n***/\n.sidebar-toggler {\n  background-image: url(../../img/sidebar-toggler.jpg);\n  background-color: #4d4d4d;\n}\n/* search box bg color on expanded */\n.page-sidebar-closed .page-sidebar .sidebar-search.open .form-container {\n  background-color: #666666 !important;\n}\n.page-sidebar-closed .page-sidebar .sidebar-search.open .form-container .remove {\n  background-image: url(\"../../img/sidebar-search-close.png\");\n}\n/* sub menu bg color on hover menu item */\n.page-sidebar-closed ul.page-sidebar-menu > li:hover .sub-menu {\n  background-color: #666666;\n}\n/***\nFooter \n***/\n.footer .footer-inner {\n  color: #b3b3b3;\n}\n.footer .footer-tools .go-top {\n  background-color: #787878;\n}\n.footer .footer-tools .go-top:hover {\n  opacity: 0.7;\n  filter: alpha(opacity=70);\n}\n.footer .footer-tools .go-top i {\n  color: #b3b3b3;\n}\n/***\nFooter Layouts (new in v1.3)\n***/\n/* begin:fixed footer */\n.page-footer-fixed .footer {\n  background-color: #4d4d4d;\n}\n.page-footer-fixed .footer .footer-inner {\n  color: #b3b3b3;\n}\n.page-footer-fixed .footer .footer-tools .go-top {\n  background-color: #787878;\n}\n.page-footer-fixed .footer .footer-tools .go-top i {\n  color: #b3b3b3;\n}\n/* end:fixed footer */\n/***\nGritter Notifications \n***/\n.gritter-top {\n  background: url(../../plugins/gritter/images/gritter.png) no-repeat left -30px !important;\n}\n.gritter-bottom {\n  background: url(../../plugins/gritter/images/gritter.png) no-repeat left bottom !important;\n}\n.gritter-item {\n  display: block;\n  background: url(../../plugins/gritter/images/gritter.png) no-repeat left -40px !important;\n}\n.gritter-close {\n  background: url(../../plugins/gritter/images/gritter.png) no-repeat left top !important;\n}\n.gritter-title {\n  text-shadow: none !important;\n  /* Not supported by IE :( */\n\n}\n/* for the light (white) version of the gritter notice */\n.gritter-light .gritter-item,\n.gritter-light .gritter-bottom,\n.gritter-light .gritter-top,\n.gritter-light .gritter-close {\n  background-image: url(../../plugins/gritter/images/gritter-light.png) !important;\n}\n.gritter-item-wrapper a {\n  color: #18a5ed;\n}\n.gritter-item-wrapper a:hover {\n  color: #0b6694;\n}\n/* begin: boxed page */\n@media (min-width: 992px) {\n  .page-boxed {\n    background-color: #575757 !important;\n  }\n  .page-boxed .page-container {\n    background-color: #666666;\n    border-left: 1px solid #878787;\n    border-bottom: 1px solid #878787;\n  }\n  .page-boxed.page-sidebar-fixed .page-container {\n    border-left: 0;\n    border-bottom: 0;\n  }\n  .page-boxed.page-sidebar-fixed .page-sidebar {\n    border-left: 1px solid #878787;\n  }\n  .page-boxed.page-sidebar-fixed.page-footer-fixed .footer {\n    background-color: #575757 !important;\n  }\n}\n/* end: boxed page */\n/***\nLandscape phone to portrait tablet\n***/\n@media (max-width: 991px) {\n  /***\n    page sidebar\n    ***/\n  .page-sidebar {\n    background-color: #525252 !important;\n  }\n  ul.page-sidebar-menu > li > a {\n    border-top: 1px solid #737373 !important;\n  }\n  ul.page-sidebar-menu > li:last-child > a {\n    border-bottom: 0 !important;\n  }\n  .page-sidebar .sidebar-search input {\n    background-color: #525252 !important;\n  }\n  ul.page-sidebar-menu > li.open > a,\n  ul.page-sidebar-menu > li > a:hover,\n  ul.page-sidebar-menu > li:hover > a {\n    background: #474747;\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/css/themes/light.css",
    "content": "/***\nlight theme\n***/\n\n/***\nReset and overrides  \n***/\nbody {\n  background-color: #fafafa !important;\n}\n/***\nPage header\n***/\n.header {\n  filter: none !important;\n  background-image: none !important;\n  background-color: #434343 !important;\n}\n.header .btn-navbar {\n  background-color: #434343 !important;\n}\n.header .navbar-nav .dropdown-toggle:hover,\n.header .navbar-nav .dropdown.open .dropdown-toggle {\n  background-color: #4f4f4f !important;\n}\n.header .navbar-nav li.dropdown .dropdown-toggle i {\n  color: #808080 !important;\n}\n/***\nHor menu\n***/\n.header .hor-menu ul.nav li a {\n  color: #ccc;\n}\n\n.header .hor-menu ul.nav li.open > a,\n.header .hor-menu ul.nav li > a:hover,\n.header .hor-menu ul.nav li > a:focus {\n  color: #fff;\n  background: #4f4f4f;\n}\n\n.header .hor-menu .dropdown-menu li:hover > a,\n.header .hor-menu ul.nav li.active > a,\n.header .hor-menu ul.nav li.active > a:hover {\n  color: #fff;\n  background: #e02222 !important; \n}\n\n.header .hor-menu .dropdown-menu {  \n    background: #4f4f4f;\n}\n.header .hor-menu .dropdown-menu li > a {    \n    color: #ccc;\n}\n\n.header .hor-menu .hor-menu-search-form-toggler.off {\n   background: #4f4f4f url(../../img/hor-menu-search-close-white.png) no-repeat center;\n}\n\n.header .hor-menu .search-form {  \n  background:#4f4f4f; \n}\n\n.header .hor-menu .search-form form input {\n  color: #ccc;\n}\n\n.header .hor-menu .search-form .btn {\n  color: #ccc;\n  background: url(../../img/search-icon-white.png) no-repeat center;\n}\n\n.header .hor-menu .search-form form input::-webkit-input-placeholder { /* WebKit browsers */\n    color: #ccc;\n}\n.header .hor-menu .search-form form input:-moz-placeholder { /* Mozilla Firefox 4 to 18 */\n    color: #ccc;\n}\n.header .hor-menu .search-form form input::-moz-placeholder { /* Mozilla Firefox 19+ */\n    color: #ccc;\n}\n.header .hor-menu .search-form form input:-ms-input-placeholder { /* Internet Explorer 10+ */\n    color: #ccc;\n}\n/***\nPage sidebar\n***/\n.page-content {\n  border-left: 1px solid #e2e2e2 !important;\n  border-bottom: 1px solid #e2e2e2 !important;\n}\n.page-sidebar {\n  background-color: #fafafa;\n}\n.page-sidebar-fixed .page-content {\n  border: 0 !important;\n}\n.page-sidebar-fixed .page-sidebar {\n  border-right: 1px solid #e2e2e2 !important;\n}\n\n\nul.page-sidebar-menu > li > a {\n  border-top: 1px solid #e2e2e2 !important;\n  color: #000 !important;\n  font-weight: 400;\n}\n\nul.page-sidebar-menu > li:first-child > a {\n   border-top: 1px solid transparent !important;\n}\n\nul.page-sidebar-menu > li:last-child > a {\n   border-bottom: 1px solid transparent !important;\n}\n\nul.page-sidebar-menu > li a i {\n  color: #bbb !important;\n}\nul.page-sidebar-menu > li.open > a,\nul.page-sidebar-menu > li > a:hover,\nul.page-sidebar-menu > li:hover > a {\n  background: #eee;\n  border-top: 1px solid #e8e8e8;\n}\nul.page-sidebar-menu > li.active > a .selected {\n  right:-7px;\n  top:0px;\n  width: 7px;\n  height: 39px;\n  background-image: url(\"../../img/sidebar-menu-arrow-green.png\");\n}  \nul.page-sidebar-menu > li.active i {\n  color: #fff !important;\n}\n.page-sidebar-fixed ul.page-sidebar-menu > li.active > a .selected {\n  display: none;\n}\nul.page-sidebar-menu > li.active > a{\n  background: #28b779 !important;\n  border-top-color: transparent !important;\n  color:#fff !important;\n}  \nul.page-sidebar-menu > li.active > a i {\n  color: #fff;\n}\nul.page-sidebar-menu > li > a > .arrow:before,\nul.page-sidebar-menu > li > a > .arrow.open:before {\n  color: #ccc !important;\n}\nul.page-sidebar-menu > li.active > a .arrow:before, \nul.page-sidebar-menu > li.active > a .arrow.open:before {\n  color: #fff !important;\n}\nul.page-sidebar-menu > li > ul.sub-menu > li:first-child > a {\n  border-top: 0px !important;\n}\n\nul.page-sidebar-menu ul.sub-menu > li > a {\n  font-weight: 400 !important;\n  color: #333 !important;\n}\nul.page-sidebar-menu ul.sub-menu > li.active > a,\nul.page-sidebar-menu ul.sub-menu > li > a:hover {\n  color: #818181 !important;\n  background: #efefef !important; \n}\n\nul.page-sidebar-menu > li > ul.sub-menu a .arrow:before,\nul.page-sidebar-menu > li > ul.sub-menu a .arrow.open:before {\n  color: #ccc !important;\n}\n\n/* sub menu links effects */\nul.page-sidebar-menu ul.sub-menu > li.active > a,\nul.page-sidebar-menu ul.sub-menu > li > a:hover,\nul.page-sidebar-menu ul.sub-menu > li.open > a {\n  color: #818181 !important;\n  background: #efefef !important; \n}\nul.page-sidebar-menu ul.sub-menu > li > a i {\n  color: #bbb !important;\n}\n\n/* sidebar search */\n.page-sidebar .sidebar-search input {\n  background-color: #fbfbfb  !important;  \n  color: #727272 !important;\n}\n.page-sidebar .sidebar-search input::-webkit-input-placeholder {\n  color: #aaa !important;\n}\n.page-sidebar .sidebar-search input:-moz-placeholder {\n  color: #aaa !important;\n}\n.page-sidebar .sidebar-search input:-ms-input-placeholder {\n  color: #aaa !important;\n}\n.page-sidebar .sidebar-search .input-box {\n  border-bottom: 1px solid #e2e2e2 !important;\n}\n.page-sidebar .sidebar-search .submit {\n  background-image: url(../../img/search-icon-white.png);\n}\n\n/***\nSidebar toggler\n***/\n.sidebar-toggler {  \n  background-image: url(../../img/sidebar-toggler-light.jpg);\n  background-color: #333;\n}\n/* search box bg color on expanded */\n.page-sidebar-closed .page-sidebar .sidebar-search.open .form-container {\n  background-color: #fbfbfb !important;\n}\n.page-sidebar-closed .page-sidebar .sidebar-search.open .form-container .remove {  \n  background-image: url(\"../../img/sidebar-search-close-light.png\");\n}\n/* sub menu bg color on hover menu item */\n.page-sidebar-closed ul.page-sidebar-menu > li:hover .sub-menu {\n  background-color: #fbfbfb;\n}\n/***\nFooter \n***/\n.footer .footer-inner {\n  color: #333333;\n}\n.footer .footer-tools .go-top {\n  background-color: #666666;\n}\n.footer .footer-tools .go-top:hover {\n  opacity: 0.7;\n  filter: alpha(opacity=70);\n}\n.footer .footer-tools .go-top i {\n  color: #999999;\n}\n/***\nFooter Layouts (new in v1.3)\n***/\n/* begin:fixed footer */\n.page-footer-fixed .footer {\n  background-color: #434343;\n}\n.page-footer-fixed .footer .footer-inner {\n  color: #aaaaaa;\n}\n.page-footer-fixed .footer .footer-tools .go-top {\n  background-color: #666666;\n}\n.page-footer-fixed .footer .footer-tools .go-top i {\n  color: #aaaaaa;\n}\n/* end:fixed footer */\n/***\nGritter Notifications \n***/\n.gritter-top {\n  background: url(../../plugins/gritter/images/gritter.png) no-repeat left -30px !important;\n}\n.gritter-bottom {\n  background: url(../../plugins/gritter/images/gritter.png) no-repeat left bottom !important;\n}\n.gritter-item {\n  display: block;\n  background: url(../../plugins/gritter/images/gritter.png) no-repeat left -40px !important;\n}\n.gritter-close {\n  background: url(../../plugins/gritter/images/gritter.png) no-repeat left top !important;\n}\n.gritter-title {\n  text-shadow: none !important;\n  /* Not supported by IE :( */\n\n}\n/* for the light (white) version of the gritter notice */\n.gritter-light .gritter-item,\n.gritter-light .gritter-bottom,\n.gritter-light .gritter-top,\n.gritter-light .gritter-close {\n  background-image: url(../../plugins/gritter/images/gritter-light.png) !important;\n}\n.gritter-item-wrapper a {\n  color: #18a5ed;\n}\n.gritter-item-wrapper a:hover {\n  color: #0b6694;\n}\n/* begin: boxed page */\n@media (min-width: 992px) {\n  .page-boxed {\n    background-color: #E8E8E8 !important;\n  }\n  .page-boxed .page-container {\n    background-color: #fafafa;\n    border-left: 1px solid #e2e2e2;\n    border-bottom: 1px solid #e2e2e2;\n  }\n  .page-boxed.page-sidebar-fixed .page-container {\n    border-left: 0;\n    border-bottom: 0;\n  }\n  .page-boxed.page-sidebar-fixed .page-sidebar {\n    border-left: 1px solid #e2e2e2;\n  }\n  .page-boxed.page-sidebar-fixed.page-footer-fixed .footer {\n    background-color: #E8E8E8 !important;\n  }\n}\n/* end: boxed page */\n/***\nLandscape phone to portrait tablet\n***/\n@media (max-width: 991px) {\n  /***\n  page sidebar\n  ***/\n  .page-sidebar {\n    background-color: #f1f1f1 !important;\n    border-right: none !important;\n  }\n  .page-sidebar-fixed .page-sidebar {\n    border-right: none !important; \n  }\n  .page-content {\n    border-left: none !important;\n  }\n  ul.page-sidebar-menu > li > a {\n    border-top: 1px solid #ccc !important;\n  }\n  ul.page-sidebar-menu > li:last-child > a {\n    border-bottom: 0 !important;\n  }\n\n  ul.page-sidebar-menu > li.open > a,\n  ul.page-sidebar-menu > li > a:hover {\n    color: #666666 !important;\n    background-color: #dddddd !important;\n  }\n  ul.page-sidebar-menu > li.open > a {\n    border-bottom-color: transparent !important;\n  }\n  ul.page-sidebar-menu > li.active > a {\n    color: #ffffff !important;\n    background-color: #28b779 !important;\n  }\n\n  ul.page-sidebar-menu ul.sub-menu > li > a {\n    color: #111 !important;\n  }\n\n  ul.page-sidebar-menu ul.sub-menu > li.open > a,\n  ul.page-sidebar-menu ul.sub-menu > li.active > a,\n  ul.page-sidebar-menu ul.sub-menu > li > a:hover {\n    color: #666666 !important;\n    background: #dddddd !important; \n  }\n\n  .page-sidebar .sidebar-search input {\n    background-color: #f1f1f1 !important;\n    color: #ccc !important;\n  }\n\n  .page-sidebar .sidebar-search .input-box {\n    border-bottom-color: #ccc !important;\n  }\n  .page-sidebar .sidebar-search input::-webkit-input-placeholder {\n    color: #ccc !important;\n  }\n  .page-sidebar .sidebar-search input:-moz-placeholder {\n    color: #ccc !important;\n  }\n  .page-sidebar .sidebar-search input:-ms-input-placeholder {\n    color: #ccc !important;\n  }\n\n  /***\n  page footer\n  ***/\n  \n  .footer {\n    background-color: #434343;\n  }\n\n  .footer .footer-inner {\n    color: #cccccc;\n  }\n  .footer .footer-tools .go-top {\n    background-color: #666666;\n  }\n  .footer .footer-tools .go-top i {\n    color: #999999;\n  }\n}\n\n@media (max-width: 767px) {\n  body {\n    background-color: #333 !important;\n  }\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/css/themes/purple.css",
    "content": "/***\nPurple theme\n***/\n/***\nReset and overrides  \n***/\nbody {\n  background-color: #701584 !important;\n}\n/***\nPage header\n***/\n.header {\n  filter: none !important;\n  background-image: none !important;\n  background-color: #470d54 !important;\n}\n.header .btn-navbar {\n  background-color: #470d54 !important;\n}\n.header .navbar-nav .dropdown-toggle:hover,\n.header .navbar-nav .dropdown.open .dropdown-toggle {\n  background-color: #69147b !important;\n}\n.header .navbar-nav li.dropdown .dropdown-toggle i {\n  color: #c84fe3 !important;\n}\n/***\nHor menu\n***/\n.header .hor-menu ul.nav li a {\n  color: #ccc;\n}\n\n.header .hor-menu ul.nav li.open > a,\n.header .hor-menu ul.nav li > a:hover,\n.header .hor-menu ul.nav li > a:focus {\n  color: #fff;\n  background: #69147b;\n}\n\n.header .hor-menu .dropdown-menu li:hover > a,\n.header .hor-menu ul.nav li.active > a,\n.header .hor-menu ul.nav li.active > a:hover {\n  color: #fff;\n  background: #e02222 !important; \n}\n\n.header .hor-menu .dropdown-menu {  \n    background: #69147b;\n}\n.header .hor-menu .dropdown-menu li > a {    \n    color: #ccc;\n}\n\n.header .hor-menu .hor-menu-search-form-toggler.off {\n   background: #69147b url(../../img/hor-menu-search-close-white.png) no-repeat center;\n}\n\n.header .hor-menu .search-form {  \n  background:#69147b; \n}\n\n.header .hor-menu .search-form form input {\n  color: #ccc;\n}\n\n.header .hor-menu .search-form .btn {\n  color: #ccc;\n  background: url(../../img/search-icon-white.png) no-repeat center;\n}\n\n.header .hor-menu .search-form form input::-webkit-input-placeholder { /* WebKit browsers */\n    color: #ccc;\n}\n.header .hor-menu .search-form form input:-moz-placeholder { /* Mozilla Firefox 4 to 18 */\n    color: #ccc;\n}\n.header .hor-menu .search-form form input::-moz-placeholder { /* Mozilla Firefox 19+ */\n    color: #ccc;\n}\n.header .hor-menu .search-form form input:-ms-input-placeholder { /* Internet Explorer 10+ */\n    color: #ccc;\n}\n/***\nPage sidebar\n***/\n.page-sidebar {\n  background-color: #701584;\n}\nul.page-sidebar-menu > li > a {\n  border-top: 1px solid #9d1db9 !important;\n  color: #ffffff !important;\n}\nul.page-sidebar-menu > li:last-child > a {\n  border-bottom: 1px solid transparent !important;\n}\nul.page-sidebar-menu > li a i {\n  color: #cf65e7;\n}\nul.page-sidebar-menu > li.open > a,\nul.page-sidebar-menu > li > a:hover,\nul.page-sidebar-menu > li:hover > a {\n  background: #5d116e;\n}\nul.page-sidebar-menu > li.active > a {\n  background: #571067 !important;\n  border-top-color: transparent !important;\n  color: #ffffff;\n}\nul.page-sidebar-menu > li.active > a i {\n  color: #ffffff;\n}\nul.page-sidebar-menu > li > ul.sub-menu > li:first-child > a {\n  border-top: 0px !important;\n}\nul.page-sidebar-menu > li > ul.sub-menu > li.active > a,\nul.page-sidebar-menu > li > ul.sub-menu > li > a:hover {\n  color: #ffffff !important;\n  background: #951cb0 !important;\n}\nul.page-sidebar-menu > li > ul.sub-menu > li > a:hover {\n  background: #951cb0 !important;\n}\n/* 3rd level sub menu */\nul.page-sidebar-menu > li > ul.sub-menu li > ul.sub-menu > li.active > a,\nul.page-sidebar-menu > li > ul.sub-menu li > ul.sub-menu > li > a:hover,\nul.page-sidebar-menu > li > ul.sub-menu li.open > a {\n  color: #ffffff !important;\n  background: #951cb0 !important;\n}\n/* font color for all sub menu links*/\nul.page-sidebar-menu li > ul.sub-menu > li > a {\n  color: #e4a7f1;\n}\n/* menu arrows */\nul.page-sidebar-menu > li > a .arrow:before,\nul.page-sidebar-menu > li > a .arrow.open:before {\n  color: #c239df !important;\n}\nul.page-sidebar-menu > li > ul.sub-menu a .arrow:before,\nul.page-sidebar-menu > li > ul.sub-menu a .arrow.open:before {\n  color: #bb23dc !important;\n}\nul.page-sidebar-menu > li > a > .arrow.open:before {\n  color: #c84fe3 !important;\n}\nul.page-sidebar-menu > li.active > a .arrow:before,\nul.page-sidebar-menu > li.active > a .arrow.open:before {\n  color: #ffffff !important;\n}\n/* sidebar search */\n.page-sidebar .sidebar-search input {\n  background-color: #4b0e58 !important;\n  color: #bf55d7;\n}\n.page-sidebar .sidebar-search input::-webkit-input-placeholder {\n  color: #b84dd0 !important;\n}\n.page-sidebar .sidebar-search input:-moz-placeholder {\n  color: #b84dd0 !important;\n}\n.page-sidebar .sidebar-search input:-ms-input-placeholder {\n  color: #b84dd0 !important;\n}\n.page-sidebar .sidebar-search input {\n  background-color: #701584 !important;\n  color: #bfbfbf !important;\n}\n.page-sidebar .sidebar-search .input-box {\n  border-bottom: 1px solid #a93bc1 !important;\n}\n.page-sidebar .sidebar-search .submit {\n  background-image: url(../../img/search-icon-purple.png);\n}\n/***\nSidebar toggler\n***/\n.sidebar-toggler {\n  background-image: url(../../img/sidebar-toggler-purple.jpg);\n  background-color: #4b0e58;\n}\n/* search box bg color on expanded */\n.page-sidebar-closed .page-sidebar .sidebar-search.open .form-container {\n  background-color: #701584 !important;\n}\n.page-sidebar-closed .page-sidebar .sidebar-search.open .form-container .remove {\n  background-image: url(\"../../img/sidebar-search-close-purple.png\");\n}\n/* sub menu bg color on hover menu item */\n.page-sidebar-closed ul.page-sidebar-menu > li:hover .sub-menu {\n  background-color: #701584;\n}\n/***\nFooter \n***/\n.footer .footer-inner {\n  color: #c84fe3;\n}\n.footer .footer-tools .go-top {\n  background-color: #8a1aa3;\n}\n.footer .footer-tools .go-top:hover {\n  opacity: 0.7;\n  filter: alpha(opacity=70);\n}\n.footer .footer-tools .go-top i {\n  color: #c84fe3;\n}\n/***\nFooter Layouts (new in v1.3)\n***/\n/* begin:fixed footer */\n.page-footer-fixed .footer {\n  background-color: #4b0e58;\n}\n.page-footer-fixed .footer .footer-inner {\n  color: #c84fe3;\n}\n.page-footer-fixed .footer .footer-tools .go-top {\n  background-color: #8a1aa3;\n}\n.page-footer-fixed .footer .footer-tools .go-top i {\n  color: #c84fe3;\n}\n/* end:fixed footer */\n/***\nGritter Notifications \n***/\n.gritter-top {\n  background: url(../../plugins/gritter/images/gritter-purple.png) no-repeat left -30px !important;\n}\n.gritter-bottom {\n  background: url(../../plugins/gritter/images/gritter-purple.png) no-repeat left bottom !important;\n}\n.gritter-item {\n  display: block;\n  background: url(../../plugins/gritter/images/gritter-purple.png) no-repeat left -40px !important;\n}\n.gritter-close {\n  background: url(../../plugins/gritter/images/gritter-purple.png) no-repeat left top !important;\n}\n.gritter-title {\n  text-shadow: none !important;\n  /* Not supported by IE :( */\n\n}\n/* for the light (white) version of the gritter notice */\n.gritter-light .gritter-item,\n.gritter-light .gritter-bottom,\n.gritter-light .gritter-top,\n.gritter-light .gritter-close {\n  background-image: url(../../plugins/gritter/images/gritter-light.png) !important;\n}\n.gritter-item-wrapper a {\n  color: #18a5ed;\n}\n.gritter-item-wrapper a:hover {\n  color: #0b6694;\n}\n/* begin: boxed page */\n@media (min-width: 992px) {\n  .page-boxed {\n    background-color: #5a116a !important;\n  }\n  .page-boxed .page-container {\n    background-color: #701584;\n    border-left: 1px solid #a11ebd;\n    border-bottom: 1px solid #a11ebd;\n  }\n  .page-boxed.page-sidebar-fixed .page-container {\n    border-left: 0;\n    border-bottom: 0;\n  }\n  .page-boxed.page-sidebar-fixed .page-sidebar {\n    border-left: 1px solid #a11ebd;\n  }\n  .page-boxed.page-sidebar-fixed.page-footer-fixed .footer {\n    background-color: #5a116a !important;\n  }\n}\n/* end: boxed page */\n/***\nLandscape phone to portrait tablet\n***/\n@media (max-width: 991px) {\n  /***\n    page sidebar\n    ***/\n  .page-sidebar {\n    background-color: #520f61 !important;\n  }\n  ul.page-sidebar-menu > li > a {\n    border-top: 1px solid #83189a !important;\n  }\n  ul.page-sidebar-menu > li:last-child > a {\n    border-bottom: 0 !important;\n  }\n  .page-sidebar .sidebar-search input {\n    background-color: #520f61 !important;\n  }\n  ul.page-sidebar-menu > li.open > a,\n  ul.page-sidebar-menu > li > a:hover,\n  ul.page-sidebar-menu > li:hover > a {\n    background: #430d4f;\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/fonts/font.css",
    "content": "@font-face {\n  font-family: 'Open Sans';\n  font-style: normal;\n  font-weight: 300;\n  src: local('Open Sans Light'), local('OpenSans-Light'), url(../fonts/DXI1ORHCpsQm3Vp6mXoaTXhCUOGz7vYGh680lGh-uXM.woff) format('woff');\n}\n@font-face {\n  font-family: 'Open Sans';\n  font-style: normal;\n  font-weight: 400;\n  src: local('Open Sans'), local('OpenSans'), url(../fonts/cJZKeOuBrn4kERxqtaUH3T8E0i7KZn-EPnyo3HZu7kw.woff) format('woff');\n}\n@font-face {\n  font-family: 'Open Sans';\n  font-style: normal;\n  font-weight: 600;\n  src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url(../fonts/MTP_ySUJH_bn48VBG8sNSnhCUOGz7vYGh680lGh-uXM.woff) format('woff');\n}\n@font-face {\n  font-family: 'Open Sans';\n  font-style: normal;\n  font-weight: 700;\n  src: local('Open Sans Bold'), local('OpenSans-Bold'), url(../fonts/k3k702ZOKiLJc3WVjuplzHhCUOGz7vYGh680lGh-uXM.woff) format('woff');\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/manage/auditManage.js",
    "content": "//驳回应用请求\nfunction appRefuse(appAuditId, type){\n\t//驳回\n\tvar status = -1;\n\t//驳回理由\n\tvar refuseReason = document.getElementById(\"refuseReason\" + appAuditId);\n\tif(refuseReason.value == \"\"){\n\t\talert(\"驳回理由不能为空\");\n\t\trefuseReason.focus();\n\t\treturn false;\n\t}\n\t\n\tvar appRefuseBtn = document.getElementById(\"appRefuseBtn\" + appAuditId);\n\tappRefuseBtn.disabled = true;\n\t\n\tvar url = \"\";\n\tif(type == 0 || type == 1 || type == 2){\n\t\turl = \"/manage/app/addAuditStatus.do\";\n\t//用户申请\n\t}else if(type == 3){\n\t\turl = \"/manage/user/addAuditStatus.do\";\n\t}\n\t$.post(\n\t\turl,\n\t\t{\n\t\t\tappAuditId: appAuditId,\n\t\t\trefuseReason: refuseReason.value,\n\t\t\tstatus: status\n\t\t},\n        function(data){\n            if(data==1){\n            \t$(\"#appRefuseInfo\"+appAuditId).html(\"<div class='alert alert-error' ><button class='close' data-dismiss='alert'>×</button><strong>Success!</strong>更新成功，窗口会自动关闭</div>\");\n                $('appRefuseModal'+appAuditId).modal('hide');\n            \tsetTimeout(\"window.location.reload()\",1000);\n            }else{\n            \tappRefuseBtn.disabled = false;\n                $(\"#appRefuseInfo\"+appAuditId).html(\"<div class='alert alert-error' ><button class='close' data-dismiss='alert'>×</button><strong>Error!</strong>更新失败！</div>\");\n            }\n        }\n     );\n}\n\n//检查配置项\nfunction checkAppConfig(){\n\t//配置项\n\tvar appConfigKey = document.getElementById(\"appConfigKey\");\n\tif(appConfigKey.value == \"\"){\n\t\talert(\"配置项不能为空\");\n\t\tappConfigKey.focus();\n\t\treturn false;\n\t}\n\t\n\t//配置值\n\tvar appConfigValue = document.getElementById(\"appConfigValue\");\n\tif(appConfigValue.value == \"\"){\n\t\talert(\"配置值不能为空\");\n\t\tappConfigValue.focus();\n\t\treturn false;\n\t}\n\treturn true;\n}\n\n//检查配置项\nfunction checkInstanceConfig(){\n\t//配置项\n\tvar instanceConfigKey = document.getElementById(\"instanceConfigKey\");\n\tif(instanceConfigKey.value == \"\"){\n\t\talert(\"配置项不能为空\");\n\t\tinstanceConfigKey.focus();\n\t\treturn false;\n\t}\n\t\n\t//配置值\n\tvar instanceConfigValue = document.getElementById(\"instanceConfigValue\");\n\tif(instanceConfigValue.value == \"\"){\n\t\talert(\"配置值不能为空\");\n\t\tinstanceConfigValue.focus();\n\t\treturn false;\n\t}\n\treturn true;\n}\n\n\n//检查扩容配置\nfunction checkAppScaleText(){\n\tvar appScaleText = document.getElementById(\"appScaleText\");\n\tif(appScaleText.value == \"\"){\n\t\talert(\"配置不能为空\");\n\t\tappScaleText.focus();\n\t\treturn false;\n\t}\n\treturn true;\n}\n\nfunction startShowDeployLabel(){\n\tvar startDeployLabel = document.getElementById(\"startDeployLabel\");\n\tstartDeployLabel.innerHTML += '.';\n}\n\n//检查应用部署配置\nfunction checkAppDeployText(){\n\tvar appDeployText = document.getElementById(\"appDeployText\");\n\tif(appDeployText.value == \"\"){\n\t\talert(\"应用部署信息不能为空\");\n\t\tappDeployText.focus();\n\t\treturn false;\n\t}\n\tvar appAuditId = document.getElementById(\"appAuditId\");\n\t$.get(\n\t\t'/manage/app/appDeployCheck.json',\n\t\t{\n\t\t\tappAuditId: appAuditId.value,\n\t\t\tappDeployText: appDeployText.value\n\t\t},\n        function(data){\n\t\t\tvar status = data.status;\n\t\t\talert(data.message);\n\t\t\tif (status == 1) {\n\t\t\t\tvar appDeployBtn = document.getElementById(\"appDeployBtn\");\n\t\t\t\tappDeployBtn.disabled = false;\n\t    \t\t\n\t    \t\tvar appCheckBtn = document.getElementById(\"appCheckBtn\");\n\t    \t\tappCheckBtn.disabled = true;\n\t    \t\t\n\t    \t\tappDeployText.disabled = true;\n\t\t\t} else {\n\t\t\t\tappDeployText.focus();\n\t\t\t}\n        }\n     );\n}\n\nfunction addAppDeployText() {\n\tvar appDeployBtn = document.getElementById(\"appDeployBtn\");\n\tappDeployBtn.disabled = true;\n\t\n\tvar appDeployText = document.getElementById(\"appDeployText\");\n\tvar appAuditId = document.getElementById(\"appAuditId\");\n\t\n\tvar startDeployLabel = document.getElementById(\"startDeployLabel\");\n\tstartDeployLabel.innerHTML = '正在部署,请等待.';\n\t\n\t$.get(\n\t\t'/manage/app/addAppDeploy.json',\n\t\t{\n\t\t\tappAuditId: appAuditId.value,\n\t\t\tappDeployText: appDeployText.value\n\t\t},\n        function(data){\n\t\t\tvar status = data.status;\n\t\t\tif (status == 1) {\n\t\t\t\talert(\"应用部署成功,确认后将跳转到审核界面,点击[通过]按钮即可!\");\n\t\t\t} else {\n\t\t\t\talert(\"应用部署失败,请查看系统日志确认相关原因!\");\n\t\t\t}\n\t\t\twindow.location.href=\"/manage/app/auditList\";\n        }\n     );\n\t//展示简单的进度条\n\tsetInterval(startShowDeployLabel,500);\n}\n\n//添加分片验证\nfunction checkAddShardParam(){\n\tvar masterSizeSlave = document.getElementById(\"masterSizeSlave\");\n\tif(masterSizeSlave.value == \"\"){\n\t\talert(\"主从分片配置不能为空\");\n\t\tmasterSizeSlave.focus();\n\t\treturn false;\n\t}\n\t\n\treturn true;\n}\n\nfunction testisNum(id){\n   var value =document.getElementById(id).value;\n   if(value != \"\" && isNaN(value)){\n      alert(\"请输入数字类型!\");\n      document.getElementById(id).value=\"\";\n      document.getElementById(id).focus();\n   }\n}\n\n//添加水平扩容验证\nfunction checkHorizontalScale(){\n\tvar sourceId = document.getElementById(\"sourceId\");\n\tif(sourceId.value == \"\"){\n\t\talert(\"源实例ID不能为空\");\n\t\tsourceId.focus();\n\t\treturn false;\n\t}\n\t\n\tvar targetId = document.getElementById(\"targetId\");\n\tif(targetId.value == \"\"){\n\t\talert(\"目标实例ID不能为空\");\n\t\ttargetId.focus();\n\t\treturn false;\n\t}\n\t\n\tvar startSlot = document.getElementById(\"startSlot\");\n\tif(startSlot.value == \"\"){\n\t\talert(\"开始slot不能为空\");\n\t\tstartSlot.focus();\n\t\treturn false;\n\t}\n\t\n\tvar endSlot = document.getElementById(\"endSlot\");\n\tif(endSlot.value == \"\"){\n\t\talert(\"结束slot不能为空\");\n\t\tendSlot.focus();\n\t\treturn false;\n\t}\n\t\n\tvar migrateType = document.getElementById(\"migrateType\");\n\t\n\tvar appId = document.getElementById(\"appId\");\n\tvar appAuditId = document.getElementById(\"appAuditId\");\n\t$.get(\n\t\t'/manage/app/checkHorizontalScale.json',\n\t\t{\n\t\t\tsourceId: sourceId.value,\n\t\t\ttargetId: targetId.value,\n\t\t\tstartSlot: startSlot.value,\n\t\t\tendSlot: endSlot.value,\n\t\t\tappId: appId.value,\n\t\t\tappAuditId: appAuditId.value,\n\t\t\tmigrateType: migrateType.value\n\t\t},\n        function(data){\n\t\t\tvar status = data.status;\n\t\t\talert(data.message);\n\t\t\tif (status == 1) {\n\t\t\t\tvar submitButton = document.getElementById(\"submitButton\");\n\t    \t\tsubmitButton.disabled = false;\n\t    \t\t\n\t    \t\tvar checkButton = document.getElementById(\"checkButton\");\n\t    \t\tcheckButton.disabled = true;\n\t    \t\tsourceId.disabled = true;\n\t    \t\ttargetId.disabled = true;\n\t    \t\tstartSlot.disabled = true;\n\t    \t\tendSlot.disabled = true;\n\t    \t\tmigrateType.disabled = true;\n\t\t\t}\n        }\n     );\n\treturn true;\n}\n\n\n//开始水平扩容\nfunction startHorizontalScale(){\n\tvar sourceId = document.getElementById(\"sourceId\");\n\tvar targetId = document.getElementById(\"targetId\");\n\tvar startSlot = document.getElementById(\"startSlot\");\n\tvar endSlot = document.getElementById(\"endSlot\");\n\tvar appId = document.getElementById(\"appId\");\n\tvar appAuditId = document.getElementById(\"appAuditId\");\n\tvar migrateType = document.getElementById(\"migrateType\");\n\t\n\tvar submitButton = document.getElementById(\"submitButton\");\n    submitButton.disabled = true;\n\t\n\t$.get(\n\t\t'/manage/app/startHorizontalScale.json',\n\t\t{\n\t\t\tsourceId: sourceId.value,\n\t\t\ttargetId: targetId.value,\n\t\t\tstartSlot: startSlot.value,\n\t\t\tendSlot: endSlot.value,\n\t\t\tappId: appId.value,\n\t\t\tappAuditId: appAuditId.value,\n\t\t\tmigrateType: migrateType.value\n\t\t},\n        function(data){\n\t\t\tvar status = data.status;\n\t\t\talert(data.message);\n\t\t\tif (status == 1) {\n\t\t\t\twindow.location.href=\"/manage/app/handleHorizontalScale?appAuditId=\" + appAuditId.value;\n\t\t\t}\n        }\n     );\n\treturn true;\n}\n\n//重试水平扩容\nfunction retryHorizontalScale(instanceReshardProcessId){\n\tvar appAuditId = document.getElementById(\"appAuditId\");\n\tvar retryButton = document.getElementById(\"retryBtn\" + instanceReshardProcessId);\n\tinstanceReshardProcessId.disabled = true;\n\t$.get(\n\t\t'/manage/app/retryHorizontalScale.json',\n\t\t{\n\t\t\tinstanceReshardProcessId: instanceReshardProcessId\n\t\t},\n        function(data){\n\t\t\tvar status = data.status;\n\t\t\talert(data.message);\n\t\t\tif (status == 1) {\n\t\t\t\twindow.location.href=\"/manage/app/handleHorizontalScale?appAuditId=\" + appAuditId.value;\n\t\t\t}\n        }\n     );\n\treturn true;\n}\n\n\n\n//添加下线分片验证\nfunction checkOffLineInstanceParam(){\n\tvar ip = document.getElementById(\"dropIp\");\n\tif(ip.value == \"\"){\n\t\talert(\"ip不能为空\");\n\t\tip.focus();\n\t\treturn false;\n\t}\n\t\n\tvar port = document.getElementById(\"dropPort\");\n\tif(port.value == \"\"){\n\t\talert(\"port不能为空\");\n\t\tport.focus();\n\t\treturn false;\n\t}\n\treturn true;\n}\n\n\n\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/manage/machineManage.js",
    "content": "function removeMachine(id, ip) {\n\tvar removeMachineBtn = document.getElementById(id);\n\tremoveMachineBtn.disabled = true;\n\t$.get(\n\t\t'/manage/machine/checkMachineInstances.json',\n\t\t{\n\t\t\tip: ip,\n\t\t},\n        function(data){\n\t\t\tvar machineHasInstance = data.machineHasInstance;\n\t\t\tvar alertMsg;\n\t\t\tif (machineHasInstance == true) {\n\t\t\t\talertMsg = \"该机器ip=\" + ip + \"还有运行中的Redis节点,确认要删除吗？\";\n\t\t\t} else {\n\t\t\t\talertMsg = \"确认要删除ip=\" + ip + \"吗?\";\n\t\t\t}\n\t\t\tif (confirm(alertMsg)) {\n\t\t\t\tlocation.href = \"/manage/machine/delete.do?machineIp=\"+ip;\n\t\t\t} else {\n\t\t\t\tremoveMachineBtn.disabled = false;\n\t\t\t}\n        }\n     );\n}\n\nfunction saveOrUpdateMachine(machineId){\n\tvar ip = document.getElementById(\"ip\" + machineId);\n\tvar room = document.getElementById(\"room\" + machineId);\n\tvar mem = document.getElementById(\"mem\" + machineId);\n\tvar cpu = document.getElementById(\"cpu\" + machineId);\n\tvar virtual = document.getElementById(\"virtual\" + machineId);\n    var realIp = document.getElementById(\"realIp\" + machineId);\n    var machineType = document.getElementById(\"machineType\" + machineId);\n    var extraDesc = document.getElementById(\"extraDesc\" + machineId);\n    var collect = document.getElementById(\"collect\" + machineId);\n\n\tif(ip.value == \"\"){\n    \talert(\"IP不能为空!\");\n        ip.focus();\n\t\treturn false;\n    }\n    if(room.value == \"\"){\n        alert(\"机房不能为空!\");\n        room.focus();\n        return false;\n    }\n    if(mem.value == \"\"){\n        alert(\"内存不能为空!\");\n        mem.focus();\n        return false;\n    }\n    if(cpu.value == \"\"){\n        alert(\"CPU不能为空!\");\n        cpu.focus();\n        return false;\n    }\n    if(virtual.value == \"\"){\n        alert(\"是否虚机为空!\");\n        virtual.focus();\n        return false;\n    }\n    var addMachineBtn = document.getElementById(\"addMachineBtn\" + machineId);\n    addMachineBtn.disabled = true;\n    \n\t$.post(\n\t\t'/manage/machine/add.json',\n\t\t{\n            ip: ip.value,\n            room: room.value,\n            mem: mem.value,\n            cpu: cpu.value,\n            virtual: virtual.value,\n            realIp: realIp.value,\n            id:machineId,\n            machineType: machineType.value,\n            extraDesc: extraDesc.value,\n            collect: collect.value\n\t\t},\n        function(data){\n            if(data.result){\n                $(\"#machineInfo\" + machineId).html(\"<div class='alert alert-error' ><button class='close' data-dismiss='alert'>×</button><strong>Success!</strong>更新成功，窗口会自动关闭</div>\");\n                var targetId = \"#addMachineModal\" + machineId;\n                setTimeout(\"$('\" + targetId +\"').modal('hide');window.location.reload();\",1000);\n            }else{\n                addMachineBtn.disabled = false;\n                $(\"#machineInfo\" + machineId).html(\"<div class='alert alert-error' ><button class='close' data-dismiss='alert'>×</button><strong>Error!</strong>更新失败！</div>\");\n            }\n        }\n     );\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/manage/userManage.js",
    "content": "//验证手机号格式\nvar valPhones=/^(1[3|5|8][0-9]\\d{4,8};){0,6}(1[3|5|8][0-9]\\d{4,8})$/; \n//验证邮箱格式\nvar valEmails=/^(([a-zA-Z0-9]+[_|\\_|\\.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|\\_|\\.|\\-]?)*[a-zA-Z0-9]+\\.[a-zA-Z]{2,3};){0,6}([a-zA-Z0-9]+[_|\\_|\\.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|\\_|\\.|\\-]?)*[a-zA-Z0-9]+\\.[a-zA-Z]{2,3}$/;\nfunction saveOrUpdateUser(userId){\n\tvar name = document.getElementById(\"name\" + userId);\n\tvar chName = document.getElementById(\"chName\" + userId);\n\tvar email = document.getElementById(\"email\" + userId);\n\tvar mobile = document.getElementById(\"mobile\" + userId);\n\tvar type = document.getElementById(\"type\" + userId);\n\tif(name.value == \"\"){\n    \talert(\"域账户名不能为空!\");\n\t\tname.focus();\n\t\treturn false;\n    }\n\tif(chName.value == \"\"){\n    \talert(\"中文名不能为空!\");\n\t\tchName.focus();\n\t\treturn false;\n    }\n\tif(email.value == \"\"){\n\t\talert(\"邮箱不能为空!\");\n\t\temail.focus();\n\t\treturn false;\n\t}\n\tif(!valEmails.test(email.value)){\n\t\talert(\"邮箱格式错误!\");\n\t\temail.focus();\n\t\treturn false;\n\t}\n\tif(mobile.value == \"\"){\n\t\talert(\"手机号不能为空!\");\n\t\tmobile.focus();\n\t\treturn false;\n\t}\n\tif(!valPhones.test(mobile.value)){\n\t\talert(\"手机号格式错误!\");\n\t\tmobile.focus();\n\t\treturn false;\n\t}\n\tvar userBtn = document.getElementById(\"userBtn\" + userId);\n\tuserBtn.disabled = true;\n\t\n\t$.post(\n\t\t'/manage/user/add.do',\n\t\t{\n\t\t\tname: name.value,\n\t\t\tchName: chName.value,\n\t\t\temail: email.value,\n\t\t\tmobile: mobile.value,\n\t\t\ttype: type.value,\n\t\t\tuserId: userId\n\t\t},\n        function(data){\n            if(data==1){\n                $(\"#info\" + userId).html(\"<div class='alert alert-error' ><button class='close' data-dismiss='alert'>×</button><strong>Success!</strong>更新成功，窗口会自动关闭</div>\");\n                var targetId = \"#addUserModal\" + userId;\n                setTimeout(\"$('\" + targetId +\"').modal('hide');window.location.reload();\",1000);\n            }else{\n            \tuserBtn.disabled = false;\n                $(\"#info\" + userId).html(\"<div class='alert alert-error' ><button class='close' data-dismiss='alert'>×</button><strong>Error!</strong>更新失败！</div>\");\n            }\n        }\n     );\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/oldMemResource/css/invalid.css",
    "content": "\n.button,\n#main-content table tfoot td .bulk-actions select,\n.pagination a.number,\nform input.text-input,\nform textarea,\nform .wysiwyg,\nform select,\n.dp-popup {\n                -moz-border-radius: 4px;\n                -webkit-border-radius: 4px;\n\t\t\t\tborder-radius: 4px;\n\t\t\t}\n\t\t\t\n.content-box,\n.content-box-header,\nul.content-box-tabs li a.current,\n.shortcut-button,\n.notification {\n                -moz-border-radius: 6px;\n                -webkit-border-radius: 6px;\n\t\t\t\tborder-radius: 6px;\n                }\n\n.content-box-header {\n                -moz-border-radius-bottomleft: 0;\n                -moz-border-radius-bottomright: 0;\n                -webkit-border-bottom-left-radius: 0;\n                -webkit-border-bottom-right-radius: 0;\n\t\t\t\tborder-bottom-left-radius: 0;\n\t\t\t\tborder-bottom-right-radius: 0;\n                }\n\t\t\t\t\n.closed-box .content-box-header {\n                -moz-border-radius-bottomleft: 6px;\n                -moz-border-radius-bottomright: 6px;\n                -webkit-border-bottom-left-radius: 6px;\n                -webkit-border-bottom-right-radius: 6px;\n\t\t\t\tborder-bottom-left-radius: 6px;\n\t\t\t\tborder-bottom-right-radius: 6px;\n                }\n\nul.content-box-tabs li a.current {\n                -moz-border-radius-bottomleft: 0;\n                -moz-border-radius-bottomright: 0;\n                -webkit-border-bottom-left-radius: 0;\n                -webkit-border-bottom-right-radius: 0;\n\t\t\t\tborder-bottom-left-radius: 0;\n\t\t\t\tborder-bottom-right-radius: 0;\n                }\n\t\t\t\t\n\n.shortcut-button span {\n                -moz-border-radius: 7px;\n                -webkit-border-radius: 7px;\n\t\t\t\tborder-radius: 7px;\n                }\n\t\t\t\t\ndiv.wysiwyg ul.panel li a { opacity: 0.6; }\ndiv.wysiwyg ul.panel li a:hover, div.wysiwyg ul.panel li a.active { opacity: 0.99; }\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/oldMemResource/css/reset.css",
    "content": "html, body, div, span, applet, object, iframe,\nh1, h2, h3, h4, h5, h6, p, blockquote, pre,\na, abbr, acronym, address, big, cite, code,\ndel, dfn, em, font, img, ins, kbd, q, s, samp,\n\n/* Eric Meyer's Reset Stylesheet: http://meyerweb.com/eric/thoughts/2007/05/01/reset-reloaded/ */\n\nsmall, strike, strong, sub, sup, tt, var,\ndl, dt, dd, ol, ul, li,\nfieldset, form, label, legend,\ntable, caption, tbody, tfoot, thead, tr, th, td {\n\tmargin: 0;\n\tpadding: 0;\n\tborder: 0;\n\toutline: 0;\n\tfont-weight: inherit;\n\tfont-style: inherit;\n\tfont-size: 100%;\n\tfont-family: inherit;\n\tvertical-align: baseline;\n}\n/* remember to define focus styles! */\n:focus {\n\toutline: 0;\n}\nbody {\n\tline-height: 1;\n\tcolor: black;\n\tbackground: white;\n}\nol, ul {\n\tlist-style: none;\n}\n/* tables still need 'cellspacing=\"0\"' in the markup */\ntable {\n\tborder-collapse: separate;\n\tborder-spacing: 0;\n}\ncaption, th, td {\n\ttext-align: left;\n\tfont-weight: normal;\n}\nblockquote:before, blockquote:after,\nq:before, q:after {\n\tcontent: \"\";\n}\nblockquote, q {\n\tquotes: \"\" \"\";\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/oldMemResource/css/style.css",
    "content": "\n/********************************      Basic Structure      ********************************/\n\nhtml {\n                font-size: 100%;\n                height: 100%;\n                margin-bottom: 1px; /* Always show a scrollbar to avoid jumping when the scrollbar appears  */\n                }\n\nbody {\n                font-family: Arial, Helvetica, sans-serif;\n                color: #555;\n                background: #f0f0f0 url('../images/bg-body.gif') top left repeat-y;\n                font-size: 12px;\n                }\n\n#body-wrapper {\n                background: url('../images/bg-radial-gradient.gif') fixed 230px top no-repeat;\n                }                \n\n/********************************      Elements styling      ********************************/\n\nh1, h2, h3, h4, h5, h6 {\n                font-family: Helvetica, Arial, sans-serif;\n                color: #222;\n                font-weight: bold;\n                }\n\nh1            { font-family: Calibri, Helvetica, Arial, sans-serif; font-size: 31px; font-weight: bold; color: #fff; \n\t\t\t\t  position: absolute; top: -1000px;  /* Remove this line and delete the logo (in the HTML) if you don't want an image as a logo */\n\t\t\t\t}\n\t\t\t\t\nh2            { font-size: 26px; padding: 0 0 10px 0; }\nh3            { font-size: 17px; padding: 0 0 10px 0; }\nh4            { font-size: 16px; padding: 0 0 5px 0; }\nh5            { font-size: 14px; padding: 0 0 5px 0; }\nh6            { font-size: 12px; padding: 0 0 5px 0; }\n\n\na              { color: #57a000; text-decoration: none; }\na:hover     { color: #000; }\na:active     { color: #777; }\na:focus     { outline: 1px; }\n\nstrong       { font-weight: bold; color: #333; }\n\nsmall   \t\t{ font-size: 0.85em; }\n\npre           { font-family: monospace; }\n\np {\n                padding: 5px 0 10px 0;\n                line-height: 1.6em;\n                }\n\n/********************************      General Classes      ********************************/\n\n.clear {\n                clear: both;\n                }\n\t\t\t\t\n.align-left {\n                float: left;\n                }\n\t\t\t\t\n.align-right {\n                float: right;\n                }\n\n/************ Button ************/\n.button {\n\t\t\t\tfont-family: Verdana, Arial, sans-serif;\n                display: inline-block;\n                background: #459300 url('../images/bg-button-green.gif') top left repeat-x !important;\n                border: 1px solid #459300 !important;\n                padding: 4px 7px 4px 7px !important;\n                color: #fff !important;\n                font-size: 11px !important;\n                cursor: pointer;\n                }\n                \n.button:hover {\n                text-decoration: underline;\n                }\n                \n.button:active {\n                padding: 5px 7px 3px 7px !important;\n                }\n\t\t\t\t\na.remove-link {\n\t\t\t\tcolor: #bb0000;\n\t\t\t\t}\n\na.remove-link:hover {\n\t\t\t\tcolor: #000;\n\t\t\t\t}\n\n/********************************      Sidebar      ********************************/\n\n#sidebar {\n                background: url('../images/bg-sidebar.gif') top left no-repeat;\n                width: 230px;\n                height: 100%;\n                position: absolute;\n                left: 0;\n                top: 0;\n                color: #888;\n                font-size: 11px;\n                }\n\n#sidebar #sidebar-wrapper {\n                margin: 0 0 0 9px;\n                }\n\n#sidebar a,\n#sidebar a:active {\n                color:#ccc;\n                }\n\n#sidebar a:hover {\n                color:#fff;\n                }\n\n#sidebar #sidebar-title {\n                margin: 40px 0 40px 15px;\n                }\n\n#sidebar #logo {\n                margin: 40px 0 40px 0;\n                }\n\n#sidebar #profile-links {\n                padding: 0 15px 20px 15px;\n                text-align: right;\n                line-height: 1.5em;\n                }\n\n/************ Sidebar Accordion Menu ************/\n\n#sidebar #main-nav {\n                width: 206px;\n                padding: 0;\n                margin: 0 0 0 15px;\n                font-family: Helvetica, Arial, sans-serif;\n                }\n\n#sidebar #main-nav li {\n                list-style: none;\n                padding-bottom: 10px;\n                text-align: right;\n                }\n\n#sidebar #main-nav li a.nav-top-item {\n                background: transparent url('../images/bg-menu-item-green.gif') right center no-repeat; /* Background image for default color scheme - green */\n                padding: 10px 15px;\n                color: #fff;\n                font-size: 14px;\n                cursor: pointer;\n                display: block;\n                text-decoration: none;\n                }\n\n#sidebar #main-nav li a.current {\n                background-image: url('../images/bg-menu-item-current.gif') !important;\n                color: #333;\n                font-weight: bold;\n                }\n                \n#sidebar #main-nav li a.current:hover {\n                color: #333;\n                }\n\n#sidebar #main-nav ul {\n                padding: 0;\n                font-size: 12px;\n                margin: 0;\n                }\n\n#sidebar #main-nav ul li {\n                list-style: none;\n                margin: 0;\n                text-align: right;\n\t\t\t\tpadding: 0;\n                }\n\n#sidebar #main-nav ul li a {\n                padding: 8px 15px;\n                display: block;\n                color: #aaa;\n                font-size: 13px;\n                line-height: 1.2em;\n                }\n\n#sidebar #main-nav ul li a:hover,\n#sidebar #main-nav ul li a.current,\n#sidebar #main-nav ul li a.current:hover {\n                color: #fff;\n                }\n\n#sidebar #main-nav ul li a.current {\n                background: transparent url('../images/menu-current-arrow.gif') right center no-repeat !important;\n                }\n\n\n/************ Messages ************/\n\n#messages p,\n#messages form {\n                border-top: 1px solid #ddd;\n                padding: 10px 0;\n                }\n\n#messages h4 {\n                padding: 10px 0;\n                }\n\t\t\t\t\n#messages fieldset {\n                margin: 0;\n                }\n\t\t\t\t\n#messages textarea {\n                margin: 0 0 15px 0;\n                }\n/********************************      Main Content      ********************************/\n\n/************ Layout ************/\n\n#main-content {\n                margin: 0 30px 0 260px;\n                padding: 40px 0 0 0;\n                }\n\n.column-left {\n                width: 48%;\n                float: left;\n                }\n                \n.column-right {\n                width: 48%;\n                float: right;\n                }\n               \n#page-intro {\n                font-size: 17px;\n                padding: 0 0 20px 0;\n                }\n\n\t\t\t\t\n#footer {\n\t\t\t\tborder-top: 1px solid #ccc;\n\t\t\t\tmargin: 40px 0 0 0;\n\t\t\t\tpadding: 20px 0;\n\t\t\t\tfont-size: 12px;\n                }\n/************ Lists ************/\n\n#main-content ul,\n#main-content ol {\n                padding: 10px 0;\n                }\n\n/* Unordered List */\n\n#main-content ul li {\n                background: url('../images/icons/bullet_black.png') center left no-repeat;\n                padding: 4px 0 4px 20px;\n                }\n\n/* Ordered List */\n\n#main-content ol {\n                padding: 0 0 0 24px;\n                }\n\n#main-content ol li {\n                list-style: decimal;\n                padding: 4px 0;\n                }\n\n/*************** Content Box ***************/\n\n.content-box {\n                border: 1px solid #ccc;\n                margin: 0 0 20px 0;\n                background: #fff;\n                }\n\n.content-box-header {\n                background: #e5e5e5 url('../images/bg-content-box.gif') top left repeat-x;\n                margin-top: 1px;\n                height: 40px;\n                }\n\n.content-box-header h3 {\n                padding: 12px 15px 10px;\n                float: left;\n                }\n\nul.content-box-tabs {\n                float: right;\n                padding: 12px 15px 0 0 !important;\n\t\t\t\tmargin: 0 !important;\n                }\n\nul.content-box-tabs li {\n                float: left;\n                margin: 0;\n                padding: 0 !important;\n                background-image: none !important;\n                }\n                \nul.content-box-tabs li a {\n                color: #333;\n                padding: 8px 10px;\n                display: block;\n                margin: 1px;\n                border-bottom: 0;\n                }\n\nul.content-box-tabs li a:hover {\n                color: #57a000;\n                }              \n                \nul.content-box-tabs li a.current {\n                background: #fff;\n                border: 1px solid #ccc;\n                border-bottom: 0;\n                margin: 0;\n                }\n\n.content-box-content {\n                padding: 20px;\n                font-size: 13px;\n                border-top: 1px solid #ccc;\n                }\n                \n/************ Table ************/\n\n#main-content table {\n                width: 100%;\n                border-collapse: collapse;\n                }\n                \n#main-content table thead th {\n                font-weight: bold;\n                font-size: 15px;\n                border-bottom: 1px solid #ddd;\n                }\n                \n#main-content tbody {\n                border-bottom: 1px solid #ddd;\n                }\n                \n#main-content tbody tr {\n                background: #fff;\n                }\n              \n#main-content tbody tr.alt-row {\n                background: #f3f3f3;\n                }\n                \n#main-content table td,\n#main-content table th {\n                padding: 10px;\n                line-height: 1.3em;\n                }        \n\t\t\t\t\n#main-content table tfoot td .bulk-actions {\n                padding: 15px 0 5px 0;\n                } \n\t\t\t\t\n#main-content table tfoot td .bulk-actions select {\n                padding: 4px;\n\t\t\t\tborder: 1px solid #ccc;\n                }      \n\t\t\t\t\n/*************** Pagination ***************/\n\n#main-content .pagination {\n                text-align: right;\n                padding: 20px 0 5px 0;\n                font-family: Verdana, Arial, Helvetica, sans-serif;\n                font-size: 10px;\n                }\n.pagination a {\n                margin: 0 5px 0 0;\n                padding: 3px 6px;\n                }\n\n.pagination a.number {\n\t\t\t\tborder: 1px solid #ddd;\n                }\n\n.pagination a.current {\n                background: #469400 url('../images/bg-button-green.gif') top left repeat-x !important;\n                border-color: #459300 !important;\n                color: #fff !important;\n                }\n\t\t\t\t\n.pagination a.current:hover {\n\t\t\t\ttext-decoration: underline;\n                }\n\n/************ Shortcut Buttons ************/\n\n.shortcut-button {\n                border: 1px solid #ccc;\n                background: #f7f7f7 url('../images/shortcut-button-bg.gif') top left no-repeat;\n                display: block;\n                width: 120px;\n                margin: 0 0 20px 0;\n                }\n\n.shortcut-button span {\n                border: 1px solid #fff;\n                display:block;\n                padding: 15px 10px 15px 10px;\n                text-align: center;\n                color: #555;\n                font-size: 13px;\n                line-height: 1.3em;\n                }\n\n.shortcut-button span img {\n                margin-bottom: 10px;\n                }\n\n.shortcut-button:hover {\n                background: #fff;\n\t\t\t\t\n                }\n\t\t\t\t\n.shortcut-button span:hover {\n\t\t\t\tcolor: #57a000; \n                }\n\nul.shortcut-buttons-set li {\n                float: left;\n                margin: 0 15px 0 0;\n\t\t\t\tpadding: 0 !important;\n\t\t\t\tbackground: 0;\n                }\n\n/*************** Forms ***************/\n\nform label {\n                display: block;\n                padding: 0 0 10px;\n                font-weight: bold;\n                }\n             \nform fieldset legend {\n                font-weight: bold;\n                margin-bottom: 10px;\n                padding-top: 10px;\n                }\n                \nform p small {\n                font-size: 0.75em;\n                color: #777;\n                }\n\t\t\t\t\n\t\t\t\t\nform input.text-input,\nform select,\nform textarea,\nform .wysiwyg {\n                padding: 6px;\n                font-size: 13px;\n                background: #fff url('../images/bg-form-field.gif') top left repeat-x;\n                border: 1px solid #d5d5d5;\n\t\t\t\tcolor: #333;\n                }\nform .tiny-input {\n                width: 5% !important;\n                }\t\t\t\t\n            \nform .small-input {\n                width: 25% !important;\n                }\n                \nform .medium-input {\n                width: 50% !important;\n                }\n                \nform .large-input {\n                width: 97.5% !important;\n\t\t\t\tfont-size: 16px !important;\n\t\t\t\tpadding: 8px !important;\n                }\n                \nform textarea {\n                width: 97.5% !important;\n                font-family: Arial, Helvetica, sans-serif;\n                }\n                \nform select {\n                padding: 4px;\n                background: #fff;\n                }\n\t\t\t\t\nform input[type=\"checkbox\"],\nform input[type=\"radio\"] {\n\t\t\t\tpadding: 0;\n                background: none;\n\t\t\t\tborder: 0;\n                }\n\n/*************** Notifications ***************/\n\n.notification {\n                position: relative;\n                margin: 0 0 15px 0;\n                padding: 0;\n                border: 1px solid;\n                background-position: 10px 11px !important;\n                background-repeat: no-repeat !important;\n                font-size: 13px;\n                width: 99.8%;\n                }\n                \n\n.attention {\n                background: #fffbcc url('../images/icons/exclamation.png') 10px 11px no-repeat;\n                border-color: #e6db55;\n                color: #666452;\n                }\n\n.information {\n                background: #dbe3ff url('../images/icons/information.png');\n                border-color: #a2b4ee;\n                color: #585b66;\n                }\n\n.success {\n                background: #d5ffce url('../images/icons/tick_circle.png');\n                border-color: #9adf8f;\n                color: #556652;\n                }\n\n.error {\n                background: #ffcece url('../images/icons/cross_circle.png');\n                border-color: #df8f8f;\n                color: #665252;\n                }\n\n.notification div {\n                display:block;\n                font-style:normal;\n                padding: 10px 10px 10px 36px;\n                line-height: 1.5em;\n                }\n\n.notification .close {\n                color:#990000;\n                font-size:9px;\n                position:absolute;\n                right:5px;\n                top:5px;\n                }\n\n/* Notification for form inputs */\n\n.input-notification {\n\t\t\t\tbackground-position: left 2px;\n\t\t\t\tbackground-repeat: no-repeat;\n\t\t\t\tpadding: 2px 0 2px 22px;\n\t\t\t\tbackground-color: transparent;\n\t\t\t\tmargin: 0 0 0 5px;\n\t\t\t\t}\n\n/* Notification for login page */\n\n#login-wrapper #login-content .notification {\n\t\t\t\tborder: 0;\n\t\t\t\tbackground-color: #141414;\n\t\t\t\tcolor: #fff !important;\n\t\t\t\t}\n\n/********************************      Login Page      ********************************/\n\nbody#login {\n                color: #fff;\n                background: #222 url('../images/bg-login.gif');\n\t\t\t\t}\n\t\t\t\t\n#login-wrapper {\n                background: url('../images/bg-login-top.png') top left repeat-x;\n\t\t\t\t}\n\n#login-wrapper #login-top {\n\t\t\t\twidth: 100%;\n\t\t\t\tpadding: 140px 0 50px 0;\n\t\t\t\ttext-align: center;\n\t\t\t\t}\n\t\t\t\t\n#login-wrapper #login-content {\n\t\t\t\ttext-align: left;\n\t\t\t\twidth: 300px;\n\t\t\t\tmargin: 0 auto;\n\t\t\t\t}\n\t\t\t\t\n#login-wrapper #login-content label {\n\t\t\t\tcolor: #fff;\n\t\t\t\tfont-weight: normal;\n\t\t\t\tfont-size: 14px;\n\t\t\t\tfont-family: Helvetica, Arial, sans-serif;\n\t\t\t\tfloat: left;\n\t\t\t\twidth: 70px;\n\t\t\t\tpadding: 0;\n\t\t\t\t}\n\t\t\t\t\n#login-wrapper #login-content input {\n\t\t\t\twidth: 200px;\n\t\t\t\tfloat: right;\n\t\t\t\tmargin: 0 0 20px 0;\n\t\t\t\tborder: 0;\n\t\t\t\tbackground: #fff;\n\t\t\t\t}\n\t\t\t\t\n#login-wrapper #login-content p {\n\t\t\t\tpadding: 0;\n\t\t\t\t}\n\t\t\t\t\n#login-wrapper #login-content p#remember-password {\n\t\t\t\tfloat: right;\n\t\t\t\t}\n\t\t\t\t\n#login-wrapper #login-content p#remember-password input {\n\t\t\t\tfloat: none;\n\t\t\t\twidth: auto;\n\t\t\t\tborder: 0;\n\t\t\t\tbackground: none;\n\t\t\t\tmargin: 0 10px 0 0;\n\t\t\t\t}\n\t\t\t\t\n#login-wrapper #login-content p .button {\n\t\t\t\twidth: auto;\n\t\t\t\tmargin-top: 20px;\n\t\t\t\t}\n\n/********************************      jQuery plugins styles      ********************************/\n\n/*************** Facebox ***************/\n\n#facebox .b {\n  background:url(../images/b.png);\n}\n\n#facebox .tl {\n  background:url(../images/tl.png);\n}\n\n#facebox .tr {\n  background:url(../images/tr.png);\n}\n\n#facebox .bl {\n  background:url(../images/bl.png);\n}\n\n#facebox .br {\n  background:url(../images/br.png);\n}\n\n#facebox {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 100;\n  text-align: left;\n}\n\n#facebox .popup {\n  position: relative;\n}\n\n#facebox table {\n  border-collapse: collapse;\n}\n\n#facebox td {\n  border-bottom: 0;\n  padding: 0;\n}\n\n#facebox .body {\n  padding: 10px;\n  background: #fff;\n  width: 370px;\n}\n\n#facebox .loading {\n  text-align: center;\n}\n\n#facebox .image {\n  text-align: center;\n}\n\n#facebox img {\n  border: 0;\n  margin: 0;\n}\n\n#facebox .footer {\n  border-top: 1px solid #DDDDDD;\n  padding-top: 5px;\n  margin-top: 10px;\n  text-align: right;\n}\n\n#facebox .tl, #facebox .tr, #facebox .bl, #facebox .br {\n  height: 10px;\n  width: 10px;\n  overflow: hidden;\n  padding: 0;\n}\n\n#facebox_overlay {\n  position: fixed;\n  top: 0px;\n  left: 0px;\n  height:100%;\n  width:100%;\n}\n\n.facebox_hide {\n  z-index:-100;\n}\n\n.facebox_overlayBG {\n  background-color: #000;\n  z-index: 99;\n}\n\n/*************** jQuery WYSIWYG ***************/\n\ndiv.wysiwyg { border: 1px solid #cccccc; padding: 5px; background-color: #ffffff; width: 97.5% !important; }\ndiv.wysiwyg * { margin: 0; padding: 0; }\n\ndiv.wysiwyg ul.panel { border-bottom: 1px solid #cccccc; float: left; width: 100%; padding: 0 0 5px 0; }\ndiv.wysiwyg ul.panel li { list-style-type: none; float: left; margin: 0 2px; padding: 0 !important;  background: #ffffff; background-image: none !important;}\ndiv.wysiwyg ul.panel li.separator { height: 16px; margin: 0 4px; border-left: 1px solid #cccccc; }\ndiv.wysiwyg ul.panel li a { display: block; padding: 0 !important; width: 16px; height: 16px; background: url('../images/icons/jquery.wysiwyg.gif') no-repeat -64px -80px; border: 0; cursor: pointer; padding: 1px; }\ndiv.wysiwyg ul.panel li a:hover, div.wysiwyg ul.panel li a.active {  }\ndiv.wysiwyg ul.panel li a.active { background-color: #f9f9f9; border: 1px solid #cccccc; border-left-color: #aaaaaa; border-top-color: #aaaaaa; padding: 0; }\n\ndiv.wysiwyg ul.panel li a.bold { background-position: 0 -16px; }\ndiv.wysiwyg ul.panel li a.italic { background-position: -16px -16px; }\ndiv.wysiwyg ul.panel li a.strikeThrough { background-position: -32px -16px; }\ndiv.wysiwyg ul.panel li a.underline { background-position: -48px -16px; }\n\ndiv.wysiwyg ul.panel li a.justifyLeft { background-position: 0 0; }\ndiv.wysiwyg ul.panel li a.justifyCenter { background-position: -16px 0; }\ndiv.wysiwyg ul.panel li a.justifyRight { background-position: -32px 0; }\ndiv.wysiwyg ul.panel li a.justifyFull { background-position: -48px 0; }\n\ndiv.wysiwyg ul.panel li a.indent { background-position: -64px 0; }\ndiv.wysiwyg ul.panel li a.outdent { background-position: -80px 0; }\n\ndiv.wysiwyg ul.panel li a.subscript { background-position: -64px -16px; }\ndiv.wysiwyg ul.panel li a.superscript { background-position: -80px -16px; }\n\ndiv.wysiwyg ul.panel li a.undo { background-position: 0 -64px; }\ndiv.wysiwyg ul.panel li a.redo { background-position: -16px -64px; }\n\ndiv.wysiwyg ul.panel li a.insertOrderedList { background-position: -32px -48px; }\ndiv.wysiwyg ul.panel li a.insertUnorderedList { background-position: -16px -48px; }\ndiv.wysiwyg ul.panel li a.insertHorizontalRule { background-position: 0 -48px; }\n\ndiv.wysiwyg ul.panel li a.h1 { background-position: 0 -32px; }\ndiv.wysiwyg ul.panel li a.h2 { background-position: -16px -32px; }\ndiv.wysiwyg ul.panel li a.h3 { background-position: -32px -32px; }\ndiv.wysiwyg ul.panel li a.h4 { background-position: -48px -32px; }\ndiv.wysiwyg ul.panel li a.h5 { background-position: -64px -32px; }\ndiv.wysiwyg ul.panel li a.h6 { background-position: -80px -32px; }\n\ndiv.wysiwyg ul.panel li a.cut { background-position: -32px -64px; }\ndiv.wysiwyg ul.panel li a.copy { background-position: -48px -64px; }\ndiv.wysiwyg ul.panel li a.paste { background-position: -64px -64px; }\n\ndiv.wysiwyg ul.panel li a.increaseFontSize { background-position: -16px -80px; }\ndiv.wysiwyg ul.panel li a.decreaseFontSize { background-position: -32px -80px; }\n\ndiv.wysiwyg ul.panel li a.createLink { background-position: -80px -48px; }\ndiv.wysiwyg ul.panel li a.insertImage { background-position: -80px -80px; }\n\ndiv.wysiwyg ul.panel li a.html { background-position: -48px -48px; }\ndiv.wysiwyg ul.panel li a.removeFormat { background-position: -80px -64px; }\n\ndiv.wysiwyg ul.panel li a.empty { background-position: -64px -80px; }\n\ndiv.wysiwyg iframe { border: 0; margin: 5px 0 0 0; clear: left; width: 97.5% !important; }\n\n.tab-content{ padding-left:10px;}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/oldMemResource/scripts/facebox.js",
    "content": "/*\n * Facebox (for jQuery)\n * version: 1.2 (05/05/2008)\n * @requires jQuery v1.2 or later\n *\n * Examples at http://famspam.com/facebox/\n *\n * Licensed under the MIT:\n *   http://www.opensource.org/licenses/mit-license.php\n *\n * Copyright 2007, 2008 Chris Wanstrath [ chris@ozmm.org ]\n *\n * Usage:\n *  \n *  jQuery(document).ready(function() {\n *    jQuery('a[rel*=facebox]').facebox() \n *  })\n *\n *  <a href=\"#terms\" rel=\"facebox\">Terms</a>\n *    Loads the #terms div in the box\n *\n *  <a href=\"terms.html\" rel=\"facebox\">Terms</a>\n *    Loads the terms.html page in the box\n *\n *  <a href=\"terms.png\" rel=\"facebox\">Terms</a>\n *    Loads the terms.png image in the box\n *\n *\n *  You can also use it programmatically:\n * \n *    jQuery.facebox('some html')\n *\n *  The above will open a facebox with \"some html\" as the content.\n *    \n *    jQuery.facebox(function($) { \n *      $.get('blah.html', function(data) { $.facebox(data) })\n *    })\n *\n *  The above will show a loading screen before the passed function is called,\n *  allowing for a better ajaxy experience.\n *\n *  The facebox function can also display an ajax page or image:\n *  \n *    jQuery.facebox({ ajax: 'remote.html' })\n *    jQuery.facebox({ image: 'dude.jpg' })\n *\n *  Want to close the facebox?  Trigger the 'close.facebox' document event:\n *\n *    jQuery(document).trigger('close.facebox')\n *\n *  Facebox also has a bunch of other hooks:\n *\n *    loading.facebox\n *    beforeReveal.facebox\n *    reveal.facebox (aliased as 'afterReveal.facebox')\n *    init.facebox\n *\n *  Simply bind a function to any of these hooks:\n *\n *   $(document).bind('reveal.facebox', function() { ...stuff to do after the facebox and contents are revealed... })\n *\n */\n(function($) {\n  $.facebox = function(data, klass) {\n    $.facebox.loading()\n\n    if (data.ajax) fillFaceboxFromAjax(data.ajax)\n    else if (data.image) fillFaceboxFromImage(data.image)\n    else if (data.div) fillFaceboxFromHref(data.div)\n    else if ($.isFunction(data)) data.call($)\n    else $.facebox.reveal(data, klass)\n  }\n\n  /*\n   * Public, $.facebox methods\n   */\n\n  $.extend($.facebox, {\n    settings: {\n      opacity      : 0,\n      overlay      : true,\n      loadingImage : '/resources/images/loading.gif',\n      closeImage   : '/resources/images/closelabel.gif',\n      imageTypes   : [ 'png', 'jpg', 'jpeg', 'gif' ],\n      faceboxHtml  : '\\\n    <div id=\"facebox\" style=\"display:none;\"> \\\n      <div class=\"popup\"> \\\n        <table> \\\n          <tbody> \\\n            <tr> \\\n              <td class=\"tl\"/><td class=\"b\"/><td class=\"tr\"/> \\\n            </tr> \\\n            <tr> \\\n              <td class=\"b\"/> \\\n              <td class=\"body\"> \\\n                <div class=\"content\"> \\\n                </div> \\\n                <div class=\"footer\"> \\\n                  <a href=\"#\" class=\"close\"> \\\n                    <img src=\"/resources/images/closelabel.gif\" title=\"close\" class=\"close_image\" /> \\\n                  </a> \\\n                </div> \\\n              </td> \\\n              <td class=\"b\"/> \\\n            </tr> \\\n            <tr> \\\n              <td class=\"bl\"/><td class=\"b\"/><td class=\"br\"/> \\\n            </tr> \\\n          </tbody> \\\n        </table> \\\n      </div> \\\n    </div>'\n    },\n\n    loading: function() {\n      init()\n      if ($('#facebox .loading').length == 1) return true\n      showOverlay()\n\n      $('#facebox .content').empty()\n      $('#facebox .body').children().hide().end().\n        append('<div class=\"loading\"><img src=\"'+$.facebox.settings.loadingImage+'\"/></div>')\n\n      $('#facebox').css({\n        top:\tgetPageScroll()[1] + (getPageHeight() / 10),\n        left:\t385.5\n      }).show()\n\n      $(document).bind('keydown.facebox', function(e) {\n        if (e.keyCode == 27) $.facebox.close()\n        return true\n      })\n      $(document).trigger('loading.facebox')\n    },\n\n    reveal: function(data, klass) {\n      $(document).trigger('beforeReveal.facebox')\n      if (klass) $('#facebox .content').addClass(klass)\n      $('#facebox .content').append(data)\n      $('#facebox .loading').remove()\n      $('#facebox .body').children().fadeIn('normal')\n      $('#facebox').css('left', $(window).width() / 2 - ($('#facebox table').width() / 2))\n      $(document).trigger('reveal.facebox').trigger('afterReveal.facebox')\n    },\n\n    close: function() {\n      $(document).trigger('close.facebox')\n      return false\n    }\n  })\n\n  /*\n   * Public, $.fn methods\n   */\n\n  $.fn.facebox = function(settings) {\n    init(settings)\n\n    function clickHandler() {\n      $.facebox.loading(true)\n\n      // support for rel=\"facebox.inline_popup\" syntax, to add a class\n      // also supports deprecated \"facebox[.inline_popup]\" syntax\n      var klass = this.rel.match(/facebox\\[?\\.(\\w+)\\]?/)\n      if (klass) klass = klass[1]\n\n      fillFaceboxFromHref(this.href, klass)\n      return false\n    }\n\n    return this.click(clickHandler)\n  }\n\n  /*\n   * Private methods\n   */\n\n  // called one time to setup facebox on this page\n  function init(settings) {\n    if ($.facebox.settings.inited) return true\n    else $.facebox.settings.inited = true\n\n    $(document).trigger('init.facebox')\n    makeCompatible()\n\n    var imageTypes = $.facebox.settings.imageTypes.join('|')\n    $.facebox.settings.imageTypesRegexp = new RegExp('\\.' + imageTypes + '$', 'i')\n\n    if (settings) $.extend($.facebox.settings, settings)\n    $('body').append($.facebox.settings.faceboxHtml)\n\n    var preload = [ new Image(), new Image() ]\n    preload[0].src = $.facebox.settings.closeImage\n    preload[1].src = $.facebox.settings.loadingImage\n\n    $('#facebox').find('.b:first, .bl, .br, .tl, .tr').each(function() {\n      preload.push(new Image())\n      preload.slice(-1).src = $(this).css('background-image').replace(/url\\((.+)\\)/, '$1')\n    })\n\n    $('#facebox .close').click($.facebox.close)\n    $('#facebox .close_image').attr('src', $.facebox.settings.closeImage)\n  }\n  \n  // getPageScroll() by quirksmode.com\n  function getPageScroll() {\n    var xScroll, yScroll;\n    if (self.pageYOffset) {\n      yScroll = self.pageYOffset;\n      xScroll = self.pageXOffset;\n    } else if (document.documentElement && document.documentElement.scrollTop) {\t // Explorer 6 Strict\n      yScroll = document.documentElement.scrollTop;\n      xScroll = document.documentElement.scrollLeft;\n    } else if (document.body) {// all other Explorers\n      yScroll = document.body.scrollTop;\n      xScroll = document.body.scrollLeft;\t\n    }\n    return new Array(xScroll,yScroll) \n  }\n\n  // Adapted from getPageSize() by quirksmode.com\n  function getPageHeight() {\n    var windowHeight\n    if (self.innerHeight) {\t// all except Explorer\n      windowHeight = self.innerHeight;\n    } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode\n      windowHeight = document.documentElement.clientHeight;\n    } else if (document.body) { // other Explorers\n      windowHeight = document.body.clientHeight;\n    }\t\n    return windowHeight\n  }\n\n  // Backwards compatibility\n  function makeCompatible() {\n    var $s = $.facebox.settings\n\n    $s.loadingImage = $s.loading_image || $s.loadingImage\n    $s.closeImage = $s.close_image || $s.closeImage\n    $s.imageTypes = $s.image_types || $s.imageTypes\n    $s.faceboxHtml = $s.facebox_html || $s.faceboxHtml\n  }\n\n  // Figures out what you want to display and displays it\n  // formats are:\n  //     div: #id\n  //   image: blah.extension\n  //    ajax: anything else\n  function fillFaceboxFromHref(href, klass) {\n    // div\n    if (href.match(/#/)) {\n      var url    = window.location.href.split('#')[0]\n      var target = href.replace(url,'')\n      $.facebox.reveal($(target).clone().show(), klass)\n\n    // image\n    } else if (href.match($.facebox.settings.imageTypesRegexp)) {\n      fillFaceboxFromImage(href, klass)\n    // ajax\n    } else {\n      fillFaceboxFromAjax(href, klass)\n    }\n  }\n\n  function fillFaceboxFromImage(href, klass) {\n    var image = new Image()\n    image.onload = function() {\n      $.facebox.reveal('<div class=\"image\"><img src=\"' + image.src + '\" /></div>', klass)\n    }\n    image.src = href\n  }\n\n  function fillFaceboxFromAjax(href, klass) {\n    $.get(href, function(data) { $.facebox.reveal(data, klass) })\n  }\n\n  function skipOverlay() {\n    return $.facebox.settings.overlay == false || $.facebox.settings.opacity === null \n  }\n\n  function showOverlay() {\n    if (skipOverlay()) return\n\n    if ($('facebox_overlay').length == 0) \n      $(\"body\").append('<div id=\"facebox_overlay\" class=\"facebox_hide\"></div>')\n\n    $('#facebox_overlay').hide().addClass(\"facebox_overlayBG\")\n      .css('opacity', $.facebox.settings.opacity)\n      .click(function() { $(document).trigger('close.facebox') })\n      .fadeIn(200)\n    return false\n  }\n\n  function hideOverlay() {\n    if (skipOverlay()) return\n\n    $('#facebox_overlay').fadeOut(200, function(){\n      $(\"#facebox_overlay\").removeClass(\"facebox_overlayBG\")\n      $(\"#facebox_overlay\").addClass(\"facebox_hide\") \n      $(\"#facebox_overlay\").remove()\n    })\n    \n    return false\n  }\n\n  /*\n   * Bindings\n   */\n\n  $(document).bind('close.facebox', function() {\n    $(document).unbind('keydown.facebox')\n    $('#facebox').fadeOut(function() {\n      $('#facebox .content').removeClass().addClass('content')\n      hideOverlay()\n      $('#facebox .loading').remove()\n    })\n  })\n\n})(jQuery);\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/oldMemResource/scripts/jquery.wysiwyg.js",
    "content": "/**\n * WYSIWYG - jQuery plugin 0.5\n *\n * Copyright (c) 2008-2009 Juan M Martinez\n * http://plugins.jquery.com/project/jWYSIWYG\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 * $Id: $\n */\n(function( $ )\n{\n    $.fn.document = function()\n    {\n        var element = this[0];\n\n        if ( element.nodeName.toLowerCase() == 'iframe' )\n            return element.contentWindow.document;\n            /*\n            return ( $.browser.msie )\n                ? document.frames[element.id].document\n                : element.contentWindow.document // contentDocument;\n             */\n        else\n            return $(this);\n    };\n\n    $.fn.documentSelection = function()\n    {\n        var element = this[0];\n\n        if ( element.contentWindow.document.selection )\n            return element.contentWindow.document.selection.createRange().text;\n        else\n            return element.contentWindow.getSelection().toString();\n    };\n\n    $.fn.wysiwyg = function( options )\n    {\n        if ( arguments.length > 0 && arguments[0].constructor == String )\n        {\n            var action = arguments[0].toString();\n            var params = [];\n\n            for ( var i = 1; i < arguments.length; i++ )\n                params[i - 1] = arguments[i];\n\n            if ( action in Wysiwyg )\n            {\n                return this.each(function()\n                {\n                    $.data(this, 'wysiwyg')\n                     .designMode();\n\n                    Wysiwyg[action].apply(this, params);\n                });\n            }\n            else return this;\n        }\n\n        var controls = {};\n\n        /**\n         * If the user set custom controls, we catch it, and merge with the\n         * defaults controls later.\n         */\n        if ( options && options.controls )\n        {\n            var controls = options.controls;\n            delete options.controls;\n        }\n\n        var options = $.extend({\n            html : '<'+'?xml version=\"1.0\" encoding=\"UTF-8\"?'+'><!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\"><html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\"><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">STYLE_SHEET</head><body style=\"font-family: Arial, Helvetica, sans-serif !important; font-size: 13px; height: 100%; line-height: 1.5em !important;\">INITIAL_CONTENT</body></html>',\n            css  : {},\n\n            debug        : false,\n\n            autoSave     : true,  // http://code.google.com/p/jwysiwyg/issues/detail?id=11\n            rmUnwantedBr : true,  // http://code.google.com/p/jwysiwyg/issues/detail?id=15\n            brIE         : true,\n\n            controls : {},\n            messages : {}\n        }, options);\n\n        options.messages = $.extend(true, options.messages, Wysiwyg.MSGS_EN);\n        options.controls = $.extend(true, options.controls, Wysiwyg.TOOLBAR);\n\n        for ( var control in controls )\n        {\n            if ( control in options.controls )\n                $.extend(options.controls[control], controls[control]);\n            else\n                options.controls[control] = controls[control];\n        }\n\n        // not break the chain\n        return this.each(function()\n        {\n            Wysiwyg(this, options);\n        });\n    };\n\n    function Wysiwyg( element, options )\n    {\n        return this instanceof Wysiwyg\n            ? this.init(element, options)\n            : new Wysiwyg(element, options);\n    }\n\n    $.extend(Wysiwyg, {\n        insertImage : function( szURL, attributes )\n        {\n            var self = $.data(this, 'wysiwyg');\n\n            if ( self.constructor == Wysiwyg && szURL && szURL.length > 0 )\n            {\n                if ( attributes )\n                {\n                    self.editorDoc.execCommand('insertImage', false, '#jwysiwyg#');\n                    var img = self.getElementByAttributeValue('img', 'src', '#jwysiwyg#');\n\n                    if ( img )\n                    {\n                        img.src = szURL;\n\n                        for ( var attribute in attributes )\n                        {\n                            img.setAttribute(attribute, attributes[attribute]);\n                        }\n                    }\n                }\n                else\n                {\n                    self.editorDoc.execCommand('insertImage', false, szURL);\n                }\n            }\n        },\n\n        createLink : function( szURL )\n        {\n            var self = $.data(this, 'wysiwyg');\n\n            if ( self.constructor == Wysiwyg && szURL && szURL.length > 0 )\n            {\n                var selection = $(self.editor).documentSelection();\n\n                if ( selection.length > 0 )\n                {\n                    self.editorDoc.execCommand('unlink', false, []);\n                    self.editorDoc.execCommand('createLink', false, szURL);\n                }\n                else if ( self.options.messages.nonSelection )\n                    alert(self.options.messages.nonSelection);\n            }\n        },\n\n        setContent : function( newContent )\n        {\n            var self = $.data(this, 'wysiwyg');\n                self.setContent( newContent );\n                self.saveContent();\n        },\n\n        clear : function()\n        {\n            var self = $.data(this, 'wysiwyg');\n                self.setContent('');\n                self.saveContent();\n        },\n\n        MSGS_EN : {\n            nonSelection : 'select the text you wish to link'\n        },\n\n        TOOLBAR : {\n            bold          : { visible : true, tags : ['b', 'strong'], css : { fontWeight : 'bold' } },\n            italic        : { visible : true, tags : ['i', 'em'], css : { fontStyle : 'italic' } },\n            strikeThrough : { visible : false, tags : ['s', 'strike'], css : { textDecoration : 'line-through' } },\n            underline     : { visible : false, tags : ['u'], css : { textDecoration : 'underline' } },\n\n            separator00 : { visible : false, separator : true },\n\n            justifyLeft   : { visible : false, css : { textAlign : 'left' } },\n            justifyCenter : { visible : false, tags : ['center'], css : { textAlign : 'center' } },\n            justifyRight  : { visible : false, css : { textAlign : 'right' } },\n            justifyFull   : { visible : false, css : { textAlign : 'justify' } },\n\n            separator01 : { visible : false, separator : true },\n\n            indent  : { visible : false },\n            outdent : { visible : false },\n\n            separator02 : { visible : false, separator : true },\n\n            subscript   : { visible : false, tags : ['sub'] },\n            superscript : { visible : false, tags : ['sup'] },\n\n            separator03 : { visible : false, separator : true },\n\n            undo : { visible : false },\n            redo : { visible : false },\n\n            separator04 : { visible : false, separator : true },\n\n            insertOrderedList    : { visible : false, tags : ['ol'] },\n            insertUnorderedList  : { visible : false, tags : ['ul'] },\n            insertHorizontalRule : { visible : false, tags : ['hr'] },\n\n            separator05 : { separator : true },\n\n            createLink : {\n                visible : true,\n                exec    : function()\n                {\n                    var selection = $(this.editor).documentSelection();\n\n                    if ( selection.length > 0 )\n                    {\n                        if ( $.browser.msie )\n                            this.editorDoc.execCommand('createLink', true, null);\n                        else\n                        {\n                            var szURL = prompt('URL', 'http://');\n\n                            if ( szURL && szURL.length > 0 )\n                            {\n                                this.editorDoc.execCommand('unlink', false, []);\n                                this.editorDoc.execCommand('createLink', false, szURL);\n                            }\n                        }\n                    }\n                    else if ( this.options.messages.nonSelection )\n                        alert(this.options.messages.nonSelection);\n                },\n\n                tags : ['a']\n            },\n\n            insertImage : {\n                visible : true,\n                exec    : function()\n                {\n                    if ( $.browser.msie )\n                        this.editorDoc.execCommand('insertImage', true, null);\n                    else\n                    {\n                        var szURL = prompt('URL', 'http://');\n\n                        if ( szURL && szURL.length > 0 )\n                            this.editorDoc.execCommand('insertImage', false, szURL);\n                    }\n                },\n\n                tags : ['img']\n            },\n\n            separator06 : { separator : true },\n\n            h1mozilla : { visible : true && $.browser.mozilla, className : 'h1', command : 'heading', arguments : ['h1'], tags : ['h1'] },\n            h2mozilla : { visible : true && $.browser.mozilla, className : 'h2', command : 'heading', arguments : ['h2'], tags : ['h2'] },\n            h3mozilla : { visible : true && $.browser.mozilla, className : 'h3', command : 'heading', arguments : ['h3'], tags : ['h3'] },\n\n            h1 : { visible : true && !( $.browser.mozilla ), className : 'h1', command : 'formatBlock', arguments : ['Heading 1'], tags : ['h1'] },\n            h2 : { visible : true && !( $.browser.mozilla ), className : 'h2', command : 'formatBlock', arguments : ['Heading 2'], tags : ['h2'] },\n            h3 : { visible : true && !( $.browser.mozilla ), className : 'h3', command : 'formatBlock', arguments : ['Heading 3'], tags : ['h3'] },\n\n            separator07 : { visible : false, separator : true },\n\n            cut   : { visible : false },\n            copy  : { visible : false },\n            paste : { visible : false },\n\n            separator08 : { separator : true && !( $.browser.msie ) },\n\n            increaseFontSize : { visible : true && !( $.browser.msie ), tags : ['big'] },\n            decreaseFontSize : { visible : true && !( $.browser.msie ), tags : ['small'] },\n\n            separator09 : { separator : true },\n\n            html : {\n                visible : false,\n                exec    : function()\n                {\n                    if ( this.viewHTML )\n                    {\n                        this.setContent( $(this.original).val() );\n                        $(this.original).hide();\n                    }\n                    else\n                    {\n                        this.saveContent();\n                        $(this.original).show();\n                    }\n\n                    this.viewHTML = !( this.viewHTML );\n                }\n            },\n\n            removeFormat : {\n                visible : true,\n                exec    : function()\n                {\n                    this.editorDoc.execCommand('removeFormat', false, []);\n                    this.editorDoc.execCommand('unlink', false, []);\n                }\n            }\n        }\n    });\n\n    $.extend(Wysiwyg.prototype,\n    {\n        original : null,\n        options  : {},\n\n        element  : null,\n        editor   : null,\n\n        init : function( element, options )\n        {\n            var self = this;\n\n            this.editor = element;\n            this.options = options || {};\n\n            $.data(element, 'wysiwyg', this);\n\n            var newX = element.width || element.clientWidth;\n            var newY = element.height || element.clientHeight;\n\n            if ( element.nodeName.toLowerCase() == 'textarea' )\n            {\n                this.original = element;\n\n                if ( newX == 0 && element.cols )\n                    newX = ( element.cols * 8 ) + 21;\n\n                if ( newY == 0 && element.rows )\n                    newY = ( element.rows * 16 ) + 16;\n\n                var editor = this.editor = $('<iframe></iframe>').css({\n                    minHeight : ( newY - 6 ).toString() + 'px',\n                    width     : ( newX - 8 ).toString() + 'px'\n                }).attr('id', $(element).attr('id') + 'IFrame');\n\n                if ( $.browser.msie )\n                {\n                    this.editor\n                        .css('height', ( newY ).toString() + 'px');\n\n                    /**\n                    var editor = $('<span></span>').css({\n                        width     : ( newX - 6 ).toString() + 'px',\n                        height    : ( newY - 8 ).toString() + 'px'\n                    }).attr('id', $(element).attr('id') + 'IFrame');\n\n                    editor.outerHTML = this.editor.outerHTML;\n                     */\n                }\n            }\n\n            var panel = this.panel = $('<ul></ul>').addClass('panel');\n\n            this.appendControls();\n            this.element = $('<div></div>').css({\n                width : ( newX > 0 ) ? ( newX ).toString() + 'px' : '100%'\n            }).addClass('wysiwyg')\n              .append(panel)\n              .append( $('<div><!-- --></div>').css({ clear : 'both' }) )\n              .append(editor);\n\n            $(element)\n            // .css('display', 'none')\n            .hide()\n            .before(this.element);\n\n            this.viewHTML = false;\n\n            this.initialHeight = newY - 8;\n\n            /**\n             * @link http://code.google.com/p/jwysiwyg/issues/detail?id=52\n             */\n            this.initialContent = $(element).val();\n\n            this.initFrame();\n\n            if ( this.initialContent.length == 0 )\n                this.setContent('');\n\n            if ( this.options.autoSave )\n                $('form').submit(function() { self.saveContent(); });\n\n            $('form').bind('reset', function()\n            {\n                self.setContent( self.initialContent );\n                self.saveContent();\n            });\n        },\n\n        initFrame : function()\n        {\n            var self = this;\n            var style = '';\n\n            /**\n             * @link http://code.google.com/p/jwysiwyg/issues/detail?id=14\n             */\n            if ( this.options.css && this.options.css.constructor == String )\n                style = '<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"' + this.options.css + '\" />';\n\n            this.editorDoc = $(this.editor).document();\n            this.editorDoc_designMode = false;\n\n            try {\n                this.editorDoc.designMode = 'on';\n                this.editorDoc_designMode = true;\n            } catch ( e ) {\n                // Will fail on Gecko if the editor is placed in an hidden container element\n                // The design mode will be set ones the editor is focused\n\n                $(this.editorDoc).focus(function()\n                {\n                    self.designMode();\n                });\n            }\n\n            this.editorDoc.open();\n            this.editorDoc.write(\n                this.options.html\n                    .replace(/INITIAL_CONTENT/, this.initialContent)\n                    .replace(/STYLE_SHEET/, style)\n            );\n            this.editorDoc.close();\n            this.editorDoc.contentEditable = 'true';\n\n            if ( $.browser.msie )\n            {\n                /**\n                 * Remove the horrible border it has on IE.\n                 */\n                setTimeout(function() { $(self.editorDoc.body).css('border', 'none'); }, 0);\n            }\n\n            $(this.editorDoc).click(function( event )\n            {\n                self.checkTargets( event.target ? event.target : event.srcElement);\n            });\n\n            /**\n             * @link http://code.google.com/p/jwysiwyg/issues/detail?id=20\n             */\n            $(this.original).focus(function()\n            {\n                $(self.editorDoc.body).focus();\n            });\n\n            if ( this.options.autoSave )\n            {\n                /**\n                 * @link http://code.google.com/p/jwysiwyg/issues/detail?id=11\n                 */\n                $(this.editorDoc).keydown(function() { self.saveContent(); })\n                                 .keyup(function() { self.saveContent(); })\n                                 .mousedown(function() { self.saveContent(); });\n            }\n\n            if ( this.options.css )\n            {\n                setTimeout(function()\n                {\n                    if ( self.options.css.constructor == String )\n                    {\n                        /**\n                         * $(self.editorDoc)\n                         * .find('head')\n                         * .append(\n                         *     $('<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" />')\n                         *     .attr('href', self.options.css)\n                         * );\n                         */\n                    }\n                    else\n                        $(self.editorDoc).find('body').css(self.options.css);\n                }, 0);\n            }\n\n            $(this.editorDoc).keydown(function( event )\n            {\n                if ( $.browser.msie && self.options.brIE && event.keyCode == 13 )\n                {\n                    var rng = self.getRange();\n                        rng.pasteHTML('<br />');\n                        rng.collapse(false);\n                        rng.select();\n\n    \t\t\t\treturn false;\n                }\n            });\n        },\n\n        designMode : function()\n        {\n            if ( !( this.editorDoc_designMode ) )\n            {\n                try {\n                    this.editorDoc.designMode = 'on';\n                    this.editorDoc_designMode = true;\n                } catch ( e ) {}\n            }\n        },\n\n        getSelection : function()\n        {\n            return ( window.getSelection ) ? window.getSelection() : document.selection;\n        },\n\n        getRange : function()\n        {\n            var selection = this.getSelection();\n\n            if ( !( selection ) )\n                return null;\n\n            return ( selection.rangeCount > 0 ) ? selection.getRangeAt(0) : selection.createRange();\n        },\n\n        getContent : function()\n        {\n            return $( $(this.editor).document() ).find('body').html();\n        },\n\n        setContent : function( newContent )\n        {\n            $( $(this.editor).document() ).find('body').html(newContent);\n        },\n\n        saveContent : function()\n        {\n            if ( this.original )\n            {\n                var content = this.getContent();\n\n                if ( this.options.rmUnwantedBr )\n                    content = ( content.substr(-4) == '<br>' ) ? content.substr(0, content.length - 4) : content;\n\n                $(this.original).val(content);\n            }\n        },\n\n        appendMenu : function( cmd, args, className, fn )\n        {\n            var self = this;\n            var args = args || [];\n\n            $('<li></li>').append(\n                $('<a><!-- --></a>').addClass(className || cmd)\n            ).mousedown(function() {\n                if ( fn ) fn.apply(self); else self.editorDoc.execCommand(cmd, false, args);\n                if ( self.options.autoSave ) self.saveContent();\n            }).appendTo( this.panel );\n        },\n\n        appendMenuSeparator : function()\n        {\n            $('<li class=\"separator\"></li>').appendTo( this.panel );\n        },\n\n        appendControls : function()\n        {\n            for ( var name in this.options.controls )\n            {\n                var control = this.options.controls[name];\n\n                if ( control.separator )\n                {\n                    if ( control.visible !== false )\n                        this.appendMenuSeparator();\n                }\n                else if ( control.visible )\n                {\n                    this.appendMenu(\n                        control.command || name, control.arguments || [],\n                        control.className || control.command || name || 'empty', control.exec\n                    );\n                }\n            }\n        },\n\n        checkTargets : function( element )\n        {\n            for ( var name in this.options.controls )\n            {\n                var control = this.options.controls[name];\n                var className = control.className || control.command || name || 'empty';\n\n                $('.' + className, this.panel).removeClass('active');\n\n                if ( control.tags )\n                {\n                    var elm = element;\n\n                    do {\n                        if ( elm.nodeType != 1 )\n                            break;\n\n                        if ( $.inArray(elm.tagName.toLowerCase(), control.tags) != -1 )\n                            $('.' + className, this.panel).addClass('active');\n                    } while ( elm = elm.parentNode );\n                }\n\n                if ( control.css )\n                {\n                    var elm = $(element);\n\n                    do {\n                        if ( elm[0].nodeType != 1 )\n                            break;\n\n                        for ( var cssProperty in control.css )\n                            if ( elm.css(cssProperty).toString().toLowerCase() == control.css[cssProperty] )\n                                $('.' + className, this.panel).addClass('active');\n                    } while ( elm = elm.parent() );\n                }\n            }\n        },\n\n        getElementByAttributeValue : function( tagName, attributeName, attributeValue )\n        {\n            var elements = this.editorDoc.getElementsByTagName(tagName);\n\n            for ( var i = 0; i < elements.length; i++ )\n            {\n                var value = elements[i].getAttribute(attributeName);\n\n                if ( $.browser.msie )\n                {\n                    /** IE add full path, so I check by the last chars. */\n                    value = value.substr(value.length - attributeValue.length);\n                }\n\n                if ( value == attributeValue )\n                    return elements[i];\n            }\n\n            return false;\n        }\n    });\n})(jQuery);"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/oldMemResource/scripts/session-create.js",
    "content": "/** 提交登录请求*/\nfunction doLoginAuth() {\n\t//数据验证\n\tvar errBeforeSubmit = \"\";\n\tif(document.getElementById(\"devUser\").value==null || document.getElementById(\"devUser\").value==\"\") {\n\t\terrBeforeSubmit = \"用户名不能为空. \";\n\t} \n\tif(document.getElementById(\"devPwd\").value==null || document.getElementById(\"devPwd\").value==\"\") {\n\t\terrBeforeSubmit += \"密码不能为空. \";\n\t} \n\tif(errBeforeSubmit != \"\") {\n\t\tshowNotify(errBeforeSubmit);\n\t\treturn ;\n\t}\n\t//构建HTTP请求参数\n\tvar request = { \"u\" :  document.getElementById(\"devUser\").value,\n\t\t\t\t\t\"p\" :  document.getElementById(\"devPwd\").value\n\t\t\t\t};\n\t//构建Ajax请求提交表单信息\n\t$.ajax({url:\"/memcloud/session-create.json\",\n\t\t\ttype: \"post\",//POST方式提交表单内容\n\t\t\ttimeout : 8000,//响应超时间8秒\n\t\t\tasync : false,//同步提交\n\t\t\tcache : false,//禁止浏览器缓存\n\t\t\tcontentType : \"application/x-www-form-urlencoded; charset=UTF-8\",//明确告诉服务器协商编码方式，以免服务器端出现中文乱码\n\t\t\tbeforeSend : function(xmlHttpRequest){//请求发送前的逻辑\n\t\t\t\tshowNotify(\"正在登录...\");\n\t\t\t\tdocument.getElementById(\"btnLogin\").disabled = true;\n            },\n\t\t\tdataType : \"json\",\n\t\t\tdata : request,//HTTP请求数据（表单数据）\n\t\t\tsuccess : function(response,httpStatus) {//HTTP响应成功后的处理逻辑\n\t\t\t\tif(response[\"status\"]==200) {//登录成功\n\t\t\t\t\tlocation.href = \"/memcloud/session.html\";//登录后去当行页\n\t\t\t\t} else {\n\t\t\t\t\tshowNotify(\"登录失败：\"+response[\"data\"]);//返回码：response[\"status\"]\n\t\t\t\t\tdocument.getElementById(\"btnLogin\").disabled = false;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n}\n\nfunction hideNotify() {\n\tdocument.getElementById(\"devNotify\").style.display ='none';\n}\n\nfunction showNotify(notification) {\n\tdocument.getElementById(\"devNotify\").innerHTML=notification;\n\tdocument.getElementById(\"devNotify\").style.display ='';\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/oldMemResource/scripts/simpla.jquery.configuration.js",
    "content": "$(document).ready(function(){\n\t\n\t//Sidebar Accordion Menu:\n\t\t\n\t\t$(\"#main-nav li ul\").hide(); // Hide all sub menus\n\t\t$(\"#main-nav li a.current\").parent().find(\"ul\").slideToggle(\"slow\"); // Slide down the current menu item's sub menu\n\t\t\n\t\t$(\"#main-nav li a.nav-top-item\").click( // When a top menu item is clicked...\n\t\t\tfunction () {\n\t\t\t\t$(this).parent().siblings().find(\"ul\").slideUp(\"normal\"); // Slide up all sub menus except the one clicked\n\t\t\t\t$(this).next().slideToggle(\"normal\"); // Slide down the clicked sub menu\n\t\t\t\treturn false;\n\t\t\t}\n\t\t);\n\t\t\n\t\t$(\"#main-nav li a.no-submenu\").click( // When a menu item with no sub menu is clicked...\n\t\t\tfunction () {\n\t\t\t\twindow.location.href=(this.href); // Just open the link instead of a sub menu\n\t\t\t\treturn false;\n\t\t\t}\n\t\t); \n\n    // Sidebar Accordion Menu Hover Effect:\n\t\t\n\t\t$(\"#main-nav li .nav-top-item\").hover(\n\t\t\tfunction () {\n\t\t\t\t$(this).stop().animate({ paddingRight: \"25px\" }, 200);\n\t\t\t}, \n\t\t\tfunction () {\n\t\t\t\t$(this).stop().animate({ paddingRight: \"15px\" });\n\t\t\t}\n\t\t);\n\n    //Minimize Content Box\n\t\t\n\t\t$(\".content-box-header h3\").css({ \"cursor\":\"s-resize\" }); // Give the h3 in Content Box Header a different cursor\n\t\t$(\".closed-box .content-box-content\").hide(); // Hide the content of the header if it has the class \"closed\"\n\t\t$(\".closed-box .content-box-tabs\").hide(); // Hide the tabs in the header if it has the class \"closed\"\n\t\t\n\t\t$(\".content-box-header h3\").click( // When the h3 is clicked...\n\t\t\tfunction () {\n\t\t\t  $(this).parent().next().toggle(); // Toggle the Content Box\n\t\t\t  $(this).parent().parent().toggleClass(\"closed-box\"); // Toggle the class \"closed-box\" on the content box\n\t\t\t  $(this).parent().find(\".content-box-tabs\").toggle(); // Toggle the tabs\n\t\t\t}\n\t\t);\n\n    // Content box tabs:\n\t\t\n\t\t$('.content-box .content-box-content div.tab-content').hide(); // Hide the content divs\n\t\t$('ul.content-box-tabs li a.default-tab').addClass('current'); // Add the class \"current\" to the default tab\n\t\t$('.content-box-content div.default-tab').show(); // Show the div with class \"default-tab\"\n\t\t\n\t\t$('.content-box ul.content-box-tabs li a').click( // When a tab is clicked...\n\t\t\tfunction() { \n\t\t\t\t$(this).parent().siblings().find(\"a\").removeClass('current'); // Remove \"current\" class from all tabs\n\t\t\t\t$(this).addClass('current'); // Add class \"current\" to clicked tab\n\t\t\t\tvar currentTab = $(this).attr('href'); // Set variable \"currentTab\" to the value of href of clicked tab\n\t\t\t\t$(currentTab).siblings().hide(); // Hide all content divs\n\t\t\t\t$(currentTab).show(); // Show the content div with the id equal to the id of clicked tab\n\t\t\t\treturn false; \n\t\t\t}\n\t\t);\n\n    //Close button:\n\t\t\n\t\t$(\".close\").click(\n\t\t\tfunction () {\n\t\t\t\t$(this).parent().fadeTo(400, 0, function () { // Links with the class \"close\" will close parent\n\t\t\t\t\t$(this).slideUp(400);\n\t\t\t\t});\n\t\t\t\treturn false;\n\t\t\t}\n\t\t);\n\n    // Alternating table rows:\n\t\t\n\t\t$('tbody tr:even').addClass(\"alt-row\"); // Add class \"alt-row\" to even table rows\n\n    // Check all checkboxes when the one in a table head is checked:\n\t\t\n\t\t$('.check-all').click(\n\t\t\tfunction(){\n\t\t\t\t$(this).parent().parent().parent().parent().find(\"input[type='checkbox']\").attr('checked', $(this).is(':checked'));   \n\t\t\t}\n\t\t);\n\n    // Initialise Facebox Modal window:\n\t\t\n\t\t$('a[rel*=modal]').facebox(); // Applies modal window to any link with attribute rel=\"modal\"\n\n    // Initialise jQuery WYSIWYG:\n\t\t\n\t\t$(\".wysiwyg\").wysiwyg(); // Applies WYSIWYG editor to any textarea with the class \"wysiwyg\"\n\n});\n  \n  \n  "
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/plugins/bootstrap/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": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/plugins/bootstrap/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": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/plugins/bootstrap/js/bootstrap2-typeahead.js",
    "content": "/* =============================================================\n * bootstrap-typeahead.js v2.3.2\n * http://twitter.github.com/bootstrap/javascript.html#typeahead\n * =============================================================\n * Copyright 2012 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($){\n\n  \"use strict\"; // jshint ;_;\n\n\n /* TYPEAHEAD PUBLIC CLASS DEFINITION\n  * ================================= */\n\n  var Typeahead = function (element, options) {\n    this.$element = $(element)\n    this.options = $.extend({}, $.fn.typeahead.defaults, options)\n    this.matcher = this.options.matcher || this.matcher\n    this.sorter = this.options.sorter || this.sorter\n    this.highlighter = this.options.highlighter || this.highlighter\n    this.updater = this.options.updater || this.updater\n    this.source = this.options.source\n    this.$menu = $(this.options.menu)\n    this.shown = false\n    this.listen()\n  }\n\n  Typeahead.prototype = {\n\n    constructor: Typeahead\n\n  , select: function () {\n      var val = this.$menu.find('.active').attr('data-value')\n      this.$element\n        .val(this.updater(val))\n        .change()\n      return this.hide()\n    }\n\n  , updater: function (item) {\n      return item\n    }\n\n  , show: function () {\n      var pos = $.extend({}, this.$element.position(), {\n        height: this.$element[0].offsetHeight\n      })\n\n      this.$menu\n        .insertAfter(this.$element)\n        .css({\n          top: pos.top + pos.height\n        , left: pos.left\n        })\n        .show()\n\n      this.shown = true\n      return this\n    }\n\n  , hide: function () {\n      this.$menu.hide()\n      this.shown = false\n      return this\n    }\n\n  , lookup: function (event) {\n      var items\n\n      this.query = this.$element.val()\n\n      if (!this.query || this.query.length < this.options.minLength) {\n        return this.shown ? this.hide() : this\n      }\n\n      items = $.isFunction(this.source) ? this.source(this.query, $.proxy(this.process, this)) : this.source\n\n      return items ? this.process(items) : this\n    }\n\n  , process: function (items) {\n      var that = this\n\n      items = $.grep(items, function (item) {\n        return that.matcher(item)\n      })\n\n      items = this.sorter(items)\n\n      if (!items.length) {\n        return this.shown ? this.hide() : this\n      }\n\n      return this.render(items.slice(0, this.options.items)).show()\n    }\n\n  , matcher: function (item) {\n      return ~item.toLowerCase().indexOf(this.query.toLowerCase())\n    }\n\n  , sorter: function (items) {\n      var beginswith = []\n        , caseSensitive = []\n        , caseInsensitive = []\n        , item\n\n      while (item = items.shift()) {\n        if (!item.toLowerCase().indexOf(this.query.toLowerCase())) beginswith.push(item)\n        else if (~item.indexOf(this.query)) caseSensitive.push(item)\n        else caseInsensitive.push(item)\n      }\n\n      return beginswith.concat(caseSensitive, caseInsensitive)\n    }\n\n  , highlighter: function (item) {\n      var query = this.query.replace(/[\\-\\[\\]{}()*+?.,\\\\\\^$|#\\s]/g, '\\\\$&')\n      return item.replace(new RegExp('(' + query + ')', 'ig'), function ($1, match) {\n        return '<strong>' + match + '</strong>'\n      })\n    }\n\n  , render: function (items) {\n      var that = this\n\n      items = $(items).map(function (i, item) {\n        i = $(that.options.item).attr('data-value', item)\n        i.find('a').html(that.highlighter(item))\n        return i[0]\n      })\n\n      items.first().addClass('active')\n      this.$menu.html(items)\n      return this\n    }\n\n  , next: function (event) {\n      var active = this.$menu.find('.active').removeClass('active')\n        , next = active.next()\n\n      if (!next.length) {\n        next = $(this.$menu.find('li')[0])\n      }\n\n      next.addClass('active')\n    }\n\n  , prev: function (event) {\n      var active = this.$menu.find('.active').removeClass('active')\n        , prev = active.prev()\n\n      if (!prev.length) {\n        prev = this.$menu.find('li').last()\n      }\n\n      prev.addClass('active')\n    }\n\n  , listen: function () {\n      this.$element\n        .on('focus',    $.proxy(this.focus, this))\n        .on('blur',     $.proxy(this.blur, this))\n        .on('keypress', $.proxy(this.keypress, this))\n        .on('keyup',    $.proxy(this.keyup, this))\n\n      if (this.eventSupported('keydown')) {\n        this.$element.on('keydown', $.proxy(this.keydown, this))\n      }\n\n      this.$menu\n        .on('click', $.proxy(this.click, this))\n        .on('mouseenter', 'li', $.proxy(this.mouseenter, this))\n        .on('mouseleave', 'li', $.proxy(this.mouseleave, this))\n    }\n\n  , eventSupported: function(eventName) {\n      var isSupported = eventName in this.$element\n      if (!isSupported) {\n        this.$element.setAttribute(eventName, 'return;')\n        isSupported = typeof this.$element[eventName] === 'function'\n      }\n      return isSupported\n    }\n\n  , move: function (e) {\n      if (!this.shown) return\n\n      switch(e.keyCode) {\n        case 9: // tab\n        case 13: // enter\n        case 27: // escape\n          e.preventDefault()\n          break\n\n        case 38: // up arrow\n          e.preventDefault()\n          this.prev()\n          break\n\n        case 40: // down arrow\n          e.preventDefault()\n          this.next()\n          break\n      }\n\n      e.stopPropagation()\n    }\n\n  , keydown: function (e) {\n      this.suppressKeyPressRepeat = ~$.inArray(e.keyCode, [40,38,9,13,27])\n      this.move(e)\n    }\n\n  , keypress: function (e) {\n      if (this.suppressKeyPressRepeat) return\n      this.move(e)\n    }\n\n  , keyup: function (e) {\n      switch(e.keyCode) {\n        case 40: // down arrow\n        case 38: // up arrow\n        case 16: // shift\n        case 17: // ctrl\n        case 18: // alt\n          break\n\n        case 9: // tab\n        case 13: // enter\n          if (!this.shown) return\n          this.select()\n          break\n\n        case 27: // escape\n          if (!this.shown) return\n          this.hide()\n          break\n\n        default:\n          this.lookup()\n      }\n\n      e.stopPropagation()\n      e.preventDefault()\n  }\n\n  , focus: function (e) {\n      this.focused = true\n    }\n\n  , blur: function (e) {\n      this.focused = false\n      if (!this.mousedover && this.shown) this.hide()\n    }\n\n  , click: function (e) {\n      e.stopPropagation()\n      e.preventDefault()\n      this.select()\n      this.$element.focus()\n    }\n\n  , mouseenter: function (e) {\n      this.mousedover = true\n      this.$menu.find('.active').removeClass('active')\n      $(e.currentTarget).addClass('active')\n    }\n\n  , mouseleave: function (e) {\n      this.mousedover = false\n      if (!this.focused && this.shown) this.hide()\n    }\n\n  }\n\n\n  /* TYPEAHEAD PLUGIN DEFINITION\n   * =========================== */\n\n  var old = $.fn.typeahead\n\n  $.fn.typeahead = function (option) {\n    return this.each(function () {\n      var $this = $(this)\n        , data = $this.data('typeahead')\n        , options = typeof option == 'object' && option\n      if (!data) $this.data('typeahead', (data = new Typeahead(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.typeahead.defaults = {\n    source: []\n  , items: 8\n  , menu: '<ul class=\"typeahead dropdown-menu\"></ul>'\n  , item: '<li><a href=\"#\"></a></li>'\n  , minLength: 1\n  }\n\n  $.fn.typeahead.Constructor = Typeahead\n\n\n /* TYPEAHEAD NO CONFLICT\n  * =================== */\n\n  $.fn.typeahead.noConflict = function () {\n    $.fn.typeahead = old\n    return this\n  }\n\n\n /* TYPEAHEAD DATA-API\n  * ================== */\n\n  $(document).on('focus.typeahead.data-api', '[data-provide=\"typeahead\"]', function (e) {\n    var $this = $(this)\n    if ($this.data('typeahead')) return\n    $this.typeahead($this.data())\n  })\n\n}(window.jQuery);"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/plugins/data-tables/DT_bootstrap.css",
    "content": "\ndiv.dataTables_length label {\n\tfloat: left;\n\ttext-align: left;\n}\n\ndiv.dataTables_length select {\n\twidth: 75px;\n}\n\ndiv.dataTables_filter label {\n\tfloat: right;\n}\n\ndiv.dataTables_info {\n\tposition: relative;\n\ttop:15px;\n}\n\ndiv.dataTables_paginate {\n\tfloat: right;\n\tmargin: 0;\n}\n\ntable.table {\n\tclear: both;\n\tmargin-bottom: 6px !important;\n\tmax-width: none !important;\n}\n\ntable.table thead .sorting,\ntable.table thead .sorting_asc,\ntable.table thead .sorting_desc,\ntable.table thead .sorting_asc_disabled,\ntable.table thead .sorting_desc_disabled {\n\tcursor: pointer;\n\t*cursor: hand;\n}\n\ntable.table thead .sorting { background: url('images/sort_both.png') no-repeat center right; }\ntable.table thead .sorting_asc { background: url('images/sort_asc.png') no-repeat center right; }\ntable.table thead .sorting_desc { background: url('images/sort_desc.png') no-repeat center right; }\n\ntable.table thead .sorting_asc_disabled { background: url('images/sort_asc_disabled.png') no-repeat center right; }\ntable.table thead .sorting_desc_disabled { background: url('images/sort_desc_disabled.png') no-repeat center right; }\n\ntable.dataTable th:active {\n\toutline: none;\n}\n\n/* Scrolling */\ndiv.dataTables_scrollHead table {\n\tmargin-bottom: 0 !important;\n\tborder-bottom-left-radius: 0;\n\tborder-bottom-right-radius: 0;\n}\n\ndiv.dataTables_scrollHead table thead tr:last-child th:first-child,\ndiv.dataTables_scrollHead table thead tr:last-child td:first-child {\n\tborder-bottom-left-radius: 0 !important;\n\tborder-bottom-right-radius: 0 !important;\n}\n\ndiv.dataTables_scrollBody table {\n\tborder-top: none;\n\tmargin-bottom: 0 !important;\n}\n\ndiv.dataTables_scrollBody tbody tr:first-child th,\ndiv.dataTables_scrollBody tbody tr:first-child td {\n\tborder-top: none;\n}\n\ndiv.dataTables_scrollFoot table {\n\tborder-top: none;\n}\n\n/*\n * TableTools styles\n */\n\ntable.DTTT_selectable tbody tr {\n\tcursor: pointer;\n\t*cursor: hand;\n}\n\ndiv.DTTT .btn {\n\tcolor: #333 !important;\n\tfont-size: 12px;\n}\n\ndiv.DTTT .btn:hover {\n\ttext-decoration: none !important;\n}\n\n\nul.DTTT_dropdown.dropdown-menu a {\n\tcolor: #333 !important; /* needed only when demo_page.css is included */\n}\n\nul.DTTT_dropdown.dropdown-menu li:hover a {\n\tbackground-color: #0088cc;\n\tcolor: white !important;\n}\n\n/* TableTools information display */\ndiv.DTTT_print_info.modal {\n\theight: 150px;\n\tmargin-top: -75px;\n\ttext-align: center;\n}\n\ndiv.DTTT_print_info h6 {\n\tfont-weight: normal;\n\tfont-size: 28px;\n\tline-height: 28px;\n\tmargin: 1em;\n}\n\ndiv.DTTT_print_info p {\n\tfont-size: 14px;\n\tline-height: 20px;\n}\n\n\n\n/*\n * FixedColumns styles\n */\ndiv.DTFC_LeftHeadWrapper table,\ndiv.DTFC_LeftFootWrapper table,\ntable.DTFC_Cloned tr.even {\n\tbackground-color: white;\n}\n\ndiv.DTFC_LeftHeadWrapper table {\n\tmargin-bottom: 0 !important;\n\tborder-top-right-radius: 0 !important;\n\tborder-bottom-left-radius: 0 !important;\n\tborder-bottom-right-radius: 0 !important;\n}\n\ndiv.DTFC_LeftHeadWrapper table thead tr:last-child th:first-child,\ndiv.DTFC_LeftHeadWrapper table thead tr:last-child td:first-child {\n\tborder-bottom-left-radius: 0 !important;\n\tborder-bottom-right-radius: 0 !important;\n}\n\ndiv.DTFC_LeftBodyWrapper table {\n\tborder-top: none;\n\tmargin-bottom: 0 !important;\n}\n\ndiv.DTFC_LeftBodyWrapper tbody tr:first-child th,\ndiv.DTFC_LeftBodyWrapper tbody tr:first-child td {\n\tborder-top: none;\n}\n\ndiv.DTFC_LeftFootWrapper table {\n\tborder-top: none;\n}\n\n.dataTables_processing {\n\tposition: absolute;\n\ttop: 50%;\n\tleft: 50%;\n\twidth: 180px;\n\theight: 40px;\n\tmargin-left: -90px;\n\tpadding: 10px 0 10px 0;\n\ttext-align: center;\n\tcolor: #333;\n\tfont-size: 13px;\n\tbackground-color: #ddd;\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/plugins/data-tables/DT_bootstrap.js",
    "content": "/* Set the defaults for DataTables initialisation */\n$.extend( true, $.fn.dataTable.defaults, {\n\t\"sDom\": \"<'row'<'col-md-6 col-sm-12'l><'col-md-12 col-sm-12'f>r><'table-scrollable't><'row'<'col-md-5 col-sm-12'i><'col-md-7 col-sm-12'p>>\", // horizobtal scrollable datatable\n\t//\"sDom\": \"<'row'<'col-md-6 col-sm-12'l><'col-md-12 col-sm-12'f>r>t<'row'<'col-md-5 col-sm-12'i><'col-md-7 col-sm-12'p>>\", // defaukt datatable without  horizobtal scroll\n\t\"sPaginationType\": \"bootstrap\",\n\t\"oLanguage\": {\n\t\t\"sLengthMenu\": \"_MENU_ records\"\n\t}\n} );\n\n\n/* Default class modification */\n$.extend( $.fn.dataTableExt.oStdClasses, {\n\t\"sWrapper\": \"dataTables_wrapper form-inline\"\n} );\n\n\n/* API method to get paging information */\n$.fn.dataTableExt.oApi.fnPagingInfo = function ( oSettings )\n{\n\treturn {\n\t\t\"iStart\":         oSettings._iDisplayStart,\n\t\t\"iEnd\":           oSettings.fnDisplayEnd(),\n\t\t\"iLength\":        oSettings._iDisplayLength,\n\t\t\"iTotal\":         oSettings.fnRecordsTotal(),\n\t\t\"iFilteredTotal\": oSettings.fnRecordsDisplay(),\n\t\t\"iPage\":          Math.ceil( oSettings._iDisplayStart / oSettings._iDisplayLength ),\n\t\t\"iTotalPages\":    Math.ceil( oSettings.fnRecordsDisplay() / oSettings._iDisplayLength )\n\t};\n};\n\n\n/* Bootstrap style pagination control */\n$.extend( $.fn.dataTableExt.oPagination, {\n\t\"bootstrap\": {\n\t\t\"fnInit\": function( oSettings, nPaging, fnDraw ) {\n\t\t\tvar oLang = oSettings.oLanguage.oPaginate;\n\t\t\tvar fnClickHandler = function ( e ) {\n\t\t\t\te.preventDefault();\n\t\t\t\tif ( oSettings.oApi._fnPageChange(oSettings, e.data.action) ) {\n\t\t\t\t\tfnDraw( oSettings );\n\t\t\t\t}\n\t\t\t};\n\n\t\t\t// pagination with prev, next link icons\n\t\t\t$(nPaging).append(\n\t\t\t\t'<ul class=\"pagination\">'+\n\t\t\t\t\t'<li class=\"prev disabled\"><a style=\"height:32px\" href=\"#\" title=\"前一页\"><i class=\"fa fa-angle-left\"></i></a></li>'+\n\t\t\t\t\t'<li class=\"next disabled\"><a style=\"height:32px\" href=\"#\" title=\"下一页\"><i class=\"fa fa-angle-right\"></i></a></li>'+\n\t\t\t\t'</ul>'\n\t\t\t);\n\n\t\t\tvar els = $('a', nPaging);\n\t\t\t$(els[0]).bind( 'click.DT', { action: \"previous\" }, fnClickHandler );\n\t\t\t$(els[1]).bind( 'click.DT', { action: \"next\" }, fnClickHandler );\n\t\t},\n\n\t\t\"fnUpdate\": function ( oSettings, fnDraw ) {\n\t\t\tvar iListLength = 5;\n\t\t\tvar oPaging = oSettings.oInstance.fnPagingInfo();\n\t\t\tvar an = oSettings.aanFeatures.p;\n\t\t\tvar i, j, sClass, iStart, iEnd, iHalf=Math.floor(iListLength/2);\n\n\t\t\tif ( oPaging.iTotalPages < iListLength) {\n\t\t\t\tiStart = 1;\n\t\t\t\tiEnd = oPaging.iTotalPages;\n\t\t\t}\n\t\t\telse if ( oPaging.iPage <= iHalf ) {\n\t\t\t\tiStart = 1;\n\t\t\t\tiEnd = iListLength;\n\t\t\t} else if ( oPaging.iPage >= (oPaging.iTotalPages-iHalf) ) {\n\t\t\t\tiStart = oPaging.iTotalPages - iListLength + 1;\n\t\t\t\tiEnd = oPaging.iTotalPages;\n\t\t\t} else {\n\t\t\t\tiStart = oPaging.iPage - iHalf + 1;\n\t\t\t\tiEnd = iStart + iListLength - 1;\n\t\t\t}\n\n\t\t\tif (oPaging.iTotalPages < 0) {\n\t\t\t\t$('.pagination', an[i]).css('visibility', 'hidden');\n\t\t\t} else {\n\t\t\t\t$('.pagination', an[i]).css('visibility', 'visible');\n\t\t\t}\n\n\t\t\tfor ( i=0, iLen=an.length ; i<iLen ; i++ ) {\n\t\t\t\t// Remove the middle elements\n\t\t\t\t$('li:gt(0)', an[i]).filter(':not(:last)').remove();\n\n\t\t\t\t// Add the new list items and their event handlers\n\t\t\t\tfor ( j=iStart ; j<=iEnd ; j++ ) {\n\t\t\t\t\tsClass = (j==oPaging.iPage+1) ? 'class=\"active\"' : '';\n\t\t\t\t\t$('<li '+sClass+'><a href=\"#\">'+j+'</a></li>')\n\t\t\t\t\t\t.insertBefore( $('li:last', an[i])[0] )\n\t\t\t\t\t\t.bind('click', function (e) {\n\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\toSettings._iDisplayStart = (parseInt($('a', this).text(),10)-1) * oPaging.iLength;\n\t\t\t\t\t\t\tfnDraw( oSettings );\n\t\t\t\t\t\t} );\n\t\t\t\t}\n\n\t\t\t\t// Add / remove disabled classes from the static elements\n\t\t\t\tif ( oPaging.iPage === 0 ) {\n\t\t\t\t\t$('li:first', an[i]).addClass('disabled');\n\t\t\t\t} else {\n\t\t\t\t\t$('li:first', an[i]).removeClass('disabled');\n\t\t\t\t}\n\n\t\t\t\tif ( oPaging.iPage === oPaging.iTotalPages-1 || oPaging.iTotalPages === 0 ) {\n\t\t\t\t\t$('li:last', an[i]).addClass('disabled');\n\t\t\t\t} else {\n\t\t\t\t\t$('li:last', an[i]).removeClass('disabled');\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n} );\n\n\n/*\n * TableTools Bootstrap compatibility\n * Required TableTools 2.1+\n */\nif ( $.fn.DataTable.TableTools ) {\n\t// Set the classes that TableTools uses to something suitable for Bootstrap\n\t$.extend( true, $.fn.DataTable.TableTools.classes, {\n\t\t\"container\": \"DTTT btn-group\",\n\t\t\"buttons\": {\n\t\t\t\"normal\": \"btn default\",\n\t\t\t\"disabled\": \"disabled\"\n\t\t},\n\t\t\"collection\": {\n\t\t\t\"container\": \"DTTT_dropdown dropdown-menu\",\n\t\t\t\"buttons\": {\n\t\t\t\t\"normal\": \"\",\n\t\t\t\t\"disabled\": \"disabled\"\n\t\t\t}\n\t\t},\n\t\t\"print\": {\n\t\t\t\"info\": \"DTTT_print_info modal\"\n\t\t},\n\t\t\"select\": {\n\t\t\t\"row\": \"active\"\n\t\t}\n\t} );\n\n\t// Have the collection use a bootstrap compatible dropdown\n\t$.extend( true, $.fn.DataTable.TableTools.DEFAULTS.oTags, {\n\t\t\"collection\": {\n\t\t\t\"container\": \"ul\",\n\t\t\t\"button\": \"li\",\n\t\t\t\"liner\": \"a\"\n\t\t}\n\t} );\n}"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/plugins/data-tables/jquery.dataTables.js",
    "content": "/**\n * @summary     DataTables\n * @description Paginate, search and sort HTML tables\n * @version     1.9.4\n * @file        jquery.dataTables.js\n * @author      Allan Jardine (www.sprymedia.co.uk)\n * @contact     www.sprymedia.co.uk/contact\n *\n * @copyright Copyright 2008-2012 Allan Jardine, all rights reserved.\n *\n * This source file is free software, under either the GPL v2 license or a\n * BSD style license, available at:\n *   http://datatables.net/license_gpl2\n *   http://datatables.net/license_bsd\n * \n * This source file is distributed in the hope that it will be useful, but \n * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY \n * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.\n * \n * For details please refer to: http://www.datatables.net\n */\n\n/*jslint evil: true, undef: true, browser: true */\n/*globals $, jQuery,define,_fnExternApiFunc,_fnInitialise,_fnInitComplete,_fnLanguageCompat,_fnAddColumn,_fnColumnOptions,_fnAddData,_fnCreateTr,_fnGatherData,_fnBuildHead,_fnDrawHead,_fnDraw,_fnReDraw,_fnAjaxUpdate,_fnAjaxParameters,_fnAjaxUpdateDraw,_fnServerParams,_fnAddOptionsHtml,_fnFeatureHtmlTable,_fnScrollDraw,_fnAdjustColumnSizing,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnBuildSearchArray,_fnBuildSearchRow,_fnFilterCreateSearch,_fnDataToSearch,_fnSort,_fnSortAttachListener,_fnSortingClasses,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnFeatureHtmlLength,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnNodeToDataIndex,_fnVisbleColumns,_fnCalculateEnd,_fnConvertToWidth,_fnCalculateColumnWidths,_fnScrollingWidthAdjust,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnDetectType,_fnSettingsFromNode,_fnGetDataMaster,_fnGetTrNodes,_fnGetTdNodes,_fnEscapeRegex,_fnDeleteIndex,_fnReOrderIndex,_fnColumnOrdering,_fnLog,_fnClearTable,_fnSaveState,_fnLoadState,_fnCreateCookie,_fnReadCookie,_fnDetectHeader,_fnGetUniqueThs,_fnScrollBarWidth,_fnApplyToChildren,_fnMap,_fnGetRowData,_fnGetCellData,_fnSetCellData,_fnGetObjectDataFn,_fnSetObjectDataFn,_fnApplyColumnDefs,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnJsonString,_fnRender,_fnNodeToColumnIndex,_fnInfoMacros,_fnBrowserDetect,_fnGetColumns*/\n\n(/** @lends <global> */function( window, document, undefined ) {\n\n(function( factory ) {\n\t\"use strict\";\n\n\t// Define as an AMD module if possible\n\tif ( typeof define === 'function' && define.amd )\n\t{\n\t\tdefine( ['jquery'], factory );\n\t}\n\t/* Define using browser globals otherwise\n\t * Prevent multiple instantiations if the script is loaded twice\n\t */\n\telse if ( jQuery && !jQuery.fn.dataTable )\n\t{\n\t\tfactory( jQuery );\n\t}\n}\n(/** @lends <global> */function( $ ) {\n\t\"use strict\";\n\t/** \n\t * DataTables is a plug-in for the jQuery Javascript library. It is a \n\t * highly flexible tool, based upon the foundations of progressive \n\t * enhancement, which will add advanced interaction controls to any \n\t * HTML table. For a full list of features please refer to\n\t * <a href=\"http://datatables.net\">DataTables.net</a>.\n\t *\n\t * Note that the <i>DataTable</i> object is not a global variable but is\n\t * aliased to <i>jQuery.fn.DataTable</i> and <i>jQuery.fn.dataTable</i> through which \n\t * it may be  accessed.\n\t *\n\t *  @class\n\t *  @param {object} [oInit={}] Configuration object for DataTables. Options\n\t *    are defined by {@link DataTable.defaults}\n\t *  @requires jQuery 1.3+\n\t * \n\t *  @example\n\t *    // Basic initialisation\n\t *    $(document).ready( function {\n\t *      $('#example').dataTable();\n\t *    } );\n\t *  \n\t *  @example\n\t *    // Initialisation with configuration options - in this case, disable\n\t *    // pagination and sorting.\n\t *    $(document).ready( function {\n\t *      $('#example').dataTable( {\n\t *        \"bPaginate\": false,\n\t *        \"bSort\": false \n\t *      } );\n\t *    } );\n\t */\n\tvar DataTable = function( oInit )\n\t{\n\t\t\n\t\t\n\t\t/**\n\t\t * Add a column to the list used for the table with default values\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @param {node} nTh The th element for this column\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnAddColumn( oSettings, nTh )\n\t\t{\n\t\t\tvar oDefaults = DataTable.defaults.columns;\n\t\t\tvar iCol = oSettings.aoColumns.length;\n\t\t\tvar oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, {\n\t\t\t\t\"sSortingClass\": oSettings.oClasses.sSortable,\n\t\t\t\t\"sSortingClassJUI\": oSettings.oClasses.sSortJUI,\n\t\t\t\t\"nTh\": nTh ? nTh : document.createElement('th'),\n\t\t\t\t\"sTitle\":    oDefaults.sTitle    ? oDefaults.sTitle    : nTh ? nTh.innerHTML : '',\n\t\t\t\t\"aDataSort\": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol],\n\t\t\t\t\"mData\": oDefaults.mData ? oDefaults.oDefaults : iCol\n\t\t\t} );\n\t\t\toSettings.aoColumns.push( oCol );\n\t\t\t\n\t\t\t/* Add a column specific filter */\n\t\t\tif ( oSettings.aoPreSearchCols[ iCol ] === undefined || oSettings.aoPreSearchCols[ iCol ] === null )\n\t\t\t{\n\t\t\t\toSettings.aoPreSearchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch );\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tvar oPre = oSettings.aoPreSearchCols[ iCol ];\n\t\t\t\t\n\t\t\t\t/* Don't require that the user must specify bRegex, bSmart or bCaseInsensitive */\n\t\t\t\tif ( oPre.bRegex === undefined )\n\t\t\t\t{\n\t\t\t\t\toPre.bRegex = true;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif ( oPre.bSmart === undefined )\n\t\t\t\t{\n\t\t\t\t\toPre.bSmart = true;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif ( oPre.bCaseInsensitive === undefined )\n\t\t\t\t{\n\t\t\t\t\toPre.bCaseInsensitive = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t/* Use the column options function to initialise classes etc */\n\t\t\t_fnColumnOptions( oSettings, iCol, null );\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Apply options for a column\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @param {int} iCol column index to consider\n\t\t *  @param {object} oOptions object with sType, bVisible and bSearchable etc\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnColumnOptions( oSettings, iCol, oOptions )\n\t\t{\n\t\t\tvar oCol = oSettings.aoColumns[ iCol ];\n\t\t\t\n\t\t\t/* User specified column options */\n\t\t\tif ( oOptions !== undefined && oOptions !== null )\n\t\t\t{\n\t\t\t\t/* Backwards compatibility for mDataProp */\n\t\t\t\tif ( oOptions.mDataProp && !oOptions.mData )\n\t\t\t\t{\n\t\t\t\t\toOptions.mData = oOptions.mDataProp;\n\t\t\t\t}\n\t\t\n\t\t\t\tif ( oOptions.sType !== undefined )\n\t\t\t\t{\n\t\t\t\t\toCol.sType = oOptions.sType;\n\t\t\t\t\toCol._bAutoType = false;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t$.extend( oCol, oOptions );\n\t\t\t\t_fnMap( oCol, oOptions, \"sWidth\", \"sWidthOrig\" );\n\t\t\n\t\t\t\t/* iDataSort to be applied (backwards compatibility), but aDataSort will take\n\t\t\t\t * priority if defined\n\t\t\t\t */\n\t\t\t\tif ( oOptions.iDataSort !== undefined )\n\t\t\t\t{\n\t\t\t\t\toCol.aDataSort = [ oOptions.iDataSort ];\n\t\t\t\t}\n\t\t\t\t_fnMap( oCol, oOptions, \"aDataSort\" );\n\t\t\t}\n\t\t\n\t\t\t/* Cache the data get and set functions for speed */\n\t\t\tvar mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null;\n\t\t\tvar mData = _fnGetObjectDataFn( oCol.mData );\n\t\t\n\t\t\toCol.fnGetData = function (oData, sSpecific) {\n\t\t\t\tvar innerData = mData( oData, sSpecific );\n\t\t\n\t\t\t\tif ( oCol.mRender && (sSpecific && sSpecific !== '') )\n\t\t\t\t{\n\t\t\t\t\treturn mRender( innerData, sSpecific, oData );\n\t\t\t\t}\n\t\t\t\treturn innerData;\n\t\t\t};\n\t\t\toCol.fnSetData = _fnSetObjectDataFn( oCol.mData );\n\t\t\t\n\t\t\t/* Feature sorting overrides column specific when off */\n\t\t\tif ( !oSettings.oFeatures.bSort )\n\t\t\t{\n\t\t\t\toCol.bSortable = false;\n\t\t\t}\n\t\t\t\n\t\t\t/* Check that the class assignment is correct for sorting */\n\t\t\tif ( !oCol.bSortable ||\n\t\t\t\t ($.inArray('asc', oCol.asSorting) == -1 && $.inArray('desc', oCol.asSorting) == -1) )\n\t\t\t{\n\t\t\t\toCol.sSortingClass = oSettings.oClasses.sSortableNone;\n\t\t\t\toCol.sSortingClassJUI = \"\";\n\t\t\t}\n\t\t\telse if ( $.inArray('asc', oCol.asSorting) == -1 && $.inArray('desc', oCol.asSorting) == -1 )\n\t\t\t{\n\t\t\t\toCol.sSortingClass = oSettings.oClasses.sSortable;\n\t\t\t\toCol.sSortingClassJUI = oSettings.oClasses.sSortJUI;\n\t\t\t}\n\t\t\telse if ( $.inArray('asc', oCol.asSorting) != -1 && $.inArray('desc', oCol.asSorting) == -1 )\n\t\t\t{\n\t\t\t\toCol.sSortingClass = oSettings.oClasses.sSortableAsc;\n\t\t\t\toCol.sSortingClassJUI = oSettings.oClasses.sSortJUIAscAllowed;\n\t\t\t}\n\t\t\telse if ( $.inArray('asc', oCol.asSorting) == -1 && $.inArray('desc', oCol.asSorting) != -1 )\n\t\t\t{\n\t\t\t\toCol.sSortingClass = oSettings.oClasses.sSortableDesc;\n\t\t\t\toCol.sSortingClassJUI = oSettings.oClasses.sSortJUIDescAllowed;\n\t\t\t}\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Adjust the table column widths for new data. Note: you would probably want to \n\t\t * do a redraw after calling this function!\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnAdjustColumnSizing ( oSettings )\n\t\t{\n\t\t\t/* Not interested in doing column width calculation if auto-width is disabled */\n\t\t\tif ( oSettings.oFeatures.bAutoWidth === false )\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t\n\t\t\t_fnCalculateColumnWidths( oSettings );\n\t\t\tfor ( var i=0 , iLen=oSettings.aoColumns.length ; i<iLen ; i++ )\n\t\t\t{\n\t\t\t\toSettings.aoColumns[i].nTh.style.width = oSettings.aoColumns[i].sWidth;\n\t\t\t}\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Covert the index of a visible column to the index in the data array (take account\n\t\t * of hidden columns)\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @param {int} iMatch Visible column index to lookup\n\t\t *  @returns {int} i the data index\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnVisibleToColumnIndex( oSettings, iMatch )\n\t\t{\n\t\t\tvar aiVis = _fnGetColumns( oSettings, 'bVisible' );\n\t\t\n\t\t\treturn typeof aiVis[iMatch] === 'number' ?\n\t\t\t\taiVis[iMatch] :\n\t\t\t\tnull;\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Covert the index of an index in the data array and convert it to the visible\n\t\t *   column index (take account of hidden columns)\n\t\t *  @param {int} iMatch Column index to lookup\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @returns {int} i the data index\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnColumnIndexToVisible( oSettings, iMatch )\n\t\t{\n\t\t\tvar aiVis = _fnGetColumns( oSettings, 'bVisible' );\n\t\t\tvar iPos = $.inArray( iMatch, aiVis );\n\t\t\n\t\t\treturn iPos !== -1 ? iPos : null;\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Get the number of visible columns\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @returns {int} i the number of visible columns\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnVisbleColumns( oSettings )\n\t\t{\n\t\t\treturn _fnGetColumns( oSettings, 'bVisible' ).length;\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Get an array of column indexes that match a given property\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @param {string} sParam Parameter in aoColumns to look for - typically \n\t\t *    bVisible or bSearchable\n\t\t *  @returns {array} Array of indexes with matched properties\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnGetColumns( oSettings, sParam )\n\t\t{\n\t\t\tvar a = [];\n\t\t\n\t\t\t$.map( oSettings.aoColumns, function(val, i) {\n\t\t\t\tif ( val[sParam] ) {\n\t\t\t\t\ta.push( i );\n\t\t\t\t}\n\t\t\t} );\n\t\t\n\t\t\treturn a;\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Get the sort type based on an input string\n\t\t *  @param {string} sData data we wish to know the type of\n\t\t *  @returns {string} type (defaults to 'string' if no type can be detected)\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnDetectType( sData )\n\t\t{\n\t\t\tvar aTypes = DataTable.ext.aTypes;\n\t\t\tvar iLen = aTypes.length;\n\t\t\t\n\t\t\tfor ( var i=0 ; i<iLen ; i++ )\n\t\t\t{\n\t\t\t\tvar sType = aTypes[i]( sData );\n\t\t\t\tif ( sType !== null )\n\t\t\t\t{\n\t\t\t\t\treturn sType;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\treturn 'string';\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Figure out how to reorder a display list\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @returns array {int} aiReturn index list for reordering\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnReOrderIndex ( oSettings, sColumns )\n\t\t{\n\t\t\tvar aColumns = sColumns.split(',');\n\t\t\tvar aiReturn = [];\n\t\t\t\n\t\t\tfor ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )\n\t\t\t{\n\t\t\t\tfor ( var j=0 ; j<iLen ; j++ )\n\t\t\t\t{\n\t\t\t\t\tif ( oSettings.aoColumns[i].sName == aColumns[j] )\n\t\t\t\t\t{\n\t\t\t\t\t\taiReturn.push( j );\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\t\n\t\t\treturn aiReturn;\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Get the column ordering that DataTables expects\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @returns {string} comma separated list of names\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnColumnOrdering ( oSettings )\n\t\t{\n\t\t\tvar sNames = '';\n\t\t\tfor ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )\n\t\t\t{\n\t\t\t\tsNames += oSettings.aoColumns[i].sName+',';\n\t\t\t}\n\t\t\tif ( sNames.length == iLen )\n\t\t\t{\n\t\t\t\treturn \"\";\n\t\t\t}\n\t\t\treturn sNames.slice(0, -1);\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Take the column definitions and static columns arrays and calculate how\n\t\t * they relate to column indexes. The callback function will then apply the\n\t\t * definition found for a column to a suitable configuration object.\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @param {array} aoColDefs The aoColumnDefs array that is to be applied\n\t\t *  @param {array} aoCols The aoColumns array that defines columns individually\n\t\t *  @param {function} fn Callback function - takes two parameters, the calculated\n\t\t *    column index and the definition for that column.\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn )\n\t\t{\n\t\t\tvar i, iLen, j, jLen, k, kLen;\n\t\t\n\t\t\t// Column definitions with aTargets\n\t\t\tif ( aoColDefs )\n\t\t\t{\n\t\t\t\t/* Loop over the definitions array - loop in reverse so first instance has priority */\n\t\t\t\tfor ( i=aoColDefs.length-1 ; i>=0 ; i-- )\n\t\t\t\t{\n\t\t\t\t\t/* Each definition can target multiple columns, as it is an array */\n\t\t\t\t\tvar aTargets = aoColDefs[i].aTargets;\n\t\t\t\t\tif ( !$.isArray( aTargets ) )\n\t\t\t\t\t{\n\t\t\t\t\t\t_fnLog( oSettings, 1, 'aTargets must be an array of targets, not a '+(typeof aTargets) );\n\t\t\t\t\t}\n\t\t\n\t\t\t\t\tfor ( j=0, jLen=aTargets.length ; j<jLen ; j++ )\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t/* Add columns that we don't yet know about */\n\t\t\t\t\t\t\twhile( oSettings.aoColumns.length <= aTargets[j] )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t_fnAddColumn( oSettings );\n\t\t\t\t\t\t\t}\n\t\t\n\t\t\t\t\t\t\t/* Integer, basic index */\n\t\t\t\t\t\t\tfn( aTargets[j], aoColDefs[i] );\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t/* Negative integer, right to left column counting */\n\t\t\t\t\t\t\tfn( oSettings.aoColumns.length+aTargets[j], aoColDefs[i] );\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if ( typeof aTargets[j] === 'string' )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t/* Class name matching on TH element */\n\t\t\t\t\t\t\tfor ( k=0, kLen=oSettings.aoColumns.length ; k<kLen ; k++ )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif ( aTargets[j] == \"_all\" ||\n\t\t\t\t\t\t\t\t     $(oSettings.aoColumns[k].nTh).hasClass( aTargets[j] ) )\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tfn( k, aoColDefs[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}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\n\t\t\t// Statically defined columns array\n\t\t\tif ( aoCols )\n\t\t\t{\n\t\t\t\tfor ( i=0, iLen=aoCols.length ; i<iLen ; i++ )\n\t\t\t\t{\n\t\t\t\t\tfn( i, aoCols[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\t/**\n\t\t * Add a data array to the table, creating DOM node etc. This is the parallel to \n\t\t * _fnGatherData, but for adding rows from a Javascript source, rather than a\n\t\t * DOM source.\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @param {array} aData data array to be added\n\t\t *  @returns {int} >=0 if successful (index of new aoData entry), -1 if failed\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnAddData ( oSettings, aDataSupplied )\n\t\t{\n\t\t\tvar oCol;\n\t\t\t\n\t\t\t/* Take an independent copy of the data source so we can bash it about as we wish */\n\t\t\tvar aDataIn = ($.isArray(aDataSupplied)) ?\n\t\t\t\taDataSupplied.slice() :\n\t\t\t\t$.extend( true, {}, aDataSupplied );\n\t\t\t\n\t\t\t/* Create the object for storing information about this new row */\n\t\t\tvar iRow = oSettings.aoData.length;\n\t\t\tvar oData = $.extend( true, {}, DataTable.models.oRow );\n\t\t\toData._aData = aDataIn;\n\t\t\toSettings.aoData.push( oData );\n\t\t\n\t\t\t/* Create the cells */\n\t\t\tvar nTd, sThisType;\n\t\t\tfor ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )\n\t\t\t{\n\t\t\t\toCol = oSettings.aoColumns[i];\n\t\t\n\t\t\t\t/* Use rendered data for filtering / sorting */\n\t\t\t\tif ( typeof oCol.fnRender === 'function' && oCol.bUseRendered && oCol.mData !== null )\n\t\t\t\t{\n\t\t\t\t\t_fnSetCellData( oSettings, iRow, i, _fnRender(oSettings, iRow, i) );\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t_fnSetCellData( oSettings, iRow, i, _fnGetCellData( oSettings, iRow, i ) );\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t/* See if we should auto-detect the column type */\n\t\t\t\tif ( oCol._bAutoType && oCol.sType != 'string' )\n\t\t\t\t{\n\t\t\t\t\t/* Attempt to auto detect the type - same as _fnGatherData() */\n\t\t\t\t\tvar sVarType = _fnGetCellData( oSettings, iRow, i, 'type' );\n\t\t\t\t\tif ( sVarType !== null && sVarType !== '' )\n\t\t\t\t\t{\n\t\t\t\t\t\tsThisType = _fnDetectType( sVarType );\n\t\t\t\t\t\tif ( oCol.sType === null )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\toCol.sType = sThisType;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if ( oCol.sType != sThisType && oCol.sType != \"html\" )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t/* String is always the 'fallback' option */\n\t\t\t\t\t\t\toCol.sType = 'string';\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\n\t\t\t/* Add to the display array */\n\t\t\toSettings.aiDisplayMaster.push( iRow );\n\t\t\n\t\t\t/* Create the DOM information */\n\t\t\tif ( !oSettings.oFeatures.bDeferRender )\n\t\t\t{\n\t\t\t\t_fnCreateTr( oSettings, iRow );\n\t\t\t}\n\t\t\n\t\t\treturn iRow;\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Read in the data from the target table from the DOM\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnGatherData( oSettings )\n\t\t{\n\t\t\tvar iLoop, i, iLen, j, jLen, jInner,\n\t\t\t \tnTds, nTrs, nTd, nTr, aLocalData, iThisIndex,\n\t\t\t\tiRow, iRows, iColumn, iColumns, sNodeName,\n\t\t\t\toCol, oData;\n\t\t\t\n\t\t\t/*\n\t\t\t * Process by row first\n\t\t\t * Add the data object for the whole table - storing the tr node. Note - no point in getting\n\t\t\t * DOM based data if we are going to go and replace it with Ajax source data.\n\t\t\t */\n\t\t\tif ( oSettings.bDeferLoading || oSettings.sAjaxSource === null )\n\t\t\t{\n\t\t\t\tnTr = oSettings.nTBody.firstChild;\n\t\t\t\twhile ( nTr )\n\t\t\t\t{\n\t\t\t\t\tif ( nTr.nodeName.toUpperCase() == \"TR\" )\n\t\t\t\t\t{\n\t\t\t\t\t\tiThisIndex = oSettings.aoData.length;\n\t\t\t\t\t\tnTr._DT_RowIndex = iThisIndex;\n\t\t\t\t\t\toSettings.aoData.push( $.extend( true, {}, DataTable.models.oRow, {\n\t\t\t\t\t\t\t\"nTr\": nTr\n\t\t\t\t\t\t} ) );\n\t\t\n\t\t\t\t\t\toSettings.aiDisplayMaster.push( iThisIndex );\n\t\t\t\t\t\tnTd = nTr.firstChild;\n\t\t\t\t\t\tjInner = 0;\n\t\t\t\t\t\twhile ( nTd )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsNodeName = nTd.nodeName.toUpperCase();\n\t\t\t\t\t\t\tif ( sNodeName == \"TD\" || sNodeName == \"TH\" )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t_fnSetCellData( oSettings, iThisIndex, jInner, $.trim(nTd.innerHTML) );\n\t\t\t\t\t\t\t\tjInner++;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tnTd = nTd.nextSibling;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tnTr = nTr.nextSibling;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t/* Gather in the TD elements of the Table - note that this is basically the same as\n\t\t\t * fnGetTdNodes, but that function takes account of hidden columns, which we haven't yet\n\t\t\t * setup!\n\t\t\t */\n\t\t\tnTrs = _fnGetTrNodes( oSettings );\n\t\t\tnTds = [];\n\t\t\tfor ( i=0, iLen=nTrs.length ; i<iLen ; i++ )\n\t\t\t{\n\t\t\t\tnTd = nTrs[i].firstChild;\n\t\t\t\twhile ( nTd )\n\t\t\t\t{\n\t\t\t\t\tsNodeName = nTd.nodeName.toUpperCase();\n\t\t\t\t\tif ( sNodeName == \"TD\" || sNodeName == \"TH\" )\n\t\t\t\t\t{\n\t\t\t\t\t\tnTds.push( nTd );\n\t\t\t\t\t}\n\t\t\t\t\tnTd = nTd.nextSibling;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t/* Now process by column */\n\t\t\tfor ( iColumn=0, iColumns=oSettings.aoColumns.length ; iColumn<iColumns ; iColumn++ )\n\t\t\t{\n\t\t\t\toCol = oSettings.aoColumns[iColumn];\n\t\t\n\t\t\t\t/* Get the title of the column - unless there is a user set one */\n\t\t\t\tif ( oCol.sTitle === null )\n\t\t\t\t{\n\t\t\t\t\toCol.sTitle = oCol.nTh.innerHTML;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tvar\n\t\t\t\t\tbAutoType = oCol._bAutoType,\n\t\t\t\t\tbRender = typeof oCol.fnRender === 'function',\n\t\t\t\t\tbClass = oCol.sClass !== null,\n\t\t\t\t\tbVisible = oCol.bVisible,\n\t\t\t\t\tnCell, sThisType, sRendered, sValType;\n\t\t\t\t\n\t\t\t\t/* A single loop to rule them all (and be more efficient) */\n\t\t\t\tif ( bAutoType || bRender || bClass || !bVisible )\n\t\t\t\t{\n\t\t\t\t\tfor ( iRow=0, iRows=oSettings.aoData.length ; iRow<iRows ; iRow++ )\n\t\t\t\t\t{\n\t\t\t\t\t\toData = oSettings.aoData[iRow];\n\t\t\t\t\t\tnCell = nTds[ (iRow*iColumns) + iColumn ];\n\t\t\t\t\t\t\n\t\t\t\t\t\t/* Type detection */\n\t\t\t\t\t\tif ( bAutoType && oCol.sType != 'string' )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsValType = _fnGetCellData( oSettings, iRow, iColumn, 'type' );\n\t\t\t\t\t\t\tif ( sValType !== '' )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tsThisType = _fnDetectType( sValType );\n\t\t\t\t\t\t\t\tif ( oCol.sType === null )\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\toCol.sType = sThisType;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse if ( oCol.sType != sThisType && \n\t\t\t\t\t\t\t\t          oCol.sType != \"html\" )\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t/* String is always the 'fallback' option */\n\t\t\t\t\t\t\t\t\toCol.sType = 'string';\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\n\t\t\t\t\t\tif ( oCol.mRender )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// mRender has been defined, so we need to get the value and set it\n\t\t\t\t\t\t\tnCell.innerHTML = _fnGetCellData( oSettings, iRow, iColumn, 'display' );\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if ( oCol.mData !== iColumn )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// If mData is not the same as the column number, then we need to\n\t\t\t\t\t\t\t// get the dev set value. If it is the column, no point in wasting\n\t\t\t\t\t\t\t// time setting the value that is already there!\n\t\t\t\t\t\t\tnCell.innerHTML = _fnGetCellData( oSettings, iRow, iColumn, 'display' );\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\t/* Rendering */\n\t\t\t\t\t\tif ( bRender )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsRendered = _fnRender( oSettings, iRow, iColumn );\n\t\t\t\t\t\t\tnCell.innerHTML = sRendered;\n\t\t\t\t\t\t\tif ( oCol.bUseRendered )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t/* Use the rendered data for filtering / sorting */\n\t\t\t\t\t\t\t\t_fnSetCellData( oSettings, iRow, iColumn, sRendered );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\t/* Classes */\n\t\t\t\t\t\tif ( bClass )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tnCell.className += ' '+oCol.sClass;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\t/* Column visibility */\n\t\t\t\t\t\tif ( !bVisible )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\toData._anHidden[iColumn] = nCell;\n\t\t\t\t\t\t\tnCell.parentNode.removeChild( nCell );\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\toData._anHidden[iColumn] = null;\n\t\t\t\t\t\t}\n\t\t\n\t\t\t\t\t\tif ( oCol.fnCreatedCell )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\toCol.fnCreatedCell.call( oSettings.oInstance,\n\t\t\t\t\t\t\t\tnCell, _fnGetCellData( oSettings, iRow, iColumn, 'display' ), oData._aData, iRow, iColumn\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\t\t\t/* Row created callbacks */\n\t\t\tif ( oSettings.aoRowCreatedCallback.length !== 0 )\n\t\t\t{\n\t\t\t\tfor ( i=0, iLen=oSettings.aoData.length ; i<iLen ; i++ )\n\t\t\t\t{\n\t\t\t\t\toData = oSettings.aoData[i];\n\t\t\t\t\t_fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [oData.nTr, oData._aData, i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Take a TR element and convert it to an index in aoData\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @param {node} n the TR element to find\n\t\t *  @returns {int} index if the node is found, null if not\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnNodeToDataIndex( oSettings, n )\n\t\t{\n\t\t\treturn (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null;\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Take a TD element and convert it into a column data index (not the visible index)\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @param {int} iRow The row number the TD/TH can be found in\n\t\t *  @param {node} n The TD/TH element to find\n\t\t *  @returns {int} index if the node is found, -1 if not\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnNodeToColumnIndex( oSettings, iRow, n )\n\t\t{\n\t\t\tvar anCells = _fnGetTdNodes( oSettings, iRow );\n\t\t\n\t\t\tfor ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )\n\t\t\t{\n\t\t\t\tif ( anCells[i] === n )\n\t\t\t\t{\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\t\n\t\t\n\t\t/**\n\t\t * Get an array of data for a given row from the internal data cache\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @param {int} iRow aoData row id\n\t\t *  @param {string} sSpecific data get type ('type' 'filter' 'sort')\n\t\t *  @param {array} aiColumns Array of column indexes to get data from\n\t\t *  @returns {array} Data array\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnGetRowData( oSettings, iRow, sSpecific, aiColumns )\n\t\t{\n\t\t\tvar out = [];\n\t\t\tfor ( var i=0, iLen=aiColumns.length ; i<iLen ; i++ )\n\t\t\t{\n\t\t\t\tout.push( _fnGetCellData( oSettings, iRow, aiColumns[i], sSpecific ) );\n\t\t\t}\n\t\t\treturn out;\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Get the data for a given cell from the internal cache, taking into account data mapping\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @param {int} iRow aoData row id\n\t\t *  @param {int} iCol Column index\n\t\t *  @param {string} sSpecific data get type ('display', 'type' 'filter' 'sort')\n\t\t *  @returns {*} Cell data\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnGetCellData( oSettings, iRow, iCol, sSpecific )\n\t\t{\n\t\t\tvar sData;\n\t\t\tvar oCol = oSettings.aoColumns[iCol];\n\t\t\tvar oData = oSettings.aoData[iRow]._aData;\n\t\t\n\t\t\tif ( (sData=oCol.fnGetData( oData, sSpecific )) === undefined )\n\t\t\t{\n\t\t\t\tif ( oSettings.iDrawError != oSettings.iDraw && oCol.sDefaultContent === null )\n\t\t\t\t{\n\t\t\t\t\t_fnLog( oSettings, 0, \"Requested unknown parameter \"+\n\t\t\t\t\t\t(typeof oCol.mData=='function' ? '{mData function}' : \"'\"+oCol.mData+\"'\")+\n\t\t\t\t\t\t\" from the data source for row \"+iRow );\n\t\t\t\t\toSettings.iDrawError = oSettings.iDraw;\n\t\t\t\t}\n\t\t\t\treturn oCol.sDefaultContent;\n\t\t\t}\n\t\t\n\t\t\t/* When the data source is null, we can use default column data */\n\t\t\tif ( sData === null && oCol.sDefaultContent !== null )\n\t\t\t{\n\t\t\t\tsData = oCol.sDefaultContent;\n\t\t\t}\n\t\t\telse if ( typeof sData === 'function' )\n\t\t\t{\n\t\t\t\t/* If the data source is a function, then we run it and use the return */\n\t\t\t\treturn sData();\n\t\t\t}\n\t\t\n\t\t\tif ( sSpecific == 'display' && sData === null )\n\t\t\t{\n\t\t\t\treturn '';\n\t\t\t}\n\t\t\treturn sData;\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Set the value for a specific cell, into the internal data cache\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @param {int} iRow aoData row id\n\t\t *  @param {int} iCol Column index\n\t\t *  @param {*} val Value to set\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnSetCellData( oSettings, iRow, iCol, val )\n\t\t{\n\t\t\tvar oCol = oSettings.aoColumns[iCol];\n\t\t\tvar oData = oSettings.aoData[iRow]._aData;\n\t\t\n\t\t\toCol.fnSetData( oData, val );\n\t\t}\n\t\t\n\t\t\n\t\t// Private variable that is used to match array syntax in the data property object\n\t\tvar __reArray = /\\[.*?\\]$/;\n\t\t\n\t\t/**\n\t\t * Return a function that can be used to get data from a source object, taking\n\t\t * into account the ability to use nested objects as a source\n\t\t *  @param {string|int|function} mSource The data source for the object\n\t\t *  @returns {function} Data get function\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnGetObjectDataFn( mSource )\n\t\t{\n\t\t\tif ( mSource === null )\n\t\t\t{\n\t\t\t\t/* Give an empty string for rendering / sorting etc */\n\t\t\t\treturn function (data, type) {\n\t\t\t\t\treturn null;\n\t\t\t\t};\n\t\t\t}\n\t\t\telse if ( typeof mSource === 'function' )\n\t\t\t{\n\t\t\t\treturn function (data, type, extra) {\n\t\t\t\t\treturn mSource( data, type, extra );\n\t\t\t\t};\n\t\t\t}\n\t\t\telse if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 || mSource.indexOf('[') !== -1) )\n\t\t\t{\n\t\t\t\t/* If there is a . in the source string then the data source is in a \n\t\t\t\t * nested object so we loop over the data for each level to get the next\n\t\t\t\t * level down. On each loop we test for undefined, and if found immediately\n\t\t\t\t * return. This allows entire objects to be missing and sDefaultContent to\n\t\t\t\t * be used if defined, rather than throwing an error\n\t\t\t\t */\n\t\t\t\tvar fetchData = function (data, type, src) {\n\t\t\t\t\tvar a = src.split('.');\n\t\t\t\t\tvar arrayNotation, out, innerSrc;\n\t\t\n\t\t\t\t\tif ( src !== \"\" )\n\t\t\t\t\t{\n\t\t\t\t\t\tfor ( var i=0, iLen=a.length ; i<iLen ; i++ )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// Check if we are dealing with an array notation request\n\t\t\t\t\t\t\tarrayNotation = a[i].match(__reArray);\n\t\t\n\t\t\t\t\t\t\tif ( arrayNotation ) {\n\t\t\t\t\t\t\t\ta[i] = a[i].replace(__reArray, '');\n\t\t\n\t\t\t\t\t\t\t\t// Condition allows simply [] to be passed in\n\t\t\t\t\t\t\t\tif ( a[i] !== \"\" ) {\n\t\t\t\t\t\t\t\t\tdata = data[ a[i] ];\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tout = [];\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t// Get the remainder of the nested object to get\n\t\t\t\t\t\t\t\ta.splice( 0, i+1 );\n\t\t\t\t\t\t\t\tinnerSrc = a.join('.');\n\t\t\n\t\t\t\t\t\t\t\t// Traverse each entry in the array getting the properties requested\n\t\t\t\t\t\t\t\tfor ( var j=0, jLen=data.length ; j<jLen ; j++ ) {\n\t\t\t\t\t\t\t\t\tout.push( fetchData( data[j], type, innerSrc ) );\n\t\t\t\t\t\t\t\t}\n\t\t\n\t\t\t\t\t\t\t\t// If a string is given in between the array notation indicators, that\n\t\t\t\t\t\t\t\t// is used to join the strings together, otherwise an array is returned\n\t\t\t\t\t\t\t\tvar join = arrayNotation[0].substring(1, arrayNotation[0].length-1);\n\t\t\t\t\t\t\t\tdata = (join===\"\") ? out : out.join(join);\n\t\t\n\t\t\t\t\t\t\t\t// The inner call to fetchData has already traversed through the remainder\n\t\t\t\t\t\t\t\t// of the source requested, so we exit from the loop\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\n\t\t\t\t\t\t\tif ( data === null || data[ a[i] ] === undefined )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tdata = data[ a[i] ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\n\t\t\t\t\treturn data;\n\t\t\t\t};\n\t\t\n\t\t\t\treturn function (data, type) {\n\t\t\t\t\treturn fetchData( data, type, mSource );\n\t\t\t\t};\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t/* Array or flat object mapping */\n\t\t\t\treturn function (data, type) {\n\t\t\t\t\treturn data[mSource];\t\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Return a function that can be used to set data from a source object, taking\n\t\t * into account the ability to use nested objects as a source\n\t\t *  @param {string|int|function} mSource The data source for the object\n\t\t *  @returns {function} Data set function\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnSetObjectDataFn( mSource )\n\t\t{\n\t\t\tif ( mSource === null )\n\t\t\t{\n\t\t\t\t/* Nothing to do when the data source is null */\n\t\t\t\treturn function (data, val) {};\n\t\t\t}\n\t\t\telse if ( typeof mSource === 'function' )\n\t\t\t{\n\t\t\t\treturn function (data, val) {\n\t\t\t\t\tmSource( data, 'set', val );\n\t\t\t\t};\n\t\t\t}\n\t\t\telse if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 || mSource.indexOf('[') !== -1) )\n\t\t\t{\n\t\t\t\t/* Like the get, we need to get data from a nested object */\n\t\t\t\tvar setData = function (data, val, src) {\n\t\t\t\t\tvar a = src.split('.'), b;\n\t\t\t\t\tvar arrayNotation, o, innerSrc;\n\t\t\n\t\t\t\t\tfor ( var i=0, iLen=a.length-1 ; i<iLen ; i++ )\n\t\t\t\t\t{\n\t\t\t\t\t\t// Check if we are dealing with an array notation request\n\t\t\t\t\t\tarrayNotation = a[i].match(__reArray);\n\t\t\n\t\t\t\t\t\tif ( arrayNotation )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ta[i] = a[i].replace(__reArray, '');\n\t\t\t\t\t\t\tdata[ a[i] ] = [];\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t// Get the remainder of the nested object to set so we can recurse\n\t\t\t\t\t\t\tb = a.slice();\n\t\t\t\t\t\t\tb.splice( 0, i+1 );\n\t\t\t\t\t\t\tinnerSrc = b.join('.');\n\t\t\n\t\t\t\t\t\t\t// Traverse each entry in the array setting the properties requested\n\t\t\t\t\t\t\tfor ( var j=0, jLen=val.length ; j<jLen ; j++ )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\to = {};\n\t\t\t\t\t\t\t\tsetData( o, val[j], innerSrc );\n\t\t\t\t\t\t\t\tdata[ a[i] ].push( o );\n\t\t\t\t\t\t\t}\n\t\t\n\t\t\t\t\t\t\t// The inner call to setData has already traversed through the remainder\n\t\t\t\t\t\t\t// of the source and has set the data, thus we can exit here\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\n\t\t\t\t\t\t// If the nested object doesn't currently exist - since we are\n\t\t\t\t\t\t// trying to set the value - create it\n\t\t\t\t\t\tif ( data[ a[i] ] === null || data[ a[i] ] === undefined )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tdata[ a[i] ] = {};\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdata = data[ a[i] ];\n\t\t\t\t\t}\n\t\t\n\t\t\t\t\t// If array notation is used, we just want to strip it and use the property name\n\t\t\t\t\t// and assign the value. If it isn't used, then we get the result we want anyway\n\t\t\t\t\tdata[ a[a.length-1].replace(__reArray, '') ] = val;\n\t\t\t\t};\n\t\t\n\t\t\t\treturn function (data, val) {\n\t\t\t\t\treturn setData( data, val, mSource );\n\t\t\t\t};\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t/* Array or flat object mapping */\n\t\t\t\treturn function (data, val) {\n\t\t\t\t\tdata[mSource] = val;\t\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Return an array with the full table data\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @returns array {array} aData Master data array\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnGetDataMaster ( oSettings )\n\t\t{\n\t\t\tvar aData = [];\n\t\t\tvar iLen = oSettings.aoData.length;\n\t\t\tfor ( var i=0 ; i<iLen; i++ )\n\t\t\t{\n\t\t\t\taData.push( oSettings.aoData[i]._aData );\n\t\t\t}\n\t\t\treturn aData;\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Nuke the table\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnClearTable( oSettings )\n\t\t{\n\t\t\toSettings.aoData.splice( 0, oSettings.aoData.length );\n\t\t\toSettings.aiDisplayMaster.splice( 0, oSettings.aiDisplayMaster.length );\n\t\t\toSettings.aiDisplay.splice( 0, oSettings.aiDisplay.length );\n\t\t\t_fnCalculateEnd( oSettings );\n\t\t}\n\t\t\n\t\t\n\t\t /**\n\t\t * Take an array of integers (index array) and remove a target integer (value - not \n\t\t * the key!)\n\t\t *  @param {array} a Index array to target\n\t\t *  @param {int} iTarget value to find\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnDeleteIndex( a, iTarget )\n\t\t{\n\t\t\tvar iTargetIndex = -1;\n\t\t\t\n\t\t\tfor ( var i=0, iLen=a.length ; i<iLen ; i++ )\n\t\t\t{\n\t\t\t\tif ( a[i] == iTarget )\n\t\t\t\t{\n\t\t\t\t\tiTargetIndex = i;\n\t\t\t\t}\n\t\t\t\telse if ( a[i] > iTarget )\n\t\t\t\t{\n\t\t\t\t\ta[i]--;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif ( iTargetIndex != -1 )\n\t\t\t{\n\t\t\t\ta.splice( iTargetIndex, 1 );\n\t\t\t}\n\t\t}\n\t\t\n\t\t\n\t\t /**\n\t\t * Call the developer defined fnRender function for a given cell (row/column) with\n\t\t * the required parameters and return the result.\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @param {int} iRow aoData index for the row\n\t\t *  @param {int} iCol aoColumns index for the column\n\t\t *  @returns {*} Return of the developer's fnRender function\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnRender( oSettings, iRow, iCol )\n\t\t{\n\t\t\tvar oCol = oSettings.aoColumns[iCol];\n\t\t\n\t\t\treturn oCol.fnRender( {\n\t\t\t\t\"iDataRow\":    iRow,\n\t\t\t\t\"iDataColumn\": iCol,\n\t\t\t\t\"oSettings\":   oSettings,\n\t\t\t\t\"aData\":       oSettings.aoData[iRow]._aData,\n\t\t\t\t\"mDataProp\":   oCol.mData\n\t\t\t}, _fnGetCellData(oSettings, iRow, iCol, 'display') );\n\t\t}\n\t\t/**\n\t\t * Create a new TR element (and it's TD children) for a row\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @param {int} iRow Row to consider\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnCreateTr ( oSettings, iRow )\n\t\t{\n\t\t\tvar oData = oSettings.aoData[iRow];\n\t\t\tvar nTd;\n\t\t\n\t\t\tif ( oData.nTr === null )\n\t\t\t{\n\t\t\t\toData.nTr = document.createElement('tr');\n\t\t\n\t\t\t\t/* Use a private property on the node to allow reserve mapping from the node\n\t\t\t\t * to the aoData array for fast look up\n\t\t\t\t */\n\t\t\t\toData.nTr._DT_RowIndex = iRow;\n\t\t\n\t\t\t\t/* Special parameters can be given by the data source to be used on the row */\n\t\t\t\tif ( oData._aData.DT_RowId )\n\t\t\t\t{\n\t\t\t\t\toData.nTr.id = oData._aData.DT_RowId;\n\t\t\t\t}\n\t\t\n\t\t\t\tif ( oData._aData.DT_RowClass )\n\t\t\t\t{\n\t\t\t\t\toData.nTr.className = oData._aData.DT_RowClass;\n\t\t\t\t}\n\t\t\n\t\t\t\t/* Process each column */\n\t\t\t\tfor ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )\n\t\t\t\t{\n\t\t\t\t\tvar oCol = oSettings.aoColumns[i];\n\t\t\t\t\tnTd = document.createElement( oCol.sCellType );\n\t\t\n\t\t\t\t\t/* Render if needed - if bUseRendered is true then we already have the rendered\n\t\t\t\t\t * value in the data source - so can just use that\n\t\t\t\t\t */\n\t\t\t\t\tnTd.innerHTML = (typeof oCol.fnRender === 'function' && (!oCol.bUseRendered || oCol.mData === null)) ?\n\t\t\t\t\t\t_fnRender( oSettings, iRow, i ) :\n\t\t\t\t\t\t_fnGetCellData( oSettings, iRow, i, 'display' );\n\t\t\t\t\n\t\t\t\t\t/* Add user defined class */\n\t\t\t\t\tif ( oCol.sClass !== null )\n\t\t\t\t\t{\n\t\t\t\t\t\tnTd.className = oCol.sClass;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif ( oCol.bVisible )\n\t\t\t\t\t{\n\t\t\t\t\t\toData.nTr.appendChild( nTd );\n\t\t\t\t\t\toData._anHidden[i] = null;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\toData._anHidden[i] = nTd;\n\t\t\t\t\t}\n\t\t\n\t\t\t\t\tif ( oCol.fnCreatedCell )\n\t\t\t\t\t{\n\t\t\t\t\t\toCol.fnCreatedCell.call( oSettings.oInstance,\n\t\t\t\t\t\t\tnTd, _fnGetCellData( oSettings, iRow, i, 'display' ), oData._aData, iRow, i\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\n\t\t\t\t_fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [oData.nTr, oData._aData, iRow] );\n\t\t\t}\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Create the HTML header for the table\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnBuildHead( oSettings )\n\t\t{\n\t\t\tvar i, nTh, iLen, j, jLen;\n\t\t\tvar iThs = $('th, td', oSettings.nTHead).length;\n\t\t\tvar iCorrector = 0;\n\t\t\tvar jqChildren;\n\t\t\t\n\t\t\t/* If there is a header in place - then use it - otherwise it's going to get nuked... */\n\t\t\tif ( iThs !== 0 )\n\t\t\t{\n\t\t\t\t/* We've got a thead from the DOM, so remove hidden columns and apply width to vis cols */\n\t\t\t\tfor ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )\n\t\t\t\t{\n\t\t\t\t\tnTh = oSettings.aoColumns[i].nTh;\n\t\t\t\t\tnTh.setAttribute('role', 'columnheader');\n\t\t\t\t\tif ( oSettings.aoColumns[i].bSortable )\n\t\t\t\t\t{\n\t\t\t\t\t\tnTh.setAttribute('tabindex', oSettings.iTabIndex);\n\t\t\t\t\t\tnTh.setAttribute('aria-controls', oSettings.sTableId);\n\t\t\t\t\t}\n\t\t\n\t\t\t\t\tif ( oSettings.aoColumns[i].sClass !== null )\n\t\t\t\t\t{\n\t\t\t\t\t\t$(nTh).addClass( oSettings.aoColumns[i].sClass );\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t/* Set the title of the column if it is user defined (not what was auto detected) */\n\t\t\t\t\tif ( oSettings.aoColumns[i].sTitle != nTh.innerHTML )\n\t\t\t\t\t{\n\t\t\t\t\t\tnTh.innerHTML = oSettings.aoColumns[i].sTitle;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t/* We don't have a header in the DOM - so we are going to have to create one */\n\t\t\t\tvar nTr = document.createElement( \"tr\" );\n\t\t\t\t\n\t\t\t\tfor ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )\n\t\t\t\t{\n\t\t\t\t\tnTh = oSettings.aoColumns[i].nTh;\n\t\t\t\t\tnTh.innerHTML = oSettings.aoColumns[i].sTitle;\n\t\t\t\t\tnTh.setAttribute('tabindex', '0');\n\t\t\t\t\t\n\t\t\t\t\tif ( oSettings.aoColumns[i].sClass !== null )\n\t\t\t\t\t{\n\t\t\t\t\t\t$(nTh).addClass( oSettings.aoColumns[i].sClass );\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tnTr.appendChild( nTh );\n\t\t\t\t}\n\t\t\t\t$(oSettings.nTHead).html( '' )[0].appendChild( nTr );\n\t\t\t\t_fnDetectHeader( oSettings.aoHeader, oSettings.nTHead );\n\t\t\t}\n\t\t\t\n\t\t\t/* ARIA role for the rows */\t\n\t\t\t$(oSettings.nTHead).children('tr').attr('role', 'row');\n\t\t\t\n\t\t\t/* Add the extra markup needed by jQuery UI's themes */\n\t\t\tif ( oSettings.bJUI )\n\t\t\t{\n\t\t\t\tfor ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )\n\t\t\t\t{\n\t\t\t\t\tnTh = oSettings.aoColumns[i].nTh;\n\t\t\t\t\t\n\t\t\t\t\tvar nDiv = document.createElement('div');\n\t\t\t\t\tnDiv.className = oSettings.oClasses.sSortJUIWrapper;\n\t\t\t\t\t$(nTh).contents().appendTo(nDiv);\n\t\t\t\t\t\n\t\t\t\t\tvar nSpan = document.createElement('span');\n\t\t\t\t\tnSpan.className = oSettings.oClasses.sSortIcon;\n\t\t\t\t\tnDiv.appendChild( nSpan );\n\t\t\t\t\tnTh.appendChild( nDiv );\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif ( oSettings.oFeatures.bSort )\n\t\t\t{\n\t\t\t\tfor ( i=0 ; i<oSettings.aoColumns.length ; i++ )\n\t\t\t\t{\n\t\t\t\t\tif ( oSettings.aoColumns[i].bSortable !== false )\n\t\t\t\t\t{\n\t\t\t\t\t\t_fnSortAttachListener( oSettings, oSettings.aoColumns[i].nTh, i );\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t$(oSettings.aoColumns[i].nTh).addClass( oSettings.oClasses.sSortableNone );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t/* Deal with the footer - add classes if required */\n\t\t\tif ( oSettings.oClasses.sFooterTH !== \"\" )\n\t\t\t{\n\t\t\t\t$(oSettings.nTFoot).children('tr').children('th').addClass( oSettings.oClasses.sFooterTH );\n\t\t\t}\n\t\t\t\n\t\t\t/* Cache the footer elements */\n\t\t\tif ( oSettings.nTFoot !== null )\n\t\t\t{\n\t\t\t\tvar anCells = _fnGetUniqueThs( oSettings, null, oSettings.aoFooter );\n\t\t\t\tfor ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )\n\t\t\t\t{\n\t\t\t\t\tif ( anCells[i] )\n\t\t\t\t\t{\n\t\t\t\t\t\toSettings.aoColumns[i].nTf = anCells[i];\n\t\t\t\t\t\tif ( oSettings.aoColumns[i].sClass )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$(anCells[i]).addClass( oSettings.aoColumns[i].sClass );\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\t\n\t\t\n\t\t/**\n\t\t * Draw the header (or footer) element based on the column visibility states. The\n\t\t * methodology here is to use the layout array from _fnDetectHeader, modified for\n\t\t * the instantaneous column visibility, to construct the new layout. The grid is\n\t\t * traversed over cell at a time in a rows x columns grid fashion, although each \n\t\t * cell insert can cover multiple elements in the grid - which is tracks using the\n\t\t * aApplied array. Cell inserts in the grid will only occur where there isn't\n\t\t * already a cell in that position.\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @param array {objects} aoSource Layout array from _fnDetectHeader\n\t\t *  @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc, \n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnDrawHead( oSettings, aoSource, bIncludeHidden )\n\t\t{\n\t\t\tvar i, iLen, j, jLen, k, kLen, n, nLocalTr;\n\t\t\tvar aoLocal = [];\n\t\t\tvar aApplied = [];\n\t\t\tvar iColumns = oSettings.aoColumns.length;\n\t\t\tvar iRowspan, iColspan;\n\t\t\n\t\t\tif (  bIncludeHidden === undefined )\n\t\t\t{\n\t\t\t\tbIncludeHidden = false;\n\t\t\t}\n\t\t\n\t\t\t/* Make a copy of the master layout array, but without the visible columns in it */\n\t\t\tfor ( i=0, iLen=aoSource.length ; i<iLen ; i++ )\n\t\t\t{\n\t\t\t\taoLocal[i] = aoSource[i].slice();\n\t\t\t\taoLocal[i].nTr = aoSource[i].nTr;\n\t\t\n\t\t\t\t/* Remove any columns which are currently hidden */\n\t\t\t\tfor ( j=iColumns-1 ; j>=0 ; j-- )\n\t\t\t\t{\n\t\t\t\t\tif ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden )\n\t\t\t\t\t{\n\t\t\t\t\t\taoLocal[i].splice( j, 1 );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\n\t\t\t\t/* Prep the applied array - it needs an element for each row */\n\t\t\t\taApplied.push( [] );\n\t\t\t}\n\t\t\n\t\t\tfor ( i=0, iLen=aoLocal.length ; i<iLen ; i++ )\n\t\t\t{\n\t\t\t\tnLocalTr = aoLocal[i].nTr;\n\t\t\t\t\n\t\t\t\t/* All cells are going to be replaced, so empty out the row */\n\t\t\t\tif ( nLocalTr )\n\t\t\t\t{\n\t\t\t\t\twhile( (n = nLocalTr.firstChild) )\n\t\t\t\t\t{\n\t\t\t\t\t\tnLocalTr.removeChild( n );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\n\t\t\t\tfor ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ )\n\t\t\t\t{\n\t\t\t\t\tiRowspan = 1;\n\t\t\t\t\tiColspan = 1;\n\t\t\n\t\t\t\t\t/* Check to see if there is already a cell (row/colspan) covering our target\n\t\t\t\t\t * insert point. If there is, then there is nothing to do.\n\t\t\t\t\t */\n\t\t\t\t\tif ( aApplied[i][j] === undefined )\n\t\t\t\t\t{\n\t\t\t\t\t\tnLocalTr.appendChild( aoLocal[i][j].cell );\n\t\t\t\t\t\taApplied[i][j] = 1;\n\t\t\n\t\t\t\t\t\t/* Expand the cell to cover as many rows as needed */\n\t\t\t\t\t\twhile ( aoLocal[i+iRowspan] !== undefined &&\n\t\t\t\t\t\t        aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\taApplied[i+iRowspan][j] = 1;\n\t\t\t\t\t\t\tiRowspan++;\n\t\t\t\t\t\t}\n\t\t\n\t\t\t\t\t\t/* Expand the cell to cover as many columns as needed */\n\t\t\t\t\t\twhile ( aoLocal[i][j+iColspan] !== undefined &&\n\t\t\t\t\t\t        aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t/* Must update the applied array over the rows for the columns */\n\t\t\t\t\t\t\tfor ( k=0 ; k<iRowspan ; k++ )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\taApplied[i+k][j+iColspan] = 1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tiColspan++;\n\t\t\t\t\t\t}\n\t\t\n\t\t\t\t\t\t/* Do the actual expansion in the DOM */\n\t\t\t\t\t\taoLocal[i][j].cell.rowSpan = iRowspan;\n\t\t\t\t\t\taoLocal[i][j].cell.colSpan = iColspan;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Insert the required TR nodes into the table for display\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnDraw( oSettings )\n\t\t{\n\t\t\t/* Provide a pre-callback function which can be used to cancel the draw is false is returned */\n\t\t\tvar aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] );\n\t\t\tif ( $.inArray( false, aPreDraw ) !== -1 )\n\t\t\t{\n\t\t\t\t_fnProcessingDisplay( oSettings, false );\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\tvar i, iLen, n;\n\t\t\tvar anRows = [];\n\t\t\tvar iRowCount = 0;\n\t\t\tvar iStripes = oSettings.asStripeClasses.length;\n\t\t\tvar iOpenRows = oSettings.aoOpenRows.length;\n\t\t\t\n\t\t\toSettings.bDrawing = true;\n\t\t\t\n\t\t\t/* Check and see if we have an initial draw position from state saving */\n\t\t\tif ( oSettings.iInitDisplayStart !== undefined && oSettings.iInitDisplayStart != -1 )\n\t\t\t{\n\t\t\t\tif ( oSettings.oFeatures.bServerSide )\n\t\t\t\t{\n\t\t\t\t\toSettings._iDisplayStart = oSettings.iInitDisplayStart;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\toSettings._iDisplayStart = (oSettings.iInitDisplayStart >= oSettings.fnRecordsDisplay()) ?\n\t\t\t\t\t\t0 : oSettings.iInitDisplayStart;\n\t\t\t\t}\n\t\t\t\toSettings.iInitDisplayStart = -1;\n\t\t\t\t_fnCalculateEnd( oSettings );\n\t\t\t}\n\t\t\t\n\t\t\t/* Server-side processing draw intercept */\n\t\t\tif ( oSettings.bDeferLoading )\n\t\t\t{\n\t\t\t\toSettings.bDeferLoading = false;\n\t\t\t\toSettings.iDraw++;\n\t\t\t}\n\t\t\telse if ( !oSettings.oFeatures.bServerSide )\n\t\t\t{\n\t\t\t\toSettings.iDraw++;\n\t\t\t}\n\t\t\telse if ( !oSettings.bDestroying && !_fnAjaxUpdate( oSettings ) )\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\tif ( oSettings.aiDisplay.length !== 0 )\n\t\t\t{\n\t\t\t\tvar iStart = oSettings._iDisplayStart;\n\t\t\t\tvar iEnd = oSettings._iDisplayEnd;\n\t\t\t\t\n\t\t\t\tif ( oSettings.oFeatures.bServerSide )\n\t\t\t\t{\n\t\t\t\t\tiStart = 0;\n\t\t\t\t\tiEnd = oSettings.aoData.length;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tfor ( var j=iStart ; j<iEnd ; j++ )\n\t\t\t\t{\n\t\t\t\t\tvar aoData = oSettings.aoData[ oSettings.aiDisplay[j] ];\n\t\t\t\t\tif ( aoData.nTr === null )\n\t\t\t\t\t{\n\t\t\t\t\t\t_fnCreateTr( oSettings, oSettings.aiDisplay[j] );\n\t\t\t\t\t}\n\t\t\n\t\t\t\t\tvar nRow = aoData.nTr;\n\t\t\t\t\t\n\t\t\t\t\t/* Remove the old striping classes and then add the new one */\n\t\t\t\t\tif ( iStripes !== 0 )\n\t\t\t\t\t{\n\t\t\t\t\t\tvar sStripe = oSettings.asStripeClasses[ iRowCount % iStripes ];\n\t\t\t\t\t\tif ( aoData._sRowStripe != sStripe )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe );\n\t\t\t\t\t\t\taoData._sRowStripe = sStripe;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t/* Row callback functions - might want to manipulate the row */\n\t\t\t\t\t_fnCallbackFire( oSettings, 'aoRowCallback', null, \n\t\t\t\t\t\t[nRow, oSettings.aoData[ oSettings.aiDisplay[j] ]._aData, iRowCount, j] );\n\t\t\t\t\t\n\t\t\t\t\tanRows.push( nRow );\n\t\t\t\t\tiRowCount++;\n\t\t\t\t\t\n\t\t\t\t\t/* If there is an open row - and it is attached to this parent - attach it on redraw */\n\t\t\t\t\tif ( iOpenRows !== 0 )\n\t\t\t\t\t{\n\t\t\t\t\t\tfor ( var k=0 ; k<iOpenRows ; k++ )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif ( nRow == oSettings.aoOpenRows[k].nParent )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tanRows.push( oSettings.aoOpenRows[k].nTr );\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\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t/* Table is empty - create a row with an empty message in it */\n\t\t\t\tanRows[ 0 ] = document.createElement( 'tr' );\n\t\t\t\t\n\t\t\t\tif ( oSettings.asStripeClasses[0] )\n\t\t\t\t{\n\t\t\t\t\tanRows[ 0 ].className = oSettings.asStripeClasses[0];\n\t\t\t\t}\n\t\t\n\t\t\t\tvar oLang = oSettings.oLanguage;\n\t\t\t\tvar sZero = oLang.sZeroRecords;\n\t\t\t\tif ( oSettings.iDraw == 1 && oSettings.sAjaxSource !== null && !oSettings.oFeatures.bServerSide )\n\t\t\t\t{\n\t\t\t\t\tsZero = oLang.sLoadingRecords;\n\t\t\t\t}\n\t\t\t\telse if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 )\n\t\t\t\t{\n\t\t\t\t\tsZero = oLang.sEmptyTable;\n\t\t\t\t}\n\t\t\n\t\t\t\tvar nTd = document.createElement( 'td' );\n\t\t\t\tnTd.setAttribute( 'valign', \"top\" );\n\t\t\t\tnTd.colSpan = _fnVisbleColumns( oSettings );\n\t\t\t\tnTd.className = oSettings.oClasses.sRowEmpty;\n\t\t\t\tnTd.innerHTML = _fnInfoMacros( oSettings, sZero );\n\t\t\t\t\n\t\t\t\tanRows[ iRowCount ].appendChild( nTd );\n\t\t\t}\n\t\t\t\n\t\t\t/* Header and footer callbacks */\n\t\t\t_fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0], \n\t\t\t\t_fnGetDataMaster( oSettings ), oSettings._iDisplayStart, oSettings.fnDisplayEnd(), oSettings.aiDisplay ] );\n\t\t\t\n\t\t\t_fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0], \n\t\t\t\t_fnGetDataMaster( oSettings ), oSettings._iDisplayStart, oSettings.fnDisplayEnd(), oSettings.aiDisplay ] );\n\t\t\t\n\t\t\t/* \n\t\t\t * Need to remove any old row from the display - note we can't just empty the tbody using\n\t\t\t * $().html('') since this will unbind the jQuery event handlers (even although the node \n\t\t\t * still exists!) - equally we can't use innerHTML, since IE throws an exception.\n\t\t\t */\n\t\t\tvar\n\t\t\t\tnAddFrag = document.createDocumentFragment(),\n\t\t\t\tnRemoveFrag = document.createDocumentFragment(),\n\t\t\t\tnBodyPar, nTrs;\n\t\t\t\n\t\t\tif ( oSettings.nTBody )\n\t\t\t{\n\t\t\t\tnBodyPar = oSettings.nTBody.parentNode;\n\t\t\t\tnRemoveFrag.appendChild( oSettings.nTBody );\n\t\t\t\t\n\t\t\t\t/* When doing infinite scrolling, only remove child rows when sorting, filtering or start\n\t\t\t\t * up. When not infinite scroll, always do it.\n\t\t\t\t */\n\t\t\t\tif ( !oSettings.oScroll.bInfinite || !oSettings._bInitComplete ||\n\t\t\t\t \toSettings.bSorted || oSettings.bFiltered )\n\t\t\t\t{\n\t\t\t\t\twhile( (n = oSettings.nTBody.firstChild) )\n\t\t\t\t\t{\n\t\t\t\t\t\toSettings.nTBody.removeChild( n );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t/* Put the draw table into the dom */\n\t\t\t\tfor ( i=0, iLen=anRows.length ; i<iLen ; i++ )\n\t\t\t\t{\n\t\t\t\t\tnAddFrag.appendChild( anRows[i] );\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\toSettings.nTBody.appendChild( nAddFrag );\n\t\t\t\tif ( nBodyPar !== null )\n\t\t\t\t{\n\t\t\t\t\tnBodyPar.appendChild( oSettings.nTBody );\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t/* Call all required callback functions for the end of a draw */\n\t\t\t_fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] );\n\t\t\t\n\t\t\t/* Draw is complete, sorting and filtering must be as well */\n\t\t\toSettings.bSorted = false;\n\t\t\toSettings.bFiltered = false;\n\t\t\toSettings.bDrawing = false;\n\t\t\t\n\t\t\tif ( oSettings.oFeatures.bServerSide )\n\t\t\t{\n\t\t\t\t_fnProcessingDisplay( oSettings, false );\n\t\t\t\tif ( !oSettings._bInitComplete )\n\t\t\t\t{\n\t\t\t\t\t_fnInitComplete( oSettings );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Redraw the table - taking account of the various features which are enabled\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnReDraw( oSettings )\n\t\t{\n\t\t\tif ( oSettings.oFeatures.bSort )\n\t\t\t{\n\t\t\t\t/* Sorting will refilter and draw for us */\n\t\t\t\t_fnSort( oSettings, oSettings.oPreviousSearch );\n\t\t\t}\n\t\t\telse if ( oSettings.oFeatures.bFilter )\n\t\t\t{\n\t\t\t\t/* Filtering will redraw for us */\n\t\t\t\t_fnFilterComplete( oSettings, oSettings.oPreviousSearch );\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_fnCalculateEnd( oSettings );\n\t\t\t\t_fnDraw( oSettings );\n\t\t\t}\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Add the options to the page HTML for the table\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnAddOptionsHtml ( oSettings )\n\t\t{\n\t\t\t/*\n\t\t\t * Create a temporary, empty, div which we can later on replace with what we have generated\n\t\t\t * we do it this way to rendering the 'options' html offline - speed :-)\n\t\t\t */\n\t\t\tvar nHolding = $('<div></div>')[0];\n\t\t\toSettings.nTable.parentNode.insertBefore( nHolding, oSettings.nTable );\n\t\t\t\n\t\t\t/* \n\t\t\t * All DataTables are wrapped in a div\n\t\t\t */\n\t\t\toSettings.nTableWrapper = $('<div id=\"'+oSettings.sTableId+'_wrapper\" class=\"'+oSettings.oClasses.sWrapper+'\" role=\"grid\"></div>')[0];\n\t\t\toSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;\n\t\t\n\t\t\t/* Track where we want to insert the option */\n\t\t\tvar nInsertNode = oSettings.nTableWrapper;\n\t\t\t\n\t\t\t/* Loop over the user set positioning and place the elements as needed */\n\t\t\tvar aDom = oSettings.sDom.split('');\n\t\t\tvar nTmp, iPushFeature, cOption, nNewNode, cNext, sAttr, j;\n\t\t\tfor ( var i=0 ; i<aDom.length ; i++ )\n\t\t\t{\n\t\t\t\tiPushFeature = 0;\n\t\t\t\tcOption = aDom[i];\n\t\t\t\t\n\t\t\t\tif ( cOption == '<' )\n\t\t\t\t{\n\t\t\t\t\t/* New container div */\n\t\t\t\t\tnNewNode = $('<div></div>')[0];\n\t\t\t\t\t\n\t\t\t\t\t/* Check to see if we should append an id and/or a class name to the container */\n\t\t\t\t\tcNext = aDom[i+1];\n\t\t\t\t\tif ( cNext == \"'\" || cNext == '\"' )\n\t\t\t\t\t{\n\t\t\t\t\t\tsAttr = \"\";\n\t\t\t\t\t\tj = 2;\n\t\t\t\t\t\twhile ( aDom[i+j] != cNext )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsAttr += aDom[i+j];\n\t\t\t\t\t\t\tj++;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\t/* Replace jQuery UI constants */\n\t\t\t\t\t\tif ( sAttr == \"H\" )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsAttr = oSettings.oClasses.sJUIHeader;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if ( sAttr == \"F\" )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsAttr = oSettings.oClasses.sJUIFooter;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\t/* The attribute can be in the format of \"#id.class\", \"#id\" or \"class\" This logic\n\t\t\t\t\t\t * breaks the string into parts and applies them as needed\n\t\t\t\t\t\t */\n\t\t\t\t\t\tif ( sAttr.indexOf('.') != -1 )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvar aSplit = sAttr.split('.');\n\t\t\t\t\t\t\tnNewNode.id = aSplit[0].substr(1, aSplit[0].length-1);\n\t\t\t\t\t\t\tnNewNode.className = aSplit[1];\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if ( sAttr.charAt(0) == \"#\" )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tnNewNode.id = sAttr.substr(1, sAttr.length-1);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tnNewNode.className = sAttr;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\ti += j; /* Move along the position array */\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tnInsertNode.appendChild( nNewNode );\n\t\t\t\t\tnInsertNode = nNewNode;\n\t\t\t\t}\n\t\t\t\telse if ( cOption == '>' )\n\t\t\t\t{\n\t\t\t\t\t/* End container div */\n\t\t\t\t\tnInsertNode = nInsertNode.parentNode;\n\t\t\t\t}\n\t\t\t\telse if ( cOption == 'l' && oSettings.oFeatures.bPaginate && oSettings.oFeatures.bLengthChange )\n\t\t\t\t{\n\t\t\t\t\t/* Length */\n\t\t\t\t\tnTmp = _fnFeatureHtmlLength( oSettings );\n\t\t\t\t\tiPushFeature = 1;\n\t\t\t\t}\n\t\t\t\telse if ( cOption == 'f' && oSettings.oFeatures.bFilter )\n\t\t\t\t{\n\t\t\t\t\t/* Filter */\n\t\t\t\t\tnTmp = _fnFeatureHtmlFilter( oSettings );\n\t\t\t\t\tiPushFeature = 1;\n\t\t\t\t}\n\t\t\t\telse if ( cOption == 'r' && oSettings.oFeatures.bProcessing )\n\t\t\t\t{\n\t\t\t\t\t/* pRocessing */\n\t\t\t\t\tnTmp = _fnFeatureHtmlProcessing( oSettings );\n\t\t\t\t\tiPushFeature = 1;\n\t\t\t\t}\n\t\t\t\telse if ( cOption == 't' )\n\t\t\t\t{\n\t\t\t\t\t/* Table */\n\t\t\t\t\tnTmp = _fnFeatureHtmlTable( oSettings );\n\t\t\t\t\tiPushFeature = 1;\n\t\t\t\t}\n\t\t\t\telse if ( cOption ==  'i' && oSettings.oFeatures.bInfo )\n\t\t\t\t{\n\t\t\t\t\t/* Info */\n\t\t\t\t\tnTmp = _fnFeatureHtmlInfo( oSettings );\n\t\t\t\t\tiPushFeature = 1;\n\t\t\t\t}\n\t\t\t\telse if ( cOption == 'p' && oSettings.oFeatures.bPaginate )\n\t\t\t\t{\n\t\t\t\t\t/* Pagination */\n\t\t\t\t\tnTmp = _fnFeatureHtmlPaginate( oSettings );\n\t\t\t\t\tiPushFeature = 1;\n\t\t\t\t}\n\t\t\t\telse if ( DataTable.ext.aoFeatures.length !== 0 )\n\t\t\t\t{\n\t\t\t\t\t/* Plug-in features */\n\t\t\t\t\tvar aoFeatures = DataTable.ext.aoFeatures;\n\t\t\t\t\tfor ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ )\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( cOption == aoFeatures[k].cFeature )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tnTmp = aoFeatures[k].fnInit( oSettings );\n\t\t\t\t\t\t\tif ( nTmp )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tiPushFeature = 1;\n\t\t\t\t\t\t\t}\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\t\n\t\t\t\t/* Add to the 2D features array */\n\t\t\t\tif ( iPushFeature == 1 && nTmp !== null )\n\t\t\t\t{\n\t\t\t\t\tif ( typeof oSettings.aanFeatures[cOption] !== 'object' )\n\t\t\t\t\t{\n\t\t\t\t\t\toSettings.aanFeatures[cOption] = [];\n\t\t\t\t\t}\n\t\t\t\t\toSettings.aanFeatures[cOption].push( nTmp );\n\t\t\t\t\tnInsertNode.appendChild( nTmp );\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t/* Built our DOM structure - replace the holding div with what we want */\n\t\t\tnHolding.parentNode.replaceChild( oSettings.nTableWrapper, nHolding );\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Use the DOM source to create up an array of header cells. The idea here is to\n\t\t * create a layout grid (array) of rows x columns, which contains a reference\n\t\t * to the cell that that point in the grid (regardless of col/rowspan), such that\n\t\t * any column / row could be removed and the new grid constructed\n\t\t *  @param array {object} aLayout Array to store the calculated layout in\n\t\t *  @param {node} nThead The header/footer element for the table\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnDetectHeader ( aLayout, nThead )\n\t\t{\n\t\t\tvar nTrs = $(nThead).children('tr');\n\t\t\tvar nTr, nCell;\n\t\t\tvar i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan;\n\t\t\tvar bUnique;\n\t\t\tvar fnShiftCol = function ( a, i, j ) {\n\t\t\t\tvar k = a[i];\n\t\t                while ( k[j] ) {\n\t\t\t\t\tj++;\n\t\t\t\t}\n\t\t\t\treturn j;\n\t\t\t};\n\t\t\n\t\t\taLayout.splice( 0, aLayout.length );\n\t\t\t\n\t\t\t/* We know how many rows there are in the layout - so prep it */\n\t\t\tfor ( i=0, iLen=nTrs.length ; i<iLen ; i++ )\n\t\t\t{\n\t\t\t\taLayout.push( [] );\n\t\t\t}\n\t\t\t\n\t\t\t/* Calculate a layout array */\n\t\t\tfor ( i=0, iLen=nTrs.length ; i<iLen ; i++ )\n\t\t\t{\n\t\t\t\tnTr = nTrs[i];\n\t\t\t\tiColumn = 0;\n\t\t\t\t\n\t\t\t\t/* For every cell in the row... */\n\t\t\t\tnCell = nTr.firstChild;\n\t\t\t\twhile ( nCell ) {\n\t\t\t\t\tif ( nCell.nodeName.toUpperCase() == \"TD\" ||\n\t\t\t\t\t     nCell.nodeName.toUpperCase() == \"TH\" )\n\t\t\t\t\t{\n\t\t\t\t\t\t/* Get the col and rowspan attributes from the DOM and sanitise them */\n\t\t\t\t\t\tiColspan = nCell.getAttribute('colspan') * 1;\n\t\t\t\t\t\tiRowspan = nCell.getAttribute('rowspan') * 1;\n\t\t\t\t\t\tiColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan;\n\t\t\t\t\t\tiRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan;\n\t\t\n\t\t\t\t\t\t/* There might be colspan cells already in this row, so shift our target \n\t\t\t\t\t\t * accordingly\n\t\t\t\t\t\t */\n\t\t\t\t\t\tiColShifted = fnShiftCol( aLayout, i, iColumn );\n\t\t\t\t\t\t\n\t\t\t\t\t\t/* Cache calculation for unique columns */\n\t\t\t\t\t\tbUnique = iColspan === 1 ? true : false;\n\t\t\t\t\t\t\n\t\t\t\t\t\t/* If there is col / rowspan, copy the information into the layout grid */\n\t\t\t\t\t\tfor ( l=0 ; l<iColspan ; l++ )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfor ( k=0 ; k<iRowspan ; k++ )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\taLayout[i+k][iColShifted+l] = {\n\t\t\t\t\t\t\t\t\t\"cell\": nCell,\n\t\t\t\t\t\t\t\t\t\"unique\": bUnique\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\taLayout[i+k].nTr = nTr;\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\tnCell = nCell.nextSibling;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Get an array of unique th elements, one for each column\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @param {node} nHeader automatically detect the layout from this node - optional\n\t\t *  @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional\n\t\t *  @returns array {node} aReturn list of unique th's\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnGetUniqueThs ( oSettings, nHeader, aLayout )\n\t\t{\n\t\t\tvar aReturn = [];\n\t\t\tif ( !aLayout )\n\t\t\t{\n\t\t\t\taLayout = oSettings.aoHeader;\n\t\t\t\tif ( nHeader )\n\t\t\t\t{\n\t\t\t\t\taLayout = [];\n\t\t\t\t\t_fnDetectHeader( aLayout, nHeader );\n\t\t\t\t}\n\t\t\t}\n\t\t\n\t\t\tfor ( var i=0, iLen=aLayout.length ; i<iLen ; i++ )\n\t\t\t{\n\t\t\t\tfor ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ )\n\t\t\t\t{\n\t\t\t\t\tif ( aLayout[i][j].unique && \n\t\t\t\t\t\t (!aReturn[j] || !oSettings.bSortCellsTop) )\n\t\t\t\t\t{\n\t\t\t\t\t\taReturn[j] = aLayout[i][j].cell;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\treturn aReturn;\n\t\t}\n\t\t\n\t\t\n\t\t\n\t\t/**\n\t\t * Update the table using an Ajax call\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @returns {boolean} Block the table drawing or not\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnAjaxUpdate( oSettings )\n\t\t{\n\t\t\tif ( oSettings.bAjaxDataGet )\n\t\t\t{\n\t\t\t\toSettings.iDraw++;\n\t\t\t\t_fnProcessingDisplay( oSettings, true );\n\t\t\t\tvar iColumns = oSettings.aoColumns.length;\n\t\t\t\tvar aoData = _fnAjaxParameters( oSettings );\n\t\t\t\t_fnServerParams( oSettings, aoData );\n\t\t\t\t\n\t\t\t\toSettings.fnServerData.call( oSettings.oInstance, oSettings.sAjaxSource, aoData,\n\t\t\t\t\tfunction(json) {\n\t\t\t\t\t\t_fnAjaxUpdateDraw( oSettings, json );\n\t\t\t\t\t}, oSettings );\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Build up the parameters in an object needed for a server-side processing request\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @returns {bool} block the table drawing or not\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnAjaxParameters( oSettings )\n\t\t{\n\t\t\tvar iColumns = oSettings.aoColumns.length;\n\t\t\tvar aoData = [], mDataProp, aaSort, aDataSort;\n\t\t\tvar i, j;\n\t\t\t\n\t\t\taoData.push( { \"name\": \"sEcho\",          \"value\": oSettings.iDraw } );\n\t\t\taoData.push( { \"name\": \"iColumns\",       \"value\": iColumns } );\n\t\t\taoData.push( { \"name\": \"sColumns\",       \"value\": _fnColumnOrdering(oSettings) } );\n\t\t\taoData.push( { \"name\": \"iDisplayStart\",  \"value\": oSettings._iDisplayStart } );\n\t\t\taoData.push( { \"name\": \"iDisplayLength\", \"value\": oSettings.oFeatures.bPaginate !== false ?\n\t\t\t\toSettings._iDisplayLength : -1 } );\n\t\t\t\t\n\t\t\tfor ( i=0 ; i<iColumns ; i++ )\n\t\t\t{\n\t\t\t  mDataProp = oSettings.aoColumns[i].mData;\n\t\t\t\taoData.push( { \"name\": \"mDataProp_\"+i, \"value\": typeof(mDataProp)===\"function\" ? 'function' : mDataProp } );\n\t\t\t}\n\t\t\t\n\t\t\t/* Filtering */\n\t\t\tif ( oSettings.oFeatures.bFilter !== false )\n\t\t\t{\n\t\t\t\taoData.push( { \"name\": \"sSearch\", \"value\": oSettings.oPreviousSearch.sSearch } );\n\t\t\t\taoData.push( { \"name\": \"bRegex\",  \"value\": oSettings.oPreviousSearch.bRegex } );\n\t\t\t\tfor ( i=0 ; i<iColumns ; i++ )\n\t\t\t\t{\n\t\t\t\t\taoData.push( { \"name\": \"sSearch_\"+i,     \"value\": oSettings.aoPreSearchCols[i].sSearch } );\n\t\t\t\t\taoData.push( { \"name\": \"bRegex_\"+i,      \"value\": oSettings.aoPreSearchCols[i].bRegex } );\n\t\t\t\t\taoData.push( { \"name\": \"bSearchable_\"+i, \"value\": oSettings.aoColumns[i].bSearchable } );\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t/* Sorting */\n\t\t\tif ( oSettings.oFeatures.bSort !== false )\n\t\t\t{\n\t\t\t\tvar iCounter = 0;\n\t\t\n\t\t\t\taaSort = ( oSettings.aaSortingFixed !== null ) ?\n\t\t\t\t\toSettings.aaSortingFixed.concat( oSettings.aaSorting ) :\n\t\t\t\t\toSettings.aaSorting.slice();\n\t\t\t\t\n\t\t\t\tfor ( i=0 ; i<aaSort.length ; i++ )\n\t\t\t\t{\n\t\t\t\t\taDataSort = oSettings.aoColumns[ aaSort[i][0] ].aDataSort;\n\t\t\t\t\t\n\t\t\t\t\tfor ( j=0 ; j<aDataSort.length ; j++ )\n\t\t\t\t\t{\n\t\t\t\t\t\taoData.push( { \"name\": \"iSortCol_\"+iCounter,  \"value\": aDataSort[j] } );\n\t\t\t\t\t\taoData.push( { \"name\": \"sSortDir_\"+iCounter,  \"value\": aaSort[i][1] } );\n\t\t\t\t\t\tiCounter++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\taoData.push( { \"name\": \"iSortingCols\",   \"value\": iCounter } );\n\t\t\t\t\n\t\t\t\tfor ( i=0 ; i<iColumns ; i++ )\n\t\t\t\t{\n\t\t\t\t\taoData.push( { \"name\": \"bSortable_\"+i,  \"value\": oSettings.aoColumns[i].bSortable } );\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\treturn aoData;\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Add Ajax parameters from plug-ins\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @param array {objects} aoData name/value pairs to send to the server\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnServerParams( oSettings, aoData )\n\t\t{\n\t\t\t_fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [aoData] );\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Data the data from the server (nuking the old) and redraw the table\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @param {object} json json data return from the server.\n\t\t *  @param {string} json.sEcho Tracking flag for DataTables to match requests\n\t\t *  @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering\n\t\t *  @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering\n\t\t *  @param {array} json.aaData The data to display on this page\n\t\t *  @param {string} [json.sColumns] Column ordering (sName, comma separated)\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnAjaxUpdateDraw ( oSettings, json )\n\t\t{\n\t\t\tif ( json.sEcho !== undefined )\n\t\t\t{\n\t\t\t\t/* Protect against old returns over-writing a new one. Possible when you get\n\t\t\t\t * very fast interaction, and later queries are completed much faster\n\t\t\t\t */\n\t\t\t\tif ( json.sEcho*1 < oSettings.iDraw )\n\t\t\t\t{\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\toSettings.iDraw = json.sEcho * 1;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif ( !oSettings.oScroll.bInfinite ||\n\t\t\t\t   (oSettings.oScroll.bInfinite && (oSettings.bSorted || oSettings.bFiltered)) )\n\t\t\t{\n\t\t\t\t_fnClearTable( oSettings );\n\t\t\t}\n\t\t\toSettings._iRecordsTotal = parseInt(json.iTotalRecords, 10);\n\t\t\toSettings._iRecordsDisplay = parseInt(json.iTotalDisplayRecords, 10);\n\t\t\t\n\t\t\t/* Determine if reordering is required */\n\t\t\tvar sOrdering = _fnColumnOrdering(oSettings);\n\t\t\tvar bReOrder = (json.sColumns !== undefined && sOrdering !== \"\" && json.sColumns != sOrdering );\n\t\t\tvar aiIndex;\n\t\t\tif ( bReOrder )\n\t\t\t{\n\t\t\t\taiIndex = _fnReOrderIndex( oSettings, json.sColumns );\n\t\t\t}\n\t\t\t\n\t\t\tvar aData = _fnGetObjectDataFn( oSettings.sAjaxDataProp )( json );\n\t\t\tfor ( var i=0, iLen=aData.length ; i<iLen ; i++ )\n\t\t\t{\n\t\t\t\tif ( bReOrder )\n\t\t\t\t{\n\t\t\t\t\t/* If we need to re-order, then create a new array with the correct order and add it */\n\t\t\t\t\tvar aDataSorted = [];\n\t\t\t\t\tfor ( var j=0, jLen=oSettings.aoColumns.length ; j<jLen ; j++ )\n\t\t\t\t\t{\n\t\t\t\t\t\taDataSorted.push( aData[i][ aiIndex[j] ] );\n\t\t\t\t\t}\n\t\t\t\t\t_fnAddData( oSettings, aDataSorted );\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t/* No re-order required, sever got it \"right\" - just straight add */\n\t\t\t\t\t_fnAddData( oSettings, aData[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t\toSettings.aiDisplay = oSettings.aiDisplayMaster.slice();\n\t\t\t\n\t\t\toSettings.bAjaxDataGet = false;\n\t\t\t_fnDraw( oSettings );\n\t\t\toSettings.bAjaxDataGet = true;\n\t\t\t_fnProcessingDisplay( oSettings, false );\n\t\t}\n\t\t\n\t\t\n\t\t\n\t\t/**\n\t\t * Generate the node required for filtering text\n\t\t *  @returns {node} Filter control element\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnFeatureHtmlFilter ( oSettings )\n\t\t{\n\t\t\tvar oPreviousSearch = oSettings.oPreviousSearch;\n\t\t\t\n\t\t\tvar sSearchStr = oSettings.oLanguage.sSearch;\n\t\t\tsSearchStr = (sSearchStr.indexOf('_INPUT_') !== -1) ?\n\t\t\t  sSearchStr.replace('_INPUT_', '<input type=\"text\" />') :\n\t\t\t  sSearchStr===\"\" ? '<input type=\"text\" />' : sSearchStr+' <input type=\"text\" />';\n\t\t\t\n\t\t\tvar nFilter = document.createElement( 'div' );\n\t\t\tnFilter.className = oSettings.oClasses.sFilter;\n\t\t\tnFilter.innerHTML = '<label>'+sSearchStr+'</label>';\n\t\t\tif ( !oSettings.aanFeatures.f )\n\t\t\t{\n\t\t\t\tnFilter.id = oSettings.sTableId+'_filter';\n\t\t\t}\n\t\t\t\n\t\t\tvar jqFilter = $('input[type=\"text\"]', nFilter);\n\t\t\n\t\t\t// Store a reference to the input element, so other input elements could be\n\t\t\t// added to the filter wrapper if needed (submit button for example)\n\t\t\tnFilter._DT_Input = jqFilter[0];\n\t\t\n\t\t\tjqFilter.val( oPreviousSearch.sSearch.replace('\"','&quot;') );\n\t\t\tjqFilter.bind( 'keyup.DT', function(e) {\n\t\t\t\t/* Update all other filter input elements for the new display */\n\t\t\t\tvar n = oSettings.aanFeatures.f;\n\t\t\t\tvar val = this.value===\"\" ? \"\" : this.value; // mental IE8 fix :-(\n\t\t\n\t\t\t\tfor ( var i=0, iLen=n.length ; i<iLen ; i++ )\n\t\t\t\t{\n\t\t\t\t\tif ( n[i] != $(this).parents('div.dataTables_filter')[0] )\n\t\t\t\t\t{\n\t\t\t\t\t\t$(n[i]._DT_Input).val( val );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t/* Now do the filter */\n\t\t\t\tif ( val != oPreviousSearch.sSearch )\n\t\t\t\t{\n\t\t\t\t\t_fnFilterComplete( oSettings, { \n\t\t\t\t\t\t\"sSearch\": val, \n\t\t\t\t\t\t\"bRegex\": oPreviousSearch.bRegex,\n\t\t\t\t\t\t\"bSmart\": oPreviousSearch.bSmart ,\n\t\t\t\t\t\t\"bCaseInsensitive\": oPreviousSearch.bCaseInsensitive \n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t} );\n\t\t\n\t\t\tjqFilter\n\t\t\t\t.attr('aria-controls', oSettings.sTableId)\n\t\t\t\t.bind( 'keypress.DT', function(e) {\n\t\t\t\t\t/* Prevent form submission */\n\t\t\t\t\tif ( e.keyCode == 13 )\n\t\t\t\t\t{\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\t\n\t\t\treturn nFilter;\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Filter the table using both the global filter and column based filtering\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @param {object} oSearch search information\n\t\t *  @param {int} [iForce] force a research of the master array (1) or not (undefined or 0)\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnFilterComplete ( oSettings, oInput, iForce )\n\t\t{\n\t\t\tvar oPrevSearch = oSettings.oPreviousSearch;\n\t\t\tvar aoPrevSearch = oSettings.aoPreSearchCols;\n\t\t\tvar fnSaveFilter = function ( oFilter ) {\n\t\t\t\t/* Save the filtering values */\n\t\t\t\toPrevSearch.sSearch = oFilter.sSearch;\n\t\t\t\toPrevSearch.bRegex = oFilter.bRegex;\n\t\t\t\toPrevSearch.bSmart = oFilter.bSmart;\n\t\t\t\toPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive;\n\t\t\t};\n\t\t\n\t\t\t/* In server-side processing all filtering is done by the server, so no point hanging around here */\n\t\t\tif ( !oSettings.oFeatures.bServerSide )\n\t\t\t{\n\t\t\t\t/* Global filter */\n\t\t\t\t_fnFilter( oSettings, oInput.sSearch, iForce, oInput.bRegex, oInput.bSmart, oInput.bCaseInsensitive );\n\t\t\t\tfnSaveFilter( oInput );\n\t\t\n\t\t\t\t/* Now do the individual column filter */\n\t\t\t\tfor ( var i=0 ; i<oSettings.aoPreSearchCols.length ; i++ )\n\t\t\t\t{\n\t\t\t\t\t_fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, aoPrevSearch[i].bRegex, \n\t\t\t\t\t\taoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive );\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t/* Custom filtering */\n\t\t\t\t_fnFilterCustom( oSettings );\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tfnSaveFilter( oInput );\n\t\t\t}\n\t\t\t\n\t\t\t/* Tell the draw function we have been filtering */\n\t\t\toSettings.bFiltered = true;\n\t\t\t$(oSettings.oInstance).trigger('filter', oSettings);\n\t\t\t\n\t\t\t/* Redraw the table */\n\t\t\toSettings._iDisplayStart = 0;\n\t\t\t_fnCalculateEnd( oSettings );\n\t\t\t_fnDraw( oSettings );\n\t\t\t\n\t\t\t/* Rebuild search array 'offline' */\n\t\t\t_fnBuildSearchArray( oSettings, 0 );\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Apply custom filtering functions\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnFilterCustom( oSettings )\n\t\t{\n\t\t\tvar afnFilters = DataTable.ext.afnFiltering;\n\t\t\tvar aiFilterColumns = _fnGetColumns( oSettings, 'bSearchable' );\n\t\t\n\t\t\tfor ( var i=0, iLen=afnFilters.length ; i<iLen ; i++ )\n\t\t\t{\n\t\t\t\tvar iCorrector = 0;\n\t\t\t\tfor ( var j=0, jLen=oSettings.aiDisplay.length ; j<jLen ; j++ )\n\t\t\t\t{\n\t\t\t\t\tvar iDisIndex = oSettings.aiDisplay[j-iCorrector];\n\t\t\t\t\tvar bTest = afnFilters[i](\n\t\t\t\t\t\toSettings,\n\t\t\t\t\t\t_fnGetRowData( oSettings, iDisIndex, 'filter', aiFilterColumns ),\n\t\t\t\t\t\tiDisIndex\n\t\t\t\t\t);\n\t\t\t\t\t\n\t\t\t\t\t/* Check if we should use this row based on the filtering function */\n\t\t\t\t\tif ( !bTest )\n\t\t\t\t\t{\n\t\t\t\t\t\toSettings.aiDisplay.splice( j-iCorrector, 1 );\n\t\t\t\t\t\tiCorrector++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Filter the table on a per-column basis\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @param {string} sInput string to filter on\n\t\t *  @param {int} iColumn column to filter\n\t\t *  @param {bool} bRegex treat search string as a regular expression or not\n\t\t *  @param {bool} bSmart use smart filtering or not\n\t\t *  @param {bool} bCaseInsensitive Do case insenstive matching or not\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnFilterColumn ( oSettings, sInput, iColumn, bRegex, bSmart, bCaseInsensitive )\n\t\t{\n\t\t\tif ( sInput === \"\" )\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\tvar iIndexCorrector = 0;\n\t\t\tvar rpSearch = _fnFilterCreateSearch( sInput, bRegex, bSmart, bCaseInsensitive );\n\t\t\t\n\t\t\tfor ( var i=oSettings.aiDisplay.length-1 ; i>=0 ; i-- )\n\t\t\t{\n\t\t\t\tvar sData = _fnDataToSearch( _fnGetCellData( oSettings, oSettings.aiDisplay[i], iColumn, 'filter' ),\n\t\t\t\t\toSettings.aoColumns[iColumn].sType );\n\t\t\t\tif ( ! rpSearch.test( sData ) )\n\t\t\t\t{\n\t\t\t\t\toSettings.aiDisplay.splice( i, 1 );\n\t\t\t\t\tiIndexCorrector++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Filter the data table based on user input and draw the table\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @param {string} sInput string to filter on\n\t\t *  @param {int} iForce optional - force a research of the master array (1) or not (undefined or 0)\n\t\t *  @param {bool} bRegex treat as a regular expression or not\n\t\t *  @param {bool} bSmart perform smart filtering or not\n\t\t *  @param {bool} bCaseInsensitive Do case insenstive matching or not\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnFilter( oSettings, sInput, iForce, bRegex, bSmart, bCaseInsensitive )\n\t\t{\n\t\t\tvar i;\n\t\t\tvar rpSearch = _fnFilterCreateSearch( sInput, bRegex, bSmart, bCaseInsensitive );\n\t\t\tvar oPrevSearch = oSettings.oPreviousSearch;\n\t\t\t\n\t\t\t/* Check if we are forcing or not - optional parameter */\n\t\t\tif ( !iForce )\n\t\t\t{\n\t\t\t\tiForce = 0;\n\t\t\t}\n\t\t\t\n\t\t\t/* Need to take account of custom filtering functions - always filter */\n\t\t\tif ( DataTable.ext.afnFiltering.length !== 0 )\n\t\t\t{\n\t\t\t\tiForce = 1;\n\t\t\t}\n\t\t\t\n\t\t\t/*\n\t\t\t * If the input is blank - we want the full data set\n\t\t\t */\n\t\t\tif ( sInput.length <= 0 )\n\t\t\t{\n\t\t\t\toSettings.aiDisplay.splice( 0, oSettings.aiDisplay.length);\n\t\t\t\toSettings.aiDisplay = oSettings.aiDisplayMaster.slice();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t/*\n\t\t\t\t * We are starting a new search or the new search string is smaller \n\t\t\t\t * then the old one (i.e. delete). Search from the master array\n\t\t\t \t */\n\t\t\t\tif ( oSettings.aiDisplay.length == oSettings.aiDisplayMaster.length ||\n\t\t\t\t\t   oPrevSearch.sSearch.length > sInput.length || iForce == 1 ||\n\t\t\t\t\t   sInput.indexOf(oPrevSearch.sSearch) !== 0 )\n\t\t\t\t{\n\t\t\t\t\t/* Nuke the old display array - we are going to rebuild it */\n\t\t\t\t\toSettings.aiDisplay.splice( 0, oSettings.aiDisplay.length);\n\t\t\t\t\t\n\t\t\t\t\t/* Force a rebuild of the search array */\n\t\t\t\t\t_fnBuildSearchArray( oSettings, 1 );\n\t\t\t\t\t\n\t\t\t\t\t/* Search through all records to populate the search array\n\t\t\t\t\t * The the oSettings.aiDisplayMaster and asDataSearch arrays have 1 to 1 \n\t\t\t\t\t * mapping\n\t\t\t\t\t */\n\t\t\t\t\tfor ( i=0 ; i<oSettings.aiDisplayMaster.length ; i++ )\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( rpSearch.test(oSettings.asDataSearch[i]) )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\toSettings.aiDisplay.push( oSettings.aiDisplayMaster[i] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t  }\n\t\t\t  else\n\t\t\t\t{\n\t\t\t  \t/* Using old search array - refine it - do it this way for speed\n\t\t\t  \t * Don't have to search the whole master array again\n\t\t\t\t\t */\n\t\t\t  \tvar iIndexCorrector = 0;\n\t\t\t  \t\n\t\t\t  \t/* Search the current results */\n\t\t\t  \tfor ( i=0 ; i<oSettings.asDataSearch.length ; i++ )\n\t\t\t\t\t{\n\t\t\t  \t\tif ( ! rpSearch.test(oSettings.asDataSearch[i]) )\n\t\t\t\t\t\t{\n\t\t\t  \t\t\toSettings.aiDisplay.splice( i-iIndexCorrector, 1 );\n\t\t\t  \t\t\tiIndexCorrector++;\n\t\t\t  \t\t}\n\t\t\t  \t}\n\t\t\t  }\n\t\t\t}\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Create an array which can be quickly search through\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @param {int} iMaster use the master data array - optional\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnBuildSearchArray ( oSettings, iMaster )\n\t\t{\n\t\t\tif ( !oSettings.oFeatures.bServerSide )\n\t\t\t{\n\t\t\t\t/* Clear out the old data */\n\t\t\t\toSettings.asDataSearch = [];\n\t\t\n\t\t\t\tvar aiFilterColumns = _fnGetColumns( oSettings, 'bSearchable' );\n\t\t\t\tvar aiIndex = (iMaster===1) ?\n\t\t\t\t \toSettings.aiDisplayMaster :\n\t\t\t\t \toSettings.aiDisplay;\n\t\t\t\t\n\t\t\t\tfor ( var i=0, iLen=aiIndex.length ; i<iLen ; i++ )\n\t\t\t\t{\n\t\t\t\t\toSettings.asDataSearch[i] = _fnBuildSearchRow(\n\t\t\t\t\t\toSettings,\n\t\t\t\t\t\t_fnGetRowData( oSettings, aiIndex[i], 'filter', aiFilterColumns )\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Create a searchable string from a single data row\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @param {array} aData Row data array to use for the data to search\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnBuildSearchRow( oSettings, aData )\n\t\t{\n\t\t\tvar sSearch = aData.join('  ');\n\t\t\t\n\t\t\t/* If it looks like there is an HTML entity in the string, attempt to decode it */\n\t\t\tif ( sSearch.indexOf('&') !== -1 )\n\t\t\t{\n\t\t\t\tsSearch = $('<div>').html(sSearch).text();\n\t\t\t}\n\t\t\t\n\t\t\t// Strip newline characters\n\t\t\treturn sSearch.replace( /[\\n\\r]/g, \" \" );\n\t\t}\n\t\t\n\t\t/**\n\t\t * Build a regular expression object suitable for searching a table\n\t\t *  @param {string} sSearch string to search for\n\t\t *  @param {bool} bRegex treat as a regular expression or not\n\t\t *  @param {bool} bSmart perform smart filtering or not\n\t\t *  @param {bool} bCaseInsensitive Do case insensitive matching or not\n\t\t *  @returns {RegExp} constructed object\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnFilterCreateSearch( sSearch, bRegex, bSmart, bCaseInsensitive )\n\t\t{\n\t\t\tvar asSearch, sRegExpString;\n\t\t\t\n\t\t\tif ( bSmart )\n\t\t\t{\n\t\t\t\t/* Generate the regular expression to use. Something along the lines of:\n\t\t\t\t * ^(?=.*?\\bone\\b)(?=.*?\\btwo\\b)(?=.*?\\bthree\\b).*$\n\t\t\t\t */\n\t\t\t\tasSearch = bRegex ? sSearch.split( ' ' ) : _fnEscapeRegex( sSearch ).split( ' ' );\n\t\t\t\tsRegExpString = '^(?=.*?'+asSearch.join( ')(?=.*?' )+').*$';\n\t\t\t\treturn new RegExp( sRegExpString, bCaseInsensitive ? \"i\" : \"\" );\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tsSearch = bRegex ? sSearch : _fnEscapeRegex( sSearch );\n\t\t\t\treturn new RegExp( sSearch, bCaseInsensitive ? \"i\" : \"\" );\n\t\t\t}\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Convert raw data into something that the user can search on\n\t\t *  @param {string} sData data to be modified\n\t\t *  @param {string} sType data type\n\t\t *  @returns {string} search string\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnDataToSearch ( sData, sType )\n\t\t{\n\t\t\tif ( typeof DataTable.ext.ofnSearch[sType] === \"function\" )\n\t\t\t{\n\t\t\t\treturn DataTable.ext.ofnSearch[sType]( sData );\n\t\t\t}\n\t\t\telse if ( sData === null )\n\t\t\t{\n\t\t\t\treturn '';\n\t\t\t}\n\t\t\telse if ( sType == \"html\" )\n\t\t\t{\n\t\t\t\treturn sData.replace(/[\\r\\n]/g,\" \").replace( /<.*?>/g, \"\" );\n\t\t\t}\n\t\t\telse if ( typeof sData === \"string\" )\n\t\t\t{\n\t\t\t\treturn sData.replace(/[\\r\\n]/g,\" \");\n\t\t\t}\n\t\t\treturn sData;\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * scape a string such that it can be used in a regular expression\n\t\t *  @param {string} sVal string to escape\n\t\t *  @returns {string} escaped string\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnEscapeRegex ( sVal )\n\t\t{\n\t\t\tvar acEscape = [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\\\', '$', '^', '-' ];\n\t\t\tvar reReplace = new RegExp( '(\\\\' + acEscape.join('|\\\\') + ')', 'g' );\n\t\t\treturn sVal.replace(reReplace, '\\\\$1');\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Generate the node required for the info display\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @returns {node} Information element\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnFeatureHtmlInfo ( oSettings )\n\t\t{\n\t\t\tvar nInfo = document.createElement( 'div' );\n\t\t\tnInfo.className = oSettings.oClasses.sInfo;\n\t\t\t\n\t\t\t/* Actions that are to be taken once only for this feature */\n\t\t\tif ( !oSettings.aanFeatures.i )\n\t\t\t{\n\t\t\t\t/* Add draw callback */\n\t\t\t\toSettings.aoDrawCallback.push( {\n\t\t\t\t\t\"fn\": _fnUpdateInfo,\n\t\t\t\t\t\"sName\": \"information\"\n\t\t\t\t} );\n\t\t\t\t\n\t\t\t\t/* Add id */\n\t\t\t\tnInfo.id = oSettings.sTableId+'_info';\n\t\t\t}\n\t\t\toSettings.nTable.setAttribute( 'aria-describedby', oSettings.sTableId+'_info' );\n\t\t\t\n\t\t\treturn nInfo;\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Update the information elements in the display\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnUpdateInfo ( oSettings )\n\t\t{\n\t\t\t/* Show information about the table */\n\t\t\tif ( !oSettings.oFeatures.bInfo || oSettings.aanFeatures.i.length === 0 )\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\tvar\n\t\t\t\toLang = oSettings.oLanguage,\n\t\t\t\tiStart = oSettings._iDisplayStart+1,\n\t\t\t\tiEnd = oSettings.fnDisplayEnd(),\n\t\t\t\tiMax = oSettings.fnRecordsTotal(),\n\t\t\t\tiTotal = oSettings.fnRecordsDisplay(),\n\t\t\t\tsOut;\n\t\t\t\n\t\t\tif ( iTotal === 0 )\n\t\t\t{\n\t\t\t\t/* Empty record set */\n\t\t\t\tsOut = oLang.sInfoEmpty;\n\t\t\t}\n\t\t\telse {\n\t\t\t\t/* Normal record set */\n\t\t\t\tsOut = oLang.sInfo;\n\t\t\t}\n\t\t\n\t\t\tif ( iTotal != iMax )\n\t\t\t{\n\t\t\t\t/* Record set after filtering */\n\t\t\t\tsOut += ' ' + oLang.sInfoFiltered;\n\t\t\t}\n\t\t\n\t\t\t// Convert the macros\n\t\t\tsOut += oLang.sInfoPostFix;\n\t\t\tsOut = _fnInfoMacros( oSettings, sOut );\n\t\t\t\n\t\t\tif ( oLang.fnInfoCallback !== null )\n\t\t\t{\n\t\t\t\tsOut = oLang.fnInfoCallback.call( oSettings.oInstance, \n\t\t\t\t\toSettings, iStart, iEnd, iMax, iTotal, sOut );\n\t\t\t}\n\t\t\t\n\t\t\tvar n = oSettings.aanFeatures.i;\n\t\t\tfor ( var i=0, iLen=n.length ; i<iLen ; i++ )\n\t\t\t{\n\t\t\t\t$(n[i]).html( sOut );\n\t\t\t}\n\t\t}\n\t\t\n\t\t\n\t\tfunction _fnInfoMacros ( oSettings, str )\n\t\t{\n\t\t\tvar\n\t\t\t\tiStart = oSettings._iDisplayStart+1,\n\t\t\t\tsStart = oSettings.fnFormatNumber( iStart ),\n\t\t\t\tiEnd = oSettings.fnDisplayEnd(),\n\t\t\t\tsEnd = oSettings.fnFormatNumber( iEnd ),\n\t\t\t\tiTotal = oSettings.fnRecordsDisplay(),\n\t\t\t\tsTotal = oSettings.fnFormatNumber( iTotal ),\n\t\t\t\tiMax = oSettings.fnRecordsTotal(),\n\t\t\t\tsMax = oSettings.fnFormatNumber( iMax );\n\t\t\n\t\t\t// When infinite scrolling, we are always starting at 1. _iDisplayStart is used only\n\t\t\t// internally\n\t\t\tif ( oSettings.oScroll.bInfinite )\n\t\t\t{\n\t\t\t\tsStart = oSettings.fnFormatNumber( 1 );\n\t\t\t}\n\t\t\n\t\t\treturn str.\n\t\t\t\treplace(/_START_/g, sStart).\n\t\t\t\treplace(/_END_/g,   sEnd).\n\t\t\t\treplace(/_TOTAL_/g, sTotal).\n\t\t\t\treplace(/_MAX_/g,   sMax);\n\t\t}\n\t\t\n\t\t\n\t\t\n\t\t/**\n\t\t * Draw the table for the first time, adding all required features\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnInitialise ( oSettings )\n\t\t{\n\t\t\tvar i, iLen, iAjaxStart=oSettings.iInitDisplayStart;\n\t\t\t\n\t\t\t/* Ensure that the table data is fully initialised */\n\t\t\tif ( oSettings.bInitialised === false )\n\t\t\t{\n\t\t\t\tsetTimeout( function(){ _fnInitialise( oSettings ); }, 200 );\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\t/* Show the display HTML options */\n\t\t\t_fnAddOptionsHtml( oSettings );\n\t\t\t\n\t\t\t/* Build and draw the header / footer for the table */\n\t\t\t_fnBuildHead( oSettings );\n\t\t\t_fnDrawHead( oSettings, oSettings.aoHeader );\n\t\t\tif ( oSettings.nTFoot )\n\t\t\t{\n\t\t\t\t_fnDrawHead( oSettings, oSettings.aoFooter );\n\t\t\t}\n\t\t\n\t\t\t/* Okay to show that something is going on now */\n\t\t\t_fnProcessingDisplay( oSettings, true );\n\t\t\t\n\t\t\t/* Calculate sizes for columns */\n\t\t\tif ( oSettings.oFeatures.bAutoWidth )\n\t\t\t{\n\t\t\t\t_fnCalculateColumnWidths( oSettings );\n\t\t\t}\n\t\t\t\n\t\t\tfor ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )\n\t\t\t{\n\t\t\t\tif ( oSettings.aoColumns[i].sWidth !== null )\n\t\t\t\t{\n\t\t\t\t\toSettings.aoColumns[i].nTh.style.width = _fnStringToCss( oSettings.aoColumns[i].sWidth );\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t/* If there is default sorting required - let's do it. The sort function will do the\n\t\t\t * drawing for us. Otherwise we draw the table regardless of the Ajax source - this allows\n\t\t\t * the table to look initialised for Ajax sourcing data (show 'loading' message possibly)\n\t\t\t */\n\t\t\tif ( oSettings.oFeatures.bSort )\n\t\t\t{\n\t\t\t\t_fnSort( oSettings );\n\t\t\t}\n\t\t\telse if ( oSettings.oFeatures.bFilter )\n\t\t\t{\n\t\t\t\t_fnFilterComplete( oSettings, oSettings.oPreviousSearch );\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\toSettings.aiDisplay = oSettings.aiDisplayMaster.slice();\n\t\t\t\t_fnCalculateEnd( oSettings );\n\t\t\t\t_fnDraw( oSettings );\n\t\t\t}\n\t\t\t\n\t\t\t/* if there is an ajax source load the data */\n\t\t\tif ( oSettings.sAjaxSource !== null && !oSettings.oFeatures.bServerSide )\n\t\t\t{\n\t\t\t\tvar aoData = [];\n\t\t\t\t_fnServerParams( oSettings, aoData );\n\t\t\t\toSettings.fnServerData.call( oSettings.oInstance, oSettings.sAjaxSource, aoData, function(json) {\n\t\t\t\t\tvar aData = (oSettings.sAjaxDataProp !== \"\") ?\n\t\t\t\t\t \t_fnGetObjectDataFn( oSettings.sAjaxDataProp )(json) : json;\n\t\t\n\t\t\t\t\t/* Got the data - add it to the table */\n\t\t\t\t\tfor ( i=0 ; i<aData.length ; i++ )\n\t\t\t\t\t{\n\t\t\t\t\t\t_fnAddData( oSettings, aData[i] );\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t/* Reset the init display for cookie saving. We've already done a filter, and\n\t\t\t\t\t * therefore cleared it before. So we need to make it appear 'fresh'\n\t\t\t\t\t */\n\t\t\t\t\toSettings.iInitDisplayStart = iAjaxStart;\n\t\t\t\t\t\n\t\t\t\t\tif ( oSettings.oFeatures.bSort )\n\t\t\t\t\t{\n\t\t\t\t\t\t_fnSort( oSettings );\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\toSettings.aiDisplay = oSettings.aiDisplayMaster.slice();\n\t\t\t\t\t\t_fnCalculateEnd( oSettings );\n\t\t\t\t\t\t_fnDraw( oSettings );\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t_fnProcessingDisplay( oSettings, false );\n\t\t\t\t\t_fnInitComplete( oSettings, json );\n\t\t\t\t}, oSettings );\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\t/* Server-side processing initialisation complete is done at the end of _fnDraw */\n\t\t\tif ( !oSettings.oFeatures.bServerSide )\n\t\t\t{\n\t\t\t\t_fnProcessingDisplay( oSettings, false );\n\t\t\t\t_fnInitComplete( oSettings );\n\t\t\t}\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Draw the table for the first time, adding all required features\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @param {object} [json] JSON from the server that completed the table, if using Ajax source\n\t\t *    with client-side processing (optional)\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnInitComplete ( oSettings, json )\n\t\t{\n\t\t\toSettings._bInitComplete = true;\n\t\t\t_fnCallbackFire( oSettings, 'aoInitComplete', 'init', [oSettings, json] );\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Language compatibility - when certain options are given, and others aren't, we\n\t\t * need to duplicate the values over, in order to provide backwards compatibility\n\t\t * with older language files.\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnLanguageCompat( oLanguage )\n\t\t{\n\t\t\tvar oDefaults = DataTable.defaults.oLanguage;\n\t\t\n\t\t\t/* Backwards compatibility - if there is no sEmptyTable given, then use the same as\n\t\t\t * sZeroRecords - assuming that is given.\n\t\t\t */\n\t\t\tif ( !oLanguage.sEmptyTable && oLanguage.sZeroRecords &&\n\t\t\t\toDefaults.sEmptyTable === \"No data available in table\" )\n\t\t\t{\n\t\t\t\t_fnMap( oLanguage, oLanguage, 'sZeroRecords', 'sEmptyTable' );\n\t\t\t}\n\t\t\n\t\t\t/* Likewise with loading records */\n\t\t\tif ( !oLanguage.sLoadingRecords && oLanguage.sZeroRecords &&\n\t\t\t\toDefaults.sLoadingRecords === \"Loading...\" )\n\t\t\t{\n\t\t\t\t_fnMap( oLanguage, oLanguage, 'sZeroRecords', 'sLoadingRecords' );\n\t\t\t}\n\t\t}\n\t\t\n\t\t\n\t\t\n\t\t/**\n\t\t * Generate the node required for user display length changing\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @returns {node} Display length feature node\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnFeatureHtmlLength ( oSettings )\n\t\t{\n\t\t\tif ( oSettings.oScroll.bInfinite )\n\t\t\t{\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\t\n\t\t\t/* This can be overruled by not using the _MENU_ var/macro in the language variable */\n\t\t\tvar sName = 'name=\"'+oSettings.sTableId+'_length\"';\n\t\t\tvar sStdMenu = '<select size=\"1\" '+sName+'>';\n\t\t\tvar i, iLen;\n\t\t\tvar aLengthMenu = oSettings.aLengthMenu;\n\t\t\t\n\t\t\tif ( aLengthMenu.length == 2 && typeof aLengthMenu[0] === 'object' && \n\t\t\t\t\ttypeof aLengthMenu[1] === 'object' )\n\t\t\t{\n\t\t\t\tfor ( i=0, iLen=aLengthMenu[0].length ; i<iLen ; i++ )\n\t\t\t\t{\n\t\t\t\t\tsStdMenu += '<option value=\"'+aLengthMenu[0][i]+'\">'+aLengthMenu[1][i]+'</option>';\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tfor ( i=0, iLen=aLengthMenu.length ; i<iLen ; i++ )\n\t\t\t\t{\n\t\t\t\t\tsStdMenu += '<option value=\"'+aLengthMenu[i]+'\">'+aLengthMenu[i]+'</option>';\n\t\t\t\t}\n\t\t\t}\n\t\t\tsStdMenu += '</select>';\n\t\t\t\n\t\t\tvar nLength = document.createElement( 'div' );\n\t\t\tif ( !oSettings.aanFeatures.l )\n\t\t\t{\n\t\t\t\tnLength.id = oSettings.sTableId+'_length';\n\t\t\t}\n\t\t\tnLength.className = oSettings.oClasses.sLength;\n\t\t\tnLength.innerHTML = '<label>'+oSettings.oLanguage.sLengthMenu.replace( '_MENU_', sStdMenu )+'</label>';\n\t\t\t\n\t\t\t/*\n\t\t\t * Set the length to the current display length - thanks to Andrea Pavlovic for this fix,\n\t\t\t * and Stefan Skopnik for fixing the fix!\n\t\t\t */\n\t\t\t$('select option[value=\"'+oSettings._iDisplayLength+'\"]', nLength).attr(\"selected\", true);\n\t\t\t\n\t\t\t$('select', nLength).bind( 'change.DT', function(e) {\n\t\t\t\tvar iVal = $(this).val();\n\t\t\t\t\n\t\t\t\t/* Update all other length options for the new display */\n\t\t\t\tvar n = oSettings.aanFeatures.l;\n\t\t\t\tfor ( i=0, iLen=n.length ; i<iLen ; i++ )\n\t\t\t\t{\n\t\t\t\t\tif ( n[i] != this.parentNode )\n\t\t\t\t\t{\n\t\t\t\t\t\t$('select', n[i]).val( iVal );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t/* Redraw the table */\n\t\t\t\toSettings._iDisplayLength = parseInt(iVal, 10);\n\t\t\t\t_fnCalculateEnd( oSettings );\n\t\t\t\t\n\t\t\t\t/* If we have space to show extra rows (backing up from the end point - then do so */\n\t\t\t\tif ( oSettings.fnDisplayEnd() == oSettings.fnRecordsDisplay() )\n\t\t\t\t{\n\t\t\t\t\toSettings._iDisplayStart = oSettings.fnDisplayEnd() - oSettings._iDisplayLength;\n\t\t\t\t\tif ( oSettings._iDisplayStart < 0 )\n\t\t\t\t\t{\n\t\t\t\t\t\toSettings._iDisplayStart = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif ( oSettings._iDisplayLength == -1 )\n\t\t\t\t{\n\t\t\t\t\toSettings._iDisplayStart = 0;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t_fnDraw( oSettings );\n\t\t\t} );\n\t\t\n\t\t\n\t\t\t$('select', nLength).attr('aria-controls', oSettings.sTableId);\n\t\t\t\n\t\t\treturn nLength;\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Recalculate the end point based on the start point\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnCalculateEnd( oSettings )\n\t\t{\n\t\t\tif ( oSettings.oFeatures.bPaginate === false )\n\t\t\t{\n\t\t\t\toSettings._iDisplayEnd = oSettings.aiDisplay.length;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t/* Set the end point of the display - based on how many elements there are\n\t\t\t\t * still to display\n\t\t\t\t */\n\t\t\t\tif ( oSettings._iDisplayStart + oSettings._iDisplayLength > oSettings.aiDisplay.length ||\n\t\t\t\t\t   oSettings._iDisplayLength == -1 )\n\t\t\t\t{\n\t\t\t\t\toSettings._iDisplayEnd = oSettings.aiDisplay.length;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\toSettings._iDisplayEnd = oSettings._iDisplayStart + oSettings._iDisplayLength;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\t\n\t\t\n\t\t/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n\t\t * Note that most of the paging logic is done in \n\t\t * DataTable.ext.oPagination\n\t\t */\n\t\t\n\t\t/**\n\t\t * Generate the node required for default pagination\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @returns {node} Pagination feature node\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnFeatureHtmlPaginate ( oSettings )\n\t\t{\n\t\t\tif ( oSettings.oScroll.bInfinite )\n\t\t\t{\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\t\n\t\t\tvar nPaginate = document.createElement( 'div' );\n\t\t\tnPaginate.className = oSettings.oClasses.sPaging+oSettings.sPaginationType;\n\t\t\t\n\t\t\tDataTable.ext.oPagination[ oSettings.sPaginationType ].fnInit( oSettings, nPaginate, \n\t\t\t\tfunction( oSettings ) {\n\t\t\t\t\t_fnCalculateEnd( oSettings );\n\t\t\t\t\t_fnDraw( oSettings );\n\t\t\t\t}\n\t\t\t);\n\t\t\t\n\t\t\t/* Add a draw callback for the pagination on first instance, to update the paging display */\n\t\t\tif ( !oSettings.aanFeatures.p )\n\t\t\t{\n\t\t\t\toSettings.aoDrawCallback.push( {\n\t\t\t\t\t\"fn\": function( oSettings ) {\n\t\t\t\t\t\tDataTable.ext.oPagination[ oSettings.sPaginationType ].fnUpdate( oSettings, function( oSettings ) {\n\t\t\t\t\t\t\t_fnCalculateEnd( oSettings );\n\t\t\t\t\t\t\t_fnDraw( oSettings );\n\t\t\t\t\t\t} );\n\t\t\t\t\t},\n\t\t\t\t\t\"sName\": \"pagination\"\n\t\t\t\t} );\n\t\t\t}\n\t\t\treturn nPaginate;\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Alter the display settings to change the page\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @param {string|int} mAction Paging action to take: \"first\", \"previous\", \"next\" or \"last\"\n\t\t *    or page number to jump to (integer)\n\t\t *  @returns {bool} true page has changed, false - no change (no effect) eg 'first' on page 1\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnPageChange ( oSettings, mAction )\n\t\t{\n\t\t\tvar iOldStart = oSettings._iDisplayStart;\n\t\t\t\n\t\t\tif ( typeof mAction === \"number\" )\n\t\t\t{\n\t\t\t\toSettings._iDisplayStart = mAction * oSettings._iDisplayLength;\n\t\t\t\tif ( oSettings._iDisplayStart > oSettings.fnRecordsDisplay() )\n\t\t\t\t{\n\t\t\t\t\toSettings._iDisplayStart = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if ( mAction == \"first\" )\n\t\t\t{\n\t\t\t\toSettings._iDisplayStart = 0;\n\t\t\t}\n\t\t\telse if ( mAction == \"previous\" )\n\t\t\t{\n\t\t\t\toSettings._iDisplayStart = oSettings._iDisplayLength>=0 ?\n\t\t\t\t\toSettings._iDisplayStart - oSettings._iDisplayLength :\n\t\t\t\t\t0;\n\t\t\t\t\n\t\t\t\t/* Correct for under-run */\n\t\t\t\tif ( oSettings._iDisplayStart < 0 )\n\t\t\t\t{\n\t\t\t\t  oSettings._iDisplayStart = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if ( mAction == \"next\" )\n\t\t\t{\n\t\t\t\tif ( oSettings._iDisplayLength >= 0 )\n\t\t\t\t{\n\t\t\t\t\t/* Make sure we are not over running the display array */\n\t\t\t\t\tif ( oSettings._iDisplayStart + oSettings._iDisplayLength < oSettings.fnRecordsDisplay() )\n\t\t\t\t\t{\n\t\t\t\t\t\toSettings._iDisplayStart += oSettings._iDisplayLength;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\toSettings._iDisplayStart = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if ( mAction == \"last\" )\n\t\t\t{\n\t\t\t\tif ( oSettings._iDisplayLength >= 0 )\n\t\t\t\t{\n\t\t\t\t\tvar iPages = parseInt( (oSettings.fnRecordsDisplay()-1) / oSettings._iDisplayLength, 10 ) + 1;\n\t\t\t\t\toSettings._iDisplayStart = (iPages-1) * oSettings._iDisplayLength;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\toSettings._iDisplayStart = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_fnLog( oSettings, 0, \"Unknown paging action: \"+mAction );\n\t\t\t}\n\t\t\t$(oSettings.oInstance).trigger('page', oSettings);\n\t\t\t\n\t\t\treturn iOldStart != oSettings._iDisplayStart;\n\t\t}\n\t\t\n\t\t\n\t\t\n\t\t/**\n\t\t * Generate the node required for the processing node\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @returns {node} Processing element\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnFeatureHtmlProcessing ( oSettings )\n\t\t{\n\t\t\tvar nProcessing = document.createElement( 'div' );\n\t\t\t\n\t\t\tif ( !oSettings.aanFeatures.r )\n\t\t\t{\n\t\t\t\tnProcessing.id = oSettings.sTableId+'_processing';\n\t\t\t}\n\t\t\tnProcessing.innerHTML = oSettings.oLanguage.sProcessing;\n\t\t\tnProcessing.className = oSettings.oClasses.sProcessing;\n\t\t\toSettings.nTable.parentNode.insertBefore( nProcessing, oSettings.nTable );\n\t\t\t\n\t\t\treturn nProcessing;\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Display or hide the processing indicator\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @param {bool} bShow Show the processing indicator (true) or not (false)\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnProcessingDisplay ( oSettings, bShow )\n\t\t{\n\t\t\tif ( oSettings.oFeatures.bProcessing )\n\t\t\t{\n\t\t\t\tvar an = oSettings.aanFeatures.r;\n\t\t\t\tfor ( var i=0, iLen=an.length ; i<iLen ; i++ )\n\t\t\t\t{\n\t\t\t\t\tan[i].style.visibility = bShow ? \"visible\" : \"hidden\";\n\t\t\t\t}\n\t\t\t}\n\t\t\n\t\t\t$(oSettings.oInstance).trigger('processing', [oSettings, bShow]);\n\t\t}\n\t\t\n\t\t/**\n\t\t * Add any control elements for the table - specifically scrolling\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @returns {node} Node to add to the DOM\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnFeatureHtmlTable ( oSettings )\n\t\t{\n\t\t\t/* Check if scrolling is enabled or not - if not then leave the DOM unaltered */\n\t\t\tif ( oSettings.oScroll.sX === \"\" && oSettings.oScroll.sY === \"\" )\n\t\t\t{\n\t\t\t\treturn oSettings.nTable;\n\t\t\t}\n\t\t\t\n\t\t\t/*\n\t\t\t * The HTML structure that we want to generate in this function is:\n\t\t\t *  div - nScroller\n\t\t\t *    div - nScrollHead\n\t\t\t *      div - nScrollHeadInner\n\t\t\t *        table - nScrollHeadTable\n\t\t\t *          thead - nThead\n\t\t\t *    div - nScrollBody\n\t\t\t *      table - oSettings.nTable\n\t\t\t *        thead - nTheadSize\n\t\t\t *        tbody - nTbody\n\t\t\t *    div - nScrollFoot\n\t\t\t *      div - nScrollFootInner\n\t\t\t *        table - nScrollFootTable\n\t\t\t *          tfoot - nTfoot\n\t\t\t */\n\t\t\tvar\n\t\t\t \tnScroller = document.createElement('div'),\n\t\t\t \tnScrollHead = document.createElement('div'),\n\t\t\t \tnScrollHeadInner = document.createElement('div'),\n\t\t\t \tnScrollBody = document.createElement('div'),\n\t\t\t \tnScrollFoot = document.createElement('div'),\n\t\t\t \tnScrollFootInner = document.createElement('div'),\n\t\t\t \tnScrollHeadTable = oSettings.nTable.cloneNode(false),\n\t\t\t \tnScrollFootTable = oSettings.nTable.cloneNode(false),\n\t\t\t\tnThead = oSettings.nTable.getElementsByTagName('thead')[0],\n\t\t\t \tnTfoot = oSettings.nTable.getElementsByTagName('tfoot').length === 0 ? null : \n\t\t\t\t\toSettings.nTable.getElementsByTagName('tfoot')[0],\n\t\t\t\toClasses = oSettings.oClasses;\n\t\t\t\n\t\t\tnScrollHead.appendChild( nScrollHeadInner );\n\t\t\tnScrollFoot.appendChild( nScrollFootInner );\n\t\t\tnScrollBody.appendChild( oSettings.nTable );\n\t\t\tnScroller.appendChild( nScrollHead );\n\t\t\tnScroller.appendChild( nScrollBody );\n\t\t\tnScrollHeadInner.appendChild( nScrollHeadTable );\n\t\t\tnScrollHeadTable.appendChild( nThead );\n\t\t\tif ( nTfoot !== null )\n\t\t\t{\n\t\t\t\tnScroller.appendChild( nScrollFoot );\n\t\t\t\tnScrollFootInner.appendChild( nScrollFootTable );\n\t\t\t\tnScrollFootTable.appendChild( nTfoot );\n\t\t\t}\n\t\t\t\n\t\t\tnScroller.className = oClasses.sScrollWrapper;\n\t\t\tnScrollHead.className = oClasses.sScrollHead;\n\t\t\tnScrollHeadInner.className = oClasses.sScrollHeadInner;\n\t\t\tnScrollBody.className = oClasses.sScrollBody;\n\t\t\tnScrollFoot.className = oClasses.sScrollFoot;\n\t\t\tnScrollFootInner.className = oClasses.sScrollFootInner;\n\t\t\t\n\t\t\tif ( oSettings.oScroll.bAutoCss )\n\t\t\t{\n\t\t\t\tnScrollHead.style.overflow = \"hidden\";\n\t\t\t\tnScrollHead.style.position = \"relative\";\n\t\t\t\tnScrollFoot.style.overflow = \"hidden\";\n\t\t\t\tnScrollBody.style.overflow = \"auto\";\n\t\t\t}\n\t\t\t\n\t\t\tnScrollHead.style.border = \"0\";\n\t\t\tnScrollHead.style.width = \"100%\";\n\t\t\tnScrollFoot.style.border = \"0\";\n\t\t\tnScrollHeadInner.style.width = oSettings.oScroll.sXInner !== \"\" ?\n\t\t\t\toSettings.oScroll.sXInner : \"100%\"; /* will be overwritten */\n\t\t\t\n\t\t\t/* Modify attributes to respect the clones */\n\t\t\tnScrollHeadTable.removeAttribute('id');\n\t\t\tnScrollHeadTable.style.marginLeft = \"0\";\n\t\t\toSettings.nTable.style.marginLeft = \"0\";\n\t\t\tif ( nTfoot !== null )\n\t\t\t{\n\t\t\t\tnScrollFootTable.removeAttribute('id');\n\t\t\t\tnScrollFootTable.style.marginLeft = \"0\";\n\t\t\t}\n\t\t\t\n\t\t\t/* Move caption elements from the body to the header, footer or leave where it is\n\t\t\t * depending on the configuration. Note that the DTD says there can be only one caption */\n\t\t\tvar nCaption = $(oSettings.nTable).children('caption');\n\t\t\tif ( nCaption.length > 0 )\n\t\t\t{\n\t\t\t\tnCaption = nCaption[0];\n\t\t\t\tif ( nCaption._captionSide === \"top\" )\n\t\t\t\t{\n\t\t\t\t\tnScrollHeadTable.appendChild( nCaption );\n\t\t\t\t}\n\t\t\t\telse if ( nCaption._captionSide === \"bottom\" && nTfoot )\n\t\t\t\t{\n\t\t\t\t\tnScrollFootTable.appendChild( nCaption );\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t/*\n\t\t\t * Sizing\n\t\t\t */\n\t\t\t/* When x-scrolling add the width and a scroller to move the header with the body */\n\t\t\tif ( oSettings.oScroll.sX !== \"\" )\n\t\t\t{\n\t\t\t\tnScrollHead.style.width = _fnStringToCss( oSettings.oScroll.sX );\n\t\t\t\tnScrollBody.style.width = _fnStringToCss( oSettings.oScroll.sX );\n\t\t\t\t\n\t\t\t\tif ( nTfoot !== null )\n\t\t\t\t{\n\t\t\t\t\tnScrollFoot.style.width = _fnStringToCss( oSettings.oScroll.sX );\t\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t/* When the body is scrolled, then we also want to scroll the headers */\n\t\t\t\t$(nScrollBody).scroll( function (e) {\n\t\t\t\t\tnScrollHead.scrollLeft = this.scrollLeft;\n\t\t\t\t\t\n\t\t\t\t\tif ( nTfoot !== null )\n\t\t\t\t\t{\n\t\t\t\t\t\tnScrollFoot.scrollLeft = this.scrollLeft;\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\t\t\t\n\t\t\t/* When yscrolling, add the height */\n\t\t\tif ( oSettings.oScroll.sY !== \"\" )\n\t\t\t{\n\t\t\t\tnScrollBody.style.height = _fnStringToCss( oSettings.oScroll.sY );\n\t\t\t}\n\t\t\t\n\t\t\t/* Redraw - align columns across the tables */\n\t\t\toSettings.aoDrawCallback.push( {\n\t\t\t\t\"fn\": _fnScrollDraw,\n\t\t\t\t\"sName\": \"scrolling\"\n\t\t\t} );\n\t\t\t\n\t\t\t/* Infinite scrolling event handlers */\n\t\t\tif ( oSettings.oScroll.bInfinite )\n\t\t\t{\n\t\t\t\t$(nScrollBody).scroll( function() {\n\t\t\t\t\t/* Use a blocker to stop scrolling from loading more data while other data is still loading */\n\t\t\t\t\tif ( !oSettings.bDrawing && $(this).scrollTop() !== 0 )\n\t\t\t\t\t{\n\t\t\t\t\t\t/* Check if we should load the next data set */\n\t\t\t\t\t\tif ( $(this).scrollTop() + $(this).height() > \n\t\t\t\t\t\t\t$(oSettings.nTable).height() - oSettings.oScroll.iLoadGap )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t/* Only do the redraw if we have to - we might be at the end of the data */\n\t\t\t\t\t\t\tif ( oSettings.fnDisplayEnd() < oSettings.fnRecordsDisplay() )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t_fnPageChange( oSettings, 'next' );\n\t\t\t\t\t\t\t\t_fnCalculateEnd( oSettings );\n\t\t\t\t\t\t\t\t_fnDraw( oSettings );\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\t\n\t\t\toSettings.nScrollHead = nScrollHead;\n\t\t\toSettings.nScrollFoot = nScrollFoot;\n\t\t\t\n\t\t\treturn nScroller;\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Update the various tables for resizing. It's a bit of a pig this function, but\n\t\t * basically the idea to:\n\t\t *   1. Re-create the table inside the scrolling div\n\t\t *   2. Take live measurements from the DOM\n\t\t *   3. Apply the measurements\n\t\t *   4. Clean up\n\t\t *  @param {object} o dataTables settings object\n\t\t *  @returns {node} Node to add to the DOM\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnScrollDraw ( o )\n\t\t{\n\t\t\tvar\n\t\t\t\tnScrollHeadInner = o.nScrollHead.getElementsByTagName('div')[0],\n\t\t\t\tnScrollHeadTable = nScrollHeadInner.getElementsByTagName('table')[0],\n\t\t\t\tnScrollBody = o.nTable.parentNode,\n\t\t\t\ti, iLen, j, jLen, anHeadToSize, anHeadSizers, anFootSizers, anFootToSize, oStyle, iVis,\n\t\t\t\tnTheadSize, nTfootSize,\n\t\t\t\tiWidth, aApplied=[], aAppliedFooter=[], iSanityWidth,\n\t\t\t\tnScrollFootInner = (o.nTFoot !== null) ? o.nScrollFoot.getElementsByTagName('div')[0] : null,\n\t\t\t\tnScrollFootTable = (o.nTFoot !== null) ? nScrollFootInner.getElementsByTagName('table')[0] : null,\n\t\t\t\tie67 = o.oBrowser.bScrollOversize,\n\t\t\t\tzeroOut = function(nSizer) {\n\t\t\t\t\toStyle = nSizer.style;\n\t\t\t\t\toStyle.paddingTop = \"0\";\n\t\t\t\t\toStyle.paddingBottom = \"0\";\n\t\t\t\t\toStyle.borderTopWidth = \"0\";\n\t\t\t\t\toStyle.borderBottomWidth = \"0\";\n\t\t\t\t\toStyle.height = 0;\n\t\t\t\t};\n\t\t\t\n\t\t\t/*\n\t\t\t * 1. Re-create the table inside the scrolling div\n\t\t\t */\n\t\t\t\n\t\t\t/* Remove the old minimised thead and tfoot elements in the inner table */\n\t\t\t$(o.nTable).children('thead, tfoot').remove();\n\t\t\n\t\t\t/* Clone the current header and footer elements and then place it into the inner table */\n\t\t\tnTheadSize = $(o.nTHead).clone()[0];\n\t\t\to.nTable.insertBefore( nTheadSize, o.nTable.childNodes[0] );\n\t\t\tanHeadToSize = o.nTHead.getElementsByTagName('tr');\n\t\t\tanHeadSizers = nTheadSize.getElementsByTagName('tr');\n\t\t\t\n\t\t\tif ( o.nTFoot !== null )\n\t\t\t{\n\t\t\t\tnTfootSize = $(o.nTFoot).clone()[0];\n\t\t\t\to.nTable.insertBefore( nTfootSize, o.nTable.childNodes[1] );\n\t\t\t\tanFootToSize = o.nTFoot.getElementsByTagName('tr');\n\t\t\t\tanFootSizers = nTfootSize.getElementsByTagName('tr');\n\t\t\t}\n\t\t\t\n\t\t\t/*\n\t\t\t * 2. Take live measurements from the DOM - do not alter the DOM itself!\n\t\t\t */\n\t\t\t\n\t\t\t/* Remove old sizing and apply the calculated column widths\n\t\t\t * Get the unique column headers in the newly created (cloned) header. We want to apply the\n\t\t\t * calculated sizes to this header\n\t\t\t */\n\t\t\tif ( o.oScroll.sX === \"\" )\n\t\t\t{\n\t\t\t\tnScrollBody.style.width = '100%';\n\t\t\t\tnScrollHeadInner.parentNode.style.width = '100%';\n\t\t\t}\n\t\t\t\n\t\t\tvar nThs = _fnGetUniqueThs( o, nTheadSize );\n\t\t\tfor ( i=0, iLen=nThs.length ; i<iLen ; i++ )\n\t\t\t{\n\t\t\t\tiVis = _fnVisibleToColumnIndex( o, i );\n\t\t\t\tnThs[i].style.width = o.aoColumns[iVis].sWidth;\n\t\t\t}\n\t\t\t\n\t\t\tif ( o.nTFoot !== null )\n\t\t\t{\n\t\t\t\t_fnApplyToChildren( function(n) {\n\t\t\t\t\tn.style.width = \"\";\n\t\t\t\t}, anFootSizers );\n\t\t\t}\n\t\t\n\t\t\t// If scroll collapse is enabled, when we put the headers back into the body for sizing, we\n\t\t\t// will end up forcing the scrollbar to appear, making our measurements wrong for when we\n\t\t\t// then hide it (end of this function), so add the header height to the body scroller.\n\t\t\tif ( o.oScroll.bCollapse && o.oScroll.sY !== \"\" )\n\t\t\t{\n\t\t\t\tnScrollBody.style.height = (nScrollBody.offsetHeight + o.nTHead.offsetHeight)+\"px\";\n\t\t\t}\n\t\t\t\n\t\t\t/* Size the table as a whole */\n\t\t\tiSanityWidth = $(o.nTable).outerWidth();\n\t\t\tif ( o.oScroll.sX === \"\" )\n\t\t\t{\n\t\t\t\t/* No x scrolling */\n\t\t\t\to.nTable.style.width = \"100%\";\n\t\t\t\t\n\t\t\t\t/* I know this is rubbish - but IE7 will make the width of the table when 100% include\n\t\t\t\t * the scrollbar - which is shouldn't. When there is a scrollbar we need to take this\n\t\t\t\t * into account.\n\t\t\t\t */\n\t\t\t\tif ( ie67 && ($('tbody', nScrollBody).height() > nScrollBody.offsetHeight || \n\t\t\t\t\t$(nScrollBody).css('overflow-y') == \"scroll\")  )\n\t\t\t\t{\n\t\t\t\t\to.nTable.style.width = _fnStringToCss( $(o.nTable).outerWidth() - o.oScroll.iBarWidth);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif ( o.oScroll.sXInner !== \"\" )\n\t\t\t\t{\n\t\t\t\t\t/* x scroll inner has been given - use it */\n\t\t\t\t\to.nTable.style.width = _fnStringToCss(o.oScroll.sXInner);\n\t\t\t\t}\n\t\t\t\telse if ( iSanityWidth == $(nScrollBody).width() &&\n\t\t\t\t   $(nScrollBody).height() < $(o.nTable).height() )\n\t\t\t\t{\n\t\t\t\t\t/* There is y-scrolling - try to take account of the y scroll bar */\n\t\t\t\t\to.nTable.style.width = _fnStringToCss( iSanityWidth-o.oScroll.iBarWidth );\n\t\t\t\t\tif ( $(o.nTable).outerWidth() > iSanityWidth-o.oScroll.iBarWidth )\n\t\t\t\t\t{\n\t\t\t\t\t\t/* Not possible to take account of it */\n\t\t\t\t\t\to.nTable.style.width = _fnStringToCss( iSanityWidth );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t/* All else fails */\n\t\t\t\t\to.nTable.style.width = _fnStringToCss( iSanityWidth );\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t/* Recalculate the sanity width - now that we've applied the required width, before it was\n\t\t\t * a temporary variable. This is required because the column width calculation is done\n\t\t\t * before this table DOM is created.\n\t\t\t */\n\t\t\tiSanityWidth = $(o.nTable).outerWidth();\n\t\t\t\n\t\t\t/* We want the hidden header to have zero height, so remove padding and borders. Then\n\t\t\t * set the width based on the real headers\n\t\t\t */\n\t\t\t\n\t\t\t// Apply all styles in one pass. Invalidates layout only once because we don't read any \n\t\t\t// DOM properties.\n\t\t\t_fnApplyToChildren( zeroOut, anHeadSizers );\n\t\t\t \n\t\t\t// Read all widths in next pass. Forces layout only once because we do not change \n\t\t\t// any DOM properties.\n\t\t\t_fnApplyToChildren( function(nSizer) {\n\t\t\t\taApplied.push( _fnStringToCss( $(nSizer).width() ) );\n\t\t\t}, anHeadSizers );\n\t\t\t \n\t\t\t// Apply all widths in final pass. Invalidates layout only once because we do not\n\t\t\t// read any DOM properties.\n\t\t\t_fnApplyToChildren( function(nToSize, i) {\n\t\t\t\tnToSize.style.width = aApplied[i];\n\t\t\t}, anHeadToSize );\n\t\t\n\t\t\t$(anHeadSizers).height(0);\n\t\t\t\n\t\t\t/* Same again with the footer if we have one */\n\t\t\tif ( o.nTFoot !== null )\n\t\t\t{\n\t\t\t\t_fnApplyToChildren( zeroOut, anFootSizers );\n\t\t\t\t \n\t\t\t\t_fnApplyToChildren( function(nSizer) {\n\t\t\t\t\taAppliedFooter.push( _fnStringToCss( $(nSizer).width() ) );\n\t\t\t\t}, anFootSizers );\n\t\t\t\t \n\t\t\t\t_fnApplyToChildren( function(nToSize, i) {\n\t\t\t\t\tnToSize.style.width = aAppliedFooter[i];\n\t\t\t\t}, anFootToSize );\n\t\t\n\t\t\t\t$(anFootSizers).height(0);\n\t\t\t}\n\t\t\t\n\t\t\t/*\n\t\t\t * 3. Apply the measurements\n\t\t\t */\n\t\t\t\n\t\t\t/* \"Hide\" the header and footer that we used for the sizing. We want to also fix their width\n\t\t\t * to what they currently are\n\t\t\t */\n\t\t\t_fnApplyToChildren( function(nSizer, i) {\n\t\t\t\tnSizer.innerHTML = \"\";\n\t\t\t\tnSizer.style.width = aApplied[i];\n\t\t\t}, anHeadSizers );\n\t\t\t\n\t\t\tif ( o.nTFoot !== null )\n\t\t\t{\n\t\t\t\t_fnApplyToChildren( function(nSizer, i) {\n\t\t\t\t\tnSizer.innerHTML = \"\";\n\t\t\t\t\tnSizer.style.width = aAppliedFooter[i];\n\t\t\t\t}, anFootSizers );\n\t\t\t}\n\t\t\t\n\t\t\t/* Sanity check that the table is of a sensible width. If not then we are going to get\n\t\t\t * misalignment - try to prevent this by not allowing the table to shrink below its min width\n\t\t\t */\n\t\t\tif ( $(o.nTable).outerWidth() < iSanityWidth )\n\t\t\t{\n\t\t\t\t/* The min width depends upon if we have a vertical scrollbar visible or not */\n\t\t\t\tvar iCorrection = ((nScrollBody.scrollHeight > nScrollBody.offsetHeight || \n\t\t\t\t\t$(nScrollBody).css('overflow-y') == \"scroll\")) ?\n\t\t\t\t\t\tiSanityWidth+o.oScroll.iBarWidth : iSanityWidth;\n\t\t\t\t\n\t\t\t\t/* IE6/7 are a law unto themselves... */\n\t\t\t\tif ( ie67 && (nScrollBody.scrollHeight > \n\t\t\t\t\tnScrollBody.offsetHeight || $(nScrollBody).css('overflow-y') == \"scroll\")  )\n\t\t\t\t{\n\t\t\t\t\to.nTable.style.width = _fnStringToCss( iCorrection-o.oScroll.iBarWidth );\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t/* Apply the calculated minimum width to the table wrappers */\n\t\t\t\tnScrollBody.style.width = _fnStringToCss( iCorrection );\n\t\t\t\to.nScrollHead.style.width = _fnStringToCss( iCorrection );\n\t\t\t\t\n\t\t\t\tif ( o.nTFoot !== null )\n\t\t\t\t{\n\t\t\t\t\to.nScrollFoot.style.width = _fnStringToCss( iCorrection );\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t/* And give the user a warning that we've stopped the table getting too small */\n\t\t\t\tif ( o.oScroll.sX === \"\" )\n\t\t\t\t{\n\t\t\t\t\t_fnLog( o, 1, \"The table cannot fit into the current element which will cause column\"+\n\t\t\t\t\t\t\" misalignment. The table has been drawn at its minimum possible width.\" );\n\t\t\t\t}\n\t\t\t\telse if ( o.oScroll.sXInner !== \"\" )\n\t\t\t\t{\n\t\t\t\t\t_fnLog( o, 1, \"The table cannot fit into the current element which will cause column\"+\n\t\t\t\t\t\t\" misalignment. Increase the sScrollXInner value or remove it to allow automatic\"+\n\t\t\t\t\t\t\" calculation\" );\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tnScrollBody.style.width = _fnStringToCss( '100%' );\n\t\t\t\to.nScrollHead.style.width = _fnStringToCss( '100%' );\n\t\t\t\t\n\t\t\t\tif ( o.nTFoot !== null )\n\t\t\t\t{\n\t\t\t\t\to.nScrollFoot.style.width = _fnStringToCss( '100%' );\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t\n\t\t\t/*\n\t\t\t * 4. Clean up\n\t\t\t */\n\t\t\tif ( o.oScroll.sY === \"\" )\n\t\t\t{\n\t\t\t\t/* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting\n\t\t\t\t * the scrollbar height from the visible display, rather than adding it on. We need to\n\t\t\t\t * set the height in order to sort this. Don't want to do it in any other browsers.\n\t\t\t\t */\n\t\t\t\tif ( ie67 )\n\t\t\t\t{\n\t\t\t\t\tnScrollBody.style.height = _fnStringToCss( o.nTable.offsetHeight+o.oScroll.iBarWidth );\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif ( o.oScroll.sY !== \"\" && o.oScroll.bCollapse )\n\t\t\t{\n\t\t\t\tnScrollBody.style.height = _fnStringToCss( o.oScroll.sY );\n\t\t\t\t\n\t\t\t\tvar iExtra = (o.oScroll.sX !== \"\" && o.nTable.offsetWidth > nScrollBody.offsetWidth) ?\n\t\t\t\t \to.oScroll.iBarWidth : 0;\n\t\t\t\tif ( o.nTable.offsetHeight < nScrollBody.offsetHeight )\n\t\t\t\t{\n\t\t\t\t\tnScrollBody.style.height = _fnStringToCss( o.nTable.offsetHeight+iExtra );\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t/* Finally set the width's of the header and footer tables */\n\t\t\tvar iOuterWidth = $(o.nTable).outerWidth();\n\t\t\tnScrollHeadTable.style.width = _fnStringToCss( iOuterWidth );\n\t\t\tnScrollHeadInner.style.width = _fnStringToCss( iOuterWidth );\n\t\t\n\t\t\t// Figure out if there are scrollbar present - if so then we need a the header and footer to\n\t\t\t// provide a bit more space to allow \"overflow\" scrolling (i.e. past the scrollbar)\n\t\t\tvar bScrolling = $(o.nTable).height() > nScrollBody.clientHeight || $(nScrollBody).css('overflow-y') == \"scroll\";\n\t\t\tnScrollHeadInner.style.paddingRight = bScrolling ? o.oScroll.iBarWidth+\"px\" : \"0px\";\n\t\t\t\n\t\t\tif ( o.nTFoot !== null )\n\t\t\t{\n\t\t\t\tnScrollFootTable.style.width = _fnStringToCss( iOuterWidth );\n\t\t\t\tnScrollFootInner.style.width = _fnStringToCss( iOuterWidth );\n\t\t\t\tnScrollFootInner.style.paddingRight = bScrolling ? o.oScroll.iBarWidth+\"px\" : \"0px\";\n\t\t\t}\n\t\t\n\t\t\t/* Adjust the position of the header in case we loose the y-scrollbar */\n\t\t\t$(nScrollBody).scroll();\n\t\t\t\n\t\t\t/* If sorting or filtering has occurred, jump the scrolling back to the top */\n\t\t\tif ( o.bSorted || o.bFiltered )\n\t\t\t{\n\t\t\t\tnScrollBody.scrollTop = 0;\n\t\t\t}\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Apply a given function to the display child nodes of an element array (typically\n\t\t * TD children of TR rows\n\t\t *  @param {function} fn Method to apply to the objects\n\t\t *  @param array {nodes} an1 List of elements to look through for display children\n\t\t *  @param array {nodes} an2 Another list (identical structure to the first) - optional\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnApplyToChildren( fn, an1, an2 )\n\t\t{\n\t\t\tvar index=0, i=0, iLen=an1.length;\n\t\t\tvar nNode1, nNode2;\n\t\t\n\t\t\twhile ( i < iLen )\n\t\t\t{\n\t\t\t\tnNode1 = an1[i].firstChild;\n\t\t\t\tnNode2 = an2 ? an2[i].firstChild : null;\n\t\t\t\twhile ( nNode1 )\n\t\t\t\t{\n\t\t\t\t\tif ( nNode1.nodeType === 1 )\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( an2 )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfn( nNode1, nNode2, index );\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfn( nNode1, index );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tindex++;\n\t\t\t\t\t}\n\t\t\t\t\tnNode1 = nNode1.nextSibling;\n\t\t\t\t\tnNode2 = an2 ? nNode2.nextSibling : null;\n\t\t\t\t}\n\t\t\t\ti++;\n\t\t\t}\n\t\t}\n\t\t\n\t\t/**\n\t\t * Convert a CSS unit width to pixels (e.g. 2em)\n\t\t *  @param {string} sWidth width to be converted\n\t\t *  @param {node} nParent parent to get the with for (required for relative widths) - optional\n\t\t *  @returns {int} iWidth width in pixels\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnConvertToWidth ( sWidth, nParent )\n\t\t{\n\t\t\tif ( !sWidth || sWidth === null || sWidth === '' )\n\t\t\t{\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\t\n\t\t\tif ( !nParent )\n\t\t\t{\n\t\t\t\tnParent = document.body;\n\t\t\t}\n\t\t\t\n\t\t\tvar iWidth;\n\t\t\tvar nTmp = document.createElement( \"div\" );\n\t\t\tnTmp.style.width = _fnStringToCss( sWidth );\n\t\t\t\n\t\t\tnParent.appendChild( nTmp );\n\t\t\tiWidth = nTmp.offsetWidth;\n\t\t\tnParent.removeChild( nTmp );\n\t\t\t\n\t\t\treturn ( iWidth );\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Calculate the width of columns for the table\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnCalculateColumnWidths ( oSettings )\n\t\t{\n\t\t\tvar iTableWidth = oSettings.nTable.offsetWidth;\n\t\t\tvar iUserInputs = 0;\n\t\t\tvar iTmpWidth;\n\t\t\tvar iVisibleColumns = 0;\n\t\t\tvar iColums = oSettings.aoColumns.length;\n\t\t\tvar i, iIndex, iCorrector, iWidth;\n\t\t\tvar oHeaders = $('th', oSettings.nTHead);\n\t\t\tvar widthAttr = oSettings.nTable.getAttribute('width');\n\t\t\tvar nWrapper = oSettings.nTable.parentNode;\n\t\t\t\n\t\t\t/* Convert any user input sizes into pixel sizes */\n\t\t\tfor ( i=0 ; i<iColums ; i++ )\n\t\t\t{\n\t\t\t\tif ( oSettings.aoColumns[i].bVisible )\n\t\t\t\t{\n\t\t\t\t\tiVisibleColumns++;\n\t\t\t\t\t\n\t\t\t\t\tif ( oSettings.aoColumns[i].sWidth !== null )\n\t\t\t\t\t{\n\t\t\t\t\t\tiTmpWidth = _fnConvertToWidth( oSettings.aoColumns[i].sWidthOrig, \n\t\t\t\t\t\t\tnWrapper );\n\t\t\t\t\t\tif ( iTmpWidth !== null )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\toSettings.aoColumns[i].sWidth = _fnStringToCss( iTmpWidth );\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\tiUserInputs++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t/* If the number of columns in the DOM equals the number that we have to process in \n\t\t\t * DataTables, then we can use the offsets that are created by the web-browser. No custom \n\t\t\t * sizes can be set in order for this to happen, nor scrolling used\n\t\t\t */\n\t\t\tif ( iColums == oHeaders.length && iUserInputs === 0 && iVisibleColumns == iColums &&\n\t\t\t\toSettings.oScroll.sX === \"\" && oSettings.oScroll.sY === \"\" )\n\t\t\t{\n\t\t\t\tfor ( i=0 ; i<oSettings.aoColumns.length ; i++ )\n\t\t\t\t{\n\t\t\t\t\tiTmpWidth = $(oHeaders[i]).width();\n\t\t\t\t\tif ( iTmpWidth !== null )\n\t\t\t\t\t{\n\t\t\t\t\t\toSettings.aoColumns[i].sWidth = _fnStringToCss( iTmpWidth );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t/* Otherwise we are going to have to do some calculations to get the width of each column.\n\t\t\t\t * Construct a 1 row table with the widest node in the data, and any user defined widths,\n\t\t\t\t * then insert it into the DOM and allow the browser to do all the hard work of\n\t\t\t\t * calculating table widths.\n\t\t\t\t */\n\t\t\t\tvar\n\t\t\t\t\tnCalcTmp = oSettings.nTable.cloneNode( false ),\n\t\t\t\t\tnTheadClone = oSettings.nTHead.cloneNode(true),\n\t\t\t\t\tnBody = document.createElement( 'tbody' ),\n\t\t\t\t\tnTr = document.createElement( 'tr' ),\n\t\t\t\t\tnDivSizing;\n\t\t\t\t\n\t\t\t\tnCalcTmp.removeAttribute( \"id\" );\n\t\t\t\tnCalcTmp.appendChild( nTheadClone );\n\t\t\t\tif ( oSettings.nTFoot !== null )\n\t\t\t\t{\n\t\t\t\t\tnCalcTmp.appendChild( oSettings.nTFoot.cloneNode(true) );\n\t\t\t\t\t_fnApplyToChildren( function(n) {\n\t\t\t\t\t\tn.style.width = \"\";\n\t\t\t\t\t}, nCalcTmp.getElementsByTagName('tr') );\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tnCalcTmp.appendChild( nBody );\n\t\t\t\tnBody.appendChild( nTr );\n\t\t\t\t\n\t\t\t\t/* Remove any sizing that was previously applied by the styles */\n\t\t\t\tvar jqColSizing = $('thead th', nCalcTmp);\n\t\t\t\tif ( jqColSizing.length === 0 )\n\t\t\t\t{\n\t\t\t\t\tjqColSizing = $('tbody tr:eq(0)>td', nCalcTmp);\n\t\t\t\t}\n\t\t\n\t\t\t\t/* Apply custom sizing to the cloned header */\n\t\t\t\tvar nThs = _fnGetUniqueThs( oSettings, nTheadClone );\n\t\t\t\tiCorrector = 0;\n\t\t\t\tfor ( i=0 ; i<iColums ; i++ )\n\t\t\t\t{\n\t\t\t\t\tvar oColumn = oSettings.aoColumns[i];\n\t\t\t\t\tif ( oColumn.bVisible && oColumn.sWidthOrig !== null && oColumn.sWidthOrig !== \"\" )\n\t\t\t\t\t{\n\t\t\t\t\t\tnThs[i-iCorrector].style.width = _fnStringToCss( oColumn.sWidthOrig );\n\t\t\t\t\t}\n\t\t\t\t\telse if ( oColumn.bVisible )\n\t\t\t\t\t{\n\t\t\t\t\t\tnThs[i-iCorrector].style.width = \"\";\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tiCorrector++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\n\t\t\t\t/* Find the biggest td for each column and put it into the table */\n\t\t\t\tfor ( i=0 ; i<iColums ; i++ )\n\t\t\t\t{\n\t\t\t\t\tif ( oSettings.aoColumns[i].bVisible )\n\t\t\t\t\t{\n\t\t\t\t\t\tvar nTd = _fnGetWidestNode( oSettings, i );\n\t\t\t\t\t\tif ( nTd !== null )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tnTd = nTd.cloneNode(true);\n\t\t\t\t\t\t\tif ( oSettings.aoColumns[i].sContentPadding !== \"\" )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tnTd.innerHTML += oSettings.aoColumns[i].sContentPadding;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tnTr.appendChild( nTd );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t/* Build the table and 'display' it */\n\t\t\t\tnWrapper.appendChild( nCalcTmp );\n\t\t\t\t\n\t\t\t\t/* When scrolling (X or Y) we want to set the width of the table as appropriate. However,\n\t\t\t\t * when not scrolling leave the table width as it is. This results in slightly different,\n\t\t\t\t * but I think correct behaviour\n\t\t\t\t */\n\t\t\t\tif ( oSettings.oScroll.sX !== \"\" && oSettings.oScroll.sXInner !== \"\" )\n\t\t\t\t{\n\t\t\t\t\tnCalcTmp.style.width = _fnStringToCss(oSettings.oScroll.sXInner);\n\t\t\t\t}\n\t\t\t\telse if ( oSettings.oScroll.sX !== \"\" )\n\t\t\t\t{\n\t\t\t\t\tnCalcTmp.style.width = \"\";\n\t\t\t\t\tif ( $(nCalcTmp).width() < nWrapper.offsetWidth )\n\t\t\t\t\t{\n\t\t\t\t\t\tnCalcTmp.style.width = _fnStringToCss( nWrapper.offsetWidth );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if ( oSettings.oScroll.sY !== \"\" )\n\t\t\t\t{\n\t\t\t\t\tnCalcTmp.style.width = _fnStringToCss( nWrapper.offsetWidth );\n\t\t\t\t}\n\t\t\t\telse if ( widthAttr )\n\t\t\t\t{\n\t\t\t\t\tnCalcTmp.style.width = _fnStringToCss( widthAttr );\n\t\t\t\t}\n\t\t\t\tnCalcTmp.style.visibility = \"hidden\";\n\t\t\t\t\n\t\t\t\t/* Scrolling considerations */\n\t\t\t\t_fnScrollingWidthAdjust( oSettings, nCalcTmp );\n\t\t\t\t\n\t\t\t\t/* Read the width's calculated by the browser and store them for use by the caller. We\n\t\t\t\t * first of all try to use the elements in the body, but it is possible that there are\n\t\t\t\t * no elements there, under which circumstances we use the header elements\n\t\t\t\t */\n\t\t\t\tvar oNodes = $(\"tbody tr:eq(0)\", nCalcTmp).children();\n\t\t\t\tif ( oNodes.length === 0 )\n\t\t\t\t{\n\t\t\t\t\toNodes = _fnGetUniqueThs( oSettings, $('thead', nCalcTmp)[0] );\n\t\t\t\t}\n\t\t\n\t\t\t\t/* Browsers need a bit of a hand when a width is assigned to any columns when \n\t\t\t\t * x-scrolling as they tend to collapse the table to the min-width, even if\n\t\t\t\t * we sent the column widths. So we need to keep track of what the table width\n\t\t\t\t * should be by summing the user given values, and the automatic values\n\t\t\t\t */\n\t\t\t\tif ( oSettings.oScroll.sX !== \"\" )\n\t\t\t\t{\n\t\t\t\t\tvar iTotal = 0;\n\t\t\t\t\tiCorrector = 0;\n\t\t\t\t\tfor ( i=0 ; i<oSettings.aoColumns.length ; i++ )\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( oSettings.aoColumns[i].bVisible )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif ( oSettings.aoColumns[i].sWidthOrig === null )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tiTotal += $(oNodes[iCorrector]).outerWidth();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tiTotal += parseInt(oSettings.aoColumns[i].sWidth.replace('px',''), 10) +\n\t\t\t\t\t\t\t\t\t($(oNodes[iCorrector]).outerWidth() - $(oNodes[iCorrector]).width());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tiCorrector++;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tnCalcTmp.style.width = _fnStringToCss( iTotal );\n\t\t\t\t\toSettings.nTable.style.width = _fnStringToCss( iTotal );\n\t\t\t\t}\n\t\t\n\t\t\t\tiCorrector = 0;\n\t\t\t\tfor ( i=0 ; i<oSettings.aoColumns.length ; i++ )\n\t\t\t\t{\n\t\t\t\t\tif ( oSettings.aoColumns[i].bVisible )\n\t\t\t\t\t{\n\t\t\t\t\t\tiWidth = $(oNodes[iCorrector]).width();\n\t\t\t\t\t\tif ( iWidth !== null && iWidth > 0 )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\toSettings.aoColumns[i].sWidth = _fnStringToCss( iWidth );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tiCorrector++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\n\t\t\t\tvar cssWidth = $(nCalcTmp).css('width');\n\t\t\t\toSettings.nTable.style.width = (cssWidth.indexOf('%') !== -1) ?\n\t\t\t\t    cssWidth : _fnStringToCss( $(nCalcTmp).outerWidth() );\n\t\t\t\tnCalcTmp.parentNode.removeChild( nCalcTmp );\n\t\t\t}\n\t\t\n\t\t\tif ( widthAttr )\n\t\t\t{\n\t\t\t\toSettings.nTable.style.width = _fnStringToCss( widthAttr );\n\t\t\t}\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Adjust a table's width to take account of scrolling\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @param {node} n table node\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnScrollingWidthAdjust ( oSettings, n )\n\t\t{\n\t\t\tif ( oSettings.oScroll.sX === \"\" && oSettings.oScroll.sY !== \"\" )\n\t\t\t{\n\t\t\t\t/* When y-scrolling only, we want to remove the width of the scroll bar so the table\n\t\t\t\t * + scroll bar will fit into the area avaialble.\n\t\t\t\t */\n\t\t\t\tvar iOrigWidth = $(n).width();\n\t\t\t\tn.style.width = _fnStringToCss( $(n).outerWidth()-oSettings.oScroll.iBarWidth );\n\t\t\t}\n\t\t\telse if ( oSettings.oScroll.sX !== \"\" )\n\t\t\t{\n\t\t\t\t/* When x-scrolling both ways, fix the table at it's current size, without adjusting */\n\t\t\t\tn.style.width = _fnStringToCss( $(n).outerWidth() );\n\t\t\t}\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Get the widest node\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @param {int} iCol column of interest\n\t\t *  @returns {node} widest table node\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnGetWidestNode( oSettings, iCol )\n\t\t{\n\t\t\tvar iMaxIndex = _fnGetMaxLenString( oSettings, iCol );\n\t\t\tif ( iMaxIndex < 0 )\n\t\t\t{\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\n\t\t\tif ( oSettings.aoData[iMaxIndex].nTr === null )\n\t\t\t{\n\t\t\t\tvar n = document.createElement('td');\n\t\t\t\tn.innerHTML = _fnGetCellData( oSettings, iMaxIndex, iCol, '' );\n\t\t\t\treturn n;\n\t\t\t}\n\t\t\treturn _fnGetTdNodes(oSettings, iMaxIndex)[iCol];\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Get the maximum strlen for each data column\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @param {int} iCol column of interest\n\t\t *  @returns {string} max string length for each column\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnGetMaxLenString( oSettings, iCol )\n\t\t{\n\t\t\tvar iMax = -1;\n\t\t\tvar iMaxIndex = -1;\n\t\t\t\n\t\t\tfor ( var i=0 ; i<oSettings.aoData.length ; i++ )\n\t\t\t{\n\t\t\t\tvar s = _fnGetCellData( oSettings, i, iCol, 'display' )+\"\";\n\t\t\t\ts = s.replace( /<.*?>/g, \"\" );\n\t\t\t\tif ( s.length > iMax )\n\t\t\t\t{\n\t\t\t\t\tiMax = s.length;\n\t\t\t\t\tiMaxIndex = i;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\treturn iMaxIndex;\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Append a CSS unit (only if required) to a string\n\t\t *  @param {array} aArray1 first array\n\t\t *  @param {array} aArray2 second array\n\t\t *  @returns {int} 0 if match, 1 if length is different, 2 if no match\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnStringToCss( s )\n\t\t{\n\t\t\tif ( s === null )\n\t\t\t{\n\t\t\t\treturn \"0px\";\n\t\t\t}\n\t\t\t\n\t\t\tif ( typeof s == 'number' )\n\t\t\t{\n\t\t\t\tif ( s < 0 )\n\t\t\t\t{\n\t\t\t\t\treturn \"0px\";\n\t\t\t\t}\n\t\t\t\treturn s+\"px\";\n\t\t\t}\n\t\t\t\n\t\t\t/* Check if the last character is not 0-9 */\n\t\t\tvar c = s.charCodeAt( s.length-1 );\n\t\t\tif (c < 0x30 || c > 0x39)\n\t\t\t{\n\t\t\t\treturn s;\n\t\t\t}\n\t\t\treturn s+\"px\";\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Get the width of a scroll bar in this browser being used\n\t\t *  @returns {int} width in pixels\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnScrollBarWidth ()\n\t\t{  \n\t\t\tvar inner = document.createElement('p');\n\t\t\tvar style = inner.style;\n\t\t\tstyle.width = \"100%\";\n\t\t\tstyle.height = \"200px\";\n\t\t\tstyle.padding = \"0px\";\n\t\t\t\n\t\t\tvar outer = document.createElement('div');\n\t\t\tstyle = outer.style;\n\t\t\tstyle.position = \"absolute\";\n\t\t\tstyle.top = \"0px\";\n\t\t\tstyle.left = \"0px\";\n\t\t\tstyle.visibility = \"hidden\";\n\t\t\tstyle.width = \"200px\";\n\t\t\tstyle.height = \"150px\";\n\t\t\tstyle.padding = \"0px\";\n\t\t\tstyle.overflow = \"hidden\";\n\t\t\touter.appendChild(inner);\n\t\t\t\n\t\t\tdocument.body.appendChild(outer);\n\t\t\tvar w1 = inner.offsetWidth;\n\t\t\touter.style.overflow = 'scroll';\n\t\t\tvar w2 = inner.offsetWidth;\n\t\t\tif ( w1 == w2 )\n\t\t\t{\n\t\t\t\tw2 = outer.clientWidth;\n\t\t\t}\n\t\t\t\n\t\t\tdocument.body.removeChild(outer);\n\t\t\treturn (w1 - w2);  \n\t\t}\n\t\t\n\t\t/**\n\t\t * Change the order of the table\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @param {bool} bApplyClasses optional - should we apply classes or not\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnSort ( oSettings, bApplyClasses )\n\t\t{\n\t\t\tvar\n\t\t\t\ti, iLen, j, jLen, k, kLen,\n\t\t\t\tsDataType, nTh,\n\t\t\t\taaSort = [],\n\t\t\t \taiOrig = [],\n\t\t\t\toSort = DataTable.ext.oSort,\n\t\t\t\taoData = oSettings.aoData,\n\t\t\t\taoColumns = oSettings.aoColumns,\n\t\t\t\toAria = oSettings.oLanguage.oAria;\n\t\t\t\n\t\t\t/* No sorting required if server-side or no sorting array */\n\t\t\tif ( !oSettings.oFeatures.bServerSide && \n\t\t\t\t(oSettings.aaSorting.length !== 0 || oSettings.aaSortingFixed !== null) )\n\t\t\t{\n\t\t\t\taaSort = ( oSettings.aaSortingFixed !== null ) ?\n\t\t\t\t\toSettings.aaSortingFixed.concat( oSettings.aaSorting ) :\n\t\t\t\t\toSettings.aaSorting.slice();\n\t\t\t\t\n\t\t\t\t/* If there is a sorting data type, and a function belonging to it, then we need to\n\t\t\t\t * get the data from the developer's function and apply it for this column\n\t\t\t\t */\n\t\t\t\tfor ( i=0 ; i<aaSort.length ; i++ )\n\t\t\t\t{\n\t\t\t\t\tvar iColumn = aaSort[i][0];\n\t\t\t\t\tvar iVisColumn = _fnColumnIndexToVisible( oSettings, iColumn );\n\t\t\t\t\tsDataType = oSettings.aoColumns[ iColumn ].sSortDataType;\n\t\t\t\t\tif ( DataTable.ext.afnSortData[sDataType] )\n\t\t\t\t\t{\n\t\t\t\t\t\tvar aData = DataTable.ext.afnSortData[sDataType].call( \n\t\t\t\t\t\t\toSettings.oInstance, oSettings, iColumn, iVisColumn\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif ( aData.length === aoData.length )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfor ( j=0, jLen=aoData.length ; j<jLen ; j++ )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t_fnSetCellData( oSettings, j, iColumn, aData[j] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_fnLog( oSettings, 0, \"Returned data sort array (col \"+iColumn+\") is the wrong length\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t/* Create a value - key array of the current row positions such that we can use their\n\t\t\t\t * current position during the sort, if values match, in order to perform stable sorting\n\t\t\t\t */\n\t\t\t\tfor ( i=0, iLen=oSettings.aiDisplayMaster.length ; i<iLen ; i++ )\n\t\t\t\t{\n\t\t\t\t\taiOrig[ oSettings.aiDisplayMaster[i] ] = i;\n\t\t\t\t}\n\t\t\n\t\t\t\t/* Build an internal data array which is specific to the sort, so we can get and prep\n\t\t\t\t * the data to be sorted only once, rather than needing to do it every time the sorting\n\t\t\t\t * function runs. This make the sorting function a very simple comparison\n\t\t\t\t */\n\t\t\t\tvar iSortLen = aaSort.length;\n\t\t\t\tvar fnSortFormat, aDataSort;\n\t\t\t\tfor ( i=0, iLen=aoData.length ; i<iLen ; i++ )\n\t\t\t\t{\n\t\t\t\t\tfor ( j=0 ; j<iSortLen ; j++ )\n\t\t\t\t\t{\n\t\t\t\t\t\taDataSort = aoColumns[ aaSort[j][0] ].aDataSort;\n\t\t\n\t\t\t\t\t\tfor ( k=0, kLen=aDataSort.length ; k<kLen ; k++ )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsDataType = aoColumns[ aDataSort[k] ].sType;\n\t\t\t\t\t\t\tfnSortFormat = oSort[ (sDataType ? sDataType : 'string')+\"-pre\" ];\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\taoData[i]._aSortData[ aDataSort[k] ] = fnSortFormat ?\n\t\t\t\t\t\t\t\tfnSortFormat( _fnGetCellData( oSettings, i, aDataSort[k], 'sort' ) ) :\n\t\t\t\t\t\t\t\t_fnGetCellData( oSettings, i, aDataSort[k], 'sort' );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t/* Do the sort - here we want multi-column sorting based on a given data source (column)\n\t\t\t\t * and sorting function (from oSort) in a certain direction. It's reasonably complex to\n\t\t\t\t * follow on it's own, but this is what we want (example two column sorting):\n\t\t\t\t *  fnLocalSorting = function(a,b){\n\t\t\t\t *  \tvar iTest;\n\t\t\t\t *  \tiTest = oSort['string-asc']('data11', 'data12');\n\t\t\t\t *  \tif (iTest !== 0)\n\t\t\t\t *  \t\treturn iTest;\n\t\t\t\t *    iTest = oSort['numeric-desc']('data21', 'data22');\n\t\t\t\t *    if (iTest !== 0)\n\t\t\t\t *  \t\treturn iTest;\n\t\t\t\t *  \treturn oSort['numeric-asc']( aiOrig[a], aiOrig[b] );\n\t\t\t\t *  }\n\t\t\t\t * Basically we have a test for each sorting column, if the data in that column is equal,\n\t\t\t\t * test the next column. If all columns match, then we use a numeric sort on the row \n\t\t\t\t * positions in the original data array to provide a stable sort.\n\t\t\t\t */\n\t\t\t\toSettings.aiDisplayMaster.sort( function ( a, b ) {\n\t\t\t\t\tvar k, l, lLen, iTest, aDataSort, sDataType;\n\t\t\t\t\tfor ( k=0 ; k<iSortLen ; k++ )\n\t\t\t\t\t{\n\t\t\t\t\t\taDataSort = aoColumns[ aaSort[k][0] ].aDataSort;\n\t\t\n\t\t\t\t\t\tfor ( l=0, lLen=aDataSort.length ; l<lLen ; l++ )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsDataType = aoColumns[ aDataSort[l] ].sType;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tiTest = oSort[ (sDataType ? sDataType : 'string')+\"-\"+aaSort[k][1] ](\n\t\t\t\t\t\t\t\taoData[a]._aSortData[ aDataSort[l] ],\n\t\t\t\t\t\t\t\taoData[b]._aSortData[ aDataSort[l] ]\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\n\t\t\t\t\t\t\tif ( iTest !== 0 )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\treturn iTest;\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\t\n\t\t\t\t\treturn oSort['numeric-asc']( aiOrig[a], aiOrig[b] );\n\t\t\t\t} );\n\t\t\t}\n\t\t\t\n\t\t\t/* Alter the sorting classes to take account of the changes */\n\t\t\tif ( (bApplyClasses === undefined || bApplyClasses) && !oSettings.oFeatures.bDeferRender )\n\t\t\t{\n\t\t\t\t_fnSortingClasses( oSettings );\n\t\t\t}\n\t\t\n\t\t\tfor ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )\n\t\t\t{\n\t\t\t\tvar sTitle = aoColumns[i].sTitle.replace( /<.*?>/g, \"\" );\n\t\t\t\tnTh = aoColumns[i].nTh;\n\t\t\t\tnTh.removeAttribute('aria-sort');\n\t\t\t\tnTh.removeAttribute('aria-label');\n\t\t\t\t\n\t\t\t\t/* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */\n\t\t\t\tif ( aoColumns[i].bSortable )\n\t\t\t\t{\n\t\t\t\t\tif ( aaSort.length > 0 && aaSort[0][0] == i )\n\t\t\t\t\t{\n\t\t\t\t\t\tnTh.setAttribute('aria-sort', aaSort[0][1]==\"asc\" ? \"ascending\" : \"descending\" );\n\t\t\t\t\t\t\n\t\t\t\t\t\tvar nextSort = (aoColumns[i].asSorting[ aaSort[0][2]+1 ]) ? \n\t\t\t\t\t\t\taoColumns[i].asSorting[ aaSort[0][2]+1 ] : aoColumns[i].asSorting[0];\n\t\t\t\t\t\tnTh.setAttribute('aria-label', sTitle+\n\t\t\t\t\t\t\t(nextSort==\"asc\" ? oAria.sSortAscending : oAria.sSortDescending) );\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tnTh.setAttribute('aria-label', sTitle+\n\t\t\t\t\t\t\t(aoColumns[i].asSorting[0]==\"asc\" ? oAria.sSortAscending : oAria.sSortDescending) );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tnTh.setAttribute('aria-label', sTitle);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t/* Tell the draw function that we have sorted the data */\n\t\t\toSettings.bSorted = true;\n\t\t\t$(oSettings.oInstance).trigger('sort', oSettings);\n\t\t\t\n\t\t\t/* Copy the master data into the draw array and re-draw */\n\t\t\tif ( oSettings.oFeatures.bFilter )\n\t\t\t{\n\t\t\t\t/* _fnFilter() will redraw the table for us */\n\t\t\t\t_fnFilterComplete( oSettings, oSettings.oPreviousSearch, 1 );\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\toSettings.aiDisplay = oSettings.aiDisplayMaster.slice();\n\t\t\t\toSettings._iDisplayStart = 0; /* reset display back to page 0 */\n\t\t\t\t_fnCalculateEnd( oSettings );\n\t\t\t\t_fnDraw( oSettings );\n\t\t\t}\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Attach a sort handler (click) to a node\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @param {node} nNode node to attach the handler to\n\t\t *  @param {int} iDataIndex column sorting index\n\t\t *  @param {function} [fnCallback] callback function\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnSortAttachListener ( oSettings, nNode, iDataIndex, fnCallback )\n\t\t{\n\t\t\t_fnBindAction( nNode, {}, function (e) {\n\t\t\t\t/* If the column is not sortable - don't to anything */\n\t\t\t\tif ( oSettings.aoColumns[iDataIndex].bSortable === false )\n\t\t\t\t{\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t/*\n\t\t\t\t * This is a little bit odd I admit... I declare a temporary function inside the scope of\n\t\t\t\t * _fnBuildHead and the click handler in order that the code presented here can be used \n\t\t\t\t * twice - once for when bProcessing is enabled, and another time for when it is \n\t\t\t\t * disabled, as we need to perform slightly different actions.\n\t\t\t\t *   Basically the issue here is that the Javascript engine in modern browsers don't \n\t\t\t\t * appear to allow the rendering engine to update the display while it is still executing\n\t\t\t\t * it's thread (well - it does but only after long intervals). This means that the \n\t\t\t\t * 'processing' display doesn't appear for a table sort. To break the js thread up a bit\n\t\t\t\t * I force an execution break by using setTimeout - but this breaks the expected \n\t\t\t\t * thread continuation for the end-developer's point of view (their code would execute\n\t\t\t\t * too early), so we only do it when we absolutely have to.\n\t\t\t\t */\n\t\t\t\tvar fnInnerSorting = function () {\n\t\t\t\t\tvar iColumn, iNextSort;\n\t\t\t\t\t\n\t\t\t\t\t/* If the shift key is pressed then we are multiple column sorting */\n\t\t\t\t\tif ( e.shiftKey )\n\t\t\t\t\t{\n\t\t\t\t\t\t/* Are we already doing some kind of sort on this column? */\n\t\t\t\t\t\tvar bFound = false;\n\t\t\t\t\t\tfor ( var i=0 ; i<oSettings.aaSorting.length ; i++ )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif ( oSettings.aaSorting[i][0] == iDataIndex )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tbFound = true;\n\t\t\t\t\t\t\t\tiColumn = oSettings.aaSorting[i][0];\n\t\t\t\t\t\t\t\tiNextSort = oSettings.aaSorting[i][2]+1;\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tif ( !oSettings.aoColumns[iColumn].asSorting[iNextSort] )\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t/* Reached the end of the sorting options, remove from multi-col sort */\n\t\t\t\t\t\t\t\t\toSettings.aaSorting.splice( i, 1 );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t/* Move onto next sorting direction */\n\t\t\t\t\t\t\t\t\toSettings.aaSorting[i][1] = oSettings.aoColumns[iColumn].asSorting[iNextSort];\n\t\t\t\t\t\t\t\t\toSettings.aaSorting[i][2] = iNextSort;\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\t\n\t\t\t\t\t\t/* No sort yet - add it in */\n\t\t\t\t\t\tif ( bFound === false )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\toSettings.aaSorting.push( [ iDataIndex, \n\t\t\t\t\t\t\t\toSettings.aoColumns[iDataIndex].asSorting[0], 0 ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t/* If no shift key then single column sort */\n\t\t\t\t\t\tif ( oSettings.aaSorting.length == 1 && oSettings.aaSorting[0][0] == iDataIndex )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tiColumn = oSettings.aaSorting[0][0];\n\t\t\t\t\t\t\tiNextSort = oSettings.aaSorting[0][2]+1;\n\t\t\t\t\t\t\tif ( !oSettings.aoColumns[iColumn].asSorting[iNextSort] )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tiNextSort = 0;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\toSettings.aaSorting[0][1] = oSettings.aoColumns[iColumn].asSorting[iNextSort];\n\t\t\t\t\t\t\toSettings.aaSorting[0][2] = iNextSort;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\toSettings.aaSorting.splice( 0, oSettings.aaSorting.length );\n\t\t\t\t\t\t\toSettings.aaSorting.push( [ iDataIndex, \n\t\t\t\t\t\t\t\toSettings.aoColumns[iDataIndex].asSorting[0], 0 ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t/* Run the sort */\n\t\t\t\t\t_fnSort( oSettings );\n\t\t\t\t}; /* /fnInnerSorting */\n\t\t\t\t\n\t\t\t\tif ( !oSettings.oFeatures.bProcessing )\n\t\t\t\t{\n\t\t\t\t\tfnInnerSorting();\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t_fnProcessingDisplay( oSettings, true );\n\t\t\t\t\tsetTimeout( function() {\n\t\t\t\t\t\tfnInnerSorting();\n\t\t\t\t\t\tif ( !oSettings.oFeatures.bServerSide )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_fnProcessingDisplay( oSettings, false );\n\t\t\t\t\t\t}\n\t\t\t\t\t}, 0 );\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t/* Call the user specified callback function - used for async user interaction */\n\t\t\t\tif ( typeof fnCallback == 'function' )\n\t\t\t\t{\n\t\t\t\t\tfnCallback( oSettings );\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Set the sorting classes on the header, Note: it is safe to call this function \n\t\t * when bSort and bSortClasses are false\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnSortingClasses( oSettings )\n\t\t{\n\t\t\tvar i, iLen, j, jLen, iFound;\n\t\t\tvar aaSort, sClass;\n\t\t\tvar iColumns = oSettings.aoColumns.length;\n\t\t\tvar oClasses = oSettings.oClasses;\n\t\t\t\n\t\t\tfor ( i=0 ; i<iColumns ; i++ )\n\t\t\t{\n\t\t\t\tif ( oSettings.aoColumns[i].bSortable )\n\t\t\t\t{\n\t\t\t\t\t$(oSettings.aoColumns[i].nTh).removeClass( oClasses.sSortAsc +\" \"+ oClasses.sSortDesc +\n\t\t\t\t\t\t\" \"+ oSettings.aoColumns[i].sSortingClass );\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif ( oSettings.aaSortingFixed !== null )\n\t\t\t{\n\t\t\t\taaSort = oSettings.aaSortingFixed.concat( oSettings.aaSorting );\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\taaSort = oSettings.aaSorting.slice();\n\t\t\t}\n\t\t\t\n\t\t\t/* Apply the required classes to the header */\n\t\t\tfor ( i=0 ; i<oSettings.aoColumns.length ; i++ )\n\t\t\t{\n\t\t\t\tif ( oSettings.aoColumns[i].bSortable )\n\t\t\t\t{\n\t\t\t\t\tsClass = oSettings.aoColumns[i].sSortingClass;\n\t\t\t\t\tiFound = -1;\n\t\t\t\t\tfor ( j=0 ; j<aaSort.length ; j++ )\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( aaSort[j][0] == i )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsClass = ( aaSort[j][1] == \"asc\" ) ?\n\t\t\t\t\t\t\t\toClasses.sSortAsc : oClasses.sSortDesc;\n\t\t\t\t\t\t\tiFound = j;\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\t$(oSettings.aoColumns[i].nTh).addClass( sClass );\n\t\t\t\t\t\n\t\t\t\t\tif ( oSettings.bJUI )\n\t\t\t\t\t{\n\t\t\t\t\t\t/* jQuery UI uses extra markup */\n\t\t\t\t\t\tvar jqSpan = $(\"span.\"+oClasses.sSortIcon,  oSettings.aoColumns[i].nTh);\n\t\t\t\t\t\tjqSpan.removeClass(oClasses.sSortJUIAsc +\" \"+ oClasses.sSortJUIDesc +\" \"+ \n\t\t\t\t\t\t\toClasses.sSortJUI +\" \"+ oClasses.sSortJUIAscAllowed +\" \"+ oClasses.sSortJUIDescAllowed );\n\t\t\t\t\t\t\n\t\t\t\t\t\tvar sSpanClass;\n\t\t\t\t\t\tif ( iFound == -1 )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t \tsSpanClass = oSettings.aoColumns[i].sSortingClassJUI;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if ( aaSort[iFound][1] == \"asc\" )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsSpanClass = oClasses.sSortJUIAsc;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsSpanClass = oClasses.sSortJUIDesc;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tjqSpan.addClass( sSpanClass );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t/* No sorting on this column, so add the base class. This will have been assigned by\n\t\t\t\t\t * _fnAddColumn\n\t\t\t\t\t */\n\t\t\t\t\t$(oSettings.aoColumns[i].nTh).addClass( oSettings.aoColumns[i].sSortingClass );\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t/* \n\t\t\t * Apply the required classes to the table body\n\t\t\t * Note that this is given as a feature switch since it can significantly slow down a sort\n\t\t\t * on large data sets (adding and removing of classes is always slow at the best of times..)\n\t\t\t * Further to this, note that this code is admittedly fairly ugly. It could be made a lot \n\t\t\t * simpler using jQuery selectors and add/removeClass, but that is significantly slower\n\t\t\t * (on the order of 5 times slower) - hence the direct DOM manipulation here.\n\t\t\t * Note that for deferred drawing we do use jQuery - the reason being that taking the first\n\t\t\t * row found to see if the whole column needs processed can miss classes since the first\n\t\t\t * column might be new.\n\t\t\t */\n\t\t\tsClass = oClasses.sSortColumn;\n\t\t\t\n\t\t\tif ( oSettings.oFeatures.bSort && oSettings.oFeatures.bSortClasses )\n\t\t\t{\n\t\t\t\tvar nTds = _fnGetTdNodes( oSettings );\n\t\t\t\t\n\t\t\t\t/* Determine what the sorting class for each column should be */\n\t\t\t\tvar iClass, iTargetCol;\n\t\t\t\tvar asClasses = [];\n\t\t\t\tfor (i = 0; i < iColumns; i++)\n\t\t\t\t{\n\t\t\t\t\tasClasses.push(\"\");\n\t\t\t\t}\n\t\t\t\tfor (i = 0, iClass = 1; i < aaSort.length; i++)\n\t\t\t\t{\n\t\t\t\t\tiTargetCol = parseInt( aaSort[i][0], 10 );\n\t\t\t\t\tasClasses[iTargetCol] = sClass + iClass;\n\t\t\t\t\t\n\t\t\t\t\tif ( iClass < 3 )\n\t\t\t\t\t{\n\t\t\t\t\t\tiClass++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t/* Make changes to the classes for each cell as needed */\n\t\t\t\tvar reClass = new RegExp(sClass + \"[123]\");\n\t\t\t\tvar sTmpClass, sCurrentClass, sNewClass;\n\t\t\t\tfor ( i=0, iLen=nTds.length; i<iLen; i++ )\n\t\t\t\t{\n\t\t\t\t\t/* Determine which column we're looking at */\n\t\t\t\t\tiTargetCol = i % iColumns;\n\t\t\t\t\t\n\t\t\t\t\t/* What is the full list of classes now */\n\t\t\t\t\tsCurrentClass = nTds[i].className;\n\t\t\t\t\t/* What sorting class should be applied? */\n\t\t\t\t\tsNewClass = asClasses[iTargetCol];\n\t\t\t\t\t/* What would the new full list be if we did a replacement? */\n\t\t\t\t\tsTmpClass = sCurrentClass.replace(reClass, sNewClass);\n\t\t\t\t\t\n\t\t\t\t\tif ( sTmpClass != sCurrentClass )\n\t\t\t\t\t{\n\t\t\t\t\t\t/* We changed something */\n\t\t\t\t\t\tnTds[i].className = $.trim( sTmpClass );\n\t\t\t\t\t}\n\t\t\t\t\telse if ( sNewClass.length > 0 && sCurrentClass.indexOf(sNewClass) == -1 )\n\t\t\t\t\t{\n\t\t\t\t\t\t/* We need to add a class */\n\t\t\t\t\t\tnTds[i].className = sCurrentClass + \" \" + sNewClass;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\t\n\t\t\n\t\t/**\n\t\t * Save the state of a table in a cookie such that the page can be reloaded\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnSaveState ( oSettings )\n\t\t{\n\t\t\tif ( !oSettings.oFeatures.bStateSave || oSettings.bDestroying )\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\t\t\n\t\t\t/* Store the interesting variables */\n\t\t\tvar i, iLen, bInfinite=oSettings.oScroll.bInfinite;\n\t\t\tvar oState = {\n\t\t\t\t\"iCreate\":      new Date().getTime(),\n\t\t\t\t\"iStart\":       (bInfinite ? 0 : oSettings._iDisplayStart),\n\t\t\t\t\"iEnd\":         (bInfinite ? oSettings._iDisplayLength : oSettings._iDisplayEnd),\n\t\t\t\t\"iLength\":      oSettings._iDisplayLength,\n\t\t\t\t\"aaSorting\":    $.extend( true, [], oSettings.aaSorting ),\n\t\t\t\t\"oSearch\":      $.extend( true, {}, oSettings.oPreviousSearch ),\n\t\t\t\t\"aoSearchCols\": $.extend( true, [], oSettings.aoPreSearchCols ),\n\t\t\t\t\"abVisCols\":    []\n\t\t\t};\n\t\t\n\t\t\tfor ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )\n\t\t\t{\n\t\t\t\toState.abVisCols.push( oSettings.aoColumns[i].bVisible );\n\t\t\t}\n\t\t\n\t\t\t_fnCallbackFire( oSettings, \"aoStateSaveParams\", 'stateSaveParams', [oSettings, oState] );\n\t\t\t\n\t\t\toSettings.fnStateSave.call( oSettings.oInstance, oSettings, oState );\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Attempt to load a saved table state from a cookie\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @param {object} oInit DataTables init object so we can override settings\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnLoadState ( oSettings, oInit )\n\t\t{\n\t\t\tif ( !oSettings.oFeatures.bStateSave )\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\t\t\n\t\t\tvar oData = oSettings.fnStateLoad.call( oSettings.oInstance, oSettings );\n\t\t\tif ( !oData )\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\t/* Allow custom and plug-in manipulation functions to alter the saved data set and\n\t\t\t * cancelling of loading by returning false\n\t\t\t */\n\t\t\tvar abStateLoad = _fnCallbackFire( oSettings, 'aoStateLoadParams', 'stateLoadParams', [oSettings, oData] );\n\t\t\tif ( $.inArray( false, abStateLoad ) !== -1 )\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\t/* Store the saved state so it might be accessed at any time */\n\t\t\toSettings.oLoadedState = $.extend( true, {}, oData );\n\t\t\t\n\t\t\t/* Restore key features */\n\t\t\toSettings._iDisplayStart    = oData.iStart;\n\t\t\toSettings.iInitDisplayStart = oData.iStart;\n\t\t\toSettings._iDisplayEnd      = oData.iEnd;\n\t\t\toSettings._iDisplayLength   = oData.iLength;\n\t\t\toSettings.aaSorting         = oData.aaSorting.slice();\n\t\t\toSettings.saved_aaSorting   = oData.aaSorting.slice();\n\t\t\t\n\t\t\t/* Search filtering  */\n\t\t\t$.extend( oSettings.oPreviousSearch, oData.oSearch );\n\t\t\t$.extend( true, oSettings.aoPreSearchCols, oData.aoSearchCols );\n\t\t\t\n\t\t\t/* Column visibility state\n\t\t\t * Pass back visibility settings to the init handler, but to do not here override\n\t\t\t * the init object that the user might have passed in\n\t\t\t */\n\t\t\toInit.saved_aoColumns = [];\n\t\t\tfor ( var i=0 ; i<oData.abVisCols.length ; i++ )\n\t\t\t{\n\t\t\t\toInit.saved_aoColumns[i] = {};\n\t\t\t\toInit.saved_aoColumns[i].bVisible = oData.abVisCols[i];\n\t\t\t}\n\t\t\n\t\t\t_fnCallbackFire( oSettings, 'aoStateLoaded', 'stateLoaded', [oSettings, oData] );\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Create a new cookie with a value to store the state of a table\n\t\t *  @param {string} sName name of the cookie to create\n\t\t *  @param {string} sValue the value the cookie should take\n\t\t *  @param {int} iSecs duration of the cookie\n\t\t *  @param {string} sBaseName sName is made up of the base + file name - this is the base\n\t\t *  @param {function} fnCallback User definable function to modify the cookie\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnCreateCookie ( sName, sValue, iSecs, sBaseName, fnCallback )\n\t\t{\n\t\t\tvar date = new Date();\n\t\t\tdate.setTime( date.getTime()+(iSecs*1000) );\n\t\t\t\n\t\t\t/* \n\t\t\t * Shocking but true - it would appear IE has major issues with having the path not having\n\t\t\t * a trailing slash on it. We need the cookie to be available based on the path, so we\n\t\t\t * have to append the file name to the cookie name. Appalling. Thanks to vex for adding the\n\t\t\t * patch to use at least some of the path\n\t\t\t */\n\t\t\tvar aParts = window.location.pathname.split('/');\n\t\t\tvar sNameFile = sName + '_' + aParts.pop().replace(/[\\/:]/g,\"\").toLowerCase();\n\t\t\tvar sFullCookie, oData;\n\t\t\t\n\t\t\tif ( fnCallback !== null )\n\t\t\t{\n\t\t\t\toData = (typeof $.parseJSON === 'function') ? \n\t\t\t\t\t$.parseJSON( sValue ) : eval( '('+sValue+')' );\n\t\t\t\tsFullCookie = fnCallback( sNameFile, oData, date.toGMTString(),\n\t\t\t\t\taParts.join('/')+\"/\" );\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tsFullCookie = sNameFile + \"=\" + encodeURIComponent(sValue) +\n\t\t\t\t\t\"; expires=\" + date.toGMTString() +\"; path=\" + aParts.join('/')+\"/\";\n\t\t\t}\n\t\t\t\n\t\t\t/* Are we going to go over the cookie limit of 4KiB? If so, try to delete a cookies\n\t\t\t * belonging to DataTables.\n\t\t\t */\n\t\t\tvar\n\t\t\t\taCookies =document.cookie.split(';'),\n\t\t\t\tiNewCookieLen = sFullCookie.split(';')[0].length,\n\t\t\t\taOldCookies = [];\n\t\t\t\n\t\t\tif ( iNewCookieLen+document.cookie.length+10 > 4096 ) /* Magic 10 for padding */\n\t\t\t{\n\t\t\t\tfor ( var i=0, iLen=aCookies.length ; i<iLen ; i++ )\n\t\t\t\t{\n\t\t\t\t\tif ( aCookies[i].indexOf( sBaseName ) != -1 )\n\t\t\t\t\t{\n\t\t\t\t\t\t/* It's a DataTables cookie, so eval it and check the time stamp */\n\t\t\t\t\t\tvar aSplitCookie = aCookies[i].split('=');\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\toData = eval( '('+decodeURIComponent(aSplitCookie[1])+')' );\n\t\t\n\t\t\t\t\t\t\tif ( oData && oData.iCreate )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\taOldCookies.push( {\n\t\t\t\t\t\t\t\t\t\"name\": aSplitCookie[0],\n\t\t\t\t\t\t\t\t\t\"time\": oData.iCreate\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\tcatch( e ) {}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\n\t\t\t\t// Make sure we delete the oldest ones first\n\t\t\t\taOldCookies.sort( function (a, b) {\n\t\t\t\t\treturn b.time - a.time;\n\t\t\t\t} );\n\t\t\n\t\t\t\t// Eliminate as many old DataTables cookies as we need to\n\t\t\t\twhile ( iNewCookieLen + document.cookie.length + 10 > 4096 ) {\n\t\t\t\t\tif ( aOldCookies.length === 0 ) {\n\t\t\t\t\t\t// Deleted all DT cookies and still not enough space. Can't state save\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tvar old = aOldCookies.pop();\n\t\t\t\t\tdocument.cookie = old.name+\"=; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=\"+\n\t\t\t\t\t\taParts.join('/') + \"/\";\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tdocument.cookie = sFullCookie;\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Read an old cookie to get a cookie with an old table state\n\t\t *  @param {string} sName name of the cookie to read\n\t\t *  @returns {string} contents of the cookie - or null if no cookie with that name found\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnReadCookie ( sName )\n\t\t{\n\t\t\tvar\n\t\t\t\taParts = window.location.pathname.split('/'),\n\t\t\t\tsNameEQ = sName + '_' + aParts[aParts.length-1].replace(/[\\/:]/g,\"\").toLowerCase() + '=',\n\t\t\t \tsCookieContents = document.cookie.split(';');\n\t\t\t\n\t\t\tfor( var i=0 ; i<sCookieContents.length ; i++ )\n\t\t\t{\n\t\t\t\tvar c = sCookieContents[i];\n\t\t\t\t\n\t\t\t\twhile (c.charAt(0)==' ')\n\t\t\t\t{\n\t\t\t\t\tc = c.substring(1,c.length);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (c.indexOf(sNameEQ) === 0)\n\t\t\t\t{\n\t\t\t\t\treturn decodeURIComponent( c.substring(sNameEQ.length,c.length) );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Return the settings object for a particular table\n\t\t *  @param {node} nTable table we are using as a dataTable\n\t\t *  @returns {object} Settings object - or null if not found\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnSettingsFromNode ( nTable )\n\t\t{\n\t\t\tfor ( var i=0 ; i<DataTable.settings.length ; i++ )\n\t\t\t{\n\t\t\t\tif ( DataTable.settings[i].nTable === nTable )\n\t\t\t\t{\n\t\t\t\t\treturn DataTable.settings[i];\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\treturn null;\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Return an array with the TR nodes for the table\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @returns {array} TR array\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnGetTrNodes ( oSettings )\n\t\t{\n\t\t\tvar aNodes = [];\n\t\t\tvar aoData = oSettings.aoData;\n\t\t\tfor ( var i=0, iLen=aoData.length ; i<iLen ; i++ )\n\t\t\t{\n\t\t\t\tif ( aoData[i].nTr !== null )\n\t\t\t\t{\n\t\t\t\t\taNodes.push( aoData[i].nTr );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn aNodes;\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Return an flat array with all TD nodes for the table, or row\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @param {int} [iIndividualRow] aoData index to get the nodes for - optional \n\t\t *    if not given then the return array will contain all nodes for the table\n\t\t *  @returns {array} TD array\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnGetTdNodes ( oSettings, iIndividualRow )\n\t\t{\n\t\t\tvar anReturn = [];\n\t\t\tvar iCorrector;\n\t\t\tvar anTds, nTd;\n\t\t\tvar iRow, iRows=oSettings.aoData.length,\n\t\t\t\tiColumn, iColumns, oData, sNodeName, iStart=0, iEnd=iRows;\n\t\t\t\n\t\t\t/* Allow the collection to be limited to just one row */\n\t\t\tif ( iIndividualRow !== undefined )\n\t\t\t{\n\t\t\t\tiStart = iIndividualRow;\n\t\t\t\tiEnd = iIndividualRow+1;\n\t\t\t}\n\t\t\n\t\t\tfor ( iRow=iStart ; iRow<iEnd ; iRow++ )\n\t\t\t{\n\t\t\t\toData = oSettings.aoData[iRow];\n\t\t\t\tif ( oData.nTr !== null )\n\t\t\t\t{\n\t\t\t\t\t/* get the TD child nodes - taking into account text etc nodes */\n\t\t\t\t\tanTds = [];\n\t\t\t\t\tnTd = oData.nTr.firstChild;\n\t\t\t\t\twhile ( nTd )\n\t\t\t\t\t{\n\t\t\t\t\t\tsNodeName = nTd.nodeName.toLowerCase();\n\t\t\t\t\t\tif ( sNodeName == 'td' || sNodeName == 'th' )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tanTds.push( nTd );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tnTd = nTd.nextSibling;\n\t\t\t\t\t}\n\t\t\n\t\t\t\t\tiCorrector = 0;\n\t\t\t\t\tfor ( iColumn=0, iColumns=oSettings.aoColumns.length ; iColumn<iColumns ; iColumn++ )\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( oSettings.aoColumns[iColumn].bVisible )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tanReturn.push( anTds[iColumn-iCorrector] );\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tanReturn.push( oData._anHidden[iColumn] );\n\t\t\t\t\t\t\tiCorrector++;\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\t\treturn anReturn;\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Log an error message\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @param {int} iLevel log error messages, or display them to the user\n\t\t *  @param {string} sMesg error message\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnLog( oSettings, iLevel, sMesg )\n\t\t{\n\t\t\tvar sAlert = (oSettings===null) ?\n\t\t\t\t\"DataTables warning: \"+sMesg :\n\t\t\t\t\"DataTables warning (table id = '\"+oSettings.sTableId+\"'): \"+sMesg;\n\t\t\t\n\t\t\tif ( iLevel === 0 )\n\t\t\t{\n\t\t\t\tif ( DataTable.ext.sErrMode == 'alert' )\n\t\t\t\t{\n\t\t\t\t\talert( sAlert );\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tthrow new Error(sAlert);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\telse if ( window.console && console.log )\n\t\t\t{\n\t\t\t\tconsole.log( sAlert );\n\t\t\t}\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * See if a property is defined on one object, if so assign it to the other object\n\t\t *  @param {object} oRet target object\n\t\t *  @param {object} oSrc source object\n\t\t *  @param {string} sName property\n\t\t *  @param {string} [sMappedName] name to map too - optional, sName used if not given\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnMap( oRet, oSrc, sName, sMappedName )\n\t\t{\n\t\t\tif ( sMappedName === undefined )\n\t\t\t{\n\t\t\t\tsMappedName = sName;\n\t\t\t}\n\t\t\tif ( oSrc[sName] !== undefined )\n\t\t\t{\n\t\t\t\toRet[sMappedName] = oSrc[sName];\n\t\t\t}\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Extend objects - very similar to jQuery.extend, but deep copy objects, and shallow\n\t\t * copy arrays. The reason we need to do this, is that we don't want to deep copy array\n\t\t * init values (such as aaSorting) since the dev wouldn't be able to override them, but\n\t\t * we do want to deep copy arrays.\n\t\t *  @param {object} oOut Object to extend\n\t\t *  @param {object} oExtender Object from which the properties will be applied to oOut\n\t\t *  @returns {object} oOut Reference, just for convenience - oOut === the return.\n\t\t *  @memberof DataTable#oApi\n\t\t *  @todo This doesn't take account of arrays inside the deep copied objects.\n\t\t */\n\t\tfunction _fnExtend( oOut, oExtender )\n\t\t{\n\t\t\tvar val;\n\t\t\t\n\t\t\tfor ( var prop in oExtender )\n\t\t\t{\n\t\t\t\tif ( oExtender.hasOwnProperty(prop) )\n\t\t\t\t{\n\t\t\t\t\tval = oExtender[prop];\n\t\t\n\t\t\t\t\tif ( typeof oInit[prop] === 'object' && val !== null && $.isArray(val) === false )\n\t\t\t\t\t{\n\t\t\t\t\t\t$.extend( true, oOut[prop], val );\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\toOut[prop] = val;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\n\t\t\treturn oOut;\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Bind an event handers to allow a click or return key to activate the callback.\n\t\t * This is good for accessibility since a return on the keyboard will have the\n\t\t * same effect as a click, if the element has focus.\n\t\t *  @param {element} n Element to bind the action to\n\t\t *  @param {object} oData Data object to pass to the triggered function\n\t\t *  @param {function} fn Callback function for when the event is triggered\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnBindAction( n, oData, fn )\n\t\t{\n\t\t\t$(n)\n\t\t\t\t.bind( 'click.DT', oData, function (e) {\n\t\t\t\t\t\tn.blur(); // Remove focus outline for mouse users\n\t\t\t\t\t\tfn(e);\n\t\t\t\t\t} )\n\t\t\t\t.bind( 'keypress.DT', oData, function (e){\n\t\t\t\t\tif ( e.which === 13 ) {\n\t\t\t\t\t\tfn(e);\n\t\t\t\t\t} } )\n\t\t\t\t.bind( 'selectstart.DT', function () {\n\t\t\t\t\t/* Take the brutal approach to cancelling text selection */\n\t\t\t\t\treturn false;\n\t\t\t\t\t} );\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Register a callback function. Easily allows a callback function to be added to\n\t\t * an array store of callback functions that can then all be called together.\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @param {string} sStore Name of the array storage for the callbacks in oSettings\n\t\t *  @param {function} fn Function to be called back\n\t\t *  @param {string} sName Identifying name for the callback (i.e. a label)\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnCallbackReg( oSettings, sStore, fn, sName )\n\t\t{\n\t\t\tif ( fn )\n\t\t\t{\n\t\t\t\toSettings[sStore].push( {\n\t\t\t\t\t\"fn\": fn,\n\t\t\t\t\t\"sName\": sName\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Fire callback functions and trigger events. Note that the loop over the callback\n\t\t * array store is done backwards! Further note that you do not want to fire off triggers\n\t\t * in time sensitive applications (for example cell creation) as its slow.\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @param {string} sStore Name of the array storage for the callbacks in oSettings\n\t\t *  @param {string} sTrigger Name of the jQuery custom event to trigger. If null no trigger\n\t\t *    is fired\n\t\t *  @param {array} aArgs Array of arguments to pass to the callback function / trigger\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnCallbackFire( oSettings, sStore, sTrigger, aArgs )\n\t\t{\n\t\t\tvar aoStore = oSettings[sStore];\n\t\t\tvar aRet =[];\n\t\t\n\t\t\tfor ( var i=aoStore.length-1 ; i>=0 ; i-- )\n\t\t\t{\n\t\t\t\taRet.push( aoStore[i].fn.apply( oSettings.oInstance, aArgs ) );\n\t\t\t}\n\t\t\n\t\t\tif ( sTrigger !== null )\n\t\t\t{\n\t\t\t\t$(oSettings.oInstance).trigger(sTrigger, aArgs);\n\t\t\t}\n\t\t\n\t\t\treturn aRet;\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * JSON stringify. If JSON.stringify it provided by the browser, json2.js or any other\n\t\t * library, then we use that as it is fast, safe and accurate. If the function isn't \n\t\t * available then we need to built it ourselves - the inspiration for this function comes\n\t\t * from Craig Buckler ( http://www.sitepoint.com/javascript-json-serialization/ ). It is\n\t\t * not perfect and absolutely should not be used as a replacement to json2.js - but it does\n\t\t * do what we need, without requiring a dependency for DataTables.\n\t\t *  @param {object} o JSON object to be converted\n\t\t *  @returns {string} JSON string\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tvar _fnJsonString = (window.JSON) ? JSON.stringify : function( o )\n\t\t{\n\t\t\t/* Not an object or array */\n\t\t\tvar sType = typeof o;\n\t\t\tif (sType !== \"object\" || o === null)\n\t\t\t{\n\t\t\t\t// simple data type\n\t\t\t\tif (sType === \"string\")\n\t\t\t\t{\n\t\t\t\t\to = '\"'+o+'\"';\n\t\t\t\t}\n\t\t\t\treturn o+\"\";\n\t\t\t}\n\t\t\n\t\t\t/* If object or array, need to recurse over it */\n\t\t\tvar\n\t\t\t\tsProp, mValue,\n\t\t\t\tjson = [],\n\t\t\t\tbArr = $.isArray(o);\n\t\t\t\n\t\t\tfor (sProp in o)\n\t\t\t{\n\t\t\t\tmValue = o[sProp];\n\t\t\t\tsType = typeof mValue;\n\t\t\n\t\t\t\tif (sType === \"string\")\n\t\t\t\t{\n\t\t\t\t\tmValue = '\"'+mValue+'\"';\n\t\t\t\t}\n\t\t\t\telse if (sType === \"object\" && mValue !== null)\n\t\t\t\t{\n\t\t\t\t\tmValue = _fnJsonString(mValue);\n\t\t\t\t}\n\t\t\n\t\t\t\tjson.push((bArr ? \"\" : '\"'+sProp+'\":') + mValue);\n\t\t\t}\n\t\t\n\t\t\treturn (bArr ? \"[\" : \"{\") + json + (bArr ? \"]\" : \"}\");\n\t\t};\n\t\t\n\t\t\n\t\t/**\n\t\t * From some browsers (specifically IE6/7) we need special handling to work around browser\n\t\t * bugs - this function is used to detect when these workarounds are needed.\n\t\t *  @param {object} oSettings dataTables settings object\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnBrowserDetect( oSettings )\n\t\t{\n\t\t\t/* IE6/7 will oversize a width 100% element inside a scrolling element, to include the\n\t\t\t * width of the scrollbar, while other browsers ensure the inner element is contained\n\t\t\t * without forcing scrolling\n\t\t\t */\n\t\t\tvar n = $(\n\t\t\t\t'<div style=\"position:absolute; top:0; left:0; height:1px; width:1px; overflow:hidden\">'+\n\t\t\t\t\t'<div style=\"position:absolute; top:1px; left:1px; width:100px; overflow:scroll;\">'+\n\t\t\t\t\t\t'<div id=\"DT_BrowserTest\" style=\"width:100%; height:10px;\"></div>'+\n\t\t\t\t\t'</div>'+\n\t\t\t\t'</div>')[0];\n\t\t\n\t\t\tdocument.body.appendChild( n );\n\t\t\toSettings.oBrowser.bScrollOversize = $('#DT_BrowserTest', n)[0].offsetWidth === 100 ? true : false;\n\t\t\tdocument.body.removeChild( n );\n\t\t}\n\t\t\n\n\t\t/**\n\t\t * Perform a jQuery selector action on the table's TR elements (from the tbody) and\n\t\t * return the resulting jQuery object.\n\t\t *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on\n\t\t *  @param {object} [oOpts] Optional parameters for modifying the rows to be included\n\t\t *  @param {string} [oOpts.filter=none] Select TR elements that meet the current filter\n\t\t *    criterion (\"applied\") or all TR elements (i.e. no filter).\n\t\t *  @param {string} [oOpts.order=current] Order of the TR elements in the processed array.\n\t\t *    Can be either 'current', whereby the current sorting of the table is used, or\n\t\t *    'original' whereby the original order the data was read into the table is used.\n\t\t *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page\n\t\t *    (\"current\") or not (\"all\"). If 'current' is given, then order is assumed to be \n\t\t *    'current' and filter is 'applied', regardless of what they might be given as.\n\t\t *  @returns {object} jQuery object, filtered by the given selector.\n\t\t *  @dtopt API\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready(function() {\n\t\t *      var oTable = $('#example').dataTable();\n\t\t *\n\t\t *      // Highlight every second row\n\t\t *      oTable.$('tr:odd').css('backgroundColor', 'blue');\n\t\t *    } );\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready(function() {\n\t\t *      var oTable = $('#example').dataTable();\n\t\t *\n\t\t *      // Filter to rows with 'Webkit' in them, add a background colour and then\n\t\t *      // remove the filter, thus highlighting the 'Webkit' rows only.\n\t\t *      oTable.fnFilter('Webkit');\n\t\t *      oTable.$('tr', {\"filter\": \"applied\"}).css('backgroundColor', 'blue');\n\t\t *      oTable.fnFilter('');\n\t\t *    } );\n\t\t */\n\t\tthis.$ = function ( sSelector, oOpts )\n\t\t{\n\t\t\tvar i, iLen, a = [], tr;\n\t\t\tvar oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );\n\t\t\tvar aoData = oSettings.aoData;\n\t\t\tvar aiDisplay = oSettings.aiDisplay;\n\t\t\tvar aiDisplayMaster = oSettings.aiDisplayMaster;\n\t\t\n\t\t\tif ( !oOpts )\n\t\t\t{\n\t\t\t\toOpts = {};\n\t\t\t}\n\t\t\n\t\t\toOpts = $.extend( {}, {\n\t\t\t\t\"filter\": \"none\", // applied\n\t\t\t\t\"order\": \"current\", // \"original\"\n\t\t\t\t\"page\": \"all\" // current\n\t\t\t}, oOpts );\n\t\t\n\t\t\t// Current page implies that order=current and fitler=applied, since it is fairly\n\t\t\t// senseless otherwise\n\t\t\tif ( oOpts.page == 'current' )\n\t\t\t{\n\t\t\t\tfor ( i=oSettings._iDisplayStart, iLen=oSettings.fnDisplayEnd() ; i<iLen ; i++ )\n\t\t\t\t{\n\t\t\t\t\ttr = aoData[ aiDisplay[i] ].nTr;\n\t\t\t\t\tif ( tr )\n\t\t\t\t\t{\n\t\t\t\t\t\ta.push( tr );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if ( oOpts.order == \"current\" && oOpts.filter == \"none\" )\n\t\t\t{\n\t\t\t\tfor ( i=0, iLen=aiDisplayMaster.length ; i<iLen ; i++ )\n\t\t\t\t{\n\t\t\t\t\ttr = aoData[ aiDisplayMaster[i] ].nTr;\n\t\t\t\t\tif ( tr )\n\t\t\t\t\t{\n\t\t\t\t\t\ta.push( tr );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if ( oOpts.order == \"current\" && oOpts.filter == \"applied\" )\n\t\t\t{\n\t\t\t\tfor ( i=0, iLen=aiDisplay.length ; i<iLen ; i++ )\n\t\t\t\t{\n\t\t\t\t\ttr = aoData[ aiDisplay[i] ].nTr;\n\t\t\t\t\tif ( tr )\n\t\t\t\t\t{\n\t\t\t\t\t\ta.push( tr );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if ( oOpts.order == \"original\" && oOpts.filter == \"none\" )\n\t\t\t{\n\t\t\t\tfor ( i=0, iLen=aoData.length ; i<iLen ; i++ )\n\t\t\t\t{\n\t\t\t\t\ttr = aoData[ i ].nTr ;\n\t\t\t\t\tif ( tr )\n\t\t\t\t\t{\n\t\t\t\t\t\ta.push( tr );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if ( oOpts.order == \"original\" && oOpts.filter == \"applied\" )\n\t\t\t{\n\t\t\t\tfor ( i=0, iLen=aoData.length ; i<iLen ; i++ )\n\t\t\t\t{\n\t\t\t\t\ttr = aoData[ i ].nTr;\n\t\t\t\t\tif ( $.inArray( i, aiDisplay ) !== -1 && tr )\n\t\t\t\t\t{\n\t\t\t\t\t\ta.push( tr );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_fnLog( oSettings, 1, \"Unknown selection options\" );\n\t\t\t}\n\t\t\n\t\t\t/* We need to filter on the TR elements and also 'find' in their descendants\n\t\t\t * to make the selector act like it would in a full table - so we need\n\t\t\t * to build both results and then combine them together\n\t\t\t */\n\t\t\tvar jqA = $(a);\n\t\t\tvar jqTRs = jqA.filter( sSelector );\n\t\t\tvar jqDescendants = jqA.find( sSelector );\n\t\t\n\t\t\treturn $( [].concat($.makeArray(jqTRs), $.makeArray(jqDescendants)) );\n\t\t};\n\t\t\n\t\t\n\t\t/**\n\t\t * Almost identical to $ in operation, but in this case returns the data for the matched\n\t\t * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes\n\t\t * rather than any descendants, so the data can be obtained for the row/cell. If matching\n\t\t * rows are found, the data returned is the original data array/object that was used to  \n\t\t * create the row (or a generated array if from a DOM source).\n\t\t *\n\t\t * This method is often useful in-combination with $ where both functions are given the\n\t\t * same parameters and the array indexes will match identically.\n\t\t *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on\n\t\t *  @param {object} [oOpts] Optional parameters for modifying the rows to be included\n\t\t *  @param {string} [oOpts.filter=none] Select elements that meet the current filter\n\t\t *    criterion (\"applied\") or all elements (i.e. no filter).\n\t\t *  @param {string} [oOpts.order=current] Order of the data in the processed array.\n\t\t *    Can be either 'current', whereby the current sorting of the table is used, or\n\t\t *    'original' whereby the original order the data was read into the table is used.\n\t\t *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page\n\t\t *    (\"current\") or not (\"all\"). If 'current' is given, then order is assumed to be \n\t\t *    'current' and filter is 'applied', regardless of what they might be given as.\n\t\t *  @returns {array} Data for the matched elements. If any elements, as a result of the\n\t\t *    selector, were not TR, TD or TH elements in the DataTable, they will have a null \n\t\t *    entry in the array.\n\t\t *  @dtopt API\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready(function() {\n\t\t *      var oTable = $('#example').dataTable();\n\t\t *\n\t\t *      // Get the data from the first row in the table\n\t\t *      var data = oTable._('tr:first');\n\t\t *\n\t\t *      // Do something useful with the data\n\t\t *      alert( \"First cell is: \"+data[0] );\n\t\t *    } );\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready(function() {\n\t\t *      var oTable = $('#example').dataTable();\n\t\t *\n\t\t *      // Filter to 'Webkit' and get all data for \n\t\t *      oTable.fnFilter('Webkit');\n\t\t *      var data = oTable._('tr', {\"filter\": \"applied\"});\n\t\t *      \n\t\t *      // Do something with the data\n\t\t *      alert( data.length+\" rows matched the filter\" );\n\t\t *    } );\n\t\t */\n\t\tthis._ = function ( sSelector, oOpts )\n\t\t{\n\t\t\tvar aOut = [];\n\t\t\tvar i, iLen, iIndex;\n\t\t\tvar aTrs = this.$( sSelector, oOpts );\n\t\t\n\t\t\tfor ( i=0, iLen=aTrs.length ; i<iLen ; i++ )\n\t\t\t{\n\t\t\t\taOut.push( this.fnGetData(aTrs[i]) );\n\t\t\t}\n\t\t\n\t\t\treturn aOut;\n\t\t};\n\t\t\n\t\t\n\t\t/**\n\t\t * Add a single new row or multiple rows of data to the table. Please note\n\t\t * that this is suitable for client-side processing only - if you are using \n\t\t * server-side processing (i.e. \"bServerSide\": true), then to add data, you\n\t\t * must add it to the data source, i.e. the server-side, through an Ajax call.\n\t\t *  @param {array|object} mData The data to be added to the table. This can be:\n\t\t *    <ul>\n\t\t *      <li>1D array of data - add a single row with the data provided</li>\n\t\t *      <li>2D array of arrays - add multiple rows in a single call</li>\n\t\t *      <li>object - data object when using <i>mData</i></li>\n\t\t *      <li>array of objects - multiple data objects when using <i>mData</i></li>\n\t\t *    </ul>\n\t\t *  @param {bool} [bRedraw=true] redraw the table or not\n\t\t *  @returns {array} An array of integers, representing the list of indexes in \n\t\t *    <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to \n\t\t *    the table.\n\t\t *  @dtopt API\n\t\t *\n\t\t *  @example\n\t\t *    // Global var for counter\n\t\t *    var giCount = 2;\n\t\t *    \n\t\t *    $(document).ready(function() {\n\t\t *      $('#example').dataTable();\n\t\t *    } );\n\t\t *    \n\t\t *    function fnClickAddRow() {\n\t\t *      $('#example').dataTable().fnAddData( [\n\t\t *        giCount+\".1\",\n\t\t *        giCount+\".2\",\n\t\t *        giCount+\".3\",\n\t\t *        giCount+\".4\" ]\n\t\t *      );\n\t\t *        \n\t\t *      giCount++;\n\t\t *    }\n\t\t */\n\t\tthis.fnAddData = function( mData, bRedraw )\n\t\t{\n\t\t\tif ( mData.length === 0 )\n\t\t\t{\n\t\t\t\treturn [];\n\t\t\t}\n\t\t\t\n\t\t\tvar aiReturn = [];\n\t\t\tvar iTest;\n\t\t\t\n\t\t\t/* Find settings from table node */\n\t\t\tvar oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );\n\t\t\t\n\t\t\t/* Check if we want to add multiple rows or not */\n\t\t\tif ( typeof mData[0] === \"object\" && mData[0] !== null )\n\t\t\t{\n\t\t\t\tfor ( var i=0 ; i<mData.length ; i++ )\n\t\t\t\t{\n\t\t\t\t\tiTest = _fnAddData( oSettings, mData[i] );\n\t\t\t\t\tif ( iTest == -1 )\n\t\t\t\t\t{\n\t\t\t\t\t\treturn aiReturn;\n\t\t\t\t\t}\n\t\t\t\t\taiReturn.push( iTest );\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tiTest = _fnAddData( oSettings, mData );\n\t\t\t\tif ( iTest == -1 )\n\t\t\t\t{\n\t\t\t\t\treturn aiReturn;\n\t\t\t\t}\n\t\t\t\taiReturn.push( iTest );\n\t\t\t}\n\t\t\t\n\t\t\toSettings.aiDisplay = oSettings.aiDisplayMaster.slice();\n\t\t\t\n\t\t\tif ( bRedraw === undefined || bRedraw )\n\t\t\t{\n\t\t\t\t_fnReDraw( oSettings );\n\t\t\t}\n\t\t\treturn aiReturn;\n\t\t};\n\t\t\n\t\t\n\t\t/**\n\t\t * This function will make DataTables recalculate the column sizes, based on the data \n\t\t * contained in the table and the sizes applied to the columns (in the DOM, CSS or \n\t\t * through the sWidth parameter). This can be useful when the width of the table's \n\t\t * parent element changes (for example a window resize).\n\t\t *  @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to\n\t\t *  @dtopt API\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready(function() {\n\t\t *      var oTable = $('#example').dataTable( {\n\t\t *        \"sScrollY\": \"200px\",\n\t\t *        \"bPaginate\": false\n\t\t *      } );\n\t\t *      \n\t\t *      $(window).bind('resize', function () {\n\t\t *        oTable.fnAdjustColumnSizing();\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\tthis.fnAdjustColumnSizing = function ( bRedraw )\n\t\t{\n\t\t\tvar oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);\n\t\t\t_fnAdjustColumnSizing( oSettings );\n\t\t\t\n\t\t\tif ( bRedraw === undefined || bRedraw )\n\t\t\t{\n\t\t\t\tthis.fnDraw( false );\n\t\t\t}\n\t\t\telse if ( oSettings.oScroll.sX !== \"\" || oSettings.oScroll.sY !== \"\" )\n\t\t\t{\n\t\t\t\t/* If not redrawing, but scrolling, we want to apply the new column sizes anyway */\n\t\t\t\tthis.oApi._fnScrollDraw(oSettings);\n\t\t\t}\n\t\t};\n\t\t\n\t\t\n\t\t/**\n\t\t * Quickly and simply clear a table\n\t\t *  @param {bool} [bRedraw=true] redraw the table or not\n\t\t *  @dtopt API\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready(function() {\n\t\t *      var oTable = $('#example').dataTable();\n\t\t *      \n\t\t *      // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...)\n\t\t *      oTable.fnClearTable();\n\t\t *    } );\n\t\t */\n\t\tthis.fnClearTable = function( bRedraw )\n\t\t{\n\t\t\t/* Find settings from table node */\n\t\t\tvar oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );\n\t\t\t_fnClearTable( oSettings );\n\t\t\t\n\t\t\tif ( bRedraw === undefined || bRedraw )\n\t\t\t{\n\t\t\t\t_fnDraw( oSettings );\n\t\t\t}\n\t\t};\n\t\t\n\t\t\n\t\t/**\n\t\t * The exact opposite of 'opening' a row, this function will close any rows which \n\t\t * are currently 'open'.\n\t\t *  @param {node} nTr the table row to 'close'\n\t\t *  @returns {int} 0 on success, or 1 if failed (can't find the row)\n\t\t *  @dtopt API\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready(function() {\n\t\t *      var oTable;\n\t\t *      \n\t\t *      // 'open' an information row when a row is clicked on\n\t\t *      $('#example tbody tr').click( function () {\n\t\t *        if ( oTable.fnIsOpen(this) ) {\n\t\t *          oTable.fnClose( this );\n\t\t *        } else {\n\t\t *          oTable.fnOpen( this, \"Temporary row opened\", \"info_row\" );\n\t\t *        }\n\t\t *      } );\n\t\t *      \n\t\t *      oTable = $('#example').dataTable();\n\t\t *    } );\n\t\t */\n\t\tthis.fnClose = function( nTr )\n\t\t{\n\t\t\t/* Find settings from table node */\n\t\t\tvar oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );\n\t\t\t\n\t\t\tfor ( var i=0 ; i<oSettings.aoOpenRows.length ; i++ )\n\t\t\t{\n\t\t\t\tif ( oSettings.aoOpenRows[i].nParent == nTr )\n\t\t\t\t{\n\t\t\t\t\tvar nTrParent = oSettings.aoOpenRows[i].nTr.parentNode;\n\t\t\t\t\tif ( nTrParent )\n\t\t\t\t\t{\n\t\t\t\t\t\t/* Remove it if it is currently on display */\n\t\t\t\t\t\tnTrParent.removeChild( oSettings.aoOpenRows[i].nTr );\n\t\t\t\t\t}\n\t\t\t\t\toSettings.aoOpenRows.splice( i, 1 );\n\t\t\t\t\treturn 0;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn 1;\n\t\t};\n\t\t\n\t\t\n\t\t/**\n\t\t * Remove a row for the table\n\t\t *  @param {mixed} mTarget The index of the row from aoData to be deleted, or\n\t\t *    the TR element you want to delete\n\t\t *  @param {function|null} [fnCallBack] Callback function\n\t\t *  @param {bool} [bRedraw=true] Redraw the table or not\n\t\t *  @returns {array} The row that was deleted\n\t\t *  @dtopt API\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready(function() {\n\t\t *      var oTable = $('#example').dataTable();\n\t\t *      \n\t\t *      // Immediately remove the first row\n\t\t *      oTable.fnDeleteRow( 0 );\n\t\t *    } );\n\t\t */\n\t\tthis.fnDeleteRow = function( mTarget, fnCallBack, bRedraw )\n\t\t{\n\t\t\t/* Find settings from table node */\n\t\t\tvar oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );\n\t\t\tvar i, iLen, iAODataIndex;\n\t\t\t\n\t\t\tiAODataIndex = (typeof mTarget === 'object') ? \n\t\t\t\t_fnNodeToDataIndex(oSettings, mTarget) : mTarget;\n\t\t\t\n\t\t\t/* Return the data array from this row */\n\t\t\tvar oData = oSettings.aoData.splice( iAODataIndex, 1 );\n\t\t\n\t\t\t/* Update the _DT_RowIndex parameter */\n\t\t\tfor ( i=0, iLen=oSettings.aoData.length ; i<iLen ; i++ )\n\t\t\t{\n\t\t\t\tif ( oSettings.aoData[i].nTr !== null )\n\t\t\t\t{\n\t\t\t\t\toSettings.aoData[i].nTr._DT_RowIndex = i;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t/* Remove the target row from the search array */\n\t\t\tvar iDisplayIndex = $.inArray( iAODataIndex, oSettings.aiDisplay );\n\t\t\toSettings.asDataSearch.splice( iDisplayIndex, 1 );\n\t\t\t\n\t\t\t/* Delete from the display arrays */\n\t\t\t_fnDeleteIndex( oSettings.aiDisplayMaster, iAODataIndex );\n\t\t\t_fnDeleteIndex( oSettings.aiDisplay, iAODataIndex );\n\t\t\t\n\t\t\t/* If there is a user callback function - call it */\n\t\t\tif ( typeof fnCallBack === \"function\" )\n\t\t\t{\n\t\t\t\tfnCallBack.call( this, oSettings, oData );\n\t\t\t}\n\t\t\t\n\t\t\t/* Check for an 'overflow' they case for displaying the table */\n\t\t\tif ( oSettings._iDisplayStart >= oSettings.fnRecordsDisplay() )\n\t\t\t{\n\t\t\t\toSettings._iDisplayStart -= oSettings._iDisplayLength;\n\t\t\t\tif ( oSettings._iDisplayStart < 0 )\n\t\t\t\t{\n\t\t\t\t\toSettings._iDisplayStart = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif ( bRedraw === undefined || bRedraw )\n\t\t\t{\n\t\t\t\t_fnCalculateEnd( oSettings );\n\t\t\t\t_fnDraw( oSettings );\n\t\t\t}\n\t\t\t\n\t\t\treturn oData;\n\t\t};\n\t\t\n\t\t\n\t\t/**\n\t\t * Restore the table to it's original state in the DOM by removing all of DataTables \n\t\t * enhancements, alterations to the DOM structure of the table and event listeners.\n\t\t *  @param {boolean} [bRemove=false] Completely remove the table from the DOM\n\t\t *  @dtopt API\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready(function() {\n\t\t *      // This example is fairly pointless in reality, but shows how fnDestroy can be used\n\t\t *      var oTable = $('#example').dataTable();\n\t\t *      oTable.fnDestroy();\n\t\t *    } );\n\t\t */\n\t\tthis.fnDestroy = function ( bRemove )\n\t\t{\n\t\t\tvar oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );\n\t\t\tvar nOrig = oSettings.nTableWrapper.parentNode;\n\t\t\tvar nBody = oSettings.nTBody;\n\t\t\tvar i, iLen;\n\t\t\n\t\t\tbRemove = (bRemove===undefined) ? false : bRemove;\n\t\t\t\n\t\t\t/* Flag to note that the table is currently being destroyed - no action should be taken */\n\t\t\toSettings.bDestroying = true;\n\t\t\t\n\t\t\t/* Fire off the destroy callbacks for plug-ins etc */\n\t\t\t_fnCallbackFire( oSettings, \"aoDestroyCallback\", \"destroy\", [oSettings] );\n\t\t\n\t\t\t/* If the table is not being removed, restore the hidden columns */\n\t\t\tif ( !bRemove )\n\t\t\t{\n\t\t\t\tfor ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )\n\t\t\t\t{\n\t\t\t\t\tif ( oSettings.aoColumns[i].bVisible === false )\n\t\t\t\t\t{\n\t\t\t\t\t\tthis.fnSetColumnVis( i, true );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t/* Blitz all DT events */\n\t\t\t$(oSettings.nTableWrapper).find('*').andSelf().unbind('.DT');\n\t\t\t\n\t\t\t/* If there is an 'empty' indicator row, remove it */\n\t\t\t$('tbody>tr>td.'+oSettings.oClasses.sRowEmpty, oSettings.nTable).parent().remove();\n\t\t\t\n\t\t\t/* When scrolling we had to break the table up - restore it */\n\t\t\tif ( oSettings.nTable != oSettings.nTHead.parentNode )\n\t\t\t{\n\t\t\t\t$(oSettings.nTable).children('thead').remove();\n\t\t\t\toSettings.nTable.appendChild( oSettings.nTHead );\n\t\t\t}\n\t\t\t\n\t\t\tif ( oSettings.nTFoot && oSettings.nTable != oSettings.nTFoot.parentNode )\n\t\t\t{\n\t\t\t\t$(oSettings.nTable).children('tfoot').remove();\n\t\t\t\toSettings.nTable.appendChild( oSettings.nTFoot );\n\t\t\t}\n\t\t\t\n\t\t\t/* Remove the DataTables generated nodes, events and classes */\n\t\t\toSettings.nTable.parentNode.removeChild( oSettings.nTable );\n\t\t\t$(oSettings.nTableWrapper).remove();\n\t\t\t\n\t\t\toSettings.aaSorting = [];\n\t\t\toSettings.aaSortingFixed = [];\n\t\t\t_fnSortingClasses( oSettings );\n\t\t\t\n\t\t\t$(_fnGetTrNodes( oSettings )).removeClass( oSettings.asStripeClasses.join(' ') );\n\t\t\t\n\t\t\t$('th, td', oSettings.nTHead).removeClass( [\n\t\t\t\toSettings.oClasses.sSortable,\n\t\t\t\toSettings.oClasses.sSortableAsc,\n\t\t\t\toSettings.oClasses.sSortableDesc,\n\t\t\t\toSettings.oClasses.sSortableNone ].join(' ')\n\t\t\t);\n\t\t\tif ( oSettings.bJUI )\n\t\t\t{\n\t\t\t\t$('th span.'+oSettings.oClasses.sSortIcon\n\t\t\t\t\t+ ', td span.'+oSettings.oClasses.sSortIcon, oSettings.nTHead).remove();\n\t\t\n\t\t\t\t$('th, td', oSettings.nTHead).each( function () {\n\t\t\t\t\tvar jqWrapper = $('div.'+oSettings.oClasses.sSortJUIWrapper, this);\n\t\t\t\t\tvar kids = jqWrapper.contents();\n\t\t\t\t\t$(this).append( kids );\n\t\t\t\t\tjqWrapper.remove();\n\t\t\t\t} );\n\t\t\t}\n\t\t\t\n\t\t\t/* Add the TR elements back into the table in their original order */\n\t\t\tif ( !bRemove && oSettings.nTableReinsertBefore )\n\t\t\t{\n\t\t\t\tnOrig.insertBefore( oSettings.nTable, oSettings.nTableReinsertBefore );\n\t\t\t}\n\t\t\telse if ( !bRemove )\n\t\t\t{\n\t\t\t\tnOrig.appendChild( oSettings.nTable );\n\t\t\t}\n\t\t\n\t\t\tfor ( i=0, iLen=oSettings.aoData.length ; i<iLen ; i++ )\n\t\t\t{\n\t\t\t\tif ( oSettings.aoData[i].nTr !== null )\n\t\t\t\t{\n\t\t\t\t\tnBody.appendChild( oSettings.aoData[i].nTr );\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t/* Restore the width of the original table */\n\t\t\tif ( oSettings.oFeatures.bAutoWidth === true )\n\t\t\t{\n\t\t\t  oSettings.nTable.style.width = _fnStringToCss(oSettings.sDestroyWidth);\n\t\t\t}\n\t\t\t\n\t\t\t/* If the were originally stripe classes - then we add them back here. Note\n\t\t\t * this is not fool proof (for example if not all rows had stripe classes - but\n\t\t\t * it's a good effort without getting carried away\n\t\t\t */\n\t\t\tiLen = oSettings.asDestroyStripes.length;\n\t\t\tif (iLen)\n\t\t\t{\n\t\t\t\tvar anRows = $(nBody).children('tr');\n\t\t\t\tfor ( i=0 ; i<iLen ; i++ )\n\t\t\t\t{\n\t\t\t\t\tanRows.filter(':nth-child(' + iLen + 'n + ' + i + ')').addClass( oSettings.asDestroyStripes[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t/* Remove the settings object from the settings array */\n\t\t\tfor ( i=0, iLen=DataTable.settings.length ; i<iLen ; i++ )\n\t\t\t{\n\t\t\t\tif ( DataTable.settings[i] == oSettings )\n\t\t\t\t{\n\t\t\t\t\tDataTable.settings.splice( i, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t/* End it all */\n\t\t\toSettings = null;\n\t\t\toInit = null;\n\t\t};\n\t\t\n\t\t\n\t\t/**\n\t\t * Redraw the table\n\t\t *  @param {bool} [bComplete=true] Re-filter and resort (if enabled) the table before the draw.\n\t\t *  @dtopt API\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready(function() {\n\t\t *      var oTable = $('#example').dataTable();\n\t\t *      \n\t\t *      // Re-draw the table - you wouldn't want to do it here, but it's an example :-)\n\t\t *      oTable.fnDraw();\n\t\t *    } );\n\t\t */\n\t\tthis.fnDraw = function( bComplete )\n\t\t{\n\t\t\tvar oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );\n\t\t\tif ( bComplete === false )\n\t\t\t{\n\t\t\t\t_fnCalculateEnd( oSettings );\n\t\t\t\t_fnDraw( oSettings );\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_fnReDraw( oSettings );\n\t\t\t}\n\t\t};\n\t\t\n\t\t\n\t\t/**\n\t\t * Filter the input based on data\n\t\t *  @param {string} sInput String to filter the table on\n\t\t *  @param {int|null} [iColumn] Column to limit filtering to\n\t\t *  @param {bool} [bRegex=false] Treat as regular expression or not\n\t\t *  @param {bool} [bSmart=true] Perform smart filtering or not\n\t\t *  @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es)\n\t\t *  @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false)\n\t\t *  @dtopt API\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready(function() {\n\t\t *      var oTable = $('#example').dataTable();\n\t\t *      \n\t\t *      // Sometime later - filter...\n\t\t *      oTable.fnFilter( 'test string' );\n\t\t *    } );\n\t\t */\n\t\tthis.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive )\n\t\t{\n\t\t\tvar oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );\n\t\t\t\n\t\t\tif ( !oSettings.oFeatures.bFilter )\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\tif ( bRegex === undefined || bRegex === null )\n\t\t\t{\n\t\t\t\tbRegex = false;\n\t\t\t}\n\t\t\t\n\t\t\tif ( bSmart === undefined || bSmart === null )\n\t\t\t{\n\t\t\t\tbSmart = true;\n\t\t\t}\n\t\t\t\n\t\t\tif ( bShowGlobal === undefined || bShowGlobal === null )\n\t\t\t{\n\t\t\t\tbShowGlobal = true;\n\t\t\t}\n\t\t\t\n\t\t\tif ( bCaseInsensitive === undefined || bCaseInsensitive === null )\n\t\t\t{\n\t\t\t\tbCaseInsensitive = true;\n\t\t\t}\n\t\t\t\n\t\t\tif ( iColumn === undefined || iColumn === null )\n\t\t\t{\n\t\t\t\t/* Global filter */\n\t\t\t\t_fnFilterComplete( oSettings, {\n\t\t\t\t\t\"sSearch\":sInput+\"\",\n\t\t\t\t\t\"bRegex\": bRegex,\n\t\t\t\t\t\"bSmart\": bSmart,\n\t\t\t\t\t\"bCaseInsensitive\": bCaseInsensitive\n\t\t\t\t}, 1 );\n\t\t\t\t\n\t\t\t\tif ( bShowGlobal && oSettings.aanFeatures.f )\n\t\t\t\t{\n\t\t\t\t\tvar n = oSettings.aanFeatures.f;\n\t\t\t\t\tfor ( var i=0, iLen=n.length ; i<iLen ; i++ )\n\t\t\t\t\t{\n\t\t\t\t\t\t// IE9 throws an 'unknown error' if document.activeElement is used\n\t\t\t\t\t\t// inside an iframe or frame...\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tif ( n[i]._DT_Input != document.activeElement )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$(n[i]._DT_Input).val( sInput );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch ( e ) {\n\t\t\t\t\t\t\t$(n[i]._DT_Input).val( sInput );\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\telse\n\t\t\t{\n\t\t\t\t/* Single column filter */\n\t\t\t\t$.extend( oSettings.aoPreSearchCols[ iColumn ], {\n\t\t\t\t\t\"sSearch\": sInput+\"\",\n\t\t\t\t\t\"bRegex\": bRegex,\n\t\t\t\t\t\"bSmart\": bSmart,\n\t\t\t\t\t\"bCaseInsensitive\": bCaseInsensitive\n\t\t\t\t} );\n\t\t\t\t_fnFilterComplete( oSettings, oSettings.oPreviousSearch, 1 );\n\t\t\t}\n\t\t};\n\t\t\n\t\t\n\t\t/**\n\t\t * Get the data for the whole table, an individual row or an individual cell based on the \n\t\t * provided parameters.\n\t\t *  @param {int|node} [mRow] A TR row node, TD/TH cell node or an integer. If given as\n\t\t *    a TR node then the data source for the whole row will be returned. If given as a\n\t\t *    TD/TH cell node then iCol will be automatically calculated and the data for the\n\t\t *    cell returned. If given as an integer, then this is treated as the aoData internal\n\t\t *    data index for the row (see fnGetPosition) and the data for that row used.\n\t\t *  @param {int} [iCol] Optional column index that you want the data of.\n\t\t *  @returns {array|object|string} If mRow is undefined, then the data for all rows is\n\t\t *    returned. If mRow is defined, just data for that row, and is iCol is\n\t\t *    defined, only data for the designated cell is returned.\n\t\t *  @dtopt API\n\t\t *\n\t\t *  @example\n\t\t *    // Row data\n\t\t *    $(document).ready(function() {\n\t\t *      oTable = $('#example').dataTable();\n\t\t *\n\t\t *      oTable.$('tr').click( function () {\n\t\t *        var data = oTable.fnGetData( this );\n\t\t *        // ... do something with the array / object of data for the row\n\t\t *      } );\n\t\t *    } );\n\t\t *\n\t\t *  @example\n\t\t *    // Individual cell data\n\t\t *    $(document).ready(function() {\n\t\t *      oTable = $('#example').dataTable();\n\t\t *\n\t\t *      oTable.$('td').click( function () {\n\t\t *        var sData = oTable.fnGetData( this );\n\t\t *        alert( 'The cell clicked on had the value of '+sData );\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\tthis.fnGetData = function( mRow, iCol )\n\t\t{\n\t\t\tvar oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );\n\t\t\t\n\t\t\tif ( mRow !== undefined )\n\t\t\t{\n\t\t\t\tvar iRow = mRow;\n\t\t\t\tif ( typeof mRow === 'object' )\n\t\t\t\t{\n\t\t\t\t\tvar sNode = mRow.nodeName.toLowerCase();\n\t\t\t\t\tif (sNode === \"tr\" )\n\t\t\t\t\t{\n\t\t\t\t\t\tiRow = _fnNodeToDataIndex(oSettings, mRow);\n\t\t\t\t\t}\n\t\t\t\t\telse if ( sNode === \"td\" )\n\t\t\t\t\t{\n\t\t\t\t\t\tiRow = _fnNodeToDataIndex(oSettings, mRow.parentNode);\n\t\t\t\t\t\tiCol = _fnNodeToColumnIndex( oSettings, iRow, mRow );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\n\t\t\t\tif ( iCol !== undefined )\n\t\t\t\t{\n\t\t\t\t\treturn _fnGetCellData( oSettings, iRow, iCol, '' );\n\t\t\t\t}\n\t\t\t\treturn (oSettings.aoData[iRow]!==undefined) ?\n\t\t\t\t\toSettings.aoData[iRow]._aData : null;\n\t\t\t}\n\t\t\treturn _fnGetDataMaster( oSettings );\n\t\t};\n\t\t\n\t\t\n\t\t/**\n\t\t * Get an array of the TR nodes that are used in the table's body. Note that you will \n\t\t * typically want to use the '$' API method in preference to this as it is more \n\t\t * flexible.\n\t\t *  @param {int} [iRow] Optional row index for the TR element you want\n\t\t *  @returns {array|node} If iRow is undefined, returns an array of all TR elements\n\t\t *    in the table's body, or iRow is defined, just the TR element requested.\n\t\t *  @dtopt API\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready(function() {\n\t\t *      var oTable = $('#example').dataTable();\n\t\t *      \n\t\t *      // Get the nodes from the table\n\t\t *      var nNodes = oTable.fnGetNodes( );\n\t\t *    } );\n\t\t */\n\t\tthis.fnGetNodes = function( iRow )\n\t\t{\n\t\t\tvar oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );\n\t\t\t\n\t\t\tif ( iRow !== undefined ) {\n\t\t\t\treturn (oSettings.aoData[iRow]!==undefined) ?\n\t\t\t\t\toSettings.aoData[iRow].nTr : null;\n\t\t\t}\n\t\t\treturn _fnGetTrNodes( oSettings );\n\t\t};\n\t\t\n\t\t\n\t\t/**\n\t\t * Get the array indexes of a particular cell from it's DOM element\n\t\t * and column index including hidden columns\n\t\t *  @param {node} nNode this can either be a TR, TD or TH in the table's body\n\t\t *  @returns {int} If nNode is given as a TR, then a single index is returned, or\n\t\t *    if given as a cell, an array of [row index, column index (visible), \n\t\t *    column index (all)] is given.\n\t\t *  @dtopt API\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready(function() {\n\t\t *      $('#example tbody td').click( function () {\n\t\t *        // Get the position of the current data from the node\n\t\t *        var aPos = oTable.fnGetPosition( this );\n\t\t *        \n\t\t *        // Get the data array for this row\n\t\t *        var aData = oTable.fnGetData( aPos[0] );\n\t\t *        \n\t\t *        // Update the data array and return the value\n\t\t *        aData[ aPos[1] ] = 'clicked';\n\t\t *        this.innerHTML = 'clicked';\n\t\t *      } );\n\t\t *      \n\t\t *      // Init DataTables\n\t\t *      oTable = $('#example').dataTable();\n\t\t *    } );\n\t\t */\n\t\tthis.fnGetPosition = function( nNode )\n\t\t{\n\t\t\tvar oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );\n\t\t\tvar sNodeName = nNode.nodeName.toUpperCase();\n\t\t\t\n\t\t\tif ( sNodeName == \"TR\" )\n\t\t\t{\n\t\t\t\treturn _fnNodeToDataIndex(oSettings, nNode);\n\t\t\t}\n\t\t\telse if ( sNodeName == \"TD\" || sNodeName == \"TH\" )\n\t\t\t{\n\t\t\t\tvar iDataIndex = _fnNodeToDataIndex( oSettings, nNode.parentNode );\n\t\t\t\tvar iColumnIndex = _fnNodeToColumnIndex( oSettings, iDataIndex, nNode );\n\t\t\t\treturn [ iDataIndex, _fnColumnIndexToVisible(oSettings, iColumnIndex ), iColumnIndex ];\n\t\t\t}\n\t\t\treturn null;\n\t\t};\n\t\t\n\t\t\n\t\t/**\n\t\t * Check to see if a row is 'open' or not.\n\t\t *  @param {node} nTr the table row to check\n\t\t *  @returns {boolean} true if the row is currently open, false otherwise\n\t\t *  @dtopt API\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready(function() {\n\t\t *      var oTable;\n\t\t *      \n\t\t *      // 'open' an information row when a row is clicked on\n\t\t *      $('#example tbody tr').click( function () {\n\t\t *        if ( oTable.fnIsOpen(this) ) {\n\t\t *          oTable.fnClose( this );\n\t\t *        } else {\n\t\t *          oTable.fnOpen( this, \"Temporary row opened\", \"info_row\" );\n\t\t *        }\n\t\t *      } );\n\t\t *      \n\t\t *      oTable = $('#example').dataTable();\n\t\t *    } );\n\t\t */\n\t\tthis.fnIsOpen = function( nTr )\n\t\t{\n\t\t\tvar oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );\n\t\t\tvar aoOpenRows = oSettings.aoOpenRows;\n\t\t\t\n\t\t\tfor ( var i=0 ; i<oSettings.aoOpenRows.length ; i++ )\n\t\t\t{\n\t\t\t\tif ( oSettings.aoOpenRows[i].nParent == nTr )\n\t\t\t\t{\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\t\n\t\t\n\t\t/**\n\t\t * This function will place a new row directly after a row which is currently \n\t\t * on display on the page, with the HTML contents that is passed into the \n\t\t * function. This can be used, for example, to ask for confirmation that a \n\t\t * particular record should be deleted.\n\t\t *  @param {node} nTr The table row to 'open'\n\t\t *  @param {string|node|jQuery} mHtml The HTML to put into the row\n\t\t *  @param {string} sClass Class to give the new TD cell\n\t\t *  @returns {node} The row opened. Note that if the table row passed in as the\n\t\t *    first parameter, is not found in the table, this method will silently\n\t\t *    return.\n\t\t *  @dtopt API\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready(function() {\n\t\t *      var oTable;\n\t\t *      \n\t\t *      // 'open' an information row when a row is clicked on\n\t\t *      $('#example tbody tr').click( function () {\n\t\t *        if ( oTable.fnIsOpen(this) ) {\n\t\t *          oTable.fnClose( this );\n\t\t *        } else {\n\t\t *          oTable.fnOpen( this, \"Temporary row opened\", \"info_row\" );\n\t\t *        }\n\t\t *      } );\n\t\t *      \n\t\t *      oTable = $('#example').dataTable();\n\t\t *    } );\n\t\t */\n\t\tthis.fnOpen = function( nTr, mHtml, sClass )\n\t\t{\n\t\t\t/* Find settings from table node */\n\t\t\tvar oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );\n\t\t\n\t\t\t/* Check that the row given is in the table */\n\t\t\tvar nTableRows = _fnGetTrNodes( oSettings );\n\t\t\tif ( $.inArray(nTr, nTableRows) === -1 )\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\t/* the old open one if there is one */\n\t\t\tthis.fnClose( nTr );\n\t\t\t\n\t\t\tvar nNewRow = document.createElement(\"tr\");\n\t\t\tvar nNewCell = document.createElement(\"td\");\n\t\t\tnNewRow.appendChild( nNewCell );\n\t\t\tnNewCell.className = sClass;\n\t\t\tnNewCell.colSpan = _fnVisbleColumns( oSettings );\n\t\t\n\t\t\tif (typeof mHtml === \"string\")\n\t\t\t{\n\t\t\t\tnNewCell.innerHTML = mHtml;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$(nNewCell).html( mHtml );\n\t\t\t}\n\t\t\n\t\t\t/* If the nTr isn't on the page at the moment - then we don't insert at the moment */\n\t\t\tvar nTrs = $('tr', oSettings.nTBody);\n\t\t\tif ( $.inArray(nTr, nTrs) != -1  )\n\t\t\t{\n\t\t\t\t$(nNewRow).insertAfter(nTr);\n\t\t\t}\n\t\t\t\n\t\t\toSettings.aoOpenRows.push( {\n\t\t\t\t\"nTr\": nNewRow,\n\t\t\t\t\"nParent\": nTr\n\t\t\t} );\n\t\t\t\n\t\t\treturn nNewRow;\n\t\t};\n\t\t\n\t\t\n\t\t/**\n\t\t * Change the pagination - provides the internal logic for pagination in a simple API \n\t\t * function. With this function you can have a DataTables table go to the next, \n\t\t * previous, first or last pages.\n\t\t *  @param {string|int} mAction Paging action to take: \"first\", \"previous\", \"next\" or \"last\"\n\t\t *    or page number to jump to (integer), note that page 0 is the first page.\n\t\t *  @param {bool} [bRedraw=true] Redraw the table or not\n\t\t *  @dtopt API\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready(function() {\n\t\t *      var oTable = $('#example').dataTable();\n\t\t *      oTable.fnPageChange( 'next' );\n\t\t *    } );\n\t\t */\n\t\tthis.fnPageChange = function ( mAction, bRedraw )\n\t\t{\n\t\t\tvar oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );\n\t\t\t_fnPageChange( oSettings, mAction );\n\t\t\t_fnCalculateEnd( oSettings );\n\t\t\t\n\t\t\tif ( bRedraw === undefined || bRedraw )\n\t\t\t{\n\t\t\t\t_fnDraw( oSettings );\n\t\t\t}\n\t\t};\n\t\t\n\t\t\n\t\t/**\n\t\t * Show a particular column\n\t\t *  @param {int} iCol The column whose display should be changed\n\t\t *  @param {bool} bShow Show (true) or hide (false) the column\n\t\t *  @param {bool} [bRedraw=true] Redraw the table or not\n\t\t *  @dtopt API\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready(function() {\n\t\t *      var oTable = $('#example').dataTable();\n\t\t *      \n\t\t *      // Hide the second column after initialisation\n\t\t *      oTable.fnSetColumnVis( 1, false );\n\t\t *    } );\n\t\t */\n\t\tthis.fnSetColumnVis = function ( iCol, bShow, bRedraw )\n\t\t{\n\t\t\tvar oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );\n\t\t\tvar i, iLen;\n\t\t\tvar aoColumns = oSettings.aoColumns;\n\t\t\tvar aoData = oSettings.aoData;\n\t\t\tvar nTd, bAppend, iBefore;\n\t\t\t\n\t\t\t/* No point in doing anything if we are requesting what is already true */\n\t\t\tif ( aoColumns[iCol].bVisible == bShow )\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\t/* Show the column */\n\t\t\tif ( bShow )\n\t\t\t{\n\t\t\t\tvar iInsert = 0;\n\t\t\t\tfor ( i=0 ; i<iCol ; i++ )\n\t\t\t\t{\n\t\t\t\t\tif ( aoColumns[i].bVisible )\n\t\t\t\t\t{\n\t\t\t\t\t\tiInsert++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t/* Need to decide if we should use appendChild or insertBefore */\n\t\t\t\tbAppend = (iInsert >= _fnVisbleColumns( oSettings ));\n\t\t\n\t\t\t\t/* Which coloumn should we be inserting before? */\n\t\t\t\tif ( !bAppend )\n\t\t\t\t{\n\t\t\t\t\tfor ( i=iCol ; i<aoColumns.length ; i++ )\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( aoColumns[i].bVisible )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tiBefore = i;\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\n\t\t\t\tfor ( i=0, iLen=aoData.length ; i<iLen ; i++ )\n\t\t\t\t{\n\t\t\t\t\tif ( aoData[i].nTr !== null )\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( bAppend )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\taoData[i].nTr.appendChild( \n\t\t\t\t\t\t\t\taoData[i]._anHidden[iCol]\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\taoData[i].nTr.insertBefore(\n\t\t\t\t\t\t\t\taoData[i]._anHidden[iCol], \n\t\t\t\t\t\t\t\t_fnGetTdNodes( oSettings, i )[iBefore] );\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\telse\n\t\t\t{\n\t\t\t\t/* Remove a column from display */\n\t\t\t\tfor ( i=0, iLen=aoData.length ; i<iLen ; i++ )\n\t\t\t\t{\n\t\t\t\t\tif ( aoData[i].nTr !== null )\n\t\t\t\t\t{\n\t\t\t\t\t\tnTd = _fnGetTdNodes( oSettings, i )[iCol];\n\t\t\t\t\t\taoData[i]._anHidden[iCol] = nTd;\n\t\t\t\t\t\tnTd.parentNode.removeChild( nTd );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\n\t\t\t/* Clear to set the visible flag */\n\t\t\taoColumns[iCol].bVisible = bShow;\n\t\t\n\t\t\t/* Redraw the header and footer based on the new column visibility */\n\t\t\t_fnDrawHead( oSettings, oSettings.aoHeader );\n\t\t\tif ( oSettings.nTFoot )\n\t\t\t{\n\t\t\t\t_fnDrawHead( oSettings, oSettings.aoFooter );\n\t\t\t}\n\t\t\t\n\t\t\t/* If there are any 'open' rows, then we need to alter the colspan for this col change */\n\t\t\tfor ( i=0, iLen=oSettings.aoOpenRows.length ; i<iLen ; i++ )\n\t\t\t{\n\t\t\t\toSettings.aoOpenRows[i].nTr.colSpan = _fnVisbleColumns( oSettings );\n\t\t\t}\n\t\t\t\n\t\t\t/* Do a redraw incase anything depending on the table columns needs it \n\t\t\t * (built-in: scrolling) \n\t\t\t */\n\t\t\tif ( bRedraw === undefined || bRedraw )\n\t\t\t{\n\t\t\t\t_fnAdjustColumnSizing( oSettings );\n\t\t\t\t_fnDraw( oSettings );\n\t\t\t}\n\t\t\t\n\t\t\t_fnSaveState( oSettings );\n\t\t};\n\t\t\n\t\t\n\t\t/**\n\t\t * Get the settings for a particular table for external manipulation\n\t\t *  @returns {object} DataTables settings object. See \n\t\t *    {@link DataTable.models.oSettings}\n\t\t *  @dtopt API\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready(function() {\n\t\t *      var oTable = $('#example').dataTable();\n\t\t *      var oSettings = oTable.fnSettings();\n\t\t *      \n\t\t *      // Show an example parameter from the settings\n\t\t *      alert( oSettings._iDisplayStart );\n\t\t *    } );\n\t\t */\n\t\tthis.fnSettings = function()\n\t\t{\n\t\t\treturn _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );\n\t\t};\n\t\t\n\t\t\n\t\t/**\n\t\t * Sort the table by a particular column\n\t\t *  @param {int} iCol the data index to sort on. Note that this will not match the \n\t\t *    'display index' if you have hidden data entries\n\t\t *  @dtopt API\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready(function() {\n\t\t *      var oTable = $('#example').dataTable();\n\t\t *      \n\t\t *      // Sort immediately with columns 0 and 1\n\t\t *      oTable.fnSort( [ [0,'asc'], [1,'asc'] ] );\n\t\t *    } );\n\t\t */\n\t\tthis.fnSort = function( aaSort )\n\t\t{\n\t\t\tvar oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );\n\t\t\toSettings.aaSorting = aaSort;\n\t\t\t_fnSort( oSettings );\n\t\t};\n\t\t\n\t\t\n\t\t/**\n\t\t * Attach a sort listener to an element for a given column\n\t\t *  @param {node} nNode the element to attach the sort listener to\n\t\t *  @param {int} iColumn the column that a click on this node will sort on\n\t\t *  @param {function} [fnCallback] callback function when sort is run\n\t\t *  @dtopt API\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready(function() {\n\t\t *      var oTable = $('#example').dataTable();\n\t\t *      \n\t\t *      // Sort on column 1, when 'sorter' is clicked on\n\t\t *      oTable.fnSortListener( document.getElementById('sorter'), 1 );\n\t\t *    } );\n\t\t */\n\t\tthis.fnSortListener = function( nNode, iColumn, fnCallback )\n\t\t{\n\t\t\t_fnSortAttachListener( _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ), nNode, iColumn,\n\t\t\t \tfnCallback );\n\t\t};\n\t\t\n\t\t\n\t\t/**\n\t\t * Update a table cell or row - this method will accept either a single value to\n\t\t * update the cell with, an array of values with one element for each column or\n\t\t * an object in the same format as the original data source. The function is\n\t\t * self-referencing in order to make the multi column updates easier.\n\t\t *  @param {object|array|string} mData Data to update the cell/row with\n\t\t *  @param {node|int} mRow TR element you want to update or the aoData index\n\t\t *  @param {int} [iColumn] The column to update (not used of mData is an array or object)\n\t\t *  @param {bool} [bRedraw=true] Redraw the table or not\n\t\t *  @param {bool} [bAction=true] Perform pre-draw actions or not\n\t\t *  @returns {int} 0 on success, 1 on error\n\t\t *  @dtopt API\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready(function() {\n\t\t *      var oTable = $('#example').dataTable();\n\t\t *      oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell\n\t\t *      oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], 1, 0 ); // Row\n\t\t *    } );\n\t\t */\n\t\tthis.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction )\n\t\t{\n\t\t\tvar oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );\n\t\t\tvar i, iLen, sDisplay;\n\t\t\tvar iRow = (typeof mRow === 'object') ? \n\t\t\t\t_fnNodeToDataIndex(oSettings, mRow) : mRow;\n\t\t\t\n\t\t\tif ( $.isArray(mData) && iColumn === undefined )\n\t\t\t{\n\t\t\t\t/* Array update - update the whole row */\n\t\t\t\toSettings.aoData[iRow]._aData = mData.slice();\n\t\t\t\t\n\t\t\t\t/* Flag to the function that we are recursing */\n\t\t\t\tfor ( i=0 ; i<oSettings.aoColumns.length ; i++ )\n\t\t\t\t{\n\t\t\t\t\tthis.fnUpdate( _fnGetCellData( oSettings, iRow, i ), iRow, i, false, false );\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if ( $.isPlainObject(mData) && iColumn === undefined )\n\t\t\t{\n\t\t\t\t/* Object update - update the whole row - assume the developer gets the object right */\n\t\t\t\toSettings.aoData[iRow]._aData = $.extend( true, {}, mData );\n\t\t\n\t\t\t\tfor ( i=0 ; i<oSettings.aoColumns.length ; i++ )\n\t\t\t\t{\n\t\t\t\t\tthis.fnUpdate( _fnGetCellData( oSettings, iRow, i ), iRow, i, false, false );\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t/* Individual cell update */\n\t\t\t\t_fnSetCellData( oSettings, iRow, iColumn, mData );\n\t\t\t\tsDisplay = _fnGetCellData( oSettings, iRow, iColumn, 'display' );\n\t\t\t\t\n\t\t\t\tvar oCol = oSettings.aoColumns[iColumn];\n\t\t\t\tif ( oCol.fnRender !== null )\n\t\t\t\t{\n\t\t\t\t\tsDisplay = _fnRender( oSettings, iRow, iColumn );\n\t\t\t\t\tif ( oCol.bUseRendered )\n\t\t\t\t\t{\n\t\t\t\t\t\t_fnSetCellData( oSettings, iRow, iColumn, sDisplay );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif ( oSettings.aoData[iRow].nTr !== null )\n\t\t\t\t{\n\t\t\t\t\t/* Do the actual HTML update */\n\t\t\t\t\t_fnGetTdNodes( oSettings, iRow )[iColumn].innerHTML = sDisplay;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t/* Modify the search index for this row (strictly this is likely not needed, since fnReDraw\n\t\t\t * will rebuild the search array - however, the redraw might be disabled by the user)\n\t\t\t */\n\t\t\tvar iDisplayIndex = $.inArray( iRow, oSettings.aiDisplay );\n\t\t\toSettings.asDataSearch[iDisplayIndex] = _fnBuildSearchRow(\n\t\t\t\toSettings, \n\t\t\t\t_fnGetRowData( oSettings, iRow, 'filter', _fnGetColumns( oSettings, 'bSearchable' ) )\n\t\t\t);\n\t\t\t\n\t\t\t/* Perform pre-draw actions */\n\t\t\tif ( bAction === undefined || bAction )\n\t\t\t{\n\t\t\t\t_fnAdjustColumnSizing( oSettings );\n\t\t\t}\n\t\t\t\n\t\t\t/* Redraw the table */\n\t\t\tif ( bRedraw === undefined || bRedraw )\n\t\t\t{\n\t\t\t\t_fnReDraw( oSettings );\n\t\t\t}\n\t\t\treturn 0;\n\t\t};\n\t\t\n\t\t\n\t\t/**\n\t\t * Provide a common method for plug-ins to check the version of DataTables being used, in order\n\t\t * to ensure compatibility.\n\t\t *  @param {string} sVersion Version string to check for, in the format \"X.Y.Z\". Note that the\n\t\t *    formats \"X\" and \"X.Y\" are also acceptable.\n\t\t *  @returns {boolean} true if this version of DataTables is greater or equal to the required\n\t\t *    version, or false if this version of DataTales is not suitable\n\t\t *  @method\n\t\t *  @dtopt API\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready(function() {\n\t\t *      var oTable = $('#example').dataTable();\n\t\t *      alert( oTable.fnVersionCheck( '1.9.0' ) );\n\t\t *    } );\n\t\t */\n\t\tthis.fnVersionCheck = DataTable.ext.fnVersionCheck;\n\t\t\n\t\t\n\t\t/*\n\t\t * This is really a good bit rubbish this method of exposing the internal methods\n\t\t * publicly... - To be fixed in 2.0 using methods on the prototype\n\t\t */\n\t\t\n\t\t\n\t\t/**\n\t\t * Create a wrapper function for exporting an internal functions to an external API.\n\t\t *  @param {string} sFunc API function name\n\t\t *  @returns {function} wrapped function\n\t\t *  @memberof DataTable#oApi\n\t\t */\n\t\tfunction _fnExternApiFunc (sFunc)\n\t\t{\n\t\t\treturn function() {\n\t\t\t\tvar aArgs = [_fnSettingsFromNode(this[DataTable.ext.iApiIndex])].concat( \n\t\t\t\t\tArray.prototype.slice.call(arguments) );\n\t\t\t\treturn DataTable.ext.oApi[sFunc].apply( this, aArgs );\n\t\t\t};\n\t\t}\n\t\t\n\t\t\n\t\t/**\n\t\t * Reference to internal functions for use by plug-in developers. Note that these\n\t\t * methods are references to internal functions and are considered to be private.\n\t\t * If you use these methods, be aware that they are liable to change between versions\n\t\t * (check the upgrade notes).\n\t\t *  @namespace\n\t\t */\n\t\tthis.oApi = {\n\t\t\t\"_fnExternApiFunc\": _fnExternApiFunc,\n\t\t\t\"_fnInitialise\": _fnInitialise,\n\t\t\t\"_fnInitComplete\": _fnInitComplete,\n\t\t\t\"_fnLanguageCompat\": _fnLanguageCompat,\n\t\t\t\"_fnAddColumn\": _fnAddColumn,\n\t\t\t\"_fnColumnOptions\": _fnColumnOptions,\n\t\t\t\"_fnAddData\": _fnAddData,\n\t\t\t\"_fnCreateTr\": _fnCreateTr,\n\t\t\t\"_fnGatherData\": _fnGatherData,\n\t\t\t\"_fnBuildHead\": _fnBuildHead,\n\t\t\t\"_fnDrawHead\": _fnDrawHead,\n\t\t\t\"_fnDraw\": _fnDraw,\n\t\t\t\"_fnReDraw\": _fnReDraw,\n\t\t\t\"_fnAjaxUpdate\": _fnAjaxUpdate,\n\t\t\t\"_fnAjaxParameters\": _fnAjaxParameters,\n\t\t\t\"_fnAjaxUpdateDraw\": _fnAjaxUpdateDraw,\n\t\t\t\"_fnServerParams\": _fnServerParams,\n\t\t\t\"_fnAddOptionsHtml\": _fnAddOptionsHtml,\n\t\t\t\"_fnFeatureHtmlTable\": _fnFeatureHtmlTable,\n\t\t\t\"_fnScrollDraw\": _fnScrollDraw,\n\t\t\t\"_fnAdjustColumnSizing\": _fnAdjustColumnSizing,\n\t\t\t\"_fnFeatureHtmlFilter\": _fnFeatureHtmlFilter,\n\t\t\t\"_fnFilterComplete\": _fnFilterComplete,\n\t\t\t\"_fnFilterCustom\": _fnFilterCustom,\n\t\t\t\"_fnFilterColumn\": _fnFilterColumn,\n\t\t\t\"_fnFilter\": _fnFilter,\n\t\t\t\"_fnBuildSearchArray\": _fnBuildSearchArray,\n\t\t\t\"_fnBuildSearchRow\": _fnBuildSearchRow,\n\t\t\t\"_fnFilterCreateSearch\": _fnFilterCreateSearch,\n\t\t\t\"_fnDataToSearch\": _fnDataToSearch,\n\t\t\t\"_fnSort\": _fnSort,\n\t\t\t\"_fnSortAttachListener\": _fnSortAttachListener,\n\t\t\t\"_fnSortingClasses\": _fnSortingClasses,\n\t\t\t\"_fnFeatureHtmlPaginate\": _fnFeatureHtmlPaginate,\n\t\t\t\"_fnPageChange\": _fnPageChange,\n\t\t\t\"_fnFeatureHtmlInfo\": _fnFeatureHtmlInfo,\n\t\t\t\"_fnUpdateInfo\": _fnUpdateInfo,\n\t\t\t\"_fnFeatureHtmlLength\": _fnFeatureHtmlLength,\n\t\t\t\"_fnFeatureHtmlProcessing\": _fnFeatureHtmlProcessing,\n\t\t\t\"_fnProcessingDisplay\": _fnProcessingDisplay,\n\t\t\t\"_fnVisibleToColumnIndex\": _fnVisibleToColumnIndex,\n\t\t\t\"_fnColumnIndexToVisible\": _fnColumnIndexToVisible,\n\t\t\t\"_fnNodeToDataIndex\": _fnNodeToDataIndex,\n\t\t\t\"_fnVisbleColumns\": _fnVisbleColumns,\n\t\t\t\"_fnCalculateEnd\": _fnCalculateEnd,\n\t\t\t\"_fnConvertToWidth\": _fnConvertToWidth,\n\t\t\t\"_fnCalculateColumnWidths\": _fnCalculateColumnWidths,\n\t\t\t\"_fnScrollingWidthAdjust\": _fnScrollingWidthAdjust,\n\t\t\t\"_fnGetWidestNode\": _fnGetWidestNode,\n\t\t\t\"_fnGetMaxLenString\": _fnGetMaxLenString,\n\t\t\t\"_fnStringToCss\": _fnStringToCss,\n\t\t\t\"_fnDetectType\": _fnDetectType,\n\t\t\t\"_fnSettingsFromNode\": _fnSettingsFromNode,\n\t\t\t\"_fnGetDataMaster\": _fnGetDataMaster,\n\t\t\t\"_fnGetTrNodes\": _fnGetTrNodes,\n\t\t\t\"_fnGetTdNodes\": _fnGetTdNodes,\n\t\t\t\"_fnEscapeRegex\": _fnEscapeRegex,\n\t\t\t\"_fnDeleteIndex\": _fnDeleteIndex,\n\t\t\t\"_fnReOrderIndex\": _fnReOrderIndex,\n\t\t\t\"_fnColumnOrdering\": _fnColumnOrdering,\n\t\t\t\"_fnLog\": _fnLog,\n\t\t\t\"_fnClearTable\": _fnClearTable,\n\t\t\t\"_fnSaveState\": _fnSaveState,\n\t\t\t\"_fnLoadState\": _fnLoadState,\n\t\t\t\"_fnCreateCookie\": _fnCreateCookie,\n\t\t\t\"_fnReadCookie\": _fnReadCookie,\n\t\t\t\"_fnDetectHeader\": _fnDetectHeader,\n\t\t\t\"_fnGetUniqueThs\": _fnGetUniqueThs,\n\t\t\t\"_fnScrollBarWidth\": _fnScrollBarWidth,\n\t\t\t\"_fnApplyToChildren\": _fnApplyToChildren,\n\t\t\t\"_fnMap\": _fnMap,\n\t\t\t\"_fnGetRowData\": _fnGetRowData,\n\t\t\t\"_fnGetCellData\": _fnGetCellData,\n\t\t\t\"_fnSetCellData\": _fnSetCellData,\n\t\t\t\"_fnGetObjectDataFn\": _fnGetObjectDataFn,\n\t\t\t\"_fnSetObjectDataFn\": _fnSetObjectDataFn,\n\t\t\t\"_fnApplyColumnDefs\": _fnApplyColumnDefs,\n\t\t\t\"_fnBindAction\": _fnBindAction,\n\t\t\t\"_fnExtend\": _fnExtend,\n\t\t\t\"_fnCallbackReg\": _fnCallbackReg,\n\t\t\t\"_fnCallbackFire\": _fnCallbackFire,\n\t\t\t\"_fnJsonString\": _fnJsonString,\n\t\t\t\"_fnRender\": _fnRender,\n\t\t\t\"_fnNodeToColumnIndex\": _fnNodeToColumnIndex,\n\t\t\t\"_fnInfoMacros\": _fnInfoMacros,\n\t\t\t\"_fnBrowserDetect\": _fnBrowserDetect,\n\t\t\t\"_fnGetColumns\": _fnGetColumns\n\t\t};\n\t\t\n\t\t$.extend( DataTable.ext.oApi, this.oApi );\n\t\t\n\t\tfor ( var sFunc in DataTable.ext.oApi )\n\t\t{\n\t\t\tif ( sFunc )\n\t\t\t{\n\t\t\t\tthis[sFunc] = _fnExternApiFunc(sFunc);\n\t\t\t}\n\t\t}\n\t\t\n\t\t\n\t\tvar _that = this;\n\t\tthis.each(function() {\n\t\t\tvar i=0, iLen, j, jLen, k, kLen;\n\t\t\tvar sId = this.getAttribute( 'id' );\n\t\t\tvar bInitHandedOff = false;\n\t\t\tvar bUsePassedData = false;\n\t\t\t\n\t\t\t\n\t\t\t/* Sanity check */\n\t\t\tif ( this.nodeName.toLowerCase() != 'table' )\n\t\t\t{\n\t\t\t\t_fnLog( null, 0, \"Attempted to initialise DataTables on a node which is not a \"+\n\t\t\t\t\t\"table: \"+this.nodeName );\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\t/* Check to see if we are re-initialising a table */\n\t\t\tfor ( i=0, iLen=DataTable.settings.length ; i<iLen ; i++ )\n\t\t\t{\n\t\t\t\t/* Base check on table node */\n\t\t\t\tif ( DataTable.settings[i].nTable == this )\n\t\t\t\t{\n\t\t\t\t\tif ( oInit === undefined || oInit.bRetrieve )\n\t\t\t\t\t{\n\t\t\t\t\t\treturn DataTable.settings[i].oInstance;\n\t\t\t\t\t}\n\t\t\t\t\telse if ( oInit.bDestroy )\n\t\t\t\t\t{\n\t\t\t\t\t\tDataTable.settings[i].oInstance.fnDestroy();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t_fnLog( DataTable.settings[i], 0, \"Cannot reinitialise DataTable.\\n\\n\"+\n\t\t\t\t\t\t\t\"To retrieve the DataTables object for this table, pass no arguments or see \"+\n\t\t\t\t\t\t\t\"the docs for bRetrieve and bDestroy\" );\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t/* If the element we are initialising has the same ID as a table which was previously\n\t\t\t\t * initialised, but the table nodes don't match (from before) then we destroy the old\n\t\t\t\t * instance by simply deleting it. This is under the assumption that the table has been\n\t\t\t\t * destroyed by other methods. Anyone using non-id selectors will need to do this manually\n\t\t\t\t */\n\t\t\t\tif ( DataTable.settings[i].sTableId == this.id )\n\t\t\t\t{\n\t\t\t\t\tDataTable.settings.splice( i, 1 );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t/* Ensure the table has an ID - required for accessibility */\n\t\t\tif ( sId === null || sId === \"\" )\n\t\t\t{\n\t\t\t\tsId = \"DataTables_Table_\"+(DataTable.ext._oExternConfig.iNextUnique++);\n\t\t\t\tthis.id = sId;\n\t\t\t}\n\t\t\t\n\t\t\t/* Create the settings object for this table and set some of the default parameters */\n\t\t\tvar oSettings = $.extend( true, {}, DataTable.models.oSettings, {\n\t\t\t\t\"nTable\":        this,\n\t\t\t\t\"oApi\":          _that.oApi,\n\t\t\t\t\"oInit\":         oInit,\n\t\t\t\t\"sDestroyWidth\": $(this).width(),\n\t\t\t\t\"sInstance\":     sId,\n\t\t\t\t\"sTableId\":      sId\n\t\t\t} );\n\t\t\tDataTable.settings.push( oSettings );\n\t\t\t\n\t\t\t// Need to add the instance after the instance after the settings object has been added\n\t\t\t// to the settings array, so we can self reference the table instance if more than one\n\t\t\toSettings.oInstance = (_that.length===1) ? _that : $(this).dataTable();\n\t\t\t\n\t\t\t/* Setting up the initialisation object */\n\t\t\tif ( !oInit )\n\t\t\t{\n\t\t\t\toInit = {};\n\t\t\t}\n\t\t\t\n\t\t\t// Backwards compatibility, before we apply all the defaults\n\t\t\tif ( oInit.oLanguage )\n\t\t\t{\n\t\t\t\t_fnLanguageCompat( oInit.oLanguage );\n\t\t\t}\n\t\t\t\n\t\t\toInit = _fnExtend( $.extend(true, {}, DataTable.defaults), oInit );\n\t\t\t\n\t\t\t// Map the initialisation options onto the settings object\n\t\t\t_fnMap( oSettings.oFeatures, oInit, \"bPaginate\" );\n\t\t\t_fnMap( oSettings.oFeatures, oInit, \"bLengthChange\" );\n\t\t\t_fnMap( oSettings.oFeatures, oInit, \"bFilter\" );\n\t\t\t_fnMap( oSettings.oFeatures, oInit, \"bSort\" );\n\t\t\t_fnMap( oSettings.oFeatures, oInit, \"bInfo\" );\n\t\t\t_fnMap( oSettings.oFeatures, oInit, \"bProcessing\" );\n\t\t\t_fnMap( oSettings.oFeatures, oInit, \"bAutoWidth\" );\n\t\t\t_fnMap( oSettings.oFeatures, oInit, \"bSortClasses\" );\n\t\t\t_fnMap( oSettings.oFeatures, oInit, \"bServerSide\" );\n\t\t\t_fnMap( oSettings.oFeatures, oInit, \"bDeferRender\" );\n\t\t\t_fnMap( oSettings.oScroll, oInit, \"sScrollX\", \"sX\" );\n\t\t\t_fnMap( oSettings.oScroll, oInit, \"sScrollXInner\", \"sXInner\" );\n\t\t\t_fnMap( oSettings.oScroll, oInit, \"sScrollY\", \"sY\" );\n\t\t\t_fnMap( oSettings.oScroll, oInit, \"bScrollCollapse\", \"bCollapse\" );\n\t\t\t_fnMap( oSettings.oScroll, oInit, \"bScrollInfinite\", \"bInfinite\" );\n\t\t\t_fnMap( oSettings.oScroll, oInit, \"iScrollLoadGap\", \"iLoadGap\" );\n\t\t\t_fnMap( oSettings.oScroll, oInit, \"bScrollAutoCss\", \"bAutoCss\" );\n\t\t\t_fnMap( oSettings, oInit, \"asStripeClasses\" );\n\t\t\t_fnMap( oSettings, oInit, \"asStripClasses\", \"asStripeClasses\" ); // legacy\n\t\t\t_fnMap( oSettings, oInit, \"fnServerData\" );\n\t\t\t_fnMap( oSettings, oInit, \"fnFormatNumber\" );\n\t\t\t_fnMap( oSettings, oInit, \"sServerMethod\" );\n\t\t\t_fnMap( oSettings, oInit, \"aaSorting\" );\n\t\t\t_fnMap( oSettings, oInit, \"aaSortingFixed\" );\n\t\t\t_fnMap( oSettings, oInit, \"aLengthMenu\" );\n\t\t\t_fnMap( oSettings, oInit, \"sPaginationType\" );\n\t\t\t_fnMap( oSettings, oInit, \"sAjaxSource\" );\n\t\t\t_fnMap( oSettings, oInit, \"sAjaxDataProp\" );\n\t\t\t_fnMap( oSettings, oInit, \"iCookieDuration\" );\n\t\t\t_fnMap( oSettings, oInit, \"sCookiePrefix\" );\n\t\t\t_fnMap( oSettings, oInit, \"sDom\" );\n\t\t\t_fnMap( oSettings, oInit, \"bSortCellsTop\" );\n\t\t\t_fnMap( oSettings, oInit, \"iTabIndex\" );\n\t\t\t_fnMap( oSettings, oInit, \"oSearch\", \"oPreviousSearch\" );\n\t\t\t_fnMap( oSettings, oInit, \"aoSearchCols\", \"aoPreSearchCols\" );\n\t\t\t_fnMap( oSettings, oInit, \"iDisplayLength\", \"_iDisplayLength\" );\n\t\t\t_fnMap( oSettings, oInit, \"bJQueryUI\", \"bJUI\" );\n\t\t\t_fnMap( oSettings, oInit, \"fnCookieCallback\" );\n\t\t\t_fnMap( oSettings, oInit, \"fnStateLoad\" );\n\t\t\t_fnMap( oSettings, oInit, \"fnStateSave\" );\n\t\t\t_fnMap( oSettings.oLanguage, oInit, \"fnInfoCallback\" );\n\t\t\t\n\t\t\t/* Callback functions which are array driven */\n\t\t\t_fnCallbackReg( oSettings, 'aoDrawCallback',       oInit.fnDrawCallback,      'user' );\n\t\t\t_fnCallbackReg( oSettings, 'aoServerParams',       oInit.fnServerParams,      'user' );\n\t\t\t_fnCallbackReg( oSettings, 'aoStateSaveParams',    oInit.fnStateSaveParams,   'user' );\n\t\t\t_fnCallbackReg( oSettings, 'aoStateLoadParams',    oInit.fnStateLoadParams,   'user' );\n\t\t\t_fnCallbackReg( oSettings, 'aoStateLoaded',        oInit.fnStateLoaded,       'user' );\n\t\t\t_fnCallbackReg( oSettings, 'aoRowCallback',        oInit.fnRowCallback,       'user' );\n\t\t\t_fnCallbackReg( oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow,        'user' );\n\t\t\t_fnCallbackReg( oSettings, 'aoHeaderCallback',     oInit.fnHeaderCallback,    'user' );\n\t\t\t_fnCallbackReg( oSettings, 'aoFooterCallback',     oInit.fnFooterCallback,    'user' );\n\t\t\t_fnCallbackReg( oSettings, 'aoInitComplete',       oInit.fnInitComplete,      'user' );\n\t\t\t_fnCallbackReg( oSettings, 'aoPreDrawCallback',    oInit.fnPreDrawCallback,   'user' );\n\t\t\t\n\t\t\tif ( oSettings.oFeatures.bServerSide && oSettings.oFeatures.bSort &&\n\t\t\t\t   oSettings.oFeatures.bSortClasses )\n\t\t\t{\n\t\t\t\t/* Enable sort classes for server-side processing. Safe to do it here, since server-side\n\t\t\t\t * processing must be enabled by the developer\n\t\t\t\t */\n\t\t\t\t_fnCallbackReg( oSettings, 'aoDrawCallback', _fnSortingClasses, 'server_side_sort_classes' );\n\t\t\t}\n\t\t\telse if ( oSettings.oFeatures.bDeferRender )\n\t\t\t{\n\t\t\t\t_fnCallbackReg( oSettings, 'aoDrawCallback', _fnSortingClasses, 'defer_sort_classes' );\n\t\t\t}\n\t\t\t\n\t\t\tif ( oInit.bJQueryUI )\n\t\t\t{\n\t\t\t\t/* Use the JUI classes object for display. You could clone the oStdClasses object if \n\t\t\t\t * you want to have multiple tables with multiple independent classes \n\t\t\t\t */\n\t\t\t\t$.extend( oSettings.oClasses, DataTable.ext.oJUIClasses );\n\t\t\t\t\n\t\t\t\tif ( oInit.sDom === DataTable.defaults.sDom && DataTable.defaults.sDom === \"lfrtip\" )\n\t\t\t\t{\n\t\t\t\t\t/* Set the DOM to use a layout suitable for jQuery UI's theming */\n\t\t\t\t\toSettings.sDom = '<\"H\"lfr>t<\"F\"ip>';\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$.extend( oSettings.oClasses, DataTable.ext.oStdClasses );\n\t\t\t}\n\t\t\t$(this).addClass( oSettings.oClasses.sTable );\n\t\t\t\n\t\t\t/* Calculate the scroll bar width and cache it for use later on */\n\t\t\tif ( oSettings.oScroll.sX !== \"\" || oSettings.oScroll.sY !== \"\" )\n\t\t\t{\n\t\t\t\toSettings.oScroll.iBarWidth = _fnScrollBarWidth();\n\t\t\t}\n\t\t\t\n\t\t\tif ( oSettings.iInitDisplayStart === undefined )\n\t\t\t{\n\t\t\t\t/* Display start point, taking into account the save saving */\n\t\t\t\toSettings.iInitDisplayStart = oInit.iDisplayStart;\n\t\t\t\toSettings._iDisplayStart = oInit.iDisplayStart;\n\t\t\t}\n\t\t\t\n\t\t\t/* Must be done after everything which can be overridden by a cookie! */\n\t\t\tif ( oInit.bStateSave )\n\t\t\t{\n\t\t\t\toSettings.oFeatures.bStateSave = true;\n\t\t\t\t_fnLoadState( oSettings, oInit );\n\t\t\t\t_fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' );\n\t\t\t}\n\t\t\t\n\t\t\tif ( oInit.iDeferLoading !== null )\n\t\t\t{\n\t\t\t\toSettings.bDeferLoading = true;\n\t\t\t\tvar tmp = $.isArray( oInit.iDeferLoading );\n\t\t\t\toSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading;\n\t\t\t\toSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading;\n\t\t\t}\n\t\t\t\n\t\t\tif ( oInit.aaData !== null )\n\t\t\t{\n\t\t\t\tbUsePassedData = true;\n\t\t\t}\n\t\t\t\n\t\t\t/* Language definitions */\n\t\t\tif ( oInit.oLanguage.sUrl !== \"\" )\n\t\t\t{\n\t\t\t\t/* Get the language definitions from a file - because this Ajax call makes the language\n\t\t\t\t * get async to the remainder of this function we use bInitHandedOff to indicate that \n\t\t\t\t * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor\n\t\t\t\t */\n\t\t\t\toSettings.oLanguage.sUrl = oInit.oLanguage.sUrl;\n\t\t\t\t$.getJSON( oSettings.oLanguage.sUrl, null, function( json ) {\n\t\t\t\t\t_fnLanguageCompat( json );\n\t\t\t\t\t$.extend( true, oSettings.oLanguage, oInit.oLanguage, json );\n\t\t\t\t\t_fnInitialise( oSettings );\n\t\t\t\t} );\n\t\t\t\tbInitHandedOff = true;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$.extend( true, oSettings.oLanguage, oInit.oLanguage );\n\t\t\t}\n\t\t\t\n\t\t\t\n\t\t\t/*\n\t\t\t * Stripes\n\t\t\t */\n\t\t\tif ( oInit.asStripeClasses === null )\n\t\t\t{\n\t\t\t\toSettings.asStripeClasses =[\n\t\t\t\t\toSettings.oClasses.sStripeOdd,\n\t\t\t\t\toSettings.oClasses.sStripeEven\n\t\t\t\t];\n\t\t\t}\n\t\t\t\n\t\t\t/* Remove row stripe classes if they are already on the table row */\n\t\t\tiLen=oSettings.asStripeClasses.length;\n\t\t\toSettings.asDestroyStripes = [];\n\t\t\tif (iLen)\n\t\t\t{\n\t\t\t\tvar bStripeRemove = false;\n\t\t\t\tvar anRows = $(this).children('tbody').children('tr:lt(' + iLen + ')');\n\t\t\t\tfor ( i=0 ; i<iLen ; i++ )\n\t\t\t\t{\n\t\t\t\t\tif ( anRows.hasClass( oSettings.asStripeClasses[i] ) )\n\t\t\t\t\t{\n\t\t\t\t\t\tbStripeRemove = true;\n\t\t\t\t\t\t\n\t\t\t\t\t\t/* Store the classes which we are about to remove so they can be re-added on destroy */\n\t\t\t\t\t\toSettings.asDestroyStripes.push( oSettings.asStripeClasses[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif ( bStripeRemove )\n\t\t\t\t{\n\t\t\t\t\tanRows.removeClass( oSettings.asStripeClasses.join(' ') );\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t/*\n\t\t\t * Columns\n\t\t\t * See if we should load columns automatically or use defined ones\n\t\t\t */\n\t\t\tvar anThs = [];\n\t\t\tvar aoColumnsInit;\n\t\t\tvar nThead = this.getElementsByTagName('thead');\n\t\t\tif ( nThead.length !== 0 )\n\t\t\t{\n\t\t\t\t_fnDetectHeader( oSettings.aoHeader, nThead[0] );\n\t\t\t\tanThs = _fnGetUniqueThs( oSettings );\n\t\t\t}\n\t\t\t\n\t\t\t/* If not given a column array, generate one with nulls */\n\t\t\tif ( oInit.aoColumns === null )\n\t\t\t{\n\t\t\t\taoColumnsInit = [];\n\t\t\t\tfor ( i=0, iLen=anThs.length ; i<iLen ; i++ )\n\t\t\t\t{\n\t\t\t\t\taoColumnsInit.push( null );\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\taoColumnsInit = oInit.aoColumns;\n\t\t\t}\n\t\t\t\n\t\t\t/* Add the columns */\n\t\t\tfor ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ )\n\t\t\t{\n\t\t\t\t/* Short cut - use the loop to check if we have column visibility state to restore */\n\t\t\t\tif ( oInit.saved_aoColumns !== undefined && oInit.saved_aoColumns.length == iLen )\n\t\t\t\t{\n\t\t\t\t\tif ( aoColumnsInit[i] === null )\n\t\t\t\t\t{\n\t\t\t\t\t\taoColumnsInit[i] = {};\n\t\t\t\t\t}\n\t\t\t\t\taoColumnsInit[i].bVisible = oInit.saved_aoColumns[i].bVisible;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t_fnAddColumn( oSettings, anThs ? anThs[i] : null );\n\t\t\t}\n\t\t\t\n\t\t\t/* Apply the column definitions */\n\t\t\t_fnApplyColumnDefs( oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) {\n\t\t\t\t_fnColumnOptions( oSettings, iCol, oDef );\n\t\t\t} );\n\t\t\t\n\t\t\t\n\t\t\t/*\n\t\t\t * Sorting\n\t\t\t * Check the aaSorting array\n\t\t\t */\n\t\t\tfor ( i=0, iLen=oSettings.aaSorting.length ; i<iLen ; i++ )\n\t\t\t{\n\t\t\t\tif ( oSettings.aaSorting[i][0] >= oSettings.aoColumns.length )\n\t\t\t\t{\n\t\t\t\t\toSettings.aaSorting[i][0] = 0;\n\t\t\t\t}\n\t\t\t\tvar oColumn = oSettings.aoColumns[ oSettings.aaSorting[i][0] ];\n\t\t\t\t\n\t\t\t\t/* Add a default sorting index */\n\t\t\t\tif ( oSettings.aaSorting[i][2] === undefined )\n\t\t\t\t{\n\t\t\t\t\toSettings.aaSorting[i][2] = 0;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t/* If aaSorting is not defined, then we use the first indicator in asSorting */\n\t\t\t\tif ( oInit.aaSorting === undefined && oSettings.saved_aaSorting === undefined )\n\t\t\t\t{\n\t\t\t\t\toSettings.aaSorting[i][1] = oColumn.asSorting[0];\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t/* Set the current sorting index based on aoColumns.asSorting */\n\t\t\t\tfor ( j=0, jLen=oColumn.asSorting.length ; j<jLen ; j++ )\n\t\t\t\t{\n\t\t\t\t\tif ( oSettings.aaSorting[i][1] == oColumn.asSorting[j] )\n\t\t\t\t\t{\n\t\t\t\t\t\toSettings.aaSorting[i][2] = j;\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\t\t\n\t\t\t/* Do a first pass on the sorting classes (allows any size changes to be taken into\n\t\t\t * account, and also will apply sorting disabled classes if disabled\n\t\t\t */\n\t\t\t_fnSortingClasses( oSettings );\n\t\t\t\n\t\t\t\n\t\t\t/*\n\t\t\t * Final init\n\t\t\t * Cache the header, body and footer as required, creating them if needed\n\t\t\t */\n\t\t\t\n\t\t\t/* Browser support detection */\n\t\t\t_fnBrowserDetect( oSettings );\n\t\t\t\n\t\t\t// Work around for Webkit bug 83867 - store the caption-side before removing from doc\n\t\t\tvar captions = $(this).children('caption').each( function () {\n\t\t\t\tthis._captionSide = $(this).css('caption-side');\n\t\t\t} );\n\t\t\t\n\t\t\tvar thead = $(this).children('thead');\n\t\t\tif ( thead.length === 0 )\n\t\t\t{\n\t\t\t\tthead = [ document.createElement( 'thead' ) ];\n\t\t\t\tthis.appendChild( thead[0] );\n\t\t\t}\n\t\t\toSettings.nTHead = thead[0];\n\t\t\t\n\t\t\tvar tbody = $(this).children('tbody');\n\t\t\tif ( tbody.length === 0 )\n\t\t\t{\n\t\t\t\ttbody = [ document.createElement( 'tbody' ) ];\n\t\t\t\tthis.appendChild( tbody[0] );\n\t\t\t}\n\t\t\toSettings.nTBody = tbody[0];\n\t\t\toSettings.nTBody.setAttribute( \"role\", \"alert\" );\n\t\t\toSettings.nTBody.setAttribute( \"aria-live\", \"polite\" );\n\t\t\toSettings.nTBody.setAttribute( \"aria-relevant\", \"all\" );\n\t\t\t\n\t\t\tvar tfoot = $(this).children('tfoot');\n\t\t\tif ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== \"\" || oSettings.oScroll.sY !== \"\") )\n\t\t\t{\n\t\t\t\t// If we are a scrolling table, and no footer has been given, then we need to create\n\t\t\t\t// a tfoot element for the caption element to be appended to\n\t\t\t\ttfoot = [ document.createElement( 'tfoot' ) ];\n\t\t\t\tthis.appendChild( tfoot[0] );\n\t\t\t}\n\t\t\t\n\t\t\tif ( tfoot.length > 0 )\n\t\t\t{\n\t\t\t\toSettings.nTFoot = tfoot[0];\n\t\t\t\t_fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot );\n\t\t\t}\n\t\t\t\n\t\t\t/* Check if there is data passing into the constructor */\n\t\t\tif ( bUsePassedData )\n\t\t\t{\n\t\t\t\tfor ( i=0 ; i<oInit.aaData.length ; i++ )\n\t\t\t\t{\n\t\t\t\t\t_fnAddData( oSettings, oInit.aaData[ i ] );\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t/* Grab the data from the page */\n\t\t\t\t_fnGatherData( oSettings );\n\t\t\t}\n\t\t\t\n\t\t\t/* Copy the data index array */\n\t\t\toSettings.aiDisplay = oSettings.aiDisplayMaster.slice();\n\t\t\t\n\t\t\t/* Initialisation complete - table can be drawn */\n\t\t\toSettings.bInitialised = true;\n\t\t\t\n\t\t\t/* Check if we need to initialise the table (it might not have been handed off to the\n\t\t\t * language processor)\n\t\t\t */\n\t\t\tif ( bInitHandedOff === false )\n\t\t\t{\n\t\t\t\t_fnInitialise( oSettings );\n\t\t\t}\n\t\t} );\n\t\t_that = null;\n\t\treturn this;\n\t};\n\n\t\n\t\n\t/**\n\t * Provide a common method for plug-ins to check the version of DataTables being used, in order\n\t * to ensure compatibility.\n\t *  @param {string} sVersion Version string to check for, in the format \"X.Y.Z\". Note that the\n\t *    formats \"X\" and \"X.Y\" are also acceptable.\n\t *  @returns {boolean} true if this version of DataTables is greater or equal to the required\n\t *    version, or false if this version of DataTales is not suitable\n\t *  @static\n\t *  @dtopt API-Static\n\t *\n\t *  @example\n\t *    alert( $.fn.dataTable.fnVersionCheck( '1.9.0' ) );\n\t */\n\tDataTable.fnVersionCheck = function( sVersion )\n\t{\n\t\t/* This is cheap, but effective */\n\t\tvar fnZPad = function (Zpad, count)\n\t\t{\n\t\t\twhile(Zpad.length < count) {\n\t\t\t\tZpad += '0';\n\t\t\t}\n\t\t\treturn Zpad;\n\t\t};\n\t\tvar aThis = DataTable.ext.sVersion.split('.');\n\t\tvar aThat = sVersion.split('.');\n\t\tvar sThis = '', sThat = '';\n\t\t\n\t\tfor ( var i=0, iLen=aThat.length ; i<iLen ; i++ )\n\t\t{\n\t\t\tsThis += fnZPad( aThis[i], 3 );\n\t\t\tsThat += fnZPad( aThat[i], 3 );\n\t\t}\n\t\t\n\t\treturn parseInt(sThis, 10) >= parseInt(sThat, 10);\n\t};\n\t\n\t\n\t/**\n\t * Check if a TABLE node is a DataTable table already or not.\n\t *  @param {node} nTable The TABLE node to check if it is a DataTable or not (note that other\n\t *    node types can be passed in, but will always return false).\n\t *  @returns {boolean} true the table given is a DataTable, or false otherwise\n\t *  @static\n\t *  @dtopt API-Static\n\t *\n\t *  @example\n\t *    var ex = document.getElementById('example');\n\t *    if ( ! $.fn.DataTable.fnIsDataTable( ex ) ) {\n\t *      $(ex).dataTable();\n\t *    }\n\t */\n\tDataTable.fnIsDataTable = function ( nTable )\n\t{\n\t\tvar o = DataTable.settings;\n\t\n\t\tfor ( var i=0 ; i<o.length ; i++ )\n\t\t{\n\t\t\tif ( o[i].nTable === nTable || o[i].nScrollHead === nTable || o[i].nScrollFoot === nTable )\n\t\t\t{\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\n\t\treturn false;\n\t};\n\t\n\t\n\t/**\n\t * Get all DataTable tables that have been initialised - optionally you can select to\n\t * get only currently visible tables.\n\t *  @param {boolean} [bVisible=false] Flag to indicate if you want all (default) or \n\t *    visible tables only.\n\t *  @returns {array} Array of TABLE nodes (not DataTable instances) which are DataTables\n\t *  @static\n\t *  @dtopt API-Static\n\t *\n\t *  @example\n\t *    var table = $.fn.dataTable.fnTables(true);\n\t *    if ( table.length > 0 ) {\n\t *      $(table).dataTable().fnAdjustColumnSizing();\n\t *    }\n\t */\n\tDataTable.fnTables = function ( bVisible )\n\t{\n\t\tvar out = [];\n\t\n\t\tjQuery.each( DataTable.settings, function (i, o) {\n\t\t\tif ( !bVisible || (bVisible === true && $(o.nTable).is(':visible')) )\n\t\t\t{\n\t\t\t\tout.push( o.nTable );\n\t\t\t}\n\t\t} );\n\t\n\t\treturn out;\n\t};\n\t\n\n\t/**\n\t * Version string for plug-ins to check compatibility. Allowed format is\n\t * a.b.c.d.e where: a:int, b:int, c:int, d:string(dev|beta), e:int. d and\n\t * e are optional\n\t *  @member\n\t *  @type string\n\t *  @default Version number\n\t */\n\tDataTable.version = \"1.9.4\";\n\n\t/**\n\t * Private data store, containing all of the settings objects that are created for the\n\t * tables on a given page.\n\t * \n\t * Note that the <i>DataTable.settings</i> object is aliased to <i>jQuery.fn.dataTableExt</i> \n\t * through which it may be accessed and manipulated, or <i>jQuery.fn.dataTable.settings</i>.\n\t *  @member\n\t *  @type array\n\t *  @default []\n\t *  @private\n\t */\n\tDataTable.settings = [];\n\n\t/**\n\t * Object models container, for the various models that DataTables has available\n\t * to it. These models define the objects that are used to hold the active state \n\t * and configuration of the table.\n\t *  @namespace\n\t */\n\tDataTable.models = {};\n\t\n\t\n\t/**\n\t * DataTables extension options and plug-ins. This namespace acts as a collection \"area\"\n\t * for plug-ins that can be used to extend the default DataTables behaviour - indeed many\n\t * of the build in methods use this method to provide their own capabilities (sorting methods\n\t * for example).\n\t * \n\t * Note that this namespace is aliased to jQuery.fn.dataTableExt so it can be readily accessed\n\t * and modified by plug-ins.\n\t *  @namespace\n\t */\n\tDataTable.models.ext = {\n\t\t/**\n\t\t * Plug-in filtering functions - this method of filtering is complimentary to the default\n\t\t * type based filtering, and a lot more comprehensive as it allows you complete control\n\t\t * over the filtering logic. Each element in this array is a function (parameters\n\t\t * described below) that is called for every row in the table, and your logic decides if\n\t\t * it should be included in the filtered data set or not.\n\t\t *   <ul>\n\t\t *     <li>\n\t\t *       Function input parameters:\n\t\t *       <ul>\n\t\t *         <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li>\n\t\t *         <li>{array|object} Data for the row to be processed (same as the original format\n\t\t *           that was passed in as the data source, or an array from a DOM data source</li>\n\t\t *         <li>{int} Row index in aoData ({@link DataTable.models.oSettings.aoData}), which can\n\t\t *           be useful to retrieve the TR element if you need DOM interaction.</li>\n\t\t *       </ul>\n\t\t *     </li>\n\t\t *     <li>\n\t\t *       Function return:\n\t\t *       <ul>\n\t\t *         <li>{boolean} Include the row in the filtered result set (true) or not (false)</li>\n\t\t *       </ul>\n\t\t *     </il>\n\t\t *   </ul>\n\t\t *  @type array\n\t\t *  @default []\n\t\t *\n\t\t *  @example\n\t\t *    // The following example shows custom filtering being applied to the fourth column (i.e.\n\t\t *    // the aData[3] index) based on two input values from the end-user, matching the data in \n\t\t *    // a certain range.\n\t\t *    $.fn.dataTableExt.afnFiltering.push(\n\t\t *      function( oSettings, aData, iDataIndex ) {\n\t\t *        var iMin = document.getElementById('min').value * 1;\n\t\t *        var iMax = document.getElementById('max').value * 1;\n\t\t *        var iVersion = aData[3] == \"-\" ? 0 : aData[3]*1;\n\t\t *        if ( iMin == \"\" && iMax == \"\" ) {\n\t\t *          return true;\n\t\t *        }\n\t\t *        else if ( iMin == \"\" && iVersion < iMax ) {\n\t\t *          return true;\n\t\t *        }\n\t\t *        else if ( iMin < iVersion && \"\" == iMax ) {\n\t\t *          return true;\n\t\t *        }\n\t\t *        else if ( iMin < iVersion && iVersion < iMax ) {\n\t\t *          return true;\n\t\t *        }\n\t\t *        return false;\n\t\t *      }\n\t\t *    );\n\t\t */\n\t\t\"afnFiltering\": [],\n\t\n\t\n\t\t/**\n\t\t * Plug-in sorting functions - this method of sorting is complimentary to the default type\n\t\t * based sorting that DataTables does automatically, allowing much greater control over the\n\t\t * the data that is being used to sort a column. This is useful if you want to do sorting\n\t\t * based on live data (for example the contents of an 'input' element) rather than just the\n\t\t * static string that DataTables knows of. The way these plug-ins work is that you create\n\t\t * an array of the values you wish to be sorted for the column in question and then return\n\t\t * that array. Which pre-sorting function is run here depends on the sSortDataType parameter\n\t\t * that is used for the column (if any). This is the corollary of <i>ofnSearch</i> for sort \n\t\t * data.\n\t\t *   <ul>\n\t     *     <li>\n\t     *       Function input parameters:\n\t     *       <ul>\n\t\t *         <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li>\n\t     *         <li>{int} Target column index</li>\n\t     *       </ul>\n\t     *     </li>\n\t\t *     <li>\n\t\t *       Function return:\n\t\t *       <ul>\n\t\t *         <li>{array} Data for the column to be sorted upon</li>\n\t\t *       </ul>\n\t\t *     </il>\n\t\t *   </ul>\n\t\t *  \n\t\t * Note that as of v1.9, it is typically preferable to use <i>mData</i> to prepare data for\n\t\t * the different uses that DataTables can put the data to. Specifically <i>mData</i> when\n\t\t * used as a function will give you a 'type' (sorting, filtering etc) that you can use to \n\t\t * prepare the data as required for the different types. As such, this method is deprecated.\n\t\t *  @type array\n\t\t *  @default []\n\t\t *  @deprecated\n\t\t *\n\t\t *  @example\n\t\t *    // Updating the cached sorting information with user entered values in HTML input elements\n\t\t *    jQuery.fn.dataTableExt.afnSortData['dom-text'] = function ( oSettings, iColumn )\n\t\t *    {\n\t\t *      var aData = [];\n\t\t *      $( 'td:eq('+iColumn+') input', oSettings.oApi._fnGetTrNodes(oSettings) ).each( function () {\n\t\t *        aData.push( this.value );\n\t\t *      } );\n\t\t *      return aData;\n\t\t *    }\n\t\t */\n\t\t\"afnSortData\": [],\n\t\n\t\n\t\t/**\n\t\t * Feature plug-ins - This is an array of objects which describe the feature plug-ins that are\n\t\t * available to DataTables. These feature plug-ins are accessible through the sDom initialisation\n\t\t * option. As such, each feature plug-in must describe a function that is used to initialise\n\t\t * itself (fnInit), a character so the feature can be enabled by sDom (cFeature) and the name\n\t\t * of the feature (sFeature). Thus the objects attached to this method must provide:\n\t\t *   <ul>\n\t\t *     <li>{function} fnInit Initialisation of the plug-in\n\t\t *       <ul>\n\t     *         <li>\n\t     *           Function input parameters:\n\t     *           <ul>\n\t\t *             <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li>\n\t     *           </ul>\n\t     *         </li>\n\t\t *         <li>\n\t\t *           Function return:\n\t\t *           <ul>\n\t\t *             <li>{node|null} The element which contains your feature. Note that the return\n\t\t *                may also be void if your plug-in does not require to inject any DOM elements \n\t\t *                into DataTables control (sDom) - for example this might be useful when \n\t\t *                developing a plug-in which allows table control via keyboard entry.</li>\n\t\t *           </ul>\n\t\t *         </il>\n\t\t *       </ul>\n\t\t *     </li>\n\t\t *     <li>{character} cFeature Character that will be matched in sDom - case sensitive</li>\n\t\t *     <li>{string} sFeature Feature name</li>\n\t\t *   </ul>\n\t\t *  @type array\n\t\t *  @default []\n\t\t * \n\t\t *  @example\n\t\t *    // How TableTools initialises itself.\n\t\t *    $.fn.dataTableExt.aoFeatures.push( {\n\t\t *      \"fnInit\": function( oSettings ) {\n\t\t *        return new TableTools( { \"oDTSettings\": oSettings } );\n\t\t *      },\n\t\t *      \"cFeature\": \"T\",\n\t\t *      \"sFeature\": \"TableTools\"\n\t\t *    } );\n\t\t */\n\t\t\"aoFeatures\": [],\n\t\n\t\n\t\t/**\n\t\t * Type detection plug-in functions - DataTables utilises types to define how sorting and\n\t\t * filtering behave, and types can be either  be defined by the developer (sType for the\n\t\t * column) or they can be automatically detected by the methods in this array. The functions\n\t\t * defined in the array are quite simple, taking a single parameter (the data to analyse) \n\t\t * and returning the type if it is a known type, or null otherwise.\n\t\t *   <ul>\n\t     *     <li>\n\t     *       Function input parameters:\n\t     *       <ul>\n\t\t *         <li>{*} Data from the column cell to be analysed</li>\n\t     *       </ul>\n\t     *     </li>\n\t\t *     <li>\n\t\t *       Function return:\n\t\t *       <ul>\n\t\t *         <li>{string|null} Data type detected, or null if unknown (and thus pass it\n\t\t *           on to the other type detection functions.</li>\n\t\t *       </ul>\n\t\t *     </il>\n\t\t *   </ul>\n\t\t *  @type array\n\t\t *  @default []\n\t\t *  \n\t\t *  @example\n\t\t *    // Currency type detection plug-in:\n\t\t *    jQuery.fn.dataTableExt.aTypes.push(\n\t\t *      function ( sData ) {\n\t\t *        var sValidChars = \"0123456789.-\";\n\t\t *        var Char;\n\t\t *        \n\t\t *        // Check the numeric part\n\t\t *        for ( i=1 ; i<sData.length ; i++ ) {\n\t\t *          Char = sData.charAt(i); \n\t\t *          if (sValidChars.indexOf(Char) == -1) {\n\t\t *            return null;\n\t\t *          }\n\t\t *        }\n\t\t *        \n\t\t *        // Check prefixed by currency\n\t\t *        if ( sData.charAt(0) == '$' || sData.charAt(0) == '&pound;' ) {\n\t\t *          return 'currency';\n\t\t *        }\n\t\t *        return null;\n\t\t *      }\n\t\t *    );\n\t\t */\n\t\t\"aTypes\": [],\n\t\n\t\n\t\t/**\n\t\t * Provide a common method for plug-ins to check the version of DataTables being used, \n\t\t * in order to ensure compatibility.\n\t\t *  @type function\n\t\t *  @param {string} sVersion Version string to check for, in the format \"X.Y.Z\". Note \n\t\t *    that the formats \"X\" and \"X.Y\" are also acceptable.\n\t\t *  @returns {boolean} true if this version of DataTables is greater or equal to the \n\t\t *    required version, or false if this version of DataTales is not suitable\n\t\t *\n\t\t *  @example\n\t\t *    $(document).ready(function() {\n\t\t *      var oTable = $('#example').dataTable();\n\t\t *      alert( oTable.fnVersionCheck( '1.9.0' ) );\n\t\t *    } );\n\t\t */\n\t\t\"fnVersionCheck\": DataTable.fnVersionCheck,\n\t\n\t\n\t\t/**\n\t\t * Index for what 'this' index API functions should use\n\t\t *  @type int\n\t\t *  @default 0\n\t\t */\n\t\t\"iApiIndex\": 0,\n\t\n\t\n\t\t/**\n\t\t * Pre-processing of filtering data plug-ins - When you assign the sType for a column\n\t\t * (or have it automatically detected for you by DataTables or a type detection plug-in), \n\t\t * you will typically be using this for custom sorting, but it can also be used to provide \n\t\t * custom filtering by allowing you to pre-processing the data and returning the data in\n\t\t * the format that should be filtered upon. This is done by adding functions this object \n\t\t * with a parameter name which matches the sType for that target column. This is the\n\t\t * corollary of <i>afnSortData</i> for filtering data.\n\t\t *   <ul>\n\t     *     <li>\n\t     *       Function input parameters:\n\t     *       <ul>\n\t\t *         <li>{*} Data from the column cell to be prepared for filtering</li>\n\t     *       </ul>\n\t     *     </li>\n\t\t *     <li>\n\t\t *       Function return:\n\t\t *       <ul>\n\t\t *         <li>{string|null} Formatted string that will be used for the filtering.</li>\n\t\t *       </ul>\n\t\t *     </il>\n\t\t *   </ul>\n\t\t * \n\t\t * Note that as of v1.9, it is typically preferable to use <i>mData</i> to prepare data for\n\t\t * the different uses that DataTables can put the data to. Specifically <i>mData</i> when\n\t\t * used as a function will give you a 'type' (sorting, filtering etc) that you can use to \n\t\t * prepare the data as required for the different types. As such, this method is deprecated.\n\t\t *  @type object\n\t\t *  @default {}\n\t\t *  @deprecated\n\t\t *\n\t\t *  @example\n\t\t *    $.fn.dataTableExt.ofnSearch['title-numeric'] = function ( sData ) {\n\t\t *      return sData.replace(/\\n/g,\" \").replace( /<.*?>/g, \"\" );\n\t\t *    }\n\t\t */\n\t\t\"ofnSearch\": {},\n\t\n\t\n\t\t/**\n\t\t * Container for all private functions in DataTables so they can be exposed externally\n\t\t *  @type object\n\t\t *  @default {}\n\t\t */\n\t\t\"oApi\": {},\n\t\n\t\n\t\t/**\n\t\t * Storage for the various classes that DataTables uses\n\t\t *  @type object\n\t\t *  @default {}\n\t\t */\n\t\t\"oStdClasses\": {},\n\t\t\n\t\n\t\t/**\n\t\t * Storage for the various classes that DataTables uses - jQuery UI suitable\n\t\t *  @type object\n\t\t *  @default {}\n\t\t */\n\t\t\"oJUIClasses\": {},\n\t\n\t\n\t\t/**\n\t\t * Pagination plug-in methods - The style and controls of the pagination can significantly \n\t\t * impact on how the end user interacts with the data in your table, and DataTables allows \n\t\t * the addition of pagination controls by extending this object, which can then be enabled\n\t\t * through the <i>sPaginationType</i> initialisation parameter. Each pagination type that\n\t\t * is added is an object (the property name of which is what <i>sPaginationType</i> refers\n\t\t * to) that has two properties, both methods that are used by DataTables to update the\n\t\t * control's state.\n\t\t *   <ul>\n\t\t *     <li>\n\t\t *       fnInit -  Initialisation of the paging controls. Called only during initialisation \n\t\t *         of the table. It is expected that this function will add the required DOM elements \n\t\t *         to the page for the paging controls to work. The element pointer \n\t\t *         'oSettings.aanFeatures.p' array is provided by DataTables to contain the paging \n\t\t *         controls (note that this is a 2D array to allow for multiple instances of each \n\t\t *         DataTables DOM element). It is suggested that you add the controls to this element \n\t\t *         as children\n\t\t *       <ul>\n\t     *         <li>\n\t     *           Function input parameters:\n\t     *           <ul>\n\t\t *             <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li>\n\t\t *             <li>{node} Container into which the pagination controls must be inserted</li>\n\t\t *             <li>{function} Draw callback function - whenever the controls cause a page\n\t\t *               change, this method must be called to redraw the table.</li>\n\t     *           </ul>\n\t     *         </li>\n\t\t *         <li>\n\t\t *           Function return:\n\t\t *           <ul>\n\t\t *             <li>No return required</li>\n\t\t *           </ul>\n\t\t *         </il>\n\t\t *       </ul>\n\t\t *     </il>\n\t\t *     <li>\n\t\t *       fnInit -  This function is called whenever the paging status of the table changes and is\n\t\t *         typically used to update classes and/or text of the paging controls to reflex the new \n\t\t *         status.\n\t\t *       <ul>\n\t     *         <li>\n\t     *           Function input parameters:\n\t     *           <ul>\n\t\t *             <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li>\n\t\t *             <li>{function} Draw callback function - in case you need to redraw the table again\n\t\t *               or attach new event listeners</li>\n\t     *           </ul>\n\t     *         </li>\n\t\t *         <li>\n\t\t *           Function return:\n\t\t *           <ul>\n\t\t *             <li>No return required</li>\n\t\t *           </ul>\n\t\t *         </il>\n\t\t *       </ul>\n\t\t *     </il>\n\t\t *   </ul>\n\t\t *  @type object\n\t\t *  @default {}\n\t\t *\n\t\t *  @example\n\t\t *    $.fn.dataTableExt.oPagination.four_button = {\n\t\t *      \"fnInit\": function ( oSettings, nPaging, fnCallbackDraw ) {\n\t\t *        nFirst = document.createElement( 'span' );\n\t\t *        nPrevious = document.createElement( 'span' );\n\t\t *        nNext = document.createElement( 'span' );\n\t\t *        nLast = document.createElement( 'span' );\n\t\t *        \n\t\t *        nFirst.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sFirst ) );\n\t\t *        nPrevious.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sPrevious ) );\n\t\t *        nNext.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sNext ) );\n\t\t *        nLast.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sLast ) );\n\t\t *        \n\t\t *        nFirst.className = \"paginate_button first\";\n\t\t *        nPrevious.className = \"paginate_button previous\";\n\t\t *        nNext.className=\"paginate_button next\";\n\t\t *        nLast.className = \"paginate_button last\";\n\t\t *        \n\t\t *        nPaging.appendChild( nFirst );\n\t\t *        nPaging.appendChild( nPrevious );\n\t\t *        nPaging.appendChild( nNext );\n\t\t *        nPaging.appendChild( nLast );\n\t\t *        \n\t\t *        $(nFirst).click( function () {\n\t\t *          oSettings.oApi._fnPageChange( oSettings, \"first\" );\n\t\t *          fnCallbackDraw( oSettings );\n\t\t *        } );\n\t\t *        \n\t\t *        $(nPrevious).click( function() {\n\t\t *          oSettings.oApi._fnPageChange( oSettings, \"previous\" );\n\t\t *          fnCallbackDraw( oSettings );\n\t\t *        } );\n\t\t *        \n\t\t *        $(nNext).click( function() {\n\t\t *          oSettings.oApi._fnPageChange( oSettings, \"next\" );\n\t\t *          fnCallbackDraw( oSettings );\n\t\t *        } );\n\t\t *        \n\t\t *        $(nLast).click( function() {\n\t\t *          oSettings.oApi._fnPageChange( oSettings, \"last\" );\n\t\t *          fnCallbackDraw( oSettings );\n\t\t *        } );\n\t\t *        \n\t\t *        $(nFirst).bind( 'selectstart', function () { return false; } );\n\t\t *        $(nPrevious).bind( 'selectstart', function () { return false; } );\n\t\t *        $(nNext).bind( 'selectstart', function () { return false; } );\n\t\t *        $(nLast).bind( 'selectstart', function () { return false; } );\n\t\t *      },\n\t\t *      \n\t\t *      \"fnUpdate\": function ( oSettings, fnCallbackDraw ) {\n\t\t *        if ( !oSettings.aanFeatures.p ) {\n\t\t *          return;\n\t\t *        }\n\t\t *        \n\t\t *        // Loop over each instance of the pager\n\t\t *        var an = oSettings.aanFeatures.p;\n\t\t *        for ( var i=0, iLen=an.length ; i<iLen ; i++ ) {\n\t\t *          var buttons = an[i].getElementsByTagName('span');\n\t\t *          if ( oSettings._iDisplayStart === 0 ) {\n\t\t *            buttons[0].className = \"paginate_disabled_previous\";\n\t\t *            buttons[1].className = \"paginate_disabled_previous\";\n\t\t *          }\n\t\t *          else {\n\t\t *            buttons[0].className = \"paginate_enabled_previous\";\n\t\t *            buttons[1].className = \"paginate_enabled_previous\";\n\t\t *          }\n\t\t *          \n\t\t *          if ( oSettings.fnDisplayEnd() == oSettings.fnRecordsDisplay() ) {\n\t\t *            buttons[2].className = \"paginate_disabled_next\";\n\t\t *            buttons[3].className = \"paginate_disabled_next\";\n\t\t *          }\n\t\t *          else {\n\t\t *            buttons[2].className = \"paginate_enabled_next\";\n\t\t *            buttons[3].className = \"paginate_enabled_next\";\n\t\t *          }\n\t\t *        }\n\t\t *      }\n\t\t *    };\n\t\t */\n\t\t\"oPagination\": {},\n\t\n\t\n\t\t/**\n\t\t * Sorting plug-in methods - Sorting in DataTables is based on the detected type of the\n\t\t * data column (you can add your own type detection functions, or override automatic \n\t\t * detection using sType). With this specific type given to the column, DataTables will \n\t\t * apply the required sort from the functions in the object. Each sort type must provide\n\t\t * two mandatory methods, one each for ascending and descending sorting, and can optionally\n\t\t * provide a pre-formatting method that will help speed up sorting by allowing DataTables\n\t\t * to pre-format the sort data only once (rather than every time the actual sort functions\n\t\t * are run). The two sorting functions are typical Javascript sort methods:\n\t\t *   <ul>\n\t     *     <li>\n\t     *       Function input parameters:\n\t     *       <ul>\n\t\t *         <li>{*} Data to compare to the second parameter</li>\n\t\t *         <li>{*} Data to compare to the first parameter</li>\n\t     *       </ul>\n\t     *     </li>\n\t\t *     <li>\n\t\t *       Function return:\n\t\t *       <ul>\n\t\t *         <li>{int} Sorting match: <0 if first parameter should be sorted lower than\n\t\t *           the second parameter, ===0 if the two parameters are equal and >0 if\n\t\t *           the first parameter should be sorted height than the second parameter.</li>\n\t\t *       </ul>\n\t\t *     </il>\n\t\t *   </ul>\n\t\t *  @type object\n\t\t *  @default {}\n\t\t *\n\t\t *  @example\n\t\t *    // Case-sensitive string sorting, with no pre-formatting method\n\t\t *    $.extend( $.fn.dataTableExt.oSort, {\n\t\t *      \"string-case-asc\": function(x,y) {\n\t\t *        return ((x < y) ? -1 : ((x > y) ? 1 : 0));\n\t\t *      },\n\t\t *      \"string-case-desc\": function(x,y) {\n\t\t *        return ((x < y) ? 1 : ((x > y) ? -1 : 0));\n\t\t *      }\n\t\t *    } );\n\t\t *\n\t\t *  @example\n\t\t *    // Case-insensitive string sorting, with pre-formatting\n\t\t *    $.extend( $.fn.dataTableExt.oSort, {\n\t\t *      \"string-pre\": function(x) {\n\t\t *        return x.toLowerCase();\n\t\t *      },\n\t\t *      \"string-asc\": function(x,y) {\n\t\t *        return ((x < y) ? -1 : ((x > y) ? 1 : 0));\n\t\t *      },\n\t\t *      \"string-desc\": function(x,y) {\n\t\t *        return ((x < y) ? 1 : ((x > y) ? -1 : 0));\n\t\t *      }\n\t\t *    } );\n\t\t */\n\t\t\"oSort\": {},\n\t\n\t\n\t\t/**\n\t\t * Version string for plug-ins to check compatibility. Allowed format is\n\t\t * a.b.c.d.e where: a:int, b:int, c:int, d:string(dev|beta), e:int. d and\n\t\t * e are optional\n\t\t *  @type string\n\t\t *  @default Version number\n\t\t */\n\t\t\"sVersion\": DataTable.version,\n\t\n\t\n\t\t/**\n\t\t * How should DataTables report an error. Can take the value 'alert' or 'throw'\n\t\t *  @type string\n\t\t *  @default alert\n\t\t */\n\t\t\"sErrMode\": \"alert\",\n\t\n\t\n\t\t/**\n\t\t * Store information for DataTables to access globally about other instances\n\t\t *  @namespace\n\t\t *  @private\n\t\t */\n\t\t\"_oExternConfig\": {\n\t\t\t/* int:iNextUnique - next unique number for an instance */\n\t\t\t\"iNextUnique\": 0\n\t\t}\n\t};\n\t\n\t\n\t\n\t\n\t/**\n\t * Template object for the way in which DataTables holds information about\n\t * search information for the global filter and individual column filters.\n\t *  @namespace\n\t */\n\tDataTable.models.oSearch = {\n\t\t/**\n\t\t * Flag to indicate if the filtering should be case insensitive or not\n\t\t *  @type boolean\n\t\t *  @default true\n\t\t */\n\t\t\"bCaseInsensitive\": true,\n\t\n\t\t/**\n\t\t * Applied search term\n\t\t *  @type string\n\t\t *  @default <i>Empty string</i>\n\t\t */\n\t\t\"sSearch\": \"\",\n\t\n\t\t/**\n\t\t * Flag to indicate if the search term should be interpreted as a\n\t\t * regular expression (true) or not (false) and therefore and special\n\t\t * regex characters escaped.\n\t\t *  @type boolean\n\t\t *  @default false\n\t\t */\n\t\t\"bRegex\": false,\n\t\n\t\t/**\n\t\t * Flag to indicate if DataTables is to use its smart filtering or not.\n\t\t *  @type boolean\n\t\t *  @default true\n\t\t */\n\t\t\"bSmart\": true\n\t};\n\t\n\t\n\t\n\t\n\t/**\n\t * Template object for the way in which DataTables holds information about\n\t * each individual row. This is the object format used for the settings \n\t * aoData array.\n\t *  @namespace\n\t */\n\tDataTable.models.oRow = {\n\t\t/**\n\t\t * TR element for the row\n\t\t *  @type node\n\t\t *  @default null\n\t\t */\n\t\t\"nTr\": null,\n\t\n\t\t/**\n\t\t * Data object from the original data source for the row. This is either\n\t\t * an array if using the traditional form of DataTables, or an object if\n\t\t * using mData options. The exact type will depend on the passed in\n\t\t * data from the data source, or will be an array if using DOM a data \n\t\t * source.\n\t\t *  @type array|object\n\t\t *  @default []\n\t\t */\n\t\t\"_aData\": [],\n\t\n\t\t/**\n\t\t * Sorting data cache - this array is ostensibly the same length as the\n\t\t * number of columns (although each index is generated only as it is \n\t\t * needed), and holds the data that is used for sorting each column in the\n\t\t * row. We do this cache generation at the start of the sort in order that\n\t\t * the formatting of the sort data need be done only once for each cell\n\t\t * per sort. This array should not be read from or written to by anything\n\t\t * other than the master sorting methods.\n\t\t *  @type array\n\t\t *  @default []\n\t\t *  @private\n\t\t */\n\t\t\"_aSortData\": [],\n\t\n\t\t/**\n\t\t * Array of TD elements that are cached for hidden rows, so they can be\n\t\t * reinserted into the table if a column is made visible again (or to act\n\t\t * as a store if a column is made hidden). Only hidden columns have a \n\t\t * reference in the array. For non-hidden columns the value is either\n\t\t * undefined or null.\n\t\t *  @type array nodes\n\t\t *  @default []\n\t\t *  @private\n\t\t */\n\t\t\"_anHidden\": [],\n\t\n\t\t/**\n\t\t * Cache of the class name that DataTables has applied to the row, so we\n\t\t * can quickly look at this variable rather than needing to do a DOM check\n\t\t * on className for the nTr property.\n\t\t *  @type string\n\t\t *  @default <i>Empty string</i>\n\t\t *  @private\n\t\t */\n\t\t\"_sRowStripe\": \"\"\n\t};\n\t\n\t\n\t\n\t/**\n\t * Template object for the column information object in DataTables. This object\n\t * is held in the settings aoColumns array and contains all the information that\n\t * DataTables needs about each individual column.\n\t * \n\t * Note that this object is related to {@link DataTable.defaults.columns} \n\t * but this one is the internal data store for DataTables's cache of columns.\n\t * It should NOT be manipulated outside of DataTables. Any configuration should\n\t * be done through the initialisation options.\n\t *  @namespace\n\t */\n\tDataTable.models.oColumn = {\n\t\t/**\n\t\t * A list of the columns that sorting should occur on when this column\n\t\t * is sorted. That this property is an array allows multi-column sorting\n\t\t * to be defined for a column (for example first name / last name columns\n\t\t * would benefit from this). The values are integers pointing to the\n\t\t * columns to be sorted on (typically it will be a single integer pointing\n\t\t * at itself, but that doesn't need to be the case).\n\t\t *  @type array\n\t\t */\n\t\t\"aDataSort\": null,\n\t\n\t\t/**\n\t\t * Define the sorting directions that are applied to the column, in sequence\n\t\t * as the column is repeatedly sorted upon - i.e. the first value is used\n\t\t * as the sorting direction when the column if first sorted (clicked on).\n\t\t * Sort it again (click again) and it will move on to the next index.\n\t\t * Repeat until loop.\n\t\t *  @type array\n\t\t */\n\t\t\"asSorting\": null,\n\t\t\n\t\t/**\n\t\t * Flag to indicate if the column is searchable, and thus should be included\n\t\t * in the filtering or not.\n\t\t *  @type boolean\n\t\t */\n\t\t\"bSearchable\": null,\n\t\t\n\t\t/**\n\t\t * Flag to indicate if the column is sortable or not.\n\t\t *  @type boolean\n\t\t */\n\t\t\"bSortable\": null,\n\t\t\n\t\t/**\n\t\t * <code>Deprecated</code> When using fnRender, you have two options for what \n\t\t * to do with the data, and this property serves as the switch. Firstly, you \n\t\t * can have the sorting and filtering use the rendered value (true - default), \n\t\t * or you can have the sorting and filtering us the original value (false).\n\t\t *\n\t\t * Please note that this option has now been deprecated and will be removed\n\t\t * in the next version of DataTables. Please use mRender / mData rather than\n\t\t * fnRender.\n\t\t *  @type boolean\n\t\t *  @deprecated\n\t\t */\n\t\t\"bUseRendered\": null,\n\t\t\n\t\t/**\n\t\t * Flag to indicate if the column is currently visible in the table or not\n\t\t *  @type boolean\n\t\t */\n\t\t\"bVisible\": null,\n\t\t\n\t\t/**\n\t\t * Flag to indicate to the type detection method if the automatic type\n\t\t * detection should be used, or if a column type (sType) has been specified\n\t\t *  @type boolean\n\t\t *  @default true\n\t\t *  @private\n\t\t */\n\t\t\"_bAutoType\": true,\n\t\t\n\t\t/**\n\t\t * Developer definable function that is called whenever a cell is created (Ajax source,\n\t\t * etc) or processed for input (DOM source). This can be used as a compliment to mRender\n\t\t * allowing you to modify the DOM element (add background colour for example) when the\n\t\t * element is available.\n\t\t *  @type function\n\t\t *  @param {element} nTd The TD node that has been created\n\t\t *  @param {*} sData The Data for the cell\n\t\t *  @param {array|object} oData The data for the whole row\n\t\t *  @param {int} iRow The row index for the aoData data store\n\t\t *  @default null\n\t\t */\n\t\t\"fnCreatedCell\": null,\n\t\t\n\t\t/**\n\t\t * Function to get data from a cell in a column. You should <b>never</b>\n\t\t * access data directly through _aData internally in DataTables - always use\n\t\t * the method attached to this property. It allows mData to function as\n\t\t * required. This function is automatically assigned by the column \n\t\t * initialisation method\n\t\t *  @type function\n\t\t *  @param {array|object} oData The data array/object for the array \n\t\t *    (i.e. aoData[]._aData)\n\t\t *  @param {string} sSpecific The specific data type you want to get - \n\t\t *    'display', 'type' 'filter' 'sort'\n\t\t *  @returns {*} The data for the cell from the given row's data\n\t\t *  @default null\n\t\t */\n\t\t\"fnGetData\": null,\n\t\t\n\t\t/**\n\t\t * <code>Deprecated</code> Custom display function that will be called for the \n\t\t * display of each cell in this column.\n\t\t *\n\t\t * Please note that this option has now been deprecated and will be removed\n\t\t * in the next version of DataTables. Please use mRender / mData rather than\n\t\t * fnRender.\n\t\t *  @type function\n\t\t *  @param {object} o Object with the following parameters:\n\t\t *  @param {int}    o.iDataRow The row in aoData\n\t\t *  @param {int}    o.iDataColumn The column in question\n\t\t *  @param {array}  o.aData The data for the row in question\n\t\t *  @param {object} o.oSettings The settings object for this DataTables instance\n\t\t *  @returns {string} The string you which to use in the display\n\t\t *  @default null\n\t\t *  @deprecated\n\t\t */\n\t\t\"fnRender\": null,\n\t\t\n\t\t/**\n\t\t * Function to set data for a cell in the column. You should <b>never</b> \n\t\t * set the data directly to _aData internally in DataTables - always use\n\t\t * this method. It allows mData to function as required. This function\n\t\t * is automatically assigned by the column initialisation method\n\t\t *  @type function\n\t\t *  @param {array|object} oData The data array/object for the array \n\t\t *    (i.e. aoData[]._aData)\n\t\t *  @param {*} sValue Value to set\n\t\t *  @default null\n\t\t */\n\t\t\"fnSetData\": null,\n\t\t\n\t\t/**\n\t\t * Property to read the value for the cells in the column from the data \n\t\t * source array / object. If null, then the default content is used, if a\n\t\t * function is given then the return from the function is used.\n\t\t *  @type function|int|string|null\n\t\t *  @default null\n\t\t */\n\t\t\"mData\": null,\n\t\t\n\t\t/**\n\t\t * Partner property to mData which is used (only when defined) to get\n\t\t * the data - i.e. it is basically the same as mData, but without the\n\t\t * 'set' option, and also the data fed to it is the result from mData.\n\t\t * This is the rendering method to match the data method of mData.\n\t\t *  @type function|int|string|null\n\t\t *  @default null\n\t\t */\n\t\t\"mRender\": null,\n\t\t\n\t\t/**\n\t\t * Unique header TH/TD element for this column - this is what the sorting\n\t\t * listener is attached to (if sorting is enabled.)\n\t\t *  @type node\n\t\t *  @default null\n\t\t */\n\t\t\"nTh\": null,\n\t\t\n\t\t/**\n\t\t * Unique footer TH/TD element for this column (if there is one). Not used \n\t\t * in DataTables as such, but can be used for plug-ins to reference the \n\t\t * footer for each column.\n\t\t *  @type node\n\t\t *  @default null\n\t\t */\n\t\t\"nTf\": null,\n\t\t\n\t\t/**\n\t\t * The class to apply to all TD elements in the table's TBODY for the column\n\t\t *  @type string\n\t\t *  @default null\n\t\t */\n\t\t\"sClass\": null,\n\t\t\n\t\t/**\n\t\t * When DataTables calculates the column widths to assign to each column,\n\t\t * it finds the longest string in each column and then constructs a\n\t\t * temporary table and reads the widths from that. The problem with this\n\t\t * is that \"mmm\" is much wider then \"iiii\", but the latter is a longer \n\t\t * string - thus the calculation can go wrong (doing it properly and putting\n\t\t * it into an DOM object and measuring that is horribly(!) slow). Thus as\n\t\t * a \"work around\" we provide this option. It will append its value to the\n\t\t * text that is found to be the longest string for the column - i.e. padding.\n\t\t *  @type string\n\t\t */\n\t\t\"sContentPadding\": null,\n\t\t\n\t\t/**\n\t\t * Allows a default value to be given for a column's data, and will be used\n\t\t * whenever a null data source is encountered (this can be because mData\n\t\t * is set to null, or because the data source itself is null).\n\t\t *  @type string\n\t\t *  @default null\n\t\t */\n\t\t\"sDefaultContent\": null,\n\t\t\n\t\t/**\n\t\t * Name for the column, allowing reference to the column by name as well as\n\t\t * by index (needs a lookup to work by name).\n\t\t *  @type string\n\t\t */\n\t\t\"sName\": null,\n\t\t\n\t\t/**\n\t\t * Custom sorting data type - defines which of the available plug-ins in\n\t\t * afnSortData the custom sorting will use - if any is defined.\n\t\t *  @type string\n\t\t *  @default std\n\t\t */\n\t\t\"sSortDataType\": 'std',\n\t\t\n\t\t/**\n\t\t * Class to be applied to the header element when sorting on this column\n\t\t *  @type string\n\t\t *  @default null\n\t\t */\n\t\t\"sSortingClass\": null,\n\t\t\n\t\t/**\n\t\t * Class to be applied to the header element when sorting on this column -\n\t\t * when jQuery UI theming is used.\n\t\t *  @type string\n\t\t *  @default null\n\t\t */\n\t\t\"sSortingClassJUI\": null,\n\t\t\n\t\t/**\n\t\t * Title of the column - what is seen in the TH element (nTh).\n\t\t *  @type string\n\t\t */\n\t\t\"sTitle\": null,\n\t\t\n\t\t/**\n\t\t * Column sorting and filtering type\n\t\t *  @type string\n\t\t *  @default null\n\t\t */\n\t\t\"sType\": null,\n\t\t\n\t\t/**\n\t\t * Width of the column\n\t\t *  @type string\n\t\t *  @default null\n\t\t */\n\t\t\"sWidth\": null,\n\t\t\n\t\t/**\n\t\t * Width of the column when it was first \"encountered\"\n\t\t *  @type string\n\t\t *  @default null\n\t\t */\n\t\t\"sWidthOrig\": null\n\t};\n\t\n\t\n\t\n\t/**\n\t * Initialisation options that can be given to DataTables at initialisation \n\t * time.\n\t *  @namespace\n\t */\n\tDataTable.defaults = {\n\t\t/**\n\t\t * An array of data to use for the table, passed in at initialisation which \n\t\t * will be used in preference to any data which is already in the DOM. This is\n\t\t * particularly useful for constructing tables purely in Javascript, for\n\t\t * example with a custom Ajax call.\n\t\t *  @type array\n\t\t *  @default null\n\t\t *  @dtopt Option\n\t\t * \n\t\t *  @example\n\t\t *    // Using a 2D array data source\n\t\t *    $(document).ready( function () {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"aaData\": [\n\t\t *          ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],\n\t\t *          ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],\n\t\t *        ],\n\t\t *        \"aoColumns\": [\n\t\t *          { \"sTitle\": \"Engine\" },\n\t\t *          { \"sTitle\": \"Browser\" },\n\t\t *          { \"sTitle\": \"Platform\" },\n\t\t *          { \"sTitle\": \"Version\" },\n\t\t *          { \"sTitle\": \"Grade\" }\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t *    \n\t\t *  @example\n\t\t *    // Using an array of objects as a data source (mData)\n\t\t *    $(document).ready( function () {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"aaData\": [\n\t\t *          {\n\t\t *            \"engine\":   \"Trident\",\n\t\t *            \"browser\":  \"Internet Explorer 4.0\",\n\t\t *            \"platform\": \"Win 95+\",\n\t\t *            \"version\":  4,\n\t\t *            \"grade\":    \"X\"\n\t\t *          },\n\t\t *          {\n\t\t *            \"engine\":   \"Trident\",\n\t\t *            \"browser\":  \"Internet Explorer 5.0\",\n\t\t *            \"platform\": \"Win 95+\",\n\t\t *            \"version\":  5,\n\t\t *            \"grade\":    \"C\"\n\t\t *          }\n\t\t *        ],\n\t\t *        \"aoColumns\": [\n\t\t *          { \"sTitle\": \"Engine\",   \"mData\": \"engine\" },\n\t\t *          { \"sTitle\": \"Browser\",  \"mData\": \"browser\" },\n\t\t *          { \"sTitle\": \"Platform\", \"mData\": \"platform\" },\n\t\t *          { \"sTitle\": \"Version\",  \"mData\": \"version\" },\n\t\t *          { \"sTitle\": \"Grade\",    \"mData\": \"grade\" }\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"aaData\": null,\n\t\n\t\n\t\t/**\n\t\t * If sorting is enabled, then DataTables will perform a first pass sort on \n\t\t * initialisation. You can define which column(s) the sort is performed upon, \n\t\t * and the sorting direction, with this variable. The aaSorting array should \n\t\t * contain an array for each column to be sorted initially containing the \n\t\t * column's index and a direction string ('asc' or 'desc').\n\t\t *  @type array\n\t\t *  @default [[0,'asc']]\n\t\t *  @dtopt Option\n\t\t * \n\t\t *  @example\n\t\t *    // Sort by 3rd column first, and then 4th column\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"aaSorting\": [[2,'asc'], [3,'desc']]\n\t\t *      } );\n\t\t *    } );\n\t\t *    \n\t\t *    // No initial sorting\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"aaSorting\": []\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"aaSorting\": [[0,'asc']],\n\t\n\t\n\t\t/**\n\t\t * This parameter is basically identical to the aaSorting parameter, but \n\t\t * cannot be overridden by user interaction with the table. What this means \n\t\t * is that you could have a column (visible or hidden) which the sorting will \n\t\t * always be forced on first - any sorting after that (from the user) will \n\t\t * then be performed as required. This can be useful for grouping rows \n\t\t * together.\n\t\t *  @type array\n\t\t *  @default null\n\t\t *  @dtopt Option\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"aaSortingFixed\": [[0,'asc']]\n\t\t *      } );\n\t\t *    } )\n\t\t */\n\t\t\"aaSortingFixed\": null,\n\t\n\t\n\t\t/**\n\t\t * This parameter allows you to readily specify the entries in the length drop\n\t\t * down menu that DataTables shows when pagination is enabled. It can be \n\t\t * either a 1D array of options which will be used for both the displayed \n\t\t * option and the value, or a 2D array which will use the array in the first \n\t\t * position as the value, and the array in the second position as the \n\t\t * displayed options (useful for language strings such as 'All').\n\t\t *  @type array\n\t\t *  @default [ 10, 25, 50, 100 ]\n\t\t *  @dtopt Option\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"aLengthMenu\": [[10, 25, 50, -1], [10, 25, 50, \"All\"]]\n\t\t *      } );\n\t\t *    } );\n\t\t *  \n\t\t *  @example\n\t\t *    // Setting the default display length as well as length menu\n\t\t *    // This is likely to be wanted if you remove the '10' option which\n\t\t *    // is the iDisplayLength default.\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"iDisplayLength\": 25,\n\t\t *        \"aLengthMenu\": [[25, 50, 100, -1], [25, 50, 100, \"All\"]]\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"aLengthMenu\": [ 10, 25, 50, 100 ],\n\t\n\t\n\t\t/**\n\t\t * The aoColumns option in the initialisation parameter allows you to define\n\t\t * details about the way individual columns behave. For a full list of\n\t\t * column options that can be set, please see \n\t\t * {@link DataTable.defaults.columns}. Note that if you use aoColumns to\n\t\t * define your columns, you must have an entry in the array for every single\n\t\t * column that you have in your table (these can be null if you don't which\n\t\t * to specify any options).\n\t\t *  @member\n\t\t */\n\t\t\"aoColumns\": null,\n\t\n\t\t/**\n\t\t * Very similar to aoColumns, aoColumnDefs allows you to target a specific \n\t\t * column, multiple columns, or all columns, using the aTargets property of \n\t\t * each object in the array. This allows great flexibility when creating \n\t\t * tables, as the aoColumnDefs arrays can be of any length, targeting the \n\t\t * columns you specifically want. aoColumnDefs may use any of the column \n\t\t * options available: {@link DataTable.defaults.columns}, but it _must_\n\t\t * have aTargets defined in each object in the array. Values in the aTargets\n\t\t * array may be:\n\t\t *   <ul>\n\t\t *     <li>a string - class name will be matched on the TH for the column</li>\n\t\t *     <li>0 or a positive integer - column index counting from the left</li>\n\t\t *     <li>a negative integer - column index counting from the right</li>\n\t\t *     <li>the string \"_all\" - all columns (i.e. assign a default)</li>\n\t\t *   </ul>\n\t\t *  @member\n\t\t */\n\t\t\"aoColumnDefs\": null,\n\t\n\t\n\t\t/**\n\t\t * Basically the same as oSearch, this parameter defines the individual column\n\t\t * filtering state at initialisation time. The array must be of the same size \n\t\t * as the number of columns, and each element be an object with the parameters\n\t\t * \"sSearch\" and \"bEscapeRegex\" (the latter is optional). 'null' is also\n\t\t * accepted and the default will be used.\n\t\t *  @type array\n\t\t *  @default []\n\t\t *  @dtopt Option\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"aoSearchCols\": [\n\t\t *          null,\n\t\t *          { \"sSearch\": \"My filter\" },\n\t\t *          null,\n\t\t *          { \"sSearch\": \"^[0-9]\", \"bEscapeRegex\": false }\n\t\t *        ]\n\t\t *      } );\n\t\t *    } )\n\t\t */\n\t\t\"aoSearchCols\": [],\n\t\n\t\n\t\t/**\n\t\t * An array of CSS classes that should be applied to displayed rows. This \n\t\t * array may be of any length, and DataTables will apply each class \n\t\t * sequentially, looping when required.\n\t\t *  @type array\n\t\t *  @default null <i>Will take the values determined by the oClasses.sStripe*\n\t\t *    options</i>\n\t\t *  @dtopt Option\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"asStripeClasses\": [ 'strip1', 'strip2', 'strip3' ]\n\t\t *      } );\n\t\t *    } )\n\t\t */\n\t\t\"asStripeClasses\": null,\n\t\n\t\n\t\t/**\n\t\t * Enable or disable automatic column width calculation. This can be disabled\n\t\t * as an optimisation (it takes some time to calculate the widths) if the\n\t\t * tables widths are passed in using aoColumns.\n\t\t *  @type boolean\n\t\t *  @default true\n\t\t *  @dtopt Features\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function () {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"bAutoWidth\": false\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"bAutoWidth\": true,\n\t\n\t\n\t\t/**\n\t\t * Deferred rendering can provide DataTables with a huge speed boost when you\n\t\t * are using an Ajax or JS data source for the table. This option, when set to\n\t\t * true, will cause DataTables to defer the creation of the table elements for\n\t\t * each row until they are needed for a draw - saving a significant amount of\n\t\t * time.\n\t\t *  @type boolean\n\t\t *  @default false\n\t\t *  @dtopt Features\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      var oTable = $('#example').dataTable( {\n\t\t *        \"sAjaxSource\": \"sources/arrays.txt\",\n\t\t *        \"bDeferRender\": true\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"bDeferRender\": false,\n\t\n\t\n\t\t/**\n\t\t * Replace a DataTable which matches the given selector and replace it with \n\t\t * one which has the properties of the new initialisation object passed. If no\n\t\t * table matches the selector, then the new DataTable will be constructed as\n\t\t * per normal.\n\t\t *  @type boolean\n\t\t *  @default false\n\t\t *  @dtopt Options\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"sScrollY\": \"200px\",\n\t\t *        \"bPaginate\": false\n\t\t *      } );\n\t\t *      \n\t\t *      // Some time later....\n\t\t *      $('#example').dataTable( {\n\t\t *        \"bFilter\": false,\n\t\t *        \"bDestroy\": true\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"bDestroy\": false,\n\t\n\t\n\t\t/**\n\t\t * Enable or disable filtering of data. Filtering in DataTables is \"smart\" in\n\t\t * that it allows the end user to input multiple words (space separated) and\n\t\t * will match a row containing those words, even if not in the order that was\n\t\t * specified (this allow matching across multiple columns). Note that if you\n\t\t * wish to use filtering in DataTables this must remain 'true' - to remove the\n\t\t * default filtering input box and retain filtering abilities, please use\n\t\t * {@link DataTable.defaults.sDom}.\n\t\t *  @type boolean\n\t\t *  @default true\n\t\t *  @dtopt Features\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function () {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"bFilter\": false\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"bFilter\": true,\n\t\n\t\n\t\t/**\n\t\t * Enable or disable the table information display. This shows information \n\t\t * about the data that is currently visible on the page, including information\n\t\t * about filtered data if that action is being performed.\n\t\t *  @type boolean\n\t\t *  @default true\n\t\t *  @dtopt Features\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function () {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"bInfo\": false\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"bInfo\": true,\n\t\n\t\n\t\t/**\n\t\t * Enable jQuery UI ThemeRoller support (required as ThemeRoller requires some\n\t\t * slightly different and additional mark-up from what DataTables has\n\t\t * traditionally used).\n\t\t *  @type boolean\n\t\t *  @default false\n\t\t *  @dtopt Features\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"bJQueryUI\": true\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"bJQueryUI\": false,\n\t\n\t\n\t\t/**\n\t\t * Allows the end user to select the size of a formatted page from a select\n\t\t * menu (sizes are 10, 25, 50 and 100). Requires pagination (bPaginate).\n\t\t *  @type boolean\n\t\t *  @default true\n\t\t *  @dtopt Features\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function () {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"bLengthChange\": false\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"bLengthChange\": true,\n\t\n\t\n\t\t/**\n\t\t * Enable or disable pagination.\n\t\t *  @type boolean\n\t\t *  @default true\n\t\t *  @dtopt Features\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function () {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"bPaginate\": false\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"bPaginate\": true,\n\t\n\t\n\t\t/**\n\t\t * Enable or disable the display of a 'processing' indicator when the table is\n\t\t * being processed (e.g. a sort). This is particularly useful for tables with\n\t\t * large amounts of data where it can take a noticeable amount of time to sort\n\t\t * the entries.\n\t\t *  @type boolean\n\t\t *  @default false\n\t\t *  @dtopt Features\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function () {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"bProcessing\": true\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"bProcessing\": false,\n\t\n\t\n\t\t/**\n\t\t * Retrieve the DataTables object for the given selector. Note that if the\n\t\t * table has already been initialised, this parameter will cause DataTables\n\t\t * to simply return the object that has already been set up - it will not take\n\t\t * account of any changes you might have made to the initialisation object\n\t\t * passed to DataTables (setting this parameter to true is an acknowledgement\n\t\t * that you understand this). bDestroy can be used to reinitialise a table if\n\t\t * you need.\n\t\t *  @type boolean\n\t\t *  @default false\n\t\t *  @dtopt Options\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      initTable();\n\t\t *      tableActions();\n\t\t *    } );\n\t\t *    \n\t\t *    function initTable ()\n\t\t *    {\n\t\t *      return $('#example').dataTable( {\n\t\t *        \"sScrollY\": \"200px\",\n\t\t *        \"bPaginate\": false,\n\t\t *        \"bRetrieve\": true\n\t\t *      } );\n\t\t *    }\n\t\t *    \n\t\t *    function tableActions ()\n\t\t *    {\n\t\t *      var oTable = initTable();\n\t\t *      // perform API operations with oTable \n\t\t *    }\n\t\t */\n\t\t\"bRetrieve\": false,\n\t\n\t\n\t\t/**\n\t\t * Indicate if DataTables should be allowed to set the padding / margin\n\t\t * etc for the scrolling header elements or not. Typically you will want\n\t\t * this.\n\t\t *  @type boolean\n\t\t *  @default true\n\t\t *  @dtopt Options\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"bScrollAutoCss\": false,\n\t\t *        \"sScrollY\": \"200px\"\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"bScrollAutoCss\": true,\n\t\n\t\n\t\t/**\n\t\t * When vertical (y) scrolling is enabled, DataTables will force the height of\n\t\t * the table's viewport to the given height at all times (useful for layout).\n\t\t * However, this can look odd when filtering data down to a small data set,\n\t\t * and the footer is left \"floating\" further down. This parameter (when\n\t\t * enabled) will cause DataTables to collapse the table's viewport down when\n\t\t * the result set will fit within the given Y height.\n\t\t *  @type boolean\n\t\t *  @default false\n\t\t *  @dtopt Options\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"sScrollY\": \"200\",\n\t\t *        \"bScrollCollapse\": true\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"bScrollCollapse\": false,\n\t\n\t\n\t\t/**\n\t\t * Enable infinite scrolling for DataTables (to be used in combination with\n\t\t * sScrollY). Infinite scrolling means that DataTables will continually load\n\t\t * data as a user scrolls through a table, which is very useful for large\n\t\t * dataset. This cannot be used with pagination, which is automatically\n\t\t * disabled. Note - the Scroller extra for DataTables is recommended in\n\t\t * in preference to this option.\n\t\t *  @type boolean\n\t\t *  @default false\n\t\t *  @dtopt Features\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"bScrollInfinite\": true,\n\t\t *        \"bScrollCollapse\": true,\n\t\t *        \"sScrollY\": \"200px\"\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"bScrollInfinite\": false,\n\t\n\t\n\t\t/**\n\t\t * Configure DataTables to use server-side processing. Note that the\n\t\t * sAjaxSource parameter must also be given in order to give DataTables a\n\t\t * source to obtain the required data for each draw.\n\t\t *  @type boolean\n\t\t *  @default false\n\t\t *  @dtopt Features\n\t\t *  @dtopt Server-side\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function () {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"bServerSide\": true,\n\t\t *        \"sAjaxSource\": \"xhr.php\"\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"bServerSide\": false,\n\t\n\t\n\t\t/**\n\t\t * Enable or disable sorting of columns. Sorting of individual columns can be\n\t\t * disabled by the \"bSortable\" option for each column.\n\t\t *  @type boolean\n\t\t *  @default true\n\t\t *  @dtopt Features\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function () {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"bSort\": false\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"bSort\": true,\n\t\n\t\n\t\t/**\n\t\t * Allows control over whether DataTables should use the top (true) unique\n\t\t * cell that is found for a single column, or the bottom (false - default).\n\t\t * This is useful when using complex headers.\n\t\t *  @type boolean\n\t\t *  @default false\n\t\t *  @dtopt Options\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"bSortCellsTop\": true\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"bSortCellsTop\": false,\n\t\n\t\n\t\t/**\n\t\t * Enable or disable the addition of the classes 'sorting_1', 'sorting_2' and\n\t\t * 'sorting_3' to the columns which are currently being sorted on. This is\n\t\t * presented as a feature switch as it can increase processing time (while\n\t\t * classes are removed and added) so for large data sets you might want to\n\t\t * turn this off.\n\t\t *  @type boolean\n\t\t *  @default true\n\t\t *  @dtopt Features\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function () {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"bSortClasses\": false\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"bSortClasses\": true,\n\t\n\t\n\t\t/**\n\t\t * Enable or disable state saving. When enabled a cookie will be used to save\n\t\t * table display information such as pagination information, display length,\n\t\t * filtering and sorting. As such when the end user reloads the page the\n\t\t * display display will match what thy had previously set up.\n\t\t *  @type boolean\n\t\t *  @default false\n\t\t *  @dtopt Features\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function () {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"bStateSave\": true\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"bStateSave\": false,\n\t\n\t\n\t\t/**\n\t\t * Customise the cookie and / or the parameters being stored when using\n\t\t * DataTables with state saving enabled. This function is called whenever\n\t\t * the cookie is modified, and it expects a fully formed cookie string to be\n\t\t * returned. Note that the data object passed in is a Javascript object which\n\t\t * must be converted to a string (JSON.stringify for example).\n\t\t *  @type function\n\t\t *  @param {string} sName Name of the cookie defined by DataTables\n\t\t *  @param {object} oData Data to be stored in the cookie\n\t\t *  @param {string} sExpires Cookie expires string\n\t\t *  @param {string} sPath Path of the cookie to set\n\t\t *  @returns {string} Cookie formatted string (which should be encoded by\n\t\t *    using encodeURIComponent())\n\t\t *  @dtopt Callbacks\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function () {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"fnCookieCallback\": function (sName, oData, sExpires, sPath) {\n\t\t *          // Customise oData or sName or whatever else here\n\t\t *          return sName + \"=\"+JSON.stringify(oData)+\"; expires=\" + sExpires +\"; path=\" + sPath;\n\t\t *        }\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"fnCookieCallback\": null,\n\t\n\t\n\t\t/**\n\t\t * This function is called when a TR element is created (and all TD child\n\t\t * elements have been inserted), or registered if using a DOM source, allowing\n\t\t * manipulation of the TR element (adding classes etc).\n\t\t *  @type function\n\t\t *  @param {node} nRow \"TR\" element for the current row\n\t\t *  @param {array} aData Raw data array for this row\n\t\t *  @param {int} iDataIndex The index of this row in aoData\n\t\t *  @dtopt Callbacks\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"fnCreatedRow\": function( nRow, aData, iDataIndex ) {\n\t\t *          // Bold the grade for all 'A' grade browsers\n\t\t *          if ( aData[4] == \"A\" )\n\t\t *          {\n\t\t *            $('td:eq(4)', nRow).html( '<b>A</b>' );\n\t\t *          }\n\t\t *        }\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"fnCreatedRow\": null,\n\t\n\t\n\t\t/**\n\t\t * This function is called on every 'draw' event, and allows you to\n\t\t * dynamically modify any aspect you want about the created DOM.\n\t\t *  @type function\n\t\t *  @param {object} oSettings DataTables settings object\n\t\t *  @dtopt Callbacks\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"fnDrawCallback\": function( oSettings ) {\n\t\t *          alert( 'DataTables has redrawn the table' );\n\t\t *        }\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"fnDrawCallback\": null,\n\t\n\t\n\t\t/**\n\t\t * Identical to fnHeaderCallback() but for the table footer this function\n\t\t * allows you to modify the table footer on every 'draw' even.\n\t\t *  @type function\n\t\t *  @param {node} nFoot \"TR\" element for the footer\n\t\t *  @param {array} aData Full table data (as derived from the original HTML)\n\t\t *  @param {int} iStart Index for the current display starting point in the \n\t\t *    display array\n\t\t *  @param {int} iEnd Index for the current display ending point in the \n\t\t *    display array\n\t\t *  @param {array int} aiDisplay Index array to translate the visual position\n\t\t *    to the full data array\n\t\t *  @dtopt Callbacks\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"fnFooterCallback\": function( nFoot, aData, iStart, iEnd, aiDisplay ) {\n\t\t *          nFoot.getElementsByTagName('th')[0].innerHTML = \"Starting index is \"+iStart;\n\t\t *        }\n\t\t *      } );\n\t\t *    } )\n\t\t */\n\t\t\"fnFooterCallback\": null,\n\t\n\t\n\t\t/**\n\t\t * When rendering large numbers in the information element for the table\n\t\t * (i.e. \"Showing 1 to 10 of 57 entries\") DataTables will render large numbers\n\t\t * to have a comma separator for the 'thousands' units (e.g. 1 million is\n\t\t * rendered as \"1,000,000\") to help readability for the end user. This\n\t\t * function will override the default method DataTables uses.\n\t\t *  @type function\n\t\t *  @member\n\t\t *  @param {int} iIn number to be formatted\n\t\t *  @returns {string} formatted string for DataTables to show the number\n\t\t *  @dtopt Callbacks\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"fnFormatNumber\": function ( iIn ) {\n\t\t *          if ( iIn &lt; 1000 ) {\n\t\t *            return iIn;\n\t\t *          } else {\n\t\t *            var \n\t\t *              s=(iIn+\"\"), \n\t\t *              a=s.split(\"\"), out=\"\", \n\t\t *              iLen=s.length;\n\t\t *            \n\t\t *            for ( var i=0 ; i&lt;iLen ; i++ ) {\n\t\t *              if ( i%3 === 0 &amp;&amp; i !== 0 ) {\n\t\t *                out = \"'\"+out;\n\t\t *              }\n\t\t *              out = a[iLen-i-1]+out;\n\t\t *            }\n\t\t *          }\n\t\t *          return out;\n\t\t *        };\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"fnFormatNumber\": function ( iIn ) {\n\t\t\tif ( iIn < 1000 )\n\t\t\t{\n\t\t\t\t// A small optimisation for what is likely to be the majority of use cases\n\t\t\t\treturn iIn;\n\t\t\t}\n\t\n\t\t\tvar s=(iIn+\"\"), a=s.split(\"\"), out=\"\", iLen=s.length;\n\t\t\t\n\t\t\tfor ( var i=0 ; i<iLen ; i++ )\n\t\t\t{\n\t\t\t\tif ( i%3 === 0 && i !== 0 )\n\t\t\t\t{\n\t\t\t\t\tout = this.oLanguage.sInfoThousands+out;\n\t\t\t\t}\n\t\t\t\tout = a[iLen-i-1]+out;\n\t\t\t}\n\t\t\treturn out;\n\t\t},\n\t\n\t\n\t\t/**\n\t\t * This function is called on every 'draw' event, and allows you to\n\t\t * dynamically modify the header row. This can be used to calculate and\n\t\t * display useful information about the table.\n\t\t *  @type function\n\t\t *  @param {node} nHead \"TR\" element for the header\n\t\t *  @param {array} aData Full table data (as derived from the original HTML)\n\t\t *  @param {int} iStart Index for the current display starting point in the\n\t\t *    display array\n\t\t *  @param {int} iEnd Index for the current display ending point in the\n\t\t *    display array\n\t\t *  @param {array int} aiDisplay Index array to translate the visual position\n\t\t *    to the full data array\n\t\t *  @dtopt Callbacks\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"fnHeaderCallback\": function( nHead, aData, iStart, iEnd, aiDisplay ) {\n\t\t *          nHead.getElementsByTagName('th')[0].innerHTML = \"Displaying \"+(iEnd-iStart)+\" records\";\n\t\t *        }\n\t\t *      } );\n\t\t *    } )\n\t\t */\n\t\t\"fnHeaderCallback\": null,\n\t\n\t\n\t\t/**\n\t\t * The information element can be used to convey information about the current\n\t\t * state of the table. Although the internationalisation options presented by\n\t\t * DataTables are quite capable of dealing with most customisations, there may\n\t\t * be times where you wish to customise the string further. This callback\n\t\t * allows you to do exactly that.\n\t\t *  @type function\n\t\t *  @param {object} oSettings DataTables settings object\n\t\t *  @param {int} iStart Starting position in data for the draw\n\t\t *  @param {int} iEnd End position in data for the draw\n\t\t *  @param {int} iMax Total number of rows in the table (regardless of\n\t\t *    filtering)\n\t\t *  @param {int} iTotal Total number of rows in the data set, after filtering\n\t\t *  @param {string} sPre The string that DataTables has formatted using it's\n\t\t *    own rules\n\t\t *  @returns {string} The string to be displayed in the information element.\n\t\t *  @dtopt Callbacks\n\t\t * \n\t\t *  @example\n\t\t *    $('#example').dataTable( {\n\t\t *      \"fnInfoCallback\": function( oSettings, iStart, iEnd, iMax, iTotal, sPre ) {\n\t\t *        return iStart +\" to \"+ iEnd;\n\t\t *      }\n\t\t *    } );\n\t\t */\n\t\t\"fnInfoCallback\": null,\n\t\n\t\n\t\t/**\n\t\t * Called when the table has been initialised. Normally DataTables will\n\t\t * initialise sequentially and there will be no need for this function,\n\t\t * however, this does not hold true when using external language information\n\t\t * since that is obtained using an async XHR call.\n\t\t *  @type function\n\t\t *  @param {object} oSettings DataTables settings object\n\t\t *  @param {object} json The JSON object request from the server - only\n\t\t *    present if client-side Ajax sourced data is used\n\t\t *  @dtopt Callbacks\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"fnInitComplete\": function(oSettings, json) {\n\t\t *          alert( 'DataTables has finished its initialisation.' );\n\t\t *        }\n\t\t *      } );\n\t\t *    } )\n\t\t */\n\t\t\"fnInitComplete\": null,\n\t\n\t\n\t\t/**\n\t\t * Called at the very start of each table draw and can be used to cancel the\n\t\t * draw by returning false, any other return (including undefined) results in\n\t\t * the full draw occurring).\n\t\t *  @type function\n\t\t *  @param {object} oSettings DataTables settings object\n\t\t *  @returns {boolean} False will cancel the draw, anything else (including no\n\t\t *    return) will allow it to complete.\n\t\t *  @dtopt Callbacks\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"fnPreDrawCallback\": function( oSettings ) {\n\t\t *          if ( $('#test').val() == 1 ) {\n\t\t *            return false;\n\t\t *          }\n\t\t *        }\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"fnPreDrawCallback\": null,\n\t\n\t\n\t\t/**\n\t\t * This function allows you to 'post process' each row after it have been\n\t\t * generated for each table draw, but before it is rendered on screen. This\n\t\t * function might be used for setting the row class name etc.\n\t\t *  @type function\n\t\t *  @param {node} nRow \"TR\" element for the current row\n\t\t *  @param {array} aData Raw data array for this row\n\t\t *  @param {int} iDisplayIndex The display index for the current table draw\n\t\t *  @param {int} iDisplayIndexFull The index of the data in the full list of\n\t\t *    rows (after filtering)\n\t\t *  @dtopt Callbacks\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"fnRowCallback\": function( nRow, aData, iDisplayIndex, iDisplayIndexFull ) {\n\t\t *          // Bold the grade for all 'A' grade browsers\n\t\t *          if ( aData[4] == \"A\" )\n\t\t *          {\n\t\t *            $('td:eq(4)', nRow).html( '<b>A</b>' );\n\t\t *          }\n\t\t *        }\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"fnRowCallback\": null,\n\t\n\t\n\t\t/**\n\t\t * This parameter allows you to override the default function which obtains\n\t\t * the data from the server ($.getJSON) so something more suitable for your\n\t\t * application. For example you could use POST data, or pull information from\n\t\t * a Gears or AIR database.\n\t\t *  @type function\n\t\t *  @member\n\t\t *  @param {string} sSource HTTP source to obtain the data from (sAjaxSource)\n\t\t *  @param {array} aoData A key/value pair object containing the data to send\n\t\t *    to the server\n\t\t *  @param {function} fnCallback to be called on completion of the data get\n\t\t *    process that will draw the data on the page.\n\t\t *  @param {object} oSettings DataTables settings object\n\t\t *  @dtopt Callbacks\n\t\t *  @dtopt Server-side\n\t\t * \n\t\t *  @example\n\t\t *    // POST data to server\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"bProcessing\": true,\n\t\t *        \"bServerSide\": true,\n\t\t *        \"sAjaxSource\": \"xhr.php\",\n\t\t *        \"fnServerData\": function ( sSource, aoData, fnCallback, oSettings ) {\n\t\t *          oSettings.jqXHR = $.ajax( {\n\t\t *            \"dataType\": 'json', \n\t\t *            \"type\": \"POST\", \n\t\t *            \"url\": sSource, \n\t\t *            \"data\": aoData, \n\t\t *            \"success\": fnCallback\n\t\t *          } );\n\t\t *        }\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"fnServerData\": function ( sUrl, aoData, fnCallback, oSettings ) {\n\t\t\toSettings.jqXHR = $.ajax( {\n\t\t\t\t\"url\":  sUrl,\n\t\t\t\t\"data\": aoData,\n\t\t\t\t\"success\": function (json) {\n\t\t\t\t\tif ( json.sError ) {\n\t\t\t\t\t\toSettings.oApi._fnLog( oSettings, 0, json.sError );\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t$(oSettings.oInstance).trigger('xhr', [oSettings, json]);\n\t\t\t\t\tfnCallback( json );\n\t\t\t\t},\n\t\t\t\t\"dataType\": \"json\",\n\t\t\t\t\"cache\": false,\n\t\t\t\t\"type\": oSettings.sServerMethod,\n\t\t\t\t\"error\": function (xhr, error, thrown) {\n\t\t\t\t\tif ( error == \"parsererror\" ) {\n\t\t\t\t\t\toSettings.oApi._fnLog( oSettings, 0, \"DataTables warning: JSON data from \"+\n\t\t\t\t\t\t\t\"server could not be parsed. This is caused by a JSON formatting error.\" );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\t\t},\n\t\n\t\n\t\t/**\n\t\t * It is often useful to send extra data to the server when making an Ajax\n\t\t * request - for example custom filtering information, and this callback\n\t\t * function makes it trivial to send extra information to the server. The\n\t\t * passed in parameter is the data set that has been constructed by\n\t\t * DataTables, and you can add to this or modify it as you require.\n\t\t *  @type function\n\t\t *  @param {array} aoData Data array (array of objects which are name/value\n\t\t *    pairs) that has been constructed by DataTables and will be sent to the\n\t\t *    server. In the case of Ajax sourced data with server-side processing\n\t\t *    this will be an empty array, for server-side processing there will be a\n\t\t *    significant number of parameters!\n\t\t *  @returns {undefined} Ensure that you modify the aoData array passed in,\n\t\t *    as this is passed by reference.\n\t\t *  @dtopt Callbacks\n\t\t *  @dtopt Server-side\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"bProcessing\": true,\n\t\t *        \"bServerSide\": true,\n\t\t *        \"sAjaxSource\": \"scripts/server_processing.php\",\n\t\t *        \"fnServerParams\": function ( aoData ) {\n\t\t *          aoData.push( { \"name\": \"more_data\", \"value\": \"my_value\" } );\n\t\t *        }\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"fnServerParams\": null,\n\t\n\t\n\t\t/**\n\t\t * Load the table state. With this function you can define from where, and how, the\n\t\t * state of a table is loaded. By default DataTables will load from its state saving\n\t\t * cookie, but you might wish to use local storage (HTML5) or a server-side database.\n\t\t *  @type function\n\t\t *  @member\n\t\t *  @param {object} oSettings DataTables settings object\n\t\t *  @return {object} The DataTables state object to be loaded\n\t\t *  @dtopt Callbacks\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"bStateSave\": true,\n\t\t *        \"fnStateLoad\": function (oSettings) {\n\t\t *          var o;\n\t\t *          \n\t\t *          // Send an Ajax request to the server to get the data. Note that\n\t\t *          // this is a synchronous request.\n\t\t *          $.ajax( {\n\t\t *            \"url\": \"/state_load\",\n\t\t *            \"async\": false,\n\t\t *            \"dataType\": \"json\",\n\t\t *            \"success\": function (json) {\n\t\t *              o = json;\n\t\t *            }\n\t\t *          } );\n\t\t *          \n\t\t *          return o;\n\t\t *        }\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"fnStateLoad\": function ( oSettings ) {\n\t\t\tvar sData = this.oApi._fnReadCookie( oSettings.sCookiePrefix+oSettings.sInstance );\n\t\t\tvar oData;\n\t\n\t\t\ttry {\n\t\t\t\toData = (typeof $.parseJSON === 'function') ? \n\t\t\t\t\t$.parseJSON(sData) : eval( '('+sData+')' );\n\t\t\t} catch (e) {\n\t\t\t\toData = null;\n\t\t\t}\n\t\n\t\t\treturn oData;\n\t\t},\n\t\n\t\n\t\t/**\n\t\t * Callback which allows modification of the saved state prior to loading that state.\n\t\t * This callback is called when the table is loading state from the stored data, but\n\t\t * prior to the settings object being modified by the saved state. Note that for \n\t\t * plug-in authors, you should use the 'stateLoadParams' event to load parameters for \n\t\t * a plug-in.\n\t\t *  @type function\n\t\t *  @param {object} oSettings DataTables settings object\n\t\t *  @param {object} oData The state object that is to be loaded\n\t\t *  @dtopt Callbacks\n\t\t * \n\t\t *  @example\n\t\t *    // Remove a saved filter, so filtering is never loaded\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"bStateSave\": true,\n\t\t *        \"fnStateLoadParams\": function (oSettings, oData) {\n\t\t *          oData.oSearch.sSearch = \"\";\n\t\t *        }\n\t\t *      } );\n\t\t *    } );\n\t\t * \n\t\t *  @example\n\t\t *    // Disallow state loading by returning false\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"bStateSave\": true,\n\t\t *        \"fnStateLoadParams\": function (oSettings, oData) {\n\t\t *          return false;\n\t\t *        }\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"fnStateLoadParams\": null,\n\t\n\t\n\t\t/**\n\t\t * Callback that is called when the state has been loaded from the state saving method\n\t\t * and the DataTables settings object has been modified as a result of the loaded state.\n\t\t *  @type function\n\t\t *  @param {object} oSettings DataTables settings object\n\t\t *  @param {object} oData The state object that was loaded\n\t\t *  @dtopt Callbacks\n\t\t * \n\t\t *  @example\n\t\t *    // Show an alert with the filtering value that was saved\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"bStateSave\": true,\n\t\t *        \"fnStateLoaded\": function (oSettings, oData) {\n\t\t *          alert( 'Saved filter was: '+oData.oSearch.sSearch );\n\t\t *        }\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"fnStateLoaded\": null,\n\t\n\t\n\t\t/**\n\t\t * Save the table state. This function allows you to define where and how the state\n\t\t * information for the table is stored - by default it will use a cookie, but you\n\t\t * might want to use local storage (HTML5) or a server-side database.\n\t\t *  @type function\n\t\t *  @member\n\t\t *  @param {object} oSettings DataTables settings object\n\t\t *  @param {object} oData The state object to be saved\n\t\t *  @dtopt Callbacks\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"bStateSave\": true,\n\t\t *        \"fnStateSave\": function (oSettings, oData) {\n\t\t *          // Send an Ajax request to the server with the state object\n\t\t *          $.ajax( {\n\t\t *            \"url\": \"/state_save\",\n\t\t *            \"data\": oData,\n\t\t *            \"dataType\": \"json\",\n\t\t *            \"method\": \"POST\"\n\t\t *            \"success\": function () {}\n\t\t *          } );\n\t\t *        }\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"fnStateSave\": function ( oSettings, oData ) {\n\t\t\tthis.oApi._fnCreateCookie( \n\t\t\t\toSettings.sCookiePrefix+oSettings.sInstance, \n\t\t\t\tthis.oApi._fnJsonString(oData), \n\t\t\t\toSettings.iCookieDuration, \n\t\t\t\toSettings.sCookiePrefix, \n\t\t\t\toSettings.fnCookieCallback\n\t\t\t);\n\t\t},\n\t\n\t\n\t\t/**\n\t\t * Callback which allows modification of the state to be saved. Called when the table \n\t\t * has changed state a new state save is required. This method allows modification of\n\t\t * the state saving object prior to actually doing the save, including addition or \n\t\t * other state properties or modification. Note that for plug-in authors, you should \n\t\t * use the 'stateSaveParams' event to save parameters for a plug-in.\n\t\t *  @type function\n\t\t *  @param {object} oSettings DataTables settings object\n\t\t *  @param {object} oData The state object to be saved\n\t\t *  @dtopt Callbacks\n\t\t * \n\t\t *  @example\n\t\t *    // Remove a saved filter, so filtering is never saved\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"bStateSave\": true,\n\t\t *        \"fnStateSaveParams\": function (oSettings, oData) {\n\t\t *          oData.oSearch.sSearch = \"\";\n\t\t *        }\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"fnStateSaveParams\": null,\n\t\n\t\n\t\t/**\n\t\t * Duration of the cookie which is used for storing session information. This\n\t\t * value is given in seconds.\n\t\t *  @type int\n\t\t *  @default 7200 <i>(2 hours)</i>\n\t\t *  @dtopt Options\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"iCookieDuration\": 60*60*24; // 1 day\n\t\t *      } );\n\t\t *    } )\n\t\t */\n\t\t\"iCookieDuration\": 7200,\n\t\n\t\n\t\t/**\n\t\t * When enabled DataTables will not make a request to the server for the first\n\t\t * page draw - rather it will use the data already on the page (no sorting etc\n\t\t * will be applied to it), thus saving on an XHR at load time. iDeferLoading\n\t\t * is used to indicate that deferred loading is required, but it is also used\n\t\t * to tell DataTables how many records there are in the full table (allowing\n\t\t * the information element and pagination to be displayed correctly). In the case\n\t\t * where a filtering is applied to the table on initial load, this can be\n\t\t * indicated by giving the parameter as an array, where the first element is\n\t\t * the number of records available after filtering and the second element is the\n\t\t * number of records without filtering (allowing the table information element\n\t\t * to be shown correctly).\n\t\t *  @type int | array\n\t\t *  @default null\n\t\t *  @dtopt Options\n\t\t * \n\t\t *  @example\n\t\t *    // 57 records available in the table, no filtering applied\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"bServerSide\": true,\n\t\t *        \"sAjaxSource\": \"scripts/server_processing.php\",\n\t\t *        \"iDeferLoading\": 57\n\t\t *      } );\n\t\t *    } );\n\t\t * \n\t\t *  @example\n\t\t *    // 57 records after filtering, 100 without filtering (an initial filter applied)\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"bServerSide\": true,\n\t\t *        \"sAjaxSource\": \"scripts/server_processing.php\",\n\t\t *        \"iDeferLoading\": [ 57, 100 ],\n\t\t *        \"oSearch\": {\n\t\t *          \"sSearch\": \"my_filter\"\n\t\t *        }\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"iDeferLoading\": null,\n\t\n\t\n\t\t/**\n\t\t * Number of rows to display on a single page when using pagination. If\n\t\t * feature enabled (bLengthChange) then the end user will be able to override\n\t\t * this to a custom setting using a pop-up menu.\n\t\t *  @type int\n\t\t *  @default 10\n\t\t *  @dtopt Options\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"iDisplayLength\": 50\n\t\t *      } );\n\t\t *    } )\n\t\t */\n\t\t\"iDisplayLength\": 10,\n\t\n\t\n\t\t/**\n\t\t * Define the starting point for data display when using DataTables with\n\t\t * pagination. Note that this parameter is the number of records, rather than\n\t\t * the page number, so if you have 10 records per page and want to start on\n\t\t * the third page, it should be \"20\".\n\t\t *  @type int\n\t\t *  @default 0\n\t\t *  @dtopt Options\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"iDisplayStart\": 20\n\t\t *      } );\n\t\t *    } )\n\t\t */\n\t\t\"iDisplayStart\": 0,\n\t\n\t\n\t\t/**\n\t\t * The scroll gap is the amount of scrolling that is left to go before\n\t\t * DataTables will load the next 'page' of data automatically. You typically\n\t\t * want a gap which is big enough that the scrolling will be smooth for the\n\t\t * user, while not so large that it will load more data than need.\n\t\t *  @type int\n\t\t *  @default 100\n\t\t *  @dtopt Options\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"bScrollInfinite\": true,\n\t\t *        \"bScrollCollapse\": true,\n\t\t *        \"sScrollY\": \"200px\",\n\t\t *        \"iScrollLoadGap\": 50\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"iScrollLoadGap\": 100,\n\t\n\t\n\t\t/**\n\t\t * By default DataTables allows keyboard navigation of the table (sorting, paging,\n\t\t * and filtering) by adding a tabindex attribute to the required elements. This\n\t\t * allows you to tab through the controls and press the enter key to activate them.\n\t\t * The tabindex is default 0, meaning that the tab follows the flow of the document.\n\t\t * You can overrule this using this parameter if you wish. Use a value of -1 to\n\t\t * disable built-in keyboard navigation.\n\t\t *  @type int\n\t\t *  @default 0\n\t\t *  @dtopt Options\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"iTabIndex\": 1\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"iTabIndex\": 0,\n\t\n\t\n\t\t/**\n\t\t * All strings that DataTables uses in the user interface that it creates\n\t\t * are defined in this object, allowing you to modified them individually or\n\t\t * completely replace them all as required.\n\t\t *  @namespace\n\t\t */\n\t\t\"oLanguage\": {\n\t\t\t/**\n\t\t\t * Strings that are used for WAI-ARIA labels and controls only (these are not\n\t\t\t * actually visible on the page, but will be read by screenreaders, and thus\n\t\t\t * must be internationalised as well).\n\t\t\t *  @namespace\n\t\t\t */\n\t\t\t\"oAria\": {\n\t\t\t\t/**\n\t\t\t\t * ARIA label that is added to the table headers when the column may be\n\t\t\t\t * sorted ascending by activing the column (click or return when focused).\n\t\t\t\t * Note that the column header is prefixed to this string.\n\t\t\t\t *  @type string\n\t\t\t\t *  @default : activate to sort column ascending\n\t\t\t\t *  @dtopt Language\n\t\t\t\t * \n\t\t\t\t *  @example\n\t\t\t\t *    $(document).ready( function() {\n\t\t\t\t *      $('#example').dataTable( {\n\t\t\t\t *        \"oLanguage\": {\n\t\t\t\t *          \"oAria\": {\n\t\t\t\t *            \"sSortAscending\": \" - click/return to sort ascending\"\n\t\t\t\t *          }\n\t\t\t\t *        }\n\t\t\t\t *      } );\n\t\t\t\t *    } );\n\t\t\t\t */\n\t\t\t\t\"sSortAscending\": \": activate to sort column ascending\",\n\t\n\t\t\t\t/**\n\t\t\t\t * ARIA label that is added to the table headers when the column may be\n\t\t\t\t * sorted descending by activing the column (click or return when focused).\n\t\t\t\t * Note that the column header is prefixed to this string.\n\t\t\t\t *  @type string\n\t\t\t\t *  @default : activate to sort column ascending\n\t\t\t\t *  @dtopt Language\n\t\t\t\t * \n\t\t\t\t *  @example\n\t\t\t\t *    $(document).ready( function() {\n\t\t\t\t *      $('#example').dataTable( {\n\t\t\t\t *        \"oLanguage\": {\n\t\t\t\t *          \"oAria\": {\n\t\t\t\t *            \"sSortDescending\": \" - click/return to sort descending\"\n\t\t\t\t *          }\n\t\t\t\t *        }\n\t\t\t\t *      } );\n\t\t\t\t *    } );\n\t\t\t\t */\n\t\t\t\t\"sSortDescending\": \": activate to sort column descending\"\n\t\t\t},\n\t\n\t\t\t/**\n\t\t\t * Pagination string used by DataTables for the two built-in pagination\n\t\t\t * control types (\"two_button\" and \"full_numbers\")\n\t\t\t *  @namespace\n\t\t\t */\n\t\t\t\"oPaginate\": {\n\t\t\t\t/**\n\t\t\t\t * Text to use when using the 'full_numbers' type of pagination for the\n\t\t\t\t * button to take the user to the first page.\n\t\t\t\t *  @type string\n\t\t\t\t *  @default First\n\t\t\t\t *  @dtopt Language\n\t\t\t\t * \n\t\t\t\t *  @example\n\t\t\t\t *    $(document).ready( function() {\n\t\t\t\t *      $('#example').dataTable( {\n\t\t\t\t *        \"oLanguage\": {\n\t\t\t\t *          \"oPaginate\": {\n\t\t\t\t *            \"sFirst\": \"First page\"\n\t\t\t\t *          }\n\t\t\t\t *        }\n\t\t\t\t *      } );\n\t\t\t\t *    } );\n\t\t\t\t */\n\t\t\t\t\"sFirst\": \"First\",\n\t\t\t\n\t\t\t\n\t\t\t\t/**\n\t\t\t\t * Text to use when using the 'full_numbers' type of pagination for the\n\t\t\t\t * button to take the user to the last page.\n\t\t\t\t *  @type string\n\t\t\t\t *  @default Last\n\t\t\t\t *  @dtopt Language\n\t\t\t\t * \n\t\t\t\t *  @example\n\t\t\t\t *    $(document).ready( function() {\n\t\t\t\t *      $('#example').dataTable( {\n\t\t\t\t *        \"oLanguage\": {\n\t\t\t\t *          \"oPaginate\": {\n\t\t\t\t *            \"sLast\": \"Last page\"\n\t\t\t\t *          }\n\t\t\t\t *        }\n\t\t\t\t *      } );\n\t\t\t\t *    } );\n\t\t\t\t */\n\t\t\t\t\"sLast\": \"Last\",\n\t\t\t\n\t\t\t\n\t\t\t\t/**\n\t\t\t\t * Text to use for the 'next' pagination button (to take the user to the \n\t\t\t\t * next page).\n\t\t\t\t *  @type string\n\t\t\t\t *  @default Next\n\t\t\t\t *  @dtopt Language\n\t\t\t\t * \n\t\t\t\t *  @example\n\t\t\t\t *    $(document).ready( function() {\n\t\t\t\t *      $('#example').dataTable( {\n\t\t\t\t *        \"oLanguage\": {\n\t\t\t\t *          \"oPaginate\": {\n\t\t\t\t *            \"sNext\": \"Next page\"\n\t\t\t\t *          }\n\t\t\t\t *        }\n\t\t\t\t *      } );\n\t\t\t\t *    } );\n\t\t\t\t */\n\t\t\t\t\"sNext\": \"Next\",\n\t\t\t\n\t\t\t\n\t\t\t\t/**\n\t\t\t\t * Text to use for the 'previous' pagination button (to take the user to  \n\t\t\t\t * the previous page).\n\t\t\t\t *  @type string\n\t\t\t\t *  @default Previous\n\t\t\t\t *  @dtopt Language\n\t\t\t\t * \n\t\t\t\t *  @example\n\t\t\t\t *    $(document).ready( function() {\n\t\t\t\t *      $('#example').dataTable( {\n\t\t\t\t *        \"oLanguage\": {\n\t\t\t\t *          \"oPaginate\": {\n\t\t\t\t *            \"sPrevious\": \"Previous page\"\n\t\t\t\t *          }\n\t\t\t\t *        }\n\t\t\t\t *      } );\n\t\t\t\t *    } );\n\t\t\t\t */\n\t\t\t\t\"sPrevious\": \"Previous\"\n\t\t\t},\n\t\t\n\t\t\t/**\n\t\t\t * This string is shown in preference to sZeroRecords when the table is\n\t\t\t * empty of data (regardless of filtering). Note that this is an optional\n\t\t\t * parameter - if it is not given, the value of sZeroRecords will be used\n\t\t\t * instead (either the default or given value).\n\t\t\t *  @type string\n\t\t\t *  @default No data available in table\n\t\t\t *  @dtopt Language\n\t\t\t * \n\t\t\t *  @example\n\t\t\t *    $(document).ready( function() {\n\t\t\t *      $('#example').dataTable( {\n\t\t\t *        \"oLanguage\": {\n\t\t\t *          \"sEmptyTable\": \"No data available in table\"\n\t\t\t *        }\n\t\t\t *      } );\n\t\t\t *    } );\n\t\t\t */\n\t\t\t\"sEmptyTable\": \"No data available in table\",\n\t\t\n\t\t\n\t\t\t/**\n\t\t\t * This string gives information to the end user about the information that \n\t\t\t * is current on display on the page. The _START_, _END_ and _TOTAL_ \n\t\t\t * variables are all dynamically replaced as the table display updates, and \n\t\t\t * can be freely moved or removed as the language requirements change.\n\t\t\t *  @type string\n\t\t\t *  @default Showing _START_ to _END_ of _TOTAL_ entries\n\t\t\t *  @dtopt Language\n\t\t\t * \n\t\t\t *  @example\n\t\t\t *    $(document).ready( function() {\n\t\t\t *      $('#example').dataTable( {\n\t\t\t *        \"oLanguage\": {\n\t\t\t *          \"sInfo\": \"Got a total of _TOTAL_ entries to show (_START_ to _END_)\"\n\t\t\t *        }\n\t\t\t *      } );\n\t\t\t *    } );\n\t\t\t */\n\t\t\t\"sInfo\": \"Showing _START_ to _END_ of _TOTAL_ entries\",\n\t\t\n\t\t\n\t\t\t/**\n\t\t\t * Display information string for when the table is empty. Typically the \n\t\t\t * format of this string should match sInfo.\n\t\t\t *  @type string\n\t\t\t *  @default Showing 0 to 0 of 0 entries\n\t\t\t *  @dtopt Language\n\t\t\t * \n\t\t\t *  @example\n\t\t\t *    $(document).ready( function() {\n\t\t\t *      $('#example').dataTable( {\n\t\t\t *        \"oLanguage\": {\n\t\t\t *          \"sInfoEmpty\": \"No entries to show\"\n\t\t\t *        }\n\t\t\t *      } );\n\t\t\t *    } );\n\t\t\t */\n\t\t\t\"sInfoEmpty\": \"Showing 0 to 0 of 0 entries\",\n\t\t\n\t\t\n\t\t\t/**\n\t\t\t * When a user filters the information in a table, this string is appended \n\t\t\t * to the information (sInfo) to give an idea of how strong the filtering \n\t\t\t * is. The variable _MAX_ is dynamically updated.\n\t\t\t *  @type string\n\t\t\t *  @default (filtered from _MAX_ total entries)\n\t\t\t *  @dtopt Language\n\t\t\t * \n\t\t\t *  @example\n\t\t\t *    $(document).ready( function() {\n\t\t\t *      $('#example').dataTable( {\n\t\t\t *        \"oLanguage\": {\n\t\t\t *          \"sInfoFiltered\": \" - filtering from _MAX_ records\"\n\t\t\t *        }\n\t\t\t *      } );\n\t\t\t *    } );\n\t\t\t */\n\t\t\t\"sInfoFiltered\": \"(filtered from _MAX_ total entries)\",\n\t\t\n\t\t\n\t\t\t/**\n\t\t\t * If can be useful to append extra information to the info string at times,\n\t\t\t * and this variable does exactly that. This information will be appended to\n\t\t\t * the sInfo (sInfoEmpty and sInfoFiltered in whatever combination they are\n\t\t\t * being used) at all times.\n\t\t\t *  @type string\n\t\t\t *  @default <i>Empty string</i>\n\t\t\t *  @dtopt Language\n\t\t\t * \n\t\t\t *  @example\n\t\t\t *    $(document).ready( function() {\n\t\t\t *      $('#example').dataTable( {\n\t\t\t *        \"oLanguage\": {\n\t\t\t *          \"sInfoPostFix\": \"All records shown are derived from real information.\"\n\t\t\t *        }\n\t\t\t *      } );\n\t\t\t *    } );\n\t\t\t */\n\t\t\t\"sInfoPostFix\": \"\",\n\t\t\n\t\t\n\t\t\t/**\n\t\t\t * DataTables has a build in number formatter (fnFormatNumber) which is used\n\t\t\t * to format large numbers that are used in the table information. By\n\t\t\t * default a comma is used, but this can be trivially changed to any\n\t\t\t * character you wish with this parameter.\n\t\t\t *  @type string\n\t\t\t *  @default ,\n\t\t\t *  @dtopt Language\n\t\t\t * \n\t\t\t *  @example\n\t\t\t *    $(document).ready( function() {\n\t\t\t *      $('#example').dataTable( {\n\t\t\t *        \"oLanguage\": {\n\t\t\t *          \"sInfoThousands\": \"'\"\n\t\t\t *        }\n\t\t\t *      } );\n\t\t\t *    } );\n\t\t\t */\n\t\t\t\"sInfoThousands\": \",\",\n\t\t\n\t\t\n\t\t\t/**\n\t\t\t * Detail the action that will be taken when the drop down menu for the\n\t\t\t * pagination length option is changed. The '_MENU_' variable is replaced\n\t\t\t * with a default select list of 10, 25, 50 and 100, and can be replaced\n\t\t\t * with a custom select box if required.\n\t\t\t *  @type string\n\t\t\t *  @default Show _MENU_ entries\n\t\t\t *  @dtopt Language\n\t\t\t * \n\t\t\t *  @example\n\t\t\t *    // Language change only\n\t\t\t *    $(document).ready( function() {\n\t\t\t *      $('#example').dataTable( {\n\t\t\t *        \"oLanguage\": {\n\t\t\t *          \"sLengthMenu\": \"Display _MENU_ records\"\n\t\t\t *        }\n\t\t\t *      } );\n\t\t\t *    } );\n\t\t\t *    \n\t\t\t *  @example\n\t\t\t *    // Language and options change\n\t\t\t *    $(document).ready( function() {\n\t\t\t *      $('#example').dataTable( {\n\t\t\t *        \"oLanguage\": {\n\t\t\t *          \"sLengthMenu\": 'Display <select>'+\n\t\t\t *            '<option value=\"10\">10</option>'+\n\t\t\t *            '<option value=\"20\">20</option>'+\n\t\t\t *            '<option value=\"30\">30</option>'+\n\t\t\t *            '<option value=\"40\">40</option>'+\n\t\t\t *            '<option value=\"50\">50</option>'+\n\t\t\t *            '<option value=\"-1\">All</option>'+\n\t\t\t *            '</select> records'\n\t\t\t *        }\n\t\t\t *      } );\n\t\t\t *    } );\n\t\t\t */\n\t\t\t\"sLengthMenu\": \"Show _MENU_ entries\",\n\t\t\n\t\t\n\t\t\t/**\n\t\t\t * When using Ajax sourced data and during the first draw when DataTables is\n\t\t\t * gathering the data, this message is shown in an empty row in the table to\n\t\t\t * indicate to the end user the the data is being loaded. Note that this\n\t\t\t * parameter is not used when loading data by server-side processing, just\n\t\t\t * Ajax sourced data with client-side processing.\n\t\t\t *  @type string\n\t\t\t *  @default Loading...\n\t\t\t *  @dtopt Language\n\t\t\t * \n\t\t\t *  @example\n\t\t\t *    $(document).ready( function() {\n\t\t\t *      $('#example').dataTable( {\n\t\t\t *        \"oLanguage\": {\n\t\t\t *          \"sLoadingRecords\": \"Please wait - loading...\"\n\t\t\t *        }\n\t\t\t *      } );\n\t\t\t *    } );\n\t\t\t */\n\t\t\t\"sLoadingRecords\": \"Loading...\",\n\t\t\n\t\t\n\t\t\t/**\n\t\t\t * Text which is displayed when the table is processing a user action\n\t\t\t * (usually a sort command or similar).\n\t\t\t *  @type string\n\t\t\t *  @default Processing...\n\t\t\t *  @dtopt Language\n\t\t\t * \n\t\t\t *  @example\n\t\t\t *    $(document).ready( function() {\n\t\t\t *      $('#example').dataTable( {\n\t\t\t *        \"oLanguage\": {\n\t\t\t *          \"sProcessing\": \"DataTables is currently busy\"\n\t\t\t *        }\n\t\t\t *      } );\n\t\t\t *    } );\n\t\t\t */\n\t\t\t\"sProcessing\": \"Processing...\",\n\t\t\n\t\t\n\t\t\t/**\n\t\t\t * Details the actions that will be taken when the user types into the\n\t\t\t * filtering input text box. The variable \"_INPUT_\", if used in the string,\n\t\t\t * is replaced with the HTML text box for the filtering input allowing\n\t\t\t * control over where it appears in the string. If \"_INPUT_\" is not given\n\t\t\t * then the input box is appended to the string automatically.\n\t\t\t *  @type string\n\t\t\t *  @default Search:\n\t\t\t *  @dtopt Language\n\t\t\t * \n\t\t\t *  @example\n\t\t\t *    // Input text box will be appended at the end automatically\n\t\t\t *    $(document).ready( function() {\n\t\t\t *      $('#example').dataTable( {\n\t\t\t *        \"oLanguage\": {\n\t\t\t *          \"sSearch\": \"Filter records:\"\n\t\t\t *        }\n\t\t\t *      } );\n\t\t\t *    } );\n\t\t\t *    \n\t\t\t *  @example\n\t\t\t *    // Specify where the filter should appear\n\t\t\t *    $(document).ready( function() {\n\t\t\t *      $('#example').dataTable( {\n\t\t\t *        \"oLanguage\": {\n\t\t\t *          \"sSearch\": \"Apply filter _INPUT_ to table\"\n\t\t\t *        }\n\t\t\t *      } );\n\t\t\t *    } );\n\t\t\t */\n\t\t\t\"sSearch\": \"Search:\",\n\t\t\n\t\t\n\t\t\t/**\n\t\t\t * All of the language information can be stored in a file on the\n\t\t\t * server-side, which DataTables will look up if this parameter is passed.\n\t\t\t * It must store the URL of the language file, which is in a JSON format,\n\t\t\t * and the object has the same properties as the oLanguage object in the\n\t\t\t * initialiser object (i.e. the above parameters). Please refer to one of\n\t\t\t * the example language files to see how this works in action.\n\t\t\t *  @type string\n\t\t\t *  @default <i>Empty string - i.e. disabled</i>\n\t\t\t *  @dtopt Language\n\t\t\t * \n\t\t\t *  @example\n\t\t\t *    $(document).ready( function() {\n\t\t\t *      $('#example').dataTable( {\n\t\t\t *        \"oLanguage\": {\n\t\t\t *          \"sUrl\": \"http://www.sprymedia.co.uk/dataTables/lang.txt\"\n\t\t\t *        }\n\t\t\t *      } );\n\t\t\t *    } );\n\t\t\t */\n\t\t\t\"sUrl\": \"\",\n\t\t\n\t\t\n\t\t\t/**\n\t\t\t * Text shown inside the table records when the is no information to be\n\t\t\t * displayed after filtering. sEmptyTable is shown when there is simply no\n\t\t\t * information in the table at all (regardless of filtering).\n\t\t\t *  @type string\n\t\t\t *  @default No matching records found\n\t\t\t *  @dtopt Language\n\t\t\t * \n\t\t\t *  @example\n\t\t\t *    $(document).ready( function() {\n\t\t\t *      $('#example').dataTable( {\n\t\t\t *        \"oLanguage\": {\n\t\t\t *          \"sZeroRecords\": \"No records to display\"\n\t\t\t *        }\n\t\t\t *      } );\n\t\t\t *    } );\n\t\t\t */\n\t\t\t\"sZeroRecords\": \"No matching records found\"\n\t\t},\n\t\n\t\n\t\t/**\n\t\t * This parameter allows you to have define the global filtering state at\n\t\t * initialisation time. As an object the \"sSearch\" parameter must be\n\t\t * defined, but all other parameters are optional. When \"bRegex\" is true,\n\t\t * the search string will be treated as a regular expression, when false\n\t\t * (default) it will be treated as a straight string. When \"bSmart\"\n\t\t * DataTables will use it's smart filtering methods (to word match at\n\t\t * any point in the data), when false this will not be done.\n\t\t *  @namespace\n\t\t *  @extends DataTable.models.oSearch\n\t\t *  @dtopt Options\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"oSearch\": {\"sSearch\": \"Initial search\"}\n\t\t *      } );\n\t\t *    } )\n\t\t */\n\t\t\"oSearch\": $.extend( {}, DataTable.models.oSearch ),\n\t\n\t\n\t\t/**\n\t\t * By default DataTables will look for the property 'aaData' when obtaining\n\t\t * data from an Ajax source or for server-side processing - this parameter\n\t\t * allows that property to be changed. You can use Javascript dotted object\n\t\t * notation to get a data source for multiple levels of nesting.\n\t\t *  @type string\n\t\t *  @default aaData\n\t\t *  @dtopt Options\n\t\t *  @dtopt Server-side\n\t\t * \n\t\t *  @example\n\t\t *    // Get data from { \"data\": [...] }\n\t\t *    $(document).ready( function() {\n\t\t *      var oTable = $('#example').dataTable( {\n\t\t *        \"sAjaxSource\": \"sources/data.txt\",\n\t\t *        \"sAjaxDataProp\": \"data\"\n\t\t *      } );\n\t\t *    } );\n\t\t *    \n\t\t *  @example\n\t\t *    // Get data from { \"data\": { \"inner\": [...] } }\n\t\t *    $(document).ready( function() {\n\t\t *      var oTable = $('#example').dataTable( {\n\t\t *        \"sAjaxSource\": \"sources/data.txt\",\n\t\t *        \"sAjaxDataProp\": \"data.inner\"\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"sAjaxDataProp\": \"aaData\",\n\t\n\t\n\t\t/**\n\t\t * You can instruct DataTables to load data from an external source using this\n\t\t * parameter (use aData if you want to pass data in you already have). Simply\n\t\t * provide a url a JSON object can be obtained from. This object must include\n\t\t * the parameter 'aaData' which is the data source for the table.\n\t\t *  @type string\n\t\t *  @default null\n\t\t *  @dtopt Options\n\t\t *  @dtopt Server-side\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"sAjaxSource\": \"http://www.sprymedia.co.uk/dataTables/json.php\"\n\t\t *      } );\n\t\t *    } )\n\t\t */\n\t\t\"sAjaxSource\": null,\n\t\n\t\n\t\t/**\n\t\t * This parameter can be used to override the default prefix that DataTables\n\t\t * assigns to a cookie when state saving is enabled.\n\t\t *  @type string\n\t\t *  @default SpryMedia_DataTables_\n\t\t *  @dtopt Options\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"sCookiePrefix\": \"my_datatable_\",\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"sCookiePrefix\": \"SpryMedia_DataTables_\",\n\t\n\t\n\t\t/**\n\t\t * This initialisation variable allows you to specify exactly where in the\n\t\t * DOM you want DataTables to inject the various controls it adds to the page\n\t\t * (for example you might want the pagination controls at the top of the\n\t\t * table). DIV elements (with or without a custom class) can also be added to\n\t\t * aid styling. The follow syntax is used:\n\t\t *   <ul>\n\t\t *     <li>The following options are allowed:\t\n\t\t *       <ul>\n\t\t *         <li>'l' - Length changing</li\n\t\t *         <li>'f' - Filtering input</li>\n\t\t *         <li>'t' - The table!</li>\n\t\t *         <li>'i' - Information</li>\n\t\t *         <li>'p' - Pagination</li>\n\t\t *         <li>'r' - pRocessing</li>\n\t\t *       </ul>\n\t\t *     </li>\n\t\t *     <li>The following constants are allowed:\n\t\t *       <ul>\n\t\t *         <li>'H' - jQueryUI theme \"header\" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li>\n\t\t *         <li>'F' - jQueryUI theme \"footer\" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li>\n\t\t *       </ul>\n\t\t *     </li>\n\t\t *     <li>The following syntax is expected:\n\t\t *       <ul>\n\t\t *         <li>'&lt;' and '&gt;' - div elements</li>\n\t\t *         <li>'&lt;\"class\" and '&gt;' - div with a class</li>\n\t\t *         <li>'&lt;\"#id\" and '&gt;' - div with an ID</li>\n\t\t *       </ul>\n\t\t *     </li>\n\t\t *     <li>Examples:\n\t\t *       <ul>\n\t\t *         <li>'&lt;\"wrapper\"flipt&gt;'</li>\n\t\t *         <li>'&lt;lf&lt;t&gt;ip&gt;'</li>\n\t\t *       </ul>\n\t\t *     </li>\n\t\t *   </ul>\n\t\t *  @type string\n\t\t *  @default lfrtip <i>(when bJQueryUI is false)</i> <b>or</b> \n\t\t *    <\"H\"lfr>t<\"F\"ip> <i>(when bJQueryUI is true)</i>\n\t\t *  @dtopt Options\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"sDom\": '&lt;\"top\"i&gt;rt&lt;\"bottom\"flp&gt;&lt;\"clear\"&gt;'\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"sDom\": \"lfrtip\",\n\t\n\t\n\t\t/**\n\t\t * DataTables features two different built-in pagination interaction methods\n\t\t * ('two_button' or 'full_numbers') which present different page controls to\n\t\t * the end user. Further methods can be added using the API (see below).\n\t\t *  @type string\n\t\t *  @default two_button\n\t\t *  @dtopt Options\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"sPaginationType\": \"full_numbers\"\n\t\t *      } );\n\t\t *    } )\n\t\t */\n\t\t\"sPaginationType\": \"two_button\",\n\t\n\t\n\t\t/**\n\t\t * Enable horizontal scrolling. When a table is too wide to fit into a certain\n\t\t * layout, or you have a large number of columns in the table, you can enable\n\t\t * x-scrolling to show the table in a viewport, which can be scrolled. This\n\t\t * property can be any CSS unit, or a number (in which case it will be treated\n\t\t * as a pixel measurement).\n\t\t *  @type string\n\t\t *  @default <i>blank string - i.e. disabled</i>\n\t\t *  @dtopt Features\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"sScrollX\": \"100%\",\n\t\t *        \"bScrollCollapse\": true\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"sScrollX\": \"\",\n\t\n\t\n\t\t/**\n\t\t * This property can be used to force a DataTable to use more width than it\n\t\t * might otherwise do when x-scrolling is enabled. For example if you have a\n\t\t * table which requires to be well spaced, this parameter is useful for\n\t\t * \"over-sizing\" the table, and thus forcing scrolling. This property can by\n\t\t * any CSS unit, or a number (in which case it will be treated as a pixel\n\t\t * measurement).\n\t\t *  @type string\n\t\t *  @default <i>blank string - i.e. disabled</i>\n\t\t *  @dtopt Options\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"sScrollX\": \"100%\",\n\t\t *        \"sScrollXInner\": \"110%\"\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"sScrollXInner\": \"\",\n\t\n\t\n\t\t/**\n\t\t * Enable vertical scrolling. Vertical scrolling will constrain the DataTable\n\t\t * to the given height, and enable scrolling for any data which overflows the\n\t\t * current viewport. This can be used as an alternative to paging to display\n\t\t * a lot of data in a small area (although paging and scrolling can both be\n\t\t * enabled at the same time). This property can be any CSS unit, or a number\n\t\t * (in which case it will be treated as a pixel measurement).\n\t\t *  @type string\n\t\t *  @default <i>blank string - i.e. disabled</i>\n\t\t *  @dtopt Features\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"sScrollY\": \"200px\",\n\t\t *        \"bPaginate\": false\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"sScrollY\": \"\",\n\t\n\t\n\t\t/**\n\t\t * Set the HTTP method that is used to make the Ajax call for server-side\n\t\t * processing or Ajax sourced data.\n\t\t *  @type string\n\t\t *  @default GET\n\t\t *  @dtopt Options\n\t\t *  @dtopt Server-side\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"bServerSide\": true,\n\t\t *        \"sAjaxSource\": \"scripts/post.php\",\n\t\t *        \"sServerMethod\": \"POST\"\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"sServerMethod\": \"GET\"\n\t};\n\t\n\t\n\t\n\t/**\n\t * Column options that can be given to DataTables at initialisation time.\n\t *  @namespace\n\t */\n\tDataTable.defaults.columns = {\n\t\t/**\n\t\t * Allows a column's sorting to take multiple columns into account when \n\t\t * doing a sort. For example first name / last name columns make sense to \n\t\t * do a multi-column sort over the two columns.\n\t\t *  @type array\n\t\t *  @default null <i>Takes the value of the column index automatically</i>\n\t\t *  @dtopt Columns\n\t\t * \n\t\t *  @example\n\t\t *    // Using aoColumnDefs\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"aoColumnDefs\": [\n\t\t *          { \"aDataSort\": [ 0, 1 ], \"aTargets\": [ 0 ] },\n\t\t *          { \"aDataSort\": [ 1, 0 ], \"aTargets\": [ 1 ] },\n\t\t *          { \"aDataSort\": [ 2, 3, 4 ], \"aTargets\": [ 2 ] }\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t *    \n\t\t *  @example\n\t\t *    // Using aoColumns\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"aoColumns\": [\n\t\t *          { \"aDataSort\": [ 0, 1 ] },\n\t\t *          { \"aDataSort\": [ 1, 0 ] },\n\t\t *          { \"aDataSort\": [ 2, 3, 4 ] },\n\t\t *          null,\n\t\t *          null\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"aDataSort\": null,\n\t\n\t\n\t\t/**\n\t\t * You can control the default sorting direction, and even alter the behaviour\n\t\t * of the sort handler (i.e. only allow ascending sorting etc) using this\n\t\t * parameter.\n\t\t *  @type array\n\t\t *  @default [ 'asc', 'desc' ]\n\t\t *  @dtopt Columns\n\t\t * \n\t\t *  @example\n\t\t *    // Using aoColumnDefs\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"aoColumnDefs\": [\n\t\t *          { \"asSorting\": [ \"asc\" ], \"aTargets\": [ 1 ] },\n\t\t *          { \"asSorting\": [ \"desc\", \"asc\", \"asc\" ], \"aTargets\": [ 2 ] },\n\t\t *          { \"asSorting\": [ \"desc\" ], \"aTargets\": [ 3 ] }\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t *    \n\t\t *  @example\n\t\t *    // Using aoColumns\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"aoColumns\": [\n\t\t *          null,\n\t\t *          { \"asSorting\": [ \"asc\" ] },\n\t\t *          { \"asSorting\": [ \"desc\", \"asc\", \"asc\" ] },\n\t\t *          { \"asSorting\": [ \"desc\" ] },\n\t\t *          null\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"asSorting\": [ 'asc', 'desc' ],\n\t\n\t\n\t\t/**\n\t\t * Enable or disable filtering on the data in this column.\n\t\t *  @type boolean\n\t\t *  @default true\n\t\t *  @dtopt Columns\n\t\t * \n\t\t *  @example\n\t\t *    // Using aoColumnDefs\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"aoColumnDefs\": [ \n\t\t *          { \"bSearchable\": false, \"aTargets\": [ 0 ] }\n\t\t *        ] } );\n\t\t *    } );\n\t\t *    \n\t\t *  @example\n\t\t *    // Using aoColumns\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"aoColumns\": [ \n\t\t *          { \"bSearchable\": false },\n\t\t *          null,\n\t\t *          null,\n\t\t *          null,\n\t\t *          null\n\t\t *        ] } );\n\t\t *    } );\n\t\t */\n\t\t\"bSearchable\": true,\n\t\n\t\n\t\t/**\n\t\t * Enable or disable sorting on this column.\n\t\t *  @type boolean\n\t\t *  @default true\n\t\t *  @dtopt Columns\n\t\t * \n\t\t *  @example\n\t\t *    // Using aoColumnDefs\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"aoColumnDefs\": [ \n\t\t *          { \"bSortable\": false, \"aTargets\": [ 0 ] }\n\t\t *        ] } );\n\t\t *    } );\n\t\t *    \n\t\t *  @example\n\t\t *    // Using aoColumns\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"aoColumns\": [ \n\t\t *          { \"bSortable\": false },\n\t\t *          null,\n\t\t *          null,\n\t\t *          null,\n\t\t *          null\n\t\t *        ] } );\n\t\t *    } );\n\t\t */\n\t\t\"bSortable\": true,\n\t\n\t\n\t\t/**\n\t\t * <code>Deprecated</code> When using fnRender() for a column, you may wish \n\t\t * to use the original data (before rendering) for sorting and filtering \n\t\t * (the default is to used the rendered data that the user can see). This \n\t\t * may be useful for dates etc.\n\t\t * \n\t\t * Please note that this option has now been deprecated and will be removed\n\t\t * in the next version of DataTables. Please use mRender / mData rather than\n\t\t * fnRender.\n\t\t *  @type boolean\n\t\t *  @default true\n\t\t *  @dtopt Columns\n\t\t *  @deprecated\n\t\t */\n\t\t\"bUseRendered\": true,\n\t\n\t\n\t\t/**\n\t\t * Enable or disable the display of this column.\n\t\t *  @type boolean\n\t\t *  @default true\n\t\t *  @dtopt Columns\n\t\t * \n\t\t *  @example\n\t\t *    // Using aoColumnDefs\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"aoColumnDefs\": [ \n\t\t *          { \"bVisible\": false, \"aTargets\": [ 0 ] }\n\t\t *        ] } );\n\t\t *    } );\n\t\t *    \n\t\t *  @example\n\t\t *    // Using aoColumns\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"aoColumns\": [ \n\t\t *          { \"bVisible\": false },\n\t\t *          null,\n\t\t *          null,\n\t\t *          null,\n\t\t *          null\n\t\t *        ] } );\n\t\t *    } );\n\t\t */\n\t\t\"bVisible\": true,\n\t\t\n\t\t\n\t\t/**\n\t\t * Developer definable function that is called whenever a cell is created (Ajax source,\n\t\t * etc) or processed for input (DOM source). This can be used as a compliment to mRender\n\t\t * allowing you to modify the DOM element (add background colour for example) when the\n\t\t * element is available.\n\t\t *  @type function\n\t\t *  @param {element} nTd The TD node that has been created\n\t\t *  @param {*} sData The Data for the cell\n\t\t *  @param {array|object} oData The data for the whole row\n\t\t *  @param {int} iRow The row index for the aoData data store\n\t\t *  @param {int} iCol The column index for aoColumns\n\t\t *  @dtopt Columns\n\t\t * \n\t\t *  @example\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"aoColumnDefs\": [ {\n\t\t *          \"aTargets\": [3],\n\t\t *          \"fnCreatedCell\": function (nTd, sData, oData, iRow, iCol) {\n\t\t *            if ( sData == \"1.7\" ) {\n\t\t *              $(nTd).css('color', 'blue')\n\t\t *            }\n\t\t *          }\n\t\t *        } ]\n\t\t *      });\n\t\t *    } );\n\t\t */\n\t\t\"fnCreatedCell\": null,\n\t\n\t\n\t\t/**\n\t\t * <code>Deprecated</code> Custom display function that will be called for the \n\t\t * display of each cell in this column.\n\t\t *\n\t\t * Please note that this option has now been deprecated and will be removed\n\t\t * in the next version of DataTables. Please use mRender / mData rather than\n\t\t * fnRender.\n\t\t *  @type function\n\t\t *  @param {object} o Object with the following parameters:\n\t\t *  @param {int}    o.iDataRow The row in aoData\n\t\t *  @param {int}    o.iDataColumn The column in question\n\t\t *  @param {array}  o.aData The data for the row in question\n\t\t *  @param {object} o.oSettings The settings object for this DataTables instance\n\t\t *  @param {object} o.mDataProp The data property used for this column\n\t\t *  @param {*}      val The current cell value\n\t\t *  @returns {string} The string you which to use in the display\n\t\t *  @dtopt Columns\n\t\t *  @deprecated\n\t\t */\n\t\t\"fnRender\": null,\n\t\n\t\n\t\t/**\n\t\t * The column index (starting from 0!) that you wish a sort to be performed\n\t\t * upon when this column is selected for sorting. This can be used for sorting\n\t\t * on hidden columns for example.\n\t\t *  @type int\n\t\t *  @default -1 <i>Use automatically calculated column index</i>\n\t\t *  @dtopt Columns\n\t\t * \n\t\t *  @example\n\t\t *    // Using aoColumnDefs\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"aoColumnDefs\": [ \n\t\t *          { \"iDataSort\": 1, \"aTargets\": [ 0 ] }\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t *    \n\t\t *  @example\n\t\t *    // Using aoColumns\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"aoColumns\": [ \n\t\t *          { \"iDataSort\": 1 },\n\t\t *          null,\n\t\t *          null,\n\t\t *          null,\n\t\t *          null\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"iDataSort\": -1,\n\t\n\t\n\t\t/**\n\t\t * This parameter has been replaced by mData in DataTables to ensure naming\n\t\t * consistency. mDataProp can still be used, as there is backwards compatibility\n\t\t * in DataTables for this option, but it is strongly recommended that you use\n\t\t * mData in preference to mDataProp.\n\t\t *  @name DataTable.defaults.columns.mDataProp\n\t\t */\n\t\n\t\n\t\t/**\n\t\t * This property can be used to read data from any JSON data source property,\n\t\t * including deeply nested objects / properties. mData can be given in a\n\t\t * number of different ways which effect its behaviour:\n\t\t *   <ul>\n\t\t *     <li>integer - treated as an array index for the data source. This is the\n\t\t *       default that DataTables uses (incrementally increased for each column).</li>\n\t\t *     <li>string - read an object property from the data source. Note that you can\n\t\t *       use Javascript dotted notation to read deep properties / arrays from the\n\t\t *       data source.</li>\n\t\t *     <li>null - the sDefaultContent option will be used for the cell (null\n\t\t *       by default, so you will need to specify the default content you want -\n\t\t *       typically an empty string). This can be useful on generated columns such \n\t\t *       as edit / delete action columns.</li>\n\t\t *     <li>function - the function given will be executed whenever DataTables \n\t\t *       needs to set or get the data for a cell in the column. The function \n\t\t *       takes three parameters:\n\t\t *       <ul>\n\t\t *         <li>{array|object} The data source for the row</li>\n\t\t *         <li>{string} The type call data requested - this will be 'set' when\n\t\t *           setting data or 'filter', 'display', 'type', 'sort' or undefined when \n\t\t *           gathering data. Note that when <i>undefined</i> is given for the type\n\t\t *           DataTables expects to get the raw data for the object back</li>\n\t\t *         <li>{*} Data to set when the second parameter is 'set'.</li>\n\t\t *       </ul>\n\t\t *       The return value from the function is not required when 'set' is the type\n\t\t *       of call, but otherwise the return is what will be used for the data\n\t\t *       requested.</li>\n\t\t *    </ul>\n\t\t *\n\t\t * Note that prior to DataTables 1.9.2 mData was called mDataProp. The name change\n\t\t * reflects the flexibility of this property and is consistent with the naming of\n\t\t * mRender. If 'mDataProp' is given, then it will still be used by DataTables, as\n\t\t * it automatically maps the old name to the new if required.\n\t\t *  @type string|int|function|null\n\t\t *  @default null <i>Use automatically calculated column index</i>\n\t\t *  @dtopt Columns\n\t\t * \n\t\t *  @example\n\t\t *    // Read table data from objects\n\t\t *    $(document).ready( function() {\n\t\t *      var oTable = $('#example').dataTable( {\n\t\t *        \"sAjaxSource\": \"sources/deep.txt\",\n\t\t *        \"aoColumns\": [\n\t\t *          { \"mData\": \"engine\" },\n\t\t *          { \"mData\": \"browser\" },\n\t\t *          { \"mData\": \"platform.inner\" },\n\t\t *          { \"mData\": \"platform.details.0\" },\n\t\t *          { \"mData\": \"platform.details.1\" }\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t * \n\t\t *  @example\n\t\t *    // Using mData as a function to provide different information for\n\t\t *    // sorting, filtering and display. In this case, currency (price)\n\t\t *    $(document).ready( function() {\n\t\t *      var oTable = $('#example').dataTable( {\n\t\t *        \"aoColumnDefs\": [ {\n\t\t *          \"aTargets\": [ 0 ],\n\t\t *          \"mData\": function ( source, type, val ) {\n\t\t *            if (type === 'set') {\n\t\t *              source.price = val;\n\t\t *              // Store the computed dislay and filter values for efficiency\n\t\t *              source.price_display = val==\"\" ? \"\" : \"$\"+numberFormat(val);\n\t\t *              source.price_filter  = val==\"\" ? \"\" : \"$\"+numberFormat(val)+\" \"+val;\n\t\t *              return;\n\t\t *            }\n\t\t *            else if (type === 'display') {\n\t\t *              return source.price_display;\n\t\t *            }\n\t\t *            else if (type === 'filter') {\n\t\t *              return source.price_filter;\n\t\t *            }\n\t\t *            // 'sort', 'type' and undefined all just use the integer\n\t\t *            return source.price;\n\t\t *          }\n\t\t *        } ]\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"mData\": null,\n\t\n\t\n\t\t/**\n\t\t * This property is the rendering partner to mData and it is suggested that\n\t\t * when you want to manipulate data for display (including filtering, sorting etc)\n\t\t * but not altering the underlying data for the table, use this property. mData\n\t\t * can actually do everything this property can and more, but this parameter is\n\t\t * easier to use since there is no 'set' option. Like mData is can be given\n\t\t * in a number of different ways to effect its behaviour, with the addition of \n\t\t * supporting array syntax for easy outputting of arrays (including arrays of\n\t\t * objects):\n\t\t *   <ul>\n\t\t *     <li>integer - treated as an array index for the data source. This is the\n\t\t *       default that DataTables uses (incrementally increased for each column).</li>\n\t\t *     <li>string - read an object property from the data source. Note that you can\n\t\t *       use Javascript dotted notation to read deep properties / arrays from the\n\t\t *       data source and also array brackets to indicate that the data reader should\n\t\t *       loop over the data source array. When characters are given between the array\n\t\t *       brackets, these characters are used to join the data source array together.\n\t\t *       For example: \"accounts[, ].name\" would result in a comma separated list with\n\t\t *       the 'name' value from the 'accounts' array of objects.</li>\n\t\t *     <li>function - the function given will be executed whenever DataTables \n\t\t *       needs to set or get the data for a cell in the column. The function \n\t\t *       takes three parameters:\n\t\t *       <ul>\n\t\t *         <li>{array|object} The data source for the row (based on mData)</li>\n\t\t *         <li>{string} The type call data requested - this will be 'filter', 'display', \n\t\t *           'type' or 'sort'.</li>\n\t\t *         <li>{array|object} The full data source for the row (not based on mData)</li>\n\t\t *       </ul>\n\t\t *       The return value from the function is what will be used for the data\n\t\t *       requested.</li>\n\t\t *    </ul>\n\t\t *  @type string|int|function|null\n\t\t *  @default null <i>Use mData</i>\n\t\t *  @dtopt Columns\n\t\t * \n\t\t *  @example\n\t\t *    // Create a comma separated list from an array of objects\n\t\t *    $(document).ready( function() {\n\t\t *      var oTable = $('#example').dataTable( {\n\t\t *        \"sAjaxSource\": \"sources/deep.txt\",\n\t\t *        \"aoColumns\": [\n\t\t *          { \"mData\": \"engine\" },\n\t\t *          { \"mData\": \"browser\" },\n\t\t *          {\n\t\t *            \"mData\": \"platform\",\n\t\t *            \"mRender\": \"[, ].name\"\n\t\t *          }\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t * \n\t\t *  @example\n\t\t *    // Use as a function to create a link from the data source\n\t\t *    $(document).ready( function() {\n\t\t *      var oTable = $('#example').dataTable( {\n\t\t *        \"aoColumnDefs\": [\n\t\t *        {\n\t\t *          \"aTargets\": [ 0 ],\n\t\t *          \"mData\": \"download_link\",\n\t\t *          \"mRender\": function ( data, type, full ) {\n\t\t *            return '<a href=\"'+data+'\">Download</a>';\n\t\t *          }\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"mRender\": null,\n\t\n\t\n\t\t/**\n\t\t * Change the cell type created for the column - either TD cells or TH cells. This\n\t\t * can be useful as TH cells have semantic meaning in the table body, allowing them\n\t\t * to act as a header for a row (you may wish to add scope='row' to the TH elements).\n\t\t *  @type string\n\t\t *  @default td\n\t\t *  @dtopt Columns\n\t\t * \n\t\t *  @example\n\t\t *    // Make the first column use TH cells\n\t\t *    $(document).ready( function() {\n\t\t *      var oTable = $('#example').dataTable( {\n\t\t *        \"aoColumnDefs\": [ {\n\t\t *          \"aTargets\": [ 0 ],\n\t\t *          \"sCellType\": \"th\"\n\t\t *        } ]\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"sCellType\": \"td\",\n\t\n\t\n\t\t/**\n\t\t * Class to give to each cell in this column.\n\t\t *  @type string\n\t\t *  @default <i>Empty string</i>\n\t\t *  @dtopt Columns\n\t\t * \n\t\t *  @example\n\t\t *    // Using aoColumnDefs\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"aoColumnDefs\": [ \n\t\t *          { \"sClass\": \"my_class\", \"aTargets\": [ 0 ] }\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t *    \n\t\t *  @example\n\t\t *    // Using aoColumns\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"aoColumns\": [ \n\t\t *          { \"sClass\": \"my_class\" },\n\t\t *          null,\n\t\t *          null,\n\t\t *          null,\n\t\t *          null\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"sClass\": \"\",\n\t\t\n\t\t/**\n\t\t * When DataTables calculates the column widths to assign to each column,\n\t\t * it finds the longest string in each column and then constructs a\n\t\t * temporary table and reads the widths from that. The problem with this\n\t\t * is that \"mmm\" is much wider then \"iiii\", but the latter is a longer \n\t\t * string - thus the calculation can go wrong (doing it properly and putting\n\t\t * it into an DOM object and measuring that is horribly(!) slow). Thus as\n\t\t * a \"work around\" we provide this option. It will append its value to the\n\t\t * text that is found to be the longest string for the column - i.e. padding.\n\t\t * Generally you shouldn't need this, and it is not documented on the \n\t\t * general DataTables.net documentation\n\t\t *  @type string\n\t\t *  @default <i>Empty string<i>\n\t\t *  @dtopt Columns\n\t\t *    \n\t\t *  @example\n\t\t *    // Using aoColumns\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"aoColumns\": [ \n\t\t *          null,\n\t\t *          null,\n\t\t *          null,\n\t\t *          {\n\t\t *            \"sContentPadding\": \"mmm\"\n\t\t *          }\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"sContentPadding\": \"\",\n\t\n\t\n\t\t/**\n\t\t * Allows a default value to be given for a column's data, and will be used\n\t\t * whenever a null data source is encountered (this can be because mData\n\t\t * is set to null, or because the data source itself is null).\n\t\t *  @type string\n\t\t *  @default null\n\t\t *  @dtopt Columns\n\t\t * \n\t\t *  @example\n\t\t *    // Using aoColumnDefs\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"aoColumnDefs\": [ \n\t\t *          {\n\t\t *            \"mData\": null,\n\t\t *            \"sDefaultContent\": \"Edit\",\n\t\t *            \"aTargets\": [ -1 ]\n\t\t *          }\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t *    \n\t\t *  @example\n\t\t *    // Using aoColumns\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"aoColumns\": [ \n\t\t *          null,\n\t\t *          null,\n\t\t *          null,\n\t\t *          {\n\t\t *            \"mData\": null,\n\t\t *            \"sDefaultContent\": \"Edit\"\n\t\t *          }\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"sDefaultContent\": null,\n\t\n\t\n\t\t/**\n\t\t * This parameter is only used in DataTables' server-side processing. It can\n\t\t * be exceptionally useful to know what columns are being displayed on the\n\t\t * client side, and to map these to database fields. When defined, the names\n\t\t * also allow DataTables to reorder information from the server if it comes\n\t\t * back in an unexpected order (i.e. if you switch your columns around on the\n\t\t * client-side, your server-side code does not also need updating).\n\t\t *  @type string\n\t\t *  @default <i>Empty string</i>\n\t\t *  @dtopt Columns\n\t\t * \n\t\t *  @example\n\t\t *    // Using aoColumnDefs\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"aoColumnDefs\": [ \n\t\t *          { \"sName\": \"engine\", \"aTargets\": [ 0 ] },\n\t\t *          { \"sName\": \"browser\", \"aTargets\": [ 1 ] },\n\t\t *          { \"sName\": \"platform\", \"aTargets\": [ 2 ] },\n\t\t *          { \"sName\": \"version\", \"aTargets\": [ 3 ] },\n\t\t *          { \"sName\": \"grade\", \"aTargets\": [ 4 ] }\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t *    \n\t\t *  @example\n\t\t *    // Using aoColumns\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"aoColumns\": [ \n\t\t *          { \"sName\": \"engine\" },\n\t\t *          { \"sName\": \"browser\" },\n\t\t *          { \"sName\": \"platform\" },\n\t\t *          { \"sName\": \"version\" },\n\t\t *          { \"sName\": \"grade\" }\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"sName\": \"\",\n\t\n\t\n\t\t/**\n\t\t * Defines a data source type for the sorting which can be used to read\n\t\t * real-time information from the table (updating the internally cached\n\t\t * version) prior to sorting. This allows sorting to occur on user editable\n\t\t * elements such as form inputs.\n\t\t *  @type string\n\t\t *  @default std\n\t\t *  @dtopt Columns\n\t\t * \n\t\t *  @example\n\t\t *    // Using aoColumnDefs\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"aoColumnDefs\": [\n\t\t *          { \"sSortDataType\": \"dom-text\", \"aTargets\": [ 2, 3 ] },\n\t\t *          { \"sType\": \"numeric\", \"aTargets\": [ 3 ] },\n\t\t *          { \"sSortDataType\": \"dom-select\", \"aTargets\": [ 4 ] },\n\t\t *          { \"sSortDataType\": \"dom-checkbox\", \"aTargets\": [ 5 ] }\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t *    \n\t\t *  @example\n\t\t *    // Using aoColumns\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"aoColumns\": [\n\t\t *          null,\n\t\t *          null,\n\t\t *          { \"sSortDataType\": \"dom-text\" },\n\t\t *          { \"sSortDataType\": \"dom-text\", \"sType\": \"numeric\" },\n\t\t *          { \"sSortDataType\": \"dom-select\" },\n\t\t *          { \"sSortDataType\": \"dom-checkbox\" }\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"sSortDataType\": \"std\",\n\t\n\t\n\t\t/**\n\t\t * The title of this column.\n\t\t *  @type string\n\t\t *  @default null <i>Derived from the 'TH' value for this column in the \n\t\t *    original HTML table.</i>\n\t\t *  @dtopt Columns\n\t\t * \n\t\t *  @example\n\t\t *    // Using aoColumnDefs\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"aoColumnDefs\": [ \n\t\t *          { \"sTitle\": \"My column title\", \"aTargets\": [ 0 ] }\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t *    \n\t\t *  @example\n\t\t *    // Using aoColumns\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"aoColumns\": [ \n\t\t *          { \"sTitle\": \"My column title\" },\n\t\t *          null,\n\t\t *          null,\n\t\t *          null,\n\t\t *          null\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"sTitle\": null,\n\t\n\t\n\t\t/**\n\t\t * The type allows you to specify how the data for this column will be sorted.\n\t\t * Four types (string, numeric, date and html (which will strip HTML tags\n\t\t * before sorting)) are currently available. Note that only date formats\n\t\t * understood by Javascript's Date() object will be accepted as type date. For\n\t\t * example: \"Mar 26, 2008 5:03 PM\". May take the values: 'string', 'numeric',\n\t\t * 'date' or 'html' (by default). Further types can be adding through\n\t\t * plug-ins.\n\t\t *  @type string\n\t\t *  @default null <i>Auto-detected from raw data</i>\n\t\t *  @dtopt Columns\n\t\t * \n\t\t *  @example\n\t\t *    // Using aoColumnDefs\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"aoColumnDefs\": [ \n\t\t *          { \"sType\": \"html\", \"aTargets\": [ 0 ] }\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t *    \n\t\t *  @example\n\t\t *    // Using aoColumns\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"aoColumns\": [ \n\t\t *          { \"sType\": \"html\" },\n\t\t *          null,\n\t\t *          null,\n\t\t *          null,\n\t\t *          null\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"sType\": null,\n\t\n\t\n\t\t/**\n\t\t * Defining the width of the column, this parameter may take any CSS value\n\t\t * (3em, 20px etc). DataTables apples 'smart' widths to columns which have not\n\t\t * been given a specific width through this interface ensuring that the table\n\t\t * remains readable.\n\t\t *  @type string\n\t\t *  @default null <i>Automatic</i>\n\t\t *  @dtopt Columns\n\t\t * \n\t\t *  @example\n\t\t *    // Using aoColumnDefs\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"aoColumnDefs\": [ \n\t\t *          { \"sWidth\": \"20%\", \"aTargets\": [ 0 ] }\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t *    \n\t\t *  @example\n\t\t *    // Using aoColumns\n\t\t *    $(document).ready( function() {\n\t\t *      $('#example').dataTable( {\n\t\t *        \"aoColumns\": [ \n\t\t *          { \"sWidth\": \"20%\" },\n\t\t *          null,\n\t\t *          null,\n\t\t *          null,\n\t\t *          null\n\t\t *        ]\n\t\t *      } );\n\t\t *    } );\n\t\t */\n\t\t\"sWidth\": null\n\t};\n\t\n\t\n\t\n\t/**\n\t * DataTables settings object - this holds all the information needed for a\n\t * given table, including configuration, data and current application of the\n\t * table options. DataTables does not have a single instance for each DataTable\n\t * with the settings attached to that instance, but rather instances of the\n\t * DataTable \"class\" are created on-the-fly as needed (typically by a \n\t * $().dataTable() call) and the settings object is then applied to that\n\t * instance.\n\t * \n\t * Note that this object is related to {@link DataTable.defaults} but this \n\t * one is the internal data store for DataTables's cache of columns. It should\n\t * NOT be manipulated outside of DataTables. Any configuration should be done\n\t * through the initialisation options.\n\t *  @namespace\n\t *  @todo Really should attach the settings object to individual instances so we\n\t *    don't need to create new instances on each $().dataTable() call (if the\n\t *    table already exists). It would also save passing oSettings around and\n\t *    into every single function. However, this is a very significant \n\t *    architecture change for DataTables and will almost certainly break\n\t *    backwards compatibility with older installations. This is something that\n\t *    will be done in 2.0.\n\t */\n\tDataTable.models.oSettings = {\n\t\t/**\n\t\t * Primary features of DataTables and their enablement state.\n\t\t *  @namespace\n\t\t */\n\t\t\"oFeatures\": {\n\t\t\t\n\t\t\t/**\n\t\t\t * Flag to say if DataTables should automatically try to calculate the\n\t\t\t * optimum table and columns widths (true) or not (false).\n\t\t\t * Note that this parameter will be set by the initialisation routine. To\n\t\t\t * set a default use {@link DataTable.defaults}.\n\t\t\t *  @type boolean\n\t\t\t */\n\t\t\t\"bAutoWidth\": null,\n\t\n\t\t\t/**\n\t\t\t * Delay the creation of TR and TD elements until they are actually\n\t\t\t * needed by a driven page draw. This can give a significant speed\n\t\t\t * increase for Ajax source and Javascript source data, but makes no\n\t\t\t * difference at all fro DOM and server-side processing tables.\n\t\t\t * Note that this parameter will be set by the initialisation routine. To\n\t\t\t * set a default use {@link DataTable.defaults}.\n\t\t\t *  @type boolean\n\t\t\t */\n\t\t\t\"bDeferRender\": null,\n\t\t\t\n\t\t\t/**\n\t\t\t * Enable filtering on the table or not. Note that if this is disabled\n\t\t\t * then there is no filtering at all on the table, including fnFilter.\n\t\t\t * To just remove the filtering input use sDom and remove the 'f' option.\n\t\t\t * Note that this parameter will be set by the initialisation routine. To\n\t\t\t * set a default use {@link DataTable.defaults}.\n\t\t\t *  @type boolean\n\t\t\t */\n\t\t\t\"bFilter\": null,\n\t\t\t\n\t\t\t/**\n\t\t\t * Table information element (the 'Showing x of y records' div) enable\n\t\t\t * flag.\n\t\t\t * Note that this parameter will be set by the initialisation routine. To\n\t\t\t * set a default use {@link DataTable.defaults}.\n\t\t\t *  @type boolean\n\t\t\t */\n\t\t\t\"bInfo\": null,\n\t\t\t\n\t\t\t/**\n\t\t\t * Present a user control allowing the end user to change the page size\n\t\t\t * when pagination is enabled.\n\t\t\t * Note that this parameter will be set by the initialisation routine. To\n\t\t\t * set a default use {@link DataTable.defaults}.\n\t\t\t *  @type boolean\n\t\t\t */\n\t\t\t\"bLengthChange\": null,\n\t\n\t\t\t/**\n\t\t\t * Pagination enabled or not. Note that if this is disabled then length\n\t\t\t * changing must also be disabled.\n\t\t\t * Note that this parameter will be set by the initialisation routine. To\n\t\t\t * set a default use {@link DataTable.defaults}.\n\t\t\t *  @type boolean\n\t\t\t */\n\t\t\t\"bPaginate\": null,\n\t\t\t\n\t\t\t/**\n\t\t\t * Processing indicator enable flag whenever DataTables is enacting a\n\t\t\t * user request - typically an Ajax request for server-side processing.\n\t\t\t * Note that this parameter will be set by the initialisation routine. To\n\t\t\t * set a default use {@link DataTable.defaults}.\n\t\t\t *  @type boolean\n\t\t\t */\n\t\t\t\"bProcessing\": null,\n\t\t\t\n\t\t\t/**\n\t\t\t * Server-side processing enabled flag - when enabled DataTables will\n\t\t\t * get all data from the server for every draw - there is no filtering,\n\t\t\t * sorting or paging done on the client-side.\n\t\t\t * Note that this parameter will be set by the initialisation routine. To\n\t\t\t * set a default use {@link DataTable.defaults}.\n\t\t\t *  @type boolean\n\t\t\t */\n\t\t\t\"bServerSide\": null,\n\t\t\t\n\t\t\t/**\n\t\t\t * Sorting enablement flag.\n\t\t\t * Note that this parameter will be set by the initialisation routine. To\n\t\t\t * set a default use {@link DataTable.defaults}.\n\t\t\t *  @type boolean\n\t\t\t */\n\t\t\t\"bSort\": null,\n\t\t\t\n\t\t\t/**\n\t\t\t * Apply a class to the columns which are being sorted to provide a\n\t\t\t * visual highlight or not. This can slow things down when enabled since\n\t\t\t * there is a lot of DOM interaction.\n\t\t\t * Note that this parameter will be set by the initialisation routine. To\n\t\t\t * set a default use {@link DataTable.defaults}.\n\t\t\t *  @type boolean\n\t\t\t */\n\t\t\t\"bSortClasses\": null,\n\t\t\t\n\t\t\t/**\n\t\t\t * State saving enablement flag.\n\t\t\t * Note that this parameter will be set by the initialisation routine. To\n\t\t\t * set a default use {@link DataTable.defaults}.\n\t\t\t *  @type boolean\n\t\t\t */\n\t\t\t\"bStateSave\": null\n\t\t},\n\t\t\n\t\n\t\t/**\n\t\t * Scrolling settings for a table.\n\t\t *  @namespace\n\t\t */\n\t\t\"oScroll\": {\n\t\t\t/**\n\t\t\t * Indicate if DataTables should be allowed to set the padding / margin\n\t\t\t * etc for the scrolling header elements or not. Typically you will want\n\t\t\t * this.\n\t\t\t * Note that this parameter will be set by the initialisation routine. To\n\t\t\t * set a default use {@link DataTable.defaults}.\n\t\t\t *  @type boolean\n\t\t\t */\n\t\t\t\"bAutoCss\": null,\n\t\t\t\n\t\t\t/**\n\t\t\t * When the table is shorter in height than sScrollY, collapse the\n\t\t\t * table container down to the height of the table (when true).\n\t\t\t * Note that this parameter will be set by the initialisation routine. To\n\t\t\t * set a default use {@link DataTable.defaults}.\n\t\t\t *  @type boolean\n\t\t\t */\n\t\t\t\"bCollapse\": null,\n\t\t\t\n\t\t\t/**\n\t\t\t * Infinite scrolling enablement flag. Now deprecated in favour of\n\t\t\t * using the Scroller plug-in.\n\t\t\t * Note that this parameter will be set by the initialisation routine. To\n\t\t\t * set a default use {@link DataTable.defaults}.\n\t\t\t *  @type boolean\n\t\t\t */\n\t\t\t\"bInfinite\": null,\n\t\t\t\n\t\t\t/**\n\t\t\t * Width of the scrollbar for the web-browser's platform. Calculated\n\t\t\t * during table initialisation.\n\t\t\t *  @type int\n\t\t\t *  @default 0\n\t\t\t */\n\t\t\t\"iBarWidth\": 0,\n\t\t\t\n\t\t\t/**\n\t\t\t * Space (in pixels) between the bottom of the scrolling container and \n\t\t\t * the bottom of the scrolling viewport before the next page is loaded\n\t\t\t * when using infinite scrolling.\n\t\t\t * Note that this parameter will be set by the initialisation routine. To\n\t\t\t * set a default use {@link DataTable.defaults}.\n\t\t\t *  @type int\n\t\t\t */\n\t\t\t\"iLoadGap\": null,\n\t\t\t\n\t\t\t/**\n\t\t\t * Viewport width for horizontal scrolling. Horizontal scrolling is \n\t\t\t * disabled if an empty string.\n\t\t\t * Note that this parameter will be set by the initialisation routine. To\n\t\t\t * set a default use {@link DataTable.defaults}.\n\t\t\t *  @type string\n\t\t\t */\n\t\t\t\"sX\": null,\n\t\t\t\n\t\t\t/**\n\t\t\t * Width to expand the table to when using x-scrolling. Typically you\n\t\t\t * should not need to use this.\n\t\t\t * Note that this parameter will be set by the initialisation routine. To\n\t\t\t * set a default use {@link DataTable.defaults}.\n\t\t\t *  @type string\n\t\t\t *  @deprecated\n\t\t\t */\n\t\t\t\"sXInner\": null,\n\t\t\t\n\t\t\t/**\n\t\t\t * Viewport height for vertical scrolling. Vertical scrolling is disabled\n\t\t\t * if an empty string.\n\t\t\t * Note that this parameter will be set by the initialisation routine. To\n\t\t\t * set a default use {@link DataTable.defaults}.\n\t\t\t *  @type string\n\t\t\t */\n\t\t\t\"sY\": null\n\t\t},\n\t\t\n\t\t/**\n\t\t * Language information for the table.\n\t\t *  @namespace\n\t\t *  @extends DataTable.defaults.oLanguage\n\t\t */\n\t\t\"oLanguage\": {\n\t\t\t/**\n\t\t\t * Information callback function. See \n\t\t\t * {@link DataTable.defaults.fnInfoCallback}\n\t\t\t *  @type function\n\t\t\t *  @default null\n\t\t\t */\n\t\t\t\"fnInfoCallback\": null\n\t\t},\n\t\t\n\t\t/**\n\t\t * Browser support parameters\n\t\t *  @namespace\n\t\t */\n\t\t\"oBrowser\": {\n\t\t\t/**\n\t\t\t * Indicate if the browser incorrectly calculates width:100% inside a\n\t\t\t * scrolling element (IE6/7)\n\t\t\t *  @type boolean\n\t\t\t *  @default false\n\t\t\t */\n\t\t\t\"bScrollOversize\": false\n\t\t},\n\t\t\n\t\t/**\n\t\t * Array referencing the nodes which are used for the features. The \n\t\t * parameters of this object match what is allowed by sDom - i.e.\n\t\t *   <ul>\n\t\t *     <li>'l' - Length changing</li>\n\t\t *     <li>'f' - Filtering input</li>\n\t\t *     <li>'t' - The table!</li>\n\t\t *     <li>'i' - Information</li>\n\t\t *     <li>'p' - Pagination</li>\n\t\t *     <li>'r' - pRocessing</li>\n\t\t *   </ul>\n\t\t *  @type array\n\t\t *  @default []\n\t\t */\n\t\t\"aanFeatures\": [],\n\t\t\n\t\t/**\n\t\t * Store data information - see {@link DataTable.models.oRow} for detailed\n\t\t * information.\n\t\t *  @type array\n\t\t *  @default []\n\t\t */\n\t\t\"aoData\": [],\n\t\t\n\t\t/**\n\t\t * Array of indexes which are in the current display (after filtering etc)\n\t\t *  @type array\n\t\t *  @default []\n\t\t */\n\t\t\"aiDisplay\": [],\n\t\t\n\t\t/**\n\t\t * Array of indexes for display - no filtering\n\t\t *  @type array\n\t\t *  @default []\n\t\t */\n\t\t\"aiDisplayMaster\": [],\n\t\t\n\t\t/**\n\t\t * Store information about each column that is in use\n\t\t *  @type array\n\t\t *  @default []\n\t\t */\n\t\t\"aoColumns\": [],\n\t\t\n\t\t/**\n\t\t * Store information about the table's header\n\t\t *  @type array\n\t\t *  @default []\n\t\t */\n\t\t\"aoHeader\": [],\n\t\t\n\t\t/**\n\t\t * Store information about the table's footer\n\t\t *  @type array\n\t\t *  @default []\n\t\t */\n\t\t\"aoFooter\": [],\n\t\t\n\t\t/**\n\t\t * Search data array for regular expression searching\n\t\t *  @type array\n\t\t *  @default []\n\t\t */\n\t\t\"asDataSearch\": [],\n\t\t\n\t\t/**\n\t\t * Store the applied global search information in case we want to force a \n\t\t * research or compare the old search to a new one.\n\t\t * Note that this parameter will be set by the initialisation routine. To\n\t\t * set a default use {@link DataTable.defaults}.\n\t\t *  @namespace\n\t\t *  @extends DataTable.models.oSearch\n\t\t */\n\t\t\"oPreviousSearch\": {},\n\t\t\n\t\t/**\n\t\t * Store the applied search for each column - see \n\t\t * {@link DataTable.models.oSearch} for the format that is used for the\n\t\t * filtering information for each column.\n\t\t *  @type array\n\t\t *  @default []\n\t\t */\n\t\t\"aoPreSearchCols\": [],\n\t\t\n\t\t/**\n\t\t * Sorting that is applied to the table. Note that the inner arrays are\n\t\t * used in the following manner:\n\t\t * <ul>\n\t\t *   <li>Index 0 - column number</li>\n\t\t *   <li>Index 1 - current sorting direction</li>\n\t\t *   <li>Index 2 - index of asSorting for this column</li>\n\t\t * </ul>\n\t\t * Note that this parameter will be set by the initialisation routine. To\n\t\t * set a default use {@link DataTable.defaults}.\n\t\t *  @type array\n\t\t *  @todo These inner arrays should really be objects\n\t\t */\n\t\t\"aaSorting\": null,\n\t\t\n\t\t/**\n\t\t * Sorting that is always applied to the table (i.e. prefixed in front of\n\t\t * aaSorting).\n\t\t * Note that this parameter will be set by the initialisation routine. To\n\t\t * set a default use {@link DataTable.defaults}.\n\t\t *  @type array|null\n\t\t *  @default null\n\t\t */\n\t\t\"aaSortingFixed\": null,\n\t\t\n\t\t/**\n\t\t * Classes to use for the striping of a table.\n\t\t * Note that this parameter will be set by the initialisation routine. To\n\t\t * set a default use {@link DataTable.defaults}.\n\t\t *  @type array\n\t\t *  @default []\n\t\t */\n\t\t\"asStripeClasses\": null,\n\t\t\n\t\t/**\n\t\t * If restoring a table - we should restore its striping classes as well\n\t\t *  @type array\n\t\t *  @default []\n\t\t */\n\t\t\"asDestroyStripes\": [],\n\t\t\n\t\t/**\n\t\t * If restoring a table - we should restore its width \n\t\t *  @type int\n\t\t *  @default 0\n\t\t */\n\t\t\"sDestroyWidth\": 0,\n\t\t\n\t\t/**\n\t\t * Callback functions array for every time a row is inserted (i.e. on a draw).\n\t\t *  @type array\n\t\t *  @default []\n\t\t */\n\t\t\"aoRowCallback\": [],\n\t\t\n\t\t/**\n\t\t * Callback functions for the header on each draw.\n\t\t *  @type array\n\t\t *  @default []\n\t\t */\n\t\t\"aoHeaderCallback\": [],\n\t\t\n\t\t/**\n\t\t * Callback function for the footer on each draw.\n\t\t *  @type array\n\t\t *  @default []\n\t\t */\n\t\t\"aoFooterCallback\": [],\n\t\t\n\t\t/**\n\t\t * Array of callback functions for draw callback functions\n\t\t *  @type array\n\t\t *  @default []\n\t\t */\n\t\t\"aoDrawCallback\": [],\n\t\t\n\t\t/**\n\t\t * Array of callback functions for row created function\n\t\t *  @type array\n\t\t *  @default []\n\t\t */\n\t\t\"aoRowCreatedCallback\": [],\n\t\t\n\t\t/**\n\t\t * Callback functions for just before the table is redrawn. A return of \n\t\t * false will be used to cancel the draw.\n\t\t *  @type array\n\t\t *  @default []\n\t\t */\n\t\t\"aoPreDrawCallback\": [],\n\t\t\n\t\t/**\n\t\t * Callback functions for when the table has been initialised.\n\t\t *  @type array\n\t\t *  @default []\n\t\t */\n\t\t\"aoInitComplete\": [],\n\t\n\t\t\n\t\t/**\n\t\t * Callbacks for modifying the settings to be stored for state saving, prior to\n\t\t * saving state.\n\t\t *  @type array\n\t\t *  @default []\n\t\t */\n\t\t\"aoStateSaveParams\": [],\n\t\t\n\t\t/**\n\t\t * Callbacks for modifying the settings that have been stored for state saving\n\t\t * prior to using the stored values to restore the state.\n\t\t *  @type array\n\t\t *  @default []\n\t\t */\n\t\t\"aoStateLoadParams\": [],\n\t\t\n\t\t/**\n\t\t * Callbacks for operating on the settings object once the saved state has been\n\t\t * loaded\n\t\t *  @type array\n\t\t *  @default []\n\t\t */\n\t\t\"aoStateLoaded\": [],\n\t\t\n\t\t/**\n\t\t * Cache the table ID for quick access\n\t\t *  @type string\n\t\t *  @default <i>Empty string</i>\n\t\t */\n\t\t\"sTableId\": \"\",\n\t\t\n\t\t/**\n\t\t * The TABLE node for the main table\n\t\t *  @type node\n\t\t *  @default null\n\t\t */\n\t\t\"nTable\": null,\n\t\t\n\t\t/**\n\t\t * Permanent ref to the thead element\n\t\t *  @type node\n\t\t *  @default null\n\t\t */\n\t\t\"nTHead\": null,\n\t\t\n\t\t/**\n\t\t * Permanent ref to the tfoot element - if it exists\n\t\t *  @type node\n\t\t *  @default null\n\t\t */\n\t\t\"nTFoot\": null,\n\t\t\n\t\t/**\n\t\t * Permanent ref to the tbody element\n\t\t *  @type node\n\t\t *  @default null\n\t\t */\n\t\t\"nTBody\": null,\n\t\t\n\t\t/**\n\t\t * Cache the wrapper node (contains all DataTables controlled elements)\n\t\t *  @type node\n\t\t *  @default null\n\t\t */\n\t\t\"nTableWrapper\": null,\n\t\t\n\t\t/**\n\t\t * Indicate if when using server-side processing the loading of data \n\t\t * should be deferred until the second draw.\n\t\t * Note that this parameter will be set by the initialisation routine. To\n\t\t * set a default use {@link DataTable.defaults}.\n\t\t *  @type boolean\n\t\t *  @default false\n\t\t */\n\t\t\"bDeferLoading\": false,\n\t\t\n\t\t/**\n\t\t * Indicate if all required information has been read in\n\t\t *  @type boolean\n\t\t *  @default false\n\t\t */\n\t\t\"bInitialised\": false,\n\t\t\n\t\t/**\n\t\t * Information about open rows. Each object in the array has the parameters\n\t\t * 'nTr' and 'nParent'\n\t\t *  @type array\n\t\t *  @default []\n\t\t */\n\t\t\"aoOpenRows\": [],\n\t\t\n\t\t/**\n\t\t * Dictate the positioning of DataTables' control elements - see\n\t\t * {@link DataTable.model.oInit.sDom}.\n\t\t * Note that this parameter will be set by the initialisation routine. To\n\t\t * set a default use {@link DataTable.defaults}.\n\t\t *  @type string\n\t\t *  @default null\n\t\t */\n\t\t\"sDom\": null,\n\t\t\n\t\t/**\n\t\t * Which type of pagination should be used.\n\t\t * Note that this parameter will be set by the initialisation routine. To\n\t\t * set a default use {@link DataTable.defaults}.\n\t\t *  @type string \n\t\t *  @default two_button\n\t\t */\n\t\t\"sPaginationType\": \"two_button\",\n\t\t\n\t\t/**\n\t\t * The cookie duration (for bStateSave) in seconds.\n\t\t * Note that this parameter will be set by the initialisation routine. To\n\t\t * set a default use {@link DataTable.defaults}.\n\t\t *  @type int\n\t\t *  @default 0\n\t\t */\n\t\t\"iCookieDuration\": 0,\n\t\t\n\t\t/**\n\t\t * The cookie name prefix.\n\t\t * Note that this parameter will be set by the initialisation routine. To\n\t\t * set a default use {@link DataTable.defaults}.\n\t\t *  @type string\n\t\t *  @default <i>Empty string</i>\n\t\t */\n\t\t\"sCookiePrefix\": \"\",\n\t\t\n\t\t/**\n\t\t * Callback function for cookie creation.\n\t\t * Note that this parameter will be set by the initialisation routine. To\n\t\t * set a default use {@link DataTable.defaults}.\n\t\t *  @type function\n\t\t *  @default null\n\t\t */\n\t\t\"fnCookieCallback\": null,\n\t\t\n\t\t/**\n\t\t * Array of callback functions for state saving. Each array element is an \n\t\t * object with the following parameters:\n\t\t *   <ul>\n\t\t *     <li>function:fn - function to call. Takes two parameters, oSettings\n\t\t *       and the JSON string to save that has been thus far created. Returns\n\t\t *       a JSON string to be inserted into a json object \n\t\t *       (i.e. '\"param\": [ 0, 1, 2]')</li>\n\t\t *     <li>string:sName - name of callback</li>\n\t\t *   </ul>\n\t\t *  @type array\n\t\t *  @default []\n\t\t */\n\t\t\"aoStateSave\": [],\n\t\t\n\t\t/**\n\t\t * Array of callback functions for state loading. Each array element is an \n\t\t * object with the following parameters:\n\t\t *   <ul>\n\t\t *     <li>function:fn - function to call. Takes two parameters, oSettings \n\t\t *       and the object stored. May return false to cancel state loading</li>\n\t\t *     <li>string:sName - name of callback</li>\n\t\t *   </ul>\n\t\t *  @type array\n\t\t *  @default []\n\t\t */\n\t\t\"aoStateLoad\": [],\n\t\t\n\t\t/**\n\t\t * State that was loaded from the cookie. Useful for back reference\n\t\t *  @type object\n\t\t *  @default null\n\t\t */\n\t\t\"oLoadedState\": null,\n\t\t\n\t\t/**\n\t\t * Source url for AJAX data for the table.\n\t\t * Note that this parameter will be set by the initialisation routine. To\n\t\t * set a default use {@link DataTable.defaults}.\n\t\t *  @type string\n\t\t *  @default null\n\t\t */\n\t\t\"sAjaxSource\": null,\n\t\t\n\t\t/**\n\t\t * Property from a given object from which to read the table data from. This\n\t\t * can be an empty string (when not server-side processing), in which case \n\t\t * it is  assumed an an array is given directly.\n\t\t * Note that this parameter will be set by the initialisation routine. To\n\t\t * set a default use {@link DataTable.defaults}.\n\t\t *  @type string\n\t\t */\n\t\t\"sAjaxDataProp\": null,\n\t\t\n\t\t/**\n\t\t * Note if draw should be blocked while getting data\n\t\t *  @type boolean\n\t\t *  @default true\n\t\t */\n\t\t\"bAjaxDataGet\": true,\n\t\t\n\t\t/**\n\t\t * The last jQuery XHR object that was used for server-side data gathering. \n\t\t * This can be used for working with the XHR information in one of the \n\t\t * callbacks\n\t\t *  @type object\n\t\t *  @default null\n\t\t */\n\t\t\"jqXHR\": null,\n\t\t\n\t\t/**\n\t\t * Function to get the server-side data.\n\t\t * Note that this parameter will be set by the initialisation routine. To\n\t\t * set a default use {@link DataTable.defaults}.\n\t\t *  @type function\n\t\t */\n\t\t\"fnServerData\": null,\n\t\t\n\t\t/**\n\t\t * Functions which are called prior to sending an Ajax request so extra \n\t\t * parameters can easily be sent to the server\n\t\t *  @type array\n\t\t *  @default []\n\t\t */\n\t\t\"aoServerParams\": [],\n\t\t\n\t\t/**\n\t\t * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if \n\t\t * required).\n\t\t * Note that this parameter will be set by the initialisation routine. To\n\t\t * set a default use {@link DataTable.defaults}.\n\t\t *  @type string\n\t\t */\n\t\t\"sServerMethod\": null,\n\t\t\n\t\t/**\n\t\t * Format numbers for display.\n\t\t * Note that this parameter will be set by the initialisation routine. To\n\t\t * set a default use {@link DataTable.defaults}.\n\t\t *  @type function\n\t\t */\n\t\t\"fnFormatNumber\": null,\n\t\t\n\t\t/**\n\t\t * List of options that can be used for the user selectable length menu.\n\t\t * Note that this parameter will be set by the initialisation routine. To\n\t\t * set a default use {@link DataTable.defaults}.\n\t\t *  @type array\n\t\t *  @default []\n\t\t */\n\t\t\"aLengthMenu\": null,\n\t\t\n\t\t/**\n\t\t * Counter for the draws that the table does. Also used as a tracker for\n\t\t * server-side processing\n\t\t *  @type int\n\t\t *  @default 0\n\t\t */\n\t\t\"iDraw\": 0,\n\t\t\n\t\t/**\n\t\t * Indicate if a redraw is being done - useful for Ajax\n\t\t *  @type boolean\n\t\t *  @default false\n\t\t */\n\t\t\"bDrawing\": false,\n\t\t\n\t\t/**\n\t\t * Draw index (iDraw) of the last error when parsing the returned data\n\t\t *  @type int\n\t\t *  @default -1\n\t\t */\n\t\t\"iDrawError\": -1,\n\t\t\n\t\t/**\n\t\t * Paging display length\n\t\t *  @type int\n\t\t *  @default 10\n\t\t */\n\t\t\"_iDisplayLength\": 10,\n\t\n\t\t/**\n\t\t * Paging start point - aiDisplay index\n\t\t *  @type int\n\t\t *  @default 0\n\t\t */\n\t\t\"_iDisplayStart\": 0,\n\t\n\t\t/**\n\t\t * Paging end point - aiDisplay index. Use fnDisplayEnd rather than\n\t\t * this property to get the end point\n\t\t *  @type int\n\t\t *  @default 10\n\t\t *  @private\n\t\t */\n\t\t\"_iDisplayEnd\": 10,\n\t\t\n\t\t/**\n\t\t * Server-side processing - number of records in the result set\n\t\t * (i.e. before filtering), Use fnRecordsTotal rather than\n\t\t * this property to get the value of the number of records, regardless of\n\t\t * the server-side processing setting.\n\t\t *  @type int\n\t\t *  @default 0\n\t\t *  @private\n\t\t */\n\t\t\"_iRecordsTotal\": 0,\n\t\n\t\t/**\n\t\t * Server-side processing - number of records in the current display set\n\t\t * (i.e. after filtering). Use fnRecordsDisplay rather than\n\t\t * this property to get the value of the number of records, regardless of\n\t\t * the server-side processing setting.\n\t\t *  @type boolean\n\t\t *  @default 0\n\t\t *  @private\n\t\t */\n\t\t\"_iRecordsDisplay\": 0,\n\t\t\n\t\t/**\n\t\t * Flag to indicate if jQuery UI marking and classes should be used.\n\t\t * Note that this parameter will be set by the initialisation routine. To\n\t\t * set a default use {@link DataTable.defaults}.\n\t\t *  @type boolean\n\t\t */\n\t\t\"bJUI\": null,\n\t\t\n\t\t/**\n\t\t * The classes to use for the table\n\t\t *  @type object\n\t\t *  @default {}\n\t\t */\n\t\t\"oClasses\": {},\n\t\t\n\t\t/**\n\t\t * Flag attached to the settings object so you can check in the draw \n\t\t * callback if filtering has been done in the draw. Deprecated in favour of\n\t\t * events.\n\t\t *  @type boolean\n\t\t *  @default false\n\t\t *  @deprecated\n\t\t */\n\t\t\"bFiltered\": false,\n\t\t\n\t\t/**\n\t\t * Flag attached to the settings object so you can check in the draw \n\t\t * callback if sorting has been done in the draw. Deprecated in favour of\n\t\t * events.\n\t\t *  @type boolean\n\t\t *  @default false\n\t\t *  @deprecated\n\t\t */\n\t\t\"bSorted\": false,\n\t\t\n\t\t/**\n\t\t * Indicate that if multiple rows are in the header and there is more than \n\t\t * one unique cell per column, if the top one (true) or bottom one (false) \n\t\t * should be used for sorting / title by DataTables.\n\t\t * Note that this parameter will be set by the initialisation routine. To\n\t\t * set a default use {@link DataTable.defaults}.\n\t\t *  @type boolean\n\t\t */\n\t\t\"bSortCellsTop\": null,\n\t\t\n\t\t/**\n\t\t * Initialisation object that is used for the table\n\t\t *  @type object\n\t\t *  @default null\n\t\t */\n\t\t\"oInit\": null,\n\t\t\n\t\t/**\n\t\t * Destroy callback functions - for plug-ins to attach themselves to the\n\t\t * destroy so they can clean up markup and events.\n\t\t *  @type array\n\t\t *  @default []\n\t\t */\n\t\t\"aoDestroyCallback\": [],\n\t\n\t\t\n\t\t/**\n\t\t * Get the number of records in the current record set, before filtering\n\t\t *  @type function\n\t\t */\n\t\t\"fnRecordsTotal\": function ()\n\t\t{\n\t\t\tif ( this.oFeatures.bServerSide ) {\n\t\t\t\treturn parseInt(this._iRecordsTotal, 10);\n\t\t\t} else {\n\t\t\t\treturn this.aiDisplayMaster.length;\n\t\t\t}\n\t\t},\n\t\t\n\t\t/**\n\t\t * Get the number of records in the current record set, after filtering\n\t\t *  @type function\n\t\t */\n\t\t\"fnRecordsDisplay\": function ()\n\t\t{\n\t\t\tif ( this.oFeatures.bServerSide ) {\n\t\t\t\treturn parseInt(this._iRecordsDisplay, 10);\n\t\t\t} else {\n\t\t\t\treturn this.aiDisplay.length;\n\t\t\t}\n\t\t},\n\t\t\n\t\t/**\n\t\t * Set the display end point - aiDisplay index\n\t\t *  @type function\n\t\t *  @todo Should do away with _iDisplayEnd and calculate it on-the-fly here\n\t\t */\n\t\t\"fnDisplayEnd\": function ()\n\t\t{\n\t\t\tif ( this.oFeatures.bServerSide ) {\n\t\t\t\tif ( this.oFeatures.bPaginate === false || this._iDisplayLength == -1 ) {\n\t\t\t\t\treturn this._iDisplayStart+this.aiDisplay.length;\n\t\t\t\t} else {\n\t\t\t\t\treturn Math.min( this._iDisplayStart+this._iDisplayLength, \n\t\t\t\t\t\tthis._iRecordsDisplay );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn this._iDisplayEnd;\n\t\t\t}\n\t\t},\n\t\t\n\t\t/**\n\t\t * The DataTables object for this table\n\t\t *  @type object\n\t\t *  @default null\n\t\t */\n\t\t\"oInstance\": null,\n\t\t\n\t\t/**\n\t\t * Unique identifier for each instance of the DataTables object. If there\n\t\t * is an ID on the table node, then it takes that value, otherwise an\n\t\t * incrementing internal counter is used.\n\t\t *  @type string\n\t\t *  @default null\n\t\t */\n\t\t\"sInstance\": null,\n\t\n\t\t/**\n\t\t * tabindex attribute value that is added to DataTables control elements, allowing\n\t\t * keyboard navigation of the table and its controls.\n\t\t */\n\t\t\"iTabIndex\": 0,\n\t\n\t\t/**\n\t\t * DIV container for the footer scrolling table if scrolling\n\t\t */\n\t\t\"nScrollHead\": null,\n\t\n\t\t/**\n\t\t * DIV container for the footer scrolling table if scrolling\n\t\t */\n\t\t\"nScrollFoot\": null\n\t};\n\n\t/**\n\t * Extension object for DataTables that is used to provide all extension options.\n\t * \n\t * Note that the <i>DataTable.ext</i> object is available through\n\t * <i>jQuery.fn.dataTable.ext</i> where it may be accessed and manipulated. It is\n\t * also aliased to <i>jQuery.fn.dataTableExt</i> for historic reasons.\n\t *  @namespace\n\t *  @extends DataTable.models.ext\n\t */\n\tDataTable.ext = $.extend( true, {}, DataTable.models.ext );\n\t\n\t$.extend( DataTable.ext.oStdClasses, {\n\t\t\"sTable\": \"dataTable\",\n\t\n\t\t/* Two buttons buttons */\n\t\t\"sPagePrevEnabled\": \"paginate_enabled_previous\",\n\t\t\"sPagePrevDisabled\": \"paginate_disabled_previous\",\n\t\t\"sPageNextEnabled\": \"paginate_enabled_next\",\n\t\t\"sPageNextDisabled\": \"paginate_disabled_next\",\n\t\t\"sPageJUINext\": \"\",\n\t\t\"sPageJUIPrev\": \"\",\n\t\t\n\t\t/* Full numbers paging buttons */\n\t\t\"sPageButton\": \"paginate_button\",\n\t\t\"sPageButtonActive\": \"paginate_active\",\n\t\t\"sPageButtonStaticDisabled\": \"paginate_button paginate_button_disabled\",\n\t\t\"sPageFirst\": \"first\",\n\t\t\"sPagePrevious\": \"previous\",\n\t\t\"sPageNext\": \"next\",\n\t\t\"sPageLast\": \"last\",\n\t\t\n\t\t/* Striping classes */\n\t\t\"sStripeOdd\": \"odd\",\n\t\t\"sStripeEven\": \"even\",\n\t\t\n\t\t/* Empty row */\n\t\t\"sRowEmpty\": \"dataTables_empty\",\n\t\t\n\t\t/* Features */\n\t\t\"sWrapper\": \"dataTables_wrapper\",\n\t\t\"sFilter\": \"dataTables_filter\",\n\t\t\"sInfo\": \"dataTables_info\",\n\t\t\"sPaging\": \"dataTables_paginate paging_\", /* Note that the type is postfixed */\n\t\t\"sLength\": \"dataTables_length\",\n\t\t\"sProcessing\": \"dataTables_processing\",\n\t\t\n\t\t/* Sorting */\n\t\t\"sSortAsc\": \"sorting_asc\",\n\t\t\"sSortDesc\": \"sorting_desc\",\n\t\t\"sSortable\": \"sorting\", /* Sortable in both directions */\n\t\t\"sSortableAsc\": \"sorting_asc_disabled\",\n\t\t\"sSortableDesc\": \"sorting_desc_disabled\",\n\t\t\"sSortableNone\": \"sorting_disabled\",\n\t\t\"sSortColumn\": \"sorting_\", /* Note that an int is postfixed for the sorting order */\n\t\t\"sSortJUIAsc\": \"\",\n\t\t\"sSortJUIDesc\": \"\",\n\t\t\"sSortJUI\": \"\",\n\t\t\"sSortJUIAscAllowed\": \"\",\n\t\t\"sSortJUIDescAllowed\": \"\",\n\t\t\"sSortJUIWrapper\": \"\",\n\t\t\"sSortIcon\": \"\",\n\t\t\n\t\t/* Scrolling */\n\t\t\"sScrollWrapper\": \"dataTables_scroll\",\n\t\t\"sScrollHead\": \"dataTables_scrollHead\",\n\t\t\"sScrollHeadInner\": \"dataTables_scrollHeadInner\",\n\t\t\"sScrollBody\": \"dataTables_scrollBody\",\n\t\t\"sScrollFoot\": \"dataTables_scrollFoot\",\n\t\t\"sScrollFootInner\": \"dataTables_scrollFootInner\",\n\t\t\n\t\t/* Misc */\n\t\t\"sFooterTH\": \"\",\n\t\t\"sJUIHeader\": \"\",\n\t\t\"sJUIFooter\": \"\"\n\t} );\n\t\n\t\n\t$.extend( DataTable.ext.oJUIClasses, DataTable.ext.oStdClasses, {\n\t\t/* Two buttons buttons */\n\t\t\"sPagePrevEnabled\": \"fg-button ui-button ui-state-default ui-corner-left\",\n\t\t\"sPagePrevDisabled\": \"fg-button ui-button ui-state-default ui-corner-left ui-state-disabled\",\n\t\t\"sPageNextEnabled\": \"fg-button ui-button ui-state-default ui-corner-right\",\n\t\t\"sPageNextDisabled\": \"fg-button ui-button ui-state-default ui-corner-right ui-state-disabled\",\n\t\t\"sPageJUINext\": \"ui-icon ui-icon-circle-arrow-e\",\n\t\t\"sPageJUIPrev\": \"ui-icon ui-icon-circle-arrow-w\",\n\t\t\n\t\t/* Full numbers paging buttons */\n\t\t\"sPageButton\": \"fg-button ui-button ui-state-default\",\n\t\t\"sPageButtonActive\": \"fg-button ui-button ui-state-default ui-state-disabled\",\n\t\t\"sPageButtonStaticDisabled\": \"fg-button ui-button ui-state-default ui-state-disabled\",\n\t\t\"sPageFirst\": \"first ui-corner-tl ui-corner-bl\",\n\t\t\"sPageLast\": \"last ui-corner-tr ui-corner-br\",\n\t\t\n\t\t/* Features */\n\t\t\"sPaging\": \"dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi \"+\n\t\t\t\"ui-buttonset-multi paging_\", /* Note that the type is postfixed */\n\t\t\n\t\t/* Sorting */\n\t\t\"sSortAsc\": \"ui-state-default\",\n\t\t\"sSortDesc\": \"ui-state-default\",\n\t\t\"sSortable\": \"ui-state-default\",\n\t\t\"sSortableAsc\": \"ui-state-default\",\n\t\t\"sSortableDesc\": \"ui-state-default\",\n\t\t\"sSortableNone\": \"ui-state-default\",\n\t\t\"sSortJUIAsc\": \"css_right ui-icon ui-icon-triangle-1-n\",\n\t\t\"sSortJUIDesc\": \"css_right ui-icon ui-icon-triangle-1-s\",\n\t\t\"sSortJUI\": \"css_right ui-icon ui-icon-carat-2-n-s\",\n\t\t\"sSortJUIAscAllowed\": \"css_right ui-icon ui-icon-carat-1-n\",\n\t\t\"sSortJUIDescAllowed\": \"css_right ui-icon ui-icon-carat-1-s\",\n\t\t\"sSortJUIWrapper\": \"DataTables_sort_wrapper\",\n\t\t\"sSortIcon\": \"DataTables_sort_icon\",\n\t\t\n\t\t/* Scrolling */\n\t\t\"sScrollHead\": \"dataTables_scrollHead ui-state-default\",\n\t\t\"sScrollFoot\": \"dataTables_scrollFoot ui-state-default\",\n\t\t\n\t\t/* Misc */\n\t\t\"sFooterTH\": \"ui-state-default\",\n\t\t\"sJUIHeader\": \"fg-toolbar ui-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix\",\n\t\t\"sJUIFooter\": \"fg-toolbar ui-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix\"\n\t} );\n\t\n\t/*\n\t * Variable: oPagination\n\t * Purpose:  \n\t * Scope:    jQuery.fn.dataTableExt\n\t */\n\t$.extend( DataTable.ext.oPagination, {\n\t\t/*\n\t\t * Variable: two_button\n\t\t * Purpose:  Standard two button (forward/back) pagination\n\t\t * Scope:    jQuery.fn.dataTableExt.oPagination\n\t\t */\n\t\t\"two_button\": {\n\t\t\t/*\n\t\t\t * Function: oPagination.two_button.fnInit\n\t\t\t * Purpose:  Initialise dom elements required for pagination with forward/back buttons only\n\t\t\t * Returns:  -\n\t\t\t * Inputs:   object:oSettings - dataTables settings object\n\t\t\t *           node:nPaging - the DIV which contains this pagination control\n\t\t\t *           function:fnCallbackDraw - draw function which must be called on update\n\t\t\t */\n\t\t\t\"fnInit\": function ( oSettings, nPaging, fnCallbackDraw )\n\t\t\t{\n\t\t\t\tvar oLang = oSettings.oLanguage.oPaginate;\n\t\t\t\tvar oClasses = oSettings.oClasses;\n\t\t\t\tvar fnClickHandler = function ( e ) {\n\t\t\t\t\tif ( oSettings.oApi._fnPageChange( oSettings, e.data.action ) )\n\t\t\t\t\t{\n\t\t\t\t\t\tfnCallbackDraw( oSettings );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\n\t\t\t\tvar sAppend = (!oSettings.bJUI) ?\n\t\t\t\t\t'<a class=\"'+oSettings.oClasses.sPagePrevDisabled+'\" tabindex=\"'+oSettings.iTabIndex+'\" role=\"button\">'+oLang.sPrevious+'</a>'+\n\t\t\t\t\t'<a class=\"'+oSettings.oClasses.sPageNextDisabled+'\" tabindex=\"'+oSettings.iTabIndex+'\" role=\"button\">'+oLang.sNext+'</a>'\n\t\t\t\t\t:\n\t\t\t\t\t'<a class=\"'+oSettings.oClasses.sPagePrevDisabled+'\" tabindex=\"'+oSettings.iTabIndex+'\" role=\"button\"><span class=\"'+oSettings.oClasses.sPageJUIPrev+'\"></span></a>'+\n\t\t\t\t\t'<a class=\"'+oSettings.oClasses.sPageNextDisabled+'\" tabindex=\"'+oSettings.iTabIndex+'\" role=\"button\"><span class=\"'+oSettings.oClasses.sPageJUINext+'\"></span></a>';\n\t\t\t\t$(nPaging).append( sAppend );\n\t\t\t\t\n\t\t\t\tvar els = $('a', nPaging);\n\t\t\t\tvar nPrevious = els[0],\n\t\t\t\t\tnNext = els[1];\n\t\t\t\t\n\t\t\t\toSettings.oApi._fnBindAction( nPrevious, {action: \"previous\"}, fnClickHandler );\n\t\t\t\toSettings.oApi._fnBindAction( nNext,     {action: \"next\"},     fnClickHandler );\n\t\t\t\t\n\t\t\t\t/* ID the first elements only */\n\t\t\t\tif ( !oSettings.aanFeatures.p )\n\t\t\t\t{\n\t\t\t\t\tnPaging.id = oSettings.sTableId+'_paginate';\n\t\t\t\t\tnPrevious.id = oSettings.sTableId+'_previous';\n\t\t\t\t\tnNext.id = oSettings.sTableId+'_next';\n\t\n\t\t\t\t\tnPrevious.setAttribute('aria-controls', oSettings.sTableId);\n\t\t\t\t\tnNext.setAttribute('aria-controls', oSettings.sTableId);\n\t\t\t\t}\n\t\t\t},\n\t\t\t\n\t\t\t/*\n\t\t\t * Function: oPagination.two_button.fnUpdate\n\t\t\t * Purpose:  Update the two button pagination at the end of the draw\n\t\t\t * Returns:  -\n\t\t\t * Inputs:   object:oSettings - dataTables settings object\n\t\t\t *           function:fnCallbackDraw - draw function to call on page change\n\t\t\t */\n\t\t\t\"fnUpdate\": function ( oSettings, fnCallbackDraw )\n\t\t\t{\n\t\t\t\tif ( !oSettings.aanFeatures.p )\n\t\t\t\t{\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tvar oClasses = oSettings.oClasses;\n\t\t\t\tvar an = oSettings.aanFeatures.p;\n\t\t\t\tvar nNode;\n\t\n\t\t\t\t/* Loop over each instance of the pager */\n\t\t\t\tfor ( var i=0, iLen=an.length ; i<iLen ; i++ )\n\t\t\t\t{\n\t\t\t\t\tnNode = an[i].firstChild;\n\t\t\t\t\tif ( nNode )\n\t\t\t\t\t{\n\t\t\t\t\t\t/* Previous page */\n\t\t\t\t\t\tnNode.className = ( oSettings._iDisplayStart === 0 ) ?\n\t\t\t\t\t\t    oClasses.sPagePrevDisabled : oClasses.sPagePrevEnabled;\n\t\t\t\t\t\t    \n\t\t\t\t\t\t/* Next page */\n\t\t\t\t\t\tnNode = nNode.nextSibling;\n\t\t\t\t\t\tnNode.className = ( oSettings.fnDisplayEnd() == oSettings.fnRecordsDisplay() ) ?\n\t\t\t\t\t\t    oClasses.sPageNextDisabled : oClasses.sPageNextEnabled;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t\n\t\t\n\t\t/*\n\t\t * Variable: iFullNumbersShowPages\n\t\t * Purpose:  Change the number of pages which can be seen\n\t\t * Scope:    jQuery.fn.dataTableExt.oPagination\n\t\t */\n\t\t\"iFullNumbersShowPages\": 5,\n\t\t\n\t\t/*\n\t\t * Variable: full_numbers\n\t\t * Purpose:  Full numbers pagination\n\t\t * Scope:    jQuery.fn.dataTableExt.oPagination\n\t\t */\n\t\t\"full_numbers\": {\n\t\t\t/*\n\t\t\t * Function: oPagination.full_numbers.fnInit\n\t\t\t * Purpose:  Initialise dom elements required for pagination with a list of the pages\n\t\t\t * Returns:  -\n\t\t\t * Inputs:   object:oSettings - dataTables settings object\n\t\t\t *           node:nPaging - the DIV which contains this pagination control\n\t\t\t *           function:fnCallbackDraw - draw function which must be called on update\n\t\t\t */\n\t\t\t\"fnInit\": function ( oSettings, nPaging, fnCallbackDraw )\n\t\t\t{\n\t\t\t\tvar oLang = oSettings.oLanguage.oPaginate;\n\t\t\t\tvar oClasses = oSettings.oClasses;\n\t\t\t\tvar fnClickHandler = function ( e ) {\n\t\t\t\t\tif ( oSettings.oApi._fnPageChange( oSettings, e.data.action ) )\n\t\t\t\t\t{\n\t\t\t\t\t\tfnCallbackDraw( oSettings );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\n\t\t\t\t$(nPaging).append(\n\t\t\t\t\t'<a  tabindex=\"'+oSettings.iTabIndex+'\" class=\"'+oClasses.sPageButton+\" \"+oClasses.sPageFirst+'\">'+oLang.sFirst+'</a>'+\n\t\t\t\t\t'<a  tabindex=\"'+oSettings.iTabIndex+'\" class=\"'+oClasses.sPageButton+\" \"+oClasses.sPagePrevious+'\">'+oLang.sPrevious+'</a>'+\n\t\t\t\t\t'<span></span>'+\n\t\t\t\t\t'<a tabindex=\"'+oSettings.iTabIndex+'\" class=\"'+oClasses.sPageButton+\" \"+oClasses.sPageNext+'\">'+oLang.sNext+'</a>'+\n\t\t\t\t\t'<a tabindex=\"'+oSettings.iTabIndex+'\" class=\"'+oClasses.sPageButton+\" \"+oClasses.sPageLast+'\">'+oLang.sLast+'</a>'\n\t\t\t\t);\n\t\t\t\tvar els = $('a', nPaging);\n\t\t\t\tvar nFirst = els[0],\n\t\t\t\t\tnPrev = els[1],\n\t\t\t\t\tnNext = els[2],\n\t\t\t\t\tnLast = els[3];\n\t\t\t\t\n\t\t\t\toSettings.oApi._fnBindAction( nFirst, {action: \"first\"},    fnClickHandler );\n\t\t\t\toSettings.oApi._fnBindAction( nPrev,  {action: \"previous\"}, fnClickHandler );\n\t\t\t\toSettings.oApi._fnBindAction( nNext,  {action: \"next\"},     fnClickHandler );\n\t\t\t\toSettings.oApi._fnBindAction( nLast,  {action: \"last\"},     fnClickHandler );\n\t\t\t\t\n\t\t\t\t/* ID the first elements only */\n\t\t\t\tif ( !oSettings.aanFeatures.p )\n\t\t\t\t{\n\t\t\t\t\tnPaging.id = oSettings.sTableId+'_paginate';\n\t\t\t\t\tnFirst.id =oSettings.sTableId+'_first';\n\t\t\t\t\tnPrev.id =oSettings.sTableId+'_previous';\n\t\t\t\t\tnNext.id =oSettings.sTableId+'_next';\n\t\t\t\t\tnLast.id =oSettings.sTableId+'_last';\n\t\t\t\t}\n\t\t\t},\n\t\t\t\n\t\t\t/*\n\t\t\t * Function: oPagination.full_numbers.fnUpdate\n\t\t\t * Purpose:  Update the list of page buttons shows\n\t\t\t * Returns:  -\n\t\t\t * Inputs:   object:oSettings - dataTables settings object\n\t\t\t *           function:fnCallbackDraw - draw function to call on page change\n\t\t\t */\n\t\t\t\"fnUpdate\": function ( oSettings, fnCallbackDraw )\n\t\t\t{\n\t\t\t\tif ( !oSettings.aanFeatures.p )\n\t\t\t\t{\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tvar iPageCount = DataTable.ext.oPagination.iFullNumbersShowPages;\n\t\t\t\tvar iPageCountHalf = Math.floor(iPageCount / 2);\n\t\t\t\tvar iPages = Math.ceil((oSettings.fnRecordsDisplay()) / oSettings._iDisplayLength);\n\t\t\t\tvar iCurrentPage = Math.ceil(oSettings._iDisplayStart / oSettings._iDisplayLength) + 1;\n\t\t\t\tvar sList = \"\";\n\t\t\t\tvar iStartButton, iEndButton, i, iLen;\n\t\t\t\tvar oClasses = oSettings.oClasses;\n\t\t\t\tvar anButtons, anStatic, nPaginateList, nNode;\n\t\t\t\tvar an = oSettings.aanFeatures.p;\n\t\t\t\tvar fnBind = function (j) {\n\t\t\t\t\toSettings.oApi._fnBindAction( this, {\"page\": j+iStartButton-1}, function(e) {\n\t\t\t\t\t\t/* Use the information in the element to jump to the required page */\n\t\t\t\t\t\toSettings.oApi._fnPageChange( oSettings, e.data.page );\n\t\t\t\t\t\tfnCallbackDraw( oSettings );\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t} );\n\t\t\t\t};\n\t\t\t\t\n\t\t\t\t/* Pages calculation */\n\t\t\t\tif ( oSettings._iDisplayLength === -1 )\n\t\t\t\t{\n\t\t\t\t\tiStartButton = 1;\n\t\t\t\t\tiEndButton = 1;\n\t\t\t\t\tiCurrentPage = 1;\n\t\t\t\t}\n\t\t\t\telse if (iPages < iPageCount)\n\t\t\t\t{\n\t\t\t\t\tiStartButton = 1;\n\t\t\t\t\tiEndButton = iPages;\n\t\t\t\t}\n\t\t\t\telse if (iCurrentPage <= iPageCountHalf)\n\t\t\t\t{\n\t\t\t\t\tiStartButton = 1;\n\t\t\t\t\tiEndButton = iPageCount;\n\t\t\t\t}\n\t\t\t\telse if (iCurrentPage >= (iPages - iPageCountHalf))\n\t\t\t\t{\n\t\t\t\t\tiStartButton = iPages - iPageCount + 1;\n\t\t\t\t\tiEndButton = iPages;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tiStartButton = iCurrentPage - Math.ceil(iPageCount / 2) + 1;\n\t\t\t\t\tiEndButton = iStartButton + iPageCount - 1;\n\t\t\t\t}\n\t\n\t\t\t\t\n\t\t\t\t/* Build the dynamic list */\n\t\t\t\tfor ( i=iStartButton ; i<=iEndButton ; i++ )\n\t\t\t\t{\n\t\t\t\t\tsList += (iCurrentPage !== i) ?\n\t\t\t\t\t\t'<a tabindex=\"'+oSettings.iTabIndex+'\" class=\"'+oClasses.sPageButton+'\">'+oSettings.fnFormatNumber(i)+'</a>' :\n\t\t\t\t\t\t'<a tabindex=\"'+oSettings.iTabIndex+'\" class=\"'+oClasses.sPageButtonActive+'\">'+oSettings.fnFormatNumber(i)+'</a>';\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t/* Loop over each instance of the pager */\n\t\t\t\tfor ( i=0, iLen=an.length ; i<iLen ; i++ )\n\t\t\t\t{\n\t\t\t\t\tnNode = an[i];\n\t\t\t\t\tif ( !nNode.hasChildNodes() )\n\t\t\t\t\t{\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t/* Build up the dynamic list first - html and listeners */\n\t\t\t\t\t$('span:eq(0)', nNode)\n\t\t\t\t\t\t.html( sList )\n\t\t\t\t\t\t.children('a').each( fnBind );\n\t\t\t\t\t\n\t\t\t\t\t/* Update the permanent button's classes */\n\t\t\t\t\tanButtons = nNode.getElementsByTagName('a');\n\t\t\t\t\tanStatic = [\n\t\t\t\t\t\tanButtons[0], anButtons[1], \n\t\t\t\t\t\tanButtons[anButtons.length-2], anButtons[anButtons.length-1]\n\t\t\t\t\t];\n\t\n\t\t\t\t\t$(anStatic).removeClass( oClasses.sPageButton+\" \"+oClasses.sPageButtonActive+\" \"+oClasses.sPageButtonStaticDisabled );\n\t\t\t\t\t$([anStatic[0], anStatic[1]]).addClass( \n\t\t\t\t\t\t(iCurrentPage==1) ?\n\t\t\t\t\t\t\toClasses.sPageButtonStaticDisabled :\n\t\t\t\t\t\t\toClasses.sPageButton\n\t\t\t\t\t);\n\t\t\t\t\t$([anStatic[2], anStatic[3]]).addClass(\n\t\t\t\t\t\t(iPages===0 || iCurrentPage===iPages || oSettings._iDisplayLength===-1) ?\n\t\t\t\t\t\t\toClasses.sPageButtonStaticDisabled :\n\t\t\t\t\t\t\toClasses.sPageButton\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} );\n\t\n\t$.extend( DataTable.ext.oSort, {\n\t\t/*\n\t\t * text sorting\n\t\t */\n\t\t\"string-pre\": function ( a )\n\t\t{\n\t\t\tif ( typeof a != 'string' ) {\n\t\t\t\ta = (a !== null && a.toString) ? a.toString() : '';\n\t\t\t}\n\t\t\treturn a.toLowerCase();\n\t\t},\n\t\n\t\t\"string-asc\": function ( x, y )\n\t\t{\n\t\t\treturn ((x < y) ? -1 : ((x > y) ? 1 : 0));\n\t\t},\n\t\t\n\t\t\"string-desc\": function ( x, y )\n\t\t{\n\t\t\treturn ((x < y) ? 1 : ((x > y) ? -1 : 0));\n\t\t},\n\t\t\n\t\t\n\t\t/*\n\t\t * html sorting (ignore html tags)\n\t\t */\n\t\t\"html-pre\": function ( a )\n\t\t{\n\t\t\treturn a.replace( /<.*?>/g, \"\" ).toLowerCase();\n\t\t},\n\t\t\n\t\t\"html-asc\": function ( x, y )\n\t\t{\n\t\t\treturn ((x < y) ? -1 : ((x > y) ? 1 : 0));\n\t\t},\n\t\t\n\t\t\"html-desc\": function ( x, y )\n\t\t{\n\t\t\treturn ((x < y) ? 1 : ((x > y) ? -1 : 0));\n\t\t},\n\t\t\n\t\t\n\t\t/*\n\t\t * date sorting\n\t\t */\n\t\t\"date-pre\": function ( a )\n\t\t{\n\t\t\tvar x = Date.parse( a );\n\t\t\t\n\t\t\tif ( isNaN(x) || x===\"\" )\n\t\t\t{\n\t\t\t\tx = Date.parse( \"01/01/1970 00:00:00\" );\n\t\t\t}\n\t\t\treturn x;\n\t\t},\n\t\n\t\t\"date-asc\": function ( x, y )\n\t\t{\n\t\t\treturn x - y;\n\t\t},\n\t\t\n\t\t\"date-desc\": function ( x, y )\n\t\t{\n\t\t\treturn y - x;\n\t\t},\n\t\t\n\t\t\n\t\t/*\n\t\t * numerical sorting\n\t\t */\n\t\t\"numeric-pre\": function ( a )\n\t\t{\n\t\t\treturn (a==\"-\" || a===\"\") ? 0 : a*1;\n\t\t},\n\t\n\t\t\"numeric-asc\": function ( x, y )\n\t\t{\n\t\t\treturn x - y;\n\t\t},\n\t\t\n\t\t\"numeric-desc\": function ( x, y )\n\t\t{\n\t\t\treturn y - x;\n\t\t}\n\t} );\n\t\n\t\n\t$.extend( DataTable.ext.aTypes, [\n\t\t/*\n\t\t * Function: -\n\t\t * Purpose:  Check to see if a string is numeric\n\t\t * Returns:  string:'numeric' or null\n\t\t * Inputs:   mixed:sText - string to check\n\t\t */\n\t\tfunction ( sData )\n\t\t{\n\t\t\t/* Allow zero length strings as a number */\n\t\t\tif ( typeof sData === 'number' )\n\t\t\t{\n\t\t\t\treturn 'numeric';\n\t\t\t}\n\t\t\telse if ( typeof sData !== 'string' )\n\t\t\t{\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\t\n\t\t\tvar sValidFirstChars = \"0123456789-\";\n\t\t\tvar sValidChars = \"0123456789.\";\n\t\t\tvar Char;\n\t\t\tvar bDecimal = false;\n\t\t\t\n\t\t\t/* Check for a valid first char (no period and allow negatives) */\n\t\t\tChar = sData.charAt(0); \n\t\t\tif (sValidFirstChars.indexOf(Char) == -1) \n\t\t\t{\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\t\n\t\t\t/* Check all the other characters are valid */\n\t\t\tfor ( var i=1 ; i<sData.length ; i++ ) \n\t\t\t{\n\t\t\t\tChar = sData.charAt(i); \n\t\t\t\tif (sValidChars.indexOf(Char) == -1) \n\t\t\t\t{\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t/* Only allowed one decimal place... */\n\t\t\t\tif ( Char == \".\" )\n\t\t\t\t{\n\t\t\t\t\tif ( bDecimal )\n\t\t\t\t\t{\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t\tbDecimal = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\treturn 'numeric';\n\t\t},\n\t\t\n\t\t/*\n\t\t * Function: -\n\t\t * Purpose:  Check to see if a string is actually a formatted date\n\t\t * Returns:  string:'date' or null\n\t\t * Inputs:   string:sText - string to check\n\t\t */\n\t\tfunction ( sData )\n\t\t{\n\t\t\tvar iParse = Date.parse(sData);\n\t\t\tif ( (iParse !== null && !isNaN(iParse)) || (typeof sData === 'string' && sData.length === 0) )\n\t\t\t{\n\t\t\t\treturn 'date';\n\t\t\t}\n\t\t\treturn null;\n\t\t},\n\t\t\n\t\t/*\n\t\t * Function: -\n\t\t * Purpose:  Check to see if a string should be treated as an HTML string\n\t\t * Returns:  string:'html' or null\n\t\t * Inputs:   string:sText - string to check\n\t\t */\n\t\tfunction ( sData )\n\t\t{\n\t\t\tif ( typeof sData === 'string' && sData.indexOf('<') != -1 && sData.indexOf('>') != -1 )\n\t\t\t{\n\t\t\t\treturn 'html';\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t] );\n\t\n\n\t// jQuery aliases\n\t$.fn.DataTable = DataTable;\n\t$.fn.dataTable = DataTable;\n\t$.fn.dataTableSettings = DataTable.settings;\n\t$.fn.dataTableExt = DataTable.ext;\n\n\n\t// Information about events fired by DataTables - for documentation.\n\t/**\n\t * Draw event, fired whenever the table is redrawn on the page, at the same point as\n\t * fnDrawCallback. This may be useful for binding events or performing calculations when\n\t * the table is altered at all.\n\t *  @name DataTable#draw\n\t *  @event\n\t *  @param {event} e jQuery event object\n\t *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}\n\t */\n\n\t/**\n\t * Filter event, fired when the filtering applied to the table (using the build in global\n\t * global filter, or column filters) is altered.\n\t *  @name DataTable#filter\n\t *  @event\n\t *  @param {event} e jQuery event object\n\t *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}\n\t */\n\n\t/**\n\t * Page change event, fired when the paging of the table is altered.\n\t *  @name DataTable#page\n\t *  @event\n\t *  @param {event} e jQuery event object\n\t *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}\n\t */\n\n\t/**\n\t * Sort event, fired when the sorting applied to the table is altered.\n\t *  @name DataTable#sort\n\t *  @event\n\t *  @param {event} e jQuery event object\n\t *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}\n\t */\n\n\t/**\n\t * DataTables initialisation complete event, fired when the table is fully drawn,\n\t * including Ajax data loaded, if Ajax data is required.\n\t *  @name DataTable#init\n\t *  @event\n\t *  @param {event} e jQuery event object\n\t *  @param {object} oSettings DataTables settings object\n\t *  @param {object} json The JSON object request from the server - only\n\t *    present if client-side Ajax sourced data is used</li></ol>\n\t */\n\n\t/**\n\t * State save event, fired when the table has changed state a new state save is required.\n\t * This method allows modification of the state saving object prior to actually doing the\n\t * save, including addition or other state properties (for plug-ins) or modification\n\t * of a DataTables core property.\n\t *  @name DataTable#stateSaveParams\n\t *  @event\n\t *  @param {event} e jQuery event object\n\t *  @param {object} oSettings DataTables settings object\n\t *  @param {object} json The state information to be saved\n\t */\n\n\t/**\n\t * State load event, fired when the table is loading state from the stored data, but\n\t * prior to the settings object being modified by the saved state - allowing modification\n\t * of the saved state is required or loading of state for a plug-in.\n\t *  @name DataTable#stateLoadParams\n\t *  @event\n\t *  @param {event} e jQuery event object\n\t *  @param {object} oSettings DataTables settings object\n\t *  @param {object} json The saved state information\n\t */\n\n\t/**\n\t * State loaded event, fired when state has been loaded from stored data and the settings\n\t * object has been modified by the loaded data.\n\t *  @name DataTable#stateLoaded\n\t *  @event\n\t *  @param {event} e jQuery event object\n\t *  @param {object} oSettings DataTables settings object\n\t *  @param {object} json The saved state information\n\t */\n\n\t/**\n\t * Processing event, fired when DataTables is doing some kind of processing (be it,\n\t * sort, filter or anything else). Can be used to indicate to the end user that\n\t * there is something happening, or that something has finished.\n\t *  @name DataTable#processing\n\t *  @event\n\t *  @param {event} e jQuery event object\n\t *  @param {object} oSettings DataTables settings object\n\t *  @param {boolean} bShow Flag for if DataTables is doing processing or not\n\t */\n\n\t/**\n\t * Ajax (XHR) event, fired whenever an Ajax request is completed from a request to \n\t * made to the server for new data (note that this trigger is called in fnServerData,\n\t * if you override fnServerData and which to use this event, you need to trigger it in\n\t * you success function).\n\t *  @name DataTable#xhr\n\t *  @event\n\t *  @param {event} e jQuery event object\n\t *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}\n\t *  @param {object} json JSON returned from the server\n\t */\n\n\t/**\n\t * Destroy event, fired when the DataTable is destroyed by calling fnDestroy or passing\n\t * the bDestroy:true parameter in the initialisation object. This can be used to remove\n\t * bound events, added DOM nodes, etc.\n\t *  @name DataTable#destroy\n\t *  @event\n\t *  @param {event} e jQuery event object\n\t *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}\n\t */\n}));\n\n}(window, document));\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/plugins/font-awesome/css/font-awesome.css",
    "content": "/*!\n *  Font Awesome 4.0.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('../fonts/fontawesome-webfont.eot?v=4.0.1');\n  src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.0.1') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff?v=4.0.1') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.0.1') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.0.1#fontawesomeregular') format('svg');\n  font-weight: normal;\n  font-style: normal;\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\";\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-move: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-resize-full:before {\n  content: \"\\f065\";\n}\n.fa-resize-small: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-resize-vertical:before {\n  content: \"\\f07d\";\n}\n.fa-resize-horizontal:before {\n  content: \"\\f07e\";\n}\n.fa-bar-chart-o:before {\n  content: \"\\f080\";\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-fullscreen:before {\n  content: \"\\f0b2\";\n}\n.fa-group: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-reorder: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: \"\\f0d6\";\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:before {\n  content: \"\\f0f7\";\n}\n.fa-hospital: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-expand-o:before {\n  content: \"\\f116\";\n}\n.fa-collapse-o:before {\n  content: \"\\f117\";\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-o:before {\n  content: \"\\f13e\";\n}\n.fa-bullseye:before {\n  content: \"\\f140\";\n}\n.fa-ellipsis-horizontal:before {\n  content: \"\\f141\";\n}\n.fa-ellipsis-vertical: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: \"\\f145\";\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"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/plugins/font-awesome/less/bordered-pulled.less",
    "content": "// Bordered & Pulled\n// -------------------------\n\n.@{fa-css-prefix}-border {\n  padding: .2em .25em .15em;\n  border: solid .08em @fa-border-color;\n  border-radius: .1em;\n}\n\n.pull-right { float: right; }\n.pull-left { float: left; }\n\n.@{fa-css-prefix} {\n  &.pull-left { margin-right: .3em; }\n  &.pull-right { margin-left: .3em; }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/plugins/font-awesome/less/core.less",
    "content": "// Base Class Definition\n// -------------------------\n\n.@{fa-css-prefix} {\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"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/plugins/font-awesome/less/fixed-width.less",
    "content": "// Fixed Width Icons\n// -------------------------\n.@{fa-css-prefix}-fw {\n  width: (18em / 14);\n  text-align: center;\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/plugins/font-awesome/less/font-awesome.less",
    "content": "/*!\n *  Font Awesome 4.0.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 \"larger\";\n@import \"fixed-width\";\n@import \"list\";\n@import \"bordered-pulled\";\n@import \"spinning\";\n@import \"rotated-flipped\";\n@import \"stacked\";\n@import \"icons\";\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/plugins/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.@{fa-css-prefix}-glass:before { content: @fa-var-glass; }\n.@{fa-css-prefix}-music:before { content: @fa-var-music; }\n.@{fa-css-prefix}-search:before { content: @fa-var-search; }\n.@{fa-css-prefix}-envelope-o:before { content: @fa-var-envelope-o; }\n.@{fa-css-prefix}-heart:before { content: @fa-var-heart; }\n.@{fa-css-prefix}-star:before { content: @fa-var-star; }\n.@{fa-css-prefix}-star-o:before { content: @fa-var-star-o; }\n.@{fa-css-prefix}-user:before { content: @fa-var-user; }\n.@{fa-css-prefix}-film:before { content: @fa-var-film; }\n.@{fa-css-prefix}-th-large:before { content: @fa-var-th-large; }\n.@{fa-css-prefix}-th:before { content: @fa-var-th; }\n.@{fa-css-prefix}-th-list:before { content: @fa-var-th-list; }\n.@{fa-css-prefix}-check:before { content: @fa-var-check; }\n.@{fa-css-prefix}-times:before { content: @fa-var-times; }\n.@{fa-css-prefix}-search-plus:before { content: @fa-var-search-plus; }\n.@{fa-css-prefix}-search-minus:before { content: @fa-var-search-minus; }\n.@{fa-css-prefix}-power-off:before { content: @fa-var-power-off; }\n.@{fa-css-prefix}-signal:before { content: @fa-var-signal; }\n.@{fa-css-prefix}-gear:before,\n.@{fa-css-prefix}-cog:before { content: @fa-var-cog; }\n.@{fa-css-prefix}-trash-o:before { content: @fa-var-trash-o; }\n.@{fa-css-prefix}-home:before { content: @fa-var-home; }\n.@{fa-css-prefix}-file-o:before { content: @fa-var-file-o; }\n.@{fa-css-prefix}-clock-o:before { content: @fa-var-clock-o; }\n.@{fa-css-prefix}-road:before { content: @fa-var-road; }\n.@{fa-css-prefix}-download:before { content: @fa-var-download; }\n.@{fa-css-prefix}-arrow-circle-o-down:before { content: @fa-var-arrow-circle-o-down; }\n.@{fa-css-prefix}-arrow-circle-o-up:before { content: @fa-var-arrow-circle-o-up; }\n.@{fa-css-prefix}-inbox:before { content: @fa-var-inbox; }\n.@{fa-css-prefix}-play-circle-o:before { content: @fa-var-play-circle-o; }\n.@{fa-css-prefix}-rotate-right:before,\n.@{fa-css-prefix}-repeat:before { content: @fa-var-repeat; }\n.@{fa-css-prefix}-refresh:before { content: @fa-var-refresh; }\n.@{fa-css-prefix}-list-alt:before { content: @fa-var-list-alt; }\n.@{fa-css-prefix}-lock:before { content: @fa-var-lock; }\n.@{fa-css-prefix}-flag:before { content: @fa-var-flag; }\n.@{fa-css-prefix}-headphones:before { content: @fa-var-headphones; }\n.@{fa-css-prefix}-volume-off:before { content: @fa-var-volume-off; }\n.@{fa-css-prefix}-volume-down:before { content: @fa-var-volume-down; }\n.@{fa-css-prefix}-volume-up:before { content: @fa-var-volume-up; }\n.@{fa-css-prefix}-qrcode:before { content: @fa-var-qrcode; }\n.@{fa-css-prefix}-barcode:before { content: @fa-var-barcode; }\n.@{fa-css-prefix}-tag:before { content: @fa-var-tag; }\n.@{fa-css-prefix}-tags:before { content: @fa-var-tags; }\n.@{fa-css-prefix}-book:before { content: @fa-var-book; }\n.@{fa-css-prefix}-bookmark:before { content: @fa-var-bookmark; }\n.@{fa-css-prefix}-print:before { content: @fa-var-print; }\n.@{fa-css-prefix}-camera:before { content: @fa-var-camera; }\n.@{fa-css-prefix}-font:before { content: @fa-var-font; }\n.@{fa-css-prefix}-bold:before { content: @fa-var-bold; }\n.@{fa-css-prefix}-italic:before { content: @fa-var-italic; }\n.@{fa-css-prefix}-text-height:before { content: @fa-var-text-height; }\n.@{fa-css-prefix}-text-width:before { content: @fa-var-text-width; }\n.@{fa-css-prefix}-align-left:before { content: @fa-var-align-left; }\n.@{fa-css-prefix}-align-center:before { content: @fa-var-align-center; }\n.@{fa-css-prefix}-align-right:before { content: @fa-var-align-right; }\n.@{fa-css-prefix}-align-justify:before { content: @fa-var-align-justify; }\n.@{fa-css-prefix}-list:before { content: @fa-var-list; }\n.@{fa-css-prefix}-dedent:before,\n.@{fa-css-prefix}-outdent:before { content: @fa-var-outdent; }\n.@{fa-css-prefix}-indent:before { content: @fa-var-indent; }\n.@{fa-css-prefix}-video-camera:before { content: @fa-var-video-camera; }\n.@{fa-css-prefix}-picture-o:before { content: @fa-var-picture-o; }\n.@{fa-css-prefix}-pencil:before { content: @fa-var-pencil; }\n.@{fa-css-prefix}-map-marker:before { content: @fa-var-map-marker; }\n.@{fa-css-prefix}-adjust:before { content: @fa-var-adjust; }\n.@{fa-css-prefix}-tint:before { content: @fa-var-tint; }\n.@{fa-css-prefix}-edit:before,\n.@{fa-css-prefix}-pencil-square-o:before { content: @fa-var-pencil-square-o; }\n.@{fa-css-prefix}-share-square-o:before { content: @fa-var-share-square-o; }\n.@{fa-css-prefix}-check-square-o:before { content: @fa-var-check-square-o; }\n.@{fa-css-prefix}-move:before { content: @fa-var-move; }\n.@{fa-css-prefix}-step-backward:before { content: @fa-var-step-backward; }\n.@{fa-css-prefix}-fast-backward:before { content: @fa-var-fast-backward; }\n.@{fa-css-prefix}-backward:before { content: @fa-var-backward; }\n.@{fa-css-prefix}-play:before { content: @fa-var-play; }\n.@{fa-css-prefix}-pause:before { content: @fa-var-pause; }\n.@{fa-css-prefix}-stop:before { content: @fa-var-stop; }\n.@{fa-css-prefix}-forward:before { content: @fa-var-forward; }\n.@{fa-css-prefix}-fast-forward:before { content: @fa-var-fast-forward; }\n.@{fa-css-prefix}-step-forward:before { content: @fa-var-step-forward; }\n.@{fa-css-prefix}-eject:before { content: @fa-var-eject; }\n.@{fa-css-prefix}-chevron-left:before { content: @fa-var-chevron-left; }\n.@{fa-css-prefix}-chevron-right:before { content: @fa-var-chevron-right; }\n.@{fa-css-prefix}-plus-circle:before { content: @fa-var-plus-circle; }\n.@{fa-css-prefix}-minus-circle:before { content: @fa-var-minus-circle; }\n.@{fa-css-prefix}-times-circle:before { content: @fa-var-times-circle; }\n.@{fa-css-prefix}-check-circle:before { content: @fa-var-check-circle; }\n.@{fa-css-prefix}-question-circle:before { content: @fa-var-question-circle; }\n.@{fa-css-prefix}-info-circle:before { content: @fa-var-info-circle; }\n.@{fa-css-prefix}-crosshairs:before { content: @fa-var-crosshairs; }\n.@{fa-css-prefix}-times-circle-o:before { content: @fa-var-times-circle-o; }\n.@{fa-css-prefix}-check-circle-o:before { content: @fa-var-check-circle-o; }\n.@{fa-css-prefix}-ban:before { content: @fa-var-ban; }\n.@{fa-css-prefix}-arrow-left:before { content: @fa-var-arrow-left; }\n.@{fa-css-prefix}-arrow-right:before { content: @fa-var-arrow-right; }\n.@{fa-css-prefix}-arrow-up:before { content: @fa-var-arrow-up; }\n.@{fa-css-prefix}-arrow-down:before { content: @fa-var-arrow-down; }\n.@{fa-css-prefix}-mail-forward:before,\n.@{fa-css-prefix}-share:before { content: @fa-var-share; }\n.@{fa-css-prefix}-resize-full:before { content: @fa-var-resize-full; }\n.@{fa-css-prefix}-resize-small:before { content: @fa-var-resize-small; }\n.@{fa-css-prefix}-plus:before { content: @fa-var-plus; }\n.@{fa-css-prefix}-minus:before { content: @fa-var-minus; }\n.@{fa-css-prefix}-asterisk:before { content: @fa-var-asterisk; }\n.@{fa-css-prefix}-exclamation-circle:before { content: @fa-var-exclamation-circle; }\n.@{fa-css-prefix}-gift:before { content: @fa-var-gift; }\n.@{fa-css-prefix}-leaf:before { content: @fa-var-leaf; }\n.@{fa-css-prefix}-fire:before { content: @fa-var-fire; }\n.@{fa-css-prefix}-eye:before { content: @fa-var-eye; }\n.@{fa-css-prefix}-eye-slash:before { content: @fa-var-eye-slash; }\n.@{fa-css-prefix}-warning:before,\n.@{fa-css-prefix}-exclamation-triangle:before { content: @fa-var-exclamation-triangle; }\n.@{fa-css-prefix}-plane:before { content: @fa-var-plane; }\n.@{fa-css-prefix}-calendar:before { content: @fa-var-calendar; }\n.@{fa-css-prefix}-random:before { content: @fa-var-random; }\n.@{fa-css-prefix}-comment:before { content: @fa-var-comment; }\n.@{fa-css-prefix}-magnet:before { content: @fa-var-magnet; }\n.@{fa-css-prefix}-chevron-up:before { content: @fa-var-chevron-up; }\n.@{fa-css-prefix}-chevron-down:before { content: @fa-var-chevron-down; }\n.@{fa-css-prefix}-retweet:before { content: @fa-var-retweet; }\n.@{fa-css-prefix}-shopping-cart:before { content: @fa-var-shopping-cart; }\n.@{fa-css-prefix}-folder:before { content: @fa-var-folder; }\n.@{fa-css-prefix}-folder-open:before { content: @fa-var-folder-open; }\n.@{fa-css-prefix}-resize-vertical:before { content: @fa-var-resize-vertical; }\n.@{fa-css-prefix}-resize-horizontal:before { content: @fa-var-resize-horizontal; }\n.@{fa-css-prefix}-bar-chart-o:before { content: @fa-var-bar-chart-o; }\n.@{fa-css-prefix}-twitter-square:before { content: @fa-var-twitter-square; }\n.@{fa-css-prefix}-facebook-square:before { content: @fa-var-facebook-square; }\n.@{fa-css-prefix}-camera-retro:before { content: @fa-var-camera-retro; }\n.@{fa-css-prefix}-key:before { content: @fa-var-key; }\n.@{fa-css-prefix}-gears:before,\n.@{fa-css-prefix}-cogs:before { content: @fa-var-cogs; }\n.@{fa-css-prefix}-comments:before { content: @fa-var-comments; }\n.@{fa-css-prefix}-thumbs-o-up:before { content: @fa-var-thumbs-o-up; }\n.@{fa-css-prefix}-thumbs-o-down:before { content: @fa-var-thumbs-o-down; }\n.@{fa-css-prefix}-star-half:before { content: @fa-var-star-half; }\n.@{fa-css-prefix}-heart-o:before { content: @fa-var-heart-o; }\n.@{fa-css-prefix}-sign-out:before { content: @fa-var-sign-out; }\n.@{fa-css-prefix}-linkedin-square:before { content: @fa-var-linkedin-square; }\n.@{fa-css-prefix}-thumb-tack:before { content: @fa-var-thumb-tack; }\n.@{fa-css-prefix}-external-link:before { content: @fa-var-external-link; }\n.@{fa-css-prefix}-sign-in:before { content: @fa-var-sign-in; }\n.@{fa-css-prefix}-trophy:before { content: @fa-var-trophy; }\n.@{fa-css-prefix}-github-square:before { content: @fa-var-github-square; }\n.@{fa-css-prefix}-upload:before { content: @fa-var-upload; }\n.@{fa-css-prefix}-lemon-o:before { content: @fa-var-lemon-o; }\n.@{fa-css-prefix}-phone:before { content: @fa-var-phone; }\n.@{fa-css-prefix}-square-o:before { content: @fa-var-square-o; }\n.@{fa-css-prefix}-bookmark-o:before { content: @fa-var-bookmark-o; }\n.@{fa-css-prefix}-phone-square:before { content: @fa-var-phone-square; }\n.@{fa-css-prefix}-twitter:before { content: @fa-var-twitter; }\n.@{fa-css-prefix}-facebook:before { content: @fa-var-facebook; }\n.@{fa-css-prefix}-github:before { content: @fa-var-github; }\n.@{fa-css-prefix}-unlock:before { content: @fa-var-unlock; }\n.@{fa-css-prefix}-credit-card:before { content: @fa-var-credit-card; }\n.@{fa-css-prefix}-rss:before { content: @fa-var-rss; }\n.@{fa-css-prefix}-hdd-o:before { content: @fa-var-hdd-o; }\n.@{fa-css-prefix}-bullhorn:before { content: @fa-var-bullhorn; }\n.@{fa-css-prefix}-bell:before { content: @fa-var-bell; }\n.@{fa-css-prefix}-certificate:before { content: @fa-var-certificate; }\n.@{fa-css-prefix}-hand-o-right:before { content: @fa-var-hand-o-right; }\n.@{fa-css-prefix}-hand-o-left:before { content: @fa-var-hand-o-left; }\n.@{fa-css-prefix}-hand-o-up:before { content: @fa-var-hand-o-up; }\n.@{fa-css-prefix}-hand-o-down:before { content: @fa-var-hand-o-down; }\n.@{fa-css-prefix}-arrow-circle-left:before { content: @fa-var-arrow-circle-left; }\n.@{fa-css-prefix}-arrow-circle-right:before { content: @fa-var-arrow-circle-right; }\n.@{fa-css-prefix}-arrow-circle-up:before { content: @fa-var-arrow-circle-up; }\n.@{fa-css-prefix}-arrow-circle-down:before { content: @fa-var-arrow-circle-down; }\n.@{fa-css-prefix}-globe:before { content: @fa-var-globe; }\n.@{fa-css-prefix}-wrench:before { content: @fa-var-wrench; }\n.@{fa-css-prefix}-tasks:before { content: @fa-var-tasks; }\n.@{fa-css-prefix}-filter:before { content: @fa-var-filter; }\n.@{fa-css-prefix}-briefcase:before { content: @fa-var-briefcase; }\n.@{fa-css-prefix}-fullscreen:before { content: @fa-var-fullscreen; }\n.@{fa-css-prefix}-group:before { content: @fa-var-group; }\n.@{fa-css-prefix}-chain:before,\n.@{fa-css-prefix}-link:before { content: @fa-var-link; }\n.@{fa-css-prefix}-cloud:before { content: @fa-var-cloud; }\n.@{fa-css-prefix}-flask:before { content: @fa-var-flask; }\n.@{fa-css-prefix}-cut:before,\n.@{fa-css-prefix}-scissors:before { content: @fa-var-scissors; }\n.@{fa-css-prefix}-copy:before,\n.@{fa-css-prefix}-files-o:before { content: @fa-var-files-o; }\n.@{fa-css-prefix}-paperclip:before { content: @fa-var-paperclip; }\n.@{fa-css-prefix}-save:before,\n.@{fa-css-prefix}-floppy-o:before { content: @fa-var-floppy-o; }\n.@{fa-css-prefix}-square:before { content: @fa-var-square; }\n.@{fa-css-prefix}-reorder:before { content: @fa-var-reorder; }\n.@{fa-css-prefix}-list-ul:before { content: @fa-var-list-ul; }\n.@{fa-css-prefix}-list-ol:before { content: @fa-var-list-ol; }\n.@{fa-css-prefix}-strikethrough:before { content: @fa-var-strikethrough; }\n.@{fa-css-prefix}-underline:before { content: @fa-var-underline; }\n.@{fa-css-prefix}-table:before { content: @fa-var-table; }\n.@{fa-css-prefix}-magic:before { content: @fa-var-magic; }\n.@{fa-css-prefix}-truck:before { content: @fa-var-truck; }\n.@{fa-css-prefix}-pinterest:before { content: @fa-var-pinterest; }\n.@{fa-css-prefix}-pinterest-square:before { content: @fa-var-pinterest-square; }\n.@{fa-css-prefix}-google-plus-square:before { content: @fa-var-google-plus-square; }\n.@{fa-css-prefix}-google-plus:before { content: @fa-var-google-plus; }\n.@{fa-css-prefix}-money:before { content: @fa-var-money; }\n.@{fa-css-prefix}-caret-down:before { content: @fa-var-caret-down; }\n.@{fa-css-prefix}-caret-up:before { content: @fa-var-caret-up; }\n.@{fa-css-prefix}-caret-left:before { content: @fa-var-caret-left; }\n.@{fa-css-prefix}-caret-right:before { content: @fa-var-caret-right; }\n.@{fa-css-prefix}-columns:before { content: @fa-var-columns; }\n.@{fa-css-prefix}-unsorted:before,\n.@{fa-css-prefix}-sort:before { content: @fa-var-sort; }\n.@{fa-css-prefix}-sort-down:before,\n.@{fa-css-prefix}-sort-asc:before { content: @fa-var-sort-asc; }\n.@{fa-css-prefix}-sort-up:before,\n.@{fa-css-prefix}-sort-desc:before { content: @fa-var-sort-desc; }\n.@{fa-css-prefix}-envelope:before { content: @fa-var-envelope; }\n.@{fa-css-prefix}-linkedin:before { content: @fa-var-linkedin; }\n.@{fa-css-prefix}-rotate-left:before,\n.@{fa-css-prefix}-undo:before { content: @fa-var-undo; }\n.@{fa-css-prefix}-legal:before,\n.@{fa-css-prefix}-gavel:before { content: @fa-var-gavel; }\n.@{fa-css-prefix}-dashboard:before,\n.@{fa-css-prefix}-tachometer:before { content: @fa-var-tachometer; }\n.@{fa-css-prefix}-comment-o:before { content: @fa-var-comment-o; }\n.@{fa-css-prefix}-comments-o:before { content: @fa-var-comments-o; }\n.@{fa-css-prefix}-flash:before,\n.@{fa-css-prefix}-bolt:before { content: @fa-var-bolt; }\n.@{fa-css-prefix}-sitemap:before { content: @fa-var-sitemap; }\n.@{fa-css-prefix}-umbrella:before { content: @fa-var-umbrella; }\n.@{fa-css-prefix}-paste:before,\n.@{fa-css-prefix}-clipboard:before { content: @fa-var-clipboard; }\n.@{fa-css-prefix}-lightbulb-o:before { content: @fa-var-lightbulb-o; }\n.@{fa-css-prefix}-exchange:before { content: @fa-var-exchange; }\n.@{fa-css-prefix}-cloud-download:before { content: @fa-var-cloud-download; }\n.@{fa-css-prefix}-cloud-upload:before { content: @fa-var-cloud-upload; }\n.@{fa-css-prefix}-user-md:before { content: @fa-var-user-md; }\n.@{fa-css-prefix}-stethoscope:before { content: @fa-var-stethoscope; }\n.@{fa-css-prefix}-suitcase:before { content: @fa-var-suitcase; }\n.@{fa-css-prefix}-bell-o:before { content: @fa-var-bell-o; }\n.@{fa-css-prefix}-coffee:before { content: @fa-var-coffee; }\n.@{fa-css-prefix}-cutlery:before { content: @fa-var-cutlery; }\n.@{fa-css-prefix}-file-text-o:before { content: @fa-var-file-text-o; }\n.@{fa-css-prefix}-building:before { content: @fa-var-building; }\n.@{fa-css-prefix}-hospital:before { content: @fa-var-hospital; }\n.@{fa-css-prefix}-ambulance:before { content: @fa-var-ambulance; }\n.@{fa-css-prefix}-medkit:before { content: @fa-var-medkit; }\n.@{fa-css-prefix}-fighter-jet:before { content: @fa-var-fighter-jet; }\n.@{fa-css-prefix}-beer:before { content: @fa-var-beer; }\n.@{fa-css-prefix}-h-square:before { content: @fa-var-h-square; }\n.@{fa-css-prefix}-plus-square:before { content: @fa-var-plus-square; }\n.@{fa-css-prefix}-angle-double-left:before { content: @fa-var-angle-double-left; }\n.@{fa-css-prefix}-angle-double-right:before { content: @fa-var-angle-double-right; }\n.@{fa-css-prefix}-angle-double-up:before { content: @fa-var-angle-double-up; }\n.@{fa-css-prefix}-angle-double-down:before { content: @fa-var-angle-double-down; }\n.@{fa-css-prefix}-angle-left:before { content: @fa-var-angle-left; }\n.@{fa-css-prefix}-angle-right:before { content: @fa-var-angle-right; }\n.@{fa-css-prefix}-angle-up:before { content: @fa-var-angle-up; }\n.@{fa-css-prefix}-angle-down:before { content: @fa-var-angle-down; }\n.@{fa-css-prefix}-desktop:before { content: @fa-var-desktop; }\n.@{fa-css-prefix}-laptop:before { content: @fa-var-laptop; }\n.@{fa-css-prefix}-tablet:before { content: @fa-var-tablet; }\n.@{fa-css-prefix}-mobile-phone:before,\n.@{fa-css-prefix}-mobile:before { content: @fa-var-mobile; }\n.@{fa-css-prefix}-circle-o:before { content: @fa-var-circle-o; }\n.@{fa-css-prefix}-quote-left:before { content: @fa-var-quote-left; }\n.@{fa-css-prefix}-quote-right:before { content: @fa-var-quote-right; }\n.@{fa-css-prefix}-spinner:before { content: @fa-var-spinner; }\n.@{fa-css-prefix}-circle:before { content: @fa-var-circle; }\n.@{fa-css-prefix}-mail-reply:before,\n.@{fa-css-prefix}-reply:before { content: @fa-var-reply; }\n.@{fa-css-prefix}-github-alt:before { content: @fa-var-github-alt; }\n.@{fa-css-prefix}-folder-o:before { content: @fa-var-folder-o; }\n.@{fa-css-prefix}-folder-open-o:before { content: @fa-var-folder-open-o; }\n.@{fa-css-prefix}-expand-o:before { content: @fa-var-expand-o; }\n.@{fa-css-prefix}-collapse-o:before { content: @fa-var-collapse-o; }\n.@{fa-css-prefix}-smile-o:before { content: @fa-var-smile-o; }\n.@{fa-css-prefix}-frown-o:before { content: @fa-var-frown-o; }\n.@{fa-css-prefix}-meh-o:before { content: @fa-var-meh-o; }\n.@{fa-css-prefix}-gamepad:before { content: @fa-var-gamepad; }\n.@{fa-css-prefix}-keyboard-o:before { content: @fa-var-keyboard-o; }\n.@{fa-css-prefix}-flag-o:before { content: @fa-var-flag-o; }\n.@{fa-css-prefix}-flag-checkered:before { content: @fa-var-flag-checkered; }\n.@{fa-css-prefix}-terminal:before { content: @fa-var-terminal; }\n.@{fa-css-prefix}-code:before { content: @fa-var-code; }\n.@{fa-css-prefix}-reply-all:before { content: @fa-var-reply-all; }\n.@{fa-css-prefix}-mail-reply-all:before { content: @fa-var-mail-reply-all; }\n.@{fa-css-prefix}-star-half-empty:before,\n.@{fa-css-prefix}-star-half-full:before,\n.@{fa-css-prefix}-star-half-o:before { content: @fa-var-star-half-o; }\n.@{fa-css-prefix}-location-arrow:before { content: @fa-var-location-arrow; }\n.@{fa-css-prefix}-crop:before { content: @fa-var-crop; }\n.@{fa-css-prefix}-code-fork:before { content: @fa-var-code-fork; }\n.@{fa-css-prefix}-unlink:before,\n.@{fa-css-prefix}-chain-broken:before { content: @fa-var-chain-broken; }\n.@{fa-css-prefix}-question:before { content: @fa-var-question; }\n.@{fa-css-prefix}-info:before { content: @fa-var-info; }\n.@{fa-css-prefix}-exclamation:before { content: @fa-var-exclamation; }\n.@{fa-css-prefix}-superscript:before { content: @fa-var-superscript; }\n.@{fa-css-prefix}-subscript:before { content: @fa-var-subscript; }\n.@{fa-css-prefix}-eraser:before { content: @fa-var-eraser; }\n.@{fa-css-prefix}-puzzle-piece:before { content: @fa-var-puzzle-piece; }\n.@{fa-css-prefix}-microphone:before { content: @fa-var-microphone; }\n.@{fa-css-prefix}-microphone-slash:before { content: @fa-var-microphone-slash; }\n.@{fa-css-prefix}-shield:before { content: @fa-var-shield; }\n.@{fa-css-prefix}-calendar-o:before { content: @fa-var-calendar-o; }\n.@{fa-css-prefix}-fire-extinguisher:before { content: @fa-var-fire-extinguisher; }\n.@{fa-css-prefix}-rocket:before { content: @fa-var-rocket; }\n.@{fa-css-prefix}-maxcdn:before { content: @fa-var-maxcdn; }\n.@{fa-css-prefix}-chevron-circle-left:before { content: @fa-var-chevron-circle-left; }\n.@{fa-css-prefix}-chevron-circle-right:before { content: @fa-var-chevron-circle-right; }\n.@{fa-css-prefix}-chevron-circle-up:before { content: @fa-var-chevron-circle-up; }\n.@{fa-css-prefix}-chevron-circle-down:before { content: @fa-var-chevron-circle-down; }\n.@{fa-css-prefix}-html5:before { content: @fa-var-html5; }\n.@{fa-css-prefix}-css3:before { content: @fa-var-css3; }\n.@{fa-css-prefix}-anchor:before { content: @fa-var-anchor; }\n.@{fa-css-prefix}-unlock-o:before { content: @fa-var-unlock-o; }\n.@{fa-css-prefix}-bullseye:before { content: @fa-var-bullseye; }\n.@{fa-css-prefix}-ellipsis-horizontal:before { content: @fa-var-ellipsis-horizontal; }\n.@{fa-css-prefix}-ellipsis-vertical:before { content: @fa-var-ellipsis-vertical; }\n.@{fa-css-prefix}-rss-square:before { content: @fa-var-rss-square; }\n.@{fa-css-prefix}-play-circle:before { content: @fa-var-play-circle; }\n.@{fa-css-prefix}-ticket:before { content: @fa-var-ticket; }\n.@{fa-css-prefix}-minus-square:before { content: @fa-var-minus-square; }\n.@{fa-css-prefix}-minus-square-o:before { content: @fa-var-minus-square-o; }\n.@{fa-css-prefix}-level-up:before { content: @fa-var-level-up; }\n.@{fa-css-prefix}-level-down:before { content: @fa-var-level-down; }\n.@{fa-css-prefix}-check-square:before { content: @fa-var-check-square; }\n.@{fa-css-prefix}-pencil-square:before { content: @fa-var-pencil-square; }\n.@{fa-css-prefix}-external-link-square:before { content: @fa-var-external-link-square; }\n.@{fa-css-prefix}-share-square:before { content: @fa-var-share-square; }\n.@{fa-css-prefix}-compass:before { content: @fa-var-compass; }\n.@{fa-css-prefix}-toggle-down:before,\n.@{fa-css-prefix}-caret-square-o-down:before { content: @fa-var-caret-square-o-down; }\n.@{fa-css-prefix}-toggle-up:before,\n.@{fa-css-prefix}-caret-square-o-up:before { content: @fa-var-caret-square-o-up; }\n.@{fa-css-prefix}-toggle-right:before,\n.@{fa-css-prefix}-caret-square-o-right:before { content: @fa-var-caret-square-o-right; }\n.@{fa-css-prefix}-euro:before,\n.@{fa-css-prefix}-eur:before { content: @fa-var-eur; }\n.@{fa-css-prefix}-gbp:before { content: @fa-var-gbp; }\n.@{fa-css-prefix}-dollar:before,\n.@{fa-css-prefix}-usd:before { content: @fa-var-usd; }\n.@{fa-css-prefix}-rupee:before,\n.@{fa-css-prefix}-inr:before { content: @fa-var-inr; }\n.@{fa-css-prefix}-cny:before,\n.@{fa-css-prefix}-rmb:before,\n.@{fa-css-prefix}-yen:before,\n.@{fa-css-prefix}-jpy:before { content: @fa-var-jpy; }\n.@{fa-css-prefix}-ruble:before,\n.@{fa-css-prefix}-rouble:before,\n.@{fa-css-prefix}-rub:before { content: @fa-var-rub; }\n.@{fa-css-prefix}-won:before,\n.@{fa-css-prefix}-krw:before { content: @fa-var-krw; }\n.@{fa-css-prefix}-bitcoin:before,\n.@{fa-css-prefix}-btc:before { content: @fa-var-btc; }\n.@{fa-css-prefix}-file:before { content: @fa-var-file; }\n.@{fa-css-prefix}-file-text:before { content: @fa-var-file-text; }\n.@{fa-css-prefix}-sort-alpha-asc:before { content: @fa-var-sort-alpha-asc; }\n.@{fa-css-prefix}-sort-alpha-desc:before { content: @fa-var-sort-alpha-desc; }\n.@{fa-css-prefix}-sort-amount-asc:before { content: @fa-var-sort-amount-asc; }\n.@{fa-css-prefix}-sort-amount-desc:before { content: @fa-var-sort-amount-desc; }\n.@{fa-css-prefix}-sort-numeric-asc:before { content: @fa-var-sort-numeric-asc; }\n.@{fa-css-prefix}-sort-numeric-desc:before { content: @fa-var-sort-numeric-desc; }\n.@{fa-css-prefix}-thumbs-up:before { content: @fa-var-thumbs-up; }\n.@{fa-css-prefix}-thumbs-down:before { content: @fa-var-thumbs-down; }\n.@{fa-css-prefix}-youtube-square:before { content: @fa-var-youtube-square; }\n.@{fa-css-prefix}-youtube:before { content: @fa-var-youtube; }\n.@{fa-css-prefix}-xing:before { content: @fa-var-xing; }\n.@{fa-css-prefix}-xing-square:before { content: @fa-var-xing-square; }\n.@{fa-css-prefix}-youtube-play:before { content: @fa-var-youtube-play; }\n.@{fa-css-prefix}-dropbox:before { content: @fa-var-dropbox; }\n.@{fa-css-prefix}-stack-overflow:before { content: @fa-var-stack-overflow; }\n.@{fa-css-prefix}-instagram:before { content: @fa-var-instagram; }\n.@{fa-css-prefix}-flickr:before { content: @fa-var-flickr; }\n.@{fa-css-prefix}-adn:before { content: @fa-var-adn; }\n.@{fa-css-prefix}-bitbucket:before { content: @fa-var-bitbucket; }\n.@{fa-css-prefix}-bitbucket-square:before { content: @fa-var-bitbucket-square; }\n.@{fa-css-prefix}-tumblr:before { content: @fa-var-tumblr; }\n.@{fa-css-prefix}-tumblr-square:before { content: @fa-var-tumblr-square; }\n.@{fa-css-prefix}-long-arrow-down:before { content: @fa-var-long-arrow-down; }\n.@{fa-css-prefix}-long-arrow-up:before { content: @fa-var-long-arrow-up; }\n.@{fa-css-prefix}-long-arrow-left:before { content: @fa-var-long-arrow-left; }\n.@{fa-css-prefix}-long-arrow-right:before { content: @fa-var-long-arrow-right; }\n.@{fa-css-prefix}-apple:before { content: @fa-var-apple; }\n.@{fa-css-prefix}-windows:before { content: @fa-var-windows; }\n.@{fa-css-prefix}-android:before { content: @fa-var-android; }\n.@{fa-css-prefix}-linux:before { content: @fa-var-linux; }\n.@{fa-css-prefix}-dribbble:before { content: @fa-var-dribbble; }\n.@{fa-css-prefix}-skype:before { content: @fa-var-skype; }\n.@{fa-css-prefix}-foursquare:before { content: @fa-var-foursquare; }\n.@{fa-css-prefix}-trello:before { content: @fa-var-trello; }\n.@{fa-css-prefix}-female:before { content: @fa-var-female; }\n.@{fa-css-prefix}-male:before { content: @fa-var-male; }\n.@{fa-css-prefix}-gittip:before { content: @fa-var-gittip; }\n.@{fa-css-prefix}-sun-o:before { content: @fa-var-sun-o; }\n.@{fa-css-prefix}-moon-o:before { content: @fa-var-moon-o; }\n.@{fa-css-prefix}-archive:before { content: @fa-var-archive; }\n.@{fa-css-prefix}-bug:before { content: @fa-var-bug; }\n.@{fa-css-prefix}-vk:before { content: @fa-var-vk; }\n.@{fa-css-prefix}-weibo:before { content: @fa-var-weibo; }\n.@{fa-css-prefix}-renren:before { content: @fa-var-renren; }\n.@{fa-css-prefix}-pagelines:before { content: @fa-var-pagelines; }\n.@{fa-css-prefix}-stack-exchange:before { content: @fa-var-stack-exchange; }\n.@{fa-css-prefix}-arrow-circle-o-right:before { content: @fa-var-arrow-circle-o-right; }\n.@{fa-css-prefix}-arrow-circle-o-left:before { content: @fa-var-arrow-circle-o-left; }\n.@{fa-css-prefix}-toggle-left:before,\n.@{fa-css-prefix}-caret-square-o-left:before { content: @fa-var-caret-square-o-left; }\n.@{fa-css-prefix}-dot-circle-o:before { content: @fa-var-dot-circle-o; }\n.@{fa-css-prefix}-wheelchair:before { content: @fa-var-wheelchair; }\n.@{fa-css-prefix}-vimeo-square:before { content: @fa-var-vimeo-square; }\n.@{fa-css-prefix}-turkish-lira:before,\n.@{fa-css-prefix}-try:before { content: @fa-var-try; }\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/plugins/font-awesome/less/larger.less",
    "content": "// Icon Sizes\n// -------------------------\n\n/* makes the font 33% larger relative to the icon container */\n.@{fa-css-prefix}-lg {\n  font-size: (4em / 3);\n  line-height: (3em / 4);\n  vertical-align: -15%;\n}\n.@{fa-css-prefix}-2x { font-size: 2em; }\n.@{fa-css-prefix}-3x { font-size: 3em; }\n.@{fa-css-prefix}-4x { font-size: 4em; }\n.@{fa-css-prefix}-5x { font-size: 5em; }\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/plugins/font-awesome/less/list.less",
    "content": "// List Icons\n// -------------------------\n\n.@{fa-css-prefix}-ul {\n  padding-left: 0;\n  margin-left: @fa-li-width;\n  list-style-type: none;\n  > li { position: relative; }\n}\n.@{fa-css-prefix}-li {\n  position: absolute;\n  left: -@fa-li-width;\n  width: @fa-li-width;\n  top: (2em / 14);\n  text-align: center;\n  &.@{fa-css-prefix}-lg {\n    left: -@fa-li-width + (4em / 14);\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/plugins/font-awesome/less/mixins.less",
    "content": "// Mixins\n// --------------------------\n\n.fa-icon-rotate(@degrees, @rotation) {\n  filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=@rotation);\n  -webkit-transform: rotate(@degrees);\n     -moz-transform: rotate(@degrees);\n      -ms-transform: rotate(@degrees);\n       -o-transform: rotate(@degrees);\n          transform: rotate(@degrees);\n}\n\n.fa-icon-flip(@horiz, @vert, @rotation) {\n  filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=@rotation, mirror=1);\n  -webkit-transform: scale(@horiz, @vert);\n     -moz-transform: scale(@horiz, @vert);\n      -ms-transform: scale(@horiz, @vert);\n       -o-transform: scale(@horiz, @vert);\n          transform: scale(@horiz, @vert);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/plugins/font-awesome/less/path.less",
    "content": "/* FONT PATH\n * -------------------------- */\n\n@font-face {\n  font-family: 'FontAwesome';\n  src: url('@{fa-font-path}/fontawesome-webfont.eot?v=@{fa-version}');\n  src: url('@{fa-font-path}/fontawesome-webfont.eot?#iefix&v=@{fa-version}') format('embedded-opentype'),\n    url('@{fa-font-path}/fontawesome-webfont.woff?v=@{fa-version}') format('woff'),\n    url('@{fa-font-path}/fontawesome-webfont.ttf?v=@{fa-version}') format('truetype'),\n    url('@{fa-font-path}/fontawesome-webfont.svg?v=@{fa-version}#fontawesomeregular') format('svg');\n//  src: url('@{fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts\n  font-weight: normal;\n  font-style: normal;\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/plugins/font-awesome/less/rotated-flipped.less",
    "content": "// Rotated & Flipped Icons\n// -------------------------\n\n.@{fa-css-prefix}-rotate-90  { .fa-icon-rotate(90deg, 1);  }\n.@{fa-css-prefix}-rotate-180 { .fa-icon-rotate(180deg, 2); }\n.@{fa-css-prefix}-rotate-270 { .fa-icon-rotate(270deg, 3); }\n\n.@{fa-css-prefix}-flip-horizontal { .fa-icon-flip(-1, 1, 0); }\n.@{fa-css-prefix}-flip-vertical   { .fa-icon-flip(1, -1, 2); }\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/plugins/font-awesome/less/spinning.less",
    "content": "// Spinning Icons\n// --------------------------\n\n.@{fa-css-prefix}-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\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"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/plugins/font-awesome/less/stacked.less",
    "content": "// Stacked Icons\n// -------------------------\n\n.@{fa-css-prefix}-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-css-prefix}-stack-1x, .@{fa-css-prefix}-stack-2x {\n  position: absolute;\n  left: 0;\n  width: 100%;\n  text-align: center;\n}\n.@{fa-css-prefix}-stack-1x { line-height: inherit; }\n.@{fa-css-prefix}-stack-2x { font-size: 2em; }\n.@{fa-css-prefix}-inverse { color: @fa-inverse; }\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/plugins/font-awesome/less/variables.less",
    "content": "// Variables\n// --------------------------\n\n@fa-font-path:        \"../fonts\";\n//@fa-font-path:        \"//netdna.bootstrapcdn.com/font-awesome/4.0.1/fonts\"; // for referencing Bootstrap CDN font files directly\n@fa-css-prefix:       fa;\n@fa-version:          \"4.0.1\";\n@fa-border-color:     #eee;\n@fa-inverse:          #fff;\n@fa-li-width:         (30em / 14);\n\n@fa-var-glass: \"\\f000\";\n@fa-var-music: \"\\f001\";\n@fa-var-search: \"\\f002\";\n@fa-var-envelope-o: \"\\f003\";\n@fa-var-heart: \"\\f004\";\n@fa-var-star: \"\\f005\";\n@fa-var-star-o: \"\\f006\";\n@fa-var-user: \"\\f007\";\n@fa-var-film: \"\\f008\";\n@fa-var-th-large: \"\\f009\";\n@fa-var-th: \"\\f00a\";\n@fa-var-th-list: \"\\f00b\";\n@fa-var-check: \"\\f00c\";\n@fa-var-times: \"\\f00d\";\n@fa-var-search-plus: \"\\f00e\";\n@fa-var-search-minus: \"\\f010\";\n@fa-var-power-off: \"\\f011\";\n@fa-var-signal: \"\\f012\";\n@fa-var-cog: \"\\f013\";\n@fa-var-trash-o: \"\\f014\";\n@fa-var-home: \"\\f015\";\n@fa-var-file-o: \"\\f016\";\n@fa-var-clock-o: \"\\f017\";\n@fa-var-road: \"\\f018\";\n@fa-var-download: \"\\f019\";\n@fa-var-arrow-circle-o-down: \"\\f01a\";\n@fa-var-arrow-circle-o-up: \"\\f01b\";\n@fa-var-inbox: \"\\f01c\";\n@fa-var-play-circle-o: \"\\f01d\";\n@fa-var-repeat: \"\\f01e\";\n@fa-var-refresh: \"\\f021\";\n@fa-var-list-alt: \"\\f022\";\n@fa-var-lock: \"\\f023\";\n@fa-var-flag: \"\\f024\";\n@fa-var-headphones: \"\\f025\";\n@fa-var-volume-off: \"\\f026\";\n@fa-var-volume-down: \"\\f027\";\n@fa-var-volume-up: \"\\f028\";\n@fa-var-qrcode: \"\\f029\";\n@fa-var-barcode: \"\\f02a\";\n@fa-var-tag: \"\\f02b\";\n@fa-var-tags: \"\\f02c\";\n@fa-var-book: \"\\f02d\";\n@fa-var-bookmark: \"\\f02e\";\n@fa-var-print: \"\\f02f\";\n@fa-var-camera: \"\\f030\";\n@fa-var-font: \"\\f031\";\n@fa-var-bold: \"\\f032\";\n@fa-var-italic: \"\\f033\";\n@fa-var-text-height: \"\\f034\";\n@fa-var-text-width: \"\\f035\";\n@fa-var-align-left: \"\\f036\";\n@fa-var-align-center: \"\\f037\";\n@fa-var-align-right: \"\\f038\";\n@fa-var-align-justify: \"\\f039\";\n@fa-var-list: \"\\f03a\";\n@fa-var-outdent: \"\\f03b\";\n@fa-var-indent: \"\\f03c\";\n@fa-var-video-camera: \"\\f03d\";\n@fa-var-picture-o: \"\\f03e\";\n@fa-var-pencil: \"\\f040\";\n@fa-var-map-marker: \"\\f041\";\n@fa-var-adjust: \"\\f042\";\n@fa-var-tint: \"\\f043\";\n@fa-var-pencil-square-o: \"\\f044\";\n@fa-var-share-square-o: \"\\f045\";\n@fa-var-check-square-o: \"\\f046\";\n@fa-var-move: \"\\f047\";\n@fa-var-step-backward: \"\\f048\";\n@fa-var-fast-backward: \"\\f049\";\n@fa-var-backward: \"\\f04a\";\n@fa-var-play: \"\\f04b\";\n@fa-var-pause: \"\\f04c\";\n@fa-var-stop: \"\\f04d\";\n@fa-var-forward: \"\\f04e\";\n@fa-var-fast-forward: \"\\f050\";\n@fa-var-step-forward: \"\\f051\";\n@fa-var-eject: \"\\f052\";\n@fa-var-chevron-left: \"\\f053\";\n@fa-var-chevron-right: \"\\f054\";\n@fa-var-plus-circle: \"\\f055\";\n@fa-var-minus-circle: \"\\f056\";\n@fa-var-times-circle: \"\\f057\";\n@fa-var-check-circle: \"\\f058\";\n@fa-var-question-circle: \"\\f059\";\n@fa-var-info-circle: \"\\f05a\";\n@fa-var-crosshairs: \"\\f05b\";\n@fa-var-times-circle-o: \"\\f05c\";\n@fa-var-check-circle-o: \"\\f05d\";\n@fa-var-ban: \"\\f05e\";\n@fa-var-arrow-left: \"\\f060\";\n@fa-var-arrow-right: \"\\f061\";\n@fa-var-arrow-up: \"\\f062\";\n@fa-var-arrow-down: \"\\f063\";\n@fa-var-share: \"\\f064\";\n@fa-var-resize-full: \"\\f065\";\n@fa-var-resize-small: \"\\f066\";\n@fa-var-plus: \"\\f067\";\n@fa-var-minus: \"\\f068\";\n@fa-var-asterisk: \"\\f069\";\n@fa-var-exclamation-circle: \"\\f06a\";\n@fa-var-gift: \"\\f06b\";\n@fa-var-leaf: \"\\f06c\";\n@fa-var-fire: \"\\f06d\";\n@fa-var-eye: \"\\f06e\";\n@fa-var-eye-slash: \"\\f070\";\n@fa-var-exclamation-triangle: \"\\f071\";\n@fa-var-plane: \"\\f072\";\n@fa-var-calendar: \"\\f073\";\n@fa-var-random: \"\\f074\";\n@fa-var-comment: \"\\f075\";\n@fa-var-magnet: \"\\f076\";\n@fa-var-chevron-up: \"\\f077\";\n@fa-var-chevron-down: \"\\f078\";\n@fa-var-retweet: \"\\f079\";\n@fa-var-shopping-cart: \"\\f07a\";\n@fa-var-folder: \"\\f07b\";\n@fa-var-folder-open: \"\\f07c\";\n@fa-var-resize-vertical: \"\\f07d\";\n@fa-var-resize-horizontal: \"\\f07e\";\n@fa-var-bar-chart-o: \"\\f080\";\n@fa-var-twitter-square: \"\\f081\";\n@fa-var-facebook-square: \"\\f082\";\n@fa-var-camera-retro: \"\\f083\";\n@fa-var-key: \"\\f084\";\n@fa-var-cogs: \"\\f085\";\n@fa-var-comments: \"\\f086\";\n@fa-var-thumbs-o-up: \"\\f087\";\n@fa-var-thumbs-o-down: \"\\f088\";\n@fa-var-star-half: \"\\f089\";\n@fa-var-heart-o: \"\\f08a\";\n@fa-var-sign-out: \"\\f08b\";\n@fa-var-linkedin-square: \"\\f08c\";\n@fa-var-thumb-tack: \"\\f08d\";\n@fa-var-external-link: \"\\f08e\";\n@fa-var-sign-in: \"\\f090\";\n@fa-var-trophy: \"\\f091\";\n@fa-var-github-square: \"\\f092\";\n@fa-var-upload: \"\\f093\";\n@fa-var-lemon-o: \"\\f094\";\n@fa-var-phone: \"\\f095\";\n@fa-var-square-o: \"\\f096\";\n@fa-var-bookmark-o: \"\\f097\";\n@fa-var-phone-square: \"\\f098\";\n@fa-var-twitter: \"\\f099\";\n@fa-var-facebook: \"\\f09a\";\n@fa-var-github: \"\\f09b\";\n@fa-var-unlock: \"\\f09c\";\n@fa-var-credit-card: \"\\f09d\";\n@fa-var-rss: \"\\f09e\";\n@fa-var-hdd-o: \"\\f0a0\";\n@fa-var-bullhorn: \"\\f0a1\";\n@fa-var-bell: \"\\f0f3\";\n@fa-var-certificate: \"\\f0a3\";\n@fa-var-hand-o-right: \"\\f0a4\";\n@fa-var-hand-o-left: \"\\f0a5\";\n@fa-var-hand-o-up: \"\\f0a6\";\n@fa-var-hand-o-down: \"\\f0a7\";\n@fa-var-arrow-circle-left: \"\\f0a8\";\n@fa-var-arrow-circle-right: \"\\f0a9\";\n@fa-var-arrow-circle-up: \"\\f0aa\";\n@fa-var-arrow-circle-down: \"\\f0ab\";\n@fa-var-globe: \"\\f0ac\";\n@fa-var-wrench: \"\\f0ad\";\n@fa-var-tasks: \"\\f0ae\";\n@fa-var-filter: \"\\f0b0\";\n@fa-var-briefcase: \"\\f0b1\";\n@fa-var-fullscreen: \"\\f0b2\";\n@fa-var-group: \"\\f0c0\";\n@fa-var-link: \"\\f0c1\";\n@fa-var-cloud: \"\\f0c2\";\n@fa-var-flask: \"\\f0c3\";\n@fa-var-scissors: \"\\f0c4\";\n@fa-var-files-o: \"\\f0c5\";\n@fa-var-paperclip: \"\\f0c6\";\n@fa-var-floppy-o: \"\\f0c7\";\n@fa-var-square: \"\\f0c8\";\n@fa-var-reorder: \"\\f0c9\";\n@fa-var-list-ul: \"\\f0ca\";\n@fa-var-list-ol: \"\\f0cb\";\n@fa-var-strikethrough: \"\\f0cc\";\n@fa-var-underline: \"\\f0cd\";\n@fa-var-table: \"\\f0ce\";\n@fa-var-magic: \"\\f0d0\";\n@fa-var-truck: \"\\f0d1\";\n@fa-var-pinterest: \"\\f0d2\";\n@fa-var-pinterest-square: \"\\f0d3\";\n@fa-var-google-plus-square: \"\\f0d4\";\n@fa-var-google-plus: \"\\f0d5\";\n@fa-var-money: \"\\f0d6\";\n@fa-var-caret-down: \"\\f0d7\";\n@fa-var-caret-up: \"\\f0d8\";\n@fa-var-caret-left: \"\\f0d9\";\n@fa-var-caret-right: \"\\f0da\";\n@fa-var-columns: \"\\f0db\";\n@fa-var-sort: \"\\f0dc\";\n@fa-var-sort-asc: \"\\f0dd\";\n@fa-var-sort-desc: \"\\f0de\";\n@fa-var-envelope: \"\\f0e0\";\n@fa-var-linkedin: \"\\f0e1\";\n@fa-var-undo: \"\\f0e2\";\n@fa-var-gavel: \"\\f0e3\";\n@fa-var-tachometer: \"\\f0e4\";\n@fa-var-comment-o: \"\\f0e5\";\n@fa-var-comments-o: \"\\f0e6\";\n@fa-var-bolt: \"\\f0e7\";\n@fa-var-sitemap: \"\\f0e8\";\n@fa-var-umbrella: \"\\f0e9\";\n@fa-var-clipboard: \"\\f0ea\";\n@fa-var-lightbulb-o: \"\\f0eb\";\n@fa-var-exchange: \"\\f0ec\";\n@fa-var-cloud-download: \"\\f0ed\";\n@fa-var-cloud-upload: \"\\f0ee\";\n@fa-var-user-md: \"\\f0f0\";\n@fa-var-stethoscope: \"\\f0f1\";\n@fa-var-suitcase: \"\\f0f2\";\n@fa-var-bell-o: \"\\f0a2\";\n@fa-var-coffee: \"\\f0f4\";\n@fa-var-cutlery: \"\\f0f5\";\n@fa-var-file-text-o: \"\\f0f6\";\n@fa-var-building: \"\\f0f7\";\n@fa-var-hospital: \"\\f0f8\";\n@fa-var-ambulance: \"\\f0f9\";\n@fa-var-medkit: \"\\f0fa\";\n@fa-var-fighter-jet: \"\\f0fb\";\n@fa-var-beer: \"\\f0fc\";\n@fa-var-h-square: \"\\f0fd\";\n@fa-var-plus-square: \"\\f0fe\";\n@fa-var-angle-double-left: \"\\f100\";\n@fa-var-angle-double-right: \"\\f101\";\n@fa-var-angle-double-up: \"\\f102\";\n@fa-var-angle-double-down: \"\\f103\";\n@fa-var-angle-left: \"\\f104\";\n@fa-var-angle-right: \"\\f105\";\n@fa-var-angle-up: \"\\f106\";\n@fa-var-angle-down: \"\\f107\";\n@fa-var-desktop: \"\\f108\";\n@fa-var-laptop: \"\\f109\";\n@fa-var-tablet: \"\\f10a\";\n@fa-var-mobile: \"\\f10b\";\n@fa-var-circle-o: \"\\f10c\";\n@fa-var-quote-left: \"\\f10d\";\n@fa-var-quote-right: \"\\f10e\";\n@fa-var-spinner: \"\\f110\";\n@fa-var-circle: \"\\f111\";\n@fa-var-reply: \"\\f112\";\n@fa-var-github-alt: \"\\f113\";\n@fa-var-folder-o: \"\\f114\";\n@fa-var-folder-open-o: \"\\f115\";\n@fa-var-expand-o: \"\\f116\";\n@fa-var-collapse-o: \"\\f117\";\n@fa-var-smile-o: \"\\f118\";\n@fa-var-frown-o: \"\\f119\";\n@fa-var-meh-o: \"\\f11a\";\n@fa-var-gamepad: \"\\f11b\";\n@fa-var-keyboard-o: \"\\f11c\";\n@fa-var-flag-o: \"\\f11d\";\n@fa-var-flag-checkered: \"\\f11e\";\n@fa-var-terminal: \"\\f120\";\n@fa-var-code: \"\\f121\";\n@fa-var-reply-all: \"\\f122\";\n@fa-var-mail-reply-all: \"\\f122\";\n@fa-var-star-half-o: \"\\f123\";\n@fa-var-location-arrow: \"\\f124\";\n@fa-var-crop: \"\\f125\";\n@fa-var-code-fork: \"\\f126\";\n@fa-var-chain-broken: \"\\f127\";\n@fa-var-question: \"\\f128\";\n@fa-var-info: \"\\f129\";\n@fa-var-exclamation: \"\\f12a\";\n@fa-var-superscript: \"\\f12b\";\n@fa-var-subscript: \"\\f12c\";\n@fa-var-eraser: \"\\f12d\";\n@fa-var-puzzle-piece: \"\\f12e\";\n@fa-var-microphone: \"\\f130\";\n@fa-var-microphone-slash: \"\\f131\";\n@fa-var-shield: \"\\f132\";\n@fa-var-calendar-o: \"\\f133\";\n@fa-var-fire-extinguisher: \"\\f134\";\n@fa-var-rocket: \"\\f135\";\n@fa-var-maxcdn: \"\\f136\";\n@fa-var-chevron-circle-left: \"\\f137\";\n@fa-var-chevron-circle-right: \"\\f138\";\n@fa-var-chevron-circle-up: \"\\f139\";\n@fa-var-chevron-circle-down: \"\\f13a\";\n@fa-var-html5: \"\\f13b\";\n@fa-var-css3: \"\\f13c\";\n@fa-var-anchor: \"\\f13d\";\n@fa-var-unlock-o: \"\\f13e\";\n@fa-var-bullseye: \"\\f140\";\n@fa-var-ellipsis-horizontal: \"\\f141\";\n@fa-var-ellipsis-vertical: \"\\f142\";\n@fa-var-rss-square: \"\\f143\";\n@fa-var-play-circle: \"\\f144\";\n@fa-var-ticket: \"\\f145\";\n@fa-var-minus-square: \"\\f146\";\n@fa-var-minus-square-o: \"\\f147\";\n@fa-var-level-up: \"\\f148\";\n@fa-var-level-down: \"\\f149\";\n@fa-var-check-square: \"\\f14a\";\n@fa-var-pencil-square: \"\\f14b\";\n@fa-var-external-link-square: \"\\f14c\";\n@fa-var-share-square: \"\\f14d\";\n@fa-var-compass: \"\\f14e\";\n@fa-var-caret-square-o-down: \"\\f150\";\n@fa-var-caret-square-o-up: \"\\f151\";\n@fa-var-caret-square-o-right: \"\\f152\";\n@fa-var-eur: \"\\f153\";\n@fa-var-gbp: \"\\f154\";\n@fa-var-usd: \"\\f155\";\n@fa-var-inr: \"\\f156\";\n@fa-var-jpy: \"\\f157\";\n@fa-var-rub: \"\\f158\";\n@fa-var-krw: \"\\f159\";\n@fa-var-btc: \"\\f15a\";\n@fa-var-file: \"\\f15b\";\n@fa-var-file-text: \"\\f15c\";\n@fa-var-sort-alpha-asc: \"\\f15d\";\n@fa-var-sort-alpha-desc: \"\\f15e\";\n@fa-var-sort-amount-asc: \"\\f160\";\n@fa-var-sort-amount-desc: \"\\f161\";\n@fa-var-sort-numeric-asc: \"\\f162\";\n@fa-var-sort-numeric-desc: \"\\f163\";\n@fa-var-thumbs-up: \"\\f164\";\n@fa-var-thumbs-down: \"\\f165\";\n@fa-var-youtube-square: \"\\f166\";\n@fa-var-youtube: \"\\f167\";\n@fa-var-xing: \"\\f168\";\n@fa-var-xing-square: \"\\f169\";\n@fa-var-youtube-play: \"\\f16a\";\n@fa-var-dropbox: \"\\f16b\";\n@fa-var-stack-overflow: \"\\f16c\";\n@fa-var-instagram: \"\\f16d\";\n@fa-var-flickr: \"\\f16e\";\n@fa-var-adn: \"\\f170\";\n@fa-var-bitbucket: \"\\f171\";\n@fa-var-bitbucket-square: \"\\f172\";\n@fa-var-tumblr: \"\\f173\";\n@fa-var-tumblr-square: \"\\f174\";\n@fa-var-long-arrow-down: \"\\f175\";\n@fa-var-long-arrow-up: \"\\f176\";\n@fa-var-long-arrow-left: \"\\f177\";\n@fa-var-long-arrow-right: \"\\f178\";\n@fa-var-apple: \"\\f179\";\n@fa-var-windows: \"\\f17a\";\n@fa-var-android: \"\\f17b\";\n@fa-var-linux: \"\\f17c\";\n@fa-var-dribbble: \"\\f17d\";\n@fa-var-skype: \"\\f17e\";\n@fa-var-foursquare: \"\\f180\";\n@fa-var-trello: \"\\f181\";\n@fa-var-female: \"\\f182\";\n@fa-var-male: \"\\f183\";\n@fa-var-gittip: \"\\f184\";\n@fa-var-sun-o: \"\\f185\";\n@fa-var-moon-o: \"\\f186\";\n@fa-var-archive: \"\\f187\";\n@fa-var-bug: \"\\f188\";\n@fa-var-vk: \"\\f189\";\n@fa-var-weibo: \"\\f18a\";\n@fa-var-renren: \"\\f18b\";\n@fa-var-pagelines: \"\\f18c\";\n@fa-var-stack-exchange: \"\\f18d\";\n@fa-var-arrow-circle-o-right: \"\\f18e\";\n@fa-var-arrow-circle-o-left: \"\\f190\";\n@fa-var-caret-square-o-left: \"\\f191\";\n@fa-var-dot-circle-o: \"\\f192\";\n@fa-var-wheelchair: \"\\f193\";\n@fa-var-vimeo-square: \"\\f194\";\n@fa-var-try: \"\\f195\";\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/plugins/font-awesome/scss/_bordered-pulled.scss",
    "content": "// Bordered & Pulled\n// -------------------------\n\n.#{$fa-css-prefix}-border {\n  padding: .2em .25em .15em;\n  border: solid .08em $fa-border-color;\n  border-radius: .1em;\n}\n\n.pull-right { float: right; }\n.pull-left { float: left; }\n\n.#{$fa-css-prefix} {\n  &.pull-left { margin-right: .3em; }\n  &.pull-right { margin-left: .3em; }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/plugins/font-awesome/scss/_core.scss",
    "content": "// Base Class Definition\n// -------------------------\n\n.#{$fa-css-prefix} {\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"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/plugins/font-awesome/scss/_fixed-width.scss",
    "content": "// Fixed Width Icons\n// -------------------------\n.#{$fa-css-prefix}-fw {\n  width: (18em / 14);\n  text-align: center;\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/plugins/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.#{$fa-css-prefix}-glass:before { content: $fa-var-glass; }\n.#{$fa-css-prefix}-music:before { content: $fa-var-music; }\n.#{$fa-css-prefix}-search:before { content: $fa-var-search; }\n.#{$fa-css-prefix}-envelope-o:before { content: $fa-var-envelope-o; }\n.#{$fa-css-prefix}-heart:before { content: $fa-var-heart; }\n.#{$fa-css-prefix}-star:before { content: $fa-var-star; }\n.#{$fa-css-prefix}-star-o:before { content: $fa-var-star-o; }\n.#{$fa-css-prefix}-user:before { content: $fa-var-user; }\n.#{$fa-css-prefix}-film:before { content: $fa-var-film; }\n.#{$fa-css-prefix}-th-large:before { content: $fa-var-th-large; }\n.#{$fa-css-prefix}-th:before { content: $fa-var-th; }\n.#{$fa-css-prefix}-th-list:before { content: $fa-var-th-list; }\n.#{$fa-css-prefix}-check:before { content: $fa-var-check; }\n.#{$fa-css-prefix}-times:before { content: $fa-var-times; }\n.#{$fa-css-prefix}-search-plus:before { content: $fa-var-search-plus; }\n.#{$fa-css-prefix}-search-minus:before { content: $fa-var-search-minus; }\n.#{$fa-css-prefix}-power-off:before { content: $fa-var-power-off; }\n.#{$fa-css-prefix}-signal:before { content: $fa-var-signal; }\n.#{$fa-css-prefix}-gear:before,\n.#{$fa-css-prefix}-cog:before { content: $fa-var-cog; }\n.#{$fa-css-prefix}-trash-o:before { content: $fa-var-trash-o; }\n.#{$fa-css-prefix}-home:before { content: $fa-var-home; }\n.#{$fa-css-prefix}-file-o:before { content: $fa-var-file-o; }\n.#{$fa-css-prefix}-clock-o:before { content: $fa-var-clock-o; }\n.#{$fa-css-prefix}-road:before { content: $fa-var-road; }\n.#{$fa-css-prefix}-download:before { content: $fa-var-download; }\n.#{$fa-css-prefix}-arrow-circle-o-down:before { content: $fa-var-arrow-circle-o-down; }\n.#{$fa-css-prefix}-arrow-circle-o-up:before { content: $fa-var-arrow-circle-o-up; }\n.#{$fa-css-prefix}-inbox:before { content: $fa-var-inbox; }\n.#{$fa-css-prefix}-play-circle-o:before { content: $fa-var-play-circle-o; }\n.#{$fa-css-prefix}-rotate-right:before,\n.#{$fa-css-prefix}-repeat:before { content: $fa-var-repeat; }\n.#{$fa-css-prefix}-refresh:before { content: $fa-var-refresh; }\n.#{$fa-css-prefix}-list-alt:before { content: $fa-var-list-alt; }\n.#{$fa-css-prefix}-lock:before { content: $fa-var-lock; }\n.#{$fa-css-prefix}-flag:before { content: $fa-var-flag; }\n.#{$fa-css-prefix}-headphones:before { content: $fa-var-headphones; }\n.#{$fa-css-prefix}-volume-off:before { content: $fa-var-volume-off; }\n.#{$fa-css-prefix}-volume-down:before { content: $fa-var-volume-down; }\n.#{$fa-css-prefix}-volume-up:before { content: $fa-var-volume-up; }\n.#{$fa-css-prefix}-qrcode:before { content: $fa-var-qrcode; }\n.#{$fa-css-prefix}-barcode:before { content: $fa-var-barcode; }\n.#{$fa-css-prefix}-tag:before { content: $fa-var-tag; }\n.#{$fa-css-prefix}-tags:before { content: $fa-var-tags; }\n.#{$fa-css-prefix}-book:before { content: $fa-var-book; }\n.#{$fa-css-prefix}-bookmark:before { content: $fa-var-bookmark; }\n.#{$fa-css-prefix}-print:before { content: $fa-var-print; }\n.#{$fa-css-prefix}-camera:before { content: $fa-var-camera; }\n.#{$fa-css-prefix}-font:before { content: $fa-var-font; }\n.#{$fa-css-prefix}-bold:before { content: $fa-var-bold; }\n.#{$fa-css-prefix}-italic:before { content: $fa-var-italic; }\n.#{$fa-css-prefix}-text-height:before { content: $fa-var-text-height; }\n.#{$fa-css-prefix}-text-width:before { content: $fa-var-text-width; }\n.#{$fa-css-prefix}-align-left:before { content: $fa-var-align-left; }\n.#{$fa-css-prefix}-align-center:before { content: $fa-var-align-center; }\n.#{$fa-css-prefix}-align-right:before { content: $fa-var-align-right; }\n.#{$fa-css-prefix}-align-justify:before { content: $fa-var-align-justify; }\n.#{$fa-css-prefix}-list:before { content: $fa-var-list; }\n.#{$fa-css-prefix}-dedent:before,\n.#{$fa-css-prefix}-outdent:before { content: $fa-var-outdent; }\n.#{$fa-css-prefix}-indent:before { content: $fa-var-indent; }\n.#{$fa-css-prefix}-video-camera:before { content: $fa-var-video-camera; }\n.#{$fa-css-prefix}-picture-o:before { content: $fa-var-picture-o; }\n.#{$fa-css-prefix}-pencil:before { content: $fa-var-pencil; }\n.#{$fa-css-prefix}-map-marker:before { content: $fa-var-map-marker; }\n.#{$fa-css-prefix}-adjust:before { content: $fa-var-adjust; }\n.#{$fa-css-prefix}-tint:before { content: $fa-var-tint; }\n.#{$fa-css-prefix}-edit:before,\n.#{$fa-css-prefix}-pencil-square-o:before { content: $fa-var-pencil-square-o; }\n.#{$fa-css-prefix}-share-square-o:before { content: $fa-var-share-square-o; }\n.#{$fa-css-prefix}-check-square-o:before { content: $fa-var-check-square-o; }\n.#{$fa-css-prefix}-move:before { content: $fa-var-move; }\n.#{$fa-css-prefix}-step-backward:before { content: $fa-var-step-backward; }\n.#{$fa-css-prefix}-fast-backward:before { content: $fa-var-fast-backward; }\n.#{$fa-css-prefix}-backward:before { content: $fa-var-backward; }\n.#{$fa-css-prefix}-play:before { content: $fa-var-play; }\n.#{$fa-css-prefix}-pause:before { content: $fa-var-pause; }\n.#{$fa-css-prefix}-stop:before { content: $fa-var-stop; }\n.#{$fa-css-prefix}-forward:before { content: $fa-var-forward; }\n.#{$fa-css-prefix}-fast-forward:before { content: $fa-var-fast-forward; }\n.#{$fa-css-prefix}-step-forward:before { content: $fa-var-step-forward; }\n.#{$fa-css-prefix}-eject:before { content: $fa-var-eject; }\n.#{$fa-css-prefix}-chevron-left:before { content: $fa-var-chevron-left; }\n.#{$fa-css-prefix}-chevron-right:before { content: $fa-var-chevron-right; }\n.#{$fa-css-prefix}-plus-circle:before { content: $fa-var-plus-circle; }\n.#{$fa-css-prefix}-minus-circle:before { content: $fa-var-minus-circle; }\n.#{$fa-css-prefix}-times-circle:before { content: $fa-var-times-circle; }\n.#{$fa-css-prefix}-check-circle:before { content: $fa-var-check-circle; }\n.#{$fa-css-prefix}-question-circle:before { content: $fa-var-question-circle; }\n.#{$fa-css-prefix}-info-circle:before { content: $fa-var-info-circle; }\n.#{$fa-css-prefix}-crosshairs:before { content: $fa-var-crosshairs; }\n.#{$fa-css-prefix}-times-circle-o:before { content: $fa-var-times-circle-o; }\n.#{$fa-css-prefix}-check-circle-o:before { content: $fa-var-check-circle-o; }\n.#{$fa-css-prefix}-ban:before { content: $fa-var-ban; }\n.#{$fa-css-prefix}-arrow-left:before { content: $fa-var-arrow-left; }\n.#{$fa-css-prefix}-arrow-right:before { content: $fa-var-arrow-right; }\n.#{$fa-css-prefix}-arrow-up:before { content: $fa-var-arrow-up; }\n.#{$fa-css-prefix}-arrow-down:before { content: $fa-var-arrow-down; }\n.#{$fa-css-prefix}-mail-forward:before,\n.#{$fa-css-prefix}-share:before { content: $fa-var-share; }\n.#{$fa-css-prefix}-resize-full:before { content: $fa-var-resize-full; }\n.#{$fa-css-prefix}-resize-small:before { content: $fa-var-resize-small; }\n.#{$fa-css-prefix}-plus:before { content: $fa-var-plus; }\n.#{$fa-css-prefix}-minus:before { content: $fa-var-minus; }\n.#{$fa-css-prefix}-asterisk:before { content: $fa-var-asterisk; }\n.#{$fa-css-prefix}-exclamation-circle:before { content: $fa-var-exclamation-circle; }\n.#{$fa-css-prefix}-gift:before { content: $fa-var-gift; }\n.#{$fa-css-prefix}-leaf:before { content: $fa-var-leaf; }\n.#{$fa-css-prefix}-fire:before { content: $fa-var-fire; }\n.#{$fa-css-prefix}-eye:before { content: $fa-var-eye; }\n.#{$fa-css-prefix}-eye-slash:before { content: $fa-var-eye-slash; }\n.#{$fa-css-prefix}-warning:before,\n.#{$fa-css-prefix}-exclamation-triangle:before { content: $fa-var-exclamation-triangle; }\n.#{$fa-css-prefix}-plane:before { content: $fa-var-plane; }\n.#{$fa-css-prefix}-calendar:before { content: $fa-var-calendar; }\n.#{$fa-css-prefix}-random:before { content: $fa-var-random; }\n.#{$fa-css-prefix}-comment:before { content: $fa-var-comment; }\n.#{$fa-css-prefix}-magnet:before { content: $fa-var-magnet; }\n.#{$fa-css-prefix}-chevron-up:before { content: $fa-var-chevron-up; }\n.#{$fa-css-prefix}-chevron-down:before { content: $fa-var-chevron-down; }\n.#{$fa-css-prefix}-retweet:before { content: $fa-var-retweet; }\n.#{$fa-css-prefix}-shopping-cart:before { content: $fa-var-shopping-cart; }\n.#{$fa-css-prefix}-folder:before { content: $fa-var-folder; }\n.#{$fa-css-prefix}-folder-open:before { content: $fa-var-folder-open; }\n.#{$fa-css-prefix}-resize-vertical:before { content: $fa-var-resize-vertical; }\n.#{$fa-css-prefix}-resize-horizontal:before { content: $fa-var-resize-horizontal; }\n.#{$fa-css-prefix}-bar-chart-o:before { content: $fa-var-bar-chart-o; }\n.#{$fa-css-prefix}-twitter-square:before { content: $fa-var-twitter-square; }\n.#{$fa-css-prefix}-facebook-square:before { content: $fa-var-facebook-square; }\n.#{$fa-css-prefix}-camera-retro:before { content: $fa-var-camera-retro; }\n.#{$fa-css-prefix}-key:before { content: $fa-var-key; }\n.#{$fa-css-prefix}-gears:before,\n.#{$fa-css-prefix}-cogs:before { content: $fa-var-cogs; }\n.#{$fa-css-prefix}-comments:before { content: $fa-var-comments; }\n.#{$fa-css-prefix}-thumbs-o-up:before { content: $fa-var-thumbs-o-up; }\n.#{$fa-css-prefix}-thumbs-o-down:before { content: $fa-var-thumbs-o-down; }\n.#{$fa-css-prefix}-star-half:before { content: $fa-var-star-half; }\n.#{$fa-css-prefix}-heart-o:before { content: $fa-var-heart-o; }\n.#{$fa-css-prefix}-sign-out:before { content: $fa-var-sign-out; }\n.#{$fa-css-prefix}-linkedin-square:before { content: $fa-var-linkedin-square; }\n.#{$fa-css-prefix}-thumb-tack:before { content: $fa-var-thumb-tack; }\n.#{$fa-css-prefix}-external-link:before { content: $fa-var-external-link; }\n.#{$fa-css-prefix}-sign-in:before { content: $fa-var-sign-in; }\n.#{$fa-css-prefix}-trophy:before { content: $fa-var-trophy; }\n.#{$fa-css-prefix}-github-square:before { content: $fa-var-github-square; }\n.#{$fa-css-prefix}-upload:before { content: $fa-var-upload; }\n.#{$fa-css-prefix}-lemon-o:before { content: $fa-var-lemon-o; }\n.#{$fa-css-prefix}-phone:before { content: $fa-var-phone; }\n.#{$fa-css-prefix}-square-o:before { content: $fa-var-square-o; }\n.#{$fa-css-prefix}-bookmark-o:before { content: $fa-var-bookmark-o; }\n.#{$fa-css-prefix}-phone-square:before { content: $fa-var-phone-square; }\n.#{$fa-css-prefix}-twitter:before { content: $fa-var-twitter; }\n.#{$fa-css-prefix}-facebook:before { content: $fa-var-facebook; }\n.#{$fa-css-prefix}-github:before { content: $fa-var-github; }\n.#{$fa-css-prefix}-unlock:before { content: $fa-var-unlock; }\n.#{$fa-css-prefix}-credit-card:before { content: $fa-var-credit-card; }\n.#{$fa-css-prefix}-rss:before { content: $fa-var-rss; }\n.#{$fa-css-prefix}-hdd-o:before { content: $fa-var-hdd-o; }\n.#{$fa-css-prefix}-bullhorn:before { content: $fa-var-bullhorn; }\n.#{$fa-css-prefix}-bell:before { content: $fa-var-bell; }\n.#{$fa-css-prefix}-certificate:before { content: $fa-var-certificate; }\n.#{$fa-css-prefix}-hand-o-right:before { content: $fa-var-hand-o-right; }\n.#{$fa-css-prefix}-hand-o-left:before { content: $fa-var-hand-o-left; }\n.#{$fa-css-prefix}-hand-o-up:before { content: $fa-var-hand-o-up; }\n.#{$fa-css-prefix}-hand-o-down:before { content: $fa-var-hand-o-down; }\n.#{$fa-css-prefix}-arrow-circle-left:before { content: $fa-var-arrow-circle-left; }\n.#{$fa-css-prefix}-arrow-circle-right:before { content: $fa-var-arrow-circle-right; }\n.#{$fa-css-prefix}-arrow-circle-up:before { content: $fa-var-arrow-circle-up; }\n.#{$fa-css-prefix}-arrow-circle-down:before { content: $fa-var-arrow-circle-down; }\n.#{$fa-css-prefix}-globe:before { content: $fa-var-globe; }\n.#{$fa-css-prefix}-wrench:before { content: $fa-var-wrench; }\n.#{$fa-css-prefix}-tasks:before { content: $fa-var-tasks; }\n.#{$fa-css-prefix}-filter:before { content: $fa-var-filter; }\n.#{$fa-css-prefix}-briefcase:before { content: $fa-var-briefcase; }\n.#{$fa-css-prefix}-fullscreen:before { content: $fa-var-fullscreen; }\n.#{$fa-css-prefix}-group:before { content: $fa-var-group; }\n.#{$fa-css-prefix}-chain:before,\n.#{$fa-css-prefix}-link:before { content: $fa-var-link; }\n.#{$fa-css-prefix}-cloud:before { content: $fa-var-cloud; }\n.#{$fa-css-prefix}-flask:before { content: $fa-var-flask; }\n.#{$fa-css-prefix}-cut:before,\n.#{$fa-css-prefix}-scissors:before { content: $fa-var-scissors; }\n.#{$fa-css-prefix}-copy:before,\n.#{$fa-css-prefix}-files-o:before { content: $fa-var-files-o; }\n.#{$fa-css-prefix}-paperclip:before { content: $fa-var-paperclip; }\n.#{$fa-css-prefix}-save:before,\n.#{$fa-css-prefix}-floppy-o:before { content: $fa-var-floppy-o; }\n.#{$fa-css-prefix}-square:before { content: $fa-var-square; }\n.#{$fa-css-prefix}-reorder:before { content: $fa-var-reorder; }\n.#{$fa-css-prefix}-list-ul:before { content: $fa-var-list-ul; }\n.#{$fa-css-prefix}-list-ol:before { content: $fa-var-list-ol; }\n.#{$fa-css-prefix}-strikethrough:before { content: $fa-var-strikethrough; }\n.#{$fa-css-prefix}-underline:before { content: $fa-var-underline; }\n.#{$fa-css-prefix}-table:before { content: $fa-var-table; }\n.#{$fa-css-prefix}-magic:before { content: $fa-var-magic; }\n.#{$fa-css-prefix}-truck:before { content: $fa-var-truck; }\n.#{$fa-css-prefix}-pinterest:before { content: $fa-var-pinterest; }\n.#{$fa-css-prefix}-pinterest-square:before { content: $fa-var-pinterest-square; }\n.#{$fa-css-prefix}-google-plus-square:before { content: $fa-var-google-plus-square; }\n.#{$fa-css-prefix}-google-plus:before { content: $fa-var-google-plus; }\n.#{$fa-css-prefix}-money:before { content: $fa-var-money; }\n.#{$fa-css-prefix}-caret-down:before { content: $fa-var-caret-down; }\n.#{$fa-css-prefix}-caret-up:before { content: $fa-var-caret-up; }\n.#{$fa-css-prefix}-caret-left:before { content: $fa-var-caret-left; }\n.#{$fa-css-prefix}-caret-right:before { content: $fa-var-caret-right; }\n.#{$fa-css-prefix}-columns:before { content: $fa-var-columns; }\n.#{$fa-css-prefix}-unsorted:before,\n.#{$fa-css-prefix}-sort:before { content: $fa-var-sort; }\n.#{$fa-css-prefix}-sort-down:before,\n.#{$fa-css-prefix}-sort-asc:before { content: $fa-var-sort-asc; }\n.#{$fa-css-prefix}-sort-up:before,\n.#{$fa-css-prefix}-sort-desc:before { content: $fa-var-sort-desc; }\n.#{$fa-css-prefix}-envelope:before { content: $fa-var-envelope; }\n.#{$fa-css-prefix}-linkedin:before { content: $fa-var-linkedin; }\n.#{$fa-css-prefix}-rotate-left:before,\n.#{$fa-css-prefix}-undo:before { content: $fa-var-undo; }\n.#{$fa-css-prefix}-legal:before,\n.#{$fa-css-prefix}-gavel:before { content: $fa-var-gavel; }\n.#{$fa-css-prefix}-dashboard:before,\n.#{$fa-css-prefix}-tachometer:before { content: $fa-var-tachometer; }\n.#{$fa-css-prefix}-comment-o:before { content: $fa-var-comment-o; }\n.#{$fa-css-prefix}-comments-o:before { content: $fa-var-comments-o; }\n.#{$fa-css-prefix}-flash:before,\n.#{$fa-css-prefix}-bolt:before { content: $fa-var-bolt; }\n.#{$fa-css-prefix}-sitemap:before { content: $fa-var-sitemap; }\n.#{$fa-css-prefix}-umbrella:before { content: $fa-var-umbrella; }\n.#{$fa-css-prefix}-paste:before,\n.#{$fa-css-prefix}-clipboard:before { content: $fa-var-clipboard; }\n.#{$fa-css-prefix}-lightbulb-o:before { content: $fa-var-lightbulb-o; }\n.#{$fa-css-prefix}-exchange:before { content: $fa-var-exchange; }\n.#{$fa-css-prefix}-cloud-download:before { content: $fa-var-cloud-download; }\n.#{$fa-css-prefix}-cloud-upload:before { content: $fa-var-cloud-upload; }\n.#{$fa-css-prefix}-user-md:before { content: $fa-var-user-md; }\n.#{$fa-css-prefix}-stethoscope:before { content: $fa-var-stethoscope; }\n.#{$fa-css-prefix}-suitcase:before { content: $fa-var-suitcase; }\n.#{$fa-css-prefix}-bell-o:before { content: $fa-var-bell-o; }\n.#{$fa-css-prefix}-coffee:before { content: $fa-var-coffee; }\n.#{$fa-css-prefix}-cutlery:before { content: $fa-var-cutlery; }\n.#{$fa-css-prefix}-file-text-o:before { content: $fa-var-file-text-o; }\n.#{$fa-css-prefix}-building:before { content: $fa-var-building; }\n.#{$fa-css-prefix}-hospital:before { content: $fa-var-hospital; }\n.#{$fa-css-prefix}-ambulance:before { content: $fa-var-ambulance; }\n.#{$fa-css-prefix}-medkit:before { content: $fa-var-medkit; }\n.#{$fa-css-prefix}-fighter-jet:before { content: $fa-var-fighter-jet; }\n.#{$fa-css-prefix}-beer:before { content: $fa-var-beer; }\n.#{$fa-css-prefix}-h-square:before { content: $fa-var-h-square; }\n.#{$fa-css-prefix}-plus-square:before { content: $fa-var-plus-square; }\n.#{$fa-css-prefix}-angle-double-left:before { content: $fa-var-angle-double-left; }\n.#{$fa-css-prefix}-angle-double-right:before { content: $fa-var-angle-double-right; }\n.#{$fa-css-prefix}-angle-double-up:before { content: $fa-var-angle-double-up; }\n.#{$fa-css-prefix}-angle-double-down:before { content: $fa-var-angle-double-down; }\n.#{$fa-css-prefix}-angle-left:before { content: $fa-var-angle-left; }\n.#{$fa-css-prefix}-angle-right:before { content: $fa-var-angle-right; }\n.#{$fa-css-prefix}-angle-up:before { content: $fa-var-angle-up; }\n.#{$fa-css-prefix}-angle-down:before { content: $fa-var-angle-down; }\n.#{$fa-css-prefix}-desktop:before { content: $fa-var-desktop; }\n.#{$fa-css-prefix}-laptop:before { content: $fa-var-laptop; }\n.#{$fa-css-prefix}-tablet:before { content: $fa-var-tablet; }\n.#{$fa-css-prefix}-mobile-phone:before,\n.#{$fa-css-prefix}-mobile:before { content: $fa-var-mobile; }\n.#{$fa-css-prefix}-circle-o:before { content: $fa-var-circle-o; }\n.#{$fa-css-prefix}-quote-left:before { content: $fa-var-quote-left; }\n.#{$fa-css-prefix}-quote-right:before { content: $fa-var-quote-right; }\n.#{$fa-css-prefix}-spinner:before { content: $fa-var-spinner; }\n.#{$fa-css-prefix}-circle:before { content: $fa-var-circle; }\n.#{$fa-css-prefix}-mail-reply:before,\n.#{$fa-css-prefix}-reply:before { content: $fa-var-reply; }\n.#{$fa-css-prefix}-github-alt:before { content: $fa-var-github-alt; }\n.#{$fa-css-prefix}-folder-o:before { content: $fa-var-folder-o; }\n.#{$fa-css-prefix}-folder-open-o:before { content: $fa-var-folder-open-o; }\n.#{$fa-css-prefix}-expand-o:before { content: $fa-var-expand-o; }\n.#{$fa-css-prefix}-collapse-o:before { content: $fa-var-collapse-o; }\n.#{$fa-css-prefix}-smile-o:before { content: $fa-var-smile-o; }\n.#{$fa-css-prefix}-frown-o:before { content: $fa-var-frown-o; }\n.#{$fa-css-prefix}-meh-o:before { content: $fa-var-meh-o; }\n.#{$fa-css-prefix}-gamepad:before { content: $fa-var-gamepad; }\n.#{$fa-css-prefix}-keyboard-o:before { content: $fa-var-keyboard-o; }\n.#{$fa-css-prefix}-flag-o:before { content: $fa-var-flag-o; }\n.#{$fa-css-prefix}-flag-checkered:before { content: $fa-var-flag-checkered; }\n.#{$fa-css-prefix}-terminal:before { content: $fa-var-terminal; }\n.#{$fa-css-prefix}-code:before { content: $fa-var-code; }\n.#{$fa-css-prefix}-reply-all:before { content: $fa-var-reply-all; }\n.#{$fa-css-prefix}-mail-reply-all:before { content: $fa-var-mail-reply-all; }\n.#{$fa-css-prefix}-star-half-empty:before,\n.#{$fa-css-prefix}-star-half-full:before,\n.#{$fa-css-prefix}-star-half-o:before { content: $fa-var-star-half-o; }\n.#{$fa-css-prefix}-location-arrow:before { content: $fa-var-location-arrow; }\n.#{$fa-css-prefix}-crop:before { content: $fa-var-crop; }\n.#{$fa-css-prefix}-code-fork:before { content: $fa-var-code-fork; }\n.#{$fa-css-prefix}-unlink:before,\n.#{$fa-css-prefix}-chain-broken:before { content: $fa-var-chain-broken; }\n.#{$fa-css-prefix}-question:before { content: $fa-var-question; }\n.#{$fa-css-prefix}-info:before { content: $fa-var-info; }\n.#{$fa-css-prefix}-exclamation:before { content: $fa-var-exclamation; }\n.#{$fa-css-prefix}-superscript:before { content: $fa-var-superscript; }\n.#{$fa-css-prefix}-subscript:before { content: $fa-var-subscript; }\n.#{$fa-css-prefix}-eraser:before { content: $fa-var-eraser; }\n.#{$fa-css-prefix}-puzzle-piece:before { content: $fa-var-puzzle-piece; }\n.#{$fa-css-prefix}-microphone:before { content: $fa-var-microphone; }\n.#{$fa-css-prefix}-microphone-slash:before { content: $fa-var-microphone-slash; }\n.#{$fa-css-prefix}-shield:before { content: $fa-var-shield; }\n.#{$fa-css-prefix}-calendar-o:before { content: $fa-var-calendar-o; }\n.#{$fa-css-prefix}-fire-extinguisher:before { content: $fa-var-fire-extinguisher; }\n.#{$fa-css-prefix}-rocket:before { content: $fa-var-rocket; }\n.#{$fa-css-prefix}-maxcdn:before { content: $fa-var-maxcdn; }\n.#{$fa-css-prefix}-chevron-circle-left:before { content: $fa-var-chevron-circle-left; }\n.#{$fa-css-prefix}-chevron-circle-right:before { content: $fa-var-chevron-circle-right; }\n.#{$fa-css-prefix}-chevron-circle-up:before { content: $fa-var-chevron-circle-up; }\n.#{$fa-css-prefix}-chevron-circle-down:before { content: $fa-var-chevron-circle-down; }\n.#{$fa-css-prefix}-html5:before { content: $fa-var-html5; }\n.#{$fa-css-prefix}-css3:before { content: $fa-var-css3; }\n.#{$fa-css-prefix}-anchor:before { content: $fa-var-anchor; }\n.#{$fa-css-prefix}-unlock-o:before { content: $fa-var-unlock-o; }\n.#{$fa-css-prefix}-bullseye:before { content: $fa-var-bullseye; }\n.#{$fa-css-prefix}-ellipsis-horizontal:before { content: $fa-var-ellipsis-horizontal; }\n.#{$fa-css-prefix}-ellipsis-vertical:before { content: $fa-var-ellipsis-vertical; }\n.#{$fa-css-prefix}-rss-square:before { content: $fa-var-rss-square; }\n.#{$fa-css-prefix}-play-circle:before { content: $fa-var-play-circle; }\n.#{$fa-css-prefix}-ticket:before { content: $fa-var-ticket; }\n.#{$fa-css-prefix}-minus-square:before { content: $fa-var-minus-square; }\n.#{$fa-css-prefix}-minus-square-o:before { content: $fa-var-minus-square-o; }\n.#{$fa-css-prefix}-level-up:before { content: $fa-var-level-up; }\n.#{$fa-css-prefix}-level-down:before { content: $fa-var-level-down; }\n.#{$fa-css-prefix}-check-square:before { content: $fa-var-check-square; }\n.#{$fa-css-prefix}-pencil-square:before { content: $fa-var-pencil-square; }\n.#{$fa-css-prefix}-external-link-square:before { content: $fa-var-external-link-square; }\n.#{$fa-css-prefix}-share-square:before { content: $fa-var-share-square; }\n.#{$fa-css-prefix}-compass:before { content: $fa-var-compass; }\n.#{$fa-css-prefix}-toggle-down:before,\n.#{$fa-css-prefix}-caret-square-o-down:before { content: $fa-var-caret-square-o-down; }\n.#{$fa-css-prefix}-toggle-up:before,\n.#{$fa-css-prefix}-caret-square-o-up:before { content: $fa-var-caret-square-o-up; }\n.#{$fa-css-prefix}-toggle-right:before,\n.#{$fa-css-prefix}-caret-square-o-right:before { content: $fa-var-caret-square-o-right; }\n.#{$fa-css-prefix}-euro:before,\n.#{$fa-css-prefix}-eur:before { content: $fa-var-eur; }\n.#{$fa-css-prefix}-gbp:before { content: $fa-var-gbp; }\n.#{$fa-css-prefix}-dollar:before,\n.#{$fa-css-prefix}-usd:before { content: $fa-var-usd; }\n.#{$fa-css-prefix}-rupee:before,\n.#{$fa-css-prefix}-inr:before { content: $fa-var-inr; }\n.#{$fa-css-prefix}-cny:before,\n.#{$fa-css-prefix}-rmb:before,\n.#{$fa-css-prefix}-yen:before,\n.#{$fa-css-prefix}-jpy:before { content: $fa-var-jpy; }\n.#{$fa-css-prefix}-ruble:before,\n.#{$fa-css-prefix}-rouble:before,\n.#{$fa-css-prefix}-rub:before { content: $fa-var-rub; }\n.#{$fa-css-prefix}-won:before,\n.#{$fa-css-prefix}-krw:before { content: $fa-var-krw; }\n.#{$fa-css-prefix}-bitcoin:before,\n.#{$fa-css-prefix}-btc:before { content: $fa-var-btc; }\n.#{$fa-css-prefix}-file:before { content: $fa-var-file; }\n.#{$fa-css-prefix}-file-text:before { content: $fa-var-file-text; }\n.#{$fa-css-prefix}-sort-alpha-asc:before { content: $fa-var-sort-alpha-asc; }\n.#{$fa-css-prefix}-sort-alpha-desc:before { content: $fa-var-sort-alpha-desc; }\n.#{$fa-css-prefix}-sort-amount-asc:before { content: $fa-var-sort-amount-asc; }\n.#{$fa-css-prefix}-sort-amount-desc:before { content: $fa-var-sort-amount-desc; }\n.#{$fa-css-prefix}-sort-numeric-asc:before { content: $fa-var-sort-numeric-asc; }\n.#{$fa-css-prefix}-sort-numeric-desc:before { content: $fa-var-sort-numeric-desc; }\n.#{$fa-css-prefix}-thumbs-up:before { content: $fa-var-thumbs-up; }\n.#{$fa-css-prefix}-thumbs-down:before { content: $fa-var-thumbs-down; }\n.#{$fa-css-prefix}-youtube-square:before { content: $fa-var-youtube-square; }\n.#{$fa-css-prefix}-youtube:before { content: $fa-var-youtube; }\n.#{$fa-css-prefix}-xing:before { content: $fa-var-xing; }\n.#{$fa-css-prefix}-xing-square:before { content: $fa-var-xing-square; }\n.#{$fa-css-prefix}-youtube-play:before { content: $fa-var-youtube-play; }\n.#{$fa-css-prefix}-dropbox:before { content: $fa-var-dropbox; }\n.#{$fa-css-prefix}-stack-overflow:before { content: $fa-var-stack-overflow; }\n.#{$fa-css-prefix}-instagram:before { content: $fa-var-instagram; }\n.#{$fa-css-prefix}-flickr:before { content: $fa-var-flickr; }\n.#{$fa-css-prefix}-adn:before { content: $fa-var-adn; }\n.#{$fa-css-prefix}-bitbucket:before { content: $fa-var-bitbucket; }\n.#{$fa-css-prefix}-bitbucket-square:before { content: $fa-var-bitbucket-square; }\n.#{$fa-css-prefix}-tumblr:before { content: $fa-var-tumblr; }\n.#{$fa-css-prefix}-tumblr-square:before { content: $fa-var-tumblr-square; }\n.#{$fa-css-prefix}-long-arrow-down:before { content: $fa-var-long-arrow-down; }\n.#{$fa-css-prefix}-long-arrow-up:before { content: $fa-var-long-arrow-up; }\n.#{$fa-css-prefix}-long-arrow-left:before { content: $fa-var-long-arrow-left; }\n.#{$fa-css-prefix}-long-arrow-right:before { content: $fa-var-long-arrow-right; }\n.#{$fa-css-prefix}-apple:before { content: $fa-var-apple; }\n.#{$fa-css-prefix}-windows:before { content: $fa-var-windows; }\n.#{$fa-css-prefix}-android:before { content: $fa-var-android; }\n.#{$fa-css-prefix}-linux:before { content: $fa-var-linux; }\n.#{$fa-css-prefix}-dribbble:before { content: $fa-var-dribbble; }\n.#{$fa-css-prefix}-skype:before { content: $fa-var-skype; }\n.#{$fa-css-prefix}-foursquare:before { content: $fa-var-foursquare; }\n.#{$fa-css-prefix}-trello:before { content: $fa-var-trello; }\n.#{$fa-css-prefix}-female:before { content: $fa-var-female; }\n.#{$fa-css-prefix}-male:before { content: $fa-var-male; }\n.#{$fa-css-prefix}-gittip:before { content: $fa-var-gittip; }\n.#{$fa-css-prefix}-sun-o:before { content: $fa-var-sun-o; }\n.#{$fa-css-prefix}-moon-o:before { content: $fa-var-moon-o; }\n.#{$fa-css-prefix}-archive:before { content: $fa-var-archive; }\n.#{$fa-css-prefix}-bug:before { content: $fa-var-bug; }\n.#{$fa-css-prefix}-vk:before { content: $fa-var-vk; }\n.#{$fa-css-prefix}-weibo:before { content: $fa-var-weibo; }\n.#{$fa-css-prefix}-renren:before { content: $fa-var-renren; }\n.#{$fa-css-prefix}-pagelines:before { content: $fa-var-pagelines; }\n.#{$fa-css-prefix}-stack-exchange:before { content: $fa-var-stack-exchange; }\n.#{$fa-css-prefix}-arrow-circle-o-right:before { content: $fa-var-arrow-circle-o-right; }\n.#{$fa-css-prefix}-arrow-circle-o-left:before { content: $fa-var-arrow-circle-o-left; }\n.#{$fa-css-prefix}-toggle-left:before,\n.#{$fa-css-prefix}-caret-square-o-left:before { content: $fa-var-caret-square-o-left; }\n.#{$fa-css-prefix}-dot-circle-o:before { content: $fa-var-dot-circle-o; }\n.#{$fa-css-prefix}-wheelchair:before { content: $fa-var-wheelchair; }\n.#{$fa-css-prefix}-vimeo-square:before { content: $fa-var-vimeo-square; }\n.#{$fa-css-prefix}-turkish-lira:before,\n.#{$fa-css-prefix}-try:before { content: $fa-var-try; }\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/plugins/font-awesome/scss/_larger.scss",
    "content": "// Icon Sizes\n// -------------------------\n\n/* makes the font 33% larger relative to the icon container */\n.#{$fa-css-prefix}-lg {\n  font-size: (4em / 3);\n  line-height: (3em / 4);\n  vertical-align: -15%;\n}\n.#{$fa-css-prefix}-2x { font-size: 2em; }\n.#{$fa-css-prefix}-3x { font-size: 3em; }\n.#{$fa-css-prefix}-4x { font-size: 4em; }\n.#{$fa-css-prefix}-5x { font-size: 5em; }\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/plugins/font-awesome/scss/_list.scss",
    "content": "// List Icons\n// -------------------------\n\n.#{$fa-css-prefix}-ul {\n  padding-left: 0;\n  margin-left: $fa-li-width;\n  list-style-type: none;\n  > li { position: relative; }\n}\n.#{$fa-css-prefix}-li {\n  position: absolute;\n  left: -$fa-li-width;\n  width: $fa-li-width;\n  top: (2em / 14);\n  text-align: center;\n  &.#{$fa-css-prefix}-lg {\n    left: -$fa-li-width + (4em / 14);\n  }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/plugins/font-awesome/scss/_mixins.scss",
    "content": "// Mixins\n// --------------------------\n\n@mixin fa-icon-rotate($degrees, $rotation) {\n  filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=$rotation);\n  -webkit-transform: rotate($degrees);\n     -moz-transform: rotate($degrees);\n      -ms-transform: rotate($degrees);\n       -o-transform: rotate($degrees);\n          transform: rotate($degrees);\n}\n\n@mixin fa-icon-flip($horiz, $vert, $rotation) {\n  filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=$rotation);\n  -webkit-transform: scale($horiz, $vert);\n     -moz-transform: scale($horiz, $vert);\n      -ms-transform: scale($horiz, $vert);\n       -o-transform: scale($horiz, $vert);\n          transform: scale($horiz, $vert);\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/plugins/font-awesome/scss/_path.scss",
    "content": "/* FONT PATH\n * -------------------------- */\n\n@font-face {\n  font-family: 'FontAwesome';\n  src: url('#{$fa-font-path}/fontawesome-webfont.eot?v=#{$fa-version}');\n  src: url('#{$fa-font-path}/fontawesome-webfont.eot?#iefix&v=#{$fa-version}') format('embedded-opentype'),\n    url('#{$fa-font-path}/fontawesome-webfont.woff?v=#{$fa-version}') format('woff'),\n    url('#{$fa-font-path}/fontawesome-webfont.ttf?v=#{$fa-version}') format('truetype'),\n    url('#{$fa-font-path}/fontawesome-webfont.svg?v=#{$fa-version}#fontawesomeregular') format('svg');\n  //src: url('#{$fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts\n  font-weight: normal;\n  font-style: normal;\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/plugins/font-awesome/scss/_rotated-flipped.scss",
    "content": "// Rotated & Flipped Icons\n// -------------------------\n\n.#{$fa-css-prefix}-rotate-90  { @include fa-icon-rotate(90deg, 1);  }\n.#{$fa-css-prefix}-rotate-180 { @include fa-icon-rotate(180deg, 2); }\n.#{$fa-css-prefix}-rotate-270 { @include fa-icon-rotate(270deg, 3); }\n\n.#{$fa-css-prefix}-flip-horizontal { @include fa-icon-flip(-1, 1, 0); }\n.#{$fa-css-prefix}-flip-vertical   { @include fa-icon-flip(1, -1, 2); }\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/plugins/font-awesome/scss/_spinning.scss",
    "content": "// Spinning Icons\n// --------------------------\n\n.#{$fa-css-prefix}-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\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"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/plugins/font-awesome/scss/_stacked.scss",
    "content": "// Stacked Icons\n// -------------------------\n\n.#{$fa-css-prefix}-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-css-prefix}-stack-1x, .#{$fa-css-prefix}-stack-2x {\n  position: absolute;\n  left: 0;\n  width: 100%;\n  text-align: center;\n}\n.#{$fa-css-prefix}-stack-1x { line-height: inherit; }\n.#{$fa-css-prefix}-stack-2x { font-size: 2em; }\n.#{$fa-css-prefix}-inverse { color: $fa-inverse; }\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/plugins/font-awesome/scss/_variables.scss",
    "content": "// Variables\n// --------------------------\n\n$fa-font-path:        \"../fonts\" !default;\n//$fa-font-path:        \"//netdna.bootstrapcdn.com/font-awesome/4.0.1/fonts\" !default; // for referencing Bootstrap CDN font files directly\n$fa-css-prefix:       fa !default;\n$fa-version:          \"4.0.1\" !default;\n$fa-border-color:     #eee !default;\n$fa-inverse:          #fff !default;\n$fa-li-width:        (30em / 14) !default;\n\n$fa-var-glass: \"\\f000\";\n$fa-var-music: \"\\f001\";\n$fa-var-search: \"\\f002\";\n$fa-var-envelope-o: \"\\f003\";\n$fa-var-heart: \"\\f004\";\n$fa-var-star: \"\\f005\";\n$fa-var-star-o: \"\\f006\";\n$fa-var-user: \"\\f007\";\n$fa-var-film: \"\\f008\";\n$fa-var-th-large: \"\\f009\";\n$fa-var-th: \"\\f00a\";\n$fa-var-th-list: \"\\f00b\";\n$fa-var-check: \"\\f00c\";\n$fa-var-times: \"\\f00d\";\n$fa-var-search-plus: \"\\f00e\";\n$fa-var-search-minus: \"\\f010\";\n$fa-var-power-off: \"\\f011\";\n$fa-var-signal: \"\\f012\";\n$fa-var-cog: \"\\f013\";\n$fa-var-trash-o: \"\\f014\";\n$fa-var-home: \"\\f015\";\n$fa-var-file-o: \"\\f016\";\n$fa-var-clock-o: \"\\f017\";\n$fa-var-road: \"\\f018\";\n$fa-var-download: \"\\f019\";\n$fa-var-arrow-circle-o-down: \"\\f01a\";\n$fa-var-arrow-circle-o-up: \"\\f01b\";\n$fa-var-inbox: \"\\f01c\";\n$fa-var-play-circle-o: \"\\f01d\";\n$fa-var-repeat: \"\\f01e\";\n$fa-var-refresh: \"\\f021\";\n$fa-var-list-alt: \"\\f022\";\n$fa-var-lock: \"\\f023\";\n$fa-var-flag: \"\\f024\";\n$fa-var-headphones: \"\\f025\";\n$fa-var-volume-off: \"\\f026\";\n$fa-var-volume-down: \"\\f027\";\n$fa-var-volume-up: \"\\f028\";\n$fa-var-qrcode: \"\\f029\";\n$fa-var-barcode: \"\\f02a\";\n$fa-var-tag: \"\\f02b\";\n$fa-var-tags: \"\\f02c\";\n$fa-var-book: \"\\f02d\";\n$fa-var-bookmark: \"\\f02e\";\n$fa-var-print: \"\\f02f\";\n$fa-var-camera: \"\\f030\";\n$fa-var-font: \"\\f031\";\n$fa-var-bold: \"\\f032\";\n$fa-var-italic: \"\\f033\";\n$fa-var-text-height: \"\\f034\";\n$fa-var-text-width: \"\\f035\";\n$fa-var-align-left: \"\\f036\";\n$fa-var-align-center: \"\\f037\";\n$fa-var-align-right: \"\\f038\";\n$fa-var-align-justify: \"\\f039\";\n$fa-var-list: \"\\f03a\";\n$fa-var-outdent: \"\\f03b\";\n$fa-var-indent: \"\\f03c\";\n$fa-var-video-camera: \"\\f03d\";\n$fa-var-picture-o: \"\\f03e\";\n$fa-var-pencil: \"\\f040\";\n$fa-var-map-marker: \"\\f041\";\n$fa-var-adjust: \"\\f042\";\n$fa-var-tint: \"\\f043\";\n$fa-var-pencil-square-o: \"\\f044\";\n$fa-var-share-square-o: \"\\f045\";\n$fa-var-check-square-o: \"\\f046\";\n$fa-var-move: \"\\f047\";\n$fa-var-step-backward: \"\\f048\";\n$fa-var-fast-backward: \"\\f049\";\n$fa-var-backward: \"\\f04a\";\n$fa-var-play: \"\\f04b\";\n$fa-var-pause: \"\\f04c\";\n$fa-var-stop: \"\\f04d\";\n$fa-var-forward: \"\\f04e\";\n$fa-var-fast-forward: \"\\f050\";\n$fa-var-step-forward: \"\\f051\";\n$fa-var-eject: \"\\f052\";\n$fa-var-chevron-left: \"\\f053\";\n$fa-var-chevron-right: \"\\f054\";\n$fa-var-plus-circle: \"\\f055\";\n$fa-var-minus-circle: \"\\f056\";\n$fa-var-times-circle: \"\\f057\";\n$fa-var-check-circle: \"\\f058\";\n$fa-var-question-circle: \"\\f059\";\n$fa-var-info-circle: \"\\f05a\";\n$fa-var-crosshairs: \"\\f05b\";\n$fa-var-times-circle-o: \"\\f05c\";\n$fa-var-check-circle-o: \"\\f05d\";\n$fa-var-ban: \"\\f05e\";\n$fa-var-arrow-left: \"\\f060\";\n$fa-var-arrow-right: \"\\f061\";\n$fa-var-arrow-up: \"\\f062\";\n$fa-var-arrow-down: \"\\f063\";\n$fa-var-share: \"\\f064\";\n$fa-var-resize-full: \"\\f065\";\n$fa-var-resize-small: \"\\f066\";\n$fa-var-plus: \"\\f067\";\n$fa-var-minus: \"\\f068\";\n$fa-var-asterisk: \"\\f069\";\n$fa-var-exclamation-circle: \"\\f06a\";\n$fa-var-gift: \"\\f06b\";\n$fa-var-leaf: \"\\f06c\";\n$fa-var-fire: \"\\f06d\";\n$fa-var-eye: \"\\f06e\";\n$fa-var-eye-slash: \"\\f070\";\n$fa-var-exclamation-triangle: \"\\f071\";\n$fa-var-plane: \"\\f072\";\n$fa-var-calendar: \"\\f073\";\n$fa-var-random: \"\\f074\";\n$fa-var-comment: \"\\f075\";\n$fa-var-magnet: \"\\f076\";\n$fa-var-chevron-up: \"\\f077\";\n$fa-var-chevron-down: \"\\f078\";\n$fa-var-retweet: \"\\f079\";\n$fa-var-shopping-cart: \"\\f07a\";\n$fa-var-folder: \"\\f07b\";\n$fa-var-folder-open: \"\\f07c\";\n$fa-var-resize-vertical: \"\\f07d\";\n$fa-var-resize-horizontal: \"\\f07e\";\n$fa-var-bar-chart-o: \"\\f080\";\n$fa-var-twitter-square: \"\\f081\";\n$fa-var-facebook-square: \"\\f082\";\n$fa-var-camera-retro: \"\\f083\";\n$fa-var-key: \"\\f084\";\n$fa-var-cogs: \"\\f085\";\n$fa-var-comments: \"\\f086\";\n$fa-var-thumbs-o-up: \"\\f087\";\n$fa-var-thumbs-o-down: \"\\f088\";\n$fa-var-star-half: \"\\f089\";\n$fa-var-heart-o: \"\\f08a\";\n$fa-var-sign-out: \"\\f08b\";\n$fa-var-linkedin-square: \"\\f08c\";\n$fa-var-thumb-tack: \"\\f08d\";\n$fa-var-external-link: \"\\f08e\";\n$fa-var-sign-in: \"\\f090\";\n$fa-var-trophy: \"\\f091\";\n$fa-var-github-square: \"\\f092\";\n$fa-var-upload: \"\\f093\";\n$fa-var-lemon-o: \"\\f094\";\n$fa-var-phone: \"\\f095\";\n$fa-var-square-o: \"\\f096\";\n$fa-var-bookmark-o: \"\\f097\";\n$fa-var-phone-square: \"\\f098\";\n$fa-var-twitter: \"\\f099\";\n$fa-var-facebook: \"\\f09a\";\n$fa-var-github: \"\\f09b\";\n$fa-var-unlock: \"\\f09c\";\n$fa-var-credit-card: \"\\f09d\";\n$fa-var-rss: \"\\f09e\";\n$fa-var-hdd-o: \"\\f0a0\";\n$fa-var-bullhorn: \"\\f0a1\";\n$fa-var-bell: \"\\f0f3\";\n$fa-var-certificate: \"\\f0a3\";\n$fa-var-hand-o-right: \"\\f0a4\";\n$fa-var-hand-o-left: \"\\f0a5\";\n$fa-var-hand-o-up: \"\\f0a6\";\n$fa-var-hand-o-down: \"\\f0a7\";\n$fa-var-arrow-circle-left: \"\\f0a8\";\n$fa-var-arrow-circle-right: \"\\f0a9\";\n$fa-var-arrow-circle-up: \"\\f0aa\";\n$fa-var-arrow-circle-down: \"\\f0ab\";\n$fa-var-globe: \"\\f0ac\";\n$fa-var-wrench: \"\\f0ad\";\n$fa-var-tasks: \"\\f0ae\";\n$fa-var-filter: \"\\f0b0\";\n$fa-var-briefcase: \"\\f0b1\";\n$fa-var-fullscreen: \"\\f0b2\";\n$fa-var-group: \"\\f0c0\";\n$fa-var-link: \"\\f0c1\";\n$fa-var-cloud: \"\\f0c2\";\n$fa-var-flask: \"\\f0c3\";\n$fa-var-scissors: \"\\f0c4\";\n$fa-var-files-o: \"\\f0c5\";\n$fa-var-paperclip: \"\\f0c6\";\n$fa-var-floppy-o: \"\\f0c7\";\n$fa-var-square: \"\\f0c8\";\n$fa-var-reorder: \"\\f0c9\";\n$fa-var-list-ul: \"\\f0ca\";\n$fa-var-list-ol: \"\\f0cb\";\n$fa-var-strikethrough: \"\\f0cc\";\n$fa-var-underline: \"\\f0cd\";\n$fa-var-table: \"\\f0ce\";\n$fa-var-magic: \"\\f0d0\";\n$fa-var-truck: \"\\f0d1\";\n$fa-var-pinterest: \"\\f0d2\";\n$fa-var-pinterest-square: \"\\f0d3\";\n$fa-var-google-plus-square: \"\\f0d4\";\n$fa-var-google-plus: \"\\f0d5\";\n$fa-var-money: \"\\f0d6\";\n$fa-var-caret-down: \"\\f0d7\";\n$fa-var-caret-up: \"\\f0d8\";\n$fa-var-caret-left: \"\\f0d9\";\n$fa-var-caret-right: \"\\f0da\";\n$fa-var-columns: \"\\f0db\";\n$fa-var-sort: \"\\f0dc\";\n$fa-var-sort-asc: \"\\f0dd\";\n$fa-var-sort-desc: \"\\f0de\";\n$fa-var-envelope: \"\\f0e0\";\n$fa-var-linkedin: \"\\f0e1\";\n$fa-var-undo: \"\\f0e2\";\n$fa-var-gavel: \"\\f0e3\";\n$fa-var-tachometer: \"\\f0e4\";\n$fa-var-comment-o: \"\\f0e5\";\n$fa-var-comments-o: \"\\f0e6\";\n$fa-var-bolt: \"\\f0e7\";\n$fa-var-sitemap: \"\\f0e8\";\n$fa-var-umbrella: \"\\f0e9\";\n$fa-var-clipboard: \"\\f0ea\";\n$fa-var-lightbulb-o: \"\\f0eb\";\n$fa-var-exchange: \"\\f0ec\";\n$fa-var-cloud-download: \"\\f0ed\";\n$fa-var-cloud-upload: \"\\f0ee\";\n$fa-var-user-md: \"\\f0f0\";\n$fa-var-stethoscope: \"\\f0f1\";\n$fa-var-suitcase: \"\\f0f2\";\n$fa-var-bell-o: \"\\f0a2\";\n$fa-var-coffee: \"\\f0f4\";\n$fa-var-cutlery: \"\\f0f5\";\n$fa-var-file-text-o: \"\\f0f6\";\n$fa-var-building: \"\\f0f7\";\n$fa-var-hospital: \"\\f0f8\";\n$fa-var-ambulance: \"\\f0f9\";\n$fa-var-medkit: \"\\f0fa\";\n$fa-var-fighter-jet: \"\\f0fb\";\n$fa-var-beer: \"\\f0fc\";\n$fa-var-h-square: \"\\f0fd\";\n$fa-var-plus-square: \"\\f0fe\";\n$fa-var-angle-double-left: \"\\f100\";\n$fa-var-angle-double-right: \"\\f101\";\n$fa-var-angle-double-up: \"\\f102\";\n$fa-var-angle-double-down: \"\\f103\";\n$fa-var-angle-left: \"\\f104\";\n$fa-var-angle-right: \"\\f105\";\n$fa-var-angle-up: \"\\f106\";\n$fa-var-angle-down: \"\\f107\";\n$fa-var-desktop: \"\\f108\";\n$fa-var-laptop: \"\\f109\";\n$fa-var-tablet: \"\\f10a\";\n$fa-var-mobile: \"\\f10b\";\n$fa-var-circle-o: \"\\f10c\";\n$fa-var-quote-left: \"\\f10d\";\n$fa-var-quote-right: \"\\f10e\";\n$fa-var-spinner: \"\\f110\";\n$fa-var-circle: \"\\f111\";\n$fa-var-reply: \"\\f112\";\n$fa-var-github-alt: \"\\f113\";\n$fa-var-folder-o: \"\\f114\";\n$fa-var-folder-open-o: \"\\f115\";\n$fa-var-expand-o: \"\\f116\";\n$fa-var-collapse-o: \"\\f117\";\n$fa-var-smile-o: \"\\f118\";\n$fa-var-frown-o: \"\\f119\";\n$fa-var-meh-o: \"\\f11a\";\n$fa-var-gamepad: \"\\f11b\";\n$fa-var-keyboard-o: \"\\f11c\";\n$fa-var-flag-o: \"\\f11d\";\n$fa-var-flag-checkered: \"\\f11e\";\n$fa-var-terminal: \"\\f120\";\n$fa-var-code: \"\\f121\";\n$fa-var-reply-all: \"\\f122\";\n$fa-var-mail-reply-all: \"\\f122\";\n$fa-var-star-half-o: \"\\f123\";\n$fa-var-location-arrow: \"\\f124\";\n$fa-var-crop: \"\\f125\";\n$fa-var-code-fork: \"\\f126\";\n$fa-var-chain-broken: \"\\f127\";\n$fa-var-question: \"\\f128\";\n$fa-var-info: \"\\f129\";\n$fa-var-exclamation: \"\\f12a\";\n$fa-var-superscript: \"\\f12b\";\n$fa-var-subscript: \"\\f12c\";\n$fa-var-eraser: \"\\f12d\";\n$fa-var-puzzle-piece: \"\\f12e\";\n$fa-var-microphone: \"\\f130\";\n$fa-var-microphone-slash: \"\\f131\";\n$fa-var-shield: \"\\f132\";\n$fa-var-calendar-o: \"\\f133\";\n$fa-var-fire-extinguisher: \"\\f134\";\n$fa-var-rocket: \"\\f135\";\n$fa-var-maxcdn: \"\\f136\";\n$fa-var-chevron-circle-left: \"\\f137\";\n$fa-var-chevron-circle-right: \"\\f138\";\n$fa-var-chevron-circle-up: \"\\f139\";\n$fa-var-chevron-circle-down: \"\\f13a\";\n$fa-var-html5: \"\\f13b\";\n$fa-var-css3: \"\\f13c\";\n$fa-var-anchor: \"\\f13d\";\n$fa-var-unlock-o: \"\\f13e\";\n$fa-var-bullseye: \"\\f140\";\n$fa-var-ellipsis-horizontal: \"\\f141\";\n$fa-var-ellipsis-vertical: \"\\f142\";\n$fa-var-rss-square: \"\\f143\";\n$fa-var-play-circle: \"\\f144\";\n$fa-var-ticket: \"\\f145\";\n$fa-var-minus-square: \"\\f146\";\n$fa-var-minus-square-o: \"\\f147\";\n$fa-var-level-up: \"\\f148\";\n$fa-var-level-down: \"\\f149\";\n$fa-var-check-square: \"\\f14a\";\n$fa-var-pencil-square: \"\\f14b\";\n$fa-var-external-link-square: \"\\f14c\";\n$fa-var-share-square: \"\\f14d\";\n$fa-var-compass: \"\\f14e\";\n$fa-var-caret-square-o-down: \"\\f150\";\n$fa-var-caret-square-o-up: \"\\f151\";\n$fa-var-caret-square-o-right: \"\\f152\";\n$fa-var-eur: \"\\f153\";\n$fa-var-gbp: \"\\f154\";\n$fa-var-usd: \"\\f155\";\n$fa-var-inr: \"\\f156\";\n$fa-var-jpy: \"\\f157\";\n$fa-var-rub: \"\\f158\";\n$fa-var-krw: \"\\f159\";\n$fa-var-btc: \"\\f15a\";\n$fa-var-file: \"\\f15b\";\n$fa-var-file-text: \"\\f15c\";\n$fa-var-sort-alpha-asc: \"\\f15d\";\n$fa-var-sort-alpha-desc: \"\\f15e\";\n$fa-var-sort-amount-asc: \"\\f160\";\n$fa-var-sort-amount-desc: \"\\f161\";\n$fa-var-sort-numeric-asc: \"\\f162\";\n$fa-var-sort-numeric-desc: \"\\f163\";\n$fa-var-thumbs-up: \"\\f164\";\n$fa-var-thumbs-down: \"\\f165\";\n$fa-var-youtube-square: \"\\f166\";\n$fa-var-youtube: \"\\f167\";\n$fa-var-xing: \"\\f168\";\n$fa-var-xing-square: \"\\f169\";\n$fa-var-youtube-play: \"\\f16a\";\n$fa-var-dropbox: \"\\f16b\";\n$fa-var-stack-overflow: \"\\f16c\";\n$fa-var-instagram: \"\\f16d\";\n$fa-var-flickr: \"\\f16e\";\n$fa-var-adn: \"\\f170\";\n$fa-var-bitbucket: \"\\f171\";\n$fa-var-bitbucket-square: \"\\f172\";\n$fa-var-tumblr: \"\\f173\";\n$fa-var-tumblr-square: \"\\f174\";\n$fa-var-long-arrow-down: \"\\f175\";\n$fa-var-long-arrow-up: \"\\f176\";\n$fa-var-long-arrow-left: \"\\f177\";\n$fa-var-long-arrow-right: \"\\f178\";\n$fa-var-apple: \"\\f179\";\n$fa-var-windows: \"\\f17a\";\n$fa-var-android: \"\\f17b\";\n$fa-var-linux: \"\\f17c\";\n$fa-var-dribbble: \"\\f17d\";\n$fa-var-skype: \"\\f17e\";\n$fa-var-foursquare: \"\\f180\";\n$fa-var-trello: \"\\f181\";\n$fa-var-female: \"\\f182\";\n$fa-var-male: \"\\f183\";\n$fa-var-gittip: \"\\f184\";\n$fa-var-sun-o: \"\\f185\";\n$fa-var-moon-o: \"\\f186\";\n$fa-var-archive: \"\\f187\";\n$fa-var-bug: \"\\f188\";\n$fa-var-vk: \"\\f189\";\n$fa-var-weibo: \"\\f18a\";\n$fa-var-renren: \"\\f18b\";\n$fa-var-pagelines: \"\\f18c\";\n$fa-var-stack-exchange: \"\\f18d\";\n$fa-var-arrow-circle-o-right: \"\\f18e\";\n$fa-var-arrow-circle-o-left: \"\\f190\";\n$fa-var-caret-square-o-left: \"\\f191\";\n$fa-var-dot-circle-o: \"\\f192\";\n$fa-var-wheelchair: \"\\f193\";\n$fa-var-vimeo-square: \"\\f194\";\n$fa-var-try: \"\\f195\";\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/plugins/font-awesome/scss/font-awesome.scss",
    "content": "/*!\n *  Font Awesome 4.0.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 \"larger\";\n@import \"fixed-width\";\n@import \"list\";\n@import \"bordered-pulled\";\n@import \"spinning\";\n@import \"rotated-flipped\";\n@import \"stacked\";\n@import \"icons\";\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/scripts/app.js",
    "content": "/**\nCore script to handle the entire theme and core functions\n**/\nvar App = function () {\n\n    // IE mode\n    var isRTL = false;\n    var isIE8 = false;\n    var isIE9 = false;\n    var isIE10 = false;\n\n    var sidebarWidth = 225;\n    var sidebarCollapsedWidth = 35;\n\n    var responsiveHandlers = [];\n\n    // theme layout color set\n    var layoutColorCodes = {\n        'blue': '#4b8df8',\n        'red': '#e02222',\n        'green': '#35aa47',\n        'purple': '#852b99',\n        'grey': '#555555',\n        'light-grey': '#fafafa',\n        'yellow': '#ffb848'\n    };\n\n    // To get the correct viewport width based on  http://andylangton.co.uk/articles/javascript/get-viewport-size-javascript/\n    var _getViewPort = function () {\n        var e = window, a = 'inner';\n        if (!('innerWidth' in window)) {\n            a = 'client';\n            e = document.documentElement || document.body;\n        }\n        return {\n            width: e[a + 'Width'],\n            height: e[a + 'Height']\n        }\n    }\n\n    // initializes main settings\n    var handleInit = function () {\n\n        if ($('body').css('direction') === 'rtl') {\n            isRTL = true;\n        }\n\n        isIE8 = !! navigator.userAgent.match(/MSIE 8.0/);\n        isIE9 = !! navigator.userAgent.match(/MSIE 9.0/);\n        isIE10 = !! navigator.userAgent.match(/MSIE 10.0/);\n\n        if (isIE10) {\n            jQuery('html').addClass('ie10'); // detect IE10 version\n        }\n        \n        if (isIE10 || isIE9 || isIE8) {\n            jQuery('html').addClass('ie'); // detect IE10 version\n        }\n\n        /*\n          Virtual keyboards:\n          Also, note that if you're using inputs in your modal – iOS has a rendering bug which doesn't \n          update the position of fixed elements when the virtual keyboard is triggered  \n        */\n        var deviceAgent = navigator.userAgent.toLowerCase();\n        if (deviceAgent.match(/(iphone|ipod|ipad)/)) {\n            $(document).on('focus', 'input, textarea', function () {\n                $('.header').hide();\n                $('.footer').hide();\n            });\n            $(document).on('blur', 'input, textarea', function () {\n                $('.header').show();\n                $('.footer').show();\n            });\n        }\n    }\n\n    var handleSidebarState = function () {\n        // remove sidebar toggler if window width smaller than 992(for tablet and phone mode)\n        var viewport = _getViewPort();\n        if (viewport.width < 992) {\n            $('body').removeClass(\"page-sidebar-closed\");\n        }\n    }\n\n    // runs callback functions set by App.addResponsiveHandler().\n    var runResponsiveHandlers = function () {\n        // reinitialize other subscribed elements\n        for (var i in responsiveHandlers) {\n            var each = responsiveHandlers[i];\n            each.call();\n        }\n    }\n\n    // reinitialize the laypot on window resize\n    var handleResponsive = function () {\n        handleSidebarState();\n        handleSidebarAndContentHeight();\n        handleFixedSidebar();\n        runResponsiveHandlers();\n    }\n\n    // initialize the layout on page load\n    var handleResponsiveOnInit = function () {\n        handleSidebarState();\n        handleSidebarAndContentHeight();\n    }\n\n    // handle the layout reinitialization on window resize\n    var handleResponsiveOnResize = function () {\n        var resize;\n        if (isIE8) {\n            var currheight;\n            $(window).resize(function () {\n                if (currheight == document.documentElement.clientHeight) {\n                    return; //quite event since only body resized not window.\n                }\n                if (resize) {\n                    clearTimeout(resize);\n                }\n                resize = setTimeout(function () {\n                    handleResponsive();\n                }, 50); // wait 50ms until window resize finishes.                \n                currheight = document.documentElement.clientHeight; // store last body client height\n            });\n        } else {\n            $(window).resize(function () {\n                if (resize) {\n                    clearTimeout(resize);\n                }\n                resize = setTimeout(function () {\n                    handleResponsive();\n                }, 50); // wait 50ms until window resize finishes.\n            });\n        }\n    }\n\n    //* BEGIN:CORE HANDLERS *//\n    // this function handles responsive layout on screen size resize or mobile device rotate.\n\n    // Set proper height for sidebar and content. The content and sidebar height must be synced always.\n    var handleSidebarAndContentHeight = function () {\n        var content = $('.page-content');\n        var sidebar = $('.page-sidebar');\n        var body = $('body');\n        var height;\n\n        if (body.hasClass(\"page-footer-fixed\") === true && body.hasClass(\"page-sidebar-fixed\") === false) {\n            var available_height = $(window).height() - $('.footer').outerHeight();\n            if (content.height() < available_height) {\n                content.attr('style', 'min-height:' + available_height + 'px !important');\n            }\n        } else {\n            if (body.hasClass('page-sidebar-fixed')) {\n                height = _calculateFixedSidebarViewportHeight();\n            } else {\n                height = sidebar.height() + 20;\n            }\n            if (height >= content.height()) {\n                content.attr('style', 'min-height:' + height + 'px !important');\n            }\n        }\n    }\n\n    // Handle sidebar menu\n    var handleSidebarMenu = function () {\n        jQuery('.page-sidebar').on('click', 'li > a', function (e) {\n            if ($(this).next().hasClass('sub-menu') == false) {\n                if ($('.btn-navbar').hasClass('collapsed') == false) {\n                    $('.btn-navbar').click();\n                }\n                return;\n            }\n\n            if ($(this).next().hasClass('sub-menu.always-open')) {\n                return;\n            }\n\n            var parent = $(this).parent().parent();\n            var the = $(this);\n\n            parent.children('li.open').children('a').children('.arrow').removeClass('open');\n            parent.children('li.open').children('.sub-menu').slideUp(200);\n            parent.children('li.open').removeClass('open');\n\n            var sub = jQuery(this).next();\n            var slideOffeset = -200;\n            var slideSpeed = 200;\n\n            if (sub.is(\":visible\")) {\n                jQuery('.arrow', jQuery(this)).removeClass(\"open\");\n                jQuery(this).parent().removeClass(\"open\");\n                sub.slideUp(slideSpeed, function () {\n                    if ($('body').hasClass('page-sidebar-fixed') == false && $('body').hasClass('page-sidebar-closed') == false) {\n                        App.scrollTo(the, slideOffeset);\n                    }\n                    handleSidebarAndContentHeight();\n                });\n            } else {\n                jQuery('.arrow', jQuery(this)).addClass(\"open\");\n                jQuery(this).parent().addClass(\"open\");\n                sub.slideDown(slideSpeed, function () {\n                    if ($('body').hasClass('page-sidebar-fixed') == false && $('body').hasClass('page-sidebar-closed') == false) {\n                        App.scrollTo(the, slideOffeset);\n                    }\n                    handleSidebarAndContentHeight();\n                });\n            }\n\n            e.preventDefault();\n        });\n\n        // handle ajax links\n        jQuery('.page-sidebar').on('click', ' li > a.ajaxify', function (e) {\n            e.preventDefault();\n            App.scrollTop();\n\n            var url = $(this).attr(\"href\");\n            var menuContainer = jQuery('.page-sidebar ul');\n            var pageContent = $('.page-content');\n            var pageContentBody = $('.page-content .page-content-body');\n\n            menuContainer.children('li.active').removeClass('active');\n            menuContainer.children('arrow.open').removeClass('open');\n\n            $(this).parents('li').each(function () {\n                $(this).addClass('active');\n                $(this).children('a > span.arrow').addClass('open');\n            });\n            $(this).parents('li').addClass('active');\n\n            App.blockUI(pageContent, false);\n\n            $.ajax({\n                type: \"GET\",\n                cache: false,\n                url: url,\n                dataType: \"do\",\n                success: function (res) {\n                    App.unblockUI(pageContent);\n                    pageContentBody.html(res);\n                    App.fixContentHeight(); // fix content height\n                    App.initAjax(); // initialize core stuff\n                },\n                error: function (xhr, ajaxOptions, thrownError) {\n                    pageContentBody.html('<h4>Could not load the requested content.</h4>');\n                    App.unblockUI(pageContent);\n                },\n                async: false\n            });\n        });\n    }\n\n    // Helper function to calculate sidebar height for fixed sidebar layout.\n    var _calculateFixedSidebarViewportHeight = function () {\n        var sidebarHeight = $(window).height() - $('.header').height() + 1;\n        if ($('body').hasClass(\"page-footer-fixed\")) {\n            sidebarHeight = sidebarHeight - $('.footer').outerHeight();\n        }\n\n        return sidebarHeight;\n    }\n\n    // Handles fixed sidebar\n    var handleFixedSidebar = function () {\n        var menu = $('.page-sidebar-menu');\n\n        if (menu.parent('.slimScrollDiv').size() === 1) { // destroy existing instance before updating the height\n            menu.slimScroll({\n                destroy: true\n            });\n            menu.removeAttr('style');\n            $('.page-sidebar').removeAttr('style');\n        }\n\n        if ($('.page-sidebar-fixed').size() === 0) {\n            handleSidebarAndContentHeight();\n            return;\n        }\n\n        var viewport = _getViewPort();\n        if (viewport.width >= 992) {\n            var sidebarHeight = _calculateFixedSidebarViewportHeight();\n\n            menu.slimScroll({\n                size: '7px',\n                color: '#a1b2bd',\n                opacity: .3,\n                position: isRTL ? 'left' : 'right',\n                height: sidebarHeight,\n                allowPageScroll: false,\n                disableFadeOut: false\n            });\n            handleSidebarAndContentHeight();\n        }\n    }\n\n    // Handles the sidebar menu hover effect for fixed sidebar.\n    var handleFixedSidebarHoverable = function () {\n        if ($('body').hasClass('page-sidebar-fixed') === false) {\n            return;\n        }\n\n        $('.page-sidebar').off('mouseenter').on('mouseenter', function () {\n            var body = $('body');\n\n            if ((body.hasClass('page-sidebar-closed') === false || body.hasClass('page-sidebar-fixed') === false) || $(this).hasClass('page-sidebar-hovering')) {\n                return;\n            }\n\n            body.removeClass('page-sidebar-closed').addClass('page-sidebar-hover-on');\n            $(this).addClass('page-sidebar-hovering');\n            $(this).animate({\n                width: sidebarWidth\n            }, 400, '', function () {\n                $(this).removeClass('page-sidebar-hovering');\n            });\n        });\n\n        $('.page-sidebar').off('mouseleave').on('mouseleave', function () {\n            var body = $('body');\n\n            if ((body.hasClass('page-sidebar-hover-on') === false || body.hasClass('page-sidebar-fixed') === false) || $(this).hasClass('page-sidebar-hovering')) {\n                return;\n            }\n\n            $(this).addClass('page-sidebar-hovering');\n            $(this).animate({\n                width: sidebarCollapsedWidth\n            }, 400, '', function () {\n                $('body').addClass('page-sidebar-closed').removeClass('page-sidebar-hover-on');\n                $(this).removeClass('page-sidebar-hovering');\n            });\n        });\n    }\n\n    // Handles sidebar toggler to close/hide the sidebar.\n    var handleSidebarToggler = function () {\n        var viewport = _getViewPort();\n        if ($.cookie('sidebar_closed') === '1' && viewport.width >= 992) {\n            $('body').addClass('page-sidebar-closed');\n        }\n\n        // handle sidebar show/hide\n        $('.page-sidebar, .header').on('click', '.sidebar-toggler', function (e) {\n            var body = $('body');\n            var sidebar = $('.page-sidebar');\n\n            if ((body.hasClass(\"page-sidebar-hover-on\") && body.hasClass('page-sidebar-fixed')) || sidebar.hasClass('page-sidebar-hovering')) {\n                body.removeClass('page-sidebar-hover-on');\n                sidebar.css('width', '').hide().show();\n                $.cookie('sidebar_closed', '0');\n                e.stopPropagation();\n                runResponsiveHandlers();\n                return;\n            }\n\n            $(\".sidebar-search\", sidebar).removeClass(\"open\");\n\n            if (body.hasClass(\"page-sidebar-closed\")) {\n                body.removeClass(\"page-sidebar-closed\");\n                if (body.hasClass('page-sidebar-fixed')) {\n                    sidebar.css('width', '');\n                }\n                $.cookie('sidebar_closed', '0');\n            } else {\n                body.addClass(\"page-sidebar-closed\");\n                $.cookie('sidebar_closed', '1');\n            }\n            runResponsiveHandlers();\n        });\n\n        // handle the search bar close\n        $('.page-sidebar').on('click', '.sidebar-search .remove', function (e) {\n            e.preventDefault();\n            $('.sidebar-search').removeClass(\"open\");\n        });\n\n        // handle the search query submit on enter press\n        $('.page-sidebar').on('keypress', '.sidebar-search input', function (e) {\n            if (e.which == 13) {\n                $('.sidebar-search').submit();\n                return false; //<---- Add this line\n            }\n        });\n\n        // handle the search submit\n        $('.sidebar-search .submit').on('click', function (e) {\n            e.preventDefault();\n            if ($('body').hasClass(\"page-sidebar-closed\")) {\n                if ($('.sidebar-search').hasClass('open') == false) {\n                    if ($('.page-sidebar-fixed').size() === 1) {\n                        $('.page-sidebar .sidebar-toggler').click(); //trigger sidebar toggle button\n                    }\n                    $('.sidebar-search').addClass(\"open\");\n                } else {\n                    $('.sidebar-search').submit();\n                }\n            } else {\n                $('.sidebar-search').submit();\n            }\n        });\n    }\n\n    // Handles the horizontal menu\n    var handleHorizontalMenu = function () {\n        //handle hor menu search form toggler click\n        $('.header').on('click', '.hor-menu .hor-menu-search-form-toggler', function (e) {\n            if ($(this).hasClass('off')) {\n                $(this).removeClass('off');\n                $('.header .hor-menu .search-form').hide();\n            } else {\n                $(this).addClass('off');\n                $('.header .hor-menu .search-form').show();\n            }\n            e.preventDefault();\n        });\n\n        //handle hor menu search button click\n        $('.header').on('click', '.hor-menu .search-form .btn', function (e) {\n            $('.form-search').submit();\n            e.preventDefault();\n        });\n\n        //handle hor menu search form on enter press\n        $('.header').on('keypress', '.hor-menu .search-form input', function (e) {\n            if (e.which == 13) {\n                $('.form-search').submit();\n                return false;\n            }\n        });\n    }\n\n    // Handles the go to top button at the footer\n    var handleGoTop = function () {\n        /* set variables locally for increased performance */\n        jQuery('.footer').on('click', '.go-top', function (e) {\n            App.scrollTo();\n            e.preventDefault();\n        });\n    }\n\n    // Handles portlet tools & actions\n    var handlePortletTools = function () {\n        jQuery('body').on('click', '.portlet > .portlet-title > .tools > a.remove', function (e) {\n            e.preventDefault();\n            jQuery(this).closest(\".portlet\").remove();\n        });\n\n        jQuery('body').on('click', '.portlet > .portlet-title > .tools > a.reload', function (e) {\n            e.preventDefault();\n            var el = jQuery(this).closest(\".portlet\").children(\".portlet-body\");\n            App.blockUI(el);\n            window.setTimeout(function () {\n                App.unblockUI(el);\n            }, 1000);\n        });\n\n        jQuery('body').on('click', '.portlet > .portlet-title > .tools > .collapse, .portlet .portlet-title > .tools > .expand', function (e) {\n            e.preventDefault();\n            var el = jQuery(this).closest(\".portlet\").children(\".portlet-body\");\n            if (jQuery(this).hasClass(\"collapse\")) {\n                jQuery(this).removeClass(\"collapse\").addClass(\"expand\");\n                el.slideUp(200);\n            } else {\n                jQuery(this).removeClass(\"expand\").addClass(\"collapse\");\n                el.slideDown(200);\n            }\n        });\n    }\n\n    // Handles custom checkboxes & radios using jQuery Uniform plugin\n    var handleUniform = function () {\n        if (!jQuery().uniform) {\n            return;\n        }\n        var test = $(\"input[type=checkbox]:not(.toggle), input[type=radio]:not(.toggle, .star)\");\n        if (test.size() > 0) {\n            test.each(function () {\n                if ($(this).parents(\".checker\").size() == 0) {\n                    $(this).show();\n                    $(this).uniform();\n                }\n            });\n        }\n    }\n\n    // Handles Bootstrap Accordions.\n    var handleAccordions = function () {\n        var lastClicked;\n        //add scrollable class name if you need scrollable panes\n        jQuery('body').on('click', '.accordion.scrollable .accordion-toggle', function () {\n            lastClicked = jQuery(this);\n        }); //move to faq section\n\n        jQuery('body').on('show.bs.collapse', '.accordion.scrollable', function () {\n            jQuery('html,body').animate({\n                scrollTop: lastClicked.offset().top - 150\n            }, 'slow');\n        });\n    }\n\n    // Handles Bootstrap Tabs.\n    var handleTabs = function () {\n        // fix content height on tab click\n        $('body').on('shown.bs.tab', '.nav.nav-tabs', function () {\n            handleSidebarAndContentHeight();\n        });\n\n        //activate tab if tab id provided in the URL\n        if (location.hash) {\n            var tabid = location.hash.substr(1);\n            $('a[href=\"#' + tabid + '\"]').parents('.tab-pane:hidden').each(function(){\n                var tabid = $(this).attr(\"id\");\n                $('a[href=\"#' + tabid + '\"]').click();    \n            });            \n            $('a[href=\"#' + tabid + '\"]').click();\n        }\n    }\n\n    // Handles Bootstrap Modals.\n    var handleModals = function () {\n        // fix stackable modal issue: when 2 or more modals opened, closing one of modal will remove .modal-open class. \n        $('body').on('hide.bs.modal', function () {\n           if ($('.modal:visible').size() > 1 && $('html').hasClass('modal-open') == false) {\n              $('html').addClass('modal-open');\n           } else if ($('.modal:visible').size() <= 1) {\n              $('html').removeClass('modal-open');\n           }\n        });\n            \n        $('body').on('show.bs.modal', '.modal', function () {\n            if ($(this).hasClass(\"modal-scroll\")) {\n                $('body').addClass(\"modal-open-noscroll\");\n            } \n        });\n\n        $('body').on('hide.bs.modal', '.modal', function () {\n            $('body').removeClass(\"modal-open-noscroll\");\n        });\n    }\n\n    // Handles Bootstrap Tooltips.\n    var handleTooltips = function () {\n       jQuery('.tooltips').tooltip();\n    }\n\n    // Handles Bootstrap Dropdowns\n    var handleDropdowns = function () {\n        /*\n          For touch supported devices disable the \n          hoverable dropdowns - data-hover=\"dropdown\"  \n        */\n        if (App.isTouchDevice()) {\n            $('[data-hover=\"dropdown\"]').each(function(){\n                $(this).parent().off(\"hover\");\n                $(this).off(\"hover\");\n            });\n        }\n        /*\n          Hold dropdown on click  \n        */\n        $('body').on('click', '.dropdown-menu.hold-on-click', function (e) {\n            e.stopPropagation();\n        });\n    }\n\n    // Handle Hower Dropdowns\n    var handleDropdownHover = function () {\n        $('[data-hover=\"dropdown\"]').dropdownHover();\n    }\n\n    var handleAlerts = function () {\n        $('body').on('click', '[data-close=\"alert\"]', function(e){\n            $(this).parent('.alert').hide();\n            e.preventDefault();\n        });\n    }\n\n    // Handles Bootstrap Popovers\n\n    // last popep popover\n    var lastPopedPopover;\n\n    var handlePopovers = function () {\n        jQuery('.popovers').popover();\n\n        // close last poped popover\n\n        $(document).on('click.bs.popover.data-api', function (e) {\n            if (lastPopedPopover) {\n                lastPopedPopover.popover('hide');\n            }\n        });\n    }\n\n    // Handles scrollable contents using jQuery SlimScroll plugin.\n    var handleScrollers = function () {\n        $('.scroller').each(function () {\n            var height;\n            if ($(this).attr(\"data-height\")) {\n                height = $(this).attr(\"data-height\");\n            } else {\n                height = $(this).css('height');\n            }\n            $(this).slimScroll({\n                size: '7px',\n                color: ($(this).attr(\"data-handle-color\")  ? $(this).attr(\"data-handle-color\") : '#a1b2bd'),\n                railColor: ($(this).attr(\"data-rail-color\")  ? $(this).attr(\"data-rail-color\") : '#333'),\n                position: isRTL ? 'left' : 'right',\n                height: height,\n                alwaysVisible: ($(this).attr(\"data-always-visible\") == \"1\" ? true : false),\n                railVisible: ($(this).attr(\"data-rail-visible\") == \"1\" ? true : false),\n                disableFadeOut: true\n            });\n        });\n    }\n\n    // Handles Image Preview using jQuery Fancybox plugin\n    var handleFancybox = function () {\n        if (!jQuery.fancybox) {\n            return;\n        }\n\n        if (jQuery(\".fancybox-button\").size() > 0) {\n            jQuery(\".fancybox-button\").fancybox({\n                groupAttr: 'data-rel',\n                prevEffect: 'none',\n                nextEffect: 'none',\n                closeBtn: true,\n                helpers: {\n                    title: {\n                        type: 'inside'\n                    }\n                }\n            });\n        }\n    }\n\n    // Fix input placeholder issue for IE8 and IE9\n    var handleFixInputPlaceholderForIE = function () {\n        //fix html5 placeholder attribute for ie7 & ie8\n        if (isIE8 || isIE9) { // ie8 & ie9\n            // this is html5 placeholder fix for inputs, inputs with placeholder-no-fix class will be skipped(e.g: we need this for password fields)\n            jQuery('input[placeholder]:not(.placeholder-no-fix), textarea[placeholder]:not(.placeholder-no-fix)').each(function () {\n\n                var input = jQuery(this);\n\n                if (input.val() == '' && input.attr(\"placeholder\") != '') {\n                    input.addClass(\"placeholder\").val(input.attr('placeholder'));\n                }\n\n                input.focus(function () {\n                    if (input.val() == input.attr('placeholder')) {\n                        input.val('');\n                    }\n                });\n\n                input.blur(function () {\n                    if (input.val() == '' || input.val() == input.attr('placeholder')) {\n                        input.val(input.attr('placeholder'));\n                    }\n                });\n            });\n        }\n    }\n\n    // Handle full screen mode toggle\n    var handleFullScreenMode = function() {\n        // mozfullscreenerror event handler\n       \n        // toggle full screen\n        function toggleFullScreen() {\n          if (!document.fullscreenElement &&    // alternative standard method\n              !document.mozFullScreenElement && !document.webkitFullscreenElement) {  // current working methods\n            if (document.documentElement.requestFullscreen) {\n              document.documentElement.requestFullscreen();\n            } else if (document.documentElement.mozRequestFullScreen) {\n              document.documentElement.mozRequestFullScreen();\n            } else if (document.documentElement.webkitRequestFullscreen) {\n              document.documentElement.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);\n            }\n          } else {\n            if (document.cancelFullScreen) {\n              document.cancelFullScreen();\n            } else if (document.mozCancelFullScreen) {\n              document.mozCancelFullScreen();\n            } else if (document.webkitCancelFullScreen) {\n              document.webkitCancelFullScreen();\n            }\n          }\n        }\n\n        $('#trigger_fullscreen').click(function() {\n            toggleFullScreen();\n        });\n    }\n\n    // Handle Select2 Dropdowns\n    var handleSelect2 = function() {\n        if (jQuery().select2) {\n            $('.select2me').select2({\n                placeholder: \"Select\",\n                allowClear: true\n            });\n        }\n    }\n\n    // Handle Theme Settings\n    var handleTheme = function () {\n\n        var panel = $('.theme-panel');\n\n        if ($('body').hasClass('page-boxed') == false) {\n            $('.layout-option', panel).val(\"fluid\");\n        }\n\n        $('.sidebar-option', panel).val(\"default\");\n        $('.header-option', panel).val(\"fixed\");\n        $('.footer-option', panel).val(\"default\");\n\n        //handle theme layout\n        var resetLayout = function () {\n            $(\"body\").\n            removeClass(\"page-boxed\").\n            removeClass(\"page-footer-fixed\").\n            removeClass(\"page-sidebar-fixed\").\n            removeClass(\"page-header-fixed\");\n\n            $('.header > .header-inner').removeClass(\"container\");\n\n            if ($('.page-container').parent(\".container\").size() === 1) {\n                $('.page-container').insertAfter('body > .clearfix');\n            }\n\n            if ($('.footer > .container').size() === 1) {\n                $('.footer').html($('.footer > .container').html());\n            } else if ($('.footer').parent(\".container\").size() === 1) {\n                $('.footer').insertAfter('.page-container');\n            }\n\n            $('body > .container').remove();\n        }\n\n        var lastSelectedLayout = '';\n\n        var setLayout = function () {\n\n            var layoutOption = $('.layout-option', panel).val();\n            var sidebarOption = $('.sidebar-option', panel).val();\n            var headerOption = $('.header-option', panel).val();\n            var footerOption = $('.footer-option', panel).val();\n\n            if (sidebarOption == \"fixed\" && headerOption == \"default\") {\n                alert('Default Header with Fixed Sidebar option is not supported. Proceed with Fixed Header with Fixed Sidebar.');\n                $('.header-option', panel).val(\"fixed\");\n                $('.sidebar-option', panel).val(\"fixed\");\n                sidebarOption = 'fixed';\n                headerOption = 'fixed';\n            }\n\n            resetLayout(); // reset layout to default state\n\n            if (layoutOption === \"boxed\") {\n                $(\"body\").addClass(\"page-boxed\");\n\n                // set header\n                $('.header > .header-inner').addClass(\"container\");\n                var cont = $('body > .clearfix').after('<div class=\"container\"></div>');\n\n                // set content\n                $('.page-container').appendTo('body > .container');\n\n                // set footer\n                if (footerOption === 'fixed') {\n                    $('.footer').html('<div class=\"container\">' + $('.footer').html() + '</div>');\n                } else {\n                    $('.footer').appendTo('body > .container');\n                }\n            }\n\n            if (lastSelectedLayout != layoutOption) {\n                //layout changed, run responsive handler:\n                runResponsiveHandlers();\n            }\n            lastSelectedLayout = layoutOption;\n\n            //header\n            if (headerOption === 'fixed') {\n                $(\"body\").addClass(\"page-header-fixed\");\n                $(\".header\").removeClass(\"navbar-static-top\").addClass(\"navbar-fixed-top\");\n            } else {\n                $(\"body\").removeClass(\"page-header-fixed\");\n                $(\".header\").removeClass(\"navbar-fixed-top\").addClass(\"navbar-static-top\");\n            }\n\n            //sidebar\n            if (sidebarOption === 'fixed') {\n                $(\"body\").addClass(\"page-sidebar-fixed\");\n            } else {\n                $(\"body\").removeClass(\"page-sidebar-fixed\");\n            }\n\n            //footer \n            if (footerOption === 'fixed') {\n                $(\"body\").addClass(\"page-footer-fixed\");\n            } else {\n                $(\"body\").removeClass(\"page-footer-fixed\");\n            }\n\n            handleSidebarAndContentHeight(); // fix content height            \n            handleFixedSidebar(); // reinitialize fixed sidebar\n            handleFixedSidebarHoverable(); // reinitialize fixed sidebar hover effect\n        }\n\n        // handle theme colors\n        var setColor = function (color) {\n            $('#style_color').attr(\"href\", \"assets/css/themes/\" + color + \".css\");\n            $.cookie('style_color', color);\n        }\n\n        $('.toggler', panel).click(function () {\n            $('.toggler').hide();\n            $('.toggler-close').show();\n            $('.theme-panel > .theme-options').show();\n        });\n\n        $('.toggler-close', panel).click(function () {\n            $('.toggler').show();\n            $('.toggler-close').hide();\n            $('.theme-panel > .theme-options').hide();\n        });\n\n        $('.theme-colors > ul > li', panel).click(function () {\n            var color = $(this).attr(\"data-style\");\n            setColor(color);\n            $('ul > li', panel).removeClass(\"current\");\n            $(this).addClass(\"current\");\n        });\n\n        $('.layout-option, .header-option, .sidebar-option, .footer-option', panel).change(setLayout);\n\n        if ($.cookie('style_color')) {\n            setColor($.cookie('style_color'));\n        }\n    }\n\n    //* END:CORE HANDLERS *//\n\n    return {\n\n        //main function to initiate the theme\n        init: function () {\n\n            //IMPORTANT!!!: Do not modify the core handlers call order.\n\n            //core handlers\n            handleInit(); // initialize core variables\n            handleResponsiveOnResize(); // set and handle responsive    \n            handleUniform(); // hanfle custom radio & checkboxes\n            handleScrollers(); // handles slim scrolling contents \n            handleResponsiveOnInit(); // handler responsive elements on page load\n\n            //layout handlers\n            handleFixedSidebar(); // handles fixed sidebar menu\n            handleFixedSidebarHoverable(); // handles fixed sidebar on hover effect \n            handleSidebarMenu(); // handles main menu\n            handleHorizontalMenu(); // handles horizontal menu\n            //handleSidebarToggler(); // handles sidebar hide/show            \n            handleFixInputPlaceholderForIE(); // fixes/enables html5 placeholder attribute for IE9, IE8\n            handleGoTop(); //handles scroll to top functionality in the footer\n            //handleTheme(); // handles style customer tool\n\n            //ui component handlers\n            handleFancybox(); // handle fancy box\n            handleSelect2(); // handle custom Select2 dropdowns\n            handlePortletTools(); // handles portlet action bar functionality(refresh, configure, toggle, remove)\n            handleAlerts(); //handle closabled alerts\n            handleDropdowns(); // handle dropdowns\n            handleTabs(); // handle tabs\n            handleTooltips(); // handle bootstrap tooltips\n            handlePopovers(); // handles bootstrap popovers\n            handleAccordions(); //handles accordions \n            handleModals(); // handle modals\n            handleFullScreenMode(); // handles full screen\n        },\n\n        //main function to initiate core javascript after ajax complete\n        initAjax: function () {\n            handleSelect2(); // handle custom Select2 dropdowns\n            handleDropdowns(); // handle dropdowns\n            handleTooltips(); // handle bootstrap tooltips\n            handlePopovers(); // handles bootstrap popovers\n            handleAccordions(); //handles accordions \n            handleUniform(); // hanfle custom radio & checkboxes     \n            handleDropdownHover() // handles dropdown hover       \n        },\n\n        //public function to fix the sidebar and content height accordingly\n        fixContentHeight: function () {\n            handleSidebarAndContentHeight();\n        },\n\n        //public function to remember last opened popover that needs to be closed on click\n        setLastPopedPopover: function (el) {\n            lastPopedPopover = el;\n        },\n\n        //public function to add callback a function which will be called on window resize\n        addResponsiveHandler: function (func) {\n            responsiveHandlers.push(func);\n        },\n\n        // useful function to make equal height for contacts stand side by side\n        setEqualHeight: function (els) {\n            var tallestEl = 0;\n            els = jQuery(els);\n            els.each(function () {\n                var currentHeight = $(this).height();\n                if (currentHeight > tallestEl) {\n                    tallestColumn = currentHeight;\n                }\n            });\n            els.height(tallestEl);\n        },\n\n        // wrapper function to scroll(focus) to an element\n        scrollTo: function (el, offeset) {\n            pos = (el && el.size() > 0) ? el.offset().top : 0;\n            jQuery('html,body').animate({\n                scrollTop: pos + (offeset ? offeset : 0)\n            }, 'slow');\n        },\n\n        // function to scroll to the top\n        scrollTop: function () {\n            App.scrollTo();\n        },\n\n        // wrapper function to  block element(indicate loading)\n        blockUI: function (el, centerY) {\n            var el = jQuery(el);\n            if (el.height() <= 400) {\n                centerY = true;\n            }\n            el.block({\n                message: '<img src=\"../img/ajax-loading.gif\" align=\"\">',\n                centerY: centerY != undefined ? centerY : true,\n                css: {\n                    top: '10%',\n                    border: 'none',\n                    padding: '2px',\n                    backgroundColor: 'none'\n                },\n                overlayCSS: {\n                    backgroundColor: '#000',\n                    opacity: 0.05,\n                    cursor: 'wait'\n                }\n            });\n        },\n\n        // wrapper function to  un-block element(finish loading)\n        unblockUI: function (el, clean) {\n            jQuery(el).unblock({\n                onUnblock: function () {\n                    jQuery(el).css('position', '');\n                    jQuery(el).css('zoom', '');\n                }\n            });\n        },\n\n        // initializes uniform elements\n        initUniform: function (els) {\n            if (els) {\n                jQuery(els).each(function () {\n                    if ($(this).parents(\".checker\").size() == 0) {\n                        $(this).show();\n                        $(this).uniform();\n                    }\n                });\n            } else {\n                handleUniform();\n            }\n        },\n\n        //wrapper function to update/sync jquery uniform checkbox & radios\n        updateUniform: function (els) {\n            $.uniform.update(els); // update the uniform checkbox & radios UI after the actual input control state changed\n        },\n\n        //public function to initialize the fancybox plugin\n        initFancybox: function () {\n            handleFancybox();\n        },\n\n        //public helper function to get actual input value(used in IE9 and IE8 due to placeholder attribute not supported)\n        getActualVal: function (el) {\n            var el = jQuery(el);\n            if (el.val() === el.attr(\"placeholder\")) {\n                return \"\";\n            }\n            return el.val();\n        },\n\n        //public function to get a paremeter by name from URL\n        getURLParameter: function (paramName) {\n            var searchString = window.location.search.substring(1),\n                i, val, params = searchString.split(\"&\");\n\n            for (i = 0; i < params.length; i++) {\n                val = params[i].split(\"=\");\n                if (val[0] == paramName) {\n                    return unescape(val[1]);\n                }\n            }\n            return null;\n        },\n\n        // check for device touch support\n        isTouchDevice: function () {\n            try {\n                document.createEvent(\"TouchEvent\");\n                return true;\n            } catch (e) {\n                return false;\n            }\n        },\n\n        // check IE8 mode\n        isIE8: function () {\n            return isIE8;\n        },\n\n        // check IE9 mode\n        isIE9: function () {\n            return isIE9;\n        },\n\n        //check RTL mode\n        isRTL: function () {\n            return isRTL;\n        },\n\n        // get layout color code by color name\n        getLayoutColorCode: function (name) {\n            if (layoutColorCodes[name]) {\n                return layoutColorCodes[name];\n            } else {\n                return '';\n            }\n        }\n\n    };\n\n}();"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/scripts/calendar.js",
    "content": "var Calendar = function () {\n\n\n    return {\n        //main function to initiate the module\n        init: function () {\n            Calendar.initCalendar();\n        },\n\n        initCalendar: function () {\n\n            if (!jQuery().fullCalendar) {\n                return;\n            }\n\n            var date = new Date();\n            var d = date.getDate();\n            var m = date.getMonth();\n            var y = date.getFullYear();\n\n            var h = {};\n\n            if (App.isRTL()) {\n                 if ($('#calendar').parents(\".portlet\").width() <= 720) {\n                    $('#calendar').addClass(\"mobile\");\n                    h = {\n                        right: 'title, prev, next',\n                        center: '',\n                        right: 'agendaDay, agendaWeek, month, today'\n                    };\n                } else {\n                    $('#calendar').removeClass(\"mobile\");\n                    h = {\n                        right: 'title',\n                        center: '',\n                        left: 'agendaDay, agendaWeek, month, today, prev,next'\n                    };\n                }                \n            } else {\n                 if ($('#calendar').parents(\".portlet\").width() <= 720) {\n                    $('#calendar').addClass(\"mobile\");\n                    h = {\n                        left: 'title, prev, next',\n                        center: '',\n                        right: 'today,month,agendaWeek,agendaDay'\n                    };\n                } else {\n                    $('#calendar').removeClass(\"mobile\");\n                    h = {\n                        left: 'title',\n                        center: '',\n                        right: 'prev,next,today,month,agendaWeek,agendaDay'\n                    };\n                }\n            }\n           \n\n            var initDrag = function (el) {\n                // create an Event Object (http://arshaw.com/fullcalendar/docs/event_data/Event_Object/)\n                // it doesn't need to have a start or end\n                var eventObject = {\n                    title: $.trim(el.text()) // use the element's text as the event title\n                };\n                // store the Event Object in the DOM element so we can get to it later\n                el.data('eventObject', eventObject);\n                // make the event draggable using jQuery UI\n                el.draggable({\n                    zIndex: 999,\n                    revert: true, // will cause the event to go back to its\n                    revertDuration: 0 //  original position after the drag\n                });\n            }\n\n            var addEvent = function (title) {\n                title = title.length == 0 ? \"Untitled Event\" : title;\n                var html = $('<div class=\"external-event label label-default\">' + title + '</div>');\n                jQuery('#event_box').append(html);\n                initDrag(html);\n            }\n\n            $('#external-events div.external-event').each(function () {\n                initDrag($(this))\n            });\n\n            $('#event_add').unbind('click').click(function () {\n                var title = $('#event_title').val();\n                addEvent(title);\n            });\n\n            //predefined events\n            $('#event_box').html(\"\");\n            addEvent(\"My Event 1\");\n            addEvent(\"My Event 2\");\n            addEvent(\"My Event 3\");\n            addEvent(\"My Event 4\");\n            addEvent(\"My Event 5\");\n            addEvent(\"My Event 6\");\n\n            $('#calendar').fullCalendar('destroy'); // destroy the calendar\n            $('#calendar').fullCalendar({ //re-initialize the calendar\n                header: h,\n                slotMinutes: 15,\n                editable: true,\n                droppable: true, // this allows things to be dropped onto the calendar !!!\n                drop: function (date, allDay) { // this function is called when something is dropped\n\n                    // retrieve the dropped element's stored Event Object\n                    var originalEventObject = $(this).data('eventObject');\n                    // we need to copy it, so that multiple events don't have a reference to the same object\n                    var copiedEventObject = $.extend({}, originalEventObject);\n\n                    // assign it the date that was reported\n                    copiedEventObject.start = date;\n                    copiedEventObject.allDay = allDay;\n                    copiedEventObject.className = $(this).attr(\"data-class\");\n\n                    // render the event on the calendar\n                    // the last `true` argument determines if the event \"sticks\" (http://arshaw.com/fullcalendar/docs/event_rendering/renderEvent/)\n                    $('#calendar').fullCalendar('renderEvent', copiedEventObject, true);\n\n                    // is the \"remove after drop\" checkbox checked?\n                    if ($('#drop-remove').is(':checked')) {\n                        // if so, remove the element from the \"Draggable Events\" list\n                        $(this).remove();\n                    }\n                },\n                events: [{\n                        title: 'All Day Event',                        \n                        start: new Date(y, m, 1),\n                        backgroundColor: App.getLayoutColorCode('yellow')\n                    }, {\n                        title: 'Long Event',\n                        start: new Date(y, m, d - 5),\n                        end: new Date(y, m, d - 2),\n                        backgroundColor: App.getLayoutColorCode('green')\n                    }, {\n                        title: 'Repeating Event',\n                        start: new Date(y, m, d - 3, 16, 0),\n                        allDay: false,\n                        backgroundColor: App.getLayoutColorCode('red')\n                    }, {\n                        title: 'Repeating Event',\n                        start: new Date(y, m, d + 4, 16, 0),\n                        allDay: false,\n                        backgroundColor: App.getLayoutColorCode('green')\n                    }, {\n                        title: 'Meeting',\n                        start: new Date(y, m, d, 10, 30),\n                        allDay: false,\n                    }, {\n                        title: 'Lunch',\n                        start: new Date(y, m, d, 12, 0),\n                        end: new Date(y, m, d, 14, 0),\n                        backgroundColor: App.getLayoutColorCode('grey'),\n                        allDay: false,\n                    }, {\n                        title: 'Birthday Party',\n                        start: new Date(y, m, d + 1, 19, 0),\n                        end: new Date(y, m, d + 1, 22, 30),\n                        backgroundColor: App.getLayoutColorCode('purple'),\n                        allDay: false,\n                    }, {\n                        title: 'Click for Google',\n                        start: new Date(y, m, 28),\n                        end: new Date(y, m, 29),\n                        backgroundColor: App.getLayoutColorCode('yellow'),\n                        url: 'http://google.com/',\n                    }\n                ]\n            });\n\n        }\n\n    };\n\n}();"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/scripts/charts.js",
    "content": "var Charts = function () {\n\n    return {\n        //main function to initiate the module\n\n        init: function () {\n\n            App.addResponsiveHandler(function () {\n                 Charts.initPieCharts(); \n            });\n            \n        },\n\n        initCharts: function () {\n\n            if (!jQuery.plot) {\n                return;\n            }\n\n            var data = [];\n            var totalPoints = 250;\n\n            // random data generator for plot charts\n\n            function getRandomData() {\n                if (data.length > 0) data = data.slice(1);\n                // do a random walk\n                while (data.length < totalPoints) {\n                    var prev = data.length > 0 ? data[data.length - 1] : 50;\n                    var y = prev + Math.random() * 10 - 5;\n                    if (y < 0) y = 0;\n                    if (y > 100) y = 100;\n                    data.push(y);\n                }\n                // zip the generated y values with the x values\n                var res = [];\n                for (var i = 0; i < data.length; ++i) res.push([i, data[i]])\n                return res;\n            }\n\n            //Basic Chart\n\n            function chart1() {\n                var d1 = [];\n                for (var i = 0; i < Math.PI * 2; i += 0.25)\n                    d1.push([i, Math.sin(i)]);\n\n                var d2 = [];\n                for (var i = 0; i < Math.PI * 2; i += 0.25)\n                    d2.push([i, Math.cos(i)]);\n\n                var d3 = [];\n                for (var i = 0; i < Math.PI * 2; i += 0.1)\n                    d3.push([i, Math.tan(i)]);\n\n                $.plot($(\"#chart_1\"), [{\n                            label: \"sin(x)\",\n                            data: d1\n                        }, {\n                            label: \"cos(x)\",\n                            data: d2\n                        }, {\n                            label: \"tan(x)\",\n                            data: d3\n                        }\n                    ], {\n                        series: {\n                            lines: {\n                                show: true\n                            },\n                            points: {\n                                show: true\n                            }\n                        },\n                        xaxis: {\n                            ticks: [0, [Math.PI / 2, \"\\u03c0/2\"],\n                                [Math.PI, \"\\u03c0\"],\n                                [Math.PI * 3 / 2, \"3\\u03c0/2\"],\n                                [Math.PI * 2, \"2\\u03c0\"]\n                            ]\n                        },\n                        yaxis: {\n                            ticks: 10,\n                            min: -2,\n                            max: 2\n                        },\n                        grid: {\n                            backgroundColor: {\n                                colors: [\"#fff\", \"#eee\"]\n                            }\n                        }\n                    });\n\n            }\n\n            //Interactive Chart\n\n            function chart2() {\n                function randValue() {\n                    return (Math.floor(Math.random() * (1 + 40 - 20))) + 20;\n                }\n                var pageviews = [\n                    [1, randValue()],\n                    [2, randValue()],\n                    [3, 2 + randValue()],\n                    [4, 3 + randValue()],\n                    [5, 5 + randValue()],\n                    [6, 10 + randValue()],\n                    [7, 15 + randValue()],\n                    [8, 20 + randValue()],\n                    [9, 25 + randValue()],\n                    [10, 30 + randValue()],\n                    [11, 35 + randValue()],\n                    [12, 25 + randValue()],\n                    [13, 15 + randValue()],\n                    [14, 20 + randValue()],\n                    [15, 45 + randValue()],\n                    [16, 50 + randValue()],\n                    [17, 65 + randValue()],\n                    [18, 70 + randValue()],\n                    [19, 85 + randValue()],\n                    [20, 80 + randValue()],\n                    [21, 75 + randValue()],\n                    [22, 80 + randValue()],\n                    [23, 75 + randValue()],\n                    [24, 70 + randValue()],\n                    [25, 65 + randValue()],\n                    [26, 75 + randValue()],\n                    [27, 80 + randValue()],\n                    [28, 85 + randValue()],\n                    [29, 90 + randValue()],\n                    [30, 95 + randValue()]\n                ];\n                var visitors = [\n                    [1, randValue() - 5],\n                    [2, randValue() - 5],\n                    [3, randValue() - 5],\n                    [4, 6 + randValue()],\n                    [5, 5 + randValue()],\n                    [6, 20 + randValue()],\n                    [7, 25 + randValue()],\n                    [8, 36 + randValue()],\n                    [9, 26 + randValue()],\n                    [10, 38 + randValue()],\n                    [11, 39 + randValue()],\n                    [12, 50 + randValue()],\n                    [13, 51 + randValue()],\n                    [14, 12 + randValue()],\n                    [15, 13 + randValue()],\n                    [16, 14 + randValue()],\n                    [17, 15 + randValue()],\n                    [18, 15 + randValue()],\n                    [19, 16 + randValue()],\n                    [20, 17 + randValue()],\n                    [21, 18 + randValue()],\n                    [22, 19 + randValue()],\n                    [23, 20 + randValue()],\n                    [24, 21 + randValue()],\n                    [25, 14 + randValue()],\n                    [26, 24 + randValue()],\n                    [27, 25 + randValue()],\n                    [28, 26 + randValue()],\n                    [29, 27 + randValue()],\n                    [30, 31 + randValue()]\n                ];\n\n                var plot = $.plot($(\"#chart_2\"), [{\n                            data: pageviews,\n                            label: \"Unique Visits\"\n                        }, {\n                            data: visitors,\n                            label: \"Page Views\"\n                        }\n                    ], {\n                        series: {\n                            lines: {\n                                show: true,\n                                lineWidth: 2,\n                                fill: true,\n                                fillColor: {\n                                    colors: [{\n                                            opacity: 0.05\n                                        }, {\n                                            opacity: 0.01\n                                        }\n                                    ]\n                                }\n                            },\n                            points: {\n                                show: true\n                            },\n                            shadowSize: 2\n                        },\n                        grid: {\n                            hoverable: true,\n                            clickable: true,\n                            tickColor: \"#eee\",\n                            borderWidth: 0\n                        },\n                        colors: [\"#d12610\", \"#37b7f3\", \"#52e136\"],\n                        xaxis: {\n                            ticks: 11,\n                            tickDecimals: 0\n                        },\n                        yaxis: {\n                            ticks: 11,\n                            tickDecimals: 0\n                        }\n                    });\n\n\n                function showTooltip(x, y, contents) {\n                    $('<div id=\"tooltip\">' + contents + '</div>').css({\n                            position: 'absolute',\n                            display: 'none',\n                            top: y + 5,\n                            left: x + 15,\n                            border: '1px solid #333',\n                            padding: '4px',\n                            color: '#fff',\n                            'border-radius': '3px',\n                            'background-color': '#333',\n                            opacity: 0.80\n                        }).appendTo(\"body\").fadeIn(200);\n                }\n\n                var previousPoint = null;\n                $(\"#chart_2\").bind(\"plothover\", function (event, pos, item) {\n                    $(\"#x\").text(pos.x.toFixed(2));\n                    $(\"#y\").text(pos.y.toFixed(2));\n\n                    if (item) {\n                        if (previousPoint != item.dataIndex) {\n                            previousPoint = item.dataIndex;\n\n                            $(\"#tooltip\").remove();\n                            var x = item.datapoint[0].toFixed(2),\n                                y = item.datapoint[1].toFixed(2);\n\n                            showTooltip(item.pageX, item.pageY, item.series.label + \" of \" + x + \" = \" + y);\n                        }\n                    } else {\n                        $(\"#tooltip\").remove();\n                        previousPoint = null;\n                    }\n                });\n            }\n\n            //Tracking Curves\n\n            function chart3() {\n                //tracking curves:\n\n                var sin = [],\n                    cos = [];\n                for (var i = 0; i < 14; i += 0.1) {\n                    sin.push([i, Math.sin(i)]);\n                    cos.push([i, Math.cos(i)]);\n                }\n\n                plot = $.plot($(\"#chart_3\"), [{\n                            data: sin,\n                            label: \"sin(x) = -0.00\"\n                        }, {\n                            data: cos,\n                            label: \"cos(x) = -0.00\"\n                        }\n                    ], {\n                        series: {\n                            lines: {\n                                show: true\n                            }\n                        },\n                        crosshair: {\n                            mode: \"x\"\n                        },\n                        grid: {\n                            hoverable: true,\n                            autoHighlight: false\n                        },\n                        yaxis: {\n                            min: -1.2,\n                            max: 1.2\n                        }\n                    });\n\n                var legends = $(\"#chart_3 .legendLabel\");\n                legends.each(function () {\n                    // fix the widths so they don't jump around\n                    $(this).css('width', $(this).width());\n                });\n\n                var updateLegendTimeout = null;\n                var latestPosition = null;\n\n                function updateLegend() {\n                    updateLegendTimeout = null;\n\n                    var pos = latestPosition;\n\n                    var axes = plot.getAxes();\n                    if (pos.x < axes.xaxis.min || pos.x > axes.xaxis.max || pos.y < axes.yaxis.min || pos.y > axes.yaxis.max) return;\n\n                    var i, j, dataset = plot.getData();\n                    for (i = 0; i < dataset.length; ++i) {\n                        var series = dataset[i];\n\n                        // find the nearest points, x-wise\n                        for (j = 0; j < series.data.length; ++j)\n                            if (series.data[j][0] > pos.x) break;\n\n                            // now interpolate\n                        var y, p1 = series.data[j - 1],\n                            p2 = series.data[j];\n                        if (p1 == null) y = p2[1];\n                        else if (p2 == null) y = p1[1];\n                        else y = p1[1] + (p2[1] - p1[1]) * (pos.x - p1[0]) / (p2[0] - p1[0]);\n\n                        legends.eq(i).text(series.label.replace(/=.*/, \"= \" + y.toFixed(2)));\n                    }\n                }\n\n                $(\"#chart_3\").bind(\"plothover\", function (event, pos, item) {\n                    latestPosition = pos;\n                    if (!updateLegendTimeout) updateLegendTimeout = setTimeout(updateLegend, 50);\n                });\n            }\n\n            //Dynamic Chart\n\n            function chart4() {\n                //server load\n                var options = {\n                    series: {\n                        shadowSize: 1\n                    },\n                    lines: {\n                        show: true,\n                        lineWidth: 0.5,\n                        fill: true,\n                        fillColor: {\n                            colors: [{\n                                    opacity: 0.1\n                                }, {\n                                    opacity: 1\n                                }\n                            ]\n                        }\n                    },\n                    yaxis: {\n                        min: 0,\n                        max: 100,\n                        tickFormatter: function (v) {\n                            return v + \"%\";\n                        }\n                    },\n                    xaxis: {\n                        show: false\n                    },\n                    colors: [\"#6ef146\"],\n                    grid: {\n                        tickColor: \"#a8a3a3\",\n                        borderWidth: 0\n                    }\n                };\n\n                var updateInterval = 30;\n                var plot = $.plot($(\"#chart_4\"), [getRandomData()], options);\n\n                function update() {\n                    plot.setData([getRandomData()]);\n                    plot.draw();\n                    setTimeout(update, updateInterval);\n                }\n                update();\n            }\n\n            //bars with controls\n\n            function chart5() {\n                var d1 = [];\n                for (var i = 0; i <= 10; i += 1)\n                    d1.push([i, parseInt(Math.random() * 30)]);\n\n                var d2 = [];\n                for (var i = 0; i <= 10; i += 1)\n                    d2.push([i, parseInt(Math.random() * 30)]);\n\n                var d3 = [];\n                for (var i = 0; i <= 10; i += 1)\n                    d3.push([i, parseInt(Math.random() * 30)]);\n\n                var stack = 0,\n                    bars = true,\n                    lines = false,\n                    steps = false;\n\n                function plotWithOptions() {\n                    $.plot($(\"#chart_5\"), [d1, d2, d3], {\n                            series: {\n                                stack: stack,\n                                lines: {\n                                    show: lines,\n                                    fill: true,\n                                    steps: steps\n                                },\n                                bars: {\n                                    show: bars,\n                                    barWidth: 0.6\n                                }\n                            }\n                        });\n                }\n\n                $(\".stackControls input\").click(function (e) {\n                    e.preventDefault();\n                    stack = $(this).val() == \"With stacking\" ? true : null;\n                    plotWithOptions();\n                });\n                $(\".graphControls input\").click(function (e) {\n                    e.preventDefault();\n                    bars = $(this).val().indexOf(\"Bars\") != -1;\n                    lines = $(this).val().indexOf(\"Lines\") != -1;\n                    steps = $(this).val().indexOf(\"steps\") != -1;\n                    plotWithOptions();\n                });\n\n                plotWithOptions();\n            }\n\n            //graph\n            chart1();\n            chart2();\n            chart3();\n            chart4();\n            chart5();\n\n        },\n\n        initBarCharts: function () {\n\n            // bar chart:\n            var data1 = GenerateSeries(0);\n     \n            function GenerateSeries(added){\n                var data = [];\n                var start = 100 + added;\n                var end = 200 + added;\n         \n                for(i=1;i<=20;i++){        \n                    var d = Math.floor(Math.random() * (end - start + 1) + start);        \n                    data.push([i, d]);\n                    start++;\n                    end++;\n                }\n         \n                return data;\n            }\n         \n            var options = {\n                    series:{\n                        bars:{show: true}\n                    },\n                    bars:{\n                          barWidth:0.8\n                    },            \n                    grid:{\n                        backgroundColor: { colors: [\"#fafafa\", \"#35aa47\"] }\n                    }\n            };\n \n            $.plot($(\"#chart_1_1\"), [data1], options);\n\n            // horizontal bar chart:\n\n            var data1 = [\n                [10, 10], [20, 20], [30, 30], [40, 40], [50, 50]\n            ];\n         \n            var options = {\n                    series:{\n                        bars:{show: true}\n                    },\n                    bars:{\n                        horizontal:true,\n                        barWidth:6\n                    },\n                    grid:{\n                        backgroundColor: { colors: [\"#fafafa\", \"#4b8df8\"] }\n                    }\n            };\n         \n            $.plot($(\"#chart_1_2\"), [data1], options);  \n        },\n\n        initPieCharts: function () {\n\n            var data = [];\n            var series = Math.floor(Math.random() * 10) + 1;\n            series = series < 5 ? 5 : series;\n            \n            for (var i = 0; i < series; i++) {\n                data[i] = {\n                    label: \"Series\" + (i + 1),\n                    data: Math.floor(Math.random() * 100) + 1\n                }\n            }\n\n            // DEFAULT\n            $.plot($(\"#pie_chart\"), data, {\n                    series: {\n                        pie: {\n                            show: true\n                        }\n                    }\n                });\n\n            // GRAPH 1\n            $.plot($(\"#pie_chart_1\"), data, {\n                    series: {\n                        pie: {\n                            show: true\n                        }\n                    },\n                    legend: {\n                        show: false\n                    }\n                });\n\n            // GRAPH 2\n            $.plot($(\"#pie_chart_2\"), data, {\n                    series: {\n                        pie: {\n                            show: true,\n                            radius: 1,\n                            label: {\n                                show: true,\n                                radius: 1,\n                                formatter: function (label, series) {\n                                    return '<div style=\"font-size:8pt;text-align:center;padding:2px;color:white;\">' + label + '<br/>' + Math.round(series.percent) + '%</div>';\n                                },\n                                background: {\n                                    opacity: 0.8\n                                }\n                            }\n                        }\n                    },\n                    legend: {\n                        show: false\n                    }\n                });\n\n            // GRAPH 3\n            $.plot($(\"#pie_chart_3\"), data, {\n                    series: {\n                        pie: {\n                            show: true,\n                            radius: 1,\n                            label: {\n                                show: true,\n                                radius: 3 / 4,\n                                formatter: function (label, series) {\n                                    return '<div style=\"font-size:8pt;text-align:center;padding:2px;color:white;\">' + label + '<br/>' + Math.round(series.percent) + '%</div>';\n                                },\n                                background: {\n                                    opacity: 0.5\n                                }\n                            }\n                        }\n                    },\n                    legend: {\n                        show: false\n                    }\n                });\n\n            // GRAPH 4\n            $.plot($(\"#pie_chart_4\"), data, {\n                    series: {\n                        pie: {\n                            show: true,\n                            radius: 1,\n                            label: {\n                                show: true,\n                                radius: 3 / 4,\n                                formatter: function (label, series) {\n                                    return '<div style=\"font-size:8pt;text-align:center;padding:2px;color:white;\">' + label + '<br/>' + Math.round(series.percent) + '%</div>';\n                                },\n                                background: {\n                                    opacity: 0.5,\n                                    color: '#000'\n                                }\n                            }\n                        }\n                    },\n                    legend: {\n                        show: false\n                    }\n                });\n\n            // GRAPH 5\n            $.plot($(\"#pie_chart_5\"), data, {\n                    series: {\n                        pie: {\n                            show: true,\n                            radius: 3 / 4,\n                            label: {\n                                show: true,\n                                radius: 3 / 4,\n                                formatter: function (label, series) {\n                                    return '<div style=\"font-size:8pt;text-align:center;padding:2px;color:white;\">' + label + '<br/>' + Math.round(series.percent) + '%</div>';\n                                },\n                                background: {\n                                    opacity: 0.5,\n                                    color: '#000'\n                                }\n                            }\n                        }\n                    },\n                    legend: {\n                        show: false\n                    }\n                });\n\n            // GRAPH 6\n            $.plot($(\"#pie_chart_6\"), data, {\n                    series: {\n                        pie: {\n                            show: true,\n                            radius: 1,\n                            label: {\n                                show: true,\n                                radius: 2 / 3,\n                                formatter: function (label, series) {\n                                    return '<div style=\"font-size:8pt;text-align:center;padding:2px;color:white;\">' + label + '<br/>' + Math.round(series.percent) + '%</div>';\n                                },\n                                threshold: 0.1\n                            }\n                        }\n                    },\n                    legend: {\n                        show: false\n                    }\n                });\n\n            // GRAPH 7\n            $.plot($(\"#pie_chart_7\"), data, {\n                    series: {\n                        pie: {\n                            show: true,\n                            combine: {\n                                color: '#999',\n                                threshold: 0.1\n                            }\n                        }\n                    },\n                    legend: {\n                        show: false\n                    }\n                });\n\n            // GRAPH 8\n            $.plot($(\"#pie_chart_8\"), data, {\n                    series: {\n                        pie: {\n                            show: true,\n                            radius: 300,\n                            label: {\n                                show: true,\n                                formatter: function (label, series) {\n                                    return '<div style=\"font-size:8pt;text-align:center;padding:2px;color:white;\">' + label + '<br/>' + Math.round(series.percent) + '%</div>';\n                                },\n                                threshold: 0.1\n                            }\n                        }\n                    },\n                    legend: {\n                        show: false\n                    }\n                });\n\n            // GRAPH 9\n            $.plot($(\"#pie_chart_9\"), data, {\n                    series: {\n                        pie: {\n                            show: true,\n                            radius: 1,\n                            tilt: 0.5,\n                            label: {\n                                show: true,\n                                radius: 1,\n                                formatter: function (label, series) {\n                                    return '<div style=\"font-size:8pt;text-align:center;padding:2px;color:white;\">' + label + '<br/>' + Math.round(series.percent) + '%</div>';\n                                },\n                                background: {\n                                    opacity: 0.8\n                                }\n                            },\n                            combine: {\n                                color: '#999',\n                                threshold: 0.1\n                            }\n                        }\n                    },\n                    legend: {\n                        show: false\n                    }\n                });\n\n            // DONUT\n            $.plot($(\"#donut\"), data, {\n                    series: {\n                        pie: {\n                            innerRadius: 0.5,\n                            show: true\n                        }\n                    }\n                });\n\n            // INTERACTIVE\n            $.plot($(\"#interactive\"), data, {\n                    series: {\n                        pie: {\n                            show: true\n                        }\n                    },\n                    grid: {\n                        hoverable: true,\n                        clickable: true\n                    }\n                });\n            $(\"#interactive\").bind(\"plothover\", pieHover);\n            $(\"#interactive\").bind(\"plotclick\", pieClick);\n\n            function pieHover(event, pos, obj) {\n            if (!obj)\n                    return;\n                percent = parseFloat(obj.series.percent).toFixed(2);\n                $(\"#hover\").html('<span style=\"font-weight: bold; color: ' + obj.series.color + '\">' + obj.series.label + ' (' + percent + '%)</span>');\n            }\n\n            function pieClick(event, pos, obj) {\n                if (!obj)\n                    return;\n                percent = parseFloat(obj.series.percent).toFixed(2);\n                alert('' + obj.series.label + ': ' + percent + '%');\n            }\n\n        }\n        \n    };\n\n}();"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/scripts/coming-soon.js",
    "content": "var ComingSoon = function () {\n\n    return {\n        //main function to initiate the module\n        init: function () {\n\n            $.backstretch([\n    \t\t        \"assets/img/bg/1.jpg\",\n    \t\t        \"assets/img/bg/2.jpg\",\n    \t\t        \"assets/img/bg/3.jpg\",\n    \t\t        \"assets/img/bg/4.jpg\"\n    \t\t        ], {\n    \t\t          fade: 1000,\n    \t\t          duration: 10000\n    \t\t    });\n\n            var austDay = new Date();\n            austDay = new Date(austDay.getFullYear() + 1, 1 - 1, 26);\n            $('#defaultCountdown').countdown({until: austDay});\n            $('#year').text(austDay.getFullYear());\n        }\n\n    };\n\n}();"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/scripts/contact-us.js",
    "content": "var ContactUs = function () {\n\n    return {\n        //main function to initiate the module\n        init: function () {\n\t\t\tvar map;\n\t\t\t$(document).ready(function(){\n\t\t\t  map = new GMaps({\n\t\t\t\tdiv: '#map',\n\t\t\t\tlat: -13.004333,\n\t\t\t\tlng: -38.494333\n\t\t\t  });\n\t\t\t   var marker = map.addMarker({\n\t\t            lat: -13.004333,\n\t\t\t\t\tlng: -38.494333,\n\t\t            title: 'Loop, Inc.',\n\t\t            infoWindow: {\n\t\t                content: \"<b>Loop, Inc.</b> 795 Park Ave, Suite 120<br>San Francisco, CA 94107\"\n\t\t            }\n\t\t        });\n\n\t\t\t   marker.infoWindow.open(map, marker);\n\t\t\t});\n        }\n    };\n\n}();"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/scripts/custom.js",
    "content": "/**\nCustom module for you to write your own javascript functions\n**/\nvar Custom = function () {\n\n    // private functions & variables\n\n    var myFunc = function(text) {\n        alert(text);\n    }\n\n    // public functions\n    return {\n\n        //main function\n        init: function () {\n            //initialize here something.            \n        },\n\n        //some helper function\n        doSomeStuff: function () {\n            myFunc();\n        }\n\n    };\n\n}();\n\n/***\nUsage\n***/\n//Custom.init();\n//Custom.doSomeStuff();"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/scripts/form-components.js",
    "content": "var FormComponents = function () {\n\n\n    var handleBootstrapTouchSpin = function() {\n\n        $(\"#touchspin_demo1\").TouchSpin({\n            inputGroupClass: 'input-medium',            \n            spinUpClass: 'green',\n            spinDownClass: 'green',\n            min: -1000000000,\n            max: 1000000000,\n            stepinterval: 50,\n            maxboostedstep: 10000000,\n            prefix: '$'\n        }); \n        \n        $(\"#touchspin_demo2\").TouchSpin({\n            inputGroupClass: 'input-medium',\n            spinUpClass: 'blue',\n            spinDownClass: 'blue',\n            min: 0,\n            max: 100,\n            step: 0.1,\n            decimals: 2,\n            boostat: 5,\n            maxboostedstep: 10,\n            postfix: '%'\n        });         \n    }\n\n    var handleBootstrapMaxlength = function() {\n        $('#maxlength_defaultconfig').maxlength({\n            limitReachedClass: \"label label-danger\",\n        })\n    \n        $('#maxlength_thresholdconfig').maxlength({\n            limitReachedClass: \"label label-danger\",\n            threshold: 20\n        });\n\n        $('#maxlength_alloptions').maxlength({\n            alwaysShow: true,\n            warningClass: \"label label-success\",\n            limitReachedClass: \"label label-danger\",\n            separator: ' out of ',\n            preText: 'You typed ',\n            postText: ' chars available.',\n            validate: true\n        });\n\n        $('#maxlength_textarea').maxlength({\n            limitReachedClass: \"label label-danger\",\n            alwaysShow: true\n        });\n\n        $('#maxlength_placement').maxlength({\n            limitReachedClass: \"label label-danger\",\n            alwaysShow: true,\n            placement: App.isRTL() ? 'top-right' : 'top-left'\n        });\n    }\n\n    var handleSpinners = function () {\n        $('#spinner1').spinner();\n        $('#spinner2').spinner({disabled: true});\n        $('#spinner3').spinner({value:0, min: 0, max: 10});\n        $('#spinner4').spinner({value:0, step: 5, min: 0, max: 200});\n    }\n\n    var handleWysihtml5 = function () {\n        if (!jQuery().wysihtml5) {\n            return;\n        }\n\n        if ($('.wysihtml5').size() > 0) {\n            $('.wysihtml5').wysihtml5({\n                \"stylesheets\": [\"assets/plugins/bootstrap-wysihtml5/wysiwyg-color.css\"]\n            });\n        }\n    }\n\n    var handleTagsInput = function () {\n        if (!jQuery().tagsInput) {\n            return;\n        }\n        $('#tags_1').tagsInput({\n            width: 'auto',\n            'onAddTag': function () {\n                //alert(1);\n            },\n        });\n        $('#tags_2').tagsInput({\n            width: 300\n        });\n    }\n\n    var handleDatePickers = function () {\n\n        if (jQuery().datepicker) {\n            $('.date-picker').datepicker({\n                rtl: App.isRTL(),\n                autoclose: true\n            });\n            $('body').removeClass(\"modal-open\"); // fix bug when inline picker is used in modal\n        }\n    }\n\n    var handleTimePickers = function () {\n\n        if (jQuery().timepicker) {\n            $('.timepicker-default').timepicker({\n                autoclose: true\n            });\n            $('.timepicker-24').timepicker({\n                autoclose: true,\n                minuteStep: 1,\n                showSeconds: true,\n                showMeridian: false\n            });\n        }\n    }\n\n    var handleDateRangePickers = function () {\n        if (!jQuery().daterangepicker) {\n            return;\n        }\n\n        $('#defaultrange').daterangepicker({\n                opens: (App.isRTL() ? 'left' : 'right'),\n                format: 'MM/DD/YYYY',\n                separator: ' to ',\n                startDate: moment().subtract('days', 29),\n                endDate: moment(),\n                minDate: '01/01/2012',\n                maxDate: '12/31/2014',\n            },\n            function (start, end) {\n                console.log(\"Callback has been called!\");\n                $('#defaultrange input').val(start.format('MMMM D, YYYY') + ' - ' + end.format('MMMM D, YYYY'));\n            }\n        );        \n\n        $('#reportrange').daterangepicker({\n                opens: (App.isRTL() ? 'left' : 'right'),\n                startDate: moment().subtract('days', 29),\n                endDate: moment(),\n                minDate: '01/01/2012',\n                maxDate: '12/31/2014',\n                dateLimit: {\n                    days: 60\n                },\n                showDropdowns: true,\n                showWeekNumbers: true,\n                timePicker: false,\n                timePickerIncrement: 1,\n                timePicker12Hour: true,\n                ranges: {\n                    'Today': [moment(), moment()],\n                    'Yesterday': [moment().subtract('days', 1), moment().subtract('days', 1)],\n                    'Last 7 Days': [moment().subtract('days', 6), moment()],\n                    'Last 30 Days': [moment().subtract('days', 29), moment()],\n                    'This Month': [moment().startOf('month'), moment().endOf('month')],\n                    'Last Month': [moment().subtract('month', 1).startOf('month'), moment().subtract('month', 1).endOf('month')]\n                },\n                buttonClasses: ['btn'],\n                applyClass: 'green',\n                cancelClass: 'default',\n                format: 'MM/DD/YYYY',\n                separator: ' to ',\n                locale: {\n                    applyLabel: 'Apply',\n                    fromLabel: 'From',\n                    toLabel: 'To',\n                    customRangeLabel: 'Custom Range',\n                    daysOfWeek: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'],\n                    monthNames: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],\n                    firstDay: 1\n                }\n            },\n            function (start, end) {\n                console.log(\"Callback has been called!\");\n                $('#reportrange span').html(start.format('MMMM D, YYYY') + ' - ' + end.format('MMMM D, YYYY'));\n            }\n        );\n        //Set the initial state of the picker label\n        $('#reportrange span').html(moment().subtract('days', 29).format('MMMM D, YYYY') + ' - ' + moment().format('MMMM D, YYYY'));\n    }\n\n    var handleDatetimePicker = function () {\n\n        $(\".form_datetime\").datetimepicker({\n            autoclose: true,\n            isRTL: App.isRTL(),\n            format: \"dd MM yyyy - hh:ii\",\n            pickerPosition: (App.isRTL() ? \"bottom-right\" : \"bottom-left\")\n        });\n\n        $(\".form_advance_datetime\").datetimepicker({\n            isRTL: App.isRTL(),\n            format: \"dd MM yyyy - hh:ii\",\n            autoclose: true,\n            todayBtn: true,\n            startDate: \"2013-02-14 10:00\",\n            pickerPosition: (App.isRTL() ? \"bottom-right\" : \"bottom-left\"),\n            minuteStep: 10\n        });\n\n        $(\".form_meridian_datetime\").datetimepicker({\n            isRTL: App.isRTL(),\n            format: \"dd MM yyyy - HH:ii P\",\n            showMeridian: true,\n            autoclose: true,\n            pickerPosition: (App.isRTL() ? \"bottom-right\" : \"bottom-left\"),\n            todayBtn: true\n        });\n\n        $('body').removeClass(\"modal-open\"); // fix bug when inline picker is used in modal\n    }\n\n    var handleClockfaceTimePickers = function () {\n\n        if (!jQuery().clockface) {\n            return;\n        }\n\n        $('.clockface_1').clockface();\n\n        $('#clockface_2').clockface({\n            format: 'HH:mm',\n            trigger: 'manual'\n        });\n\n        $('#clockface_2_toggle').click(function (e) {\n            e.stopPropagation();\n            $('#clockface_2').clockface('toggle');\n        });\n\n        $('#clockface_2_modal').clockface({\n            format: 'HH:mm',\n            trigger: 'manual'\n        });\n\n        $('#clockface_2_modal_toggle').click(function (e) {\n            e.stopPropagation();\n            $('#clockface_2_modal').clockface('toggle');\n        });\n\n        $('.clockface_3').clockface({\n            format: 'H:mm'\n        }).clockface('show', '14:30');\n    }\n\n    var handleColorPicker = function () {\n        if (!jQuery().colorpicker) {\n            return;\n        }\n        $('.colorpicker-default').colorpicker({\n            format: 'hex'\n        });\n        $('.colorpicker-rgba').colorpicker();\n    }\n\n    var handleSelect2 = function () {\n\n        $('#select2_sample1').select2({\n            placeholder: \"Select an option\",\n            allowClear: true\n        });\n\n        $('#select2_sample2').select2({\n            placeholder: \"Select a State\",\n            allowClear: true\n        });\n\n        $(\"#select2_sample3\").select2({\n            placeholder: \"Select...\",\n            allowClear: true,\n            minimumInputLength: 1,\n            query: function (query) {\n                var data = {\n                    results: []\n                }, i, j, s;\n                for (i = 1; i < 5; i++) {\n                    s = \"\";\n                    for (j = 0; j < i; j++) {\n                        s = s + query.term;\n                    }\n                    data.results.push({\n                        id: query.term + i,\n                        text: s\n                    });\n                }\n                query.callback(data);\n            }\n        });\n\n        function format(state) {\n            if (!state.id) return state.text; // optgroup\n            return \"<img class='flag' src='assets/img/flags/\" + state.id.toLowerCase() + \".png'/>&nbsp;&nbsp;\" + state.text;\n        }\n        $(\"#select2_sample4\").select2({\n            placeholder: \"Select a Country\",\n            allowClear: true,\n            formatResult: format,\n            formatSelection: format,\n            escapeMarkup: function (m) {\n                return m;\n            }\n        });\n\n        $(\"#select2_sample5\").select2({\n            tags: [\"red\", \"green\", \"blue\", \"yellow\", \"pink\"]\n        });\n\n\n        function movieFormatResult(movie) {\n            var markup = \"<table class='movie-result'><tr>\";\n            if (movie.posters !== undefined && movie.posters.thumbnail !== undefined) {\n                markup += \"<td valign='top'><img src='\" + movie.posters.thumbnail + \"'/></td>\";\n            }\n            markup += \"<td valign='top'><h5>\" + movie.title + \"</h5>\";\n            if (movie.critics_consensus !== undefined) {\n                markup += \"<div class='movie-synopsis'>\" + movie.critics_consensus + \"</div>\";\n            } else if (movie.synopsis !== undefined) {\n                markup += \"<div class='movie-synopsis'>\" + movie.synopsis + \"</div>\";\n            }\n            markup += \"</td></tr></table>\"\n            return markup;\n        }\n\n        function movieFormatSelection(movie) {\n            return movie.title;\n        }\n\n        $(\"#select2_sample6\").select2({\n            placeholder: \"Search for a movie\",\n            minimumInputLength: 1,\n            ajax: { // instead of writing the function to execute the request we use Select2's convenient helper\n                url: \"http://api.rottentomatoes.com/api/public/v1.0/movies.json\",\n                dataType: 'jsonp',\n                data: function (term, page) {\n                    return {\n                        q: term, // search term\n                        page_limit: 10,\n                        apikey: \"ju6z9mjyajq2djue3gbvv26t\" // please do not use so this example keeps working\n                    };\n                },\n                results: function (data, page) { // parse the results into the format expected by Select2.\n                    // since we are using custom formatting functions we do not need to alter remote JSON data\n                    return {\n                        results: data.movies\n                    };\n                }\n            },\n            initSelection: function (element, callback) {\n                // the input tag has a value attribute preloaded that points to a preselected movie's id\n                // this function resolves that id attribute to an object that select2 can render\n                // using its formatResult renderer - that way the movie name is shown preselected\n                var id = $(element).val();\n                if (id !== \"\") {\n                    $.ajax(\"http://api.rottentomatoes.com/api/public/v1.0/movies/\" + id + \".json\", {\n                        data: {\n                            apikey: \"ju6z9mjyajq2djue3gbvv26t\"\n                        },\n                        dataType: \"jsonp\"\n                    }).done(function (data) {\n                        callback(data);\n                    });\n                }\n            },\n            formatResult: movieFormatResult, // omitted for brevity, see the source of this page\n            formatSelection: movieFormatSelection, // omitted for brevity, see the source of this page\n            dropdownCssClass: \"bigdrop\", // apply css that makes the dropdown taller\n            escapeMarkup: function (m) {\n                return m;\n            } // we do not want to escape markup since we are displaying html in results\n        });\n    }\n\n    var handleSelect2Modal = function () {\n\n        $('#select2_sample_modal_1').select2({\n            placeholder: \"Select an option\",\n            allowClear: true\n        });\n\n        $('#select2_sample_modal_2').select2({\n            placeholder: \"Select a State\",\n            allowClear: true\n        });\n\n        $(\"#select2_sample_modal_3\").select2({\n            allowClear: true,\n            minimumInputLength: 1,\n            query: function (query) {\n                var data = {\n                    results: []\n                }, i, j, s;\n                for (i = 1; i < 5; i++) {\n                    s = \"\";\n                    for (j = 0; j < i; j++) {\n                        s = s + query.term;\n                    }\n                    data.results.push({\n                        id: query.term + i,\n                        text: s\n                    });\n                }\n                query.callback(data);\n            }\n        });\n\n        function format(state) {\n            if (!state.id) return state.text; // optgroup\n            return \"<img class='flag' src='assets/img/flags/\" + state.id.toLowerCase() + \".png'/>&nbsp;&nbsp;\" + state.text;\n        }\n        $(\"#select2_sample_modal_4\").select2({\n            allowClear: true,\n            formatResult: format,\n            formatSelection: format,\n            escapeMarkup: function (m) {\n                return m;\n            }\n        });\n\n        $(\"#select2_sample_modal_5\").select2({\n            tags: [\"red\", \"green\", \"blue\", \"yellow\", \"pink\"]\n        });\n\n\n        function movieFormatResult(movie) {\n            var markup = \"<table class='movie-result'><tr>\";\n            if (movie.posters !== undefined && movie.posters.thumbnail !== undefined) {\n                markup += \"<td valign='top'><img src='\" + movie.posters.thumbnail + \"'/></td>\";\n            }\n            markup += \"<td valign='top'><h5>\" + movie.title + \"</h5>\";\n            if (movie.critics_consensus !== undefined) {\n                markup += \"<div class='movie-synopsis'>\" + movie.critics_consensus + \"</div>\";\n            } else if (movie.synopsis !== undefined) {\n                markup += \"<div class='movie-synopsis'>\" + movie.synopsis + \"</div>\";\n            }\n            markup += \"</td></tr></table>\"\n            return markup;\n        }\n\n        function movieFormatSelection(movie) {\n            return movie.title;\n        }\n\n        $(\"#select2_sample_modal_6\").select2({\n            placeholder: \"Search for a movie\",\n            minimumInputLength: 1,\n            ajax: { // instead of writing the function to execute the request we use Select2's convenient helper\n                url: \"http://api.rottentomatoes.com/api/public/v1.0/movies.json\",\n                dataType: 'jsonp',\n                data: function (term, page) {\n                    return {\n                        q: term, // search term\n                        page_limit: 10,\n                        apikey: \"ju6z9mjyajq2djue3gbvv26t\" // please do not use so this example keeps working\n                    };\n                },\n                results: function (data, page) { // parse the results into the format expected by Select2.\n                    // since we are using custom formatting functions we do not need to alter remote JSON data\n                    return {\n                        results: data.movies\n                    };\n                }\n            },\n            initSelection: function (element, callback) {\n                // the input tag has a value attribute preloaded that points to a preselected movie's id\n                // this function resolves that id attribute to an object that select2 can render\n                // using its formatResult renderer - that way the movie name is shown preselected\n                var id = $(element).val();\n                if (id !== \"\") {\n                    $.ajax(\"http://api.rottentomatoes.com/api/public/v1.0/movies/\" + id + \".json\", {\n                        data: {\n                            apikey: \"ju6z9mjyajq2djue3gbvv26t\"\n                        },\n                        dataType: \"jsonp\"\n                    }).done(function (data) {\n                        callback(data);\n                    });\n                }\n            },\n            formatResult: movieFormatResult, // omitted for brevity, see the source of this page\n            formatSelection: movieFormatSelection, // omitted for brevity, see the source of this page\n            dropdownCssClass: \"bigdrop\", // apply css that makes the dropdown taller\n            escapeMarkup: function (m) {\n                return m;\n            } // we do not want to escape markup since we are displaying html in results\n        });\n    }\n\n    var handleMultiSelect = function () {\n        $('#my_multi_select1').multiSelect();\n        $('#my_multi_select2').multiSelect({\n            selectableOptgroup: true\n        });\n\n        $('#my_multi_select3').multiSelect({\n            selectableHeader: \"<input type='text' class='form-control search-input' autocomplete='off' placeholder='search...'>\",\n            selectionHeader: \"<input type='text' class='form-control search-input' autocomplete='off' placeholder='search...'>\",\n            afterInit: function (ms) {\n                var that = this,\n                    $selectableSearch = that.$selectableUl.prev(),\n                    $selectionSearch = that.$selectionUl.prev(),\n                    selectableSearchString = '#' + that.$container.attr('id') + ' .ms-elem-selectable:not(.ms-selected)',\n                    selectionSearchString = '#' + that.$container.attr('id') + ' .ms-elem-selection.ms-selected';\n\n                that.qs1 = $selectableSearch.quicksearch(selectableSearchString)\n                    .on('keydown', function (e) {\n                        if (e.which === 40) {\n                            that.$selectableUl.focus();\n                            return false;\n                        }\n                    });\n\n                that.qs2 = $selectionSearch.quicksearch(selectionSearchString)\n                    .on('keydown', function (e) {\n                        if (e.which == 40) {\n                            that.$selectionUl.focus();\n                            return false;\n                        }\n                    });\n            },\n            afterSelect: function () {\n                this.qs1.cache();\n                this.qs2.cache();\n            },\n            afterDeselect: function () {\n                this.qs1.cache();\n                this.qs2.cache();\n            }\n        });\n    }\n\n    var handleInputMasks = function () {\n        $.extend($.inputmask.defaults, {\n            'autounmask': true\n        });\n\n        $(\"#mask_date\").inputmask(\"d/m/y\", {\n            autoUnmask: true\n        }); //direct mask        \n        $(\"#mask_date1\").inputmask(\"d/m/y\", {\n            \"placeholder\": \"*\"\n        }); //change the placeholder\n        $(\"#mask_date2\").inputmask(\"d/m/y\", {\n            \"placeholder\": \"dd/mm/yyyy\"\n        }); //multi-char placeholder\n        $(\"#mask_phone\").inputmask(\"mask\", {\n            \"mask\": \"(999) 999-9999\"\n        }); //specifying fn & options\n        $(\"#mask_tin\").inputmask({\n            \"mask\": \"99-9999999\"\n        }); //specifying options only\n        $(\"#mask_number\").inputmask({\n            \"mask\": \"9\",\n            \"repeat\": 10,\n            \"greedy\": false\n        }); // ~ mask \"9\" or mask \"99\" or ... mask \"9999999999\"\n        $(\"#mask_decimal\").inputmask('decimal', {\n            rightAlignNumerics: false\n        }); //disables the right alignment of the decimal input\n        $(\"#mask_currency\").inputmask('€ 999.999.999,99', {\n            numericInput: true\n        }); //123456  =>  € ___.__1.234,56\n\n        $(\"#mask_currency2\").inputmask('€ 999,999,999.99', {\n            numericInput: true,\n            rightAlignNumerics: false,\n            greedy: false\n        }); //123456  =>  € ___.__1.234,56\n        $(\"#mask_ssn\").inputmask(\"999-99-9999\", {\n            placeholder: \" \",\n            clearMaskOnLostFocus: true\n        }); //default\n    }\n\n    var handleIPAddressInput = function () {\n        $('#input_ipv4').ipAddress();\n        $('#input_ipv6').ipAddress({\n            v: 6\n        });\n    }\n\n    var handlePasswordStrengthChecker = function () {\n        var initialized = false;\n        var input = $(\"#password_strength\");\n\n        input.keydown(function () {\n            if (initialized === false) {\n                // set base options\n                input.pwstrength({\n                    raisePower: 1.4,\n                    minChar: 8,\n                    verdicts: [\"Weak\", \"Normal\", \"Medium\", \"Strong\", \"Very Strong\"],\n                    scores: [17, 26, 40, 50, 60]\n                });\n\n                // add your own rule to calculate the password strength\n                input.pwstrength(\"addRule\", \"demoRule\", function (options, word, score) {\n                    return word.match(/[a-z].[0-9]/) && score;\n                }, 10, true);\n\n                // set as initialized \n                initialized = true;\n            }\n        });\n    }\n\n    var handleUsernameAvailabilityChecker1 = function () {\n        var input = $(\"#username1_input\");\n\n        $(\"#username1_checker\").click(function (e) {\n            var pop = $(this);\n\n            if (input.val() === \"\") {\n                input.closest('.form-group').removeClass('has-success').addClass('has-error');\n\n                pop.popover('destroy');\n                pop.popover({\n                    'placement': (App.isRTL() ? 'left' : 'right'),\n                    'html': true,\n                    'container': 'body',\n                    'content': 'Please enter a username to check its availability.',\n                });\n                // add error class to the popover\n                pop.data('bs.popover').tip().addClass('error');\n                // set last poped popover to be closed on click(see App.js => handlePopovers function)     \n                App.setLastPopedPopover(pop);\n                pop.popover('show');\n                e.stopPropagation(); // prevent closing the popover\n\n                return;\n            }\n\n            var btn = $(this);\n\n            btn.attr('disabled', true);\n\n            input.attr(\"readonly\", true).\n            attr(\"disabled\", true).\n            addClass(\"spinner\");\n\n            $.post('demo/username_checker.php', {\n                username: input.val()\n            }, function (res) {\n                btn.attr('disabled', false);\n\n                input.attr(\"readonly\", false).\n                attr(\"disabled\", false).\n                removeClass(\"spinner\");\n\n                if (res.status == 'OK') {\n                    input.closest('.form-group').removeClass('has-error').addClass('has-success');\n\n                    pop.popover('destroy');\n                    pop.popover({\n                        'html': true,\n                        'placement': (App.isRTL() ? 'left' : 'right'),\n                        'container': 'body',\n                        'content': res.message,\n                    });\n                    pop.popover('show');\n                    pop.data('bs.popover').tip().removeClass('error').addClass('success');\n                } else {\n                    input.closest('.form-group').removeClass('has-success').addClass('has-error');\n\n                    pop.popover('destroy');\n                    pop.popover({\n                        'html': true,\n                        'placement': (App.isRTL() ? 'left' : 'right'),\n                        'container': 'body',\n                        'content': res.message,\n                    });\n                    pop.popover('show');\n                    pop.data('bs.popover').tip().removeClass('success').addClass('error');\n                    App.setLastPopedPopover(pop);\n                }\n\n            }, 'json');\n\n        });\n    }\n\n    var handleUsernameAvailabilityChecker2 = function () {\n        $(\"#username2_input\").change(function () {\n            var input = $(this);\n\n            if (input.val() === \"\") {\n                return;\n            }\n\n            input.attr(\"readonly\", true).\n            attr(\"disabled\", true).\n            addClass(\"spinner\");\n\n            $.post('demo/username_checker.php', {\n                username: input.val()\n            }, function (res) {\n                input.attr(\"readonly\", false).\n                attr(\"disabled\", false).\n                removeClass(\"spinner\");\n\n                // change popover font color based on the result\n                if (res.status == 'OK') {\n                    input.closest('.form-group').removeClass('has-error').addClass('has-success');\n                    $('.icon-exclamation-sign', input.closest('.form-group')).remove();\n                    input.before('<i class=\"icon-ok\"></i>');\n                    input.data('bs.popover').tip().removeClass('error').addClass('success');\n                } else {\n                    input.closest('.form-group').removeClass('has-success').addClass('has-error');\n                    $('.icon-ok', input.closest('.form-group')).remove();\n                    input.before('<i class=\"icon-exclamation-sign\"></i>');\n\n                    input.popover('destroy');\n                    input.popover({\n                        'html': true,\n                        'placement': (App.isRTL() ? 'left' : 'right'),\n                        'container': 'body',\n                        'content': res.message,\n                    });\n                    input.popover('show');\n                    input.data('bs.popover').tip().removeClass('success').addClass('error');\n\n                    App.setLastPopedPopover(input);\n                }\n\n            }, 'json');\n\n        });\n    }\n\n    return {\n        //main function to initiate the module\n        init: function () {\n            handleBootstrapTouchSpin();\n            handleBootstrapMaxlength();\n            handleSpinners();\n            handleWysihtml5();\n            handleTagsInput();\n            handleDatePickers();\n            handleTimePickers();\n            handleDatetimePicker();\n            handleDateRangePickers();\n            handleClockfaceTimePickers();\n            handleColorPicker();\n            handleSelect2();\n            handleSelect2Modal();\n            handleInputMasks();\n            handleIPAddressInput();\n            handleMultiSelect();\n            handlePasswordStrengthChecker();\n            handleUsernameAvailabilityChecker1();\n            handleUsernameAvailabilityChecker2();\n        }\n    };\n\n}();"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/scripts/form-dropzone.js",
    "content": "var FormDropzone = function () {\n\n\n    return {\n        //main function to initiate the module\n        init: function () {  \n\n            Dropzone.options.myDropzone = {\n                init: function() {\n                    this.on(\"addedfile\", function(file) {\n                        // Create the remove button\n                        var removeButton = Dropzone.createElement(\"<button class='btn btn-sm btn-block'>Remove file</button>\");\n                        \n                        // Capture the Dropzone instance as closure.\n                        var _this = this;\n\n                        // Listen to the click event\n                        removeButton.addEventListener(\"click\", function(e) {\n                          // Make sure the button click doesn't submit the form:\n                          e.preventDefault();\n                          e.stopPropagation();\n\n                          // Remove the file preview.\n                          _this.removeFile(file);\n                          // If you want to the delete the file on the server as well,\n                          // you can do the AJAX request here.\n                        });\n\n                        // Add the button to the file preview element.\n                        file.previewElement.appendChild(removeButton);\n                    });\n                }            \n            }\n        }\n    };\n}();"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/scripts/form-editable.js",
    "content": "var FormEditable = function () {\n\n    $.mockjaxSettings.responseTime = 500;\n\n    var log = function (settings, response) {\n        var s = [],\n            str;\n        s.push(settings.type.toUpperCase() + ' url = \"' + settings.url + '\"');\n        for (var a in settings.data) {\n            if (settings.data[a] && typeof settings.data[a] === 'object') {\n                str = [];\n                for (var j in settings.data[a]) {\n                    str.push(j + ': \"' + settings.data[a][j] + '\"');\n                }\n                str = '{ ' + str.join(', ') + ' }';\n            } else {\n                str = '\"' + settings.data[a] + '\"';\n            }\n            s.push(a + ' = ' + str);\n        }\n        s.push('RESPONSE: status = ' + response.status);\n\n        if (response.responseText) {\n            if ($.isArray(response.responseText)) {\n                s.push('[');\n                $.each(response.responseText, function (i, v) {\n                    s.push('{value: ' + v.value + ', text: \"' + v.text + '\"}');\n                });\n                s.push(']');\n            } else {\n                s.push($.trim(response.responseText));\n            }\n        }\n        s.push('--------------------------------------\\n');\n        $('#console').val(s.join('\\n') + $('#console').val());\n    }\n\n    var initAjaxMock = function () {\n        //ajax mocks\n\n        $.mockjax({\n            url: '/post',\n            response: function (settings) {\n                log(settings, this);\n            }\n        });\n\n        $.mockjax({\n            url: '/error',\n            status: 400,\n            statusText: 'Bad Request',\n            response: function (settings) {\n                this.responseText = 'Please input correct value';\n                log(settings, this);\n            }\n        });\n\n        $.mockjax({\n            url: '/status',\n            status: 500,\n            response: function (settings) {\n                this.responseText = 'Internal Server Error';\n                log(settings, this);\n            }\n        });\n\n        $.mockjax({\n            url: '/groups',\n            response: function (settings) {\n                this.responseText = [{\n                        value: 0,\n                        text: 'Guest'\n                    }, {\n                        value: 1,\n                        text: 'Service'\n                    }, {\n                        value: 2,\n                        text: 'Customer'\n                    }, {\n                        value: 3,\n                        text: 'Operator'\n                    }, {\n                        value: 4,\n                        text: 'Support'\n                    }, {\n                        value: 5,\n                        text: 'Admin'\n                    }\n                ];\n                log(settings, this);\n            }\n        });\n\n    }\n\n    var initEditables = function () {\n\n        //set editable mode based on URL parameter\n        if (App.getURLParameter('mode') == 'inline') {\n            $.fn.editable.defaults.mode = 'inline';\n            $('#inline').attr(\"checked\", true);\n            jQuery.uniform.update('#inline');\n        } else {\n            $('#inline').attr(\"checked\", false);\n            jQuery.uniform.update('#inline');\n        }\n\n        //global settings \n        $.fn.editable.defaults.inputclass = 'form-control';\n        $.fn.editable.defaults.url = '/post';\n\n        //editables element samples \n        $('#username').editable({\n            url: '/post',\n            type: 'text',\n            pk: 1,\n            name: 'username',\n            title: 'Enter username'\n        });\n\n        $('#firstname').editable({\n            validate: function (value) {\n                if ($.trim(value) == '') return 'This field is required';\n            }\n        });\n\n        $('#sex').editable({\n            prepend: \"not selected\",\n            inputclass: 'form-control',\n            source: [{\n                    value: 1,\n                    text: 'Male'\n                }, {\n                    value: 2,\n                    text: 'Female'\n                }\n            ],\n            display: function (value, sourceData) {\n                var colors = {\n                    \"\": \"gray\",\n                    1: \"green\",\n                    2: \"blue\"\n                },\n                    elem = $.grep(sourceData, function (o) {\n                        return o.value == value;\n                    });\n\n                if (elem.length) {\n                    $(this).text(elem[0].text).css(\"color\", colors[value]);\n                } else {\n                    $(this).empty();\n                }\n            }\n        });\n\n        $('#status').editable();\n\n        $('#group').editable({\n            showbuttons: false\n        });\n\n        $('#vacation').editable({\n            rtl : App.isRTL() \n        });\n\n        $('#dob').editable({\n            inputclass: 'form-control',\n        });\n\n        $('#event').editable({\n            placement: (App.isRTL() ? 'left' : 'right'),\n            combodate: {\n                firstItem: 'name'\n            }\n        });\n\n        $('#meeting_start').editable({\n            format: 'yyyy-mm-dd hh:ii',\n            viewformat: 'dd/mm/yyyy hh:ii',\n            validate: function (v) {\n                if (v && v.getDate() == 10) return 'Day cant be 10!';\n            },\n            datetimepicker: {\n                rtl : App.isRTL(),\n                todayBtn: 'linked',\n                weekStart: 1\n            }\n        });\n\n        $('#comments').editable({\n            showbuttons: 'bottom'\n        });\n\n        $('#note').editable({\n            showbuttons : (App.isRTL() ? 'left' : 'right')\n        });\n\n        $('#pencil').click(function (e) {\n            e.stopPropagation();\n            e.preventDefault();\n            $('#note').editable('toggle');\n        });\n\n        $('#state').editable({\n            source: [\"Alabama\", \"Alaska\", \"Arizona\", \"Arkansas\", \"California\", \"Colorado\", \"Connecticut\", \"Delaware\", \"Florida\", \"Georgia\", \"Hawaii\", \"Idaho\", \"Illinois\", \"Indiana\", \"Iowa\", \"Kansas\", \"Kentucky\", \"Louisiana\", \"Maine\", \"Maryland\", \"Massachusetts\", \"Michigan\", \"Minnesota\", \"Mississippi\", \"Missouri\", \"Montana\", \"Nebraska\", \"Nevada\", \"New Hampshire\", \"New Jersey\", \"New Mexico\", \"New York\", \"North Dakota\", \"North Carolina\", \"Ohio\", \"Oklahoma\", \"Oregon\", \"Pennsylvania\", \"Rhode Island\", \"South Carolina\", \"South Dakota\", \"Tennessee\", \"Texas\", \"Utah\", \"Vermont\", \"Virginia\", \"Washington\", \"West Virginia\", \"Wisconsin\", \"Wyoming\"]\n        });\n\n        $('#fruits').editable({\n            pk: 1,\n            limit: 3,\n            source: [{\n                    value: 1,\n                    text: 'banana'\n                }, {\n                    value: 2,\n                    text: 'peach'\n                }, {\n                    value: 3,\n                    text: 'apple'\n                }, {\n                    value: 4,\n                    text: 'watermelon'\n                }, {\n                    value: 5,\n                    text: 'orange'\n                }\n            ]\n        });\n\n        $('#fruits').on('shown', function(e, reason) {\n            App.initUniform();\n        });\n\n        $('#tags').editable({\n            inputclass: 'form-control input-medium',\n            select2: {\n                tags: ['html', 'javascript', 'css', 'ajax'],\n                tokenSeparators: [\",\", \" \"]\n            }\n        });\n\n        var countries = [];\n        $.each({\n            \"BD\": \"Bangladesh\",\n            \"BE\": \"Belgium\",\n            \"BF\": \"Burkina Faso\",\n            \"BG\": \"Bulgaria\",\n            \"BA\": \"Bosnia and Herzegovina\",\n            \"BB\": \"Barbados\",\n            \"WF\": \"Wallis and Futuna\",\n            \"BL\": \"Saint Bartelemey\",\n            \"BM\": \"Bermuda\",\n            \"BN\": \"Brunei Darussalam\",\n            \"BO\": \"Bolivia\",\n            \"BH\": \"Bahrain\",\n            \"BI\": \"Burundi\",\n            \"BJ\": \"Benin\",\n            \"BT\": \"Bhutan\",\n            \"JM\": \"Jamaica\",\n            \"BV\": \"Bouvet Island\",\n            \"BW\": \"Botswana\",\n            \"WS\": \"Samoa\",\n            \"BR\": \"Brazil\",\n            \"BS\": \"Bahamas\",\n            \"JE\": \"Jersey\",\n            \"BY\": \"Belarus\",\n            \"O1\": \"Other Country\",\n            \"LV\": \"Latvia\",\n            \"RW\": \"Rwanda\",\n            \"RS\": \"Serbia\",\n            \"TL\": \"Timor-Leste\",\n            \"RE\": \"Reunion\",\n            \"LU\": \"Luxembourg\",\n            \"TJ\": \"Tajikistan\",\n            \"RO\": \"Romania\",\n            \"PG\": \"Papua New Guinea\",\n            \"GW\": \"Guinea-Bissau\",\n            \"GU\": \"Guam\",\n            \"GT\": \"Guatemala\",\n            \"GS\": \"South Georgia and the South Sandwich Islands\",\n            \"GR\": \"Greece\",\n            \"GQ\": \"Equatorial Guinea\",\n            \"GP\": \"Guadeloupe\",\n            \"JP\": \"Japan\",\n            \"GY\": \"Guyana\",\n            \"GG\": \"Guernsey\",\n            \"GF\": \"French Guiana\",\n            \"GE\": \"Georgia\",\n            \"GD\": \"Grenada\",\n            \"GB\": \"United Kingdom\",\n            \"GA\": \"Gabon\",\n            \"SV\": \"El Salvador\",\n            \"GN\": \"Guinea\",\n            \"GM\": \"Gambia\",\n            \"GL\": \"Greenland\",\n            \"GI\": \"Gibraltar\",\n            \"GH\": \"Ghana\",\n            \"OM\": \"Oman\",\n            \"TN\": \"Tunisia\",\n            \"JO\": \"Jordan\",\n            \"HR\": \"Croatia\",\n            \"HT\": \"Haiti\",\n            \"HU\": \"Hungary\",\n            \"HK\": \"Hong Kong\",\n            \"HN\": \"Honduras\",\n            \"HM\": \"Heard Island and McDonald Islands\",\n            \"VE\": \"Venezuela\",\n            \"PR\": \"Puerto Rico\",\n            \"PS\": \"Palestinian Territory\",\n            \"PW\": \"Palau\",\n            \"PT\": \"Portugal\",\n            \"SJ\": \"Svalbard and Jan Mayen\",\n            \"PY\": \"Paraguay\",\n            \"IQ\": \"Iraq\",\n            \"PA\": \"Panama\",\n            \"PF\": \"French Polynesia\",\n            \"BZ\": \"Belize\",\n            \"PE\": \"Peru\",\n            \"PK\": \"Pakistan\",\n            \"PH\": \"Philippines\",\n            \"PN\": \"Pitcairn\",\n            \"TM\": \"Turkmenistan\",\n            \"PL\": \"Poland\",\n            \"PM\": \"Saint Pierre and Miquelon\",\n            \"ZM\": \"Zambia\",\n            \"EH\": \"Western Sahara\",\n            \"RU\": \"Russian Federation\",\n            \"EE\": \"Estonia\",\n            \"EG\": \"Egypt\",\n            \"TK\": \"Tokelau\",\n            \"ZA\": \"South Africa\",\n            \"EC\": \"Ecuador\",\n            \"IT\": \"Italy\",\n            \"VN\": \"Vietnam\",\n            \"SB\": \"Solomon Islands\",\n            \"EU\": \"Europe\",\n            \"ET\": \"Ethiopia\",\n            \"SO\": \"Somalia\",\n            \"ZW\": \"Zimbabwe\",\n            \"SA\": \"Saudi Arabia\",\n            \"ES\": \"Spain\",\n            \"ER\": \"Eritrea\",\n            \"ME\": \"Montenegro\",\n            \"MD\": \"Moldova, Republic of\",\n            \"MG\": \"Madagascar\",\n            \"MF\": \"Saint Martin\",\n            \"MA\": \"Morocco\",\n            \"MC\": \"Monaco\",\n            \"UZ\": \"Uzbekistan\",\n            \"MM\": \"Myanmar\",\n            \"ML\": \"Mali\",\n            \"MO\": \"Macao\",\n            \"MN\": \"Mongolia\",\n            \"MH\": \"Marshall Islands\",\n            \"MK\": \"Macedonia\",\n            \"MU\": \"Mauritius\",\n            \"MT\": \"Malta\",\n            \"MW\": \"Malawi\",\n            \"MV\": \"Maldives\",\n            \"MQ\": \"Martinique\",\n            \"MP\": \"Northern Mariana Islands\",\n            \"MS\": \"Montserrat\",\n            \"MR\": \"Mauritania\",\n            \"IM\": \"Isle of Man\",\n            \"UG\": \"Uganda\",\n            \"TZ\": \"Tanzania, United Republic of\",\n            \"MY\": \"Malaysia\",\n            \"MX\": \"Mexico\",\n            \"IL\": \"Israel\",\n            \"FR\": \"France\",\n            \"IO\": \"British Indian Ocean Territory\",\n            \"FX\": \"France, Metropolitan\",\n            \"SH\": \"Saint Helena\",\n            \"FI\": \"Finland\",\n            \"FJ\": \"Fiji\",\n            \"FK\": \"Falkland Islands (Malvinas)\",\n            \"FM\": \"Micronesia, Federated States of\",\n            \"FO\": \"Faroe Islands\",\n            \"NI\": \"Nicaragua\",\n            \"NL\": \"Netherlands\",\n            \"NO\": \"Norway\",\n            \"NA\": \"Namibia\",\n            \"VU\": \"Vanuatu\",\n            \"NC\": \"New Caledonia\",\n            \"NE\": \"Niger\",\n            \"NF\": \"Norfolk Island\",\n            \"NG\": \"Nigeria\",\n            \"NZ\": \"New Zealand\",\n            \"NP\": \"Nepal\",\n            \"NR\": \"Nauru\",\n            \"NU\": \"Niue\",\n            \"CK\": \"Cook Islands\",\n            \"CI\": \"Cote d'Ivoire\",\n            \"CH\": \"Switzerland\",\n            \"CO\": \"Colombia\",\n            \"CN\": \"China\",\n            \"CM\": \"Cameroon\",\n            \"CL\": \"Chile\",\n            \"CC\": \"Cocos (Keeling) Islands\",\n            \"CA\": \"Canada\",\n            \"CG\": \"Congo\",\n            \"CF\": \"Central African Republic\",\n            \"CD\": \"Congo, The Democratic Republic of the\",\n            \"CZ\": \"Czech Republic\",\n            \"CY\": \"Cyprus\",\n            \"CX\": \"Christmas Island\",\n            \"CR\": \"Costa Rica\",\n            \"CV\": \"Cape Verde\",\n            \"CU\": \"Cuba\",\n            \"SZ\": \"Swaziland\",\n            \"SY\": \"Syrian Arab Republic\",\n            \"KG\": \"Kyrgyzstan\",\n            \"KE\": \"Kenya\",\n            \"SR\": \"Suriname\",\n            \"KI\": \"Kiribati\",\n            \"KH\": \"Cambodia\",\n            \"KN\": \"Saint Kitts and Nevis\",\n            \"KM\": \"Comoros\",\n            \"ST\": \"Sao Tome and Principe\",\n            \"SK\": \"Slovakia\",\n            \"KR\": \"Korea, Republic of\",\n            \"SI\": \"Slovenia\",\n            \"KP\": \"Korea, Democratic People's Republic of\",\n            \"KW\": \"Kuwait\",\n            \"SN\": \"Senegal\",\n            \"SM\": \"San Marino\",\n            \"SL\": \"Sierra Leone\",\n            \"SC\": \"Seychelles\",\n            \"KZ\": \"Kazakhstan\",\n            \"KY\": \"Cayman Islands\",\n            \"SG\": \"Singapore\",\n            \"SE\": \"Sweden\",\n            \"SD\": \"Sudan\",\n            \"DO\": \"Dominican Republic\",\n            \"DM\": \"Dominica\",\n            \"DJ\": \"Djibouti\",\n            \"DK\": \"Denmark\",\n            \"VG\": \"Virgin Islands, British\",\n            \"DE\": \"Germany\",\n            \"YE\": \"Yemen\",\n            \"DZ\": \"Algeria\",\n            \"US\": \"United States\",\n            \"UY\": \"Uruguay\",\n            \"YT\": \"Mayotte\",\n            \"UM\": \"United States Minor Outlying Islands\",\n            \"LB\": \"Lebanon\",\n            \"LC\": \"Saint Lucia\",\n            \"LA\": \"Lao People's Democratic Republic\",\n            \"TV\": \"Tuvalu\",\n            \"TW\": \"Taiwan\",\n            \"TT\": \"Trinidad and Tobago\",\n            \"TR\": \"Turkey\",\n            \"LK\": \"Sri Lanka\",\n            \"LI\": \"Liechtenstein\",\n            \"A1\": \"Anonymous Proxy\",\n            \"TO\": \"Tonga\",\n            \"LT\": \"Lithuania\",\n            \"A2\": \"Satellite Provider\",\n            \"LR\": \"Liberia\",\n            \"LS\": \"Lesotho\",\n            \"TH\": \"Thailand\",\n            \"TF\": \"French Southern Territories\",\n            \"TG\": \"Togo\",\n            \"TD\": \"Chad\",\n            \"TC\": \"Turks and Caicos Islands\",\n            \"LY\": \"Libyan Arab Jamahiriya\",\n            \"VA\": \"Holy See (Vatican City State)\",\n            \"VC\": \"Saint Vincent and the Grenadines\",\n            \"AE\": \"United Arab Emirates\",\n            \"AD\": \"Andorra\",\n            \"AG\": \"Antigua and Barbuda\",\n            \"AF\": \"Afghanistan\",\n            \"AI\": \"Anguilla\",\n            \"VI\": \"Virgin Islands, U.S.\",\n            \"IS\": \"Iceland\",\n            \"IR\": \"Iran, Islamic Republic of\",\n            \"AM\": \"Armenia\",\n            \"AL\": \"Albania\",\n            \"AO\": \"Angola\",\n            \"AN\": \"Netherlands Antilles\",\n            \"AQ\": \"Antarctica\",\n            \"AP\": \"Asia/Pacific Region\",\n            \"AS\": \"American Samoa\",\n            \"AR\": \"Argentina\",\n            \"AU\": \"Australia\",\n            \"AT\": \"Austria\",\n            \"AW\": \"Aruba\",\n            \"IN\": \"India\",\n            \"AX\": \"Aland Islands\",\n            \"AZ\": \"Azerbaijan\",\n            \"IE\": \"Ireland\",\n            \"ID\": \"Indonesia\",\n            \"UA\": \"Ukraine\",\n            \"QA\": \"Qatar\",\n            \"MZ\": \"Mozambique\"\n        }, function (k, v) {\n            countries.push({\n                id: k,\n                text: v\n            });\n        });\n\n        $('#country').editable({\n            inputclass: 'form-control input-medium',\n            source: countries\n        });\n\n        $('#address').editable({\n            url: '/post',\n            value: {\n                city: \"San Francisco\",\n                street: \"Valencia\",\n                building: \"#24\"\n            },\n            validate: function (value) {\n                if (value.city == '') return 'city is required!';\n            },\n            display: function (value) {\n                if (!value) {\n                    $(this).empty();\n                    return;\n                }\n                var html = '<b>' + $('<div>').text(value.city).html() + '</b>, ' + $('<div>').text(value.street).html() + ' st., bld. ' + $('<div>').text(value.building).html();\n                $(this).html(html);\n            }\n        });\n    }\n\n    return {\n        //main function to initiate the module\n        init: function () {\n\n            // inii ajax simulation\n            initAjaxMock();\n\n            // init editable elements\n            initEditables();\n            \n            // init editable toggler\n            $('#enable').click(function () {\n                $('#user .editable').editable('toggleDisabled');\n            });\n\n            // init \n            $('#inline').on('change', function (e) {\n                if ($(this).is(':checked')) {\n                    window.location.href = 'form_editable.html?mode=inline';\n                } else {\n                    window.location.href = 'form_editable.html';\n                }\n            });\n\n            // handle editable elements on hidden event fired\n            $('#user .editable').on('hidden', function (e, reason) {\n                if (reason === 'save' || reason === 'nochange') {\n                    var $next = $(this).closest('tr').next().find('.editable');\n                    if ($('#autoopen').is(':checked')) {\n                        setTimeout(function () {\n                            $next.editable('show');\n                        }, 300);\n                    } else {\n                        $next.focus();\n                    }\n                }\n            });\n\n\n        }\n\n    };\n\n}();"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/scripts/form-fileupload.js",
    "content": "var FormFileUpload = function () {\n\n\n    return {\n        //main function to initiate the module\n        init: function () {\n\n             // Initialize the jQuery File Upload widget:\n            $('#fileupload').fileupload({\n                // Uncomment the following to send cross-domain cookies:\n                //xhrFields: {withCredentials: true},                \n                url: 'assets/plugins/jquery-file-upload/server/php/'\n            });\n\n            // Enable iframe cross-domain access via redirect option:\n            $('#fileupload').fileupload(\n                'option',\n                'redirect',\n                window.location.href.replace(\n                    /\\/[^\\/]*$/,\n                    '/cors/result.html?%s'\n                )\n            );\n\n            // Demo settings:\n            $('#fileupload').fileupload('option', {\n                url: $('#fileupload').fileupload('option', 'url'),\n                // Enable image resizing, except for Android and Opera,\n                // which actually support image resizing, but fail to\n                // send Blob objects via XHR requests:\n                disableImageResize: /Android(?!.*Chrome)|Opera/\n                    .test(window.navigator.userAgent),\n                maxFileSize: 5000000,\n                acceptFileTypes: /(\\.|\\/)(gif|jpe?g|png)$/i\n            });\n\n                // Upload server status check for browsers with CORS support:\n            if ($.support.cors) {\n                $.ajax({\n                    url: 'assets/plugins/jquery-file-upload/server/php/',\n                    type: 'HEAD'\n                }).fail(function () {\n                    $('<div class=\"alert alert-danger\"/>')\n                        .text('Upload server currently unavailable - ' +\n                                new Date())\n                        .appendTo('#fileupload');\n                });\n            }\n            \n            ////////////////////\n\n            // Initialize the jQuery File Upload widget:\n            $('#fileupload').fileupload({\n                // Uncomment the following to send cross-domain cookies:\n                //xhrFields: {withCredentials: true},\n                autoUpload: false,\n                url: 'assets/plugins/jquery-file-upload/server/php/'\n            });\n\n            // initialize uniform checkboxes  \n            App.initUniform('.fileupload-toggle-checkbox');\n        }\n\n    };\n\n}();"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/scripts/form-image-crop.js",
    "content": "var FormImageCrop = function () {\n\n    var demo1 = function() {\n        $('#demo1').Jcrop();\n    }\n\n    var demo2 = function() {\n        var jcrop_api;\n\n        $('#demo2').Jcrop({\n          onChange:   showCoords,\n          onSelect:   showCoords,\n          onRelease:  clearCoords\n        },function(){\n          jcrop_api = this;\n        });\n\n        $('#coords').on('change','input',function(e){\n          var x1 = $('#x1').val(),\n              x2 = $('#x2').val(),\n              y1 = $('#y1').val(),\n              y2 = $('#y2').val();\n          jcrop_api.setSelect([x1,y1,x2,y2]);\n        });\n\n        // Simple event handler, called from onChange and onSelect\n        // event handlers, as per the Jcrop invocation above\n        function showCoords(c)\n        {\n            $('#x1').val(c.x);\n            $('#y1').val(c.y);\n            $('#x2').val(c.x2);\n            $('#y2').val(c.y2);\n            $('#w').val(c.w);\n            $('#h').val(c.h);\n        };\n\n        function clearCoords()\n        {\n            $('#coords input').val('');\n        };\n    }\n\n    var demo3 = function() {\n        // Create variables (in this scope) to hold the API and image size\n        var jcrop_api,\n            boundx,\n            boundy,\n            // Grab some information about the preview pane\n            $preview = $('#preview-pane'),\n            $pcnt = $('#preview-pane .preview-container'),\n            $pimg = $('#preview-pane .preview-container img'),\n\n            xsize = $pcnt.width(),\n            ysize = $pcnt.height();\n        \n            console.log('init',[xsize,ysize]);\n\n        $('#demo3').Jcrop({\n          onChange: updatePreview,\n          onSelect: updatePreview,\n          aspectRatio: xsize / ysize\n        },function(){\n          // Use the API to get the real image size\n          var bounds = this.getBounds();\n          boundx = bounds[0];\n          boundy = bounds[1];\n          // Store the API in the jcrop_api variable\n          jcrop_api = this;\n          // Move the preview into the jcrop container for css positioning\n          $preview.appendTo(jcrop_api.ui.holder);\n        });\n\n        function updatePreview(c)\n        {\n          if (parseInt(c.w) > 0)\n          {\n            var rx = xsize / c.w;\n            var ry = ysize / c.h;\n\n            $pimg.css({\n              width: Math.round(rx * boundx) + 'px',\n              height: Math.round(ry * boundy) + 'px',\n              marginLeft: '-' + Math.round(rx * c.x) + 'px',\n              marginTop: '-' + Math.round(ry * c.y) + 'px'\n            });\n          }\n        };\n    }\n\n    var demo4 = function() {\n        var jcrop_api;\n\n        $('#demo4').Jcrop({\n          bgFade:     true,\n          bgOpacity: .2,\n          setSelect: [ 60, 70, 540, 330 ]\n        },function(){\n          jcrop_api = this;\n        });\n\n        $('#fadetog').change(function(){\n          jcrop_api.setOptions({\n            bgFade: this.checked\n          });\n        }).attr('checked', true);\n        App.updateUniform('#fadetog');\n\n        $('#shadetog').change(function(){\n          if (this.checked) $('#shadetxt').slideDown();\n            else $('#shadetxt').slideUp();\n          jcrop_api.setOptions({\n            shade: this.checked\n          });\n        }).attr('checked', false);\n\n        // Define page sections\n        var sections = {\n          bgc_buttons: 'Change bgColor',\n          bgo_buttons: 'Change bgOpacity',\n          anim_buttons: 'Animate Selection'\n        };\n        // Define animation buttons\n        var ac = {\n          anim1: [217,122,382,284],\n          anim2: [20,20,580,380],\n          anim3: [24,24,176,376],\n          anim4: [347,165,550,355],\n          anim5: [136,55,472,183]\n        };\n        // Define bgOpacity buttons\n        var bgo = {\n          Low: .2,\n          Mid: .5,\n          High: .8,\n          Full: 1\n        };\n        // Define bgColor buttons\n        var bgc = {\n          R: '#900',\n          B: '#4BB6F0',\n          Y: '#F0B207',\n          G: '#46B81C',\n          W: 'white',\n          K: 'black'\n        };\n        // Create fieldset targets for buttons\n        for(i in sections)\n          insertSection(i,sections[i]);\n\n        function create_btn(c) {\n          var $o = $('<button />').addClass('btn small');\n          if (c) $o.append(c);\n          return $o;\n        }\n\n        var a_count = 1;\n        // Create animation buttons\n        for(i in ac) {\n          $('#anim_buttons .btn-group')\n            .append(\n              create_btn(a_count++).click(animHandler(ac[i])),\n              ' '\n            );\n        }\n\n        $('#anim_buttons .btn-group').append(\n          create_btn('Bye!').click(function(e){\n            $(e.target).addClass('active');\n            jcrop_api.animateTo(\n              [300,200,300,200],\n              function(){\n                this.release();\n                $(e.target).closest('.btn-group').find('.active').removeClass('active');\n              }\n            );\n            return false;\n          })\n        );\n\n        // Create bgOpacity buttons\n        for(i in bgo) {\n          $('#bgo_buttons .btn-group').append(\n            create_btn(i).click(setoptHandler('bgOpacity',bgo[i])),\n            ' '\n          );\n        }\n        // Create bgColor buttons\n        for(i in bgc) {\n          $('#bgc_buttons .btn-group').append(\n            create_btn(i).css({\n              background: bgc[i],\n              color: ((i == 'K') || (i == 'R'))?'white':'black'\n            }).click(setoptHandler('bgColor',bgc[i])), ' '\n          );\n        }\n        // Function to insert named sections into interface\n        function insertSection(k,v) {\n          $('#interface').prepend(\n            $('<fieldset></fieldset>').attr('id',k).append(\n              $('<h4></h4>').append(v),\n              '<div class=\"btn-toolbar\"><div class=\"btn-group\"></div></div>'\n            )\n          );\n        };\n        // Handler for option-setting buttons\n        function setoptHandler(k,v) {\n          return function(e) {\n            $(e.target).closest('.btn-group').find('.active').removeClass('active');\n            $(e.target).addClass('active');\n            var opt = { };\n            opt[k] = v;\n            jcrop_api.setOptions(opt);\n            return false;\n          };\n        };\n        // Handler for animation buttons\n        function animHandler(v) {\n          return function(e) {\n            $(e.target).addClass('active');\n            jcrop_api.animateTo(v,function(){\n              $(e.target).closest('.btn-group').find('.active').removeClass('active');\n            });\n            return false;\n          };\n        };\n\n        $('#bgo_buttons .btn:first,#bgc_buttons .btn:last').addClass('active');\n        $('#interface').show();\n    }\n\n    var demo5 = function() {\n        // The variable jcrop_api will hold a reference to the\n        // Jcrop API once Jcrop is instantiated.\n        var jcrop_api;\n\n        // In this example, since Jcrop may be attached or detached\n        // at the whim of the user, I've wrapped the call into a function\n        initJcrop();\n        \n        // The function is pretty simple\n        function initJcrop()//{{{\n        {\n          // Hide any interface elements that require Jcrop\n          // (This is for the local user interface portion.)\n          $('.requiresjcrop').hide();\n\n          // Invoke Jcrop in typical fashion\n          $('#demo5').Jcrop({\n            onRelease: releaseCheck\n          },function(){\n\n            jcrop_api = this;\n            jcrop_api.animateTo([100,100,400,300]);\n\n            // Setup and dipslay the interface for \"enabled\"\n            $('#can_click,#can_move,#can_size').attr('checked','checked');\n            App.updateUniform('#can_click,#can_move,#can_size');\n\n            $('#ar_lock,#size_lock,#bg_swap').attr('checked',false);\n            App.updateUniform('#ar_lock,#size_lock,#bg_swap');\n            \n            $('.requiresjcrop').show();\n\n          });\n\n        };\n        //}}}\n\n        // Use the API to find cropping dimensions\n        // Then generate a random selection\n        // This function is used by setSelect and animateTo buttons\n        // Mainly for demonstration purposes\n        function getRandom() {\n          var dim = jcrop_api.getBounds();\n          return [\n            Math.round(Math.random() * dim[0]),\n            Math.round(Math.random() * dim[1]),\n            Math.round(Math.random() * dim[0]),\n            Math.round(Math.random() * dim[1])\n          ];\n        };\n\n        // This function is bound to the onRelease handler...\n        // In certain circumstances (such as if you set minSize\n        // and aspectRatio together), you can inadvertently lose\n        // the selection. This callback re-enables creating selections\n        // in such a case. Although the need to do this is based on a\n        // buggy behavior, it's recommended that you in some way trap\n        // the onRelease callback if you use allowSelect: false\n        function releaseCheck()\n        {\n          jcrop_api.setOptions({ allowSelect: true });\n          $('#can_click').attr('checked',false);\n          App.updateUniform('#can_click');\n        };\n\n        // Attach interface buttons\n        // This may appear to be a lot of code but it's simple stuff\n        $('#setSelect').click(function(e) {\n          // Sets a random selection\n          jcrop_api.setSelect(getRandom());\n        });\n        $('#animateTo').click(function(e) {\n          // Animates to a random selection\n          jcrop_api.animateTo(getRandom());\n        });\n        $('#release').click(function(e) {\n          // Release method clears the selection\n          jcrop_api.release();\n        });\n        $('#disable').click(function(e) {\n          // Disable Jcrop instance\n          jcrop_api.disable();\n          // Update the interface to reflect disabled state\n          $('#enable').show();\n          $('.requiresjcrop').hide();\n        });\n        $('#enable').click(function(e) {\n          // Re-enable Jcrop instance\n          jcrop_api.enable();\n          // Update the interface to reflect enabled state\n          $('#enable').hide();\n          $('.requiresjcrop').show();\n        });\n        $('#rehook').click(function(e) {\n          // This button is visible when Jcrop has been destroyed\n          // It performs the re-attachment and updates the UI\n          $('#rehook,#enable').hide();\n          initJcrop();\n          $('#unhook,.requiresjcrop').show();\n          return false;\n        });\n        $('#unhook').click(function(e) {\n          // Destroy Jcrop widget, restore original state\n          jcrop_api.destroy();\n          // Update the interface to reflect un-attached state\n          $('#unhook,#enable,.requiresjcrop').hide();\n          $('#rehook').show();\n          return false;\n        });\n\n        // Hook up the three image-swapping buttons\n        $('#img1').click(function(e) {\n          $(this).addClass('active').closest('.btn-group')\n            .find('button.active').not(this).removeClass('active');\n\n          jcrop_api.setImage('assets/plugins/jcrop/demos/demo_files/sago.jpg');\n          jcrop_api.setOptions({ bgOpacity: .6 });\n          return false;\n        });\n        $('#img2').click(function(e) {\n          $(this).addClass('active').closest('.btn-group')\n            .find('button.active').not(this).removeClass('active');\n\n          jcrop_api.setImage('assets/plugins/jcrop/demos/demo_files/pool.jpg');\n          jcrop_api.setOptions({ bgOpacity: .6 });\n          return false;\n        });\n        $('#img3').click(function(e) {\n          $(this).addClass('active').closest('.btn-group')\n            .find('button.active').not(this).removeClass('active');\n\n          jcrop_api.setImage('assets/plugins/jcrop/demos/demo_files/sago.jpg',function(){\n            this.setOptions({\n              bgOpacity: 1,\n              outerImage: 'assets/plugins/jcrop/demos/demo_files/sagomod.jpg'\n            });\n            this.animateTo(getRandom());\n          });\n          return false;\n        });\n\n        // The checkboxes simply set options based on it's checked value\n        // Options are changed by passing a new options object\n\n        // Also, to prevent strange behavior, they are initially checked\n        // This matches the default initial state of Jcrop\n\n        $('#can_click').change(function(e) {\n          jcrop_api.setOptions({ allowSelect: !!this.checked });\n          jcrop_api.focus();\n        });\n        $('#can_move').change(function(e) {\n          jcrop_api.setOptions({ allowMove: !!this.checked });\n          jcrop_api.focus();\n        });\n        $('#can_size').change(function(e) {\n          jcrop_api.setOptions({ allowResize: !!this.checked });\n          jcrop_api.focus();\n        });\n        $('#ar_lock').change(function(e) {\n          jcrop_api.setOptions(this.checked?\n            { aspectRatio: 4/3 }: { aspectRatio: 0 });\n          jcrop_api.focus();\n        });\n        $('#size_lock').change(function(e) {\n          jcrop_api.setOptions(this.checked? {\n            minSize: [ 80, 80 ],\n            maxSize: [ 350, 350 ]\n          }: {\n            minSize: [ 0, 0 ],\n            maxSize: [ 0, 0 ]\n          });\n          jcrop_api.focus();\n        });\n\n    }\n\n    var demo6 = function() {\n        var api;\n\n        $('#demo6').Jcrop({\n          // start off with jcrop-light class\n          bgOpacity: 0.5,\n          bgColor: 'white',\n          addClass: 'jcrop-light'\n        },function(){\n          api = this;\n          api.setSelect([130,65,130+350,65+285]);\n          api.setOptions({ bgFade: true });\n          api.ui.selection.addClass('jcrop-selection');\n        });\n\n        $('#buttonbar').on('click','button',function(e){\n          var $t = $(this), $g = $t.closest('.btn-group');\n          $g.find('button.active').removeClass('active');\n          $t.addClass('active');\n          $g.find('[data-setclass]').each(function(){\n            var $th = $(this), c = $th.data('setclass'),\n              a = $th.hasClass('active');\n            if (a) {\n              api.ui.holder.addClass(c);\n              switch(c){\n                case 'jcrop-light':\n                  api.setOptions({ bgColor: 'white', bgOpacity: 0.5 });\n                  break;\n\n                case 'jcrop-dark':\n                  api.setOptions({ bgColor: 'black', bgOpacity: 0.4 });\n                  break;\n\n                case 'jcrop-normal':\n                  api.setOptions({\n                    bgColor: $.Jcrop.defaults.bgColor,\n                    bgOpacity: $.Jcrop.defaults.bgOpacity\n                  });\n                  break;\n              }\n            }\n            else api.ui.holder.removeClass(c);\n          });\n        });\n    }\n\n    var demo7 = function() {\n        // I did JSON.stringify(jcrop_api.tellSelect()) on a crop I liked:\n        var c = {\"x\":13,\"y\":7,\"x2\":487,\"y2\":107,\"w\":474,\"h\":100};\n\n        $('#demo7').Jcrop({\n          bgFade: true,\n          setSelect: [c.x,c.y,c.x2,c.y2]\n        });\n    }\n\n    var demo8 = function() {\n        $('#demo8').Jcrop({\n          aspectRatio: 1,\n          onSelect: updateCoords\n        });\n\n        function updateCoords(c)\n          {\n            $('#crop_x').val(c.x);\n            $('#crop_y').val(c.y);\n            $('#crop_w').val(c.w);\n            $('#crop_h').val(c.h);\n          };\n\n          $('#demo8_form').submit(function(){\n            if (parseInt($('#crop_w').val())) return true;\n            alert('Please select a crop region then press submit.');\n            return false;\n            });\n\n    }\n\n    var handleResponsive = function() {\n      if ($(window).width() <= 1024) {\n        $('.responsive-1024').addClass(\"col-md-12\");\n      } else {\n        $('.responsive-1024').removeClass(\"col-md-12\");\n      }\n    }\n\n    return {\n        //main function to initiate the module\n        init: function () {\n            \n            if (!jQuery().Jcrop) {;\n                return;\n            }\n\n            App.addResponsiveHandler(handleResponsive);\n            handleResponsive();\n\n            demo1();\n            demo2();\n            demo3();\n            demo4();\n            demo5();\n            demo6();\n            demo7();\n            demo8();\n        }\n\n    };\n\n}();"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/scripts/form-samples.js",
    "content": "var FormSamples = function () {\n\n\n    return {\n        //main function to initiate the module\n        init: function () {\n\n            // use select2 dropdown instead of chosen as select2 works fine with bootstrap on responsive layouts.\n            $('.select2_category').select2({\n\t            placeholder: \"Select an option\",\n\t            allowClear: true\n\t        });\n\n            $('.select2_sample1').select2({\n                placeholder: \"Select a State\",\n                allowClear: true\n            });\n\n            $(\".select2_sample2\").select2({\n                placeholder: \"Type to select an option\",\n                allowClear: true,\n                minimumInputLength: 1,\n                query: function (query) {\n                    var data = {\n                        results: []\n                    }, i, j, s;\n                    for (i = 1; i < 5; i++) {\n                        s = \"\";\n                        for (j = 0; j < i; j++) {\n                            s = s + query.term;\n                        }\n                        data.results.push({\n                            id: query.term + i,\n                            text: s\n                        });\n                    }\n                    query.callback(data);\n                }\n            });\n\n            $(\".select2_sample3\").select2({\n                tags: [\"red\", \"green\", \"blue\", \"yellow\", \"pink\"]\n            });\n\n        }\n\n    };\n\n}();"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/scripts/form-validation.js",
    "content": "var FormValidation = function () {\n\n    var handleValidation1 = function() {\n        // for more info visit the official plugin documentation: \n            // http://docs.jquery.com/Plugins/Validation\n\n            var form1 = $('#form_sample_1');\n            var error1 = $('.alert-danger', form1);\n            var success1 = $('.alert-success', form1);\n\n            form1.validate({\n                errorElement: 'span', //default input error message container\n                errorClass: 'help-block', // default input error message class\n                focusInvalid: false, // do not focus the last invalid input\n                ignore: \"\",\n                rules: {\n                    name: {\n                        minlength: 2,\n                        required: true\n                    },\n                    email: {\n                        required: true,\n                        email: true\n                    },\n                    url: {\n                        required: true,\n                        url: true\n                    },\n                    number: {\n                        required: true,\n                        number: true\n                    },\n                    digits: {\n                        required: true,\n                        digits: true\n                    },\n                    creditcard: {\n                        required: true,\n                        creditcard: true\n                    },\n                    occupation: {\n                        minlength: 5,\n                    },\n                    category: {\n                        required: true\n                    }\n                },\n\n                invalidHandler: function (event, validator) { //display error alert on form submit              \n                    success1.hide();\n                    error1.show();\n                    App.scrollTo(error1, -200);\n                },\n\n                highlight: function (element) { // hightlight error inputs\n                    $(element)\n                        .closest('.form-group').addClass('has-error'); // set error class to the control group\n                },\n\n                unhighlight: function (element) { // revert the change done by hightlight\n                    $(element)\n                        .closest('.form-group').removeClass('has-error'); // set error class to the control group\n                },\n\n                success: function (label) {\n                    label\n                        .closest('.form-group').removeClass('has-error'); // set success class to the control group\n                },\n\n                submitHandler: function (form) {\n                    success1.show();\n                    error1.hide();\n                }\n            });\n\n    }\n\n    var handleValidation2 = function() {\n        // for more info visit the official plugin documentation: \n            // http://docs.jquery.com/Plugins/Validation\n\n            var form2 = $('#form_sample_2');\n            var error2 = $('.alert-danger', form2);\n            var success2 = $('.alert-success', form2);\n\n            form2.validate({\n                errorElement: 'span', //default input error message container\n                errorClass: 'help-block', // default input error message class\n                focusInvalid: false, // do not focus the last invalid input\n                ignore: \"\",\n                rules: {\n                    name: {\n                        minlength: 2,\n                        required: true\n                    },\n                    email: {\n                        required: true,\n                        email: true\n                    },\n                    email: {\n                        required: true,\n                        email: true\n                    },\n                    url: {\n                        required: true,\n                        url: true\n                    },\n                    number: {\n                        required: true,\n                        number: true\n                    },\n                    digits: {\n                        required: true,\n                        digits: true\n                    },\n                    creditcard: {\n                        required: true,\n                        creditcard: true\n                    },\n                },\n\n                invalidHandler: function (event, validator) { //display error alert on form submit              \n                    success2.hide();\n                    error2.show();\n                    App.scrollTo(error2, -200);\n                },\n\n                errorPlacement: function (error, element) { // render error placement for each input type\n                    var icon = $(element).parent('.input-icon').children('i');\n                    icon.removeClass('fa-check').addClass(\"fa-warning\");  \n                    icon.attr(\"data-original-title\", error.text()).tooltip({'container': 'body'});\n                },\n\n                highlight: function (element) { // hightlight error inputs\n                    $(element)\n                        .closest('.form-group').addClass('has-error'); // set error class to the control group   \n                },\n\n                unhighlight: function (element) { // revert the change done by hightlight\n                    \n                },\n\n                success: function (label, element) {\n                    var icon = $(element).parent('.input-icon').children('i');\n                    $(element).closest('.form-group').removeClass('has-error').addClass('has-success'); // set success class to the control group\n                    icon.removeClass(\"fa-warning\").addClass(\"fa-check\");\n                },\n\n                submitHandler: function (form) {\n                    success2.show();\n                    error2.hide();\n                }\n            });\n\n\n    }\n\n    var handleValidation3 = function() {\n        // for more info visit the official plugin documentation: \n        // http://docs.jquery.com/Plugins/Validation\n\n            var form3 = $('#form_sample_3');\n            var error3 = $('.alert-danger', form3);\n            var success3 = $('.alert-success', form3);\n\n            //IMPORTANT: update CKEDITOR textarea with actual content before submit\n            form3.on('submit', function() {\n                for(var instanceName in CKEDITOR.instances) {\n                    CKEDITOR.instances[instanceName].updateElement();\n                }\n            })\n\n            form3.validate({\n                errorElement: 'span', //default input error message container\n                errorClass: 'help-block', // default input error message class\n                focusInvalid: false, // do not focus the last invalid input\n                ignore: \"\",\n                rules: {\n                    name: {\n                        minlength: 2,\n                        required: true\n                    },\n                    email: {\n                        required: true,\n                        email: true\n                    },\n                    category: {\n                        required: true\n                    },\n                    options1: {\n                        required: true\n                    },\n                    options2: {\n                        required: true\n                    },\n                    occupation: {\n                        minlength: 5,\n                    },\n                    membership: {\n                        required: true\n                    },\n                    service: {\n                        required: true,\n                        minlength: 2\n                    },\n                    markdown: {\n                        required: true\n                    },\n                    editor1: {\n                        required: true\n                    },\n                    editor2: {\n                        required: true\n                    }\n                },\n\n                messages: { // custom messages for radio buttons and checkboxes\n                    membership: {\n                        required: \"Please select a Membership type\"\n                    },\n                    service: {\n                        required: \"Please select  at least 2 types of Service\",\n                        minlength: jQuery.format(\"Please select  at least {0} types of Service\")\n                    }\n                },\n\n                errorPlacement: function (error, element) { // render error placement for each input type\n                    if (element.parent(\".input-group\").size() > 0) {\n                        error.insertAfter(element.parent(\".input-group\"));\n                    } else if (element.attr(\"data-error-container\")) { \n                        error.appendTo(element.attr(\"data-error-container\"));\n                    } else if (element.parents('.radio-list').size() > 0) { \n                        error.appendTo(element.parents('.radio-list').attr(\"data-error-container\"));\n                    } else if (element.parents('.radio-inline').size() > 0) { \n                        error.appendTo(element.parents('.radio-inline').attr(\"data-error-container\"));\n                    } else if (element.parents('.checkbox-list').size() > 0) {\n                        error.appendTo(element.parents('.checkbox-list').attr(\"data-error-container\"));\n                    } else if (element.parents('.checkbox-inline').size() > 0) { \n                        error.appendTo(element.parents('.checkbox-inline').attr(\"data-error-container\"));\n                    } else {\n                        error.insertAfter(element); // for other inputs, just perform default behavior\n                    }\n                },\n\n                invalidHandler: function (event, validator) { //display error alert on form submit   \n                    success3.hide();\n                    error3.show();\n                    App.scrollTo(error3, -200);\n                },\n\n                highlight: function (element) { // hightlight error inputs\n                   $(element)\n                        .closest('.form-group').addClass('has-error'); // set error class to the control group\n                },\n\n                unhighlight: function (element) { // revert the change done by hightlight\n                    $(element)\n                        .closest('.form-group').removeClass('has-error'); // set error class to the control group\n                },\n\n                success: function (label) {\n                    label\n                        .closest('.form-group').removeClass('has-error'); // set success class to the control group\n                },\n\n                submitHandler: function (form) {\n                    success3.show();\n                    error3.hide();\n                }\n\n            });\n\n             //apply validation on select2 dropdown value change, this only needed for chosen dropdown integration.\n            $('.select2me', form3).change(function () {\n                form3.validate().element($(this)); //revalidate the chosen dropdown value and show error or success message for the input\n            });\n    }\n\n    var handleWysihtml5 = function() {\n        if (!jQuery().wysihtml5) {\n            \n            return;\n        }\n\n        if ($('.wysihtml5').size() > 0) {\n            $('.wysihtml5').wysihtml5({\n                \"stylesheets\": [\"assets/plugins/bootstrap-wysihtml5/wysiwyg-color.css\"]\n            });\n        }\n    }\n\n    return {\n        //main function to initiate the module\n        init: function () {\n\n            handleWysihtml5();\n            handleValidation1();\n            handleValidation2();\n            handleValidation3();\n\n        }\n\n    };\n\n}();"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/scripts/form-wizard.js",
    "content": "var FormWizard = function () {\n\n\n    return {\n        //main function to initiate the module\n        init: function () {\n            if (!jQuery().bootstrapWizard) {\n                return;\n            }\n\n            function format(state) {\n                if (!state.id) return state.text; // optgroup\n                return \"<img class='flag' src='assets/img/flags/\" + state.id.toLowerCase() + \".png'/>&nbsp;&nbsp;\" + state.text;\n            }\n\n            $(\"#country_list\").select2({\n                placeholder: \"Select\",\n                allowClear: true,\n                formatResult: format,\n                formatSelection: format,\n                escapeMarkup: function (m) {\n                    return m;\n                }\n            });\n\n            var form = $('#submit_form');\n            var error = $('.alert-danger', form);\n            var success = $('.alert-success', form);\n\n            form.validate({\n                doNotHideMessage: true, //this option enables to show the error/success messages on tab switch.\n                errorElement: 'span', //default input error message container\n                errorClass: 'help-block', // default input error message class\n                focusInvalid: false, // do not focus the last invalid input\n                rules: {\n                    //account\n                    username: {\n                        minlength: 5,\n                        required: true\n                    },\n                    password: {\n                        minlength: 5,\n                        required: true\n                    },\n                    rpassword: {\n                        minlength: 5,\n                        required: true,\n                        equalTo: \"#submit_form_password\"\n                    },\n                    //profile\n                    fullname: {\n                        required: true\n                    },\n                    email: {\n                        required: true,\n                        email: true\n                    },\n                    phone: {\n                        required: true\n                    },\n                    gender: {\n                        required: true\n                    },\n                    address: {\n                        required: true\n                    },\n                    city: {\n                        required: true\n                    },\n                    country: {\n                        required: true\n                    },\n                    //payment\n                    card_name: {\n                        required: true\n                    },\n                    card_number: {\n                        minlength: 16,\n                        maxlength: 16,\n                        required: true\n                    },\n                    card_cvc: {\n                        digits: true,\n                        required: true,\n                        minlength: 3,\n                        maxlength: 4\n                    },\n                    card_expiry_date: {\n                        required: true\n                    },\n                    'payment[]': {\n                        required: true,\n                        minlength: 1\n                    }\n                },\n\n                messages: { // custom messages for radio buttons and checkboxes\n                    'payment[]': {\n                        required: \"Please select at least one option\",\n                        minlength: jQuery.format(\"Please select at least one option\")\n                    }\n                },\n\n                errorPlacement: function (error, element) { // render error placement for each input type\n                    if (element.attr(\"name\") == \"gender\") { // for uniform radio buttons, insert the after the given container\n                        error.insertAfter(\"#form_gender_error\");\n                    } else if (element.attr(\"name\") == \"payment[]\") { // for uniform radio buttons, insert the after the given container\n                        error.insertAfter(\"#form_payment_error\");\n                    } else {\n                        error.insertAfter(element); // for other inputs, just perform default behavior\n                    }\n                },\n\n                invalidHandler: function (event, validator) { //display error alert on form submit   \n                    success.hide();\n                    error.show();\n                    App.scrollTo(error, -200);\n                },\n\n                highlight: function (element) { // hightlight error inputs\n                    $(element)\n                        .closest('.form-group').removeClass('has-success').addClass('has-error'); // set error class to the control group\n                },\n\n                unhighlight: function (element) { // revert the change done by hightlight\n                    $(element)\n                        .closest('.form-group').removeClass('has-error'); // set error class to the control group\n                },\n\n                success: function (label) {\n                    if (label.attr(\"for\") == \"gender\" || label.attr(\"for\") == \"payment[]\") { // for checkboxes and radio buttons, no need to show OK icon\n                        label\n                            .closest('.form-group').removeClass('has-error').addClass('has-success');\n                        label.remove(); // remove error label here\n                    } else { // display success icon for other inputs\n                        label\n                            .addClass('valid') // mark the current input as valid and display OK icon\n                        .closest('.form-group').removeClass('has-error').addClass('has-success'); // set success class to the control group\n                    }\n                },\n\n                submitHandler: function (form) {\n                    success.show();\n                    error.hide();\n                    //add here some ajax code to submit your form or just call form.submit() if you want to submit the form without ajax\n                }\n\n            });\n\n            var displayConfirm = function() {\n                $('#tab4 .form-control-static', form).each(function(){\n                    var input = $('[name=\"'+$(this).attr(\"data-display\")+'\"]', form);\n                    if (input.is(\":text\") || input.is(\"textarea\")) {\n                        $(this).html(input.val());\n                    } else if (input.is(\"select\")) {\n                        $(this).html(input.find('option:selected').text());\n                    } else if (input.is(\":radio\") && input.is(\":checked\")) {\n                        $(this).html(input.attr(\"data-title\"));\n                    } else if ($(this).attr(\"data-display\") == 'payment') {\n                        var payment = [];\n                        $('[name=\"payment[]\"]').each(function(){\n                            payment.push($(this).attr('data-title'));\n                        });\n                        $(this).html(payment.join(\"<br>\"));\n                    }\n                });\n            }\n\n            var handleTitle = function(tab, navigation, index) {\n                var total = navigation.find('li').length;\n                var current = index + 1;\n                // set wizard title\n                $('.step-title', $('#form_wizard_1')).text('Step ' + (index + 1) + ' of ' + total);\n                // set done steps\n                jQuery('li', $('#form_wizard_1')).removeClass(\"done\");\n                var li_list = navigation.find('li');\n                for (var i = 0; i < index; i++) {\n                    jQuery(li_list[i]).addClass(\"done\");\n                }\n\n                if (current == 1) {\n                    $('#form_wizard_1').find('.button-previous').hide();\n                } else {\n                    $('#form_wizard_1').find('.button-previous').show();\n                }\n\n                if (current >= total) {\n                    $('#form_wizard_1').find('.button-next').hide();\n                    $('#form_wizard_1').find('.button-submit').show();\n                    displayConfirm();\n                } else {\n                    $('#form_wizard_1').find('.button-next').show();\n                    $('#form_wizard_1').find('.button-submit').hide();\n                }\n                App.scrollTo($('.page-title'));\n            }\n\n            // default form wizard\n            $('#form_wizard_1').bootstrapWizard({\n                'nextSelector': '.button-next',\n                'previousSelector': '.button-previous',\n                onTabClick: function (tab, navigation, index, clickedIndex) {\n                    success.hide();\n                    error.hide();\n                    if (form.valid() == false) {\n                        return false;\n                    }\n                    handleTitle(tab, navigation, clickedIndex);\n                },\n                onNext: function (tab, navigation, index) {\n                    success.hide();\n                    error.hide();\n\n                    if (form.valid() == false) {\n                        return false;\n                    }\n\n                    handleTitle(tab, navigation, index);\n                },\n                onPrevious: function (tab, navigation, index) {\n                    success.hide();\n                    error.hide();\n\n                    handleTitle(tab, navigation, index);\n                },\n                onTabShow: function (tab, navigation, index) {\n                    var total = navigation.find('li').length;\n                    var current = index + 1;\n                    var $percent = (current / total) * 100;\n                    $('#form_wizard_1').find('.progress-bar').css({\n                        width: $percent + '%'\n                    });\n                }\n            });\n\n            $('#form_wizard_1').find('.button-previous').hide();\n            $('#form_wizard_1 .button-submit').click(function () {\n                alert('Finished! Hope you like it :)');\n            }).hide();\n        }\n\n    };\n\n}();"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/scripts/idle-timeout.js",
    "content": "var IdleTimeout = function () {\n\n    return {\n\n        //main function to initiate the module\n        init: function () {\n\n            // cache a reference to the countdown element so we don't have to query the DOM for it on each ping.\n            var $countdown;\n\n            $('body').append('<div class=\"modal fade\" id=\"idle-timeout-dialog\" data-backdrop=\"static\"><div class=\"modal-dialog modal-small\"><div class=\"modal-content\"><div class=\"modal-header\"><h4 class=\"modal-title\">Your session is about to expire.</h4></div><div class=\"modal-body\"><p><i class=\"fa fa-warning\"></i> You session will be locked in <span id=\"idle-timeout-counter\"></span> seconds.</p><p>Do you want to continue your session?</p></div><div class=\"modal-footer\"><button id=\"idle-timeout-dialog-logout\" type=\"button\" class=\"btn btn-default\">No, Logout</button><button id=\"idle-timeout-dialog-keepalive\" type=\"button\" class=\"btn btn-primary\" data-dismiss=\"modal\">Yes, Keep Working</button></div></div></div></div>');\n                    \n            // start the idle timer plugin\n            $.idleTimeout('#idle-timeout-dialog', '.modal-content button:last', {\n                idleAfter: 5, // 5 seconds\n                timeout: 30000, //30 seconds to timeout\n                pollingInterval: 5, // 5 seconds\n                keepAliveURL: 'demo/idletimeout_keepalive.php',\n                serverResponseEquals: 'OK',\n                onTimeout: function(){\n                    window.location = \"extra_lock.html\";\n                },\n                onIdle: function(){\n                    $('#idle-timeout-dialog').modal('show');\n                    $countdown = $('#idle-timeout-counter');\n\n                    $('#idle-timeout-dialog-keepalive').on('click', function () { \n                        $('#idle-timeout-dialog').modal('hide');\n                    });\n\n                    $('#idle-timeout-dialog-logout').on('click', function () { \n                        $('#idle-timeout-dialog').modal('hide');\n                        $.idleTimeout.options.onTimeout.call(this);\n                    });\n                },\n                onCountdown: function(counter){\n                    $countdown.html(counter); // update the counter\n                }\n            });\n            \n        }\n\n    };\n\n}();"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/scripts/inbox.js",
    "content": "var Inbox = function () {\n\n    var content = $('.inbox-content');\n    var loading = $('.inbox-loading');\n\n    var loadInbox = function (el, name) {\n        var url = 'inbox_inbox.html';\n        var title = $('.inbox-nav > li.' + name + ' a').attr('data-title');\n\n        loading.show();\n        content.html('');\n        toggleButton(el);\n\n        $.ajax({\n            type: \"GET\",\n            cache: false,\n            url: url,\n            dataType: \"html\",\n            success: function(res) \n            {\n                toggleButton(el);\n\n                $('.inbox-nav > li.active').removeClass('active');\n                $('.inbox-nav > li.' + name).addClass('active');\n                $('.inbox-header > h1').text(title);\n\n                loading.hide();\n                content.html(res);\n                App.fixContentHeight();\n                App.initUniform();\n            },\n            error: function(xhr, ajaxOptions, thrownError)\n            {\n                toggleButton(el);\n            },\n            async: false\n        });\n    }\n\n    var loadMessage = function (el, name, resetMenu) {\n        var url = 'inbox_view.html';\n\n        loading.show();\n        content.html('');\n        toggleButton(el);\n        \n        $.ajax({\n            type: \"GET\",\n            cache: false,\n            url: url,\n            dataType: \"html\",\n            success: function(res) \n            {\n                toggleButton(el);\n\n                if (resetMenu) {\n                    $('.inbox-nav > li.active').removeClass('active');\n                }\n                $('.inbox-header > h1').text('View Message');\n\n                loading.hide();\n                content.html(res);\n                App.fixContentHeight();\n                App.initUniform();\n            },\n            error: function(xhr, ajaxOptions, thrownError)\n            {\n                toggleButton(el);\n            },\n            async: false\n        });\n    }\n\n    var initWysihtml5 = function () {\n        $('.inbox-wysihtml5').wysihtml5({\n            \"stylesheets\": [\"assets/plugins/bootstrap-wysihtml5/wysiwyg-color.css\"]\n        });\n    }\n\n    var initFileupload = function () {\n\n        $('#fileupload').fileupload({\n            // Uncomment the following to send cross-domain cookies:\n            //xhrFields: {withCredentials: true},\n            url: 'assets/plugins/jquery-file-upload/server/php/',\n            autoUpload: true\n        });\n\n        // Upload server status check for browsers with CORS support:\n        if ($.support.cors) {\n            $.ajax({\n                url: 'assets/plugins/jquery-file-upload/server/php/',\n                type: 'HEAD'\n            }).fail(function () {\n                $('<span class=\"alert alert-error\"/>')\n                    .text('Upload server currently unavailable - ' +\n                    new Date())\n                    .appendTo('#fileupload');\n            });\n        }\n    }\n\n    var loadCompose = function (el) {\n        var url = 'inbox_compose.html';\n\n        loading.show();\n        content.html('');\n        toggleButton(el);\n\n        // load the form via ajax\n        $.ajax({\n            type: \"GET\",\n            cache: false,\n            url: url,\n            dataType: \"html\",\n            success: function(res) \n            {\n                toggleButton(el);\n\n                $('.inbox-nav > li.active').removeClass('active');\n                $('.inbox-header > h1').text('Compose');\n\n                loading.hide();\n                content.html(res);\n\n                initFileupload();\n                initWysihtml5();\n\n                $('.inbox-wysihtml5').focus();\n                App.fixContentHeight();\n                App.initUniform();\n            },\n            error: function(xhr, ajaxOptions, thrownError)\n            {\n                toggleButton(el);\n            },\n            async: false\n        });\n    }\n\n    var loadReply = function (el) {\n        var url = 'inbox_reply.html';\n\n        loading.show();\n        content.html('');\n        toggleButton(el);\n\n        // load the form via ajax\n        $.ajax({\n            type: \"GET\",\n            cache: false,\n            url: url,\n            dataType: \"html\",\n            success: function(res) \n            {\n                toggleButton(el);\n\n                $('.inbox-nav > li.active').removeClass('active');\n                $('.inbox-header > h1').text('Reply');\n\n                loading.hide();\n                content.html(res);\n                $('[name=\"message\"]').val($('#reply_email_content_body').html());\n\n                handleCCInput(); // init \"CC\" input field\n\n                initFileupload();\n                initWysihtml5();\n                App.fixContentHeight();\n                App.initUniform();\n            },\n            error: function(xhr, ajaxOptions, thrownError)\n            {\n                toggleButton(el);\n            },\n            async: false\n        });\n    }\n\n    var loadSearchResults = function (el) {\n        var url = 'inbox_search_result.html';\n\n        loading.show();\n        content.html('');\n        toggleButton(el);\n\n        $.ajax({\n            type: \"GET\",\n            cache: false,\n            url: url,\n            dataType: \"html\",\n            success: function(res) \n            {\n                toggleButton(el);\n\n                $('.inbox-nav > li.active').removeClass('active');\n                $('.inbox-header > h1').text('Search');\n\n                loading.hide();\n                content.html(res);\n                App.fixContentHeight();\n                App.initUniform();\n            },\n            error: function(xhr, ajaxOptions, thrownError)\n            {\n                toggleButton(el);\n            },\n            async: false\n        });\n    }\n\n    var handleCCInput = function () {\n        var the = $('.inbox-compose .mail-to .inbox-cc');\n        var input = $('.inbox-compose .input-cc');\n        the.hide();\n        input.show();\n        $('.close', input).click(function () {\n            input.hide();\n            the.show();\n        });\n    }\n\n    var handleBCCInput = function () {\n\n        var the = $('.inbox-compose .mail-to .inbox-bcc');\n        var input = $('.inbox-compose .input-bcc');\n        the.hide();\n        input.show();\n        $('.close', input).click(function () {\n            input.hide();\n            the.show();\n        });\n    }\n\n    var toggleButton = function(el) {\n        if (typeof el == 'undefined') {\n            return;\n        }\n        if (el.attr(\"disabled\")) {\n            el.attr(\"disabled\", false);\n        } else {\n            el.attr(\"disabled\", true);\n        }\n    }\n\n    return {\n        //main function to initiate the module\n        init: function () {\n\n            // handle compose btn click\n            $('.inbox .compose-btn a').live('click', function () {\n                loadCompose($(this));\n            });\n\n            // handle reply and forward button click\n            $('.inbox .reply-btn').live('click', function () {\n                loadReply($(this));\n            });\n\n            // handle view message\n            $('.inbox-content .view-message').live('click', function () {\n                loadMessage($(this));\n            });\n\n            // handle inbox listing\n            $('.inbox-nav > li.inbox > a').click(function () {\n                loadInbox($(this), 'inbox');\n            });\n\n            // handle sent listing\n            $('.inbox-nav > li.sent > a').click(function () {\n                loadInbox($(this), 'sent');\n            });\n\n            // handle draft listing\n            $('.inbox-nav > li.draft > a').click(function () {\n                loadInbox($(this), 'draft');\n            });\n\n            // handle trash listing\n            $('.inbox-nav > li.trash > a').click(function () {\n                loadInbox($(this), 'trash');\n            });\n\n            //handle compose/reply cc input toggle\n            $('.inbox-compose .mail-to .inbox-cc').live('click', function () {\n                handleCCInput();\n            });\n\n            //handle compose/reply bcc input toggle\n            $('.inbox-compose .mail-to .inbox-bcc').live('click', function () {\n                handleBCCInput();\n            });\n\n            //handle loading content based on URL parameter\n            if (App.getURLParameter(\"a\") === \"view\") {\n                loadMessage();\n            } else if (App.getURLParameter(\"a\") === \"compose\") {\n                loadCompose();\n            } else {\n               $('.inbox-nav > li.inbox > a').click();\n            }\n\n        }\n\n    };\n\n}();"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/scripts/index.js",
    "content": "var Index = function () {\n\n\n    return {\n\n        //main function\n        init: function () {\n            App.addResponsiveHandler(function () {\n                jQuery('.vmaps').each(function () {\n                    var map = jQuery(this);\n                    map.width(map.parent().width());\n                });\n            });\n        },\n\n        initJQVMAP: function () {\n\n            var showMap = function (name) {\n                jQuery('.vmaps').hide();\n                jQuery('#vmap_' + name).show();\n            }\n\n            var setMap = function (name) {\n                var data = {\n                    map: 'world_en',\n                    backgroundColor: null,\n                    borderColor: '#333333',\n                    borderOpacity: 0.5,\n                    borderWidth: 1,\n                    color: '#c6c6c6',\n                    enableZoom: true,\n                    hoverColor: '#c9dfaf',\n                    hoverOpacity: null,\n                    values: sample_data,\n                    normalizeFunction: 'linear',\n                    scaleColors: ['#b6da93', '#909cae'],\n                    selectedColor: '#c9dfaf',\n                    selectedRegion: null,\n                    showTooltip: true,\n                    onLabelShow: function (event, label, code) {\n\n                    },\n                    onRegionOver: function (event, code) {\n                        if (code == 'ca') {\n                            event.preventDefault();\n                        }\n                    },\n                    onRegionClick: function (element, code, region) {\n                        var message = 'You clicked \"' + region + '\" which has the code: ' + code.toUpperCase();\n                        alert(message);\n                    }\n                };\n\n                data.map = name + '_en';\n                var map = jQuery('#vmap_' + name);\n                if (!map) {\n                    return;\n                }\n                map.width(map.parent().parent().width());\n                map.show();\n                map.vectorMap(data);\n                map.hide();\n            }\n\n            setMap(\"world\");\n            setMap(\"usa\");\n            setMap(\"europe\");\n            setMap(\"russia\");\n            setMap(\"germany\");\n            showMap(\"world\");\n\n            jQuery('#regional_stat_world').click(function () {\n                showMap(\"world\");\n            });\n\n            jQuery('#regional_stat_usa').click(function () {\n                showMap(\"usa\");\n            });\n\n            jQuery('#regional_stat_europe').click(function () {\n                showMap(\"europe\");\n            });\n            jQuery('#regional_stat_russia').click(function () {\n                showMap(\"russia\");\n            });\n            jQuery('#regional_stat_germany').click(function () {\n                showMap(\"germany\");\n            });\n\n            $('#region_statistics_loading').hide();\n            $('#region_statistics_content').show();\n        },\n\n        initCalendar: function () {\n            if (!jQuery().fullCalendar) {\n                return;\n            }\n\n            var date = new Date();\n            var d = date.getDate();\n            var m = date.getMonth();\n            var y = date.getFullYear();\n\n            var h = {};\n\n            if ($('#calendar').width() <= 400) {\n                $('#calendar').addClass(\"mobile\");\n                h = {\n                    left: 'title, prev, next',\n                    center: '',\n                    right: 'today,month,agendaWeek,agendaDay'\n                };\n            } else {\n                $('#calendar').removeClass(\"mobile\");\n                if (App.isRTL()) {\n                    h = {\n                        right: 'title',\n                        center: '',\n                        left: 'prev,next,today,month,agendaWeek,agendaDay'\n                    };\n                } else {\n                    h = {\n                        left: 'title',\n                        center: '',\n                        right: 'prev,next,today,month,agendaWeek,agendaDay'\n                    };\n                }               \n            }\n\n            $('#calendar').fullCalendar('destroy'); // destroy the calendar\n            $('#calendar').fullCalendar({ //re-initialize the calendar\n                disableDragging: false,\n                header: h,\n                editable: true,\n                events: [{\n                        title: 'All Day Event',                        \n                        start: new Date(y, m, 1),\n                        backgroundColor: App.getLayoutColorCode('yellow')\n                    }, {\n                        title: 'Long Event',\n                        start: new Date(y, m, d - 5),\n                        end: new Date(y, m, d - 2),\n                        backgroundColor: App.getLayoutColorCode('green')\n                    }, {\n                        title: 'Repeating Event',\n                        start: new Date(y, m, d - 3, 16, 0),\n                        allDay: false,\n                        backgroundColor: App.getLayoutColorCode('red')\n                    }, {\n                        title: 'Repeating Event',\n                        start: new Date(y, m, d + 4, 16, 0),\n                        allDay: false,\n                        backgroundColor: App.getLayoutColorCode('green')\n                    }, {\n                        title: 'Meeting',\n                        start: new Date(y, m, d, 10, 30),\n                        allDay: false,\n                    }, {\n                        title: 'Lunch',\n                        start: new Date(y, m, d, 12, 0),\n                        end: new Date(y, m, d, 14, 0),\n                        backgroundColor: App.getLayoutColorCode('grey'),\n                        allDay: false,\n                    }, {\n                        title: 'Birthday Party',\n                        start: new Date(y, m, d + 1, 19, 0),\n                        end: new Date(y, m, d + 1, 22, 30),\n                        backgroundColor: App.getLayoutColorCode('purple'),\n                        allDay: false,\n                    }, {\n                        title: 'Click for Google',\n                        start: new Date(y, m, 28),\n                        end: new Date(y, m, 29),\n                        backgroundColor: App.getLayoutColorCode('yellow'),\n                        url: 'http://google.com/',\n                    }\n                ]\n            });\n        },\n\n        initCharts: function () {\n            if (!jQuery.plot) {\n                return;\n            }\n\n            var data = [];\n            var totalPoints = 250;\n\n            // random data generator for plot charts\n\n            function getRandomData() {\n                if (data.length > 0) data = data.slice(1);\n                // do a random walk\n                while (data.length < totalPoints) {\n                    var prev = data.length > 0 ? data[data.length - 1] : 50;\n                    var y = prev + Math.random() * 10 - 5;\n                    if (y < 0) y = 0;\n                    if (y > 100) y = 100;\n                    data.push(y);\n                }\n                // zip the generated y values with the x values\n                var res = [];\n                for (var i = 0; i < data.length; ++i) res.push([i, data[i]])\n                return res;\n            }\n\n            function showTooltip(title, x, y, contents) {\n                $('<div id=\"tooltip\" class=\"chart-tooltip\"><div class=\"date\">' + title + '<\\/div><div class=\"label label-success\">CTR: ' + x / 10 + '%<\\/div><div class=\"label label-danger\">Imp: ' + x * 12 + '<\\/div><\\/div>').css({\n                    position: 'absolute',\n                    display: 'none',\n                    top: y - 100,\n                    width: 80,\n                    left: x - 40,\n                    border: '0px solid #ccc',\n                    padding: '2px 6px',\n                    'background-color': '#fff',\n                }).appendTo(\"body\").fadeIn(200);\n            }\n\n            function randValue() {\n                return (Math.floor(Math.random() * (1 + 50 - 20))) + 10;\n            }\n\n            var pageviews = [\n                [1, randValue()],\n                [2, randValue()],\n                [3, 2 + randValue()],\n                [4, 3 + randValue()],\n                [5, 5 + randValue()],\n                [6, 10 + randValue()],\n                [7, 15 + randValue()],\n                [8, 20 + randValue()],\n                [9, 25 + randValue()],\n                [10, 30 + randValue()],\n                [11, 35 + randValue()],\n                [12, 25 + randValue()],\n                [13, 15 + randValue()],\n                [14, 20 + randValue()],\n                [15, 45 + randValue()],\n                [16, 50 + randValue()],\n                [17, 65 + randValue()],\n                [18, 70 + randValue()],\n                [19, 85 + randValue()],\n                [20, 80 + randValue()],\n                [21, 75 + randValue()],\n                [22, 80 + randValue()],\n                [23, 75 + randValue()],\n                [24, 70 + randValue()],\n                [25, 65 + randValue()],\n                [26, 75 + randValue()],\n                [27, 80 + randValue()],\n                [28, 85 + randValue()],\n                [29, 90 + randValue()],\n                [30, 95 + randValue()]\n            ];\n\n            var visitors = [\n                [1, randValue() - 5],\n                [2, randValue() - 5],\n                [3, randValue() - 5],\n                [4, 6 + randValue()],\n                [5, 5 + randValue()],\n                [6, 20 + randValue()],\n                [7, 25 + randValue()],\n                [8, 36 + randValue()],\n                [9, 26 + randValue()],\n                [10, 38 + randValue()],\n                [11, 39 + randValue()],\n                [12, 50 + randValue()],\n                [13, 51 + randValue()],\n                [14, 12 + randValue()],\n                [15, 13 + randValue()],\n                [16, 14 + randValue()],\n                [17, 15 + randValue()],\n                [18, 15 + randValue()],\n                [19, 16 + randValue()],\n                [20, 17 + randValue()],\n                [21, 18 + randValue()],\n                [22, 19 + randValue()],\n                [23, 20 + randValue()],\n                [24, 21 + randValue()],\n                [25, 14 + randValue()],\n                [26, 24 + randValue()],\n                [27, 25 + randValue()],\n                [28, 26 + randValue()],\n                [29, 27 + randValue()],\n                [30, 31 + randValue()]\n            ];\n\n            if ($('#site_statistics').size() != 0) {\n\n                $('#site_statistics_loading').hide();\n                $('#site_statistics_content').show();\n\n                var plot_statistics = $.plot($(\"#site_statistics\"), [{\n                        data: pageviews,\n                        label: \"Unique Visits\"\n                    }, {\n                        data: visitors,\n                        label: \"Page Views\"\n                    }\n                ], {\n                    series: {\n                        lines: {\n                            show: true,\n                            lineWidth: 2,\n                            fill: true,\n                            fillColor: {\n                                colors: [{\n                                        opacity: 0.05\n                                    }, {\n                                        opacity: 0.01\n                                    }\n                                ]\n                            }\n                        },\n                        points: {\n                            show: true\n                        },\n                        shadowSize: 2\n                    },\n                    grid: {\n                        hoverable: true,\n                        clickable: true,\n                        tickColor: \"#eee\",\n                        borderWidth: 0\n                    },\n                    colors: [\"#d12610\", \"#37b7f3\", \"#52e136\"],\n                    xaxis: {\n                        ticks: 11,\n                        tickDecimals: 0\n                    },\n                    yaxis: {\n                        ticks: 11,\n                        tickDecimals: 0\n                    }\n                });\n\n                var previousPoint = null;\n                $(\"#site_statistics\").bind(\"plothover\", function (event, pos, item) {\n                    $(\"#x\").text(pos.x.toFixed(2));\n                    $(\"#y\").text(pos.y.toFixed(2));\n                    if (item) {\n                        if (previousPoint != item.dataIndex) {\n                            previousPoint = item.dataIndex;\n\n                            $(\"#tooltip\").remove();\n                            var x = item.datapoint[0].toFixed(2),\n                                y = item.datapoint[1].toFixed(2);\n\n                            showTooltip('24 Jan 2013', item.pageX, item.pageY, item.series.label + \" of \" + x + \" = \" + y);\n                        }\n                    } else {\n                        $(\"#tooltip\").remove();\n                        previousPoint = null;\n                    }\n                });\n            }               \n\n            if ($('#load_statistics').size() != 0) {\n                 //server load\n                $('#load_statistics_loading').hide();\n                $('#load_statistics_content').show();\n        \n                var updateInterval = 30;\n                var plot_statistics = $.plot($(\"#load_statistics\"), [getRandomData()], {\n                series: {\n                    shadowSize: 1\n                },\n                lines: {\n                    show: true,\n                    lineWidth: 0.2,\n                    fill: true,\n                    fillColor: {\n                        colors: [{\n                                opacity: 0.1\n                            }, {\n                                opacity: 1\n                            }\n                        ]\n                    }\n                },\n                yaxis: {\n                    min: 0,\n                    max: 100,\n                    tickFormatter: function (v) {\n                        return v + \"%\";\n                    }\n                },\n                xaxis: {\n                    show: false\n                },\n                colors: [\"#e14e3d\"],\n                grid: {\n                    tickColor: \"#a8a3a3\",\n                    borderWidth: 0\n                }\n                });\n                \n                function statisticsUpdate() {\n                plot_statistics.setData([getRandomData()]);\n                plot_statistics.draw();\n                setTimeout(statisticsUpdate, updateInterval);\n                \n                }\n                \n                statisticsUpdate();\n\n                $('#load_statistics').bind(\"mouseleave\", function () {\n                    $(\"#tooltip\").remove();\n                });\n            }\n\n            if ($('#site_activities').size() != 0) {\n                //site activities\n                var previousPoint2 = null;\n                $('#site_activities_loading').hide();\n                $('#site_activities_content').show();\n\n                var activities = [\n                    [1, 10],\n                    [2, 9],\n                    [3, 8],\n                    [4, 6],\n                    [5, 5],\n                    [6, 3],\n                    [7, 9],\n                    [8, 10],\n                    [9, 12],\n                    [10, 14],\n                    [11, 15],\n                    [12, 13],\n                    [13, 11],\n                    [14, 10],\n                    [15, 9],\n                    [16, 8],\n                    [17, 12],\n                    [18, 14],\n                    [19, 16],\n                    [20, 19],\n                    [21, 20],\n                    [22, 20],\n                    [23, 19],\n                    [24, 17],\n                    [25, 15],\n                    [25, 14],\n                    [26, 12],\n                    [27, 10],\n                    [28, 8],\n                    [29, 10],\n                    [30, 12],\n                    [31, 10],\n                    [32, 9],\n                    [33, 8],\n                    [34, 6],\n                    [35, 5],\n                    [36, 3],\n                    [37, 9],\n                    [38, 10],\n                    [39, 12],\n                    [40, 14],\n                    [41, 15],\n                    [42, 13],\n                    [43, 11],\n                    [44, 10],\n                    [45, 9],\n                    [46, 8],\n                    [47, 12],\n                    [48, 14],\n                    [49, 16],\n                    [50, 12],\n                    [51, 10]\n                ];\n\n                var plot_activities = $.plot(\n                    $(\"#site_activities\"), [{\n                        data: activities,\n                        color: \"rgba(107,207,123, 0.9)\",\n                        shadowSize: 0,\n                        bars: {\n                            show: true,\n                            lineWidth: 0,\n                            fill: true,\n                            fillColor: {\n                                colors: [{\n                                        opacity: 1\n                                    }, {\n                                        opacity: 1\n                                    }\n                                ]\n                            }\n                        }\n                    }\n                ], {\n                    series: {\n                        bars: {\n                            show: true,\n                            barWidth: 0.9\n                        }\n                    },\n                    grid: {\n                        show: false,\n                        hoverable: true,\n                        clickable: false,\n                        autoHighlight: true,\n                        borderWidth: 0\n                    },\n                    yaxis: {\n                        min: 0,\n                        max: 20\n                    }\n                });\n\n                $(\"#site_activities\").bind(\"plothover\", function (event, pos, item) {\n                    $(\"#x\").text(pos.x.toFixed(2));\n                    $(\"#y\").text(pos.y.toFixed(2));\n                    if (item) {\n                        if (previousPoint2 != item.dataIndex) {\n                            previousPoint2 = item.dataIndex;\n                            $(\"#tooltip\").remove();\n                            var x = item.datapoint[0].toFixed(2),\n                                y = item.datapoint[1].toFixed(2);\n                            showTooltip('24 Feb 2013', item.pageX, item.pageY, x);\n                        }\n                    }\n                });\n\n                $('#site_activities').bind(\"mouseleave\", function () {\n                    $(\"#tooltip\").remove();\n                });\n            }\n        },\n\n        initMiniCharts: function () {\n             \n            $('.easy-pie-chart .number.transactions').easyPieChart({\n                animate: 1000,\n                size: 75,\n                lineWidth: 3,\n                barColor: App.getLayoutColorCode('yellow')\n            });\n\n            $('.easy-pie-chart .number.visits').easyPieChart({\n                animate: 1000,\n                size: 75,\n                lineWidth: 3,\n                barColor: App.getLayoutColorCode('green')\n            });\n             \n            $('.easy-pie-chart .number.bounce').easyPieChart({\n                animate: 1000,\n                size: 75,\n                lineWidth: 3,\n                barColor: App.getLayoutColorCode('red')\n            });\n\n            $('.easy-pie-chart-reload').click(function(){\n                $('.easy-pie-chart .number').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            $(\"#sparkline_bar\").sparkline([8,9,10,11,10,10,12,10,10,11,9,12,11,10,9,11,13,13,12], {\n                type: 'bar',\n                width: '100',\n                barWidth: 5,\n                height: '55',\n                barColor: '#35aa47',\n                negBarColor: '#e02222'}\n            );\n\n            $(\"#sparkline_bar2\").sparkline([9,11,12,13,12,13,10,14,13,11,11,12,11,11,10,12,11,10], {\n                type: 'bar',\n                width: '100',\n                barWidth: 5,\n                height: '55',\n                barColor: '#ffb848',\n                negBarColor: '#e02222'}\n            );\n\n            $(\"#sparkline_line\").sparkline([9,10,9,10,10,11,12,10,10,11,11,12,11,10,12,11,10,12], {\n                type: 'line',\n                width: '100',\n                height: '55',\n                lineColor: '#ffb848'\n            });\n\n        },\n\n        initChat: function () {\n\n            var cont = $('#chats');\n            var list = $('.chats', cont);\n            var form = $('.chat-form', cont);\n            var input = $('input', form);\n            var btn = $('.btn', form);\n\n            var handleClick = function (e) {\n                e.preventDefault();\n                \n                var text = input.val();\n                if (text.length == 0) {\n                    return;\n                }\n\n                var time = new Date();\n                var time_str = time.toString('MMM dd, yyyy hh:mm');\n                var tpl = '';\n                tpl += '<li class=\"out\">';\n                tpl += '<img class=\"avatar\" alt=\"\" src=\"assets/img/avatar1.jpg\"/>';\n                tpl += '<div class=\"message\">';\n                tpl += '<span class=\"arrow\"></span>';\n                tpl += '<a href=\"#\" class=\"name\">Bob Nilson</a>&nbsp;';\n                tpl += '<span class=\"datetime\">at ' + time_str + '</span>';\n                tpl += '<span class=\"body\">';\n                tpl += text;\n                tpl += '</span>';\n                tpl += '</div>';\n                tpl += '</li>';\n\n                var msg = list.append(tpl);\n                input.val(\"\");\n                $('.scroller', cont).slimScroll({\n                    scrollTo: list.height()\n                });\n            }\n\n            /*\n            $('.scroller', cont).slimScroll({\n                scrollTo: list.height()\n            });\n            */\n\n            $('body').on('click', '.message .name', function(e){\n                e.preventDefault(); // prevent click event\n\n                var name = $(this).text(); // get clicked user's full name\n                input.val('@' +  name + ':'); // set it into the input field\n                App.scrollTo(input); // scroll to input if needed\n            });\n\n            btn.click(handleClick);\n            input.keypress(function (e) {\n                if (e.which == 13) {\n                    handleClick();\n                    return false; //<---- Add this line\n                }\n            });\n        },\n\n        initDashboardDaterange: function () {\n\n            $('#dashboard-report-range').daterangepicker({\n                opens: (App.isRTL() ? 'right' : 'left'),\n                startDate: moment().subtract('days', 29),\n                endDate: moment(),\n                minDate: '01/01/2012',\n                maxDate: '12/31/2014',\n                dateLimit: {\n                    days: 60\n                },\n                showDropdowns: false,\n                showWeekNumbers: true,\n                timePicker: false,\n                timePickerIncrement: 1,\n                timePicker12Hour: true,\n                ranges: {\n                    'Today': [moment(), moment()],\n                    'Yesterday': [moment().subtract('days', 1), moment().subtract('days', 1)],\n                    'Last 7 Days': [moment().subtract('days', 6), moment()],\n                    'Last 30 Days': [moment().subtract('days', 29), moment()],\n                    'This Month': [moment().startOf('month'), moment().endOf('month')],\n                    'Last Month': [moment().subtract('month', 1).startOf('month'), moment().subtract('month', 1).endOf('month')]\n                },\n                buttonClasses: ['btn'],\n                applyClass: 'blue',\n                cancelClass: 'default',\n                format: 'MM/DD/YYYY',\n                separator: ' to ',\n                locale: {\n                    applyLabel: 'Apply',\n                    fromLabel: 'From',\n                    toLabel: 'To',\n                    customRangeLabel: 'Custom Range',\n                    daysOfWeek: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'],\n                    monthNames: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],\n                    firstDay: 1\n                }\n            },\n            function (start, end) {\n                console.log(\"Callback has been called!\");\n                $('#dashboard-report-range span').html(start.format('MMMM D, YYYY') + ' - ' + end.format('MMMM D, YYYY'));\n            }\n            );\n\n\n            $('#dashboard-report-range span').html(moment().subtract('days', 29).format('MMMM D, YYYY') + ' - ' + moment().format('MMMM D, YYYY'));\n            $('#dashboard-report-range').show();\n        },\n\n        initIntro: function () {\n            if ($.cookie('intro_show')) {\n                return;\n            }\n\n            $.cookie('intro_show', 1);\n\n            setTimeout(function () {\n                var unique_id = $.gritter.add({\n                    // (string | mandatory) the heading of the notification\n                    title: 'Meet Metronic!',\n                    // (string | mandatory) the text inside the notification\n                    text: 'Metronic is a brand new Responsive Admin Dashboard Template you have always been looking for!',\n                    // (string | optional) the image to display on the left\n                    image: './assets/img/avatar1.jpg',\n                    // (bool | optional) if you want it to fade out on its own or just sit there\n                    sticky: true,\n                    // (int | optional) the time you want it to be alive for before fading out\n                    time: '',\n                    // (string | optional) the class name you want to apply to that specific message\n                    class_name: 'my-sticky-class'\n                });\n\n                // You can have it return a unique id, this can be used to manually remove it later using\n                setTimeout(function () {\n                    $.gritter.remove(unique_id, {\n                        fade: true,\n                        speed: 'slow'\n                    });\n                }, 12000);\n            }, 2000);\n\n            setTimeout(function () {\n                var unique_id = $.gritter.add({\n                    // (string | mandatory) the heading of the notification\n                    title: 'Buy Metronic!',\n                    // (string | mandatory) the text inside the notification\n                    text: 'Metronic comes with a huge collection of reusable and easy customizable UI components and plugins. Buy Metronic today!',\n                    // (string | optional) the image to display on the left\n                    image: './assets/img/avatar1.jpg',\n                    // (bool | optional) if you want it to fade out on its own or just sit there\n                    sticky: true,\n                    // (int | optional) the time you want it to be alive for before fading out\n                    time: '',\n                    // (string | optional) the class name you want to apply to that specific message\n                    class_name: 'my-sticky-class'\n                });\n\n                // You can have it return a unique id, this can be used to manually remove it later using\n                setTimeout(function () {\n                    $.gritter.remove(unique_id, {\n                        fade: true,\n                        speed: 'slow'\n                    });\n                }, 13000);\n            }, 8000);\n\n            setTimeout(function () {\n\n                $('#styler').pulsate({\n                    color: \"#bb3319\",\n                    repeat: 10\n                });\n\n                $.extend($.gritter.options, {\n                    position: 'top-left'\n                });\n\n                var unique_id = $.gritter.add({\n                    position: 'top-left',\n                    // (string | mandatory) the heading of the notification\n                    title: 'Customize Metronic!',\n                    // (string | mandatory) the text inside the notification\n                    text: 'Metronic allows you to easily customize the theme colors and layout settings.',\n                    // (string | optional) the image to display on the left\n                    image1: './assets/img/avatar1.png',\n                    // (bool | optional) if you want it to fade out on its own or just sit there\n                    sticky: true,\n                    // (int | optional) the time you want it to be alive for before fading out\n                    time: '',\n                    // (string | optional) the class name you want to apply to that specific message\n                    class_name: 'my-sticky-class'\n                });\n\n                $.extend($.gritter.options, {\n                    position: 'top-right'\n                });\n\n                // You can have it return a unique id, this can be used to manually remove it later using\n                setTimeout(function () {\n                    $.gritter.remove(unique_id, {\n                        fade: true,\n                        speed: 'slow'\n                    });\n                }, 15000);\n\n            }, 23000);\n\n            setTimeout(function () {\n\n                $.extend($.gritter.options, {\n                    position: 'top-left'\n                });\n\n                var unique_id = $.gritter.add({\n                    // (string | mandatory) the heading of the notification\n                    title: 'Notification',\n                    // (string | mandatory) the text inside the notification\n                    text: 'You have 3 new notifications.',\n                    // (string | optional) the image to display on the left\n                    image1: './assets/img/image1.jpg',\n                    // (bool | optional) if you want it to fade out on its own or just sit there\n                    sticky: true,\n                    // (int | optional) the time you want it to be alive for before fading out\n                    time: '',\n                    // (string | optional) the class name you want to apply to that specific message\n                    class_name: 'my-sticky-class'\n                });\n\n                setTimeout(function () {\n                    $.gritter.remove(unique_id, {\n                        fade: true,\n                        speed: 'slow'\n                    });\n                }, 4000);\n\n                $.extend($.gritter.options, {\n                    position: 'top-right'\n                });\n\n                var number = $('#header_notification_bar .badge').text();\n                number = parseInt(number);\n                number = number + 3;\n                $('#header_notification_bar .badge').text(number);\n                $('#header_notification_bar').pulsate({\n                    color: \"#66bce6\",\n                    repeat: 5\n                });\n\n            }, 40000);\n\n            setTimeout(function () {\n\n                $.extend($.gritter.options, {\n                    position: 'top-left'\n                });\n\n                var unique_id = $.gritter.add({\n                    // (string | mandatory) the heading of the notification\n                    title: 'Inbox',\n                    // (string | mandatory) the text inside the notification\n                    text: 'You have 2 new messages in your inbox.',\n                    // (string | optional) the image to display on the left\n                    image1: './assets/img/avatar1.jpg',\n                    // (bool | optional) if you want it to fade out on its own or just sit there\n                    sticky: true,\n                    // (int | optional) the time you want it to be alive for before fading out\n                    time: '',\n                    // (string | optional) the class name you want to apply to that specific message\n                    class_name: 'my-sticky-class'\n                });\n\n                $.extend($.gritter.options, {\n                    position: 'top-right'\n                });\n\n                setTimeout(function () {\n                    $.gritter.remove(unique_id, {\n                        fade: true,\n                        speed: 'slow'\n                    });\n                }, 4000);\n\n                var number = $('#header_inbox_bar .badge').text();\n                number = parseInt(number);\n                number = number + 2;\n                $('#header_inbox_bar .badge').text(number);\n                $('#header_inbox_bar').pulsate({\n                    color: \"#dd5131\",\n                    repeat: 5\n                });\n\n            }, 60000);\n        }\n\n    };\n\n}();"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/scripts/lock.js",
    "content": "var Lock = function () {\n\n    return {\n        //main function to initiate the module\n        init: function () {\n\n             $.backstretch([\n\t\t        \"assets/img/bg/1.jpg\",\n\t\t        \"assets/img/bg/2.jpg\",\n\t\t        \"assets/img/bg/3.jpg\",\n\t\t        \"assets/img/bg/4.jpg\"\n\t\t        ], {\n\t\t          fade: 1000,\n\t\t          duration: 8000\n\t\t      });\n        }\n\n    };\n\n}();"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/scripts/login-soft.js",
    "content": "var Login = function () {\n\n\tvar handleLogin = function() {\n\t\t$('.login-form').validate({\n\t            errorElement: 'span', //default input error message container\n\t            errorClass: 'help-block', // default input error message class\n\t            focusInvalid: false, // do not focus the last invalid input\n\t            rules: {\n\t                username: {\n\t                    required: true\n\t                },\n\t                password: {\n\t                    required: true\n\t                },\n\t                remember: {\n\t                    required: false\n\t                }\n\t            },\n\n\t            messages: {\n\t                username: {\n\t                    required: \"Username is required.\"\n\t                },\n\t                password: {\n\t                    required: \"Password is required.\"\n\t                }\n\t            },\n\n\t            invalidHandler: function (event, validator) { //display error alert on form submit   \n\t                $('.alert-danger', $('.login-form')).show();\n\t            },\n\n\t            highlight: function (element) { // hightlight error inputs\n\t                $(element)\n\t                    .closest('.form-group').addClass('has-error'); // set error class to the control group\n\t            },\n\n\t            success: function (label) {\n\t                label.closest('.form-group').removeClass('has-error');\n\t                label.remove();\n\t            },\n\n\t            errorPlacement: function (error, element) {\n\t                error.insertAfter(element.closest('.input-icon'));\n\t            },\n\n\t            submitHandler: function (form) {\n\t                form.submit();\n\t            }\n\t        });\n\n\t        $('.login-form input').keypress(function (e) {\n\t            if (e.which == 13) {\n\t                if ($('.login-form').validate().form()) {\n\t                    $('.login-form').submit();\n\t                }\n\t                return false;\n\t            }\n\t        });\n\t}\n\n\tvar handleForgetPassword = function () {\n\t\t$('.forget-form').validate({\n\t            errorElement: 'span', //default input error message container\n\t            errorClass: 'help-block', // default input error message class\n\t            focusInvalid: false, // do not focus the last invalid input\n\t            ignore: \"\",\n\t            rules: {\n\t                email: {\n\t                    required: true,\n\t                    email: true\n\t                }\n\t            },\n\n\t            messages: {\n\t                email: {\n\t                    required: \"Email is required.\"\n\t                }\n\t            },\n\n\t            invalidHandler: function (event, validator) { //display error alert on form submit   \n\n\t            },\n\n\t            highlight: function (element) { // hightlight error inputs\n\t                $(element)\n\t                    .closest('.form-group').addClass('has-error'); // set error class to the control group\n\t            },\n\n\t            success: function (label) {\n\t                label.closest('.form-group').removeClass('has-error');\n\t                label.remove();\n\t            },\n\n\t            errorPlacement: function (error, element) {\n\t                error.insertAfter(element.closest('.input-icon'));\n\t            },\n\n\t            submitHandler: function (form) {\n\t                form.submit();\n\t            }\n\t        });\n\n\t        $('.forget-form input').keypress(function (e) {\n\t            if (e.which == 13) {\n\t                if ($('.forget-form').validate().form()) {\n\t                    $('.forget-form').submit();\n\t                }\n\t                return false;\n\t            }\n\t        });\n\n\t        jQuery('#forget-password').click(function () {\n\t            jQuery('.login-form').hide();\n\t            jQuery('.forget-form').show();\n\t        });\n\n\t        jQuery('#back-btn').click(function () {\n\t            jQuery('.login-form').show();\n\t            jQuery('.forget-form').hide();\n\t        });\n\n\t}\n\n\tvar handleRegister = function () {\n\n\t\tfunction format(state) {\n            if (!state.id) return state.text; // optgroup\n            return \"<img class='flag' src='assets/img/flags/\" + state.id.toLowerCase() + \".png'/>&nbsp;&nbsp;\" + state.text;\n        }\n\n\n\t\t$(\"#select2_sample4\").select2({\n\t\t  \tplaceholder: '<i class=\"fa fa-map-marker\"></i>&nbsp;Select a Country',\n            allowClear: true,\n            formatResult: format,\n            formatSelection: format,\n            escapeMarkup: function (m) {\n                return m;\n            }\n        });\n\n\n\t\t\t$('#select2_sample4').change(function () {\n                $('.register-form').validate().element($(this)); //revalidate the chosen dropdown value and show error or success message for the input\n            });\n\n\n\n         $('.register-form').validate({\n\t            errorElement: 'span', //default input error message container\n\t            errorClass: 'help-block', // default input error message class\n\t            focusInvalid: false, // do not focus the last invalid input\n\t            ignore: \"\",\n\t            rules: {\n\t                \n\t                fullname: {\n\t                    required: true\n\t                },\n\t                email: {\n\t                    required: true,\n\t                    email: true\n\t                },\n\t                address: {\n\t                    required: true\n\t                },\n\t                city: {\n\t                    required: true\n\t                },\n\t                country: {\n\t                    required: true\n\t                },\n\n\t                username: {\n\t                    required: true\n\t                },\n\t                password: {\n\t                    required: true\n\t                },\n\t                rpassword: {\n\t                    equalTo: \"#register_password\"\n\t                },\n\n\t                tnc: {\n\t                    required: true\n\t                }\n\t            },\n\n\t            messages: { // custom messages for radio buttons and checkboxes\n\t                tnc: {\n\t                    required: \"Please accept TNC first.\"\n\t                }\n\t            },\n\n\t            invalidHandler: function (event, validator) { //display error alert on form submit   \n\n\t            },\n\n\t            highlight: function (element) { // hightlight error inputs\n\t                $(element)\n\t                    .closest('.form-group').addClass('has-error'); // set error class to the control group\n\t            },\n\n\t            success: function (label) {\n\t                label.closest('.form-group').removeClass('has-error');\n\t                label.remove();\n\t            },\n\n\t            errorPlacement: function (error, element) {\n\t                if (element.attr(\"name\") == \"tnc\") { // insert checkbox errors after the container                  \n\t                    error.insertAfter($('#register_tnc_error'));\n\t                } else if (element.closest('.input-icon').size() === 1) {\n\t                    error.insertAfter(element.closest('.input-icon'));\n\t                } else {\n\t                \terror.insertAfter(element);\n\t                }\n\t            },\n\n\t            submitHandler: function (form) {\n\t                form.submit();\n\t            }\n\t        });\n\n\t\t\t$('.register-form input').keypress(function (e) {\n\t            if (e.which == 13) {\n\t                if ($('.register-form').validate().form()) {\n\t                    $('.register-form').submit();\n\t                }\n\t                return false;\n\t            }\n\t        });\n\n\t        jQuery('#register-btn').click(function () {\n\t            jQuery('.login-form').hide();\n\t            jQuery('.register-form').show();\n\t        });\n\n\t        jQuery('#register-back-btn').click(function () {\n\t            jQuery('.login-form').show();\n\t            jQuery('.register-form').hide();\n\t        });\n\t}\n    \n    return {\n        //main function to initiate the module\n        init: function () {\n        \t\n            handleLogin();\n            handleForgetPassword();\n            handleRegister();        \n\t       \n\t       \t$.backstretch([\n\t\t        \"assets/img/bg/1.jpg\",\n\t\t        \"assets/img/bg/2.jpg\",\n\t\t        \"assets/img/bg/3.jpg\",\n\t\t        \"assets/img/bg/4.jpg\"\n\t\t        ], {\n\t\t          fade: 1000,\n\t\t          duration: 8000\n\t\t    });\n        }\n\n    };\n\n}();"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/scripts/login.js",
    "content": "var Login = function () {\n\n\tvar handleLogin = function() {\n\n\t\t$('.login-form').validate({\n\t            errorElement: 'span', //default input error message container\n\t            errorClass: 'help-block', // default input error message class\n\t            focusInvalid: false, // do not focus the last invalid input\n\t            rules: {\n\t                username: {\n\t                    required: true\n\t                },\n\t                password: {\n\t                    required: true\n\t                },\n\t                remember: {\n\t                    required: false\n\t                }\n\t            },\n\n\t            messages: {\n\t                username: {\n\t                    required: \"Username is required.\"\n\t                },\n\t                password: {\n\t                    required: \"Password is required.\"\n\t                }\n\t            },\n\n\t            invalidHandler: function (event, validator) { //display error alert on form submit   \n\t                $('.alert-danger', $('.login-form')).show();\n\t            },\n\n\t            highlight: function (element) { // hightlight error inputs\n\t                $(element)\n\t                    .closest('.form-group').addClass('has-error'); // set error class to the control group\n\t            },\n\n\t            success: function (label) {\n\t                label.closest('.form-group').removeClass('has-error');\n\t                label.remove();\n\t            },\n\n\t            errorPlacement: function (error, element) {\n\t                error.insertAfter(element.closest('.input-icon'));\n\t            },\n\n\t            submitHandler: function (form) {\n\t                form.submit(); // form validation success, call ajax form submit\n\t            }\n\t        });\n\n\t        $('.login-form input').keypress(function (e) {\n\t            if (e.which == 13) {\n\t                if ($('.login-form').validate().form()) {\n\t                    $('.login-form').submit(); //form validation success, call ajax form submit\n\t                }\n\t                return false;\n\t            }\n\t        });\n\t}\n\n\tvar handleForgetPassword = function () {\n\t\t$('.forget-form').validate({\n\t            errorElement: 'span', //default input error message container\n\t            errorClass: 'help-block', // default input error message class\n\t            focusInvalid: false, // do not focus the last invalid input\n\t            ignore: \"\",\n\t            rules: {\n\t                email: {\n\t                    required: true,\n\t                    email: true\n\t                }\n\t            },\n\n\t            messages: {\n\t                email: {\n\t                    required: \"Email is required.\"\n\t                }\n\t            },\n\n\t            invalidHandler: function (event, validator) { //display error alert on form submit   \n\n\t            },\n\n\t            highlight: function (element) { // hightlight error inputs\n\t                $(element)\n\t                    .closest('.form-group').addClass('has-error'); // set error class to the control group\n\t            },\n\n\t            success: function (label) {\n\t                label.closest('.form-group').removeClass('has-error');\n\t                label.remove();\n\t            },\n\n\t            errorPlacement: function (error, element) {\n\t                error.insertAfter(element.closest('.input-icon'));\n\t            },\n\n\t            submitHandler: function (form) {\n\t                form.submit();\n\t            }\n\t        });\n\n\t        $('.forget-form input').keypress(function (e) {\n\t            if (e.which == 13) {\n\t                if ($('.forget-form').validate().form()) {\n\t                    $('.forget-form').submit();\n\t                }\n\t                return false;\n\t            }\n\t        });\n\n\t        jQuery('#forget-password').click(function () {\n\t            jQuery('.login-form').hide();\n\t            jQuery('.forget-form').show();\n\t        });\n\n\t        jQuery('#back-btn').click(function () {\n\t            jQuery('.login-form').show();\n\t            jQuery('.forget-form').hide();\n\t        });\n\n\t}\n\n\tvar handleRegister = function () {\n\n\t\tfunction format(state) {\n            if (!state.id) return state.text; // optgroup\n            return \"<img class='flag' src='assets/img/flags/\" + state.id.toLowerCase() + \".png'/>&nbsp;&nbsp;\" + state.text;\n        }\n\n\n\t\t$(\"#select2_sample4\").select2({\n\t\t  \tplaceholder: '<i class=\"fa fa-map-marker\"></i>&nbsp;Select a Country',\n            allowClear: true,\n            formatResult: format,\n            formatSelection: format,\n            escapeMarkup: function (m) {\n                return m;\n            }\n        });\n\n\n\t\t\t$('#select2_sample4').change(function () {\n                $('.register-form').validate().element($(this)); //revalidate the chosen dropdown value and show error or success message for the input\n            });\n\n\n\n         $('.register-form').validate({\n\t            errorElement: 'span', //default input error message container\n\t            errorClass: 'help-block', // default input error message class\n\t            focusInvalid: false, // do not focus the last invalid input\n\t            ignore: \"\",\n\t            rules: {\n\t                \n\t                fullname: {\n\t                    required: true\n\t                },\n\t                email: {\n\t                    required: true,\n\t                    email: true\n\t                },\n\t                address: {\n\t                    required: true\n\t                },\n\t                city: {\n\t                    required: true\n\t                },\n\t                country: {\n\t                    required: true\n\t                },\n\n\t                username: {\n\t                    required: true\n\t                },\n\t                password: {\n\t                    required: true\n\t                },\n\t                rpassword: {\n\t                    equalTo: \"#register_password\"\n\t                },\n\n\t                tnc: {\n\t                    required: true\n\t                }\n\t            },\n\n\t            messages: { // custom messages for radio buttons and checkboxes\n\t                tnc: {\n\t                    required: \"Please accept TNC first.\"\n\t                }\n\t            },\n\n\t            invalidHandler: function (event, validator) { //display error alert on form submit   \n\n\t            },\n\n\t            highlight: function (element) { // hightlight error inputs\n\t                $(element)\n\t                    .closest('.form-group').addClass('has-error'); // set error class to the control group\n\t            },\n\n\t            success: function (label) {\n\t                label.closest('.form-group').removeClass('has-error');\n\t                label.remove();\n\t            },\n\n\t            errorPlacement: function (error, element) {\n\t                if (element.attr(\"name\") == \"tnc\") { // insert checkbox errors after the container                  \n\t                    error.insertAfter($('#register_tnc_error'));\n\t                } else if (element.closest('.input-icon').size() === 1) {\n\t                    error.insertAfter(element.closest('.input-icon'));\n\t                } else {\n\t                \terror.insertAfter(element);\n\t                }\n\t            },\n\n\t            submitHandler: function (form) {\n\t                form.submit();\n\t            }\n\t        });\n\n\t\t\t$('.register-form input').keypress(function (e) {\n\t            if (e.which == 13) {\n\t                if ($('.register-form').validate().form()) {\n\t                    $('.register-form').submit();\n\t                }\n\t                return false;\n\t            }\n\t        });\n\n\t        jQuery('#register-btn').click(function () {\n\t            jQuery('.login-form').hide();\n\t            jQuery('.register-form').show();\n\t        });\n\n\t        jQuery('#register-back-btn').click(function () {\n\t            jQuery('.login-form').show();\n\t            jQuery('.register-form').hide();\n\t        });\n\t}\n    \n    return {\n        //main function to initiate the module\n        init: function () {\n        \t\n            handleLogin();\n            handleForgetPassword();\n            handleRegister();        \n\t       \n        }\n\n    };\n\n}();"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/scripts/maps-google.js",
    "content": "var MapsGoogle = function () {\n\n    var mapBasic = function () {\n        new GMaps({\n            div: '#gmap_basic',\n            lat: -12.043333,\n            lng: -77.028333\n        });\n    }\n\n    var mapMarker = function () {\n        var map = new GMaps({\n            div: '#gmap_marker',\n            lat: -12.043333,\n            lng: -77.028333\n        });\n        map.addMarker({\n            lat: -12.043333,\n            lng: -77.03,\n            title: 'Lima',\n            details: {\n                database_id: 42,\n                author: 'HPNeo'\n            },\n            click: function (e) {\n                if (console.log) console.log(e);\n                alert('You clicked in this marker');\n            }\n        });\n        map.addMarker({\n            lat: -12.042,\n            lng: -77.028333,\n            title: 'Marker with InfoWindow',\n            infoWindow: {\n                content: '<span style=\"color:#000\">HTML Content!</span>'\n            }\n        });\n    }\n\n    var mapPolylines = function () {\n        var map = new GMaps({\n            div: '#gmap_polylines',\n            lat: -12.043333,\n            lng: -77.028333,\n            click: function (e) {\n                console.log(e);\n            }\n        });\n\n        path = [\n            [-12.044012922866312, -77.02470665341184],\n            [-12.05449279282314, -77.03024273281858],\n            [-12.055122327623378, -77.03039293652341],\n            [-12.075917129727586, -77.02764635449216],\n            [-12.07635776902266, -77.02792530422971],\n            [-12.076819390363665, -77.02893381481931],\n            [-12.088527520066453, -77.0241058385925],\n            [-12.090814532191756, -77.02271108990476]\n        ];\n\n        map.drawPolyline({\n            path: path,\n            strokeColor: '#131540',\n            strokeOpacity: 0.6,\n            strokeWeight: 6\n        });\n    }\n\n    var mapGeolocation = function () {\n\n        var map = new GMaps({\n            div: '#gmap_geo',\n            lat: -12.043333,\n            lng: -77.028333\n        });\n\n        GMaps.geolocate({\n            success: function (position) {\n                map.setCenter(position.coords.latitude, position.coords.longitude);\n            },\n            error: function (error) {\n                alert('Geolocation failed: ' + error.message);\n            },\n            not_supported: function () {\n                alert(\"Your browser does not support geolocation\");\n            },\n            always: function () {\n                //alert(\"Geolocation Done!\");\n            }\n        });\n    }\n\n    var mapGeocoding = function () {\n\n        var map = new GMaps({\n            div: '#gmap_geocoding',\n            lat: -12.043333,\n            lng: -77.028333\n        });\n\n        var handleAction = function () {\n            var text = $.trim($('#gmap_geocoding_address').val());\n            GMaps.geocode({\n                address: text,\n                callback: function (results, status) {\n                    if (status == 'OK') {\n                        var latlng = results[0].geometry.location;\n                        map.setCenter(latlng.lat(), latlng.lng());\n                        map.addMarker({\n                            lat: latlng.lat(),\n                            lng: latlng.lng()\n                        });\n                        App.scrollTo($('#gmap_geocoding'));\n                    }\n                }\n            });\n        }\n\n        $('#gmap_geocoding_btn').click(function (e) {\n            e.preventDefault();\n            handleAction();\n        });\n\n        $(\"#gmap_geocoding_address\").keypress(function (e) {\n            var keycode = (e.keyCode ? e.keyCode : e.which);\n            if (keycode == '13') {\n                e.preventDefault();\n                handleAction();\n            }\n        });\n\n    }\n\n    var mapPolygone = function () {\n        var map = new GMaps({\n            div: '#gmap_polygons',\n            lat: -12.043333,\n            lng: -77.028333\n        });\n\n        var path = [\n            [-12.040397656836609, -77.03373871559225],\n            [-12.040248585302038, -77.03993927003302],\n            [-12.050047116528843, -77.02448169303511],\n            [-12.044804866577001, -77.02154422636042]\n        ];\n\n        var polygon = map.drawPolygon({\n            paths: path,\n            strokeColor: '#BBD8E9',\n            strokeOpacity: 1,\n            strokeWeight: 3,\n            fillColor: '#BBD8E9',\n            fillOpacity: 0.6\n        });\n    }\n\n    var mapRoutes = function () {\n\n        var map = new GMaps({\n            div: '#gmap_routes',\n            lat: -12.043333,\n            lng: -77.028333\n        });\n        $('#gmap_routes_start').click(function (e) {\n            e.preventDefault();\n            App.scrollTo($(this), 400);\n            map.travelRoute({\n                origin: [-12.044012922866312, -77.02470665341184],\n                destination: [-12.090814532191756, -77.02271108990476],\n                travelMode: 'driving',\n                step: function (e) {\n                    $('#gmap_routes_instructions').append('<li>' + e.instructions + '</li>');\n                    $('#gmap_routes_instructions li:eq(' + e.step_number + ')').delay(800 * e.step_number).fadeIn(500, function () {\n                        map.setCenter(e.end_location.lat(), e.end_location.lng());\n                        map.drawPolyline({\n                            path: e.path,\n                            strokeColor: '#131540',\n                            strokeOpacity: 0.6,\n                            strokeWeight: 6\n                        });\n                    });\n                }\n            });\n        });\n    }\n\n    return {\n        //main function to initiate map samples\n        init: function () {\n            mapBasic();\n            mapMarker();\n            mapGeolocation();\n            mapGeocoding();\n            mapPolylines();\n            mapPolygone();\n            mapRoutes();\n        }\n\n    };\n\n}();"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/scripts/maps-vector.js",
    "content": "var MapsVector = function () {\n\n    var setMap = function (name) {\n        var data = {\n            map: 'world_en',\n            backgroundColor: null,\n            borderColor: '#333333',\n            borderOpacity: 0.5,\n            borderWidth: 1,\n            color: '#c6c6c6',\n            enableZoom: true,\n            hoverColor: '#c9dfaf',\n            hoverOpacity: null,\n            values: sample_data,\n            normalizeFunction: 'linear',\n            scaleColors: ['#b6da93', '#427d1a'],\n            selectedColor: '#c9dfaf',\n            selectedRegion: null,\n            showTooltip: true,\n            onRegionOver: function (event, code) {\n                //sample to interact with map\n                if (code == 'ca') {\n                    event.preventDefault();\n                }\n            },\n            onRegionClick: function (element, code, region) {\n                //sample to interact with map\n                var message = 'You clicked \"' + region + '\" which has the code: ' + code.toUpperCase();\n                alert(message);\n            }\n        };\n\n        data.map = name + '_en';\n        var map = jQuery('#vmap_' + name);\n        if (!map) {\n            return;\n        }\n        map.width(map.parent().width());\n        map.vectorMap(data);\n    }\n\n\n    return {\n        //main function to initiate map samples\n        init: function () {\n            setMap(\"world\");\n            setMap(\"usa\");\n            setMap(\"europe\");\n            setMap(\"russia\");\n            setMap(\"germany\");\n\n            // redraw maps on window or content resized \n            App.addResponsiveHandler(function(){\n                setMap(\"world\");\n                setMap(\"usa\");\n                setMap(\"europe\");\n                setMap(\"russia\");\n                setMap(\"germany\");\n            });\n        }\n\n    };\n\n}();"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/scripts/portfolio.js",
    "content": "var Portfolio = function () {\n\n\n    return {\n        //main function to initiate the module\n        init: function () {\n            $('.mix-grid').mixitup();\n        }\n\n    };\n\n}();"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/scripts/portlet-draggable.js",
    "content": "var PortletDraggable = function () {\n\n    return {\n        //main function to initiate the module\n        init: function () {\n\n            if (!jQuery().sortable) {\n                return;\n            }\n\n            $(\"#sortable_portlets\").sortable({\n                connectWith: \".portlet\",\n                items: \".portlet\",\n                opacity: 0.8,\n                coneHelperSize: true,\n                placeholder: 'sortable-box-placeholder round-all',\n                forcePlaceholderSize: true,\n                tolerance: \"pointer\"\n            });\n\n            $(\".column\").disableSelection();\n\n        }\n\n    };\n\n}();"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/scripts/search.js",
    "content": "var Search = function () {\n\n    return {\n        //main function to initiate the module\n        init: function () {\n            if (jQuery().datepicker) {\n                $('.date-picker').datepicker();\n            }\n\n            App.initFancybox();\n        }\n\n    };\n\n}();"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/scripts/table-advanced.js",
    "content": "var TableAdvanced = function () {\n\n    var initTable1 = function() {\n\n        /* Formatting function for row details */\n        function fnFormatDetails ( oTable, nTr )\n        {\n            var aData = oTable.fnGetData( nTr );\n            var sOut = '<table>';\n            sOut += '<tr><td>Platform(s):</td><td>'+aData[2]+'</td></tr>';\n            sOut += '<tr><td>Engine version:</td><td>'+aData[3]+'</td></tr>';\n            sOut += '<tr><td>CSS grade:</td><td>'+aData[4]+'</td></tr>';\n            sOut += '<tr><td>Others:</td><td>Could provide a link here</td></tr>';\n            sOut += '</table>';\n             \n            return sOut;\n        }\n\n        /*\n         * Insert a 'details' column to the table\n         */\n        var nCloneTh = document.createElement( 'th' );\n        var nCloneTd = document.createElement( 'td' );\n        nCloneTd.innerHTML = '<span class=\"row-details row-details-close\"></span>';\n         \n        $('#sample_1 thead tr').each( function () {\n            this.insertBefore( nCloneTh, this.childNodes[0] );\n        } );\n         \n        $('#sample_1 tbody tr').each( function () {\n            this.insertBefore(  nCloneTd.cloneNode( true ), this.childNodes[0] );\n        } );\n         \n        /*\n         * Initialize DataTables, with no sorting on the 'details' column\n         */\n        var oTable = $('#sample_1').dataTable( {\n            \"aoColumnDefs\": [\n                {\"bSortable\": false, \"aTargets\": [ 0 ] }\n            ],\n            \"aaSorting\": [[1, 'asc']],\n             \"aLengthMenu\": [\n                [5, 15, 20, -1],\n                [5, 15, 20, \"All\"] // change per page values here\n            ],\n            // set the initial value\n            \"iDisplayLength\": 10,\n        });\n\n        jQuery('#sample_1_wrapper .dataTables_filter input').addClass(\"form-control input-small\"); // modify table search input\n        jQuery('#sample_1_wrapper .dataTables_length select').addClass(\"form-control input-small\"); // modify table per page dropdown\n        jQuery('#sample_1_wrapper .dataTables_length select').select2(); // initialize select2 dropdown\n         \n        /* Add event listener for opening and closing details\n         * Note that the indicator for showing which row is open is not controlled by DataTables,\n         * rather it is done here\n         */\n        $('#sample_1').on('click', ' tbody td .row-details', function () {\n            var nTr = $(this).parents('tr')[0];\n            if ( oTable.fnIsOpen(nTr) )\n            {\n                /* This row is already open - close it */\n                $(this).addClass(\"row-details-close\").removeClass(\"row-details-open\");\n                oTable.fnClose( nTr );\n            }\n            else\n            {\n                /* Open this row */                \n                $(this).addClass(\"row-details-open\").removeClass(\"row-details-close\");\n                oTable.fnOpen( nTr, fnFormatDetails(oTable, nTr), 'details' );\n            }\n        });\n    }\n\n     var initTable2 = function() {\n        var oTable = $('#sample_2').dataTable( {           \n            \"aoColumnDefs\": [\n                { \"aTargets\": [ 0 ] }\n            ],\n            \"aaSorting\": [[1, 'asc']],\n             \"aLengthMenu\": [\n                [5, 15, 20, -1],\n                [5, 15, 20, \"All\"] // change per page values here\n            ],\n            // set the initial value\n            \"iDisplayLength\": 10,\n        });\n\n        jQuery('#sample_2_wrapper .dataTables_filter input').addClass(\"form-control input-small\"); // modify table search input\n        jQuery('#sample_2_wrapper .dataTables_length select').addClass(\"form-control input-small\"); // modify table per page dropdown\n        jQuery('#sample_2_wrapper .dataTables_length select').select2(); // initialize select2 dropdown\n\n        $('#sample_2_column_toggler input[type=\"checkbox\"]').change(function(){\n            /* Get the DataTables object again - this is not a recreation, just a get of the object */\n            var iCol = parseInt($(this).attr(\"data-column\"));\n            var bVis = oTable.fnSettings().aoColumns[iCol].bVisible;\n            oTable.fnSetColumnVis(iCol, (bVis ? false : true));\n        });\n    }\n\n    return {\n\n        //main function to initiate the module\n        init: function () {\n            \n            if (!jQuery().dataTable) {\n                return;\n            }\n\n            initTable1();\n            initTable2();\n        }\n\n    };\n\n}();"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/scripts/table-ajax.js",
    "content": "var TableAjax = function () {\n\n    return {\n\n        //main function to initiate the module\n        init: function () {\n            \n            if (!jQuery().dataTable) {\n                return;\n            }\n\n            // begin first table\n            $('#sample_1').dataTable({\n                \"sDom\" : \"<'row'<'col-md-6 col-sm-12'l><'col-md-12 col-sm-12'f>r>t<'row'<'col-md-5 col-sm-12'i><'col-md-7 col-sm-12'p>>\", //default layout without horizontal scroll(remove this setting to enable horizontal scroll for the table)\n                \"aLengthMenu\": [\n                    [10, 25, 50, 100, -1],\n                    [10, 25, 50, 100, \"All\"] // change per page values here\n                ],\n                \"bProcessing\": true,\n                \"bServerSide\": true,\n                \"sAjaxSource\": \"demo/table_ajax.php\",\n                // set the initial value\n                \"iDisplayLength\": 10,\n                \"sPaginationType\": \"bootstrap\",\n                \"oLanguage\": {\n                    \"sProcessing\": '<i class=\"fa fa-coffee\"></i>&nbsp;Please wait...',\n                    \"sLengthMenu\": \"_MENU_ records\",\n                    \"oPaginate\": {\n                        \"sPrevious\": \"Prev\",\n                        \"sNext\": \"Next\"\n                    }\n                },\n                \"aoColumnDefs\": [{\n                        'bSortable': false,\n                        'aTargets': [0]\n                    }\n                ]\n            });\n\n            jQuery('#sample_1_wrapper .dataTables_filter input').addClass(\"form-control input-medium\"); // modify table search input\n            jQuery('#sample_1_wrapper .dataTables_length select').addClass(\"form-control input-small\"); // modify table per page dropdown\n\n            // handle record edit/remove\n            $('body').on('click', '#sample_1_wrapper .btn-editable', function() {\n                alert('Edit record with id:' + $(this).attr(\"data-id\"));\n            });\n\n            $('body').on('click', '#sample_1_wrapper .btn-removable', function() {\n                alert('Remove record with id:' + $(this).attr(\"data-id\"));\n            });\n\n        }\n\n    };\n\n}();"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/scripts/table-editable.js",
    "content": "var TableEditable = function () {\n\n    return {\n\n        //main function to initiate the module\n        init: function () {\n            function restoreRow(oTable, nRow) {\n                var aData = oTable.fnGetData(nRow);\n                var jqTds = $('>td', nRow);\n\n                for (var i = 0, iLen = jqTds.length; i < iLen; i++) {\n                    oTable.fnUpdate(aData[i], nRow, i, false);\n                }\n\n                oTable.fnDraw();\n            }\n\n            function editRow(oTable, nRow) {\n                var aData = oTable.fnGetData(nRow);\n                var jqTds = $('>td', nRow);\n                jqTds[0].innerHTML = '<input type=\"text\" class=\"form-control input-small\" value=\"' + aData[0] + '\">';\n                jqTds[1].innerHTML = '<input type=\"text\" class=\"form-control input-small\" value=\"' + aData[1] + '\">';\n                jqTds[2].innerHTML = '<input type=\"text\" class=\"form-control input-small\" value=\"' + aData[2] + '\">';\n                jqTds[3].innerHTML = '<input type=\"text\" class=\"form-control input-small\" value=\"' + aData[3] + '\">';\n                jqTds[4].innerHTML = '<a class=\"edit\" href=\"\">Save</a>';\n                jqTds[5].innerHTML = '<a class=\"cancel\" href=\"\">Cancel</a>';\n            }\n\n            function saveRow(oTable, nRow) {\n                var jqInputs = $('input', nRow);\n                oTable.fnUpdate(jqInputs[0].value, nRow, 0, false);\n                oTable.fnUpdate(jqInputs[1].value, nRow, 1, false);\n                oTable.fnUpdate(jqInputs[2].value, nRow, 2, false);\n                oTable.fnUpdate(jqInputs[3].value, nRow, 3, false);\n                oTable.fnUpdate('<a class=\"edit\" href=\"\">Edit</a>', nRow, 4, false);\n                oTable.fnUpdate('<a class=\"delete\" href=\"\">Delete</a>', nRow, 5, false);\n                oTable.fnDraw();\n            }\n\n            function cancelEditRow(oTable, nRow) {\n                var jqInputs = $('input', nRow);\n                oTable.fnUpdate(jqInputs[0].value, nRow, 0, false);\n                oTable.fnUpdate(jqInputs[1].value, nRow, 1, false);\n                oTable.fnUpdate(jqInputs[2].value, nRow, 2, false);\n                oTable.fnUpdate(jqInputs[3].value, nRow, 3, false);\n                oTable.fnUpdate('<a class=\"edit\" href=\"\">Edit</a>', nRow, 4, false);\n                oTable.fnDraw();\n            }\n\n            var oTable = $('#sample_editable_1').dataTable({\n                // set the initial value\n                \"iDisplayLength\": 100,\n                \n                \"sPaginationType\": \"bootstrap\",\n                \"oLanguage\": {\n                    \"sLengthMenu\": \"_MENU_ records\",\n                    \"oPaginate\": {\n                        \"sPrevious\": \"Prev\",\n                        \"sNext\": \"Next\"\n                    }\n                },\n                \"aoColumnDefs\": \n                [\n                   {'bSortable': false,'aTargets': [0]}\n                ]\n            });\n            jQuery('#sample_editable_1_wrapper>div:first-child').css(\"display\",\"none\");\n            \n\n            jQuery('#sample_editable_1_wrapper .dataTables_filter input').addClass(\"form-control input-medium\"); // modify table search input\n            jQuery('#sample_editable_1_wrapper .dataTables_length select').addClass(\"form-control input-small\"); // modify table per page dropdown\n            jQuery('#sample_editable_1_wrapper .dataTables_length select').select2({\n                showSearchInput : false //hide search box with special css class\n            }); // initialize select2 dropdown\n\n            var nEditing = null;\n\n            $('#sample_editable_1_new').click(function (e) {\n                e.preventDefault();\n                var aiNew = oTable.fnAddData(['', '', '', '',\n                        '<a class=\"edit\" href=\"\">Edit</a>', '<a class=\"cancel\" data-mode=\"new\" href=\"\">Cancel</a>'\n                ]);\n                var nRow = oTable.fnGetNodes(aiNew[0]);\n                editRow(oTable, nRow);\n                nEditing = nRow;\n            });\n\n            $('#sample_editable_1 a.delete').live('click', function (e) {\n                e.preventDefault();\n\n                if (confirm(\"Are you sure to delete this row ?\") == false) {\n                    return;\n                }\n\n                var nRow = $(this).parents('tr')[0];\n                oTable.fnDeleteRow(nRow);\n                alert(\"Deleted! Do not forget to do some ajax to sync with backend :)\");\n            });\n\n            $('#sample_editable_1 a.cancel').live('click', function (e) {\n                e.preventDefault();\n                if ($(this).attr(\"data-mode\") == \"new\") {\n                    var nRow = $(this).parents('tr')[0];\n                    oTable.fnDeleteRow(nRow);\n                } else {\n                    restoreRow(oTable, nEditing);\n                    nEditing = null;\n                }\n            });\n\n            $('#sample_editable_1 a.edit').live('click', function (e) {\n                e.preventDefault();\n\n                /* Get the row as a parent of the link that was clicked on */\n                var nRow = $(this).parents('tr')[0];\n\n                if (nEditing !== null && nEditing != nRow) {\n                    /* Currently editing - but not this row - restore the old before continuing to edit mode */\n                    restoreRow(oTable, nEditing);\n                    editRow(oTable, nRow);\n                    nEditing = nRow;\n                } else if (nEditing == nRow && this.innerHTML == \"Save\") {\n                    /* Editing this row and want to save it */\n                    saveRow(oTable, nEditing);\n                    nEditing = null;\n                    alert(\"Updated! Do not forget to do some ajax to sync with backend :)\");\n                } else {\n                    /* No edit in progress - let's start one */\n                    editRow(oTable, nRow);\n                    nEditing = nRow;\n                }\n            });\n        }\n\n    };\n\n}();"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/scripts/table-managed.js",
    "content": "var TableManaged = function () {\n    return {\n        //main function to initiate the module\n        init: function () {\n            \n            if (!jQuery().dataTable) {\n                return;\n            }\n            // begin first table\n            $('#tableDataList').dataTable({\n                \"iDisplayLength\": 100,\n                \"sPaginationType\": \"bootstrap\",\n                \"oLanguage\": {\n                    \"sLengthMenu\": \"_MENU_ records\",\n                    \"oPaginate\": {\n                        \"sPrevious\": \"Prev\",\n                        \"sNext\": \"Next\"\n                    }\n                },\n            });\n            //jQuery('.pagination>li:first-child').css(\"display\",\"none\");\n            //jQuery('.pagination>li:last-child').css(\"display\",\"none\");\n            jQuery('#tableDataList_wrapper>div:first-child').css(\"display\",\"none\");\n            \n        }\n\n    };\n\n}();"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/scripts/tasks.js",
    "content": "var Tasks = function () {\n\n\n    return {\n\n        //main function to initiate the module\n        initDashboardWidget: function () {\n\t\t\t$('input.liChild').change(function() {\n\t\t\t\tif ($(this).is(':checked')) { \n\t\t\t\t\t$(this).parents('li').addClass(\"task-done\"); \n\t\t\t\t} else { \n\t\t\t\t\t$(this).parents('li').removeClass(\"task-done\"); \n\t\t\t\t}\n\t\t\t}); \n        }\n\n    };\n\n}();"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/scripts/ui-bootbox.js",
    "content": "var UIBootbox = function () {\n\n    return {\n\n        //main function to initiate the module\n        init: function () {\n\n            $('#demo_1').click(function(){\n                bootbox.alert(\"Hello world!\");    \n            });\n            //end #demo_1\n\n            $('#demo_2').click(function(){\n                bootbox.alert(\"Hello world!\", function() {\n                    alert(\"Hello world callback\");\n                });  \n            });\n            //end #demo_2\n        \n            $('#demo_3').click(function(){\n                bootbox.confirm(\"Are you sure?\", function(result) {\n                   alert(\"Confirm result: \"+result);\n                }); \n            });\n            //end #demo_3\n\n            $('#demo_4').click(function(){\n                bootbox.prompt(\"What is your name?\", function(result) {\n                    if (result === null) {\n                        alert(\"Prompt dismissed\");\n                    } else {\n                        alert(\"Hi <b>\"+result+\"</b>\");\n                    }\n                });\n            });\n            //end #demo_6\n\n            $('#demo_5').click(function(){\n                bootbox.dialog({\n                    message: \"I am a custom dialog\",\n                    title: \"Custom title\",\n                    buttons: {\n                      success: {\n                        label: \"Success!\",\n                        className: \"green\",\n                        callback: function() {\n                          alert(\"great success\");\n                        }\n                      },\n                      danger: {\n                        label: \"Danger!\",\n                        className: \"red\",\n                        callback: function() {\n                          alert(\"uh oh, look out!\");\n                        }\n                      },\n                      main: {\n                        label: \"Click ME!\",\n                        className: \"blue\",\n                        callback: function() {\n                          alert(\"Primary button\");\n                        }\n                      }\n                    }\n                });\n            });\n            //end #demo_7\n        }\n    };\n\n}();"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/scripts/ui-datepaginator.js",
    "content": "var UIDatepaginator = function () {\n\n    return {\n\n        //main function to initiate the module\n        init: function () {\n\n            //sample #1\n            $('#datepaginator_sample_1').datepaginator();\n\n            //sample #2\n            $('#datepaginator_sample_2').datepaginator({\n                size: \"large\"\n            });\n\n            //sample #3\n            $('#datepaginator_sample_3').datepaginator({\n                size: \"small\"\n            });\n\n            //sample #3\n            $('#datepaginator_sample_4').datepaginator({\n                onSelectedDateChanged: function(event, date) {\n                  alert(\"Selected date: \" + moment(date).format(\"Do, MMM YYYY\"));\n                }\n            });\n            \n        } // end init\n\n    };\n\n}();"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/scripts/ui-extended-modals.js",
    "content": "var UIExtendedModals = function () {\n\n    \n    return {\n        //main function to initiate the module\n        init: function () {\n        \n            // general settings\n            $.fn.modal.defaults.spinner = $.fn.modalmanager.defaults.spinner = \n              '<div class=\"loading-spinner\" style=\"width: 200px; margin-left: -100px;\">' +\n                '<div class=\"progress progress-striped active\">' +\n                  '<div class=\"progress-bar\" style=\"width: 100%;\"></div>' +\n                '</div>' +\n              '</div>';\n\n            $.fn.modalmanager.defaults.resize = true;\n\n            //dynamic demo:\n            $('.dynamic .demo').click(function(){\n              var tmpl = [\n                // tabindex is required for focus\n                '<div class=\"modal hide fade\" tabindex=\"-1\">',\n                  '<div class=\"modal-header\">',\n                    '<button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\">×</button>',\n                    '<h4 class=\"modal-title\">Modal header</h4>', \n                  '</div>',\n                  '<div class=\"modal-body\">',\n                    '<p>Test</p>',\n                  '</div>',\n                  '<div class=\"modal-footer\">',\n                    '<a href=\"#\" data-dismiss=\"modal\" class=\"btn btn-default\">Close</a>',\n                    '<a href=\"#\" class=\"btn btn-primary\">Save changes</a>',\n                  '</div>',\n                '</div>'\n              ].join('');\n              \n              $(tmpl).modal();\n            });\n\n            //ajax demo:\n            var $modal = $('#ajax-modal');\n\n            $('#ajax-demo').on('click', function(){\n              // create the backdrop and wait for next modal to be triggered\n              $('body').modalmanager('loading');\n\n              setTimeout(function(){\n                  $modal.load('ui_extended_modals_ajax_sample.html', '', function(){\n                  $modal.modal();\n                });\n              }, 1000);\n            });\n\n            $modal.on('click', '.update', function(){\n              $modal.modal('loading');\n              setTimeout(function(){\n                $modal\n                  .modal('loading')\n                  .find('.modal-body')\n                    .prepend('<div class=\"alert alert-info fade in\">' +\n                      'Updated!<button type=\"button\" class=\"close\" data-dismiss=\"alert\">&times;</button>' +\n                    '</div>');\n              }, 1000);\n            });\n        }\n\n    };\n\n}();"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/scripts/ui-general.js",
    "content": "var UIGeneral = function () {\n\n    var handlePulsate = function () {\n        if (!jQuery().pulsate) {\n            return;\n        }\n\n        if (App.isIE8() == true) {\n            return; // pulsate plugin does not support IE8 and below\n        }\n\n        if (jQuery().pulsate) {\n            jQuery('#pulsate-regular').pulsate({\n                color: \"#bf1c56\"\n            });\n\n            jQuery('#pulsate-once').click(function () {\n                $('#pulsate-once-target').pulsate({\n                    color: \"#399bc3\",\n                    repeat: false\n                });\n            });\n\n            jQuery('#pulsate-crazy').click(function () {\n                $('#pulsate-crazy-target').pulsate({\n                    color: \"#fdbe41\",\n                    reach: 50,\n                    repeat: 10,\n                    speed: 100,\n                    glow: true\n                });\n            });\n        }\n    }\n\n    var handleGritterNotifications = function () {\n        if (!jQuery.gritter) {\n            return;\n        }\n\n        $('#gritter-sticky').click(function () {\n            var unique_id = $.gritter.add({\n                // (string | mandatory) the heading of the notification\n                title: 'This is a sticky notice!',\n                // (string | mandatory) the text inside the notification\n                text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus eget tincidunt velit. Cum sociis natoque penatibus et <a href=\"#\">some link sample</a> montes, nascetur ridiculus mus.',\n                // (string | optional) the image to display on the left\n                image: './assets/img/avatar1.jpg',\n                // (bool | optional) if you want it to fade out on its own or just sit there\n                sticky: true,\n                // (int | optional) the time you want it to be alive for before fading out\n                time: '',\n                // (string | optional) the class name you want to apply to that specific message\n                class_name: 'my-sticky-class'\n            });\n            return false;\n        });\n\n        $('#gritter-regular').click(function () {\n\n            $.gritter.add({\n                // (string | mandatory) the heading of the notification\n                title: 'This is a regular notice!',\n                // (string | mandatory) the text inside the notification\n                text: 'This will fade out after a certain amount of time. Vivamus eget tincidunt velit. Cum sociis natoque penatibus et <a href=\"#\">some link sample</a> montes, nascetur ridiculus mus.',\n                // (string | optional) the image to display on the left\n                image: './assets/img/avatar1.jpg',\n                // (bool | optional) if you want it to fade out on its own or just sit there\n                sticky: false,\n                // (int | optional) the time you want it to be alive for before fading out\n                time: ''\n            });\n\n            return false;\n\n        });\n\n        $('#gritter-max').click(function () {\n\n            $.gritter.add({\n                // (string | mandatory) the heading of the notification\n                title: 'This is a notice with a max of 3 on screen at one time!',\n                // (string | mandatory) the text inside the notification\n                text: 'This will fade out after a certain amount of time. Vivamus eget tincidunt velit. Cum sociis natoque penatibus et <a href=\"#\">some link sample</a> montes, nascetur ridiculus mus.',\n                // (string | optional) the image to display on the left\n                image: './assets/img/avatar1.jpg',\n                // (bool | optional) if you want it to fade out on its own or just sit there\n                sticky: false,\n                // (function) before the gritter notice is opened\n                before_open: function () {\n                    if ($('.gritter-item-wrapper').length == 3) {\n                        // Returning false prevents a new gritter from opening\n                        return false;\n                    }\n                }\n            });\n            return false;\n        });\n\n        $('#gritter-without-image').click(function () {\n            $.gritter.add({\n                // (string | mandatory) the heading of the notification\n                title: 'This is a notice without an image!',\n                // (string | mandatory) the text inside the notification\n                text: 'This will fade out after a certain amount of time. Vivamus eget tincidunt velit. Cum sociis natoque penatibus et <a href=\"#\">some link sample</a> montes, nascetur ridiculus mus.'\n            });\n\n            return false;\n        });\n\n        $('#gritter-light').click(function () {\n\n            $.gritter.add({\n                // (string | mandatory) the heading of the notification\n                title: 'This is a light notification',\n                // (string | mandatory) the text inside the notification\n                text: 'Just add a \"gritter-light\" class_name to your $.gritter.add or globally to $.gritter.options.class_name',\n                class_name: 'gritter-light'\n            });\n\n            return false;\n        });\n\n        $(\"#gritter-remove-all\").click(function () {\n\n            $.gritter.removeAll();\n            return false;\n\n        });\n    }\n\n    var handleDynamicPagination = function() {\n        $('#dynamic_pager_demo1').bootpag({\n            paginationClass: 'pagination',\n            next: '<icon class=\"fa fa-angle-right\"></i>',\n            prev: '<icon class=\"fa fa-angle-left\"></i>',\n            total: 6,\n            page: 1,\n        }).on(\"page\", function(event, num){\n            $(\"#dynamic_pager_content1\").html(\"Page \" + num + \" content here\"); // or some ajax content loading...\n        });\n\n        $('#dynamic_pager_demo2').bootpag({\n            paginationClass: 'pagination pagination-sm',\n            next: '<icon class=\"fa fa-angle-right\"></i>',\n            prev: '<icon class=\"fa fa-angle-left\"></i>',\n            total: 24,\n            page: 1,\n            maxVisible: 6 \n        }).on('page', function(event, num){\n            $(\"#dynamic_pager_content2\").html(\"Page \" + num + \" content here\"); // or some ajax content loading...\n        });\n    }\n\n    return {\n        //main function to initiate the module\n        init: function () {\n            handlePulsate();\n            handleGritterNotifications();\n            handleDynamicPagination();\n        }\n\n    };\n\n}();"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/scripts/ui-ion-sliders.js",
    "content": "var UIIonSliders = function () {\n\n    return {\n        //main function to initiate the module\n        init: function () {\n\n            $(\"#range_1\").ionRangeSlider({\n                min: 0,\n                max: 5000,\n                from: 1000,\n                to: 4000,\n                type: 'double',\n                step: 1,\n                prefix: \"$\",\n                prettify: false,\n                hasGrid: true\n            });\n\n            $(\"#range_2\").ionRangeSlider();\n\n            $(\"#range_5\").ionRangeSlider({\n                min: 0,\n                max: 10,\n                type: 'single',\n                step: 0.1,\n                postfix: \" mm\",\n                prettify: false,\n                hasGrid: true\n            });\n\n            $(\"#range_6\").ionRangeSlider({\n                min: -50,\n                max: 50,\n                from: 0,\n                type: 'single',\n                step: 1,\n                postfix: \"°\",\n                prettify: false,\n                hasGrid: true\n            });\n\n            $(\"#range_4\").ionRangeSlider({\n                type: \"single\",\n                step: 100,\n                postfix: \" light years\",\n                from: 55000,\n                hideText: true\n            });\n            \n            $(\"#range_3\").ionRangeSlider({\n                type: \"double\",\n                postfix: \" miles\",\n                step: 10000,\n                from: 25000000,\n                to: 35000000,\n                onChange: function(obj){\n                    var t = \"\";\n                    for(var prop in obj) {\n                        t += prop + \": \" + obj[prop] + \"\\r\\n\";\n                    }\n                    $(\"#result\").html(t);\n                }\n            });\n\n            $(\"#updateLast\").on(\"click\", function(){\n\n                $(\"#range_3\").ionRangeSlider(\"update\", {\n                    min: Math.round(10000 + Math.random() * 40000),\n                    max: Math.round(200000 + Math.random() * 100000),\n                    step: 1,\n                    from: Math.round(40000 + Math.random() * 40000),\n                    to: Math.round(150000 + Math.random() * 80000)\n                });\n\n            });\n            \n        }\n\n    };\n\n}();"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/scripts/ui-jqueryui-sliders.js",
    "content": "\nvar UIjQueryUISliders = function () {\n\n    return {\n        //main function to initiate the module\n        init: function () {\n            // basic\n            $(\".slider-basic\").slider(); // basic sliders\n\n             // vertical range sliders\n            $(\"#slider-range\").slider({\n                isRTL: App.isRTL(),\n                range: true,\n                values: [17, 67],\n                slide: function (event, ui) {\n                    $(\"#slider-range-amount\").text(\"$\" + ui.values[0] + \" - $\" + ui.values[1]);\n                }\n            });\n            \n            // snap inc\n            $(\"#slider-snap-inc\").slider({\n                isRTL: App.isRTL(),\n                value: 100,\n                min: 0,\n                max: 1000,\n                step: 100,\n                slide: function (event, ui) {\n                    $(\"#slider-snap-inc-amount\").text(\"$\" + ui.value);\n                }\n            });\n\n            $(\"#slider-snap-inc-amount\").text(\"$\" + $(\"#slider-snap-inc\").slider(\"value\"));\n\n            // range slider\n            $(\"#slider-range\").slider({\n                isRTL: App.isRTL(),\n                range: true,\n                min: 0,\n                max: 500,\n                values: [75, 300],\n                slide: function (event, ui) {\n                    $(\"#slider-range-amount\").text(\"$\" + ui.values[0] + \" - $\" + ui.values[1]);\n                }\n            });\n\n            $(\"#slider-range-amount\").text(\"$\" + $(\"#slider-range\").slider(\"values\", 0) + \" - $\" + $(\"#slider-range\").slider(\"values\", 1));\n\n            //range max\n\n            $(\"#slider-range-max\").slider({\n                isRTL: App.isRTL(),\n                range: \"max\",\n                min: 1,\n                max: 10,\n                value: 2,\n                slide: function (event, ui) {\n                    $(\"#slider-range-max-amount\").text(ui.value);\n                }\n            });\n\n            $(\"#slider-range-max-amount\").text($(\"#slider-range-max\").slider(\"value\"));\n\n            // range min\n            $(\"#slider-range-min\").slider({\n                isRTL: App.isRTL(),\n                range: \"min\",\n                value: 37,\n                min: 1,\n                max: 700,\n                slide: function (event, ui) {\n                    $(\"#slider-range-min-amount\").text(\"$\" + ui.value);\n                }\n            });\n\n            $(\"#slider-range-min-amount\").text(\"$\" + $(\"#slider-range-min\").slider(\"value\"));\n\n            // vertical slider\n            $(\"#slider-vertical\").slider({\n                isRTL: App.isRTL(),\n                orientation: \"vertical\",\n                range: \"min\",\n                min: 0,\n                max: 100,\n                value: 60,\n                slide: function (event, ui) {\n                    $(\"#slider-vertical-amount\").text(ui.value);\n                }\n            });\n            $(\"#slider-vertical-amount\").text($(\"#slider-vertical\").slider(\"value\"));\n\n            // vertical range sliders\n            $(\"#slider-range-vertical\").slider({\n                isRTL: App.isRTL(),\n                orientation: \"vertical\",\n                range: true,\n                values: [17, 67],\n                slide: function (event, ui) {\n                    $(\"#slider-range-vertical-amount\").text(\"$\" + ui.values[0] + \" - $\" + ui.values[1]);\n                }\n            });\n\n            $(\"#slider-range-vertical-amount\").text(\"$\" + $(\"#slider-range-vertical\").slider(\"values\", 0) + \" - $\" + $(\"#slider-range-vertical\").slider(\"values\", 1));\n\n        }\n\n    };\n\n}();"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/scripts/ui-knob.js",
    "content": "var UIKnob = function () {\n\n    return {\n        //main function to initiate the module\n        \n        init: function () {\n            //knob does not support ie8 so skip it\n            if (!jQuery().knob || App.isIE8()) {\n                return;\n            }\n\n            // general knob\n            $(\".knob\").knob({\n                'dynamicDraw': true,\n                'thickness': 0.2,\n                'tickColorizeValues': true,\n                'skin': 'tron'\n            });  \n        }\n\n    };\n\n}();\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/scripts/ui-nestable.js",
    "content": "var UINestable = function () {\n\n    var updateOutput = function (e) {\n        var list = e.length ? e : $(e.target),\n            output = list.data('output');\n        if (window.JSON) {\n            output.val(window.JSON.stringify(list.nestable('serialize'))); //, null, 2));\n        } else {\n            output.val('JSON browser support required for this demo.');\n        }\n    };\n\n\n    return {\n        //main function to initiate the module\n        init: function () {\n\n            // activate Nestable for list 1\n            $('#nestable_list_1').nestable({\n                group: 1\n            })\n                .on('change', updateOutput);\n\n            // activate Nestable for list 2\n            $('#nestable_list_2').nestable({\n                group: 1\n            })\n                .on('change', updateOutput);\n\n            // output initial serialised data\n            updateOutput($('#nestable_list_1').data('output', $('#nestable_list_1_output')));\n            updateOutput($('#nestable_list_2').data('output', $('#nestable_list_2_output')));\n\n            $('#nestable_list_menu').on('click', function (e) {\n                var target = $(e.target),\n                    action = target.data('action');\n                if (action === 'expand-all') {\n                    $('.dd').nestable('expandAll');\n                }\n                if (action === 'collapse-all') {\n                    $('.dd').nestable('collapseAll');\n                }\n            });\n\n            $('#nestable_list_3').nestable();\n\n        }\n\n    };\n\n}();"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/scripts/ui-nouisliders.js",
    "content": "var UINoUiSliders = function () {\n\n    return {\n        //main function to initiate the module\n        init: function () {\n\n            // slider 1\n            $(\"#slider_1\").noUiSlider({\n                 start: [20, 80]\n                ,range: [0, 100]\n                ,connect: true\n                ,handles: 2\n            });\n\n            // slider 2\n            $('#slider_2').noUiSlider({\n                     range: [-20,40]\n                    ,start: [10,30]\n                    ,handles: 2\n                    ,connect: true\n                    ,step: 1\n                    ,serialization: {\n                         to: [$('#slider_2_input_start'), $('#slider_2_input_end')]\n                        ,resolution: 1\n                }\n            });\n\n            // slider 3\n            $(\"#slider_3\").noUiSlider({\n                 start: [20, 80]\n                ,range: [0, 100]\n                ,connect: true\n                ,handles: 2\n            });\n\n            $(\"#slider_3_checkbox\").change(function(){\n                // If the checkbox is checked\n                if ($(this).is(\":checked\")) {\n                    // Disable the slider\n                    $(\"#slider_3\").attr(\"disabled\", \"disabled\");\n                } else {\n                    // Enabled the slider\n                    $(\"#slider_3\").removeAttr(\"disabled\");\n                }\n            });\n\n            // slider 4\n            $(\"#slider_4\").noUiSlider({\n                 start: [20, 80]\n                ,range: [0, 100]\n                ,connect: true\n                ,handles: 2\n            });\n\n            $(\"#slider_4_btn\").click(function(){\n                alert($(\"#slider_4\").val());\n            });\n        }\n\n    };\n\n}();"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/scripts/ui-toastr.js",
    "content": "var UIToastr = function () {\n\n    return {\n        //main function to initiate the module\n        init: function () {\n\n            var i = -1,\n                toastCount = 0,\n                $toastlast,\n                getMessage = function () {\n                    var msgs = ['Hello, some notification sample goes here',\n                        '<div><input class=\"form-control input-small\" value=\"textbox\"/>&nbsp;<a href=\"http://themeforest.net/item/metronic-responsive-admin-dashboard-template/4021469?ref=keenthemes\" target=\"_blank\">Check this out</a></div><div><button type=\"button\" id=\"okBtn\" class=\"btn blue\">Close me</button><button type=\"button\" id=\"surpriseBtn\" class=\"btn default\" style=\"margin: 0 8px 0 8px\">Surprise me</button></div>',\n                        'Did you like this one ? :)',\n                        'Totally Awesome!!!',\n                        'Yeah, this is the Metronic!',\n                        'Explore the power of Metronic. Purchase it now!'\n                    ];\n                    i++;\n                    if (i === msgs.length) {\n                        i = 0;\n                    }\n\n                    return msgs[i];\n                };\n\n            $('#showtoast').click(function () {\n                var shortCutFunction = $(\"#toastTypeGroup input:checked\").val();\n                var msg = $('#message').val();\n                var title = $('#title').val() || '';\n                var $showDuration = $('#showDuration');\n                var $hideDuration = $('#hideDuration');\n                var $timeOut = $('#timeOut');\n                var $extendedTimeOut = $('#extendedTimeOut');\n                var $showEasing = $('#showEasing');\n                var $hideEasing = $('#hideEasing');\n                var $showMethod = $('#showMethod');\n                var $hideMethod = $('#hideMethod');\n                var toastIndex = toastCount++;\n\n                toastr.options = {\n                    closeButton: $('#closeButton').prop('checked'),\n                    debug: $('#debugInfo').prop('checked'),\n                    positionClass: $('#positionGroup input:checked').val() || 'toast-top-right',\n                    onclick: null\n                };\n\n                if ($('#addBehaviorOnToastClick').prop('checked')) {\n                    toastr.options.onclick = function () {\n                        alert('You can perform some custom action after a toast goes away');\n                    };\n                }\n\n                if ($showDuration.val().length) {\n                    toastr.options.showDuration = $showDuration.val();\n                }\n\n                if ($hideDuration.val().length) {\n                    toastr.options.hideDuration = $hideDuration.val();\n                }\n\n                if ($timeOut.val().length) {\n                    toastr.options.timeOut = $timeOut.val();\n                }\n\n                if ($extendedTimeOut.val().length) {\n                    toastr.options.extendedTimeOut = $extendedTimeOut.val();\n                }\n\n                if ($showEasing.val().length) {\n                    toastr.options.showEasing = $showEasing.val();\n                }\n\n                if ($hideEasing.val().length) {\n                    toastr.options.hideEasing = $hideEasing.val();\n                }\n\n                if ($showMethod.val().length) {\n                    toastr.options.showMethod = $showMethod.val();\n                }\n\n                if ($hideMethod.val().length) {\n                    toastr.options.hideMethod = $hideMethod.val();\n                }\n\n                if (!msg) {\n                    msg = getMessage();\n                }\n\n                $(\"#toastrOptions\").text(\"Command: toastr[\" + shortCutFunction + \"](\\\"\" + msg + (title ? \"\\\", \\\"\" + title : '') + \"\\\")\\n\\ntoastr.options = \" + JSON.stringify(toastr.options, null, 2));\n\n                var $toast = toastr[shortCutFunction](msg, title); // Wire up an event handler to a button in the toast, if it exists\n                $toastlast = $toast;\n                if ($toast.find('#okBtn').length) {\n                    $toast.delegate('#okBtn', 'click', function () {\n                        alert('you clicked me. i was toast #' + toastIndex + '. goodbye!');\n                        $toast.remove();\n                    });\n                }\n                if ($toast.find('#surpriseBtn').length) {\n                    $toast.delegate('#surpriseBtn', 'click', function () {\n                        alert('Surprise! you clicked me. i was toast #' + toastIndex + '. You could perform an action here.');\n                    });\n                }\n\n                $('#clearlasttoast').click(function () {\n                    toastr.clear($toastlast);\n                });\n            });\n            $('#cleartoasts').click(function () {\n                toastr.clear();\n            });\n\n        }\n\n    };\n\n}();"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/manage/scripts/ui-tree.js",
    "content": "var UITree = function () {\n\n    return {\n        //main function to initiate the module\n        init: function () {\n\n            var DataSourceTree = function (options) {\n                this._data  = options.data;\n                this._delay = options.delay;\n            };\n\n            DataSourceTree.prototype = {\n\n                data: function (options, callback) {\n                    var self = this;\n\n                    setTimeout(function () {\n                        var data = $.extend(true, [], self._data);\n\n                        callback({ data: data });\n\n                    }, this._delay)\n                }\n            };\n            \n            // INITIALIZING TREE\n            var treeDataSource = new DataSourceTree({\n                data: [\n                    { name: 'Sales', type: 'folder', additionalParameters: { id: 'F1' } },\n                    { name: 'Projects', type: 'folder', additionalParameters: { id: 'F2' } },\n                    { name: 'Reports', type: 'item', additionalParameters: { id: 'I1' } },\n                    { name: 'Finance', type: 'item', additionalParameters: { id: 'I2' } }\n                ],\n                delay: 400\n            });\n\n            var treeDataSource2 = new DataSourceTree({\n                data: [\n                    { name: 'System Logs <div class=\"tree-actions\"></div>', type: 'folder', additionalParameters: { id: 'F11' } },\n                    { name: 'Notifications <div class=\"tree-actions\"></div>', type: 'folder', additionalParameters: { id: 'F12' } },\n                    { name: '<i class=\"fa fa-bell\"></i> Alerts', type: 'item', additionalParameters: { id: 'I11' } },\n                    { name: '<i class=\"fa fa-bar-chart-o\"></i> Tasks', type: 'item', additionalParameters: { id: 'I12' } }\n                ],\n                delay: 400\n            });\n\n            var treeDataSource3 = new DataSourceTree({\n                data: [\n                    { name: 'Resources <div class=\"tree-actions\"></div>', type: 'folder', additionalParameters: { id: 'F11' } },\n                    { name: 'Projects <div class=\"tree-actions\"></div>', type: 'folder', additionalParameters: { id: 'F12' } },\n                    { name: 'Nike Promo 2013', type: 'item', additionalParameters: { id: 'I11' } },\n                    { name: 'IPO Reports', type: 'item', additionalParameters: { id: 'I12' } }\n                ],\n                delay: 400\n            });\n\n            var treeDataSource4 = new DataSourceTree({\n                data: [\n                    { name: 'Projects<div class=\"tree-actions\"><i class=\"fa fa-plus\"></i><i class=\"fa fa-trash-o\"></i><i class=\"fa fa-refresh\"></i></div>', type: 'folder', additionalParameters: { id: 'F11' } },\n                    { name: 'Reports<div class=\"tree-actions\"><i class=\"fa fa-plus\"></i><i class=\"fa fa-trash-o\"></i><i class=\"fa fa-refresh\"></i></div>', type: 'folder', additionalParameters: { id: 'F12' } },\n                    { name: '<i class=\"fa fa-user\"></i> Member <div class=\"tree-actions\"><i class=\"fa fa-plus\"></i><i class=\"fa fa-trash-o\"></i><i class=\"fa fa-refresh\"></i></div><div class=\"tree-actions\"><i class=\"fa fa-plus\"></i><i class=\"fa fa-trash-o\"></i><i class=\"fa fa-refresh\"></i></div>', type: 'item', additionalParameters: { id: 'I11' } },\n                    { name: '<i class=\"fa fa-calendar\"></i> Events <div class=\"tree-actions\"><i class=\"fa fa-plus\"></i><i class=\"fa fa-trash-o\"></i><i class=\"fa fa-refresh\"></i></div>', type: 'item', additionalParameters: { id: 'I12' } },\n                    { name: '<i class=\"fa fa-suitcase\"></i> Portfolio <div class=\"tree-actions\"><i class=\"fa fa-plus\"></i><i class=\"fa fa-trash-o\"></i><i class=\"fa fa-refresh\"></i></div>', type: 'item', additionalParameters: { id: 'I12' } }\n                ],\n                delay: 400\n            });\n\n            var treeDataSource5 = new DataSourceTree({\n                data: [\n                    { name: 'Projects<div class=\"tree-actions\"><i class=\"fa fa-plus\"></i><i class=\"fa fa-trash-o\"></i><i class=\"fa fa-refresh\"></i></div>', type: 'folder', additionalParameters: { id: 'F11' } },\n                    { name: 'Reports<div class=\"tree-actions\"><i class=\"fa fa-plus\"></i><i class=\"fa fa-trash-o\"></i><i class=\"fa fa-refresh\"></i></div>', type: 'folder', additionalParameters: { id: 'F12' } },\n                    { name: '<i class=\"fa fa-user\"></i> Member <div class=\"tree-actions\"><i class=\"fa fa-plus\"></i><i class=\"fa fa-trash-o\"></i><i class=\"fa fa-refresh\"></i></div><div class=\"tree-actions\"><i class=\"fa fa-plus\"></i><i class=\"fa fa-trash-o\"></i><i class=\"fa fa-refresh\"></i></div>', type: 'item', additionalParameters: { id: 'I11' } },\n                    { name: '<i class=\"fa fa-calendar\"></i> Events <div class=\"tree-actions\"><i class=\"fa fa-plus\"></i><i class=\"fa fa-trash-o\"></i><i class=\"fa fa-refresh\"></i></div>', type: 'item', additionalParameters: { id: 'I12' } },\n                    { name: '<i class=\"fa fa-suitcase\"></i> Portfolio <div class=\"tree-actions\"><i class=\"fa fa-plus\"></i><i class=\"fa fa-trash-o\"></i><i class=\"fa fa-refresh\"></i></div>', type: 'item', additionalParameters: { id: 'I12' } }\n                ],\n                delay: 400\n            });  \n\n            var treeDataSource6 = new DataSourceTree({\n                data: [\n                    { name: 'Projects<div class=\"tree-actions\"><i class=\"fa fa-plus\"></i><i class=\"fa fa-trash-o\"></i><i class=\"fa fa-refresh\"></i></div>', type: 'folder', additionalParameters: { id: 'F11' } },\n                    { name: 'Reports<div class=\"tree-actions\"><i class=\"fa fa-plus\"></i><i class=\"fa fa-trash-o\"></i><i class=\"fa fa-refresh\"></i></div>', type: 'folder', additionalParameters: { id: 'F12' } },\n                    { name: '<i class=\"fa fa-user\"></i> Member <div class=\"tree-actions\"><i class=\"fa fa-plus\"></i><i class=\"fa fa-trash-o\"></i><i class=\"fa fa-refresh\"></i></div><div class=\"tree-actions\"><i class=\"fa fa-plus\"></i><i class=\"fa fa-trash-o\"></i><i class=\"fa fa-refresh\"></i></div>', type: 'item', additionalParameters: { id: 'I11' } },\n                    { name: '<i class=\"fa fa-calendar\"></i> Events <div class=\"tree-actions\"><i class=\"fa fa-plus\"></i><i class=\"fa fa-trash-o\"></i><i class=\"fa fa-refresh\"></i></div>', type: 'item', additionalParameters: { id: 'I12' } },\n                    { name: '<i class=\"fa fa-suitcase\"></i> Portfolio <div class=\"tree-actions\"><i class=\"fa fa-plus\"></i><i class=\"fa fa-trash-o\"></i><i class=\"fa fa-refresh\"></i></div>', type: 'item', additionalParameters: { id: 'I12' } }\n                ],\n                delay: 400\n            });    \n\n            $('#MyTree').tree({\n                dataSource: treeDataSource,\n                loadingHTML: '<img src=\"assets/img/input-spinner.gif\"/>',\n            });\n\n\n            $('#MyTree2').tree({\n                dataSource: treeDataSource2,\n                loadingHTML: '<img src=\"assets/img/input-spinner.gif\"/>',\n            });\n\n            $('#MyTree3').tree({\n                dataSource: treeDataSource3,\n                loadingHTML: '<img src=\"assets/img/input-spinner.gif\"/>',\n            });\n\n            $('#MyTree4').tree({\n                selectable: false,\n                dataSource: treeDataSource4,\n                loadingHTML: '<img src=\"assets/img/input-spinner.gif\"/>',\n            });\n\n            $('#MyTree5').tree({\n                selectable: false,\n                dataSource: treeDataSource5,\n                loadingHTML: '<img src=\"assets/img/input-spinner.gif\"/>',\n            });\n\n            $('#MyTree6').tree({\n                selectable: false,\n                dataSource: treeDataSource6,\n                loadingHTML: '<img src=\"assets/img/input-spinner.gif\"/>',\n            });\n        }\n\n    };\n\n}();"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/calendar-setup.js",
    "content": "/*  Copyright Mihai Bazon, 2002, 2003  |  http://dynarch.com/mishoo/\n * ---------------------------------------------------------------------------\n *\n * The DHTML Calendar\n *\n * Details and latest version at:\n * http://dynarch.com/mishoo/calendar.epl\n *\n * This script is distributed under the GNU Lesser General Public License.\n * Read the entire license text here: http://www.gnu.org/licenses/lgpl.html\n *\n * This file defines helper functions for setting up the calendar.  They are\n * intended to help non-programmers get a working calendar on their site\n * quickly.  This script should not be seen as part of the calendar.  It just\n * shows you what one can do with the calendar, while in the same time\n * providing a quick and simple method for setting it up.  If you need\n * exhaustive customization of the calendar creation process feel free to\n * modify this code to suit your needs (this is recommended and much better\n * than modifying calendar.js itself).\n */\n\n// $Id: calendar-setup.js,v 1.1 2008/12/10 10:39:35 fangying Exp $\n\n/**\n *  This function \"patches\" an input field (or other element) to use a calendar\n *  widget for date selection.\n *\n *  The \"params\" is a single object that can have the following properties:\n *\n *    prop. name   | description\n *  -------------------------------------------------------------------------------------------------\n *   inputField    | the ID of an input field to store the date\n *   displayArea   | the ID of a DIV or other element to show the date\n *   button        | ID of a button or other element that will trigger the calendar\n *   eventName     | event that will trigger the calendar, without the \"on\" prefix (default: \"click\")\n *   ifFormat      | date format that will be stored in the input field\n *   daFormat      | the date format that will be used to display the date in displayArea\n *   singleClick   | (true/false) wether the calendar is in single click mode or not (default: true)\n *   firstDay      | numeric: 0 to 6.  \"0\" means display Sunday first, \"1\" means display Monday first, etc.\n *   align         | alignment (default: \"Br\"); if you don't know what's this see the calendar documentation\n *   range         | array with 2 elements.  Default: [1900, 2999] -- the range of years available\n *   weekNumbers   | (true/false) if it's true (default) the calendar will display week numbers\n *   flat          | null or element ID; if not null the calendar will be a flat calendar having the parent with the given ID\n *   flatCallback  | function that receives a JS Date object and returns an URL to point the browser to (for flat calendar)\n *   disableFunc   | function that receives a JS Date object and should return true if that date has to be disabled in the calendar\n *   onSelect      | function that gets called when a date is selected.  You don't _have_ to supply this (the default is generally okay)\n *   onClose       | function that gets called when the calendar is closed.  [default]\n *   onUpdate      | function that gets called after the date is updated in the input field.  Receives a reference to the calendar.\n *   date          | the date that the calendar will be initially displayed to\n *   showsTime     | default: false; if true the calendar will include a time selector\n *   timeFormat    | the time format; can be \"12\" or \"24\", default is \"12\"\n *   electric      | if true (default) then given fields/date areas are updated for each move; otherwise they're updated only on close\n *   step          | configures the step of the years in drop-down boxes; default: 2\n *   position      | configures the calendar absolute position; default: null\n *   cache         | if \"true\" (but default: \"false\") it will reuse the same calendar object, where possible\n *   showOthers    | if \"true\" (but default: \"false\") it will show days from other months too\n *\n *  None of them is required, they all have default values.  However, if you\n *  pass none of \"inputField\", \"displayArea\" or \"button\" you'll get a warning\n *  saying \"nothing to setup\".\n */\nCalendar.setup = function (params) {\n\tfunction param_default(pname, def) { if (typeof params[pname] == \"undefined\") { params[pname] = def; } };\n\n\tparam_default(\"inputField\",     null);\n\tparam_default(\"displayArea\",    null);\n\tparam_default(\"button\",         null);\n\tparam_default(\"eventName\",      \"click\");\n\tparam_default(\"ifFormat\",       \"%Y/%m/%d\");\n\tparam_default(\"daFormat\",       \"%Y/%m/%d\");\n\tparam_default(\"singleClick\",    true);\n\tparam_default(\"disableFunc\",    null);\n\tparam_default(\"dateStatusFunc\", params[\"disableFunc\"]);\t// takes precedence if both are defined\n\tparam_default(\"dateText\",       null);\n\tparam_default(\"firstDay\",       null);\n\tparam_default(\"align\",          \"Br\");\n\tparam_default(\"range\",          [1900, 2999]);\n\tparam_default(\"weekNumbers\",    true);\n\tparam_default(\"flat\",           null);\n\tparam_default(\"flatCallback\",   null);\n\tparam_default(\"onSelect\",       null);\n\tparam_default(\"onClose\",        null);\n\tparam_default(\"onUpdate\",       null);\n\tparam_default(\"date\",           null);\n\tparam_default(\"showsTime\",      false);\n\tparam_default(\"timeFormat\",     \"24\");\n\tparam_default(\"electric\",       true);\n\tparam_default(\"step\",           2);\n\tparam_default(\"position\",       null);\n\tparam_default(\"cache\",          false);\n\tparam_default(\"showOthers\",     false);\n\tparam_default(\"multiple\",       null);\n\n\tvar tmp = [\"inputField\", \"displayArea\", \"button\"];\n\tfor (var i in tmp) {\n\t\tif (typeof params[tmp[i]] == \"string\") {\n\t\t\tparams[tmp[i]] = document.getElementById(params[tmp[i]]);\n\t\t}\n\t}\n\tif (!(params.flat || params.multiple || params.inputField || params.displayArea || params.button)) {\n\t\talert(\"Calendar.setup:\\n  Nothing to setup (no fields found).  Please check your code\");\n\t\treturn false;\n\t}\n\n\tfunction onSelect(cal) {\n\t\tvar p = cal.params;\n\t\tvar update = (cal.dateClicked || p.electric);\n\t\tif (update && p.inputField) {\n\t\t\tp.inputField.value = cal.date.print(p.ifFormat);\n\t\t\tif (typeof p.inputField.onchange == \"function\")\n\t\t\t\tp.inputField.onchange();\n\t\t}\n\t\tif (update && p.displayArea)\n\t\t\tp.displayArea.innerHTML = cal.date.print(p.daFormat);\n\t\tif (update && typeof p.onUpdate == \"function\")\n\t\t\tp.onUpdate(cal);\n\t\tif (update && p.flat) {\n\t\t\tif (typeof p.flatCallback == \"function\")\n\t\t\t\tp.flatCallback(cal);\n\t\t}\n\t\tif (update && p.singleClick && cal.dateClicked)\n\t\t\tcal.callCloseHandler();\n\t};\n\n\tif (params.flat != null) {\n\t\tif (typeof params.flat == \"string\")\n\t\t\tparams.flat = document.getElementById(params.flat);\n\t\tif (!params.flat) {\n\t\t\talert(\"Calendar.setup:\\n  Flat specified but can't find parent.\");\n\t\t\treturn false;\n\t\t}\n\t\tvar cal = new Calendar(params.firstDay, params.date, params.onSelect || onSelect);\n\t\tcal.showsOtherMonths = params.showOthers;\n\t\tcal.showsTime = params.showsTime;\n\t\tcal.time24 = (params.timeFormat == \"24\");\n\t\tcal.params = params;\n\t\tcal.weekNumbers = params.weekNumbers;\n\t\tcal.setRange(params.range[0], params.range[1]);\n\t\tcal.setDateStatusHandler(params.dateStatusFunc);\n\t\tcal.getDateText = params.dateText;\n\t\tif (params.ifFormat) {\n\t\t\tcal.setDateFormat(params.ifFormat);\n\t\t}\n\t\tif (params.inputField && typeof params.inputField.value == \"string\") {\n\t\t\tcal.parseDate(params.inputField.value);\n\t\t}\n\t\tcal.create(params.flat);\n\t\tcal.show();\n\t\treturn false;\n\t}\n\n\tvar triggerEl = params.button || params.displayArea || params.inputField;\n\ttriggerEl[\"on\" + params.eventName] = function() {\n\t\tvar dateEl = params.inputField || params.displayArea;\n\t\tvar dateFmt = params.inputField ? params.ifFormat : params.daFormat;\n\t\tvar mustCreate = false;\n\t\tvar cal = window.calendar;\n\t\tif (dateEl)\n\t\t\tparams.date = Date.parseDate(dateEl.value || dateEl.innerHTML, dateFmt);\n\t\tif (!(cal && params.cache)) {\n\t\t\twindow.calendar = cal = new Calendar(params.firstDay,\n\t\t\t\t\t\t\t     params.date,\n\t\t\t\t\t\t\t     params.onSelect || onSelect,\n\t\t\t\t\t\t\t     params.onClose || function(cal) { cal.hide(); });\n\t\t\tcal.showsTime = params.showsTime;\n\t\t\tcal.time24 = (params.timeFormat == \"24\");\n\t\t\tcal.weekNumbers = params.weekNumbers;\n\t\t\tmustCreate = true;\n\t\t} else {\n\t\t\tif (params.date)\n\t\t\t\tcal.setDate(params.date);\n\t\t\tcal.hide();\n\t\t}\n\t\tif (params.multiple) {\n\t\t\tcal.multiple = {};\n\t\t\tfor (var i = params.multiple.length; --i >= 0;) {\n\t\t\t\tvar d = params.multiple[i];\n\t\t\t\tvar ds = d.print(\"%Y%m%d\");\n\t\t\t\tcal.multiple[ds] = d;\n\t\t\t}\n\t\t}\n\t\tcal.showsOtherMonths = params.showOthers;\n\t\tcal.yearStep = params.step;\n\t\tcal.setRange(params.range[0], params.range[1]);\n\t\tcal.params = params;\n\t\tcal.setDateStatusHandler(params.dateStatusFunc);\n\t\tcal.getDateText = params.dateText;\n\t\tcal.setDateFormat(dateFmt);\n\t\tif (mustCreate)\n\t\t\tcal.create();\n\t\tcal.refresh();\n\t\tif (!params.position)\n\t\t\tcal.showAtElement(params.button || params.displayArea || params.inputField, params.align);\n\t\telse\n\t\t\tcal.showAt(params.position[0], params.position[1]);\n\t\treturn false;\n\t};\n\n\treturn cal;\n};\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/calendar-setup_stripped.js",
    "content": "/*  Copyright Mihai Bazon, 2002, 2003  |  http://dynarch.com/mishoo/\n * ---------------------------------------------------------------------------\n *\n * The DHTML Calendar\n *\n * Details and latest version at:\n * http://dynarch.com/mishoo/calendar.epl\n *\n * This script is distributed under the GNU Lesser General Public License.\n * Read the entire license text here: http://www.gnu.org/licenses/lgpl.html\n *\n * This file defines helper functions for setting up the calendar.  They are\n * intended to help non-programmers get a working calendar on their site\n * quickly.  This script should not be seen as part of the calendar.  It just\n * shows you what one can do with the calendar, while in the same time\n * providing a quick and simple method for setting it up.  If you need\n * exhaustive customization of the calendar creation process feel free to\n * modify this code to suit your needs (this is recommended and much better\n * than modifying calendar.js itself).\n */\n Calendar.setup=function(params){function param_default(pname,def){if(typeof params[pname]==\"undefined\"){params[pname]=def;}};param_default(\"inputField\",null);param_default(\"displayArea\",null);param_default(\"button\",null);param_default(\"eventName\",\"click\");param_default(\"ifFormat\",\"%Y/%m/%d\");param_default(\"daFormat\",\"%Y/%m/%d\");param_default(\"singleClick\",true);param_default(\"disableFunc\",null);param_default(\"dateStatusFunc\",params[\"disableFunc\"]);param_default(\"dateText\",null);param_default(\"firstDay\",null);param_default(\"align\",\"Br\");param_default(\"range\",[1900,2999]);param_default(\"weekNumbers\",true);param_default(\"flat\",null);param_default(\"flatCallback\",null);param_default(\"onSelect\",null);param_default(\"onClose\",null);param_default(\"onUpdate\",null);param_default(\"date\",null);param_default(\"showsTime\",false);param_default(\"timeFormat\",\"24\");param_default(\"electric\",true);param_default(\"step\",2);param_default(\"position\",null);param_default(\"cache\",false);param_default(\"showOthers\",false);param_default(\"multiple\",null);var tmp=[\"inputField\",\"displayArea\",\"button\"];for(var i in tmp){if(typeof params[tmp[i]]==\"string\"){params[tmp[i]]=document.getElementById(params[tmp[i]]);}}if(!(params.flat||params.multiple||params.inputField||params.displayArea||params.button)){alert(\"Calendar.setup:\\n  Nothing to setup (no fields found).  Please check your code\");return false;}function onSelect(cal){var p=cal.params;var update=(cal.dateClicked||p.electric);if(update&&p.inputField){p.inputField.value=cal.date.print(p.ifFormat);if(typeof p.inputField.onchange==\"function\")p.inputField.onchange();}if(update&&p.displayArea)p.displayArea.innerHTML=cal.date.print(p.daFormat);if(update&&typeof p.onUpdate==\"function\")p.onUpdate(cal);if(update&&p.flat){if(typeof p.flatCallback==\"function\")p.flatCallback(cal);}if(update&&p.singleClick&&cal.dateClicked)cal.callCloseHandler();};if(params.flat!=null){if(typeof params.flat==\"string\")params.flat=document.getElementById(params.flat);if(!params.flat){alert(\"Calendar.setup:\\n  Flat specified but can't find parent.\");return false;}var cal=new Calendar(params.firstDay,params.date,params.onSelect||onSelect);cal.showsOtherMonths=params.showOthers;cal.showsTime=params.showsTime;cal.time24=(params.timeFormat==\"24\");cal.params=params;cal.weekNumbers=params.weekNumbers;cal.setRange(params.range[0],params.range[1]);cal.setDateStatusHandler(params.dateStatusFunc);cal.getDateText=params.dateText;if(params.ifFormat){cal.setDateFormat(params.ifFormat);}if(params.inputField&&typeof params.inputField.value==\"string\"){cal.parseDate(params.inputField.value);}cal.create(params.flat);cal.show();return false;}var triggerEl=params.button||params.displayArea||params.inputField;triggerEl[\"on\"+params.eventName]=function(){var dateEl=params.inputField||params.displayArea;var dateFmt=params.inputField?params.ifFormat:params.daFormat;var mustCreate=false;var cal=window.calendar;if(dateEl)params.date=Date.parseDate(dateEl.value||dateEl.innerHTML,dateFmt);if(!(cal&&params.cache)){window.calendar=cal=new Calendar(params.firstDay,params.date,params.onSelect||onSelect,params.onClose||function(cal){cal.hide();});cal.showsTime=params.showsTime;cal.time24=(params.timeFormat==\"24\");cal.weekNumbers=params.weekNumbers;mustCreate=true;}else{if(params.date)cal.setDate(params.date);cal.hide();}if(params.multiple){cal.multiple={};for(var i=params.multiple.length;--i>=0;){var d=params.multiple[i];var ds=d.print(\"%Y%m%d\");cal.multiple[ds]=d;}}cal.showsOtherMonths=params.showOthers;cal.yearStep=params.step;cal.setRange(params.range[0],params.range[1]);cal.params=params;cal.setDateStatusHandler(params.dateStatusFunc);cal.getDateText=params.dateText;cal.setDateFormat(dateFmt);if(mustCreate)cal.create();cal.refresh();if(!params.position)cal.showAtElement(params.button||params.displayArea||params.inputField,params.align);else cal.showAt(params.position[0],params.position[1]);return false;};return cal;};"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/calendar.js",
    "content": "/*  Copyright Mihai Bazon, 2002-2005  |  www.bazon.net/mishoo\n * -----------------------------------------------------------\n *\n * The DHTML Calendar, version 1.0 \"It is happening again\"\n *\n * Details and latest version at:\n * www.dynarch.com/projects/calendar\n *\n * This script is developed by Dynarch.com.  Visit us at www.dynarch.com.\n *\n * This script is distributed under the GNU Lesser General Public License.\n * Read the entire license text here: http://www.gnu.org/licenses/lgpl.html\n */\n\n// $Id: calendar.js,v 1.1 2008/12/10 10:39:35 fangying Exp $\n\n/** The Calendar object constructor. */\nCalendar = function (firstDayOfWeek, dateStr, onSelected, onClose) {\n\t// member variables\n\tthis.activeDiv = null;\n\tthis.currentDateEl = null;\n\tthis.getDateStatus = null;\n\tthis.getDateToolTip = null;\n\tthis.getDateText = null;\n\tthis.timeout = null;\n\tthis.onSelected = onSelected || null;\n\tthis.onClose = onClose || null;\n\tthis.dragging = false;\n\tthis.hidden = false;\n\tthis.minYear = 1970;\n\tthis.maxYear = 2050;\n\tthis.dateFormat = Calendar._TT[\"DEF_DATE_FORMAT\"];\n\tthis.ttDateFormat = Calendar._TT[\"TT_DATE_FORMAT\"];\n\tthis.isPopup = true;\n\tthis.weekNumbers = true;\n\tthis.firstDayOfWeek = typeof firstDayOfWeek == \"number\" ? firstDayOfWeek : Calendar._FD; // 0 for Sunday, 1 for Monday, etc.\n\tthis.showsOtherMonths = false;\n\tthis.dateStr = dateStr;\n\tthis.ar_days = null;\n\tthis.showsTime = false;\n\tthis.time24 = true;\n\tthis.yearStep = 2;\n\tthis.hiliteToday = true;\n\tthis.multiple = null;\n\t// HTML elements\n\tthis.table = null;\n\tthis.element = null;\n\tthis.tbody = null;\n\tthis.firstdayname = null;\n\t// Combo boxes\n\tthis.monthsCombo = null;\n\tthis.yearsCombo = null;\n\tthis.hilitedMonth = null;\n\tthis.activeMonth = null;\n\tthis.hilitedYear = null;\n\tthis.activeYear = null;\n\t// Information\n\tthis.dateClicked = false;\n\n\t// one-time initializations\n\tif (typeof Calendar._SDN == \"undefined\") {\n\t\t// table of short day names\n\t\tif (typeof Calendar._SDN_len == \"undefined\")\n\t\t\tCalendar._SDN_len = 3;\n\t\tvar ar = new Array();\n\t\tfor (var i = 8; i > 0;) {\n\t\t\tar[--i] = Calendar._DN[i].substr(0, Calendar._SDN_len);\n\t\t}\n\t\tCalendar._SDN = ar;\n\t\t// table of short month names\n\t\tif (typeof Calendar._SMN_len == \"undefined\")\n\t\t\tCalendar._SMN_len = 3;\n\t\tar = new Array();\n\t\tfor (var i = 12; i > 0;) {\n\t\t\tar[--i] = Calendar._MN[i].substr(0, Calendar._SMN_len);\n\t\t}\n\t\tCalendar._SMN = ar;\n\t}\n};\n\n// ** constants\n\n/// \"static\", needed for event handlers.\nCalendar._C = null;\n\n/// detect a special case of \"web browser\"\nCalendar.is_ie = ( /msie/i.test(navigator.userAgent) &&\n\t\t   !/opera/i.test(navigator.userAgent) );\n\nCalendar.is_ie5 = ( Calendar.is_ie && /msie 5\\.0/i.test(navigator.userAgent) );\n\n/// detect Opera browser\nCalendar.is_opera = /opera/i.test(navigator.userAgent);\n\n/// detect KHTML-based browsers\nCalendar.is_khtml = /Konqueror|Safari|KHTML/i.test(navigator.userAgent);\n\n// BEGIN: UTILITY FUNCTIONS; beware that these might be moved into a separate\n//        library, at some point.\n\nCalendar.getAbsolutePos = function(el) {\n\tvar SL = 0, ST = 0;\n\tvar is_div = /^div$/i.test(el.tagName);\n\tif (is_div && el.scrollLeft)\n\t\tSL = el.scrollLeft;\n\tif (is_div && el.scrollTop)\n\t\tST = el.scrollTop;\n\tvar r = { x: el.offsetLeft - SL, y: el.offsetTop - ST };\n\tif (el.offsetParent) {\n\t\tvar tmp = this.getAbsolutePos(el.offsetParent);\n\t\tr.x += tmp.x;\n\t\tr.y += tmp.y;\n\t}\n\treturn r;\n};\n\nCalendar.isRelated = function (el, evt) {\n\tvar related = evt.relatedTarget;\n\tif (!related) {\n\t\tvar type = evt.type;\n\t\tif (type == \"mouseover\") {\n\t\t\trelated = evt.fromElement;\n\t\t} else if (type == \"mouseout\") {\n\t\t\trelated = evt.toElement;\n\t\t}\n\t}\n\twhile (related) {\n\t\tif (related == el) {\n\t\t\treturn true;\n\t\t}\n\t\trelated = related.parentNode;\n\t}\n\treturn false;\n};\n\nCalendar.removeClass = function(el, className) {\n\tif (!(el && el.className)) {\n\t\treturn;\n\t}\n\tvar cls = el.className.split(\" \");\n\tvar ar = new Array();\n\tfor (var i = cls.length; i > 0;) {\n\t\tif (cls[--i] != className) {\n\t\t\tar[ar.length] = cls[i];\n\t\t}\n\t}\n\tel.className = ar.join(\" \");\n};\n\nCalendar.addClass = function(el, className) {\n\tCalendar.removeClass(el, className);\n\tel.className += \" \" + className;\n};\n\n// FIXME: the following 2 functions totally suck, are useless and should be replaced immediately.\nCalendar.getElement = function(ev) {\n\tvar f = Calendar.is_ie ? window.event.srcElement : ev.currentTarget;\n\twhile (f.nodeType != 1 || /^div$/i.test(f.tagName))\n\t\tf = f.parentNode;\n\treturn f;\n};\n\nCalendar.getTargetElement = function(ev) {\n\tvar f = Calendar.is_ie ? window.event.srcElement : ev.target;\n\twhile (f.nodeType != 1)\n\t\tf = f.parentNode;\n\treturn f;\n};\n\nCalendar.stopEvent = function(ev) {\n\tev || (ev = window.event);\n\tif (Calendar.is_ie) {\n\t\tev.cancelBubble = true;\n\t\tev.returnValue = false;\n\t} else {\n\t\tev.preventDefault();\n\t\tev.stopPropagation();\n\t}\n\treturn false;\n};\n\nCalendar.addEvent = function(el, evname, func) {\n\tif (el.attachEvent) { // IE\n\t\tel.attachEvent(\"on\" + evname, func);\n\t} else if (el.addEventListener) { // Gecko / W3C\n\t\tel.addEventListener(evname, func, true);\n\t} else {\n\t\tel[\"on\" + evname] = func;\n\t}\n};\n\nCalendar.removeEvent = function(el, evname, func) {\n\tif (el.detachEvent) { // IE\n\t\tel.detachEvent(\"on\" + evname, func);\n\t} else if (el.removeEventListener) { // Gecko / W3C\n\t\tel.removeEventListener(evname, func, true);\n\t} else {\n\t\tel[\"on\" + evname] = null;\n\t}\n};\n\nCalendar.createElement = function(type, parent) {\n\tvar el = null;\n\tif (document.createElementNS) {\n\t\t// use the XHTML namespace; IE won't normally get here unless\n\t\t// _they_ \"fix\" the DOM2 implementation.\n\t\tel = document.createElementNS(\"http://www.w3.org/1999/xhtml\", type);\n\t} else {\n\t\tel = document.createElement(type);\n\t}\n\tif (typeof parent != \"undefined\") {\n\t\tparent.appendChild(el);\n\t}\n\treturn el;\n};\n\n// END: UTILITY FUNCTIONS\n\n// BEGIN: CALENDAR STATIC FUNCTIONS\n\n/** Internal -- adds a set of events to make some element behave like a button. */\nCalendar._add_evs = function(el) {\n\twith (Calendar) {\n\t\taddEvent(el, \"mouseover\", dayMouseOver);\n\t\taddEvent(el, \"mousedown\", dayMouseDown);\n\t\taddEvent(el, \"mouseout\", dayMouseOut);\n\t\tif (is_ie) {\n\t\t\taddEvent(el, \"dblclick\", dayMouseDblClick);\n\t\t\tel.setAttribute(\"unselectable\", true);\n\t\t}\n\t}\n};\n\nCalendar.findMonth = function(el) {\n\tif (typeof el.month != \"undefined\") {\n\t\treturn el;\n\t} else if (typeof el.parentNode.month != \"undefined\") {\n\t\treturn el.parentNode;\n\t}\n\treturn null;\n};\n\nCalendar.findYear = function(el) {\n\tif (typeof el.year != \"undefined\") {\n\t\treturn el;\n\t} else if (typeof el.parentNode.year != \"undefined\") {\n\t\treturn el.parentNode;\n\t}\n\treturn null;\n};\n\nCalendar.showMonthsCombo = function () {\n\tvar cal = Calendar._C;\n\tif (!cal) {\n\t\treturn false;\n\t}\n\tvar cal = cal;\n\tvar cd = cal.activeDiv;\n\tvar mc = cal.monthsCombo;\n\tif (cal.hilitedMonth) {\n\t\tCalendar.removeClass(cal.hilitedMonth, \"hilite\");\n\t}\n\tif (cal.activeMonth) {\n\t\tCalendar.removeClass(cal.activeMonth, \"active\");\n\t}\n\tvar mon = cal.monthsCombo.getElementsByTagName(\"div\")[cal.date.getMonth()];\n\tCalendar.addClass(mon, \"active\");\n\tcal.activeMonth = mon;\n\tvar s = mc.style;\n\ts.display = \"block\";\n\tif (cd.navtype < 0)\n\t\ts.left = cd.offsetLeft + \"px\";\n\telse {\n\t\tvar mcw = mc.offsetWidth;\n\t\tif (typeof mcw == \"undefined\")\n\t\t\t// Konqueror brain-dead techniques\n\t\t\tmcw = 50;\n\t\ts.left = (cd.offsetLeft + cd.offsetWidth - mcw) + \"px\";\n\t}\n\ts.top = (cd.offsetTop + cd.offsetHeight) + \"px\";\n};\n\nCalendar.showYearsCombo = function (fwd) {\n\tvar cal = Calendar._C;\n\tif (!cal) {\n\t\treturn false;\n\t}\n\tvar cal = cal;\n\tvar cd = cal.activeDiv;\n\tvar yc = cal.yearsCombo;\n\tif (cal.hilitedYear) {\n\t\tCalendar.removeClass(cal.hilitedYear, \"hilite\");\n\t}\n\tif (cal.activeYear) {\n\t\tCalendar.removeClass(cal.activeYear, \"active\");\n\t}\n\tcal.activeYear = null;\n\tvar Y = cal.date.getFullYear() + (fwd ? 1 : -1);\n\tvar yr = yc.firstChild;\n\tvar show = false;\n\tfor (var i = 12; i > 0; --i) {\n\t\tif (Y >= cal.minYear && Y <= cal.maxYear) {\n\t\t\tyr.innerHTML = Y;\n\t\t\tyr.year = Y;\n\t\t\tyr.style.display = \"block\";\n\t\t\tshow = true;\n\t\t} else {\n\t\t\tyr.style.display = \"none\";\n\t\t}\n\t\tyr = yr.nextSibling;\n\t\tY += fwd ? cal.yearStep : -cal.yearStep;\n\t}\n\tif (show) {\n\t\tvar s = yc.style;\n\t\ts.display = \"block\";\n\t\tif (cd.navtype < 0)\n\t\t\ts.left = cd.offsetLeft + \"px\";\n\t\telse {\n\t\t\tvar ycw = yc.offsetWidth;\n\t\t\tif (typeof ycw == \"undefined\")\n\t\t\t\t// Konqueror brain-dead techniques\n\t\t\t\tycw = 50;\n\t\t\ts.left = (cd.offsetLeft + cd.offsetWidth - ycw) + \"px\";\n\t\t}\n\t\ts.top = (cd.offsetTop + cd.offsetHeight) + \"px\";\n\t}\n};\n\n// event handlers\n\nCalendar.tableMouseUp = function(ev) {\n\tvar cal = Calendar._C;\n\tif (!cal) {\n\t\treturn false;\n\t}\n\tif (cal.timeout) {\n\t\tclearTimeout(cal.timeout);\n\t}\n\tvar el = cal.activeDiv;\n\tif (!el) {\n\t\treturn false;\n\t}\n\tvar target = Calendar.getTargetElement(ev);\n\tev || (ev = window.event);\n\tCalendar.removeClass(el, \"active\");\n\tif (target == el || target.parentNode == el) {\n\t\tCalendar.cellClick(el, ev);\n\t}\n\tvar mon = Calendar.findMonth(target);\n\tvar date = null;\n\tif (mon) {\n\t\tdate = new Date(cal.date);\n\t\tif (mon.month != date.getMonth()) {\n\t\t\tdate.setMonth(mon.month);\n\t\t\tcal.setDate(date);\n\t\t\tcal.dateClicked = false;\n\t\t\tcal.callHandler();\n\t\t}\n\t} else {\n\t\tvar year = Calendar.findYear(target);\n\t\tif (year) {\n\t\t\tdate = new Date(cal.date);\n\t\t\tif (year.year != date.getFullYear()) {\n\t\t\t\tdate.setFullYear(year.year);\n\t\t\t\tcal.setDate(date);\n\t\t\t\tcal.dateClicked = false;\n\t\t\t\tcal.callHandler();\n\t\t\t}\n\t\t}\n\t}\n\twith (Calendar) {\n\t\tremoveEvent(document, \"mouseup\", tableMouseUp);\n\t\tremoveEvent(document, \"mouseover\", tableMouseOver);\n\t\tremoveEvent(document, \"mousemove\", tableMouseOver);\n\t\tcal._hideCombos();\n\t\t_C = null;\n\t\treturn stopEvent(ev);\n\t}\n};\n\nCalendar.tableMouseOver = function (ev) {\n\tvar cal = Calendar._C;\n\tif (!cal) {\n\t\treturn;\n\t}\n\tvar el = cal.activeDiv;\n\tvar target = Calendar.getTargetElement(ev);\n\tif (target == el || target.parentNode == el) {\n\t\tCalendar.addClass(el, \"hilite active\");\n\t\tCalendar.addClass(el.parentNode, \"rowhilite\");\n\t} else {\n\t\tif (typeof el.navtype == \"undefined\" || (el.navtype != 50 && (el.navtype == 0 || Math.abs(el.navtype) > 2)))\n\t\t\tCalendar.removeClass(el, \"active\");\n\t\tCalendar.removeClass(el, \"hilite\");\n\t\tCalendar.removeClass(el.parentNode, \"rowhilite\");\n\t}\n\tev || (ev = window.event);\n\tif (el.navtype == 50 && target != el) {\n\t\tvar pos = Calendar.getAbsolutePos(el);\n\t\tvar w = el.offsetWidth;\n\t\tvar x = ev.clientX;\n\t\tvar dx;\n\t\tvar decrease = true;\n\t\tif (x > pos.x + w) {\n\t\t\tdx = x - pos.x - w;\n\t\t\tdecrease = false;\n\t\t} else\n\t\t\tdx = pos.x - x;\n\n\t\tif (dx < 0) dx = 0;\n\t\tvar range = el._range;\n\t\tvar current = el._current;\n\t\tvar count = Math.floor(dx / 10) % range.length;\n\t\tfor (var i = range.length; --i >= 0;)\n\t\t\tif (range[i] == current)\n\t\t\t\tbreak;\n\t\twhile (count-- > 0)\n\t\t\tif (decrease) {\n\t\t\t\tif (--i < 0)\n\t\t\t\t\ti = range.length - 1;\n\t\t\t} else if ( ++i >= range.length )\n\t\t\t\ti = 0;\n\t\tvar newval = range[i];\n\t\tel.innerHTML = newval;\n\n\t\tcal.onUpdateTime();\n\t}\n\tvar mon = Calendar.findMonth(target);\n\tif (mon) {\n\t\tif (mon.month != cal.date.getMonth()) {\n\t\t\tif (cal.hilitedMonth) {\n\t\t\t\tCalendar.removeClass(cal.hilitedMonth, \"hilite\");\n\t\t\t}\n\t\t\tCalendar.addClass(mon, \"hilite\");\n\t\t\tcal.hilitedMonth = mon;\n\t\t} else if (cal.hilitedMonth) {\n\t\t\tCalendar.removeClass(cal.hilitedMonth, \"hilite\");\n\t\t}\n\t} else {\n\t\tif (cal.hilitedMonth) {\n\t\t\tCalendar.removeClass(cal.hilitedMonth, \"hilite\");\n\t\t}\n\t\tvar year = Calendar.findYear(target);\n\t\tif (year) {\n\t\t\tif (year.year != cal.date.getFullYear()) {\n\t\t\t\tif (cal.hilitedYear) {\n\t\t\t\t\tCalendar.removeClass(cal.hilitedYear, \"hilite\");\n\t\t\t\t}\n\t\t\t\tCalendar.addClass(year, \"hilite\");\n\t\t\t\tcal.hilitedYear = year;\n\t\t\t} else if (cal.hilitedYear) {\n\t\t\t\tCalendar.removeClass(cal.hilitedYear, \"hilite\");\n\t\t\t}\n\t\t} else if (cal.hilitedYear) {\n\t\t\tCalendar.removeClass(cal.hilitedYear, \"hilite\");\n\t\t}\n\t}\n\treturn Calendar.stopEvent(ev);\n};\n\nCalendar.tableMouseDown = function (ev) {\n\tif (Calendar.getTargetElement(ev) == Calendar.getElement(ev)) {\n\t\treturn Calendar.stopEvent(ev);\n\t}\n};\n\nCalendar.calDragIt = function (ev) {\n\tvar cal = Calendar._C;\n\tif (!(cal && cal.dragging)) {\n\t\treturn false;\n\t}\n\tvar posX;\n\tvar posY;\n\tif (Calendar.is_ie) {\n\t\tposY = window.event.clientY + document.body.scrollTop;\n\t\tposX = window.event.clientX + document.body.scrollLeft;\n\t} else {\n\t\tposX = ev.pageX;\n\t\tposY = ev.pageY;\n\t}\n\tcal.hideShowCovered();\n\tvar st = cal.element.style;\n\tst.left = (posX - cal.xOffs) + \"px\";\n\tst.top = (posY - cal.yOffs) + \"px\";\n\treturn Calendar.stopEvent(ev);\n};\n\nCalendar.calDragEnd = function (ev) {\n\tvar cal = Calendar._C;\n\tif (!cal) {\n\t\treturn false;\n\t}\n\tcal.dragging = false;\n\twith (Calendar) {\n\t\tremoveEvent(document, \"mousemove\", calDragIt);\n\t\tremoveEvent(document, \"mouseup\", calDragEnd);\n\t\ttableMouseUp(ev);\n\t}\n\tcal.hideShowCovered();\n};\n\nCalendar.dayMouseDown = function(ev) {\n\tvar el = Calendar.getElement(ev);\n\tif (el.disabled) {\n\t\treturn false;\n\t}\n\tvar cal = el.calendar;\n\tcal.activeDiv = el;\n\tCalendar._C = cal;\n\tif (el.navtype != 300) with (Calendar) {\n\t\tif (el.navtype == 50) {\n\t\t\tel._current = el.innerHTML;\n\t\t\taddEvent(document, \"mousemove\", tableMouseOver);\n\t\t} else\n\t\t\taddEvent(document, Calendar.is_ie5 ? \"mousemove\" : \"mouseover\", tableMouseOver);\n\t\taddClass(el, \"hilite active\");\n\t\taddEvent(document, \"mouseup\", tableMouseUp);\n\t} else if (cal.isPopup) {\n\t\tcal._dragStart(ev);\n\t}\n\tif (el.navtype == -1 || el.navtype == 1) {\n\t\tif (cal.timeout) clearTimeout(cal.timeout);\n\t\tcal.timeout = setTimeout(\"Calendar.showMonthsCombo()\", 250);\n\t} else if (el.navtype == -2 || el.navtype == 2) {\n\t\tif (cal.timeout) clearTimeout(cal.timeout);\n\t\tcal.timeout = setTimeout((el.navtype > 0) ? \"Calendar.showYearsCombo(true)\" : \"Calendar.showYearsCombo(false)\", 250);\n\t} else {\n\t\tcal.timeout = null;\n\t}\n\treturn Calendar.stopEvent(ev);\n};\n\nCalendar.dayMouseDblClick = function(ev) {\n\tCalendar.cellClick(Calendar.getElement(ev), ev || window.event);\n\tif (Calendar.is_ie) {\n\t\tdocument.selection.empty();\n\t}\n};\n\nCalendar.dayMouseOver = function(ev) {\n\tvar el = Calendar.getElement(ev);\n\tif (Calendar.isRelated(el, ev) || Calendar._C || el.disabled) {\n\t\treturn false;\n\t}\n\tif (el.ttip) {\n\t\tif (el.ttip.substr(0, 1) == \"_\") {\n\t\t\tel.ttip = el.caldate.print(el.calendar.ttDateFormat) + el.ttip.substr(1);\n\t\t}\n\t\tel.calendar.tooltips.innerHTML = el.ttip;\n\t}\n\tif (el.navtype != 300) {\n\t\tCalendar.addClass(el, \"hilite\");\n\t\tif (el.caldate) {\n\t\t\tCalendar.addClass(el.parentNode, \"rowhilite\");\n\t\t}\n\t}\n\treturn Calendar.stopEvent(ev);\n};\n\nCalendar.dayMouseOut = function(ev) {\n\twith (Calendar) {\n\t\tvar el = getElement(ev);\n\t\tif (isRelated(el, ev) || _C || el.disabled)\n\t\t\treturn false;\n\t\tremoveClass(el, \"hilite\");\n\t\tif (el.caldate)\n\t\t\tremoveClass(el.parentNode, \"rowhilite\");\n\t\tif (el.calendar)\n\t\t\tel.calendar.tooltips.innerHTML = _TT[\"SEL_DATE\"];\n\t\treturn stopEvent(ev);\n\t}\n};\n\n/**\n *  A generic \"click\" handler :) handles all types of buttons defined in this\n *  calendar.\n */\nCalendar.cellClick = function(el, ev) {\n\tvar cal = el.calendar;\n\tvar closing = false;\n\tvar newdate = false;\n\tvar date = null;\n\tif (typeof el.navtype == \"undefined\") {\n\t\tif (cal.currentDateEl) {\n\t\t\tCalendar.removeClass(cal.currentDateEl, \"selected\");\n\t\t\tCalendar.addClass(el, \"selected\");\n\t\t\tclosing = (cal.currentDateEl == el);\n\t\t\tif (!closing) {\n\t\t\t\tcal.currentDateEl = el;\n\t\t\t}\n\t\t}\n\t\tcal.date.setDateOnly(el.caldate);\n\t\tdate = cal.date;\n\t\tvar other_month = !(cal.dateClicked = !el.otherMonth);\n\t\tif (!other_month && !cal.currentDateEl)\n\t\t\tcal._toggleMultipleDate(new Date(date));\n\t\telse\n\t\t\tnewdate = !el.disabled;\n\t\t// a date was clicked\n\t\tif (other_month)\n\t\t\tcal._init(cal.firstDayOfWeek, date);\n\t} else {\n\t\tif (el.navtype == 200) {\n\t\t\tCalendar.removeClass(el, \"hilite\");\n\t\t\tcal.callCloseHandler();\n\t\t\treturn;\n\t\t}\n\t\tdate = new Date(cal.date);\n\t\tif (el.navtype == 0)\n\t\t\tdate.setDateOnly(new Date()); // TODAY\n\t\t// unless \"today\" was clicked, we assume no date was clicked so\n\t\t// the selected handler will know not to close the calenar when\n\t\t// in single-click mode.\n\t\t// cal.dateClicked = (el.navtype == 0);\n\t\tcal.dateClicked = false;\n\t\tvar year = date.getFullYear();\n\t\tvar mon = date.getMonth();\n\t\tfunction setMonth(m) {\n\t\t\tvar day = date.getDate();\n\t\t\tvar max = date.getMonthDays(m);\n\t\t\tif (day > max) {\n\t\t\t\tdate.setDate(max);\n\t\t\t}\n\t\t\tdate.setMonth(m);\n\t\t};\n\t\tswitch (el.navtype) {\n\t\t    case 400:\n\t\t\tCalendar.removeClass(el, \"hilite\");\n\t\t\tvar text = Calendar._TT[\"ABOUT\"];\n\t\t\tif (typeof text != \"undefined\") {\n\t\t\t\ttext += cal.showsTime ? Calendar._TT[\"ABOUT_TIME\"] : \"\";\n\t\t\t} else {\n\t\t\t\t// FIXME: this should be removed as soon as lang files get updated!\n\t\t\t\ttext = \"Help and about box text is not translated into this language.\\n\" +\n\t\t\t\t\t\"If you know this language and you feel generous please update\\n\" +\n\t\t\t\t\t\"the corresponding file in \\\"lang\\\" subdir to match calendar-en.js\\n\" +\n\t\t\t\t\t\"and send it back to <mihai_bazon@yahoo.com> to get it into the distribution  ;-)\\n\\n\" +\n\t\t\t\t\t\"Thank you!\\n\" +\n\t\t\t\t\t\"http://dynarch.com/mishoo/calendar.epl\\n\";\n\t\t\t}\n\t\t\talert(text);\n\t\t\treturn;\n\t\t    case -2:\n\t\t\tif (year > cal.minYear) {\n\t\t\t\tdate.setFullYear(year - 1);\n\t\t\t}\n\t\t\tbreak;\n\t\t    case -1:\n\t\t\tif (mon > 0) {\n\t\t\t\tsetMonth(mon - 1);\n\t\t\t} else if (year-- > cal.minYear) {\n\t\t\t\tdate.setFullYear(year);\n\t\t\t\tsetMonth(11);\n\t\t\t}\n\t\t\tbreak;\n\t\t    case 1:\n\t\t\tif (mon < 11) {\n\t\t\t\tsetMonth(mon + 1);\n\t\t\t} else if (year < cal.maxYear) {\n\t\t\t\tdate.setFullYear(year + 1);\n\t\t\t\tsetMonth(0);\n\t\t\t}\n\t\t\tbreak;\n\t\t    case 2:\n\t\t\tif (year < cal.maxYear) {\n\t\t\t\tdate.setFullYear(year + 1);\n\t\t\t}\n\t\t\tbreak;\n\t\t    case 100:\n\t\t\tcal.setFirstDayOfWeek(el.fdow);\n\t\t\treturn;\n\t\t    case 50:\n\t\t\tvar range = el._range;\n\t\t\tvar current = el.innerHTML;\n\t\t\tfor (var i = range.length; --i >= 0;)\n\t\t\t\tif (range[i] == current)\n\t\t\t\t\tbreak;\n\t\t\tif (ev && ev.shiftKey) {\n\t\t\t\tif (--i < 0)\n\t\t\t\t\ti = range.length - 1;\n\t\t\t} else if ( ++i >= range.length )\n\t\t\t\ti = 0;\n\t\t\tvar newval = range[i];\n\t\t\tel.innerHTML = newval;\n\t\t\tcal.onUpdateTime();\n\t\t\treturn;\n\t\t    case 0:\n\t\t\t// TODAY will bring us here\n\t\t\tif ((typeof cal.getDateStatus == \"function\") &&\n\t\t\t    cal.getDateStatus(date, date.getFullYear(), date.getMonth(), date.getDate())) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tif (!date.equalsTo(cal.date)) {\n\t\t\tcal.setDate(date);\n\t\t\tnewdate = true;\n\t\t} else if (el.navtype == 0)\n\t\t\tnewdate = closing = true;\n\t}\n\tif (newdate) {\n\t\tev && cal.callHandler();\n\t}\n\tif (closing) {\n\t\tCalendar.removeClass(el, \"hilite\");\n\t\tev && cal.callCloseHandler();\n\t}\n};\n\n// END: CALENDAR STATIC FUNCTIONS\n\n// BEGIN: CALENDAR OBJECT FUNCTIONS\n\n/**\n *  This function creates the calendar inside the given parent.  If _par is\n *  null than it creates a popup calendar inside the BODY element.  If _par is\n *  an element, be it BODY, then it creates a non-popup calendar (still\n *  hidden).  Some properties need to be set before calling this function.\n */\nCalendar.prototype.create = function (_par) {\n\tvar parent = null;\n\tif (! _par) {\n\t\t// default parent is the document body, in which case we create\n\t\t// a popup calendar.\n\t\tparent = document.getElementsByTagName(\"body\")[0];\n\t\tthis.isPopup = true;\n\t} else {\n\t\tparent = _par;\n\t\tthis.isPopup = false;\n\t}\n\tthis.date = this.dateStr ? new Date(this.dateStr) : new Date();\n\n\tvar table = Calendar.createElement(\"table\");\n\tthis.table = table;\n\ttable.cellSpacing = 0;\n\ttable.cellPadding = 0;\n\ttable.calendar = this;\n\tCalendar.addEvent(table, \"mousedown\", Calendar.tableMouseDown);\n\n\tvar div = Calendar.createElement(\"div\");\n\tthis.element = div;\n\tdiv.className = \"calendar\";\n\tif (this.isPopup) {\n\t\tdiv.style.position = \"absolute\";\n\t\tdiv.style.display = \"none\";\n\t}\n\tdiv.appendChild(table);\n\n\tvar thead = Calendar.createElement(\"thead\", table);\n\tvar cell = null;\n\tvar row = null;\n\n\tvar cal = this;\n\tvar hh = function (text, cs, navtype) {\n\t\tcell = Calendar.createElement(\"td\", row);\n\t\tcell.colSpan = cs;\n\t\tcell.className = \"button\";\n\t\tif (navtype != 0 && Math.abs(navtype) <= 2)\n\t\t\tcell.className += \" nav\";\n\t\tCalendar._add_evs(cell);\n\t\tcell.calendar = cal;\n\t\tcell.navtype = navtype;\n\t\tcell.innerHTML = \"<div unselectable='on'>\" + text + \"</div>\";\n\t\treturn cell;\n\t};\n\n\trow = Calendar.createElement(\"tr\", thead);\n\tvar title_length = 6;\n\t(this.isPopup) && --title_length;\n\t(this.weekNumbers) && ++title_length;\n\n\thh(\"?\", 1, 400).ttip = Calendar._TT[\"INFO\"];\n\tthis.title = hh(\"\", title_length, 300);\n\tthis.title.className = \"title\";\n\tif (this.isPopup) {\n\t\tthis.title.ttip = Calendar._TT[\"DRAG_TO_MOVE\"];\n\t\tthis.title.style.cursor = \"move\";\n\t\thh(\"&#x00d7;\", 1, 200).ttip = Calendar._TT[\"CLOSE\"];\n\t}\n\n\trow = Calendar.createElement(\"tr\", thead);\n\trow.className = \"headrow\";\n\n\tthis._nav_py = hh(\"&#x00ab;\", 1, -2);\n\tthis._nav_py.ttip = Calendar._TT[\"PREV_YEAR\"];\n\n\tthis._nav_pm = hh(\"&#x2039;\", 1, -1);\n\tthis._nav_pm.ttip = Calendar._TT[\"PREV_MONTH\"];\n\n\tthis._nav_now = hh(Calendar._TT[\"TODAY\"], this.weekNumbers ? 4 : 3, 0);\n\tthis._nav_now.ttip = Calendar._TT[\"GO_TODAY\"];\n\n\tthis._nav_nm = hh(\"&#x203a;\", 1, 1);\n\tthis._nav_nm.ttip = Calendar._TT[\"NEXT_MONTH\"];\n\n\tthis._nav_ny = hh(\"&#x00bb;\", 1, 2);\n\tthis._nav_ny.ttip = Calendar._TT[\"NEXT_YEAR\"];\n\n\t// day names\n\trow = Calendar.createElement(\"tr\", thead);\n\trow.className = \"daynames\";\n\tif (this.weekNumbers) {\n\t\tcell = Calendar.createElement(\"td\", row);\n\t\tcell.className = \"name wn\";\n\t\tcell.innerHTML = Calendar._TT[\"WK\"];\n\t}\n\tfor (var i = 7; i > 0; --i) {\n\t\tcell = Calendar.createElement(\"td\", row);\n\t\tif (!i) {\n\t\t\tcell.navtype = 100;\n\t\t\tcell.calendar = this;\n\t\t\tCalendar._add_evs(cell);\n\t\t}\n\t}\n\tthis.firstdayname = (this.weekNumbers) ? row.firstChild.nextSibling : row.firstChild;\n\tthis._displayWeekdays();\n\n\tvar tbody = Calendar.createElement(\"tbody\", table);\n\tthis.tbody = tbody;\n\n\tfor (i = 6; i > 0; --i) {\n\t\trow = Calendar.createElement(\"tr\", tbody);\n\t\tif (this.weekNumbers) {\n\t\t\tcell = Calendar.createElement(\"td\", row);\n\t\t}\n\t\tfor (var j = 7; j > 0; --j) {\n\t\t\tcell = Calendar.createElement(\"td\", row);\n\t\t\tcell.calendar = this;\n\t\t\tCalendar._add_evs(cell);\n\t\t}\n\t}\n\n\tif (this.showsTime) {\n\t\trow = Calendar.createElement(\"tr\", tbody);\n\t\trow.className = \"time\";\n\n\t\tcell = Calendar.createElement(\"td\", row);\n\t\tcell.className = \"time\";\n\t\tcell.colSpan = 2;\n\t\tcell.innerHTML = Calendar._TT[\"TIME\"] || \"&nbsp;\";\n\n\t\tcell = Calendar.createElement(\"td\", row);\n\t\tcell.className = \"time\";\n\t\tcell.colSpan = this.weekNumbers ? 4 : 3;\n\n\t\t(function(){\n\t\t\tfunction makeTimePart(className, init, range_start, range_end) {\n\t\t\t\tvar part = Calendar.createElement(\"span\", cell);\n\t\t\t\tpart.className = className;\n\t\t\t\tpart.innerHTML = init;\n\t\t\t\tpart.calendar = cal;\n\t\t\t\tpart.ttip = Calendar._TT[\"TIME_PART\"];\n\t\t\t\tpart.navtype = 50;\n\t\t\t\tpart._range = [];\n\t\t\t\tif (typeof range_start != \"number\")\n\t\t\t\t\tpart._range = range_start;\n\t\t\t\telse {\n\t\t\t\t\tfor (var i = range_start; i <= range_end; ++i) {\n\t\t\t\t\t\tvar txt;\n\t\t\t\t\t\tif (i < 10 && range_end >= 10) txt = '0' + i;\n\t\t\t\t\t\telse txt = '' + i;\n\t\t\t\t\t\tpart._range[part._range.length] = txt;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tCalendar._add_evs(part);\n\t\t\t\treturn part;\n\t\t\t};\n\t\t\tvar hrs = cal.date.getHours();\n\t\t\tvar mins = cal.date.getMinutes();\n\t\t\tvar t12 = !cal.time24;\n\t\t\tvar pm = (hrs > 12);\n\t\t\tif (t12 && pm) hrs -= 12;\n\t\t\tvar H = makeTimePart(\"hour\", hrs, t12 ? 1 : 0, t12 ? 12 : 23);\n\t\t\tvar span = Calendar.createElement(\"span\", cell);\n\t\t\tspan.innerHTML = \":\";\n\t\t\tspan.className = \"colon\";\n\t\t\tvar M = makeTimePart(\"minute\", mins, 0, 59);\n\t\t\tvar AP = null;\n\t\t\tcell = Calendar.createElement(\"td\", row);\n\t\t\tcell.className = \"time\";\n\t\t\tcell.colSpan = 2;\n\t\t\tif (t12)\n\t\t\t\tAP = makeTimePart(\"ampm\", pm ? \"pm\" : \"am\", [\"am\", \"pm\"]);\n\t\t\telse\n\t\t\t\tcell.innerHTML = \"&nbsp;\";\n\n\t\t\tcal.onSetTime = function() {\n\t\t\t\tvar pm, hrs = this.date.getHours(),\n\t\t\t\t\tmins = this.date.getMinutes();\n\t\t\t\tif (t12) {\n\t\t\t\t\tpm = (hrs >= 12);\n\t\t\t\t\tif (pm) hrs -= 12;\n\t\t\t\t\tif (hrs == 0) hrs = 12;\n\t\t\t\t\tAP.innerHTML = pm ? \"pm\" : \"am\";\n\t\t\t\t}\n\t\t\t\tH.innerHTML = (hrs < 10) ? (\"0\" + hrs) : hrs;\n\t\t\t\tM.innerHTML = (mins < 10) ? (\"0\" + mins) : mins;\n\t\t\t};\n\n\t\t\tcal.onUpdateTime = function() {\n\t\t\t\tvar date = this.date;\n\t\t\t\tvar h = parseInt(H.innerHTML, 10);\n\t\t\t\tif (t12) {\n\t\t\t\t\tif (/pm/i.test(AP.innerHTML) && h < 12)\n\t\t\t\t\t\th += 12;\n\t\t\t\t\telse if (/am/i.test(AP.innerHTML) && h == 12)\n\t\t\t\t\t\th = 0;\n\t\t\t\t}\n\t\t\t\tvar d = date.getDate();\n\t\t\t\tvar m = date.getMonth();\n\t\t\t\tvar y = date.getFullYear();\n\t\t\t\tdate.setHours(h);\n\t\t\t\tdate.setMinutes(parseInt(M.innerHTML, 10));\n\t\t\t\tdate.setFullYear(y);\n\t\t\t\tdate.setMonth(m);\n\t\t\t\tdate.setDate(d);\n\t\t\t\tthis.dateClicked = false;\n\t\t\t\tthis.callHandler();\n\t\t\t};\n\t\t})();\n\t} else {\n\t\tthis.onSetTime = this.onUpdateTime = function() {};\n\t}\n\n\tvar tfoot = Calendar.createElement(\"tfoot\", table);\n\n\trow = Calendar.createElement(\"tr\", tfoot);\n\trow.className = \"footrow\";\n\n\tcell = hh(Calendar._TT[\"SEL_DATE\"], this.weekNumbers ? 8 : 7, 300);\n\tcell.className = \"ttip\";\n\tif (this.isPopup) {\n\t\tcell.ttip = Calendar._TT[\"DRAG_TO_MOVE\"];\n\t\tcell.style.cursor = \"move\";\n\t}\n\tthis.tooltips = cell;\n\n\tdiv = Calendar.createElement(\"div\", this.element);\n\tthis.monthsCombo = div;\n\tdiv.className = \"combo\";\n\tfor (i = 0; i < Calendar._MN.length; ++i) {\n\t\tvar mn = Calendar.createElement(\"div\");\n\t\tmn.className = Calendar.is_ie ? \"label-IEfix\" : \"label\";\n\t\tmn.month = i;\n\t\tmn.innerHTML = Calendar._SMN[i];\n\t\tdiv.appendChild(mn);\n\t}\n\n\tdiv = Calendar.createElement(\"div\", this.element);\n\tthis.yearsCombo = div;\n\tdiv.className = \"combo\";\n\tfor (i = 12; i > 0; --i) {\n\t\tvar yr = Calendar.createElement(\"div\");\n\t\tyr.className = Calendar.is_ie ? \"label-IEfix\" : \"label\";\n\t\tdiv.appendChild(yr);\n\t}\n\n\tthis._init(this.firstDayOfWeek, this.date);\n\tparent.appendChild(this.element);\n};\n\n/** keyboard navigation, only for popup calendars */\nCalendar._keyEvent = function(ev) {\n\tvar cal = window._dynarch_popupCalendar;\n\tif (!cal || cal.multiple)\n\t\treturn false;\n\t(Calendar.is_ie) && (ev = window.event);\n\tvar act = (Calendar.is_ie || ev.type == \"keypress\"),\n\t\tK = ev.keyCode;\n\tif (ev.ctrlKey) {\n\t\tswitch (K) {\n\t\t    case 37: // KEY left\n\t\t\tact && Calendar.cellClick(cal._nav_pm);\n\t\t\tbreak;\n\t\t    case 38: // KEY up\n\t\t\tact && Calendar.cellClick(cal._nav_py);\n\t\t\tbreak;\n\t\t    case 39: // KEY right\n\t\t\tact && Calendar.cellClick(cal._nav_nm);\n\t\t\tbreak;\n\t\t    case 40: // KEY down\n\t\t\tact && Calendar.cellClick(cal._nav_ny);\n\t\t\tbreak;\n\t\t    default:\n\t\t\treturn false;\n\t\t}\n\t} else switch (K) {\n\t    case 32: // KEY space (now)\n\t\tCalendar.cellClick(cal._nav_now);\n\t\tbreak;\n\t    case 27: // KEY esc\n\t\tact && cal.callCloseHandler();\n\t\tbreak;\n\t    case 37: // KEY left\n\t    case 38: // KEY up\n\t    case 39: // KEY right\n\t    case 40: // KEY down\n\t\tif (act) {\n\t\t\tvar prev, x, y, ne, el, step;\n\t\t\tprev = K == 37 || K == 38;\n\t\t\tstep = (K == 37 || K == 39) ? 1 : 7;\n\t\t\tfunction setVars() {\n\t\t\t\tel = cal.currentDateEl;\n\t\t\t\tvar p = el.pos;\n\t\t\t\tx = p & 15;\n\t\t\t\ty = p >> 4;\n\t\t\t\tne = cal.ar_days[y][x];\n\t\t\t};setVars();\n\t\t\tfunction prevMonth() {\n\t\t\t\tvar date = new Date(cal.date);\n\t\t\t\tdate.setDate(date.getDate() - step);\n\t\t\t\tcal.setDate(date);\n\t\t\t};\n\t\t\tfunction nextMonth() {\n\t\t\t\tvar date = new Date(cal.date);\n\t\t\t\tdate.setDate(date.getDate() + step);\n\t\t\t\tcal.setDate(date);\n\t\t\t};\n\t\t\twhile (1) {\n\t\t\t\tswitch (K) {\n\t\t\t\t    case 37: // KEY left\n\t\t\t\t\tif (--x >= 0)\n\t\t\t\t\t\tne = cal.ar_days[y][x];\n\t\t\t\t\telse {\n\t\t\t\t\t\tx = 6;\n\t\t\t\t\t\tK = 38;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t    case 38: // KEY up\n\t\t\t\t\tif (--y >= 0)\n\t\t\t\t\t\tne = cal.ar_days[y][x];\n\t\t\t\t\telse {\n\t\t\t\t\t\tprevMonth();\n\t\t\t\t\t\tsetVars();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t    case 39: // KEY right\n\t\t\t\t\tif (++x < 7)\n\t\t\t\t\t\tne = cal.ar_days[y][x];\n\t\t\t\t\telse {\n\t\t\t\t\t\tx = 0;\n\t\t\t\t\t\tK = 40;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t    case 40: // KEY down\n\t\t\t\t\tif (++y < cal.ar_days.length)\n\t\t\t\t\t\tne = cal.ar_days[y][x];\n\t\t\t\t\telse {\n\t\t\t\t\t\tnextMonth();\n\t\t\t\t\t\tsetVars();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (ne) {\n\t\t\t\tif (!ne.disabled)\n\t\t\t\t\tCalendar.cellClick(ne);\n\t\t\t\telse if (prev)\n\t\t\t\t\tprevMonth();\n\t\t\t\telse\n\t\t\t\t\tnextMonth();\n\t\t\t}\n\t\t}\n\t\tbreak;\n\t    case 13: // KEY enter\n\t\tif (act)\n\t\t\tCalendar.cellClick(cal.currentDateEl, ev);\n\t\tbreak;\n\t    default:\n\t\treturn false;\n\t}\n\treturn Calendar.stopEvent(ev);\n};\n\n/**\n *  (RE)Initializes the calendar to the given date and firstDayOfWeek\n */\nCalendar.prototype._init = function (firstDayOfWeek, date) {\n\tvar today = new Date(),\n\t\tTY = today.getFullYear(),\n\t\tTM = today.getMonth(),\n\t\tTD = today.getDate();\n\tthis.table.style.visibility = \"hidden\";\n\tvar year = date.getFullYear();\n\tif (year < this.minYear) {\n\t\tyear = this.minYear;\n\t\tdate.setFullYear(year);\n\t} else if (year > this.maxYear) {\n\t\tyear = this.maxYear;\n\t\tdate.setFullYear(year);\n\t}\n\tthis.firstDayOfWeek = firstDayOfWeek;\n\tthis.date = new Date(date);\n\tvar month = date.getMonth();\n\tvar mday = date.getDate();\n\tvar no_days = date.getMonthDays();\n\n\t// calendar voodoo for computing the first day that would actually be\n\t// displayed in the calendar, even if it's from the previous month.\n\t// WARNING: this is magic. ;-)\n\tdate.setDate(1);\n\tvar day1 = (date.getDay() - this.firstDayOfWeek) % 7;\n\tif (day1 < 0)\n\t\tday1 += 7;\n\tdate.setDate(-day1);\n\tdate.setDate(date.getDate() + 1);\n\n\tvar row = this.tbody.firstChild;\n\tvar MN = Calendar._SMN[month];\n\tvar ar_days = this.ar_days = new Array();\n\tvar weekend = Calendar._TT[\"WEEKEND\"];\n\tvar dates = this.multiple ? (this.datesCells = {}) : null;\n\tfor (var i = 0; i < 6; ++i, row = row.nextSibling) {\n\t\tvar cell = row.firstChild;\n\t\tif (this.weekNumbers) {\n\t\t\tcell.className = \"day wn\";\n\t\t\tcell.innerHTML = date.getWeekNumber();\n\t\t\tcell = cell.nextSibling;\n\t\t}\n\t\trow.className = \"daysrow\";\n\t\tvar hasdays = false, iday, dpos = ar_days[i] = [];\n\t\tfor (var j = 0; j < 7; ++j, cell = cell.nextSibling, date.setDate(iday + 1)) {\n\t\t\tiday = date.getDate();\n\t\t\tvar wday = date.getDay();\n\t\t\tcell.className = \"day\";\n\t\t\tcell.pos = i << 4 | j;\n\t\t\tdpos[j] = cell;\n\t\t\tvar current_month = (date.getMonth() == month);\n\t\t\tif (!current_month) {\n\t\t\t\tif (this.showsOtherMonths) {\n\t\t\t\t\tcell.className += \" othermonth\";\n\t\t\t\t\tcell.otherMonth = true;\n\t\t\t\t} else {\n\t\t\t\t\tcell.className = \"emptycell\";\n\t\t\t\t\tcell.innerHTML = \"&nbsp;\";\n\t\t\t\t\tcell.disabled = true;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcell.otherMonth = false;\n\t\t\t\thasdays = true;\n\t\t\t}\n\t\t\tcell.disabled = false;\n\t\t\tcell.innerHTML = this.getDateText ? this.getDateText(date, iday) : iday;\n\t\t\tif (dates)\n\t\t\t\tdates[date.print(\"%Y%m%d\")] = cell;\n\t\t\tif (this.getDateStatus) {\n\t\t\t\tvar status = this.getDateStatus(date, year, month, iday);\n\t\t\t\tif (this.getDateToolTip) {\n\t\t\t\t\tvar toolTip = this.getDateToolTip(date, year, month, iday);\n\t\t\t\t\tif (toolTip)\n\t\t\t\t\t\tcell.title = toolTip;\n\t\t\t\t}\n\t\t\t\tif (status === true) {\n\t\t\t\t\tcell.className += \" disabled\";\n\t\t\t\t\tcell.disabled = true;\n\t\t\t\t} else {\n\t\t\t\t\tif (/disabled/i.test(status))\n\t\t\t\t\t\tcell.disabled = true;\n\t\t\t\t\tcell.className += \" \" + status;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!cell.disabled) {\n\t\t\t\tcell.caldate = new Date(date);\n\t\t\t\tcell.ttip = \"_\";\n\t\t\t\tif (!this.multiple && current_month\n\t\t\t\t    && iday == mday && this.hiliteToday) {\n\t\t\t\t\tcell.className += \" selected\";\n\t\t\t\t\tthis.currentDateEl = cell;\n\t\t\t\t}\n\t\t\t\tif (date.getFullYear() == TY &&\n\t\t\t\t    date.getMonth() == TM &&\n\t\t\t\t    iday == TD) {\n\t\t\t\t\tcell.className += \" today\";\n\t\t\t\t\tcell.ttip += Calendar._TT[\"PART_TODAY\"];\n\t\t\t\t}\n\t\t\t\tif (weekend.indexOf(wday.toString()) != -1)\n\t\t\t\t\tcell.className += cell.otherMonth ? \" oweekend\" : \" weekend\";\n\t\t\t}\n\t\t}\n\t\tif (!(hasdays || this.showsOtherMonths))\n\t\t\trow.className = \"emptyrow\";\n\t}\n\tthis.title.innerHTML = Calendar._MN[month] + \", \" + year;\n\tthis.onSetTime();\n\tthis.table.style.visibility = \"visible\";\n\tthis._initMultipleDates();\n\t// PROFILE\n\t// this.tooltips.innerHTML = \"Generated in \" + ((new Date()) - today) + \" ms\";\n};\n\nCalendar.prototype._initMultipleDates = function() {\n\tif (this.multiple) {\n\t\tfor (var i in this.multiple) {\n\t\t\tvar cell = this.datesCells[i];\n\t\t\tvar d = this.multiple[i];\n\t\t\tif (!d)\n\t\t\t\tcontinue;\n\t\t\tif (cell)\n\t\t\t\tcell.className += \" selected\";\n\t\t}\n\t}\n};\n\nCalendar.prototype._toggleMultipleDate = function(date) {\n\tif (this.multiple) {\n\t\tvar ds = date.print(\"%Y%m%d\");\n\t\tvar cell = this.datesCells[ds];\n\t\tif (cell) {\n\t\t\tvar d = this.multiple[ds];\n\t\t\tif (!d) {\n\t\t\t\tCalendar.addClass(cell, \"selected\");\n\t\t\t\tthis.multiple[ds] = date;\n\t\t\t} else {\n\t\t\t\tCalendar.removeClass(cell, \"selected\");\n\t\t\t\tdelete this.multiple[ds];\n\t\t\t}\n\t\t}\n\t}\n};\n\nCalendar.prototype.setDateToolTipHandler = function (unaryFunction) {\n\tthis.getDateToolTip = unaryFunction;\n};\n\n/**\n *  Calls _init function above for going to a certain date (but only if the\n *  date is different than the currently selected one).\n */\nCalendar.prototype.setDate = function (date) {\n\tif (!date.equalsTo(this.date)) {\n\t\tthis._init(this.firstDayOfWeek, date);\n\t}\n};\n\n/**\n *  Refreshes the calendar.  Useful if the \"disabledHandler\" function is\n *  dynamic, meaning that the list of disabled date can change at runtime.\n *  Just * call this function if you think that the list of disabled dates\n *  should * change.\n */\nCalendar.prototype.refresh = function () {\n\tthis._init(this.firstDayOfWeek, this.date);\n};\n\n/** Modifies the \"firstDayOfWeek\" parameter (pass 0 for Synday, 1 for Monday, etc.). */\nCalendar.prototype.setFirstDayOfWeek = function (firstDayOfWeek) {\n\tthis._init(firstDayOfWeek, this.date);\n\tthis._displayWeekdays();\n};\n\n/**\n *  Allows customization of what dates are enabled.  The \"unaryFunction\"\n *  parameter must be a function object that receives the date (as a JS Date\n *  object) and returns a boolean value.  If the returned value is true then\n *  the passed date will be marked as disabled.\n */\nCalendar.prototype.setDateStatusHandler = Calendar.prototype.setDisabledHandler = function (unaryFunction) {\n\tthis.getDateStatus = unaryFunction;\n};\n\n/** Customization of allowed year range for the calendar. */\nCalendar.prototype.setRange = function (a, z) {\n\tthis.minYear = a;\n\tthis.maxYear = z;\n};\n\n/** Calls the first user handler (selectedHandler). */\nCalendar.prototype.callHandler = function () {\n\tif (this.onSelected) {\n\t\tthis.onSelected(this, this.date.print(this.dateFormat));\n\t}\n};\n\n/** Calls the second user handler (closeHandler). */\nCalendar.prototype.callCloseHandler = function () {\n\tif (this.onClose) {\n\t\tthis.onClose(this);\n\t}\n\tthis.hideShowCovered();\n};\n\n/** Removes the calendar object from the DOM tree and destroys it. */\nCalendar.prototype.destroy = function () {\n\tvar el = this.element.parentNode;\n\tel.removeChild(this.element);\n\tCalendar._C = null;\n\twindow._dynarch_popupCalendar = null;\n};\n\n/**\n *  Moves the calendar element to a different section in the DOM tree (changes\n *  its parent).\n */\nCalendar.prototype.reparent = function (new_parent) {\n\tvar el = this.element;\n\tel.parentNode.removeChild(el);\n\tnew_parent.appendChild(el);\n};\n\n// This gets called when the user presses a mouse button anywhere in the\n// document, if the calendar is shown.  If the click was outside the open\n// calendar this function closes it.\nCalendar._checkCalendar = function(ev) {\n\tvar calendar = window._dynarch_popupCalendar;\n\tif (!calendar) {\n\t\treturn false;\n\t}\n\tvar el = Calendar.is_ie ? Calendar.getElement(ev) : Calendar.getTargetElement(ev);\n\tfor (; el != null && el != calendar.element; el = el.parentNode);\n\tif (el == null) {\n\t\t// calls closeHandler which should hide the calendar.\n\t\twindow._dynarch_popupCalendar.callCloseHandler();\n\t\treturn Calendar.stopEvent(ev);\n\t}\n};\n\n/** Shows the calendar. */\nCalendar.prototype.show = function () {\n\tvar rows = this.table.getElementsByTagName(\"tr\");\n\tfor (var i = rows.length; i > 0;) {\n\t\tvar row = rows[--i];\n\t\tCalendar.removeClass(row, \"rowhilite\");\n\t\tvar cells = row.getElementsByTagName(\"td\");\n\t\tfor (var j = cells.length; j > 0;) {\n\t\t\tvar cell = cells[--j];\n\t\t\tCalendar.removeClass(cell, \"hilite\");\n\t\t\tCalendar.removeClass(cell, \"active\");\n\t\t}\n\t}\n\tthis.element.style.display = \"block\";\n\tthis.hidden = false;\n\tif (this.isPopup) {\n\t\twindow._dynarch_popupCalendar = this;\n\t\tCalendar.addEvent(document, \"keydown\", Calendar._keyEvent);\n\t\tCalendar.addEvent(document, \"keypress\", Calendar._keyEvent);\n\t\tCalendar.addEvent(document, \"mousedown\", Calendar._checkCalendar);\n\t}\n\tthis.hideShowCovered();\n};\n\n/**\n *  Hides the calendar.  Also removes any \"hilite\" from the class of any TD\n *  element.\n */\nCalendar.prototype.hide = function () {\n\tif (this.isPopup) {\n\t\tCalendar.removeEvent(document, \"keydown\", Calendar._keyEvent);\n\t\tCalendar.removeEvent(document, \"keypress\", Calendar._keyEvent);\n\t\tCalendar.removeEvent(document, \"mousedown\", Calendar._checkCalendar);\n\t}\n\tthis.element.style.display = \"none\";\n\tthis.hidden = true;\n\tthis.hideShowCovered();\n};\n\n/**\n *  Shows the calendar at a given absolute position (beware that, depending on\n *  the calendar element style -- position property -- this might be relative\n *  to the parent's containing rectangle).\n */\nCalendar.prototype.showAt = function (x, y) {\n\tvar s = this.element.style;\n\ts.left = x + \"px\";\n\ts.top = y + \"px\";\n\tthis.show();\n};\n\n/** Shows the calendar near a given element. */\nCalendar.prototype.showAtElement = function (el, opts) {\n\tvar self = this;\n\tvar p = Calendar.getAbsolutePos(el);\n\tif (!opts || typeof opts != \"string\") {\n\t\tthis.showAt(p.x, p.y + el.offsetHeight);\n\t\treturn true;\n\t}\n\tfunction fixPosition(box) {\n\t\tif (box.x < 0)\n\t\t\tbox.x = 0;\n\t\tif (box.y < 0)\n\t\t\tbox.y = 0;\n\t\tvar cp = document.createElement(\"div\");\n\t\tvar s = cp.style;\n\t\ts.position = \"absolute\";\n\t\ts.right = s.bottom = s.width = s.height = \"0px\";\n\t\tdocument.body.appendChild(cp);\n\t\tvar br = Calendar.getAbsolutePos(cp);\n\t\tdocument.body.removeChild(cp);\n\t\tif (Calendar.is_ie) {\n\t\t\tbr.y += document.body.scrollTop;\n\t\t\tbr.x += document.body.scrollLeft;\n\t\t} else {\n\t\t\tbr.y += window.scrollY;\n\t\t\tbr.x += window.scrollX;\n\t\t}\n\t\tvar tmp = box.x + box.width - br.x;\n\t\tif (tmp > 0) box.x -= tmp;\n\t\ttmp = box.y + box.height - br.y;\n\t\tif (tmp > 0) box.y -= tmp;\n\t};\n\tthis.element.style.display = \"block\";\n\tCalendar.continuation_for_the_fucking_khtml_browser = function() {\n\t\tvar w = self.element.offsetWidth;\n\t\tvar h = self.element.offsetHeight;\n\t\tself.element.style.display = \"none\";\n\t\tvar valign = opts.substr(0, 1);\n\t\tvar halign = \"l\";\n\t\tif (opts.length > 1) {\n\t\t\thalign = opts.substr(1, 1);\n\t\t}\n\t\t// vertical alignment\n\t\tswitch (valign) {\n\t\t    case \"T\": p.y -= h; break;\n\t\t    case \"B\": p.y += el.offsetHeight; break;\n\t\t    case \"C\": p.y += (el.offsetHeight - h) / 2; break;\n\t\t    case \"t\": p.y += el.offsetHeight - h; break;\n\t\t    case \"b\": break; // already there\n\t\t}\n\t\t// horizontal alignment\n\t\tswitch (halign) {\n\t\t    case \"L\": p.x -= w; break;\n\t\t    case \"R\": p.x += el.offsetWidth; break;\n\t\t    case \"C\": p.x += (el.offsetWidth - w) / 2; break;\n\t\t    case \"l\": p.x += el.offsetWidth - w; break;\n\t\t    case \"r\": break; // already there\n\t\t}\n\t\tp.width = w;\n\t\tp.height = h + 40;\n\t\tself.monthsCombo.style.display = \"none\";\n\t\tfixPosition(p);\n\t\tself.showAt(p.x, p.y);\n\t};\n\tif (Calendar.is_khtml)\n\t\tsetTimeout(\"Calendar.continuation_for_the_fucking_khtml_browser()\", 10);\n\telse\n\t\tCalendar.continuation_for_the_fucking_khtml_browser();\n};\n\n/** Customizes the date format. */\nCalendar.prototype.setDateFormat = function (str) {\n\tthis.dateFormat = str;\n};\n\n/** Customizes the tooltip date format. */\nCalendar.prototype.setTtDateFormat = function (str) {\n\tthis.ttDateFormat = str;\n};\n\n/**\n *  Tries to identify the date represented in a string.  If successful it also\n *  calls this.setDate which moves the calendar to the given date.\n */\nCalendar.prototype.parseDate = function(str, fmt) {\n\tif (!fmt)\n\t\tfmt = this.dateFormat;\n\tthis.setDate(Date.parseDate(str, fmt));\n};\n\nCalendar.prototype.hideShowCovered = function () {\n\tif (!Calendar.is_ie && !Calendar.is_opera)\n\t\treturn;\n\tfunction getVisib(obj){\n\t\tvar value = obj.style.visibility;\n\t\tif (!value) {\n\t\t\tif (document.defaultView && typeof (document.defaultView.getComputedStyle) == \"function\") { // Gecko, W3C\n\t\t\t\tif (!Calendar.is_khtml)\n\t\t\t\t\tvalue = document.defaultView.\n\t\t\t\t\t\tgetComputedStyle(obj, \"\").getPropertyValue(\"visibility\");\n\t\t\t\telse\n\t\t\t\t\tvalue = '';\n\t\t\t} else if (obj.currentStyle) { // IE\n\t\t\t\tvalue = obj.currentStyle.visibility;\n\t\t\t} else\n\t\t\t\tvalue = '';\n\t\t}\n\t\treturn value;\n\t};\n\n\tvar tags = new Array(\"applet\", \"iframe\", \"select\");\n\tvar el = this.element;\n\n\tvar p = Calendar.getAbsolutePos(el);\n\tvar EX1 = p.x;\n\tvar EX2 = el.offsetWidth + EX1;\n\tvar EY1 = p.y;\n\tvar EY2 = el.offsetHeight + EY1;\n\n\tfor (var k = tags.length; k > 0; ) {\n\t\tvar ar = document.getElementsByTagName(tags[--k]);\n\t\tvar cc = null;\n\n\t\tfor (var i = ar.length; i > 0;) {\n\t\t\tcc = ar[--i];\n\n\t\t\tp = Calendar.getAbsolutePos(cc);\n\t\t\tvar CX1 = p.x;\n\t\t\tvar CX2 = cc.offsetWidth + CX1;\n\t\t\tvar CY1 = p.y;\n\t\t\tvar CY2 = cc.offsetHeight + CY1;\n\n\t\t\tif (this.hidden || (CX1 > EX2) || (CX2 < EX1) || (CY1 > EY2) || (CY2 < EY1)) {\n\t\t\t\tif (!cc.__msh_save_visibility) {\n\t\t\t\t\tcc.__msh_save_visibility = getVisib(cc);\n\t\t\t\t}\n\t\t\t\tcc.style.visibility = cc.__msh_save_visibility;\n\t\t\t} else {\n\t\t\t\tif (!cc.__msh_save_visibility) {\n\t\t\t\t\tcc.__msh_save_visibility = getVisib(cc);\n\t\t\t\t}\n\t\t\t\tcc.style.visibility = \"hidden\";\n\t\t\t}\n\t\t}\n\t}\n};\n\n/** Internal function; it displays the bar with the names of the weekday. */\nCalendar.prototype._displayWeekdays = function () {\n\tvar fdow = this.firstDayOfWeek;\n\tvar cell = this.firstdayname;\n\tvar weekend = Calendar._TT[\"WEEKEND\"];\n\tfor (var i = 0; i < 7; ++i) {\n\t\tcell.className = \"day name\";\n\t\tvar realday = (i + fdow) % 7;\n\t\tif (i) {\n\t\t\tcell.ttip = Calendar._TT[\"DAY_FIRST\"].replace(\"%s\", Calendar._DN[realday]);\n\t\t\tcell.navtype = 100;\n\t\t\tcell.calendar = this;\n\t\t\tcell.fdow = realday;\n\t\t\tCalendar._add_evs(cell);\n\t\t}\n\t\tif (weekend.indexOf(realday.toString()) != -1) {\n\t\t\tCalendar.addClass(cell, \"weekend\");\n\t\t}\n\t\tcell.innerHTML = Calendar._SDN[(i + fdow) % 7];\n\t\tcell = cell.nextSibling;\n\t}\n};\n\n/** Internal function.  Hides all combo boxes that might be displayed. */\nCalendar.prototype._hideCombos = function () {\n\tthis.monthsCombo.style.display = \"none\";\n\tthis.yearsCombo.style.display = \"none\";\n};\n\n/** Internal function.  Starts dragging the element. */\nCalendar.prototype._dragStart = function (ev) {\n\tif (this.dragging) {\n\t\treturn;\n\t}\n\tthis.dragging = true;\n\tvar posX;\n\tvar posY;\n\tif (Calendar.is_ie) {\n\t\tposY = window.event.clientY + document.body.scrollTop;\n\t\tposX = window.event.clientX + document.body.scrollLeft;\n\t} else {\n\t\tposY = ev.clientY + window.scrollY;\n\t\tposX = ev.clientX + window.scrollX;\n\t}\n\tvar st = this.element.style;\n\tthis.xOffs = posX - parseInt(st.left);\n\tthis.yOffs = posY - parseInt(st.top);\n\twith (Calendar) {\n\t\taddEvent(document, \"mousemove\", calDragIt);\n\t\taddEvent(document, \"mouseup\", calDragEnd);\n\t}\n};\n\n// BEGIN: DATE OBJECT PATCHES\n\n/** Adds the number of days array to the Date object. */\nDate._MD = new Array(31,28,31,30,31,30,31,31,30,31,30,31);\n\n/** Constants used for time computations */\nDate.SECOND = 1000 /* milliseconds */;\nDate.MINUTE = 60 * Date.SECOND;\nDate.HOUR   = 60 * Date.MINUTE;\nDate.DAY    = 24 * Date.HOUR;\nDate.WEEK   =  7 * Date.DAY;\n\nDate.parseDate = function(str, fmt) {\n\tvar today = new Date();\n\tvar y = 0;\n\tvar m = -1;\n\tvar d = 0;\n\tvar a = str.split(/\\W+/);\n\tvar b = fmt.match(/%./g);\n\tvar i = 0, j = 0;\n\tvar hr = 0;\n\tvar min = 0;\n\tfor (i = 0; i < a.length; ++i) {\n\t\tif (!a[i])\n\t\t\tcontinue;\n\t\tswitch (b[i]) {\n\t\t    case \"%d\":\n\t\t    case \"%e\":\n\t\t\td = parseInt(a[i], 10);\n\t\t\tbreak;\n\n\t\t    case \"%m\":\n\t\t\tm = parseInt(a[i], 10) - 1;\n\t\t\tbreak;\n\n\t\t    case \"%Y\":\n\t\t    case \"%y\":\n\t\t\ty = parseInt(a[i], 10);\n\t\t\t(y < 100) && (y += (y > 29) ? 1900 : 2000);\n\t\t\tbreak;\n\n\t\t    case \"%b\":\n\t\t    case \"%B\":\n\t\t\tfor (j = 0; j < 12; ++j) {\n\t\t\t\tif (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { m = j; break; }\n\t\t\t}\n\t\t\tbreak;\n\n\t\t    case \"%H\":\n\t\t    case \"%I\":\n\t\t    case \"%k\":\n\t\t    case \"%l\":\n\t\t\thr = parseInt(a[i], 10);\n\t\t\tbreak;\n\n\t\t    case \"%P\":\n\t\t    case \"%p\":\n\t\t\tif (/pm/i.test(a[i]) && hr < 12)\n\t\t\t\thr += 12;\n\t\t\telse if (/am/i.test(a[i]) && hr >= 12)\n\t\t\t\thr -= 12;\n\t\t\tbreak;\n\n\t\t    case \"%M\":\n\t\t\tmin = parseInt(a[i], 10);\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (isNaN(y)) y = today.getFullYear();\n\tif (isNaN(m)) m = today.getMonth();\n\tif (isNaN(d)) d = today.getDate();\n\tif (isNaN(hr)) hr = today.getHours();\n\tif (isNaN(min)) min = today.getMinutes();\n\tif (y != 0 && m != -1 && d != 0)\n\t\treturn new Date(y, m, d, hr, min, 0);\n\ty = 0; m = -1; d = 0;\n\tfor (i = 0; i < a.length; ++i) {\n\t\tif (a[i].search(/[a-zA-Z]+/) != -1) {\n\t\t\tvar t = -1;\n\t\t\tfor (j = 0; j < 12; ++j) {\n\t\t\t\tif (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { t = j; break; }\n\t\t\t}\n\t\t\tif (t != -1) {\n\t\t\t\tif (m != -1) {\n\t\t\t\t\td = m+1;\n\t\t\t\t}\n\t\t\t\tm = t;\n\t\t\t}\n\t\t} else if (parseInt(a[i], 10) <= 12 && m == -1) {\n\t\t\tm = a[i]-1;\n\t\t} else if (parseInt(a[i], 10) > 31 && y == 0) {\n\t\t\ty = parseInt(a[i], 10);\n\t\t\t(y < 100) && (y += (y > 29) ? 1900 : 2000);\n\t\t} else if (d == 0) {\n\t\t\td = a[i];\n\t\t}\n\t}\n\tif (y == 0)\n\t\ty = today.getFullYear();\n\tif (m != -1 && d != 0)\n\t\treturn new Date(y, m, d, hr, min, 0);\n\treturn today;\n};\n\n/** Returns the number of days in the current month */\nDate.prototype.getMonthDays = function(month) {\n\tvar year = this.getFullYear();\n\tif (typeof month == \"undefined\") {\n\t\tmonth = this.getMonth();\n\t}\n\tif (((0 == (year%4)) && ( (0 != (year%100)) || (0 == (year%400)))) && month == 1) {\n\t\treturn 29;\n\t} else {\n\t\treturn Date._MD[month];\n\t}\n};\n\n/** Returns the number of day in the year. */\nDate.prototype.getDayOfYear = function() {\n\tvar now = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);\n\tvar then = new Date(this.getFullYear(), 0, 0, 0, 0, 0);\n\tvar time = now - then;\n\treturn Math.floor(time / Date.DAY);\n};\n\n/** Returns the number of the week in year, as defined in ISO 8601. */\nDate.prototype.getWeekNumber = function() {\n\tvar d = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);\n\tvar DoW = d.getDay();\n\td.setDate(d.getDate() - (DoW + 6) % 7 + 3); // Nearest Thu\n\tvar ms = d.valueOf(); // GMT\n\td.setMonth(0);\n\td.setDate(4); // Thu in Week 1\n\treturn Math.round((ms - d.valueOf()) / (7 * 864e5)) + 1;\n};\n\n/** Checks date and time equality */\nDate.prototype.equalsTo = function(date) {\n\treturn ((this.getFullYear() == date.getFullYear()) &&\n\t\t(this.getMonth() == date.getMonth()) &&\n\t\t(this.getDate() == date.getDate()) &&\n\t\t(this.getHours() == date.getHours()) &&\n\t\t(this.getMinutes() == date.getMinutes()));\n};\n\n/** Set only the year, month, date parts (keep existing time) */\nDate.prototype.setDateOnly = function(date) {\n\tvar tmp = new Date(date);\n\tthis.setDate(1);\n\tthis.setFullYear(tmp.getFullYear());\n\tthis.setMonth(tmp.getMonth());\n\tthis.setDate(tmp.getDate());\n};\n\n/** Prints the date in a string according to the given format. */\nDate.prototype.print = function (str) {\n\tvar m = this.getMonth();\n\tvar d = this.getDate();\n\tvar y = this.getFullYear();\n\tvar wn = this.getWeekNumber();\n\tvar w = this.getDay();\n\tvar s = {};\n\tvar hr = this.getHours();\n\tvar pm = (hr >= 12);\n\tvar ir = (pm) ? (hr - 12) : hr;\n\tvar dy = this.getDayOfYear();\n\tif (ir == 0)\n\t\tir = 12;\n\tvar min = this.getMinutes();\n\tvar sec = this.getSeconds();\n\ts[\"%a\"] = Calendar._SDN[w]; // abbreviated weekday name [FIXME: I18N]\n\ts[\"%A\"] = Calendar._DN[w]; // full weekday name\n\ts[\"%b\"] = Calendar._SMN[m]; // abbreviated month name [FIXME: I18N]\n\ts[\"%B\"] = Calendar._MN[m]; // full month name\n\t// FIXME: %c : preferred date and time representation for the current locale\n\ts[\"%C\"] = 1 + Math.floor(y / 100); // the century number\n\ts[\"%d\"] = (d < 10) ? (\"0\" + d) : d; // the day of the month (range 01 to 31)\n\ts[\"%e\"] = d; // the day of the month (range 1 to 31)\n\t// FIXME: %D : american date style: %m/%d/%y\n\t// FIXME: %E, %F, %G, %g, %h (man strftime)\n\ts[\"%H\"] = (hr < 10) ? (\"0\" + hr) : hr; // hour, range 00 to 23 (24h format)\n\ts[\"%I\"] = (ir < 10) ? (\"0\" + ir) : ir; // hour, range 01 to 12 (12h format)\n\ts[\"%j\"] = (dy < 100) ? ((dy < 10) ? (\"00\" + dy) : (\"0\" + dy)) : dy; // day of the year (range 001 to 366)\n\ts[\"%k\"] = hr;\t\t// hour, range 0 to 23 (24h format)\n\ts[\"%l\"] = ir;\t\t// hour, range 1 to 12 (12h format)\n\ts[\"%m\"] = (m < 9) ? (\"0\" + (1+m)) : (1+m); // month, range 01 to 12\n\ts[\"%M\"] = (min < 10) ? (\"0\" + min) : min; // minute, range 00 to 59\n\ts[\"%n\"] = \"\\n\";\t\t// a newline character\n\ts[\"%p\"] = pm ? \"PM\" : \"AM\";\n\ts[\"%P\"] = pm ? \"pm\" : \"am\";\n\t// FIXME: %r : the time in am/pm notation %I:%M:%S %p\n\t// FIXME: %R : the time in 24-hour notation %H:%M\n\ts[\"%s\"] = Math.floor(this.getTime() / 1000);\n\ts[\"%S\"] = (sec < 10) ? (\"0\" + sec) : sec; // seconds, range 00 to 59\n\ts[\"%t\"] = \"\\t\";\t\t// a tab character\n\t// FIXME: %T : the time in 24-hour notation (%H:%M:%S)\n\ts[\"%U\"] = s[\"%W\"] = s[\"%V\"] = (wn < 10) ? (\"0\" + wn) : wn;\n\ts[\"%u\"] = w + 1;\t// the day of the week (range 1 to 7, 1 = MON)\n\ts[\"%w\"] = w;\t\t// the day of the week (range 0 to 6, 0 = SUN)\n\t// FIXME: %x : preferred date representation for the current locale without the time\n\t// FIXME: %X : preferred time representation for the current locale without the date\n\ts[\"%y\"] = ('' + y).substr(2, 2); // year without the century (range 00 to 99)\n\ts[\"%Y\"] = y;\t\t// year with the century\n\ts[\"%%\"] = \"%\";\t\t// a literal '%' character\n\n\tvar re = /%./g;\n\tif (!Calendar.is_ie5 && !Calendar.is_khtml)\n\t\treturn str.replace(re, function (par) { return s[par] || par; });\n\n\tvar a = str.match(re);\n\tfor (var i = 0; i < a.length; i++) {\n\t\tvar tmp = s[a[i]];\n\t\tif (tmp) {\n\t\t\tre = new RegExp(a[i], 'g');\n\t\t\tstr = str.replace(re, tmp);\n\t\t}\n\t}\n\n\treturn str;\n};\n\nDate.prototype.__msh_oldSetFullYear = Date.prototype.setFullYear;\nDate.prototype.setFullYear = function(y) {\n\tvar d = new Date(this);\n\td.__msh_oldSetFullYear(y);\n\tif (d.getMonth() != this.getMonth())\n\t\tthis.setDate(28);\n\tthis.__msh_oldSetFullYear(y);\n};\n\n// END: DATE OBJECT PATCHES\n\n\n// global object that remembers the calendar\nwindow._dynarch_popupCalendar = null;\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/calendar_stripped.js",
    "content": "/*  Copyright Mihai Bazon, 2002-2005  |  www.bazon.net/mishoo\n * -----------------------------------------------------------\n *\n * The DHTML Calendar, version 1.0 \"It is happening again\"\n *\n * Details and latest version at:\n * www.dynarch.com/projects/calendar\n *\n * This script is developed by Dynarch.com.  Visit us at www.dynarch.com.\n *\n * This script is distributed under the GNU Lesser General Public License.\n * Read the entire license text here: http://www.gnu.org/licenses/lgpl.html\n */\n Calendar=function(firstDayOfWeek,dateStr,onSelected,onClose){this.activeDiv=null;this.currentDateEl=null;this.getDateStatus=null;this.getDateToolTip=null;this.getDateText=null;this.timeout=null;this.onSelected=onSelected||null;this.onClose=onClose||null;this.dragging=false;this.hidden=false;this.minYear=1970;this.maxYear=2050;this.dateFormat=Calendar._TT[\"DEF_DATE_FORMAT\"];this.ttDateFormat=Calendar._TT[\"TT_DATE_FORMAT\"];this.isPopup=true;this.weekNumbers=true;this.firstDayOfWeek=typeof firstDayOfWeek==\"number\"?firstDayOfWeek:Calendar._FD;this.showsOtherMonths=false;this.dateStr=dateStr;this.ar_days=null;this.showsTime=false;this.time24=true;this.yearStep=2;this.hiliteToday=true;this.multiple=null;this.table=null;this.element=null;this.tbody=null;this.firstdayname=null;this.monthsCombo=null;this.yearsCombo=null;this.hilitedMonth=null;this.activeMonth=null;this.hilitedYear=null;this.activeYear=null;this.dateClicked=false;if(typeof Calendar._SDN==\"undefined\"){if(typeof Calendar._SDN_len==\"undefined\")Calendar._SDN_len=3;var ar=new Array();for(var i=8;i>0;){ar[--i]=Calendar._DN[i].substr(0,Calendar._SDN_len);}Calendar._SDN=ar;if(typeof Calendar._SMN_len==\"undefined\")Calendar._SMN_len=3;ar=new Array();for(var i=12;i>0;){ar[--i]=Calendar._MN[i].substr(0,Calendar._SMN_len);}Calendar._SMN=ar;}};Calendar._C=null;Calendar.is_ie=(/msie/i.test(navigator.userAgent)&&!/opera/i.test(navigator.userAgent));Calendar.is_ie5=(Calendar.is_ie&&/msie 5\\.0/i.test(navigator.userAgent));Calendar.is_opera=/opera/i.test(navigator.userAgent);Calendar.is_khtml=/Konqueror|Safari|KHTML/i.test(navigator.userAgent);Calendar.getAbsolutePos=function(el){var SL=0,ST=0;var is_div=/^div$/i.test(el.tagName);if(is_div&&el.scrollLeft)SL=el.scrollLeft;if(is_div&&el.scrollTop)ST=el.scrollTop;var r={x:el.offsetLeft-SL,y:el.offsetTop-ST};if(el.offsetParent){var tmp=this.getAbsolutePos(el.offsetParent);r.x+=tmp.x;r.y+=tmp.y;}return r;};Calendar.isRelated=function(el,evt){var related=evt.relatedTarget;if(!related){var type=evt.type;if(type==\"mouseover\"){related=evt.fromElement;}else if(type==\"mouseout\"){related=evt.toElement;}}while(related){if(related==el){return true;}related=related.parentNode;}return false;};Calendar.removeClass=function(el,className){if(!(el&&el.className)){return;}var cls=el.className.split(\" \");var ar=new Array();for(var i=cls.length;i>0;){if(cls[--i]!=className){ar[ar.length]=cls[i];}}el.className=ar.join(\" \");};Calendar.addClass=function(el,className){Calendar.removeClass(el,className);el.className+=\" \"+className;};Calendar.getElement=function(ev){var f=Calendar.is_ie?window.event.srcElement:ev.currentTarget;while(f.nodeType!=1||/^div$/i.test(f.tagName))f=f.parentNode;return f;};Calendar.getTargetElement=function(ev){var f=Calendar.is_ie?window.event.srcElement:ev.target;while(f.nodeType!=1)f=f.parentNode;return f;};Calendar.stopEvent=function(ev){ev||(ev=window.event);if(Calendar.is_ie){ev.cancelBubble=true;ev.returnValue=false;}else{ev.preventDefault();ev.stopPropagation();}return false;};Calendar.addEvent=function(el,evname,func){if(el.attachEvent){el.attachEvent(\"on\"+evname,func);}else if(el.addEventListener){el.addEventListener(evname,func,true);}else{el[\"on\"+evname]=func;}};Calendar.removeEvent=function(el,evname,func){if(el.detachEvent){el.detachEvent(\"on\"+evname,func);}else if(el.removeEventListener){el.removeEventListener(evname,func,true);}else{el[\"on\"+evname]=null;}};Calendar.createElement=function(type,parent){var el=null;if(document.createElementNS){el=document.createElementNS(\"http://www.w3.org/1999/xhtml\",type);}else{el=document.createElement(type);}if(typeof parent!=\"undefined\"){parent.appendChild(el);}return el;};Calendar._add_evs=function(el){with(Calendar){addEvent(el,\"mouseover\",dayMouseOver);addEvent(el,\"mousedown\",dayMouseDown);addEvent(el,\"mouseout\",dayMouseOut);if(is_ie){addEvent(el,\"dblclick\",dayMouseDblClick);el.setAttribute(\"unselectable\",true);}}};Calendar.findMonth=function(el){if(typeof el.month!=\"undefined\"){return el;}else if(typeof el.parentNode.month!=\"undefined\"){return el.parentNode;}return null;};Calendar.findYear=function(el){if(typeof el.year!=\"undefined\"){return el;}else if(typeof el.parentNode.year!=\"undefined\"){return el.parentNode;}return null;};Calendar.showMonthsCombo=function(){var cal=Calendar._C;if(!cal){return false;}var cal=cal;var cd=cal.activeDiv;var mc=cal.monthsCombo;if(cal.hilitedMonth){Calendar.removeClass(cal.hilitedMonth,\"hilite\");}if(cal.activeMonth){Calendar.removeClass(cal.activeMonth,\"active\");}var mon=cal.monthsCombo.getElementsByTagName(\"div\")[cal.date.getMonth()];Calendar.addClass(mon,\"active\");cal.activeMonth=mon;var s=mc.style;s.display=\"block\";if(cd.navtype<0)s.left=cd.offsetLeft+\"px\";else{var mcw=mc.offsetWidth;if(typeof mcw==\"undefined\")mcw=50;s.left=(cd.offsetLeft+cd.offsetWidth-mcw)+\"px\";}s.top=(cd.offsetTop+cd.offsetHeight)+\"px\";};Calendar.showYearsCombo=function(fwd){var cal=Calendar._C;if(!cal){return false;}var cal=cal;var cd=cal.activeDiv;var yc=cal.yearsCombo;if(cal.hilitedYear){Calendar.removeClass(cal.hilitedYear,\"hilite\");}if(cal.activeYear){Calendar.removeClass(cal.activeYear,\"active\");}cal.activeYear=null;var Y=cal.date.getFullYear()+(fwd?1:-1);var yr=yc.firstChild;var show=false;for(var i=12;i>0;--i){if(Y>=cal.minYear&&Y<=cal.maxYear){yr.innerHTML=Y;yr.year=Y;yr.style.display=\"block\";show=true;}else{yr.style.display=\"none\";}yr=yr.nextSibling;Y+=fwd?cal.yearStep:-cal.yearStep;}if(show){var s=yc.style;s.display=\"block\";if(cd.navtype<0)s.left=cd.offsetLeft+\"px\";else{var ycw=yc.offsetWidth;if(typeof ycw==\"undefined\")ycw=50;s.left=(cd.offsetLeft+cd.offsetWidth-ycw)+\"px\";}s.top=(cd.offsetTop+cd.offsetHeight)+\"px\";}};Calendar.tableMouseUp=function(ev){var cal=Calendar._C;if(!cal){return false;}if(cal.timeout){clearTimeout(cal.timeout);}var el=cal.activeDiv;if(!el){return false;}var target=Calendar.getTargetElement(ev);ev||(ev=window.event);Calendar.removeClass(el,\"active\");if(target==el||target.parentNode==el){Calendar.cellClick(el,ev);}var mon=Calendar.findMonth(target);var date=null;if(mon){date=new Date(cal.date);if(mon.month!=date.getMonth()){date.setMonth(mon.month);cal.setDate(date);cal.dateClicked=false;cal.callHandler();}}else{var year=Calendar.findYear(target);if(year){date=new Date(cal.date);if(year.year!=date.getFullYear()){date.setFullYear(year.year);cal.setDate(date);cal.dateClicked=false;cal.callHandler();}}}with(Calendar){removeEvent(document,\"mouseup\",tableMouseUp);removeEvent(document,\"mouseover\",tableMouseOver);removeEvent(document,\"mousemove\",tableMouseOver);cal._hideCombos();_C=null;return stopEvent(ev);}};Calendar.tableMouseOver=function(ev){var cal=Calendar._C;if(!cal){return;}var el=cal.activeDiv;var target=Calendar.getTargetElement(ev);if(target==el||target.parentNode==el){Calendar.addClass(el,\"hilite active\");Calendar.addClass(el.parentNode,\"rowhilite\");}else{if(typeof el.navtype==\"undefined\"||(el.navtype!=50&&(el.navtype==0||Math.abs(el.navtype)>2)))Calendar.removeClass(el,\"active\");Calendar.removeClass(el,\"hilite\");Calendar.removeClass(el.parentNode,\"rowhilite\");}ev||(ev=window.event);if(el.navtype==50&&target!=el){var pos=Calendar.getAbsolutePos(el);var w=el.offsetWidth;var x=ev.clientX;var dx;var decrease=true;if(x>pos.x+w){dx=x-pos.x-w;decrease=false;}else dx=pos.x-x;if(dx<0)dx=0;var range=el._range;var current=el._current;var count=Math.floor(dx/10)%range.length;for(var i=range.length;--i>=0;)if(range[i]==current)break;while(count-->0)if(decrease){if(--i<0)i=range.length-1;}else if(++i>=range.length)i=0;var newval=range[i];el.innerHTML=newval;cal.onUpdateTime();}var mon=Calendar.findMonth(target);if(mon){if(mon.month!=cal.date.getMonth()){if(cal.hilitedMonth){Calendar.removeClass(cal.hilitedMonth,\"hilite\");}Calendar.addClass(mon,\"hilite\");cal.hilitedMonth=mon;}else if(cal.hilitedMonth){Calendar.removeClass(cal.hilitedMonth,\"hilite\");}}else{if(cal.hilitedMonth){Calendar.removeClass(cal.hilitedMonth,\"hilite\");}var year=Calendar.findYear(target);if(year){if(year.year!=cal.date.getFullYear()){if(cal.hilitedYear){Calendar.removeClass(cal.hilitedYear,\"hilite\");}Calendar.addClass(year,\"hilite\");cal.hilitedYear=year;}else if(cal.hilitedYear){Calendar.removeClass(cal.hilitedYear,\"hilite\");}}else if(cal.hilitedYear){Calendar.removeClass(cal.hilitedYear,\"hilite\");}}return Calendar.stopEvent(ev);};Calendar.tableMouseDown=function(ev){if(Calendar.getTargetElement(ev)==Calendar.getElement(ev)){return Calendar.stopEvent(ev);}};Calendar.calDragIt=function(ev){var cal=Calendar._C;if(!(cal&&cal.dragging)){return false;}var posX;var posY;if(Calendar.is_ie){posY=window.event.clientY+document.body.scrollTop;posX=window.event.clientX+document.body.scrollLeft;}else{posX=ev.pageX;posY=ev.pageY;}cal.hideShowCovered();var st=cal.element.style;st.left=(posX-cal.xOffs)+\"px\";st.top=(posY-cal.yOffs)+\"px\";return Calendar.stopEvent(ev);};Calendar.calDragEnd=function(ev){var cal=Calendar._C;if(!cal){return false;}cal.dragging=false;with(Calendar){removeEvent(document,\"mousemove\",calDragIt);removeEvent(document,\"mouseup\",calDragEnd);tableMouseUp(ev);}cal.hideShowCovered();};Calendar.dayMouseDown=function(ev){var el=Calendar.getElement(ev);if(el.disabled){return false;}var cal=el.calendar;cal.activeDiv=el;Calendar._C=cal;if(el.navtype!=300)with(Calendar){if(el.navtype==50){el._current=el.innerHTML;addEvent(document,\"mousemove\",tableMouseOver);}else addEvent(document,Calendar.is_ie5?\"mousemove\":\"mouseover\",tableMouseOver);addClass(el,\"hilite active\");addEvent(document,\"mouseup\",tableMouseUp);}else if(cal.isPopup){cal._dragStart(ev);}if(el.navtype==-1||el.navtype==1){if(cal.timeout)clearTimeout(cal.timeout);cal.timeout=setTimeout(\"Calendar.showMonthsCombo()\",250);}else if(el.navtype==-2||el.navtype==2){if(cal.timeout)clearTimeout(cal.timeout);cal.timeout=setTimeout((el.navtype>0)?\"Calendar.showYearsCombo(true)\":\"Calendar.showYearsCombo(false)\",250);}else{cal.timeout=null;}return Calendar.stopEvent(ev);};Calendar.dayMouseDblClick=function(ev){Calendar.cellClick(Calendar.getElement(ev),ev||window.event);if(Calendar.is_ie){document.selection.empty();}};Calendar.dayMouseOver=function(ev){var el=Calendar.getElement(ev);if(Calendar.isRelated(el,ev)||Calendar._C||el.disabled){return false;}if(el.ttip){if(el.ttip.substr(0,1)==\"_\"){el.ttip=el.caldate.print(el.calendar.ttDateFormat)+el.ttip.substr(1);}el.calendar.tooltips.innerHTML=el.ttip;}if(el.navtype!=300){Calendar.addClass(el,\"hilite\");if(el.caldate){Calendar.addClass(el.parentNode,\"rowhilite\");}}return Calendar.stopEvent(ev);};Calendar.dayMouseOut=function(ev){with(Calendar){var el=getElement(ev);if(isRelated(el,ev)||_C||el.disabled)return false;removeClass(el,\"hilite\");if(el.caldate)removeClass(el.parentNode,\"rowhilite\");if(el.calendar)el.calendar.tooltips.innerHTML=_TT[\"SEL_DATE\"];return stopEvent(ev);}};Calendar.cellClick=function(el,ev){var cal=el.calendar;var closing=false;var newdate=false;var date=null;if(typeof el.navtype==\"undefined\"){if(cal.currentDateEl){Calendar.removeClass(cal.currentDateEl,\"selected\");Calendar.addClass(el,\"selected\");closing=(cal.currentDateEl==el);if(!closing){cal.currentDateEl=el;}}cal.date.setDateOnly(el.caldate);date=cal.date;var other_month=!(cal.dateClicked=!el.otherMonth);if(!other_month&&!cal.currentDateEl)cal._toggleMultipleDate(new Date(date));else newdate=!el.disabled;if(other_month)cal._init(cal.firstDayOfWeek,date);}else{if(el.navtype==200){Calendar.removeClass(el,\"hilite\");cal.callCloseHandler();return;}date=new Date(cal.date);if(el.navtype==0)date.setDateOnly(new Date());cal.dateClicked=false;var year=date.getFullYear();var mon=date.getMonth();function setMonth(m){var day=date.getDate();var max=date.getMonthDays(m);if(day>max){date.setDate(max);}date.setMonth(m);};switch(el.navtype){case 400:Calendar.removeClass(el,\"hilite\");var text=Calendar._TT[\"ABOUT\"];if(typeof text!=\"undefined\"){text+=cal.showsTime?Calendar._TT[\"ABOUT_TIME\"]:\"\";}else{text=\"Help and about box text is not translated into this language.\\n\"+\"If you know this language and you feel generous please update\\n\"+\"the corresponding file in \\\"lang\\\" subdir to match calendar-en.js\\n\"+\"and send it back to <mihai_bazon@yahoo.com> to get it into the distribution  ;-)\\n\\n\"+\"Thank you!\\n\"+\"http://dynarch.com/mishoo/calendar.epl\\n\";}alert(text);return;case-2:if(year>cal.minYear){date.setFullYear(year-1);}break;case-1:if(mon>0){setMonth(mon-1);}else if(year-->cal.minYear){date.setFullYear(year);setMonth(11);}break;case 1:if(mon<11){setMonth(mon+1);}else if(year<cal.maxYear){date.setFullYear(year+1);setMonth(0);}break;case 2:if(year<cal.maxYear){date.setFullYear(year+1);}break;case 100:cal.setFirstDayOfWeek(el.fdow);return;case 50:var range=el._range;var current=el.innerHTML;for(var i=range.length;--i>=0;)if(range[i]==current)break;if(ev&&ev.shiftKey){if(--i<0)i=range.length-1;}else if(++i>=range.length)i=0;var newval=range[i];el.innerHTML=newval;cal.onUpdateTime();return;case 0:if((typeof cal.getDateStatus==\"function\")&&cal.getDateStatus(date,date.getFullYear(),date.getMonth(),date.getDate())){return false;}break;}if(!date.equalsTo(cal.date)){cal.setDate(date);newdate=true;}else if(el.navtype==0)newdate=closing=true;}if(newdate){ev&&cal.callHandler();}if(closing){Calendar.removeClass(el,\"hilite\");ev&&cal.callCloseHandler();}};Calendar.prototype.create=function(_par){var parent=null;if(!_par){parent=document.getElementsByTagName(\"body\")[0];this.isPopup=true;}else{parent=_par;this.isPopup=false;}this.date=this.dateStr?new Date(this.dateStr):new Date();var table=Calendar.createElement(\"table\");this.table=table;table.cellSpacing=0;table.cellPadding=0;table.calendar=this;Calendar.addEvent(table,\"mousedown\",Calendar.tableMouseDown);var div=Calendar.createElement(\"div\");this.element=div;div.className=\"calendar\";if(this.isPopup){div.style.position=\"absolute\";div.style.display=\"none\";}div.appendChild(table);var thead=Calendar.createElement(\"thead\",table);var cell=null;var row=null;var cal=this;var hh=function(text,cs,navtype){cell=Calendar.createElement(\"td\",row);cell.colSpan=cs;cell.className=\"button\";if(navtype!=0&&Math.abs(navtype)<=2)cell.className+=\" nav\";Calendar._add_evs(cell);cell.calendar=cal;cell.navtype=navtype;cell.innerHTML=\"<div unselectable='on'>\"+text+\"</div>\";return cell;};row=Calendar.createElement(\"tr\",thead);var title_length=6;(this.isPopup)&&--title_length;(this.weekNumbers)&&++title_length;hh(\"?\",1,400).ttip=Calendar._TT[\"INFO\"];this.title=hh(\"\",title_length,300);this.title.className=\"title\";if(this.isPopup){this.title.ttip=Calendar._TT[\"DRAG_TO_MOVE\"];this.title.style.cursor=\"move\";hh(\"&#x00d7;\",1,200).ttip=Calendar._TT[\"CLOSE\"];}row=Calendar.createElement(\"tr\",thead);row.className=\"headrow\";this._nav_py=hh(\"&#x00ab;\",1,-2);this._nav_py.ttip=Calendar._TT[\"PREV_YEAR\"];this._nav_pm=hh(\"&#x2039;\",1,-1);this._nav_pm.ttip=Calendar._TT[\"PREV_MONTH\"];this._nav_now=hh(Calendar._TT[\"TODAY\"],this.weekNumbers?4:3,0);this._nav_now.ttip=Calendar._TT[\"GO_TODAY\"];this._nav_nm=hh(\"&#x203a;\",1,1);this._nav_nm.ttip=Calendar._TT[\"NEXT_MONTH\"];this._nav_ny=hh(\"&#x00bb;\",1,2);this._nav_ny.ttip=Calendar._TT[\"NEXT_YEAR\"];row=Calendar.createElement(\"tr\",thead);row.className=\"daynames\";if(this.weekNumbers){cell=Calendar.createElement(\"td\",row);cell.className=\"name wn\";cell.innerHTML=Calendar._TT[\"WK\"];}for(var i=7;i>0;--i){cell=Calendar.createElement(\"td\",row);if(!i){cell.navtype=100;cell.calendar=this;Calendar._add_evs(cell);}}this.firstdayname=(this.weekNumbers)?row.firstChild.nextSibling:row.firstChild;this._displayWeekdays();var tbody=Calendar.createElement(\"tbody\",table);this.tbody=tbody;for(i=6;i>0;--i){row=Calendar.createElement(\"tr\",tbody);if(this.weekNumbers){cell=Calendar.createElement(\"td\",row);}for(var j=7;j>0;--j){cell=Calendar.createElement(\"td\",row);cell.calendar=this;Calendar._add_evs(cell);}}if(this.showsTime){row=Calendar.createElement(\"tr\",tbody);row.className=\"time\";cell=Calendar.createElement(\"td\",row);cell.className=\"time\";cell.colSpan=2;cell.innerHTML=Calendar._TT[\"TIME\"]||\"&nbsp;\";cell=Calendar.createElement(\"td\",row);cell.className=\"time\";cell.colSpan=this.weekNumbers?4:3;(function(){function makeTimePart(className,init,range_start,range_end){var part=Calendar.createElement(\"span\",cell);part.className=className;part.innerHTML=init;part.calendar=cal;part.ttip=Calendar._TT[\"TIME_PART\"];part.navtype=50;part._range=[];if(typeof range_start!=\"number\")part._range=range_start;else{for(var i=range_start;i<=range_end;++i){var txt;if(i<10&&range_end>=10)txt='0'+i;else txt=''+i;part._range[part._range.length]=txt;}}Calendar._add_evs(part);return part;};var hrs=cal.date.getHours();var mins=cal.date.getMinutes();var t12=!cal.time24;var pm=(hrs>12);if(t12&&pm)hrs-=12;var H=makeTimePart(\"hour\",hrs,t12?1:0,t12?12:23);var span=Calendar.createElement(\"span\",cell);span.innerHTML=\":\";span.className=\"colon\";var M=makeTimePart(\"minute\",mins,0,59);var AP=null;cell=Calendar.createElement(\"td\",row);cell.className=\"time\";cell.colSpan=2;if(t12)AP=makeTimePart(\"ampm\",pm?\"pm\":\"am\",[\"am\",\"pm\"]);else cell.innerHTML=\"&nbsp;\";cal.onSetTime=function(){var pm,hrs=this.date.getHours(),mins=this.date.getMinutes();if(t12){pm=(hrs>=12);if(pm)hrs-=12;if(hrs==0)hrs=12;AP.innerHTML=pm?\"pm\":\"am\";}H.innerHTML=(hrs<10)?(\"0\"+hrs):hrs;M.innerHTML=(mins<10)?(\"0\"+mins):mins;};cal.onUpdateTime=function(){var date=this.date;var h=parseInt(H.innerHTML,10);if(t12){if(/pm/i.test(AP.innerHTML)&&h<12)h+=12;else if(/am/i.test(AP.innerHTML)&&h==12)h=0;}var d=date.getDate();var m=date.getMonth();var y=date.getFullYear();date.setHours(h);date.setMinutes(parseInt(M.innerHTML,10));date.setFullYear(y);date.setMonth(m);date.setDate(d);this.dateClicked=false;this.callHandler();};})();}else{this.onSetTime=this.onUpdateTime=function(){};}var tfoot=Calendar.createElement(\"tfoot\",table);row=Calendar.createElement(\"tr\",tfoot);row.className=\"footrow\";cell=hh(Calendar._TT[\"SEL_DATE\"],this.weekNumbers?8:7,300);cell.className=\"ttip\";if(this.isPopup){cell.ttip=Calendar._TT[\"DRAG_TO_MOVE\"];cell.style.cursor=\"move\";}this.tooltips=cell;div=Calendar.createElement(\"div\",this.element);this.monthsCombo=div;div.className=\"combo\";for(i=0;i<Calendar._MN.length;++i){var mn=Calendar.createElement(\"div\");mn.className=Calendar.is_ie?\"label-IEfix\":\"label\";mn.month=i;mn.innerHTML=Calendar._SMN[i];div.appendChild(mn);}div=Calendar.createElement(\"div\",this.element);this.yearsCombo=div;div.className=\"combo\";for(i=12;i>0;--i){var yr=Calendar.createElement(\"div\");yr.className=Calendar.is_ie?\"label-IEfix\":\"label\";div.appendChild(yr);}this._init(this.firstDayOfWeek,this.date);parent.appendChild(this.element);};Calendar._keyEvent=function(ev){var cal=window._dynarch_popupCalendar;if(!cal||cal.multiple)return false;(Calendar.is_ie)&&(ev=window.event);var act=(Calendar.is_ie||ev.type==\"keypress\"),K=ev.keyCode;if(ev.ctrlKey){switch(K){case 37:act&&Calendar.cellClick(cal._nav_pm);break;case 38:act&&Calendar.cellClick(cal._nav_py);break;case 39:act&&Calendar.cellClick(cal._nav_nm);break;case 40:act&&Calendar.cellClick(cal._nav_ny);break;default:return false;}}else switch(K){case 32:Calendar.cellClick(cal._nav_now);break;case 27:act&&cal.callCloseHandler();break;case 37:case 38:case 39:case 40:if(act){var prev,x,y,ne,el,step;prev=K==37||K==38;step=(K==37||K==39)?1:7;function setVars(){el=cal.currentDateEl;var p=el.pos;x=p&15;y=p>>4;ne=cal.ar_days[y][x];};setVars();function prevMonth(){var date=new Date(cal.date);date.setDate(date.getDate()-step);cal.setDate(date);};function nextMonth(){var date=new Date(cal.date);date.setDate(date.getDate()+step);cal.setDate(date);};while(1){switch(K){case 37:if(--x>=0)ne=cal.ar_days[y][x];else{x=6;K=38;continue;}break;case 38:if(--y>=0)ne=cal.ar_days[y][x];else{prevMonth();setVars();}break;case 39:if(++x<7)ne=cal.ar_days[y][x];else{x=0;K=40;continue;}break;case 40:if(++y<cal.ar_days.length)ne=cal.ar_days[y][x];else{nextMonth();setVars();}break;}break;}if(ne){if(!ne.disabled)Calendar.cellClick(ne);else if(prev)prevMonth();else nextMonth();}}break;case 13:if(act)Calendar.cellClick(cal.currentDateEl,ev);break;default:return false;}return Calendar.stopEvent(ev);};Calendar.prototype._init=function(firstDayOfWeek,date){var today=new Date(),TY=today.getFullYear(),TM=today.getMonth(),TD=today.getDate();this.table.style.visibility=\"hidden\";var year=date.getFullYear();if(year<this.minYear){year=this.minYear;date.setFullYear(year);}else if(year>this.maxYear){year=this.maxYear;date.setFullYear(year);}this.firstDayOfWeek=firstDayOfWeek;this.date=new Date(date);var month=date.getMonth();var mday=date.getDate();var no_days=date.getMonthDays();date.setDate(1);var day1=(date.getDay()-this.firstDayOfWeek)%7;if(day1<0)day1+=7;date.setDate(-day1);date.setDate(date.getDate()+1);var row=this.tbody.firstChild;var MN=Calendar._SMN[month];var ar_days=this.ar_days=new Array();var weekend=Calendar._TT[\"WEEKEND\"];var dates=this.multiple?(this.datesCells={}):null;for(var i=0;i<6;++i,row=row.nextSibling){var cell=row.firstChild;if(this.weekNumbers){cell.className=\"day wn\";cell.innerHTML=date.getWeekNumber();cell=cell.nextSibling;}row.className=\"daysrow\";var hasdays=false,iday,dpos=ar_days[i]=[];for(var j=0;j<7;++j,cell=cell.nextSibling,date.setDate(iday+1)){iday=date.getDate();var wday=date.getDay();cell.className=\"day\";cell.pos=i<<4|j;dpos[j]=cell;var current_month=(date.getMonth()==month);if(!current_month){if(this.showsOtherMonths){cell.className+=\" othermonth\";cell.otherMonth=true;}else{cell.className=\"emptycell\";cell.innerHTML=\"&nbsp;\";cell.disabled=true;continue;}}else{cell.otherMonth=false;hasdays=true;}cell.disabled=false;cell.innerHTML=this.getDateText?this.getDateText(date,iday):iday;if(dates)dates[date.print(\"%Y%m%d\")]=cell;if(this.getDateStatus){var status=this.getDateStatus(date,year,month,iday);if(this.getDateToolTip){var toolTip=this.getDateToolTip(date,year,month,iday);if(toolTip)cell.title=toolTip;}if(status===true){cell.className+=\" disabled\";cell.disabled=true;}else{if(/disabled/i.test(status))cell.disabled=true;cell.className+=\" \"+status;}}if(!cell.disabled){cell.caldate=new Date(date);cell.ttip=\"_\";if(!this.multiple&&current_month&&iday==mday&&this.hiliteToday){cell.className+=\" selected\";this.currentDateEl=cell;}if(date.getFullYear()==TY&&date.getMonth()==TM&&iday==TD){cell.className+=\" today\";cell.ttip+=Calendar._TT[\"PART_TODAY\"];}if(weekend.indexOf(wday.toString())!=-1)cell.className+=cell.otherMonth?\" oweekend\":\" weekend\";}}if(!(hasdays||this.showsOtherMonths))row.className=\"emptyrow\";}this.title.innerHTML=Calendar._MN[month]+\", \"+year;this.onSetTime();this.table.style.visibility=\"visible\";this._initMultipleDates();};Calendar.prototype._initMultipleDates=function(){if(this.multiple){for(var i in this.multiple){var cell=this.datesCells[i];var d=this.multiple[i];if(!d)continue;if(cell)cell.className+=\" selected\";}}};Calendar.prototype._toggleMultipleDate=function(date){if(this.multiple){var ds=date.print(\"%Y%m%d\");var cell=this.datesCells[ds];if(cell){var d=this.multiple[ds];if(!d){Calendar.addClass(cell,\"selected\");this.multiple[ds]=date;}else{Calendar.removeClass(cell,\"selected\");delete this.multiple[ds];}}}};Calendar.prototype.setDateToolTipHandler=function(unaryFunction){this.getDateToolTip=unaryFunction;};Calendar.prototype.setDate=function(date){if(!date.equalsTo(this.date)){this._init(this.firstDayOfWeek,date);}};Calendar.prototype.refresh=function(){this._init(this.firstDayOfWeek,this.date);};Calendar.prototype.setFirstDayOfWeek=function(firstDayOfWeek){this._init(firstDayOfWeek,this.date);this._displayWeekdays();};Calendar.prototype.setDateStatusHandler=Calendar.prototype.setDisabledHandler=function(unaryFunction){this.getDateStatus=unaryFunction;};Calendar.prototype.setRange=function(a,z){this.minYear=a;this.maxYear=z;};Calendar.prototype.callHandler=function(){if(this.onSelected){this.onSelected(this,this.date.print(this.dateFormat));}};Calendar.prototype.callCloseHandler=function(){if(this.onClose){this.onClose(this);}this.hideShowCovered();};Calendar.prototype.destroy=function(){var el=this.element.parentNode;el.removeChild(this.element);Calendar._C=null;window._dynarch_popupCalendar=null;};Calendar.prototype.reparent=function(new_parent){var el=this.element;el.parentNode.removeChild(el);new_parent.appendChild(el);};Calendar._checkCalendar=function(ev){var calendar=window._dynarch_popupCalendar;if(!calendar){return false;}var el=Calendar.is_ie?Calendar.getElement(ev):Calendar.getTargetElement(ev);for(;el!=null&&el!=calendar.element;el=el.parentNode);if(el==null){window._dynarch_popupCalendar.callCloseHandler();return Calendar.stopEvent(ev);}};Calendar.prototype.show=function(){var rows=this.table.getElementsByTagName(\"tr\");for(var i=rows.length;i>0;){var row=rows[--i];Calendar.removeClass(row,\"rowhilite\");var cells=row.getElementsByTagName(\"td\");for(var j=cells.length;j>0;){var cell=cells[--j];Calendar.removeClass(cell,\"hilite\");Calendar.removeClass(cell,\"active\");}}this.element.style.display=\"block\";this.hidden=false;if(this.isPopup){window._dynarch_popupCalendar=this;Calendar.addEvent(document,\"keydown\",Calendar._keyEvent);Calendar.addEvent(document,\"keypress\",Calendar._keyEvent);Calendar.addEvent(document,\"mousedown\",Calendar._checkCalendar);}this.hideShowCovered();};Calendar.prototype.hide=function(){if(this.isPopup){Calendar.removeEvent(document,\"keydown\",Calendar._keyEvent);Calendar.removeEvent(document,\"keypress\",Calendar._keyEvent);Calendar.removeEvent(document,\"mousedown\",Calendar._checkCalendar);}this.element.style.display=\"none\";this.hidden=true;this.hideShowCovered();};Calendar.prototype.showAt=function(x,y){var s=this.element.style;s.left=x+\"px\";s.top=y+\"px\";this.show();};Calendar.prototype.showAtElement=function(el,opts){var self=this;var p=Calendar.getAbsolutePos(el);if(!opts||typeof opts!=\"string\"){this.showAt(p.x,p.y+el.offsetHeight);return true;}function fixPosition(box){if(box.x<0)box.x=0;if(box.y<0)box.y=0;var cp=document.createElement(\"div\");var s=cp.style;s.position=\"absolute\";s.right=s.bottom=s.width=s.height=\"0px\";document.body.appendChild(cp);var br=Calendar.getAbsolutePos(cp);document.body.removeChild(cp);if(Calendar.is_ie){br.y+=document.body.scrollTop;br.x+=document.body.scrollLeft;}else{br.y+=window.scrollY;br.x+=window.scrollX;}var tmp=box.x+box.width-br.x;if(tmp>0)box.x-=tmp;tmp=box.y+box.height-br.y;if(tmp>0)box.y-=tmp;};this.element.style.display=\"block\";Calendar.continuation_for_the_fucking_khtml_browser=function(){var w=self.element.offsetWidth;var h=self.element.offsetHeight;self.element.style.display=\"none\";var valign=opts.substr(0,1);var halign=\"l\";if(opts.length>1){halign=opts.substr(1,1);}switch(valign){case \"T\":p.y-=h;break;case \"B\":p.y+=el.offsetHeight;break;case \"C\":p.y+=(el.offsetHeight-h)/2;break;case \"t\":p.y+=el.offsetHeight-h;break;case \"b\":break;}switch(halign){case \"L\":p.x-=w;break;case \"R\":p.x+=el.offsetWidth;break;case \"C\":p.x+=(el.offsetWidth-w)/2;break;case \"l\":p.x+=el.offsetWidth-w;break;case \"r\":break;}p.width=w;p.height=h+40;self.monthsCombo.style.display=\"none\";fixPosition(p);self.showAt(p.x,p.y);};if(Calendar.is_khtml)setTimeout(\"Calendar.continuation_for_the_fucking_khtml_browser()\",10);else Calendar.continuation_for_the_fucking_khtml_browser();};Calendar.prototype.setDateFormat=function(str){this.dateFormat=str;};Calendar.prototype.setTtDateFormat=function(str){this.ttDateFormat=str;};Calendar.prototype.parseDate=function(str,fmt){if(!fmt)fmt=this.dateFormat;this.setDate(Date.parseDate(str,fmt));};Calendar.prototype.hideShowCovered=function(){if(!Calendar.is_ie&&!Calendar.is_opera)return;function getVisib(obj){var value=obj.style.visibility;if(!value){if(document.defaultView&&typeof(document.defaultView.getComputedStyle)==\"function\"){if(!Calendar.is_khtml)value=document.defaultView. getComputedStyle(obj,\"\").getPropertyValue(\"visibility\");else value='';}else if(obj.currentStyle){value=obj.currentStyle.visibility;}else value='';}return value;};var tags=new Array(\"applet\",\"iframe\",\"select\");var el=this.element;var p=Calendar.getAbsolutePos(el);var EX1=p.x;var EX2=el.offsetWidth+EX1;var EY1=p.y;var EY2=el.offsetHeight+EY1;for(var k=tags.length;k>0;){var ar=document.getElementsByTagName(tags[--k]);var cc=null;for(var i=ar.length;i>0;){cc=ar[--i];p=Calendar.getAbsolutePos(cc);var CX1=p.x;var CX2=cc.offsetWidth+CX1;var CY1=p.y;var CY2=cc.offsetHeight+CY1;if(this.hidden||(CX1>EX2)||(CX2<EX1)||(CY1>EY2)||(CY2<EY1)){if(!cc.__msh_save_visibility){cc.__msh_save_visibility=getVisib(cc);}cc.style.visibility=cc.__msh_save_visibility;}else{if(!cc.__msh_save_visibility){cc.__msh_save_visibility=getVisib(cc);}cc.style.visibility=\"hidden\";}}}};Calendar.prototype._displayWeekdays=function(){var fdow=this.firstDayOfWeek;var cell=this.firstdayname;var weekend=Calendar._TT[\"WEEKEND\"];for(var i=0;i<7;++i){cell.className=\"day name\";var realday=(i+fdow)%7;if(i){cell.ttip=Calendar._TT[\"DAY_FIRST\"].replace(\"%s\",Calendar._DN[realday]);cell.navtype=100;cell.calendar=this;cell.fdow=realday;Calendar._add_evs(cell);}if(weekend.indexOf(realday.toString())!=-1){Calendar.addClass(cell,\"weekend\");}cell.innerHTML=Calendar._SDN[(i+fdow)%7];cell=cell.nextSibling;}};Calendar.prototype._hideCombos=function(){this.monthsCombo.style.display=\"none\";this.yearsCombo.style.display=\"none\";};Calendar.prototype._dragStart=function(ev){if(this.dragging){return;}this.dragging=true;var posX;var posY;if(Calendar.is_ie){posY=window.event.clientY+document.body.scrollTop;posX=window.event.clientX+document.body.scrollLeft;}else{posY=ev.clientY+window.scrollY;posX=ev.clientX+window.scrollX;}var st=this.element.style;this.xOffs=posX-parseInt(st.left);this.yOffs=posY-parseInt(st.top);with(Calendar){addEvent(document,\"mousemove\",calDragIt);addEvent(document,\"mouseup\",calDragEnd);}};Date._MD=new Array(31,28,31,30,31,30,31,31,30,31,30,31);Date.SECOND=1000;Date.MINUTE=60*Date.SECOND;Date.HOUR=60*Date.MINUTE;Date.DAY=24*Date.HOUR;Date.WEEK=7*Date.DAY;Date.parseDate=function(str,fmt){var today=new Date();var y=0;var m=-1;var d=0;var a=str.split(/\\W+/);var b=fmt.match(/%./g);var i=0,j=0;var hr=0;var min=0;for(i=0;i<a.length;++i){if(!a[i])continue;switch(b[i]){case \"%d\":case \"%e\":d=parseInt(a[i],10);break;case \"%m\":m=parseInt(a[i],10)-1;break;case \"%Y\":case \"%y\":y=parseInt(a[i],10);(y<100)&&(y+=(y>29)?1900:2000);break;case \"%b\":case \"%B\":for(j=0;j<12;++j){if(Calendar._MN[j].substr(0,a[i].length).toLowerCase()==a[i].toLowerCase()){m=j;break;}}break;case \"%H\":case \"%I\":case \"%k\":case \"%l\":hr=parseInt(a[i],10);break;case \"%P\":case \"%p\":if(/pm/i.test(a[i])&&hr<12)hr+=12;else if(/am/i.test(a[i])&&hr>=12)hr-=12;break;case \"%M\":min=parseInt(a[i],10);break;}}if(isNaN(y))y=today.getFullYear();if(isNaN(m))m=today.getMonth();if(isNaN(d))d=today.getDate();if(isNaN(hr))hr=today.getHours();if(isNaN(min))min=today.getMinutes();if(y!=0&&m!=-1&&d!=0)return new Date(y,m,d,hr,min,0);y=0;m=-1;d=0;for(i=0;i<a.length;++i){if(a[i].search(/[a-zA-Z]+/)!=-1){var t=-1;for(j=0;j<12;++j){if(Calendar._MN[j].substr(0,a[i].length).toLowerCase()==a[i].toLowerCase()){t=j;break;}}if(t!=-1){if(m!=-1){d=m+1;}m=t;}}else if(parseInt(a[i],10)<=12&&m==-1){m=a[i]-1;}else if(parseInt(a[i],10)>31&&y==0){y=parseInt(a[i],10);(y<100)&&(y+=(y>29)?1900:2000);}else if(d==0){d=a[i];}}if(y==0)y=today.getFullYear();if(m!=-1&&d!=0)return new Date(y,m,d,hr,min,0);return today;};Date.prototype.getMonthDays=function(month){var year=this.getFullYear();if(typeof month==\"undefined\"){month=this.getMonth();}if(((0==(year%4))&&((0!=(year%100))||(0==(year%400))))&&month==1){return 29;}else{return Date._MD[month];}};Date.prototype.getDayOfYear=function(){var now=new Date(this.getFullYear(),this.getMonth(),this.getDate(),0,0,0);var then=new Date(this.getFullYear(),0,0,0,0,0);var time=now-then;return Math.floor(time/Date.DAY);};Date.prototype.getWeekNumber=function(){var d=new Date(this.getFullYear(),this.getMonth(),this.getDate(),0,0,0);var DoW=d.getDay();d.setDate(d.getDate()-(DoW+6)%7+3);var ms=d.valueOf();d.setMonth(0);d.setDate(4);return Math.round((ms-d.valueOf())/(7*864e5))+1;};Date.prototype.equalsTo=function(date){return((this.getFullYear()==date.getFullYear())&&(this.getMonth()==date.getMonth())&&(this.getDate()==date.getDate())&&(this.getHours()==date.getHours())&&(this.getMinutes()==date.getMinutes()));};Date.prototype.setDateOnly=function(date){var tmp=new Date(date);this.setDate(1);this.setFullYear(tmp.getFullYear());this.setMonth(tmp.getMonth());this.setDate(tmp.getDate());};Date.prototype.print=function(str){var m=this.getMonth();var d=this.getDate();var y=this.getFullYear();var wn=this.getWeekNumber();var w=this.getDay();var s={};var hr=this.getHours();var pm=(hr>=12);var ir=(pm)?(hr-12):hr;var dy=this.getDayOfYear();if(ir==0)ir=12;var min=this.getMinutes();var sec=this.getSeconds();s[\"%a\"]=Calendar._SDN[w];s[\"%A\"]=Calendar._DN[w];s[\"%b\"]=Calendar._SMN[m];s[\"%B\"]=Calendar._MN[m];s[\"%C\"]=1+Math.floor(y/100);s[\"%d\"]=(d<10)?(\"0\"+d):d;s[\"%e\"]=d;s[\"%H\"]=(hr<10)?(\"0\"+hr):hr;s[\"%I\"]=(ir<10)?(\"0\"+ir):ir;s[\"%j\"]=(dy<100)?((dy<10)?(\"00\"+dy):(\"0\"+dy)):dy;s[\"%k\"]=hr;s[\"%l\"]=ir;s[\"%m\"]=(m<9)?(\"0\"+(1+m)):(1+m);s[\"%M\"]=(min<10)?(\"0\"+min):min;s[\"%n\"]=\"\\n\";s[\"%p\"]=pm?\"PM\":\"AM\";s[\"%P\"]=pm?\"pm\":\"am\";s[\"%s\"]=Math.floor(this.getTime()/1000);s[\"%S\"]=(sec<10)?(\"0\"+sec):sec;s[\"%t\"]=\"\\t\";s[\"%U\"]=s[\"%W\"]=s[\"%V\"]=(wn<10)?(\"0\"+wn):wn;s[\"%u\"]=w+1;s[\"%w\"]=w;s[\"%y\"]=(''+y).substr(2,2);s[\"%Y\"]=y;s[\"%%\"]=\"%\";var re=/%./g;if(!Calendar.is_ie5&&!Calendar.is_khtml)return str.replace(re,function(par){return s[par]||par;});var a=str.match(re);for(var i=0;i<a.length;i++){var tmp=s[a[i]];if(tmp){re=new RegExp(a[i],'g');str=str.replace(re,tmp);}}return str;};Date.prototype.__msh_oldSetFullYear=Date.prototype.setFullYear;Date.prototype.setFullYear=function(y){var d=new Date(this);d.__msh_oldSetFullYear(y);if(d.getMonth()!=this.getMonth())this.setDate(28);this.__msh_oldSetFullYear(y);};window._dynarch_popupCalendar=null;"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/calendar-af.js",
    "content": "// ** I18N Afrikaans\nCalendar._DN = new Array\n(\"Sondag\",\n \"Maandag\",\n \"Dinsdag\",\n \"Woensdag\",\n \"Donderdag\",\n \"Vrydag\",\n \"Saterdag\",\n \"Sondag\");\nCalendar._MN = new Array\n(\"Januarie\",\n \"Februarie\",\n \"Maart\",\n \"April\",\n \"Mei\",\n \"Junie\",\n \"Julie\",\n \"Augustus\",\n \"September\",\n \"Oktober\",\n \"November\",\n \"Desember\");\n\n// tooltips\nCalendar._TT = {};\nCalendar._TT[\"TOGGLE\"] = \"Verander eerste dag van die week\";\nCalendar._TT[\"PREV_YEAR\"] = \"Vorige jaar (hou vir keuselys)\";\nCalendar._TT[\"PREV_MONTH\"] = \"Vorige maand (hou vir keuselys)\";\nCalendar._TT[\"GO_TODAY\"] = \"Gaan na vandag\";\nCalendar._TT[\"NEXT_MONTH\"] = \"Volgende maand (hou vir keuselys)\";\nCalendar._TT[\"NEXT_YEAR\"] = \"Volgende jaar (hou vir keuselys)\";\nCalendar._TT[\"SEL_DATE\"] = \"Kies datum\";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \"Sleep om te skuif\";\nCalendar._TT[\"PART_TODAY\"] = \" (vandag)\";\nCalendar._TT[\"MON_FIRST\"] = \"Vertoon Maandag eerste\";\nCalendar._TT[\"SUN_FIRST\"] = \"Display Sunday first\";\nCalendar._TT[\"CLOSE\"] = \"Close\";\nCalendar._TT[\"TODAY\"] = \"Today\";\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/calendar-al.js",
    "content": "// Calendar ALBANIAN language\n//author Rigels Gordani rige@hotmail.com\n\n// ditet\nCalendar._DN = new Array\n(\"E Diele\",\n\"E Hene\",\n\"E Marte\",\n\"E Merkure\",\n\"E Enjte\",\n\"E Premte\",\n\"E Shtune\",\n\"E Diele\");\n\n//ditet shkurt\nCalendar._SDN = new Array\n(\"Die\",\n\"Hen\",\n\"Mar\",\n\"Mer\",\n\"Enj\",\n\"Pre\",\n\"Sht\",\n\"Die\");\n\n// muajt\nCalendar._MN = new Array\n(\"Janar\",\n\"Shkurt\",\n\"Mars\",\n\"Prill\",\n\"Maj\",\n\"Qeshor\",\n\"Korrik\",\n\"Gusht\",\n\"Shtator\",\n\"Tetor\",\n\"Nentor\",\n\"Dhjetor\");\n\n// muajte shkurt\nCalendar._SMN = new Array\n(\"Jan\",\n\"Shk\",\n\"Mar\",\n\"Pri\",\n\"Maj\",\n\"Qes\",\n\"Kor\",\n\"Gus\",\n\"Sht\",\n\"Tet\",\n\"Nen\",\n\"Dhj\");\n\n// ndihmesa\nCalendar._TT = {};\nCalendar._TT[\"INFO\"] = \"Per kalendarin\";\n\nCalendar._TT[\"ABOUT\"] =\n\"Zgjedhes i ores/dates ne DHTML \\n\" +\n\"\\n\\n\" +\"Zgjedhja e Dates:\\n\" +\n\"- Perdor butonat \\xab, \\xbb per te zgjedhur vitin\\n\" +\n\"- Perdor  butonat\" + String.fromCharCode(0x2039) + \", \" + \nString.fromCharCode(0x203a) +\n\" per te  zgjedhur muajin\\n\" +\n\"- Mbani shtypur butonin e mousit per nje zgjedje me te shpejte.\";\nCalendar._TT[\"ABOUT_TIME\"] = \"\\n\\n\" +\n\"Zgjedhja e kohes:\\n\" +\n\"- Kliko tek ndonje nga pjeset e ores per ta rritur ate\\n\" +\n\"- ose kliko me Shift per ta zvogeluar ate\\n\" +\n\"- ose cliko dhe terhiq per zgjedhje me te shpejte.\";\n\nCalendar._TT[\"PREV_YEAR\"] = \"Viti i shkuar (prit per menune)\";\nCalendar._TT[\"PREV_MONTH\"] = \"Muaji i shkuar (prit per menune)\";\nCalendar._TT[\"GO_TODAY\"] = \"Sot\";\nCalendar._TT[\"NEXT_MONTH\"] = \"Muaji i ardhshem (prit per menune)\";\nCalendar._TT[\"NEXT_YEAR\"] = \"Viti i ardhshem (prit per menune)\";\nCalendar._TT[\"SEL_DATE\"] = \"Zgjidh daten\";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \"Terhiqe per te levizur\";\nCalendar._TT[\"PART_TODAY\"] = \" (sot)\";\n\n// \"%s\" eshte dita e pare e javes\n// %s do te zevendesohet me emrin e dite\nCalendar._TT[\"DAY_FIRST\"] = \"Trego te %s te paren\";\n\n\nCalendar._TT[\"WEEKEND\"] = \"0,6\";\n\nCalendar._TT[\"CLOSE\"] = \"Mbyll\";\nCalendar._TT[\"TODAY\"] = \"Sot\";\nCalendar._TT[\"TIME_PART\"] = \"Kliko me (Shift-)ose terhiqe per te ndryshuarvleren\";\n\n// date formats\nCalendar._TT[\"DEF_DATE_FORMAT\"] = \"%Y-%m-%d\";\nCalendar._TT[\"TT_DATE_FORMAT\"] = \"%a, %b %e\";\n\nCalendar._TT[\"WK\"] = \"Java\";\nCalendar._TT[\"TIME\"] = \"Koha:\";\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/calendar-bg.js",
    "content": "// ** I18N\n\n// Calendar BG language\n// Author: Mihai Bazon, <mihai_bazon@yahoo.com>\n// Translator: Valentin Sheiretsky, <valio@valio.eu.org>\n// Encoding: Windows-1251\n// Distributed under the same terms as the calendar itself.\n\n// For translators: please use UTF-8 if possible.  We strongly believe that\n// Unicode is the answer to a real internationalized world.  Also please\n// include your contact information in the header, as can be seen above.\n\n// full day names\nCalendar._DN = new Array\n(\"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\");\n\n// Please note that the following array of short day names (and the same goes\n// for short month names, _SMN) isn't absolutely necessary.  We give it here\n// for exemplification on how one can customize the short day names, but if\n// they are simply the first N letters of the full name you can simply say:\n//\n//   Calendar._SDN_len = N; // short day name length\n//   Calendar._SMN_len = N; // short month name length\n//\n// If N = 3 then this is not needed either since we assume a value of 3 if not\n// present, to be compatible with translation files that were written before\n// this feature.\n\n// short day names\nCalendar._SDN = new Array\n(\"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\");\n\n// full month names\nCalendar._MN = new Array\n(\"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\");\n\n// short month names\nCalendar._SMN = new Array\n(\"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\");\n\n// tooltips\nCalendar._TT = {};\nCalendar._TT[\"INFO\"] = \"  \";\n\nCalendar._TT[\"ABOUT\"] =\n\"DHTML Date/Time Selector\\n\" +\n\"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\\n\" + // don't translate this this ;-)\n\"For latest version visit: http://www.dynarch.com/projects/calendar/\\n\" +\n\"Distributed under GNU LGPL.  See http://gnu.org/licenses/lgpl.html for details.\" +\n\"\\n\\n\" +\n\"Date selection:\\n\" +\n\"- Use the \\xab, \\xbb buttons to select year\\n\" +\n\"- Use the \" + String.fromCharCode(0x2039) + \", \" + String.fromCharCode(0x203a) + \" buttons to select month\\n\" +\n\"- Hold mouse button on any of the above buttons for faster selection.\";\nCalendar._TT[\"ABOUT_TIME\"] = \"\\n\\n\" +\n\"Time selection:\\n\" +\n\"- Click on any of the time parts to increase it\\n\" +\n\"- or Shift-click to decrease it\\n\" +\n\"- or click and drag for faster selection.\";\n\nCalendar._TT[\"PREV_YEAR\"] = \"  (  )\";\nCalendar._TT[\"PREV_MONTH\"] = \"  (  )\";\nCalendar._TT[\"GO_TODAY\"] = \" \";\nCalendar._TT[\"NEXT_MONTH\"] = \"  (  )\";\nCalendar._TT[\"NEXT_YEAR\"] = \"  (  )\";\nCalendar._TT[\"SEL_DATE\"] = \" \";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \"\";\nCalendar._TT[\"PART_TODAY\"] = \" ()\";\n\n// the following is to inform that \"%s\" is to be the first day of week\n// %s will be replaced with the day name.\nCalendar._TT[\"DAY_FIRST\"] = \"%s   \";\n\n// This may be locale-dependent.  It specifies the week-end days, as an array\n// of comma-separated numbers.  The numbers are from 0 to 6: 0 means Sunday, 1\n// means Monday, etc.\nCalendar._TT[\"WEEKEND\"] = \"0,6\";\n\nCalendar._TT[\"CLOSE\"] = \"\";\nCalendar._TT[\"TODAY\"] = \"\";\nCalendar._TT[\"TIME_PART\"] = \"(Shift-)Click  drag    \";\n\n// date formats\nCalendar._TT[\"DEF_DATE_FORMAT\"] = \"%Y-%m-%d\";\nCalendar._TT[\"TT_DATE_FORMAT\"] = \"%A - %e %B %Y\";\n\nCalendar._TT[\"WK\"] = \"\";\nCalendar._TT[\"TIME\"] = \":\";\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/calendar-big5-utf8.js",
    "content": "// ** I18N\n\n// Calendar big5-utf8 language\n// Author: Gary Fu, <gary@garyfu.idv.tw>\n// Encoding: utf8\n// Distributed under the same terms as the calendar itself.\n\n// For translators: please use UTF-8 if possible.  We strongly believe that\n// Unicode is the answer to a real internationalized world.  Also please\n// include your contact information in the header, as can be seen above.\n\t\n// full day names\nCalendar._DN = new Array\n(\"星期日\",\n \"星期一\",\n \"星期二\",\n \"星期三\",\n \"星期四\",\n \"星期五\",\n \"星期六\",\n \"星期日\");\n\n// Please note that the following array of short day names (and the same goes\n// for short month names, _SMN) isn't absolutely necessary.  We give it here\n// for exemplification on how one can customize the short day names, but if\n// they are simply the first N letters of the full name you can simply say:\n//\n//   Calendar._SDN_len = N; // short day name length\n//   Calendar._SMN_len = N; // short month name length\n//\n// If N = 3 then this is not needed either since we assume a value of 3 if not\n// present, to be compatible with translation files that were written before\n// this feature.\n\n// short day names\nCalendar._SDN = new Array\n(\"日\",\n \"一\",\n \"二\",\n \"三\",\n \"四\",\n \"五\",\n \"六\",\n \"日\");\n\n// full month names\nCalendar._MN = new Array\n(\"一月\",\n \"二月\",\n \"三月\",\n \"四月\",\n \"五月\",\n \"六月\",\n \"七月\",\n \"八月\",\n \"九月\",\n \"十月\",\n \"十一月\",\n \"十二月\");\n\n// short month names\nCalendar._SMN = new Array\n(\"一月\",\n \"二月\",\n \"三月\",\n \"四月\",\n \"五月\",\n \"六月\",\n \"七月\",\n \"八月\",\n \"九月\",\n \"十月\",\n \"十一月\",\n \"十二月\");\n\n// tooltips\nCalendar._TT = {};\nCalendar._TT[\"INFO\"] = \"關於\";\n\nCalendar._TT[\"ABOUT\"] =\n\"DHTML Date/Time Selector\\n\" +\n\"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\\n\" + // don't translate this this ;-)\n\"For latest version visit: http://www.dynarch.com/projects/calendar/\\n\" +\n\"Distributed under GNU LGPL.  See http://gnu.org/licenses/lgpl.html for details.\" +\n\"\\n\\n\" +\n\"日期選擇方法:\\n\" +\n\"- 使用 \\xab, \\xbb 按鈕可選擇年份\\n\" +\n\"- 使用 \" + String.fromCharCode(0x2039) + \", \" + String.fromCharCode(0x203a) + \" 按鈕可選擇月份\\n\" +\n\"- 按住上面的按鈕可以加快選取\";\nCalendar._TT[\"ABOUT_TIME\"] = \"\\n\\n\" +\n\"時間選擇方法:\\n\" +\n\"- 點擊任何的時間部份可增加其值\\n\" +\n\"- 同時按Shift鍵再點擊可減少其值\\n\" +\n\"- 點擊並拖曳可加快改變的值\";\n\nCalendar._TT[\"PREV_YEAR\"] = \"上一年 (按住選單)\";\nCalendar._TT[\"PREV_MONTH\"] = \"下一年 (按住選單)\";\nCalendar._TT[\"GO_TODAY\"] = \"到今日\";\nCalendar._TT[\"NEXT_MONTH\"] = \"上一月 (按住選單)\";\nCalendar._TT[\"NEXT_YEAR\"] = \"下一月 (按住選單)\";\nCalendar._TT[\"SEL_DATE\"] = \"選擇日期\";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \"拖曳\";\nCalendar._TT[\"PART_TODAY\"] = \" (今日)\";\n\n// the following is to inform that \"%s\" is to be the first day of week\n// %s will be replaced with the day name.\nCalendar._TT[\"DAY_FIRST\"] = \"將 %s 顯示在前\";\n\n// This may be locale-dependent.  It specifies the week-end days, as an array\n// of comma-separated numbers.  The numbers are from 0 to 6: 0 means Sunday, 1\n// means Monday, etc.\nCalendar._TT[\"WEEKEND\"] = \"0,6\";\n\nCalendar._TT[\"CLOSE\"] = \"關閉\";\nCalendar._TT[\"TODAY\"] = \"今日\";\nCalendar._TT[\"TIME_PART\"] = \"點擊or拖曳可改變時間(同時按Shift為減)\";\n\n// date formats\nCalendar._TT[\"DEF_DATE_FORMAT\"] = \"%Y-%m-%d\";\nCalendar._TT[\"TT_DATE_FORMAT\"] = \"%a, %b %e\";\n\nCalendar._TT[\"WK\"] = \"週\";\nCalendar._TT[\"TIME\"] = \"Time:\";\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/calendar-big5.js",
    "content": "// ** I18N\n\n// Calendar big5 language\n// Author: Gary Fu, <gary@garyfu.idv.tw>\n// Encoding: big5\n// Distributed under the same terms as the calendar itself.\n\n// For translators: please use UTF-8 if possible.  We strongly believe that\n// Unicode is the answer to a real internationalized world.  Also please\n// include your contact information in the header, as can be seen above.\n\t\n// full day names\nCalendar._DN = new Array\n(\"P\",\n \"P@\",\n \"PG\",\n \"PT\",\n \"P|\",\n \"P\",\n \"P\",\n \"P\");\n\n// Please note that the following array of short day names (and the same goes\n// for short month names, _SMN) isn't absolutely necessary.  We give it here\n// for exemplification on how one can customize the short day names, but if\n// they are simply the first N letters of the full name you can simply say:\n//\n//   Calendar._SDN_len = N; // short day name length\n//   Calendar._SMN_len = N; // short month name length\n//\n// If N = 3 then this is not needed either since we assume a value of 3 if not\n// present, to be compatible with translation files that were written before\n// this feature.\n\n// short day names\nCalendar._SDN = new Array\n(\"\",\n \"@\",\n \"G\",\n \"T\",\n \"|\",\n \"\",\n \"\",\n \"\");\n\n// full month names\nCalendar._MN = new Array\n(\"@\",\n \"G\",\n \"T\",\n \"|\",\n \"\",\n \"\",\n \"C\",\n \"K\",\n \"E\",\n \"Q\",\n \"Q@\",\n \"QG\");\n\n// short month names\nCalendar._SMN = new Array\n(\"@\",\n \"G\",\n \"T\",\n \"|\",\n \"\",\n \"\",\n \"C\",\n \"K\",\n \"E\",\n \"Q\",\n \"Q@\",\n \"QG\");\n\n// tooltips\nCalendar._TT = {};\nCalendar._TT[\"INFO\"] = \"\";\n\nCalendar._TT[\"ABOUT\"] =\n\"DHTML Date/Time Selector\\n\" +\n\"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\\n\" + // don't translate this this ;-)\n\"For latest version visit: http://www.dynarch.com/projects/calendar/\\n\" +\n\"Distributed under GNU LGPL.  See http://gnu.org/licenses/lgpl.html for details.\" +\n\"\\n\\n\" +\n\"ܤk:\\n\" +\n\"- ϥ \\xab, \\xbb siܦ~\\n\" +\n\"- ϥ \" + String.fromCharCode(0x2039) + \", \" + String.fromCharCode(0x203a) + \" siܤ\\n\" +\n\"- WsiH[ֿ\";\nCalendar._TT[\"ABOUT_TIME\"] = \"\\n\\n\" +\n\"ɶܤk:\\n\" +\n\"- I󪺮ɶiW[\\n\" +\n\"- PɫShiftAIi֨\\n\" +\n\"- Ié즲i[֧ܪ\";\n\nCalendar._TT[\"PREV_YEAR\"] = \"W@~ ()\";\nCalendar._TT[\"PREV_MONTH\"] = \"U@~ ()\";\nCalendar._TT[\"GO_TODAY\"] = \"줵\";\nCalendar._TT[\"NEXT_MONTH\"] = \"W@ ()\";\nCalendar._TT[\"NEXT_YEAR\"] = \"U@ ()\";\nCalendar._TT[\"SEL_DATE\"] = \"ܤ\";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \"즲\";\nCalendar._TT[\"PART_TODAY\"] = \" ()\";\n\n// the following is to inform that \"%s\" is to be the first day of week\n// %s will be replaced with the day name.\nCalendar._TT[\"DAY_FIRST\"] = \"N %s ܦbe\";\n\n// This may be locale-dependent.  It specifies the week-end days, as an array\n// of comma-separated numbers.  The numbers are from 0 to 6: 0 means Sunday, 1\n// means Monday, etc.\nCalendar._TT[\"WEEKEND\"] = \"0,6\";\n\nCalendar._TT[\"CLOSE\"] = \"\";\nCalendar._TT[\"TODAY\"] = \"\";\nCalendar._TT[\"TIME_PART\"] = \"Ior즲iܮɶ(PɫShift)\";\n\n// date formats\nCalendar._TT[\"DEF_DATE_FORMAT\"] = \"%Y-%m-%d\";\nCalendar._TT[\"TT_DATE_FORMAT\"] = \"%a, %b %e\";\n\nCalendar._TT[\"WK\"] = \"g\";\nCalendar._TT[\"TIME\"] = \"Time:\";\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/calendar-br.js",
    "content": "﻿// ** I18N\n\n// Calendar pt-BR language\n// Author: Fernando Dourado, <fernando.dourado@ig.com.br>\n// Encoding: any\n// Distributed under the same terms as the calendar itself.\n\n// For translators: please use UTF-8 if possible.  We strongly believe that\n// Unicode is the answer to a real internationalized world.  Also please\n// include your contact information in the header, as can be seen above.\n\n// full day names\nCalendar._DN = new Array\n(\"Domingo\",\n \"Segunda\",\n \"Terça\",\n \"Quarta\",\n \"Quinta\",\n \"Sexta\",\n \"Sabádo\",\n \"Domingo\");\n\n// Please note that the following array of short day names (and the same goes\n// for short month names, _SMN) isn't absolutely necessary.  We give it here\n// for exemplification on how one can customize the short day names, but if\n// they are simply the first N letters of the full name you can simply say:\n//\n//   Calendar._SDN_len = N; // short day name length\n//   Calendar._SMN_len = N; // short month name length\n//\n// If N = 3 then this is not needed either since we assume a value of 3 if not\n// present, to be compatible with translation files that were written before\n// this feature.\n\n// short day names\n// [No changes using default values]\n\n// full month names\nCalendar._MN = new Array\n(\"Janeiro\",\n \"Fevereiro\",\n \"Março\",\n \"Abril\",\n \"Maio\",\n \"Junho\",\n \"Julho\",\n \"Agosto\",\n \"Setembro\",\n \"Outubro\",\n \"Novembro\",\n \"Dezembro\");\n\n// short month names\n// [No changes using default values]\n\n// tooltips\nCalendar._TT = {};\nCalendar._TT[\"INFO\"] = \"Sobre o calendário\";\n\nCalendar._TT[\"ABOUT\"] =\n\"DHTML Date/Time Selector\\n\" +\n\"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\\n\" + // don't translate this this ;-)\n\"For latest version visit: http://www.dynarch.com/projects/calendar/\\n\" +\n\"Distributed under GNU LGPL.  See http://gnu.org/licenses/lgpl.html for details.\" +\n\"\\n\\n\" +\n\"Translate to portuguese Brazil (pt-BR) by Fernando Dourado (fernando.dourado@ig.com.br)\\n\" +\n\"Tradução para o português Brasil (pt-BR) por Fernando Dourado (fernando.dourado@ig.com.br)\" +\n\"\\n\\n\" +\n\"Selecionar data:\\n\" +\n\"- Use as teclas \\xab, \\xbb para selecionar o ano\\n\" +\n\"- Use as teclas \" + String.fromCharCode(0x2039) + \", \" + String.fromCharCode(0x203a) + \" para selecionar o mês\\n\" +\n\"- Clique e segure com o mouse em qualquer botão para selecionar rapidamente.\";\n\nCalendar._TT[\"ABOUT_TIME\"] = \"\\n\\n\" +\n\"Selecionar hora:\\n\" +\n\"- Clique em qualquer uma das partes da hora para aumentar\\n\" +\n\"- ou Shift-clique para diminuir\\n\" +\n\"- ou clique e arraste para selecionar rapidamente.\";\n\nCalendar._TT[\"PREV_YEAR\"] = \"Ano anterior (clique e segure para menu)\";\nCalendar._TT[\"PREV_MONTH\"] = \"Mês anterior (clique e segure para menu)\";\nCalendar._TT[\"GO_TODAY\"] = \"Ir para a data atual\";\nCalendar._TT[\"NEXT_MONTH\"] = \"Próximo mês (clique e segure para menu)\";\nCalendar._TT[\"NEXT_YEAR\"] = \"Próximo ano (clique e segure para menu)\";\nCalendar._TT[\"SEL_DATE\"] = \"Selecione uma data\";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \"Clique e segure para mover\";\nCalendar._TT[\"PART_TODAY\"] = \" (hoje)\";\n\n// the following is to inform that \"%s\" is to be the first day of week\n// %s will be replaced with the day name.\nCalendar._TT[\"DAY_FIRST\"] = \"Exibir %s primeiro\";\n\n// This may be locale-dependent.  It specifies the week-end days, as an array\n// of comma-separated numbers.  The numbers are from 0 to 6: 0 means Sunday, 1\n// means Monday, etc.\nCalendar._TT[\"WEEKEND\"] = \"0,6\";\n\nCalendar._TT[\"CLOSE\"] = \"Fechar\";\nCalendar._TT[\"TODAY\"] = \"Hoje\";\nCalendar._TT[\"TIME_PART\"] = \"(Shift-)Clique ou arraste para mudar o valor\";\n\n// date formats\nCalendar._TT[\"DEF_DATE_FORMAT\"] = \"%d/%m/%Y\";\nCalendar._TT[\"TT_DATE_FORMAT\"] = \"%d de %B de %Y\";\n\nCalendar._TT[\"WK\"] = \"sem\";\nCalendar._TT[\"TIME\"] = \"Hora:\";\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/calendar-ca.js",
    "content": "// ** I18N\n\n// Calendar CA language\n// Author: Mihai Bazon, <mihai_bazon@yahoo.com>\n// Encoding: any\n// Distributed under the same terms as the calendar itself.\n\n// For translators: please use UTF-8 if possible.  We strongly believe that\n// Unicode is the answer to a real internationalized world.  Also please\n// include your contact information in the header, as can be seen above.\n\n// full day names\nCalendar._DN = new Array\n(\"Diumenge\",\n \"Dilluns\",\n \"Dimarts\",\n \"Dimecres\",\n \"Dijous\",\n \"Divendres\",\n \"Dissabte\",\n \"Diumenge\");\n\n// Please note that the following array of short day names (and the same goes\n// for short month names, _SMN) isn't absolutely necessary.  We give it here\n// for exemplification on how one can customize the short day names, but if\n// they are simply the first N letters of the full name you can simply say:\n//\n//   Calendar._SDN_len = N; // short day name length\n//   Calendar._SMN_len = N; // short month name length\n//\n// If N = 3 then this is not needed either since we assume a value of 3 if not\n// present, to be compatible with translation files that were written before\n// this feature.\n\n// short day names\nCalendar._SDN = new Array\n(\"Diu\",\n \"Dil\",\n \"Dmt\",\n \"Dmc\",\n \"Dij\",\n \"Div\",\n \"Dis\",\n \"Diu\");\n\n// full month names\nCalendar._MN = new Array\n(\"Gener\",\n \"Febrer\",\n \"Mar\",\n \"Abril\",\n \"Maig\",\n \"Juny\",\n \"Juliol\",\n \"Agost\",\n \"Setembre\",\n \"Octubre\",\n \"Novembre\",\n \"Desembre\");\n\n// short month names\nCalendar._SMN = new Array\n(\"Gen\",\n \"Feb\",\n \"Mar\",\n \"Abr\",\n \"Mai\",\n \"Jun\",\n \"Jul\",\n \"Ago\",\n \"Set\",\n \"Oct\",\n \"Nov\",\n \"Des\");\n\n// tooltips\nCalendar._TT = {};\nCalendar._TT[\"INFO\"] = \"Sobre el calendari\";\n\nCalendar._TT[\"ABOUT\"] =\n\"DHTML Selector de Data/Hora\\n\" +\n\"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\\n\" + // don't translate this this ;-)\n\"For latest version visit: http://www.dynarch.com/projects/calendar/\\n\" +\n\"Distributed under GNU LGPL.  See http://gnu.org/licenses/lgpl.html for details.\" +\n\"\\n\\n\" +\n\"Sel.lecci de Dates:\\n\" +\n\"- Fes servir els botons \\xab, \\xbb per sel.leccionar l'any\\n\" +\n\"- Fes servir els botons \" + String.fromCharCode(0x2039) + \", \" + String.fromCharCode(0x203a) + \" per se.lecciconar el mes\\n\" +\n\"- Mant el ratol apretat en qualsevol dels anteriors per sel.lecci rpida.\";\nCalendar._TT[\"ABOUT_TIME\"] = \"\\n\\n\" +\n\"Time selection:\\n\" +\n\"- claca en qualsevol de les parts de la hora per augmentar-les\\n\" +\n\"- o Shift-click per decrementar-la\\n\" +\n\"- or click and arrastra per sel.lecci rpida.\";\n\nCalendar._TT[\"PREV_YEAR\"] = \"Any anterior (Mantenir per menu)\";\nCalendar._TT[\"PREV_MONTH\"] = \"Mes anterior (Mantenir per menu)\";\nCalendar._TT[\"GO_TODAY\"] = \"Anar a avui\";\nCalendar._TT[\"NEXT_MONTH\"] = \"Mes segent (Mantenir per menu)\";\nCalendar._TT[\"NEXT_YEAR\"] = \"Any segent (Mantenir per menu)\";\nCalendar._TT[\"SEL_DATE\"] = \"Sel.leccionar data\";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \"Arrastrar per moure\";\nCalendar._TT[\"PART_TODAY\"] = \" (avui)\";\n\n// the following is to inform that \"%s\" is to be the first day of week\n// %s will be replaced with the day name.\nCalendar._TT[\"DAY_FIRST\"] = \"Mostra %s primer\";\n\n// This may be locale-dependent.  It specifies the week-end days, as an array\n// of comma-separated numbers.  The numbers are from 0 to 6: 0 means Sunday, 1\n// means Monday, etc.\nCalendar._TT[\"WEEKEND\"] = \"0,6\";\n\nCalendar._TT[\"CLOSE\"] = \"Tanca\";\nCalendar._TT[\"TODAY\"] = \"Avui\";\nCalendar._TT[\"TIME_PART\"] = \"(Shift-)Click a arrastra per canviar el valor\";\n\n// date formats\nCalendar._TT[\"DEF_DATE_FORMAT\"] = \"%Y-%m-%d\";\nCalendar._TT[\"TT_DATE_FORMAT\"] = \"%a, %b %e\";\n\nCalendar._TT[\"WK\"] = \"st\";\nCalendar._TT[\"TIME\"] = \"Hora:\";\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/calendar-cs-utf8.js",
    "content": "/* \n\tcalendar-cs-win.js\n\tlanguage: Czech\n\tencoding: windows-1250\n\tauthor: Lubos Jerabek (xnet@seznam.cz)\n\t        Jan Uhlir (espinosa@centrum.cz)\n*/\n\n// ** I18N\nCalendar._DN  = new Array('Neděle','Pondělí','Úterý','Středa','Čtvrtek','Pátek','Sobota','Neděle');\nCalendar._SDN = new Array('Ne','Po','Út','St','Čt','Pá','So','Ne');\nCalendar._MN  = new Array('Leden','Únor','Březen','Duben','Květen','Červen','Červenec','Srpen','Září','Říjen','Listopad','Prosinec');\nCalendar._SMN = new Array('Led','Úno','Bře','Dub','Kvě','Črv','Čvc','Srp','Zář','Říj','Lis','Pro');\n\n// tooltips\nCalendar._TT = {};\nCalendar._TT[\"INFO\"] = \"O komponentě kalendář\";\nCalendar._TT[\"TOGGLE\"] = \"Změna prvního dne v týdnu\";\nCalendar._TT[\"PREV_YEAR\"] = \"Předchozí rok (přidrž pro menu)\";\nCalendar._TT[\"PREV_MONTH\"] = \"Předchozí měsíc (přidrž pro menu)\";\nCalendar._TT[\"GO_TODAY\"] = \"Dnešní datum\";\nCalendar._TT[\"NEXT_MONTH\"] = \"Další měsíc (přidrž pro menu)\";\nCalendar._TT[\"NEXT_YEAR\"] = \"Další rok (přidrž pro menu)\";\nCalendar._TT[\"SEL_DATE\"] = \"Vyber datum\";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \"Chyť a táhni, pro přesun\";\nCalendar._TT[\"PART_TODAY\"] = \" (dnes)\";\nCalendar._TT[\"MON_FIRST\"] = \"Ukaž jako první Pondělí\";\n//Calendar._TT[\"SUN_FIRST\"] = \"Ukaž jako první Neděli\";\n\nCalendar._TT[\"ABOUT\"] =\n\"DHTML Date/Time Selector\\n\" +\n\"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\\n\" + // don't translate this this ;-)\n\"For latest version visit: http://www.dynarch.com/projects/calendar/\\n\" +\n\"Distributed under GNU LGPL.  See http://gnu.org/licenses/lgpl.html for details.\" +\n\"\\n\\n\" +\n\"Výběr datumu:\\n\" +\n\"- Use the \\xab, \\xbb buttons to select year\\n\" +\n\"- Použijte tlačítka \" + String.fromCharCode(0x2039) + \", \" + String.fromCharCode(0x203a) + \" k výběru měsíce\\n\" +\n\"- Podržte tlačítko myši na jakémkoliv z těch tlačítek pro rychlejší výběr.\";\n\nCalendar._TT[\"ABOUT_TIME\"] = \"\\n\\n\" +\n\"Výběr času:\\n\" +\n\"- Klikněte na jakoukoliv z částí výběru času pro zvýšení.\\n\" +\n\"- nebo Shift-click pro snížení\\n\" +\n\"- nebo klikněte a táhněte pro rychlejší výběr.\";\n\n// the following is to inform that \"%s\" is to be the first day of week\n// %s will be replaced with the day name.\nCalendar._TT[\"DAY_FIRST\"] = \"Zobraz %s první\";\n\n// This may be locale-dependent.  It specifies the week-end days, as an array\n// of comma-separated numbers.  The numbers are from 0 to 6: 0 means Sunday, 1\n// means Monday, etc.\nCalendar._TT[\"WEEKEND\"] = \"0,6\";\n\nCalendar._TT[\"CLOSE\"] = \"Zavřít\";\nCalendar._TT[\"TODAY\"] = \"Dnes\";\nCalendar._TT[\"TIME_PART\"] = \"(Shift-)Klikni nebo táhni pro změnu hodnoty\";\n\n// date formats\nCalendar._TT[\"DEF_DATE_FORMAT\"] = \"d.m.yy\";\nCalendar._TT[\"TT_DATE_FORMAT\"] = \"%a, %b %e\";\n\nCalendar._TT[\"WK\"] = \"wk\";\nCalendar._TT[\"TIME\"] = \"Čas:\";\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/calendar-cs-win.js",
    "content": "/* \n\tcalendar-cs-win.js\n\tlanguage: Czech\n\tencoding: windows-1250\n\tauthor: Lubos Jerabek (xnet@seznam.cz)\n\t        Jan Uhlir (espinosa@centrum.cz)\n*/\n\n// ** I18N\nCalendar._DN  = new Array('Nedle','Pondl','ter','Steda','tvrtek','Ptek','Sobota','Nedle');\nCalendar._SDN = new Array('Ne','Po','t','St','t','P','So','Ne');\nCalendar._MN  = new Array('Leden','nor','Bezen','Duben','Kvten','erven','ervenec','Srpen','Z','jen','Listopad','Prosinec');\nCalendar._SMN = new Array('Led','no','Be','Dub','Kv','rv','vc','Srp','Z','j','Lis','Pro');\n\n// tooltips\nCalendar._TT = {};\nCalendar._TT[\"INFO\"] = \"O komponent kalend\";\nCalendar._TT[\"TOGGLE\"] = \"Zmna prvnho dne v tdnu\";\nCalendar._TT[\"PREV_YEAR\"] = \"Pedchoz rok (pidr pro menu)\";\nCalendar._TT[\"PREV_MONTH\"] = \"Pedchoz msc (pidr pro menu)\";\nCalendar._TT[\"GO_TODAY\"] = \"Dnen datum\";\nCalendar._TT[\"NEXT_MONTH\"] = \"Dal msc (pidr pro menu)\";\nCalendar._TT[\"NEXT_YEAR\"] = \"Dal rok (pidr pro menu)\";\nCalendar._TT[\"SEL_DATE\"] = \"Vyber datum\";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \"Chy a thni, pro pesun\";\nCalendar._TT[\"PART_TODAY\"] = \" (dnes)\";\nCalendar._TT[\"MON_FIRST\"] = \"Uka jako prvn Pondl\";\n//Calendar._TT[\"SUN_FIRST\"] = \"Uka jako prvn Nedli\";\n\nCalendar._TT[\"ABOUT\"] =\n\"DHTML Date/Time Selector\\n\" +\n\"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\\n\" + // don't translate this this ;-)\n\"For latest version visit: http://www.dynarch.com/projects/calendar/\\n\" +\n\"Distributed under GNU LGPL.  See http://gnu.org/licenses/lgpl.html for details.\" +\n\"\\n\\n\" +\n\"Vbr datumu:\\n\" +\n\"- Use the \\xab, \\xbb buttons to select year\\n\" +\n\"- Pouijte tlatka \" + String.fromCharCode(0x2039) + \", \" + String.fromCharCode(0x203a) + \" k vbru msce\\n\" +\n\"- Podrte tlatko myi na jakmkoliv z tch tlatek pro rychlej vbr.\";\n\nCalendar._TT[\"ABOUT_TIME\"] = \"\\n\\n\" +\n\"Vbr asu:\\n\" +\n\"- Kliknte na jakoukoliv z st vbru asu pro zven.\\n\" +\n\"- nebo Shift-click pro snen\\n\" +\n\"- nebo kliknte a thnte pro rychlej vbr.\";\n\n// the following is to inform that \"%s\" is to be the first day of week\n// %s will be replaced with the day name.\nCalendar._TT[\"DAY_FIRST\"] = \"Zobraz %s prvn\";\n\n// This may be locale-dependent.  It specifies the week-end days, as an array\n// of comma-separated numbers.  The numbers are from 0 to 6: 0 means Sunday, 1\n// means Monday, etc.\nCalendar._TT[\"WEEKEND\"] = \"0,6\";\n\nCalendar._TT[\"CLOSE\"] = \"Zavt\";\nCalendar._TT[\"TODAY\"] = \"Dnes\";\nCalendar._TT[\"TIME_PART\"] = \"(Shift-)Klikni nebo thni pro zmnu hodnoty\";\n\n// date formats\nCalendar._TT[\"DEF_DATE_FORMAT\"] = \"d.m.yy\";\nCalendar._TT[\"TT_DATE_FORMAT\"] = \"%a, %b %e\";\n\nCalendar._TT[\"WK\"] = \"wk\";\nCalendar._TT[\"TIME\"] = \"as:\";\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/calendar-da.js",
    "content": "// ** I18N\n\n// Calendar DA language\n// Author: Michael Thingmand Henriksen, <michael (a) thingmand dot dk>\n// Encoding: any\n// Distributed under the same terms as the calendar itself.\n\n// For translators: please use UTF-8 if possible. We strongly believe that\n// Unicode is the answer to a real internationalized world. Also please\n// include your contact information in the header, as can be seen above.\n\n// full day names\nCalendar._DN = new Array\n(\"Søndag\",\n\"Mandag\",\n\"Tirsdag\",\n\"Onsdag\",\n\"Torsdag\",\n\"Fredag\",\n\"Lørdag\",\n\"Søndag\");\n\n// Please note that the following array of short day names (and the same goes\n// for short month names, _SMN) isn't absolutely necessary. We give it here\n// for exemplification on how one can customize the short day names, but if\n// they are simply the first N letters of the full name you can simply say:\n//\n// Calendar._SDN_len = N; // short day name length\n// Calendar._SMN_len = N; // short month name length\n//\n// If N = 3 then this is not needed either since we assume a value of 3 if not\n// present, to be compatible with translation files that were written before\n// this feature.\n\n// short day names\nCalendar._SDN = new Array\n(\"Søn\",\n\"Man\",\n\"Tir\",\n\"Ons\",\n\"Tor\",\n\"Fre\",\n\"Lør\",\n\"Søn\");\n\n// full month names\nCalendar._MN = new Array\n(\"Januar\",\n\"Februar\",\n\"Marts\",\n\"April\",\n\"Maj\",\n\"Juni\",\n\"Juli\",\n\"August\",\n\"September\",\n\"Oktober\",\n\"November\",\n\"December\");\n\n// short month names\nCalendar._SMN = new Array\n(\"Jan\",\n\"Feb\",\n\"Mar\",\n\"Apr\",\n\"Maj\",\n\"Jun\",\n\"Jul\",\n\"Aug\",\n\"Sep\",\n\"Okt\",\n\"Nov\",\n\"Dec\");\n\n// tooltips\nCalendar._TT = {};\nCalendar._TT[\"INFO\"] = \"Om Kalenderen\";\n\nCalendar._TT[\"ABOUT\"] =\n\"DHTML Date/Time Selector\\n\" +\n\"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\\n\" + // don't translate this this ;-)\n\"For den seneste version besøg: http://www.dynarch.com/projects/calendar/\\n\"; +\n\"Distribueret under GNU LGPL. Se http://gnu.org/licenses/lgpl.html for detajler.\" +\n\"\\n\\n\" +\n\"Valg af dato:\\n\" +\n\"- Brug \\xab, \\xbb knapperne for at vælge år\\n\" +\n\"- Brug \" + String.fromCharCode(0x2039) + \", \" + String.fromCharCode(0x203a) + \" knapperne for at vælge måned\\n\" +\n\"- Hold knappen på musen nede på knapperne ovenfor for hurtigere valg.\";\nCalendar._TT[\"ABOUT_TIME\"] = \"\\n\\n\" +\n\"Valg af tid:\\n\" +\n\"- Klik på en vilkårlig del for større værdi\\n\" +\n\"- eller Shift-klik for for mindre værdi\\n\" +\n\"- eller klik og træk for hurtigere valg.\";\n\nCalendar._TT[\"PREV_YEAR\"] = \"Ét år tilbage (hold for menu)\";\nCalendar._TT[\"PREV_MONTH\"] = \"Én måned tilbage (hold for menu)\";\nCalendar._TT[\"GO_TODAY\"] = \"Gå til i dag\";\nCalendar._TT[\"NEXT_MONTH\"] = \"Én måned frem (hold for menu)\";\nCalendar._TT[\"NEXT_YEAR\"] = \"Ét år frem (hold for menu)\";\nCalendar._TT[\"SEL_DATE\"] = \"Vælg dag\";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \"Træk vinduet\";\nCalendar._TT[\"PART_TODAY\"] = \" (i dag)\";\n\n// the following is to inform that \"%s\" is to be the first day of week\n// %s will be replaced with the day name.\nCalendar._TT[\"DAY_FIRST\"] = \"Vis %s først\";\n\n// This may be locale-dependent. It specifies the week-end days, as an array\n// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1\n// means Monday, etc.\nCalendar._TT[\"WEEKEND\"] = \"0,6\";\n\nCalendar._TT[\"CLOSE\"] = \"Luk\";\nCalendar._TT[\"TODAY\"] = \"I dag\";\nCalendar._TT[\"TIME_PART\"] = \"(Shift-)klik eller træk for at ændre værdi\";\n\n// date formats\nCalendar._TT[\"DEF_DATE_FORMAT\"] = \"%d-%m-%Y\";\nCalendar._TT[\"TT_DATE_FORMAT\"] = \"%a, %b %e\";\n\nCalendar._TT[\"WK\"] = \"Uge\";\nCalendar._TT[\"TIME\"] = \"Tid:\";\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/calendar-de.js",
    "content": "// ** I18N\n\n// Calendar DE language\n// Author: Jack (tR), <jack@jtr.de>\n// Encoding: any\n// Distributed under the same terms as the calendar itself.\n\n// For translators: please use UTF-8 if possible.  We strongly believe that\n// Unicode is the answer to a real internationalized world.  Also please\n// include your contact information in the header, as can be seen above.\n\n// full day names\nCalendar._DN = new Array\n(\"Sonntag\",\n \"Montag\",\n \"Dienstag\",\n \"Mittwoch\",\n \"Donnerstag\",\n \"Freitag\",\n \"Samstag\",\n \"Sonntag\");\n\n// Please note that the following array of short day names (and the same goes\n// for short month names, _SMN) isn't absolutely necessary.  We give it here\n// for exemplification on how one can customize the short day names, but if\n// they are simply the first N letters of the full name you can simply say:\n//\n//   Calendar._SDN_len = N; // short day name length\n//   Calendar._SMN_len = N; // short month name length\n//\n// If N = 3 then this is not needed either since we assume a value of 3 if not\n// present, to be compatible with translation files that were written before\n// this feature.\n\n// short day names\nCalendar._SDN = new Array\n(\"So\",\n \"Mo\",\n \"Di\",\n \"Mi\",\n \"Do\",\n \"Fr\",\n \"Sa\",\n \"So\");\n\n// full month names\nCalendar._MN = new Array\n(\"Januar\",\n \"Februar\",\n \"M\\u00e4rz\",\n \"April\",\n \"Mai\",\n \"Juni\",\n \"Juli\",\n \"August\",\n \"September\",\n \"Oktober\",\n \"November\",\n \"Dezember\");\n\n// short month names\nCalendar._SMN = new Array\n(\"Jan\",\n \"Feb\",\n \"M\\u00e4r\",\n \"Apr\",\n \"May\",\n \"Jun\",\n \"Jul\",\n \"Aug\",\n \"Sep\",\n \"Okt\",\n \"Nov\",\n \"Dez\");\n\n// tooltips\nCalendar._TT = {};\nCalendar._TT[\"INFO\"] = \"\\u00DCber dieses Kalendarmodul\";\n\nCalendar._TT[\"ABOUT\"] =\n\"DHTML Date/Time Selector\\n\" +\n\"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\\n\" + // don't translate this ;-)\n\"For latest version visit: http://www.dynarch.com/projects/calendar/\\n\" +\n\"Distributed under GNU LGPL.  See http://gnu.org/licenses/lgpl.html for details.\" +\n\"\\n\\n\" +\n\"Datum ausw\\u00e4hlen:\\n\" +\n\"- Benutzen Sie die \\xab, \\xbb Buttons um das Jahr zu w\\u00e4hlen\\n\" +\n\"- Benutzen Sie die \" + String.fromCharCode(0x2039) + \", \" + String.fromCharCode(0x203a) + \" Buttons um den Monat zu w\\u00e4hlen\\n\" +\n\"- F\\u00fcr eine Schnellauswahl halten Sie die Maustaste \\u00fcber diesen Buttons fest.\";\nCalendar._TT[\"ABOUT_TIME\"] = \"\\n\\n\" +\n\"Zeit ausw\\u00e4hlen:\\n\" +\n\"- Klicken Sie auf die Teile der Uhrzeit, um diese zu erh\\u00F6hen\\n\" +\n\"- oder klicken Sie mit festgehaltener Shift-Taste um diese zu verringern\\n\" +\n\"- oder klicken und festhalten f\\u00fcr Schnellauswahl.\";\n\nCalendar._TT[\"TOGGLE\"] = \"Ersten Tag der Woche w\\u00e4hlen\";\nCalendar._TT[\"PREV_YEAR\"] = \"Voriges Jahr (Festhalten f\\u00fcr Schnellauswahl)\";\nCalendar._TT[\"PREV_MONTH\"] = \"Voriger Monat (Festhalten f\\u00fcr Schnellauswahl)\";\nCalendar._TT[\"GO_TODAY\"] = \"Heute ausw\\u00e4hlen\";\nCalendar._TT[\"NEXT_MONTH\"] = \"N\\u00e4chst. Monat (Festhalten f\\u00fcr Schnellauswahl)\";\nCalendar._TT[\"NEXT_YEAR\"] = \"N\\u00e4chst. Jahr (Festhalten f\\u00fcr Schnellauswahl)\";\nCalendar._TT[\"SEL_DATE\"] = \"Datum ausw\\u00e4hlen\";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \"Zum Bewegen festhalten\";\nCalendar._TT[\"PART_TODAY\"] = \" (Heute)\";\n\n// the following is to inform that \"%s\" is to be the first day of week\n// %s will be replaced with the day name.\nCalendar._TT[\"DAY_FIRST\"] = \"Woche beginnt mit %s \";\n\n// This may be locale-dependent.  It specifies the week-end days, as an array\n// of comma-separated numbers.  The numbers are from 0 to 6: 0 means Sunday, 1\n// means Monday, etc.\nCalendar._TT[\"WEEKEND\"] = \"0,6\";\n\nCalendar._TT[\"CLOSE\"] = \"Schlie\\u00dfen\";\nCalendar._TT[\"TODAY\"] = \"Heute\";\nCalendar._TT[\"TIME_PART\"] = \"(Shift-)Klick oder Festhalten und Ziehen um den Wert zu \\u00e4ndern\";\n\n// date formats\nCalendar._TT[\"DEF_DATE_FORMAT\"] = \"%d.%m.%Y\";\nCalendar._TT[\"TT_DATE_FORMAT\"] = \"%a, %b %e\";\n\nCalendar._TT[\"WK\"] = \"wk\";\nCalendar._TT[\"TIME\"] = \"Zeit:\";\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/calendar-du.js",
    "content": "// ** I18N\nCalendar._DN = new Array\n(\"Zondag\",\n \"Maandag\",\n \"Dinsdag\",\n \"Woensdag\",\n \"Donderdag\",\n \"Vrijdag\",\n \"Zaterdag\",\n \"Zondag\");\nCalendar._MN = new Array\n(\"Januari\",\n \"Februari\",\n \"Maart\",\n \"April\",\n \"Mei\",\n \"Juni\",\n \"Juli\",\n \"Augustus\",\n \"September\",\n \"Oktober\",\n \"November\",\n \"December\");\n\n// tooltips\nCalendar._TT = {};\nCalendar._TT[\"TOGGLE\"] = \"Toggle startdag van de week\";\nCalendar._TT[\"PREV_YEAR\"] = \"Vorig jaar (indrukken voor menu)\";\nCalendar._TT[\"PREV_MONTH\"] = \"Vorige month (indrukken voor menu)\";\nCalendar._TT[\"GO_TODAY\"] = \"Naar Vandaag\";\nCalendar._TT[\"NEXT_MONTH\"] = \"Volgende Maand (indrukken voor menu)\";\nCalendar._TT[\"NEXT_YEAR\"] = \"Volgend jaar (indrukken voor menu)\";\nCalendar._TT[\"SEL_DATE\"] = \"Selecteer datum\";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \"Sleep om te verplaatsen\";\nCalendar._TT[\"PART_TODAY\"] = \" (vandaag)\";\nCalendar._TT[\"MON_FIRST\"] = \"Toon Maandag eerst\";\nCalendar._TT[\"SUN_FIRST\"] = \"Toon Zondag eerst\";\nCalendar._TT[\"CLOSE\"] = \"Sluiten\";\nCalendar._TT[\"TODAY\"] = \"Vandaag\";\n\n// date formats\nCalendar._TT[\"DEF_DATE_FORMAT\"] = \"y-mm-dd\";\nCalendar._TT[\"TT_DATE_FORMAT\"] = \"D, M d\";\n\nCalendar._TT[\"WK\"] = \"wk\";\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/calendar-el.js",
    "content": "﻿// ** I18N\nCalendar._DN = new Array\n(\"Κυριακή\",\n \"Δευτέρα\",\n \"Τρίτη\",\n \"Τετάρτη\",\n \"Πέμπτη\",\n \"Παρασκευή\",\n \"Σάββατο\",\n \"Κυριακή\");\n\nCalendar._SDN = new Array\n(\"Κυ\",\n \"Δε\",\n \"Tρ\",\n \"Τε\",\n \"Πε\",\n \"Πα\",\n \"Σα\",\n \"Κυ\");\n\nCalendar._MN = new Array\n(\"Ιανουάριος\",\n \"Φεβρουάριος\",\n \"Μάρτιος\",\n \"Απρίλιος\",\n \"Μάϊος\",\n \"Ιούνιος\",\n \"Ιούλιος\",\n \"Αύγουστος\",\n \"Σεπτέμβριος\",\n \"Οκτώβριος\",\n \"Νοέμβριος\",\n \"Δεκέμβριος\");\n\nCalendar._SMN = new Array\n(\"Ιαν\",\n \"Φεβ\",\n \"Μαρ\",\n \"Απρ\",\n \"Μαι\",\n \"Ιουν\",\n \"Ιουλ\",\n \"Αυγ\",\n \"Σεπ\",\n \"Οκτ\",\n \"Νοε\",\n \"Δεκ\");\n\n// tooltips\nCalendar._TT = {};\nCalendar._TT[\"INFO\"] = \"Για το ημερολόγιο\";\n\nCalendar._TT[\"ABOUT\"] =\n\"Επιλογέας ημερομηνίας/ώρας σε DHTML\\n\" +\n\"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\\n\" + // don't translate this this ;-)\n\"Για τελευταία έκδοση: http://www.dynarch.com/projects/calendar/\\n\" +\n\"Distributed under GNU LGPL.  See http://gnu.org/licenses/lgpl.html for details.\" +\n\"\\n\\n\" +\n\"Επιλογή ημερομηνίας:\\n\" +\n\"- Χρησιμοποιείστε τα κουμπιά \\xab, \\xbb για επιλογή έτους\\n\" +\n\"- Χρησιμοποιείστε τα κουμπιά \" + String.fromCharCode(0x2039) + \", \" + String.fromCharCode(0x203a) + \" για επιλογή μήνα\\n\" +\n\"- Κρατήστε κουμπί ποντικού πατημένο στα παραπάνω κουμπιά για πιο γρήγορη επιλογή.\";\nCalendar._TT[\"ABOUT_TIME\"] = \"\\n\\n\" +\n\"Επιλογή ώρας:\\n\" +\n\"- Κάντε κλικ σε ένα από τα μέρη της ώρας για αύξηση\\n\" +\n\"- ή Shift-κλικ για μείωση\\n\" +\n\"- ή κλικ και μετακίνηση για πιο γρήγορη επιλογή.\";\nCalendar._TT[\"TOGGLE\"] = \"Μπάρα πρώτης ημέρας της εβδομάδας\";\nCalendar._TT[\"PREV_YEAR\"] = \"Προηγ. έτος (κρατήστε για το μενού)\";\nCalendar._TT[\"PREV_MONTH\"] = \"Προηγ. μήνας (κρατήστε για το μενού)\";\nCalendar._TT[\"GO_TODAY\"] = \"Σήμερα\";\nCalendar._TT[\"NEXT_MONTH\"] = \"Επόμενος μήνας (κρατήστε για το μενού)\";\nCalendar._TT[\"NEXT_YEAR\"] = \"Επόμενο έτος (κρατήστε για το μενού)\";\nCalendar._TT[\"SEL_DATE\"] = \"Επιλέξτε ημερομηνία\";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \"Σύρτε για να μετακινήσετε\";\nCalendar._TT[\"PART_TODAY\"] = \" (σήμερα)\";\nCalendar._TT[\"MON_FIRST\"] = \"Εμφάνιση Δευτέρας πρώτα\";\nCalendar._TT[\"SUN_FIRST\"] = \"Εμφάνιση Κυριακής πρώτα\";\nCalendar._TT[\"CLOSE\"] = \"Κλείσιμο\";\nCalendar._TT[\"TODAY\"] = \"Σήμερα\";\nCalendar._TT[\"TIME_PART\"] = \"(Shift-)κλικ ή μετακίνηση για αλλαγή\";\n\n// date formats\nCalendar._TT[\"DEF_DATE_FORMAT\"] = \"dd-mm-y\";\nCalendar._TT[\"TT_DATE_FORMAT\"] = \"D, d M\";\n\nCalendar._TT[\"WK\"] = \"εβδ\";\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/calendar-en.js",
    "content": "// ** I18N\n\n// Calendar EN language\n// Author: Mihai Bazon, <mihai_bazon@yahoo.com>\n// Encoding: any\n// Distributed under the same terms as the calendar itself.\n\n// For translators: please use UTF-8 if possible.  We strongly believe that\n// Unicode is the answer to a real internationalized world.  Also please\n// include your contact information in the header, as can be seen above.\n\n// full day names\nCalendar._DN = new Array\n(\"Sunday\",\n \"Monday\",\n \"Tuesday\",\n \"Wednesday\",\n \"Thursday\",\n \"Friday\",\n \"Saturday\",\n \"Sunday\");\n\n// Please note that the following array of short day names (and the same goes\n// for short month names, _SMN) isn't absolutely necessary.  We give it here\n// for exemplification on how one can customize the short day names, but if\n// they are simply the first N letters of the full name you can simply say:\n//\n//   Calendar._SDN_len = N; // short day name length\n//   Calendar._SMN_len = N; // short month name length\n//\n// If N = 3 then this is not needed either since we assume a value of 3 if not\n// present, to be compatible with translation files that were written before\n// this feature.\n\n// short day names\nCalendar._SDN = new Array\n(\"Sun\",\n \"Mon\",\n \"Tue\",\n \"Wed\",\n \"Thu\",\n \"Fri\",\n \"Sat\",\n \"Sun\");\n\n// First day of the week. \"0\" means display Sunday first, \"1\" means display\n// Monday first, etc.\nCalendar._FD = 0;\n\n// full month names\nCalendar._MN = new Array\n(\"January\",\n \"February\",\n \"March\",\n \"April\",\n \"May\",\n \"June\",\n \"July\",\n \"August\",\n \"September\",\n \"October\",\n \"November\",\n \"December\");\n\n// short month names\nCalendar._SMN = new Array\n(\"Jan\",\n \"Feb\",\n \"Mar\",\n \"Apr\",\n \"May\",\n \"Jun\",\n \"Jul\",\n \"Aug\",\n \"Sep\",\n \"Oct\",\n \"Nov\",\n \"Dec\");\n\n// tooltips\nCalendar._TT = {};\nCalendar._TT[\"INFO\"] = \"About the calendar\";\n\nCalendar._TT[\"ABOUT\"] =\n\"DHTML Date/Time Selector\\n\" +\n\"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\\n\" + // don't translate this this ;-)\n\"For latest version visit: http://www.dynarch.com/projects/calendar/\\n\" +\n\"Distributed under GNU LGPL.  See http://gnu.org/licenses/lgpl.html for details.\" +\n\"\\n\\n\" +\n\"Date selection:\\n\" +\n\"- Use the \\xab, \\xbb buttons to select year\\n\" +\n\"- Use the \" + String.fromCharCode(0x2039) + \", \" + String.fromCharCode(0x203a) + \" buttons to select month\\n\" +\n\"- Hold mouse button on any of the above buttons for faster selection.\";\nCalendar._TT[\"ABOUT_TIME\"] = \"\\n\\n\" +\n\"Time selection:\\n\" +\n\"- Click on any of the time parts to increase it\\n\" +\n\"- or Shift-click to decrease it\\n\" +\n\"- or click and drag for faster selection.\";\n\nCalendar._TT[\"PREV_YEAR\"] = \"Prev. year (hold for menu)\";\nCalendar._TT[\"PREV_MONTH\"] = \"Prev. month (hold for menu)\";\nCalendar._TT[\"GO_TODAY\"] = \"Go Today\";\nCalendar._TT[\"NEXT_MONTH\"] = \"Next month (hold for menu)\";\nCalendar._TT[\"NEXT_YEAR\"] = \"Next year (hold for menu)\";\nCalendar._TT[\"SEL_DATE\"] = \"Select date\";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \"Drag to move\";\nCalendar._TT[\"PART_TODAY\"] = \" (today)\";\n\n// the following is to inform that \"%s\" is to be the first day of week\n// %s will be replaced with the day name.\nCalendar._TT[\"DAY_FIRST\"] = \"Display %s first\";\n\n// This may be locale-dependent.  It specifies the week-end days, as an array\n// of comma-separated numbers.  The numbers are from 0 to 6: 0 means Sunday, 1\n// means Monday, etc.\nCalendar._TT[\"WEEKEND\"] = \"0,6\";\n\nCalendar._TT[\"CLOSE\"] = \"Close\";\nCalendar._TT[\"TODAY\"] = \"Today\";\nCalendar._TT[\"TIME_PART\"] = \"(Shift-)Click or drag to change value\";\n\n// date formats\nCalendar._TT[\"DEF_DATE_FORMAT\"] = \"%Y-%m-%d\";\nCalendar._TT[\"TT_DATE_FORMAT\"] = \"%a, %b %e\";\n\nCalendar._TT[\"WK\"] = \"wk\";\nCalendar._TT[\"TIME\"] = \"Time:\";\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/calendar-es.js",
    "content": "// ** I18N\n\n// Calendar ES (spanish) language\n// Author: Mihai Bazon, <mihai_bazon@yahoo.com>\n// Updater: Servilio Afre Puentes <servilios@yahoo.com>\n// Updated: 2004-06-03\n// Encoding: utf-8\n// Distributed under the same terms as the calendar itself.\n\n// For translators: please use UTF-8 if possible.  We strongly believe that\n// Unicode is the answer to a real internationalized world.  Also please\n// include your contact information in the header, as can be seen above.\n\n// full day names\nCalendar._DN = new Array\n(\"Domingo\",\n \"Lunes\",\n \"Martes\",\n \"Mircoles\",\n \"Jueves\",\n \"Viernes\",\n \"Sbado\",\n \"Domingo\");\n\n// Please note that the following array of short day names (and the same goes\n// for short month names, _SMN) isn't absolutely necessary.  We give it here\n// for exemplification on how one can customize the short day names, but if\n// they are simply the first N letters of the full name you can simply say:\n//\n//   Calendar._SDN_len = N; // short day name length\n//   Calendar._SMN_len = N; // short month name length\n//\n// If N = 3 then this is not needed either since we assume a value of 3 if not\n// present, to be compatible with translation files that were written before\n// this feature.\n\n// short day names\nCalendar._SDN = new Array\n(\"Dom\",\n \"Lun\",\n \"Mar\",\n \"Mi\",\n \"Jue\",\n \"Vie\",\n \"Sb\",\n \"Dom\");\n\n// First day of the week. \"0\" means display Sunday first, \"1\" means display\n// Monday first, etc.\nCalendar._FD = 1;\n\n// full month names\nCalendar._MN = new Array\n(\"Enero\",\n \"Febrero\",\n \"Marzo\",\n \"Abril\",\n \"Mayo\",\n \"Junio\",\n \"Julio\",\n \"Agosto\",\n \"Septiembre\",\n \"Octubre\",\n \"Noviembre\",\n \"Diciembre\");\n\n// short month names\nCalendar._SMN = new Array\n(\"Ene\",\n \"Feb\",\n \"Mar\",\n \"Abr\",\n \"May\",\n \"Jun\",\n \"Jul\",\n \"Ago\",\n \"Sep\",\n \"Oct\",\n \"Nov\",\n \"Dic\");\n\n// tooltips\nCalendar._TT = {};\nCalendar._TT[\"INFO\"] = \"Acerca del calendario\";\n\nCalendar._TT[\"ABOUT\"] =\n\"Selector DHTML de Fecha/Hora\\n\" +\n\"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\\n\" + // don't translate this this ;-)\n\"Para conseguir la ltima versin visite: http://www.dynarch.com/projects/calendar/\\n\" +\n\"Distribuido bajo licencia GNU LGPL. Visite http://gnu.org/licenses/lgpl.html para ms detalles.\" +\n\"\\n\\n\" +\n\"Seleccin de fecha:\\n\" +\n\"- Use los botones \\xab, \\xbb para seleccionar el ao\\n\" +\n\"- Use los botones \" + String.fromCharCode(0x2039) + \", \" + String.fromCharCode(0x203a) + \" para seleccionar el mes\\n\" +\n\"- Mantenga pulsado el ratn en cualquiera de estos botones para una seleccin rpida.\";\nCalendar._TT[\"ABOUT_TIME\"] = \"\\n\\n\" +\n\"Seleccin de hora:\\n\" +\n\"- Pulse en cualquiera de las partes de la hora para incrementarla\\n\" +\n\"- o pulse las maysculas mientras hace clic para decrementarla\\n\" +\n\"- o haga clic y arrastre el ratn para una seleccin ms rpida.\";\n\nCalendar._TT[\"PREV_YEAR\"] = \"Ao anterior (mantener para men)\";\nCalendar._TT[\"PREV_MONTH\"] = \"Mes anterior (mantener para men)\";\nCalendar._TT[\"GO_TODAY\"] = \"Ir a hoy\";\nCalendar._TT[\"NEXT_MONTH\"] = \"Mes siguiente (mantener para men)\";\nCalendar._TT[\"NEXT_YEAR\"] = \"Ao siguiente (mantener para men)\";\nCalendar._TT[\"SEL_DATE\"] = \"Seleccionar fecha\";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \"Arrastrar para mover\";\nCalendar._TT[\"PART_TODAY\"] = \" (hoy)\";\n\n// the following is to inform that \"%s\" is to be the first day of week\n// %s will be replaced with the day name.\nCalendar._TT[\"DAY_FIRST\"] = \"Hacer %s primer da de la semana\";\n\n// This may be locale-dependent.  It specifies the week-end days, as an array\n// of comma-separated numbers.  The numbers are from 0 to 6: 0 means Sunday, 1\n// means Monday, etc.\nCalendar._TT[\"WEEKEND\"] = \"0,6\";\n\nCalendar._TT[\"CLOSE\"] = \"Cerrar\";\nCalendar._TT[\"TODAY\"] = \"Hoy\";\nCalendar._TT[\"TIME_PART\"] = \"(Mayscula-)Clic o arrastre para cambiar valor\";\n\n// date formats\nCalendar._TT[\"DEF_DATE_FORMAT\"] = \"%d/%m/%Y\";\nCalendar._TT[\"TT_DATE_FORMAT\"] = \"%A, %e de %B de %Y\";\n\nCalendar._TT[\"WK\"] = \"sem\";\nCalendar._TT[\"TIME\"] = \"Hora:\";\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/calendar-fi.js",
    "content": "﻿// ** I18N\n\n// Calendar FI language (Finnish, Suomi)\n// Author: Jarno Käyhkö, <gambler@phnet.fi>\n// Encoding: UTF-8\n// Distributed under the same terms as the calendar itself.\n\n// full day names\nCalendar._DN = new Array\n(\"Sunnuntai\",\n \"Maanantai\",\n \"Tiistai\",\n \"Keskiviikko\",\n \"Torstai\",\n \"Perjantai\",\n \"Lauantai\",\n \"Sunnuntai\");\n\n// short day names\nCalendar._SDN = new Array\n(\"Su\",\n \"Ma\",\n \"Ti\",\n \"Ke\",\n \"To\",\n \"Pe\",\n \"La\",\n \"Su\");\n\n// full month names\nCalendar._MN = new Array\n(\"Tammikuu\",\n \"Helmikuu\",\n \"Maaliskuu\",\n \"Huhtikuu\",\n \"Toukokuu\",\n \"Kesäkuu\",\n \"Heinäkuu\",\n \"Elokuu\",\n \"Syyskuu\",\n \"Lokakuu\",\n \"Marraskuu\",\n \"Joulukuu\");\n\n// short month names\nCalendar._SMN = new Array\n(\"Tam\",\n \"Hel\",\n \"Maa\",\n \"Huh\",\n \"Tou\",\n \"Kes\",\n \"Hei\",\n \"Elo\",\n \"Syy\",\n \"Lok\",\n \"Mar\",\n \"Jou\");\n\n// tooltips\nCalendar._TT = {};\nCalendar._TT[\"INFO\"] = \"Tietoja kalenterista\";\n\nCalendar._TT[\"ABOUT\"] =\n\"DHTML Date/Time Selector\\n\" +\n\"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\\n\" + // don't translate this this ;-)\n\"Uusin versio osoitteessa: http://www.dynarch.com/projects/calendar/\\n\" +\n\"Julkaistu GNU LGPL lisenssin alaisuudessa. Lisätietoja osoitteessa http://gnu.org/licenses/lgpl.html\" +\n\"\\n\\n\" +\n\"Päivämäärä valinta:\\n\" +\n\"- Käytä \\xab, \\xbb painikkeita valitaksesi vuosi\\n\" +\n\"- Käytä \" + String.fromCharCode(0x2039) + \", \" + String.fromCharCode(0x203a) + \" painikkeita valitaksesi kuukausi\\n\" +\n\"- Pitämällä hiiren painiketta minkä tahansa yllä olevan painikkeen kohdalla, saat näkyviin valikon nopeampaan siirtymiseen.\";\nCalendar._TT[\"ABOUT_TIME\"] = \"\\n\\n\" +\n\"Ajan valinta:\\n\" +\n\"- Klikkaa kellonajan numeroita lisätäksesi aikaa\\n\" +\n\"- tai pitämällä Shift-näppäintä pohjassa saat aikaa taaksepäin\\n\" +\n\"- tai klikkaa ja pidä hiiren painike pohjassa sekä liikuta hiirtä muuttaaksesi aikaa nopeasti eteen- ja taaksepäin.\";\n\nCalendar._TT[\"PREV_YEAR\"] = \"Edell. vuosi (paina hetki, näet valikon)\";\nCalendar._TT[\"PREV_MONTH\"] = \"Edell. kuukausi (paina hetki, näet valikon)\";\nCalendar._TT[\"GO_TODAY\"] = \"Siirry tähän päivään\";\nCalendar._TT[\"NEXT_MONTH\"] = \"Seur. kuukausi (paina hetki, näet valikon)\";\nCalendar._TT[\"NEXT_YEAR\"] = \"Seur. vuosi (paina hetki, näet valikon)\";\nCalendar._TT[\"SEL_DATE\"] = \"Valitse päivämäärä\";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \"Siirrä kalenterin paikkaa\";\nCalendar._TT[\"PART_TODAY\"] = \" (tänään)\";\nCalendar._TT[\"MON_FIRST\"] = \"Näytä maanantai ensimmäisenä\";\nCalendar._TT[\"SUN_FIRST\"] = \"Näytä sunnuntai ensimmäisenä\";\nCalendar._TT[\"CLOSE\"] = \"Sulje\";\nCalendar._TT[\"TODAY\"] = \"Tänään\";\nCalendar._TT[\"TIME_PART\"] = \"(Shift-) Klikkaa tai liikuta muuttaaksesi aikaa\";\n\n// date formats\nCalendar._TT[\"DEF_DATE_FORMAT\"] = \"%d.%m.%Y\";\nCalendar._TT[\"TT_DATE_FORMAT\"] = \"%d.%m.%Y\";\n\nCalendar._TT[\"WK\"] = \"Vko\";\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/calendar-fr.js",
    "content": "// ** I18N\n\n// Calendar EN language\n// Author: Mihai Bazon, <mihai_bazon@yahoo.com>\n// Encoding: any\n// Distributed under the same terms as the calendar itself.\n\n// For translators: please use UTF-8 if possible.  We strongly believe that\n// Unicode is the answer to a real internationalized world.  Also please\n// include your contact information in the header, as can be seen above.\n\n// Translator: David Duret, <pilgrim@mala-template.net> from previous french version\n\n// full day names\nCalendar._DN = new Array\n(\"Dimanche\",\n \"Lundi\",\n \"Mardi\",\n \"Mercredi\",\n \"Jeudi\",\n \"Vendredi\",\n \"Samedi\",\n \"Dimanche\");\n\n// Please note that the following array of short day names (and the same goes\n// for short month names, _SMN) isn't absolutely necessary.  We give it here\n// for exemplification on how one can customize the short day names, but if\n// they are simply the first N letters of the full name you can simply say:\n//\n//   Calendar._SDN_len = N; // short day name length\n//   Calendar._SMN_len = N; // short month name length\n//\n// If N = 3 then this is not needed either since we assume a value of 3 if not\n// present, to be compatible with translation files that were written before\n// this feature.\n\n// short day names\nCalendar._SDN = new Array\n(\"Dim\",\n \"Lun\",\n \"Mar\",\n \"Mar\",\n \"Jeu\",\n \"Ven\",\n \"Sam\",\n \"Dim\");\n\n// full month names\nCalendar._MN = new Array\n(\"Janvier\",\n \"Fvrier\",\n \"Mars\",\n \"Avril\",\n \"Mai\",\n \"Juin\",\n \"Juillet\",\n \"Aot\",\n \"Septembre\",\n \"Octobre\",\n \"Novembre\",\n \"Dcembre\");\n\n// short month names\nCalendar._SMN = new Array\n(\"Jan\",\n \"Fev\",\n \"Mar\",\n \"Avr\",\n \"Mai\",\n \"Juin\",\n \"Juil\",\n \"Aout\",\n \"Sep\",\n \"Oct\",\n \"Nov\",\n \"Dec\");\n\n// tooltips\nCalendar._TT = {};\nCalendar._TT[\"INFO\"] = \"A propos du calendrier\";\n\nCalendar._TT[\"ABOUT\"] =\n\"DHTML Date/Heure Selecteur\\n\" +\n\"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\\n\" + // don't translate this this ;-)\n\"Pour la derniere version visitez : http://www.dynarch.com/projects/calendar/\\n\" +\n\"Distribu par GNU LGPL.  Voir http://gnu.org/licenses/lgpl.html pour les details.\" +\n\"\\n\\n\" +\n\"Selection de la date :\\n\" +\n\"- Utiliser les bouttons \\xab, \\xbb  pour selectionner l\\'annee\\n\" +\n\"- Utiliser les bouttons \" + String.fromCharCode(0x2039) + \", \" + String.fromCharCode(0x203a) + \" pour selectionner les mois\\n\" +\n\"- Garder la souris sur n'importe quels boutons pour une selection plus rapide\";\nCalendar._TT[\"ABOUT_TIME\"] = \"\\n\\n\" +\n\"Selection de l\\'heure :\\n\" +\n\"- Cliquer sur heures ou minutes pour incrementer\\n\" +\n\"- ou Maj-clic pour decrementer\\n\" +\n\"- ou clic et glisser-deplacer pour une selection plus rapide\";\n\nCalendar._TT[\"PREV_YEAR\"] = \"Anne prc. (maintenir pour menu)\";\nCalendar._TT[\"PREV_MONTH\"] = \"Mois prc. (maintenir pour menu)\";\nCalendar._TT[\"GO_TODAY\"] = \"Atteindre la date du jour\";\nCalendar._TT[\"NEXT_MONTH\"] = \"Mois suiv. (maintenir pour menu)\";\nCalendar._TT[\"NEXT_YEAR\"] = \"Anne suiv. (maintenir pour menu)\";\nCalendar._TT[\"SEL_DATE\"] = \"Slectionner une date\";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \"Dplacer\";\nCalendar._TT[\"PART_TODAY\"] = \" (Aujourd'hui)\";\n\n// the following is to inform that \"%s\" is to be the first day of week\n// %s will be replaced with the day name.\nCalendar._TT[\"DAY_FIRST\"] = \"Afficher %s en premier\";\n\n// This may be locale-dependent.  It specifies the week-end days, as an array\n// of comma-separated numbers.  The numbers are from 0 to 6: 0 means Sunday, 1\n// means Monday, etc.\nCalendar._TT[\"WEEKEND\"] = \"0,6\";\n\nCalendar._TT[\"CLOSE\"] = \"Fermer\";\nCalendar._TT[\"TODAY\"] = \"Aujourd'hui\";\nCalendar._TT[\"TIME_PART\"] = \"(Maj-)Clic ou glisser pour modifier la valeur\";\n\n// date formats\nCalendar._TT[\"DEF_DATE_FORMAT\"] = \"%d/%m/%Y\";\nCalendar._TT[\"TT_DATE_FORMAT\"] = \"%a, %b %e\";\n\nCalendar._TT[\"WK\"] = \"Sem.\";\nCalendar._TT[\"TIME\"] = \"Heure :\";\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/calendar-he-utf8.js",
    "content": "// ** I18N\n\n// Calendar EN language\n// Author: Idan Sofer, <idan@idanso.dyndns.org>\n// Encoding: UTF-8\n// Distributed under the same terms as the calendar itself.\n\n// For translators: please use UTF-8 if possible.  We strongly believe that\n// Unicode is the answer to a real internationalized world.  Also please\n// include your contact information in the header, as can be seen above.\n\n// full day names\nCalendar._DN = new Array\n(\"ראשון\",\n \"שני\",\n \"שלישי\",\n \"רביעי\",\n \"חמישי\",\n \"שישי\",\n \"שבת\",\n \"ראשון\");\n\n// Please note that the following array of short day names (and the same goes\n// for short month names, _SMN) isn't absolutely necessary.  We give it here\n// for exemplification on how one can customize the short day names, but if\n// they are simply the first N letters of the full name you can simply say:\n//\n//   Calendar._SDN_len = N; // short day name length\n//   Calendar._SMN_len = N; // short month name length\n//\n// If N = 3 then this is not needed either since we assume a value of 3 if not\n// present, to be compatible with translation files that were written before\n// this feature.\n\n// short day names\nCalendar._SDN = new Array\n(\"א\",\n \"ב\",\n \"ג\",\n \"ד\",\n \"ה\",\n \"ו\",\n \"ש\",\n \"א\");\n\n// full month names\nCalendar._MN = new Array\n(\"ינואר\",\n \"פברואר\",\n \"מרץ\",\n \"אפריל\",\n \"מאי\",\n \"יוני\",\n \"יולי\",\n \"אוגוסט\",\n \"ספטמבר\",\n \"אוקטובר\",\n \"נובמבר\",\n \"דצמבר\");\n\n// short month names\nCalendar._SMN = new Array\n(\"ינא\",\n \"פבר\",\n \"מרץ\",\n \"אפר\",\n \"מאי\",\n \"יונ\",\n \"יול\",\n \"אוג\",\n \"ספט\",\n \"אוק\",\n \"נוב\",\n \"דצמ\");\n\n// tooltips\nCalendar._TT = {};\nCalendar._TT[\"INFO\"] = \"אודות השנתון\";\n\nCalendar._TT[\"ABOUT\"] =\n\"בחרן תאריך/שעה DHTML\\n\" +\n\"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\\n\" + // don't translate this this ;-)\n\"הגירסא האחרונה זמינה ב: http://www.dynarch.com/projects/calendar/\\n\" +\n\"מופץ תחת זיכיון ה GNU LGPL.  עיין ב http://gnu.org/licenses/lgpl.html לפרטים נוספים.\" +\n\"\\n\\n\" +\n\" בחירת תאריך:\\n\" +\n\"- השתמש בכפתורים \\xab, \\xbb לבחירת שנה\\n\" +\n\"- השתמש בכפתורים \" + String.fromCharCode(0x2039) + \", \" + String.fromCharCode(0x203a) + \" לבחירת חודש\\n\" +\n\"- החזק העכבר לחוץ מעל הכפתורים המוזכרים לעיל לבחירה מהירה יותר.\";\nCalendar._TT[\"ABOUT_TIME\"] = \"\\n\\n\" +\n\"בחירת זמן:\\n\" +\n\"- לחץ על כל אחד מחלקי הזמן כדי להוסיף\\n\" +\n\"- או shift בשילוב עם לחיצה כדי להחסיר\\n\" +\n\"- או לחץ וגרור לפעולה מהירה יותר.\";\n\nCalendar._TT[\"PREV_YEAR\"] = \"שנה קודמת - החזק לקבלת תפריט\";\nCalendar._TT[\"PREV_MONTH\"] = \"חודש קודם - החזק לקבלת תפריט\";\nCalendar._TT[\"GO_TODAY\"] = \"עבור להיום\";\nCalendar._TT[\"NEXT_MONTH\"] = \"חודש הבא - החזק לתפריט\";\nCalendar._TT[\"NEXT_YEAR\"] = \"שנה הבאה - החזק לתפריט\";\nCalendar._TT[\"SEL_DATE\"] = \"בחר תאריך\";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \"גרור להזזה\";\nCalendar._TT[\"PART_TODAY\"] = \" )היום(\";\n\n// the following is to inform that \"%s\" is to be the first day of week\n// %s will be replaced with the day name.\nCalendar._TT[\"DAY_FIRST\"] = \"הצג %s קודם\";\n\n// This may be locale-dependent.  It specifies the week-end days, as an array\n// of comma-separated numbers.  The numbers are from 0 to 6: 0 means Sunday, 1\n// means Monday, etc.\nCalendar._TT[\"WEEKEND\"] = \"6\";\n\nCalendar._TT[\"CLOSE\"] = \"סגור\";\nCalendar._TT[\"TODAY\"] = \"היום\";\nCalendar._TT[\"TIME_PART\"] = \"(שיפט-)לחץ וגרור כדי לשנות ערך\";\n\n// date formats\nCalendar._TT[\"DEF_DATE_FORMAT\"] = \"%Y-%m-%d\";\nCalendar._TT[\"TT_DATE_FORMAT\"] = \"%a, %b %e\";\n\nCalendar._TT[\"WK\"] = \"wk\";\nCalendar._TT[\"TIME\"] = \"שעה::\";\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/calendar-hr-utf8.js",
    "content": "/* Croatian language file for the DHTML Calendar version 0.9.2 \n* Author Krunoslav Zubrinic <krunoslav.zubrinic@vip.hr>, June 2003.\n* Feel free to use this script under the terms of the GNU Lesser General\n* Public License, as long as you do not remove or alter this notice.\n*/\nCalendar._DN = new Array\n(\"Nedjelja\",\n \"Ponedjeljak\",\n \"Utorak\",\n \"Srijeda\",\n \"Četvrtak\",\n \"Petak\",\n \"Subota\",\n \"Nedjelja\");\nCalendar._MN = new Array\n(\"Siječanj\",\n \"Veljača\",\n \"Ožujak\",\n \"Travanj\",\n \"Svibanj\",\n \"Lipanj\",\n \"Srpanj\",\n \"Kolovoz\",\n \"Rujan\",\n \"Listopad\",\n \"Studeni\",\n \"Prosinac\");\n\n// tooltips\nCalendar._TT = {};\nCalendar._TT[\"TOGGLE\"] = \"Promjeni dan s kojim počinje tjedan\";\nCalendar._TT[\"PREV_YEAR\"] = \"Prethodna godina (dugi pritisak za meni)\";\nCalendar._TT[\"PREV_MONTH\"] = \"Prethodni mjesec (dugi pritisak za meni)\";\nCalendar._TT[\"GO_TODAY\"] = \"Idi na tekući dan\";\nCalendar._TT[\"NEXT_MONTH\"] = \"Slijedeći mjesec (dugi pritisak za meni)\";\nCalendar._TT[\"NEXT_YEAR\"] = \"Slijedeća godina (dugi pritisak za meni)\";\nCalendar._TT[\"SEL_DATE\"] = \"Izaberite datum\";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \"Pritisni i povuci za promjenu pozicije\";\nCalendar._TT[\"PART_TODAY\"] = \" (today)\";\nCalendar._TT[\"MON_FIRST\"] = \"Prikaži ponedjeljak kao prvi dan\";\nCalendar._TT[\"SUN_FIRST\"] = \"Prikaži nedjelju kao prvi dan\";\nCalendar._TT[\"CLOSE\"] = \"Zatvori\";\nCalendar._TT[\"TODAY\"] = \"Danas\";\n\n// date formats\nCalendar._TT[\"DEF_DATE_FORMAT\"] = \"dd-mm-y\";\nCalendar._TT[\"TT_DATE_FORMAT\"] = \"DD, dd.mm.y\";\n\nCalendar._TT[\"WK\"] = \"Tje\";"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/calendar-hu.js",
    "content": "// ** I18N\n\n// Calendar HU language\n// Author: ???\n// Modifier: KARASZI Istvan, <jscalendar@spam.raszi.hu>\n// Encoding: any\n// Distributed under the same terms as the calendar itself.\n\n// For translators: please use UTF-8 if possible.  We strongly believe that\n// Unicode is the answer to a real internationalized world.  Also please\n// include your contact information in the header, as can be seen above.\n\n// full day names\nCalendar._DN = new Array\n(\"Vasrnap\",\n \"Htf\",\n \"Kedd\",\n \"Szerda\",\n \"Cstrtk\",\n \"Pntek\",\n \"Szombat\",\n \"Vasrnap\");\n\n// Please note that the following array of short day names (and the same goes\n// for short month names, _SMN) isn't absolutely necessary.  We give it here\n// for exemplification on how one can customize the short day names, but if\n// they are simply the first N letters of the full name you can simply say:\n//\n//   Calendar._SDN_len = N; // short day name length\n//   Calendar._SMN_len = N; // short month name length\n//\n// If N = 3 then this is not needed either since we assume a value of 3 if not\n// present, to be compatible with translation files that were written before\n// this feature.\n\n// short day names\nCalendar._SDN = new Array\n(\"v\",\n \"h\",\n \"k\",\n \"sze\",\n \"cs\",\n \"p\",\n \"szo\",\n \"v\");\n\n// full month names\nCalendar._MN = new Array\n(\"janur\",\n \"februr\",\n \"mrcius\",\n \"prilis\",\n \"mjus\",\n \"jnius\",\n \"jlius\",\n \"augusztus\",\n \"szeptember\",\n \"oktber\",\n \"november\",\n \"december\");\n\n// short month names\nCalendar._SMN = new Array\n(\"jan\",\n \"feb\",\n \"mr\",\n \"pr\",\n \"mj\",\n \"jn\",\n \"jl\",\n \"aug\",\n \"sze\",\n \"okt\",\n \"nov\",\n \"dec\");\n\n// tooltips\nCalendar._TT = {};\nCalendar._TT[\"INFO\"] = \"A kalendriumrl\";\n\nCalendar._TT[\"ABOUT\"] =\n\"DHTML dtum/id kivlaszt\\n\" +\n\"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\\n\" + // don't translate this this ;-)\n\"a legfrissebb verzi megtallhat: http://www.dynarch.com/projects/calendar/\\n\" +\n\"GNU LGPL alatt terjesztve.  Lsd a http://gnu.org/licenses/lgpl.html oldalt a rszletekhez.\" +\n\"\\n\\n\" +\n\"Dtum vlaszts:\\n\" +\n\"- hasznlja a \\xab, \\xbb gombokat az v kivlasztshoz\\n\" +\n\"- hasznlja a \" + String.fromCharCode(0x2039) + \", \" + String.fromCharCode(0x203a) + \" gombokat a hnap kivlasztshoz\\n\" +\n\"- tartsa lenyomva az egrgombot a gyors vlasztshoz.\";\nCalendar._TT[\"ABOUT_TIME\"] = \"\\n\\n\" +\n\"Id vlaszts:\\n\" +\n\"- kattintva nvelheti az idt\\n\" +\n\"- shift-tel kattintva cskkentheti\\n\" +\n\"- lenyomva tartva s hzva gyorsabban kivlaszthatja.\";\n\nCalendar._TT[\"PREV_YEAR\"] = \"Elz v (tartsa nyomva a menhz)\";\nCalendar._TT[\"PREV_MONTH\"] = \"Elz hnap (tartsa nyomva a menhz)\";\nCalendar._TT[\"GO_TODAY\"] = \"Mai napra ugrs\";\nCalendar._TT[\"NEXT_MONTH\"] = \"Kv. hnap (tartsa nyomva a menhz)\";\nCalendar._TT[\"NEXT_YEAR\"] = \"Kv. v (tartsa nyomva a menhz)\";\nCalendar._TT[\"SEL_DATE\"] = \"Vlasszon dtumot\";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \"Hzza a mozgatshoz\";\nCalendar._TT[\"PART_TODAY\"] = \" (ma)\";\n\n// the following is to inform that \"%s\" is to be the first day of week\n// %s will be replaced with the day name.\nCalendar._TT[\"DAY_FIRST\"] = \"%s legyen a ht els napja\";\n\n// This may be locale-dependent.  It specifies the week-end days, as an array\n// of comma-separated numbers.  The numbers are from 0 to 6: 0 means Sunday, 1\n// means Monday, etc.\nCalendar._TT[\"WEEKEND\"] = \"0,6\";\n\nCalendar._TT[\"CLOSE\"] = \"Bezr\";\nCalendar._TT[\"TODAY\"] = \"Ma\";\nCalendar._TT[\"TIME_PART\"] = \"(Shift-)Klikk vagy hzs az rtk vltoztatshoz\";\n\n// date formats\nCalendar._TT[\"DEF_DATE_FORMAT\"] = \"%Y-%m-%d\";\nCalendar._TT[\"TT_DATE_FORMAT\"] = \"%b %e, %a\";\n\nCalendar._TT[\"WK\"] = \"ht\";\nCalendar._TT[\"TIME\"] = \"id:\";\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/calendar-it.js",
    "content": "// ** I18N\n\n// Calendar EN language\n// Author: Mihai Bazon, <mihai_bazon@yahoo.com>\n// Translator: Fabio Di Bernardini, <altraqua@email.it>\n// Encoding: any\n// Distributed under the same terms as the calendar itself.\n\n// For translators: please use UTF-8 if possible.  We strongly believe that\n// Unicode is the answer to a real internationalized world.  Also please\n// include your contact information in the header, as can be seen above.\n\n// full day names\nCalendar._DN = new Array\n(\"Domenica\",\n \"Lunedì\",\n \"Martedì\",\n \"Mercoledì\",\n \"Giovedì\",\n \"Venerdì\",\n \"Sabato\",\n \"Domenica\");\n\n// Please note that the following array of short day names (and the same goes\n// for short month names, _SMN) isn't absolutely necessary.  We give it here\n// for exemplification on how one can customize the short day names, but if\n// they are simply the first N letters of the full name you can simply say:\n//\n//   Calendar._SDN_len = N; // short day name length\n//   Calendar._SMN_len = N; // short month name length\n//\n// If N = 3 then this is not needed either since we assume a value of 3 if not\n// present, to be compatible with translation files that were written before\n// this feature.\n\n// short day names\nCalendar._SDN = new Array\n(\"Dom\",\n \"Lun\",\n \"Mar\",\n \"Mer\",\n \"Gio\",\n \"Ven\",\n \"Sab\",\n \"Dom\");\n\n// full month names\nCalendar._MN = new Array\n(\"Gennaio\",\n \"Febbraio\",\n \"Marzo\",\n \"Aprile\",\n \"Maggio\",\n \"Giugno\",\n \"Luglio\",\n \"Augosto\",\n \"Settembre\",\n \"Ottobre\",\n \"Novembre\",\n \"Dicembre\");\n\n// short month names\nCalendar._SMN = new Array\n(\"Gen\",\n \"Feb\",\n \"Mar\",\n \"Apr\",\n \"Mag\",\n \"Giu\",\n \"Lug\",\n \"Ago\",\n \"Set\",\n \"Ott\",\n \"Nov\",\n \"Dic\");\n\n// tooltips\nCalendar._TT = {};\nCalendar._TT[\"INFO\"] = \"Informazioni sul calendario\";\n\nCalendar._TT[\"ABOUT\"] =\n\"DHTML Date/Time Selector\\n\" +\n\"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\\n\" + // don't translate this this ;-)\n\"Per gli aggiornamenti: http://www.dynarch.com/projects/calendar/\\n\" +\n\"Distribuito sotto licenza GNU LGPL.  Vedi http://gnu.org/licenses/lgpl.html per i dettagli.\" +\n\"\\n\\n\" +\n\"Selezione data:\\n\" +\n\"- Usa \\xab, \\xbb per selezionare l'anno\\n\" +\n\"- Usa  \" + String.fromCharCode(0x2039) + \", \" + String.fromCharCode(0x203a) + \" per i mesi\\n\" +\n\"- Tieni premuto a lungo il mouse per accedere alle funzioni di selezione veloce.\";\nCalendar._TT[\"ABOUT_TIME\"] = \"\\n\\n\" +\n\"Selezione orario:\\n\" +\n\"- Clicca sul numero per incrementarlo\\n\" +\n\"- o Shift+click per decrementarlo\\n\" +\n\"- o click e sinistra o destra per variarlo.\";\n\nCalendar._TT[\"PREV_YEAR\"] = \"Anno prec.(clicca a lungo per il menù)\";\nCalendar._TT[\"PREV_MONTH\"] = \"Mese prec. (clicca a lungo per il menù)\";\nCalendar._TT[\"GO_TODAY\"] = \"Oggi\";\nCalendar._TT[\"NEXT_MONTH\"] = \"Pross. mese (clicca a lungo per il menù)\";\nCalendar._TT[\"NEXT_YEAR\"] = \"Pross. anno (clicca a lungo per il menù)\";\nCalendar._TT[\"SEL_DATE\"] = \"Seleziona data\";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \"Trascina per spostarlo\";\nCalendar._TT[\"PART_TODAY\"] = \" (oggi)\";\n\n// the following is to inform that \"%s\" is to be the first day of week\n// %s will be replaced with the day name.\nCalendar._TT[\"DAY_FIRST\"] = \"Mostra prima %s\";\n\n// This may be locale-dependent.  It specifies the week-end days, as an array\n// of comma-separated numbers.  The numbers are from 0 to 6: 0 means Sunday, 1\n// means Monday, etc.\nCalendar._TT[\"WEEKEND\"] = \"0,6\";\n\nCalendar._TT[\"CLOSE\"] = \"Chiudi\";\nCalendar._TT[\"TODAY\"] = \"Oggi\";\nCalendar._TT[\"TIME_PART\"] = \"(Shift-)Click o trascina per cambiare il valore\";\n\n// date formats\nCalendar._TT[\"DEF_DATE_FORMAT\"] = \"%d-%m-%Y\";\nCalendar._TT[\"TT_DATE_FORMAT\"] = \"%a:%b:%e\";\n\nCalendar._TT[\"WK\"] = \"set\";\nCalendar._TT[\"TIME\"] = \"Ora:\";\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/calendar-jp.js",
    "content": "// ** I18N\nCalendar._DN = new Array\n(\"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"y\",\n \"\");\nCalendar._MN = new Array\n(\"1\",\n \"2\",\n \"3\",\n \"4\",\n \"5\",\n \"6\",\n \"7\",\n \"8\",\n \"9\",\n \"10\",\n \"11\",\n \"12\");\n\n// tooltips\nCalendar._TT = {};\nCalendar._TT[\"TOGGLE\"] = \"T̍ŏ̗j؂ւ\";\nCalendar._TT[\"PREV_YEAR\"] = \"ON\";\nCalendar._TT[\"PREV_MONTH\"] = \"O\";\nCalendar._TT[\"GO_TODAY\"] = \"\";\nCalendar._TT[\"NEXT_MONTH\"] = \"\";\nCalendar._TT[\"NEXT_YEAR\"] = \"N\";\nCalendar._TT[\"SEL_DATE\"] = \"tI\";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \"EBhËړ\";\nCalendar._TT[\"PART_TODAY\"] = \" ()\";\nCalendar._TT[\"MON_FIRST\"] = \"j擪\";\nCalendar._TT[\"SUN_FIRST\"] = \"j擪\";\nCalendar._TT[\"CLOSE\"] = \"\";\nCalendar._TT[\"TODAY\"] = \"\";\n\n// date formats\nCalendar._TT[\"DEF_DATE_FORMAT\"] = \"y-mm-dd\";\nCalendar._TT[\"TT_DATE_FORMAT\"] = \"%m %d (%a)\";\n\nCalendar._TT[\"WK\"] = \"T\";\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/calendar-ko-utf8.js",
    "content": "// ** I18N\n\n// Calendar EN language\n// Author: Mihai Bazon, <mihai_bazon@yahoo.com>\n// Translation: Yourim Yi <yyi@yourim.net>\n// Encoding: EUC-KR\n// lang : ko\n// Distributed under the same terms as the calendar itself.\n\n// For translators: please use UTF-8 if possible.  We strongly believe that\n// Unicode is the answer to a real internationalized world.  Also please\n// include your contact information in the header, as can be seen above.\n\n// full day names\n\nCalendar._DN = new Array\n(\"일요일\",\n \"월요일\",\n \"화요일\",\n \"수요일\",\n \"목요일\",\n \"금요일\",\n \"토요일\",\n \"일요일\");\n\n// Please note that the following array of short day names (and the same goes\n// for short month names, _SMN) isn't absolutely necessary.  We give it here\n// for exemplification on how one can customize the short day names, but if\n// they are simply the first N letters of the full name you can simply say:\n//\n//   Calendar._SDN_len = N; // short day name length\n//   Calendar._SMN_len = N; // short month name length\n//\n// If N = 3 then this is not needed either since we assume a value of 3 if not\n// present, to be compatible with translation files that were written before\n// this feature.\n\n// short day names\nCalendar._SDN = new Array\n(\"일\",\n \"월\",\n \"화\",\n \"수\",\n \"목\",\n \"금\",\n \"토\",\n \"일\");\n\n// full month names\nCalendar._MN = new Array\n(\"1월\",\n \"2월\",\n \"3월\",\n \"4월\",\n \"5월\",\n \"6월\",\n \"7월\",\n \"8월\",\n \"9월\",\n \"10월\",\n \"11월\",\n \"12월\");\n\n// short month names\nCalendar._SMN = new Array\n(\"1\",\n \"2\",\n \"3\",\n \"4\",\n \"5\",\n \"6\",\n \"7\",\n \"8\",\n \"9\",\n \"10\",\n \"11\",\n \"12\");\n\n// tooltips\nCalendar._TT = {};\nCalendar._TT[\"INFO\"] = \"calendar 에 대해서\";\n\nCalendar._TT[\"ABOUT\"] =\n\"DHTML Date/Time Selector\\n\" +\n\"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\\n\" + // don't translate this this ;-)\n\"\\n\"+\n\"최신 버전을 받으시려면 http://www.dynarch.com/projects/calendar/ 에 방문하세요\\n\" +\n\"\\n\"+\n\"GNU LGPL 라이센스로 배포됩니다. \\n\"+\n\"라이센스에 대한 자세한 내용은 http://gnu.org/licenses/lgpl.html 을 읽으세요.\" +\n\"\\n\\n\" +\n\"날짜 선택:\\n\" +\n\"- 연도를 선택하려면 \\xab, \\xbb 버튼을 사용합니다\\n\" +\n\"- 달을 선택하려면 \" + String.fromCharCode(0x2039) + \", \" + String.fromCharCode(0x203a) + \" 버튼을 누르세요\\n\" +\n\"- 계속 누르고 있으면 위 값들을 빠르게 선택하실 수 있습니다.\";\nCalendar._TT[\"ABOUT_TIME\"] = \"\\n\\n\" +\n\"시간 선택:\\n\" +\n\"- 마우스로 누르면 시간이 증가합니다\\n\" +\n\"- Shift 키와 함께 누르면 감소합니다\\n\" +\n\"- 누른 상태에서 마우스를 움직이면 좀 더 빠르게 값이 변합니다.\\n\";\n\nCalendar._TT[\"PREV_YEAR\"] = \"지난 해 (길게 누르면 목록)\";\nCalendar._TT[\"PREV_MONTH\"] = \"지난 달 (길게 누르면 목록)\";\nCalendar._TT[\"GO_TODAY\"] = \"오늘 날짜로\";\nCalendar._TT[\"NEXT_MONTH\"] = \"다음 달 (길게 누르면 목록)\";\nCalendar._TT[\"NEXT_YEAR\"] = \"다음 해 (길게 누르면 목록)\";\nCalendar._TT[\"SEL_DATE\"] = \"날짜를 선택하세요\";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \"마우스 드래그로 이동 하세요\";\nCalendar._TT[\"PART_TODAY\"] = \" (오늘)\";\nCalendar._TT[\"MON_FIRST\"] = \"월요일을 한 주의 시작 요일로\";\nCalendar._TT[\"SUN_FIRST\"] = \"일요일을 한 주의 시작 요일로\";\nCalendar._TT[\"CLOSE\"] = \"닫기\";\nCalendar._TT[\"TODAY\"] = \"오늘\";\nCalendar._TT[\"TIME_PART\"] = \"(Shift-)클릭 또는 드래그 하세요\";\n\n// date formats\nCalendar._TT[\"DEF_DATE_FORMAT\"] = \"%Y-%m-%d\";\nCalendar._TT[\"TT_DATE_FORMAT\"] = \"%b/%e [%a]\";\n\nCalendar._TT[\"WK\"] = \"주\";\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/calendar-ko.js",
    "content": "// ** I18N\n\n// Calendar EN language\n// Author: Mihai Bazon, <mihai_bazon@yahoo.com>\n// Translation: Yourim Yi <yyi@yourim.net>\n// Encoding: EUC-KR\n// lang : ko\n// Distributed under the same terms as the calendar itself.\n\n// For translators: please use UTF-8 if possible.  We strongly believe that\n// Unicode is the answer to a real internationalized world.  Also please\n// include your contact information in the header, as can be seen above.\n\n// full day names\n\nCalendar._DN = new Array\n(\"Ͽ\",\n \"\",\n \"ȭ\",\n \"\",\n \"\",\n \"ݿ\",\n \"\",\n \"Ͽ\");\n\n// Please note that the following array of short day names (and the same goes\n// for short month names, _SMN) isn't absolutely necessary.  We give it here\n// for exemplification on how one can customize the short day names, but if\n// they are simply the first N letters of the full name you can simply say:\n//\n//   Calendar._SDN_len = N; // short day name length\n//   Calendar._SMN_len = N; // short month name length\n//\n// If N = 3 then this is not needed either since we assume a value of 3 if not\n// present, to be compatible with translation files that were written before\n// this feature.\n\n// short day names\nCalendar._SDN = new Array\n(\"\",\n \"\",\n \"ȭ\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\");\n\n// full month names\nCalendar._MN = new Array\n(\"1\",\n \"2\",\n \"3\",\n \"4\",\n \"5\",\n \"6\",\n \"7\",\n \"8\",\n \"9\",\n \"10\",\n \"11\",\n \"12\");\n\n// short month names\nCalendar._SMN = new Array\n(\"1\",\n \"2\",\n \"3\",\n \"4\",\n \"5\",\n \"6\",\n \"7\",\n \"8\",\n \"9\",\n \"10\",\n \"11\",\n \"12\");\n\n// tooltips\nCalendar._TT = {};\nCalendar._TT[\"INFO\"] = \"calendar  ؼ\";\n\nCalendar._TT[\"ABOUT\"] =\n\"DHTML Date/Time Selector\\n\" +\n\"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\\n\" + // don't translate this this ;-)\n\"\\n\"+\n\"ֽ  ÷ http://www.dynarch.com/projects/calendar/  湮ϼ\\n\" +\n\"\\n\"+\n\"GNU LGPL ̼ ˴ϴ. \\n\"+\n\"̼  ڼ  http://gnu.org/licenses/lgpl.html  .\" +\n\"\\n\\n\" +\n\"¥ :\\n\" +\n\"-  Ϸ \\xab, \\xbb ư մϴ\\n\" +\n\"-  Ϸ \" + String.fromCharCode(0x2039) + \", \" + String.fromCharCode(0x203a) + \" ư \\n\" +\n\"-       Ͻ  ֽϴ.\";\nCalendar._TT[\"ABOUT_TIME\"] = \"\\n\\n\" +\n\"ð :\\n\" +\n\"- 콺  ð մϴ\\n\" +\n\"- Shift Ű Բ  մϴ\\n\" +\n\"-  ¿ 콺 ̸     մϴ.\\n\";\n\nCalendar._TT[\"PREV_YEAR\"] = \"  (  )\";\nCalendar._TT[\"PREV_MONTH\"] = \"  (  )\";\nCalendar._TT[\"GO_TODAY\"] = \" ¥\";\nCalendar._TT[\"NEXT_MONTH\"] = \"  (  )\";\nCalendar._TT[\"NEXT_YEAR\"] = \"  (  )\";\nCalendar._TT[\"SEL_DATE\"] = \"¥ ϼ\";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \"콺 巡׷ ̵ ϼ\";\nCalendar._TT[\"PART_TODAY\"] = \" ()\";\nCalendar._TT[\"MON_FIRST\"] = \"    Ϸ\";\nCalendar._TT[\"SUN_FIRST\"] = \"Ͽ    Ϸ\";\nCalendar._TT[\"CLOSE\"] = \"ݱ\";\nCalendar._TT[\"TODAY\"] = \"\";\nCalendar._TT[\"TIME_PART\"] = \"(Shift-)Ŭ Ǵ 巡 ϼ\";\n\n// date formats\nCalendar._TT[\"DEF_DATE_FORMAT\"] = \"%Y-%m-%d\";\nCalendar._TT[\"TT_DATE_FORMAT\"] = \"%b/%e [%a]\";\n\nCalendar._TT[\"WK\"] = \"\";\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/calendar-lt-utf8.js",
    "content": "// ** I18N\n\n// Calendar LT language\n// Author: Martynas Majeris, <martynas@solmetra.lt>\n// Encoding: UTF-8\n// Distributed under the same terms as the calendar itself.\n\n// For translators: please use UTF-8 if possible.  We strongly believe that\n// Unicode is the answer to a real internationalized world.  Also please\n// include your contact information in the header, as can be seen above.\n\n// full day names\nCalendar._DN = new Array\n(\"Sekmadienis\",\n \"Pirmadienis\",\n \"Antradienis\",\n \"Trečiadienis\",\n \"Ketvirtadienis\",\n \"Pentadienis\",\n \"Šeštadienis\",\n \"Sekmadienis\");\n\n// Please note that the following array of short day names (and the same goes\n// for short month names, _SMN) isn't absolutely necessary.  We give it here\n// for exemplification on how one can customize the short day names, but if\n// they are simply the first N letters of the full name you can simply say:\n//\n//   Calendar._SDN_len = N; // short day name length\n//   Calendar._SMN_len = N; // short month name length\n//\n// If N = 3 then this is not needed either since we assume a value of 3 if not\n// present, to be compatible with translation files that were written before\n// this feature.\n\n// short day names\nCalendar._SDN = new Array\n(\"Sek\",\n \"Pir\",\n \"Ant\",\n \"Tre\",\n \"Ket\",\n \"Pen\",\n \"Šeš\",\n \"Sek\");\n\n// full month names\nCalendar._MN = new Array\n(\"Sausis\",\n \"Vasaris\",\n \"Kovas\",\n \"Balandis\",\n \"Gegužė\",\n \"Birželis\",\n \"Liepa\",\n \"Rugpjūtis\",\n \"Rugsėjis\",\n \"Spalis\",\n \"Lapkritis\",\n \"Gruodis\");\n\n// short month names\nCalendar._SMN = new Array\n(\"Sau\",\n \"Vas\",\n \"Kov\",\n \"Bal\",\n \"Geg\",\n \"Bir\",\n \"Lie\",\n \"Rgp\",\n \"Rgs\",\n \"Spa\",\n \"Lap\",\n \"Gru\");\n\n// tooltips\nCalendar._TT = {};\nCalendar._TT[\"INFO\"] = \"Apie kalendorių\";\n\nCalendar._TT[\"ABOUT\"] =\n\"DHTML Date/Time Selector\\n\" +\n\"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\\n\" + // don't translate this this ;-)\n\"Naujausią versiją rasite: http://www.dynarch.com/projects/calendar/\\n\" +\n\"Platinamas pagal GNU LGPL licenciją. Aplankykite http://gnu.org/licenses/lgpl.html\" +\n\"\\n\\n\" +\n\"Datos pasirinkimas:\\n\" +\n\"- Metų pasirinkimas: \\xab, \\xbb\\n\" +\n\"- Mėnesio pasirinkimas: \" + String.fromCharCode(0x2039) + \", \" + String.fromCharCode(0x203a) + \"\\n\" +\n\"- Nuspauskite ir laikykite pelės klavišą greitesniam pasirinkimui.\";\nCalendar._TT[\"ABOUT_TIME\"] = \"\\n\\n\" +\n\"Laiko pasirinkimas:\\n\" +\n\"- Spustelkite ant valandų arba minučių - skaičius padidės vienetu.\\n\" +\n\"- Jei spausite kartu su Shift, skaičius sumažės.\\n\" +\n\"- Greitam pasirinkimui spustelkite ir pajudinkite pelę.\";\n\nCalendar._TT[\"PREV_YEAR\"] = \"Ankstesni metai (laikykite, jei norite meniu)\";\nCalendar._TT[\"PREV_MONTH\"] = \"Ankstesnis mėnuo (laikykite, jei norite meniu)\";\nCalendar._TT[\"GO_TODAY\"] = \"Pasirinkti šiandieną\";\nCalendar._TT[\"NEXT_MONTH\"] = \"Kitas mėnuo (laikykite, jei norite meniu)\";\nCalendar._TT[\"NEXT_YEAR\"] = \"Kiti metai (laikykite, jei norite meniu)\";\nCalendar._TT[\"SEL_DATE\"] = \"Pasirinkite datą\";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \"Tempkite\";\nCalendar._TT[\"PART_TODAY\"] = \" (šiandien)\";\nCalendar._TT[\"MON_FIRST\"] = \"Pirma savaitės diena - pirmadienis\";\nCalendar._TT[\"SUN_FIRST\"] = \"Pirma savaitės diena - sekmadienis\";\nCalendar._TT[\"CLOSE\"] = \"Uždaryti\";\nCalendar._TT[\"TODAY\"] = \"Šiandien\";\nCalendar._TT[\"TIME_PART\"] = \"Spustelkite arba tempkite jei norite pakeisti\";\n\n// date formats\nCalendar._TT[\"DEF_DATE_FORMAT\"] = \"%Y-%m-%d\";\nCalendar._TT[\"TT_DATE_FORMAT\"] = \"%A, %Y-%m-%d\";\n\nCalendar._TT[\"WK\"] = \"sav\";\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/calendar-lt.js",
    "content": "// ** I18N\n\n// Calendar LT language\n// Author: Martynas Majeris, <martynas@solmetra.lt>\n// Encoding: Windows-1257\n// Distributed under the same terms as the calendar itself.\n\n// For translators: please use UTF-8 if possible.  We strongly believe that\n// Unicode is the answer to a real internationalized world.  Also please\n// include your contact information in the header, as can be seen above.\n\n// full day names\nCalendar._DN = new Array\n(\"Sekmadienis\",\n \"Pirmadienis\",\n \"Antradienis\",\n \"Treiadienis\",\n \"Ketvirtadienis\",\n \"Pentadienis\",\n \"etadienis\",\n \"Sekmadienis\");\n\n// Please note that the following array of short day names (and the same goes\n// for short month names, _SMN) isn't absolutely necessary.  We give it here\n// for exemplification on how one can customize the short day names, but if\n// they are simply the first N letters of the full name you can simply say:\n//\n//   Calendar._SDN_len = N; // short day name length\n//   Calendar._SMN_len = N; // short month name length\n//\n// If N = 3 then this is not needed either since we assume a value of 3 if not\n// present, to be compatible with translation files that were written before\n// this feature.\n\n// short day names\nCalendar._SDN = new Array\n(\"Sek\",\n \"Pir\",\n \"Ant\",\n \"Tre\",\n \"Ket\",\n \"Pen\",\n \"e\",\n \"Sek\");\n\n// full month names\nCalendar._MN = new Array\n(\"Sausis\",\n \"Vasaris\",\n \"Kovas\",\n \"Balandis\",\n \"Gegu\",\n \"Birelis\",\n \"Liepa\",\n \"Rugpjtis\",\n \"Rugsjis\",\n \"Spalis\",\n \"Lapkritis\",\n \"Gruodis\");\n\n// short month names\nCalendar._SMN = new Array\n(\"Sau\",\n \"Vas\",\n \"Kov\",\n \"Bal\",\n \"Geg\",\n \"Bir\",\n \"Lie\",\n \"Rgp\",\n \"Rgs\",\n \"Spa\",\n \"Lap\",\n \"Gru\");\n\n// tooltips\nCalendar._TT = {};\nCalendar._TT[\"INFO\"] = \"Apie kalendori\";\n\nCalendar._TT[\"ABOUT\"] =\n\"DHTML Date/Time Selector\\n\" +\n\"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\\n\" + // don't translate this this ;-)\n\"Naujausi versij rasite: http://www.dynarch.com/projects/calendar/\\n\" +\n\"Platinamas pagal GNU LGPL licencij. Aplankykite http://gnu.org/licenses/lgpl.html\" +\n\"\\n\\n\" +\n\"Datos pasirinkimas:\\n\" +\n\"- Met pasirinkimas: \\xab, \\xbb\\n\" +\n\"- Mnesio pasirinkimas: \" + String.fromCharCode(0x2039) + \", \" + String.fromCharCode(0x203a) + \"\\n\" +\n\"- Nuspauskite ir laikykite pels klavi greitesniam pasirinkimui.\";\nCalendar._TT[\"ABOUT_TIME\"] = \"\\n\\n\" +\n\"Laiko pasirinkimas:\\n\" +\n\"- Spustelkite ant valand arba minui - skaius padids vienetu.\\n\" +\n\"- Jei spausite kartu su Shift, skaiius sumas.\\n\" +\n\"- Greitam pasirinkimui spustelkite ir pajudinkite pel.\";\n\nCalendar._TT[\"PREV_YEAR\"] = \"Ankstesni metai (laikykite, jei norite meniu)\";\nCalendar._TT[\"PREV_MONTH\"] = \"Ankstesnis mnuo (laikykite, jei norite meniu)\";\nCalendar._TT[\"GO_TODAY\"] = \"Pasirinkti iandien\";\nCalendar._TT[\"NEXT_MONTH\"] = \"Kitas mnuo (laikykite, jei norite meniu)\";\nCalendar._TT[\"NEXT_YEAR\"] = \"Kiti metai (laikykite, jei norite meniu)\";\nCalendar._TT[\"SEL_DATE\"] = \"Pasirinkite dat\";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \"Tempkite\";\nCalendar._TT[\"PART_TODAY\"] = \" (iandien)\";\nCalendar._TT[\"MON_FIRST\"] = \"Pirma savaits diena - pirmadienis\";\nCalendar._TT[\"SUN_FIRST\"] = \"Pirma savaits diena - sekmadienis\";\nCalendar._TT[\"CLOSE\"] = \"Udaryti\";\nCalendar._TT[\"TODAY\"] = \"iandien\";\nCalendar._TT[\"TIME_PART\"] = \"Spustelkite arba tempkite jei norite pakeisti\";\n\n// date formats\nCalendar._TT[\"DEF_DATE_FORMAT\"] = \"%Y-%m-%d\";\nCalendar._TT[\"TT_DATE_FORMAT\"] = \"%A, %Y-%m-%d\";\n\nCalendar._TT[\"WK\"] = \"sav\";\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/calendar-lv.js",
    "content": "// ** I18N\n\n// Calendar LV language\n// Author: Juris Valdovskis, <juris@dc.lv>\n// Encoding: cp1257\n// Distributed under the same terms as the calendar itself.\n\n// For translators: please use UTF-8 if possible.  We strongly believe that\n// Unicode is the answer to a real internationalized world.  Also please\n// include your contact information in the header, as can be seen above.\n\n// full day names\nCalendar._DN = new Array\n(\"Svtdiena\",\n \"Pirmdiena\",\n \"Otrdiena\",\n \"Trediena\",\n \"Ceturdiena\",\n \"Piektdiena\",\n \"Sestdiena\",\n \"Svtdiena\");\n\n// Please note that the following array of short day names (and the same goes\n// for short month names, _SMN) isn't absolutely necessary.  We give it here\n// for exemplification on how one can customize the short day names, but if\n// they are simply the first N letters of the full name you can simply say:\n//\n//   Calendar._SDN_len = N; // short day name length\n//   Calendar._SMN_len = N; // short month name length\n//\n// If N = 3 then this is not needed either since we assume a value of 3 if not\n// present, to be compatible with translation files that were written before\n// this feature.\n\n// short day names\nCalendar._SDN = new Array\n(\"Sv\",\n \"Pr\",\n \"Ot\",\n \"Tr\",\n \"Ce\",\n \"Pk\",\n \"Se\",\n \"Sv\");\n\n// full month names\nCalendar._MN = new Array\n(\"Janvris\",\n \"Februris\",\n \"Marts\",\n \"Aprlis\",\n \"Maijs\",\n \"Jnijs\",\n \"Jlijs\",\n \"Augusts\",\n \"Septembris\",\n \"Oktobris\",\n \"Novembris\",\n \"Decembris\");\n\n// short month names\nCalendar._SMN = new Array\n(\"Jan\",\n \"Feb\",\n \"Mar\",\n \"Apr\",\n \"Mai\",\n \"Jn\",\n \"Jl\",\n \"Aug\",\n \"Sep\",\n \"Okt\",\n \"Nov\",\n \"Dec\");\n\n// tooltips\nCalendar._TT = {};\nCalendar._TT[\"INFO\"] = \"Par kalendru\";\n\nCalendar._TT[\"ABOUT\"] =\n\"DHTML Date/Time Selector\\n\" +\n\"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\\n\" + // don't translate this this ;-)\n\"For latest version visit: http://www.dynarch.com/projects/calendar/\\n\" +\n\"Distributed under GNU LGPL.  See http://gnu.org/licenses/lgpl.html for details.\" +\n\"\\n\\n\" +\n\"Datuma izvle:\\n\" +\n\"- Izmanto \\xab, \\xbb pogas, lai izvltos gadu\\n\" +\n\"- Izmanto \" + String.fromCharCode(0x2039) + \", \" + String.fromCharCode(0x203a) + \"pogas, lai izvltos mnesi\\n\" +\n\"- Turi nospiestu peles pogu uz jebkuru no augstk mintajm pogm, lai patrintu izvli.\";\nCalendar._TT[\"ABOUT_TIME\"] = \"\\n\\n\" +\n\"Laika izvle:\\n\" +\n\"- Uzklikini uz jebkuru no laika dam, lai palielintu to\\n\" +\n\"- vai Shift-klikis, lai samazintu to\\n\" +\n\"- vai noklikini un velc uz attiecgo virzienu lai maintu trk.\";\n\nCalendar._TT[\"PREV_YEAR\"] = \"Iepr. gads (turi izvlnei)\";\nCalendar._TT[\"PREV_MONTH\"] = \"Iepr. mnesis (turi izvlnei)\";\nCalendar._TT[\"GO_TODAY\"] = \"odien\";\nCalendar._TT[\"NEXT_MONTH\"] = \"Nkoais mnesis (turi izvlnei)\";\nCalendar._TT[\"NEXT_YEAR\"] = \"Nkoais gads (turi izvlnei)\";\nCalendar._TT[\"SEL_DATE\"] = \"Izvlies datumu\";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \"Velc, lai prvietotu\";\nCalendar._TT[\"PART_TODAY\"] = \" (odien)\";\n\n// the following is to inform that \"%s\" is to be the first day of week\n// %s will be replaced with the day name.\nCalendar._TT[\"DAY_FIRST\"] = \"Attlot %s k pirmo\";\n\n// This may be locale-dependent.  It specifies the week-end days, as an array\n// of comma-separated numbers.  The numbers are from 0 to 6: 0 means Sunday, 1\n// means Monday, etc.\nCalendar._TT[\"WEEKEND\"] = \"1,7\";\n\nCalendar._TT[\"CLOSE\"] = \"Aizvrt\";\nCalendar._TT[\"TODAY\"] = \"odien\";\nCalendar._TT[\"TIME_PART\"] = \"(Shift-)Klikis vai prvieto, lai maintu\";\n\n// date formats\nCalendar._TT[\"DEF_DATE_FORMAT\"] = \"%d-%m-%Y\";\nCalendar._TT[\"TT_DATE_FORMAT\"] = \"%a, %e %b\";\n\nCalendar._TT[\"WK\"] = \"wk\";\nCalendar._TT[\"TIME\"] = \"Laiks:\";\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/calendar-nl.js",
    "content": "// ** I18N\nCalendar._DN = new Array\n(\"Zondag\",\n \"Maandag\",\n \"Dinsdag\",\n \"Woensdag\",\n \"Donderdag\",\n \"Vrijdag\",\n \"Zaterdag\",\n \"Zondag\");\n\nCalendar._SDN_len = 2;\n\nCalendar._MN = new Array\n(\"Januari\",\n \"Februari\",\n \"Maart\",\n \"April\",\n \"Mei\",\n \"Juni\",\n \"Juli\",\n \"Augustus\",\n \"September\",\n \"Oktober\",\n \"November\",\n \"December\");\n\n// tooltips\nCalendar._TT = {};\nCalendar._TT[\"INFO\"] = \"Info\";\n\nCalendar._TT[\"ABOUT\"] =\n\"DHTML Datum/Tijd Selector\\n\" +\n\"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\\n\" +\n\"Ga voor de meest recente versie naar: http://www.dynarch.com/projects/calendar/\\n\" +\n\"Verspreid onder de GNU LGPL. Zie http://gnu.org/licenses/lgpl.html voor details.\" +\n\"\\n\\n\" +\n\"Datum selectie:\\n\" +\n\"- Gebruik de \\xab \\xbb knoppen om een jaar te selecteren\\n\" +\n\"- Gebruik de \" + String.fromCharCode(0x2039) + \", \" + String.fromCharCode(0x203a) + \" knoppen om een maand te selecteren\\n\" +\n\"- Houd de muis ingedrukt op de genoemde knoppen voor een snellere selectie.\";\nCalendar._TT[\"ABOUT_TIME\"] = \"\\n\\n\" +\n\"Tijd selectie:\\n\" +\n\"- Klik op een willekeurig onderdeel van het tijd gedeelte om het te verhogen\\n\" +\n\"- of Shift-klik om het te verlagen\\n\" +\n\"- of klik en sleep voor een snellere selectie.\";\n\n//Calendar._TT[\"TOGGLE\"] = \"Selecteer de eerste week-dag\";\nCalendar._TT[\"PREV_YEAR\"] = \"Vorig jaar (ingedrukt voor menu)\";\nCalendar._TT[\"PREV_MONTH\"] = \"Vorige maand (ingedrukt voor menu)\";\nCalendar._TT[\"GO_TODAY\"] = \"Ga naar Vandaag\";\nCalendar._TT[\"NEXT_MONTH\"] = \"Volgende maand (ingedrukt voor menu)\";\nCalendar._TT[\"NEXT_YEAR\"] = \"Volgend jaar (ingedrukt voor menu)\";\nCalendar._TT[\"SEL_DATE\"] = \"Selecteer datum\";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \"Klik en sleep om te verplaatsen\";\nCalendar._TT[\"PART_TODAY\"] = \" (vandaag)\";\n//Calendar._TT[\"MON_FIRST\"] = \"Toon Maandag eerst\";\n//Calendar._TT[\"SUN_FIRST\"] = \"Toon Zondag eerst\";\n\nCalendar._TT[\"DAY_FIRST\"] = \"Toon %s eerst\";\n\nCalendar._TT[\"WEEKEND\"] = \"0,6\";\n\nCalendar._TT[\"CLOSE\"] = \"Sluiten\";\nCalendar._TT[\"TODAY\"] = \"(vandaag)\";\nCalendar._TT[\"TIME_PART\"] = \"(Shift-)Klik of sleep om de waarde te veranderen\";\n\n// date formats\nCalendar._TT[\"DEF_DATE_FORMAT\"] = \"%d-%m-%Y\";\nCalendar._TT[\"TT_DATE_FORMAT\"] = \"%a, %e %b %Y\";\n\nCalendar._TT[\"WK\"] = \"wk\";\nCalendar._TT[\"TIME\"] = \"Tijd:\";"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/calendar-no.js",
    "content": "// ** I18N\n\n// Calendar NO language\n// Author: Daniel Holmen, <daniel.holmen@ciber.no>\n// Encoding: UTF-8\n// Distributed under the same terms as the calendar itself.\n\n// For translators: please use UTF-8 if possible.  We strongly believe that\n// Unicode is the answer to a real internationalized world.  Also please\n// include your contact information in the header, as can be seen above.\n\n// full day names\nCalendar._DN = new Array\n(\"Søndag\",\n \"Mandag\",\n \"Tirsdag\",\n \"Onsdag\",\n \"Torsdag\",\n \"Fredag\",\n \"Lørdag\",\n \"Søndag\");\n\n// Please note that the following array of short day names (and the same goes\n// for short month names, _SMN) isn't absolutely necessary.  We give it here\n// for exemplification on how one can customize the short day names, but if\n// they are simply the first N letters of the full name you can simply say:\n//\n//   Calendar._SDN_len = N; // short day name length\n//   Calendar._SMN_len = N; // short month name length\n//\n// If N = 3 then this is not needed either since we assume a value of 3 if not\n// present, to be compatible with translation files that were written before\n// this feature.\n\n// short day names\nCalendar._SDN = new Array\n(\"Søn\",\n \"Man\",\n \"Tir\",\n \"Ons\",\n \"Tor\",\n \"Fre\",\n \"Lør\",\n \"Søn\");\n\n// full month names\nCalendar._MN = new Array\n(\"Januar\",\n \"Februar\",\n \"Mars\",\n \"April\",\n \"Mai\",\n \"Juni\",\n \"Juli\",\n \"August\",\n \"September\",\n \"Oktober\",\n \"November\",\n \"Desember\");\n\n// short month names\nCalendar._SMN = new Array\n(\"Jan\",\n \"Feb\",\n \"Mar\",\n \"Apr\",\n \"Mai\",\n \"Jun\",\n \"Jul\",\n \"Aug\",\n \"Sep\",\n \"Okt\",\n \"Nov\",\n \"Des\");\n\n// tooltips\nCalendar._TT = {};\nCalendar._TT[\"INFO\"] = \"Om kalenderen\";\n\nCalendar._TT[\"ABOUT\"] =\n\"DHTML Dato-/Tidsvelger\\n\" +\n\"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\\n\" + // don't translate this this ;-)\n\"For nyeste versjon, gå til: http://www.dynarch.com/projects/calendar/\\n\" +\n\"Distribuert under GNU LGPL.  Se http://gnu.org/licenses/lgpl.html for detaljer.\" +\n\"\\n\\n\" +\n\"Datovalg:\\n\" +\n\"- Bruk knappene \\xab og \\xbb for å velge år\\n\" +\n\"- Bruk knappene \" + String.fromCharCode(0x2039) + \" og \" + String.fromCharCode(0x203a) + \" for å velge måned\\n\" +\n\"- Hold inne musknappen eller knappene over for raskere valg.\";\nCalendar._TT[\"ABOUT_TIME\"] = \"\\n\\n\" +\n\"Tidsvalg:\\n\" +\n\"- Klikk på en av tidsdelene for å øke den\\n\" +\n\"- eller Shift-klikk for å senke verdien\\n\" +\n\"- eller klikk-og-dra for raskere valg..\";\n\nCalendar._TT[\"PREV_YEAR\"] = \"Forrige. år (hold for meny)\";\nCalendar._TT[\"PREV_MONTH\"] = \"Forrige. måned (hold for meny)\";\nCalendar._TT[\"GO_TODAY\"] = \"Gå til idag\";\nCalendar._TT[\"NEXT_MONTH\"] = \"Neste måned (hold for meny)\";\nCalendar._TT[\"NEXT_YEAR\"] = \"Neste år (hold for meny)\";\nCalendar._TT[\"SEL_DATE\"] = \"Velg dato\";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \"Dra for å flytte\";\nCalendar._TT[\"PART_TODAY\"] = \" (idag)\";\nCalendar._TT[\"MON_FIRST\"] = \"Vis mandag først\";\nCalendar._TT[\"SUN_FIRST\"] = \"Vis søndag først\";\nCalendar._TT[\"CLOSE\"] = \"Lukk\";\nCalendar._TT[\"TODAY\"] = \"Idag\";\nCalendar._TT[\"TIME_PART\"] = \"(Shift-)Klikk eller dra for å endre verdi\";\n\n// date formats\nCalendar._TT[\"DEF_DATE_FORMAT\"] = \"%d.%m.%Y\";\nCalendar._TT[\"TT_DATE_FORMAT\"] = \"%a, %b %e\";\n\nCalendar._TT[\"WK\"] = \"uke\";"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/calendar-pl-utf8.js",
    "content": "﻿// ** I18N\n\n// Calendar PL language\n// Author: Dariusz Pietrzak, <eyck@ghost.anime.pl>\n// Author: Janusz Piwowarski, <jpiw@go2.pl>\n// Encoding: utf-8\n// Distributed under the same terms as the calendar itself.\n\nCalendar._DN = new Array\n(\"Niedziela\",\n \"Poniedziałek\",\n \"Wtorek\",\n \"Środa\",\n \"Czwartek\",\n \"Piątek\",\n \"Sobota\",\n \"Niedziela\");\nCalendar._SDN = new Array\n(\"Nie\",\n \"Pn\",\n \"Wt\",\n \"Śr\",\n \"Cz\",\n \"Pt\",\n \"So\",\n \"Nie\");\nCalendar._MN = new Array\n(\"Styczeń\",\n \"Luty\",\n \"Marzec\",\n \"Kwiecień\",\n \"Maj\",\n \"Czerwiec\",\n \"Lipiec\",\n \"Sierpień\",\n \"Wrzesień\",\n \"Październik\",\n \"Listopad\",\n \"Grudzień\");\nCalendar._SMN = new Array\n(\"Sty\",\n \"Lut\",\n \"Mar\",\n \"Kwi\",\n \"Maj\",\n \"Cze\",\n \"Lip\",\n \"Sie\",\n \"Wrz\",\n \"Paź\",\n \"Lis\",\n \"Gru\");\n\n// tooltips\nCalendar._TT = {};\nCalendar._TT[\"INFO\"] = \"O kalendarzu\";\n\nCalendar._TT[\"ABOUT\"] =\n\"DHTML Date/Time Selector\\n\" +\n\"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\\n\" + // don't translate this this ;-)\n\"Aby pobrać najnowszą wersję, odwiedź: http://www.dynarch.com/projects/calendar/\\n\" +\n\"Dostępny na licencji GNU LGPL. Zobacz szczegóły na http://gnu.org/licenses/lgpl.html.\" +\n\"\\n\\n\" +\n\"Wybór daty:\\n\" +\n\"- Użyj przycisków \\xab, \\xbb by wybrać rok\\n\" +\n\"- Użyj przycisków \" + String.fromCharCode(0x2039) + \", \" + String.fromCharCode(0x203a) + \" by wybrać miesiąc\\n\" +\n\"- Przytrzymaj klawisz myszy nad jednym z powyższych przycisków dla szybszego wyboru.\";\nCalendar._TT[\"ABOUT_TIME\"] = \"\\n\\n\" +\n\"Wybór czasu:\\n\" +\n\"- Kliknij na jednym z pól czasu by zwiększyć jego wartość\\n\" +\n\"- lub kliknij trzymając Shift by zmiejszyć jego wartość\\n\" +\n\"- lub kliknij i przeciągnij dla szybszego wyboru.\";\n\n//Calendar._TT[\"TOGGLE\"] = \"Zmień pierwszy dzień tygodnia\";\nCalendar._TT[\"PREV_YEAR\"] = \"Poprzedni rok (przytrzymaj dla menu)\";\nCalendar._TT[\"PREV_MONTH\"] = \"Poprzedni miesiąc (przytrzymaj dla menu)\";\nCalendar._TT[\"GO_TODAY\"] = \"Idź do dzisiaj\";\nCalendar._TT[\"NEXT_MONTH\"] = \"Następny miesiąc (przytrzymaj dla menu)\";\nCalendar._TT[\"NEXT_YEAR\"] = \"Następny rok (przytrzymaj dla menu)\";\nCalendar._TT[\"SEL_DATE\"] = \"Wybierz datę\";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \"Przeciągnij by przesunąć\";\nCalendar._TT[\"PART_TODAY\"] = \" (dzisiaj)\";\nCalendar._TT[\"MON_FIRST\"] = \"Wyświetl poniedziałek jako pierwszy\";\nCalendar._TT[\"SUN_FIRST\"] = \"Wyświetl niedzielę jako pierwszą\";\nCalendar._TT[\"CLOSE\"] = \"Zamknij\";\nCalendar._TT[\"TODAY\"] = \"Dzisiaj\";\nCalendar._TT[\"TIME_PART\"] = \"(Shift-)Kliknij lub przeciągnij by zmienić wartość\";\n\n// date formats\nCalendar._TT[\"DEF_DATE_FORMAT\"] = \"%Y-%m-%d\";\nCalendar._TT[\"TT_DATE_FORMAT\"] = \"%e %B, %A\";\n\nCalendar._TT[\"WK\"] = \"ty\";\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/calendar-pl.js",
    "content": "// ** I18N\n// Calendar PL language\n// Author: Artur Filipiak, <imagen@poczta.fm>\n// January, 2004\n// Encoding: UTF-8\nCalendar._DN = new Array\n(\"Niedziela\", \"Poniedziałek\", \"Wtorek\", \"Środa\", \"Czwartek\", \"Piątek\", \"Sobota\", \"Niedziela\");\n\nCalendar._SDN = new Array\n(\"N\", \"Pn\", \"Wt\", \"Śr\", \"Cz\", \"Pt\", \"So\", \"N\");\n\nCalendar._MN = new Array\n(\"Styczeń\", \"Luty\", \"Marzec\", \"Kwiecień\", \"Maj\", \"Czerwiec\", \"Lipiec\", \"Sierpień\", \"Wrzesień\", \"Październik\", \"Listopad\", \"Grudzień\");\n\nCalendar._SMN = new Array\n(\"Sty\", \"Lut\", \"Mar\", \"Kwi\", \"Maj\", \"Cze\", \"Lip\", \"Sie\", \"Wrz\", \"Paź\", \"Lis\", \"Gru\");\n\n// tooltips\nCalendar._TT = {};\nCalendar._TT[\"INFO\"] = \"O kalendarzu\";\n\nCalendar._TT[\"ABOUT\"] =\n\"DHTML Date/Time Selector\\n\" +\n\"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\\n\" + // don't translate this this ;-)\n\"For latest version visit: http://www.dynarch.com/projects/calendar/\\n\" +\n\"Distributed under GNU LGPL.  See http://gnu.org/licenses/lgpl.html for details.\" +\n\"\\n\\n\" +\n\"Wybór daty:\\n\" +\n\"- aby wybrać rok użyj przycisków \\xab, \\xbb\\n\" +\n\"- aby wybrać miesiąc użyj przycisków \" + String.fromCharCode(0x2039) + \", \" + String.fromCharCode(0x203a) + \"\\n\" +\n\"- aby przyspieszyć wybór przytrzymaj wciśnięty przycisk myszy nad ww. przyciskami.\";\nCalendar._TT[\"ABOUT_TIME\"] = \"\\n\\n\" +\n\"Wybór czasu:\\n\" +\n\"- aby zwiększyć wartość kliknij na dowolnym elemencie selekcji czasu\\n\" +\n\"- aby zmniejszyć wartość użyj dodatkowo klawisza Shift\\n\" +\n\"- możesz również poruszać myszkę w lewo i prawo wraz z wciśniętym lewym klawiszem.\";\n\nCalendar._TT[\"PREV_YEAR\"] = \"Poprz. rok (przytrzymaj dla menu)\";\nCalendar._TT[\"PREV_MONTH\"] = \"Poprz. miesiąc (przytrzymaj dla menu)\";\nCalendar._TT[\"GO_TODAY\"] = \"Pokaż dziś\";\nCalendar._TT[\"NEXT_MONTH\"] = \"Nast. miesiąc (przytrzymaj dla menu)\";\nCalendar._TT[\"NEXT_YEAR\"] = \"Nast. rok (przytrzymaj dla menu)\";\nCalendar._TT[\"SEL_DATE\"] = \"Wybierz datę\";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \"Przesuń okienko\";\nCalendar._TT[\"PART_TODAY\"] = \" (dziś)\";\nCalendar._TT[\"MON_FIRST\"] = \"Pokaż Poniedziałek jako pierwszy\";\nCalendar._TT[\"SUN_FIRST\"] = \"Pokaż Niedzielę jako pierwszą\";\nCalendar._TT[\"CLOSE\"] = \"Zamknij\";\nCalendar._TT[\"TODAY\"] = \"Dziś\";\nCalendar._TT[\"TIME_PART\"] = \"(Shift-)klik | drag, aby zmienić wartość\";\n\n// date formats\nCalendar._TT[\"DEF_DATE_FORMAT\"] = \"%Y.%m.%d\";\nCalendar._TT[\"TT_DATE_FORMAT\"] = \"%a, %b %e\";\n\nCalendar._TT[\"WK\"] = \"wk\";"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/calendar-pt.js",
    "content": "// ** I18N\n\n// Calendar pt_BR language\n// Author: Adalberto Machado, <betosm@terra.com.br>\n// Encoding: any\n// Distributed under the same terms as the calendar itself.\n\n// For translators: please use UTF-8 if possible.  We strongly believe that\n// Unicode is the answer to a real internationalized world.  Also please\n// include your contact information in the header, as can be seen above.\n\n// full day names\nCalendar._DN = new Array\n(\"Domingo\",\n \"Segunda\",\n \"Terca\",\n \"Quarta\",\n \"Quinta\",\n \"Sexta\",\n \"Sabado\",\n \"Domingo\");\n\n// Please note that the following array of short day names (and the same goes\n// for short month names, _SMN) isn't absolutely necessary.  We give it here\n// for exemplification on how one can customize the short day names, but if\n// they are simply the first N letters of the full name you can simply say:\n//\n//   Calendar._SDN_len = N; // short day name length\n//   Calendar._SMN_len = N; // short month name length\n//\n// If N = 3 then this is not needed either since we assume a value of 3 if not\n// present, to be compatible with translation files that were written before\n// this feature.\n\n// short day names\nCalendar._SDN = new Array\n(\"Dom\",\n \"Seg\",\n \"Ter\",\n \"Qua\",\n \"Qui\",\n \"Sex\",\n \"Sab\",\n \"Dom\");\n\n// full month names\nCalendar._MN = new Array\n(\"Janeiro\",\n \"Fevereiro\",\n \"Marco\",\n \"Abril\",\n \"Maio\",\n \"Junho\",\n \"Julho\",\n \"Agosto\",\n \"Setembro\",\n \"Outubro\",\n \"Novembro\",\n \"Dezembro\");\n\n// short month names\nCalendar._SMN = new Array\n(\"Jan\",\n \"Fev\",\n \"Mar\",\n \"Abr\",\n \"Mai\",\n \"Jun\",\n \"Jul\",\n \"Ago\",\n \"Set\",\n \"Out\",\n \"Nov\",\n \"Dez\");\n\n// tooltips\nCalendar._TT = {};\nCalendar._TT[\"INFO\"] = \"Sobre o calendario\";\n\nCalendar._TT[\"ABOUT\"] =\n\"DHTML Date/Time Selector\\n\" +\n\"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\\n\" + // don't translate this this ;-)\n\"Ultima versao visite: http://www.dynarch.com/projects/calendar/\\n\" +\n\"Distribuido sobre GNU LGPL.  Veja http://gnu.org/licenses/lgpl.html para detalhes.\" +\n\"\\n\\n\" +\n\"Selecao de data:\\n\" +\n\"- Use os botoes \\xab, \\xbb para selecionar o ano\\n\" +\n\"- Use os botoes \" + String.fromCharCode(0x2039) + \", \" + String.fromCharCode(0x203a) + \" para selecionar o mes\\n\" +\n\"- Segure o botao do mouse em qualquer um desses botoes para selecao rapida.\";\nCalendar._TT[\"ABOUT_TIME\"] = \"\\n\\n\" +\n\"Selecao de hora:\\n\" +\n\"- Clique em qualquer parte da hora para incrementar\\n\" +\n\"- ou Shift-click para decrementar\\n\" +\n\"- ou clique e segure para selecao rapida.\";\n\nCalendar._TT[\"PREV_YEAR\"] = \"Ant. ano (segure para menu)\";\nCalendar._TT[\"PREV_MONTH\"] = \"Ant. mes (segure para menu)\";\nCalendar._TT[\"GO_TODAY\"] = \"Hoje\";\nCalendar._TT[\"NEXT_MONTH\"] = \"Prox. mes (segure para menu)\";\nCalendar._TT[\"NEXT_YEAR\"] = \"Prox. ano (segure para menu)\";\nCalendar._TT[\"SEL_DATE\"] = \"Selecione a data\";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \"Arraste para mover\";\nCalendar._TT[\"PART_TODAY\"] = \" (hoje)\";\n\n// the following is to inform that \"%s\" is to be the first day of week\n// %s will be replaced with the day name.\nCalendar._TT[\"DAY_FIRST\"] = \"Mostre %s primeiro\";\n\n// This may be locale-dependent.  It specifies the week-end days, as an array\n// of comma-separated numbers.  The numbers are from 0 to 6: 0 means Sunday, 1\n// means Monday, etc.\nCalendar._TT[\"WEEKEND\"] = \"0,6\";\n\nCalendar._TT[\"CLOSE\"] = \"Fechar\";\nCalendar._TT[\"TODAY\"] = \"Hoje\";\nCalendar._TT[\"TIME_PART\"] = \"(Shift-)Click ou arraste para mudar valor\";\n\n// date formats\nCalendar._TT[\"DEF_DATE_FORMAT\"] = \"%d/%m/%Y\";\nCalendar._TT[\"TT_DATE_FORMAT\"] = \"%a, %e %b\";\n\nCalendar._TT[\"WK\"] = \"sm\";\nCalendar._TT[\"TIME\"] = \"Hora:\";\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/calendar-ro.js",
    "content": "// ** I18N\nCalendar._DN = new Array\n(\"Duminică\",\n \"Luni\",\n \"Marţi\",\n \"Miercuri\",\n \"Joi\",\n \"Vineri\",\n \"Sâmbătă\",\n \"Duminică\");\nCalendar._SDN_len = 2;\nCalendar._MN = new Array\n(\"Ianuarie\",\n \"Februarie\",\n \"Martie\",\n \"Aprilie\",\n \"Mai\",\n \"Iunie\",\n \"Iulie\",\n \"August\",\n \"Septembrie\",\n \"Octombrie\",\n \"Noiembrie\",\n \"Decembrie\");\n\n// tooltips\nCalendar._TT = {};\n\nCalendar._TT[\"INFO\"] = \"Despre calendar\";\n\nCalendar._TT[\"ABOUT\"] =\n\"DHTML Date/Time Selector\\n\" +\n\"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\\n\" + // don't translate this this ;-)\n\"Pentru ultima versiune vizitaţi: http://www.dynarch.com/projects/calendar/\\n\" +\n\"Distribuit sub GNU LGPL.  See http://gnu.org/licenses/lgpl.html for details.\" +\n\"\\n\\n\" +\n\"Selecţia datei:\\n\" +\n\"- Folosiţi butoanele \\xab, \\xbb pentru a selecta anul\\n\" +\n\"- Folosiţi butoanele \" + String.fromCharCode(0x2039) + \", \" + String.fromCharCode(0x203a) + \" pentru a selecta luna\\n\" +\n\"- Tineţi butonul mouse-ului apăsat pentru selecţie mai rapidă.\";\nCalendar._TT[\"ABOUT_TIME\"] = \"\\n\\n\" +\n\"Selecţia orei:\\n\" +\n\"- Click pe ora sau minut pentru a mări valoarea cu 1\\n\" +\n\"- Sau Shift-Click pentru a micşora valoarea cu 1\\n\" +\n\"- Sau Click şi drag pentru a selecta mai repede.\";\n\nCalendar._TT[\"PREV_YEAR\"] = \"Anul precedent (lung pt menu)\";\nCalendar._TT[\"PREV_MONTH\"] = \"Luna precedentă (lung pt menu)\";\nCalendar._TT[\"GO_TODAY\"] = \"Data de azi\";\nCalendar._TT[\"NEXT_MONTH\"] = \"Luna următoare (lung pt menu)\";\nCalendar._TT[\"NEXT_YEAR\"] = \"Anul următor (lung pt menu)\";\nCalendar._TT[\"SEL_DATE\"] = \"Selectează data\";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \"Trage pentru a mişca\";\nCalendar._TT[\"PART_TODAY\"] = \" (astăzi)\";\nCalendar._TT[\"DAY_FIRST\"] = \"Afişează %s prima zi\";\nCalendar._TT[\"WEEKEND\"] = \"0,6\";\nCalendar._TT[\"CLOSE\"] = \"Închide\";\nCalendar._TT[\"TODAY\"] = \"Astăzi\";\nCalendar._TT[\"TIME_PART\"] = \"(Shift-)Click sau drag pentru a selecta\";\n\n// date formats\nCalendar._TT[\"DEF_DATE_FORMAT\"] = \"%d-%m-%Y\";\nCalendar._TT[\"TT_DATE_FORMAT\"] = \"%A, %d %B\";\n\nCalendar._TT[\"WK\"] = \"spt\";\nCalendar._TT[\"TIME\"] = \"Ora:\";\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/calendar-ru.js",
    "content": "// ** I18N\n\n// Calendar RU language\n// Translation: Sly Golovanov, http://golovanov.net, <sly@golovanov.net>\n// Encoding: any\n// Distributed under the same terms as the calendar itself.\n\n// For translators: please use UTF-8 if possible.  We strongly believe that\n// Unicode is the answer to a real internationalized world.  Also please\n// include your contact information in the header, as can be seen above.\n\n// full day names\nCalendar._DN = new Array\n(\"воскресенье\",\n \"понедельник\",\n \"вторник\",\n \"среда\",\n \"четверг\",\n \"пятница\",\n \"суббота\",\n \"воскресенье\");\n\n// Please note that the following array of short day names (and the same goes\n// for short month names, _SMN) isn't absolutely necessary.  We give it here\n// for exemplification on how one can customize the short day names, but if\n// they are simply the first N letters of the full name you can simply say:\n//\n//   Calendar._SDN_len = N; // short day name length\n//   Calendar._SMN_len = N; // short month name length\n//\n// If N = 3 then this is not needed either since we assume a value of 3 if not\n// present, to be compatible with translation files that were written before\n// this feature.\n\n// short day names\nCalendar._SDN = new Array\n(\"вск\",\n \"пон\",\n \"втр\",\n \"срд\",\n \"чет\",\n \"пят\",\n \"суб\",\n \"вск\");\n\n// full month names\nCalendar._MN = new Array\n(\"январь\",\n \"февраль\",\n \"март\",\n \"апрель\",\n \"май\",\n \"июнь\",\n \"июль\",\n \"август\",\n \"сентябрь\",\n \"октябрь\",\n \"ноябрь\",\n \"декабрь\");\n\n// short month names\nCalendar._SMN = new Array\n(\"янв\",\n \"фев\",\n \"мар\",\n \"апр\",\n \"май\",\n \"июн\",\n \"июл\",\n \"авг\",\n \"сен\",\n \"окт\",\n \"ноя\",\n \"дек\");\n\n// tooltips\nCalendar._TT = {};\nCalendar._TT[\"INFO\"] = \"О календаре...\";\n\nCalendar._TT[\"ABOUT\"] =\n\"DHTML Date/Time Selector\\n\" +\n\"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\\n\" + // don't translate this this ;-)\n\"For latest version visit: http://www.dynarch.com/projects/calendar/\\n\" +\n\"Distributed under GNU LGPL.  See http://gnu.org/licenses/lgpl.html for details.\" +\n\"\\n\\n\" +\n\"Как выбрать дату:\\n\" +\n\"- При помощи кнопок \\xab, \\xbb можно выбрать год\\n\" +\n\"- При помощи кнопок \" + String.fromCharCode(0x2039) + \", \" + String.fromCharCode(0x203a) + \" можно выбрать месяц\\n\" +\n\"- Подержите эти кнопки нажатыми, чтобы появилось меню быстрого выбора.\";\nCalendar._TT[\"ABOUT_TIME\"] = \"\\n\\n\" +\n\"Как выбрать время:\\n\" +\n\"- При клике на часах или минутах они увеличиваются\\n\" +\n\"- при клике с нажатой клавишей Shift они уменьшаются\\n\" +\n\"- если нажать и двигать мышкой влево/вправо, они будут меняться быстрее.\";\n\nCalendar._TT[\"PREV_YEAR\"] = \"На год назад (удерживать для меню)\";\nCalendar._TT[\"PREV_MONTH\"] = \"На месяц назад (удерживать для меню)\";\nCalendar._TT[\"GO_TODAY\"] = \"Сегодня\";\nCalendar._TT[\"NEXT_MONTH\"] = \"На месяц вперед (удерживать для меню)\";\nCalendar._TT[\"NEXT_YEAR\"] = \"На год вперед (удерживать для меню)\";\nCalendar._TT[\"SEL_DATE\"] = \"Выберите дату\";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \"Перетаскивайте мышкой\";\nCalendar._TT[\"PART_TODAY\"] = \" (сегодня)\";\n\n// the following is to inform that \"%s\" is to be the first day of week\n// %s will be replaced with the day name.\nCalendar._TT[\"DAY_FIRST\"] = \"Первый день недели будет %s\";\n\n// This may be locale-dependent.  It specifies the week-end days, as an array\n// of comma-separated numbers.  The numbers are from 0 to 6: 0 means Sunday, 1\n// means Monday, etc.\nCalendar._TT[\"WEEKEND\"] = \"0,6\";\n\nCalendar._TT[\"CLOSE\"] = \"Закрыть\";\nCalendar._TT[\"TODAY\"] = \"Сегодня\";\nCalendar._TT[\"TIME_PART\"] = \"(Shift-)клик или нажать и двигать\";\n\n// date formats\nCalendar._TT[\"DEF_DATE_FORMAT\"] = \"%Y-%m-%d\";\nCalendar._TT[\"TT_DATE_FORMAT\"] = \"%e %b, %a\";\n\nCalendar._TT[\"WK\"] = \"нед\";\nCalendar._TT[\"TIME\"] = \"Время:\";\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/calendar-ru_win_.js",
    "content": "// ** I18N\n\n// Calendar RU language\n// Translation: Sly Golovanov, http://golovanov.net, <sly@golovanov.net>\n// Encoding: any\n// Distributed under the same terms as the calendar itself.\n\n// For translators: please use UTF-8 if possible.  We strongly believe that\n// Unicode is the answer to a real internationalized world.  Also please\n// include your contact information in the header, as can be seen above.\n\n// full day names\nCalendar._DN = new Array\n(\"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\");\n\n// Please note that the following array of short day names (and the same goes\n// for short month names, _SMN) isn't absolutely necessary.  We give it here\n// for exemplification on how one can customize the short day names, but if\n// they are simply the first N letters of the full name you can simply say:\n//\n//   Calendar._SDN_len = N; // short day name length\n//   Calendar._SMN_len = N; // short month name length\n//\n// If N = 3 then this is not needed either since we assume a value of 3 if not\n// present, to be compatible with translation files that were written before\n// this feature.\n\n// short day names\nCalendar._SDN = new Array\n(\"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\");\n\n// full month names\nCalendar._MN = new Array\n(\"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\");\n\n// short month names\nCalendar._SMN = new Array\n(\"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\");\n\n// tooltips\nCalendar._TT = {};\nCalendar._TT[\"INFO\"] = \" ...\";\n\nCalendar._TT[\"ABOUT\"] =\n\"DHTML Date/Time Selector\\n\" +\n\"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\\n\" + // don't translate this this ;-)\n\"For latest version visit: http://www.dynarch.com/projects/calendar/\\n\" +\n\"Distributed under GNU LGPL.  See http://gnu.org/licenses/lgpl.html for details.\" +\n\"\\n\\n\" +\n\"  :\\n\" +\n\"-    \\xab, \\xbb   \\n\" +\n\"-    \" + String.fromCharCode(0x2039) + \", \" + String.fromCharCode(0x203a) + \"   \\n\" +\n\"-    ,     .\";\nCalendar._TT[\"ABOUT_TIME\"] = \"\\n\\n\" +\n\"  :\\n\" +\n\"-        \\n\" +\n\"-      Shift  \\n\" +\n\"-      /,    .\";\n\nCalendar._TT[\"PREV_YEAR\"] = \"   (  )\";\nCalendar._TT[\"PREV_MONTH\"] = \"   (  )\";\nCalendar._TT[\"GO_TODAY\"] = \"\";\nCalendar._TT[\"NEXT_MONTH\"] = \"   (  )\";\nCalendar._TT[\"NEXT_YEAR\"] = \"   (  )\";\nCalendar._TT[\"SEL_DATE\"] = \" \";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \" \";\nCalendar._TT[\"PART_TODAY\"] = \" ()\";\n\n// the following is to inform that \"%s\" is to be the first day of week\n// %s will be replaced with the day name.\nCalendar._TT[\"DAY_FIRST\"] = \"    %s\";\n\n// This may be locale-dependent.  It specifies the week-end days, as an array\n// of comma-separated numbers.  The numbers are from 0 to 6: 0 means Sunday, 1\n// means Monday, etc.\nCalendar._TT[\"WEEKEND\"] = \"0,6\";\n\nCalendar._TT[\"CLOSE\"] = \"\";\nCalendar._TT[\"TODAY\"] = \"\";\nCalendar._TT[\"TIME_PART\"] = \"(Shift-)    \";\n\n// date formats\nCalendar._TT[\"DEF_DATE_FORMAT\"] = \"%Y-%m-%d\";\nCalendar._TT[\"TT_DATE_FORMAT\"] = \"%e %b, %a\";\n\nCalendar._TT[\"WK\"] = \"\";\nCalendar._TT[\"TIME\"] = \":\";\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/calendar-si.js",
    "content": "/* Slovenian language file for the DHTML Calendar version 0.9.2 \n* Author David Milost <mercy@volja.net>, January 2004.\n* Feel free to use this script under the terms of the GNU Lesser General\n* Public License, as long as you do not remove or alter this notice.\n*/\n // full day names\nCalendar._DN = new Array\n(\"Nedelja\",\n \"Ponedeljek\",\n \"Torek\",\n \"Sreda\",\n \"Četrtek\",\n \"Petek\",\n \"Sobota\",\n \"Nedelja\");\n // short day names\n Calendar._SDN = new Array\n(\"Ned\",\n \"Pon\",\n \"Tor\",\n \"Sre\",\n \"Čet\",\n \"Pet\",\n \"Sob\",\n \"Ned\");\n// short month names\nCalendar._SMN = new Array\n(\"Jan\",\n \"Feb\",\n \"Mar\",\n \"Apr\",\n \"Maj\",\n \"Jun\",\n \"Jul\",\n \"Avg\",\n \"Sep\",\n \"Okt\",\n \"Nov\",\n \"Dec\");\n  // full month names\nCalendar._MN = new Array\n(\"Januar\",\n \"Februar\",\n \"Marec\",\n \"April\",\n \"Maj\",\n \"Junij\",\n \"Julij\",\n \"Avgust\",\n \"September\",\n \"Oktober\",\n \"November\",\n \"December\");\n\n// tooltips\n// tooltips\nCalendar._TT = {};\nCalendar._TT[\"INFO\"] = \"O koledarju\";\n\nCalendar._TT[\"ABOUT\"] =\n\"DHTML Date/Time Selector\\n\" +\n\"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\\n\" + // don't translate this this ;-)\n\"Za zadnjo verzijo pojdine na naslov: http://www.dynarch.com/projects/calendar/\\n\" +\n\"Distribuirano pod GNU LGPL.  Poglejte http://gnu.org/licenses/lgpl.html za podrobnosti.\" +\n\"\\n\\n\" +\n\"Izbor datuma:\\n\" +\n\"- Uporabite \\xab, \\xbb gumbe za izbor leta\\n\" +\n\"- Uporabite \" + String.fromCharCode(0x2039) + \", \" + String.fromCharCode(0x203a) + \" gumbe za izbor meseca\\n\" +\n\"- Zadržite klik na kateremkoli od zgornjih gumbov za hiter izbor.\";\nCalendar._TT[\"ABOUT_TIME\"] = \"\\n\\n\" +\n\"Izbor ćasa:\\n\" +\n\"- Kliknite na katerikoli del ćasa za poveć. le-tega\\n\" +\n\"- ali Shift-click za zmanj. le-tega\\n\" +\n\"- ali kliknite in povlecite za hiter izbor.\";\n\nCalendar._TT[\"TOGGLE\"] = \"Spremeni dan s katerim se prićne teden\";\nCalendar._TT[\"PREV_YEAR\"] = \"Predhodnje leto (dolg klik za meni)\";\nCalendar._TT[\"PREV_MONTH\"] = \"Predhodnji mesec (dolg klik za meni)\";\nCalendar._TT[\"GO_TODAY\"] = \"Pojdi na tekoći dan\";\nCalendar._TT[\"NEXT_MONTH\"] = \"Naslednji mesec (dolg klik za meni)\";\nCalendar._TT[\"NEXT_YEAR\"] = \"Naslednje leto (dolg klik za meni)\";\nCalendar._TT[\"SEL_DATE\"] = \"Izberite datum\";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \"Pritisni in povleci za spremembo pozicije\";\nCalendar._TT[\"PART_TODAY\"] = \" (danes)\";\nCalendar._TT[\"MON_FIRST\"] = \"Prikaži ponedeljek kot prvi dan\";\nCalendar._TT[\"SUN_FIRST\"] = \"Prikaži nedeljo kot prvi dan\";\nCalendar._TT[\"CLOSE\"] = \"Zapri\";\nCalendar._TT[\"TODAY\"] = \"Danes\";\n\n// date formats\nCalendar._TT[\"DEF_DATE_FORMAT\"] = \"%Y-%m-%d\";\nCalendar._TT[\"TT_DATE_FORMAT\"] = \"%a, %b %e\";\n\nCalendar._TT[\"WK\"] = \"Ted\";"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/calendar-sk.js",
    "content": "// ** I18N\n\n// Calendar SK language\n// Author: Peter Valach (pvalach@gmx.net)\n// Encoding: utf-8\n// Last update: 2003/10/29\n// Distributed under the same terms as the calendar itself.\n\n// full day names\nCalendar._DN = new Array\n(\"NedeÄľa\",\n \"Pondelok\",\n \"Utorok\",\n \"Streda\",\n \"Ĺ tvrtok\",\n \"Piatok\",\n \"Sobota\",\n \"NedeÄľa\");\n\n// short day names\nCalendar._SDN = new Array\n(\"Ned\",\n \"Pon\",\n \"Uto\",\n \"Str\",\n \"Ĺ tv\",\n \"Pia\",\n \"Sob\",\n \"Ned\");\n\n// full month names\nCalendar._MN = new Array\n(\"JanuĂˇr\",\n \"FebruĂˇr\",\n \"Marec\",\n \"AprĂ­l\",\n \"MĂˇj\",\n \"JĂşn\",\n \"JĂşl\",\n \"August\",\n \"September\",\n \"OktĂłber\",\n \"November\",\n \"December\");\n\n// short month names\nCalendar._SMN = new Array\n(\"Jan\",\n \"Feb\",\n \"Mar\",\n \"Apr\",\n \"MĂˇj\",\n \"JĂşn\",\n \"JĂşl\",\n \"Aug\",\n \"Sep\",\n \"Okt\",\n \"Nov\",\n \"Dec\");\n\n// tooltips\nCalendar._TT = {};\nCalendar._TT[\"INFO\"] = \"O kalendĂˇri\";\n\nCalendar._TT[\"ABOUT\"] =\n\"DHTML Date/Time Selector\\n\" +\n\"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\\n\" +\n\"PoslednĂş verziu nĂˇjdete na: http://www.dynarch.com/projects/calendar/\\n\" +\n\"DistribuovanĂ© pod GNU LGPL.  ViÄŹ http://gnu.org/licenses/lgpl.html pre detaily.\" +\n\"\\n\\n\" +\n\"VĂ˝ber dĂˇtumu:\\n\" +\n\"- PouĹľite tlaÄŤidlĂˇ \\xab, \\xbb pre vĂ˝ber roku\\n\" +\n\"- PouĹľite tlaÄŤidlĂˇ \" + String.fromCharCode(0x2039) + \", \" + String.fromCharCode(0x203a) + \" pre vĂ˝ber mesiaca\\n\" +\n\"- Ak ktorĂ©koÄľvek z tĂ˝chto tlaÄŤidiel podrĹľĂ­te dlhĹˇie, zobrazĂ­ sa rĂ˝chly vĂ˝ber.\";\nCalendar._TT[\"ABOUT_TIME\"] = \"\\n\\n\" +\n\"VĂ˝ber ÄŤasu:\\n\" +\n\"- Kliknutie na niektorĂş poloĹľku ÄŤasu ju zvĂ˝Ĺˇi\\n\" +\n\"- Shift-klik ju znĂ­Ĺľi\\n\" +\n\"- Ak podrĹľĂ­te tlaÄŤĂ­tko stlaÄŤenĂ©, posĂşvanĂ­m menĂ­te hodnotu.\";\n\nCalendar._TT[\"PREV_YEAR\"] = \"PredoĹˇlĂ˝ rok (podrĹľte pre menu)\";\nCalendar._TT[\"PREV_MONTH\"] = \"PredoĹˇlĂ˝ mesiac (podrĹľte pre menu)\";\nCalendar._TT[\"GO_TODAY\"] = \"PrejsĹĄ na dneĹˇok\";\nCalendar._TT[\"NEXT_MONTH\"] = \"Nasl. mesiac (podrĹľte pre menu)\";\nCalendar._TT[\"NEXT_YEAR\"] = \"Nasl. rok (podrĹľte pre menu)\";\nCalendar._TT[\"SEL_DATE\"] = \"ZvoÄľte dĂˇtum\";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \"PodrĹľanĂ­m tlaÄŤĂ­tka zmenĂ­te polohu\";\nCalendar._TT[\"PART_TODAY\"] = \" (dnes)\";\nCalendar._TT[\"MON_FIRST\"] = \"ZobraziĹĄ pondelok ako prvĂ˝\";\nCalendar._TT[\"SUN_FIRST\"] = \"ZobraziĹĄ nedeÄľu ako prvĂş\";\nCalendar._TT[\"CLOSE\"] = \"ZavrieĹĄ\";\nCalendar._TT[\"TODAY\"] = \"Dnes\";\nCalendar._TT[\"TIME_PART\"] = \"(Shift-)klik/ĹĄahanie zmenĂ­ hodnotu\";\n\n// date formats\nCalendar._TT[\"DEF_DATE_FORMAT\"] = \"$d. %m. %Y\";\nCalendar._TT[\"TT_DATE_FORMAT\"] = \"%a, %e. %b\";\n\nCalendar._TT[\"WK\"] = \"tĂ˝Ĺľ\";\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/calendar-sp.js",
    "content": "// ** I18N\n\n// Calendar SP language\n// Author: Rafael Velasco <rvu_at_idecnet_dot_com>\n// Encoding: any\n// Distributed under the same terms as the calendar itself.\n\n// For translators: please use UTF-8 if possible.  We strongly believe that\n// Unicode is the answer to a real internationalized world.  Also please\n// include your contact information in the header, as can be seen above.\n\n// full day names\nCalendar._DN = new Array\n(\"Domingo\",\n \"Lunes\",\n \"Martes\",\n \"Miercoles\",\n \"Jueves\",\n \"Viernes\",\n \"Sabado\",\n \"Domingo\");\n\nCalendar._SDN = new Array\n(\"Dom\",\n \"Lun\",\n \"Mar\",\n \"Mie\",\n \"Jue\",\n \"Vie\",\n \"Sab\",\n \"Dom\");\n\n// full month names\nCalendar._MN = new Array\n(\"Enero\",\n \"Febrero\",\n \"Marzo\",\n \"Abril\",\n \"Mayo\",\n \"Junio\",\n \"Julio\",\n \"Agosto\",\n \"Septiembre\",\n \"Octubre\",\n \"Noviembre\",\n \"Diciembre\");\n\n// short month names\nCalendar._SMN = new Array\n(\"Ene\",\n \"Feb\",\n \"Mar\",\n \"Abr\",\n \"May\",\n \"Jun\",\n \"Jul\",\n \"Ago\",\n \"Sep\",\n \"Oct\",\n \"Nov\",\n \"Dic\");\n\n// tooltips\nCalendar._TT = {};\nCalendar._TT[\"INFO\"] = \"Informacin del Calendario\";\n\nCalendar._TT[\"ABOUT\"] =\n\"DHTML Date/Time Selector\\n\" +\n\"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\\n\" + // don't translate this this ;-)\n\"Nuevas versiones en: http://www.dynarch.com/projects/calendar/\\n\" +\n\"Distribuida bajo licencia GNU LGPL.  Para detalles vea http://gnu.org/licenses/lgpl.html .\" +\n\"\\n\\n\" +\n\"Seleccin de Fechas:\\n\" +\n\"- Use  \\xab, \\xbb para seleccionar el ao\\n\" +\n\"- Use \" + String.fromCharCode(0x2039) + \", \" + String.fromCharCode(0x203a) + \" para seleccionar el mes\\n\" +\n\"- Mantenga presionado el botn del ratn en cualquiera de las opciones superiores para un acceso rapido .\";\nCalendar._TT[\"ABOUT_TIME\"] = \"\\n\\n\" +\n\"Seleccin del Reloj:\\n\" +\n\"- Seleccione la hora para cambiar el reloj\\n\" +\n\"- o presione  Shift-click para disminuirlo\\n\" +\n\"- o presione click y arrastre del ratn para una seleccin rapida.\";\n\nCalendar._TT[\"PREV_YEAR\"] = \"Ao anterior (Presione para menu)\";\nCalendar._TT[\"PREV_MONTH\"] = \"Mes Anterior (Presione para menu)\";\nCalendar._TT[\"GO_TODAY\"] = \"Ir a Hoy\";\nCalendar._TT[\"NEXT_MONTH\"] = \"Mes Siguiente (Presione para menu)\";\nCalendar._TT[\"NEXT_YEAR\"] = \"Ao Siguiente (Presione para menu)\";\nCalendar._TT[\"SEL_DATE\"] = \"Seleccione fecha\";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \"Arrastre y mueva\";\nCalendar._TT[\"PART_TODAY\"] = \" (Hoy)\";\n\n// the following is to inform that \"%s\" is to be the first day of week\n// %s will be replaced with the day name.\nCalendar._TT[\"DAY_FIRST\"] = \"Mostrar %s primero\";\n\n// This may be locale-dependent.  It specifies the week-end days, as an array\n// of comma-separated numbers.  The numbers are from 0 to 6: 0 means Sunday, 1\n// means Monday, etc.\nCalendar._TT[\"WEEKEND\"] = \"0,6\";\n\nCalendar._TT[\"CLOSE\"] = \"Cerrar\";\nCalendar._TT[\"TODAY\"] = \"Hoy\";\nCalendar._TT[\"TIME_PART\"] = \"(Shift-)Click o arrastra para cambar el valor\";\n\n// date formats\nCalendar._TT[\"DEF_DATE_FORMAT\"] = \"%dd-%mm-%yy\";\nCalendar._TT[\"TT_DATE_FORMAT\"] = \"%A, %e de %B de %Y\";\n\nCalendar._TT[\"WK\"] = \"Sm\";\nCalendar._TT[\"TIME\"] = \"Hora:\";\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/calendar-sv.js",
    "content": "// ** I18N\n\n// Calendar SV language (Swedish, svenska)\n// Author: Mihai Bazon, <mihai_bazon@yahoo.com>\n// Translation team: <sv@li.org>\n// Translator: Leonard Norrgrd <leonard.norrgard@refactor.fi>\n// Last translator: Leonard Norrgrd <leonard.norrgard@refactor.fi>\n// Encoding: iso-latin-1\n// Distributed under the same terms as the calendar itself.\n\n// For translators: please use UTF-8 if possible.  We strongly believe that\n// Unicode is the answer to a real internationalized world.  Also please\n// include your contact information in the header, as can be seen above.\n\n// full day names\nCalendar._DN = new Array\n(\"sndag\",\n \"mndag\",\n \"tisdag\",\n \"onsdag\",\n \"torsdag\",\n \"fredag\",\n \"lrdag\",\n \"sndag\");\n\n// Please note that the following array of short day names (and the same goes\n// for short month names, _SMN) isn't absolutely necessary.  We give it here\n// for exemplification on how one can customize the short day names, but if\n// they are simply the first N letters of the full name you can simply say:\n//\n//   Calendar._SDN_len = N; // short day name length\n//   Calendar._SMN_len = N; // short month name length\n//\n// If N = 3 then this is not needed either since we assume a value of 3 if not\n// present, to be compatible with translation files that were written before\n// this feature.\nCalendar._SDN_len = 2;\nCalendar._SMN_len = 3;\n\n// full month names\nCalendar._MN = new Array\n(\"januari\",\n \"februari\",\n \"mars\",\n \"april\",\n \"maj\",\n \"juni\",\n \"juli\",\n \"augusti\",\n \"september\",\n \"oktober\",\n \"november\",\n \"december\");\n\n// tooltips\nCalendar._TT = {};\nCalendar._TT[\"INFO\"] = \"Om kalendern\";\n\nCalendar._TT[\"ABOUT\"] =\n\"DHTML Datum/tid-vljare\\n\" +\n\"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\\n\" + // don't translate this this ;-)\n\"Fr senaste version g till: http://www.dynarch.com/projects/calendar/\\n\" +\n\"Distribueras under GNU LGPL.  Se http://gnu.org/licenses/lgpl.html fr detaljer.\" +\n\"\\n\\n\" +\n\"Val av datum:\\n\" +\n\"- Anvnd knapparna \\xab, \\xbb fr att vlja r\\n\" +\n\"- Anvnd knapparna \" + String.fromCharCode(0x2039) + \", \" + String.fromCharCode(0x203a) + \" fr att vlja mnad\\n\" +\n\"- Hll musknappen nedtryckt p ngon av ovanstende knappar fr snabbare val.\";\nCalendar._TT[\"ABOUT_TIME\"] = \"\\n\\n\" +\n\"Val av tid:\\n\" +\n\"- Klicka p en del av tiden fr att ka den delen\\n\" +\n\"- eller skift-klicka fr att minska den\\n\" +\n\"- eller klicka och drag fr snabbare val.\";\n\nCalendar._TT[\"PREV_YEAR\"] = \"Fregende r (hll fr menu)\";\nCalendar._TT[\"PREV_MONTH\"] = \"Fregende mnad (hll fr menu)\";\nCalendar._TT[\"GO_TODAY\"] = \"G till dagens datum\";\nCalendar._TT[\"NEXT_MONTH\"] = \"Fljande mnad (hll fr menu)\";\nCalendar._TT[\"NEXT_YEAR\"] = \"Fljande r (hll fr menu)\";\nCalendar._TT[\"SEL_DATE\"] = \"Vlj datum\";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \"Drag fr att flytta\";\nCalendar._TT[\"PART_TODAY\"] = \" (idag)\";\nCalendar._TT[\"MON_FIRST\"] = \"Visa mndag frst\";\nCalendar._TT[\"SUN_FIRST\"] = \"Visa sndag frst\";\nCalendar._TT[\"CLOSE\"] = \"Stng\";\nCalendar._TT[\"TODAY\"] = \"Idag\";\nCalendar._TT[\"TIME_PART\"] = \"(Skift-)klicka eller drag fr att ndra tid\";\n\n// date formats\nCalendar._TT[\"DEF_DATE_FORMAT\"] = \"%Y-%m-%d\";\nCalendar._TT[\"TT_DATE_FORMAT\"] = \"%A %d %b %Y\";\n\nCalendar._TT[\"WK\"] = \"vecka\";\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/calendar-tr.js",
    "content": "//////////////////////////////////////////////////////////////////////////////////////////////\n//\tTurkish Translation by Nuri AKMAN\n//\tLocation: Ankara/TURKEY\n//\te-mail\t: nuriakman@hotmail.com\n//\tDate\t: April, 9 2003\n//\n//\tNote: if Turkish Characters does not shown on you screen\n//\t\t  please include falowing line your html code:\n//\n//\t\t  <meta http-equiv=\"Content-Type\" content=\"text/html; charset=windows-1254\">\n//\n//////////////////////////////////////////////////////////////////////////////////////////////\n\n// ** I18N\nCalendar._DN = new Array\n(\"Pazar\",\n \"Pazartesi\",\n \"Sal\",\n \"aramba\",\n \"Perembe\",\n \"Cuma\",\n \"Cumartesi\",\n \"Pazar\");\nCalendar._MN = new Array\n(\"Ocak\",\n \"ubat\",\n \"Mart\",\n \"Nisan\",\n \"Mays\",\n \"Haziran\",\n \"Temmuz\",\n \"Austos\",\n \"Eyll\",\n \"Ekim\",\n \"Kasm\",\n \"Aralk\");\n\n// tooltips\nCalendar._TT = {};\nCalendar._TT[\"TOGGLE\"] = \"Haftann ilk gnn kaydr\";\nCalendar._TT[\"PREV_YEAR\"] = \"nceki Yl (Men iin basl tutunuz)\";\nCalendar._TT[\"PREV_MONTH\"] = \"nceki Ay (Men iin basl tutunuz)\";\nCalendar._TT[\"GO_TODAY\"] = \"Bugn'e git\";\nCalendar._TT[\"NEXT_MONTH\"] = \"Sonraki Ay (Men iin basl tutunuz)\";\nCalendar._TT[\"NEXT_YEAR\"] = \"Sonraki Yl (Men iin basl tutunuz)\";\nCalendar._TT[\"SEL_DATE\"] = \"Tarih seiniz\";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \"Tamak iin srkleyiniz\";\nCalendar._TT[\"PART_TODAY\"] = \" (bugn)\";\nCalendar._TT[\"MON_FIRST\"] = \"Takvim Pazartesi gnnden balasn\";\nCalendar._TT[\"SUN_FIRST\"] = \"Takvim Pazar gnnden balasn\";\nCalendar._TT[\"CLOSE\"] = \"Kapat\";\nCalendar._TT[\"TODAY\"] = \"Bugn\";\n\n// date formats\nCalendar._TT[\"DEF_DATE_FORMAT\"] = \"dd-mm-y\";\nCalendar._TT[\"TT_DATE_FORMAT\"] = \"d MM y, DD\";\n\nCalendar._TT[\"WK\"] = \"Hafta\";\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/calendar-zh.js",
    "content": "// ** I18N\n\n// Calendar ZH language\n// Author: muziq, <muziq@sina.com>\n// Encoding: GB2312 or GBK\n// Distributed under the same terms as the calendar itself.\n\n// full day names\nCalendar._DN = new Array\n(\"\",\n \"һ\",\n \"ڶ\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\");\n\n// Please note that the following array of short day names (and the same goes\n// for short month names, _SMN) isn't absolutely necessary.  We give it here\n// for exemplification on how one can customize the short day names, but if\n// they are simply the first N letters of the full name you can simply say:\n//\n//   Calendar._SDN_len = N; // short day name length\n//   Calendar._SMN_len = N; // short month name length\n//\n// If N = 3 then this is not needed either since we assume a value of 3 if not\n// present, to be compatible with translation files that were written before\n// this feature.\n\n// short day names\nCalendar._SDN = new Array\n(\"\",\n \"һ\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\");\n\n// full month names\nCalendar._MN = new Array\n(\"һ\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"ʮ\",\n \"ʮһ\",\n \"ʮ\");\n\n// short month names\nCalendar._SMN = new Array\n(\"һ\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"ʮ\",\n \"ʮһ\",\n \"ʮ\");\n\n// tooltips\nCalendar._TT = {};\nCalendar._TT[\"INFO\"] = \"\";\n\nCalendar._TT[\"ABOUT\"] =\n\"DHTML Date/Time Selector\\n\" +\n\"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\\n\" + // don't translate this this ;-)\n\"For latest version visit: http://www.dynarch.com/projects/calendar/\\n\" +\n\"Distributed under GNU LGPL.  See http://gnu.org/licenses/lgpl.html for details.\" +\n\"\\n\\n\" +\n\"ѡ:\\n\" +\n\"-  \\xab, \\xbb ťѡ\\n\" +\n\"-  \" + String.fromCharCode(0x2039) + \", \" + String.fromCharCode(0x203a) + \" ťѡ·\\n\" +\n\"- ϰťɴӲ˵пѡݻ·\";\nCalendar._TT[\"ABOUT_TIME\"] = \"\\n\\n\" +\n\"ѡʱ:\\n\" +\n\"- Сʱӿʹֵһ\\n\" +\n\"- סShiftСʱӿʹֵһ\\n\" +\n\"- ϶ɽпѡ\";\n\nCalendar._TT[\"PREV_YEAR\"] = \"һ (ס˵)\";\nCalendar._TT[\"PREV_MONTH\"] = \"һ (ס˵)\";\nCalendar._TT[\"GO_TODAY\"] = \"ת\";\nCalendar._TT[\"NEXT_MONTH\"] = \"һ (ס˵)\";\nCalendar._TT[\"NEXT_YEAR\"] = \"һ (ס˵)\";\nCalendar._TT[\"SEL_DATE\"] = \"ѡ\";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \"϶\";\nCalendar._TT[\"PART_TODAY\"] = \" ()\";\n\n// the following is to inform that \"%s\" is to be the first day of week\n// %s will be replaced with the day name.\nCalendar._TT[\"DAY_FIRST\"] = \"ʾ%s\";\n\n// This may be locale-dependent.  It specifies the week-end days, as an array\n// of comma-separated numbers.  The numbers are from 0 to 6: 0 means Sunday, 1\n// means Monday, etc.\nCalendar._TT[\"WEEKEND\"] = \"0,6\";\n\nCalendar._TT[\"CLOSE\"] = \"ر\";\nCalendar._TT[\"TODAY\"] = \"\";\nCalendar._TT[\"TIME_PART\"] = \"(Shift-)϶ıֵ\";\n\n// date formats\nCalendar._TT[\"DEF_DATE_FORMAT\"] = \"%Y-%m-%d\";\nCalendar._TT[\"TT_DATE_FORMAT\"] = \"%A, %b %e\";\n\nCalendar._TT[\"WK\"] = \"\";\nCalendar._TT[\"TIME\"] = \"ʱ:\";\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/lang/cn_utf8.js",
    "content": "// ** I18N\n\n// Calendar EN language\n// Author: Mihai Bazon, <mishoo@infoiasi.ro>\n// Encoding: any\n// Translator : Niko <nikoused@gmail.com>\n// Distributed under the same terms as the calendar itself.\n\n// For translators: please use UTF-8 if possible.  We strongly believe that\n// Unicode is the answer to a real internationalized world.  Also please\n// include your contact information in the header, as can be seen above.\n\n// full day names\nCalendar._DN = new Array\n(\"\\u5468\\u65e5\",//\\u5468\\u65e5\n \"\\u5468\\u4e00\",//\\u5468\\u4e00\n \"\\u5468\\u4e8c\",//\\u5468\\u4e8c\n \"\\u5468\\u4e09\",//\\u5468\\u4e09\n \"\\u5468\\u56db\",//\\u5468\\u56db\n \"\\u5468\\u4e94\",//\\u5468\\u4e94\n \"\\u5468\\u516d\",//\\u5468\\u516d\n \"\\u5468\\u65e5\");//\\u5468\\u65e5\n\n// Please note that the following array of short day names (and the same goes\n// for short month names, _SMN) isn't absolutely necessary.  We give it here\n// for exemplification on how one can customize the short day names, but if\n// they are simply the first N letters of the full name you can simply say:\n//\n//   Calendar._SDN_len = N; // short day name length\n//   Calendar._SMN_len = N; // short month name length\n//\n// If N = 3 then this is not needed either since we assume a value of 3 if not\n// present, to be compatible with translation files that were written before\n// this feature.\n\n// short day names\nCalendar._SDN = new Array\n(\"\\u5468\\u65e5\",\n \"\\u5468\\u4e00\",\n \"\\u5468\\u4e8c\",\n \"\\u5468\\u4e09\",\n \"\\u5468\\u56db\",\n \"\\u5468\\u4e94\",\n \"\\u5468\\u516d\",\n \"\\u5468\\u65e5\");\n\n// full month names\nCalendar._MN = new Array\n(\"\\u4e00\\u6708\",\n \"\\u4e8c\\u6708\",\n \"\\u4e09\\u6708\",\n \"\\u56db\\u6708\",\n \"\\u4e94\\u6708\",\n \"\\u516d\\u6708\",\n \"\\u4e03\\u6708\",\n \"\\u516b\\u6708\",\n \"\\u4e5d\\u6708\",\n \"\\u5341\\u6708\",\n \"\\u5341\\u4e00\\u6708\",\n \"\\u5341\\u4e8c\\u6708\");\n\n// short month names\nCalendar._SMN = new Array\n(\"\\u4e00\\u6708\",\n \"\\u4e8c\\u6708\",\n \"\\u4e09\\u6708\",\n \"\\u56db\\u6708\",\n \"\\u4e94\\u6708\",\n \"\\u516d\\u6708\",\n \"\\u4e03\\u6708\",\n \"\\u516b\\u6708\",\n \"\\u4e5d\\u6708\",\n \"\\u5341\\u6708\",\n \"\\u5341\\u4e00\\u6708\",\n \"\\u5341\\u4e8c\\u6708\");\n\n// tooltips\nCalendar._TT = {};\nCalendar._TT[\"INFO\"] = \"\\u5173\\u4e8e\";\n\nCalendar._TT[\"ABOUT\"] =\n\"   DHTML \\u65e5\\u8d77/\\u65f6\\u95f4\\u9009\\u62e9\\u63a7\\u4ef6\\n\" +\n\"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\\n\" + // don't translate this this ;-)\n\"For latest version visit: \\u6700\\u65b0\\u7248\\u672c\\u8bf7\\u767b\\u9646http://www.dynarch.com/projects/calendar/\\u5bdf\\u770b\\n\" +\n\"\\u9075\\u5faaGNU LGPL.  \\u7ec6\\u8282\\u53c2\\u9605 http://gnu.org/licenses/lgpl.html\" +\n\"\\n\\n\" +\n\"\\u65e5\\u671f\\u9009\\u62e9:\\n\" +\n\"- \\u70b9\\u51fb\\xab(\\xbb)\\u6309\\u94ae\\u9009\\u62e9\\u4e0a(\\u4e0b)\\u4e00\\u5e74\\u5ea6.\\n\" +\n\"- \\u70b9\\u51fb\" + String.fromCharCode(0x2039) + \"(\" + String.fromCharCode(0x203a) + \")\\u6309\\u94ae\\u9009\\u62e9\\u4e0a(\\u4e0b)\\u4e2a\\u6708\\u4efd.\\n\" +\n\"- \\u957f\\u65f6\\u95f4\\u6309\\u7740\\u6309\\u94ae\\u5c06\\u51fa\\u73b0\\u66f4\\u591a\\u9009\\u62e9\\u9879.\";\nCalendar._TT[\"ABOUT_TIME\"] = \"\\n\\n\" +\n\"\\u65f6\\u95f4\\u9009\\u62e9:\\n\" +\n\"-\\u5728\\u65f6\\u95f4\\u90e8\\u5206(\\u5206\\u6216\\u8005\\u79d2)\\u4e0a\\u5355\\u51fb\\u9f20\\u6807\\u5de6\\u952e\\u6765\\u589e\\u52a0\\u5f53\\u524d\\u65f6\\u95f4\\u90e8\\u5206(\\u5206\\u6216\\u8005\\u79d2)\\n\" +\n\"-\\u5728\\u65f6\\u95f4\\u90e8\\u5206(\\u5206\\u6216\\u8005\\u79d2)\\u4e0a\\u6309\\u4f4fShift\\u952e\\u540e\\u5355\\u51fb\\u9f20\\u6807\\u5de6\\u952e\\u6765\\u51cf\\u5c11\\u5f53\\u524d\\u65f6\\u95f4\\u90e8\\u5206(\\u5206\\u6216\\u8005\\u79d2).\";\n\nCalendar._TT[\"PREV_YEAR\"] = \"\\u4e0a\\u4e00\\u5e74\";\nCalendar._TT[\"PREV_MONTH\"] = \"\\u4e0a\\u4e2a\\u6708\";\nCalendar._TT[\"GO_TODAY\"] = \"\\u5230\\u4eca\\u5929\";\nCalendar._TT[\"NEXT_MONTH\"] = \"\\u4e0b\\u4e2a\\u6708\";\nCalendar._TT[\"NEXT_YEAR\"] = \"\\u4e0b\\u4e00\\u5e74\";\nCalendar._TT[\"SEL_DATE\"] = \"\\u9009\\u62e9\\u65e5\\u671f\";\nCalendar._TT[\"DRAG_TO_MOVE\"] = \"\\u62d6\\u52a8\";\nCalendar._TT[\"PART_TODAY\"] = \" (\\u4eca\\u5929)\";\n\n// the following is to inform that \"%s\" is to be the first day of week\n// %s will be replaced with the day name.\nCalendar._TT[\"DAY_FIRST\"] = \"%s\\u4e3a\\u8fd9\\u5468\\u7684\\u7b2c\\u4e00\\u5929\";\n\n// This may be locale-dependent.  It specifies the week-end days, as an array\n// of comma-separated numbers.  The numbers are from 0 to 6: 0 means Sunday, 1\n// means Monday, etc.\nCalendar._TT[\"WEEKEND\"] = \"0,6\";\n\nCalendar._TT[\"CLOSE\"] = \"\\u5173\\u95ed\";\nCalendar._TT[\"TODAY\"] = \"\\u4eca\\u5929\";\nCalendar._TT[\"TIME_PART\"] = \"(\\u6309\\u7740Shift\\u952e)\\u5355\\u51fb\\u6216\\u62d6\\u52a8\\u6539\\u53d8\\u503c\";\n\n// date formats\nCalendar._TT[\"DEF_DATE_FORMAT\"] = \"%Y-%m-%d\";\nCalendar._TT[\"TT_DATE_FORMAT\"] = \"%a, %b %e\\u65e5\";\n\nCalendar._TT[\"WK\"] = \"\\u5468\";\nCalendar._TT[\"TIME\"] = \"\\u65f6\\u95f4:\";\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/resources/widgets/jscalendar/skins/aqua/theme.css",
    "content": "/* Distributed as part of The Coolest DHTML Calendar\n   Author: Mihai Bazon, www.bazon.net/mishoo\n   Copyright Dynarch.com 2005, www.dynarch.com\n*/\n\n/* The main calendar widget.  DIV containing a table. */\n\ndiv.calendar { position: relative; }\n\n.calendar, .calendar table {\n  border: 1px solid #bdb2bf;\n  font-size: 11px;\n  color: #000;\n  cursor: default;\n  background: url(\"normal-bg.gif\");\n  font-family: \"trebuchet ms\",verdana,tahoma,sans-serif;\n}\n\n.calendar {\n  border-color: #797979;\n}\n\n/* Header part -- contains navigation buttons and day names. */\n\n.calendar .button { /* \"<<\", \"<\", \">\", \">>\" buttons have this class */\n  text-align: center;    /* They are the navigation buttons */\n  padding: 2px;          /* Make the buttons seem like they're pressing */\n  background: url(\"title-bg.gif\") repeat-x 0 100%; color: #000;\n  font-weight: bold;\n}\n\n.calendar .nav {\n  font-family: verdana,tahoma,sans-serif;\n}\n\n.calendar .nav div {\n  background: transparent url(\"menuarrow.gif\") no-repeat 100% 100%;\n}\n\n.calendar thead tr { background: url(\"title-bg.gif\") repeat-x 0 100%; color: #000; }\n\n.calendar thead .title { /* This holds the current \"month, year\" */\n  font-weight: bold;      /* Pressing it will take you to the current date */\n  text-align: center;\n  padding: 2px;\n  background: url(\"title-bg.gif\") repeat-x 0 100%; color: #000;\n}\n\n.calendar thead .headrow { /* Row <TR> containing navigation buttons */\n}\n\n.calendar thead .name { /* Cells <TD> containing the day names */\n  border-bottom: 1px solid #797979;\n  padding: 2px;\n  text-align: center;\n  color: #000;\n}\n\n.calendar thead .weekend { /* How a weekend day name shows in header */\n  color: #c44;\n}\n\n.calendar thead .hilite { /* How do the buttons in header appear when hover */\n  background: url(\"hover-bg.gif\");\n  border-bottom: 1px solid #797979;\n  padding: 2px 2px 1px 2px;\n}\n\n.calendar thead .active { /* Active (pressed) buttons in header */\n  background: url(\"active-bg.gif\"); color: #fff;\n  padding: 3px 1px 0px 3px;\n  border-bottom: 1px solid #797979;\n}\n\n.calendar thead .daynames { /* Row <TR> containing the day names */\n  background: url(\"dark-bg.gif\");\n}\n\n/* The body part -- contains all the days in month. */\n\n.calendar tbody .day { /* Cells <TD> containing month days dates */\n  font-family: verdana,tahoma,sans-serif;\n  width: 2em;\n  color: #000;\n  text-align: right;\n  padding: 2px 4px 2px 2px;\n}\n.calendar tbody .day.othermonth {\n  font-size: 80%;\n  color: #999;\n}\n.calendar tbody .day.othermonth.oweekend {\n  color: #f99;\n}\n\n.calendar table .wn {\n  padding: 2px 3px 2px 2px;\n  border-right: 1px solid #797979;\n  background: url(\"dark-bg.gif\");\n}\n\n.calendar tbody .rowhilite td,\n.calendar tbody .rowhilite td.wn {\n  background: url(\"rowhover-bg.gif\");\n}\n\n.calendar tbody td.today { font-weight: bold; /* background: url(\"today-bg.gif\") no-repeat 70% 50%; */ }\n\n.calendar tbody td.hilite { /* Hovered cells <TD> */\n  background: url(\"hover-bg.gif\");\n  padding: 1px 3px 1px 1px;\n  border: 1px solid #bbb;\n}\n\n.calendar tbody td.active { /* Active (pressed) cells <TD> */\n  padding: 2px 2px 0px 2px;\n}\n\n.calendar tbody td.weekend { /* Cells showing weekend days */\n  color: #c44;\n}\n\n.calendar tbody td.selected { /* Cell showing selected date */\n  font-weight: bold;\n  border: 1px solid #797979;\n  padding: 1px 3px 1px 1px;\n  background: url(\"active-bg.gif\"); color: #fff;\n}\n\n.calendar tbody .disabled { color: #999; }\n\n.calendar tbody .emptycell { /* Empty cells (the best is to hide them) */\n  visibility: hidden;\n}\n\n.calendar tbody .emptyrow { /* Empty row (some months need less than 6 rows) */\n  display: none;\n}\n\n/* The footer part -- status bar and \"Close\" button */\n\n.calendar tfoot .footrow { /* The <TR> in footer (only one right now) */\n  text-align: center;\n  background: #565;\n  color: #fff;\n}\n\n.calendar tfoot .ttip { /* Tooltip (status bar) cell <TD> */\n  padding: 2px;\n  background: url(\"status-bg.gif\") repeat-x 0 0; color: #000;\n}\n\n.calendar tfoot .hilite { /* Hover style for buttons in footer */\n  background: #afa;\n  border: 1px solid #084;\n  color: #000;\n  padding: 1px;\n}\n\n.calendar tfoot .active { /* Active (pressed) style for buttons in footer */\n  background: #7c7;\n  padding: 2px 0px 0px 2px;\n}\n\n/* Combo boxes (menus that display months/years for direct selection) */\n\n.calendar .combo {\n  position: absolute;\n  display: none;\n  top: 0px;\n  left: 0px;\n  width: 4em;\n  cursor: default;\n  border-width: 0 1px 1px 1px;\n  border-style: solid;\n  border-color: #797979;\n  background: url(\"normal-bg.gif\"); color: #000;\n  z-index: 100;\n  font-size: 90%;\n}\n\n.calendar .combo .label,\n.calendar .combo .label-IEfix {\n  text-align: center;\n  padding: 1px;\n}\n\n.calendar .combo .label-IEfix {\n  width: 4em;\n}\n\n.calendar .combo .hilite {\n  background: url(\"hover-bg.gif\"); color: #000;\n}\n\n.calendar .combo .active {\n  background: url(\"active-bg.gif\"); color: #fff;\n  font-weight: bold;\n}\n\n.calendar td.time {\n  border-top: 1px solid #797979;\n  padding: 1px 0px;\n  text-align: center;\n  background: url(\"dark-bg.gif\");\n}\n\n.calendar td.time .hour,\n.calendar td.time .minute,\n.calendar td.time .ampm {\n  padding: 0px 5px 0px 6px;\n  font-weight: bold;\n  background: url(\"normal-bg.gif\"); color: #000;\n}\n\n.calendar td.time .hour,\n.calendar td.time .minute {\n  font-family: monospace;\n}\n\n.calendar td.time .ampm {\n  text-align: center;\n}\n\n.calendar td.time .colon {\n  padding: 0px 2px 0px 3px;\n  font-weight: bold;\n}\n\n.calendar td.time span.hilite {\n  background: url(\"hover-bg.gif\"); color: #000;\n}\n\n.calendar td.time span.active {\n  background: url(\"active-bg.gif\"); color: #fff;\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/WEB-INF/web.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<web-app version=\"3.0\"\n         xmlns=\"http://java.sun.com/xml/ns/javaee\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://java.sun.com/xml/ns/javaee\n            http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd\">\n<!-- use empty -->\n</web-app>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/daily.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <title>CacheCloud值班电话</title>\n    <jsp:include page=\"/WEB-INF/include/head.jsp\"/>\n</head>\n<body>\n\t<div class=\"container\">\n\t\t<jsp:include page=\"/WEB-INF/include/headMenu.jsp\"/>\n\t\t<div class=\"row\">\n\t\t\t<div class=\"page-header\">\n                <h4>\n                \t值班联系人: \n                </h4>\n            </div>\n            <div id=\"contact\" class=\"page-body\">\n               <div class=\"well\">\n    \t\t\t\t<jsp:include page=\"/WEB-INF/include/contact.jsp\"/>\n\t\t\t   </div>\n            </div>\n\t\t\t\n\t\t</div>\n\t</div>\n</body>\n</html>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/error.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%@ include file=\"/WEB-INF/jsp/manage/commons/taglibs.jsp\"%>\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <title>CacheCloud异常</title>\n    <jsp:include page=\"/WEB-INF/include/head.jsp\"/>\n</head>\n<body>\n\t<div class=\"container\">\n\t\t<div class=\"row\">\n\t\t\t<div class=\"page-header\">\n                <h4>\n                \t<img width=\"70\" height=\"60\" src=\"/resources/img/cry.jpg\">\n                \t出错了！请联系我们: \n                </h4>\n            </div>\n            <div id=\"contact\" class=\"page-body\">\n               <div class=\"well\">\n\t\t\t   \t  <jsp:include page=\"/WEB-INF/include/contact.jsp\"/>\n\t\t\t   </div>\n            </div>\n\t\t\t\n\t\t</div>\n\t</div>\n</body>\n</html>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/index.jsp",
    "content": "<% \nresponse.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);\nString newLocation = \"admin/app/list\";\nresponse.setHeader(\"Location\",newLocation);\n%>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/main/webapp/test.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<html>\n<head>\n    <title>test</title>\n</head>\n<body>\n\ttest mm monitor\n</body>\n</html>\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/test/java/com/sohu/cache/dao/InstanceDaoTest.java",
    "content": "package com.sohu.cache.dao;\n\nimport com.sohu.test.BaseTest;\n\nimport org.junit.Test;\n\nimport javax.annotation.Resource;\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\n\n/**\n * 机器测试\n * \n * @author leifu\n * @Date 2016年3月17日\n * @Time 下午2:15:02\n */\npublic class InstanceDaoTest extends BaseTest {\n\n    @Resource\n    private InstanceDao instanceDao;\n\n    @Test\n    public void testGetMachineInstanceCountMap() throws Exception {\n        System.out.println(\"================testGetMachineInstanceCountMap start================\");\n        List<Map<String, Object>> mapList = instanceDao.getMachineInstanceCountMap();\n        for(Map<String, Object> map : mapList) {\n            System.out.println(map.get(\"ip\"));\n            System.out.println(map.get(\"count\"));\n        }\n        System.out.println(\"================testGetMachineInstanceCountMap start================\");\n\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/test/java/com/sohu/cache/dao/InstanceFaultDaoTest.java",
    "content": "package com.sohu.cache.dao;\n\nimport com.sohu.cache.entity.InstanceFault;\nimport com.sohu.test.BaseTest;\nimport org.junit.After;\nimport org.junit.Test;\nimport org.springframework.jdbc.core.JdbcTemplate;\n\nimport javax.annotation.Resource;\nimport java.util.Date;\nimport java.util.List;\n\n/**\n * Created by yijunzhang on 14-12-29.\n */\npublic class InstanceFaultDaoTest extends BaseTest {\n\n    @Resource\n    private InstanceFaultDao instanceFaultDao;\n\n    @Resource\n    private JdbcTemplate jdbcTemplate;\n\n    private int appId=10170;\n    private int instId=702;\n\n    @Test\n    public void testGetListByInstId() throws Exception {\n        List<InstanceFault> list = instanceFaultDao.getListByInstId(instId);\n        assertTrue(list.size() > 0);\n    }\n\n    @Test\n    public void testGetListByAppId() throws Exception {\n        List<InstanceFault> list = instanceFaultDao.getListByAppId(appId);\n        assertTrue(list.size() > 0);\n    }\n\n    @Test\n    public void cleanUp() {\n        jdbcTemplate.update(\"delete from instance_fault where app_id=\" + appId);\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/test/java/com/sohu/cache/dao/InstanceReshardProcessDaoTest.java",
    "content": "package com.sohu.cache.dao;\n\nimport java.util.Date;\n\nimport javax.annotation.Resource;\n\nimport org.junit.Test;\n\nimport com.sohu.cache.entity.InstanceReshardProcess;\nimport com.sohu.test.BaseTest;\n\n/**\n * @author leifu\n * @Date 2017年6月24日\n * @Time 下午8:44:27\n */\npublic class InstanceReshardProcessDaoTest extends BaseTest {\n\n    @Resource(name = \"instanceReshardProcessDao\")\n    private InstanceReshardProcessDao instanceReshardProcessDao;\n    \n    \n    @Test\n    public void testNotNull() {\n        assertNotNull(instanceReshardProcessDao);\n    }\n    \n    @Test\n    public void testSave() {\n        InstanceReshardProcess instanceReshardProcess = new InstanceReshardProcess();\n        instanceReshardProcess.setAppId(10000);\n        instanceReshardProcess.setAuditId(123);\n        instanceReshardProcess.setCreateTime(new Date());\n        instanceReshardProcess.setEndSlot(500);\n        instanceReshardProcess.setEndTime(new Date());\n        instanceReshardProcess.setFinishSlotNum(0);\n        instanceReshardProcess.setMigratingSlot(400);\n        instanceReshardProcess.setSourceInstanceId(1);\n        instanceReshardProcess.setStartSlot(300);\n        instanceReshardProcess.setStartTime(new Date());\n        instanceReshardProcess.setStatus(1);\n        instanceReshardProcess.setTargetInstanceId(5);\n        instanceReshardProcess.setUpdateTime(new Date());\n        \n        instanceReshardProcessDao.save(instanceReshardProcess);\n    }\n    \n    @Test\n    public void testUpdateEndTime() {\n        int id = 1;\n        instanceReshardProcessDao.updateEndTime(id, new Date());\n    }\n    \n    @Test\n    public void testUpdateStatus() {\n        int id = 1;\n        int status = 2;\n        instanceReshardProcessDao.updateStatus(id, status);\n    }\n    \n    @Test\n    public void testUpdateFinishSlotNum() {\n        int id = 1;\n        instanceReshardProcessDao.increaseFinishSlotNum(id);\n    }\n    \n    @Test\n    public void testUpdateMigratingSlot() {\n        int id = 1;\n        instanceReshardProcessDao.updateMigratingSlot(id, 30);\n    }\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/test/java/com/sohu/cache/dao/MachineDaoTest.java",
    "content": "package com.sohu.cache.dao;\n\nimport com.sohu.cache.entity.MachineInfo;\nimport com.sohu.test.BaseTest;\n\nimport org.junit.Test;\n\nimport javax.annotation.Resource;\n\nimport java.util.Date;\n\n/**\n * 机器测试\n * \n * @author leifu\n * @Date 2016年3月17日\n * @Time 下午2:15:02\n */\npublic class MachineDaoTest extends BaseTest {\n\n    @Resource\n    private MachineDao machineDao;\n\n    @Test\n    public void testSaveMachine() throws Exception {\n\n        MachineInfo machineInfo = new MachineInfo();\n        machineInfo.setCpu(16);\n        machineInfo.setIp(\"10.10.53.181\");\n        machineInfo.setMem(96);\n        machineInfo.setModifyTime(new Date());\n        machineInfo.setRealIp(\"\");\n        machineInfo.setRoom(\"北显\");\n        machineInfo.setServiceTime(new Date());\n        machineInfo.setSshPasswd(\"cachecloud-open\");\n        machineInfo.setSshUser(\"cachecloud-open\");\n\n        machineDao.saveMachineInfo(machineInfo);\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/test/java/com/sohu/cache/stats/app/AppDataMigrateCenterTest.java",
    "content": "package com.sohu.cache.stats.app;\n\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\nimport java.util.Map;\nimport java.util.Map.Entry;\n\nimport javax.annotation.Resource;\n\nimport org.junit.Test;\n\nimport com.sohu.cache.constant.AppDataMigrateEnum;\nimport com.sohu.cache.constant.AppDataMigrateResult;\nimport com.sohu.cache.constant.RedisMigrateToolConstant;\nimport com.sohu.cache.stats.app.impl.AppDataMigrateCenterImpl;\nimport com.sohu.cache.util.ConstUtils;\nimport com.sohu.test.BaseTest;\n\n/**\n * 测试迁移数据\n * \n * @author leifu\n * @Date 2016-6-8\n * @Time 下午8:53:19\n */\npublic class AppDataMigrateCenterTest extends BaseTest {\n\n    @Resource(name = \"appDataMigrateCenter\")\n    private AppDataMigrateCenterImpl appDataMigrateCenter;\n    \n    private final static String REDIS_SOURCE_PASS = \"redisSourcePassWord\";\n    \n    private final static String REDIS_TARGET_PASS = \"redisTargetPassWord\";\n\n    @Test\n    public void testCheckMigrateMachine() {\n        // 1.机器是否在列表里(已测)\n        // 2.是否正确安装redis-migrate-tool(已测)\n        // 3.是否存在正在执行的redis-migrate-tool(已测)\n\n        String migrateMachineIp = \"127.0.0.1\";\n        AppDataMigrateEnum sourceRedisMigrateEnum = AppDataMigrateEnum.REDIS_NODE;\n        String sourceServers = \"127.0.0.1:6379\";\n\n        AppDataMigrateEnum targetRedisMigrateEnum = AppDataMigrateEnum.REDIS_CLUSTER_NODE;\n        String targetServers = \"127.0.0.1:6380\";\n\n        AppDataMigrateResult redisMigrateResult = appDataMigrateCenter.check(migrateMachineIp, sourceRedisMigrateEnum,\n                sourceServers, targetRedisMigrateEnum, targetServers, REDIS_SOURCE_PASS, REDIS_TARGET_PASS);\n\n        logger.info(\"===============testCheck start=================\");\n        logger.info(redisMigrateResult.toString());\n        logger.info(\"===============testCheck end=================\");\n    }\n\n    @Test\n    public void testCheckServers() {\n        // 1. 实例列表格式问题(已测)\n        // 2.1 rdb文件是否存在(已测)\n        // 2.2 redis节点是否存活\n\n        String migrateMachineIp = \"127.0.0.1\";\n\n        // RedisMigrateEnum sourceRedisMigrateEnum =\n        // RedisMigrateEnum.REDIS_NODE;\n        // String sourceServers = \"127.0.0.1:6388\";\n\n        AppDataMigrateEnum sourceRedisMigrateEnum = AppDataMigrateEnum.RDB_FILE;\n        String sourceServers = \"/opt/soft/redis/data/dump-6380.rdb\";\n\n        AppDataMigrateEnum targetRedisMigrateEnum = AppDataMigrateEnum.REDIS_CLUSTER_NODE;\n        String targetServers = \"127.0.0.1:6380\";\n\n        AppDataMigrateResult redisMigrateResult = appDataMigrateCenter.check(migrateMachineIp, sourceRedisMigrateEnum,\n                sourceServers, targetRedisMigrateEnum, targetServers, REDIS_SOURCE_PASS, REDIS_TARGET_PASS);\n\n        logger.info(\"===============testCheck start=================\");\n        logger.info(redisMigrateResult.toString());\n        logger.info(\"===============testCheck end=================\");\n    }\n\n    private String getConfigContent() {\n        AppDataMigrateEnum sourceRedisMigrateEnum = AppDataMigrateEnum.REDIS_NODE;\n        String sourceServers = \"127.0.0.1:6379\";\n\n        AppDataMigrateEnum targetRedisMigrateEnum = AppDataMigrateEnum.REDIS_CLUSTER_NODE;\n        String targetServers = \"127.0.0.1:6380\";\n\n        int port = ConstUtils.REDIS_MIGRATE_TOOL_PORT;\n        String configConent = appDataMigrateCenter.generateConfig(port, sourceRedisMigrateEnum, sourceServers,\n                targetRedisMigrateEnum, targetServers, REDIS_SOURCE_PASS, REDIS_TARGET_PASS);\n        return configConent;\n    }\n\n    @Test\n    public void testConfigFile() {\n        String configConent = getConfigContent();\n        logger.info(\"===============testCheck start=================\");\n        logger.info(configConent);\n        logger.info(\"===============testCheck end=================\");\n    }\n\n    @Test\n    public void testCreateRemoteFile() {\n        String fileName = \"rmt-\" + new SimpleDateFormat(\"yyyyMMddHHmmss\").format(new Date()) + \".conf\";\n        String configConent = getConfigContent();\n        String migrateMachineIp = \"127.0.0.1\";\n        appDataMigrateCenter.createRemoteFile(migrateMachineIp, fileName, configConent);\n    }\n\n    @Test\n    public void testMigrateNode() {\n        String migrateMachineIp = \"127.0.0.1\";\n        AppDataMigrateEnum sourceRedisMigrateEnum = AppDataMigrateEnum.REDIS_NODE;\n        String sourceServers = \"127.0.0.1:6379\";\n        AppDataMigrateEnum targetRedisMigrateEnum = AppDataMigrateEnum.REDIS_CLUSTER_NODE;\n        String targetServers = \"127.0.0.1:6380\";\n\n        boolean isMigrate = appDataMigrateCenter.migrate(migrateMachineIp, sourceRedisMigrateEnum, sourceServers,\n                targetRedisMigrateEnum,\n                targetServers, 10000, 20000, REDIS_SOURCE_PASS, REDIS_TARGET_PASS, 30000);\n        logger.warn(\"============testMigrate start=============\");\n        logger.warn(\"isMigrate:{}\", isMigrate);\n        logger.warn(\"============testMigrate end=============\");\n    }\n    \n    @Test\n    public void testMigrateRDB() {\n        String migrateMachineIp = \"127.0.0.1\";\n        AppDataMigrateEnum sourceRedisMigrateEnum = AppDataMigrateEnum.RDB_FILE;\n        String sourceServers = \"/opt/soft/redis/data/dump-6379.rdb.back\";\n        AppDataMigrateEnum targetRedisMigrateEnum = AppDataMigrateEnum.REDIS_NODE;\n        String targetServers = \"127.0.0.1:6380\";\n\n        boolean isMigrate = appDataMigrateCenter.migrate(migrateMachineIp, sourceRedisMigrateEnum, sourceServers,\n                targetRedisMigrateEnum,\n                targetServers, 10000, 20000, REDIS_SOURCE_PASS, REDIS_TARGET_PASS, 30000);\n        logger.warn(\"============testMigrate start=============\");\n        logger.warn(\"isMigrate:{}\", isMigrate);\n        logger.warn(\"============testMigrate end=============\");\n    }\n    \n    @Test\n    public void testShowMiragteToolProcess() {\n        long id = 1;\n        Map<RedisMigrateToolConstant, Map<String, Object>> map = appDataMigrateCenter.showMiragteToolProcess(id);\n        logger.warn(\"============testShowMiragteToolProcess start=============\");\n        for(Entry<RedisMigrateToolConstant, Map<String, Object>> entry : map.entrySet()) {\n            logger.info(entry.getKey().getValue());\n            for(Entry<String, Object> entry2 : entry.getValue().entrySet()) {\n                logger.info(\"\\t\" + entry2.getKey() + \"->\" + entry2.getValue());\n            }\n        }\n        logger.warn(\"============testShowMiragteToolProcess end=============\");\n    }\n    \n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/test/java/com/sohu/cache/stats/app/ImportAppCenterTest.java",
    "content": "package com.sohu.cache.stats.app;\n\nimport java.util.Date;\n\nimport javax.annotation.Resource;\n\nimport org.junit.Test;\n\nimport com.sohu.cache.constant.ImportAppResult;\nimport com.sohu.cache.entity.AppDesc;\nimport com.sohu.cache.util.ConstUtils;\nimport com.sohu.test.BaseTest;\n\n/**\n * 应用导入测试\n * \n * @author leifu\n * @Date 2016-4-16\n * @Time 下午5:55:38\n */\npublic class ImportAppCenterTest extends BaseTest {\n\n    @Resource(name = \"importAppCenter\")\n    private ImportAppCenter importAppCenter;\n\n    @Test\n    public void testImport() {\n        // 应用信息\n        AppDesc appDesc = new AppDesc();\n        appDesc.setName(\"my-old-sentinel\");\n        appDesc.setIntro(\"my-old-sentinel desc\");\n        appDesc.setOfficer(\"付磊\");\n        appDesc.setCreateTime(new Date());\n        appDesc.setPassedTime(new Date());\n        appDesc.setIsTest(1);\n        appDesc.setType(ConstUtils.CACHE_TYPE_REDIS_CLUSTER);\n        appDesc.setMemAlertValue(80);\n        appDesc.setStatus(2);\n        appDesc.setUserId(1);\n        appDesc.setVerId(1);\n\n        // 实例信息\n        String appInstanceInfo =\n                        \"10.10.53.159:7000:512\\n\" +\n                        \"10.10.53.159:7001:512\\n\" +\n                        \"10.10.53.159:26379:mymaster\\n\" +\n                        \"10.10.53.159:26380:mymaster\\n\" +\n                        \"10.10.53.159:26381:mymaster\";\n        boolean result = importAppCenter.importAppAndInstance(appDesc, appInstanceInfo);\n        logger.info(\"result: {}\", result);\n    }\n\n    /**\n     * 重复应用名\n     */\n    @Test\n    public void testCheckAppDuplicateName() {\n        // 应用信息\n        AppDesc appDesc = new AppDesc();\n        appDesc.setName(\"redis-cluster-test\");\n        // 实例信息\n        String appInstanceInfo = \"\";\n        ImportAppResult importAppResult = importAppCenter.check(appDesc, appInstanceInfo);\n        logger.info(\"importAppResult: {}\", importAppResult);\n    }\n\n    /**\n     * 应用实例详情为空\n     */\n    @Test\n    public void testCheckEmptyAppInstanceInfo1() {\n        // 应用信息\n        AppDesc appDesc = new AppDesc();\n        appDesc.setName(\"carlosfu1\");\n        // 实例信息\n        String appInstanceInfo = \"\";\n        ImportAppResult importAppResult = importAppCenter.check(appDesc, appInstanceInfo);\n        logger.info(\"importAppResult: {}\", importAppResult);\n    }\n\n    /**\n     * 应用实例详情格式有问题1\n     */\n    @Test\n    public void testCheckWrongFormatAppInstanceInfo2() {\n        // 应用信息\n        AppDesc appDesc = new AppDesc();\n        appDesc.setName(\"carlosfu2\");\n        // 实例信息\n        String appInstanceInfo = \"\\n10.10.53.159:6379:1024\";\n        ImportAppResult importAppResult = importAppCenter.check(appDesc, appInstanceInfo);\n        logger.info(\"importAppResult: {}\", importAppResult);\n    }\n\n    /**\n     * 应用实例详情格式有问题2\n     */\n    @Test\n    public void testCheckWrongFormatAppInstanceInfo3() {\n        // 应用信息\n        AppDesc appDesc = new AppDesc();\n        appDesc.setName(\"carlosfu3\");\n        // 实例信息\n        String appInstanceInfo = \"10.10.53.159:6379\";\n        ImportAppResult importAppResult = importAppCenter.check(appDesc, appInstanceInfo);\n        logger.info(\"importAppResult: {}\", importAppResult);\n    }\n\n    /**\n     * 应用实例详情格式有问题4\n     */\n    @Test\n    public void testCheckWrongFormatAppInstanceInfo4() {\n        // 应用信息\n        AppDesc appDesc = new AppDesc();\n        appDesc.setName(\"carlosfu4\");\n        // 实例信息\n        String appInstanceInfo = \"10.10.10.10:6379:1024\";\n        ImportAppResult importAppResult = importAppCenter.check(appDesc, appInstanceInfo);\n        logger.info(\"importAppResult: {}\", importAppResult);\n    }\n\n    /**\n     * 应用实例详情格式有问题5\n     */\n    @Test\n    public void testCheckWrongFormatAppInstanceInfo5() {\n        // 应用信息\n        AppDesc appDesc = new AppDesc();\n        appDesc.setName(\"carlosfu5\");\n        // 实例信息\n        String appInstanceInfo = \"10.10.53.162:ab:1024\";\n        ImportAppResult importAppResult = importAppCenter.check(appDesc, appInstanceInfo);\n        logger.info(\"importAppResult: {}\", importAppResult);\n    }\n\n    /**\n     * 已经存在实例信息\n     */\n    @Test\n    public void testCheckExistInstanceInfo() {\n        // 应用信息\n        AppDesc appDesc = new AppDesc();\n        appDesc.setName(\"carlosfu6\");\n        // 实例信息\n        String appInstanceInfo = \"10.10.53.162:6379:1024\";\n        ImportAppResult importAppResult = importAppCenter.check(appDesc, appInstanceInfo);\n        logger.info(\"importAppResult: {}\", importAppResult);\n    }\n\n    /**\n     * 已经存在实例信息\n     */\n    @Test\n    public void testCheckNotRunInstance() {\n        // 应用信息\n        AppDesc appDesc = new AppDesc();\n        appDesc.setName(\"carlosfu7\");\n        // 实例信息\n        String appInstanceInfo = \"10.10.53.162:6399:1024\";\n        ImportAppResult importAppResult = importAppCenter.check(appDesc, appInstanceInfo);\n        logger.info(\"importAppResult: {}\", importAppResult);\n    }\n\n    /**\n     * 最大内存检查\n     */\n    @Test\n    public void testCheckWrongMaxMemory() {\n        // 应用信息\n        AppDesc appDesc = new AppDesc();\n        appDesc.setName(\"carlosfu8\");\n        // 实例信息\n        String appInstanceInfo = \"10.10.53.159:6379:aa\";\n        ImportAppResult importAppResult = importAppCenter.check(appDesc, appInstanceInfo);\n        logger.info(\"importAppResult: {}\", importAppResult);\n    }\n\n    /**\n     */\n    @Test\n    public void testCheckDataNode() {\n        // 应用信息\n        AppDesc appDesc = new AppDesc();\n        appDesc.setName(\"carlosfu9\");\n        // 实例信息\n        String appInstanceInfo = \"10.10.53.159:6379:1024\";\n        ImportAppResult importAppResult = importAppCenter.check(appDesc, appInstanceInfo);\n        logger.info(\"importAppResult: {}\", importAppResult);\n    }\n\n    /**\n     * 测试sentinel的masterName\n     */\n    @Test\n    public void testCheckSentinelNodeMasterName() {\n        // 应用信息\n        AppDesc appDesc = new AppDesc();\n        appDesc.setName(\"carlosfu10\");\n        // 实例信息\n        String appInstanceInfo = \"10.10.53.159:26379:1024\";\n        ImportAppResult importAppResult = importAppCenter.check(appDesc, appInstanceInfo);\n        logger.info(\"importAppResult: {}\", importAppResult);\n    }\n\n    /**\n     * 检测sentinel节点\n     */\n    @Test\n    public void testCheckSentinelNode() {\n        // 应用信息\n        AppDesc appDesc = new AppDesc();\n        appDesc.setName(\"carlosfu11\");\n        // 实例信息\n        String appInstanceInfo = \"10.10.53.159:26379:mymaster\";\n        ImportAppResult importAppResult = importAppCenter.check(appDesc, appInstanceInfo);\n        logger.info(\"importAppResult: {}\", importAppResult);\n    }\n\n    /**\n     * 检测sentinel节点\n     */\n    @Test\n    public void testCheckSentinelAllNodes() {\n        // 应用信息\n        AppDesc appDesc = new AppDesc();\n        appDesc.setName(\"carlosfu12\");\n        // 实例信息\n        String appInstanceInfo =\n                \"10.10.53.159:7000:512\\n\" +\n                        \"10.10.53.159:7001:512\\n\" +\n                        \"10.10.53.159:26379:mymaster\\n\" +\n                        \"10.10.53.159:26380:mymaster\\n\" +\n                        \"10.10.53.159:26381:mymaster\";\n        ImportAppResult importAppResult = importAppCenter.check(appDesc, appInstanceInfo);\n        logger.info(\"importAppResult: {}\", importAppResult);\n    }\n\n    @Test\n    public void testCheckClusterNodes() {\n        // 应用信息\n        AppDesc appDesc = new AppDesc();\n        appDesc.setName(\"carlosfu13\");\n        // 实例信息\n        String appInstanceInfo =\n                \"10.10.53.159:8000:512\\n\" +\n                        \"10.10.53.159:8001:512\\n\" +\n                        \"10.10.53.159:8002:512\\n\" +\n                        \"10.10.53.159:8003:512\\n\" +\n                        \"10.10.53.159:8004:512\\n\" +\n                        \"10.10.53.159:8005:512\\n\";\n        ImportAppResult importAppResult = importAppCenter.check(appDesc, appInstanceInfo);\n        logger.info(\"importAppResult: {}\", importAppResult);\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/test/java/com/sohu/test/BaseTest.java",
    "content": "package com.sohu.test;\n\nimport org.junit.Assert;\nimport org.junit.runner.RunWith;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.test.context.ContextConfiguration;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.util.StopWatch;\n\n/**\n * Created by yijunzhang on 14-6-4.\n */\n@RunWith(SpringJUnit4ClassRunner.class)\n@ContextConfiguration({\"classpath:spring-test.xml\"})\npublic class BaseTest  extends Assert {\n    protected final Logger logger = LoggerFactory.getLogger(this.getClass());\n\n    protected StopWatch watch = new StopWatch();\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/test/java/com/sohu/test/SimpleBaseTest.java",
    "content": "package com.sohu.test;\n\nimport org.junit.Assert;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n\n/**\n * User: lingguo\n * Date: 14-6-11\n * Time: 下午3:57\n */\npublic class SimpleBaseTest extends Assert {\n    protected final Logger logger = LoggerFactory.getLogger(this.getClass());\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/test/java/com/sohu/test/alert/AppServiceAlertImplTest.java",
    "content": "package com.sohu.test.alert;\n\nimport javax.annotation.Resource;\n\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.web.service.AppService;\nimport org.junit.Test;\n\nimport com.sohu.cache.alert.AppAlertService;\nimport com.sohu.test.BaseTest;\nimport org.springframework.util.StopWatch;\n\nimport java.util.List;\n\n/**\n * app报警测试\n * \n * @author leifu\n * @Date 2014年12月16日\n * @Time 下午2:58:47\n */\npublic class AppServiceAlertImplTest extends BaseTest {\n\n    @Resource(name = \"appAlertService\")\n    private AppAlertService appAlertService;\n\n    @Resource\n    private AppService appService;\n\n    @Test\n    public void testNotNull() {\n        assertNotNull(appAlertService);\n    }\n\n    @Test\n    public void getAppInstanceInfo() {\n        watch.start(\"getAppInstanceInfo1\");\n        List<InstanceInfo> list = appService.getAppInstanceInfo(10129L);\n        watch.stop();\n        watch.start(\"getAppInstanceInfo2\");\n        list = appService.getAppInstanceInfo(10129L);\n        watch.stop();\n        logger.info(watch.prettyPrint());\n        for (InstanceInfo info : list) {\n            logger.warn(\"{}:{} -> {}:{} id={}\", info.getIp(), info.getPort(), info.getMasterHost(), info.getMasterPort(),info.getMasterInstanceId());\n        }\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/test/java/com/sohu/test/app/AppStatsCenterImplTest.java",
    "content": "package com.sohu.test.app;\n\nimport java.util.List;\n\nimport com.sohu.cache.entity.AppCommandGroup;\nimport com.sohu.cache.entity.AppCommandStats;\nimport com.sohu.cache.stats.app.AppStatsCenter;\nimport com.sohu.cache.web.vo.AppDetailVO;\nimport com.sohu.test.BaseTest;\n\nimport org.junit.Test;\n\nimport javax.annotation.Resource;\n\n/**\n * Created by yijunzhang on 14-8-29.\n */\npublic class AppStatsCenterImplTest extends BaseTest {\n\n    @Resource\n    private AppStatsCenter appStatsCenter;\n\n    @Test\n    public void getAppDetail() {\n        long appId = 10015L;\n        long begin = System.currentTimeMillis();\n        AppDetailVO resultVO = appStatsCenter.getAppDetail(appId);\n        logger.info(\"cost=\" + (System.currentTimeMillis() - begin));\n        logger.info(\"result={}\", resultVO);\n    }\n    \n    @Test\n    public void getAppCommandGroup(){\n    \tlong appId = 10016L;\n    \tlong beginTime = 201408260001L;\n    \tlong endTime = 201408261601L;\n    \tList<AppCommandGroup> list = appStatsCenter.getAppCommandGroup(appId, beginTime, endTime);\n        logger.info(\"list={}\", list);\n    }\n    \n    @Test\n    public void getTop5AppCommandStatsList(){\n    \tlong appId = 10130L;\n    \tlong beginTime = 201411060000L;\n    \tlong endTime = 201411070000L;\n    \tList<AppCommandStats> list = appStatsCenter.getTop5AppCommandStatsList(appId, beginTime, endTime);\n        logger.info(\"list={}\", list);\n    }\n\n    @Test\n    public void getCommandStatsListAll(){\n        long appId = 999L;\n        long beginTime = 201409100001L;\n        long endTime = 201409101601L;\n        List<AppCommandStats> list = appStatsCenter.getCommandStatsList(appId, beginTime, endTime);\n        logger.info(\"list={}\", list);\n    }\n\n    @Test\n    public void executeCommandRedisTest() {\n        long appId = 998L;\n        String command = \"info all\";\n        String value = appStatsCenter.executeCommand(appId, command);\n        logger.info(\"value={}\", value);\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/test/java/com/sohu/test/cache/inspect/AppClientConnInspectorTest.java",
    "content": "package com.sohu.test.cache.inspect;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport javax.annotation.Resource;\n\nimport org.junit.Test;\n\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.inspect.InspectParamEnum;\nimport com.sohu.cache.inspect.impl.AppClientConnInspector;\nimport com.sohu.cache.web.service.AppService;\nimport com.sohu.test.BaseTest;\n\n/**\n * 应用客户端连接数测试\n * @author leifu\n * @Date 2016年6月16日\n * @Time 上午10:31:51\n */\npublic class AppClientConnInspectorTest extends BaseTest {\n\n    @Resource\n    private AppClientConnInspector appClientConnInspector;\n    \n    @Resource\n    private AppService appService;\n    \n    @Test\n    public void testApp() {\n        long appId = 10024;\n        Map<InspectParamEnum, Object> paramMap = new HashMap<InspectParamEnum, Object>();\n        paramMap.put(InspectParamEnum.SPLIT_KEY, appId);\n        List<InstanceInfo> instanceInfoList = appService.getAppInstanceInfo(appId);\n        paramMap.put(InspectParamEnum.INSTANCE_LIST, instanceInfoList);\n        appClientConnInspector.inspect(paramMap);\n    }\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/test/java/com/sohu/test/dao/AppAuditDaoTest.java",
    "content": "package com.sohu.test.dao;\n\nimport com.sohu.cache.constant.AppAuditType;\nimport com.sohu.cache.constant.AppStatusEnum;\nimport com.sohu.cache.dao.AppAuditDao;\nimport com.sohu.cache.dao.AppDao;\nimport com.sohu.cache.dao.AppUserDao;\nimport com.sohu.cache.entity.AppAudit;\nimport com.sohu.cache.entity.AppDesc;\nimport com.sohu.cache.entity.AppUser;\nimport com.sohu.test.BaseTest;\n\nimport org.junit.Test;\n\nimport javax.annotation.Resource;\n\nimport java.util.Date;\nimport java.util.List;\n\n/**\n * Created by yijunzhang on 14-10-20.\n */\npublic class AppAuditDaoTest extends BaseTest{\n    @Resource\n    private AppAuditDao appAuditDao;\n\n    @Resource\n    private AppUserDao appUserDao;\n\n    @Resource\n    private AppDao appDao;\n\n    @Test\n    public void testInsert(){\n        int memSize = 4;\n        AppDesc appDesc = appDao.getAppDescById(10132L);\n        AppUser appUser = appUserDao.get(10016L);\n        AppAudit appAudit = new AppAudit();\n        appAudit.setAppId(appDesc.getAppId());\n        appAudit.setUserId(appUser.getId());\n        appAudit.setUserName(appUser.getName());\n        appAudit.setModifyTime(new Date());\n        appAudit.setParam1(String.valueOf(memSize));\n        appAudit.setParam2(appDesc.getTypeDesc());\n        appAudit.setInfo(\"应用申请:类型:\" + appDesc.getTypeDesc() + \";初始申请空间:\" + memSize + \";\");\n        appAudit.setStatus(AppStatusEnum.STATUS_INITIALIZE.getStatus());\n        appAudit.setType(AppAuditType.APP_AUDIT.getValue());\n        appAuditDao.insertAppAudit(appAudit);\n\n    }\n    \n    @Test\n    public void testSelect(){\n        List<AppAudit> audits = appAuditDao.selectWaitAppAudits(1, 1);\n        logger.info(\"list={}\", audits);\n    }\n    \n    @Test\n    public void testUpdateRefuseReason(){\n        appAuditDao.updateRefuseReason(13, \"呵呵!\");\n    }\n\n    \n    @Test\n    public void testGetAppAuditByAppId(){\n        Long appId = 10170L;\n        List<AppAudit> appAudits = appAuditDao.getAppAuditByAppId(appId);\n        for(AppAudit appAudit : appAudits){\n            logger.info(\"{}\", appAudit);\n        }\n    }\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/test/java/com/sohu/test/dao/AppAuditLogDaoTest.java",
    "content": "package com.sohu.test.dao;\n\nimport javax.annotation.Resource;\n\nimport org.junit.Test;\n\nimport com.sohu.cache.constant.AppAuditLogTypeEnum;\nimport com.sohu.cache.dao.AppAuditLogDao;\nimport com.sohu.cache.entity.AppAuditLog;\nimport com.sohu.test.BaseTest;\n\n/**\n * @author leifu\n * @Date 2014年12月23日\n * @Time 上午9:41:16\n */\npublic class AppAuditLogDaoTest extends BaseTest {\n    @Resource(name = \"appAuditLogDao\")\n    private AppAuditLogDao appAuditLogDao;\n\n    @Test\n    public void getAuditByType() {\n        Long appAuditId = 75L;\n        AppAuditLog appAuditLog = appAuditLogDao.getAuditByType(appAuditId, AppAuditLogTypeEnum.APP_CHECK.value());\n        logger.info(\"{}\", appAuditLog);\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/test/java/com/sohu/test/dao/AppClientReportDataSizeDaoTest.java",
    "content": "package com.sohu.test.dao;\n\nimport java.util.Date;\n\nimport javax.annotation.Resource;\n\nimport org.junit.Test;\n\nimport com.sohu.cache.dao.AppClientReportDataSizeDao;\nimport com.sohu.cache.entity.AppClientDataSizeStat;\nimport com.sohu.test.BaseTest;\n\n/**\n * 客户端内收集数据map的尺寸查询--测试\n * @author leifu\n * @Date 2015年7月13日\n * @Time 下午3:43:20\n */\npublic class AppClientReportDataSizeDaoTest extends BaseTest {\n\n    @Resource\n    private AppClientReportDataSizeDao appClientReportDataSizeDao;\n\n    @Test\n    public void testSave() {\n        AppClientDataSizeStat stat = new AppClientDataSizeStat();\n        stat.setClientIp(\"10.7.40.201\");\n        stat.setReportTime(new Date());\n        stat.setCollectTime(20150120135000L);\n        stat.setCreateTime(new Date());\n\n        stat.setCostMapSize(100);\n        stat.setExceptionMapSize(5);\n        stat.setValueMapSize(86);\n        stat.setCollectMapSize(50);\n\n        appClientReportDataSizeDao.save(stat);\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/test/java/com/sohu/test/dao/AppClientVersionDaoTest.java",
    "content": "package com.sohu.test.dao;\n\nimport java.util.List;\n\nimport javax.annotation.Resource;\n\nimport org.junit.Test;\n\nimport com.sohu.cache.dao.AppClientVersionDao;\nimport com.sohu.cache.entity.AppClientVersion;\nimport com.sohu.test.BaseTest;\n\npublic class AppClientVersionDaoTest extends BaseTest{\n\n    @Resource\n    private AppClientVersionDao appClientVersionDao;\n    \n    \n    @Test\n    public void testGetByClientIp(){\n        List<AppClientVersion> list = appClientVersionDao.getByClientIp(\"192.168.106.165\");\n        logger.info(\"list={}\", list);\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/test/java/com/sohu/test/dao/AppDaoTest.java",
    "content": "package com.sohu.test.dao;\n\nimport java.util.List;\n\nimport com.sohu.cache.dao.AppDao;\nimport com.sohu.cache.entity.AppDesc;\nimport com.sohu.cache.entity.AppSearch;\nimport com.sohu.test.BaseTest;\n\nimport org.junit.Test;\n\nimport javax.annotation.Resource;\n\n/**\n * User: lingguo\n * Date: 14-6-10\n * Time: 下午11:36\n */\npublic class AppDaoTest extends BaseTest{\n    @Resource\n    private AppDao appDao;\n\n    @Test\n    public void testAppDao() {\n        long appId = 998L;\n        AppDesc appDesc = appDao.getAppDescById(appId);\n        logger.info(\"{}\", appDesc.toString());\n    }\n    \n    \n    @Test\n    public void testGetAllAppDescList(){\n        AppSearch vo = new AppSearch();\n        vo.setAppName(\"vrspoll\");\n        vo.setAppId(10011L);\n        List<AppDesc> list = appDao.getAllAppDescList(vo);\n        logger.info(\"list is {}\", list);\n    }\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/test/java/com/sohu/test/dao/AppDataMigrateStatusDaoTest.java",
    "content": "package com.sohu.test.dao;\n\nimport java.util.Date;\nimport java.util.List;\n\nimport javax.annotation.Resource;\n\nimport org.junit.Test;\n\nimport com.sohu.cache.constant.AppDataMigrateStatusEnum;\nimport com.sohu.cache.dao.AppDataMigrateStatusDao;\nimport com.sohu.cache.entity.AppDataMigrateStatus;\nimport com.sohu.test.BaseTest;\n\n/**\n * 迁移状态dao测试\n * \n * @author leifu\n * @Date 2016-6-9\n * @Time 下午5:38:51\n */\npublic class AppDataMigrateStatusDaoTest extends BaseTest {\n\n    @Resource\n    private AppDataMigrateStatusDao appDataMigrateStatusDao;\n\n    @Test\n    public void testSave() {\n        AppDataMigrateStatus appDataMigrateStatus = new AppDataMigrateStatus();\n        appDataMigrateStatus.setEndTime(new Date());\n        appDataMigrateStatus.setMigrateMachineIp(\"10.10.53.159\");\n        appDataMigrateStatus.setMigrateMachinePort(8888);\n        appDataMigrateStatus.setStartTime(new Date());\n        appDataMigrateStatus.setStatus(1);\n        appDataMigrateStatus.setUserId(10244);\n        appDataMigrateStatus.setSourceAppId(10023);\n        appDataMigrateStatus.setSourceMigrateType(1);\n        appDataMigrateStatus.setSourceServers(\"10.10.53.159:6379\");\n        appDataMigrateStatus.setTargetAppId(0);\n        appDataMigrateStatus.setTargetMigrateType(2);\n        appDataMigrateStatus.setTargetServers(\"10.10.52.136:6385\");\n        appDataMigrateStatus.setLogPath(\"/opt/redis-migrate-tool/rmt-20160609144601.log\");\n        appDataMigrateStatus.setConfigPath(\"/opt/redis-migrate-tool/rmt-20160609144601.conf\");\n        appDataMigrateStatusDao.save(appDataMigrateStatus);\n    }\n\n    @Test\n    public void testSearch() {\n        List<AppDataMigrateStatus> list = appDataMigrateStatusDao.search(null);\n        System.out.println(\"list.size: \" + list.size());\n        logger.info(\"==============testSearch start==============\");\n        for (AppDataMigrateStatus appDataMigrateStatus : list) {\n            logger.info(appDataMigrateStatus.toString());\n        }\n        logger.info(\"==============testSearch end==============\");\n    }\n    \n    @Test\n    public void testGet() {\n        long id = 1;\n        AppDataMigrateStatus appDataMigrateStatus = appDataMigrateStatusDao.get(id);\n        logger.info(\"==============testGet start==============\");\n        logger.info(appDataMigrateStatus.toString());\n        logger.info(\"==============testGet end==============\");\n    }\n    \n    @Test\n    public void testUpdate() {\n        long id = 1;\n        int status = AppDataMigrateStatusEnum.END.getStatus();\n        appDataMigrateStatusDao.updateStatus(id, status);\n        AppDataMigrateStatus appDataMigrateStatus = appDataMigrateStatusDao.get(id);\n        logger.info(\"==============testGet start==============\");\n        logger.info(appDataMigrateStatus.toString());\n        logger.info(\"==============testGet end==============\");\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/test/java/com/sohu/test/dao/AppStatsDaoTest.java",
    "content": "package com.sohu.test.dao;\n\nimport com.sohu.cache.dao.AppStatsDao;\nimport com.sohu.cache.entity.AppCommandStats;\nimport com.sohu.cache.entity.AppStats;\nimport com.sohu.cache.entity.TimeDimensionality;\nimport com.sohu.test.BaseTest;\nimport org.junit.Test;\n\nimport javax.annotation.Resource;\nimport java.util.Date;\nimport java.util.List;\n\n/**\n * Created by yijunzhang on 14-6-9.\n */\npublic class AppStatsDaoTest extends BaseTest {\n\n    @Resource\n    private AppStatsDao appStatsDao;\n\n    private long appId = 10011L;\n\n    private long collectTime = 201412011530L;\n\n    @Test\n    public void testMergeAppStats() {\n        assertNotNull(appStatsDao);\n        AppStats appStats = new AppStats();\n        appStats.setAppId(appId);\n        appStats.setCollectTime(collectTime);\n        appStats.setConnectedClients(1);\n        appStats.setCreateTime(new Date());\n        appStats.setHits(10);\n        appStats.setMisses(10);\n        appStats.setUsedMemory(1024);\n        appStats.setEvictedKeys(10);\n        appStats.setExpiredKeys(10);\n        appStats.setNetInputByte(0);\n        appStats.setNetOutputByte(0);\n        appStats.setModifyTime(new Date());\n        appStatsDao.mergeMinuteAppStats(appStats);\n        appStatsDao.mergeHourAppStats(appStats);\n    }\n\n    @Test\n    public void testMergeCommandStatus() {\n        assertNotNull(appStatsDao);\n        AppCommandStats commandStats = new AppCommandStats();\n        commandStats.setAppId(appId);\n        commandStats.setCollectTime(collectTime);\n        commandStats.setCommandName(\"get\");\n        commandStats.setCommandCount(10);\n        commandStats.setModifyTime(new Date());\n        appStatsDao.mergeMinuteCommandStatus(commandStats);\n        appStatsDao.mergeHourCommandStatus(commandStats);\n    }\n\n    @Test\n    public void testMergeHourCommandStatus() {\n        String time = \"2014090216\";\n        for (int i = 10; i <= 19; i++) {\n            AppCommandStats commandStats = new AppCommandStats();\n            long collectTime = Long.parseLong(time + i);\n            commandStats.setAppId(appId);\n            commandStats.setCollectTime(collectTime);\n            commandStats.setCommandName(\"get\");\n            commandStats.setCommandCount(i + 100);\n            commandStats.setModifyTime(new Date());\n            appStatsDao.mergeHourCommandStatus(commandStats);\n        }\n    }\n\n    @Test\n    public void testMergeHourAppStats() {\n        assertNotNull(appStatsDao);\n        String time = \"2014090216\";\n        for (int i = 10; i <= 19; i++) {\n            long collectTime = Long.parseLong(time + i);\n            AppStats appStats = new AppStats();\n            appStats.setAppId(appId);\n            appStats.setCollectTime(collectTime);\n            appStats.setConnectedClients(1);\n            appStats.setCreateTime(new Date());\n            appStats.setHits(i * 20);\n            appStats.setMisses(i * 10);\n            appStats.setUsedMemory(i);\n            appStats.setEvictedKeys(i);\n            appStats.setExpiredKeys(i);\n            appStats.setModifyTime(new Date());\n            appStatsDao.mergeHourAppStats(appStats);\n        }\n    }\n\n    @Test\n    public void getAppStatsListByDate() {\n        List<AppStats> list = appStatsDao.getAppStatsList(appId, new TimeDimensionality(collectTime, collectTime + 20, \"yyyyMMddHHmm\"));\n        logger.info(list.toString());\n    }\n\n    @Test\n    public void getAppCommandStatsListByDate() {\n        List<AppCommandStats> list = appStatsDao.getAppCommandStatsList(appId, \"get\", new TimeDimensionality(collectTime, collectTime + 20, \"yyyyMMddHHmm\"));\n        logger.info(\"list->\" + list.toString());\n        logger.info(\"size->\" + list.size());\n    }\n\n    @Test\n    public void getAppAllCommandStatsList() {\n        List<AppCommandStats> list = appStatsDao.getAppAllCommandStatsList(appId, new TimeDimensionality(collectTime, collectTime + 1800, \"yyyyMMddHHmm\"));\n        logger.info(\"list->\" + list.toString());\n        logger.info(\"size->\" + list.size());\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/test/java/com/sohu/test/dao/AppToUserDaoTest.java",
    "content": "package com.sohu.test.dao;\n\nimport com.sohu.cache.dao.AppToUserDao;\nimport com.sohu.test.BaseTest;\n\nimport org.junit.Test;\n\nimport javax.annotation.Resource;\n\n\n/**\n * \n * @author leifu\n * @Time 2014年10月20日\n */\npublic class AppToUserDaoTest extends BaseTest{\n\n    @Resource\n    private AppToUserDao appToUserDao;\n\n    @Test\n    public void testDelete(){\n//        appToUserDao.deleteAppToUser(10087, 10040);\n    }\n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/test/java/com/sohu/test/dao/AppUserDaoTest.java",
    "content": "package com.sohu.test.dao;\n\nimport com.sohu.cache.dao.AppUserDao;\nimport com.sohu.cache.entity.AppUser;\nimport com.sohu.test.BaseTest;\n\nimport org.junit.Test;\n\nimport javax.annotation.Resource;\n\n/**\n * User: lingguo\n * Date: 14-6-10\n * Time: 下午11:36\n */\npublic class AppUserDaoTest extends BaseTest{\n    @Resource\n    private AppUserDao appUserDao;\n\n    @Test\n    public void testAppDao() {\n        AppUser appUser = AppUser.buildFrom(null, \"11\", \"fff\", \"leifu@sohu-inc.com\", \"13820794024\", -1);\n        appUserDao.save(appUser);\n        logger.info(\"{}\", appUser);\n    }\n    \n    \n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/test/java/com/sohu/test/dao/InstanceConfigDaoTest.java",
    "content": "package com.sohu.test.dao;\n\nimport java.util.Date;\nimport java.util.List;\n\nimport javax.annotation.Resource;\n\nimport org.junit.Test;\n\nimport com.sohu.cache.dao.InstanceConfigDao;\nimport com.sohu.cache.entity.InstanceConfig;\nimport com.sohu.cache.util.ConstUtils;\nimport com.sohu.test.BaseTest;\n\n/**\n * 配置模板测试\n * \n * @author leifu\n * @Date 2016年6月22日\n * @Time 下午5:55:51\n */\npublic class InstanceConfigDaoTest extends BaseTest {\n\n    @Resource\n    private InstanceConfigDao instanceConfigDao;\n\n    @Test\n    public void testGetByType() {\n        List<InstanceConfig> instanceConfigTemplateList = instanceConfigDao\n                .getByType(ConstUtils.CACHE_REDIS_STANDALONE);\n        for (InstanceConfig instanceConfigTemplate : instanceConfigTemplateList) {\n            logger.info(instanceConfigTemplate.toString());\n        }\n    }\n\n    @Test\n    public void testById() {\n        long id = 1;\n        InstanceConfig instanceConfig = instanceConfigDao.getById(id);\n        logger.info(\"===========testById start==============\");\n        logger.info(instanceConfig.toString());\n        logger.info(\"===========testById end==============\");\n    }\n\n    @Test\n    public void testByConfigKeyAndType() {\n        String configKey = \"port\";\n        int type = ConstUtils.CACHE_REDIS_STANDALONE;\n        InstanceConfig instanceConfig = instanceConfigDao.getByConfigKeyAndType(configKey, type);\n        logger.info(\"===========testById start==============\");\n        logger.info(instanceConfig.toString());\n        logger.info(\"===========testById end==============\");\n    }\n\n    @Test\n    public void testSaveOrUpdate() {\n        InstanceConfig instanceConfig = new InstanceConfig();\n        instanceConfig.setConfigKey(\"hello\");\n        instanceConfig.setConfigValue(\"world\");\n        instanceConfig.setInfo(\"info\");\n        instanceConfig.setStatus(1);\n        instanceConfig.setType(ConstUtils.CACHE_TYPE_REDIS_CLUSTER);\n        instanceConfig.setUpdateTime(new Date());\n\n        logger.info(\"===========testSaveOrUpdate start==============\");\n        instanceConfigDao.saveOrUpdate(instanceConfig);\n        logger.info(\"===========testSaveOrUpdate end==============\");\n    }\n\n    @Test\n    public void testUpdateStatus() {\n        long id = 1;\n        int status = 0;\n        logger.info(\"===========testUpdateStatus start==============\");\n        instanceConfigDao.updateStatus(id, status);\n        logger.info(\"===========testUpdateStatus end==============\");\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/test/java/com/sohu/test/dao/QuartzDaoTest.java",
    "content": "package com.sohu.test.dao;\n\nimport com.sohu.cache.dao.QuartzDao;\nimport com.sohu.cache.entity.TriggerInfo;\nimport com.sohu.cache.util.ConstUtils;\nimport com.sohu.test.BaseTest;\n\nimport org.junit.Test;\nimport org.quartz.Trigger;\n\nimport java.util.List;\n\nimport javax.annotation.Resource;\n\n/**\n * @author: lingguo\n * @time: 2014/10/13 16:02\n */\npublic class QuartzDaoTest extends BaseTest {\n\n    @Resource\n    private QuartzDao quartzDao;\n\n    @Test\n    public void testGetTriggersByJobGroup() {\n        List<TriggerInfo> triggers = quartzDao.getTriggersByJobGroup(ConstUtils.REDIS_JOB_GROUP);\n        for (TriggerInfo info: triggers) {\n            logger.info(\"info: {}\", info);\n        }\n    }\n\n    @Test\n    public void testGetAllTriggers() {\n        List<TriggerInfo> triggers = quartzDao.getAllTriggers();\n        for (TriggerInfo info: triggers) {\n            logger.info(\"{}\", info);\n        }\n    }\n\n    @Test\n    public void testSearchTriggerByNameOrGroup() {\n        String queryString = \"10078\";\n        List<TriggerInfo> triggers = quartzDao.searchTriggerByNameOrGroup(queryString);\n        for (TriggerInfo info: triggers) {\n            logger.info(\"info: {}, {}\", info, queryString);\n        }\n    }\n\n\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/test/java/com/sohu/test/init/MachineInitTest.java",
    "content": "package com.sohu.test.init;\n\nimport com.sohu.cache.init.MachineInitLoad;\nimport com.sohu.test.BaseTest;\n\nimport org.junit.Test;\n\nimport javax.annotation.Resource;\n\n/**\n * User: lingguo\n * Date: 14-6-12\n * Time: 下午3:20\n */\npublic class MachineInitTest extends BaseTest {\n\n    @Resource\n    MachineInitLoad machineInitLoad;\n\n    @Test\n    public void testInit() {\n        machineInitLoad.init();\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/test/java/com/sohu/test/inspect/InspectHandlerTest.java",
    "content": "package com.sohu.test.inspect;\n\nimport com.sohu.cache.inspect.InspectHandler;\nimport com.sohu.test.BaseTest;\nimport org.junit.Test;\n\nimport javax.annotation.Resource;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * Created by yijunzhang on 15-1-20.\n */\npublic class InspectHandlerTest extends BaseTest {\n\n    @Resource\n    private InspectHandler hostInspectHandler;\n\n    @Resource\n    private InspectHandler appInspectHandler;\n\n    @Test\n    public void handle(){\n        try {\n            hostInspectHandler.handle();\n            //appInspectHandler.handle();\n            TimeUnit.SECONDS.sleep(30);\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/test/java/com/sohu/test/instance/InstanceStatsCenterTest.java",
    "content": "package com.sohu.test.instance;\n\nimport com.sohu.cache.entity.InstanceCommandStats;\nimport com.sohu.cache.entity.InstanceStats;\nimport com.sohu.cache.stats.instance.InstanceStatsCenter;\nimport com.sohu.test.BaseTest;\nimport org.junit.Test;\n\nimport javax.annotation.Resource;\nimport java.util.List;\n\n/**\n * Created by yijunzhang on 14-9-18.\n */\npublic class InstanceStatsCenterTest extends BaseTest {\n\n    @Resource\n    private InstanceStatsCenter instanceStatsCenter;\n\n    @Test\n    public void getCommandStatsList() {\n        watch.start(\"getCommandStatsList\");\n        List<InstanceCommandStats> list = instanceStatsCenter.getCommandStatsList(523L,201506170000L,201506172359L,\"get\");\n        watch.stop();\n        logger.info(watch.prettyPrint());\n        logger.info(\"list={}\", list);\n    }\n\n    @Test\n    public void getInstanceStats() {\n        InstanceStats instanceStats = instanceStatsCenter.getInstanceStats(51L);\n        logger.info(\"{}\", instanceStats);\n        logger.info(\"{}\", instanceStats.getInfoMap());\n        logger.info(\"{}\", instanceStats.isRun());\n\n        instanceStats = instanceStatsCenter.getInstanceStats(139L);\n        logger.info(\"{}\", instanceStats);\n        logger.info(\"{}\", instanceStats.getInfoMap());\n        logger.info(\"{}\", instanceStats.isRun());\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/test/java/com/sohu/test/machine/PortGeneratorTest.java",
    "content": "package com.sohu.test.machine;\n\nimport java.util.List;\n\nimport javax.annotation.Resource;\n\nimport org.junit.Test;\n\nimport com.sohu.cache.dao.MachineDao;\nimport com.sohu.cache.entity.MachineInfo;\nimport com.sohu.cache.exception.SSHException;\nimport com.sohu.cache.machine.PortGenerator;\nimport com.sohu.cache.ssh.SSHUtil;\nimport com.sohu.test.BaseTest;\n\n/**\n * 查找最大端口两种方法对比\n * \n * @author leifu\n * @Date 2016年4月21日\n * @Time 下午6:14:31\n */\npublic class PortGeneratorTest extends BaseTest {\n    @Resource\n    private MachineDao machineDao;\n\n    @Test\n    public void testCheckMaxPort() throws SSHException {\n        List<MachineInfo> machineList = machineDao.getAllMachines();\n        for (MachineInfo machineInfo : machineList) {\n            String ip = machineInfo.getIp();\n            int sshPort = SSHUtil.getSshPort(ip);\n            String m1 = PortGenerator.getMaxPortStrOld(ip, sshPort);\n            String m2 = PortGenerator.getMaxPortStr(ip, sshPort);\n            boolean isSame = m1.equals(m2);\n            if (!isSame) {\n                System.out.println(ip + \", m1: \" + m1 + \", m2:\" + m2);\n            }\n        }\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/test/java/com/sohu/test/misc/MiscTest.java",
    "content": "package com.sohu.test.misc;\n\nimport com.sohu.test.SimpleBaseTest;\n\nimport com.google.common.collect.ImmutableMap;\nimport org.apache.commons.collections4.MapUtils;\nimport org.junit.Test;\n\nimport java.io.File;\nimport java.net.URISyntaxException;\nimport java.net.URL;\nimport java.nio.file.Paths;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * User: lingguo\n * Date: 14-6-30\n */\npublic class MiscTest extends SimpleBaseTest {\n\n    @Test\n    public void testSplit() {\n        String key = \"diff.cmd_get\";\n        String[] array = key.split(\"\\\\.\");\n        for (String s: array) {\n            logger.info(\"{}\", s);\n        }\n    }\n\n\n    @Test\n    public void testConvert() {\n        String value = \"2.39%\";\n        double result = 0;\n        try {\n            result = Double.parseDouble(value.substring(0, value.length()));\n        } catch (NumberFormatException e) {\n            logger.error(e.getMessage(), e);\n        }\n        logger.info(\"convert: {}\", result);\n    }\n\n    @Test\n    public void testCharacter() {\n        String ch = Character.toString((char)2);\n        logger.info(\"ch: {}\",ch);\n    }\n\n    @Test\n    public void testMaps() {\n        Map<String, Long> map = new HashMap<String, Long>();\n        map.put(\"first\", 10L);\n        map.put(\"second\", 20L);\n        map.put(\"third\", null);\n        logger.info(\"third from map: {}\", map.get(\"third\"));\n\n        try {\n            ImmutableMap<String, Long> readMap = ImmutableMap.copyOf(map);\n            logger.info(\"third from readMap: {}\", readMap.get(\"third\"));\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n        }\n\n        logger.info(\"third from MapUtils: {}\", MapUtils.getLong(map, \"third\", 1000L));\n    }\n\n    @Test\n    public void testPwd() {\n        String dir1 = System.getProperty(\"user.dir\");\n        String dir2 = Paths.get(\"\").toAbsolutePath().toString();\n        logger.info(\"dir1: {}, dir2: {}\", dir1, dir2);\n    }\n\n    @Test\n    public void deleteLocalFile() {\n        URL url = ClassLoader.getSystemResource(\"script/cachecloud-init.sh\");\n        try {\n            File file = new File(url.toURI());\n            if (file.exists()) {\n                logger.info(\"file is \" + file.getAbsolutePath());\n            }\n        } catch (URISyntaxException e) {\n            e.printStackTrace();\n        }\n    }\n\n    @Test\n    public void testLoggerError() {\n        String invalidIntStr = \"234t\";\n        try {\n            Integer.parseInt(invalidIntStr);\n        } catch (NumberFormatException e) {\n            logger.error(\"str: {}\", invalidIntStr, e);\n        }\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/test/java/com/sohu/test/protocol/RedisProtocolTest.java",
    "content": "package com.sohu.test.protocol;\n\nimport com.sohu.cache.protocol.RedisProtocol;\nimport org.junit.Test;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * Created by yijunzhang on 14-12-5.\n */\npublic class RedisProtocolTest {\n    private final Logger logger = LoggerFactory.getLogger(this.getClass());\n\n    @Test\n    public void testRedisProtocolEcho() {\n        logger.info(RedisProtocol.getRunShell(6379, true));\n        logger.info(RedisProtocol.getSentinelShell(6379));\n        logger.info(RedisProtocol.getConfig(6379, false));\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/test/java/com/sohu/test/redis/Node.java",
    "content": "package com.sohu.test.redis;\n\n/**\n * Created by yijunzhang on 14-5-27.\n */\npublic class Node {\n\n    private String host;\n\n    private int port;\n\n    /**\n     * Master=0\n     * Slave =1;\n     */\n    private int type;\n\n    /**\n     * 是否被选中 0：未选中,1 选中\n     */\n    private int selected = 0;\n\n    public Node(String host, int port, int type) {\n        this.host = host;\n        this.port = port;\n        this.type = type;\n    }\n\n    @Override\n    public String toString() {\n        return \"Node{\" +\n                \"host='\" + host + '\\'' +\n                \", port=\" + port +\n                \", type=\" + type +\n                \", selected=\" + selected +\n                '}';\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) return true;\n        if (!(o instanceof Node)) return false;\n\n        Node node = (Node) o;\n\n        if (port != node.port) return false;\n        if (type != node.type) return false;\n        if (host != null ? !host.equals(node.host) : node.host != null) return false;\n\n        return true;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = host != null ? host.hashCode() : 0;\n        result = 31 * result + port;\n        result = 31 * result + type;\n        return result;\n    }\n\n    public String getHost() {\n        return host;\n    }\n\n    public int getPort() {\n        return port;\n    }\n\n    public int getType() {\n        return type;\n    }\n\n    public boolean isSelected() {\n        return selected == 1;\n    }\n\n    public void selected() {\n        this.selected = 1;\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/test/java/com/sohu/test/redis/RedisConfigTemplateTest.java",
    "content": "package com.sohu.test.redis;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\n\nimport javax.annotation.Resource;\n\nimport org.junit.Test;\n\nimport com.sohu.cache.redis.RedisConfigTemplateService;\nimport com.sohu.test.BaseTest;\n\n/**\n * Redis配置模板测试\n * @author leifu\n * @Date 2016年6月22日\n * @Time 下午6:26:28\n */\npublic class RedisConfigTemplateTest extends BaseTest {\n\n    @Resource\n    private RedisConfigTemplateService redisConfigTemplateService;\n    \n\n    @Test\n    public void testSentinelConfig() {\n        String masterName = \"mymaster\";\n        String host = \"127.0.0.1\";\n        int port = 6379;\n        int sentinelPort = 26379;\n\n        List<String> sentinelList1 = redisConfigTemplateService.handleSentinelDefaultConfig(masterName, host, port, sentinelPort);\n        List<String> sentinelList2 = redisConfigTemplateService.handleSentinelConfig(masterName, host, port, sentinelPort);\n\n        Collections.sort(sentinelList1);\n        Collections.sort(sentinelList2);\n\n        for (int i = 0; i < sentinelList1.size() && i < sentinelList2.size(); i++) {\n            System.out.println(sentinelList1.get(i) + \"<-->\" + sentinelList2.get(i));\n            System.out.println(sentinelList1.get(i).equals(sentinelList2.get(i)));\n        }\n    }\n\n    @Test\n    public void testCommonConfig() {\n        int port = 6379;\n        int maxMemory = 2048;\n\n        List<String> commonList1 = redisConfigTemplateService.handleCommonDefaultConfig(port, maxMemory);\n        List<String> commonList2 = redisConfigTemplateService.handleCommonConfig(port, maxMemory);\n\n        Collections.sort(commonList1);\n        Collections.sort(commonList2);\n\n        List<String> remains = new ArrayList<String>();\n        for (String config : commonList2) {\n            if (commonList1.contains(config)) {\n                System.out.println(config);\n            } else {\n                remains.add(config);\n            }\n        }\n\n        System.out.println(\"===============remain====================\");\n        for (int i = 0; i < remains.size(); i++) {\n            System.out.println(remains.get(i));\n        }\n    }\n\n    @Test\n    public void testClusterConfig() {\n        int port = 6379;\n\n        List<String> clusterList1 = redisConfigTemplateService.handleClusterDefaultConfig(port);\n        List<String> clusterList2 = redisConfigTemplateService.handleClusterConfig(port);\n\n        Collections.sort(clusterList1);\n        Collections.sort(clusterList2);\n\n        for (int i = 0; i < clusterList1.size() && i < clusterList2.size(); i++) {\n            System.out.println(clusterList1.get(i) + \"<-->\" + clusterList2.get(i));\n            System.out.println(clusterList1.get(i).equals(clusterList2.get(i)));\n        }\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/test/java/com/sohu/test/redis/RedisImportantDataDeal.java",
    "content": "package com.sohu.test.redis;\n\nimport java.io.BufferedReader;\nimport java.io.IOException;\nimport java.io.InputStreamReader;\nimport java.util.List;\n\nimport javax.annotation.Resource;\n\nimport org.apache.commons.collections.CollectionUtils;\nimport org.junit.Test;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.sohu.cache.constant.InstanceStatusEnum;\nimport com.sohu.cache.dao.InstanceDao;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.redis.RedisCenter;\nimport com.sohu.cache.util.TypeUtil;\nimport com.sohu.test.BaseTest;\n\nimport redis.clients.jedis.Jedis;\n\n/**\n * redis重要数据处理（请注意BaseTest是local环境）\n * \n * @author leifu\n * @Date 2015年3月4日\n * @Time 上午11:04:04\n */\npublic class RedisImportantDataDeal extends BaseTest {\n    private final static Logger logger = LoggerFactory.getLogger(RedisImportantDataDeal.class);\n\n    @Resource(name = \"instanceDao\")\n    private InstanceDao instanceDao;\n    \n    @Resource(name = \"redisCenter\")\n    private RedisCenter redisCenter;\n\n    @Test\n    public void clearAllAppData() {\n        // /////////////一定要谨慎处理/////////////////\n        // /////////////一定要谨慎处理/////////////////\n        // /////////////一定要谨慎处理/////////////////\n        long appId = 000L;\n        // /////////////一定要谨慎处理///////////////\n        // /////////////一定要谨慎处理/////////////////\n        // /////////////一定要谨慎处理/////////////////\n\n        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));\n        logger.warn(\"确认要清除appId:\" + appId + \"的所有内存数据(输入y代表确认):\");\n        String confirm = null;\n        try {\n            confirm = br.readLine();\n        } catch (IOException e1) {\n            e1.printStackTrace();\n        } finally {\n            if (br != null) {\n                try {\n                    br.close();\n                } catch (IOException e) {\n                    e.printStackTrace();\n                }\n            }\n        }\n        if (!\"y\".equals(confirm)) {\n            return;\n        }\n        List<InstanceInfo> instanceList = instanceDao.getInstListByAppId(appId);\n        if (CollectionUtils.isEmpty(instanceList)) {\n            logger.error(\"appId: {}, 可能输入错误，不存在实例列表\");\n        }\n        for (InstanceInfo instance : instanceList) {\n            if (instance.getStatus() != InstanceStatusEnum.GOOD_STATUS.getStatus()) {\n                continue;\n            }\n            String host = instance.getIp();\n            int port = instance.getPort();\n            // master + 非sentinel节点\n            Boolean isMater = redisCenter.isMaster(appId, host, port);\n            if (isMater != null && isMater.equals(true) && !TypeUtil.isRedisSentinel(instance.getType())) {\n                Jedis jedis = new Jedis(host, port, 30000);\n                try {\n                    logger.info(\"{}:{} 开始清理内存\", host, port);\n                    long start = System.currentTimeMillis();\n                    jedis.flushAll();\n                    logger.info(\"{}:{} 清理完成, 耗时:{} ms\", host, port, (System.currentTimeMillis() - start));\n                } catch (Exception e) {\n                    logger.error(e.getMessage());\n                } finally {\n                    jedis.close();\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/test/java/com/sohu/test/schedule/ScheduleUtilTestTest.java",
    "content": "package com.sohu.test.schedule;\n\nimport com.sohu.cache.util.ScheduleUtil;\nimport com.sohu.test.SimpleBaseTest;\n\nimport org.junit.Test;\n\n/**\n * User: lingguo\n * Date: 14-6-12\n * Time: 上午11:08\n */\npublic class ScheduleUtilTestTest extends SimpleBaseTest {\n\n    @Test\n    public void testHourCron() {\n        long hostId = 34L;\n        logger.info(\"{}\", ScheduleUtil.getHourCronByHostId(hostId));\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/test/java/com/sohu/test/schedule/SchedulerCenterTest.java",
    "content": "package com.sohu.test.schedule;\n\nimport com.sohu.cache.schedule.SchedulerCenter;\nimport com.sohu.cache.util.ConstUtils;\nimport com.sohu.test.BaseTest;\n\nimport org.junit.Test;\nimport org.quartz.Trigger;\nimport org.quartz.TriggerKey;\n\nimport javax.annotation.Resource;\n\n/**\n * @author: lingguo\n * @time: 2014/9/2 11:47\n */\npublic class SchedulerCenterTest extends BaseTest {\n\n    @Resource\n    SchedulerCenter schedulerCenter;\n\n    @Test\n    public void testSchedule() {\n        TriggerKey key = TriggerKey.triggerKey(\"appInfoAlertTrigger\", \"appAlert\");\n        Trigger trigger = schedulerCenter.getTrigger(key);\n        if(trigger != null){\n            boolean isSchedule = schedulerCenter.unscheduleJob(key);\n            logger.warn(\"isSchedule={}\",isSchedule);\n        }\n//        try {\n//            TimeUnit.SECONDS.sleep(5);\n//        } catch (InterruptedException e) {\n//            logger.error(\"{}\", e);\n//        }\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/test/java/com/sohu/test/stats/app/AppCenterTest.java",
    "content": "package com.sohu.test.stats.app;\n\nimport com.sohu.cache.dao.AppStatsDao;\nimport com.sohu.cache.stats.app.AppStatsCenter;\nimport com.sohu.cache.constant.AppTopology;\nimport com.sohu.cache.entity.AppCommandStats;\nimport com.sohu.cache.entity.AppDesc;\nimport com.sohu.cache.entity.AppStats;\nimport com.sohu.cache.util.ScheduleUtil;\nimport com.sohu.test.BaseTest;\n\nimport org.junit.Assert;\nimport org.junit.Test;\n\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Map;\n\nimport javax.annotation.Resource;\n\n/**\n * Created by lingguo on 14-6-26.\n */\npublic class AppCenterTest extends BaseTest {\n\n    @Resource\n    private AppStatsCenter appStatsCenter;\n\n    @Test\n    public void testGetAppStatsListByMinuteTime() {\n        Assert.assertNotNull(appStatsCenter);\n\n        long appId = 999;\n        long endTime = ScheduleUtil.getCollectTime(new Date());\n        long beginTime = ScheduleUtil.getLastCollectTime(endTime);\n\n        List<AppStats> appStatsList = appStatsCenter.getAppStatsListByMinuteTime(appId, beginTime, endTime);\n        for (AppStats appStats: appStatsList) {\n            logger.info(\"appStats: {}\", appStats);\n        }\n    }\n\n    @Test\n    public void testGetAppCommandStatsListByMinuteTime() {\n        Assert.assertNotNull(appStatsCenter);\n\n        long appId = 999;\n        String beginStr = new SimpleDateFormat(\"yyyyMMdd\").format(new Date());\n        long begin = Integer.parseInt(beginStr + \"0000\");\n        long end = Integer.parseInt(beginStr + \"2359\");\n        List<AppCommandStats> topAppCommandStatsListByDate = appStatsCenter.getTop5AppCommandStatsList(appId, begin, end);\n        for (AppCommandStats appCommandStats : topAppCommandStatsListByDate) {\n            logger.info(\"appCommandStats: {}\", appCommandStats.toString());\n        }\n    }\n\n    @Test\n    public void testQueryAppTopology() {\n        Assert.assertNotNull(appStatsCenter);\n\n        long appId = 999;\n        Map<AppTopology, Object> appTopologyMap = appStatsCenter.queryAppTopology(appId);\n        for (AppTopology appTopology: appTopologyMap.keySet()) {\n            logger.info(\"key: {}, value: {}\", appTopology.getValue(), appTopologyMap.get(appTopology));\n        }\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/test/java/com/sohu/test/util/ObjectConvertTest.java",
    "content": "package com.sohu.test.util;\n\nimport com.sohu.cache.dao.InstanceDao;\nimport com.sohu.cache.entity.InstanceInfo;\nimport com.sohu.cache.util.ObjectConvert;\nimport com.sohu.test.BaseTest;\n\nimport org.junit.Test;\n\nimport java.util.List;\nimport javax.annotation.Resource;\n\n/**\n * User: lingguo\n * Date: 14-6-19\n * Time: 下午2:35\n */\npublic class ObjectConvertTest extends BaseTest {\n\n    @Resource\n    InstanceDao instanceDao;\n\n    @Test\n    public void testAssembleInst() {\n        long appId = 10000L;\n        List<InstanceInfo> infoList = instanceDao.getInstListByAppId(appId);\n        String shardInfo = ObjectConvert.assembleInstance(infoList);\n        logger.warn(\"shards: {}\", shardInfo);\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/test/java/com/sohu/test/util/SSHUtilTest.java",
    "content": "package com.sohu.test.util;\n\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.sohu.cache.entity.MachineStats;\nimport com.sohu.cache.exception.SSHException;\nimport com.sohu.cache.ssh.SSHUtil;\n\n/**\n * ssh工具测试\n * @author leifu\n * @Date 2016-3-28\n * @Time 下午9:09:55\n */\npublic class SSHUtilTest extends Assert{\n    private Logger logger = LoggerFactory.getLogger(SSHUtilTest.class);\n\n    @Test\n    public void testMachineStats() throws SSHException {\n        String ip = \"127.0.0.1\";\n        int port = 22;\n        String userName = \"cachecloud-open\";\n        String password = \"cachecloud-open\";\n        MachineStats machineStats = SSHUtil.getMachineInfo(ip, port, userName, password);\n        logger.info(\"ip {} machineStats: {}\", machineStats);\n    }\n    \n    @Test\n    public void testCpu() {\n        String redhat = \"Cpu(s):  1.1%us,  0.5%sy,  0.0%ni, 98.4%id,  0.0%wa,  0.0%hi,  0.1%si,  0.0%st\";\n        String centos7 = \"%Cpu(s):  0.11 us,  0.0 sy,  0.0 ni, 99.9 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st\";\n        String centos6 = \"Cpu(s):  4.7%us, 16.0%sy,  0.0%ni, 67.0%id, 12.1%wa,  0.1%hi,  0.1%si,  0.0%st\";\n        \n        assertTrue(SSHUtil.getUsCpu(redhat) == 1.1);\n        assertTrue(SSHUtil.getUsCpu(centos7) == 0.11);\n        assertTrue(SSHUtil.getUsCpu(centos6) == 4.7);\n    }\n    \n    \n    \n    \n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/test/java/com/sohu/test/util/ScheduleUtilTest.java",
    "content": "package com.sohu.test.util;\n\nimport com.sohu.cache.util.ScheduleUtil;\nimport com.sohu.test.SimpleBaseTest;\n\nimport org.junit.Test;\n\nimport java.util.Date;\n\n/**\n * User: lingguo\n * Date: 14-6-30\n */\npublic class ScheduleUtilTest extends SimpleBaseTest {\n\n    @Test\n    public void testGtBeginTimeOfDay() {\n        long todayBegin = ScheduleUtil.getBeginTimeOfDay(new Date(), 0);\n        long tomorrowBegin = ScheduleUtil.getBeginTimeOfDay(new Date(), 1);\n        logger.info(\"today: {}, tomorrow: {}\", todayBegin, tomorrowBegin);\n    }\n\n\n    @Test\n    public void testGetHourCronByHostId() {\n        String cron1 = ScheduleUtil.getHourCronByHostId(24);\n        String cron3 = ScheduleUtil.getHourCronByHostId(25);\n//        try {\n//            TimeUnit.SECONDS.sleep(5);\n//        } catch (InterruptedException e) {\n//            logger.error(e.getMessage(), e);\n//        }\n        String cron2 = ScheduleUtil.getHourCronByHostId(24);\n        String cron4 = ScheduleUtil.getHourCronByHostId(25);\n\n        logger.info(\"cron1: {}, cron2: {}, cron3: {}, cron4: {}\", cron1, cron2, cron3, cron4);\n        logger.info(\"time: {}\", new Date());\n\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/test/resources/logback-test.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n  Example LOGBACK Configuration File\n  http://logback.qos.ch/manual/configuration.html\n  -->\n<configuration scan=\"true\" scanPeriod=\"30 seconds\">\n\n    <appender name=\"console\" class=\"ch.qos.logback.core.ConsoleAppender\">\n        <encoder>\n            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>\n        </encoder>\n    </appender>\n\n    <root level=\"info\">\n        <appender-ref ref=\"console\"/>\n    </root>\n</configuration>"
  },
  {
    "path": "open-monitor-center/cachecloud/cachecloud-open-web/src/test/resources/spring-test.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\n                     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd\"\n       default-autowire=\"byName\">\n    <import resource=\"classpath:spring/spring-config.xml\"/>\n    <import resource=\"classpath:spring/spring-mybatis.xml\"/>\n    <import resource=\"classpath:spring/spring-service.xml\"/>\n    <import resource=\"classpath:spring/spring-data.xml\"/>\n    <import resource=\"classpath:spring/spring-manage.xml\"/>\n    <import resource=\"classpath:spring/spring-mvc.xml\"/>\n    <import resource=\"classpath:spring/spring-jmx.xml\"/>\n    <import resource=\"classpath:spring/spring-alert.xml\"/>\n    <import resource=\"classpath:spring/spring-client-report.xml\"/>\n    <import resource=\"classpath:spring/spring-inspector.xml\"/>\n\n</beans>"
  },
  {
    "path": "open-monitor-center/cachecloud/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\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\n    <modelVersion>4.0.0</modelVersion>\n    <groupId>com.sohu.tv</groupId>\n    <artifactId>open-cachecloud</artifactId>\n    <name>open-cachecloud</name>\n    <packaging>pom</packaging>\n    <version>1.0-SNAPSHOT</version>\n    <modules>\n        <module>cachecloud-open-web</module>\n        <module>cachecloud-open-client</module>\n        <module>cachecloud-open-common</module>\n    </modules>\n\n    <properties>\n        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n        <spring.version>4.2.4.RELEASE</spring.version>\n        <quartz.version>2.2.1</quartz.version>\n        <logback.version>1.1.1</logback.version>\n        <mysql.java.version>5.1.29</mysql.java.version>\n        <junit.version>4.11</junit.version>\n        <servlet.api.version>3.1</servlet.api.version>\n        <jetty.version>9.2.3.v20140905</jetty.version>\n        <mybatis.spring.version>1.2.3</mybatis.spring.version>\n        <mybatis.version>3.2.8</mybatis.version>\n        <jedis.version>2.8.0</jedis.version>\n        <jackson.version>2.3.2</jackson.version>\n        <httpcoponents.version>4.3.2</httpcoponents.version>\n        <apache.commons.collections>4.0</apache.commons.collections>\n        <maven.compiler.plugin>3.1</maven.compiler.plugin>\n        <maven.compiler.target>1.7</maven.compiler.target>\n        <maven.war.plugin>2.4</maven.war.plugin>\n        <maven.surefire.plugin>2.16</maven.surefire.plugin>\n        <maven.clean.plugin>2.5</maven.clean.plugin>\n        <ganymed.ssh.version>build210</ganymed.ssh.version>\n        <commons.collections.version>3.2.1</commons.collections.version>\n        <guava.version>15.0</guava.version>\n        <commons-lang.version>2.3</commons-lang.version>\n        <json-lib.version>2.2.1</json-lib.version>\n        <slf4j.version>1.7.6</slf4j.version>\n        <commons.configuration.version>1.6</commons.configuration.version>\n        <velocity.version>1.7</velocity.version>\n        <velocity-tool.version>2.0</velocity-tool.version>\n        <velocity-tools-generic.version>2.1.0-SNAPSHOT</velocity-tools-generic.version>\n        <fastjson.version>1.2.28</fastjson.version>\n        <maven.deloy.plugin>2.8.1</maven.deloy.plugin>\n        <maven-source-plugin>2.2.1</maven-source-plugin>\n        <maven-resources-plugin>2.6</maven-resources-plugin>\n    </properties>\n\n    <dependencyManagement>\n        <dependencies>\n            <dependency>\n                <groupId>org.quartz-scheduler</groupId>\n                <artifactId>quartz</artifactId>\n                <version>${quartz.version}</version>\n                <exclusions>\n                    <exclusion>\n                        <artifactId>slf4j-api</artifactId>\n                        <groupId>org.slf4j</groupId>\n                    </exclusion>\n                </exclusions>\n            </dependency>\n\n            <dependency>\n                <groupId>ch.qos.logback</groupId>\n                <artifactId>logback-classic</artifactId>\n                <version>${logback.version}</version>\n                <scope>compile</scope>\n            </dependency>\n\n            <dependency>\n                <groupId>mysql</groupId>\n                <artifactId>mysql-connector-java</artifactId>\n                <version>${mysql.java.version}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>junit</groupId>\n                <artifactId>junit</artifactId>\n                <version>${junit.version}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>javax.servlet</groupId>\n                <artifactId>javax.servlet-api</artifactId>\n                <version>3.1.0</version>\n            </dependency>\n\n            <dependency>\n                <groupId>org.mybatis</groupId>\n                <artifactId>mybatis-spring</artifactId>\n                <version>${mybatis.spring.version}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>org.mybatis</groupId>\n                <artifactId>mybatis</artifactId>\n                <version>${mybatis.version}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>org.springframework</groupId>\n                <artifactId>spring-context-support</artifactId>\n                <version>${spring.version}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>org.mybatis.spring.boot</groupId>\n                <artifactId>mybatis-spring-boot-starter</artifactId>\n                <version>${mybatis-spring-boot.version}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>redis.clients</groupId>\n                <artifactId>jedis</artifactId>\n                <version>${jedis.version}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>com.fasterxml.jackson.core</groupId>\n                <artifactId>jackson-databind</artifactId>\n                <version>${jackson.version}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>org.apache.httpcomponents</groupId>\n                <artifactId>httpclient</artifactId>\n                <version>${httpcoponents.version}</version>\n            </dependency>\n\n            <!-- SSH远程 -->\n            <dependency>\n                <groupId>ch.ethz.ganymed</groupId>\n                <artifactId>ganymed-ssh2</artifactId>\n                <version>${ganymed.ssh.version}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>org.apache.commons</groupId>\n                <artifactId>commons-collections4</artifactId>\n                <version>${apache.commons.collections}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>com.google.guava</groupId>\n                <artifactId>guava</artifactId>\n                <version>${guava.version}</version>\n            </dependency>\n            \n            <dependency>\n\t\t\t\t<groupId>commons-lang</groupId>\n\t\t\t\t<artifactId>commons-lang</artifactId>\n\t\t\t\t<version>${commons-lang.version}</version>\n\t\t\t</dependency>\n\t\t\t\n\t\t\t<dependency>\n\t\t\t\t<groupId>net.sf.json-lib</groupId>\n\t\t\t\t<artifactId>json-lib</artifactId>\n\t\t\t\t<version>${json-lib.version}</version>\n\t\t\t</dependency>\n\n            <dependency>\n                <groupId>org.slf4j</groupId>\n                <artifactId>slf4j-api</artifactId>\n                <version>${slf4j.version}</version>\n                <scope>compile</scope>\n            </dependency>\n            <dependency>\n                <groupId>commons-configuration</groupId>\n                <artifactId>commons-configuration</artifactId>\n                <version>${commons.configuration.version}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>org.apache.velocity</groupId>\n                <artifactId>velocity</artifactId>\n                <version>${velocity.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>org.apache.velocity</groupId>\n                <artifactId>velocity-tools</artifactId>\n                <version>${velocity-tool.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>org.apache.velocity</groupId>\n                <artifactId>velocity-tools-generic</artifactId>\n                <version>${velocity-tools-generic.version}</version>\n            </dependency>\n\n            <dependency>\n\t\t\t  <groupId>com.alibaba</groupId>\n\t\t\t  <artifactId>fastjson</artifactId>\n\t\t\t  <version>${fastjson.version}</version>\n\t\t\t</dependency>\n            \n        </dependencies>\n    </dependencyManagement>\n\n    <developers>\n\n        <developer>\n            <name>yijunzhang</name>\n            <email>yijunzhang@sohu-inc.com</email>\n            <organization>sohu-tv</organization>\n            <roles>\n                <role>developer</role>\n            </roles>\n        </developer>\n\n        <developer>\n            <name>leifu</name>\n            <email>leifu@sohu-inc.com</email>\n            <organization>sohu-tv</organization>\n            <roles>\n                <role>developer</role>\n            </roles>\n        </developer>\n\n        <developer>\n            <name>lingguo</name>\n            <email>lingguo@sohu-inc.com</email>\n            <organization>sohu-tv</organization>\n            <roles>\n                <role>developer</role>\n            </roles>\n        </developer>\n    </developers>\n\n    <build>\n        <pluginManagement>\n            <plugins>\n                <plugin>\n                    <groupId>org.eclipse.jetty</groupId>\n                    <artifactId>jetty-maven-plugin</artifactId>\n                    <configuration>\n                        <webAppConfig>\n                            <allowDuplicateFragmentNames>true</allowDuplicateFragmentNames>\n                        </webAppConfig>\n                        <httpConnector>\n                            <port>8585</port>\n                        </httpConnector>\n                    </configuration>\n                    <version>${jetty.version}</version>\n                </plugin>\n\n                <plugin>\n                    <groupId>org.apache.maven.plugins</groupId>\n                    <artifactId>maven-compiler-plugin</artifactId>\n                    <version>${maven.compiler.plugin}</version>\n                    <configuration>\n                        <source>${maven.compiler.target}</source>\n                        <target>${maven.compiler.target}</target>\n                    </configuration>\n                </plugin>\n\n                <plugin>\n                    <groupId>org.apache.maven.plugins</groupId>\n                    <artifactId>maven-surefire-plugin</artifactId>\n                    <version>${maven.surefire.plugin}</version>\n                    <configuration>\n                        <skipTests>true</skipTests>\n                    </configuration>\n                </plugin>\n\n                <plugin>\n                    <artifactId>maven-clean-plugin</artifactId>\n                    <version>${maven.clean.plugin}</version>\n                    <configuration>\n                        <filesets>\n                            <fileset>\n                                <directory>${basedir}/src/main/webapp/WEB-INF/classes</directory>\n                            </fileset>\n                            <fileset>\n                                <directory>${basedir}/src/main/webapp/WEB-INF/lib</directory>\n                            </fileset>\n                        </filesets>\n                    </configuration>\n                </plugin>\n                \n                <plugin>\n\t            \t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t\t<artifactId>maven-deploy-plugin</artifactId>\n\t\t\t\t\t<version>${maven.deloy.plugin}</version>\n\t\t\t\t</plugin>\n\t\t\t\t\n\t\t\t\t<plugin>\n\t\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t\t<artifactId>maven-source-plugin</artifactId>\n\t\t\t\t\t<version>${maven-source-plugin}</version>\n\t\t\t\t\t<configuration>\n\t\t\t\t\t\t<attach>true</attach>\n\t\t\t\t\t</configuration>\n\t\t\t\t\t<executions>\n\t\t\t\t\t\t<execution>\n\t\t\t\t\t\t\t<phase>compile</phase>\n\t\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t\t<goal>jar</goal>\n\t\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t</execution>\n\t\t\t\t\t</executions>\n\t\t\t\t</plugin>\n\t\t\t\t\n\t\t\t\t<plugin>\n\t                <groupId>org.apache.maven.plugins</groupId>\n\t                <artifactId>maven-resources-plugin</artifactId>\n\t                <version>${maven-resources-plugin}</version>\n\t                <configuration>\n\t                    <encoding>UTF-8</encoding>\n\t                </configuration>\n\t            </plugin>\n                \n            </plugins>\n        </pluginManagement>\n    </build>\n    \n\t<repositories>\n\t<repository>\n\t\t<id>central</id>\n\t\t<url>http://repo1.maven.org/maven2</url>\n\t\t<snapshots>\n\t\t\t<enabled>false</enabled>\n\t\t</snapshots>\n\t</repository>\n\n\t<repository>\n\t\t<id>com.springsource.repository.maven.release</id>\n\t\t<url>http://repo.springsource.org/release/</url>\n\t\t<snapshots>\n\t\t\t<enabled>false</enabled>\n\t\t</snapshots>\n\t</repository>\n\t<repository>\n\t\t<id>nexus</id>\n\t\t<name>local private nexus</name>\n\t\t<url>http://maven.oschina.net/content/groups/public/</url>\n\t\t<releases>\n\t\t\t<enabled>true</enabled>\n\t\t</releases>\n\t\t<snapshots>\n\t\t\t<enabled>false</enabled>\n\t\t</snapshots>\n\t</repository>\n\n</repositories>  \n    \n\n</project>"
  },
  {
    "path": "open-monitor-center/cachecloud/script/cachecloud-init.sh",
    "content": "#!/bin/bash\n\n############################################################################\n# @desc: \n#\t- 1. create user;\n#\t- 2. create default directories and authorize;\n#\t- 3. @usage: sh cachecloud-init.sh [username]\n# @author: leifu\n# @time: \n###########################################################################\n\nset -o nounset\nset -o errexit\n\nreadonly redisDir=\"/opt/cachecloud/redis\"\nreadonly redisTarGz=\"redis-3.0.7.tar.gz\"\n\n\n# check if the user exists\ncheckExist() {\n\tlocal num=`cat /etc/passwd | grep -w $1 | wc -l`\n\t\t \n\t#cat /etc/passwd | grep -q \"$1\"\n\tif [[ $num == 1 ]]; then\n\t\techo \"user $1 exists, overwrite user and *init all data*: [y/n]?\"\n\t\tread replace\n\t\tif [[ ${replace} == \"y\" ]]; then\n\t\t\techo \"delete existed user: $1.\"\n\t\t\tuserdel -r \"$1\"\n\t\t\tcreateUser \"$1\"\n\t\t\tinit \"$1\"\n\t\t\treturn 0\n\t\tfi\n\telse\n\t\tcreateUser \"$1\"\n\t\tinit \"$1\"\n\tfi\n\treturn 0\n}\n\n\n# create the user\ncreateUser() {\n\t# create a user \n\tuseradd -m -d /home/$1 -s /bin/bash $1\n\n\t# give the user a password\n\tpasswd $1\n\n\t# add the user to sudoers\n\t#\techo \"$1\tALL=(ALL)   ALL\" >> /etc/sudoers\n\n\t#  Maximum number of days between password change\n\tchage -M 9999 $1\n\techo \"OK: create user: $1 done\"\n\n}\n\n# create defautl dirs and authorize\ninit() {\n\t# create working dirs and a tmp dir\n\tmkdir -p /opt/cachecloud/data\n\tmkdir -p /opt/cachecloud/conf\n\tmkdir -p /opt/cachecloud/logs\n\tmkdir -p /opt/cachecloud/redis\n\tmkdir -p /tmp/cachecloud\n\n\t# change owner\n\tchown -R $1:$1 /opt/cachecloud\n\tchown -R $1:$1 /tmp/cachecloud\n\techo \"OK: init: $1 done\"\n}\n\n\n\n# install redis \ninstallRedis() {\n\t#which redis-server\n\t#if [[ $? == 0 ]]; then\n\t#\techo \"WARN: redis is already installed, exit.\"\n\t#\treturn\n\t#fi\n\n\tyum install -y gcc\n\tmkdir -p ${redisDir} && cd ${redisDir}\n\twget http://download.redis.io/releases/${redisTarGz} && mv ${redisTarGz} redis.tar.gz && tar zxvf redis.tar.gz --strip-component=1\n\tmake && make install\n\tif [[ $? == 0 ]]; then\n\t\techo \"OK: redis is installed, exit.\"\n\t\tchown -R $1:$1 ${redisDir}\n\t\texport PATH=$PATH:${redisDir}/src\n\t\treturn\n\tfi\n\techo \"ERROR: redis is NOT installed, exit.\"\n}\n\nusername=$1\ncheckExist \"${username}\"\ninstallRedis \"${username}\"\n"
  },
  {
    "path": "open-monitor-center/cachecloud/script/cachecloud.sql",
    "content": "-- MySQL dump 10.13  Distrib 5.5.16, for Linux (x86_64)\n--\n-- Host: 10.10.19.167    Database: cache-cloud\n-- ------------------------------------------------------\n-- Server version\t5.5.34-32.0-log\n\n/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;\n/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;\n/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;\n/*!40101 SET NAMES utf8 */;\n/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;\n/*!40103 SET TIME_ZONE='+00:00' */;\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 */;\n\n--\n-- Table structure for table `QRTZ_BLOB_TRIGGERS`\n--\n\nDROP TABLE IF EXISTS `QRTZ_BLOB_TRIGGERS`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!40101 SET character_set_client = utf8 */;\nCREATE TABLE `QRTZ_BLOB_TRIGGERS` (\n  `SCHED_NAME` varchar(120) NOT NULL,\n  `TRIGGER_NAME` varchar(200) NOT NULL,\n  `TRIGGER_GROUP` varchar(200) NOT NULL,\n  `BLOB_DATA` blob,\n  PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),\n  KEY `SCHED_NAME` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Trigger 作为 Blob 类型存储(用于 Quartz 用户用 JDBC 创建他们自己定制的 Trigger 类型';\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Table structure for table `QRTZ_CALENDARS`\n--\n\nDROP TABLE IF EXISTS `QRTZ_CALENDARS`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!40101 SET character_set_client = utf8 */;\nCREATE TABLE `QRTZ_CALENDARS` (\n  `SCHED_NAME` varchar(120) NOT NULL COMMENT 'scheduler名称',\n  `CALENDAR_NAME` varchar(200) NOT NULL COMMENT 'calendar名称',\n  `CALENDAR` blob NOT NULL COMMENT 'calendar信息',\n  PRIMARY KEY (`SCHED_NAME`,`CALENDAR_NAME`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='以 Blob 类型存储 Quartz 的 Calendar 信息';\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Table structure for table `QRTZ_CRON_TRIGGERS`\n--\n\nDROP TABLE IF EXISTS `QRTZ_CRON_TRIGGERS`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!40101 SET character_set_client = utf8 */;\nCREATE TABLE `QRTZ_CRON_TRIGGERS` (\n  `SCHED_NAME` varchar(120) NOT NULL COMMENT 'scheduler名称',\n  `TRIGGER_NAME` varchar(200) NOT NULL COMMENT 'trigger名',\n  `TRIGGER_GROUP` varchar(200) NOT NULL COMMENT 'trigger组',\n  `CRON_EXPRESSION` varchar(120) NOT NULL COMMENT 'cron表达式',\n  `TIME_ZONE_ID` varchar(80) DEFAULT NULL COMMENT '时区',\n  PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储 Cron Trigger，包括 Cron 表达式和时区信息';\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Table structure for table `QRTZ_FIRED_TRIGGERS`\n--\n\nDROP TABLE IF EXISTS `QRTZ_FIRED_TRIGGERS`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!40101 SET character_set_client = utf8 */;\nCREATE TABLE `QRTZ_FIRED_TRIGGERS` (\n  `SCHED_NAME` varchar(120) NOT NULL,\n  `ENTRY_ID` varchar(95) NOT NULL,\n  `TRIGGER_NAME` varchar(200) NOT NULL,\n  `TRIGGER_GROUP` varchar(200) NOT NULL,\n  `INSTANCE_NAME` varchar(200) NOT NULL,\n  `FIRED_TIME` bigint(13) NOT NULL,\n  `SCHED_TIME` bigint(13) NOT NULL,\n  `PRIORITY` int(11) NOT NULL,\n  `STATE` varchar(16) NOT NULL,\n  `JOB_NAME` varchar(200) DEFAULT NULL,\n  `JOB_GROUP` varchar(200) DEFAULT NULL,\n  `IS_NONCONCURRENT` varchar(1) DEFAULT NULL COMMENT '是否非并行执行',\n  `REQUESTS_RECOVERY` varchar(1) DEFAULT NULL COMMENT '是否持久化',\n  PRIMARY KEY (`SCHED_NAME`,`ENTRY_ID`),\n  KEY `IDX_QRTZ_FT_TRIG_INST_NAME` (`SCHED_NAME`,`INSTANCE_NAME`),\n  KEY `IDX_QRTZ_FT_INST_JOB_REQ_RCVRY` (`SCHED_NAME`,`INSTANCE_NAME`,`REQUESTS_RECOVERY`),\n  KEY `IDX_QRTZ_FT_J_G` (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`),\n  KEY `IDX_QRTZ_FT_JG` (`SCHED_NAME`,`JOB_GROUP`),\n  KEY `IDX_QRTZ_FT_T_G` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),\n  KEY `IDX_QRTZ_FT_TG` (`SCHED_NAME`,`TRIGGER_GROUP`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储已触发的 Trigger相关的状态信息，以及关联 Job 的执行信息';\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Table structure for table `QRTZ_JOB_DETAILS`\n--\n\nDROP TABLE IF EXISTS `QRTZ_JOB_DETAILS`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!40101 SET character_set_client = utf8 */;\nCREATE TABLE `QRTZ_JOB_DETAILS` (\n  `SCHED_NAME` varchar(120) NOT NULL,\n  `JOB_NAME` varchar(200) NOT NULL,\n  `JOB_GROUP` varchar(200) NOT NULL,\n  `DESCRIPTION` varchar(250) DEFAULT NULL,\n  `JOB_CLASS_NAME` varchar(250) NOT NULL,\n  `IS_DURABLE` varchar(1) NOT NULL COMMENT '是否持久化，0不持久化，1持久化',\n  `IS_NONCONCURRENT` varchar(1) NOT NULL COMMENT '是否非并发，0非并发，1并发',\n  `IS_UPDATE_DATA` varchar(1) NOT NULL,\n  `REQUESTS_RECOVERY` varchar(1) NOT NULL COMMENT '是否可恢复，0不恢复，1恢复',\n  `JOB_DATA` blob,\n  PRIMARY KEY (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`),\n  KEY `IDX_QRTZ_J_REQ_RECOVERY` (`SCHED_NAME`,`REQUESTS_RECOVERY`),\n  KEY `IDX_QRTZ_J_GRP` (`SCHED_NAME`,`JOB_GROUP`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储每一个已配置的 Job 的详细信息';\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Table structure for table `QRTZ_LOCKS`\n--\n\nDROP TABLE IF EXISTS `QRTZ_LOCKS`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!40101 SET character_set_client = utf8 */;\nCREATE TABLE `QRTZ_LOCKS` (\n  `SCHED_NAME` varchar(120) NOT NULL,\n  `LOCK_NAME` varchar(40) NOT NULL,\n  PRIMARY KEY (`SCHED_NAME`,`LOCK_NAME`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储程序的悲观锁的信息(假如使用了悲观锁)';\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Table structure for table `QRTZ_PAUSED_TRIGGER_GRPS`\n--\n\nDROP TABLE IF EXISTS `QRTZ_PAUSED_TRIGGER_GRPS`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!40101 SET character_set_client = utf8 */;\nCREATE TABLE `QRTZ_PAUSED_TRIGGER_GRPS` (\n  `SCHED_NAME` varchar(120) NOT NULL,\n  `TRIGGER_GROUP` varchar(200) NOT NULL,\n  PRIMARY KEY (`SCHED_NAME`,`TRIGGER_GROUP`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储已暂停的 Trigger 组的信息';\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Table structure for table `QRTZ_SCHEDULER_STATE`\n--\n\nDROP TABLE IF EXISTS `QRTZ_SCHEDULER_STATE`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!40101 SET character_set_client = utf8 */;\nCREATE TABLE `QRTZ_SCHEDULER_STATE` (\n  `SCHED_NAME` varchar(120) NOT NULL,\n  `INSTANCE_NAME` varchar(200) NOT NULL COMMENT '执行quartz实例的主机名',\n  `LAST_CHECKIN_TIME` bigint(13) NOT NULL COMMENT '实例将状态报告给集群中的其它实例的上一次时间',\n  `CHECKIN_INTERVAL` bigint(13) NOT NULL COMMENT '实例间状态报告的时间频率',\n  PRIMARY KEY (`SCHED_NAME`,`INSTANCE_NAME`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储少量的有关 Scheduler 的状态信息';\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Table structure for table `QRTZ_SIMPLE_TRIGGERS`\n--\n\nDROP TABLE IF EXISTS `QRTZ_SIMPLE_TRIGGERS`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!40101 SET character_set_client = utf8 */;\nCREATE TABLE `QRTZ_SIMPLE_TRIGGERS` (\n  `SCHED_NAME` varchar(120) NOT NULL,\n  `TRIGGER_NAME` varchar(200) NOT NULL,\n  `TRIGGER_GROUP` varchar(200) NOT NULL,\n  `REPEAT_COUNT` bigint(7) NOT NULL COMMENT '重复次数',\n  `REPEAT_INTERVAL` bigint(12) NOT NULL COMMENT '重复间隔',\n  `TIMES_TRIGGERED` bigint(10) NOT NULL COMMENT '已出发次数',\n  PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储简单的 Trigger，包括重复次数，间隔，以及已触的次数';\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Table structure for table `QRTZ_SIMPROP_TRIGGERS`\n--\n\nDROP TABLE IF EXISTS `QRTZ_SIMPROP_TRIGGERS`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!40101 SET character_set_client = utf8 */;\nCREATE TABLE `QRTZ_SIMPROP_TRIGGERS` (\n  `SCHED_NAME` varchar(120) NOT NULL,\n  `TRIGGER_NAME` varchar(200) NOT NULL,\n  `TRIGGER_GROUP` varchar(200) NOT NULL,\n  `STR_PROP_1` varchar(512) DEFAULT NULL,\n  `STR_PROP_2` varchar(512) DEFAULT NULL,\n  `STR_PROP_3` varchar(512) DEFAULT NULL,\n  `INT_PROP_1` int(11) DEFAULT NULL,\n  `INT_PROP_2` int(11) DEFAULT NULL,\n  `LONG_PROP_1` bigint(20) DEFAULT NULL,\n  `LONG_PROP_2` bigint(20) DEFAULT NULL,\n  `DEC_PROP_1` decimal(13,4) DEFAULT NULL,\n  `DEC_PROP_2` decimal(13,4) DEFAULT NULL,\n  `BOOL_PROP_1` varchar(1) DEFAULT NULL,\n  `BOOL_PROP_2` varchar(1) DEFAULT NULL,\n  PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Table structure for table `QRTZ_TRIGGERS`\n--\n\nDROP TABLE IF EXISTS `QRTZ_TRIGGERS`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!40101 SET character_set_client = utf8 */;\nCREATE TABLE `QRTZ_TRIGGERS` (\n  `SCHED_NAME` varchar(120) NOT NULL,\n  `TRIGGER_NAME` varchar(200) NOT NULL,\n  `TRIGGER_GROUP` varchar(200) NOT NULL,\n  `JOB_NAME` varchar(200) NOT NULL,\n  `JOB_GROUP` varchar(200) NOT NULL,\n  `DESCRIPTION` varchar(250) DEFAULT NULL,\n  `NEXT_FIRE_TIME` bigint(13) DEFAULT NULL,\n  `PREV_FIRE_TIME` bigint(13) DEFAULT NULL,\n  `PRIORITY` int(11) DEFAULT NULL,\n  `TRIGGER_STATE` varchar(16) NOT NULL,\n  `TRIGGER_TYPE` varchar(8) NOT NULL,\n  `START_TIME` bigint(13) NOT NULL,\n  `END_TIME` bigint(13) DEFAULT NULL,\n  `CALENDAR_NAME` varchar(200) DEFAULT NULL,\n  `MISFIRE_INSTR` smallint(2) DEFAULT NULL,\n  `JOB_DATA` blob,\n  PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),\n  KEY `IDX_QRTZ_T_J` (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`),\n  KEY `IDX_QRTZ_T_JG` (`SCHED_NAME`,`JOB_GROUP`),\n  KEY `IDX_QRTZ_T_C` (`SCHED_NAME`,`CALENDAR_NAME`),\n  KEY `IDX_QRTZ_T_G` (`SCHED_NAME`,`TRIGGER_GROUP`),\n  KEY `IDX_QRTZ_T_STATE` (`SCHED_NAME`,`TRIGGER_STATE`),\n  KEY `IDX_QRTZ_T_N_STATE` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`,`TRIGGER_STATE`),\n  KEY `IDX_QRTZ_T_N_G_STATE` (`SCHED_NAME`,`TRIGGER_GROUP`,`TRIGGER_STATE`),\n  KEY `IDX_QRTZ_T_NEXT_FIRE_TIME` (`SCHED_NAME`,`NEXT_FIRE_TIME`),\n  KEY `IDX_QRTZ_T_NFT_ST` (`SCHED_NAME`,`TRIGGER_STATE`,`NEXT_FIRE_TIME`),\n  KEY `IDX_QRTZ_T_NFT_MISFIRE` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`),\n  KEY `IDX_QRTZ_T_NFT_ST_MISFIRE` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`,`TRIGGER_STATE`),\n  KEY `IDX_QRTZ_T_NFT_ST_MISFIRE_GRP` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`,`TRIGGER_GROUP`,`TRIGGER_STATE`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储已配置的 Trigger 的信息';\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Table structure for table `app_audit`\n--\n\nDROP TABLE IF EXISTS `app_audit`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!40101 SET character_set_client = utf8 */;\nCREATE TABLE `app_audit` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT,\n  `app_id` bigint(20) NOT NULL COMMENT '应用id',\n  `user_id` bigint(20) NOT NULL COMMENT '申请人的id',\n  `user_name` varchar(64) NOT NULL COMMENT '用户名',\n  `type` tinyint(4) NOT NULL COMMENT '申请类型:0:申请应用,1:应用扩容,2:修改配置',\n  `param1` varchar(600) DEFAULT NULL COMMENT '预留参数1',\n  `param2` varchar(600) DEFAULT NULL COMMENT '预留参数2',\n  `param3` varchar(600) DEFAULT NULL COMMENT '预留参数3',\n  `info` varchar(360) NOT NULL COMMENT '申请描述',\n  `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '0:等待审批; 1:审批通过; -1:驳回',\n  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,\n  `modify_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n  `refuse_reason` varchar(360) DEFAULT NULL COMMENT '驳回理由',\n  PRIMARY KEY (`id`),\n  KEY `idx_appid` (`app_id`),\n  KEY `idx_create_time` (`create_time`),\n  KEY `idx_status_create_time` (`status`,`create_time`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='应用审核表';\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Table structure for table `app_audit_log`\n--\n\nDROP TABLE IF EXISTS `app_audit_log`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!40101 SET character_set_client = utf8 */;\nCREATE TABLE `app_audit_log` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT,\n  `app_id` bigint(20) NOT NULL COMMENT '应用id',\n  `user_id` bigint(20) NOT NULL COMMENT '审批操作人id',\n  `info` longtext NOT NULL COMMENT 'app审批的详细信息',\n  `type` tinyint(4) NOT NULL,\n  `create_time` datetime NOT NULL,\n  `app_audit_id` bigint(20) NOT NULL COMMENT '审批id',\n  PRIMARY KEY (`id`),\n  KEY `idx_audit_appid` (`app_id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='app审核日志表';\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Table structure for table `app_client_costtime_minute_stat`\n--\n\nDROP TABLE IF EXISTS `app_client_costtime_minute_stat`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!40101 SET character_set_client = utf8 */;\nCREATE TABLE `app_client_costtime_minute_stat` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\n  `app_id` bigint(20) NOT NULL COMMENT '应用id',\n  `collect_time` bigint(20) NOT NULL COMMENT '统计时间:格式yyyyMMddHHmm00',\n  `client_ip` varchar(20) NOT NULL COMMENT '客户端ip',\n  `report_time` datetime NOT NULL COMMENT '客户端上报时间',\n  `create_time` datetime NOT NULL COMMENT '创建时间',\n  `command` varchar(20) NOT NULL COMMENT '命令',\n  `mean` double NOT NULL COMMENT '耗时平均值',\n  `median` int(11) NOT NULL COMMENT '耗时中值',\n  `ninety_percent_max` int(11) NOT NULL COMMENT '耗时90%最大值',\n  `ninety_nine_percent_max` int(11) NOT NULL COMMENT '耗时99%最大值',\n  `hundred_max` int(11) NOT NULL COMMENT '耗时最大值',\n  `count` int(11) NOT NULL COMMENT '调用次数',\n  `instance_host` varchar(20) DEFAULT NULL COMMENT '客户端上报实例ip',\n  `instance_port` int(11) DEFAULT NULL COMMENT '客户端上报实例port',\n  `instance_id` bigint(20) DEFAULT NULL COMMENT '实例id',\n  PRIMARY KEY (`id`),\n  KEY `idx_appid_collecttime` (`app_id`,`collect_time`),\n  KEY `idx_collect_time` (`collect_time`),\n  KEY `idx_group` (`app_id`,`instance_id`,`client_ip`,`collect_time`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客户端每分钟耗时上报数据统计';\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Table structure for table `app_client_costtime_minute_stat_total`\n--\n\nDROP TABLE IF EXISTS `app_client_costtime_minute_stat_total`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!40101 SET character_set_client = utf8 */;\nCREATE TABLE `app_client_costtime_minute_stat_total` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\n  `app_id` bigint(20) NOT NULL COMMENT '应用id',\n  `collect_time` bigint(20) NOT NULL COMMENT '统计时间:格式yyyyMMddHHmm00',\n  `create_time` datetime NOT NULL COMMENT '创建时间',\n  `command` varchar(20) NOT NULL COMMENT '命令',\n  `mean` double NOT NULL COMMENT '耗时平均值',\n  `median` int(11) NOT NULL COMMENT '耗时中值',\n  `ninety_percent_max` int(11) NOT NULL COMMENT '耗时90%最大值',\n  `ninety_nine_percent_max` int(11) NOT NULL COMMENT '耗时99%最大值',\n  `hundred_max` int(11) NOT NULL COMMENT '耗时最大值',\n  `total_cost` double NOT NULL COMMENT '总耗时',\n  `total_count` int(11) NOT NULL COMMENT '调用次数',\n  `max_instance_host` varchar(20) DEFAULT NULL COMMENT '客户端上报最大耗时对应的实例ip',\n  `max_instance_port` int(11) DEFAULT NULL COMMENT '客户端上报最大耗时对应的实例port',\n  `max_instance_id` bigint(20) DEFAULT NULL COMMENT '最大耗时对应的实例id',\n  `max_client_ip` varchar(20) NOT NULL COMMENT '最大耗时对应的客户端ip',\n  `accumulation` int(10) NOT NULL DEFAULT '0' COMMENT '参与累加实例数和客户端数',\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `app_id` (`app_id`,`command`,`collect_time`),\n  KEY `idx_appid_collecttime` (`app_id`,`collect_time`),\n  KEY `idx_collect_time` (`collect_time`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='应用全局耗时统计';\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Table structure for table `app_client_datasize_minute_stat`\n--\n\nDROP TABLE IF EXISTS `app_client_datasize_minute_stat`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!40101 SET character_set_client = utf8 */;\nCREATE TABLE `app_client_datasize_minute_stat` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\n  `collect_time` bigint(20) NOT NULL COMMENT '统计时间:格式yyyyMMddHHmm00',\n  `client_ip` varchar(20) NOT NULL COMMENT '客户端ip',\n  `report_time` datetime NOT NULL COMMENT '客户端上报时间',\n  `create_time` datetime NOT NULL COMMENT '创建时间',\n  `cost_map_size` varchar(20) NOT NULL COMMENT '耗时map尺寸',\n  `value_map_size` double NOT NULL COMMENT '值map尺寸',\n  `exception_map_size` int(11) NOT NULL COMMENT '异常map尺寸',\n  `collect_map_size` int(11) NOT NULL COMMENT '耗时map尺寸',\n  PRIMARY KEY (`id`),\n  KEY `idx_client_ip` (`client_ip`),\n  KEY `idx_collect_time_client_ip` (`collect_time`,`client_ip`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客户端每分钟耗时上报收集数据的map尺寸';\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Table structure for table `app_client_exception_minute_stat`\n--\n\nDROP TABLE IF EXISTS `app_client_exception_minute_stat`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!40101 SET character_set_client = utf8 */;\nCREATE TABLE `app_client_exception_minute_stat` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\n  `app_id` bigint(20) NOT NULL COMMENT '应用id',\n  `collect_time` bigint(20) NOT NULL COMMENT '统计时间:格式yyyyMMddHHmm00',\n  `client_ip` varchar(20) NOT NULL COMMENT '客户端ip',\n  `report_time` datetime NOT NULL COMMENT '客户端上报时间',\n  `create_time` datetime NOT NULL COMMENT '创建时间',\n  `exception_class` varchar(255) NOT NULL COMMENT '异常类',\n  `exception_count` varchar(255) NOT NULL COMMENT '异常个数',\n  `instance_host` varchar(20) DEFAULT NULL COMMENT '实例ip',\n  `instance_port` int(11) DEFAULT NULL COMMENT '实例port',\n  `instance_id` bigint(20) DEFAULT NULL COMMENT '实例id',\n  `type` tinyint(4) DEFAULT '1' COMMENT '异常类型:1是jedis异常,2是客户端异常',\n  PRIMARY KEY (`id`),\n  KEY `idx_appid_collecttime` (`app_id`,`collect_time`),\n  KEY `idx_collect_time` (`collect_time`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客户端每分钟异常上报数据统计';\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Table structure for table `app_client_value_distri_minute_stat`\n--\n\nDROP TABLE IF EXISTS `app_client_value_distri_minute_stat`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!40101 SET character_set_client = utf8 */;\nCREATE TABLE `app_client_value_distri_minute_stat` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\n  `app_id` bigint(20) NOT NULL COMMENT '应用id',\n  `collect_time` bigint(20) NOT NULL COMMENT '统计时间:格式yyyyMMddHHmm00',\n  `client_ip` varchar(20) NOT NULL COMMENT '客户端ip',\n  `report_time` datetime NOT NULL COMMENT '客户端上报时间',\n  `create_time` datetime NOT NULL COMMENT '创建时间',\n  `command` varchar(20) NOT NULL COMMENT '命令',\n  `distribute_value` varchar(20) NOT NULL COMMENT '值分布',\n  `distribute_type` tinyint(4) NOT NULL COMMENT '值分布类型',\n  `count` int(11) NOT NULL COMMENT '调用次数',\n  `instance_host` varchar(20) DEFAULT NULL COMMENT '实例ip',\n  `instance_port` int(11) DEFAULT NULL COMMENT '实例port',\n  `instance_id` bigint(20) DEFAULT NULL COMMENT '实例id',\n  PRIMARY KEY (`id`),\n  KEY `idx_appid_collecttime` (`app_id`,`collect_time`),\n  KEY `idx_collect_time` (`collect_time`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客户端每分钟值分布上报数据统计';\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Table structure for table `app_client_version_statistic`\n--\n\nDROP TABLE IF EXISTS `app_client_version_statistic`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!40101 SET character_set_client = utf8 */;\nCREATE TABLE `app_client_version_statistic` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT,\n  `app_id` bigint(20) NOT NULL COMMENT '应用id',\n  `client_ip` varchar(20) NOT NULL COMMENT '客户端ip地址',\n  `client_version` varchar(20) NOT NULL COMMENT '客户端版本',\n  `report_time` datetime DEFAULT NULL COMMENT '上报时间',\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `app_client_ip` (`app_id`,`client_ip`),\n  KEY `app_id` (`app_id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客户端上报版本信息统计';\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Table structure for table `app_desc`\n--\n\nDROP TABLE IF EXISTS `app_desc`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!40101 SET character_set_client = utf8 */;\nCREATE TABLE `app_desc` (\n  `app_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '应用id',\n  `name` varchar(36) NOT NULL COMMENT '应用名',\n  `user_id` bigint(20) NOT NULL COMMENT '申请人id',\n  `status` tinyint(4) NOT NULL COMMENT '应用状态, 0未分配，1申请未审批，2审批并发布 3:应用下线,4:驳回',\n  `intro` varchar(255) NOT NULL COMMENT '应用描述',\n  `create_time` datetime NOT NULL COMMENT '创建时间',\n  `passed_time` datetime NOT NULL COMMENT '审批通过时间',\n  `type` int(10) NOT NULL DEFAULT '0' COMMENT 'cache类型，2. redis-cluster,5. redis-sentinel ,6.redis-standalone ',\n  `officer` varchar(20) NOT NULL COMMENT '负责人，中文',\n  `ver_id` int(11) NOT NULL COMMENT '版本',\n  `is_test` tinyint(4) DEFAULT '0' COMMENT '是否测试：1是0否',\n  `need_persistence` tinyint(4) DEFAULT '1' COMMENT '是否需要持久化: 1是0否',\n  `need_hot_back_up` tinyint(4) DEFAULT '1' COMMENT '是否需要热备: 1是0否',\n  `has_back_store` tinyint(4) DEFAULT '1' COMMENT '是否有后端数据源: 1是0否',\n  `forecase_qps` int(11) DEFAULT NULL COMMENT '预估qps',\n  `forecast_obj_num` int(11) DEFAULT NULL COMMENT '预估条目数',\n  `mem_alert_value` int(11) DEFAULT NULL COMMENT '内存报警阀值',\n  `client_machine_room` varchar(36) DEFAULT NULL COMMENT '客户端机房信息',\n  PRIMARY KEY (`app_id`),\n  UNIQUE KEY `uidx_app_name` (`name`),\n  UNIQUE KEY `idx_app_uid` (`app_id`)\n) ENGINE=InnoDB AUTO_INCREMENT=10000 DEFAULT CHARSET=utf8 COMMENT='app应用描述';\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Table structure for table `app_hour_command_statistics`\n--\n\nDROP TABLE IF EXISTS `app_hour_command_statistics`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!40101 SET character_set_client = utf8 */;\nCREATE TABLE `app_hour_command_statistics` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\n  `app_id` bigint(20) NOT NULL COMMENT '应用id',\n  `collect_time` bigint(20) NOT NULL COMMENT '统计时间:格式yyyyMMddHH',\n  `command_name` varchar(60) NOT NULL COMMENT '命令名称',\n  `command_count` bigint(20) NOT NULL COMMENT '命令执行次数',\n  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `modify_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '修改时间',\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `app_id` (`app_id`,`command_name`,`collect_time`),\n  KEY `idx_create_time` (`create_time`),\n  KEY `idx_modify_time` (`modify_time`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='应用的每小时命令统计';\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Table structure for table `app_hour_statistics`\n--\n\nDROP TABLE IF EXISTS `app_hour_statistics`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!40101 SET character_set_client = utf8 */;\nCREATE TABLE `app_hour_statistics` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\n  `app_id` bigint(20) NOT NULL COMMENT '应用id',\n  `collect_time` bigint(20) NOT NULL COMMENT '收集时间:格式yyyyMMddHH',\n  `hits` bigint(20) NOT NULL COMMENT '每小时命中数量和',\n  `misses` bigint(20) NOT NULL COMMENT '每小时未命中数量和',\n  `command_count` bigint(20) DEFAULT '0' COMMENT '命令总数',\n  `used_memory` bigint(20) NOT NULL COMMENT '每小时内存占用最大值',\n  `expired_keys` bigint(20) NOT NULL COMMENT '每小时过期key数量和',\n  `evicted_keys` bigint(20) NOT NULL COMMENT '每小时驱逐key数量和',\n  `net_input_byte` bigint(20) DEFAULT '0' COMMENT '网络输入字节',\n  `net_output_byte` bigint(20) DEFAULT '0' COMMENT '网络输出字节',\n  `connected_clients` int(10) NOT NULL COMMENT '每小时客户端连接数最大值',\n  `object_size` bigint(20) NOT NULL COMMENT '每小时存储对象数最大值',\n  `accumulation` int(10) NOT NULL DEFAULT '0' COMMENT '每小时参与累加实例数最小值',\n  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `modify_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '每小时修改时间最大值',\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `app_id` (`app_id`,`collect_time`),\n  KEY `idx_create_time` (`create_time`),\n  KEY `idx_modify_time` (`modify_time`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='应用统计数据每小时统计';\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Table structure for table `app_minute_command_statistics`\n--\n\nDROP TABLE IF EXISTS `app_minute_command_statistics`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!40101 SET character_set_client = utf8 */;\nCREATE TABLE `app_minute_command_statistics` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\n  `app_id` bigint(20) NOT NULL COMMENT '应用id',\n  `collect_time` bigint(20) NOT NULL COMMENT '统计时间:格式yyyyMMddHHmm',\n  `command_name` varchar(60) NOT NULL COMMENT '命令名称',\n  `command_count` bigint(20) NOT NULL COMMENT '命令执行次数',\n  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `modify_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '修改时间',\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `app_id` (`app_id`,`collect_time`,`command_name`),\n  KEY `idx_create_time` (`create_time`),\n  KEY `idx_modify_time` (`modify_time`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='应用的每分钟命令统计';\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Table structure for table `app_minute_statistics`\n--\n\nDROP TABLE IF EXISTS `app_minute_statistics`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!40101 SET character_set_client = utf8 */;\nCREATE TABLE `app_minute_statistics` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\n  `app_id` bigint(20) NOT NULL COMMENT '应用id',\n  `collect_time` bigint(20) NOT NULL COMMENT '收集时间:格式yyyyMMddHHmm',\n  `hits` bigint(20) NOT NULL COMMENT '命中数量',\n  `misses` bigint(20) NOT NULL COMMENT '未命中数量',\n  `command_count` bigint(20) DEFAULT '0' COMMENT '命令总数',\n  `used_memory` bigint(20) NOT NULL COMMENT '内存占用',\n  `expired_keys` bigint(20) NOT NULL COMMENT '过期key数量',\n  `evicted_keys` bigint(20) NOT NULL COMMENT '驱逐key数量',\n  `net_input_byte` bigint(20) DEFAULT '0' COMMENT '网络输入字节',\n  `net_output_byte` bigint(20) DEFAULT '0' COMMENT '网络输出字节',\n  `connected_clients` int(10) NOT NULL COMMENT '客户端连接数',\n  `object_size` bigint(20) NOT NULL COMMENT '每分钟存储对象数最大值',\n  `accumulation` int(10) NOT NULL DEFAULT '0' COMMENT '参与累加实例数',\n  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `modify_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '修改时间',\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `app_id` (`app_id`,`collect_time`),\n  KEY `idx_create_time` (`create_time`),\n  KEY `idx_modify_time` (`modify_time`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Table structure for table `app_to_user`\n--\n\nDROP TABLE IF EXISTS `app_to_user`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!40101 SET character_set_client = utf8 */;\nCREATE TABLE `app_to_user` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT,\n  `user_id` bigint(20) NOT NULL COMMENT '用户id',\n  `app_id` bigint(20) NOT NULL COMMENT '应用id',\n  PRIMARY KEY (`id`),\n  KEY `app_id` (`app_id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Table structure for table `app_user`\n--\n\nDROP TABLE IF EXISTS `app_user`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!40101 SET character_set_client = utf8 */;\nCREATE TABLE `app_user` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT,\n  `name` varchar(64) NOT NULL COMMENT '用户名',\n  `ch_name` varchar(255) NOT NULL COMMENT '中文名',\n  `email` varchar(64) NOT NULL COMMENT '邮箱',\n  `mobile` varchar(16) NOT NULL COMMENT '手机',\n  `type` int(4) NOT NULL DEFAULT '2' COMMENT '0管理员，1预留，2普通用户，-1无效',\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `uidx_user_name` (`name`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户表';\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Table structure for table `instance_fault`\n--\n\nDROP TABLE IF EXISTS `instance_fault`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!40101 SET character_set_client = utf8 */;\nCREATE TABLE `instance_fault` (\n  `id` int(11) NOT NULL AUTO_INCREMENT,\n  `app_id` bigint(20) NOT NULL COMMENT '应用id',\n  `inst_id` bigint(20) NOT NULL COMMENT '实例id',\n  `ip` varchar(16) NOT NULL COMMENT 'ip地址',\n  `port` int(11) NOT NULL COMMENT '端口',\n  `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态:0:心跳停止,1:心跳恢复',\n  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `type` mediumint(4) NOT NULL COMMENT '类型：2. redis-cluster, 5. redis-sentinel 6.redis-standalone',\n  `reason` mediumtext NOT NULL COMMENT '故障原因描述',\n  PRIMARY KEY (`id`),\n  KEY `idx_ip_port` (`ip`,`port`),\n  KEY `app_id` (`app_id`),\n  KEY `inst_id` (`inst_id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例故障表';\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Table structure for table `instance_host`\n--\n\nDROP TABLE IF EXISTS `instance_host`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!40101 SET character_set_client = utf8 */;\nCREATE TABLE `instance_host` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT,\n  `ip` varchar(16) NOT NULL COMMENT '机器ip',\n  `ssh_user` varchar(32) DEFAULT NULL COMMENT 'ssh用户',\n  `ssh_pwd` varchar(32) DEFAULT NULL COMMENT 'ssh密码',\n  `warn` int(5) DEFAULT '1' COMMENT '0不报警，1报警',\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `uidx_host_ip` (`ip`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='机器表';\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Table structure for table `instance_info`\n--\n\nDROP TABLE IF EXISTS `instance_info`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!40101 SET character_set_client = utf8 */;\nCREATE TABLE `instance_info` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'instance id',\n  `parent_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '对等实例的id',\n  `app_id` bigint(20) NOT NULL COMMENT '应用id，与app_desc关联',\n  `host_id` bigint(20) NOT NULL COMMENT '对应的主机id，与instance_host关联',\n  `ip` varchar(16) NOT NULL COMMENT '实例的ip',\n  `port` int(11) NOT NULL COMMENT '实例端口',\n  `status` tinyint(4) NOT NULL COMMENT '是否启用:0:节点异常,1:正常启用,2:节点下线',\n  `mem` int(11) NOT NULL COMMENT '内存大小',\n  `conn` int(11) NOT NULL COMMENT '连接数',\n  `cmd` varchar(255) NOT NULL COMMENT '启动实例的命令/redis-sentinel的masterName',\n  `type` mediumint(11) NOT NULL COMMENT '类型：2. redis-cluster, 5. redis-sentinel 6.redis-standalone',\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `uidx_inst_ipport` (`ip`,`port`),\n  KEY `app_id` (`app_id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例信息';\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Table structure for table `instance_statistics`\n--\n\nDROP TABLE IF EXISTS `instance_statistics`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!40101 SET character_set_client = utf8 */;\nCREATE TABLE `instance_statistics` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增id',\n  `inst_id` bigint(20) NOT NULL COMMENT '实例的id',\n  `app_id` bigint(20) NOT NULL COMMENT 'app id',\n  `host_id` bigint(20) NOT NULL COMMENT '机器的id',\n  `ip` varchar(16) COLLATE utf8_bin NOT NULL COMMENT 'ip',\n  `port` int(255) NOT NULL COMMENT 'port',\n  `role` tinyint(255) NOT NULL COMMENT '主从，1主2从',\n  `max_memory` bigint(255) NOT NULL COMMENT '预分配内存，单位byte',\n  `used_memory` bigint(255) NOT NULL COMMENT '已使用内存，单位byte',\n  `curr_items` bigint(255) NOT NULL COMMENT '当前item数量',\n  `curr_connections` int(255) NOT NULL COMMENT '当前连接数',\n  `misses` bigint(255) NOT NULL COMMENT 'miss数',\n  `hits` bigint(255) NOT NULL COMMENT '命中数',\n  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,\n  `modify_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `ip` (`ip`,`port`),\n  KEY `app_id` (`app_id`),\n  KEY `machine_id` (`host_id`),\n  KEY `idx_inst_id` (`inst_id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='实例的最新统计信息';\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Table structure for table `machine_info`\n--\n\nDROP TABLE IF EXISTS `machine_info`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!40101 SET character_set_client = utf8 */;\nCREATE TABLE `machine_info` (\n  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '机器的id',\n  `ssh_user` varchar(20) COLLATE utf8_bin NOT NULL DEFAULT 'cachecloud' COMMENT 'ssh用户',\n  `ssh_passwd` varchar(20) COLLATE utf8_bin NOT NULL DEFAULT 'cachecloud' COMMENT 'ssh密码',\n  `ip` varchar(16) COLLATE utf8_bin NOT NULL COMMENT 'ip',\n  `room` varchar(20) COLLATE utf8_bin NOT NULL COMMENT '所属机房',\n  `mem` int(11) unsigned NOT NULL COMMENT '内存大小，单位G',\n  `cpu` mediumint(24) unsigned NOT NULL COMMENT 'cpu数量',\n  `virtual` tinyint(8) unsigned NOT NULL DEFAULT '1' COMMENT '是否虚拟，0表示否，1表示是',\n  `real_ip` varchar(16) COLLATE utf8_bin NOT NULL COMMENT '宿主机ip',\n  `service_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '上线时间',\n  `fault_count` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '故障次数',\n  `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',\n  `warn` tinyint(255) unsigned NOT NULL DEFAULT '1' COMMENT '是否启用报警，0不启用，1启用',\n  `available` tinyint(255) NOT NULL COMMENT '表示机器是否可用，1表示可用，0表示不可用；',\n  `groupId` int(11) NOT NULL DEFAULT '0' COMMENT '机器分组，默认为0，表示原生资源，非0表示外部提供的资源(可扩展)',\n  `type` int(11) NOT NULL DEFAULT '0' COMMENT '0原生 1 其他',\n  `extra_desc` varchar(255) COLLATE utf8_bin DEFAULT NULL COMMENT '对于机器的额外说明(例如机器安装的其他服务(web,mysql,queue等等))',\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `ip` (`ip`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='保存机器的静态信息';\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Table structure for table `machine_statistics`\n--\n\nDROP TABLE IF EXISTS `machine_statistics`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!40101 SET character_set_client = utf8 */;\nCREATE TABLE `machine_statistics` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT,\n  `host_id` bigint(20) NOT NULL COMMENT '机器id',\n  `ip` varchar(16) NOT NULL COMMENT '机器ip',\n  `cpu_usage` varchar(120) NOT NULL COMMENT 'cpu使用率',\n  `load` varchar(120) NOT NULL COMMENT '机器负载',\n  `traffic` varchar(120) NOT NULL COMMENT 'io网络流量',\n  `memory_usage_ratio` varchar(120) NOT NULL COMMENT '内存使用率',\n  `memory_free` varchar(120) NOT NULL COMMENT '内存剩余',\n  `memory_total` varchar(120) NOT NULL COMMENT '总内存量',\n  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `modify_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '修改时间',\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `uidx_ip` (`ip`),\n  KEY `host_id` (`host_id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='机器状态统计信息';\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Table structure for table `standard_statistics`\n--\n\nDROP TABLE IF EXISTS `standard_statistics`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!40101 SET character_set_client = utf8 */;\nCREATE TABLE `standard_statistics` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\n  `collect_time` bigint(20) NOT NULL COMMENT '收集时间:格式yyyyMMddHHmm',\n  `ip` varchar(16) NOT NULL COMMENT 'ip地址',\n  `port` int(11) NOT NULL COMMENT '端口/hostId',\n  `db_type` varchar(16) NOT NULL COMMENT '收集的数据类型',\n  `info_json` text NOT NULL COMMENT '收集的json数据',\n  `diff_json` text NOT NULL COMMENT '上一次收集差异的json数据',\n  `created_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `uniq_index` (`ip`,`port`,`db_type`,`collect_time`),\n  KEY `idx_create_time` (`created_time`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;\n\nCREATE TABLE `instance_slow_log` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增id',\n  `instance_id` bigint(20) NOT NULL COMMENT '实例的id',\n  `app_id` bigint(20) NOT NULL COMMENT 'app id',\n  `ip` varchar(32) NOT NULL COMMENT 'ip',\n  `port` int(11) NOT NULL COMMENT 'port',\n  `slow_log_id` bigint(20) NOT NULL COMMENT '慢查询id',\n  `cost_time` int(11) NOT NULL COMMENT '耗时(微妙)',\n  `command` varchar(255) NOT NULL COMMENT '执行命令',\n  `execute_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '执行时间点',\n  `create_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '记录创建时间',\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `slowlogkey` (`instance_id`,`slow_log_id`,`execute_time`),\n  KEY `idx_app_create_time` (`app_id`,`create_time`)\n) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='实例慢查询列表';\n\nCREATE TABLE `app_client_value_minute_stats` (\n  `app_id` bigint(20) NOT NULL COMMENT '应用id',\n  `collect_time` bigint(20) NOT NULL COMMENT '统计时间:格式yyyyMMddHHmm00',\n  `update_time` datetime NOT NULL COMMENT '创建时间',\n  `command` varchar(20) NOT NULL COMMENT '命令',\n  `distribute_type` tinyint(4) NOT NULL COMMENT '值分布类型',\n  `count` int(11) NOT NULL COMMENT '调用次数',\n  PRIMARY KEY (`app_id`,`collect_time`,`command`,`distribute_type`),\n  KEY `idx_collect_time` (`collect_time`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客户端每分钟值分布上报数据统计';\n\nCREATE TABLE `app_client_instance` (\n  `app_id` bigint(20) NOT NULL COMMENT '应用id',\n  `client_ip` varchar(20) NOT NULL COMMENT '客户端ip',\n  `instance_host` varchar(20) NOT NULL COMMENT 'redis节点ip',\n  `instance_port` int(11) NOT NULL COMMENT 'redis节点端口',\n  `instance_id` bigint(20) NOT NULL COMMENT 'redis节点id',\n  `day` date NOT NULL COMMENT '日期',\n  PRIMARY KEY (`app_id`,`day`,`client_ip`,`instance_id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='应用实例与客户端对应关系表';\n\nCREATE TABLE `system_config` (\n  `config_key` varchar(255) NOT NULL COMMENT '配置key',\n  `config_value` varchar(512) NOT NULL COMMENT '配置value',\n  `info` varchar(255) NOT NULL COMMENT '配置说明',\n  `status` tinyint NOT NULL COMMENT '1:可用,0:不可用',\n  `order_id` int NOT NULL COMMENT '顺序', \n  PRIMARY KEY (`config_key`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='系统配置';\n\n--\n-- init cachecloud data\n--\n\ninsert into system_config(config_key,config_value,info,status,order_id) values('cachecloud.machine.ssh.name','cachecloud','机器ssh用户名',1,1);\ninsert into system_config(config_key,config_value,info,status,order_id) values('cachecloud.machine.ssh.password','cachecloud','机器ssh密码',1,2);\ninsert into system_config(config_key,config_value,info,status,order_id) values('cachecloud.machine.ssh.port','22','机器ssh端口',1,3);\ninsert into system_config(config_key,config_value,info,status,order_id) values('cachecloud.admin.user.name','admin','cachecloud-admin用户名',1,4);\ninsert into system_config(config_key,config_value,info,status,order_id) values('cachecloud.admin.user.password','admin','cachelcoud-admin密码',1,5);\ninsert into system_config(config_key,config_value,info,status,order_id) values('cachecloud.superAdmin','admin,xx,yy','超级管理员组',1,6);\ninsert into system_config(config_key,config_value,info,status,order_id) values('machine.cpu.alert.ratio','80.0','机器cpu报警阀值',1,7);\ninsert into system_config(config_key,config_value,info,status,order_id) values('machine.mem.alert.ratio','80.0','机器内存报警阀值',1,8);\ninsert into system_config(config_key,config_value,info,status,order_id) values('machine.load.alert.ratio','8.0','机器负载报警阀值',1,9);\ninsert into system_config(config_key,config_value,info,status,order_id) values('cachecloud.documentUrl','http://cachecloud.github.io','文档地址',1,10);\ninsert into system_config(config_key,config_value,info,status,order_id) values('cachecloud.owner.email','xx@sohu.com,yy@qq.com','邮件报警(逗号隔开)',1,11);\ninsert into system_config(config_key,config_value,info,status,order_id) values('cachecloud.owner.phone','13812345678,13787654321','手机号报警(逗号隔开)',1,12);\ninsert into system_config(config_key,config_value,info,status,order_id) values('cachecloud.mavenWareHouse','http://your_maven_house','maven仓库地址(客户端)',1,13);\ninsert into system_config(config_key,config_value,info,status,order_id) values('cachecloud.contact','user1:(xx@zz.com, user1:135xxxxxxxx)<br/>user2: (user2@zz.com, user2:138xxxxxxxx)','值班联系人信息',1,14);\ninsert into system_config(config_key,config_value,info,status,order_id) values('cachecloud.good.client','1.0-SNAPSHOT','可用客户端版本(用逗号隔开)',1,15);\ninsert into system_config(config_key,config_value,info,status,order_id) values('cachecloud.warn.client','0.1','警告客户端版本(用逗号隔开)',1,16);\ninsert into system_config(config_key,config_value,info,status,order_id) values('cachecloud.error.client','0.0','不可用客户端版本(用逗号隔开)',1,17);\n\ninsert into system_config(config_key,config_value,info,status,order_id) values('redis.migrate.tool.home','/opt/cachecloud/redis-migrate-tool/','redis-migrate-tool安装路径',1,18);\ninsert into system_config(config_key,config_value,info,status,order_id) values('cachecloud.user.login.type','1','用户登录状态保存方式(session或cookie)',1,19);\ninsert into system_config(config_key,config_value,info,status,order_id) values('cachecloud.cookie.domain','','cookie登录方式所需要的域名',1,20);\ninsert into system_config(config_key,config_value,info,status,order_id) values('cachecloud.base.dir','/opt','cachecloud根目录，要和cachecloud-init.sh脚本中的目录一致',1,21);\ninsert into system_config(config_key,config_value,info,status,order_id) values('cachecloud.app.client.conn.threshold','2000','应用连接数报警阀值',1,22);\n\ninsert into system_config(config_key,config_value,info,status,order_id) values('cachecloud.email.alert.interface','','邮件报警接口(说明:http://cachecloud.github.io 邮件和短信报警接口规范)',1,23);\ninsert into system_config(config_key,config_value,info,status,order_id) values('cachecloud.mobile.alert.interface','','短信报警接口(说明:http://cachecloud.github.io 邮件和短信报警接口规范)',1,24);\ninsert into system_config(config_key,config_value,info,status,order_id) values('cachecloud.ldap.url','','LDAP接口地址(例如:ldap://ldap.xx.com)',1,25);\n\ninsert into system_config(config_key,config_value,info,status,order_id) values('cachecloud.whether.schedule.clean.data','false','是否定期清理统计数据',1,26);\n\ninsert into system_config(config_key,config_value,info,status,order_id) values('cachecloud.app.secret.base.key','cachecloud-2014','appkey秘钥基准key',1,27);\ninsert into system_config(config_key,config_value,info,status,order_id) values('cachecloud.machine.stats.cron.minute','1','机器性能统计周期(分钟)',1,28);\n\n\nCREATE TABLE `app_data_migrate_status` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增id',\n  `migrate_machine_ip` varchar(255) NOT NULL COMMENT '迁移工具所在机器ip',\n  `migrate_machine_port` int NOT NULL COMMENT '迁移工具所占port',\n  `source_migrate_type` tinyint(4) NOT NULL COMMENT '源迁移类型,0:single,1:redis cluster,2:rdb file,3:twemproxy',\n  `source_servers` varchar(2048) NOT NULL COMMENT '源实例列表',\n  `target_migrate_type` tinyint(4) NOT NULL COMMENT '目标迁移类型,0:single,1:redis cluster,2:rdb file,3:twemproxy',\n  `target_servers` varchar(2048) NOT NULL COMMENT '目标实例列表',\n  `source_app_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '源应用id',\n  `target_app_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '目标应用id',\n  `user_id` bigint(20) NOT NULL COMMENT '操作人',\n  `status` tinyint(4) NOT NULL COMMENT '迁移执行状态,0:开始,1:结束,2:异常',\n  `start_time` datetime NOT NULL COMMENT '迁移开始执行时间',\n  `end_time` datetime DEFAULT NULL COMMENT '迁移结束执行时间',\n  `log_path` varchar(255) NOT NULL COMMENT '日志文件路径',\n  `config_path` varchar(255) NOT NULL COMMENT '配置文件路径',\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='迁移状态';\n\ninsert into app_user(name,ch_name,email,mobile,type) values('admin','admin','admin@sohu-inc.com','13500000000',0);\n\n\nCREATE TABLE `instance_config` (\n  `id` int(11) NOT NULL AUTO_INCREMENT,\n  `config_key` varchar(128) NOT NULL COMMENT '配置名',\n  `config_value` varchar(512) NOT NULL COMMENT '配置值',\n  `info` varchar(512) NOT NULL COMMENT '配置说明',\n  `update_time` datetime NOT NULL COMMENT '更新时间',\n  `type` mediumint(9) NOT NULL COMMENT '类型：2.cluster节点特殊配置, 5:sentinel节点配置, 6:redis普通节点',\n  status tinyint not null comment '1有效,0无效',\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `config_key_type` (`config_key`,`type`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('cluster-enabled','yes','是否开启集群模式',now(),2,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('cluster-node-timeout','15000','集群节点超时时间,默认15秒',now(),2,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('cluster-slave-validity-factor','10','从节点延迟有效性判断因子,默认10秒',now(),2,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('cluster-migration-barrier','1','主从迁移至少需要的从节点数,默认1个',now(),2,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('cluster-config-file','nodes-%d.conf','集群配置文件名称,格式:nodes-{port}.conf',now(),2,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('cluster-require-full-coverage','no','节点部分失败期间,其他节点是否继续工作',now(),2,1);\n\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('port','%d','sentinel实例端口',now(),5,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('dir','%s','工作目录',now(),5,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('sentinel monitor','%s %s %d 1','master名称定义和最少参与监控的sentinel数,格式:masterName ip port num',now(),5,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('sentinel down-after-milliseconds','%s 20000','Sentinel判定服务器断线的毫秒数',now(),5,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('sentinel failover-timeout','%s 180000','故障迁移超时时间,默认:3分钟',now(),5,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('sentinel parallel-syncs','%s 1','在执行故障转移时,最多有多少个从服务器同时对新的主服务器进行同步,默认:1',now(),5,1);\n\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('daemonize','no','是否守护进程',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('tcp-backlog','511','TCP连接完成队列',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('timeout','0','客户端闲置多少秒后关闭连接,默认为0,永不关闭',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('tcp-keepalive','60','检测客户端是否健康周期,默认关闭',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('loglevel','notice','日志级别',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('databases','16','可用的数据库数，默认值为16个,默认数据库为0',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('dir','%s','redis工作目录',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('stop-writes-on-bgsave-error','no','bgsave出错了不停写',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('repl-timeout','60','master批量数据传输时间或者ping回复时间间隔,默认:60秒',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('repl-ping-slave-period','10','指定slave定期ping master的周期,默认:10秒',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('repl-disable-tcp-nodelay','no','是否禁用socket的NO_DELAY,默认关闭，影响主从延迟',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('repl-backlog-size','10M','复制缓存区,默认:1mb,配置为:10Mb',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('repl-backlog-ttl','7200','master在没有Slave的情况下释放BACKLOG的时间多久:默认:3600,配置为:7200',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('slave-serve-stale-data','yes','当slave服务器和master服务器失去连接后，或者当数据正在复制传输的时候，如果此参数值设置“yes”，slave服务器可以继续接受客户端的请求',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('slave-read-only','yes','slave服务器节点是否只读,cluster的slave节点默认读写都不可用,需要调用readonly开启可读模式',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('slave-priority','100','slave的优先级,影响sentinel/cluster晋升master操作,0永远不晋升',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('lua-time-limit','5000','Lua脚本最长的执行时间，单位为毫秒',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('slowlog-log-slower-than','10000','慢查询被记录的阀值,默认10毫秒',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('slowlog-max-len','128','最多记录慢查询的条数',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('hash-max-ziplist-entries','512','hash数据结构优化参数',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('hash-max-ziplist-value','64','hash数据结构优化参数',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('list-max-ziplist-entries','512','list数据结构优化参数',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('list-max-ziplist-value','64','list数据结构优化参数',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('set-max-intset-entries','512','set数据结构优化参数',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('zset-max-ziplist-entries','128','zset数据结构优化参数',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('zset-max-ziplist-value','64','zset数据结构优化参数',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('activerehashing','yes','是否激活重置哈希,默认:yes',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('client-output-buffer-limit normal','0 0 0','客户端输出缓冲区限制(客户端)',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('client-output-buffer-limit slave','512mb 128mb 60','客户端输出缓冲区限制(复制)',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('client-output-buffer-limit pubsub','32mb 8mb 60','客户端输出缓冲区限制(发布订阅)',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('hz','10','执行后台task数量,默认:10',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('port','%d','端口',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('maxmemory','%dmb','当前实例最大可用内存',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('maxmemory-policy','volatile-lru','内存不够时,淘汰策略,默认:volatile-lru',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('appendonly','yes','开启append only持久化模式',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('appendfsync','everysec','默认:aof每秒同步一次',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('appendfilename','appendonly-%d.aof','aof文件名称,默认:appendonly-{port}.aof',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('dbfilename','dump-%d.rdb','RDB文件默认名称,默认dump-{port}.rdb',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('aof-rewrite-incremental-fsync','yes','aof rewrite过程中,是否采取增量文件同步策略,默认:yes',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('no-appendfsync-on-rewrite','yes','是否在后台aof文件rewrite期间调用fsync,默认调用,修改为yes,防止可能fsync阻塞,但可能丢失rewrite期间的数据',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('auto-aof-rewrite-min-size','64m','触发rewrite的aof文件最小阀值,默认64m',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('auto-aof-rewrite-percentage','%d','Redis重写aof文件的比例条件,默认从100开始,统一机器下不同实例按4%递减',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('rdbcompression','yes','rdb是否压缩',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('rdbchecksum','yes','rdb校验和',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('repl-diskless-sync','no','开启无盘复制',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('repl-diskless-sync-delay','5','无盘复制延时',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('save 900','1','900秒有一次修改做bgsave',now(),6,0);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('save 300','10','300秒有10次修改做bgsave',now(),6,0);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('save 60','10000','60秒有10000次修改做bgsave',now(),6,0);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('maxclients','10000','客户端最大连接数',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('hll-sparse-max-bytes','3000','HyperLogLog稀疏表示限制设置\t',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('min-slaves-to-write','0','当slave数量小于min-slaves-to-write，且延迟小于等于min-slaves-max-lag时， master停止写入操作',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('min-slaves-max-lag','10','当slave服务器和master服务器失去连接后，或者当数据正在复制传输的时候，如果此参数值设置yes，slave服务器可以继续接受客户端的请求',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('aof-load-truncated','yes','加载aof文件时，是否忽略aof文件不完整的情况，是否Redis正常启动',now(),6,1);\ninsert into instance_config(config_key,config_value,info,update_time, type, status) values('notify-keyspace-events','','keyspace事件通知功能',now(),6,1);\n\n-- change appdesc add 秘钥和客户端连接数报警\nalter table app_desc add column client_conn_alert_value int(11) DEFAULT 2000 COMMENT '客户端连接报警阀值';\nalter table app_desc add column app_key varchar(255) DEFAULT NULL COMMENT '应用秘钥';\n\nalter table instance_statistics add column mem_fragmentation_ratio double default 0 COMMENT '碎片率';\nalter table instance_statistics add column aof_delayed_fsync int default 0 COMMENT 'aof阻塞次数';\n\nupdate machine_info set available=1;\n\n/*!40101 SET character_set_client = @saved_cs_client */;\n/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;\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/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\n/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\n/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;\n\n-- Dump completed on 2016-01-13  9:28:31\n\n-- add column for the switch of server status collection\nALTER TABLE `machine_info` ADD COLUMN `collect` int DEFAULT 1 COMMENT 'switch of collect server status, 1:open, 0:close';\n\n-- add server status table\nDROP TABLE IF EXISTS `server`;\nCREATE TABLE `server` (\n  `ip` varchar(16) NOT NULL COMMENT 'ip',\n  `host` varchar(255) DEFAULT NULL COMMENT 'host',\n  `nmon` varchar(255) DEFAULT NULL COMMENT 'nmon version',\n  `cpus` tinyint(4) DEFAULT NULL COMMENT 'logic cpu num',\n  `cpu_model` varchar(255) DEFAULT NULL COMMENT 'cpu 型号',\n  `dist` varchar(255) DEFAULT NULL COMMENT '发行版信息',\n  `kernel` varchar(255) DEFAULT NULL COMMENT '内核信息',\n  `ulimit` varchar(255) DEFAULT NULL COMMENT 'ulimit -n,ulimit -u',\n  `updatetime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n  PRIMARY KEY (`ip`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\nDROP TABLE IF EXISTS `server_stat`;\nCREATE TABLE `server_stat` (\n  `ip` varchar(16) NOT NULL COMMENT 'ip',\n  `cdate` date NOT NULL COMMENT '数据收集天',\n  `ctime` char(4) NOT NULL COMMENT '数据收集小时分钟',\n  `cuser` float DEFAULT NULL COMMENT '用户态占比',\n  `csys` float DEFAULT NULL COMMENT '内核态占比',\n  `cwio` float DEFAULT NULL COMMENT 'wio占比',\n  `c_ext` text COMMENT '子cpu占比',\n  `cload1` float DEFAULT NULL COMMENT '1分钟load',\n  `cload5` float DEFAULT NULL COMMENT '5分钟load',\n  `cload15` float DEFAULT NULL COMMENT '15分钟load',\n  `mtotal` float DEFAULT NULL COMMENT '总内存,单位M',\n  `mfree` float DEFAULT NULL COMMENT '空闲内存',\n  `mcache` float DEFAULT NULL COMMENT 'cache',\n  `mbuffer` float DEFAULT NULL COMMENT 'buffer',\n  `mswap` float DEFAULT NULL COMMENT 'cache',\n  `mswap_free` float DEFAULT NULL COMMENT 'cache',\n  `nin` float DEFAULT NULL COMMENT '网络入流量 单位K/s',\n  `nout` float DEFAULT NULL COMMENT '网络出流量 单位k/s',\n  `nin_ext` text COMMENT '各网卡入流量详情',\n  `nout_ext` text COMMENT '各网卡出流量详情',\n  `tuse` int(11) DEFAULT NULL COMMENT 'tcp estab连接数',\n  `torphan` int(11) DEFAULT NULL COMMENT 'tcp orphan连接数',\n  `twait` int(11) DEFAULT NULL COMMENT 'tcp time wait连接数',\n  `dread` float DEFAULT NULL COMMENT '磁盘读速率 单位K/s',\n  `dwrite` float DEFAULT NULL COMMENT '磁盘写速率 单位K/s',\n  `diops` float DEFAULT NULL COMMENT '磁盘io速率 交互次数/s',\n  `dbusy` float DEFAULT NULL COMMENT '磁盘io带宽使用百分比',\n  `d_ext` text COMMENT '磁盘各分区占比',\n  `dspace` text COMMENT '磁盘各分区空间使用率',\n  PRIMARY KEY (`ip`,`cdate`,`ctime`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\n-- 应用级别\nalter table app_desc add column important_level tinyint not null default 2 comment '应用级别，1:最重要，2:一般重要，3:一般'; \n\nCREATE TABLE `instance_alert` (\n  `config_key` varchar(255) NOT NULL COMMENT '配置key',\n  `alert_value` varchar(512) NOT NULL COMMENT '报警阀值',\n  `info` varchar(255) NOT NULL COMMENT '配置说明',\n  `status` tinyint(4) NOT NULL COMMENT '1:可用,0:不可用',\n  `order_id` int(11) NOT NULL COMMENT '顺序',\n  `compare_type` tinyint(4) NOT NULL COMMENT '比较类型：-1小于,0等于,1大于',\n  `value_type` tinyint(4) NOT NULL DEFAULT '1' COMMENT '1固定值,2差值',\n  PRIMARY KEY (`config_key`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例报警阀值';\n\nalter table app_desc add column password varchar(255) default '' comment 'redis密码';\n\nCREATE TABLE `app_daily` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增id',\n  `app_id` bigint(20) NOT NULL COMMENT '应用id',\n  `date` date NOT NULL COMMENT '日期',\n  `create_time` datetime NOT NULL,\n  `slow_log_count` bigint(20) NOT NULL COMMENT '慢查询个数',\n  `client_exception_count` bigint(20) NOT NULL COMMENT '客户端异常个数',\n  `max_minute_client_count` bigint(20) NOT NULL COMMENT '每分钟最大客户端连接数',\n  `avg_minute_client_count` bigint(20) NOT NULL COMMENT '每分钟平均客户端连接数',\n  `max_minute_command_count` bigint(20) NOT NULL COMMENT '每分钟最大命令数',\n  `avg_minute_command_count` bigint(20) NOT NULL COMMENT '每分钟平均命令数',\n  `avg_hit_ratio` double NOT NULL COMMENT '平均命中率',\n  `min_minute_hit_ratio` double NOT NULL COMMENT '每分钟最小命中率',\n  `max_minute_hit_ratio` double NOT NULL COMMENT '每分钟最大命中率',\n  `avg_used_memory` bigint(20) NOT NULL COMMENT '最大内存使用量',\n  `max_used_memory` bigint(20) NOT NULL COMMENT '平均内存使用量',\n  `expired_keys_count` bigint(20) NOT NULL COMMENT '过期键个数',\n  `evicted_keys_count` bigint(20) NOT NULL COMMENT '剔除键个数',\n  `avg_minute_net_input_byte` double NOT NULL COMMENT '每分钟平均网络input量',\n  `max_minute_net_input_byte` double NOT NULL COMMENT '每分钟最大网络input量',\n  `avg_minute_net_output_byte` double NOT NULL COMMENT '每分钟平均网络output量',\n  `max_minute_net_output_byte` double NOT NULL COMMENT '每分钟最大网络output量',\n  `avg_object_size` bigint(20) NOT NULL COMMENT '键个数平均值',\n  `max_object_size` bigint(20) NOT NULL COMMENT '键个数最大值',\n  `big_key_times` bigint(20) NOT NULL COMMENT 'bigkey次数',\n  `big_key_info` varchar(512) COLLATE utf8_bin NOT NULL COMMENT 'bigkey详情',\n  PRIMARY KEY (`id`),\n  KEY `idx_appid_date` (`app_id`,`date`)\n) ENGINE=InnoDB AUTO_INCREMENT=933 DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='app日报';\n\nDROP TABLE IF EXISTS `instance_alert_configs`;\nCREATE TABLE `instance_alert_configs` (\n  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id',\n  `alert_config` varchar(255) NOT NULL COMMENT '报警配置',\n  `alert_value` varchar(512) NOT NULL COMMENT '报警阀值',\n  `config_info` varchar(255) NOT NULL COMMENT '配置说明',\n  `type` tinyint(4) NOT NULL COMMENT '1:全局报警,2:实例报警',\n  `instance_id` bigint(20) NOT NULL DEFAULT 0 COMMENT '0:全局配置，其他代表实例id',\n  `status` tinyint(4) NOT NULL COMMENT '1:可用,0:不可用',\n  `compare_type` tinyint(4) NOT NULL COMMENT '比较类型：1小于,2等于,3大于,4不等于',\n  `check_cycle` tinyint(4) NOT NULL COMMENT '1:一分钟,2:五分钟,3:半小时4:一个小时,5:一天',\n  `update_time` datetime not null comment '报警配置更新时间',\n  `last_check_time` datetime not null comment '上次检查时间',\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `uniq_index` (`type`,`instance_id`,`alert_config`,`compare_type`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例报警阀值配置';\n\nalter table standard_statistics add column cluster_info_json varchar(20480) not null default '' comment '收集的cluster info json数据';\n\n\nDROP TABLE IF EXISTS `instance_reshard_process`;\nCREATE TABLE `instance_reshard_process` (\n  id int not null auto_increment comment '自增id',\n  app_id bigint not null comment '应用id',\n  audit_id bigint not null comment '审核id',\n  source_instance_id int not null comment '源实例id',\n  target_instance_id int not null comment '目标实例id',\n  start_slot int not null comment '开始slot',\n  end_slot int not null comment '结束slot',\n  migrating_slot int not null comment '正在迁移的slot',\n  is_pipeline tinyint not null comment '是否为pipeline,0:否,1:是',\n  finish_slot_num int not null comment '已经完成迁移的slot数量',\n  status tinyint not null comment '0:运行中 1:完成 2:出错',\n  start_time datetime NOT NULL COMMENT '迁移开始时间',\n  end_time datetime NOT NULL COMMENT '迁移结束时间',\n  create_time datetime NOT NULL COMMENT '创建时间',\n  update_time datetime NOT NULL COMMENT '更新时间',\n  PRIMARY KEY (`id`),\n  KEY `idx_audit` (`audit_id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例Reshard进度';\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/script/deploy.sh",
    "content": "#!/bin/bash\n\ncachecloud_dir=$1\nbase_dir=/opt/cachecloud-web\nmkdir -p ${base_dir}\nmkdir -p ${base_dir}/logs\ncp ${cachecloud_dir}/cachecloud/script/start.sh ${base_dir}\ncp ${cachecloud_dir}/cachecloud/script/stop.sh ${base_dir}\ncp ${cachecloud_dir}/cachecloud/cachecloud-open-web/target/cachecloud-open-web-1.0-SNAPSHOT.war ${base_dir}\ncp ${cachecloud_dir}/cachecloud/cachecloud-open-web/src/main/resources/cachecloud-web.conf  ${base_dir}/cachecloud-open-web-1.0-SNAPSHOT.conf\n"
  },
  {
    "path": "open-monitor-center/cachecloud/script/start.sh",
    "content": "#!/bin/bash\n\n###########################################################################\n# @author: leifu \n# @desc: start cachecloud\n# @time: 2016-03-31 \n###########################################################################\n\nSERVER_NAME=cachecloud\nDEPLOY_DIR=/opt/cachecloud-web\nSTDOUT_FILE=${DEPLOY_DIR}/logs/cachecloud-web.log\nWAR_FILE=${DEPLOY_DIR}/cachecloud-open-web-1.0-SNAPSHOT.war\n\nPIDS=`ps -f | grep java | grep \"${DEPLOY_DIR}\" |awk '{print $2}'`\nif [ -n \"$PIDS\" ]; then\n    echo \"ERROR: The ${SERVER_NAME} already started!\"\n    echo \"PID: $PIDS\"\n    exit 1\nfi\n\nJAVA_OPTS=\"-server -Xmx4g -Xms4g -Xss256k -XX:MaxDirectMemorySize=1G -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:G1ReservePercent=25 -XX:InitiatingHeapOccupancyPercent=40 -XX:+PrintGCDateStamps -Xloggc:/opt/cachecloud-web/logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/cachecloud-web/logs/java.hprof -XX:+DisableExplicitGC -XX:-OmitStackTraceInFastThrow -XX:+PrintCommandLineFlags -XX:+UnlockCommercialFeatures -XX:+FlightRecorder -Djava.awt.headless=true -Djava.net.preferIPv4Stack=true -Djava.util.Arrays.useLegacyMergeSort=true -Dfile.encoding=UTF-8\"\necho -e \"Starting the ${SERVER_NAME} ...\\c\"\nnohup java $JAVA_OPTS -jar ${WAR_FILE} > $STDOUT_FILE 2>&1 &\nCOUNT=0\nwhile [ $COUNT -lt 1 ]; do    \n    echo -e \".\\c\"\n    sleep 1 \n    COUNT=`ps -f | grep java | grep \"${DEPLOY_DIR}\" | awk '{print $2}' | wc -l`\n    if [ $COUNT -gt 0 ]; then\n        break\n    fi\ndone\n\necho \"OK!\"\nPIDS=`ps -f | grep java | grep \"${DEPLOY_DIR}\" | awk '{print $2}'`\necho \"PID: $PIDS\"\necho \"STDOUT: $STDOUT_FILE\"\n\n"
  },
  {
    "path": "open-monitor-center/cachecloud/script/stop.sh",
    "content": "#!/bin/bash\n###########################################################################\n# @author: leifu \n# @desc: stop cachecloud\n# @time: \n###########################################################################\nDEPLOY_DIR=/opt/cachecloud-web\nSERVER_NAME=cachecloud\nPIDS=`ps -ef | grep java | grep \"${DEPLOY_DIR}\" |awk '{print $2}'`\nif [ -z \"$PIDS\" ]; then\n    echo \"ERROR: The $SERVER_NAME does not started!\"\n    exit 1\nfi\n\necho -e \"Stopping the $SERVER_NAME ...\\c\"\nfor PID in $PIDS ; do\n    kill $PID > /dev/null 2>&1\ndone\n\nCOUNT=0\nwhile [ $COUNT -lt 1 ]; do    \n    echo -e \".\\c\"\n    sleep 1\n    COUNT=1\n    for PID in $PIDS ; do\n        PID_EXIST=`ps -f -p $PID | grep java`\n        if [ -n \"$PID_EXIST\" ]; then\n            COUNT=0\n            break\n        fi\n    done\ndone\n\necho \"OK!\"\necho \"PID: $PIDS\"\n"
  },
  {
    "path": "open-monitor-center/open-admin-server/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" 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  <parent>\n    <groupId>com.open.capacity</groupId>\n    <artifactId>open-monitor-center</artifactId>\n    <version>0.0.1-SNAPSHOT</version>\n  </parent>\n  <artifactId>open-admin-server</artifactId>\n  <description>spring boot admin 监控</description>\n  <dependencies>\n  \t\t\n  \t\t<dependency>\n            <groupId>de.codecentric</groupId>\n            <artifactId>spring-boot-admin-server</artifactId>\n            <version>1.5.6</version>\n        </dependency>\n        <dependency>\n            <groupId>de.codecentric</groupId>\n            <artifactId>spring-boot-admin-server-ui</artifactId>\n            <version>1.5.6</version>\n        </dependency>\n        \n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-starter-turbine</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>de.codecentric</groupId>\n            <artifactId>spring-boot-admin-server-ui-turbine</artifactId>\n            <version>1.5.6</version>\n        </dependency>\n  \t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-mail</artifactId>\n\t\t</dependency>\n\t\t\n\t\t<dependency>\n\t\t\t<groupId>org.jolokia</groupId>\n\t\t\t<artifactId>jolokia-core</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-eureka</artifactId>\n\t\t</dependency>\n\t\t\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n  \t\t\n  </dependencies>\n</project>"
  },
  {
    "path": "open-monitor-center/open-admin-server/src/main/java/com/open/capacity/Controller.java",
    "content": "package com.open.capacity;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.core.io.FileSystemResource;\nimport org.springframework.mail.SimpleMailMessage;\nimport org.springframework.mail.javamail.JavaMailSender;\nimport org.springframework.mail.javamail.MimeMessageHelper;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport javax.mail.MessagingException;\nimport javax.mail.internet.MimeMessage;\nimport java.io.File;\n\n/**\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2017年11月24日 下午5:34:47 类说明\n */\n@RestController\npublic class Controller {\n    @Autowired\n    private JavaMailSender javaMailSender;\n\n    @GetMapping(\"/send\")\n    public String send() {\n        SimpleMailMessage message = new SimpleMailMessage();\n\n        message.setFrom(\"18579068155@163.com\");\n        message.setTo(\"wang.wen@neusoft.com\");\n        message.setSubject(\"测试邮件\");\n        message.setText(\"好好学习\");\n        javaMailSender.send(message);\n        return \"hello\";\n    }\n\n    @GetMapping(\"/send1\")\n    public String send1() throws MessagingException {\n\n        MimeMessage msg = javaMailSender.createMimeMessage();\n        MimeMessageHelper msgHelper = new MimeMessageHelper(msg, true, \"utf-8\");\n\n        msgHelper.setFrom(\"18579068155@163.com\");\n        msgHelper.setTo(\"wang.wen@neusoft.com\");\n        msgHelper.setSubject(\"测试发送带附件的邮件\");\n        msgHelper.setText(\"测试邮件\");\n\n        FileSystemResource file = new FileSystemResource(new File(\"D:\" + File.separator + \"20171124150927.jpg\"));\n        msgHelper.addAttachment(\"20171124150927.jpg\", file); // 添加附件\n\n        // Properties prop = new Properties();\n        // prop.put(\"mail.smtp.auth\", \"true\");\n        // prop.put(\"mail.smtp.timeout\", \"25000\");\n        // javaMailSender.setJavaMailProperties(prop);\n\n        javaMailSender.send(msg);\n\n        return \"hello\";\n    }\n}\n"
  },
  {
    "path": "open-monitor-center/open-admin-server/src/main/java/com/open/capacity/OpenAdminApp.java",
    "content": "package com.open.capacity;\n\n\nimport de.codecentric.boot.admin.config.EnableAdminServer;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.client.discovery.EnableDiscoveryClient;\n\n/**\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2017年12月8日 上午9:03:32\n * 类说明\n */\n@EnableAdminServer\n@EnableDiscoveryClient\n@SpringBootApplication\npublic class OpenAdminApp {\n    public static void main(String[] args) {\n        SpringApplication.run(OpenAdminApp.class, args);\n    }\n\n}\n"
  },
  {
    "path": "open-monitor-center/open-admin-server/src/main/resources/application.yml",
    "content": "server:  \n  port: 9998  \nspring:  \n  application:  \n    name: unieap-admin-server\n  boot:  \n    admin:  \n      notify:  \n        mail:  \n          enabled: true\n          to: 624191343@qq.com  \n          from: 18579068155@163.com  \n#          ignore-changes: UNKNOWN:UP  \n          ignore-changes:  \n            -  \n              \"*:UP\" #从任何状态到up状态都不要发邮件通知  \n      routes:  \n        endpoints: env,metrics,dump,jolokia,info,configprops,trace,logfile,refresh,flyway,liquibase,heapdump,loggers,auditevents,hystrix.stream\n      turbine:\n        clusters: default\n        #,unieap-eureka-server-single\n        location: turbine  \n  mail:\n    host: smtp.163.com\n    username: 18579068155@163.com\n    password: 1q2w3e4r\n    properties:\n        mail.smtp.auth : true\n        mail.smtp.timeout : 2000\n        mail.smtp.starttls.enable : true\n        mail.smtp.starttls.required : true \neureka:  \n  client:  \n    serviceUrl:  \n      defaultZone: http://127.0.0.1:1111/eureka/  \nmanagement:  \n  security:  \n    enabled: false"
  },
  {
    "path": "open-monitor-center/open-zipkin-center/open-zipkin-kafka-client/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" 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  <parent>\n    <groupId>com.open.capacity</groupId>\n    <artifactId>open-zipkin-center</artifactId>\n    <version>0.0.1-SNAPSHOT</version>\n  </parent>\n  <artifactId>open-zipkin-client-kafka</artifactId>\n  \n  <dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-sleuth-zipkin-stream</artifactId>\n\t\t\t<exclusions>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<groupId>io.zipkin.java</groupId>\n\t\t\t\t\t<artifactId>zipkin-server</artifactId>\n\t\t\t\t</exclusion>\n\t\t\t</exclusions>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-stream-kafka</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-starter-sleuth</artifactId>\n        </dependency>\n\t\t\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-eureka</artifactId>\n\t\t</dependency>\n\t\t\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-actuator</artifactId>\n\t\t</dependency>\n\t\t\n\t</dependencies>\n  \n  \n</project>"
  },
  {
    "path": "open-monitor-center/open-zipkin-center/open-zipkin-kafka-client/src/main/java/com/open/capacity/ZipKinClientApp.java",
    "content": "package com.open.capacity;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.netflix.eureka.EnableEurekaClient;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n@RestController\n@EnableEurekaClient\n@SpringBootApplication\npublic class ZipKinClientApp {\n\n    @GetMapping(\"/hello\")\n    public String hello() {\n        return \"hello\";\n    }\n\n    @GetMapping(\"/world\")\n    public String world() {\n        return \"world\";\n    }\n\n    @GetMapping(\"/test\")\n    public String test() {\n        return \"test\";\n    }\n\n    private static final Logger logger = LoggerFactory.getLogger(ZipKinClientApp.class);\n\n    public static void main(String[] args) {\n        SpringApplication.run(ZipKinClientApp.class, args);\n    }\n}"
  },
  {
    "path": "open-monitor-center/open-zipkin-center/open-zipkin-kafka-client/src/main/resources/application.yml",
    "content": "server:\n  port: 9412\nspring:\n  application:\n    name: open-zipkin-kafka-client\n  zipkin:\n    base-url: http://127.0.0.1:9411  \n  cloud:\n    stream:\n      kafka:\n        binder:\n          brokers: zookeeper01:9092,zookeeper02:9092,zookeeper03:9092\n          zkNodes: zookeeper01:2181,zookeeper02:2181,zookeeper03:2181 #,10.10.68.200:2181,10.10.68.201:2181\n  sleuth:\n    sampler:\n      percentage: 1.0  \n    rxjava:\n      schedulers:\n        ignoredthreads: HystrixMetricPoller,^RxComputation.*$,^RxIoScheduler.*$ #忽略rxjava相关线程，防止产生无意义的span\n        \n        \nhystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 12000 #hystix失败超时时间判定        \n      \nlogging:\n  level:\n    root: INFO\n    org.springframework.cloud.sleuth: DEBUG\n\n\n\neureka:\n  instance:\n    preferIpAddress: true\n  client:\n    registerWithEureka: true\n    serviceUrl:\n        defaultZone: http://134.224.249.39:1111/eureka/\n\n    "
  },
  {
    "path": "open-monitor-center/open-zipkin-center/open-zipkin-kafka-server/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" 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  <parent>\n    <groupId>com.open.capacity</groupId>\n    <artifactId>open-zipkin-center</artifactId>\n    <version>0.0.1-SNAPSHOT</version>\n  </parent>\n  <artifactId>open-zipkin-server-kafka</artifactId>\n  \n  \n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>io.zipkin.java</groupId>\n\t\t\t<artifactId>zipkin-autoconfigure-ui</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-sleuth-zipkin-stream</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-stream-kafka</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>io.zipkin.java</groupId>\n\t\t\t<artifactId>zipkin-autoconfigure-storage-elasticsearch-http</artifactId>\n\t\t\t<version>1.24.0</version>\n\t\t\t<optional>true</optional>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-sleuth</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-actuator</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-eureka</artifactId>\n\t\t</dependency>\n\n\n\t</dependencies>\n  \n  \n</project>"
  },
  {
    "path": "open-monitor-center/open-zipkin-center/open-zipkin-kafka-server/src/main/java/com/open/capacity/OpenZipkinServer.java",
    "content": "package com.open.capacity;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.client.discovery.EnableDiscoveryClient;\nimport org.springframework.cloud.sleuth.zipkin.stream.EnableZipkinStreamServer;\n\n/** \n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2017年11月12日 上午22:57:51 类说明\n* 类说明 \n*/\n@EnableDiscoveryClient\n@SpringBootApplication\n@EnableZipkinStreamServer\npublic class OpenZipkinServer {\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(OpenZipkinServer.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "open-monitor-center/open-zipkin-center/open-zipkin-kafka-server/src/main/resources/application.yml",
    "content": "server:\n  port: 9411\nspring:\n  application:\n    name: open-zipkin-kafka-server\n  sleuth:\n    enabled: false\n  sampler:\n    percentage: 1.0\n  cloud:\n    stream:\n      kafka:\n        binder:\n          brokers: zookeeper01:9092,zookeeper02:9092,zookeeper03:9092\n          zkNodes: zookeeper01:2181,zookeeper02:2181,zookeeper03:2181 #,10.10.68.200:2181,10.10.68.201:2181\n          min-partition-count: 3 \n          auto-add-partitions: true\n          replication-factor: 3\nlogging:\n  level:\n    root: INFO\n    org: DEBUG\n    com: DEBUG\neureka:\n  instance:\n    preferIpAddress: true\n  client:\n    registerWithEureka: true\n    serviceUrl:\n        defaultZone: http://134.224.249.39:1111/eureka/\n\nzipkin:\n  storage:\n    type: elasticsearch\n    elasticsearch:\n      cluster: owen\n      hosts: http://130.75.131.233:9200,http://130.75.131.234:9200,http://130.75.131.235:9200\n      index: zipkin\n      index-shards: 5\n      index-replicas: 1\n\n    "
  },
  {
    "path": "open-monitor-center/open-zipkin-center/open-zipkin-memery-client/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" 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  <parent>\n    <groupId>com.open.capacity</groupId>\n    <artifactId>open-zipkin-center</artifactId>\n    <version>0.0.1-SNAPSHOT</version>\n  </parent>\n  <artifactId>open-zipkin-client-memery</artifactId>\n  \n   <dependencies>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-sleuth</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-sleuth-zipkin</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-eureka</artifactId>\n\t\t</dependency>\n\t\t\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-actuator</artifactId>\n\t\t</dependency>\n\t\t\n\t</dependencies>\n  \n</project>"
  },
  {
    "path": "open-monitor-center/open-zipkin-center/open-zipkin-memery-client/src/main/java/com/open/capacity/TestController.java",
    "content": "package com.open.capacity;\n\nimport javax.annotation.Resource;\n\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RestController;\nimport org.springframework.web.client.RestTemplate;\n\n/** \n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2017年11月12日 上午22:57:51 类说明\n* 类说明 \n*/\n@RestController\npublic class TestController {\n\t\n\t@Resource\n\tprivate RestTemplate restTemplate ;\n\n\t@GetMapping(value=\"/hello\")\n\tpublic String hello(){\n\t\treturn \"hello\" ;\n\t}\n\t\n\t@GetMapping(value=\"/world\")\n\tpublic String world(){\n\t\t\n\t\t\n\t\treturn restTemplate.getForObject(\"http://unieap-eureka-client/hello\", String.class) ;\n\t}\n\t\n}\n"
  },
  {
    "path": "open-monitor-center/open-zipkin-center/open-zipkin-memery-client/src/main/java/com/open/capacity/ZipKinClientApp.java",
    "content": "package com.open.capacity;\n\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.client.loadbalancer.LoadBalanced;\nimport org.springframework.cloud.netflix.eureka.EnableEurekaClient;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.web.client.RestTemplate;\n\n/** \n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2017年11月12日 上午22:57:51 类说明\n* 类说明 \n*/\n@EnableEurekaClient\n@SpringBootApplication\npublic class ZipKinClientApp {\n\t\n\t@Bean\n\t@LoadBalanced\n\tpublic RestTemplate restTemplate(){\n\t\treturn new RestTemplate();\n\t}\n\t\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(ZipKinClientApp.class, args);\n\t}\n} \n"
  },
  {
    "path": "open-monitor-center/open-zipkin-center/open-zipkin-memery-client/src/main/resources/application.yml",
    "content": "server:\n  port: 9412\nspring:\n  application:\n    name: open-zipkin-memery-client\n  zipkin:\n    enabled: true\n    base-url: http://open-zipkin-memery-server/ \n    locator:\n      discovery:\n        enabled: true\n  sleuth:\n    sampler:\n      percentage: 1.0\n    rxjava:\n      schedulers:\n        ignoredthreads: HystrixMetricPoller,^RxComputation.*$,^RxIoScheduler.*$ #忽略rxjava相关线程，防止产生无意义的span\nhystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 12000 #hystix失败超时时间判定        \n      \nlogging:\n  level:\n    root: INFO\n    org.springframework.cloud.sleuth: DEBUG\n\neureka:\n  client:\n    serviceUrl:\n      defaultZone:  http://127.0.0.1:1111/eureka\n  instance:\n    prefer-ip-address: true\n    instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}\n    lease-renewal-interval-in-seconds: 5  #每隔几秒告诉eureka服务器我还存活，用于心跳检测\n    lease-expiration-duration-in-seconds: 10 #如果心跳检测一直没有发送，10秒后会从eureka服务器中将此服务剔除s"
  },
  {
    "path": "open-monitor-center/open-zipkin-center/open-zipkin-memery-server/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" 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  <parent>\n    <groupId>com.open.capacity</groupId>\n    <artifactId>open-zipkin-center</artifactId>\n    <version>0.0.1-SNAPSHOT</version>\n  </parent>\n  <artifactId>open-zipkin-server-memery</artifactId>\n  \n  \n\t<dependencies>\n\t\t<!-- ><dependency> <groupId>io.zipkin.java</groupId> <artifactId>zipkin-autoconfigure-ui</artifactId> \n\t\t\t</dependency> <dependency> <groupId>io.zipkin.java</groupId> <artifactId>zipkin-server</artifactId> \n\t\t\t</dependency> -->\n\n\n\t\t<!-- 基于内存的链路跟踪 -->\n\t\t<dependency>\n\t\t\t<groupId>io.zipkin.java</groupId>\n\t\t\t<artifactId>zipkin-autoconfigure-ui</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>io.zipkin.java</groupId>\n\t\t\t<artifactId>zipkin-server</artifactId>\n\t\t</dependency>\n\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-actuator</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-eureka</artifactId>\n\t\t</dependency>\n\n\n\t</dependencies>\n\n\t<!-- 形成带第三方jar包的可执行jar包，jar包目录结构如下 application.properties lib META-INF mybatis \n\t\torg -->\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t\t<version>1.3.3.RELEASE</version>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>repackage</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t</plugins>\n\t\t<finalName>open-zipkin-server-memery</finalName>\n\t</build>\n  \n  \n  \n</project>"
  },
  {
    "path": "open-monitor-center/open-zipkin-center/open-zipkin-memery-server/src/main/java/com/open/capacity/OpenZipkinSerApp.java",
    "content": "package com.open.capacity;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.client.discovery.EnableDiscoveryClient;\n\nimport zipkin.server.EnableZipkinServer;\n\n/** \n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2017年11月12日 上午22:57:51 类说明\n*/\n@EnableDiscoveryClient\n@EnableZipkinServer\n@SpringBootApplication\npublic class OpenZipkinSerApp {\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(OpenZipkinSerApp.class, args);\n\t}\n}\n"
  },
  {
    "path": "open-monitor-center/open-zipkin-center/open-zipkin-memery-server/src/main/resources/application.yml",
    "content": "server:\n  port: 9410\nspring:\n  application:\n    name: open-zipkin-memery-server\nlogging:\n  level:\n    root: INFO\n    org.springframework.cloud.sleuth: DEBUG #监控行为\n\n\neureka:\n  client:\n    serviceUrl:\n      defaultZone:  http://127.0.0.1:1111/eureka\n    register-with-eureka: true  \n  instance:\n    prefer-ip-address: true\n    instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}\n    lease-renewal-interval-in-seconds: 5  #每隔几秒告诉eureka服务器我还存活，用于心跳检测\n    lease-expiration-duration-in-seconds: 10 #如果心跳检测一直没有发送，10秒后会从eureka服务器中将此服务剔除s\n"
  },
  {
    "path": "open-monitor-center/open-zipkin-center/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" 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  <parent>\n    <groupId>com.open.capacity</groupId>\n    <artifactId>open-monitor-center</artifactId>\n    <version>0.0.1-SNAPSHOT</version>\n  </parent>\n  <artifactId>open-zipkin-center</artifactId>\n  <description>链路跟踪</description>\n  <packaging>pom</packaging>\n  <modules>\n  \t<module>open-zipkin-kafka-client</module>\n  \t<module>open-zipkin-kafka-server</module>\n  \t<module>open-zipkin-memery-client</module>\n  \t<module>open-zipkin-memery-server</module>\n  </modules>\n</project>"
  },
  {
    "path": "open-monitor-center/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" 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  <parent>\n    <groupId>com.open.capacity</groupId>\n    <artifactId>open-capacity-platform</artifactId>\n    <version>0.0.1-SNAPSHOT</version>\n  </parent>\n  <artifactId>open-monitor-center</artifactId>\n  <description>监控中心</description>\n  <packaging>pom</packaging>\n\n  <modules>\n  \t<module>open-admin-server</module>\n  \t<module>open-zipkin-center</module>\n  </modules>\n</project>"
  },
  {
    "path": "open-oauth-center/README.md",
    "content": "# 认证服务器-->认证中心 \n\n\n## OAuth2分为四个角色：资源拥有者、资源服务器、授权服务器、客户端 \n\n\n![](https://i.imgur.com/MSPOyMJ.jpg)\n\n\n## open-oauth-center  oauth2 认证服务器 资源服务器分离架构中心 \n\n![](https://i.imgur.com/V9hvviQ.png)\n\n\n\n## open-oauth-server 认证中心 \n![](https://i.imgur.com/RWrGfa4.png)\n\n## 客户端模式 \n![](https://i.imgur.com/2otLKyU.png)\n\n## 密码模式 \n![](https://i.imgur.com/ky6gGPF.jpg)\n\n## 授权码模式 \n1.获取授权码\n\thttp://localhost:8000/oauth/authorize?client_id=webApp&redirect_uri=http://www.baidu.com&state=abc&scope=app&response_type=code\n\n2.授权码换token\n![](https://i.imgur.com/01lpwCL.png)\n\n\n## open-oauth-client  open-oauth-client-two  open-api-gateway 均为资源服务器  \n\n![](https://i.imgur.com/WZZiWbm.png)\n\n\n\n## 源码分析   \n![](https://i.imgur.com/Cfm2bq6.jpg)\n\n \n## 资源服务器校验核心逻辑 \n\n![](https://i.imgur.com/ysrtPT9.png)\n \n认证服务器 资源服务器统一实现配置tokenstore，同时直接连接redis校验token是否有效  \n ![](https://i.imgur.com/l19iTmo.png)  \nRemoteTokenServices  \n一般为单点登录sso时使用，此方式需要通过http方式连接认证中心，同时还需要访问redis，多一层网络连接，建议不采用此方式\n\n"
  },
  {
    "path": "open-oauth-center/db/init.sql",
    "content": " \n\nCREATE DATABASE IF NOT EXISTS `oauth2-security` DEFAULT CHARACTER SET = utf8mb4;\n\nUse `oauth2-security`;\n \n\nset session  \nsql_mode='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';  \n\n \n# Host: 134.224.249.39  (Version 5.7.18)\n# Date: 2018-06-01 15:28:08\n# Generator: MySQL-Front 5.4  (Build 4.153) - http://www.mysqlfront.de/\n\n/*!40101 SET NAMES utf8 */;\n\n#\n# Structure for table \"all_services\"\n#\n\nDROP TABLE IF EXISTS `all_services`;\nCREATE TABLE `all_services` (\n  `create_time` datetime DEFAULT NULL,\n  `version` int(11) DEFAULT '0',\n  `name` varchar(255) NOT NULL,\n  `path` varchar(255) NOT NULL,\n  `status` int(11) NOT NULL,\n  `catalog` varchar(255) NOT NULL,\n  `pathID` int(11) NOT NULL,\n  `apiID` varchar(255) DEFAULT NULL,\n  `desc` varchar(255) DEFAULT NULL,\n  PRIMARY KEY (`pathID`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\n#\n# Data for table \"all_services\"\n#\n\nINSERT INTO `all_services` VALUES ('2017-07-26 15:14:15',1,'公共校验-中至号码校验','/zznumbercheck',1,'bss',1,'bipxx1','公共校验-中至号码校验的描述，公共校验-中至号码校验公共校验-中至号码校验的描述，公共校验-中至号码校验'),('2017-07-26 15:16:04',1,'公共校验-黑名单与实名制校验','/blackandrealname',1,'bss',2,NULL,NULL),('2017-07-26 15:17:57',1,'网厅-23G缴费','/payfee',1,'bss',3,NULL,NULL),('2017-07-26 15:18:30',1,'全业务-流量订购','/doresources',1,'bss',4,NULL,NULL),('2017-08-16 15:03:44',1,'吉安大数据服务','/checkjian',1,'bss',5,NULL,NULL),('2017-09-04 17:58:33',1,'网厅-佣金审核','/commision',1,'bss',6,NULL,NULL),('2017-09-25 10:04:09',1,'路由查询接口','/routeinfo',1,'bss',7,NULL,NULL),('2017-09-25 10:04:51',1,'话费余额查询接口','/qryrealfeeinfo',1,'bss',8,NULL,NULL),('2017-09-25 10:05:47',1,'普通产品3G号码订购','/doo2oprod',1,'bss',9,NULL,NULL),('2017-09-25 10:06:37',1,'4G所有已订购产品查询','/ecaop.trades.query.comm.orderpro.qry',1,'bss',10,NULL,NULL),('2017-09-25 10:07:24',1,'流量产品4G号码订购','/ecaop.trades.sell.mob.comm.traffic.sub',1,'bss',11,NULL,NULL),('2017-09-25 10:13:50',1,'3G账单查询','/billqry',1,'bss',12,NULL,NULL),('2017-09-25 15:06:08',1,'免费资源查询','/qryFeePolicyAddup',1,'bss',13,NULL,NULL),('2017-09-29 15:07:13',1,'3G套餐余量与流量查询','/queryproductinfo',1,'bss',25,NULL,NULL),('2017-10-09 15:03:04',1,'4G缴费接口','/ecaop.trades.serv.payment.fee.sub',1,'bss',26,NULL,NULL),('2017-10-16 16:22:53',1,'liyuntest','/liyuntest',1,'bss',27,'',NULL),('2017-10-19 16:56:30',1,'年度账单接口','/yearbill',1,'bss',28,'',NULL),('2017-12-20 15:54:57',1,'一证五户-用户号码查询','/OneCardFiveUserSer_QryUserNumbe',1,'bss',29,'',NULL),('2017-12-20 16:09:59',1,'国政通校验_身份认证','/faceRecognition_identityCheck',1,'bss',30,'',NULL),('2017-12-27 23:54:04',1,'商品订购用户鉴权接口','/paygoodsauth',1,'bss',31,'',NULL),('2017-12-27 23:54:27',1,'商品订购订单状态查询接口','/paygoodsstatusquery',1,'bss',32,'',NULL),('2017-12-27 23:55:18',1,'商品订购接口','/paygoodsorder',1,'bss',33,'',NULL),('2017-12-28 00:28:57',1,'欠费/实时话费查询','/qryowefeeinfo',1,'bss',34,'',NULL),('2018-03-29 20:04:43',1,'中台-沃受理_订单生产回单','/bss.trades.sell.brd.produce.back',1,'bss',35,'',NULL),('2018-03-29 20:05:04',1,'中台-二维码生成查询接口','/contactcentre.QRCodeManage.createQRCodeByRequest',1,'bss',36,'',NULL),('2018-03-29 20:05:21',1,'沃受理-码上购移网信息同步接口','/mobieOrderInfoSync',1,'bss',37,'',NULL),('2018-03-29 20:05:38',1,'沃受理-码上购融合信息同步接口','/mixOrderInfoSync',1,'bss',38,'',NULL),('2018-03-29 20:05:55',1,'沃受理-预约单信息同步接口','/serviceReceiveOnlineOrde',1,'bss',39,'',NULL),('2018-03-29 20:06:11',1,'沃受理-预订单状态查询接口','/serviceOrderStatusQueryOrder',1,'bss',40,'',NULL),('2018-03-29 22:00:22',1,'AOP-CBSS号码资源查询-简单版','/ecaop.trades.query.comm.simpsnres.qry',1,'bss',41,'',NULL),('2018-03-29 22:00:39',1,'AOP-CBSS号码状态变更-简单版','/ecaop.trades.query.comm.simpsnres.chg',1,'bss',42,'',NULL),('2018-03-29 22:00:56',1,'AOP-CBSS开户处理申请接口','/ecaop.trades.sell.mob.newu.open.app',1,'bss',43,'',NULL),('2018-03-29 22:01:13',1,'AOP-CBSS开户处理提交接口','/ecaop.trades.sell.mob.newu.open.sub',1,'bss',44,'',NULL),('2018-03-29 22:01:31',1,'AOP-CBSS开户卡数据同步接口','/ecaop.trades.sell.mob.newu.opencarddate.syn',1,'bss',45,'',NULL),('2018-03-29 22:01:52',1,'AOP-CBSS写卡数据查询接口','/ecaop.trades.sell.mob.comm.carddate.qry',1,'bss',46,'',NULL),('2018-03-29 22:02:48',1,'AOP-CBSS写卡结果通知接口','/ecaop.trades.sell.mob.comm.cardres.notify',1,'bss',47,'',NULL),('2018-03-29 22:03:03',1,'AOP-CBSS订单信息同步接口','/ecaop.trades.syn.orderinfo.sub',1,'bss',48,'',NULL),('2018-03-29 22:03:20',1,'AOP-CBSS客户资料校验接口','/ecaop.trades.query.comm.cust.check',1,'bss',49,'',NULL),('2018-03-29 22:03:40',1,'AOP-CBSS终端状态查询变更-BSS用','/ecaop.trades.query.resi.term.bsschg',1,'bss',50,'',NULL),('2018-03-29 22:13:10',1,'固网装移修状态查询','/broadbandselfquery',1,'bss',51,'',NULL),('2018-03-29 22:44:57',1,'号码中心_选占','/numberCenter_selectedNum',1,'bss',52,'',NULL),('2018-03-29 22:46:14',1,'BSS客户资料校验接口','/T2000501',1,'bss',53,'',NULL);\n\n#\n# Structure for table \"client_services\"\n#\n\nDROP TABLE IF EXISTS `client_services`;\nCREATE TABLE `client_services` (\n  `service_id` varchar(255) NOT NULL,\n  `client_id` varchar(255) NOT NULL,\n  `status` int(1) NOT NULL,\n  `filter_id` varchar(20) DEFAULT NULL,\n  `latch_num` varchar(18) DEFAULT NULL,\n  `latch_type` varchar(2) DEFAULT NULL,\n  `latch_time` datetime DEFAULT NULL,\n  `latch_end` varchar(20) DEFAULT NULL,\n  UNIQUE KEY `client_services_i` (`service_id`,`client_id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\n#\n# Data for table \"client_services\"\n#\n\nINSERT INTO `client_services` VALUES ('1','9hyb3mnDQUd3dSmRhuf5',1,NULL,NULL,NULL,NULL,NULL),('1','DTt2xqJMby31XPAYchrt',1,NULL,NULL,NULL,NULL,NULL),('1','gmR1gMebojozhUsq1mRK',1,NULL,NULL,NULL,NULL,NULL),('1','KsUKSx1W1OrDD5prtJd2',1,'','',NULL,NULL,NULL),('1','LXcTfXL2cGZTDQ8ejdtt',1,NULL,NULL,NULL,NULL,NULL),('1','UgtMR61nA2mW7WuFJX57',1,'','',NULL,NULL,''),('1','YfDJIu0k1K3DuDTSuGhb',1,'','',NULL,NULL,NULL),('1','ynrAR6HDs2GiLJJAmSe1',1,NULL,NULL,NULL,NULL,NULL),('1','yvqJ1Ji5WrtLJlNCPrkC',1,'','',NULL,NULL,NULL),('10','7NctTv3kOeb8V5PXapag',2,NULL,NULL,NULL,NULL,NULL),('10','bLL6XuZA3g8mDspHvzFr',1,'','',NULL,NULL,NULL),('10','gmR1gMebojozhUsq1mRK',1,NULL,NULL,NULL,NULL,NULL),('10','hxllfenfa',1,NULL,NULL,NULL,NULL,NULL),('10','xWOpbjKtQDcop7enpBwU',1,NULL,NULL,NULL,NULL,NULL),('11','7NctTv3kOeb8V5PXapag',1,NULL,NULL,NULL,NULL,NULL),('11','bLL6XuZA3g8mDspHvzFr',1,'','',NULL,NULL,NULL),('11','hxllfenfa',1,NULL,NULL,NULL,NULL,NULL),('11','xWOpbjKtQDcop7enpBwU',1,NULL,NULL,NULL,NULL,NULL),('12','bLL6XuZA3g8mDspHvzFr',1,'','',NULL,NULL,NULL),('2','gmR1gMebojozhUsq1mRK',1,NULL,NULL,NULL,NULL,NULL),('2','KsUKSx1W1OrDD5prtJd2',1,'','',NULL,NULL,NULL),('2','LXcTfXL2cGZTDQ8ejdtt',1,NULL,NULL,NULL,NULL,NULL),('2','UgtMR61nA2mW7WuFJX57',1,'','',NULL,NULL,NULL),('2','YfDJIu0k1K3DuDTSuGhb',1,'','',NULL,NULL,NULL),('2','yvqJ1Ji5WrtLJlNCPrkC',1,'','',NULL,NULL,NULL),('25','bLL6XuZA3g8mDspHvzFr',1,'','',NULL,NULL,NULL),('26','YfDJIu0k1K3DuDTSuGhb',1,'','',NULL,NULL,NULL),('29','jxbss_zt',1,NULL,NULL,NULL,NULL,NULL),('29','LSsMdMUIjQ8Gwqy8fXwS',1,NULL,NULL,NULL,NULL,NULL),('3','gmR1gMebojozhUsq1mRK',1,NULL,NULL,NULL,NULL,NULL),('3','UgtMR61nA2mW7WuFJX57',1,'','',NULL,NULL,NULL),('3','YfDJIu0k1K3DuDTSuGhb',1,'','',NULL,NULL,NULL),('30','jxbss_zt',1,NULL,NULL,NULL,NULL,NULL),('30','LSsMdMUIjQ8Gwqy8fXwS',1,NULL,NULL,NULL,NULL,NULL),('31','Irb7fPzXSJKJRUBp1o9m',1,NULL,NULL,NULL,NULL,NULL),('32','Irb7fPzXSJKJRUBp1o9m',1,NULL,NULL,NULL,NULL,NULL),('33','Irb7fPzXSJKJRUBp1o9m',1,NULL,NULL,NULL,NULL,NULL),('34','7NctTv3kOeb8V5PXapag',1,NULL,NULL,NULL,NULL,NULL),('34','xWOpbjKtQDcop7enpBwU',1,NULL,NULL,NULL,NULL,NULL),('35','LSsMdMUIjQ8Gwqy8fXwS',1,NULL,NULL,NULL,NULL,NULL),('36','LSsMdMUIjQ8Gwqy8fXwS',1,NULL,NULL,NULL,NULL,NULL),('37','jxbss_zt',1,NULL,NULL,NULL,NULL,NULL),('38','jxbss_zt',1,NULL,NULL,NULL,NULL,NULL),('39','jxbss_zt',1,NULL,NULL,NULL,NULL,NULL),('4','bLL6XuZA3g8mDspHvzFr',1,'','',NULL,NULL,NULL),('4','gmR1gMebojozhUsq1mRK',1,NULL,NULL,NULL,NULL,NULL),('4','UgtMR61nA2mW7WuFJX57',1,'1','1','6','2017-10-13 11:09:20','100'),('4','YfDJIu0k1K3DuDTSuGhb',1,'','',NULL,NULL,NULL),('40','jxbss_zt',1,NULL,NULL,NULL,NULL,NULL),('41','jxbss_zt',1,NULL,NULL,NULL,NULL,NULL),('42','jxbss_zt',1,NULL,NULL,NULL,NULL,NULL),('43','jxbss_zt',1,NULL,NULL,NULL,NULL,NULL),('44','jxbss_zt',1,NULL,NULL,NULL,NULL,NULL),('45','jxbss_zt',1,NULL,NULL,NULL,NULL,NULL),('46','jxbss_zt',1,NULL,NULL,NULL,NULL,NULL),('47','jxbss_zt',1,NULL,NULL,NULL,NULL,NULL),('48','jxbss_zt',1,NULL,NULL,NULL,NULL,NULL),('49','jxbss_zt',1,NULL,NULL,NULL,NULL,NULL),('5','3PVKhw072sLvwxlsHqUi',1,'','',NULL,NULL,NULL),('5','dMJuf873pL91xHME5BH0',1,'','',NULL,NULL,NULL),('5','gmR1gMebojozhUsq1mRK',1,NULL,NULL,NULL,NULL,NULL),('5','HwChS6qfl7IsJen3hvsK',2,'','',NULL,NULL,NULL),('5','pt9sD1xsiq9WO0mdptAh',1,'','',NULL,NULL,NULL),('5','q12XZwmdmLB4xRz31PJp',1,'','',NULL,NULL,NULL),('5','w0rYW674932e9HUvs3MN',1,'','',NULL,NULL,NULL),('5','xwQLurzJcOlA6CdZWOQz',1,'','',NULL,NULL,NULL),('5','YI9dJdJLxlHg7H15u16u',1,'','',NULL,NULL,NULL),('50','jxbss_zt',1,NULL,NULL,NULL,NULL,NULL),('51','jxbss_zt',1,NULL,NULL,NULL,NULL,NULL),('52','jxbss_zt',1,NULL,NULL,NULL,NULL,NULL),('53','jxbss_zt',1,NULL,NULL,NULL,NULL,NULL),('6','2Tl9bfPmGVS8d7YSn3Xd',2,'','',NULL,NULL,NULL),('6','EroXhe2qMnijGxhFlh75',1,'','',NULL,NULL,NULL),('6','gmR1gMebojozhUsq1mRK',1,NULL,NULL,NULL,NULL,NULL),('6','LSsMdMUIjQ8Gwqy8fXwS',1,'','',NULL,NULL,NULL),('7','7NctTv3kOeb8V5PXapag',1,NULL,NULL,NULL,NULL,NULL),('7','bLL6XuZA3g8mDspHvzFr',1,'','',NULL,NULL,NULL),('7','gmR1gMebojozhUsq1mRK',1,NULL,NULL,NULL,NULL,NULL),('7','GzIBYtFz2wWQ36dI1OMB',1,'','',NULL,NULL,NULL),('7','hxllfenfa',1,NULL,NULL,NULL,NULL,NULL),('7','UgtMR61nA2mW7WuFJX57',1,'','',NULL,NULL,NULL),('7','xWOpbjKtQDcop7enpBwU',1,NULL,NULL,NULL,NULL,NULL),('7','YfDJIu0k1K3DuDTSuGhb',1,'','',NULL,NULL,NULL),('8','bLL6XuZA3g8mDspHvzFr',1,'','',NULL,NULL,NULL),('8','gmR1gMebojozhUsq1mRK',1,NULL,NULL,NULL,NULL,NULL),('9','bLL6XuZA3g8mDspHvzFr',1,'','',NULL,NULL,NULL),('9','gmR1gMebojozhUsq1mRK',1,NULL,NULL,NULL,NULL,NULL);\n\n#\n# Structure for table \"gateway_api_define\"\n#\n\nDROP TABLE IF EXISTS `gateway_api_define`;\nCREATE TABLE `gateway_api_define` (\n  `id` varchar(50) NOT NULL,\n  `path` varchar(255) NOT NULL,\n  `service_id` varchar(50) DEFAULT NULL,\n  `url` varchar(255) DEFAULT NULL,\n  `retryable` tinyint(1) DEFAULT NULL,\n  `enabled` tinyint(1) NOT NULL,\n  `strip_prefix` int(11) DEFAULT NULL,\n  `api_name` varchar(255) DEFAULT NULL,\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\n#\n# Data for table \"gateway_api_define\"\n#\n\nINSERT INTO `gateway_api_define` VALUES ('authentication-center','/auth/**','open-auth-server',NULL,0,1,1,NULL),('test163','/test163/**',NULL,'http://www.163.com',0,1,1,NULL),('test164','/test164/**',NULL,'http://www.baidu.com',0,1,1,NULL),('web','/web',NULL,'http://127.0.0.1:9999',0,1,0,NULL);\n\n#\n# Structure for table \"oauth_access_token\"\n#\n\nDROP TABLE IF EXISTS `oauth_access_token`;\nCREATE TABLE `oauth_access_token` (\n  `token_id` varchar(256) DEFAULT NULL,\n  `token` blob,\n  `authentication_id` varchar(48) NOT NULL,\n  `user_name` varchar(256) DEFAULT NULL,\n  `client_id` varchar(256) DEFAULT NULL,\n  `authentication` blob,\n  `refresh_token` varchar(256) DEFAULT NULL,\n  PRIMARY KEY (`authentication_id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\n#\n# Data for table \"oauth_access_token\"\n#\n\n\n#\n# Structure for table \"oauth_approvals\"\n#\n\nDROP TABLE IF EXISTS `oauth_approvals`;\nCREATE TABLE `oauth_approvals` (\n  `userId` varchar(256) DEFAULT NULL,\n  `clientId` varchar(256) DEFAULT NULL,\n  `scope` varchar(256) DEFAULT NULL,\n  `status` varchar(10) DEFAULT NULL,\n  `expiresAt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n  `lastModifiedAt` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\n#\n# Data for table \"oauth_approvals\"\n#\n\n\n#\n# Structure for table \"oauth_client_details\"\n#\n\nDROP TABLE IF EXISTS `oauth_client_details`;\nCREATE TABLE `oauth_client_details` (\n  `client_id` varchar(48) NOT NULL,\n  `resource_ids` varchar(256) DEFAULT NULL,\n  `client_secret` varchar(256) DEFAULT NULL,\n  `scope` varchar(256) DEFAULT NULL,\n  `authorized_grant_types` varchar(256) DEFAULT NULL,\n  `web_server_redirect_uri` varchar(256) DEFAULT NULL,\n  `authorities` varchar(256) DEFAULT NULL,\n  `access_token_validity` int(11) DEFAULT NULL,\n  `refresh_token_validity` int(11) DEFAULT NULL,\n  `additional_information` varchar(4096) DEFAULT NULL,\n  `autoapprove` varchar(256) DEFAULT NULL,\n  `lastModifiedAt` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n  PRIMARY KEY (`client_id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\n#\n# Data for table \"oauth_client_details\"\n#\n\nINSERT INTO `oauth_client_details` VALUES ('app','','app','app','password,refresh_token',NULL,NULL,1800,1800,'{}','true','0000-00-00 00:00:00'),('hello','','hello','app','password,refresh_token',NULL,NULL,1800,1800,'{}','true','0000-00-00 00:00:00'),('mobile','','mobile','all','password,refresh_token',NULL,NULL,1800,1800,'{}','true','0000-00-00 00:00:00'),('owen',NULL,'owen','app','authorization_code,password,refresh_token,client_credentials','http://127.0.0.1:9997/clientOne/login',NULL,1800,1800,'{}','true','0000-00-00 00:00:00'),('test','','test','test','password,refresh_token',NULL,NULL,1800,1800,'{}','true','0000-00-00 00:00:00'),('webApp','','webApp','app','authorization_code,password,refresh_token,client_credentials','http://www.baidu.com',NULL,1800,1800,'{}','true','0000-00-00 00:00:00');\n\n#\n# Structure for table \"oauth_client_token\"\n#\n\nDROP TABLE IF EXISTS `oauth_client_token`;\nCREATE TABLE `oauth_client_token` (\n  `token_id` varchar(256) DEFAULT NULL,\n  `token` blob,\n  `authentication_id` varchar(48) NOT NULL,\n  `user_name` varchar(256) DEFAULT NULL,\n  `client_id` varchar(256) DEFAULT NULL,\n  PRIMARY KEY (`authentication_id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\n#\n# Data for table \"oauth_client_token\"\n#\n\n\n#\n# Structure for table \"oauth_code\"\n#\n\nDROP TABLE IF EXISTS `oauth_code`;\nCREATE TABLE `oauth_code` (\n  `code` varchar(256) DEFAULT NULL,\n  `authentication` blob\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\n#\n# Data for table \"oauth_code\"\n#\n\n\n#\n# Structure for table \"oauth_refresh_token\"\n#\n\nDROP TABLE IF EXISTS `oauth_refresh_token`;\nCREATE TABLE `oauth_refresh_token` (\n  `token_id` varchar(256) DEFAULT NULL,\n  `token` blob,\n  `authentication` blob\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\n#\n# Data for table \"oauth_refresh_token\"\n#\n\n"
  },
  {
    "path": "open-oauth-center/open-oauth-client/.gitignore",
    "content": "/bin/\n"
  },
  {
    "path": "open-oauth-center/open-oauth-client/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\t<parent>\n\t\t<groupId>com.open.capacity</groupId>\n\t\t<artifactId>open-oauth-center</artifactId>\n\t\t<version>0.0.1-SNAPSHOT</version>\n\t</parent>\n\t<artifactId>open-oauth-client</artifactId>\n\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-eureka</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-actuator</artifactId>\n\t\t</dependency>\n\t</dependencies>\n</project>"
  },
  {
    "path": "open-oauth-center/open-oauth-client/src/main/java/com/open/capacity/UnieapAuthServerApp.java",
    "content": "/**\n *\n */\npackage com.open.capacity;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.client.discovery.EnableDiscoveryClient;\nimport org.springframework.context.annotation.Configuration;\n\n/**\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2018年4月5日 下午19:52:21\n * 类说明\n */\n\n\n@Configuration\n@EnableDiscoveryClient\n@SpringBootApplication\npublic class UnieapAuthServerApp {\n\n    public static void main(String[] args) {\n        SpringApplication.run(UnieapAuthServerApp.class, args);\n    }\n\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-client/src/main/java/com/open/capacity/client/oauth2/OAuth2ClientConfig.java",
    "content": "package com.open.capacity.client.oauth2;\n\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;\nimport org.springframework.security.config.annotation.web.builders.HttpSecurity;\nimport org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;\nimport org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;\nimport org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;\nimport org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler;\nimport org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler;\nimport org.springframework.security.oauth2.provider.token.TokenStore;\nimport org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;\nimport org.springframework.security.oauth2.provider.token.store.JwtTokenStore;\nimport org.springframework.security.web.AuthenticationEntryPoint;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.Resource;\n\n/**\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2018年4月5日 下午19:52:21\n */\n@Component\n@Configuration\n@EnableResourceServer\n//开启spring security 注解\n@EnableGlobalMethodSecurity(prePostEnabled = true)\npublic class OAuth2ClientConfig extends ResourceServerConfigurerAdapter {\n\n\n    //对应oauth_client_details的 resource_ids字段 如果表中有数据 client_id只能访问响应resource_ids的资源服务器\n    private static final String DEMO_RESOURCE_ID = \"test\";\n\n    @Resource\n    private ObjectMapper objectMapper; //springmvc启动时自动装配json处理类\n\n    @Autowired(required = false)\n    private TokenStore redisTokenStore;\n\n    @Autowired(required = false)\n    private JwtTokenStore jwtTokenStore;\n    @Autowired(required = false)\n    private JwtAccessTokenConverter jwtAccessTokenConverter;\n\n\n    @Autowired\n    private AuthenticationEntryPoint authenticationEntryPoint;\n\n    @Autowired\n    private OAuth2WebSecurityExpressionHandler expressionHandler;\n    @Autowired\n    private OAuth2AccessDeniedHandler oAuth2AccessDeniedHandler;\n\n    @Override\n    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {\n\n        if (jwtTokenStore != null) {\n            resources.tokenStore(jwtTokenStore);\n        } else if (redisTokenStore != null) {\n            resources.tokenStore(redisTokenStore);\n        }\n        resources.resourceId(DEMO_RESOURCE_ID).stateless(true);\n\n        resources.authenticationEntryPoint(authenticationEntryPoint);\n\n        resources.expressionHandler(expressionHandler);\n        resources.accessDeniedHandler(oAuth2AccessDeniedHandler);\n    }\n\n    @Override\n    public void configure(HttpSecurity http) throws Exception {\n\n\n        http.csrf().disable().exceptionHandling().authenticationEntryPoint(authenticationEntryPoint)\n                .and().authorizeRequests().anyRequest().authenticated().and().httpBasic();\n\n\n    }\n\n\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-client/src/main/java/com/open/capacity/client/oauth2/authorize/AuthorizeConfigManager.java",
    "content": "package com.open.capacity.client.oauth2.authorize;\n\nimport org.springframework.security.config.annotation.web.builders.HttpSecurity;\nimport org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;\n\n/**\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2018年4月5日 下午19:52:21\n * 类说明\n */\npublic interface AuthorizeConfigManager {\n\n    /**\n     * @param config\n     */\n    void config(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry config);\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-client/src/main/java/com/open/capacity/client/oauth2/authorize/AuthorizeConfigProvider.java",
    "content": "package com.open.capacity.client.oauth2.authorize;\n\nimport org.springframework.security.config.annotation.web.builders.HttpSecurity;\nimport org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;\n\n/**\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2018年4月5日 下午19:52:21\n * 类说明\n */\npublic interface AuthorizeConfigProvider {\n\n    boolean config(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry config);\n\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-client/src/main/java/com/open/capacity/client/oauth2/authorize/OpenAuthorizeConfigManager.java",
    "content": "package com.open.capacity.client.oauth2.authorize;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.security.config.annotation.web.builders.HttpSecurity;\nimport org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;\nimport org.springframework.stereotype.Component;\n\nimport java.util.List;\n\n/**\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2018年4月5日 下午19:52:21\n * 类说明\n */\n@Component\npublic class OpenAuthorizeConfigManager implements AuthorizeConfigManager {\n\n    @Autowired\n    private List<AuthorizeConfigProvider> authorizeConfigProviders;\n\n    /* (non-Javadoc)\n     * @see com.imooc.security.core.authorize.AuthorizeConfigManager#config(org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry)\n     */\n    @Override\n    public void config(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry config) {\n\n        //设置访问\n        for (AuthorizeConfigProvider authorizeConfigProvider : authorizeConfigProviders) {\n            authorizeConfigProvider.config(config);\n        }\n        config\n                .anyRequest()\n                .access(\"@rbacService.hasPermission(request, authentication)\");\n    }\n\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-client/src/main/java/com/open/capacity/client/oauth2/authorize/provider/AuthAuthorizeConfigProvider.java",
    "content": "package com.open.capacity.client.oauth2.authorize.provider;\n\nimport com.open.capacity.client.oauth2.authorize.AuthorizeConfigProvider;\nimport org.springframework.core.annotation.Order;\nimport org.springframework.security.config.annotation.web.builders.HttpSecurity;\nimport org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;\nimport org.springframework.stereotype.Component;\n\n/**\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2018年4月5日 下午19:52:21\n * 类说明\n */\n@Component\n@Order(Integer.MAX_VALUE - 1)\npublic class AuthAuthorizeConfigProvider implements AuthorizeConfigProvider {\n\n    @Override\n    public boolean config(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry config) {\n\n        config.anyRequest().authenticated();\n        return true;\n    }\n\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-client/src/main/java/com/open/capacity/client/oauth2/config/SecurityHandlerConfig.java",
    "content": "package com.open.capacity.client.oauth2.config;\n\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.security.access.AccessDeniedException;\nimport org.springframework.security.core.AuthenticationException;\nimport org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler;\nimport org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler;\nimport org.springframework.security.web.AuthenticationEntryPoint;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.Resource;\nimport javax.servlet.ServletException;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport java.io.IOException;\nimport java.util.HashMap;\nimport java.util.Map;\n\n\n/**\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2018年4月5日 下午19:52:21\n * 类说明\n */\n@Component\n@Configuration\npublic class SecurityHandlerConfig {\n\n    @Resource\n    private ObjectMapper objectMapper; //springmvc启动时自动装配json处理类\n\n\n    /**\n     * 未登录，返回401\n     *\n     * @return\n     */\n    @Bean\n    public AuthenticationEntryPoint authenticationEntryPoint() {\n        return new AuthenticationEntryPoint() {\n\n            @Override\n            public void commence(HttpServletRequest request, HttpServletResponse response,\n                                 AuthenticationException authException) throws IOException, ServletException {\n\n                Map<String, String> rsp = new HashMap<>();\n\n                response.setStatus(HttpStatus.UNAUTHORIZED.value());\n\n                rsp.put(\"resp_code\", HttpStatus.UNAUTHORIZED.value() + \"\");\n                rsp.put(\"resp_msg\", authException.getMessage());\n\n                response.setContentType(\"application/json;charset=UTF-8\");\n                response.getWriter().write(objectMapper.writeValueAsString(rsp));\n                response.getWriter().flush();\n                response.getWriter().close();\n\n            }\n        };\n    }\n\n    @Bean\n    public OAuth2WebSecurityExpressionHandler oAuth2WebSecurityExpressionHandler(ApplicationContext applicationContext) {\n        OAuth2WebSecurityExpressionHandler expressionHandler = new OAuth2WebSecurityExpressionHandler();\n        expressionHandler.setApplicationContext(applicationContext);\n        return expressionHandler;\n    }\n\n    @Bean\n    public OAuth2AccessDeniedHandler oAuth2AccessDeniedHandler() {\n        return new OAuth2AccessDeniedHandler() {\n\n            @Override\n            public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException authException) throws IOException, ServletException {\n\n                Map<String, String> rsp = new HashMap<>();\n                response.setContentType(\"application/json;charset=UTF-8\");\n\n                response.setStatus(HttpStatus.UNAUTHORIZED.value());\n\n                rsp.put(\"resp_code\", HttpStatus.UNAUTHORIZED.value() + \"\");\n                rsp.put(\"resp_msg\", authException.getMessage());\n\n                response.setContentType(\"application/json;charset=UTF-8\");\n                response.getWriter().write(objectMapper.writeValueAsString(rsp));\n                response.getWriter().flush();\n                response.getWriter().close();\n\n            }\n        };\n    }\n\n\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-client/src/main/java/com/open/capacity/client/oauth2/service/RbacService.java",
    "content": "package com.open.capacity.client.oauth2.service;\n\nimport org.springframework.security.core.Authentication;\n\nimport javax.servlet.http.HttpServletRequest;\n\n/**\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2018年4月5日 下午19:52:21\n * 类说明\n */\npublic interface RbacService {\n\n    boolean hasPermission(HttpServletRequest request, Authentication authentication);\n\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-client/src/main/java/com/open/capacity/client/oauth2/service/impl/RbacServiceImpl.java",
    "content": "/**\n *\n */\npackage com.open.capacity.client.oauth2.service.impl;\n\nimport com.open.capacity.client.oauth2.service.RbacService;\nimport org.springframework.security.core.Authentication;\nimport org.springframework.stereotype.Service;\nimport org.springframework.util.AntPathMatcher;\n\nimport javax.servlet.http.HttpServletRequest;\n\n/**\n * @param request        HttpServletRequest\n * @param authentication 认证信息\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2018年4月5日 下午19:52:21\n * 类说明\n * @return 是否有权限\n */\n\n@Service(\"rbacService\")\npublic class RbacServiceImpl implements RbacService {\n\n    private AntPathMatcher antPathMatcher = new AntPathMatcher();\n\n    @Override\n    public boolean hasPermission(HttpServletRequest request, Authentication authentication) {\n        Object principal = authentication.getPrincipal();\n\n        boolean hasPermission = true;\n\n\n        return hasPermission;\n    }\n\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-client/src/main/java/com/open/capacity/client/oauth2/token/TokenStoreConfig.java",
    "content": "package com.open.capacity.client.oauth2.token;\n\nimport com.open.capacity.client.oauth2.token.store.RedisTemplateTokenStore;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.data.redis.core.RedisTemplate;\nimport org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;\nimport org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;\nimport org.springframework.security.oauth2.provider.token.store.JwtTokenStore;\n\nimport javax.annotation.Resource;\nimport javax.sql.DataSource;\n\n/**\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2018年4月5日 下午19:52:21\n * 类说明\n * redis存储token\n */\n@Configuration\npublic class TokenStoreConfig {\n\n    @Resource\n    private DataSource dataSource;\n\n    @Autowired(required = false)\n    private RedisTemplate<String, Object> redisTemplate;\n\n\n    @Bean\n    @ConditionalOnProperty(prefix = \"security.oauth2.token.store\", name = \"type\", havingValue = \"jdbc\", matchIfMissing = true)\n    public JdbcTokenStore jdbcTokenStore() {\n\n//\t\toauth_access_token oauth_refresh_token 创建两张表\n//\t\treturn new JdbcTokenStore( dataSource ) ;\n        return new JdbcTokenStore(dataSource);\n\n    }\n\n    @Bean\n    @ConditionalOnProperty(prefix = \"security.oauth2.token.store\", name = \"type\", havingValue = \"redis\", matchIfMissing = true)\n    public RedisTemplateTokenStore redisTokenStore() {\n//\t\treturn new RedisTokenStore( redisTemplate.getConnectionFactory() ) ; //单台redis服务器\n\n\n        RedisTemplateTokenStore redisTemplateStore = new RedisTemplateTokenStore();\n        redisTemplateStore.setRedisTemplate(redisTemplate);\n        return redisTemplateStore;\n\n\n    }\n\n    //使用jwt替换原有的uuid生成token方式\n    @Configuration\n    @ConditionalOnProperty(prefix = \"security.oauth2.token.store\", name = \"type\", havingValue = \"jwt\", matchIfMissing = true)\n    public static class JWTTokenConfig {\n        @Bean\n        public JwtTokenStore jwtTokenStore() {\n            return new JwtTokenStore(jwtAccessTokenConverter());\n        }\n\n        @Bean\n        public JwtAccessTokenConverter jwtAccessTokenConverter() {\n            JwtAccessTokenConverter accessTokenConverter = new JwtAccessTokenConverter();\n            accessTokenConverter.setSigningKey(\"neusoft\");\n            return accessTokenConverter;\n        }\n    }\n\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-client/src/main/java/com/open/capacity/client/oauth2/token/store/RedisTemplateTokenStore.java",
    "content": "package com.open.capacity.client.oauth2.token.store;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.concurrent.TimeUnit;\n\nimport org.springframework.data.redis.core.RedisTemplate;\nimport org.springframework.security.oauth2.common.ExpiringOAuth2RefreshToken;\nimport org.springframework.security.oauth2.common.OAuth2AccessToken;\nimport org.springframework.security.oauth2.common.OAuth2RefreshToken;\nimport org.springframework.security.oauth2.provider.OAuth2Authentication;\nimport org.springframework.security.oauth2.provider.token.AuthenticationKeyGenerator;\nimport org.springframework.security.oauth2.provider.token.DefaultAuthenticationKeyGenerator;\nimport org.springframework.security.oauth2.provider.token.TokenStore;\n\n/** \n* @author owen 624191343@qq.com\n * @version 创建时间：2017年11月12日 上午22:57:51\n* 类说明 \n* redis集群存储token\n*/\n \npublic class RedisTemplateTokenStore implements TokenStore {\n\t\n\tprivate static final String ACCESS = \"access:\";\n\tprivate static final String AUTH_TO_ACCESS = \"auth_to_access:\";\n\tprivate static final String AUTH = \"auth:\";\n\tprivate static final String REFRESH_AUTH = \"refresh_auth:\";\n\tprivate static final String ACCESS_TO_REFRESH = \"access_to_refresh:\";\n\tprivate static final String REFRESH = \"refresh:\";\n\tprivate static final String REFRESH_TO_ACCESS = \"refresh_to_access:\";\n\tprivate static final String CLIENT_ID_TO_ACCESS = \"client_id_to_access:\";\n\tprivate static final String UNAME_TO_ACCESS = \"uname_to_access:\";\n\t\n\n\tprivate RedisTemplate<String,Object> redisTemplate ;\n\t\n\tpublic RedisTemplate<String,Object> getRedisTemplate() {\n\t\treturn redisTemplate;\n\t}\n\n\tpublic void setRedisTemplate(RedisTemplate<String,Object> redisTemplate) {\n\t\tthis.redisTemplate = redisTemplate;\n\t}\n\n\n\tprivate AuthenticationKeyGenerator authenticationKeyGenerator = new DefaultAuthenticationKeyGenerator();\n\n\n\n\t \n\tpublic void setAuthenticationKeyGenerator(AuthenticationKeyGenerator authenticationKeyGenerator) {\n\t\tthis.authenticationKeyGenerator = authenticationKeyGenerator;\n\t}\n\n\t \n\tpublic OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) {\n\t\tString key = authenticationKeyGenerator.extractKey(authentication);\n\t\tOAuth2AccessToken accessToken = (OAuth2AccessToken) redisTemplate.opsForValue().get(AUTH_TO_ACCESS+key);\n\t\tif (accessToken != null\n\t\t\t\t&& !key.equals(authenticationKeyGenerator.extractKey(readAuthentication(accessToken.getValue())))) {\n\t\t\t// Keep the stores consistent (maybe the same user is represented by this authentication but the details\n\t\t\t// have changed)\n\t\t\tstoreAccessToken(accessToken, authentication);\n\t\t}\n\t\treturn accessToken;\n\t}\n\tpublic OAuth2Authentication readAuthentication(OAuth2AccessToken token) {\n\t\treturn readAuthentication(token.getValue());\n\t}\n\tpublic OAuth2Authentication readAuthentication(String token) {\n\t\treturn (OAuth2Authentication) this.redisTemplate.opsForValue().get(AUTH +  token);\n\t}\n\tpublic OAuth2Authentication readAuthenticationForRefreshToken(OAuth2RefreshToken token) {\n\t\treturn readAuthenticationForRefreshToken(token.getValue());\n\t}\n\tpublic OAuth2Authentication readAuthenticationForRefreshToken(String token) {\n\t\treturn (OAuth2Authentication) this.redisTemplate.opsForValue().get( REFRESH_AUTH+token);\n\t}\n\tpublic void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) {\n\t\t\n\t\tOAuth2AccessToken existingAccessToken = this.getAccessToken(authentication);\n\t\t\n\t\tthis.redisTemplate.opsForValue().set(ACCESS+ token.getValue(), token);\n\t\tthis.redisTemplate.opsForValue().set(AUTH +token.getValue(), authentication);\n\t\tthis.redisTemplate.opsForValue().set(AUTH_TO_ACCESS+authenticationKeyGenerator.extractKey(authentication), token);\n\t\t\n\t\tif (!authentication.isClientOnly()) {\n\t\t\tif (existingAccessToken != null) {\n\t\t\t\tif (!existingAccessToken.isExpired()) {\n\t\t\t\t\tint seconds = token.getExpiresIn();\n\t\t\t\t\tredisTemplate.expire(UNAME_TO_ACCESS+authentication.getOAuth2Request().getClientId(), seconds, TimeUnit.SECONDS) ;\n\t\t\t\t}else{\n\t\t\t\t\tredisTemplate.opsForList().rightPush(UNAME_TO_ACCESS+getApprovalKey(authentication), token) ;\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\tredisTemplate.opsForList().rightPush(UNAME_TO_ACCESS+getApprovalKey(authentication), token) ;\n\t\t\t}\n\t\t\t\t\t\n\t\t\t\n\t\t\t\n\t\t}\n\t\t\n\t\t\n\t\tif (existingAccessToken != null) {\n\t\t\tif (!existingAccessToken.isExpired()) {\n\t\t\t\tint seconds = token.getExpiresIn();\n\t\t\t\tredisTemplate.expire(CLIENT_ID_TO_ACCESS+authentication.getOAuth2Request().getClientId(), seconds, TimeUnit.SECONDS) ;\n\t\t\t\t\n\t\t\t}else{\n\t\t\t\tredisTemplate.opsForList().rightPush(CLIENT_ID_TO_ACCESS+authentication.getOAuth2Request().getClientId(), token) ;\n\t\t\t}\n\t\t}else{\n\t\t\tredisTemplate.opsForList().rightPush(CLIENT_ID_TO_ACCESS+authentication.getOAuth2Request().getClientId(), token) ;\n\t\t}\n\t\t\n\t\t\n\t\t\n\t\tif (token.getExpiration() != null) {\n\t\t\t  \n\t\t\tint seconds = token.getExpiresIn();\n\t\t\tredisTemplate.expire(ACCESS+ token.getValue(), seconds, TimeUnit.SECONDS) ;\n\t\t\tredisTemplate.expire(AUTH+ token.getValue(), seconds, TimeUnit.SECONDS) ;\n\t\t\t\n\t\t\tredisTemplate.expire(AUTH_TO_ACCESS+ authenticationKeyGenerator.extractKey(authentication), seconds, TimeUnit.SECONDS) ;\n\t\t\tredisTemplate.expire(CLIENT_ID_TO_ACCESS+authentication.getOAuth2Request().getClientId(), seconds, TimeUnit.SECONDS) ;\n\t\t\tredisTemplate.expire(UNAME_TO_ACCESS+ getApprovalKey(authentication), seconds, TimeUnit.SECONDS) ;\n\t\t}\n\t\t\n\t\tOAuth2RefreshToken refreshToken = token.getRefreshToken();\n\t\t\n\t\tif (token.getRefreshToken() != null && token.getRefreshToken().getValue() != null) {\n\t\t\tthis.redisTemplate.opsForValue().set( REFRESH_TO_ACCESS+   token.getRefreshToken().getValue(), token.getValue());\n\t\t\tthis.redisTemplate.opsForValue().set(ACCESS_TO_REFRESH+token.getValue(), token.getRefreshToken().getValue());\n\t\t\t\n\t\t\t\n\t\t\tif (refreshToken instanceof ExpiringOAuth2RefreshToken) {\n\t\t\t\tExpiringOAuth2RefreshToken expiringRefreshToken = (ExpiringOAuth2RefreshToken) refreshToken;\n\t\t\t\tDate expiration = expiringRefreshToken.getExpiration();\n\t\t\t\tif (expiration != null) {\n\t\t\t\t\tint seconds = Long.valueOf((expiration.getTime() - System.currentTimeMillis()) / 1000L)\n\t\t\t\t\t\t\t.intValue();\n\t\t\t\t\t\n\t\t\t\t\tredisTemplate.expire( REFRESH_TO_ACCESS+   token.getRefreshToken().getValue() , seconds, TimeUnit.SECONDS) ;\n\t\t\t\t\tredisTemplate.expire( ACCESS_TO_REFRESH+token.getValue(), seconds, TimeUnit.SECONDS) ;\n\t \n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t\n\t\t}\n\t}\n\n\tprivate String getApprovalKey(OAuth2Authentication authentication) {\n\t\tString userName = authentication.getUserAuthentication() == null ? \"\" : authentication.getUserAuthentication()\n\t\t\t\t.getName();\n\t\treturn getApprovalKey(authentication.getOAuth2Request().getClientId(), userName);\n\t}\n\n\tprivate String getApprovalKey(String clientId, String userName) {\n\t\treturn clientId + (userName==null ? \"\" : \":\" + userName);\n\t}\n\n\t \n\n\tpublic void removeAccessToken(OAuth2AccessToken accessToken) {\n\t\tremoveAccessToken(accessToken.getValue());\n\t}\n\n\tpublic OAuth2AccessToken readAccessToken(String tokenValue) {\n\t\treturn (OAuth2AccessToken) this.redisTemplate.opsForValue().get(ACCESS+tokenValue);\n\t}\n\n\tpublic void removeAccessToken(String tokenValue) {\n\t\tOAuth2AccessToken removed = (OAuth2AccessToken) redisTemplate.opsForValue().get(ACCESS+tokenValue);\n\t\t// Don't remove the refresh token - it's up to the caller to do that\n\t\tOAuth2Authentication authentication = (OAuth2Authentication) this.redisTemplate.opsForValue().get(AUTH+tokenValue);\n\t\t\n\t\t\n\t\tthis.redisTemplate.delete(AUTH+tokenValue);\n\t\tredisTemplate.delete(ACCESS+tokenValue);\n\t\tthis.redisTemplate.delete(ACCESS_TO_REFRESH +tokenValue);\n\t\t\n\t\t\n\t\tif (authentication != null) {\n\t\t\tthis.redisTemplate.delete(AUTH_TO_ACCESS+authenticationKeyGenerator.extractKey(authentication));\n\t\t\n\t\t\tString clientId = authentication.getOAuth2Request().getClientId();\n\t\t\t\n//\t\t\tredisTemplate.opsForList().rightPush(\"UNAME_TO_ACCESS:\"+getApprovalKey(authentication), token) ;\n\t\t\tredisTemplate.opsForList().leftPop(UNAME_TO_ACCESS+getApprovalKey(clientId, authentication.getName()));\n\t\t\t\n\t\t\tredisTemplate.opsForList().leftPop(CLIENT_ID_TO_ACCESS+clientId);\n\t\t\t\n\t\t\tthis.redisTemplate.delete(AUTH_TO_ACCESS+authenticationKeyGenerator.extractKey(authentication));\n\t\t}\n\t}\n\n\tpublic void storeRefreshToken(OAuth2RefreshToken refreshToken, OAuth2Authentication authentication) {\n\t\tthis.redisTemplate.opsForValue().set(REFRESH+refreshToken.getValue(), refreshToken);\n\t\tthis.redisTemplate.opsForValue().set( REFRESH_AUTH + refreshToken.getValue(), authentication);\n\t}\n\n\tpublic OAuth2RefreshToken readRefreshToken(String tokenValue) {\n\t\treturn (OAuth2RefreshToken) this.redisTemplate.opsForValue().get(REFRESH+tokenValue);\n\t}\n\n\tpublic void removeRefreshToken(OAuth2RefreshToken refreshToken) {\n\t\tremoveRefreshToken(refreshToken.getValue());\n\t}\n\n\tpublic void removeRefreshToken(String tokenValue) {\n\t\tthis.redisTemplate.delete( REFRESH + tokenValue);\n\t\tthis.redisTemplate.delete( REFRESH_AUTH + tokenValue);\n\t\tthis.redisTemplate.delete(REFRESH_TO_ACCESS +tokenValue);\n\t}\n\n\tpublic void removeAccessTokenUsingRefreshToken(OAuth2RefreshToken refreshToken) {\n\t\tremoveAccessTokenUsingRefreshToken(refreshToken.getValue());\n\t}\n\n\tprivate void removeAccessTokenUsingRefreshToken(String refreshToken) {\n\t\t\n\t\tString token = (String) this.redisTemplate.opsForValue().get( REFRESH_TO_ACCESS  +refreshToken) ;\n\t\t\n\t\tif (token != null) {\n\t\t\tredisTemplate.delete(REFRESH_TO_ACCESS+ refreshToken);\n\t\t}\n\t}\n\n\tpublic Collection<OAuth2AccessToken> findTokensByClientIdAndUserName(String clientId, String userName) {\n\t\tList<Object> result =    redisTemplate.opsForList().range(UNAME_TO_ACCESS+ getApprovalKey(clientId, userName), 0, -1);\n\t\t\n\t\tif (result == null || result.size() == 0) {\n\t\t\treturn Collections.<OAuth2AccessToken> emptySet();\n\t\t}\n\t\tList<OAuth2AccessToken> accessTokens = new ArrayList<OAuth2AccessToken>(result.size());\n\t\t\n\t\tfor(Iterator<Object> it = result.iterator();it.hasNext();){\n\t\t\tOAuth2AccessToken accessToken = (OAuth2AccessToken) it.next();\n\t\t\taccessTokens.add(accessToken);\n\t\t}\n\t\t\n\t\treturn Collections.<OAuth2AccessToken> unmodifiableCollection(accessTokens); \n\t}\n\n\tpublic Collection<OAuth2AccessToken> findTokensByClientId(String clientId) {\n\t\tList<Object> result =    redisTemplate.opsForList().range((CLIENT_ID_TO_ACCESS+clientId), 0, -1);\n\t\t\n\t\tif (result == null || result.size() == 0) {\n\t\t\treturn Collections.<OAuth2AccessToken> emptySet();\n\t\t}\n\t\tList<OAuth2AccessToken> accessTokens = new ArrayList<OAuth2AccessToken>(result.size());\n\t\t\n\t\tfor(Iterator<Object> it = result.iterator();it.hasNext();){\n\t\t\tOAuth2AccessToken accessToken = (OAuth2AccessToken) it.next();\n\t\t\taccessTokens.add(accessToken);\n\t\t}\n\t\t\n\t\treturn Collections.<OAuth2AccessToken> unmodifiableCollection(accessTokens); \n\t}\n\n \n \n\n}\n\n"
  },
  {
    "path": "open-oauth-center/open-oauth-client/src/main/java/com/open/capacity/controller/TestController.java",
    "content": "package com.open.capacity.controller;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.data.redis.core.RedisTemplate;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport javax.annotation.Resource;\n\n/**\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2018年4月5日 下午19:52:21\n */\n@RestController\npublic class TestController {\n    private static final Logger logger = LoggerFactory.getLogger(TestController.class);\n\n    @Resource\n    private RedisTemplate<String, Object> redisTemplate;\n\n\n    @GetMapping(\"/test111\")\n    public String hello() {\n        return \"hello\";\n    }\n\n\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-client/src/main/java/com/open/capacity/controller/UserController.java",
    "content": "package com.open.capacity.controller;\n\nimport com.open.capacity.client.oauth2.token.store.RedisTemplateTokenStore;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.data.redis.core.RedisTemplate;\nimport org.springframework.security.access.prepost.PreAuthorize;\nimport org.springframework.security.core.authority.AuthorityUtils;\nimport org.springframework.security.oauth2.provider.OAuth2Authentication;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport javax.annotation.Resource;\nimport java.security.Principal;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2018年4月5日 下午19:52:21\n */\n@RestController\npublic class UserController {\n    private static final Logger logger = LoggerFactory.getLogger(UserController.class);\n\n    @Resource\n    private RedisTemplate<String, Object> redisTemplate;\n\n\n    @GetMapping(\"/hello\")\n    @PreAuthorize(\"hasAuthority('sys:user:add11')\")\n    public String hello() {\n        redisTemplate.opsForValue().set(\"hello\", \"owen\");\n        return \"hello\";\n    }\n\n    @RequestMapping(value = {\"/users\"}, produces = \"application/json\") // 获取用户信息。/auth/user\n    public Map<String, Object> user(OAuth2Authentication user) {\n        Map<String, Object> userInfo = new HashMap<>();\n        userInfo.put(\"user\", user.getUserAuthentication().getPrincipal());\n        logger.debug(\"认证详细信息:\" + user.getUserAuthentication().getPrincipal().toString());\n        userInfo.put(\"authorities\", AuthorityUtils.authorityListToSet(user.getUserAuthentication().getAuthorities()));\n        return userInfo;\n    }\n\n    @RequestMapping(value = {\"/user\"}, produces = \"application/json\") // 获取用户信息。/auth/user\n    public Principal user(Principal user) {\n        return user;\n    }\n\n\n    @GetMapping(\"/del/{accessToken}/{refreshToken}\")\n    public String hello2(@PathVariable String accessToken, @PathVariable String refreshToken) {\n        RedisTemplateTokenStore redisTemplateStore = new RedisTemplateTokenStore();\n        redisTemplateStore.setRedisTemplate(redisTemplate);\n        redisTemplateStore.removeAccessToken(accessToken);\n        redisTemplateStore.removeRefreshToken(refreshToken);\n        return \"delR\";\n    }\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-client/src/main/resources/application.yml",
    "content": "server:\n  port: 8100\nspring:\n  application:\n    name: open-auth-client\n  datasource:\n      type: com.alibaba.druid.pool.DruidDataSource\n#      driver-class-name:  oracle.jdbc.OracleDriver\n#      url: jdbc:oracle:thin:@127.0.0.1:1521:orcl\n#      username: crm_owner_user\n#      password: bss_crm_test\n#      filters: stat,wall\n################## mysql start ############################\n      driver-class-name:  com.mysql.jdbc.Driver\n      #     192.168.3.150   130.75.131.211\n      url: jdbc:mysql://47.94.252.160:3306/boot_security?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false\n      username: root\n      password: root\n      filters: stat,wall\n################### mysq end l##########################\n  redis:\n################### redis 单机版 start ########################## \n    host: 47.94.252.160\n    port: 6379    \n    database: 1\n################### redis 单机版 end ##########################   \n#    cluster:\n#      nodes: 192.168.3.157:7000,192.168.3.158:7000,192.168.3.159:7000,192.168.3.157:7001,192.168.3.158:7001,192.168.3.159:7001\n##        #130.75.131.237:7000,130.75.131.238:7000,130.75.131.239:7000,130.75.131.237:7001,130.75.131.238:7001,130.75.131.239:7001\n#        #192.168.3.157:7000,192.168.3.158:7000,192.168.3.159:7000,192.168.3.157:7001,192.168.3.158:7001,192.168.3.159:7001\n#    timeout: 1000 # 连接超时时间（毫秒）\n#    pool:\n#      max-active: 10  # 连接池最大连接数（使用负值表示没有限制）\n#      max-idle: 8     # 连接池中的最大空闲连接\n#      min-idle: 2     # 连接池中的最小空闲连接\n#      max-wait: 100   # 连接池最大阻塞等待时间（使用负值表示没有限制）       \n    \n    \n\nmybatis:\n  config-location: classpath:mybatis.cfg.xml\n  mapper-locations: classpath*:com/open/**/dao/*.xml  \n\n\nsecurity:\n  oauth2:\n    token:\n      store:\n        type: redis\n\n\n#设置最大超时时间\nribbon:  \n   ReadTimeout: 16000  \n   ConnectTimeout: 16000 \n\n#设置最大容错超时时间\nhystrix:\n  command:\n    default:\n      execution:\n        timeout:\n          enabled: true\n        isolation:\n          thread:\n            timeoutInMilliseconds: 16000\n\n\neureka:\n  client:\n    healthcheck:\n      enabled: true\n    serviceUrl:\n      defaultZone:  http://127.0.0.1:1111/eureka  #http://130.75.131.241:8761/eureka,http://130.75.131.248:8762/eureka\n      #http://134.224.249.33:1111/eureka/  正式库\n      #http://134.224.249.33:1111/eureka/  测试库\n      #http://127.0.0.1:8761/eureka,http://127.0.0.1:8762/eureka\n  instance:\n    prefer-ip-address: true\n    instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}\n    #instance-id: ${spring.application.name}:${docker.ipAddress}:${spring.application.instance_id:${server.port}}\n    lease-renewal-interval-in-seconds: 5  #每隔几秒告诉eureka服务器我还存活，用于心跳检测\n    lease-expiration-duration-in-seconds: 10 #如果心跳检测一直没有发送，10秒后会从eureka服务器中将此服务剔除\n#    status-page-url: http://${docker.ipAddress}:${server.port}/auth/doc.html # ${server.port}为该服务的端口号\nlogging:\n  level:\n    root: INFO\n    org.hibernate: INFO\n    org.hibernate.type.descriptor.sql.BasicBinder: TRACE\n    org.hibernate.type.descriptor.sql.BasicExtractor: TRACE\n#    com.neusoft: DEBUG     \n#    com.netflix: DEBUG                    #用于心跳检测输出的日志    \n\n\n  \n "
  },
  {
    "path": "open-oauth-center/open-oauth-client-two/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" 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  <parent>\n    <groupId>com.open.capacity</groupId>\n    <artifactId>open-oauth-center</artifactId>\n    <version>0.0.1-SNAPSHOT</version>\n  </parent>\n  <artifactId>open-capacity-client-two</artifactId>\n</project>"
  },
  {
    "path": "open-oauth-center/open-oauth-client-two/src/main/java/com/open/capacity/UnieapAuthServerApp.java",
    "content": "package com.open.capacity;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.client.loadbalancer.LoadBalanced;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.web.client.RestTemplate;\n\n/**\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2017年11月12日 上午22:57:51\n * 类说明\n */\n\n@SpringBootApplication\n@Configuration\npublic class UnieapAuthServerApp {\n\n    public static void main(String[] args) {\n        SpringApplication.run(UnieapAuthServerApp.class, args);\n    }\n\n    @Bean\n    @LoadBalanced\n    public RestTemplate restTemplate() {\n        return new RestTemplate();\n    }\n\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-client-two/src/main/java/com/open/capacity/client/oauth2/OAuth2ClientConfig.java",
    "content": "package com.open.capacity.client.oauth2;\n\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.open.capacity.client.oauth2.token.store.RedisTemplateTokenStore;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.security.config.annotation.web.builders.HttpSecurity;\nimport org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;\nimport org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;\nimport org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;\nimport org.springframework.security.oauth2.provider.token.TokenStore;\nimport org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;\nimport org.springframework.security.oauth2.provider.token.store.JwtTokenStore;\nimport org.springframework.security.web.AuthenticationEntryPoint;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.Resource;\n\n/**\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2017年11月12日 上午22:57:51\n */\n@Component\n@Configuration\n@EnableResourceServer\npublic class OAuth2ClientConfig extends ResourceServerConfigurerAdapter {\n\n    //对应oauth_client_details的 resource_ids字段 如果表中有数据 client_id只能访问响应resource_ids的资源服务器\n    private static final String DEMO_RESOURCE_ID = \"test\";\n    @Autowired(required = false)\n    private RedisTemplateTokenStore redisTemplateTokenStore;\n    @Resource\n    private ObjectMapper objectMapper; // springmvc启动时自动装配json处理类\n\n    @Autowired(required = false)\n    private TokenStore redisTokenStore;\n\n    @Autowired(required = false)\n    private JwtTokenStore jwtTokenStore;\n    @Autowired(required = false)\n    private JwtAccessTokenConverter jwtAccessTokenConverter;\n\n    @Autowired\n    private AuthenticationEntryPoint authenticationEntryPoint;\n\n    @Override\n    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {\n\n        if (jwtTokenStore != null) {\n            resources.tokenStore(jwtTokenStore);\n        } else if (redisTokenStore != null) {\n            resources.tokenStore(redisTokenStore);\n        }\n        resources.resourceId(DEMO_RESOURCE_ID).stateless(true);\n\n        resources.authenticationEntryPoint(authenticationEntryPoint);\n    }\n\n    @Override\n    public void configure(HttpSecurity http) throws Exception {\n\n        http.csrf().disable().exceptionHandling().authenticationEntryPoint(authenticationEntryPoint).and()\n                .authorizeRequests().anyRequest().authenticated().and().httpBasic();\n\n    }\n\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-client-two/src/main/java/com/open/capacity/client/oauth2/config/SecurityHandlerConfig.java",
    "content": "package com.open.capacity.client.oauth2.config;\n\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.security.core.AuthenticationException;\nimport org.springframework.security.web.AuthenticationEntryPoint;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.Resource;\nimport javax.servlet.ServletException;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport java.io.IOException;\nimport java.util.HashMap;\nimport java.util.Map;\n\n\n/**\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2018年4月5日 下午7:52:21\n * 类说明\n */\n@Component\n@Configuration\npublic class SecurityHandlerConfig {\n\n    @Resource\n    private ObjectMapper objectMapper; //springmvc启动时自动装配json处理类\n\n\n    /**\n     * 未登录，返回401\n     *\n     * @return\n     */\n    @Bean\n    public AuthenticationEntryPoint authenticationEntryPoint() {\n        return new AuthenticationEntryPoint() {\n\n            @Override\n            public void commence(HttpServletRequest request, HttpServletResponse response,\n                                 AuthenticationException authException) throws IOException, ServletException {\n\n                Map<String, String> rsp = new HashMap<>();\n                rsp.put(\"resp_code\", HttpStatus.UNAUTHORIZED.value() + \"\");\n                rsp.put(\"resp_msg\", \"请先登录\");\n\n                response.setContentType(\"application/json;charset=UTF-8\");\n                response.getWriter().write(objectMapper.writeValueAsString(rsp));\n                response.getWriter().flush();\n                response.getWriter().close();\n\n            }\n        };\n    }\n\n\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-client-two/src/main/java/com/open/capacity/client/oauth2/controller/UserController.java",
    "content": "package com.open.capacity.client.oauth2.controller;\n\nimport com.open.capacity.client.oauth2.token.store.RedisTemplateTokenStore;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.data.redis.core.RedisTemplate;\nimport org.springframework.security.core.authority.AuthorityUtils;\nimport org.springframework.security.oauth2.provider.OAuth2Authentication;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport javax.annotation.Resource;\nimport java.security.Principal;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2017年11月12日 上午22:57:51\n */\n@RestController\npublic class UserController {\n    private static final Logger logger = LoggerFactory.getLogger(UserController.class);\n\n    @Resource\n    private RedisTemplate<String, Object> redisTemplate;\n\n\n    @GetMapping(\"/hello\")\n    public String hello() {\n        redisTemplate.opsForValue().set(\"hello\", \"owen\");\n        return \"hello\";\n    }\n\n    @RequestMapping(value = {\"/users\"}, produces = \"application/json\") // 获取用户信息。/auth/user\n    public Map<String, Object> user(OAuth2Authentication user) {\n        Map<String, Object> userInfo = new HashMap<>();\n        userInfo.put(\"user\", user.getUserAuthentication().getPrincipal());\n        logger.debug(\"认证详细信息:\" + user.getUserAuthentication().getPrincipal().toString());\n        userInfo.put(\"authorities\", AuthorityUtils.authorityListToSet(user.getUserAuthentication().getAuthorities()));\n        return userInfo;\n    }\n\n    @RequestMapping(value = {\"/user\"}, produces = \"application/json\") // 获取用户信息。/auth/user\n    public Principal user(Principal user) {\n        return user;\n    }\n\n\n    @GetMapping(\"/del/{accessToken}/{refreshToken}\")\n    public String hello2(@PathVariable String accessToken, @PathVariable String refreshToken) {\n        RedisTemplateTokenStore redisTemplateStore = new RedisTemplateTokenStore();\n        redisTemplateStore.setRedisTemplate(redisTemplate);\n        redisTemplateStore.removeAccessToken(accessToken);\n        redisTemplateStore.removeRefreshToken(refreshToken);\n        return \"delR\";\n    }\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-client-two/src/main/java/com/open/capacity/client/oauth2/token/TokenStoreConfig.java",
    "content": "package com.open.capacity.client.oauth2.token;\n\nimport com.open.capacity.client.oauth2.token.store.RedisTemplateTokenStore;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.data.redis.core.RedisTemplate;\nimport org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;\nimport org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;\nimport org.springframework.security.oauth2.provider.token.store.JwtTokenStore;\n\nimport javax.annotation.Resource;\nimport javax.sql.DataSource;\n\n/**\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2017年12月18日 下午23:15:22\n * 类说明\n * redis存储token\n */\n@Configuration\npublic class TokenStoreConfig {\n\n    @Resource\n    private DataSource dataSource;\n\n    @Autowired(required = false)\n    private RedisTemplate<String, Object> redisTemplate;\n\n\n    @Bean\n    @ConditionalOnProperty(prefix = \"security.oauth2.token.store\", name = \"type\", havingValue = \"jdbc\", matchIfMissing = true)\n    public JdbcTokenStore jdbcTokenStore() {\n\n//\t\toauth_access_token oauth_refresh_token 创建两张表\n//\t\treturn new JdbcTokenStore( dataSource ) ;\n        return new JdbcTokenStore(dataSource);\n\n    }\n\n    @Bean\n    @ConditionalOnProperty(prefix = \"security.oauth2.token.store\", name = \"type\", havingValue = \"redis\", matchIfMissing = true)\n    public RedisTemplateTokenStore redisTokenStore() {\n//\t\treturn new RedisTokenStore( redisTemplate.getConnectionFactory() ) ; //单台redis服务器\n\n\n        RedisTemplateTokenStore redisTemplateStore = new RedisTemplateTokenStore();\n        redisTemplateStore.setRedisTemplate(redisTemplate);\n        return redisTemplateStore;\n\n\n    }\n\n    //使用jwt替换原有的uuid生成token方式\n    @Configuration\n    @ConditionalOnProperty(prefix = \"security.oauth2.token.store\", name = \"type\", havingValue = \"jwt\", matchIfMissing = true)\n    public static class JWTTokenConfig {\n        @Bean\n        public JwtTokenStore jwtTokenStore() {\n            return new JwtTokenStore(jwtAccessTokenConverter());\n        }\n\n        @Bean\n        public JwtAccessTokenConverter jwtAccessTokenConverter() {\n            JwtAccessTokenConverter accessTokenConverter = new JwtAccessTokenConverter();\n            accessTokenConverter.setSigningKey(\"neusoft\");\n            return accessTokenConverter;\n        }\n    }\n\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-client-two/src/main/java/com/open/capacity/client/oauth2/token/store/RedisTemplateTokenStore.java",
    "content": "package com.open.capacity.client.oauth2.token.store;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.concurrent.TimeUnit;\n\nimport org.springframework.data.redis.core.RedisTemplate;\nimport org.springframework.security.oauth2.common.ExpiringOAuth2RefreshToken;\nimport org.springframework.security.oauth2.common.OAuth2AccessToken;\nimport org.springframework.security.oauth2.common.OAuth2RefreshToken;\nimport org.springframework.security.oauth2.provider.OAuth2Authentication;\nimport org.springframework.security.oauth2.provider.token.AuthenticationKeyGenerator;\nimport org.springframework.security.oauth2.provider.token.DefaultAuthenticationKeyGenerator;\nimport org.springframework.security.oauth2.provider.token.TokenStore;\n\n/** \n* @author owen 624191343@qq.com\n * @version 创建时间：2017年11月12日 上午22:57:51\n* 类说明 \n* redis集群存储token\n*/\n \npublic class RedisTemplateTokenStore implements TokenStore {\n\t\n\tprivate static final String ACCESS = \"access:\";\n\tprivate static final String AUTH_TO_ACCESS = \"auth_to_access:\";\n\tprivate static final String AUTH = \"auth:\";\n\tprivate static final String REFRESH_AUTH = \"refresh_auth:\";\n\tprivate static final String ACCESS_TO_REFRESH = \"access_to_refresh:\";\n\tprivate static final String REFRESH = \"refresh:\";\n\tprivate static final String REFRESH_TO_ACCESS = \"refresh_to_access:\";\n\tprivate static final String CLIENT_ID_TO_ACCESS = \"client_id_to_access:\";\n\tprivate static final String UNAME_TO_ACCESS = \"uname_to_access:\";\n\t\n\n\tprivate RedisTemplate<String,Object> redisTemplate ;\n\t\n\tpublic RedisTemplate<String,Object> getRedisTemplate() {\n\t\treturn redisTemplate;\n\t}\n\n\tpublic void setRedisTemplate(RedisTemplate<String,Object> redisTemplate) {\n\t\tthis.redisTemplate = redisTemplate;\n\t}\n\n\n\tprivate AuthenticationKeyGenerator authenticationKeyGenerator = new DefaultAuthenticationKeyGenerator();\n\n\n\n\t \n\tpublic void setAuthenticationKeyGenerator(AuthenticationKeyGenerator authenticationKeyGenerator) {\n\t\tthis.authenticationKeyGenerator = authenticationKeyGenerator;\n\t}\n\n\t \n\tpublic OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) {\n\t\tString key = authenticationKeyGenerator.extractKey(authentication);\n\t\tOAuth2AccessToken accessToken = (OAuth2AccessToken) redisTemplate.opsForValue().get(AUTH_TO_ACCESS+key);\n\t\tif (accessToken != null\n\t\t\t\t&& !key.equals(authenticationKeyGenerator.extractKey(readAuthentication(accessToken.getValue())))) {\n\t\t\t// Keep the stores consistent (maybe the same user is represented by this authentication but the details\n\t\t\t// have changed)\n\t\t\tstoreAccessToken(accessToken, authentication);\n\t\t}\n\t\treturn accessToken;\n\t}\n\tpublic OAuth2Authentication readAuthentication(OAuth2AccessToken token) {\n\t\treturn readAuthentication(token.getValue());\n\t}\n\tpublic OAuth2Authentication readAuthentication(String token) {\n\t\treturn (OAuth2Authentication) this.redisTemplate.opsForValue().get(AUTH +  token);\n\t}\n\tpublic OAuth2Authentication readAuthenticationForRefreshToken(OAuth2RefreshToken token) {\n\t\treturn readAuthenticationForRefreshToken(token.getValue());\n\t}\n\tpublic OAuth2Authentication readAuthenticationForRefreshToken(String token) {\n\t\treturn (OAuth2Authentication) this.redisTemplate.opsForValue().get( REFRESH_AUTH+token);\n\t}\n\tpublic void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) {\n\t\t\n\t\tOAuth2AccessToken existingAccessToken = this.getAccessToken(authentication);\n\t\t\n\t\tthis.redisTemplate.opsForValue().set(ACCESS+ token.getValue(), token);\n\t\tthis.redisTemplate.opsForValue().set(AUTH +token.getValue(), authentication);\n\t\tthis.redisTemplate.opsForValue().set(AUTH_TO_ACCESS+authenticationKeyGenerator.extractKey(authentication), token);\n\t\t\n\t\tif (!authentication.isClientOnly()) {\n\t\t\tif (existingAccessToken != null) {\n\t\t\t\tif (!existingAccessToken.isExpired()) {\n\t\t\t\t\tint seconds = token.getExpiresIn();\n\t\t\t\t\tredisTemplate.expire(UNAME_TO_ACCESS+authentication.getOAuth2Request().getClientId(), seconds, TimeUnit.SECONDS) ;\n\t\t\t\t}else{\n\t\t\t\t\tredisTemplate.opsForList().rightPush(UNAME_TO_ACCESS+getApprovalKey(authentication), token) ;\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\tredisTemplate.opsForList().rightPush(UNAME_TO_ACCESS+getApprovalKey(authentication), token) ;\n\t\t\t}\n\t\t\t\t\t\n\t\t\t\n\t\t\t\n\t\t}\n\t\t\n\t\t\n\t\tif (existingAccessToken != null) {\n\t\t\tif (!existingAccessToken.isExpired()) {\n\t\t\t\tint seconds = token.getExpiresIn();\n\t\t\t\tredisTemplate.expire(CLIENT_ID_TO_ACCESS+authentication.getOAuth2Request().getClientId(), seconds, TimeUnit.SECONDS) ;\n\t\t\t\t\n\t\t\t}else{\n\t\t\t\tredisTemplate.opsForList().rightPush(CLIENT_ID_TO_ACCESS+authentication.getOAuth2Request().getClientId(), token) ;\n\t\t\t}\n\t\t}else{\n\t\t\tredisTemplate.opsForList().rightPush(CLIENT_ID_TO_ACCESS+authentication.getOAuth2Request().getClientId(), token) ;\n\t\t}\n\t\t\n\t\t\n\t\t\n\t\tif (token.getExpiration() != null) {\n\t\t\t  \n\t\t\tint seconds = token.getExpiresIn();\n\t\t\tredisTemplate.expire(ACCESS+ token.getValue(), seconds, TimeUnit.SECONDS) ;\n\t\t\tredisTemplate.expire(AUTH+ token.getValue(), seconds, TimeUnit.SECONDS) ;\n\t\t\t\n\t\t\tredisTemplate.expire(AUTH_TO_ACCESS+ authenticationKeyGenerator.extractKey(authentication), seconds, TimeUnit.SECONDS) ;\n\t\t\tredisTemplate.expire(CLIENT_ID_TO_ACCESS+authentication.getOAuth2Request().getClientId(), seconds, TimeUnit.SECONDS) ;\n\t\t\tredisTemplate.expire(UNAME_TO_ACCESS+ getApprovalKey(authentication), seconds, TimeUnit.SECONDS) ;\n\t\t}\n\t\t\n\t\tOAuth2RefreshToken refreshToken = token.getRefreshToken();\n\t\t\n\t\tif (token.getRefreshToken() != null && token.getRefreshToken().getValue() != null) {\n\t\t\tthis.redisTemplate.opsForValue().set( REFRESH_TO_ACCESS+   token.getRefreshToken().getValue(), token.getValue());\n\t\t\tthis.redisTemplate.opsForValue().set(ACCESS_TO_REFRESH+token.getValue(), token.getRefreshToken().getValue());\n\t\t\t\n\t\t\t\n\t\t\tif (refreshToken instanceof ExpiringOAuth2RefreshToken) {\n\t\t\t\tExpiringOAuth2RefreshToken expiringRefreshToken = (ExpiringOAuth2RefreshToken) refreshToken;\n\t\t\t\tDate expiration = expiringRefreshToken.getExpiration();\n\t\t\t\tif (expiration != null) {\n\t\t\t\t\tint seconds = Long.valueOf((expiration.getTime() - System.currentTimeMillis()) / 1000L)\n\t\t\t\t\t\t\t.intValue();\n\t\t\t\t\t\n\t\t\t\t\tredisTemplate.expire( REFRESH_TO_ACCESS+   token.getRefreshToken().getValue() , seconds, TimeUnit.SECONDS) ;\n\t\t\t\t\tredisTemplate.expire( ACCESS_TO_REFRESH+token.getValue(), seconds, TimeUnit.SECONDS) ;\n\t \n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t\n\t\t}\n\t}\n\n\tprivate String getApprovalKey(OAuth2Authentication authentication) {\n\t\tString userName = authentication.getUserAuthentication() == null ? \"\" : authentication.getUserAuthentication()\n\t\t\t\t.getName();\n\t\treturn getApprovalKey(authentication.getOAuth2Request().getClientId(), userName);\n\t}\n\n\tprivate String getApprovalKey(String clientId, String userName) {\n\t\treturn clientId + (userName==null ? \"\" : \":\" + userName);\n\t}\n\n\t \n\n\tpublic void removeAccessToken(OAuth2AccessToken accessToken) {\n\t\tremoveAccessToken(accessToken.getValue());\n\t}\n\n\tpublic OAuth2AccessToken readAccessToken(String tokenValue) {\n\t\treturn (OAuth2AccessToken) this.redisTemplate.opsForValue().get(ACCESS+tokenValue);\n\t}\n\n\tpublic void removeAccessToken(String tokenValue) {\n\t\tOAuth2AccessToken removed = (OAuth2AccessToken) redisTemplate.opsForValue().get(ACCESS+tokenValue);\n\t\t// Don't remove the refresh token - it's up to the caller to do that\n\t\tOAuth2Authentication authentication = (OAuth2Authentication) this.redisTemplate.opsForValue().get(AUTH+tokenValue);\n\t\t\n\t\t\n\t\tthis.redisTemplate.delete(AUTH+tokenValue);\n\t\tredisTemplate.delete(ACCESS+tokenValue);\n\t\tthis.redisTemplate.delete(ACCESS_TO_REFRESH +tokenValue);\n\t\t\n\t\t\n\t\tif (authentication != null) {\n\t\t\tthis.redisTemplate.delete(AUTH_TO_ACCESS+authenticationKeyGenerator.extractKey(authentication));\n\t\t\n\t\t\tString clientId = authentication.getOAuth2Request().getClientId();\n\t\t\t\n//\t\t\tredisTemplate.opsForList().rightPush(\"UNAME_TO_ACCESS:\"+getApprovalKey(authentication), token) ;\n\t\t\tredisTemplate.opsForList().leftPop(UNAME_TO_ACCESS+getApprovalKey(clientId, authentication.getName()));\n\t\t\t\n\t\t\tredisTemplate.opsForList().leftPop(CLIENT_ID_TO_ACCESS+clientId);\n\t\t\t\n\t\t\tthis.redisTemplate.delete(AUTH_TO_ACCESS+authenticationKeyGenerator.extractKey(authentication));\n\t\t}\n\t}\n\n\tpublic void storeRefreshToken(OAuth2RefreshToken refreshToken, OAuth2Authentication authentication) {\n\t\tthis.redisTemplate.opsForValue().set(REFRESH+refreshToken.getValue(), refreshToken);\n\t\tthis.redisTemplate.opsForValue().set( REFRESH_AUTH + refreshToken.getValue(), authentication);\n\t}\n\n\tpublic OAuth2RefreshToken readRefreshToken(String tokenValue) {\n\t\treturn (OAuth2RefreshToken) this.redisTemplate.opsForValue().get(REFRESH+tokenValue);\n\t}\n\n\tpublic void removeRefreshToken(OAuth2RefreshToken refreshToken) {\n\t\tremoveRefreshToken(refreshToken.getValue());\n\t}\n\n\tpublic void removeRefreshToken(String tokenValue) {\n\t\tthis.redisTemplate.delete( REFRESH + tokenValue);\n\t\tthis.redisTemplate.delete( REFRESH_AUTH + tokenValue);\n\t\tthis.redisTemplate.delete(REFRESH_TO_ACCESS +tokenValue);\n\t}\n\n\tpublic void removeAccessTokenUsingRefreshToken(OAuth2RefreshToken refreshToken) {\n\t\tremoveAccessTokenUsingRefreshToken(refreshToken.getValue());\n\t}\n\n\tprivate void removeAccessTokenUsingRefreshToken(String refreshToken) {\n\t\t\n\t\tString token = (String) this.redisTemplate.opsForValue().get( REFRESH_TO_ACCESS  +refreshToken) ;\n\t\t\n\t\tif (token != null) {\n\t\t\tredisTemplate.delete(REFRESH_TO_ACCESS+ refreshToken);\n\t\t}\n\t}\n\n\tpublic Collection<OAuth2AccessToken> findTokensByClientIdAndUserName(String clientId, String userName) {\n\t\tList<Object> result =    redisTemplate.opsForList().range(UNAME_TO_ACCESS+ getApprovalKey(clientId, userName), 0, -1);\n\t\t\n\t\tif (result == null || result.size() == 0) {\n\t\t\treturn Collections.<OAuth2AccessToken> emptySet();\n\t\t}\n\t\tList<OAuth2AccessToken> accessTokens = new ArrayList<OAuth2AccessToken>(result.size());\n\t\t\n\t\tfor(Iterator<Object> it = result.iterator();it.hasNext();){\n\t\t\tOAuth2AccessToken accessToken = (OAuth2AccessToken) it.next();\n\t\t\taccessTokens.add(accessToken);\n\t\t}\n\t\t\n\t\treturn Collections.<OAuth2AccessToken> unmodifiableCollection(accessTokens); \n\t}\n\n\tpublic Collection<OAuth2AccessToken> findTokensByClientId(String clientId) {\n\t\tList<Object> result =    redisTemplate.opsForList().range((CLIENT_ID_TO_ACCESS+clientId), 0, -1);\n\t\t\n\t\tif (result == null || result.size() == 0) {\n\t\t\treturn Collections.<OAuth2AccessToken> emptySet();\n\t\t}\n\t\tList<OAuth2AccessToken> accessTokens = new ArrayList<OAuth2AccessToken>(result.size());\n\t\t\n\t\tfor(Iterator<Object> it = result.iterator();it.hasNext();){\n\t\t\tOAuth2AccessToken accessToken = (OAuth2AccessToken) it.next();\n\t\t\taccessTokens.add(accessToken);\n\t\t}\n\t\t\n\t\treturn Collections.<OAuth2AccessToken> unmodifiableCollection(accessTokens); \n\t}\n\n \n \n\n}\n\n"
  },
  {
    "path": "open-oauth-center/open-oauth-client-two/src/main/java/com/open/capacity/controller/TestController.java",
    "content": "package com.open.capacity.controller;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.http.HttpMethod;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.security.oauth2.client.OAuth2ClientContext;\nimport org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RestController;\nimport org.springframework.web.client.RestTemplate;\n\nimport javax.annotation.Resource;\n\n/**\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2017年11月12日 上午22:57:51\n */\n\n@RestController\n@EnableOAuth2Client\npublic class TestController {\n    private static final Logger logger = LoggerFactory.getLogger(TestController.class);\n\n    @Resource\n    private RestTemplate restTemplate;\n\n\n    @Autowired(required = false)\n    private OAuth2ClientContext oauth2Context;\n\n\n    @GetMapping(\"/test111\")\n    public String hello() {\n\n        System.out.println(\"11111=============\" + oauth2Context.getAccessToken());\n\n\n        ResponseEntity<String> restExchange =\n                restTemplate.exchange(\n//                    \"http://localhost:5555/demo/service-four/{id}\",\n                        \"http://127.0.0.1:8100/test111?access_token=\" + oauth2Context.getAccessToken().getValue(),\n                        HttpMethod.GET,\n                        null, String.class);\n\n        return restExchange.getBody();\n    }\n\n\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-client-two/src/main/resources/application.yml",
    "content": "server:\n  port: 8200\nspring:\n  application:\n    name: open-auth-client\n  datasource:\n      type: com.alibaba.druid.pool.DruidDataSource\n#      driver-class-name:  oracle.jdbc.OracleDriver\n#      url: jdbc:oracle:thin:@127.0.0.1:1521:orcl\n#      username: crm_owner_user\n#      password: bss_crm_test\n#      filters: stat,wall\n################## mysql start ############################\n      driver-class-name:  com.mysql.jdbc.Driver\n      #     192.168.3.150   130.75.131.211\n      url: jdbc:mysql://47.94.252.160:3306/boot_security?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false\n      username: root\n      password: 1q2w3e4r\n      filters: stat,wall\n################### mysq end l##########################\n  redis:\n################### redis 单机版 start ########################## \n    host: 127.0.0.1\n    port: 6379    \n    database: 1\n################### redis 单机版 end ##########################   \n#    cluster:\n#      nodes: 192.168.3.157:7000,192.168.3.158:7000,192.168.3.159:7000,192.168.3.157:7001,192.168.3.158:7001,192.168.3.159:7001\n##        #130.75.131.237:7000,130.75.131.238:7000,130.75.131.239:7000,130.75.131.237:7001,130.75.131.238:7001,130.75.131.239:7001\n#        #192.168.3.157:7000,192.168.3.158:7000,192.168.3.159:7000,192.168.3.157:7001,192.168.3.158:7001,192.168.3.159:7001\n#    timeout: 1000 # 连接超时时间（毫秒）\n#    pool:\n#      max-active: 10  # 连接池最大连接数（使用负值表示没有限制）\n#      max-idle: 8     # 连接池中的最大空闲连接\n#      min-idle: 2     # 连接池中的最小空闲连接\n#      max-wait: 100   # 连接池最大阻塞等待时间（使用负值表示没有限制）       \n    \n    \n\nmybatis:\n  config-location: classpath:mybatis.cfg.xml\n  mapper-locations: classpath*:com/open/**/dao/*.xml  \n\n\nsecurity:\n  oauth2:\n    token:\n      store:\n        type: redis\n\n\n#设置最大超时时间\nribbon:  \n   ReadTimeout: 16000  \n   ConnectTimeout: 16000 \n\n#设置最大容错超时时间\nhystrix:\n  command:\n    default:\n      execution:\n        timeout:\n          enabled: true\n        isolation:\n          thread:\n            timeoutInMilliseconds: 16000\nlogging:\n  level:\n    com.neusoft: DEBUG\n\n\n  \n "
  },
  {
    "path": "open-oauth-center/open-oauth-server/README.md",
    "content": "认证服务器-->认证中心\n\n\n本认证中心采取的的数据库管理应用信息的方式来管理client_id client_secret\n![](https://i.imgur.com/LpxeaC3.jpg)\n\n同时token的生成方式支持redis集群或者jwt\n\n\n\n\n由于spring security oauth 默认定义的/oauth/token 会验证client_id以及client_secret,如果不在数据库中会弹框 效果如下\n![](https://i.imgur.com/KUjyHu2.jpg)\n\n\n所以根据源码，自定义/oauth2/token节点以password方式的获取token，并给出友好提示\n\n一.错误的打开方式\n\n1无效的client_id\n![](https://i.imgur.com/jD1576e.jpg)\n\n2.无效的client_secret\n![](https://i.imgur.com/jJENc8c.jpg)\n\n3.用户名密码错误\n![](https://i.imgur.com/UXCyPiv.jpg)\n\n二.正确的打开方式\n\n![](https://i.imgur.com/2IjVYNY.jpg)\n\n![](https://i.imgur.com/7j7dpjr.png)\n\n"
  },
  {
    "path": "open-oauth-center/open-oauth-server/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\t<parent>\n\t\t<groupId>com.open.capacity</groupId>\n\t\t<artifactId>open-oauth-center</artifactId>\n\t\t<version>0.0.1-SNAPSHOT</version>\n\t</parent>\n\t<artifactId>open-oauth-server</artifactId>\n\n\t<properties>\n\t\t<docker.image.prefix>gitgeek</docker.image.prefix>\n\t</properties>\n\n\t<dependencies>\n\t \n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-eureka</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-actuator</artifactId>\n\t\t</dependency>\n\t\t\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.session</groupId>\n\t\t\t<artifactId>spring-session</artifactId>\n\t\t</dependency>\n\n\t\t<!--<dependency>-->\n\t\t\t<!--<groupId>org.springframework.cloud</groupId>-->\n\t\t\t<!--<artifactId>spring-cloud-starter-feign</artifactId>-->\n\t\t<!--</dependency>-->\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-openfeign</artifactId>\n\t\t</dependency>\n\t\t\n\t</dependencies>\n\n\t<!-- 形成带第三方jar包的可执行jar包，jar包目录结构如下 application.properties lib META-INF mybatis \n\t\torg -->\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>repackage</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\n\t\t\t<plugin>\n\t\t\t\t<groupId>com.spotify</groupId>\n\t\t\t\t<artifactId>docker-maven-plugin</artifactId>\n\t\t\t\t<version>0.4.13</version>\n\t\t\t\t<configuration>\n\t\t\t\t\t<imageName>${docker.image.prefix}/${project.artifactId}</imageName>\n\t\t\t\t\t<dockerDirectory>src/main/docker</dockerDirectory>\n\t\t\t\t\t<resources>\n\t\t\t\t\t\t<resource>\n\t\t\t\t\t\t\t<targetPath>/</targetPath>\n\t\t\t\t\t\t\t<directory>${project.build.directory}</directory>\n\t\t\t\t\t\t\t<include>${project.build.finalName}.jar</include>\n\t\t\t\t\t\t</resource>\n\t\t\t\t\t</resources>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\n\t\t</plugins>\n\t\t<finalName>oauth-server</finalName>\n\t</build>\n\n\n</project>"
  },
  {
    "path": "open-oauth-center/open-oauth-server/src/main/docker/Dockerfile",
    "content": "FROM frolvlad/alpine-oraclejdk8\nVOLUME /tmp\nADD oauth-server.jar app.jar\nRUN sh -c 'touch /app.jar'\nENV JAVA_OPTS=\"\"\nENTRYPOINT [ \"sh\", \"-c\", \"java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar\" ]"
  },
  {
    "path": "open-oauth-center/open-oauth-server/src/main/java/com/open/capacity/OpenAuthServerApp.java",
    "content": "/**\n *\n */\npackage com.open.capacity;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.client.discovery.EnableDiscoveryClient;\nimport org.springframework.cloud.netflix.feign.EnableFeignClients;\n\n/**\n * @author owen 624191343@qq.com\n * @version 创建时间：2017年11月12日 上午22:57:51\n * 类说明\n */\n\n@EnableDiscoveryClient\n@SpringBootApplication\n@EnableFeignClients({\"com.open.capacity\"})\npublic class OpenAuthServerApp {\n\n    public static void main(String[] args) {\n        SpringApplication.run(OpenAuthServerApp.class, args);\n    }\n\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-server/src/main/java/com/open/capacity/config/FeignConfig.java",
    "content": "package com.open.capacity.config;\n\nimport feign.RequestInterceptor;\nimport feign.RequestTemplate;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.stereotype.Component;\nimport org.springframework.web.context.request.RequestContextHolder;\nimport org.springframework.web.context.request.ServletRequestAttributes;\n\nimport javax.servlet.http.HttpServletRequest;\n\n/**\n * @Author: [gitgeek]\n * @Date: [2018-07-12 11:32]\n * @Description: [ ]\n * @Version: [1.0.0]\n * @Copy: [com.zzg]\n */\n@Component\n@Configuration\npublic class FeignConfig implements RequestInterceptor {\n\n    private static final String TOKEN_KEY = \"access_token\";\n\n    @Override\n    public void apply(RequestTemplate requestTemplate) {\n        requestTemplate.header(\"access_token\", getToken(getHttpServletRequest()));\n    }\n\n    private HttpServletRequest getHttpServletRequest() {\n        try {\n            return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();\n        } catch (Exception e) {\n            return null;\n        }\n    }\n\n//    private Map<String, String> getHeaders(HttpServletRequest request) {\n//        Map<String, String> map = new LinkedHashMap<>();\n//        Enumeration<String> enumeration = request.getHeaderNames();\n//        while (enumeration.hasMoreElements()) {\n//            String key = enumeration.nextElement();\n//            String value = request.getHeader(key);\n//            map.put(key, value);\n//        }\n//        return map;\n//    }\n\n    /**\n     * 根据参数或者header获取token\n     *\n     * @param request\n     * @return\n     */\n    public static String getToken(HttpServletRequest request) {\n        String token = request.getParameter(TOKEN_KEY);\n        if (StringUtils.isBlank(token)) {\n            token = request.getHeader(TOKEN_KEY);\n        }\n\n        return token;\n    }\n\n\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-server/src/main/java/com/open/capacity/config/TokenStorePostProcessor.java",
    "content": "package com.open.capacity.config;\n\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.BeansException;\nimport org.springframework.beans.factory.FactoryBean;\nimport org.springframework.beans.factory.InitializingBean;\nimport org.springframework.beans.factory.config.BeanPostProcessor;\nimport org.springframework.stereotype.Component;\n\n/**\n * @Author: [gitgeek]\n * @Date: [2018-07-14 09:46]\n * @Description: [ ]\n * @Version: [1.0.0]\n * @Copy: [com.zzg]\n */\n@Component\npublic class TokenStorePostProcessor implements BeanPostProcessor {\n    /**\n     * Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean\n     * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}\n     * or a custom init-method). The bean will already be populated with property values.\n     * The returned bean instance may be a wrapper around the original.\n     *\n     * @param bean     the new bean instance\n     * @param beanName the name of the bean\n     * @return the bean instance to use, either the original or a wrapped one;\n     * if {@code null}, no subsequent BeanPostProcessors will be invoked\n     * @throws BeansException in case of errors\n     * @see InitializingBean#afterPropertiesSet\n     */\n    @Override\n    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {\n        return bean;\n    }\n\n    /**\n     * Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean\n     * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}\n     * or a custom init-method). The bean will already be populated with property values.\n     * The returned bean instance may be a wrapper around the original.\n     * <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean\n     * instance and the objects created by the FactoryBean (as of Spring 2.0). The\n     * post-processor can decide whether to apply to either the FactoryBean or created\n     * objects or both through corresponding {@code bean instanceof FactoryBean} checks.\n     * <p>This callback will also be invoked after a short-circuiting triggered by a\n     * {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method,\n     * in contrast to all other BeanPostProcessor callbacks.\n     *\n     * @param bean     the new bean instance\n     * @param beanName the name of the bean\n     * @return the bean instance to use, either the original or a wrapped one;\n     * if {@code null}, no subsequent BeanPostProcessors will be invoked\n     * @throws BeansException in case of errors\n     * @see InitializingBean#afterPropertiesSet\n     * @see FactoryBean\n     */\n    @Override\n    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {\n//        System.out.println(beanName);\n        if (StringUtils.equals(beanName,\"inMemoryTokenStore\")){\n            return this;\n        }\n        return bean;\n    }\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-server/src/main/java/com/open/capacity/controller/PermissionController.java",
    "content": "package com.open.capacity.controller;\n\nimport com.open.capacity.fegin.PermissionClient;\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 java.util.Set;\n\n/**\n * @Author: [gitgeek]\n * @Date: [2018-07-12 17:01]\n * @Description: [ ]\n * @Version: [1.0.0]\n * @Copy: [com.zzg]\n */\n@RestController\n@RequestMapping(\"/permissions\")\npublic class PermissionController {\n\n    @Autowired\n    private PermissionClient permissionClient;\n\n    @GetMapping(\"/current\")\n    public Object permissionsCurrent(){\n        return permissionClient.permissionsCurrent();\n    }\n\n    @GetMapping(\"/all\")\n    public Object permissionsAll(){\n        return permissionClient.permissionsAll();\n    }\n\n    @GetMapping(\"/parents\")\n    public Object parents(){\n        return permissionClient.parentMenu();\n    }\n\n    @GetMapping(params = \"roleId\")\n    public Object listByRoleId(Long roleId ){\n        return permissionClient.listByRoleId(roleId);\n    }\n\n    @GetMapping(\"/owns\")\n    public Set<String> ownsPermission() {\n        return permissionClient.ownsPermission();\n    }\n\n\n\n\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-server/src/main/java/com/open/capacity/controller/TestController.java",
    "content": "package com.open.capacity.controller;\n\nimport javax.annotation.Resource;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.data.redis.core.RedisTemplate;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2017年11月12日 上午22:57:51\n */\n@RestController\npublic class TestController {\n\tprivate static final Logger logger = LoggerFactory.getLogger(TestController.class);\n\t\n\t@Resource\n\tprivate RedisTemplate< String, Object> redisTemplate ;\n\n\t@GetMapping(\"/test111\")\n\tpublic String hello() {\n\t\treturn \"hello\";\n\t}\n\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-server/src/main/java/com/open/capacity/controller/UserController.java",
    "content": "package com.open.capacity.controller;\n\nimport com.open.capacity.fegin.UserClient;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.security.core.authority.AuthorityUtils;\nimport org.springframework.security.core.context.SecurityContextHolder;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * @author owen 624191343@qq.com\n * @version 创建时间：2017年11月12日 上午22:57:51\n */\n@RestController\npublic class UserController {\n    private static final Logger logger = LoggerFactory.getLogger(UserController.class);\n\n    @Autowired\n    private UserClient userClient;\n\n\n    @GetMapping(\"/hello\")\n    public String hello() {\n        return \"hello\";\n    }\n\n    @RequestMapping(value = {\"/users\"}, produces = \"application/json\") // 获取用户信息。/auth/user\n    public Map<String, Object> getCurrentUserDetail() {\n        Map<String, Object> userInfo = new HashMap<>();\n        userInfo.put(\"user\", SecurityContextHolder.getContext().getAuthentication().getPrincipal());\n        logger.debug(\"认证详细信息:\" + SecurityContextHolder.getContext().getAuthentication().getPrincipal().toString());\n        userInfo.put(\"authorities\", AuthorityUtils.authorityListToSet(SecurityContextHolder.getContext().getAuthentication().getAuthorities()));\n        return userInfo;\n    }\n\n    @RequestMapping(value = {\"/user\"}, produces = \"application/json\") // 获取用户信息。/auth/user\n    public Object getCurrentUser() {\n        return SecurityContextHolder.getContext().getAuthentication().getPrincipal();\n    }\n\n\n    @GetMapping(\"/current\")\n    public Object currentUser() {\n        return userClient.currentUser();\n    }\n\n    @GetMapping(value = \"/internal\", params = \"username\")\n    public Object findByUsername(String username) {\n        return userClient.findByUsername(username);\n    }\n\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-server/src/main/java/com/open/capacity/controller/UserTokenController.java",
    "content": "package com.open.capacity.controller;\n\nimport java.io.IOException;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport javax.annotation.Resource;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\nimport org.apache.commons.collections.MapUtils;\nimport org.apache.commons.lang.StringUtils;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.security.authentication.AuthenticationManager;\nimport org.springframework.security.authentication.UsernamePasswordAuthenticationToken;\nimport org.springframework.security.core.Authentication;\nimport org.springframework.security.core.context.SecurityContextHolder;\nimport org.springframework.security.oauth2.common.OAuth2AccessToken;\nimport org.springframework.security.oauth2.common.exceptions.UnapprovedClientAuthenticationException;\nimport org.springframework.security.oauth2.provider.ClientDetails;\nimport org.springframework.security.oauth2.provider.OAuth2Authentication;\nimport org.springframework.security.oauth2.provider.OAuth2Request;\nimport org.springframework.security.oauth2.provider.OAuth2RequestFactory;\nimport org.springframework.security.oauth2.provider.TokenRequest;\nimport org.springframework.security.oauth2.provider.client.ClientCredentialsTokenGranter;\nimport org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory;\nimport org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.open.capacity.server.oauth2.client.RedisClientDetailsService;\nimport com.open.capacity.utils.SpringUtil;\n\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport io.swagger.annotations.ApiParam;\n\n/** \n* @author 作者 owen E-mail: 624191343@qq.com\n* @version 创建时间：2018年4月28日 下午2:18:54 \n* 类说明 \n*/\n@Api(tags = \"Token处理\")\n@RestController\npublic class UserTokenController {\n\n\t@Resource\n\tprivate ObjectMapper objectMapper; // springmvc启动时自动装配json处理类\n\t\n\t@ApiOperation(value = \"用户名密码获取token\")\n\t@PostMapping(\"/user/token\")\n\tpublic void onAuthenticationSuccess(\n\t\t\t@ApiParam(required = true, name = \"username\", value = \"账号\") @RequestParam( value = \"username\") String username ,\n\t\t\t@ApiParam(required = true, name = \"password\", value = \"密码\") @RequestParam( value = \"password\") String password ,\n\t\t\tHttpServletRequest request, HttpServletResponse response){\n\t\tString clientId = request.getHeader(\"client_id\");\n\t\tString clientSecret = request.getHeader(\"client_secret\");\n\n\t\ttry {\n\n\t\t\tif (clientId == null || \"\".equals(clientId) ) {\n\t\t\t\tthrow new UnapprovedClientAuthenticationException(\"请求头中无client_id信息\");\n\t\t\t}\n\n\t\t\tif (clientSecret == null || \"\".equals(clientSecret)) {\n\t\t\t\tthrow new UnapprovedClientAuthenticationException(\"请求头中无client_secret信息\");\n\t\t\t}\n\n\t\t\tRedisClientDetailsService clientDetailsService =SpringUtil.getBean(RedisClientDetailsService.class);\n\t\t\t\n\t\t\tClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);\n\n\t\t\tif (clientDetails == null) {\n\t\t\t\tthrow new UnapprovedClientAuthenticationException(\"clientId对应的信息不存在\");\n\t\t\t} else if (!StringUtils.equals(clientDetails.getClientSecret(), clientSecret)) {\n\t\t\t\tthrow new UnapprovedClientAuthenticationException(\"clientSecret不匹配\");\n\t\t\t}\n\n\t\t\tTokenRequest tokenRequest = new TokenRequest(MapUtils.EMPTY_MAP, clientId,\n\t\t\t\t\tclientDetails.getScope(), \"customer\");\n\n\t\t\tOAuth2Request oAuth2Request = tokenRequest.createOAuth2Request(clientDetails);\n\n\t\t\t\n\t\t\tUsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);\n\t\t\t\n\t\t\tAuthenticationManager authenticationManager = SpringUtil.getBean(AuthenticationManager.class);\n\t\t\t\n            Authentication authentication = authenticationManager.authenticate(token);\n            SecurityContextHolder.getContext().setAuthentication(authentication);\n\t\t\t\n\t\t\tOAuth2Authentication oAuth2Authentication = new OAuth2Authentication(oAuth2Request,\n\t\t\t\t\tauthentication);\n\n\t\t\tAuthorizationServerTokenServices authorizationServerTokenServices = SpringUtil.getBean(\"defaultAuthorizationServerTokenServices\", AuthorizationServerTokenServices.class);\n\t\t\t\n\t\t\tOAuth2AccessToken oAuth2AccessToken = authorizationServerTokenServices\n\t\t\t\t\t.createAccessToken(oAuth2Authentication);\n\n\t\t\toAuth2Authentication.setAuthenticated(true);\n\n\t\t\tresponse.setContentType(\"application/json;charset=UTF-8\");\n\t\t\tresponse.getWriter().write(objectMapper.writeValueAsString(oAuth2AccessToken));\n\t\t\tresponse.getWriter().flush();\n\t\t\tresponse.getWriter().close();\n\n\t\t} catch (Exception e) {\n\n\t\t\tresponse.setStatus(HttpStatus.UNAUTHORIZED.value());\n\n\t\t\tresponse.setContentType(\"application/json;charset=UTF-8\");\n\n\t\t\tMap<String, String> rsp = new HashMap<>();\n\t\t\trsp.put(\"resp_code\", HttpStatus.UNAUTHORIZED.value() + \"\");\n\t\t\trsp.put(\"rsp_msg\", e.getMessage());\n\n\t\t\ttry {\n\t\t\t\tresponse.getWriter().write(objectMapper.writeValueAsString(rsp));\n\t\t\t\tresponse.getWriter().flush();\n\t\t\t\tresponse.getWriter().close();\n\t\t\t} catch (JsonProcessingException e1) {\n\t\t\t\t// TODO Auto-generated catch block\n\t\t\t\te1.printStackTrace();\n\t\t\t} catch (IOException e1) {\n\t\t\t\t// TODO Auto-generated catch block\n\t\t\t\te1.printStackTrace();\n\t\t\t}\n\t\t\n\n\t\t}\n\t}\n\t\n\t@ApiOperation(value = \"clientId获取token\")\n\t@PostMapping(\"/client/token\")\n\tpublic void client(\n\t\t\t@ApiParam(required = true, name = \"clientId\", value = \"应用ID\") @RequestParam( value = \"clientId\") String clientId ,\n\t\t\t@ApiParam(required = true, name = \"clientSecret\", value = \"应用密钥\") @RequestParam( value = \"clientSecret\") String clientSecret ,\n\t\t\tHttpServletRequest request, HttpServletResponse response){\n \n\n\t\ttry {\n\n\t\t\tif (clientId == null  || \"\".equals(clientId)) {\n\t\t\t\tthrow new UnapprovedClientAuthenticationException(\"请求参数中无clientId信息\");\n\t\t\t}\n\n\t\t\tif (clientSecret == null || \"\".equals(clientSecret)) {\n\t\t\t\tthrow new UnapprovedClientAuthenticationException(\"请求参数中无clientSecret信息\");\n\t\t\t}\n\n\t\t\tRedisClientDetailsService clientDetailsService =SpringUtil.getBean(RedisClientDetailsService.class);\n\t\t\t\n\t\t\tClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);\n\n\t\t\tif (clientDetails == null) {\n\t\t\t\tthrow new UnapprovedClientAuthenticationException(\"clientId对应的信息不存在\");\n\t\t\t} else if (!StringUtils.equals(clientDetails.getClientSecret(), clientSecret)) {\n\t\t\t\tthrow new UnapprovedClientAuthenticationException(\"clientSecret不匹配\");\n\t\t\t}\n\t\t\t\n\t\t\tMap<String,String> map = new HashMap<>() ;\n\t\t\tmap.put(\"client_secret\", clientSecret);\n\t\t\tmap.put(\"client_id\" ,clientId);\n\t\t\tmap.put(\"grant_type\" , \"client_credentials\") ;\n\t\t\tTokenRequest tokenRequest = new TokenRequest(map, clientId,\n\t\t\t\t\tclientDetails.getScope(), \"client_credentials\");\n\n\t\t\tOAuth2Request oAuth2Request = tokenRequest.createOAuth2Request(clientDetails);\n\n\t\t\t\n\t\t\tAuthorizationServerTokenServices authorizationServerTokenServices = SpringUtil.getBean(\"defaultAuthorizationServerTokenServices\", AuthorizationServerTokenServices.class);\n\t\t\tOAuth2RequestFactory requestFactory =  new DefaultOAuth2RequestFactory(clientDetailsService) ;\n\t\t\tClientCredentialsTokenGranter clientCredentialsTokenGranter = new ClientCredentialsTokenGranter(\n\t\t\t\t\tauthorizationServerTokenServices,\n\t\t\t\t\tclientDetailsService,  requestFactory \n\t\t\t\t\t);\n\t\t\t \n\t\t\tclientCredentialsTokenGranter.setAllowRefresh(true);\n\t\t\tOAuth2AccessToken oAuth2AccessToken = clientCredentialsTokenGranter.grant(\"client_credentials\", tokenRequest);\n\n\t\t\tresponse.setContentType(\"application/json;charset=UTF-8\");\n\t\t\tresponse.getWriter().write(objectMapper.writeValueAsString(oAuth2AccessToken));\n\t\t\tresponse.getWriter().flush();\n\t\t\tresponse.getWriter().close();\n\n\t\t} catch (Exception e) {\n\n\t\t\tresponse.setStatus(HttpStatus.UNAUTHORIZED.value());\n\t\t\tresponse.setContentType(\"application/json;charset=UTF-8\");\n\t\t\tMap<String, String> rsp = new HashMap<>();\n\t\t\trsp.put(\"resp_code\", HttpStatus.UNAUTHORIZED.value() + \"\");\n\t\t\trsp.put(\"rsp_msg\", e.getMessage());\n\n\t\t\ttry {\n\t\t\t\tresponse.getWriter().write(objectMapper.writeValueAsString(rsp));\n\t\t\t\tresponse.getWriter().flush();\n\t\t\t\tresponse.getWriter().close();\n\t\t\t} catch (JsonProcessingException e1) {\n\t\t\t\t// TODO Auto-generated catch block\n\t\t\t\te1.printStackTrace();\n\t\t\t} catch (IOException e1) {\n\t\t\t\t// TODO Auto-generated catch block\n\t\t\t\te1.printStackTrace();\n\t\t\t}\n\t\t\n\n\t\t}\n\t}\n\t\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-server/src/main/java/com/open/capacity/fegin/PermissionClient.java",
    "content": "package com.open.capacity.fegin;\n\nimport com.alibaba.fastjson.JSONArray;\nimport com.open.capacity.config.FeignConfig;\nimport org.springframework.cloud.netflix.feign.FeignClient;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\n\nimport java.util.List;\nimport java.util.Set;\n\n//import com.open.capacity.config.FeignConfig;\n\n/**\n * @Author: [gitgeek]\n * @Date: [2018-07-12 10:11]\n * @Description: [ ]\n * @Version: [1.0.0]\n * @Copy: [com.zzg]\n */\n//\n@FeignClient(value = \"open-user-center\", configuration = FeignConfig.class)\npublic interface PermissionClient {\n\n\n    @RequestMapping(value = \"/permissions/current\", method = RequestMethod.GET)\n    List permissionsCurrent();\n\n    @RequestMapping(value = \"/permissions/all\", method = RequestMethod.GET)\n    JSONArray permissionsAll();\n\n    @RequestMapping(value = \"/permissions/parents\", method = RequestMethod.GET)\n    List parentMenu();\n\n    @RequestMapping(value = \"/permissions/\", method = RequestMethod.GET, params = \"parentId\")\n    List listByRoleId(Long parentId);\n\n    @GetMapping(\"/permissions/owns\")\n    Set<String> ownsPermission();\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-server/src/main/java/com/open/capacity/fegin/RoleClient.java",
    "content": "package com.open.capacity.fegin;\n\nimport com.open.capacity.config.FeignConfig;\nimport org.springframework.cloud.netflix.feign.FeignClient;\n\n/**\n * @Author: [gitgeek]\n * @Date: [2018-07-19 17:47]\n * @Description: [ ]\n * @Version: [1.0.0]\n * @Copy: [com.zzg]\n */\n@FeignClient(value = \"open-user-center\", configuration = FeignConfig.class)\npublic interface RoleClient {\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-server/src/main/java/com/open/capacity/fegin/UserClient.java",
    "content": "package com.open.capacity.fegin;\n\nimport com.open.capacity.config.FeignConfig;\nimport org.springframework.cloud.netflix.feign.FeignClient;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\n\n/**\n * @Author: [gitgeek]\n * @Date: [2018-07-19 17:48]\n * @Description: [ ]\n * @Version: [1.0.0]\n * @Copy: [com.zzg]\n */\n@FeignClient(value = \"open-user-center\", configuration = FeignConfig.class)\npublic interface UserClient {\n\n    @GetMapping(\"/users/current\")\n    Object currentUser();\n\n    @GetMapping(\"/users/internal\")\n    Object findByUsername(@RequestParam(\"username\") String username);\n\n\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-server/src/main/java/com/open/capacity/filter/InspectHeaderFilter.java",
    "content": "package com.open.capacity.filter;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.stereotype.Component;\n\nimport javax.servlet.*;\nimport javax.servlet.http.HttpServletRequest;\nimport java.io.IOException;\n\n\n@Component\npublic class InspectHeaderFilter implements Filter {\n    private static final Logger logger = LoggerFactory.getLogger(InspectHeaderFilter.class);\n\n    @Override\n    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)\n            throws IOException, ServletException {\n\n\n        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;\n        logger.debug(\"得到头信息中的Authorization: \" + httpServletRequest.getHeader(\"Authorization\"));\n\n//        String header = httpServletRequest.getHeader(\"Authorization\") ;\n//        String token = StringUtils.substringAfter(header, \"bearer \") ;\n//        \n//        Claims claims =  Jwts.parser().setSigningKey(\"neusoft\".getBytes(\"UTF-8\")).parseClaimsJws(token).getBody() ;\n//\n//        logger.debug(\"claims: \" + claims);\n\n        filterChain.doFilter(httpServletRequest, servletResponse);\n    }\n\n    @Override\n    public void init(FilterConfig filterConfig) throws ServletException {\n    }\n\n    @Override\n    public void destroy() {\n    }\n}"
  },
  {
    "path": "open-oauth-center/open-oauth-server/src/main/java/com/open/capacity/httpclient/HttpAuthInvoker.java",
    "content": "package com.open.capacity.httpclient;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.apache.http.HttpEntity;\nimport org.apache.http.NameValuePair;\nimport org.apache.http.auth.AuthScope;\nimport org.apache.http.auth.UsernamePasswordCredentials;\nimport org.apache.http.client.CredentialsProvider;\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.BasicCredentialsProvider;\nimport org.apache.http.impl.client.CloseableHttpClient;\nimport org.apache.http.impl.client.HttpClientBuilder;\nimport org.apache.http.impl.client.HttpClients;\nimport org.apache.http.message.BasicNameValuePair;\nimport org.apache.http.util.EntityUtils;\n\nimport com.alibaba.fastjson.JSONObject;\n/** \n* @author 作者 owen E-mail: wang.wen@neusoft.com\n* @version 创建时间：2017年12月14日 上午11:13:53 \n* 类说明 http访问拿认证服务器的token\n*/\npublic class HttpAuthInvoker {\n\t\n\tprivate static final String BASE_URL=\"http://127.0.0.1:8010/hello\";\n\tprivate static final String TOKEN_URL = \"http://127.0.0.1:8000/auth/oauth/token\";\n\tpublic static String access_token;\n\n\tprivate HttpClientBuilder httpClientBuilder;\n\tprivate CloseableHttpClient httpClient;\n\n\t// private static final Object MAPPER = new ObjectMapper();\n\tpublic void start() throws Exception {\n\n\t\thttpClientBuilder = HttpClientBuilder.create();\n\t\t// CloseableHttpClient httpClient = HttpClients.createDefault();\n\t\t// http POST\n\t\t// HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();\n\t\tHttpPost httpPost = new HttpPost(TOKEN_URL);\n\t\t// HttpGet httpGet = new HttpGet(url);\n\t\t// httpPost.addHeader(\"Authorization\", \"Basic cGljYzpzZWNyZXQ=\");//\n\t\tCredentialsProvider provider = new BasicCredentialsProvider();\n\n\t\tAuthScope scope = new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, AuthScope.ANY_REALM);\n\t\tUsernamePasswordCredentials credentials = new UsernamePasswordCredentials(\"webApp\", \"webApp\");\n\t\tprovider.setCredentials(scope, credentials);\n\n\t\tList<NameValuePair> formParams = new ArrayList<NameValuePair>();\n\t\tformParams.add(new BasicNameValuePair(\"grant_type\", \"password\"));\n\t\tformParams.add(new BasicNameValuePair(\"scope\", \"app\"));\n\t\tformParams.add(new BasicNameValuePair(\"username\", \"admin\"));\n\t\tformParams.add(new BasicNameValuePair(\"password\", \"123456\"));\n\t\tHttpEntity entity = new UrlEncodedFormEntity(formParams, \"UTF-8\");\n\t\thttpPost.setEntity(entity);\n\t\thttpClientBuilder.setDefaultCredentialsProvider(provider);\n\t\thttpClient = httpClientBuilder.build();\n\t\tCloseableHttpResponse response = null;\n\t\ttry {\n\n\t\t\tresponse = httpClient.execute(httpPost);\n\n\t\t\tString content = EntityUtils.toString(response.getEntity(), \"UTF-8\");\n\t\t\t\n\t\t\tJSONObject  jsonObject = JSONObject.parseObject(content);\n\t\t\taccess_token = jsonObject.getString(\"access_token\");\n\t\t\tSystem.out.println(\"得到:access_token : \" + access_token);\n\t\t} finally {\n\t\t\tif (response != null) {\n\t\t\t\tresponse.close();\n\t\t\t}\n\n\t\t\thttpClient.close();\n\n\t\t}\n\t\t\n//\t\tString content = doAnotherGet(access_token);\n//\t\tSystem.out.println(content);\n\n\t}\n\n\tprivate String doAnotherGet(String json) throws Exception {\n\t\t// 创建代理地址实例\n\t\t// HttpHost proxy = new HttpHost(\"10.1.249.58\", 3128);\n\t\t// 创建路由 使用DefaultProxyRoutePlanner\n\t\t// DefaultProxyRoutePlanner routePlanner = new\n\t\t// DefaultProxyRoutePlanner(proxy);\n\t\t// 路由添加到httpclient 实例创建中\n\t\t// CloseableHttpClient httpClient\n\t\t// =HttpClients.custom().setRoutePlanner(routePlanner).build();\n\t\t//\n\t\tCloseableHttpClient httpClient = HttpClients.createDefault();\n\t\t// 创建http POST请求\n\t\tHttpGet httpGet = new HttpGet(BASE_URL);\n\t\t// HttpGet httpGet = new HttpGet(url);\n\t\t// URL url = new URL(BASE_URL);\n\n\t\thttpGet.addHeader(\"Authorization\", \"Bearer \" + json);\n\n\t\tCloseableHttpResponse response = null;\n\t\ttry {\n\t\t\t// 执行请求\n\t\t\tresponse = httpClient.execute(httpGet);\n\t\t\t// 判断返回状态是否为200\n\n\t\t\tString content = EntityUtils.toString(response.getEntity(), \"UTF-8\");\n\n\t\t\treturn content;\n\t\t} finally {\n\t\t\tif (response != null) {\n\t\t\t\tresponse.close();\n\t\t\t}\n\n\t\t\thttpClient.close();\n\t\t}\n\t}\n\t \n\t\n\tpublic static void main(String[] args) throws Exception {\n\t\tnew HttpAuthInvoker().start();\n\n\t}\n\t\n}"
  },
  {
    "path": "open-oauth-center/open-oauth-server/src/main/java/com/open/capacity/server/oauth2/OAuth2ServerConfig.java",
    "content": "\npackage com.open.capacity.server.oauth2;\n\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.open.capacity.server.oauth2.client.RedisClientDetailsService;\nimport com.open.capacity.server.oauth2.code.RedisAuthorizationCodeServices;\nimport com.open.capacity.server.oauth2.token.store.RedisTemplateTokenStore;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.autoconfigure.AutoConfigureAfter;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.data.redis.core.RedisTemplate;\nimport org.springframework.security.authentication.AuthenticationManager;\nimport org.springframework.security.config.annotation.web.builders.HttpSecurity;\nimport org.springframework.security.config.annotation.web.builders.WebSecurity;\nimport org.springframework.security.core.userdetails.UserDetailsService;\nimport org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;\nimport org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;\nimport org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;\nimport org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;\nimport org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;\nimport org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;\nimport org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;\nimport org.springframework.security.oauth2.provider.code.RandomValueAuthorizationCodeServices;\nimport org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;\nimport org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;\nimport org.springframework.security.oauth2.provider.token.store.JwtTokenStore;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.Resource;\nimport javax.sql.DataSource;\n\n/**\n * @author owen 624191343@qq.com\n * @version 创建时间：2017年11月12日 上午22:57:51\n */\n@Configuration\n\npublic class OAuth2ServerConfig {\n\n    private Logger logger = LoggerFactory.getLogger(OAuth2ServerConfig.class);\n\n    @Resource\n    private DataSource dataSource;\n    @Resource\n    private RedisTemplate<String, Object> redisTemplate;\n\n    @Bean // 声明 ClientDetails实现\n    @ConditionalOnProperty(prefix = \"security.oauth2.token.store\", name = \"type\", havingValue = \"redis\", matchIfMissing = true)\n    public RedisClientDetailsService clientDetailsService() {\n        RedisClientDetailsService clientDetailsService = new RedisClientDetailsService(dataSource);\n        clientDetailsService.setRedisTemplate(redisTemplate);\n        return clientDetailsService;\n    }\n\n\n//\t@Bean\n//    public ApprovalStore approvalStore() {\n//        return new JdbcApprovalStore(dataSource);\n//    }\n\n\n    @Bean\n    public RandomValueAuthorizationCodeServices authorizationCodeServices() {\n        RedisAuthorizationCodeServices redisAuthorizationCodeServices = new RedisAuthorizationCodeServices();\n        redisAuthorizationCodeServices.setRedisTemplate(redisTemplate);\n        return redisAuthorizationCodeServices;\n    }\n\n\n    /**\n     * @author owen 624191343@qq.com\n     * @version 创建时间：2017年11月12日 上午22:57:51\n     * 默认token存储在内存中\n     * DefaultTokenServices默认处理\n     */\n    @Component\n    @Configuration\n    @EnableAuthorizationServer\n    @AutoConfigureAfter(AuthorizationServerEndpointsConfigurer.class)\n    public class UnieapAuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {\n        /**\n         * 注入authenticationManager 来支持 password grant type\n         */\n        @Autowired\n        private AuthenticationManager authenticationManager;\n\n        @Resource\n        private ObjectMapper objectMapper; // springmvc启动时自动装配json处理类\n\n        @Autowired\n        private UserDetailsService userDetailsService;\n        @Autowired(required = false)\n        private RedisTemplateTokenStore redisTokenStore;\n\n        @Autowired(required = false)\n        private JwtTokenStore jwtTokenStore;\n        @Autowired(required = false)\n        private JwtAccessTokenConverter jwtAccessTokenConverter;\n\n        @Autowired\n        private WebResponseExceptionTranslator webResponseExceptionTranslator;\n\n        @Autowired\n        private RedisClientDetailsService clientDetailsService;\n\n        @Autowired(required = false)\n        private RandomValueAuthorizationCodeServices authorizationCodeServices;\n\n\n        //配置身份认证器，配置认证方式，TokenStore，TokenGranter，OAuth2RequestFactory\n        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {\n\n\n            if (jwtTokenStore != null) {\n                endpoints.tokenStore(jwtTokenStore).authenticationManager(authenticationManager)\n                        .userDetailsService(userDetailsService); // 支持\n                // password\n                // grant\n                // type;\n            } else if (redisTokenStore != null) {\n                endpoints.tokenStore(redisTokenStore).authenticationManager(authenticationManager)\n                        .userDetailsService(userDetailsService); // 支持\n                // password\n                // grant\n                // type;\n            }\n\n            if (jwtAccessTokenConverter != null) {\n                endpoints.accessTokenConverter(jwtAccessTokenConverter);\n            }\n\n            endpoints.authorizationCodeServices(authorizationCodeServices);\n\n            endpoints.exceptionTranslator(webResponseExceptionTranslator);\n\n        }\n\n        // 配置应用名称 应用id\n        //配置OAuth2的客户端相关信息\n        @Override\n        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {\n\n            // if(clientDetailsService!=null){\n            // clients.withClientDetails(clientDetailsService);\n            // }else{\n            // clients.inMemory().withClient(\"neusoft1\").secret(\"neusoft1\")\n            // .authorizedGrantTypes(\"authorization_code\", \"password\",\n            // \"refresh_token\").scopes(\"all\")\n            // .resourceIds(SERVER_RESOURCE_ID).accessTokenValiditySeconds(1200)\n            // .refreshTokenValiditySeconds(50000)\n            // .and().withClient(\"neusoft2\").secret(\"neusoft2\")\n            // .authorizedGrantTypes(\"authorization_code\", \"password\",\n            // \"refresh_token\").scopes(\"all\")\n            // .resourceIds(SERVER_RESOURCE_ID).accessTokenValiditySeconds(1200)\n            // .refreshTokenValiditySeconds(50000)\n            // ;\n            // }\n            clients.withClientDetails(clientDetailsService);\n            clientDetailsService.loadAllClientToCache();\n        }\n\n        //对应于配置AuthorizationServer安全认证的相关信息，创建ClientCredentialsTokenEndpointFilter核心过滤器\n        @Override\n        public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {\n\n            security.tokenKeyAccess(\"permitAll()\") /// url:/oauth/token_key,exposes\n                    /// public key for token\n                    /// verification if using\n                    /// JWT tokens\n                    .checkTokenAccess(\"isAuthenticated()\") // url:/oauth/check_token\n                    // allow check token\n                    .allowFormAuthenticationForClients();\n\n            // security.allowFormAuthenticationForClients();\n            //// security.tokenKeyAccess(\"permitAll()\");\n            // security.tokenKeyAccess(\"isAuthenticated()\");\n        }\n\n    }\n\n    // add for sso\n    // 在ResourceServerConfigurerAdapter配置需要token验证的资源\n    @Configuration\n    @EnableResourceServer\n    public class ResourceServer extends ResourceServerConfigurerAdapter {\n\n        public void configure(WebSecurity web) throws Exception {\n            web.ignoring().antMatchers(\"/health\");\n        }\n\n        @Override\n        public void configure(HttpSecurity http) throws Exception {\n            // http.httpBasic() //默认配置\n            // 用表单登录\n            http.formLogin()\n                    // 对请求授权\n                    .and().authorizeRequests()\n                    .antMatchers(\"/v2/api-docs\", \"/configuration/ui\", \"/swagger-resources\", \"/configuration/security\", \"/swagger-ui.html\", \"/webjars/**\").permitAll()\n                    // 所有需要restful保护的资源都需要加入到这个requestMatchers，加入到的资源作为资源服务器保护的资源\n                    .and().requestMatchers()\n                    .antMatchers(\"/users\", \"/**/users\").and().authorizeRequests()\n                    .antMatchers(\"/**/users\", \"/users\").authenticated().anyRequest().authenticated() // 所有的请求认证\n                    .and().csrf().disable() // 关闭Could not verify the provided\n            // CSRF\n            // token because your session was\n            // not\n            // found\n            ;\n        }\n    }\n\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-server/src/main/java/com/open/capacity/server/oauth2/client/RedisClientDetailsService.java",
    "content": "package com.open.capacity.server.oauth2.client;\n\nimport com.alibaba.fastjson.JSONObject;\nimport org.apache.commons.lang3.StringUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.data.redis.core.RedisTemplate;\nimport org.springframework.security.oauth2.common.exceptions.InvalidClientException;\nimport org.springframework.security.oauth2.provider.ClientDetails;\nimport org.springframework.security.oauth2.provider.NoSuchClientException;\nimport org.springframework.security.oauth2.provider.client.BaseClientDetails;\nimport org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;\nimport org.springframework.util.CollectionUtils;\n\nimport javax.sql.DataSource;\nimport java.util.List;\n\n\n/**\n * @author owen 624191343@qq.com\n * @version 创建时间：2017年11月12日 上午22:57:51\n * 类说明\n * 将oauth_client_details表数据缓存到redis，这里做个缓存优化\n * layui模块中有对oauth_client_details的crud， 注意同步redis的数据\n * 注意对oauth_client_details清楚redis db部分数据的清空\n */\n\npublic class RedisClientDetailsService extends JdbcClientDetailsService {\n\n    /**\n     * 缓存client的redis key，这里是hash结构存储\n     */\n    private static final String CACHE_CLIENT_KEY = \"oauth_client_details\";\n\n    private Logger logger = LoggerFactory.getLogger(RedisClientDetailsService.class);\n\n    private RedisTemplate<String, Object> redisTemplate;\n\n    public RedisTemplate<String, Object> getRedisTemplate() {\n        return redisTemplate;\n    }\n\n    public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {\n        this.redisTemplate = redisTemplate;\n    }\n\n    public RedisClientDetailsService(DataSource dataSource) {\n        super(dataSource);\n    }\n\n\n    @Override\n    public ClientDetails loadClientByClientId(String clientId) throws InvalidClientException {\n        ClientDetails clientDetails = null;\n\n        // 先从redis获取\n        String value = (String) redisTemplate.boundHashOps(CACHE_CLIENT_KEY).get(clientId);\n        if (StringUtils.isBlank(value)) {\n            clientDetails = cacheAndGetClient(clientId);\n        } else {\n            clientDetails = JSONObject.parseObject(value, BaseClientDetails.class);\n        }\n\n        return clientDetails;\n    }\n\n    /**\n     * 缓存client并返回client\n     *\n     * @param clientId\n     * @return\n     */\n    private ClientDetails cacheAndGetClient(String clientId) {\n        // 从数据库读取\n        ClientDetails clientDetails = null;\n        try {\n            clientDetails = super.loadClientByClientId(clientId);\n            if (clientDetails != null) {\n                // 写入redis缓存\n                redisTemplate.boundHashOps(CACHE_CLIENT_KEY).put(clientId, JSONObject.toJSONString(clientDetails));\n                logger.info(\"缓存clientId:{},{}\", clientId, clientDetails);\n            }\n        } catch (NoSuchClientException e) {\n            logger.info(\"clientId:{},{}\", clientId, clientId);\n        } catch (InvalidClientException e) {\n            // TODO Auto-generated catch block\n            e.printStackTrace();\n        }\n\n        return clientDetails;\n    }\n\n    @Override\n    public void updateClientDetails(ClientDetails clientDetails) throws NoSuchClientException {\n        super.updateClientDetails(clientDetails);\n        cacheAndGetClient(clientDetails.getClientId());\n    }\n\n    @Override\n    public void updateClientSecret(String clientId, String secret) throws NoSuchClientException {\n        super.updateClientSecret(clientId, secret);\n        cacheAndGetClient(clientId);\n    }\n\n    @Override\n    public void removeClientDetails(String clientId) throws NoSuchClientException {\n        super.removeClientDetails(clientId);\n        removeRedisCache(clientId);\n    }\n\n    /**\n     * 删除redis缓存\n     *\n     * @param clientId\n     */\n    private void removeRedisCache(String clientId) {\n        redisTemplate.boundHashOps(CACHE_CLIENT_KEY).delete(clientId);\n    }\n\n    /**\n     * 将oauth_client_details全表刷入redis\n     */\n    public void loadAllClientToCache() {\n        if (redisTemplate.hasKey(CACHE_CLIENT_KEY)) {\n            return;\n        }\n        logger.info(\"将oauth_client_details全表刷入redis\");\n\n        List<ClientDetails> list = super.listClientDetails();\n        if (CollectionUtils.isEmpty(list)) {\n            logger.error(\"oauth_client_details表数据为空，请检查\");\n            return;\n        }\n\n        list.parallelStream().forEach(client -> {\n            redisTemplate.boundHashOps(CACHE_CLIENT_KEY).put(client.getClientId(), JSONObject.toJSONString(client));\n        });\n    }\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-server/src/main/java/com/open/capacity/server/oauth2/code/RedisAuthorizationCodeServices.java",
    "content": "package com.open.capacity.server.oauth2.code;\n\nimport org.springframework.data.redis.core.RedisTemplate;\nimport org.springframework.security.oauth2.provider.OAuth2Authentication;\nimport org.springframework.security.oauth2.provider.code.RandomValueAuthorizationCodeServices;\n\nimport java.util.concurrent.TimeUnit;\n\n/**\n * @author owen 624191343@qq.com\n * @version 创建时间：2017年11月12日 上午22:57:51\n * JdbcAuthorizationCodeServices替换\n */\npublic class RedisAuthorizationCodeServices extends RandomValueAuthorizationCodeServices {\n\n    private RedisTemplate<String, Object> redisTemplate;\n\n\n    public RedisTemplate<String, Object> getRedisTemplate() {\n        return redisTemplate;\n    }\n\n    public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {\n        this.redisTemplate = redisTemplate;\n    }\n\n    /**\n     * 替换JdbcAuthorizationCodeServices的存储策略\n     * 将存储code到redis，并设置过期时间，10分钟<br>\n     */\n    @Override\n    protected void store(String code, OAuth2Authentication authentication) {\n\n        redisTemplate.opsForValue().set(redisKey(code), authentication, 10, TimeUnit.MINUTES);\n\n\n    }\n\n    @Override\n    protected OAuth2Authentication remove(final String code) {\n\n        String codeKey = redisKey(code);\n\n        OAuth2Authentication token = (OAuth2Authentication) redisTemplate.opsForValue().get(codeKey);\n\n        this.redisTemplate.delete(codeKey);\n\n        return token;\n    }\n\n    /**\n     * redis中 code key的前缀\n     *\n     * @param code\n     * @return\n     */\n    private String redisKey(String code) {\n        return \"oauth:code:\" + code;\n    }\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-server/src/main/java/com/open/capacity/server/oauth2/config/OauthLogoutHandler.java",
    "content": "package com.open.capacity.server.oauth2.config;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.security.core.Authentication;\nimport org.springframework.security.oauth2.common.OAuth2AccessToken;\nimport org.springframework.security.oauth2.common.OAuth2RefreshToken;\nimport org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails;\nimport org.springframework.security.oauth2.provider.token.TokenStore;\nimport org.springframework.security.web.authentication.logout.LogoutHandler;\nimport org.springframework.util.Assert;\n\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport java.util.Enumeration;\n\n/**\n * @author keets\n * @date 2017/10/17\n */\npublic class OauthLogoutHandler implements LogoutHandler {\n\n    private static final Logger logger = LoggerFactory.getLogger(OauthLogoutHandler.class);\n\n    @Autowired\n    private TokenStore tokenStore;\n\n    @Override\n    public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {\n        Assert.notNull(tokenStore, \"tokenStore must be set\");\n        String token = extractToken(request);\n        Assert.hasText(token, \"token must be set\");\n        OAuth2AccessToken existingAccessToken = tokenStore.readAccessToken(token);\n        OAuth2RefreshToken refreshToken;\n        if (existingAccessToken != null) {\n            if (existingAccessToken.getRefreshToken() != null) {\n                logger.info(\"remove refreshToken!\", existingAccessToken.getRefreshToken());\n                refreshToken = existingAccessToken.getRefreshToken();\n                tokenStore.removeRefreshToken(refreshToken);\n            }\n            logger.info(\"remove existingAccessToken!\", existingAccessToken);\n            tokenStore.removeAccessToken(existingAccessToken);\n        }\n        return;\n\n    }\n\n    protected String extractToken(HttpServletRequest request) {\n        // first check the header...\n        String token = extractHeaderToken(request);\n\n        // bearer type allows a request parameter as well\n        if (token == null) {\n            logger.debug(\"Token not found in headers. Trying request parameters.\");\n            token = request.getParameter(OAuth2AccessToken.ACCESS_TOKEN);\n            if (token == null) {\n                logger.debug(\"Token not found in request parameters.  Not an OAuth2 request.\");\n            } else {\n                request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_TYPE, OAuth2AccessToken.BEARER_TYPE);\n            }\n        }\n\n        return token;\n    }\n\n    protected String extractHeaderToken(HttpServletRequest request) {\n        Enumeration<String> headers = request.getHeaders(\"Authorization\");\n        while (headers.hasMoreElements()) { // typically there is only one (most\n            // servers enforce that)\n            String value = headers.nextElement();\n            if ((value.toLowerCase().startsWith(OAuth2AccessToken.BEARER_TYPE.toLowerCase()))) {\n                String authHeaderValue = value.substring(OAuth2AccessToken.BEARER_TYPE.length()).trim();\n                // Add this here for the auth details later. Would be better to\n                // change the signature of this method.\n                request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_TYPE,\n                        value.substring(0, OAuth2AccessToken.BEARER_TYPE.length()).trim());\n                int commaIndex = authHeaderValue.indexOf(',');\n                if (commaIndex > 0) {\n                    authHeaderValue = authHeaderValue.substring(0, commaIndex);\n                }\n                return authHeaderValue;\n            }\n        }\n\n        return null;\n    }\n\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-server/src/main/java/com/open/capacity/server/oauth2/config/PasswordConfig.java",
    "content": "package com.open.capacity.server.oauth2.config;\n\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;\nimport org.springframework.security.crypto.password.PasswordEncoder;\n\n/** \n* @author 作者 owen E-mail: 624191343@qq.com\n* @version 创建时间：2017年11月12日 上午22:57:51\n* 类说明 \n*/\n@Configuration\npublic class PasswordConfig {\n\t@Bean\n\tpublic PasswordEncoder passwordEncoder()\t{\n\t\treturn new BCryptPasswordEncoder();\n\t}\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-server/src/main/java/com/open/capacity/server/oauth2/config/SecurityConfig.java",
    "content": "package com.open.capacity.server.oauth2.config;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;\nimport org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;\nimport org.springframework.security.config.annotation.web.builders.HttpSecurity;\nimport org.springframework.security.config.annotation.web.builders.WebSecurity;\nimport org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;\nimport org.springframework.security.config.http.SessionCreationPolicy;\nimport org.springframework.security.core.userdetails.UserDetailsService;\nimport org.springframework.security.crypto.password.PasswordEncoder;\nimport org.springframework.security.web.AuthenticationEntryPoint;\nimport org.springframework.security.web.authentication.AuthenticationFailureHandler;\nimport org.springframework.security.web.authentication.AuthenticationSuccessHandler;\nimport org.springframework.security.web.authentication.logout.HttpStatusReturningLogoutSuccessHandler;\n\n/**\n * spring security配置\n * \n * @author owen 624191343@qq.com\n * @version 创建时间：2017年11月12日 上午22:57:51 2017年10月16日\n *          在WebSecurityConfigurerAdapter不拦截oauth要开放的资源\n */\n@EnableGlobalMethodSecurity(prePostEnabled = true)\npublic class SecurityConfig extends WebSecurityConfigurerAdapter {\n\n\t@Autowired\n\tprivate AuthenticationSuccessHandler authenticationSuccessHandler;\n\t@Autowired\n\tprivate AuthenticationFailureHandler authenticationFailureHandler;\n\t// @Autowired\n\t// private LogoutSuccessHandler logoutSuccessHandler;\n\t@Autowired(required = false)\n\tprivate AuthenticationEntryPoint authenticationEntryPoint;\n\t@Autowired\n\tprivate UserDetailsService userDetailsService;\n\n\t@Autowired\n\tprivate PasswordEncoder passwordEncoder;\n\n\t@Autowired\n\tprivate OauthLogoutHandler oauthLogoutHandler;\n\n\t@Override\n\tpublic void configure(WebSecurity web) throws Exception {\n\t\tweb.ignoring().antMatchers(\"/v2/api-docs\", \"/configuration/ui\", \"/swagger-resources\", \"/configuration/security\",\n\t\t\t\t\"/swagger-ui.html\", \"/webjars/**\", \"/doc.html\", \"/login.html\");\n\t\tweb.ignoring().antMatchers(\"/health\");\n\t}\n\n\t@Override\n\tprotected void configure(HttpSecurity http) throws Exception {\n\t\thttp.csrf().disable();\n\n\t\thttp.authorizeRequests().antMatchers(\"/user/token\", \"/client/token\").permitAll().antMatchers(\"/oauth/authorize\")\n\t\t\t\t.permitAll()\n\t\t\t\t.antMatchers(\"/v2/api-docs\", \"/configuration/ui\", \"/swagger-resources\", \"/configuration/security\",\n\t\t\t\t\t\t\"/swagger-ui.html\", \"/webjars/**\")\n\t\t\t\t.permitAll().antMatchers(\"/login\").permitAll().antMatchers(\"/users\", \"/user/login\").permitAll()\n\t\t\t\t.anyRequest().authenticated();\n\t\thttp.formLogin().loginPage(\"/login.html\").loginProcessingUrl(\"/user/login\")\n\t\t\t\t.successHandler(authenticationSuccessHandler).failureHandler(authenticationFailureHandler);\n\n\t\t// 基于密码 等模式可以无session,不支持授权码模式\n\t\tif (authenticationEntryPoint != null) {\n\t\t\thttp.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint);\n\t\t\thttp.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);\n\n\t\t} else {\n\t\t\t// 授权码模式单独处理，需要session的支持，此模式可以支持所有oauth2的认证\n\t\t\thttp.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);\n\t\t}\n\n\t\thttp.logout().logoutUrl(\"/user/logout\").clearAuthentication(true)\n\t\t.logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler())\n\t\t.addLogoutHandler(oauthLogoutHandler)\n\t\t.deleteCookies(\"JSESSIONID\",\"FP-UID\")\n        .invalidateHttpSession(true) \n        // 退出成功后，跳转到/路径。\n        .logoutSuccessUrl(\"/login\");\n\n\t\t// http.logout().logoutUrl(\"/logout\").logoutSuccessHandler(logoutSuccessHandler);\n\t\t// 解决不允许显示在iframe的问题\n\t\thttp.headers().frameOptions().disable();\n\t\thttp.headers().cacheControl();\n\n\t}\n\n\t@Override\n\tprotected void configure(AuthenticationManagerBuilder auth) throws Exception {\n\t\tauth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);\n\t}\n\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-server/src/main/java/com/open/capacity/server/oauth2/config/SecurityHandlerConfig.java",
    "content": "package com.open.capacity.server.oauth2.config;\n\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.security.authentication.BadCredentialsException;\nimport org.springframework.security.authentication.InternalAuthenticationServiceException;\nimport org.springframework.security.core.Authentication;\nimport org.springframework.security.core.AuthenticationException;\nimport org.springframework.security.oauth2.common.exceptions.*;\nimport org.springframework.security.oauth2.provider.error.DefaultWebResponseExceptionTranslator;\nimport org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;\nimport org.springframework.security.web.authentication.AuthenticationFailureHandler;\nimport org.springframework.security.web.authentication.AuthenticationSuccessHandler;\nimport org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;\nimport org.springframework.security.web.savedrequest.HttpSessionRequestCache;\nimport org.springframework.security.web.savedrequest.RequestCache;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.Resource;\nimport javax.servlet.ServletException;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport java.io.IOException;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * @author owen 624191343@qq.com\n * @version 创建时间：2017年11月12日 上午22:57:51\n */\n@Component\n@Configuration\npublic class SecurityHandlerConfig {\n\n    @Resource\n    private ObjectMapper objectMapper; // springmvc启动时自动装配json处理类\n\n//\t@Autowired\n//\tprivate AuthorizationServerTokenServices authorizationServerTokenServices;\n\n//\t@Autowired\n//\tprivate ClientDetailsService clientDetailsService;\n\n//\t@Autowired(required = false)\n//\tprivate AuthenticationEntryPoint authenticationEntryPoint;\n\n    // url匹配器\n//\tprivate AntPathMatcher pathMatcher = new AntPathMatcher();\n\n    /**\n     * 登陆成功，返回Token 装配此bean不支持授权码模式\n     *\n     * @return\n     */\n    @Bean\n    public AuthenticationSuccessHandler loginSuccessHandler() {\n        return new SavedRequestAwareAuthenticationSuccessHandler() {\n\n            private RequestCache requestCache = new HttpSessionRequestCache();\n\n            @Override\n            public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,\n                                                Authentication authentication) throws IOException, ServletException {\n\n                super.onAuthenticationSuccess(request, response, authentication);\n                return;\n\n            }\n        };\n    }\n\n    /**\n     * 登陆失败\n     *\n     * @return\n     */\n    @Bean\n    public AuthenticationFailureHandler loginFailureHandler() {\n        return new AuthenticationFailureHandler() {\n\n            @Override\n            public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,\n                                                AuthenticationException exception) throws IOException, ServletException {\n                String msg = null;\n                if (exception instanceof BadCredentialsException) {\n                    msg = \"密码错误\";\n                } else {\n                    msg = exception.getMessage();\n                }\n\n                Map<String, String> rsp = new HashMap<>();\n\n                response.setStatus(HttpStatus.UNAUTHORIZED.value());\n\n                rsp.put(\"resp_code\", HttpStatus.UNAUTHORIZED.value() + \"\");\n                rsp.put(\"rsp_msg\", msg);\n\n                response.setContentType(\"application/json;charset=UTF-8\");\n                response.getWriter().write(objectMapper.writeValueAsString(rsp));\n                response.getWriter().flush();\n                response.getWriter().close();\n\n            }\n        };\n\n    }\n\n    @Bean\n    public WebResponseExceptionTranslator webResponseExceptionTranslator() {\n        return new DefaultWebResponseExceptionTranslator() {\n\n            public static final String BAD_MSG = \"坏的凭证\";\n\n            @Override\n            public ResponseEntity<OAuth2Exception> translate(Exception e) throws Exception {\n                // e.printStackTrace();\n                OAuth2Exception oAuth2Exception;\n                if (e.getMessage() != null && e.getMessage().equals(BAD_MSG)) {\n                    oAuth2Exception = new InvalidGrantException(\"用户名或密码错误\", e);\n                } else if (e instanceof InternalAuthenticationServiceException) {\n                    oAuth2Exception = new InvalidGrantException(e.getMessage(), e);\n                } else if (e instanceof RedirectMismatchException) {\n                    oAuth2Exception = new InvalidGrantException(e.getMessage(), e);\n                } else if (e instanceof InvalidScopeException) {\n                    oAuth2Exception = new InvalidGrantException(e.getMessage(), e);\n                } else {\n                    oAuth2Exception = new UnsupportedResponseTypeException(\"服务内部错误\", e);\n                }\n\n                ResponseEntity<OAuth2Exception> response = super.translate(oAuth2Exception);\n                ResponseEntity.status(oAuth2Exception.getHttpErrorCode());\n                response.getBody().addAdditionalInformation(\"resp_code\", oAuth2Exception.getHttpErrorCode() + \"\");\n                response.getBody().addAdditionalInformation(\"resp_msg\", oAuth2Exception.getMessage());\n\n                return response;\n            }\n\n        };\n    }\n\n    @Bean\n    public OauthLogoutHandler oauthLogoutHandler() {\n        return new OauthLogoutHandler();\n    }\n\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-server/src/main/java/com/open/capacity/server/oauth2/config/SwaggerConfig.java",
    "content": "package com.open.capacity.server.oauth2.config;\n\nimport org.springframework.context.MessageSource;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.context.support.ResourceBundleMessageSource;\nimport org.springframework.stereotype.Component;\nimport org.springframework.web.servlet.ViewResolver;\nimport org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;\nimport org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;\nimport org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;\nimport org.springframework.web.servlet.view.InternalResourceViewResolver;\nimport org.springframework.web.servlet.view.JstlView;\nimport springfox.documentation.builders.ApiInfoBuilder;\nimport springfox.documentation.builders.ParameterBuilder;\nimport springfox.documentation.builders.PathSelectors;\nimport springfox.documentation.builders.RequestHandlerSelectors;\nimport springfox.documentation.schema.ModelRef;\nimport springfox.documentation.service.ApiInfo;\nimport springfox.documentation.service.Parameter;\nimport springfox.documentation.spi.DocumentationType;\nimport springfox.documentation.spring.web.plugins.Docket;\nimport springfox.documentation.swagger2.annotations.EnableSwagger2;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n@Component\n@Configuration\n@EnableSwagger2\npublic class SwaggerConfig extends WebMvcConfigurerAdapter {\n\n\n    @Bean\n    public Docket createRestApi() {\n\n\n        ParameterBuilder tokenPar = new ParameterBuilder();\n        List<Parameter> pars = new ArrayList<>();\n        tokenPar.name(\"Authorization\").description(\"令牌\").\n                modelRef(new ModelRef(\"string\")).\n                parameterType(\"header\").required(false).build();\n\n\n        ParameterBuilder clientPar = new ParameterBuilder();\n        clientPar.name(\"client_id\").description(\"应用ID\").\n                modelRef(new ModelRef(\"string\")).\n                parameterType(\"header\").required(false).build();\n\n        ParameterBuilder secretPar = new ParameterBuilder();\n        secretPar.name(\"client_secret\").description(\"应用密钥\").\n                modelRef(new ModelRef(\"string\")).\n                parameterType(\"header\").required(false).build();\n\n        pars.add(tokenPar.build());\n        pars.add(clientPar.build());\n        pars.add(secretPar.build());\n\n        return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select()\n                // .apis(RequestHandlerSelectors.basePackage(\"com.open.capacity\"))\n                .apis(RequestHandlerSelectors.any())\n                .paths(input -> PathSelectors.regex(\"/user.*\").apply(input) || PathSelectors.regex(\"/client.*\").apply(input))\n                // .paths(PathSelectors.any())\n                .build().globalOperationParameters(pars);\n    }\n\n    private ApiInfo apiInfo() {\n        return new ApiInfoBuilder().title(\"认证中心api\").description(\"认证中心api\").version(\"1.0\").build();\n    }\n\n    @Bean\n    public ViewResolver viewResolver() {\n        InternalResourceViewResolver resolver = new InternalResourceViewResolver();\n        resolver.setViewClass(JstlView.class);\n        resolver.setPrefix(\"/\");\n        resolver.setSuffix(\".html\");\n        return resolver;\n\n    }\n\n    @Bean\n    public MessageSource messageSource() {\n        ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();\n        messageSource.setBasename(\"messages\");\n        return messageSource;\n    }\n\n    @Override\n    public void addResourceHandlers(ResourceHandlerRegistry registry) {\n        super.addResourceHandlers(registry);\n        registry.addResourceHandler(\"swagger-ui.html\").addResourceLocations(\"classpath:/META-INF/resources/\");\n        registry.addResourceHandler(\"/webjars/**\").addResourceLocations(\"classpath:/META-INF/resources/webjars/\");\n    }\n\n    @Override\n    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {\n        configurer.enable();\n    }\n\n\n}"
  },
  {
    "path": "open-oauth-center/open-oauth-server/src/main/java/com/open/capacity/server/oauth2/dao/UserDao.java",
    "content": "package com.open.capacity.server.oauth2.dao;\n\nimport org.apache.ibatis.annotations.Mapper;\nimport org.apache.ibatis.annotations.Select;\n\nimport java.util.Map;\n\n@Mapper\npublic interface UserDao {\n\n\n    @Select(\"select * from sys_user t where t.username = #{username}\")\n    Map getUser(String username);\n\n\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-server/src/main/java/com/open/capacity/server/oauth2/service/UnieapUserDetailsService.java",
    "content": "package com.open.capacity.server.oauth2.service;\n\nimport com.open.capacity.server.oauth2.dao.UserDao;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;\nimport org.springframework.security.core.authority.AuthorityUtils;\nimport org.springframework.security.core.userdetails.User;\nimport org.springframework.security.core.userdetails.UserDetails;\nimport org.springframework.security.core.userdetails.UserDetailsService;\nimport org.springframework.security.core.userdetails.UsernameNotFoundException;\nimport org.springframework.security.crypto.password.PasswordEncoder;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.Resource;\nimport java.util.Map;\n\n\n/**\n * @author owen 624191343@qq.com\n * @version 创建时间：2017年11月12日 上午22:57:51\n * 类说明\n */\n@Component\npublic class UnieapUserDetailsService implements UserDetailsService {\n\n    private Logger logger = LoggerFactory.getLogger(this.getClass());\n\n    @Resource\n    private PasswordEncoder passwordEncoder;\n\n    @Resource\n    private UserDao userDao;\n\n//\t@Resource  注入查询用户的dao\n//\tprivate dao\n\n\n    @Override\n    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {\n        // TODO Auto-generated method stub\n\n        System.out.println(\"页面输入的用户名：\" + username);\n//\t\tUser user = new User(username,\"123456\",\t//默认密码都123456 \n//\t\t\tAuthorityUtils.commaSeparatedStringToAuthorityList(\"admin\")); // 第三个参数是授权的,暂时写硬编码AuthorityUtils.commaSeparatedStringToAuthorityList(\"admin\")\n//\t\t\n\n//\t\tpublic User(String username, String password, boolean enabled,\n//\t\t\t\tboolean accountNonExpired, boolean credentialsNonExpired,\n//\t\t\t\tboolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {\n\n\n        Map sysUser = userDao.getUser(username);\n\n        if (sysUser == null) {\n            throw new AuthenticationCredentialsNotFoundException(\"用户名不存在\");\n        }\n\n        String password = String.valueOf(sysUser.get(\"password\"));\n        logger.info(\"数据库存储的密码是:\" + password);\n\n        User user = new User(username, password,      //123456模拟从数据库中查询得到的\n                true, true, true, true, //是否有效，账户是否过期，密码是否过期，是否锁定，\n                AuthorityUtils.commaSeparatedStringToAuthorityList(\"ROLE_USER,ROLE_ADMIN,sys:user:add\"));\n\n        return user;\n    }\n\n\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-server/src/main/java/com/open/capacity/server/oauth2/token/TokenStoreConfig.java",
    "content": "package com.open.capacity.server.oauth2.token;\n\nimport com.open.capacity.server.oauth2.token.store.RedisTemplateTokenStore;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.data.redis.core.RedisTemplate;\nimport org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;\nimport org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;\nimport org.springframework.security.oauth2.provider.token.store.JwtTokenStore;\nimport org.springframework.util.Assert;\n\nimport javax.annotation.Resource;\nimport javax.sql.DataSource;\n\n/**\n * @author owen 624191343@qq.com\n * @version 创建时间：2017年11月12日 上午22:57:51\n * 类说明\n * redis存储token\n */\n@Configuration\npublic class TokenStoreConfig {\n\n\n    @Resource\n    private DataSource dataSource;\n\n    @Autowired(required = false)\n    private RedisTemplate<String, Object> redisTemplate;\n\n\n    @Bean\n    @ConditionalOnProperty(prefix = \"security.oauth2.token.store\", name = \"type\", havingValue = \"jdbc\", matchIfMissing = false)\n    public JdbcTokenStore jdbcTokenStore() {\n\n//\t\toauth_access_token oauth_refresh_token 创建两张表\n//\t\treturn new JdbcTokenStore( dataSource ) ;\n        return new JdbcTokenStore(dataSource);\n\n    }\n\n    @Bean\n    @ConditionalOnProperty(prefix = \"security.oauth2.token.store\", name = \"type\", havingValue = \"redis\", matchIfMissing = true)\n    public RedisTemplateTokenStore redisTokenStore() {\n//\t\treturn new RedisTokenStore( redisTemplate.getConnectionFactory() ) ; //单台redis服务器\n        Assert.state(redisTemplate != null, \"RedisTemplate must be provided\");\n\n        RedisTemplateTokenStore redisTemplateStore = new RedisTemplateTokenStore();\n        redisTemplateStore.setRedisTemplate(redisTemplate);\n        return redisTemplateStore;\n\n\n    }\n\n    //使用jwt替换原有的uuid生成token方式\n    @Configuration\n    @ConditionalOnProperty(prefix = \"security.oauth2.token.store\", name = \"type\", havingValue = \"jwt\", matchIfMissing = false)\n    public static class JWTTokenConfig {\n        @Bean\n        public JwtTokenStore jwtTokenStore() {\n            return new JwtTokenStore(jwtAccessTokenConverter());\n        }\n\n        @Bean\n        public JwtAccessTokenConverter jwtAccessTokenConverter() {\n            JwtAccessTokenConverter accessTokenConverter = new JwtAccessTokenConverter();\n            accessTokenConverter.setSigningKey(\"neusoft\");\n            return accessTokenConverter;\n        }\n    }\n\n\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-server/src/main/java/com/open/capacity/server/oauth2/token/store/RedisTemplateTokenStore.java",
    "content": "package com.open.capacity.server.oauth2.token.store;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.concurrent.TimeUnit;\n\nimport org.springframework.data.redis.core.RedisTemplate;\nimport org.springframework.security.oauth2.common.ExpiringOAuth2RefreshToken;\nimport org.springframework.security.oauth2.common.OAuth2AccessToken;\nimport org.springframework.security.oauth2.common.OAuth2RefreshToken;\nimport org.springframework.security.oauth2.provider.OAuth2Authentication;\nimport org.springframework.security.oauth2.provider.token.AuthenticationKeyGenerator;\nimport org.springframework.security.oauth2.provider.token.DefaultAuthenticationKeyGenerator;\nimport org.springframework.security.oauth2.provider.token.TokenStore;\n\n/** \n* @author owen 624191343@qq.com\n * @version 创建时间：2017年11月12日 上午22:57:51\n* 类说明 \n* redis集群存储token\n*/\n \npublic class RedisTemplateTokenStore implements TokenStore {\n\t\n\tprivate static final String ACCESS = \"access:\";\n\tprivate static final String AUTH_TO_ACCESS = \"auth_to_access:\";\n\tprivate static final String AUTH = \"auth:\";\n\tprivate static final String REFRESH_AUTH = \"refresh_auth:\";\n\tprivate static final String ACCESS_TO_REFRESH = \"access_to_refresh:\";\n\tprivate static final String REFRESH = \"refresh:\";\n\tprivate static final String REFRESH_TO_ACCESS = \"refresh_to_access:\";\n\tprivate static final String CLIENT_ID_TO_ACCESS = \"client_id_to_access:\";\n\tprivate static final String UNAME_TO_ACCESS = \"uname_to_access:\";\n\t\n\n\tprivate RedisTemplate<String,Object> redisTemplate ;\n\t\n\tpublic RedisTemplate<String,Object> getRedisTemplate() {\n\t\treturn redisTemplate;\n\t}\n\n\tpublic void setRedisTemplate(RedisTemplate<String,Object> redisTemplate) {\n\t\tthis.redisTemplate = redisTemplate;\n\t}\n\n\n\tprivate AuthenticationKeyGenerator authenticationKeyGenerator = new DefaultAuthenticationKeyGenerator();\n\n\n\n\tpublic void setAuthenticationKeyGenerator(AuthenticationKeyGenerator authenticationKeyGenerator) {\n\t\tthis.authenticationKeyGenerator = authenticationKeyGenerator;\n\t}\n\n\t@Override\n\tpublic OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) {\n\t\tString key = authenticationKeyGenerator.extractKey(authentication);\n\t\tOAuth2AccessToken accessToken = (OAuth2AccessToken) redisTemplate.opsForValue().get(AUTH_TO_ACCESS+key);\n\t\tif (accessToken != null\n\t\t\t\t&& !key.equals(authenticationKeyGenerator.extractKey(readAuthentication(accessToken.getValue())))) {\n\t\t\t// Keep the stores consistent (maybe the same user is represented by this authentication but the details\n\t\t\t// have changed)\n\t\t\tstoreAccessToken(accessToken, authentication);\n\t\t}\n\t\treturn accessToken;\n\t}\n\n\t@Override\n\tpublic OAuth2Authentication readAuthentication(OAuth2AccessToken token) {\n\t\treturn readAuthentication(token.getValue());\n\t}\n\n\t@Override\n\tpublic OAuth2Authentication readAuthentication(String token) {\n\t\treturn (OAuth2Authentication) this.redisTemplate.opsForValue().get(AUTH +  token);\n\t}\n\n\t@Override\n\tpublic OAuth2Authentication readAuthenticationForRefreshToken(OAuth2RefreshToken token) {\n\t\treturn readAuthenticationForRefreshToken(token.getValue());\n\t}\n\n\tprivate OAuth2Authentication readAuthenticationForRefreshToken(String token) {\n\t\treturn (OAuth2Authentication) this.redisTemplate.opsForValue().get( REFRESH_AUTH+token);\n\t}\n\n\t@Override\n\tpublic void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) {\n\t\t\n\t\tOAuth2AccessToken existingAccessToken = this.getAccessToken(authentication);\n\t\t\n\t\tthis.redisTemplate.opsForValue().set(ACCESS+ token.getValue(), token);\n\t\tthis.redisTemplate.opsForValue().set(AUTH +token.getValue(), authentication);\n\t\tthis.redisTemplate.opsForValue().set(AUTH_TO_ACCESS+authenticationKeyGenerator.extractKey(authentication), token);\n\t\t\n\t\tif (!authentication.isClientOnly()) {\n\t\t\tif (existingAccessToken != null) {\n\t\t\t\tif (!existingAccessToken.isExpired()) {\n\t\t\t\t\tint seconds = token.getExpiresIn();\n\t\t\t\t\tredisTemplate.expire(UNAME_TO_ACCESS+authentication.getOAuth2Request().getClientId(), seconds, TimeUnit.SECONDS) ;\n\t\t\t\t}else{\n\t\t\t\t\tredisTemplate.opsForList().rightPush(UNAME_TO_ACCESS+getApprovalKey(authentication), token) ;\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\tredisTemplate.opsForList().rightPush(UNAME_TO_ACCESS+getApprovalKey(authentication), token) ;\n\t\t\t}\n\t\t\t\t\t\n\t\t\t\n\t\t\t\n\t\t}\n\t\t\n\t\t\n\t\tif (existingAccessToken != null) {\n\t\t\tif (!existingAccessToken.isExpired()) {\n\t\t\t\tint seconds = token.getExpiresIn();\n\t\t\t\tredisTemplate.expire(CLIENT_ID_TO_ACCESS+authentication.getOAuth2Request().getClientId(), seconds, TimeUnit.SECONDS) ;\n\t\t\t\t\n\t\t\t}else{\n\t\t\t\tredisTemplate.opsForList().rightPush(CLIENT_ID_TO_ACCESS+authentication.getOAuth2Request().getClientId(), token) ;\n\t\t\t}\n\t\t}else{\n\t\t\tredisTemplate.opsForList().rightPush(CLIENT_ID_TO_ACCESS+authentication.getOAuth2Request().getClientId(), token) ;\n\t\t}\n\t\t\n\t\t\n\t\t\n\t\tif (token.getExpiration() != null) {\n\t\t\t  \n\t\t\tint seconds = token.getExpiresIn();\n\t\t\tredisTemplate.expire(ACCESS+ token.getValue(), seconds, TimeUnit.SECONDS) ;\n\t\t\tredisTemplate.expire(AUTH+ token.getValue(), seconds, TimeUnit.SECONDS) ;\n\t\t\t\n\t\t\tredisTemplate.expire(AUTH_TO_ACCESS+ authenticationKeyGenerator.extractKey(authentication), seconds, TimeUnit.SECONDS) ;\n\t\t\tredisTemplate.expire(CLIENT_ID_TO_ACCESS+authentication.getOAuth2Request().getClientId(), seconds, TimeUnit.SECONDS) ;\n\t\t\tredisTemplate.expire(UNAME_TO_ACCESS+ getApprovalKey(authentication), seconds, TimeUnit.SECONDS) ;\n\t\t}\n\t\t\n\t\tOAuth2RefreshToken refreshToken = token.getRefreshToken();\n\t\t\n\t\tif (token.getRefreshToken() != null && token.getRefreshToken().getValue() != null) {\n\t\t\tthis.redisTemplate.opsForValue().set( REFRESH_TO_ACCESS+   token.getRefreshToken().getValue(), token.getValue());\n\t\t\tthis.redisTemplate.opsForValue().set(ACCESS_TO_REFRESH+token.getValue(), token.getRefreshToken().getValue());\n\t\t\t\n\t\t\t\n\t\t\tif (refreshToken instanceof ExpiringOAuth2RefreshToken) {\n\t\t\t\tExpiringOAuth2RefreshToken expiringRefreshToken = (ExpiringOAuth2RefreshToken) refreshToken;\n\t\t\t\tDate expiration = expiringRefreshToken.getExpiration();\n\t\t\t\tif (expiration != null) {\n\t\t\t\t\tint seconds = Long.valueOf((expiration.getTime() - System.currentTimeMillis()) / 1000L)\n\t\t\t\t\t\t\t.intValue();\n\t\t\t\t\t\n\t\t\t\t\tredisTemplate.expire( REFRESH_TO_ACCESS+   token.getRefreshToken().getValue() , seconds, TimeUnit.SECONDS) ;\n\t\t\t\t\tredisTemplate.expire( ACCESS_TO_REFRESH+token.getValue(), seconds, TimeUnit.SECONDS) ;\n\t \n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t\n\t\t}\n\t}\n\n\tprivate String getApprovalKey(OAuth2Authentication authentication) {\n\t\tString userName = authentication.getUserAuthentication() == null ? \"\" : authentication.getUserAuthentication()\n\t\t\t\t.getName();\n\t\treturn getApprovalKey(authentication.getOAuth2Request().getClientId(), userName);\n\t}\n\n\tprivate String getApprovalKey(String clientId, String userName) {\n\t\treturn clientId + (userName==null ? \"\" : \":\" + userName);\n\t}\n\n\n\t@Override\n\tpublic void removeAccessToken(OAuth2AccessToken accessToken) {\n\t\tremoveAccessToken(accessToken.getValue());\n\t}\n\n\t@Override\n\tpublic OAuth2AccessToken readAccessToken(String tokenValue) {\n\t\treturn (OAuth2AccessToken) this.redisTemplate.opsForValue().get(ACCESS+tokenValue);\n\t}\n\tprivate void removeAccessToken(String tokenValue) {\n\t\tOAuth2AccessToken removed = (OAuth2AccessToken) redisTemplate.opsForValue().get(ACCESS+tokenValue);\n\t\t// Don't remove the refresh token - it's up to the caller to do that\n\t\tOAuth2Authentication authentication = (OAuth2Authentication) this.redisTemplate.opsForValue().get(AUTH+tokenValue);\n\t\t\n\t\t\n\t\tthis.redisTemplate.delete(AUTH+tokenValue);\n\t\tredisTemplate.delete(ACCESS+tokenValue);\n\t\tthis.redisTemplate.delete(ACCESS_TO_REFRESH +tokenValue);\n\t\t\n\t\t\n\t\tif (authentication != null) {\n\t\t\tthis.redisTemplate.delete(AUTH_TO_ACCESS+authenticationKeyGenerator.extractKey(authentication));\n\t\t\n\t\t\tString clientId = authentication.getOAuth2Request().getClientId();\n\t\t\t\n//\t\t\tredisTemplate.opsForList().rightPush(\"UNAME_TO_ACCESS:\"+getApprovalKey(authentication), token) ;\n\t\t\tredisTemplate.opsForList().leftPop(UNAME_TO_ACCESS+getApprovalKey(clientId, authentication.getName()));\n\t\t\t\n\t\t\tredisTemplate.opsForList().leftPop(CLIENT_ID_TO_ACCESS+clientId);\n\t\t\t\n\t\t\tthis.redisTemplate.delete(AUTH_TO_ACCESS+authenticationKeyGenerator.extractKey(authentication));\n\t\t}\n\t}\n\n\t@Override\n\tpublic void storeRefreshToken(OAuth2RefreshToken refreshToken, OAuth2Authentication authentication) {\n\t\tthis.redisTemplate.opsForValue().set(REFRESH+refreshToken.getValue(), refreshToken);\n\t\tthis.redisTemplate.opsForValue().set( REFRESH_AUTH + refreshToken.getValue(), authentication);\n\t}\n\t@Override\n\tpublic OAuth2RefreshToken readRefreshToken(String tokenValue) {\n\t\treturn (OAuth2RefreshToken) this.redisTemplate.opsForValue().get(REFRESH+tokenValue);\n\t}\n\n\t@Override\n\tpublic void removeRefreshToken(OAuth2RefreshToken refreshToken) {\n\t\tremoveRefreshToken(refreshToken.getValue());\n\t}\n\n\n\tprivate void removeRefreshToken(String tokenValue) {\n\t\tthis.redisTemplate.delete( REFRESH + tokenValue);\n\t\tthis.redisTemplate.delete( REFRESH_AUTH + tokenValue);\n\t\tthis.redisTemplate.delete(REFRESH_TO_ACCESS +tokenValue);\n\t}\n\n\t@Override\n\tpublic void removeAccessTokenUsingRefreshToken(OAuth2RefreshToken refreshToken) {\n\t\tremoveAccessTokenUsingRefreshToken(refreshToken.getValue());\n\t}\n\n\tprivate void removeAccessTokenUsingRefreshToken(String refreshToken) {\n\t\t\n\t\tString token = (String) this.redisTemplate.opsForValue().get( REFRESH_TO_ACCESS  +refreshToken) ;\n\t\t\n\t\tif (token != null) {\n\t\t\tredisTemplate.delete(REFRESH_TO_ACCESS+ refreshToken);\n\t\t}\n\t}\n\n\t@Override\n\tpublic Collection<OAuth2AccessToken> findTokensByClientIdAndUserName(String clientId, String userName) {\n\t\tList<Object> result =    redisTemplate.opsForList().range(UNAME_TO_ACCESS+ getApprovalKey(clientId, userName), 0, -1);\n\t\t\n\t\tif (result == null || result.size() == 0) {\n\t\t\treturn Collections.<OAuth2AccessToken> emptySet();\n\t\t}\n\t\tList<OAuth2AccessToken> accessTokens = new ArrayList<OAuth2AccessToken>(result.size());\n\t\t\n\t\tfor(Iterator<Object> it = result.iterator();it.hasNext();){\n\t\t\tOAuth2AccessToken accessToken = (OAuth2AccessToken) it.next();\n\t\t\taccessTokens.add(accessToken);\n\t\t}\n\t\t\n\t\treturn Collections.<OAuth2AccessToken> unmodifiableCollection(accessTokens); \n\t}\n\n\t@Override\n\tpublic Collection<OAuth2AccessToken> findTokensByClientId(String clientId) {\n\t\tList<Object> result =    redisTemplate.opsForList().range((CLIENT_ID_TO_ACCESS+clientId), 0, -1);\n\t\t\n\t\tif (result == null || result.size() == 0) {\n\t\t\treturn Collections.<OAuth2AccessToken> emptySet();\n\t\t}\n\t\tList<OAuth2AccessToken> accessTokens = new ArrayList<OAuth2AccessToken>(result.size());\n\t\t\n\t\tfor(Iterator<Object> it = result.iterator();it.hasNext();){\n\t\t\tOAuth2AccessToken accessToken = (OAuth2AccessToken) it.next();\n\t\t\taccessTokens.add(accessToken);\n\t\t}\n\t\t\n\t\treturn Collections.<OAuth2AccessToken> unmodifiableCollection(accessTokens); \n\t}\n\n\n}\n\n"
  },
  {
    "path": "open-oauth-center/open-oauth-server/src/main/java/com/open/capacity/utils/SpringUtil.java",
    "content": "package com.open.capacity.utils;\n\nimport org.springframework.beans.BeansException;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.ApplicationContextAware;\nimport org.springframework.core.env.Environment;\nimport org.springframework.stereotype.Component;\n\n/**\n * spring获取bean工具类\n *\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2018年3月20日 下午10:13:18 类说明\n */\n@Component\npublic class SpringUtil implements ApplicationContextAware {\n\n    private static ApplicationContext applicationContext = null;\n\n    @Override\n    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {\n        SpringUtil.applicationContext = applicationContext;\n    }\n\n    public static <T> T getBean(Class<T> cla) {\n        return applicationContext.getBean(cla);\n    }\n\n    public static <T> T getBean(String name, Class<T> cal) {\n        return applicationContext.getBean(name, cal);\n    }\n\n    public static String getProperty(String key) {\n        return applicationContext.getBean(Environment.class).getProperty(key);\n    }\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-server/src/main/resources/application.yml",
    "content": "server:\n  port: 8000\nspring:\n  application:\n    name: open-auth-server\n  session:\n    store-type: redis  \n  datasource:\n      type: com.alibaba.druid.pool.DruidDataSource\n#      driver-class-name:  oracle.jdbc.OracleDriver\n#      url: jdbc:oracle:thin:@127.0.0.1:1521:orcl\n#      username: crm_owner_user\n#      password: bss_crm_test\n#      filters: stat,wall\n################## mysql start ############################\n      driver-class-name:  com.mysql.jdbc.Driver\n      #     192.168.3.150   130.75.131.211  134.224.249.39  47.94.252.160\n      url: jdbc:mysql://192.168.3.150:3306/boot_security?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false\n      username: root\n      password: root\n      filters: stat,wall\n################### mysq end l##########################\n  redis:\n################### redis 单机版 start ########################## \n    host: 127.0.0.1\n    port: 6379    \n    timeout: 3000\n    database: 1\n################### redis 单机版 end ##########################   \n#    cluster:\n#      nodes: 130.75.131.237:7000,130.75.131.238:7000,130.75.131.239:7000,130.75.131.237:7001,130.75.131.238:7001,130.75.131.239:7001\n###        #130.75.131.237:7000,130.75.131.238:7000,130.75.131.239:7000,130.75.131.237:7001,130.75.131.238:7001,130.75.131.239:7001\n##        #192.168.3.157:7000,192.168.3.158:7000,192.168.3.159:7000,192.168.3.157:7001,192.168.3.158:7001,192.168.3.159:7001\n#    timeout: 1000 # 连接超时时间（毫秒）\n#    pool:\n#      max-active: 10  # 连接池最大连接数（使用负值表示没有限制）\n#      max-idle: 8     # 连接池中的最大空闲连接\n#      min-idle: 2     # 连接池中的最小空闲连接\n#      max-wait: 100   # 连接池最大阻塞等待时间（使用负值表示没有限制）       \n    \n    \n\nmybatis:\n  config-location: classpath:mybatis.cfg.xml\n  mapper-locations: classpath*:com/open/**/dao/*.xml  \n\n\nsecurity:\n  oauth2:\n    resource:\n      filter-order: 3\n    token:\n      store:\n        type: redis\n\n \n\neureka:\n  client:\n    healthcheck:\n      enabled: true\n    serviceUrl:\n      defaultZone:  http://127.0.0.1:1111/eureka  #http://130.75.131.241:8761/eureka,http://130.75.131.248:8762/eureka\n      #http://134.224.249.33:1111/eureka/  正式库\n      #http://134.224.249.33:1111/eureka/  测试库\n      #http://127.0.0.1:8761/eureka,http://127.0.0.1:8762/eureka\n  instance:\n    prefer-ip-address: true\n    instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}\n    #instance-id: ${spring.application.name}:${docker.ipAddress}:${spring.application.instance_id:${server.port}}\n    lease-renewal-interval-in-seconds: 5  #每隔几秒告诉eureka服务器我还存活，用于心跳检测\n    lease-expiration-duration-in-seconds: 10 #如果心跳检测一直没有发送，10秒后会从eureka服务器中将此服务剔除\n    #注册实例文档\n    status-page-url: http://${spring.cloud.client.ipAddress}:${server.port}/doc.html # ${server.port}为该服务的端口号\n#    status-page-url: http://${docker.ipAddress}:${server.port}/auth/doc.html # ${server.port}为该服务的端口号\nlogging:\n  level:\n    root: INFO\n    org.hibernate: INFO\n    org.hibernate.type.descriptor.sql.BasicBinder: TRACE\n    org.hibernate.type.descriptor.sql.BasicExtractor: TRACE\n#    com.neusoft: DEBUG     \n#    com.netflix: DEBUG                    #用于心跳检测输出的日志\n    \n\n\n\n\n  \n "
  },
  {
    "path": "open-oauth-center/open-oauth-server/src/main/view/static/css/import_main.css",
    "content": "html,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,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td{margin:0;padding:0;border:0}article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block}body{line-height:1}ol,ul,li{list-style:none}ins{text-decoration:none}del{text-decoration:line-through}table{border-spacing:0;border-collapse:collapse}iframe{display:block}#login_tb input{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding-top:0;padding-bottom:0}.clearfix{display:block;zoom:1}.clearfix:after{display:block;visibility:hidden;clear:both;height:0;content:\".\"}body{font:12px/1.5 Arial,sans-serif}a{color:#00c;text-decoration:underline}a:focus{outline:1px dotted}h1{font-weight:400;font-size:12px}ol{list-style:decimal}pre,code,kbd,samp,tt{font-family:monospace;line-height:100%}.pull-left{float:left}.pull-right{float:right}.ico-error,.ico-suc{display:inline-block;width:21px;height:21px;background:url(https://openapi.baidu.com/static/oauth/common/image/notice-ico_cdfda67.png) no-repeat 0 0;vertical-align:middle;*display:inline;*zoom:1}.ico-suc{background-position:-89px 0}.title-important{margin-bottom:30px;text-align:center}.title-important h3{color:#333;font-size:14px;line-height:22px}.title-important .ico-error,.title-important .ico-suc{margin-right:10px}.error-msg-list{margin:20px auto;width:450px;color:#999}.error-msg-list li{margin:20px}.device{margin:0 auto;width:250px;color:#999}.device p{line-height:30px}.device .welcome{margin-bottom:40px;color:#000;font-weight:700;font-size:14px}.device-user-code-form .input-text{width:240px}.device-user-code-form .user-code-error{color:#f7461c}.device-user-code-form .tip{margin:40px 0 25px}.device .btn{display:block;margin:0 auto 20px;padding:0;width:150px}.device-result{padding-bottom:20px;color:#666;text-align:center}#d_clip_button *{vertical-align:top}.btn{padding:0 20px;height:32px;border:solid 1px #2f5bb7;background:#3880f5;color:#fff;font-size:14px;cursor:pointer}.btn:hover{background:#4c8cf5}.btn-weaken{border-color:#dadada;background:#efefef;color:#111}.btn-weaken:hover{background:#f2f2f2}.btn-disabled,.btn-disabled:hover{border-color:#ccc;background:#ccc;cursor:default}.btn-inline{display:inline-block;-moz-box-sizing:border-box;box-sizing:border-box;line-height:32px;*zoom:1;*display:inline}.g-bd{margin:0 auto;width:670px}.dialog .g-bd{width:500px}.g-bd-wp{margin:20px;padding:20px;border:solid 1px #ddd}.dialog .g-bd-wp{padding:0;border:0}.two-cols{background:url(https://openapi.baidu.com/static/oauth/common/image/bg_col_split_891ad6d.png) repeat-y 50% 0;font-size:0}.two-cols .login,.two-cols .scope,.two-cols .user{display:inline-block;width:50%;vertical-align:top;font-size:12px;*display:inline;*zoom:1}.two-cols .login,.two-cols .user{float:left}.two-cols .scope{float:right}.rows-split{padding-top:10px;border-top:dotted 1px #ddd}.page-tip{padding-bottom:20px;color:#666;text-align:center}.controls{position:relative;margin-top:15px;color:#333}.controls-title{position:absolute;top:0;left:0;width:42px;height:32px;text-align:right;font-size:12px;line-height:32px}.controls-content{position:relative;margin-left:50px}.input{position:relative;display:inline-block;overflow:hidden;padding:0 5px;border:solid 1px #ccc;vertical-align:top;*display:inline;*zoom:1}.input:before,.input:after{position:absolute;overflow:hidden;box-shadow:0 0 6px #aaa;content:\"\"}.input:before{top:-1px;left:0;width:100%;height:1px}.input:after{top:0;left:-1px;width:1px;height:100%}.input .input-text{margin:0;padding:6px 0;height:18px;outline:0;border:0;background:0 0;vertical-align:top;font-size:14px}.input-focus{border-color:#377bcb}.input-errpr{border-color:#d91111}.form-error{margin-left:50px;height:30px;color:#da1111;line-height:30px}"
  },
  {
    "path": "open-oauth-center/open-oauth-server/src/main/view/static/css/page_all.css",
    "content": "@charset \"UTF-8\"; .login .psWrapper{width:250px;margin-left:15px}.dialog .login .psWrapper{width:210px;margin-left:0}.dialog .tang-pass-login{padding:0}.login .title{font-size:14px;font-weight:700}.login .pass-form-item-submit .btn-disabled,.login .pass-form-item-submit .btn-disabled:hover,.login .user .btn-disabled,.login .user .btn-disabled:hover{background:none repeat scroll 0 0 #CCC;border-color:#CCC;cursor:default}.tang-pass-login a,.tang-pass-login label,.tang-pass-login p,.tang-pass-login li,.tang-pass-login input{font-size:12px;margin:0;padding:0;list-style:none}.tang-pass-login input[type=submit]{-webkit-appearance:none;box-sizing:content-box;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;-ms-box-sizing:content-box}.tang-pass-login input::-webkit-input-placeholder{color:#ccc}.tang-pass-login input:-ms-input-placeholder{color:#ccc}.tang-pass-login input:-moz-placeholder{color:#ccc}.tang-pass-login .pass-label{display:block;font-size:12px;color:#666;padding-bottom:10px;display:none}.tang-pass-login label.pass-label-userName,.tang-pass-login label.pass-label-password,.tang-pass-login label.pass-label-smsPhone{display:block;position:absolute;top:6px;left:0;width:0;height:18px;overflow:hidden;padding:0 0 0 18px;background:url(https://passport.baidu.com/passApi/img/input_icons_16.png) no-repeat;z-index:20}.tang-pass-login label.pass-label-userName{background-position:4px -46px}.tang-pass-login label.pass-label-password{background-position:4px 1px}.tang-pass-login label.pass-label-smsPhone{background-position:4px -91px}.tang-pass-login .pass-form-item-userName label.pass-text-label-focus{background-position:4px -70px}.tang-pass-login .pass-form-item-password label.pass-text-label-focus{background-position:4px -23px}.tang-pass-login .pass-form-item-smsPhone label.pass-text-label-focus{background-position:4px -115px}.tang-pass-login{padding:0 20px 10px;position:relative}.tang-pass-login a{color:#1B66C7;text-decoration:none}.tang-pass-login a:hover{text-decoration:underline}.tang-pass-login-hide{position:absolute;top:-9999px}.tang-pass-login .pass-generalErrorWrapper{color:#FC4343;height:auto;_height:28px;min-height:28px}.tang-pass-login .pass-generalError{display:block;font-size:12px;line-height:14px;padding-top:8px}.tang-pass-login .pass-form-item{clear:both;position:relative;z-index:18}.tang-pass-login .pass-form-item.pass-form-item-userName{z-index:21}input::-ms-clear{display:none}input::-ms-reveal{display:none}.tang-pass-login .pass-form-item .pass-text-input{border:1px solid #DEDEDE;color:#666;display:block;font-size:12px;height:14px;margin-bottom:15px;padding:6px 10px;position:relative;transition:.3s;width:158px;z-index:17}.tang-pass-login .pass-form-item .pass-text-input-focus{border-color:#488EE7}.tang-pass-login .pass-form-item .pass-text-input-error{border-color:#FC4343}.tang-pass-login .pass-form-item .pass-text-input-verifyCode{float:left;width:76px}.tang-pass-login .pass-form-item input.pass-text-input-userName{padding-left:20px;width:176px}.tang-pass-login .pass-form-item input.pass-text-input-userName:focus{}.tang-pass-login .pass-form-item input.pass-text-input-password{padding-left:20px;width:176px}.tang-pass-login .pass-form-item input.pass-text-input-password:focus{}.tang-pass-login .pass-form-item input.open{padding-right:22px;width:164px}.tang-pass-login .pass-form-item .pass-item-selectbtn-userName{background:url(https://passport.baidu.com/passApi/img/pass_login_icons.png) no-repeat 0 -30px;position:absolute;display:block;height:16px;width:16px;top:6px;right:31px;_right:50px;cursor:pointer}.tang-pass-login .pass-form-item .pass-item-selectbtn-userName:hover{background-position:0 -46px}.tang-pass-login .pass-form-item span.open{background-position:-18px -30px}.tang-pass-login .pass-form-item span.open:hover{background-position:-18px -46px}.tang-pass-login .pass-verifyCode{background:url(https://passport.baidu.com/passApi/img/loading_16.gif) no-repeat center center;border:1px solid #DDD;float:left;height:26px;margin-left:5px;width:62px}.tang-pass-login .pass-change-verifyCode{cursor:pointer;float:left;font-size:12px;line-height:26px;padding-left:5px;text-decoration:none}.tang-pass-login .pass-form-item .pass-placeholder{color:#CCC;cursor:text;display:block;font-size:12px;height:28px;left:0;line-height:28px;_line-height:30px;padding-left:13px;position:absolute;top:1px;width:140px;z-index:1999}.tang-pass-login .pass-form-item .pass-placeholder-verifyCode{left:0;width:50px}.tang-pass-login .pass-form-item .pass-placeholder-userName,.tang-pass-login .pass-form-item .pass-placeholder-password{left:10px}.tang-pass-login .pass-form-item .pass-clearbtn{background:url(https://passport.baidu.com/passApi/img/pass_login_icons.png) no-repeat scroll 0 0 transparent;cursor:pointer;height:16px;position:absolute;right:6px;_right:26px;top:7px;width:16px;z-index:20}.tang-pass-login .pass-form-item span.pass-clearbtn-verifyCode{left:75px;right:inherit;z-index:1999}.tang-pass-login .pass-form-item span.pass-clearbtn-smsVerifyCode{left:90px;right:inherit}.tang-pass-login .pass-form-item .pass-clearbtn:hover{background-position:0 -16px}.tang-pass-login .pass-form-item-memberPass{margin-bottom:10px}.tang-pass-login .pass-form-item-memberPass input{vertical-align:middle}.tang-pass-login .pass-form-item-memberPass label{color:#666;margin-left:5px}.tang-pass-login .pass-form-item-submit{position:relative}.tang-pass-login .pass-form-item-submit input{background:#3F89EC;border-radius:3px;height:32px;transition:.3s;width:208px}.tang-pass-login .pass-form-item-submit input:hover{background:#4490F7}.tang-pass-login .pass-form-item-submit input:focus{background:#3A84E8}.tang-pass-login .pass-form-item-submit .pass-button-submit{border:0;color:#FFF;cursor:pointer;font-size:14px;font-weight:700}.tang-pass-login .pass-form-item-submit .pass-reglink{position:absolute;right:0;_right:20px;top:40px}.tang-pass-login .pass-form-item-submit .pass-fgtpwd{position:absolute;right:0;_right:20px;top:-26px}#pass-phoenix-login{border-top:1px solid #EEE;margin-top:24px;padding:0 20px 10px}#pass-phoenix-login .pass-phoenix-title{color:#666;font-size:12px;height:28px;line-height:28px;padding:2px 0}#pass-phoenix-login .pass-phoenix-list{clear:both;line-height:20px;zoom:1}#pass-phoenix-login .pass-phoenix-list:after{clear:both;content:'\\20';display:block;height:0;line-height:20px}#pass-phoenix-login #pass_phoenix_btn{float:left}#pass-phoenix-login .pass-phoenix-list .bd-acc-list{float:left;margin:0;padding:0;width:100px}.pass-qrcode-btn,.pass-sms-btn,.pass-normal-btn,.pass-unamelogin-btn,.pass-emaillogin-btn{background:url(https://passport.baidu.com/passApi/img/pass_login_icons.png) no-repeat scroll -181px -64px transparent;color:#00C;cursor:pointer;display:inline-block;float:left;font-size:12px;height:18px;margin-right:15px;overflow:hidden;padding-left:18px;text-decoration:underline;width:0}.pass-normal-btn{background-position:-217px -64px}.pass-unamelogin-btn{background-position:-217px -64px}.pass-sms-btn{background-position:-108px -64px}#pass-phoenix-login .pass-phoenix-list .bd-acc-tsina{background-position:0 -64px}#pass-phoenix-login .pass-phoenix-list .bd-acc-renren{background-position:-72px -64px}#pass-phoenix-login .pass-phoenix-list .bd-acc-qzone{background-position:-36px -64px}#pass-phoenix-login .pass-phoenix-list li{color:#00C;cursor:pointer;display:inline-block;float:left;font-size:12px;height:18px;list-style:none;margin-right:15px;overflow:hidden;padding-left:18px;text-decoration:underline;width:0}#pass-phoenix-list-login li{background:url(https://passport.baidu.com/passApi/img/pass_login_icons.png) no-repeat scroll 0 0 transparent}.choiceuser-article{padding:0 20px}.choiceuser-article .choiceuser-msg{color:#666;font-size:12px;line-height:24px;margin-top:10px}.choiceuser-article .choiceuser-back{clear:both;margin-top:10px}.choiceuser-article .choiceuser-back a{color:#1B66C7;display:block;text-align:right;text-decoration:none}.choiceuser-article .choiceuser-btn:after{clear:both;content:\" \";display:block;height:0}.choiceuser-article .choiceuser-btn{padding-left:20px;zoom:1}.choiceuser-article .choiceuser-btn input{background-color:#F7F7F7;border:1px solid #DDD;border-radius:3px;color:#666;cursor:pointer;display:block;float:left;font-weight:700;height:32px;margin:10px 10px 0 0;transition:all .3s ease 0s;width:80px}.choiceuser-article .choiceuser-btn input:hover{background-color:#EEE;border-color:#DADADA}.tang-pass-qrcode{padding:0 20px}.tang-pass-qrcode .tang-pass-qrcode-title{color:#666;font-weight:700;height:30px;line-height:30px}.tang-pass-qrcode .tang-pass-qrcode-content{margin:30px 0;text-align:center}.tang-pass-qrcode .tang-pass-qrcode-content img{height:100px;width:100px}.tang-pass-qrcode .tang-pass-qrcode-info{color:#999;font-weight:400;line-height:18px}.tang-pass-qrcode .pass-qrcode-link-back{color:#1B66C7;cursor:pointer;display:block;text-align:right;text-decoration:none}.tang-pass-qrcode .pass-qrcode-link-back:hover{text-decoration:underline}.tang-pass-sms{display:none}.tang-pass-sms .tang-pass-sms-title{color:#666;font-weight:700;height:30px;line-height:30px;visibility:hidden}.tang-pass-sms .tang-pass-sms-tip{color:#999;font-weight:400;line-height:18px}.tang-pass-sms p.pass-form-item-smsVerifyCode:after,.tang-pass-login p.pass-form-item-verifyCode:after{clear:both;content:\" \";display:block;height:0;line-height:20px}.tang-pass-sms p.pass-form-item-smsVerifyCode,.tang-pass-login p.pass-form-item-verifyCode{height:28px;margin-bottom:15px;position:relative;zoom:1}.tang-pass-sms .pass-form-item .pass-sms-link-back{display:block;padding-top:10px;text-align:right;cursor:pointer}.tang-pass-sms .pass-form-item input.pass-text-input-smsPhone{padding-left:20px;width:176px}.tang-pass-sms .pass-form-item input.pass-text-input-smsPhone:focus{}.tang-pass-sms .pass-form-item input.pass-text-input-smsVerifyCode{float:left;margin-right:10px;width:90px}.tang-pass-sms .pass-form-item span.pass-placeholder-smsPhone{padding-left:22px}.tang-pass-sms .pass-form-item span.pass-placeholder-smsVerifyCode{width:70px}.tang-pass-sms .pass-form-item span.pass-item-timer,.tang-pass-sms .pass-form-item span.pass-item-time-timing{width:84px}.tang-pass-login .pass-item-timer{background-color:#F7F7F7;border:1px solid #DDD;color:#666;cursor:pointer;display:block;float:left;font-size:12px;height:28px;padding:0;transition:all .3s ease 0s;width:84px}.tang-pass-login .pass-item-timer:hover{background-color:#EEE;border-color:#DADADA}.tang-pass-login .pass-item-time-timing{background-color:#F6F6F6;border:1px solid #EBEBEB;color:#999;cursor:default;display:block;float:left;font-size:12px;height:28px;padding:0;transition:all .3s ease 0s;width:84px}.tang-pass-login .pass-suggestion-list{position:absolute;margin:0;padding:0;z-index:21;top:28px;_top:29px;left:0;border:1px solid #dedede;border-top:0;background:#fff;width:206px}.tang-pass-login li.pass-item-suggsetion{color:#333;cursor:pointer;font-family:'宋体';font-size:12px;line-height:14px;padding:5px 0 5px 6px;position:relative;word-break:break-all;z-index:2001}.tang-pass-login li.pass-item-suggsetion a{background:url(https://passport.baidu.com/passApi/img/pass_login_icons.png) no-repeat 0 0;display:none;height:16px;position:absolute;right:4px;top:4px;width:16px}.tang-pass-login li.pass-item-suggsetion_hover a{display:block}.tang-pass-login li.pass-item-suggsetion a:hover{background-position:0 -16px}.tang-pass-login .pass-item-suggsetion_hover{background-color:#F7F7F7}.tang-pass-login .pass-form-item-submit input,.choiceuser-article .choiceuser-btn input{background-clip:padding-box}.pass-normal-btn,.pass-qrcode-btn{box-sizing:border-box;background-image:none;text-decoration:none;border:1px solid #3f89ec;background:#3f89ec;color:#fff;text-align:center;line-height:32px;height:32px;width:100%;padding-left:0;border-radius:0;font-size:14px;display:block;font-weight:700;font-size:14px}.page-tip{display:none}.tang-pass-login .pass-form-item-submit .pass-button-submit{border-radius:0}\n.scope .title,.scope form{margin:0 20px}.scope .title{margin-bottom:10px;color:#333}.scope-list{margin-bottom:10px;line-height:20px;color:#999}.scope-list li{margin-bottom:10px}.scope-form .checkbox{vertical-align:-3px;margin:0 10px 0 0}.scope a{color:#06c}\n.topbar,.topbar .g-bd{height:62px;background:#efefef url(https://openapi.baidu.com/static/oauth/widget/page.topbar/images/topbar_a5cb152.png) repeat-x}.topbar .hd-c{width:670px;margin:0 auto}.topbar .logo{display:inline;float:left;width:104px;height:35px;margin:13px 0 0 20px;overflow:hidden;background:#efefef url(https://openapi.baidu.com/static/oauth/widget/page.topbar/images/logo_7baea46.png) no-repeat;font-size:12px;text-indent:-20em}.topbar-nav{display:inline;float:right;margin:30px 20px 0 0;color:#666}.topbar-nav strong{font-weight:400}.topbar-nav strong,.topbar-nav a{margin:0 10px}\n.user .title{font-weight:700;font-size:14px;line-height:24px;text-align:center}.user .btn{display:block;width:150px;padding:0;margin:0 auto 20px}.user-avatar{margin:30px 0;text-align:center}.user-avatar .user-name{font-weight:400;color:#333}.user-avatar-img{display:block;width:80px;height:80px;margin:0 auto 20px;border:solid 2px #d9dde0;border-radius:5px}.user-avatar-img img{width:80px;height:80px;border-radius:5px}.two-cols .user-inner{width:160px;margin:0 auto}.two-cols .user .title{text-align:left}"
  },
  {
    "path": "open-oauth-center/open-oauth-server/src/main/view/static/css/saved_resource.html",
    "content": "\n<!-- saved from url=(0011)about:blank -->\n<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"></head><body></body></html>"
  },
  {
    "path": "open-oauth-center/open-oauth-server/src/main/view/static/hello.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<title>Insert title here</title>\n</head>\n<body>\n\n</body>\n\thello world\n</html>"
  },
  {
    "path": "open-oauth-center/open-oauth-server/src/main/view/static/index.html",
    "content": "hello"
  },
  {
    "path": "open-oauth-center/open-oauth-server/src/main/view/static/js/import_base_tan_802b7ff.js",
    "content": "function getLocationParams(){for(var e,t=location.search.substring(1),n=t.split(\"&\"),r={},i=0,o=n.length;o>i;i++)e=n[i].split(\"=\"),2==e.length&&(r[e[0]]=e[1]);return r}function urlMergeParams(e){var t,n,r=getLocationParams(),i=[],o=location.href;for(t in e)r[t]=e[t];for(t in r)n=e[t],null!==r[t]&&i.push(t+\"=\"+r[t]);return o.replace(location.search,\"?\"+i.join(\"&\"))}function getGrantPermissions(e,t){var n,r,i=0,o=[];if(t&&o.push(t),e&&(n=e.length))for(;n>i;i++)r=e[i],r.checked&&o.push(r.value);else e&&(r=e)&&r.checked&&o.push(r.value);return o.join(\",\")}var T,baidu=T=function(){var e,t=e=t||function(e,n){return t.dom?t.dom(e,n):null};t.version=\"2.0.2.5\",t.guid=\"$BAIDU$\",t.key=\"tangram_guid\";var n=window[t.guid]=window[t.guid]||{};return(n.versions||(n.versions=[])).push(t.version),t.check=t.check||function(){},t.lang=t.lang||{},t.forEach=function(e,t,n){var r,i,o;if(\"function\"==typeof t&&e)if(i=\"number\"==typeof e.length?e.length:e.byteLength,\"number\"==typeof i){if(\"[object Function]\"===Object.prototype.toString.call(e))return e;for(r=0;i>r;r++)o=e[r],void 0===o&&(o=e.charAt&&e.charAt(r)),t.call(n||null,o,r,e)}else if(\"number\"==typeof e)for(r=0;e>r;r++)t.call(n||null,r,r,r);else if(\"object\"==typeof e)for(r in e)e.hasOwnProperty(r)&&t.call(n||null,e[r],r,e);return e},t.type=function(){var e={},n=[,\"HTMLElement\",\"Attribute\",\"Text\",,,,,\"Comment\",\"Document\",,\"DocumentFragment\"],r=\"Array Boolean Date Error Function Number RegExp String\",i={object:1,\"function\":\"1\"},o=e.toString;return t.forEach(r.split(\" \"),function(n){e[\"[object \"+n+\"]\"]=n.toLowerCase(),t[\"is\"+n]=function(e){return t.type(e)==n.toLowerCase()}}),function(t){var r=typeof t;return i[r]?null==t?\"null\":t._type_||e[o.call(t)]||n[t.nodeType]||(t==t.window?\"Window\":\"\")||\"object\":r}}(),t.isDate=function(e){return\"date\"==t.type(e)&&\"Invalid Date\"!=e.toString()&&!isNaN(e)},t.isElement=function(e){return\"HTMLElement\"==t.type(e)},t.isEnumerable=function(e){return null!=e&&(\"object\"==typeof e||~Object.prototype.toString.call(e).indexOf(\"NodeList\"))&&(\"number\"==typeof e.length||\"number\"==typeof e.byteLength||\"undefined\"!=typeof e[0])},t.isNumber=function(e){return\"number\"==t.type(e)&&isFinite(e)},t.isPlainObject=function(e){var n,r=Object.prototype.hasOwnProperty;if(\"object\"!=t.type(e))return!1;if(e.constructor&&!r.call(e,\"constructor\")&&!r.call(e.constructor.prototype,\"isPrototypeOf\"))return!1;for(n in e);return void 0===n||r.call(e,n)},t.isObject=function(e){return\"function\"==typeof e||\"object\"==typeof e&&null!=e},t.extend=function(e,n){var r,i,o,a,s,u,c=1,l=arguments.length,f=e||{};for(t.isBoolean(e)&&(c=2)&&(f=n||{}),!t.isObject(f)&&(f={});l>c;c++)if(r=arguments[c],t.isObject(r))for(i in r)o=f[i],a=r[i],o!==a&&(t.isBoolean(e)&&e&&a&&(t.isPlainObject(a)||(s=t.isArray(a)))?(s?(s=!1,u=o&&t.isArray(o)?o:[]):u=o&&t.isPlainObject(o)?o:{},f[i]=t.extend(e,u,a)):void 0!==a&&(f[i]=a));return f},t.createChain=function(e,n,r){var i=\"dom\"==e?\"$DOM\":\"$\"+e.charAt(0).toUpperCase()+e.substr(1),o=Array.prototype.slice,a=t[e];return a?a:(a=t[e]=n||function(n){return t.extend(n,t[e].fn)},a.extend=function(n){var r;for(r in n)!function(n){\"splice\"!=n&&(a[n]=function(){var r=arguments[0];\"dom\"==e&&\"string\"==t.type(r)&&(r=\"#\"+r);var i=a(r),s=i[n].apply(i,o.call(arguments,1));return\"$DOM\"==t.type(s)?s.get(0):s})}(r);return t.extend(t[e].fn,n)},t[e][i]=t[e][i]||r||function(){},a.fn=t[e][i].prototype,a)},t.overwrite=function(e,t,n){for(var r=t.length-1;r>-1;r--)e.prototype[t[r]]=n(t[r]);return e},t.object=t.object||{},t.object.isPlain=t.isPlainObject,t.createChain(\"string\",function(e){var n=t.type(e),r=new String(~\"string|number\".indexOf(n)?e:n),i=String.prototype;return t.forEach(t.string.$String.prototype,function(e,t){i[t]||(r[t]=e)}),r}),t.string.extend({trim:function(){var e=new RegExp(\"(^[\\\\s\\\\t\\\\xa0\\\\u3000]+)|([\\\\u3000\\\\xa0\\\\s\\\\t]+$)\",\"g\");return function(){return this.replace(e,\"\")}}()}),t.createChain(\"array\",function(e){var n,r=t.array.$Array.prototype;Array.prototype,\"array\"!=t.type(e)&&(e=[]);for(n in r)e[n]=r[n];return e}),t.overwrite(t.array.$Array,\"concat slice\".split(\" \"),function(e){return function(){return t.array(Array.prototype[e].apply(this,arguments))}}),t.array.extend({indexOf:function(e,n){t.check(\".+(,number)?\",\"baidu.array.indexOf\");var r=this.length;for((n=0|n)<0&&(n=Math.max(0,r+n));r>n;n++)if(n in this&&this[n]===e)return n;return-1}}),t.createChain(\"Callbacks\",function(e){var n=e;return\"string\"===t.type(e)&&(n={},t.forEach(e.split(/\\s/),function(e){n[e]=!0})),new t.Callbacks.$Callbacks(n)},function(e){var n,r,i,o,a=t.extend({},e||{}),s=[],u=[],c=0,l=function(e,t){var r,l;if(u&&s&&(n=a.memory&&e,i=!0,u.push(e),!o)){for(o=!0;r=u.shift();)for(c=t||0;l=s[c];c++)if(l.apply(r[0],r[1])===!1&&a.stopOnFalse){n=!1;break}o=!1,a.once&&(s=[])}},f={add:function(){if(!s)return this;var e=s&&s.length;return function r(e){for(var n,i,i,o=e.length,u=0;o>u;u++)(i=e[u])&&(n=t.type(i),\"function\"===n?(!a.unique||!f.has(i))&&s.push(i):i&&i.length&&\"string\"!==n&&r(i))}(arguments),!o&&n&&l(n,e),this},remove:function(){if(!s)return this;var e;return t.forEach(arguments,function(n){for(;(e=t.array(s).indexOf(n))>-1;)s.splice(e,1),o&&c>e&&c--}),this},has:function(e){return t.array(s).indexOf(e)>-1},empty:function(){return s=[],this},disable:function(){return s=u=n=void 0,this},disabled:function(){return!s},lock:function(){return r=!0,!n&&f.disable(),this},fired:function(){return i},fireWith:function(e,t){return i&&a.once||r?this:(t=t||[],t=[e,t.slice?t.slice():t],l(t),this)},fire:function(){return f.fireWith(this,arguments),this}};return f}),t.createChain(\"Deferred\",function(e){return new t.Deferred.$Deferred(e)},function(e){var n=this,r=\"pending\",i=[[\"resolve\",\"done\",t.Callbacks(\"once memory\"),\"resolved\"],[\"reject\",\"fail\",t.Callbacks(\"once memory\"),\"rejected\"],[\"notify\",\"progress\",t.Callbacks(\"memory\")]],o={state:function(){return r},always:function(){return n.done(arguments).fail(arguments),this},then:function(){var e=arguments;return t.Deferred(function(r){t.forEach(i,function(i,o){var a=i[0],s=e[o];n[i[1]](\"function\"===t.type(s)?function(){var e=s.apply(this,arguments);e&&\"function\"===t.type(e.promise)?e.promise().done(r.resolve).fail(r.reject).progress(r.notify):r[a+\"With\"](this===n?r:this,[e])}:r[a])})}).promise()},promise:function(e){return null!=e?t.extend(e,o):o}};o.pipe=o.then,t.forEach(i,function(e,t){var a=e[2],s=e[3];o[e[1]]=a.add,s&&a.add(function(){r=s},i[1^t][2].disable,i[2][2].lock),n[e[0]]=a.fire,n[e[0]+\"With\"]=a.fireWith}),o.promise(n),e&&e.call(n,n)}),t.when=t.when||function(e){function n(e,t,n){return function(i){t[e]=this,n[e]=arguments.length>1?arguments:i,n===r?c.notifyWith(t,n):--u||c.resolveWith(t,n)}}var r,i,o,a=arguments,s=arguments.length,u=1!==s||e&&\"function\"===t.type(e.promise)?s:0,c=1===u?e:t.Deferred();if(s>1){r=new Array(s),i=new Array(s),o=new Array(s);for(var l=0;s>l;l++)a[l]&&\"function\"===t.type(a[l].promise)?a[l].promise().done(n(l,o,a)).fail(c.reject).progress(n(l,i,r)):--u}return!u&&c.resolveWith(o,a),c.promise()},t.global=t.global||function(){var e=t._global_=window[t.guid],n=e._=e._||{};return function(e,t,r){return\"undefined\"!=typeof t?(r||(t=\"undefined\"==typeof n[e]?t:n[e]),n[e]=t):e&&\"undefined\"==typeof n[e]&&(n[e]={}),n[e]}}(),t.browser=t.browser||function(){var e=navigator.userAgent,n={isStrict:\"CSS1Compat\"==document.compatMode,isGecko:/gecko/i.test(e)&&!/like gecko/i.test(e),isWebkit:/webkit/i.test(e)};try{/(\\d+\\.\\d+)/.test(external.max_version)&&(n.maxthon=+RegExp.$1)}catch(r){}switch(!0){case/msie (\\d+\\.\\d+)/i.test(e):n.ie=document.documentMode||+RegExp.$1;break;case/chrome\\/(\\d+\\.\\d+)/i.test(e):n.chrome=+RegExp.$1;break;case/(\\d+\\.\\d)?(?:\\.\\d)?\\s+safari\\/?(\\d+\\.\\d+)?/i.test(e)&&!/chrome/i.test(e):n.safari=+(RegExp.$1||RegExp.$2);break;case/firefox\\/(\\d+\\.\\d+)/i.test(e):n.firefox=+RegExp.$1;break;case/opera(?:\\/| )(\\d+(?:\\.\\d+)?)(.+?(version\\/(\\d+(?:\\.\\d+)?)))?/i.test(e):n.opera=+(RegExp.$4||RegExp.$1)}return t.extend(t,n),n}(),t.id=function(){var e=t.global(\"_maps_id\"),n=t.key;return window[t.guid]._counter=window[t.guid]._counter||1,function(r,i){var o,a=t.isString(r),s=t.isObject(r),u=s?r[n]:a?r:\"\";if(t.isString(i))switch(i){case\"get\":return s?u:e[u];case\"remove\":case\"delete\":return(o=e[u])&&(t.isElement(o)&&t.browser.ie<8?o.removeAttribute(n):delete o[n],delete e[u]),u;default:return a?((o=e[u])&&delete e[u],o&&(e[o[n]=i]=o)):s&&(u&&delete e[u],e[r[n]=i]=r),i}return s?(!u&&(e[r[n]=u=t.id()]=r),u):a?e[r]:\"TANGRAM_\"+t._global_._counter++}}(),t._util_=t._util_||{},t._util_.support=t._util_.support||function(){var e,t,n,r,i,o=document.createElement(\"div\");return o.setAttribute(\"className\",\"t\"),o.innerHTML=' <link/><table></table><a href=\"/a\">a</a><input type=\"checkbox\"/>',t=o.getElementsByTagName(\"A\")[0],t.style.cssText=\"top:1px;float:left;opacity:.5\",r=document.createElement(\"select\"),i=r.appendChild(document.createElement(\"option\")),n=o.getElementsByTagName(\"input\")[0],n.checked=!0,e={dom:{div:o,a:t,select:r,opt:i,input:n}}}(),t.createChain(\"event\",function(){var e={};return function(n){switch(t.type(n)){case\"object\":return e.originalEvent===n?e:e=new t.event.$Event(n);case\"$Event\":return n}}}(),function(e){var n,r,i=this;if(this._type_=\"$Event\",\"object\"==typeof e&&e.type){i.originalEvent=n=e;for(var o in n)\"function\"!=typeof n[o]&&(i[o]=n[o]);n.extraData&&t.extend(i,n.extraData),i.target=i.srcElement=n.srcElement||(r=n.target)&&(3==r.nodeType?r.parentNode:r),i.relatedTarget=n.relatedTarget||(r=n.fromElement)&&(r===i.target?n.toElement:r),i.keyCode=i.which=n.keyCode||n.which,i.which||void 0===n.button||(i.which=1&n.button?1:2&n.button?3:4&n.button?2:0);var a=document.documentElement,s=document.body;i.pageX=n.pageX||n.clientX+(a&&a.scrollLeft||s&&s.scrollLeft||0)-(a&&a.clientLeft||s&&s.clientLeft||0),i.pageY=n.pageY||n.clientY+(a&&a.scrollTop||s&&s.scrollTop||0)-(a&&a.clientTop||s&&s.clientTop||0),i.data}this.timeStamp=(new Date).getTime()}).extend({stopPropagation:function(){var e=this.originalEvent;e&&(e.stopPropagation?e.stopPropagation():e.cancelBubble=!0)},preventDefault:function(){var e=this.originalEvent;e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)}}),t.merge=function(e,t){var n=e.length,r=0;if(\"number\"==typeof t.length)for(var i=t.length;i>r;r++)e[n++]=t[r];else for(;void 0!==t[r];)e[n++]=t[r++];return e.length=n,e},t.array.extend({unique:function(e){var t,n,r=this.length,i=this.slice(0);for(\"function\"!=typeof e&&(e=function(e,t){return e===t});--r>0;)for(n=i[r],t=r;t--;)if(e(n,i[t])){i.splice(r,1);break}for(r=this.length=i.length,t=0;r>t;t++)this[t]=i[t];return this}}),t.query=t.query||function(){function e(e,n){var i,u,c,l,f,d,p,h=[];return r.test(e)?(c=RegExp.$2,l=RegExp.$1||\"*\",t.forEach(n.getElementsByTagName(l),function(e){e.id==c&&h.push(e)})):o.test(e)||\"*\"==e?t.merge(h,n.getElementsByTagName(e)):a.test(e)?(d=[],l=RegExp.$1,f=RegExp.$2,i=\" \"+f+\" \",n.getElementsByClassName?d=n.getElementsByClassName(f):t.forEach(n.getElementsByTagName(\"*\"),function(e){e.className&&~(\" \"+e.className+\" \").indexOf(i)&&d.push(e)}),l&&(l=l.toUpperCase())?t.forEach(d,function(e){e.tagName.toUpperCase()===l&&h.push(e)}):t.merge(h,d)):s.test(e)&&(p=e.substr(1).split(\".\"),t.forEach(n.getElementsByTagName(\"*\"),function(e){e.className&&(i=\" \"+e.className+\" \",u=!0,t.forEach(p,function(e){~i.indexOf(\" \"+e+\" \")||(u=!1)}),u&&h.push(e))})),h}function n(r,o){var a,s=r,u=\"__tangram__\",c=[];return!o&&i.test(s)&&(a=document.getElementById(s.substr(1)))?[a]:(o=o||document,o.querySelectorAll?(1!=o.nodeType||o.id?a=o.querySelectorAll(s):(o.id=u,a=o.querySelectorAll(\"#\"+u+\" \"+s),o.id=\"\"),a):~s.indexOf(\" \")?(t.forEach(e(s.substr(0,s.indexOf(\" \")),o),function(e){t.merge(c,n(s.substr(s.indexOf(\" \")+1),e))}),c):e(s,o))}var r=/^(\\w*)#([\\w\\-\\$]+)$/,i=/^#([\\w\\-\\$]+)$/,o=/^\\w+$/,a=/^(\\w*)\\.([\\w\\-\\$]+)$/,s=/^(\\.[\\w\\-\\$]+)+$/,u=/\\s*,\\s*/,c=/\\s+/g;return Array.prototype.slice,function(e,r,i){if(!e||\"string\"!=typeof e)return i||[];var o=[];return e=e.replace(c,\" \"),i&&t.merge(o,i)&&(i.length=0),t.forEach(e.indexOf(\",\")>0?e.split(u):[e],function(e){t.merge(o,n(e,r))}),t.merge(i||[],t.array(o).unique())}}(),t.createChain(\"dom\",function(e,n){var r=new t.dom.$DOM(n);if(!e)return r;if(\"$DOM\"==e._type_)return e;if(e.nodeType||e==e.window)return r[0]=e,r.length=1,r;if(e.length&&\"[object String]\"!=r.toString.call(e))return t.merge(r,e);if(\"string\"==typeof e)if(\"<\"==e.charAt(0)&&\">\"==e.charAt(e.length-1)&&e.length>2){var i=/^<(\\w+)\\s*\\/?>(?:<\\/\\1>|)$/,o=n&&\"$DOM\"===n._type_?n[0]:n,a=i.exec(e);o=o&&o.nodeType?o.ownerDocument||o:document,a=a?[o.createElement(a[1])]:t.dom.createElements?t.dom.createElements(e):[],t.merge(r,a)}else t.query(e,n,r);else if(\"function\"==typeof e)return r.ready?r.ready(e):r;return r},function(e){this.length=0,this._type_=\"$DOM\",this.context=e||document}).extend({size:function(){return this.length},splice:function(){},get:function(e){return\"number\"==typeof e?0>e?this[this.length+e]:this[e]:Array.prototype.slice.call(this,0)},toArray:function(){return this.get()}}),t.dom.extend({each:function(e){t.check(\"function\",\"baidu.dom.each\");var n,r,i=this.length;for(n=0;i>n&&(r=e.call(this[n],n,this[n],this),r!==!1&&\"break\"!=r);n++);return this}}),t._util_.eventBase=t._util_.eventBase||{},void function(e,t){e.listener||(t=e.listener={},window.addEventListener?t.add=function(e,t,n){e.addEventListener(t,n,!1)}:window.attachEvent&&(t.add=function(e,t,n){e.attachEvent(\"on\"+t,n)}))}(t._util_.eventBase),void function(e){if(!e.queue){var n=t.id,r=e.queue={},i=r.attaCache=t.global(\"eventQueueCache\"),o=e.listener;r.get=function(e,t,r,o){var a,s=n(e);return i[s]||(i[s]={}),a=i[s],t?(!a[t]&&r&&this.setupCall(e,t,r,a[t]=[],o),a[t]||[]):a},r.add=function(e,t,n,r,i){this.get(e,t,n,i).push(r)},r.remove=function(e,t,n){var r,i;if(t){var r=this.get(e,t);if(n)for(var o=r.length-1;o>=0;o--)r[o].orig==n&&r.splice(o,1);else r.length=0}else{var i=this.get(e);for(var o in i)i[o].length=0}},r.handlerList=function(e,n){for(var r,i=[],o=0;r=n[o];o++)r.delegate&&t.dom(r.delegate,e).size()<1||i.push(r);return i},r.call=function(e,n,i,o){if(i){if(!i.length)return;var a=[].slice.call(arguments,1),s=[];a.unshift(o=t.event(o||n)),o.type=n,o.currentTarget||(o.currentTarget=e),o.target||(o.target=e),i=r.handlerList(e,i);for(var u,c=0,l=i.length;l>c;c++)(u=i[c])&&(u.pkg.apply(e,a),u.one&&s.unshift(c));if(s.length)for(var c=0,l=s.length;l>c;c++)this.remove(e,n,i[c].fn)}else i=this.get(e,n),this.call(e,n,i,o)},r.setupCall=function(){var e=function(e,t,n,i){o.add(e,n,function(n){r.call(e,t,i,n)})};return function(n,r,i,o,a){if(a){n=t.dom(a,n);for(var s=0,u=n.length;u>s;s++)e(n[s],r,i,o)}else e(n,r,i,o)}}()}}(t._util_.eventBase,t.event),void function(e,n){if(!e.core){var r=e.queue,i=e.core={},o=n.special={},a=[].push,s=function(e,t){for(var n=0,r=t.length;r>n;n++)if(t.get(n).contains(e))return t[n]};i.build=function(e,n,r,i,u){var c;return i&&(c=t.dom(i,e)),n in o&&o[n].pack&&(r=o[n].pack(r)),function(n){var o,l=(t.dom(n.target),[n]);if(u&&!n.data&&(n.data=u),n.triggerData&&a.apply(l,n.triggerData),!c)return n.result=r.apply(e,l);for(var f=0;2>f;f++){if(o=s(n.target,c))return n.result=r.apply(o,l);c=t.dom(i,e)}}},i.add=function(e,t,n,i,a,s){var u,c,l=this.build(e,t,n,i,a);c=t,t in o&&(u=o[t].attachElements,c=o[t].bindType||t),r.add(e,t,c,{type:t,pkg:l,orig:n,one:s,delegate:i},u)},i.remove=function(e,t,n,i){r.remove(e,t,n,i)}}}(t._util_.eventBase,t.event),t.dom.extend({on:function(e,n,r,i,o){var a=t._util_.eventBase.core;return\"object\"==typeof n&&n?(i=r,r=n,n=null):\"function\"==typeof r?(i=r,r=null):\"function\"==typeof n&&(i=n,n=r=null),\"string\"==typeof e?(e=e.split(/[ ,]+/),this.each(function(){t.forEach(e,function(e){a.add(this,e,i,n,r,o)},this)})):\"object\"==typeof e&&(i&&(i=null),t.forEach(e,function(e,t){this.on(t,n,r,e,o)},this)),this}}),t.dom.g=function(e){return e?\"string\"==typeof e||e instanceof String?document.getElementById(e):!e.nodeName||1!=e.nodeType&&9!=e.nodeType?null:e:null},t.event.on=t.on=function(e,n,r){return\"string\"==typeof e&&(e=t.dom.g(e)),t.dom(e).on(n.replace(/^\\s*on/,\"\"),r),e},void function(){function e(e){var n,r;if(!e||\"string\"!==t.type(e))return null;try{window.DOMParser?(r=new DOMParser,n=r.parseFromString(e,\"text/xml\")):(n=new ActiveXObject(\"Microsoft.XMLDOM\"),n.async=\"false\",n.loadXML(e))}catch(i){n=void 0}if(!n||!n.documentElement||n.getElementsByTagName(\"parsererror\").length)throw new Error(\"Invalid XML: \"+e);return n}function n(e){if(!e||\"string\"!==t.type(e))return null;if(e=t.string(e).trim(),window.JSON&&window.JSON.parse)return window.JSON.parse(e);if(_.test(e.replace(T,\"@\").replace(C,\"]\").replace(E,\"\")))return new Function(\"return \"+e)();throw new Error(\"Invalid JSON: \"+e)}function r(e){e&&/\\S/.test(e)&&(window.execScript||function(e){window.eval.call(window,e)})(e)}function i(e){return function(n,r){\"string\"!==t.type(n)&&(r=n,n=\"*\");var i,o,a=n.toLowerCase().split(/\\s+/);if(\"function\"===t.type(r))for(var s,u=0;s=a[u];u++)i=/^\\+/.test(s),i&&(s=s.substr(1)||\"*\"),o=e[s]=e[s]||[],o[i?\"unshift\":\"push\"](r)}}function o(e,t,n){var r,i,o,a,s=e.contents,u=e.dataTypes,c=e.responseFields;for(i in c)i in n&&(t[c[i]]=n[i]);for(;\"*\"===u[0];)u.shift(),void 0===r&&(r=e.mimeType||t.getResponseHeader(\"content-type\"));if(r)for(i in s)if(s[i]&&s[i].test(r)){u.unshift(i);break}if(u[0]in n)o=u[0];else{for(i in n){if(!u[0]||e.converters[i+\" \"+u[0]]){o=i;break}a||(a=i)}o=o||a}return o?(o!==u[0]&&u.unshift(o),n[o]):void 0}function a(e,t){var n,r,i=e.dataTypes.slice(),o=i[0],a={};if(e.dataFilter&&(t=e.dataFilter(t,e.dataType)),i[1])for(var s in e.converters)a[s.toLowerCase()]=e.converters[s];for(var u,s=0;u=i[++s];)if(\"*\"!==u){if(\"*\"!==o&&o!==u){if(n=a[o+\" \"+u]||a[\"* \"+u],!n)for(var c in a)if(r=c.split(\" \"),r[1]===u&&(n=a[o+\" \"+r[0]]||a[\"* \"+r[0]])){n===!0?n=a[c]:a[c]!==!0&&(u=r[0],i.splice(s--,0,u));break}if(n!==!0)if(n&&e[\"throws\"])t=n(t);else try{t=n(t)}catch(l){return{state:\"parsererror\",error:n?l:\"No conversion from \"+o+\" to \"+u}}}o=u}return{state:\"success\",data:t}}function s(e,t,n,r,i,o){i=i||t.dataTypes[0],o=o||{},o[i]=!0;for(var a,u=e[i],c=u?u.length:0,l=e===k,f=0;c>f&&(l||!a);f++)a=u[f](t,n,r),\"string\"==typeof a&&(!l||o[a]?a=void 0:(t.dataTypes.unshift(a),a=s(e,t,n,r,a,o)));return!l&&a||o[\"*\"]||(a=s(e,t,n,r,\"*\",o)),a}function u(e,n){var r,i=t.ajax.settings.flatOptions||{};for(var o in n)void 0!==n[o]&&((i[o]?e:r||(r={}))[o]=n[o]);r&&t.extend(!0,e,r)}function c(e,n,r){r=\"function\"===t.type(r)?r():\"undefined\"==typeof r||null==r?\"\":r,e.push(encodeURIComponent(n)+\"=\"+encodeURIComponent(r))}function l(e,n,r,i){if(\"array\"===t.type(r))t.forEach(r,function(t,r){i||v.test(n)?c(e,n,t):l(e,n+\"[\"+(\"object\"==typeof t?r:\"\")+\"]\",t,i)});else if(i||\"object\"!==t.type(r))c(e,n,r);else for(var o in r)l(e,n+\"[\"+o+\"]\",r[o],i)}function f(){try{return new window.XMLHttpRequest}catch(e){}}function d(){try{return new window.ActiveXObject(\"Microsoft.XMLHTTP\")}catch(e){}}var p=document.URL,h=/^(?:about|app|app\\-storage|.+\\-extension|file|res|widget):$/,m=/^\\/\\//,g=/^([\\w\\+\\.\\-]+:)(?:\\/\\/([^\\/?#:]*)(?::(\\d+)|)|)/,y=/#.*$/,v=/\\[\\]$/,b=/^(?:GET|HEAD)$/,x=/([?&])_=[^&]*/,w=/^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/gm,_=/^[\\],:{}\\s]*$/,E=/(?:^|:|,)(?:\\s*\\[)+/g,T=/\\\\(?:[\"\\\\\\/bfnrt]|u[\\da-fA-F]{4})/g,C=/\"[^\"\\\\\\r\\n]*\"|true|false|null|-?(?:\\d\\d*\\.|)\\d+(?:[eE][\\-+]?\\d+|)/g,S=[\"*/\"]+[\"*\"],k={},N={},A={},O={},L=g.exec(p.toLowerCase())||[];t.createChain(\"ajax\",function(e,n){function r(e,t,n,r){var i,s,c,f,m,g=t;2!==C&&(C=2,p&&clearTimeout(p),d=void 0,l=r||\"\",$.readyState=e>0?4:0,n&&(f=o(h,$,n)),e>=200&&300>e||304===e?(h.ifModified&&(m=$.getResponseHeader(\"Last-Modified\"),m&&(A[u]=m),m=$.getResponseHeader(\"Etag\"),m&&(O[u]=m)),304===e?(g=\"notmodified\",i=!0):(i=a(h,f),g=i.state,s=i.data,c=i.error,i=!c)):(c=g,(!g||e)&&(g=\"error\",0>e&&(e=0))),$.status=e,$.statusText=\"\"+(t||g),i?_.resolveWith(v,[s,g,$]):_.rejectWith(v,[$,g,c]),$.statusCode(T),T=void 0,E.fireWith(v,[$,g]))}t.object.isPlain(e)&&(n=e,e=void 0),n=n||{};var i,u,c,l,f,d,p,h=t.ajax.setup({},n),v=h.context||h,_=t.Deferred(),E=t.Callbacks(\"once memory\"),T=h.statusCode||{},C=0,j={},D={},M=\"canceled\",$=t.extend(new t.ajax.$Ajax(e,h),{readyState:0,setRequestHeader:function(e,t){if(!C){var n=e.toLowerCase();e=j[n]=j[n]||e,D[e]=t}},getAllResponseHeaders:function(){return 2===C?l:null},getResponseHeader:function(e){var t;if(2===C){if(!f)for(f={};t=w.exec(l);)f[t[1].toLowerCase()]=t[2];t=f[e.toLowerCase()]}return void 0===t?null:t},overrideMimeType:function(e){return!C&&(h.mimeType=e),this},abort:function(e){return e=e||M,d&&d.abort(e),r(0,e),this}});if(_.promise($),$.success=$.done,$.error=$.fail,$.complete=E.add,$.statusCode=function(e){if(e)if(2>C)for(var t in e)T[t]=[T[t],e[t]];else $.always(e[$.status]);return this},h.url=((e||h.url)+\"\").replace(y,\"\").replace(m,L[1]+\"//\"),h.dataTypes=t.string(h.dataType||\"*\").trim().toLowerCase().split(/\\s+/),null==h.crossDomain&&(c=g.exec(h.url.toLowerCase()),h.crossDomain=!(!c||c[1]==L[1]&&c[2]==L[2]&&(c[3]||(\"http:\"===c[1]?80:443))==(L[3]||(\"http:\"===L[1]?80:443)))),h.data&&h.processData&&\"string\"!==t.type(h.data)&&(h.data=t.ajax.param(h.data,h.traditional)),s(k,h,n,$),2===C)return\"\";if(i=h.global,h.type=h.type.toUpperCase(),h.hasContent=!b.test(h.type),!h.hasContent&&(h.data&&(h.url+=(~h.url.indexOf(\"?\")?\"&\":\"?\")+h.data,delete h.data),u=h.url,h.cache===!1)){var H=(new Date).getTime(),B=h.url.replace(x,\"$1_=\"+H);h.url=B+(B===h.url?(~h.url.indexOf(\"?\")?\"&\":\"?\")+\"_=\"+H:\"\")}(h.data&&h.hasContent&&h.contentType!==!1||n.contentType)&&$.setRequestHeader(\"Content-Type\",h.contentType),h.ifModified&&(u=u||h.url,A[u]&&$.setRequestHeader(\"If-Modified-Since\",A[u]),O[u]&&$.setRequestHeader(\"If-None-Match\",O[u])),$.setRequestHeader(\"Accept\",h.dataTypes[0]&&h.accepts[h.dataTypes[0]]?h.accepts[h.dataTypes[0]]+(\"*\"!==h.dataTypes[0]?\", \"+S+\"; q=0.01\":\"\"):h.accepts[\"*\"]);for(var F in h.headers)$.setRequestHeader(F,h.headers[F]);if(h.beforeSend&&(h.beforeSend.call(v,$,h)===!1||2===C))return $.abort();M=\"abort\";for(var F in{success:1,error:1,complete:1})$[F](h[F]);if(d=s(N,h,n,$)){$.readyState=1,h.async&&h.timeout>0&&(p=setTimeout(function(){$.abort(\"timeout\")},h.timeout));try{C=1,d.send(D,r)}catch(I){if(!(2>C))throw I;r(-1,I)}}else r(-1,\"No Transport\");return $},function(e,t){this.url=e,this.options=t}),t.ajax.settings={url:p,isLocal:h.test(L[1]),global:!0,type:\"GET\",contentType:\"application/x-www-form-urlencoded; charset=UTF-8\",processData:!0,async:!0,accepts:{xml:\"application/xml, text/xml\",html:\"text/html\",text:\"text/plain\",json:\"application/json, text/javascript\",\"*\":S},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:\"responseXML\",text:\"responseText\"},converters:{\"* text\":window.String,\"text html\":!0,\"text json\":n,\"text xml\":e},flatOptions:{context:!0,url:!0}},t.ajax.setup=function(e,n){return n?u(e,t.ajax.settings):(n=e,e=t.ajax.settings),u(e,n),e},t.ajax.param=function(e,n){var r=[];if(\"array\"===t.type(e))t.forEach(e,function(e){c(r,e.name,e.value)});else for(var i in e)l(r,i,e[i],n);return r.join(\"&\").replace(/%20/g,\"+\")},t.ajax.prefilter=i(k),t.ajax.transport=i(N);var j=[],D=/(=)\\?(?=&|$)|\\?\\?/,M=(new Date).getTime();t.ajax.setup({jsonp:\"callback\",jsonpCallback:function(){var e=j.pop()||t.key+\"_\"+M++;return this[e]=!0,e}}),t.ajax.prefilter(\"json jsonp\",function(e,n,r){var i,o,a,s=e.data,u=e.url,c=e.jsonp!==!1,l=c&&D.test(u),f=c&&!l&&\"string\"===t.type(s)&&!(e.contentType||\"\").indexOf(\"application/x-www-form-urlencoded\")&&D.test(s);return\"jsonp\"===e.dataTypes[0]||l||f?(i=e.jsonpCallback=\"function\"===t.type(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,o=window[i],l?e.url=u.replace(D,\"$1\"+i):f?e.data=s.replace(D,\"$1\"+i):c&&(e.url+=(/\\?/.test(u)?\"&\":\"?\")+e.jsonp+\"=\"+i),e.converters[\"script json\"]=function(){return a[0]},e.dataTypes[0]=\"json\",window[i]=function(){a=arguments},r.always(function(){window[i]=o,e[i]&&(e.jsonpCallback=n.jsonpCallback,j.push(i)),a&&\"function\"===t.type(o)&&o(a[0]),a=o=void 0}),\"script\"):void 0}),t.ajax.setup({accepts:{script:\"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"},contents:{script:/javascript|ecmascript/},converters:{\"text script\":function(e){return r(e),e}}}),t.ajax.prefilter(\"script\",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type=\"GET\",e.global=!1)}),t.ajax.transport(\"script\",function(e){if(e.crossDomain){var t,n=document.head||document.getElementsByTagName(\"head\")[0]||document.documentElement;return{send:function(r,i){t=document.createElement(\"script\"),t.async=\"async\",e.scriptCharset&&(t.charset=e.scriptCharset),t.src=e.url,t.onload=t.onreadystatechange=function(e,r){(r||!t.readyState||/loaded|complete/.test(t.readyState))&&(t.onload=t.onreadystatechange=null,n&&t.parentNode&&n.removeChild(t),t=void 0,!r&&i(200,\"success\"))},n.insertBefore(t,n.firstChild)},abort:function(){t&&t.onload(0,1)}}}});var $,H=0,B=window.ActiveXObject?function(){for(var e in $)$[e](0,1)}:!1;t.ajax.settings.xhr=window.ActiveXObject?function(){return!this.isLocal&&f()||d()}:f,void function(e){t.extend(t._util_.support,{ajax:!!e,cors:!!e&&\"withCredentials\"in e})}(t.ajax.settings.xhr()),t._util_.support.ajax&&t.ajax.transport(function(e){if(!e.crossDomain||t._util_.support.cors){var n;return{send:function(r,i){var o,a=e.xhr();if(e.username?a.open(e.type,e.url,e.async,e.username,e.password):a.open(e.type,e.url,e.async),e.xhrFields)for(var s in e.xhrFields)a[s]=e.xhrFields[s];e.mimeType&&a.overrideMimeType&&a.overrideMimeType(e.mimeType),e.crossDomain||r[\"X-Requested-With\"]||(r[\"X-Requested-With\"]=\"XMLHttpRequest\");try{for(var s in r)a.setRequestHeader(s,r[s])}catch(u){}a.send(e.hasContent&&e.data||null),n=function(t,r){var s,u,c,l,f;try{if(n&&(r||4===a.readyState))if(n=void 0,o&&(a.onreadystatechange=function(){},B&&delete $[o]),r)4!==a.readyState&&a.abort();else{s=a.status,c=a.getAllResponseHeaders(),l={},f=a.responseXML,f&&f.documentElement&&(l.xml=f);try{l.text=a.responseText}catch(d){}try{u=a.statusText}catch(d){u=\"\"}s||!e.isLocal||e.crossDomain?1223===s&&(s=204):s=l.text?200:404}}catch(p){!r&&i(-1,p)}l&&i(s,u,l,c)},e.async?4===a.readyState?setTimeout(n,0):(o=++H,B&&($||($={},t.dom(window).on(\"unload\",B)),$[o]=n),a.onreadystatechange=n):n()},abort:function(){n&&n(0,1)}}}})}(),t.array.extend({contains:function(e){return!!~this.indexOf(e)}}),t.each=function(e,t,n){var r,i,o,a;if(\"function\"==typeof t&&e)if(i=\"number\"==typeof e.length?e.length:e.byteLength,\"number\"==typeof i){if(\"[object Function]\"===Object.prototype.toString.call(e))return e;for(r=0;i>r&&(o=e[r],void 0===o&&(o=e.charAt&&e.charAt(r)),a=t.call(n||o,r,o,e),a!==!1&&\"break\"!=a);r++);}else if(\"number\"==typeof e)for(r=0;e>r&&(a=t.call(n||r,r,r,r),a!==!1&&\"break\"!=a);r++);else if(\"object\"==typeof e)for(r in e)if(e.hasOwnProperty(r)&&(a=t.call(n||e[r],r,e[r],e),a===!1||\"break\"==a))break;return e},t.array.extend({each:function(e,n){return t.each(this,e,n)},forEach:function(e,n){return t.forEach(this,e,n)}}),t.array.extend({empty:function(){return this.length=0,this}}),t.array.extend({filter:function(e,n){var r,i,o,a=t.array([]),s=0;if(\"function\"===t.type(e))for(r=0,i=this.length;i>r;r++)o=this[r],e.call(n||this,o,r,this)===!0&&(a[s++]=o);return a}}),t.array.extend({find:function(e){var n,r,i=this.length;if(\"function\"==t.type(e))for(n=0;i>n;n++)if(r=this[n],e.call(this,r,n,this)===!0)return r;return null}}),t.array.extend({hash:function(e){var t,n,r={},i=e&&e.length;for(t=0,n=this.length;n>t;t++)r[this[t]]=i&&i>t?e[t]:!0;return r}}),t.array.extend({lastIndexOf:function(e,n){t.check(\".+(,number)?\",\"baidu.array.lastIndexOf\");var r=this.length;for((!(n=0|n)||n>=r)&&(n=r-1),0>n&&(n+=r);n>=0;n--)if(n in this&&this[n]===e)return n;return-1}}),t.array.extend({map:function(e,n){t.check(\"function(,.+)?\",\"baidu.array.map\");for(var r=this.length,i=t.array([]),o=0;r>o;o++)i[o]=e.call(n||this,this[o],o,this);return i}}),t.array.extend({remove:function(e){for(var t=this.length;t--;)this[t]===e&&this.splice(t,1);return this}}),t.array.extend({removeAt:function(e){return t.check(\"number\",\"baidu.array.removeAt\"),this.splice(e,1)[0]}}),t.base=t.base||{blank:function(){}},t.base.Class=function(){var e=(t._global_=window[t.guid])._instances;return e||(e=t._global_._instances={}),function(){this.guid=t.id(),this._decontrol_||(e[this.guid]=this)}}(),t.extend(t.base.Class.prototype,{toString:t.base.Class.prototype.toString=function(){return\"[object \"+(this._type_||\"Object\")+\"]\"},dispose:function(){if(delete t._global_._instances[this.guid],this._listeners_)for(var e in this._listeners_)this._listeners_[e].length=0,delete this._listeners_[e];for(var n in this)t.isFunction(this[n])?this[n]=t.base.blank:delete this[n];this.disposed=!0},fire:function(e,n){t.isString(e)&&(e=new t.base.Event(e));var r,i,o,a=this._listeners_,s=e.type,u=[e].concat(Array.prototype.slice.call(arguments,1));if(!a&&(a=this._listeners_={}),t.extend(e,n||{}),e.target=e.target||this,e.currentTarget=this,s.indexOf(\"on\")&&(s=\"on\"+s),t.isFunction(this[s])&&this[s].apply(this,u),(r=this._options)&&t.isFunction(r[s])&&r[s].apply(this,u),t.isArray(i=a[s]))for(r=i.length-1;r>-1;r--)o=i[r],o&&o.handler.apply(this,u),o&&o.once&&i.splice(r,1);return e.returnValue},on:function(e,n,r){if(!t.isFunction(n))return this;var i,o=this._listeners_;return!o&&(o=this._listeners_={}),e.indexOf(\"on\")&&(e=\"on\"+e),!t.isArray(i=o[e])&&(i=o[e]=[]),o[e].unshift({handler:n,once:!!r}),this},once:function(e,t){return this.on(e,t,!0)},one:function(e,t){return this.on(e,t,!0)},off:function(e,t){var n,r,i=this._listeners_;if(!i)return this;if(\"undefined\"==typeof e){for(n in i)delete i[n];return this}if(e.indexOf(\"on\")&&(e=\"on\"+e),\"undefined\"==typeof t)delete i[e];else if(r=i[e])for(n=r.length-1;n>=0;n--)r[n].handler===t&&r.splice(n,1);return this}}),t.base.Class.prototype.addEventListener=t.base.Class.prototype.on,t.base.Class.prototype.removeEventListener=t.base.Class.prototype.un=t.base.Class.prototype.off,t.base.Class.prototype.dispatchEvent=t.base.Class.prototype.fire,window.baiduInstance=function(e){return window[t.guid]._instances[e]},t.base.Event=function(e,t){this.type=e,this.returnValue=!0,this.target=t||null,this.currentTarget=null,this.preventDefault=function(){this.returnValue=!1}},t.base.inherits=function(e,t,n){var r,i,o=e.prototype,a=new Function;a.prototype=t.prototype,i=e.prototype=new a;for(r in o)i[r]=o[r];return e.prototype.constructor=e,e.superClass=t.prototype,\"string\"==typeof n&&(i._type_=n),e.extend=function(t){for(var n in t)i[n]=t[n];return e},e},t.base.register=function(e,t,n){(e._reg_||(e._reg_=[])).push(t);for(var r in n)e.prototype[r]=n[r]},t.cookie=t.cookie||{},t.cookie._isValidKey=function(e){return new RegExp('^[^\\\\x00-\\\\x20\\\\x7f\\\\(\\\\)<>@,;:\\\\\\\\\\\\\"\\\\[\\\\]\\\\?=\\\\{\\\\}\\\\/\\\\u0080-\\\\uffff]+$').test(e)},t.cookie.getRaw=function(e){if(t.cookie._isValidKey(e)){var n=new RegExp(\"(^| )\"+e+\"=([^;]*)(;|$)\"),r=n.exec(document.cookie);if(r)return r[2]||null}return null},t.cookie.get=function(e){var n=t.cookie.getRaw(e);return\"string\"==typeof n?n=decodeURIComponent(n):null},t.cookie.setRaw=function(e,n,r){if(t.cookie._isValidKey(e)){r=r||{};var i=r.expires;\"number\"==typeof r.expires&&(i=new Date,i.setTime(i.getTime()+r.expires)),document.cookie=e+\"=\"+n+(r.path?\"; path=\"+r.path:\"\")+(i?\"; expires=\"+i.toGMTString():\"\")+(r.domain?\"; domain=\"+r.domain:\"\")+(r.secure?\"; secure\":\"\")}},t.cookie.remove=function(e,n){n=n||{},n.expires=new Date(0),t.cookie.setRaw(e,\"\",n)},t.cookie.set=function(e,n,r){t.cookie.setRaw(e,encodeURIComponent(n),r)},t.createClass=function(e,n,r){e=t.isFunction(e)?e:function(){},r=\"object\"==typeof n?n:r||{};var i=function(){var t=this;r.decontrolled&&(t._decontrol_=!0),i.superClass.apply(t,arguments);for(var n in i.options)t[n]=i.options[n];e.apply(t,arguments);for(var n=0,o=i._reg_;o&&n<o.length;n++)o[n].apply(t,arguments)};return t.extend(i,{superClass:r.superClass||t.base.Class,inherits:function(n){if(\"function\"!=typeof n)return i;var r=function(){};r.prototype=(i.superClass=n).prototype;var o=i.prototype=new r;return t.extend(i.prototype,e.prototype),o.constructor=e,i},register:function(e,n){return(i._reg_||(i._reg_=[])).push(e),n&&t.extend(i.prototype,n),i\n},extend:function(e){return t.extend(i.prototype,e),i}}),n=t.isString(n)?n:r.className||r.type,t.isString(n)&&(e.prototype._type_=n),t.isFunction(i.superClass)&&i.inherits(i.superClass),i},t.createSingle=function(e,n){var r=new t.base.Class;return t.isString(n)&&(r._type_=n),t.extend(r,e)},t.date=t.date||{},t.createChain(\"number\",function(e){var n=parseFloat(e),r=isNaN(n)?n:e,i=\"number\"==typeof r?Number:String,o=i.prototype;return r=new i(r),t.forEach(t.number.$Number.prototype,function(e,t){o[t]||(r[t]=e)}),r}),t.number.extend({pad:function(e){var t=this,n=\"\",r=0>t,i=String(Math.abs(t));return i.length<e&&(n=new Array(e-i.length+1).join(\"0\")),(r?\"-\":\"\")+n+i}}),t.date.format=function(e,n){function r(e,t){n=n.replace(e,t)}if(\"string\"!=typeof n)return e.toString();var i=t.number.pad,o=e.getFullYear(),a=e.getMonth()+1,s=e.getDate(),u=e.getHours(),c=e.getMinutes(),l=e.getSeconds();return r(/yyyy/g,i(o,4)),r(/yy/g,i(parseInt(o.toString().slice(2),10),2)),r(/MM/g,i(a,2)),r(/M/g,a),r(/dd/g,i(s,2)),r(/d/g,s),r(/HH/g,i(u,2)),r(/H/g,u),r(/hh/g,i(u%12,2)),r(/h/g,u%12),r(/mm/g,i(c,2)),r(/m/g,c),r(/ss/g,i(l,2)),r(/s/g,l),n},t.date.parse=function(e){var t=new RegExp(\"^\\\\d+(\\\\-|\\\\/)\\\\d+(\\\\-|\\\\/)\\\\d+$\");if(\"string\"==typeof e){if(t.test(e)||isNaN(Date.parse(e))){var n=e.split(/ |T/),r=n.length>1?n[1].split(/[^\\d]/):[0,0,0],i=n[0].split(/[^\\d]/);return new Date(i[0]-0,i[1]-1,i[2]-0,r[0]-0,r[1]-0,r[2]-0)}return new Date(e)}return new Date},t.dom.extend({pushStack:function(e){var n=t.dom();return t.merge(n,e),n.prevObject=this,n.context=this.context,n}}),t.dom.createElements=function(){function e(e,t){var n,r,i,o=e.getElementsByTagName(\"SCRIPT\");for(n=o.length-1;n>=0;n--)i=o[n],r=t.createElement(\"SCRIPT\"),i.id&&(r.id=i.id),i.src&&(r.src=i.src),i.type&&(r.type=i.type),r[i.text?\"text\":\"textContent\"]=i.text||i.textContent,i.parentNode.replaceChild(r,i)}var n=/<(\\w+)/i,r=/<|&#?\\w+;/,i={area:[1,\"<map>\",\"</map>\"],col:[2,\"<table><tbody></tbody><colgroup>\",\"</colgroup></table>\"],legend:[1,\"<fieldset>\",\"</fieldset>\"],option:[1,\"<select multiple='multiple'>\",\"</select>\"],td:[3,\"<table><tbody><tr>\",\"</tr></tbody></table>\"],thead:[1,\"<table>\",\"</table>\"],tr:[2,\"<table><tbody>\",\"</tbody></table>\"],_default:[0,\"\",\"\"]};return i.optgroup=i.option,i.tbody=i.tfoot=i.colgroup=i.caption=i.thead,i.th=i.td,function(o,a){t.isNumber(o)&&(o=o.toString()),a=a||document;var s,u,c,l=o,f=(l.length,a.createElement(\"div\")),d=a.createDocumentFragment(),p=[];if(t.isString(l))if(r.test(l)){for(s=i[l.match(n)[1].toLowerCase()]||i._default,f.innerHTML=\"<i>mz</i>\"+s[1]+l+s[2],f.removeChild(f.firstChild),e(f,a),u=s[0],c=f;u--;)c=c.firstChild;t.merge(p,c.childNodes),t.forEach(p,function(e){d.appendChild(e)}),f=c=null}else p.push(a.createTextNode(l));return f=null,p}}(),t.dom.extend({add:function(e,n){var r=t.array(this.get());switch(t.type(e)){case\"HTMLElement\":r.push(e);break;case\"$DOM\":case\"array\":t.merge(r,e);break;case\"string\":t.merge(r,t.dom(e,n));break;default:\"object\"==typeof e&&e.length&&t.merge(r,e)}return this.pushStack(r.unique())}}),t.dom.extend({addClass:function(e){if(!arguments.length)return this;var n=typeof e,r=\" \";if(\"string\"==n){e=t.string.trim(e);var i=e.split(\" \");t.forEach(this,function(e){for(var t=e.className,n=0;n<i.length;n++)~(r+t+r).indexOf(r+i[n]+r)||(t+=\" \"+i[n]);e.className=t.replace(/^\\s+/g,\"\")})}else\"function\"==n&&t.forEach(this,function(n,r){t.dom(n).addClass(e.call(n,r,n.className))});return this}}),t.dom.extend({getDocument:function(){if(this.size()<=0)return void 0;var e=this[0];return 9==e.nodeType?e:e.ownerDocument||e.document}}),t._util_.cleanData=function(e){for(var n,r,i=0;r=e[i];i++)n=t.id(r,\"get\"),n&&(t._util_.eventBase.queue.remove(r),t.id(r,\"remove\"))},t.dom.extend({empty:function(){for(var e,n=0;e=this[n];n++)for(1===e.nodeType&&t._util_.cleanData(e.getElementsByTagName(\"*\"));e.firstChild;)e.removeChild(e.firstChild);return this}}),t.dom.extend({append:function(){return t.check(\"^(?:string|function|HTMLElement|\\\\$DOM)(?:,(?:string|array|HTMLElement|\\\\$DOM))*$\",\"baidu.dom.append\"),t._util_.smartInsert(this,arguments,function(e){1===this.nodeType&&this.appendChild(e)}),this}}),t.dom.extend({html:function(e){var n,r=t.dom,i=t._util_,o=this,a=!1,s=!!i.support.dom.div.getElementsByTagName(\"link\").length,u=3===i.support.dom.div.firstChild.nodeType;if(!this.size())switch(typeof e){case\"undefined\":return void 0;default:return o}var c=\"abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video\",l=/<(?:script|style|link)/i,f=new RegExp(\"<(?:\"+c+\")[\\\\s/>]\",\"i\"),d=/^\\s+/,p=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/gi,h=/<([\\w:]+)/,m={option:[1,\"<select multiple='multiple'>\",\"</select>\"],legend:[1,\"<fieldset>\",\"</fieldset>\"],thead:[1,\"<table>\",\"</table>\"],tr:[2,\"<table><tbody>\",\"</tbody></table>\"],td:[3,\"<table><tbody><tr>\",\"</tr></tbody></table>\"],col:[2,\"<table><tbody></tbody><colgroup>\",\"</colgroup></table>\"],area:[1,\"<map>\",\"</map>\"],_default:[0,\"\",\"\"]};return m.optgroup=m.option,m.tbody=m.tfoot=m.colgroup=m.caption=m.thead,m.th=m.td,s||(m._default=[1,\"X<div>\",\"</div>\"]),t.forEach(o,function(t,i){if(!n){var c=r(t);switch(typeof e){case\"undefined\":return n=1===t.nodeType?t.innerHTML:void 0,void 0;case\"number\":e=String(e);case\"string\":if(a=!0,!(l.test(e)||!s&&f.test(e)||!u&&d.test(e)||m[(h.exec(e)||[\"\",\"\"])[1].toLowerCase()])){e=e.replace(p,\"<$1></$2>\");try{1===t.nodeType&&(c.empty(),t.innerHTML=e),t=0}catch(g){}}t&&o.empty().append(e);break;case\"function\":a=!0,c.html(e.call(t,i,c.html()))}}}),a?o:n}}),t._util_.smartInsert=function(e,n,r){if(!(n.length<=0||e.size()<=0)){if(\"function\"===t.type(n[0])){var i,o=n[0];return t.forEach(e,function(e,a){i=t.dom(e),n[0]=o.call(e,a,i.html()),t._util_.smartInsert(i,n,r)})}for(var a,s,u=e.getDocument()||document,c=u.createDocumentFragment(),l=e.length-1,f=0;s=n[f];f++)s.nodeType?c.appendChild(s):t.forEach(~\"string|number\".indexOf(t.type(s))?t.dom.createElements(s,u):s,function(e){c.appendChild(e)});(a=c.firstChild)&&t.forEach(e,function(e,t){r.call(\"table\"===e.nodeName.toLowerCase()&&\"tr\"===a.nodeName.toLowerCase()?e.tBodies[0]||e.appendChild(e.ownerDocument.createElement(\"tbody\")):e,l>t?c.cloneNode(!0):c)})}},t.dom.extend({after:function(){return t.check(\"^(?:string|function|HTMLElement|\\\\$DOM)(?:,(?:string|array|HTMLElement|\\\\$DOM))*$\",\"baidu.dom.after\"),t._util_.smartInsert(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)}),this}}),t.makeArray=function(e,n){var r=n||[];return e?(null==e.length||~\"string|function|regexp\".indexOf(t.type(e))?[].push.call(r,e):t.merge(r,e),r):r},t.dom.extend({map:function(e){t.check(\"function\",\"baidu.dom.map\");var n=[],r=0;return t.forEach(this,function(t,i){n[r++]=e.call(t,i,t,t)}),this.pushStack(n)}}),t._util_.isXML=function(e){var t=(e?e.ownerDocument||e:0).documentElement;return t?\"HTML\"!==t.nodeName:!1},t.dom.extend({clone:function(){function e(e){return e.getElementsByTagName?e.getElementsByTagName(\"*\"):e.querySelectorAll?e.querySelectorAll(\"*\"):[]}function n(e,n){switch(n.clearAttributes&&n.clearAttributes(),n.mergeAttributes&&n.mergeAttributes(e),n.nodeName.toLowerCase()){case\"object\":n.outerHTML=e.outerHTML;break;case\"textarea\":case\"input\":~\"checked|radio\".indexOf(e.type)&&(e.checked&&(n.defaultChecked=n.checked=e.checked),n.value!==e.value&&(n.value=e.value)),n.defaultValue=e.defaultValue;break;case\"option\":n.selected=e.defaultSelected;break;case\"script\":n.text!==e.text&&(n.text=e.text)}n[t.key]&&n.removeAttribute(t.key)}function r(e,n){if(1===n.nodeType&&t.id(e,\"get\")){var r=s.get(e);for(var i in r)for(var o,u=0;o=r[i][u];u++)a.add(n,i,o.orig,null,null,o.one)}}function i(i,o,a){var s,u,f,d=i.cloneNode(!0);if(!(l&&c||1!==i.nodeType&&11!==i.nodeType||t._util_.isXML(i))){n(i,d),s=e(i),u=e(d),f=s.length;for(var p=0;f>p;p++)u[p]&&n(s[p],u[p])}if(o&&(r(i,d),a)){s=e(i),u=e(d),f=s.length;for(var p=0;f>p;p++)r(s[p],u[p])}return d}var o=t._util_,a=o.eventBase.core,s=o.eventBase.queue,u=o.support.dom.div,c=o.support.dom.input.cloneNode(!0).checked,l=!0;return!u.addEventListener&&u.attachEvent&&u.fireEvent&&(u.attachEvent(\"onclick\",function(){l=!1}),u.cloneNode(!0).fireEvent(\"onclick\")),function(e,t){return e=!!e,t=!!t,this.map(function(){return i(this,e,t)})}}()}),t._util_.contains=document.compareDocumentPosition?function(e,t){return!!(16&e.compareDocumentPosition(t))}:function(e,t){if(e===t)return!1;if(e.contains&&t.contains)return e.contains(t);for(;t=t.parentNode;)if(t===e)return!0;return!1},t.dom.extend({contains:function(e){var n=this[0];return e=t.dom(e)[0],n&&e?t._util_.contains(n,e):!1}}),t._util_.smartInsertTo=function(e,n,r,i){var o,a=t.dom(n),s=a[0];if(!i||!s||s.parentNode&&11!==s.parentNode.nodeType)for(var u,c=0;u=a[c];c++)t._util_.smartInsert(t.dom(u),c>0?e.clone(!0,!0):e,r);else i=\"before\"===i,o=t.merge(i?e:a,i?a:e),e!==o&&(e.length=0,t.merge(e,o))},t.dom.extend({appendTo:function(e){var n=[],r=n.push;return t.check(\"^(?:string|HTMLElement|\\\\$DOM)$\",\"baidu.dom.appendTo\"),t._util_.smartInsertTo(this,e,function(e){r.apply(n,t.makeArray(e.childNodes)),this.appendChild(e)}),this.pushStack(n)}}),t._util_.access=function(e,n,r,i,o){if(e.size()<=0)return e;switch(t.type(n)){case\"string\":if(void 0===r)return i.call(e,e[0],n);e.each(function(a,s){i.call(e,s,n,\"function\"===t.type(r)?r.call(s,a,i.call(e,s,n)):r,o)});break;case\"object\":for(var a in n)t._util_.access(e,a,n[a],i,r)}return e},t._util_.nodeName=function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},t._util_.propFixer={tabindex:\"tabIndex\",readonly:\"readOnly\",\"for\":\"htmlFor\",\"class\":\"className\",classname:\"className\",maxlength:\"maxLength\",cellspacing:\"cellSpacing\",cellpadding:\"cellPadding\",rowspan:\"rowSpan\",colspan:\"colSpan\",usemap:\"useMap\",frameborder:\"frameBorder\",contenteditable:\"contentEditable\",rboolean:/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i},!document.createElement(\"form\").enctype&&(t._util_.propFixer.enctype=\"encoding\"),t._util_.prop=function(){var e=/^(?:button|input|object|select|textarea)$/i,n=/^a(?:rea|)$/i,r=document.createElement(\"select\"),i=r.appendChild(document.createElement(\"option\")),o={tabIndex:{get:function(t){var r=t.getAttributeNode(\"tabindex\");return r&&r.specified?parseInt(r.value,10):e.test(t.nodeName)||n.test(t.nodeName)&&t.href?0:void 0}}};return!i.selected&&(o.selected={get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}}),r=i=null,function(e,n,r){var i,a,s=e.nodeType;return e&&!~\"238\".indexOf(s)?(1===s&&t._util_.isXML(e)||(n=t._util_.propFixer[n]||n,i=o[n]||{}),void 0!==r?i.set&&void 0!==(a=i.set(e,n,r))?a:e[n]=r:i.get&&null!==(a=i.get(e,n))?a:e[n]):void 0}}(),t._util_.support.getSetAttribute=\"t\"!==t._util_.support.dom.div.className,t._util_.nodeHook=function(){if(!t._util_.support.getSetAttribute){var e={};return e.name=e.id=e.coords=!0,{get:function(t,n){var r=t.getAttributeNode(n);return r&&(e[n]?\"\"!==r.value:r.specified)?r.value:void 0},set:function(e,t,n){var r=e.getAttributeNode(t);return r||(r=document.createAttribute(t),e.setAttributeNode(r)),r.value=n+\"\"}}}}(),t._util_.removeAttr=function(){var e=t._util_.propFixer,n=/\\s+/,r=t._util_.support.getSetAttribute;return function(i,o){if(o&&1===i.nodeType)for(var a,s,u,c=o.split(n),l=0;u=c[l];l++)a=e[u]||u,s=e.rboolean.test(u),!s&&t._util_.attr(i,u,\"\"),i.removeAttribute(r?u:a),s&&a in i&&(i[a]=!1)}}(),t._util_.attr=function(){var e=t._util_,n=/^(?:button|input)$/i,r=e.support.dom,i=\"t\"===r.input.value,o=\"/a\"===r.a.getAttribute(\"href\"),a=/top/.test(r.a.getAttribute(\"style\")),s=e.nodeHook,u={className:\"class\"},c={get:function(t,n){var r,i=e.prop(t,n);return i===!0||\"boolean\"!=typeof i&&(r=t.getAttributeNode(n))&&r.nodeValue!==!1?n.toLowerCase():void 0},set:function(t,n,r){if(r===!1)e.removeAttr(t,n);else{var i=e.propFixer[n]||n;i in t&&(t[i]=!0),t.setAttribute(n,n.toLowerCase())}return n}},l={type:{set:function(t,r,o){if(n.test(t.nodeName)&&t.parentNode)return o;if(!i&&\"radio\"===o&&e.nodeName(t,\"input\")){var a=t.value;return t.setAttribute(\"type\",o),a&&(t.value=a),o}}},value:{get:function(t,n){return s&&e.nodeName(t,\"button\")?s.get(t,n):n in t?t.value:null},set:function(t,n,r){return s&&e.nodeName(t,\"button\")?s.set(t,n,r):(t.value=r,void 0)}}};return e.support.getSetAttribute||(t.forEach([\"width\",\"height\"],function(e){l[e]={set:function(e,t,n){return\"\"===n?(e.setAttribute(t,\"auto\"),n):void 0}}}),l.contenteditable={get:s.get,set:function(e,t,n){\"\"===n&&(n=!1),s.set(e,t,n)}}),o||t.forEach([\"href\",\"src\",\"width\",\"height\"],function(e){l[e]={get:function(e,t){var n=e.getAttribute(t,2);return null===n?void 0:n}}}),a||(l.style={get:function(e){return e.style.cssText.toLowerCase()||void 0},set:function(e,t,n){return e.style.cssText=n+\"\"}}),function(n,r,i,o){var a,f,d=n.nodeType,p=1!==d||!e.isXML(n);return n&&!~\"238\".indexOf(d)?o&&t.dom.fn[r]?t.dom(n)[r](i):(p&&(r=u[r]||r.toLowerCase(),a=l[r]||(e.propFixer.rboolean.test(r)?c:s)),void 0!==i?null===i?(e.removeAttr(n,r),void 0):p&&a&&a.set&&void 0!==(f=a.set(n,r,i))?f:(n.setAttribute(r,i+\"\"),i):p&&a&&a.get&&null!==(f=a.get(n,r))?f:(f=n.getAttribute(r),null===f?void 0:f)):void 0}}(),t.dom.extend({attr:function(e,n){return t._util_.access(this,e,n,function(e,n,r,i){return t._util_.attr(e,n,r,i)})}}),t.dom.extend({before:function(){return t.check(\"^(?:string|function|HTMLElement|\\\\$DOM)(?:,(?:string|array|HTMLElement|\\\\$DOM))*$\",\"baidu.dom.before\"),t._util_.smartInsert(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)}),this}}),t.dom.extend({bind:function(e,t,n){return this.on(e,void 0,t,n)}}),t.dom.match=function(){function e(e){for(var t,n=[];e=e.parentNode;)e.nodeType&&n.push(e);for(var t=n.length-1;t>-1;t--)if(1==n[t].nodeType||9==n[t].nodeType)return n[t];return null}var n=document.createElement(\"DIV\");return n.id=\"__tangram__\",function(n,r,i){var o,a=t.array();switch(t.type(r)){case\"$DOM\":for(var s=n.length-1;s>-1;s--)for(var u=r.length-1;u>-1;u--)n[s]===r[u]&&a.push(n[s]);break;case\"function\":t.forEach(n,function(e,t){r.call(e,t)&&a.push(e)});break;case\"HTMLElement\":t.forEach(n,function(e){e==r&&a.push(e)});break;case\"string\":var c=t.query(r,i||document);t.forEach(n,function(n){if(o=e(n))for(var i=1==o.nodeType?t.query(r,o):c,s=0,u=i.length;u>s;s++)if(i[s]===n){a.push(n);break}}),a=a.unique();break;default:a=t.array(n).unique()}return a}}(),t.dom.extend({children:function(e){var n=[];return this.each(function(){t.forEach(this.children||this.childNodes,function(e){1==e.nodeType&&n.push(e)})}),this.pushStack(t.dom.match(n,e))}}),t.dom.extend({closest:function(e,n){var r=t.array();return t.forEach(this,function(i){for(var o=[i];i=i.parentNode;)i.nodeType&&o.push(i);o=t.dom.match(o,e,n),o.length&&r.push(o[0])}),this.pushStack(r.unique())}}),t.dom.extend({contents:function(){for(var e,n,r=[],i=0;n=this[i];i++)e=n.nodeName,r.push.apply(r,t.makeArray(e&&\"iframe\"===e.toLowerCase()?n.contentDocument||n.contentWindow.document:n.childNodes));return this.pushStack(r)}}),t.dom.extend({getComputedStyle:function(e){if(this[0].ownerDocument){var t=this[0].ownerDocument.defaultView,n=t&&t.getComputedStyle&&t.getComputedStyle(this[0],null),r=n?n.getPropertyValue(e)||n[e]:\"\";return r||this[0].style[e]}}}),t.dom.extend({getCurrentStyle:function(){var e=document.documentElement.currentStyle?function(e){return this[0].currentStyle?this[0].currentStyle[e]:this[0].style[e]}:function(e){return this.getComputedStyle(e)};return function(t){return e.call(this,t)}}()}),t._util_.getWidthOrHeight=function(){function e(e,t){var n={};for(var r in t)n[r]=e.style[r],e.style[r]=t[r];return n}var n={},r={position:\"absolute\",visibility:\"hidden\",display:\"block\"},i=/^(none|table(?!-c[ea]).+)/;return t.forEach([\"Width\",\"Height\"],function(o){var a={Width:[\"Right\",\"Left\"],Height:[\"Top\",\"Bottom\"]}[o];n[\"get\"+o]=function(n,s){var u=t.dom(n),c=0===n.offsetWidth&&i.test(u.getCurrentStyle(\"display\"))&&e(n,r),l=n[\"offset\"+o]||parseInt(u.getCurrentStyle(o.toLowerCase()))||0,f=\"padding|border\";return s&&t.forEach(s.split(\"|\"),function(e){~f.indexOf(e)?f=f.replace(new RegExp(\"\\\\|?\"+e+\"\\\\|?\"),\"\"):(l+=parseFloat(u.getCurrentStyle(e+a[0]))||0,l+=parseFloat(u.getCurrentStyle(e+a[1]))||0)}),f&&t.forEach(f.split(\"|\"),function(e){l-=parseFloat(u.getCurrentStyle(e+a[0]+(\"border\"===e?\"Width\":\"\")))||0,l-=parseFloat(u.getCurrentStyle(e+a[1]+(\"border\"===e?\"Width\":\"\")))||0}),c&&e(n,c),l}}),function(e,t,r){return n[\"width\"===t?\"getWidth\":\"getHeight\"](e,r)}}(),t._util_.setPositiveNumber=function(){var e=/[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/.source,t=new RegExp(\"^(\"+e+\")(.*)$\",\"i\");return function(e,n,r){var i=t.exec(n);return i?Math.max(0,i[1]-(r||0))+(i[2]||\"px\"):n}}(),t._util_.style=t.extend({set:function(e,t,n){e.style[t]=n}},document.documentElement.currentStyle?{get:function(e,n){var r,i=t.dom(e).getCurrentStyle(n);return/^-?(?:\\d*\\.)?\\d+(?!px)[^\\d\\s]+$/i.test(i)&&(r=e.style.left,e.style.left=\"fontSize\"===n?\"1em\":i,i=e.style.pixelLeft+\"px\",e.style.left=r),i}}:{get:function(e,n){return t.dom(e).getCurrentStyle(n)}}),t._util_.cssHooks=function(){function e(e,n,i){\"string\"===t.type(i)&&(i=t._util_.setPositiveNumber(e,i)),r.set(e,n,i)}var n=/alpha\\s*\\(\\s*opacity\\s*=\\s*([^)]*)/i,r=t._util_.style,i=t._util_.support.dom.a,o={fontWeight:{normal:400,bold:700,bolder:700,lighter:100}},a={opacity:{},width:{},height:{},fontWeight:{get:function(e,t){var n=r.get(e,t);return o.fontWeight[n]||n}}};return t.extend(a.opacity,/^0.5/.test(i.style.opacity)?{get:function(e,n){var r=t.dom(e).getCurrentStyle(n);return\"\"===r?\"1\":r}}:{get:function(e){return n.test((e.currentStyle||e.style).filter||\"\")?parseFloat(RegExp.$1)/100+\"\":\"1\"},set:function(e,t,r){var i=(e.currentStyle||e.style).filter||\"\",o=100*r;e.style.zoom=1,e.style.filter=n.test(i)?i.replace(n,\"Alpha(opacity=\"+o):i+\" progid:dximagetransform.microsoft.Alpha(opacity=\"+o+\")\"}}),t.forEach([\"width\",\"height\"],function(n){a[n]={get:function(e){return t._util_.getWidthOrHeight(e,n)+\"px\"},set:e}}),t.each({padding:\"\",border:\"Width\"},function(t,n){a[t+n]={set:e};for(var r=[\"Top\",\"Right\",\"Bottom\",\"Left\"],i=0;4>i;i++)a[t+r[i]+n]={set:e}}),a}(),t._util_.cssNumber={columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},t.string.extend({toCamelCase:function(){var e=this.valueOf();return e.indexOf(\"-\")<0&&e.indexOf(\"_\")<0?e:e.replace(/[-_][^-_]/g,function(e){return e.charAt(1).toUpperCase()})}}),t.dom.styleFixer=function(){var e=t._util_.style,n=t._util_.cssHooks,r=t._util_.cssNumber,i={\"float\":t._util_.support.dom.a.style.cssFloat?\"cssFloat\":\"styleFloat\"};return function(o,a,s){var u,c,l=t.string.toCamelCase(a),f=void 0===s?\"get\":\"set\";return l=i[l]||l,u=\"number\"!==t.type(s)||r[l]?s:s+\"px\",c=n.hasOwnProperty(l)&&n[l][f]||e[f],c(o,l,u)}}(),t.dom.extend({css:function(e,n){return t.check(\"^(?:(?:string(?:,(?:number|string|function))?)|object)$\",\"baidu.dom.css\"),t._util_.access(this,e,n,function(e,n,r){var i=t.dom.styleFixer;return i?i(e,n,r):void 0===r?this.getCurrentStyle(n):e.style[n]=r})}}),t.dom.extend({data:function(){var e=t.key,n=t.global(\"_maps_HTMLElementData\");return function(r,i){if(t.forEach(this,function(n){!n[e]&&(n[e]=t.id())}),t.isString(r)){if(\"undefined\"==typeof i){var o,a;if(a=this[0]&&(o=n[this[0][e]])&&o[r],\"undefined\"!=typeof a)return a;var s=this[0].getAttribute(\"data-\"+r);return~String(s).indexOf(\"{\")?Function(\"return \"+s)():s}t.forEach(this,function(t){var o=n[t[e]]=n[t[e]]||{};o[r]=i})}else\"object\"==t.type(r)&&t.forEach(this,function(i){var o=n[i[e]]=n[i[e]]||{};t.forEach(r,function(e,t){o[t]=r[t]})});return this}}()}),t.lang.Class=t.base.Class,t.lang.Event=t.base.Event,t.dom.extend({delegate:function(e,t,n,r){return\"function\"==typeof n&&(r=n,n=null),this.on(t,e,n,r)}}),t.dom.extend({filter:function(e){return this.pushStack(t.dom.match(this,e))}}),t.dom.extend({remove:function(e,n){arguments.length>0&&t.check(\"^string(?:,boolean)?$\",\"baidu.dom.remove\");for(var r,i=e?this.filter(e):this,o=0;r=i[o];o++)n||1!==r.nodeType||(t._util_.cleanData(r.getElementsByTagName(\"*\")),t._util_.cleanData([r])),r.parentNode&&r.parentNode.removeChild(r);return this}}),t.dom.extend({detach:function(e){return e&&t.check(\"^string$\",\"baidu.dom.detach\"),this.remove(e,!0)}}),t.object.extend=t.extend,t.dom.getStyle=function(e,n){return t.dom(t.dom.g(e)).css(n)},t.page=t.page||{},t.page.getScrollTop=function(){var e=document;return window.pageYOffset||e.documentElement.scrollTop||e.body.scrollTop},t.page.getScrollLeft=function(){var e=document;return window.pageXOffset||e.documentElement.scrollLeft||e.body.scrollLeft},function(){t.page.getMousePosition=function(){return{x:t.page.getScrollLeft()+e.x,y:t.page.getScrollTop()+e.y}};var e={x:0,y:0};t.event.on(document,\"onmousemove\",function(t){t=window.event||t,e.x=t.clientX,e.y=t.clientY})}(),t.dom.extend({off:function(e,n,r){var i=t._util_.eventBase.core,o=this;return e?\"string\"==typeof e?(\"function\"==typeof n&&(r=n,n=null),e=e.split(/[ ,]/),t.forEach(this,function(o){t.forEach(e,function(e){i.remove(o,e,r,n)})})):\"object\"==typeof e&&t.forEach(e,function(e,t){o.off(t,n,e)}):t.forEach(this,function(e){i.remove(e)}),this}}),t.event.un=t.un=function(e,n,r){return\"string\"==typeof e&&(e=t.dom.g(e)),t.dom(e).off(n.replace(/^\\s*on/,\"\"),r),e},t.event.preventDefault=function(e){return new t.event(e).preventDefault()},function(){function e(){h=!1,clearInterval(u),o.capture&&i.releaseCapture?i.releaseCapture():o.capture&&window.releaseEvents&&window.releaseEvents(Event.MOUSEMOVE|Event.MOUSEUP),document.body.style.MozUserSelect=p;var n=t.dom(document);n.off(\"selectstart\",r),o.autoStop&&n.off(\"mouseup\",e),t.isFunction(o.ondragend)&&o.ondragend(i,o,{left:f,top:d})}function n(){if(!h)return clearInterval(u),void 0;var e=o.range||[],n=t.page.getMousePosition(),r=c+n.x-a,p=l+n.y-s;t.isObject(e)&&4==e.length&&(r=Math.max(e[3],r),r=Math.min(e[1]-i.offsetWidth,r),p=Math.max(e[0],p),p=Math.min(e[2]-i.offsetHeight,p)),i.style.left=r+\"px\",i.style.top=p+\"px\",f=r,d=p,t.isFunction(o.ondrag)&&o.ondrag(i,o,{left:f,top:d})}function r(e){return t.event.preventDefault(e,!1)}var i,o,a,s,u,c,l,f,d,p,h=!1;t.dom.drag=function(m,g){if(!(i=t.dom.g(m)))return!1;o=t.object.extend({autoStop:!0,capture:!0,interval:16},g),f=c=parseInt(t.dom.getStyle(i,\"left\"))||0,d=l=parseInt(t.dom.getStyle(i,\"top\"))||0,h=!0,setTimeout(function(){var e=t.page.getMousePosition();a=o.mouseEvent?t.page.getScrollLeft()+o.mouseEvent.clientX:e.x,s=o.mouseEvent?t.page.getScrollTop()+o.mouseEvent.clientY:e.y,clearInterval(u),u=setInterval(n,o.interval)},1);var y=t.dom(document);return o.autoStop&&y.on(\"mouseup\",e),y.on(\"selectstart\",r),o.capture&&i.setCapture?i.setCapture():o.capture&&window.captureEvents&&window.captureEvents(Event.MOUSEMOVE|Event.MOUSEUP),p=document.body.style.MozUserSelect,document.body.style.MozUserSelect=\"none\",t.isFunction(o.ondragstart)&&o.ondragstart(i,o),{stop:e,dispose:e,update:function(e){t.object.extend(o,e)}}}}(),t.lang.isFunction=t.isFunction,t.dom.extend({end:function(){return this.prevObject||t.dom()}}),t.dom.extend({eq:function(e){t.check(\"number\",\"baidu.dom.eq\");var n=this.get(e);return this.pushStack(\"undefined\"==typeof n?[]:[n])}}),t.dom.extend({find:function(e){var n,r=[],i=\"__tangram__find__\",o=[];switch(t.type(e)){case\"string\":this.each(function(){t.merge(o,t.query(e,this))});break;case\"HTMLElement\":n=e.tagName+\"#\"+(e.id?e.id:e.id=i),this.each(function(){t.query(n,this).length>0&&r.push(e)}),e.id==i&&(e.id=\"\"),r.length>0&&t.merge(o,r);break;case\"$DOM\":r=e.get(),this.each(function(){t.forEach(t.query(\"*\",this),function(e){for(var t=0,n=r.length;n>t;t++)e===r[t]&&(o[o.length++]=r[t])})})}return this.pushStack(o)}}),t.dom.extend({first:function(){return this.eq(0)}}),t.dom.getAttr=function(e,n){return t.dom(t.dom.g(e)).attr(n)},t.dom.extend({getWindow:function(){var e=this.getDocument();return this.size()<=0?void 0:e.parentWindow||e.defaultView}}),t.dom.extend({offsetParent:function(){return this.map(function(){for(var e=this.offsetParent||document.body,n=/^(?:body|html)$/i;e&&\"static\"===t.dom(e).getCurrentStyle(\"position\")&&!n.test(e.nodeName);)e=e.offsetParent;return e})}}),t.dom.extend({position:function(){if(this.size()<=0)return 0;var e=/^(?:body|html)$/i,t=this.offset(),n=this.offsetParent(),r=e.test(n[0].nodeName)?{left:0,top:0}:n.offset();return t.left-=parseFloat(this.getCurrentStyle(\"marginLeft\"))||0,t.top-=parseFloat(this.getCurrentStyle(\"marginTop\"))||0,r.left+=parseFloat(n.getCurrentStyle(\"borderLeftWidth\"))||0,r.top+=parseFloat(n.getCurrentStyle(\"borderTopWidth\"))||0,{left:t.left-r.left,top:t.top-r.top}}}),t.dom.extend({offset:function(){function e(e,n,r){var i=i=t.dom(e),o=i.getCurrentStyle(\"position\");\"static\"===o&&(e.style.position=\"relative\");var a=i.offset(),s=i.getCurrentStyle(\"left\"),u=i.getCurrentStyle(\"top\"),c=~\"absolute|fixed\".indexOf(o)&&~(\"\"+s+u).indexOf(\"auto\"),l=c&&i.position();s=l&&l.left||parseFloat(s)||0,u=l&&l.top||parseFloat(u)||0,\"function\"===t.type(\"options\")&&(n=n.call(e,r,a)),void 0!=n.left&&(e.style.left=n.left-a.left+s+\"px\"),void 0!=n.top&&(e.style.top=n.top-a.top+u+\"px\")}return function(n){if(n){t.check(\"^(?:object|function)$\",\"baidu.dom.offset\");for(var r,i=0;r=this[i];i++)e(r,n,i);return this}var o,a,s=this[0],u=this.getDocument(),c={left:0,top:0};return u?(a=u.documentElement,t._util_.contains(a,s)?(\"undefined\"!=typeof s.getBoundingClientRect&&(c=s.getBoundingClientRect()),o=this.getWindow(),{left:c.left+(o.pageXOffset||a.scrollLeft)-(a.clientLeft||0),top:c.top+(o.pageYOffset||a.scrollTop)-(a.clientTop||0)}):c):void 0}}()}),t.dom.extend({has:function(e){var n=[],r=t.dom(document.body);return t.forEach(this,function(t){r[0]=t,r.find(e).length&&n.push(t)}),t.dom(n)}}),t.dom.extend({hasClass:function(e){if(arguments.length<=0||\"function\"==typeof e)return this;if(this.size()<=0)return!1;e=e.replace(/^\\s+/g,\"\").replace(/\\s+$/g,\"\").replace(/\\s+/g,\" \");var n,r=e.split(\" \");return t.forEach(this,function(e){for(var t=e.className,i=0;i<r.length;i++)if(!~(\" \"+t+\" \").indexOf(\" \"+r[i]+\" \"))return n=!1,void 0;return n!==!1?(n=!0,void 0):void 0}),n}}),t._util_.getWindowOrDocumentWidthOrHeight=t._util_.getWindowOrDocumentWidthOrHeight||function(){var e={window:{},document:{}};return t.forEach([\"Width\",\"Height\"],function(n){var r=\"client\"+n,i=\"offset\"+n,o=\"scroll\"+n;e.window[\"get\"+n]=function(e){var n=e.document,i=n.documentElement[r];return t.browser.isStrict&&i||n.body&&n.body[r]||i},e.document[\"get\"+n]=function(e){var t=e.documentElement;return t[r]>=t[o]?t[r]:Math.max(e.body[o],t[o],e.body[i],t[i])}}),function(t,n,r){return e[n][\"width\"===r?\"getWidth\":\"getHeight\"](t)}}(),t.dom.extend({height:function(e){return t._util_.access(this,\"height\",e,function(e,n,r){var i=void 0!==r,o=i&&parseFloat(r),a=null!=e&&e==e.window?\"window\":9===e.nodeType?\"document\":!1;return i&&0>o||isNaN(o)?void 0:(i&&/^(?:\\d*\\.)?\\d+$/.test(r+=\"\")&&(r+=\"px\"),a?t._util_.getWindowOrDocumentWidthOrHeight(e,a,n):i?e.style.height=r:t._util_.getWidthOrHeight(e,n))})}}),t._util_.isHidden=function(e){return\"none\"===t.dom(e).getCurrentStyle(\"display\")||!t._util_.contains(e.ownerDocument,e)},t.dom.extend({hide:function(){var e,n,r,i=[];return this.each(function(o,a){a.style&&(e=t(a),i[o]=e.data(\"olddisplay\"),r=a.style.display,i[o]||(n=t._util_.isHidden(a),(r&&\"none\"!==r||!n)&&e.data(\"olddisplay\",n?r:e.getCurrentStyle(\"display\"))),a.style.display=\"none\")})}}),t.dom.extend({innerHeight:function(){if(this.size()<=0)return 0;var e=this[0],n=null!=e&&e===e.window?\"window\":9===e.nodeType?\"document\":!1;return n?t._util_.getWindowOrDocumentWidthOrHeight(e,n,\"height\"):t._util_.getWidthOrHeight(e,\"height\",\"padding\")}}),t.dom.extend({innerWidth:function(){if(this.size()<=0)return 0;var e=this[0],n=null!=e&&e===e.window?\"window\":9===e.nodeType?\"document\":!1;return n?t._util_.getWindowOrDocumentWidthOrHeight(e,n,\"width\"):t._util_.getWidthOrHeight(e,\"width\",\"padding\")}}),t.dom.extend({insertAfter:function(e){var n=[],r=n.push;return t.check(\"^(?:string|HTMLElement|\\\\$DOM)$\",\"baidu.dom.insertAfter\"),t._util_.smartInsertTo(this,e,function(e){r.apply(n,t.makeArray(e.childNodes)),this.parentNode.insertBefore(e,this.nextSibling)},\"after\"),this.pushStack(n)}}),t.dom.extend({insertBefore:function(e){var n=[],r=n.push;return t.check(\"^(?:string|HTMLElement|\\\\$DOM)$\",\"baidu.dom.insertBefore\"),t._util_.smartInsertTo(this,e,function(e){r.apply(n,t.makeArray(e.childNodes)),this.parentNode.insertBefore(e,this)},\"before\"),this.pushStack(n)}}),t.dom.extend({insertHTML:function(e,n){var r,i,o=this[0];return o.insertAdjacentHTML&&!t.browser.opera?o.insertAdjacentHTML(e,n):(r=o.ownerDocument.createRange(),e=e.toUpperCase(),\"AFTERBEGIN\"==e||\"BEFOREEND\"==e?(r.selectNodeContents(o),r.collapse(\"AFTERBEGIN\"==e)):(i=\"BEFOREBEGIN\"==e,r[i?\"setStartBefore\":\"setEndAfter\"](o),r.collapse(i)),r.insertNode(r.createContextualFragment(n))),o}}),t.dom.extend({is:function(e){return t.dom.match(this,e).length>0}}),t.dom.extend({last:function(){return this.eq(-1)}}),t.dom.extend({next:function(e){var n=[];return t.forEach(this,function(e){for(;(e=e.nextSibling)&&e&&1!=e.nodeType;);e&&(n[n.length++]=e)}),this.pushStack(e?t.dom.match(n,e):n)}}),t.dom.extend({nextAll:function(e){var n=[];return t.forEach(this,function(e){for(;e=e.nextSibling;)e&&1==e.nodeType&&n.push(e)}),this.pushStack(t.dom.match(n,e))}}),t.dom.extend({nextUntil:function(e,n){var r=t.array();return t.forEach(this,function(n){for(var i=t.array();n=n.nextSibling;)n&&1==n.nodeType&&i.push(n);if(e&&i.length){var o=t.dom.match(i,e);o.length&&(i=i.slice(0,i.indexOf(o[0])))}t.merge(r,i)}),this.pushStack(t.dom.match(r,n))}}),t.dom.extend({not:function(e){var n,r,i,o=this.get(),a=t.isArray(e)?e:t.dom.match(this,e);for(n=o.length-1;n>-1;n--)for(r=0,i=a.length;i>r;r++)a[r]===o[n]&&o.splice(n,1);return this.pushStack(o)}}),t.dom.extend({one:function(e,t,n,r){return this.on(e,t,n,r,1)}}),t.dom.extend({outerHeight:function(e){if(this.size()<=0)return 0;var n=this[0],r=null!=n&&n===n.window?\"window\":9===n.nodeType?\"document\":!1;return r?t._util_.getWindowOrDocumentWidthOrHeight(n,r,\"height\"):t._util_.getWidthOrHeight(n,\"height\",\"padding|border\"+(e?\"|margin\":\"\"))}}),t.dom.extend({outerWidth:function(e){if(this.size()<=0)return 0;var n=this[0],r=null!=n&&n===n.window?\"window\":9===n.nodeType?\"document\":!1;return r?t._util_.getWindowOrDocumentWidthOrHeight(n,r,\"width\"):t._util_.getWidthOrHeight(n,\"width\",\"padding|border\"+(e?\"|margin\":\"\"))}}),t.dom.extend({parent:function(e){var n=[];return t.forEach(this,function(e){(e=e.parentNode)&&1==e.nodeType&&n.push(e)}),this.pushStack(t.dom.match(n,e))}}),t.dom.extend({parents:function(e){var n=[];return t.forEach(this,function(e){for(var r=[];(e=e.parentNode)&&1==e.nodeType;)r.push(e);t.merge(n,r)}),this.pushStack(t.dom.match(n,e))}}),t.dom.extend({parentsUntil:function(e,n){t.check(\"(string|HTMLElement)(,.+)?\",\"baidu.dom.parentsUntil\");var r=[];return t.forEach(this,function(n){for(var i=t.array();(n=n.parentNode)&&1==n.nodeType;)i.push(n);if(e&&i.length){var o=t.dom.match(i,e);o.length&&(i=i.slice(0,i.indexOf(o[0])))}t.merge(r,i)}),this.pushStack(t.dom.match(r,n))}}),t.dom.extend({prepend:function(){return t.check(\"^(?:string|function|HTMLElement|\\\\$DOM)(?:,(?:string|array|HTMLElement|\\\\$DOM))*$\",\"baidu.dom.prepend\"),t._util_.smartInsert(this,arguments,function(e){1===this.nodeType&&this.insertBefore(e,this.firstChild)}),this}}),t.dom.extend({prependTo:function(e){var n=[],r=n.push;return t.check(\"^(?:string|HTMLElement|\\\\$DOM)$\",\"baidu.dom.prependTo\"),t._util_.smartInsertTo(this,e,function(e){r.apply(n,t.makeArray(e.childNodes)),this.insertBefore(e,this.firstChild)}),this.pushStack(n)}}),t.dom.extend({prev:function(e){var n=[];return t.forEach(this,function(e){for(;e=e.previousSibling;)if(1==e.nodeType){n.push(e);break}}),this.pushStack(t.dom.match(n,e))}}),t.dom.extend({prevAll:function(e){var n=t.array();return t.forEach(this,function(e){for(var r=[];e=e.previousSibling;)1==e.nodeType&&r.push(e);\nt.merge(n,r.reverse())}),this.pushStack(\"string\"==typeof e?t.dom.match(n,e):n.unique())}}),t.dom.extend({prevUntil:function(e,n){t.check(\"(string|HTMLElement)(,.+)?\",\"baidu.dom.prevUntil\");var r=[];return t.forEach(this,function(n){for(var i=t.array();n=n.previousSibling;)n&&1==n.nodeType&&i.push(n);if(e&&i.length){var o=t.dom.match(i,e);o.length&&(i=i.slice(0,i.indexOf(o[0])))}t.merge(r,i)}),this.pushStack(t.dom.match(r,n))}}),t.dom.extend({prop:function(e,n){return t._util_.access(this,e,n,function(e,n,r){return t._util_.prop(e,n,r)})}}),t.string.extend({escapeReg:function(){return this.replace(new RegExp(\"([.*+?^=!:${}()|[\\\\]/\\\\\\\\])\",\"g\"),\"\\\\$1\")}}),void function(e,n){function r(e,t,n,r){var i,o,u,c,l=s++,f=0,d=t.length;for(\"string\"!=typeof n||m.test(n)||(n=n.toLowerCase(),c=n);d>f;f++)if(i=t[f]){for(o=!1,i=i[e];i;){if(i[a]===l){o=t[i.sizset];break}if(u=1===i.nodeType,u&&!r&&(i[a]=l,i.sizset=f),c){if(i.nodeName.toLowerCase()===n){o=i;break}}else if(u)if(\"string\"!=typeof n){if(i===n){o=!0;break}}else if(I(n,[i]).length>0){o=i;break}i=i[e]}t[f]=o}}t.query=function(e,n,r){return t.merge(r||[],t.sizzle(e,n))};var i=e.document,o=i.documentElement,a=\"sizcache\"+(Math.random()+\"\").replace(\".\",\"\"),s=0,u=Object.prototype.toString,c=\"undefined\",l=!1,f=!0,d=/^#([\\w\\-]+$)|^(\\w+$)|^\\.([\\w\\-]+$)/,p=/((?:\\((?:\\([^()]+\\)|[^()]+)+\\)|\\[(?:\\[[^\\[\\]]*\\]|['\"][^'\"]*['\"]|[^\\[\\]'\"]+)+\\]|\\\\.|[^ >+~,(\\[\\\\]+)+|[>+~])(\\s*,\\s*)?((?:.|\\r|\\n)*)/g,h=/\\\\/g,m=/\\W/,g=/^\\w/,y=/\\D/,v=/(-?)(\\d*)(?:n([+\\-]?\\d*))?/,b=/^\\+|\\s*/g,x=/h\\d/i,w=/input|select|textarea|button/i,_=/[\\t\\n\\f\\r]/g,E=\"(?:[-\\\\w]|[^\\\\x00-\\\\xa0]|\\\\\\\\.)\",T={ID:new RegExp(\"#(\"+E+\"+)\"),CLASS:new RegExp(\"\\\\.(\"+E+\"+)\"),NAME:new RegExp(\"\\\\[name=['\\\"]*(\"+E+\"+)['\\\"]*\\\\]\"),TAG:new RegExp(\"^(\"+E.replace(\"[-\",\"[-\\\\*\")+\"+)\"),ATTR:new RegExp(\"\\\\[\\\\s*(\"+E+\"+)\\\\s*(?:(\\\\S?=)\\\\s*(?:(['\\\"])(.*?)\\\\3|(#?\"+E+\"*)|)|)\\\\s*\\\\]\"),PSEUDO:new RegExp(\":(\"+E+\"+)(?:\\\\((['\\\"]?)((?:\\\\([^\\\\)]+\\\\)|[^\\\\(\\\\)]*)+)\\\\2\\\\))?\"),CHILD:/:(only|nth|last|first)-child(?:\\(\\s*(even|odd|(?:[+\\-]?\\d+|(?:[+\\-]?\\d*)?n\\s*(?:[+\\-]\\s*\\d+)?))\\s*\\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\\((\\d*)\\))?(?=[^\\-]|$)/},C=T.POS,S=function(){var e,t=function(e,t){return\"\\\\\"+(t-0+1)},n={};for(e in T)T[e]=new RegExp(T[e].source+/(?![^\\[]*\\])(?![^\\(]*\\))/.source),n[e]=new RegExp(/(^(?:.|\\r|\\n)*?)/.source+T[e].source.replace(/\\\\(\\d+)/g,t));return T.globalPOS=C,n}(),k=function(e){var t=!1,n=i.createElement(\"div\");try{t=e(n)}catch(r){}return n=null,t},N=k(function(e){var t=!0,n=\"script\"+(new Date).getTime();return e.innerHTML=\"<a name ='\"+n+\"'/>\",o.insertBefore(e,o.firstChild),i.getElementById(n)&&(t=!1),o.removeChild(e),t}),A=k(function(e){return e.appendChild(i.createComment(\"\")),0===e.getElementsByTagName(\"*\").length}),O=k(function(e){return e.innerHTML=\"<a href='#'></a>\",e.firstChild&&typeof e.firstChild.getAttribute!==c&&\"#\"===e.firstChild.getAttribute(\"href\")}),L=k(function(e){return e.innerHTML=\"<div class='test e'></div><div class='test'></div>\",e.getElementsByClassName&&0!==e.getElementsByClassName(\"e\").length?(e.lastChild.className=\"e\",1!==e.getElementsByClassName(\"e\").length):!1});[0,0].sort(function(){return f=!1,0});var j=function(e,r,o){o=o||[],r=r||i;var a,s,u,c=r.nodeType;if(1!==c&&9!==c)return[];if(!e||\"string\"!=typeof e)return o;if(e=t.string(e).trim(),!e)return o;if(u=M(r),!u&&(a=d.exec(e)))if(a[1]){if(9===c){if(s=r.getElementById(a[1]),!s||!s.parentNode)return $([],o);if(s.id===a[1])return $([s],o)}else if(r.ownerDocument&&(s=r.ownerDocument.getElementById(a[1]))&&B(r,s)&&s.id===a[1])return $([s],o)}else{if(a[2])return\"body\"===e&&r.body?$([r.body],o):$(r.getElementsByTagName(e),o);if(L&&a[3]&&r.getElementsByClassName)return $(r.getElementsByClassName(a[3]),o)}return D(e,r,o,n,u)},D=function(e,t,n,r,i){var o,a,s,c,l,f,d,h,m=t,g=!0,y=[],v=e;do if(p.exec(\"\"),o=p.exec(v),o&&(v=o[3],y.push(o[1]),o[2])){c=o[3];break}while(o);if(y.length>1&&C.exec(e))if(2===y.length&&P.relative[y[0]])a=U(y[0]+y[1],t,r,i);else for(a=P.relative[y[0]]?[t]:j(y.shift(),t);y.length;)e=y.shift(),P.relative[e]&&(e+=y.shift()),a=U(e,a,r,i);else if(!r&&y.length>1&&9===t.nodeType&&!i&&T.ID.test(y[0])&&!T.ID.test(y[y.length-1])&&(l=F(y.shift(),t,i),t=l.expr?I(l.expr,l.set)[0]:l.set[0]),t)for(l=r?{expr:y.pop(),set:$(r)}:F(y.pop(),y.length>=1&&(\"~\"===y[0]||\"+\"===y[0])&&t.parentNode||t,i),a=l.expr?I(l.expr,l.set):l.set,y.length>0?s=$(a):g=!1;y.length;)f=y.pop(),d=f,P.relative[f]?d=y.pop():f=\"\",null==d&&(d=t),P.relative[f](s,d,i);else s=y=[];if(s||(s=a),s||R(f||e),\"[object Array]\"===u.call(s))if(g)if(t&&1===t.nodeType)for(h=0;null!=s[h];h++)s[h]&&(s[h]===!0||1===s[h].nodeType&&B(t,s[h]))&&n.push(a[h]);else for(h=0;null!=s[h];h++)s[h]&&1===s[h].nodeType&&n.push(a[h]);else n.push.apply(n,s);else $(s,n);return c&&(D(c,m,n,r,i),H(n)),n},M=t._util_.isXML,$=t.makeArray,H=function(e){if(q&&(l=f,e.sort(q),l))for(var t=1;t<e.length;t++)e[t]===e[t-1]&&e.splice(t--,1);return e},B=t._util_.contains,F=function(e,t,n){var r,i,o,a,s,u;if(!e)return[];for(i=0,o=P.order.length;o>i;i++)if(s=P.order[i],(a=S[s].exec(e))&&(u=a[1],a.splice(1,1),\"\\\\\"!==u.substr(u.length-1)&&(a[1]=(a[1]||\"\").replace(h,\"\"),r=P.find[s](a,t,n),null!=r))){e=e.replace(T[s],\"\");break}return r||(r=typeof t.getElementsByTagName!==c?t.getElementsByTagName(\"*\"):[]),{set:r,expr:e}},I=function(e,t,r,i){for(var o,a,s,u,c,l,f,d,p,h=e,m=[],g=t,y=t&&t[0]&&M(t[0]);e&&t.length;){for(s in P.filter)if(null!=(o=S[s].exec(e))&&o[2]){if(l=P.filter[s],f=o[1],a=!1,o.splice(1,1),\"\\\\\"===f.substr(f.length-1))continue;if(g===m&&(m=[]),P.preFilter[s])if(o=P.preFilter[s](o,g,r,m,i,y)){if(o===!0)continue}else a=u=!0;if(o)for(d=0;null!=(c=g[d]);d++)c&&(u=l(c,o,d,g),p=i^u,r&&null!=u?p?a=!0:g[d]=!1:p&&(m.push(c),a=!0));if(u!==n){if(r||(g=m),e=e.replace(T[s],\"\"),!a)return[];break}}if(e===h){if(null!=a)break;R(e)}h=e}return g},R=function(e){throw new Error(e)},W=function(e){var t,n,r=e.nodeType,i=\"\";if(r){if(1===r||9===r||11===r){if(\"string\"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)i+=W(e)}else if(3===r||4===r)return e.nodeValue}else for(t=0;n=e[t];t++)8!==n.nodeType&&(i+=W(n));return i},P={match:T,leftMatch:S,order:[\"ID\",\"NAME\",\"TAG\"],attrMap:{\"class\":\"className\",\"for\":\"htmlFor\"},attrHandle:{href:O?function(e){return e.getAttribute(\"href\")}:function(e){return e.getAttribute(\"href\",2)},type:function(e){return e.getAttribute(\"type\")}},relative:{\"+\":function(e,t){var n=\"string\"==typeof t,r=n&&!m.test(t),i=n&&!r;r&&(t=t.toLowerCase());for(var o,a=0,s=e.length;s>a;a++)if(o=e[a]){for(;(o=o.previousSibling)&&1!==o.nodeType;);e[a]=i||o&&o.nodeName.toLowerCase()===t?o||!1:o===t}i&&I(t,e,!0)},\">\":function(e,t){var n,r=\"string\"==typeof t,i=0,o=e.length;if(r&&!m.test(t)){for(t=t.toLowerCase();o>i;i++)if(n=e[i]){var a=n.parentNode;e[i]=a.nodeName.toLowerCase()===t?a:!1}}else{for(;o>i;i++)n=e[i],n&&(e[i]=r?n.parentNode:n.parentNode===t);r&&I(t,e,!0)}},\"\":function(e,t,n){r(\"parentNode\",e,t,n)},\"~\":function(e,t,n){r(\"previousSibling\",e,t,n)}},find:{ID:N?function(e,t,n){if(typeof t.getElementById!==c&&!n){var r=t.getElementById(e[1]);return r&&r.parentNode?[r]:[]}}:function(e,t,r){if(typeof t.getElementById!==c&&!r){var i=t.getElementById(e[1]);return i?i.id===e[1]||typeof i.getAttributeNode!==c&&i.getAttributeNode(\"id\").nodeValue===e[1]?[i]:n:[]}},NAME:function(e,t){if(typeof t.getElementsByName!==c){for(var n=[],r=t.getElementsByName(e[1]),i=0,o=r.length;o>i;i++)r[i].getAttribute(\"name\")===e[1]&&n.push(r[i]);return 0===n.length?null:n}},TAG:A?function(e,t){return typeof t.getElementsByTagName!==c?t.getElementsByTagName(e[1]):void 0}:function(e,t){var n=t.getElementsByTagName(e[1]);if(\"*\"===e[1]){for(var r=[],i=0;n[i];i++)1===n[i].nodeType&&r.push(n[i]);n=r}return n}},preFilter:{CLASS:function(e,t,n,r,i,o){if(e=\" \"+e[1].replace(h,\"\")+\" \",o)return e;for(var a,s=0;null!=(a=t[s]);s++)a&&(i^(a.className&&~(\" \"+a.className+\" \").replace(_,\" \").indexOf(e))?n||r.push(a):n&&(t[s]=!1));return!1},ID:function(e){return e[1].replace(h,\"\")},TAG:function(e){return e[1].replace(h,\"\").toLowerCase()},CHILD:function(e){if(\"nth\"===e[1]){e[2]||R(e[0]),e[2]=e[2].replace(b,\"\");var t=v.exec(\"even\"===e[2]&&\"2n\"||\"odd\"===e[2]&&\"2n+1\"||!y.test(e[2])&&\"0n+\"+e[2]||e[2]);e[2]=t[1]+(t[2]||1)-0,e[3]=t[3]-0}else e[2]&&R(e[0]);return e[0]=s++,e},ATTR:function(e,t,n,r,i,o){var a=e[1]=e[1].replace(h,\"\");return!o&&P.attrMap[a]&&(e[1]=P.attrMap[a]),e[4]=(e[4]||e[5]||\"\").replace(h,\"\"),\"~=\"===e[2]&&(e[4]=\" \"+e[4]+\" \"),e},PSEUDO:function(e,t,n,r,o,a){if(\"not\"===e[1]){if(!((p.exec(e[3])||\"\").length>1||g.test(e[3]))){var s=I(e[3],t,n,!o);return n||r.push.apply(r,s),!1}e[3]=D(e[3],i,[],t,a)}else if(T.POS.test(e[0])||T.CHILD.test(e[0]))return!0;return e},POS:function(e){return e.unshift(!0),e}},filters:{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},parent:function(e){return!!e.firstChild},empty:function(e){return!e.firstChild},has:function(e,t,n){return!!j(n[3],e).length},header:function(e){return x.test(e.nodeName)},text:function(e){var t=e.getAttribute(\"type\"),n=e.type;return\"input\"===e.nodeName.toLowerCase()&&\"text\"===n&&(null===t||t.toLowerCase()===n)},radio:function(e){return\"input\"===e.nodeName.toLowerCase()&&\"radio\"===e.type},checkbox:function(e){return\"input\"===e.nodeName.toLowerCase()&&\"checkbox\"===e.type},file:function(e){return\"input\"===e.nodeName.toLowerCase()&&\"file\"===e.type},password:function(e){return\"input\"===e.nodeName.toLowerCase()&&\"password\"===e.type},submit:function(e){var t=e.nodeName.toLowerCase();return(\"input\"===t||\"button\"===t)&&\"submit\"===e.type},image:function(e){return\"input\"===e.nodeName.toLowerCase()&&\"image\"===e.type},reset:function(e){var t=e.nodeName.toLowerCase();return(\"input\"===t||\"button\"===t)&&\"reset\"===e.type},button:function(e){var t=e.nodeName.toLowerCase();return\"input\"===t&&\"button\"===e.type||\"button\"===t},input:function(e){return w.test(e.nodeName)},focus:function(e){var t=e.ownerDocument;return!(e!==t.activeElement||t.hasFocus&&!t.hasFocus()||!e.type&&!e.href)},active:function(e){return e===e.ownerDocument.activeElement},contains:function(e,t,n){return(e.textContent||e.innerText||W(e)).indexOf(n[3])>=0}},setFilters:{first:function(e,t){return 0===t},last:function(e,t,n,r){return t===r.length-1},even:function(e,t){return t%2===0},odd:function(e,t){return t%2===1},lt:function(e,t,n){return t<n[3]-0},gt:function(e,t,n){return t>n[3]-0},nth:function(e,t,n){return n[3]-0===t},eq:function(e,t,n){return n[3]-0===t}},filter:{PSEUDO:function(e,t,n,r){var i=t[1],o=P.filters[i];if(o)return o(e,n,t,r);if(\"not\"===i){for(var a=t[3],s=0,u=a.length;u>s;s++)if(a[s]===e)return!1;return!0}R(i)},CHILD:function(e,t){var n,r,i,o,s,u,c=t[1],l=e;switch(c){case\"only\":case\"first\":for(;l=l.previousSibling;)if(1===l.nodeType)return!1;if(\"first\"===c)return!0;l=e;case\"last\":for(;l=l.nextSibling;)if(1===l.nodeType)return!1;return!0;case\"nth\":if(n=t[2],r=t[3],1===n&&0===r)return!0;if(i=t[0],o=e.parentNode,o&&(o[a]!==i||!e.nodeIndex)){for(s=0,l=o.firstChild;l;l=l.nextSibling)1===l.nodeType&&(l.nodeIndex=++s);o[a]=i}return u=e.nodeIndex-r,0===n?0===u:u%n===0&&u/n>=0}},ID:N?function(e,t){return 1===e.nodeType&&e.getAttribute(\"id\")===t}:function(e,t){var n=typeof e.getAttributeNode!==c&&e.getAttributeNode(\"id\");return 1===e.nodeType&&n&&n.nodeValue===t},TAG:function(e,t){return\"*\"===t&&1===e.nodeType||!!e.nodeName&&e.nodeName.toLowerCase()===t},CLASS:function(e,t){return(\" \"+(e.className||e.getAttribute(\"class\"))+\" \").indexOf(t)>-1},ATTR:function(e,t){var n=t[1],r=P.attrHandle[n]?P.attrHandle[n](e):null!=e[n]?e[n]:e.getAttribute(n),i=r+\"\",o=t[2],a=t[4];return null==r?\"!=\"===o:\"=\"===o?i===a:\"*=\"===o?i.indexOf(a)>=0:\"~=\"===o?(\" \"+i+\" \").indexOf(a)>=0:a?\"!=\"===o?i!==a:\"^=\"===o?0===i.indexOf(a):\"$=\"===o?i.substr(i.length-a.length)===a:\"|=\"===o?i===a||i.substr(0,a.length+1)===a+\"-\":!1:i&&r!==!1},POS:function(e,t,n,r){var i=t[2],o=P.setFilters[i];return o?o(e,n,t,r):void 0}}};L&&(P.order.splice(1,0,\"CLASS\"),P.find.CLASS=function(e,t,n){return typeof t.getElementsByClassName===c||n?void 0:t.getElementsByClassName(e[1])});var q,z;o.compareDocumentPosition?q=function(e,t){return e===t?(l=!0,0):e.compareDocumentPosition&&t.compareDocumentPosition?4&e.compareDocumentPosition(t)?-1:1:e.compareDocumentPosition?-1:1}:(q=function(e,t){if(e===t)return l=!0,0;if(e.sourceIndex&&t.sourceIndex)return e.sourceIndex-t.sourceIndex;var n,r,i=[],o=[],a=e.parentNode,s=t.parentNode,u=a;if(a===s)return z(e,t);if(!a)return-1;if(!s)return 1;for(;u;)i.unshift(u),u=u.parentNode;for(u=s;u;)o.unshift(u),u=u.parentNode;n=i.length,r=o.length;for(var c=0;n>c&&r>c;c++)if(i[c]!==o[c])return z(i[c],o[c]);return c===n?z(e,o[c],-1):z(i[c],t,1)},z=function(e,t,n){if(e===t)return n;for(var r=e.nextSibling;r;){if(r===t)return-1;r=r.nextSibling}return 1}),i.querySelectorAll&&!function(){var e=D,t=\"__sizzle__\",n=/^\\s*[+~]/,r=/'/g,i=[];k(function(e){e.innerHTML=\"<select><option selected></option></select>\",e.querySelectorAll(\"[selected]\").length||i.push(\"\\\\[[\\\\x20\\\\t\\\\n\\\\r\\\\f]*(?:checked|disabled|ismap|multiple|readonly|selected|value)\"),e.querySelectorAll(\":checked\").length||i.push(\":checked\")}),k(function(e){e.innerHTML=\"<p class=''></p>\",e.querySelectorAll(\"[class^='']\").length&&i.push(\"[*^$]=[\\\\x20\\\\t\\\\n\\\\r\\\\f]*(?:\\\"\\\"|'')\"),e.innerHTML=\"<input type='hidden'>\",e.querySelectorAll(\":enabled\").length||i.push(\":enabled\",\":disabled\")}),i=i.length&&new RegExp(i.join(\"|\")),D=function(o,a,s,u,c){if(!(u||c||i&&i.test(o)))if(9===a.nodeType)try{return $(a.querySelectorAll(o),s)}catch(l){}else if(1===a.nodeType&&\"object\"!==a.nodeName.toLowerCase()){var f=a,d=a.getAttribute(\"id\"),p=d||t,h=a.parentNode,m=n.test(o);d?p=p.replace(r,\"\\\\$&\"):a.setAttribute(\"id\",p),m&&h&&(a=h);try{if(!m||h)return $(a.querySelectorAll(\"[id='\"+p+\"'] \"+o),s)}catch(l){}finally{d||f.removeAttribute(\"id\")}}return e(o,a,s,u,c)}}();var U=function(e,t,n,r){for(var i,o=[],a=\"\",s=t.nodeType?[t]:t,u=0,c=s.length;i=T.PSEUDO.exec(e);)a+=i[0],e=e.replace(T.PSEUDO,\"\");for(P.relative[e]&&(e+=\"*\");c>u;u++)D(e,s[u],o,n,r);return I(a,o)};e.Sizzle=t.sizzle=j,t.query.matches=function(e,t){return D(e,i,[],t,M(i))}}(window),t.dom.extend({ready:function(){var e,n=this,r=window.document;t._util_.isDomReady=!1,t._util_._readyWait=1,t.dom.holdReady=function(e){e?t._util_.readyWait++:i(!0)};var i=function(n){if(n===!0?!--t._util_.readyWait:!t._util_.isDomReady){if(!r.body)return setTimeout(i,1);t._util_.isReady=!0,n!==!0&&--t._util_.readyWait>0||(e.resolveWith(r),t.dom.trigger&&t.dom(r).trigger(\"ready\").off(\"ready\"))}},o=function(){r.addEventListener?(r.removeEventListener(\"DOMContentLoaded\",o,!1),i()):\"complete\"===r.readyState&&(r.detachEvent(\"onreadystatechange\",o),i())},a=function(n){if(!e)if(e=t.Deferred(),\"complete\"===r.readyState)setTimeout(i,1);else if(r.addEventListener)r.addEventListener(\"DOMContentLoaded\",o,!1),window.addEventListener(\"load\",i,!1);else{r.attachEvent(\"onreadystatechange\",o),window.attachEvent(\"onload\",i);var a=!1;try{a=null==window.frameElement&&r.documentElement}catch(s){}a&&a.doScroll&&!function u(){if(!t._util_.isDomReady){try{a.doScroll(\"left\")}catch(e){return setTimeout(u,50)}i()}}()}return e.promise(n)};return function(e){return a().done(e),n}}()}),t.dom.extend({removeAttr:function(e){return this.each(function(n,r){t._util_.removeAttr(r,e)}),this}}),t.dom.extend({removeClass:function(e){var n=typeof e,r=\" \";if(arguments.length||t.forEach(this,function(e){e.className=\"\"}),\"string\"==n){e=t.string.trim(e);var i=e.split(\" \");t.forEach(this,function(e){for(var n=e.className,o=0;o<i.length;o++)for(;~(r+n+r).indexOf(r+i[o]+r);)n=(r+n+r).replace(r+i[o]+r,r);e.className=t.string.trim(n)})}else\"function\"==n&&t.forEach(this,function(n,r){t.dom(n).removeClass(e.call(n,r,n.className))});return this}}),t.dom.extend({removeData:function(){var e=t.key,n=t.global(\"_maps_HTMLElementData\");return function(r){return t.forEach(this,function(n){!n[e]&&(n[e]=t.id())}),t.forEach(this,function(i){var o=n[i[e]];\"string\"==typeof r?o&&delete o[r]:\"array\"==t.type(r)&&t.forEach(r,function(e){o&&delete o[e]})}),this}}()}),t.dom.extend({removeProp:function(e){return e=t._util_.propFixer[e]||e,this.each(function(t,n){try{n[e]=void 0,delete n[e]}catch(r){}}),this}}),t._util_.smartScroll=function(e){function n(e){return e&&9===e.nodeType}function r(e){return\"Window\"==t.type(e)?e:n(e)?e.defaultView||e.parentWindow:!1}var i={scrollLeft:\"pageXOffset\",scrollTop:\"pageYOffset\"}[e],o=\"scrollLeft\"===e;return{get:function(n){var o=r(n);return o?i in o?o[i]:t.browser.isStrict&&o.document.documentElement[e]||o.document.body[e]:n[e]},set:function(t,n){if(t){var i=r(t);i?i.scrollTo(o?n:this.get(t),o?this.get(t):n):t[e]=n}}}},t.dom.extend({scrollLeft:function(){var e=t._util_.smartScroll(\"scrollLeft\");return function(n){return n&&t.check(\"^(?:number|string)$\",\"baidu.dom.scrollLeft\"),this.size()<=0?void 0===n?0:this:void 0===n?e.get(this[0]):e.set(this[0],n)||this}}()}),t.dom.extend({scrollTop:function(){var e=t._util_.smartScroll(\"scrollTop\");return function(n){return n&&t.check(\"^(?:number|string)$\",\"baidu.dom.scrollTop\"),this.size()<=0?void 0===n?0:this:void 0===n?e.get(this[0]):e.set(this[0],n)||this}}()}),t.dom.setPixel=function(e,n,r){\"undefined\"!=typeof r&&(t.dom.g(e).style[n]=r+(isNaN(r)?\"\":\"px\"))},t._util_.getDefaultDisplayValue=function(){var e={};return function(n){if(e[n])return e[n];var r,i,o,a=document.createElement(n);return document.body.appendChild(a),r=t.dom(a).getCurrentStyle(\"display\"),document.body.removeChild(a),(\"\"===r||\"none\"===r)&&(i=document.body.appendChild(document.createElement(\"iframe\")),i.frameBorder=i.width=i.height=0,o=(i.contentWindow||i.contentDocument).document,o.writeln(\"<!DOCTYPE html><html><body>\"),o.close(),a=o.appendChild(o.createElement(n)),r=t.dom(a).getCurrentStyle(\"display\"),document.body.removeChild(i),i=null),a=null,e[n]=r}}(),t.dom.extend({show:function(){var e,n,r=[];return this.each(function(i,o){o.style&&(n=t.dom(o),e=o.style.display,r[i]=n.data(\"olddisplay\"),r[i]||\"none\"!==e||(o.style.display=\"\"),\"\"===o.style.display&&t._util_.isHidden(o)&&n.data(\"olddisplay\",r[i]=t._util_.getDefaultDisplayValue(o.nodeName)))}),this.each(function(e,t){t.style&&(\"none\"===t.style.display||\"\"===t.style.display)&&(t.style.display=r[e]||\"\")})}}),t.dom.extend({siblings:function(e){var n=[];return t.forEach(this,function(e){for(var r=[],i=[],o=e;o=o.previousSibling;)1==o.nodeType&&r.push(o);for(;e=e.nextSibling;)1==e.nodeType&&i.push(e);t.merge(n,r.reverse().concat(i))}),this.pushStack(t.dom.match(n,e))}}),t.dom.extend({slice:function(){var e=Array.prototype.slice;return function(){return t.check(\"number(,number)?\",\"baidu.dom.slice\"),this.pushStack(e.apply(this,arguments))}}()}),t.dom.extend({text:function(e){var n,r=t.dom,i=this,o=!1;if(this.size()<=0)switch(typeof e){case\"undefined\":return void 0;default:return i}var a=function(e){var t=\"\",n=e.nodeType;if(n)if(1===n||9===n||11===n){if(\"string\"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)t+=a(e)}else if(3===n||4===n)return e.nodeValue;return t};return t.forEach(i,function(t,i){var s=r(t);if(!n)switch(typeof e){case\"undefined\":return n=a(t);case\"number\":e=String(e);case\"string\":o=!0,s.empty().append((t&&t.ownerDocument||document).createTextNode(e));break;case\"function\":o=!0,s.text(e.call(t,i,s.text()))}}),o?i:n}}),t.dom.extend({toggle:function(){for(var e=0,t=this.size();t>e;e++){var n=this.eq(e);\"none\"!=n.css(\"display\")?n.hide():n.show()}}}),t.dom.extend({toggleClass:function(e,n){var n=\"undefined\"==typeof n?n:Boolean(n);switch(arguments.length<=0&&t.forEach(this,function(e){e.className=\"\"}),typeof e){case\"string\":e=e.replace(/^\\s+/g,\"\").replace(/\\s+$/g,\"\").replace(/\\s+/g,\" \");var r=e.split(\" \");t.forEach(this,function(e){for(var t=e.className,i=0;i<r.length;i++)~(\" \"+t+\" \").indexOf(\" \"+r[i]+\" \")&&\"undefined\"==typeof n?t=(\" \"+t+\" \").replace(\" \"+r[i]+\" \",\" \"):~(\" \"+t+\" \").indexOf(\" \"+r[i]+\" \")||\"undefined\"!=typeof n?~(\" \"+t+\" \").indexOf(\" \"+r[i]+\" \")||n!==!0?~(\" \"+t+\" \").indexOf(\" \"+r[i]+\" \")&&n===!1&&(t=t.replace(r[i],\"\")):t+=\" \"+r[i]:t+=\" \"+r[i];e.className=t.replace(/^\\s+/g,\"\").replace(/\\s+$/g,\"\")});break;case\"function\":t.forEach(this,function(r,i){t.dom(r).toggleClass(e.call(r,i,r.className),n)})}return this}}),void function(e){if(!e.mousewheel){var n=/firefox/i.test(navigator.userAgent),r=/msie/i.test(navigator.userAgent);t.each({mouseenter:\"mouseover\",mouseleave:\"mouseout\"},function(n,r){e[n]={bindType:r,pack:function(e){var r=t.dom.contains;return function(t){var i=t.relatedTarget;return t.type=n,!i||i!==this&&!r(this,i)?e.apply(this,arguments):void 0}}}}),r||t.each({focusin:\"focus\",focusout:\"blur\"},function(t,n){e[t]={bindType:n,attachElements:\"textarea,select,input,button,a\"}}),e.mousewheel={bindType:n?\"DOMMouseScroll\":\"mousewheel\",pack:function(e){return function(t){var r=t.originalEvent;return t.type=\"mousewheel\",t.wheelDelta=t.wheelDelta||(n?-40*r.detail:r.wheelDelta)||0,e.apply(this,arguments)}}}}}(t.event.special),void function(e){var n=e.queue;t.dom.extend({triggerHandler:function(e,r,i){return i&&!i.triggerData&&(i.triggerData=r),t.forEach(this,function(t){n.call(t,e,void 0,i)}),this}})}(t._util_.eventBase),void function(e,n){var r=n.special,i=e.queue,o=t.dom,a=!window.addEventListener,s=/firefox/i.test(navigator.userAgent),u={submit:3,focus:a?3:2,blur:a?3:s?1:2},c=function(e,t){var n;document.createEvent?(n=document.createEvent(\"HTMLEvents\"),n.initEvent(e,!0,!0)):document.createEventObject&&(n=document.createEventObject(),n.type=e);var r={};if(t)for(var i in t)try{n[i]=t[i]}catch(o){n.extraData||(n.extraData=r),r[i]=t[i]}return n},l=function(e,t,n){return e.dispatchEvent?e.dispatchEvent(n):e.fireEvent?e.fireEvent(\"on\"+t,n):void 0},f=function(e,t,n,r,a){var s,f;if(s=c(t,r))if(n&&(s.triggerData=n),a)i.call(e,t,null,s);else{var d=e.window===window?3:u[t];try{(1&d||!(t in u))&&(f=l(e,t,s))}catch(p){o(e).triggerHandler(t,n,s)}if(f!==!1&&2&d)try{e[t]&&e[t]()}catch(p){}}};t.dom.extend({trigger:function(e,t,n){var i;return e in r&&(i=r[e]),this.each(function(){f(this,e,t,n,i)}),this}})}(t._util_.eventBase,t.event),t.dom.extend({unbind:function(e,t){return this.off(e,t)}}),t.dom.extend({undelegate:function(e,t,n){return this.off(t,e,n)}}),t.dom.extend({unique:function(e){return t.dom(t.array(this.toArray()).unique(e))}}),t._util_.inArray=function(e,t,n){if(!t)return-1;var r,i=Array.prototype.indexOf;if(i)return i.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},t.dom.extend({val:function(){t._util_.support.dom.select.disabled=!0;var e=t._util_,n=\"on\"===e.support.dom.input.value,r=!e.support.dom.opt.disabled,i=[\"radio\",\"checkbox\"],o={option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(n){for(var i,o,a=n.options,s=n.selectedIndex,u=\"select-one\"===n.type||0>s,c=u?null:[],l=u?s+1:a.length,f=0>s?l:u?s:0;l>f;f++)if(i=a[f],!(!i.selected&&f!==s||(r?i.disabled:null!==i.getAttribute(\"disabled\"))||i.parentNode.disabled&&e.nodeName(i.parentNode,\"optgroup\"))){if(o=t.dom(i).val(),u)return o;c.push(o)}return c},set:function(n,r,i){var o=t.makeArray(i);return t.dom(n).find(\"option\").each(function(n,r){r.selected=e.inArray(t.dom(this).val(),o)>=0}),!o.length&&(n.selectedIndex=-1),o}}};return!e.support.getSetAttribute&&(o.button=e.nodeHook),n||t.forEach(i,function(e){o[e]={get:function(e){return null===e.getAttribute(\"value\")?\"on\":e.value}}}),t.forEach(i,function(n){o[n]=o[n]||{},o[n].set=function(n,r,i){return\"array\"===t.type(i)?n.checked=e.inArray(t.dom(n).val(),i)>=0:void 0}}),function(e){var n,r;if(void 0===e){if(!(n=this[0]))return;return r=o[n.type]||o[n.nodeName.toLowerCase()]||{},r.get&&r.get(n,\"value\")||n.value}return this.each(function(n,i){if(1===i.nodeType){var a=t.dom(i),s=\"function\"===t.type(e)?e.call(i,n,a.val()):e;null==s?s=\"\":\"number\"===t.type(s)?s+=\"\":\"array\"===t.type(s)&&(s=t.array(s).map(function(e){return null==e?\"\":e+\"\"})),r=o[i.type]||o[i.nodeName.toLowerCase()]||{},r.set&&void 0!==r.set(i,\"value\",s)||(i.value=s)}}),this}}()}),t.dom.extend({width:function(e){return t._util_.access(this,\"width\",e,function(e,n,r){var i=void 0!==r,o=i&&parseFloat(r),a=null!=e&&e==e.window?\"window\":9===e.nodeType?\"document\":!1;return i&&0>o||isNaN(o)?void 0:(i&&/^(?:\\d*\\.)?\\d+$/.test(r+=\"\")&&(r+=\"px\"),a?t._util_.getWindowOrDocumentWidthOrHeight(e,a,n):i?e.style.width=r:t._util_.getWidthOrHeight(e,n))})}}),t.dom.extend({end:function(){return this.prevObject||t.dom(null)}}),void function(){for(var e=\"blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave mousewheel change select submit keydown keypress keyup error contextmenu\".split(\" \"),n={},r=function(e){n[e]=function(t,n){return null==n&&(n=t,t=null),arguments.length>0?this.on(e,null,t,n):this.trigger(e)}},i=0,o=e.length;o>i;i++)r(e[i]);t.dom.extend(n)}(),t.createChain(\"fn\",function(e){return new t.fn.$Fn(~\"function|string\".indexOf(t.type(e))?e:function(){})},function(e){this.fn=e}),t.fn.extend({bind:function(e){var n=this.fn,r=arguments.length>1?Array.prototype.slice.call(arguments,1):null;return function(){var i=\"string\"===t.type(n)?e[n]:n,o=r?r.concat(Array.prototype.slice.call(arguments,0)):arguments;return i.apply(e||i,o)}}}),t.fn.blank=function(){},t.fx=t.fx||{},t.lang.inherits=t.base.inherits,t.fx.Timeline=function(e){t.lang.Class.call(this),this.interval=16,this.duration=500,this.dynamic=!0,t.object.extend(this,e)},t.lang.inherits(t.fx.Timeline,t.lang.Class,\"baidu.fx.Timeline\").extend({launch:function(){var e=this;return e.dispatchEvent(\"onbeforestart\"),\"function\"==typeof e.initialize&&e.initialize(),e[\"\u0006btime\"]=(new Date).getTime(),e[\"\u0006etime\"]=e[\"\u0006btime\"]+(e.dynamic?e.duration:0),e[\"\u0006pulsed\"](),e},\"\u0006pulsed\":function(){var e=this,t=(new Date).getTime();return e.percent=(t-e[\"\u0006btime\"])/e.duration,e.dispatchEvent(\"onbeforeupdate\"),t>=e[\"\u0006etime\"]?(\"function\"==typeof e.render&&e.render(e.transition(e.percent=1)),\"function\"==typeof e.finish&&e.finish(),e.dispatchEvent(\"onafterfinish\"),e.dispose(),void 0):(\"function\"==typeof e.render&&e.render(e.transition(e.percent)),e.dispatchEvent(\"onafterupdate\"),e[\"\u0006timer\"]=setTimeout(function(){e[\"\u0006pulsed\"]()},e.interval),void 0)},transition:function(e){return e},cancel:function(){this[\"\u0006timer\"]&&clearTimeout(this[\"\u0006timer\"]),this[\"\u0006etime\"]=this[\"\u0006btime\"],\"function\"==typeof this.restore&&this.restore(),this.dispatchEvent(\"oncancel\"),this.dispose()},end:function(){this[\"\u0006timer\"]&&clearTimeout(this[\"\u0006timer\"]),this[\"\u0006etime\"]=this[\"\u0006btime\"],this[\"\u0006pulsed\"]()}}),t.fx.create=function(e,n,r){var i=new t.fx.Timeline(n);i.element=e,i.__type=r||i.__type,i[\"\u0006original\"]={};var o=\"baidu_current_effect\";return i.addEventListener(\"onbeforestart\",function(){var e,t=this;t.attribName=\"att_\"+t.__type.replace(/\\W/g,\"_\"),e=t.element.getAttribute(o),t.element.setAttribute(o,(e||\"\")+\"|\"+t.guid+\"|\",0),t.overlapping||((e=t.element.getAttribute(t.attribName))&&baiduInstance(e).cancel(),t.element.setAttribute(t.attribName,t.guid,0))}),i[\"\u0006clean\"]=function(e){var t,n=this;(e=n.element)&&(e.removeAttribute(n.attribName),t=e.getAttribute(o),t=t.replace(\"|\"+n.guid+\"|\",\"\"),t?e.setAttribute(o,t,0):e.removeAttribute(o))},i.addEventListener(\"oncancel\",function(){this[\"\u0006clean\"](),this[\"\u0006restore\"]()}),i.addEventListener(\"onafterfinish\",function(){this[\"\u0006clean\"](),this.restoreAfterFinish&&this[\"\u0006restore\"]()}),i.protect=function(e){this[\"\u0006original\"][e]=this.element.style[e]},i[\"\u0006restore\"]=function(){var e,t=this[\"\u0006original\"],n=this.element.style;for(var r in t)e=t[r],\"undefined\"!=typeof e&&(n[r]=e,!e&&n.removeAttribute?n.removeAttribute(r):!e&&n.removeProperty&&n.removeProperty(r))},i},t.fx.current=function(e){if(!(e=t.dom.g(e)))return null;var n,r,i=/\\|([^\\|]+)\\|/g;do if(r=e.getAttribute(\"baidu_current_effect\"))break;while((e=e.parentNode)&&1==e.nodeType);if(!r)return null;if(n=r.match(i)){i=/\\|([^\\|]+)\\|/;for(var o=0;o<n.length;o++)i.test(n[o]),n[o]=t._global_._instances[RegExp.$1]}return n},t.string.extend({formatColor:function(){var e=/^\\#[\\da-f]{6}$/i,t=/^rgb\\((\\d+),\\s*(\\d+),\\s*(\\d+)\\)$/i,n={black:\"#000000\",silver:\"#c0c0c0\",gray:\"#808080\",white:\"#ffffff\",maroon:\"#800000\",red:\"#ff0000\",purple:\"#800080\",fuchsia:\"#ff00ff\",green:\"#008000\",lime:\"#00ff00\",olive:\"#808000\",yellow:\"#ffff0\",navy:\"#000080\",blue:\"#0000ff\",teal:\"#008080\",aqua:\"#00ffff\"};return function(){var r=this.valueOf();if(e.test(r))return r;if(t.test(r)){for(var i,o=1,r=\"#\";4>o;o++)i=parseInt(RegExp[\"$\"+o]).toString(16),r+=(\"00\"+i).substr(i.length);return r}if(/^\\#[\\da-f]{3}$/.test(r)){var a=r.charAt(1),s=r.charAt(2),u=r.charAt(3);return\"#\"+a+a+s+s+u+u}return n[r]?n[r]:\"\"}}()}),t.fx.move=function(e,n){if(!(e=t.dom.g(e))||\"static\"==t.dom.getStyle(e,\"position\"))return null;if(n=t.object.extend({x:0,y:0},n||{}),0==n.x&&0==n.y)return null;var r=t.fx.create(e,t.object.extend({initialize:function(){this.protect(\"top\"),this.protect(\"left\"),this.originX=parseInt(t.dom.getStyle(e,\"left\"))||0,this.originY=parseInt(t.dom.getStyle(e,\"top\"))||0},transition:function(e){return 1-Math.pow(1-e,2)},render:function(t){e.style.top=this.y*t+this.originY+\"px\",e.style.left=this.x*t+this.originX+\"px\"}},n),\"baidu.fx.move\");return r.launch()},t.fx.moveTo=function(e,n,r){if(!(e=t.dom.g(e))||\"static\"==t.dom.getStyle(e,\"position\")||\"object\"!=typeof n)return null;var i=[n[0]||n.x||0,n[1]||n.y||0],o=parseInt(t.dom.getStyle(e,\"left\"))||0,a=parseInt(t.dom.getStyle(e,\"top\"))||0,s=t.fx.move(e,t.object.extend({x:i[0]-o,y:i[1]-a},r||{}));return s},t.fx.scrollBy=function(e,n,r){if(!(e=t.dom.g(e))||\"object\"!=typeof n)return null;var i={},o={};i.x=n[0]||n.x||0,i.y=n[1]||n.y||0;var a=t.fx.create(e,t.object.extend({initialize:function(){var t=o.sTop=e.scrollTop,n=o.sLeft=e.scrollLeft;o.sx=Math.min(e.scrollWidth-e.clientWidth-n,i.x),o.sy=Math.min(e.scrollHeight-e.clientHeight-t,i.y)},transition:function(e){return 1-Math.pow(1-e,2)},render:function(t){e.scrollTop=o.sy*t+o.sTop,e.scrollLeft=o.sx*t+o.sLeft},restore:function(){e.scrollTop=o.sTop,e.scrollLeft=o.sLeft}},r),\"baidu.fx.scroll\");return a.launch()},t.fx.scrollTo=function(e,n,r){if(!(e=t.dom.g(e))||\"object\"!=typeof n)return null;var i={};return i.x=(n[0]||n.x||0)-e.scrollLeft,i.y=(n[1]||n.y||0)-e.scrollTop,t.fx.scrollBy(e,i,r)},t._util_.smartAjax=t._util_.smartAjax||function(e){return function(n,r,i,o){\"function\"===t.type(r)&&(o=o||i,i=r,r=void 0),t.ajax({type:e,url:n,data:r,success:i,dataType:o})}},t.get=t.get||t._util_.smartAjax(\"get\"),t.global.get=function(e){return t.global(e)},t.global.set=function(e,n,r){return t.global(e,n,!r)},t.global.getZIndex=function(e,n){var r=t.global.get(\"zIndex\");return e&&(r[e]=r[e]+(n||1)),r[e]},t.global.set(\"zIndex\",{popup:5e4,dialog:1e3},!0),t.i18n=t.i18n||{},t.i18n.cultures=t.i18n.cultures||{},t.i18n.cultures[\"zh-CN\"]=t.object.extend(t.i18n.cultures[\"zh-CN\"]||{},function(){var e=\"%u4E00,%u4E8C,%u4E09,%u56DB,%u4E94,%u516D,%u4E03,%u516B,%u4E5D,%u5341\".split(\",\");return{calendar:{dateFormat:\"yyyy-MM-dd\",titleNames:\"#{yyyy}\"+unescape(\"%u5E74\")+\"&nbsp;#{MM}\"+unescape(\"%u6708\"),monthNamesShort:[1,2,3,4,5,6,7,8,9,10,11,12],monthNames:function(){for(var t=e.length,n=[],r=0;12>r;r++)n.push(unescape(e[r]||e[t-1]+e[r-t]));return n}(),dayNames:function(){var t={mon:0,tue:1,wed:2,thu:3,fri:4,sat:5,sun:\"%u65E5\"};for(var n in t)t[n]=unescape(e[t[n]]||t[n]);return t}()},timeZone:8,whitespace:new RegExp(\"(^[\\\\s\\\\t\\\\xa0\\\\u3000]+)|([\\\\u3000\\\\xa0\\\\s\\\\t]+$)\",\"g\"),number:{group:\",\",groupLength:3,decimal:\".\",positive:\"\",negative:\"-\",_format:function(e,n){return t.i18n.number._format(e,{group:this.group,groupLength:this.groupLength,decimal:this.decimal,symbol:n?this.negative:this.positive})}},currency:{symbol:unescape(\"%uFFE5\")},language:function(){var e={ok:\"%u786E%u5B9A\",cancel:\"%u53D6%u6D88\",signin:\"%u6CE8%u518C\",signup:\"%u767B%u5F55\"};for(var t in e)e[t]=unescape(e[t]);\nreturn e}()}}()),t.i18n.currentLocale=\"zh-CN\",t.i18n.date=t.i18n.date||{getDaysInMonth:function(e,n){var r=[31,28,31,30,31,30,31,31,30,31,30,31];return 1==n&&t.i18n.date.isLeapYear(e)?29:r[n]},isLeapYear:function(e){return!(e%400&&(e%4||!(e%100)))},toLocaleDate:function(e,n,r){return this._basicDate(e,n,r||t.i18n.currentLocale)},_basicDate:function(e,n,r){var i,o,a=t.i18n.cultures[r||t.i18n.currentLocale].timeZone,s=60*a,u=e.getTime();return n?(i=t.i18n.cultures[n].timeZone,o=60*i):(o=-1*e.getTimezoneOffset(),i=o/60),new Date(i!=a?u+6e4*(s-o):u)},format:function(e,n){var r=t.i18n.cultures[n||t.i18n.currentLocale];return t.date.format(t.i18n.date.toLocaleDate(e,\"\",n),r.calendar.dateFormat)}},t.isDate=function(e){return\"date\"==t.type(e)&&\"Invalid Date\"!=e.toString()&&!isNaN(e)},t.isDocument=function(e){return\"Document\"==t.type(e)},t.isElement=function(e){return\"HTMLElement\"==t.type(e)},t.isNumber=function(e){return\"number\"==t.type(e)&&isFinite(e)},t.isObject=function(e){return\"function\"==typeof e||\"object\"==typeof e&&null!=e},t.isPlainObject=function(e){var n,r=Object.prototype.hasOwnProperty;if(\"object\"!=t.type(e))return!1;if(e.constructor&&!r.call(e,\"constructor\")&&!r.call(e.constructor.prototype,\"isPrototypeOf\"))return!1;for(n in e)break;return e.item&&\"number\"==typeof e.length?!1:void 0===n||r.call(e,n)},t.isWindow=function(e){return\"Window\"==t.type(e)},t.json=t.json||{},t.json.parse=function(e){return new Function(\"return (\"+e+\")\")()},t.json.stringify=function(){function e(e){return/[\"\\\\\\x00-\\x1f]/.test(e)&&(e=e.replace(/[\"\\\\\\x00-\\x1f]/g,function(e){var t=o[e];return t?t:(t=e.charCodeAt(),\"\\\\u00\"+Math.floor(t/16).toString(16)+(t%16).toString(16))})),'\"'+e+'\"'}function n(e){var n,r,i,o=[\"[\"],a=e.length;for(r=0;a>r;r++)switch(i=e[r],typeof i){case\"undefined\":case\"function\":case\"unknown\":break;default:n&&o.push(\",\"),o.push(t.json.stringify(i)),n=1}return o.push(\"]\"),o.join(\"\")}function r(e){return 10>e?\"0\"+e:e}function i(e){return'\"'+e.getFullYear()+\"-\"+r(e.getMonth()+1)+\"-\"+r(e.getDate())+\"T\"+r(e.getHours())+\":\"+r(e.getMinutes())+\":\"+r(e.getSeconds())+'\"'}var o={\"\\b\":\"\\\\b\",\"\t\":\"\\\\t\",\"\\n\":\"\\\\n\",\"\\f\":\"\\\\f\",\"\\r\":\"\\\\r\",'\"':'\\\\\"',\"\\\\\":\"\\\\\\\\\"};return function(r){switch(typeof r){case\"undefined\":return\"undefined\";case\"number\":return isFinite(r)?String(r):\"null\";case\"string\":return e(r);case\"boolean\":return String(r);default:if(null===r)return\"null\";if(\"array\"===t.type(r))return n(r);if(\"date\"===t.type(r))return i(r);var o,a,s=[\"{\"],u=t.json.stringify;for(var c in r)if(Object.prototype.hasOwnProperty.call(r,c))switch(a=r[c],typeof a){case\"undefined\":case\"unknown\":case\"function\":break;default:o&&s.push(\",\"),o=1,s.push(u(c)+\":\"+u(a))}return s.push(\"}\"),s.join(\"\")}}}(),t.lang.createClass=t.createClass,t.lang.guid=function(){return t.id()},t.lang.isArray=t.isArray,t.lang.isDate=t.isDate,t.lang.isElement=t.isElement,t.lang.isObject=t.isObject,t.lang.isString=t.isString,t.lang.register=t.base.register,t.lang.toArray=function(e){if(null===e||void 0===e)return[];if(t.lang.isArray(e))return e;if(\"number\"!=typeof e.length||\"string\"==typeof e||t.lang.isFunction(e))return[e];if(e.item){for(var n=e.length,r=new Array(n);n--;)r[n]=e[n];return r}return[].slice.call(e)},t.number.extend({comma:function(e){var t=this;return(!e||1>e)&&(e=3),t=String(t).split(\".\"),t[0]=t[0].replace(new RegExp(\"(\\\\d)(?=(\\\\d{\"+e+\"})+$)\",\"ig\"),\"$1,\"),t.join(\".\")}}),t.number.randomInt=function(e,t){return Math.floor(Math.random()*(t-e+1)+e)},t.object.clone=function(e){var n,r,i=e;if(!e||e instanceof Number||e instanceof String||e instanceof Boolean)return i;if(t.lang.isArray(e)){i=[];var o=0;for(n=0,r=e.length;r>n;n++)i[o++]=t.object.clone(e[n])}else if(t.object.isPlain(e)){i={};for(n in e)e.hasOwnProperty(n)&&(i[n]=t.object.clone(e[n]))}return i},t.object.each=function(e,t){var n,r,i;if(\"function\"==typeof t)for(r in e)if(e.hasOwnProperty(r)&&(i=e[r],n=t.call(e,i,r),n===!1))break;return e},t.object.isEmpty=function(e){var t=!0;if(\"[object Array]\"===Object.prototype.toString.call(e))t=!e.length;else{e=new Object(e);for(var n in e)return!1}return t},t.object.keys=function(e){var t,n=[],r=0;for(t in e)e.hasOwnProperty(t)&&(n[r++]=t);return n},t.object.map=function(e,t){var n={};for(var r in e)e.hasOwnProperty(r)&&(n[r]=t(e[r],r));return n},t.object.merge=function(){function e(e){return t.lang.isObject(e)&&!t.lang.isFunction(e)}function n(n,r,i,o,a){r.hasOwnProperty(i)&&(a&&e(n[i])?t.object.merge(n[i],r[i],{overwrite:o,recursive:a}):!o&&i in n||(n[i]=r[i]))}return function(e,t,r){var i,o=0,a=r||{},s=a.overwrite,u=a.whiteList,c=a.recursive;if(u&&u.length)for(i=u.length;i>o;++o)n(e,t,u[o],s,c);else for(o in t)n(e,t,o,s,c);return e}}(),t.object.values=function(e){var t,n=[],r=0;for(t in e)e.hasOwnProperty(t)&&(n[r++]=e[t]);return n},t.page.getHeight=function(){var e=document,t=e.body,n=e.documentElement,r=\"BackCompat\"==e.compatMode?t:e.documentElement;return Math.max(n.scrollHeight,t.scrollHeight,r.clientHeight)},t.page.getViewHeight=function(){var e=document,n=t.browser.ie||1,r=\"BackCompat\"===e.compatMode&&9>n?e.body:e.documentElement;return r.clientHeight},t.page.getViewWidth=function(){var e=document,t=\"BackCompat\"==e.compatMode?e.body:e.documentElement;return t.clientWidth},t.page.getWidth=function(){var e=document,t=e.body,n=e.documentElement,r=\"BackCompat\"==e.compatMode?t:e.documentElement;return Math.max(n.scrollWidth,t.scrollWidth,r.clientWidth)},t.platform=t.platform||function(){var e=navigator.userAgent,n=function(){};return t.forEach(\"Android iPad iPhone Linux Macintosh Windows X11\".split(\" \"),function(r){var i=r.charAt(0).toUpperCase()+r.toLowerCase().substr(1);t[\"is\"+i]=n[\"is\"+i]=!!~e.indexOf(r)}),n}(),t.plugin=function(e,n,r,i){var o,a=t.isPlainObject(n);return a||(i=r,r=n),\"function\"!=t.type(r)&&(r=void 0),\"function\"!=t.type(i)&&(i=void 0),o=t.createChain(e,r,i),a&&o.extend(n),o},t.post=t.post||t._util_.smartAjax(\"post\"),t.setBack=function(e,t){return e._back_=t,e.getBack=function(){return this._back_},e},t.createChain(\"sio\",function(e){switch(typeof e){case\"string\":return new t.sio.$Sio(e)}},function(e){this.url=e}),t.sio._createScriptTag=function(e,t,n){e.setAttribute(\"type\",\"text/javascript\"),n&&e.setAttribute(\"charset\",n),e.setAttribute(\"src\",t),document.getElementsByTagName(\"head\")[0].appendChild(e)},t.sio._removeScriptTag=function(e){if(e.clearAttributes)e.clearAttributes();else for(var t in e)e.hasOwnProperty(t)&&delete e[t];e&&e.parentNode&&e.parentNode.removeChild(e),e=null},t.sio.extend({callByBrowser:function(e,n){var r,i=this.url,o=document.createElement(\"SCRIPT\"),a=0,s=n||{},u=s.charset,c=e||function(){},l=s.timeOut||0;o.onload=o.onreadystatechange=function(){if(!a){var e=o.readyState;if(\"undefined\"==typeof e||\"loaded\"==e||\"complete\"==e){a=1;try{c(),clearTimeout(r)}finally{o.onload=o.onreadystatechange=null,t.sio._removeScriptTag(o)}}}},l&&(r=setTimeout(function(){o.onload=o.onreadystatechange=null,t.sio._removeScriptTag(o),s.onfailure&&s.onfailure()},l)),t.sio._createScriptTag(o,i,u)}}),t.sio.extend({callByServer:function(e,n){function r(n){return function(){try{n?l.onfailure&&l.onfailure():(e.apply(window,arguments),clearTimeout(o)),window[i]=null,delete window[i]}catch(r){}finally{t.sio._removeScriptTag(u)}}}var i,o,a,s=this.url,u=document.createElement(\"SCRIPT\"),c=\"bd__cbs__\",l=n||{},f=l.charset,d=l.queryField||\"callback\",p=l.timeOut||0,h=new RegExp(\"(\\\\?|&)\"+d+\"=([^&]*)\");t.lang.isFunction(e)?(i=c+Math.floor(2147483648*Math.random()).toString(36),window[i]=r(0)):t.lang.isString(e)?i=e:(a=h.exec(s))&&(i=a[2]),p&&(o=setTimeout(r(1),p)),s=s.replace(h,\"$1\"+d+\"=\"+i),s.search(h)<0&&(s+=(s.indexOf(\"?\")<0?\"?\":\"&\")+d+\"=\"+i),t.sio._createScriptTag(u,s,f)}}),t.sio.extend({log:function(){var e=this.url,t=new Image,n=\"tangram_sio_log_\"+Math.floor(2147483648*Math.random()).toString(36);window[n]=t,t.onload=t.onerror=t.onabort=function(){t.onload=t.onerror=t.onabort=null,window[n]=null,t=null},t.src=e}}),t.string.extend({decodeHTML:function(){var e=this.replace(/&quot;/g,'\"').replace(/&lt;/g,\"<\").replace(/&gt;/g,\">\").replace(/&amp;/g,\"&\");return e.replace(/&#([\\d]+);/g,function(e,t){return String.fromCharCode(parseInt(t,10))})}}),t.string.extend({encodeHTML:function(){return this.replace(/&/g,\"&amp;\").replace(/</g,\"&lt;\").replace(/>/g,\"&gt;\").replace(/\"/g,\"&quot;\").replace(/'/g,\"&#39;\")}}),t.string.extend({format:function(e){var t=this.valueOf(),n=Array.prototype.slice.call(arguments,0),r=Object.prototype.toString;return n.length?(n=1==n.length?null!==e&&/\\[object Array\\]|\\[object Object\\]/.test(r.call(e))?e:n:n,t.replace(/#\\{(.+?)\\}/g,function(e,t){var i=n[t];return\"[object Function]\"==r.call(i)&&(i=i(t)),\"undefined\"==typeof i?\"\":i})):t}}),t.string.extend({getByteLength:function(){return this.replace(/[^\\x00-\\xff]/g,\"ci\").length}}),t.string.extend({stripTags:function(){return(this||\"\").replace(/<[^>]+>/g,\"\")}}),t.string.extend({subByte:function(e,n){if(t.check(\"number(,string)?$\",\"baidu.string.subByte\"),0>e||this.getByteLength()<=e)return this.valueOf();var r=this.substr(0,e).replace(/([^\\x00-\\xff])/g,\"$1 \").substr(0,e).replace(/[^\\x00-\\xff]$/,\"\").replace(/([^\\x00-\\xff]) /g,\"$1\");return r+(n||\"\")}}),t.string.extend({toHalfWidth:function(){return this.replace(/[\\uFF01-\\uFF5E]/g,function(e){return String.fromCharCode(e.charCodeAt(0)-65248)}).replace(/\\u3000/g,\" \")}}),t.string.extend({wbr:function(){return this.replace(/(?:<[^>]+>)|(?:&#?[0-9a-z]{2,6};)|(.{1})/gi,\"$&<wbr>\").replace(/><wbr>/g,\">\")}}),t.swf=t.swf||{},t.swf.version=function(){var e=navigator;if(e.plugins&&e.mimeTypes.length){var t=e.plugins[\"Shockwave Flash\"];if(t&&t.description)return t.description.replace(/([a-zA-Z]|\\s)+/,\"\").replace(/(\\s)+r/,\".\")+\".0\"}else if(window.ActiveXObject&&!window.opera)for(var n=12;n>=2;n--)try{var r=new ActiveXObject(\"ShockwaveFlash.ShockwaveFlash.\"+n);if(r){var i=r.GetVariable(\"$version\");return i.replace(/WIN/g,\"\").replace(/,/g,\".\")}}catch(o){}}(),t.swf.createHTML=function(e){e=e||{};var n,r,i,o,a,s,u=t.swf.version,c=e.ver||\"6.0.0\",l={},f=t.string.encodeHTML;for(o in e)l[o]=e[o];if(e=l,!u)return\"\";for(u=u.split(\".\"),c=c.split(\".\"),i=0;3>i&&(n=parseInt(u[i],10),r=parseInt(c[i],10),!(n>r));i++)if(r>n)return\"\";var d=e.vars,p=[\"classid\",\"codebase\",\"id\",\"width\",\"height\",\"align\"];if(e.align=e.align||\"middle\",e.classid=\"clsid:d27cdb6e-ae6d-11cf-96b8-444553540000\",e.codebase=\"http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0\",e.movie=e.url||\"\",delete e.vars,delete e.url,\"string\"==typeof d)e.flashvars=d;else{var h=[];for(o in d)s=d[o],h.push(o+\"=\"+encodeURIComponent(s));e.flashvars=h.join(\"&\")}var m=[\"<object \"];for(i=0,a=p.length;a>i;i++)s=p[i],m.push(\" \",s,'=\"',f(e[s]),'\"');m.push(\">\");var g={wmode:1,scale:1,quality:1,play:1,loop:1,menu:1,salign:1,bgcolor:1,base:1,allowscriptaccess:1,allownetworking:1,allowfullscreen:1,seamlesstabbing:1,devicefont:1,swliveconnect:1,flashvars:1,movie:1};for(o in e)s=e[o],o=o.toLowerCase(),g[o]&&(s||s===!1||0===s)&&m.push('<param name=\"'+o+'\" value=\"'+f(s)+'\" />');e.src=e.movie,e.name=e.id,delete e.id,delete e.movie,delete e.classid,delete e.codebase,e.type=\"application/x-shockwave-flash\",e.pluginspage=\"http://www.macromedia.com/go/getflashplayer\",m.push(\"<embed\");var y;for(o in e)if(s=e[o],s||s===!1||0===s){if(new RegExp(\"^salign$\",\"i\").test(o)){y=s;continue}m.push(\" \",o,'=\"',f(s),'\"')}return y&&m.push(' salign=\"',f(y),'\"'),m.push(\"></embed></object>\"),m.join(\"\")},t.swf.create=function(e,n){e=e||{};var r=t.swf.createHTML(e)||e.errorMessage||\"\";n&&\"string\"==typeof n&&(n=document.getElementById(n)),t.dom.insertHTML(n||document.body,\"beforeEnd\",r)},t.swf.getMovie=function(e){var n,r=document[e];return 9==t.browser.ie?r&&r.length?1==(n=t.array.remove(t.lang.toArray(r),function(e){return\"embed\"!=e.tagName.toLowerCase()})).length?n[0]:n:r:r||window[e]},t.swf.Proxy=function(e,n,r){var i,o=this,a=this._flash=t.swf.getMovie(e);return n?(i=setInterval(function(){try{a[n]&&(o._initialized=!0,clearInterval(i),r&&r())}catch(e){}},100),void 0):this},t.swf.Proxy.prototype.getFlash=function(){return this._flash},t.swf.Proxy.prototype.isReady=function(){return!!this._initialized},t.swf.Proxy.prototype.call=function(e){try{var t=this.getFlash(),n=Array.prototype.slice.call(arguments);n.shift(),t[e]&&t[e].apply(t,n)}catch(r){}},function(e){var n=document.createElement(\"div\");e.inlineBlockNeedsLayout=!1,e.shrinkWrapBlocks=!1,t(document).ready(function(){var t=document.body,r=document.createElement(\"div\");r.style.cssText=\"border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px\",t.appendChild(r).appendChild(n),\"undefined\"!=typeof n.style.zoom&&(n.style.cssText=\"padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;width:1px;padding:1px;display:inline;zoom:1\",e.inlineBlockNeedsLayout=3===n.offsetWidth,n.style.display=\"block\",n.innerHTML=\"<div></div>\",n.firstChild.style.width=\"5px\",e.shrinkWrapBlocks=3!==n.offsetWidth),t.removeChild(r),r=n=t=null})}(t._util_.support),t}(),require,define;!function(e){function t(e,t){if(!(e in s)){s[e]=!0;var n=document.createElement(\"script\");if(t){var i=setTimeout(t,require.timeout);n.onerror=function(){clearTimeout(i),t()},n.onreadystatechange=function(){\"complete\"==this.readyState&&clearTimeout(i)}}return n.type=\"text/javascript\",n.src=e,r.appendChild(n),n}}function n(e,n,r){var o=i[e]||(i[e]=[]);o.push(n);var a,s=u[e]||{},l=s.pkg;a=l?c[l].url:s.url||e,t(a,r&&function(){r(e)})}var r=document.getElementsByTagName(\"head\")[0],i={},o={},a={},s={},u={},c={};define=function(e,t){o[e]=t;var n=i[e];if(n){for(var r=n.length-1;r>=0;--r)n[r]();delete i[e]}},require=function(e){e=require.alias(e);var t=a[e];if(t)return t.exports;var n=o[e];if(!n)throw Error(\"Cannot find module `\"+e+\"`\");t=a[e]={exports:{}};var r=\"function\"==typeof n?n.apply(t,[require,t.exports,t]):n;return r&&(t.exports=r),t.exports},require.async=function(t,r,i){function a(e){for(var t=e.length-1;t>=0;--t){var r=e[t];if(!(r in o||r in l)){l[r]=!0,f++,n(r,s,i);var c=u[r];c&&\"deps\"in c&&a(c.deps)}}}function s(){if(0==f--){var n,i,o=[];for(n=0,i=t.length;i>n;++n)o[n]=require(t[n]);r&&r.apply(e,o)}}\"string\"==typeof t&&(t=[t]);for(var c=t.length-1;c>=0;--c)t[c]=require.alias(t[c]);var l={},f=0;a(t),s()},require.resourceMap=function(e){var t,n;n=e.res;for(t in n)n.hasOwnProperty(t)&&(u[t]=n[t]);n=e.pkg;for(t in n)n.hasOwnProperty(t)&&(c[t]=n[t])},require.loadJs=function(e){t(e)},require.loadCss=function(e){if(e.content){var t=document.createElement(\"style\");t.type=\"text/css\",t.styleSheet?t.styleSheet.cssText=e.content:t.innerHTML=e.content,r.appendChild(t)}else if(e.url){var n=document.createElement(\"link\");n.href=e.url,n.rel=\"stylesheet\",n.type=\"text/css\",r.appendChild(n)}},require.alias=function(e){return e},require.timeout=5e3,define.amd={jQuery:!0,version:\"1.0.0\"}}(this);var connectConfig={display:\"{{$display|escape:javascript}}\",is_device:\"{{$is_device|escape:javascript}}\",channel:\"{{$smarty.get.channel|escape:javascript}}\",origin:\"{{$smarty.get.origin|escape:javascript}}\",is_https:\"{{$is_https|escape:javascript}}\"};"
  },
  {
    "path": "open-oauth-center/open-oauth-server/src/main/view/static/js/login_4765ca5.js",
    "content": "passport._define(\"login.js\",function(){function _(e){alert(\"undefined:\"+e)}var passport=passport||window.passport||{},baidu=passport.tangramInst||baidu||window.baidu;!function(e){e.apiDomain={staticDomain:window.location?\"http:\"==window.location.protocol.toLowerCase()?\"http://passport.bdimg.com\":\"https://passport.baidu.com\":\"http:\"==document.location.protocol.toLowerCase()?\"http://passport.bdimg.com\":\"https://passport.baidu.com\"}}(passport);var magic=null;if(\"function\"!=typeof magic)var magic=function(){};magic._baiduInstName=magic._baiduInstName||\"bdInst_\"+(new Date).getTime();var baiduInstance=baiduInstance||baidu.baiduInstance||window.baiduInstance;window[magic._baiduInstName]=window[magic._baiduInstName]||baiduInstance,magic.resourcePath=\"\",magic.skinName=\"default\",magic.version=\"1.0.0.0\",/msie 6/i.test(navigator.userAgent)&&document.execCommand(\"BackgroundImageCache\",!1,!0),baidu.form=baidu.form||{},baidu.url=baidu.url||{},baidu.url.escapeSymbol=baidu.url.escapeSymbol||function(e){return String(e).replace(/[#%&+=\\/\\\\\\ \\　\\f\\r\\n\\t]/g,function(e){return\"%\"+(256+e.charCodeAt()).toString(16).substring(1).toUpperCase()})},baidu.form.json=baidu.form.json||function(e,t){function n(e,t){var n=p[e];n?(n.push||(p[e]=[n]),p[e].push(t)):p[e]=t}for(var i,s,o,r,a,c,l,d,u=e.elements,t=t||function(e){return e},p={},g=0,h=u.length;h>g;g++)if(i=u[g],o=i.name,!i.disabled&&o)switch(s=i.type,r=baidu.url.escapeSymbol(i.value),s){case\"radio\":case\"checkbox\":if(!i.checked)break;case\"textarea\":case\"text\":case\"password\":case\"hidden\":case\"file\":case\"select-one\":n(o,t(r,o));break;case\"select-multiple\":for(a=i.options,l=a.length,c=0;l>c;c++)d=a[c],d.selected&&n(o,t(d.value,o))}return p},magic.Base=function(){baidu.lang.Class.call(this),this._ids={},this._eid=this.guid+\"__\"},baidu.lang.inherits(magic.Base,baidu.lang.Class,\"magic.Base\").extend({getElement:function(e){return document.getElementById(this.$getId(e))},getElements:function(){var e={},t=this._ids;for(var n in t)e[n]=this.getElement(n);return e},$getId:function(e){return e=baidu.lang.isString(e)?e:\"\",this._ids[e]||(this._ids[e]=this._eid+e)},$mappingDom:function(e,t){return baidu.lang.isString(t)?this._ids[e]=t:t&&t.nodeType&&(t.id?this._ids[e]=t.id:t.id=this.$getId(e)),this},$hide:function(e){return(\"string\"==(typeof e).toLowerCase()||\"\"===e)&&(e=this.getElement(e)),e&&e.style&&(e.style.display=\"none\",e.style.visibility=\"hidden\"),this},$show:function(e){return(\"string\"==(typeof e).toLowerCase()||\"\"===e)&&(e=this.getElement(e)),e&&e.style&&(e.style.display=\"block\",e.style.visibility=\"visible\",e.style.opacity=\"1\"),this},$dispose:function(){this.fire(\"ondispose\")&&baidu.lang.Class.prototype.dispose.call(this)}}),magic.control=magic.control||{},function(){function e(e,t){var i,s=e.getAttribute(t),o=!1;if(s&&(i=s.match(n[0]))){o={};for(var r,a=0;a<i.length;a++)r=i[a].match(n[1]),!isNaN(r[2])&&(r[2]=+r[2]),n[2].test(r[2])&&(r[2]=r[2].replace(n[3],\"$2\")),n[4].test(r[2])&&(r[2]=n[5].test(r[2])),o[r[1]]=r[2]}return o}function t(t,n){var i=e(t,\"tang-event\");if(i)for(var s in i){var o=i[s].substr(1);o.indexOf(\"(\")<0&&(o+=\"()\"),baidu.dom(t).on(s,new Function(magic._baiduInstName+\"('\"+n+\"') && \"+magic._baiduInstName+\"('\"+n+\"')\"+o))}}magic.setup=magic.setup||function(n,i,s){var o=e(n,\"tang-param\")||{};for(var r in s)o[r]=s[r];var a=new i(o);a.$mappingDom(\"\",n),t(n,a.guid);for(var c=n.getElementsByTagName(\"*\"),r=c.length-1;r>=0;r--)t(c[r],a.guid);return a};var n=[/\\b[\\w\\$\\-]+\\s*:\\s*[^;]+/g,/([\\w\\$\\-]+)\\s*:\\s*([^;]+)\\s*/,/\\'|\\\"/,/^\\s*(\\'|\\\")([^\\1]*)\\1\\s*/,/^(true|false)\\s*$/i,/\\btrue\\b/i]}(),passport=passport||{},passport.lib=passport.lib||{},passport.lib.RSAExport={},function(e){function t(e,t,n){null!=e&&(\"number\"==typeof e?this.fromNumber(e,t,n):null==t&&\"string\"!=typeof e?this.fromString(e,256):this.fromString(e,t))}function n(){return new t(null)}function i(e,t,n,i,s,o){for(;--o>=0;){var r=t*this[e++]+n[i]+s;s=Math.floor(r/67108864),n[i++]=67108863&r}return s}function s(e,t,n,i,s,o){for(var r=32767&t,a=t>>15;--o>=0;){var c=32767&this[e],l=this[e++]>>15,d=a*c+l*r;c=r*c+((32767&d)<<15)+n[i]+(1073741823&s),s=(c>>>30)+(d>>>15)+a*l+(s>>>30),n[i++]=1073741823&c}return s}function o(e,t,n,i,s,o){for(var r=16383&t,a=t>>14;--o>=0;){var c=16383&this[e],l=this[e++]>>14,d=a*c+l*r;c=r*c+((16383&d)<<14)+n[i]+s,s=(c>>28)+(d>>14)+a*l,n[i++]=268435455&c}return s}function r(e){return Ln.charAt(e)}function a(e,t){var n=kn[e.charCodeAt(t)];return null==n?-1:n}function c(e){for(var t=this.t-1;t>=0;--t)e[t]=this[t];e.t=this.t,e.s=this.s}function l(e){this.t=1,this.s=0>e?-1:0,e>0?this[0]=e:-1>e?this[0]=e+DV:this.t=0}function d(e){var t=n();return t.fromInt(e),t}function u(e,n){var i;if(16==n)i=4;else if(8==n)i=3;else if(256==n)i=8;else if(2==n)i=1;else if(32==n)i=5;else{if(4!=n)return void this.fromRadix(e,n);i=2}this.t=0,this.s=0;for(var s=e.length,o=!1,r=0;--s>=0;){var c=8==i?255&e[s]:a(e,s);0>c?\"-\"==e.charAt(s)&&(o=!0):(o=!1,0==r?this[this.t++]=c:r+i>this.DB?(this[this.t-1]|=(c&(1<<this.DB-r)-1)<<r,this[this.t++]=c>>this.DB-r):this[this.t-1]|=c<<r,r+=i,r>=this.DB&&(r-=this.DB))}8==i&&0!=(128&e[0])&&(this.s=-1,r>0&&(this[this.t-1]|=(1<<this.DB-r)-1<<r)),this.clamp(),o&&t.ZERO.subTo(this,this)}function p(){for(var e=this.s&this.DM;this.t>0&&this[this.t-1]==e;)--this.t}function g(e){if(this.s<0)return\"-\"+this.negate().toString(e);var t;if(16==e)t=4;else if(8==e)t=3;else if(2==e)t=1;else if(32==e)t=5;else{if(4!=e)return this.toRadix(e);t=2}var n,i=(1<<t)-1,s=!1,o=\"\",a=this.t,c=this.DB-a*this.DB%t;if(a-->0)for(c<this.DB&&(n=this[a]>>c)>0&&(s=!0,o=r(n));a>=0;)t>c?(n=(this[a]&(1<<c)-1)<<t-c,n|=this[--a]>>(c+=this.DB-t)):(n=this[a]>>(c-=t)&i,0>=c&&(c+=this.DB,--a)),n>0&&(s=!0),s&&(o+=r(n));return s?o:\"0\"}function h(){var e=n();return t.ZERO.subTo(this,e),e}function f(){return this.s<0?this.negate():this}function m(e){var t=this.s-e.s;if(0!=t)return t;var n=this.t;if(t=n-e.t,0!=t)return this.s<0?-t:t;for(;--n>=0;)if(0!=(t=this[n]-e[n]))return t;return 0}function b(e){var t,n=1;return 0!=(t=e>>>16)&&(e=t,n+=16),0!=(t=e>>8)&&(e=t,n+=8),0!=(t=e>>4)&&(e=t,n+=4),0!=(t=e>>2)&&(e=t,n+=2),0!=(t=e>>1)&&(e=t,n+=1),n}function y(){return this.t<=0?0:this.DB*(this.t-1)+b(this[this.t-1]^this.s&this.DM)}function _(e,t){var n;for(n=this.t-1;n>=0;--n)t[n+e]=this[n];for(n=e-1;n>=0;--n)t[n]=0;t.t=this.t+e,t.s=this.s}function E(e,t){for(var n=e;n<this.t;++n)t[n-e]=this[n];t.t=Math.max(this.t-e,0),t.s=this.s}function C(e,t){var n,i=e%this.DB,s=this.DB-i,o=(1<<s)-1,r=Math.floor(e/this.DB),a=this.s<<i&this.DM;for(n=this.t-1;n>=0;--n)t[n+r+1]=this[n]>>s|a,a=(this[n]&o)<<i;for(n=r-1;n>=0;--n)t[n]=0;t[r]=a,t.t=this.t+r+1,t.s=this.s,t.clamp()}function w(e,t){t.s=this.s;var n=Math.floor(e/this.DB);if(n>=this.t)return void(t.t=0);var i=e%this.DB,s=this.DB-i,o=(1<<i)-1;t[0]=this[n]>>i;for(var r=n+1;r<this.t;++r)t[r-n-1]|=(this[r]&o)<<s,t[r-n]=this[r]>>i;i>0&&(t[this.t-n-1]|=(this.s&o)<<s),t.t=this.t-n,t.clamp()}function S(e,t){for(var n=0,i=0,s=Math.min(e.t,this.t);s>n;)i+=this[n]-e[n],t[n++]=i&this.DM,i>>=this.DB;if(e.t<this.t){for(i-=e.s;n<this.t;)i+=this[n],t[n++]=i&this.DM,i>>=this.DB;i+=this.s}else{for(i+=this.s;n<e.t;)i-=e[n],t[n++]=i&this.DM,i>>=this.DB;i-=e.s}t.s=0>i?-1:0,-1>i?t[n++]=this.DV+i:i>0&&(t[n++]=i),t.t=n,t.clamp()}function T(e,n){var i=this.abs(),s=e.abs(),o=i.t;for(n.t=o+s.t;--o>=0;)n[o]=0;for(o=0;o<s.t;++o)n[o+i.t]=i.am(0,s[o],n,o,0,i.t);n.s=0,n.clamp(),this.s!=e.s&&t.ZERO.subTo(n,n)}function I(e){for(var t=this.abs(),n=e.t=2*t.t;--n>=0;)e[n]=0;for(n=0;n<t.t-1;++n){var i=t.am(n,t[n],e,2*n,0,1);(e[n+t.t]+=t.am(n+1,2*t[n],e,2*n+1,i,t.t-n-1))>=t.DV&&(e[n+t.t]-=t.DV,e[n+t.t+1]=1)}e.t>0&&(e[e.t-1]+=t.am(n,t[n],e,2*n,0,1)),e.s=0,e.clamp()}function D(e,i,s){var o=e.abs();if(!(o.t<=0)){var r=this.abs();if(r.t<o.t)return null!=i&&i.fromInt(0),void(null!=s&&this.copyTo(s));null==s&&(s=n());var a=n(),c=this.s,l=e.s,d=this.DB-b(o[o.t-1]);d>0?(o.lShiftTo(d,a),r.lShiftTo(d,s)):(o.copyTo(a),r.copyTo(s));var u=a.t,p=a[u-1];if(0!=p){var g=p*(1<<this.F1)+(u>1?a[u-2]>>this.F2:0),h=this.FV/g,f=(1<<this.F1)/g,m=1<<this.F2,v=s.t,y=v-u,_=null==i?n():i;for(a.dlShiftTo(y,_),s.compareTo(_)>=0&&(s[s.t++]=1,s.subTo(_,s)),t.ONE.dlShiftTo(u,_),_.subTo(a,a);a.t<u;)a[a.t++]=0;for(;--y>=0;){var E=s[--v]==p?this.DM:Math.floor(s[v]*h+(s[v-1]+m)*f);if((s[v]+=a.am(0,E,s,y,0,u))<E)for(a.dlShiftTo(y,_),s.subTo(_,s);s[v]<--E;)s.subTo(_,s)}null!=i&&(s.drShiftTo(u,i),c!=l&&t.ZERO.subTo(i,i)),s.t=u,s.clamp(),d>0&&s.rShiftTo(d,s),0>c&&t.ZERO.subTo(s,s)}}}function R(e){var i=n();return this.abs().divRemTo(e,null,i),this.s<0&&i.compareTo(t.ZERO)>0&&e.subTo(i,i),i}function x(e){this.m=e}function L(e){return e.s<0||e.compareTo(this.m)>=0?e.mod(this.m):e}function k(e){return e}function P(e){e.divRemTo(this.m,null,e)}function A(e,t,n){e.multiplyTo(t,n),this.reduce(n)}function M(e,t){e.squareTo(t),this.reduce(t)}function B(){if(this.t<1)return 0;var e=this[0];if(0==(1&e))return 0;var t=3&e;return t=t*(2-(15&e)*t)&15,t=t*(2-(255&e)*t)&255,t=t*(2-((65535&e)*t&65535))&65535,t=t*(2-e*t%this.DV)%this.DV,t>0?this.DV-t:-t}function V(e){this.m=e,this.mp=e.invDigit(),this.mpl=32767&this.mp,this.mph=this.mp>>15,this.um=(1<<e.DB-15)-1,this.mt2=2*e.t}function $(e){var i=n();return e.abs().dlShiftTo(this.m.t,i),i.divRemTo(this.m,null,i),e.s<0&&i.compareTo(t.ZERO)>0&&this.m.subTo(i,i),i}function O(e){var t=n();return e.copyTo(t),this.reduce(t),t}function N(e){for(;e.t<=this.mt2;)e[e.t++]=0;for(var t=0;t<this.m.t;++t){var n=32767&e[t],i=n*this.mpl+((n*this.mph+(e[t]>>15)*this.mpl&this.um)<<15)&e.DM;for(n=t+this.m.t,e[n]+=this.m.am(0,i,e,t,0,this.m.t);e[n]>=e.DV;)e[n]-=e.DV,e[++n]++}e.clamp(),e.drShiftTo(this.m.t,e),e.compareTo(this.m)>=0&&e.subTo(this.m,e)}function U(e,t){e.squareTo(t),this.reduce(t)}function q(e,t,n){e.multiplyTo(t,n),this.reduce(n)}function F(){return 0==(this.t>0?1&this[0]:this.s)}function W(e,i){if(e>4294967295||1>e)return t.ONE;var s=n(),o=n(),r=i.convert(this),a=b(e)-1;for(r.copyTo(s);--a>=0;)if(i.sqrTo(s,o),(e&1<<a)>0)i.mulTo(o,r,s);else{var c=s;s=o,o=c}return i.revert(s)}function H(e,t){var n;return n=256>e||t.isEven()?new x(t):new V(t),this.exp(e,n)}function K(){var e=n();return this.copyTo(e),e}function j(){if(this.s<0){if(1==this.t)return this[0]-this.DV;if(0==this.t)return-1}else{if(1==this.t)return this[0];if(0==this.t)return 0}return(this[1]&(1<<32-this.DB)-1)<<this.DB|this[0]}function J(){return 0==this.t?this.s:this[0]<<24>>24}function G(){return 0==this.t?this.s:this[0]<<16>>16}function Q(e){return Math.floor(Math.LN2*this.DB/Math.log(e))}function z(){return this.s<0?-1:this.t<=0||1==this.t&&this[0]<=0?0:1}function Z(e){if(null==e&&(e=10),0==this.signum()||2>e||e>36)return\"0\";var t=this.chunkSize(e),i=Math.pow(e,t),s=d(i),o=n(),r=n(),a=\"\";for(this.divRemTo(s,o,r);o.signum()>0;)a=(i+r.intValue()).toString(e).substr(1)+a,o.divRemTo(s,o,r);return r.intValue().toString(e)+a}function Y(e,n){this.fromInt(0),null==n&&(n=10);for(var i=this.chunkSize(n),s=Math.pow(n,i),o=!1,r=0,c=0,l=0;l<e.length;++l){var d=a(e,l);0>d?\"-\"==e.charAt(l)&&0==this.signum()&&(o=!0):(c=n*c+d,++r>=i&&(this.dMultiply(s),this.dAddOffset(c,0),r=0,c=0))}r>0&&(this.dMultiply(Math.pow(n,r)),this.dAddOffset(c,0)),o&&t.ZERO.subTo(this,this)}function X(e,n,i){if(\"number\"==typeof n)if(2>e)this.fromInt(1);else for(this.fromNumber(e,i),this.testBit(e-1)||this.bitwiseTo(t.ONE.shiftLeft(e-1),at,this),this.isEven()&&this.dAddOffset(1,0);!this.isProbablePrime(n);)this.dAddOffset(2,0),this.bitLength()>e&&this.subTo(t.ONE.shiftLeft(e-1),this);else{var s=new Array,o=7&e;s.length=(e>>3)+1,n.nextBytes(s),o>0?s[0]&=(1<<o)-1:s[0]=0,this.fromString(s,256)}}function et(){var e=this.t,t=new Array;t[0]=this.s;var n,i=this.DB-e*this.DB%8,s=0;if(e-->0)for(i<this.DB&&(n=this[e]>>i)!=(this.s&this.DM)>>i&&(t[s++]=n|this.s<<this.DB-i);e>=0;)8>i?(n=(this[e]&(1<<i)-1)<<8-i,n|=this[--e]>>(i+=this.DB-8)):(n=this[e]>>(i-=8)&255,0>=i&&(i+=this.DB,--e)),0!=(128&n)&&(n|=-256),0==s&&(128&this.s)!=(128&n)&&++s,(s>0||n!=this.s)&&(t[s++]=n);return t}function tt(e){return 0==this.compareTo(e)}function nt(e){return this.compareTo(e)<0?this:e}function it(e){return this.compareTo(e)>0?this:e}function st(e,t,n){var i,s,o=Math.min(e.t,this.t);for(i=0;o>i;++i)n[i]=t(this[i],e[i]);if(e.t<this.t){for(s=e.s&this.DM,i=o;i<this.t;++i)n[i]=t(this[i],s);n.t=this.t}else{for(s=this.s&this.DM,i=o;i<e.t;++i)n[i]=t(s,e[i]);n.t=e.t}n.s=t(this.s,e.s),n.clamp()}function ot(e,t){return e&t}function rt(e){var t=n();return this.bitwiseTo(e,ot,t),t}function at(e,t){return e|t}function ct(e){var t=n();return this.bitwiseTo(e,at,t),t}function lt(e,t){return e^t}function dt(e){var t=n();return this.bitwiseTo(e,lt,t),t}function ut(e,t){return e&~t}function pt(e){var t=n();return this.bitwiseTo(e,ut,t),t}function gt(){for(var e=n(),t=0;t<this.t;++t)e[t]=this.DM&~this[t];return e.t=this.t,e.s=~this.s,e}function ht(e){var t=n();return 0>e?this.rShiftTo(-e,t):this.lShiftTo(e,t),t}function ft(e){var t=n();return 0>e?this.lShiftTo(-e,t):this.rShiftTo(e,t),t}function mt(e){if(0==e)return-1;var t=0;return 0==(65535&e)&&(e>>=16,t+=16),0==(255&e)&&(e>>=8,t+=8),0==(15&e)&&(e>>=4,t+=4),0==(3&e)&&(e>>=2,t+=2),0==(1&e)&&++t,t}function vt(){for(var e=0;e<this.t;++e)if(0!=this[e])return e*this.DB+mt(this[e]);return this.s<0?this.t*this.DB:-1}function bt(e){for(var t=0;0!=e;)e&=e-1,++t;return t}function yt(){for(var e=0,t=this.s&this.DM,n=0;n<this.t;++n)e+=bt(this[n]^t);return e}function _t(e){var t=Math.floor(e/this.DB);return t>=this.t?0!=this.s:0!=(this[t]&1<<e%this.DB)}function Et(e,n){var i=t.ONE.shiftLeft(e);return this.bitwiseTo(i,n,i),i}function Ct(e){return this.changeBit(e,at)}function wt(e){return this.changeBit(e,ut)}function St(e){return this.changeBit(e,lt)}function Tt(e,t){for(var n=0,i=0,s=Math.min(e.t,this.t);s>n;)i+=this[n]+e[n],t[n++]=i&this.DM,i>>=this.DB;if(e.t<this.t){for(i+=e.s;n<this.t;)i+=this[n],t[n++]=i&this.DM,i>>=this.DB;i+=this.s}else{for(i+=this.s;n<e.t;)i+=e[n],t[n++]=i&this.DM,i>>=this.DB;i+=e.s}t.s=0>i?-1:0,i>0?t[n++]=i:-1>i&&(t[n++]=this.DV+i),t.t=n,t.clamp()}function It(e){var t=n();return this.addTo(e,t),t}function Dt(e){var t=n();return this.subTo(e,t),t}function Rt(e){var t=n();return this.multiplyTo(e,t),t}function xt(){var e=n();return this.squareTo(e),e}function Lt(e){var t=n();return this.divRemTo(e,t,null),t}function kt(e){var t=n();return this.divRemTo(e,null,t),t}function Pt(e){var t=n(),i=n();return this.divRemTo(e,t,i),new Array(t,i)}function At(e){this[this.t]=this.am(0,e-1,this,0,0,this.t),++this.t,this.clamp()}function Mt(e,t){if(0!=e){for(;this.t<=t;)this[this.t++]=0;for(this[t]+=e;this[t]>=this.DV;)this[t]-=this.DV,++t>=this.t&&(this[this.t++]=0),++this[t]}}function Bt(){}function Vt(e){return e}function $t(e,t,n){e.multiplyTo(t,n)}function Ot(e,t){e.squareTo(t)}function Nt(e){return this.exp(e,new Bt)}function Ut(e,t,n){var i=Math.min(this.t+e.t,t);for(n.s=0,n.t=i;i>0;)n[--i]=0;var s;for(s=n.t-this.t;s>i;++i)n[i+this.t]=this.am(0,e[i],n,i,0,this.t);for(s=Math.min(e.t,t);s>i;++i)this.am(0,e[i],n,i,0,t-i);n.clamp()}function qt(e,t,n){--t;var i=n.t=this.t+e.t-t;for(n.s=0;--i>=0;)n[i]=0;for(i=Math.max(t-this.t,0);i<e.t;++i)n[this.t+i-t]=this.am(t-i,e[i],n,0,0,this.t+i-t);n.clamp(),n.drShiftTo(1,n)}function Ft(e){this.r2=n(),this.q3=n(),t.ONE.dlShiftTo(2*e.t,this.r2),this.mu=this.r2.divide(e),this.m=e}function Wt(e){if(e.s<0||e.t>2*this.m.t)return e.mod(this.m);if(e.compareTo(this.m)<0)return e;var t=n();return e.copyTo(t),this.reduce(t),t}function Ht(e){return e}function Kt(e){for(e.drShiftTo(this.m.t-1,this.r2),e.t>this.m.t+1&&(e.t=this.m.t+1,e.clamp()),this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3),this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);e.compareTo(this.r2)<0;)e.dAddOffset(1,this.m.t+1);for(e.subTo(this.r2,e);e.compareTo(this.m)>=0;)e.subTo(this.m,e)}function jt(e,t){e.squareTo(t),this.reduce(t)}function Jt(e,t,n){e.multiplyTo(t,n),this.reduce(n)}function Gt(e,t){var i,s,o=e.bitLength(),r=d(1);if(0>=o)return r;i=18>o?1:48>o?3:144>o?4:768>o?5:6,s=8>o?new x(t):t.isEven()?new Ft(t):new V(t);var a=new Array,c=3,l=i-1,u=(1<<i)-1;if(a[1]=s.convert(this),i>1){var p=n();for(s.sqrTo(a[1],p);u>=c;)a[c]=n(),s.mulTo(p,a[c-2],a[c]),c+=2}var g,h,f=e.t-1,m=!0,v=n();for(o=b(e[f])-1;f>=0;){for(o>=l?g=e[f]>>o-l&u:(g=(e[f]&(1<<o+1)-1)<<l-o,f>0&&(g|=e[f-1]>>this.DB+o-l)),c=i;0==(1&g);)g>>=1,--c;if((o-=c)<0&&(o+=this.DB,--f),m)a[g].copyTo(r),m=!1;else{for(;c>1;)s.sqrTo(r,v),s.sqrTo(v,r),c-=2;c>0?s.sqrTo(r,v):(h=r,r=v,v=h),s.mulTo(v,a[g],r)}for(;f>=0&&0==(e[f]&1<<o);)s.sqrTo(r,v),h=r,r=v,v=h,--o<0&&(o=this.DB-1,--f)}return s.revert(r)}function Qt(e){var t=this.s<0?this.negate():this.clone(),n=e.s<0?e.negate():e.clone();if(t.compareTo(n)<0){var i=t;t=n,n=i}var s=t.getLowestSetBit(),o=n.getLowestSetBit();if(0>o)return t;for(o>s&&(o=s),o>0&&(t.rShiftTo(o,t),n.rShiftTo(o,n));t.signum()>0;)(s=t.getLowestSetBit())>0&&t.rShiftTo(s,t),(s=n.getLowestSetBit())>0&&n.rShiftTo(s,n),t.compareTo(n)>=0?(t.subTo(n,t),t.rShiftTo(1,t)):(n.subTo(t,n),n.rShiftTo(1,n));return o>0&&n.lShiftTo(o,n),n}function zt(e){if(0>=e)return 0;var t=this.DV%e,n=this.s<0?e-1:0;if(this.t>0)if(0==t)n=this[0]%e;else for(var i=this.t-1;i>=0;--i)n=(t*n+this[i])%e;return n}function Zt(e){var n=e.isEven();if(this.isEven()&&n||0==e.signum())return t.ZERO;for(var i=e.clone(),s=this.clone(),o=d(1),r=d(0),a=d(0),c=d(1);0!=i.signum();){for(;i.isEven();)i.rShiftTo(1,i),n?(o.isEven()&&r.isEven()||(o.addTo(this,o),r.subTo(e,r)),o.rShiftTo(1,o)):r.isEven()||r.subTo(e,r),r.rShiftTo(1,r);for(;s.isEven();)s.rShiftTo(1,s),n?(a.isEven()&&c.isEven()||(a.addTo(this,a),c.subTo(e,c)),a.rShiftTo(1,a)):c.isEven()||c.subTo(e,c),c.rShiftTo(1,c);i.compareTo(s)>=0?(i.subTo(s,i),n&&o.subTo(a,o),r.subTo(c,r)):(s.subTo(i,s),n&&a.subTo(o,a),c.subTo(r,c))}return 0!=s.compareTo(t.ONE)?t.ZERO:c.compareTo(e)>=0?c.subtract(e):c.signum()<0?(c.addTo(e,c),c.signum()<0?c.add(e):c):c}function Yt(e){var t,n=this.abs();if(1==n.t&&n[0]<=Pn[Pn.length-1]){for(t=0;t<Pn.length;++t)if(n[0]==Pn[t])return!0;return!1}if(n.isEven())return!1;for(t=1;t<Pn.length;){for(var i=Pn[t],s=t+1;s<Pn.length&&An>i;)i*=Pn[s++];for(i=n.modInt(i);s>t;)if(i%Pn[t++]==0)return!1}return n.millerRabin(e)}function Xt(e){var i=this.subtract(t.ONE),s=i.getLowestSetBit();if(0>=s)return!1;var o=i.shiftRight(s);e=e+1>>1,e>Pn.length&&(e=Pn.length);for(var r=n(),a=0;e>a;++a){r.fromInt(Pn[Math.floor(Math.random()*Pn.length)]);var c=r.modPow(o,this);if(0!=c.compareTo(t.ONE)&&0!=c.compareTo(i)){for(var l=1;l++<s&&0!=c.compareTo(i);)if(c=c.modPowInt(2,this),0==c.compareTo(t.ONE))return!1;if(0!=c.compareTo(i))return!1}}return!0}function en(){this.i=0,this.j=0,this.S=new Array}function tn(e){var t,n,i;for(t=0;256>t;++t)this.S[t]=t;for(n=0,t=0;256>t;++t)n=n+this.S[t]+e[t%e.length]&255,i=this.S[t],this.S[t]=this.S[n],this.S[n]=i;this.i=0,this.j=0}function nn(){var e;return this.i=this.i+1&255,this.j=this.j+this.S[this.i]&255,e=this.S[this.i],this.S[this.i]=this.S[this.j],this.S[this.j]=e,this.S[e+this.S[this.i]&255]}function sn(){return new en}function on(e){Bn[Vn++]^=255&e,Bn[Vn++]^=e>>8&255,Bn[Vn++]^=e>>16&255,Bn[Vn++]^=e>>24&255,Vn>=$n&&(Vn-=$n)}function rn(){on((new Date).getTime())}function an(){if(null==Mn){for(rn(),Mn=sn(),Mn.init(Bn),Vn=0;Vn<Bn.length;++Vn)Bn[Vn]=0;Vn=0}return Mn.next()}function cn(e){var t;for(t=0;t<e.length;++t)e[t]=an()}function ln(){}function dn(e,n){return new t(e,n)}function un(e,n){if(n<e.length+11)return console.error(\"Message too long for RSA\"),null;for(var i=new Array,s=e.length-1;s>=0&&n>0;){var o=e.charCodeAt(s--);128>o?i[--n]=o:o>127&&2048>o?(i[--n]=63&o|128,i[--n]=o>>6|192):(i[--n]=63&o|128,i[--n]=o>>6&63|128,i[--n]=o>>12|224)}i[--n]=0;for(var r=new ln,a=new Array;n>2;){for(a[0]=0;0==a[0];)r.nextBytes(a);i[--n]=a[0]}return i[--n]=2,i[--n]=0,new t(i)}function pn(){this.n=null,this.e=0,this.d=null,this.p=null,this.q=null,this.dmp1=null,this.dmq1=null,this.coeff=null}function gn(e,t){null!=e&&null!=t&&e.length>0&&t.length>0?(this.n=dn(e,16),this.e=parseInt(t,16)):console.error(\"Invalid RSA public key\")}function hn(e){return e.modPowInt(this.e,this.n)}function fn(e){var t=un(e,this.n.bitLength()+7>>3);if(null==t)return null;var n=this.doPublic(t);if(null==n)return null;var i=n.toString(16);return 0==(1&i.length)?i:\"0\"+i}function mn(e,t){for(var n=e.toByteArray(),i=0;i<n.length&&0==n[i];)++i;if(n.length-i!=t-1||2!=n[i])return null;for(++i;0!=n[i];)if(++i>=n.length)return null;for(var s=\"\";++i<n.length;){var o=255&n[i];128>o?s+=String.fromCharCode(o):o>191&&224>o?(s+=String.fromCharCode((31&o)<<6|63&n[i+1]),++i):(s+=String.fromCharCode((15&o)<<12|(63&n[i+1])<<6|63&n[i+2]),i+=2)}return s}function vn(e,t,n){null!=e&&null!=t&&e.length>0&&t.length>0?(this.n=dn(e,16),this.e=parseInt(t,16),this.d=dn(n,16)):console.error(\"Invalid RSA private key\")}function bn(e,t,n,i,s,o,r,a){null!=e&&null!=t&&e.length>0&&t.length>0?(this.n=dn(e,16),this.e=parseInt(t,16),this.d=dn(n,16),this.p=dn(i,16),this.q=dn(s,16),this.dmp1=dn(o,16),this.dmq1=dn(r,16),this.coeff=dn(a,16)):console.error(\"Invalid RSA private key\")}function yn(e,n){var i=new ln,s=e>>1;this.e=parseInt(n,16);for(var o=new t(n,16);;){for(;this.p=new t(e-s,1,i),0!=this.p.subtract(t.ONE).gcd(o).compareTo(t.ONE)||!this.p.isProbablePrime(10););for(;this.q=new t(s,1,i),0!=this.q.subtract(t.ONE).gcd(o).compareTo(t.ONE)||!this.q.isProbablePrime(10););if(this.p.compareTo(this.q)<=0){var r=this.p;this.p=this.q,this.q=r}var a=this.p.subtract(t.ONE),c=this.q.subtract(t.ONE),l=a.multiply(c);if(0==l.gcd(o).compareTo(t.ONE)){this.n=this.p.multiply(this.q),this.d=o.modInverse(l),this.dmp1=this.d.mod(a),this.dmq1=this.d.mod(c),this.coeff=this.q.modInverse(this.p);break}}}function _n(e){if(null==this.p||null==this.q)return e.modPow(this.d,this.n);for(var t=e.mod(this.p).modPow(this.dmp1,this.p),n=e.mod(this.q).modPow(this.dmq1,this.q);t.compareTo(n)<0;)t=t.add(this.p);return t.subtract(n).multiply(this.coeff).mod(this.p).multiply(this.q).add(n)}function En(e){var t=dn(e,16),n=this.doPrivate(t);return null==n?null:mn(n,this.n.bitLength()+7>>3)}function Cn(e){var t,n,i=\"\";for(t=0;t+3<=e.length;t+=3)n=parseInt(e.substring(t,t+3),16),i+=Un.charAt(n>>6)+Un.charAt(63&n);for(t+1==e.length?(n=parseInt(e.substring(t,t+1),16),i+=Un.charAt(n<<2)):t+2==e.length&&(n=parseInt(e.substring(t,t+2),16),i+=Un.charAt(n>>2)+Un.charAt((3&n)<<4));(3&i.length)>0;)i+=qn;return i}function wn(e){var t,n,i=\"\",s=0;for(t=0;t<e.length&&e.charAt(t)!=qn;++t)v=Un.indexOf(e.charAt(t)),0>v||(0==s?(i+=r(v>>2),n=3&v,s=1):1==s?(i+=r(n<<2|v>>4),n=15&v,s=2):2==s?(i+=r(n),i+=r(v>>2),n=3&v,s=3):(i+=r(n<<2|v>>4),i+=r(15&v),s=0));return 1==s&&(i+=r(n<<2)),i}var Sn,Tn=0xdeadbeefcafe,In=15715070==(16777215&Tn);In&&\"Microsoft Internet Explorer\"==navigator.appName?(t.prototype.am=s,Sn=30):In&&\"Netscape\"!=navigator.appName?(t.prototype.am=i,Sn=26):(t.prototype.am=o,Sn=28),t.prototype.DB=Sn,t.prototype.DM=(1<<Sn)-1,t.prototype.DV=1<<Sn;var Dn=52;t.prototype.FV=Math.pow(2,Dn),t.prototype.F1=Dn-Sn,t.prototype.F2=2*Sn-Dn;var Rn,xn,Ln=\"0123456789abcdefghijklmnopqrstuvwxyz\",kn=new Array;for(Rn=\"0\".charCodeAt(0),xn=0;9>=xn;++xn)kn[Rn++]=xn;for(Rn=\"a\".charCodeAt(0),xn=10;36>xn;++xn)kn[Rn++]=xn;for(Rn=\"A\".charCodeAt(0),xn=10;36>xn;++xn)kn[Rn++]=xn;x.prototype.convert=L,x.prototype.revert=k,x.prototype.reduce=P,x.prototype.mulTo=A,x.prototype.sqrTo=M,V.prototype.convert=$,V.prototype.revert=O,V.prototype.reduce=N,V.prototype.mulTo=q,V.prototype.sqrTo=U,t.prototype.copyTo=c,t.prototype.fromInt=l,t.prototype.fromString=u,t.prototype.clamp=p,t.prototype.dlShiftTo=_,t.prototype.drShiftTo=E,t.prototype.lShiftTo=C,t.prototype.rShiftTo=w,t.prototype.subTo=S,t.prototype.multiplyTo=T,t.prototype.squareTo=I,t.prototype.divRemTo=D,t.prototype.invDigit=B,t.prototype.isEven=F,t.prototype.exp=W,t.prototype.toString=g,t.prototype.negate=h,t.prototype.abs=f,t.prototype.compareTo=m,t.prototype.bitLength=y,t.prototype.mod=R,t.prototype.modPowInt=H,t.ZERO=d(0),t.ONE=d(1),Bt.prototype.convert=Vt,Bt.prototype.revert=Vt,Bt.prototype.mulTo=$t,Bt.prototype.sqrTo=Ot,Ft.prototype.convert=Wt,Ft.prototype.revert=Ht,Ft.prototype.reduce=Kt,Ft.prototype.mulTo=Jt,Ft.prototype.sqrTo=jt;var Pn=[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997],An=(1<<26)/Pn[Pn.length-1];t.prototype.chunkSize=Q,t.prototype.toRadix=Z,t.prototype.fromRadix=Y,t.prototype.fromNumber=X,t.prototype.bitwiseTo=st,t.prototype.changeBit=Et,t.prototype.addTo=Tt,t.prototype.dMultiply=At,t.prototype.dAddOffset=Mt,t.prototype.multiplyLowerTo=Ut,t.prototype.multiplyUpperTo=qt,t.prototype.modInt=zt,t.prototype.millerRabin=Xt,t.prototype.clone=K,t.prototype.intValue=j,t.prototype.byteValue=J,t.prototype.shortValue=G,t.prototype.signum=z,t.prototype.toByteArray=et,t.prototype.equals=tt,t.prototype.min=nt,t.prototype.max=it,t.prototype.and=rt,t.prototype.or=ct,t.prototype.xor=dt,t.prototype.andNot=pt,t.prototype.not=gt,t.prototype.shiftLeft=ht,t.prototype.shiftRight=ft,t.prototype.getLowestSetBit=vt,t.prototype.bitCount=yt,t.prototype.testBit=_t,t.prototype.setBit=Ct,t.prototype.clearBit=wt,t.prototype.flipBit=St,t.prototype.add=It,t.prototype.subtract=Dt,t.prototype.multiply=Rt,t.prototype.divide=Lt,t.prototype.remainder=kt,t.prototype.divideAndRemainder=Pt,t.prototype.modPow=Gt,t.prototype.modInverse=Zt,t.prototype.pow=Nt,t.prototype.gcd=Qt,t.prototype.isProbablePrime=Yt,t.prototype.square=xt,en.prototype.init=tn,en.prototype.next=nn;var Mn,Bn,Vn,$n=256;if(null==Bn){Bn=new Array,Vn=0;var On;if(\"Netscape\"==navigator.appName&&navigator.appVersion<\"5\"&&window.crypto){var Nn=window.crypto.random(32);for(On=0;On<Nn.length;++On)Bn[Vn++]=255&Nn.charCodeAt(On)}for(;$n>Vn;)On=Math.floor(65536*Math.random()),Bn[Vn++]=On>>>8,Bn[Vn++]=255&On;Vn=0,rn()}ln.prototype.nextBytes=cn,pn.prototype.doPublic=hn,pn.prototype.setPublic=gn,pn.prototype.encrypt=fn,pn.prototype.doPrivate=_n,pn.prototype.setPrivate=vn,pn.prototype.setPrivateEx=bn,pn.prototype.generate=yn,pn.prototype.decrypt=En,function(){var e=function(e,i,s){var o=new ln,r=e>>1;this.e=parseInt(i,16);var a=new t(i,16),c=this,l=function(){var i=function(){if(c.p.compareTo(c.q)<=0){var e=c.p;c.p=c.q,c.q=e}var n=c.p.subtract(t.ONE),i=c.q.subtract(t.ONE),o=n.multiply(i);0==o.gcd(a).compareTo(t.ONE)?(c.n=c.p.multiply(c.q),c.d=a.modInverse(o),c.dmp1=c.d.mod(n),c.dmq1=c.d.mod(i),c.coeff=c.q.modInverse(c.p),setTimeout(function(){s()},0)):setTimeout(l,0)},d=function(){c.q=n(),c.q.fromNumberAsync(r,1,o,function(){c.q.subtract(t.ONE).gcda(a,function(e){0==e.compareTo(t.ONE)&&c.q.isProbablePrime(10)?setTimeout(i,0):setTimeout(d,0)})})},u=function(){c.p=n(),c.p.fromNumberAsync(e-r,1,o,function(){c.p.subtract(t.ONE).gcda(a,function(e){0==e.compareTo(t.ONE)&&c.p.isProbablePrime(10)?setTimeout(d,0):setTimeout(u,0)})})};setTimeout(u,0)};setTimeout(l,0)};pn.prototype.generateAsync=e;var i=function(e,t){var n=this.s<0?this.negate():this.clone(),i=e.s<0?e.negate():e.clone();if(n.compareTo(i)<0){var s=n;n=i,i=s}var o=n.getLowestSetBit(),r=i.getLowestSetBit();if(0>r)return void t(n);r>o&&(r=o),r>0&&(n.rShiftTo(r,n),i.rShiftTo(r,i));var a=function(){(o=n.getLowestSetBit())>0&&n.rShiftTo(o,n),(o=i.getLowestSetBit())>0&&i.rShiftTo(o,i),n.compareTo(i)>=0?(n.subTo(i,n),n.rShiftTo(1,n)):(i.subTo(n,i),i.rShiftTo(1,i)),n.signum()>0?setTimeout(a,0):(r>0&&i.lShiftTo(r,i),setTimeout(function(){t(i)},0))};setTimeout(a,10)};t.prototype.gcda=i;var s=function(e,n,i,s){if(\"number\"==typeof n)if(2>e)this.fromInt(1);else{this.fromNumber(e,i),this.testBit(e-1)||this.bitwiseTo(t.ONE.shiftLeft(e-1),at,this),this.isEven()&&this.dAddOffset(1,0);var o=this,r=function(){o.dAddOffset(2,0),o.bitLength()>e&&o.subTo(t.ONE.shiftLeft(e-1),o),o.isProbablePrime(n)?setTimeout(function(){s()},0):setTimeout(r,0)};setTimeout(r,0)}else{var a=new Array,c=7&e;a.length=(e>>3)+1,n.nextBytes(a),c>0?a[0]&=(1<<c)-1:a[0]=0,this.fromString(a,256)}};t.prototype.fromNumberAsync=s}();var Un=\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\",qn=\"=\",Fn=Fn||{};Fn.env=Fn.env||{};var Wn=Fn,Hn=Object.prototype,Kn=\"[object Function]\",jn=[\"toString\",\"valueOf\"];Fn.env.parseUA=function(e){var t,n=function(e){var t=0;return parseFloat(e.replace(/\\./g,function(){return 1==t++?\"\":\".\"}))},i=navigator,s={ie:0,opera:0,gecko:0,webkit:0,chrome:0,mobile:null,air:0,ipad:0,iphone:0,ipod:0,ios:null,android:0,webos:0,caja:i&&i.cajaVersion,secure:!1,os:null},o=e||navigator&&navigator.userAgent,r=window&&window.location,a=r&&r.href;return s.secure=a&&0===a.toLowerCase().indexOf(\"https\"),o&&(/windows|win32/i.test(o)?s.os=\"windows\":/macintosh/i.test(o)?s.os=\"macintosh\":/rhino/i.test(o)&&(s.os=\"rhino\"),/KHTML/.test(o)&&(s.webkit=1),t=o.match(/AppleWebKit\\/([^\\s]*)/),t&&t[1]&&(s.webkit=n(t[1]),/ Mobile\\//.test(o)?(s.mobile=\"Apple\",t=o.match(/OS ([^\\s]*)/),t&&t[1]&&(t=n(t[1].replace(\"_\",\".\"))),s.ios=t,s.ipad=s.ipod=s.iphone=0,t=o.match(/iPad|iPod|iPhone/),t&&t[0]&&(s[t[0].toLowerCase()]=s.ios)):(t=o.match(/NokiaN[^\\/]*|Android \\d\\.\\d|webOS\\/\\d\\.\\d/),t&&(s.mobile=t[0]),/webOS/.test(o)&&(s.mobile=\"WebOS\",t=o.match(/webOS\\/([^\\s]*);/),t&&t[1]&&(s.webos=n(t[1]))),/ Android/.test(o)&&(s.mobile=\"Android\",t=o.match(/Android ([^\\s]*);/),t&&t[1]&&(s.android=n(t[1])))),t=o.match(/Chrome\\/([^\\s]*)/),t&&t[1]?s.chrome=n(t[1]):(t=o.match(/AdobeAIR\\/([^\\s]*)/),t&&(s.air=t[0]))),s.webkit||(t=o.match(/Opera[\\s\\/]([^\\s]*)/),t&&t[1]?(s.opera=n(t[1]),t=o.match(/Version\\/([^\\s]*)/),t&&t[1]&&(s.opera=n(t[1])),t=o.match(/Opera Mini[^;]*/),t&&(s.mobile=t[0])):(t=o.match(/MSIE\\s([^;]*)/),t&&t[1]?s.ie=n(t[1]):(t=o.match(/Gecko\\/([^\\s]*)/),t&&(s.gecko=1,t=o.match(/rv:([^\\s\\)]*)/),t&&t[1]&&(s.gecko=n(t[1]))))))),s},Fn.env.ua=Fn.env.parseUA(),Fn.isFunction=function(e){return\"function\"==typeof e||Hn.toString.apply(e)===Kn},Fn._IEEnumFix=Fn.env.ua.ie?function(e,t){var n,i,s;for(n=0;n<jn.length;n+=1)i=jn[n],s=t[i],Wn.isFunction(s)&&s!=Hn[i]&&(e[i]=s)}:function(){},Fn.extend=function(e,t,n){if(!t||!e)throw new Error(\"extend failed, please check that all dependencies are included.\");var i,s=function(){};if(s.prototype=t.prototype,e.prototype=new s,e.prototype.constructor=e,e.superclass=t.prototype,t.prototype.constructor==Hn.constructor&&(t.prototype.constructor=t),n){for(i in n)Wn.hasOwnProperty(n,i)&&(e.prototype[i]=n[i]);Wn._IEEnumFix(e.prototype,n)}},\"undefined\"!=typeof KJUR&&KJUR||(KJUR={}),\"undefined\"!=typeof KJUR.asn1&&KJUR.asn1||(KJUR.asn1={}),KJUR.asn1.ASN1Util=new function(){this.integerToByteHex=function(e){var t=e.toString(16);return t.length%2==1&&(t=\"0\"+t),t},this.bigIntToMinTwosComplementsHex=function(e){var n=e.toString(16);if(\"-\"!=n.substr(0,1))n.length%2==1?n=\"0\"+n:n.match(/^[0-7]/)||(n=\"00\"+n);else{var i=n.substr(1),s=i.length;s%2==1?s+=1:n.match(/^[0-7]/)||(s+=2);for(var o=\"\",r=0;s>r;r++)o+=\"f\";var a=new t(o,16),c=a.xor(e).add(t.ONE);n=c.toString(16).replace(/^-/,\"\")}return n},this.getPEMStringFromHex=function(e,t){var n=CryptoJS.enc.Hex.parse(e),i=CryptoJS.enc.Base64.stringify(n),s=i.replace(/(.{64})/g,\"$1\\r\\n\");return s=s.replace(/\\r\\n$/,\"\"),\"-----BEGIN \"+t+\"-----\\r\\n\"+s+\"\\r\\n-----END \"+t+\"-----\\r\\n\"}},KJUR.asn1.ASN1Object=function(){var e=\"\";this.getLengthHexFromValue=function(){if(\"undefined\"==typeof this.hV||null==this.hV)throw\"this.hV is null or undefined.\";if(this.hV.length%2==1)throw\"value hex must be even length: n=\"+e.length+\",v=\"+this.hV;var t=this.hV.length/2,n=t.toString(16);if(n.length%2==1&&(n=\"0\"+n),128>t)return n;var i=n.length/2;if(i>15)throw\"ASN.1 length too long to represent by 8x: n = \"+t.toString(16);var s=128+i;return s.toString(16)+n},this.getEncodedHex=function(){return(null==this.hTLV||this.isModified)&&(this.hV=this.getFreshValueHex(),this.hL=this.getLengthHexFromValue(),this.hTLV=this.hT+this.hL+this.hV,this.isModified=!1),this.hTLV\n},this.getValueHex=function(){return this.getEncodedHex(),this.hV},this.getFreshValueHex=function(){return\"\"}},KJUR.asn1.DERAbstractString=function(e){KJUR.asn1.DERAbstractString.superclass.constructor.call(this),this.getString=function(){return this.s},this.setString=function(e){this.hTLV=null,this.isModified=!0,this.s=e,this.hV=stohex(this.s)},this.setStringHex=function(e){this.hTLV=null,this.isModified=!0,this.s=null,this.hV=e},this.getFreshValueHex=function(){return this.hV},\"undefined\"!=typeof e&&(\"undefined\"!=typeof e.str?this.setString(e.str):\"undefined\"!=typeof e.hex&&this.setStringHex(e.hex))},Fn.extend(KJUR.asn1.DERAbstractString,KJUR.asn1.ASN1Object),KJUR.asn1.DERAbstractTime=function(){KJUR.asn1.DERAbstractTime.superclass.constructor.call(this),this.localDateToUTC=function(e){utc=e.getTime()+6e4*e.getTimezoneOffset();var t=new Date(utc);return t},this.formatDate=function(e,t){var n=this.zeroPadding,i=this.localDateToUTC(e),s=String(i.getFullYear());\"utc\"==t&&(s=s.substr(2,2));var o=n(String(i.getMonth()+1),2),r=n(String(i.getDate()),2),a=n(String(i.getHours()),2),c=n(String(i.getMinutes()),2),l=n(String(i.getSeconds()),2);return s+o+r+a+c+l+\"Z\"},this.zeroPadding=function(e,t){return e.length>=t?e:new Array(t-e.length+1).join(\"0\")+e},this.getString=function(){return this.s},this.setString=function(e){this.hTLV=null,this.isModified=!0,this.s=e,this.hV=stohex(this.s)},this.setByDateValue=function(e,t,n,i,s,o){var r=new Date(Date.UTC(e,t-1,n,i,s,o,0));this.setByDate(r)},this.getFreshValueHex=function(){return this.hV}},Fn.extend(KJUR.asn1.DERAbstractTime,KJUR.asn1.ASN1Object),KJUR.asn1.DERAbstractStructured=function(e){KJUR.asn1.DERAbstractString.superclass.constructor.call(this),this.setByASN1ObjectArray=function(e){this.hTLV=null,this.isModified=!0,this.asn1Array=e},this.appendASN1Object=function(e){this.hTLV=null,this.isModified=!0,this.asn1Array.push(e)},this.asn1Array=new Array,\"undefined\"!=typeof e&&\"undefined\"!=typeof e.array&&(this.asn1Array=e.array)},Fn.extend(KJUR.asn1.DERAbstractStructured,KJUR.asn1.ASN1Object),KJUR.asn1.DERBoolean=function(){KJUR.asn1.DERBoolean.superclass.constructor.call(this),this.hT=\"01\",this.hTLV=\"0101ff\"},Fn.extend(KJUR.asn1.DERBoolean,KJUR.asn1.ASN1Object),KJUR.asn1.DERInteger=function(e){KJUR.asn1.DERInteger.superclass.constructor.call(this),this.hT=\"02\",this.setByBigInteger=function(e){this.hTLV=null,this.isModified=!0,this.hV=KJUR.asn1.ASN1Util.bigIntToMinTwosComplementsHex(e)},this.setByInteger=function(e){var n=new t(String(e),10);this.setByBigInteger(n)},this.setValueHex=function(e){this.hV=e},this.getFreshValueHex=function(){return this.hV},\"undefined\"!=typeof e&&(\"undefined\"!=typeof e.bigint?this.setByBigInteger(e.bigint):\"undefined\"!=typeof e[\"int\"]?this.setByInteger(e[\"int\"]):\"undefined\"!=typeof e.hex&&this.setValueHex(e.hex))},Fn.extend(KJUR.asn1.DERInteger,KJUR.asn1.ASN1Object),KJUR.asn1.DERBitString=function(e){KJUR.asn1.DERBitString.superclass.constructor.call(this),this.hT=\"03\",this.setHexValueIncludingUnusedBits=function(e){this.hTLV=null,this.isModified=!0,this.hV=e},this.setUnusedBitsAndHexValue=function(e,t){if(0>e||e>7)throw\"unused bits shall be from 0 to 7: u = \"+e;var n=\"0\"+e;this.hTLV=null,this.isModified=!0,this.hV=n+t},this.setByBinaryString=function(e){e=e.replace(/0+$/,\"\");var t=8-e.length%8;8==t&&(t=0);for(var n=0;t>=n;n++)e+=\"0\";for(var i=\"\",n=0;n<e.length-1;n+=8){var s=e.substr(n,8),o=parseInt(s,2).toString(16);1==o.length&&(o=\"0\"+o),i+=o}this.hTLV=null,this.isModified=!0,this.hV=\"0\"+t+i},this.setByBooleanArray=function(e){for(var t=\"\",n=0;n<e.length;n++)t+=1==e[n]?\"1\":\"0\";this.setByBinaryString(t)},this.newFalseArray=function(e){for(var t=new Array(e),n=0;e>n;n++)t[n]=!1;return t},this.getFreshValueHex=function(){return this.hV},\"undefined\"!=typeof e&&(\"undefined\"!=typeof e.hex?this.setHexValueIncludingUnusedBits(e.hex):\"undefined\"!=typeof e.bin?this.setByBinaryString(e.bin):\"undefined\"!=typeof e.array&&this.setByBooleanArray(e.array))},Fn.extend(KJUR.asn1.DERBitString,KJUR.asn1.ASN1Object),KJUR.asn1.DEROctetString=function(e){KJUR.asn1.DEROctetString.superclass.constructor.call(this,e),this.hT=\"04\"},Fn.extend(KJUR.asn1.DEROctetString,KJUR.asn1.DERAbstractString),KJUR.asn1.DERNull=function(){KJUR.asn1.DERNull.superclass.constructor.call(this),this.hT=\"05\",this.hTLV=\"0500\"},Fn.extend(KJUR.asn1.DERNull,KJUR.asn1.ASN1Object),KJUR.asn1.DERObjectIdentifier=function(e){var n=function(e){var t=e.toString(16);return 1==t.length&&(t=\"0\"+t),t},i=function(e){var i=\"\",s=new t(e,10),o=s.toString(2),r=7-o.length%7;7==r&&(r=0);for(var a=\"\",c=0;r>c;c++)a+=\"0\";o=a+o;for(var c=0;c<o.length-1;c+=7){var l=o.substr(c,7);c!=o.length-7&&(l=\"1\"+l),i+=n(parseInt(l,2))}return i};KJUR.asn1.DERObjectIdentifier.superclass.constructor.call(this),this.hT=\"06\",this.setValueHex=function(e){this.hTLV=null,this.isModified=!0,this.s=null,this.hV=e},this.setValueOidString=function(e){if(!e.match(/^[0-9.]+$/))throw\"malformed oid string: \"+e;var t=\"\",s=e.split(\".\"),o=40*parseInt(s[0])+parseInt(s[1]);t+=n(o),s.splice(0,2);for(var r=0;r<s.length;r++)t+=i(s[r]);this.hTLV=null,this.isModified=!0,this.s=null,this.hV=t},this.setValueName=function(e){if(\"undefined\"==typeof KJUR.asn1.x509.OID.name2oidList[e])throw\"DERObjectIdentifier oidName undefined: \"+e;var t=KJUR.asn1.x509.OID.name2oidList[e];this.setValueOidString(t)},this.getFreshValueHex=function(){return this.hV},\"undefined\"!=typeof e&&(\"undefined\"!=typeof e.oid?this.setValueOidString(e.oid):\"undefined\"!=typeof e.hex?this.setValueHex(e.hex):\"undefined\"!=typeof e.name&&this.setValueName(e.name))},Fn.extend(KJUR.asn1.DERObjectIdentifier,KJUR.asn1.ASN1Object),KJUR.asn1.DERUTF8String=function(e){KJUR.asn1.DERUTF8String.superclass.constructor.call(this,e),this.hT=\"0c\"},Fn.extend(KJUR.asn1.DERUTF8String,KJUR.asn1.DERAbstractString),KJUR.asn1.DERNumericString=function(e){KJUR.asn1.DERNumericString.superclass.constructor.call(this,e),this.hT=\"12\"},Fn.extend(KJUR.asn1.DERNumericString,KJUR.asn1.DERAbstractString),KJUR.asn1.DERPrintableString=function(e){KJUR.asn1.DERPrintableString.superclass.constructor.call(this,e),this.hT=\"13\"},Fn.extend(KJUR.asn1.DERPrintableString,KJUR.asn1.DERAbstractString),KJUR.asn1.DERTeletexString=function(e){KJUR.asn1.DERTeletexString.superclass.constructor.call(this,e),this.hT=\"14\"},Fn.extend(KJUR.asn1.DERTeletexString,KJUR.asn1.DERAbstractString),KJUR.asn1.DERIA5String=function(e){KJUR.asn1.DERIA5String.superclass.constructor.call(this,e),this.hT=\"16\"},Fn.extend(KJUR.asn1.DERIA5String,KJUR.asn1.DERAbstractString),KJUR.asn1.DERUTCTime=function(e){KJUR.asn1.DERUTCTime.superclass.constructor.call(this,e),this.hT=\"17\",this.setByDate=function(e){this.hTLV=null,this.isModified=!0,this.date=e,this.s=this.formatDate(this.date,\"utc\"),this.hV=stohex(this.s)},\"undefined\"!=typeof e&&(\"undefined\"!=typeof e.str?this.setString(e.str):\"undefined\"!=typeof e.hex?this.setStringHex(e.hex):\"undefined\"!=typeof e.date&&this.setByDate(e.date))},Fn.extend(KJUR.asn1.DERUTCTime,KJUR.asn1.DERAbstractTime),KJUR.asn1.DERGeneralizedTime=function(e){KJUR.asn1.DERGeneralizedTime.superclass.constructor.call(this,e),this.hT=\"18\",this.setByDate=function(e){this.hTLV=null,this.isModified=!0,this.date=e,this.s=this.formatDate(this.date,\"gen\"),this.hV=stohex(this.s)},\"undefined\"!=typeof e&&(\"undefined\"!=typeof e.str?this.setString(e.str):\"undefined\"!=typeof e.hex?this.setStringHex(e.hex):\"undefined\"!=typeof e.date&&this.setByDate(e.date))},Fn.extend(KJUR.asn1.DERGeneralizedTime,KJUR.asn1.DERAbstractTime),KJUR.asn1.DERSequence=function(e){KJUR.asn1.DERSequence.superclass.constructor.call(this,e),this.hT=\"30\",this.getFreshValueHex=function(){for(var e=\"\",t=0;t<this.asn1Array.length;t++){var n=this.asn1Array[t];e+=n.getEncodedHex()}return this.hV=e,this.hV}},Fn.extend(KJUR.asn1.DERSequence,KJUR.asn1.DERAbstractStructured),KJUR.asn1.DERSet=function(e){KJUR.asn1.DERSet.superclass.constructor.call(this,e),this.hT=\"31\",this.getFreshValueHex=function(){for(var e=new Array,t=0;t<this.asn1Array.length;t++){var n=this.asn1Array[t];e.push(n.getEncodedHex())}return e.sort(),this.hV=e.join(\"\"),this.hV}},Fn.extend(KJUR.asn1.DERSet,KJUR.asn1.DERAbstractStructured),KJUR.asn1.DERTaggedObject=function(e){KJUR.asn1.DERTaggedObject.superclass.constructor.call(this),this.hT=\"a0\",this.hV=\"\",this.isExplicit=!0,this.asn1Object=null,this.setASN1Object=function(e,t,n){this.hT=t,this.isExplicit=e,this.asn1Object=n,this.isExplicit?(this.hV=this.asn1Object.getEncodedHex(),this.hTLV=null,this.isModified=!0):(this.hV=null,this.hTLV=n.getEncodedHex(),this.hTLV=this.hTLV.replace(/^../,t),this.isModified=!1)},this.getFreshValueHex=function(){return this.hV},\"undefined\"!=typeof e&&(\"undefined\"!=typeof e.tag&&(this.hT=e.tag),\"undefined\"!=typeof e.explicit&&(this.isExplicit=e.explicit),\"undefined\"!=typeof e.obj&&(this.asn1Object=e.obj,this.setASN1Object(this.isExplicit,this.hT,this.asn1Object)))},Fn.extend(KJUR.asn1.DERTaggedObject,KJUR.asn1.ASN1Object),function(e){\"use strict\";var t,n={};n.decode=function(n){var i;if(t===e){var s=\"0123456789ABCDEF\",o=\" \\f\\n\\r\t \\u2028\\u2029\";for(t=[],i=0;16>i;++i)t[s.charAt(i)]=i;for(s=s.toLowerCase(),i=10;16>i;++i)t[s.charAt(i)]=i;for(i=0;i<o.length;++i)t[o.charAt(i)]=-1}var r=[],a=0,c=0;for(i=0;i<n.length;++i){var l=n.charAt(i);if(\"=\"==l)break;if(l=t[l],-1!=l){if(l===e)throw\"Illegal character at offset \"+i;a|=l,++c>=2?(r[r.length]=a,a=0,c=0):a<<=4}}if(c)throw\"Hex encoding incomplete: 4 bits missing\";return r},window.Hex=n}(),function(e){\"use strict\";var t,n={};n.decode=function(n){var i;if(t===e){var s=\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\",o=\"= \\f\\n\\r\t \\u2028\\u2029\";for(t=[],i=0;64>i;++i)t[s.charAt(i)]=i;for(i=0;i<o.length;++i)t[o.charAt(i)]=-1}var r=[],a=0,c=0;for(i=0;i<n.length;++i){var l=n.charAt(i);if(\"=\"==l)break;if(l=t[l],-1!=l){if(l===e)throw\"Illegal character at offset \"+i;a|=l,++c>=4?(r[r.length]=a>>16,r[r.length]=a>>8&255,r[r.length]=255&a,a=0,c=0):a<<=6}}switch(c){case 1:throw\"Base64 encoding incomplete: at least 2 bits missing\";case 2:r[r.length]=a>>10;break;case 3:r[r.length]=a>>16,r[r.length]=a>>8&255}return r},n.re=/-----BEGIN [^-]+-----([A-Za-z0-9+\\/=\\s]+)-----END [^-]+-----|begin-base64[^\\n]+\\n([A-Za-z0-9+\\/=\\s]+)====/,n.unarmor=function(e){var t=n.re.exec(e);if(t)if(t[1])e=t[1];else{if(!t[2])throw\"RegExp out of sync\";e=t[2]}return n.decode(e)},window.Base64=n}(),function(e){\"use strict\";function t(e,n){e instanceof t?(this.enc=e.enc,this.pos=e.pos):(this.enc=e,this.pos=n)}function n(e,t,n,i,s){this.stream=e,this.header=t,this.length=n,this.tag=i,this.sub=s}var i=100,s=\"…\",o={tag:function(e,t){var n=document.createElement(e);return n.className=t,n},text:function(e){return document.createTextNode(e)}};t.prototype.get=function(t){if(t===e&&(t=this.pos++),t>=this.enc.length)throw\"Requesting byte offset \"+t+\" on a stream of length \"+this.enc.length;return this.enc[t]},t.prototype.hexDigits=\"0123456789ABCDEF\",t.prototype.hexByte=function(e){return this.hexDigits.charAt(e>>4&15)+this.hexDigits.charAt(15&e)},t.prototype.hexDump=function(e,t,n){for(var i=\"\",s=e;t>s;++s)if(i+=this.hexByte(this.get(s)),n!==!0)switch(15&s){case 7:i+=\"  \";break;case 15:i+=\"\\n\";break;default:i+=\" \"}return i},t.prototype.parseStringISO=function(e,t){for(var n=\"\",i=e;t>i;++i)n+=String.fromCharCode(this.get(i));return n},t.prototype.parseStringUTF=function(e,t){for(var n=\"\",i=e;t>i;){var s=this.get(i++);n+=String.fromCharCode(128>s?s:s>191&&224>s?(31&s)<<6|63&this.get(i++):(15&s)<<12|(63&this.get(i++))<<6|63&this.get(i++))}return n},t.prototype.parseStringBMP=function(e,t){for(var n=\"\",i=e;t>i;i+=2){var s=this.get(i),o=this.get(i+1);n+=String.fromCharCode((s<<8)+o)}return n},t.prototype.reTime=/^((?:1[89]|2\\d)?\\d\\d)(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])([01]\\d|2[0-3])(?:([0-5]\\d)(?:([0-5]\\d)(?:[.,](\\d{1,3}))?)?)?(Z|[-+](?:[0]\\d|1[0-2])([0-5]\\d)?)?$/,t.prototype.parseTime=function(e,t){var n=this.parseStringISO(e,t),i=this.reTime.exec(n);return i?(n=i[1]+\"-\"+i[2]+\"-\"+i[3]+\" \"+i[4],i[5]&&(n+=\":\"+i[5],i[6]&&(n+=\":\"+i[6],i[7]&&(n+=\".\"+i[7]))),i[8]&&(n+=\" UTC\",\"Z\"!=i[8]&&(n+=i[8],i[9]&&(n+=\":\"+i[9]))),n):\"Unrecognized time: \"+n},t.prototype.parseInteger=function(e,t){var n=t-e;if(n>4){n<<=3;var i=this.get(e);if(0===i)n-=8;else for(;128>i;)i<<=1,--n;return\"(\"+n+\" bit)\"}for(var s=0,o=e;t>o;++o)s=s<<8|this.get(o);return s},t.prototype.parseBitString=function(e,t){var n=this.get(e),i=(t-e-1<<3)-n,s=\"(\"+i+\" bit)\";if(20>=i){var o=n;s+=\" \";for(var r=t-1;r>e;--r){for(var a=this.get(r),c=o;8>c;++c)s+=a>>c&1?\"1\":\"0\";o=0}}return s},t.prototype.parseOctetString=function(e,t){var n=t-e,o=\"(\"+n+\" byte) \";n>i&&(t=e+i);for(var r=e;t>r;++r)o+=this.hexByte(this.get(r));return n>i&&(o+=s),o},t.prototype.parseOID=function(e,t){for(var n=\"\",i=0,s=0,o=e;t>o;++o){var r=this.get(o);if(i=i<<7|127&r,s+=7,!(128&r)){if(\"\"===n){var a=80>i?40>i?0:1:2;n=a+\".\"+(i-40*a)}else n+=\".\"+(s>=31?\"bigint\":i);i=s=0}}return n},n.prototype.typeName=function(){if(this.tag===e)return\"unknown\";var t=this.tag>>6,n=(this.tag>>5&1,31&this.tag);switch(t){case 0:switch(n){case 0:return\"EOC\";case 1:return\"BOOLEAN\";case 2:return\"INTEGER\";case 3:return\"BIT_STRING\";case 4:return\"OCTET_STRING\";case 5:return\"NULL\";case 6:return\"OBJECT_IDENTIFIER\";case 7:return\"ObjectDescriptor\";case 8:return\"EXTERNAL\";case 9:return\"REAL\";case 10:return\"ENUMERATED\";case 11:return\"EMBEDDED_PDV\";case 12:return\"UTF8String\";case 16:return\"SEQUENCE\";case 17:return\"SET\";case 18:return\"NumericString\";case 19:return\"PrintableString\";case 20:return\"TeletexString\";case 21:return\"VideotexString\";case 22:return\"IA5String\";case 23:return\"UTCTime\";case 24:return\"GeneralizedTime\";case 25:return\"GraphicString\";case 26:return\"VisibleString\";case 27:return\"GeneralString\";case 28:return\"UniversalString\";case 30:return\"BMPString\";default:return\"Universal_\"+n.toString(16)}case 1:return\"Application_\"+n.toString(16);case 2:return\"[\"+n+\"]\";case 3:return\"Private_\"+n.toString(16)}},n.prototype.reSeemsASCII=/^[ -~]+$/,n.prototype.content=function(){if(this.tag===e)return null;var t=this.tag>>6,n=31&this.tag,o=this.posContent(),r=Math.abs(this.length);if(0!==t){if(null!==this.sub)return\"(\"+this.sub.length+\" elem)\";var a=this.stream.parseStringISO(o,o+Math.min(r,i));return this.reSeemsASCII.test(a)?a.substring(0,2*i)+(a.length>2*i?s:\"\"):this.stream.parseOctetString(o,o+r)}switch(n){case 1:return 0===this.stream.get(o)?\"false\":\"true\";case 2:return this.stream.parseInteger(o,o+r);case 3:return this.sub?\"(\"+this.sub.length+\" elem)\":this.stream.parseBitString(o,o+r);case 4:return this.sub?\"(\"+this.sub.length+\" elem)\":this.stream.parseOctetString(o,o+r);case 6:return this.stream.parseOID(o,o+r);case 16:case 17:return\"(\"+this.sub.length+\" elem)\";case 12:return this.stream.parseStringUTF(o,o+r);case 18:case 19:case 20:case 21:case 22:case 26:return this.stream.parseStringISO(o,o+r);case 30:return this.stream.parseStringBMP(o,o+r);case 23:case 24:return this.stream.parseTime(o,o+r)}return null},n.prototype.toString=function(){return this.typeName()+\"@\"+this.stream.pos+\"[header:\"+this.header+\",length:\"+this.length+\",sub:\"+(null===this.sub?\"null\":this.sub.length)+\"]\"},n.prototype.print=function(t){if(t===e&&(t=\"\"),document.writeln(t+this),null!==this.sub){t+=\"  \";for(var n=0,i=this.sub.length;i>n;++n)this.sub[n].print(t)}},n.prototype.toPrettyString=function(t){t===e&&(t=\"\");var n=t+this.typeName()+\" @\"+this.stream.pos;if(this.length>=0&&(n+=\"+\"),n+=this.length,32&this.tag?n+=\" (constructed)\":3!=this.tag&&4!=this.tag||null===this.sub||(n+=\" (encapsulates)\"),n+=\"\\n\",null!==this.sub){t+=\"  \";for(var i=0,s=this.sub.length;s>i;++i)n+=this.sub[i].toPrettyString(t)}return n},n.prototype.toDOM=function(){var e=o.tag(\"div\",\"node\");e.asn1=this;var t=o.tag(\"div\",\"head\"),n=this.typeName().replace(/_/g,\" \");t.innerHTML=n;var i=this.content();if(null!==i){i=String(i).replace(/</g,\"&lt;\");var s=o.tag(\"span\",\"preview\");s.appendChild(o.text(i)),t.appendChild(s)}e.appendChild(t),this.node=e,this.head=t;var r=o.tag(\"div\",\"value\");if(n=\"Offset: \"+this.stream.pos+\"<br/>\",n+=\"Length: \"+this.header+\"+\",n+=this.length>=0?this.length:-this.length+\" (undefined)\",32&this.tag?n+=\"<br/>(constructed)\":3!=this.tag&&4!=this.tag||null===this.sub||(n+=\"<br/>(encapsulates)\"),null!==i&&(n+=\"<br/>Value:<br/><b>\"+i+\"</b>\",\"object\"==typeof oids&&6==this.tag)){var a=oids[i];a&&(a.d&&(n+=\"<br/>\"+a.d),a.c&&(n+=\"<br/>\"+a.c),a.w&&(n+=\"<br/>(warning!)\"))}r.innerHTML=n,e.appendChild(r);var c=o.tag(\"div\",\"sub\");if(null!==this.sub)for(var l=0,d=this.sub.length;d>l;++l)c.appendChild(this.sub[l].toDOM());return e.appendChild(c),t.onclick=function(){e.className=\"node collapsed\"==e.className?\"node\":\"node collapsed\"},e},n.prototype.posStart=function(){return this.stream.pos},n.prototype.posContent=function(){return this.stream.pos+this.header},n.prototype.posEnd=function(){return this.stream.pos+this.header+Math.abs(this.length)},n.prototype.fakeHover=function(e){this.node.className+=\" hover\",e&&(this.head.className+=\" hover\")},n.prototype.fakeOut=function(e){var t=/ ?hover/;this.node.className=this.node.className.replace(t,\"\"),e&&(this.head.className=this.head.className.replace(t,\"\"))},n.prototype.toHexDOM_sub=function(e,t,n,i,s){if(!(i>=s)){var r=o.tag(\"span\",t);r.appendChild(o.text(n.hexDump(i,s))),e.appendChild(r)}},n.prototype.toHexDOM=function(t){var n=o.tag(\"span\",\"hex\");if(t===e&&(t=n),this.head.hexNode=n,this.head.onmouseover=function(){this.hexNode.className=\"hexCurrent\"},this.head.onmouseout=function(){this.hexNode.className=\"hex\"},n.asn1=this,n.onmouseover=function(){var e=!t.selected;e&&(t.selected=this.asn1,this.className=\"hexCurrent\"),this.asn1.fakeHover(e)},n.onmouseout=function(){var e=t.selected==this.asn1;this.asn1.fakeOut(e),e&&(t.selected=null,this.className=\"hex\")},this.toHexDOM_sub(n,\"tag\",this.stream,this.posStart(),this.posStart()+1),this.toHexDOM_sub(n,this.length>=0?\"dlen\":\"ulen\",this.stream,this.posStart()+1,this.posContent()),null===this.sub)n.appendChild(o.text(this.stream.hexDump(this.posContent(),this.posEnd())));else if(this.sub.length>0){var i=this.sub[0],s=this.sub[this.sub.length-1];this.toHexDOM_sub(n,\"intro\",this.stream,this.posContent(),i.posStart());for(var r=0,a=this.sub.length;a>r;++r)n.appendChild(this.sub[r].toHexDOM(t));this.toHexDOM_sub(n,\"outro\",this.stream,s.posEnd(),this.posEnd())}return n},n.prototype.toHexString=function(){return this.stream.hexDump(this.posStart(),this.posEnd(),!0)},n.decodeLength=function(e){var t=e.get(),n=127&t;if(n==t)return n;if(n>3)throw\"Length over 24 bits not supported at position \"+(e.pos-1);if(0===n)return-1;t=0;for(var i=0;n>i;++i)t=t<<8|e.get();return t},n.hasContent=function(e,i,s){if(32&e)return!0;if(3>e||e>4)return!1;var o=new t(s);3==e&&o.get();var r=o.get();if(r>>6&1)return!1;try{var a=n.decodeLength(o);return o.pos-s.pos+a==i}catch(c){return!1}},n.decode=function(e){e instanceof t||(e=new t(e,0));var i=new t(e),s=e.get(),o=n.decodeLength(e),r=e.pos-i.pos,a=null;if(n.hasContent(s,o,e)){var c=e.pos;if(3==s&&e.get(),a=[],o>=0){for(var l=c+o;e.pos<l;)a[a.length]=n.decode(e);if(e.pos!=l)throw\"Content size is not correct for container starting at offset \"+c}else try{for(;;){var d=n.decode(e);if(0===d.tag)break;a[a.length]=d}o=c-e.pos}catch(u){throw\"Exception while decoding undefined length content: \"+u}}else e.pos+=o;return new n(i,r,o,s,a)},n.test=function(){for(var e=[{value:[39],expected:39},{value:[129,201],expected:201},{value:[131,254,220,186],expected:16702650}],i=0,s=e.length;s>i;++i){var o=new t(e[i].value,0),r=n.decodeLength(o);r!=e[i].expected&&document.write(\"In test[\"+i+\"] expected \"+e[i].expected+\" got \"+r+\"\\n\")}},window.ASN1=n}(),ASN1.prototype.getHexStringValue=function(){var e=this.toHexString(),t=2*this.header,n=2*this.length;return e.substr(t,n)},pn.prototype.parseKey=function(e){try{var t=/^\\s*(?:[0-9A-Fa-f][0-9A-Fa-f]\\s*)+$/,n=t.test(e)?Hex.decode(e):Base64.unarmor(e),i=ASN1.decode(n);if(9===i.sub.length){var s=i.sub[1].getHexStringValue();this.n=dn(s,16);var o=i.sub[2].getHexStringValue();this.e=parseInt(o,16);var r=i.sub[3].getHexStringValue();this.d=dn(r,16);var a=i.sub[4].getHexStringValue();this.p=dn(a,16);var c=i.sub[5].getHexStringValue();this.q=dn(c,16);var l=i.sub[6].getHexStringValue();this.dmp1=dn(l,16);var d=i.sub[7].getHexStringValue();this.dmq1=dn(d,16);var u=i.sub[8].getHexStringValue();this.coeff=dn(u,16)}else{if(2!==i.sub.length)return!1;var p=i.sub[1],g=p.sub[0],s=g.sub[0].getHexStringValue();this.n=dn(s,16);var o=g.sub[1].getHexStringValue();this.e=parseInt(o,16)}return!0}catch(h){return!1}},pn.prototype.getPrivateBaseKey=function(){var e={array:[new KJUR.asn1.DERInteger({\"int\":0}),new KJUR.asn1.DERInteger({bigint:this.n}),new KJUR.asn1.DERInteger({\"int\":this.e}),new KJUR.asn1.DERInteger({bigint:this.d}),new KJUR.asn1.DERInteger({bigint:this.p}),new KJUR.asn1.DERInteger({bigint:this.q}),new KJUR.asn1.DERInteger({bigint:this.dmp1}),new KJUR.asn1.DERInteger({bigint:this.dmq1}),new KJUR.asn1.DERInteger({bigint:this.coeff})]},t=new KJUR.asn1.DERSequence(e);return t.getEncodedHex()},pn.prototype.getPrivateBaseKeyB64=function(){return Cn(this.getPrivateBaseKey())},pn.prototype.getPublicBaseKey=function(){var e={array:[new KJUR.asn1.DERObjectIdentifier({oid:\"1.2.840.113549.1.1.1\"}),new KJUR.asn1.DERNull]},t=new KJUR.asn1.DERSequence(e);e={array:[new KJUR.asn1.DERInteger({bigint:this.n}),new KJUR.asn1.DERInteger({\"int\":this.e})]};var n=new KJUR.asn1.DERSequence(e);e={hex:\"00\"+n.getEncodedHex()};var i=new KJUR.asn1.DERBitString(e);e={array:[t,i]};var s=new KJUR.asn1.DERSequence(e);return s.getEncodedHex()},pn.prototype.getPublicBaseKeyB64=function(){return Cn(this.getPublicBaseKey())},pn.prototype.wordwrap=function(e,t){if(t=t||64,!e)return e;var n=\"(.{1,\"+t+\"})( +|$\\n?)|(.{1,\"+t+\"})\";return e.match(RegExp(n,\"g\")).join(\"\\n\")},pn.prototype.getPrivateKey=function(){var e=\"-----BEGIN RSA PRIVATE KEY-----\\n\";return e+=this.wordwrap(this.getPrivateBaseKeyB64())+\"\\n\",e+=\"-----END RSA PRIVATE KEY-----\"},pn.prototype.getPublicKey=function(){var e=\"-----BEGIN PUBLIC KEY-----\\n\";return e+=this.wordwrap(this.getPublicBaseKeyB64())+\"\\n\",e+=\"-----END PUBLIC KEY-----\"},pn.prototype.hasPublicKeyProperty=function(e){return e=e||{},e.hasOwnProperty(\"n\")&&e.hasOwnProperty(\"e\")},pn.prototype.hasPrivateKeyProperty=function(e){return e=e||{},e.hasOwnProperty(\"n\")&&e.hasOwnProperty(\"e\")&&e.hasOwnProperty(\"d\")&&e.hasOwnProperty(\"p\")&&e.hasOwnProperty(\"q\")&&e.hasOwnProperty(\"dmp1\")&&e.hasOwnProperty(\"dmq1\")&&e.hasOwnProperty(\"coeff\")},pn.prototype.parsePropertiesFrom=function(e){this.n=e.n,this.e=e.e,e.hasOwnProperty(\"d\")&&(this.d=e.d,this.p=e.p,this.q=e.q,this.dmp1=e.dmp1,this.dmq1=e.dmq1,this.coeff=e.coeff)};var Jn=function(e){pn.call(this),e&&(\"string\"==typeof e?this.parseKey(e):(this.hasPrivateKeyProperty(e)||this.hasPublicKeyProperty(e))&&this.parsePropertiesFrom(e))};Jn.prototype=new pn,Jn.prototype.constructor=Jn;var Gn=function(e){e=e||{},this.default_key_size=parseInt(e.default_key_size)||1024,this.default_public_exponent=e.default_public_exponent||\"010001\",this.log=e.log||!1,this.key=null};Gn.prototype.setKey=function(e){this.log&&this.key&&console.warn(\"A key was already set, overriding existing.\"),this.key=new Jn(e)},Gn.prototype.setPrivateKey=function(e){this.setKey(e)},Gn.prototype.setPublicKey=function(e){this.setKey(e)},Gn.prototype.decrypt=function(e){try{return this.getKey().decrypt(wn(e))}catch(t){return!1}},Gn.prototype.encrypt=function(e){try{return Cn(this.getKey().encrypt(e))}catch(t){return!1}},Gn.prototype.getKey=function(e){if(!this.key){if(this.key=new Jn,e&&\"[object Function]\"==={}.toString.call(e))return void this.key.generateAsync(this.default_key_size,this.default_public_exponent,e);this.key.generate(this.default_key_size,this.default_public_exponent)}return this.key},Gn.prototype.getPrivateKey=function(){return this.getKey().getPrivateKey()},Gn.prototype.getPrivateKeyB64=function(){return this.getKey().getPrivateBaseKeyB64()},Gn.prototype.getPublicKey=function(){return this.getKey().getPublicKey()},Gn.prototype.getPublicKeyB64=function(){return this.getKey().getPublicBaseKeyB64()},e.JSEncrypt=Gn}(passport.lib.RSAExport),passport.lib.RSA=passport.lib.RSAExport.JSEncrypt;var passport=passport||window.passport||{};passport.err=passport.err||{},function(e){var t=null;t=\"function\"===(typeof e.getCurrent).toLowerCase()?e.getCurrent():{errMsg:{},labelText:{}},t.errMsg.login={\"-1\":{msg:'系统错误,请您稍后再试,<a href=\"http://passport.baidu.com/v2/?ucenterfeedback#{urldata}#login\"  target=\"_blank\">帮助中心</a>',field:\"\"},1:{msg:\"您输入的帐号格式不正确\",field:\"userName\"},2:{msg:'用户名或密码有误，请重新输入或<a href=\"http://passport.baidu.com/?getpassindex#{urldata}\"  target=\"_blank\" >找回密码</a>',field:\"userName\"},3:{msg:\"验证码不存在或已过期,请重新输入\",field:\"\"},4:{msg:'您输入的帐号或密码有误,<a href=\"http://passport.baidu.com/?getpassindex#{urldata}\"  target=\"_blank\" >忘记密码</a>？',field:\"password\"},5:{msg:\"\",field:\"\"},6:{msg:\"您输入的验证码有误\",field:\"verifyCode\"},7:{msg:'用户名或密码有误，请重新输入或<a href=\"http://passport.baidu.com/?getpassindex#{urldata}\"  target=\"_blank\" >找回密码</a>',field:\"password\"},16:{msg:'您的帐号因安全问题已被限制登录,<a href=\"http://passport.baidu.com/v2/?ucenterfeedback#{urldata}#login\"  target=\"_blank\" >帮助中心</a>',field:\"\"},257:{msg:\"请输入验证码\",field:\"verifyCode\"},100027:{msg:\"百度正在进行系统升级，暂时不能提供服务，敬请谅解\",field:\"\"},120016:{msg:\"\",field:\"\"},18:{msg:\"\",field:\"\"},19:{msg:\"\",field:\"\"},20:{msg:\"\",field:\"\"},21:{msg:\"没有登录权限\",field:\"\"},22:{msg:\"\",field:\"\"},23:{msg:\"\",field:\"\"},24:{msg:\"百度正在进行系统升级，暂时不能提供服务，敬请谅解\",field:\"\"},400031:{msg:\"请在弹出的窗口操作,或重新登录\",field:\"\"},400032:{msg:\"\",field:\"\"},400034:{msg:\"\",field:\"\"},401007:{msg:\"您的手机号关联了其他帐号，请选择登录\",field:\"\"},120021:{msg:\"登录失败,请在弹出的窗口操作,或重新登录\",field:\"\"},500010:{msg:\"登录过于频繁,请24小时后再试\",field:\"\"},200010:{msg:\"验证码不存在或已过期\",field:\"\"},100005:{msg:\"系统错误,请您稍后再试\",field:\"\"},120019:{msg:\"请在弹出的窗口操作,或重新登录\",field:\"userName\"},110024:{msg:'此帐号暂未激活,<a href=\"#{gotourl}\" >重发验证邮件</a>',field:\"\"},100023:{msg:'开启Cookie之后才能登录,<a href=\"http://passport.baidu.com/v2/?ucenterfeedback#{urldata}#login\"  target=\"_blank\" >如何开启</a>?',field:\"\"},17:{msg:\"您的帐号已锁定,请<a href='http://passport.baidu.com/v2/?ucenterfeedback#login_10' target='_blank'>解锁</a>后登录\",field:\"userName\"},400401:{msg:\"\",field:\"\"},400037:{msg:\"\",field:\"\"},50023:{msg:\"1个手机号30日内最多换绑3个账号\",field:\"\"},50024:{msg:\"注册过于频繁，请稍候再试\",field:\"\"},50025:{msg:\"注册过于频繁，请稍候再试；也可以通过上行短信的方式进行注册\",field:\"\"},50028:{msg:'帐号或密码多次输错，请3个小时之后再试或<a href=\"http://passport.baidu.com/?getpassindex&getpassType=financePwdError#{urldata}\"  target=\"_blank\">找回密码</a>',field:\"\"},50029:{msg:'帐号或密码多次输错，请3个小时之后再试或<a href=\"http://passport.baidu.com/?getpassindex&getpassType=pwdError#{urldata}\"  target=\"_blank\">找回密码</a>',field:\"\"},50030:{msg:\"抱歉，该手机号的申请次数已达当日上限，请更换手机号\",field:\"\"},50031:{msg:\"抱歉，该手机号的申请次数已达当月上限，请更换手机号\",field:\"\"},50032:{msg:\"抱歉，该手机号的申请次数已达本季度上限，请更换手机号\",field:\"\"},400413:{msg:\"\",field:\"\"},400414:{msg:\"\",field:\"\"},400415:{msg:\"帐号存在风险，为了您的帐号安全，请到百度钱包/理财/地图任一APP登录并完成验证，谢谢\",field:\"\"},400500:{msg:\"您登录的帐号已注销，请登录其他帐号或重新注册\",field:\"\"},72200:{msg:\"您的帐号因冻结暂时无法登录，请前往冻结时的手机APP，在登录页点击遇到问题进行解冻\",field:\"\"},96001:{msg:\"您的帐号因违反百度用户协议被限制登录\",field:\"\"}},t.errMsg.checkVerifycode={500002:{msg:\"您输入的验证码有误\",field:\"verifyCode\"},500018:{msg:\"验证码已失效，请重试\",field:\"verifyCode\"}},t.labelText.login={agree:\"阅读并接受\",baiduUserProtocal:\"《百度用户协议》\",verifyCode:\"验证码\",verifyCodeStaErr:\"您输入的验证码有误\",verifyCodeLenErr:\"您输入的验证码有误\",captcha:\"验证码\",captchaErr:\"您输入的动态密码有误,请重试\",captchaAlt:\"验证码图片\",captchaChange:\"换一张\",memberPassLabel:\"下次自动登录\",login:\"登录\",fgtPwd:\"登录遇到问题\",feedback:\"帮助中心\",register:\"立即注册\",phoneNum:\"手机号\",account:\"邮箱\",userName:\"手机/邮箱/用户名\",password:\"密码\",passwordResetWarnNo:'用户名或密码有误，请重新输入或<a href=\"http://passport.baidu.com/?getpassindex#{urldata}\"  target=\"_blank\" >找回密码</a>',passwordResetSms:'<a href=\"javascript:void(0)\" onclick=\"var smDom=document.getElementsByClassName(\\'pass-sms-btn\\');if(smDom.length>0){smDom[0].click();}\" >短信登录\\r\\n</a>,或者',passwordResetWarn:'用户名或密码有误，请重新输入或<a href=\"http://passport.baidu.com/?getpassindex#{urldata}\"  target=\"_blank\" >找回密码</a>',passwordResetIn:\"个月以内\",passwordResetOut:\"个月以前\",unameMailLengthError:\"邮箱过长,请重新输入\",unameInputError:\"邮箱格式错误,若未绑定邮箱,请使用用户名登录\",smsPhone:\"手机号\",smsPhoneMsg:\"请输入手机号\",smsVerifyCode:\"动态密码\",logining:\"登录中...\",loginsuccess:\"登录成功\",submitTimeup:\"登录超时,请稍后再试\",backToLogin:\"帐号密码登录\",qrcodeTitle:\"请使用<span>百度App</span>扫码登录\",qrcodeMsg:\"百度技术加密，保障您的隐私安全\",appName:\"百度App\",appHref:\"http://xbox.m.baidu.com/mo/\",sysError:\"系统错误，休息一会儿，请稍后再试\",sysUpdate:\"服务正在升级中,请您稍后再试\",cookieDisable:'开启Cookie之后才能登录,<a href=\"http://passport.baidu.com/v2/?ucenterfeedback#login\"  target=\"_blank\" >如何开启</a>?',captchaErr:\"动态密码错误\",confirmVerCodeEmpty:\"验证码为空\",foreignToLogin:\"帐号密码登录\",foreignMobileError:\"手机号码格式不正确\",foreignMobileMsg:\"海外手机号登录<span>请选择您的国家地区</span>\",foreignMobileLink:\"海外手机号\",QrcodeSuccessTip:\"扫描成功\",QrcodeSuccessMsg:\"请在手机端确认登录\",QrcodeErrorTip:\"网络连接失败\",QrcodeErrorMsg:\"请稍候再试\",QrcodeRefreshTip:\"二维码已失效\",QrcodeRefreshBtn:\"刷新二维码\",QrcodeLoadTip:\"二维码加载失败\"},e.getCurrent=function(){return t}}(passport.err);var passport=passport||window.passport||{};passport.data=passport.data||{},function(e){function t(e){this._requests=[],this._value=null,this._exception=null,this._isComplete=!1;var t=this;e(function(e){t._fulfillPromise(e)},function(e){t._breakPromise(e)})}function n(e,t,n){return t?n?function(n){return n=n||{},l.submit(d+t,i(n,e,g[e],h[e],!0),{charset:\"utf-8\",processData:function(t){if(t)for(var n in t)if(t.hasOwnProperty(n)){var i=t[n];i&&(t[n]=decodeURIComponent(i))}return s(e,t)}})}:function(n){return l.jsonp(d+t,i(n,e,g[e],h[e],!1),{charset:\"utf-8\",processData:function(t){return s(e,t)}})}:a}function i(e,t,n,i,s){var o=s?{staticpage:_.staticPage,charset:_.charset||document.characterSet||document.charset||\"\"}:{},r=f[t];if(r)for(var a in r){if(r.hasOwnProperty(a)){var l=r[a];o[a]=\"function\"==typeof l?l(e):l}\"verifypass\"==a&&(o[a]=decodeURIComponent(o[a]))}if(o.token=_.token,o.tpl=_.product||\"\",o.subpro=_.subpro,o.apiver=\"v3\",o.tt=(new Date).getTime(),e){n=n||{},i=i||{};for(var a in e)if(e.hasOwnProperty(a)){var d=i[a],u=d?d(e[a],e):e[a];\"string\"==typeof u&&(s&&(u=decodeURIComponent(u)),m[a]||(u=c.trim(u))),o[n[a]||a.toLowerCase()]=u}}return o}function s(t,n){if(e&&e.traceID&&e.traceID.getTraceID&&e.traceID.getTraceID(n),n){var i=v[t];i&&i(n);var s=n.errInfo,r=n,a=r;return s?r.errInfo=o(t,s,r):(s={no:n.err_no,msg:n.err_msg||\"\"},delete r.err_no,delete r.err_msg,a={data:r,errInfo:o(t,s,r)}),a}return n}function o(e,t){var n=y[b[e]||e];if(n&&t&&0!=t.no){var i=n[t.no]||n[-1];if(i){var s=i.msg;t.msg=s,t.field=i.field}}return t}function r(t){if(e&&e.traceID&&e.traceID.getTraceID&&e.traceID.getTraceID(t),t){var n=t.errInfo,i=t;if(!n)for(var s in t)if(t.hasOwnProperty(s)){var o=t[s];o&&(t[s]=decodeURIComponent(o))}n||(n={no:t.err_no,msg:t.err_msg||\"\"},delete i.err_no,delete i.err_msg,t={data:i,errInfo:n})}return t}var a=function(){};t.prototype={get_isComplete:function(){return this._isComplete},get_value:function(){if(!this._isComplete)return void 0;if(this._exception)throw this._exception;return this._value},call:function(e){for(var t=[],n=0,i=arguments.length-1;i>n;n++)t[n]=arguments[n+1];return this.when(function(n){return n[e].apply(n,t)})},getValue:function(e){return this.when(function(t){return t[e]})},setValue:function(e,t){this.whenOnly(function(n){n[e]=t})},when:function(e,n,i){return t.when(this,e,n,i)},whenOnly:function(e,n,i){t.whenOnly(this,e,n,i)},success:function(e,t){return this.when(e,a,t)},fail:function(e,t){return this.when(a,e,t)},_enqueueOne:function(e){this._isComplete?this._notify(e):this._requests.push(e)},_notify:function(e){this._exception?e.breakPromise&&e.breakPromise(this._exception):e.fulfillPromise&&e.fulfillPromise(this._value)},_notifyAll:function(){for(var e=0,t=this._requests.length;t>e;e++)this._notify(this._requests[e])},_fulfillPromise:function(e){this._value=e,this._exception=null,this._isComplete=!0,this._notifyAll()},_breakPromise:function(e){this._value=null,this._exception=e||new Error(\"An error occured\"),this._isComplete=!0,this._notifyAll()}},t.when=function(e,n,i,s){return new t(function(o,r){t.make(e)._enqueueOne({fulfillPromise:function(e){o(n?n.call(s,e):e)\n},breakPromise:function(e){if(i)try{o(i.call(s,e))}catch(t){r(t)}else r(e)}})})},t.whenOnly=function(e,n,i,s){t.make(e)._enqueueOne({fulfillPromise:function(e){n&&n.call(s,e)},breakPromise:function(e){i&&i.call(s,e)}})},t.make=function(e){return e instanceof t?e:t.immediate(e)},t.immediate=function(e){return new t(function(t){t(e)})};var c={};!function(e){var t=new RegExp(\"(^[\\\\s\\\\t\\\\xa0\\\\u3000]+)|([\\\\u3000\\\\xa0\\\\s\\\\t]+$)\",\"g\");e.trim=function(e){return String(e).replace(t,\"\")},e.getUniqueId=function(e){return e+Math.floor(2147483648*Math.random()).toString(36)},e.g=function(e){return e?\"string\"==typeof e||e instanceof String?document.getElementById(e):!e.nodeName||1!=e.nodeType&&9!=e.nodeType?null:e:null},e.getParent=function(t){return t=e.g(t),t.parentElement||t.parentNode||null},e.encodeHTML=function(e){return String(e).replace(/&/g,\"&amp;\").replace(/</g,\"&lt;\").replace(/>/g,\"&gt;\").replace(/\"/g,\"&quot;\").replace(/'/g,\"&#39;\")},e.array=e.array||{},e.array.indexOf=function(e,t,n){var i=e.length;for(n=0|n,0>n&&(n=Math.max(0,i+n));i>n;n++)if(n in e&&e[n]===t)return n;return-1},e.browser=e.browser||{},e.browser.opera=/opera(\\/| )(\\d+(\\.\\d+)?)(.+?(version\\/(\\d+(\\.\\d+)?)))?/i.test(navigator.userAgent)?+(RegExp.$6||RegExp.$2):void 0,e.insertHTML=function(t,n,i){t=e.g(t);var s,o;return t.insertAdjacentHTML&&!e.browser.opera?t.insertAdjacentHTML(n,i):(s=t.ownerDocument.createRange(),n=n.toUpperCase(),\"AFTERBEGIN\"==n||\"BEFOREEND\"==n?(s.selectNodeContents(t),s.collapse(\"AFTERBEGIN\"==n)):(o=\"BEFOREBEGIN\"==n,s[o?\"setStartBefore\":\"setEndAfter\"](t),s.collapse(o)),s.insertNode(s.createContextualFragment(i))),t}}(c),e.base=c;var l={};!function(n){var i=\"__bdpp_pstc__\"+(new Date).getTime(),s=i+\"_form\",o=i+\"_ifr\",r=function(e){if(\"object\"==typeof e){var t=[];for(var n in e){var i=e[n];if(void 0!==i&&null!==i){t.length&&t.push(\"&\");var s=encodeURIComponent(\"boolean\"==typeof i?i?\"1\":\"0\":i.toString());t.push(encodeURIComponent(n),\"=\",s)}}return t.join(\"\")}return\"string\"==typeof e?e:null},a=function(e,t){if(t=r(t),\"string\"==typeof t){var n=/\\?/g.test(e);e+=(n?\"&\":\"?\")+r(t)}return e},l=function(e,t,n){e.setAttribute(\"type\",\"text/javascript\"),n&&e.setAttribute(\"charset\",n),e.setAttribute(\"src\",t),document.getElementsByTagName(\"head\")[0].appendChild(e)},d=function(e){if(e.clearAttributes)e.clearAttributes();else for(var t in e)e.hasOwnProperty(t)&&delete e[t];e&&e.parentNode&&e.parentNode.removeChild(e),e=null},u=function(e,t,n){function i(e){return function(){try{e?u.onfailure&&u.onfailure():(t.apply(window,arguments),clearTimeout(o)),window[s]=null,delete window[s]}catch(n){}finally{d(r)}}}var s,o,r=document.createElement(\"SCRIPT\"),a=\"bd__cbs__\",u=n||{},p=u.charset,g=u.queryField||\"callback\",h=u.timeOut||0,f=new RegExp(\"(\\\\?|&)\"+g+\"=([^&]*)\");s=c.getUniqueId(a),window[s]=i(0),h&&(o=setTimeout(i(1),h)),e=e.replace(f,\"$1\"+g+\"=\"+s),e.search(f)<0&&(e+=(e.indexOf(\"?\")<0?\"?\":\"&\")+g+\"=\"+s),l(r,e,p)},p=function(e,t){var n=[];n.push(\"<form id='\",s,\"' target='\",o,\"' \"),n.push(\"action='\",c.encodeHTML(e),\"' method='post'>\");for(var i in t)if(t.hasOwnProperty(i)){var r=t[i];if(void 0!==r&&null!==r){var a=c.encodeHTML(\"boolean\"==typeof r?r?\"1\":\"0\":r);n.push(\"<input type='hidden' name='\",c.encodeHTML(i),\"' value='\",a,\"' />\")}}return n.push(\"</form>\"),n.join(\"\")},g=function(e,t,n,r){function a(e){return function(){try{e?r.onfailure&&r.onfailure():(n.apply(window,arguments),d&&clearTimeout(d)),window[u]=null,delete window[u]}catch(t){}}}r=r||{};var l=r.timeOut||0,d=!1,u=c.getUniqueId(\"bd__pcbs__\");t[r.queryField||\"callback\"]=\"parent.\"+u;var g=p(e,t);if(c.g(s))c.getParent(s).innerHTML=g;else{var h=[];h.push(\"<div id='\",i,\"' style='display:none;'>\"),h.push(\"<div>\",g,\"</div>\"),h.push(\"<iframe name='\",o,\"' src='\"+(\"https:\"==(window.location?window.location.protocol.toLowerCase():document.location.protocol.toLowerCase())?\"https://passport.baidu.com/passApi/html/_blank.html\":\"about:blank\")+\"' style='display:none;'></iframe>\"),h.push(\"</div>\"),c.insertHTML(document.body,\"beforeEnd\",h.join(\"\"))}window[u]=a(),l&&(d=setTimeout(a(1),l)),c.g(s).submit()};n.jsonp=function(n,i,s){return s=s||{},e&&e.traceID&&e.traceID.createTraceID&&(i.traceid=e.traceID.createTraceID()),new t(function(e,t){n=a(n,i),u(n,function(t){s.processData&&(t=s.processData(t)),e&&e(t)},{charset:s.charset,queryField:s.queryField,timeOut:s.timeOut,onfailure:function(){t&&t()}})})},n.submit=function(n,i,s){return e&&e.traceID&&e.traceID.createTraceID&&(i.traceid=e.traceID.createTraceID()),n&&i?new t(function(e){g(n,i,function(t){s.processData&&(t=s.processData(t)),e&&e(t)},s)}):void 0};var h=[];n.load=function(e){return new t(function(t){var n=h.push(new Image)-1,i=!1,s=setTimeout(function(){i=!0,t&&t()},1e3);h[n].onload=function(){clearTimeout(s),i||t&&t(),i=!0,h[n]=h[n].onload=null},h[n].src=e})}}(l);var d=\"https://passport.baidu.com\",u={getApiInfo:\"/v2/api/?getapi\",getLoginHistory:\"/v2/api/?loginhistory\",loginCheck:\"/v2/api/?logincheck\",getVerifyCodeStr:\"/v2/?reggetcodestr\",getRegSmsVerifyCodeStr:\"/v2/?regsmscodestr\",checkUserName:\"/v2/?regnamesugg\",checkPassword:\"/v2/?regpwdcheck\",checkMail:\"/v2/?regmailcheck\",isUserNoName:\"/v2/api/?ucenteradduname\",checkPhone:\"/v2/?regphonecheck\",getphonestatus:\"/v2/?getphonestatus\",sendPhoneCode:\"/v2/?regphonesend\",multiBind:\"/v2/?multiaccountassociate\",multiUnbind:\"/v2/?multiaccountdisassociate\",multiCheckUserName:\"/v2/?multiaccountusername\",multiGetaccounts:\"/v2/?multiaccountget\",multiSwitchuser:\"/v2/?loginswitch\",checkVerifycode:\"/v2/?checkvcode\",getRsaKey:\"/v2/getpublickey\",authwidGetverify:\"/v2/sapi/authwidgetverify\",checkIDcard:\"/v3/finance/main/idnumcert\",checkIDcardSecondStep:\"/v3/finance/main/upcert\",checkIDcardAllStep:\"/v3/finance/main/idnumcert\",checkIDcardState:\"/v3/finance/main/checkupcert\"},p={login:\"/v2/api/?login\",reg:\"/v2/api/?reg\",fillUserName:\"/v2/api/?ucenteradduname\",regPhone:\"/v2/api/?regphone\",checkIDcard:\"/v3/finance/main/idnumcert\",checkIDcardSecondStep:\"/v3/finance/main/upcert\",checkIDcardAllStep:\"/v3/finance/main/idnumcert\"},g={getApiInfo:{apiType:\"class\"},login:{memberPass:\"mem_pass\",safeFlag:\"safeflg\",isPhone:\"isPhone\",timeSpan:\"ppui_logintime\",logLoginType:\"logLoginType\"},fillUserName:{selectedSuggestName:\"pass_fillinusername_suggestuserradio\",timeSpan:\"ppui_fillusernametime\"},reg:{password:\"loginpass\",timeSpan:\"ppui_regtime\",suggestIndex:\"suggestIndex\",suggestType:\"suggestType\",selectedSuggestName:\"pass_reg_suggestuserradio_0\",logRegType:\"logRegType\"},regPhone:{password:\"loginpass\",timeSpan:\"ppui_regtime\",suggestIndex:\"suggestIndex\",suggestType:\"suggestType\",selectedSuggestName:\"pass_reg_suggestuserradio_0\",logRegType:\"logRegType\"}},h={loginCheck:{isPhone:function(e){return e?\"true\":\"false\"}},login:{memberPass:function(e){return e?\"on\":\"\"}}},f={checkPassword:{fromreg:1},reg:{registerType:1,verifypass:function(e){return e.password}}},m={password:!0},v={login:function(){}},b={checkUserName:\"reg\",checkMail:\"reg\",checkPhone:\"regPhone\",sendPhoneCode:\"regPhone\",multiCheckUserName:\"multiBind\",multiSwitchuser:\"changeUser\",checkVerifycode:\"checkVerifycode\"},y=passport.err.getCurrent().errMsg||passport.err.getCurrent(),_={};e.setContext=function(e){_.product=e.product||_.product,_.charset=e.charset||_.charset,_.staticPage=e.staticPage||_.staticPage,_.token=e.token||_.token,_.subpro=e.subpro||_.subpro},e.traceID={headID:e.traceID&&e.traceID.headID||\"\",flowID:e.traceID&&e.traceID.flowID||\"\",cases:e.traceID&&e.traceID.cases||\"\",initTraceID:function(e){var t=this;e&&e.length>0?(t.headID=e.slice(0,6),t.flowID=e.slice(6,8)):t.destory()},createTraceID:function(){var e=this;return e.headID+e.flowID+e.cases},startFlow:function(e){var t=this,n=t.getFlowID(e);0===t.flowID.length||t.flowID===n?(t.createHeadID(),t.flowID=n):t.finishFlow(n)},finishFlow:function(){var e=this;e.destory()},getRandom:function(){return parseInt(90*Math.random()+10,10)},createHeadID:function(){var e=this,t=(new Date).getTime()+e.getRandom().toString(),n=Number(t).toString(16),i=n.length,s=n.slice(i-6,i).toUpperCase();e.headID=s},getTraceID:function(e){var t=this,n=e&&e.traceid||\"\";t.initTraceID(n)},getFlowID:function(e){var t={login:\"01\",reg:\"02\"};return t[e]},setData:function(e){var t=this;return e.data?e.data.traceid=t.createTraceID():e.url=e.url+(e.url.indexOf(\"?\")>-1?\"&\":\"?\")+\"traceid=\"+t.createTraceID(),e},destory:function(){var e=this;e.headID=\"\",e.flowID=\"\"}};for(var E in u)u.hasOwnProperty(E)&&(e[E]=n(E,u[E]));for(var E in p)p.hasOwnProperty(E)&&(e[E]=n(E,p[E],!0));e.jsonp=function(e,t){return 0!=e.indexOf(\"http\")&&(e=d+e),t=t||{},t.flag_code&&1==t.flag_code||(t.apiver=\"v3\"),t.tt=(new Date).getTime(),l.jsonp(e,t,{charset:\"utf-8\",processData:function(e){return r(e)}})},e.post=function(e,t){return t=t||{},e=\"wap\"==t.apitype?e:d+e,t.staticpage=t.staticpage||_.staticPage,t.charset=t.charset||_.charset||document.characterSet||document.charset||\"\",t.token=t.token||_.token,t.tpl=t.tpl||_.product,l.submit(e,t,{charset:\"utf-8\",processData:function(e){return r(e)}})},e.request=l}(passport.data);var passport=passport||window.passport||{};passport.analysis=passport.analysis||{},function(e){var t=function(e,t){var n=e.config.diaPassLogin?\"dialogLogin\":\"basicLogin\",i=e.config.loginMerge?1:0,s=e.config.product||\"isnull\",o=window.location?window.location.protocol.toLowerCase():document.location.protocol.toLowerCase(),r=\"\",a=\"&tt=\"+(new Date).getTime(),c=e.guideRandom?e.guideRandom:\"\";for(var l in t)r=r+\"&\"+l+\"=\"+t[l];if(\"http:\"==o)var d=\"http://nsclick.baidu.com/v.gif?pid=111&url=&logintype=\"+n+\"&gid=\"+c+\"&merge=\"+i+\"&tpl=\"+s+r+a;else if(\"https:\"==o)var d=\"https://passport.baidu.com/img/v.gif?logintype=\"+n+\"&gid=\"+c+\"&merge=\"+i+\"&tpl=\"+s+r+a;if(d){var u=new Image;u.onload=u.onerror=function(){u.onload=u.onerror=null,u=null},u.src=d}};e.login={render:function(e){t(e,{type:\"firstrender\",loginurl:encodeURIComponent(document.location.href)}),baidu(e.getPhoenixElement(\"pass_phoenix_list_login\")).on(\"click\",function(n){var i,s=baidu(n.target);if(s&&s.attr(\"title\")){switch(s.attr(\"title\")){case\"普通登录\":i=\"normal\";break;case\"二维码登录\":i=\"qrcode\";break;case\"短信登录\":i=\"sms\";break;case\"QQ帐号\":i=\"qq\";break;case\"新浪微博\":i=\"weibo\";break;case\"人人网\":i=\"renren\";break;case\"腾讯微博\":i=\"tqq\";break;case\"飞信\":i=\"fetion\";break;case\"微信\":i=\"weixin\";break;case\"天翼\":i=\"tianyi\"}t(e,{phoenix:i})}});var n=(e.getElement(),e.getElement(\"form\"));baidu(n).on(\"submit\",function(){e.loginfirstsubmit||(e.loginfirstsubmit=!0,t(e,{type:\"loginfirstsubmit\"}))})},changeLoginType:function(e,n){t(e,{type:\"changelogintype\",logintype:n&&n.loginType||\"\"})},fieldFocus:function(e,n){n.ele.get(0).id!=e.$getId(\"smsPhone\")&&n.ele.get(0).id!=e.$getId(\"smsVerifyCode\")||e.smsloginfirstlog?e.loginfirstlog||(e.loginfirstlog=!0,t(e,{type:\"loginfirst\"})):(e.smsloginfirstlog=!0,t(e,{type:\"smsloginfirst\"}))},loginSuccess:function(e){t(e,{type:\"loginsuccess\"})},loginError:function(){},validateError:function(e,n){return n.validate&&t(e,{errno:encodeURIComponent(n.validate.msg),type:\"loginerrno\"}),{preventEvent:!1,preventDefault:!1}},fieldKeyup:function(e){e.KEYUPFLAG||(t(e,{type:\"typein\"}),e.KEYUPFLAG=!0)}}}(passport.analysis);var passport=passport||window.passport||{};return passport.hook=passport.hook||{},function(e){function t(e){var t,n,i=this,s={120016:{isLogin:!1,msg:\"您的帐号存在安全风险，我们已经为您采取保护策略，建议您先绑定手机。\"},400032:{isLogin:!0,msg:\"快来绑定密保工具吧，提升帐号安全性的同时可以快速找回密码。\"},400034:{isLogin:!1,msg:{phone:\"请绑定您的手机号码作为您的密保手机，提升帐号安全性的同时还可以快速找回密码。\",email:\"请绑定一个您的常用邮箱作为您的密保邮箱，提升帐号安全性的同时还可以快速找回密码。\"}}}[e.errno],o=e.args,r=e.title,a=s.msg,c=(e.auth_title,e.auth_msg,s.isLogin),l=e.cfg,d=function(e,t,n){var i=t.args,s={action:t.type||\"init\",u:e.config.u,tpl:e.config.product,ltoken:i.rsp.data.ltoken,lstr:i.rsp.data.lstr};e.REQUESTBINDTOKENURL=\"/v2/?loginspmbindsecureinfo\",passport.data.jsonp(\"https://passport.baidu.com\"+e.REQUESTBINDTOKENURL,s).success(function(t){0==t.errInfo.no?n&&n({bindEmailToken:t.data.bindEmailToken,bindMobileToken:t.data.bindMobileToken,authsid:t.data.authsid,loginproxy:t.data.loginproxy,otherValue:s}):alert(e.lang.sysError)})},u=function(e){var t=\"string\"==(typeof a).toLowerCase()?a:a.email;return t+=c?\"您可以<a class='bindLink bindJumpEmail'>跳过此步骤</a>或<a class='bindLink bindPhoneBtn'>绑定手机</a>。\":\"您也可以<a class='bindLink bindPhoneBtn'>绑定手机</a>。\",passport.pop.ArmorWidget(\"bindemail\",{token:e.bindEmailToken,authsid:e.authsid,title:r||\"绑定密保邮箱\",otherValue:e.otherValue,msg:t,subpro:i.config.subpro,traceid:e.traceid,onSubmitSuccess:function(e){var e=e;d(i,{args:o,type:\"check\"},function(t){e&&e.hide&&e.hide(),o.isCompleted=!0,t.loginproxy?passport.data.jsonp(t.loginproxy).success(function(e){l.onCompleted&&l.onCompleted(e,function(){l.onCancel&&l.onCancel(o)})}):l.onCancel&&l.onCancel(o)})},onRender:function(){var e=this;baidu(\".bindPhoneBtn\").on(\"click\",function(){e.close(),n.show()}),baidu(\".bindJumpEmail\").on(\"click\",function(t){t.preventDefault(),e.close(),o.isCompleted=!0,l.onCancel&&l.onCancel(o)}),baidu(\"#\"+e.getId(\"header_a\")).on(\"click\",function(){c&&(o.isCompleted=!0,l.onCancel&&l.onCancel(o))})}})},p=function(e){var n=\"string\"==(typeof a).toLowerCase()?a:a.phone;return c&&e.bindEmailToken?n+=\"您可以<a class='bindLink bindJumpPhone'>跳过此步骤</a>或<a class='bindLink bindEmailBtn'>绑定密保邮箱</a>。\":e.bindEmailToken&&(n+=\"您也可以<a class='bindLink bindEmailBtn'>绑定密保邮箱</a>。\"),passport.pop.ArmorWidget(\"bindmobile\",{token:e.bindMobileToken,authsid:e.authsid,title:r||\"绑定手机\",otherValue:e.otherValue,msg:n,bindToLogin:1,apiMargicInstance:i,subpro:i.config.subpro,traceid:e.traceid,onSubmitSuccess:function(e){var e=e;d(i,{args:o,type:\"check\"},function(t){e&&e.hide&&e.hide(),o.isCompleted=!0,t.loginproxy?passport.data.jsonp(t.loginproxy).success(function(e){l.onCompleted&&l.onCompleted(e,function(){l.onCancel&&l.onCancel(o)})}):l.onCancel&&l.onCancel(o)})},onRender:function(n){var n=this;baidu(\".bindEmailBtn\").on(\"click\",function(i){i.preventDefault(),n.close(),t=t||u(e),t.show()}),baidu(\".bindJumpPhone\").on(\"click\",function(e){e.preventDefault(),n.close(),o.isCompleted=!0,l.onCancel&&l.onCancel(o)}),baidu(\"#\"+n.getId(\"header_a\")).on(\"click\",function(){c&&(o.isCompleted=!0,l.onCancel&&l.onCancel(o))})},onBindToLoginFn:function(e,t){t&&t.mobile&&(i.config.sms?(i.getElement(\"smsPhone_placeholder\")&&i.$hide(\"smsPhone_placeholder\"),i.getElement(\"smsPhone\")&&(i.getElement(\"smsPhone\").value=t.mobile),i.getElement(\"smsVerifyCode\")&&(i.getElement(\"smsVerifyCode\").value=\"\",i.getElement(\"smsVerifyCode\").focus())):(i.getElement(\"userName_placeholder\")&&i.$hide(\"userName_placeholder\"),i.getElement(\"userName\")&&(i.getElement(\"userName\").value=t.mobile),i.getElement(\"password\")&&(i.getElement(\"password\").value=\"\",i.getElement(\"password\").focus())))}})};d(i,{args:o,type:\"init\"},function(e){passport._use(C,y[C],function(){e.bindMobileToken?(n=p(e),n.show()):e.bindEmailToken?(t=u(e),t.show()):alert(i.lang.sysError)})})}function n(e){var t,n,i=this,s=e.rspData,o=e.cfg,r=e.args,a=function(e){var e=e||\"系统检测到您的帐号疑似被盗，存在安全风险。请尽快修改密码。\";return'<div class=\"passport-forceverify-risk\"><p class=\"passport-forceverify-risk-msg\">'+e+'</p><div  class=\"passport-forceverify-risk-con clearfix\"><a class=\"passport-forceverify-risk-next\" id=\"passport_forceverify_risk_next\" href=\"###\">下次提醒</a><a class=\"passport-forceverify-risk-btn\" href=\"http://passport.baidu.com/v2/account/password\" target=\"_blank\" >立即修改</a></div></div>'};if(s&&s.secstate)switch(s.secstate){case\"PA001\":n=\"您的帐号密码输入错误次数达到上限，为保障帐号安全，登录前需验证身份。\";break;case\"PA002\":n=\"您的网络环境存在安全风险，为保障帐号安全，登录前需验证身份。\";break;case\"PA003\":n=\"您的帐号长时间未登录，为保障帐号安全，登录前需验证身份。\";break;case\"risk\":t=a(),n=\"您的帐号可能存在安全隐患，为保障您的帐号安全，登录前需验证身份。\";break;case\"cheat\":n=\"您的帐号因批量或者使用非法软件注册被冻结，登录前需验证身份。\";break;case\"PC001\":n=\"您操作频度过于频繁，为保障帐号安全，登录前需验证身份。\";break;case\"PX008\":n=\"您本次的登录地存在异常，为保障本次操作安全，登录前需验证身份。\";break;default:n=\"您的帐号存在安全风险，为保障帐号安全，登录前需验证身份。\"}var c={400031:{title:\"登录保护\",msg:\"您已开启登录保护功能，为保障帐号安全，登录前需验证身份。\"},5:{title:\"登录安全验证\",msg:\"您的网络环境存在安全风险，为保障帐号安全，登录前需验证身份。\",onSuccess:function(e,t){var n=s.gotourl+\"&authsid=\"+t.authsid;passport.data.jsonp(n).success(function(t){i._ownerDialog&&i._ownerDialog.show(),e.hide(),i.getElement(\"error\").innerHTML=0==t.errInfo.no||0==t.data.errno?'请重新登录，或<a href=\"https://passport.baidu.com/?getpass_index\" target=\"_blank\">找回密码</a>':i.lang.sysError})},onGetapiError:function(){i.getElement(\"error\").innerHTML=\"您所处的网络存在安全风险，请切换网络重试\"}},400023:{title:\"登录安全验证\",msg:\"您的网络环境存在安全风险，为保障帐号安全，登录前需验证身份。\",onSuccess:function(e,t){var n=\"https://passport.baidu.com/v3/login/main/qrbdusslogin?tt=\"+(new Date).getTime(),a={authsid:t.authsid,bduss:s.bdusssign,u:encodeURIComponent(s.u),loginVersion:\"v4\",tpl:i.config.product};passport.data.jsonp(n,a).success(function(t){e.hide(),0==t.errInfo.no||0==t.data.errno?(r.isCompleted=!0,o.onCompleted&&o.onCompleted(t,function(){o.onCancel&&o.onCancel(r)})):i.getElement(\"error\").innerHTML=i.lang.sysError})},onGetapiError:function(){i.getElement(\"error\").innerHTML=\"您所处的网络存在安全风险，请切换网络重试\"}},120019:{title:\"登录解冻验证\",msg:\"您的帐号因密码输入错误次数过多，为保障帐号安全，登陆前需验证身份。\",onSuccess:function(e,t){var n=s.gotourl+\"&authsid=\"+t.authsid;passport.data.jsonp(n).success(function(t){i._ownerDialog&&i._ownerDialog.show(),e.hide(),i.getElement(\"error\").innerHTML=0==t.errInfo.no||0==t.data.errno?'请重新登录，或<a href=\"https://passport.baidu.com/?getpass_index\" target=\"_blank\">找回密码</a>':i.lang.sysError})},onGetapiError:function(){i.getElement(\"error\").innerHTML='登录密码错误已达上限，您可以<a href=\"https://passport.baidu.com/?getpass_index\" target=\"_blank\">找回密码</a>或3小时后再试'}},120021:{title:\"安全验证\",msg:n,defaultHTML:t,onSuccess:function(e){return passport.data.jsonp(s.loginproxy).success(function(n){e.show(),0==n.errInfo.no?(r.isCompleted=!0,t?(e.getElement(\"article\").innerHTML=t,baidu(e.getElement(\"header_a\")).on(\"click\",function(){e.hide(),o.onCompleted&&o.onCompleted(n,function(){o.onCancel&&o.onCancel(r)})}),baidu(document.getElementById(\"passport_forceverify_risk_next\")).on(\"click\",function(){e.hide(),o.onCompleted&&o.onCompleted(n,function(){o.onCancel&&o.onCancel(r)})})):(e.hide(),o.onCompleted&&o.onCompleted(n,function(){o.onCancel&&o.onCancel(r)}))):alert(i.lang.sysError)}),!1},onRender:function(e){document.getElementById(\"passport_forceverify_risk_appeal\")&&(document.getElementById(\"passport_forceverify_risk_appeal\").href=e.url_forgot)}},riskCheat:{token:\"risk\",title:\"安全验证\",msg:n,defaultHTML:t,onRender:function(e){baidu(document.getElementById(\"passport_forceverify_risk_next\")).on(\"click\",function(){e.hide(),o.onCancel&&o.onCancel()}),document.getElementById(\"passport_forceverify_risk_appeal\")&&(document.getElementById(\"passport_forceverify_risk_appeal\").href=e.url_forgot)}}}[e.errno];passport._use(E,y[E],function(){forceverifyLoginverify=passport.pop.Forceverify({token:s.authtoken,title:c.title,msg:c.msg,subpro:i.config.subpro,u:s.u||\"\",lstr:s.lstr||\"\",ltoken:s.ltoken||\"\",tpl:s.tpl||\"\",traceid:s.traceid,onRender:function(e){c.onRender&&c.onRender(e)},onSubmitSuccess:function(e,t){if(\"1\"===s.realnameverifyemail)return s.realnameauthsid=t.authsid,void d.apply(i,[{args:r,rspData:s,cfg:o}]);if(c.onSuccess)return void c.onSuccess(e,t);var n=s.loginproxy;passport.data.jsonp(n).success(function(t){0==t.errInfo.no||0==t.data.errno?(e.hide(),r.isCompleted=!0,o.onCompleted&&o.onCompleted(t,function(){o.onCancel&&o.onCancel(r)})):(e.hide(),i._ownerDialog&&i._ownerDialog.show(),i.getElement(\"error\").innerHTML=i.lang.sysError)})},onGetapiError:function(e){return i._ownerDialog&&i._ownerDialog.show(),c.onGetapiError?void c.onGetapiError(e):void(i.getElement(\"error\").innerHTML=i.lang.sysError)},onHide:function(){o.onCancel&&o.onCancel(),i.config.loginMerge&&i.getElement(\"isPhone\")&&(i.getElement(\"isPhone\").value=\"\")}},!0)})}function i(e){for(var t=this,n=e.rspData,i=[],s=n.accounts.split(\";\"),o=0;o<s.length;o++){var r=s[o].split(\",\");i.push({username:r[0],portrait:r[1]})}passport._load(b+y[_],!0,function(){var e=passport.pop.init({type:\"loginMultichoice\",tangram:!0,apiOpt:{phone:n.userName,userList:i},onChoicedUser:function(n,i){e.hide(),t._ownerDialog&&t._ownerDialog.show(),t.getElement(\"userName\").value=i.username,t.getElement(\"isPhone\").value=\"false\",t.config.loginMerge&&t.getElement(\"loginMerge\")&&(t.getElement(\"loginMerge\").value=\"\"),\"sms\"==t.currentLoginType?(t.getElement(\"smsHiddenFields_switchuname\").value=i.username,t._submitSmsForm()):(t.config.loginMerge||(t._collectData(),t.switchTo(\"normal\"),t._restoreData(\"phone\")),t.submit())},onHide:function(){t.getElement(\"userName\").value=n.userName,t.getElement(\"isPhone\").value=\"\"}});e.show()})}function s(e){var t=this,n=t.$getId(\"pass_b2c_swf\"),i=e.args.rsp.data,s=I(),o=0;i&&i.bckv&&(o=parseInt(i.bckv,10)>0);var r=null;if(passport.CONSTANT=passport.CONSTANT||{},passport.CONSTANT.b2c_getlogin=function(){},passport.CONSTANT.b2c_setlogin=function(){var e={kv:i.bckv,sync:i.bcsync,checksum:i.bcchecksum,time:i.bctime};try{if(r){var t=r.get_movie(n,\"b2c_setlogin\").b2c_setlogin(e);try{var s=document.createElement(\"script\");s.type=\"text/javascript\",s.src=[b,\"/v2/b2c-stable?\",\"from=setlogin.done\",\"&checksum=\",e.checksum,\"&time=\",e.time,\"&status=\",encodeURIComponent(t)].join(\"\"),document.getElementsByTagName(\"head\")[0].appendChild(s)}catch(o){}}}catch(o){try{var s=document.createElement(\"script\");s.type=\"text/javascript\",s.src=[b,\"/v2/b2c-stable?\",\"from=setlogin.fail\",\"&msg=\",encodeURI(o.message)].join(\"\"),document.getElementsByTagName(\"head\")[0].appendChild(s)}catch(o){}}},t.getElement(\"pass_b2c\")&&s.isexists&&o){var a=function(e){var t=function(e){e=e||{};var t,n,i,s,o={},r=function(e){return e.replace(/&/g,\"&amp;\").replace(/</g,\"&lt;\").replace(/>/g,\"&gt;\").replace(/\"/g,\"&quot;\").replace(/'/g,\"&#39;\")};for(n in e)o[n]=e[n];e=o;var a=e.vars,c=[\"classid\",\"codebase\",\"id\",\"width\",\"height\",\"align\"];if(e.align=e.align||\"middle\",e.classid=\"clsid:d27cdb6e-ae6d-11cf-96b8-444553540000\",e.codebase=\"https://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0\",e.movie=e.url||\"\",delete e.vars,delete e.url,\"string\"==typeof a)e.flashvars=a;else{var l=[];for(n in a)s=a[n],l.push(n+\"=\"+encodeURIComponent(s));e.flashvars=l.join(\"&\")}var d=[\"<object \"];for(t=0,i=c.length;i>t;t++)s=c[t],d.push(\" \",s,'=\"',r(e[s]),'\"');d.push(\">\");var u={wmode:1,scale:1,quality:1,play:1,loop:1,menu:1,salign:1,bgcolor:1,base:1,allowscriptaccess:1,allownetworking:1,allowfullscreen:1,seamlesstabbing:1,devicefont:1,swliveconnect:1,flashvars:1,movie:1};for(n in e)s=e[n],n=n.toLowerCase(),u[n]&&(s||s===!1||0===s)&&d.push('<param name=\"'+n+'\" value=\"'+r(s)+'\" />');e.src=e.movie,e.name=e.id,delete e.id,delete e.movie,delete e.classid,delete e.codebase,e.type=\"application/x-shockwave-flash\",e.pluginspage=\"https://www.macromedia.com/go/getflashplayer\",d.push(\"<embed\");var p;for(n in e)if(s=e[n],s||s===!1||0===s){if(new RegExp(\"^salign$\",\"i\").test(n)){p=s;continue}d.push(\" \",n,'=\"',r(s),'\"')}return p&&d.push(' salign=\"',r(p),'\"'),d.push(\"></embed></object>\"),d.join(\"\")},n=function(e){e=e||{};var n=document.createElement(\"div\");n.innerHTML=t(e),n.style.display=\"none\",document.getElementsByTagName(\"body\")[0].appendChild(n)},i=/msie (\\d+\\.\\d+)/i.test(navigator.userAgent)?document.documentMode||+RegExp.$1:void 0;return(i>7||!i)&&n(e),{get_movie:function(e,t){var n=document[e];if(9===document.documentMode&&n&&n.length)for(var i=n.length,s=0;i>s;s++){var o=n[s];if(\"embed\"===o.tagName.toLowerCase()){n=o;break}}return t&&\"function\"!=typeof n[t]&&(n=document.getElementById(e)),n}}};try{var c=window.location.protocol.toLowerCase();r=a({id:n,width:\"1\",height:\"1\",url:c+\"//passport.baidu.com/passApi/swf/b2c.swf?_t=\"+Math.random(),allowscriptaccess:\"always\"})}catch(l){}}passport.data.request.load(b+\"/v2/b2c-flash?isexists=\"+encodeURIComponent(s.isexists)+\"&ver=\"+encodeURIComponent(s.ver)+\"&filename=\"+encodeURIComponent(s.filename))}function o(e){var t=this,n=e.rspData,i=e.args.rsp.data;return t.rebindGuideWidget?void t.rebindGuideWidget.show():void passport.use(\"uni_rebindGuide\",{tangram:!0},function(){t.rebindGuideWidget=new passport.pop.rebindGuideWidget({color:t.config.color||\"blue\",apiOpt:i,rebindType:\"rebindPhone\",onrebindGuideCompleted:function(){T(t,n)}}),t.rebindGuideWidget.show()})}function r(e){var t=this,n=e.cfg,i=e.args,s=e.rspData.rsp.data||{};passport._load(b+y[_],!0,function(){h?(h.setMakeOption&&h.setMakeOption(s.authsid,s.bdstoken),h.show()):(h=passport.pop.init({type:\"accSetPwd\",tangram:!0,color:t.config.color||\"blue\",apiOpt:{u:t.config.u,product:t.config.product,authsid:s.authsid||\"\",bdstoken:s.bdstoken||\"\",staticPage:t.config.staticPage},onHide:function(){\"1\"!=s.setpwdswitch&&(i.isCompleted=!0,n.onCancel&&n.onCancel(i))},onSubmitSuccess:function(){i.isCompleted=!0,i&&i.rsp&&i.rsp.errInfo&&(i.rsp.errInfo.no=\"0\"),s.hao123Param&&D(s.hao123Param,t),h.hide(),n.onCancel&&n.onCancel(i)}}),h.show())})}function a(e){var t=this,n=e.cfg,i=e.args,s=e.rspData.rsp.data||{};passport._load(b+y[_],!0,function(){f?(f.setMakeOption&&f.setMakeOption(s.authsid,s.bdstoken),f.show()):(f=passport.pop.init({type:\"accSetPwd\",tangram:!0,color:t.config.color||\"blue\",jumpset:\"1\"==s.jumpset?1:0,apiOpt:{u:t.config.u,product:t.config.product,authsid:s.authsid||\"\",bdstoken:s.bdstoken||\"\",username:1,staticPage:t.config.staticPage},onHide:function(){\"1\"==s.jumpset&&(i.isCompleted=!0,n.onCancel&&n.onCancel(i))},onSubmitSuccess:function(){i.isCompleted=!0,i&&i.rsp&&i.rsp.errInfo&&(i.rsp.errInfo.no=\"0\"),s.hao123Param&&D(s.hao123Param,t),f.hide(),n.onCancel&&n.onCancel(i)}}),f.show())})}function c(e){var t=this,n=e.cfg,i=e.args,s=e.rspData.rsp.data||{},o=\"400413\"===i.rsp.errInfo.no&&\"sms\"===e.rspData.rsp.loginType?\"1\":\"0\";passport._load(b+y[_],!0,function(){v?(v.reRender&&v.reRender({lstr:s.lstr||\"\",ltoken:s.ltoken||\"\",token:s.authtoken||\"\",loginproxy:s.loginproxy||\"\",select:o,loginType:e.rspData.rsp.loginType}),v.show()):(v=passport.pop.init({type:\"secondCardVerify\",tangram:!0,color:t.config.color||\"blue\",apiOpt:{u:t.config.u,product:t.config.product,lstr:s.lstr||\"\",ltoken:s.ltoken||\"\",token:s.authtoken||\"\",staticPage:t.config.staticPage,select:o,loginType:e.rspData.rsp.loginType,loginproxy:s.loginproxy||\"\"},onloginSuccess:function(){i.isCompleted=!0,i&&i.rsp&&i.rsp.errInfo&&(i.rsp.errInfo.no=\"0\"),s.hao123Param&&D(s.hao123Param,t),v.hide(),n.onCancel&&n.onCancel(i)},onSubmitSuccess:function(e,n){n.rsp.data.loginproxy&&passport.data.jsonp(n.rsp.data.loginproxy).success(function(e){\"0\"===e.errInfo.no?document.location.href=\"https://passport.baidu.com/v3/security/main/secondcardmodifyaccinfo?tpl=\"+t.config.product+\"&bdstoken=\"+n.rsp.data.bdstoken+\"&authsid=\"+n.rsp.data.mod_authsid+\"&u=\"+encodeURIComponent(e.data.u)+\"&loginType=\"+n.rsp.data.loginType+\"&hasUsername=\"+n.rsp.data.hasUsername:alert(t.lang.sysError)})}}),v.show())})}function l(e){var t=this;e.rspData=e.rspData||{},passport._load(b+y[w],!0,function(){m?m.setToken(e.rspData.token,function(){m.show()}):(m=passport.pop.init({type:\"accConnect\",tangram:!0,color:t.config.color||\"\",apiOpt:{u:t.config.u,adtext:e.rspData.adtext,product:t.config.product,token:e.rspData.token,staticPage:t.config.staticPage},onConnectSuccess:function(e){var n=e.rsp;n.connect=m,T(t,{rsp:n}),e.returnValue=!1}}),m.show())})}function d(e){var t=this,n=e.cfg,i=e.args;e.rspData=e.rspData||{},passport._load(b+y[_],!0,function(){g?g.show():(g=passport.pop.init({type:\"accRealName\",tangram:!0,color:t.config.color||\"\",apiOpt:{u:t.config.u,product:t.config.product,staticPage:t.config.staticPage,action:\"login\",realnameswitch:e.rspData.realnameswitch,authsid:e.rspData.realnameauthsid,ltoken:e.rspData.ltoken,lstr:e.rspData.lstr,cu:e.rspData.u,overseas:t.config.overseas},onHide:function(){t.fire(\"RealHide\",i),\"1\"!=e.rspData.realnameswitch&&(i.isCompleted=!0,n.onCancel&&n.onCancel(i))},onverifyHide:function(s){t.realLoginHide||(e.rspData.loginproxy&&s?passport.data.jsonp(e.rspData.loginproxy+\"&authsid=\"+s).success(function(e){0==e.errInfo.no?(i.isCompleted=!0,n.onCompleted&&n.onCompleted(e,function(){n.onCancel&&n.onCancel(i)})):alert(t.lang.sysError)}):(i.isCompleted=!0,e.rspData.hao123Param&&\"1\"==e.rspData.realnameswitch&&D(e.rspData.hao123Param,t),n.onCancel&&n.onCancel(i)))},onSubmitSuccess:function(s,o){e.rspData.loginproxy&&o.rsp.data.authsid?passport.data.jsonp(e.rspData.loginproxy+\"&authsid=\"+o.rsp.data.authsid).success(function(e){0==e.errInfo.no?(i.isCompleted=!0,t.realLoginHide=!0,g.hide(),n.onCompleted&&n.onCompleted(e,function(){n.onCancel&&n.onCancel(i)})):alert(t.lang.sysError)}):(i.isCompleted=!0,i&&i.rsp&&i.rsp.errInfo&&(i.rsp.errInfo.no=\"0\"),e.rspData.hao123Param&&\"1\"==e.rspData.realnameswitch&&D(e.rspData.hao123Param,t),t.realLoginHide=!0,g.hide(),n.onCancel&&n.onCancel(i))}}),g.show())})}function u(e,s,u){function g(t){var n=new Image;n.onload=n.onerror=function(){n.onload=n.onerror=null,n=null},n.src=b+\"/img/v.gif?type=\"+t+\"&tt=\"+(new Date).getTime(),s.isCompleted=!0,f.hao123Param&&D(f.hao123Param,e),y.confirmWidgetMobileSure.hide(),u.onCancel&&u.onCancel(s)}var h=s.rsp.errInfo.no,f=s.rsp.data,u=u||{},m=f&&(\"risk\"==f.secstate||\"cheat\"==f.secstate);if(f&&f.connectType&&e.config.connect){var v=e.fire(\"beforeWarning\",{args:s});if(!v)return;return e.getElement(\"error\").innerHTML=\"\",e._ownerDialog&&e._ownerDialog.hide(\"unHide\"),p(b+\"/passApi/css/uni_accConnect_ab6dda9.css\"),l.apply(e,[{args:s,rspData:f,cfg:u,errno:h}]),!1}if(18==h)return e.getElement(\"error\").innerHTML=\"\",e._ownerDialog&&e._ownerDialog.hide(\"unHide\"),d.apply(e,[{args:s,rspData:f,cfg:u,errno:h}]),f.hao123Param&&\"1\"!=f.realnameswitch&&D(f.hao123Param,e),!1;if(20==h){var v=e.fire(\"beforeWarning\",s);if(!v)return;return e.getElement(\"error\").innerHTML=\"\",e.getElement(\"smsError\").innerHTML=\"\",e._ownerDialog&&e._ownerDialog.hide(\"unHide\"),r.apply(e,[{args:s,rspData:s,cfg:u}]),f.hao123Param&&\"1\"!=f.setpwdswitch&&D(f.hao123Param,e),!1}if(22==h){var v=e.fire(\"beforeWarning\",s);if(!v)return;return e.getElement(\"error\").innerHTML=\"\",e.getElement(\"smsError\").innerHTML=\"\",e._ownerDialog&&e._ownerDialog.hide(\"unHide\"),a.apply(e,[{args:s,rspData:s,cfg:u}]),f.hao123Param&&D(f.hao123Param,e),!1}if(\"400413\"===h||\"400414\"===h){var v=e.fire(\"beforeWarning\",s);if(!v)return;return e.getElement(\"error\").innerHTML=\"\",e.getElement(\"smsError\").innerHTML=\"\",e._ownerDialog&&e._ownerDialog.hide(\"unHide\"),c.apply(e,[{args:s,rspData:s,cfg:u}]),f.hao123Param&&D(f.hao123Param,e),!1}if(19==h){var y=this,f=s.rsp.data,v=e.fire(\"beforeWarning\",s);if(!v)return;return e.getElement(\"error\").innerHTML=\"\",e._ownerDialog&&e._ownerDialog.hide(\"unHide\"),null==y.confirmWidgetLabel?passport._load(b+\"/passApi/js/uni_wrapper.js\",!0,function(){y.confirmWidgetLabel=passport.pop.init({type:\"confirmWidget\",tangram:!0,width:430,height:150,apiOpt:{contentHTML:\"                                        <div class='pass-confirmContent-wrapper-Label'>                                            <div class='pass-confirmContent-msg-Label'><span class='img-class' ></span></div>                                            <ul  class='pass-confirmContent-descmsg-Label' style='margin-left:20px;'>                                                <p>近日，某邮箱帐户存在被破解的可能性，建议您使用其他</p>                                                <p>邮箱绑定百度帐号，或及时修改您的百度帐号登陆密码并</p>                                                <p>绑定手机，以确保帐户安全。</p>                                            </ul>                                        </div>\"},onConfirmClose:function(){y.confirmWidgetLabel.hide(),T(e,s)},onRender:function(){y.confirmWidgetLabel.getElement(\"confirm_cancel\").style.display=\"none\",y.confirmWidgetLabel.getElement(\"confirm_continue\").style.display=\"none\",y.confirmWidgetLabel.getElement(\"confirmWidget_footer\").style.display=\"none\"}}),y.confirmWidgetLabel.show()}):y.confirmWidgetLabel.show(),f.hao123Param&&D(f.hao123Param,e),!1}if(23==h){var y=this,f=s.rsp.data,v=e.fire(\"beforeWarning\",s);if(!v)return;return e.getElement(\"error\").innerHTML=\"\",e._ownerDialog&&e._ownerDialog.hide(\"unHide\"),null==y.confirmWidgetMobileSure?passport._load(b+\"/passApi/js/uni_wrapper.js\",!0,function(){y.confirmWidgetMobileSure=passport.pop.init({type:\"confirmWidget\",tangram:!0,titleText:\"非常重要\",width:430,apiOpt:{Cancel:\"不需要解绑\",Continue:\"申诉去解绑\",contentHTML:'<div class=\"pass-confirmContent-wrapper-sureConfirm\"><div class=\"pass-confirmContent-wrapper-msg\"><p><span class=\"pass-confirmContent-redcolor\" id=\"pass-mobile-sure-num\">'+f.phoneNumber+'</span>是您绑定的手机号,请确认该手机号是否还在使用,为了帐号安全请及时解绑不使用的手机。</p></div><div class=\"pass-confirmwidget-bottom\"><span id=\"pass-mobile-sure-btn\" class=\"pass-button pass-button-grey cancel\">不需要解绑</span><a href=\"'+f.appealurl+'\" id=\"pass-appeal-btn\" class=\"pass-button pass-button-grey continue\" target=\"new\">申诉去解绑</a></div></div>'},onRender:function(){y.confirmWidgetMobileSure.getElement(\"confirm_cancel\").style.display=\"none\",y.confirmWidgetMobileSure.getElement(\"confirm_continue\").style.display=\"none\",y.confirmWidgetMobileSure.getElement(\"confirmWidget_footer\").style.display=\"none\",baidu(document.getElementById(\"pass-mobile-sure-btn\")).on(\"click\",function(){g(\"mobileSurePC\")\n}),baidu(document.getElementById(\"pass-appeal-btn\")).on(\"click\",function(){g(\"appealMobilePC\")})},onConfirmClose:function(){g(\"mobileSureClosePC\")},onConfirmContinue:function(){},onConfirmCancel:function(){}}),y.confirmWidgetMobileSure.show()}):(document.getElementById(\"pass-mobile-sure-num\")&&(document.getElementById(\"pass-mobile-sure-num\").html=f.phoneNumber||\"\"),y.confirmWidgetMobileSure.show()),f.hao123Param&&D(f.hao123Param,e),!1}if(401007==h){var v=e.fire(\"beforeWarning\",s);if(!v)return;return e.getElement(\"error\").innerHTML=\"\",e._ownerDialog&&e._ownerDialog.hide(\"unHide\"),i.apply(e,[{rspData:f}]),!1}if(120016==h||400032==h||400034==h){var v=e.fire(\"beforeWarning\",s);if(!v)return;return e.getElement(\"error\").innerHTML=\"\",e._ownerDialog&&e._ownerDialog.hide(\"unHide\"),t.apply(e,[{errno:h,args:s,cfg:u}]),f.hao123Param&&D(f.hao123Param,e),!1}if(5==h||400031==h||120019==h||120021==h||400023==h||m){var v=e.fire(\"beforeWarning\",{args:s});if(!v)return;return e.getElement(\"error\")&&(e.getElement(\"error\").innerHTML=\"\"),e._ownerDialog&&e._ownerDialog.hide(\"unHide\"),p(b+\"/passApi/css/uni_forceverify_1fc77c5.css\"),n.apply(e,[{args:s,rspData:f,cfg:u,errno:m&&120021!=h?\"riskCheat\":h}]),!1}if(400037==h){var v=e.fire(\"beforeWarning\",s);if(!v)return;return e.getElement(\"error\").innerHTML=\"\",e._ownerDialog&&e._ownerDialog.hide(\"unHide\"),o.apply(e,[{args:s,rspData:s,cfg:u}]),f.hao123Param&&D(f.hao123Param,e),!1}return!0}function p(e){if(!S[e]){S[e]=!0;var t=document.createElement(\"link\");t.rel=\"stylesheet\",t.type=\"text/css\",t.href=e,document.getElementsByTagName(\"head\")[0].appendChild(t)}return!0}var g,h,f,m,v,b=window.location?\"http:\"==window.location.protocol.toLowerCase()?\"http://passport.baidu.com\":\"https://passport.baidu.com\":\"http:\"==document.location.protocol.toLowerCase()?\"http://passport.baidu.com\":\"https://passport.baidu.com\",y={uni_armorwidget:\"/passApi/js/uni_armorwidget_23b461e.js\",uni_forceverify:\"/passApi/js/uni_forceverify_6167137.js\",uni_accConnect:\"/passApi/js/uni_accConnect_wrapper.js\",uni_wrapper:\"/passApi/js/uni_wrapper.js\"},_=\"uni_wrapper\",E=\"uni_forceverify\",C=\"uni_armorwidget\",w=\"uni_accConnect\",S={},T=function(e,t){var n=e.fire(\"loginSuccess\",t);n&&(window.location?window.location.href=t.rsp.data.u:document.location.href=t.rsp.data.u)},I=function(){var e=0,t=0,n=null,i=/msie (\\d+\\.\\d+)/i.test(navigator.userAgent);if(i||console.log(navigator.plugins[\"Shockwave Flash\"]),i){var s=new ActiveXObject(\"ShockwaveFlash.ShockwaveFlash\");s&&(e=1,t=s.GetVariable(\"$version\"))}else if(navigator&&navigator.plugins&&navigator.plugins.length>0&&navigator.plugins[\"Shockwave Flash\"]){var s=navigator.plugins[\"Shockwave Flash\"];s&&(n=s.filename,e=1,t=s.version?s.version:s.description)}return{isexists:e,ver:t,filename:n}},D=function(e,t){if(!(t&&t.config&&t.config.noSynBdu&&1===t.config.noSynBdu)){var n=document.location.protocol.toLowerCase();return\"https:\"!=n&&passport.data.request.load(n+\"//v.tieba.com/platform/agency/setbdu?bdu=\"+encodeURIComponent(e)+\"&t=\"+(new Date).getTime()),passport.data.request.load(n+\"//user.nuomi.com/pclogin/main/crossdomain?bdu=\"+encodeURIComponent(e)+\"&t=\"+(new Date).getTime()),passport.data.request.load(n+\"//passport.zongheng.com/bdpass/crossdomain.do?bdu=\"+encodeURIComponent(e)+\"&t=\"+(new Date).getTime()),passport.data.request.load(\"https://www.baifubao.com/api/0/sync_bduss/0?bdu=\"+encodeURIComponent(e)+\"&t=\"+(new Date).getTime()),passport.data.request.load(\"https://passport.qianqian.com/bdpass?bdu=\"+encodeURIComponent(e)+\"&t=\"+(new Date).getTime()),passport.data.request.load(n+\"//passport.chuanke.com/api/sync?bdu=\"+encodeURIComponent(e)+\"&t=\"+(new Date).getTime()),passport.data.request.load(n+\"//user.hao123.com/static/crossdomain.php?bdu=\"+encodeURIComponent(e)+\"&t=\"+(new Date).getTime())}};e.login={loginSuccess:function(e,t){var n=/msie (\\d+\\.\\d+)/i.test(navigator.userAgent);if(e.config.setWebToClient&&!n&&s.apply(e,[{args:t}]),e.config.noSynBdu&&1===e.config.noSynBdu){var i=u(e,t,{onCancel:function(){T(e,t)}});i&&T(e,t)}else D(t.rsp.data.hao123Param,e).success(function(){var n=u(e,t,{onCancel:function(){T(e,t)}});n&&T(e,t)});return{preventEvent:!0,preventDefault:!0}},loginError:function(e,t){return u(e,t,{onCompleted:function(t,n){e.config.noSynBdu&&1===e.config.noSynBdu?n():D(t.data.hao123Param,e).success(n)},onCancel:function(t){t&&t.isCompleted&&T(e,{rsp:t.rsp})}}),{preventEvent:!1,preventDefault:!1}},connectNeedBind:function(e,t){return u(e,t,{onCompleted:function(){},onCancel:function(){}}),{preventEvent:!1,preventDefault:!1}},validateAllError:function(e,t){var n=t.validates?e.getElement(t.validates[t.validates.length-1].field):\"\";return n&&n.focus&&n.focus(),{preventEvent:!1,preventDefault:!1}}}}(passport.hook),magic.passport=baidu.lang.createClass(function(){this._validateInfo={}},{type:\"magic.passport\",superClass:magic.Base}).extend({_getRegularField:function(e){var t=e.pwd?\"password\":\"text\",n=this,i='autocomplete=\"new-password\"',s=e.maxLength?'maxlength=\"'+e.maxLength+'\"':\"\",o=e.tip?e.tip:\"\",r=e.value?e.value:\"\",a=\"verifycode\"==e.field?\"none\":\"\",c=\"\";c=\"text\"===t?'<input type=\"text\" style=\"display:none;\">':'<input type=\"password\" style=\"display: none;\">';var l='<p id=\"'+n.$getId(e.field+\"Wrapper\")+'\" class=\"pass-form-item pass-form-item-'+e.field+'\" style=\"display:'+a+'\">'+(e.label?'<label for=\"'+n.$getId(e.field)+'\" id=\"'+n.$getId(e.field+\"Label\")+'\" class=\"pass-label pass-label-'+e.field+'\">'+e.label+\"</label>\":\"\")+c+'<input id=\"'+n.$getId(e.field)+'\" type=\"'+t+'\" name=\"'+e.field+'\" class=\"pass-text-input pass-text-input-'+e.field+'\" '+s+(e.placeholder?'placeholder=\"'+e.placeholder+'\" ':\"\")+i+(e.disabled?'\" disabled':\"\")+' value=\"'+r+'\"/>'+(e.noError?\"\":'<span id=\"'+n.$getId(e.field+\"Error\")+'\" class=\"pass-item-error pass-item-error-'+e.field+'\"></span>')+(e.hasSucc?'<span id=\"'+n.$getId(e.field+\"Succ\")+'\" class=\"pass-item-succ pass-item-succ-'+e.field+'\" style=\"display:none;\"></span>':\"\")+'<span id=\"'+n.$getId(e.field+\"Tip\")+'\" class=\"pass-item-tip pass-item-tip-'+e.field+'\" style=\"display:none\"><span id=\"'+n.$getId(e.field+\"TipText\")+'\" class=\"pass-item-tiptext pass-item-tiptext-'+e.field+'\">'+o+\"</span></span></p>\";return l},_getHiddenField:function(e,t){var n,i=this,s='<p id=\"'+i.$getId(t||\"hiddenFields\")+'\" style=\"display:none\">';for(var o in e)e.hasOwnProperty(o)&&(n=\"string\"==typeof e[o]?e[o].replace(/</g,\"&lt;\").replace(/>/g,\"&gt;\").replace(/\"/g,\"&quot;\").replace(/\\x22/g,\"&quot;\").replace(/\\x27/g,\"&#39;\"):e[o],s+='<input type=\"hidden\" id=\"'+i.$getId((t?t+\"_\":\"\")+o)+'\" name=\"'+o+'\" value=\"'+n+'\" />');return s+=\"</p>\"},_setEvent:function(){var e=this,t=this.getElement(),n=function(t){e._eventHandler.entrance.apply(e,[t])};baidu(e.getElement()).on(\"resize\",function(){var e=(navigator.userAgent,!navigator.userAgent.match(/OS [1-8]_\\d[_\\d]* like Mac OS X/i)),t=!!navigator.userAgent.toString().match(/\\(i[^;]+;( U;)? CPU.+Mac OS X/),n=navigator.userAgent.toString().indexOf(\"iPad\");if(e&&t&&null!=n){var i=document.getElementsByClassName(\"popBox\");null!=i&&i.length>0&&(i[0].style.height=window.screen.height>document.body.clientHeight?window.screen.height*(window.screen.height/document.body.clientHeight)+120+\"px\":window.screen.height*(window.screen.height/document.body.clientHeight))}}),baidu(e.getElement(\"form\")).on(\"submit\",n),baidu(e.getElement(\"license\")).on(\"click\",n),baidu(e.getElement(\"verifyCodeChange\")).on(\"click\",n),baidu(e.getElement(\"verifyCodeSend\")).on(\"click\",n),baidu(e.getElement(\"smsVcodeSend\")).on(\"click\",n),baidu(t).delegate(\".pass-suggest-item label\",\"click\",n),baidu(\".pass-text-input\",e.getElement()).on({focus:n,blur:n,change:n,keyup:n,mouseover:n,mouseout:n})},_validator:{confStorage:{},builtInMsg:{required:\"请您输入%s\",phone:\"手机号码格式不正确\",email:\"邮箱格式不正确\",idcard:\"身份证格式不正确\"},builtInRules:{required:/\\S+/,phone:/^1[3456789]\\d{9}$/,email:/^([a-zA-Z0-9_\\.\\-\\+])+\\@(([a-zA-Z0-9\\-])+\\.)+([a-zA-Z0-9]{2,4})+$/,idcard:/(^\\d{15}$)|(^\\d{17}(\\d|X|x)$)/},init:function(e,t){this.confStorage[e.$getId()]=t},validate:function(e,t,n,i){var s=e.getElement(t),o={field:t},r=/^\\s*(.+?)\\s*$/;if(!s||0==s.offsetHeight)return!1;for(var a=s.value.replace(r,\"$1\"),c=this.confStorage[e.$getId()][t],l=c.rules,d=0,u=l.length;u>d;d++){var p,g=l[d],h=this.builtInRules[g];if(p=\"[object function]\"==Object.prototype.toString.call(h).toLowerCase()?h.call(e,s,i):new RegExp(h).test(a),!p)return o.error=!0,e._validateInfo[t]=0,o.msg=this.builtInMsg[g].replace(/\\%s/,c.desc),e._validateError(o),void n.error(o)}c.asyncRule?c.asyncRule.call(e,{success:function(i){o.error=!1,o.data=i.data,e._validateInfo[t]=1,e._validateSuccess(o),n.success(o)},error:function(i){o.error=!0,e._validateInfo[t]=0,o.msg=i.msg,e._validateError(o),n.error(o)}},i):(o.error=!1,e._validateInfo[t]=1,e._validateSuccess(o),n.success(o))},validateAll:function(e,t,n){function i(){a=!0,r?t&&t.error(c):t&&t.success(c)}var s=this.confStorage[e.$getId()],o=0,r=!1,a=!1,c=[],l=this._getActiveValidate(e,!0);for(var d in s){if(a)break;this.validate(e,d,{success:function(e){o++,c.push(e),o==l&&i()},error:function(e){return r=!0,o++,c.push(e),n?void i():void(o==l&&i())}},\"all\")}},_getActiveValidate:function(e,t){var n=this.confStorage[e.$getId()],i=[];for(var s in n){var o=e.getElement(s);o&&0!=o.offsetHeight&&i.push(o)}return t?i.length:i},addRule:function(e,t){var n={};n[e]=t,baidu.extend(this.builtInRules,n)},addMsg:function(e,t){var n={};n[e]=t,baidu.extend(this.builtInMsg,n)}},validate:function(e,t){var n=this,i=n.fireEvent(\"beforeValidate\",{validate:{field:e,ele:baidu(n.getElement(e))}});i&&n._validator.validate(n,e,{success:function(e){var i=n.fireEvent(\"validateSuccess\",{validate:e});i&&t&&t.success&&t.success(e)},error:function(e){var i=n.fireEvent(\"validateError\",{validate:e});i&&t&&t.error&&t.error(e)}})},validateAll:function(e,t){var n=this;t=\"boolean\"==typeof e?e:t?t:!1;var i=n.fireEvent(\"beforeValidateAll\");i&&n._validator.validateAll(n,{success:function(t){var i=n.fireEvent(\"validateAllSuccess\",{validates:t});i&&e&&e.success&&e.success(t)},error:function(t){var i=n.fireEvent(\"validateAllError\",{validates:t});i&&e&&e.error&&e.error(t)}},t)},getValidateStatus:function(e){return this._validateInfo.hasOwnProperty(e)?this._validateInfo[e]:-1},setValidateSuccess:function(e){var t=this;t._validateInfo[e]=1,t._validateSuccess({field:e})},setValidateError:function(e,t,n){var i=this;i._validateInfo[e]=0,i._validateError({field:e,msg:t},n)},setGeneralError:function(e){this.getElement(\"error\").innerHTML=e},clearGeneralError:function(){this.getElement(\"error\").innerHTML=\"\"},_isSupportPlaceholder:function(){return\"placeholder\"in document.createElement(\"input\")},_getPlaceholder:function(e){for(var t=this,n={},i=\"\",s={},o=0;o<e.length;o++)i=t.lang[e[o].placeholder],0!=e[o].clearbtn&&(s[o]=baidu('<span id=\"'+t.$getId(e[o].label+\"_clearbtn\")+'\" class=\"pass-clearbtn pass-clearbtn-'+e[o].label+'\" style=\"display:none;\"></span>'),baidu(t.getElement(e[o].label)).after(s[o])),t._isSupportPlaceholder()&&!baidu.browser.ie?baidu(t.getElement(e[o].label)).attr({placeholder:i}):(n[o]=baidu('<span id=\"'+t.$getId(e[o].label+\"_placeholder\")+'\" class=\"pass-placeholder pass-placeholder-'+e[o].label+'\">'+i+\"</span>\"),baidu(t.getElement(e[o].label)).after(n[o])),t._rendEventPlaceholder(t.getElement(e[o].label),n[o],s[o])},_getCookie:function(e){var t,n=new RegExp(\"(^| )\"+e+\"=([^;]*)(;|$)\");return(t=document.cookie.match(n))?unescape(t[2]):null},_logPass:function(e,t){function n(e){var t,n,i,s,o,r,a=\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";for(i=e.length,n=0,t=\"\";i>n;){if(s=255&e.charCodeAt(n++),n==i){t+=a.charAt(s>>2),t+=a.charAt((3&s)<<4),t+=\"==\";break}if(o=e.charCodeAt(n++),n==i){t+=a.charAt(s>>2),t+=a.charAt((3&s)<<4|(240&o)>>4),t+=a.charAt((15&o)<<2),t+=\"=\";break}r=e.charCodeAt(n++),t+=a.charAt(s>>2),t+=a.charAt((3&s)<<4|(240&o)>>4),t+=a.charAt((15&o)<<2|(192&r)>>6),t+=a.charAt(63&r)}return t}var i=document.location.protocol+\"//nsclick.baidu.com/v.gif?v=\"+(new Date).getTime(),s=\"\";for(var o in t)s=s+o+\":\"+t[o]+\",\";s=n(\"{\"+s.substring(0,s.length-1)+\"}\");var r=\"&page=\"+e.page+\"&source=pc&tpl=\"+e.tpl+\"&auto_statistic=\"+s;if(i+=r){var a=new Image;a.onload=a.onerror=function(){a.onload=a.onerror=null,a=null},a.src=i}},_rendEventPlaceholder:function(e,t,n){if(e||n){var i,s,o=this,r=function(e){1==e?(t&&t[0]&&o.$hide(t[0]),n&&n[0]&&o.$show(n[0])):(t&&t[0]&&o.$show(t[0]),n&&n[0]&&o.$hide(n[0]))};setTimeout(function(){void 0!=e&&e.value&&r(1)},200),baidu(t).on(\"mousedown\",function(){s=!0,clearTimeout(i),i=setTimeout(function(){o.suggestionDom&&\"none\"!=o.suggestionDom.style.display||e.focus()},0)}),baidu(n).on(\"click\",function(){e.value=\"\",r(0),e.focus(),o.suggestionDom&&(o.suggestionDom.data_delete=!0,setTimeout(function(){o.suggestionDom.data_delete=!1},200))}),baidu(e).on(\"keyup\",function(){r(e.value?1:0)}),baidu(e).on(\"focus\",function(){inputCheckTimer=setInterval(function(){e.value.length?(r(1),clearInterval(inputCheckTimer)):r(0)},30)})}},SBCtoDBC:function(e){var t=\"\";if(e){for(var n=e.length,i=0;n>i;i++){var s=e.charCodeAt(i);s=s>=65281&&65374>=s?s-65248:s,s=12288==s?32:s,t+=String.fromCharCode(s)}return t}},hide:function(){this.getElement().style.display=\"none\"},show:function(){this.getElement().style.display=\"block\"},_analysis:function(e,t){return passport.analysis&&passport.analysis[this.module]&&passport.analysis[this.module][e]?(passport.analysis[this.module][e](this,t),{preventDefault:!1,preventEvent:!1}):void 0},_hook:function(e,t){return passport.hook&&passport.hook[this.module]&&passport.hook[this.module][e]?passport.hook[this.module][e](this,t):{preventDefault:!1,preventEvent:!1}},fireEvent:function(e,t){var n=this._hook(e,t),i=(this._analysis(e,t),!0);return n.preventEvent||(i=this.fire(e,t)),!n.preventDefault&&i}}),magic.passport.login=baidu.lang.createClass(function(e){var t=this;if(passport&&\"https\"==passport._protocol)var n=\"https:\";else var n=window.location?window.location.protocol.toLowerCase():document.location.protocol.toLowerCase();if(t._domain={https:\"https://passport.baidu.com\",http:\"http://passport.baidu.com\",staticFile:\"https:\"==n?\"https://ss0.bdstatic.com/5LMZfyabBhJ3otebn9fN2DJv\":\"http://passport.bdimg.com\",auto:\"https:\"==n?\"https://passport.baidu.com\":\"http://passport.baidu.com\"},t.config={isPhone:!1,memberPass:!0,isQuickUser:0,safeFlag:0,product:\"\",idc:\"\",charset:\"\",loginMerge:!1,staticPage:\"\",hasRegUrl:!1,u:\"\",lang:\"zh-CN\",autosuggest:!0,hasPlaceholder:!1,registerLink:\"\",authsiteLogin:\"\",authsiteCfgLogin:\"\",qrcode:!1,sms:0,uniqueId:!1,autoFocus:!0,subpro:\"\",setWebToClient:!0,is_voice_sms:0,voice_sms_flag:0,qrcode_animation:\"\",qrcode_style:\"\"},baidu.extend(t.config,e),t.config.authsiteLogin&&baidu.array(t.config.authsiteLogin).indexOf(\"renren\")>-1){var i=baidu.array(t.config.authsiteLogin).indexOf(\"renren\");t.config.authsiteLogin.splice(i,1)}t.config.product=t.config.product||\"isnull\",this.module=\"login\",this.guideRandom=function(){return\"xxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g,function(e){var t=16*Math.random()|0,n=\"x\"==e?t:3&t|8;return n.toString(16)}).toUpperCase()}(),t.constant={CHECKVERIFYCODE:!0,CONTAINER_CLASS:\"tang-pass-login\",LABEL_FOCUS_CLASS:\"pass-text-label-focus\",FOCUS_CLASS:\"pass-text-input-focus\",HOVER_CLASS:\"pass-text-input-hover\",ERROR_CLASS:\"pass-text-input-error\",VERIFYCODE_URL_PREFIX:t._domain.https+\"/cgi-bin/genimage?\",BLANK_IMG_URL:passport.apiDomain.staticDomain+\"/passApi/img/small_blank.gif\",MODIFY_PWD_URL_PREFIX:t._domain.https+\"/forcsdnpasschange\",GET_PASSWORD_URL:t._domain.https+\"/?getpassindex&tt=\"+(new Date).getTime()+\"&gid=\"+t.guideRandom+\"&tpl=\"+encodeURIComponent(t.config.product)+\"&u=\"+encodeURIComponent(t.config.u),REG_URL:t.config.registerLink||t._domain.https+\"/v2/?reg&tt=\"+(new Date).getTime()+\"&overseas=\"+t.config.overseas+\"&gid=\"+t.guideRandom+\"&tpl=\"+encodeURIComponent(t.config.product)+\"&u=\"+encodeURIComponent(t.config.u),PROTOCAL_URL:t._domain.http+\"/static/passpc-account/html/protocal.html\",NOCAPTCHA_URL:t._domain.auto+\"/static/passpc-base/js/ld.min.js?cdnversion=\"+(new Date).getTime(),SUBMITFLAG:!1},t.lang=passport.err.getCurrent().labelText.login,passport.data.setContext(baidu.extend({},t.config)),this.initialized=!1,this.validatorInited=!1,this.bdPsWtoken=\"\",this.innerData={normal:{},phone:{}},this.dataFiels=[\"userName\",\"password\"],this.initTime=(new Date).getTime(),confirmSmsVerifyWidget=null,checkPhoneWidget=null,checkPhoneExist=!1,t.config.overseas&&1==t.config.overseas&&(this.foreignMobile=!0),this.internation=!1,this.connectURL={nuomi:\"http://www.nuomi.com/pclogin/main/checkaccount\"},t._insertNoCaptchaScript(),t.config.defaultCss&&t._loadCssFileW(\"/passApi/css/uni_login_merge_0dc54d0.css\",function(){}),(t.config.memberPass||t.config.getapi)&&t._initApi()},{type:\"magic.passport.login\",superClass:magic.passport}).extend({_getIrregularField:function(e){var t=this,n={makeText:'<p id=\"'+t.$getId(\"MakeTextWrapper\")+'\" class=\"pass-make-text\" style=\"display:none;\"></p>',verifyCode:'<p id=\"'+t.$getId(\"verifyCodeImgWrapper\")+'\" class=\"pass-form-item pass-form-item-verifyCode\" style=\"display:none\"><label for=\"'+t.$getId(\"verifyCode\")+'\" id=\"'+t.$getId(\"verifyCodeLabel\")+'\" class=\"pass-label pass-label-verifyCode\">'+t.lang.captcha+'</label><input id=\"'+t.$getId(\"verifyCode\")+'\" type=\"text\" name=\"verifyCode\" class=\"pass-text-input pass-text-input-verifyCode\" maxlength=\"6\" /><span  id=\"'+t.$getId(\"verifyCodeImgParent\")+'\" class=\"pass-verifyCodeImgParent\" ><img id=\"'+t.$getId(\"verifyCodeImg\")+'\" class=\"pass-verifyCode\" src=\"'+t.constant.BLANK_IMG_URL+'\" /></span><a id=\"'+t.$getId(\"verifyCodeChange\")+'\" href=\"#\" class=\"pass-change-verifyCode\">'+t.lang.captchaChange+'</a><span id=\"'+t.$getId(\"verifyCodeError\")+'\" class=\"pass-error pass-error-verifyCode\"></span><span id=\"'+t.$getId(\"verifyCodeTip\")+'\" class=\"pass-tip pass-tip-verifyCode\"></span><span id=\"'+t.$getId(\"verifyCodeSuccess\")+'\" class=\"pass-success pass-success-verifyCode\"></span></p>',generalError:'<p id=\"'+t.$getId(\"errorWrapper\")+'\" class=\"pass-generalErrorWrapper\"><span id=\"'+t.$getId(\"error\")+'\" class=\"pass-generalError pass-generalError-error\"></span></p>',smsSwitch:'<p class=\"pass-smsSwitchWrapper\" id=\"'+t.$getId(\"smsSwitchWrapper\")+'\"><a class=\"pass-sms-btn\" title=\"短信快捷登录\" data-type=\"sms\" id=\"'+t.$getId(\"smsSwitch\")+'\">短信快捷登录</a></p>',rem:'<p id=\"'+t.$getId(\"memberPassWrapper\")+'\" class=\"pass-form-item pass-form-item-memberPass\"><input id=\"'+t.$getId(\"memberPass\")+'\" type=\"checkbox\" name=\"memberPass\" class=\"pass-checkbox-input pass-checkbox-memberPass\"'+(t.config.memberPass?' checked=\"checked\"':\"\")+' /><label for=\"'+t.$getId(\"memberPass\")+'\" id=\"'+t.$getId(\"memberPassLabel\")+'\" class=\"\">'+t.lang.memberPassLabel+\"</label></p>\",submit:'<p id=\"'+t.$getId(\"submitWrapper\")+'\" class=\"pass-form-item pass-form-item-submit\"><input id=\"'+t.$getId(\"submit\")+'\" type=\"submit\" value=\"'+t.lang.login+'\" class=\"pass-button pass-button-submit\" /><a class=\"pass-reglink\" href=\"'+t.constant.REG_URL+'\" target=\"_blank\" '+(t.config.hasRegUrl?\"\":'style=\"display:none\"')+\">\"+t.lang.register+'</a><a class=\"pass-fgtpwd\" href=\"'+t.constant.GET_PASSWORD_URL+'\" target=\"_blank\">'+t.lang.fgtPwd+\"</a></p>\",foreignMobileMsg:'<p class=\"pass-foreignMobile-msg\" id=\"'+t.$getId(\"foreignMobileMsg\")+'\">'+t.lang.foreignMobileMsg+\"</p>\",foreignMobileWrapper:'<div class=\"pass-form-item pass-form-item-PhoneCountry pass-foreignMobile-wrapper\" id=\"'+t.$getId(\"foreignMobileWrapper\")+'\" style=\"display:none\"><label for=\"'+t.$getId(\"foreignMobile\")+'\" id=\"'+t.$getId(\"foreignMobileLabel\")+'\" class=\"pass-label\" data-countryCode=\"\">+86</label><input id=\"'+t.$getId(\"foreignMobile\")+'\" type=\"text\" name=\"foreignusername\" class=\"pass-text-input\"/><ul id=\"'+t.$getId(\"foreignCountryList\")+'\" class=\"pass-country-list\"></ul></div>',foreignMobileLink:'<p class=\"pass-foreignMobile-link-wrapper\" id=\"'+t.$getId(\"foreignMobileLinkWrapper\")+'\"><a id=\"'+t.$getId(\"foreignMobileLink\")+'\" class=\"pass-foreignMobile-link\">'+t.lang.foreignMobileLink+\"</a></p>\",foreignMobileBack:'<p class=\"pass-foreignMobile-back-wrapper\" id=\"'+t.$getId(\"foreignMobileBackWrapper\")+'\"><a id=\"'+t.$getId(\"foreignMobileBack\")+'\" class=\"pass-foreignMobile-link\">'+t.lang.foreignToLogin+\"</a></p>\",choiceuser:'<div id=\"'+t.$getId(\"choiceuser_article\")+'\" class=\"tang-pass-login-choice choiceuser-article\"><div class=\"choiceuser-msg\"><p class=\"choiceuser-msg-title\">亲爱的用户，</p><p  class=\"choiceuser-msg-text\">为了确保您的帐号安全，请先确认您输入的帐号是用户名还是手机号：</p></div><div class=\"choiceuser-buttons\"><div class=\"choiceuser-btn\"><input class=\"pass-button pass-button-choiceuser-username\" type=\"button\" value=\"用户名\" id=\"'+t.$getId(\"choiceuser_btn_username\")+'\"/><input class=\"pass-button pass-button-choiceuser-phone\" type=\"button\" value=\"手机号\" id=\"'+t.$getId(\"choiceuser_btn_mobile\")+'\"/></div><div class=\"choiceuser-back\"><a href=\"#\" id=\"'+t.$getId(\"choiceuser_btn_back\")+'\">'+t.lang.backToLogin+\"</a></div></div></div>\",webtoclint:'<div id=\"'+t.$getId(\"pass_b2c\")+'\" style=\"display:none;\"></div>',is_voice_sms:'<div class=\"pass-smsSwitchWrapper\"><a class=\"pass-is_voice_sms-btn\" title=\"语音验证码\" data-type=\"is_voice_sms\" >语音验证码</a></div>'};return n[e]},_getTemplate:function(){var e=this,t='<form id=\"'+e.$getId(\"form\")+'\" class=\"pass-form pass-form-normal\" method=\"POST\" autocomplete=\"off\">',n={codeString:\"\",safeFlag:e.config.safeFlag,u:e.config.u,isPhone:e.config.isPhone,detect:\"1\",gid:e.guideRandom||\"\",staticPage:e.config.staticPage,quick_user:e.config.isQuickUser,logintype:e.config.diaPassLogin?\"dialogLogin\":\"basicLogin\",logLoginType:e.config.diaPassLogin?\"pc_loginDialog\":\"pc_loginBasic\",subpro:e.config.subpro,idc:e.config.idc},i=[{field:\"userName\",label:e.config.loginMerge?e.lang.userName:e.config.isPhone?e.lang.phoneNum:e.lang.account,noError:!0},{field:\"password\",pwd:!0,label:e.lang.password,noError:!0}];e.config.loginMerge&&(n.loginMerge=!0,n.isPhone=!1),t+=e._getIrregularField(\"generalError\"),t+=e._getIrregularField(\"makeText\"),e.config.sms&&(t+=e._getIrregularField(\"smsSwitch\")),t+=e._getHiddenField(n),e.foreignMobile&&(t+=e._getIrregularField(\"foreignMobileMsg\"),t+=e._getIrregularField(\"foreignMobileWrapper\"));for(var s=0;s<i.length;s++)t+=e._getRegularField(i[s]);return t+=e._getIrregularField(\"verifyCode\"),t+=e._getIrregularField(\"rem\"),t+=e._getIrregularField(\"submit\"),e.foreignMobile&&(t+=e._getIrregularField(\"foreignMobileLink\"),t+=e._getIrregularField(\"foreignMobileBack\")),t+=\"</form>\"},_collectData:function(){for(var e=this,t=e.innerData[e.config.isPhone?\"phone\":\"normal\"],n=e.dataFiels,i=0,s=n.length;s>i;i++)t[n[i]]=e.getElement(n[i]).value;return t},_restoreData:function(e){for(var t=this,n=t.innerData[e?e:t.config.isPhone?\"phone\":\"normal\"],i=t.dataFiels,s=0,o=i.length;o>s;s++)t.getElement(i[s]).value=n[i[s]]||\"\";return n},_loadCssFileW:function(e,t){var n=this;if(window._loadedFilesW=window._loadedFilesW||{},!window._loadedFilesW[e]){window._loadedFilesW[e]=!0;var i=document.createElement(\"link\");i.rel=\"stylesheet\",i.type=\"text/css\",i.href=n._domain.staticFile+e,document.getElementsByTagName(\"head\")[0].appendChild(i),i.readyState?i.onreadystatechange=function(){(\"loaded\"==i.readyState||\"complete\"==i.readyState)&&(i.onreadystatechange=null,t&&t())}:i.onload=function(){t&&t()}}},_insertScriptW:function(e,t){if(window._loadedFilesW=window._loadedFilesW||{},!window._loadedFilesW[e]){window._loadedFilesW[e]=!0;var n=document,i=n.createElement(\"SCRIPT\");i.type=\"text/javascript\",i.charset=\"UTF-8\",i.readyState?i.onreadystatechange=function(){(\"loaded\"==i.readyState||\"complete\"==i.readyState)&&(i.onreadystatechange=null,t&&t())}:i.onload=function(){t&&t()},i.src=e,n.getElementsByTagName(\"head\")[0].appendChild(i)}},_authSiteW:function(){var e=this,t=e.config,n=e.getPhoenixId(\"pass_phoenix_btn\");t.authsitecssLoad&&e._loadCssFileW(\"/passApi/css/authsite_c01e2ff.css\"),e._insertScriptW(e._domain.auto+\"/phoenix/account/jsapi\",function(){window.baidu.phoenix&&window.baidu.phoenix.require(t.authsiteLogin,baidu.extend(t.authsiteCfgLogin||{},{tpl:t.product?t.product:\"\",idc:t.idc?t.idc:\"\",u:t.u,subpro:t&&t.subpro||\"\",target:n,html:{qzone:'<a class=\"phoenix-btn-item\" href=\"#\">QQ帐号</a>',tsina:'<a class=\"phoenix-btn-item\" href=\"#\">新浪微博</a>',renren:'<a class=\"phoenix-btn-item\" href=\"#\">人人网</a>',fetion:'<a class=\"phoenix-btn-item\" href=\"#\">飞信</a>',tqq:'<a class=\"phoenix-btn-item\" href=\"#\">腾讯微博</a>',qunar:'<a class=\"phoenix-btn-item\" href=\"#\">去哪儿</a>',weixin:'<a class=\"phoenix-btn-item\" href=\"#\">微信</a>',tianyi:'<a class=\"phoenix-btn-item\" href=\"#\">天翼</a>',feifan:'<a class=\"phoenix-btn-item\" href=\"#\">飞凡</a>'},onAfterRender:function(){for(var e=baidu(\"#\"+n+\" li\"),t=function(e){e.on(\"click\",function(e){e.preventDefault()})},i=0;i<e.length;i++){var s=baidu(\".phoenix-btn-item\",e[i]);s.attr({title:s[0].innerHTML}),t(s)}}}))})},getVerifyCode:function(e){var t=this,n={fr:\"login\",vcodetype:t.vcodetype||\"\"};if(t.getElement(\"verifyCode\").value=\"\",t.$hide(\"verifyCodeSuccess\"),t.getElement(\"verifyCode_clearbtn\")&&t.$hide(\"verifyCode_clearbtn\"),t.getElement(\"verifyCodeImg\").src=\"\",e&&e.length){t.$show(\"verifyCodeImgWrapper\"),t.getElement(\"verifyCodeImg\").src=t.constant.VERIFYCODE_URL_PREFIX+e,t.getElement(\"codeString\").value=e;var i=t.fireEvent(\"renderVerifycode\",{verifyStr:e,verifyCodeImg:t.constant.VERIFYCODE_URL_PREFIX+e});if(!i)return}else passport.data.getVerifyCodeStr(n).success(function(e){if(0==e.errInfo.no){t.$show(\"verifyCodeImgWrapper\"),t.getElement(\"verifyCodeImg\").src=t.constant.VERIFYCODE_URL_PREFIX+e.data.verifyStr,t.getElement(\"codeString\").value=e.data.verifyStr;var n=t.fireEvent(\"renderVerifycode\",{verifyStr:e.data.verifyStr,verifyCodeImg:t.constant.VERIFYCODE_URL_PREFIX+e.data.verifyStr});if(!n)return}});t.getElement(\"verifyCode_placeholder\")&&setTimeout(function(){t.$show(\"verifyCode_placeholder\")},200)},_getWDom:{parent:function(e){return e.parentNode||e.parentElement},next:function(e){do e=e.nextSibling;while(e&&1!=e.nodeType);return e},prev:function(e){do e=e.previousSibling;while(e&&1!=e.nodeType);return e}},clearVerifyCode:function(){var e=this;e.$hide(\"verifyCodeImgWrapper\"),e.getElement(\"codeString\").value=\"\"},getPhoenixId:function(e){if(this.config.uniqueId)return this.$getId(e);var t={pass_phoenix_login:\"pass-phoenix-login\",pass_phoenix_list_login:\"pass-phoenix-list-login\",pass_phoenix_btn:\"pass_phoenix_btn\"};return t[e]},getPhoenixElement:function(e){return this.getElement(e)?this.getElement(e):document.getElementById(this.getPhoenixId(e))},_getTemplateOther:function(){var e=[],t=this,n=0;return t.config.authsiteLogin&&(n=t.config.authsiteLogin.length),t.config.qrcode&&2!==t.config.qrcode&&n++,e.push('<div id=\"'+t.getPhoenixId(\"pass_phoenix_login\")+'\" class=\"tang-pass-login-phoenix\"><div class=\"pass-phoenix-title\">可以使用以下方式登录<span class=\"pass-phoenix-note\"></span></div><div id=\"'+t.getPhoenixId(\"pass_phoenix_list_login\")+'\" class=\"pass-phoenix-list clearfix'+(t.config.diaPassLogin&&2==t.config.qrcode?\" pass-phoenix-list-second\":\"\")+'\">'+(t.config.phoenixLimit&&n>t.config.phoenixLimit?'<em class=\"pass-phoenix-show\"></em>':\"\")+(t.config.sms||!t.config.diaPassLogin&&t.config.qrcode?'<a class=\"pass-normal-btn\" title=\"普通登录\" style=\"display:none\" data-type=\"normal\">普通登录</a>':\"\")+(t.config.authsiteLogin?'<div class=\"pass-phoenix-btn clearfix\" id=\"'+t.getPhoenixId(\"pass_phoenix_btn\")+'\"></div>':\"\")+(t.config.diaPassLogin&&1==t.config.qrcode||!t.config.diaPassLogin&&t.config.qrcode?'<a class=\"pass-qrcode-btn\" title=\"二维码登录\" data-type=\"qrcode\">二维码登录</a>':\"\")+'</div><div class=\"clear\"></div></div>'),e.join(\"\")},_getTemplateQrcode:function(){var e=this,t=[],n=e.config.qrcodeCfg&&e.config.qrcodeCfg.appHref||e.lang.appHref,i=e.config.qrcodeCfg&&e.config.qrcodeCfg.appName||e.lang.appName;return t.push('<div id=\"'+e.$getId(\"qrcode\")+'\" class=\"clearfix tang-pass-qrcode tang-pass-login\" style=\"display:none;\">'),t.push('<div class=\"tang-pass-qrcode-content\" id=\"'+e.$getId(\"qrcodeContent\")+'\">'),t.push('<div class=\"tang-pass-qrcode-init\">'),t.push('<p class=\"tang-pass-qrcode-title\">'+e.lang.qrcodeTitle+\"</p>\"),t.push('<div class=\"Qrcode-status-con tang-pass-qrcode-imgWrapper\" id=\"'+e.$getId(\"QrcodeMain\")+'\"><img class=\"tang-pass-qrcode-img\" src=\"'+e._domain.staticFile+'/passApi/img/loading.gif\"/>'+(e.config.qrcode_animation?'<p class=\"Qrcode-status-animation\" id=\"'+e.$getId(\"QrcodeAnimation\")+'\"></p>':\"\")+\"</div>\"),t.push('<div class=\"Qrcode-status-con Qrcode-status-success\" id=\"'+e.$getId(\"QrcodeSuccess\")+'\"><p class=\"Qrcode-status-icon\"></p><p>'+e.lang.QrcodeSuccessTip+'</p><p class=\"Qrcode-status-msg\">'+e.lang.QrcodeSuccessMsg+\"</p></div>\"),t.push('<div class=\"Qrcode-status-con Qrcode-status-error\" id=\"'+e.$getId(\"QrcodeError\")+'\"><p class=\"Qrcode-status-icon\"></p><p>'+e.lang.QrcodeErrorTip+'</p><p class=\"Qrcode-status-msg\">'+e.lang.QrcodeErrorMsg+\"</p></div>\"),t.push('<div class=\"Qrcode-status-con Qrcode-status-refresh\" id=\"'+e.$getId(\"QrcodeRefresh\")+'\"><p class=\"Qrcode-status-icon\"></p><p class=\"refresh-title refresh-timeout\">'+e.lang.QrcodeRefreshTip+'</p><p class=\"refresh-title refresh-loadout\">'+e.lang.QrcodeLoadTip+'</p><p class=\"Qrcode-refresh-btn\" id=\"'+e.$getId(\"QrcodeRefreshBtn\")+'\">'+e.lang.QrcodeRefreshBtn+\"</p></div>\"),t.push('<p class=\"tang-pass-qrcode-info\">'+e.lang.qrcodeMsg.replace(\"#{appHref}\",n).replace(\"#{appName}\",i)+\"</p>\"),t.push(\"</div>\"),t.push(\"</div>\"),t.push(e.config.diaPassLogin&&1==e.config.qrcode?'<a id=\"'+e.$getId(\"qrcode_btn_back\")+'\" class=\"pass-qrcode-link pass-qrcode-link-back\">'+e.lang.backToLogin+\"</a>\":\"\"),t.push(\"</div>\"),t.join(\"\")},_setEventQrcode:function(){var e=this;baidu(e.getElement(\"qrcode_btn_back\")).on(\"click\",function(){e._changeLoginType(\"normal\")}),3==e.config.qrcode&&1==e.config.loginMergeQrcode&&(/msie 6/i.test(navigator.userAgent)||/msie 7/i.test(navigator.userAgent)?setTimeout(function(){e._changeLoginType(\"qrcode\")},0):e._changeLoginType(\"qrcode\"))},_setChannel:function(){var e=this,t={apiver:\"v3\",tt:(new Date).getTime(),tpl:e.config.product||\"\"};passport.spareWData=passport.spareWData||{},baidu(\".Qrcode-status-con\").hide(),e.$show(e.getElement(\"QrcodeMain\")),passport.spareWData.loadQrcode=setTimeout(function(){(e.config.diaPassLogin||e.config.defaultCss||e.config.qrcode_style)&&(baidu(\".Qrcode-status-con\").hide(),baidu(\".refresh-title\").hide(),baidu(\".refresh-loadout\").show(),e.$show(e.getElement(\"QrcodeRefresh\")))},5e3),baidu.ajax({url:e._domain.https+\"/v2/api/getqrcode?lp=pc&gid=\"+(e.guideRandom||\"\"),dataType:\"jsonp\",data:t,success:function(t){clearTimeout(passport.spareWData.loadQrcode),clearTimeout(passport.spareWData.unicast),passport.spareWData.channelimg=(window.location?window.location.protocol:document.location.protocol)+\"//\"+t.imgurl,passport.spareWData.sign=t.sign,e._createChannel(passport.spareWData.sign);for(var n=baidu(\".tang-pass-qrcode-img\"),i=0,s=n.length;s>i;i++)n.get(i).src=passport.spareWData.channelimg},error:function(){clearTimeout(passport.spareWData.loadQrcode),clearTimeout(passport.spareWData.unicast),(e.config.diaPassLogin||e.config.defaultCss||e.config.qrcode_style)&&(baidu(\".Qrcode-status-con\").hide(),e.$show(e.getElement(\"QrcodeError\")))}})},_stopChannel:function(){passport.spareWData=passport.spareWData||{},passport.spareWData.sign=\"\",clearInterval(passport.spareWData.timer)},_createChannel:function(sign){var me=this,qrcodeSign=sign,container=me.getElement(\"qrcodeContent\"),qrcodeInit=baidu(\".tang-pass-qrcode-init\",container).get(0),qrcodeImg=baidu(\".tang-pass-qrcode-img\",qrcodeInit).get(0),data={apiver:\"v3\",tt:(new Date).getTime()};passport.spareWData=passport.spareWData||{},passport.spareWData.unicast=setTimeout(function(){baidu(\".Qrcode-status-con\").hide(),me.$show(me.getElement(\"QrcodeError\"))},35e3),baidu.ajax({url:me._domain.https+\"/channel/unicast?channel_id=\"+passport.spareWData.sign+\"&tpl=\"+me.config.product+\"&gid=\"+(me.guideRandom||\"\"),dataType:\"jsonp\",data:data,success:function(d){if(clearTimeout(passport.spareWData.unicast),d.channel_v)try{d.channel_v=eval(\"(\"+d.channel_v+\")\")}catch(e){d.channel_v={}}else d.channel_v={};if(d.channel_v.u&&(d.channel_v.u=decodeURIComponent(d.channel_v.u)),d.errno+\"\"==\"0\"&&d.channel_v.status+\"\"==\"0\"){clearInterval(passport.spareWData.timer);\nvar data={bduss:d.channel_v.v,u:encodeURIComponent(d.channel_v.u||me.config.u),qrcode:1,tpl:me.config.product?me.config.product:\"\"};passport.data.jsonp(\"/v2/api/bdusslogin?tt=\"+(new Date).getTime(),data).success(function(e){var t=me.fireEvent(\"loginSuccess\",{rsp:e});t&&(window.location.href=e.data.u)})}else d.errno+\"\"==\"0\"&&\"1\"==d.channel_v.status?(me.config.diaPassLogin||me.config.defaultCss||me.config.qrcode_style)&&(baidu(\".Qrcode-status-con\").hide(),me.$show(me.getElement(\"QrcodeSuccess\"))):d.errno+\"\"==\"0\"&&\"2\"==d.channel_v.status&&(clearInterval(passport.spareWData.timer),me.config.diaPassLogin||me.config.defaultCss||me.config.qrcode_style?(baidu(\".Qrcode-status-con\").hide(),baidu(\".refresh-title\").hide(),baidu(\".refresh-timeout\").show(),me.$show(me.getElement(\"QrcodeRefresh\"))):(qrcodeImg&&(qrcodeImg.src=me._domain.staticFile+\"/passApi/img/loading.gif\"),me._setChannel(),passport.spareWData.timer=setInterval(function(){me._setChannel()},3e5))),qrcodeSign===passport.spareWData.sign&&me._createChannel(qrcodeSign)},error:function(){clearTimeout(passport.spareWData.unicast),(me.config.diaPassLogin||me.config.defaultCss||me.config.qrcode_style)&&(baidu(\".Qrcode-status-con\").hide(),me.$show(me.getElement(\"QrcodeError\")))}})},refreshQrcode:function(){var e=this;clearTimeout(passport.spareWData.unicast);var t=e.getElement(\"qrcodeContent\"),n=baidu(\".tang-pass-qrcode-init\",t).get(0),i=baidu(\".tang-pass-qrcode-img\",n).get(0);i&&(i.src=e._domain.staticFile+\"/passApi/img/loading.gif\"),e._setChannel(),passport.spareWData.timer=setInterval(function(){e._setChannel()},3e5)},_actionQrcode:function(){var e=this,t=e.qrcodeDialogDom?e.qrcodeDialogDom:this.getElement(),n=e._getWDom.parent(t);e._getWDom.parent(n),passport.spareWData=passport.spareWData||{},passport.spareWData.channelimg||(e._setChannel(),passport.spareWData.timer=setInterval(function(){e._setChannel()},3e5))},_showQrcode:function(){var e=this,t=this.getElement(),n=e._getWDom.parent(t),i=e._getWDom.parent(n),s=baidu(\".pass-qrcode-btn\",i).get(0);e._getWDom.prev(t)&&e.$hide(e._getWDom.prev(t)),e.$hide(\"choiceuser_article\").$hide(t).$show(baidu(\".tang-pass-qrcode\",n).get(0)),e.$hide(e._getWDom.next(s)?s:e._getWDom.parent(e._getWDom.parent(s)))},qrcodeAnimationShow:function(){var e=this;e.supportCss3Anim()?baidu(e.getElement(\"QrcodeMain\")).removeClass(\"Qrcode-animationRight\").addClass(\"Qrcode-animation\"):baidu(e.getElement(\"QrcodeMain\")).css(\"margin-left\",\"39px\"),baidu(e.getElement(\"QrcodeAnimation\")).addClass(\"Qrcode-status-guideAnim\")},qrcodeAnimationHide:function(){var e=this;baidu(e.getElement(\"QrcodeAnimation\")).removeClass(\"Qrcode-status-guideAnim\"),e.supportCss3Anim()?baidu(e.getElement(\"QrcodeMain\")).removeClass(\"Qrcode-animation\").addClass(\"Qrcode-animationRight\"):baidu(e.getElement(\"QrcodeMain\")).css(\"margin-left\",\"99px\")},supportCss3Anim:function(){var e=document.getElementsByTagName(\"body\")[0].style;return\"undefined\"!=typeof e.animation||\"undefined\"!=typeof e.WebkitAnimation?!0:!1},setqrcodeEvent:function(){var e=this;e.config.qrcode_animation&&(baidu(e.getElement(\"QrcodeMain\")).on(\"mouseenter\",function(t){t&&t.preventDefault&&t.preventDefault(),e.qrcodeAnimationShow()}),baidu(e.getElement(\"QrcodeMain\")).on(\"mouseleave\",function(t){t&&t.preventDefault&&t.preventDefault(),e.qrcodeAnimationHide()})),baidu(e.getElement(\"QrcodeRefreshBtn\")).on(\"click\",function(){e.refreshQrcode()})},_getTemplateSms:function(){var e=this,t=2==e.config.sms||3==e.config.sms?\"\":\"none\",n='<div id=\"'+e.$getId(\"sms\")+'\" class=\"tang-pass-login tang-pass-sms\" style=\"display:'+t+'\">',i={u:e.config.u,staticPage:e.config.staticPage,tpl:e.config.product?e.config.product:\"\",idc:e.config.idc?e.config.idc:\"\",isdpass:\"1\",gid:e.guideRandom||\"\",switchuname:\"\",smsCodeString:\"\",smsVcodesign:\"\",smsVcodestr:\"\",subpro:e.config.subpro,is_voice_sms:e.config.is_voice_sms,voice_sms_flag:0};return n+='<p class=\"tang-pass-sms-title\">短信登录</p>',n+='<p class=\"tang-pass-sms-tip\">'+(e.config.smsText||\"验证即登录，未注册将自动创建百度帐号\")+\"</p>\",n+='<form id=\"'+e.$getId(\"smsForm\")+'\" method=\"POST\">',n+=e._getHiddenField(i,\"smsHiddenFields\"),n+='<p id=\"'+e.$getId(\"smsErrorWrapper\")+'\" class=\"pass-generalErrorWrapper\"><span id=\"'+e.$getId(\"smsError\")+'\" class=\"pass-generalError\"></span></p>',n+='<div id=\"'+e.$getId(\"smsPhoneWrapper\")+'\" class=\"pass-form-item pass-form-item-smsPhone'+(e.foreignMobile?\" pass-form-item-PhoneCountry\":\"\")+'\"><label for=\"'+e.$getId(\"smsPhone\")+'\" id=\"'+e.$getId(e.foreignMobile?\"smsPhoneCountryLabel\":\"smsPhoneLabel\")+'\" class=\"pass-label pass-label-smsPhone\" data-countryCode=\"\">'+(e.foreignMobile?\"+86\":e.lang.smsPhone)+'</label><input id=\"'+e.$getId(\"smsPhone\")+'\" type=\"text\" name=\"username\" class=\"pass-text-input pass-text-input-smsPhone\" /><span id=\"'+e.$getId(\"smsPhoneTip\")+'\" class=\"pass-item-tip pass-item-tip-smsPhone\" style=\"display:none\"><span id=\"'+e.$getId(\"smsPhoneTipText\")+'\"></span></span>'+(e.foreignMobile?'<ul id=\"'+e.$getId(\"smsCountryList\")+'\" class=\"pass-country-list\"></ul>':\"\")+\"</div>\",n+='<p id=\"'+e.$getId(\"smsVerifyCodeWrapper\")+'\" class=\"pass-form-item pass-form-item-smsVerifyCode\"><label for=\"'+e.$getId(\"smsVerifyCode\")+'\" id=\"'+e.$getId(\"smsVerifyCodeLabel\")+'\" class=\"pass-label pass-label-smsVerifyCode\">'+e.lang.smsVerifyCode+'</label><input id=\"'+e.$getId(\"smsVerifyCode\")+'\" type=\"text\" name=\"password\" class=\"pass-text-input pass-text-input-smsVerifyCode\" /><button id=\"'+e.$getId(\"smsTimer\")+'\" class=\"pass-item-timer\">发送'+e.lang.smsVerifyCode+'</button><span id=\"'+e.$getId(\"smsVerifyCodeTip\")+'\" class=\"pass-item-tip pass-item-tip-smsVerifyCode\" style=\"display:none\"><span id=\"'+e.$getId(\"smsVerifyCodeTipText\")+'\"></span></span></p>',n+=1!=e.config.is_voice_sms?'<p id=\"'+e.$getId(\"smsSubmitWrapper\")+'\" class=\"pass-form-item pass-form-item-submit\"><input id=\"'+e.$getId(\"smsSubmit\")+'\" type=\"submit\" value=\"登录\" class=\"pass-button pass-button-submit\" /><span class=\"tang-pass-sms-agreement\">'+e.lang.agree+'<a target=\"_blank\" href=\"'+e.constant.PROTOCAL_URL+'\">'+e.lang.baiduUserProtocal+\"</a></span>\"+(3==e.config.sms?\"\":'<a id=\"'+e.$getId(\"sms_btn_back\")+'\" class=\"pass-sms-link pass-sms-link-back\">'+e.lang.backToLogin+\"</a>\")+\"</p>\":'<p id=\"'+e.$getId(\"smsSubmitWrapper\")+'\" class=\"pass-form-item pass-form-item-submit\"><input id=\"'+e.$getId(\"smsSubmit\")+'\" type=\"submit\" value=\"登录\" class=\"pass-button pass-button-submit\" /><input  type=\"button\" style=\"border:none;background:none;margin-top:12px;cursor:pointer;color:#2e7fdb;font-size:12px\" class=\"pass-is_voice\"  id=\"getVoiceSms\" value=\"获取语音验证码\" />'+(3==e.config.sms?\"\":'<a id=\"'+e.$getId(\"sms_btn_back\")+'\" class=\"pass-sms-link pass-sms-link-back\">'+e.lang.backToLogin+\"</a>\")+'</br><span class=\"tang-pass-sms-agreement\">'+e.lang.agree+'<a target=\"_blank\" href=\"'+e.constant.PROTOCAL_URL+'\">'+e.lang.baiduUserProtocal+\"</a></span></p>\",n+=\"</form>\",n+=\"</div>\"},_setEventSms:function(){var e=this,t=this.getElement(),n=e._getWDom.parent(t),i=e._getWDom.parent(n),s=baidu(\"#\"+e.$getId(\"sms\"),i).get(0);baidu(\".pass-text-input\",s),e.foreignMobile&&baidu(e.getElement(\"smsPhoneCountryLabel\")).on(\"click\",function(t){var n=e.getElement(\"smsCountryList\");n&&\"block\"!=n.style.display?(e.$show(n),baidu(e.getElement(\"smsPhoneCountryLabel\")).addClass(\"pass-label-code-up\")):n&&(e.$hide(n),baidu(e.getElement(\"smsPhoneCountryLabel\")).removeClass(\"pass-label-code-up\")),e._selectCountryList(e.getElement(\"smsPhoneWrapper\")),t.preventDefault()}),baidu(\".pass-text-input\",s).on(\"mouseover\",function(){var t=e.fireEvent(\"fieldMouseover\",{ele:baidu(this)});t&&baidu(this).addClass(e.constant.HOVER_CLASS)}),baidu(\".pass-text-input\",s).on(\"mouseout\",function(){var t=e.fireEvent(\"fieldMouseout\",{ele:baidu(this)});t&&baidu(this).removeClass(e.constant.HOVER_CLASS)}),baidu(\".pass-text-input\",s).on(\"keydown\",function(t){13==t.keyCode&&(t&&t.preventDefault&&t.preventDefault(),e._submitSmsForm(t))}),baidu(e.getElement(\"smsPhone\")).on(\"focus\",function(){e.initialized||e._initApi();var t=e.fireEvent(\"fieldFocus\",{ele:baidu(this)});if(t){baidu(this).addClass(e.constant.FOCUS_CLASS),baidu(e.getElement(\"smsPhoneLabel\")).addClass(e.constant.LABEL_FOCUS_CLASS),baidu(this).removeClass(e.constant.ERROR_CLASS);var n=document.getElementById(e.$getId(\"smsRegPromptWrapper\"));n&&e.$hide(n)}}),baidu(e.getElement(\"smsVerifyCode\")).on(\"focus\",function(){e.initialized||e._initApi();var t=e.fireEvent(\"fieldFocus\",{ele:baidu(this)});t&&(baidu(this).addClass(e.constant.FOCUS_CLASS),baidu(e.getElement(\"smsVerifyCodeLabel\")).addClass(e.constant.LABEL_FOCUS_CLASS),baidu(this).removeClass(e.constant.ERROR_CLASS))}),baidu(\".pass-text-input\",s).on(\"blur\",function(){if(this.value){var t=e.fireEvent(\"fieldBlur\",{ele:baidu(this)});if(!t)return;\"username\"==this.name?e._validatorPhoneFn(this):e._validatorSmsFn(this)}baidu(this).removeClass(e.constant.FOCUS_CLASS),baidu(e.getElement(\"smsPhoneLabel\")).removeClass(e.constant.LABEL_FOCUS_CLASS)}),baidu(\"#\"+e.$getId(\"smsTimer\"),s).on(\"click\",function(t){e.config.voice_sms_flag=0,t.preventDefault(),e._checkRegPhone()}),baidu(\"#\"+e.$getId(\"smsSubmit\"),s).on(\"click\",function(t){t&&t.preventDefault&&t.preventDefault(),e._submitSmsForm(t)}),(2==e.config.sms||3==e.config.sms)&&(/msie 6/i.test(navigator.userAgent)||/msie 7/i.test(navigator.userAgent)?setTimeout(function(){e._changeLoginType(\"sms\")},0):e._changeLoginType(\"sms\")),baidu(e.getElement(\"smsSwitch\")).on(\"click\",function(){/msie 6/i.test(navigator.userAgent)||/msie 7/i.test(navigator.userAgent)?setTimeout(function(){e._changeLoginType(\"sms\")},0):e._changeLoginType(\"sms\")}),baidu(e.getElement(\"sms_btn_back\")).on(\"click\",function(){e._changeLoginType(\"normal\"),e.getElement(\"password\")&&e._doFocus(\"password\")}),baidu(document.getElementById(\"getVoiceSms\")).on(\"click\",function(t){e.config.voice_sms_flag=1,t.preventDefault(),e._checkRegPhone()})},_setSmsGeneralError:function(e){this.getElement(\"smsError\").innerHTML=e},_sendVcode:function(e){var t,n=e||this,i=(n.config.voice_sms_flag,document.getElementById(n.$getId(\"smsPhone\"))),s=n.getElement(\"smsPhoneCountryLabel\")?baidu(n.getElement(\"smsPhoneCountryLabel\")).attr(\"data-countrycode\")||\"\":\"\",o=60,r=baidu(\"#\"+n.$getId(\"sms\")).get(0);if(n._validatorPhoneFn(i)){baidu(\"#\"+n.$getId(\"smsRegPromptBtn\"),r).off(\"click\"),baidu(\"#\"+n.$getId(\"smsRegPromptBtn\"),r).on(\"click\",function(e){e.preventDefault()}),baidu(\"#\"+n.$getId(\"smsTimer\"),r).off(\"click\"),baidu(\"#\"+n.$getId(\"smsTimer\"),r).on(\"click\",function(e){e.preventDefault()}),baidu(\"#\"+n.$getId(\"smsTimer\"),r).removeClass(\"pass-item-timer\"),baidu(\"#\"+n.$getId(\"smsTimer\"),r).addClass(\"pass-item-time-timing\");var a={gid:n.guideRandom||\"\",username:n._SBCtoDBC(i.value),countrycode:s,bdstoken:n.bdPsWtoken,tpl:n.config.product?n.config.product:\"\",flag_code:n.config.voice_sms_flag};a.dv=document.getElementById(\"dv_Input\")?document.getElementById(\"dv_Input\").value:window.LG_DV_ARG&&window.LG_DV_ARG.dvjsInput||\"\";var c=\"\";c=1==n.config.voice_sms_flag?window.location.protocol.toLowerCase()+\"//wappass.baidu.com/wp/api/login/sms?is_voice_sms=\"+n.config.voice_sms_flag:n._domain.auto+\"/v2/api/senddpass\",passport.data.jsonp(c,a).success(function(e){if(0!=e.errInfo.no){if(18==e.data.errno||19==e.data.errno||\"50020\"==e.errInfo.no||\"50021\"==e.errInfo.no){var a=n.constant.VERIFYCODE_URL_PREFIX+e.data.vcodestr;n.getElement(\"smsHiddenFields_smsVcodesign\").value=e.data.vcodesign,n.getElement(\"smsHiddenFields_smsVcodestr\").value=e.data.vcodestr,confirmSmsVerifyWidget?(n.getElement(\"confirmVerifyCodeImg\").src=a,n.getElement(\"confirmVerifyCode\").value=\"\",n._ownerDialog&&n._ownerDialog.hide(\"unHide\"),confirmSmsVerifyWidget.show()):passport._load(n._domain.auto+\"/passApi/js/uni_wrapper.js\",!0,function(){confirmSmsVerifyWidget=passport.pop.init({type:\"confirmWidget\",tangram:!0,titleText:\"安全验证\",width:490,apiOpt:{Continue:\"确定\",contentHTML:'<p class=\"pass-confirm-verifyWidget-msg\">请填写图中的验证码</p><p class=\"pass-confirm-verifyWidget-imgWrapper\"><input type=\"text\" class=\"pass-text-input pass-confirm-verifyWidget-verifyCode\" id=\"'+n.$getId(\"confirmVerifyCode\")+'\" name=\"confirmVerifyCode\" value=\"\" /><img src=\"'+a+'\" title=\"\" class=\"pass-confirm-verifyWidget-verifyCode-img\" id=\"'+n.$getId(\"confirmVerifyCodeImg\")+'\" /><a href=\"#\" class=\"pass-confirm-verifyWidget-imgChange\" id=\"'+n.$getId(\"confirmVerifyCodeChange\")+'\">换一张</a><span class=\"pass-confirm-verifyWidget-error\" id=\"'+n.$getId(\"confirmVerifyCodeError\")+'\"></span></p>'},onRender:function(){baidu(confirmSmsVerifyWidget.getElement(\"confirmWidget_footer\")).addClass(\"pass-confirm-verifyWidget-bottom\"),n.config.hasPlaceholder&&n._getPlaceholder([{label:\"confirmVerifyCode\",placeholder:\"verifyCode\"}]),baidu(n.getElement(\"confirmVerifyCodeChange\")).on(\"click\",function(){baidu(n.getElement(\"confirmVerifyCodeImg\")).attr(\"src\",n.constant.VERIFYCODE_URL_PREFIX+n.getElement(\"smsHiddenFields_smsVcodestr\").value+\"&v=\"+(new Date).getTime())}),baidu(n.getElement(\"confirmVerifyCode\")).on(\"keyup\",function(){baidu(n.getElement(\"confirmVerifyCode\")).removeClass(\"pass-text-input-error\"),baidu(n.getElement(\"confirmVerifyCodeError\")).hide(),baidu(n.getElement(\"confirmVerifyCodeError\")).get(0).innerHTML=\"\"})},onConfirmClose:function(){baidu(n.getElement(\"confirmVerifyCodeError\")).hide(),baidu(n.getElement(\"confirmVerifyCodeError\")).get(0).innerHTML=\"\",confirmSmsVerifyWidget.hide(),n._ownerDialog&&n._ownerDialog.show()},onConfirmCancel:function(){},onConfirmContinue:function(){if(\"\"==n.getElement(\"confirmVerifyCode\").value)return baidu(n.getElement(\"confirmVerifyCode\")).addClass(\"pass-text-input-error\"),baidu(n.getElement(\"confirmVerifyCodeError\")).show(),void(baidu(n.getElement(\"confirmVerifyCodeError\")).get(0).innerHTML=n.lang.confirmVerCodeEmpty);var e=document.getElementById(\"dv_Input\"),a={gid:n.guideRandom||\"\",username:n._SBCtoDBC(i.value),countrycode:s,bdstoken:n.bdPsWtoken,tpl:n.config.product?n.config.product:\"\",vcodestr:n.getElement(\"smsHiddenFields_smsVcodestr\").value,vcodesign:n.getElement(\"smsHiddenFields_smsVcodesign\").value,verifycode:n._SBCtoDBC(n.getElement(\"confirmVerifyCode\").value),flag_code:n.config.voice_sms_flag,dv:e?e.value:window.LG_DV_ARG&&window.LG_DV_ARG.dvjsInput||\"\"},c=\"\";c=1==n.config.voice_sms_flag?window.location.protocol.toLowerCase()+\"//wappass.baidu.com/wp/api/login/sms?is_voice_sms=\"+n.config.voice_sms_flag:n._domain.auto+\"/v2/api/senddpass\",passport.data.jsonp(c,a).success(function(e){if(0==e.errInfo.no){if(1==n.config.voice_sms_flag){var i=15;document.getElementById(\"getVoiceSms\").disabled=!0,t=setInterval(function(){0==--i?(clearInterval(t),baidu(\"#\"+n.$getId(\"smsTimer\"),r).removeClass(\"pass-item-time-timing\"),baidu(\"#\"+n.$getId(\"smsTimer\"),r).addClass(\"pass-item-timer\"),document.getElementById(\"getVoiceSms\").disabled=!1,document.getElementById(\"getVoiceSms\").value=\"重新发送语音验证码\",document.getElementById(n.$getId(\"smsTimer\")).innerHTML=\"重新发送\",i=60):document.getElementById(\"getVoiceSms\").value=\"已发送\"+i+\"s\"},1e3)}else t=setInterval(function(){0==--o?(clearInterval(t),baidu(\"#\"+n.$getId(\"smsTimer\"),r).removeClass(\"pass-item-time-timing\"),baidu(\"#\"+n.$getId(\"smsTimer\"),r).addClass(\"pass-item-timer\"),document.getElementById(n.$getId(\"smsTimer\")).innerHTML=\"重新发送\",o=60):document.getElementById(n.$getId(\"smsTimer\")).innerHTML=\"重新发送(\"+o+\")\"},1e3);baidu(n.getElement(\"confirmVerifyCodeError\")).hide(),baidu(n.getElement(\"confirmVerifyCodeError\")).get(0).innerHTML=\"\",confirmSmsVerifyWidget.hide(),n._ownerDialog&&n._ownerDialog.show()}else 20==e.data.errno||21==e.data.errno?(baidu(n.getElement(\"confirmVerifyCode\")).addClass(\"pass-text-input-error\"),baidu(n.getElement(\"confirmVerifyCodeError\")).show(),baidu(n.getElement(\"confirmVerifyCodeError\")).get(0).innerHTML=e.data.msg,n.getElement(\"confirmVerifyCodeImg\").src=n.constant.VERIFYCODE_URL_PREFIX+e.data.vcodestr,n.getElement(\"confirmVerifyCode\").value=\"\",n.getElement(\"smsHiddenFields_smsVcodesign\").value=e.data.vcodesign,n.getElement(\"smsHiddenFields_smsVcodestr\").value=e.data.vcodestr):27==e.data.errno?document.location.href=\"https://passport.baidu.com/v2/?reg&overseas=\"+n.config.overseas+\"&tpl=\"+n.config.product+\"&u=\"+encodeURIComponent(n.config.u):(baidu(n.getElement(\"confirmVerifyCodeError\")).hide(),confirmSmsVerifyWidget.hide(),n._ownerDialog&&n._ownerDialog.show(),n._setSmsGeneralError(1==n.config.voice_sms_flag?e.errInfo.msg:e.data.msg))})}}),n._ownerDialog&&n._ownerDialog.hide(\"unHide\"),confirmSmsVerifyWidget.show()})}else 27==e.data.errno?document.location.href=\"https://passport.baidu.com/v2/?reg&overseas=\"+n.config.overseas+\"&tpl=\"+n.config.product+\"&u=\"+encodeURIComponent(n.config.u):n._setSmsGeneralError(1!=n.config.voice_sms_flag?e.data.msg:e.errInfo.msg);baidu(\"#\"+n.$getId(\"smsTimer\"),r).addClass(\"pass-item-timer\"),baidu(\"#\"+n.$getId(\"smsTimer\"),r).removeClass(\"pass-item-time-timing\"),document.getElementById(n.$getId(\"smsTimer\")).innerHTML=\"重新发送\"}else if(1==n.config.voice_sms_flag){var c=15;document.getElementById(\"getVoiceSms\").disabled=!0,t=setInterval(function(){0==--c?(clearInterval(t),baidu(\"#\"+n.$getId(\"smsTimer\"),r).removeClass(\"pass-item-time-timing\"),baidu(\"#\"+n.$getId(\"smsTimer\"),r).addClass(\"pass-item-timer\"),document.getElementById(\"getVoiceSms\").disabled=!1,document.getElementById(\"getVoiceSms\").value=\"重新发送语音验证码\",document.getElementById(n.$getId(\"smsTimer\")).innerHTML=\"重新发送\",c=15):document.getElementById(\"getVoiceSms\").value=\"已发送\"+c+\"s\"},1e3)}else t=setInterval(function(){0==--o?(clearInterval(t),baidu(\"#\"+n.$getId(\"smsTimer\"),r).removeClass(\"pass-item-time-timing\"),baidu(\"#\"+n.$getId(\"smsTimer\"),r).addClass(\"pass-item-timer\"),document.getElementById(n.$getId(\"smsTimer\")).innerHTML=\"重新发送\",o=60):document.getElementById(n.$getId(\"smsTimer\")).innerHTML=\"重新发送(\"+o+\")\"},1e3);baidu(\"#\"+n.$getId(\"smsTimer\"),r).on(\"click\",function(e){n.config.voice_sms_flag=0,e.preventDefault(),n._checkRegPhone()})})}},_validatorPhoneFn:function(e){var t=this;if(\"\"==e.value)return t._setSmsGeneralError(\"请填写手机号\"),baidu(e).addClass(t.constant.ERROR_CLASS),!1;if(t.getElement(\"smsPhoneCountryLabel\")&&\"\"!=baidu(t.getElement(\"smsPhoneCountryLabel\")).attr(\"data-countrycode\")){if(!new RegExp(/^(\\d)*$/).test(t._SBCtoDBC(e.value)))return t._setSmsGeneralError(\"手机号码格式不正确\"),baidu(e).addClass(t.constant.ERROR_CLASS),!1}else if(!new RegExp(/^1[3456789]\\d{9}$/).test(t._SBCtoDBC(e.value)))return t._setSmsGeneralError(\"手机号码格式不正确\"),baidu(e).addClass(t.constant.ERROR_CLASS),!1;return t._setSmsGeneralError(\"\"),baidu(e).removeClass(t.constant.ERROR_CLASS),!0},_validatorSmsFn:function(e){var t=this;return\"\"==e.value?(t._setSmsGeneralError(\"请填写验证码\"),baidu(e).addClass(t.constant.ERROR_CLASS),!1):(t._setSmsGeneralError(\"\"),!0)},_postSmsData:function(e){var t=this;e.countrycode=t.getElement(\"smsPhoneCountryLabel\")?baidu(t.getElement(\"smsPhoneCountryLabel\")).attr(\"data-countrycode\")||\"\":\"\",e.token=t.bdPsWtoken,passport.data.traceID&&passport.data.traceID.startFlow&&passport.data.traceID.startFlow(\"login\"),e.dv=document.getElementById(\"dv_Input\")?document.getElementById(\"dv_Input\").value:window.LG_DV_ARG&&window.LG_DV_ARG.dvjsInput||\"\",passport.data.login(e).success(function(e){if(e.loginType=\"sms\",0==e.errInfo.no){var n=t.fireEvent(\"loginSuccess\",{rsp:e});if(!n)return;window.location.href=e.data.u}else{t.getElement(\"smsSubmit\").style.color=\"#fff\";var n=t.fireEvent(\"loginError\",{rsp:e});if(!n)return;t._setSmsGeneralError(4==e.errInfo.no?t.lang.captchaErr:e.errInfo.msg),(3==e.errInfo.no||4==e.errInfo.no)&&t._clearInput(\"smsVerifyCode\")}})},smsLoginSubmit:function(e){var t=this,e=e||{},n=baidu.form.json(t.getElement(\"smsForm\"));e.errInfo&&3==e.errInfo.no?passport.data.post(\"/v2/unite-bind\",{username:e.data.username||\"\",password:n.password,countrycode:t.getElement(\"smsPhoneCountryLabel\")?baidu(t.getElement(\"smsPhoneCountryLabel\")).attr(\"data-countrycode\")||\"\":\"\",sms:1,apiver:\"v3\",token:e.data.token||\"\"}).success(function(){t._postSmsData(n)}):t._postSmsData(n)},_submitSmsForm:function(){function e(){t._postSmsData(o)}var t=this,n=document.getElementById(t.$getId(\"smsPhone\")),i=document.getElementById(t.$getId(\"smsVerifyCode\"));if(!t._validatorPhoneFn(n))return void n.focus();if(t._validatorSmsFn(i)){var s=t.fireEvent(\"beforeSubmit\");if(s){t.getElement(\"smsSubmit\").style.color=\"#9ebef4\";var o=baidu.form.json(t.getElement(\"smsForm\"));o.password=t._SBCtoDBC(o.password),o.username=t._SBCtoDBC(o.username),o.FP_UID=t._getCookie(\"FP_UID\")||\"\",o.FP_INFO=window.PP_FP_INFO||\"\",t.loginConnect({username:o.username,password:o.password,countrycode:t.getElement(\"smsPhoneCountryLabel\")?baidu(t.getElement(\"smsPhoneCountryLabel\")).attr(\"data-countrycode\")||\"\":\"\",smsVcode:o.password,isdpass:1,sms:1},{fail:function(e){t._setSmsGeneralError(e)}},e)}}},_setEventChoiceUser:function(){var e=this,t=function(){baidu(e.getElement()).removeClass(\"tang-pass-login-hide\"),e.$show(e.getElement()).$hide(\"choiceuser_article\")},n=function(){baidu(e.getElement()).removeClass(\"tang-pass-login-hide\"),e.$show(e.getElement()).$hide(\"choiceuser_article\"),e.submit()};baidu(e.getElement(\"choiceuser_btn_username\")).on(\"click\",function(t){e.getElement(\"loginMerge\").value=\"false\",n(t)}),baidu(e.getElement(\"choiceuser_btn_mobile\")).on(\"click\",function(t){e.getElement(\"isPhone\").value=\"true\",e.getElement(\"loginMerge\").value=\"false\",n(t)}),baidu(e.getElement(\"choiceuser_btn_back\")).on(\"click\",function(e){e.preventDefault(),t()})},_getToken:function(e){var t=this;passport.spareWData=passport.spareWData||{},passport.data.getApiInfo({apiType:\"login\",gid:t.guideRandom||\"\"}).success(function(n){t.bdPsWtoken=n.data.token,e&&e(t)})},_getRSA:function(e){var t=this;passport.data.getRsaKey({gid:t.guideRandom||\"\"}).success(function(t){t.errInfo.no||0==t.errInfo.no||(t=t.data);var n=new passport.lib.RSA;n.setKey(t.pubkey),e&&e({RSA:n,rsakey:t.key})})},_changeLoginType:function(e){var t=this,n=this.getElement(),i=0,s=t._getWDom.parent(n),o=t._getWDom.parent(s),r=t.getElement(\"qrcode\"),a=t.getElement(\"sms\"),c=baidu(\".tang-pass-login-phoenix\",o).get(0),l={normal:{$btn:baidu(\".pass-normal-btn\",t.getPhoenixElement(\"pass_phoenix_list_login\")),$ele:baidu(t.getElement(\"form\")).parent()},sms:{$btn:baidu(\".pass-sms-btn\",t.getPhoenixElement(\"pass_phoenix_list_login\")),$ele:baidu(t.getElement(\"sms\"))},qrcode:{$btn:baidu(\".pass-qrcode-btn\",t.getPhoenixElement(\"pass_phoenix_list_login\")),$ele:baidu(t.getElement(\"qrcode\"))}},d=t.getElement(\"choiceuser_article\");e=e||\"normal\",!t.config.diaPassLogin||t.currentLoginType&&\"normal\"!=t.currentLoginType||(i=Math.max(s.offsetHeight,340),a&&(a.style.height=i+\"px\"),r&&(r.style.height=i+\"px\")),d&&t.$hide(\"choiceuser_article\");var u=t.fireEvent(\"changeLoginType\",{loginType:e,currentLoginType:t.currentLoginType||\"\"});if(u){for(var p in l)l[p].$ele&&l[p].$ele.length>0&&(p==e?(\"sms\"!=e&&t.$hide(l[p].$btn[0]),t.$show(l[p].$ele[0])):\"qrcode\"==p&&t.config.diaPassLogin&&3==t.config.qrcode?(t.$show(l[p].$btn[0]),t.config.qrcode_animation&&(t.qrcodeAnimationShow(),setTimeout(function(){t.qrcodeAnimationHide()},300))):(\"sms\"!=p&&t.$show(l[p].$btn[0]),t.$hide(l[p].$ele[0])));t.config.diaPassLogin&&c&&(c.style.display=\"normal\"==e?\"\":\"none\"),\"qrcode\"==e&&t._actionQrcode(),t.currentLoginType=e}},_doFocus:function(e){var t=this;t.config.autoFocus&&(\"string\"==(typeof e).toLowerCase()&&t.getElement(e)?t.getElement(e).focus():e.focus())},_clearInput:function(e){var t=this,n=t.getElement(e),i=t.getElement(e+\"_placeholder\"),s=t.getElement(e+\"_clearbtn\");n&&(i&&t.$show(i),s&&t.$hide(i),n.value=\"\",t._doFocus(n))},_insertAfterW:function(e,t){var n=this,i=n._getWDom.parent(t);i.lastChild==t?i.appendChild(e):i.insertBefore(e,n._getWDom.next(t))},_insertNoCaptchaScript:function(){var e=this;e._insertScriptW(e.constant.NOCAPTCHA_URL,function(){})},_checkCapsLock:function(){var e=this,t=baidu(e.getElement(\"password\"));t.on(\"keypress\",function(t){var n=t||window.event,i=n.keyCode||n.which,s=n.shiftKey||16==i||!1,o=document.getElementById(e.$getId(\"caps\"));if(i>=65&&90>=i&&!s||i>=97&&122>=i&&s)if(o)e.$show(o);else{var r=document.createElement(\"span\");r.id=e.$getId(\"caps\"),r.innerHTML=\"大小写锁定已打开\";var a=document.getElementById(e.$getId(\"passwordWrapper\"));\"static\"==a.style.position&&(a.style.position=\"relative\"),a.style.zIndex=a.style.zIndex?a.style.zIndex+1:20,r.style.cssText=\"position:absolute;left:60px;clear:both;top:25px;width:103px;height:37px;font-size:12px;line-height:45px;z-index:20;text-align:center;background:url('\"+e._domain.staticFile+\"/passApi/img/caps.gif') no-repeat 0 0;\",a.appendChild(r)}else o&&e.$hide(o)}),t.on(\"blur\",function(){var t=document.getElementById(e.$getId(\"caps\"));t&&e.$hide(t)})},_checkRegPhone:function(){var e=this,t=e.getElement(\"smsPhoneCountryLabel\")?baidu(e.getElement(\"smsPhoneCountryLabel\")).attr(\"data-countrycode\")||\"\":\"\",n=document.getElementById(e.$getId(\"smsPhone\"));e._validatorPhoneFn(n)&&passport.data.getphonestatus({gid:e.guideRandom||\"\",phone:e._SBCtoDBC(n.value),countrycode:t}).success(function(i){var s=e.fireEvent(\"_checkRegPhone\",{rsp:i});if(s)if(0==i.errInfo.no)e.config.sendVcodeBefore&&\"function\"==typeof e.config.sendVcodeBefore?e.config.sendVcodeBefore(e,e._sendVcode,function(){n.value=\"\",n.focus()}):e.bdPsWtoken?e._sendVcode():e._getToken(e._sendVcode);else if(3==i.errInfo.no){var o=e.config.voice_sms_flag,r=document.getElementById(e.$getId(\"smsRegPromptWrapper\")),a=document.getElementById(e.$getId(\"smsPhoneWrapper\"));if(r)e.$show(r),e.getElement(\"smsRegPromptBtn\").focus();else{var c=document.createElement(\"div\");c.id=e.$getId(\"smsRegPromptWrapper\"),c.setAttribute(\"class\",\"pass-form-sms-checkphone\"),c.style.cssText='position:absolute;clear:both;color:#826f33;z-index:999;font-size:12px;width:211px;height:71px;padding:16px 16px 11px 13px;background:url(\"'+e._domain.staticFile+'/passApi/img/smsRegphone.png\") 0px 0px no-repeat;right:0px;',c.innerHTML='<p style=\"margin:0px;padding:0px;line-height:2em;\">您的手机号码尚未注册，点击注册，帮您注册新的百度帐号</p><button id=\"'+e.$getId(\"smsRegPromptBtn\")+'\" style=\"background:#2e82ff;border:none;color:#fff;cursor:pointer;height:25px;line-height:25px;width:60px;text-align:center;position:absolute;right:16px;top:66px;\" hidefocus=true>注册</button>',a.appendChild(c),e.getElement(\"smsRegPromptBtn\").focus()}baidu(e.getElement(\"smsRegPromptBtn\")).on(\"click\",function(i){e.config.voice_sms_flag=o,e.getElement(\"smsRegPromptWrapper\")&&baidu(e.getElement(\"smsRegPromptWrapper\")).hide(),i.preventDefault(),\"\"!=t?window.location.href=e.constant.REG_URL:e.config.sendVcodeBefore&&\"function\"==typeof e.config.sendVcodeBefore?e.config.sendVcodeBefore(e,e._sendVcode,function(){n.value=\"\",n.focus()}):e.bdPsWtoken?e._sendVcode():e._getToken(e._sendVcode)}),e.config.voice_sms_flag=0}else e.config.voice_sms_flag=0,e._setSmsGeneralError(i.errInfo.msg)})},changeSuggestView:function(e){var t=this;t.suggestionDom&&e.list&&(\"hide\"==e.list?t.$hide(t.suggestionDom):\"show\"==e.list&&t.$show(t.suggestionDom)),t.selectBtn&&e.btn&&(\"close\"==e.btn?(baidu(t.selectBtn).removeClass(\"open\"),baidu(t.getElement(\"userName\")).addClass(\"open\"),t.$show(t.selectBtn)):\"open\"==e.btn?(baidu(t.selectBtn).addClass(\"open\"),baidu(t.getElement(\"userName\")).addClass(\"open\"),t.$show(t.selectBtn)):\"hide\"==e.btn?(t.$hide(t.selectBtn),baidu(t.getElement(\"userName\")).removeClass(\"open\")):\"show\"==e.btn&&(t.$show(t.selectBtn),baidu(t.getElement(\"userName\")).addClass(\"open\")),t.$hide(t.selectBtn))},_suggestion:function(e){var t=this,n=[],i=baidu(\"#\"+t.$getId(\"userName\"),t.getElement()),s=[\"qq.com\",\"163.com\",\"126.com\",\"sohu.com\",\"sina.com\",\"gmail.com\",\"21cn.com\",\"hotmail.com\",\"vip.qq.com\",\"yeah.net\",\"139.com\"],o=/^([a-zA-Z0-9_.\\-+]+)([@]?[a-zA-Z0-9_\\-*]*[.]?[a-zA-Z*]*[.]?[a-zA-Z*]*)$/,r=function(e,t){var n=e;return e.substr(0,e.indexOf(\"@\")-1).length>t.maxlength&&(n=e.substr(0,t.maxlength-4)+\"…\"+e.substr(e.indexOf(\"@\"))),baidu('<li class=\"pass-item-suggsetion\" data-select=\"'+e+'\" data-type=\"'+(t.ifdelete?\"history\":\"normal\")+'\">'+n+(t.ifdelete?'<a data-delete=\"'+e+'\" title=\"删除该记录\"></a>':\"\")+\"</li>\").get(0)},a=function(e,i){t.suggestionDom||(t.suggestionDom=document.createElement(\"ul\"),t.suggestionDom.id=t.$getId(\"suggestionWrapper\"),baidu(t.getElement(\"userNameWrapper\")).append(t.suggestionDom),baidu(t.suggestionDom).addClass(\"pass-suggestion-list\"),baidu(t.suggestionDom).on(\"click\",function(e){var s=baidu(e.target),o=s.attr(\"data-delete\"),r=s.attr(\"data-select\");if(o)e.preventDefault(),passport.data.getLoginHistory({token:t.bdPsWtoken,item:o}),t.suggestionDom.data_delete=!0,baidu(s.parent()).hide(),baidu.array(n).remove(o),n.length<1&&t.changeSuggestView({list:\"hide\",btn:\"hide\"}),t._doFocus(\"userName\"),setTimeout(function(){t.suggestionDom.data_delete=!1},200);else{\"history\"==s.attr(\"data-type\")?i.value=r:(t.suggestionDom.data_delete=!1,i.value=r||i.value),t.getElement(\"userName_placeholder\")&&t.$hide(\"userName_placeholder\"),t.changeSuggestView({list:\"hide\",btn:\"close\"}),t._doFocus(i),setTimeout(function(){t.setGeneralError(\"\"),baidu(i).removeClass(\"pass-text-input-error\"),t._doFocus(\"password\")},100);var a=t.getElement(\"userName\").value;t._loginCheck(a)}})),t.suggestionDom.innerHTML=\"\",t.$show(t.suggestionDom),t.suggestionDom.appendChild(e),baidu(\".pass-item-suggsetion\",t.suggestionDom).on(\"mouseover\",function(){baidu(\".pass-item-suggsetion_hover\",t.suggestionDom).removeClass(\"pass-item-suggsetion_hover\"),baidu(this).addClass(\"pass-item-suggsetion_hover\")}),baidu(\".pass-item-suggsetion\",t.suggestionDom).on(\"mouseout\",function(){baidu(this).removeClass(\"pass-item-suggsetion_hover\")})};!function(){if(n=t.config.loginMerge?t.loginrecord.displayname||[]:t.config.isPhone?t.loginrecord.phone:t.loginrecord.email,n.length>0){for(var i=document.createDocumentFragment(),s=0,o=n.length;o>s;s++)i.appendChild(r(n[s],{maxlength:e,ifdelete:!0}));a(i,t.getElement(\"userName\")),t.selectBtn=baidu('<span class=\"pass-item-selectbtn pass-item-selectbtn-userName\" ></span>').get(0),t.getElement(\"userNameWrapper\").appendChild(t.selectBtn),baidu(t.selectBtn).on(\"click\",function(){setTimeout(function(){t.changeSuggestView(\"none\"!=t.suggestionDom.style.display?{list:\"hide\",btn:\"close\"}:{list:\"show\",btn:\"open\"})},200)}),t.changeSuggestView({list:\"hide\",btn:\"show\"})}}(),i.on(\"keyup\",function(i){if(1==t.disUnameLogin);else{var c,l=document.createDocumentFragment(),d=this,u=0;if(n.length>0)for(var p=0,g=n.length;g>p;p++)0==n[p].indexOf(this.value)&&(l.appendChild(r(n[p],{maxlength:e,ifdelete:!0})),++u);if((n.length<1||1>u)&&(c=o.exec(this.value),c&&c[2]))for(var p=0,g=s.length;g>p;p++)if(0==(\"@\"+s[p]).indexOf(c[2])){var h=c[1];l.appendChild(r(h+\"@\"+s[p],{maxlength:e})),++u}if(t.suggestionDom&&38!==i.keyCode&&40!==i.keyCode&&t.$hide(t.suggestionDom),(n.length>1||n.length<2&&0==t.config.isPhone)&&u>0&&(38!==i.keyCode&&40!==i.keyCode&&a(l,d),(38==i.keyCode||40==i.keyCode)&&\"none\"!=t.suggestionDom.style.display)){for(var f=t.suggestionDom.childNodes,m=f.length,v=-1,b=0;m>b;b++)f[b].className.indexOf(\"pass-item-suggsetion_hover\")>-1&&(v=b);38==i.keyCode&&(q=-1===v?m-1:0===v?m-1:v-1),40==i.keyCode&&(q=-1===v?0:v===m-1?0:v+1),baidu(\".pass-item-suggsetion_hover\",t.suggestionDom).removeClass(\"pass-item-suggsetion_hover\"),baidu(f[q],t.suggestionDom).addClass(\"pass-item-suggsetion_hover\");var y=baidu(f[q]).attr(\"data-select\");d.value=\"history\"==baidu(f[q]).attr(\"data-type\")?y:d.value.substr(0,d.value.indexOf(\"@\"))+y.substr(y.indexOf(\"@\")),t.getElement(\"userName_placeholder\")&&t.$hide(\"userName_placeholder\")}}}),i.on(\"keydown\",function(e){13!=e.keyCode&&9!=e.keyCode||!t.suggestionDom||\"none\"==t.suggestionDom.style.display||(t.changeSuggestView({list:\"hide\",btn:\"close\"}),t._doFocus(\"password\"),e.preventDefault(),e.stopPropagation())}),i.on(\"blur\",function(){0==t.config.isPhone&&setTimeout(function(){t.suggestionDom&&!t.suggestionDom.data_delete&&t.changeSuggestView({list:\"hide\",btn:\"close\"})},150)}),i.on(\"focus\",function(){0==t.config.isPhone&&t.changeSuggestView({list:\"show\",btn:\"open\"})})},_initCountryCode:function(e){var t=this,n='<li class=\"pass-item-country\"><span class=\"pass-country-code\" data-countryCode=\"\">+86</span>中国</li>',i=t.countryCodeList||{},s=i.length;if(!(0>=s)){for(var o=0;s>o;o++)n+='<li class=\"pass-item-country\"><span class=\"pass-country-code\" data-countryCode='+i[o].code+\">+\"+i[o].code.substring(2)+\"</span>\"+i[o].name+\"</li>\";\nbaidu(e).html(n)}},_getCountryCode:function(e){var t=this,n={apiver:\"v3\",subpro:t.config.subpro};passport.data.jsonp(\"https://passport.baidu.com/v2/?securitygetcountrycode\",n).success(function(n){n.data.country.length>0&&(t.countryCodeList=n.data.country,t.getElement(\"foreignCountryList\")&&t._initCountryCode(t.getElement(\"foreignCountryList\")),t.getElement(\"smsCountryList\")&&t._initCountryCode(t.getElement(\"smsCountryList\")),e&&e())})},_selectCountryList:function(e){var t=this,n=baidu(e),i=n.find(\".pass-country-list\").eq(0),s=n.find(\".pass-label\");0!=s.length&&(i.on(\"click\",function(n){var o=n.target;\"li\"==o.tagName.toLowerCase()?(s.eq(0).html(baidu(o).find(\"span.pass-country-code\").eq(0).html()),s.eq(0).attr(\"data-countryCode\",baidu(o).find(\"span.pass-country-code\").eq(0).attr(\"data-countryCode\"))):\"span\"==o.tagName.toLowerCase()&&(s.eq(0).html(baidu(o).html()),s.eq(0).attr(\"data-countryCode\",baidu(o).attr(\"data-countryCode\"))),t.$hide(i[0]),s.eq(0).removeClass(\"pass-label-code-up\"),e==t.getElement(\"foreignMobileWrapper\")&&t.getElement(\"foreignMobile\")&&t.getElement(\"foreignMobile\").value?t._validatorforeignmobileFn(t.getElement(\"foreignMobile\")):e==t.getElement(\"smsPhoneWrapper\")&&t.getElement(\"smsPhone\")&&t.getElement(\"smsPhone\").value&&t._validatorPhoneFn(t.getElement(\"smsPhone\")),n.preventDefault()}),i.on(\"mouseover\",function(e){var t=e.target;\"li\"==t.tagName.toLowerCase()?(n.find(\".pass-item-country-hover\").removeClass(\"pass-item-country-hover\"),baidu(t).addClass(\"pass-item-country-hover\")):\"span\"==t.tagName.toLowerCase()&&(n.find(\".pass-item-country-hover\").removeClass(\"pass-item-country-hover\"),baidu(t).parent(\"li.pass-item-country\").addClass(\"pass-item-country-hover\"))}),i.on(\"mouseout\",function(e){var t=e.target;\"li\"==t.tagName.toLowerCase()?baidu(t).removeClass(\"pass-item-country-hover\"):\"span\"==t.tagName.toLowerCase()&&baidu(t).parent(\"li.pass-item-country\").removeClass(\"pass-item-country-hover\")}),baidu(\"html\").on(\"click\",function(e){var n=e.target;return s?void(baidu(n).attr(\"id\")!=baidu(t.getElement(\"foreignMobileLabel\")).attr(\"id\")&&baidu(n).attr(\"id\")!=baidu(t.getElement(\"smsPhoneCountryLabel\")).attr(\"id\")&&setTimeout(function(){t.$hide(i[0]),s.eq(0).removeClass(\"pass-label-code-up\")},200)):!1}))},_setForeignMobileEvent:function(){var e=this;e.getElement(\"foreignMobileLabel\")&&baidu(e.getElement(\"foreignMobileLabel\")).on(\"click\",function(t){var n=e.getElement(\"foreignCountryList\");n&&\"block\"!=n.style.display?(e.$show(n),baidu(e.getElement(\"foreignMobileLabel\")).addClass(\"pass-label-code-up\")):n&&(e.$hide(n),baidu(e.getElement(\"foreignMobileLabel\")).removeClass(\"pass-label-code-up\")),e._selectCountryList(e.getElement(\"foreignMobileWrapper\")),t.preventDefault()}),e.getElement(\"foreignMobile\")&&(baidu(e.getElement(\"foreignMobile\")).on(\"blur\",function(){if(this.value){var t=e.fireEvent(\"fieldBlur\",{ele:baidu(this)});if(!t)return;e._validatorforeignmobileFn(this)}baidu(this).removeClass(e.constant.FOCUS_CLASS)}),baidu(e.getElement(\"foreignMobile\")).on(\"focus\",function(){e.initialized||e._initApi();var t=e.fireEvent(\"fieldFocus\",{ele:baidu(this)});t&&(baidu(this).addClass(e.constant.FOCUS_CLASS),baidu(this).removeClass(e.constant.ERROR_CLASS))})),e.getElement(\"foreignMobileLink\")&&baidu(e.getElement(\"foreignMobileLink\")).on(\"click\",function(t){e.$hide(e.getElement(\"userNameWrapper\")),e.$hide(e.getElement(\"smsSwitchWrapper\")),e.$hide(e.getElement(\"foreignMobileLink\")),baidu(e.getElement(\"userName\")).removeClass(e.constant.ERROR_CLASS),e.setGeneralError(\"\"),e.getElement(\"password\").value=\"\",e.$show(e.getElement(\"foreignMobileWrapper\")),e.$show(e.getElement(\"foreignMobileMsg\")),e.$show(e.getElement(\"foreignMobileBackWrapper\")),e.internation=!0,t.preventDefault()}),e.getElement(\"foreignMobileBackWrapper\")&&baidu(e.getElement(\"foreignMobileBackWrapper\")).on(\"click\",function(t){e.$hide(e.getElement(\"foreignMobileWrapper\")),e.$hide(e.getElement(\"foreignMobileMsg\")),e.$hide(e.getElement(\"foreignMobileBackWrapper\")),baidu(e.getElement(\"foreignMobile\")).removeClass(e.constant.ERROR_CLASS),e.setGeneralError(\"\"),e.getElement(\"password\").value=\"\",e.$show(e.getElement(\"userNameWrapper\")),e.$show(e.getElement(\"smsSwitchWrapper\")),e.$show(e.getElement(\"foreignMobileLink\")),e.internation=!1,t.preventDefault()})},_validatorforeignmobileFn:function(e){var t=this;if(\"\"==e.value)return t.setGeneralError(\"请填写手机号\"),baidu(e).addClass(t.constant.ERROR_CLASS),!1;if(t.getElement(\"foreignMobileLabel\")&&\"\"!=baidu(t.getElement(\"foreignMobileLabel\")).attr(\"data-countrycode\")){if(!new RegExp(/^(\\d)*$/).test(t._SBCtoDBC(e.value)))return t.setGeneralError(\"手机号码格式不正确\"),baidu(e).addClass(t.constant.ERROR_CLASS),!1}else if(!new RegExp(/^1[3456789]\\d{9}$/).test(t._SBCtoDBC(e.value)))return t.setGeneralError(\"手机号码格式不正确\"),baidu(e).addClass(t.constant.ERROR_CLASS),!1;return t.setGeneralError(\"\"),baidu(e).removeClass(t.constant.ERROR_CLASS),!0},_operateTips:function(){var e=this,t=baidu(\"#\"+e.$getId(\"userName\"),e.getElement());if(0==e.config.isPhone)if(e.operateTipsDom)e.$show(e.operateTipsDom);else{e.operateTipsDom=document.createElement(\"div\"),e.operateTipsDom.id=e.$getId(\"operateTipsWrapper\"),t.parent().parent().append(e.operateTipsDom),baidu(e.operateTipsDom).addClass(\"pass-operate-tips\");var n='<span class=\"pass-operate-content\">邮箱登录更安全哦</span><span class=\"pass-operate-down\"><em class=\"pass-operate-down-a\">◆</em><em class=\"pass-operate-down-b\">◆</em></span>';e.operateTipsDom.innerHTML=n}t.on(\"focus\",function(){0==e.config.isPhone&&e.operateTipsDom&&e.$show(e.operateTipsDom)}),t.on(\"blur\",function(){e.operateTipsDom&&e.$hide(e.operateTipsDom)})},_rendPhoenixbtn:function(){var e=this,t=baidu(e.getPhoenixElement(\"pass_phoenix_list_login\")),n=baidu(\".pass-phoenix-show\",e.getPhoenixElement(\"pass_phoenix_list_login\"));n&&n.on(\"click\",function(){t.hasClass(\"pass-phoenix-list-hover\")?t.removeClass(\"pass-phoenix-list-hover\"):t.addClass(\"pass-phoenix-list-hover\")}),t.on(\"click\",function(t){var n=baidu(t.target),i=n.attr(\"data-type\");i&&e._changeLoginType(i)})},setMakeText:function(e){var t=this,n=t.getElement(\"MakeTextWrapper\"),e=e.replace(/</g,\"&lt;\").replace(/>/g,\"&gt;\").replace(/\"/g,\"&quot;\").replace(/\\x22/g,\"&quot;\").replace(/\\x27/g,\"&#39;\");n&&(e?(n.style.display=\"\",n.innerHTML=e):(n.style.display=\"none\",n.innerHTML=\"\"))},render:function(e){var t=this;t.getElement()||t.$mappingDom(\"\",e||document.body);var n=baidu(t.getElement());n.addClass(t.constant.CONTAINER_CLASS);var i=t._getTemplate();if(n.get(0).appendChild(baidu(i).get(0)),t.config.makeText&&t.setMakeText(t.config.makeText),t.config.setWebToClient){var s=t._getIrregularField(\"webtoclint\");t._insertAfterW(baidu(s).get(0),t.getElement())}if((t.config.authsiteLogin||!t.config.diaPassLogin&&t.config.qrcode||t.config.diaPassLogin&&1==t.config.qrcode)&&3!=t.config.sms){var o=t._getTemplateOther();t._insertAfterW(baidu(o).get(0),n.get(0)),t._rendPhoenixbtn()}if(t.config.authsiteLogin&&t._authSiteW(),t.config.qrcode){var r=t._getTemplateQrcode();\"[object function]\"==Object.prototype.toString.call(t.config.qrcodeDom).toLowerCase()&&t.config.diaPassLogin&&3==t.config.qrcode?(t.qrcodeDialogDom=t.config.qrcodeDom(),t.qrcodeDialogDom.appendChild(baidu(r).get(0)),setTimeout(function(){t._actionQrcode()},500),t.getElement(\"qrcode\").style.display=\"\"):(t._insertAfterW(baidu(r).get(0),n.get(0)),t._setEventQrcode()),t.setqrcodeEvent()}if(t.config.sms){var r=t._getTemplateSms();t._insertAfterW(baidu(r).get(0),n.get(0)),t._setEventSms()}if(t.config.loginMerge&&setTimeout(function(){t.getElement(\"loginMerge\").value=\"true\"},200),t.config.hasPlaceholder){var a=[{label:\"userName\",placeholder:\"userName\"},{label:\"password\",placeholder:\"password\"},{label:\"verifyCode\",placeholder:\"verifyCode\"}];t.config.sms&&(a.push({label:\"smsPhone\",placeholder:t.config&&t.config.diaPassLogin?\"smsPhoneMsg\":\"smsPhone\"}),a.push({label:\"smsVerifyCode\",placeholder:\"smsVerifyCode\"})),t.foreignMobile&&a.push({label:\"foreignMobile\",placeholder:t.config&&t.config.diaPassLogin?\"smsPhoneMsg\":\"smsPhone\"}),t._getPlaceholder(a)}t.foreignMobile&&(t._getCountryCode(),t._setForeignMobileEvent());var c=t.fireEvent(\"render\");c&&(t._setValidator(),t._setEvent(),t._checkCapsLock())},_initApi:function(e){var t=this;t.initialized=!0,t.initTime=(new Date).getTime(),passport.data.getApiInfo({apiType:\"login\",gid:t.guideRandom||\"\",loginType:t.config&&t.config.diaPassLogin?\"dialogLogin\":\"basicLogin\"}).success(function(n){var i=t.fireEvent(\"getApiInfo\",{rsp:n});if(i&&(1==n.data.disable&&t.setGeneralError(t.lang.sysUpdate),0==n.errInfo.no)){var s=n.data.token;t.bdPsWtoken=n.data.token,t.loginrecord={},t.config.loginMerge&&t.config.autosuggest?passport.data.getLoginHistory({token:t.bdPsWtoken,tt:(new Date).getTime(),gid:t.guideRandom}).success(function(e){t.loginrecord=e.data,t._suggestion(t.config.diaPassLogin?20:12),t.config.memberPass&&t.loginrecord.displayname.length>0&&(t._doFocus(\"password\"),t.getElement(\"userName_placeholder\")&&t.$hide(\"userName_placeholder\"),t.getElement(\"userName\").value&&\"\"!=t.getElement(\"userName\").value||(t.getElement(\"userName\").value=t.loginrecord.displayname[0],t._loginCheck(t.loginrecord.displayname[0])),t.$show(\"userName_clearbtn\").$hide(\"userName_placeholder\"))}):t.config.isPhone||!t.config.memberPass||t.constant.SUBMITFLAG||(t.getElement(\"userName\").value=n.data.rememberedUserName);var o=(navigator.userAgent,!navigator.userAgent.match(/OS [1-8]_\\d[_\\d]* like Mac OS X/i)),r=!!navigator.userAgent.toString().match(/\\(i[^;]+;( U;)? CPU.+Mac OS X/),a=navigator.userAgent.toString().indexOf(\"iPad\");if(o&&r&&null!=a){var c=document.getElementsByClassName(\"popBox\");null!=c&&c.length>0&&(c[0].style.height=window.screen.height>document.body.clientHeight?window.screen.height*(window.screen.height/document.body.clientHeight)+120+\"px\":window.screen.height*(window.screen.height/document.body.clientHeight))}t.disUnameLogin=0,t.ifShowWarning=n.data.ifShowWarning,n.data.spLogin&&t.config.diaPassLogin&&(t.spLogin=n.data.spLogin),passport.data.setContext({token:s}),navigator.cookieEnabled||t.setGeneralError(t.lang.cookieDisable),!t.config.loginMerge&&t.config.memberPass&&n.data.rememberedUserName&&!t.config.isPhone&&t.config.diaPassLogin&&3==n.data.usernametype&&t.switchTo(\"phone\"),t.config.diaPassLogin&&!t.config.loginMerge&&t._operateTips(),t.constant.SUBMITFLAG?t.getElement(\"submit\").click():e&&e.success(n)}})},submitForm:function(){var e=this;e.constant.SUBMITFLAG=!0},switchTo:function(e){var t=this;t.config.loginMerge||(t._collectData(),setTimeout(function(){t.setGeneralError(\"\"),t.selectBtn&&\"phone\"==e?t.$hide(t.selectBtn):t.selectBtn&&t.$hide(t.selectBtn)},100),t.getElement(\"userNameLabel\").innerHTML=\"phone\"==e?t.lang.phoneNum:t.lang.account,t.config.isPhone=\"phone\"==e?!0:!1,t.getElement(\"isPhone\").value=t.config.isPhone,t._restoreData(),t._setValidator(),t.suggestionDom&&t.$hide(t.suggestionDom))},setSubpro:function(e){var t=this;t.getElement(\"subpro\")&&e&&(t.getElement(\"subpro\").value=e.replace(/</g,\"&lt;\").replace(/>/g,\"&gt;\").replace(/\"/g,\"&quot;\").replace(/\\x22/g,\"&quot;\").replace(/\\x27/g,\"&#39;\"))},getCurrentType:function(){return this.config.isPhone?\"phone\":\"normal\"},_setValidator:function(){var e=this;e.validatorInited||(e._validator.addRule(\"unameMailLength\",function(e){var t=String(e.value);return/^[0-9a-zA-Z\\.\\_-]+@([0-9a-zA-Z-]+\\.)+[a-z]{2,4}$/.test(t)?t.length<=60:!0}),e._validator.addMsg(\"unameMailLength\",e.lang.unameMailLengthError),e._validator.addRule(\"unameInputLogin\",function(t){var n=String(t.value);return 0!==e.disUnameLogin||!e.config.diaPassLogin||e.config.isPhone||/^[0-9a-zA-Z\\.\\_-]+@([0-9a-zA-Z-]+\\.)+[a-z]{2,4}$/.test(n)?!0:!1}),e._validator.addMsg(\"unameInputLogin\",e.lang.unameInputError),e._validator.addRule(\"checkVcodeLength\",function(t){return t.value,e.constant.CHECKVERIFYCODE?!0:(e.$hide(\"verifyCodeSuccess\"),!1)}),e._validator.addMsg(\"checkVcodeLength\",e.lang.verifyCodeLenErr),e._validator.addRule(\"checkVcodeStatus\",function(t,n){return\"all\"!=n||e.constant.CHECKVERIFYCODE?!0:!1}),e._validator.addMsg(\"checkVcodeStatus\",e.lang.verifyCodeStaErr)),e.validatorInited=!0,e.validateRules={userName:{rules:e.config.loginMerge?[\"required\"]:e.config.isPhone?[\"required\",\"phone\"]:[\"required\",\"unameMailLength\",\"unameInputLogin\"],desc:e.config.loginMerge?e.lang.userName:e.config.isPhone?e.lang.phoneNum:e.lang.account},password:{rules:[\"required\"],desc:e.lang.password},verifyCode:{rules:[\"required\",\"checkVcodeLength\",\"checkVcodeStatus\"],desc:e.lang.captcha}},e._validator.init(e,e.validateRules)},_validateError:function(e,t){var n=this,i=baidu(n.getElement(e.field));if(n.getElement(\"operateTipsWrapper\")&&\"none\"!=n.getElement(\"operateTipsWrapper\").style.display&&n.$hide(\"operateTipsWrapper\"),i.addClass(n.constant.ERROR_CLASS),n.setGeneralError(e.msg),0===n.disUnameLogin&&\"userName\"==e.field&&e.msg==n.lang.unameInputError){var s=new Image;s.onload=s.onerror=function(){s.onload=s.onerror=null,s=null},s.src=n._domain.https+\"/img/v.gif?type=login&loginType=userName\"}t&&t.callback&&callback()},_enableUnameLoginCallback:function(e,t){var n=this,i=baidu('<input type=\"hidden\" name=\"userNameLogin\" value=\"1\">'),s=n.getElement(\"pass-pop-login-placeholder-normal\"),o=n.getElement().parentNode,r=baidu(\".tab li\",o),a=baidu(\".tab a\",o).get(0),c=baidu(e);if(e||t||(t=1===n.isLoginWeak?\"normal\":\"other\",c=n.eleLoginWeak),0==n.disUnameLogin){n.disUnameLogin=1,n._validator.confStorage[n.$getId()].userName.desc=\"用户名\",i.get(0).value=\"1\",s&&(s.innerHTML=\"用户名\"),a&&(a.innerHTML=\"用户名登录\"),n.normalLogin&&(n.normalLogin.innerHTML=\"用户名登录\",baidu(n.normalLogin).addClass(\"pass-normal-btn-s2\"),\"none\"!=n.normalLogin.style.display&&n._changeLoginType(\"normal\")),1==n.config.isPhone&&(n.switchTo(\"normal\"),r.removeClass(\"tab-selected\"),baidu(r.get(0)).addClass(\"tab-selected\")),0==n.config.isPhone?(n.getElement(\"userNameLabel\").innerHTML=\"用户名\",n.getElement(\"error\"),baidu(n.getElement(\"userName\")).removeClass(\"pass-text-input-error\"),n.operateTipsDom&&n.$show(n.operateTipsDom)):n.operateTipsDom&&n.$hide(n.operateTipsDom),baidu(\".tang-pass-pop-login-placeholder\").hide(),n.getElement(\"userName\").value||n.$show(\"pass-pop-login-placeholder-\"+(n.config.isPhone?\"phone\":\"normal\")),n.changeSuggestView({list:\"hide\",btn:\"hide\"}),\"normal\"==t?(c.removeClass(\"pass-unamelogin-btn\"),c.addClass(\"pass-emaillogin-btn\"),c.get(0).innerHTML=\"邮箱登录\"):\"other\"==t&&(c.get(0).innerHTML='忘记用户名?使用<a href=\"###\" id=\"pass-user-login\" tabIndex=\"-1\" data-click=\"other\">邮箱登录</a>');var l=new Image;l.onload=l.onerror=function(){l.onload=l.onerror=null,l=null},l.src=n._domain.https+\"/img/v.gif?type=login&loginType=normalName\"}else n.disUnameLogin=0,n._validator.confStorage[n.$getId()].userName.desc=\"邮箱\",i.get(0).value=\"0\",s&&(s.innerHTML=\"邮箱\"),a&&(a.innerHTML=\"邮箱登录\"),n.normalLogin&&(n.normalLogin.innerHTML=\"邮箱登录\",baidu(n.normalLogin).removeClass(\"pass-normal-btn-s2\"),\"none\"!=n.normalLogin.style.display&&n._changeLoginType(\"normal\")),1==n.config.isPhone&&(n.switchTo(\"normal\"),r.removeClass(\"tab-selected\"),baidu(r.get(0)).addClass(\"tab-selected\")),0==n.config.isPhone?(n.getElement(\"userNameLabel\").innerHTML=\"邮箱\",n.getElement(\"error\"),baidu(n.getElement(\"userName\")).removeClass(\"pass-text-input-error\"),n.operateTipsDom&&n.$show(n.operateTipsDom)):n.operateTipsDom&&n.$hide(n.operateTipsDom),baidu(\".tang-pass-pop-login-placeholder\").hide(),n.getElement(\"userName\").value||baidu(n.getElement(\"pass-pop-login-placeholder-\"+(n.config.isPhone?\"phone\":\"normal\"))).show(),n.changeSuggestView({list:\"hide\"}),n.selectBtn&&n.loginrecord&&n.loginrecord.email&&n.loginrecord.email.length>1?n.changeSuggestView({btn:\"show\"}):n.selectBtn&&n.changeSuggestView({btn:\"hide\"}),\"normal\"==t?(c.addClass(\"pass-unamelogin-btn\"),c.removeClass(\"pass-emaillogin-btn\"),c.get(0).innerHTML=\"用户名登录\"):\"other\"==t&&(c.get(0).innerHTML='忘记邮箱?使用<a href=\"###\" id=\"pass-user-login\" tabIndex=\"-1\" data-click=\"other\">用户名登录</a>')},_validateSuccess:function(e,t){var n=this,i=baidu(n.getElement(e.field));n.clearGeneralError(),i.removeClass(n.constant.ERROR_CLASS),t&&t.callback&&callback()},_defaultLoginErr:function(e){var t=this;if(t.vcodetype=e.data.vcodetype,e.data.codeString?(t.getVerifyCode(e.data.codeString),t._clearInput(\"verifyCode\")):t.clearVerifyCode(),400401==e.errInfo.no){if(t.getElement(\"choiceuser_article\"))t.$show(\"choiceuser_article\");else{var n=t._getIrregularField(\"choiceuser\");t._insertAfterW(baidu(n).get(0),t.getElement()),t._setEventChoiceUser()}baidu(t.getElement()).hide()}if(257==e.errInfo.no&&(baidu(t.getElement()).removeClass(\"tang-pass-login-hide\"),t.$show(t.getElement()).$hide(\"choiceuser_article\")),(6==e.errInfo.no||257==e.errInfo.no)&&t._clearInput(\"verifyCode\"),4==e.errInfo.no&&(t._clearInput(\"password\"),e.data.resetpwd)){var i=\"\";switch(e.data.resetpwd){case\"1\":i=\"1\"+t.lang.passwordResetIn;break;case\"2\":i=\"2\"+t.lang.passwordResetIn;break;case\"3\":i=\"3\"+t.lang.passwordResetIn;break;case\"4\":i=\"3\"+t.lang.passwordResetOut}i.length>0&&(e.errInfo.msg=t._format(t.lang.passwordResetWarn,{resetpwd:i}))}if(7==e.errInfo.no){var i=\"\",s=document.getElementsByClassName(\"pass-sms-btn\");i=s.length>0?t.lang.passwordResetSms:\":\",i.length>0&&(e.errInfo.msg=t._format(t.lang.passwordResetWarnNo,{resetpwd:i}))}if(e.errInfo.msg&&e.errInfo.msg.indexOf(\"#{\")>=0)if(110024==e.errInfo.no){var o=t._domain.https+\"/v2/?regnotify&action=resend&tpl=\"+t.config.product+\"&email=\"+encodeURIComponent(e.data.mail)+\"&u=\"+encodeURIComponent(e.data.u);e.errInfo.msg=t._format(e.errInfo.msg,{gotourl:o})}else{var r=t.getElement(\"userName\").value;e.errInfo.msg=t._format(e.errInfo.msg,{urldata:\"&account=\"+r+\"&tpl=\"+t.config.product+\"&u=\"+t.config.u})}e.errInfo.field?t.setValidateError(e.errInfo.field,e.errInfo.msg,e):t.setGeneralError(e.errInfo.msg,e)},_asyncValidate:{checkVerifycode:function(e){var t=this,n=t.getElement(\"verifyCode\"),i=t.getElement(\"codeString\");passport.data.checkVerifycode({verifycode:t._SBCtoDBC(n.value),codestring:i.value}).success(function(n){var i=t.fireEvent(\"checkVerifycode\",{rsp:n});i&&(0==n.errInfo.no?(e&&e.success(n),t.$hide(\"verifyCode_clearbtn\"),t.$show(\"verifyCodeSuccess\"),t.constant.CHECKVERIFYCODE=!0):500002==n.errInfo.no||500018==n.errInfo.no?(n.msg=n.errInfo.msg,e&&e.error(n),t.$hide(\"verifyCodeSuccess\"),t.constant.CHECKVERIFYCODE=!1):(e&&e.success(n),t.$hide(\"verifyCodeSuccess\"),t.constant.CHECKVERIFYCODE=!0))})}},_format:function(e,t){e=String(e);var n=Array.prototype.slice.call(arguments,1),i=Object.prototype.toString;return n.length?(n=1==n.length&&null!==t&&/\\[object Array\\]|\\[object Object\\]/.test(i.call(t))?t:n,e.replace(/#\\{(.+?)\\}/g,function(e,t){var s=n[t];return\"[object Function]\"==i.call(s)&&(s=s(t)),\"undefined\"==typeof s?\"\":s})):e},loginConnect:function(e,t,n){({username:e.username,smsVcode:e.smsVcode||\"\",sms:e.sms||\"\"}),n()},checkPhone:function(e,t){var n=this;checkPhoneWidget?(checkPhoneWidget.setMakePhone&&checkPhoneWidget.setMakePhone(t,e),n._ownerDialog&&n._ownerDialog.hide(\"unHide\"),checkPhoneWidget.show()):checkPhoneExist||passport._load(n._domain.auto+\"/passApi/js/uni_wrapper.js\",!0,function(){checkPhoneWidget=passport.pop.init({type:\"checkPhone\",apiOpt:{u:n.config.u,product:n.config.product?n.config.product:\"\",phone:t,apiMargicInstance:n,token:n.bdPsWtoken,username:e,isuserid:1,noSynBdu:n.config.noSynBdu||\"\",staticPage:n.config.staticPage},tangram:!0,onHide:function(){n._ownerDialog&&n._ownerDialog.show()}}),n._ownerDialog&&n._ownerDialog.hide(\"unHide\"),checkPhoneWidget.show()})},_loginCheck:function(e){var t=this,n=document.getElementById(\"dv_Input\")?document.getElementById(\"dv_Input\").value:window.LG_DV_ARG&&window.LG_DV_ARG.dvjsInput||\"\";n=n.length>1500?\"\":n,e.length&&t.validate(\"userName\",{success:function(){passport.data.loginCheck({sub_source:\"leadsetpwd\",userName:e,isPhone:t.config.isPhone,dv:n}).success(function(e){0==e.errInfo.no&&e.data.userid?(t.checkPhone(e.data.userid,e.data.mobile),checkPhoneExist=!0,t._ownerDialog&&t._ownerDialog.hide(\"unHide\")):e.data.codeString.length?(t.vcodetype=e.data.vcodetype,t.getVerifyCode(e.data.codeString)):t.clearVerifyCode()})}})},_SBCtoDBC:function(e){var t=\"\";if(e){for(var n=e.length,i=0;n>i;i++){var s=e.charCodeAt(i);s=s>=65281&&65374>=s?s-65248:s,s=12288==s?32:s,t+=String.fromCharCode(s)}return t}},submit:function(){var e=this;(!e.internation||e._validatorforeignmobileFn(e.getElement(\"foreignMobile\")))&&e.validateAll({success:function(){function t(){s.timeSpan=(new Date).getTime()-e.initTime,passport.data.traceID&&passport.data.traceID.startFlow&&passport.data.traceID.startFlow(\"login\"),e.internation?(s.username=e._SBCtoDBC(e.getElement(\"foreignMobile\").value),s.isPhone=!0,s.countrycode=baidu(e.getElement(\"foreignMobileLabel\")).attr(\"data-countrycode\")||\"\"):s.countrycode=\"\",s.FP_UID=e._getCookie(\"FP_UID\")||\"\",s.FP_INFO=window.PP_FP_INFO||\"\",s.dv=document.getElementById(\"dv_Input\")?document.getElementById(\"dv_Input\").value:window.LG_DV_ARG&&window.LG_DV_ARG.dvjsInput||\"\",passport.data.login(s).success(function(t){if(e.submitStatus=2,t.loginType=\"password\",0==t.errInfo.no){var n=e.fireEvent(\"loginSuccess\",{rsp:t});if(!n)return;window.location?window.location.href=t.data.u:document.location.href=t.data.u}else{c.value=e.lang.login,e.getElement(\"submit\").style.color=\"#fff\";var n=e.fireEvent(\"loginError\",{rsp:t});if(!n)return;e._defaultLoginErr(t)}})}e._doFocus(\"submit\"),e.submitStatus=1;var n=e.fireEvent(\"beforeSubmit\");if(e.getElement(\"submit\").style.color=\"#9ebef4\",n){if(e.spLogin){var i=baidu('<input type=\"hidden\" name=\"splogin\" value=\"'+e.spLogin+'\">');e.getElement(\"hiddenFields\").appendChild(i.get(0)),e.spLogin=null}var s=baidu.form.json(e.getElement(\"form\"));s.token=e.bdPsWtoken,passport.data.setContext(baidu.extend({},e.config)),s.foreignusername&&(s.foreignusername=e._SBCtoDBC(s.foreignusername)),s.userName=e._SBCtoDBC(s.userName),s.verifyCode=e._SBCtoDBC(s.verifyCode);var o=e._SBCtoDBC(e.getElement(\"password\").value);if(e.RSA&&e.rsakey){var r=o;r.length<128&&!e.config.safeFlag&&(s.password=baidu.url.escapeSymbol(e.RSA.encrypt(r)),s.rsakey=e.rsakey,s.crypttype=12)}var a,c=e.getElement(\"submit\"),l=15e3;e.getElement(\"submit\").style.color=\"#9ebef4\",c.value=e.lang.logining,a=setTimeout(function(){1!==e.submitStatus||e.config.connect||e.setGeneralError(e.lang.submitTimeup),c.value=e.lang.login},l),e.loginConnect({username:s.userName,password:s.password},{success:function(){clearTimeout(a),c.value=e.lang.login},fail:function(t){clearTimeout(a),c.value=e.lang.login,e.setGeneralError(t)}},t)}}},!0)},_eventHandler:function(){var e,t={focus:function(t){var n=e.fireEvent(\"fieldFocus\",{ele:this});n&&(this.addClass(e.constant.FOCUS_CLASS),this.removeClass(e.constant.ERROR_CLASS),baidu(e.getElement(t+\"Label\")).addClass(e.constant.LABEL_FOCUS_CLASS))},blur:function(t){var n=e.fireEvent(\"fieldBlur\",{ele:this});n&&(this.removeClass(e.constant.FOCUS_CLASS),baidu(e.getElement(t+\"Label\")).removeClass(e.constant.LABEL_FOCUS_CLASS))},mouseover:function(){var t=e.fireEvent(\"fieldMouseover\",{ele:this});t&&this.addClass(e.constant.HOVER_CLASS)},mouseout:function(){var t=e.fireEvent(\"fieldMouseout\",{ele:this});t&&this.removeClass(e.constant.HOVER_CLASS)},keyup:function(){e.fireEvent(\"fieldKeyup\",{ele:this})}},n={focus:{userName:function(){e.config.loginMerge&&e.getElement(\"loginMerge\")&&(e.getElement(\"loginMerge\").value=\"true\",e.getElement(\"isPhone\").value=\"\")},password:function(){e._getRSA(function(t){e.RSA=t.RSA,e.rsakey=t.rsakey})},verifyCode:function(){e.$hide(\"verifyCodeSuccess\")}},blur:{userName:function(){},password:function(t){var n=this.get(0).value;n.length&&e.validate(t)},verifyCode:function(t){var n=this.get(0).value;n.length&&e.validate(t);var i=e.getElement(\"verifyCode\"),s=baidu(i);i.value?e._asyncValidate.checkVerifycode.call(e,{error:function(t){s.addClass(e.constant.ERROR_CLASS),e.setGeneralError(t.msg)},success:function(){s.removeClass(e.constant.ERROR_CLASS),e.clearGeneralError()}}):e.$hide(\"verifyCodeSuccess\")}},change:{userName:function(){var t=this.get(0).value;e._loginCheck(t)},verifyCode:function(){}},click:{verifyCodeChange:function(t,n){e.getElement(\"verifyCode\").value=\"\",e._doFocus(\"verifyCode\"),e.getVerifyCode(),n.preventDefault()}},keyup:{},submit:function(t){e.submit(),t.preventDefault()}};return{entrance:function(i){e=this;var s=(baidu(i.target),i.target.name);if(!s&&i.target.id){var o=i.target.id.match(/\\d+__(.*)$/);o&&(s=o[1])}s&&(t.hasOwnProperty(i.type)&&t[i.type].apply(baidu(i.target),[s,i]),n.hasOwnProperty(i.type)&&(\"function\"==typeof n[i.type]&&n[i.type].apply(baidu(i.target),[i]),n[i.type].hasOwnProperty(s)&&n[i.type][s].apply(baidu(i.target),[s,i])),e.initialized||\"focus\"!=i.type||e._initApi())}}}(),$dispose:function(){var e=this;e.disposed||(baidu.dom(e.getElement()).removeClass(e.constant.CONTAINER_CLASS),e.getElement().removeChild(e.getElement(\"form\")),magic.Base.prototype.$dispose.call(e))}}),magic});"
  },
  {
    "path": "open-oauth-center/open-oauth-server/src/main/view/static/js/page.login_c7313e6.js",
    "content": "define(\"oauth:widget/page.login/page.login.js\",function(){window.loginSuccess=function(){var e=document.createElement(\"script\");e.src=\"https://passport.baidu.com/v3/login/api/auth?tpl=dev&return_type=2&callback=logaback\";var o=document.getElementsByTagName(\"script\"),n=o[o.length-1];n.async=!1,n.parentNode.insertBefore(e,n)},window.bdstokenSuccess=function(e){\"0\"==e.error_code&&authorize(e)},window.authorize=function(e){var o=document.forms.scopes,n=o.elements;n.bdstoken.value=e.bdstoken,n.grant_permissions.value=getGrantPermissions(n.grant_permissions_arr,devo.granted_perms),o.action=urlMergeParams({confirm_login:null}),o.submit()},function(){var e,o=\"https://passport.baidu.com/v2/?reg&authsite=0&tpl=dev&\",n={confirm_login:null,force_login:null},t=[];2==devo.confirm_login&&(n.confirm_login=1),e=encodeURIComponent(urlMergeParams(n)),t.push(\"u=\"+e),devo.quick_user?(t.push(\"regtype=2\"),t.push(\"hideback=1\"),t.push(\"loginu=\"+e)):t.push(\"adapter=smarttv\"),baidu(\"#reg-link\").attr(\"href\",o+t.join(\"&\"))}(),2==devo.confirm_login&&baidu(\"#change-acc\").attr(\"href\",urlMergeParams({confirm_login:1})),function(){var e=location.protocol+\"//\"+location.hostname+(location.port&&location.port.length?\":\"+location.port:\"\");baidu(\"#jumpurl\").val(e+\"/static/oauth/html/bdstoken_jump.html\"),baidu(document).on(\"loginSuccess\",loginSuccess),\"weibo_page\"!=devo.display&&\"weibo_iframe\"!=devo.display&&baidu(document).on(\"loginReady\",function(){baidu(\".pass-button-submit\").val(\"登录并授权\")}),baidu(\"#agreementLabel\").on(\"click\",function(){var e=baidu(\"#agreement\").prop(\"checked\");baidu(\".pass-button-submit\").prop(\"disabled\",!e)[e?\"removeClass\":\"addClass\"](\"btn-disabled\")})}();var e=location.protocol+\"//\"+location.hostname+(location.port&&location.port.length?\":\"+location.port:\"\"),o=!0;\"1\"==devo.nowebclient&&(o=!1);var n=-1,t=0;\"1\"==devo.qrcode&&(n=1,t=3);var i={product:\"dev\",loginType:1,defaultCss:!1,loginMerge:!0,hasRegUrl:!0,autosuggest:!0,hasPlaceholder:!0,authsiteCfgLogin:{act:\"implicit\",tpl:\"oauth\",display:\"popup\",u:urlMergeParams({force_login:null,confirm_login:null}),jumpUrl:e+\"/static/oauth/html/phoenix_jump.html\",onBindSuccess:function(){return baidu(document).trigger(\"loginSuccess\"),!1}},sms:1,u:urlMergeParams({force_login:null,confirm_login:null}),isPhone:!1,safeFlag:0,setWebToClient:o,staticPage:e+\"/static/oauth/html/v3Jump.html\",qrcode:t,loginMergeQrcode:n};1&devo.quick_user&&(i.isQuickUser=devo.quick_user),i.registerLink=\"https://passport.baidu.com/v2/?reg&authsite=0&tpl=dev&u=\"+encodeURIComponent(urlMergeParams({force_login:null,confirm_login:null})),devo.disable_third_login&&(i.authsiteLogin=null,i.authsiteCfgLogin=null,i.sms=0),devo.login_type&&\"sms\"==devo.login_type&&(i.sms=2),(\"weibo_page\"==devo.display||\"weibo_iframe\"==devo.display||\"dialog\"==devo.display)&&(i.authsiteLogin=null,i.sms=0,i.hasRegUrl=!1),\"weibo_page\"==devo.display&&(i.hasRegUrl=!0),passport.use(\"login\",{tangram:!1},function(e){var o=new e.passport.login(i);o.on(\"loginSuccess\",function(e){e.returnValue=!1,baidu(document).trigger(\"loginSuccess\")}),o.on(\"render\",function(){baidu(document).trigger(\"loginReady\")}),o.on(\"loginError\",function(e){var o='如果无法验证，请访问<a href=\"https://passport.baidu.com/v2/?ucenterfeedback#login_8\">https://passport.baidu.com/v2/?ucenterfeedback#login_8</a>获取帮助',n={400031:\"您的帐号已开启登录保护服务，登录前请先进行安全验证；\"+o,5:\"您所处的网络环境存在安全风险，为保证帐号安全，请先进行安全验证；\"+o,120019:\"您最近密码输入错误过于频繁，为保证帐号安全，请先进行安全验证；\"+o,120021:\"您的帐号存在安全风险，请先进行安全验证；\"+o};e.rsp.errInfo.no in n&&setTimeout(function(){var o=baidu(\".pass-forceverify-content .content-msgtext\");o.length>0&&o.html(n[e.rsp.errInfo.no])},1e3)}),o.render(\"psLogin\")})});"
  },
  {
    "path": "open-oauth-center/open-oauth-server/src/main/view/static/js/wrapper.js",
    "content": "var passport=passport||window.passport||{};passport._modulePool=passport._modulePool||{},passport._define=passport._define||function(a,s){passport._modulePool[a]=s&&s()},passport._getModule=passport._getModule||function(a){return passport._modulePool[a]},passport._load=passport._load||function(a,s,e){if(s){var t=document,n=t.createElement(\"SCRIPT\");n.type=\"text/javascript\",n.charset=\"UTF-8\";var r=a.split(\"?\")[0],o=Math.round(1e3*Math.random()),i=(new Date).getTime();n.readyState?n.onreadystatechange=function(){if(\"loaded\"==n.readyState||\"complete\"==n.readyState){if(n.onreadystatechange=null,100==o){var a=(new Date).getTime()-i;(new Image).src=document.location.protocol+\"//nsclick.baidu.com/v.gif?pid=111&type=1023&url=\"+encodeURIComponent(r)+\"&time=\"+a}e&&e()}}:n.onload=function(){if(100==o){var a=(new Date).getTime()-i;(new Image).src=document.location.protocol+\"//nsclick.baidu.com/v.gif?pid=111&type=1023&url=\"+encodeURIComponent(r)+\"&time=\"+a}e&&e()},n.src=100==o?r+\"?t=\"+Math.random():a,t.getElementsByTagName(\"head\")[0].appendChild(n)}else{var t=document,n=t.createElement(\"SCRIPT\");n.type=\"text/javascript\",n.charset=\"UTF-8\",n.src=a,t.getElementsByTagName(\"head\")[0].appendChild(n),n.readyState?n.onreadystatechange=function(){(\"loaded\"==n.readyState||\"complete\"==n.readyState)&&(n.onreadystatechange=null,e&&e())}:n.onload=function(){e&&e()}}},passport._use=passport._use||function(a,s,e){function t(){var a=passport._getModule(i);if(!a)throw new Error(\"load \"+i+\"module script error.\");e&&e(a)}var n={\"http:\":\"http://passport.bdimg.com\",\"https:\":\"https://ss0.bdstatic.com/5LMZfyabBhJ3otebn9fN2DJv\"};if(passport&&\"https\"==passport._protocol)var r=\"https:\";else var r=window.location?window.location.protocol.toLowerCase():document.location.protocol.toLowerCase();var o=(n[r]||n[\"https:\"])+s,i=a+\".js\";moduleInstance=passport._getModule(i),moduleInstance?e&&e(moduleInstance):passport._load(o,!0,t)},passport.use=passport.use||function(a,s,e){var t=s&&s.tangram===!1?\"\":\"_tangram\";s&&s.protocol&&(passport._protocol=s.protocol),\"reg\"==a&&s&&s.regPhoneOnly&&(a=\"regPhone\");var n=\"\";\"login\"===a&&s&&s.loginVersion&&\"v4\"===s.loginVersion&&(n=!0);var r=\"/passApi/js/login_4765ca5.js\",o=\"/passApi/js/login_tangram_9870fba.js\";n&&(r=\"/passApi/js/loginv4_04da7b2.js\",o=\"/passApi/js/loginv4_tangram_760b315.js\");var i={login:r,login_tangram:o,smsloginEn:\"/passApi/js/smsloginEn_660412e.js\",smsloginEn_tangram:\"/passApi/js/smsloginEn_tangram_716da88.js\",loginWLtoPC:\"/passApi/js/loginWLtoPC_8a19494.js\",accConnect:\"/passApi/js/accConnect_e7d7989.js\",accConnect_tangram:\"/passApi/js/accConnect_tangram_058dead.js\",accRealName:\"/passApi/js/accRealName_57dc11b.js\",accRealName_tangram:\"/passApi/js/accRealName_tangram_f6903ee.js\",checkPhone:\"/passApi/js/checkPhone_94361b7.js\",checkPhone_tangram:\"/passApi/js/checkPhone_tangram_239bae9.js\",checkIDcard:\"/passApi/js/checkIDcard_9d74ead.js\",checkIDcard_tangram:\"/passApi/js/checkIDcard_tangram_ff24ee3.js\",accSetPwd:\"/passApi/js/accSetPwd_8a29d14.js\",accSetPwd_tangram:\"/passApi/js/accSetPwd_tangram_def42de.js\",IDCertify:\"/passApi/js/IDCertify_2d7bef9.js\",IDCertify_tangram:\"/passApi/js/IDCertify_tangram_c65479c.js\",secondCardVerify:\"/passApi/js/secondCardVerify_e071f99.js\",secondCardVerify_tangram:\"/passApi/js/secondCardVerify_tangram_e413d5a.js\",IDCertifyQrcode:\"/passApi/js/IDCertifyQrcode_0fbc634.js\",IDCertifyQrcode_tangram:\"/passApi/js/IDCertifyQrcode_tangram_01f3c25.js\",loadingApi:\"/passApi/js/loadingApi_ff5bf20.js\",loadingApi_tangram:\"/passApi/js/loadingApi_tangram_20a8cc8.js\",loginWap:\"/passApi/js/loginWap_ddd365d.js\",reg:\"/passApi/js/reg_ff57960.js\",reg_tangram:\"/passApi/js/reg_tangram_bd97b30.js\",regPhone:\"/passApi/js/regPhone_81e3bc8.js\",regPhone_tangram:\"/passApi/js/regPhone_tangram_a5b7009.js\",fillUserName:\"/passApi/js/fillUserName_0648773.js\",fillUserName_tangram:\"/passApi/js/fillUserName_tangram_8321fa9.js\",qrcode:\"/passApi/js/qrcode_ce57dba.js\",qrcode_tangram:\"/passApi/js/qrcode_tangram_d8aed88.js\",realUserTag:\"/passApi/js/realUserTag_6b391f6.js\",realUserTag_tangram:\"/passApi/js/realUserTag_tangram_66c443c.js\",bind:\"/passApi/js/bind_1bc84d7.js\",bind_tangram:\"/passApi/js/bind_tangram_c0ca601.js\",multiBind:\"/passApi/js/multiBind_d44fb01.js\",multiBind_tangram:\"/passApi/js/multiBind_tangram_5ae1e55.js\",multiUnbind:\"/passApi/js/multiUnbind_884d4e8.js\",multiUnbind_tangram:\"/passApi/js/multiUnbind_tangram_d30ad85.js\",changeUser:\"/passApi/js/changeUser_5d7e5bb.js\",changeUser_tangram:\"/passApi/js/changeUser_tangram_3a2c21f.js\",loginMultichoice:\"/passApi/js/loginMultichoice_3a98e5a.js\",loginMultichoice_tangram:\"/passApi/js/loginMultichoice_tangram_f4eebcc.js\",confirmWidget:\"/passApi/js/confirmWidget_2d0b875.js\",confirmWidget_tangram:\"/passApi/js/confirmWidget_tangram_e070566.js\",uni_rebindGuide:\"/passApi/js/uni_rebindGuide_a831354.js\",uni_rebindGuide_tangram:\"/passApi/js/uni_rebindGuide_tangram_c96881a.js\"},p=a+t;2==arguments.length&&(e=s),s&&s.tangramInst&&(passport.tangramInst=s.tangramInst),passport._use(p,i[p],e)};"
  },
  {
    "path": "open-oauth-center/open-oauth-server/src/main/view/static/login.html",
    "content": "<!DOCTYPE html>\n<html lang=\"zh-CN\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n\n\n<title>与认证中心连接</title>\n\n\n\n\n\n<script type=\"text/javascript\">\n\tif (!-[ 1, ]) {\n\t\tvar e = (\"abbr,article,aside,audio,canvas,datalist,\"\n\t\t\t\t+ \"details,dialog,eventsource,figure,footer,\"\n\t\t\t\t+ \"header,hgroup,mark,menu,meter,nav,output,\"\n\t\t\t\t+ \"progress,section,time,video\").split(','), i = e.length;\n\t\twhile (i--) {\n\t\t\tdocument.createElement(e[i])\n\t\t}\n\t}\n</script>\n\n\n<script type=\"text/javascript\">\n\t// alert(window.innerHeight);\n\t// alert(navigator.userAgent);\n\tvar devo = {\n\t\tnowebclient : '',\n\t\tislogin : '',\n\t\tconfirm_login : '',\n\t\tquick_user : '0',\n\t\tdisplay : 'popup',\n\t\tis_sso : '',\n\t\tgranted_perms : '',\n\t\tdisable_third_login : '',\n\t\tlogin_type : '',\n\t\tis_social : '',\n\t\treq_perms_len : '1',\n\t\tnick_name : '',\n\t\tmedia_info : '',\n\t\tpublicKey : 'BAF11D465A4915BEF8C13862873A8C8BC5DB4473106254E186F25BD74DC901F2336B838B62850CEA97E7C96EBFD7F15F4CA902F0CF33B2415898956FBF1A10BABB58EB3FAB7706BD16CBC1F24E10E7BCE016C8F1446B081B232C13DB4178D48A9ACA579DFC343F2420D670D03BFB15F9EABA8471077EE9B68D022BBDA3DEB63F',\n\t\tprefilled_mobile : '',\n\t\tgranted_perms : '',\n\t\tis_dusite : '',\n\t\tclose_oversea : '',\n\t\tqrcode : '',\n\t};\n</script>\n\n<script>\n\tdevo.conf = {\n\t\t\"page_header\" : \"与认证中心连接\",\n\n\t\t\"page_title\" : \"认证中心\",\n\n\t\t\"back\" : \"返回\",\n\n\t\t\"change_account\" : \"切换帐号\",\n\n\t\t\"login_title\" : \"登录认证中心帐号\",\n\n\t\t\"regist\" : \"注册\",\n\n\t\t\"use_baidu_prefix\" : \"使用认证中心帐号访问 \",\n\n\t\t\"use_baidu_suffix\" : \" 应用\",\n\n\t\t\"normal\" : \"普通登录\",\n\n\t\t\"quick_user\" : \"用户名登录\",\n\n\t\t\"mobile\" : \"手机号登录\",\n\n\t\t\"message\" : \"快捷登录\",\n\n\t\t\"other_login\" : \"其他方式登录\",\n\n\t\t\"name_label\" : \"帐　号\",\n\n\t\t\"normal_name\" : \"邮　箱\",\n\n\t\t\"quick_user_name\" : \"用户名\",\n\n\t\t\"mobile_name\" : \"手机号\",\n\n\t\t\"normal_name_placeholder\" : \"手机号/邮箱/用户名\",\n\n\t\t\"message_name_placeholder\" : \"请输入手机号\",\n\t\t\"normal_pwd_placeholder\" : \"密码\",\n\n\t\t\"message_pwd_placeholder\" : \"动态密码\",\n\n\t\t\"vcode_placeholder\" : \"验证码\",\n\n\t\t\"pwd_label\" : \"密　码\",\n\n\t\t\"pwd_placeholder\" : \"6-14位，字母区分大小写\",\n\n\t\t\"verify_label\" : \"验证码\",\n\n\t\t\"change_verify\" : \"看不清\",\n\n\t\t\"login_btn\" : \"登 录\",\n\n\t\t\"use_logged_id\" : \"切换到快速登录模式\",\n\n\t\t\"forget_pwd\" : \"忘记密码?\",\n\n\t\t\"login_error_blank_name\" : \"请输入帐号\",\n\n\t\t\"login_error_blank_pwd\" : \"请输入密码\",\n\n\t\t\"login_error_blank_verify\" : \"请输入验证码\",\n\n\t\t\"login_error_blank_phone\" : \"请输入手机号\",\n\n\t\t\"login_error_blank_timeout\" : \"请求超时\",\n\n\t\t\"login_error_blank_unknown\" : \"登录时发生未知错误，请稍后重新输入\",\n\n\t\t\"login_error_right_phone\" : \"请输入正确的手机号\",\n\n\t\t\"send_message_again\" : \"重新发送\",\n\n\t\t\"send_code\" : \"发送动态密码\",\n\n\t\t\"get_changed\" : \"换一张\",\n\n\t\t\"account\" : \"普通\",\n\n\t\t\"sms\" : \"短信\",\n\n\t\t\"login_allow\" : \"登录并授权\",\n\n\t\t\"bind_allow\" : \"绑定并授权\",\n\n\t\t\"bind_mobile_title\" : \"绑定手机号\",\n\n\t\t\"login_wait\" : \"登录中...\",\n\n\t\t\"allow_wait\" : \"授权中...\",\n\n\t\t\"other_login_styles\" : \"使用以下方式登录\",\n\n\t\t\"login_confirm_head\" : \"亲爱的用户:\",\n\n\t\t\"login_confirm_text\" : \"为了你确保您的账号安全,请确认您输入的帐号是否为手机号后即可登录:\",\n\n\t\t\"login_confirm_phone\" : \"手机号\",\n\n\t\t\"login_confirm_username\" : \"用户名\",\n\n\t\t\"auth_desc_prefix\" : \"允许 \",\n\n\t\t\"auth_desc_suffix\" : \" 应用进行以下操作\",\n\n\t\t\"auth_ok_btn\" : \"授 权\",\n\n\t\t\"auth_is_login\" : \"检测到您已经登录认证中心可以直接进行授权\",\n\n\t\t\"auth_is_login_noperm\" : \"检测到您已经是登录状态，请确认后直接登录\",\n\n\t\t\"confirm_logged_label\" : \"用认证中心帐号登录\",\n\n\t\t\"confirm_logged_desc\" : \"您已经登录认证中心帐号\",\n\n\t\t\"confirm_ok_btn\" : \"登 录\",\n\n\t\t\"error_code_label\" : \"错误码：\",\n\n\t\t\"error_info_label\" : \"错误信息：\",\n\n\t\t\"error_info_desc\" : \"您遇到了错误\",\n\n\t\t\"developer_desc\" : \"您现在使用的服务为认证中心连接\",\n\n\t\t\"fill_desc\" : \"您还没有用户名，请补充填写一个\",\n\n\t\t\"fill_ok_btn\" : \"确 定\",\n\n\t\t\"fill_username_placeholder\" : \"用户名：\",\n\n\t\t\"verifier_desc_prefix\" : \"您正要授权给 \",\n\n\t\t\"verifier_desc_suffix\" : \" 拥有以下权限\",\n\n\t\t\"verifier_verify_code\" : \"授权码\",\n\n\t\t\"verifier_time_prefix\" : \"本授权码\",\n\n\t\t\"verifier_time_suffix\" : \"一次性有效并将在10分钟后过期\",\n\n\t\t\"verifier_app_permissions1\" : \"将授权码加入到\",\n\n\t\t\"verifier_app_permissions2\" : \"中，将视为你允许\",\n\n\t\t\"verifier_app_permissions3\" : \"访问相关授权权限\",\n\n\t\t\"device_success\" : \"您已成功为 \",\n\n\t\t\"device_denied\" : \"您已拒绝为\",\n\n\t\t\"device_opr\" : \"授权!\",\n\n\t\t\"device_auth_end\" : \"请返回设备继续操作！\",\n\n\t\t\"device_desc\" : \"一台设备正在向您的帐号申请授权\",\n\n\t\t\"device_label\" : \"请输入设备上显示的用户授权码\",\n\n\t\t\"device_code_error\" : \"用户授权码错误，请重试！\",\n\n\t\t\"device_opr_tip\" : '点击“继续”对该设备进行授权设置',\n\n\t\t\"device_ok_btn\" : \"继续\",\n\n\t\t\"device_code_tip\" : \"小写字母和数字组成，共8位\"\n\t}\n</script>\n<link rel=\"stylesheet\" type=\"text/css\" href=\"css/import_main.css\">\n<link rel=\"stylesheet\" type=\"text/css\" href=\"css/page_all.css\">\n\n<script type=\"text/javascript\" charset=\"UTF-8\" src=\"js/ld.min.js\"></script>\n\n</head>\n<body class=\"popup\">\n\n\n\t<div class=\"topbar\">\n\t\t<div class=\"main hd-c clearfix\">\n\t\t\t<strong class=\"logo\">认证中心</strong>\n\t\t\t<div class=\"topbar-nav\"></div>\n\t\t</div>\n\t</div>\n\t<section class=\"g-bd\">\n\t\t<div class=\"g-bd-wp wordwrap clearfix\">\n\n\n\n\t\t\t<div class=\"two-cols clearfix\">\n\t\t\t\t<div class=\"login\">\n\t\t\t\t\t<h3 class=\"title\">认证中心帐号登录</h3>\n\n\t\t\t\t\t<div class=\"psWrapper\">\n\t\t\t\t\t\t<div id=\"psLogin\" class=\"tang-pass-login\">\n\t\t\t\t\t\t\t<form id=\"TANGRAM_3__form\" class=\"pass-form pass-form-normal\" action=\"/user/login\"\n\t\t\t\t\t\t\t\tmethod=\"POST\" autocomplete=\"off\">\n\t\t\t\t\t\t\t\t<p id=\"TANGRAM_3__errorWrapper\" class=\"pass-generalErrorWrapper\">\n\t\t\t\t\t\t\t\t\t<span id=\"TANGRAM_3__error\"\n\t\t\t\t\t\t\t\t\t\tclass=\"pass-generalError pass-generalError-error\"></span>\n\t\t\t\t\t\t\t\t</p>\n\n\t\t\t\t\t\t\t\t<p id=\"TANGRAM_3__userNameWrapper\"\n\t\t\t\t\t\t\t\t\tclass=\"pass-form-item pass-form-item-userName\" style=\"display:\">\n\t\t\t\t\t\t\t\t\t<label for=\"TANGRAM_3__userName\" id=\"TANGRAM_3__userNameLabel\"\n\t\t\t\t\t\t\t\t\t\tclass=\"pass-label pass-label-userName\">用户名</label><input\n\t\t\t\t\t\t\t\t\t\ttype=\"text\" style=\"display: none;\"><input\n\t\t\t\t\t\t\t\t\t\tid=\"TANGRAM_3__userName\" type=\"text\" name=\"username\"\n\t\t\t\t\t\t\t\t\t\tclass=\"pass-text-input pass-text-input-userName\"\n\t\t\t\t\t\t\t\t\t\tautocomplete=\"new-password\" value=\"\" placeholder=\"用户名\"><span\n\t\t\t\t\t\t\t\t\t\tid=\"TANGRAM_3__userName_clearbtn\"\n\t\t\t\t\t\t\t\t\t\tclass=\"pass-clearbtn pass-clearbtn-userName\"\n\t\t\t\t\t\t\t\t\t\tstyle=\"display: none;\"></span><span\n\t\t\t\t\t\t\t\t\t\tid=\"TANGRAM_3__userNameTip\"\n\t\t\t\t\t\t\t\t\t\tclass=\"pass-item-tip pass-item-tip-userName\"\n\t\t\t\t\t\t\t\t\t\tstyle=\"display: none\"><span\n\t\t\t\t\t\t\t\t\t\tid=\"TANGRAM_3__userNameTipText\"\n\t\t\t\t\t\t\t\t\t\tclass=\"pass-item-tiptext pass-item-tiptext-userName\"></span></span>\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t<p id=\"TANGRAM_3__passwordWrapper\"\n\t\t\t\t\t\t\t\t\tclass=\"pass-form-item pass-form-item-password\" style=\"display:\">\n\t\t\t\t\t\t\t\t\t<label for=\"TANGRAM_3__password\" id=\"TANGRAM_3__passwordLabel\"\n\t\t\t\t\t\t\t\t\t\tclass=\"pass-label pass-label-password\">密码</label><input\n\t\t\t\t\t\t\t\t\t\ttype=\"password\" style=\"display: none;\"><input\n\t\t\t\t\t\t\t\t\t\tid=\"TANGRAM_3__password\" type=\"password\" name=\"password\"\n\t\t\t\t\t\t\t\t\t\tclass=\"pass-text-input pass-text-input-password\"\n\t\t\t\t\t\t\t\t\t\tautocomplete=\"new-password\" value=\"\" placeholder=\"密码\"><span\n\t\t\t\t\t\t\t\t\t\tid=\"TANGRAM_3__password_clearbtn\"\n\t\t\t\t\t\t\t\t\t\tclass=\"pass-clearbtn pass-clearbtn-password\"\n\t\t\t\t\t\t\t\t\t\tstyle=\"display: none;\"></span><span\n\t\t\t\t\t\t\t\t\t\tid=\"TANGRAM_3__passwordTip\"\n\t\t\t\t\t\t\t\t\t\tclass=\"pass-item-tip pass-item-tip-password\"\n\t\t\t\t\t\t\t\t\t\tstyle=\"display: none\"><span\n\t\t\t\t\t\t\t\t\t\tid=\"TANGRAM_3__passwordTipText\"\n\t\t\t\t\t\t\t\t\t\tclass=\"pass-item-tiptext pass-item-tiptext-password\"></span></span>\n\t\t\t\t\t\t\t\t</p>\n\n\t\t\t\t\t\t\t\t<p id=\"TANGRAM_3__submitWrapper\"\n\t\t\t\t\t\t\t\t\tclass=\"pass-form-item pass-form-item-submit\">\n\t\t\t\t\t\t\t\t\t<input id=\"TANGRAM_3__submit\" type=\"submit\" value=\"登录并授权\"\n\t\t\t\t\t\t\t\t\t\tclass=\"pass-button pass-button-submit\">\n\t\t\t\t\t\t\t</form>\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t<script src=\"js/wrapper.js\"></script>\n\t\t\t\t<script>\n\t\t\t\t\tfunction setCookie(c_name, value, expiredays) {\n\t\t\t\t\t\tvar exdate = new Date();\n\t\t\t\t\t\texdate.setDate(exdate.getDate() + expiredays);\n\t\t\t\t\t\tdocument.cookie = c_name\n\t\t\t\t\t\t\t\t+ \"=\"\n\t\t\t\t\t\t\t\t+ escape(value)\n\t\t\t\t\t\t\t\t+ ((expiredays == null) ? \"\" : \";expires=\"\n\t\t\t\t\t\t\t\t\t\t+ exdate.toGMTString())\n\t\t\t\t\t}\n\t\t\t\t\tfunction logaback(res) {\n\t\t\t\t\t\tdocument.getElementById(\"etken\").value = res.stoken;\n\t\t\t\t\t\tvar bdstokenForm = document.forms['bdstoken'];\n\t\t\t\t\t\tbdstokenForm && bdstokenForm.submit();\n\t\t\t\t\t\tdocument.getElementById(\"etken\").value = null;\n\t\t\t\t\t}\n\t\t\t\t</script>\n\t\t\t\t<div class=\"scope\">\n\t\t\t\t\t<p class=\"title\">允许 \"登录测试\" 应用进行以下操作：</p>\n\t\t\t\t\t<form name=\"scopes\" target=\"_self\" method=\"post\" class=\"scope-form\"\n\t\t\t\t\t\tautocomplete=\"off\">\n\t\t\t\t\t\t<ul class=\"scope-list\">\n\t\t\t\t\t\t\t<li class=\"first\"><input type=\"checkbox\" checked=\"checked\"\n\t\t\t\t\t\t\t\tdisabled=\"\" class=\"checkbox\" name=\"grant_permissions_arr\"\n\t\t\t\t\t\t\t\tvalue=\"basic\" id=\"scope-basic\"><label for=\"scope-basic\">访问您的个人资料等基础信息</label></li>\n\t\t\t\t\t\t</ul>\n\t\t\t\t\t\t<input type=\"hidden\" name=\"bdstoken\"\n\t\t\t\t\t\t\tvalue=\"405d4bb2c92133ffbd8661fc3f5c09f7\"> <input\n\t\t\t\t\t\t\ttype=\"hidden\" name=\"client_id\" value=\"SaZpR8r6XdIg5fr0qW6Ccasf\">\n\t\t\t\t\t\t<input type=\"hidden\" name=\"response_type\" value=\"code\"> <input\n\t\t\t\t\t\t\ttype=\"hidden\" name=\"display\" value=\"popup\"> <input\n\t\t\t\t\t\t\ttype=\"hidden\" name=\"grant_permissions\" value=\"\">\n\n\t\t\t\t\t\t<p class=\"rows-split\">\n\t\t\t\t\t\t\t<label for=\"agreement\" id=\"agreementLabel\"><input\n\t\t\t\t\t\t\t\ttype=\"checkbox\" class=\"checkbox\" checked=\"\" name=\"agreement\"\n\t\t\t\t\t\t\t\tvalue=\"1\" id=\"agreement\">我同意<a\n\t\t\t\t\t\t\t\thref=\"http://developer.baidu.com/wiki/index.php?title=docs/terms/connect\"\n\t\t\t\t\t\t\t\ttarget=\"_blank\">认证中心帐号连接协议</a></label>\n\t\t\t\t\t\t</p>\n\t\t\t\t\t</form>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t</div>\n\t</section>\n\n\n\t<p class=\"page-tip\">提示：为了保障帐号安全，请认准本页URL地址必须以open.capcacity.platform开头</p>\n\n\n\n\n</body>\n</html>"
  },
  {
    "path": "open-oauth-center/open-oauth-sso/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" 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  <parent>\n    <groupId>com.open.capacity</groupId>\n    <artifactId>open-oauth-center</artifactId>\n    <version>0.0.1-SNAPSHOT</version>\n  </parent>\n  <artifactId>open-oauth-sso</artifactId>\n  \n  <dependencies>\n  \t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-eureka</artifactId>\n\t\t</dependency>\n  </dependencies>\n</project>"
  },
  {
    "path": "open-oauth-center/open-oauth-sso/src/main/java/com/open/capacity/SsoClientApp.java",
    "content": "package com.open.capacity;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.client.discovery.EnableDiscoveryClient;\nimport org.springframework.security.core.Authentication;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.security.Principal;\n\n/**\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2017年11月12日 上午22:57:51\n */\n\n\n@RestController\n@EnableDiscoveryClient\n@SpringBootApplication\npublic class SsoClientApp {\n\n    public static void main(String[] args) {\n        SpringApplication.run(SsoClientApp.class, args);\n    }\n\n    @GetMapping(\"/hello\")\n    public String hello() {\n        return \"hello\";\n    }\n\n    @RequestMapping(value = {\"/user\"}, produces = \"application/json\") // 获取用户信息。/auth/user\n    public Principal user(Principal user) {\n        return user;\n    }\n\n    @GetMapping(\"/users\")\n    public Authentication user(Authentication user) {\n        return user;\n    }\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-sso/src/main/java/com/open/capacity/client/config/OauthLogoutHandler.java",
    "content": "package com.open.capacity.client.config;\n\nimport java.io.IOException;\n\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.security.core.Authentication;\nimport org.springframework.security.oauth2.provider.OAuth2Authentication;\nimport org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails;\nimport org.springframework.security.web.DefaultRedirectStrategy;\nimport org.springframework.security.web.RedirectStrategy;\nimport org.springframework.security.web.authentication.logout.LogoutHandler;\nimport org.springframework.stereotype.Component;\n\n/**\n * @author keets\n * @date 2017/10/17\n */\n@Component\npublic class OauthLogoutHandler implements LogoutHandler {\n\n    private static final Logger logger = LoggerFactory.getLogger(OauthLogoutHandler.class);\n\n    private static final String LogoutURL1 = \"http://127.0.0.1:8000/auth/user/logout?access_token=%s\";\n    private static final String LogoutURL2 = \"http://127.0.0.1:9997/logout\";\n    \n    RedirectStrategy rs = new DefaultRedirectStrategy();\n    \n//    @Autowired\n//    private TokenStore tokenStore;\n\n    @Override\n    public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {\n \n\n\n        if (authentication != null) {\n\n            if (authentication instanceof OAuth2Authentication) {\n\n                Authentication athentication = (Authentication) authentication;\n\n                OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails) athentication.getDetails();\n//                ctx.addZuulRequestHeader(\"Authorization\", \"bearer \" + details.getTokenValue());\n                \n                try {\n\t\t\t\t\trs.sendRedirect(request, response, String.format(LogoutURL1, details.getTokenValue()));\n\t\t\t\t} catch (IOException e) {\n\t\t\t\t\t// TODO Auto-generated catch block\n\t\t\t\t\te.printStackTrace();\n\t\t\t\t} \n            }\n        }\n    }\n\n     \n\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-sso/src/main/java/com/open/capacity/client/web/UnieapSecurityConfig.java",
    "content": "package com.open.capacity.client.web;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.autoconfigure.security.SecurityProperties;\nimport org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;\nimport org.springframework.boot.autoconfigure.security.oauth2.resource.ResourceServerProperties;\nimport org.springframework.boot.web.servlet.FilterRegistrationBean;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.security.config.annotation.web.builders.HttpSecurity;\nimport org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;\nimport org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails;\nimport org.springframework.security.web.authentication.logout.HttpStatusReturningLogoutSuccessHandler;\nimport org.springframework.stereotype.Component;\n\nimport com.open.capacity.client.config.OauthLogoutHandler;\nimport com.open.capacity.filter.TokenFilter;\n\n/**\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2017年11月12日 上午22:57:51\n * 类说明\n * @EnableOAuth2Sso注解。如果WebSecurityConfigurerAdapter类上注释了@EnableOAuth2Sso注解， 那么将会添加身份验证过滤器和身份验证入口。\n * 如果只有一个@EnableOAuth2Sso注解没有编写在WebSecurityConfigurerAdapter上，\n * 那么它将会为所有路径启用安全，并且会在基于HTTP Basic认证的安全链之前被添加。详见@EnableOAuth2Sso的注释。\n */\n@Component\n@Configuration\n@EnableOAuth2Sso\npublic class UnieapSecurityConfig extends WebSecurityConfigurerAdapter {\n\n\t@Autowired\n\tprivate OauthLogoutHandler oauthLogoutHandler;\n\t\n    @Override\n    public void configure(HttpSecurity http) throws Exception {\n        http.formLogin().and()\n                .antMatcher(\"/**\")\n                // 所有请求都得经过认证和授权\n                .authorizeRequests().anyRequest().authenticated()\n                .and().authorizeRequests().antMatchers(\"/\", \"/anon\").permitAll()\n                .and()\n                // 这里之所以要禁用csrf，是为了方便。\n                // 否则，退出链接必须要发送一个post请求，请求还得带csrf token\n                // 那样我还得写一个界面，发送post请求\n                .csrf().disable()\n                // 退出的URL是/logout\n                .logout().logoutUrl(\"/logout\")\n                .clearAuthentication(true)\n\t\t\t\t.logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler())\n\t\t\t\t.addLogoutHandler(oauthLogoutHandler).permitAll()\n\t\t\t\t.deleteCookies(\"JSESSIONID\",\"FP-UID\")\n                .invalidateHttpSession(true)\n                // 退出成功后，跳转到/路径。\n                .logoutSuccessUrl(\"/login\");\n\n\n        //新增token过滤器\n\n    }\n\n\n    @Bean\n    public FilterRegistrationBean mytokenFilter(SecurityProperties security, AuthorizationCodeResourceDetails authorizationCodeResourceDetails, ResourceServerProperties resourceServerProperties) {\n        FilterRegistrationBean registration = new FilterRegistrationBean();\n\n        TokenFilter tokenFilter = new TokenFilter();\n        registration.setFilter(tokenFilter);\n        registration.setOrder(security.getFilterOrder() - 11);\n\n//\t\t\tauthorizationCodeResourceDetails.setUserAuthorizationUri(\"http://127.0.0.1:8000/auth/oauth/authorize\");\n//\t\t\tauthorizationCodeResourceDetails.setAccessTokenUri(\"http://127.0.0.1:8000/auth/oauth/token\");  //http://127.0.0.1:8000/auth/oauth/authorize\n//\t\t\t\n//\t\t\tresourceServerProperties.setTokenInfoUri(\"http://127.0.0.1:8000/auth/oauth/check_token\");\n\n        return registration;\n    }\n}\n\t\n\n\t\n"
  },
  {
    "path": "open-oauth-center/open-oauth-sso/src/main/java/com/open/capacity/controller/UserController.java",
    "content": "package com.open.capacity.controller;\n\nimport org.springframework.security.core.Authentication;\nimport org.springframework.security.core.context.SecurityContextHolder;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n@RestController\npublic class UserController {\n\n    @GetMapping(\"/user\")\n    public Authentication currentUser() {\n        return SecurityContextHolder.getContext().getAuthentication();\n    }\n\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-sso/src/main/java/com/open/capacity/filter/TokenFilter.java",
    "content": "package com.open.capacity.filter;\n\nimport org.springframework.security.core.Authentication;\nimport org.springframework.security.core.context.SecurityContextHolder;\nimport org.springframework.security.oauth2.provider.OAuth2Authentication;\nimport org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails;\nimport org.springframework.security.web.DefaultRedirectStrategy;\nimport org.springframework.security.web.RedirectStrategy;\nimport org.springframework.web.filter.OncePerRequestFilter;\n\nimport javax.servlet.FilterChain;\nimport javax.servlet.ServletException;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport java.io.IOException;\nimport java.util.Enumeration;\n\n/**\n * Token过滤器\n *\n * @author owen 624191343@qq.com\n * <p>\n * 2017年10月14日\n */\npublic class TokenFilter extends OncePerRequestFilter {\n\n    private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();\n\n    @Override\n    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)\n            throws ServletException, IOException {\n\n        Authentication user = SecurityContextHolder.getContext()\n                .getAuthentication();\n\n\n        if (user != null) {\n\n            if (user instanceof OAuth2Authentication) {\n\n                Authentication athentication = (Authentication) user;\n\n                OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails) athentication.getDetails();\n                details.getTokenValue();\n\n                initSession(request);\n                //重新发起sso登录\tOAuth2ClientContextFilter redirectUser(redirect, request, response);\n\n\n            }\n\n        }\n\n//\t\tOAuth2Authentication\n        filterChain.doFilter(request, response);\n    }\n\n    private void initSession(HttpServletRequest request) {\n        Enumeration em = request.getSession().getAttributeNames();\n        while (em.hasMoreElements()) {\n            request.getSession().removeAttribute(em.nextElement().toString());\n        }\n    }\n\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-sso/src/main/java/com/open/capacity/utils/SpringUtil.java",
    "content": "package com.open.capacity.utils;\n\nimport org.springframework.beans.BeansException;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.ApplicationContextAware;\nimport org.springframework.core.env.Environment;\nimport org.springframework.stereotype.Component;\n\n/**\n * spring获取bean工具类\n *\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2018年3月20日 下午10:13:18 类说明\n */\n@Component\npublic class SpringUtil implements ApplicationContextAware {\n\n    private static ApplicationContext applicationContext = null;\n\n    public static <T> T getBean(Class<T> cla) {\n        return applicationContext.getBean(cla);\n    }\n\n    public static <T> T getBean(String name, Class<T> cal) {\n        return applicationContext.getBean(name, cal);\n    }\n\n    public static String getProperty(String key) {\n        return applicationContext.getBean(Environment.class).getProperty(key);\n    }\n\n    @Override\n    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {\n        SpringUtil.applicationContext = applicationContext;\n    }\n}\n"
  },
  {
    "path": "open-oauth-center/open-oauth-sso/src/main/resources/application.yml",
    "content": "server:\n  port: 9997\n  context-path: /clientOne\nsecurity:\n  user:\n    password: 123456\n  oauth2:\n    sso:\n      login-path: /login\n    client:\n      client-id: owen\n      client-secret: owen \n      user-authorization-uri: http://127.0.0.1:8000/oauth/authorize    \n      access-token-uri: http://127.0.0.1:8000/oauth/token\n    resource: \n#        user-info-uri: http://127.0.0.1:8000/auth/users #返回认证服务器检查\n#        prefer-token-info: false\n      token-info-uri: http://127.0.0.1:8000/oauth/check_token\n      prefer-token-info: true\n \n \nspring:\n  application:\n    name: open-auth-sso\n  datasource:\n      type: com.alibaba.druid.pool.DruidDataSource\n#      driver-class-name:  oracle.jdbc.OracleDriver\n#      url: jdbc:oracle:thin:@127.0.0.1:1521:orcl\n#      username: crm_owner_user\n#      password: bss_crm_test\n#      filters: stat,wall\n################## mysql start ############################\n      driver-class-name:  com.mysql.jdbc.Driver\n      #     192.168.3.150   130.75.131.211  134.224.249.39  47.94.252.160\n      url: jdbc:mysql://192.168.3.150:3306/boot_security?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false\n      username: root\n      password: root\n      filters: stat,wall\n################### mysq end l##########################\n  redis:\n################### redis 单机版 start ########################## \n    host: 127.0.0.1\n    port: 6379    \n    timeout: 3000\n    database: 1\n################### redis 单机版 end ##########################   \n#    cluster:\n#      nodes: 130.75.131.237:7000,130.75.131.238:7000,130.75.131.239:7000,130.75.131.237:7001,130.75.131.238:7001,130.75.131.239:7001\n###        #130.75.131.237:7000,130.75.131.238:7000,130.75.131.239:7000,130.75.131.237:7001,130.75.131.238:7001,130.75.131.239:7001\n##        #192.168.3.157:7000,192.168.3.158:7000,192.168.3.159:7000,192.168.3.157:7001,192.168.3.158:7001,192.168.3.159:7001\n#    timeout: 1000 # 连接超时时间（毫秒）\n#    pool:\n#      max-active: 10  # 连接池最大连接数（使用负值表示没有限制）\n#      max-idle: 8     # 连接池中的最大空闲连接\n#      min-idle: 2     # 连接池中的最小空闲连接\n#      max-wait: 100   # 连接池最大阻塞等待时间（使用负值表示没有限制）     \n    \n    \n\nmybatis:\n  config-location: classpath:mybatis.cfg.xml\n  mapper-locations: classpath*:com/open/**/dao/*.xml  \n  \neureka:\n  client:\n    serviceUrl:\n      defaultZone: http://127.0.0.1:1111/eureka/\n      #http://192.168.3.170:1111/eureka,http://192.168.3.171:1111/eureka,http://192.168.3.173:1111/eureka\n      #http://130.75.131.243:1111/eureka/,http://130.75.131.244:1111/eureka/,http://130.75.131.245:1111/eureka/   \n  instance:\n    prefer-ip-address: true\n    instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}\n#    instance-id: ${spring.application.name}:${docker.ipAddress}:${spring.application.instance_id:${server.port}}\n    lease-renewal-interval-in-seconds: 5\n \n"
  },
  {
    "path": "open-oauth-center/open-oauth-sso/src/main/view/static/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<title>SSO Client1</title>\n</head>\n<body>\n\t<h1>SSO Demo ClientOne</h1>\n\t<a href=\"http://127.0.0.1:9998/clientTwo/index.html\">访问ClientTwo</a>\n</body>\n</html>"
  },
  {
    "path": "open-oauth-center/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\t<parent>\n\t\t<groupId>com.open.capacity</groupId>\n\t\t<artifactId>open-capacity-platform</artifactId>\n\t\t<version>0.0.1-SNAPSHOT</version>\n\t</parent>\n\t<artifactId>open-oauth-center</artifactId>\n\t<packaging>pom</packaging>\n\n\t<dependencies>\n\n\t\t<!-- 关系型和非关系型数据库配置 -->\n\t\t<dependency>\n\t\t\t<groupId>com.open.capacity</groupId>\n\t\t\t<artifactId>open-db-core</artifactId>\n\t\t\t<version>${core.version}</version>\n\t\t</dependency>\n\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework</groupId>\n\t\t\t<artifactId>spring-context-support</artifactId>\n\t\t</dependency>\n\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.social</groupId>\n\t\t\t<artifactId>spring-social-web</artifactId>\n\t\t</dependency>\n\t\t<!-- 加入spring security spring security oauth2的处理 -->\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-oauth2</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.security</groupId>\n\t\t\t<artifactId>spring-security-jwt</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.apache.commons</groupId>\n\t\t\t<artifactId>commons-lang3</artifactId>\n\t\t</dependency>\n\n\n\t\t<!-- swagger -->\n\t\t<dependency>\n\t\t\t<groupId>io.swagger</groupId>\n\t\t\t<artifactId>swagger-core</artifactId>\n\t\t\t<version>1.5.8</version>\n\t\t</dependency>\n\t \n\t\t<dependency>\n\t\t\t<groupId>io.springfox</groupId>\n\t\t\t<artifactId>springfox-swagger2</artifactId>\n\t\t\t<version>2.4.0</version>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>io.springfox</groupId>\n\t\t\t<artifactId>springfox-swagger-ui</artifactId>\n\t\t\t<version>2.4.0</version>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.github.xiaoymin</groupId>\n\t\t\t<artifactId>swagger-bootstrap-ui</artifactId>\n\t\t\t<version>1.6</version>\n\t\t</dependency>\n\n\t</dependencies>\n\n\n\t<modules>\n\t\t<module>open-oauth-server</module>\n\t\t<module>open-oauth-client</module>\n\t\t<module>open-oauth-client-two</module>\n\t\t<module>open-oauth-sso</module>\n\t</modules>\n</project>"
  },
  {
    "path": "open-user-center/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" 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  <parent>\n    <groupId>com.open.capacity</groupId>\n    <artifactId>open-capacity-platform</artifactId>\n    <version>0.0.1-SNAPSHOT</version>\n  </parent>\n  <artifactId>open-user-center</artifactId>\n  \n  \n  <dependencies>\n\n\t\t<!-- 关系型和非关系型数据库配置 -->\n\t\t<dependency>\n\t\t\t<groupId>com.open.capacity</groupId>\n\t\t\t<artifactId>open-db-core</artifactId>\n\t\t\t<version>${core.version}</version>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.open.capacity</groupId>\n\t\t\t<artifactId>open-commons</artifactId>\n\t\t\t<version>${core.version}</version>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework</groupId>\n\t\t\t<artifactId>spring-context-support</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-eureka</artifactId>\n\t\t</dependency>\n\t\t\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.social</groupId>\n\t\t\t<artifactId>spring-social-web</artifactId>\n\t\t</dependency>\n\t\t<!-- 加入spring security spring security oauth2的处理 -->\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-oauth2</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.security</groupId>\n\t\t\t<artifactId>spring-security-jwt</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.apache.commons</groupId>\n\t\t\t<artifactId>commons-lang3</artifactId>\n\t\t</dependency>\n\t\n\n\t\t<!-- swagger -->\n\t\t<dependency>\n\t\t\t<groupId>io.swagger</groupId>\n\t\t\t<artifactId>swagger-core</artifactId>\n\t\t\t<version>1.5.8</version>\n\t\t</dependency>\n\t \n\t\t<dependency>\n\t\t\t<groupId>io.springfox</groupId>\n\t\t\t<artifactId>springfox-swagger2</artifactId>\n\t\t\t<version>2.4.0</version>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>io.springfox</groupId>\n\t\t\t<artifactId>springfox-swagger-ui</artifactId>\n\t\t\t<version>2.4.0</version>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.github.xiaoymin</groupId>\n\t\t\t<artifactId>swagger-bootstrap-ui</artifactId>\n\t\t\t<version>1.6</version>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>commons-codec</groupId>\n\t\t\t<artifactId>commons-codec</artifactId>\n\t\t</dependency>\n\t\t\n\t\t<dependency>\n\t\t\t<groupId>io.jsonwebtoken</groupId>\n\t\t\t<artifactId>jjwt</artifactId>\n\t\t\t<version>0.9.0</version>\n\t\t</dependency>\n\t\t\n\t\t<dependency>\n\t\t\t<groupId>com.google.guava</groupId>\n\t\t\t<artifactId>guava</artifactId>\n\t\t\t<version>23.0</version>\n\t\t</dependency>\n\t \n\t\t \n\t\t\n\t</dependencies>\n  \n  \n</project>"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/UserCenterApp.java",
    "content": "package com.open.capacity;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n * 用户中心\n *\n * @author owen 624191343@qq.com\n */\n//@EnableDiscoveryClient\n@SpringBootApplication\npublic class UserCenterApp {\n\n    public static void main(String[] args) {\n        SpringApplication.run(UserCenterApp.class, args);\n    }\n\n}"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/advice/ExceptionHandlerAdvice.java",
    "content": "package com.open.capacity.security.advice;\n\nimport com.open.capacity.security.dto.ResponseInfo;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.converter.HttpMessageNotReadableException;\nimport org.springframework.security.access.AccessDeniedException;\nimport org.springframework.web.bind.MissingServletRequestParameterException;\nimport org.springframework.web.bind.UnsatisfiedServletRequestParameterException;\nimport org.springframework.web.bind.annotation.ExceptionHandler;\nimport org.springframework.web.bind.annotation.ResponseStatus;\nimport org.springframework.web.bind.annotation.RestControllerAdvice;\nimport org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;\n\n/**\n * springmvc异常处理\n * * @author 作者 owen E-mail: 624191343@qq.com\n *\n * @version 创建时间：2018年3月20日 下午10:13:18 类说明\n */\n@RestControllerAdvice\npublic class ExceptionHandlerAdvice {\n\n    private static final Logger log = LoggerFactory.getLogger(ExceptionHandlerAdvice.class);\n\n    @ExceptionHandler({IllegalArgumentException.class})\n    @ResponseStatus(HttpStatus.BAD_REQUEST)\n    public ResponseInfo badRequestException(IllegalArgumentException exception) {\n        return new ResponseInfo(HttpStatus.BAD_REQUEST.value() + \"\", exception.getMessage());\n    }\n\n    @ExceptionHandler({AccessDeniedException.class})\n    @ResponseStatus(HttpStatus.FORBIDDEN)\n    public ResponseInfo badRequestException(AccessDeniedException exception) {\n        return new ResponseInfo(HttpStatus.FORBIDDEN.value() + \"\", exception.getMessage());\n    }\n\n    @ExceptionHandler({MissingServletRequestParameterException.class, HttpMessageNotReadableException.class,\n            UnsatisfiedServletRequestParameterException.class, MethodArgumentTypeMismatchException.class})\n    @ResponseStatus(HttpStatus.BAD_REQUEST)\n    public ResponseInfo badRequestException(Exception exception) {\n        return new ResponseInfo(HttpStatus.BAD_REQUEST.value() + \"\", exception.getMessage());\n    }\n\n    @ExceptionHandler(Throwable.class)\n    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)\n    public ResponseInfo exception(Throwable throwable) {\n        log.error(\"系统异常\", throwable);\n        return new ResponseInfo(HttpStatus.INTERNAL_SERVER_ERROR.value() + \"\", throwable.getMessage());\n\n    }\n\n}\n"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/advice/LogAdvice.java",
    "content": "package com.open.capacity.security.advice;\n\nimport com.open.capacity.security.annotation.LogAnnotation;\nimport com.open.capacity.security.model.SysLogs;\nimport com.open.capacity.security.service.SysLogService;\nimport io.swagger.annotations.ApiOperation;\nimport org.aspectj.lang.ProceedingJoinPoint;\nimport org.aspectj.lang.annotation.Around;\nimport org.aspectj.lang.annotation.Aspect;\nimport org.aspectj.lang.reflect.MethodSignature;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\nimport org.springframework.util.StringUtils;\n\n/**\n * 统一日志处理\n *\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2018年3月20日 下午10:13:18 类说明\n */\n@Aspect\n@Component\npublic class LogAdvice {\n\n    @Autowired\n    private SysLogService logService;\n\n    @Around(value = \"@annotation(com.open.capacity.security.annotation.LogAnnotation)\")\n    public Object logSave(ProceedingJoinPoint joinPoint) throws Throwable {\n        SysLogs sysLogs = new SysLogs();\n        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();\n\n        String module = null;\n        LogAnnotation logAnnotation = methodSignature.getMethod().getDeclaredAnnotation(LogAnnotation.class);\n        module = logAnnotation.module();\n        if (StringUtils.isEmpty(module)) {\n            ApiOperation apiOperation = methodSignature.getMethod().getDeclaredAnnotation(ApiOperation.class);\n            if (apiOperation != null) {\n                module = apiOperation.value();\n            }\n        }\n\n        if (StringUtils.isEmpty(module)) {\n            throw new RuntimeException(\"没有指定日志module\");\n        }\n        sysLogs.setModule(module);\n\n        try {\n            Object object = joinPoint.proceed();\n\n            sysLogs.setFlag(true);\n            logService.save(sysLogs);\n\n            return object;\n        } catch (Exception e) {\n            sysLogs.setFlag(false);\n            sysLogs.setRemark(e.getMessage());\n            logService.save(sysLogs);\n            throw e;\n        }\n\n    }\n}\n"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/annotation/LogAnnotation.java",
    "content": "package com.open.capacity.security.annotation;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * 日志注解\n * * @author 作者 owen E-mail: 624191343@qq.com\n *\n * @version 创建时间：2018年3月20日 下午10:13:18 类说明\n */\n@Target({ElementType.METHOD})\n@Retention(RetentionPolicy.RUNTIME)\npublic @interface LogAnnotation {\n    String module() default \"\";\n}\n"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/config/AsycTaskExecutorConfig.java",
    "content": "package com.open.capacity.security.config;\n\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.core.task.TaskExecutor;\nimport org.springframework.scheduling.annotation.EnableAsync;\nimport org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;\n\n/**\n * 线程池配置、启用异步\n *\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2018年3月20日 下午10:13:18 类说明\n */\n@EnableAsync(proxyTargetClass = true)\n@Configuration\npublic class AsycTaskExecutorConfig {\n\n    @Bean\n    public TaskExecutor taskExecutor() {\n        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();\n        taskExecutor.setCorePoolSize(50);\n        taskExecutor.setMaxPoolSize(100);\n\n        return taskExecutor;\n    }\n}\n"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/config/LoginPageConfig.java",
    "content": "package com.open.capacity.security.config;\n\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.servlet.view.RedirectView;\n\n@Controller\npublic class LoginPageConfig {\n\n    @RequestMapping(\"/\")\n    public RedirectView loginPage() {\n        return new RedirectView(\"/login.html\");\n    }\n}\n"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/config/SecurityConfig.java",
    "content": "package com.open.capacity.security.config;\n\nimport com.open.capacity.security.filter.TokenFilter;\nimport com.open.capacity.security.service.TokenService;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;\nimport org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;\nimport org.springframework.security.config.annotation.web.builders.HttpSecurity;\nimport org.springframework.security.config.annotation.web.builders.WebSecurity;\nimport org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;\nimport org.springframework.security.config.http.SessionCreationPolicy;\nimport org.springframework.security.core.userdetails.UserDetailsService;\nimport org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;\nimport org.springframework.security.web.AuthenticationEntryPoint;\nimport org.springframework.security.web.authentication.AuthenticationFailureHandler;\nimport org.springframework.security.web.authentication.AuthenticationSuccessHandler;\nimport org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;\nimport org.springframework.security.web.authentication.logout.LogoutSuccessHandler;\n\n/**\n * spring security配置\n *\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2018年3月20日 下午10:13:18 类说明\n * 类说明\n */\n//开启spring security 注解\n@EnableGlobalMethodSecurity(prePostEnabled = true)\npublic class SecurityConfig extends WebSecurityConfigurerAdapter {\n\n    @Autowired\n    private AuthenticationSuccessHandler authenticationSuccessHandler;\n    @Autowired\n    private AuthenticationFailureHandler authenticationFailureHandler;\n    @Autowired\n    private LogoutSuccessHandler logoutSuccessHandler;\n    @Autowired\n    private AuthenticationEntryPoint authenticationEntryPoint;\n    @Autowired\n    private UserDetailsService userDetailsService;\n\n    @Autowired\n    private TokenService tokenService;\n\n    @Bean\n    public BCryptPasswordEncoder bCryptPasswordEncoder() {\n        return new BCryptPasswordEncoder();\n    }\n\n    @Override\n    public void configure(WebSecurity web) throws Exception {\n        web.ignoring().antMatchers(\"/js/**\");\n        web.ignoring().antMatchers(\"/css/**\");\n        web.ignoring().antMatchers(\"/layui/**\");\n        web.ignoring().antMatchers(\"/img/**\");\n        web.ignoring().antMatchers(\"/fonts/**\");\n        web.ignoring().antMatchers(\"/lib/**\");\n        web.ignoring().antMatchers(\"/pages/**\");\n        web.ignoring().antMatchers(\"/assets/**\");\n        web.ignoring().antMatchers(\"/base-component/**\");\n        // 忽略登录界面\n        web.ignoring().antMatchers(\"/login.html\");\n    }\n\n    @Override\n    protected void configure(HttpSecurity http) throws Exception {\n        http.csrf().disable();\n\n        // 基于token，所以不需要session\n        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);\n\n        http.authorizeRequests()\n                .antMatchers(\"/\", \"/*.html\", \"/favicon.ico\", \"/css/**\", \"/js/**\", \"/fonts/**\", \"/lib/**\", \"/img/**\",\n                        \"/v2/api-docs/**\", \"/swagger-resources/**\", \"/webjars/**\", \"/pages/**\", \"/druid/**\", \"/users/internal\",\n                        \"/statics/**\")\n                .permitAll().anyRequest().authenticated();\n        http.formLogin().loginPage(\"/login.html\").loginProcessingUrl(\"/login\")\n                .successHandler(authenticationSuccessHandler).failureHandler(authenticationFailureHandler).and()\n                .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint);\n        http.logout().logoutUrl(\"/logout\").logoutSuccessHandler(logoutSuccessHandler);\n        // 解决不允许显示在iframe的问题\n        http.headers().frameOptions().disable();\n        http.headers().cacheControl();\n\n        //新增token过滤器\n        TokenFilter tokenFilter = new TokenFilter();\n        tokenFilter.setTokenService(tokenService);\n        tokenFilter.setUserDetailsService(userDetailsService);\n        tokenFilter.afterPropertiesSet();\n        http.addFilterBefore(tokenFilter, UsernamePasswordAuthenticationFilter.class);\n    }\n\n\n    @Override\n    protected void configure(AuthenticationManagerBuilder auth) throws Exception {\n        auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());\n    }\n\n}\n"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/config/SecurityHandlerConfig.java",
    "content": "package com.open.capacity.security.config;\n\nimport com.open.capacity.security.dto.LoginUser;\nimport com.open.capacity.security.dto.ResponseInfo;\nimport com.open.capacity.security.dto.Token;\nimport com.open.capacity.security.filter.TokenFilter;\nimport com.open.capacity.security.service.TokenService;\nimport com.open.capacity.security.utils.ResponseUtil;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.security.authentication.BadCredentialsException;\nimport org.springframework.security.core.Authentication;\nimport org.springframework.security.core.AuthenticationException;\nimport org.springframework.security.web.AuthenticationEntryPoint;\nimport org.springframework.security.web.authentication.AuthenticationFailureHandler;\nimport org.springframework.security.web.authentication.AuthenticationSuccessHandler;\nimport org.springframework.security.web.authentication.logout.LogoutSuccessHandler;\n\nimport javax.servlet.ServletException;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport java.io.IOException;\n\n/**\n * spring security处理器\n *\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2018年3月20日 下午10:13:18 类说明\n */\n@Configuration\npublic class SecurityHandlerConfig {\n\n    @Autowired\n    private TokenService tokenService;\n\n    /**\n     * 登陆成功，返回Token\n     *\n     * @return\n     */\n    @Bean\n    public AuthenticationSuccessHandler loginSuccessHandler() {\n        return new AuthenticationSuccessHandler() {\n\n            @Override\n            public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,\n                                                Authentication authentication) throws IOException, ServletException {\n                LoginUser loginUser = (LoginUser) authentication.getPrincipal();\n\n                Token token = tokenService.saveToken(loginUser);\n                ResponseUtil.responseJson(response, HttpStatus.OK.value(), token);\n            }\n        };\n    }\n\n    /**\n     * 登陆失败\n     *\n     * @return\n     */\n    @Bean\n    public AuthenticationFailureHandler loginFailureHandler() {\n        return new AuthenticationFailureHandler() {\n\n            @Override\n            public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,\n                                                AuthenticationException exception) throws IOException, ServletException {\n                String msg = null;\n                if (exception instanceof BadCredentialsException) {\n                    msg = \"密码错误\";\n                } else {\n                    msg = exception.getMessage();\n                }\n                ResponseInfo info = new ResponseInfo(HttpStatus.UNAUTHORIZED.value() + \"\", msg);\n                ResponseUtil.responseJson(response, HttpStatus.UNAUTHORIZED.value(), info);\n            }\n        };\n\n    }\n\n    /**\n     * 未登录，返回401\n     *\n     * @return\n     */\n    @Bean\n    public AuthenticationEntryPoint authenticationEntryPoint() {\n        return new AuthenticationEntryPoint() {\n\n            @Override\n            public void commence(HttpServletRequest request, HttpServletResponse response,\n                                 AuthenticationException authException) throws IOException, ServletException {\n                ResponseInfo info = new ResponseInfo(HttpStatus.UNAUTHORIZED.value() + \"\", \"请先登录\");\n                ResponseUtil.responseJson(response, HttpStatus.UNAUTHORIZED.value(), info);\n            }\n        };\n    }\n\n    /**\n     * 退出处理\n     *\n     * @return\n     */\n    @Bean\n    public LogoutSuccessHandler logoutSussHandler() {\n        return new LogoutSuccessHandler() {\n\n            @Override\n            public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,\n                                        Authentication authentication) throws IOException, ServletException {\n                ResponseInfo info = new ResponseInfo(HttpStatus.OK.value() + \"\", \"退出成功\");\n\n                String token = TokenFilter.getToken(request);\n                tokenService.deleteToken(token);\n\n                ResponseUtil.responseJson(response, HttpStatus.OK.value(), info);\n            }\n        };\n\n    }\n\n}\n"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/config/SwaggerConfig.java",
    "content": "package com.open.capacity.security.config;\n\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport springfox.documentation.builders.ApiInfoBuilder;\nimport springfox.documentation.builders.PathSelectors;\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 * swagger文档\n *\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2018年3月20日 下午10:13:18 类说明\n */\n@Configuration\n@EnableSwagger2\npublic class SwaggerConfig {\n\n    @Bean\n    public Docket docket() {\n        return new Docket(DocumentationType.SWAGGER_2).groupName(\"swagger接口文档\")\n                .apiInfo(new ApiInfoBuilder().title(\"swagger接口文档\")\n                        .contact(new Contact(\"owen\", \"\", \"624191343@qq.com\")).version(\"1.0\").build())\n                .select().paths(PathSelectors.any()).build();\n    }\n}\n"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/config/WebMvcConfig.java",
    "content": "package com.open.capacity.security.config;\n\nimport com.open.capacity.security.page.table.PageTableArgumentResolver;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.stereotype.Component;\nimport org.springframework.util.ResourceUtils;\nimport org.springframework.web.context.request.RequestContextListener;\nimport org.springframework.web.cors.CorsConfiguration;\nimport org.springframework.web.cors.UrlBasedCorsConfigurationSource;\nimport org.springframework.web.filter.CorsFilter;\nimport org.springframework.web.method.support.HandlerMethodArgumentResolver;\nimport org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;\nimport org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;\n\nimport java.io.File;\nimport java.util.List;\n\n@Component\n@Configuration\npublic class WebMvcConfig extends WebMvcConfigurerAdapter {\n\n    /**\n     * 上传文件根路径\n     */\n    @Value(\"${files.path}\")\n    private String filesPath;\n\n    /**\n     * 跨域支持\n     *\n     * @return\n     */\n    @Bean\n    // 前后分离 ajax跨域调用处理\n    public CorsFilter corsFilter() {\n        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();\n        final CorsConfiguration config = new CorsConfiguration();\n        config.setAllowCredentials(true); // 允许cookies跨域\n        config.addAllowedOrigin(\"*\");// 允许向该服务器提交请求的URI，*表示全部允许。。这里尽量限制来源域，比如http://xxxx:8080\n        // ,以降低安全风险。。\n        config.addAllowedHeader(\"*\");// 允许访问的头信息,*表示全部\n        config.setMaxAge(18000L);// 预检请求的缓存时间（秒），即在这个时间段里，对于相同的跨域请求不会再预检了\n        config.addAllowedMethod(\"*\");// 允许提交请求的方法，*表示全部允许，也可以单独设置GET、PUT等\n        /*\n         * config.addAllowedMethod(\"HEAD\"); config.addAllowedMethod(\"GET\");//\n         * 允许Get的请求方法 config.addAllowedMethod(\"PUT\");\n         * config.addAllowedMethod(\"POST\"); config.addAllowedMethod(\"DELETE\");\n         * config.addAllowedMethod(\"PATCH\");\n         */\n        source.registerCorsConfiguration(\"/**\", config);\n        return new CorsFilter(source);\n    }\n\n    @Bean\n    public RequestContextListener requestContextListener() {\n        return new RequestContextListener();\n    }\n\n    /**\n     * datatable分页解析\n     *\n     * @return\n     */\n    @Bean\n    public PageTableArgumentResolver tableHandlerMethodArgumentResolver() {\n        return new PageTableArgumentResolver();\n    }\n\n    @Override\n    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {\n        argumentResolvers.add(tableHandlerMethodArgumentResolver());\n    }\n\n    /**\n     * 外部文件访问\n     */\n    @Override\n    public void addResourceHandlers(ResourceHandlerRegistry registry) {\n        registry.addResourceHandler(\"/statics/**\")\n                .addResourceLocations(ResourceUtils.FILE_URL_PREFIX + filesPath + File.separator);\n    }\n\n}\n"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/controller/PermissionController.java",
    "content": "package com.open.capacity.security.controller;\n\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\nimport com.google.common.collect.Lists;\nimport com.open.capacity.security.annotation.LogAnnotation;\nimport com.open.capacity.security.dao.PermissionDao;\nimport com.open.capacity.security.dto.LoginUser;\nimport com.open.capacity.security.model.Permission;\nimport com.open.capacity.security.service.PermissionService;\nimport com.open.capacity.security.utils.UserUtil;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.security.access.prepost.PreAuthorize;\nimport org.springframework.util.CollectionUtils;\nimport org.springframework.util.StringUtils;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Set;\nimport java.util.stream.Collectors;\n\n/**\n * 权限相关接口\n *\n * @author owen 624191343@qq.com\n */\n@Api(tags = \"权限\")\n@RestController\n@RequestMapping(\"/permissions\")\npublic class PermissionController {\n\n    @Autowired\n    private PermissionDao permissionDao;\n    @Autowired\n    private PermissionService permissionService;\n\n    @ApiOperation(value = \"当前登录用户拥有的权限\")\n    @GetMapping(\"/current\")\n    public List<Permission> permissionsCurrent() {\n        LoginUser loginUser = UserUtil.getLoginUser();\n        List<Permission> list = loginUser.getPermissions();\n        final List<Permission> permissions = list.stream().filter(l -> l.getType().equals(1))\n                .collect(Collectors.toList());\n\n        setChild(permissions);\n\n        return permissions.stream().filter(p -> p.getParentId().equals(0L)).collect(Collectors.toList());\n    }\n\n    private void setChild(List<Permission> permissions) {\n        permissions.parallelStream().forEach(per -> {\n            List<Permission> child = permissions.stream().filter(p -> p.getParentId().equals(per.getId()))\n                    .collect(Collectors.toList());\n            per.setChild(child);\n        });\n    }\n\n    /**\n     * 菜单列表\n     *\n     * @param pId\n     * @param permissionsAll\n     * @param list\n     */\n    private void setPermissionsList(Long pId, List<Permission> permissionsAll, List<Permission> list) {\n        for (Permission per : permissionsAll) {\n            if (per.getParentId().equals(pId)) {\n                list.add(per);\n                if (permissionsAll.stream().filter(p -> p.getParentId().equals(per.getId())).findAny() != null) {\n                    setPermissionsList(per.getId(), permissionsAll, list);\n                }\n            }\n        }\n    }\n\n    @GetMapping\n    @ApiOperation(value = \"菜单列表\")\n    @PreAuthorize(\"hasAuthority('sys:menu:query')\")\n    public List<Permission> permissionsList() {\n        List<Permission> permissionsAll = permissionDao.listAll();\n\n        List<Permission> list = Lists.newArrayList();\n        setPermissionsList(0L, permissionsAll, list);\n\n        return list;\n    }\n\n    @GetMapping(\"/all\")\n    @ApiOperation(value = \"所有菜单\")\n    @PreAuthorize(\"hasAuthority('sys:menu:query')\")\n    public JSONArray permissionsAll() {\n        List<Permission> permissionsAll = permissionDao.listAll();\n        JSONArray array = new JSONArray();\n        setPermissionsTree(0L, permissionsAll, array);\n\n        return array;\n    }\n\n    @GetMapping(\"/parents\")\n    @ApiOperation(value = \"一级菜单\")\n    @PreAuthorize(\"hasAuthority('sys:menu:query')\")\n    public List<Permission> parentMenu() {\n        List<Permission> parents = permissionDao.listParents();\n\n        return parents;\n    }\n\n    /**\n     * 菜单树\n     *\n     * @param pId\n     * @param permissionsAll\n     * @param array\n     */\n    private void setPermissionsTree(Long pId, List<Permission> permissionsAll, JSONArray array) {\n        for (Permission per : permissionsAll) {\n            if (per.getParentId().equals(pId)) {\n                String string = JSONObject.toJSONString(per);\n                JSONObject parent = (JSONObject) JSONObject.parse(string);\n                array.add(parent);\n\n                if (permissionsAll.stream().filter(p -> p.getParentId().equals(per.getId())).findAny() != null) {\n                    JSONArray child = new JSONArray();\n                    parent.put(\"child\", child);\n                    setPermissionsTree(per.getId(), permissionsAll, child);\n                }\n            }\n        }\n    }\n\n    @GetMapping(params = \"roleId\")\n    @ApiOperation(value = \"根据角色id删除权限\")\n    @PreAuthorize(\"hasAnyAuthority('sys:menu:query','sys:role:query')\")\n    public List<Permission> listByRoleId(Long roleId) {\n        return permissionDao.listByRoleId(roleId);\n    }\n\n    @LogAnnotation\n    @PostMapping\n    @ApiOperation(value = \"保存菜单\")\n    @PreAuthorize(\"hasAuthority('sys:menu:add')\")\n    public void save(@RequestBody Permission permission) {\n        permissionDao.save(permission);\n    }\n\n    @GetMapping(\"/{id}\")\n    @ApiOperation(value = \"根据菜单id获取菜单\")\n    @PreAuthorize(\"hasAuthority('sys:menu:query')\")\n    public Permission get(@PathVariable Long id) {\n        return permissionDao.getById(id);\n    }\n\n    @LogAnnotation\n    @PutMapping\n    @ApiOperation(value = \"修改菜单\")\n    @PreAuthorize(\"hasAuthority('sys:menu:add')\")\n    public void update(@RequestBody Permission permission) {\n        permissionService.update(permission);\n    }\n\n    /**\n     * 校验权限\n     *\n     * @return\n     */\n    @GetMapping(\"/owns\")\n    @ApiOperation(value = \"校验当前用户的权限\")\n    public Set<String> ownsPermission() {\n        List<Permission> permissions = UserUtil.getLoginUser().getPermissions();\n        if (CollectionUtils.isEmpty(permissions)) {\n            return Collections.emptySet();\n        }\n\n        return permissions.parallelStream().filter(p -> !StringUtils.isEmpty(p.getPermission()))\n                .map(Permission::getPermission).collect(Collectors.toSet());\n    }\n\n    @LogAnnotation\n    @DeleteMapping(\"/{id}\")\n    @ApiOperation(value = \"删除菜单\")\n    @PreAuthorize(\"hasAuthority('sys:menu:del')\")\n    public void delete(@PathVariable Long id) {\n        permissionService.delete(id);\n    }\n}\n"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/controller/RoleController.java",
    "content": "package com.open.capacity.security.controller;\n\nimport com.google.common.collect.Maps;\nimport com.open.capacity.security.annotation.LogAnnotation;\nimport com.open.capacity.security.dao.RoleDao;\nimport com.open.capacity.security.dto.RoleDto;\nimport com.open.capacity.security.model.Role;\nimport com.open.capacity.security.page.table.PageTableHandler;\nimport com.open.capacity.security.page.table.PageTableHandler.CountHandler;\nimport com.open.capacity.security.page.table.PageTableHandler.ListHandler;\nimport com.open.capacity.security.page.table.PageTableRequest;\nimport com.open.capacity.security.page.table.PageTableResponse;\nimport com.open.capacity.security.service.RoleService;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.security.access.prepost.PreAuthorize;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.List;\n\n/**\n * 角色相关接口\n *\n * @author owen 624191343@qq.com\n */\n@Api(tags = \"角色\")\n@RestController\n@RequestMapping(\"/roles\")\npublic class RoleController {\n\n    @Autowired\n    private RoleService roleService;\n    @Autowired\n    private RoleDao roleDao;\n\n    @LogAnnotation\n    @PostMapping\n    @ApiOperation(value = \"保存角色\")\n    @PreAuthorize(\"hasAuthority('sys:role:add')\")\n    public void saveRole(@RequestBody RoleDto roleDto) {\n        roleService.saveRole(roleDto);\n    }\n\n    @GetMapping\n    @ApiOperation(value = \"角色列表\")\n    @PreAuthorize(\"hasAuthority('sys:role:query')\")\n    public PageTableResponse listRoles(PageTableRequest request) {\n        return new PageTableHandler(new CountHandler() {\n\n            @Override\n            public int count(PageTableRequest request) {\n                return roleDao.count(request.getParams());\n            }\n        }, new ListHandler() {\n\n            @Override\n            public List<Role> list(PageTableRequest request) {\n                List<Role> list = roleDao.list(request.getParams(), request.getOffset(), request.getLimit());\n                return list;\n            }\n        }).handle(request);\n    }\n\n    @GetMapping(\"/{id}\")\n    @ApiOperation(value = \"根据id获取角色\")\n    @PreAuthorize(\"hasAuthority('sys:role:query')\")\n    public Role get(@PathVariable Long id) {\n        return roleDao.getById(id);\n    }\n\n    @GetMapping(\"/all\")\n    @ApiOperation(value = \"所有角色\")\n    @PreAuthorize(\"hasAnyAuthority('sys:user:query','sys:role:query')\")\n    public List<Role> roles() {\n        return roleDao.list(Maps.newHashMap(), null, null);\n    }\n\n    @GetMapping(params = \"userId\")\n    @ApiOperation(value = \"根据用户id获取拥有的角色\")\n    @PreAuthorize(\"hasAnyAuthority('sys:user:query','sys:role:query')\")\n    public List<Role> roles(Long userId) {\n        return roleDao.listByUserId(userId);\n    }\n\n    @LogAnnotation\n    @DeleteMapping(\"/{id}\")\n    @ApiOperation(value = \"删除角色\")\n    @PreAuthorize(\"hasAuthority('sys:role:del')\")\n    public void delete(@PathVariable Long id) {\n        roleService.deleteRole(id);\n    }\n}\n"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/controller/UserController.java",
    "content": "package com.open.capacity.security.controller;\n\nimport com.open.capacity.security.annotation.LogAnnotation;\nimport com.open.capacity.security.dao.UserDao;\nimport com.open.capacity.security.dto.LoginUser;\nimport com.open.capacity.security.dto.UserDto;\nimport com.open.capacity.security.model.SysUser;\nimport com.open.capacity.security.page.table.PageTableHandler;\nimport com.open.capacity.security.page.table.PageTableHandler.CountHandler;\nimport com.open.capacity.security.page.table.PageTableHandler.ListHandler;\nimport com.open.capacity.security.page.table.PageTableRequest;\nimport com.open.capacity.security.page.table.PageTableResponse;\nimport com.open.capacity.security.service.UserService;\nimport com.open.capacity.security.utils.UserUtil;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.BeanUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.security.access.prepost.PreAuthorize;\nimport org.springframework.security.core.userdetails.UserDetailsService;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.List;\n\n/**\n * 用户相关接口\n *\n * @author 624191343@qq.com\n */\n@Api(tags = \"用户\")\n\n@RestController\n@RequestMapping(\"/users\")\npublic class UserController {\n\n    private static final Logger log = LoggerFactory.getLogger(UserController.class);\n\n    @Autowired\n    private UserService userService;\n    @Autowired\n    private UserDao userDao;\n\n    @Autowired\n    private UserDetailsService userDetailsService;\n\n    @LogAnnotation\n    @PostMapping\n    @ApiOperation(value = \"保存用户\")\n    @PreAuthorize(\"hasAuthority('sys:user:add')\")\n    public SysUser saveUser(@RequestBody UserDto userDto) {\n        SysUser u = userService.getUser(userDto.getUsername());\n        if (u != null) {\n            throw new IllegalArgumentException(userDto.getUsername() + \"已存在\");\n        }\n\n        return userService.saveUser(userDto);\n    }\n\n    @LogAnnotation\n    @PutMapping\n    @ApiOperation(value = \"修改用户\")\n    @PreAuthorize(\"hasAuthority('sys:user:add')\")\n    public SysUser updateUser(@RequestBody UserDto userDto) {\n        return userService.updateUser(userDto);\n    }\n\n    @LogAnnotation\n    @PutMapping(params = \"headImgUrl\")\n    @ApiOperation(value = \"修改头像\")\n    public void updateHeadImgUrl(String headImgUrl) {\n        SysUser user = UserUtil.getLoginUser();\n        UserDto userDto = new UserDto();\n        BeanUtils.copyProperties(user, userDto);\n        userDto.setHeadImgUrl(headImgUrl);\n\n        userService.updateUser(userDto);\n        log.debug(\"{}修改了头像\", user.getUsername());\n    }\n\n    @LogAnnotation\n    @PutMapping(\"/{username}\")\n    @ApiOperation(value = \"修改密码\")\n    @PreAuthorize(\"hasAuthority('sys:user:password')\")\n    public void changePassword(@PathVariable String username, String oldPassword, String newPassword) {\n        userService.changePassword(username, oldPassword, newPassword);\n    }\n\n    @GetMapping\n    @ApiOperation(value = \"用户列表\")\n    @PreAuthorize(\"hasAuthority('sys:user:query')\")\n    public PageTableResponse listUsers(PageTableRequest request) {\n        return new PageTableHandler(new CountHandler() {\n\n            @Override\n            public int count(PageTableRequest request) {\n                return userDao.count(request.getParams());\n            }\n        }, new ListHandler() {\n\n            @Override\n            public List<SysUser> list(PageTableRequest request) {\n                List<SysUser> list = userDao.list(request.getParams(), request.getOffset(), request.getLimit());\n                return list;\n            }\n        }).handle(request);\n    }\n\n    @ApiOperation(value = \"当前登录用户\")\n    @GetMapping(\"/current\")\n    public SysUser currentUser() {\n        return UserUtil.getLoginUser();\n    }\n\n    @ApiOperation(value = \"根据用户id获取用户\")\n    @GetMapping(\"/{id}\")\n    @PreAuthorize(\"hasAuthority('sys:user:query')\")\n    public SysUser user(@PathVariable Long id) {\n        return userDao.getById(id);\n    }\n\n    @GetMapping(value = \"/internal\", params = \"username\")\n    public LoginUser findByUsername(String username) {\n        return (LoginUser) userDetailsService.loadUserByUsername(username);\n    }\n\n}\n"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/dao/PermissionDao.java",
    "content": "package com.open.capacity.security.dao;\n\nimport com.open.capacity.security.model.Permission;\nimport org.apache.ibatis.annotations.*;\n\nimport java.util.List;\nimport java.util.Set;\n\n@Mapper\npublic interface PermissionDao {\n\n    @Select(\"select * from sys_permission t order by t.sort\")\n    List<Permission> listAll();\n\n    @Select(\"select * from sys_permission t where t.type = 1 order by t.sort\")\n    List<Permission> listParents();\n\n    @Select(\"select distinct p.* from sys_permission p inner join sys_role_permission rp on p.id = rp.permissionId inner join sys_role_user ru on ru.roleId = rp.roleId where ru.userId = #{userId} order by p.sort\")\n    List<Permission> listByUserId(Long userId);\n\n    @Select(\"select p.* from sys_permission p inner join sys_role_permission rp on p.id = rp.permissionId where rp.roleId = #{roleId} order by p.sort\")\n    List<Permission> listByRoleId(Long roleId);\n\n    @Select(\"select * from sys_permission t where t.id = #{id}\")\n    Permission getById(Long id);\n\n    @Insert(\"insert into sys_permission(parentId, name, css, href, type, permission, sort) values(#{parentId}, #{name}, #{css}, #{href}, #{type}, #{permission}, #{sort})\")\n    int save(Permission permission);\n\n    @Update(\"update sys_permission t set parentId = #{parentId}, name = #{name}, css = #{css}, href = #{href}, type = #{type}, permission = #{permission}, sort = #{sort} where t.id = #{id}\")\n    int update(Permission permission);\n\n    @Delete(\"delete from sys_permission where id = #{id}\")\n    int delete(Long id);\n\n    @Delete(\"delete from sys_permission where parentId = #{id}\")\n    int deleteByParentId(Long id);\n\n    @Delete(\"delete from sys_role_permission where permissionId = #{permissionId}\")\n    int deleteRolePermission(Long permissionId);\n\n    @Select(\"select ru.userId from sys_role_permission rp inner join sys_role_user ru on ru.roleId = rp.roleId where rp.permissionId = #{permissionId}\")\n    Set<Long> listUserIds(Long permissionId);\n}\n"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/dao/RoleDao.java",
    "content": "package com.open.capacity.security.dao;\n\nimport com.open.capacity.security.model.Role;\nimport org.apache.ibatis.annotations.*;\n\nimport java.util.List;\nimport java.util.Map;\n\n@Mapper\npublic interface RoleDao {\n\n    @Options(useGeneratedKeys = true, keyProperty = \"id\")\n    @Insert(\"insert into sys_role(name, description, createTime, updateTime) values(#{name}, #{description}, now(),now())\")\n    int save(Role role);\n\n    int count(@Param(\"params\") Map<String, Object> params);\n\n    List<Role> list(@Param(\"params\") Map<String, Object> params, @Param(\"offset\") Integer offset,\n                    @Param(\"limit\") Integer limit);\n\n    @Select(\"select * from sys_role t where t.id = #{id}\")\n    Role getById(Long id);\n\n    @Select(\"select * from sys_role t where t.name = #{name}\")\n    Role getRole(String name);\n\n    @Update(\"update sys_role t set t.name = #{name}, t.description = #{description}, updateTime = now() where t.id = #{id}\")\n    int update(Role role);\n\n    @Select(\"select * from sys_role r inner join sys_role_user ru on r.id = ru.roleId where ru.userId = #{userId}\")\n    List<Role> listByUserId(Long userId);\n\n    @Delete(\"delete from sys_role_permission where roleId = #{roleId}\")\n    int deleteRolePermission(Long roleId);\n\n    int saveRolePermission(@Param(\"roleId\") Long roleId, @Param(\"permissionIds\") List<Long> permissionIds);\n\n    @Delete(\"delete from sys_role where id = #{id}\")\n    int delete(Long id);\n\n    @Delete(\"delete from sys_role_user where roleId = #{roleId}\")\n    int deleteRoleUser(Long roleId);\n\n}\n"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/dao/RoleDao.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.open.capacity.security.dao.RoleDao\">\n\n    <sql id=\"where\">\n        <where>\n            <if test=\"params.name != null and params.name != ''\">\n                and t.name like concat('%', #{params.name}, '%')\n            </if>\n        </where>\n    </sql>\n\n    <select id=\"count\" resultType=\"int\">\n        select count(1) from sys_role t\n        <include refid=\"where\"/>\n    </select>\n\n    <select id=\"list\" resultType=\"com.open.capacity.security.model.Role\">\n        select * from sys_role t\n        <include refid=\"where\"/>\n        ${params.orderBy}\n        <if test=\"offset != null and offset >= 0 and limit != null and limit >= 0\">\n            limit #{offset}, #{limit}\n        </if>\n    </select>\n\n    <insert id=\"saveRolePermission\">\n        insert into sys_role_permission(roleId, permissionId) values\n        <foreach collection=\"permissionIds\" item=\"permissionId\"\n                 separator=\",\">\n            (#{roleId}, #{permissionId})\n        </foreach>\n    </insert>\n\n</mapper>"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/dao/SysLogsDao.java",
    "content": "package com.open.capacity.security.dao;\n\nimport com.open.capacity.security.model.SysLogs;\nimport org.apache.ibatis.annotations.Delete;\nimport org.apache.ibatis.annotations.Insert;\nimport org.apache.ibatis.annotations.Mapper;\nimport org.apache.ibatis.annotations.Param;\n\nimport java.util.List;\nimport java.util.Map;\n\n@Mapper\npublic interface SysLogsDao {\n\n    @Insert(\"insert into sys_logs(userId, module, flag, remark, createTime) values(#{user.id}, #{module}, #{flag}, #{remark}, now())\")\n    int save(SysLogs sysLogs);\n\n    int count(@Param(\"params\") Map<String, Object> params);\n\n    List<SysLogs> list(@Param(\"params\") Map<String, Object> params, @Param(\"offset\") Integer offset,\n                       @Param(\"limit\") Integer limit);\n\n    @Delete(\"delete from sys_logs where createTime <= #{time}\")\n    int deleteLogs(String time);\n}\n"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/dao/SysLogsDao.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.open.capacity.security.dao.SysLogsDao\">\n\n    <resultMap id=\"BaseResultMap\" type=\"com.open.capacity.security.model.SysLogs\">\n        <id column=\"id\" property=\"id\"/>\n        <result column=\"module\" property=\"module\"/>\n        <result column=\"remark\" property=\"remark\"/>\n        <result column=\"flag\" property=\"flag\"/>\n        <result column=\"createTime\" property=\"createTime\"/>\n        <association property=\"user\" javaType=\"com.open.capacity.security.model.SysUser\">\n            <result property=\"id\" column=\"userId\"/>\n            <result property=\"username\" column=\"username\"/>\n            <result property=\"nickname\" column=\"nickname\"/>\n        </association>\n    </resultMap>\n\n    <sql id=\"where\">\n        <where>\n            <if test=\"params.flag != null and params.flag != ''\">\n                and t.flag = #{params.flag}\n            </if>\n            <if test=\"params.nickname != null and params.nickname != ''\">\n                and u.nickname like concat('%', #{params.nickname}, '%')\n            </if>\n            <if test=\"params.beginTime != null and params.beginTime != ''\">\n                and t.createTime &gt;= #{params.beginTime}\n            </if>\n            <if test=\"params.endTime != null and params.endTime != ''\">\n                and DATE(t.createTime) &lt;= #{params.endTime}\n            </if>\n        </where>\n    </sql>\n\n    <select id=\"count\" resultType=\"int\">\n        select count(1) from sys_logs t left join sys_user\n        u on\n        u.id = t.userId\n        <include refid=\"where\"/>\n    </select>\n\n    <select id=\"list\" resultMap=\"BaseResultMap\">\n        select t.*, u.username, u.nickname from sys_logs t left join sys_user\n        u on\n        u.id = t.userId\n        <include refid=\"where\"/>\n        ${params.orderBy}\n        limit #{offset}, #{limit}\n    </select>\n\n</mapper>\n"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/dao/TokenDao.java",
    "content": "package com.open.capacity.security.dao;\n\nimport com.open.capacity.security.model.TokenModel;\nimport org.apache.ibatis.annotations.*;\n\n@Mapper\npublic interface TokenDao {\n\n    @Insert(\"insert into t_token(id, val, expireTime, createTime, updateTime) values (#{id}, #{val}, #{expireTime}, #{createTime}, #{updateTime})\")\n    int save(TokenModel model);\n\n    @Select(\"select * from t_token t where t.id = #{id}\")\n    TokenModel getById(String id);\n\n    @Update(\"update t_token t set t.val = #{val}, t.expireTime = #{expireTime}, t.updateTime = #{updateTime} where t.id = #{id}\")\n    int update(TokenModel model);\n\n    @Delete(\"delete from t_token where id = #{id}\")\n    int delete(String id);\n}\n"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/dao/UserDao.java",
    "content": "package com.open.capacity.security.dao;\n\nimport com.open.capacity.security.model.SysUser;\nimport org.apache.ibatis.annotations.*;\n\nimport java.util.List;\nimport java.util.Map;\n\n@Mapper\npublic interface UserDao {\n\n    @Options(useGeneratedKeys = true, keyProperty = \"id\")\n    @Insert(\"insert into sys_user(username, password, nickname, headImgUrl, phone, telephone, email, birthday, sex, status, createTime, updateTime) values(#{username}, #{password}, #{nickname}, #{headImgUrl}, #{phone}, #{telephone}, #{email}, #{birthday}, #{sex}, #{status}, now(), now())\")\n    int save(SysUser user);\n\n    @Select(\"select * from sys_user t where t.id = #{id}\")\n    SysUser getById(Long id);\n\n    @Select(\"select * from sys_user t where t.username = #{username}\")\n    SysUser getUser(String username);\n\n    @Update(\"update sys_user t set t.password = #{password} where t.id = #{id}\")\n    int changePassword(@Param(\"id\") Long id, @Param(\"password\") String password);\n\n    Integer count(@Param(\"params\") Map<String, Object> params);\n\n    List<SysUser> list(@Param(\"params\") Map<String, Object> params, @Param(\"offset\") Integer offset,\n                       @Param(\"limit\") Integer limit);\n\n    @Delete(\"delete from sys_role_user where userId = #{userId}\")\n    int deleteUserRole(Long userId);\n\n    int saveUserRoles(@Param(\"userId\") Long userId, @Param(\"roleIds\") List<Long> roleIds);\n\n    int update(SysUser user);\n}\n"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/dao/UserDao.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.open.capacity.security.dao.UserDao\">\n\n    <sql id=\"where\">\n        <where>\n            <if test=\"params.username != null and params.username != ''\">\n                and t.username like concat('%', #{params.username}, '%')\n            </if>\n            <if test=\"params.nickname != null and params.nickname != ''\">\n                and t.nickname like concat('%', #{params.nickname}, '%')\n            </if>\n            <if test=\"params.status != null and params.status != ''\">\n                and t.status = #{params.status}\n            </if>\n        </where>\n    </sql>\n\n    <select id=\"count\" resultType=\"int\">\n        select count(1) from sys_user t\n        <include refid=\"where\"/>\n    </select>\n\n    <select id=\"list\" resultType=\"com.open.capacity.security.model.SysUser\">\n        select * from sys_user t\n        <include refid=\"where\"/>\n        ${params.orderBy}\n        limit #{offset}, #{limit}\n    </select>\n\n    <insert id=\"saveUserRoles\">\n        insert into sys_role_user(roleId, userId) values\n        <foreach collection=\"roleIds\" item=\"roleId\" separator=\",\">\n            (#{roleId}, #{userId})\n        </foreach>\n    </insert>\n\n    <update id=\"update\">\n        update sys_user t\n        <set>\n            <if test=\"username != null\">\n                username = #{username},\n            </if>\n            <if test=\"nickname != null\">\n                nickname = #{nickname},\n            </if>\n            <if test=\"headImgUrl != null\">\n                headImgUrl = #{headImgUrl},\n            </if>\n            <if test=\"phone != null\">\n                phone = #{phone},\n            </if>\n            <if test=\"telephone != null\">\n                telephone = #{telephone},\n            </if>\n            <if test=\"email != null\">\n                email = #{email},\n            </if>\n            <if test=\"birthday != null\">\n                birthday = #{birthday},\n            </if>\n            <if test=\"sex != null\">\n                sex = #{sex},\n            </if>\n            <if test=\"status != null\">\n                status = #{status},\n            </if>\n            updateTime = #{updateTime}\n        </set>\n        where t.id = #{id}\n    </update>\n</mapper>"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/dto/Token.java",
    "content": "package com.open.capacity.security.dto;\n\nimport java.io.Serializable;\n\n/**\n * Restful方式登陆token\n *\n * @author owen 624191343@qq.com\n * <p>\n * 2017年8月4日\n */\npublic class Token implements Serializable {\n\n    private static final long serialVersionUID = 6314027741784310221L;\n\n    private String token;\n    /**\n     * 登陆时间戳（毫秒）\n     */\n    private Long loginTime;\n\n    public Token(String token, Long loginTime) {\n        super();\n        this.token = token;\n        this.loginTime = loginTime;\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 Long getLoginTime() {\n        return loginTime;\n    }\n\n    public void setLoginTime(Long loginTime) {\n        this.loginTime = loginTime;\n    }\n\n}\n"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/filter/TokenFilter.java",
    "content": "package com.open.capacity.security.filter;\n\nimport com.open.capacity.security.dto.LoginUser;\nimport com.open.capacity.security.service.TokenService;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.security.authentication.UsernamePasswordAuthenticationToken;\nimport org.springframework.security.core.context.SecurityContextHolder;\nimport org.springframework.security.core.userdetails.UserDetailsService;\nimport org.springframework.web.filter.OncePerRequestFilter;\n\nimport javax.servlet.FilterChain;\nimport javax.servlet.ServletException;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport java.io.IOException;\n\n/**\n * Token过滤器\n *\n * @author owen 624191343@qq.com\n * <p>\n * 2017年10月14日\n */\npublic class TokenFilter extends OncePerRequestFilter {\n\n    private static final String TOKEN_KEY = \"access_token\";\n    private static final Long MINUTES_10 = 10 * 60 * 1000L;\n    private TokenService tokenService;\n    private UserDetailsService userDetailsService;\n\n    /**\n     * 根据参数或者header获取token\n     *\n     * @param request\n     * @return\n     */\n    public static String getToken(HttpServletRequest request) {\n        String token = request.getParameter(TOKEN_KEY);\n        if (StringUtils.isBlank(token)) {\n            token = request.getHeader(TOKEN_KEY);\n        }\n\n        return token;\n    }\n\n    public TokenService getTokenService() {\n        return tokenService;\n    }\n\n    public void setTokenService(TokenService tokenService) {\n        this.tokenService = tokenService;\n    }\n\n    public UserDetailsService getUserDetailsService() {\n        return userDetailsService;\n    }\n\n    public void setUserDetailsService(UserDetailsService userDetailsService) {\n        this.userDetailsService = userDetailsService;\n    }\n\n    @Override\n    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)\n            throws ServletException, IOException {\n        String token = getToken(request);\n        if (StringUtils.isNotBlank(token)) {\n            LoginUser loginUser = tokenService.getLoginUser(token);\n            if (loginUser != null) {\n                loginUser = checkLoginTime(loginUser);\n                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(loginUser,\n                        null, loginUser.getAuthorities());\n                SecurityContextHolder.getContext().setAuthentication(authentication);\n            }\n        }\n\n        filterChain.doFilter(request, response);\n    }\n\n    /**\n     * 校验时间<br>\n     * 过期时间与当前时间对比，临近过期10分钟内的话，自动刷新缓存\n     *\n     * @param loginUser\n     * @return\n     */\n    private LoginUser checkLoginTime(LoginUser loginUser) {\n        long expireTime = loginUser.getExpireTime();\n        long currentTime = System.currentTimeMillis();\n        if (expireTime - currentTime <= MINUTES_10) {\n            String token = loginUser.getToken();\n            loginUser = (LoginUser) userDetailsService.loadUserByUsername(loginUser.getUsername());\n            loginUser.setToken(token);\n            tokenService.refresh(loginUser);\n        }\n        return loginUser;\n    }\n\n}\n"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/page/table/PageTableArgumentResolver.java",
    "content": "package com.open.capacity.security.page.table;\n\nimport com.google.common.collect.Maps;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.core.MethodParameter;\nimport org.springframework.util.CollectionUtils;\nimport org.springframework.web.bind.support.WebDataBinderFactory;\nimport org.springframework.web.context.request.NativeWebRequest;\nimport org.springframework.web.method.support.HandlerMethodArgumentResolver;\nimport org.springframework.web.method.support.ModelAndViewContainer;\n\nimport javax.servlet.http.HttpServletRequest;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * 分页、查询参数解析\n *\n * @author 624191343@qq.com\n */\npublic class PageTableArgumentResolver implements HandlerMethodArgumentResolver {\n\n    @Override\n    public boolean supportsParameter(MethodParameter parameter) {\n        Class<?> cla = parameter.getParameterType();\n\n        return cla.isAssignableFrom(PageTableRequest.class);\n    }\n\n    @Override\n    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,\n                                  NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {\n        HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);\n\n        PageTableRequest tableRequest = new PageTableRequest();\n        Map<String, String[]> param = request.getParameterMap();\n        if (param.containsKey(\"start\")) {\n            tableRequest.setOffset(Integer.parseInt(request.getParameter(\"start\")));\n        }\n\n        if (param.containsKey(\"length\")) {\n            tableRequest.setLimit(Integer.parseInt(request.getParameter(\"length\")));\n        }\n\n        Map<String, Object> map = Maps.newHashMap();\n        tableRequest.setParams(map);\n\n        param.forEach((k, v) -> {\n            if (v.length == 1) {\n                map.put(k, v[0]);\n            } else {\n                map.put(k, Arrays.asList(v));\n            }\n        });\n\n        setOrderBy(tableRequest, map);\n        removeParam(tableRequest);\n\n        return tableRequest;\n    }\n\n    /**\n     * 去除datatables分页带的一些复杂参数\n     *\n     * @param tableRequest\n     */\n    private void removeParam(PageTableRequest tableRequest) {\n        Map<String, Object> map = tableRequest.getParams();\n\n        if (!CollectionUtils.isEmpty(map)) {\n            Map<String, Object> param = new HashMap<>();\n            map.forEach((k, v) -> {\n                if (k.indexOf(\"[\") < 0 && k.indexOf(\"]\") < 0 && !\"_\".equals(k)) {\n                    param.put(k, v);\n                }\n            });\n\n            tableRequest.setParams(param);\n        }\n    }\n\n    /**\n     * 从datatables分页请求数据中解析排序\n     *\n     * @param tableRequest\n     * @param map\n     */\n    private void setOrderBy(PageTableRequest tableRequest, Map<String, Object> map) {\n        StringBuilder orderBy = new StringBuilder();\n        int size = map.size();\n        for (int i = 0; i < size; i++) {\n            String index = (String) map.get(\"order[\" + i + \"][column]\");\n            if (StringUtils.isEmpty(index)) {\n                break;\n            }\n            String column = (String) map.get(\"columns[\" + index + \"][data]\");\n            if (StringUtils.isBlank(column)) {\n                continue;\n            }\n            String sort = (String) map.get(\"order[\" + i + \"][dir]\");\n\n            orderBy.append(column).append(\" \").append(sort).append(\", \");\n        }\n\n        if (orderBy.length() > 0) {\n            tableRequest.getParams().put(\"orderBy\",\n                    \" order by \" + StringUtils.substringBeforeLast(orderBy.toString(), \",\"));\n        }\n    }\n\n}\n"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/page/table/PageTableHandler.java",
    "content": "package com.open.capacity.security.page.table;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * 分页查询处理器\n *\n * @author 624191343@qq.com\n */\n\npublic class PageTableHandler {\n\n    private CountHandler countHandler;\n    private ListHandler listHandler;\n    private OrderHandler orderHandler;\n\n    public PageTableHandler(CountHandler countHandler, ListHandler listHandler) {\n        super();\n        this.countHandler = countHandler;\n        this.listHandler = listHandler;\n    }\n\n    public PageTableHandler(CountHandler countHandler, ListHandler listHandler, OrderHandler orderHandler) {\n        this(countHandler, listHandler);\n        this.orderHandler = orderHandler;\n    }\n\n    public PageTableResponse handle(PageTableRequest dtRequest) {\n        int count = 0;\n        List<?> list = null;\n\n        count = this.countHandler.count(dtRequest);\n        if (count > 0) {\n            if (orderHandler != null) {\n                dtRequest = orderHandler.order(dtRequest);\n            }\n            list = this.listHandler.list(dtRequest);\n        }\n\n        if (list == null) {\n            list = new ArrayList<>();\n        }\n\n        return new PageTableResponse(count, count, list);\n    }\n\n    public interface ListHandler {\n        List<?> list(PageTableRequest request);\n    }\n\n    public interface CountHandler {\n        int count(PageTableRequest request);\n    }\n\n    public interface OrderHandler {\n        PageTableRequest order(PageTableRequest request);\n    }\n}"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/page/table/PageTableRequest.java",
    "content": "package com.open.capacity.security.page.table;\n\nimport java.io.Serializable;\nimport java.util.Map;\n\n/**\n * 分页查询参数\n *\n * @author 624191343@qq.com\n */\npublic class PageTableRequest implements Serializable {\n\n    private static final long serialVersionUID = 7328071045193618467L;\n\n    private Integer offset;\n    private Integer limit;\n    private Map<String, Object> params;\n\n    public Integer getOffset() {\n        return offset;\n    }\n\n    public void setOffset(Integer offset) {\n        this.offset = offset;\n    }\n\n    public Integer getLimit() {\n        return limit;\n    }\n\n    public void setLimit(Integer limit) {\n        this.limit = limit;\n    }\n\n    public Map<String, Object> getParams() {\n        return params;\n    }\n\n    public void setParams(Map<String, Object> params) {\n        this.params = params;\n    }\n}\n"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/page/table/PageTableResponse.java",
    "content": "package com.open.capacity.security.page.table;\n\nimport java.io.Serializable;\nimport java.util.List;\n\n/**\n * 分页查询返回\n *\n * @author 624191343@qq.com\n */\npublic class PageTableResponse implements Serializable {\n\n    private static final long serialVersionUID = 620421858510718076L;\n\n    private Integer recordsTotal;\n    private Integer recordsFiltered;\n    private List<?> data;\n\n    public PageTableResponse(Integer recordsTotal, Integer recordsFiltered, List<?> data) {\n        super();\n        this.recordsTotal = recordsTotal;\n        this.recordsFiltered = recordsFiltered;\n        this.data = data;\n    }\n\n    public Integer getRecordsTotal() {\n        return recordsTotal;\n    }\n\n    public void setRecordsTotal(Integer recordsTotal) {\n        this.recordsTotal = recordsTotal;\n    }\n\n    public Integer getRecordsFiltered() {\n        return recordsFiltered;\n    }\n\n    public void setRecordsFiltered(Integer recordsFiltered) {\n        this.recordsFiltered = recordsFiltered;\n    }\n\n    public List<?> getData() {\n        return data;\n    }\n\n    public void setData(List<?> data) {\n        this.data = data;\n    }\n\n}"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/service/MicroServiceService.java",
    "content": "package com.open.capacity.security.service;\n\nimport com.open.capacity.security.model.Permission;\n\npublic interface MicroServiceService {\n\n    void save(Permission permission);\n\n    void update(Permission permission);\n\n    void delete(Long id);\n}\n"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/service/PermissionService.java",
    "content": "package com.open.capacity.security.service;\n\nimport com.open.capacity.security.model.Permission;\n\npublic interface PermissionService {\n\n    void save(Permission permission);\n\n    void update(Permission permission);\n\n    void delete(Long id);\n}\n"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/service/RoleService.java",
    "content": "package com.open.capacity.security.service;\n\nimport com.open.capacity.security.dto.RoleDto;\n\npublic interface RoleService {\n\n    void saveRole(RoleDto roleDto);\n\n    void deleteRole(Long id);\n}\n"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/service/SysLogService.java",
    "content": "package com.open.capacity.security.service;\n\nimport com.open.capacity.security.model.SysLogs;\n\n/**\n * 日志service\n *\n * @author 624191343@qq.com\n * <p>\n * 2017年8月19日\n */\npublic interface SysLogService {\n\n    void save(SysLogs sysLogs);\n\n    void save(Long userId, String module, Boolean flag, String remark);\n\n    void deleteLogs();\n}\n"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/service/TokenService.java",
    "content": "package com.open.capacity.security.service;\n\nimport com.open.capacity.security.dto.LoginUser;\nimport com.open.capacity.security.dto.Token;\n\n/**\n * Token管理器<br>\n * 可存储到redis或者数据库<br>\n * 具体可看实现类<br>\n * 默认基于redis，实现类为 com.boot.security.server.service.impl.TokenServiceJWTImpl<br>\n * 如要换成数据库存储，将TokenServiceImpl类上的注解@Primary挪到com.boot.security.server.service.impl.TokenServiceDbImpl\n *\n * @author 624191343@qq.com\n * <p>\n * 2017年10月14日\n */\npublic interface TokenService {\n\n    Token saveToken(LoginUser loginUser);\n\n    void refresh(LoginUser loginUser);\n\n    LoginUser getLoginUser(String token);\n\n    boolean deleteToken(String token);\n\n}\n"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/service/UserService.java",
    "content": "package com.open.capacity.security.service;\n\nimport com.open.capacity.security.dto.UserDto;\nimport com.open.capacity.security.model.SysUser;\n\npublic interface UserService {\n\n    SysUser saveUser(UserDto userDto);\n\n    SysUser updateUser(UserDto userDto);\n\n    SysUser getUser(String username);\n\n    void changePassword(String username, String oldPassword, String newPassword);\n\n}\n"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/service/impl/PermissionServiceImpl.java",
    "content": "package com.open.capacity.security.service.impl;\n\nimport com.open.capacity.security.dao.PermissionDao;\nimport com.open.capacity.security.model.Permission;\nimport com.open.capacity.security.service.PermissionService;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\n@Service\npublic class PermissionServiceImpl implements PermissionService {\n\n    private static final Logger log = LoggerFactory.getLogger(PermissionServiceImpl.class);\n\n    @Autowired\n    private PermissionDao permissionDao;\n\n    @Override\n    public void save(Permission permission) {\n        permissionDao.save(permission);\n\n        log.debug(\"新增菜单{}\", permission.getName());\n    }\n\n    @Override\n    public void update(Permission permission) {\n        permissionDao.update(permission);\n    }\n\n    @Override\n    @Transactional\n    public void delete(Long id) {\n        permissionDao.deleteRolePermission(id);\n        permissionDao.delete(id);\n        permissionDao.deleteByParentId(id);\n\n        log.debug(\"删除菜单id:{}\", id);\n    }\n\n}\n"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/service/impl/RoleServiceImpl.java",
    "content": "package com.open.capacity.security.service.impl;\n\nimport com.open.capacity.security.dao.RoleDao;\nimport com.open.capacity.security.dto.RoleDto;\nimport com.open.capacity.security.model.Role;\nimport com.open.capacity.security.service.RoleService;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\nimport org.springframework.util.CollectionUtils;\n\nimport java.util.List;\n\n@Service\npublic class RoleServiceImpl implements RoleService {\n\n    private static final Logger log = LoggerFactory.getLogger(RoleServiceImpl.class);\n\n    @Autowired\n    private RoleDao roleDao;\n\n    @Override\n    @Transactional\n    public void saveRole(RoleDto roleDto) {\n        Role role = roleDto;\n        List<Long> permissionIds = roleDto.getPermissionIds();\n        permissionIds.remove(0L);\n\n        if (role.getId() != null) {// 修改\n            updateRole(role, permissionIds);\n        } else {// 新增\n            saveRole(role, permissionIds);\n        }\n    }\n\n    private void saveRole(Role role, List<Long> permissionIds) {\n        Role r = roleDao.getRole(role.getName());\n        if (r != null) {\n            throw new IllegalArgumentException(role.getName() + \"已存在\");\n        }\n\n        roleDao.save(role);\n        if (!CollectionUtils.isEmpty(permissionIds)) {\n            roleDao.saveRolePermission(role.getId(), permissionIds);\n        }\n        log.debug(\"新增角色{}\", role.getName());\n    }\n\n    private void updateRole(Role role, List<Long> permissionIds) {\n        Role r = roleDao.getRole(role.getName());\n        if (r != null && r.getId() != role.getId()) {\n            throw new IllegalArgumentException(role.getName() + \"已存在\");\n        }\n\n        roleDao.update(role);\n\n        roleDao.deleteRolePermission(role.getId());\n        if (!CollectionUtils.isEmpty(permissionIds)) {\n            roleDao.saveRolePermission(role.getId(), permissionIds);\n        }\n        log.debug(\"修改角色{}\", role.getName());\n    }\n\n    @Override\n    @Transactional\n    public void deleteRole(Long id) {\n        roleDao.deleteRolePermission(id);\n        roleDao.deleteRoleUser(id);\n        roleDao.delete(id);\n\n        log.debug(\"删除角色id:{}\", id);\n    }\n\n}\n"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/service/impl/SysLogServiceImpl.java",
    "content": "package com.open.capacity.security.service.impl;\n\nimport com.open.capacity.security.dao.SysLogsDao;\nimport com.open.capacity.security.model.SysLogs;\nimport com.open.capacity.security.model.SysUser;\nimport com.open.capacity.security.service.SysLogService;\nimport com.open.capacity.security.utils.UserUtil;\nimport org.apache.commons.lang3.time.DateFormatUtils;\nimport org.apache.commons.lang3.time.DateUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.scheduling.annotation.Async;\nimport org.springframework.stereotype.Service;\n\nimport java.util.Date;\n\n@Service\npublic class SysLogServiceImpl implements SysLogService {\n\n    private static final Logger log = LoggerFactory.getLogger(SysLogServiceImpl.class);\n\n    @Autowired\n    private SysLogsDao sysLogsDao;\n\n    @Override\n    public void save(SysLogs sysLogs) {\n        SysUser user = UserUtil.getLoginUser();\n        if (user == null || user.getId() == null) {\n            return;\n        }\n\n        sysLogs.setUser(user);\n        sysLogsDao.save(sysLogs);\n    }\n\n    @Async\n    @Override\n    public void save(Long userId, String module, Boolean flag, String remark) {\n        SysLogs sysLogs = new SysLogs();\n        sysLogs.setFlag(flag);\n        sysLogs.setModule(module);\n        sysLogs.setRemark(remark);\n\n        SysUser user = new SysUser();\n        user.setId(userId);\n        sysLogs.setUser(user);\n\n        sysLogsDao.save(sysLogs);\n\n    }\n\n    @Override\n    public void deleteLogs() {\n        Date date = DateUtils.addMonths(new Date(), -3);\n        String time = DateFormatUtils.format(date, DateFormatUtils.ISO_8601_EXTENDED_DATE_FORMAT.getPattern());\n\n        int n = sysLogsDao.deleteLogs(time);\n        log.info(\"删除{}之前日志{}条\", time, n);\n    }\n}\n"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/service/impl/TokenServiceImpl.java",
    "content": "package com.open.capacity.security.service.impl;\n\nimport com.open.capacity.security.dto.LoginUser;\nimport com.open.capacity.security.dto.Token;\nimport com.open.capacity.security.service.SysLogService;\nimport com.open.capacity.security.service.TokenService;\nimport io.jsonwebtoken.ExpiredJwtException;\nimport io.jsonwebtoken.Jwts;\nimport io.jsonwebtoken.SignatureAlgorithm;\nimport org.apache.commons.collections4.MapUtils;\nimport org.apache.commons.lang3.StringUtils;\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.context.annotation.Primary;\nimport org.springframework.data.redis.core.RedisTemplate;\nimport org.springframework.stereotype.Service;\n\nimport javax.crypto.spec.SecretKeySpec;\nimport javax.xml.bind.DatatypeConverter;\nimport java.security.Key;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.UUID;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * token存到redis的实现类<br>\n * jwt实现的token\n *\n * @author owen 624191343@qq.com\n */\n@Primary\n@Service\npublic class TokenServiceImpl implements TokenService {\n\n    private static final Logger log = LoggerFactory.getLogger(TokenServiceImpl.class);\n    private static final String LOGIN_USER_KEY = \"LOGIN_USER_KEY\";\n    private static Key KEY = null;\n    /**\n     * token过期秒数\n     */\n    @Value(\"${token.expire.seconds:7200}\")\n    private Integer expireSeconds;\n    @Autowired\n    private RedisTemplate<String, Object> redisTemplate;\n    @Autowired\n    private SysLogService logService;\n    /**\n     * 私钥\n     */\n    @Value(\"${token.jwtSecret:open-layui-web}\")\n    private String jwtSecret;\n\n    @Override\n    public Token saveToken(LoginUser loginUser) {\n        loginUser.setToken(UUID.randomUUID().toString());\n        String jwtToken = createJWTToken(loginUser);\n        loginUser.setJwtToken(jwtToken);\n        cacheLoginUser(loginUser);\n        // 登陆日志\n        logService.save(loginUser.getId(), \"登陆\", true, null);\n        return new Token(jwtToken, loginUser.getLoginTime());\n    }\n\n    /**\n     * 生成jwt\n     *\n     * @param loginUser\n     * @return\n     */\n    private String createJWTToken(LoginUser loginUser) {\n        Map<String, Object> claims = new HashMap<>();\n        claims.put(LOGIN_USER_KEY, loginUser.getToken());// 放入一个随机字符串，通过该串可找到登陆用户\n\n        String jwtToken = Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.HS256, getKeyInstance())\n                .compact();\n\n        return jwtToken;\n    }\n\n    private void cacheLoginUser(LoginUser loginUser) {\n        loginUser.setLoginTime(System.currentTimeMillis());\n        loginUser.setExpireTime(loginUser.getLoginTime() + expireSeconds * 1000);\n        // 根据uuid将loginUser缓存\n        redisTemplate.boundValueOps(getTokenKey(loginUser.getToken())).set(loginUser, expireSeconds, TimeUnit.SECONDS);\n    }\n\n    /**\n     * 更新缓存的用户信息\n     */\n    @Override\n    public void refresh(LoginUser loginUser) {\n        cacheLoginUser(loginUser);\n    }\n\n    @Override\n    public LoginUser getLoginUser(String jwtToken) {\n        String uuid = getUUIDFromJWT(jwtToken);\n        if (uuid != null) {\n            return (LoginUser) redisTemplate.boundValueOps(getTokenKey(uuid)).get();\n        }\n\n        return null;\n    }\n\n    @Override\n    public boolean deleteToken(String jwtToken) {\n        String uuid = getUUIDFromJWT(jwtToken);\n        if (uuid != null) {\n            String key = getTokenKey(uuid);\n            LoginUser loginUser = (LoginUser) redisTemplate.opsForValue().get(key);\n            if (loginUser != null) {\n                redisTemplate.delete(key);\n                // 退出日志\n                logService.save(loginUser.getId(), \"退出\", true, null);\n\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    private String getTokenKey(String uuid) {\n        return \"tokens:\" + uuid;\n    }\n\n    private Key getKeyInstance() {\n        if (KEY == null) {\n            synchronized (TokenServiceImpl.class) {\n                if (KEY == null) {// 双重锁\n                    byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(jwtSecret);\n                    KEY = new SecretKeySpec(apiKeySecretBytes, SignatureAlgorithm.HS256.getJcaName());\n                }\n            }\n        }\n\n        return KEY;\n    }\n\n    private String getUUIDFromJWT(String jwtToken) {\n        if (\"null\".equals(jwtToken) || StringUtils.isBlank(jwtToken)) {\n            return null;\n        }\n\n        Map<String, Object> jwtClaims = null;\n        try {\n            jwtClaims = Jwts.parser().setSigningKey(getKeyInstance()).parseClaimsJws(jwtToken).getBody();\n            return MapUtils.getString(jwtClaims, LOGIN_USER_KEY);\n        } catch (ExpiredJwtException e) {\n            log.error(\"{}已过期\", jwtToken);\n        } catch (Exception e) {\n            log.error(\"{}\", e);\n        }\n\n        return null;\n    }\n}\n"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/service/impl/UserDetailsServiceImpl.java",
    "content": "package com.open.capacity.security.service.impl;\n\nimport com.open.capacity.security.dao.PermissionDao;\nimport com.open.capacity.security.dto.LoginUser;\nimport com.open.capacity.security.model.Permission;\nimport com.open.capacity.security.model.SysUser;\nimport com.open.capacity.security.model.SysUser.Status;\nimport com.open.capacity.security.service.UserService;\nimport org.springframework.beans.BeanUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;\nimport org.springframework.security.authentication.DisabledException;\nimport org.springframework.security.authentication.LockedException;\nimport org.springframework.security.core.userdetails.UserDetails;\nimport org.springframework.security.core.userdetails.UserDetailsService;\nimport org.springframework.security.core.userdetails.UsernameNotFoundException;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\n\n/**\n * spring security登陆处理\n *\n * @author owen 624191343@qq.com\n */\n@Service\npublic class UserDetailsServiceImpl implements UserDetailsService {\n\n    @Autowired\n    private UserService userService;\n    @Autowired\n    private PermissionDao permissionDao;\n\n    @Override\n    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {\n        SysUser sysUser = userService.getUser(username);\n        if (sysUser == null) {\n            throw new AuthenticationCredentialsNotFoundException(\"用户名不存在\");\n        } else if (sysUser.getStatus() == Status.LOCKED) {\n            throw new LockedException(\"用户被锁定,请联系管理员\");\n        } else if (sysUser.getStatus() == Status.DISABLED) {\n            throw new DisabledException(\"用户已作废\");\n        }\n\n        LoginUser loginUser = new LoginUser();\n        BeanUtils.copyProperties(sysUser, loginUser);\n\n        List<Permission> permissions = permissionDao.listByUserId(sysUser.getId());\n        loginUser.setPermissions(permissions);\n\n        return loginUser;\n    }\n\n}\n"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/service/impl/UserServiceImpl.java",
    "content": "package com.open.capacity.security.service.impl;\n\nimport com.open.capacity.security.dao.UserDao;\nimport com.open.capacity.security.dto.UserDto;\nimport com.open.capacity.security.model.SysUser;\nimport com.open.capacity.security.model.SysUser.Status;\nimport com.open.capacity.security.service.UserService;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\nimport org.springframework.util.CollectionUtils;\n\nimport java.util.List;\n\n@Service\npublic class UserServiceImpl implements UserService {\n\n    private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class);\n\n    @Autowired\n    private UserDao userDao;\n    @Autowired\n    private BCryptPasswordEncoder passwordEncoder;\n\n    @Override\n    @Transactional\n    public SysUser saveUser(UserDto userDto) {\n        SysUser user = userDto;\n        user.setPassword(passwordEncoder.encode(user.getPassword()));\n        user.setStatus(Status.VALID);\n        userDao.save(user);\n        saveUserRoles(user.getId(), userDto.getRoleIds());\n\n        log.debug(\"新增用户{}\", user.getUsername());\n        return user;\n    }\n\n    private void saveUserRoles(Long userId, List<Long> roleIds) {\n        if (roleIds != null) {\n            userDao.deleteUserRole(userId);\n            if (!CollectionUtils.isEmpty(roleIds)) {\n                userDao.saveUserRoles(userId, roleIds);\n            }\n        }\n    }\n\n    @Override\n    public SysUser getUser(String username) {\n        return userDao.getUser(username);\n    }\n\n    @Override\n    public void changePassword(String username, String oldPassword, String newPassword) {\n        SysUser u = userDao.getUser(username);\n        if (u == null) {\n            throw new IllegalArgumentException(\"用户不存在\");\n        }\n\n        if (!passwordEncoder.matches(oldPassword, u.getPassword())) {\n            throw new IllegalArgumentException(\"旧密码错误\");\n        }\n\n        userDao.changePassword(u.getId(), passwordEncoder.encode(newPassword));\n\n        log.debug(\"修改{}的密码\", username);\n    }\n\n    @Override\n    @Transactional\n    public SysUser updateUser(UserDto userDto) {\n        userDao.update(userDto);\n        saveUserRoles(userDto.getId(), userDto.getRoleIds());\n\n        return userDto;\n    }\n\n}\n"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/utils/FileUtil.java",
    "content": "package com.open.capacity.security.utils;\n\nimport org.apache.commons.codec.digest.DigestUtils;\nimport org.springframework.web.multipart.MultipartFile;\n\nimport java.io.*;\nimport java.time.LocalDate;\n\n/**\n * 文件工具类\n *\n * @author 624191343@qq.com\n */\npublic class FileUtil {\n\n    public static String saveFile(MultipartFile file, String pathname) {\n        try {\n            File targetFile = new File(pathname);\n            if (targetFile.exists()) {\n                return pathname;\n            }\n\n            if (!targetFile.getParentFile().exists()) {\n                targetFile.getParentFile().mkdirs();\n            }\n            file.transferTo(targetFile);\n\n            return pathname;\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n\n        return null;\n    }\n\n    public static boolean deleteFile(String pathname) {\n        File file = new File(pathname);\n        if (file.exists()) {\n            boolean flag = file.delete();\n\n            if (flag) {\n                File[] files = file.getParentFile().listFiles();\n                if (files == null || files.length == 0) {\n                    file.getParentFile().delete();\n                }\n            }\n\n            return flag;\n        }\n\n        return false;\n    }\n\n    public static String fileMd5(InputStream inputStream) {\n        try {\n            return DigestUtils.md5Hex(inputStream);\n        } catch (IOException e) {\n            e.printStackTrace();\n        }\n\n        return null;\n    }\n\n    public static String getPath() {\n        return \"/\" + LocalDate.now().toString().replace(\"-\", \"/\") + \"/\";\n    }\n\n    /**\n     * 将文本写入文件\n     *\n     * @param value\n     * @param path\n     */\n    public static void saveTextFile(String value, String path) {\n        FileWriter writer = null;\n        try {\n            File file = new File(path);\n            if (!file.getParentFile().exists()) {\n                file.getParentFile().mkdirs();\n            }\n\n            writer = new FileWriter(file);\n            writer.write(value);\n            writer.flush();\n        } catch (IOException e) {\n            e.printStackTrace();\n        } finally {\n            try {\n                if (writer != null) {\n                    writer.close();\n                }\n            } catch (IOException e) {\n                e.printStackTrace();\n            }\n        }\n    }\n\n    public static String getText(String path) {\n        File file = new File(path);\n        if (!file.exists()) {\n            return null;\n        }\n\n        try {\n            return getText(new FileInputStream(file));\n        } catch (FileNotFoundException e) {\n            e.printStackTrace();\n        }\n\n        return null;\n    }\n\n    public static String getText(InputStream inputStream) {\n        InputStreamReader isr = null;\n        BufferedReader bufferedReader = null;\n        try {\n            isr = new InputStreamReader(inputStream, \"utf-8\");\n            bufferedReader = new BufferedReader(isr);\n            StringBuilder builder = new StringBuilder();\n            String string;\n            while ((string = bufferedReader.readLine()) != null) {\n                string = string + \"\\n\";\n                builder.append(string);\n            }\n\n            return builder.toString();\n        } catch (IOException e) {\n            e.printStackTrace();\n        } finally {\n            if (bufferedReader != null) {\n                try {\n                    bufferedReader.close();\n                } catch (IOException e) {\n                    e.printStackTrace();\n                }\n            }\n            if (isr != null) {\n                try {\n                    isr.close();\n                } catch (IOException e) {\n                    e.printStackTrace();\n                }\n            }\n        }\n\n        return null;\n    }\n}\n"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/utils/ResponseUtil.java",
    "content": "package com.open.capacity.security.utils;\n\nimport com.alibaba.fastjson.JSONObject;\n\nimport javax.servlet.http.HttpServletResponse;\nimport java.io.IOException;\n\npublic class ResponseUtil {\n\n    public static void responseJson(HttpServletResponse response, int status, Object data) {\n        try {\n            response.setHeader(\"Access-Control-Allow-Origin\", \"*\");\n            response.setHeader(\"Access-Control-Allow-Methods\", \"*\");\n            response.setContentType(\"application/json;charset=UTF-8\");\n            response.setStatus(status);\n\n            response.getWriter().write(JSONObject.toJSONString(data));\n        } catch (IOException e) {\n            e.printStackTrace();\n        }\n    }\n}\n"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/utils/SpringUtil.java",
    "content": "package com.open.capacity.security.utils;\n\nimport org.springframework.beans.BeansException;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.ApplicationContextAware;\nimport org.springframework.core.env.Environment;\nimport org.springframework.stereotype.Component;\n\n/**\n * spring获取bean工具类\n *\n * @author 作者 owen E-mail: 624191343@qq.com\n * @version 创建时间：2018年3月20日 下午10:13:18 类说明\n */\n@Component\npublic class SpringUtil implements ApplicationContextAware {\n\n    private static ApplicationContext applicationContext = null;\n\n    public static <T> T getBean(Class<T> cla) {\n        return applicationContext.getBean(cla);\n    }\n\n    public static <T> T getBean(String name, Class<T> cal) {\n        return applicationContext.getBean(name, cal);\n    }\n\n    public static String getProperty(String key) {\n        return applicationContext.getBean(Environment.class).getProperty(key);\n    }\n\n    @Override\n    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {\n        SpringUtil.applicationContext = applicationContext;\n    }\n}\n"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/utils/StrUtil.java",
    "content": "package com.open.capacity.security.utils;\n\nimport com.google.common.collect.Lists;\n\nimport java.util.List;\n\n/**\n * 字符串转化工具类\n *\n * @author 624191343@qq.com\n */\npublic class StrUtil {\n\n    /**\n     * 字符串转为驼峰\n     *\n     * @param str\n     * @return\n     */\n    public static String str2hump(String str) {\n        StringBuffer buffer = new StringBuffer();\n        if (str != null && str.length() > 0) {\n            if (str.contains(\"_\")) {\n                String[] chars = str.split(\"_\");\n                int size = chars.length;\n                if (size > 0) {\n                    List<String> list = Lists.newArrayList();\n                    for (String s : chars) {\n                        if (s != null && s.trim().length() > 0) {\n                            list.add(s);\n                        }\n                    }\n\n                    size = list.size();\n                    if (size > 0) {\n                        buffer.append(list.get(0));\n                        for (int i = 1; i < size; i++) {\n                            String s = list.get(i);\n                            buffer.append(s.substring(0, 1).toUpperCase());\n                            if (s.length() > 1) {\n                                buffer.append(s.substring(1));\n                            }\n                        }\n                    }\n                }\n            } else {\n                buffer.append(str);\n            }\n        }\n\n        return buffer.toString();\n    }\n\n}\n"
  },
  {
    "path": "open-user-center/src/main/java/com/open/capacity/security/utils/UserUtil.java",
    "content": "package com.open.capacity.security.utils;\n\nimport com.open.capacity.security.dto.LoginUser;\nimport org.springframework.security.authentication.AnonymousAuthenticationToken;\nimport org.springframework.security.authentication.UsernamePasswordAuthenticationToken;\nimport org.springframework.security.core.Authentication;\nimport org.springframework.security.core.context.SecurityContextHolder;\n\npublic class UserUtil {\n\n    public static LoginUser getLoginUser() {\n        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();\n        if (authentication != null) {\n            if (authentication instanceof AnonymousAuthenticationToken) {\n                return null;\n            }\n\n            if (authentication instanceof UsernamePasswordAuthenticationToken) {\n                return (LoginUser) authentication.getPrincipal();\n            }\n        }\n\n        return null;\n    }\n\n}\n"
  },
  {
    "path": "open-user-center/src/main/resources/application.yml",
    "content": "server:\n  port: 9700\nspring:\n  application:\n    name: open-user-center\n  session:\n    store-type: redis  \n  datasource:\n      type: com.alibaba.druid.pool.DruidDataSource\n#      driver-class-name:  oracle.jdbc.OracleDriver\n#      url: jdbc:oracle:thin:@127.0.0.1:1521:orcl\n#      username: crm_owner_user\n#      password: bss_crm_test\n#      filters: stat,wall\n################## mysql start ############################\n      driver-class-name:  com.mysql.jdbc.Driver\n      #     192.168.3.150   130.75.131.211   134.224.249.39 47.94.252.160\n      url: jdbc:mysql://134.224.249.39:3306/boot_security?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false\n      username: root\n      password: root\n      filters: stat,wall\n################### mysq end l##########################\n  redis:\n################### redis 单机版 start ########################## \n    host: 127.0.0.1\n    port: 6379    \n    timeout: 3000\n    database: 1\n################### redis 单机版 end ##########################   \n#    cluster:\n#      nodes: 130.75.131.237:7000,130.75.131.238:7000,130.75.131.239:7000,130.75.131.237:7001,130.75.131.238:7001,130.75.131.239:7001\n###        #130.75.131.237:7000,130.75.131.238:7000,130.75.131.239:7000,130.75.131.237:7001,130.75.131.238:7001,130.75.131.239:7001\n##        #192.168.3.157:7000,192.168.3.158:7000,192.168.3.159:7000,192.168.3.157:7001,192.168.3.158:7001,192.168.3.159:7001\n#    timeout: 1000 # 连接超时时间（毫秒）\n#    pool:\n#      max-active: 10  # 连接池最大连接数（使用负值表示没有限制）\n#      max-idle: 8     # 连接池中的最大空闲连接\n#      min-idle: 2     # 连接池中的最小空闲连接\n#      max-wait: 100   # 连接池最大阻塞等待时间（使用负值表示没有限制）       \n    \n    \n\nmybatis:\n  config-location: classpath:mybatis.cfg.xml\n  mapper-locations: classpath*:com/open/**/dao/*.xml  \n\n\nsecurity:\n  oauth2:\n    resource:\n      filter-order: 3\n    token:\n      store:\n        type: redis\n\n \n\neureka:\n  client:\n    healthcheck:\n      enabled: true\n    serviceUrl:\n      defaultZone:  http://127.0.0.1:1111/eureka  #http://130.75.131.241:8761/eureka,http://130.75.131.248:8762/eureka\n      #http://134.224.249.33:1111/eureka/  正式库\n      #http://134.224.249.33:1111/eureka/  测试库\n      #http://127.0.0.1:8761/eureka,http://127.0.0.1:8762/eureka\n  instance:\n    prefer-ip-address: true\n    instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}\n    #instance-id: ${spring.application.name}:${docker.ipAddress}:${spring.application.instance_id:${server.port}}\n    lease-renewal-interval-in-seconds: 5  #每隔几秒告诉eureka服务器我还存活，用于心跳检测\n    lease-expiration-duration-in-seconds: 10 #如果心跳检测一直没有发送，10秒后会从eureka服务器中将此服务剔除\n    #注册实例文档\n    status-page-url: http://${spring.cloud.client.ipAddress}:${server.port}/auth/doc.html # ${server.port}为该服务的端口号\n#    status-page-url: http://${docker.ipAddress}:${server.port}/auth/doc.html # ${server.port}为该服务的端口号\nlogging:\n  level:\n    root: INFO\n    org.hibernate: INFO\n    org.hibernate.type.descriptor.sql.BasicBinder: TRACE\n    org.hibernate.type.descriptor.sql.BasicExtractor: TRACE\n#    com.neusoft: DEBUG     \n#    com.netflix: DEBUG                    #用于心跳检测输出的日志\n    \n\n\n\n\n  \n "
  },
  {
    "path": "open-xxl-job/README.md",
    "content": "<p align=\"center\">\n    <img src=\"https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/xxl-logo.jpg\" width=\"150\">\n    <h3 align=\"center\">XXL-JOB</h3>\n    <p align=\"center\">\n        XXL-JOB, a lightweight distributed task scheduling framework.\n        <br>\n        <a href=\"http://www.xuxueli.com/xxl-job/\"><strong>-- Home Page --</strong></a>\n        <br>\n        <br>\n        <a href=\"https://travis-ci.org/xuxueli/xxl-job\">\n            <img src=\"https://travis-ci.org/xuxueli/xxl-job.svg?branch=master\" >\n        </a>\n        <a href=\"https://maven-badges.herokuapp.com/maven-central/com.xuxueli/xxl-job/\">\n            <img src=\"https://maven-badges.herokuapp.com/maven-central/com.xuxueli/xxl-job/badge.svg\" >\n        </a>\n         <a href=\"https://github.com/xuxueli/xxl-job/releases\">\n             <img src=\"https://img.shields.io/github/release/xuxueli/xxl-job.svg\" >\n         </a>\n         <a href=\"http://www.gnu.org/licenses/gpl-3.0.html\">\n             <img src=\"https://img.shields.io/badge/license-GPLv3-blue.svg\" >\n         </a>\n         <a href=\"https://gitter.im/xuxueli/xxl-job?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge\">\n              <img src=\"https://badges.gitter.im/xuxueli/xxl-job.svg\" >\n         </a>\n         <a href=\"http://www.xuxueli.com/page/donate.html\">\n               <img src=\"https://img.shields.io/badge/%24-donate-ff69b4.svg?style=flat-square\" >\n         </a>\n    </p>    \n</p>\n\n\n## Introduction\nXXL-JOB is a lightweight distributed task scheduling framework. \nIt's core design goal is to develop quickly and learn simple, lightweight, and easy to expand. \nNow, it's already open source, and many companies use it in production environments, real \"out-of-the-box\".\n\nXXL-JOB是一个轻量级分布式任务调度框架，其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线，开箱即用。\n\n\n## Documentation\n- [中文文档](http://www.xuxueli.com/xxl-job/)\n- [English Documentation](http://www.xuxueli.com/xxl-job/en/)\n\n\n## Features\n- 1、简单：支持通过Web页面对任务进行CRUD操作，操作简单，一分钟上手；\n- 2、动态：支持动态修改任务状态、暂停/恢复任务，以及终止运行中任务，即时生效；\n- 3、调度中心HA（中心式）：调度采用中心式设计，“调度中心”基于集群Quartz实现并支持集群部署，可保证调度中心HA；\n- 4、执行器HA（分布式）：任务分布式执行，任务\"执行器\"支持集群部署，可保证任务执行HA；\n- 5、注册中心: 执行器会周期性自动注册任务, 调度中心将会自动发现注册的任务并触发执行。同时，也支持手动录入执行器地址；\n- 6、弹性扩容缩容：一旦有新执行器机器上线或者下线，下次调度时将会重新分配任务；\n- 7、路由策略：执行器集群部署时提供丰富的路由策略，包括：第一个、最后一个、轮询、随机、一致性HASH、最不经常使用、最近最久未使用、故障转移、忙碌转移等；\n- 8、故障转移：任务路由策略选择\"故障转移\"情况下，如果执行器集群中某一台机器故障，将会自动Failover切换到一台正常的执行器发送调度请求。\n- 9、失败处理策略；调度失败时的处理策略，策略包括：失败告警（默认）、失败重试；\n- 10、失败重试：调度中心调度失败且启用\"失败重试\"策略时，将会自动重试一次；执行器执行失败且回调失败重试状态时，也将会自动重试一次；\n- 11、阻塞处理策略：调度过于密集执行器来不及处理时的处理策略，策略包括：单机串行（默认）、丢弃后续调度、覆盖之前调度；\n- 12、分片广播任务：执行器集群部署时，任务路由策略选择\"分片广播\"情况下，一次任务调度将会广播触发集群中所有执行器执行一次任务，可根据分片参数开发分片任务；\n- 13、动态分片：分片广播任务以执行器为维度进行分片，支持动态扩容执行器集群从而动态增加分片数量，协同进行业务处理；在进行大数据量业务操作时可显著提升任务处理能力和速度。\n- 14、事件触发：除了\"Cron方式\"和\"任务依赖方式\"触发任务执行之外，支持基于事件的触发任务方式。调度中心提供触发任务单次执行的API服务，可根据业务事件灵活触发。\n- 15、任务进度监控：支持实时监控任务进度；\n- 16、Rolling实时日志：支持在线查看调度结果，并且支持以Rolling方式实时查看执行器输出的完整的执行日志；\n- 17、GLUE：提供Web IDE，支持在线开发任务逻辑代码，动态发布，实时编译生效，省略部署上线的过程。支持30个版本的历史版本回溯。\n- 18、脚本任务：支持以GLUE模式开发和运行脚本任务，包括Shell、Python、NodeJS等类型脚本;\n- 19、任务依赖：支持配置子任务依赖，当父任务执行结束且执行成功后将会主动触发一次子任务的执行, 多个子任务用逗号分隔；\n- 20、一致性：“调度中心”通过DB锁保证集群分布式调度的一致性, 一次任务调度只会触发一次执行；\n- 21、自定义任务参数：支持在线配置调度任务入参，即时生效；\n- 22、调度线程池：调度系统多线程触发调度运行，确保调度精确执行，不被堵塞；\n- 23、数据加密：调度中心和执行器之间的通讯进行数据加密，提升调度信息安全性；\n- 24、邮件报警：任务失败时支持邮件报警，支持配置多邮件地址群发报警邮件；\n- 25、推送maven中央仓库: 将会把最新稳定版推送到maven中央仓库, 方便用户接入和使用;\n- 26、运行报表：支持实时查看运行数据，如任务数量、调度次数、执行器数量等；以及调度报表，如调度日期分布图，调度成功分布图等；\n- 27、全异步：系统底层实现全部异步化，针对密集调度进行流量削峰，理论上支持任意时长任务的运行；\n- 28、国际化：调度中心支持国际化设置，提供中文、英文两种可选语言，默认为中文；\n\n## Development\n于2015年中，我在github上创建XXL-JOB项目仓库并提交第一个commit，随之进行系统结构设计，UI选型，交互设计……\n\n于2015-11月，XXL-JOB终于RELEASE了第一个大版本V1.0， 随后我将之发布到OSCHINA，XXL-JOB在OSCHINA上获得了@红薯的热门推荐，同期分别达到了OSCHINA的“热门动弹”排行第一和git.oschina的开源软件月热度排行第一，在此特别感谢红薯，感谢大家的关注和支持。\n\n于2015-12月，我将XXL-JOB发表到我司内部知识库，并且得到内部同事认可。\n\n于2016-01月，我司展开XXL-JOB的内部接入和定制工作，在此感谢袁某和尹某两位同事的贡献，同时也感谢内部其他给与关注与支持的同事。\n\n于2017-05-13，在上海举办的 \"[第62期开源中国源创会](https://www.oschina.net/event/2236961)\" 的 \"放码过来\" 环节，我登台对XXL-JOB做了演讲，台下五百位在场观众反响热烈（[图文回顾](https://www.oschina.net/question/2686220_2242120) ）。\n\n于2017-12-11，XXL-JOB有幸参会《[InfoQ ArchSummit全球架构师峰会](http://bj2017.archsummit.com/)》，并被拍拍贷架构总监\"杨波老师\"在专题 \"[微服务原理、基础架构和开源实践](http://bj2017.archsummit.com/training/2)\" 中现场介绍。\n\n> 我司大众点评目前已接入XXL-JOB，内部别名《Ferrari》（Ferrari基于XXL-JOB的V1.1版本定制而成，新接入应用推荐升级最新版本）。**\n据最新统计, 自2016-01-21接入至2017-12-01期间，该系统已调度约100万次，表现优异。新接入应用推荐使用最新版本，因为经过数个大版本的更新，系统的任务模型、UI交互模型以及底层调度通讯模型都有了较大的优化和提升，核心功能更加稳定高效。\n\n至今，XXL-JOB已接入多家公司的线上产品线，接入场景如电商业务，O2O业务和大数据作业等，截止2016-07-19为止，XXL-JOB已接入的公司包括不限于：\n    \n\t- 1、大众点评；\n\t- 2、山东学而网络科技有限公司；\n\t- 3、安徽慧通互联科技有限公司；\n\t- 4、人人聚财金服；\n\t- 5、上海棠棣信息科技股份有限公司\n\t- 6、运满满\n\t- 7、米其林 (中国区)\n\t- 8、妈妈联盟\n\t- 9、九樱天下（北京）信息技术有限公司\n\t- 10、万普拉斯科技有限公司(一加手机)\n\t- 11、上海亿保健康管理有限公司\n\t- 12、海尔馨厨 (海尔)\n\t- 13、河南大红包电子商务有限公司\n\t- 14、成都顺点科技有限公司\n\t- 15、深圳市怡亚通\n\t- 16、深圳麦亚信科技股份有限公司\n\t- 17、上海博莹科技信息技术有限公司\n\t- 18、中国平安科技有限公司\n\t- 19、杭州知时信息科技有限公司\n\t- 20、博莹科技（上海）有限公司\n\t- 21、成都依能股份有限责任公司\n\t- 22、湖南高阳通联信息技术有限公司\n\t- 23、深圳市邦德文化发展有限公司\n\t- 24、福建阿思可网络教育有限公司\n\t- 25、优信二手车\n\t- 26、上海悠游堂投资发展股份有限公司\n\t- 27、北京粉笔蓝天科技有限公司\n\t- 28、中秀科技(无锡)有限公司\n\t- 29、武汉空心科技有限公司\n\t- 30、北京蚂蚁风暴科技有限公司\n\t- 31、四川互宜达科技有限公司\n    - 32、钱包行云（北京）科技有限公司\n    - 33、重庆欣才集团\n    - 34、咪咕互动娱乐有限公司（中国移动）\n    - 35、北京诺亦腾科技有限公司\n    - 36、增长引擎(北京)信息技术有限公司\n    - 37、北京英贝思科技有限公司\n    - 38、刚泰集团\n    - 39、深圳泰久信息系统股份有限公司\n    - 40、随行付支付有限公司\n    - 41、广州瀚农网络科技有限公司\n    - 42、享点科技有限公司\n    - 43、杭州比智科技有限公司\n    - 44、圳临界线网络科技有限公司\n    - 45、广州知识圈网络科技有限公司\n    - 46、国誉商业上海有限公司\n    - 47、海尔消费金融有限公司，嗨付、够花 (海尔)\n    - 48、广州巴图鲁信息科技有限公司\n    - 49、深圳市鹏海运电子数据交换有限公司\n    - 50、深圳市亚飞电子商务有限公司\n    - 51、上海趣医网络有限公司\n    - 52、聚金资本\n    - 53、北京父母邦网络科技有限公司\n    - 54、中山元赫软件科技有限公司\n    - 55、中商惠民(北京)电子商务有限公司\n    - 56、凯京集团\n    - 57、华夏票联（北京）科技有限公司\n    - 58、拍拍贷\n    - 59、北京尚德机构在线教育有限公司\n    - 60、任子行股份有限公司\n    - 61、北京时态电子商务有限公司\n    - 62、深圳卷皮网络科技有限公司\n    - 63、北京安博通科技股份有限公司\n    - 64、未来无线网\n    - 65、厦门瓷禧网络有限公司\n    - 66、北京递蓝科软件股份有限公司\n    - 67、郑州创海软件科技公司\n    - 68、北京国槐信息科技有限公司\n    - 69、浪潮软件集团\n    - 70、多立恒(北京)信息技术有限公司\n    - 71、广州极迅客信息科技有限公司\n    - 72、赫基（中国）集团股份有限公司\n    - 73、海投汇\n\t- ……\n\n> 更多接入的公司，欢迎在 [登记地址](https://github.com/xuxueli/xxl-job/issues/1 ) 登记，登记仅仅为了产品推广。\n\n欢迎大家的关注和使用，XXL-JOB也将拥抱变化，持续发展。\n\n\n## Communication\n\n- [社区交流](http://www.xuxueli.com/page/community.html)\n- [Gitter](https://gitter.im/xuxueli/xxl-job)\n\n\n## Contributing\nContributions are welcome! Open a pull request to fix a bug, or open an [Issue](https://github.com/xuxueli/xxl-job/issues/) to discuss a new feature or change.\n\n欢迎参与项目贡献！比如提交PR修复一个bug，或者新建 [Issue](https://github.com/xuxueli/xxl-job/issues/) 讨论新特性或者变更。\n\n\n## Copyright and License\nThis product is open source and free, and will continue to provide free community technical support. Individual or enterprise users are free to access and use.\n\n- Licensed under the GNU General Public License (GPL) v3.\n- Copyright (c) 2015-present, xuxueli.\n\n产品开源免费，并且将持续提供免费的社区技术支持。个人或企业内部可自由的接入和使用。\n\n\n## Donate\nNo matter how much the donation amount is enough to express your thought, thank you very much ：）     [To donate](http://www.xuxueli.com/page/donate.html )\n\n无论捐赠金额多少都足够表达您这份心意，非常感谢 ：）      [前往捐赠](http://www.xuxueli.com/page/donate.html )\n"
  },
  {
    "path": "open-xxl-job/db/tables_xxl_job.sql",
    "content": "CREATE database if NOT EXISTS `iyydb_job` default character set utf8 collate utf8_general_ci;\nuse `iyydb_job`;\n\n \n\n\nSET FOREIGN_KEY_CHECKS=0;\n\n\n\n#\n# Structure for table \"XXL_JOB_QRTZ_CALENDARS\"\n#\n\nCREATE TABLE `XXL_JOB_QRTZ_CALENDARS` (\n  `SCHED_NAME` varchar(120) NOT NULL,\n  `CALENDAR_NAME` varchar(200) NOT NULL,\n  `CALENDAR` blob NOT NULL,\n  PRIMARY KEY (`SCHED_NAME`,`CALENDAR_NAME`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\n#\n# Data for table \"XXL_JOB_QRTZ_CALENDARS\"\n#\n\n\n#\n# Structure for table \"XXL_JOB_QRTZ_FIRED_TRIGGERS\"\n#\n\nCREATE TABLE `XXL_JOB_QRTZ_FIRED_TRIGGERS` (\n  `SCHED_NAME` varchar(120) NOT NULL,\n  `ENTRY_ID` varchar(95) NOT NULL,\n  `TRIGGER_NAME` varchar(200) NOT NULL,\n  `TRIGGER_GROUP` varchar(200) NOT NULL,\n  `INSTANCE_NAME` varchar(200) NOT NULL,\n  `FIRED_TIME` bigint(13) NOT NULL,\n  `SCHED_TIME` bigint(13) NOT NULL,\n  `PRIORITY` int(11) NOT NULL,\n  `STATE` varchar(16) NOT NULL,\n  `JOB_NAME` varchar(200) DEFAULT NULL,\n  `JOB_GROUP` varchar(200) DEFAULT NULL,\n  `IS_NONCONCURRENT` varchar(1) DEFAULT NULL,\n  `REQUESTS_RECOVERY` varchar(1) DEFAULT NULL,\n  PRIMARY KEY (`SCHED_NAME`,`ENTRY_ID`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\n#\n# Data for table \"XXL_JOB_QRTZ_FIRED_TRIGGERS\"\n#\n\nINSERT INTO `XXL_JOB_QRTZ_FIRED_TRIGGERS` VALUES ('schedulerFactoryBean','owen15263060811091526306081114','5','1','owen1526306081109',1526306155083,1526306160000,5,'ACQUIRED',NULL,NULL,'0','0');\n\n#\n# Structure for table \"XXL_JOB_QRTZ_JOB_DETAILS\"\n#\n\nCREATE TABLE `XXL_JOB_QRTZ_JOB_DETAILS` (\n  `SCHED_NAME` varchar(120) NOT NULL,\n  `JOB_NAME` varchar(200) NOT NULL,\n  `JOB_GROUP` varchar(200) NOT NULL,\n  `DESCRIPTION` varchar(250) DEFAULT NULL,\n  `JOB_CLASS_NAME` varchar(250) NOT NULL,\n  `IS_DURABLE` varchar(1) NOT NULL,\n  `IS_NONCONCURRENT` varchar(1) NOT NULL,\n  `IS_UPDATE_DATA` varchar(1) NOT NULL,\n  `REQUESTS_RECOVERY` varchar(1) NOT NULL,\n  `JOB_DATA` blob,\n  PRIMARY KEY (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\n#\n# Data for table \"XXL_JOB_QRTZ_JOB_DETAILS\"\n#\n\nINSERT INTO `XXL_JOB_QRTZ_JOB_DETAILS` VALUES ('quartzScheduler','3','1',NULL,'com.open.capacity.core.jobbean.RemoteHttpJobBean','0','0','0','0',X'ACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787000737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F40000000000010770800000010000000007800'),('quartzScheduler','4','1',NULL,'com.open.capacity.core.jobbean.RemoteHttpJobBean','0','0','0','0',X'ACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787000737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F40000000000010770800000010000000007800'),('schedulerFactoryBean','5','1',NULL,'com.xxl.job.admin.core.jobbean.RemoteHttpJobBean','0','0','0','0',X'ACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787000737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F40000000000010770800000010000000007800'),('schedulerFactoryBean','6','1',NULL,'com.xxl.job.admin.core.jobbean.RemoteHttpJobBean','0','0','0','0',X'ACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787000737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F40000000000010770800000010000000007800');\n\n#\n# Structure for table \"XXL_JOB_QRTZ_LOCKS\"\n#\n\nCREATE TABLE `XXL_JOB_QRTZ_LOCKS` (\n  `SCHED_NAME` varchar(120) NOT NULL,\n  `LOCK_NAME` varchar(40) NOT NULL,\n  PRIMARY KEY (`SCHED_NAME`,`LOCK_NAME`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\n#\n# Data for table \"XXL_JOB_QRTZ_LOCKS\"\n#\n\nINSERT INTO `XXL_JOB_QRTZ_LOCKS` VALUES ('quartzScheduler','STATE_ACCESS'),('quartzScheduler','TRIGGER_ACCESS'),('schedulerFactoryBean','STATE_ACCESS'),('schedulerFactoryBean','TRIGGER_ACCESS');\n\n#\n# Structure for table \"XXL_JOB_QRTZ_PAUSED_TRIGGER_GRPS\"\n#\n\nCREATE TABLE `XXL_JOB_QRTZ_PAUSED_TRIGGER_GRPS` (\n  `SCHED_NAME` varchar(120) NOT NULL,\n  `TRIGGER_GROUP` varchar(200) NOT NULL,\n  PRIMARY KEY (`SCHED_NAME`,`TRIGGER_GROUP`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\n#\n# Data for table \"XXL_JOB_QRTZ_PAUSED_TRIGGER_GRPS\"\n#\n\n\n#\n# Structure for table \"XXL_JOB_QRTZ_SCHEDULER_STATE\"\n#\n\nCREATE TABLE `XXL_JOB_QRTZ_SCHEDULER_STATE` (\n  `SCHED_NAME` varchar(120) NOT NULL,\n  `INSTANCE_NAME` varchar(200) NOT NULL,\n  `LAST_CHECKIN_TIME` bigint(13) NOT NULL,\n  `CHECKIN_INTERVAL` bigint(13) NOT NULL,\n  PRIMARY KEY (`SCHED_NAME`,`INSTANCE_NAME`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\n#\n# Data for table \"XXL_JOB_QRTZ_SCHEDULER_STATE\"\n#\n\nINSERT INTO `XXL_JOB_QRTZ_SCHEDULER_STATE` VALUES ('quartzScheduler','USERCHI-E29PEDA1525876570951',1525876886761,5000),('schedulerFactoryBean','owen1526306081109',1526306155345,5000);\n\n#\n# Structure for table \"XXL_JOB_QRTZ_TRIGGER_GROUP\"\n#\n\nCREATE TABLE `XXL_JOB_QRTZ_TRIGGER_GROUP` (\n  `id` int(11) NOT NULL AUTO_INCREMENT,\n  `app_name` varchar(64) NOT NULL COMMENT '执行器AppName',\n  `title` varchar(12) NOT NULL COMMENT '执行器名称',\n  `order` tinyint(4) NOT NULL DEFAULT '0' COMMENT '排序',\n  `address_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '执行器地址类型：0=自动注册、1=手动录入',\n  `address_list` varchar(512) DEFAULT NULL COMMENT '执行器地址列表，多地址逗号分隔',\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;\n\n#\n# Data for table \"XXL_JOB_QRTZ_TRIGGER_GROUP\"\n#\n\nINSERT INTO `XXL_JOB_QRTZ_TRIGGER_GROUP` VALUES (1,'open-xxl-job-demo','示例执行器',1,0,NULL);\n\n#\n# Structure for table \"XXL_JOB_QRTZ_TRIGGER_INFO\"\n#\n\nCREATE TABLE `XXL_JOB_QRTZ_TRIGGER_INFO` (\n  `id` int(11) NOT NULL AUTO_INCREMENT,\n  `job_group` int(11) NOT NULL COMMENT '执行器主键ID',\n  `job_cron` varchar(128) NOT NULL COMMENT '任务执行CRON',\n  `job_desc` varchar(255) NOT NULL,\n  `add_time` datetime DEFAULT NULL,\n  `update_time` datetime DEFAULT NULL,\n  `author` varchar(64) DEFAULT NULL COMMENT '作者',\n  `alarm_email` varchar(255) DEFAULT NULL COMMENT '报警邮件',\n  `executor_route_strategy` varchar(50) DEFAULT NULL COMMENT '执行器路由策略',\n  `executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',\n  `executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数',\n  `executor_block_strategy` varchar(50) DEFAULT NULL COMMENT '阻塞处理策略',\n  `executor_fail_strategy` varchar(50) DEFAULT NULL COMMENT '失败处理策略',\n  `glue_type` varchar(50) NOT NULL COMMENT 'GLUE类型',\n  `glue_source` text COMMENT 'GLUE源代码',\n  `glue_remark` varchar(128) DEFAULT NULL COMMENT 'GLUE备注',\n  `glue_updatetime` datetime DEFAULT NULL COMMENT 'GLUE更新时间',\n  `child_jobid` varchar(255) DEFAULT NULL COMMENT '子任务ID，多个逗号分隔',\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;\n\n#\n# Data for table \"XXL_JOB_QRTZ_TRIGGER_INFO\"\n#\n\nINSERT INTO `XXL_JOB_QRTZ_TRIGGER_INFO` VALUES (5,1,'*/5 * * * * ?','有参任务','2018-05-12 06:30:38','2018-05-12 06:30:38','merlin','624191343@qq.com','FIRST','demoJobHandler','demoJobHandler','SERIAL_EXECUTION','FAIL_ALARM','BEAN','','GLUE代码初始化','2018-05-12 06:30:38',NULL),(6,1,'*/5 * * * * ?','无参任务','2018-05-12 06:32:16','2018-05-12 06:32:16','merlin','624191343@qq.com','FIRST','demoJobHandler','','SERIAL_EXECUTION','FAIL_ALARM','BEAN','','GLUE代码初始化','2018-05-12 06:32:16',NULL);\n\n#\n# Structure for table \"XXL_JOB_QRTZ_TRIGGER_LOG\"\n#\n\nCREATE TABLE `XXL_JOB_QRTZ_TRIGGER_LOG` (\n  `id` int(11) NOT NULL AUTO_INCREMENT,\n  `job_group` int(11) NOT NULL COMMENT '执行器主键ID',\n  `job_id` int(11) NOT NULL COMMENT '任务，主键ID',\n  `glue_type` varchar(50) DEFAULT NULL COMMENT 'GLUE类型',\n  `executor_address` varchar(255) DEFAULT NULL COMMENT '执行器地址，本次执行的地址',\n  `executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',\n  `executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数',\n  `trigger_time` datetime DEFAULT NULL COMMENT '调度-时间',\n  `trigger_code` int(11) NOT NULL COMMENT '调度-结果',\n  `trigger_msg` varchar(2048) DEFAULT NULL COMMENT '调度-日志',\n  `handle_time` datetime DEFAULT NULL COMMENT '执行-时间',\n  `handle_code` int(11) NOT NULL COMMENT '执行-状态',\n  `handle_msg` varchar(2048) DEFAULT NULL COMMENT '执行-日志',\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=69 DEFAULT CHARSET=utf8;\n\n#\n# Data for table \"XXL_JOB_QRTZ_TRIGGER_LOG\"\n#\n\nINSERT INTO `XXL_JOB_QRTZ_TRIGGER_LOG` VALUES (1,1,5,'BEAN','192.168.45.1:9999','demoJobHandler','demoJobHandler','2018-05-14 21:51:25',200,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：[192.168.45.1:9999]<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度：<br>address：192.168.45.1:9999<br>code：200<br>msg：null','2018-05-14 21:51:36',200,''),(2,1,5,'BEAN','192.168.45.1:9999','demoJobHandler','demoJobHandler','2018-05-14 21:51:30',200,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：[192.168.45.1:9999]<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度：<br>address：192.168.45.1:9999<br>code：200<br>msg：null','2018-05-14 21:51:46',200,''),(3,1,5,'BEAN','192.168.45.1:9999','demoJobHandler','demoJobHandler','2018-05-14 21:51:35',200,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：[192.168.45.1:9999]<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度：<br>address：192.168.45.1:9999<br>code：200<br>msg：null','2018-05-14 21:51:56',200,''),(4,1,5,'BEAN','192.168.45.1:9999','demoJobHandler','demoJobHandler','2018-05-14 21:51:40',200,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：[192.168.45.1:9999]<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度：<br>address：192.168.45.1:9999<br>code：200<br>msg：null','2018-05-14 21:52:06',200,''),(5,1,5,'BEAN','192.168.45.1:9999','demoJobHandler','demoJobHandler','2018-05-14 21:51:45',200,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：[192.168.45.1:9999]<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度：<br>address：192.168.45.1:9999<br>code：200<br>msg：null','2018-05-14 21:52:16',200,''),(6,1,5,'BEAN','192.168.45.1:9999','demoJobHandler','demoJobHandler','2018-05-14 21:51:50',200,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：[192.168.45.1:9999]<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度：<br>address：192.168.45.1:9999<br>code：200<br>msg：null','2018-05-14 21:52:26',200,''),(7,1,5,'BEAN','192.168.45.1:9999','demoJobHandler','demoJobHandler','2018-05-14 21:51:55',200,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：[192.168.45.1:9999]<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度：<br>address：192.168.45.1:9999<br>code：200<br>msg：null','2018-05-14 21:52:36',200,''),(8,1,5,'BEAN','192.168.45.1:9999','demoJobHandler','demoJobHandler','2018-05-14 21:52:00',200,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：[192.168.45.1:9999]<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度：<br>address：192.168.45.1:9999<br>code：200<br>msg：null','2018-05-14 21:52:46',200,''),(9,1,5,'BEAN','192.168.45.1:9999','demoJobHandler','demoJobHandler','2018-05-14 21:52:05',200,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：[192.168.45.1:9999]<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度：<br>address：192.168.45.1:9999<br>code：200<br>msg：null','2018-05-14 21:52:56',200,''),(10,1,5,'BEAN','192.168.45.1:9999','demoJobHandler','demoJobHandler','2018-05-14 21:52:10',200,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：[192.168.45.1:9999]<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度：<br>address：192.168.45.1:9999<br>code：200<br>msg：null','2018-05-14 21:53:06',200,''),(11,1,5,'BEAN','192.168.45.1:9999','demoJobHandler','demoJobHandler','2018-05-14 21:52:15',200,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：[192.168.45.1:9999]<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度：<br>address：192.168.45.1:9999<br>code：200<br>msg：null','2018-05-14 21:53:16',200,''),(12,1,5,'BEAN','192.168.45.1:9999','demoJobHandler','demoJobHandler','2018-05-14 21:52:20',200,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：[192.168.45.1:9999]<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度：<br>address：192.168.45.1:9999<br>code：200<br>msg：null','2018-05-14 21:53:26',200,''),(13,1,5,'BEAN','192.168.45.1:9999','demoJobHandler','demoJobHandler','2018-05-14 21:52:25',200,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：[192.168.45.1:9999]<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度：<br>address：192.168.45.1:9999<br>code：200<br>msg：null','2018-05-14 21:53:36',200,''),(14,1,5,'BEAN','192.168.45.1:9999','demoJobHandler','demoJobHandler','2018-05-14 21:52:30',200,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：[192.168.45.1:9999]<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度：<br>address：192.168.45.1:9999<br>code：200<br>msg：null','2018-05-14 21:53:46',200,''),(15,1,5,'BEAN','192.168.45.1:9999','demoJobHandler','demoJobHandler','2018-05-14 21:52:35',200,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：[192.168.45.1:9999]<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度：<br>address：192.168.45.1:9999<br>code：200<br>msg：null','2018-05-14 21:53:56',200,''),(16,1,5,'BEAN','192.168.45.1:9999','demoJobHandler','demoJobHandler','2018-05-14 21:52:40',200,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：[192.168.45.1:9999]<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度：<br>address：192.168.45.1:9999<br>code：200<br>msg：null','2018-05-14 21:54:06',500,'Web容器销毁终止 [业务运行中，被强制终止]'),(17,1,5,'BEAN','192.168.45.1:9999','demoJobHandler','demoJobHandler','2018-05-14 21:52:45',200,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：[192.168.45.1:9999]<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度：<br>address：192.168.45.1:9999<br>code：200<br>msg：null','2018-05-14 21:54:06',500,'Web容器销毁终止 [任务尚未执行，在调度队列中被终止]'),(18,1,5,'BEAN','192.168.45.1:9999','demoJobHandler','demoJobHandler','2018-05-14 21:52:50',200,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：[192.168.45.1:9999]<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度：<br>address：192.168.45.1:9999<br>code：200<br>msg：null','2018-05-14 21:54:06',500,'Web容器销毁终止 [任务尚未执行，在调度队列中被终止]'),(19,1,5,'BEAN','192.168.45.1:9999','demoJobHandler','demoJobHandler','2018-05-14 21:52:55',200,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：[192.168.45.1:9999]<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度：<br>address：192.168.45.1:9999<br>code：200<br>msg：null','2018-05-14 21:54:06',500,'Web容器销毁终止 [任务尚未执行，在调度队列中被终止]'),(20,1,5,'BEAN','192.168.45.1:9999','demoJobHandler','demoJobHandler','2018-05-14 21:53:00',200,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：[192.168.45.1:9999]<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度：<br>address：192.168.45.1:9999<br>code：200<br>msg：null','2018-05-14 21:54:06',500,'Web容器销毁终止 [任务尚未执行，在调度队列中被终止]'),(21,1,6,'BEAN','192.168.45.1:9999','demoJobHandler','','2018-05-14 21:53:01',200,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：[192.168.45.1:9999]<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度：<br>address：192.168.45.1:9999<br>code：200<br>msg：null','2018-05-14 21:53:11',200,''),(22,1,5,'BEAN','192.168.45.1:9999','demoJobHandler','demoJobHandler','2018-05-14 21:53:05',200,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：[192.168.45.1:9999]<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度：<br>address：192.168.45.1:9999<br>code：200<br>msg：null','2018-05-14 21:54:06',500,'Web容器销毁终止 [任务尚未执行，在调度队列中被终止]'),(23,1,6,'BEAN','192.168.45.1:9999','demoJobHandler','','2018-05-14 21:53:05',200,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：[192.168.45.1:9999]<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度：<br>address：192.168.45.1:9999<br>code：200<br>msg：null','2018-05-14 21:53:21',200,''),(24,1,5,'BEAN','192.168.45.1:9999','demoJobHandler','demoJobHandler','2018-05-14 21:53:10',200,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：[192.168.45.1:9999]<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度：<br>address：192.168.45.1:9999<br>code：200<br>msg：null','2018-05-14 21:54:06',500,'Web容器销毁终止 [任务尚未执行，在调度队列中被终止]'),(25,1,6,'BEAN','192.168.45.1:9999','demoJobHandler','','2018-05-14 21:53:10',200,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：[192.168.45.1:9999]<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度：<br>address：192.168.45.1:9999<br>code：200<br>msg：null','2018-05-14 21:53:31',200,''),(26,1,5,'BEAN','192.168.45.1:9999','demoJobHandler','demoJobHandler','2018-05-14 21:53:15',200,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：[192.168.45.1:9999]<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度：<br>address：192.168.45.1:9999<br>code：200<br>msg：null','2018-05-14 21:54:06',500,'Web容器销毁终止 [任务尚未执行，在调度队列中被终止]'),(27,1,6,'BEAN','192.168.45.1:9999','demoJobHandler','','2018-05-14 21:53:15',200,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：[192.168.45.1:9999]<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度：<br>address：192.168.45.1:9999<br>code：200<br>msg：null','2018-05-14 21:53:41',200,''),(28,1,5,'BEAN','192.168.45.1:9999','demoJobHandler','demoJobHandler','2018-05-14 21:53:20',200,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：[192.168.45.1:9999]<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度：<br>address：192.168.45.1:9999<br>code：200<br>msg：null','2018-05-14 21:54:06',500,'Web容器销毁终止 [任务尚未执行，在调度队列中被终止]'),(29,1,6,'BEAN','192.168.45.1:9999','demoJobHandler','','2018-05-14 21:53:20',200,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：[192.168.45.1:9999]<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度：<br>address：192.168.45.1:9999<br>code：200<br>msg：null','2018-05-14 21:53:51',200,''),(30,1,5,'BEAN','192.168.45.1:9999','demoJobHandler','demoJobHandler','2018-05-14 21:53:25',200,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：[192.168.45.1:9999]<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度：<br>address：192.168.45.1:9999<br>code：200<br>msg：null','2018-05-14 21:54:06',500,'Web容器销毁终止 [任务尚未执行，在调度队列中被终止]'),(31,1,6,'BEAN','192.168.45.1:9999','demoJobHandler','','2018-05-14 21:53:25',200,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：[192.168.45.1:9999]<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度：<br>address：192.168.45.1:9999<br>code：200<br>msg：null','2018-05-14 21:54:01',200,''),(32,1,5,'BEAN','192.168.45.1:9999','demoJobHandler','demoJobHandler','2018-05-14 21:53:30',200,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：[192.168.45.1:9999]<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度：<br>address：192.168.45.1:9999<br>code：200<br>msg：null','2018-05-14 21:54:06',500,'Web容器销毁终止 [任务尚未执行，在调度队列中被终止]'),(33,1,6,'BEAN','192.168.45.1:9999','demoJobHandler','','2018-05-14 21:53:30',200,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：[192.168.45.1:9999]<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度：<br>address：192.168.45.1:9999<br>code：200<br>msg：null','2018-05-14 21:54:06',500,'Web容器销毁终止 [业务运行中，被强制终止]'),(34,1,6,'BEAN','192.168.45.1:9999','demoJobHandler','','2018-05-14 21:53:35',200,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：[192.168.45.1:9999]<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度：<br>address：192.168.45.1:9999<br>code：200<br>msg：null','2018-05-14 21:54:06',500,'Web容器销毁终止 [任务尚未执行，在调度队列中被终止]'),(35,1,6,'BEAN','192.168.45.1:9999','demoJobHandler','','2018-05-14 21:53:40',200,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：[192.168.45.1:9999]<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度：<br>address：192.168.45.1:9999<br>code：200<br>msg：null','2018-05-14 21:54:06',500,'Web容器销毁终止 [任务尚未执行，在调度队列中被终止]'),(36,1,6,'BEAN','192.168.45.1:9999','demoJobHandler','','2018-05-14 21:53:45',200,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：[192.168.45.1:9999]<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度：<br>address：192.168.45.1:9999<br>code：200<br>msg：null','2018-05-14 21:54:06',500,'Web容器销毁终止 [任务尚未执行，在调度队列中被终止]'),(37,1,6,'BEAN','192.168.45.1:9999','demoJobHandler','','2018-05-14 21:53:50',200,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：[192.168.45.1:9999]<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度：<br>address：192.168.45.1:9999<br>code：200<br>msg：null','2018-05-14 21:54:06',500,'Web容器销毁终止 [任务尚未执行，在调度队列中被终止]'),(38,1,6,'BEAN','192.168.45.1:9999','demoJobHandler','','2018-05-14 21:53:55',200,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：[192.168.45.1:9999]<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度：<br>address：192.168.45.1:9999<br>code：200<br>msg：null','2018-05-14 21:54:06',500,'Web容器销毁终止 [任务尚未执行，在调度队列中被终止]'),(39,1,6,'BEAN','192.168.45.1:9999','demoJobHandler','','2018-05-14 21:54:00',200,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：[192.168.45.1:9999]<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度：<br>address：192.168.45.1:9999<br>code：200<br>msg：null','2018-05-14 21:54:06',500,'Web容器销毁终止 [任务尚未执行，在调度队列中被终止]'),(40,1,6,'BEAN','192.168.45.1:9999','demoJobHandler','','2018-05-14 21:54:05',200,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：[192.168.45.1:9999]<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度：<br>address：192.168.45.1:9999<br>code：200<br>msg：null','2018-05-14 21:54:06',500,'Web容器销毁终止 [任务尚未执行，在调度队列中被终止]'),(41,1,6,'BEAN','192.168.45.1:9999','demoJobHandler','','2018-05-14 21:54:10',500,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：[192.168.45.1:9999]<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度：<br>address：192.168.45.1:9999<br>code：500<br>msg：java.lang.RuntimeException: Network request error: Connect to 192.168.45.1:9999 [/192.168.45.1] failed: Connection refused: connect',NULL,0,NULL),(42,1,6,'BEAN',NULL,'demoJobHandler','','2018-05-14 21:54:46',500,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：null<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br>----------------------<br>调度失败：执行器地址为空',NULL,0,NULL),(43,1,6,'BEAN',NULL,'demoJobHandler','','2018-05-14 21:54:46',500,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：null<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br>----------------------<br>调度失败：执行器地址为空',NULL,0,NULL),(44,1,6,'BEAN',NULL,'demoJobHandler','','2018-05-14 21:54:46',500,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：null<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br>----------------------<br>调度失败：执行器地址为空',NULL,0,NULL),(45,1,6,'BEAN',NULL,'demoJobHandler','','2018-05-14 21:54:46',500,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：null<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br>----------------------<br>调度失败：执行器地址为空',NULL,0,NULL),(46,1,6,'BEAN',NULL,'demoJobHandler','','2018-05-14 21:54:46',500,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：null<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br>----------------------<br>调度失败：执行器地址为空',NULL,0,NULL),(47,1,6,'BEAN',NULL,'demoJobHandler','','2018-05-14 21:54:46',500,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：null<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br>----------------------<br>调度失败：执行器地址为空',NULL,0,NULL),(48,1,6,'BEAN',NULL,'demoJobHandler','','2018-05-14 21:54:46',500,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：null<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br>----------------------<br>调度失败：执行器地址为空',NULL,0,NULL),(49,1,6,'BEAN',NULL,'demoJobHandler','','2018-05-14 21:54:50',500,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：null<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br>----------------------<br>调度失败：执行器地址为空',NULL,0,NULL),(50,1,6,'BEAN',NULL,'demoJobHandler','','2018-05-14 21:54:55',500,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：null<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br>----------------------<br>调度失败：执行器地址为空',NULL,0,NULL),(51,1,6,'BEAN',NULL,'demoJobHandler','','2018-05-14 21:55:00',500,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：null<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br>----------------------<br>调度失败：执行器地址为空',NULL,0,NULL),(52,1,6,'BEAN',NULL,'demoJobHandler','','2018-05-14 21:55:05',500,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：null<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br>----------------------<br>调度失败：执行器地址为空',NULL,0,NULL),(53,1,5,'BEAN',NULL,'demoJobHandler','demoJobHandler','2018-05-14 21:55:07',500,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：null<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br>----------------------<br>调度失败：执行器地址为空',NULL,0,NULL),(54,1,6,'BEAN',NULL,'demoJobHandler','','2018-05-14 21:55:10',500,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：null<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br>----------------------<br>调度失败：执行器地址为空',NULL,0,NULL),(55,1,6,'BEAN',NULL,'demoJobHandler','','2018-05-14 21:55:15',500,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：null<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br>----------------------<br>调度失败：执行器地址为空',NULL,0,NULL),(56,1,6,'BEAN',NULL,'demoJobHandler','','2018-05-14 21:55:20',500,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：null<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br>----------------------<br>调度失败：执行器地址为空',NULL,0,NULL),(57,1,6,'BEAN',NULL,'demoJobHandler','','2018-05-14 21:55:25',500,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：null<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br>----------------------<br>调度失败：执行器地址为空',NULL,0,NULL),(58,1,6,'BEAN',NULL,'demoJobHandler','','2018-05-14 21:55:30',500,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：null<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br>----------------------<br>调度失败：执行器地址为空',NULL,0,NULL),(59,1,5,'BEAN',NULL,'demoJobHandler','demoJobHandler','2018-05-14 21:55:35',500,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：null<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br>----------------------<br>调度失败：执行器地址为空',NULL,0,NULL),(60,1,6,'BEAN',NULL,'demoJobHandler','','2018-05-14 21:55:35',500,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：null<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br>----------------------<br>调度失败：执行器地址为空',NULL,0,NULL),(61,1,5,'BEAN',NULL,'demoJobHandler','demoJobHandler','2018-05-14 21:55:40',500,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：null<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br>----------------------<br>调度失败：执行器地址为空',NULL,0,NULL),(62,1,6,'BEAN',NULL,'demoJobHandler','','2018-05-14 21:55:40',500,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：null<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br>----------------------<br>调度失败：执行器地址为空',NULL,0,NULL),(63,1,5,'BEAN',NULL,'demoJobHandler','demoJobHandler','2018-05-14 21:55:45',500,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：null<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br>----------------------<br>调度失败：执行器地址为空',NULL,0,NULL),(64,1,6,'BEAN',NULL,'demoJobHandler','','2018-05-14 21:55:45',500,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：null<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br>----------------------<br>调度失败：执行器地址为空',NULL,0,NULL),(65,1,5,'BEAN',NULL,'demoJobHandler','demoJobHandler','2018-05-14 21:55:50',500,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：null<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br>----------------------<br>调度失败：执行器地址为空',NULL,0,NULL),(66,1,6,'BEAN',NULL,'demoJobHandler','','2018-05-14 21:55:50',500,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：null<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br>----------------------<br>调度失败：执行器地址为空',NULL,0,NULL),(67,1,5,'BEAN',NULL,'demoJobHandler','demoJobHandler','2018-05-14 21:55:55',500,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：null<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br>----------------------<br>调度失败：执行器地址为空',NULL,0,NULL),(68,1,6,'BEAN',NULL,'demoJobHandler','','2018-05-14 21:55:55',500,'调度机器：192.168.45.1<br>执行器-注册方式：自动注册<br>执行器-地址列表：null<br>路由策略：第一个<br>阻塞处理策略：单机串行<br>失败处理策略：失败告警<br>----------------------<br>调度失败：执行器地址为空',NULL,0,NULL);\n\n#\n# Structure for table \"XXL_JOB_QRTZ_TRIGGER_LOGGLUE\"\n#\n\nCREATE TABLE `XXL_JOB_QRTZ_TRIGGER_LOGGLUE` (\n  `id` int(11) NOT NULL AUTO_INCREMENT,\n  `job_id` int(11) NOT NULL COMMENT '任务，主键ID',\n  `glue_type` varchar(50) DEFAULT NULL COMMENT 'GLUE类型',\n  `glue_source` text COMMENT 'GLUE源代码',\n  `glue_remark` varchar(128) NOT NULL COMMENT 'GLUE备注',\n  `add_time` timestamp NULL DEFAULT NULL,\n  `update_time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\n#\n# Data for table \"XXL_JOB_QRTZ_TRIGGER_LOGGLUE\"\n#\n\n\n#\n# Structure for table \"XXL_JOB_QRTZ_TRIGGER_REGISTRY\"\n#\n\nCREATE TABLE `XXL_JOB_QRTZ_TRIGGER_REGISTRY` (\n  `id` int(11) NOT NULL AUTO_INCREMENT,\n  `registry_group` varchar(255) NOT NULL,\n  `registry_key` varchar(255) NOT NULL,\n  `registry_value` varchar(255) NOT NULL,\n  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;\n\n#\n# Data for table \"XXL_JOB_QRTZ_TRIGGER_REGISTRY\"\n#\n\nINSERT INTO `XXL_JOB_QRTZ_TRIGGER_REGISTRY` VALUES (2,'EXECUTOR','open-xxl-job-demo','192.168.45.1:9999','2018-05-12 06:35:07');\n\n#\n# Structure for table \"XXL_JOB_QRTZ_TRIGGERS\"\n#\n\nCREATE TABLE `XXL_JOB_QRTZ_TRIGGERS` (\n  `SCHED_NAME` varchar(120) NOT NULL,\n  `TRIGGER_NAME` varchar(200) NOT NULL,\n  `TRIGGER_GROUP` varchar(200) NOT NULL,\n  `JOB_NAME` varchar(200) NOT NULL,\n  `JOB_GROUP` varchar(200) NOT NULL,\n  `DESCRIPTION` varchar(250) DEFAULT NULL,\n  `NEXT_FIRE_TIME` bigint(13) DEFAULT NULL,\n  `PREV_FIRE_TIME` bigint(13) DEFAULT NULL,\n  `PRIORITY` int(11) DEFAULT NULL,\n  `TRIGGER_STATE` varchar(16) NOT NULL,\n  `TRIGGER_TYPE` varchar(8) NOT NULL,\n  `START_TIME` bigint(13) NOT NULL,\n  `END_TIME` bigint(13) DEFAULT NULL,\n  `CALENDAR_NAME` varchar(200) DEFAULT NULL,\n  `MISFIRE_INSTR` smallint(2) DEFAULT NULL,\n  `JOB_DATA` blob,\n  PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),\n  KEY `SCHED_NAME` (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`),\n  CONSTRAINT `XXL_JOB_QRTZ_TRIGGERS_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) REFERENCES `XXL_JOB_QRTZ_JOB_DETAILS` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\n#\n# Data for table \"XXL_JOB_QRTZ_TRIGGERS\"\n#\n\nINSERT INTO `XXL_JOB_QRTZ_TRIGGERS` VALUES ('quartzScheduler','3','1','3','1',NULL,1525885261000,-1,5,'PAUSED','CRON',1525876730000,0,NULL,2,X''),('quartzScheduler','4','1','4','1',NULL,1525885261000,-1,5,'PAUSED','CRON',1525876778000,0,NULL,2,X''),('schedulerFactoryBean','5','1','5','1',NULL,1526306160000,1526306155000,5,'ACQUIRED','CRON',1526305882000,0,NULL,2,X''),('schedulerFactoryBean','6','1','6','1',NULL,1526306160000,1526306155000,5,'WAITING','CRON',1526305980000,0,NULL,2,X'');\n\n#\n# Structure for table \"XXL_JOB_QRTZ_SIMPROP_TRIGGERS\"\n#\n\nCREATE TABLE `XXL_JOB_QRTZ_SIMPROP_TRIGGERS` (\n  `SCHED_NAME` varchar(120) NOT NULL,\n  `TRIGGER_NAME` varchar(200) NOT NULL,\n  `TRIGGER_GROUP` varchar(200) NOT NULL,\n  `STR_PROP_1` varchar(512) DEFAULT NULL,\n  `STR_PROP_2` varchar(512) DEFAULT NULL,\n  `STR_PROP_3` varchar(512) DEFAULT NULL,\n  `INT_PROP_1` int(11) DEFAULT NULL,\n  `INT_PROP_2` int(11) DEFAULT NULL,\n  `LONG_PROP_1` bigint(20) DEFAULT NULL,\n  `LONG_PROP_2` bigint(20) DEFAULT NULL,\n  `DEC_PROP_1` decimal(13,4) DEFAULT NULL,\n  `DEC_PROP_2` decimal(13,4) DEFAULT NULL,\n  `BOOL_PROP_1` varchar(1) DEFAULT NULL,\n  `BOOL_PROP_2` varchar(1) DEFAULT NULL,\n  PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),\n  CONSTRAINT `XXL_JOB_QRTZ_SIMPROP_TRIGGERS_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `XXL_JOB_QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\n#\n# Data for table \"XXL_JOB_QRTZ_SIMPROP_TRIGGERS\"\n#\n\n\n#\n# Structure for table \"XXL_JOB_QRTZ_SIMPLE_TRIGGERS\"\n#\n\nCREATE TABLE `XXL_JOB_QRTZ_SIMPLE_TRIGGERS` (\n  `SCHED_NAME` varchar(120) NOT NULL,\n  `TRIGGER_NAME` varchar(200) NOT NULL,\n  `TRIGGER_GROUP` varchar(200) NOT NULL,\n  `REPEAT_COUNT` bigint(7) NOT NULL,\n  `REPEAT_INTERVAL` bigint(12) NOT NULL,\n  `TIMES_TRIGGERED` bigint(10) NOT NULL,\n  PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),\n  CONSTRAINT `XXL_JOB_QRTZ_SIMPLE_TRIGGERS_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `XXL_JOB_QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\n#\n# Data for table \"XXL_JOB_QRTZ_SIMPLE_TRIGGERS\"\n#\n\n\n#\n# Structure for table \"XXL_JOB_QRTZ_CRON_TRIGGERS\"\n#\n\nCREATE TABLE `XXL_JOB_QRTZ_CRON_TRIGGERS` (\n  `SCHED_NAME` varchar(120) NOT NULL,\n  `TRIGGER_NAME` varchar(200) NOT NULL,\n  `TRIGGER_GROUP` varchar(200) NOT NULL,\n  `CRON_EXPRESSION` varchar(200) NOT NULL,\n  `TIME_ZONE_ID` varchar(80) DEFAULT NULL,\n  PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),\n  CONSTRAINT `XXL_JOB_QRTZ_CRON_TRIGGERS_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `XXL_JOB_QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\n#\n# Data for table \"XXL_JOB_QRTZ_CRON_TRIGGERS\"\n#\n\nINSERT INTO `XXL_JOB_QRTZ_CRON_TRIGGERS` VALUES ('quartzScheduler','3','1','1 1 1 * * ? *','Asia/Shanghai'),('quartzScheduler','4','1','1 1 1 * * ? *','Asia/Shanghai'),('schedulerFactoryBean','5','1','*/5 * * * * ?','GMT+08:00'),('schedulerFactoryBean','6','1','*/5 * * * * ?','GMT+08:00');\n\n#\n# Structure for table \"XXL_JOB_QRTZ_BLOB_TRIGGERS\"\n#\n\nCREATE TABLE `XXL_JOB_QRTZ_BLOB_TRIGGERS` (\n  `SCHED_NAME` varchar(120) NOT NULL,\n  `TRIGGER_NAME` varchar(200) NOT NULL,\n  `TRIGGER_GROUP` varchar(200) NOT NULL,\n  `BLOB_DATA` blob,\n  PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),\n  CONSTRAINT `XXL_JOB_QRTZ_BLOB_TRIGGERS_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `XXL_JOB_QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\n#\n# Data for table \"XXL_JOB_QRTZ_BLOB_TRIGGERS\"\n#\n"
  },
  {
    "path": "open-xxl-job/doc/分布式任务调度平台XXL-JOB.html",
    "content": "<!DOCTYPE html>\n<!-- saved from url=(0143)http://www.xuxueli.com/xxl-job/#/?id=%e3%80%8a%e5%88%86%e5%b8%83%e5%bc%8f%e4%bb%bb%e5%8a%a1%e8%b0%83%e5%ba%a6%e5%b9%b3%e5%8f%b0xxl-job%e3%80%8b -->\n<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n    \n    <title>分布式任务调度平台XXL-JOB</title>\n    <link rel=\"icon\" href=\"http://www.xuxueli.com/xxl-job/favicon.ico\">\n\n    <meta name=\"keywords\" content=\"XXL-JOB,轻量级,分布式,任务调度\">\n    <meta name=\"description\" content=\"XXL-JOB是一个轻量级分布式任务调度框架，其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线，开箱即用。\">\n    <meta name=\"viewport\" content=\"width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0\">\n\n    <link rel=\"stylesheet\" href=\"./分布式任务调度平台XXL-JOB_files/vue.css\">\n\n<style>\n.sidebar {\n  padding-top: 0;\n}\n\n.search {\n  margin-bottom: 20px;\n  padding: 6px;\n  border-bottom: 1px solid #eee;\n}\n\n.search .results-panel {\n  display: none;\n}\n\n.search .results-panel.show {\n  display: block;\n}\n\n.search input {\n  outline: none;\n  border: none;\n  width: 100%;\n  padding: 7px;\n  line-height: 22px;\n  font-size: 14px;\n  -webkit-appearance: none;\n  -moz-appearance: none;\n  appearance: none;\n}\n\n.search h2 {\n  font-size: 17px;\n  margin: 10px 0;\n}\n\n.search a {\n  text-decoration: none;\n  color: inherit;\n}\n\n.search .matching-post {\n  border-bottom: 1px solid #eee;\n}\n\n.search .matching-post:last-child {\n  border-bottom: 0;\n}\n\n.search p {\n  font-size: 14px;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  display: -webkit-box;\n  -webkit-line-clamp: 2;\n  -webkit-box-orient: vertical;\n}\n\n.search p.empty {\n  text-align: center;\n}</style></head>\n<body data-page=\"https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/XXL-JOB%E5%AE%98%E6%96%B9%E6%96%87%E6%A1%A3.md\" class=\"ready sticky\">\n    <nav class=\"app-nav no-badge\"><ul>\n<li><p><a href=\"http://www.xuxueli.com/index.html\">主页</a></p></li>\n<li><p><a href=\"https://github.com/xuxueli/xxl-job/releases\" target=\"_blank\">下载</a></p></li>\n<li><p>语言</p><ul>\n<li><a href=\"http://www.xuxueli.com/xxl-job/\">中文</a></li>\n<li><a href=\"http://www.xuxueli.com/xxl-job/en/\">English</a></li>\n</ul>\n</li>\n</ul>\n</nav><section class=\"cover show\" style=\"background: linear-gradient(to left bottom, hsl(187, 100%, 85%) 0%,hsl(144, 100%, 85%) 100%)\"><div class=\"cover-main\"><p><img src=\"./分布式任务调度平台XXL-JOB_files/xxl-logo.png\" width=\"100\"></p><h1 id=\"xxl-job\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=xxl-job\" data-id=\"xxl-job\" class=\"anchor\"><span>XXL-JOB</span></a></h1><blockquote>\n<p>轻量级分布式任务调度框架</p></blockquote>\n<ul>\n<li>开发迅速、学习简单、轻量级、易扩展</li>\n</ul>\n<p><a href=\"https://github.com/xuxueli/xxl-job/\" target=\"_blank\">GitHub</a>\n<a href=\"http://gitee.com/xuxueli0323/xxl-job\" target=\"_blank\">Gitee</a>\n<a href=\"http://www.xuxueli.com/xxl-job/#/?id=%e3%80%8a%e5%88%86%e5%b8%83%e5%bc%8f%e4%bb%bb%e5%8a%a1%e8%b0%83%e5%ba%a6%e5%b9%b3%e5%8f%b0xxl-job%e3%80%8b\">Get Started</a></p></div><div class=\"mask\"></div></section><main><button class=\"sidebar-toggle\"><div class=\"sidebar-toggle-button\"><span></span><span></span><span></span></div></button><aside class=\"sidebar\"><div class=\"search\"><input type=\"search\" value=\"\" placeholder=\"Type to search\"><div class=\"results-panel\"></div></div><div class=\"sidebar-nav\"><ul><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=%e3%80%8a%e5%88%86%e5%b8%83%e5%bc%8f%e4%bb%bb%e5%8a%a1%e8%b0%83%e5%ba%a6%e5%b9%b3%e5%8f%b0xxl-job%e3%80%8b\">《分布式任务调度平台XXL-JOB》</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=%e4%b8%80%e3%80%81%e7%ae%80%e4%bb%8b\">一、简介</a></li><li><ul class=\"children\"><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_11-%e6%a6%82%e8%bf%b0\">1.1 概述</a></li><li class=\"active\"><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_12-%e7%89%b9%e6%80%a7\">1.2 特性</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_13-%e5%8f%91%e5%b1%95\">1.3 发展</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_14-%e4%b8%8b%e8%bd%bd\">1.4 下载</a></li><li><ul class=\"children\"><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%96%87%e6%a1%a3%e5%9c%b0%e5%9d%80\">文档地址</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ba%90%e7%a0%81%e4%bb%93%e5%ba%93%e5%9c%b0%e5%9d%80\">源码仓库地址</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=%e4%b8%ad%e5%a4%ae%e4%bb%93%e5%ba%93%e5%9c%b0%e5%9d%80\">中央仓库地址</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%8a%80%e6%9c%af%e4%ba%a4%e6%b5%81\">技术交流</a></li></ul></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_15-%e7%8e%af%e5%a2%83\">1.5 环境</a></li></ul></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=%e4%ba%8c%e3%80%81%e5%bf%ab%e9%80%9f%e5%85%a5%e9%97%a8\">二、快速入门</a></li><li><ul class=\"children\"><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_21-%e5%88%9d%e5%a7%8b%e5%8c%96%e8%b0%83%e5%ba%a6%e6%95%b0%e6%8d%ae%e5%ba%93\">2.1 初始化“调度数据库”</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_22-%e7%bc%96%e8%af%91%e6%ba%90%e7%a0%81\">2.2 编译源码</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_23-%e9%85%8d%e7%bd%ae%e9%83%a8%e7%bd%b2%e8%b0%83%e5%ba%a6%e4%b8%ad%e5%bf%83\">2.3 配置部署“调度中心”</a></li><li><ul class=\"children\"><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e4%b8%80%ef%bc%9a%e8%b0%83%e5%ba%a6%e4%b8%ad%e5%bf%83%e9%85%8d%e7%bd%ae%ef%bc%9a\">步骤一：调度中心配置：</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e4%ba%8c%ef%bc%9a%e9%83%a8%e7%bd%b2%e9%a1%b9%e7%9b%ae%ef%bc%9a\">步骤二：部署项目：</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e4%b8%89%ef%bc%9a%e8%b0%83%e5%ba%a6%e4%b8%ad%e5%bf%83%e9%9b%86%e7%be%a4%ef%bc%88%e5%8f%af%e9%80%89%ef%bc%89%ef%bc%9a\">步骤三：调度中心集群（可选）：</a></li></ul></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_24-%e9%85%8d%e7%bd%ae%e9%83%a8%e7%bd%b2%e6%89%a7%e8%a1%8c%e5%99%a8%e9%a1%b9%e7%9b%ae\">2.4 配置部署“执行器项目”</a></li><li><ul class=\"children\"><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e4%b8%80%ef%bc%9amaven%e4%be%9d%e8%b5%96\">步骤一：maven依赖</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e4%ba%8c%ef%bc%9a%e6%89%a7%e8%a1%8c%e5%99%a8%e9%85%8d%e7%bd%ae\">步骤二：执行器配置</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e4%b8%89%ef%bc%9a%e6%89%a7%e8%a1%8c%e5%99%a8%e7%bb%84%e4%bb%b6%e9%85%8d%e7%bd%ae\">步骤三：执行器组件配置</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e5%9b%9b%ef%bc%9a%e9%83%a8%e7%bd%b2%e6%89%a7%e8%a1%8c%e5%99%a8%e9%a1%b9%e7%9b%ae%ef%bc%9a\">步骤四：部署执行器项目：</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e4%ba%94%ef%bc%9a%e6%89%a7%e8%a1%8c%e5%99%a8%e9%9b%86%e7%be%a4%ef%bc%88%e5%8f%af%e9%80%89%ef%bc%89%ef%bc%9a\">步骤五：执行器集群（可选）：</a></li></ul></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_25-%e5%bc%80%e5%8f%91%e7%ac%ac%e4%b8%80%e4%b8%aa%e4%bb%bb%e5%8a%a1hello-world\">2.5 开发第一个任务“Hello World”</a></li><li><ul class=\"children\"><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e4%b8%80%ef%bc%9a%e6%96%b0%e5%bb%ba%e4%bb%bb%e5%8a%a1%ef%bc%9a\">步骤一：新建任务：</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e4%ba%8c%ef%bc%9aglue%e6%a8%a1%e5%bc%8fjava-%e4%bb%bb%e5%8a%a1%e5%bc%80%e5%8f%91%ef%bc%9a\">步骤二：“GLUE模式(Java)” 任务开发：</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e4%b8%89%ef%bc%9a%e8%a7%a6%e5%8f%91%e6%89%a7%e8%a1%8c%ef%bc%9a\">步骤三：触发执行：</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e5%9b%9b%ef%bc%9a%e6%9f%a5%e7%9c%8b%e6%97%a5%e5%bf%97%ef%bc%9a\">步骤四：查看日志：</a></li></ul></li></ul></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=%e4%b8%89%e3%80%81%e4%bb%bb%e5%8a%a1%e8%af%a6%e8%a7%a3\">三、任务详解</a></li><li><ul class=\"children\"><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=%e9%85%8d%e7%bd%ae%e5%b1%9e%e6%80%a7%e8%af%a6%e7%bb%86%e8%af%b4%e6%98%8e%ef%bc%9a\">配置属性详细说明：</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_31-bean%e6%a8%a1%e5%bc%8f\">3.1 BEAN模式</a></li><li><ul class=\"children\"><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e4%b8%80%ef%bc%9a%e6%89%a7%e8%a1%8c%e5%99%a8%e9%a1%b9%e7%9b%ae%e4%b8%ad%ef%bc%8c%e5%bc%80%e5%8f%91jobhandler%ef%bc%9a\">步骤一：执行器项目中，开发JobHandler：</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e4%ba%8c%ef%bc%9a%e8%b0%83%e5%ba%a6%e4%b8%ad%e5%bf%83%ef%bc%8c%e6%96%b0%e5%bb%ba%e8%b0%83%e5%ba%a6%e4%bb%bb%e5%8a%a1\">步骤二：调度中心，新建调度任务</a></li></ul></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_32-glue%e6%a8%a1%e5%bc%8fjava\">3.2 GLUE模式(Java)</a></li><li><ul class=\"children\"><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e4%b8%80%ef%bc%9a%e8%b0%83%e5%ba%a6%e4%b8%ad%e5%bf%83%ef%bc%8c%e6%96%b0%e5%bb%ba%e8%b0%83%e5%ba%a6%e4%bb%bb%e5%8a%a1%ef%bc%9a\">步骤一：调度中心，新建调度任务：</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e4%ba%8c%ef%bc%9a%e5%bc%80%e5%8f%91%e4%bb%bb%e5%8a%a1%e4%bb%a3%e7%a0%81%ef%bc%9a\">步骤二：开发任务代码：</a></li></ul></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_33-glue%e6%a8%a1%e5%bc%8fshell\">3.3 GLUE模式(Shell)</a></li><li><ul class=\"children\"><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e4%b8%80%ef%bc%9a%e8%b0%83%e5%ba%a6%e4%b8%ad%e5%bf%83%ef%bc%8c%e6%96%b0%e5%bb%ba%e8%b0%83%e5%ba%a6%e4%bb%bb%e5%8a%a1\">步骤一：调度中心，新建调度任务</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e4%ba%8c%ef%bc%9a%e5%bc%80%e5%8f%91%e4%bb%bb%e5%8a%a1%e4%bb%a3%e7%a0%81%ef%bc%9a-1\">步骤二：开发任务代码：</a></li></ul></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_34-glue%e6%a8%a1%e5%bc%8fpython\">3.4 GLUE模式(Python)</a></li><li><ul class=\"children\"><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e4%b8%80%ef%bc%9a%e8%b0%83%e5%ba%a6%e4%b8%ad%e5%bf%83%ef%bc%8c%e6%96%b0%e5%bb%ba%e8%b0%83%e5%ba%a6%e4%bb%bb%e5%8a%a1-1\">步骤一：调度中心，新建调度任务</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e4%ba%8c%ef%bc%9a%e5%bc%80%e5%8f%91%e4%bb%bb%e5%8a%a1%e4%bb%a3%e7%a0%81%ef%bc%9a-2\">步骤二：开发任务代码：</a></li></ul></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_35-glue%e6%a8%a1%e5%bc%8fnodejs\">3.5 GLUE模式(NodeJS)</a></li><li><ul class=\"children\"><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e4%b8%80%ef%bc%9a%e8%b0%83%e5%ba%a6%e4%b8%ad%e5%bf%83%ef%bc%8c%e6%96%b0%e5%bb%ba%e8%b0%83%e5%ba%a6%e4%bb%bb%e5%8a%a1-2\">步骤一：调度中心，新建调度任务</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e4%ba%8c%ef%bc%9a%e5%bc%80%e5%8f%91%e4%bb%bb%e5%8a%a1%e4%bb%a3%e7%a0%81%ef%bc%9a-3\">步骤二：开发任务代码：</a></li></ul></li></ul></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=%e5%9b%9b%e3%80%81%e4%bb%bb%e5%8a%a1%e7%ae%a1%e7%90%86\">四、任务管理</a></li><li><ul class=\"children\"><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_40-%e9%85%8d%e7%bd%ae%e6%89%a7%e8%a1%8c%e5%99%a8\">4.0 配置执行器</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%89%a7%e8%a1%8c%e5%99%a8%e5%b1%9e%e6%80%a7%e8%af%b4%e6%98%8e\">执行器属性说明</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_41-%e6%96%b0%e5%bb%ba%e4%bb%bb%e5%8a%a1\">4.1 新建任务</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_42-%e7%bc%96%e8%be%91%e4%bb%bb%e5%8a%a1\">4.2 编辑任务</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_43-%e7%bc%96%e8%be%91glue%e4%bb%a3%e7%a0%81\">4.3 编辑GLUE代码</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_44-%e6%9a%82%e5%81%9c%e6%81%a2%e5%a4%8d%e4%bb%bb%e5%8a%a1\">4.4 暂停/恢复任务</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_45-%e6%89%8b%e5%8a%a8%e8%a7%a6%e5%8f%91%e4%b8%80%e6%ac%a1%e8%b0%83%e5%ba%a6\">4.5 手动触发一次调度</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_46-%e6%9f%a5%e7%9c%8b%e8%b0%83%e5%ba%a6%e6%97%a5%e5%bf%97\">4.6 查看调度日志</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_47-%e6%9f%a5%e7%9c%8b%e6%89%a7%e8%a1%8c%e6%97%a5%e5%bf%97\">4.7 查看执行日志</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_48-%e7%bb%88%e6%ad%a2%e8%bf%90%e8%a1%8c%e4%b8%ad%e7%9a%84%e4%bb%bb%e5%8a%a1\">4.8 终止运行中的任务</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_49-%e5%88%a0%e9%99%a4%e6%89%a7%e8%a1%8c%e6%97%a5%e5%bf%97\">4.9 删除执行日志</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_410-%e5%88%a0%e9%99%a4%e4%bb%bb%e5%8a%a1\">4.10 删除任务</a></li></ul></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=%e4%ba%94%e3%80%81%e6%80%bb%e4%bd%93%e8%ae%be%e8%ae%a1\">五、总体设计</a></li><li><ul class=\"children\"><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_51-%e6%ba%90%e7%a0%81%e7%9b%ae%e5%bd%95%e4%bb%8b%e7%bb%8d\">5.1 源码目录介绍</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_52-%e8%b0%83%e5%ba%a6%e6%95%b0%e6%8d%ae%e5%ba%93%e9%85%8d%e7%bd%ae\">5.2 “调度数据库”配置</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_53-%e6%9e%b6%e6%9e%84%e8%ae%be%e8%ae%a1\">5.3 架构设计</a></li><li><ul class=\"children\"><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_531-%e8%ae%be%e8%ae%a1%e6%80%9d%e6%83%b3\">5.3.1 设计思想</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_532-%e7%b3%bb%e7%bb%9f%e7%bb%84%e6%88%90\">5.3.2 系统组成</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_533-%e6%9e%b6%e6%9e%84%e5%9b%be\">5.3.3 架构图</a></li></ul></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_54-%e8%b0%83%e5%ba%a6%e6%a8%a1%e5%9d%97%e5%89%96%e6%9e%90\">5.4 调度模块剖析</a></li><li><ul class=\"children\"><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_541-quartz%e7%9a%84%e4%b8%8d%e8%b6%b3\">5.4.1 quartz的不足</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_542-remotehttpjobbean\">5.4.2 RemoteHttpJobBean</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_543-%e8%b0%83%e5%ba%a6%e4%b8%ad%e5%bf%83ha%ef%bc%88%e9%9b%86%e7%be%a4%ef%bc%89\">5.4.3 调度中心HA（集群）</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_544-%e8%b0%83%e5%ba%a6%e7%ba%bf%e7%a8%8b%e6%b1%a0\">5.4.4 调度线程池</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_545-disallowconcurrentexecution\">5.4.5 @DisallowConcurrentExecution</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_546-misfire\">5.4.6 misfire</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_547-%e6%97%a5%e5%bf%97%e5%9b%9e%e8%b0%83%e6%9c%8d%e5%8a%a1\">5.4.7 日志回调服务</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_548-%e4%bb%bb%e5%8a%a1ha%ef%bc%88failover%ef%bc%89\">5.4.8 任务HA（Failover）</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_549-%e8%b0%83%e5%ba%a6%e6%97%a5%e5%bf%97\">5.4.9 调度日志</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_5410-%e4%bb%bb%e5%8a%a1%e4%be%9d%e8%b5%96\">5.4.10 任务依赖</a></li></ul></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_55-%e4%bb%bb%e5%8a%a1-quot%e8%bf%90%e8%a1%8c%e6%a8%a1%e5%bc%8fquot-%e5%89%96%e6%9e%90\">5.5 任务 \"运行模式\" 剖析</a></li><li><ul class=\"children\"><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_551-quotbean%e6%a8%a1%e5%bc%8fquot-%e4%bb%bb%e5%8a%a1\">5.5.1 \"Bean模式\" 任务</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_552-quotglue%e6%a8%a1%e5%bc%8fjavaquot-%e4%bb%bb%e5%8a%a1\">5.5.2 \"GLUE模式(Java)\" 任务</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_553-glue%e6%a8%a1%e5%bc%8fshell-glue%e6%a8%a1%e5%bc%8fpython-glue%e6%a8%a1%e5%bc%8fnodejs\">5.5.3 GLUE模式(Shell) + GLUE模式(Python) + GLUE模式(NodeJS)</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_554-%e6%89%a7%e8%a1%8c%e5%99%a8\">5.5.4 执行器</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_555-%e4%bb%bb%e5%8a%a1%e6%97%a5%e5%bf%97\">5.5.5 任务日志</a></li></ul></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_56-%e9%80%9a%e8%ae%af%e6%a8%a1%e5%9d%97%e5%89%96%e6%9e%90\">5.6 通讯模块剖析</a></li><li><ul class=\"children\"><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_561-%e4%b8%80%e6%ac%a1%e5%ae%8c%e6%95%b4%e7%9a%84%e4%bb%bb%e5%8a%a1%e8%b0%83%e5%ba%a6%e9%80%9a%e8%ae%af%e6%b5%81%e7%a8%8b\">5.6.1 一次完整的任务调度通讯流程</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_562-%e9%80%9a%e8%ae%af%e6%95%b0%e6%8d%ae%e5%8a%a0%e5%af%86\">5.6.2 通讯数据加密</a></li></ul></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_57-%e4%bb%bb%e5%8a%a1%e6%b3%a8%e5%86%8c-%e4%bb%bb%e5%8a%a1%e8%87%aa%e5%8a%a8%e5%8f%91%e7%8e%b0\">5.7 任务注册, 任务自动发现</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_58-%e4%bb%bb%e5%8a%a1%e6%89%a7%e8%a1%8c%e7%bb%93%e6%9e%9c\">5.8 任务执行结果</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_59-%e5%88%86%e7%89%87%e5%b9%bf%e6%92%ad-amp-%e5%8a%a8%e6%80%81%e5%88%86%e7%89%87\">5.9 分片广播 &amp; 动态分片</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_510-%e8%ae%bf%e9%97%ae%e4%bb%a4%e7%89%8c%ef%bc%88accesstoken%ef%bc%89\">5.10 访问令牌（AccessToken）</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_511-%e8%b0%83%e5%ba%a6%e4%b8%ad%e5%bf%83api%e6%9c%8d%e5%8a%a1\">5.11 调度中心API服务</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_512-%e6%89%a7%e8%a1%8c%e5%99%a8api%e6%9c%8d%e5%8a%a1\">5.12 执行器API服务</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_513-%e6%95%85%e9%9a%9c%e8%bd%ac%e7%a7%bb-amp-%e5%a4%b1%e8%b4%a5%e9%87%8d%e8%af%95\">5.13 故障转移 &amp; 失败重试</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_514-%e6%89%a7%e8%a1%8c%e5%99%a8%e7%81%b0%e5%ba%a6%e4%b8%8a%e7%ba%bf\">5.14 执行器灰度上线</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_515-%e4%bb%bb%e5%8a%a1%e6%89%a7%e8%a1%8c%e7%bb%93%e6%9e%9c%e8%af%b4%e6%98%8e\">5.15 任务执行结果说明</a></li></ul></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=%e5%85%ad%e3%80%81%e7%89%88%e6%9c%ac%e6%9b%b4%e6%96%b0%e6%97%a5%e5%bf%97\">六、版本更新日志</a></li><li><ul class=\"children\"><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_61-%e7%89%88%e6%9c%ac-v11x%ef%bc%8c%e6%96%b0%e7%89%b9%e6%80%a72015-12-05\">6.1 版本 V1.1.x，新特性[2015-12-05]</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_62-%e7%89%88%e6%9c%ac-v12x%ef%bc%8c%e6%96%b0%e7%89%b9%e6%80%a72016-01-17\">6.2 版本 V1.2.x，新特性[2016-01-17]</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_63-%e7%89%88%e6%9c%ac-v130%ef%bc%8c%e6%96%b0%e7%89%b9%e6%80%a72016-05-19\">6.3 版本 V1.3.0，新特性[2016-05-19]</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_64-%e7%89%88%e6%9c%ac-v131%ef%bc%8c%e6%96%b0%e7%89%b9%e6%80%a72016-05-23\">6.4 版本 V1.3.1，新特性[2016-05-23]</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_65-%e7%89%88%e6%9c%ac-v132%ef%bc%8c%e6%96%b0%e7%89%b9%e6%80%a72016-05-28\">6.5 版本 V1.3.2，新特性[2016-05-28]</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_66-%e7%89%88%e6%9c%ac-v140-%e6%96%b0%e7%89%b9%e6%80%a72016-07-24\">6.6 版本 V1.4.0 新特性[2016-07-24]</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_67-%e7%89%88%e6%9c%ac-v141-%e6%96%b0%e7%89%b9%e6%80%a72016-09-06\">6.7 版本 V1.4.1 新特性[2016-09-06]</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_68-%e7%89%88%e6%9c%ac-v142-%e6%96%b0%e7%89%b9%e6%80%a72016-09-29\">6.8 版本 V1.4.2 新特性[2016-09-29]</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_69-%e7%89%88%e6%9c%ac-v150-%e7%89%b9%e6%80%a72016-11-13\">6.9 版本 V1.5.0 特性[2016-11-13]</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_610-%e7%89%88%e6%9c%ac-v151-%e7%89%b9%e6%80%a72016-11-13\">6.10 版本 V1.5.1 特性[2016-11-13]</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_610-%e7%89%88%e6%9c%ac-v152-%e7%89%b9%e6%80%a72017-02-28\">6.10 版本 V1.5.2 特性[2017-02-28]</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_611-%e7%89%88%e6%9c%ac-v160-%e7%89%b9%e6%80%a72017-03-13\">6.11 版本 V1.6.0 特性[2017-03-13]</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_612-%e7%89%88%e6%9c%ac-v161-%e7%89%b9%e6%80%a72017-03-25\">6.12 版本 V1.6.1 特性[2017-03-25]</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_613-%e7%89%88%e6%9c%ac-v162-%e7%89%b9%e6%80%a72017-04-25\">6.13 版本 V1.6.2 特性[2017-04-25]</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_614-%e7%89%88%e6%9c%ac-v170-%e7%89%b9%e6%80%a72017-05-02\">6.14 版本 V1.7.0 特性[2017-05-02]</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_615-%e7%89%88%e6%9c%ac-v171-%e7%89%b9%e6%80%a72017-05-08\">6.15 版本 V1.7.1 特性[2017-05-08]</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_616-%e7%89%88%e6%9c%ac-v172-%e7%89%b9%e6%80%a72017-05-17\">6.16 版本 V1.7.2 特性[2017-05-17]</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_617-%e7%89%88%e6%9c%ac-v180-%e7%89%b9%e6%80%a72017-07-17\">6.17 版本 V1.8.0 特性[2017-07-17]</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_618-%e7%89%88%e6%9c%ac-v181-%e7%89%b9%e6%80%a72017-07-30\">6.18 版本 V1.8.1 特性[2017-07-30]</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_619-%e7%89%88%e6%9c%ac-v182-%e7%89%b9%e6%80%a72017-09-04\">6.19 版本 V1.8.2 特性[2017-09-04]</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_620-%e7%89%88%e6%9c%ac-v190-%e7%89%b9%e6%80%a72017-12-29\">6.20 版本 V1.9.0 特性[2017-12-29]</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_621-%e7%89%88%e6%9c%ac-v191-%e7%89%b9%e6%80%a72018-02-22\">6.21 版本 V1.9.1 特性[2018-02-22]</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_622-%e7%89%88%e6%9c%ac-v192-%e7%89%b9%e6%80%a7%e8%bf%ad%e4%bb%a3%e4%b8%ad\">6.22 版本 V1.9.2 特性[迭代中]</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=todo-list\">TODO LIST</a></li></ul></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=%e4%b8%83%e3%80%81%e5%85%b6%e4%bb%96\">七、其他</a></li><li><ul class=\"children\"><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_71-%e9%a1%b9%e7%9b%ae%e8%b4%a1%e7%8c%ae\">7.1 项目贡献</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_72-%e7%94%a8%e6%88%b7%e6%8e%a5%e5%85%a5%e7%99%bb%e8%ae%b0\">7.2 用户接入登记</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=_73-%e5%bc%80%e6%ba%90%e5%8d%8f%e8%ae%ae%e5%92%8c%e7%89%88%e6%9d%83\">7.3 开源协议和版权</a></li><li><a class=\"section-link\" href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%8d%90%e8%b5%a0\">捐赠</a></li></ul></li></ul></div></aside><section class=\"content\"><article class=\"markdown-section\" id=\"main\"><h2 id=\"《分布式任务调度平台xxl-job》\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=%e3%80%8a%e5%88%86%e5%b8%83%e5%bc%8f%e4%bb%bb%e5%8a%a1%e8%b0%83%e5%ba%a6%e5%b9%b3%e5%8f%b0xxl-job%e3%80%8b\" data-id=\"《分布式任务调度平台xxl-job》\" class=\"anchor\"><span>《分布式任务调度平台XXL-JOB》</span></a></h2><p><a href=\"https://travis-ci.org/xuxueli/xxl-job\" target=\"_blank\"><img src=\"./分布式任务调度平台XXL-JOB_files/xxl-job.svg\" data-origin=\"https://travis-ci.org/xuxueli/xxl-job.svg?branch=master\" alt=\"Build Status\"></a>\n<a href=\"https://maven-badges.herokuapp.com/maven-central/com.xuxueli/xxl-job/\" target=\"_blank\"><img src=\"./分布式任务调度平台XXL-JOB_files/badge.svg\" data-origin=\"https://maven-badges.herokuapp.com/maven-central/com.xuxueli/xxl-job/badge.svg\" alt=\"Maven Central\"></a>\n<a href=\"https://github.com/xuxueli/xxl-job/releases\" target=\"_blank\"><img src=\"./分布式任务调度平台XXL-JOB_files/xxl-job(1).svg\" data-origin=\"https://img.shields.io/github/release/xuxueli/xxl-job.svg\" alt=\"GitHub release\"></a>\n<a href=\"http://www.gnu.org/licenses/gpl-3.0.html\" target=\"_blank\"><img src=\"./分布式任务调度平台XXL-JOB_files/license-GPLv3-blue.svg\" data-origin=\"https://img.shields.io/badge/license-GPLv3-blue.svg\" alt=\"License\"></a>\n<a href=\"https://gitter.im/xuxueli/xxl-job?utm_source=badge&amp;utm_medium=badge&amp;utm_campaign=pr-badge\" target=\"_blank\"><img src=\"./分布式任务调度平台XXL-JOB_files/xxl-job(2).svg\" data-origin=\"https://badges.gitter.im/xuxueli/xxl-job.svg\" alt=\"Gitter\"></a>\n<a href=\"http://www.xuxueli.com/page/donate.html\" target=\"_blank\"><img src=\"./分布式任务调度平台XXL-JOB_files/$-donate-ff69b4.svg\" data-origin=\"https://img.shields.io/badge/%24-donate-ff69b4.svg?style=flat-square\" alt=\"donate\"></a></p><h2 id=\"一、简介\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=%e4%b8%80%e3%80%81%e7%ae%80%e4%bb%8b\" data-id=\"一、简介\" class=\"anchor\"><span>一、简介</span></a></h2><h3 id=\"_11-概述\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_11-%e6%a6%82%e8%bf%b0\" data-id=\"_11-概述\" class=\"anchor\"><span>1.1 概述</span></a></h3><p>XXL-JOB是一个轻量级分布式任务调度框架，其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线，开箱即用。</p><h3 id=\"_12-特性\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_12-%e7%89%b9%e6%80%a7\" data-id=\"_12-特性\" class=\"anchor\"><span>1.2 特性</span></a></h3><ul>\n<li>1、简单：支持通过Web页面对任务进行CRUD操作，操作简单，一分钟上手；</li>\n<li>2、动态：支持动态修改任务状态、暂停/恢复任务，以及终止运行中任务，即时生效；</li>\n<li>3、调度中心HA（中心式）：调度采用中心式设计，“调度中心”基于集群Quartz实现并支持集群部署，可保证调度中心HA；</li>\n<li>4、执行器HA（分布式）：任务分布式执行，任务\"执行器\"支持集群部署，可保证任务执行HA；</li>\n<li>5、注册中心: 执行器会周期性自动注册任务, 调度中心将会自动发现注册的任务并触发执行。同时，也支持手动录入执行器地址；</li>\n<li>6、弹性扩容缩容：一旦有新执行器机器上线或者下线，下次调度时将会重新分配任务；</li>\n<li>7、路由策略：执行器集群部署时提供丰富的路由策略，包括：第一个、最后一个、轮询、随机、一致性HASH、最不经常使用、最近最久未使用、故障转移、忙碌转移等；</li>\n<li>8、故障转移：任务路由策略选择\"故障转移\"情况下，如果执行器集群中某一台机器故障，将会自动Failover切换到一台正常的执行器发送调度请求。</li>\n<li>9、失败处理策略；调度失败时的处理策略，策略包括：失败告警（默认）、失败重试；</li>\n<li>10、失败重试：调度中心调度失败且启用\"失败重试\"策略时，将会自动重试一次；执行器执行失败且回调失败重试状态时，也将会自动重试一次；</li>\n<li>11、阻塞处理策略：调度过于密集执行器来不及处理时的处理策略，策略包括：单机串行（默认）、丢弃后续调度、覆盖之前调度；</li>\n<li>12、分片广播任务：执行器集群部署时，任务路由策略选择\"分片广播\"情况下，一次任务调度将会广播触发集群中所有执行器执行一次任务，可根据分片参数开发分片任务；</li>\n<li>13、动态分片：分片广播任务以执行器为维度进行分片，支持动态扩容执行器集群从而动态增加分片数量，协同进行业务处理；在进行大数据量业务操作时可显著提升任务处理能力和速度。</li>\n<li>14、事件触发：除了\"Cron方式\"和\"任务依赖方式\"触发任务执行之外，支持基于事件的触发任务方式。调度中心提供触发任务单次执行的API服务，可根据业务事件灵活触发。</li>\n<li>15、任务进度监控：支持实时监控任务进度；</li>\n<li>16、Rolling实时日志：支持在线查看调度结果，并且支持以Rolling方式实时查看执行器输出的完整的执行日志；</li>\n<li>17、GLUE：提供Web IDE，支持在线开发任务逻辑代码，动态发布，实时编译生效，省略部署上线的过程。支持30个版本的历史版本回溯。</li>\n<li>18、脚本任务：支持以GLUE模式开发和运行脚本任务，包括Shell、Python、NodeJS等类型脚本;</li>\n<li>19、任务依赖：支持配置子任务依赖，当父任务执行结束且执行成功后将会主动触发一次子任务的执行, 多个子任务用逗号分隔；</li>\n<li>20、一致性：“调度中心”通过DB锁保证集群分布式调度的一致性, 一次任务调度只会触发一次执行；</li>\n<li>21、自定义任务参数：支持在线配置调度任务入参，即时生效；</li>\n<li>22、调度线程池：调度系统多线程触发调度运行，确保调度精确执行，不被堵塞；</li>\n<li>23、数据加密：调度中心和执行器之间的通讯进行数据加密，提升调度信息安全性；</li>\n<li>24、邮件报警：任务失败时支持邮件报警，支持配置多邮件地址群发报警邮件；</li>\n<li>25、推送maven中央仓库: 将会把最新稳定版推送到maven中央仓库, 方便用户接入和使用;</li>\n<li>26、运行报表：支持实时查看运行数据，如任务数量、调度次数、执行器数量等；以及调度报表，如调度日期分布图，调度成功分布图等；</li>\n<li>27、全异步：系统底层实现全部异步化，针对密集调度进行流量削峰，理论上支持任意时长任务的运行；</li>\n<li>28、国际化：调度中心支持国际化设置，提供中文、英文两种可选语言，默认为中文；</li>\n</ul>\n<h3 id=\"_13-发展\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_13-%e5%8f%91%e5%b1%95\" data-id=\"_13-发展\" class=\"anchor\"><span>1.3 发展</span></a></h3><p>于2015年中，我在github上创建XXL-JOB项目仓库并提交第一个commit，随之进行系统结构设计，UI选型，交互设计……</p><p>于2015-11月，XXL-JOB终于RELEASE了第一个大版本V1.0， 随后我将之发布到OSCHINA，XXL-JOB在OSCHINA上获得了@红薯的热门推荐，同期分别达到了OSCHINA的“热门动弹”排行第一和git.oschina的开源软件月热度排行第一，在此特别感谢红薯，感谢大家的关注和支持。</p><p>于2015-12月，我将XXL-JOB发表到我司内部知识库，并且得到内部同事认可。</p><p>于2016-01月，我司展开XXL-JOB的内部接入和定制工作，在此感谢袁某和尹某两位同事的贡献，同时也感谢内部其他给与关注与支持的同事。</p><p>于2017-05-13，在上海举办的 \"<a href=\"https://www.oschina.net/event/2236961\" target=\"_blank\">第62期开源中国源创会</a>\" 的 \"放码过来\" 环节，我登台对XXL-JOB做了演讲，台下五百位在场观众反响热烈（<a href=\"https://www.oschina.net/question/2686220_2242120\" target=\"_blank\">图文回顾</a> ）。</p><p>于2017-10-22，又拍云 Open Talk 联合 Spring Cloud 中国社区举办的 \"<a href=\"https://opentalk.upyun.com/303.html\" target=\"_blank\">进击的微服务实战派上海站</a>\"，我登台对XXL-JOB做了演讲，现场观众反响热烈并在会后与XXL-JOB用户热烈讨论交流</p><p>于2017-12-11，XXL-JOB有幸参会《<a href=\"http://bj2017.archsummit.com/\" target=\"_blank\">InfoQ ArchSummit全球架构师峰会</a>》，并被拍拍贷架构总监\"杨波老师\"在专题 \"<a href=\"http://bj2017.archsummit.com/training/2\" target=\"_blank\">微服务原理、基础架构和开源实践</a>\" 中现场介绍。</p><p>于2017-12-18，XXL-JOB参与\"<a href=\"http://www.oschina.net/project/top_cn_2017?sort=1\" target=\"_blank\">2017年度最受欢迎中国开源软件</a>\"评比，在当时已录入的约九千个国产开源项目中角逐，最终进入了前30强。</p><p>于2018-01-15，XXL-JOB参与\"<a href=\"https://www.oschina.net/news/92438/2017-mayun-top-50\" target=\"_blank\">2017码云最火开源项目</a>\"评比，在当时已录入的约六千五百个码云项目中角逐，最终进去了前20强。</p><blockquote>\n<p>我司大众点评目前已接入XXL-JOB，内部别名《Ferrari》（Ferrari基于XXL-JOB的V1.1版本定制而成，新接入应用推荐升级最新版本）。\n据最新统计, 自2016-01-21接入至2017-12-01期间，该系统已调度约100万次，表现优异。新接入应用推荐使用最新版本，因为经过数个大版本的更新，系统的任务模型、UI交互模型以及底层调度通讯模型都有了较大的优化和提升，核心功能更加稳定高效。</p></blockquote>\n<p>至今，XXL-JOB已接入多家公司的线上产品线，接入场景如电商业务，O2O业务和大数据作业等，截止最新统计时间为止，XXL-JOB已接入的公司包括不限于：</p><pre v-pre=\"\" data-lang=\"\"><code class=\"lang-\">- 1、大众点评；\n- 2、山东学而网络科技有限公司；\n- 3、安徽慧通互联科技有限公司；\n- 4、人人聚财金服；\n- 5、上海棠棣信息科技股份有限公司\n- 6、运满满\n- 7、米其林 (中国区)\n- 8、妈妈联盟\n- 9、九樱天下（北京）信息技术有限公司\n- 10、万普拉斯科技有限公司(一加手机)\n- 11、上海亿保健康管理有限公司\n- 12、海尔馨厨 (海尔)\n- 13、河南大红包电子商务有限公司\n- 14、成都顺点科技有限公司\n- 15、深圳市怡亚通\n- 16、深圳麦亚信科技股份有限公司\n- 17、上海博莹科技信息技术有限公司\n- 18、中国平安科技有限公司\n- 19、杭州知时信息科技有限公司\n- 20、博莹科技（上海）有限公司\n- 21、成都依能股份有限责任公司\n- 22、湖南高阳通联信息技术有限公司\n- 23、深圳市邦德文化发展有限公司\n- 24、福建阿思可网络教育有限公司\n- 25、优信二手车\n- 26、上海悠游堂投资发展股份有限公司\n- 27、北京粉笔蓝天科技有限公司\n- 28、中秀科技(无锡)有限公司\n- 29、武汉空心科技有限公司\n- 30、北京蚂蚁风暴科技有限公司\n- 31、四川互宜达科技有限公司\n- 32、钱包行云（北京）科技有限公司\n- 33、重庆欣才集团\n- 34、咪咕互动娱乐有限公司（中国移动）\n- 35、北京诺亦腾科技有限公司\n- 36、增长引擎(北京)信息技术有限公司\n- 37、北京英贝思科技有限公司\n- 38、刚泰集团\n- 39、深圳泰久信息系统股份有限公司\n- 40、随行付支付有限公司\n- 41、广州瀚农网络科技有限公司\n- 42、享点科技有限公司\n- 43、杭州比智科技有限公司\n- 44、圳临界线网络科技有限公司\n- 45、广州知识圈网络科技有限公司\n- 46、国誉商业上海有限公司\n- 47、海尔消费金融有限公司，嗨付、够花 (海尔)\n- 48、广州巴图鲁信息科技有限公司\n- 49、深圳市鹏海运电子数据交换有限公司\n- 50、深圳市亚飞电子商务有限公司\n- 51、上海趣医网络有限公司\n- 52、聚金资本\n- 53、北京父母邦网络科技有限公司\n- 54、中山元赫软件科技有限公司\n- 55、中商惠民(北京)电子商务有限公司\n- 56、凯京集团\n- 57、华夏票联（北京）科技有限公司\n- 58、拍拍贷\n- 59、北京尚德机构在线教育有限公司\n- 60、任子行股份有限公司\n- 61、北京时态电子商务有限公司\n- 62、深圳卷皮网络科技有限公司\n- 63、北京安博通科技股份有限公司\n- 64、未来无线网\n- 65、厦门瓷禧网络有限公司\n- 66、北京递蓝科软件股份有限公司\n- 67、郑州创海软件科技公司\n- 68、北京国槐信息科技有限公司\n- 69、浪潮软件集团\n- 70、多立恒(北京)信息技术有限公司\n- 71、广州极迅客信息科技有限公司\n- 72、赫基（中国）集团股份有限公司\n- 73、海投汇\n- 74、上海润益创业孵化器管理股份有限公司\n- 75、汉纳森（厦门）数据股份有限公司\n- 76、安信信托\n- 77、岚儒财富\n- 78、捷道软件\n- ……</code></pre><blockquote>\n<p>更多接入的公司，欢迎在 <a href=\"https://github.com/xuxueli/xxl-job/issues/1\" target=\"_blank\">登记地址</a> 登记，登记仅仅为了产品推广。</p></blockquote>\n<p>欢迎大家的关注和使用，XXL-JOB也将拥抱变化，持续发展。</p><h3 id=\"_14-下载\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_14-%e4%b8%8b%e8%bd%bd\" data-id=\"_14-下载\" class=\"anchor\"><span>1.4 下载</span></a></h3><h4 id=\"文档地址\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%96%87%e6%a1%a3%e5%9c%b0%e5%9d%80\" data-id=\"文档地址\" class=\"anchor\"><span>文档地址</span></a></h4><ul>\n<li><a href=\"http://www.xuxueli.com/xxl-job/\" target=\"_blank\">中文文档</a></li>\n<li><a href=\"http://www.xuxueli.com/xxl-job/en/\" target=\"_blank\">English Documentation</a></li>\n</ul>\n<h4 id=\"源码仓库地址\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ba%90%e7%a0%81%e4%bb%93%e5%ba%93%e5%9c%b0%e5%9d%80\" data-id=\"源码仓库地址\" class=\"anchor\"><span>源码仓库地址</span></a></h4><table>\n<thead>\n<tr>\n<th>源码仓库地址</th>\n<th>Release Download</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><a href=\"https://github.com/xuxueli/xxl-job\" target=\"_blank\">https://github.com/xuxueli/xxl-job</a></td>\n<td><a href=\"https://github.com/xuxueli/xxl-job/releases\" target=\"_blank\">Download</a>  </td>\n</tr>\n<tr>\n<td><a href=\"http://gitee.com/xuxueli0323/xxl-job\" target=\"_blank\">http://gitee.com/xuxueli0323/xxl-job</a></td>\n<td><a href=\"http://gitee.com/xuxueli0323/xxl-job/releases\" target=\"_blank\">Download</a></td>\n</tr>\n</tbody>\n</table>\n<h4 id=\"中央仓库地址\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=%e4%b8%ad%e5%a4%ae%e4%bb%93%e5%ba%93%e5%9c%b0%e5%9d%80\" data-id=\"中央仓库地址\" class=\"anchor\"><span>中央仓库地址</span></a></h4><pre v-pre=\"\" data-lang=\"\"><code class=\"lang-\"><span class=\"token comment\" spellcheck=\"true\">&lt;!-- http://repo1.maven.org/maven2/com/xuxueli/xxl-job-core/ --&gt;</span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>dependency</span><span class=\"token punctuation\">&gt;</span></span>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>groupId</span><span class=\"token punctuation\">&gt;</span></span>com.xuxueli<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>groupId</span><span class=\"token punctuation\">&gt;</span></span>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>artifactId</span><span class=\"token punctuation\">&gt;</span></span>xxl-job-core<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>artifactId</span><span class=\"token punctuation\">&gt;</span></span>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>version</span><span class=\"token punctuation\">&gt;</span></span>${最新稳定版本}<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>version</span><span class=\"token punctuation\">&gt;</span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>dependency</span><span class=\"token punctuation\">&gt;</span></span></code></pre><h4 id=\"技术交流\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%8a%80%e6%9c%af%e4%ba%a4%e6%b5%81\" data-id=\"技术交流\" class=\"anchor\"><span>技术交流</span></a></h4><ul>\n<li><a href=\"http://www.xuxueli.com/page/community.html\" target=\"_blank\">社区交流</a></li>\n<li><a href=\"https://gitter.im/xuxueli/xxl-job\" target=\"_blank\">Gitter</a></li>\n</ul>\n<h3 id=\"_15-环境\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_15-%e7%8e%af%e5%a2%83\" data-id=\"_15-环境\" class=\"anchor\"><span>1.5 环境</span></a></h3><ul>\n<li>JDK：1.7+</li>\n<li>Servlet/JSP Spec：3.1/2.3</li>\n<li>Tomcat：8.5.x/Jetty9.2.x</li>\n<li>Spring-boot：1.5.x/Spring4.x</li>\n<li>Mysql：5.6+</li>\n<li>Maven：3+</li>\n</ul>\n<h2 id=\"二、快速入门\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=%e4%ba%8c%e3%80%81%e5%bf%ab%e9%80%9f%e5%85%a5%e9%97%a8\" data-id=\"二、快速入门\" class=\"anchor\"><span>二、快速入门</span></a></h2><h3 id=\"_21-初始化调度数据库\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_21-%e5%88%9d%e5%a7%8b%e5%8c%96%e8%b0%83%e5%ba%a6%e6%95%b0%e6%8d%ae%e5%ba%93\" data-id=\"_21-初始化调度数据库\" class=\"anchor\"><span>2.1 初始化“调度数据库”</span></a></h3><p>请下载项目源码并解压，获取 \"调度数据库初始化SQL脚本\" 并执行即可，正常情况下应该生成16张表。</p><p>\"调度数据库初始化SQL脚本\" 位置为:</p><pre v-pre=\"\" data-lang=\"\"><code class=\"lang-\">/xxl-job/doc/db/tables_xxl_job.sql</code></pre><p>调度中心支持集群部署，集群情况下各节点务必连接同一个mysql实例;</p><p>如果mysql做主从,调度中心集群节点务必强制走主库;</p><h3 id=\"_22-编译源码\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_22-%e7%bc%96%e8%af%91%e6%ba%90%e7%a0%81\" data-id=\"_22-编译源码\" class=\"anchor\"><span>2.2 编译源码</span></a></h3><p>解压源码,按照maven格式将源码导入IDE, 使用maven进行编译即可，源码结构如下：</p><pre v-pre=\"\" data-lang=\"\"><code class=\"lang-\">xxl-job-admin：调度中心\nxxl-job-core：公共依赖\nxxl-job-executor：执行器Sample示例（选择合适的版本执行器，可直接使用，也可以参考其并将现有项目改造成执行器）\n    ：xxl-job-executor-sample-spring：Spring版本，通过Spring容器管理执行器，比较通用，推荐这种方式；\n    ：xxl-job-executor-sample-springboot：Springboot版本，通过Springboot管理执行器；\n    ：xxl-job-executor-sample-jfinal：JFinal版本，通过JFinal管理执行器；\n    ：xxl-job-executor-sample-nutz：Nutz版本，通过Nutz管理执行器；</code></pre><h3 id=\"_23-配置部署调度中心\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_23-%e9%85%8d%e7%bd%ae%e9%83%a8%e7%bd%b2%e8%b0%83%e5%ba%a6%e4%b8%ad%e5%bf%83\" data-id=\"_23-配置部署调度中心\" class=\"anchor\"><span>2.3 配置部署“调度中心”</span></a></h3><pre v-pre=\"\" data-lang=\"\"><code class=\"lang-\">调度中心项目：xxl-job-admin\n作用：统一管理任务调度平台上调度任务，负责触发调度执行，并且提供任务管理平台。</code></pre><h4 id=\"步骤一：调度中心配置：\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e4%b8%80%ef%bc%9a%e8%b0%83%e5%ba%a6%e4%b8%ad%e5%bf%83%e9%85%8d%e7%bd%ae%ef%bc%9a\" data-id=\"步骤一：调度中心配置：\" class=\"anchor\"><span>步骤一：调度中心配置：</span></a></h4><p>调度中心配置文件地址：</p><pre v-pre=\"\" data-lang=\"\"><code class=\"lang-\">/xxl-job/xxl-job-admin/src/main/resources/xxl-job-admin.properties</code></pre><p>调度中心配置内容说明：</p><pre v-pre=\"\" data-lang=\"\"><code class=\"lang-\">### 调度中心JDBC链接：链接地址请保持和 2.1章节 所创建的调度数据库的地址一致\nxxl.job.db.driverClass=com.mysql.jdbc.Driver\nxxl.job.db.url=jdbc:mysql://localhost:3306/xxl-job?useUnicode=true&amp;characterEncoding=UTF-8\nxxl.job.db.user=root\nxxl.job.db.password=root_pwd\n\n### 报警邮箱\nxxl.job.mail.host=smtp.163.com\nxxl.job.mail.port=25\nxxl.job.mail.ssl=false\nxxl.job.mail.username=ovono802302@163.com\nxxl.job.mail.password=asdfzxcv\nxxl.job.mail.sendFrom=ovono802302@163.com\nxxl.job.mail.sendNick=《任务调度平台XXL-JOB》\n\n### 登录账号\nxxl.job.login.username=admin\nxxl.job.login.password=123456\n\n### 调度中心通讯TOKEN，非空时启用\nxxl.job.accessToken=\n\n### 调度中心国际化设置，默认为中文版本，值设置为“en”时切换为英文版本\nxxl.job.i18n=</code></pre><h4 id=\"步骤二：部署项目：\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e4%ba%8c%ef%bc%9a%e9%83%a8%e7%bd%b2%e9%a1%b9%e7%9b%ae%ef%bc%9a\" data-id=\"步骤二：部署项目：\" class=\"anchor\"><span>步骤二：部署项目：</span></a></h4><p>如果已经正确进行上述配置，可将项目编译打war包并部署到tomcat中。\n调度中心访问地址：<a href=\"http://localhost:8080/xxl-job-admin\" target=\"_blank\">http://localhost:8080/xxl-job-admin</a> (该地址执行器将会使用到，作为回调地址)，登录后运行界面如下图所示</p><p><img src=\"./分布式任务调度平台XXL-JOB_files/img_6yC0.png\" data-origin=\"https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_6yC0.png\" alt=\"输入图片说明\" title=\"在这里输入图片标题\"></p><p>至此“调度中心”项目已经部署成功。</p><h4 id=\"步骤三：调度中心集群（可选）：\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e4%b8%89%ef%bc%9a%e8%b0%83%e5%ba%a6%e4%b8%ad%e5%bf%83%e9%9b%86%e7%be%a4%ef%bc%88%e5%8f%af%e9%80%89%ef%bc%89%ef%bc%9a\" data-id=\"步骤三：调度中心集群（可选）：\" class=\"anchor\"><span>步骤三：调度中心集群（可选）：</span></a></h4><p>调度中心支持集群部署，提升调度系统容灾和可用性。</p><p>调度中心集群部署时，几点要求和建议：</p><ul>\n<li>DB配置保持一致；</li>\n<li>登陆账号配置保持一致；</li>\n<li>集群机器时钟保持一致（单机集群忽视）；</li>\n<li>建议：推荐通过nginx为调度中心集群做负载均衡，分配域名。调度中心访问、执行器回调配置、调用API服务等操作均通过该域名进行。</li>\n</ul>\n<h3 id=\"_24-配置部署执行器项目\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_24-%e9%85%8d%e7%bd%ae%e9%83%a8%e7%bd%b2%e6%89%a7%e8%a1%8c%e5%99%a8%e9%a1%b9%e7%9b%ae\" data-id=\"_24-配置部署执行器项目\" class=\"anchor\"><span>2.4 配置部署“执行器项目”</span></a></h3><pre v-pre=\"\" data-lang=\"\"><code class=\"lang-\">“执行器”项目：xxl-job-executor-sample-spring (提供多种版本执行器供选择，现以Spring版本为例，可直接使用，也可以参考其并将现有项目改造成执行器)\n作用：负责接收“调度中心”的调度并执行；可直接部署执行器，也可以将执行器集成到现有业务项目中。</code></pre><h4 id=\"步骤一：maven依赖\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e4%b8%80%ef%bc%9amaven%e4%be%9d%e8%b5%96\" data-id=\"步骤一：maven依赖\" class=\"anchor\"><span>步骤一：maven依赖</span></a></h4><p>确认pom文件中引入了 \"xxl-job-core\" 的maven依赖；</p><h4 id=\"步骤二：执行器配置\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e4%ba%8c%ef%bc%9a%e6%89%a7%e8%a1%8c%e5%99%a8%e9%85%8d%e7%bd%ae\" data-id=\"步骤二：执行器配置\" class=\"anchor\"><span>步骤二：执行器配置</span></a></h4><p>执行器配置，配置文件地址：</p><pre v-pre=\"\" data-lang=\"\"><code class=\"lang-\">/xxl-job/xxl-job-executor-samples/xxl-job-executor-sample-spring/src/main/resources/xxl-job-executor.properties</code></pre><p>执行器配置，配置内容说明：</p><pre v-pre=\"\" data-lang=\"\"><code class=\"lang-\">### xxl-job admin address list：调度中心部署跟地址：如调度中心集群部署存在多个地址则用逗号分隔。执行器将会使用该地址进行\"执行器心跳注册\"和\"任务结果回调\"。\nxxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin\n\n### xxl-job executor address：执行器\"AppName\"和地址信息配置：AppName执行器心跳注册分组依据；地址信息用于\"调度中心请求并触发任务\"和\"执行器注册\"。执行器默认端口为9999，执行器IP默认为空表示自动获取IP，多网卡时可手动设置指定IP，手动设置IP时将会绑定Host。单机部署多个执行器时，注意要配置不同执行器端口；\nxxl.job.executor.appname=xxl-job-executor-sample\nxxl.job.executor.ip=\nxxl.job.executor.port=9999\n\n### xxl-job, access token：执行器通讯TOKEN，非空时启用\nxxl.job.accessToken=\n\n### xxl-job log path：执行器运行日志文件存储的磁盘位置，需要对该路径拥有读写权限\nxxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler/\n\n### xxl-job log retention days：执行器Log文件定期清理功能，指定日志保存天数，日志文件过期自动删除。限制至少保持3天，否则功能不生效；\nxxl.job.executor.logretentiondays=-1</code></pre><h4 id=\"步骤三：执行器组件配置\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e4%b8%89%ef%bc%9a%e6%89%a7%e8%a1%8c%e5%99%a8%e7%bb%84%e4%bb%b6%e9%85%8d%e7%bd%ae\" data-id=\"步骤三：执行器组件配置\" class=\"anchor\"><span>步骤三：执行器组件配置</span></a></h4><p>执行器组件，配置文件地址：</p><pre v-pre=\"\" data-lang=\"\"><code class=\"lang-\">/xxl-job/xxl-job-executor-samples/xxl-job-executor-sample-spring/src/main/resources/applicationcontext-xxl-job.xml</code></pre><p>执行器组件，配置内容说明：</p><pre v-pre=\"\" data-lang=\"\"><code class=\"lang-\"><span class=\"token comment\" spellcheck=\"true\">&lt;!-- 配置01、JobHandler 扫描路径：自动扫描容器中JobHandler --&gt;</span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token namespace\">context:</span>component-scan</span> <span class=\"token attr-name\">base-package</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>com.xxl.job.executor.service.jobhandler<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/&gt;</span></span>\n\n<span class=\"token comment\" spellcheck=\"true\">&lt;!-- 配置02、执行器 --&gt;</span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>bean</span> <span class=\"token attr-name\">id</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>xxlJobExecutor<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>com.xxl.job.core.executor.XxlJobExecutor<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">init-method</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>start<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">destroy-method</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>destroy<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">&gt;</span></span>\n    <span class=\"token comment\" spellcheck=\"true\">&lt;!-- 执行器注册中心地址[选填]，为空则关闭自动注册 --&gt;</span>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>property</span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>adminAddresses<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">value</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>${xxl.job.admin.addresses}<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/&gt;</span></span>\n    <span class=\"token comment\" spellcheck=\"true\">&lt;!-- 执行器AppName[选填]，为空则关闭自动注册 --&gt;</span>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>property</span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>appName<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">value</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>${xxl.job.executor.appname}<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/&gt;</span></span>\n    <span class=\"token comment\" spellcheck=\"true\">&lt;!-- 执行器IP[选填]，为空则自动获取 --&gt;</span>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>property</span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>ip<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">value</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>${xxl.job.executor.ip}<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/&gt;</span></span>\n    <span class=\"token comment\" spellcheck=\"true\">&lt;!-- 执行器端口号[选填]，为空则自动获取 --&gt;</span>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>property</span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>port<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">value</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>${xxl.job.executor.port}<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/&gt;</span></span>\n    <span class=\"token comment\" spellcheck=\"true\">&lt;!-- 访问令牌[选填]，非空则进行匹配校验 --&gt;</span>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>property</span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>accessToken<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">value</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>${xxl.job.accessToken}<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/&gt;</span></span>\n    <span class=\"token comment\" spellcheck=\"true\">&lt;!-- 执行器日志路径[选填]，为空则使用默认路径 --&gt;</span>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>property</span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>logPath<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">value</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>${xxl.job.executor.logpath}<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/&gt;</span></span>\n    <span class=\"token comment\" spellcheck=\"true\">&lt;!-- 日志保存天数[选填]，值大于3时生效 --&gt;</span>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>property</span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>logRetentionDays<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">value</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>${xxl.job.executor.logretentiondays}<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/&gt;</span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>bean</span><span class=\"token punctuation\">&gt;</span></span></code></pre><h4 id=\"步骤四：部署执行器项目：\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e5%9b%9b%ef%bc%9a%e9%83%a8%e7%bd%b2%e6%89%a7%e8%a1%8c%e5%99%a8%e9%a1%b9%e7%9b%ae%ef%bc%9a\" data-id=\"步骤四：部署执行器项目：\" class=\"anchor\"><span>步骤四：部署执行器项目：</span></a></h4><p>如果已经正确进行上述配置，可将执行器项目编译打部署，系统提供多种执行器Sample示例项目，选择其中一个即可，各自的部署方式如下。</p><pre v-pre=\"\" data-lang=\"\"><code class=\"lang-\">xxl-job-executor-sample-springboot：项目编译打包成springboot类型的可执行JAR包，命令启动即可；\nxxl-job-executor-sample-spring：项目编译打包成WAR包，并部署到tomcat中。\nxxl-job-executor-sample-jfinal：同上\nxxl-job-executor-sample-nutz：同上</code></pre><p>至此“执行器”项目已经部署结束。</p><h4 id=\"步骤五：执行器集群（可选）：\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e4%ba%94%ef%bc%9a%e6%89%a7%e8%a1%8c%e5%99%a8%e9%9b%86%e7%be%a4%ef%bc%88%e5%8f%af%e9%80%89%ef%bc%89%ef%bc%9a\" data-id=\"步骤五：执行器集群（可选）：\" class=\"anchor\"><span>步骤五：执行器集群（可选）：</span></a></h4><p>执行器支持集群部署，提升调度系统可用性，同时提升任务处理能力。</p><p>执行器集群部署时，几点要求和建议：</p><ul>\n<li>执行器回调地址（xxl.job.admin.addresses）需要保持一致；执行器根据该配置进行执行器自动注册等操作。 </li>\n<li>同一个执行器集群内AppName（xxl.job.executor.appname）需要保持一致；调度中心根据该配置动态发现不同集群的在线执行器列表。</li>\n</ul>\n<h3 id=\"_25-开发第一个任务hello-world\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_25-%e5%bc%80%e5%8f%91%e7%ac%ac%e4%b8%80%e4%b8%aa%e4%bb%bb%e5%8a%a1hello-world\" data-id=\"_25-开发第一个任务hello-world\" class=\"anchor\"><span>2.5 开发第一个任务“Hello World”</span></a></h3><p>本示例以新建一个 “GLUE模式(Java)” 运行模式的任务为例。更多有关任务的详细配置，请查看“章节三：任务详解”。\n（ “GLUE模式(Java)”的执行代码托管到调度中心在线维护，相比“Bean模式任务”需要在执行器项目开发部署上线，更加简便轻量）</p><blockquote>\n<p>前提：请确认“调度中心”和“执行器”项目已经成功部署并启动；</p></blockquote>\n<h4 id=\"步骤一：新建任务：\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e4%b8%80%ef%bc%9a%e6%96%b0%e5%bb%ba%e4%bb%bb%e5%8a%a1%ef%bc%9a\" data-id=\"步骤一：新建任务：\" class=\"anchor\"><span>步骤一：新建任务：</span></a></h4><p>登录调度中心，点击下图所示“新建任务”按钮，新建示例任务。然后，参考下面截图中任务的参数配置，点击保存。</p><p><img src=\"./分布式任务调度平台XXL-JOB_files/img_o8HQ.png\" data-origin=\"https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_o8HQ.png\" alt=\"输入图片说明\" title=\"在这里输入图片标题\"></p><p><img src=\"./分布式任务调度平台XXL-JOB_files/img_ZAsz.png\" data-origin=\"https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_ZAsz.png\" alt=\"输入图片说明\" title=\"在这里输入图片标题\"></p><h4 id=\"步骤二：glue模式java-任务开发：\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e4%ba%8c%ef%bc%9aglue%e6%a8%a1%e5%bc%8fjava-%e4%bb%bb%e5%8a%a1%e5%bc%80%e5%8f%91%ef%bc%9a\" data-id=\"步骤二：glue模式java-任务开发：\" class=\"anchor\"><span>步骤二：“GLUE模式(Java)” 任务开发：</span></a></h4><p>请点击任务右侧 “GLUE” 按钮，进入 “GLUE编辑器开发界面” ，见下图。“GLUE模式(Java)” 运行模式的任务默认已经初始化了示例任务代码，即打印Hello World。\n（ “GLUE模式(Java)” 运行模式的任务实际上是一段继承自IJobHandler的Java类代码，它在执行器项目中运行，可使用@Resource/@Autowire注入执行器里中的其他服务，详细介绍请查看第三章节）</p><p><img src=\"./分布式任务调度平台XXL-JOB_files/img_Fgql.png\" data-origin=\"https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_Fgql.png\" alt=\"输入图片说明\" title=\"在这里输入图片标题\"></p><p><img src=\"./分布式任务调度平台XXL-JOB_files/img_dNUJ.png\" data-origin=\"https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_dNUJ.png\" alt=\"输入图片说明\" title=\"在这里输入图片标题\"></p><h4 id=\"步骤三：触发执行：\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e4%b8%89%ef%bc%9a%e8%a7%a6%e5%8f%91%e6%89%a7%e8%a1%8c%ef%bc%9a\" data-id=\"步骤三：触发执行：\" class=\"anchor\"><span>步骤三：触发执行：</span></a></h4><p>请点击任务右侧 “执行” 按钮，可手动触发一次任务执行（通常情况下，通过配置Cron表达式进行任务调度出发）。</p><h4 id=\"步骤四：查看日志：\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e5%9b%9b%ef%bc%9a%e6%9f%a5%e7%9c%8b%e6%97%a5%e5%bf%97%ef%bc%9a\" data-id=\"步骤四：查看日志：\" class=\"anchor\"><span>步骤四：查看日志：</span></a></h4><p>请点击任务右侧 “日志” 按钮，可前往任务日志界面查看任务日志。\n在任务日志界面中，可查看该任务的历史调度记录以及每一次调度的任务调度信息、执行参数和执行信息。运行中的任务点击右侧的“执行日志”按钮，可进入日志控制台查看实时执行日志。</p><p><img src=\"./分布式任务调度平台XXL-JOB_files/img_inc8.png\" data-origin=\"https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_inc8.png\" alt=\"输入图片说明\" title=\"在这里输入图片标题\"></p><p>在日志控制台，可以Rolling方式实时查看任务在执行器一侧运行输出的日志信息，实时监控任务进度；</p><p><img src=\"./分布式任务调度平台XXL-JOB_files/img_eYrv.png\" data-origin=\"https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_eYrv.png\" alt=\"输入图片说明\" title=\"在这里输入图片标题\"></p><h2 id=\"三、任务详解\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=%e4%b8%89%e3%80%81%e4%bb%bb%e5%8a%a1%e8%af%a6%e8%a7%a3\" data-id=\"三、任务详解\" class=\"anchor\"><span>三、任务详解</span></a></h2><h3 id=\"配置属性详细说明：\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=%e9%85%8d%e7%bd%ae%e5%b1%9e%e6%80%a7%e8%af%a6%e7%bb%86%e8%af%b4%e6%98%8e%ef%bc%9a\" data-id=\"配置属性详细说明：\" class=\"anchor\"><span>配置属性详细说明：</span></a></h3><pre v-pre=\"\" data-lang=\"\"><code class=\"lang-\">- 执行器：任务的绑定的执行器，任务触发调度时将会自动发现注册成功的执行器, 实现任务自动发现功能; 另一方面也可以方便的进行任务分组。每个任务必须绑定一个执行器, 可在 \"执行器管理\" 进行设置;\n- 描述：任务的描述信息，便于任务管理；\n- 路由策略：当执行器集群部署时，提供丰富的路由策略，包括；\n    FIRST（第一个）：固定选择第一个机器；\n    LAST（最后一个）：固定选择最后一个机器；\n    ROUND（轮询）：；\n    RANDOM（随机）：随机选择在线的机器；\n    CONSISTENT_HASH（一致性HASH）：每个任务按照Hash算法固定选择某一台机器，且所有任务均匀散列在不同机器上。\n    LEAST_FREQUENTLY_USED（最不经常使用）：使用频率最低的机器优先被选举；\n    LEAST_RECENTLY_USED（最近最久未使用）：最久为使用的机器优先被选举；\n    FAILOVER（故障转移）：按照顺序依次进行心跳检测，第一个心跳检测成功的机器选定为目标执行器并发起调度；\n    BUSYOVER（忙碌转移）：按照顺序依次进行空闲检测，第一个空闲检测成功的机器选定为目标执行器并发起调度；\n    SHARDING_BROADCAST(分片广播)：广播触发对应集群中所有机器执行一次任务，同时传递分片参数；可根据分片参数开发分片任务；\n\n- Cron：触发任务执行的Cron表达式；\n- 运行模式：\n    BEAN模式：任务以JobHandler方式维护在执行器端；需要结合 \"JobHandler\" 属性匹配执行器中任务；\n    GLUE模式(Java)：任务以源码方式维护在调度中心；该模式的任务实际上是一段继承自IJobHandler的Java类代码并 \"groovy\" 源码方式维护，它在执行器项目中运行，可使用@Resource/@Autowire注入执行器里中的其他服务；\n    GLUE模式(Shell)：任务以源码方式维护在调度中心；该模式的任务实际上是一段 \"shell\" 脚本；\n    GLUE模式(Python)：任务以源码方式维护在调度中心；该模式的任务实际上是一段 \"python\" 脚本；\n    GLUE模式(NodeJS)：任务以源码方式维护在调度中心；该模式的任务实际上是一段 \"nodejs\" 脚本；\n- JobHandler：运行模式为 \"BEAN模式\" 时生效，对应执行器中新开发的JobHandler类“@JobHandler”注解自定义的value值；\n- 子任务：每个任务都拥有一个唯一的任务ID(任务ID可以从任务列表获取)，当本任务执行结束并且执行成功时，将会触发子任务ID所对应的任务的一次主动调度。\n- 阻塞处理策略：调度过于密集执行器来不及处理时的处理策略；\n    单机串行（默认）：调度请求进入单机执行器后，调度请求进入FIFO队列并以串行方式运行；\n    丢弃后续调度：调度请求进入单机执行器后，发现执行器存在运行的调度任务，本次请求将会被丢弃并标记为失败；\n    覆盖之前调度：调度请求进入单机执行器后，发现执行器存在运行的调度任务，将会终止运行中的调度任务并清空队列，然后运行本地调度任务；\n- 失败处理策略；调度失败时的处理策略；\n    失败告警（默认）：调度失败和执行失败时，都将会触发失败报警，默认会发送报警邮件；\n    失败重试：调度失败时，除了进行失败告警之外，将会自动重试一次；注意在执行失败时不会重试，而是根据回调返回值判断是否重试；\n- 执行参数：任务执行所需的参数，多个参数时用逗号分隔，任务执行时将会把多个参数转换成数组传入；\n- 报警邮件：任务调度失败时邮件通知的邮箱地址，支持配置多邮箱地址，配置多个邮箱地址时用逗号分隔；\n- 负责人：任务的负责人；</code></pre><h3 id=\"_31-bean模式\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_31-bean%e6%a8%a1%e5%bc%8f\" data-id=\"_31-bean模式\" class=\"anchor\"><span>3.1 BEAN模式</span></a></h3><p>任务逻辑以JobHandler的形式存在于“执行器”所在项目中，开发流程如下：</p><h4 id=\"步骤一：执行器项目中，开发jobhandler：\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e4%b8%80%ef%bc%9a%e6%89%a7%e8%a1%8c%e5%99%a8%e9%a1%b9%e7%9b%ae%e4%b8%ad%ef%bc%8c%e5%bc%80%e5%8f%91jobhandler%ef%bc%9a\" data-id=\"步骤一：执行器项目中，开发jobhandler：\" class=\"anchor\"><span>步骤一：执行器项目中，开发JobHandler：</span></a></h4><pre v-pre=\"\" data-lang=\"\"><code class=\"lang-\"> - 1、继承\"IJobHandler\"：“com.xxl.job.core.handler.IJobHandler”；\n - 2、注册到Spring容器：添加“@Component”注解，被Spring容器扫描为Bean实例；\n - 3、注册到执行器工厂：添加“@JobHandler(value=\"自定义jobhandler名称\")”注解，注解value值对应的是调度中心新建任务的JobHandler属性的值。\n - 4、执行日志：需要通过 \"XxlJobLogger.log\" 打印执行日志；\n（可参考Sample示例执行器中的DemoJobHandler，见下图）</code></pre><p><img src=\"./分布式任务调度平台XXL-JOB_files/img_oLlM.png\" data-origin=\"https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_oLlM.png\" alt=\"输入图片说明\" title=\"在这里输入图片标题\"></p><h4 id=\"步骤二：调度中心，新建调度任务\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e4%ba%8c%ef%bc%9a%e8%b0%83%e5%ba%a6%e4%b8%ad%e5%bf%83%ef%bc%8c%e6%96%b0%e5%bb%ba%e8%b0%83%e5%ba%a6%e4%bb%bb%e5%8a%a1\" data-id=\"步骤二：调度中心，新建调度任务\" class=\"anchor\"><span>步骤二：调度中心，新建调度任务</span></a></h4><p>参考上文“配置属性详细说明”对新建的任务进行参数配置，运行模式选中 \"BEAN模式\"，JobHandler属性填写任务注解“@JobHandler”中定义的值；</p><p><img src=\"./分布式任务调度平台XXL-JOB_files/img_ZAsz.png\" data-origin=\"https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_ZAsz.png\" alt=\"输入图片说明\" title=\"在这里输入图片标题\"></p><h3 id=\"_32-glue模式java\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_32-glue%e6%a8%a1%e5%bc%8fjava\" data-id=\"_32-glue模式java\" class=\"anchor\"><span>3.2 GLUE模式(Java)</span></a></h3><p>任务以源码方式维护在调度中心，支持通过Web IDE在线更新，实时编译和生效，因此不需要指定JobHandler。开发流程如下：</p><h4 id=\"步骤一：调度中心，新建调度任务：\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e4%b8%80%ef%bc%9a%e8%b0%83%e5%ba%a6%e4%b8%ad%e5%bf%83%ef%bc%8c%e6%96%b0%e5%bb%ba%e8%b0%83%e5%ba%a6%e4%bb%bb%e5%8a%a1%ef%bc%9a\" data-id=\"步骤一：调度中心，新建调度任务：\" class=\"anchor\"><span>步骤一：调度中心，新建调度任务：</span></a></h4><p>参考上文“配置属性详细说明”对新建的任务进行参数配置，运行模式选中 \"GLUE模式(Java)\"；</p><p><img src=\"./分布式任务调度平台XXL-JOB_files/img_tJOq.png\" data-origin=\"https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_tJOq.png\" alt=\"输入图片说明\" title=\"在这里输入图片标题\"></p><h4 id=\"步骤二：开发任务代码：\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e4%ba%8c%ef%bc%9a%e5%bc%80%e5%8f%91%e4%bb%bb%e5%8a%a1%e4%bb%a3%e7%a0%81%ef%bc%9a\" data-id=\"步骤二：开发任务代码：\" class=\"anchor\"><span>步骤二：开发任务代码：</span></a></h4><p>选中指定任务，点击该任务右侧“GLUE”按钮，将会前往GLUE任务的Web IDE界面，在该界面支持对任务代码进行开发（也可以在IDE中开发完成后，复制粘贴到编辑中）。</p><p>版本回溯功能（支持30个版本的版本回溯）：在GLUE任务的Web IDE界面，选择右上角下拉框“版本回溯”，会列出该GLUE的更新历史，选择相应版本即可显示该版本代码，保存后GLUE代码即回退到对应的历史版本；</p><p><img src=\"./分布式任务调度平台XXL-JOB_files/img_dNUJ.png\" data-origin=\"https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_dNUJ.png\" alt=\"输入图片说明\" title=\"在这里输入图片标题\"></p><h3 id=\"_33-glue模式shell\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_33-glue%e6%a8%a1%e5%bc%8fshell\" data-id=\"_33-glue模式shell\" class=\"anchor\"><span>3.3 GLUE模式(Shell)</span></a></h3><h4 id=\"步骤一：调度中心，新建调度任务\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e4%b8%80%ef%bc%9a%e8%b0%83%e5%ba%a6%e4%b8%ad%e5%bf%83%ef%bc%8c%e6%96%b0%e5%bb%ba%e8%b0%83%e5%ba%a6%e4%bb%bb%e5%8a%a1\" data-id=\"步骤一：调度中心，新建调度任务\" class=\"anchor\"><span>步骤一：调度中心，新建调度任务</span></a></h4><p>参考上文“配置属性详细说明”对新建的任务进行参数配置，运行模式选中 \"GLUE模式(Shell)\"；</p><h4 id=\"步骤二：开发任务代码：-1\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e4%ba%8c%ef%bc%9a%e5%bc%80%e5%8f%91%e4%bb%bb%e5%8a%a1%e4%bb%a3%e7%a0%81%ef%bc%9a-1\" data-id=\"步骤二：开发任务代码：-1\" class=\"anchor\"><span>步骤二：开发任务代码：</span></a></h4><p>选中指定任务，点击该任务右侧“GLUE”按钮，将会前往GLUE任务的Web IDE界面，在该界面支持对任务代码进行开发（也可以在IDE中开发完成后，复制粘贴到编辑中）。</p><p>该模式的任务实际上是一段 \"shell\" 脚本；</p><p><img src=\"./分布式任务调度平台XXL-JOB_files/img_iUw0.png\" data-origin=\"https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_iUw0.png\" alt=\"输入图片说明\" title=\"在这里输入图片标题\"></p><h3 id=\"_34-glue模式python\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_34-glue%e6%a8%a1%e5%bc%8fpython\" data-id=\"_34-glue模式python\" class=\"anchor\"><span>3.4 GLUE模式(Python)</span></a></h3><h4 id=\"步骤一：调度中心，新建调度任务-1\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e4%b8%80%ef%bc%9a%e8%b0%83%e5%ba%a6%e4%b8%ad%e5%bf%83%ef%bc%8c%e6%96%b0%e5%bb%ba%e8%b0%83%e5%ba%a6%e4%bb%bb%e5%8a%a1-1\" data-id=\"步骤一：调度中心，新建调度任务-1\" class=\"anchor\"><span>步骤一：调度中心，新建调度任务</span></a></h4><p>参考上文“配置属性详细说明”对新建的任务进行参数配置，运行模式选中 \"GLUE模式(Python)\"；</p><h4 id=\"步骤二：开发任务代码：-2\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e4%ba%8c%ef%bc%9a%e5%bc%80%e5%8f%91%e4%bb%bb%e5%8a%a1%e4%bb%a3%e7%a0%81%ef%bc%9a-2\" data-id=\"步骤二：开发任务代码：-2\" class=\"anchor\"><span>步骤二：开发任务代码：</span></a></h4><p>选中指定任务，点击该任务右侧“GLUE”按钮，将会前往GLUE任务的Web IDE界面，在该界面支持对任务代码进行开发（也可以在IDE中开发完成后，复制粘贴到编辑中）。</p><p>该模式的任务实际上是一段 \"python\" 脚本；</p><p><img src=\"./分布式任务调度平台XXL-JOB_files/img_BPLG.png\" data-origin=\"https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_BPLG.png\" alt=\"输入图片说明\" title=\"在这里输入图片标题\"></p><h3 id=\"_35-glue模式nodejs\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_35-glue%e6%a8%a1%e5%bc%8fnodejs\" data-id=\"_35-glue模式nodejs\" class=\"anchor\"><span>3.5 GLUE模式(NodeJS)</span></a></h3><h4 id=\"步骤一：调度中心，新建调度任务-2\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e4%b8%80%ef%bc%9a%e8%b0%83%e5%ba%a6%e4%b8%ad%e5%bf%83%ef%bc%8c%e6%96%b0%e5%bb%ba%e8%b0%83%e5%ba%a6%e4%bb%bb%e5%8a%a1-2\" data-id=\"步骤一：调度中心，新建调度任务-2\" class=\"anchor\"><span>步骤一：调度中心，新建调度任务</span></a></h4><p>参考上文“配置属性详细说明”对新建的任务进行参数配置，运行模式选中 \"GLUE模式(NodeJS)\"；</p><h4 id=\"步骤二：开发任务代码：-3\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%ad%a5%e9%aa%a4%e4%ba%8c%ef%bc%9a%e5%bc%80%e5%8f%91%e4%bb%bb%e5%8a%a1%e4%bb%a3%e7%a0%81%ef%bc%9a-3\" data-id=\"步骤二：开发任务代码：-3\" class=\"anchor\"><span>步骤二：开发任务代码：</span></a></h4><p>选中指定任务，点击该任务右侧“GLUE”按钮，将会前往GLUE任务的Web IDE界面，在该界面支持对任务代码进行开发（也可以在IDE中开发完成后，复制粘贴到编辑中）。</p><p>该模式的任务实际上是一段 \"nodejS\" 脚本；</p><h2 id=\"四、任务管理\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=%e5%9b%9b%e3%80%81%e4%bb%bb%e5%8a%a1%e7%ae%a1%e7%90%86\" data-id=\"四、任务管理\" class=\"anchor\"><span>四、任务管理</span></a></h2><h3 id=\"_40-配置执行器\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_40-%e9%85%8d%e7%bd%ae%e6%89%a7%e8%a1%8c%e5%99%a8\" data-id=\"_40-配置执行器\" class=\"anchor\"><span>4.0 配置执行器</span></a></h3><p>点击进入\"执行器管理\"界面, 如下图:\n<img src=\"./分布式任务调度平台XXL-JOB_files/img_Hr2T.png\" data-origin=\"https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_Hr2T.png\" alt=\"输入图片说明\" title=\"在这里输入图片标题\"></p><pre v-pre=\"\" data-lang=\"\"><code class=\"lang-\">1、\"调度中心OnLine:\"右侧显示在线的\"调度中心\"列表, 任务执行结束后, 将会以failover的模式进行回调调度中心通知执行结果, 避免回调的单点风险;\n2、\"执行器列表\" 中显示在线的执行器列表, 可通过\"OnLine 机器\"查看对应执行器的集群机器。</code></pre><p>点击按钮 \"+新增执行器\" 弹框如下图, 可新增执行器配置:</p><p><img src=\"./分布式任务调度平台XXL-JOB_files/img_V3vF.png\" data-origin=\"https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_V3vF.png\" alt=\"输入图片说明\" title=\"在这里输入图片标题\"></p><h3 id=\"执行器属性说明\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%89%a7%e8%a1%8c%e5%99%a8%e5%b1%9e%e6%80%a7%e8%af%b4%e6%98%8e\" data-id=\"执行器属性说明\" class=\"anchor\"><span>执行器属性说明</span></a></h3><pre v-pre=\"\" data-lang=\"\"><code class=\"lang-\">AppName: 是每个执行器集群的唯一标示AppName, 执行器会周期性以AppName为对象进行自动注册。可通过该配置自动发现注册成功的执行器, 供任务调度时使用;\n名称: 执行器的名称, 因为AppName限制字母数字等组成,可读性不强, 名称为了提高执行器的可读性;\n排序: 执行器的排序, 系统中需要执行器的地方,如任务新增, 将会按照该排序读取可用的执行器列表;\n注册方式：调度中心获取执行器地址的方式；\n    自动注册：执行器自动进行执行器注册，调度中心通过底层注册表可以动态发现执行器机器地址；\n    手动录入：人工手动录入执行器的地址信息，多地址逗号分隔，供调度中心使用；\n机器地址：\"注册方式\"为\"手动录入\"时有效，支持人工维护执行器的地址信息；</code></pre><h3 id=\"_41-新建任务\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_41-%e6%96%b0%e5%bb%ba%e4%bb%bb%e5%8a%a1\" data-id=\"_41-新建任务\" class=\"anchor\"><span>4.1 新建任务</span></a></h3><p>进入任务管理界面，点击“新增任务”按钮，在弹出的“新增任务”界面配置任务属性后保存即可。详情页参考章节 \"三、任务详解\"。</p><h3 id=\"_42-编辑任务\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_42-%e7%bc%96%e8%be%91%e4%bb%bb%e5%8a%a1\" data-id=\"_42-编辑任务\" class=\"anchor\"><span>4.2 编辑任务</span></a></h3><p>进入任务管理界面，选中指定任务。点击该任务右侧“编辑”按钮，在弹出的“编辑任务”界面更新任务属性后保存即可，可以修改设置的任务属性信息：</p><h3 id=\"_43-编辑glue代码\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_43-%e7%bc%96%e8%be%91glue%e4%bb%a3%e7%a0%81\" data-id=\"_43-编辑glue代码\" class=\"anchor\"><span>4.3 编辑GLUE代码</span></a></h3><p>该操作仅针对GLUE任务。</p><p>选中指定任务，点击该任务右侧“GLUE”按钮，将会前往GLUE任务的Web IDE界面，在该界面支持对任务代码进行开发。可参考章节 \"3.2 GLUE模式(Java)\"。</p><h3 id=\"_44-暂停恢复任务\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_44-%e6%9a%82%e5%81%9c%e6%81%a2%e5%a4%8d%e4%bb%bb%e5%8a%a1\" data-id=\"_44-暂停恢复任务\" class=\"anchor\"><span>4.4 暂停/恢复任务</span></a></h3><p>可对任务进行“暂停”和“恢复”操作。\n需要注意的是，此处的暂停/恢复仅针对任务的后续调度触发行为，不会影响到已经触发的调度任务，如需终止已经触发的调度任务，可查看“4.8 终止运行中的任务”</p><p><img src=\"./分布式任务调度平台XXL-JOB_files/img_ZAhX.png\" data-origin=\"https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_ZAhX.png\" alt=\"输入图片说明\" title=\"在这里输入图片标题\"></p><h3 id=\"_45-手动触发一次调度\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_45-%e6%89%8b%e5%8a%a8%e8%a7%a6%e5%8f%91%e4%b8%80%e6%ac%a1%e8%b0%83%e5%ba%a6\" data-id=\"_45-手动触发一次调度\" class=\"anchor\"><span>4.5 手动触发一次调度</span></a></h3><p>点击“执行”按钮，可手动触发一次任务调度，不影响原有调度规则。</p><p><img src=\"./分布式任务调度平台XXL-JOB_files/img_Z5wp.png\" data-origin=\"https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_Z5wp.png\" alt=\"输入图片说明\" title=\"在这里输入图片标题\"></p><h3 id=\"_46-查看调度日志\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_46-%e6%9f%a5%e7%9c%8b%e8%b0%83%e5%ba%a6%e6%97%a5%e5%bf%97\" data-id=\"_46-查看调度日志\" class=\"anchor\"><span>4.6 查看调度日志</span></a></h3><p>点击“日志”按钮，可以查看任务历史调度日志。在历史调入日志界面可查看每次任务调度的调度结果、执行结果等，点击“执行日志”按钮可查看执行器完整日志。</p><p><img src=\"./分布式任务调度平台XXL-JOB_files/img_9235.png\" data-origin=\"https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_9235.png\" alt=\"输入图片说明\" title=\"在这里输入图片标题\"></p><p><img src=\"./分布式任务调度平台XXL-JOB_files/img_UDSo.png\" data-origin=\"https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_UDSo.png\" alt=\"输入图片说明\" title=\"在这里输入图片标题\"></p><pre v-pre=\"\" data-lang=\"\"><code class=\"lang-\">调度时间：\"调度中心\"触发本次调度并向\"执行器\"发送任务执行信号的时间；\n调度结果：\"调度中心\"触发本次调度的结果，200表示成功，500或其他表示失败；\n调度备注：\"调度中心\"触发本次调度的日志信息；\n执行器地址：本次任务执行的机器地址\n运行模式：触发调度时任务的运行模式，运行模式可参考章节 \"三、任务详解\"；\n任务参数：本地任务执行的入参\n执行时间：\"执行器\"中本次任务执行结束后回调的时间；\n执行结果：\"执行器\"中本次任务执行的结果，200表示成功，500或其他表示失败；\n执行备注：\"执行器\"中本次任务执行的日志信息；\n操作：\n    \"执行日志\"按钮：点击可查看本地任务执行的详细日志信息；详见“4.7 查看执行日志”；\n    \"终止任务\"按钮：点击可终止本地调度对应执行器上本任务的执行线程，包括未执行的阻塞任务一并被终止；</code></pre><h3 id=\"_47-查看执行日志\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_47-%e6%9f%a5%e7%9c%8b%e6%89%a7%e8%a1%8c%e6%97%a5%e5%bf%97\" data-id=\"_47-查看执行日志\" class=\"anchor\"><span>4.7 查看执行日志</span></a></h3><p>点击执行日志右侧的 “执行日志” 按钮，可跳转至执行日志界面，可以查看业务代码中打印的完整日志，如下图；</p><p><img src=\"./分布式任务调度平台XXL-JOB_files/img_tvGI.png\" data-origin=\"https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_tvGI.png\" alt=\"输入图片说明\" title=\"在这里输入图片标题\"></p><h3 id=\"_48-终止运行中的任务\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_48-%e7%bb%88%e6%ad%a2%e8%bf%90%e8%a1%8c%e4%b8%ad%e7%9a%84%e4%bb%bb%e5%8a%a1\" data-id=\"_48-终止运行中的任务\" class=\"anchor\"><span>4.8 终止运行中的任务</span></a></h3><p>仅针对执行中的任务。\n在任务日志界面，点击右侧的“终止任务”按钮，将会向本次任务对应的执行器发送任务终止请求，将会终止掉本次任务，同时会清空掉整个任务执行队列。</p><p><img src=\"./分布式任务调度平台XXL-JOB_files/img_hIci.png\" data-origin=\"https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_hIci.png\" alt=\"输入图片说明\" title=\"在这里输入图片标题\"></p><p>任务终止时通过 \"interrupt\" 执行线程的方式实现, 将会触发 \"InterruptedException\" 异常。因此如果JobHandler内部catch到了该异常并消化掉的话, 任务终止功能将不可用。</p><p>因此, 如果遇到上述任务终止不可用的情况, 需要在JobHandler中应该针对 \"InterruptedException\" 异常进行特殊处理 (向上抛出) , 正确逻辑如下:</p><pre v-pre=\"\" data-lang=\"\"><code class=\"lang-\">try{\n    // TODO\n} catch (Exception e) {\n    if (e instanceof InterruptedException) {\n        throw e;\n    }\n    logger.warn(\"{}\", e);\n}</code></pre><p>而且，在JobHandler中开启子线程时，子线程也不可catch处理\"InterruptedException\"，应该主动向上抛出。</p><h3 id=\"_49-删除执行日志\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_49-%e5%88%a0%e9%99%a4%e6%89%a7%e8%a1%8c%e6%97%a5%e5%bf%97\" data-id=\"_49-删除执行日志\" class=\"anchor\"><span>4.9 删除执行日志</span></a></h3><p>在任务日志界面，选中执行器和任务之后，点击右侧的\"删除\"按钮将会出现\"日志清理\"弹框，弹框中支持选择不同类型的日志清理策略，选中后点击\"确定\"按钮即可进行日志清理操作；\n<img src=\"./分布式任务调度平台XXL-JOB_files/img_Ypik.png\" data-origin=\"https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_Ypik.png\" alt=\"输入图片说明\" title=\"在这里输入图片标题\"></p><p><img src=\"./分布式任务调度平台XXL-JOB_files/img_EB65.png\" data-origin=\"https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_EB65.png\" alt=\"输入图片说明\" title=\"在这里输入图片标题\"></p><h3 id=\"_410-删除任务\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_410-%e5%88%a0%e9%99%a4%e4%bb%bb%e5%8a%a1\" data-id=\"_410-删除任务\" class=\"anchor\"><span>4.10 删除任务</span></a></h3><p>点击删除按钮，可以删除对应任务。</p><p><img src=\"./分布式任务调度平台XXL-JOB_files/img_Z9Qr.png\" data-origin=\"https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_Z9Qr.png\" alt=\"输入图片说明\" title=\"在这里输入图片标题\"></p><h2 id=\"五、总体设计\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=%e4%ba%94%e3%80%81%e6%80%bb%e4%bd%93%e8%ae%be%e8%ae%a1\" data-id=\"五、总体设计\" class=\"anchor\"><span>五、总体设计</span></a></h2><h3 id=\"_51-源码目录介绍\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_51-%e6%ba%90%e7%a0%81%e7%9b%ae%e5%bd%95%e4%bb%8b%e7%bb%8d\" data-id=\"_51-源码目录介绍\" class=\"anchor\"><span>5.1 源码目录介绍</span></a></h3><pre v-pre=\"\" data-lang=\"\"><code class=\"lang-\">- /doc :文档资料\n- /db :“调度数据库”建表脚本\n- /xxl-job-admin :调度中心，项目源码\n- /xxl-job-core :公共Jar依赖\n- /xxl-job-executor-samples :执行器，Sample示例项目（大家可以在该项目上进行开发，也可以将现有项目改造生成执行器项目）</code></pre><h3 id=\"_52-调度数据库配置\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_52-%e8%b0%83%e5%ba%a6%e6%95%b0%e6%8d%ae%e5%ba%93%e9%85%8d%e7%bd%ae\" data-id=\"_52-调度数据库配置\" class=\"anchor\"><span>5.2 “调度数据库”配置</span></a></h3><p>XXL-JOB调度模块基于Quartz集群实现，其“调度数据库”是在Quartz的11张集群mysql表基础上扩展而成。</p><p>XXL-JOB首先定制了Quartz原生表结构前缀（XXL_JOB<em>QRTZ</em>）。</p><p><img src=\"./分布式任务调度平台XXL-JOB_files/img_bNwm.png\" data-origin=\"https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_bNwm.png\" alt=\"输入图片说明\" title=\"在这里输入图片标题\"></p><p>然后，在此基础上新增了几张张扩展表，如下：</p><pre v-pre=\"\" data-lang=\"\"><code class=\"lang-\">- XXL_JOB_QRTZ_TRIGGER_GROUP：执行器信息表，维护任务执行器信息；\n- XXL_JOB_QRTZ_TRIGGER_REGISTRY：执行器注册表，维护在线的执行器和调度中心机器地址信息；\n- XXL_JOB_QRTZ_TRIGGER_INFO：调度扩展信息表： 用于保存XXL-JOB调度任务的扩展信息，如任务分组、任务名、机器地址、执行器、执行入参和报警邮件等等；\n- XXL_JOB_QRTZ_TRIGGER_LOG：调度日志表： 用于保存XXL-JOB任务调度的历史信息，如调度结果、执行结果、调度入参、调度机器和执行器等等；\n- XXL_JOB_QRTZ_TRIGGER_LOGGLUE：任务GLUE日志：用于保存GLUE更新历史，用于支持GLUE的版本回溯功能；</code></pre><p>因此，XXL-JOB调度数据库共计用于16张数据库表。</p><h3 id=\"_53-架构设计\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_53-%e6%9e%b6%e6%9e%84%e8%ae%be%e8%ae%a1\" data-id=\"_53-架构设计\" class=\"anchor\"><span>5.3 架构设计</span></a></h3><h4 id=\"_531-设计思想\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_531-%e8%ae%be%e8%ae%a1%e6%80%9d%e6%83%b3\" data-id=\"_531-设计思想\" class=\"anchor\"><span>5.3.1 设计思想</span></a></h4><p>将调度行为抽象形成“调度中心”公共平台，而平台自身并不承担业务逻辑，“调度中心”负责发起调度请求。</p><p>将任务抽象成分散的JobHandler，交由“执行器”统一管理，“执行器”负责接收调度请求并执行对应的JobHandler中业务逻辑。</p><p>因此，“调度”和“任务”两部分可以相互解耦，提高系统整体稳定性和扩展性；</p><h4 id=\"_532-系统组成\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_532-%e7%b3%bb%e7%bb%9f%e7%bb%84%e6%88%90\" data-id=\"_532-系统组成\" class=\"anchor\"><span>5.3.2 系统组成</span></a></h4><ul>\n<li><strong>调度模块（调度中心）</strong>：\n  负责管理调度信息，按照调度配置发出调度请求，自身不承担业务代码。调度系统与任务解耦，提高了系统可用性和稳定性，同时调度系统性能不再受限于任务模块；\n  支持可视化、简单且动态的管理调度信息，包括任务新建，更新，删除，GLUE开发和任务报警等，所有上述操作都会实时生效，同时支持监控调度结果以及执行日志，支持执行器Failover。</li>\n<li><strong>执行模块（执行器）</strong>：\n  负责接收调度请求并执行任务逻辑。任务模块专注于任务的执行等操作，开发和维护更加简单和高效；\n  接收“调度中心”的执行请求、终止请求和日志请求等。</li>\n</ul>\n<h4 id=\"_533-架构图\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_533-%e6%9e%b6%e6%9e%84%e5%9b%be\" data-id=\"_533-架构图\" class=\"anchor\"><span>5.3.3 架构图</span></a></h4><p><img src=\"./分布式任务调度平台XXL-JOB_files/img_Qohm.png\" data-origin=\"https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_Qohm.png\" alt=\"输入图片说明\" title=\"在这里输入图片标题\"></p><h3 id=\"_54-调度模块剖析\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_54-%e8%b0%83%e5%ba%a6%e6%a8%a1%e5%9d%97%e5%89%96%e6%9e%90\" data-id=\"_54-调度模块剖析\" class=\"anchor\"><span>5.4 调度模块剖析</span></a></h3><h4 id=\"_541-quartz的不足\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_541-quartz%e7%9a%84%e4%b8%8d%e8%b6%b3\" data-id=\"_541-quartz的不足\" class=\"anchor\"><span>5.4.1 quartz的不足</span></a></h4><p>Quartz作为开源作业调度中的佼佼者，是作业调度的首选。但是集群环境中Quartz采用API的方式对任务进行管理，从而可以避免上述问题，但是同样存在以下问题：</p><ul>\n<li>问题一：调用API的的方式操作任务，不人性化；</li>\n<li>问题二：需要持久化业务QuartzJobBean到底层数据表中，系统侵入性相当严重。</li>\n<li>问题三：调度逻辑和QuartzJobBean耦合在同一个项目中，这将导致一个问题，在调度任务数量逐渐增多，同时调度任务逻辑逐渐加重的情况加，此时调度系统的性能将大大受限于业务；</li>\n<li>问题四：quartz底层以“抢占式”获取DB锁并由抢占成功节点负责运行任务，会导致节点负载悬殊非常大；而XXL-JOB通过执行器实现“协同分配式”运行任务，充分发挥集群优势，负载各节点均衡。</li>\n</ul>\n<p>XXL-JOB弥补了quartz的上述不足之处。</p><h4 id=\"_542-remotehttpjobbean\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_542-remotehttpjobbean\" data-id=\"_542-remotehttpjobbean\" class=\"anchor\"><span>5.4.2 RemoteHttpJobBean</span></a></h4><p>常规Quartz的开发，任务逻辑一般维护在QuartzJobBean中，耦合很严重。XXL-JOB中“调度模块”和“任务模块”完全解耦，调度模块中的所有调度任务使用同一个QuartzJobBean，即RemoteHttpJobBean。不同的调度任务将各自参数维护在各自扩展表数据中，当触发RemoteHttpJobBean执行时，将会解析不同的任务参数发起远程调用，调用各自的远程执行器服务。</p><p>这种调用模型类似RPC调用，RemoteHttpJobBean提供调用代理的功能，而执行器提供远程服务的功能。</p><h4 id=\"_543-调度中心ha（集群）\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_543-%e8%b0%83%e5%ba%a6%e4%b8%ad%e5%bf%83ha%ef%bc%88%e9%9b%86%e7%be%a4%ef%bc%89\" data-id=\"_543-调度中心ha（集群）\" class=\"anchor\"><span>5.4.3 调度中心HA（集群）</span></a></h4><p>基于Quartz的集群方案，数据库选用Mysql；集群分布式并发环境中使用QUARTZ定时任务调度，会在各个节点会上报任务，存到数据库中，执行时会从数据库中取出触发器来执行，如果触发器的名称和执行时间相同，则只有一个节点去执行此任务。</p><pre v-pre=\"\" data-lang=\"\"><code class=\"lang-\"># for cluster\norg.quartz.jobStore.tablePrefix = XXL_JOB_QRTZ_\norg.quartz.scheduler.instanceId: AUTO\norg.quartz.jobStore.class: org.quartz.impl.jdbcjobstore.JobStoreTX\norg.quartz.jobStore.isClustered: true\norg.quartz.jobStore.clusterCheckinInterval: 1000</code></pre><h4 id=\"_544-调度线程池\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_544-%e8%b0%83%e5%ba%a6%e7%ba%bf%e7%a8%8b%e6%b1%a0\" data-id=\"_544-调度线程池\" class=\"anchor\"><span>5.4.4 调度线程池</span></a></h4><p>调度采用线程池方式实现，避免单线程因阻塞而引起任务调度延迟。</p><pre v-pre=\"\" data-lang=\"\"><code class=\"lang-\">org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool\norg.quartz.threadPool.threadCount: 15\norg.quartz.threadPool.threadPriority: 5\norg.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true</code></pre><p>XXL-JOB系统中业务逻辑在远程执行器执行，全异步化设计，调度中心每次触发调度时仅发送一次调度请求，执行器会将请求存入执行队列并且立即响应调度中心，异步运行；相比直接在quartz的QuartzJobBean中执行业务逻辑，极大的降低了调度线程占用时间；</p><p>XXL-JOB调度中心中每个JOB逻辑非常 “轻”，单个JOB一次运行平均耗时基本在 \"10ms\" 之内（基本为一次请求的网络开销）；因此，可以保证使用有限的线程支撑大量的JOB并发运行；</p><p>理论支撑任务量公式如下：</p><pre v-pre=\"\" data-lang=\"\"><code class=\"lang-\">理论支撑任务量 = 线程数配置 / 平均调度频率（每秒） * 平均触发耗时（单位s）</code></pre><p>理论上采用推荐机器配置 \"4核4G内存\" + \"配置1s运行1次密集任务\" + \"调度中心与执行器ping延迟10ms（0.01s）\" 的情况下，</p><pre v-pre=\"\" data-lang=\"\"><code class=\"lang-\">- 单线程支撑任务量  ：1 / 1 * 0.01 = 100个任务\n- 15个线程支撑任务量：15 / 1 * 0.01 = 1500个任务</code></pre><p>实际场景中，由于调度中心与执行器ping延迟不同、DB读写耗时不同、任务调度密集程度不同，会导致任务量上限会上下波动。</p><p>如若需要支撑更多的任务量，可以通过 \"调大调度线程数\" 、\"降低调度中心与执行器ping延迟\" 和 \"提升机器配置\" 几种方式实现。</p><h4 id=\"_545-disallowconcurrentexecution\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_545-disallowconcurrentexecution\" data-id=\"_545-disallowconcurrentexecution\" class=\"anchor\"><span>5.4.5 @DisallowConcurrentExecution</span></a></h4><p>XXL-JOB调度模块的“调度中心”默认不使用该注解，即默认开启并行机制，因为RemoteHttpJobBean为公共QuartzJobBean，这样在多线程调度的情况下，调度模块被阻塞的几率很低，大大提高了调度系统的承载量。</p><p>XXL-JOB的每个调度任务虽然在调度模块是并行调度执行的，但是任务调度传递到任务模块的“执行器”确实串行执行的，同时支持任务终止。</p><h4 id=\"_546-misfire\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_546-misfire\" data-id=\"_546-misfire\" class=\"anchor\"><span>5.4.6 misfire</span></a></h4><p>错过了触发时间，处理规则。\n可能原因：服务重启；调度线程被QuartzJobBean阻塞，线程被耗尽；某个任务启用了@DisallowConcurrentExecution，上次调度持续阻塞，下次调度被错过；</p><p>quartz.properties中关于misfire的阀值配置如下，单位毫秒：</p><pre v-pre=\"\" data-lang=\"\"><code class=\"lang-\">org.quartz.jobStore.misfireThreshold: 60000</code></pre><p>Misfire规则：\n    withMisfireHandlingInstructionDoNothing：不触发立即执行，等待下次调度；\n    withMisfireHandlingInstructionIgnoreMisfires：以错过的第一个频率时间立刻开始执行；\n    withMisfireHandlingInstructionFireAndProceed：以当前时间为触发频率立刻触发一次执行；</p><p>XXL-JOB默认misfire规则为：withMisfireHandlingInstructionDoNothing</p><pre v-pre=\"\" data-lang=\"\"><code class=\"lang-\">CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(jobInfo.getJobCron()).withMisfireHandlingInstructionDoNothing();\nCronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withSchedule(cronScheduleBuilder).build();</code></pre><h4 id=\"_547-日志回调服务\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_547-%e6%97%a5%e5%bf%97%e5%9b%9e%e8%b0%83%e6%9c%8d%e5%8a%a1\" data-id=\"_547-日志回调服务\" class=\"anchor\"><span>5.4.7 日志回调服务</span></a></h4><p>调度模块的“调度中心”作为Web服务部署时，一方面承担调度中心功能，另一方面也为执行器提供API服务。</p><p>调度中心提供的\"日志回调服务API服务\"代码位置如下：</p><pre v-pre=\"\" data-lang=\"\"><code class=\"lang-\">xxl-job-admin#com.xxl.job.admin.controller.JobApiController.callback</code></pre><p>“执行器”在接收到任务执行请求后，执行任务，在执行结束之后会将执行结果回调通知“调度中心”：</p><h4 id=\"_548-任务ha（failover）\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_548-%e4%bb%bb%e5%8a%a1ha%ef%bc%88failover%ef%bc%89\" data-id=\"_548-任务ha（failover）\" class=\"anchor\"><span>5.4.8 任务HA（Failover）</span></a></h4><p>执行器如若集群部署，调度中心将会感知到在线的所有执行器，如“127.0.0.1:9997, 127.0.0.1:9998, 127.0.0.1:9999”。</p><p>当任务\"路由策略\"选择\"故障转移(FAILOVER)\"时，当调度中心每次发起调度请求时，会按照顺序对执行器发出心跳检测请求，第一个检测为存活状态的执行器将会被选定并发送调度请求。</p><p>调度成功后，可在日志监控界面查看“调度备注”，如下；\n<img src=\"./分布式任务调度平台XXL-JOB_files/img_jrdI.png\" data-origin=\"https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_jrdI.png\" alt=\"输入图片说明\" title=\"在这里输入图片标题\"></p><p>“调度备注”可以看出本地调度运行轨迹，执行器的\"注册方式\"、\"地址列表\"和任务的\"路由策略\"。\"故障转移(FAILOVER)\"路由策略下，调度中心首先对第一个地址进行心跳检测，心跳失败因此自动跳过，第二个依然心跳检测失败……\n直至心跳检测第三个地址“127.0.0.1:9999”成功，选定为“目标执行器”；然后对“目标执行器”发送调度请求，调度流程结束，等待执行器回调执行结果。</p><h4 id=\"_549-调度日志\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_549-%e8%b0%83%e5%ba%a6%e6%97%a5%e5%bf%97\" data-id=\"_549-调度日志\" class=\"anchor\"><span>5.4.9 调度日志</span></a></h4><p>调度中心每次进行任务调度，都会记录一条任务日志，任务日志主要包括以下三部分内容：</p><ul>\n<li>任务信息：包括“执行器地址”、“JobHandler”和“执行参数”等属性，点击任务ID按钮可查看，根据这些参数，可以精确的定位任务执行的具体机器和任务代码；</li>\n<li>调度信息：包括“调度时间”、“调度结果”和“调度日志”等，根据这些参数，可以了解“调度中心”发起调度请求时具体情况。</li>\n<li>执行信息：包括“执行时间”、“执行结果”和“执行日志”等，根据这些参数，可以了解在“执行器”端任务执行的具体情况；</li>\n</ul>\n<p>调度日志，针对单次调度，属性说明如下：</p><ul>\n<li>执行器地址：任务执行的机器地址；</li>\n<li>JobHandler：Bean模式表示任务执行的JobHandler名称；</li>\n<li>任务参数：任务执行的入参；</li>\n<li>调度时间：调度中心，发起调度的时间；</li>\n<li>调度结果：调度中心，发起调度的结果，SUCCESS或FAIL；</li>\n<li>调度备注：调度中心，发起调度的备注信息，如地址心跳检测日志等；</li>\n<li>执行时间：执行器，任务执行结束后回调的时间；</li>\n<li>执行结果：执行器，任务执行的结果，SUCCESS或FAIL；</li>\n<li>执行备注：执行器，任务执行的备注信息，如异常日志等；</li>\n<li>执行日志：任务执行过程中，业务代码中打印的完整执行日志，见“4.7 查看执行日志”；</li>\n</ul>\n<h4 id=\"_5410-任务依赖\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_5410-%e4%bb%bb%e5%8a%a1%e4%be%9d%e8%b5%96\" data-id=\"_5410-任务依赖\" class=\"anchor\"><span>5.4.10 任务依赖</span></a></h4><p>原理：XXL-JOB中每个任务都对应有一个任务ID，同时，每个任务支持设置属性“子任务ID”，因此，通过“任务ID”可以匹配任务依赖关系。</p><p>当父任务执行结束并且执行成功时，将会根据“子任务ID”匹配子任务依赖，如果匹配到子任务，将会主动触发一次子任务的执行。</p><p>在任务日志界面，点击任务的“执行备注”的“查看”按钮，可以看到匹配子任务以及触发子任务执行的日志信息，如无信息则表示未触发子任务执行，可参考下图。</p><p><img src=\"./分布式任务调度平台XXL-JOB_files/img_Wb2o.png\" data-origin=\"https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_Wb2o.png\" alt=\"输入图片说明\" title=\"在这里输入图片标题\"></p><p><img src=\"./分布式任务调度平台XXL-JOB_files/img_jOAU.png\" data-origin=\"https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_jOAU.png\" alt=\"输入图片说明\" title=\"在这里输入图片标题\"></p><h3 id=\"_55-任务-quot运行模式quot-剖析\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_55-%e4%bb%bb%e5%8a%a1-quot%e8%bf%90%e8%a1%8c%e6%a8%a1%e5%bc%8fquot-%e5%89%96%e6%9e%90\" data-id=\"_55-任务-quot运行模式quot-剖析\" class=\"anchor\"><span>5.5 任务 \"运行模式\" 剖析</span></a></h3><h4 id=\"_551-quotbean模式quot-任务\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_551-quotbean%e6%a8%a1%e5%bc%8fquot-%e4%bb%bb%e5%8a%a1\" data-id=\"_551-quotbean模式quot-任务\" class=\"anchor\"><span>5.5.1 \"Bean模式\" 任务</span></a></h4><p>开发步骤：可参考 \"章节三\" ；\n原理：每个Bean模式任务都是一个Spring的Bean类实例，它被维护在“执行器”项目的Spring容器中。任务类需要加“@JobHandler(value=\"名称\")”注解，因为“执行器”会根据该注解识别Spring容器中的任务。任务类需要继承统一接口“IJobHandler”，任务逻辑在execute方法中开发，因为“执行器”在接收到调度中心的调度请求时，将会调用“IJobHandler”的execute方法，执行任务逻辑。</p><h4 id=\"_552-quotglue模式javaquot-任务\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_552-quotglue%e6%a8%a1%e5%bc%8fjavaquot-%e4%bb%bb%e5%8a%a1\" data-id=\"_552-quotglue模式javaquot-任务\" class=\"anchor\"><span>5.5.2 \"GLUE模式(Java)\" 任务</span></a></h4><p>开发步骤：可参考 \"章节三\" ；\n原理：每个 \"GLUE模式(Java)\" 任务的代码，实际上是“一个继承自“IJobHandler”的实现类的类代码”，“执行器”接收到“调度中心”的调度请求时，会通过Groovy类加载器加载此代码，实例化成Java对象，同时注入此代码中声明的Spring服务（请确保Glue代码中的服务和类引用在“执行器”项目中存在），然后调用该对象的execute方法，执行任务逻辑。</p><h4 id=\"_553-glue模式shell-glue模式python-glue模式nodejs\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_553-glue%e6%a8%a1%e5%bc%8fshell-glue%e6%a8%a1%e5%bc%8fpython-glue%e6%a8%a1%e5%bc%8fnodejs\" data-id=\"_553-glue模式shell-glue模式python-glue模式nodejs\" class=\"anchor\"><span>5.5.3 GLUE模式(Shell) + GLUE模式(Python) + GLUE模式(NodeJS)</span></a></h4><p>开发步骤：可参考 \"章节三\" ；\n原理：脚本任务的源码托管在调度中心，脚本逻辑在执行器运行。当触发脚本任务时，执行器会加载脚本源码在执行器机器上生成一份脚本文件，然后通过Java代码调用该脚本；并且实时将脚本输出日志写到任务日志文件中，从而在调度中心可以实时监控脚本运行情况；</p><p>目前支持的脚本类型如下：</p><pre v-pre=\"\" data-lang=\"\"><code class=\"lang-\">- shell脚本：任务运行模式选择为 \"GLUE模式(Shell)\"时支持 \"shell\" 脚本任务；\n- python脚本：任务运行模式选择为 \"GLUE模式(Python)\"时支持 \"python\" 脚本任务；\n- nodejs脚本：务运行模式选择为 \"GLUE模式(NodeJS)\"时支持 \"nodejs\" 脚本任务；</code></pre><p>脚本任务通过 Exit Code 判断任务执行结果，状态码可参考章节 \"5.15 任务执行结果说明\"；</p><h4 id=\"_554-执行器\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_554-%e6%89%a7%e8%a1%8c%e5%99%a8\" data-id=\"_554-执行器\" class=\"anchor\"><span>5.5.4 执行器</span></a></h4><p>执行器实际上是一个内嵌的Jetty服务器，默认端口9999（配置项：xxl.job.executor.port）。</p><p>在项目启动时，执行器会通过“@JobHandler”识别Spring容器中“Bean模式任务”，以注解的value属性为key管理起来。</p><p>“执行器”接收到“调度中心”的调度请求时，如果任务类型为“Bean模式”，将会匹配Spring容器中的“Bean模式任务”，然后调用其execute方法，执行任务逻辑。如果任务类型为“GLUE模式”，将会加载GLue代码，实例化Java对象，注入依赖的Spring服务（注意：Glue代码中注入的Spring服务，必须存在与该“执行器”项目的Spring容器中），然后调用execute方法，执行任务逻辑。</p><h4 id=\"_555-任务日志\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_555-%e4%bb%bb%e5%8a%a1%e6%97%a5%e5%bf%97\" data-id=\"_555-任务日志\" class=\"anchor\"><span>5.5.5 任务日志</span></a></h4><p>XXL-JOB会为每次调度请求生成一个单独的日志文件，需要通过 \"XxlJobLogger.log\" 打印执行日志，“调度中心”查看执行日志时将会加载对应的日志文件。</p><p>(历史版本通过重写LOG4J的Appender实现，存在依赖限制，该方式在新版本已经被抛弃)</p><p>日志文件存放的位置可在“执行器”配置文件进行自定义，默认目录格式为：/data/applogs/xxl-job/jobhandler/“格式化日期”/“数据库调度日志记录的主键ID.log”。</p><p>在JobHandler中开启子线程时，子线程将会将会把日志打印在父线程即JobHandler的执行日志中，方便日志追踪。</p><h3 id=\"_56-通讯模块剖析\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_56-%e9%80%9a%e8%ae%af%e6%a8%a1%e5%9d%97%e5%89%96%e6%9e%90\" data-id=\"_56-通讯模块剖析\" class=\"anchor\"><span>5.6 通讯模块剖析</span></a></h3><h4 id=\"_561-一次完整的任务调度通讯流程\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_561-%e4%b8%80%e6%ac%a1%e5%ae%8c%e6%95%b4%e7%9a%84%e4%bb%bb%e5%8a%a1%e8%b0%83%e5%ba%a6%e9%80%9a%e8%ae%af%e6%b5%81%e7%a8%8b\" data-id=\"_561-一次完整的任务调度通讯流程\" class=\"anchor\"><span>5.6.1 一次完整的任务调度通讯流程</span></a></h4><pre v-pre=\"\" data-lang=\"\"><code class=\"lang-\">- 1、“调度中心”向“执行器”发送http调度请求: “执行器”中接收请求的服务，实际上是一台内嵌jetty服务器，默认端口9999;\n- 2、“执行器”执行任务逻辑；\n- 3、“执行器”http回调“调度中心”调度结果: “调度中心”中接收回调的服务，是针对执行器开放一套API服务;</code></pre><h4 id=\"_562-通讯数据加密\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_562-%e9%80%9a%e8%ae%af%e6%95%b0%e6%8d%ae%e5%8a%a0%e5%af%86\" data-id=\"_562-通讯数据加密\" class=\"anchor\"><span>5.6.2 通讯数据加密</span></a></h4><p>调度中心向执行器发送的调度请求时使用RequestModel和ResponseModel两个对象封装调度请求参数和响应数据, 在进行通讯之前底层会将上述两个对象对象序列化，并进行数据协议以及时间戳检验,从而达到数据加密的功能;</p><h3 id=\"_57-任务注册-任务自动发现\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_57-%e4%bb%bb%e5%8a%a1%e6%b3%a8%e5%86%8c-%e4%bb%bb%e5%8a%a1%e8%87%aa%e5%8a%a8%e5%8f%91%e7%8e%b0\" data-id=\"_57-任务注册-任务自动发现\" class=\"anchor\"><span>5.7 任务注册, 任务自动发现</span></a></h3><p>自v1.5版本之后, 任务取消了\"任务执行机器\"属性, 改为通过任务注册和自动发现的方式, 动态获取远程执行器地址并执行。</p><pre v-pre=\"\" data-lang=\"\"><code class=\"lang-\">AppName: 每个执行器机器集群的唯一标示, 任务注册以 \"执行器\" 为最小粒度进行注册; 每个任务通过其绑定的执行器可感知对应的执行器机器列表;\n注册表: 见\"XXL_JOB_QRTZ_TRIGGER_REGISTRY\"表, \"执行器\" 在进行任务注册时将会周期性维护一条注册记录，即机器地址和AppName的绑定关系; \"调度中心\" 从而可以动态感知每个AppName在线的机器列表;\n执行器注册: 任务注册Beat周期默认30s; 执行器以一倍Beat进行执行器注册, 调度中心以一倍Beat进行动态任务发现; 注册信息的失效时间被三倍Beat; \n执行器注册摘除：执行器销毁时，将会主动上报调度中心并摘除对应的执行器机器信息，提高心跳注册的实时性；</code></pre><p>为保证系统\"轻量级\"并且降低学习部署成本，没有采用Zookeeper作为注册中心，采用DB方式进行任务注册发现；</p><h3 id=\"_58-任务执行结果\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_58-%e4%bb%bb%e5%8a%a1%e6%89%a7%e8%a1%8c%e7%bb%93%e6%9e%9c\" data-id=\"_58-任务执行结果\" class=\"anchor\"><span>5.8 任务执行结果</span></a></h3><p>自v1.6.2之后，任务执行结果通过 \"IJobHandler\" 的返回值 \"ReturnT\" 进行判断；\n当返回值符合 \"ReturnT.code == ReturnT.SUCCESS_CODE\" 时表示任务执行成功，否则表示任务执行失败，而且可以通过 \"ReturnT.msg\" 回调错误信息给调度中心；\n从而，在任务逻辑中可以方便的控制任务执行结果；</p><h3 id=\"_59-分片广播-amp-动态分片\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_59-%e5%88%86%e7%89%87%e5%b9%bf%e6%92%ad-amp-%e5%8a%a8%e6%80%81%e5%88%86%e7%89%87\" data-id=\"_59-分片广播-amp-动态分片\" class=\"anchor\"><span>5.9 分片广播 &amp; 动态分片</span></a></h3><p>执行器集群部署时，任务路由策略选择\"分片广播\"情况下，一次任务调度将会广播触发对应集群中所有执行器执行一次任务，同时传递分片参数；可根据分片参数开发分片任务；</p><p>\"分片广播\" 以执行器为维度进行分片，支持动态扩容执行器集群从而动态增加分片数量，协同进行业务处理；在进行大数据量业务操作时可显著提升任务处理能力和速度。</p><p>\"分片广播\" 和普通任务开发流程一致，不同之处在于可以可以获取分片参数，获取分片参数进行分片业务处理。</p><ul>\n<li>Java语言任务获取分片参数方式：BEAN、GLUE模式(Java)<pre v-pre=\"\" data-lang=\"\"><code class=\"lang-\">// 可参考Sample示例执行器中的示例任务\"ShardingJobHandler\"了解试用 \nShardingUtil.ShardingVO shardingVO = ShardingUtil.getShardingVo();</code></pre></li>\n<li>脚本语言任务获取分片参数方式：GLUE模式(Shell)、GLUE模式(Python)、GLUE模式(Nodejs)<pre v-pre=\"\" data-lang=\"\"><code class=\"lang-\">// 脚本任务入参固定为三个，依次为：任务传参、分片序号、分片总数。以Shell模式任务为例，获取分片参数代码如下\necho \"分片序号 index = $2\"\necho \"分片总数 total = $3\"</code></pre></li>\n</ul>\n<p>分片参数属性说明：</p><pre v-pre=\"\" data-lang=\"\"><code class=\"lang-\">index：当前分片序号(从0开始)，执行器集群列表中当前执行器的序号；\ntotal：总分片数，执行器集群的总机器数量；</code></pre><p>该特性适用场景如：</p><ul>\n<li>1、分片任务场景：10个执行器的集群来处理10w条数据，每台机器只需要处理1w条数据，耗时降低10倍；</li>\n<li>2、广播任务场景：广播执行器机器运行shell脚本、广播集群节点进行缓存更新等</li>\n</ul>\n<h3 id=\"_510-访问令牌（accesstoken）\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_510-%e8%ae%bf%e9%97%ae%e4%bb%a4%e7%89%8c%ef%bc%88accesstoken%ef%bc%89\" data-id=\"_510-访问令牌（accesstoken）\" class=\"anchor\"><span>5.10 访问令牌（AccessToken）</span></a></h3><p>为提升系统安全性，调度中心和执行器进行安全性校验，双方AccessToken匹配才允许通讯；</p><p>调度中心和执行器，可通过配置项 \"xxl.job.accessToken\" 进行AccessToken的设置。</p><p>调度中心和执行器，如果需要正常通讯，只有两种设置；</p><ul>\n<li>设置一：调度中心和执行器，均不设置AccessToken；关闭安全性校验；</li>\n<li>设置二：调度中心和执行器，设置了相同的AccessToken；</li>\n</ul>\n<h3 id=\"_511-调度中心api服务\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_511-%e8%b0%83%e5%ba%a6%e4%b8%ad%e5%bf%83api%e6%9c%8d%e5%8a%a1\" data-id=\"_511-调度中心api服务\" class=\"anchor\"><span>5.11 调度中心API服务</span></a></h3><p>调度中心提供了API服务，供执行器和业务方选择使用，目前提供的API服务有：</p><pre v-pre=\"\" data-lang=\"\"><code class=\"lang-\">1、任务结果回调服务；\n2、执行器注册服务；\n3、执行器注册摘除服务；\n4、触发任务单次执行服务，支持任务根据业务事件触发；</code></pre><p>调度中心API服务位置：com.xxl.job.core.biz.AdminBiz.java</p><p>调度中心API服务请求参考代码：com.xxl.job.adminbiz.AdminBizTest.java</p><h3 id=\"_512-执行器api服务\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_512-%e6%89%a7%e8%a1%8c%e5%99%a8api%e6%9c%8d%e5%8a%a1\" data-id=\"_512-执行器api服务\" class=\"anchor\"><span>5.12 执行器API服务</span></a></h3><p>执行器提供了API服务，供调度中心选择使用，目前提供的API服务有：</p><pre v-pre=\"\" data-lang=\"\"><code class=\"lang-\">1、心跳检测\n2、忙碌检测\n3、触发任务执行\n4、获取Rolling Log\n5、终止任务</code></pre><p>执行器API服务位置：com.xxl.job.core.biz.ExecutorBiz</p><p>执行器API服务请求参考代码：com.xxl.executor.test.DemoJobHandlerTest</p><h3 id=\"_513-故障转移-amp-失败重试\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_513-%e6%95%85%e9%9a%9c%e8%bd%ac%e7%a7%bb-amp-%e5%a4%b1%e8%b4%a5%e9%87%8d%e8%af%95\" data-id=\"_513-故障转移-amp-失败重试\" class=\"anchor\"><span>5.13 故障转移 &amp; 失败重试</span></a></h3><p>一次完整任务流程包括\"调度（调度中心） + 执行（执行器）\"两个阶段。</p><ul>\n<li>\"故障转移\"发生在调度阶段，在执行器集群部署时，如果某一台执行器发生故障，该策略支持自动进行Failover切换到一台正常的执行器机器并且完成调度请求流程。</li>\n<li>\"失败重试\"发生在\"调度 + 执行\"两个阶段，如下：<ul>\n<li>调度中心调度失败时，任务失败处理策略选择\"失败重试\"，将会自动重试一次；</li>\n<li>执行器运行失败时，任务执行结果返回\"失败重试（IJobHandler.FAIL_RETRY）\"回调，将会自动重试一次；</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"_514-执行器灰度上线\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_514-%e6%89%a7%e8%a1%8c%e5%99%a8%e7%81%b0%e5%ba%a6%e4%b8%8a%e7%ba%bf\" data-id=\"_514-执行器灰度上线\" class=\"anchor\"><span>5.14 执行器灰度上线</span></a></h3><p>调度中心与业务解耦，只需部署一次后常年不需要维护。但是，执行器中托管运行着业务作业，作业上线和变更需要重启执行器，尤其是Bean模式任务。\n执行器重启可能会中断运行中的任务。但是，XXL-JOB得益于自建执行器与自建注册中心，可以通过灰度上线的方式，避免因重启导致的任务中断的问题。</p><p>步骤如下：</p><ul>\n<li>1、执行器改为手动注册，下线一半机器列表（A组），线上运行另一半机器列表（B组）；</li>\n<li>2、等待A组机器任务运行结束并编译上线；执行器注册地址替换为A组；</li>\n<li>3、等待B组机器任务运行结束并编译上线；执行器注册地址替换为A组+B组；\n操作结束；</li>\n</ul>\n<h3 id=\"_515-任务执行结果说明\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_515-%e4%bb%bb%e5%8a%a1%e6%89%a7%e8%a1%8c%e7%bb%93%e6%9e%9c%e8%af%b4%e6%98%8e\" data-id=\"_515-任务执行结果说明\" class=\"anchor\"><span>5.15 任务执行结果说明</span></a></h3><p>系统根据以下标准判断任务执行结果，可参考之。</p><table>\n<thead>\n<tr>\n<th>--</th>\n<th>Bean/Glue(Java)</th>\n<th>Glue(Shell) 等脚本任务</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>成功</td>\n<td>IJobHandler.SUCCESS</td>\n<td>0</td>\n</tr>\n<tr>\n<td>失败</td>\n<td>IJobHandler.FAIL</td>\n<td>-1（其他）</td>\n</tr>\n<tr>\n<td>失败重试</td>\n<td>IJobHandler.FAIL_RETRY</td>\n<td>101</td>\n</tr>\n</tbody>\n</table>\n<h2 id=\"六、版本更新日志\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=%e5%85%ad%e3%80%81%e7%89%88%e6%9c%ac%e6%9b%b4%e6%96%b0%e6%97%a5%e5%bf%97\" data-id=\"六、版本更新日志\" class=\"anchor\"><span>六、版本更新日志</span></a></h2><h3 id=\"_61-版本-v11x，新特性2015-12-05\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_61-%e7%89%88%e6%9c%ac-v11x%ef%bc%8c%e6%96%b0%e7%89%b9%e6%80%a72015-12-05\" data-id=\"_61-版本-v11x，新特性2015-12-05\" class=\"anchor\"><span>6.1 版本 V1.1.x，新特性[2015-12-05]</span></a></h3><p><strong>【于V1.1.x版本，XXL-JOB正式应用于我司，内部定制别名为 “Ferrari”，新接入应用推荐使用最新版本】</strong></p><ul>\n<li>1、简单：支持通过Web页面对任务进行CRUD操作，操作简单，一分钟上手；</li>\n<li>2、动态：支持动态修改任务状态，动态暂停/恢复任务，即时生效；</li>\n<li>3、服务HA：任务信息持久化到mysql中，Job服务天然支持集群，保证服务HA；</li>\n<li>4、任务HA：某台Job服务挂掉，任务会平滑分配给其他的某一台存活服务，即使所有服务挂掉，重启时或补偿执行丢失任务；</li>\n<li>5、一个任务只会在其中一台服务器上执行；</li>\n<li>6、任务串行执行；</li>\n<li>7、支持自定义参数；</li>\n<li>8、支持远程任务执行终止；</li>\n</ul>\n<h3 id=\"_62-版本-v12x，新特性2016-01-17\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_62-%e7%89%88%e6%9c%ac-v12x%ef%bc%8c%e6%96%b0%e7%89%b9%e6%80%a72016-01-17\" data-id=\"_62-版本-v12x，新特性2016-01-17\" class=\"anchor\"><span>6.2 版本 V1.2.x，新特性[2016-01-17]</span></a></h3><ul>\n<li>1、支持任务分组；</li>\n<li>2、支持“本地任务”、“远程任务”；</li>\n<li>3、底层通讯支持两种方式，Servlet方式 + JETTY方式；</li>\n<li>4、支持“任务日志”；</li>\n<li><p>5、支持“串行执行”，并行执行；</p><p>  说明：V1.2版本将系统架构按功能拆分为：</p><pre v-pre=\"\" data-lang=\"\"><code class=\"lang-\">  - 调度模块（调度中心）：负责管理调度信息，按照调度配置发出调度请求；\n  - 执行模块（执行器）：负责接收调度请求并执行任务逻辑；\n  - 通讯模块：负责调度模块和任务模块之间的信息通讯；</code></pre><p>  优点：</p><pre v-pre=\"\" data-lang=\"\"><code class=\"lang-\">  - 解耦：任务模块提供任务接口，调度模块维护调度信息，业务相互独立；\n  - 高扩展性；\n  - 稳定性；</code></pre></li>\n</ul>\n<h3 id=\"_63-版本-v130，新特性2016-05-19\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_63-%e7%89%88%e6%9c%ac-v130%ef%bc%8c%e6%96%b0%e7%89%b9%e6%80%a72016-05-19\" data-id=\"_63-版本-v130，新特性2016-05-19\" class=\"anchor\"><span>6.3 版本 V1.3.0，新特性[2016-05-19]</span></a></h3><ul>\n<li>1、遗弃“本地任务”模式，推荐使用“远程任务”，易于系统解耦，任务对应的JobHandler统称为“执行器”；</li>\n<li>2、遗弃“servlet”方式底层系统通讯，推荐使用JETTY方式，调度+回调双向通讯，重构通讯逻辑；</li>\n<li>3、UI交互优化：左侧菜单展开状态优化，菜单项选中状态优化，任务列表打开表格有压缩优化；</li>\n<li><p>4、【重要】“执行器”细分为：BEAN、GLUE两种开发模式，简介见下文：</p><p>  “执行器” 模式简介：</p><pre v-pre=\"\" data-lang=\"\"><code class=\"lang-\">  - BEAN模式执行器：每个执行器都是Spring的一个Bean实例，XXL-JOB通过注解@JobHandler识别和调度执行器；\n   -GLUE模式执行器：每个执行器对应一段代码，在线Web编辑和维护，动态编译生效，执行器负责加载GLUE代码和执行；</code></pre></li>\n</ul>\n<h3 id=\"_64-版本-v131，新特性2016-05-23\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_64-%e7%89%88%e6%9c%ac-v131%ef%bc%8c%e6%96%b0%e7%89%b9%e6%80%a72016-05-23\" data-id=\"_64-版本-v131，新特性2016-05-23\" class=\"anchor\"><span>6.4 版本 V1.3.1，新特性[2016-05-23]</span></a></h3><ul>\n<li>1、更新项目目录结构：<ul>\n<li>/xxl-job-admin -------------------- 【调度中心】：负责管理调度信息，按照调度配置发出调度请求；</li>\n<li>/xxl-job-core ----------------------- 公共依赖</li>\n<li>/xxl-job-executor-example ------ 【执行器】：负责接收调度请求并执行任务逻辑；</li>\n<li>/db ---------------------------------- 建表脚本</li>\n<li>/doc --------------------------------- 用户手册</li>\n</ul>\n</li>\n<li>2、在新的目录结构上，升级了用户手册；</li>\n<li>3、优化了一些交互和UI；</li>\n</ul>\n<h3 id=\"_65-版本-v132，新特性2016-05-28\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_65-%e7%89%88%e6%9c%ac-v132%ef%bc%8c%e6%96%b0%e7%89%b9%e6%80%a72016-05-28\" data-id=\"_65-版本-v132，新特性2016-05-28\" class=\"anchor\"><span>6.5 版本 V1.3.2，新特性[2016-05-28]</span></a></h3><ul>\n<li>1、调度逻辑进行事务包裹；</li>\n<li>2、执行器异步回调执行日志；</li>\n<li>3、【重要】在 “调度中心” 支持HA的基础上，扩展执行器的Failover支持，支持配置多执行期地址；</li>\n</ul>\n<h3 id=\"_66-版本-v140-新特性2016-07-24\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_66-%e7%89%88%e6%9c%ac-v140-%e6%96%b0%e7%89%b9%e6%80%a72016-07-24\" data-id=\"_66-版本-v140-新特性2016-07-24\" class=\"anchor\"><span>6.6 版本 V1.4.0 新特性[2016-07-24]</span></a></h3><ul>\n<li>1、任务依赖: 通过事件触发方式实现, 任务执行成功并回调时会主动触发一次子任务的调度, 多个子任务用逗号分隔;</li>\n<li>2、执行器底层实现代码进行重度重构, 优化底层建表脚本;</li>\n<li>3、执行器中任务线程分组逻辑优化: 之前根据执行器JobHandler进行线程分组,当多个任务复用Jobhanlder会导致相互阻塞。现改为根据调度中心任务进行任务线程分组,任务与任务执行相互隔离;</li>\n<li>4、执行器调度通讯方案优化, 通过Hex + HC实现建议RPC通讯协议, 优化了通讯参数的维护和解析流程;</li>\n<li>5、调度中心, 新建/编辑任务, 界面属性调整: <ul>\n<li>5.1、任务新增/编辑界面中去除 \"任务名JobName\"属性 ,该属性改为系统自动生成: 该字段之前主要用于在 \"调度中心\" 唯一标示一个任务, 现实意义不大, 因此计划淡化掉该字段,改为系统生成UUID,从而简化任务新建的操作;</li>\n<li>5.2、任务新增/编辑界面中去除 \"GLUE模式\" 复选框位置调整, 改为贴近\"JobHandler\"输入框右侧;</li>\n<li>5.3、任务新增/编辑界面中去除 \"报警阈值\" 属性;</li>\n<li>5.4、任务新增/编辑界面中去除 \"子任务Key\" 属性, 每个任务全局任务Key可以从任务列表获取, 当本任务执行结束且成功后, 将会根据子任务Key匹配子任务并主动触发一次子任务执行;</li>\n</ul>\n</li>\n<li>6、问题修复:<ul>\n<li>6.1、执行器jetty关闭优化,解决一处可能导致jetty无法关闭的问题;</li>\n<li>6.2、执行器任务终止时,执行队列回调优化,解决一处导致任务无法回调的问题；</li>\n<li>6.3、调度中心中列表分页参数优化,解决一处因服务器限制post长度而引起的问题;</li>\n<li>6.4、执行器Jobhandler注解优化,解决一处因事务代理导致的容器无法加载JobHandler的问题;</li>\n<li>6.5、远程调度优化,禁用retry策略,解决一处可能导致重复调用的问题;</li>\n</ul>\n</li>\n</ul>\n<p>Tips: 历史版本(V1.3.x)目前已经Release至稳定版本, 进入维护阶段, 地址见分支 <a href=\"https://github.com/xuxueli/xxl-job/tree/v1.3\" target=\"_blank\">V1.3</a> 。新特性将会在master分支持续更新。</p><h3 id=\"_67-版本-v141-新特性2016-09-06\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_67-%e7%89%88%e6%9c%ac-v141-%e6%96%b0%e7%89%b9%e6%80%a72016-09-06\" data-id=\"_67-版本-v141-新特性2016-09-06\" class=\"anchor\"><span>6.7 版本 V1.4.1 新特性[2016-09-06]</span></a></h3><ul>\n<li>1、项目成功推送maven中央仓库, 中央仓库地址以及依赖如下: <pre v-pre=\"\" data-lang=\"\"><code class=\"lang-\">  <span class=\"token comment\" spellcheck=\"true\">&lt;!-- http://repo1.maven.org/maven2/com/xuxueli/xxl-job-core/ --&gt;</span>\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>dependency</span><span class=\"token punctuation\">&gt;</span></span>\n      <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>groupId</span><span class=\"token punctuation\">&gt;</span></span>com.xuxueli<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>groupId</span><span class=\"token punctuation\">&gt;</span></span>\n      <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>artifactId</span><span class=\"token punctuation\">&gt;</span></span>xxl-job-core<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>artifactId</span><span class=\"token punctuation\">&gt;</span></span>\n      <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>version</span><span class=\"token punctuation\">&gt;</span></span>${最新稳定版}<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>version</span><span class=\"token punctuation\">&gt;</span></span>\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>dependency</span><span class=\"token punctuation\">&gt;</span></span></code></pre></li>\n<li>2、为适配中央仓库规则, 项目groupId从com.xxl改为com.xuxueli。</li>\n<li>3、系统版本不在维护在项目跟pom中,各个子模块单独配置版本配置,解决子模块无法单独编译的问题;</li>\n<li>4、底层RPC通讯,传输数据的字节长度统计规则优化,可节省50%数据传输量;</li>\n<li>5、IJobHandler取消任务返回值,原通过返回值判断执行状态,逻辑改为:默认任务执行成功,仅在捕获异常时认定任务执行失败。</li>\n<li>6、系统公共弹框功能,插件化;</li>\n<li>7、底层表结构,表明统一大写;</li>\n<li>8、调度中心,异常处理器JSON响应的ContentType修改,修复浏览器不识别的问题;</li>\n</ul>\n<h3 id=\"_68-版本-v142-新特性2016-09-29\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_68-%e7%89%88%e6%9c%ac-v142-%e6%96%b0%e7%89%b9%e6%80%a72016-09-29\" data-id=\"_68-版本-v142-新特性2016-09-29\" class=\"anchor\"><span>6.8 版本 V1.4.2 新特性[2016-09-29]</span></a></h3><ul>\n<li>1、推送新版本 V1.4.2 至中央仓库, 大版本 V1.4 进入维护阶段;</li>\n<li>2、任务新增时,任务列表偏移问题修复;</li>\n<li>3、修复一处因bootstrap不支持模态框重叠而导致的样式错乱的问题, 在任务编辑时会出现该问题;</li>\n<li>4、调度超时和Handler匹配不到时,调度状态优化;</li>\n<li>5、因catch异常,导致任务不可终止的问题,给出解决方案, 见文档;</li>\n</ul>\n<h3 id=\"_69-版本-v150-特性2016-11-13\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_69-%e7%89%88%e6%9c%ac-v150-%e7%89%b9%e6%80%a72016-11-13\" data-id=\"_69-版本-v150-特性2016-11-13\" class=\"anchor\"><span>6.9 版本 V1.5.0 特性[2016-11-13]</span></a></h3><ul>\n<li>1、任务注册: 执行器会周期性自动注册任务, 调度中心将会自动发现注册的任务并触发执行。</li>\n<li>2、\"执行器\" 新增参数 \"AppName\" : 是每个执行器集群的唯一标示AppName, 并周期性以AppName为对象进行自动注册。</li>\n<li>3、调度中心新增栏目 \"执行器管理\" : 管理在线的执行器, 通过属性AppName自动发现注册的执行器。只有被管理的执行器才允许被使用;</li>\n<li>4、\"任务组\"属性改为\"执行器\": 每个任务需要绑定指定的执行器, 调度地址通过绑定的执行器获取;</li>\n<li>5、抛弃\"任务机器\"属性: 通过任务绑定的执行器, 自动发现注册的远程执行器地址并触发调度请求。</li>\n<li>6、\"公共依赖\"中新增DBGlueLoader,基于原生jdbc实现GLUE源码的加载器,减少第三方依赖(mybatis,spring-orm等);精简和优化执行器测配置(针对GLUE任务),降低上手难度;</li>\n<li>7、表结构调整,底层重构优化;</li>\n<li>8、\"调度中心\"自动注册和发现,failover: 调度中心周期性自动注册, 任务回调时可以感知在线的所有调度中心地址, 通过failover的方式进行任务回调,避免回调单点风险。</li>\n</ul>\n<h3 id=\"_610-版本-v151-特性2016-11-13\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_610-%e7%89%88%e6%9c%ac-v151-%e7%89%b9%e6%80%a72016-11-13\" data-id=\"_610-版本-v151-特性2016-11-13\" class=\"anchor\"><span>6.10 版本 V1.5.1 特性[2016-11-13]</span></a></h3><ul>\n<li>1、底层代码重构和逻辑优化，POM清理以及CleanCode；</li>\n<li>2、Servlet/JSP Spec设定为3.0/2.2</li>\n<li>3、Spring升级至3.2.17.RELEASE版本；</li>\n<li>4、Jetty升级版本至8.2.0.v20160908；</li>\n<li>5、已推送V1.5.0和V1.5.1至Maven中央仓库；</li>\n</ul>\n<h3 id=\"_610-版本-v152-特性2017-02-28\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_610-%e7%89%88%e6%9c%ac-v152-%e7%89%b9%e6%80%a72017-02-28\" data-id=\"_610-版本-v152-特性2017-02-28\" class=\"anchor\"><span>6.10 版本 V1.5.2 特性[2017-02-28]</span></a></h3><ul>\n<li>1、IP工具类获取IP逻辑优化，IP静态缓存；</li>\n<li>2、执行器、调度中心，均支持自定义注册IP地址；解决机器多网卡时错误网卡注册的情况；</li>\n<li>3、任务跨天执行时生成多份日志文件的问题修复；</li>\n<li>4、底层日志底层日志调整，非敏感日志level调整为debug；</li>\n<li>5、升级数据库连接池c3p0版本；</li>\n<li>6、执行器log4j配置优化，去除无效属性；</li>\n<li>7、底层代码重构和逻辑优化以及CleanCode；</li>\n<li>8、GLUE依赖注入逻辑优化，支持别名注入；</li>\n</ul>\n<h3 id=\"_611-版本-v160-特性2017-03-13\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_611-%e7%89%88%e6%9c%ac-v160-%e7%89%b9%e6%80%a72017-03-13\" data-id=\"_611-版本-v160-特性2017-03-13\" class=\"anchor\"><span>6.11 版本 V1.6.0 特性[2017-03-13]</span></a></h3><ul>\n<li>1、通讯方案升级，原基于HEX的通讯模型调整为基于HTTP的B-RPC的通讯模型；</li>\n<li>2、执行器支持手动设置执行地址列表，提供开关切换使用注册地址还是手动设置的地址；</li>\n<li>3、执行器路由规则：第一个、最后一个、轮询、随机、一致性HASH、最不经常使用、最近最久未使用、故障转移；</li>\n<li>4、规范线程模型统一，统一线程销毁方案(通过listener或stop方法，容器销毁时销毁线程；Daemon方式有时不太理想)；</li>\n<li>5、规范系统配置数据，通过配置文件统一管理；</li>\n<li>6、CleanCode，清理无效的历史参数；</li>\n<li>7、底层扩展数据结构以及相关表结构调整；</li>\n<li>8、新建任务默认为非运行状态；</li>\n<li>9、GLUE模式任务实例更新逻辑优化，原根据超时时间更新改为根据版本号更新，源码变动版本号加一；</li>\n</ul>\n<h3 id=\"_612-版本-v161-特性2017-03-25\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_612-%e7%89%88%e6%9c%ac-v161-%e7%89%b9%e6%80%a72017-03-25\" data-id=\"_612-版本-v161-特性2017-03-25\" class=\"anchor\"><span>6.12 版本 V1.6.1 特性[2017-03-25]</span></a></h3><ul>\n<li>1、Rolling日志；</li>\n<li>2、WebIDE交互重构；</li>\n<li>3、通讯增强校验，有效过滤非正常请求；</li>\n<li>4、权限增强校验，采用动态登录TOKEN（推荐接入内部SSO）；</li>\n<li>5、数据库配置优化，解决乱码问题；</li>\n</ul>\n<h3 id=\"_613-版本-v162-特性2017-04-25\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_613-%e7%89%88%e6%9c%ac-v162-%e7%89%b9%e6%80%a72017-04-25\" data-id=\"_613-版本-v162-特性2017-04-25\" class=\"anchor\"><span>6.13 版本 V1.6.2 特性[2017-04-25]</span></a></h3><ul>\n<li>1、运行报表：支持实时查看运行数据，如任务数量、调度次数、执行器数量等；以及调度报表，如调度日期分布图，调度成功分布图等；</li>\n<li>2、JobHandler支持设置任务返回值，在任务逻辑中可以方便的控制任务执行结果；</li>\n<li>3、资源路径包含空格或中文时资源文件无法加载时，无法准确查看异常信息的问题处理。</li>\n<li>4、路由策越优化：循环和LFU路由策略计数器自增无上限问题和首次路由压力集中在首台机器的问题修复；</li>\n</ul>\n<h3 id=\"_614-版本-v170-特性2017-05-02\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_614-%e7%89%88%e6%9c%ac-v170-%e7%89%b9%e6%80%a72017-05-02\" data-id=\"_614-版本-v170-特性2017-05-02\" class=\"anchor\"><span>6.14 版本 V1.7.0 特性[2017-05-02]</span></a></h3><ul>\n<li>1、脚本任务：支持以GLUE模式开发和运行脚本任务，包括Shell、Python和Groovy等类型脚本;</li>\n<li>2、新增spring-boot类型执行器example项目；</li>\n<li>3、升级jetty版本至9.2；</li>\n<li>4、任务运行日志移除log4j组件依赖，改为底层自主实现，从而取消了对日志组件的依赖限制；</li>\n<li>5、执行器移除GlueLoader依赖，改为推送方式实现，从而GLUE源码加载不再依赖JDBC；</li>\n<li>6、登录拦截Redirect时获取项目名，解决非根据目录发布时跳转404问题；</li>\n</ul>\n<h3 id=\"_615-版本-v171-特性2017-05-08\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_615-%e7%89%88%e6%9c%ac-v171-%e7%89%b9%e6%80%a72017-05-08\" data-id=\"_615-版本-v171-特性2017-05-08\" class=\"anchor\"><span>6.15 版本 V1.7.1 特性[2017-05-08]</span></a></h3><ul>\n<li>1、运行日志读写编码统一为UTF-8，解决windows环境下日志乱码问题；</li>\n<li>2、通讯超时时间限定为10s，避免异常情况下调度线程占用；</li>\n<li>3、执行器，server启动、销毁和注册逻辑调整；</li>\n<li>4、JettyServer关闭逻辑优化，修复执行器无法正常关闭导致端口占用和频繁打印c3p0日志的问题；</li>\n<li>5、JobHandler中开启子线程时，支持子线程输出执行日志并通过Rolling查看。</li>\n<li>6、任务日志清理功能；</li>\n<li>7、弹框组件统一替换为layer；</li>\n<li>8、升级quartz版本至2.3.0；</li>\n</ul>\n<h3 id=\"_616-版本-v172-特性2017-05-17\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_616-%e7%89%88%e6%9c%ac-v172-%e7%89%b9%e6%80%a72017-05-17\" data-id=\"_616-版本-v172-特性2017-05-17\" class=\"anchor\"><span>6.16 版本 V1.7.2 特性[2017-05-17]</span></a></h3><ul>\n<li>1、阻塞处理策略：调度过于密集执行器来不及处理时的处理策略，策略包括：单机串行（默认）、丢弃后续调度、覆盖之前调度；</li>\n<li>2、失败处理策略；调度失败时的处理策略，策略包括：失败告警（默认）、失败重试；</li>\n<li>3、通讯时间戳超时时间调整为180s；</li>\n<li>4、执行器与数据库彻底解耦，但是执行器需要配置调度中心集群地址。调度中心提供API供执行器回调和心跳注册服务，取消调度中心内部jetty，心跳周期调整为30s，心跳失效为三倍心跳；</li>\n<li>5、执行参数编辑时丢失问题修复；</li>\n<li>6、新增任务测试Demo，方便在开发时进行任务逻辑测试；</li>\n</ul>\n<h3 id=\"_617-版本-v180-特性2017-07-17\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_617-%e7%89%88%e6%9c%ac-v180-%e7%89%b9%e6%80%a72017-07-17\" data-id=\"_617-版本-v180-特性2017-07-17\" class=\"anchor\"><span>6.17 版本 V1.8.0 特性[2017-07-17]</span></a></h3><ul>\n<li>1、任务Cron更新逻辑优化，改为rescheduleJob，同时防止cron重复设置；</li>\n<li>2、API回调服务失败状态码优化，方便问题排查；</li>\n<li>3、XxlJobLogger的日志多参数支持；</li>\n<li>4、路由策略新增 \"忙碌转移\" 模式：按照顺序依次进行空闲检测，第一个空闲检测成功的机器选定为目标执行器并发起调度；</li>\n<li>5、路由策略代码重构；</li>\n<li>6、执行器重复注册问题修复；</li>\n<li>7、任务线程轮空30次后自动销毁，降低低频任务的无效线程消耗。</li>\n<li>8、执行器任务执行结果批量回调，降低回调频率提升执行器性能；</li>\n<li>9、springboot版本执行器，取消XML配置，改为类配置方式；</li>\n<li>10、执行日志，支持根据运行 \"状态\" 筛选日志；</li>\n<li>11、调度中心任务注册检测逻辑优化；</li>\n</ul>\n<h3 id=\"_618-版本-v181-特性2017-07-30\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_618-%e7%89%88%e6%9c%ac-v181-%e7%89%b9%e6%80%a72017-07-30\" data-id=\"_618-版本-v181-特性2017-07-30\" class=\"anchor\"><span>6.18 版本 V1.8.1 特性[2017-07-30]</span></a></h3><ul>\n<li>1、分片广播任务：执行器集群部署时，任务路由策略选择\"分片广播\"情况下，一次任务调度将会广播触发集群中所有执行器执行一次任务，可根据分片参数处理分片任务；</li>\n<li>2、动态分片：分片广播任务以执行器为维度进行分片，支持动态扩容执行器集群从而动态增加分片数量，协同进行业务处理；在进行大数据量业务操作时可显著提升任务处理能力和速度。</li>\n<li>3、执行器JobHandler禁止命名冲突；</li>\n<li>4、执行器集群地址列表进行自然排序；</li>\n<li>5、调度中心，DAO层代码精简优化并且新增测试用例覆盖；</li>\n<li>6、调度中心API服务改为自研RPC形式，统一底层通讯模型；</li>\n<li>7、新增调度中心API服务测试Demo，方便在调度中心API扩展和测试；</li>\n<li>8、任务列表页交互优化，更换执行器分组时自动刷新任务列表，新建任务时默认定位在当前执行器位置；</li>\n<li>9、访问令牌（accessToken）：为提升系统安全性，调度中心和执行器进行安全性校验，双方AccessToken匹配才允许通讯；</li>\n<li>10、springboot版本执行器，升级至1.5.6.RELEASE版本；</li>\n<li>11、统一maven依赖版本管理；</li>\n</ul>\n<h3 id=\"_619-版本-v182-特性2017-09-04\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_619-%e7%89%88%e6%9c%ac-v182-%e7%89%b9%e6%80%a72017-09-04\" data-id=\"_619-版本-v182-特性2017-09-04\" class=\"anchor\"><span>6.19 版本 V1.8.2 特性[2017-09-04]</span></a></h3><ul>\n<li>1、项目主页搭建：提供中英文文档：<a href=\"http://www.xuxueli.com/xxl-job\" target=\"_blank\">http://www.xuxueli.com/xxl-job</a> </li>\n<li>2、JFinal执行器Sample示例项目；</li>\n<li>3、事件触发：除了\"Cron方式\"和\"任务依赖方式\"触发任务执行之外，支持基于事件的触发任务方式。调度中心提供触发任务单次执行的API服务，可根据业务事件灵活触发。</li>\n<li>4、执行器摘除：执行器销毁时，主动通知调度中心并摘除对应执行器节点，提高执行器状态感知的时效性。</li>\n<li>5、执行器手动设置IP时将会绑定Host；</li>\n<li>6、规范项目目录，方便扩展多执行器；</li>\n<li>7、解决执行器回调URL不支持配置HTTPS时问题；</li>\n<li>8、执行器回调线程销毁前, 批量回调队列中数据，防止任务结果丢失；</li>\n<li>9、调度中心任务监控线程销毁时，批量对失败任务告警，防止告警信息丢失；</li>\n<li>10、任务日志文件路径时间戳格式化时SimpleDateFormat并发问题解决；</li>\n</ul>\n<h3 id=\"_620-版本-v190-特性2017-12-29\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_620-%e7%89%88%e6%9c%ac-v190-%e7%89%b9%e6%80%a72017-12-29\" data-id=\"_620-版本-v190-特性2017-12-29\" class=\"anchor\"><span>6.20 版本 V1.9.0 特性[2017-12-29]</span></a></h3><ul>\n<li>1、新增Nutz执行器Sample示例项目；</li>\n<li>2、新增任务运行模式 \"GLUE模式(NodeJS) \"，支持NodeJS脚本任务；</li>\n<li>3、脚本任务Shell、Python和Nodejs等支持获取分片参数；</li>\n<li>4、失败重试，完整支持：调度中心调度失败且启用\"失败重试\"策略时，将会自动重试一次；执行器执行失败且回调失败重试状态（新增失败重试状态返回值）时，也将会自动重试一次；</li>\n<li>5、失败告警策略扩展：默认提供邮件失败告警，可扩展短信等，扩展代码位置为 \"JobFailMonitorHelper.failAlarm\"；</li>\n<li>6、执行器端口支持自动生成(小于等于0时)，避免端口定义冲突；</li>\n<li>7、调度报表优化，支持时间区间筛选；</li>\n<li>8、Log组件支持输出异常栈信息，底层实现优化；</li>\n<li>9、告警邮件样式优化，调整为表格形式，邮件组件调整为commons-email简化邮件操作；</li>\n<li>10、项目依赖全量升级至较新稳定版本，如spring、jackson等等；</li>\n<li>11、任务日志，记录发起调度的机器信息；</li>\n<li>12、交互优化，如登陆注销；</li>\n<li>13、任务Cron长度扩展支持至128位，支持负责类型Cron设置；</li>\n<li>14、执行器地址录入交互优化，地址长度扩展支持至512位，支持大规模执行器集群配置；</li>\n<li>15、任务参数“IJobHandler.execute”入参改为“String params”，增强入参通用性。</li>\n<li>16、IJobHandler提供init/destroy方法，支持在相应任务线程初始化和销毁时进行附加操作；</li>\n<li>17、任务注解调整为 “@JobHandler”，与任务抽象接口统一；</li>\n<li>18、修复任务监控线程被耗时任务阻塞的问题；</li>\n<li>19、修复任务监控线程无法监控任务触发和执行状态均未0的问题；</li>\n<li>20、执行器动态代理对象，拦截非业务方法的执行；</li>\n<li>21、修复JobThread捕获Error错误不更新JobLog的问题；</li>\n<li>22、修复任务列表界面左侧菜单合并时样式错乱问题；</li>\n<li>23、调度中心项目日志配置改为xml文件格式；</li>\n<li>24、Log地址格式兼容，支持非\"/\"结尾路径配置；</li>\n<li>25、底层系统日志级别规范调整，清理遗留代码；</li>\n<li>26、建表SQL优化，支持同步创建制定编码的库和表；</li>\n<li>27、系统安全性优化，登陆Token写Cookie时进行MD5加密，同时Cookie启用HttpOnly；</li>\n<li>28、新增\"任务ID\"属性，移除\"JobKey\"属性，前者承担所有功能，方便后续增强任务依赖功能。</li>\n<li>29、任务循环依赖问题修复，避免子任务与父任务重复导致的调度死循环；</li>\n<li>30、任务列表新增筛选条件 \"任务描述\"，快速检索任务；</li>\n<li>31、执行器Log文件定期清理功能：执行器新增配置项（\"xxl.job.executor.logretentiondays\"）日志保存天数，日志文件过期自动删除。</li>\n</ul>\n<h3 id=\"_621-版本-v191-特性2018-02-22\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_621-%e7%89%88%e6%9c%ac-v191-%e7%89%b9%e6%80%a72018-02-22\" data-id=\"_621-版本-v191-特性2018-02-22\" class=\"anchor\"><span>6.21 版本 V1.9.1 特性[2018-02-22]</span></a></h3><ul>\n<li>1、国际化：调度中心实现国际化，支持中文、英文两种语言，默认为中文。</li>\n<li>2、调度报表新增\"运行中\"中状态项；</li>\n<li>3、调度报表优化，报表SQL调优并且新增LocalCache缓存（缓存时间60s），提高大数据量下报表加载速度；</li>\n<li>4、修复打包部署时资源文件乱码问题；</li>\n<li>5、修复新版本chrome滚动到顶部失效问题；</li>\n<li>6、调度中心配置加载优化，取消对配置文件名的强依赖，支持加载磁盘配置；</li>\n<li>7、修复脚本任务Log文件未正常close的问题；</li>\n<li>8、项目依赖全量升级至较新稳定版本，如spring、jackson等等；</li>\n</ul>\n<h3 id=\"_622-版本-v192-特性迭代中\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_622-%e7%89%88%e6%9c%ac-v192-%e7%89%b9%e6%80%a7%e8%bf%ad%e4%bb%a3%e4%b8%ad\" data-id=\"_622-版本-v192-特性迭代中\" class=\"anchor\"><span>6.22 版本 V1.9.2 特性[迭代中]</span></a></h3><ul>\n<li>1、[迭代中]支持通过API服务操作任务信息；</li>\n<li>2、[迭代中]任务告警逻辑调整：任务调度，以及任务回调失败时，均推送监控队列。后期考虑通过任务Log字段控制告警状态；</li>\n<li>3、[迭代中]任务超时设置，超时任务主动终止；</li>\n<li>4、任务属性枚举 \"任务模式、阻塞策略\" 国际化优化；</li>\n<li>5、任务日志表状态字段类型优化；</li>\n<li>6、Glue(Shell) 等脚本任务支持失败重试；</li>\n<li>7、告警邮箱支持SSL配置；</li>\n<li>8、Window机器下File.separator不兼容问题修复；</li>\n<li>9、任务日志查询速度优化，百万级别日志量搜索速度提升1000倍；</li>\n<li>10、底层LocalCache组件兼容性优化，支持jdk、jdk10编译部署；</li>\n</ul>\n<h3 id=\"todo-list\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=todo-list\" data-id=\"todo-list\" class=\"anchor\"><span>TODO LIST</span></a></h3><ul>\n<li>1、任务权限管理：执行器为粒度分配权限，核心操作校验权限；</li>\n<li>2、任务分片路由：分片采用一致性Hash算法计算出尽量稳定的分片顺序，即使注册机器存在波动也不会引起分批分片顺序大的波动；目前采用IP自然排序，可以满足需求，待定；</li>\n<li>3、任务单机多线程：提升任务单机并行处理能力；</li>\n<li>4、回调失败丢包问题：执行器回调失败写文件，重启或周期性回调重试；调度中心周期性请求并同步未回调的执行结果；</li>\n<li>5、任务依赖，流程图，子任务+会签任务，各节点日志；</li>\n<li>6、调度任务优先级；</li>\n<li>7、移除quartz依赖，重写调度模块：新增或恢复任务时将下次执行记录插入delayqueue，调度中心集群竞争分布式锁，成功节点批量加载到期delayqueue数据，批量执行。</li>\n<li>8、springboot 和 docker镜像，并且推送docker镜像到中央仓库，更进一步实现产品开箱即用；</li>\n<li>9、多数据库支持；</li>\n<li>10、执行器Log清理功能：调度中心Log删除时同步删除执行器中的Log文件；</li>\n<li>11、Bean模式任务，JobHandler自动从执行器中查询展示为下拉框，选择后自动填充任务名称等属性；</li>\n<li>12、API事件触发类型任务（更类似MQ消息）支持\"动态传参、延时消费\"；该类型任务不走Quartz，单独建立MQ消息表，调度中心竞争触发；</li>\n<li>13、任务依赖增强，新增任务类型 \"流程任务\"，流程节点可挂载普通类型任务，承担任务依赖功能。现有子任务模型取消；需要考虑任务依赖死循环问题；</li>\n<li>14、分片任务某一分片失败，支持分片转移；</li>\n<li>15、调度中心触发任务后，先推送触发队列，异步触发，然后立即返回。降低quartz线程占用时长。</li>\n<li>16、新增API服务 \"XxlJobService\" ，支持通过API服务来维护管理任务信息；</li>\n<li>17、新增任务默认运行状态，任务更新时运行状态保持不变；</li>\n<li>18、告警邮件中展示失败告警信息；</li>\n<li>19、提供多版本执行器：不依赖容器版本、不内嵌Jetty版本（通过配置executoraddress替换jetty通讯）等；</li>\n<li>20、注册中心支持扩展，除默认基于DB之外，支持扩展接入第三方注册中心如zk、eureka等；</li>\n<li>21、依赖Core内部国际化处理；</li>\n<li>22、故障转移、失败重试等策略，规范化合并归类；</li>\n<li>23、流程任务，支持参数传递；</li>\n<li>24、SimpleTrigger 支持；</li>\n</ul>\n<h2 id=\"七、其他\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=%e4%b8%83%e3%80%81%e5%85%b6%e4%bb%96\" data-id=\"七、其他\" class=\"anchor\"><span>七、其他</span></a></h2><h3 id=\"_71-项目贡献\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_71-%e9%a1%b9%e7%9b%ae%e8%b4%a1%e7%8c%ae\" data-id=\"_71-项目贡献\" class=\"anchor\"><span>7.1 项目贡献</span></a></h3><p>欢迎参与项目贡献！比如提交PR修复一个bug，或者新建 <a href=\"https://github.com/xuxueli/xxl-job/issues/\" target=\"_blank\">Issue</a> 讨论新特性或者变更。</p><h3 id=\"_72-用户接入登记\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_72-%e7%94%a8%e6%88%b7%e6%8e%a5%e5%85%a5%e7%99%bb%e8%ae%b0\" data-id=\"_72-用户接入登记\" class=\"anchor\"><span>7.2 用户接入登记</span></a></h3><p>更多接入的公司，欢迎在 <a href=\"https://github.com/xuxueli/xxl-job/issues/1\" target=\"_blank\">登记地址</a> 登记，登记仅仅为了产品推广。</p><h3 id=\"_73-开源协议和版权\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=_73-%e5%bc%80%e6%ba%90%e5%8d%8f%e8%ae%ae%e5%92%8c%e7%89%88%e6%9d%83\" data-id=\"_73-开源协议和版权\" class=\"anchor\"><span>7.3 开源协议和版权</span></a></h3><p>产品开源免费，并且将持续提供免费的社区技术支持。个人或企业内部可自由的接入和使用。</p><ul>\n<li>Licensed under the GNU General Public License (GPL) v3.</li>\n<li>Copyright (c) 2015-present, xuxueli.</li>\n</ul>\n<hr>\n<h3 id=\"捐赠\"><a href=\"http://www.xuxueli.com/xxl-job/#/?id=%e6%8d%90%e8%b5%a0\" data-id=\"捐赠\" class=\"anchor\"><span>捐赠</span></a></h3><p>无论捐赠金额多少都足够表达您这份心意，非常感谢 ：）      <a href=\"http://www.xuxueli.com/page/donate.html\" target=\"_blank\">前往捐赠</a></p></article></section></main>\n\n\n<script src=\"./分布式任务调度平台XXL-JOB_files/hm.js\"></script><script async=\"\" src=\"./分布式任务调度平台XXL-JOB_files/analytics.js\"></script><script>\n    window.$docsify = {\n        /*name: 'XXL-JOB',*/\n        /*homepage: 'README.md',*/\n        homepage: 'https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/XXL-JOB%E5%AE%98%E6%96%B9%E6%96%87%E6%A1%A3.md',\n        /*repo: 'https://github.com/xuxueli/xxl-job/'*/\n        coverpage: true,\n        /*coverpage: '_coverpage.md',*/\n        loadNavbar: true,\n        /*maxLevel: 5,*/\n        auto2top: true\n    }\n</script>\n\n<!-- Docsify -->\n<script src=\"./分布式任务调度平台XXL-JOB_files/docsify.min.js\"></script>\n<script src=\"./分布式任务调度平台XXL-JOB_files/search.min.js\"></script>\n<!-- Prism -->\n<script src=\"./分布式任务调度平台XXL-JOB_files/prism-java.min.js\"></script>\n\n<!-- google start -->\n<script>\n    (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){\n        (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),\n        m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)\n    })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');\n\n    ga('create', 'UA-105336587-1', 'auto');\n    ga('send', 'pageview');\n\n</script>\n<!-- google end -->\n\n\n<!-- baidu start -->\n<script>\n    var _hmt = _hmt || [];\n    (function() {\n        var hm = document.createElement(\"script\");\n        hm.src = \"https://hm.baidu.com/hm.js?2a4e116e8983ca87e083a41b552fe6a2\";\n        var s = document.getElementsByTagName(\"script\")[0];\n        s.parentNode.insertBefore(hm, s);\n    })();\n</script>\n<!-- baidu end -->\n\n<!-- cnzz start -->\n<script type=\"text/javascript\">\n    var cnzz_protocol = ((\"https:\" == document.location.protocol) ? \" https://\" : \" http://\");\n    document.write(unescape(\"%3Cspan style='display:none;' id='cnzz_stat_icon_1263800177'%3E%3C/span%3E%3Cscript src='\" + cnzz_protocol + \"s13.cnzz.com/z_stat.php%3Fid%3D1263800177' type='text/javascript'%3E%3C/script%3E\"));\n</script><span style=\"display:none;\" id=\"cnzz_stat_icon_1263800177\"><a href=\"http://www.cnzz.com/stat/website.php?web_id=1263800177\" target=\"_blank\" title=\"站长统计\">站长统计</a></span><script src=\"./分布式任务调度平台XXL-JOB_files/z_stat.php\" type=\"text/javascript\"></script><script src=\"./分布式任务调度平台XXL-JOB_files/core.php\" charset=\"utf-8\" type=\"text/javascript\"></script>\n<!-- cnzz end -->\n\n<div class=\"progress\" style=\"opacity: 0; width: 0%;\"></div></body></html>"
  },
  {
    "path": "open-xxl-job/doc/分布式任务调度平台XXL-JOB_files/analytics.js",
    "content": "(function(){var $c=function(a){this.w=a||[]};$c.prototype.set=function(a){this.w[a]=!0};$c.prototype.encode=function(){for(var a=[],b=0;b<this.w.length;b++)this.w[b]&&(a[Math.floor(b/6)]^=1<<b%6);for(b=0;b<a.length;b++)a[b]=\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_\".charAt(a[b]||0);return a.join(\"\")+\"~\"};var vd=new $c;function J(a){vd.set(a)}var Td=function(a){a=Dd(a);a=new $c(a);for(var b=vd.w.slice(),c=0;c<a.w.length;c++)b[c]=b[c]||a.w[c];return(new $c(b)).encode()},Dd=function(a){a=a.get(Gd);ka(a)||(a=[]);return a};var ea=function(a){return\"function\"==typeof a},ka=function(a){return\"[object Array]\"==Object.prototype.toString.call(Object(a))},qa=function(a){return void 0!=a&&-1<(a.constructor+\"\").indexOf(\"String\")},D=function(a,b){return 0==a.indexOf(b)},sa=function(a){return a?a.replace(/^[\\s\\xa0]+|[\\s\\xa0]+$/g,\"\"):\"\"},ra=function(){for(var a=O.navigator.userAgent+(M.cookie?M.cookie:\"\")+(M.referrer?M.referrer:\"\"),b=a.length,c=O.history.length;0<c;)a+=c--^b++;return[hd()^La(a)&2147483647,Math.round((new Date).getTime()/\n1E3)].join(\".\")},ta=function(a){var b=M.createElement(\"img\");b.width=1;b.height=1;b.src=a;return b},ua=function(){},K=function(a){if(encodeURIComponent instanceof Function)return encodeURIComponent(a);J(28);return a},L=function(a,b,c,d){try{a.addEventListener?a.addEventListener(b,c,!!d):a.attachEvent&&a.attachEvent(\"on\"+b,c)}catch(e){J(27)}},f=/^[\\w\\-:/.?=&%!]+$/,wa=function(a,b,c){a&&(c?(c=\"\",b&&f.test(b)&&(c=' id=\"'+b+'\"'),f.test(a)&&M.write(\"<script\"+c+' src=\"'+a+'\">\\x3c/script>')):(c=M.createElement(\"script\"),\nc.type=\"text/javascript\",c.async=!0,c.src=a,b&&(c.id=b),a=M.getElementsByTagName(\"script\")[0],a.parentNode.insertBefore(c,a)))},be=function(a,b){return E(M.location[b?\"href\":\"search\"],a)},E=function(a,b){return(a=a.match(\"(?:&|#|\\\\?)\"+K(b).replace(/([.*+?^=!:${}()|\\[\\]\\/\\\\])/g,\"\\\\$1\")+\"=([^&#]*)\"))&&2==a.length?a[1]:\"\"},xa=function(){var a=\"\"+M.location.hostname;return 0==a.indexOf(\"www.\")?a.substring(4):a},de=function(a,b){var c=a.indexOf(b);if(5==c||6==c)if(a=a.charAt(c+b.length),\"/\"==a||\"?\"==a||\n\"\"==a||\":\"==a)return!0;return!1},ya=function(a,b){var c=M.referrer;if(/^(https?|android-app):\\/\\//i.test(c)){if(a)return c;a=\"//\"+M.location.hostname;if(!de(c,a))return b&&(b=a.replace(/\\./g,\"-\")+\".cdn.ampproject.org\",de(c,b))?void 0:c}},za=function(a,b){if(1==b.length&&null!=b[0]&&\"object\"===typeof b[0])return b[0];for(var c={},d=Math.min(a.length+1,b.length),e=0;e<d;e++)if(\"object\"===typeof b[e]){for(var g in b[e])b[e].hasOwnProperty(g)&&(c[g]=b[e][g]);break}else e<a.length&&(c[a[e]]=b[e]);return c};var ee=function(){this.keys=[];this.values={};this.m={}};ee.prototype.set=function(a,b,c){this.keys.push(a);c?this.m[\":\"+a]=b:this.values[\":\"+a]=b};ee.prototype.get=function(a){return this.m.hasOwnProperty(\":\"+a)?this.m[\":\"+a]:this.values[\":\"+a]};ee.prototype.map=function(a){for(var b=0;b<this.keys.length;b++){var c=this.keys[b],d=this.get(c);d&&a(c,d)}};var O=window,M=document,va=function(a,b){return setTimeout(a,b)};var F=window,Ea=document,G=function(a){var b=F._gaUserPrefs;if(b&&b.ioo&&b.ioo()||a&&!0===F[\"ga-disable-\"+a])return!0;try{var c=F.external;if(c&&c._gaUserPrefs&&\"oo\"==c._gaUserPrefs)return!0}catch(g){}a=[];b=Ea.cookie.split(\";\");c=/^\\s*AMP_TOKEN=\\s*(.*?)\\s*$/;for(var d=0;d<b.length;d++){var e=b[d].match(c);e&&a.push(e[1])}for(b=0;b<a.length;b++)if(\"$OPT_OUT\"==decodeURIComponent(a[b]))return!0;return!1};var Ca=function(a){var b=[],c=M.cookie.split(\";\");a=new RegExp(\"^\\\\s*\"+a+\"=\\\\s*(.*?)\\\\s*$\");for(var d=0;d<c.length;d++){var e=c[d].match(a);e&&b.push(e[1])}return b},zc=function(a,b,c,d,e,g){e=G(e)?!1:eb.test(M.location.hostname)||\"/\"==c&&vc.test(d)?!1:!0;if(!e)return!1;b&&1200<b.length&&(b=b.substring(0,1200));c=a+\"=\"+b+\"; path=\"+c+\"; \";g&&(c+=\"expires=\"+(new Date((new Date).getTime()+g)).toGMTString()+\"; \");d&&\"none\"!==d&&(c+=\"domain=\"+d+\";\");d=M.cookie;M.cookie=c;if(!(d=d!=M.cookie))a:{a=Ca(a);\nfor(d=0;d<a.length;d++)if(b==a[d]){d=!0;break a}d=!1}return d},Cc=function(a){return encodeURIComponent?encodeURIComponent(a).replace(/\\(/g,\"%28\").replace(/\\)/g,\"%29\"):a},vc=/^(www\\.)?google(\\.com?)?(\\.[a-z]{2})?$/,eb=/(^|\\.)doubleclick\\.net$/i;var oc,Id=/^.*Version\\/?(\\d+)[^\\d].*$/i,ne=function(){if(void 0!==O.__ga4__)return O.__ga4__;if(void 0===oc){var a=O.navigator.userAgent;if(a){var b=a;try{b=decodeURIComponent(a)}catch(c){}if(a=!(0<=b.indexOf(\"Chrome\"))&&!(0<=b.indexOf(\"CriOS\"))&&(0<=b.indexOf(\"Safari/\")||0<=b.indexOf(\"Safari,\")))b=Id.exec(b),a=11<=(b?Number(b[1]):-1);oc=a}else oc=!1}return oc};var Fa,Ga,fb,Ab,ja=/^https?:\\/\\/[^/]*cdn\\.ampproject\\.org\\//,Ub=[],ic=function(){Z.D([ua])},tc=function(a,b){var c=Ca(\"AMP_TOKEN\");if(1<c.length)return J(55),!1;c=decodeURIComponent(c[0]||\"\");if(\"$OPT_OUT\"==c||\"$ERROR\"==c||G(b))return J(62),!1;if(!ja.test(M.referrer)&&\"$NOT_FOUND\"==c)return J(68),!1;if(void 0!==Ab)return J(56),va(function(){a(Ab)},0),!0;if(Fa)return Ub.push(a),!0;if(\"$RETRIEVING\"==c)return J(57),va(function(){tc(a,b)},1E4),!0;Fa=!0;c&&\"$\"!=c[0]||(xc(\"$RETRIEVING\",3E4),setTimeout(Mc,\n3E4),c=\"\");return Pc(c,b)?(Ub.push(a),!0):!1},Pc=function(a,b,c){if(!window.JSON)return J(58),!1;var d=O.XMLHttpRequest;if(!d)return J(59),!1;var e=new d;if(!(\"withCredentials\"in e))return J(60),!1;e.open(\"POST\",(c||\"https://ampcid.google.com/v1/publisher:getClientId\")+\"?key=AIzaSyA65lEHUEizIsNtlbNo-l2K18dT680nsaM\",!0);e.withCredentials=!0;e.setRequestHeader(\"Content-Type\",\"text/plain\");e.onload=function(){Fa=!1;if(4==e.readyState){try{200!=e.status&&(J(61),Qc(\"\",\"$ERROR\",3E4));var d=JSON.parse(e.responseText);\nd.optOut?(J(63),Qc(\"\",\"$OPT_OUT\",31536E6)):d.clientId?Qc(d.clientId,d.securityToken,31536E6):!c&&d.alternateUrl?(Ga&&clearTimeout(Ga),Fa=!0,Pc(a,b,d.alternateUrl)):(J(64),Qc(\"\",\"$NOT_FOUND\",36E5))}catch(ca){J(65),Qc(\"\",\"$ERROR\",3E4)}e=null}};d={originScope:\"AMP_ECID_GOOGLE\"};a&&(d.securityToken=a);e.send(JSON.stringify(d));Ga=va(function(){J(66);Qc(\"\",\"$ERROR\",3E4)},1E4);return!0},Mc=function(){Fa=!1},xc=function(a,b){if(void 0===fb){fb=\"\";for(var c=id(),d=0;d<c.length;d++){var e=c[d];if(zc(\"AMP_TOKEN\",\nencodeURIComponent(a),\"/\",e,\"\",b)){fb=e;return}}}zc(\"AMP_TOKEN\",encodeURIComponent(a),\"/\",fb,\"\",b)},Qc=function(a,b,c){Ga&&clearTimeout(Ga);b&&xc(b,c);Ab=a;b=Ub;Ub=[];for(c=0;c<b.length;c++)b[c](a)};var oe=function(){return(Ba||\"https:\"==M.location.protocol?\"https:\":\"http:\")+\"//www.google-analytics.com\"},Da=function(a){this.name=\"len\";this.message=a+\"-8192\"},ba=function(a,b,c){c=c||ua;if(2036>=b.length)wc(a,b,c);else if(8192>=b.length)x(a,b,c)||wd(a,b,c)||wc(a,b,c);else throw ge(\"len\",b.length),new Da(b.length);},pe=function(a,b,c,d){d=d||ua;wd(a+\"?\"+b,\"\",d,c)},wc=function(a,b,c){var d=ta(a+\"?\"+b);d.onload=d.onerror=function(){d.onload=null;d.onerror=null;c()}},wd=function(a,b,c,d){var e=O.XMLHttpRequest;\nif(!e)return!1;var g=new e;if(!(\"withCredentials\"in g))return!1;a=a.replace(/^http:/,\"https:\");g.open(\"POST\",a,!0);g.withCredentials=!0;g.setRequestHeader(\"Content-Type\",\"text/plain\");g.onreadystatechange=function(){if(4==g.readyState){if(d)try{var a=g.responseText;if(1>a.length)ge(\"xhr\",\"ver\",\"0\"),c();else if(\"1\"!=a.charAt(0))ge(\"xhr\",\"ver\",String(a.length)),c();else if(3<d.count++)ge(\"xhr\",\"tmr\",\"\"+d.count),c();else if(1==a.length)c();else{var b=a.charAt(1);if(\"d\"==b)pe(\"https://stats.g.doubleclick.net/j/collect\",\nd.U,d,c);else if(\"g\"==b){var e=\"https://www.google.%/ads/ga-audiences\".replace(\"%\",\"com\");wc(e,d.google,c);var w=a.substring(2);if(w)if(/^[a-z.]{1,6}$/.test(w)){var ha=\"https://www.google.%/ads/ga-audiences\".replace(\"%\",w);wc(ha,d.google,ua)}else ge(\"tld\",\"bcc\",w)}else ge(\"xhr\",\"brc\",b),c()}}catch(ue){ge(\"xhr\",\"rsp\"),c()}else c();g=null}};g.send(b);return!0},x=function(a,b,c){return O.navigator.sendBeacon?O.navigator.sendBeacon(a,b)?(c(),!0):!1:!1},ge=function(a,b,c){1<=100*Math.random()||G(\"?\")||\n(a=[\"t=error\",\"_e=\"+a,\"_v=j67\",\"sr=1\"],b&&a.push(\"_f=\"+b),c&&a.push(\"_m=\"+K(c.substring(0,100))),a.push(\"aip=1\"),a.push(\"z=\"+hd()),wc(\"https://www.google-analytics.com/u/d\",a.join(\"&\"),ua))};var h=function(a){var b=O.gaData=O.gaData||{};return b[a]=b[a]||{}};var Ha=function(){this.M=[]};Ha.prototype.add=function(a){this.M.push(a)};Ha.prototype.D=function(a){try{for(var b=0;b<this.M.length;b++){var c=a.get(this.M[b]);c&&ea(c)&&c.call(O,a)}}catch(d){}b=a.get(Ia);b!=ua&&ea(b)&&(a.set(Ia,ua,!0),setTimeout(b,10))};function Ja(a){if(100!=a.get(Ka)&&La(P(a,Q))%1E4>=100*R(a,Ka))throw\"abort\";}function Ma(a){if(G(P(a,Na)))throw\"abort\";}function Oa(){var a=M.location.protocol;if(\"http:\"!=a&&\"https:\"!=a)throw\"abort\";}\nfunction Pa(a){try{O.navigator.sendBeacon?J(42):O.XMLHttpRequest&&\"withCredentials\"in new O.XMLHttpRequest&&J(40)}catch(c){}a.set(ld,Td(a),!0);a.set(Ac,R(a,Ac)+1);var b=[];Qa.map(function(c,d){d.F&&(c=a.get(c),void 0!=c&&c!=d.defaultValue&&(\"boolean\"==typeof c&&(c*=1),b.push(d.F+\"=\"+K(\"\"+c))))});b.push(\"z=\"+Bd());a.set(Ra,b.join(\"&\"),!0)}\nfunction Sa(a){var b=P(a,gd)||oe()+\"/collect\",c=a.get(qe),d=P(a,fa);!d&&a.get(Vd)&&(d=\"beacon\");if(c)pe(b,P(a,Ra),c,a.get(Ia));else if(d){c=d;d=P(a,Ra);var e=a.get(Ia);e=e||ua;\"image\"==c?wc(b,d,e):\"xhr\"==c&&wd(b,d,e)||\"beacon\"==c&&x(b,d,e)||ba(b,d,e)}else ba(b,P(a,Ra),a.get(Ia));b=a.get(Na);b=h(b);c=b.hitcount;b.hitcount=c?c+1:1;b=a.get(Na);delete h(b).pending_experiments;a.set(Ia,ua,!0)}\nfunction Hc(a){(O.gaData=O.gaData||{}).expId&&a.set(Nc,(O.gaData=O.gaData||{}).expId);(O.gaData=O.gaData||{}).expVar&&a.set(Oc,(O.gaData=O.gaData||{}).expVar);var b=a.get(Na);if(b=h(b).pending_experiments){var c=[];for(d in b)b.hasOwnProperty(d)&&b[d]&&c.push(encodeURIComponent(d)+\".\"+encodeURIComponent(b[d]));var d=c.join(\"!\")}else d=void 0;d&&a.set(m,d,!0)}function cd(){if(O.navigator&&\"preview\"==O.navigator.loadPurpose)throw\"abort\";}\nfunction yd(a){var b=O.gaDevIds;ka(b)&&0!=b.length&&a.set(\"&did\",b.join(\",\"),!0)}function vb(a){if(!a.get(Na))throw\"abort\";};var hd=function(){return Math.round(2147483647*Math.random())},Bd=function(){try{var a=new Uint32Array(1);O.crypto.getRandomValues(a);return a[0]&2147483647}catch(b){return hd()}};function Ta(a){var b=R(a,Ua);500<=b&&J(15);var c=P(a,Va);if(\"transaction\"!=c&&\"item\"!=c){c=R(a,Wa);var d=(new Date).getTime(),e=R(a,Xa);0==e&&a.set(Xa,d);e=Math.round(2*(d-e)/1E3);0<e&&(c=Math.min(c+e,20),a.set(Xa,d));if(0>=c)throw\"abort\";a.set(Wa,--c)}a.set(Ua,++b)};var Ya=function(){this.data=new ee},Qa=new ee,Za=[];Ya.prototype.get=function(a){var b=$a(a),c=this.data.get(a);b&&void 0==c&&(c=ea(b.defaultValue)?b.defaultValue():b.defaultValue);return b&&b.Z?b.Z(this,a,c):c};var P=function(a,b){a=a.get(b);return void 0==a?\"\":\"\"+a},R=function(a,b){a=a.get(b);return void 0==a||\"\"===a?0:1*a};Ya.prototype.set=function(a,b,c){if(a)if(\"object\"==typeof a)for(var d in a)a.hasOwnProperty(d)&&ab(this,d,a[d],c);else ab(this,a,b,c)};\nvar ab=function(a,b,c,d){if(void 0!=c)switch(b){case Na:wb.test(c)}var e=$a(b);e&&e.o?e.o(a,b,c,d):a.data.set(b,c,d)},bb=function(a,b,c,d,e){this.name=a;this.F=b;this.Z=d;this.o=e;this.defaultValue=c},$a=function(a){var b=Qa.get(a);if(!b)for(var c=0;c<Za.length;c++){var d=Za[c],e=d[0].exec(a);if(e){b=d[1](e);Qa.set(b.name,b);break}}return b},yc=function(a){var b;Qa.map(function(c,d){d.F==a&&(b=d)});return b&&b.name},S=function(a,b,c,d,e){a=new bb(a,b,c,d,e);Qa.set(a.name,a);return a.name},cb=function(a,\nb){Za.push([new RegExp(\"^\"+a+\"$\"),b])},T=function(a,b,c){return S(a,b,c,void 0,db)},db=function(){};var gb=qa(window.GoogleAnalyticsObject)&&sa(window.GoogleAnalyticsObject)||\"ga\",jd=/^(?:utma\\.)?\\d+\\.\\d+$/,kd=/^amp-[\\w.-]{22,64}$/,Ba=!1,hb=T(\"apiVersion\",\"v\"),ib=T(\"clientVersion\",\"_v\");S(\"anonymizeIp\",\"aip\");var jb=S(\"adSenseId\",\"a\"),Va=S(\"hitType\",\"t\"),Ia=S(\"hitCallback\"),Ra=S(\"hitPayload\");S(\"nonInteraction\",\"ni\");S(\"currencyCode\",\"cu\");S(\"dataSource\",\"ds\");var Vd=S(\"useBeacon\",void 0,!1),fa=S(\"transport\");S(\"sessionControl\",\"sc\",\"\");S(\"sessionGroup\",\"sg\");S(\"queueTime\",\"qt\");var Ac=S(\"_s\",\"_s\");\nS(\"screenName\",\"cd\");var kb=S(\"location\",\"dl\",\"\"),lb=S(\"referrer\",\"dr\"),mb=S(\"page\",\"dp\",\"\");S(\"hostname\",\"dh\");var nb=S(\"language\",\"ul\"),ob=S(\"encoding\",\"de\");S(\"title\",\"dt\",function(){return M.title||void 0});cb(\"contentGroup([0-9]+)\",function(a){return new bb(a[0],\"cg\"+a[1])});var pb=S(\"screenColors\",\"sd\"),qb=S(\"screenResolution\",\"sr\"),rb=S(\"viewportSize\",\"vp\"),sb=S(\"javaEnabled\",\"je\"),tb=S(\"flashVersion\",\"fl\");S(\"campaignId\",\"ci\");S(\"campaignName\",\"cn\");S(\"campaignSource\",\"cs\");\nS(\"campaignMedium\",\"cm\");S(\"campaignKeyword\",\"ck\");S(\"campaignContent\",\"cc\");var ub=S(\"eventCategory\",\"ec\"),xb=S(\"eventAction\",\"ea\"),yb=S(\"eventLabel\",\"el\"),zb=S(\"eventValue\",\"ev\"),Bb=S(\"socialNetwork\",\"sn\"),Cb=S(\"socialAction\",\"sa\"),Db=S(\"socialTarget\",\"st\"),Eb=S(\"l1\",\"plt\"),Fb=S(\"l2\",\"pdt\"),Gb=S(\"l3\",\"dns\"),Hb=S(\"l4\",\"rrt\"),Ib=S(\"l5\",\"srt\"),Jb=S(\"l6\",\"tcp\"),Kb=S(\"l7\",\"dit\"),Lb=S(\"l8\",\"clt\"),Mb=S(\"timingCategory\",\"utc\"),Nb=S(\"timingVar\",\"utv\"),Ob=S(\"timingLabel\",\"utl\"),Pb=S(\"timingValue\",\"utt\");\nS(\"appName\",\"an\");S(\"appVersion\",\"av\",\"\");S(\"appId\",\"aid\",\"\");S(\"appInstallerId\",\"aiid\",\"\");S(\"exDescription\",\"exd\");S(\"exFatal\",\"exf\");var Nc=S(\"expId\",\"xid\"),Oc=S(\"expVar\",\"xvar\"),m=S(\"exp\",\"exp\"),Rc=S(\"_utma\",\"_utma\"),Sc=S(\"_utmz\",\"_utmz\"),Tc=S(\"_utmht\",\"_utmht\"),Ua=S(\"_hc\",void 0,0),Xa=S(\"_ti\",void 0,0),Wa=S(\"_to\",void 0,20);cb(\"dimension([0-9]+)\",function(a){return new bb(a[0],\"cd\"+a[1])});cb(\"metric([0-9]+)\",function(a){return new bb(a[0],\"cm\"+a[1])});S(\"linkerParam\",void 0,void 0,Bc,db);\nvar ld=S(\"usage\",\"_u\"),Gd=S(\"_um\");S(\"forceSSL\",void 0,void 0,function(){return Ba},function(a,b,c){J(34);Ba=!!c});var ed=S(\"_j1\",\"jid\"),ia=S(\"_j2\",\"gjid\");cb(\"\\\\&(.*)\",function(a){var b=new bb(a[0],a[1]),c=yc(a[0].substring(1));c&&(b.Z=function(a){return a.get(c)},b.o=function(a,b,g,ca){a.set(c,g,ca)},b.F=void 0);return b});\nvar Qb=T(\"_oot\"),dd=S(\"previewTask\"),Rb=S(\"checkProtocolTask\"),md=S(\"validationTask\"),Sb=S(\"checkStorageTask\"),Uc=S(\"historyImportTask\"),Tb=S(\"samplerTask\"),Vb=S(\"_rlt\"),Wb=S(\"buildHitTask\"),Xb=S(\"sendHitTask\"),Vc=S(\"ceTask\"),zd=S(\"devIdTask\"),Cd=S(\"timingTask\"),Ld=S(\"displayFeaturesTask\"),oa=S(\"customTask\"),V=T(\"name\"),Q=T(\"clientId\",\"cid\"),n=T(\"clientIdTime\"),xd=T(\"storedClientId\"),Ad=S(\"userId\",\"uid\"),Na=T(\"trackingId\",\"tid\"),U=T(\"cookieName\",void 0,\"_ga\"),W=T(\"cookieDomain\"),Yb=T(\"cookiePath\",\nvoid 0,\"/\"),Zb=T(\"cookieExpires\",void 0,63072E3),Hd=T(\"cookieUpdate\",void 0,!0),$b=T(\"legacyCookieDomain\"),Wc=T(\"legacyHistoryImport\",void 0,!0),ac=T(\"storage\",void 0,\"cookie\"),bc=T(\"allowLinker\",void 0,!1),cc=T(\"allowAnchor\",void 0,!0),Ka=T(\"sampleRate\",\"sf\",100),dc=T(\"siteSpeedSampleRate\",void 0,1),ec=T(\"alwaysSendReferrer\",void 0,!1),I=T(\"_gid\",\"_gid\"),la=T(\"_gcn\"),Kd=T(\"useAmpClientId\"),ce=T(\"_gclid\"),fe=T(\"_gt\"),he=T(\"_ge\",void 0,7776E6),ie=T(\"_gclsrc\"),je=T(\"storeGac\",void 0,!0),gd=S(\"transportUrl\"),\nMd=S(\"_r\",\"_r\"),qe=S(\"_dp\");function X(a,b,c,d){b[a]=function(){try{return d&&J(d),c.apply(this,arguments)}catch(e){throw ge(\"exc\",a,e&&e.name),e;}}};var Od=function(){this.V=100;this.$=this.fa=!1;this.oa=\"detourexp\";this.ea=1},Ed=function(a){var b=new Od,c;if(b.fa&&b.$)return 0;b.$=!0;if(a){if(b.oa&&void 0!==a.get(b.oa))return R(a,b.oa);if(0==a.get(dc))return 0}if(0==b.V)return 0;void 0===c&&(c=Bd());return 0==c%b.V?Math.floor(c/b.V)%b.ea+1:0};function fc(){var a,b;if((b=(b=O.navigator)?b.plugins:null)&&b.length)for(var c=0;c<b.length&&!a;c++){var d=b[c];-1<d.name.indexOf(\"Shockwave Flash\")&&(a=d.description)}if(!a)try{var e=new ActiveXObject(\"ShockwaveFlash.ShockwaveFlash.7\");a=e.GetVariable(\"$version\")}catch(g){}if(!a)try{e=new ActiveXObject(\"ShockwaveFlash.ShockwaveFlash.6\"),a=\"WIN 6,0,21,0\",e.AllowScriptAccess=\"always\",a=e.GetVariable(\"$version\")}catch(g){}if(!a)try{e=new ActiveXObject(\"ShockwaveFlash.ShockwaveFlash\"),a=e.GetVariable(\"$version\")}catch(g){}a&&\n(e=a.match(/[\\d]+/g))&&3<=e.length&&(a=e[0]+\".\"+e[1]+\" r\"+e[2]);return a||void 0};var aa=function(a){var b=Math.min(R(a,dc),100);return La(P(a,Q))%100>=b?!1:!0},gc=function(a){var b={};if(Ec(b)||Fc(b)){var c=b[Eb];void 0==c||Infinity==c||isNaN(c)||(0<c?(Y(b,Gb),Y(b,Jb),Y(b,Ib),Y(b,Fb),Y(b,Hb),Y(b,Kb),Y(b,Lb),va(function(){a(b)},10)):L(O,\"load\",function(){gc(a)},!1))}},Ec=function(a){var b=O.performance||O.webkitPerformance;b=b&&b.timing;if(!b)return!1;var c=b.navigationStart;if(0==c)return!1;a[Eb]=b.loadEventStart-c;a[Gb]=b.domainLookupEnd-b.domainLookupStart;a[Jb]=b.connectEnd-\nb.connectStart;a[Ib]=b.responseStart-b.requestStart;a[Fb]=b.responseEnd-b.responseStart;a[Hb]=b.fetchStart-c;a[Kb]=b.domInteractive-c;a[Lb]=b.domContentLoadedEventStart-c;return!0},Fc=function(a){if(O.top!=O)return!1;var b=O.external,c=b&&b.onloadT;b&&!b.isValidLoadTime&&(c=void 0);2147483648<c&&(c=void 0);0<c&&b.setPageReadyTime();if(void 0==c)return!1;a[Eb]=c;return!0},Y=function(a,b){var c=a[b];if(isNaN(c)||Infinity==c||0>c)a[b]=void 0},Fd=function(a){return function(b){if(\"pageview\"==b.get(Va)&&\n!a.I){a.I=!0;var c=aa(b),d=0<E(b.get(kb),\"gclid\").length;(c||d)&&gc(function(b){c&&a.send(\"timing\",b);d&&a.send(\"adtiming\",b)})}}};var hc=!1,mc=function(a){if(\"cookie\"==P(a,ac)){if(a.get(Hd)||P(a,xd)!=P(a,Q)){var b=1E3*R(a,Zb);ma(a,Q,U,b)}ma(a,I,la,864E5);if(a.get(je)){var c=a.get(ce);if(c){var d=Math.min(R(a,he),1E3*R(a,Zb));d=Math.min(d,1E3*R(a,fe)+d-(new Date).getTime());a.data.set(he,d);b={};var e=a.get(fe),g=a.get(ie),ca=kc(P(a,Yb)),l=lc(P(a,W)),k=P(a,Na);g&&\"aw.ds\"!=g?b&&(b.ua=!0):(c=[\"1\",e,Cc(c)].join(\".\"),0<d&&(b&&(b.ta=!0),zc(\"_gac_\"+Cc(k),c,ca,l,k,d)));le(b)}}else J(75);if(a=\"none\"===lc(P(a,W)))a=M.location.hostname,\na=eb.test(a)||vc.test(a);a&&J(30)}},ma=function(a,b,c,d){var e=nd(a,b);if(e){c=P(a,c);var g=kc(P(a,Yb)),ca=lc(P(a,W)),l=P(a,Na);if(\"auto\"!=ca)zc(c,e,g,ca,l,d)&&(hc=!0);else{J(32);for(var k=id(),w=0;w<k.length;w++)if(ca=k[w],a.data.set(W,ca),e=nd(a,b),zc(c,e,g,ca,l,d)){hc=!0;return}a.data.set(W,\"auto\")}}},nc=function(a){if(\"cookie\"==P(a,ac)&&!hc&&(mc(a),!hc))throw\"abort\";},Yc=function(a){if(a.get(Wc)){var b=P(a,W),c=P(a,$b)||xa(),d=Xc(\"__utma\",c,b);d&&(J(19),a.set(Tc,(new Date).getTime(),!0),a.set(Rc,\nd.R),(b=Xc(\"__utmz\",c,b))&&d.hash==b.hash&&a.set(Sc,b.R))}},nd=function(a,b){b=Cc(P(a,b));var c=lc(P(a,W)).split(\".\").length;a=jc(P(a,Yb));1<a&&(c+=\"-\"+a);return b?[\"GA1\",c,b].join(\".\"):\"\"},Xd=function(a,b){return na(b,P(a,W),P(a,Yb))},na=function(a,b,c){if(!a||1>a.length)J(12);else{for(var d=[],e=0;e<a.length;e++){var g=a[e];var ca=g.split(\".\");var l=ca.shift();(\"GA1\"==l||\"1\"==l)&&1<ca.length?(g=ca.shift().split(\"-\"),1==g.length&&(g[1]=\"1\"),g[0]*=1,g[1]*=1,ca={H:g,s:ca.join(\".\")}):ca=kd.test(g)?\n{H:[0,0],s:g}:void 0;ca&&d.push(ca)}if(1==d.length)return J(13),d[0].s;if(0==d.length)J(12);else{J(14);d=Gc(d,lc(b).split(\".\").length,0);if(1==d.length)return d[0].s;d=Gc(d,jc(c),1);1<d.length&&J(41);return d[0]&&d[0].s}}},Gc=function(a,b,c){for(var d=[],e=[],g,ca=0;ca<a.length;ca++){var l=a[ca];l.H[c]==b?d.push(l):void 0==g||l.H[c]<g?(e=[l],g=l.H[c]):l.H[c]==g&&e.push(l)}return 0<d.length?d:e},lc=function(a){return 0==a.indexOf(\".\")?a.substr(1):a},id=function(){var a=[],b=xa().split(\".\");if(4==b.length){var c=\nb[b.length-1];if(parseInt(c,10)==c)return[\"none\"]}for(c=b.length-2;0<=c;c--)a.push(b.slice(c).join(\".\"));a.push(\"none\");return a},kc=function(a){if(!a)return\"/\";1<a.length&&a.lastIndexOf(\"/\")==a.length-1&&(a=a.substr(0,a.length-1));0!=a.indexOf(\"/\")&&(a=\"/\"+a);return a},jc=function(a){a=kc(a);return\"/\"==a?1:a.split(\"/\").length},le=function(a){a.ta&&J(77);a.na&&J(74);a.pa&&J(73);a.ua&&J(69)};function Xc(a,b,c){\"none\"==b&&(b=\"\");var d=[],e=Ca(a);a=\"__utma\"==a?6:2;for(var g=0;g<e.length;g++){var ca=(\"\"+e[g]).split(\".\");ca.length>=a&&d.push({hash:ca[0],R:e[g],O:ca})}if(0!=d.length)return 1==d.length?d[0]:Zc(b,d)||Zc(c,d)||Zc(null,d)||d[0]}function Zc(a,b){if(null==a)var c=a=1;else c=La(a),a=La(D(a,\".\")?a.substring(1):\".\"+a);for(var d=0;d<b.length;d++)if(b[d].hash==c||b[d].hash==a)return b[d]};var od=new RegExp(/^https?:\\/\\/([^\\/:]+)/),pd=/(.*)([?&#])(?:_ga=[^&#]*)(?:&?)(.*)/,me=/(.*)([?&#])(?:_gac=[^&#]*)(?:&?)(.*)/;function Bc(a){var b=a.get(Q),c=a.get(I)||\"\";b=\"_ga=2.\"+K(pa(c+b,0)+\".\"+c+\"-\"+b);if((c=a.get(ce))&&a.get(je)){var d=R(a,fe);1E3*d+R(a,he)<=(new Date).getTime()?(J(76),a=\"\"):(J(44),a=\"&_gac=1.\"+K([pa(c,0),d,c].join(\".\")))}else a=\"\";return b+a}\nfunction Ic(a,b){var c=new Date,d=O.navigator,e=d.plugins||[];a=[a,d.userAgent,c.getTimezoneOffset(),c.getYear(),c.getDate(),c.getHours(),c.getMinutes()+b];for(b=0;b<e.length;++b)a.push(e[b].description);return La(a.join(\".\"))}function pa(a,b){var c=new Date,d=O.navigator,e=c.getHours()+Math.floor((c.getMinutes()+b)/60);return La([a,d.userAgent,d.language||\"\",c.getTimezoneOffset(),c.getYear(),c.getDate()+Math.floor(e/24),(24+e)%24,(60+c.getMinutes()+b)%60].join(\".\"))}\nvar Dc=function(a){J(48);this.target=a;this.T=!1};Dc.prototype.ca=function(a,b){if(a.tagName){if(\"a\"==a.tagName.toLowerCase()){a.href&&(a.href=qd(this,a.href,b));return}if(\"form\"==a.tagName.toLowerCase())return rd(this,a)}if(\"string\"==typeof a)return qd(this,a,b)};\nvar qd=function(a,b,c){var d=pd.exec(b);d&&3<=d.length&&(b=d[1]+(d[3]?d[2]+d[3]:\"\"));(d=me.exec(b))&&3<=d.length&&(b=d[1]+(d[3]?d[2]+d[3]:\"\"));a=a.target.get(\"linkerParam\");var e=b.indexOf(\"?\");d=b.indexOf(\"#\");c?b+=(-1==d?\"#\":\"&\")+a:(c=-1==e?\"?\":\"&\",b=-1==d?b+(c+a):b.substring(0,d)+c+a+b.substring(d));b=b.replace(/&+_ga=/,\"&_ga=\");return b=b.replace(/&+_gac=/,\"&_gac=\")},rd=function(a,b){if(b&&b.action)if(\"get\"==b.method.toLowerCase()){a=a.target.get(\"linkerParam\").split(\"&\");for(var c=0;c<a.length;c++){var d=\na[c].split(\"=\"),e=d[1];d=d[0];for(var g=b.childNodes||[],ca=!1,l=0;l<g.length;l++)if(g[l].name==d){g[l].setAttribute(\"value\",e);ca=!0;break}ca||(g=M.createElement(\"input\"),g.setAttribute(\"type\",\"hidden\"),g.setAttribute(\"name\",d),g.setAttribute(\"value\",e),b.appendChild(g))}}else\"post\"==b.method.toLowerCase()&&(b.action=qd(a,b.action))};\nDc.prototype.S=function(a,b,c){function d(c){try{c=c||O.event;a:{var d=c.target||c.srcElement;for(c=100;d&&0<c;){if(d.href&&d.nodeName.match(/^a(?:rea)?$/i)){var g=d;break a}d=d.parentNode;c--}g={}}(\"http:\"==g.protocol||\"https:\"==g.protocol)&&sd(a,g.hostname||\"\")&&g.href&&(g.href=qd(e,g.href,b))}catch(k){J(26)}}var e=this;this.T||(this.T=!0,L(M,\"mousedown\",d,!1),L(M,\"keyup\",d,!1));c&&L(M,\"submit\",function(b){b=b||O.event;if((b=b.target||b.srcElement)&&b.action){var c=b.action.match(od);c&&sd(a,c[1])&&\nrd(e,b)}})};function sd(a,b){if(b==M.location.hostname)return!1;for(var c=0;c<a.length;c++)if(a[c]instanceof RegExp){if(a[c].test(b))return!0}else if(0<=b.indexOf(a[c]))return!0;return!1}function ke(a,b){return b!=Ic(a,0)&&b!=Ic(a,-1)&&b!=Ic(a,-2)&&b!=pa(a,0)&&b!=pa(a,-1)&&b!=pa(a,-2)};var p=/^(GTM|OPT)-[A-Z0-9]+$/,q=/;_gaexp=[^;]*/g,r=/;((__utma=)|([^;=]+=GAX?\\d+\\.))[^;]*/g,Aa=/^https?:\\/\\/[\\w\\-.]+\\.google.com(:\\d+)?\\/optimize\\/opt-launch\\.html\\?.*$/,t=function(a){function b(a,b){b&&(c+=\"&\"+a+\"=\"+K(b))}var c=\"https://www.google-analytics.com/gtm/js?id=\"+K(a.id);\"dataLayer\"!=a.B&&b(\"l\",a.B);b(\"t\",a.target);b(\"cid\",a.clientId);b(\"cidt\",a.ka);b(\"gac\",a.la);b(\"aip\",a.ia);a.sync&&b(\"m\",\"sync\");b(\"cycle\",a.G);a.qa&&b(\"gclid\",a.qa);Aa.test(M.referrer)&&b(\"cb\",String(hd()));return c};var Jd=function(a,b,c){this.aa=b;(b=c)||(b=(b=P(a,V))&&\"t0\"!=b?Wd.test(b)?\"_gat_\"+Cc(P(a,Na)):\"_gat_\"+Cc(b):\"_gat\");this.Y=b;this.ra=null},Rd=function(a,b){var c=b.get(Wb);b.set(Wb,function(b){Pd(a,b,ed);Pd(a,b,ia);var d=c(b);Qd(a,b);return d});var d=b.get(Xb);b.set(Xb,function(b){var c=d(b);if(b.get(ed)){if(ne()!==H(a,b)){J(80);var e={U:re(a,b,1),google:re(a,b,2),count:0};pe(\"https://stats.g.doubleclick.net/j/collect\",e.U,e)}else ta(re(a,b,0));b.set(ed,\"\",!0)}return c})},Pd=function(a,b,c){b.get(c)||\n(\"1\"==Ca(a.Y)[0]?b.set(c,\"\",!0):b.set(c,\"\"+hd(),!0))},Qd=function(a,b){b.get(ed)&&zc(a.Y,\"1\",b.get(Yb),b.get(W),b.get(Na),6E4)},re=function(a,b,c){var d=new ee,e=function(a){$a(a).F&&d.set($a(a).F,b.get(a))};e(hb);e(ib);e(Na);e(Q);e(ed);if(0==c||1==c)e(Ad),e(ia),e(I);d.set($a(ld).F,Td(b));var g=\"\";d.map(function(a,b){g+=K(a)+\"=\";g+=K(\"\"+b)+\"&\"});g+=\"z=\"+hd();0==c?g=a.aa+g:1==c?g=\"t=dc&aip=1&_r=3&\"+g:2==c&&(g=\"t=sr&aip=1&_r=4&slf_rd=1&\"+g);return g},H=function(a,b){null===a.ra&&(a.ra=1===Ed(b),a.ra&&\nJ(33));return a.ra},Wd=/^gtm\\d+$/;var fd=function(a,b){a=a.b;if(!a.get(\"dcLoaded\")){var c=new $c(Dd(a));c.set(29);a.set(Gd,c.w);b=b||{};var d;b[U]&&(d=Cc(b[U]));b=new Jd(a,\"https://stats.g.doubleclick.net/r/collect?t=dc&aip=1&_r=3&\",d);Rd(b,a);a.set(\"dcLoaded\",!0)}};var Sd=function(a){if(!a.get(\"dcLoaded\")&&\"cookie\"==a.get(ac)){var b=new Jd(a);Pd(b,a,ed);Pd(b,a,ia);Qd(b,a);if(a.get(ed)){var c=ne()!==H(b,a);a.set(Md,1,!0);c?(J(79),a.set(gd,oe()+\"/j/collect\",!0),a.set(qe,{U:re(b,a,1),google:re(b,a,2),count:0},!0)):a.set(gd,oe()+\"/r/collect\",!0)}}};var Lc=function(){var a=O.gaGlobal=O.gaGlobal||{};return a.hid=a.hid||hd()};var ad,bd=function(a,b,c){if(!ad){var d=M.location.hash;var e=O.name,g=/^#?gaso=([^&]*)/;if(e=(d=(d=d&&d.match(g)||e&&e.match(g))?d[1]:Ca(\"GASO\")[0]||\"\")&&d.match(/^(?:!([-0-9a-z.]{1,40})!)?([-.\\w]{10,1200})$/i))zc(\"GASO\",\"\"+d,c,b,a,0),window._udo||(window._udo=b),window._utcp||(window._utcp=c),a=e[1],wa(\"https://www.google.com/analytics/web/inpage/pub/inpage.js?\"+(a?\"prefix=\"+a+\"&\":\"\")+hd(),\"_gasojs\");ad=!0}};var wb=/^(UA|YT|MO|GP)-(\\d+)-(\\d+)$/,pc=function(a){function b(a,b){d.b.data.set(a,b)}function c(a,c){b(a,c);d.filters.add(a)}var d=this;this.b=new Ya;this.filters=new Ha;b(V,a[V]);b(Na,sa(a[Na]));b(U,a[U]);b(W,a[W]||xa());b(Yb,a[Yb]);b(Zb,a[Zb]);b(Hd,a[Hd]);b($b,a[$b]);b(Wc,a[Wc]);b(bc,a[bc]);b(cc,a[cc]);b(Ka,a[Ka]);b(dc,a[dc]);b(ec,a[ec]);b(ac,a[ac]);b(Ad,a[Ad]);b(n,a[n]);b(Kd,a[Kd]);b(je,a[je]);b(hb,1);b(ib,\"j67\");c(Qb,Ma);c(oa,ua);c(dd,cd);c(Rb,Oa);c(md,vb);c(Sb,nc);c(Uc,Yc);c(Tb,Ja);c(Vb,Ta);\nc(Vc,Hc);c(zd,yd);c(Ld,Sd);c(Wb,Pa);c(Xb,Sa);c(Cd,Fd(this));Kc(this.b);Jc(this.b,a[Q]);this.b.set(jb,Lc());bd(this.b.get(Na),this.b.get(W),this.b.get(Yb))},Jc=function(a,b){var c=P(a,U);a.data.set(la,\"_ga\"==c?\"_gid\":c+\"_gid\");if(\"cookie\"==P(a,ac)){hc=!1;c=Ca(P(a,U));c=Xd(a,c);if(!c){c=P(a,W);var d=P(a,$b)||xa();c=Xc(\"__utma\",d,c);void 0!=c?(J(10),c=c.O[1]+\".\"+c.O[2]):c=void 0}c&&(hc=!0);if(d=c&&!a.get(Hd))if(d=c.split(\".\"),2!=d.length)d=!1;else if(d=Number(d[1])){var e=R(a,Zb);d=d+e<(new Date).getTime()/\n1E3}else d=!1;d&&(c=void 0);c&&(a.data.set(xd,c),a.data.set(Q,c),c=Ca(P(a,la)),(c=Xd(a,c))&&a.data.set(I,c));if(a.get(je)&&(c=a.get(ce),d=a.get(ie),!c||d&&\"aw.ds\"!=d)){c={};if(M){d=[];e=M.cookie.split(\";\");for(var g=/^\\s*_gac_(UA-\\d+-\\d+)=\\s*(.+?)\\s*$/,ca=0;ca<e.length;ca++){var l=e[ca].match(g);l&&d.push({ja:l[1],value:l[2]})}e={};if(d&&d.length)for(g=0;g<d.length;g++)(ca=d[g].value.split(\".\"),\"1\"!=ca[0]||3!=ca.length)?c&&(c.na=!0):ca[1]&&(e[d[g].ja]?c&&(c.pa=!0):e[d[g].ja]=[],e[d[g].ja].push({timestamp:ca[1],\nqa:ca[2]}));d=e}else d={};d=d[P(a,Na)];le(c);d&&0!=d.length&&(c=d[0],a.data.set(fe,c.timestamp),a.data.set(ce,c.qa))}}if(a.get(Hd))a:if(d=be(\"_ga\",a.get(cc)))if(a.get(bc))if(c=d.indexOf(\".\"),-1==c)J(22);else{e=d.substring(0,c);g=d.substring(c+1);c=g.indexOf(\".\");d=g.substring(0,c);g=g.substring(c+1);if(\"1\"==e){if(c=g,ke(c,d)){J(23);break a}}else if(\"2\"==e){c=g.indexOf(\"-\");e=\"\";0<c?(e=g.substring(0,c),c=g.substring(c+1)):c=g.substring(1);if(ke(e+c,d)){J(53);break a}e&&(J(2),a.data.set(I,e))}else{J(22);\nbreak a}J(11);a.data.set(Q,c);if(c=be(\"_gac\",a.get(cc)))c=c.split(\".\"),\"1\"!=c[0]||4!=c.length?J(72):ke(c[3],c[1])?J(71):(a.data.set(ce,c[3]),a.data.set(fe,c[2]),J(70))}else J(21);b&&(J(9),a.data.set(Q,K(b)));a.get(Q)||((b=(b=O.gaGlobal&&O.gaGlobal.vid)&&-1!=b.search(jd)?b:void 0)?(J(17),a.data.set(Q,b)):(J(8),a.data.set(Q,ra())));a.get(I)||(J(3),a.data.set(I,ra()));mc(a)},Kc=function(a){var b=O.navigator,c=O.screen,d=M.location;a.set(lb,ya(a.get(ec),a.get(Kd)));if(d){var e=d.pathname||\"\";\"/\"!=e.charAt(0)&&\n(J(31),e=\"/\"+e);a.set(kb,d.protocol+\"//\"+d.hostname+e+d.search)}c&&a.set(qb,c.width+\"x\"+c.height);c&&a.set(pb,c.colorDepth+\"-bit\");c=M.documentElement;var g=(e=M.body)&&e.clientWidth&&e.clientHeight,ca=[];c&&c.clientWidth&&c.clientHeight&&(\"CSS1Compat\"===M.compatMode||!g)?ca=[c.clientWidth,c.clientHeight]:g&&(ca=[e.clientWidth,e.clientHeight]);c=0>=ca[0]||0>=ca[1]?\"\":ca.join(\"x\");a.set(rb,c);a.set(tb,fc());a.set(ob,M.characterSet||M.charset);a.set(sb,b&&\"function\"===typeof b.javaEnabled&&b.javaEnabled()||\n!1);a.set(nb,(b&&(b.language||b.browserLanguage)||\"\").toLowerCase());a.data.set(ce,be(\"gclid\",!0));a.data.set(ie,be(\"gclsrc\",!0));a.data.set(fe,Math.round((new Date).getTime()/1E3));if(d&&a.get(cc)&&(b=M.location.hash)){b=b.split(/[?&#]+/);d=[];for(c=0;c<b.length;++c)(D(b[c],\"utm_id\")||D(b[c],\"utm_campaign\")||D(b[c],\"utm_source\")||D(b[c],\"utm_medium\")||D(b[c],\"utm_term\")||D(b[c],\"utm_content\")||D(b[c],\"gclid\")||D(b[c],\"dclid\")||D(b[c],\"gclsrc\"))&&d.push(b[c]);0<d.length&&(b=\"#\"+d.join(\"&\"),a.set(kb,\na.get(kb)+b))}};pc.prototype.get=function(a){return this.b.get(a)};pc.prototype.set=function(a,b){this.b.set(a,b)};var qc={pageview:[mb],event:[ub,xb,yb,zb],social:[Bb,Cb,Db],timing:[Mb,Nb,Pb,Ob]};pc.prototype.send=function(a){if(!(1>arguments.length)){if(\"string\"===typeof arguments[0]){var b=arguments[0];var c=[].slice.call(arguments,1)}else b=arguments[0]&&arguments[0][Va],c=arguments;b&&(c=za(qc[b]||[],c),c[Va]=b,this.b.set(c,void 0,!0),this.filters.D(this.b),this.b.data.m={})}};\npc.prototype.ma=function(a,b){var c=this;u(a,c,b)||(v(a,function(){u(a,c,b)}),y(String(c.get(V)),a,void 0,b,!0))};var rc=function(a){if(\"prerender\"==M.visibilityState)return!1;a();return!0},z=function(a){if(!rc(a)){J(16);var b=!1,c=function(){if(!b&&rc(a)){b=!0;var d=c,e=M;e.removeEventListener?e.removeEventListener(\"visibilitychange\",d,!1):e.detachEvent&&e.detachEvent(\"onvisibilitychange\",d)}};L(M,\"visibilitychange\",c)}};var td=/^(?:(\\w+)\\.)?(?:(\\w+):)?(\\w+)$/,sc=function(a){if(ea(a[0]))this.u=a[0];else{var b=td.exec(a[0]);null!=b&&4==b.length&&(this.c=b[1]||\"t0\",this.K=b[2]||\"\",this.C=b[3],this.a=[].slice.call(a,1),this.K||(this.A=\"create\"==this.C,this.i=\"require\"==this.C,this.g=\"provide\"==this.C,this.ba=\"remove\"==this.C),this.i&&(3<=this.a.length?(this.X=this.a[1],this.W=this.a[2]):this.a[1]&&(qa(this.a[1])?this.X=this.a[1]:this.W=this.a[1])));b=a[1];a=a[2];if(!this.C)throw\"abort\";if(this.i&&(!qa(b)||\"\"==b))throw\"abort\";\nif(this.g&&(!qa(b)||\"\"==b||!ea(a)))throw\"abort\";if(ud(this.c)||ud(this.K))throw\"abort\";if(this.g&&\"t0\"!=this.c)throw\"abort\";}};function ud(a){return 0<=a.indexOf(\".\")||0<=a.indexOf(\":\")};var Yd,Zd,$d,A;Yd=new ee;$d=new ee;A=new ee;Zd={ec:45,ecommerce:46,linkid:47};\nvar u=function(a,b,c){b==N||b.get(V);var d=Yd.get(a);if(!ea(d))return!1;b.plugins_=b.plugins_||new ee;if(b.plugins_.get(a))return!0;b.plugins_.set(a,new d(b,c||{}));return!0},y=function(a,b,c,d,e){if(!ea(Yd.get(b))&&!$d.get(b)){Zd.hasOwnProperty(b)&&J(Zd[b]);if(p.test(b)){J(52);a=N.j(a);if(!a)return!0;c=d||{};d={id:b,B:c.dataLayer||\"dataLayer\",ia:!!a.get(\"anonymizeIp\"),sync:e,G:!1};a.get(\"&gtm\")==b&&(d.G=!0);var g=String(a.get(\"name\"));\"t0\"!=g&&(d.target=g);G(String(a.get(\"trackingId\")))||(d.clientId=\nString(a.get(Q)),d.ka=Number(a.get(n)),c=c.palindrome?r:q,c=(c=M.cookie.replace(/^|(; +)/g,\";\").match(c))?c.sort().join(\"\").substring(1):void 0,d.la=c,d.qa=E(a.b.get(kb)||\"\",\"gclid\"));a=d.B;c=(new Date).getTime();O[a]=O[a]||[];c={\"gtm.start\":c};e||(c.event=\"gtm.js\");O[a].push(c);c=t(d)}!c&&Zd.hasOwnProperty(b)?(J(39),c=b+\".js\"):J(43);c&&(c&&0<=c.indexOf(\"/\")||(c=(Ba||\"https:\"==M.location.protocol?\"https:\":\"http:\")+\"//www.google-analytics.com/plugins/ua/\"+c),d=ae(c),a=d.protocol,c=M.location.protocol,\n(\"https:\"==a||a==c||(\"http:\"!=a?0:\"http:\"==c))&&B(d)&&(wa(d.url,void 0,e),$d.set(b,!0)))}},v=function(a,b){var c=A.get(a)||[];c.push(b);A.set(a,c)},C=function(a,b){Yd.set(a,b);b=A.get(a)||[];for(var c=0;c<b.length;c++)b[c]();A.set(a,[])},B=function(a){var b=ae(M.location.href);if(D(a.url,\"https://www.google-analytics.com/gtm/js?id=\"))return!0;if(a.query||0<=a.url.indexOf(\"?\")||0<=a.path.indexOf(\"://\"))return!1;if(a.host==b.host&&a.port==b.port)return!0;b=\"http:\"==a.protocol?80:443;return\"www.google-analytics.com\"==\na.host&&(a.port||b)==b&&D(a.path,\"/plugins/\")?!0:!1},ae=function(a){function b(a){var b=(a.hostname||\"\").split(\":\")[0].toLowerCase(),c=(a.protocol||\"\").toLowerCase();c=1*a.port||(\"http:\"==c?80:\"https:\"==c?443:\"\");a=a.pathname||\"\";D(a,\"/\")||(a=\"/\"+a);return[b,\"\"+c,a]}var c=M.createElement(\"a\");c.href=M.location.href;var d=(c.protocol||\"\").toLowerCase(),e=b(c),g=c.search||\"\",ca=d+\"//\"+e[0]+(e[1]?\":\"+e[1]:\"\");D(a,\"//\")?a=d+a:D(a,\"/\")?a=ca+a:!a||D(a,\"?\")?a=ca+e[2]+(a||g):0>a.split(\"/\")[0].indexOf(\":\")&&\n(a=ca+e[2].substring(0,e[2].lastIndexOf(\"/\"))+\"/\"+a);c.href=a;d=b(c);return{protocol:(c.protocol||\"\").toLowerCase(),host:d[0],port:d[1],path:d[2],query:c.search||\"\",url:a||\"\"}};var Z={ga:function(){Z.f=[]}};Z.ga();Z.D=function(a){var b=Z.J.apply(Z,arguments);b=Z.f.concat(b);for(Z.f=[];0<b.length&&!Z.v(b[0])&&!(b.shift(),0<Z.f.length););Z.f=Z.f.concat(b)};Z.J=function(a){for(var b=[],c=0;c<arguments.length;c++)try{var d=new sc(arguments[c]);d.g?C(d.a[0],d.a[1]):(d.i&&(d.ha=y(d.c,d.a[0],d.X,d.W)),b.push(d))}catch(e){}return b};\nZ.v=function(a){try{if(a.u)a.u.call(O,N.j(\"t0\"));else{var b=a.c==gb?N:N.j(a.c);if(a.A){if(\"t0\"==a.c&&(b=N.create.apply(N,a.a),null===b))return!0}else if(a.ba)N.remove(a.c);else if(b)if(a.i){if(a.ha&&(a.ha=y(a.c,a.a[0],a.X,a.W)),!u(a.a[0],b,a.W))return!0}else if(a.K){var c=a.C,d=a.a,e=b.plugins_.get(a.K);e[c].apply(e,d)}else b[a.C].apply(b,a.a)}}catch(g){}};var N=function(a){J(1);Z.D.apply(Z,[arguments])};N.h={};N.P=[];N.L=0;N.answer=42;var uc=[Na,W,V];\nN.create=function(a){var b=za(uc,[].slice.call(arguments));b[V]||(b[V]=\"t0\");var c=\"\"+b[V];if(N.h[c])return N.h[c];a:{if(b[Kd]){J(67);if(b[ac]&&\"cookie\"!=b[ac]){var d=!1;break a}if(void 0!==Ab)b[Q]||(b[Q]=Ab);else{b:{d=String(b[W]||xa());var e=String(b[Yb]||\"/\"),g=Ca(String(b[U]||\"_ga\"));d=na(g,d,e);if(!d||jd.test(d))d=!0;else if(d=Ca(\"AMP_TOKEN\"),0==d.length)d=!0;else{if(1==d.length&&(d=decodeURIComponent(d[0]),\"$RETRIEVING\"==d||\"$OPT_OUT\"==d||\"$ERROR\"==d||\"$NOT_FOUND\"==d)){d=!0;break b}d=!1}}if(d&&\ntc(ic,String(b[Na]))){d=!0;break a}}}d=!1}if(d)return null;b=new pc(b);N.h[c]=b;N.P.push(b);return b};N.remove=function(a){for(var b=0;b<N.P.length;b++)if(N.P[b].get(V)==a){N.P.splice(b,1);N.h[a]=null;break}};N.j=function(a){return N.h[a]};N.getAll=function(){return N.P.slice(0)};\nN.N=function(){\"ga\"!=gb&&J(49);var a=O[gb];if(!a||42!=a.answer){N.L=a&&a.l;N.loaded=!0;var b=O[gb]=N;X(\"create\",b,b.create);X(\"remove\",b,b.remove);X(\"getByName\",b,b.j,5);X(\"getAll\",b,b.getAll,6);b=pc.prototype;X(\"get\",b,b.get,7);X(\"set\",b,b.set,4);X(\"send\",b,b.send);X(\"requireSync\",b,b.ma);b=Ya.prototype;X(\"get\",b,b.get);X(\"set\",b,b.set);if(\"https:\"!=M.location.protocol&&!Ba){a:{b=M.getElementsByTagName(\"script\");for(var c=0;c<b.length&&100>c;c++){var d=b[c].src;if(d&&0==d.indexOf(\"https://www.google-analytics.com/analytics\")){b=\n!0;break a}}b=!1}b&&(Ba=!0)}(O.gaplugins=O.gaplugins||{}).Linker=Dc;b=Dc.prototype;C(\"linker\",Dc);X(\"decorate\",b,b.ca,20);X(\"autoLink\",b,b.S,25);C(\"displayfeatures\",fd);C(\"adfeatures\",fd);a=a&&a.q;ka(a)?Z.D.apply(N,a):J(50)}};N.da=function(){for(var a=N.getAll(),b=0;b<a.length;b++)a[b].get(V)};var da=N.N,Nd=O[gb];Nd&&Nd.r?da():z(da);z(function(){Z.D([\"provide\",\"render\",ua])});function La(a){var b=1,c;if(a)for(b=0,c=a.length-1;0<=c;c--){var d=a.charCodeAt(c);b=(b<<6&268435455)+d+(d<<14);d=b&266338304;b=0!=d?b^d>>21:b}return b};})(window);\n"
  },
  {
    "path": "open-xxl-job/doc/分布式任务调度平台XXL-JOB_files/core.php",
    "content": "!function(){var p,q,r,a=encodeURIComponent,b=\"1263800177\",c=\"\",d=\"\",e=\"online_v3.php\",f=\"z7.cnzz.com\",g=\"1\",h=\"text\",i=\"z\",j=\"&#31449;&#38271;&#32479;&#35745;\",k=window[\"_CNZZDbridge_\"+b][\"bobject\"],l=\"http:\",m=\"0\",n=l+\"//online.cnzz.com/online/\"+e,o=[];o.push(\"id=\"+b),o.push(\"h=\"+f),o.push(\"on=\"+a(d)),o.push(\"s=\"+a(c)),n+=\"?\"+o.join(\"&\"),\"0\"===m&&k[\"callRequest\"]([l+\"//cnzz.mmstat.com/9.gif?abc=1\"]),g&&(\"\"!==d?k[\"createScriptIcon\"](n,\"utf-8\"):(q=\"z\"==i?\"http://www.cnzz.com/stat/website.php?web_id=\"+b:\"http://quanjing.cnzz.com\",\"pic\"===h?(r=l+\"//icon.cnzz.com/img/\"+c+\".gif\",p=\"<a href='\"+q+\"' target=_blank title='\"+j+\"'><img border=0 hspace=0 vspace=0 src='\"+r+\"'></a>\"):p=\"<a href='\"+q+\"' target=_blank title='\"+j+\"'>\"+j+\"</a>\",k[\"createIcon\"]([p])))}();"
  },
  {
    "path": "open-xxl-job/doc/分布式任务调度平台XXL-JOB_files/hm.js",
    "content": "(function(){var h={},mt={},c={id:\"2a4e116e8983ca87e083a41b552fe6a2\",dm:[\"xuxueli.com\"],js:\"tongji.baidu.com/hm-web/js/\",etrk:[],icon:'',ctrk:false,align:-1,nv:-1,vdur:1800000,age:31536000000,rec:0,rp:[],trust:0,vcard:0,qiao:0,lxb:0,conv:0,med:0,cvcc:'',cvcf:[],apps:''};var q=void 0,r=!0,t=null,u=!1;mt.cookie={};mt.cookie.set=function(a,b,d){var f;d.H&&(f=new Date,f.setTime(f.getTime()+d.H));document.cookie=a+\"=\"+b+(d.domain?\"; domain=\"+d.domain:\"\")+(d.path?\"; path=\"+d.path:\"\")+(f?\"; expires=\"+f.toGMTString():\"\")+(d.hb?\"; secure\":\"\")};mt.cookie.get=function(a){return(a=RegExp(\"(^| )\"+a+\"=([^;]*)(;|$)\").exec(document.cookie))?a[2]:t};mt.h={};mt.h.oa=function(a){return document.getElementById(a)};\nmt.h.J=function(a,b){var d=[],f=[];if(!a)return f;for(;a.parentNode!=t;){for(var g=0,n=0,l=a.parentNode.childNodes.length,p=0;p<l;p++){var e=a.parentNode.childNodes[p];if(e.nodeName===a.nodeName&&(g++,e===a&&(n=g),0<n&&1<g))break}if((l=\"\"!==a.id)&&b){d.unshift(\"#\"+encodeURIComponent(a.id));break}else l&&(l=\"#\"+encodeURIComponent(a.id),l=0<d.length?l+\">\"+d.join(\">\"):l,f.push(l)),d.unshift(encodeURIComponent(String(a.nodeName).toLowerCase())+(1<g?\"[\"+n+\"]\":\"\"));a=a.parentNode}f.push(d.join(\">\"));return f};\nmt.h.$a=function(a){return(a=mt.h.J(a,r))&&a.length?String(a[0]):\"\"};mt.h.Za=function(a){return mt.h.J(a,u)};mt.h.Xa=function(a,b){for(b=b.toUpperCase();(a=a.parentNode)&&1==a.nodeType;)if(a.tagName==b)return a;return t};mt.h.pa=function(a){return 9===a.nodeType?a:a.ownerDocument||a.document};\nmt.h.Ya=function(a){var b={top:0,left:0};if(!a)return b;var d=mt.h.pa(a).documentElement;\"undefined\"!==typeof a.getBoundingClientRect&&(b=a.getBoundingClientRect());return{top:b.top+(window.pageYOffset||d.scrollTop)-(d.clientTop||0),left:b.left+(window.pageXOffset||d.scrollLeft)-(d.clientLeft||0)}};\n(mt.h.Ea=function(){function a(){if(!a.A){a.A=r;for(var b=0,d=f.length;b<d;b++)f[b]()}}function b(){try{document.documentElement.doScroll(\"left\")}catch(d){setTimeout(b,1);return}a()}var d=u,f=[],g;document.addEventListener?g=function(){document.removeEventListener(\"DOMContentLoaded\",g,u);a()}:document.attachEvent&&(g=function(){\"complete\"===document.readyState&&(document.detachEvent(\"onreadystatechange\",g),a())});(function(){if(!d)if(d=r,\"complete\"===document.readyState)a.A=r;else if(document.addEventListener)document.addEventListener(\"DOMContentLoaded\",\ng,u),window.addEventListener(\"load\",a,u);else if(document.attachEvent){document.attachEvent(\"onreadystatechange\",g);window.attachEvent(\"onload\",a);var f=u;try{f=window.frameElement==t}catch(l){}document.documentElement.doScroll&&f&&b()}})();return function(b){a.A?b():f.push(b)}}()).A=u;mt.event={};mt.event.c=function(a,b,d){a.attachEvent?a.attachEvent(\"on\"+b,function(b){d.call(a,b)}):a.addEventListener&&a.addEventListener(b,d,u)};\nmt.event.preventDefault=function(a){a.preventDefault?a.preventDefault():a.returnValue=u};\n(function(){var a=mt.event;mt.f={};mt.f.Da=/msie (\\d+\\.\\d+)/i.test(navigator.userAgent);mt.f.Ba=/msie (\\d+\\.\\d+)/i.test(navigator.userAgent)?document.documentMode||+RegExp.$1:q;mt.f.cookieEnabled=navigator.cookieEnabled;mt.f.javaEnabled=navigator.javaEnabled();mt.f.language=navigator.language||navigator.browserLanguage||navigator.systemLanguage||navigator.userLanguage||\"\";mt.f.Ga=(window.screen.width||0)+\"x\"+(window.screen.height||0);mt.f.colorDepth=window.screen.colorDepth||0;mt.f.K=function(){var a;\na=a||document;return parseInt(window.pageYOffset||a.documentElement.scrollTop||a.body&&a.body.scrollTop||0,10)};mt.f.L=function(){var a=document;return parseInt(window.innerHeight||a.documentElement.clientHeight||a.body&&a.body.clientHeight||0,10)};mt.f.orientation=0;(function(){function b(){var a=0;window.orientation!==q&&(a=window.orientation);screen&&(screen.orientation&&screen.orientation.angle!==q)&&(a=screen.orientation.angle);mt.f.orientation=a}b();a.c(window,\"orientationchange\",b)})();return mt.f})();\nmt.l={};mt.l.parse=function(){return(new Function('return (\" + source + \")'))()};\nmt.l.stringify=function(){function a(a){/[\"\\\\\\x00-\\x1f]/.test(a)&&(a=a.replace(/[\"\\\\\\x00-\\x1f]/g,function(a){var b=d[a];if(b)return b;b=a.charCodeAt();return\"\\\\u00\"+Math.floor(b/16).toString(16)+(b%16).toString(16)}));return'\"'+a+'\"'}function b(a){return 10>a?\"0\"+a:a}var d={\"\\b\":\"\\\\b\",\"\\t\":\"\\\\t\",\"\\n\":\"\\\\n\",\"\\f\":\"\\\\f\",\"\\r\":\"\\\\r\",'\"':'\\\\\"',\"\\\\\":\"\\\\\\\\\"};return function(d){switch(typeof d){case \"undefined\":return\"undefined\";case \"number\":return isFinite(d)?String(d):\"null\";case \"string\":return a(d);case \"boolean\":return String(d);\ndefault:if(d===t)return\"null\";if(d instanceof Array){var g=[\"[\"],n=d.length,l,p,e;for(p=0;p<n;p++)switch(e=d[p],typeof e){case \"undefined\":case \"function\":case \"unknown\":break;default:l&&g.push(\",\"),g.push(mt.l.stringify(e)),l=1}g.push(\"]\");return g.join(\"\")}if(d instanceof Date)return'\"'+d.getFullYear()+\"-\"+b(d.getMonth()+1)+\"-\"+b(d.getDate())+\"T\"+b(d.getHours())+\":\"+b(d.getMinutes())+\":\"+b(d.getSeconds())+'\"';l=[\"{\"];p=mt.l.stringify;for(n in d)if(Object.prototype.hasOwnProperty.call(d,n))switch(e=\nd[n],typeof e){case \"undefined\":case \"unknown\":case \"function\":break;default:g&&l.push(\",\"),g=1,l.push(p(n)+\":\"+p(e))}l.push(\"}\");return l.join(\"\")}}}();mt.lang={};mt.lang.d=function(a,b){return\"[object \"+b+\"]\"==={}.toString.call(a)};mt.lang.cb=function(a){return mt.lang.d(a,\"Number\")&&isFinite(a)};mt.lang.fb=function(a){return mt.lang.d(a,\"String\")};mt.lang.j=function(a){return a.replace?a.replace(/'/g,\"'0\").replace(/\\*/g,\"'1\").replace(/!/g,\"'2\"):a};mt.localStorage={};\nmt.localStorage.C=function(){if(!mt.localStorage.g)try{mt.localStorage.g=document.createElement(\"input\"),mt.localStorage.g.type=\"hidden\",mt.localStorage.g.style.display=\"none\",mt.localStorage.g.addBehavior(\"#default#userData\"),document.getElementsByTagName(\"head\")[0].appendChild(mt.localStorage.g)}catch(a){return u}return r};\nmt.localStorage.set=function(a,b,d){var f=new Date;f.setTime(f.getTime()+d||31536E6);try{window.localStorage?(b=f.getTime()+\"|\"+b,window.localStorage.setItem(a,b)):mt.localStorage.C()&&(mt.localStorage.g.expires=f.toUTCString(),mt.localStorage.g.load(document.location.hostname),mt.localStorage.g.setAttribute(a,b),mt.localStorage.g.save(document.location.hostname))}catch(g){}};\nmt.localStorage.get=function(a){if(window.localStorage){if(a=window.localStorage.getItem(a)){var b=a.indexOf(\"|\"),d=a.substring(0,b)-0;if(d&&d>(new Date).getTime())return a.substring(b+1)}}else if(mt.localStorage.C())try{return mt.localStorage.g.load(document.location.hostname),mt.localStorage.g.getAttribute(a)}catch(f){}return t};\nmt.localStorage.remove=function(a){if(window.localStorage)window.localStorage.removeItem(a);else if(mt.localStorage.C())try{mt.localStorage.g.load(document.location.hostname),mt.localStorage.g.removeAttribute(a),mt.localStorage.g.save(document.location.hostname)}catch(b){}};mt.sessionStorage={};mt.sessionStorage.set=function(a,b){if(window.sessionStorage)try{window.sessionStorage.setItem(a,b)}catch(d){}};\nmt.sessionStorage.get=function(a){return window.sessionStorage?window.sessionStorage.getItem(a):t};mt.sessionStorage.remove=function(a){window.sessionStorage&&window.sessionStorage.removeItem(a)};mt.aa={};mt.aa.log=function(a,b){var d=new Image,f=\"mini_tangram_log_\"+Math.floor(2147483648*Math.random()).toString(36);window[f]=d;d.onload=d.onerror=d.onabort=function(){d.onload=d.onerror=d.onabort=t;d=window[f]=t;b&&b(a)};d.src=a};mt.S={};\nmt.S.ua=function(){var a=\"\";if(navigator.plugins&&navigator.mimeTypes.length){var b=navigator.plugins[\"Shockwave Flash\"];b&&b.description&&(a=b.description.replace(/^.*\\s+(\\S+)\\s+\\S+$/,\"$1\"))}else if(window.ActiveXObject)try{if(b=new ActiveXObject(\"ShockwaveFlash.ShockwaveFlash\"))(a=b.GetVariable(\"$version\"))&&(a=a.replace(/^.*\\s+(\\d+),(\\d+).*$/,\"$1.$2\"))}catch(d){}return a};\nmt.S.Wa=function(a,b,d,f,g){return'<object classid=\"clsid:d27cdb6e-ae6d-11cf-96b8-444553540000\" id=\"'+a+'\" width=\"'+d+'\" height=\"'+f+'\"><param name=\"movie\" value=\"'+b+'\" /><param name=\"flashvars\" value=\"'+(g||\"\")+'\" /><param name=\"allowscriptaccess\" value=\"always\" /><embed type=\"application/x-shockwave-flash\" name=\"'+a+'\" width=\"'+d+'\" height=\"'+f+'\" src=\"'+b+'\" flashvars=\"'+(g||\"\")+'\" allowscriptaccess=\"always\" /></object>'};mt.url={};\nmt.url.i=function(a,b){var d=a.match(RegExp(\"(^|&|\\\\?|#)(\"+b+\")=([^&#]*)(&|$|#)\",\"\"));return d?d[3]:t};mt.url.ab=function(a){return(a=a.match(/^(https?:)\\/\\//))?a[1]:t};mt.url.ra=function(a){return(a=a.match(/^(https?:\\/\\/)?([^\\/\\?#]*)/))?a[2].replace(/.*@/,\"\"):t};mt.url.W=function(a){return(a=mt.url.ra(a))?a.replace(/:\\d+$/,\"\"):a};mt.url.J=function(a){return(a=a.match(/^(https?:\\/\\/)?[^\\/]*(.*)/))?a[2].replace(/[\\?#].*/,\"\").replace(/^$/,\"/\"):t};\n(function(){function a(){for(var a=u,d=document.getElementsByTagName(\"script\"),f=d.length,f=100<f?100:f,g=0;g<f;g++){var n=d[g].src;if(n&&0===n.indexOf(\"https://hm.baidu.com/h\")){a=r;break}}return a}return h.na=a})();var A=h.na;\nh.D={bb:\"http://tongji.baidu.com/hm-web/welcome/ico\",$:\"hm.baidu.com/hm.gif\",ea:\"baidu.com\",ya:\"hmmd\",za:\"hmpl\",Pa:\"utm_medium\",xa:\"hmkw\",Ra:\"utm_term\",va:\"hmci\",Oa:\"utm_content\",Aa:\"hmsr\",Qa:\"utm_source\",wa:\"hmcu\",Na:\"utm_campaign\",r:0,m:Math.round(+new Date/1E3),U:Math.round(+new Date/1E3)%65535,protocol:\"https:\"===document.location.protocol?\"https:\":\"http:\",O:A()||\"https:\"===document.location.protocol?\"https:\":\"http:\",eb:0,Ta:6E5,gb:5E3,Ua:5,Va:1024,Sa:1,P:2147483647,ba:\"cc cf ci ck cl cm cp cu cw ds vl ep et fl ja ln lo lt rnd si su v cv lv api sn ct u tt\".split(\" \")};\n(function(){var a={p:{},c:function(a,d){this.p[a]=this.p[a]||[];this.p[a].push(d)},w:function(a,d){this.p[a]=this.p[a]||[];for(var f=this.p[a].length,g=0;g<f;g++)this.p[a][g](d)}};return h.G=a})();\n(function(){function a(a,f){var g=document.createElement(\"script\");g.charset=\"utf-8\";b.d(f,\"Function\")&&(g.readyState?g.onreadystatechange=function(){if(\"loaded\"===g.readyState||\"complete\"===g.readyState)g.onreadystatechange=t,f()}:g.onload=function(){f()});g.src=a;var n=document.getElementsByTagName(\"script\")[0];n.parentNode.insertBefore(g,n)}var b=mt.lang;return h.load=a})();\n(function(){function a(){return function(){h.b.a.nv=0;h.b.a.st=4;h.b.a.et=3;h.b.a.ep=h.F.sa()+\",\"+h.F.qa();h.b.k()}}function b(){clearTimeout(z);var a;v&&(a=\"visible\"==document[v]);x&&(a=!document[x]);p=\"undefined\"==typeof a?r:a;if((!l||!e)&&p&&k)y=r,m=+new Date;else if(l&&e&&(!p||!k))y=u,s+=+new Date-m;l=p;e=k;z=setTimeout(b,100)}function d(a){var k=document,m=\"\";if(a in k)m=a;else for(var d=[\"webkit\",\"ms\",\"moz\",\"o\"],b=0;b<d.length;b++){var s=d[b]+a.charAt(0).toUpperCase()+a.slice(1);if(s in k){m=\ns;break}}return m}function f(a){if(!(\"focus\"==a.type||\"blur\"==a.type)||!(a.target&&a.target!=window))k=\"focus\"==a.type||\"focusin\"==a.type?r:u,b()}var g=mt.event,n=h.G,l=r,p=r,e=r,k=r,w=+new Date,m=w,s=0,y=r,v=d(\"visibilityState\"),x=d(\"hidden\"),z;b();(function(){var a=v.replace(/[vV]isibilityState/,\"visibilitychange\");g.c(document,a,b);g.c(window,\"pageshow\",b);g.c(window,\"pagehide\",b);\"object\"==typeof document.onfocusin?(g.c(document,\"focusin\",f),g.c(document,\"focusout\",f)):(g.c(window,\"focus\",f),\ng.c(window,\"blur\",f))})();h.F={sa:function(){return+new Date-w},qa:function(){return y?+new Date-m+s:s}};n.c(\"pv-b\",function(){g.c(window,\"unload\",a())});return h.F})();\n(function(){var a=mt.lang,b=h.D,d=h.load,f={Ca:function(g){if((window._dxt===q||a.d(window._dxt,\"Array\"))&&\"undefined\"!==typeof h.b){var f=h.b.I();d([b.protocol,\"//datax.baidu.com/x.js?si=\",c.id,\"&dm=\",encodeURIComponent(f)].join(\"\"),g)}},Ma:function(d){if(a.d(d,\"String\")||a.d(d,\"Number\"))window._dxt=window._dxt||[],window._dxt.push([\"_setUserId\",d])}};return h.ha=f})();\n(function(){function a(a,d,m,b){if(!(a===q||d===q||b===q)){if(\"\"===a)return[d,m,b].join(\"*\");a=String(a).split(\"!\");for(var e,v=u,x=0;x<a.length;x++)if(e=a[x].split(\"*\"),String(d)===e[0]){e[1]=m;e[2]=b;a[x]=e.join(\"*\");v=r;break}v||a.push([d,m,b].join(\"*\"));return a.join(\"!\")}}function b(a){for(var e in a)if({}.hasOwnProperty.call(a,e)){var m=a[e];d.d(m,\"Object\")||d.d(m,\"Array\")?b(m):a[e]=String(m)}}var d=mt.lang,f=mt.l,g=mt.f,n=h.D,l=h.G,p=h.ha,e={s:[],B:0,Y:u,o:{T:\"\",page:\"\"},init:function(){e.e=\n0;l.c(\"pv-b\",function(){e.ia();e.la()});l.c(\"pv-d\",function(){e.ma();e.o.page=\"\"});l.c(\"stag-b\",function(){h.b.a.api=e.e||e.B?e.e+\"_\"+e.B:\"\";h.b.a.ct=[decodeURIComponent(h.b.getData(\"Hm_ct_\"+c.id)||\"\"),e.o.T,e.o.page].join(\"!\")});l.c(\"stag-d\",function(){h.b.a.api=0;e.e=0;e.B=0})},ia:function(){var a=window._hmt||[];if(!a||d.d(a,\"Array\"))window._hmt={id:c.id,cmd:{},push:function(){for(var a=window._hmt,k=0;k<arguments.length;k++){var b=arguments[k];d.d(b,\"Array\")&&(a.cmd[a.id].push(b),\"_setAccount\"===\nb[0]&&(1<b.length&&/^[0-9a-f]{32}$/.test(b[1]))&&(b=b[1],a.id=b,a.cmd[b]=a.cmd[b]||[]))}}},window._hmt.cmd[c.id]=[],window._hmt.push.apply(window._hmt,a)},la:function(){var a=window._hmt;if(a&&a.cmd&&a.cmd[c.id])for(var d=a.cmd[c.id],m=/^_track(Event|MobConv|Order|RTEvent)$/,b=0,f=d.length;b<f;b++){var v=d[b];m.test(v[0])?e.s.push(v):e.Q(v)}a.cmd[c.id]={push:e.Q}},ma:function(){if(0<e.s.length)for(var a=0,d=e.s.length;a<d;a++)e.Q(e.s[a]);e.s=t},Q:function(a){var b=a[0];if(e.hasOwnProperty(b)&&d.d(e[b],\n\"Function\"))e[b](a)},_setAccount:function(a){1<a.length&&/^[0-9a-f]{32}$/.test(a[1])&&(e.e|=1)},_setAutoPageview:function(a){if(1<a.length&&(a=a[1],u===a||r===a))e.e|=2,h.b.X=a},_trackPageview:function(a){if(1<a.length&&a[1].charAt&&\"/\"===a[1].charAt(0)){e.e|=4;h.b.a.et=0;h.b.a.ep=\"\";h.b.a.vl=g.K()+g.L();h.b.M?(h.b.a.nv=0,h.b.a.st=4):h.b.M=r;var b=h.b.a.u,d=h.b.a.su;h.b.a.u=n.protocol+\"//\"+document.location.host+a[1];e.Y||(h.b.a.su=document.location.href);h.b.k();h.b.a.u=b;h.b.a.su=d}},_trackEvent:function(a){2<\na.length&&(e.e|=8,h.b.a.nv=0,h.b.a.st=4,h.b.a.et=4,h.b.a.ep=d.j(a[1])+\"*\"+d.j(a[2])+(a[3]?\"*\"+d.j(a[3]):\"\")+(a[4]?\"*\"+d.j(a[4]):\"\"),h.b.k())},_setCustomVar:function(a){if(!(4>a.length)){var b=a[1],m=a[4]||3;if(0<b&&6>b&&0<m&&4>m){e.B++;for(var s=(h.b.a.cv||\"*\").split(\"!\"),f=s.length;f<b-1;f++)s.push(\"*\");s[b-1]=m+\"*\"+d.j(a[2])+\"*\"+d.j(a[3]);h.b.a.cv=s.join(\"!\");a=h.b.a.cv.replace(/[^1](\\*[^!]*){2}/g,\"*\").replace(/((^|!)\\*)+$/g,\"\");\"\"!==a?h.b.setData(\"Hm_cv_\"+c.id,encodeURIComponent(a),c.age):h.b.Fa(\"Hm_cv_\"+\nc.id)}}},_setUserTag:function(b){if(!(3>b.length)){var e=d.j(b[1]);b=d.j(b[2]);if(e!==q&&b!==q){var m=decodeURIComponent(h.b.getData(\"Hm_ct_\"+c.id)||\"\"),m=a(m,e,1,b);h.b.setData(\"Hm_ct_\"+c.id,encodeURIComponent(m),c.age)}}},_setVisitTag:function(b){if(!(3>b.length)){var f=d.j(b[1]);b=d.j(b[2]);if(f!==q&&b!==q){var m=e.o.T,m=a(m,f,2,b);e.o.T=m}}},_setPageTag:function(b){if(!(3>b.length)){var f=d.j(b[1]);b=d.j(b[2]);if(f!==q&&b!==q){var m=e.o.page,m=a(m,f,3,b);e.o.page=m}}},_setReferrerOverride:function(a){1<\na.length&&(h.b.a.su=a[1].charAt&&\"/\"===a[1].charAt(0)?n.protocol+\"//\"+window.location.host+a[1]:a[1],e.Y=r)},_trackOrder:function(a){a=a[1];d.d(a,\"Object\")&&(b(a),e.e|=16,h.b.a.nv=0,h.b.a.st=4,h.b.a.et=94,h.b.a.ep=f.stringify(a),h.b.k())},_trackMobConv:function(a){if(a={webim:1,tel:2,map:3,sms:4,callback:5,share:6}[a[1]])e.e|=32,h.b.a.et=93,h.b.a.ep=a,h.b.k()},_trackRTPageview:function(a){a=a[1];d.d(a,\"Object\")&&(b(a),a=f.stringify(a),512>=encodeURIComponent(a).length&&(e.e|=64,h.b.a.rt=a))},_trackRTEvent:function(a){a=\na[1];if(d.d(a,\"Object\")){b(a);a=encodeURIComponent(f.stringify(a));var g=function(a){var b=h.b.a.rt;e.e|=128;h.b.a.et=90;h.b.a.rt=a;h.b.k();h.b.a.rt=b},m=a.length;if(900>=m)g.call(this,a);else for(var m=Math.ceil(m/900),s=\"block|\"+Math.round(Math.random()*n.P).toString(16)+\"|\"+m+\"|\",l=[],v=0;v<m;v++)l.push(v),l.push(a.substring(900*v,900*v+900)),g.call(this,s+l.join(\"|\")),l=[]}},_setUserId:function(a){a=a[1];p.Ca();p.Ma(a)}};e.init();h.fa=e;return h.fa})();\n(function(){function a(){\"undefined\"===typeof window[\"_bdhm_loaded_\"+c.id]&&(window[\"_bdhm_loaded_\"+c.id]=r,this.a={},this.X=r,this.M=u,this.init())}var b=mt.url,d=mt.aa,f=mt.S,g=mt.lang,n=mt.cookie,l=mt.f,p=mt.localStorage,e=mt.sessionStorage,k=h.D,w=h.G;a.prototype={N:function(a,b){a=\".\"+a.replace(/:\\d+/,\"\");b=\".\"+b.replace(/:\\d+/,\"\");var d=a.indexOf(b);return-1<d&&d+b.length===a.length},Z:function(a,b){a=a.replace(/^https?:\\/\\//,\"\");return 0===a.indexOf(b)},z:function(a){for(var d=0;d<c.dm.length;d++)if(-1<\nc.dm[d].indexOf(\"/\")){if(this.Z(a,c.dm[d]))return r}else{var e=b.W(a);if(e&&this.N(e,c.dm[d]))return r}return u},I:function(){for(var a=document.location.hostname,b=0,d=c.dm.length;b<d;b++)if(this.N(a,c.dm[b]))return c.dm[b].replace(/(:\\d+)?[\\/\\?#].*/,\"\");return a},V:function(){for(var a=0,b=c.dm.length;a<b;a++){var d=c.dm[a];if(-1<d.indexOf(\"/\")&&this.Z(document.location.href,d))return d.replace(/^[^\\/]+(\\/.*)/,\"$1\")+\"/\"}return\"/\"},ta:function(){if(!document.referrer)return k.m-k.r>c.vdur?1:4;var a=\nu;this.z(document.referrer)&&this.z(document.location.href)?a=r:(a=b.W(document.referrer),a=this.N(a||\"\",document.location.hostname));return a?k.m-k.r>c.vdur?1:4:3},getData:function(a){try{return n.get(a)||e.get(a)||p.get(a)}catch(b){}},setData:function(a,b,d){try{n.set(a,b,{domain:this.I(),path:this.V(),H:d}),d?p.set(a,b,d):e.set(a,b)}catch(f){}},Fa:function(a){try{n.set(a,\"\",{domain:this.I(),path:this.V(),H:-1}),e.remove(a),p.remove(a)}catch(b){}},Ka:function(){var a,b,d,e,f;k.r=this.getData(\"Hm_lpvt_\"+\nc.id)||0;13===k.r.length&&(k.r=Math.round(k.r/1E3));b=this.ta();a=4!==b?1:0;if(d=this.getData(\"Hm_lvt_\"+c.id)){e=d.split(\",\");for(f=e.length-1;0<=f;f--)13===e[f].length&&(e[f]=\"\"+Math.round(e[f]/1E3));for(;2592E3<k.m-e[0];)e.shift();f=4>e.length?2:3;for(1===a&&e.push(k.m);4<e.length;)e.shift();d=e.join(\",\");e=e[e.length-1]}else d=k.m,e=\"\",f=1;this.setData(\"Hm_lvt_\"+c.id,d,c.age);this.setData(\"Hm_lpvt_\"+c.id,k.m);d=k.m===this.getData(\"Hm_lpvt_\"+c.id)?\"1\":\"0\";if(0===c.nv&&this.z(document.location.href)&&\n(\"\"===document.referrer||this.z(document.referrer)))a=0,b=4;this.a.nv=a;this.a.st=b;this.a.cc=d;this.a.lt=e;this.a.lv=f},Ja:function(){for(var a=[],b=this.a.et,d=0,e=k.ba.length;d<e;d++){var f=k.ba[d],g=this.a[f];\"undefined\"!==typeof g&&\"\"!==g&&(\"tt\"!==f||\"tt\"===f&&0===b)&&(\"ct\"!==f||\"ct\"===f&&0===b)&&a.push(f+\"=\"+encodeURIComponent(g))}switch(b){case 0:a.push(\"sn=\"+k.U);this.a.rt&&a.push(\"rt=\"+encodeURIComponent(this.a.rt));break;case 3:a.push(\"sn=\"+k.U);break;case 90:this.a.rt&&a.push(\"rt=\"+this.a.rt)}return a.join(\"&\")},\nLa:function(){this.Ka();this.a.si=c.id;this.a.su=document.referrer;this.a.ds=l.Ga;this.a.cl=l.colorDepth+\"-bit\";this.a.ln=String(l.language).toLowerCase();this.a.ja=l.javaEnabled?1:0;this.a.ck=l.cookieEnabled?1:0;this.a.lo=\"number\"===typeof _bdhm_top?1:0;this.a.fl=f.ua();this.a.v=\"1.2.30\";this.a.cv=decodeURIComponent(this.getData(\"Hm_cv_\"+c.id)||\"\");this.a.tt=document.title||\"\";this.a.vl=l.K()+l.L();var a=document.location.href;this.a.cm=b.i(a,k.ya)||\"\";this.a.cp=b.i(a,k.za)||b.i(a,k.Pa)||\"\";this.a.cw=\nb.i(a,k.xa)||b.i(a,k.Ra)||\"\";this.a.ci=b.i(a,k.va)||b.i(a,k.Oa)||\"\";this.a.cf=b.i(a,k.Aa)||b.i(a,k.Qa)||\"\";this.a.cu=b.i(a,k.wa)||b.i(a,k.Na)||\"\"},init:function(){try{this.La(),0===this.a.nv?this.Ia():this.R(\".*\"),h.b=this,this.ga(),w.w(\"pv-b\"),this.Ha()}catch(a){var b=[];b.push(\"si=\"+c.id);b.push(\"n=\"+encodeURIComponent(a.name));b.push(\"m=\"+encodeURIComponent(a.message));b.push(\"r=\"+encodeURIComponent(document.referrer));d.log(k.O+\"//\"+k.$+\"?\"+b.join(\"&\"))}},Ha:function(){function a(){w.w(\"pv-d\")}\nthis.X?(this.M=r,this.a.et=0,this.a.ep=\"\",this.a.vl=l.K()+l.L(),this.k(a)):a()},k:function(a){var b=this;b.a.rnd=Math.round(Math.random()*k.P);w.w(\"stag-b\");var e=k.O+\"//\"+k.$+\"?\"+b.Ja();w.w(\"stag-d\");b.da(e);d.log(e,function(d){b.R(d);g.d(a,\"Function\")&&a.call(b)})},ga:function(){var a=document.location.hash.substring(1),d=RegExp(c.id),e=-1<document.referrer.indexOf(k.ea),f=b.i(a,\"jn\"),g=/^heatlink$|^select$|^pageclick$/.test(f);a&&(d.test(a)&&e&&g)&&(this.a.rnd=Math.round(Math.random()*k.P),a=document.createElement(\"script\"),\na.setAttribute(\"type\",\"text/javascript\"),a.setAttribute(\"charset\",\"utf-8\"),a.setAttribute(\"src\",k.protocol+\"//\"+c.js+f+\".js?\"+this.a.rnd),f=document.getElementsByTagName(\"script\")[0],f.parentNode.insertBefore(a,f))},da:function(a){var b=e.get(\"Hm_unsent_\"+c.id)||\"\",d=this.a.u?\"\":\"&u=\"+encodeURIComponent(document.location.href),b=encodeURIComponent(a.replace(/^https?:\\/\\//,\"\")+d)+(b?\",\"+b:\"\");e.set(\"Hm_unsent_\"+c.id,b)},R:function(a){var b=e.get(\"Hm_unsent_\"+c.id)||\"\";b&&(a=encodeURIComponent(a.replace(/^https?:\\/\\//,\n\"\")),a=RegExp(a.replace(/([\\*\\(\\)])/g,\"\\\\$1\")+\"(%26u%3D[^,]*)?,?\",\"g\"),(b=b.replace(a,\"\").replace(/,$/,\"\"))?e.set(\"Hm_unsent_\"+c.id,b):e.remove(\"Hm_unsent_\"+c.id))},Ia:function(){var a=this,b=e.get(\"Hm_unsent_\"+c.id);if(b)for(var b=b.split(\",\"),f=function(b){d.log(k.O+\"//\"+decodeURIComponent(b),function(b){a.R(b)})},g=0,l=b.length;g<l;g++)f(b[g])}};return new a})();\n(function(){var a=mt.event,b=mt.l;try{if(window.performance&&performance.timing&&\"undefined\"!==typeof h.b){var d=function(a){var b=performance.timing,d=b[a+\"Start\"]?b[a+\"Start\"]:0;a=b[a+\"End\"]?b[a+\"End\"]:0;return{start:d,end:a,value:0<a-d?a-d:0}},f=function(){var a;a=d(\"navigation\");var f=d(\"request\");a={netAll:f.start-a.start,netDns:d(\"domainLookup\").value,netTcp:d(\"connect\").value,srv:d(\"response\").start-f.start,dom:performance.timing.domInteractive-performance.timing.fetchStart,loadEvent:d(\"loadEvent\").end-\na.start};h.b.a.et=87;h.b.a.ep=b.stringify(a);h.b.k()};a.c(window,\"load\",function(){setTimeout(f,500)})}}catch(g){}})();\n(function(){var a=mt.f,b=mt.lang,d=mt.event,f=mt.l;if(\"undefined\"!==typeof h.b&&(c.med||(!a.Da||7<a.Ba)&&c.cvcc)){var g,n,l,p,e=function(a){if(a.item){for(var b=a.length,d=Array(b);b--;)d[b]=a[b];return d}return[].slice.call(a)},k=function(a,b){for(var d in a)if(a.hasOwnProperty(d)&&b.call(a,d,a[d])===u)return u},w=function(a,d){var e={};e.n=g;e.t=\"clk\";e.v=a;if(d){var k=d.getAttribute(\"href\"),m=d.getAttribute(\"onclick\")?\"\"+d.getAttribute(\"onclick\"):t,n=d.getAttribute(\"id\")||\"\";l.test(k)?(e.sn=\"mediate\",\ne.snv=k):b.d(m,\"String\")&&l.test(m)&&(e.sn=\"wrap\",e.snv=m);e.id=n}h.b.a.et=86;h.b.a.ep=f.stringify(e);h.b.k();for(e=+new Date;400>=+new Date-e;);};if(c.med)n=\"/zoosnet\",g=\"swt\",l=/swt|zixun|call|chat|zoos|business|talk|kefu|openkf|online|\\/LR\\/Chatpre\\.aspx/i,p={click:function(){for(var a=[],b=e(document.getElementsByTagName(\"a\")),b=[].concat.apply(b,e(document.getElementsByTagName(\"area\"))),b=[].concat.apply(b,e(document.getElementsByTagName(\"img\"))),d,f,g=0,k=b.length;g<k;g++)d=b[g],f=d.getAttribute(\"onclick\"),\nd=d.getAttribute(\"href\"),(l.test(f)||l.test(d))&&a.push(b[g]);return a}};else if(c.cvcc){n=\"/other-comm\";g=\"other\";l=c.cvcc.q||q;var m=c.cvcc.id||q;p={click:function(){for(var a=[],b=e(document.getElementsByTagName(\"a\")),b=[].concat.apply(b,e(document.getElementsByTagName(\"area\"))),b=[].concat.apply(b,e(document.getElementsByTagName(\"img\"))),d,f,g,k=0,n=b.length;k<n;k++)d=b[k],l!==q?(f=d.getAttribute(\"onclick\"),g=d.getAttribute(\"href\"),m?(d=d.getAttribute(\"id\"),(l.test(f)||l.test(g)||m.test(d))&&\na.push(b[k])):(l.test(f)||l.test(g))&&a.push(b[k])):m!==q&&(d=d.getAttribute(\"id\"),m.test(d)&&a.push(b[k]));return a}}}if(\"undefined\"!==typeof p&&\"undefined\"!==typeof l){var s;n+=/\\/$/.test(n)?\"\":\"/\";var y=function(a,d){if(s===d)return w(n+a,d),u;if(b.d(d,\"Array\")||b.d(d,\"NodeList\"))for(var e=0,f=d.length;e<f;e++)if(s===d[e])return w(n+a+\"/\"+(e+1),d[e]),u};d.c(document,\"mousedown\",function(a){a=a||window.event;s=a.target||a.srcElement;var d={};for(k(p,function(a,e){d[a]=b.d(e,\"Function\")?e():document.getElementById(e)});s&&\ns!==document&&k(d,y)!==u;)s=s.parentNode})}}})();(function(){var a=mt.h,b=mt.lang,d=mt.event,f=mt.l;if(\"undefined\"!==typeof h.b&&b.d(c.cvcf,\"Array\")&&0<c.cvcf.length){var g={ca:function(){for(var b=c.cvcf.length,f,p=0;p<b;p++)(f=a.oa(decodeURIComponent(c.cvcf[p])))&&d.c(f,\"click\",g.ka())},ka:function(){return function(){h.b.a.et=86;var a={n:\"form\",t:\"clk\"};a.id=this.id;h.b.a.ep=f.stringify(a);h.b.k()}}};a.Ea(function(){g.ca()})}})();\n(function(){var a=mt.event,b=mt.l;if(c.med&&\"undefined\"!==typeof h.b){var d=+new Date,f={n:\"anti\",sb:0,kb:0,clk:0},g=function(){h.b.a.et=86;h.b.a.ep=b.stringify(f);h.b.k()};a.c(document,\"click\",function(){f.clk++});a.c(document,\"keyup\",function(){f.kb=1});a.c(window,\"scroll\",function(){f.sb++});a.c(window,\"unload\",function(){f.t=+new Date-d;g()});a.c(window,\"load\",function(){setTimeout(g,5E3)})}})();})();\n"
  },
  {
    "path": "open-xxl-job/doc/分布式任务调度平台XXL-JOB_files/vue.css",
    "content": "@import url(\"https://fonts.googleapis.com/css?family=Roboto+Mono|Source+Sans+Pro:300,400,600\");*{-webkit-font-smoothing:antialiased;-webkit-overflow-scrolling:touch;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-text-size-adjust:none;-webkit-touch-callout:none;box-sizing:border-box}body:not(.ready){overflow:hidden}body:not(.ready) .app-nav,body:not(.ready)>nav,body:not(.ready) [data-cloak]{display:none}div#app{font-size:30px;font-weight:lighter;margin:40vh auto;text-align:center}div#app:empty:before{content:\"Loading...\"}.emoji{height:19.2px;height:1.2rem;vertical-align:middle}.progress{background-color:#42b983;background-color:var(--theme-color,#42b983);height:2px;left:0;position:fixed;right:0;top:0;transition:width .2s,opacity .4s;width:0;z-index:5}.search .search-keyword,.search a:hover{color:#42b983;color:var(--theme-color,#42b983)}.search .search-keyword{font-style:normal}body,html{height:100%}body{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;color:#34495e;font-family:Source Sans Pro,Helvetica Neue,Arial,sans-serif;font-size:15px;letter-spacing:0;margin:0;overflow-x:hidden}img{max-width:100%}kbd{border:1px solid #ccc;border-radius:3px;display:inline-block;font-size:12px!important;line-height:12px;margin-bottom:3px;padding:3px 5px;vertical-align:middle}.app-nav{left:0;margin:25px 60px 0 0;position:absolute;right:0;text-align:right;z-index:2}.app-nav p{margin:0}.app-nav>a{margin:0 16px;margin:0 1rem;padding:5px 0}.app-nav li,.app-nav ul{display:inline-block;list-style:none;margin:0}.app-nav a{color:inherit;font-size:16px;text-decoration:none;transition:color .3s}.app-nav a.active,.app-nav a:hover{color:#42b983;color:var(--theme-color,#42b983)}.app-nav a.active{border-bottom:2px solid #42b983;border-bottom:2px solid var(--theme-color,#42b983)}.app-nav li{display:inline-block;margin:0 16px;margin:0 1rem;padding:5px 0;position:relative}.app-nav li ul{background-color:#fff;border:1px solid #ddd;border-bottom-color:#ccc;border-radius:4px;box-sizing:border-box;display:none;max-height:calc(100vh - 61px);overflow-y:scroll;padding:10px 0;position:absolute;right:-15px;text-align:left;top:100%;white-space:nowrap}.app-nav li ul li{display:block;font-size:14px;line-height:16px;line-height:1rem;margin:0;margin:8px 14px;white-space:nowrap}.app-nav li ul a{display:block;font-size:inherit;margin:0;padding:0}.app-nav li ul a.active{border-bottom:0}.app-nav li:hover ul{display:block}.app-nav.no-badge{margin-right:25px}.github-corner{border-bottom:0;position:fixed;right:0;text-decoration:none;top:0;z-index:1}.github-corner svg{color:#fff;fill:#42b983;fill:var(--theme-color,#42b983);height:80px;width:80px}.github-corner:hover .octo-arm{-webkit-animation:a .56s ease-in-out;animation:a .56s ease-in-out}main{display:block;position:relative;width:100vw;height:100%}.anchor{display:inline-block;text-decoration:none;transition:all .3s}.anchor span{color:#34495e}.anchor:hover{text-decoration:underline}.sidebar{border-right:1px solid rgba(0,0,0,.07);overflow-y:auto;padding:40px 0;top:0;bottom:0;left:0;position:absolute;transition:-webkit-transform .25s ease-out;transition:transform .25s ease-out;transition:transform .25s ease-out,-webkit-transform .25s ease-out;width:300px;z-index:3}.sidebar>h1{margin:0 auto 16px;margin:0 auto 1rem;font-size:24px;font-size:1.5rem;font-weight:300;text-align:center}.sidebar>h1 a{color:inherit;text-decoration:none}.sidebar>h1 .app-nav{display:block;position:static}.sidebar .sidebar-nav{line-height:2em}.sidebar ul{margin:0;padding:0}.sidebar li>p{font-weight:700;margin:0}.sidebar ul,.sidebar ul li{list-style:none}.sidebar ul li a{border-bottom:none;display:block}.sidebar ul li ul{padding-left:20px}.sidebar::-webkit-scrollbar{width:4px}.sidebar::-webkit-scrollbar-thumb{background:transparent;border-radius:4px}.sidebar:hover::-webkit-scrollbar-thumb{background:hsla(0,0%,53%,.4)}.sidebar:hover::-webkit-scrollbar-track{background:hsla(0,0%,53%,.1)}.sidebar-toggle{background-color:transparent;background-color:hsla(0,0%,100%,.8);border:0;outline:none;padding:10px;bottom:0;left:0;position:absolute;text-align:center;transition:opacity .3s;width:30px;width:284px;z-index:4}.sidebar-toggle .sidebar-toggle-button:hover{opacity:.4}.sidebar-toggle span{background-color:#42b983;background-color:var(--theme-color,#42b983);display:block;margin-bottom:4px;width:16px;height:2px}body.sticky .sidebar,body.sticky .sidebar-toggle{position:fixed}.content{padding-top:20px;top:0;right:0;bottom:0;left:300px;position:absolute;transition:left .25s ease}.markdown-section{margin:0 auto;max-width:800px;padding:30px 15px 40px;position:relative}.markdown-section>*{box-sizing:border-box;font-size:inherit}.markdown-section>:first-child{margin-top:0!important}.markdown-section hr{border:none;border-bottom:1px solid #eee;margin:2em 0}.markdown-section table{border-collapse:collapse;border-spacing:0;display:block;margin-bottom:16px;margin-bottom:1rem;overflow:auto;width:100%}.markdown-section th{font-weight:700}.markdown-section td,.markdown-section th{border:1px solid #ddd;padding:6px 13px}.markdown-section tr{border-top:1px solid #ccc}.markdown-section p.tip,.markdown-section tr:nth-child(2n){background-color:#f8f8f8}.markdown-section p.tip{border-bottom-right-radius:2px;border-left:4px solid #f66;border-top-right-radius:2px;margin:2em 0;padding:12px 24px 12px 30px;position:relative}.markdown-section p.tip code{background-color:#efefef}.markdown-section p.tip em{color:#34495e}.markdown-section p.tip:before{background-color:#f66;border-radius:100%;color:#fff;content:\"!\";font-family:Dosis,Source Sans Pro,Helvetica Neue,Arial,sans-serif;font-size:14px;font-weight:700;left:-12px;line-height:20px;position:absolute;width:20px;height:20px;text-align:center;top:14px}.markdown-section p.warn{background:rgba(66,185,131,.1);border-radius:2px;padding:16px;padding:1rem}body.close .sidebar{-webkit-transform:translateX(-300px);transform:translateX(-300px)}body.close .sidebar-toggle{width:auto}body.close .content{left:0}@media print{.app-nav,.github-corner,.sidebar,.sidebar-toggle{display:none}}@media screen and (max-width:768px){.github-corner,.sidebar,.sidebar-toggle{position:fixed}.app-nav{margin-top:16px}.app-nav li ul{top:30px}main{height:auto;overflow-x:hidden}.sidebar{left:-300px;transition:-webkit-transform .25s ease-out;transition:transform .25s ease-out;transition:transform .25s ease-out,-webkit-transform .25s ease-out}.content{left:0;max-width:100vw;position:static;transition:-webkit-transform .25s ease;transition:transform .25s ease;transition:transform .25s ease,-webkit-transform .25s ease}.app-nav,.github-corner{transition:-webkit-transform .25s ease-out;transition:transform .25s ease-out;transition:transform .25s ease-out,-webkit-transform .25s ease-out}.sidebar-toggle{background-color:transparent;width:auto}body.close .sidebar{-webkit-transform:translateX(300px);transform:translateX(300px)}body.close .sidebar-toggle{background-color:hsla(0,0%,100%,.8);transition:background-color 1s;width:284px}body.close .content{-webkit-transform:translateX(300px);transform:translateX(300px)}body.close .app-nav,body.close .github-corner{display:none}.github-corner .octo-arm{-webkit-animation:a .56s ease-in-out;animation:a .56s ease-in-out}.github-corner:hover .octo-arm{-webkit-animation:none;animation:none}}@-webkit-keyframes a{0%,to{-webkit-transform:rotate(0);transform:rotate(0)}20%,60%{-webkit-transform:rotate(-25deg);transform:rotate(-25deg)}40%,80%{-webkit-transform:rotate(10deg);transform:rotate(10deg)}}@keyframes a{0%,to{-webkit-transform:rotate(0);transform:rotate(0)}20%,60%{-webkit-transform:rotate(-25deg);transform:rotate(-25deg)}40%,80%{-webkit-transform:rotate(10deg);transform:rotate(10deg)}}section.cover{-webkit-box-align:center;-ms-flex-align:center;align-items:center;background-position:50%;background-repeat:no-repeat;background-size:cover;height:100vh;display:none}section.cover .cover-main{-webkit-box-flex:1;-ms-flex:1;flex:1;margin:-20px 16px 0;text-align:center;z-index:1}section.cover a{color:inherit}section.cover a,section.cover a:hover{text-decoration:none}section.cover p{line-height:24px;line-height:1.5rem;margin:1em 0}section.cover h1{color:inherit;font-size:40px;font-size:2.5rem;font-weight:300;margin:10px 0 40px;margin:.625rem 0 2.5rem;position:relative;text-align:center}section.cover h1 a{display:block}section.cover h1 small{bottom:-7px;bottom:-.4375rem;font-size:16px;font-size:1rem;position:absolute}section.cover blockquote{font-size:24px;font-size:1.5rem;text-align:center}section.cover ul{line-height:1.8;list-style-type:none;margin:1em auto;max-width:500px;padding:0}section.cover .cover-main>p:last-child a{border-color:#42b983;border:1px solid var(--theme-color,#42b983);border-radius:2rem;box-sizing:border-box;color:#42b983;color:var(--theme-color,#42b983);display:inline-block;font-size:16.8px;font-size:1.05rem;letter-spacing:1.6px;letter-spacing:.1rem;margin-right:16px;margin-right:1rem;padding:.75em 32px;padding:.75em 2rem;text-decoration:none;transition:all .15s ease}section.cover .cover-main>p:last-child a:last-child{background-color:#42b983;background-color:var(--theme-color,#42b983);color:#fff;margin-right:0}section.cover .cover-main>p:last-child a:last-child:hover{color:inherit;opacity:.8}section.cover .cover-main>p:last-child a:hover{color:inherit}section.cover blockquote>p>a{border-bottom:2px solid #42b983;border-bottom:2px solid var(--theme-color,#42b983);transition:color .3s}section.cover blockquote>p>a:hover{color:#42b983;color:var(--theme-color,#42b983)}section.cover.show{display:-webkit-box;display:-ms-flexbox;display:flex}section.cover.has-mask .mask{background-color:#fff;opacity:.8;position:absolute;width:100%;height:100%}.sidebar,body{background-color:#fff}.sidebar{color:#364149}.sidebar li{margin:6px 0 6px 15px}.sidebar ul li a{color:#505d6b;font-size:14px;font-weight:400;overflow:hidden;text-decoration:none;text-overflow:ellipsis;white-space:nowrap}.sidebar ul li a:hover{text-decoration:underline}.sidebar ul li ul{padding:0}.sidebar ul li.active>a{border-right:2px solid;color:#42b983;color:var(--theme-color,#42b983);font-weight:600}.app-sub-sidebar .section-link:before{content:\"-\";padding-right:4px}.markdown-section h1,.markdown-section h2,.markdown-section h3,.markdown-section h4,.markdown-section strong{color:#2c3e50;font-weight:600}.markdown-section a{color:#42b983;color:var(--theme-color,#42b983);font-weight:600}.markdown-section h1{font-size:32px;font-size:2rem;margin:0 0 16px;margin:0 0 1rem}.markdown-section h2{font-size:28px;font-size:1.75rem;margin:45px 0 12.8px;margin:45px 0 .8rem}.markdown-section h3{font-size:24px;font-size:1.5rem;margin:40px 0 9.6px;margin:40px 0 .6rem}.markdown-section h4{font-size:20px;font-size:1.25rem}.markdown-section h5,.markdown-section h6{font-size:16px;font-size:1rem}.markdown-section h6{color:#777}.markdown-section figure,.markdown-section ol,.markdown-section p,.markdown-section ul{margin:1.2em 0}.markdown-section ol,.markdown-section p,.markdown-section ul{line-height:25.6px;line-height:1.6rem;word-spacing:.8px;word-spacing:.05rem}.markdown-section ol,.markdown-section ul{padding-left:24px;padding-left:1.5rem}.markdown-section blockquote{border-left:4px solid #42b983;border-left:4px solid var(--theme-color,#42b983);color:#858585;margin:2em 0;padding-left:20px}.markdown-section blockquote p{font-weight:600;margin-left:0}.markdown-section iframe{margin:1em 0}.markdown-section em{color:#7f8c8d}.markdown-section code{border-radius:2px;color:#e96900;font-size:12.8px;font-size:.8rem;margin:0 2px;padding:3px 5px;white-space:pre-wrap}.markdown-section code,.markdown-section pre{background-color:#f8f8f8;font-family:Roboto Mono,Monaco,courier,monospace}.markdown-section pre{-moz-osx-font-smoothing:initial;-webkit-font-smoothing:initial;line-height:24px;line-height:1.5rem;margin:1.2em 0;overflow:auto;padding:0 22.4px;padding:0 1.4rem;position:relative;word-wrap:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#8e908c}.token.namespace{opacity:.7}.token.boolean,.token.number{color:#c76b29}.token.punctuation{color:#525252}.token.property{color:#c08b30}.token.tag{color:#2973b7}.token.string{color:#42b983;color:var(--theme-color,#42b983)}.token.selector{color:#6679cc}.token.attr-name{color:#2973b7}.language-css .token.string,.style .token.string,.token.entity,.token.url{color:#22a2c9}.token.attr-value,.token.control,.token.directive,.token.unit{color:#42b983;color:var(--theme-color,#42b983)}.token.keyword{color:#e96900}.token.atrule,.token.regex,.token.statement{color:#22a2c9}.token.placeholder,.token.variable{color:#3d8fd1}.token.deleted{text-decoration:line-through}.token.inserted{border-bottom:1px dotted #202746;text-decoration:none}.token.italic{font-style:italic}.token.bold,.token.important{font-weight:700}.token.important{color:#c94922}.token.entity{cursor:help}.markdown-section pre>code{-moz-osx-font-smoothing:initial;-webkit-font-smoothing:initial;background-color:#f8f8f8;border-radius:2px;color:#525252;display:block;font-family:Roboto Mono,Monaco,courier,monospace;font-size:12.8px;font-size:.8rem;line-height:inherit;margin:0 2px;max-width:inherit;overflow:inherit;padding:2.2em 5px;white-space:inherit}.markdown-section code:after,.markdown-section code:before{letter-spacing:.8px;letter-spacing:.05rem}code .token{-moz-osx-font-smoothing:initial;-webkit-font-smoothing:initial;min-height:24px;min-height:1.5rem}pre:after{color:#ccc;content:attr(data-lang);font-size:9.6px;font-size:.6rem;font-weight:600;height:15px;line-height:15px;padding:5px 10px 0;position:absolute;right:0;text-align:right;top:0}"
  },
  {
    "path": "open-xxl-job/doc/分布式任务调度平台XXL-JOB_files/z_stat.php",
    "content": "(function(){function k(){this.c=\"1263800177\";this.ca=\"z\";this.Z=\"\";this.W=\"\";this.Y=\"\";this.C=\"1525694713\";this.aa=\"z7.cnzz.com\";this.X=\"\";this.G=\"CNZZDATA\"+this.c;this.F=\"_CNZZDbridge_\"+this.c;this.P=\"_cnzz_CV\"+this.c;this.R=\"CZ_UUID\"+this.c;this.L=\"UM_distinctid\";this.H=\"0\";this.K={};this.a={};this.Aa()}function g(a,\nb){try{var c=[];c.push(\"siteid=1263800177\");c.push(\"name=\"+f(a.name));c.push(\"msg=\"+f(a.message));c.push(\"r=\"+f(h.referrer));c.push(\"page=\"+f(e.location.href));c.push(\"agent=\"+f(e.navigator.userAgent));c.push(\"ex=\"+f(b));c.push(\"rnd=\"+Math.floor(2147483648*Math.random()));(new Image).src=\"http://jserr.cnzz.com/log.php?\"+c.join(\"&\")}catch(d){}}var h=document,e=window,f=encodeURIComponent,m=decodeURIComponent,r=unescape;k.prototype={Aa:function(){try{this.ja(),this.V(),this.wa(),this.T(),this.za(),\nthis.w(),this.ua(),this.ta(),this.xa(),this.o(),this.sa(),this.va(),this.ya(),this.qa(),this.oa(),this.ra(),this.Ea(),e[this.F]=e[this.F]||{},this.pa(\"_cnzz_CV\")}catch(a){g(a,\"i failed\")}},Ca:function(){try{var a=this;e._czc={push:function(){return a.M.apply(a,arguments)}}}catch(b){g(b,\"oP failed\")}},oa:function(){try{var a=e._czc;if(\"[object Array]\"==={}.toString.call(a))for(var b=0;b<a.length;b++){var c=a[b];switch(c[0]){case \"_setAccount\":e._cz_account=\"[object String]\"==={}.toString.call(c[1])?\nc[1]:String(c[1]);break;case \"_setAutoPageview\":\"boolean\"===typeof c[1]&&(e._cz_autoPageview=c[1])}}}catch(d){g(d,\"cS failed\")}},Ea:function(){try{if(\"undefined\"===typeof e._cz_account||e._cz_account===this.c){e._cz_account=this.c;if(\"[object Array]\"==={}.toString.call(e._czc))for(var a=e._czc,b=0,c=a.length;b<c;b++)this.M(a[b]);this.Ca()}}catch(d){g(d,\"pP failed\")}},M:function(a){try{if(\"[object Array]\"==={}.toString.call(a))switch(a[0]){case \"_trackPageview\":if(a[1]){this.a.f=\"http://\"+\ne.location.host;\"/\"!==a[1].charAt(0)&&(this.a.f+=\"/\");this.a.f+=a[1];if(\"\"===a[2])this.a.g=\"\";else if(a[2]){var b=a[2];\"http\"!==b.substr(0,4)&&(b=\"http://\"+e.location.host,\"/\"!==a[2].charAt(0)&&(b+=\"/\"),b+=a[2]);this.a.g=b}this.s();\"undefined\"!==typeof this.a.g&&delete this.a.g;\"undefined\"!==typeof this.a.f&&delete this.a.f}break;case \"_trackEvent\":var c=[];a[1]&&a[2]&&(c.push(f(a[1])),c.push(f(a[2])),c.push(a[3]?f(a[3]):\"\"),a[4]=parseFloat(a[4]),c.push(isNaN(a[4])?0:a[4]),c.push(a[5]?\nf(a[5]):\"\"),this.v=c.join(\"|\"),this.s(),delete this.v);break;case \"_setCustomVar\":if(3<=a.length){if(!a[1]||!a[2])return!1;var d=a[1],l=a[2],n=a[3]||0;a=0;for(var h in this.a.b)a++;if(5<=a)return!1;var p;0==n?p=\"p\":-1==n||-2==n?p=n:p=(new Date).getTime()+1E3*n;this.a.b[d]={};this.a.b[d].da=l;this.a.b[d].h=p;this.I()}break;case \"_deleteCustomVar\":2<=a.length&&(d=a[1],this.a.b[d]&&(delete this.a.b[d],this.I()));break;case \"_trackPageContent\":a[1]&&(this.D=a[1],this.s(),delete this.D);case \"_trackPageAction\":c=\n[];a[1]&&a[2]&&(c.push(f(a[1])),c.push(f(a[2])),this.u=c.join(\"|\"),this.s(),delete this.u);break;case \"_setUUid\":var m=a[1];if(128<m.length)return!1;var k=new Date;k.setTime(k.getTime()+157248E5);this.ba(this.R,m,k)}}catch(u){g(u,\"aC failed\")}},ra:function(){try{var a=this.m(this.P),b,c;this.a.b={};if(a)for(var d=a.split(\"&\"),a=0;a<d.length;a++)c=m(d[a]),b=c.split(\"|\"),this.a.b[m(b[0])]={},this.a.b[m(b[0])].da=m(b[1]),this.a.b[m(b[0])].h=m(b[2])}catch(l){g(l,\"gCV failed\")}},ka:function(){try{var a=\n(new Date).getTime(),b;for(b in this.a.b)\"p\"===this.a.b[b].h?this.a.b[b].h=0:\"-1\"!==this.a.b[b].h&&a>this.a.b[b].h&&delete this.a.b[b];this.I()}catch(c){g(c,\"cCV failed\")}},I:function(){try{var a=[],b,c,d;for(d in this.a.b){var l=[];l.push(d);l.push(this.a.b[d].da);l.push(this.a.b[d].h);b=l.join(\"|\");a.push(b)}if(!a.length)return!0;var e=new Date;e.setTime(e.getTime()+157248E5);c=this.P+\"=\";this.b=f(a.join(\"&\"));c+=this.b;c+=\"; expires=\"+e.toUTCString();h.cookie=c+\"; path=/\"}catch(t){g(t,\"sCV failed\")}},\nqa:function(){try{if(\"\"!==e.location.hash)return this.O=e.location.href}catch(a){g(a,\"gCP failed\")}},o:function(){try{return this.a.Fa=h.referrer||\"\"}catch(a){g(a,\"gR failed\")}},sa:function(){try{return this.a.A=e.navigator.systemLanguage||e.navigator.language,this.a.A=this.a.A.toLowerCase(),this.a.A}catch(a){g(a,\"gL failed\")}},va:function(){try{return e.screen.width&&e.screen.height?this.a.J=e.screen.width+\"x\"+e.screen.height:this.a.J=\"0x0\",this.a.J}catch(a){g(a,\"gS failed\")}},w:function(){try{return this.a.Ba=\nthis.i(\"ntime\")||\"none\"}catch(a){g(a,\"gLVST failed\")}},U:function(){try{return this.a.ea=this.i(\"ltime\")||(new Date).getTime()}catch(a){g(a,\"gFVBT failed\")}},ua:function(){try{var a=this.i(\"cnzz_a\");if(null===a)a=0;else{var b=1E3*this.w(),c=new Date;c.setTime(b);(new Date).getDate()===c.getDate()?a++:a=0}return this.a.Ja=a}catch(d){g(d,\"gRT failed\")}},ta:function(){try{return this.a.B=this.i(\"rtime\"),null===this.a.B&&(this.a.B=0),0<this.U()&&432E5<(new Date).getTime()-this.U()&&(this.a.B++,this.a.ea=\n(new Date).getTime()),this.a.B}catch(a){g(a,\"gRVT failed\")}},xa:function(){try{return\"none\"===this.w()?this.a.Ia=0:this.a.Ia=parseInt(((new Date).getTime()-1E3*this.w())/1E3)}catch(a){g(a,\"gST failed\")}},wa:function(){try{var a=this.i(\"sin\")||\"none\";if(!h.domain)return this.a.Ha=\"none\";this.o().split(\"/\")[2]!==h.domain&&(a=this.o());return this.a.Ha=a}catch(b){g(b,\"gS failed\")}},T:function(){try{return this.a.l=this.i(\"cnzz_eid\")||\"none\"}catch(a){g(a,\"gC failed\")}},Ga:function(){try{var a=\"http://c.cnzz.com/core.php?\",\nb=[];b.push(\"web_id=\"+f(this.c));this.Z&&b.push(\"show=\"+f(this.Z));this.Y&&b.push(\"online=\"+f(this.Y));this.W&&b.push(\"l=\"+f(this.W));this.ca&&b.push(\"t=\"+this.ca);a+=b.join(\"&\");this.na(a,\"utf-8\")}catch(c){g(c,\"rN failed\")}},ja:function(){try{return!1===e.navigator.cookieEnabled?this.a.ma=!1:this.a.ma=!0}catch(a){g(a,\"cCE failed\")}},ba:function(a,b,c,d,e,g){a=f(a)+\"=\"+f(b);c instanceof Date&&(a+=\"; expires=\"+c.toGMTString());d&&(a+=\"; path=\"+d);e&&(a+=\"; domain=\"+e);g&&(a+=\"; secure\");h.cookie=a},\nm:function(a){try{a+=\"=\";var b=h.cookie,c=b.indexOf(a),d=\"\";if(-1<c){var e=b.indexOf(\";\",c);-1===e&&(e=b.length);d=m(b.substring(c+a.length,e))}return d?d:\"\"}catch(n){g(n,\"gAC failed\")}},pa:function(a){try{h.cookie=a+\"=; expires=\"+(new Date(0)).toUTCString()+\"; path=/\"}catch(b){g(b,\"dAC failed\")}},ya:function(){try{var a=h.title;40<a.length&&(a=a.substr(0,40),a+=\"...\");this.a.Da=a}catch(b){g(b,\"gT failed\")}},N:function(a){try{return\"http\"!==a.substr(0,4)?\"\":/http:\\/\\/.*?\\//i.exec(a)}catch(b){g(b,\n\"cH failed\")}},V:function(){try{var a=this.G,b={},c=this.m(this.G);if(0<c.length)if(1E8<this.c){var d=c.split(\"|\");b.cnzz_eid=m(d[0]);b.ntime=m(d[1])}else for(var d=c.split(\"&\"),e=0,f=d.length;e<f;e++){var h=d[e].split(\"=\");b[m(h[0])]=m(h[1])}this.K=b}catch(p){g(p,\"iC failed:\"+a+\":\"+c)}},$:function(){try{var a=this.G+\"=\",b=[],c=new Date;c.setTime(c.getTime()+157248E5);if(1E8<this.c){if(\"none\"!==this.a.l)b.push(f(this.a.l));else{var d=Math.floor(2147483648*Math.random())+\"-\"+this.C+\"-\"+this.N(this.o());\nb.push(f(d))}b.push(this.C);0<b.length?(a+=f(b.join(\"|\")),a+=\"; expires=\"+c.toUTCString(),a+=\"; path=/\"):a+=\"; expires=\"+(new Date(0)).toUTCString()}else\"none\"!==this.a.l?b.push(\"cnzz_eid=\"+f(this.a.l)):(d=Math.floor(2147483648*Math.random())+\"-\"+this.C+\"-\"+this.N(this.o()),b.push(\"cnzz_eid=\"+f(d))),b.push(\"ntime=\"+this.C),0<b.length?(a+=f(b.join(\"&\")),a+=\"; expires=\"+c.toUTCString(),a+=\"; path=/\"):a+=\"; expires=\"+(new Date(0)).toUTCString();h.cookie=a}catch(l){g(l,\"sS failed\")}},i:function(a){try{return\"undefined\"!==\ntypeof this.K[a]?this.K[a]:null}catch(b){g(b,\"gCPa failed\")}},na:function(a,b){try{if(b=b||\"utf-8\",\"1\"===this.H){var c=h.createElement(\"script\");c.type=\"text/javascript\";c.async=!0;c.charset=b;c.src=a;var d=h.getElementsByTagName(\"script\")[0];d.parentNode&&d.parentNode.insertBefore(c,d)}else h.write(r(\"%3Cscript src='\"+a+\"' charset='\"+b+\"' type='text/javascript'%3E%3C/script%3E\"))}catch(l){g(l,\"cAS failed\")}},ha:function(a,b){try{var c=h.getElementById(\"cnzz_stat_icon_\"+this.c);if(c){var d=h.createElement(\"script\");\nd.type=\"text/javascript\";d.async=!0;d.charset=b;d.src=a;c.appendChild(d)}else\"0\"===this.H&&h.write(r(\"%3Cscript src='\"+a+\"' charset='\"+b+\"' type='text/javascript'%3E%3C/script%3E\"))}catch(l){g(l,\"cSI failed\")}},ga:function(a){try{for(var b=a.length,c=\"\",d=0;d<b;d++)a[d]&&(c+=r(a[d]));var e=h.getElementById(\"cnzz_stat_icon_\"+this.c);e?e.innerHTML=c:\"0\"===this.H&&h.write(c)}catch(n){g(n,\"cI failed\")}},s:function(){try{this.$();this.V();this.T();this.ka();var a=this.m(this.R),b=[];b.push(\"id=\"+f(this.c));\nthis.a.g||\"\"===this.a.g?b.push(\"r=\"+f(this.a.g)):b.push(\"r=\"+f(this.a.Fa));b.push(\"lg=\"+f(this.a.A));b.push(\"ntime=\"+f(this.a.Ba));b.push(\"cnzz_eid=\"+f(this.a.l));b.push(\"showp=\"+f(this.a.J));this.a.f?b.push(\"p=\"+f(this.a.f)):\"[object String]\"==={}.toString.call(this.O)&&b.push(\"p=\"+f(this.O));\"[object String]\"==={}.toString.call(this.v)&&b.push(\"ei=\"+f(this.v));\"[object String]\"==={}.toString.call(this.b)&&b.push(\"cv=\"+this.b);\"[object String]\"==={}.toString.call(this.D)&&b.push(\"pc=\"+f(this.D));\n\"[object String]\"==={}.toString.call(this.u)&&b.push(\"ai=\"+this.u);a&&b.push(\"uuid=\"+f(a));b.push(\"t=\"+f(this.a.Da));b.push(\"umuuid=\"+f(this.a.S));b.push(\"h=1\");var c=b.join(\"&\");\"[object String]\"==={}.toString.call(this.v)?this.j([\"http://ei.cnzz.com/stat.htm?\"+c]):this.D||this.u?this.j([\"http://ca.cnzz.com/stat.htm?\"+c]):(this.X&&this.j([\"http://\"+this.X+\"/stat.htm?\"+c]),this.aa&&this.j([\"http://\"+this.aa+\"/stat.htm?\"+c]))}catch(d){g(d,\n\"sD failed\")}},fa:function(){function a(){function a(a,b){var c,d=0;for(c=0;c<b.length;c++)d|=h[c]<<8*c;return a^d}var b=e.navigator.userAgent,f,g,h=[],k=0;for(f=0;f<b.length;f++)g=b.charCodeAt(f),h.unshift(g&255),4<=h.length&&(k=a(k,h),h=[]);0<h.length&&(k=a(k,h));return k.toString(16)}function b(){for(var a=1*new Date,b=0;a==1*new Date;)b++;return a.toString(16)+b.toString(16)}return function(){var c=(e.screen.height*e.screen.width).toString(16);return b()+\"-\"+Math.random().toString(16).replace(\".\",\n\"\")+\"-\"+a()+\"-\"+c+\"-\"+b()}}(),za:function(){try{var a=this.a,b;if(!(b=this.m(this.L))){var c=this.fa(),d=new Date;d.setTime(d.getTime()+157248E5);var e=document.location.hostname.match(/[a-z0-9][a-z0-9\\-]+\\.[a-z\\.]{2,6}$/i);this.ba(this.L,c,d,\"/\",e?e[0]:\"\");b=c}a.S=b;return this.a.S}catch(n){g(n,\"gC failed\")}},j:function(a){try{for(var b=a.length,c=null,d=0;d<b;d++)a[d]&&(c=\"cnzz_image_\"+Math.floor(2147483648*Math.random()),e[c]=new Image,e[c].la=c,e[c].onload=e[c].onerror=e[c].onabort=function(){try{this.onload=\nthis.onerror=this.onabort=null,e[this.la]=null}catch(l){}},e[c].src=a[d]+\"&rnd=\"+Math.floor(2147483648*Math.random()))}catch(l){g(l,\"cR failed\")}},ia:function(){for(var a=e.navigator.userAgent.toLowerCase(),b=0;12>b;b++)if(-1<a.indexOf(\"#mobileconf#\"[b]))return\"mobile\";return\"pc\"}};try{var q=new k;e[q.F].bobject=q;!1!==e._cz_autoPageview?q.s():q.$();k.prototype.getACookie=k.prototype.m;k.prototype.callRequest=k.prototype.j;k.prototype.createScriptIcon=k.prototype.ha;k.prototype.createIcon=k.prototype.ga;\nq.Ga();q.ia()}catch(a){g(a,\"main failed\")}})();\n"
  },
  {
    "path": "open-xxl-job/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" 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 <parent>\n    <groupId>com.open.capacity</groupId>\n    <artifactId>open-capacity-platform</artifactId>\n    <version>0.0.1-SNAPSHOT</version>\n  </parent>\n  <artifactId>open-xxl-job</artifactId>\n  <packaging>pom</packaging>\n  \n  <properties> \n  \t<javax.servlet-api.version>3.0.1</javax.servlet-api.version>\n\t\t<jsp-api.version>2.2</jsp-api.version>\n\n\t\t<spring.version>4.3.14.RELEASE</spring.version>\n\t\t<jackson.version>2.9.4</jackson.version>\n\t\t<aspectjweaver.version>1.8.13</aspectjweaver.version>\n\t\t<freemarker.version>2.3.23</freemarker.version>\n\t\t<junit.version>4.12</junit.version>\n\n\t\t<jetty-server.version>9.2.24.v20180105</jetty-server.version>\n\t\t<hessian.version>4.0.51</hessian.version>\n\t\t<httpclient.version>4.5.5</httpclient.version>\n\t\t\n\t\t<commons-exec.version>1.3</commons-exec.version>\n\t\t<commons-collections4.version>4.1</commons-collections4.version>\n\t\t<commons-lang3.version>3.7</commons-lang3.version>\n\t\t<commons-email.version>1.5</commons-email.version>\n\n\t\t<c3p0.version>0.9.5.2</c3p0.version>\n\t\t<mysql-connector-java.version>5.1.45</mysql-connector-java.version>\n\t\t<mybatis-spring.version>1.3.1</mybatis-spring.version>\n\t\t<mybatis.version>3.4.5</mybatis.version>\n\n\t\t<groovy-all.version>2.4.13</groovy-all.version>\n\t\t<quartz.version>2.3.0</quartz.version>\n\n\t\t<spring-boot.version>1.5.10.RELEASE</spring-boot.version>\n\t</properties>\n  \n  \n  <modules>\n  \t<module>xxl-job-core</module>\n  \t<module>xxl-job-admin</module>\n  \t<module>xxl-job-demo</module>\n  \t\n  </modules>\n</project>"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\t<parent>\n\t\t<groupId>com.open.capacity</groupId>\n\t\t<artifactId>open-xxl-job</artifactId>\n\t\t<version>0.0.1-SNAPSHOT</version>\n\t</parent>\n\t<artifactId>xxl-job-admin</artifactId>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.apache.commons</groupId>\n\t\t\t<artifactId>commons-lang3</artifactId>\n\t\t\t<version>3.7</version>\n\t\t</dependency>\n\t\t\n\t\t<!-- commons-collections4 -->\n\t\t<dependency>\n\t\t\t<groupId>org.apache.commons</groupId>\n\t\t\t<artifactId>commons-collections4</artifactId>\n\t\t\t<version>${commons-collections4.version}</version>\n\t\t</dependency>\n\t\t<!-- commons-email -->\n\t\t<dependency>\n\t\t\t<groupId>org.apache.commons</groupId>\n\t\t\t<artifactId>commons-email</artifactId>\n\t\t\t<version>${commons-email.version}</version>\n\t\t</dependency>\n\n\t\t\n\t\t<dependency>\n\t\t\t<groupId>com.alibaba</groupId>\n\t\t\t<artifactId>fastjson</artifactId>\n\t\t\t<version>1.2.4</version>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>io.springfox</groupId>\n\t\t\t<artifactId>springfox-swagger-ui</artifactId>\n\t\t\t<version>2.5.0</version>\n\t\t\t<scope>compile</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>io.springfox</groupId>\n\t\t\t<artifactId>springfox-swagger2</artifactId>\n\t\t\t<version>2.5.0</version>\n\t\t\t<scope>compile</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.quartz-scheduler</groupId>\n\t\t\t<artifactId>quartz-jobs</artifactId>\n\t\t\t<version>2.3.0</version>\n\t\t</dependency>\n\t\t \n\t  \n\t\t<dependency>\n\t\t\t<groupId>org.aspectj</groupId>\n\t\t\t<artifactId>aspectjweaver</artifactId>\n\t\t\t<version>1.8.13</version>\n\t\t</dependency>\n\t\t<!-- jackson (support spring json) -->\n\t\t<dependency>\n\t\t\t<groupId>org.codehaus.jackson</groupId>\n\t\t\t<artifactId>jackson-mapper-asl</artifactId>\n\t\t\t<version>1.9.13</version>\n\t\t</dependency>\n\t\t\n\t\t<!-- 关系型和非关系型数据库配置 -->\n\t\t<dependency>\n\t\t\t<groupId>com.open.capacity</groupId>\n\t\t\t<artifactId>open-db-core</artifactId>\n\t\t\t<version>${core.version}</version>\n\t\t</dependency>\n\t\t \n\n\t\t<!-- commons-beanutils -->\n\t\t<dependency>\n\t\t\t<groupId>commons-beanutils</groupId>\n\t\t\t<artifactId>commons-beanutils</artifactId>\n\t\t\t<version>1.9.3</version>\n\t\t</dependency>\n\t\t<!-- commons-lang -->\n\t\t<dependency>\n\t\t\t<groupId>commons-lang</groupId>\n\t\t\t<artifactId>commons-lang</artifactId>\n\t\t\t<version>2.6</version>\n\t\t</dependency>\n\n\t\t<!-- servlet -->\n\t\t<dependency>\n\t\t\t<groupId>javax.servlet</groupId>\n\t\t\t<artifactId>javax.servlet-api</artifactId>\n\t\t\t<version>3.1.0</version>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>javax.servlet.jsp</groupId>\n\t\t\t<artifactId>jsp-api</artifactId>\n\t\t\t<version>2.2</version>\n\t\t</dependency>\n\n\t\t<!-- junit -->\n\t\t<dependency>\n\t\t\t<groupId>junit</groupId>\n\t\t\t<artifactId>junit</artifactId>\n\t\t\t<version>4.12</version>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t <dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-freemarker</artifactId>\n\t\t</dependency>\n\t\t<!-- freemarker -->\n\t\t<dependency>\n\t\t\t<groupId>org.freemarker</groupId>\n\t\t\t<artifactId>freemarker</artifactId>\n\t\t\t<version>2.3.27-incubating</version>\n\t\t</dependency>\n\t\t<dependency><!-- 该依赖必加，里面有sping对schedule的支持 -->\n\t\t\t<groupId>org.springframework</groupId>\n\t\t\t<artifactId>spring-context-support</artifactId>\n\t\t</dependency>\n\t \n\n\n\t\t<!-- httpclient -->\n\t\t<dependency>\n\t\t\t<groupId>org.apache.httpcomponents</groupId>\n\t\t\t<artifactId>httpclient</artifactId>\n\t\t\t<version>4.5.2</version>\n\t\t</dependency>\n\n\t\t<!-- javax.mail -->\n\t\t<dependency>\n\t\t\t<groupId>javax.mail</groupId>\n\t\t\t<artifactId>mail</artifactId>\n\t\t\t<version>1.4.7</version>\n\t\t</dependency>\n\n\t\t<!-- quartz ：quartz-2.2.3/c3p0-0.9.1.1/slf4j-api-1.6.6 -->\n\t\t<!-- quartz ：quartz-2.2.3/c3p0-0.9.1.1/slf4j-api-1.6.6 -->\n\t\t <dependency>\n\t\t\t<groupId>org.quartz-scheduler</groupId>\n\t\t\t<artifactId>quartz</artifactId>\n\t\t\t<version>2.3.0</version>\n\t\t\t<exclusions>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<artifactId>c3p0</artifactId>\n\t\t\t\t\t<groupId>com.mchange</groupId>\n\t\t\t\t</exclusion>\n\t\t\t</exclusions>\n\t\t</dependency>\n\t\t\n\n\t\t<!-- xxl-job-core -->\n\t\t<dependency>\n\t\t\t<groupId>com.open.capacity</groupId>\n\t\t\t<artifactId>xxl-job-core</artifactId>\n\t\t\t<version>0.0.1-SNAPSHOT</version>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-devtools</artifactId>\n\t\t</dependency>\n\t\t<!--<dependency> -->\n\t\t<!--<groupId>org.springframework.boot</groupId> -->\n\t\t<!--<artifactId>spring-boot-starter-thymeleaf</artifactId> -->\n\t\t<!--</dependency> -->\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web-services</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/Application.java",
    "content": "package com.xxl.job.admin;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.boot.context.properties.EnableConfigurationProperties;\nimport org.springframework.context.annotation.ComponentScan;\nimport org.springframework.context.annotation.ImportResource;\nimport org.springframework.context.annotation.PropertySource;\n\n/**\n * Created by ccb on 2017/1/20.\n */\n\n\n@SpringBootApplication\n@ComponentScan(basePackages={\"com.xxl.job.admin\",\"com.open.capacity\"})\n@PropertySource(value = \"classpath:xxl-job-admin.properties\")\npublic class Application {\n    public static void main(String[] args){\n        SpringApplication.run(Application.class,args);\n    }\n}"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/component/SpringJobFactory.java",
    "content": "package com.xxl.job.admin.component;\n\nimport org.quartz.spi.TriggerFiredBundle;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.config.AutowireCapableBeanFactory;\nimport org.springframework.scheduling.quartz.AdaptableJobFactory;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class SpringJobFactory extends AdaptableJobFactory {\n\n    @Autowired\n    private AutowireCapableBeanFactory capableBeanFactory;\n\n    @Override\n    protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {\n        Object jobInstance = super.createJobInstance(bundle);\n        capableBeanFactory.autowireBean(jobInstance);\n        return jobInstance;\n    }\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/config/MyWebMvcConfigurer.java",
    "content": "package com.xxl.job.admin.config;\n\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.stereotype.Component;\nimport org.springframework.web.servlet.config.annotation.InterceptorRegistry;\nimport org.springframework.web.servlet.config.annotation.ViewControllerRegistry;\nimport org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;\n\nimport com.xxl.job.admin.controller.interceptor.PermissionInterceptor;\n\n@Configuration\npublic class MyWebMvcConfigurer extends WebMvcConfigurerAdapter {\n    @Override\n    public void addInterceptors(InterceptorRegistry registry) {\n        registry.addInterceptor(new PermissionInterceptor()).addPathPatterns(\"/**\").excludePathPatterns(\"/toLogin\");\n        super.addInterceptors(registry);\n\n    }\n\n    /**\n     * 过去要访问一个页面需要先创建个Controller控制类，再写方法跳转到页面\n     * 在这里配置后就不需要那么麻烦了，直接访问http://localhost:8080/toLogin就跳转到login.jsp页面了\n     *\n     * @param registry\n     */\n    @Override\n    public void addViewControllers(ViewControllerRegistry registry) {\n        registry.addViewController(\"/\").setViewName(\"/toLogin\");\n        super.addViewControllers(registry);\n    }\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/config/QuartzConfig.java",
    "content": "package com.xxl.job.admin.config;\n\nimport java.io.IOException;\nimport java.util.Properties;\n\nimport javax.sql.DataSource;\n\nimport org.quartz.Scheduler;\nimport org.quartz.SchedulerException;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.scheduling.quartz.SchedulerFactoryBean;\n\nimport com.xxl.job.admin.component.SpringJobFactory;\n\n/**\n * @author owen 定时任务配置\n *\n */\n@Configuration\npublic class QuartzConfig {\n\t@Autowired\n\tprivate SpringJobFactory springJobFactory;\n\t@Autowired\n\tprivate DataSource druidDataSource ;\n\t\n\t@Bean\n\tpublic SchedulerFactoryBean schedulerFactoryBean() {\n\t\tSchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();\n\t\ttry {\n\t\t\tschedulerFactoryBean.setDataSource(druidDataSource);\n\t\t\tschedulerFactoryBean.setQuartzProperties(quartzProperties());\n\t\t\tschedulerFactoryBean.setJobFactory(springJobFactory);\n\t\t} catch (IOException e) {\n\t\t\t// TODO Auto-generated catch block\n\t\t\te.printStackTrace();\n\t\t}\n\t\treturn schedulerFactoryBean;\n\t}\n\n\t@Bean(name = \"scheduler\")\n\tpublic Scheduler scheduler() throws IOException, SchedulerException {\n\t\treturn schedulerFactoryBean().getScheduler();\n\t}\n\n\t/**\n\t * 设置quartz属性\n\t *\n\t * @throws IOException\n\t */\n\tpublic Properties quartzProperties() throws IOException {\n\t\tProperties prop = new Properties();\n\t\t// prop.setProperty(\"org.quartz.scheduler.rmi.export\", \"false\");\n\t\t// prop.setProperty(\"org.quartz.scheduler.rmi.proxy\", \"false\");\n\t\t// prop.setProperty(\"org.quartz.scheduler.wrapJobExecutionInUserTransaction\",\n\t\t// \"false\");\n\t\tprop.setProperty(\"org.quartz.scheduler.instanceName\", \"scheduler\");\n\t\tprop.setProperty(\"org.quartz.scheduler.instanceId\", \"AUTO\");\n\t\t// prop.setProperty(\"org.quartz.scheduler.skipUpdateCheck\", \"true\");\n\t\t// prop.setProperty(\"org.quartz.scheduler.jobFactory.class\",\n\t\t// \"org.quartz.simpl.SimpleJobFactory\");\n\t\tprop.setProperty(\"org.quartz.jobStore.class\", \"org.quartz.impl.jdbcjobstore.JobStoreTX\");\n\t\tprop.setProperty(\"org.quartz.jobStore.misfireThreshold\", \"60000\");\n\t\tprop.setProperty(\"org.quartz.jobStore.maxMisfiresToHandleAtATime\", \"1\");\n\t\tprop.setProperty(\"org.quartz.jobStore.tablePrefix\", \"XXL_JOB_QRTZ_\");\n\t\tprop.setProperty(\"org.quartz.jobStore.isClustered\", \"true\");// 是否集群\n\t\tprop.setProperty(\"org.quartz.jobStore.clusterCheckinInterval\", \"5000\");\n\t\tprop.setProperty(\"org.quartz.jobStore.dataSource\", \"quartzDataSource\");\n\t\tprop.setProperty(\"org.quartz.threadPool.class\", \"org.quartz.simpl.SimpleThreadPool\");\n\t\tprop.setProperty(\"org.quartz.threadPool.threadPriority\", \"5\");\n\t\tprop.setProperty(\"org.quartz.threadPool.threadCount\", \"15\");\n\t\tprop.setProperty(\"org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread\", \"1000\");\n\t\treturn prop;\n\t}\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/config/Swagger2Config.java",
    "content": "/**\n * @Copyright ®2017 Sinosoft Co. Ltd. All rights reserved.<br/>\n * 项目名称 : 交银康联智能运营平台\n * 创建日期 : 2017年5月24日\n * 修改历史 : \n *     1. [2017年5月24日]创建文件 by sinosoft\n */\npackage com.xxl.job.admin.config;\n\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\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 * Configuration注解　加载此类配置\n * EnableSwagger2注解　启用Swagger2\n * @author sinfosoft\n * @date 2017年5月24日 下午5:47:11 \n * @version V1.0\n */\n@Configuration\n@EnableSwagger2\npublic class Swagger2Config {\n\n    @Bean\n    public Docket createRestApi() {\n        return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()) //创建API基本信息\n                .groupName(\"\") //指定分组，对应(/v2/api-docs?group=)\n                .pathMapping(\"\") //base地址，最终会拼接Controller中的地址\n                .select() //控制要暴露的接口\n                .apis(RequestHandlerSelectors.basePackage(\"com.shaoytsh.spinrgbootwebproject.controller\")) //通过指定扫描包暴露接口\n                .paths(PathSelectors.any()) //设置过滤规则暴露接口\n                .build();\n    }\n\n    private ApiInfo apiInfo() {\n        return new ApiInfoBuilder().title(\"job RESTful APIs\").description(\"业务服务\").termsOfServiceUrl(\"\")\n                .contact(new Contact(\"shaoytsh\", \"http://shaoytsh.cn/\", \"shyttsyj@126.com\")).version(\"1.0\").license(\"\").licenseUrl(\"\").build();\n    }\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/controller/IndexController.java",
    "content": "package com.xxl.job.admin.controller;\n\nimport com.xxl.job.admin.controller.annotation.PermessionLimit;\nimport com.xxl.job.admin.controller.interceptor.PermissionInterceptor;\nimport com.xxl.job.admin.core.util.I18nUtil;\nimport com.xxl.job.admin.service.XxlJobService;\nimport com.xxl.job.core.biz.model.ReturnT;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.propertyeditors.CustomDateEditor;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.WebDataBinder;\nimport org.springframework.web.bind.annotation.InitBinder;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.ResponseBody;\n\nimport javax.annotation.Resource;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\nimport java.util.Map;\n\n/**\n * index controller\n * @author xuxueli 2015-12-19 16:13:16\n */\n@Controller\npublic class IndexController {\n\n\t@Resource\n\tprivate XxlJobService xxlJobService;\n\n\t@RequestMapping(\"/\")\n\tpublic String index(Model model) {\n\n\t\tMap<String, Object> dashboardMap = xxlJobService.dashboardInfo();\n\t\tmodel.addAllAttributes(dashboardMap);\n\n\t\treturn \"index\";\n\t}\n\n    @RequestMapping(\"/chartInfo\")\n\t@ResponseBody\n\tpublic ReturnT<Map<String, Object>> chartInfo(Date startDate, Date endDate) {\n        ReturnT<Map<String, Object>> chartInfo = xxlJobService.chartInfo(startDate, endDate);\n        return chartInfo;\n    }\n\t\n\t@RequestMapping(\"/toLogin\")\n\t@PermessionLimit(limit=false)\n\tpublic String toLogin(Model model, HttpServletRequest request) {\n\t\tif (PermissionInterceptor.ifLogin(request)) {\n\t\t\treturn \"redirect:/\";\n\t\t}\n\t\treturn \"login\";\n\t}\n\t\n\t@RequestMapping(value=\"login\", method=RequestMethod.POST)\n\t@ResponseBody\n\t@PermessionLimit(limit=false)\n\tpublic ReturnT<String> loginDo(HttpServletRequest request, HttpServletResponse response, String userName, String password, String ifRemember){\n\t\t// valid\n\t\tif (PermissionInterceptor.ifLogin(request)) {\n\t\t\treturn ReturnT.SUCCESS;\n\t\t}\n\n\t\t// param\n\t\tif (StringUtils.isBlank(userName) || StringUtils.isBlank(password)){\n\t\t\treturn new ReturnT<String>(500, I18nUtil.getString(\"login_param_empty\"));\n\t\t}\n\t\tboolean ifRem = (StringUtils.isNotBlank(ifRemember) && \"on\".equals(ifRemember))?true:false;\n\n\t\t// do login\n\t\tboolean loginRet = PermissionInterceptor.login(response, userName, password, ifRem);\n\t\tif (!loginRet) {\n\t\t\treturn new ReturnT<String>(500, I18nUtil.getString(\"login_param_unvalid\"));\n\t\t}\n\t\treturn ReturnT.SUCCESS;\n\t}\n\t\n\t@RequestMapping(value=\"logout\", method=RequestMethod.POST)\n\t@ResponseBody\n\t@PermessionLimit(limit=false)\n\tpublic ReturnT<String> logout(HttpServletRequest request, HttpServletResponse response){\n\t\tif (PermissionInterceptor.ifLogin(request)) {\n\t\t\tPermissionInterceptor.logout(request, response);\n\t\t}\n\t\treturn ReturnT.SUCCESS;\n\t}\n\t\n\t@RequestMapping(\"/help\")\n\tpublic String help() {\n\n\t\t/*if (!PermissionInterceptor.ifLogin(request)) {\n\t\t\treturn \"redirect:/toLogin\";\n\t\t}*/\n\n\t\treturn \"help\";\n\t}\n\n\t@InitBinder\n\tpublic void initBinder(WebDataBinder binder) {\n\t\tSimpleDateFormat dateFormat = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n\t\tdateFormat.setLenient(false);\n\t\tbinder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));\n\t}\n\t\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/controller/JobApiController.java",
    "content": "package com.xxl.job.admin.controller;\n\nimport com.xxl.job.admin.controller.annotation.PermessionLimit;\nimport com.xxl.job.core.biz.AdminBiz;\nimport com.xxl.job.core.rpc.codec.RpcRequest;\nimport com.xxl.job.core.rpc.codec.RpcResponse;\nimport com.xxl.job.core.rpc.netcom.NetComServerFactory;\nimport com.xxl.job.core.rpc.serialize.HessianSerializer;\nimport com.xxl.job.core.util.HttpClientUtil;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.RequestMapping;\n\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport java.io.IOException;\nimport java.io.OutputStream;\n\n/**\n * Created by xuxueli on 17/5/10.\n */\n@Controller\npublic class JobApiController {\n    private static Logger logger = LoggerFactory.getLogger(JobApiController.class);\n\n    private RpcResponse doInvoke(HttpServletRequest request) {\n        try {\n            // deserialize request\n            byte[] requestBytes = HttpClientUtil.readBytes(request);\n            if (requestBytes == null || requestBytes.length==0) {\n                RpcResponse rpcResponse = new RpcResponse();\n                rpcResponse.setError(\"RpcRequest byte[] is null\");\n                return rpcResponse;\n            }\n            RpcRequest rpcRequest = (RpcRequest) HessianSerializer.deserialize(requestBytes, RpcRequest.class);\n\n            // invoke\n            RpcResponse rpcResponse = NetComServerFactory.invokeService(rpcRequest, null);\n            return rpcResponse;\n        } catch (Exception e) {\n            logger.error(e.getMessage(), e);\n\n            RpcResponse rpcResponse = new RpcResponse();\n            rpcResponse.setError(\"Server-error:\" + e.getMessage());\n            return rpcResponse;\n        }\n    }\n\n    @RequestMapping(AdminBiz.MAPPING)\n    @PermessionLimit(limit=false)\n    public void api(HttpServletRequest request, HttpServletResponse response) throws IOException {\n\n        // invoke\n        RpcResponse rpcResponse = doInvoke(request);\n\n        // serialize response\n        byte[] responseBytes = HessianSerializer.serialize(rpcResponse);\n\n        response.setContentType(\"text/html;charset=utf-8\");\n        response.setStatus(HttpServletResponse.SC_OK);\n        //baseRequest.setHandled(true);\n\n        OutputStream out = response.getOutputStream();\n        out.write(responseBytes);\n        out.flush();\n    }\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/controller/JobCodeController.java",
    "content": "package com.xxl.job.admin.controller;\n\nimport com.xxl.job.admin.core.model.XxlJobInfo;\nimport com.xxl.job.admin.core.model.XxlJobLogGlue;\nimport com.xxl.job.admin.core.util.I18nUtil;\nimport com.xxl.job.admin.dao.XxlJobInfoDao;\nimport com.xxl.job.admin.dao.XxlJobLogGlueDao;\nimport com.xxl.job.core.biz.model.ReturnT;\nimport com.xxl.job.core.glue.GlueTypeEnum;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.ResponseBody;\n\nimport javax.annotation.Resource;\nimport java.util.Date;\nimport java.util.List;\n\n/**\n * job code controller\n * @author xuxueli 2015-12-19 16:13:16\n */\n@Controller\n@RequestMapping(\"/jobcode\")\npublic class JobCodeController {\n\t\n\t@Resource\n\tprivate XxlJobInfoDao xxlJobInfoDao;\n\t@Resource\n\tprivate XxlJobLogGlueDao xxlJobLogGlueDao;\n\n\t@RequestMapping\n\tpublic String index(Model model, int jobId) {\n\t\tXxlJobInfo jobInfo = xxlJobInfoDao.loadById(jobId);\n\t\tList<XxlJobLogGlue> jobLogGlues = xxlJobLogGlueDao.findByJobId(jobId);\n\n\t\tif (jobInfo == null) {\n\t\t\tthrow new RuntimeException(I18nUtil.getString(\"jobinfo_glue_jobid_unvalid\"));\n\t\t}\n\t\tif (GlueTypeEnum.BEAN == GlueTypeEnum.match(jobInfo.getGlueType())) {\n\t\t\tthrow new RuntimeException(I18nUtil.getString(\"jobinfo_glue_gluetype_unvalid\"));\n\t\t}\n\n\t\t// Glue类型-字典\n\t\tmodel.addAttribute(\"GlueTypeEnum\", GlueTypeEnum.values());\n\n\t\tmodel.addAttribute(\"jobInfo\", jobInfo);\n\t\tmodel.addAttribute(\"jobLogGlues\", jobLogGlues);\n\t\treturn \"jobcode/jobcode.index\";\n\t}\n\t\n\t@RequestMapping(\"/save\")\n\t@ResponseBody\n\tpublic ReturnT<String> save(Model model, int id, String glueSource, String glueRemark) {\n\t\t// valid\n\t\tif (glueRemark==null) {\n\t\t\treturn new ReturnT<String>(500, (I18nUtil.getString(\"system_please_input\") + I18nUtil.getString(\"jobinfo_glue_remark\")) );\n\t\t}\n\t\tif (glueRemark.length()<4 || glueRemark.length()>100) {\n\t\t\treturn new ReturnT<String>(500, I18nUtil.getString(\"jobinfo_glue_remark_limit\"));\n\t\t}\n\t\tXxlJobInfo exists_jobInfo = xxlJobInfoDao.loadById(id);\n\t\tif (exists_jobInfo == null) {\n\t\t\treturn new ReturnT<String>(500, I18nUtil.getString(\"jobinfo_glue_jobid_unvalid\"));\n\t\t}\n\t\t\n\t\t// update new code\n\t\texists_jobInfo.setGlueSource(glueSource);\n\t\texists_jobInfo.setGlueRemark(glueRemark);\n\t\texists_jobInfo.setGlueUpdatetime(new Date());\n\t\txxlJobInfoDao.update(exists_jobInfo);\n\n\t\t// log old code\n\t\tXxlJobLogGlue xxlJobLogGlue = new XxlJobLogGlue();\n\t\txxlJobLogGlue.setJobId(exists_jobInfo.getId());\n\t\txxlJobLogGlue.setGlueType(exists_jobInfo.getGlueType());\n\t\txxlJobLogGlue.setGlueSource(glueSource);\n\t\txxlJobLogGlue.setGlueRemark(glueRemark);\n\t\txxlJobLogGlueDao.save(xxlJobLogGlue);\n\n\t\t// remove code backup more than 30\n\t\txxlJobLogGlueDao.removeOld(exists_jobInfo.getId(), 30);\n\n\t\treturn ReturnT.SUCCESS;\n\t}\n\t\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/controller/JobGroupController.java",
    "content": "package com.xxl.job.admin.controller;\n\nimport com.xxl.job.admin.core.model.XxlJobGroup;\nimport com.xxl.job.admin.core.util.I18nUtil;\nimport com.xxl.job.admin.dao.XxlJobGroupDao;\nimport com.xxl.job.admin.dao.XxlJobInfoDao;\nimport com.xxl.job.core.biz.model.ReturnT;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.ResponseBody;\n\nimport javax.annotation.Resource;\nimport java.util.List;\n\n/**\n * job group controller\n * @author xuxueli 2016-10-02 20:52:56\n */\n@Controller\n@RequestMapping(\"/jobgroup\")\npublic class JobGroupController {\n\n\t@Resource\n\tpublic XxlJobInfoDao xxlJobInfoDao;\n\t@Resource\n\tpublic XxlJobGroupDao xxlJobGroupDao;\n\n\t@RequestMapping\n\tpublic String index(Model model) {\n\n\t\t// job group (executor)\n\t\tList<XxlJobGroup> list = xxlJobGroupDao.findAll();\n\n\t\tmodel.addAttribute(\"list\", list);\n\t\treturn \"jobgroup/jobgroup.index\";\n\t}\n\n\t@RequestMapping(\"/save\")\n\t@ResponseBody\n\tpublic ReturnT<String> save(XxlJobGroup xxlJobGroup){\n\n\t\t// valid\n\t\tif (xxlJobGroup.getAppName()==null || StringUtils.isBlank(xxlJobGroup.getAppName())) {\n\t\t\treturn new ReturnT<String>(500, (I18nUtil.getString(\"system_please_input\")+\"AppName\") );\n\t\t}\n\t\tif (xxlJobGroup.getAppName().length()<4 || xxlJobGroup.getAppName().length()>64) {\n\t\t\treturn new ReturnT<String>(500, I18nUtil.getString(\"jobgroup_field_appName_length\") );\n\t\t}\n\t\tif (xxlJobGroup.getTitle()==null || StringUtils.isBlank(xxlJobGroup.getTitle())) {\n\t\t\treturn new ReturnT<String>(500, (I18nUtil.getString(\"system_please_input\") + I18nUtil.getString(\"jobgroup_field_title\")) );\n\t\t}\n\t\tif (xxlJobGroup.getAddressType()!=0) {\n\t\t\tif (StringUtils.isBlank(xxlJobGroup.getAddressList())) {\n\t\t\t\treturn new ReturnT<String>(500, I18nUtil.getString(\"jobgroup_field_addressType_limit\") );\n\t\t\t}\n\t\t\tString[] addresss = xxlJobGroup.getAddressList().split(\",\");\n\t\t\tfor (String item: addresss) {\n\t\t\t\tif (StringUtils.isBlank(item)) {\n\t\t\t\t\treturn new ReturnT<String>(500, I18nUtil.getString(\"jobgroup_field_registryList_unvalid\") );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tint ret = xxlJobGroupDao.save(xxlJobGroup);\n\t\treturn (ret>0)?ReturnT.SUCCESS:ReturnT.FAIL;\n\t}\n\n\t@RequestMapping(\"/update\")\n\t@ResponseBody\n\tpublic ReturnT<String> update(XxlJobGroup xxlJobGroup){\n\t\t// valid\n\t\tif (xxlJobGroup.getAppName()==null || StringUtils.isBlank(xxlJobGroup.getAppName())) {\n\t\t\treturn new ReturnT<String>(500, (I18nUtil.getString(\"system_please_input\")+\"AppName\") );\n\t\t}\n\t\tif (xxlJobGroup.getAppName().length()<4 || xxlJobGroup.getAppName().length()>64) {\n\t\t\treturn new ReturnT<String>(500, I18nUtil.getString(\"jobgroup_field_appName_length\") );\n\t\t}\n\t\tif (xxlJobGroup.getTitle()==null || StringUtils.isBlank(xxlJobGroup.getTitle())) {\n\t\t\treturn new ReturnT<String>(500, (I18nUtil.getString(\"system_please_input\") + I18nUtil.getString(\"jobgroup_field_title\")) );\n\t\t}\n\t\tif (xxlJobGroup.getAddressType()!=0) {\n\t\t\tif (StringUtils.isBlank(xxlJobGroup.getAddressList())) {\n\t\t\t\treturn new ReturnT<String>(500, I18nUtil.getString(\"jobgroup_field_addressType_limit\") );\n\t\t\t}\n\t\t\tString[] addresss = xxlJobGroup.getAddressList().split(\",\");\n\t\t\tfor (String item: addresss) {\n\t\t\t\tif (StringUtils.isBlank(item)) {\n\t\t\t\t\treturn new ReturnT<String>(500, I18nUtil.getString(\"jobgroup_field_registryList_unvalid\") );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tint ret = xxlJobGroupDao.update(xxlJobGroup);\n\t\treturn (ret>0)?ReturnT.SUCCESS:ReturnT.FAIL;\n\t}\n\n\t@RequestMapping(\"/remove\")\n\t@ResponseBody\n\tpublic ReturnT<String> remove(int id){\n\n\t\t// valid\n\t\tint count = xxlJobInfoDao.pageListCount(0, 10, id, null, null);\n\t\tif (count > 0) {\n\t\t\treturn new ReturnT<String>(500, I18nUtil.getString(\"jobgroup_del_limit_0\") );\n\t\t}\n\n\t\tList<XxlJobGroup> allList = xxlJobGroupDao.findAll();\n\t\tif (allList.size() == 1) {\n\t\t\treturn new ReturnT<String>(500, I18nUtil.getString(\"jobgroup_del_limit_1\") );\n\t\t}\n\n\t\tint ret = xxlJobGroupDao.remove(id);\n\t\treturn (ret>0)?ReturnT.SUCCESS:ReturnT.FAIL;\n\t}\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/controller/JobInfoController.java",
    "content": "package com.xxl.job.admin.controller;\n\nimport com.xxl.job.admin.core.enums.ExecutorFailStrategyEnum;\nimport com.xxl.job.admin.core.model.XxlJobGroup;\nimport com.xxl.job.admin.core.model.XxlJobInfo;\nimport com.xxl.job.admin.core.route.ExecutorRouteStrategyEnum;\nimport com.xxl.job.admin.dao.XxlJobGroupDao;\nimport com.xxl.job.admin.service.XxlJobService;\nimport com.xxl.job.core.biz.model.ReturnT;\nimport com.xxl.job.core.enums.ExecutorBlockStrategyEnum;\nimport com.xxl.job.core.glue.GlueTypeEnum;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.ResponseBody;\n\nimport javax.annotation.Resource;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * index controller\n * @author xuxueli 2015-12-19 16:13:16\n */\n@Controller\n@RequestMapping(\"/jobinfo\")\npublic class JobInfoController {\n\n\t@Resource\n\tprivate XxlJobGroupDao xxlJobGroupDao;\n\t@Resource\n\tprivate XxlJobService xxlJobService;\n\t\n\t@RequestMapping\n\tpublic String index(Model model, @RequestParam(required = false, defaultValue = \"-1\") int jobGroup) {\n\n\t\t// 枚举-字典\n\t\tmodel.addAttribute(\"ExecutorRouteStrategyEnum\", ExecutorRouteStrategyEnum.values());\t// 路由策略-列表\n\t\tmodel.addAttribute(\"GlueTypeEnum\", GlueTypeEnum.values());\t\t\t\t\t\t\t\t// Glue类型-字典\n\t\tmodel.addAttribute(\"ExecutorBlockStrategyEnum\", ExecutorBlockStrategyEnum.values());\t// 阻塞处理策略-字典\n\t\tmodel.addAttribute(\"ExecutorFailStrategyEnum\", ExecutorFailStrategyEnum.values());\t\t// 失败处理策略-字典\n\n\t\t// 任务组\n\t\tList<XxlJobGroup> jobGroupList =  xxlJobGroupDao.findAll();\n\t\tmodel.addAttribute(\"JobGroupList\", jobGroupList);\n\t\tmodel.addAttribute(\"jobGroup\", jobGroup);\n\n\t\treturn \"jobinfo/jobinfo.index\";\n\t}\n\t\n\t@RequestMapping(\"/pageList\")\n\t@ResponseBody\n\tpublic Map<String, Object> pageList(@RequestParam(required = false, defaultValue = \"0\") int start,  \n\t\t\t@RequestParam(required = false, defaultValue = \"10\") int length,\n\t\t\tint jobGroup, String jobDesc, String executorHandler, String filterTime) {\n\t\t\n\t\treturn xxlJobService.pageList(start, length, jobGroup, jobDesc, executorHandler, filterTime);\n\t}\n\t\n\t@RequestMapping(\"/add\")\n\t@ResponseBody\n\tpublic ReturnT<String> add(XxlJobInfo jobInfo) {\n\t\treturn xxlJobService.add(jobInfo);\n\t}\n\t\n\t@RequestMapping(\"/update\")\n\t@ResponseBody\n\tpublic ReturnT<String> update(XxlJobInfo jobInfo) {\n\t\treturn xxlJobService.update(jobInfo);\n\t}\n\t\n\t@RequestMapping(\"/remove\")\n\t@ResponseBody\n\tpublic ReturnT<String> remove(int id) {\n\t\treturn xxlJobService.remove(id);\n\t}\n\t\n\t@RequestMapping(\"/pause\")\n\t@ResponseBody\n\tpublic ReturnT<String> pause(int id) {\n\t\treturn xxlJobService.pause(id);\n\t}\n\t\n\t@RequestMapping(\"/resume\")\n\t@ResponseBody\n\tpublic ReturnT<String> resume(int id) {\n\t\treturn xxlJobService.resume(id);\n\t}\n\t\n\t@RequestMapping(\"/trigger\")\n\t@ResponseBody\n\tpublic ReturnT<String> triggerJob(int id) {\n\t\treturn xxlJobService.triggerJob(id);\n\t}\n\t\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/controller/JobLogController.java",
    "content": "package com.xxl.job.admin.controller;\n\nimport com.xxl.job.admin.core.model.XxlJobGroup;\nimport com.xxl.job.admin.core.model.XxlJobInfo;\nimport com.xxl.job.admin.core.model.XxlJobLog;\nimport com.xxl.job.admin.core.schedule.XxlJobDynamicScheduler;\nimport com.xxl.job.admin.core.util.I18nUtil;\nimport com.xxl.job.admin.dao.XxlJobGroupDao;\nimport com.xxl.job.admin.dao.XxlJobInfoDao;\nimport com.xxl.job.admin.dao.XxlJobLogDao;\nimport com.xxl.job.core.biz.ExecutorBiz;\nimport com.xxl.job.core.biz.model.LogResult;\nimport com.xxl.job.core.biz.model.ReturnT;\nimport com.xxl.job.core.glue.GlueTypeEnum;\nimport com.xxl.job.core.rpc.netcom.NetComClientProxy;\nimport org.apache.commons.lang3.StringUtils;\nimport org.apache.commons.lang3.time.DateUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.ResponseBody;\n\nimport javax.annotation.Resource;\nimport java.text.ParseException;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * index controller\n * @author xuxueli 2015-12-19 16:13:16\n */\n@Controller\n@RequestMapping(\"/joblog\")\npublic class JobLogController {\n\tprivate static Logger logger = LoggerFactory.getLogger(JobLogController.class);\n\n\t@Resource\n\tprivate XxlJobGroupDao xxlJobGroupDao;\n\t@Resource\n\tpublic XxlJobInfoDao xxlJobInfoDao;\n\t@Resource\n\tpublic XxlJobLogDao xxlJobLogDao;\n\n\t@RequestMapping\n\tpublic String index(Model model, @RequestParam(required = false, defaultValue = \"0\") Integer jobId) {\n\n\t\t// 执行器列表\n\t\tList<XxlJobGroup> jobGroupList =  xxlJobGroupDao.findAll();\n\t\tmodel.addAttribute(\"JobGroupList\", jobGroupList);\n\t\tmodel.addAttribute(\"GlueTypeEnum\", GlueTypeEnum.values());\n\n\t\t// 任务\n\t\tif (jobId > 0) {\n\t\t\tXxlJobInfo jobInfo = xxlJobInfoDao.loadById(jobId);\n\t\t\tmodel.addAttribute(\"jobInfo\", jobInfo);\n\t\t}\n\n\t\treturn \"joblog/joblog.index\";\n\t}\n\n\t@RequestMapping(\"/getJobsByGroup\")\n\t@ResponseBody\n\tpublic ReturnT<List<XxlJobInfo>> getJobsByGroup(int jobGroup){\n\t\tList<XxlJobInfo> list = xxlJobInfoDao.getJobsByGroup(jobGroup);\n\t\treturn new ReturnT<List<XxlJobInfo>>(list);\n\t}\n\t\n\t@RequestMapping(\"/pageList\")\n\t@ResponseBody\n\tpublic Map<String, Object> pageList(@RequestParam(required = false, defaultValue = \"0\") int start,  \n\t\t\t@RequestParam(required = false, defaultValue = \"10\") int length,\n\t\t\tint jobGroup, int jobId, int logStatus, String filterTime) {\n\t\t\n\t\t// parse param\n\t\tDate triggerTimeStart = null;\n\t\tDate triggerTimeEnd = null;\n\t\tif (StringUtils.isNotBlank(filterTime)) {\n\t\t\tString[] temp = filterTime.split(\" - \");\n\t\t\tif (temp!=null && temp.length == 2) {\n\t\t\t\ttry {\n\t\t\t\t\ttriggerTimeStart = DateUtils.parseDate(temp[0], new String[]{\"yyyy-MM-dd HH:mm:ss\"});\n\t\t\t\t\ttriggerTimeEnd = DateUtils.parseDate(temp[1], new String[]{\"yyyy-MM-dd HH:mm:ss\"});\n\t\t\t\t} catch (ParseException e) {\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\t// page query\n\t\tList<XxlJobLog> list = xxlJobLogDao.pageList(start, length, jobGroup, jobId, triggerTimeStart, triggerTimeEnd, logStatus);\n\t\tint list_count = xxlJobLogDao.pageListCount(start, length, jobGroup, jobId, triggerTimeStart, triggerTimeEnd, logStatus);\n\t\t\n\t\t// package result\n\t\tMap<String, Object> maps = new HashMap<String, Object>();\n\t    maps.put(\"recordsTotal\", list_count);\t\t// 总记录数\n\t    maps.put(\"recordsFiltered\", list_count);\t// 过滤后的总记录数\n\t    maps.put(\"data\", list);  \t\t\t\t\t// 分页列表\n\t\treturn maps;\n\t}\n\n\t@RequestMapping(\"/logDetailPage\")\n\tpublic String logDetailPage(int id, Model model){\n\n\t\t// base check\n\t\tReturnT<String> logStatue = ReturnT.SUCCESS;\n\t\tXxlJobLog jobLog = xxlJobLogDao.load(id);\n\t\tif (jobLog == null) {\n            throw new RuntimeException(I18nUtil.getString(\"joblog_logid_unvalid\"));\n\t\t}\n\n        model.addAttribute(\"triggerCode\", jobLog.getTriggerCode());\n        model.addAttribute(\"handleCode\", jobLog.getHandleCode());\n        model.addAttribute(\"executorAddress\", jobLog.getExecutorAddress());\n        model.addAttribute(\"triggerTime\", jobLog.getTriggerTime().getTime());\n        model.addAttribute(\"logId\", jobLog.getId());\n\t\treturn \"joblog/joblog.detail\";\n\t}\n\n\t@RequestMapping(\"/logDetailCat\")\n\t@ResponseBody\n\tpublic ReturnT<LogResult> logDetailCat(String executorAddress, long triggerTime, int logId, int fromLineNum){\n\t\ttry {\n\t\t\tExecutorBiz executorBiz = XxlJobDynamicScheduler.getExecutorBiz(executorAddress);\n\t\t\tReturnT<LogResult> logResult = executorBiz.log(triggerTime, logId, fromLineNum);\n\n\t\t\t// is end\n            if (logResult.getContent()!=null && logResult.getContent().getFromLineNum() > logResult.getContent().getToLineNum()) {\n                XxlJobLog jobLog = xxlJobLogDao.load(logId);\n                if (jobLog.getHandleCode() > 0) {\n                    logResult.getContent().setEnd(true);\n                }\n            }\n\n\t\t\treturn logResult;\n\t\t} catch (Exception e) {\n\t\t\tlogger.error(e.getMessage(), e);\n\t\t\treturn new ReturnT<LogResult>(ReturnT.FAIL_CODE, e.getMessage());\n\t\t}\n\t}\n\n\t@RequestMapping(\"/logKill\")\n\t@ResponseBody\n\tpublic ReturnT<String> logKill(int id){\n\t\t// base check\n\t\tXxlJobLog log = xxlJobLogDao.load(id);\n\t\tXxlJobInfo jobInfo = xxlJobInfoDao.loadById(log.getJobId());\n\t\tif (jobInfo==null) {\n\t\t\treturn new ReturnT<String>(500, I18nUtil.getString(\"jobinfo_glue_jobid_unvalid\"));\n\t\t}\n\t\tif (ReturnT.SUCCESS_CODE != log.getTriggerCode()) {\n\t\t\treturn new ReturnT<String>(500, I18nUtil.getString(\"joblog_kill_log_limit\"));\n\t\t}\n\n\t\t// request of kill\n\t\tReturnT<String> runResult = null;\n\t\ttry {\n\t\t\tExecutorBiz executorBiz = XxlJobDynamicScheduler.getExecutorBiz(log.getExecutorAddress());\n\t\t\trunResult = executorBiz.kill(jobInfo.getId());\n\t\t} catch (Exception e) {\n\t\t\tlogger.error(e.getMessage(), e);\n\t\t\trunResult = new ReturnT<String>(500, e.getMessage());\n\t\t}\n\n\t\tif (ReturnT.SUCCESS_CODE == runResult.getCode()) {\n\t\t\tlog.setHandleCode(ReturnT.FAIL_CODE);\n\t\t\tlog.setHandleMsg( I18nUtil.getString(\"joblog_kill_log_byman\")+\":\" + (runResult.getMsg()!=null?runResult.getMsg():\"\"));\n\t\t\tlog.setHandleTime(new Date());\n\t\t\txxlJobLogDao.updateHandleInfo(log);\n\t\t\treturn new ReturnT<String>(runResult.getMsg());\n\t\t} else {\n\t\t\treturn new ReturnT<String>(500, runResult.getMsg());\n\t\t}\n\t}\n\n\t@RequestMapping(\"/clearLog\")\n\t@ResponseBody\n\tpublic ReturnT<String> clearLog(int jobGroup, int jobId, int type){\n\n\t\tDate clearBeforeTime = null;\n\t\tint clearBeforeNum = 0;\n\t\tif (type == 1) {\n\t\t\tclearBeforeTime = DateUtils.addMonths(new Date(), -1);\t// 清理一个月之前日志数据\n\t\t} else if (type == 2) {\n\t\t\tclearBeforeTime = DateUtils.addMonths(new Date(), -3);\t// 清理三个月之前日志数据\n\t\t} else if (type == 3) {\n\t\t\tclearBeforeTime = DateUtils.addMonths(new Date(), -6);\t// 清理六个月之前日志数据\n\t\t} else if (type == 4) {\n\t\t\tclearBeforeTime = DateUtils.addYears(new Date(), -1);\t// 清理一年之前日志数据\n\t\t} else if (type == 5) {\n\t\t\tclearBeforeNum = 1000;\t\t// 清理一千条以前日志数据\n\t\t} else if (type == 6) {\n\t\t\tclearBeforeNum = 10000;\t\t// 清理一万条以前日志数据\n\t\t} else if (type == 7) {\n\t\t\tclearBeforeNum = 30000;\t\t// 清理三万条以前日志数据\n\t\t} else if (type == 8) {\n\t\t\tclearBeforeNum = 100000;\t// 清理十万条以前日志数据\n\t\t} else if (type == 9) {\n\t\t\tclearBeforeNum = 0;\t\t\t// 清理所有日志数据\n\t\t} else {\n\t\t\treturn new ReturnT<String>(ReturnT.FAIL_CODE, I18nUtil.getString(\"joblog_clean_type_unvalid\"));\n\t\t}\n\n\t\txxlJobLogDao.clearLog(jobGroup, jobId, clearBeforeTime, clearBeforeNum);\n\t\treturn ReturnT.SUCCESS;\n\t}\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/controller/annotation/PermessionLimit.java",
    "content": "package com.xxl.job.admin.controller.annotation;\n\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * 权限限制\n * @author xuxueli 2015-12-12 18:29:02\n */\n@Target(ElementType.METHOD)\n@Retention(RetentionPolicy.RUNTIME)\npublic @interface PermessionLimit {\n\t\n\t/**\n\t * 登录拦截 (默认拦截)\n\t */\n\tboolean limit() default true;\n\n}"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/controller/interceptor/CookieInterceptor.java",
    "content": "package com.xxl.job.admin.controller.interceptor;\n\nimport com.xxl.job.admin.core.util.FtlUtil;\nimport com.xxl.job.admin.core.util.I18nUtil;\nimport org.apache.commons.lang3.ArrayUtils;\nimport org.springframework.stereotype.Component;\nimport org.springframework.web.servlet.ModelAndView;\nimport org.springframework.web.servlet.handler.HandlerInterceptorAdapter;\n\nimport javax.servlet.http.Cookie;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport java.util.HashMap;\n\n/**\n * push cookies to model as cookieMap\n *\n * @author xuxueli 2015-12-12 18:09:04\n */\n@Component\npublic class CookieInterceptor extends HandlerInterceptorAdapter {\n\n\t@Override\n\tpublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,\n\t\t\tModelAndView modelAndView) throws Exception {\n\n\t\t// cookie\n\t\tif (modelAndView!=null && ArrayUtils.isNotEmpty(request.getCookies())) {\n\t\t\tHashMap<String, Cookie> cookieMap = new HashMap<String, Cookie>();\n\t\t\tfor (Cookie ck : request.getCookies()) {\n\t\t\t\tcookieMap.put(ck.getName(), ck);\n\t\t\t}\n\t\t\tmodelAndView.addObject(\"cookieMap\", cookieMap);\n\t\t}\n\n\t\t// static method\n\t\tif (modelAndView != null) {\n\t\t\tmodelAndView.addObject(\"I18nUtil\", FtlUtil.generateStaticModel(I18nUtil.class.getName()));\n\t\t}\n\t\t\n\t\tsuper.postHandle(request, response, handler, modelAndView);\n\t}\n\t\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/controller/interceptor/PermissionInterceptor.java",
    "content": "package com.xxl.job.admin.controller.interceptor;\n\nimport java.math.BigInteger;\n\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\nimport org.apache.commons.codec.digest.DigestUtils;\nimport org.springframework.stereotype.Component;\nimport org.springframework.web.method.HandlerMethod;\nimport org.springframework.web.servlet.handler.HandlerInterceptorAdapter;\n\nimport com.xxl.job.admin.controller.annotation.PermessionLimit;\nimport com.xxl.job.admin.core.util.CookieUtil;\nimport com.xxl.job.admin.core.util.PropertiesUtil;\n\n/**\n * 权限拦截, 简易版\n *\n * @author xuxueli 2015-12-12 18:09:04\n */\n@Component\npublic class PermissionInterceptor extends HandlerInterceptorAdapter {\n\n\n\tpublic static final String LOGIN_IDENTITY_KEY = \"XXL_JOB_LOGIN_IDENTITY\";\n\tpublic static final String LOGIN_IDENTITY_TOKEN;\n    static {\n        String username = PropertiesUtil.getString(\"xxl.job.login.username\");\n        String password = PropertiesUtil.getString(\"xxl.job.login.password\");\n\n        // login token\n        String tokenTmp = DigestUtils.md5Hex(username + \"_\" + password);\n\t\ttokenTmp = new BigInteger(1, tokenTmp.getBytes()).toString(16);\n\n\t\tLOGIN_IDENTITY_TOKEN = tokenTmp;\n    }\n\n\n\n\tpublic static boolean login(HttpServletResponse response, String username, String password, boolean ifRemember){\n\n    \t// login token\n\t\tString tokenTmp = DigestUtils.md5Hex(username + \"_\" + password);\n\t\ttokenTmp = new BigInteger(1, tokenTmp.getBytes()).toString(16);\n\n\t\tif (!LOGIN_IDENTITY_TOKEN.equals(tokenTmp)){\n\t\t\treturn false;\n\t\t}\n\n\t\t// do login\n\t\tCookieUtil.set(response, LOGIN_IDENTITY_KEY, LOGIN_IDENTITY_TOKEN, ifRemember);\n\t\treturn true;\n\t}\n\tpublic static void logout(HttpServletRequest request, HttpServletResponse response){\n\t\tCookieUtil.remove(request, response, LOGIN_IDENTITY_KEY);\n\t}\n\tpublic static boolean ifLogin(HttpServletRequest request){\n\t\tString indentityInfo = CookieUtil.getValue(request, LOGIN_IDENTITY_KEY);\n\t\tif (indentityInfo==null || !LOGIN_IDENTITY_TOKEN.equals(indentityInfo.trim())) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n\n\n\n\t@Override\n\tpublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {\n\t\t\n\t\tif (!(handler instanceof HandlerMethod)) {\n\t\t\treturn super.preHandle(request, response, handler);\n\t\t}\n\t\t\n\t\tif (!ifLogin(request)) {\n\t\t\tHandlerMethod method = (HandlerMethod)handler;\n\t\t\tPermessionLimit permission = method.getMethodAnnotation(PermessionLimit.class);\n\t\t\tif (permission == null || permission.limit()) {\n\t\t\t\tresponse.sendRedirect(request.getContextPath() + \"/toLogin\");\n\t\t\t\t//request.getRequestDispatcher(\"/toLogin\").forward(request, response);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn super.preHandle(request, response, handler);\n\t}\n\t\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/controller/resolver/WebExceptionResolver.java",
    "content": "package com.xxl.job.admin.controller.resolver;\n\nimport com.xxl.job.core.biz.model.ReturnT;\nimport com.xxl.job.core.util.JacksonUtil;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.stereotype.Component;\nimport org.springframework.web.bind.annotation.ResponseBody;\nimport org.springframework.web.method.HandlerMethod;\nimport org.springframework.web.servlet.HandlerExceptionResolver;\nimport org.springframework.web.servlet.ModelAndView;\n\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport java.io.IOException;\n\n/**\n * common exception resolver\n * @author xuxueli 2016-1-6 19:22:18\n */\n@Component\npublic class WebExceptionResolver implements HandlerExceptionResolver {\n\tprivate static transient Logger logger = LoggerFactory.getLogger(WebExceptionResolver.class);\n\n\t@Override\n\tpublic ModelAndView resolveException(HttpServletRequest request,\n\t\t\tHttpServletResponse response, Object handler, Exception ex) {\n\t\tlogger.error(\"WebExceptionResolver:{}\", ex);\n\n\t\t// if json\n\t\tboolean isJson = false;\n\t\tHandlerMethod method = (HandlerMethod)handler;\n\t\tResponseBody responseBody = method.getMethodAnnotation(ResponseBody.class);\n\t\tif (responseBody != null) {\n\t\t\tisJson = true;\n\t\t}\n\n\t\t// error result\n\t\tReturnT<String> errorResult = new ReturnT<String>(ReturnT.FAIL_CODE, ex.toString().replaceAll(\"\\n\", \"<br/>\"));\n\n\t\t// response\n\t\tModelAndView mv = new ModelAndView();\n\t\tif (isJson) {\n\t\t\ttry {\n\t\t\t\tresponse.setContentType(\"application/json;charset=utf-8\");\n\t\t\t\tresponse.getWriter().print(JacksonUtil.writeValueAsString(errorResult));\n\t\t\t} catch (IOException e) {\n\t\t\t\tlogger.error(e.getMessage(), e);\n\t\t\t}\n\t\t\treturn mv;\n\t\t} else {\n\n\t\t\tmv.addObject(\"exceptionMsg\", errorResult.getMsg());\n\t\t\tmv.setViewName(\"/common/common.exception\");\n\t\t\treturn mv;\n\t\t}\n\t}\n\t\n}"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/conf/XxlJobAdminConfig.java",
    "content": "package com.xxl.job.admin.core.conf;\n\nimport org.springframework.beans.factory.InitializingBean;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.context.annotation.Configuration;\n\n/**\n * xxl-job config\n *\n * @author xuxueli 2017-04-28\n */\n@Configuration\npublic class XxlJobAdminConfig implements InitializingBean{\n    private static XxlJobAdminConfig adminConfig = null;\n    public static XxlJobAdminConfig getAdminConfig() {\n        return adminConfig;\n    }\n\n    @Override\n    public void afterPropertiesSet() throws Exception {\n        adminConfig = this;\n    }\n\n    @Value(\"${xxl.job.mail.host:127.0.0.1}\")\n    private String mailHost;\n\n    @Value(\"${xxl.job.mail.port:9999}\")\n    private String mailPort;\n\n    @Value(\"${xxl.job.mail.ssl:false}\")\n    private boolean mailSSL;\n\n    @Value(\"${xxl.job.mail.username:admin}\")\n    private String mailUsername;\n\n    @Value(\"${xxl.job.mail.password:123456}\")\n    private String mailPassword;\n\n    @Value(\"${xxl.job.mail.sendNick:owen}\")\n    private String mailSendNick;\n\n    @Value(\"${xxl.job.login.username:admin}\")\n    private String loginUsername;\n\n    @Value(\"${xxl.job.login.password:123456}\")\n    private String loginPassword;\n\n    @Value(\"${xxl.job.i18n:}\")\n    private String i18n;\n\n\n    public String getMailHost() {\n        return mailHost;\n    }\n\n    public String getMailPort() {\n        return mailPort;\n    }\n\n    public boolean isMailSSL() {\n        return mailSSL;\n    }\n\n    public String getMailUsername() {\n        return mailUsername;\n    }\n\n    public String getMailPassword() {\n        return mailPassword;\n    }\n\n    public String getMailSendNick() {\n        return mailSendNick;\n    }\n\n    public String getLoginUsername() {\n        return loginUsername;\n    }\n\n    public String getLoginPassword() {\n        return loginPassword;\n    }\n\n    public String getI18n() {\n        return i18n;\n    }\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/enums/ExecutorFailStrategyEnum.java",
    "content": "package com.xxl.job.admin.core.enums;\n\nimport com.xxl.job.admin.core.util.I18nUtil;\n\n/**\n * Created by xuxueli on 17/5/9.\n */\npublic enum ExecutorFailStrategyEnum {\n\n    FAIL_ALARM(I18nUtil.getString(\"jobconf_fail_alarm\")),\n\n    FAIL_RETRY(I18nUtil.getString(\"jobconf_fail_retry\"));\n\n    private final String title;\n    private ExecutorFailStrategyEnum(String title) {\n        this.title = title;\n    }\n\n    public String getTitle() {\n        return title;\n    }\n\n    public static ExecutorFailStrategyEnum match(String name, ExecutorFailStrategyEnum defaultItem) {\n        if (name != null) {\n            for (ExecutorFailStrategyEnum item: ExecutorFailStrategyEnum.values()) {\n                if (item.name().equals(name)) {\n                    return item;\n                }\n            }\n        }\n        return defaultItem;\n    }\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/jobbean/RemoteHttpJobBean.java",
    "content": "package com.xxl.job.admin.core.jobbean;\n\nimport com.xxl.job.admin.core.trigger.XxlJobTrigger;\nimport org.quartz.JobExecutionContext;\nimport org.quartz.JobExecutionException;\nimport org.quartz.JobKey;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.scheduling.quartz.QuartzJobBean;\n\n/**\n * http job bean\n * “@DisallowConcurrentExecution” diable concurrent, thread size can not be only one, better given more\n * @author xuxueli 2015-12-17 18:20:34\n */\n//@DisallowConcurrentExecution\npublic class RemoteHttpJobBean extends QuartzJobBean {\n\tprivate static Logger logger = LoggerFactory.getLogger(RemoteHttpJobBean.class);\n\n\t@Override\n\tprotected void executeInternal(JobExecutionContext context)\n\t\t\tthrows JobExecutionException {\n\n\t\t// load jobId\n\t\tJobKey jobKey = context.getTrigger().getJobKey();\n\t\tInteger jobId = Integer.valueOf(jobKey.getName());\n\n\t\t// trigger\n\t\tXxlJobTrigger.trigger(jobId);\n\t}\n\n}"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/model/XxlJobGroup.java",
    "content": "package com.xxl.job.admin.core.model;\n\nimport org.apache.commons.lang3.StringUtils;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\n\n/**\n * Created by xuxueli on 16/9/30.\n */\npublic class XxlJobGroup {\n\n    private int id;\n    private String appName;\n    private String title;\n    private int order;\n    private int addressType;    // 执行器地址类型：0=自动注册、1=手动录入\n    private String addressList;    // 执行器地址列表，多地址逗号分隔(手动录入)\n\n    // registry list\n    private List<String> registryList;  // 执行器地址列表(系统注册)\n    public List<String> getRegistryList() {\n        if (StringUtils.isNotBlank(addressList)) {\n            registryList = new ArrayList<String>(Arrays.asList(addressList.split(\",\")));\n        }\n        return registryList;\n    }\n\n    public int getId() {\n        return id;\n    }\n\n    public void setId(int id) {\n        this.id = id;\n    }\n\n    public String getAppName() {\n        return appName;\n    }\n\n    public void setAppName(String appName) {\n        this.appName = appName;\n    }\n\n    public String getTitle() {\n        return title;\n    }\n\n    public void setTitle(String title) {\n        this.title = title;\n    }\n\n    public int getOrder() {\n        return order;\n    }\n\n    public void setOrder(int order) {\n        this.order = order;\n    }\n\n    public int getAddressType() {\n        return addressType;\n    }\n\n    public void setAddressType(int addressType) {\n        this.addressType = addressType;\n    }\n\n    public String getAddressList() {\n        return addressList;\n    }\n\n    public void setAddressList(String addressList) {\n        this.addressList = addressList;\n    }\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/model/XxlJobInfo.java",
    "content": "package com.xxl.job.admin.core.model;\n\nimport java.util.Date;\n\n/**\n * xxl-job info\n * @author xuxueli  2016-1-12 18:25:49\n */\npublic class XxlJobInfo {\n\t\n\tprivate int id;\t\t\t\t// 主键ID\t    (JobKey.name)\n\t\n\tprivate int jobGroup;\t\t// 执行器主键ID\t(JobKey.group)\n\tprivate String jobCron;\t\t// 任务执行CRON表达式 【base on quartz】\n\tprivate String jobDesc;\n\t\n\tprivate Date addTime;\n\tprivate Date updateTime;\n\t\n\tprivate String author;\t\t// 负责人\n\tprivate String alarmEmail;\t// 报警邮件\n\n\tprivate String executorRouteStrategy;\t// 执行器路由策略\n\tprivate String executorHandler;\t\t    // 执行器，任务Handler名称\n\tprivate String executorParam;\t\t    // 执行器，任务参数\n\tprivate String executorBlockStrategy;\t// 阻塞处理策略\n\tprivate String executorFailStrategy;\t// 失败处理策略\n\t\n\tprivate String glueType;\t\t// GLUE类型\t#com.xxl.job.core.glue.GlueTypeEnum\n\tprivate String glueSource;\t\t// GLUE源代码\n\tprivate String glueRemark;\t\t// GLUE备注\n\tprivate Date glueUpdatetime;\t// GLUE更新时间\n\n\tprivate String childJobId;\t\t// 子任务ID，多个逗号分隔\n\t\n\t// copy from quartz\n\tprivate String jobStatus;\t\t// 任务状态 【base on quartz】\n\n\tpublic int getId() {\n\t\treturn id;\n\t}\n\n\tpublic void setId(int id) {\n\t\tthis.id = id;\n\t}\n\n\tpublic int getJobGroup() {\n\t\treturn jobGroup;\n\t}\n\n\tpublic void setJobGroup(int jobGroup) {\n\t\tthis.jobGroup = jobGroup;\n\t}\n\n\tpublic String getJobCron() {\n\t\treturn jobCron;\n\t}\n\n\tpublic void setJobCron(String jobCron) {\n\t\tthis.jobCron = jobCron;\n\t}\n\n\tpublic String getJobDesc() {\n\t\treturn jobDesc;\n\t}\n\n\tpublic void setJobDesc(String jobDesc) {\n\t\tthis.jobDesc = jobDesc;\n\t}\n\n\tpublic Date getAddTime() {\n\t\treturn addTime;\n\t}\n\n\tpublic void setAddTime(Date addTime) {\n\t\tthis.addTime = addTime;\n\t}\n\n\tpublic Date getUpdateTime() {\n\t\treturn updateTime;\n\t}\n\n\tpublic void setUpdateTime(Date updateTime) {\n\t\tthis.updateTime = updateTime;\n\t}\n\n\tpublic String getAuthor() {\n\t\treturn author;\n\t}\n\n\tpublic void setAuthor(String author) {\n\t\tthis.author = author;\n\t}\n\n\tpublic String getAlarmEmail() {\n\t\treturn alarmEmail;\n\t}\n\n\tpublic void setAlarmEmail(String alarmEmail) {\n\t\tthis.alarmEmail = alarmEmail;\n\t}\n\n    public String getExecutorRouteStrategy() {\n        return executorRouteStrategy;\n    }\n\n    public void setExecutorRouteStrategy(String executorRouteStrategy) {\n        this.executorRouteStrategy = executorRouteStrategy;\n    }\n\n    public String getExecutorHandler() {\n\t\treturn executorHandler;\n\t}\n\n\tpublic void setExecutorHandler(String executorHandler) {\n\t\tthis.executorHandler = executorHandler;\n\t}\n\n\tpublic String getExecutorParam() {\n\t\treturn executorParam;\n\t}\n\n\tpublic void setExecutorParam(String executorParam) {\n\t\tthis.executorParam = executorParam;\n\t}\n\n\tpublic String getExecutorBlockStrategy() {\n\t\treturn executorBlockStrategy;\n\t}\n\n\tpublic void setExecutorBlockStrategy(String executorBlockStrategy) {\n\t\tthis.executorBlockStrategy = executorBlockStrategy;\n\t}\n\n\tpublic String getExecutorFailStrategy() {\n\t\treturn executorFailStrategy;\n\t}\n\n\tpublic void setExecutorFailStrategy(String executorFailStrategy) {\n\t\tthis.executorFailStrategy = executorFailStrategy;\n\t}\n\n\tpublic String getGlueType() {\n\t\treturn glueType;\n\t}\n\n\tpublic void setGlueType(String glueType) {\n\t\tthis.glueType = glueType;\n\t}\n\n\tpublic String getGlueSource() {\n\t\treturn glueSource;\n\t}\n\n\tpublic void setGlueSource(String glueSource) {\n\t\tthis.glueSource = glueSource;\n\t}\n\n\tpublic String getGlueRemark() {\n\t\treturn glueRemark;\n\t}\n\n\tpublic void setGlueRemark(String glueRemark) {\n\t\tthis.glueRemark = glueRemark;\n\t}\n\n\tpublic Date getGlueUpdatetime() {\n\t\treturn glueUpdatetime;\n\t}\n\n\tpublic void setGlueUpdatetime(Date glueUpdatetime) {\n\t\tthis.glueUpdatetime = glueUpdatetime;\n\t}\n\n\tpublic String getChildJobId() {\n\t\treturn childJobId;\n\t}\n\n\tpublic void setChildJobId(String childJobId) {\n\t\tthis.childJobId = childJobId;\n\t}\n\n\tpublic String getJobStatus() {\n\t\treturn jobStatus;\n\t}\n\n\tpublic void setJobStatus(String jobStatus) {\n\t\tthis.jobStatus = jobStatus;\n\t}\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/model/XxlJobLog.java",
    "content": "package com.xxl.job.admin.core.model;\n\nimport java.util.Date;\n\n/**\n * xxl-job log, used to track trigger process\n * @author xuxueli  2015-12-19 23:19:09\n */\npublic class XxlJobLog {\n\t\n\tprivate int id;\n\t\n\t// job info\n\tprivate int jobGroup;\n\tprivate int jobId;\n\n\t// glueType\n\tprivate String glueType;\n\n\t// execute info\n\tprivate String executorAddress;\n\tprivate String executorHandler;\n\tprivate String executorParam;\n\t\n\t// trigger info\n\tprivate Date triggerTime;\n\tprivate int triggerCode;\n\tprivate String triggerMsg;\n\t\n\t// handle info\n\tprivate Date handleTime;\n\tprivate int handleCode;\n\tprivate String handleMsg;\n\n\tpublic int getId() {\n\t\treturn id;\n\t}\n\n\tpublic void setId(int id) {\n\t\tthis.id = id;\n\t}\n\n\tpublic int getJobGroup() {\n\t\treturn jobGroup;\n\t}\n\n\tpublic void setJobGroup(int jobGroup) {\n\t\tthis.jobGroup = jobGroup;\n\t}\n\n\tpublic int getJobId() {\n\t\treturn jobId;\n\t}\n\n\tpublic void setJobId(int jobId) {\n\t\tthis.jobId = jobId;\n\t}\n\n\tpublic String getGlueType() {\n\t\treturn glueType;\n\t}\n\n\tpublic void setGlueType(String glueType) {\n\t\tthis.glueType = glueType;\n\t}\n\n\tpublic String getExecutorAddress() {\n\t\treturn executorAddress;\n\t}\n\n\tpublic void setExecutorAddress(String executorAddress) {\n\t\tthis.executorAddress = executorAddress;\n\t}\n\n\tpublic String getExecutorHandler() {\n\t\treturn executorHandler;\n\t}\n\n\tpublic void setExecutorHandler(String executorHandler) {\n\t\tthis.executorHandler = executorHandler;\n\t}\n\n\tpublic String getExecutorParam() {\n\t\treturn executorParam;\n\t}\n\n\tpublic void setExecutorParam(String executorParam) {\n\t\tthis.executorParam = executorParam;\n\t}\n\n\tpublic Date getTriggerTime() {\n\t\treturn triggerTime;\n\t}\n\n\tpublic void setTriggerTime(Date triggerTime) {\n\t\tthis.triggerTime = triggerTime;\n\t}\n\n\tpublic int getTriggerCode() {\n\t\treturn triggerCode;\n\t}\n\n\tpublic void setTriggerCode(int triggerCode) {\n\t\tthis.triggerCode = triggerCode;\n\t}\n\n\tpublic String getTriggerMsg() {\n\t\treturn triggerMsg;\n\t}\n\n\tpublic void setTriggerMsg(String triggerMsg) {\n\t\t// plugin\n\t\tif (triggerMsg!=null && triggerMsg.length()>2000) {\n\t\t\ttriggerMsg = triggerMsg.substring(0, 2000);\n\t\t}\n\t\tthis.triggerMsg = triggerMsg;\n\t}\n\n\tpublic Date getHandleTime() {\n\t\treturn handleTime;\n\t}\n\n\tpublic void setHandleTime(Date handleTime) {\n\t\tthis.handleTime = handleTime;\n\t}\n\n\tpublic int getHandleCode() {\n\t\treturn handleCode;\n\t}\n\n\tpublic void setHandleCode(int handleCode) {\n\t\tthis.handleCode = handleCode;\n\t}\n\n\tpublic String getHandleMsg() {\n\t\treturn handleMsg;\n\t}\n\n\tpublic void setHandleMsg(String handleMsg) {\n\t\t// plugin\n\t\tif (handleMsg!=null && handleMsg.length()>2000) {\n\t\t\thandleMsg = handleMsg.substring(0, 2000);\n\t\t}\n\t\tthis.handleMsg = handleMsg;\n\t}\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/model/XxlJobLogGlue.java",
    "content": "package com.xxl.job.admin.core.model;\n\n/**\n * xxl-job log for glue, used to track job code process\n * @author xuxueli 2016-5-19 17:57:46\n */\npublic class XxlJobLogGlue {\n\t\n\tprivate int id;\n\tprivate int jobId;\t\t\t\t// 任务主键ID\n\tprivate String glueType;\t\t// GLUE类型\t#com.xxl.job.core.glue.GlueTypeEnum\n\tprivate String glueSource;\n\tprivate String glueRemark;\n\tprivate String addTime;\n\tprivate String updateTime;\n\n\tpublic int getId() {\n\t\treturn id;\n\t}\n\n\tpublic void setId(int id) {\n\t\tthis.id = id;\n\t}\n\n\tpublic int getJobId() {\n\t\treturn jobId;\n\t}\n\n\tpublic void setJobId(int jobId) {\n\t\tthis.jobId = jobId;\n\t}\n\n\tpublic String getGlueType() {\n\t\treturn glueType;\n\t}\n\n\tpublic void setGlueType(String glueType) {\n\t\tthis.glueType = glueType;\n\t}\n\n\tpublic String getGlueSource() {\n\t\treturn glueSource;\n\t}\n\n\tpublic void setGlueSource(String glueSource) {\n\t\tthis.glueSource = glueSource;\n\t}\n\n\tpublic String getGlueRemark() {\n\t\treturn glueRemark;\n\t}\n\n\tpublic void setGlueRemark(String glueRemark) {\n\t\tthis.glueRemark = glueRemark;\n\t}\n\n\tpublic String getAddTime() {\n\t\treturn addTime;\n\t}\n\n\tpublic void setAddTime(String addTime) {\n\t\tthis.addTime = addTime;\n\t}\n\n\tpublic String getUpdateTime() {\n\t\treturn updateTime;\n\t}\n\n\tpublic void setUpdateTime(String updateTime) {\n\t\tthis.updateTime = updateTime;\n\t}\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/model/XxlJobRegistry.java",
    "content": "package com.xxl.job.admin.core.model;\n\nimport java.util.Date;\n\n/**\n * Created by xuxueli on 16/9/30.\n */\npublic class XxlJobRegistry {\n\n    private int id;\n    private String registryGroup;\n    private String registryKey;\n    private String registryValue;\n    private Date updateTime;\n\n    public int getId() {\n        return id;\n    }\n\n    public void setId(int id) {\n        this.id = id;\n    }\n\n    public String getRegistryGroup() {\n        return registryGroup;\n    }\n\n    public void setRegistryGroup(String registryGroup) {\n        this.registryGroup = registryGroup;\n    }\n\n    public String getRegistryKey() {\n        return registryKey;\n    }\n\n    public void setRegistryKey(String registryKey) {\n        this.registryKey = registryKey;\n    }\n\n    public String getRegistryValue() {\n        return registryValue;\n    }\n\n    public void setRegistryValue(String registryValue) {\n        this.registryValue = registryValue;\n    }\n\n    public Date getUpdateTime() {\n        return updateTime;\n    }\n\n    public void setUpdateTime(Date updateTime) {\n        this.updateTime = updateTime;\n    }\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/route/ExecutorRouteStrategyEnum.java",
    "content": "package com.xxl.job.admin.core.route;\n\nimport com.xxl.job.admin.core.route.strategy.*;\nimport com.xxl.job.admin.core.util.I18nUtil;\n\n/**\n * Created by xuxueli on 17/3/10.\n */\npublic enum ExecutorRouteStrategyEnum {\n\n    FIRST(I18nUtil.getString(\"jobconf_route_first\"), new ExecutorRouteFirst()),\n    LAST(I18nUtil.getString(\"jobconf_route_last\"), new ExecutorRouteLast()),\n    ROUND(I18nUtil.getString(\"jobconf_route_round\"), new ExecutorRouteRound()),\n    RANDOM(I18nUtil.getString(\"jobconf_route_random\"), new ExecutorRouteRandom()),\n    CONSISTENT_HASH(I18nUtil.getString(\"jobconf_route_consistenthash\"), new ExecutorRouteConsistentHash()),\n    LEAST_FREQUENTLY_USED(I18nUtil.getString(\"jobconf_route_lfu\"), new ExecutorRouteLFU()),\n    LEAST_RECENTLY_USED(I18nUtil.getString(\"jobconf_route_lru\"), new ExecutorRouteLRU()),\n    FAILOVER(I18nUtil.getString(\"jobconf_route_failover\"), new ExecutorRouteFailover()),\n    BUSYOVER(I18nUtil.getString(\"jobconf_route_busyover\"), new ExecutorRouteBusyover()),\n    SHARDING_BROADCAST(I18nUtil.getString(\"jobconf_route_shard\"), null);\n\n    ExecutorRouteStrategyEnum(String title, ExecutorRouter router) {\n        this.title = title;\n        this.router = router;\n    }\n\n    private String title;\n    private ExecutorRouter router;\n\n    public String getTitle() {\n        return title;\n    }\n    public ExecutorRouter getRouter() {\n        return router;\n    }\n\n    public static ExecutorRouteStrategyEnum match(String name, ExecutorRouteStrategyEnum defaultItem){\n        if (name != null) {\n            for (ExecutorRouteStrategyEnum item: ExecutorRouteStrategyEnum.values()) {\n                if (item.name().equals(name)) {\n                    return item;\n                }\n            }\n        }\n        return defaultItem;\n    }\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/route/ExecutorRouter.java",
    "content": "package com.xxl.job.admin.core.route;\n\nimport com.xxl.job.core.biz.model.ReturnT;\nimport com.xxl.job.core.biz.model.TriggerParam;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.ArrayList;\n\n/**\n * Created by xuxueli on 17/3/10.\n */\npublic abstract class ExecutorRouter {\n    protected static Logger logger = LoggerFactory.getLogger(ExecutorRouter.class);\n\n    /**\n     * route run executor\n     *\n     * @param triggerParam\n     * @param addressList\n     * @return  ReturnT.content: final address\n     */\n    public abstract ReturnT<String> routeRun(TriggerParam triggerParam, ArrayList<String> addressList);\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/route/strategy/ExecutorRouteBusyover.java",
    "content": "package com.xxl.job.admin.core.route.strategy;\n\nimport com.xxl.job.admin.core.route.ExecutorRouter;\nimport com.xxl.job.admin.core.schedule.XxlJobDynamicScheduler;\nimport com.xxl.job.admin.core.trigger.XxlJobTrigger;\nimport com.xxl.job.admin.core.util.I18nUtil;\nimport com.xxl.job.core.biz.ExecutorBiz;\nimport com.xxl.job.core.biz.model.ReturnT;\nimport com.xxl.job.core.biz.model.TriggerParam;\n\nimport java.util.ArrayList;\n\n/**\n * Created by xuxueli on 17/3/10.\n */\npublic class ExecutorRouteBusyover extends ExecutorRouter {\n\n    public String route(int jobId, ArrayList<String> addressList) {\n        return addressList.get(0);\n    }\n\n    @Override\n    public ReturnT<String> routeRun(TriggerParam triggerParam, ArrayList<String> addressList) {\n\n        StringBuffer idleBeatResultSB = new StringBuffer();\n        for (String address : addressList) {\n            // beat\n            ReturnT<String> idleBeatResult = null;\n            try {\n                ExecutorBiz executorBiz = XxlJobDynamicScheduler.getExecutorBiz(address);\n                idleBeatResult = executorBiz.idleBeat(triggerParam.getJobId());\n            } catch (Exception e) {\n                logger.error(e.getMessage(), e);\n                idleBeatResult = new ReturnT<String>(ReturnT.FAIL_CODE, \"\"+e );\n            }\n            idleBeatResultSB.append( (idleBeatResultSB.length()>0)?\"<br><br>\":\"\")\n                    .append(I18nUtil.getString(\"jobconf_idleBeat\") + \"：\")\n                    .append(\"<br>address：\").append(address)\n                    .append(\"<br>code：\").append(idleBeatResult.getCode())\n                    .append(\"<br>msg：\").append(idleBeatResult.getMsg());\n\n            // beat success\n            if (idleBeatResult.getCode() == ReturnT.SUCCESS_CODE) {\n\n                ReturnT<String> runResult = XxlJobTrigger.runExecutor(triggerParam, address);\n                idleBeatResultSB.append(\"<br><br>\").append(runResult.getMsg());\n\n                // result\n                runResult.setMsg(idleBeatResultSB.toString());\n                runResult.setContent(address);\n                return runResult;\n            }\n        }\n\n        return new ReturnT<String>(ReturnT.FAIL_CODE, idleBeatResultSB.toString());\n    }\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/route/strategy/ExecutorRouteConsistentHash.java",
    "content": "package com.xxl.job.admin.core.route.strategy;\n\nimport com.xxl.job.admin.core.route.ExecutorRouter;\nimport com.xxl.job.admin.core.trigger.XxlJobTrigger;\nimport com.xxl.job.core.biz.model.ReturnT;\nimport com.xxl.job.core.biz.model.TriggerParam;\n\nimport java.io.UnsupportedEncodingException;\nimport java.security.MessageDigest;\nimport java.security.NoSuchAlgorithmException;\nimport java.util.ArrayList;\nimport java.util.SortedMap;\nimport java.util.TreeMap;\n\n/**\n * 分组下机器地址相同，不同JOB均匀散列在不同机器上，保证分组下机器分配JOB平均；且每个JOB固定调度其中一台机器；\n *      a、virtual node：解决不均衡问题\n *      b、hash method replace hashCode：String的hashCode可能重复，需要进一步扩大hashCode的取值范围\n * Created by xuxueli on 17/3/10.\n */\npublic class ExecutorRouteConsistentHash extends ExecutorRouter {\n\n    private static int VIRTUAL_NODE_NUM = 5;\n\n    /**\n     * get hash code on 2^32 ring (md5散列的方式计算hash值)\n     * @param key\n     * @return\n     */\n    private static long hash(String key) {\n\n        // md5 byte\n        MessageDigest md5;\n        try {\n            md5 = MessageDigest.getInstance(\"MD5\");\n        } catch (NoSuchAlgorithmException e) {\n            throw new RuntimeException(\"MD5 not supported\", e);\n        }\n        md5.reset();\n        byte[] keyBytes = null;\n        try {\n            keyBytes = key.getBytes(\"UTF-8\");\n        } catch (UnsupportedEncodingException e) {\n            throw new RuntimeException(\"Unknown string :\" + key, e);\n        }\n\n        md5.update(keyBytes);\n        byte[] digest = md5.digest();\n\n        // hash code, Truncate to 32-bits\n        long hashCode = ((long) (digest[3] & 0xFF) << 24)\n                | ((long) (digest[2] & 0xFF) << 16)\n                | ((long) (digest[1] & 0xFF) << 8)\n                | (digest[0] & 0xFF);\n\n        long truncateHashCode = hashCode & 0xffffffffL;\n        return truncateHashCode;\n    }\n\n    public String route(int jobId, ArrayList<String> addressList) {\n\n        // ------A1------A2-------A3------\n        // -----------J1------------------\n        TreeMap<Long, String> addressRing = new TreeMap<Long, String>();\n        for (String address: addressList) {\n            for (int i = 0; i < VIRTUAL_NODE_NUM; i++) {\n                long addressHash = hash(\"SHARD-\" + address + \"-NODE-\" + i);\n                addressRing.put(addressHash, address);\n            }\n        }\n\n        long jobHash = hash(String.valueOf(jobId));\n        SortedMap<Long, String> lastRing = addressRing.tailMap(jobHash);\n        if (!lastRing.isEmpty()) {\n            return lastRing.get(lastRing.firstKey());\n        }\n        return addressRing.firstEntry().getValue();\n    }\n\n    @Override\n    public ReturnT<String> routeRun(TriggerParam triggerParam, ArrayList<String> addressList) {\n        // address\n        String address = route(triggerParam.getJobId(), addressList);\n\n        // run executor\n        ReturnT<String> runResult = XxlJobTrigger.runExecutor(triggerParam, address);\n        runResult.setContent(address);\n        return runResult;\n    }\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/route/strategy/ExecutorRouteFailover.java",
    "content": "package com.xxl.job.admin.core.route.strategy;\n\nimport com.xxl.job.admin.core.route.ExecutorRouter;\nimport com.xxl.job.admin.core.schedule.XxlJobDynamicScheduler;\nimport com.xxl.job.admin.core.trigger.XxlJobTrigger;\nimport com.xxl.job.admin.core.util.I18nUtil;\nimport com.xxl.job.core.biz.ExecutorBiz;\nimport com.xxl.job.core.biz.model.ReturnT;\nimport com.xxl.job.core.biz.model.TriggerParam;\n\nimport java.util.ArrayList;\n\n/**\n * Created by xuxueli on 17/3/10.\n */\npublic class ExecutorRouteFailover extends ExecutorRouter {\n\n    public String route(int jobId, ArrayList<String> addressList) {\n        return addressList.get(0);\n    }\n\n    @Override\n    public ReturnT<String> routeRun(TriggerParam triggerParam, ArrayList<String> addressList) {\n\n        StringBuffer beatResultSB = new StringBuffer();\n        for (String address : addressList) {\n            // beat\n            ReturnT<String> beatResult = null;\n            try {\n                ExecutorBiz executorBiz = XxlJobDynamicScheduler.getExecutorBiz(address);\n                beatResult = executorBiz.beat();\n            } catch (Exception e) {\n                logger.error(e.getMessage(), e);\n                beatResult = new ReturnT<String>(ReturnT.FAIL_CODE, \"\"+e );\n            }\n            beatResultSB.append( (beatResultSB.length()>0)?\"<br><br>\":\"\")\n                    .append(I18nUtil.getString(\"jobconf_beat\") + \"：\")\n                    .append(\"<br>address：\").append(address)\n                    .append(\"<br>code：\").append(beatResult.getCode())\n                    .append(\"<br>msg：\").append(beatResult.getMsg());\n\n            // beat success\n            if (beatResult.getCode() == ReturnT.SUCCESS_CODE) {\n\n                ReturnT<String> runResult = XxlJobTrigger.runExecutor(triggerParam, address);\n                beatResultSB.append(\"<br><br>\").append(runResult.getMsg());\n\n                // result\n                runResult.setMsg(beatResultSB.toString());\n                runResult.setContent(address);\n                return runResult;\n            }\n        }\n        return new ReturnT<String>(ReturnT.FAIL_CODE, beatResultSB.toString());\n\n    }\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/route/strategy/ExecutorRouteFirst.java",
    "content": "package com.xxl.job.admin.core.route.strategy;\n\nimport com.xxl.job.admin.core.route.ExecutorRouter;\nimport com.xxl.job.admin.core.trigger.XxlJobTrigger;\nimport com.xxl.job.core.biz.model.ReturnT;\nimport com.xxl.job.core.biz.model.TriggerParam;\n\nimport java.util.ArrayList;\n\n/**\n * Created by xuxueli on 17/3/10.\n */\npublic class ExecutorRouteFirst extends ExecutorRouter {\n\n    public String route(int jobId, ArrayList<String> addressList) {\n        return addressList.get(0);\n    }\n\n    @Override\n    public ReturnT<String> routeRun(TriggerParam triggerParam, ArrayList<String> addressList) {\n\n        // address\n        String address = route(triggerParam.getJobId(), addressList);\n\n        // run executor\n        ReturnT<String> runResult = XxlJobTrigger.runExecutor(triggerParam, address);\n        runResult.setContent(address);\n        return runResult;\n    }\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/route/strategy/ExecutorRouteLFU.java",
    "content": "package com.xxl.job.admin.core.route.strategy;\n\nimport com.xxl.job.admin.core.route.ExecutorRouter;\nimport com.xxl.job.admin.core.trigger.XxlJobTrigger;\nimport com.xxl.job.core.biz.model.ReturnT;\nimport com.xxl.job.core.biz.model.TriggerParam;\n\nimport java.util.*;\nimport java.util.concurrent.ConcurrentHashMap;\n\n/**\n * 单个JOB对应的每个执行器，使用频率最低的优先被选举\n *      a(*)、LFU(Least Frequently Used)：最不经常使用，频率/次数\n *      b、LRU(Least Recently Used)：最近最久未使用，时间\n *\n * Created by xuxueli on 17/3/10.\n */\npublic class ExecutorRouteLFU extends ExecutorRouter {\n\n    private static ConcurrentHashMap<Integer, HashMap<String, Integer>> jobLfuMap = new ConcurrentHashMap<Integer, HashMap<String, Integer>>();\n    private static long CACHE_VALID_TIME = 0;\n\n    public String route(int jobId, ArrayList<String> addressList) {\n\n        // cache clear\n        if (System.currentTimeMillis() > CACHE_VALID_TIME) {\n            jobLfuMap.clear();\n            CACHE_VALID_TIME = System.currentTimeMillis() + 1000*60*60*24;\n        }\n\n        // lfu item init\n        HashMap<String, Integer> lfuItemMap = jobLfuMap.get(jobId);     // Key排序可以用TreeMap+构造入参Compare；Value排序暂时只能通过ArrayList；\n        if (lfuItemMap == null) {\n            lfuItemMap = new HashMap<String, Integer>();\n            jobLfuMap.put(jobId, lfuItemMap);\n        }\n        for (String address: addressList) {\n            if (!lfuItemMap.containsKey(address) || lfuItemMap.get(address) >1000000 ) {\n                lfuItemMap.put(address, new Random().nextInt(addressList.size()));  // 初始化时主动Random一次，缓解首次压力\n            }\n        }\n\n        // load least userd count address\n        List<Map.Entry<String, Integer>> lfuItemList = new ArrayList<Map.Entry<String, Integer>>(lfuItemMap.entrySet());\n        Collections.sort(lfuItemList, new Comparator<Map.Entry<String, Integer>>() {\n            @Override\n            public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {\n                return o1.getValue().compareTo(o2.getValue());\n            }\n        });\n\n        Map.Entry<String, Integer> addressItem = lfuItemList.get(0);\n        String minAddress = addressItem.getKey();\n        addressItem.setValue(addressItem.getValue() + 1);\n\n        return addressItem.getKey();\n    }\n\n    @Override\n    public ReturnT<String> routeRun(TriggerParam triggerParam, ArrayList<String> addressList) {\n\n        // address\n        String address = route(triggerParam.getJobId(), addressList);\n\n        // run executor\n        ReturnT<String> runResult = XxlJobTrigger.runExecutor(triggerParam, address);\n        runResult.setContent(address);\n        return runResult;\n    }\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/route/strategy/ExecutorRouteLRU.java",
    "content": "package com.xxl.job.admin.core.route.strategy;\n\nimport com.xxl.job.admin.core.route.ExecutorRouter;\nimport com.xxl.job.admin.core.trigger.XxlJobTrigger;\nimport com.xxl.job.core.biz.model.ReturnT;\nimport com.xxl.job.core.biz.model.TriggerParam;\n\nimport java.util.ArrayList;\nimport java.util.LinkedHashMap;\nimport java.util.concurrent.ConcurrentHashMap;\n\n/**\n * 单个JOB对应的每个执行器，最久为使用的优先被选举\n *      a、LFU(Least Frequently Used)：最不经常使用，频率/次数\n *      b(*)、LRU(Least Recently Used)：最近最久未使用，时间\n *\n * Created by xuxueli on 17/3/10.\n */\npublic class ExecutorRouteLRU extends ExecutorRouter {\n\n    private static ConcurrentHashMap<Integer, LinkedHashMap<String, String>> jobLRUMap = new ConcurrentHashMap<Integer, LinkedHashMap<String, String>>();\n    private static long CACHE_VALID_TIME = 0;\n\n    public String route(int jobId, ArrayList<String> addressList) {\n\n        // cache clear\n        if (System.currentTimeMillis() > CACHE_VALID_TIME) {\n            jobLRUMap.clear();\n            CACHE_VALID_TIME = System.currentTimeMillis() + 1000*60*60*24;\n        }\n\n        // init lru\n        LinkedHashMap<String, String> lruItem = jobLRUMap.get(jobId);\n        if (lruItem == null) {\n            /**\n             * LinkedHashMap\n             *      a、accessOrder：ture=访问顺序排序（get/put时排序）；false=插入顺序排期；\n             *      b、removeEldestEntry：新增元素时将会调用，返回true时会删除最老元素；可封装LinkedHashMap并重写该方法，比如定义最大容量，超出是返回true即可实现固定长度的LRU算法；\n             */\n            lruItem = new LinkedHashMap<>(16, 0.75f, true);\n            jobLRUMap.put(jobId, lruItem);\n        }\n\n        // put\n        for (String address: addressList) {\n            if (!lruItem.containsKey(address)) {\n                lruItem.put(address, address);\n            }\n        }\n\n        // load\n        String eldestKey = lruItem.entrySet().iterator().next().getKey();\n        String eldestValue = lruItem.get(eldestKey);\n        return eldestValue;\n    }\n\n\n    @Override\n    public ReturnT<String> routeRun(TriggerParam triggerParam, ArrayList<String> addressList) {\n\n        // address\n        String address = route(triggerParam.getJobId(), addressList);\n\n        // run executor\n        ReturnT<String> runResult = XxlJobTrigger.runExecutor(triggerParam, address);\n        runResult.setContent(address);\n        return runResult;\n    }\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/route/strategy/ExecutorRouteLast.java",
    "content": "package com.xxl.job.admin.core.route.strategy;\n\nimport com.xxl.job.admin.core.route.ExecutorRouter;\nimport com.xxl.job.admin.core.trigger.XxlJobTrigger;\nimport com.xxl.job.core.biz.model.ReturnT;\nimport com.xxl.job.core.biz.model.TriggerParam;\n\nimport java.util.ArrayList;\n\n/**\n * Created by xuxueli on 17/3/10.\n */\npublic class ExecutorRouteLast extends ExecutorRouter {\n\n    public String route(int jobId, ArrayList<String> addressList) {\n        return addressList.get(addressList.size()-1);\n    }\n\n    @Override\n    public ReturnT<String> routeRun(TriggerParam triggerParam, ArrayList<String> addressList) {\n        // address\n        String address = route(triggerParam.getJobId(), addressList);\n\n        // run executor\n        ReturnT<String> runResult = XxlJobTrigger.runExecutor(triggerParam, address);\n        runResult.setContent(address);\n        return runResult;\n    }\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/route/strategy/ExecutorRouteRandom.java",
    "content": "package com.xxl.job.admin.core.route.strategy;\n\nimport com.xxl.job.admin.core.route.ExecutorRouter;\nimport com.xxl.job.admin.core.trigger.XxlJobTrigger;\nimport com.xxl.job.core.biz.model.ReturnT;\nimport com.xxl.job.core.biz.model.TriggerParam;\n\nimport java.util.ArrayList;\nimport java.util.Random;\n\n/**\n * Created by xuxueli on 17/3/10.\n */\npublic class ExecutorRouteRandom extends ExecutorRouter {\n\n    private static Random localRandom = new Random();\n\n    public String route(int jobId, ArrayList<String> addressList) {\n        // Collections.shuffle(addressList);\n        return addressList.get(localRandom.nextInt(addressList.size()));\n    }\n\n    @Override\n    public ReturnT<String> routeRun(TriggerParam triggerParam, ArrayList<String> addressList) {\n        // address\n        String address = route(triggerParam.getJobId(), addressList);\n\n        // run executor\n        ReturnT<String> runResult = XxlJobTrigger.runExecutor(triggerParam, address);\n        runResult.setContent(address);\n        return runResult;\n    }\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/route/strategy/ExecutorRouteRound.java",
    "content": "package com.xxl.job.admin.core.route.strategy;\n\nimport com.xxl.job.admin.core.route.ExecutorRouter;\nimport com.xxl.job.admin.core.trigger.XxlJobTrigger;\nimport com.xxl.job.core.biz.model.ReturnT;\nimport com.xxl.job.core.biz.model.TriggerParam;\n\nimport java.util.ArrayList;\nimport java.util.Random;\nimport java.util.concurrent.ConcurrentHashMap;\n\n/**\n * Created by xuxueli on 17/3/10.\n */\npublic class ExecutorRouteRound extends ExecutorRouter {\n\n    private static ConcurrentHashMap<Integer, Integer> routeCountEachJob = new ConcurrentHashMap<Integer, Integer>();\n    private static long CACHE_VALID_TIME = 0;\n    private static int count(int jobId) {\n        // cache clear\n        if (System.currentTimeMillis() > CACHE_VALID_TIME) {\n            routeCountEachJob.clear();\n            CACHE_VALID_TIME = System.currentTimeMillis() + 1000*60*60*24;\n        }\n\n        // count++\n        Integer count = routeCountEachJob.get(jobId);\n        count = (count==null || count>1000000)?(new Random().nextInt(100)):++count;  // 初始化时主动Random一次，缓解首次压力\n        routeCountEachJob.put(jobId, count);\n        return count;\n    }\n\n    public String route(int jobId, ArrayList<String> addressList) {\n        return addressList.get(count(jobId)%addressList.size());\n    }\n\n\n    @Override\n    public ReturnT<String> routeRun(TriggerParam triggerParam, ArrayList<String> addressList) {\n\n        // address\n        String address = route(triggerParam.getJobId(), addressList);\n\n        // run executor\n        ReturnT<String> runResult = XxlJobTrigger.runExecutor(triggerParam, address);\n        runResult.setContent(address);\n        return runResult;\n    }\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/schedule/XxlJobDynamicScheduler.java",
    "content": "package com.xxl.job.admin.core.schedule;\n\nimport java.util.Date;\nimport java.util.HashSet;\nimport java.util.concurrent.ConcurrentHashMap;\n\nimport javax.annotation.PostConstruct;\nimport javax.annotation.PreDestroy;\nimport javax.annotation.Resource;\n\nimport org.quartz.CronScheduleBuilder;\nimport org.quartz.CronTrigger;\nimport org.quartz.Job;\nimport org.quartz.JobBuilder;\nimport org.quartz.JobDetail;\nimport org.quartz.JobKey;\nimport org.quartz.Scheduler;\nimport org.quartz.SchedulerException;\nimport org.quartz.Trigger;\nimport org.quartz.Trigger.TriggerState;\nimport org.quartz.TriggerBuilder;\nimport org.quartz.TriggerKey;\nimport org.quartz.impl.triggers.CronTriggerImpl;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.BeansException;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.ApplicationContextAware;\nimport org.springframework.stereotype.Component;\nimport org.springframework.util.Assert;\n\nimport com.xxl.job.admin.core.jobbean.RemoteHttpJobBean;\nimport com.xxl.job.admin.core.model.XxlJobInfo;\nimport com.xxl.job.admin.core.thread.JobFailMonitorHelper;\nimport com.xxl.job.admin.core.thread.JobRegistryMonitorHelper;\nimport com.xxl.job.admin.core.util.I18nUtil;\nimport com.xxl.job.admin.dao.XxlJobGroupDao;\nimport com.xxl.job.admin.dao.XxlJobInfoDao;\nimport com.xxl.job.admin.dao.XxlJobLogDao;\nimport com.xxl.job.admin.dao.XxlJobRegistryDao;\nimport com.xxl.job.core.biz.AdminBiz;\nimport com.xxl.job.core.biz.ExecutorBiz;\nimport com.xxl.job.core.enums.ExecutorBlockStrategyEnum;\nimport com.xxl.job.core.rpc.netcom.NetComClientProxy;\nimport com.xxl.job.core.rpc.netcom.NetComServerFactory;\n\n/**\n * base quartz scheduler util\n * @author xuxueli 2015-12-19 16:13:53\n */\n@Component\npublic final class XxlJobDynamicScheduler implements ApplicationContextAware {\n    private static final Logger logger = LoggerFactory.getLogger(XxlJobDynamicScheduler.class);\n\n    // ---------------------- param ----------------------\n\n    // scheduler\n    private static Scheduler scheduler;\n    public void setScheduler(Scheduler scheduler) {\n\t\tXxlJobDynamicScheduler.scheduler = scheduler;\n\t}\n\n\t// accessToken\n    private static String accessToken;\n    public void setAccessToken(String accessToken) {\n        this.accessToken = accessToken;\n    }\n\n    // dao\n    public static XxlJobLogDao xxlJobLogDao;\n    public static XxlJobInfoDao xxlJobInfoDao;\n    public static XxlJobRegistryDao xxlJobRegistryDao;\n    public static XxlJobGroupDao xxlJobGroupDao;\n    public static AdminBiz adminBiz;\n\n    // ---------------------- applicationContext ----------------------\n    @Override\n\tpublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {\n    \tXxlJobDynamicScheduler.scheduler = applicationContext.getBean(\"scheduler\",Scheduler.class);\n\t\tXxlJobDynamicScheduler.xxlJobLogDao = applicationContext.getBean(XxlJobLogDao.class);\n\t\tXxlJobDynamicScheduler.xxlJobInfoDao = applicationContext.getBean(XxlJobInfoDao.class);\n        XxlJobDynamicScheduler.xxlJobRegistryDao = applicationContext.getBean(XxlJobRegistryDao.class);\n        XxlJobDynamicScheduler.xxlJobGroupDao = applicationContext.getBean(XxlJobGroupDao.class);\n        XxlJobDynamicScheduler.adminBiz = applicationContext.getBean(AdminBiz.class);\n\t}\n\n    // ---------------------- init + destroy ----------------------\n    @PostConstruct\n    public void init() throws Exception {\n        // admin registry monitor run\n        JobRegistryMonitorHelper.getInstance().start();\n\n        // admin monitor run\n        JobFailMonitorHelper.getInstance().start();\n\n        // admin-server(spring-mvc)\n        NetComServerFactory.putService(AdminBiz.class, XxlJobDynamicScheduler.adminBiz);\n        NetComServerFactory.setAccessToken(accessToken);\n\n        // init i18n\n        initI18n();\n\n        // valid\n        Assert.notNull(scheduler, \"quartz scheduler is null\");\n        logger.info(\">>>>>>>>> init xxl-job admin success.\");\n    }\n\n    private void initI18n(){\n        for (ExecutorBlockStrategyEnum item:ExecutorBlockStrategyEnum.values()) {\n            item.setTitle(I18nUtil.getString(\"jobconf_block_\".concat(item.name())));\n        }\n    }\n    @PreDestroy\n    public void destroy(){\n        // admin registry stop\n        JobRegistryMonitorHelper.getInstance().toStop();\n\n        // admin monitor stop\n        JobFailMonitorHelper.getInstance().toStop();\n    }\n\n    // ---------------------- executor-client ----------------------\n    private static ConcurrentHashMap<String, ExecutorBiz> executorBizRepository = new ConcurrentHashMap<String, ExecutorBiz>();\n    public static ExecutorBiz getExecutorBiz(String address) throws Exception {\n        // valid\n        if (address==null || address.trim().length()==0) {\n            return null;\n        }\n\n        // load-cache\n        address = address.trim();\n        ExecutorBiz executorBiz = executorBizRepository.get(address);\n        if (executorBiz != null) {\n            return executorBiz;\n        }\n\n        // set-cache\n        executorBiz = (ExecutorBiz) new NetComClientProxy(ExecutorBiz.class, address, accessToken).getObject();\n        executorBizRepository.put(address, executorBiz);\n        return executorBiz;\n    }\n\n    // ---------------------- schedule util ----------------------\n\n    /**\n     * fill job info\n     *\n     * @param jobInfo\n     */\n\tpublic static void fillJobInfo(XxlJobInfo jobInfo) {\n\t\t// TriggerKey : name + group\n        String group = String.valueOf(jobInfo.getJobGroup());\n        String name = String.valueOf(jobInfo.getId());\n        TriggerKey triggerKey = TriggerKey.triggerKey(name, group);\n\n        try {\n\t\t\tTrigger trigger = scheduler.getTrigger(triggerKey);\n\n\t\t\tTriggerState triggerState = scheduler.getTriggerState(triggerKey);\n\t\t\t\n\t\t\t// parse params\n\t\t\tif (trigger!=null && trigger instanceof CronTriggerImpl) {\n\t\t\t\tString cronExpression = ((CronTriggerImpl) trigger).getCronExpression();\n\t\t\t\tjobInfo.setJobCron(cronExpression);\n\t\t\t}\n\n\t\t\t//JobKey jobKey = new JobKey(jobInfo.getJobName(), String.valueOf(jobInfo.getJobGroup()));\n            //JobDetail jobDetail = scheduler.getJobDetail(jobKey);\n            //String jobClass = jobDetail.getJobClass().getName();\n\n\t\t\tif (triggerState!=null) {\n\t\t\t\tjobInfo.setJobStatus(triggerState.name());\n\t\t\t}\n\t\t\t\n\t\t} catch (SchedulerException e) {\n\t\t\tlogger.error(e.getMessage(), e);\n\t\t}\n\t}\n\t\n    /**\n     * check if exists\n     *\n     * @param jobName\n     * @param jobGroup\n     * @return\n     * @throws SchedulerException\n     */\n\tpublic static boolean checkExists(String jobName, String jobGroup) throws SchedulerException{\n\t\tTriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);\n\t\treturn scheduler.checkExists(triggerKey);\n\t}\n\n    /**\n     * addJob\n     *\n     * @param jobName\n     * @param jobGroup\n     * @param cronExpression\n     * @return\n     * @throws SchedulerException\n     */\n\tpublic static boolean addJob(String jobName, String jobGroup, String cronExpression) throws SchedulerException {\n    \t// TriggerKey : name + group\n        TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);\n        JobKey jobKey = new JobKey(jobName, jobGroup);\n        \n        // TriggerKey valid if_exists\n        if (checkExists(jobName, jobGroup)) {\n            logger.info(\">>>>>>>>> addJob fail, job already exist, jobGroup:{}, jobName:{}\", jobGroup, jobName);\n            return false;\n        }\n        \n        // CronTrigger : TriggerKey + cronExpression\t// withMisfireHandlingInstructionDoNothing 忽略掉调度终止过程中忽略的调度\n        CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression).withMisfireHandlingInstructionDoNothing();\n        CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withSchedule(cronScheduleBuilder).build();\n\n        // JobDetail : jobClass\n\t\tClass<? extends Job> jobClass_ = RemoteHttpJobBean.class;   // Class.forName(jobInfo.getJobClass());\n        \n\t\tJobDetail jobDetail = JobBuilder.newJob(jobClass_).withIdentity(jobKey).build();\n        /*if (jobInfo.getJobData()!=null) {\n        \tJobDataMap jobDataMap = jobDetail.getJobDataMap();\n        \tjobDataMap.putAll(JacksonUtil.readValue(jobInfo.getJobData(), Map.class));\t\n        \t// JobExecutionContext context.getMergedJobDataMap().get(\"mailGuid\");\n\t\t}*/\n        \n        // schedule : jobDetail + cronTrigger\n        Date date = scheduler.scheduleJob(jobDetail, cronTrigger);\n\n        logger.info(\">>>>>>>>>>> addJob success, jobDetail:{}, cronTrigger:{}, date:{}\", jobDetail, cronTrigger, date);\n        return true;\n    }\n    \n    /**\n     * rescheduleJob\n     *\n     * @param jobGroup\n     * @param jobName\n     * @param cronExpression\n     * @return\n     * @throws SchedulerException\n     */\n\tpublic static boolean rescheduleJob(String jobGroup, String jobName, String cronExpression) throws SchedulerException {\n    \t\n    \t// TriggerKey valid if_exists\n        if (!checkExists(jobName, jobGroup)) {\n        \tlogger.info(\">>>>>>>>>>> rescheduleJob fail, job not exists, JobGroup:{}, JobName:{}\", jobGroup, jobName);\n            return false;\n        }\n        \n        // TriggerKey : name + group\n        TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);\n        CronTrigger oldTrigger = (CronTrigger) scheduler.getTrigger(triggerKey);\n\n        if (oldTrigger != null) {\n            // avoid repeat\n            String oldCron = oldTrigger.getCronExpression();\n            if (oldCron.equals(cronExpression)){\n                return true;\n            }\n\n            // CronTrigger : TriggerKey + cronExpression\n            CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression).withMisfireHandlingInstructionDoNothing();\n            oldTrigger = oldTrigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(cronScheduleBuilder).build();\n\n            // rescheduleJob\n            scheduler.rescheduleJob(triggerKey, oldTrigger);\n        } else {\n            // CronTrigger : TriggerKey + cronExpression\n            CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression).withMisfireHandlingInstructionDoNothing();\n            CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withSchedule(cronScheduleBuilder).build();\n\n            // JobDetail-JobDataMap fresh\n            JobKey jobKey = new JobKey(jobName, jobGroup);\n            JobDetail jobDetail = scheduler.getJobDetail(jobKey);\n            /*JobDataMap jobDataMap = jobDetail.getJobDataMap();\n            jobDataMap.clear();\n            jobDataMap.putAll(JacksonUtil.readValue(jobInfo.getJobData(), Map.class));*/\n\n            // Trigger fresh\n            HashSet<Trigger> triggerSet = new HashSet<Trigger>();\n            triggerSet.add(cronTrigger);\n\n            scheduler.scheduleJob(jobDetail, triggerSet, true);\n        }\n\n        logger.info(\">>>>>>>>>>> resumeJob success, JobGroup:{}, JobName:{}\", jobGroup, jobName);\n        return true;\n    }\n    \n    /**\n     * unscheduleJob\n     *\n     * @param jobName\n     * @param jobGroup\n     * @return\n     * @throws SchedulerException\n     */\n    public static boolean removeJob(String jobName, String jobGroup) throws SchedulerException {\n    \t// TriggerKey : name + group\n        TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);\n        boolean result = false;\n        if (checkExists(jobName, jobGroup)) {\n            result = scheduler.unscheduleJob(triggerKey);\n            logger.info(\">>>>>>>>>>> removeJob, triggerKey:{}, result [{}]\", triggerKey, result);\n        }\n        return true;\n    }\n\n    /**\n     * pause\n     *\n     * @param jobName\n     * @param jobGroup\n     * @return\n     * @throws SchedulerException\n     */\n    public static boolean pauseJob(String jobName, String jobGroup) throws SchedulerException {\n    \t// TriggerKey : name + group\n    \tTriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);\n        \n        boolean result = false;\n        if (checkExists(jobName, jobGroup)) {\n            scheduler.pauseTrigger(triggerKey);\n            result = true;\n            logger.info(\">>>>>>>>>>> pauseJob success, triggerKey:{}\", triggerKey);\n        } else {\n        \tlogger.info(\">>>>>>>>>>> pauseJob fail, triggerKey:{}\", triggerKey);\n        }\n        return result;\n    }\n    \n    /**\n     * resume\n     *\n     * @param jobName\n     * @param jobGroup\n     * @return\n     * @throws SchedulerException\n     */\n    public static boolean resumeJob(String jobName, String jobGroup) throws SchedulerException {\n    \t// TriggerKey : name + group\n    \tTriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);\n        \n        boolean result = false;\n        if (checkExists(jobName, jobGroup)) {\n            scheduler.resumeTrigger(triggerKey);\n            result = true;\n            logger.info(\">>>>>>>>>>> resumeJob success, triggerKey:{}\", triggerKey);\n        } else {\n        \tlogger.info(\">>>>>>>>>>> resumeJob fail, triggerKey:{}\", triggerKey);\n        }\n        return result;\n    }\n    \n    /**\n     * run\n     *\n     * @param jobName\n     * @param jobGroup\n     * @return\n     * @throws SchedulerException\n     */\n    public static boolean triggerJob(String jobName, String jobGroup) throws SchedulerException {\n    \t// TriggerKey : name + group\n    \tJobKey jobKey = new JobKey(jobName, jobGroup);\n        \n        boolean result = false;\n        if (checkExists(jobName, jobGroup)) {\n            scheduler.triggerJob(jobKey);\n            result = true;\n            logger.info(\">>>>>>>>>>> runJob success, jobKey:{}\", jobKey);\n        } else {\n        \tlogger.info(\">>>>>>>>>>> runJob fail, jobKey:{}\", jobKey);\n        }\n        return result;\n    }\n\n    /**\n     * finaAllJobList\n     *\n     * @return\n     *//*\n    @Deprecated\n    public static List<Map<String, Object>> finaAllJobList(){\n        List<Map<String, Object>> jobList = new ArrayList<Map<String,Object>>();\n\n        try {\n            if (scheduler.getJobGroupNames()==null || scheduler.getJobGroupNames().size()==0) {\n                return null;\n            }\n            String groupName = scheduler.getJobGroupNames().get(0);\n            Set<JobKey> jobKeys = scheduler.getJobKeys(GroupMatcher.jobGroupEquals(groupName));\n            if (jobKeys!=null && jobKeys.size()>0) {\n                for (JobKey jobKey : jobKeys) {\n                    TriggerKey triggerKey = TriggerKey.triggerKey(jobKey.getName(), Scheduler.DEFAULT_GROUP);\n                    Trigger trigger = scheduler.getTrigger(triggerKey);\n                    JobDetail jobDetail = scheduler.getJobDetail(jobKey);\n                    TriggerState triggerState = scheduler.getTriggerState(triggerKey);\n                    Map<String, Object> jobMap = new HashMap<String, Object>();\n                    jobMap.put(\"TriggerKey\", triggerKey);\n                    jobMap.put(\"Trigger\", trigger);\n                    jobMap.put(\"JobDetail\", jobDetail);\n                    jobMap.put(\"TriggerState\", triggerState);\n                    jobList.add(jobMap);\n                }\n            }\n\n        } catch (SchedulerException e) {\n            logger.error(e.getMessage(), e);\n            return null;\n        }\n        return jobList;\n    }*/\n\n}"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/thread/JobFailMonitorHelper.java",
    "content": "package com.xxl.job.admin.core.thread;\n\nimport com.xxl.job.admin.core.model.XxlJobGroup;\nimport com.xxl.job.admin.core.model.XxlJobInfo;\nimport com.xxl.job.admin.core.model.XxlJobLog;\nimport com.xxl.job.admin.core.schedule.XxlJobDynamicScheduler;\nimport com.xxl.job.admin.core.util.I18nUtil;\nimport com.xxl.job.admin.core.util.MailUtil;\nimport com.xxl.job.core.biz.model.ReturnT;\nimport com.xxl.job.core.handler.IJobHandler;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.text.MessageFormat;\nimport java.util.*;\nimport java.util.concurrent.LinkedBlockingQueue;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * job monitor instance\n * @author xuxueli 2015-9-1 18:05:56\n */\npublic class JobFailMonitorHelper {\n\tprivate static Logger logger = LoggerFactory.getLogger(JobFailMonitorHelper.class);\n\t\n\tprivate static JobFailMonitorHelper instance = new JobFailMonitorHelper();\n\tpublic static JobFailMonitorHelper getInstance(){\n\t\treturn instance;\n\t}\n\n\t// ---------------------- monitor ----------------------\n\n\tprivate LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<Integer>(0xfff8);\n\n\tprivate Thread monitorThread;\n\tprivate volatile boolean toStop = false;\n\tpublic void start(){\n\t\tmonitorThread = new Thread(new Runnable() {\n\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\t// monitor\n\t\t\t\twhile (!toStop) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tList<Integer> jobLogIdList = new ArrayList<Integer>();\n\t\t\t\t\t\tint drainToNum = JobFailMonitorHelper.instance.queue.drainTo(jobLogIdList);\n\n\t\t\t\t\t\tif (CollectionUtils.isNotEmpty(jobLogIdList)) {\n\t\t\t\t\t\t\tfor (Integer jobLogId : jobLogIdList) {\n\t\t\t\t\t\t\t\tif (jobLogId==null || jobLogId==0) {\n\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tXxlJobLog log = XxlJobDynamicScheduler.xxlJobLogDao.load(jobLogId);\n\t\t\t\t\t\t\t\tif (log == null) {\n\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (IJobHandler.SUCCESS.getCode() == log.getTriggerCode() && log.getHandleCode() == 0) {\n\t\t\t\t\t\t\t\t\tJobFailMonitorHelper.monitor(jobLogId);\n\t\t\t\t\t\t\t\t\tlogger.info(\">>>>>>>>>>> job monitor, job running, JobLogId:{}\", jobLogId);\n\t\t\t\t\t\t\t\t} else if (IJobHandler.SUCCESS.getCode() == log.getHandleCode()) {\n\t\t\t\t\t\t\t\t\t// job success, pass\n\t\t\t\t\t\t\t\t\tlogger.info(\">>>>>>>>>>> job monitor, job success, JobLogId:{}\", jobLogId);\n\t\t\t\t\t\t\t\t} else if (IJobHandler.FAIL.getCode() == log.getTriggerCode()\n\t\t\t\t\t\t\t\t\t\t|| IJobHandler.FAIL.getCode() == log.getHandleCode()\n\t\t\t\t\t\t\t\t\t\t|| IJobHandler.FAIL_RETRY.getCode() == log.getHandleCode() ) {\n\t\t\t\t\t\t\t\t\t// job fail,\n\t\t\t\t\t\t\t\t\tfailAlarm(log);\n\t\t\t\t\t\t\t\t\tlogger.info(\">>>>>>>>>>> job monitor, job fail, JobLogId:{}\", jobLogId);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tJobFailMonitorHelper.monitor(jobLogId);\n\t\t\t\t\t\t\t\t\tlogger.info(\">>>>>>>>>>> job monitor, job status unknown, JobLogId:{}\", jobLogId);\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\tTimeUnit.SECONDS.sleep(10);\n\t\t\t\t\t} catch (Exception e) {\n\t\t\t\t\t\tlogger.error(\"job monitor error:{}\", e);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// monitor all clear\n\t\t\t\tList<Integer> jobLogIdList = new ArrayList<Integer>();\n\t\t\t\tint drainToNum = getInstance().queue.drainTo(jobLogIdList);\n\t\t\t\tif (jobLogIdList!=null && jobLogIdList.size()>0) {\n\t\t\t\t\tfor (Integer jobLogId: jobLogIdList) {\n\t\t\t\t\t\tXxlJobLog log = XxlJobDynamicScheduler.xxlJobLogDao.load(jobLogId);\n\t\t\t\t\t\tif (ReturnT.FAIL_CODE == log.getTriggerCode()|| ReturnT.FAIL_CODE==log.getHandleCode()) {\n\t\t\t\t\t\t\t// job fail,\n\t\t\t\t\t\t\tfailAlarm(log);\n\t\t\t\t\t\t\tlogger.info(\">>>>>>>>>>> job monitor last, job fail, JobLogId:{}\", jobLogId);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t}\n\t\t});\n\t\tmonitorThread.setDaemon(true);\n\t\tmonitorThread.start();\n\t}\n\n\tpublic void toStop(){\n\t\ttoStop = true;\n\t\t// interrupt and wait\n\t\tmonitorThread.interrupt();\n\t\ttry {\n\t\t\tmonitorThread.join();\n\t\t} catch (InterruptedException e) {\n\t\t\tlogger.error(e.getMessage(), e);\n\t\t}\n\t}\n\t\n\t// producer\n\tpublic static void monitor(int jobLogId){\n\t\tgetInstance().queue.offer(jobLogId);\n\t}\n\n\n\t// ---------------------- alarm ----------------------\n\n\t// email alarm template\n\tprivate static final String mailBodyTemplate = \"<h5>\" + I18nUtil.getString(\"jobconf_monitor_detail\") + \"：</span>\" +\n\t\t\t\"<table border=\\\"1\\\" cellpadding=\\\"3\\\" style=\\\"border-collapse:collapse; width:80%;\\\" >\\n\" +\n\t\t\t\"   <thead style=\\\"font-weight: bold;color: #ffffff;background-color: #ff8c00;\\\" >\" +\n\t\t\t\"      <tr>\\n\" +\n\t\t\t\"         <td>\"+ I18nUtil.getString(\"jobinfo_field_jobgroup\") +\"</td>\\n\" +\n\t\t\t\"         <td>\"+ I18nUtil.getString(\"jobinfo_field_id\") +\"</td>\\n\" +\n\t\t\t\"         <td>\"+ I18nUtil.getString(\"jobinfo_field_jobdesc\") +\"</td>\\n\" +\n\t\t\t\"         <td>\"+ I18nUtil.getString(\"jobconf_monitor_alarm_title\") +\"</td>\\n\" +\n\t\t\t\"      </tr>\\n\" +\n\t\t\t\"   <thead/>\\n\" +\n\t\t\t\"   <tbody>\\n\" +\n\t\t\t\"      <tr>\\n\" +\n\t\t\t\"         <td>{0}</td>\\n\" +\n\t\t\t\"         <td>{1}</td>\\n\" +\n\t\t\t\"         <td>{2}</td>\\n\" +\n\t\t\t\"         <td>\"+ I18nUtil.getString(\"jobconf_monitor_alarm_type\") +\"</td>\\n\" +\n\t\t\t\"      </tr>\\n\" +\n\t\t\t\"   <tbody>\\n\" +\n\t\t\t\"</table>\";\n\n\t/**\n\t * fail alarm\n\t *\n\t * @param jobLog\n\t */\n\tprivate void failAlarm(XxlJobLog jobLog){\n\n\t\t// send monitor email\n\t\tXxlJobInfo info = XxlJobDynamicScheduler.xxlJobInfoDao.loadById(jobLog.getJobId());\n\t\tif (info!=null && info.getAlarmEmail()!=null && info.getAlarmEmail().trim().length()>0) {\n\n\t\t\tSet<String> emailSet = new HashSet<String>(Arrays.asList(info.getAlarmEmail().split(\",\")));\n\t\t\tfor (String email: emailSet) {\n\t\t\t\tXxlJobGroup group = XxlJobDynamicScheduler.xxlJobGroupDao.load(Integer.valueOf(info.getJobGroup()));\n\n\t\t\t\tString title = I18nUtil.getString(\"jobconf_monitor\");\n\t\t\t\tString content = MessageFormat.format(mailBodyTemplate, group!=null?group.getTitle():\"null\", info.getId(), info.getJobDesc());\n\n\t\t\t\tMailUtil.sendMail(email, title, content);\n\t\t\t}\n\t\t}\n\n\t\t// TODO, custom alarm strategy, such as sms\n\n\t}\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/thread/JobRegistryMonitorHelper.java",
    "content": "package com.xxl.job.admin.core.thread;\n\nimport com.xxl.job.admin.core.model.XxlJobGroup;\nimport com.xxl.job.admin.core.model.XxlJobRegistry;\nimport com.xxl.job.admin.core.schedule.XxlJobDynamicScheduler;\nimport com.xxl.job.core.enums.RegistryConfig;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * job registry instance\n * @author xuxueli 2016-10-02 19:10:24\n */\npublic class JobRegistryMonitorHelper {\n\tprivate static Logger logger = LoggerFactory.getLogger(JobRegistryMonitorHelper.class);\n\n\tprivate static JobRegistryMonitorHelper instance = new JobRegistryMonitorHelper();\n\tpublic static JobRegistryMonitorHelper getInstance(){\n\t\treturn instance;\n\t}\n\n\tprivate Thread registryThread;\n\tprivate volatile boolean toStop = false;\n\tpublic void start(){\n\t\tregistryThread = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\twhile (!toStop) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\t// auto registry group\n\t\t\t\t\t\tList<XxlJobGroup> groupList = XxlJobDynamicScheduler.xxlJobGroupDao.findByAddressType(0);\n\t\t\t\t\t\tif (CollectionUtils.isNotEmpty(groupList)) {\n\n\t\t\t\t\t\t\t// remove dead address (admin/executor)\n\t\t\t\t\t\t\tXxlJobDynamicScheduler.xxlJobRegistryDao.removeDead(RegistryConfig.DEAD_TIMEOUT);\n\n\t\t\t\t\t\t\t// fresh online address (admin/executor)\n\t\t\t\t\t\t\tHashMap<String, List<String>> appAddressMap = new HashMap<String, List<String>>();\n\t\t\t\t\t\t\tList<XxlJobRegistry> list = XxlJobDynamicScheduler.xxlJobRegistryDao.findAll(RegistryConfig.DEAD_TIMEOUT);\n\t\t\t\t\t\t\tif (list != null) {\n\t\t\t\t\t\t\t\tfor (XxlJobRegistry item: list) {\n\t\t\t\t\t\t\t\t\tif (RegistryConfig.RegistType.EXECUTOR.name().equals(item.getRegistryGroup())) {\n\t\t\t\t\t\t\t\t\t\tString appName = item.getRegistryKey();\n\t\t\t\t\t\t\t\t\t\tList<String> registryList = appAddressMap.get(appName);\n\t\t\t\t\t\t\t\t\t\tif (registryList == null) {\n\t\t\t\t\t\t\t\t\t\t\tregistryList = new ArrayList<String>();\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tif (!registryList.contains(item.getRegistryValue())) {\n\t\t\t\t\t\t\t\t\t\t\tregistryList.add(item.getRegistryValue());\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tappAddressMap.put(appName, registryList);\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\n\t\t\t\t\t\t\t// fresh group address\n\t\t\t\t\t\t\tfor (XxlJobGroup group: groupList) {\n\t\t\t\t\t\t\t\tList<String> registryList = appAddressMap.get(group.getAppName());\n\t\t\t\t\t\t\t\tString addressListStr = null;\n\t\t\t\t\t\t\t\tif (CollectionUtils.isNotEmpty(registryList)) {\n\t\t\t\t\t\t\t\t\tCollections.sort(registryList);\n\t\t\t\t\t\t\t\t\taddressListStr = StringUtils.join(registryList, \",\");\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tgroup.setAddressList(addressListStr);\n\t\t\t\t\t\t\t\tXxlJobDynamicScheduler.xxlJobGroupDao.update(group);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (Exception e) {\n\t\t\t\t\t\tlogger.error(\"job registry instance error:{}\", e);\n\t\t\t\t\t}\n\t\t\t\t\ttry {\n\t\t\t\t\t\tTimeUnit.SECONDS.sleep(RegistryConfig.BEAT_TIMEOUT);\n\t\t\t\t\t} catch (InterruptedException e) {\n\t\t\t\t\t\tlogger.error(\"job registry instance error:{}\", e);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tregistryThread.setDaemon(true);\n\t\tregistryThread.start();\n\t}\n\n\tpublic void toStop(){\n\t\ttoStop = true;\n\t\t// interrupt and wait\n\t\tregistryThread.interrupt();\n\t\ttry {\n\t\t\tregistryThread.join();\n\t\t} catch (InterruptedException e) {\n\t\t\tlogger.error(e.getMessage(), e);\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/trigger/XxlJobTrigger.java",
    "content": "package com.xxl.job.admin.core.trigger;\n\nimport com.xxl.job.admin.core.enums.ExecutorFailStrategyEnum;\nimport com.xxl.job.admin.core.model.XxlJobGroup;\nimport com.xxl.job.admin.core.model.XxlJobInfo;\nimport com.xxl.job.admin.core.model.XxlJobLog;\nimport com.xxl.job.admin.core.route.ExecutorRouteStrategyEnum;\nimport com.xxl.job.admin.core.schedule.XxlJobDynamicScheduler;\nimport com.xxl.job.admin.core.thread.JobFailMonitorHelper;\nimport com.xxl.job.admin.core.util.I18nUtil;\nimport com.xxl.job.core.biz.ExecutorBiz;\nimport com.xxl.job.core.biz.model.ReturnT;\nimport com.xxl.job.core.biz.model.TriggerParam;\nimport com.xxl.job.core.enums.ExecutorBlockStrategyEnum;\nimport com.xxl.job.core.util.IpUtil;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.ArrayList;\nimport java.util.Date;\n\n/**\n * xxl-job trigger\n * Created by xuxueli on 17/7/13.\n */\npublic class XxlJobTrigger {\n    private static Logger logger = LoggerFactory.getLogger(XxlJobTrigger.class);\n\n    /**\n     * trigger job\n     *\n     * @param jobId\n     */\n    public static void trigger(int jobId) {\n\n        // load data\n        XxlJobInfo jobInfo = XxlJobDynamicScheduler.xxlJobInfoDao.loadById(jobId);              // job info\n        if (jobInfo == null) {\n            logger.warn(\">>>>>>>>>>>> trigger fail, jobId invalid，jobId={}\", jobId);\n            return;\n        }\n        XxlJobGroup group = XxlJobDynamicScheduler.xxlJobGroupDao.load(jobInfo.getJobGroup());  // group info\n\n        ExecutorBlockStrategyEnum blockStrategy = ExecutorBlockStrategyEnum.match(jobInfo.getExecutorBlockStrategy(), ExecutorBlockStrategyEnum.SERIAL_EXECUTION);  // block strategy\n        ExecutorFailStrategyEnum failStrategy = ExecutorFailStrategyEnum.match(jobInfo.getExecutorFailStrategy(), ExecutorFailStrategyEnum.FAIL_ALARM);    // fail strategy\n        ExecutorRouteStrategyEnum executorRouteStrategyEnum = ExecutorRouteStrategyEnum.match(jobInfo.getExecutorRouteStrategy(), null);    // route strategy\n        ArrayList<String> addressList = (ArrayList<String>) group.getRegistryList();\n\n        // broadcast\n        if (ExecutorRouteStrategyEnum.SHARDING_BROADCAST == executorRouteStrategyEnum && CollectionUtils.isNotEmpty(addressList)) {\n            for (int i = 0; i < addressList.size(); i++) {\n                String address = addressList.get(i);\n\n                // 1、save log-id\n                XxlJobLog jobLog = new XxlJobLog();\n                jobLog.setJobGroup(jobInfo.getJobGroup());\n                jobLog.setJobId(jobInfo.getId());\n                XxlJobDynamicScheduler.xxlJobLogDao.save(jobLog);\n                logger.debug(\">>>>>>>>>>> xxl-job trigger start, jobId:{}\", jobLog.getId());\n\n                // 2、prepare trigger-info\n                //jobLog.setExecutorAddress(executorAddress);\n                jobLog.setGlueType(jobInfo.getGlueType());\n                jobLog.setExecutorHandler(jobInfo.getExecutorHandler());\n                jobLog.setExecutorParam(jobInfo.getExecutorParam());\n                jobLog.setTriggerTime(new Date());\n\n                ReturnT<String> triggerResult = new ReturnT<String>(null);\n                StringBuffer triggerMsgSb = new StringBuffer();\n                triggerMsgSb.append(I18nUtil.getString(\"jobconf_trigger_admin_adress\")).append(\"：\").append(IpUtil.getIp());\n                triggerMsgSb.append(\"<br>\").append(I18nUtil.getString(\"jobconf_trigger_exe_regtype\")).append(\"：\")\n                        .append( (group.getAddressType() == 0)?I18nUtil.getString(\"jobgroup_field_addressType_0\"):I18nUtil.getString(\"jobgroup_field_addressType_1\") );\n                triggerMsgSb.append(\"<br>\").append(I18nUtil.getString(\"jobconf_trigger_exe_regaddress\")).append(\"：\").append(group.getRegistryList());\n                triggerMsgSb.append(\"<br>\").append(I18nUtil.getString(\"jobinfo_field_executorRouteStrategy\")).append(\"：\").append(executorRouteStrategyEnum.getTitle()).append(\"(\"+i+\"/\"+addressList.size()+\")\"); // update01\n                triggerMsgSb.append(\"<br>\").append(I18nUtil.getString(\"jobinfo_field_executorBlockStrategy\")).append(\"：\").append(blockStrategy.getTitle());\n                triggerMsgSb.append(\"<br>\").append(I18nUtil.getString(\"jobinfo_field_executorFailStrategy\")).append(\"：\").append(failStrategy.getTitle());\n\n                // 3、trigger-valid\n                if (triggerResult.getCode()==ReturnT.SUCCESS_CODE && CollectionUtils.isEmpty(addressList)) {\n                    triggerResult.setCode(ReturnT.FAIL_CODE);\n                    triggerMsgSb.append(\"<br>----------------------<br>\").append(I18nUtil.getString(\"jobconf_trigger_address_empty\"));\n                }\n\n                if (triggerResult.getCode() == ReturnT.SUCCESS_CODE) {\n                    // 4.1、trigger-param\n                    TriggerParam triggerParam = new TriggerParam();\n                    triggerParam.setJobId(jobInfo.getId());\n                    triggerParam.setExecutorHandler(jobInfo.getExecutorHandler());\n                    triggerParam.setExecutorParams(jobInfo.getExecutorParam());\n                    triggerParam.setExecutorBlockStrategy(jobInfo.getExecutorBlockStrategy());\n                    triggerParam.setLogId(jobLog.getId());\n                    triggerParam.setLogDateTim(jobLog.getTriggerTime().getTime());\n                    triggerParam.setGlueType(jobInfo.getGlueType());\n                    triggerParam.setGlueSource(jobInfo.getGlueSource());\n                    triggerParam.setGlueUpdatetime(jobInfo.getGlueUpdatetime().getTime());\n                    triggerParam.setBroadcastIndex(i);\n                    triggerParam.setBroadcastTotal(addressList.size()); // update02\n\n                    // 4.2、trigger-run (route run / trigger remote executor)\n                    triggerResult = runExecutor(triggerParam, address);     // update03\n                    triggerMsgSb.append(\"<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>\"+ I18nUtil.getString(\"jobconf_trigger_run\") +\"<<<<<<<<<<< </span><br>\").append(triggerResult.getMsg());\n\n                    // 4.3、trigger (fail retry)\n                    if (triggerResult.getCode()!=ReturnT.SUCCESS_CODE && failStrategy == ExecutorFailStrategyEnum.FAIL_RETRY) {\n                        triggerResult = runExecutor(triggerParam, address);  // update04\n                        triggerMsgSb.append(\"<br><br><span style=\\\"color:#F39C12;\\\" > >>>>>>>>>>>\"+ I18nUtil.getString(\"jobconf_trigger_fail_retry\") +\"<<<<<<<<<<< </span><br>\").append(triggerResult.getMsg());\n                    }\n                }\n\n                // 5、save trigger-info\n                jobLog.setExecutorAddress(triggerResult.getContent());\n                jobLog.setTriggerCode(triggerResult.getCode());\n                jobLog.setTriggerMsg(triggerMsgSb.toString());\n                XxlJobDynamicScheduler.xxlJobLogDao.updateTriggerInfo(jobLog);\n\n                // 6、monitor trigger\n                JobFailMonitorHelper.monitor(jobLog.getId());\n                logger.debug(\">>>>>>>>>>> xxl-job trigger end, jobId:{}\", jobLog.getId());\n\n            }\n        } else {\n            // 1、save log-id\n            XxlJobLog jobLog = new XxlJobLog();\n            jobLog.setJobGroup(jobInfo.getJobGroup());\n            jobLog.setJobId(jobInfo.getId());\n            XxlJobDynamicScheduler.xxlJobLogDao.save(jobLog);\n            logger.debug(\">>>>>>>>>>> xxl-job trigger start, jobId:{}\", jobLog.getId());\n\n            // 2、prepare trigger-info\n            //jobLog.setExecutorAddress(executorAddress);\n            jobLog.setGlueType(jobInfo.getGlueType());\n            jobLog.setExecutorHandler(jobInfo.getExecutorHandler());\n            jobLog.setExecutorParam(jobInfo.getExecutorParam());\n            jobLog.setTriggerTime(new Date());\n\n            ReturnT<String> triggerResult = new ReturnT<String>(null);\n            StringBuffer triggerMsgSb = new StringBuffer();\n            triggerMsgSb.append(I18nUtil.getString(\"jobconf_trigger_admin_adress\")).append(\"：\").append(IpUtil.getIp());\n            triggerMsgSb.append(\"<br>\").append(I18nUtil.getString(\"jobconf_trigger_exe_regtype\")).append(\"：\")\n                    .append( (group.getAddressType() == 0)?I18nUtil.getString(\"jobgroup_field_addressType_0\"):I18nUtil.getString(\"jobgroup_field_addressType_1\") );\n            triggerMsgSb.append(\"<br>\").append(I18nUtil.getString(\"jobconf_trigger_exe_regaddress\")).append(\"：\").append(group.getRegistryList());\n            triggerMsgSb.append(\"<br>\").append(I18nUtil.getString(\"jobinfo_field_executorRouteStrategy\")).append(\"：\").append(executorRouteStrategyEnum.getTitle());\n            triggerMsgSb.append(\"<br>\").append(I18nUtil.getString(\"jobinfo_field_executorBlockStrategy\")).append(\"：\").append(blockStrategy.getTitle());\n            triggerMsgSb.append(\"<br>\").append(I18nUtil.getString(\"jobinfo_field_executorFailStrategy\")).append(\"：\").append(failStrategy.getTitle());\n\n            // 3、trigger-valid\n            if (triggerResult.getCode()==ReturnT.SUCCESS_CODE && CollectionUtils.isEmpty(addressList)) {\n                triggerResult.setCode(ReturnT.FAIL_CODE);\n                triggerMsgSb.append(\"<br>----------------------<br>\").append(I18nUtil.getString(\"jobconf_trigger_address_empty\"));\n            }\n\n            if (triggerResult.getCode() == ReturnT.SUCCESS_CODE) {\n                // 4.1、trigger-param\n                TriggerParam triggerParam = new TriggerParam();\n                triggerParam.setJobId(jobInfo.getId());\n                triggerParam.setExecutorHandler(jobInfo.getExecutorHandler());\n                triggerParam.setExecutorParams(jobInfo.getExecutorParam());\n                triggerParam.setExecutorBlockStrategy(jobInfo.getExecutorBlockStrategy());\n                triggerParam.setLogId(jobLog.getId());\n                triggerParam.setLogDateTim(jobLog.getTriggerTime().getTime());\n                triggerParam.setGlueType(jobInfo.getGlueType());\n                triggerParam.setGlueSource(jobInfo.getGlueSource());\n                triggerParam.setGlueUpdatetime(jobInfo.getGlueUpdatetime().getTime());\n                triggerParam.setBroadcastIndex(0);\n                triggerParam.setBroadcastTotal(1);\n\n                // 4.2、trigger-run (route run / trigger remote executor)\n                triggerResult = executorRouteStrategyEnum.getRouter().routeRun(triggerParam, addressList);\n                triggerMsgSb.append(\"<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>\"+ I18nUtil.getString(\"jobconf_trigger_run\") +\"<<<<<<<<<<< </span><br>\").append(triggerResult.getMsg());\n\n                // 4.3、trigger (fail retry)\n                if (triggerResult.getCode()!=ReturnT.SUCCESS_CODE && failStrategy == ExecutorFailStrategyEnum.FAIL_RETRY) {\n                    triggerResult = executorRouteStrategyEnum.getRouter().routeRun(triggerParam, addressList);\n                    triggerMsgSb.append(\"<br><br><span style=\\\"color:#F39C12;\\\" > >>>>>>>>>>>\"+ I18nUtil.getString(\"jobconf_trigger_fail_retry\") +\"<<<<<<<<<<< </span><br>\").append(triggerResult.getMsg());\n                }\n            }\n\n            // 5、save trigger-info\n            jobLog.setExecutorAddress(triggerResult.getContent());\n            jobLog.setTriggerCode(triggerResult.getCode());\n            jobLog.setTriggerMsg(triggerMsgSb.toString());\n            XxlJobDynamicScheduler.xxlJobLogDao.updateTriggerInfo(jobLog);\n\n            // 6、monitor trigger\n            JobFailMonitorHelper.monitor(jobLog.getId());\n            logger.debug(\">>>>>>>>>>> xxl-job trigger end, jobId:{}\", jobLog.getId());\n        }\n\n    }\n\n    /**\n     * run executor\n     * @param triggerParam\n     * @param address\n     * @return  ReturnT.content: final address\n     */\n    public static ReturnT<String> runExecutor(TriggerParam triggerParam, String address){\n        ReturnT<String> runResult = null;\n        try {\n            ExecutorBiz executorBiz = XxlJobDynamicScheduler.getExecutorBiz(address);\n            runResult = executorBiz.run(triggerParam);\n        } catch (Exception e) {\n            logger.error(\">>>>>>>>>>> xxl-job trigger error, please check if the executor[{}] is running.\", address, e);\n            runResult = new ReturnT<String>(ReturnT.FAIL_CODE, \"\"+e );\n        }\n\n        StringBuffer runResultSB = new StringBuffer(I18nUtil.getString(\"jobconf_trigger_run\") + \"：\");\n        runResultSB.append(\"<br>address：\").append(address);\n        runResultSB.append(\"<br>code：\").append(runResult.getCode());\n        runResultSB.append(\"<br>msg：\").append(runResult.getMsg());\n\n        runResult.setMsg(runResultSB.toString());\n        runResult.setContent(address);\n        return runResult;\n    }\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/util/CookieUtil.java",
    "content": "package com.xxl.job.admin.core.util;\n\nimport javax.servlet.http.Cookie;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\n/**\n * Cookie.Util\n *\n * @author xuxueli 2015-12-12 18:01:06\n */\npublic class CookieUtil {\n\n\t// 默认缓存时间,单位/秒, 2H\n\tprivate static final int COOKIE_MAX_AGE = 60 * 60 * 2;\n\t// 保存路径,根路径\n\tprivate static final String COOKIE_PATH = \"/\";\n\t\n\t/**\n\t * 保存\n\t *\n\t * @param response\n\t * @param key\n\t * @param value\n\t * @param ifRemember \n\t */\n\tpublic static void set(HttpServletResponse response, String key, String value, boolean ifRemember) {\n\t\tint age = ifRemember?COOKIE_MAX_AGE:-1;\n\t\tset(response, key, value, null, COOKIE_PATH, age, true);\n\t}\n\n\t/**\n\t * 保存\n\t *\n\t * @param response\n\t * @param key\n\t * @param value\n\t * @param maxAge\n\t */\n\tprivate static void set(HttpServletResponse response, String key, String value, String domain, String path, int maxAge, boolean isHttpOnly) {\n\t\tCookie cookie = new Cookie(key, value);\n\t\tif (domain != null) {\n\t\t\tcookie.setDomain(domain);\n\t\t}\n\t\tcookie.setPath(path);\n\t\tcookie.setMaxAge(maxAge);\n\t\tcookie.setHttpOnly(isHttpOnly);\n\t\tresponse.addCookie(cookie);\n\t}\n\t\n\t/**\n\t * 查询value\n\t *\n\t * @param request\n\t * @param key\n\t * @return\n\t */\n\tpublic static String getValue(HttpServletRequest request, String key) {\n\t\tCookie cookie = get(request, key);\n\t\tif (cookie != null) {\n\t\t\treturn cookie.getValue();\n\t\t}\n\t\treturn null;\n\t}\n\n\t/**\n\t * 查询Cookie\n\t *\n\t * @param request\n\t * @param key\n\t */\n\tprivate static Cookie get(HttpServletRequest request, String key) {\n\t\tCookie[] arr_cookie = request.getCookies();\n\t\tif (arr_cookie != null && arr_cookie.length > 0) {\n\t\t\tfor (Cookie cookie : arr_cookie) {\n\t\t\t\tif (cookie.getName().equals(key)) {\n\t\t\t\t\treturn cookie;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\t\n\t/**\n\t * 删除Cookie\n\t *\n\t * @param request\n\t * @param response\n\t * @param key\n\t */\n\tpublic static void remove(HttpServletRequest request, HttpServletResponse response, String key) {\n\t\tCookie cookie = get(request, key);\n\t\tif (cookie != null) {\n\t\t\tset(response, key, \"\", null, COOKIE_PATH, 0, true);\n\t\t}\n\t}\n\n}"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/util/FtlUtil.java",
    "content": "package com.xxl.job.admin.core.util;\n\nimport freemarker.ext.beans.BeansWrapper;\nimport freemarker.template.TemplateHashModel;\n\n/**\n * ftl util\n *\n * @author xuxueli 2018-01-17 20:37:48\n */\npublic class FtlUtil {\n\n    public static TemplateHashModel generateStaticModel(String packageName) {\n        try {\n            BeansWrapper wrapper = BeansWrapper.getDefaultInstance();\n            TemplateHashModel staticModels = wrapper.getStaticModels();\n            TemplateHashModel fileStatics = (TemplateHashModel) staticModels.get(packageName);\n            return fileStatics;\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n        return null;\n    }\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/util/I18nUtil.java",
    "content": "package com.xxl.job.admin.core.util;\n\nimport java.io.IOException;\nimport java.text.MessageFormat;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Properties;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.core.io.ClassPathResource;\nimport org.springframework.core.io.Resource;\nimport org.springframework.core.io.support.EncodedResource;\nimport org.springframework.core.io.support.PropertiesLoaderUtils;\n\nimport com.xxl.job.core.util.JacksonUtil;\n\n/**\n * i18n util\n *\n * @author xuxueli 2018-01-17 20:39:06\n */\npublic class I18nUtil {\n    private static Logger logger = LoggerFactory.getLogger(I18nUtil.class);\n\n    private static Properties prop = null;\n    public static Properties loadI18nProp(){\n        if (prop != null) {\n            return prop;\n        }\n        try {\n            // build i18n prop\n            String i18nFile = \"i18n/message.properties\";\n\n            // load prop\n            Resource resource = new ClassPathResource(i18nFile);\n            EncodedResource encodedResource = new EncodedResource(resource,\"UTF-8\");\n            prop = PropertiesLoaderUtils.loadProperties(encodedResource);\n        } catch (IOException e) {\n            logger.error(e.getMessage(), e);\n        }\n        return prop;\n    }\n\n    /**\n     * get val of i18n key\n     *\n     * @param key\n     * @return\n     */\n    public static String getString(String key) {\n        return loadI18nProp().getProperty(key);\n    }\n\n    /**\n     * get mult val of i18n mult key, as json\n     *\n     * @param keys\n     * @return\n     */\n    public static String getMultString(String... keys) {\n        Map<String, String> map = new HashMap<>();\n\n        Properties prop = loadI18nProp();\n        if (keys!=null && keys.length>0) {\n            for (String key: keys) {\n                map.put(key, prop.getProperty(key));\n            }\n        } else {\n            for (String key: prop.stringPropertyNames()) {\n                map.put(key, prop.getProperty(key));\n            }\n        }\n\n        String json = JacksonUtil.writeValueAsString(map);\n        return json;\n    }\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/util/LocalCacheUtil.java",
    "content": "package com.xxl.job.admin.core.util;\n\nimport org.apache.commons.lang3.StringUtils;\n\nimport java.util.concurrent.ConcurrentHashMap;\n\n/**\n * local cache tool\n *\n * @author xuxueli 2018-01-22 21:37:34\n */\npublic class LocalCacheUtil {\n\n    private static ConcurrentHashMap<String, LocalCacheData> cacheRepository = new ConcurrentHashMap<>();\n    private static class LocalCacheData{\n        private String key;\n        private Object val;\n        private long timeoutTime;\n\n        public LocalCacheData() {\n        }\n\n        public LocalCacheData(String key, Object val, long timeoutTime) {\n            this.key = key;\n            this.val = val;\n            this.timeoutTime = timeoutTime;\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 Object getVal() {\n            return val;\n        }\n\n        public void setVal(Object val) {\n            this.val = val;\n        }\n\n        public long getTimeoutTime() {\n            return timeoutTime;\n        }\n\n        public void setTimeoutTime(long timeoutTime) {\n            this.timeoutTime = timeoutTime;\n        }\n    }\n\n\n    /**\n     * set cache\n     *\n     * @param key\n     * @param val\n     * @param cacheTime\n     * @return\n     */\n    public static boolean set(String key, Object val, long cacheTime){\n\n        // clean timeout cache, before set new cache (avoid cache too much)\n        cleanTimeutCache();\n\n        // set new cache\n        if (StringUtils.isBlank(key)) {\n            return false;\n        }\n        if (val == null) {\n            remove(key);\n        }\n        if (cacheTime <= 0) {\n            remove(key);\n        }\n        long timeoutTime = System.currentTimeMillis() + cacheTime;\n        LocalCacheData localCacheData = new LocalCacheData(key, val, timeoutTime);\n        cacheRepository.put(localCacheData.getKey(), localCacheData);\n        return true;\n    }\n\n    /**\n     * remove cache\n     *\n     * @param key\n     * @return\n     */\n    public static boolean remove(String key){\n        if (StringUtils.isBlank(key)) {\n            return false;\n        }\n        cacheRepository.remove(key);\n        return true;\n    }\n\n    /**\n     * get cache\n     *\n     * @param key\n     * @return\n     */\n    public static Object get(String key){\n        if (StringUtils.isBlank(key)) {\n            return null;\n        }\n        LocalCacheData localCacheData = cacheRepository.get(key);\n        if (localCacheData!=null && System.currentTimeMillis()<localCacheData.getTimeoutTime()) {\n            return localCacheData.getVal();\n        } else {\n            remove(key);\n            return null;\n        }\n    }\n\n    /**\n     * clean timeout cache\n     *\n     * @return\n     */\n    public static boolean cleanTimeutCache(){\n        if (!cacheRepository.keySet().isEmpty()) {\n            for (String key: cacheRepository.keySet()) {\n                LocalCacheData localCacheData = cacheRepository.get(key);\n                if (localCacheData!=null && System.currentTimeMillis()>=localCacheData.getTimeoutTime()) {\n                    cacheRepository.remove(key);\n                }\n            }\n        }\n        return true;\n    }\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/util/MailUtil.java",
    "content": "package com.xxl.job.admin.core.util;\n\nimport java.nio.charset.Charset;\n\nimport org.apache.commons.mail.DefaultAuthenticator;\nimport org.apache.commons.mail.EmailException;\nimport org.apache.commons.mail.HtmlEmail;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * 邮件发送.Util\n *\n * @author xuxueli 2016-3-12 15:06:20\n */\npublic class MailUtil {\n\tprivate static Logger logger = LoggerFactory.getLogger(MailUtil.class);\n\t\n\t/**\n\t *\n\t * @param toAddress\t\t收件人邮箱\n\t * @param mailSubject\t邮件主题\n\t * @param mailBody\t\t邮件正文\n\t * @return\n\t */\n\tpublic static boolean sendMail(String toAddress, String mailSubject, String mailBody){\n\n\t\ttry {\n\t\t\t// Create the email message\n\t\t\tHtmlEmail email = new HtmlEmail();\n\n\t\t\t//email.setDebug(true);\t\t// 将会打印一些log\n\t\t\t//email.setTLS(true);\t\t// 是否TLS校验，，某些邮箱需要TLS安全校验，同理有SSL校验\n\t\t\t//email.setSSL(true);\n\n\t\t\temail.setHostName(PropertiesUtil.getString(\"xxl.job.mail.host\"));\n\n\t\t\tif (\"true\".equals(PropertiesUtil.getString(\"xxl.job.mail.ssl\"))) {\n\t\t\t\temail.setSslSmtpPort(PropertiesUtil.getString(\"xxl.job.mail.port\"));\n\t\t\t\temail.setSSLOnConnect(true);\n\t\t\t} else {\n\t\t\t\temail.setSmtpPort(Integer.valueOf(PropertiesUtil.getString(\"xxl.job.mail.port\")));\n\t\t\t}\n\n\t\t\temail.setAuthenticator(new DefaultAuthenticator(PropertiesUtil.getString(\"xxl.job.mail.username\"), \n\t\t\t\t\tPropertiesUtil.getString(\"xxl.job.mail.password\")));\n\t\t\temail.setCharset(Charset.defaultCharset().name());\n\n\t\t\temail.setFrom(PropertiesUtil.getString(\"xxl.job.mail.username\"), PropertiesUtil.getString(\"xxl.job.mail.sendNick\"));\n\t\t\temail.addTo(toAddress);\n\t\t\temail.setSubject(mailSubject);\n\t\t\temail.setMsg(mailBody);\n\n\t\t\t//email.attach(attachment);\t// add the attachment\n\n\t\t\temail.send();\t\t\t\t// send the email\n\t\t\treturn true;\n\t\t} catch (EmailException e) {\n\t\t\tlogger.error(e.getMessage(), e);\n\n\t\t}\n\t\treturn false;\n\t}\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/util/PropertiesUtil.java",
    "content": "package com.xxl.job.admin.core.util;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.core.io.ClassPathResource;\nimport org.springframework.core.io.Resource;\nimport org.springframework.core.io.support.EncodedResource;\nimport org.springframework.core.io.support.PropertiesLoaderUtils;\n\nimport java.io.IOException;\nimport java.util.Properties;\n\n/**\n * properties util\n * @author xuxueli 2015-8-28 10:35:53\n */\npublic class PropertiesUtil {\n\tprivate static Logger logger = LoggerFactory.getLogger(PropertiesUtil.class);\n\tprivate static final String file_name = \"xxl-job-admin.properties\";\n\n\n\tpublic static String getString(String key) {\n\t\tProperties prop = null;\n\t\ttry {\n\t\t\tResource resource = new ClassPathResource(file_name);\n\t\t\tEncodedResource encodedResource = new EncodedResource(resource,\"UTF-8\");\n\t\t\tprop = PropertiesLoaderUtils.loadProperties(encodedResource);\n\t\t} catch (IOException e) {\n\t\t\tlogger.error(e.getMessage(), e);\n\t\t}\n\t\tif (prop!=null) {\n\t\t\treturn prop.getProperty(key);\n\t\t}\n\t\treturn null;\n\t}\npublic static void main(String[] args) {\n\tString user =PropertiesUtil.getString(\"xxl.job.login.username\");\n\tSystem.out.println(\"用户名: \"+user);\n}\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/dao/XxlJobGroupDao.java",
    "content": "package com.xxl.job.admin.dao;\n\nimport com.xxl.job.admin.core.model.XxlJobGroup;\n\nimport org.apache.ibatis.annotations.Mapper;\nimport org.apache.ibatis.annotations.Param;\n\nimport java.util.List;\n\n/**\n * Created by xuxueli on 16/9/30.\n */\n@Mapper\npublic interface XxlJobGroupDao {\n\n    public List<XxlJobGroup> findAll();\n\n    public List<XxlJobGroup> findByAddressType(@Param(\"addressType\") int addressType);\n\n    public int save(XxlJobGroup xxlJobGroup);\n\n    public int update(XxlJobGroup xxlJobGroup);\n\n    public int remove(@Param(\"id\") int id);\n\n    public XxlJobGroup load(@Param(\"id\") int id);\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/dao/XxlJobGroupMapper.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \n\t\"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.xxl.job.admin.dao.XxlJobGroupDao\">\n\t\n\t<resultMap id=\"XxlJobGroup\" type=\"com.xxl.job.admin.core.model.XxlJobGroup\" >\n\t\t<result column=\"id\" property=\"id\" />\n\t    <result column=\"app_name\" property=\"appName\" />\n\t    <result column=\"title\" property=\"title\" />\n\t    <result column=\"order\" property=\"order\" />\n\t\t<result column=\"address_type\" property=\"addressType\" />\n\t\t<result column=\"address_list\" property=\"addressList\" />\n\t</resultMap>\n\n\t<sql id=\"Base_Column_List\">\n\t\tt.id,\n\t\tt.app_name,\n\t\tt.title,\n\t\tt.order,\n\t\tt.address_type,\n\t\tt.address_list\n\t</sql>\n\n\t<select id=\"findAll\" resultMap=\"XxlJobGroup\">\n\t\tSELECT <include refid=\"Base_Column_List\" />\n\t\tFROM XXL_JOB_QRTZ_TRIGGER_GROUP AS t\n\t\tORDER BY t.order ASC\n\t</select>\n\n\t<select id=\"findByAddressType\" parameterType=\"java.lang.Integer\" resultMap=\"XxlJobGroup\">\n\t\tSELECT <include refid=\"Base_Column_List\" />\n\t\tFROM XXL_JOB_QRTZ_TRIGGER_GROUP AS t\n\t\tWHERE t.address_type = #{addressType}\n\t\tORDER BY t.order ASC\n\t</select>\n\n\t<insert id=\"save\" parameterType=\"com.xxl.job.admin.core.model.XxlJobGroup\" useGeneratedKeys=\"true\" keyProperty=\"id\" >\n\t\tINSERT INTO XXL_JOB_QRTZ_TRIGGER_GROUP ( `app_name`, `title`, `order`, `address_type`, `address_list`)\n\t\tvalues ( #{appName}, #{title}, #{order}, #{addressType}, #{addressList});\n\t</insert>\n\n\t<update id=\"update\" parameterType=\"com.xxl.job.admin.core.model.XxlJobGroup\" >\n\t\tUPDATE XXL_JOB_QRTZ_TRIGGER_GROUP\n\t\tSET `app_name` = #{appName},\n\t\t\t`title` = #{title},\n\t\t\t`order` = #{order},\n\t\t\t`address_type` = #{addressType},\n\t\t\t`address_list` = #{addressList}\n\t\tWHERE id = #{id}\n\t</update>\n\n\t<delete id=\"remove\" parameterType=\"java.lang.Integer\" >\n\t\tDELETE FROM XXL_JOB_QRTZ_TRIGGER_GROUP\n\t\tWHERE id = #{id}\n\t</delete>\n\n\t<select id=\"load\" parameterType=\"java.lang.Integer\" resultMap=\"XxlJobGroup\">\n\t\tSELECT <include refid=\"Base_Column_List\" />\n\t\tFROM XXL_JOB_QRTZ_TRIGGER_GROUP AS t\n\t\tWHERE t.id = #{id}\n\t</select>\n\n</mapper>"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/dao/XxlJobInfoDao.java",
    "content": "package com.xxl.job.admin.dao;\n\nimport com.xxl.job.admin.core.model.XxlJobInfo;\n\nimport org.apache.ibatis.annotations.Mapper;\nimport org.apache.ibatis.annotations.Param;\n\nimport java.util.List;\n\n\n/**\n * job info\n * @author xuxueli 2016-1-12 18:03:45\n */\n@Mapper\npublic interface XxlJobInfoDao {\n\n\tpublic List<XxlJobInfo> pageList(@Param(\"offset\") int offset,\n\t\t\t\t\t\t\t\t\t @Param(\"pagesize\") int pagesize,\n\t\t\t\t\t\t\t\t\t @Param(\"jobGroup\") int jobGroup,\n\t\t\t\t\t\t\t\t\t @Param(\"jobDesc\") String jobDesc,\n\t\t\t\t\t\t\t\t\t @Param(\"executorHandler\") String executorHandler);\n\tpublic int pageListCount(@Param(\"offset\") int offset,\n\t\t\t\t\t\t\t @Param(\"pagesize\") int pagesize,\n\t\t\t\t\t\t\t @Param(\"jobGroup\") int jobGroup,\n\t\t\t\t\t\t\t @Param(\"jobDesc\") String jobDesc,\n\t\t\t\t\t\t\t @Param(\"executorHandler\") String executorHandler);\n\t\n\tpublic int save(XxlJobInfo info);\n\n\tpublic XxlJobInfo loadById(@Param(\"id\") int id);\n\t\n\tpublic int update(XxlJobInfo item);\n\t\n\tpublic int delete(@Param(\"id\") int id);\n\n\tpublic List<XxlJobInfo> getJobsByGroup(@Param(\"jobGroup\") int jobGroup);\n\n\tpublic int findAllCount();\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/dao/XxlJobInfoMapper.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \n\t\"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.xxl.job.admin.dao.XxlJobInfoDao\">\n\t\n\t<resultMap id=\"XxlJobInfo\" type=\"com.xxl.job.admin.core.model.XxlJobInfo\" >\n\t\t<result column=\"id\" property=\"id\" />\n\t\n\t\t<result column=\"job_group\" property=\"jobGroup\" />\n\t    <result column=\"job_cron\" property=\"jobCron\" />\n\t    <result column=\"job_desc\" property=\"jobDesc\" />\n\t    \n\t    <result column=\"add_time\" property=\"addTime\" />\n\t    <result column=\"update_time\" property=\"updateTime\" />\n\t    \n\t    <result column=\"author\" property=\"author\" />\n\t    <result column=\"alarm_email\" property=\"alarmEmail\" />\n\n\t\t<result column=\"executor_route_strategy\" property=\"executorRouteStrategy\" />\n\t\t<result column=\"executor_handler\" property=\"executorHandler\" />\n\t    <result column=\"executor_param\" property=\"executorParam\" />\n\t\t<result column=\"executor_block_strategy\" property=\"executorBlockStrategy\" />\n\t\t<result column=\"executor_fail_strategy\" property=\"executorFailStrategy\" />\n\t    \n\t    <result column=\"glue_type\" property=\"glueType\" />\n\t    <result column=\"glue_source\" property=\"glueSource\" />\n\t    <result column=\"glue_remark\" property=\"glueRemark\" />\n\t\t<result column=\"glue_updatetime\" property=\"glueUpdatetime\" />\n\n\t\t<result column=\"child_jobid\" property=\"childJobId\" />\n\t</resultMap>\n\n\t<sql id=\"Base_Column_List\">\n\t\tt.id,\n\t\tt.job_group,\n\t\tt.job_cron,\n\t\tt.job_desc,\n\t\tt.add_time,\n\t\tt.update_time,\n\t\tt.author,\n\t\tt.alarm_email,\n\t\tt.executor_route_strategy,\n\t\tt.executor_handler,\n\t\tt.executor_param,\n\t\tt.executor_block_strategy,\n\t\tt.executor_fail_strategy,\n\t\tt.glue_type,\n\t\tt.glue_source,\n\t\tt.glue_remark,\n\t\tt.glue_updatetime,\n\t\tt.child_jobid\n\t</sql>\n\t\n\t<select id=\"pageList\" parameterType=\"java.util.HashMap\" resultMap=\"XxlJobInfo\">\n\t\tSELECT <include refid=\"Base_Column_List\" />\n\t\tFROM XXL_JOB_QRTZ_TRIGGER_INFO AS t\n\t\t<trim prefix=\"WHERE\" prefixOverrides=\"AND | OR\" >\n\t\t\t<if test=\"jobGroup gt 0\">\n\t\t\t\tAND t.job_group = #{jobGroup}\n\t\t\t</if>\n\t\t\t<if test=\"jobDesc != null and jobDesc != ''\">\n\t\t\t\tAND t.job_desc like CONCAT(CONCAT('%', #{jobDesc}), '%')\n\t\t\t</if>\n\t\t\t<if test=\"executorHandler != null and executorHandler != ''\">\n\t\t\t\tAND t.executor_handler like CONCAT(CONCAT('%', #{executorHandler}), '%')\n\t\t\t</if>\n\t\t</trim>\n\t\tORDER BY id DESC\n\t\tLIMIT #{offset}, #{pagesize}\n\t</select>\n\t\n\t<select id=\"pageListCount\" parameterType=\"java.util.HashMap\" resultType=\"int\">\n\t\tSELECT count(1)\n\t\tFROM XXL_JOB_QRTZ_TRIGGER_INFO AS t\n\t\t<trim prefix=\"WHERE\" prefixOverrides=\"AND | OR\" >\n\t\t\t<if test=\"jobGroup gt 0\">\n\t\t\t\tAND t.job_group = #{jobGroup}\n\t\t\t</if>\n\t\t\t<if test=\"jobDesc != null and jobDesc != ''\">\n\t\t\t\tAND t.job_desc like CONCAT(CONCAT('%', #{jobDesc}), '%')\n\t\t\t</if>\n\t\t\t<if test=\"executorHandler != null and executorHandler != ''\">\n\t\t\t\tAND t.executor_handler like CONCAT(CONCAT('%', #{executorHandler}), '%')\n\t\t\t</if>\n\t\t</trim>\n\t</select>\n\n\t<insert id=\"save\" parameterType=\"com.xxl.job.admin.core.model.XxlJobInfo\" useGeneratedKeys=\"true\" keyProperty=\"id\" >\n\t\tINSERT INTO XXL_JOB_QRTZ_TRIGGER_INFO (\n\t\t\tjob_group,\n\t\t\tjob_cron,\n\t\t\tjob_desc,\n\t\t\tadd_time,\n\t\t\tupdate_time,\n\t\t\tauthor,\n\t\t\talarm_email,\n            executor_route_strategy,\n\t\t\texecutor_handler,\n\t\t\texecutor_param,\n\t\t\texecutor_block_strategy,\n\t\t\texecutor_fail_strategy,\n\t\t\tglue_type,\n\t\t\tglue_source,\n\t\t\tglue_remark,\n\t\t\tglue_updatetime,\n\t\t\tchild_jobid\n\t\t) VALUES (\n\t\t\t#{jobGroup},\n\t\t\t#{jobCron}, \n\t\t\t#{jobDesc},\n\t\t\tNOW(),\n\t\t\tNOW(),\n\t\t\t#{author},\n\t\t\t#{alarmEmail},\n\t\t\t#{executorRouteStrategy},\n\t\t\t#{executorHandler},\n\t\t\t#{executorParam},\n\t\t\t#{executorBlockStrategy},\n\t\t\t#{executorFailStrategy},\n\t\t\t#{glueType},\n\t\t\t#{glueSource},\n\t\t\t#{glueRemark},\n\t\t\tNOW(),\n\t\t\t#{childJobId}\n\t\t);\n\t\t<!--<selectKey resultType=\"java.lang.Integer\" order=\"AFTER\" keyProperty=\"id\">\n\t\t\tSELECT LAST_INSERT_ID()\n\t\t\t/*SELECT @@IDENTITY AS id*/\n\t\t</selectKey>-->\n\t</insert>\n\n\t<select id=\"loadById\" parameterType=\"java.util.HashMap\" resultMap=\"XxlJobInfo\">\n\t\tSELECT <include refid=\"Base_Column_List\" />\n\t\tFROM XXL_JOB_QRTZ_TRIGGER_INFO AS t\n\t\tWHERE t.id = #{id}\n\t</select>\n\t\n\t<update id=\"update\" parameterType=\"com.xxl.job.admin.core.model.XxlJobInfo\" >\n\t\tUPDATE XXL_JOB_QRTZ_TRIGGER_INFO\n\t\tSET \n\t\t\tjob_cron = #{jobCron},\n\t\t\tjob_desc = #{jobDesc},\n\t\t\tupdate_time = NOW(),\n\t\t\tauthor = #{author},\n\t\t\talarm_email = #{alarmEmail},\n\t\t\texecutor_route_strategy = #{executorRouteStrategy},\n\t\t\texecutor_handler = #{executorHandler},\n\t\t\texecutor_param = #{executorParam},\n\t\t\texecutor_block_strategy = #{executorBlockStrategy},\n\t\t\texecutor_fail_strategy = #{executorFailStrategy},\n\t\t\tglue_type = #{glueType},\n\t\t\tglue_source = #{glueSource},\n\t\t\tglue_remark = #{glueRemark},\n\t\t\tglue_updatetime = #{glueUpdatetime},\n\t\t\tchild_jobid = #{childJobId}\n\t\tWHERE id = #{id}\n\t</update>\n\t\n\t<delete id=\"delete\" parameterType=\"java.util.HashMap\">\n\t\tDELETE\n\t\tFROM XXL_JOB_QRTZ_TRIGGER_INFO\n\t\tWHERE id = #{id}\n\t</delete>\n\n\t<select id=\"getJobsByGroup\" parameterType=\"java.util.HashMap\" resultMap=\"XxlJobInfo\">\n\t\tSELECT <include refid=\"Base_Column_List\" />\n\t\tFROM XXL_JOB_QRTZ_TRIGGER_INFO AS t\n\t\tWHERE t.job_group = #{jobGroup}\n\t</select>\n\n\t<select id=\"findAllCount\" resultType=\"int\">\n\t\tSELECT count(1)\n\t\tFROM XXL_JOB_QRTZ_TRIGGER_INFO\n\t</select>\n\n</mapper>"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/dao/XxlJobLogDao.java",
    "content": "package com.xxl.job.admin.dao;\n\nimport com.xxl.job.admin.core.model.XxlJobLog;\n\nimport org.apache.ibatis.annotations.Mapper;\nimport org.apache.ibatis.annotations.Param;\n\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * job log\n * @author xuxueli 2016-1-12 18:03:06\n */\n@Mapper\npublic interface XxlJobLogDao {\n\t\n\tpublic List<XxlJobLog> pageList(@Param(\"offset\") int offset,\n\t\t\t\t\t\t\t\t\t@Param(\"pagesize\") int pagesize,\n\t\t\t\t\t\t\t\t\t@Param(\"jobGroup\") int jobGroup,\n\t\t\t\t\t\t\t\t\t@Param(\"jobId\") int jobId,\n\t\t\t\t\t\t\t\t\t@Param(\"triggerTimeStart\") Date triggerTimeStart,\n\t\t\t\t\t\t\t\t\t@Param(\"triggerTimeEnd\") Date triggerTimeEnd,\n\t\t\t\t\t\t\t\t\t@Param(\"logStatus\") int logStatus);\n\tpublic int pageListCount(@Param(\"offset\") int offset,\n\t\t\t\t\t\t\t @Param(\"pagesize\") int pagesize,\n\t\t\t\t\t\t\t @Param(\"jobGroup\") int jobGroup,\n\t\t\t\t\t\t\t @Param(\"jobId\") int jobId,\n\t\t\t\t\t\t\t @Param(\"triggerTimeStart\") Date triggerTimeStart,\n\t\t\t\t\t\t\t @Param(\"triggerTimeEnd\") Date triggerTimeEnd,\n\t\t\t\t\t\t\t @Param(\"logStatus\") int logStatus);\n\t\n\tpublic XxlJobLog load(@Param(\"id\") int id);\n\n\tpublic int save(XxlJobLog xxlJobLog);\n\n\tpublic int updateTriggerInfo(XxlJobLog xxlJobLog);\n\n\tpublic int updateHandleInfo(XxlJobLog xxlJobLog);\n\t\n\tpublic int delete(@Param(\"jobId\") int jobId);\n\n\tpublic int triggerCountByHandleCode(@Param(\"handleCode\") int handleCode);\n\n\tpublic List<Map<String, Object>> triggerCountByDay(@Param(\"from\") Date from,\n\t\t\t\t\t\t\t\t\t\t\t\t\t   @Param(\"to\") Date to);\n\n\tpublic int clearLog(@Param(\"jobGroup\") int jobGroup,\n\t\t\t\t\t\t@Param(\"jobId\") int jobId,\n\t\t\t\t\t\t@Param(\"clearBeforeTime\") Date clearBeforeTime,\n\t\t\t\t\t\t@Param(\"clearBeforeNum\") int clearBeforeNum);\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/dao/XxlJobLogGlueDao.java",
    "content": "package com.xxl.job.admin.dao;\n\nimport com.xxl.job.admin.core.model.XxlJobLogGlue;\n\nimport org.apache.ibatis.annotations.Mapper;\nimport org.apache.ibatis.annotations.Param;\n\nimport java.util.List;\n\n/**\n * job log for glue\n * @author xuxueli 2016-5-19 18:04:56\n */\n@Mapper\npublic interface XxlJobLogGlueDao {\n\t\n\tpublic int save(XxlJobLogGlue xxlJobLogGlue);\n\t\n\tpublic List<XxlJobLogGlue> findByJobId(@Param(\"jobId\") int jobId);\n\n\tpublic int removeOld(@Param(\"jobId\") int jobId, @Param(\"limit\") int limit);\n\n\tpublic int deleteByJobId(@Param(\"jobId\") int jobId);\n\t\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/dao/XxlJobLogGlueMapper.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \n\t\"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.xxl.job.admin.dao.XxlJobLogGlueDao\">\n\t\n\t<resultMap id=\"XxlJobLogGlue\" type=\"com.xxl.job.admin.core.model.XxlJobLogGlue\" >\n\t\t<result column=\"id\" property=\"id\" />\n\t    <result column=\"job_id\" property=\"jobId\" />\n\t\t<result column=\"glue_type\" property=\"glueType\" />\n\t    <result column=\"glue_source\" property=\"glueSource\" />\n\t    <result column=\"glue_remark\" property=\"glueRemark\" />\n\t    <result column=\"add_time\" property=\"addTime\" />\n\t    <result column=\"update_time\" property=\"updateTime\" />\n\t</resultMap>\n\n\t<sql id=\"Base_Column_List\">\n\t\tt.id,\n\t\tt.job_id,\n\t\tt.glue_type,\n\t\tt.glue_source,\n\t\tt.glue_remark,\n\t\tt.add_time,\n\t\tt.update_time\n\t</sql>\n\t\n\t<insert id=\"save\" parameterType=\"com.xxl.job.admin.core.model.XxlJobLogGlue\" useGeneratedKeys=\"true\" keyProperty=\"id\" >\n\t\tINSERT INTO XXL_JOB_QRTZ_TRIGGER_LOGGLUE (\n\t\t\t`job_id`,\n\t\t\t`glue_type`,\n\t\t\t`glue_source`,\n\t\t\t`glue_remark`,\n\t\t\t`add_time`, \n\t\t\t`update_time`\n\t\t) VALUES (\n\t\t\t#{jobId},\n\t\t\t#{glueType},\n\t\t\t#{glueSource},\n\t\t\t#{glueRemark},\n\t\t\tnow(),\n\t\t\tnow()\n\t\t);\n\t\t<!--<selectKey resultType=\"java.lang.Integer\" order=\"AFTER\" keyProperty=\"id\">\n\t\t\tSELECT LAST_INSERT_ID() \n\t\t</selectKey>-->\n\t</insert>\n\t\n\t<select id=\"findByJobId\" parameterType=\"java.lang.Integer\" resultMap=\"XxlJobLogGlue\">\n\t\tSELECT <include refid=\"Base_Column_List\" />\n\t\tFROM XXL_JOB_QRTZ_TRIGGER_LOGGLUE AS t\n\t\tWHERE t.job_id = #{jobId}\n\t\tORDER BY id DESC\n\t</select>\n\t\n\t<delete id=\"removeOld\" >\n\t\tDELETE FROM XXL_JOB_QRTZ_TRIGGER_LOGGLUE\n\t\tWHERE id NOT in(\n\t\t\tSELECT id FROM(\n\t\t\t\tSELECT id FROM XXL_JOB_QRTZ_TRIGGER_LOGGLUE\n\t\t\t\tWHERE `job_id` = #{jobId}\n\t\t\t\tORDER BY update_time desc\n\t\t\t\tLIMIT 0, #{limit}\n\t\t\t) t1\n\t\t) AND `job_id` = #{jobId}\n\t</delete>\n\t\n\t<delete id=\"deleteByJobId\" parameterType=\"java.lang.Integer\" >\n\t\tDELETE FROM XXL_JOB_QRTZ_TRIGGER_LOGGLUE\n\t\tWHERE `job_id` = #{jobId}\n\t</delete>\n\t\n</mapper>"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/dao/XxlJobLogMapper.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \n\t\"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.xxl.job.admin.dao.XxlJobLogDao\">\n\t\n\t<resultMap id=\"XxlJobLog\" type=\"com.xxl.job.admin.core.model.XxlJobLog\" >\n\t\t<result column=\"id\" property=\"id\" />\n\n\t\t<result column=\"job_group\" property=\"jobGroup\" />\n\t\t<result column=\"job_id\" property=\"jobId\" />\n\n\t\t<result column=\"glue_type\" property=\"glueType\" />\n\n\t\t<result column=\"executor_address\" property=\"executorAddress\" />\n\t\t<result column=\"executor_handler\" property=\"executorHandler\" />\n\t    <result column=\"executor_param\" property=\"executorParam\" />\n\t    \n\t    <result column=\"trigger_time\" property=\"triggerTime\" />\n\t    <result column=\"trigger_code\" property=\"triggerCode\" />\n\t    <result column=\"trigger_msg\" property=\"triggerMsg\" />\n\t    \n\t    <result column=\"handle_time\" property=\"handleTime\" />\n\t    <result column=\"handle_code\" property=\"handleCode\" />\n\t    <result column=\"handle_msg\" property=\"handleMsg\" />\n\t    \n\t</resultMap>\n\n\t<sql id=\"Base_Column_List\">\n\t\tt.id,\n\t\tt.job_group,\n\t\tt.job_id,\n\t\tt.glue_type,\n\t\tt.executor_address,\n\t\tt.executor_handler,\n\t\tt.executor_param,\n\t\tt.trigger_time,\n\t\tt.trigger_code,\n\t\tt.trigger_msg,\n\t\tt.handle_time,\n\t\tt.handle_code,\n\t\tt.handle_msg\n\t</sql>\n\t\n\t<select id=\"pageList\" resultMap=\"XxlJobLog\">\n\t\tSELECT <include refid=\"Base_Column_List\" />\n\t\tFROM XXL_JOB_QRTZ_TRIGGER_LOG AS t\n\t\t<trim prefix=\"WHERE\" prefixOverrides=\"AND | OR\" >\n\t\t\t<if test=\"jobGroup != null and jobGroup != ''\">\n\t\t\t\tAND t.job_group = #{jobGroup}\n\t\t\t</if>\n\t\t\t<if test=\"jobId gt 0\">\n\t\t\t\tAND t.job_id = #{jobId}\n\t\t\t</if>\n\t\t\t<if test=\"triggerTimeStart != null\">\n\t\t\t\tAND t.trigger_time <![CDATA[ >= ]]> #{triggerTimeStart}\n\t\t\t</if>\n\t\t\t<if test=\"triggerTimeEnd != null\">\n\t\t\t\tAND t.trigger_time <![CDATA[ <= ]]> #{triggerTimeEnd}\n\t\t\t</if>\n\t\t\t<if test=\"logStatus == 1\" >\n\t\t\t\tAND t.handle_code = 200\n\t\t\t</if>\n\t\t\t<if test=\"logStatus == 2\" >\n\t\t\t\tAND (\n\t\t\t\t\t(t.trigger_code <![CDATA[ > ]]> 0 AND t.trigger_code!=200) ||\n\t\t\t\t\t(t.handle_code <![CDATA[ > ]]> 0 AND t.handle_code!=200)\n\t\t\t\t)\n\t\t\t</if>\n\t\t\t<if test=\"logStatus == 3\" >\n\t\t\t\tAND (t.trigger_code = 200 AND t.handle_code=0)\n\t\t\t</if>\n\t\t</trim>\n\t\tORDER BY id DESC\n\t\tLIMIT #{offset}, #{pagesize}\n\t</select>\n\t\n\t<select id=\"pageListCount\" resultType=\"int\">\n\t\tSELECT count(1)\n\t\tFROM XXL_JOB_QRTZ_TRIGGER_LOG AS t\n\t\t<trim prefix=\"WHERE\" prefixOverrides=\"AND | OR\" >\n\t\t\t<if test=\"jobGroup != null and jobGroup != ''\">\n\t\t\t\tAND t.job_group = #{jobGroup}\n\t\t\t</if>\n\t\t\t<if test=\"jobId gt 0\">\n\t\t\t\tAND t.job_id = #{jobId}\n\t\t\t</if>\n\t\t\t<if test=\"triggerTimeStart != null\">\n\t\t\t\tAND t.trigger_time <![CDATA[ >= ]]> #{triggerTimeStart}\n\t\t\t</if>\n\t\t\t<if test=\"triggerTimeEnd != null\">\n\t\t\t\tAND t.trigger_time <![CDATA[ <= ]]> #{triggerTimeEnd}\n\t\t\t</if>\n\t\t\t<if test=\"logStatus == 1\" >\n\t\t\t\tAND t.handle_code = 200\n\t\t\t</if>\n\t\t\t<if test=\"logStatus == 2\" >\n\t\t\t\tAND (\n\t\t\t\t(t.trigger_code <![CDATA[ > ]]> 0 AND t.trigger_code!=200) ||\n\t\t\t\t(t.handle_code <![CDATA[ > ]]> 0 AND t.handle_code!=200)\n\t\t\t\t)\n\t\t\t</if>\n\t\t\t<if test=\"logStatus == 3\" >\n\t\t\t\tAND (t.trigger_code = 200 AND t.handle_code=0)\n\t\t\t</if>\n\t\t</trim>\n\t</select>\n\t\n\t<select id=\"load\" parameterType=\"java.lang.Integer\" resultMap=\"XxlJobLog\">\n\t\tSELECT <include refid=\"Base_Column_List\" />\n\t\tFROM XXL_JOB_QRTZ_TRIGGER_LOG AS t\n\t\tWHERE t.id = #{id}\n\t</select>\n\n\t\n\t<insert id=\"save\" parameterType=\"com.xxl.job.admin.core.model.XxlJobLog\" useGeneratedKeys=\"true\" keyProperty=\"id\" >\n\t\tINSERT INTO XXL_JOB_QRTZ_TRIGGER_LOG (\n\t\t\t`job_group`,\n\t\t\t`job_id`,\n\t\t\t`trigger_code`,\n\t\t\t`handle_code`\n\t\t) VALUES (\n\t\t\t#{jobGroup},\n\t\t\t#{jobId},\n\t\t\t#{triggerCode},\n\t\t\t#{handleCode}\n\t\t);\n\t\t<!--<selectKey resultType=\"java.lang.Integer\" order=\"AFTER\" keyProperty=\"id\">\n\t\t\tSELECT LAST_INSERT_ID() \n\t\t</selectKey>-->\n\t</insert>\n\n\t<update id=\"updateTriggerInfo\" >\n\t\tUPDATE XXL_JOB_QRTZ_TRIGGER_LOG\n\t\tSET\n\t\t    `glue_type`= #{glueType},\n\t\t\t`trigger_time`= #{triggerTime},\n\t\t\t`trigger_code`= #{triggerCode},\n\t\t\t`trigger_msg`= #{triggerMsg},\n\t\t\t`executor_address`= #{executorAddress},\n\t\t\t`executor_handler`=#{executorHandler},\n\t\t\t`executor_param`= #{executorParam}\n\t\tWHERE `id`= #{id}\n\t</update>\n\n\t<update id=\"updateHandleInfo\">\n\t\tUPDATE XXL_JOB_QRTZ_TRIGGER_LOG\n\t\tSET \n\t\t\t`handle_time`= #{handleTime}, \n\t\t\t`handle_code`= #{handleCode},\n\t\t\t`handle_msg`= #{handleMsg} \n\t\tWHERE `id`= #{id}\n\t</update>\n\t\n\t<delete id=\"delete\" >\n\t\tdelete from XXL_JOB_QRTZ_TRIGGER_LOG\n\t\tWHERE job_id = #{jobId}\n\t</delete>\n\n\t<select id=\"triggerCountByHandleCode\" resultType=\"int\" >\n\t\tSELECT count(1)\n\t\tFROM XXL_JOB_QRTZ_TRIGGER_LOG AS t\n\t\t<trim prefix=\"WHERE\" prefixOverrides=\"AND | OR\" >\n\t\t\t<if test=\"handleCode gt 0\">\n\t\t\t\tAND t.handle_code = #{handleCode}\n\t\t\t</if>\n\t\t</trim>\n\t</select>\n\n    <select id=\"triggerCountByDay\" resultType=\"java.util.Map\" >\n\t\tSELECT\n\t\t\tDATE_FORMAT(trigger_time,'%Y-%m-%d') triggerDay,\n\t\t\tCOUNT(handle_code) triggerDayCount,\n\t\t\tSUM(CASE WHEN handle_code = 0 then 1 else 0 end) as triggerDayCountRunning,\n\t\t\tSUM(CASE WHEN handle_code = 200 then 1 else 0 end) as triggerDayCountSuc\n\t\tFROM XXL_JOB_QRTZ_TRIGGER_LOG\n\t\tWHERE trigger_time BETWEEN #{from} and #{to}\n\t\tGROUP BY triggerDay;\n    </select>\n\n\t<delete id=\"clearLog\" >\n\t\tdelete from XXL_JOB_QRTZ_TRIGGER_LOG\n\t\t<trim prefix=\"WHERE\" prefixOverrides=\"AND | OR\" >\n\t\t\t<if test=\"jobGroup gt 0\">\n\t\t\t\tAND job_group = #{jobGroup}\n\t\t\t</if>\n\t\t\t<if test=\"jobId gt 0\">\n\t\t\t\tAND job_id = #{jobId}\n\t\t\t</if>\n\t\t\t<if test=\"clearBeforeTime != null\">\n\t\t\t\tAND trigger_time <![CDATA[ <= ]]> #{clearBeforeTime}\n\t\t\t</if>\n\t\t\t<if test=\"clearBeforeNum gt 0\">\n\t\t\t\tAND id NOT in(\n\t\t\t\t\tSELECT id FROM(\n\t\t\t\t\t\tSELECT id FROM XXL_JOB_QRTZ_TRIGGER_LOG AS t\n\t\t\t\t\t\t<trim prefix=\"WHERE\" prefixOverrides=\"AND | OR\" >\n\t\t\t\t\t\t\t<if test=\"jobGroup gt 0\">\n\t\t\t\t\t\t\t\tAND t.job_group = #{jobGroup}\n\t\t\t\t\t\t\t</if>\n\t\t\t\t\t\t\t<if test=\"jobId gt 0\">\n\t\t\t\t\t\t\t\tAND t.job_id = #{jobId}\n\t\t\t\t\t\t\t</if>\n\t\t\t\t\t\t</trim>\n\t\t\t\t\t\tORDER BY t.trigger_time desc\n\t\t\t\t\t\tLIMIT 0, #{clearBeforeNum}\n\t\t\t\t\t) t1\n\t\t\t\t)\n\t\t\t</if>\n\t\t</trim>\n\t</delete>\n\t\n</mapper>"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/dao/XxlJobRegistryDao.java",
    "content": "package com.xxl.job.admin.dao;\n\nimport com.xxl.job.admin.core.model.XxlJobRegistry;\n\nimport org.apache.ibatis.annotations.Mapper;\nimport org.apache.ibatis.annotations.Param;\n\nimport java.util.List;\n\n/**\n * Created by xuxueli on 16/9/30.\n */\n@Mapper\npublic interface XxlJobRegistryDao {\n\n    public int removeDead(@Param(\"timeout\") int timeout);\n\n    public List<XxlJobRegistry> findAll(@Param(\"timeout\") int timeout);\n\n    public int registryUpdate(@Param(\"registryGroup\") String registryGroup,\n                              @Param(\"registryKey\") String registryKey,\n                              @Param(\"registryValue\") String registryValue);\n\n    public int registrySave(@Param(\"registryGroup\") String registryGroup,\n                            @Param(\"registryKey\") String registryKey,\n                            @Param(\"registryValue\") String registryValue);\n\n    public int registryDelete(@Param(\"registryGroup\") String registGroup,\n                          @Param(\"registryKey\") String registryKey,\n                          @Param(\"registryValue\") String registryValue);\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/dao/XxlJobRegistryMapper.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \n\t\"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.xxl.job.admin.dao.XxlJobRegistryDao\">\n\t\n\t<resultMap id=\"XxlJobRegistry\" type=\"com.xxl.job.admin.core.model.XxlJobRegistry\" >\n\t\t<result column=\"id\" property=\"id\" />\n\t    <result column=\"registry_group\" property=\"registryGroup\" />\n\t    <result column=\"registry_key\" property=\"registryKey\" />\n\t    <result column=\"registry_value\" property=\"registryValue\" />\n\t\t<result column=\"update_time\" property=\"updateTime\" />\n\t</resultMap>\n\n\t<sql id=\"Base_Column_List\">\n\t\tt.id,\n\t\tt.registry_group,\n\t\tt.registry_key,\n\t\tt.registry_value,\n\t\tt.update_time\n\t</sql>\n\t\n\t<delete id=\"removeDead\" parameterType=\"java.lang.Integer\" >\n\t\tDELETE FROM XXL_JOB_QRTZ_TRIGGER_REGISTRY\n\t\tWHERE update_time <![CDATA[ < ]]> DATE_ADD(NOW(),INTERVAL -#{timeout} SECOND)\n\t</delete>\n\n\t<select id=\"findAll\" parameterType=\"java.lang.Integer\" resultMap=\"XxlJobRegistry\">\n\t\tSELECT <include refid=\"Base_Column_List\" />\n\t\tFROM XXL_JOB_QRTZ_TRIGGER_REGISTRY AS t\n\t\tWHERE t.update_time <![CDATA[ > ]]> DATE_ADD(NOW(),INTERVAL -#{timeout} SECOND)\n\t</select>\n\n    <update id=\"registryUpdate\" >\n        UPDATE XXL_JOB_QRTZ_TRIGGER_REGISTRY\n        SET `update_time` = NOW()\n        WHERE `registry_group` = #{registryGroup}\n          AND `registry_key` = #{registryKey}\n          AND `registry_value` = #{registryValue}\n    </update>\n\n    <insert id=\"registrySave\" >\n        INSERT INTO XXL_JOB_QRTZ_TRIGGER_REGISTRY( `registry_group` , `registry_key` , `registry_value`, `update_time`)\n        VALUES( #{registryGroup}  , #{registryKey} , #{registryValue}, NOW())\n    </insert>\n\n\t<delete id=\"registryDelete\" >\n\t\tDELETE FROM XXL_JOB_QRTZ_TRIGGER_REGISTRY\n\t\tWHERE registry_group = #{registryGroup}\n\t\t\tAND registry_key = #{registryKey}\n\t\t\tAND registry_value = #{registryValue}\n\t</delete>\n\n</mapper>"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/service/XxlJobService.java",
    "content": "package com.xxl.job.admin.service;\n\n\nimport com.xxl.job.admin.core.model.XxlJobInfo;\nimport com.xxl.job.core.biz.model.ReturnT;\n\nimport java.util.Date;\nimport java.util.Map;\n\n/**\n * core job action for xxl-job\n * \n * @author xuxueli 2016-5-28 15:30:33\n */\npublic interface XxlJobService {\n\n\t/**\n\t * page list\n\t *\n\t * @param start\n\t * @param length\n\t * @param jobGroup\n\t * @param jobDesc\n\t * @param executorHandler\n\t * @param filterTime\n\t * @return\n\t */\n\tpublic Map<String, Object> pageList(int start, int length, int jobGroup, String jobDesc, String executorHandler, String filterTime);\n\n\t/**\n\t * add job\n\t *\n\t * @param jobInfo\n\t * @return\n\t */\n\tpublic ReturnT<String> add(XxlJobInfo jobInfo);\n\n\t/**\n\t * update job\n\t *\n\t * @param jobInfo\n\t * @return\n\t */\n\tpublic ReturnT<String> update(XxlJobInfo jobInfo);\n\n\t/**\n\t * remove job\n\t *\n\t * @param id\n\t * @return\n\t */\n\tpublic ReturnT<String> remove(int id);\n\n\t/**\n\t * pause job\n\t *\n\t * @param id\n\t * @return\n\t */\n\tpublic ReturnT<String> pause(int id);\n\n\t/**\n\t * resume job\n\t *\n\t * @param id\n\t * @return\n\t */\n\tpublic ReturnT<String> resume(int id);\n\n\t/**\n\t * trigger job\n\t *\n\t * @param id\n\t * @return\n\t */\n\tpublic ReturnT<String> triggerJob(int id);\n\n\t/**\n\t * dashboard info\n\t *\n\t * @return\n\t */\n\tpublic Map<String,Object> dashboardInfo();\n\n\t/**\n\t * chart info\n\t *\n\t * @param startDate\n\t * @param endDate\n\t * @return\n\t */\n\tpublic ReturnT<Map<String,Object>> chartInfo(Date startDate, Date endDate);\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/service/impl/AdminBizImpl.java",
    "content": "package com.xxl.job.admin.service.impl;\n\nimport com.xxl.job.admin.core.model.XxlJobInfo;\nimport com.xxl.job.admin.core.model.XxlJobLog;\nimport com.xxl.job.admin.core.util.I18nUtil;\nimport com.xxl.job.admin.dao.XxlJobInfoDao;\nimport com.xxl.job.admin.dao.XxlJobLogDao;\nimport com.xxl.job.admin.dao.XxlJobRegistryDao;\nimport com.xxl.job.admin.service.XxlJobService;\nimport com.xxl.job.core.biz.AdminBiz;\nimport com.xxl.job.core.biz.model.HandleCallbackParam;\nimport com.xxl.job.core.biz.model.RegistryParam;\nimport com.xxl.job.core.biz.model.ReturnT;\nimport com.xxl.job.core.handler.IJobHandler;\nimport org.apache.commons.lang3.StringUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.stereotype.Service;\n\nimport javax.annotation.Resource;\nimport java.text.MessageFormat;\nimport java.util.Date;\nimport java.util.List;\n\n/**\n * @author xuxueli 2017-07-27 21:54:20\n */\n@Service\npublic class AdminBizImpl implements AdminBiz {\n    private static Logger logger = LoggerFactory.getLogger(AdminBizImpl.class);\n\n    @Resource\n    public XxlJobLogDao xxlJobLogDao;\n    @Resource\n    private XxlJobInfoDao xxlJobInfoDao;\n    @Resource\n    private XxlJobRegistryDao xxlJobRegistryDao;\n    @Resource\n    private XxlJobService xxlJobService;\n\n\n    @Override\n    public ReturnT<String> callback(List<HandleCallbackParam> callbackParamList) {\n        for (HandleCallbackParam handleCallbackParam: callbackParamList) {\n            ReturnT<String> callbackResult = callback(handleCallbackParam);\n            logger.info(\">>>>>>>>> JobApiController.callback {}, handleCallbackParam={}, callbackResult={}\",\n                    (callbackResult.getCode()==IJobHandler.SUCCESS.getCode()?\"success\":\"fail\"), handleCallbackParam, callbackResult);\n        }\n\n        return ReturnT.SUCCESS;\n    }\n\n    private ReturnT<String> callback(HandleCallbackParam handleCallbackParam) {\n        // valid log item\n        XxlJobLog log = xxlJobLogDao.load(handleCallbackParam.getLogId());\n        if (log == null) {\n            return new ReturnT<String>(ReturnT.FAIL_CODE, \"log item not found.\");\n        }\n        if (log.getHandleCode() > 0) {\n            return new ReturnT<String>(ReturnT.FAIL_CODE, \"log repeate callback.\");     // avoid repeat callback, trigger child job etc\n        }\n\n        // trigger success, to trigger child job\n        String callbackMsg = null;\n        if (IJobHandler.SUCCESS.getCode() == handleCallbackParam.getExecuteResult().getCode()) {\n            XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadById(log.getJobId());\n            if (xxlJobInfo!=null && StringUtils.isNotBlank(xxlJobInfo.getChildJobId())) {\n                callbackMsg = \"<br><br><span style=\\\"color:#00c0ef;\\\" > >>>>>>>>>>>\"+ I18nUtil.getString(\"jobconf_trigger_child_run\") +\"<<<<<<<<<<< </span><br>\";\n\n                String[] childJobIds = xxlJobInfo.getChildJobId().split(\",\");\n                for (int i = 0; i < childJobIds.length; i++) {\n                    int childJobId = (StringUtils.isNotBlank(childJobIds[i]) && StringUtils.isNumeric(childJobIds[i]))?Integer.valueOf(childJobIds[i]):-1;\n                    if (childJobId > 0) {\n                        ReturnT<String> triggerChildResult = xxlJobService.triggerJob(childJobId);\n\n                        // add msg\n                        callbackMsg += MessageFormat.format(I18nUtil.getString(\"jobconf_callback_child_msg1\"),\n                                (i+1),\n                                childJobIds.length,\n                                childJobIds[i],\n                                (triggerChildResult.getCode()==ReturnT.SUCCESS_CODE?I18nUtil.getString(\"system_success\"):I18nUtil.getString(\"system_fail\")),\n                                triggerChildResult.getMsg());\n                    } else {\n                        callbackMsg += MessageFormat.format(I18nUtil.getString(\"jobconf_callback_child_msg2\"),\n                                (i+1),\n                                childJobIds.length,\n                                childJobIds[i]);\n                    }\n                }\n\n            }\n        } else if (IJobHandler.FAIL_RETRY.getCode() == handleCallbackParam.getExecuteResult().getCode()){\n            ReturnT<String> retryTriggerResult = xxlJobService.triggerJob(log.getJobId());\n            callbackMsg = \"<br><br><span style=\\\"color:#F39C12;\\\" > >>>>>>>>>>>\"+ I18nUtil.getString(\"jobconf_exe_fail_retry\") +\"<<<<<<<<<<< </span><br>\";\n\n            callbackMsg += MessageFormat.format(I18nUtil.getString(\"jobconf_callback_msg1\"),\n                   (retryTriggerResult.getCode()==ReturnT.SUCCESS_CODE?I18nUtil.getString(\"system_success\"):I18nUtil.getString(\"system_fail\")), retryTriggerResult.getMsg());\n        }\n\n        // handle msg\n        StringBuffer handleMsg = new StringBuffer();\n        if (log.getHandleMsg()!=null) {\n            handleMsg.append(log.getHandleMsg()).append(\"<br>\");\n        }\n        if (handleCallbackParam.getExecuteResult().getMsg() != null) {\n            handleMsg.append(handleCallbackParam.getExecuteResult().getMsg());\n        }\n        if (callbackMsg != null) {\n            handleMsg.append(callbackMsg);\n        }\n\n        // success, save log\n        log.setHandleTime(new Date());\n        log.setHandleCode(handleCallbackParam.getExecuteResult().getCode());\n        log.setHandleMsg(handleMsg.toString());\n        xxlJobLogDao.updateHandleInfo(log);\n\n        return ReturnT.SUCCESS;\n    }\n\n    @Override\n    public ReturnT<String> registry(RegistryParam registryParam) {\n        int ret = xxlJobRegistryDao.registryUpdate(registryParam.getRegistGroup(), registryParam.getRegistryKey(), registryParam.getRegistryValue());\n        if (ret < 1) {\n            xxlJobRegistryDao.registrySave(registryParam.getRegistGroup(), registryParam.getRegistryKey(), registryParam.getRegistryValue());\n        }\n        return ReturnT.SUCCESS;\n    }\n\n    @Override\n    public ReturnT<String> registryRemove(RegistryParam registryParam) {\n        xxlJobRegistryDao.registryDelete(registryParam.getRegistGroup(), registryParam.getRegistryKey(), registryParam.getRegistryValue());\n        return ReturnT.SUCCESS;\n    }\n\n    @Override\n    public ReturnT<String> triggerJob(int jobId) {\n        return xxlJobService.triggerJob(jobId);\n    }\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/service/impl/XxlJobServiceImpl.java",
    "content": "package com.xxl.job.admin.service.impl;\n\nimport com.xxl.job.admin.core.enums.ExecutorFailStrategyEnum;\nimport com.xxl.job.admin.core.model.XxlJobGroup;\nimport com.xxl.job.admin.core.model.XxlJobInfo;\nimport com.xxl.job.admin.core.route.ExecutorRouteStrategyEnum;\nimport com.xxl.job.admin.core.schedule.XxlJobDynamicScheduler;\nimport com.xxl.job.admin.core.util.I18nUtil;\nimport com.xxl.job.admin.core.util.LocalCacheUtil;\nimport com.xxl.job.admin.dao.XxlJobGroupDao;\nimport com.xxl.job.admin.dao.XxlJobInfoDao;\nimport com.xxl.job.admin.dao.XxlJobLogDao;\nimport com.xxl.job.admin.dao.XxlJobLogGlueDao;\nimport com.xxl.job.admin.service.XxlJobService;\nimport com.xxl.job.core.biz.model.ReturnT;\nimport com.xxl.job.core.enums.ExecutorBlockStrategyEnum;\nimport com.xxl.job.core.glue.GlueTypeEnum;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.apache.commons.lang3.time.DateUtils;\nimport org.apache.commons.lang3.time.FastDateFormat;\nimport org.quartz.CronExpression;\nimport org.quartz.SchedulerException;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.stereotype.Service;\n\nimport javax.annotation.Resource;\nimport java.text.MessageFormat;\nimport java.util.*;\n\n/**\n * core job action for xxl-job\n * @author xuxueli 2016-5-28 15:30:33\n */\n@Service\npublic class XxlJobServiceImpl implements XxlJobService {\n\tprivate static Logger logger = LoggerFactory.getLogger(XxlJobServiceImpl.class);\n\n\t@Resource\n\tprivate XxlJobGroupDao xxlJobGroupDao;\n\t@Resource\n\tprivate XxlJobInfoDao xxlJobInfoDao;\n\t@Resource\n\tpublic XxlJobLogDao xxlJobLogDao;\n\t@Resource\n\tprivate XxlJobLogGlueDao xxlJobLogGlueDao;\n\t\n\t@Override\n\tpublic Map<String, Object> pageList(int start, int length, int jobGroup, String jobDesc, String executorHandler, String filterTime) {\n\n\t\t// page list\n\t\tList<XxlJobInfo> list = xxlJobInfoDao.pageList(start, length, jobGroup, jobDesc, executorHandler);\n\t\tint list_count = xxlJobInfoDao.pageListCount(start, length, jobGroup, jobDesc, executorHandler);\n\t\t\n\t\t// fill job info\n\t\tif (list!=null && list.size()>0) {\n\t\t\tfor (XxlJobInfo jobInfo : list) {\n\t\t\t\tXxlJobDynamicScheduler.fillJobInfo(jobInfo);\n\t\t\t}\n\t\t}\n\t\t\n\t\t// package result\n\t\tMap<String, Object> maps = new HashMap<String, Object>();\n\t    maps.put(\"recordsTotal\", list_count);\t\t// 总记录数\n\t    maps.put(\"recordsFiltered\", list_count);\t// 过滤后的总记录数\n\t    maps.put(\"data\", list);  \t\t\t\t\t// 分页列表\n\t\treturn maps;\n\t}\n\n\t@Override\n\tpublic ReturnT<String> add(XxlJobInfo jobInfo) {\n\t\t// valid\n\t\tXxlJobGroup group = xxlJobGroupDao.load(jobInfo.getJobGroup());\n\t\tif (group == null) {\n\t\t\treturn new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString(\"system_please_choose\")+I18nUtil.getString(\"jobinfo_field_jobgroup\")) );\n\t\t}\n\t\tif (!CronExpression.isValidExpression(jobInfo.getJobCron())) {\n\t\t\treturn new ReturnT<String>(ReturnT.FAIL_CODE, I18nUtil.getString(\"jobinfo_field_cron_unvalid\") );\n\t\t}\n\t\tif (StringUtils.isBlank(jobInfo.getJobDesc())) {\n\t\t\treturn new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString(\"system_please_input\")+I18nUtil.getString(\"jobinfo_field_jobdesc\")) );\n\t\t}\n\t\tif (StringUtils.isBlank(jobInfo.getAuthor())) {\n\t\t\treturn new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString(\"system_please_input\")+I18nUtil.getString(\"jobinfo_field_author\")) );\n\t\t}\n\t\tif (ExecutorRouteStrategyEnum.match(jobInfo.getExecutorRouteStrategy(), null) == null) {\n\t\t\treturn new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString(\"jobinfo_field_executorRouteStrategy\")+I18nUtil.getString(\"system_unvalid\")) );\n\t\t}\n\t\tif (ExecutorBlockStrategyEnum.match(jobInfo.getExecutorBlockStrategy(), null) == null) {\n\t\t\treturn new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString(\"jobinfo_field_executorBlockStrategy\")+I18nUtil.getString(\"system_unvalid\")) );\n\t\t}\n\t\tif (ExecutorFailStrategyEnum.match(jobInfo.getExecutorFailStrategy(), null) == null) {\n\t\t\treturn new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString(\"jobinfo_field_executorFailStrategy\")+I18nUtil.getString(\"system_unvalid\")) );\n\t\t}\n\t\tif (GlueTypeEnum.match(jobInfo.getGlueType()) == null) {\n\t\t\treturn new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString(\"jobinfo_field_gluetype\")+I18nUtil.getString(\"system_unvalid\")) );\n\t\t}\n\t\tif (GlueTypeEnum.BEAN==GlueTypeEnum.match(jobInfo.getGlueType()) && StringUtils.isBlank(jobInfo.getExecutorHandler())) {\n\t\t\treturn new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString(\"system_please_input\")+\"JobHandler\") );\n\t\t}\n\n\t\t// fix \"\\r\" in shell\n\t\tif (GlueTypeEnum.GLUE_SHELL==GlueTypeEnum.match(jobInfo.getGlueType()) && jobInfo.getGlueSource()!=null) {\n\t\t\tjobInfo.setGlueSource(jobInfo.getGlueSource().replaceAll(\"\\r\", \"\"));\n\t\t}\n\n\t\t// ChildJobId valid\n\t\tif (StringUtils.isNotBlank(jobInfo.getChildJobId())) {\n\t\t\tString[] childJobIds = StringUtils.split(jobInfo.getChildJobId(), \",\");\n\t\t\tfor (String childJobIdItem: childJobIds) {\n\t\t\t\tif (StringUtils.isNotBlank(childJobIdItem) && StringUtils.isNumeric(childJobIdItem)) {\n\t\t\t\t\tXxlJobInfo childJobInfo = xxlJobInfoDao.loadById(Integer.valueOf(childJobIdItem));\n\t\t\t\t\tif (childJobInfo==null) {\n\t\t\t\t\t\treturn new ReturnT<String>(ReturnT.FAIL_CODE,\n\t\t\t\t\t\t\t\tMessageFormat.format((I18nUtil.getString(\"jobinfo_field_childJobId\")+\"({0})\"+I18nUtil.getString(\"system_not_found\")), childJobIdItem));\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\treturn new ReturnT<String>(ReturnT.FAIL_CODE,\n\t\t\t\t\t\t\tMessageFormat.format((I18nUtil.getString(\"jobinfo_field_childJobId\")+\"({0})\"+I18nUtil.getString(\"system_unvalid\")), childJobIdItem));\n\t\t\t\t}\n\t\t\t}\n\t\t\tjobInfo.setChildJobId(StringUtils.join(childJobIds, \",\"));\n\t\t}\n\n\t\t// add in db\n\t\txxlJobInfoDao.save(jobInfo);\n\t\tif (jobInfo.getId() < 1) {\n\t\t\treturn new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString(\"jobinfo_field_add\")+I18nUtil.getString(\"system_fail\")) );\n\t\t}\n\n\t\t// add in quartz\n        String qz_group = String.valueOf(jobInfo.getJobGroup());\n        String qz_name = String.valueOf(jobInfo.getId());\n        try {\n            XxlJobDynamicScheduler.addJob(qz_name, qz_group, jobInfo.getJobCron());\n            //XxlJobDynamicScheduler.pauseJob(qz_name, qz_group);\n            return ReturnT.SUCCESS;\n        } catch (SchedulerException e) {\n            logger.error(e.getMessage(), e);\n            try {\n                xxlJobInfoDao.delete(jobInfo.getId());\n                XxlJobDynamicScheduler.removeJob(qz_name, qz_group);\n            } catch (SchedulerException e1) {\n                logger.error(e.getMessage(), e1);\n            }\n            return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString(\"jobinfo_field_add\")+I18nUtil.getString(\"system_fail\"))+\":\" + e.getMessage());\n        }\n\t}\n\n\t@Override\n\tpublic ReturnT<String> update(XxlJobInfo jobInfo) {\n\n\t\t// valid\n\t\tif (!CronExpression.isValidExpression(jobInfo.getJobCron())) {\n\t\t\treturn new ReturnT<String>(ReturnT.FAIL_CODE, I18nUtil.getString(\"jobinfo_field_cron_unvalid\") );\n\t\t}\n\t\tif (StringUtils.isBlank(jobInfo.getJobDesc())) {\n\t\t\treturn new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString(\"system_please_input\")+I18nUtil.getString(\"jobinfo_field_jobdesc\")) );\n\t\t}\n\t\tif (StringUtils.isBlank(jobInfo.getAuthor())) {\n\t\t\treturn new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString(\"system_please_input\")+I18nUtil.getString(\"jobinfo_field_author\")) );\n\t\t}\n\t\tif (ExecutorRouteStrategyEnum.match(jobInfo.getExecutorRouteStrategy(), null) == null) {\n\t\t\treturn new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString(\"jobinfo_field_executorRouteStrategy\")+I18nUtil.getString(\"system_unvalid\")) );\n\t\t}\n\t\tif (ExecutorBlockStrategyEnum.match(jobInfo.getExecutorBlockStrategy(), null) == null) {\n\t\t\treturn new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString(\"jobinfo_field_executorBlockStrategy\")+I18nUtil.getString(\"system_unvalid\")) );\n\t\t}\n\t\tif (ExecutorFailStrategyEnum.match(jobInfo.getExecutorFailStrategy(), null) == null) {\n\t\t\treturn new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString(\"jobinfo_field_executorFailStrategy\")+I18nUtil.getString(\"system_unvalid\")));\n\t\t}\n\n\t\t// ChildJobId valid\n\t\tif (StringUtils.isNotBlank(jobInfo.getChildJobId())) {\n\t\t\tString[] childJobIds = StringUtils.split(jobInfo.getChildJobId(), \",\");\n\t\t\tfor (String childJobIdItem: childJobIds) {\n\t\t\t\tif (StringUtils.isNotBlank(childJobIdItem) && StringUtils.isNumeric(childJobIdItem)) {\n\t\t\t\t\tXxlJobInfo childJobInfo = xxlJobInfoDao.loadById(Integer.valueOf(childJobIdItem));\n\t\t\t\t\tif (childJobInfo==null) {\n\t\t\t\t\t\treturn new ReturnT<String>(ReturnT.FAIL_CODE,\n\t\t\t\t\t\t\t\tMessageFormat.format((I18nUtil.getString(\"jobinfo_field_childJobId\")+\"({0})\"+I18nUtil.getString(\"system_not_found\")), childJobIdItem));\n\t\t\t\t\t}\n\t\t\t\t\t// avoid cycle relate\n\t\t\t\t\tif (childJobInfo.getId() == jobInfo.getId()) {\n\t\t\t\t\t\treturn new ReturnT<String>(ReturnT.FAIL_CODE, MessageFormat.format(I18nUtil.getString(\"jobinfo_field_childJobId_limit\"), childJobIdItem));\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\treturn new ReturnT<String>(ReturnT.FAIL_CODE,\n\t\t\t\t\t\t\tMessageFormat.format((I18nUtil.getString(\"jobinfo_field_childJobId\")+\"({0})\"+I18nUtil.getString(\"system_unvalid\")), childJobIdItem));\n\t\t\t\t}\n\t\t\t}\n\t\t\tjobInfo.setChildJobId(StringUtils.join(childJobIds, \",\"));\n\t\t}\n\n\t\t// stage job info\n\t\tXxlJobInfo exists_jobInfo = xxlJobInfoDao.loadById(jobInfo.getId());\n\t\tif (exists_jobInfo == null) {\n\t\t\treturn new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString(\"jobinfo_field_id\")+I18nUtil.getString(\"system_not_found\")) );\n\t\t}\n\t\t//String old_cron = exists_jobInfo.getJobCron();\n\n\t\texists_jobInfo.setJobCron(jobInfo.getJobCron());\n\t\texists_jobInfo.setJobDesc(jobInfo.getJobDesc());\n\t\texists_jobInfo.setAuthor(jobInfo.getAuthor());\n\t\texists_jobInfo.setAlarmEmail(jobInfo.getAlarmEmail());\n\t\texists_jobInfo.setExecutorRouteStrategy(jobInfo.getExecutorRouteStrategy());\n\t\texists_jobInfo.setExecutorHandler(jobInfo.getExecutorHandler());\n\t\texists_jobInfo.setExecutorParam(jobInfo.getExecutorParam());\n\t\texists_jobInfo.setExecutorBlockStrategy(jobInfo.getExecutorBlockStrategy());\n\t\texists_jobInfo.setExecutorFailStrategy(jobInfo.getExecutorFailStrategy());\n\t\texists_jobInfo.setChildJobId(jobInfo.getChildJobId());\n        xxlJobInfoDao.update(exists_jobInfo);\n\n\t\t// fresh quartz\n\t\tString qz_group = String.valueOf(exists_jobInfo.getJobGroup());\n\t\tString qz_name = String.valueOf(exists_jobInfo.getId());\n        try {\n            boolean ret = XxlJobDynamicScheduler.rescheduleJob(qz_group, qz_name, exists_jobInfo.getJobCron());\n            return ret?ReturnT.SUCCESS:ReturnT.FAIL;\n        } catch (SchedulerException e) {\n            logger.error(e.getMessage(), e);\n        }\n\n\t\treturn ReturnT.FAIL;\n\t}\n\n\t@Override\n\tpublic ReturnT<String> remove(int id) {\n\t\tXxlJobInfo xxlJobInfo = xxlJobInfoDao.loadById(id);\n        String group = String.valueOf(xxlJobInfo.getJobGroup());\n        String name = String.valueOf(xxlJobInfo.getId());\n\n\t\ttry {\n\t\t\tXxlJobDynamicScheduler.removeJob(name, group);\n\t\t\txxlJobInfoDao.delete(id);\n\t\t\txxlJobLogDao.delete(id);\n\t\t\txxlJobLogGlueDao.deleteByJobId(id);\n\t\t\treturn ReturnT.SUCCESS;\n\t\t} catch (SchedulerException e) {\n\t\t\tlogger.error(e.getMessage(), e);\n\t\t}\n\t\treturn ReturnT.FAIL;\n\t}\n\n\t@Override\n\tpublic ReturnT<String> pause(int id) {\n        XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadById(id);\n        String group = String.valueOf(xxlJobInfo.getJobGroup());\n        String name = String.valueOf(xxlJobInfo.getId());\n\n\t\ttry {\n            boolean ret = XxlJobDynamicScheduler.pauseJob(name, group);\t// jobStatus do not store\n            return ret?ReturnT.SUCCESS:ReturnT.FAIL;\n\t\t} catch (SchedulerException e) {\n\t\t\tlogger.error(e.getMessage(), e);\n\t\t\treturn ReturnT.FAIL;\n\t\t}\n\t}\n\n\t@Override\n\tpublic ReturnT<String> resume(int id) {\n        XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadById(id);\n        String group = String.valueOf(xxlJobInfo.getJobGroup());\n        String name = String.valueOf(xxlJobInfo.getId());\n\n\t\ttry {\n\t\t\tboolean ret = XxlJobDynamicScheduler.resumeJob(name, group);\n\t\t\treturn ret?ReturnT.SUCCESS:ReturnT.FAIL;\n\t\t} catch (SchedulerException e) {\n\t\t\tlogger.error(e.getMessage(), e);\n\t\t\treturn ReturnT.FAIL;\n\t\t}\n\t}\n\n\t@Override\n\tpublic ReturnT<String> triggerJob(int id) {\n        XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadById(id);\n        if (xxlJobInfo == null) {\n        \treturn new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString(\"jobinfo_field_id\")+I18nUtil.getString(\"system_unvalid\")) );\n\t\t}\n\n        String group = String.valueOf(xxlJobInfo.getJobGroup());\n        String name = String.valueOf(xxlJobInfo.getId());\n\n\t\ttry {\n\t\t\tXxlJobDynamicScheduler.triggerJob(name, group);\n\t\t\treturn ReturnT.SUCCESS;\n\t\t} catch (SchedulerException e) {\n\t\t\tlogger.error(e.getMessage(), e);\n\t\t\treturn new ReturnT<String>(ReturnT.FAIL_CODE, e.getMessage());\n\t\t}\n\t}\n\n\t@Override\n\tpublic Map<String, Object> dashboardInfo() {\n\n\t\tint jobInfoCount = xxlJobInfoDao.findAllCount();\n\t\tint jobLogCount = xxlJobLogDao.triggerCountByHandleCode(-1);\n\t\tint jobLogSuccessCount = xxlJobLogDao.triggerCountByHandleCode(ReturnT.SUCCESS_CODE);\n\n\t\t// executor count\n\t\tSet<String> executerAddressSet = new HashSet<String>();\n\t\tList<XxlJobGroup> groupList = xxlJobGroupDao.findAll();\n\n\t\tif (CollectionUtils.isNotEmpty(groupList)) {\n\t\t\tfor (XxlJobGroup group: groupList) {\n\t\t\t\tif (CollectionUtils.isNotEmpty(group.getRegistryList())) {\n\t\t\t\t\texecuterAddressSet.addAll(group.getRegistryList());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tint executorCount = executerAddressSet.size();\n\n\t\tMap<String, Object> dashboardMap = new HashMap<String, Object>();\n\t\tdashboardMap.put(\"jobInfoCount\", jobInfoCount);\n\t\tdashboardMap.put(\"jobLogCount\", jobLogCount);\n\t\tdashboardMap.put(\"jobLogSuccessCount\", jobLogSuccessCount);\n\t\tdashboardMap.put(\"executorCount\", executorCount);\n\t\treturn dashboardMap;\n\t}\n\n\tprivate static final String TRIGGER_CHART_DATA_CACHE = \"trigger_chart_data_cache\";\n\t@Override\n\tpublic ReturnT<Map<String, Object>> chartInfo(Date startDate, Date endDate) {\n\t\t// get cache\n\t\tString cacheKey = TRIGGER_CHART_DATA_CACHE + \"_\" + startDate.getTime() + \"_\" + endDate.getTime();\n\t\tMap<String, Object> chartInfo = (Map<String, Object>) LocalCacheUtil.get(cacheKey);\n\t\tif (chartInfo != null) {\n\t\t\treturn new ReturnT<Map<String, Object>>(chartInfo);\n\t\t}\n\n\t\t// process\n\t\tList<String> triggerDayList = new ArrayList<String>();\n\t\tList<Integer> triggerDayCountRunningList = new ArrayList<Integer>();\n\t\tList<Integer> triggerDayCountSucList = new ArrayList<Integer>();\n\t\tList<Integer> triggerDayCountFailList = new ArrayList<Integer>();\n\t\tint triggerCountRunningTotal = 0;\n\t\tint triggerCountSucTotal = 0;\n\t\tint triggerCountFailTotal = 0;\n\n\t\tList<Map<String, Object>> triggerCountMapAll = xxlJobLogDao.triggerCountByDay(startDate, endDate);\n\t\tif (CollectionUtils.isNotEmpty(triggerCountMapAll)) {\n\t\t\tfor (Map<String, Object> item: triggerCountMapAll) {\n\t\t\t\tString day = String.valueOf(item.get(\"triggerDay\"));\n\t\t\t\tint triggerDayCount = Integer.valueOf(String.valueOf(item.get(\"triggerDayCount\")));\n\t\t\t\tint triggerDayCountRunning = Integer.valueOf(String.valueOf(item.get(\"triggerDayCountRunning\")));\n\t\t\t\tint triggerDayCountSuc = Integer.valueOf(String.valueOf(item.get(\"triggerDayCountSuc\")));\n\t\t\t\tint triggerDayCountFail = triggerDayCount - triggerDayCountRunning - triggerDayCountSuc;\n\n\t\t\t\ttriggerDayList.add(day);\n\t\t\t\ttriggerDayCountRunningList.add(triggerDayCountRunning);\n\t\t\t\ttriggerDayCountSucList.add(triggerDayCountSuc);\n\t\t\t\ttriggerDayCountFailList.add(triggerDayCountFail);\n\n\t\t\t\ttriggerCountRunningTotal += triggerDayCountRunning;\n\t\t\t\ttriggerCountSucTotal += triggerDayCountSuc;\n\t\t\t\ttriggerCountFailTotal += triggerDayCountFail;\n\t\t\t}\n\t\t} else {\n            for (int i = 4; i > -1; i--) {\n                triggerDayList.add(FastDateFormat.getInstance(\"yyyy-MM-dd\").format(DateUtils.addDays(new Date(), -i)));\n                triggerDayCountSucList.add(0);\n                triggerDayCountFailList.add(0);\n            }\n\t\t}\n\n\t\tMap<String, Object> result = new HashMap<String, Object>();\n\t\tresult.put(\"triggerDayList\", triggerDayList);\n\t\tresult.put(\"triggerDayCountRunningList\", triggerDayCountRunningList);\n\t\tresult.put(\"triggerDayCountSucList\", triggerDayCountSucList);\n\t\tresult.put(\"triggerDayCountFailList\", triggerDayCountFailList);\n\n\t\tresult.put(\"triggerCountRunningTotal\", triggerCountRunningTotal);\n\t\tresult.put(\"triggerCountSucTotal\", triggerCountSucTotal);\n\t\tresult.put(\"triggerCountFailTotal\", triggerCountFailTotal);\n\n\t\t// set cache\n\t\tLocalCacheUtil.set(cacheKey, result, 60*1000);     // cache 60s\n\n\t\treturn new ReturnT<Map<String, Object>>(result);\n\t}\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/resources/application.yml",
    "content": "server:\n  port: 8888\nspring:\n  application:\n    name: xxl-job-admin\n  datasource:\n      type: com.alibaba.druid.pool.DruidDataSource\n#      driver-class-name:  oracle.jdbc.OracleDriver\n#      url: jdbc:oracle:thin:@127.0.0.1:1521:orcl\n#      username: crm_owner_user\n#      password: bss_crm_test\n#      filters: stat,wall\n################## mysql start ############################\n      driver-class-name:  com.mysql.jdbc.Driver\n      #     192.168.3.150   130.75.131.211  134.224.249.39\n      url: jdbc:mysql://134.224.249.39:3306/iyydb_job?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false\n      username: root\n      password: root\n      filters: stat,wall\n  thymeleaf: \n    cache: false\n  freemarker:\n    cache: false\n    settings:\n      template_update_delay: 0\n      default_encoding: UTF-8\n      output_encoding: UTF-8\n      locale: zh_CN\n      number_format: 0.##########     \n      date_format: yyyy-MM-dd\n      time_format: HH:mm:ss\n      datetime_format: yyyy-MM-dd HH:mm:s\n      classic_compatible: true\n      template_exception_handler: ignore  \n    \n\nmybatis:\n  config-location: classpath:mybatis.cfg.xml\n  mapper-locations: classpath*:com/xxl/**/dao/*.xml  \n \n\nlog:\n  level:\n    root: info\n    com.xxl: debug\n    com.open: debug\n  maxsize: 30MB\n\n   \n "
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/resources/i18n/message.properties",
    "content": "admin_name=任务调度中心\nadmin_name_full=分布式任务调度平台XXL-JOB\nadmin_version=1.9.2 (快照版)\n\n## system\nsystem_tips=系统提示\nsystem_ok=确定\nsystem_close=关闭\nsystem_save=保存\nsystem_cancel=取消\nsystem_search=搜索\nsystem_status=状态\nsystem_opt=操作\nsystem_please_input=请输入\nsystem_please_choose=请选择\nsystem_success=成功\nsystem_fail=失败\nsystem_add_suc=新增成功\nsystem_add_fail=新增失败\nsystem_update_suc=更新成功\nsystem_update_fail=更新失败\nsystem_all=全部\nsystem_api_error=接口异常\nsystem_show=查看\nsystem_empty=无\nsystem_opt_suc=操作成功\nsystem_opt_fail=操作失败\nsystem_opt_edit=编辑\nsystem_opt_del=删除\nsystem_unvalid=非法\nsystem_not_found=不存在\nsystem_nav=导航\n\n## daterangepicker\ndaterangepicker_ranges_recent_hour=最近一小时\ndaterangepicker_ranges_today=今日\ndaterangepicker_ranges_yesterday=昨日\ndaterangepicker_ranges_this_month=本月\ndaterangepicker_ranges_last_month=上个月\ndaterangepicker_ranges_recent_week=最近一周\ndaterangepicker_ranges_recent_month=最近一月\ndaterangepicker_custom_name=自定义\ndaterangepicker_custom_starttime=起始时间\ndaterangepicker_custom_endtime=结束时间\ndaterangepicker_custom_daysofweek=日,一,二,三,四,五,六\ndaterangepicker_custom_monthnames=一月,二月,三月,四月,五月,六月,七月,八月,九月,十月,十一月,十二月\n\n## dataTable\ndataTable_sProcessing=处理中...\ndataTable_sLengthMenu=每页 _MENU_ 条记录\ndataTable_sZeroRecords=没有匹配结果\ndataTable_sInfo=第 _PAGE_ 页 ( 总共 _PAGES_ 页，_TOTAL_ 条记录 )\ndataTable_sInfoEmpty=无记录\ndataTable_sInfoFiltered=(由 _MAX_ 项结果过滤)\ndataTable_sSearch=搜索\ndataTable_sEmptyTable=表中数据为空\ndataTable_sLoadingRecords=载入中...\ndataTable_sFirst=首页\ndataTable_sPrevious=上页\ndataTable_sNext=下页\ndataTable_sLast=末页\ndataTable_sSortAscending=: 以升序排列此列\ndataTable_sSortDescending=: 以降序排列此列\n\n## login\nlogin_btn=登录\nlogin_remember_me=记住密码\nlogin_username_placeholder=请输入登录账号\nlogin_password_placeholder=请输入登录密码\nlogin_username_empty=请输入登录账号\nlogin_username_lt_5=登录账号不应低于5位\nlogin_password_empty=请输入登录密码\nlogin_password_lt_5=登录密码不应低于5位\nlogin_success=登录成功\nlogin_fail=登录失败\nlogin_param_empty=账号或密码为空\nlogin_param_unvalid=账号或密码错误\n\n## logout\nlogout_btn=注销\nlogout_confirm=确认注销登录?\nlogout_success=注销成功\nlogout_fail=注销失败\n\n## dashboard\njob_dashboard_name=运行报表\njob_dashboard_job_num=任务数量\njob_dashboard_job_num_tip=调度中心运行的任务数量\njob_dashboard_trigger_num=调度次数\njob_dashboard_trigger_num_tip=调度中心触发的调度次数\njob_dashboard_jobgroup_num=执行器数量\njob_dashboard_jobgroup_num_tip=调度中心在线的执行器机器数量\njob_dashboard_report=调度报表\njob_dashboard_report_loaddata_fail=调度报表数据加载异常\njob_dashboard_date_report=日期分布图\njob_dashboard_rate_report=成功比例图\n\n## job info\njobinfo_name=任务管理\njobinfo_job=任务\njobinfo_field_add=新增任务\njobinfo_field_update=更新任务\njobinfo_field_id=任务ID\njobinfo_field_jobgroup=执行器\njobinfo_field_jobdesc=任务描述\njobinfo_field_gluetype=运行模式\njobinfo_field_executorparam=任务参数\njobinfo_field_cron_unvalid=Cron格式非法\njobinfo_field_author=负责人\njobinfo_field_alarmemail=报警邮件\njobinfo_field_alarmemail_placeholder=请输入报警邮件，多个邮件地址则逗号分隔\njobinfo_field_executorRouteStrategy=路由策略\njobinfo_field_childJobId=子任务ID\njobinfo_field_childJobId_limit=子任务ID({0})不可与父任务重复\njobinfo_field_childJobId_placeholder=请输入子任务的任务ID,如存在多个则逗号分隔\njobinfo_field_executorBlockStrategy=阻塞处理策略\njobinfo_field_executorFailStrategy=失败处理策略\njobinfo_script_location=脚本位置\njobinfo_shard_index=分片序号\njobinfo_shard_total=分片总数\njobinfo_opt_pause=暂停\njobinfo_opt_resume=恢复\njobinfo_opt_log=日志\njobinfo_opt_run=执行\njobinfo_glue_remark=源码备注\njobinfo_glue_remark_limit=源码备注长度限制为4~100\njobinfo_glue_rollback=版本回溯\njobinfo_glue_jobid_unvalid=任务ID非法\njobinfo_glue_gluetype_unvalid=该任务非GLUE模式\n\n## job log\njoblog_name=调度日志\njoblog_status=状态\njoblog_status_all=全部\njoblog_status_suc=成功\njoblog_status_fail=失败\njoblog_status_running=进行中\njoblog_field_triggerTime=调度时间\njoblog_field_triggerCode=调度结果\njoblog_field_triggerMsg=调度备注\njoblog_field_handleTime=执行时间\njoblog_field_handleCode=执行结果\njoblog_field_handleMsg=执行备注\njoblog_field_executorAddress=执行器地址\njoblog_clean=清理\njoblog_clean_log=日志清理\njoblog_clean_type=清理方式\njoblog_clean_type_1=清理一个月之前日志数据\njoblog_clean_type_2=清理三个月之前日志数据\njoblog_clean_type_3=清理六个月之前日志数据\njoblog_clean_type_4=清理一年之前日志数据\njoblog_clean_type_5=清理一千条以前日志数据\njoblog_clean_type_6=清理一万条以前日志数据\njoblog_clean_type_7=清理三万条以前日志数据\njoblog_clean_type_8=清理十万条以前日志数据\njoblog_clean_type_9=清理所有日志数据\njoblog_clean_type_unvalid=清理类型参数异常\njoblog_handleCode_200=成功\njoblog_handleCode_500=失败\njoblog_handleCode_501=失败重试\njoblog_kill_log=终止任务\njoblog_kill_log_limit=调度失败，无法终止日志\njoblog_kill_log_byman=人为操作主动终止\njoblog_rolling_log=执行日志\njoblog_rolling_log_refresh=刷新\njoblog_rolling_log_triggerfail=任务发起调度失败，无法查看执行日志\njoblog_rolling_log_failoften=终止请求Rolling日志,请求失败次数超上限,可刷新页面重新加载日志\njoblog_logid_unvalid=日志ID非法\n\n## job group\njobgroup_name=执行器管理\njobgroup_list=执行器列表\njobgroup_add=新增执行器\njobgroup_edit=编辑执行器\njobgroup_del=删除执行器\njobgroup_field_order=排序\njobgroup_field_title=名称\njobgroup_field_addressType=注册方式\njobgroup_field_addressType_0=自动注册\njobgroup_field_addressType_1=手动录入\njobgroup_field_addressType_limit=手动录入注册方式，机器地址不可为空\njobgroup_field_registryList=机器地址\njobgroup_field_registryList_unvalid=机器地址格式非法\njobgroup_field_registryList_placeholder=请输入执行器地址列表，多地址逗号分隔\njobgroup_field_appName_limit=限制以小写字母开头，由小写字母、数字和中划线组成\njobgroup_field_appName_length=AppName长度限制为4~64\njobgroup_field_title_length=名称长度限制为4~12\njobgroup_field_order_digits=请输入整数\njobgroup_field_orderrange=取值范围为1~1000\njobgroup_del_limit_0=拒绝删除，该执行器使用中\njobgroup_del_limit_1=拒绝删除, 系统至少保留一个执行器\n\n## job conf\njobconf_block_SERIAL_EXECUTION=单机串行\njobconf_block_DISCARD_LATER=丢弃后续调度\njobconf_block_COVER_EARLY=覆盖之前调度\njobconf_fail_alarm=失败告警\njobconf_fail_retry=失败重试\njobconf_route_first=第一个\njobconf_route_last=最后一个\njobconf_route_round=轮询\njobconf_route_random=随机\njobconf_route_consistenthash=一致性HASH\njobconf_route_lfu=最不经常使用\njobconf_route_lru=最近最久未使用\njobconf_route_failover=故障转移\njobconf_route_busyover=忙碌转移\njobconf_route_shard=分片广播\njobconf_idleBeat=空闲检测\njobconf_beat=心跳检测\njobconf_monitor=调度中心监控报警\njobconf_monitor_detail=监控告警明细\njobconf_monitor_alarm_title=告警类型\njobconf_monitor_alarm_type=调度失败\njobconf_trigger_admin_adress=调度机器\njobconf_trigger_exe_regtype=执行器-注册方式\njobconf_trigger_exe_regaddress=执行器-地址列表\njobconf_trigger_address_empty=调度失败：执行器地址为空\njobconf_trigger_run=触发调度\njobconf_trigger_child_run=触发子任务\njobconf_trigger_fail_retry=调度失败重试\njobconf_exe_fail_retry=执行失败重试\njobconf_callback_child_msg1={0}/{1} [任务ID={2}], 触发{3}, 触发备注: {4} <br>\njobconf_callback_child_msg2={0}/{1} [任务ID={2}], 触发失败, 触发备注: 任务ID格式错误 <br>\njobconf_callback_msg1=触发{0}, 触发备注: {1} <br>\n\n## help\njob_help=使用教程\njob_help_document=官方文档"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/resources/i18n/message_en.properties",
    "content": "admin_name=Scheduling Center\nadmin_name_full=Distributed Task Scheduling Platform XXL-JOB\nadmin_version=1.9.2 (SNAPSHOT)\n\n## system\nsystem_tips=System message\nsystem_ok=Confirm \nsystem_close=Close\nsystem_save=Save \nsystem_cancel=Cancel\nsystem_search=Search\nsystem_status=Status\nsystem_opt=Operate\nsystem_please_input=please input \nsystem_please_choose=please choose \nsystem_success=success\nsystem_fail=fail\nsystem_add_suc=add success\nsystem_add_fail=add fail\nsystem_update_suc=update success\nsystem_update_fail=update fail\nsystem_all=All\nsystem_api_error=net error\nsystem_show=Show\nsystem_empty=Empty\nsystem_opt_suc=operate success\nsystem_opt_fail=operate fail\nsystem_opt_edit=Edit \nsystem_opt_del=Delete \nsystem_unvalid=illegal\nsystem_not_found=not exist\nsystem_nav=Navigation\n\n## daterangepicker\ndaterangepicker_ranges_recent_hour=recent one hour\ndaterangepicker_ranges_today=today\ndaterangepicker_ranges_yesterday=yesterday\ndaterangepicker_ranges_this_month=this month\ndaterangepicker_ranges_last_month=last month\ndaterangepicker_ranges_recent_week=recent one week\ndaterangepicker_ranges_recent_month=recent one month\ndaterangepicker_custom_name=custom\ndaterangepicker_custom_starttime=start time\ndaterangepicker_custom_endtime=end time\ndaterangepicker_custom_daysofweek=Sun,Mon,Tue,Wed,Thu,Fri,Sat\ndaterangepicker_custom_monthnames=Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec\n\n## dataTable\ndataTable_sProcessing=processing...\ndataTable_sLengthMenu= _MENU_ records per page\ndataTable_sZeroRecords=No matching results\ndataTable_sInfo=page _PAGE_  ( Total _PAGES_ pages，_TOTAL_ records )\ndataTable_sInfoEmpty=No Record\ndataTable_sInfoFiltered=(Filtered by _MAX_ results)\ndataTable_sSearch=Search\ndataTable_sEmptyTable=Table data is empty\ndataTable_sLoadingRecords=Loading...\ndataTable_sFirst=FIRST PAGE\ndataTable_sPrevious=Previous Page\ndataTable_sNext=Next Page\ndataTable_sLast=LAST PAGE\ndataTable_sSortAscending=: Rank this column in ascending order\ndataTable_sSortDescending=: Rank this column in descending order\n\n## login\nlogin_btn=Login\nlogin_remember_me=Remember Me\nlogin_username_placeholder=Please enter username\nlogin_password_placeholder=Please enter password\nlogin_username_empty=Please enter username\nlogin_username_lt_5=Username length should not be less than 5\nlogin_password_empty=Please enter password\nlogin_password_lt_5=Password length should not be less than 5\nlogin_success=Login success\nlogin_fail=Login fail\nlogin_param_empty=Username or password is empty\nlogin_param_unvalid=Username or password error\n\n## logout\nlogout_btn=Logout\nlogout_confirm=Confirm logout?\nlogout_success=Logout success\nlogout_fail=Logout fail\n\n## dashboard\njob_dashboard_name=Run report\njob_dashboard_job_num=Job number\njob_dashboard_job_num_tip=The number of tasks running in the scheduling center\njob_dashboard_trigger_num=trigger number\njob_dashboard_trigger_num_tip=The number of trigger record scheduled by the scheduling center\njob_dashboard_jobgroup_num=Executor number\njob_dashboard_jobgroup_num_tip=The number of online executor machines perceived by the scheduling center\njob_dashboard_report=Scheduling report\njob_dashboard_report_loaddata_fail=Scheduling report load data error\njob_dashboard_date_report=Date distribution\njob_dashboard_rate_report=Percentage distribution\n\n## job info\njobinfo_name=Job Manage\njobinfo_job=Job\njobinfo_field_add=Add Job\njobinfo_field_update=Edit Job\njobinfo_field_id=Job ID\njobinfo_field_jobgroup=Executor\njobinfo_field_jobdesc=Job description\njobinfo_field_gluetype=GLUE Type\njobinfo_field_executorparam=Param\njobinfo_field_cron_unvalid=The Cron is illegal\njobinfo_field_author=Author\njobinfo_field_alarmemail=Alarm email\njobinfo_field_alarmemail_placeholder=Please enter alarm mail, if there are more than one comma separated\njobinfo_field_executorRouteStrategy=Route Strategy\njobinfo_field_childJobId=Child Job ID\njobinfo_field_childJobId_limit=Child job ID({0}) cannot be duplicated with the parent job.\njobinfo_field_childJobId_placeholder=Please enter the Child job ID, if there are more than one comma separated\njobinfo_field_executorBlockStrategy=Block Strategy\njobinfo_field_executorFailStrategy=Fail Strategy\njobinfo_script_location=Script location\njobinfo_shard_index=Shard index\njobinfo_shard_total=Shard total\njobinfo_opt_pause=Pause\njobinfo_opt_resume=Resume\njobinfo_opt_log=Log\njobinfo_opt_run=Run\njobinfo_glue_remark=Resource Remark\njobinfo_glue_remark_limit=Resource Remark length is limited to 4~100\njobinfo_glue_rollback=Version Backtrack\njobinfo_glue_jobid_unvalid=Job ID is illegal\njobinfo_glue_gluetype_unvalid=The job is not GLUE Type\n\n## job log\njoblog_name=Trigger Log\njoblog_status=Status\njoblog_status_all=All\njoblog_status_suc=Success\njoblog_status_fail=Fail\njoblog_status_running=Running\njoblog_field_triggerTime=Trigger Time\njoblog_field_triggerCode=Trigger Result\njoblog_field_triggerMsg=Trigger Msg\njoblog_field_handleTime=Handle Time\njoblog_field_handleCode=Handle Result\njoblog_field_handleMsg=Trigger Msg\njoblog_field_executorAddress=Executor Address\njoblog_clean=Clean\njoblog_clean_log=Clean Log\njoblog_clean_type=Clean Type\njoblog_clean_type_1=Clean up log data a month ago\njoblog_clean_type_2=Clean up log data three month ago\njoblog_clean_type_3=Clean up log data six month ago\njoblog_clean_type_4=Clean up log data a year ago\njoblog_clean_type_5=Clean up log data a thousand record ago\njoblog_clean_type_6=Clean up log data ten thousand record ago\njoblog_clean_type_7=Clean up log data thirty thousand record ago\njoblog_clean_type_8=Clean up log data hundred thousand record ago\njoblog_clean_type_9=Clean up all log data\njoblog_clean_type_unvalid=Clean type is illegal\njoblog_handleCode_200=Success\njoblog_handleCode_500=Fail\njoblog_handleCode_501=Fail retry\njoblog_kill_log=Kill Job\njoblog_kill_log_limit=Trigger Fail, can not kill job\njoblog_kill_log_byman=Manual operation to active kill job\njoblog_rolling_log=Rolling log\njoblog_rolling_log_refresh=Refresh \njoblog_rolling_log_triggerfail=The job trigger fail, can not view the rolling log\njoblog_rolling_log_failoften=The request for the Rolling log is terminated, the number of failed requests exceeds the limit, Reload the log on the refresh page\njoblog_logid_unvalid=Log ID is illegal\n\n## job group\njobgroup_name=Executor Manage\njobgroup_list=Executor List\njobgroup_add=Add Executor\njobgroup_edit=Edit Executor\njobgroup_del=Delete Executor\njobgroup_field_order=Order\njobgroup_field_title=Title\njobgroup_field_addressType=Registry Type\njobgroup_field_addressType_0=Automatic registration\njobgroup_field_addressType_1=Manual registration\njobgroup_field_addressType_limit=Manually registration type, the machine address must not be empty\njobgroup_field_registryList=machine address\njobgroup_field_registryList_unvalid=registry machine address is illegal\njobgroup_field_registryList_placeholder=Please enter the machine address, if there are more than one comma separated\njobgroup_field_appName_limit=Limit the beginning of a lowercase letter, consists of lowercase letters、number and underscores.\njobgroup_field_appName_length=AppName length is limited to 4~64\njobgroup_field_title_length=Title length is limited to 4~12\njobgroup_field_order_digits=Please enter a positive integer\njobgroup_field_orderrange=Order is limited to 1~1000\njobgroup_del_limit_0=Refuse to delete, the executor is being used\njobgroup_del_limit_1=Refuses to delete, the system retains at least one executor\n\n## job conf\njobconf_block_SERIAL_EXECUTION=Serial execution\njobconf_block_DISCARD_LATER=Discard Later\njobconf_block_COVER_EARLY=Cover Early\njobconf_fail_alarm=Fail Alarm\njobconf_fail_retry=Fail Retry\njobconf_route_first=First\njobconf_route_last=Last\njobconf_route_round=Round\njobconf_route_random=Random\njobconf_route_consistenthash=Consistent Hash\njobconf_route_lfu=Least Frequently Used\njobconf_route_lru=Least Recently Used\njobconf_route_failover=Failover\njobconf_route_busyover=Busyover\njobconf_route_shard=Sharding Broadcast\njobconf_idleBeat=Idle check\njobconf_beat=Heartbeats\njobconf_monitor=Scheduling Center monitor alarm\njobconf_monitor_detail=monitor alarm details\njobconf_monitor_alarm_title=Alarm Type\njobconf_monitor_alarm_type=Trigger Fail\njobconf_trigger_admin_adress=Trigger machine address\njobconf_trigger_exe_regtype=Execotor-Registry Type\njobconf_trigger_exe_regaddress=Execotor-Registry Address\njobconf_trigger_address_empty=Trigger Fail：registry address is empty\njobconf_trigger_run=Trigger Job\njobconf_trigger_child_run=Trigger child job\njobconf_trigger_fail_retry=Trigger fail retry\njobconf_exe_fail_retry=Handle fail retry\njobconf_callback_child_msg1={0}/{1} [Job ID={2}], Trigger {3}, Trigger msg: {4} <br>\njobconf_callback_child_msg2={0}/{1} [Job ID={2}], Trigger Fail, Trigger msg: Job ID is illegal <br>\njobconf_callback_msg1=Trigger {0}, Trigger msg: {1} <br>\n\n## help\njob_help=Tutorial\njob_help_document=Official Document"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/resources/log4j.properties",
    "content": "log4j.rootLogger=info,console,logFile\n\nlog4j.appender.console=org.apache.log4j.ConsoleAppender\nlog4j.appender.console.layout=org.apache.log4j.PatternLayout\nlog4j.appender.console.layout.ConversionPattern=%d - xxl-job-admin - %p [%c] - <%m>%n\n\nlog4j.appender.logFile=org.apache.log4j.DailyRollingFileAppender\nlog4j.appender.logFile.File=/data/applogs/xxl-job/xxl-job-admin.log\nlog4j.appender.logFile.layout=org.apache.log4j.PatternLayout\nlog4j.appender.logFile.layout.ConversionPattern=%d - xxl-job-admin - %p [%c] - <%m>%n\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/resources/log4j.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE log4j:configuration PUBLIC \"-//log4j/log4j Configuration//EN\" \"log4j.dtd\">\n<log4j:configuration xmlns:log4j=\"http://jakarta.apache.org/log4j/\" threshold=\"null\" debug=\"null\">\n\n\t<appender name=\"CONSOLE\" class=\"org.apache.log4j.ConsoleAppender\">\n\t\t<param name=\"Target\" value=\"System.out\" />\n\t\t<layout class=\"org.apache.log4j.PatternLayout\">\n            <param name=\"ConversionPattern\" value=\"%-d{yyyy-MM-dd HH:mm:ss} xxl-job-admin [%c]-[%t]-[%M]-[%L]-[%p] %m%n\"/>\n\t\t</layout>\n\t</appender>\n\t\n    <appender name=\"FILE\" class=\"org.apache.log4j.DailyRollingFileAppender\">\n        <param name=\"file\" value=\"/data/applogs/xxl-job/xxl-job-admin.log\"/>\n        <param name=\"append\" value=\"true\"/>\n        <param name=\"encoding\" value=\"UTF-8\"/>\n        <layout class=\"org.apache.log4j.PatternLayout\">\n            <param name=\"ConversionPattern\" value=\"%-d{yyyy-MM-dd HH:mm:ss} xxl-job-admin [%c]-[%t]-[%M]-[%L]-[%p] %m%n\"/>\n        </layout>\n    </appender>\n\n    <root>\n        <level value=\"INFO\" />\n        <appender-ref ref=\"CONSOLE\" />\n        <appender-ref ref=\"FILE\" />\n    </root>\n\n</log4j:configuration>"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/resources/xxl-job-admin.properties",
    "content": "\n### xxl-job email\nxxl.job.mail.host=smtp.163.com\nxxl.job.mail.port=25\nxxl.job.mail.ssl=false\nxxl.job.mail.username=ovono802302@163.com\nxxl.job.mail.password=asdfzxcv\nxxl.job.mail.sendNick=《任务调度平台XXL-JOB》\n\n### xxl-job login\nxxl.job.login.username=admin\nxxl.job.login.password=123456\n\n### xxl-job, access token\nxxl.job.accessToken=\n\n### xxl-job, i18n (default empty as chinese, \"en\" as english)\nxxl.job.i18n="
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/view/500.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<meta charset=\"UTF-8\">\n\t<title>应用程序异常 (500)</title> \n    <style type=\"text/css\"> \n        body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }\n        div.dialog {\n            width: 80%;\n            padding: 1em 4em;\n            margin: 4em auto 0 auto;\n            border: 1px solid #ccc;\n            border-right-color: #999;\n            border-bottom-color: #999;\n        }\n        h1 { font-size: 100%; color: #f00; line-height: 1.5em; }\n    </style>\n    \n</head> \n</head>\n<body> \n\n\t<div class=\"dialog\"> \n\t    <h1>应用程序异常</h1> \n\t    <p>抱歉！您访问的页面出现异常，请稍后重试或联系管理员。</p> \n\t</div>\n\n</body>\n</html>"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/view/i18n/message.properties",
    "content": "admin_name=任务调度中心\nadmin_name_full=分布式任务调度平台XXL-JOB\nadmin_version=1.9.2 (快照版)\n\n## system\nsystem_tips=系统提示\nsystem_ok=确定\nsystem_close=关闭\nsystem_save=保存\nsystem_cancel=取消\nsystem_search=搜索\nsystem_status=状态\nsystem_opt=操作\nsystem_please_input=请输入\nsystem_please_choose=请选择\nsystem_success=成功\nsystem_fail=失败\nsystem_add_suc=新增成功\nsystem_add_fail=新增失败\nsystem_update_suc=更新成功\nsystem_update_fail=更新失败\nsystem_all=全部\nsystem_api_error=接口异常\nsystem_show=查看\nsystem_empty=无\nsystem_opt_suc=操作成功\nsystem_opt_fail=操作失败\nsystem_opt_edit=编辑\nsystem_opt_del=删除\nsystem_unvalid=非法\nsystem_not_found=不存在\nsystem_nav=导航\n\n## daterangepicker\ndaterangepicker_ranges_recent_hour=最近一小时\ndaterangepicker_ranges_today=今日\ndaterangepicker_ranges_yesterday=昨日\ndaterangepicker_ranges_this_month=本月\ndaterangepicker_ranges_last_month=上个月\ndaterangepicker_ranges_recent_week=最近一周\ndaterangepicker_ranges_recent_month=最近一月\ndaterangepicker_custom_name=自定义\ndaterangepicker_custom_starttime=起始时间\ndaterangepicker_custom_endtime=结束时间\ndaterangepicker_custom_daysofweek=日,一,二,三,四,五,六\ndaterangepicker_custom_monthnames=一月,二月,三月,四月,五月,六月,七月,八月,九月,十月,十一月,十二月\n\n## dataTable\ndataTable_sProcessing=处理中...\ndataTable_sLengthMenu=每页 _MENU_ 条记录\ndataTable_sZeroRecords=没有匹配结果\ndataTable_sInfo=第 _PAGE_ 页 ( 总共 _PAGES_ 页，_TOTAL_ 条记录 )\ndataTable_sInfoEmpty=无记录\ndataTable_sInfoFiltered=(由 _MAX_ 项结果过滤)\ndataTable_sSearch=搜索\ndataTable_sEmptyTable=表中数据为空\ndataTable_sLoadingRecords=载入中...\ndataTable_sFirst=首页\ndataTable_sPrevious=上页\ndataTable_sNext=下页\ndataTable_sLast=末页\ndataTable_sSortAscending=: 以升序排列此列\ndataTable_sSortDescending=: 以降序排列此列\n\n## login\nlogin_btn=登录\nlogin_remember_me=记住密码\nlogin_username_placeholder=请输入登录账号\nlogin_password_placeholder=请输入登录密码\nlogin_username_empty=请输入登录账号\nlogin_username_lt_5=登录账号不应低于5位\nlogin_password_empty=请输入登录密码\nlogin_password_lt_5=登录密码不应低于5位\nlogin_success=登录成功\nlogin_fail=登录失败\nlogin_param_empty=账号或密码为空\nlogin_param_unvalid=账号或密码错误\n\n## logout\nlogout_btn=注销\nlogout_confirm=确认注销登录?\nlogout_success=注销成功\nlogout_fail=注销失败\n\n## dashboard\njob_dashboard_name=运行报表\njob_dashboard_job_num=任务数量\njob_dashboard_job_num_tip=调度中心运行的任务数量\njob_dashboard_trigger_num=调度次数\njob_dashboard_trigger_num_tip=调度中心触发的调度次数\njob_dashboard_jobgroup_num=执行器数量\njob_dashboard_jobgroup_num_tip=调度中心在线的执行器机器数量\njob_dashboard_report=调度报表\njob_dashboard_report_loaddata_fail=调度报表数据加载异常\njob_dashboard_date_report=日期分布图\njob_dashboard_rate_report=成功比例图\n\n## job info\njobinfo_name=任务管理\njobinfo_job=任务\njobinfo_field_add=新增任务\njobinfo_field_update=更新任务\njobinfo_field_id=任务ID\njobinfo_field_jobgroup=执行器\njobinfo_field_jobdesc=任务描述\njobinfo_field_gluetype=运行模式\njobinfo_field_executorparam=任务参数\njobinfo_field_cron_unvalid=Cron格式非法\njobinfo_field_author=负责人\njobinfo_field_alarmemail=报警邮件\njobinfo_field_alarmemail_placeholder=请输入报警邮件，多个邮件地址则逗号分隔\njobinfo_field_executorRouteStrategy=路由策略\njobinfo_field_childJobId=子任务ID\njobinfo_field_childJobId_limit=子任务ID({0})不可与父任务重复\njobinfo_field_childJobId_placeholder=请输入子任务的任务ID,如存在多个则逗号分隔\njobinfo_field_executorBlockStrategy=阻塞处理策略\njobinfo_field_executorFailStrategy=失败处理策略\njobinfo_script_location=脚本位置\njobinfo_shard_index=分片序号\njobinfo_shard_total=分片总数\njobinfo_opt_pause=暂停\njobinfo_opt_resume=恢复\njobinfo_opt_log=日志\njobinfo_opt_run=执行\njobinfo_glue_remark=源码备注\njobinfo_glue_remark_limit=源码备注长度限制为4~100\njobinfo_glue_rollback=版本回溯\njobinfo_glue_jobid_unvalid=任务ID非法\njobinfo_glue_gluetype_unvalid=该任务非GLUE模式\n\n## job log\njoblog_name=调度日志\njoblog_status=状态\njoblog_status_all=全部\njoblog_status_suc=成功\njoblog_status_fail=失败\njoblog_status_running=进行中\njoblog_field_triggerTime=调度时间\njoblog_field_triggerCode=调度结果\njoblog_field_triggerMsg=调度备注\njoblog_field_handleTime=执行时间\njoblog_field_handleCode=执行结果\njoblog_field_handleMsg=执行备注\njoblog_field_executorAddress=执行器地址\njoblog_clean=清理\njoblog_clean_log=日志清理\njoblog_clean_type=清理方式\njoblog_clean_type_1=清理一个月之前日志数据\njoblog_clean_type_2=清理三个月之前日志数据\njoblog_clean_type_3=清理六个月之前日志数据\njoblog_clean_type_4=清理一年之前日志数据\njoblog_clean_type_5=清理一千条以前日志数据\njoblog_clean_type_6=清理一万条以前日志数据\njoblog_clean_type_7=清理三万条以前日志数据\njoblog_clean_type_8=清理十万条以前日志数据\njoblog_clean_type_9=清理所有日志数据\njoblog_clean_type_unvalid=清理类型参数异常\njoblog_handleCode_200=成功\njoblog_handleCode_500=失败\njoblog_handleCode_501=失败重试\njoblog_kill_log=终止任务\njoblog_kill_log_limit=调度失败，无法终止日志\njoblog_kill_log_byman=人为操作主动终止\njoblog_rolling_log=执行日志\njoblog_rolling_log_refresh=刷新\njoblog_rolling_log_triggerfail=任务发起调度失败，无法查看执行日志\njoblog_rolling_log_failoften=终止请求Rolling日志,请求失败次数超上限,可刷新页面重新加载日志\njoblog_logid_unvalid=日志ID非法\n\n## job group\njobgroup_name=执行器管理\njobgroup_list=执行器列表\njobgroup_add=新增执行器\njobgroup_edit=编辑执行器\njobgroup_del=删除执行器\njobgroup_field_order=排序\njobgroup_field_title=名称\njobgroup_field_addressType=注册方式\njobgroup_field_addressType_0=自动注册\njobgroup_field_addressType_1=手动录入\njobgroup_field_addressType_limit=手动录入注册方式，机器地址不可为空\njobgroup_field_registryList=机器地址\njobgroup_field_registryList_unvalid=机器地址格式非法\njobgroup_field_registryList_placeholder=请输入执行器地址列表，多地址逗号分隔\njobgroup_field_appName_limit=限制以小写字母开头，由小写字母、数字和中划线组成\njobgroup_field_appName_length=AppName长度限制为4~64\njobgroup_field_title_length=名称长度限制为4~12\njobgroup_field_order_digits=请输入整数\njobgroup_field_orderrange=取值范围为1~1000\njobgroup_del_limit_0=拒绝删除，该执行器使用中\njobgroup_del_limit_1=拒绝删除, 系统至少保留一个执行器\n\n## job conf\njobconf_block_SERIAL_EXECUTION=单机串行\njobconf_block_DISCARD_LATER=丢弃后续调度\njobconf_block_COVER_EARLY=覆盖之前调度\njobconf_fail_alarm=失败告警\njobconf_fail_retry=失败重试\njobconf_route_first=第一个\njobconf_route_last=最后一个\njobconf_route_round=轮询\njobconf_route_random=随机\njobconf_route_consistenthash=一致性HASH\njobconf_route_lfu=最不经常使用\njobconf_route_lru=最近最久未使用\njobconf_route_failover=故障转移\njobconf_route_busyover=忙碌转移\njobconf_route_shard=分片广播\njobconf_idleBeat=空闲检测\njobconf_beat=心跳检测\njobconf_monitor=调度中心监控报警\njobconf_monitor_detail=监控告警明细\njobconf_monitor_alarm_title=告警类型\njobconf_monitor_alarm_type=调度失败\njobconf_trigger_admin_adress=调度机器\njobconf_trigger_exe_regtype=执行器-注册方式\njobconf_trigger_exe_regaddress=执行器-地址列表\njobconf_trigger_address_empty=调度失败：执行器地址为空\njobconf_trigger_run=触发调度\njobconf_trigger_child_run=触发子任务\njobconf_trigger_fail_retry=调度失败重试\njobconf_exe_fail_retry=执行失败重试\njobconf_callback_child_msg1={0}/{1} [任务ID={2}], 触发{3}, 触发备注: {4} <br>\njobconf_callback_child_msg2={0}/{1} [任务ID={2}], 触发失败, 触发备注: 任务ID格式错误 <br>\njobconf_callback_msg1=触发{0}, 触发备注: {1} <br>\n\n## help\njob_help=使用教程\njob_help_document=官方文档"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/view/i18n/message_en.properties",
    "content": "admin_name=Scheduling Center\nadmin_name_full=Distributed Task Scheduling Platform XXL-JOB\nadmin_version=1.9.2 (SNAPSHOT)\n\n## system\nsystem_tips=System message\nsystem_ok=Confirm \nsystem_close=Close\nsystem_save=Save \nsystem_cancel=Cancel\nsystem_search=Search\nsystem_status=Status\nsystem_opt=Operate\nsystem_please_input=please input \nsystem_please_choose=please choose \nsystem_success=success\nsystem_fail=fail\nsystem_add_suc=add success\nsystem_add_fail=add fail\nsystem_update_suc=update success\nsystem_update_fail=update fail\nsystem_all=All\nsystem_api_error=net error\nsystem_show=Show\nsystem_empty=Empty\nsystem_opt_suc=operate success\nsystem_opt_fail=operate fail\nsystem_opt_edit=Edit \nsystem_opt_del=Delete \nsystem_unvalid=illegal\nsystem_not_found=not exist\nsystem_nav=Navigation\n\n## daterangepicker\ndaterangepicker_ranges_recent_hour=recent one hour\ndaterangepicker_ranges_today=today\ndaterangepicker_ranges_yesterday=yesterday\ndaterangepicker_ranges_this_month=this month\ndaterangepicker_ranges_last_month=last month\ndaterangepicker_ranges_recent_week=recent one week\ndaterangepicker_ranges_recent_month=recent one month\ndaterangepicker_custom_name=custom\ndaterangepicker_custom_starttime=start time\ndaterangepicker_custom_endtime=end time\ndaterangepicker_custom_daysofweek=Sun,Mon,Tue,Wed,Thu,Fri,Sat\ndaterangepicker_custom_monthnames=Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec\n\n## dataTable\ndataTable_sProcessing=processing...\ndataTable_sLengthMenu= _MENU_ records per page\ndataTable_sZeroRecords=No matching results\ndataTable_sInfo=page _PAGE_  ( Total _PAGES_ pages，_TOTAL_ records )\ndataTable_sInfoEmpty=No Record\ndataTable_sInfoFiltered=(Filtered by _MAX_ results)\ndataTable_sSearch=Search\ndataTable_sEmptyTable=Table data is empty\ndataTable_sLoadingRecords=Loading...\ndataTable_sFirst=FIRST PAGE\ndataTable_sPrevious=Previous Page\ndataTable_sNext=Next Page\ndataTable_sLast=LAST PAGE\ndataTable_sSortAscending=: Rank this column in ascending order\ndataTable_sSortDescending=: Rank this column in descending order\n\n## login\nlogin_btn=Login\nlogin_remember_me=Remember Me\nlogin_username_placeholder=Please enter username\nlogin_password_placeholder=Please enter password\nlogin_username_empty=Please enter username\nlogin_username_lt_5=Username length should not be less than 5\nlogin_password_empty=Please enter password\nlogin_password_lt_5=Password length should not be less than 5\nlogin_success=Login success\nlogin_fail=Login fail\nlogin_param_empty=Username or password is empty\nlogin_param_unvalid=Username or password error\n\n## logout\nlogout_btn=Logout\nlogout_confirm=Confirm logout?\nlogout_success=Logout success\nlogout_fail=Logout fail\n\n## dashboard\njob_dashboard_name=Run report\njob_dashboard_job_num=Job number\njob_dashboard_job_num_tip=The number of tasks running in the scheduling center\njob_dashboard_trigger_num=trigger number\njob_dashboard_trigger_num_tip=The number of trigger record scheduled by the scheduling center\njob_dashboard_jobgroup_num=Executor number\njob_dashboard_jobgroup_num_tip=The number of online executor machines perceived by the scheduling center\njob_dashboard_report=Scheduling report\njob_dashboard_report_loaddata_fail=Scheduling report load data error\njob_dashboard_date_report=Date distribution\njob_dashboard_rate_report=Percentage distribution\n\n## job info\njobinfo_name=Job Manage\njobinfo_job=Job\njobinfo_field_add=Add Job\njobinfo_field_update=Edit Job\njobinfo_field_id=Job ID\njobinfo_field_jobgroup=Executor\njobinfo_field_jobdesc=Job description\njobinfo_field_gluetype=GLUE Type\njobinfo_field_executorparam=Param\njobinfo_field_cron_unvalid=The Cron is illegal\njobinfo_field_author=Author\njobinfo_field_alarmemail=Alarm email\njobinfo_field_alarmemail_placeholder=Please enter alarm mail, if there are more than one comma separated\njobinfo_field_executorRouteStrategy=Route Strategy\njobinfo_field_childJobId=Child Job ID\njobinfo_field_childJobId_limit=Child job ID({0}) cannot be duplicated with the parent job.\njobinfo_field_childJobId_placeholder=Please enter the Child job ID, if there are more than one comma separated\njobinfo_field_executorBlockStrategy=Block Strategy\njobinfo_field_executorFailStrategy=Fail Strategy\njobinfo_script_location=Script location\njobinfo_shard_index=Shard index\njobinfo_shard_total=Shard total\njobinfo_opt_pause=Pause\njobinfo_opt_resume=Resume\njobinfo_opt_log=Log\njobinfo_opt_run=Run\njobinfo_glue_remark=Resource Remark\njobinfo_glue_remark_limit=Resource Remark length is limited to 4~100\njobinfo_glue_rollback=Version Backtrack\njobinfo_glue_jobid_unvalid=Job ID is illegal\njobinfo_glue_gluetype_unvalid=The job is not GLUE Type\n\n## job log\njoblog_name=Trigger Log\njoblog_status=Status\njoblog_status_all=All\njoblog_status_suc=Success\njoblog_status_fail=Fail\njoblog_status_running=Running\njoblog_field_triggerTime=Trigger Time\njoblog_field_triggerCode=Trigger Result\njoblog_field_triggerMsg=Trigger Msg\njoblog_field_handleTime=Handle Time\njoblog_field_handleCode=Handle Result\njoblog_field_handleMsg=Trigger Msg\njoblog_field_executorAddress=Executor Address\njoblog_clean=Clean\njoblog_clean_log=Clean Log\njoblog_clean_type=Clean Type\njoblog_clean_type_1=Clean up log data a month ago\njoblog_clean_type_2=Clean up log data three month ago\njoblog_clean_type_3=Clean up log data six month ago\njoblog_clean_type_4=Clean up log data a year ago\njoblog_clean_type_5=Clean up log data a thousand record ago\njoblog_clean_type_6=Clean up log data ten thousand record ago\njoblog_clean_type_7=Clean up log data thirty thousand record ago\njoblog_clean_type_8=Clean up log data hundred thousand record ago\njoblog_clean_type_9=Clean up all log data\njoblog_clean_type_unvalid=Clean type is illegal\njoblog_handleCode_200=Success\njoblog_handleCode_500=Fail\njoblog_handleCode_501=Fail retry\njoblog_kill_log=Kill Job\njoblog_kill_log_limit=Trigger Fail, can not kill job\njoblog_kill_log_byman=Manual operation to active kill job\njoblog_rolling_log=Rolling log\njoblog_rolling_log_refresh=Refresh \njoblog_rolling_log_triggerfail=The job trigger fail, can not view the rolling log\njoblog_rolling_log_failoften=The request for the Rolling log is terminated, the number of failed requests exceeds the limit, Reload the log on the refresh page\njoblog_logid_unvalid=Log ID is illegal\n\n## job group\njobgroup_name=Executor Manage\njobgroup_list=Executor List\njobgroup_add=Add Executor\njobgroup_edit=Edit Executor\njobgroup_del=Delete Executor\njobgroup_field_order=Order\njobgroup_field_title=Title\njobgroup_field_addressType=Registry Type\njobgroup_field_addressType_0=Automatic registration\njobgroup_field_addressType_1=Manual registration\njobgroup_field_addressType_limit=Manually registration type, the machine address must not be empty\njobgroup_field_registryList=machine address\njobgroup_field_registryList_unvalid=registry machine address is illegal\njobgroup_field_registryList_placeholder=Please enter the machine address, if there are more than one comma separated\njobgroup_field_appName_limit=Limit the beginning of a lowercase letter, consists of lowercase letters、number and underscores.\njobgroup_field_appName_length=AppName length is limited to 4~64\njobgroup_field_title_length=Title length is limited to 4~12\njobgroup_field_order_digits=Please enter a positive integer\njobgroup_field_orderrange=Order is limited to 1~1000\njobgroup_del_limit_0=Refuse to delete, the executor is being used\njobgroup_del_limit_1=Refuses to delete, the system retains at least one executor\n\n## job conf\njobconf_block_SERIAL_EXECUTION=Serial execution\njobconf_block_DISCARD_LATER=Discard Later\njobconf_block_COVER_EARLY=Cover Early\njobconf_fail_alarm=Fail Alarm\njobconf_fail_retry=Fail Retry\njobconf_route_first=First\njobconf_route_last=Last\njobconf_route_round=Round\njobconf_route_random=Random\njobconf_route_consistenthash=Consistent Hash\njobconf_route_lfu=Least Frequently Used\njobconf_route_lru=Least Recently Used\njobconf_route_failover=Failover\njobconf_route_busyover=Busyover\njobconf_route_shard=Sharding Broadcast\njobconf_idleBeat=Idle check\njobconf_beat=Heartbeats\njobconf_monitor=Scheduling Center monitor alarm\njobconf_monitor_detail=monitor alarm details\njobconf_monitor_alarm_title=Alarm Type\njobconf_monitor_alarm_type=Trigger Fail\njobconf_trigger_admin_adress=Trigger machine address\njobconf_trigger_exe_regtype=Execotor-Registry Type\njobconf_trigger_exe_regaddress=Execotor-Registry Address\njobconf_trigger_address_empty=Trigger Fail：registry address is empty\njobconf_trigger_run=Trigger Job\njobconf_trigger_child_run=Trigger child job\njobconf_trigger_fail_retry=Trigger fail retry\njobconf_exe_fail_retry=Handle fail retry\njobconf_callback_child_msg1={0}/{1} [Job ID={2}], Trigger {3}, Trigger msg: {4} <br>\njobconf_callback_child_msg2={0}/{1} [Job ID={2}], Trigger Fail, Trigger msg: Job ID is illegal <br>\njobconf_callback_msg1=Trigger {0}, Trigger msg: {1} <br>\n\n## help\njob_help=Tutorial\njob_help_document=Official Document"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/view/static/adminlte/dist/css/google-local/local.google.fonts.css",
    "content": "/* vietnamese */\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: normal;\n  font-weight: 300;\n  src: local('Source Sans Pro Light'), local('SourceSansPro-Light'), url('fonts/toadOcfmlt9b38dHJxOBGD_j0nMiB9fPhg_k1wdK2h0.woff2') format('woff2');\n  unicode-range: U+0102-0103, U+1EA0-1EF1, U+20AB;\n}\n/* latin-ext */\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: normal;\n  font-weight: 300;\n  src: local('Source Sans Pro Light'), local('SourceSansPro-Light'), url('fonts/toadOcfmlt9b38dHJxOBGDRVvBvQIc1z78c__uoBcyI.woff2') format('woff2');\n  unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;\n}\n/* latin */\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: normal;\n  font-weight: 300;\n  src: local('Source Sans Pro Light'), local('SourceSansPro-Light'), url('fonts/toadOcfmlt9b38dHJxOBGOode0-EuMkY--TSyExeINg.woff2') format('woff2');\n  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;\n}\n/* vietnamese */\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: normal;\n  font-weight: 400;\n  src: local('Source Sans Pro'), local('SourceSansPro-Regular'), url('fonts/ODelI1aHBYDBqgeIAH2zlNOAHFN6BivSraYkjhveRHY.woff2') format('woff2');\n  unicode-range: U+0102-0103, U+1EA0-1EF1, U+20AB;\n}\n/* latin-ext */\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: normal;\n  font-weight: 400;\n  src: local('Source Sans Pro'), local('SourceSansPro-Regular'), url('fonts/ODelI1aHBYDBqgeIAH2zlC2Q8seG17bfDXYR_jUsrzg.woff2') format('woff2');\n  unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;\n}\n/* latin */\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: normal;\n  font-weight: 400;\n  src: local('Source Sans Pro'), local('SourceSansPro-Regular'), url('fonts/ODelI1aHBYDBqgeIAH2zlNV_2ngZ8dMf8fLgjYEouxg.woff2') format('woff2');\n  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;\n}\n/* vietnamese */\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: normal;\n  font-weight: 600;\n  src: local('Source Sans Pro Semibold'), local('SourceSansPro-Semibold'), url('fonts/toadOcfmlt9b38dHJxOBGClYwVOhDRq2vbpGRTZ7bbs.woff2') format('woff2');\n  unicode-range: U+0102-0103, U+1EA0-1EF1, U+20AB;\n}\n/* latin-ext */\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: normal;\n  font-weight: 600;\n  src: local('Source Sans Pro Semibold'), local('SourceSansPro-Semibold'), url('fonts/toadOcfmlt9b38dHJxOBGFKFh1TDTPrUZWzVp6FtpG8.woff2') format('woff2');\n  unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;\n}\n/* latin */\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: normal;\n  font-weight: 600;\n  src: local('Source Sans Pro Semibold'), local('SourceSansPro-Semibold'), url('fonts/toadOcfmlt9b38dHJxOBGCOFnW3Jk0f09zW_Yln67Ac.woff2') format('woff2');\n  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;\n}\n/* vietnamese */\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: normal;\n  font-weight: 700;\n  src: local('Source Sans Pro Bold'), local('SourceSansPro-Bold'), url('fonts/toadOcfmlt9b38dHJxOBGDovqjS_dXPZszO_XltPdNg.woff2') format('woff2');\n  unicode-range: U+0102-0103, U+1EA0-1EF1, U+20AB;\n}\n/* latin-ext */\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: normal;\n  font-weight: 700;\n  src: local('Source Sans Pro Bold'), local('SourceSansPro-Bold'), url('fonts/toadOcfmlt9b38dHJxOBGFxe-GPfKKFmiXaJ_Q0GFr8.woff2') format('woff2');\n  unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;\n}\n/* latin */\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: normal;\n  font-weight: 700;\n  src: local('Source Sans Pro Bold'), local('SourceSansPro-Bold'), url('fonts/toadOcfmlt9b38dHJxOBGEo0As1BFRXtCDhS66znb_k.woff2') format('woff2');\n  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;\n}\n/* vietnamese */\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: italic;\n  font-weight: 300;\n  src: local('Source Sans Pro Light Italic'), local('SourceSansPro-LightIt'), url('fonts/fpTVHK8qsXbIeTHTrnQH6E78GtRp3lhchupCJNw8t58.woff2') format('woff2');\n  unicode-range: U+0102-0103, U+1EA0-1EF1, U+20AB;\n}\n/* latin-ext */\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: italic;\n  font-weight: 300;\n  src: local('Source Sans Pro Light Italic'), local('SourceSansPro-LightIt'), url('fonts/fpTVHK8qsXbIeTHTrnQH6Lpx497t94oDua8KfAL9f-E.woff2') format('woff2');\n  unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;\n}\n/* latin */\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: italic;\n  font-weight: 300;\n  src: local('Source Sans Pro Light Italic'), local('SourceSansPro-LightIt'), url('fonts/fpTVHK8qsXbIeTHTrnQH6MAjkyiewWYrWZc50I8hK7I.woff2') format('woff2');\n  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;\n}\n/* vietnamese */\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: italic;\n  font-weight: 400;\n  src: local('Source Sans Pro Italic'), local('SourceSansPro-It'), url('fonts/M2Jd71oPJhLKp0zdtTvoM7YHq4FgHI02B8rPccK0FJQ.woff2') format('woff2');\n  unicode-range: U+0102-0103, U+1EA0-1EF1, U+20AB;\n}\n/* latin-ext */\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: italic;\n  font-weight: 400;\n  src: local('Source Sans Pro Italic'), local('SourceSansPro-It'), url('fonts/M2Jd71oPJhLKp0zdtTvoM40tgx99jmYGv_xzYuwd1rU.woff2') format('woff2');\n  unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;\n}\n/* latin */\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: italic;\n  font-weight: 400;\n  src: local('Source Sans Pro Italic'), local('SourceSansPro-It'), url('fonts/M2Jd71oPJhLKp0zdtTvoMxgy2Fsj5sj3EzlXpqVXRKo.woff2') format('woff2');\n  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;\n}\n/* vietnamese */\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: italic;\n  font-weight: 600;\n  src: local('Source Sans Pro Semibold Italic'), local('SourceSansPro-SemiboldIt'), url('fonts/fpTVHK8qsXbIeTHTrnQH6CzM2XYAq8cDhaXsrN8WXcA.woff2') format('woff2');\n  unicode-range: U+0102-0103, U+1EA0-1EF1, U+20AB;\n}\n/* latin-ext */\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: italic;\n  font-weight: 600;\n  src: local('Source Sans Pro Semibold Italic'), local('SourceSansPro-SemiboldIt'), url('fonts/fpTVHK8qsXbIeTHTrnQH6OXKTZYPNtG1yMB_YJSqlic.woff2') format('woff2');\n  unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;\n}\n/* latin */\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: italic;\n  font-weight: 600;\n  src: local('Source Sans Pro Semibold Italic'), local('SourceSansPro-SemiboldIt'), url('fonts/fpTVHK8qsXbIeTHTrnQH6GQKuzMuncr0JB710wa2dPI.woff2') format('woff2');\n  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/view/static/adminlte/plugins/datatables/dataTables.bootstrap.css",
    "content": "div.dataTables_length label {\n\tfont-weight: normal;\n\ttext-align: left;\n\twhite-space: nowrap;\n}\n\ndiv.dataTables_length select {\n\twidth: 75px;\n\tdisplay: inline-block;\n}\n\ndiv.dataTables_filter {\n\ttext-align: right;\n}\n\ndiv.dataTables_filter label {\n\tfont-weight: normal;\n\twhite-space: nowrap;\n\ttext-align: left;\n}\n\ndiv.dataTables_filter input {\n\tmargin-left: 0.5em;\n\tdisplay: inline-block;\n\twidth: auto;\n}\n\ndiv.dataTables_info {\n\tpadding-top: 8px;\n\twhite-space: nowrap;\n}\n\ndiv.dataTables_paginate {\n\tmargin: 0;\n\twhite-space: nowrap;\n\ttext-align: right;\n}\n\ndiv.dataTables_paginate ul.pagination {\n\tmargin: 2px 0;\n\twhite-space: nowrap;\n}\n\n@media screen and (max-width: 767px) {\n\tdiv.dataTables_wrapper > div.row > div,\n\tdiv.dataTables_length,\n\tdiv.dataTables_filter,\n\tdiv.dataTables_info,\n\tdiv.dataTables_paginate {\n\t\ttext-align: center;\n\t}\n\n\tdiv.DTTT {\n\t\tmargin-bottom: 0.5em;\n\t}\n}\n\n\ntable.dataTable td,\ntable.dataTable th {\n\t-webkit-box-sizing: content-box;\n\t-moz-box-sizing: content-box;\n\tbox-sizing: content-box;\n}\n\n\ntable.dataTable {\n\tclear: both;\n\tmargin-top: 6px !important;\n\tmargin-bottom: 6px !important;\n\tmax-width: none !important;\n}\n\ntable.dataTable thead .sorting,\ntable.dataTable thead .sorting_asc,\ntable.dataTable thead .sorting_desc,\ntable.dataTable thead .sorting_asc_disabled,\ntable.dataTable thead .sorting_desc_disabled {\n\tcursor: pointer;\n\tposition: relative;\n}\n\ntable.dataTable thead .sorting:after,\ntable.dataTable thead .sorting_asc:after,\ntable.dataTable thead .sorting_desc:after {\n\tposition: absolute;\n\ttop: 8px;\n\tright: 8px;\n\tdisplay: block;\n\tfont-family: 'Glyphicons Halflings';\n\topacity: 0.5;\n}\ntable.dataTable thead .sorting:after {\n\topacity: 0.2;\n\tcontent: \"\\e150\"; /* sort */\n}\ntable.dataTable thead .sorting_asc:after {\n\tcontent: \"\\e155\"; /* sort-by-attributes */\n}\ntable.dataTable thead .sorting_desc:after {\n\tcontent: \"\\e156\"; /* sort-by-attributes-alt */\n}\ndiv.dataTables_scrollBody table.dataTable thead .sorting:after,\ndiv.dataTables_scrollBody table.dataTable thead .sorting_asc:after,\ndiv.dataTables_scrollBody table.dataTable thead .sorting_desc:after {\n\tdisplay: none;\n}\n\ntable.dataTable thead .sorting_asc_disabled:after,\ntable.dataTable thead .sorting_desc_disabled:after {\n\tcolor: #eee;\n}\n\ntable.dataTable thead > tr > th {\n\tpadding-right: 30px;\n}\n\ntable.dataTable th:active {\n\toutline: none;\n}\n\n\n/* Condensed */\ntable.dataTable.table-condensed thead > tr > th {\n\tpadding-right: 20px;\n}\n\ntable.dataTable.table-condensed thead .sorting:after,\ntable.dataTable.table-condensed thead .sorting_asc:after,\ntable.dataTable.table-condensed thead .sorting_desc:after {\n\ttop: 6px;\n\tright: 6px;\n}\n\n/* Scrolling */\ndiv.dataTables_scrollHead table {\n\tmargin-bottom: 0 !important;\n\tborder-bottom-left-radius: 0;\n\tborder-bottom-right-radius: 0;\n}\n\ndiv.dataTables_scrollHead table thead tr:last-child th:first-child,\ndiv.dataTables_scrollHead table thead tr:last-child td:first-child {\n\tborder-bottom-left-radius: 0 !important;\n\tborder-bottom-right-radius: 0 !important;\n}\n\ndiv.dataTables_scrollBody table {\n\tborder-top: none;\n\tmargin-top: 0 !important;\n\tmargin-bottom: 0 !important;\n}\n\ndiv.dataTables_scrollBody tbody tr:first-child th,\ndiv.dataTables_scrollBody tbody tr:first-child td {\n\tborder-top: none;\n}\n\ndiv.dataTables_scrollFoot table {\n\tmargin-top: 0 !important;\n\tborder-top: none;\n}\n\n/* Frustratingly the border-collapse:collapse used by Bootstrap makes the column\n   width calculations when using scrolling impossible to align columns. We have\n   to use separate\n */\ntable.table-bordered.dataTable {\n\tborder-collapse: separate !important;\n}\ntable.table-bordered thead th,\ntable.table-bordered thead td {\n\tborder-left-width: 0;\n\tborder-top-width: 0;\n}\ntable.table-bordered tbody th,\ntable.table-bordered tbody td {\n\tborder-left-width: 0;\n\tborder-bottom-width: 0;\n}\ntable.table-bordered tfoot th,\ntable.table-bordered tfoot td {\n    border-left-width: 0;\n    border-bottom-width: 0;\n}\ntable.table-bordered th:last-child,\ntable.table-bordered td:last-child {\n\tborder-right-width: 0;\n}\ndiv.dataTables_scrollHead table.table-bordered {\n\tborder-bottom-width: 0;\n}\n\n\n\n\n/*\n * TableTools styles\n */\n.table.dataTable tbody tr.active td,\n.table.dataTable tbody tr.active th {\n\tbackground-color: #08C;\n\tcolor: white;\n}\n\n.table.dataTable tbody tr.active:hover td,\n.table.dataTable tbody tr.active:hover th {\n\tbackground-color: #0075b0 !important;\n}\n\n.table.dataTable tbody tr.active th > a,\n.table.dataTable tbody tr.active td > a {\n\tcolor: white;\n}\n\n.table-striped.dataTable tbody tr.active:nth-child(odd) td,\n.table-striped.dataTable tbody tr.active:nth-child(odd) th {\n\tbackground-color: #017ebc;\n}\n\ntable.DTTT_selectable tbody tr {\n\tcursor: pointer;\n}\n\ndiv.DTTT .btn:hover {\n\ttext-decoration: none !important;\n}\n\nul.DTTT_dropdown.dropdown-menu {\n  z-index: 2003;\n}\n\nul.DTTT_dropdown.dropdown-menu a {\n\tcolor: #333 !important; /* needed only when demo_page.css is included */\n}\n\nul.DTTT_dropdown.dropdown-menu li {\n\tposition: relative;\n}\n\nul.DTTT_dropdown.dropdown-menu li:hover a {\n\tbackground-color: #0088cc;\n\tcolor: white !important;\n}\n\ndiv.DTTT_collection_background {\n\tz-index: 2002;\t\n}\n\n/* TableTools information display */\ndiv.DTTT_print_info {\n\tposition: fixed;\n\ttop: 50%;\n\tleft: 50%;\n\twidth: 400px;\n\theight: 150px;\n\tmargin-left: -200px;\n\tmargin-top: -75px;\n\ttext-align: center;\n\tcolor: #333;\n\tpadding: 10px 30px;\n\topacity: 0.95;\n\n\tbackground-color: white;\n\tborder: 1px solid rgba(0, 0, 0, 0.2);\n\tborder-radius: 6px;\n\t\n\t-webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.5);\n\t        box-shadow: 0 3px 7px rgba(0, 0, 0, 0.5);\n}\n\ndiv.DTTT_print_info h6 {\n\tfont-weight: normal;\n\tfont-size: 28px;\n\tline-height: 28px;\n\tmargin: 1em;\n}\n\ndiv.DTTT_print_info p {\n\tfont-size: 14px;\n\tline-height: 20px;\n}\n\ndiv.dataTables_processing {\n    position: absolute;\n    top: 50%;\n    left: 50%;\n    width: 100%;\n    height: 60px;\n    margin-left: -50%;\n    margin-top: -25px;\n    padding-top: 20px;\n    padding-bottom: 20px;\n    text-align: center;\n    font-size: 1.2em;\n    background-color: white;\n    background: -webkit-gradient(linear, left top, right top, color-stop(0%, rgba(255,255,255,0)), color-stop(25%, rgba(255,255,255,0.9)), color-stop(75%, rgba(255,255,255,0.9)), color-stop(100%, rgba(255,255,255,0)));\n    background: -webkit-linear-gradient(left, rgba(255,255,255,0) 0%, rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, rgba(255,255,255,0) 100%);\n    background: -moz-linear-gradient(left, rgba(255,255,255,0) 0%, rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, rgba(255,255,255,0) 100%);\n    background: -ms-linear-gradient(left, rgba(255,255,255,0) 0%, rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, rgba(255,255,255,0) 100%);\n    background: -o-linear-gradient(left, rgba(255,255,255,0) 0%, rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, rgba(255,255,255,0) 100%);\n    background: linear-gradient(to right, rgba(255,255,255,0) 0%, rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, rgba(255,255,255,0) 100%);\n}\n\n\n\n/*\n * FixedColumns styles\n */\ndiv.DTFC_LeftHeadWrapper table,\ndiv.DTFC_LeftFootWrapper table,\ndiv.DTFC_RightHeadWrapper table,\ndiv.DTFC_RightFootWrapper table,\ntable.DTFC_Cloned tr.even {\n    background-color: white;\n    margin-bottom: 0;\n}\n \ndiv.DTFC_RightHeadWrapper table ,\ndiv.DTFC_LeftHeadWrapper table {\n\tborder-bottom: none !important;\n    margin-bottom: 0 !important;\n    border-top-right-radius: 0 !important;\n    border-bottom-left-radius: 0 !important;\n    border-bottom-right-radius: 0 !important;\n}\n \ndiv.DTFC_RightHeadWrapper table thead tr:last-child th:first-child,\ndiv.DTFC_RightHeadWrapper table thead tr:last-child td:first-child,\ndiv.DTFC_LeftHeadWrapper table thead tr:last-child th:first-child,\ndiv.DTFC_LeftHeadWrapper table thead tr:last-child td:first-child {\n    border-bottom-left-radius: 0 !important;\n    border-bottom-right-radius: 0 !important;\n}\n \ndiv.DTFC_RightBodyWrapper table,\ndiv.DTFC_LeftBodyWrapper table {\n    border-top: none;\n    margin: 0 !important;\n}\n \ndiv.DTFC_RightBodyWrapper tbody tr:first-child th,\ndiv.DTFC_RightBodyWrapper tbody tr:first-child td,\ndiv.DTFC_LeftBodyWrapper tbody tr:first-child th,\ndiv.DTFC_LeftBodyWrapper tbody tr:first-child td {\n    border-top: none;\n}\n \ndiv.DTFC_RightFootWrapper table,\ndiv.DTFC_LeftFootWrapper table {\n    border-top: none;\n    margin-top: 0 !important;\n}\n\n\ndiv.DTFC_LeftBodyWrapper table.dataTable thead .sorting:after,\ndiv.DTFC_LeftBodyWrapper table.dataTable thead .sorting_asc:after,\ndiv.DTFC_LeftBodyWrapper table.dataTable thead .sorting_desc:after,\ndiv.DTFC_RightBodyWrapper table.dataTable thead .sorting:after,\ndiv.DTFC_RightBodyWrapper table.dataTable thead .sorting_asc:after,\ndiv.DTFC_RightBodyWrapper table.dataTable thead .sorting_desc:after {\n\tdisplay: none;\n}\n\n\n/*\n * FixedHeader styles\n */\ndiv.FixedHeader_Cloned table {\n\tmargin: 0 !important\n}\n\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/view/static/adminlte/plugins/datatables/jquery.dataTables_themeroller.css",
    "content": "/*\n * Table styles\n */\ntable.dataTable {\n  width: 100%;\n  margin: 0 auto;\n  clear: both;\n  border-collapse: separate;\n  border-spacing: 0;\n  /*\n   * Header and footer styles\n   */\n  /*\n   * Body styles\n   */\n}\ntable.dataTable thead th,\ntable.dataTable thead td,\ntable.dataTable tfoot th,\ntable.dataTable tfoot td {\n  padding: 4px 10px;\n}\ntable.dataTable thead th,\ntable.dataTable tfoot th {\n  font-weight: bold;\n}\ntable.dataTable thead th:active,\ntable.dataTable thead td:active {\n  outline: none;\n}\ntable.dataTable thead .sorting_asc,\ntable.dataTable thead .sorting_desc,\ntable.dataTable thead .sorting {\n  cursor: pointer;\n  *cursor: hand;\n}\ntable.dataTable thead th div.DataTables_sort_wrapper {\n  position: relative;\n  padding-right: 10px;\n}\ntable.dataTable thead th div.DataTables_sort_wrapper span {\n  position: absolute;\n  top: 50%;\n  margin-top: -8px;\n  right: -5px;\n}\ntable.dataTable thead th.ui-state-default {\n  border-right-width: 0;\n}\ntable.dataTable thead th.ui-state-default:last-child {\n  border-right-width: 1px;\n}\ntable.dataTable tbody tr {\n  background-color: #ffffff;\n}\ntable.dataTable tbody tr.selected {\n  background-color: #B0BED9;\n}\ntable.dataTable tbody th,\ntable.dataTable tbody td {\n  padding: 8px 10px;\n}\ntable.dataTable th.center,\ntable.dataTable td.center,\ntable.dataTable td.dataTables_empty {\n  text-align: center;\n}\ntable.dataTable th.right,\ntable.dataTable td.right {\n  text-align: right;\n}\ntable.dataTable.row-border tbody th, table.dataTable.row-border tbody td, table.dataTable.display tbody th, table.dataTable.display tbody td {\n  border-top: 1px solid #ddd;\n}\ntable.dataTable.row-border tbody tr:first-child th,\ntable.dataTable.row-border tbody tr:first-child td, table.dataTable.display tbody tr:first-child th,\ntable.dataTable.display tbody tr:first-child td {\n  border-top: none;\n}\ntable.dataTable.cell-border tbody th, table.dataTable.cell-border tbody td {\n  border-top: 1px solid #ddd;\n  border-right: 1px solid #ddd;\n}\ntable.dataTable.cell-border tbody tr th:first-child,\ntable.dataTable.cell-border tbody tr td:first-child {\n  border-left: 1px solid #ddd;\n}\ntable.dataTable.cell-border tbody tr:first-child th,\ntable.dataTable.cell-border tbody tr:first-child td {\n  border-top: none;\n}\ntable.dataTable.stripe tbody tr.odd, table.dataTable.display tbody tr.odd {\n  background-color: #f9f9f9;\n}\ntable.dataTable.stripe tbody tr.odd.selected, table.dataTable.display tbody tr.odd.selected {\n  background-color: #abb9d3;\n}\ntable.dataTable.hover tbody tr:hover,\ntable.dataTable.hover tbody tr.odd:hover,\ntable.dataTable.hover tbody tr.even:hover, table.dataTable.display tbody tr:hover,\ntable.dataTable.display tbody tr.odd:hover,\ntable.dataTable.display tbody tr.even:hover {\n  background-color: whitesmoke;\n}\ntable.dataTable.hover tbody tr:hover.selected,\ntable.dataTable.hover tbody tr.odd:hover.selected,\ntable.dataTable.hover tbody tr.even:hover.selected, table.dataTable.display tbody tr:hover.selected,\ntable.dataTable.display tbody tr.odd:hover.selected,\ntable.dataTable.display tbody tr.even:hover.selected {\n  background-color: #a9b7d1;\n}\ntable.dataTable.order-column tbody tr > .sorting_1,\ntable.dataTable.order-column tbody tr > .sorting_2,\ntable.dataTable.order-column tbody tr > .sorting_3, table.dataTable.display tbody tr > .sorting_1,\ntable.dataTable.display tbody tr > .sorting_2,\ntable.dataTable.display tbody tr > .sorting_3 {\n  background-color: #f9f9f9;\n}\ntable.dataTable.order-column tbody tr.selected > .sorting_1,\ntable.dataTable.order-column tbody tr.selected > .sorting_2,\ntable.dataTable.order-column tbody tr.selected > .sorting_3, table.dataTable.display tbody tr.selected > .sorting_1,\ntable.dataTable.display tbody tr.selected > .sorting_2,\ntable.dataTable.display tbody tr.selected > .sorting_3 {\n  background-color: #acbad4;\n}\ntable.dataTable.display tbody tr.odd > .sorting_1, table.dataTable.order-column.stripe tbody tr.odd > .sorting_1 {\n  background-color: #f1f1f1;\n}\ntable.dataTable.display tbody tr.odd > .sorting_2, table.dataTable.order-column.stripe tbody tr.odd > .sorting_2 {\n  background-color: #f3f3f3;\n}\ntable.dataTable.display tbody tr.odd > .sorting_3, table.dataTable.order-column.stripe tbody tr.odd > .sorting_3 {\n  background-color: whitesmoke;\n}\ntable.dataTable.display tbody tr.odd.selected > .sorting_1, table.dataTable.order-column.stripe tbody tr.odd.selected > .sorting_1 {\n  background-color: #a6b3cd;\n}\ntable.dataTable.display tbody tr.odd.selected > .sorting_2, table.dataTable.order-column.stripe tbody tr.odd.selected > .sorting_2 {\n  background-color: #a7b5ce;\n}\ntable.dataTable.display tbody tr.odd.selected > .sorting_3, table.dataTable.order-column.stripe tbody tr.odd.selected > .sorting_3 {\n  background-color: #a9b6d0;\n}\ntable.dataTable.display tbody tr.even > .sorting_1, table.dataTable.order-column.stripe tbody tr.even > .sorting_1 {\n  background-color: #f9f9f9;\n}\ntable.dataTable.display tbody tr.even > .sorting_2, table.dataTable.order-column.stripe tbody tr.even > .sorting_2 {\n  background-color: #fbfbfb;\n}\ntable.dataTable.display tbody tr.even > .sorting_3, table.dataTable.order-column.stripe tbody tr.even > .sorting_3 {\n  background-color: #fdfdfd;\n}\ntable.dataTable.display tbody tr.even.selected > .sorting_1, table.dataTable.order-column.stripe tbody tr.even.selected > .sorting_1 {\n  background-color: #acbad4;\n}\ntable.dataTable.display tbody tr.even.selected > .sorting_2, table.dataTable.order-column.stripe tbody tr.even.selected > .sorting_2 {\n  background-color: #adbbd6;\n}\ntable.dataTable.display tbody tr.even.selected > .sorting_3, table.dataTable.order-column.stripe tbody tr.even.selected > .sorting_3 {\n  background-color: #afbdd8;\n}\ntable.dataTable.display tbody tr:hover > .sorting_1,\ntable.dataTable.display tbody tr.odd:hover > .sorting_1,\ntable.dataTable.display tbody tr.even:hover > .sorting_1, table.dataTable.order-column.hover tbody tr:hover > .sorting_1,\ntable.dataTable.order-column.hover tbody tr.odd:hover > .sorting_1,\ntable.dataTable.order-column.hover tbody tr.even:hover > .sorting_1 {\n  background-color: #eaeaea;\n}\ntable.dataTable.display tbody tr:hover > .sorting_2,\ntable.dataTable.display tbody tr.odd:hover > .sorting_2,\ntable.dataTable.display tbody tr.even:hover > .sorting_2, table.dataTable.order-column.hover tbody tr:hover > .sorting_2,\ntable.dataTable.order-column.hover tbody tr.odd:hover > .sorting_2,\ntable.dataTable.order-column.hover tbody tr.even:hover > .sorting_2 {\n  background-color: #ebebeb;\n}\ntable.dataTable.display tbody tr:hover > .sorting_3,\ntable.dataTable.display tbody tr.odd:hover > .sorting_3,\ntable.dataTable.display tbody tr.even:hover > .sorting_3, table.dataTable.order-column.hover tbody tr:hover > .sorting_3,\ntable.dataTable.order-column.hover tbody tr.odd:hover > .sorting_3,\ntable.dataTable.order-column.hover tbody tr.even:hover > .sorting_3 {\n  background-color: #eeeeee;\n}\ntable.dataTable.display tbody tr:hover.selected > .sorting_1,\ntable.dataTable.display tbody tr.odd:hover.selected > .sorting_1,\ntable.dataTable.display tbody tr.even:hover.selected > .sorting_1, table.dataTable.order-column.hover tbody tr:hover.selected > .sorting_1,\ntable.dataTable.order-column.hover tbody tr.odd:hover.selected > .sorting_1,\ntable.dataTable.order-column.hover tbody tr.even:hover.selected > .sorting_1 {\n  background-color: #a1aec7;\n}\ntable.dataTable.display tbody tr:hover.selected > .sorting_2,\ntable.dataTable.display tbody tr.odd:hover.selected > .sorting_2,\ntable.dataTable.display tbody tr.even:hover.selected > .sorting_2, table.dataTable.order-column.hover tbody tr:hover.selected > .sorting_2,\ntable.dataTable.order-column.hover tbody tr.odd:hover.selected > .sorting_2,\ntable.dataTable.order-column.hover tbody tr.even:hover.selected > .sorting_2 {\n  background-color: #a2afc8;\n}\ntable.dataTable.display tbody tr:hover.selected > .sorting_3,\ntable.dataTable.display tbody tr.odd:hover.selected > .sorting_3,\ntable.dataTable.display tbody tr.even:hover.selected > .sorting_3, table.dataTable.order-column.hover tbody tr:hover.selected > .sorting_3,\ntable.dataTable.order-column.hover tbody tr.odd:hover.selected > .sorting_3,\ntable.dataTable.order-column.hover tbody tr.even:hover.selected > .sorting_3 {\n  background-color: #a4b2cb;\n}\ntable.dataTable.nowrap th, table.dataTable.nowrap td {\n  white-space: nowrap;\n}\ntable.dataTable.compact thead th,\ntable.dataTable.compact thead td {\n  padding: 5px 9px;\n}\ntable.dataTable.compact tfoot th,\ntable.dataTable.compact tfoot td {\n  padding: 5px 9px 3px 9px;\n}\ntable.dataTable.compact tbody th,\ntable.dataTable.compact tbody td {\n  padding: 4px 5px;\n}\ntable.dataTable th.dt-left,\ntable.dataTable td.dt-left {\n  text-align: left;\n}\ntable.dataTable th.dt-center,\ntable.dataTable td.dt-center,\ntable.dataTable td.dataTables_empty {\n  text-align: center;\n}\ntable.dataTable th.dt-right,\ntable.dataTable td.dt-right {\n  text-align: right;\n}\ntable.dataTable th.dt-justify,\ntable.dataTable td.dt-justify {\n  text-align: justify;\n}\ntable.dataTable th.dt-nowrap,\ntable.dataTable td.dt-nowrap {\n  white-space: nowrap;\n}\ntable.dataTable thead th.dt-head-left,\ntable.dataTable thead td.dt-head-left,\ntable.dataTable tfoot th.dt-head-left,\ntable.dataTable tfoot td.dt-head-left {\n  text-align: left;\n}\ntable.dataTable thead th.dt-head-center,\ntable.dataTable thead td.dt-head-center,\ntable.dataTable tfoot th.dt-head-center,\ntable.dataTable tfoot td.dt-head-center {\n  text-align: center;\n}\ntable.dataTable thead th.dt-head-right,\ntable.dataTable thead td.dt-head-right,\ntable.dataTable tfoot th.dt-head-right,\ntable.dataTable tfoot td.dt-head-right {\n  text-align: right;\n}\ntable.dataTable thead th.dt-head-justify,\ntable.dataTable thead td.dt-head-justify,\ntable.dataTable tfoot th.dt-head-justify,\ntable.dataTable tfoot td.dt-head-justify {\n  text-align: justify;\n}\ntable.dataTable thead th.dt-head-nowrap,\ntable.dataTable thead td.dt-head-nowrap,\ntable.dataTable tfoot th.dt-head-nowrap,\ntable.dataTable tfoot td.dt-head-nowrap {\n  white-space: nowrap;\n}\ntable.dataTable tbody th.dt-body-left,\ntable.dataTable tbody td.dt-body-left {\n  text-align: left;\n}\ntable.dataTable tbody th.dt-body-center,\ntable.dataTable tbody td.dt-body-center {\n  text-align: center;\n}\ntable.dataTable tbody th.dt-body-right,\ntable.dataTable tbody td.dt-body-right {\n  text-align: right;\n}\ntable.dataTable tbody th.dt-body-justify,\ntable.dataTable tbody td.dt-body-justify {\n  text-align: justify;\n}\ntable.dataTable tbody th.dt-body-nowrap,\ntable.dataTable tbody td.dt-body-nowrap {\n  white-space: nowrap;\n}\n\ntable.dataTable,\ntable.dataTable th,\ntable.dataTable td {\n  -webkit-box-sizing: content-box;\n  -moz-box-sizing: content-box;\n  box-sizing: content-box;\n}\n\n/*\n * Control feature layout\n */\n.dataTables_wrapper {\n  position: relative;\n  clear: both;\n  *zoom: 1;\n  zoom: 1;\n}\n.dataTables_wrapper .dataTables_length {\n  float: left;\n}\n.dataTables_wrapper .dataTables_filter {\n  float: right;\n  text-align: right;\n}\n.dataTables_wrapper .dataTables_filter input {\n  margin-left: 0.5em;\n}\n.dataTables_wrapper .dataTables_info {\n  clear: both;\n  float: left;\n  padding-top: 0.55em;\n}\n.dataTables_wrapper .dataTables_paginate {\n  float: right;\n  text-align: right;\n}\n.dataTables_wrapper .dataTables_paginate .fg-button {\n  box-sizing: border-box;\n  display: inline-block;\n  min-width: 1.5em;\n  padding: 0.5em;\n  margin-left: 2px;\n  text-align: center;\n  text-decoration: none !important;\n  cursor: pointer;\n  *cursor: hand;\n  color: #333 !important;\n  border: 1px solid transparent;\n}\n.dataTables_wrapper .dataTables_paginate .fg-button:active {\n  outline: none;\n}\n.dataTables_wrapper .dataTables_paginate .fg-button:first-child {\n  border-top-left-radius: 3px;\n  border-bottom-left-radius: 3px;\n}\n.dataTables_wrapper .dataTables_paginate .fg-button:last-child {\n  border-top-right-radius: 3px;\n  border-bottom-right-radius: 3px;\n}\n.dataTables_wrapper .dataTables_processing {\n  position: absolute;\n  top: 50%;\n  left: 50%;\n  width: 100%;\n  height: 40px;\n  margin-left: -50%;\n  margin-top: -25px;\n  padding-top: 20px;\n  text-align: center;\n  font-size: 1.2em;\n  background-color: white;\n  background: -webkit-gradient(linear, left top, right top, color-stop(0%, rgba(255, 255, 255, 0)), color-stop(25%, rgba(255, 255, 255, 0.9)), color-stop(75%, rgba(255, 255, 255, 0.9)), color-stop(100%, rgba(255, 255, 255, 0)));\n  /* Chrome,Safari4+ */\n  background: -webkit-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);\n  /* Chrome10+,Safari5.1+ */\n  background: -moz-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);\n  /* FF3.6+ */\n  background: -ms-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);\n  /* IE10+ */\n  background: -o-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);\n  /* Opera 11.10+ */\n  background: linear-gradient(to right, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);\n  /* W3C */\n}\n.dataTables_wrapper .dataTables_length,\n.dataTables_wrapper .dataTables_filter,\n.dataTables_wrapper .dataTables_info,\n.dataTables_wrapper .dataTables_processing,\n.dataTables_wrapper .dataTables_paginate {\n  color: #333;\n}\n.dataTables_wrapper .dataTables_scroll {\n  clear: both;\n}\n.dataTables_wrapper .dataTables_scrollBody {\n  *margin-top: -1px;\n  -webkit-overflow-scrolling: touch;\n}\n.dataTables_wrapper .ui-widget-header {\n  font-weight: normal;\n}\n.dataTables_wrapper .ui-toolbar {\n  padding: 8px;\n}\n.dataTables_wrapper:after {\n  visibility: hidden;\n  display: block;\n  content: \"\";\n  clear: both;\n  height: 0;\n}\n\n@media screen and (max-width: 767px) {\n  .dataTables_wrapper .dataTables_length,\n  .dataTables_wrapper .dataTables_filter,\n  .dataTables_wrapper .dataTables_info,\n  .dataTables_wrapper .dataTables_paginate {\n    float: none;\n    text-align: center;\n  }\n  .dataTables_wrapper .dataTables_filter,\n  .dataTables_wrapper .dataTables_paginate {\n    margin-top: 0.5em;\n  }\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/view/static/adminlte/plugins/daterangepicker/daterangepicker.css",
    "content": ".daterangepicker {\n  position: absolute;\n  color: inherit;\n  background: #fff;\n  border-radius: 4px;\n  width: 278px;\n  padding: 4px;\n  margin-top: 1px;\n  top: 100px;\n  left: 20px;\n  /* Calendars */ }\n  .daterangepicker:before, .daterangepicker:after {\n    position: absolute;\n    display: inline-block;\n    border-bottom-color: rgba(0, 0, 0, 0.2);\n    content: ''; }\n  .daterangepicker:before {\n    top: -7px;\n    border-right: 7px solid transparent;\n    border-left: 7px solid transparent;\n    border-bottom: 7px solid #ccc; }\n  .daterangepicker:after {\n    top: -6px;\n    border-right: 6px solid transparent;\n    border-bottom: 6px solid #fff;\n    border-left: 6px solid transparent; }\n  .daterangepicker.opensleft:before {\n    right: 9px; }\n  .daterangepicker.opensleft:after {\n    right: 10px; }\n  .daterangepicker.openscenter:before {\n    left: 0;\n    right: 0;\n    width: 0;\n    margin-left: auto;\n    margin-right: auto; }\n  .daterangepicker.openscenter:after {\n    left: 0;\n    right: 0;\n    width: 0;\n    margin-left: auto;\n    margin-right: auto; }\n  .daterangepicker.opensright:before {\n    left: 9px; }\n  .daterangepicker.opensright:after {\n    left: 10px; }\n  .daterangepicker.dropup {\n    margin-top: -5px; }\n    .daterangepicker.dropup:before {\n      top: initial;\n      bottom: -7px;\n      border-bottom: initial;\n      border-top: 7px solid #ccc; }\n    .daterangepicker.dropup:after {\n      top: initial;\n      bottom: -6px;\n      border-bottom: initial;\n      border-top: 6px solid #fff; }\n  .daterangepicker.dropdown-menu {\n    max-width: none;\n    z-index: 3001; }\n  .daterangepicker.single .ranges, .daterangepicker.single .calendar {\n    float: none; }\n  .daterangepicker.show-calendar .calendar {\n    display: block; }\n  .daterangepicker .calendar {\n    display: none;\n    max-width: 270px;\n    margin: 4px; }\n    .daterangepicker .calendar.single .calendar-table {\n      border: none; }\n    .daterangepicker .calendar th, .daterangepicker .calendar td {\n      white-space: nowrap;\n      text-align: center;\n      min-width: 32px; }\n  .daterangepicker .calendar-table {\n    border: 1px solid #fff;\n    padding: 4px;\n    border-radius: 4px;\n    background: #fff; }\n  .daterangepicker table {\n    width: 100%;\n    margin: 0; }\n  .daterangepicker td, .daterangepicker th {\n    text-align: center;\n    width: 20px;\n    height: 20px;\n    border-radius: 4px;\n    border: 1px solid transparent;\n    white-space: nowrap;\n    cursor: pointer; }\n    .daterangepicker td.available:hover, .daterangepicker th.available:hover {\n      background: #eee; }\n    .daterangepicker td.week, .daterangepicker th.week {\n      font-size: 80%;\n      color: #ccc; }\n  .daterangepicker td.off, .daterangepicker td.off.in-range, .daterangepicker td.off.start-date, .daterangepicker td.off.end-date {\n    background-color: #fff;\n    border-color: transparent;\n    color: #999; }\n  .daterangepicker td.in-range {\n    background-color: #ebf4f8;\n    border-color: transparent;\n    color: #000;\n    border-radius: 0; }\n  .daterangepicker td.start-date {\n    border-radius: 4px 0 0 4px; }\n  .daterangepicker td.end-date {\n    border-radius: 0 4px 4px 0; }\n  .daterangepicker td.start-date.end-date {\n    border-radius: 4px; }\n  .daterangepicker td.active, .daterangepicker td.active:hover {\n    background-color: #357ebd;\n    border-color: transparent;\n    color: #fff; }\n  .daterangepicker th.month {\n    width: auto; }\n  .daterangepicker td.disabled, .daterangepicker option.disabled {\n    color: #999;\n    cursor: not-allowed;\n    text-decoration: line-through; }\n  .daterangepicker select.monthselect, .daterangepicker select.yearselect {\n    font-size: 12px;\n    padding: 1px;\n    height: auto;\n    margin: 0;\n    cursor: default; }\n  .daterangepicker select.monthselect {\n    margin-right: 2%;\n    width: 56%; }\n  .daterangepicker select.yearselect {\n    width: 40%; }\n  .daterangepicker select.hourselect, .daterangepicker select.minuteselect, .daterangepicker select.secondselect, .daterangepicker select.ampmselect {\n    width: 50px;\n    margin-bottom: 0; }\n  .daterangepicker .input-mini {\n    border: 1px solid #ccc;\n    border-radius: 4px;\n    color: #555;\n    height: 30px;\n    line-height: 30px;\n    display: block;\n    vertical-align: middle;\n    margin: 0 0 5px 0;\n    padding: 0 6px 0 28px;\n    width: 100%; }\n    .daterangepicker .input-mini.active {\n      border: 1px solid #08c;\n      border-radius: 4px; }\n  .daterangepicker .daterangepicker_input {\n    position: relative; }\n    .daterangepicker .daterangepicker_input i {\n      position: absolute;\n      left: 8px;\n      top: 8px; }\n  .daterangepicker .calendar-time {\n    text-align: center;\n    margin: 5px auto;\n    line-height: 30px;\n    position: relative;\n    padding-left: 28px; }\n    .daterangepicker .calendar-time select.disabled {\n      color: #ccc;\n      cursor: not-allowed; }\n\n.ranges {\n  font-size: 11px;\n  float: none;\n  margin: 4px;\n  text-align: left; }\n  .ranges ul {\n    list-style: none;\n    margin: 0 auto;\n    padding: 0;\n    width: 100%; }\n  .ranges li {\n    font-size: 13px;\n    background: #f5f5f5;\n    border: 1px solid #f5f5f5;\n    border-radius: 4px;\n    color: #08c;\n    padding: 3px 12px;\n    margin-bottom: 8px;\n    cursor: pointer; }\n    .ranges li:hover {\n      background: #08c;\n      border: 1px solid #08c;\n      color: #fff; }\n    .ranges li.active {\n      background: #08c;\n      border: 1px solid #08c;\n      color: #fff; }\n\n/*  Larger Screen Styling */\n@media (min-width: 564px) {\n  .daterangepicker {\n    width: auto; }\n    .daterangepicker .ranges ul {\n      width: 160px; }\n    .daterangepicker.single .ranges ul {\n      width: 100%; }\n    .daterangepicker.single .calendar.left {\n      clear: none; }\n    .daterangepicker.single .ranges, .daterangepicker.single .calendar {\n      float: left; }\n    .daterangepicker .calendar.left {\n      clear: left;\n      margin-right: 0; }\n      .daterangepicker .calendar.left .calendar-table {\n        border-right: none;\n        border-top-right-radius: 0;\n        border-bottom-right-radius: 0; }\n    .daterangepicker .calendar.right {\n      margin-left: 0; }\n      .daterangepicker .calendar.right .calendar-table {\n        border-left: none;\n        border-top-left-radius: 0;\n        border-bottom-left-radius: 0; }\n    .daterangepicker .left .daterangepicker_input {\n      padding-right: 12px; }\n    .daterangepicker .calendar.left .calendar-table {\n      padding-right: 12px; }\n    .daterangepicker .ranges, .daterangepicker .calendar {\n      float: left; } }\n\n@media (min-width: 730px) {\n  .daterangepicker .ranges {\n    width: auto;\n    float: left; }\n  .daterangepicker .calendar.left {\n    clear: none; } }\n\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/view/static/adminlte/plugins/daterangepicker/daterangepicker.js",
    "content": "/**\n* @version: 2.1.19\n* @author: Dan Grossman http://www.dangrossman.info/\n* @copyright: Copyright (c) 2012-2015 Dan Grossman. All rights reserved.\n* @license: Licensed under the MIT license. See http://www.opensource.org/licenses/mit-license.php\n* @website: https://www.improvely.com/\n*/\n\n(function(root, factory) {\n\n  if (typeof define === 'function' && define.amd) {\n    define(['moment', 'jquery', 'exports'], function(momentjs, $, exports) {\n      root.daterangepicker = factory(root, exports, momentjs, $);\n    });\n\n  } else if (typeof exports !== 'undefined') {\n      var momentjs = require('moment');\n      var jQuery = (typeof window != 'undefined') ? window.jQuery : undefined;  //isomorphic issue\n      if (!jQuery) {\n          try {\n              jQuery = require('jquery');\n              if (!jQuery.fn) jQuery.fn = {}; //isomorphic issue\n          } catch (err) {\n              if (!jQuery) throw new Error('jQuery dependency not found');\n          }\n      }\n\n    factory(root, exports, momentjs, jQuery);\n\n  // Finally, as a browser global.\n  } else {\n    root.daterangepicker = factory(root, {}, root.moment || moment, (root.jQuery || root.Zepto || root.ender || root.$));\n  }\n\n}(this || {}, function(root, daterangepicker, moment, $) { // 'this' doesn't exist on a server\n\n    var DateRangePicker = function(element, options, cb) {\n\n        //default settings for options\n        this.parentEl = 'body';\n        this.element = $(element);\n        this.startDate = moment().startOf('day');\n        this.endDate = moment().endOf('day');\n        this.minDate = false;\n        this.maxDate = false;\n        this.dateLimit = false;\n        this.autoApply = false;\n        this.singleDatePicker = false;\n        this.showDropdowns = false;\n        this.showWeekNumbers = false;\n        this.showISOWeekNumbers = false;\n        this.timePicker = false;\n        this.timePicker24Hour = false;\n        this.timePickerIncrement = 1;\n        this.timePickerSeconds = false;\n        this.linkedCalendars = true;\n        this.autoUpdateInput = true;\n        this.alwaysShowCalendars = false;\n        this.ranges = {};\n\n        this.opens = 'right';\n        if (this.element.hasClass('pull-right'))\n            this.opens = 'left';\n\n        this.drops = 'down';\n        if (this.element.hasClass('dropup'))\n            this.drops = 'up';\n\n        this.buttonClasses = 'btn btn-sm';\n        this.applyClass = 'btn-success';\n        this.cancelClass = 'btn-default';\n\n        this.locale = {\n            format: 'MM/DD/YYYY',\n            separator: ' - ',\n            applyLabel: 'Apply',\n            cancelLabel: 'Cancel',\n            weekLabel: 'W',\n            customRangeLabel: 'Custom Range',\n            daysOfWeek: moment.weekdaysMin(),\n            monthNames: moment.monthsShort(),\n            firstDay: moment.localeData().firstDayOfWeek()\n        };\n\n        this.callback = function() { };\n\n        //some state information\n        this.isShowing = false;\n        this.leftCalendar = {};\n        this.rightCalendar = {};\n\n        //custom options from user\n        if (typeof options !== 'object' || options === null)\n            options = {};\n\n        //allow setting options with data attributes\n        //data-api options will be overwritten with custom javascript options\n        options = $.extend(this.element.data(), options);\n\n        //html template for the picker UI\n        if (typeof options.template !== 'string' && !(options.template instanceof $))\n            options.template = '<div class=\"daterangepicker dropdown-menu\">' +\n                '<div class=\"calendar left\">' +\n                    '<div class=\"daterangepicker_input\">' +\n                      '<input class=\"input-mini\" type=\"text\" name=\"daterangepicker_start\" value=\"\" />' +\n                      '<i class=\"fa fa-calendar glyphicon glyphicon-calendar\"></i>' +\n                      '<div class=\"calendar-time\">' +\n                        '<div></div>' +\n                        '<i class=\"fa fa-clock-o glyphicon glyphicon-time\"></i>' +\n                      '</div>' +\n                    '</div>' +\n                    '<div class=\"calendar-table\"></div>' +\n                '</div>' +\n                '<div class=\"calendar right\">' +\n                    '<div class=\"daterangepicker_input\">' +\n                      '<input class=\"input-mini\" type=\"text\" name=\"daterangepicker_end\" value=\"\" />' +\n                      '<i class=\"fa fa-calendar glyphicon glyphicon-calendar\"></i>' +\n                      '<div class=\"calendar-time\">' +\n                        '<div></div>' +\n                        '<i class=\"fa fa-clock-o glyphicon glyphicon-time\"></i>' +\n                      '</div>' +\n                    '</div>' +\n                    '<div class=\"calendar-table\"></div>' +\n                '</div>' +\n                '<div class=\"ranges\">' +\n                    '<div class=\"range_inputs\">' +\n                        '<button class=\"applyBtn\" disabled=\"disabled\" type=\"button\"></button> ' +\n                        '<button class=\"cancelBtn\" type=\"button\"></button>' +\n                    '</div>' +\n                '</div>' +\n            '</div>';\n\n        this.parentEl = (options.parentEl && $(options.parentEl).length) ? $(options.parentEl) : $(this.parentEl);\n        this.container = $(options.template).appendTo(this.parentEl);\n\n        //\n        // handle all the possible options overriding defaults\n        //\n\n        if (typeof options.locale === 'object') {\n\n            if (typeof options.locale.format === 'string')\n                this.locale.format = options.locale.format;\n\n            if (typeof options.locale.separator === 'string')\n                this.locale.separator = options.locale.separator;\n\n            if (typeof options.locale.daysOfWeek === 'object')\n                this.locale.daysOfWeek = options.locale.daysOfWeek.slice();\n\n            if (typeof options.locale.monthNames === 'object')\n              this.locale.monthNames = options.locale.monthNames.slice();\n\n            if (typeof options.locale.firstDay === 'number')\n              this.locale.firstDay = options.locale.firstDay;\n\n            if (typeof options.locale.applyLabel === 'string')\n              this.locale.applyLabel = options.locale.applyLabel;\n\n            if (typeof options.locale.cancelLabel === 'string')\n              this.locale.cancelLabel = options.locale.cancelLabel;\n\n            if (typeof options.locale.weekLabel === 'string')\n              this.locale.weekLabel = options.locale.weekLabel;\n\n            if (typeof options.locale.customRangeLabel === 'string')\n              this.locale.customRangeLabel = options.locale.customRangeLabel;\n\n        }\n\n        if (typeof options.startDate === 'string')\n            this.startDate = moment(options.startDate, this.locale.format);\n\n        if (typeof options.endDate === 'string')\n            this.endDate = moment(options.endDate, this.locale.format);\n\n        if (typeof options.minDate === 'string')\n            this.minDate = moment(options.minDate, this.locale.format);\n\n        if (typeof options.maxDate === 'string')\n            this.maxDate = moment(options.maxDate, this.locale.format);\n\n        if (typeof options.startDate === 'object')\n            this.startDate = moment(options.startDate);\n\n        if (typeof options.endDate === 'object')\n            this.endDate = moment(options.endDate);\n\n        if (typeof options.minDate === 'object')\n            this.minDate = moment(options.minDate);\n\n        if (typeof options.maxDate === 'object')\n            this.maxDate = moment(options.maxDate);\n\n        // sanity check for bad options\n        if (this.minDate && this.startDate.isBefore(this.minDate))\n            this.startDate = this.minDate.clone();\n\n        // sanity check for bad options\n        if (this.maxDate && this.endDate.isAfter(this.maxDate))\n            this.endDate = this.maxDate.clone();\n\n        if (typeof options.applyClass === 'string')\n            this.applyClass = options.applyClass;\n\n        if (typeof options.cancelClass === 'string')\n            this.cancelClass = options.cancelClass;\n\n        if (typeof options.dateLimit === 'object')\n            this.dateLimit = options.dateLimit;\n\n        if (typeof options.opens === 'string')\n            this.opens = options.opens;\n\n        if (typeof options.drops === 'string')\n            this.drops = options.drops;\n\n        if (typeof options.showWeekNumbers === 'boolean')\n            this.showWeekNumbers = options.showWeekNumbers;\n\n        if (typeof options.showISOWeekNumbers === 'boolean')\n            this.showISOWeekNumbers = options.showISOWeekNumbers;\n\n        if (typeof options.buttonClasses === 'string')\n            this.buttonClasses = options.buttonClasses;\n\n        if (typeof options.buttonClasses === 'object')\n            this.buttonClasses = options.buttonClasses.join(' ');\n\n        if (typeof options.showDropdowns === 'boolean')\n            this.showDropdowns = options.showDropdowns;\n\n        if (typeof options.singleDatePicker === 'boolean') {\n            this.singleDatePicker = options.singleDatePicker;\n            if (this.singleDatePicker)\n                this.endDate = this.startDate.clone();\n        }\n\n        if (typeof options.timePicker === 'boolean')\n            this.timePicker = options.timePicker;\n\n        if (typeof options.timePickerSeconds === 'boolean')\n            this.timePickerSeconds = options.timePickerSeconds;\n\n        if (typeof options.timePickerIncrement === 'number')\n            this.timePickerIncrement = options.timePickerIncrement;\n\n        if (typeof options.timePicker24Hour === 'boolean')\n            this.timePicker24Hour = options.timePicker24Hour;\n\n        if (typeof options.autoApply === 'boolean')\n            this.autoApply = options.autoApply;\n\n        if (typeof options.autoUpdateInput === 'boolean')\n            this.autoUpdateInput = options.autoUpdateInput;\n\n        if (typeof options.linkedCalendars === 'boolean')\n            this.linkedCalendars = options.linkedCalendars;\n\n        if (typeof options.isInvalidDate === 'function')\n            this.isInvalidDate = options.isInvalidDate;\n\n        if (typeof options.alwaysShowCalendars === 'boolean')\n            this.alwaysShowCalendars = options.alwaysShowCalendars;\n\n        // update day names order to firstDay\n        if (this.locale.firstDay != 0) {\n            var iterator = this.locale.firstDay;\n            while (iterator > 0) {\n                this.locale.daysOfWeek.push(this.locale.daysOfWeek.shift());\n                iterator--;\n            }\n        }\n\n        var start, end, range;\n\n        //if no start/end dates set, check if an input element contains initial values\n        if (typeof options.startDate === 'undefined' && typeof options.endDate === 'undefined') {\n            if ($(this.element).is('input[type=text]')) {\n                var val = $(this.element).val(),\n                    split = val.split(this.locale.separator);\n\n                start = end = null;\n\n                if (split.length == 2) {\n                    start = moment(split[0], this.locale.format);\n                    end = moment(split[1], this.locale.format);\n                } else if (this.singleDatePicker && val !== \"\") {\n                    start = moment(val, this.locale.format);\n                    end = moment(val, this.locale.format);\n                }\n                if (start !== null && end !== null) {\n                    this.setStartDate(start);\n                    this.setEndDate(end);\n                }\n            }\n        }\n\n        if (typeof options.ranges === 'object') {\n            for (range in options.ranges) {\n\n                if (typeof options.ranges[range][0] === 'string')\n                    start = moment(options.ranges[range][0], this.locale.format);\n                else\n                    start = moment(options.ranges[range][0]);\n\n                if (typeof options.ranges[range][1] === 'string')\n                    end = moment(options.ranges[range][1], this.locale.format);\n                else\n                    end = moment(options.ranges[range][1]);\n\n                // If the start or end date exceed those allowed by the minDate or dateLimit\n                // options, shorten the range to the allowable period.\n                if (this.minDate && start.isBefore(this.minDate))\n                    start = this.minDate.clone();\n\n                var maxDate = this.maxDate;\n                if (this.dateLimit && start.clone().add(this.dateLimit).isAfter(maxDate))\n                    maxDate = start.clone().add(this.dateLimit);\n                if (maxDate && end.isAfter(maxDate))\n                    end = maxDate.clone();\n\n                // If the end of the range is before the minimum or the start of the range is\n                // after the maximum, don't display this range option at all.\n                if ((this.minDate && end.isBefore(this.minDate)) || (maxDate && start.isAfter(maxDate)))\n                    continue;\n                \n                //Support unicode chars in the range names.\n                var elem = document.createElement('textarea');\n                elem.innerHTML = range;\n                var rangeHtml = elem.value;\n\n                this.ranges[rangeHtml] = [start, end];\n            }\n\n            var list = '<ul>';\n            for (range in this.ranges) {\n                list += '<li>' + range + '</li>';\n            }\n            list += '<li>' + this.locale.customRangeLabel + '</li>';\n            list += '</ul>';\n            this.container.find('.ranges').prepend(list);\n        }\n\n        if (typeof cb === 'function') {\n            this.callback = cb;\n        }\n\n        if (!this.timePicker) {\n            this.startDate = this.startDate.startOf('day');\n            this.endDate = this.endDate.endOf('day');\n            this.container.find('.calendar-time').hide();\n        }\n\n        //can't be used together for now\n        if (this.timePicker && this.autoApply)\n            this.autoApply = false;\n\n        if (this.autoApply && typeof options.ranges !== 'object') {\n            this.container.find('.ranges').hide();\n        } else if (this.autoApply) {\n            this.container.find('.applyBtn, .cancelBtn').addClass('hide');\n        }\n\n        if (this.singleDatePicker) {\n            this.container.addClass('single');\n            this.container.find('.calendar.left').addClass('single');\n            this.container.find('.calendar.left').show();\n            this.container.find('.calendar.right').hide();\n            this.container.find('.daterangepicker_input input, .daterangepicker_input i').hide();\n            if (!this.timePicker) {\n                this.container.find('.ranges').hide();\n            }\n        }\n\n        if ((typeof options.ranges === 'undefined' && !this.singleDatePicker) || this.alwaysShowCalendars) {\n            this.container.addClass('show-calendar');\n        }\n\n        this.container.addClass('opens' + this.opens);\n\n        //swap the position of the predefined ranges if opens right\n        if (typeof options.ranges !== 'undefined' && this.opens == 'right') {\n            var ranges = this.container.find('.ranges');\n            var html = ranges.clone();\n            ranges.remove();\n            this.container.find('.calendar.left').parent().prepend(html);\n        }\n\n        //apply CSS classes and labels to buttons\n        this.container.find('.applyBtn, .cancelBtn').addClass(this.buttonClasses);\n        if (this.applyClass.length)\n            this.container.find('.applyBtn').addClass(this.applyClass);\n        if (this.cancelClass.length)\n            this.container.find('.cancelBtn').addClass(this.cancelClass);\n        this.container.find('.applyBtn').html(this.locale.applyLabel);\n        this.container.find('.cancelBtn').html(this.locale.cancelLabel);\n\n        //\n        // event listeners\n        //\n\n        this.container.find('.calendar')\n            .on('click.daterangepicker', '.prev', $.proxy(this.clickPrev, this))\n            .on('click.daterangepicker', '.next', $.proxy(this.clickNext, this))\n            .on('click.daterangepicker', 'td.available', $.proxy(this.clickDate, this))\n            .on('mouseenter.daterangepicker', 'td.available', $.proxy(this.hoverDate, this))\n            .on('mouseleave.daterangepicker', 'td.available', $.proxy(this.updateFormInputs, this))\n            .on('change.daterangepicker', 'select.yearselect', $.proxy(this.monthOrYearChanged, this))\n            .on('change.daterangepicker', 'select.monthselect', $.proxy(this.monthOrYearChanged, this))\n            .on('change.daterangepicker', 'select.hourselect,select.minuteselect,select.secondselect,select.ampmselect', $.proxy(this.timeChanged, this))\n            .on('click.daterangepicker', '.daterangepicker_input input', $.proxy(this.showCalendars, this))\n            //.on('keyup.daterangepicker', '.daterangepicker_input input', $.proxy(this.formInputsChanged, this))\n            .on('change.daterangepicker', '.daterangepicker_input input', $.proxy(this.formInputsChanged, this));\n\n        this.container.find('.ranges')\n            .on('click.daterangepicker', 'button.applyBtn', $.proxy(this.clickApply, this))\n            .on('click.daterangepicker', 'button.cancelBtn', $.proxy(this.clickCancel, this))\n            .on('click.daterangepicker', 'li', $.proxy(this.clickRange, this))\n            .on('mouseenter.daterangepicker', 'li', $.proxy(this.hoverRange, this))\n            .on('mouseleave.daterangepicker', 'li', $.proxy(this.updateFormInputs, this));\n\n        if (this.element.is('input')) {\n            this.element.on({\n                'click.daterangepicker': $.proxy(this.show, this),\n                'focus.daterangepicker': $.proxy(this.show, this),\n                'keyup.daterangepicker': $.proxy(this.elementChanged, this),\n                'keydown.daterangepicker': $.proxy(this.keydown, this)\n            });\n        } else {\n            this.element.on('click.daterangepicker', $.proxy(this.toggle, this));\n        }\n\n        //\n        // if attached to a text input, set the initial value\n        //\n\n        if (this.element.is('input') && !this.singleDatePicker && this.autoUpdateInput) {\n            this.element.val(this.startDate.format(this.locale.format) + this.locale.separator + this.endDate.format(this.locale.format));\n            this.element.trigger('change');\n        } else if (this.element.is('input') && this.autoUpdateInput) {\n            this.element.val(this.startDate.format(this.locale.format));\n            this.element.trigger('change');\n        }\n\n    };\n\n    DateRangePicker.prototype = {\n\n        constructor: DateRangePicker,\n\n        setStartDate: function(startDate) {\n            if (typeof startDate === 'string')\n                this.startDate = moment(startDate, this.locale.format);\n\n            if (typeof startDate === 'object')\n                this.startDate = moment(startDate);\n\n            if (!this.timePicker)\n                this.startDate = this.startDate.startOf('day');\n\n            if (this.timePicker && this.timePickerIncrement)\n                this.startDate.minute(Math.round(this.startDate.minute() / this.timePickerIncrement) * this.timePickerIncrement);\n\n            if (this.minDate && this.startDate.isBefore(this.minDate))\n                this.startDate = this.minDate;\n\n            if (this.maxDate && this.startDate.isAfter(this.maxDate))\n                this.startDate = this.maxDate;\n\n            if (!this.isShowing)\n                this.updateElement();\n\n            this.updateMonthsInView();\n        },\n\n        setEndDate: function(endDate) {\n            if (typeof endDate === 'string')\n                this.endDate = moment(endDate, this.locale.format);\n\n            if (typeof endDate === 'object')\n                this.endDate = moment(endDate);\n\n            if (!this.timePicker)\n                this.endDate = this.endDate.endOf('day');\n\n            if (this.timePicker && this.timePickerIncrement)\n                this.endDate.minute(Math.round(this.endDate.minute() / this.timePickerIncrement) * this.timePickerIncrement);\n\n            if (this.endDate.isBefore(this.startDate))\n                this.endDate = this.startDate.clone();\n\n            if (this.maxDate && this.endDate.isAfter(this.maxDate))\n                this.endDate = this.maxDate;\n\n            if (this.dateLimit && this.startDate.clone().add(this.dateLimit).isBefore(this.endDate))\n                this.endDate = this.startDate.clone().add(this.dateLimit);\n\n            this.previousRightTime = this.endDate.clone();\n\n            if (!this.isShowing)\n                this.updateElement();\n\n            this.updateMonthsInView();\n        },\n\n        isInvalidDate: function() {\n            return false;\n        },\n\n        updateView: function() {\n            if (this.timePicker) {\n                this.renderTimePicker('left');\n                this.renderTimePicker('right');\n                if (!this.endDate) {\n                    this.container.find('.right .calendar-time select').attr('disabled', 'disabled').addClass('disabled');\n                } else {\n                    this.container.find('.right .calendar-time select').removeAttr('disabled').removeClass('disabled');\n                }\n            }\n            if (this.endDate) {\n                this.container.find('input[name=\"daterangepicker_end\"]').removeClass('active');\n                this.container.find('input[name=\"daterangepicker_start\"]').addClass('active');\n            } else {\n                this.container.find('input[name=\"daterangepicker_end\"]').addClass('active');\n                this.container.find('input[name=\"daterangepicker_start\"]').removeClass('active');\n            }\n            this.updateMonthsInView();\n            this.updateCalendars();\n            this.updateFormInputs();\n        },\n\n        updateMonthsInView: function() {\n            if (this.endDate) {\n\n                //if both dates are visible already, do nothing\n                if (!this.singleDatePicker && this.leftCalendar.month && this.rightCalendar.month &&\n                    (this.startDate.format('YYYY-MM') == this.leftCalendar.month.format('YYYY-MM') || this.startDate.format('YYYY-MM') == this.rightCalendar.month.format('YYYY-MM'))\n                    &&\n                    (this.endDate.format('YYYY-MM') == this.leftCalendar.month.format('YYYY-MM') || this.endDate.format('YYYY-MM') == this.rightCalendar.month.format('YYYY-MM'))\n                    ) {\n                    return;\n                }\n\n                this.leftCalendar.month = this.startDate.clone().date(2);\n                if (!this.linkedCalendars && (this.endDate.month() != this.startDate.month() || this.endDate.year() != this.startDate.year())) {\n                    this.rightCalendar.month = this.endDate.clone().date(2);\n                } else {\n                    this.rightCalendar.month = this.startDate.clone().date(2).add(1, 'month');\n                }\n                \n            } else {\n                if (this.leftCalendar.month.format('YYYY-MM') != this.startDate.format('YYYY-MM') && this.rightCalendar.month.format('YYYY-MM') != this.startDate.format('YYYY-MM')) {\n                    this.leftCalendar.month = this.startDate.clone().date(2);\n                    this.rightCalendar.month = this.startDate.clone().date(2).add(1, 'month');\n                }\n            }\n        },\n\n        updateCalendars: function() {\n\n            if (this.timePicker) {\n                var hour, minute, second;\n                if (this.endDate) {\n                    hour = parseInt(this.container.find('.left .hourselect').val(), 10);\n                    minute = parseInt(this.container.find('.left .minuteselect').val(), 10);\n                    second = this.timePickerSeconds ? parseInt(this.container.find('.left .secondselect').val(), 10) : 0;\n                    if (!this.timePicker24Hour) {\n                        var ampm = this.container.find('.left .ampmselect').val();\n                        if (ampm === 'PM' && hour < 12)\n                            hour += 12;\n                        if (ampm === 'AM' && hour === 12)\n                            hour = 0;\n                    }\n                } else {\n                    hour = parseInt(this.container.find('.right .hourselect').val(), 10);\n                    minute = parseInt(this.container.find('.right .minuteselect').val(), 10);\n                    second = this.timePickerSeconds ? parseInt(this.container.find('.right .secondselect').val(), 10) : 0;\n                    if (!this.timePicker24Hour) {\n                        var ampm = this.container.find('.right .ampmselect').val();\n                        if (ampm === 'PM' && hour < 12)\n                            hour += 12;\n                        if (ampm === 'AM' && hour === 12)\n                            hour = 0;\n                    }\n                }\n                this.leftCalendar.month.hour(hour).minute(minute).second(second);\n                this.rightCalendar.month.hour(hour).minute(minute).second(second);\n            }\n\n            this.renderCalendar('left');\n            this.renderCalendar('right');\n\n            //highlight any predefined range matching the current start and end dates\n            this.container.find('.ranges li').removeClass('active');\n            if (this.endDate == null) return;\n\n            this.calculateChosenLabel();\n        },\n\n        renderCalendar: function(side) {\n\n            //\n            // Build the matrix of dates that will populate the calendar\n            //\n\n            var calendar = side == 'left' ? this.leftCalendar : this.rightCalendar;\n            var month = calendar.month.month();\n            var year = calendar.month.year();\n            var hour = calendar.month.hour();\n            var minute = calendar.month.minute();\n            var second = calendar.month.second();\n            var daysInMonth = moment([year, month]).daysInMonth();\n            var firstDay = moment([year, month, 1]);\n            var lastDay = moment([year, month, daysInMonth]);\n            var lastMonth = moment(firstDay).subtract(1, 'month').month();\n            var lastYear = moment(firstDay).subtract(1, 'month').year();\n            var daysInLastMonth = moment([lastYear, lastMonth]).daysInMonth();\n            var dayOfWeek = firstDay.day();\n\n            //initialize a 6 rows x 7 columns array for the calendar\n            var calendar = [];\n            calendar.firstDay = firstDay;\n            calendar.lastDay = lastDay;\n\n            for (var i = 0; i < 6; i++) {\n                calendar[i] = [];\n            }\n\n            //populate the calendar with date objects\n            var startDay = daysInLastMonth - dayOfWeek + this.locale.firstDay + 1;\n            if (startDay > daysInLastMonth)\n                startDay -= 7;\n\n            if (dayOfWeek == this.locale.firstDay)\n                startDay = daysInLastMonth - 6;\n\n            var curDate = moment([lastYear, lastMonth, startDay, 12, minute, second]);\n\n            var col, row;\n            for (var i = 0, col = 0, row = 0; i < 42; i++, col++, curDate = moment(curDate).add(24, 'hour')) {\n                if (i > 0 && col % 7 === 0) {\n                    col = 0;\n                    row++;\n                }\n                calendar[row][col] = curDate.clone().hour(hour).minute(minute).second(second);\n                curDate.hour(12);\n\n                if (this.minDate && calendar[row][col].format('YYYY-MM-DD') == this.minDate.format('YYYY-MM-DD') && calendar[row][col].isBefore(this.minDate) && side == 'left') {\n                    calendar[row][col] = this.minDate.clone();\n                }\n\n                if (this.maxDate && calendar[row][col].format('YYYY-MM-DD') == this.maxDate.format('YYYY-MM-DD') && calendar[row][col].isAfter(this.maxDate) && side == 'right') {\n                    calendar[row][col] = this.maxDate.clone();\n                }\n\n            }\n\n            //make the calendar object available to hoverDate/clickDate\n            if (side == 'left') {\n                this.leftCalendar.calendar = calendar;\n            } else {\n                this.rightCalendar.calendar = calendar;\n            }\n\n            //\n            // Display the calendar\n            //\n\n            var minDate = side == 'left' ? this.minDate : this.startDate;\n            var maxDate = this.maxDate;\n            var selected = side == 'left' ? this.startDate : this.endDate;\n\n            var html = '<table class=\"table-condensed\">';\n            html += '<thead>';\n            html += '<tr>';\n\n            // add empty cell for week number\n            if (this.showWeekNumbers || this.showISOWeekNumbers)\n                html += '<th></th>';\n\n            if ((!minDate || minDate.isBefore(calendar.firstDay)) && (!this.linkedCalendars || side == 'left')) {\n                html += '<th class=\"prev available\"><i class=\"fa fa-chevron-left glyphicon glyphicon-chevron-left\"></i></th>';\n            } else {\n                html += '<th></th>';\n            }\n\n            var dateHtml = this.locale.monthNames[calendar[1][1].month()] + calendar[1][1].format(\" YYYY\");\n\n            if (this.showDropdowns) {\n                var currentMonth = calendar[1][1].month();\n                var currentYear = calendar[1][1].year();\n                var maxYear = (maxDate && maxDate.year()) || (currentYear + 5);\n                var minYear = (minDate && minDate.year()) || (currentYear - 50);\n                var inMinYear = currentYear == minYear;\n                var inMaxYear = currentYear == maxYear;\n\n                var monthHtml = '<select class=\"monthselect\">';\n                for (var m = 0; m < 12; m++) {\n                    if ((!inMinYear || m >= minDate.month()) && (!inMaxYear || m <= maxDate.month())) {\n                        monthHtml += \"<option value='\" + m + \"'\" +\n                            (m === currentMonth ? \" selected='selected'\" : \"\") +\n                            \">\" + this.locale.monthNames[m] + \"</option>\";\n                    } else {\n                        monthHtml += \"<option value='\" + m + \"'\" +\n                            (m === currentMonth ? \" selected='selected'\" : \"\") +\n                            \" disabled='disabled'>\" + this.locale.monthNames[m] + \"</option>\";\n                    }\n                }\n                monthHtml += \"</select>\";\n\n                var yearHtml = '<select class=\"yearselect\">';\n                for (var y = minYear; y <= maxYear; y++) {\n                    yearHtml += '<option value=\"' + y + '\"' +\n                        (y === currentYear ? ' selected=\"selected\"' : '') +\n                        '>' + y + '</option>';\n                }\n                yearHtml += '</select>';\n\n                dateHtml = monthHtml + yearHtml;\n            }\n\n            html += '<th colspan=\"5\" class=\"month\">' + dateHtml + '</th>';\n            if ((!maxDate || maxDate.isAfter(calendar.lastDay)) && (!this.linkedCalendars || side == 'right' || this.singleDatePicker)) {\n                html += '<th class=\"next available\"><i class=\"fa fa-chevron-right glyphicon glyphicon-chevron-right\"></i></th>';\n            } else {\n                html += '<th></th>';\n            }\n\n            html += '</tr>';\n            html += '<tr>';\n\n            // add week number label\n            if (this.showWeekNumbers || this.showISOWeekNumbers)\n                html += '<th class=\"week\">' + this.locale.weekLabel + '</th>';\n\n            $.each(this.locale.daysOfWeek, function(index, dayOfWeek) {\n                html += '<th>' + dayOfWeek + '</th>';\n            });\n\n            html += '</tr>';\n            html += '</thead>';\n            html += '<tbody>';\n\n            //adjust maxDate to reflect the dateLimit setting in order to\n            //grey out end dates beyond the dateLimit\n            if (this.endDate == null && this.dateLimit) {\n                var maxLimit = this.startDate.clone().add(this.dateLimit).endOf('day');\n                if (!maxDate || maxLimit.isBefore(maxDate)) {\n                    maxDate = maxLimit;\n                }\n            }\n\n            for (var row = 0; row < 6; row++) {\n                html += '<tr>';\n\n                // add week number\n                if (this.showWeekNumbers)\n                    html += '<td class=\"week\">' + calendar[row][0].week() + '</td>';\n                else if (this.showISOWeekNumbers)\n                    html += '<td class=\"week\">' + calendar[row][0].isoWeek() + '</td>';\n\n                for (var col = 0; col < 7; col++) {\n\n                    var classes = [];\n\n                    //highlight today's date\n                    if (calendar[row][col].isSame(new Date(), \"day\"))\n                        classes.push('today');\n\n                    //highlight weekends\n                    if (calendar[row][col].isoWeekday() > 5)\n                        classes.push('weekend');\n\n                    //grey out the dates in other months displayed at beginning and end of this calendar\n                    if (calendar[row][col].month() != calendar[1][1].month())\n                        classes.push('off');\n\n                    //don't allow selection of dates before the minimum date\n                    if (this.minDate && calendar[row][col].isBefore(this.minDate, 'day'))\n                        classes.push('off', 'disabled');\n\n                    //don't allow selection of dates after the maximum date\n                    if (maxDate && calendar[row][col].isAfter(maxDate, 'day'))\n                        classes.push('off', 'disabled');\n\n                    //don't allow selection of date if a custom function decides it's invalid\n                    if (this.isInvalidDate(calendar[row][col]))\n                        classes.push('off', 'disabled');\n\n                    //highlight the currently selected start date\n                    if (calendar[row][col].format('YYYY-MM-DD') == this.startDate.format('YYYY-MM-DD'))\n                        classes.push('active', 'start-date');\n\n                    //highlight the currently selected end date\n                    if (this.endDate != null && calendar[row][col].format('YYYY-MM-DD') == this.endDate.format('YYYY-MM-DD'))\n                        classes.push('active', 'end-date');\n\n                    //highlight dates in-between the selected dates\n                    if (this.endDate != null && calendar[row][col] > this.startDate && calendar[row][col] < this.endDate)\n                        classes.push('in-range');\n\n                    var cname = '', disabled = false;\n                    for (var i = 0; i < classes.length; i++) {\n                        cname += classes[i] + ' ';\n                        if (classes[i] == 'disabled')\n                            disabled = true;\n                    }\n                    if (!disabled)\n                        cname += 'available';\n\n                    html += '<td class=\"' + cname.replace(/^\\s+|\\s+$/g, '') + '\" data-title=\"' + 'r' + row + 'c' + col + '\">' + calendar[row][col].date() + '</td>';\n\n                }\n                html += '</tr>';\n            }\n\n            html += '</tbody>';\n            html += '</table>';\n\n            this.container.find('.calendar.' + side + ' .calendar-table').html(html);\n\n        },\n\n        renderTimePicker: function(side) {\n\n            var html, selected, minDate, maxDate = this.maxDate;\n\n            if (this.dateLimit && (!this.maxDate || this.startDate.clone().add(this.dateLimit).isAfter(this.maxDate)))\n                maxDate = this.startDate.clone().add(this.dateLimit);\n\n            if (side == 'left') {\n                selected = this.startDate.clone();\n                minDate = this.minDate;\n            } else if (side == 'right') {\n                selected = this.endDate ? this.endDate.clone() : this.previousRightTime.clone();\n                minDate = this.startDate;\n\n                //Preserve the time already selected\n                var timeSelector = this.container.find('.calendar.right .calendar-time div');\n                if (timeSelector.html() != '') {\n\n                    selected.hour(timeSelector.find('.hourselect option:selected').val() || selected.hour());\n                    selected.minute(timeSelector.find('.minuteselect option:selected').val() || selected.minute());\n                    selected.second(timeSelector.find('.secondselect option:selected').val() || selected.second());\n\n                    if (!this.timePicker24Hour) {\n                        var ampm = timeSelector.find('.ampmselect option:selected').val();\n                        if (ampm === 'PM' && selected.hour() < 12)\n                            selected.hour(selected.hour() + 12);\n                        if (ampm === 'AM' && selected.hour() === 12)\n                            selected.hour(0);\n                    }\n\n                    if (selected.isBefore(this.startDate))\n                        selected = this.startDate.clone();\n\n                    if (selected.isAfter(maxDate))\n                        selected = maxDate.clone();\n\n                }\n            }\n\n            //\n            // hours\n            //\n\n            html = '<select class=\"hourselect\">';\n\n            var start = this.timePicker24Hour ? 0 : 1;\n            var end = this.timePicker24Hour ? 23 : 12;\n\n            for (var i = start; i <= end; i++) {\n                var i_in_24 = i;\n                if (!this.timePicker24Hour)\n                    i_in_24 = selected.hour() >= 12 ? (i == 12 ? 12 : i + 12) : (i == 12 ? 0 : i);\n\n                var time = selected.clone().hour(i_in_24);\n                var disabled = false;\n                if (minDate && time.minute(59).isBefore(minDate))\n                    disabled = true;\n                if (maxDate && time.minute(0).isAfter(maxDate))\n                    disabled = true;\n\n                if (i_in_24 == selected.hour() && !disabled) {\n                    html += '<option value=\"' + i + '\" selected=\"selected\">' + i + '</option>';\n                } else if (disabled) {\n                    html += '<option value=\"' + i + '\" disabled=\"disabled\" class=\"disabled\">' + i + '</option>';\n                } else {\n                    html += '<option value=\"' + i + '\">' + i + '</option>';\n                }\n            }\n\n            html += '</select> ';\n\n            //\n            // minutes\n            //\n\n            html += ': <select class=\"minuteselect\">';\n\n            for (var i = 0; i < 60; i += this.timePickerIncrement) {\n                var padded = i < 10 ? '0' + i : i;\n                var time = selected.clone().minute(i);\n\n                var disabled = false;\n                if (minDate && time.second(59).isBefore(minDate))\n                    disabled = true;\n                if (maxDate && time.second(0).isAfter(maxDate))\n                    disabled = true;\n\n                if (selected.minute() == i && !disabled) {\n                    html += '<option value=\"' + i + '\" selected=\"selected\">' + padded + '</option>';\n                } else if (disabled) {\n                    html += '<option value=\"' + i + '\" disabled=\"disabled\" class=\"disabled\">' + padded + '</option>';\n                } else {\n                    html += '<option value=\"' + i + '\">' + padded + '</option>';\n                }\n            }\n\n            html += '</select> ';\n\n            //\n            // seconds\n            //\n\n            if (this.timePickerSeconds) {\n                html += ': <select class=\"secondselect\">';\n\n                for (var i = 0; i < 60; i++) {\n                    var padded = i < 10 ? '0' + i : i;\n                    var time = selected.clone().second(i);\n\n                    var disabled = false;\n                    if (minDate && time.isBefore(minDate))\n                        disabled = true;\n                    if (maxDate && time.isAfter(maxDate))\n                        disabled = true;\n\n                    if (selected.second() == i && !disabled) {\n                        html += '<option value=\"' + i + '\" selected=\"selected\">' + padded + '</option>';\n                    } else if (disabled) {\n                        html += '<option value=\"' + i + '\" disabled=\"disabled\" class=\"disabled\">' + padded + '</option>';\n                    } else {\n                        html += '<option value=\"' + i + '\">' + padded + '</option>';\n                    }\n                }\n\n                html += '</select> ';\n            }\n\n            //\n            // AM/PM\n            //\n\n            if (!this.timePicker24Hour) {\n                html += '<select class=\"ampmselect\">';\n\n                var am_html = '';\n                var pm_html = '';\n\n                if (minDate && selected.clone().hour(12).minute(0).second(0).isBefore(minDate))\n                    am_html = ' disabled=\"disabled\" class=\"disabled\"';\n\n                if (maxDate && selected.clone().hour(0).minute(0).second(0).isAfter(maxDate))\n                    pm_html = ' disabled=\"disabled\" class=\"disabled\"';\n\n                if (selected.hour() >= 12) {\n                    html += '<option value=\"AM\"' + am_html + '>AM</option><option value=\"PM\" selected=\"selected\"' + pm_html + '>PM</option>';\n                } else {\n                    html += '<option value=\"AM\" selected=\"selected\"' + am_html + '>AM</option><option value=\"PM\"' + pm_html + '>PM</option>';\n                }\n\n                html += '</select>';\n            }\n\n            this.container.find('.calendar.' + side + ' .calendar-time div').html(html);\n\n        },\n\n        updateFormInputs: function() {\n\n            //ignore mouse movements while an above-calendar text input has focus\n            if (this.container.find('input[name=daterangepicker_start]').is(\":focus\") || this.container.find('input[name=daterangepicker_end]').is(\":focus\"))\n                return;\n\n            this.container.find('input[name=daterangepicker_start]').val(this.startDate.format(this.locale.format));\n            if (this.endDate)\n                this.container.find('input[name=daterangepicker_end]').val(this.endDate.format(this.locale.format));\n\n            if (this.singleDatePicker || (this.endDate && (this.startDate.isBefore(this.endDate) || this.startDate.isSame(this.endDate)))) {\n                this.container.find('button.applyBtn').removeAttr('disabled');\n            } else {\n                this.container.find('button.applyBtn').attr('disabled', 'disabled');\n            }\n\n        },\n\n        move: function() {\n            var parentOffset = { top: 0, left: 0 },\n                containerTop;\n            var parentRightEdge = $(window).width();\n            if (!this.parentEl.is('body')) {\n                parentOffset = {\n                    top: this.parentEl.offset().top - this.parentEl.scrollTop(),\n                    left: this.parentEl.offset().left - this.parentEl.scrollLeft()\n                };\n                parentRightEdge = this.parentEl[0].clientWidth + this.parentEl.offset().left;\n            }\n\n            if (this.drops == 'up')\n                containerTop = this.element.offset().top - this.container.outerHeight() - parentOffset.top;\n            else\n                containerTop = this.element.offset().top + this.element.outerHeight() - parentOffset.top;\n            this.container[this.drops == 'up' ? 'addClass' : 'removeClass']('dropup');\n\n            if (this.opens == 'left') {\n                this.container.css({\n                    top: containerTop,\n                    right: parentRightEdge - this.element.offset().left - this.element.outerWidth(),\n                    left: 'auto'\n                });\n                if (this.container.offset().left < 0) {\n                    this.container.css({\n                        right: 'auto',\n                        left: 9\n                    });\n                }\n            } else if (this.opens == 'center') {\n                this.container.css({\n                    top: containerTop,\n                    left: this.element.offset().left - parentOffset.left + this.element.outerWidth() / 2\n                            - this.container.outerWidth() / 2,\n                    right: 'auto'\n                });\n                if (this.container.offset().left < 0) {\n                    this.container.css({\n                        right: 'auto',\n                        left: 9\n                    });\n                }\n            } else {\n                this.container.css({\n                    top: containerTop,\n                    left: this.element.offset().left - parentOffset.left,\n                    right: 'auto'\n                });\n                if (this.container.offset().left + this.container.outerWidth() > $(window).width()) {\n                    this.container.css({\n                        left: 'auto',\n                        right: 0\n                    });\n                }\n            }\n        },\n\n        show: function(e) {\n            if (this.isShowing) return;\n\n            // Create a click proxy that is private to this instance of datepicker, for unbinding\n            this._outsideClickProxy = $.proxy(function(e) { this.outsideClick(e); }, this);\n\n            // Bind global datepicker mousedown for hiding and\n            $(document)\n              .on('mousedown.daterangepicker', this._outsideClickProxy)\n              // also support mobile devices\n              .on('touchend.daterangepicker', this._outsideClickProxy)\n              // also explicitly play nice with Bootstrap dropdowns, which stopPropagation when clicking them\n              .on('click.daterangepicker', '[data-toggle=dropdown]', this._outsideClickProxy)\n              // and also close when focus changes to outside the picker (eg. tabbing between controls)\n              .on('focusin.daterangepicker', this._outsideClickProxy);\n\n            // Reposition the picker if the window is resized while it's open\n            $(window).on('resize.daterangepicker', $.proxy(function(e) { this.move(e); }, this));\n\n            this.oldStartDate = this.startDate.clone();\n            this.oldEndDate = this.endDate.clone();\n            this.previousRightTime = this.endDate.clone();\n\n            this.updateView();\n            this.container.show();\n            this.move();\n            this.element.trigger('show.daterangepicker', this);\n            this.isShowing = true;\n        },\n\n        hide: function(e) {\n            if (!this.isShowing) return;\n\n            //incomplete date selection, revert to last values\n            if (!this.endDate) {\n                this.startDate = this.oldStartDate.clone();\n                this.endDate = this.oldEndDate.clone();\n            }\n\n            //if a new date range was selected, invoke the user callback function\n            if (!this.startDate.isSame(this.oldStartDate) || !this.endDate.isSame(this.oldEndDate))\n                this.callback(this.startDate, this.endDate, this.chosenLabel);\n\n            //if picker is attached to a text input, update it\n            this.updateElement();\n\n            $(document).off('.daterangepicker');\n            $(window).off('.daterangepicker');\n            this.container.hide();\n            this.element.trigger('hide.daterangepicker', this);\n            this.isShowing = false;\n        },\n\n        toggle: function(e) {\n            if (this.isShowing) {\n                this.hide();\n            } else {\n                this.show();\n            }\n        },\n\n        outsideClick: function(e) {\n            var target = $(e.target);\n            // if the page is clicked anywhere except within the daterangerpicker/button\n            // itself then call this.hide()\n            if (\n                // ie modal dialog fix\n                e.type == \"focusin\" ||\n                target.closest(this.element).length ||\n                target.closest(this.container).length ||\n                target.closest('.calendar-table').length\n                ) return;\n            this.hide();\n        },\n\n        showCalendars: function() {\n            this.container.addClass('show-calendar');\n            this.move();\n            this.element.trigger('showCalendar.daterangepicker', this);\n        },\n\n        hideCalendars: function() {\n            this.container.removeClass('show-calendar');\n            this.element.trigger('hideCalendar.daterangepicker', this);\n        },\n\n        hoverRange: function(e) {\n\n            //ignore mouse movements while an above-calendar text input has focus\n            if (this.container.find('input[name=daterangepicker_start]').is(\":focus\") || this.container.find('input[name=daterangepicker_end]').is(\":focus\"))\n                return;\n\n            var label = e.target.innerHTML;\n            if (label == this.locale.customRangeLabel) {\n                this.updateView();\n            } else {\n                var dates = this.ranges[label];\n                this.container.find('input[name=daterangepicker_start]').val(dates[0].format(this.locale.format));\n                this.container.find('input[name=daterangepicker_end]').val(dates[1].format(this.locale.format));\n            }\n            \n        },\n\n        clickRange: function(e) {\n            var label = e.target.innerHTML;\n            this.chosenLabel = label;\n            if (label == this.locale.customRangeLabel) {\n                this.showCalendars();\n            } else {\n                var dates = this.ranges[label];\n                this.startDate = dates[0];\n                this.endDate = dates[1];\n\n                if (!this.timePicker) {\n                    this.startDate.startOf('day');\n                    this.endDate.endOf('day');\n                }\n\n                if (!this.alwaysShowCalendars)\n                    this.hideCalendars();\n                this.clickApply();\n            }\n        },\n\n        clickPrev: function(e) {\n            var cal = $(e.target).parents('.calendar');\n            if (cal.hasClass('left')) {\n                this.leftCalendar.month.subtract(1, 'month');\n                if (this.linkedCalendars)\n                    this.rightCalendar.month.subtract(1, 'month');\n            } else {\n                this.rightCalendar.month.subtract(1, 'month');\n            }\n            this.updateCalendars();\n        },\n\n        clickNext: function(e) {\n            var cal = $(e.target).parents('.calendar');\n            if (cal.hasClass('left')) {\n                this.leftCalendar.month.add(1, 'month');\n            } else {\n                this.rightCalendar.month.add(1, 'month');\n                if (this.linkedCalendars)\n                    this.leftCalendar.month.add(1, 'month');\n            }\n            this.updateCalendars();\n        },\n\n        hoverDate: function(e) {\n\n            //ignore mouse movements while an above-calendar text input has focus\n            if (this.container.find('input[name=daterangepicker_start]').is(\":focus\") || this.container.find('input[name=daterangepicker_end]').is(\":focus\"))\n                return;\n\n            //ignore dates that can't be selected\n            if (!$(e.target).hasClass('available')) return;\n\n            //have the text inputs above calendars reflect the date being hovered over\n            var title = $(e.target).attr('data-title');\n            var row = title.substr(1, 1);\n            var col = title.substr(3, 1);\n            var cal = $(e.target).parents('.calendar');\n            var date = cal.hasClass('left') ? this.leftCalendar.calendar[row][col] : this.rightCalendar.calendar[row][col];\n\n            if (this.endDate) {\n                this.container.find('input[name=daterangepicker_start]').val(date.format(this.locale.format));\n            } else {\n                this.container.find('input[name=daterangepicker_end]').val(date.format(this.locale.format));\n            }\n\n            //highlight the dates between the start date and the date being hovered as a potential end date\n            var leftCalendar = this.leftCalendar;\n            var rightCalendar = this.rightCalendar;\n            var startDate = this.startDate;\n            if (!this.endDate) {\n                this.container.find('.calendar td').each(function(index, el) {\n\n                    //skip week numbers, only look at dates\n                    if ($(el).hasClass('week')) return;\n\n                    var title = $(el).attr('data-title');\n                    var row = title.substr(1, 1);\n                    var col = title.substr(3, 1);\n                    var cal = $(el).parents('.calendar');\n                    var dt = cal.hasClass('left') ? leftCalendar.calendar[row][col] : rightCalendar.calendar[row][col];\n\n                    if (dt.isAfter(startDate) && dt.isBefore(date)) {\n                        $(el).addClass('in-range');\n                    } else {\n                        $(el).removeClass('in-range');\n                    }\n\n                });\n            }\n\n        },\n\n        clickDate: function(e) {\n\n            if (!$(e.target).hasClass('available')) return;\n\n            var title = $(e.target).attr('data-title');\n            var row = title.substr(1, 1);\n            var col = title.substr(3, 1);\n            var cal = $(e.target).parents('.calendar');\n            var date = cal.hasClass('left') ? this.leftCalendar.calendar[row][col] : this.rightCalendar.calendar[row][col];\n\n            //\n            // this function needs to do a few things:\n            // * alternate between selecting a start and end date for the range,\n            // * if the time picker is enabled, apply the hour/minute/second from the select boxes to the clicked date\n            // * if autoapply is enabled, and an end date was chosen, apply the selection\n            // * if single date picker mode, and time picker isn't enabled, apply the selection immediately\n            //\n\n            if (this.endDate || date.isBefore(this.startDate, 'day')) {\n                if (this.timePicker) {\n                    var hour = parseInt(this.container.find('.left .hourselect').val(), 10);\n                    if (!this.timePicker24Hour) {\n                        var ampm = this.container.find('.left .ampmselect').val();\n                        if (ampm === 'PM' && hour < 12)\n                            hour += 12;\n                        if (ampm === 'AM' && hour === 12)\n                            hour = 0;\n                    }\n                    var minute = parseInt(this.container.find('.left .minuteselect').val(), 10);\n                    var second = this.timePickerSeconds ? parseInt(this.container.find('.left .secondselect').val(), 10) : 0;\n                    date = date.clone().hour(hour).minute(minute).second(second);\n                }\n                this.endDate = null;\n                this.setStartDate(date.clone());\n            } else if (!this.endDate && date.isBefore(this.startDate)) {\n                //special case: clicking the same date for start/end, \n                //but the time of the end date is before the start date\n                this.setEndDate(this.startDate.clone());\n            } else {\n                if (this.timePicker) {\n                    var hour = parseInt(this.container.find('.right .hourselect').val(), 10);\n                    if (!this.timePicker24Hour) {\n                        var ampm = this.container.find('.right .ampmselect').val();\n                        if (ampm === 'PM' && hour < 12)\n                            hour += 12;\n                        if (ampm === 'AM' && hour === 12)\n                            hour = 0;\n                    }\n                    var minute = parseInt(this.container.find('.right .minuteselect').val(), 10);\n                    var second = this.timePickerSeconds ? parseInt(this.container.find('.right .secondselect').val(), 10) : 0;\n                    date = date.clone().hour(hour).minute(minute).second(second);\n                }\n                this.setEndDate(date.clone());\n                if (this.autoApply) {\n                  this.calculateChosenLabel();\n                  this.clickApply();\n                }\n            }\n\n            if (this.singleDatePicker) {\n                this.setEndDate(this.startDate);\n                if (!this.timePicker)\n                    this.clickApply();\n            }\n\n            this.updateView();\n\n        },\n\n        calculateChosenLabel: function() {\n          var customRange = true;\n          var i = 0;\n          for (var range in this.ranges) {\n              if (this.timePicker) {\n                  if (this.startDate.isSame(this.ranges[range][0]) && this.endDate.isSame(this.ranges[range][1])) {\n                      customRange = false;\n                      this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')').addClass('active').html();\n                      break;\n                  }\n              } else {\n                  //ignore times when comparing dates if time picker is not enabled\n                  if (this.startDate.format('YYYY-MM-DD') == this.ranges[range][0].format('YYYY-MM-DD') && this.endDate.format('YYYY-MM-DD') == this.ranges[range][1].format('YYYY-MM-DD')) {\n                      customRange = false;\n                      this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')').addClass('active').html();\n                      break;\n                  }\n              }\n              i++;\n          }\n          if (customRange) {\n              this.chosenLabel = this.container.find('.ranges li:last').addClass('active').html();\n              this.showCalendars();\n          }\n        },\n\n        clickApply: function(e) {\n            this.hide();\n            this.element.trigger('apply.daterangepicker', this);\n        },\n\n        clickCancel: function(e) {\n            this.startDate = this.oldStartDate;\n            this.endDate = this.oldEndDate;\n            this.hide();\n            this.element.trigger('cancel.daterangepicker', this);\n        },\n\n        monthOrYearChanged: function(e) {\n            var isLeft = $(e.target).closest('.calendar').hasClass('left'),\n                leftOrRight = isLeft ? 'left' : 'right',\n                cal = this.container.find('.calendar.'+leftOrRight);\n\n            // Month must be Number for new moment versions\n            var month = parseInt(cal.find('.monthselect').val(), 10);\n            var year = cal.find('.yearselect').val();\n\n            if (!isLeft) {\n                if (year < this.startDate.year() || (year == this.startDate.year() && month < this.startDate.month())) {\n                    month = this.startDate.month();\n                    year = this.startDate.year();\n                }\n            }\n\n            if (this.minDate) {\n                if (year < this.minDate.year() || (year == this.minDate.year() && month < this.minDate.month())) {\n                    month = this.minDate.month();\n                    year = this.minDate.year();\n                }\n            }\n\n            if (this.maxDate) {\n                if (year > this.maxDate.year() || (year == this.maxDate.year() && month > this.maxDate.month())) {\n                    month = this.maxDate.month();\n                    year = this.maxDate.year();\n                }\n            }\n\n            if (isLeft) {\n                this.leftCalendar.month.month(month).year(year);\n                if (this.linkedCalendars)\n                    this.rightCalendar.month = this.leftCalendar.month.clone().add(1, 'month');\n            } else {\n                this.rightCalendar.month.month(month).year(year);\n                if (this.linkedCalendars)\n                    this.leftCalendar.month = this.rightCalendar.month.clone().subtract(1, 'month');\n            }\n            this.updateCalendars();\n        },\n\n        timeChanged: function(e) {\n\n            var cal = $(e.target).closest('.calendar'),\n                isLeft = cal.hasClass('left');\n\n            var hour = parseInt(cal.find('.hourselect').val(), 10);\n            var minute = parseInt(cal.find('.minuteselect').val(), 10);\n            var second = this.timePickerSeconds ? parseInt(cal.find('.secondselect').val(), 10) : 0;\n\n            if (!this.timePicker24Hour) {\n                var ampm = cal.find('.ampmselect').val();\n                if (ampm === 'PM' && hour < 12)\n                    hour += 12;\n                if (ampm === 'AM' && hour === 12)\n                    hour = 0;\n            }\n\n            if (isLeft) {\n                var start = this.startDate.clone();\n                start.hour(hour);\n                start.minute(minute);\n                start.second(second);\n                this.setStartDate(start);\n                if (this.singleDatePicker) {\n                    this.endDate = this.startDate.clone();\n                } else if (this.endDate && this.endDate.format('YYYY-MM-DD') == start.format('YYYY-MM-DD') && this.endDate.isBefore(start)) {\n                    this.setEndDate(start.clone());\n                }\n            } else if (this.endDate) {\n                var end = this.endDate.clone();\n                end.hour(hour);\n                end.minute(minute);\n                end.second(second);\n                this.setEndDate(end);\n            }\n\n            //update the calendars so all clickable dates reflect the new time component\n            this.updateCalendars();\n\n            //update the form inputs above the calendars with the new time\n            this.updateFormInputs();\n\n            //re-render the time pickers because changing one selection can affect what's enabled in another\n            this.renderTimePicker('left');\n            this.renderTimePicker('right');\n\n        },\n\n        formInputsChanged: function(e) {\n            var isRight = $(e.target).closest('.calendar').hasClass('right');\n            var start = moment(this.container.find('input[name=\"daterangepicker_start\"]').val(), this.locale.format);\n            var end = moment(this.container.find('input[name=\"daterangepicker_end\"]').val(), this.locale.format);\n\n            if (start.isValid() && end.isValid()) {\n\n                if (isRight && end.isBefore(start))\n                    start = end.clone();\n\n                this.setStartDate(start);\n                this.setEndDate(end);\n\n                if (isRight) {\n                    this.container.find('input[name=\"daterangepicker_start\"]').val(this.startDate.format(this.locale.format));\n                } else {\n                    this.container.find('input[name=\"daterangepicker_end\"]').val(this.endDate.format(this.locale.format));\n                }\n\n            }\n\n            this.updateCalendars();\n            if (this.timePicker) {\n                this.renderTimePicker('left');\n                this.renderTimePicker('right');\n            }\n        },\n\n        elementChanged: function() {\n            if (!this.element.is('input')) return;\n            if (!this.element.val().length) return;\n            if (this.element.val().length < this.locale.format.length) return;\n\n            var dateString = this.element.val().split(this.locale.separator),\n                start = null,\n                end = null;\n\n            if (dateString.length === 2) {\n                start = moment(dateString[0], this.locale.format);\n                end = moment(dateString[1], this.locale.format);\n            }\n\n            if (this.singleDatePicker || start === null || end === null) {\n                start = moment(this.element.val(), this.locale.format);\n                end = start;\n            }\n\n            if (!start.isValid() || !end.isValid()) return;\n\n            this.setStartDate(start);\n            this.setEndDate(end);\n            this.updateView();\n        },\n\n        keydown: function(e) {\n            //hide on tab or enter\n            if ((e.keyCode === 9) || (e.keyCode === 13)) {\n                this.hide();\n            }\n        },\n\n        updateElement: function() {\n            if (this.element.is('input') && !this.singleDatePicker && this.autoUpdateInput) {\n                this.element.val(this.startDate.format(this.locale.format) + this.locale.separator + this.endDate.format(this.locale.format));\n                this.element.trigger('change');\n            } else if (this.element.is('input') && this.autoUpdateInput) {\n                this.element.val(this.startDate.format(this.locale.format));\n                this.element.trigger('change');\n            }\n        },\n\n        remove: function() {\n            this.container.remove();\n            this.element.off('.daterangepicker');\n            this.element.removeData();\n        }\n\n    };\n\n    $.fn.daterangepicker = function(options, callback) {\n        this.each(function() {\n            var el = $(this);\n            if (el.data('daterangepicker'))\n                el.data('daterangepicker').remove();\n            el.data('daterangepicker', new DateRangePicker(el, options, callback));\n        });\n        return this;\n    };\n    \n    return DateRangePicker;\n\n}));\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/view/static/adminlte/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": "open-xxl-job/xxl-job-admin/src/main/view/static/adminlte/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": "open-xxl-job/xxl-job-admin/src/main/view/static/adminlte/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": "open-xxl-job/xxl-job-admin/src/main/view/static/adminlte/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": "open-xxl-job/xxl-job-admin/src/main/view/static/adminlte/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": "open-xxl-job/xxl-job-admin/src/main/view/static/adminlte/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": "open-xxl-job/xxl-job-admin/src/main/view/static/adminlte/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": "open-xxl-job/xxl-job-admin/src/main/view/static/adminlte/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": "open-xxl-job/xxl-job-admin/src/main/view/static/adminlte/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": "open-xxl-job/xxl-job-admin/src/main/view/static/adminlte/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": "open-xxl-job/xxl-job-admin/src/main/view/static/adminlte/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": "open-xxl-job/xxl-job-admin/src/main/view/static/js/common.1.js",
    "content": "$(function(){\n\n\t// logout\n\t$(\"#logoutBtn\").click(function(){\n\t\tlayer.confirm('确认注销登录?', {icon: 3, title:'系统提示'}, function(index){\n\t\t\tlayer.close(index);\n\n\t\t\t$.post(base_url + \"/logout\", function(data, status) {\n\t\t\t\tif (data.code == \"200\") {\n\t\t\t\t\tlayer.open({\n\t\t\t\t\t\ttitle: '系统提示',\n\t\t\t\t\t\tcontent: '注销成功',\n\t\t\t\t\t\ticon: '1',\n\t\t\t\t\t\tend: function(layero, index){\n\t\t\t\t\t\t\twindow.location.href = base_url + \"/toLogin\";\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tlayer.open({\n\t\t\t\t\t\ttitle: '系统提示',\n\t\t\t\t\t\tcontent: (data.msg || \"操作失败\"),\n\t\t\t\t\t\ticon: '2'\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\n\t});\n\n\t// slideToTop\n\tvar slideToTop = $(\"<div />\");\n\tslideToTop.html('<i class=\"fa fa-chevron-up\"></i>');\n\tslideToTop.css({\n\t\tposition: 'fixed',\n\t\tbottom: '20px',\n\t\tright: '25px',\n\t\twidth: '40px',\n\t\theight: '40px',\n\t\tcolor: '#eee',\n\t\t'font-size': '',\n\t\t'line-height': '40px',\n\t\t'text-align': 'center',\n\t\t'background-color': '#222d32',\n\t\tcursor: 'pointer',\n\t\t'border-radius': '5px',\n\t\t'z-index': '99999',\n\t\topacity: '.7',\n\t\t'display': 'none'\n\t});\n\tslideToTop.on('mouseenter', function () {\n\t\t$(this).css('opacity', '1');\n\t});\n\tslideToTop.on('mouseout', function () {\n\t\t$(this).css('opacity', '.7');\n\t});\n\t$('.wrapper').append(slideToTop);\n\t$(window).scroll(function () {\n\t\tif ($(window).scrollTop() >= 150) {\n\t\t\tif (!$(slideToTop).is(':visible')) {\n\t\t\t\t$(slideToTop).fadeIn(500);\n\t\t\t}\n\t\t} else {\n\t\t\t$(slideToTop).fadeOut(500);\n\t\t}\n\t});\n\t$(slideToTop).click(function () {\n\t\t$(\"body\").animate({\n\t\t\tscrollTop: 0\n\t\t}, 100);\n\t});\n\n\t// 左侧菜单状态，js + 后端 + cookie方式（新）\n\t$('.sidebar-toggle').click(function(){\n\t\tvar xxljob_adminlte_settings = $.cookie('xxljob_adminlte_settings');\t// 左侧菜单展开状态[xxljob_adminlte_settings]：on=展开，off=折叠\n\t\tif ('off' == xxljob_adminlte_settings) {\n            xxljob_adminlte_settings = 'on';\n\t\t} else {\n            xxljob_adminlte_settings = 'off';\n\t\t}\n\t\t$.cookie('xxljob_adminlte_settings', xxljob_adminlte_settings, { expires: 7 });\t//$.cookie('the_cookie', '', { expires: -1 });\n\t});\n\t// 左侧菜单状态，js + cookie方式（遗弃）\n\t/*\n\t var xxljob_adminlte_settings = $.cookie('xxljob_adminlte_settings');\n\t if (xxljob_adminlte_settings == 'off') {\n\t $('body').addClass('sidebar-collapse');\n\t }\n\t */\n\t\n});\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/view/static/js/index.js",
    "content": "/**\n * Created by xuxueli on 17/4/24.\n */\n\n\n$(function () {\n\n    /**\n     *\n     */\n    $.ajax({\n        type : 'POST',\n        url : base_url + '/triggerChartDate',\n        data : {        },\n        dataType : \"json\",\n        success : function(data){\n            if (data.code == 200) {\n                lineChartInit(data)\n                pieChartInit(data);\n            } else {\n                layer.open({\n                    title: '系统提示',\n                    content: (data.msg || '调度报表数据加载异常'),\n                    icon: '2'\n                });\n            }\n        }\n    });\n\n\n\n    /**\n     * 折线图\n     */\n    function lineChartInit(data) {\n        var option = {\n               title: {\n                   text: '日期分布图'\n               },\n               tooltip : {\n                   trigger: 'axis',\n                   axisPointer: {\n                       type: 'cross',\n                       label: {\n                           backgroundColor: '#6a7985'\n                       }\n                   }\n               },\n               legend: {\n                   data:['成功调度次数','失败调度次数']\n               },\n               toolbox: {\n                   feature: {\n                       /*saveAsImage: {}*/\n                   }\n               },\n               grid: {\n                   left: '3%',\n                   right: '4%',\n                   bottom: '3%',\n                   containLabel: true\n               },\n               xAxis : [\n                   {\n                       type : 'category',\n                       boundaryGap : false,\n                       data : data.content.triggerDayList\n                   }\n               ],\n               yAxis : [\n                   {\n                       type : 'value'\n                   }\n               ],\n               series : [\n                   {\n                       name:'成功调度次数',\n                       type:'line',\n                       stack: '总量',\n                       areaStyle: {normal: {}},\n                       data: data.content.triggerDayCountSucList\n                   },\n                   {\n                       name:'失败调度次数',\n                       type:'line',\n                       stack: '总量',\n                       label: {\n                           normal: {\n                               show: true,\n                               position: 'top'\n                           }\n                       },\n                       areaStyle: {normal: {}},\n                       data: data.content.triggerDayCountFailList\n                   }\n               ],\n                color:['#00A65A', '#F39C12']\n        };\n\n        var lineChart = echarts.init(document.getElementById('lineChart'));\n        lineChart.setOption(option);\n    }\n\n    /**\n     * 饼图\n     */\n    function pieChartInit(data) {\n        var option = {\n            title : {\n                text: '成功比例图',\n                /*subtext: 'subtext',*/\n                x:'center'\n            },\n            tooltip : {\n                trigger: 'item',\n                formatter: \"{a} <br/>{b} : {c} ({d}%)\"\n            },\n            legend: {\n                orient: 'vertical',\n                left: 'left',\n                data: ['成功调度次数','失败调度次数']\n            },\n            series : [\n                {\n                    name: '分布比例',\n                    type: 'pie',\n                    radius : '55%',\n                    center: ['50%', '60%'],\n                    data:[\n                        {\n                            value:data.content.triggerCountSucTotal,\n                            name:'成功调度次数'\n                        },\n                        {\n                            value:data.content.triggerCountFailTotal,\n                            name:'失败调度次数'\n                        }\n                    ],\n                    itemStyle: {\n                        emphasis: {\n                            shadowBlur: 10,\n                            shadowOffsetX: 0,\n                            shadowColor: 'rgba(0, 0, 0, 0.5)'\n                        }\n                    }\n                }\n            ],\n            color:['#00A65A', '#F39C12']\n        };\n        var pieChart = echarts.init(document.getElementById('pieChart'));\n        pieChart.setOption(option);\n    }\n\n    // 过滤时间\n    /*$('#filterTime').daterangepicker({\n        autoApply:false,\n        singleDatePicker:false,\n        showDropdowns:false,        // 是否显示年月选择条件\n        timePicker: true, \t\t\t// 是否显示小时和分钟选择条件\n        timePickerIncrement: 10, \t// 时间的增量，单位为分钟\n        timePicker24Hour : true,\n        opens : 'left', //日期选择框的弹出位置\n        ranges: {\n            '最近1小时': [moment().subtract(1, 'hours'), moment()],\n            '今日': [moment().startOf('day'), moment().endOf('day')],\n            '昨日': [moment().subtract(1, 'days').startOf('day'), moment().subtract(1, 'days').endOf('day')],\n            '最近7日': [moment().subtract(6, 'days'), moment()],\n            '最近30日': [moment().subtract(29, 'days'), moment()],\n            '本月': [moment().startOf('month'), moment().endOf('month')],\n            '上个月': [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')]\n        },\n        locale : {\n            format: 'YYYY-MM-DD HH:mm:ss',\n            separator : ' - ',\n            customRangeLabel : '自定义',\n            applyLabel : '确定',\n            cancelLabel : '取消',\n            fromLabel : '起始时间',\n            toLabel : '结束时间',\n            daysOfWeek : [ '日', '一', '二', '三', '四', '五', '六' ],\n            monthNames : [ '一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月' ],\n            firstDay : 1,\n            startDate: moment().startOf('day'),\n            endDate: moment().endOf('day')\n        }\n    });*/\n\n});\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/view/static/js/jobcode.index.1.js",
    "content": "$(function() {\n\n\t// init code editor\n\t/*var codeEditor = CodeMirror.fromTextArea(document.getElementById(\"glueSource\"), {\n\t\tmode : \"text/x-java\",\n\t\tlineNumbers : true,\n\t\tmatchBrackets : true\n\t});*/\n\n\tvar codeEditor;\n\tfunction initIde(glueType, glueSource) {\n\t\tvar ideMode = \"text/x-java\";\n\t\tif ('GLUE_GROOVY'==glueType){\n\t\t\tideMode = \"text/x-java\";\n\t\t} else if ('GLUE_SHELL'==glueType){\n\t\t\tideMode = \"text/x-sh\";\n\t\t} else if ('GLUE_PYTHON'==glueType){\n\t\t\tideMode = \"text/x-python\";\n\t\t}\n\n\t\tcodeEditor = CodeMirror(document.getElementById(\"ideWindow\"), {\n\t\t\tmode : ideMode,\n\t\t\tlineNumbers : true,\n\t\t\tmatchBrackets : true,\n\t\t\tvalue: glueSource\n\t\t});\n\t}\n\n\tinitIde(glueType, $(\"#version_now\").val());\n\n\t// code change\n\t$(\".source_version\").click(function(){\n\t\tvar glueType = $(this).attr('glueType');\n\t\tvar sourceId = $(this).attr('version');\n\t\tvar temp = $( \"#\" + sourceId ).val();\n\n\t\tcodeEditor.setValue('');\n\t\tinitIde(glueType, temp);\n\t});\n\n\t// code source save\n\t$(\"#save\").click(function() {\n\t\t$('#saveModal').modal({backdrop: false, keyboard: false}).modal('show');\n\t});\n\n\t$(\"#saveModal .ok\").click(function() {\n\n\t\tvar glueSource = codeEditor.getValue();\n\t\tvar glueRemark = $(\"#glueRemark\").val();\n\t\t\n\t\tif (!glueRemark) {\n\t\t\tlayer.open({\n\t\t\t\ttitle: '系统提示',\n\t\t\t\tcontent: '请输入备注',\n\t\t\t\ticon: '2'\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tif (glueRemark.length <4 || glueRemark.length > 100) {\n\t\t\tlayer.open({\n\t\t\t\ttitle: '系统提示',\n\t\t\t\tcontent: '备注长度应该在4至100之间',\n\t\t\t\ticon: '2'\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\t$.ajax({\n\t\t\ttype : 'POST',\n\t\t\turl : base_url + '/jobcode/save',\n\t\t\tdata : {\n\t\t\t\t'id' : id,\n\t\t\t\t'glueSource' : glueSource,\n\t\t\t\t'glueRemark' : glueRemark\n\t\t\t},\n\t\t\tdataType : \"json\",\n\t\t\tsuccess : function(data){\n\t\t\t\tif (data.code == 200) {\n\t\t\t\t\tlayer.open({\n\t\t\t\t\t\ttitle: '系统提示',\n\t\t\t\t\t\tcontent: '保存成功',\n\t\t\t\t\t\ticon: '1',\n\t\t\t\t\t\tend: function(layero, index){\n\t\t\t\t\t\t\t//$(window).unbind('beforeunload');\n\t\t\t\t\t\t\twindow.location.reload();\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tlayer.open({\n\t\t\t\t\t\ttitle: '系统提示',\n\t\t\t\t\t\tcontent: (data.msg || \"保存失败\"),\n\t\t\t\t\t\ticon: '2'\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t});\n\t\n\t// before upload\n\t/*$(window).bind('beforeunload',function(){\n\t\treturn 'Glue尚未保存，确定离开Glue编辑器？';\n\t});*/\n\t\n});\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/view/static/js/jobgroup.index.1.js",
    "content": "$(function() {\n\n\t// remove\n\t$('.remove').on('click', function(){\n\t\tvar id = $(this).attr('id');\n\n\t\tlayer.confirm('确认删除分组?', {icon: 3, title:'系统提示'}, function(index){\n\t\t\tlayer.close(index);\n\n\t\t\t$.ajax({\n\t\t\t\ttype : 'POST',\n\t\t\t\turl : base_url + '/jobgroup/remove',\n\t\t\t\tdata : {\"id\":id},\n\t\t\t\tdataType : \"json\",\n\t\t\t\tsuccess : function(data){\n\t\t\t\t\tif (data.code == 200) {\n\t\t\t\t\t\tlayer.open({\n\t\t\t\t\t\t\ttitle: '系统提示',\n\t\t\t\t\t\t\tcontent: '删除成功',\n\t\t\t\t\t\t\ticon: '1',\n\t\t\t\t\t\t\tend: function(layero, index){\n\t\t\t\t\t\t\t\twindow.location.reload();\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\tlayer.open({\n\t\t\t\t\t\t\ttitle: '系统提示',\n\t\t\t\t\t\t\tcontent: (data.msg || \"删除失败\"),\n\t\t\t\t\t\t\ticon: '2'\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});\n\n\t// jquery.validate 自定义校验 “英文字母开头，只含有英文字母、数字和下划线”\n\tjQuery.validator.addMethod(\"myValid01\", function(value, element) {\n\t\tvar length = value.length;\n\t\tvar valid = /^[a-z][a-zA-Z0-9-]*$/;\n\t\treturn this.optional(element) || valid.test(value);\n\t}, \"限制以小写字母开头，由小写字母、数字和下划线组成\");\n\n\t$('.add').on('click', function(){\n\t\t$('#addModal').modal({backdrop: false, keyboard: false}).modal('show');\n\t});\n\tvar addModalValidate = $(\"#addModal .form\").validate({\n\t\terrorElement : 'span',\n\t\terrorClass : 'help-block',\n\t\tfocusInvalid : true,\n\t\trules : {\n\t\t\tappName : {\n\t\t\t\trequired : true,\n\t\t\t\trangelength:[4,64],\n\t\t\t\tmyValid01 : true\n\t\t\t},\n\t\t\ttitle : {\n\t\t\t\trequired : true,\n\t\t\t\trangelength:[4, 12]\n\t\t\t},\n\t\t\torder : {\n\t\t\t\trequired : true,\n\t\t\t\tdigits:true,\n\t\t\t\trange:[1,1000]\n\t\t\t}\n\t\t},\n\t\tmessages : {\n\t\t\tappName : {\n\t\t\t\trequired :\"请输入“AppName”\",\n\t\t\t\trangelength:\"AppName长度限制为4~64\",\n\t\t\t\tmyValid01: \"限制以小写字母开头，由小写字母、数字和中划线组成\"\n\t\t\t},\n\t\t\ttitle : {\n\t\t\t\trequired :\"请输入“执行器名称”\",\n\t\t\t\trangelength:\"长度限制为4~12\"\n\t\t\t},\n\t\t\torder : {\n\t\t\t\trequired :\"请输入“排序”\",\n\t\t\t\tdigits: \"请输入整数\",\n\t\t\t\trange: \"取值范围为1~1000\"\n\t\t\t}\n\t\t},\n\t\thighlight : function(element) {\n\t\t\t$(element).closest('.form-group').addClass('has-error');\n\t\t},\n\t\tsuccess : function(label) {\n\t\t\tlabel.closest('.form-group').removeClass('has-error');\n\t\t\tlabel.remove();\n\t\t},\n\t\terrorPlacement : function(error, element) {\n\t\t\telement.parent('div').append(error);\n\t\t},\n\t\tsubmitHandler : function(form) {\n\t\t\t$.post(base_url + \"/jobgroup/save\",  $(\"#addModal .form\").serialize(), function(data, status) {\n\t\t\t\tif (data.code == \"200\") {\n\t\t\t\t\t$('#addModal').modal('hide');\n\t\t\t\t\tlayer.open({\n\t\t\t\t\t\ttitle: '系统提示',\n\t\t\t\t\t\tcontent: '新增成功',\n\t\t\t\t\t\ticon: '1',\n\t\t\t\t\t\tend: function(layero, index){\n\t\t\t\t\t\t\twindow.location.reload();\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tlayer.open({\n\t\t\t\t\t\ttitle: '系统提示',\n\t\t\t\t\t\tcontent: (data.msg || \"新增失败\"),\n\t\t\t\t\t\ticon: '2'\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t});\n\t$(\"#addModal\").on('hide.bs.modal', function () {\n\t\t$(\"#addModal .form\")[0].reset();\n\t\taddModalValidate.resetForm();\n\t\t$(\"#addModal .form .form-group\").removeClass(\"has-error\");\n\t});\n\n\t// 注册方式，切换\n\t$(\"#addModal input[name=addressType], #updateModal input[name=addressType]\").click(function(){\n\t\tvar addressType = $(this).val();\n\t\tvar $addressList = $(this).parents(\"form\").find(\"input[name=addressList]\");\n\t\tif (addressType == 0) {\n\t\t\t$addressList.val(\"\");\n\t\t\t$addressList.attr(\"readonly\",\"readonly\");\n\t\t} else {\n\t\t\t$addressList.removeAttr(\"readonly\");\n\t\t}\n\t});\n\n\t// update\n\t$('.update').on('click', function(){\n\t\t$(\"#updateModal .form input[name='id']\").val($(this).attr(\"id\"));\n\t\t$(\"#updateModal .form input[name='appName']\").val($(this).attr(\"appName\"));\n\t\t$(\"#updateModal .form input[name='title']\").val($(this).attr(\"title\"));\n\t\t$(\"#updateModal .form input[name='order']\").val($(this).attr(\"order\"));\n\n\t\t// 注册方式\n\t\tvar addressType = $(this).attr(\"addressType\");\n\t\t$(\"#updateModal .form input[name='addressType']\").removeAttr('checked');\n\t\t//$(\"#updateModal .form input[name='addressType'][value='\"+ addressType +\"']\").attr('checked', 'true');\n\t\t$(\"#updateModal .form input[name='addressType'][value='\"+ addressType +\"']\").click();\n\t\t// 机器地址\n\t\t$(\"#updateModal .form input[name='addressList']\").val($(this).attr(\"addressList\"));\n\n\t\t$('#updateModal').modal({backdrop: false, keyboard: false}).modal('show');\n\t});\n\tvar updateModalValidate = $(\"#updateModal .form\").validate({\n\t\terrorElement : 'span',\n\t\terrorClass : 'help-block',\n\t\tfocusInvalid : true,\n\t\trules : {\n\t\t\tappName : {\n\t\t\t\trequired : true,\n\t\t\t\trangelength:[4,64],\n\t\t\t\tmyValid01 : true\n\t\t\t},\n\t\t\ttitle : {\n\t\t\t\trequired : true,\n\t\t\t\trangelength:[4, 12]\n\t\t\t},\n\t\t\torder : {\n\t\t\t\trequired : true,\n\t\t\t\tdigits:true,\n\t\t\t\trange:[1,1000]\n\t\t\t}\n\t\t},\n\t\tmessages : {\n\t\t\tappName : {\n\t\t\t\trequired :\"请输入“AppName”\",\n\t\t\t\trangelength:\"AppName长度限制为4~64\",\n\t\t\t\tmyValid01: \"限制以小写字母开头，由小写字母、数字和中划线组成\"\n\t\t\t},\n\t\t\ttitle : {\n\t\t\t\trequired :\"请输入“执行器名称”\",\n\t\t\t\trangelength:\"长度限制为4~12\"\n\t\t\t},\n\t\t\torder : {\n\t\t\t\trequired :\"请输入“排序”\",\n\t\t\t\tdigits: \"请输入整数\",\n\t\t\t\trange: \"取值范围为1~1000\"\n\t\t\t}\n\t\t},\n\t\thighlight : function(element) {\n\t\t\t$(element).closest('.form-group').addClass('has-error');\n\t\t},\n\t\tsuccess : function(label) {\n\t\t\tlabel.closest('.form-group').removeClass('has-error');\n\t\t\tlabel.remove();\n\t\t},\n\t\terrorPlacement : function(error, element) {\n\t\t\telement.parent('div').append(error);\n\t\t},\n\t\tsubmitHandler : function(form) {\n\t\t\t$.post(base_url + \"/jobgroup/update\",  $(\"#updateModal .form\").serialize(), function(data, status) {\n\t\t\t\tif (data.code == \"200\") {\n\t\t\t\t\t$('#addModal').modal('hide');\n\n\t\t\t\t\tlayer.open({\n\t\t\t\t\t\ttitle: '系统提示',\n\t\t\t\t\t\tcontent: '更新成功',\n\t\t\t\t\t\ticon: '1',\n\t\t\t\t\t\tend: function(layero, index){\n\t\t\t\t\t\t\twindow.location.reload();\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tlayer.open({\n\t\t\t\t\t\ttitle: '系统提示',\n\t\t\t\t\t\tcontent: (data.msg || \"更新失败\"),\n\t\t\t\t\t\ticon: '2'\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t});\n\t$(\"#updateModal\").on('hide.bs.modal', function () {\n\t\t$(\"#updateModal .form\")[0].reset();\n\t\taddModalValidate.resetForm();\n\t\t$(\"#updateModal .form .form-group\").removeClass(\"has-error\");\n\t});\n\n\t\n});\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/view/static/js/jobinfo.index.1.js",
    "content": "$(function() {\n\t// init date tables\n\tvar jobTable = $(\"#job_list\").dataTable({\n\t\t\"deferRender\": true,\n\t\t\"processing\" : true, \n\t    \"serverSide\": true,\n\t\t\"ajax\": {\n\t\t\turl: base_url + \"/jobinfo/pageList\",\n\t\t\ttype:\"post\",\n\t        data : function ( d ) {\n\t        \tvar obj = {};\n\t        \tobj.jobGroup = $('#jobGroup').val();\n\t        \tobj.executorHandler = $('#executorHandler').val();\n\t        \tobj.start = d.start;\n\t        \tobj.length = d.length;\n                return obj;\n            }\n\t    },\n\t    \"searching\": false,\n\t    \"ordering\": false,\n\t    //\"scrollX\": true,\t// X轴滚动条，取消自适应\n\t    \"columns\": [\n\t                { \"data\": 'id', \"bSortable\": false, \"visible\" : false},\n\t                { \n\t                \t\"data\": 'jobGroup', \n\t                \t\"visible\" : false,\n\t                \t\"render\": function ( data, type, row ) {\n\t            \t\t\tvar groupMenu = $(\"#jobGroup\").find(\"option\");\n\t            \t\t\tfor ( var index in $(\"#jobGroup\").find(\"option\")) {\n\t            \t\t\t\tif ($(groupMenu[index]).attr('value') == data) {\n\t\t\t\t\t\t\t\t\treturn $(groupMenu[index]).html();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t            \t\t\treturn data;\n\t            \t\t}\n            \t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"data\": 'childJobKey',\n\t\t\t\t\t\t\"width\":'10%',\n\t\t\t\t\t\t\"visible\" : true,\n\t\t\t\t\t\t\"render\": function ( data, type, row ) {\n\t\t\t\t\t\t\tvar jobKey = row.jobGroup + \"_\" + row.id;\n\t\t\t\t\t\t\treturn jobKey;\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t                { \"data\": 'jobDesc', \"visible\" : true,\"width\":'20%'},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"data\": 'glueType',\n\t\t\t\t\t\t\"width\":'20%',\n\t\t\t\t\t\t\"visible\" : true,\n\t\t\t\t\t\t\"render\": function ( data, type, row ) {\n\t\t\t\t\t\t\tif ('GLUE_GROOVY'==row.glueType) {\n\t\t\t\t\t\t\t\treturn \"GLUE模式(Java)\";\n\t\t\t\t\t\t\t} else if ('GLUE_SHELL'==row.glueType) {\n\t\t\t\t\t\t\t\treturn \"GLUE模式(Shell)\";\n\t\t\t\t\t\t\t} else if ('GLUE_PYTHON'==row.glueType) {\n\t\t\t\t\t\t\t\treturn \"GLUE模式(Python)\";\n\t\t\t\t\t\t\t} else if ('BEAN'==row.glueType) {\n\t\t\t\t\t\t\t\treturn \"BEAN模式：\" + row.executorHandler;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn row.executorHandler;\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t                { \"data\": 'executorParam', \"visible\" : false},\n\t\t\t\t\t{ \"data\": 'jobCron', \"visible\" : true,\"width\":'10%'},\n\t                { \n\t                \t\"data\": 'addTime', \n\t                \t\"visible\" : false, \n\t                \t\"render\": function ( data, type, row ) {\n\t                \t\treturn data?moment(new Date(data)).format(\"YYYY-MM-DD HH:mm:ss\"):\"\";\n\t                \t}\n\t                },\n\t                { \n\t                \t\"data\": 'updateTime', \n\t                \t\"visible\" : false, \n\t                \t\"render\": function ( data, type, row ) {\n\t                \t\treturn data?moment(new Date(data)).format(\"YYYY-MM-DD HH:mm:ss\"):\"\";\n\t                \t}\n\t                },\n\t                { \"data\": 'author', \"visible\" : true, \"width\":'10%'},\n\t                { \"data\": 'alarmEmail', \"visible\" : false},\n\t                { \"data\": 'glueType', \"visible\" : false},\n\t                { \n\t                \t\"data\": 'jobStatus',\n\t\t\t\t\t\t\"width\":'10%',\n\t                \t\"visible\" : true,\n\t                \t\"render\": function ( data, type, row ) {\n\t                \t\tif ('NORMAL' == data) {\n\t                \t\t\treturn '<small class=\"label label-success\" ><i class=\"fa fa-clock-o\"></i>'+ data +'</small>'; \n\t\t\t\t\t\t\t} else if ('PAUSED' == data){\n\t\t\t\t\t\t\t\treturn '<small class=\"label label-default\" title=\"暂停\" ><i class=\"fa fa-clock-o\"></i>'+ data +'</small>'; \n\t\t\t\t\t\t\t} else if ('BLOCKED' == data){\n\t\t\t\t\t\t\t\treturn '<small class=\"label label-default\" title=\"阻塞[串行]\" ><i class=\"fa fa-clock-o\"></i>'+ data +'</small>'; \n\t\t\t\t\t\t\t}\n\t                \t\treturn data;\n\t                \t}\n\t                },\n\t                {\n\t\t\t\t\t\t\"data\": '操作' ,\n\t\t\t\t\t\t\"width\":'15%',\n\t                \t\"render\": function ( data, type, row ) {\n\t                \t\treturn function(){\n\t                \t\t\t// status\n\t                \t\t\tvar pause_resume = \"\";\n\t                \t\t\tif ('NORMAL' == row.jobStatus) {\n\t                \t\t\t\tpause_resume = '<button class=\"btn btn-primary btn-xs job_operate\" _type=\"job_pause\" type=\"button\">暂停</button>  ';\n\t\t\t\t\t\t\t\t} else if ('PAUSED' == row.jobStatus){\n\t\t\t\t\t\t\t\t\tpause_resume = '<button class=\"btn btn-primary btn-xs job_operate\" _type=\"job_resume\" type=\"button\">恢复</button>  ';\n\t\t\t\t\t\t\t\t}\n\t                \t\t\t// log url\n\t                \t\t\tvar logUrl = base_url +'/joblog?jobId='+ row.id;\n\t                \t\t\t\n\t                \t\t\t// log url\n\t                \t\t\tvar codeBtn = \"\";\n                                if ('BEAN' != row.glueType) {\n\t\t\t\t\t\t\t\t\tvar codeUrl = base_url +'/jobcode?jobId='+ row.id;\n\t\t\t\t\t\t\t\t\tcodeBtn = '<button class=\"btn btn-warning btn-xs\" type=\"button\" onclick=\"javascript:window.open(\\'' + codeUrl + '\\')\" >GLUE</button>  '\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// html\n                                tableData['key'+row.id] = row;\n\t\t\t\t\t\t\t\tvar html = '<p id=\"'+ row.id +'\" >'+\n\t\t\t\t\t\t\t\t\t'<button class=\"btn btn-primary btn-xs job_operate\" _type=\"job_trigger\" type=\"button\">执行</button>  '+\n\t\t\t\t\t\t\t\t\tpause_resume +\n\t\t\t\t\t\t\t\t\t'<button class=\"btn btn-primary btn-xs\" type=\"job_del\" type=\"button\" onclick=\"javascript:window.open(\\'' + logUrl + '\\')\" >日志</button><br>  '+\n\t\t\t\t\t\t\t\t\t'<button class=\"btn btn-warning btn-xs update\" type=\"button\">编辑</button>  '+\n\t\t\t\t\t\t\t\t\tcodeBtn +\n\t\t\t\t\t\t\t\t\t'<button class=\"btn btn-danger btn-xs job_operate\" _type=\"job_del\" type=\"button\">删除</button>  '+\n\t\t\t\t\t\t\t\t\t'</p>';\n\n\t                \t\t\treturn html;\n\t\t\t\t\t\t\t};\n\t                \t}\n\t                }\n\t            ],\n\t\t\"language\" : {\n\t\t\t\"sProcessing\" : \"处理中...\",\n\t\t\t\"sLengthMenu\" : \"每页 _MENU_ 条记录\",\n\t\t\t\"sZeroRecords\" : \"没有匹配结果\",\n\t\t\t\"sInfo\" : \"第 _PAGE_ 页 ( 总共 _PAGES_ 页，_TOTAL_ 条记录 )\",\n\t\t\t\"sInfoEmpty\" : \"无记录\",\n\t\t\t\"sInfoFiltered\" : \"(由 _MAX_ 项结果过滤)\",\n\t\t\t\"sInfoPostFix\" : \"\",\n\t\t\t\"sSearch\" : \"搜索:\",\n\t\t\t\"sUrl\" : \"\",\n\t\t\t\"sEmptyTable\" : \"表中数据为空\",\n\t\t\t\"sLoadingRecords\" : \"载入中...\",\n\t\t\t\"sInfoThousands\" : \",\",\n\t\t\t\"oPaginate\" : {\n\t\t\t\t\"sFirst\" : \"首页\",\n\t\t\t\t\"sPrevious\" : \"上页\",\n\t\t\t\t\"sNext\" : \"下页\",\n\t\t\t\t\"sLast\" : \"末页\"\n\t\t\t},\n\t\t\t\"oAria\" : {\n\t\t\t\t\"sSortAscending\" : \": 以升序排列此列\",\n\t\t\t\t\"sSortDescending\" : \": 以降序排列此列\"\n\t\t\t}\n\t\t}\n\t});\n\n    // table data\n    var tableData = {};\n\n\t// 搜索按钮\n\t$('#searchBtn').on('click', function(){\n\t\tjobTable.fnDraw();\n\t});\n\t\n\t// jobGroup change\n\t$('#jobGroup').on('change', function(){\n        //reload\n        var jobGroup = $('#jobGroup').val();\n        window.location.href = base_url + \"/jobinfo?jobGroup=\" + jobGroup;\n    });\n\t\n\t// job operate\n\t$(\"#job_list\").on('click', '.job_operate',function() {\n\t\tvar typeName;\n\t\tvar url;\n\t\tvar needFresh = false;\n\n\t\tvar type = $(this).attr(\"_type\");\n\t\tif (\"job_pause\" == type) {\n\t\t\ttypeName = \"暂停\";\n\t\t\turl = base_url + \"/jobinfo/pause\";\n\t\t\tneedFresh = true;\n\t\t} else if (\"job_resume\" == type) {\n\t\t\ttypeName = \"恢复\";\n\t\t\turl = base_url + \"/jobinfo/resume\";\n\t\t\tneedFresh = true;\n\t\t} else if (\"job_del\" == type) {\n\t\t\ttypeName = \"删除\";\n\t\t\turl = base_url + \"/jobinfo/remove\";\n\t\t\tneedFresh = true;\n\t\t} else if (\"job_trigger\" == type) {\n\t\t\ttypeName = \"执行\";\n\t\t\turl = base_url + \"/jobinfo/trigger\";\n\t\t} else {\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tvar id = $(this).parent('p').attr(\"id\");\n\n\t\tlayer.confirm('确认' + typeName + '?', {icon: 3, title:'系统提示'}, function(index){\n\t\t\tlayer.close(index);\n\n\t\t\t$.ajax({\n\t\t\t\ttype : 'POST',\n\t\t\t\turl : url,\n\t\t\t\tdata : {\n\t\t\t\t\t\"id\" : id\n\t\t\t\t},\n\t\t\t\tdataType : \"json\",\n\t\t\t\tsuccess : function(data){\n\t\t\t\t\tif (data.code == 200) {\n\n\t\t\t\t\t\tlayer.open({\n\t\t\t\t\t\t\ttitle: '系统提示',\n\t\t\t\t\t\t\tcontent: typeName + \"成功\",\n\t\t\t\t\t\t\ticon: '1',\n\t\t\t\t\t\t\tend: function(layero, index){\n\t\t\t\t\t\t\t\tif (needFresh) {\n\t\t\t\t\t\t\t\t\t//window.location.reload();\n\t\t\t\t\t\t\t\t\tjobTable.fnDraw();\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\tlayer.open({\n\t\t\t\t\t\t\ttitle: '系统提示',\n\t\t\t\t\t\t\tcontent: (data.msg || typeName + \"失败\"),\n\t\t\t\t\t\t\ticon: '2'\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\t\n\t// jquery.validate 自定义校验 “英文字母开头，只含有英文字母、数字和下划线”\n\tjQuery.validator.addMethod(\"myValid01\", function(value, element) {\n\t\tvar length = value.length;\n\t\tvar valid = /^[a-zA-Z][a-zA-Z0-9_]*$/;\n\t\treturn this.optional(element) || valid.test(value);\n\t}, \"只支持英文字母开头，只含有英文字母、数字和下划线\");\n\t\n\t// 新增\n\t$(\".add\").click(function(){\n\t\t$('#addModal').modal({backdrop: false, keyboard: false}).modal('show');\n\t});\n\tvar addModalValidate = $(\"#addModal .form\").validate({\n\t\terrorElement : 'span',  \n        errorClass : 'help-block',\n        focusInvalid : true,  \n        rules : {\n\t\t\tjobDesc : {\n\t\t\t\trequired : true,\n\t\t\t\tmaxlength: 50\n\t\t\t},\n            jobCron : {\n            \trequired : true\n            },\n\t\t\tauthor : {\n\t\t\t\trequired : true\n\t\t\t}\n        }, \n        messages : {  \n            jobDesc : {\n            \trequired :\"请输入“描述”.\"\n            },\n            jobCron : {\n            \trequired :\"请输入“Cron”.\"\n            },\n            author : {\n            \trequired : \"请输入“负责人”.\"\n            }\n        },\n\t\thighlight : function(element) {  \n            $(element).closest('.form-group').addClass('has-error');  \n        },\n        success : function(label) {  \n            label.closest('.form-group').removeClass('has-error');  \n            label.remove();  \n        },\n        errorPlacement : function(error, element) {  \n            element.parent('div').append(error);  \n        },\n        submitHandler : function(form) {\n        \t$.post(base_url + \"/jobinfo/add\",  $(\"#addModal .form\").serialize(), function(data, status) {\n    \t\t\tif (data.code == \"200\") {\n\t\t\t\t\t$('#addModal').modal('hide');\n\t\t\t\t\tlayer.open({\n\t\t\t\t\t\ttitle: '系统提示',\n\t\t\t\t\t\tcontent: '新增任务成功',\n\t\t\t\t\t\ticon: '1',\n\t\t\t\t\t\tend: function(layero, index){\n\t\t\t\t\t\t\tjobTable.fnDraw();\n\t\t\t\t\t\t\t//window.location.reload();\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n    \t\t\t} else {\n\t\t\t\t\tlayer.open({\n\t\t\t\t\t\ttitle: '系统提示',\n\t\t\t\t\t\tcontent: (data.msg || \"新增失败\"),\n\t\t\t\t\t\ticon: '2'\n\t\t\t\t\t});\n    \t\t\t}\n    \t\t});\n\t\t}\n\t});\n\t$(\"#addModal\").on('hide.bs.modal', function () {\n\t\t$(\"#addModal .form\")[0].reset();\n\t\taddModalValidate.resetForm();\n\t\t$(\"#addModal .form .form-group\").removeClass(\"has-error\");\n\t\t$(\".remote_panel\").show();\t// remote\n\n\t\t$(\"#addModal .form input[name='executorHandler']\").removeAttr(\"readonly\");\n\t});\n\n\n    // 运行模式\n    $(\".glueType\").change(function(){\n\t\t// executorHandler\n        var $executorHandler = $(this).parents(\"form\").find(\"input[name='executorHandler']\");\n        var glueType = $(this).val();\n        if ('BEAN' != glueType) {\n            $executorHandler.val(\"\");\n            $executorHandler.attr(\"readonly\",\"readonly\");\n        } else {\n            $executorHandler.removeAttr(\"readonly\");\n        }\n    });\n\n\t$(\"#addModal .glueType\").change(function(){\n\t\t// glueSource\n\t\tvar glueType = $(this).val();\n\t\tif ('GLUE_GROOVY'==glueType){\n\t\t\t$(\"#addModal .form textarea[name='glueSource']\").val( $(\"#addModal .form .glueSource_java\").val() );\n\t\t} else if ('GLUE_SHELL'==glueType){\n\t\t\t$(\"#addModal .form textarea[name='glueSource']\").val( $(\"#addModal .form .glueSource_shell\").val() );\n\t\t} else if ('GLUE_PYTHON'==glueType){\n\t\t\t$(\"#addModal .form textarea[name='glueSource']\").val( $(\"#addModal .form .glueSource_python\").val() );\n\t\t}\n\t});\n\n\t// 更新\n\t$(\"#job_list\").on('click', '.update',function() {\n\n        var id = $(this).parent('p').attr(\"id\");\n        var row = tableData['key'+id];\n        if (!row) {\n            layer.open({\n                title: '系统提示',\n                content: (\"任务信息加载失败，请刷新页面\"),\n                icon: '2'\n            });\n            return;\n        }\n\n\t\t// base data\n\t\t$(\"#updateModal .form input[name='id']\").val( row.id );\n\t\t$('#updateModal .form select[name=jobGroup] option[value='+ row.jobGroup +']').prop('selected', true);\n\t\t$(\"#updateModal .form input[name='jobDesc']\").val( row.jobDesc );\n\t\t$(\"#updateModal .form input[name='jobCron']\").val( row.jobCron );\n\t\t$(\"#updateModal .form input[name='author']\").val( row.author );\n\t\t$(\"#updateModal .form input[name='alarmEmail']\").val( row.alarmEmail );\n\t\t$('#updateModal .form select[name=executorRouteStrategy] option[value='+ row.executorRouteStrategy +']').prop('selected', true);\n\t\t$(\"#updateModal .form input[name='executorHandler']\").val( row.executorHandler );\n\t\t$(\"#updateModal .form input[name='executorParam']\").val( row.executorParam );\n        $(\"#updateModal .form input[name='childJobKey']\").val( row.childJobKey );\n\t\t$('#updateModal .form select[name=executorBlockStrategy] option[value='+ row.executorBlockStrategy +']').prop('selected', true);\n\t\t$('#updateModal .form select[name=executorFailStrategy] option[value='+ row.executorFailStrategy +']').prop('selected', true);\n\t\t$('#updateModal .form select[name=glueType] option[value='+ row.glueType +']').prop('selected', true);\n\n        $(\"#updateModal .form select[name=glueType]\").change();\n\n\t\t// show\n\t\t$('#updateModal').modal({backdrop: false, keyboard: false}).modal('show');\n\t});\n\tvar updateModalValidate = $(\"#updateModal .form\").validate({\n\t\terrorElement : 'span',  \n        errorClass : 'help-block',\n        focusInvalid : true,\n\n\t\trules : {\n\t\t\tjobDesc : {\n\t\t\t\trequired : true,\n\t\t\t\tmaxlength: 50\n\t\t\t},\n\t\t\tjobCron : {\n\t\t\t\trequired : true\n\t\t\t},\n\t\t\tauthor : {\n\t\t\t\trequired : true\n\t\t\t}\n\t\t},\n\t\tmessages : {\n\t\t\tjobDesc : {\n\t\t\t\trequired :\"请输入“描述”.\"\n\t\t\t},\n\t\t\tjobCron : {\n\t\t\t\trequired :\"请输入“Cron”.\"\n\t\t\t},\n\t\t\tauthor : {\n\t\t\t\trequired : \"请输入“负责人”.\"\n\t\t\t}\n\t\t},\n\t\thighlight : function(element) {\n            $(element).closest('.form-group').addClass('has-error');  \n        },\n        success : function(label) {  \n            label.closest('.form-group').removeClass('has-error');  \n            label.remove();  \n        },\n        errorPlacement : function(error, element) {  \n            element.parent('div').append(error);  \n        },\n        submitHandler : function(form) {\n\t\t\t// post\n    \t\t$.post(base_url + \"/jobinfo/reschedule\", $(\"#updateModal .form\").serialize(), function(data, status) {\n    \t\t\tif (data.code == \"200\") {\n\t\t\t\t\t$('#updateModal').modal('hide');\n\t\t\t\t\tlayer.open({\n\t\t\t\t\t\ttitle: '系统提示',\n\t\t\t\t\t\tcontent: '更新成功',\n\t\t\t\t\t\ticon: '1',\n\t\t\t\t\t\tend: function(layero, index){\n\t\t\t\t\t\t\t//window.location.reload();\n\t\t\t\t\t\t\tjobTable.fnDraw();\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n    \t\t\t} else {\n\t\t\t\t\tlayer.open({\n\t\t\t\t\t\ttitle: '系统提示',\n\t\t\t\t\t\tcontent: (data.msg || \"更新失败\"),\n\t\t\t\t\t\ticon: '2'\n\t\t\t\t\t});\n    \t\t\t}\n    \t\t});\n\t\t}\n\t});\n\t$(\"#updateModal\").on('hide.bs.modal', function () {\n\t\t$(\"#updateModal .form\")[0].reset()\n\t});\n\n});\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/view/static/js/joblog.detail.1.js",
    "content": "$(function() {\n\n    // trigger fail, end\n    if (triggerCode != 200) {\n        $('#logConsoleRunning').hide();\n        $('#logConsole').append('<span style=\"color: red;\">任务发起调度失败，无法查看执行日志</span>');\n        return;\n    }\n\n    // pull log\n    var fromLineNum = 1;    // [from, to], start as 1\n    var pullFailCount = 0;\n    function pullLog() {\n        // pullFailCount, max=20\n        if (pullFailCount++ > 20) {\n            logRunStop('<span style=\"color: red;\">终止请求Rolling日志,请求失败次数超上限,可刷新页面重新加载日志</span>');\n            return;\n        }\n\n        // load\n        console.log(\"pullLog, fromLineNum:\" + fromLineNum);\n\n        $.ajax({\n            type : 'POST',\n            async: false,   // sync, make log ordered\n            url : base_url + '/joblog/logDetailCat',\n            data : {\n                \"executorAddress\":executorAddress,\n                \"triggerTime\":triggerTime,\n                \"logId\":logId,\n                \"fromLineNum\":fromLineNum\n            },\n            dataType : \"json\",\n            success : function(data){\n\n                if (data.code == 200) {\n                    if (!data.content) {\n                        console.log('pullLog fail');\n                        return;\n                    }\n                    if (fromLineNum != data.content.fromLineNum) {\n                        console.log('pullLog fromLineNum not match');\n                        return;\n                    }\n                    if (fromLineNum > data.content.toLineNum ) {\n                        console.log('pullLog already line-end');\n\n                        // valid end\n                        if (data.content.end) {\n                            logRunStop('<br><span style=\"color: green;\">[Rolling Log Finish]</span>');\n                            return;\n                        }\n\n                        return;\n                    }\n\n                    // append content\n                    fromLineNum = data.content.toLineNum + 1;\n                    $('#logConsole').append(data.content.logContent);\n                    pullFailCount = 0;\n\n                    // scroll to bottom\n                    scrollTo(0, document.body.scrollHeight);        // $('#logConsolePre').scrollTop( document.body.scrollHeight + 300 );\n\n                } else {\n                    console.log('pullLog fail:'+data.msg);\n                }\n            }\n        });\n    }\n\n    // pull first page\n    pullLog();\n\n    // handler already callback, end\n    if (handleCode > 0) {\n        logRunStop('<br><span style=\"color: green;\">[Load Log Finish]</span>');\n        return;\n    }\n\n    // round until end\n    var logRun = setInterval(function () {\n        pullLog()\n    }, 3000);\n    function logRunStop(content){\n        $('#logConsoleRunning').hide();\n        logRun = window.clearInterval(logRun);\n        $('#logConsole').append(content);\n    }\n\n});\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/view/static/js/joblog.index.1.js",
    "content": "$(function() {\n\n\t// 任务组列表选中, 任务列表初始化和选中\n\t$(\"#jobGroup\").on(\"change\", function () {\n\t\tvar jobGroup = $(this).children('option:selected').val();\n\t\t$.ajax({\n\t\t\ttype : 'POST',\n            async: false,   // async, avoid js invoke pagelist before jobId data init\n\t\t\turl : base_url + '/joblog/getJobsByGroup',\n\t\t\tdata : {\"jobGroup\":jobGroup},\n\t\t\tdataType : \"json\",\n\t\t\tsuccess : function(data){\n\t\t\t\tif (data.code == 200) {\n\t\t\t\t\t$(\"#jobId\").html('<option value=\"0\" >全部</option>');\n\t\t\t\t\t$.each(data.content, function (n, value) {\n                        $(\"#jobId\").append('<option value=\"' + value.id + '\" >' + value.jobDesc + '</option>');\n                    });\n                    if ($(\"#jobId\").attr(\"paramVal\")){\n                        $(\"#jobId\").find(\"option[value='\" + $(\"#jobId\").attr(\"paramVal\") + \"']\").attr(\"selected\",true);\n                    }\n\t\t\t\t} else {\n\t\t\t\t\tlayer.open({\n\t\t\t\t\t\ttitle: '系统提示',\n\t\t\t\t\t\tcontent: (data.msg || \"接口异常\"),\n\t\t\t\t\t\ticon: '2'\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t});\n\tif ($(\"#jobGroup\").attr(\"paramVal\")){\n\t\t$(\"#jobGroup\").find(\"option[value='\" + $(\"#jobGroup\").attr(\"paramVal\") + \"']\").attr(\"selected\",true);\n        $(\"#jobGroup\").change();\n\t}\n\n\t// 过滤时间\n\t$('#filterTime').daterangepicker({\n        autoApply:false,\n        singleDatePicker:false,\n        showDropdowns:false,        // 是否显示年月选择条件\n\t\ttimePicker: true, \t\t\t// 是否显示小时和分钟选择条件\n\t\ttimePickerIncrement: 10, \t// 时间的增量，单位为分钟\n        timePicker24Hour : true,\n        opens : 'left', //日期选择框的弹出位置\n\t\tranges: {\n\t\t\t'最近1小时': [moment().subtract(1, 'hours'), moment()],\n\t\t\t'今日': [moment().startOf('day'), moment().endOf('day')],\n\t\t\t'昨日': [moment().subtract(1, 'days').startOf('day'), moment().subtract(1, 'days').endOf('day')],\n\t\t\t'最近7日': [moment().subtract(6, 'days'), moment()],\n\t\t\t'最近30日': [moment().subtract(29, 'days'), moment()],\n\t\t\t'本月': [moment().startOf('month'), moment().endOf('month')],\n\t\t\t'上个月': [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')]\n\t\t},\n        locale : {\n            format: 'YYYY-MM-DD HH:mm:ss',\n            separator : ' - ',\n        \tcustomRangeLabel : '自定义',\n            applyLabel : '确定',\n            cancelLabel : '取消',\n            fromLabel : '起始时间',\n            toLabel : '结束时间',\n            daysOfWeek : [ '日', '一', '二', '三', '四', '五', '六' ],\n            monthNames : [ '一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月' ],\n            firstDay : 1,\n            startDate: moment().startOf('day'),\n            endDate: moment().endOf('day')\n        }\n\t});\n\n\t// init date tables\n\tvar logTable = $(\"#joblog_list\").dataTable({\n\t\t\"deferRender\": true,\n\t\t\"processing\" : true, \n\t    \"serverSide\": true,\n\t\t\"ajax\": {\n\t        url: base_url + \"/joblog/pageList\" ,\n\t        data : function ( d ) {\n\t        \tvar obj = {};\n\t        \tobj.jobGroup = $('#jobGroup').val();\n\t        \tobj.jobId = $('#jobId').val();\n                obj.logStatus = $('#logStatus').val();\n\t\t\t\tobj.filterTime = $('#filterTime').val();\n\t        \tobj.start = d.start;\n\t        \tobj.length = d.length;\n                return obj;\n            }\n\t    },\n\t    \"searching\": false,\n\t    \"ordering\": false,\n\t    //\"scrollX\": false,\n\t    \"columns\": [\n\t                { \"data\": 'id', \"bSortable\": false, \"visible\" : false},\n\t\t\t\t\t{ \"data\": 'jobGroup', \"visible\" : false},\n\t                { \"data\": 'jobId', \"visible\" : false},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"data\": 'JobKey',\n\t\t\t\t\t\t\"visible\" : true,\n\t\t\t\t\t\t\"render\": function ( data, type, row ) {\n\t\t\t\t\t\t\tvar jobKey = row.jobGroup + \"_\" + row.jobId;\n\n                            var glueTypeTitle = row.glueType;\n                            if ('GLUE_GROOVY'==row.glueType) {\n                                glueTypeTitle = \"GLUE模式(Java)\";\n                            } else if ('GLUE_SHELL'==row.glueType) {\n                                glueTypeTitle = \"GLUE模式(Shell)\";\n                            } else if ('GLUE_PYTHON'==row.glueType) {\n                                glueTypeTitle = \"GLUE模式(Python)\";\n                            } else if ('BEAN'==row.glueType) {\n                                glueTypeTitle = \"BEAN模式：\" + row.executorHandler;\n                            }\n\n                            var temp = '';\n                            temp += '执行器地址：' + (row.executorAddress?row.executorAddress:'');\n                            temp += '<br>运行模式：' + glueTypeTitle;\n                            temp += '<br>任务参数：' + row.executorParam;\n\n                            return '<a class=\"logTips\" href=\"javascript:;\" >'+ jobKey +'<span style=\"display:none;\">'+ temp +'</span></a>';\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t// { \"data\": 'executorAddress', \"visible\" : true},\n\t\t\t\t\t// {\n\t\t\t\t\t// \t\"data\": 'glueType',\n\t\t\t\t\t//  \t\"visible\" : true,\n\t\t\t\t\t// \t\"render\": function ( data, type, row ) {\n\t\t\t\t\t// \t\tif ('GLUE_GROOVY'==row.glueType) {\n\t\t\t\t\t// \t\t\treturn \"GLUE模式(Java)\";\n\t\t\t\t\t// \t\t} else if ('GLUE_SHELL'==row.glueType) {\n\t\t\t\t\t// \t\t \treturn \"GLUE模式(Shell)\";\n\t\t\t\t\t// \t\t} else if ('GLUE_PYTHON'==row.glueType) {\n\t\t\t\t\t// \t\t\treturn \"GLUE模式(Python)\";\n\t\t\t\t\t// \t\t} else if ('BEAN'==row.glueType) {\n\t\t\t\t\t// \t\t \treturn \"BEAN模式：\" + row.executorHandler;\n\t\t\t\t\t// \t\t}\n\t\t\t\t\t// \t\treturn row.executorHandler;\n\t\t\t\t\t// \t }\n\t\t\t\t\t// },\n\t\t\t\t\t// { \"data\": 'executorParam', \"visible\" : true},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"data\": 'triggerTime',\n\t\t\t\t\t\t\"render\": function ( data, type, row ) {\n\t\t\t\t\t\t\treturn data?moment(new Date(data)).format(\"YYYY-MM-DD HH:mm:ss\"):\"\";\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"data\": 'triggerCode',\n\t\t\t\t\t\t\"render\": function ( data, type, row ) {\n\t\t\t\t\t\t\treturn (data==200)?'<span style=\"color: green\">成功</span>':(data==500)?'<span style=\"color: red\">失败</span>':(data==0)?'':data;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"data\": 'triggerMsg',\n\t\t\t\t\t\t\"render\": function ( data, type, row ) {\n\t\t\t\t\t\t\treturn data?'<a class=\"logTips\" href=\"javascript:;\" >查看<span style=\"display:none;\">'+ data +'</span></a>':\"无\";\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t                { \n\t                \t\"data\": 'handleTime',\n\t                \t\"render\": function ( data, type, row ) {\n\t                \t\treturn data?moment(new Date(data)).format(\"YYYY-MM-DD HH:mm:ss\"):\"\";\n\t                \t}\n\t                },\n\t                {\n\t\t\t\t\t\t\"data\": 'handleCode',\n\t\t\t\t\t\t\"render\": function ( data, type, row ) {\n\t\t\t\t\t\t\treturn (data==200)?'<span style=\"color: green\">成功</span>':(data==500)?'<span style=\"color: red\">失败</span>':(data==0)?'':data;\n\t\t\t\t\t\t}\n\t                },\n\t                { \n\t                \t\"data\": 'handleMsg',\n\t                \t\"render\": function ( data, type, row ) {\n\t                \t\treturn data?'<a class=\"logTips\" href=\"javascript:;\" >查看<span style=\"display:none;\">'+ data +'</span></a>':\"无\";\n\t                \t}\n\t                },\n\t                {\n\t\t\t\t\t\t\"data\": 'handleMsg' ,\n\t\t\t\t\t\t\"bSortable\": false,\n\t\t\t\t\t\t\"width\": \"8%\" ,\n\t                \t\"render\": function ( data, type, row ) {\n\t                \t\t// better support expression or string, not function\n\t                \t\treturn function () {\n\t\t                \t\tif (row.triggerCode == 200){\n\t\t                \t\t\tvar temp = '<a href=\"javascript:;\" class=\"logDetail\" _id=\"'+ row.id +'\">执行日志</a>';\n\t\t                \t\t\tif(row.handleCode == 0){\n\t\t                \t\t\t\ttemp += '<br><a href=\"javascript:;\" class=\"logKill\" _id=\"'+ row.id +'\" style=\"color: red;\" >终止任务</a>';\n\t\t                \t\t\t}\n\t\t                \t\t\treturn temp;\n\t\t                \t\t}\n\t\t                \t\treturn null;\t\n\t                \t\t}\n\t                \t}\n\t                }\n\t            ],\n\t\t\"language\" : {\n\t\t\t\"sProcessing\" : \"处理中...\",\n\t\t\t\"sLengthMenu\" : \"每页 _MENU_ 条记录\",\n\t\t\t\"sZeroRecords\" : \"没有匹配结果\",\n\t\t\t\"sInfo\" : \"第 _PAGE_ 页 ( 总共 _PAGES_ 页，_TOTAL_ 条记录 )\",\n\t\t\t\"sInfoEmpty\" : \"无记录\",\n\t\t\t\"sInfoFiltered\" : \"(由 _MAX_ 项结果过滤)\",\n\t\t\t\"sInfoPostFix\" : \"\",\n\t\t\t\"sSearch\" : \"搜索:\",\n\t\t\t\"sUrl\" : \"\",\n\t\t\t\"sEmptyTable\" : \"表中数据为空\",\n\t\t\t\"sLoadingRecords\" : \"载入中...\",\n\t\t\t\"sInfoThousands\" : \",\",\n\t\t\t\"oPaginate\" : {\n\t\t\t\t\"sFirst\" : \"首页\",\n\t\t\t\t\"sPrevious\" : \"上页\",\n\t\t\t\t\"sNext\" : \"下页\",\n\t\t\t\t\"sLast\" : \"末页\"\n\t\t\t},\n\t\t\t\"oAria\" : {\n\t\t\t\t\"sSortAscending\" : \": 以升序排列此列\",\n\t\t\t\t\"sSortDescending\" : \": 以降序排列此列\"\n\t\t\t}\n\t\t}\n\t});\n\t\n\t// 日志弹框提示\n\t$('#joblog_list').on('click', '.logTips', function(){\n\t\tvar msg = $(this).find('span').html();\n\t\tComAlertTec.show(msg);\n\t});\n\t\n\t// 搜索按钮\n\t$('#searchBtn').on('click', function(){\n\t\tlogTable.fnDraw();\n\t});\n\t\n\t// 查看执行器详细执行日志\n\t$('#joblog_list').on('click', '.logDetail', function(){\n\t\tvar _id = $(this).attr('_id');\n\t\t\n\t\twindow.open(base_url + '/joblog/logDetailPage?id=' + _id);\n\t\treturn;\n\t});\n\n\t/**\n\t * 终止任务\n\t */\n\t$('#joblog_list').on('click', '.logKill', function(){\n\t\tvar _id = $(this).attr('_id');\n\n        layer.confirm('确认主动终止任务?', {icon: 3, title:'系统提示'}, function(index){\n            layer.close(index);\n\n            $.ajax({\n                type : 'POST',\n                url : base_url + '/joblog/logKill',\n                data : {\"id\":_id},\n                dataType : \"json\",\n                success : function(data){\n                    if (data.code == 200) {\n                        layer.open({\n                            title: '系统提示',\n                            content: '操作成功',\n                            icon: '1',\n                            end: function(layero, index){\n                                logTable.fnDraw();\n                            }\n                        });\n                    } else {\n                        layer.open({\n                            title: '系统提示',\n                            content: (data.msg || \"操作失败\"),\n                            icon: '2'\n                        });\n                    }\n                },\n            });\n        });\n\n\t});\n\n\t/**\n\t * 清理任务Log\n\t */\n\t$('#clearLog').on('click', function(){\n\n\t\tvar jobGroup = $('#jobGroup').val();\n\t\tvar jobId = $('#jobId').val();\n\n\t\tvar jobGroupText = $(\"#jobGroup\").find(\"option:selected\").text();\n\t\tvar jobIdText = $(\"#jobId\").find(\"option:selected\").text();\n\n\t\t$('#clearLogModal input[name=jobGroup]').val(jobGroup);\n\t\t$('#clearLogModal input[name=jobId]').val(jobId);\n\n\t\t$('#clearLogModal .jobGroupText').val(jobGroupText);\n\t\t$('#clearLogModal .jobIdText').val(jobIdText);\n\n\t\t$('#clearLogModal').modal('show');\n\n\t});\n\t$(\"#clearLogModal .ok\").on('click', function(){\n\t\t$.post(base_url + \"/joblog/clearLog\",  $(\"#clearLogModal .form\").serialize(), function(data, status) {\n\t\t\tif (data.code == \"200\") {\n\t\t\t\t$('#clearLogModal').modal('hide');\n\t\t\t\tlayer.open({\n\t\t\t\t\ttitle: '系统提示',\n\t\t\t\t\tcontent: '日志清理成功',\n\t\t\t\t\ticon: '1',\n\t\t\t\t\tend: function(layero, index){\n\t\t\t\t\t\tlogTable.fnDraw();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tlayer.open({\n\t\t\t\t\ttitle: '系统提示',\n\t\t\t\t\tcontent: (data.msg || \"日志清理失败\"),\n\t\t\t\t\ticon: '2'\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t});\n\t$(\"#clearLogModal\").on('hide.bs.modal', function () {\n\t\t$(\"#clearLogModal .form\")[0].reset();\n\t});\n\n});\n\n\n// 提示-科技主题\nvar ComAlertTec = {\n\thtml:function(){\n\t\tvar html =\n\t\t\t'<div class=\"modal fade\" id=\"ComAlertTec\" tabindex=\"-1\" role=\"dialog\" aria-labelledby=\"myModalLabel\" aria-hidden=\"true\">' +\n\t\t\t'<div class=\"modal-dialog\">' +\n\t\t\t'<div class=\"modal-content-tec\">' +\n\t\t\t'<div class=\"modal-body\"><div class=\"alert\" style=\"color:#fff;\"></div></div>' +\n\t\t\t'<div class=\"modal-footer\">' +\n\t\t\t'<div class=\"text-center\" >' +\n\t\t\t'<button type=\"button\" class=\"btn btn-info ok\" data-dismiss=\"modal\" >确认</button>' +\n\t\t\t'</div>' +\n\t\t\t'</div>' +\n\t\t\t'</div>' +\n\t\t\t'</div>' +\n\t\t\t'</div>';\n\t\treturn html;\n\t},\n\tshow:function(msg, callback){\n\t\t// dom init\n\t\tif ($('#ComAlertTec').length == 0){\n\t\t\t$('body').append(ComAlertTec.html());\n\t\t}\n\n\t\t// 弹框初始\n\t\t$('#ComAlertTec .alert').html(msg);\n\t\t$('#ComAlertTec').modal('show');\n\n\t\t$('#ComAlertTec .ok').click(function(){\n\t\t\t$('#ComAlertTec').modal('hide');\n\t\t\tif(typeof callback == 'function') {\n\t\t\t\tcallback();\n\t\t\t}\n\t\t});\n\t}\n};\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/view/static/js/login.1.js",
    "content": "$(function(){\n\t// 复选框\n    $('input').iCheck({\n      checkboxClass: 'icheckbox_square-blue',\n      radioClass: 'iradio_square-blue',\n      increaseArea: '20%' // optional\n    });\n    \n\t// 登录.规则校验\n\tvar loginFormValid = $(\"#loginForm\").validate({\n\t\terrorElement : 'span',  \n        errorClass : 'help-block',\n        focusInvalid : true,  \n        rules : {  \n        \tuserName : {  \n        \t\trequired : true ,\n                minlength: 5,\n                maxlength: 18\n            },  \n            password : {  \n            \trequired : true ,\n                minlength: 5,\n                maxlength: 18\n            } \n        }, \n        messages : {  \n        \tuserName : {  \n                required :\"请输入登录账号.\"  ,\n                minlength:\"登录账号不应低于5位\",\n                maxlength:\"登录账号不应超过18位\"\n            },  \n            password : {\n            \trequired :\"请输入登录密码.\"  ,\n                minlength:\"登录密码不应低于5位\",\n                maxlength:\"登录密码不应超过18位\"\n            }\n        }, \n\t\thighlight : function(element) {  \n            $(element).closest('.form-group').addClass('has-error');  \n        },\n        success : function(label) {  \n            label.closest('.form-group').removeClass('has-error');  \n            label.remove();  \n        },\n        errorPlacement : function(error, element) {  \n            element.parent('div').append(error);  \n        },\n        submitHandler : function(form) {\n\t\t    console.log($(\"#loginForm\").serialize());\n\t\t\t$.post(base_url + \"/login\", $(\"#loginForm\").serialize(), function(data, status) {\n\t\t\t\tif (data.code == \"200\") {\n                    layer.open({\n                        title: '系统提示',\n                        content: '登录成功',\n                        icon: '1',\n                        end: function(layero, index){\n                            window.location.href = base_url;//+\"/index\"\n                        }\n                    });\n\t\t\t\t} else {\n                    layer.open({\n                        title: '系统提示',\n                        content: (data.msg || \"登录失败\"),\n                        icon: '2'\n                    });\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t});\n});"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/view/static/plugins/codemirror/addon/hint/anyword-hint.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n(function(mod) {\n  if (typeof exports == \"object\" && typeof module == \"object\") // CommonJS\n    mod(require(\"../../lib/codemirror\"));\n  else if (typeof define == \"function\" && define.amd) // AMD\n    define([\"../../lib/codemirror\"], mod);\n  else // Plain browser env\n    mod(CodeMirror);\n})(function(CodeMirror) {\n  \"use strict\";\n\n  var WORD = /[\\w$]+/, RANGE = 500;\n\n  CodeMirror.registerHelper(\"hint\", \"anyword\", function(editor, options) {\n    var word = options && options.word || WORD;\n    var range = options && options.range || RANGE;\n    var cur = editor.getCursor(), curLine = editor.getLine(cur.line);\n    var end = cur.ch, start = end;\n    while (start && word.test(curLine.charAt(start - 1))) --start;\n    var curWord = start != end && curLine.slice(start, end);\n\n    var list = options && options.list || [], seen = {};\n    var re = new RegExp(word.source, \"g\");\n    for (var dir = -1; dir <= 1; dir += 2) {\n      var line = cur.line, endLine = Math.min(Math.max(line + dir * range, editor.firstLine()), editor.lastLine()) + dir;\n      for (; line != endLine; line += dir) {\n        var text = editor.getLine(line), m;\n        while (m = re.exec(text)) {\n          if (line == cur.line && m[0] === curWord) continue;\n          if ((!curWord || m[0].lastIndexOf(curWord, 0) == 0) && !Object.prototype.hasOwnProperty.call(seen, m[0])) {\n            seen[m[0]] = true;\n            list.push(m[0]);\n          }\n        }\n      }\n    }\n    return {list: list, from: CodeMirror.Pos(cur.line, start), to: CodeMirror.Pos(cur.line, end)};\n  });\n});\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/view/static/plugins/codemirror/addon/hint/show-hint.css",
    "content": ".CodeMirror-hints {\n  position: absolute;\n  z-index: 10;\n  overflow: hidden;\n  list-style: none;\n\n  margin: 0;\n  padding: 2px;\n\n  -webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.2);\n  -moz-box-shadow: 2px 3px 5px rgba(0,0,0,.2);\n  box-shadow: 2px 3px 5px rgba(0,0,0,.2);\n  border-radius: 3px;\n  border: 1px solid silver;\n\n  background: white;\n  font-size: 90%;\n  font-family: monospace;\n\n  max-height: 20em;\n  overflow-y: auto;\n}\n\n.CodeMirror-hint {\n  margin: 0;\n  padding: 0 4px;\n  border-radius: 2px;\n  max-width: 19em;\n  overflow: hidden;\n  white-space: pre;\n  color: black;\n  cursor: pointer;\n}\n\nli.CodeMirror-hint-active {\n  background: #08f;\n  color: white;\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/view/static/plugins/codemirror/addon/hint/show-hint.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n(function(mod) {\n  if (typeof exports == \"object\" && typeof module == \"object\") // CommonJS\n    mod(require(\"../../lib/codemirror\"));\n  else if (typeof define == \"function\" && define.amd) // AMD\n    define([\"../../lib/codemirror\"], mod);\n  else // Plain browser env\n    mod(CodeMirror);\n})(function(CodeMirror) {\n  \"use strict\";\n\n  var HINT_ELEMENT_CLASS        = \"CodeMirror-hint\";\n  var ACTIVE_HINT_ELEMENT_CLASS = \"CodeMirror-hint-active\";\n\n  // This is the old interface, kept around for now to stay\n  // backwards-compatible.\n  CodeMirror.showHint = function(cm, getHints, options) {\n    if (!getHints) return cm.showHint(options);\n    if (options && options.async) getHints.async = true;\n    var newOpts = {hint: getHints};\n    if (options) for (var prop in options) newOpts[prop] = options[prop];\n    return cm.showHint(newOpts);\n  };\n\n  CodeMirror.defineExtension(\"showHint\", function(options) {\n    options = parseOptions(this, this.getCursor(\"start\"), options);\n    var selections = this.listSelections()\n    if (selections.length > 1) return;\n    // By default, don't allow completion when something is selected.\n    // A hint function can have a `supportsSelection` property to\n    // indicate that it can handle selections.\n    if (this.somethingSelected()) {\n      if (!options.hint.supportsSelection) return;\n      // Don't try with cross-line selections\n      for (var i = 0; i < selections.length; i++)\n        if (selections[i].head.line != selections[i].anchor.line) return;\n    }\n\n    if (this.state.completionActive) this.state.completionActive.close();\n    var completion = this.state.completionActive = new Completion(this, options);\n    if (!completion.options.hint) return;\n\n    CodeMirror.signal(this, \"startCompletion\", this);\n    completion.update(true);\n  });\n\n  function Completion(cm, options) {\n    this.cm = cm;\n    this.options = options;\n    this.widget = null;\n    this.debounce = 0;\n    this.tick = 0;\n    this.startPos = this.cm.getCursor(\"start\");\n    this.startLen = this.cm.getLine(this.startPos.line).length - this.cm.getSelection().length;\n\n    var self = this;\n    cm.on(\"cursorActivity\", this.activityFunc = function() { self.cursorActivity(); });\n  }\n\n  var requestAnimationFrame = window.requestAnimationFrame || function(fn) {\n    return setTimeout(fn, 1000/60);\n  };\n  var cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout;\n\n  Completion.prototype = {\n    close: function() {\n      if (!this.active()) return;\n      this.cm.state.completionActive = null;\n      this.tick = null;\n      this.cm.off(\"cursorActivity\", this.activityFunc);\n\n      if (this.widget && this.data) CodeMirror.signal(this.data, \"close\");\n      if (this.widget) this.widget.close();\n      CodeMirror.signal(this.cm, \"endCompletion\", this.cm);\n    },\n\n    active: function() {\n      return this.cm.state.completionActive == this;\n    },\n\n    pick: function(data, i) {\n      var completion = data.list[i];\n      if (completion.hint) completion.hint(this.cm, data, completion);\n      else this.cm.replaceRange(getText(completion), completion.from || data.from,\n                                completion.to || data.to, \"complete\");\n      CodeMirror.signal(data, \"pick\", completion);\n      this.close();\n    },\n\n    cursorActivity: function() {\n      if (this.debounce) {\n        cancelAnimationFrame(this.debounce);\n        this.debounce = 0;\n      }\n\n      var pos = this.cm.getCursor(), line = this.cm.getLine(pos.line);\n      if (pos.line != this.startPos.line || line.length - pos.ch != this.startLen - this.startPos.ch ||\n          pos.ch < this.startPos.ch || this.cm.somethingSelected() ||\n          (pos.ch && this.options.closeCharacters.test(line.charAt(pos.ch - 1)))) {\n        this.close();\n      } else {\n        var self = this;\n        this.debounce = requestAnimationFrame(function() {self.update();});\n        if (this.widget) this.widget.disable();\n      }\n    },\n\n    update: function(first) {\n      if (this.tick == null) return;\n      if (!this.options.hint.async) {\n        this.finishUpdate(this.options.hint(this.cm, this.options), first);\n      } else {\n        var myTick = ++this.tick, self = this;\n        this.options.hint(this.cm, function(data) {\n          if (self.tick == myTick) self.finishUpdate(data, first);\n        }, this.options);\n      }\n    },\n\n    finishUpdate: function(data, first) {\n      if (this.data) CodeMirror.signal(this.data, \"update\");\n\n      var picked = (this.widget && this.widget.picked) || (first && this.options.completeSingle);\n      if (this.widget) this.widget.close();\n\n      if (data && this.data && isNewCompletion(this.data, data)) return;\n      this.data = data;\n\n      if (data && data.list.length) {\n        if (picked && data.list.length == 1) {\n          this.pick(data, 0);\n        } else {\n          this.widget = new Widget(this, data);\n          CodeMirror.signal(data, \"shown\");\n        }\n      }\n    }\n  };\n\n  function isNewCompletion(old, nw) {\n    var moved = CodeMirror.cmpPos(nw.from, old.from)\n    return moved > 0 && old.to.ch - old.from.ch != nw.to.ch - nw.from.ch\n  }\n\n  function parseOptions(cm, pos, options) {\n    var editor = cm.options.hintOptions;\n    var out = {};\n    for (var prop in defaultOptions) out[prop] = defaultOptions[prop];\n    if (editor) for (var prop in editor)\n      if (editor[prop] !== undefined) out[prop] = editor[prop];\n    if (options) for (var prop in options)\n      if (options[prop] !== undefined) out[prop] = options[prop];\n    if (out.hint.resolve) out.hint = out.hint.resolve(cm, pos)\n    return out;\n  }\n\n  function getText(completion) {\n    if (typeof completion == \"string\") return completion;\n    else return completion.text;\n  }\n\n  function buildKeyMap(completion, handle) {\n    var baseMap = {\n      Up: function() {handle.moveFocus(-1);},\n      Down: function() {handle.moveFocus(1);},\n      PageUp: function() {handle.moveFocus(-handle.menuSize() + 1, true);},\n      PageDown: function() {handle.moveFocus(handle.menuSize() - 1, true);},\n      Home: function() {handle.setFocus(0);},\n      End: function() {handle.setFocus(handle.length - 1);},\n      Enter: handle.pick,\n      Tab: handle.pick,\n      Esc: handle.close\n    };\n    var custom = completion.options.customKeys;\n    var ourMap = custom ? {} : baseMap;\n    function addBinding(key, val) {\n      var bound;\n      if (typeof val != \"string\")\n        bound = function(cm) { return val(cm, handle); };\n      // This mechanism is deprecated\n      else if (baseMap.hasOwnProperty(val))\n        bound = baseMap[val];\n      else\n        bound = val;\n      ourMap[key] = bound;\n    }\n    if (custom)\n      for (var key in custom) if (custom.hasOwnProperty(key))\n        addBinding(key, custom[key]);\n    var extra = completion.options.extraKeys;\n    if (extra)\n      for (var key in extra) if (extra.hasOwnProperty(key))\n        addBinding(key, extra[key]);\n    return ourMap;\n  }\n\n  function getHintElement(hintsElement, el) {\n    while (el && el != hintsElement) {\n      if (el.nodeName.toUpperCase() === \"LI\" && el.parentNode == hintsElement) return el;\n      el = el.parentNode;\n    }\n  }\n\n  function Widget(completion, data) {\n    this.completion = completion;\n    this.data = data;\n    this.picked = false;\n    var widget = this, cm = completion.cm;\n\n    var hints = this.hints = document.createElement(\"ul\");\n    hints.className = \"CodeMirror-hints\";\n    this.selectedHint = data.selectedHint || 0;\n\n    var completions = data.list;\n    for (var i = 0; i < completions.length; ++i) {\n      var elt = hints.appendChild(document.createElement(\"li\")), cur = completions[i];\n      var className = HINT_ELEMENT_CLASS + (i != this.selectedHint ? \"\" : \" \" + ACTIVE_HINT_ELEMENT_CLASS);\n      if (cur.className != null) className = cur.className + \" \" + className;\n      elt.className = className;\n      if (cur.render) cur.render(elt, data, cur);\n      else elt.appendChild(document.createTextNode(cur.displayText || getText(cur)));\n      elt.hintId = i;\n    }\n\n    var pos = cm.cursorCoords(completion.options.alignWithWord ? data.from : null);\n    var left = pos.left, top = pos.bottom, below = true;\n    hints.style.left = left + \"px\";\n    hints.style.top = top + \"px\";\n    // If we're at the edge of the screen, then we want the menu to appear on the left of the cursor.\n    var winW = window.innerWidth || Math.max(document.body.offsetWidth, document.documentElement.offsetWidth);\n    var winH = window.innerHeight || Math.max(document.body.offsetHeight, document.documentElement.offsetHeight);\n    (completion.options.container || document.body).appendChild(hints);\n    var box = hints.getBoundingClientRect(), overlapY = box.bottom - winH;\n    if (overlapY > 0) {\n      var height = box.bottom - box.top, curTop = pos.top - (pos.bottom - box.top);\n      if (curTop - height > 0) { // Fits above cursor\n        hints.style.top = (top = pos.top - height) + \"px\";\n        below = false;\n      } else if (height > winH) {\n        hints.style.height = (winH - 5) + \"px\";\n        hints.style.top = (top = pos.bottom - box.top) + \"px\";\n        var cursor = cm.getCursor();\n        if (data.from.ch != cursor.ch) {\n          pos = cm.cursorCoords(cursor);\n          hints.style.left = (left = pos.left) + \"px\";\n          box = hints.getBoundingClientRect();\n        }\n      }\n    }\n    var overlapX = box.right - winW;\n    if (overlapX > 0) {\n      if (box.right - box.left > winW) {\n        hints.style.width = (winW - 5) + \"px\";\n        overlapX -= (box.right - box.left) - winW;\n      }\n      hints.style.left = (left = pos.left - overlapX) + \"px\";\n    }\n\n    cm.addKeyMap(this.keyMap = buildKeyMap(completion, {\n      moveFocus: function(n, avoidWrap) { widget.changeActive(widget.selectedHint + n, avoidWrap); },\n      setFocus: function(n) { widget.changeActive(n); },\n      menuSize: function() { return widget.screenAmount(); },\n      length: completions.length,\n      close: function() { completion.close(); },\n      pick: function() { widget.pick(); },\n      data: data\n    }));\n\n    if (completion.options.closeOnUnfocus) {\n      var closingOnBlur;\n      cm.on(\"blur\", this.onBlur = function() { closingOnBlur = setTimeout(function() { completion.close(); }, 100); });\n      cm.on(\"focus\", this.onFocus = function() { clearTimeout(closingOnBlur); });\n    }\n\n    var startScroll = cm.getScrollInfo();\n    cm.on(\"scroll\", this.onScroll = function() {\n      var curScroll = cm.getScrollInfo(), editor = cm.getWrapperElement().getBoundingClientRect();\n      var newTop = top + startScroll.top - curScroll.top;\n      var point = newTop - (window.pageYOffset || (document.documentElement || document.body).scrollTop);\n      if (!below) point += hints.offsetHeight;\n      if (point <= editor.top || point >= editor.bottom) return completion.close();\n      hints.style.top = newTop + \"px\";\n      hints.style.left = (left + startScroll.left - curScroll.left) + \"px\";\n    });\n\n    CodeMirror.on(hints, \"dblclick\", function(e) {\n      var t = getHintElement(hints, e.target || e.srcElement);\n      if (t && t.hintId != null) {widget.changeActive(t.hintId); widget.pick();}\n    });\n\n    CodeMirror.on(hints, \"click\", function(e) {\n      var t = getHintElement(hints, e.target || e.srcElement);\n      if (t && t.hintId != null) {\n        widget.changeActive(t.hintId);\n        if (completion.options.completeOnSingleClick) widget.pick();\n      }\n    });\n\n    CodeMirror.on(hints, \"mousedown\", function() {\n      setTimeout(function(){cm.focus();}, 20);\n    });\n\n    CodeMirror.signal(data, \"select\", completions[0], hints.firstChild);\n    return true;\n  }\n\n  Widget.prototype = {\n    close: function() {\n      if (this.completion.widget != this) return;\n      this.completion.widget = null;\n      this.hints.parentNode.removeChild(this.hints);\n      this.completion.cm.removeKeyMap(this.keyMap);\n\n      var cm = this.completion.cm;\n      if (this.completion.options.closeOnUnfocus) {\n        cm.off(\"blur\", this.onBlur);\n        cm.off(\"focus\", this.onFocus);\n      }\n      cm.off(\"scroll\", this.onScroll);\n    },\n\n    disable: function() {\n      this.completion.cm.removeKeyMap(this.keyMap);\n      var widget = this;\n      this.keyMap = {Enter: function() { widget.picked = true; }};\n      this.completion.cm.addKeyMap(this.keyMap);\n    },\n\n    pick: function() {\n      this.completion.pick(this.data, this.selectedHint);\n    },\n\n    changeActive: function(i, avoidWrap) {\n      if (i >= this.data.list.length)\n        i = avoidWrap ? this.data.list.length - 1 : 0;\n      else if (i < 0)\n        i = avoidWrap ? 0  : this.data.list.length - 1;\n      if (this.selectedHint == i) return;\n      var node = this.hints.childNodes[this.selectedHint];\n      node.className = node.className.replace(\" \" + ACTIVE_HINT_ELEMENT_CLASS, \"\");\n      node = this.hints.childNodes[this.selectedHint = i];\n      node.className += \" \" + ACTIVE_HINT_ELEMENT_CLASS;\n      if (node.offsetTop < this.hints.scrollTop)\n        this.hints.scrollTop = node.offsetTop - 3;\n      else if (node.offsetTop + node.offsetHeight > this.hints.scrollTop + this.hints.clientHeight)\n        this.hints.scrollTop = node.offsetTop + node.offsetHeight - this.hints.clientHeight + 3;\n      CodeMirror.signal(this.data, \"select\", this.data.list[this.selectedHint], node);\n    },\n\n    screenAmount: function() {\n      return Math.floor(this.hints.clientHeight / this.hints.firstChild.offsetHeight) || 1;\n    }\n  };\n\n  function applicableHelpers(cm, helpers) {\n    if (!cm.somethingSelected()) return helpers\n    var result = []\n    for (var i = 0; i < helpers.length; i++)\n      if (helpers[i].supportsSelection) result.push(helpers[i])\n    return result\n  }\n\n  function resolveAutoHints(cm, pos) {\n    var helpers = cm.getHelpers(pos, \"hint\"), words\n    if (helpers.length) {\n      var async = false, resolved\n      for (var i = 0; i < helpers.length; i++) if (helpers[i].async) async = true\n      if (async) {\n        resolved = function(cm, callback, options) {\n          var app = applicableHelpers(cm, helpers)\n          function run(i, result) {\n            if (i == app.length) return callback(null)\n            var helper = app[i]\n            if (helper.async) {\n              helper(cm, function(result) {\n                if (result) callback(result)\n                else run(i + 1)\n              }, options)\n            } else {\n              var result = helper(cm, options)\n              if (result) callback(result)\n              else run(i + 1)\n            }\n          }\n          run(0)\n        }\n        resolved.async = true\n      } else {\n        resolved = function(cm, options) {\n          var app = applicableHelpers(cm, helpers)\n          for (var i = 0; i < app.length; i++) {\n            var cur = app[i](cm, options)\n            if (cur && cur.list.length) return cur\n          }\n        }\n      }\n      resolved.supportsSelection = true\n      return resolved\n    } else if (words = cm.getHelper(cm.getCursor(), \"hintWords\")) {\n      return function(cm) { return CodeMirror.hint.fromList(cm, {words: words}) }\n    } else if (CodeMirror.hint.anyword) {\n      return function(cm, options) { return CodeMirror.hint.anyword(cm, options) }\n    } else {\n      return function() {}\n    }\n  }\n\n  CodeMirror.registerHelper(\"hint\", \"auto\", {\n    resolve: resolveAutoHints\n  });\n\n  CodeMirror.registerHelper(\"hint\", \"fromList\", function(cm, options) {\n    var cur = cm.getCursor(), token = cm.getTokenAt(cur);\n    var to = CodeMirror.Pos(cur.line, token.end);\n    if (token.string && /\\w/.test(token.string[token.string.length - 1])) {\n      var term = token.string, from = CodeMirror.Pos(cur.line, token.start);\n    } else {\n      var term = \"\", from = to;\n    }\n    var found = [];\n    for (var i = 0; i < options.words.length; i++) {\n      var word = options.words[i];\n      if (word.slice(0, term.length) == term)\n        found.push(word);\n    }\n\n    if (found.length) return {list: found, from: from, to: to};\n  });\n\n  CodeMirror.commands.autocomplete = CodeMirror.showHint;\n\n  var defaultOptions = {\n    hint: CodeMirror.hint.auto,\n    completeSingle: true,\n    alignWithWord: true,\n    closeCharacters: /[\\s()\\[\\]{};:>,]/,\n    closeOnUnfocus: true,\n    completeOnSingleClick: true,\n    container: null,\n    customKeys: null,\n    extraKeys: null\n  };\n\n  CodeMirror.defineOption(\"hintOptions\", null);\n});\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/view/static/plugins/codemirror/lib/codemirror.css",
    "content": "/* BASICS */\n\n.CodeMirror {\n  /* Set height, width, borders, and global font properties here */\n  font-family: monospace;\n  height: 300px;\n  color: black;\n}\n\n/* PADDING */\n\n.CodeMirror-lines {\n  padding: 4px 0; /* Vertical padding around content */\n}\n.CodeMirror pre {\n  padding: 0 4px; /* Horizontal padding of content */\n}\n\n.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {\n  background-color: white; /* The little square between H and V scrollbars */\n}\n\n/* GUTTER */\n\n.CodeMirror-gutters {\n  border-right: 1px solid #ddd;\n  background-color: #f7f7f7;\n  white-space: nowrap;\n}\n.CodeMirror-linenumbers {}\n.CodeMirror-linenumber {\n  padding: 0 3px 0 5px;\n  min-width: 20px;\n  text-align: right;\n  color: #999;\n  white-space: nowrap;\n}\n\n.CodeMirror-guttermarker { color: black; }\n.CodeMirror-guttermarker-subtle { color: #999; }\n\n/* CURSOR */\n\n.CodeMirror-cursor {\n  border-left: 1px solid black;\n  border-right: none;\n  width: 0;\n}\n/* Shown when moving in bi-directional text */\n.CodeMirror div.CodeMirror-secondarycursor {\n  border-left: 1px solid silver;\n}\n.cm-fat-cursor .CodeMirror-cursor {\n  width: auto;\n  border: 0;\n  background: #7e7;\n}\n.cm-fat-cursor div.CodeMirror-cursors {\n  z-index: 1;\n}\n\n.cm-animate-fat-cursor {\n  width: auto;\n  border: 0;\n  -webkit-animation: blink 1.06s steps(1) infinite;\n  -moz-animation: blink 1.06s steps(1) infinite;\n  animation: blink 1.06s steps(1) infinite;\n  background-color: #7e7;\n}\n@-moz-keyframes blink {\n  0% {}\n  50% { background-color: transparent; }\n  100% {}\n}\n@-webkit-keyframes blink {\n  0% {}\n  50% { background-color: transparent; }\n  100% {}\n}\n@keyframes blink {\n  0% {}\n  50% { background-color: transparent; }\n  100% {}\n}\n\n/* Can style cursor different in overwrite (non-insert) mode */\n.CodeMirror-overwrite .CodeMirror-cursor {}\n\n.cm-tab { display: inline-block; text-decoration: inherit; }\n\n.CodeMirror-ruler {\n  border-left: 1px solid #ccc;\n  position: absolute;\n}\n\n/* DEFAULT THEME */\n\n.cm-s-default .cm-header {color: blue;}\n.cm-s-default .cm-quote {color: #090;}\n.cm-negative {color: #d44;}\n.cm-positive {color: #292;}\n.cm-header, .cm-strong {font-weight: bold;}\n.cm-em {font-style: italic;}\n.cm-link {text-decoration: underline;}\n.cm-strikethrough {text-decoration: line-through;}\n\n.cm-s-default .cm-keyword {color: #708;}\n.cm-s-default .cm-atom {color: #219;}\n.cm-s-default .cm-number {color: #164;}\n.cm-s-default .cm-def {color: #00f;}\n.cm-s-default .cm-variable,\n.cm-s-default .cm-punctuation,\n.cm-s-default .cm-property,\n.cm-s-default .cm-operator {}\n.cm-s-default .cm-variable-2 {color: #05a;}\n.cm-s-default .cm-variable-3 {color: #085;}\n.cm-s-default .cm-comment {color: #a50;}\n.cm-s-default .cm-string {color: #a11;}\n.cm-s-default .cm-string-2 {color: #f50;}\n.cm-s-default .cm-meta {color: #555;}\n.cm-s-default .cm-qualifier {color: #555;}\n.cm-s-default .cm-builtin {color: #30a;}\n.cm-s-default .cm-bracket {color: #997;}\n.cm-s-default .cm-tag {color: #170;}\n.cm-s-default .cm-attribute {color: #00c;}\n.cm-s-default .cm-hr {color: #999;}\n.cm-s-default .cm-link {color: #00c;}\n\n.cm-s-default .cm-error {color: #f00;}\n.cm-invalidchar {color: #f00;}\n\n.CodeMirror-composing { border-bottom: 2px solid; }\n\n/* Default styles for common addons */\n\ndiv.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}\ndiv.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}\n.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }\n.CodeMirror-activeline-background {background: #e8f2ff;}\n\n/* STOP */\n\n/* The rest of this file contains styles related to the mechanics of\n   the editor. You probably shouldn't touch them. */\n\n.CodeMirror {\n  position: relative;\n  overflow: hidden;\n  background: white;\n}\n\n.CodeMirror-scroll {\n  overflow: scroll !important; /* Things will break if this is overridden */\n  /* 30px is the magic margin used to hide the element's real scrollbars */\n  /* See overflow: hidden in .CodeMirror */\n  margin-bottom: -30px; margin-right: -30px;\n  padding-bottom: 30px;\n  height: 100%;\n  outline: none; /* Prevent dragging from highlighting the element */\n  position: relative;\n}\n.CodeMirror-sizer {\n  position: relative;\n  border-right: 30px solid transparent;\n}\n\n/* The fake, visible scrollbars. Used to force redraw during scrolling\n   before actual scrolling happens, thus preventing shaking and\n   flickering artifacts. */\n.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {\n  position: absolute;\n  z-index: 6;\n  display: none;\n}\n.CodeMirror-vscrollbar {\n  right: 0; top: 0;\n  overflow-x: hidden;\n  overflow-y: scroll;\n}\n.CodeMirror-hscrollbar {\n  bottom: 0; left: 0;\n  overflow-y: hidden;\n  overflow-x: scroll;\n}\n.CodeMirror-scrollbar-filler {\n  right: 0; bottom: 0;\n}\n.CodeMirror-gutter-filler {\n  left: 0; bottom: 0;\n}\n\n.CodeMirror-gutters {\n  position: absolute; left: 0; top: 0;\n  min-height: 100%;\n  z-index: 3;\n}\n.CodeMirror-gutter {\n  white-space: normal;\n  height: 100%;\n  display: inline-block;\n  vertical-align: top;\n  margin-bottom: -30px;\n  /* Hack to make IE7 behave */\n  *zoom:1;\n  *display:inline;\n}\n.CodeMirror-gutter-wrapper {\n  position: absolute;\n  z-index: 4;\n  background: none !important;\n  border: none !important;\n}\n.CodeMirror-gutter-background {\n  position: absolute;\n  top: 0; bottom: 0;\n  z-index: 4;\n}\n.CodeMirror-gutter-elt {\n  position: absolute;\n  cursor: default;\n  z-index: 4;\n}\n.CodeMirror-gutter-wrapper {\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  user-select: none;\n}\n\n.CodeMirror-lines {\n  cursor: text;\n  min-height: 1px; /* prevents collapsing before first draw */\n}\n.CodeMirror pre {\n  /* Reset some styles that the rest of the page might have set */\n  -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;\n  border-width: 0;\n  background: transparent;\n  font-family: inherit;\n  font-size: inherit;\n  margin: 0;\n  white-space: pre;\n  word-wrap: normal;\n  line-height: inherit;\n  color: inherit;\n  z-index: 2;\n  position: relative;\n  overflow: visible;\n  -webkit-tap-highlight-color: transparent;\n  -webkit-font-variant-ligatures: none;\n  font-variant-ligatures: none;\n}\n.CodeMirror-wrap pre {\n  word-wrap: break-word;\n  white-space: pre-wrap;\n  word-break: normal;\n}\n\n.CodeMirror-linebackground {\n  position: absolute;\n  left: 0; right: 0; top: 0; bottom: 0;\n  z-index: 0;\n}\n\n.CodeMirror-linewidget {\n  position: relative;\n  z-index: 2;\n  overflow: auto;\n}\n\n.CodeMirror-widget {}\n\n.CodeMirror-code {\n  outline: none;\n}\n\n/* Force content-box sizing for the elements where we expect it */\n.CodeMirror-scroll,\n.CodeMirror-sizer,\n.CodeMirror-gutter,\n.CodeMirror-gutters,\n.CodeMirror-linenumber {\n  -moz-box-sizing: content-box;\n  box-sizing: content-box;\n}\n\n.CodeMirror-measure {\n  position: absolute;\n  width: 100%;\n  height: 0;\n  overflow: hidden;\n  visibility: hidden;\n}\n\n.CodeMirror-cursor { position: absolute; }\n.CodeMirror-measure pre { position: static; }\n\ndiv.CodeMirror-cursors {\n  visibility: hidden;\n  position: relative;\n  z-index: 3;\n}\ndiv.CodeMirror-dragcursors {\n  visibility: visible;\n}\n\n.CodeMirror-focused div.CodeMirror-cursors {\n  visibility: visible;\n}\n\n.CodeMirror-selected { background: #d9d9d9; }\n.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }\n.CodeMirror-crosshair { cursor: crosshair; }\n.CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; }\n.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; }\n\n.cm-searching {\n  background: #ffa;\n  background: rgba(255, 255, 0, .4);\n}\n\n/* IE7 hack to prevent it from returning funny offsetTops on the spans */\n.CodeMirror span { *vertical-align: text-bottom; }\n\n/* Used to force a border model for a node */\n.cm-force-border { padding-right: .1px; }\n\n@media print {\n  /* Hide the cursor when printing */\n  .CodeMirror div.CodeMirror-cursors {\n    visibility: hidden;\n  }\n}\n\n/* See issue #2901 */\n.cm-tab-wrap-hack:after { content: ''; }\n\n/* Help users use markselection to safely style text background */\nspan.CodeMirror-selectedtext { background: none; }\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/view/static/plugins/codemirror/lib/codemirror.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n// This is CodeMirror (http://codemirror.net), a code editor\n// implemented in JavaScript on top of the browser's DOM.\n//\n// You can find some technical background for some of the code below\n// at http://marijnhaverbeke.nl/blog/#cm-internals .\n\n(function(mod) {\n  if (typeof exports == \"object\" && typeof module == \"object\") // CommonJS\n    module.exports = mod();\n  else if (typeof define == \"function\" && define.amd) // AMD\n    return define([], mod);\n  else // Plain browser env\n    (this || window).CodeMirror = mod();\n})(function() {\n  \"use strict\";\n\n  // BROWSER SNIFFING\n\n  // Kludges for bugs and behavior differences that can't be feature\n  // detected are enabled based on userAgent etc sniffing.\n  var userAgent = navigator.userAgent;\n  var platform = navigator.platform;\n\n  var gecko = /gecko\\/\\d/i.test(userAgent);\n  var ie_upto10 = /MSIE \\d/.test(userAgent);\n  var ie_11up = /Trident\\/(?:[7-9]|\\d{2,})\\..*rv:(\\d+)/.exec(userAgent);\n  var ie = ie_upto10 || ie_11up;\n  var ie_version = ie && (ie_upto10 ? document.documentMode || 6 : ie_11up[1]);\n  var webkit = /WebKit\\//.test(userAgent);\n  var qtwebkit = webkit && /Qt\\/\\d+\\.\\d+/.test(userAgent);\n  var chrome = /Chrome\\//.test(userAgent);\n  var presto = /Opera\\//.test(userAgent);\n  var safari = /Apple Computer/.test(navigator.vendor);\n  var mac_geMountainLion = /Mac OS X 1\\d\\D([8-9]|\\d\\d)\\D/.test(userAgent);\n  var phantom = /PhantomJS/.test(userAgent);\n\n  var ios = /AppleWebKit/.test(userAgent) && /Mobile\\/\\w+/.test(userAgent);\n  // This is woefully incomplete. Suggestions for alternative methods welcome.\n  var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(userAgent);\n  var mac = ios || /Mac/.test(platform);\n  var windows = /win/i.test(platform);\n\n  var presto_version = presto && userAgent.match(/Version\\/(\\d*\\.\\d*)/);\n  if (presto_version) presto_version = Number(presto_version[1]);\n  if (presto_version && presto_version >= 15) { presto = false; webkit = true; }\n  // Some browsers use the wrong event properties to signal cmd/ctrl on OS X\n  var flipCtrlCmd = mac && (qtwebkit || presto && (presto_version == null || presto_version < 12.11));\n  var captureRightClick = gecko || (ie && ie_version >= 9);\n\n  // Optimize some code when these features are not used.\n  var sawReadOnlySpans = false, sawCollapsedSpans = false;\n\n  // EDITOR CONSTRUCTOR\n\n  // A CodeMirror instance represents an editor. This is the object\n  // that user code is usually dealing with.\n\n  function CodeMirror(place, options) {\n    if (!(this instanceof CodeMirror)) return new CodeMirror(place, options);\n\n    this.options = options = options ? copyObj(options) : {};\n    // Determine effective options based on given values and defaults.\n    copyObj(defaults, options, false);\n    setGuttersForLineNumbers(options);\n\n    var doc = options.value;\n    if (typeof doc == \"string\") doc = new Doc(doc, options.mode, null, options.lineSeparator);\n    this.doc = doc;\n\n    var input = new CodeMirror.inputStyles[options.inputStyle](this);\n    var display = this.display = new Display(place, doc, input);\n    display.wrapper.CodeMirror = this;\n    updateGutters(this);\n    themeChanged(this);\n    if (options.lineWrapping)\n      this.display.wrapper.className += \" CodeMirror-wrap\";\n    if (options.autofocus && !mobile) display.input.focus();\n    initScrollbars(this);\n\n    this.state = {\n      keyMaps: [],  // stores maps added by addKeyMap\n      overlays: [], // highlighting overlays, as added by addOverlay\n      modeGen: 0,   // bumped when mode/overlay changes, used to invalidate highlighting info\n      overwrite: false,\n      delayingBlurEvent: false,\n      focused: false,\n      suppressEdits: false, // used to disable editing during key handlers when in readOnly mode\n      pasteIncoming: false, cutIncoming: false, // help recognize paste/cut edits in input.poll\n      selectingText: false,\n      draggingText: false,\n      highlight: new Delayed(), // stores highlight worker timeout\n      keySeq: null,  // Unfinished key sequence\n      specialChars: null\n    };\n\n    var cm = this;\n\n    // Override magic textarea content restore that IE sometimes does\n    // on our hidden textarea on reload\n    if (ie && ie_version < 11) setTimeout(function() { cm.display.input.reset(true); }, 20);\n\n    registerEventHandlers(this);\n    ensureGlobalHandlers();\n\n    startOperation(this);\n    this.curOp.forceUpdate = true;\n    attachDoc(this, doc);\n\n    if ((options.autofocus && !mobile) || cm.hasFocus())\n      setTimeout(bind(onFocus, this), 20);\n    else\n      onBlur(this);\n\n    for (var opt in optionHandlers) if (optionHandlers.hasOwnProperty(opt))\n      optionHandlers[opt](this, options[opt], Init);\n    maybeUpdateLineNumberWidth(this);\n    if (options.finishInit) options.finishInit(this);\n    for (var i = 0; i < initHooks.length; ++i) initHooks[i](this);\n    endOperation(this);\n    // Suppress optimizelegibility in Webkit, since it breaks text\n    // measuring on line wrapping boundaries.\n    if (webkit && options.lineWrapping &&\n        getComputedStyle(display.lineDiv).textRendering == \"optimizelegibility\")\n      display.lineDiv.style.textRendering = \"auto\";\n  }\n\n  // DISPLAY CONSTRUCTOR\n\n  // The display handles the DOM integration, both for input reading\n  // and content drawing. It holds references to DOM nodes and\n  // display-related state.\n\n  function Display(place, doc, input) {\n    var d = this;\n    this.input = input;\n\n    // Covers bottom-right square when both scrollbars are present.\n    d.scrollbarFiller = elt(\"div\", null, \"CodeMirror-scrollbar-filler\");\n    d.scrollbarFiller.setAttribute(\"cm-not-content\", \"true\");\n    // Covers bottom of gutter when coverGutterNextToScrollbar is on\n    // and h scrollbar is present.\n    d.gutterFiller = elt(\"div\", null, \"CodeMirror-gutter-filler\");\n    d.gutterFiller.setAttribute(\"cm-not-content\", \"true\");\n    // Will contain the actual code, positioned to cover the viewport.\n    d.lineDiv = elt(\"div\", null, \"CodeMirror-code\");\n    // Elements are added to these to represent selection and cursors.\n    d.selectionDiv = elt(\"div\", null, null, \"position: relative; z-index: 1\");\n    d.cursorDiv = elt(\"div\", null, \"CodeMirror-cursors\");\n    // A visibility: hidden element used to find the size of things.\n    d.measure = elt(\"div\", null, \"CodeMirror-measure\");\n    // When lines outside of the viewport are measured, they are drawn in this.\n    d.lineMeasure = elt(\"div\", null, \"CodeMirror-measure\");\n    // Wraps everything that needs to exist inside the vertically-padded coordinate system\n    d.lineSpace = elt(\"div\", [d.measure, d.lineMeasure, d.selectionDiv, d.cursorDiv, d.lineDiv],\n                      null, \"position: relative; outline: none\");\n    // Moved around its parent to cover visible view.\n    d.mover = elt(\"div\", [elt(\"div\", [d.lineSpace], \"CodeMirror-lines\")], null, \"position: relative\");\n    // Set to the height of the document, allowing scrolling.\n    d.sizer = elt(\"div\", [d.mover], \"CodeMirror-sizer\");\n    d.sizerWidth = null;\n    // Behavior of elts with overflow: auto and padding is\n    // inconsistent across browsers. This is used to ensure the\n    // scrollable area is big enough.\n    d.heightForcer = elt(\"div\", null, null, \"position: absolute; height: \" + scrollerGap + \"px; width: 1px;\");\n    // Will contain the gutters, if any.\n    d.gutters = elt(\"div\", null, \"CodeMirror-gutters\");\n    d.lineGutter = null;\n    // Actual scrollable element.\n    d.scroller = elt(\"div\", [d.sizer, d.heightForcer, d.gutters], \"CodeMirror-scroll\");\n    d.scroller.setAttribute(\"tabIndex\", \"-1\");\n    // The element in which the editor lives.\n    d.wrapper = elt(\"div\", [d.scrollbarFiller, d.gutterFiller, d.scroller], \"CodeMirror\");\n\n    // Work around IE7 z-index bug (not perfect, hence IE7 not really being supported)\n    if (ie && ie_version < 8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; }\n    if (!webkit && !(gecko && mobile)) d.scroller.draggable = true;\n\n    if (place) {\n      if (place.appendChild) place.appendChild(d.wrapper);\n      else place(d.wrapper);\n    }\n\n    // Current rendered range (may be bigger than the view window).\n    d.viewFrom = d.viewTo = doc.first;\n    d.reportedViewFrom = d.reportedViewTo = doc.first;\n    // Information about the rendered lines.\n    d.view = [];\n    d.renderedView = null;\n    // Holds info about a single rendered line when it was rendered\n    // for measurement, while not in view.\n    d.externalMeasured = null;\n    // Empty space (in pixels) above the view\n    d.viewOffset = 0;\n    d.lastWrapHeight = d.lastWrapWidth = 0;\n    d.updateLineNumbers = null;\n\n    d.nativeBarWidth = d.barHeight = d.barWidth = 0;\n    d.scrollbarsClipped = false;\n\n    // Used to only resize the line number gutter when necessary (when\n    // the amount of lines crosses a boundary that makes its width change)\n    d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null;\n    // Set to true when a non-horizontal-scrolling line widget is\n    // added. As an optimization, line widget aligning is skipped when\n    // this is false.\n    d.alignWidgets = false;\n\n    d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null;\n\n    // Tracks the maximum line length so that the horizontal scrollbar\n    // can be kept static when scrolling.\n    d.maxLine = null;\n    d.maxLineLength = 0;\n    d.maxLineChanged = false;\n\n    // Used for measuring wheel scrolling granularity\n    d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null;\n\n    // True when shift is held down.\n    d.shift = false;\n\n    // Used to track whether anything happened since the context menu\n    // was opened.\n    d.selForContextMenu = null;\n\n    d.activeTouch = null;\n\n    input.init(d);\n  }\n\n  // STATE UPDATES\n\n  // Used to get the editor into a consistent state again when options change.\n\n  function loadMode(cm) {\n    cm.doc.mode = CodeMirror.getMode(cm.options, cm.doc.modeOption);\n    resetModeState(cm);\n  }\n\n  function resetModeState(cm) {\n    cm.doc.iter(function(line) {\n      if (line.stateAfter) line.stateAfter = null;\n      if (line.styles) line.styles = null;\n    });\n    cm.doc.frontier = cm.doc.first;\n    startWorker(cm, 100);\n    cm.state.modeGen++;\n    if (cm.curOp) regChange(cm);\n  }\n\n  function wrappingChanged(cm) {\n    if (cm.options.lineWrapping) {\n      addClass(cm.display.wrapper, \"CodeMirror-wrap\");\n      cm.display.sizer.style.minWidth = \"\";\n      cm.display.sizerWidth = null;\n    } else {\n      rmClass(cm.display.wrapper, \"CodeMirror-wrap\");\n      findMaxLine(cm);\n    }\n    estimateLineHeights(cm);\n    regChange(cm);\n    clearCaches(cm);\n    setTimeout(function(){updateScrollbars(cm);}, 100);\n  }\n\n  // Returns a function that estimates the height of a line, to use as\n  // first approximation until the line becomes visible (and is thus\n  // properly measurable).\n  function estimateHeight(cm) {\n    var th = textHeight(cm.display), wrapping = cm.options.lineWrapping;\n    var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3);\n    return function(line) {\n      if (lineIsHidden(cm.doc, line)) return 0;\n\n      var widgetsHeight = 0;\n      if (line.widgets) for (var i = 0; i < line.widgets.length; i++) {\n        if (line.widgets[i].height) widgetsHeight += line.widgets[i].height;\n      }\n\n      if (wrapping)\n        return widgetsHeight + (Math.ceil(line.text.length / perLine) || 1) * th;\n      else\n        return widgetsHeight + th;\n    };\n  }\n\n  function estimateLineHeights(cm) {\n    var doc = cm.doc, est = estimateHeight(cm);\n    doc.iter(function(line) {\n      var estHeight = est(line);\n      if (estHeight != line.height) updateLineHeight(line, estHeight);\n    });\n  }\n\n  function themeChanged(cm) {\n    cm.display.wrapper.className = cm.display.wrapper.className.replace(/\\s*cm-s-\\S+/g, \"\") +\n      cm.options.theme.replace(/(^|\\s)\\s*/g, \" cm-s-\");\n    clearCaches(cm);\n  }\n\n  function guttersChanged(cm) {\n    updateGutters(cm);\n    regChange(cm);\n    setTimeout(function(){alignHorizontally(cm);}, 20);\n  }\n\n  // Rebuild the gutter elements, ensure the margin to the left of the\n  // code matches their width.\n  function updateGutters(cm) {\n    var gutters = cm.display.gutters, specs = cm.options.gutters;\n    removeChildren(gutters);\n    for (var i = 0; i < specs.length; ++i) {\n      var gutterClass = specs[i];\n      var gElt = gutters.appendChild(elt(\"div\", null, \"CodeMirror-gutter \" + gutterClass));\n      if (gutterClass == \"CodeMirror-linenumbers\") {\n        cm.display.lineGutter = gElt;\n        gElt.style.width = (cm.display.lineNumWidth || 1) + \"px\";\n      }\n    }\n    gutters.style.display = i ? \"\" : \"none\";\n    updateGutterSpace(cm);\n  }\n\n  function updateGutterSpace(cm) {\n    var width = cm.display.gutters.offsetWidth;\n    cm.display.sizer.style.marginLeft = width + \"px\";\n  }\n\n  // Compute the character length of a line, taking into account\n  // collapsed ranges (see markText) that might hide parts, and join\n  // other lines onto it.\n  function lineLength(line) {\n    if (line.height == 0) return 0;\n    var len = line.text.length, merged, cur = line;\n    while (merged = collapsedSpanAtStart(cur)) {\n      var found = merged.find(0, true);\n      cur = found.from.line;\n      len += found.from.ch - found.to.ch;\n    }\n    cur = line;\n    while (merged = collapsedSpanAtEnd(cur)) {\n      var found = merged.find(0, true);\n      len -= cur.text.length - found.from.ch;\n      cur = found.to.line;\n      len += cur.text.length - found.to.ch;\n    }\n    return len;\n  }\n\n  // Find the longest line in the document.\n  function findMaxLine(cm) {\n    var d = cm.display, doc = cm.doc;\n    d.maxLine = getLine(doc, doc.first);\n    d.maxLineLength = lineLength(d.maxLine);\n    d.maxLineChanged = true;\n    doc.iter(function(line) {\n      var len = lineLength(line);\n      if (len > d.maxLineLength) {\n        d.maxLineLength = len;\n        d.maxLine = line;\n      }\n    });\n  }\n\n  // Make sure the gutters options contains the element\n  // \"CodeMirror-linenumbers\" when the lineNumbers option is true.\n  function setGuttersForLineNumbers(options) {\n    var found = indexOf(options.gutters, \"CodeMirror-linenumbers\");\n    if (found == -1 && options.lineNumbers) {\n      options.gutters = options.gutters.concat([\"CodeMirror-linenumbers\"]);\n    } else if (found > -1 && !options.lineNumbers) {\n      options.gutters = options.gutters.slice(0);\n      options.gutters.splice(found, 1);\n    }\n  }\n\n  // SCROLLBARS\n\n  // Prepare DOM reads needed to update the scrollbars. Done in one\n  // shot to minimize update/measure roundtrips.\n  function measureForScrollbars(cm) {\n    var d = cm.display, gutterW = d.gutters.offsetWidth;\n    var docH = Math.round(cm.doc.height + paddingVert(cm.display));\n    return {\n      clientHeight: d.scroller.clientHeight,\n      viewHeight: d.wrapper.clientHeight,\n      scrollWidth: d.scroller.scrollWidth, clientWidth: d.scroller.clientWidth,\n      viewWidth: d.wrapper.clientWidth,\n      barLeft: cm.options.fixedGutter ? gutterW : 0,\n      docHeight: docH,\n      scrollHeight: docH + scrollGap(cm) + d.barHeight,\n      nativeBarWidth: d.nativeBarWidth,\n      gutterWidth: gutterW\n    };\n  }\n\n  function NativeScrollbars(place, scroll, cm) {\n    this.cm = cm;\n    var vert = this.vert = elt(\"div\", [elt(\"div\", null, null, \"min-width: 1px\")], \"CodeMirror-vscrollbar\");\n    var horiz = this.horiz = elt(\"div\", [elt(\"div\", null, null, \"height: 100%; min-height: 1px\")], \"CodeMirror-hscrollbar\");\n    place(vert); place(horiz);\n\n    on(vert, \"scroll\", function() {\n      if (vert.clientHeight) scroll(vert.scrollTop, \"vertical\");\n    });\n    on(horiz, \"scroll\", function() {\n      if (horiz.clientWidth) scroll(horiz.scrollLeft, \"horizontal\");\n    });\n\n    this.checkedZeroWidth = false;\n    // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).\n    if (ie && ie_version < 8) this.horiz.style.minHeight = this.vert.style.minWidth = \"18px\";\n  }\n\n  NativeScrollbars.prototype = copyObj({\n    update: function(measure) {\n      var needsH = measure.scrollWidth > measure.clientWidth + 1;\n      var needsV = measure.scrollHeight > measure.clientHeight + 1;\n      var sWidth = measure.nativeBarWidth;\n\n      if (needsV) {\n        this.vert.style.display = \"block\";\n        this.vert.style.bottom = needsH ? sWidth + \"px\" : \"0\";\n        var totalHeight = measure.viewHeight - (needsH ? sWidth : 0);\n        // A bug in IE8 can cause this value to be negative, so guard it.\n        this.vert.firstChild.style.height =\n          Math.max(0, measure.scrollHeight - measure.clientHeight + totalHeight) + \"px\";\n      } else {\n        this.vert.style.display = \"\";\n        this.vert.firstChild.style.height = \"0\";\n      }\n\n      if (needsH) {\n        this.horiz.style.display = \"block\";\n        this.horiz.style.right = needsV ? sWidth + \"px\" : \"0\";\n        this.horiz.style.left = measure.barLeft + \"px\";\n        var totalWidth = measure.viewWidth - measure.barLeft - (needsV ? sWidth : 0);\n        this.horiz.firstChild.style.width =\n          (measure.scrollWidth - measure.clientWidth + totalWidth) + \"px\";\n      } else {\n        this.horiz.style.display = \"\";\n        this.horiz.firstChild.style.width = \"0\";\n      }\n\n      if (!this.checkedZeroWidth && measure.clientHeight > 0) {\n        if (sWidth == 0) this.zeroWidthHack();\n        this.checkedZeroWidth = true;\n      }\n\n      return {right: needsV ? sWidth : 0, bottom: needsH ? sWidth : 0};\n    },\n    setScrollLeft: function(pos) {\n      if (this.horiz.scrollLeft != pos) this.horiz.scrollLeft = pos;\n      if (this.disableHoriz) this.enableZeroWidthBar(this.horiz, this.disableHoriz);\n    },\n    setScrollTop: function(pos) {\n      if (this.vert.scrollTop != pos) this.vert.scrollTop = pos;\n      if (this.disableVert) this.enableZeroWidthBar(this.vert, this.disableVert);\n    },\n    zeroWidthHack: function() {\n      var w = mac && !mac_geMountainLion ? \"12px\" : \"18px\";\n      this.horiz.style.height = this.vert.style.width = w;\n      this.horiz.style.pointerEvents = this.vert.style.pointerEvents = \"none\";\n      this.disableHoriz = new Delayed;\n      this.disableVert = new Delayed;\n    },\n    enableZeroWidthBar: function(bar, delay) {\n      bar.style.pointerEvents = \"auto\";\n      function maybeDisable() {\n        // To find out whether the scrollbar is still visible, we\n        // check whether the element under the pixel in the bottom\n        // left corner of the scrollbar box is the scrollbar box\n        // itself (when the bar is still visible) or its filler child\n        // (when the bar is hidden). If it is still visible, we keep\n        // it enabled, if it's hidden, we disable pointer events.\n        var box = bar.getBoundingClientRect();\n        var elt = document.elementFromPoint(box.left + 1, box.bottom - 1);\n        if (elt != bar) bar.style.pointerEvents = \"none\";\n        else delay.set(1000, maybeDisable);\n      }\n      delay.set(1000, maybeDisable);\n    },\n    clear: function() {\n      var parent = this.horiz.parentNode;\n      parent.removeChild(this.horiz);\n      parent.removeChild(this.vert);\n    }\n  }, NativeScrollbars.prototype);\n\n  function NullScrollbars() {}\n\n  NullScrollbars.prototype = copyObj({\n    update: function() { return {bottom: 0, right: 0}; },\n    setScrollLeft: function() {},\n    setScrollTop: function() {},\n    clear: function() {}\n  }, NullScrollbars.prototype);\n\n  CodeMirror.scrollbarModel = {\"native\": NativeScrollbars, \"null\": NullScrollbars};\n\n  function initScrollbars(cm) {\n    if (cm.display.scrollbars) {\n      cm.display.scrollbars.clear();\n      if (cm.display.scrollbars.addClass)\n        rmClass(cm.display.wrapper, cm.display.scrollbars.addClass);\n    }\n\n    cm.display.scrollbars = new CodeMirror.scrollbarModel[cm.options.scrollbarStyle](function(node) {\n      cm.display.wrapper.insertBefore(node, cm.display.scrollbarFiller);\n      // Prevent clicks in the scrollbars from killing focus\n      on(node, \"mousedown\", function() {\n        if (cm.state.focused) setTimeout(function() { cm.display.input.focus(); }, 0);\n      });\n      node.setAttribute(\"cm-not-content\", \"true\");\n    }, function(pos, axis) {\n      if (axis == \"horizontal\") setScrollLeft(cm, pos);\n      else setScrollTop(cm, pos);\n    }, cm);\n    if (cm.display.scrollbars.addClass)\n      addClass(cm.display.wrapper, cm.display.scrollbars.addClass);\n  }\n\n  function updateScrollbars(cm, measure) {\n    if (!measure) measure = measureForScrollbars(cm);\n    var startWidth = cm.display.barWidth, startHeight = cm.display.barHeight;\n    updateScrollbarsInner(cm, measure);\n    for (var i = 0; i < 4 && startWidth != cm.display.barWidth || startHeight != cm.display.barHeight; i++) {\n      if (startWidth != cm.display.barWidth && cm.options.lineWrapping)\n        updateHeightsInViewport(cm);\n      updateScrollbarsInner(cm, measureForScrollbars(cm));\n      startWidth = cm.display.barWidth; startHeight = cm.display.barHeight;\n    }\n  }\n\n  // Re-synchronize the fake scrollbars with the actual size of the\n  // content.\n  function updateScrollbarsInner(cm, measure) {\n    var d = cm.display;\n    var sizes = d.scrollbars.update(measure);\n\n    d.sizer.style.paddingRight = (d.barWidth = sizes.right) + \"px\";\n    d.sizer.style.paddingBottom = (d.barHeight = sizes.bottom) + \"px\";\n    d.heightForcer.style.borderBottom = sizes.bottom + \"px solid transparent\"\n\n    if (sizes.right && sizes.bottom) {\n      d.scrollbarFiller.style.display = \"block\";\n      d.scrollbarFiller.style.height = sizes.bottom + \"px\";\n      d.scrollbarFiller.style.width = sizes.right + \"px\";\n    } else d.scrollbarFiller.style.display = \"\";\n    if (sizes.bottom && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) {\n      d.gutterFiller.style.display = \"block\";\n      d.gutterFiller.style.height = sizes.bottom + \"px\";\n      d.gutterFiller.style.width = measure.gutterWidth + \"px\";\n    } else d.gutterFiller.style.display = \"\";\n  }\n\n  // Compute the lines that are visible in a given viewport (defaults\n  // the the current scroll position). viewport may contain top,\n  // height, and ensure (see op.scrollToPos) properties.\n  function visibleLines(display, doc, viewport) {\n    var top = viewport && viewport.top != null ? Math.max(0, viewport.top) : display.scroller.scrollTop;\n    top = Math.floor(top - paddingTop(display));\n    var bottom = viewport && viewport.bottom != null ? viewport.bottom : top + display.wrapper.clientHeight;\n\n    var from = lineAtHeight(doc, top), to = lineAtHeight(doc, bottom);\n    // Ensure is a {from: {line, ch}, to: {line, ch}} object, and\n    // forces those lines into the viewport (if possible).\n    if (viewport && viewport.ensure) {\n      var ensureFrom = viewport.ensure.from.line, ensureTo = viewport.ensure.to.line;\n      if (ensureFrom < from) {\n        from = ensureFrom;\n        to = lineAtHeight(doc, heightAtLine(getLine(doc, ensureFrom)) + display.wrapper.clientHeight);\n      } else if (Math.min(ensureTo, doc.lastLine()) >= to) {\n        from = lineAtHeight(doc, heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight);\n        to = ensureTo;\n      }\n    }\n    return {from: from, to: Math.max(to, from + 1)};\n  }\n\n  // LINE NUMBERS\n\n  // Re-align line numbers and gutter marks to compensate for\n  // horizontal scrolling.\n  function alignHorizontally(cm) {\n    var display = cm.display, view = display.view;\n    if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) return;\n    var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft;\n    var gutterW = display.gutters.offsetWidth, left = comp + \"px\";\n    for (var i = 0; i < view.length; i++) if (!view[i].hidden) {\n      if (cm.options.fixedGutter && view[i].gutter)\n        view[i].gutter.style.left = left;\n      var align = view[i].alignable;\n      if (align) for (var j = 0; j < align.length; j++)\n        align[j].style.left = left;\n    }\n    if (cm.options.fixedGutter)\n      display.gutters.style.left = (comp + gutterW) + \"px\";\n  }\n\n  // Used to ensure that the line number gutter is still the right\n  // size for the current document size. Returns true when an update\n  // is needed.\n  function maybeUpdateLineNumberWidth(cm) {\n    if (!cm.options.lineNumbers) return false;\n    var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display;\n    if (last.length != display.lineNumChars) {\n      var test = display.measure.appendChild(elt(\"div\", [elt(\"div\", last)],\n                                                 \"CodeMirror-linenumber CodeMirror-gutter-elt\"));\n      var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW;\n      display.lineGutter.style.width = \"\";\n      display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding) + 1;\n      display.lineNumWidth = display.lineNumInnerWidth + padding;\n      display.lineNumChars = display.lineNumInnerWidth ? last.length : -1;\n      display.lineGutter.style.width = display.lineNumWidth + \"px\";\n      updateGutterSpace(cm);\n      return true;\n    }\n    return false;\n  }\n\n  function lineNumberFor(options, i) {\n    return String(options.lineNumberFormatter(i + options.firstLineNumber));\n  }\n\n  // Computes display.scroller.scrollLeft + display.gutters.offsetWidth,\n  // but using getBoundingClientRect to get a sub-pixel-accurate\n  // result.\n  function compensateForHScroll(display) {\n    return display.scroller.getBoundingClientRect().left - display.sizer.getBoundingClientRect().left;\n  }\n\n  // DISPLAY DRAWING\n\n  function DisplayUpdate(cm, viewport, force) {\n    var display = cm.display;\n\n    this.viewport = viewport;\n    // Store some values that we'll need later (but don't want to force a relayout for)\n    this.visible = visibleLines(display, cm.doc, viewport);\n    this.editorIsHidden = !display.wrapper.offsetWidth;\n    this.wrapperHeight = display.wrapper.clientHeight;\n    this.wrapperWidth = display.wrapper.clientWidth;\n    this.oldDisplayWidth = displayWidth(cm);\n    this.force = force;\n    this.dims = getDimensions(cm);\n    this.events = [];\n  }\n\n  DisplayUpdate.prototype.signal = function(emitter, type) {\n    if (hasHandler(emitter, type))\n      this.events.push(arguments);\n  };\n  DisplayUpdate.prototype.finish = function() {\n    for (var i = 0; i < this.events.length; i++)\n      signal.apply(null, this.events[i]);\n  };\n\n  function maybeClipScrollbars(cm) {\n    var display = cm.display;\n    if (!display.scrollbarsClipped && display.scroller.offsetWidth) {\n      display.nativeBarWidth = display.scroller.offsetWidth - display.scroller.clientWidth;\n      display.heightForcer.style.height = scrollGap(cm) + \"px\";\n      display.sizer.style.marginBottom = -display.nativeBarWidth + \"px\";\n      display.sizer.style.borderRightWidth = scrollGap(cm) + \"px\";\n      display.scrollbarsClipped = true;\n    }\n  }\n\n  // Does the actual updating of the line display. Bails out\n  // (returning false) when there is nothing to be done and forced is\n  // false.\n  function updateDisplayIfNeeded(cm, update) {\n    var display = cm.display, doc = cm.doc;\n\n    if (update.editorIsHidden) {\n      resetView(cm);\n      return false;\n    }\n\n    // Bail out if the visible area is already rendered and nothing changed.\n    if (!update.force &&\n        update.visible.from >= display.viewFrom && update.visible.to <= display.viewTo &&\n        (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo) &&\n        display.renderedView == display.view && countDirtyView(cm) == 0)\n      return false;\n\n    if (maybeUpdateLineNumberWidth(cm)) {\n      resetView(cm);\n      update.dims = getDimensions(cm);\n    }\n\n    // Compute a suitable new viewport (from & to)\n    var end = doc.first + doc.size;\n    var from = Math.max(update.visible.from - cm.options.viewportMargin, doc.first);\n    var to = Math.min(end, update.visible.to + cm.options.viewportMargin);\n    if (display.viewFrom < from && from - display.viewFrom < 20) from = Math.max(doc.first, display.viewFrom);\n    if (display.viewTo > to && display.viewTo - to < 20) to = Math.min(end, display.viewTo);\n    if (sawCollapsedSpans) {\n      from = visualLineNo(cm.doc, from);\n      to = visualLineEndNo(cm.doc, to);\n    }\n\n    var different = from != display.viewFrom || to != display.viewTo ||\n      display.lastWrapHeight != update.wrapperHeight || display.lastWrapWidth != update.wrapperWidth;\n    adjustView(cm, from, to);\n\n    display.viewOffset = heightAtLine(getLine(cm.doc, display.viewFrom));\n    // Position the mover div to align with the current scroll position\n    cm.display.mover.style.top = display.viewOffset + \"px\";\n\n    var toUpdate = countDirtyView(cm);\n    if (!different && toUpdate == 0 && !update.force && display.renderedView == display.view &&\n        (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo))\n      return false;\n\n    // For big changes, we hide the enclosing element during the\n    // update, since that speeds up the operations on most browsers.\n    var focused = activeElt();\n    if (toUpdate > 4) display.lineDiv.style.display = \"none\";\n    patchDisplay(cm, display.updateLineNumbers, update.dims);\n    if (toUpdate > 4) display.lineDiv.style.display = \"\";\n    display.renderedView = display.view;\n    // There might have been a widget with a focused element that got\n    // hidden or updated, if so re-focus it.\n    if (focused && activeElt() != focused && focused.offsetHeight) focused.focus();\n\n    // Prevent selection and cursors from interfering with the scroll\n    // width and height.\n    removeChildren(display.cursorDiv);\n    removeChildren(display.selectionDiv);\n    display.gutters.style.height = display.sizer.style.minHeight = 0;\n\n    if (different) {\n      display.lastWrapHeight = update.wrapperHeight;\n      display.lastWrapWidth = update.wrapperWidth;\n      startWorker(cm, 400);\n    }\n\n    display.updateLineNumbers = null;\n\n    return true;\n  }\n\n  function postUpdateDisplay(cm, update) {\n    var viewport = update.viewport;\n\n    for (var first = true;; first = false) {\n      if (!first || !cm.options.lineWrapping || update.oldDisplayWidth == displayWidth(cm)) {\n        // Clip forced viewport to actual scrollable area.\n        if (viewport && viewport.top != null)\n          viewport = {top: Math.min(cm.doc.height + paddingVert(cm.display) - displayHeight(cm), viewport.top)};\n        // Updated line heights might result in the drawn area not\n        // actually covering the viewport. Keep looping until it does.\n        update.visible = visibleLines(cm.display, cm.doc, viewport);\n        if (update.visible.from >= cm.display.viewFrom && update.visible.to <= cm.display.viewTo)\n          break;\n      }\n      if (!updateDisplayIfNeeded(cm, update)) break;\n      updateHeightsInViewport(cm);\n      var barMeasure = measureForScrollbars(cm);\n      updateSelection(cm);\n      updateScrollbars(cm, barMeasure);\n      setDocumentHeight(cm, barMeasure);\n    }\n\n    update.signal(cm, \"update\", cm);\n    if (cm.display.viewFrom != cm.display.reportedViewFrom || cm.display.viewTo != cm.display.reportedViewTo) {\n      update.signal(cm, \"viewportChange\", cm, cm.display.viewFrom, cm.display.viewTo);\n      cm.display.reportedViewFrom = cm.display.viewFrom; cm.display.reportedViewTo = cm.display.viewTo;\n    }\n  }\n\n  function updateDisplaySimple(cm, viewport) {\n    var update = new DisplayUpdate(cm, viewport);\n    if (updateDisplayIfNeeded(cm, update)) {\n      updateHeightsInViewport(cm);\n      postUpdateDisplay(cm, update);\n      var barMeasure = measureForScrollbars(cm);\n      updateSelection(cm);\n      updateScrollbars(cm, barMeasure);\n      setDocumentHeight(cm, barMeasure);\n      update.finish();\n    }\n  }\n\n  function setDocumentHeight(cm, measure) {\n    cm.display.sizer.style.minHeight = measure.docHeight + \"px\";\n    cm.display.heightForcer.style.top = measure.docHeight + \"px\";\n    cm.display.gutters.style.height = (measure.docHeight + cm.display.barHeight + scrollGap(cm)) + \"px\";\n  }\n\n  // Read the actual heights of the rendered lines, and update their\n  // stored heights to match.\n  function updateHeightsInViewport(cm) {\n    var display = cm.display;\n    var prevBottom = display.lineDiv.offsetTop;\n    for (var i = 0; i < display.view.length; i++) {\n      var cur = display.view[i], height;\n      if (cur.hidden) continue;\n      if (ie && ie_version < 8) {\n        var bot = cur.node.offsetTop + cur.node.offsetHeight;\n        height = bot - prevBottom;\n        prevBottom = bot;\n      } else {\n        var box = cur.node.getBoundingClientRect();\n        height = box.bottom - box.top;\n      }\n      var diff = cur.line.height - height;\n      if (height < 2) height = textHeight(display);\n      if (diff > .001 || diff < -.001) {\n        updateLineHeight(cur.line, height);\n        updateWidgetHeight(cur.line);\n        if (cur.rest) for (var j = 0; j < cur.rest.length; j++)\n          updateWidgetHeight(cur.rest[j]);\n      }\n    }\n  }\n\n  // Read and store the height of line widgets associated with the\n  // given line.\n  function updateWidgetHeight(line) {\n    if (line.widgets) for (var i = 0; i < line.widgets.length; ++i)\n      line.widgets[i].height = line.widgets[i].node.parentNode.offsetHeight;\n  }\n\n  // Do a bulk-read of the DOM positions and sizes needed to draw the\n  // view, so that we don't interleave reading and writing to the DOM.\n  function getDimensions(cm) {\n    var d = cm.display, left = {}, width = {};\n    var gutterLeft = d.gutters.clientLeft;\n    for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) {\n      left[cm.options.gutters[i]] = n.offsetLeft + n.clientLeft + gutterLeft;\n      width[cm.options.gutters[i]] = n.clientWidth;\n    }\n    return {fixedPos: compensateForHScroll(d),\n            gutterTotalWidth: d.gutters.offsetWidth,\n            gutterLeft: left,\n            gutterWidth: width,\n            wrapperWidth: d.wrapper.clientWidth};\n  }\n\n  // Sync the actual display DOM structure with display.view, removing\n  // nodes for lines that are no longer in view, and creating the ones\n  // that are not there yet, and updating the ones that are out of\n  // date.\n  function patchDisplay(cm, updateNumbersFrom, dims) {\n    var display = cm.display, lineNumbers = cm.options.lineNumbers;\n    var container = display.lineDiv, cur = container.firstChild;\n\n    function rm(node) {\n      var next = node.nextSibling;\n      // Works around a throw-scroll bug in OS X Webkit\n      if (webkit && mac && cm.display.currentWheelTarget == node)\n        node.style.display = \"none\";\n      else\n        node.parentNode.removeChild(node);\n      return next;\n    }\n\n    var view = display.view, lineN = display.viewFrom;\n    // Loop over the elements in the view, syncing cur (the DOM nodes\n    // in display.lineDiv) with the view as we go.\n    for (var i = 0; i < view.length; i++) {\n      var lineView = view[i];\n      if (lineView.hidden) {\n      } else if (!lineView.node || lineView.node.parentNode != container) { // Not drawn yet\n        var node = buildLineElement(cm, lineView, lineN, dims);\n        container.insertBefore(node, cur);\n      } else { // Already drawn\n        while (cur != lineView.node) cur = rm(cur);\n        var updateNumber = lineNumbers && updateNumbersFrom != null &&\n          updateNumbersFrom <= lineN && lineView.lineNumber;\n        if (lineView.changes) {\n          if (indexOf(lineView.changes, \"gutter\") > -1) updateNumber = false;\n          updateLineForChanges(cm, lineView, lineN, dims);\n        }\n        if (updateNumber) {\n          removeChildren(lineView.lineNumber);\n          lineView.lineNumber.appendChild(document.createTextNode(lineNumberFor(cm.options, lineN)));\n        }\n        cur = lineView.node.nextSibling;\n      }\n      lineN += lineView.size;\n    }\n    while (cur) cur = rm(cur);\n  }\n\n  // When an aspect of a line changes, a string is added to\n  // lineView.changes. This updates the relevant part of the line's\n  // DOM structure.\n  function updateLineForChanges(cm, lineView, lineN, dims) {\n    for (var j = 0; j < lineView.changes.length; j++) {\n      var type = lineView.changes[j];\n      if (type == \"text\") updateLineText(cm, lineView);\n      else if (type == \"gutter\") updateLineGutter(cm, lineView, lineN, dims);\n      else if (type == \"class\") updateLineClasses(lineView);\n      else if (type == \"widget\") updateLineWidgets(cm, lineView, dims);\n    }\n    lineView.changes = null;\n  }\n\n  // Lines with gutter elements, widgets or a background class need to\n  // be wrapped, and have the extra elements added to the wrapper div\n  function ensureLineWrapped(lineView) {\n    if (lineView.node == lineView.text) {\n      lineView.node = elt(\"div\", null, null, \"position: relative\");\n      if (lineView.text.parentNode)\n        lineView.text.parentNode.replaceChild(lineView.node, lineView.text);\n      lineView.node.appendChild(lineView.text);\n      if (ie && ie_version < 8) lineView.node.style.zIndex = 2;\n    }\n    return lineView.node;\n  }\n\n  function updateLineBackground(lineView) {\n    var cls = lineView.bgClass ? lineView.bgClass + \" \" + (lineView.line.bgClass || \"\") : lineView.line.bgClass;\n    if (cls) cls += \" CodeMirror-linebackground\";\n    if (lineView.background) {\n      if (cls) lineView.background.className = cls;\n      else { lineView.background.parentNode.removeChild(lineView.background); lineView.background = null; }\n    } else if (cls) {\n      var wrap = ensureLineWrapped(lineView);\n      lineView.background = wrap.insertBefore(elt(\"div\", null, cls), wrap.firstChild);\n    }\n  }\n\n  // Wrapper around buildLineContent which will reuse the structure\n  // in display.externalMeasured when possible.\n  function getLineContent(cm, lineView) {\n    var ext = cm.display.externalMeasured;\n    if (ext && ext.line == lineView.line) {\n      cm.display.externalMeasured = null;\n      lineView.measure = ext.measure;\n      return ext.built;\n    }\n    return buildLineContent(cm, lineView);\n  }\n\n  // Redraw the line's text. Interacts with the background and text\n  // classes because the mode may output tokens that influence these\n  // classes.\n  function updateLineText(cm, lineView) {\n    var cls = lineView.text.className;\n    var built = getLineContent(cm, lineView);\n    if (lineView.text == lineView.node) lineView.node = built.pre;\n    lineView.text.parentNode.replaceChild(built.pre, lineView.text);\n    lineView.text = built.pre;\n    if (built.bgClass != lineView.bgClass || built.textClass != lineView.textClass) {\n      lineView.bgClass = built.bgClass;\n      lineView.textClass = built.textClass;\n      updateLineClasses(lineView);\n    } else if (cls) {\n      lineView.text.className = cls;\n    }\n  }\n\n  function updateLineClasses(lineView) {\n    updateLineBackground(lineView);\n    if (lineView.line.wrapClass)\n      ensureLineWrapped(lineView).className = lineView.line.wrapClass;\n    else if (lineView.node != lineView.text)\n      lineView.node.className = \"\";\n    var textClass = lineView.textClass ? lineView.textClass + \" \" + (lineView.line.textClass || \"\") : lineView.line.textClass;\n    lineView.text.className = textClass || \"\";\n  }\n\n  function updateLineGutter(cm, lineView, lineN, dims) {\n    if (lineView.gutter) {\n      lineView.node.removeChild(lineView.gutter);\n      lineView.gutter = null;\n    }\n    if (lineView.gutterBackground) {\n      lineView.node.removeChild(lineView.gutterBackground);\n      lineView.gutterBackground = null;\n    }\n    if (lineView.line.gutterClass) {\n      var wrap = ensureLineWrapped(lineView);\n      lineView.gutterBackground = elt(\"div\", null, \"CodeMirror-gutter-background \" + lineView.line.gutterClass,\n                                      \"left: \" + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) +\n                                      \"px; width: \" + dims.gutterTotalWidth + \"px\");\n      wrap.insertBefore(lineView.gutterBackground, lineView.text);\n    }\n    var markers = lineView.line.gutterMarkers;\n    if (cm.options.lineNumbers || markers) {\n      var wrap = ensureLineWrapped(lineView);\n      var gutterWrap = lineView.gutter = elt(\"div\", null, \"CodeMirror-gutter-wrapper\", \"left: \" +\n                                             (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + \"px\");\n      cm.display.input.setUneditable(gutterWrap);\n      wrap.insertBefore(gutterWrap, lineView.text);\n      if (lineView.line.gutterClass)\n        gutterWrap.className += \" \" + lineView.line.gutterClass;\n      if (cm.options.lineNumbers && (!markers || !markers[\"CodeMirror-linenumbers\"]))\n        lineView.lineNumber = gutterWrap.appendChild(\n          elt(\"div\", lineNumberFor(cm.options, lineN),\n              \"CodeMirror-linenumber CodeMirror-gutter-elt\",\n              \"left: \" + dims.gutterLeft[\"CodeMirror-linenumbers\"] + \"px; width: \"\n              + cm.display.lineNumInnerWidth + \"px\"));\n      if (markers) for (var k = 0; k < cm.options.gutters.length; ++k) {\n        var id = cm.options.gutters[k], found = markers.hasOwnProperty(id) && markers[id];\n        if (found)\n          gutterWrap.appendChild(elt(\"div\", [found], \"CodeMirror-gutter-elt\", \"left: \" +\n                                     dims.gutterLeft[id] + \"px; width: \" + dims.gutterWidth[id] + \"px\"));\n      }\n    }\n  }\n\n  function updateLineWidgets(cm, lineView, dims) {\n    if (lineView.alignable) lineView.alignable = null;\n    for (var node = lineView.node.firstChild, next; node; node = next) {\n      var next = node.nextSibling;\n      if (node.className == \"CodeMirror-linewidget\")\n        lineView.node.removeChild(node);\n    }\n    insertLineWidgets(cm, lineView, dims);\n  }\n\n  // Build a line's DOM representation from scratch\n  function buildLineElement(cm, lineView, lineN, dims) {\n    var built = getLineContent(cm, lineView);\n    lineView.text = lineView.node = built.pre;\n    if (built.bgClass) lineView.bgClass = built.bgClass;\n    if (built.textClass) lineView.textClass = built.textClass;\n\n    updateLineClasses(lineView);\n    updateLineGutter(cm, lineView, lineN, dims);\n    insertLineWidgets(cm, lineView, dims);\n    return lineView.node;\n  }\n\n  // A lineView may contain multiple logical lines (when merged by\n  // collapsed spans). The widgets for all of them need to be drawn.\n  function insertLineWidgets(cm, lineView, dims) {\n    insertLineWidgetsFor(cm, lineView.line, lineView, dims, true);\n    if (lineView.rest) for (var i = 0; i < lineView.rest.length; i++)\n      insertLineWidgetsFor(cm, lineView.rest[i], lineView, dims, false);\n  }\n\n  function insertLineWidgetsFor(cm, line, lineView, dims, allowAbove) {\n    if (!line.widgets) return;\n    var wrap = ensureLineWrapped(lineView);\n    for (var i = 0, ws = line.widgets; i < ws.length; ++i) {\n      var widget = ws[i], node = elt(\"div\", [widget.node], \"CodeMirror-linewidget\");\n      if (!widget.handleMouseEvents) node.setAttribute(\"cm-ignore-events\", \"true\");\n      positionLineWidget(widget, node, lineView, dims);\n      cm.display.input.setUneditable(node);\n      if (allowAbove && widget.above)\n        wrap.insertBefore(node, lineView.gutter || lineView.text);\n      else\n        wrap.appendChild(node);\n      signalLater(widget, \"redraw\");\n    }\n  }\n\n  function positionLineWidget(widget, node, lineView, dims) {\n    if (widget.noHScroll) {\n      (lineView.alignable || (lineView.alignable = [])).push(node);\n      var width = dims.wrapperWidth;\n      node.style.left = dims.fixedPos + \"px\";\n      if (!widget.coverGutter) {\n        width -= dims.gutterTotalWidth;\n        node.style.paddingLeft = dims.gutterTotalWidth + \"px\";\n      }\n      node.style.width = width + \"px\";\n    }\n    if (widget.coverGutter) {\n      node.style.zIndex = 5;\n      node.style.position = \"relative\";\n      if (!widget.noHScroll) node.style.marginLeft = -dims.gutterTotalWidth + \"px\";\n    }\n  }\n\n  // POSITION OBJECT\n\n  // A Pos instance represents a position within the text.\n  var Pos = CodeMirror.Pos = function(line, ch) {\n    if (!(this instanceof Pos)) return new Pos(line, ch);\n    this.line = line; this.ch = ch;\n  };\n\n  // Compare two positions, return 0 if they are the same, a negative\n  // number when a is less, and a positive number otherwise.\n  var cmp = CodeMirror.cmpPos = function(a, b) { return a.line - b.line || a.ch - b.ch; };\n\n  function copyPos(x) {return Pos(x.line, x.ch);}\n  function maxPos(a, b) { return cmp(a, b) < 0 ? b : a; }\n  function minPos(a, b) { return cmp(a, b) < 0 ? a : b; }\n\n  // INPUT HANDLING\n\n  function ensureFocus(cm) {\n    if (!cm.state.focused) { cm.display.input.focus(); onFocus(cm); }\n  }\n\n  // This will be set to an array of strings when copying, so that,\n  // when pasting, we know what kind of selections the copied text\n  // was made out of.\n  var lastCopied = null;\n\n  function applyTextInput(cm, inserted, deleted, sel, origin) {\n    var doc = cm.doc;\n    cm.display.shift = false;\n    if (!sel) sel = doc.sel;\n\n    var paste = cm.state.pasteIncoming || origin == \"paste\";\n    var textLines = doc.splitLines(inserted), multiPaste = null;\n    // When pasing N lines into N selections, insert one line per selection\n    if (paste && sel.ranges.length > 1) {\n      if (lastCopied && lastCopied.join(\"\\n\") == inserted) {\n        if (sel.ranges.length % lastCopied.length == 0) {\n          multiPaste = [];\n          for (var i = 0; i < lastCopied.length; i++)\n            multiPaste.push(doc.splitLines(lastCopied[i]));\n        }\n      } else if (textLines.length == sel.ranges.length) {\n        multiPaste = map(textLines, function(l) { return [l]; });\n      }\n    }\n\n    // Normal behavior is to insert the new text into every selection\n    for (var i = sel.ranges.length - 1; i >= 0; i--) {\n      var range = sel.ranges[i];\n      var from = range.from(), to = range.to();\n      if (range.empty()) {\n        if (deleted && deleted > 0) // Handle deletion\n          from = Pos(from.line, from.ch - deleted);\n        else if (cm.state.overwrite && !paste) // Handle overwrite\n          to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length));\n      }\n      var updateInput = cm.curOp.updateInput;\n      var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i % multiPaste.length] : textLines,\n                         origin: origin || (paste ? \"paste\" : cm.state.cutIncoming ? \"cut\" : \"+input\")};\n      makeChange(cm.doc, changeEvent);\n      signalLater(cm, \"inputRead\", cm, changeEvent);\n    }\n    if (inserted && !paste)\n      triggerElectric(cm, inserted);\n\n    ensureCursorVisible(cm);\n    cm.curOp.updateInput = updateInput;\n    cm.curOp.typing = true;\n    cm.state.pasteIncoming = cm.state.cutIncoming = false;\n  }\n\n  function handlePaste(e, cm) {\n    var pasted = e.clipboardData && e.clipboardData.getData(\"text/plain\");\n    if (pasted) {\n      e.preventDefault();\n      if (!cm.isReadOnly() && !cm.options.disableInput)\n        runInOp(cm, function() { applyTextInput(cm, pasted, 0, null, \"paste\"); });\n      return true;\n    }\n  }\n\n  function triggerElectric(cm, inserted) {\n    // When an 'electric' character is inserted, immediately trigger a reindent\n    if (!cm.options.electricChars || !cm.options.smartIndent) return;\n    var sel = cm.doc.sel;\n\n    for (var i = sel.ranges.length - 1; i >= 0; i--) {\n      var range = sel.ranges[i];\n      if (range.head.ch > 100 || (i && sel.ranges[i - 1].head.line == range.head.line)) continue;\n      var mode = cm.getModeAt(range.head);\n      var indented = false;\n      if (mode.electricChars) {\n        for (var j = 0; j < mode.electricChars.length; j++)\n          if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) {\n            indented = indentLine(cm, range.head.line, \"smart\");\n            break;\n          }\n      } else if (mode.electricInput) {\n        if (mode.electricInput.test(getLine(cm.doc, range.head.line).text.slice(0, range.head.ch)))\n          indented = indentLine(cm, range.head.line, \"smart\");\n      }\n      if (indented) signalLater(cm, \"electricInput\", cm, range.head.line);\n    }\n  }\n\n  function copyableRanges(cm) {\n    var text = [], ranges = [];\n    for (var i = 0; i < cm.doc.sel.ranges.length; i++) {\n      var line = cm.doc.sel.ranges[i].head.line;\n      var lineRange = {anchor: Pos(line, 0), head: Pos(line + 1, 0)};\n      ranges.push(lineRange);\n      text.push(cm.getRange(lineRange.anchor, lineRange.head));\n    }\n    return {text: text, ranges: ranges};\n  }\n\n  function disableBrowserMagic(field) {\n    field.setAttribute(\"autocorrect\", \"off\");\n    field.setAttribute(\"autocapitalize\", \"off\");\n    field.setAttribute(\"spellcheck\", \"false\");\n  }\n\n  // TEXTAREA INPUT STYLE\n\n  function TextareaInput(cm) {\n    this.cm = cm;\n    // See input.poll and input.reset\n    this.prevInput = \"\";\n\n    // Flag that indicates whether we expect input to appear real soon\n    // now (after some event like 'keypress' or 'input') and are\n    // polling intensively.\n    this.pollingFast = false;\n    // Self-resetting timeout for the poller\n    this.polling = new Delayed();\n    // Tracks when input.reset has punted to just putting a short\n    // string into the textarea instead of the full selection.\n    this.inaccurateSelection = false;\n    // Used to work around IE issue with selection being forgotten when focus moves away from textarea\n    this.hasSelection = false;\n    this.composing = null;\n  };\n\n  function hiddenTextarea() {\n    var te = elt(\"textarea\", null, null, \"position: absolute; padding: 0; width: 1px; height: 1em; outline: none\");\n    var div = elt(\"div\", [te], null, \"overflow: hidden; position: relative; width: 3px; height: 0px;\");\n    // The textarea is kept positioned near the cursor to prevent the\n    // fact that it'll be scrolled into view on input from scrolling\n    // our fake cursor out of view. On webkit, when wrap=off, paste is\n    // very slow. So make the area wide instead.\n    if (webkit) te.style.width = \"1000px\";\n    else te.setAttribute(\"wrap\", \"off\");\n    // If border: 0; -- iOS fails to open keyboard (issue #1287)\n    if (ios) te.style.border = \"1px solid black\";\n    disableBrowserMagic(te);\n    return div;\n  }\n\n  TextareaInput.prototype = copyObj({\n    init: function(display) {\n      var input = this, cm = this.cm;\n\n      // Wraps and hides input textarea\n      var div = this.wrapper = hiddenTextarea();\n      // The semihidden textarea that is focused when the editor is\n      // focused, and receives input.\n      var te = this.textarea = div.firstChild;\n      display.wrapper.insertBefore(div, display.wrapper.firstChild);\n\n      // Needed to hide big blue blinking cursor on Mobile Safari (doesn't seem to work in iOS 8 anymore)\n      if (ios) te.style.width = \"0px\";\n\n      on(te, \"input\", function() {\n        if (ie && ie_version >= 9 && input.hasSelection) input.hasSelection = null;\n        input.poll();\n      });\n\n      on(te, \"paste\", function(e) {\n        if (signalDOMEvent(cm, e) || handlePaste(e, cm)) return\n\n        cm.state.pasteIncoming = true;\n        input.fastPoll();\n      });\n\n      function prepareCopyCut(e) {\n        if (signalDOMEvent(cm, e)) return\n        if (cm.somethingSelected()) {\n          lastCopied = cm.getSelections();\n          if (input.inaccurateSelection) {\n            input.prevInput = \"\";\n            input.inaccurateSelection = false;\n            te.value = lastCopied.join(\"\\n\");\n            selectInput(te);\n          }\n        } else if (!cm.options.lineWiseCopyCut) {\n          return;\n        } else {\n          var ranges = copyableRanges(cm);\n          lastCopied = ranges.text;\n          if (e.type == \"cut\") {\n            cm.setSelections(ranges.ranges, null, sel_dontScroll);\n          } else {\n            input.prevInput = \"\";\n            te.value = ranges.text.join(\"\\n\");\n            selectInput(te);\n          }\n        }\n        if (e.type == \"cut\") cm.state.cutIncoming = true;\n      }\n      on(te, \"cut\", prepareCopyCut);\n      on(te, \"copy\", prepareCopyCut);\n\n      on(display.scroller, \"paste\", function(e) {\n        if (eventInWidget(display, e) || signalDOMEvent(cm, e)) return;\n        cm.state.pasteIncoming = true;\n        input.focus();\n      });\n\n      // Prevent normal selection in the editor (we handle our own)\n      on(display.lineSpace, \"selectstart\", function(e) {\n        if (!eventInWidget(display, e)) e_preventDefault(e);\n      });\n\n      on(te, \"compositionstart\", function() {\n        var start = cm.getCursor(\"from\");\n        if (input.composing) input.composing.range.clear()\n        input.composing = {\n          start: start,\n          range: cm.markText(start, cm.getCursor(\"to\"), {className: \"CodeMirror-composing\"})\n        };\n      });\n      on(te, \"compositionend\", function() {\n        if (input.composing) {\n          input.poll();\n          input.composing.range.clear();\n          input.composing = null;\n        }\n      });\n    },\n\n    prepareSelection: function() {\n      // Redraw the selection and/or cursor\n      var cm = this.cm, display = cm.display, doc = cm.doc;\n      var result = prepareSelection(cm);\n\n      // Move the hidden textarea near the cursor to prevent scrolling artifacts\n      if (cm.options.moveInputWithCursor) {\n        var headPos = cursorCoords(cm, doc.sel.primary().head, \"div\");\n        var wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect();\n        result.teTop = Math.max(0, Math.min(display.wrapper.clientHeight - 10,\n                                            headPos.top + lineOff.top - wrapOff.top));\n        result.teLeft = Math.max(0, Math.min(display.wrapper.clientWidth - 10,\n                                             headPos.left + lineOff.left - wrapOff.left));\n      }\n\n      return result;\n    },\n\n    showSelection: function(drawn) {\n      var cm = this.cm, display = cm.display;\n      removeChildrenAndAdd(display.cursorDiv, drawn.cursors);\n      removeChildrenAndAdd(display.selectionDiv, drawn.selection);\n      if (drawn.teTop != null) {\n        this.wrapper.style.top = drawn.teTop + \"px\";\n        this.wrapper.style.left = drawn.teLeft + \"px\";\n      }\n    },\n\n    // Reset the input to correspond to the selection (or to be empty,\n    // when not typing and nothing is selected)\n    reset: function(typing) {\n      if (this.contextMenuPending) return;\n      var minimal, selected, cm = this.cm, doc = cm.doc;\n      if (cm.somethingSelected()) {\n        this.prevInput = \"\";\n        var range = doc.sel.primary();\n        minimal = hasCopyEvent &&\n          (range.to().line - range.from().line > 100 || (selected = cm.getSelection()).length > 1000);\n        var content = minimal ? \"-\" : selected || cm.getSelection();\n        this.textarea.value = content;\n        if (cm.state.focused) selectInput(this.textarea);\n        if (ie && ie_version >= 9) this.hasSelection = content;\n      } else if (!typing) {\n        this.prevInput = this.textarea.value = \"\";\n        if (ie && ie_version >= 9) this.hasSelection = null;\n      }\n      this.inaccurateSelection = minimal;\n    },\n\n    getField: function() { return this.textarea; },\n\n    supportsTouch: function() { return false; },\n\n    focus: function() {\n      if (this.cm.options.readOnly != \"nocursor\" && (!mobile || activeElt() != this.textarea)) {\n        try { this.textarea.focus(); }\n        catch (e) {} // IE8 will throw if the textarea is display: none or not in DOM\n      }\n    },\n\n    blur: function() { this.textarea.blur(); },\n\n    resetPosition: function() {\n      this.wrapper.style.top = this.wrapper.style.left = 0;\n    },\n\n    receivedFocus: function() { this.slowPoll(); },\n\n    // Poll for input changes, using the normal rate of polling. This\n    // runs as long as the editor is focused.\n    slowPoll: function() {\n      var input = this;\n      if (input.pollingFast) return;\n      input.polling.set(this.cm.options.pollInterval, function() {\n        input.poll();\n        if (input.cm.state.focused) input.slowPoll();\n      });\n    },\n\n    // When an event has just come in that is likely to add or change\n    // something in the input textarea, we poll faster, to ensure that\n    // the change appears on the screen quickly.\n    fastPoll: function() {\n      var missed = false, input = this;\n      input.pollingFast = true;\n      function p() {\n        var changed = input.poll();\n        if (!changed && !missed) {missed = true; input.polling.set(60, p);}\n        else {input.pollingFast = false; input.slowPoll();}\n      }\n      input.polling.set(20, p);\n    },\n\n    // Read input from the textarea, and update the document to match.\n    // When something is selected, it is present in the textarea, and\n    // selected (unless it is huge, in which case a placeholder is\n    // used). When nothing is selected, the cursor sits after previously\n    // seen text (can be empty), which is stored in prevInput (we must\n    // not reset the textarea when typing, because that breaks IME).\n    poll: function() {\n      var cm = this.cm, input = this.textarea, prevInput = this.prevInput;\n      // Since this is called a *lot*, try to bail out as cheaply as\n      // possible when it is clear that nothing happened. hasSelection\n      // will be the case when there is a lot of text in the textarea,\n      // in which case reading its value would be expensive.\n      if (this.contextMenuPending || !cm.state.focused ||\n          (hasSelection(input) && !prevInput && !this.composing) ||\n          cm.isReadOnly() || cm.options.disableInput || cm.state.keySeq)\n        return false;\n\n      var text = input.value;\n      // If nothing changed, bail.\n      if (text == prevInput && !cm.somethingSelected()) return false;\n      // Work around nonsensical selection resetting in IE9/10, and\n      // inexplicable appearance of private area unicode characters on\n      // some key combos in Mac (#2689).\n      if (ie && ie_version >= 9 && this.hasSelection === text ||\n          mac && /[\\uf700-\\uf7ff]/.test(text)) {\n        cm.display.input.reset();\n        return false;\n      }\n\n      if (cm.doc.sel == cm.display.selForContextMenu) {\n        var first = text.charCodeAt(0);\n        if (first == 0x200b && !prevInput) prevInput = \"\\u200b\";\n        if (first == 0x21da) { this.reset(); return this.cm.execCommand(\"undo\"); }\n      }\n      // Find the part of the input that is actually new\n      var same = 0, l = Math.min(prevInput.length, text.length);\n      while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) ++same;\n\n      var self = this;\n      runInOp(cm, function() {\n        applyTextInput(cm, text.slice(same), prevInput.length - same,\n                       null, self.composing ? \"*compose\" : null);\n\n        // Don't leave long text in the textarea, since it makes further polling slow\n        if (text.length > 1000 || text.indexOf(\"\\n\") > -1) input.value = self.prevInput = \"\";\n        else self.prevInput = text;\n\n        if (self.composing) {\n          self.composing.range.clear();\n          self.composing.range = cm.markText(self.composing.start, cm.getCursor(\"to\"),\n                                             {className: \"CodeMirror-composing\"});\n        }\n      });\n      return true;\n    },\n\n    ensurePolled: function() {\n      if (this.pollingFast && this.poll()) this.pollingFast = false;\n    },\n\n    onKeyPress: function() {\n      if (ie && ie_version >= 9) this.hasSelection = null;\n      this.fastPoll();\n    },\n\n    onContextMenu: function(e) {\n      var input = this, cm = input.cm, display = cm.display, te = input.textarea;\n      var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop;\n      if (!pos || presto) return; // Opera is difficult.\n\n      // Reset the current text selection only if the click is done outside of the selection\n      // and 'resetSelectionOnContextMenu' option is true.\n      var reset = cm.options.resetSelectionOnContextMenu;\n      if (reset && cm.doc.sel.contains(pos) == -1)\n        operation(cm, setSelection)(cm.doc, simpleSelection(pos), sel_dontScroll);\n\n      var oldCSS = te.style.cssText, oldWrapperCSS = input.wrapper.style.cssText;\n      input.wrapper.style.cssText = \"position: absolute\"\n      var wrapperBox = input.wrapper.getBoundingClientRect()\n      te.style.cssText = \"position: absolute; width: 30px; height: 30px; top: \" + (e.clientY - wrapperBox.top - 5) +\n        \"px; left: \" + (e.clientX - wrapperBox.left - 5) + \"px; z-index: 1000; background: \" +\n        (ie ? \"rgba(255, 255, 255, .05)\" : \"transparent\") +\n        \"; outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);\";\n      if (webkit) var oldScrollY = window.scrollY; // Work around Chrome issue (#2712)\n      display.input.focus();\n      if (webkit) window.scrollTo(null, oldScrollY);\n      display.input.reset();\n      // Adds \"Select all\" to context menu in FF\n      if (!cm.somethingSelected()) te.value = input.prevInput = \" \";\n      input.contextMenuPending = true;\n      display.selForContextMenu = cm.doc.sel;\n      clearTimeout(display.detectingSelectAll);\n\n      // Select-all will be greyed out if there's nothing to select, so\n      // this adds a zero-width space so that we can later check whether\n      // it got selected.\n      function prepareSelectAllHack() {\n        if (te.selectionStart != null) {\n          var selected = cm.somethingSelected();\n          var extval = \"\\u200b\" + (selected ? te.value : \"\");\n          te.value = \"\\u21da\"; // Used to catch context-menu undo\n          te.value = extval;\n          input.prevInput = selected ? \"\" : \"\\u200b\";\n          te.selectionStart = 1; te.selectionEnd = extval.length;\n          // Re-set this, in case some other handler touched the\n          // selection in the meantime.\n          display.selForContextMenu = cm.doc.sel;\n        }\n      }\n      function rehide() {\n        input.contextMenuPending = false;\n        input.wrapper.style.cssText = oldWrapperCSS\n        te.style.cssText = oldCSS;\n        if (ie && ie_version < 9) display.scrollbars.setScrollTop(display.scroller.scrollTop = scrollPos);\n\n        // Try to detect the user choosing select-all\n        if (te.selectionStart != null) {\n          if (!ie || (ie && ie_version < 9)) prepareSelectAllHack();\n          var i = 0, poll = function() {\n            if (display.selForContextMenu == cm.doc.sel && te.selectionStart == 0 &&\n                te.selectionEnd > 0 && input.prevInput == \"\\u200b\")\n              operation(cm, commands.selectAll)(cm);\n            else if (i++ < 10) display.detectingSelectAll = setTimeout(poll, 500);\n            else display.input.reset();\n          };\n          display.detectingSelectAll = setTimeout(poll, 200);\n        }\n      }\n\n      if (ie && ie_version >= 9) prepareSelectAllHack();\n      if (captureRightClick) {\n        e_stop(e);\n        var mouseup = function() {\n          off(window, \"mouseup\", mouseup);\n          setTimeout(rehide, 20);\n        };\n        on(window, \"mouseup\", mouseup);\n      } else {\n        setTimeout(rehide, 50);\n      }\n    },\n\n    readOnlyChanged: function(val) {\n      if (!val) this.reset();\n    },\n\n    setUneditable: nothing,\n\n    needsContentAttribute: false\n  }, TextareaInput.prototype);\n\n  // CONTENTEDITABLE INPUT STYLE\n\n  function ContentEditableInput(cm) {\n    this.cm = cm;\n    this.lastAnchorNode = this.lastAnchorOffset = this.lastFocusNode = this.lastFocusOffset = null;\n    this.polling = new Delayed();\n    this.gracePeriod = false;\n  }\n\n  ContentEditableInput.prototype = copyObj({\n    init: function(display) {\n      var input = this, cm = input.cm;\n      var div = input.div = display.lineDiv;\n      disableBrowserMagic(div);\n\n      on(div, \"paste\", function(e) {\n        if (!signalDOMEvent(cm, e)) handlePaste(e, cm);\n      })\n\n      on(div, \"compositionstart\", function(e) {\n        var data = e.data;\n        input.composing = {sel: cm.doc.sel, data: data, startData: data};\n        if (!data) return;\n        var prim = cm.doc.sel.primary();\n        var line = cm.getLine(prim.head.line);\n        var found = line.indexOf(data, Math.max(0, prim.head.ch - data.length));\n        if (found > -1 && found <= prim.head.ch)\n          input.composing.sel = simpleSelection(Pos(prim.head.line, found),\n                                                Pos(prim.head.line, found + data.length));\n      });\n      on(div, \"compositionupdate\", function(e) {\n        input.composing.data = e.data;\n      });\n      on(div, \"compositionend\", function(e) {\n        var ours = input.composing;\n        if (!ours) return;\n        if (e.data != ours.startData && !/\\u200b/.test(e.data))\n          ours.data = e.data;\n        // Need a small delay to prevent other code (input event,\n        // selection polling) from doing damage when fired right after\n        // compositionend.\n        setTimeout(function() {\n          if (!ours.handled)\n            input.applyComposition(ours);\n          if (input.composing == ours)\n            input.composing = null;\n        }, 50);\n      });\n\n      on(div, \"touchstart\", function() {\n        input.forceCompositionEnd();\n      });\n\n      on(div, \"input\", function() {\n        if (input.composing) return;\n        if (cm.isReadOnly() || !input.pollContent())\n          runInOp(input.cm, function() {regChange(cm);});\n      });\n\n      function onCopyCut(e) {\n        if (signalDOMEvent(cm, e)) return\n        if (cm.somethingSelected()) {\n          lastCopied = cm.getSelections();\n          if (e.type == \"cut\") cm.replaceSelection(\"\", null, \"cut\");\n        } else if (!cm.options.lineWiseCopyCut) {\n          return;\n        } else {\n          var ranges = copyableRanges(cm);\n          lastCopied = ranges.text;\n          if (e.type == \"cut\") {\n            cm.operation(function() {\n              cm.setSelections(ranges.ranges, 0, sel_dontScroll);\n              cm.replaceSelection(\"\", null, \"cut\");\n            });\n          }\n        }\n        // iOS exposes the clipboard API, but seems to discard content inserted into it\n        if (e.clipboardData && !ios) {\n          e.preventDefault();\n          e.clipboardData.clearData();\n          e.clipboardData.setData(\"text/plain\", lastCopied.join(\"\\n\"));\n        } else {\n          // Old-fashioned briefly-focus-a-textarea hack\n          var kludge = hiddenTextarea(), te = kludge.firstChild;\n          cm.display.lineSpace.insertBefore(kludge, cm.display.lineSpace.firstChild);\n          te.value = lastCopied.join(\"\\n\");\n          var hadFocus = document.activeElement;\n          selectInput(te);\n          setTimeout(function() {\n            cm.display.lineSpace.removeChild(kludge);\n            hadFocus.focus();\n          }, 50);\n        }\n      }\n      on(div, \"copy\", onCopyCut);\n      on(div, \"cut\", onCopyCut);\n    },\n\n    prepareSelection: function() {\n      var result = prepareSelection(this.cm, false);\n      result.focus = this.cm.state.focused;\n      return result;\n    },\n\n    showSelection: function(info) {\n      if (!info || !this.cm.display.view.length) return;\n      if (info.focus) this.showPrimarySelection();\n      this.showMultipleSelections(info);\n    },\n\n    showPrimarySelection: function() {\n      var sel = window.getSelection(), prim = this.cm.doc.sel.primary();\n      var curAnchor = domToPos(this.cm, sel.anchorNode, sel.anchorOffset);\n      var curFocus = domToPos(this.cm, sel.focusNode, sel.focusOffset);\n      if (curAnchor && !curAnchor.bad && curFocus && !curFocus.bad &&\n          cmp(minPos(curAnchor, curFocus), prim.from()) == 0 &&\n          cmp(maxPos(curAnchor, curFocus), prim.to()) == 0)\n        return;\n\n      var start = posToDOM(this.cm, prim.from());\n      var end = posToDOM(this.cm, prim.to());\n      if (!start && !end) return;\n\n      var view = this.cm.display.view;\n      var old = sel.rangeCount && sel.getRangeAt(0);\n      if (!start) {\n        start = {node: view[0].measure.map[2], offset: 0};\n      } else if (!end) {\n        var measure = view[view.length - 1].measure;\n        var map = measure.maps ? measure.maps[measure.maps.length - 1] : measure.map;\n        end = {node: map[map.length - 1], offset: map[map.length - 2] - map[map.length - 3]};\n      }\n\n      try { var rng = range(start.node, start.offset, end.offset, end.node); }\n      catch(e) {} // Our model of the DOM might be outdated, in which case the range we try to set can be impossible\n      if (rng) {\n        if (!gecko && this.cm.state.focused) {\n          sel.collapse(start.node, start.offset);\n          if (!rng.collapsed) sel.addRange(rng);\n        } else {\n          sel.removeAllRanges();\n          sel.addRange(rng);\n        }\n        if (old && sel.anchorNode == null) sel.addRange(old);\n        else if (gecko) this.startGracePeriod();\n      }\n      this.rememberSelection();\n    },\n\n    startGracePeriod: function() {\n      var input = this;\n      clearTimeout(this.gracePeriod);\n      this.gracePeriod = setTimeout(function() {\n        input.gracePeriod = false;\n        if (input.selectionChanged())\n          input.cm.operation(function() { input.cm.curOp.selectionChanged = true; });\n      }, 20);\n    },\n\n    showMultipleSelections: function(info) {\n      removeChildrenAndAdd(this.cm.display.cursorDiv, info.cursors);\n      removeChildrenAndAdd(this.cm.display.selectionDiv, info.selection);\n    },\n\n    rememberSelection: function() {\n      var sel = window.getSelection();\n      this.lastAnchorNode = sel.anchorNode; this.lastAnchorOffset = sel.anchorOffset;\n      this.lastFocusNode = sel.focusNode; this.lastFocusOffset = sel.focusOffset;\n    },\n\n    selectionInEditor: function() {\n      var sel = window.getSelection();\n      if (!sel.rangeCount) return false;\n      var node = sel.getRangeAt(0).commonAncestorContainer;\n      return contains(this.div, node);\n    },\n\n    focus: function() {\n      if (this.cm.options.readOnly != \"nocursor\") this.div.focus();\n    },\n    blur: function() { this.div.blur(); },\n    getField: function() { return this.div; },\n\n    supportsTouch: function() { return true; },\n\n    receivedFocus: function() {\n      var input = this;\n      if (this.selectionInEditor())\n        this.pollSelection();\n      else\n        runInOp(this.cm, function() { input.cm.curOp.selectionChanged = true; });\n\n      function poll() {\n        if (input.cm.state.focused) {\n          input.pollSelection();\n          input.polling.set(input.cm.options.pollInterval, poll);\n        }\n      }\n      this.polling.set(this.cm.options.pollInterval, poll);\n    },\n\n    selectionChanged: function() {\n      var sel = window.getSelection();\n      return sel.anchorNode != this.lastAnchorNode || sel.anchorOffset != this.lastAnchorOffset ||\n        sel.focusNode != this.lastFocusNode || sel.focusOffset != this.lastFocusOffset;\n    },\n\n    pollSelection: function() {\n      if (!this.composing && !this.gracePeriod && this.selectionChanged()) {\n        var sel = window.getSelection(), cm = this.cm;\n        this.rememberSelection();\n        var anchor = domToPos(cm, sel.anchorNode, sel.anchorOffset);\n        var head = domToPos(cm, sel.focusNode, sel.focusOffset);\n        if (anchor && head) runInOp(cm, function() {\n          setSelection(cm.doc, simpleSelection(anchor, head), sel_dontScroll);\n          if (anchor.bad || head.bad) cm.curOp.selectionChanged = true;\n        });\n      }\n    },\n\n    pollContent: function() {\n      var cm = this.cm, display = cm.display, sel = cm.doc.sel.primary();\n      var from = sel.from(), to = sel.to();\n      if (from.line < display.viewFrom || to.line > display.viewTo - 1) return false;\n\n      var fromIndex;\n      if (from.line == display.viewFrom || (fromIndex = findViewIndex(cm, from.line)) == 0) {\n        var fromLine = lineNo(display.view[0].line);\n        var fromNode = display.view[0].node;\n      } else {\n        var fromLine = lineNo(display.view[fromIndex].line);\n        var fromNode = display.view[fromIndex - 1].node.nextSibling;\n      }\n      var toIndex = findViewIndex(cm, to.line);\n      if (toIndex == display.view.length - 1) {\n        var toLine = display.viewTo - 1;\n        var toNode = display.lineDiv.lastChild;\n      } else {\n        var toLine = lineNo(display.view[toIndex + 1].line) - 1;\n        var toNode = display.view[toIndex + 1].node.previousSibling;\n      }\n\n      var newText = cm.doc.splitLines(domTextBetween(cm, fromNode, toNode, fromLine, toLine));\n      var oldText = getBetween(cm.doc, Pos(fromLine, 0), Pos(toLine, getLine(cm.doc, toLine).text.length));\n      while (newText.length > 1 && oldText.length > 1) {\n        if (lst(newText) == lst(oldText)) { newText.pop(); oldText.pop(); toLine--; }\n        else if (newText[0] == oldText[0]) { newText.shift(); oldText.shift(); fromLine++; }\n        else break;\n      }\n\n      var cutFront = 0, cutEnd = 0;\n      var newTop = newText[0], oldTop = oldText[0], maxCutFront = Math.min(newTop.length, oldTop.length);\n      while (cutFront < maxCutFront && newTop.charCodeAt(cutFront) == oldTop.charCodeAt(cutFront))\n        ++cutFront;\n      var newBot = lst(newText), oldBot = lst(oldText);\n      var maxCutEnd = Math.min(newBot.length - (newText.length == 1 ? cutFront : 0),\n                               oldBot.length - (oldText.length == 1 ? cutFront : 0));\n      while (cutEnd < maxCutEnd &&\n             newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1))\n        ++cutEnd;\n\n      newText[newText.length - 1] = newBot.slice(0, newBot.length - cutEnd);\n      newText[0] = newText[0].slice(cutFront);\n\n      var chFrom = Pos(fromLine, cutFront);\n      var chTo = Pos(toLine, oldText.length ? lst(oldText).length - cutEnd : 0);\n      if (newText.length > 1 || newText[0] || cmp(chFrom, chTo)) {\n        replaceRange(cm.doc, newText, chFrom, chTo, \"+input\");\n        return true;\n      }\n    },\n\n    ensurePolled: function() {\n      this.forceCompositionEnd();\n    },\n    reset: function() {\n      this.forceCompositionEnd();\n    },\n    forceCompositionEnd: function() {\n      if (!this.composing || this.composing.handled) return;\n      this.applyComposition(this.composing);\n      this.composing.handled = true;\n      this.div.blur();\n      this.div.focus();\n    },\n    applyComposition: function(composing) {\n      if (this.cm.isReadOnly())\n        operation(this.cm, regChange)(this.cm)\n      else if (composing.data && composing.data != composing.startData)\n        operation(this.cm, applyTextInput)(this.cm, composing.data, 0, composing.sel);\n    },\n\n    setUneditable: function(node) {\n      node.contentEditable = \"false\"\n    },\n\n    onKeyPress: function(e) {\n      e.preventDefault();\n      if (!this.cm.isReadOnly())\n        operation(this.cm, applyTextInput)(this.cm, String.fromCharCode(e.charCode == null ? e.keyCode : e.charCode), 0);\n    },\n\n    readOnlyChanged: function(val) {\n      this.div.contentEditable = String(val != \"nocursor\")\n    },\n\n    onContextMenu: nothing,\n    resetPosition: nothing,\n\n    needsContentAttribute: true\n  }, ContentEditableInput.prototype);\n\n  function posToDOM(cm, pos) {\n    var view = findViewForLine(cm, pos.line);\n    if (!view || view.hidden) return null;\n    var line = getLine(cm.doc, pos.line);\n    var info = mapFromLineView(view, line, pos.line);\n\n    var order = getOrder(line), side = \"left\";\n    if (order) {\n      var partPos = getBidiPartAt(order, pos.ch);\n      side = partPos % 2 ? \"right\" : \"left\";\n    }\n    var result = nodeAndOffsetInLineMap(info.map, pos.ch, side);\n    result.offset = result.collapse == \"right\" ? result.end : result.start;\n    return result;\n  }\n\n  function badPos(pos, bad) { if (bad) pos.bad = true; return pos; }\n\n  function domToPos(cm, node, offset) {\n    var lineNode;\n    if (node == cm.display.lineDiv) {\n      lineNode = cm.display.lineDiv.childNodes[offset];\n      if (!lineNode) return badPos(cm.clipPos(Pos(cm.display.viewTo - 1)), true);\n      node = null; offset = 0;\n    } else {\n      for (lineNode = node;; lineNode = lineNode.parentNode) {\n        if (!lineNode || lineNode == cm.display.lineDiv) return null;\n        if (lineNode.parentNode && lineNode.parentNode == cm.display.lineDiv) break;\n      }\n    }\n    for (var i = 0; i < cm.display.view.length; i++) {\n      var lineView = cm.display.view[i];\n      if (lineView.node == lineNode)\n        return locateNodeInLineView(lineView, node, offset);\n    }\n  }\n\n  function locateNodeInLineView(lineView, node, offset) {\n    var wrapper = lineView.text.firstChild, bad = false;\n    if (!node || !contains(wrapper, node)) return badPos(Pos(lineNo(lineView.line), 0), true);\n    if (node == wrapper) {\n      bad = true;\n      node = wrapper.childNodes[offset];\n      offset = 0;\n      if (!node) {\n        var line = lineView.rest ? lst(lineView.rest) : lineView.line;\n        return badPos(Pos(lineNo(line), line.text.length), bad);\n      }\n    }\n\n    var textNode = node.nodeType == 3 ? node : null, topNode = node;\n    if (!textNode && node.childNodes.length == 1 && node.firstChild.nodeType == 3) {\n      textNode = node.firstChild;\n      if (offset) offset = textNode.nodeValue.length;\n    }\n    while (topNode.parentNode != wrapper) topNode = topNode.parentNode;\n    var measure = lineView.measure, maps = measure.maps;\n\n    function find(textNode, topNode, offset) {\n      for (var i = -1; i < (maps ? maps.length : 0); i++) {\n        var map = i < 0 ? measure.map : maps[i];\n        for (var j = 0; j < map.length; j += 3) {\n          var curNode = map[j + 2];\n          if (curNode == textNode || curNode == topNode) {\n            var line = lineNo(i < 0 ? lineView.line : lineView.rest[i]);\n            var ch = map[j] + offset;\n            if (offset < 0 || curNode != textNode) ch = map[j + (offset ? 1 : 0)];\n            return Pos(line, ch);\n          }\n        }\n      }\n    }\n    var found = find(textNode, topNode, offset);\n    if (found) return badPos(found, bad);\n\n    for (var after = topNode.nextSibling, dist = textNode ? textNode.nodeValue.length - offset : 0; after; after = after.nextSibling) {\n      found = find(after, after.firstChild, 0);\n      if (found)\n        return badPos(Pos(found.line, found.ch - dist), bad);\n      else\n        dist += after.textContent.length;\n    }\n    for (var before = topNode.previousSibling, dist = offset; before; before = before.previousSibling) {\n      found = find(before, before.firstChild, -1);\n      if (found)\n        return badPos(Pos(found.line, found.ch + dist), bad);\n      else\n        dist += after.textContent.length;\n    }\n  }\n\n  function domTextBetween(cm, from, to, fromLine, toLine) {\n    var text = \"\", closing = false, lineSep = cm.doc.lineSeparator();\n    function recognizeMarker(id) { return function(marker) { return marker.id == id; }; }\n    function walk(node) {\n      if (node.nodeType == 1) {\n        var cmText = node.getAttribute(\"cm-text\");\n        if (cmText != null) {\n          if (cmText == \"\") cmText = node.textContent.replace(/\\u200b/g, \"\");\n          text += cmText;\n          return;\n        }\n        var markerID = node.getAttribute(\"cm-marker\"), range;\n        if (markerID) {\n          var found = cm.findMarks(Pos(fromLine, 0), Pos(toLine + 1, 0), recognizeMarker(+markerID));\n          if (found.length && (range = found[0].find()))\n            text += getBetween(cm.doc, range.from, range.to).join(lineSep);\n          return;\n        }\n        if (node.getAttribute(\"contenteditable\") == \"false\") return;\n        for (var i = 0; i < node.childNodes.length; i++)\n          walk(node.childNodes[i]);\n        if (/^(pre|div|p)$/i.test(node.nodeName))\n          closing = true;\n      } else if (node.nodeType == 3) {\n        var val = node.nodeValue;\n        if (!val) return;\n        if (closing) {\n          text += lineSep;\n          closing = false;\n        }\n        text += val;\n      }\n    }\n    for (;;) {\n      walk(from);\n      if (from == to) break;\n      from = from.nextSibling;\n    }\n    return text;\n  }\n\n  CodeMirror.inputStyles = {\"textarea\": TextareaInput, \"contenteditable\": ContentEditableInput};\n\n  // SELECTION / CURSOR\n\n  // Selection objects are immutable. A new one is created every time\n  // the selection changes. A selection is one or more non-overlapping\n  // (and non-touching) ranges, sorted, and an integer that indicates\n  // which one is the primary selection (the one that's scrolled into\n  // view, that getCursor returns, etc).\n  function Selection(ranges, primIndex) {\n    this.ranges = ranges;\n    this.primIndex = primIndex;\n  }\n\n  Selection.prototype = {\n    primary: function() { return this.ranges[this.primIndex]; },\n    equals: function(other) {\n      if (other == this) return true;\n      if (other.primIndex != this.primIndex || other.ranges.length != this.ranges.length) return false;\n      for (var i = 0; i < this.ranges.length; i++) {\n        var here = this.ranges[i], there = other.ranges[i];\n        if (cmp(here.anchor, there.anchor) != 0 || cmp(here.head, there.head) != 0) return false;\n      }\n      return true;\n    },\n    deepCopy: function() {\n      for (var out = [], i = 0; i < this.ranges.length; i++)\n        out[i] = new Range(copyPos(this.ranges[i].anchor), copyPos(this.ranges[i].head));\n      return new Selection(out, this.primIndex);\n    },\n    somethingSelected: function() {\n      for (var i = 0; i < this.ranges.length; i++)\n        if (!this.ranges[i].empty()) return true;\n      return false;\n    },\n    contains: function(pos, end) {\n      if (!end) end = pos;\n      for (var i = 0; i < this.ranges.length; i++) {\n        var range = this.ranges[i];\n        if (cmp(end, range.from()) >= 0 && cmp(pos, range.to()) <= 0)\n          return i;\n      }\n      return -1;\n    }\n  };\n\n  function Range(anchor, head) {\n    this.anchor = anchor; this.head = head;\n  }\n\n  Range.prototype = {\n    from: function() { return minPos(this.anchor, this.head); },\n    to: function() { return maxPos(this.anchor, this.head); },\n    empty: function() {\n      return this.head.line == this.anchor.line && this.head.ch == this.anchor.ch;\n    }\n  };\n\n  // Take an unsorted, potentially overlapping set of ranges, and\n  // build a selection out of it. 'Consumes' ranges array (modifying\n  // it).\n  function normalizeSelection(ranges, primIndex) {\n    var prim = ranges[primIndex];\n    ranges.sort(function(a, b) { return cmp(a.from(), b.from()); });\n    primIndex = indexOf(ranges, prim);\n    for (var i = 1; i < ranges.length; i++) {\n      var cur = ranges[i], prev = ranges[i - 1];\n      if (cmp(prev.to(), cur.from()) >= 0) {\n        var from = minPos(prev.from(), cur.from()), to = maxPos(prev.to(), cur.to());\n        var inv = prev.empty() ? cur.from() == cur.head : prev.from() == prev.head;\n        if (i <= primIndex) --primIndex;\n        ranges.splice(--i, 2, new Range(inv ? to : from, inv ? from : to));\n      }\n    }\n    return new Selection(ranges, primIndex);\n  }\n\n  function simpleSelection(anchor, head) {\n    return new Selection([new Range(anchor, head || anchor)], 0);\n  }\n\n  // Most of the external API clips given positions to make sure they\n  // actually exist within the document.\n  function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1));}\n  function clipPos(doc, pos) {\n    if (pos.line < doc.first) return Pos(doc.first, 0);\n    var last = doc.first + doc.size - 1;\n    if (pos.line > last) return Pos(last, getLine(doc, last).text.length);\n    return clipToLen(pos, getLine(doc, pos.line).text.length);\n  }\n  function clipToLen(pos, linelen) {\n    var ch = pos.ch;\n    if (ch == null || ch > linelen) return Pos(pos.line, linelen);\n    else if (ch < 0) return Pos(pos.line, 0);\n    else return pos;\n  }\n  function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size;}\n  function clipPosArray(doc, array) {\n    for (var out = [], i = 0; i < array.length; i++) out[i] = clipPos(doc, array[i]);\n    return out;\n  }\n\n  // SELECTION UPDATES\n\n  // The 'scroll' parameter given to many of these indicated whether\n  // the new cursor position should be scrolled into view after\n  // modifying the selection.\n\n  // If shift is held or the extend flag is set, extends a range to\n  // include a given position (and optionally a second position).\n  // Otherwise, simply returns the range between the given positions.\n  // Used for cursor motion and such.\n  function extendRange(doc, range, head, other) {\n    if (doc.cm && doc.cm.display.shift || doc.extend) {\n      var anchor = range.anchor;\n      if (other) {\n        var posBefore = cmp(head, anchor) < 0;\n        if (posBefore != (cmp(other, anchor) < 0)) {\n          anchor = head;\n          head = other;\n        } else if (posBefore != (cmp(head, other) < 0)) {\n          head = other;\n        }\n      }\n      return new Range(anchor, head);\n    } else {\n      return new Range(other || head, head);\n    }\n  }\n\n  // Extend the primary selection range, discard the rest.\n  function extendSelection(doc, head, other, options) {\n    setSelection(doc, new Selection([extendRange(doc, doc.sel.primary(), head, other)], 0), options);\n  }\n\n  // Extend all selections (pos is an array of selections with length\n  // equal the number of selections)\n  function extendSelections(doc, heads, options) {\n    for (var out = [], i = 0; i < doc.sel.ranges.length; i++)\n      out[i] = extendRange(doc, doc.sel.ranges[i], heads[i], null);\n    var newSel = normalizeSelection(out, doc.sel.primIndex);\n    setSelection(doc, newSel, options);\n  }\n\n  // Updates a single range in the selection.\n  function replaceOneSelection(doc, i, range, options) {\n    var ranges = doc.sel.ranges.slice(0);\n    ranges[i] = range;\n    setSelection(doc, normalizeSelection(ranges, doc.sel.primIndex), options);\n  }\n\n  // Reset the selection to a single range.\n  function setSimpleSelection(doc, anchor, head, options) {\n    setSelection(doc, simpleSelection(anchor, head), options);\n  }\n\n  // Give beforeSelectionChange handlers a change to influence a\n  // selection update.\n  function filterSelectionChange(doc, sel, options) {\n    var obj = {\n      ranges: sel.ranges,\n      update: function(ranges) {\n        this.ranges = [];\n        for (var i = 0; i < ranges.length; i++)\n          this.ranges[i] = new Range(clipPos(doc, ranges[i].anchor),\n                                     clipPos(doc, ranges[i].head));\n      },\n      origin: options && options.origin\n    };\n    signal(doc, \"beforeSelectionChange\", doc, obj);\n    if (doc.cm) signal(doc.cm, \"beforeSelectionChange\", doc.cm, obj);\n    if (obj.ranges != sel.ranges) return normalizeSelection(obj.ranges, obj.ranges.length - 1);\n    else return sel;\n  }\n\n  function setSelectionReplaceHistory(doc, sel, options) {\n    var done = doc.history.done, last = lst(done);\n    if (last && last.ranges) {\n      done[done.length - 1] = sel;\n      setSelectionNoUndo(doc, sel, options);\n    } else {\n      setSelection(doc, sel, options);\n    }\n  }\n\n  // Set a new selection.\n  function setSelection(doc, sel, options) {\n    setSelectionNoUndo(doc, sel, options);\n    addSelectionToHistory(doc, doc.sel, doc.cm ? doc.cm.curOp.id : NaN, options);\n  }\n\n  function setSelectionNoUndo(doc, sel, options) {\n    if (hasHandler(doc, \"beforeSelectionChange\") || doc.cm && hasHandler(doc.cm, \"beforeSelectionChange\"))\n      sel = filterSelectionChange(doc, sel, options);\n\n    var bias = options && options.bias ||\n      (cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1);\n    setSelectionInner(doc, skipAtomicInSelection(doc, sel, bias, true));\n\n    if (!(options && options.scroll === false) && doc.cm)\n      ensureCursorVisible(doc.cm);\n  }\n\n  function setSelectionInner(doc, sel) {\n    if (sel.equals(doc.sel)) return;\n\n    doc.sel = sel;\n\n    if (doc.cm) {\n      doc.cm.curOp.updateInput = doc.cm.curOp.selectionChanged = true;\n      signalCursorActivity(doc.cm);\n    }\n    signalLater(doc, \"cursorActivity\", doc);\n  }\n\n  // Verify that the selection does not partially select any atomic\n  // marked ranges.\n  function reCheckSelection(doc) {\n    setSelectionInner(doc, skipAtomicInSelection(doc, doc.sel, null, false), sel_dontScroll);\n  }\n\n  // Return a selection that does not partially select any atomic\n  // ranges.\n  function skipAtomicInSelection(doc, sel, bias, mayClear) {\n    var out;\n    for (var i = 0; i < sel.ranges.length; i++) {\n      var range = sel.ranges[i];\n      var old = sel.ranges.length == doc.sel.ranges.length && doc.sel.ranges[i];\n      var newAnchor = skipAtomic(doc, range.anchor, old && old.anchor, bias, mayClear);\n      var newHead = skipAtomic(doc, range.head, old && old.head, bias, mayClear);\n      if (out || newAnchor != range.anchor || newHead != range.head) {\n        if (!out) out = sel.ranges.slice(0, i);\n        out[i] = new Range(newAnchor, newHead);\n      }\n    }\n    return out ? normalizeSelection(out, sel.primIndex) : sel;\n  }\n\n  function skipAtomicInner(doc, pos, oldPos, dir, mayClear) {\n    var line = getLine(doc, pos.line);\n    if (line.markedSpans) for (var i = 0; i < line.markedSpans.length; ++i) {\n      var sp = line.markedSpans[i], m = sp.marker;\n      if ((sp.from == null || (m.inclusiveLeft ? sp.from <= pos.ch : sp.from < pos.ch)) &&\n          (sp.to == null || (m.inclusiveRight ? sp.to >= pos.ch : sp.to > pos.ch))) {\n        if (mayClear) {\n          signal(m, \"beforeCursorEnter\");\n          if (m.explicitlyCleared) {\n            if (!line.markedSpans) break;\n            else {--i; continue;}\n          }\n        }\n        if (!m.atomic) continue;\n\n        if (oldPos) {\n          var near = m.find(dir < 0 ? 1 : -1), diff;\n          if (dir < 0 ? m.inclusiveRight : m.inclusiveLeft)\n            near = movePos(doc, near, -dir, near && near.line == pos.line ? line : null);\n          if (near && near.line == pos.line && (diff = cmp(near, oldPos)) && (dir < 0 ? diff < 0 : diff > 0))\n            return skipAtomicInner(doc, near, pos, dir, mayClear);\n        }\n\n        var far = m.find(dir < 0 ? -1 : 1);\n        if (dir < 0 ? m.inclusiveLeft : m.inclusiveRight)\n          far = movePos(doc, far, dir, far.line == pos.line ? line : null);\n        return far ? skipAtomicInner(doc, far, pos, dir, mayClear) : null;\n      }\n    }\n    return pos;\n  }\n\n  // Ensure a given position is not inside an atomic range.\n  function skipAtomic(doc, pos, oldPos, bias, mayClear) {\n    var dir = bias || 1;\n    var found = skipAtomicInner(doc, pos, oldPos, dir, mayClear) ||\n        (!mayClear && skipAtomicInner(doc, pos, oldPos, dir, true)) ||\n        skipAtomicInner(doc, pos, oldPos, -dir, mayClear) ||\n        (!mayClear && skipAtomicInner(doc, pos, oldPos, -dir, true));\n    if (!found) {\n      doc.cantEdit = true;\n      return Pos(doc.first, 0);\n    }\n    return found;\n  }\n\n  function movePos(doc, pos, dir, line) {\n    if (dir < 0 && pos.ch == 0) {\n      if (pos.line > doc.first) return clipPos(doc, Pos(pos.line - 1));\n      else return null;\n    } else if (dir > 0 && pos.ch == (line || getLine(doc, pos.line)).text.length) {\n      if (pos.line < doc.first + doc.size - 1) return Pos(pos.line + 1, 0);\n      else return null;\n    } else {\n      return new Pos(pos.line, pos.ch + dir);\n    }\n  }\n\n  // SELECTION DRAWING\n\n  function updateSelection(cm) {\n    cm.display.input.showSelection(cm.display.input.prepareSelection());\n  }\n\n  function prepareSelection(cm, primary) {\n    var doc = cm.doc, result = {};\n    var curFragment = result.cursors = document.createDocumentFragment();\n    var selFragment = result.selection = document.createDocumentFragment();\n\n    for (var i = 0; i < doc.sel.ranges.length; i++) {\n      if (primary === false && i == doc.sel.primIndex) continue;\n      var range = doc.sel.ranges[i];\n      if (range.from().line >= cm.display.viewTo || range.to().line < cm.display.viewFrom) continue;\n      var collapsed = range.empty();\n      if (collapsed || cm.options.showCursorWhenSelecting)\n        drawSelectionCursor(cm, range.head, curFragment);\n      if (!collapsed)\n        drawSelectionRange(cm, range, selFragment);\n    }\n    return result;\n  }\n\n  // Draws a cursor for the given range\n  function drawSelectionCursor(cm, head, output) {\n    var pos = cursorCoords(cm, head, \"div\", null, null, !cm.options.singleCursorHeightPerLine);\n\n    var cursor = output.appendChild(elt(\"div\", \"\\u00a0\", \"CodeMirror-cursor\"));\n    cursor.style.left = pos.left + \"px\";\n    cursor.style.top = pos.top + \"px\";\n    cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + \"px\";\n\n    if (pos.other) {\n      // Secondary cursor, shown when on a 'jump' in bi-directional text\n      var otherCursor = output.appendChild(elt(\"div\", \"\\u00a0\", \"CodeMirror-cursor CodeMirror-secondarycursor\"));\n      otherCursor.style.display = \"\";\n      otherCursor.style.left = pos.other.left + \"px\";\n      otherCursor.style.top = pos.other.top + \"px\";\n      otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + \"px\";\n    }\n  }\n\n  // Draws the given range as a highlighted selection\n  function drawSelectionRange(cm, range, output) {\n    var display = cm.display, doc = cm.doc;\n    var fragment = document.createDocumentFragment();\n    var padding = paddingH(cm.display), leftSide = padding.left;\n    var rightSide = Math.max(display.sizerWidth, displayWidth(cm) - display.sizer.offsetLeft) - padding.right;\n\n    function add(left, top, width, bottom) {\n      if (top < 0) top = 0;\n      top = Math.round(top);\n      bottom = Math.round(bottom);\n      fragment.appendChild(elt(\"div\", null, \"CodeMirror-selected\", \"position: absolute; left: \" + left +\n                               \"px; top: \" + top + \"px; width: \" + (width == null ? rightSide - left : width) +\n                               \"px; height: \" + (bottom - top) + \"px\"));\n    }\n\n    function drawForLine(line, fromArg, toArg) {\n      var lineObj = getLine(doc, line);\n      var lineLen = lineObj.text.length;\n      var start, end;\n      function coords(ch, bias) {\n        return charCoords(cm, Pos(line, ch), \"div\", lineObj, bias);\n      }\n\n      iterateBidiSections(getOrder(lineObj), fromArg || 0, toArg == null ? lineLen : toArg, function(from, to, dir) {\n        var leftPos = coords(from, \"left\"), rightPos, left, right;\n        if (from == to) {\n          rightPos = leftPos;\n          left = right = leftPos.left;\n        } else {\n          rightPos = coords(to - 1, \"right\");\n          if (dir == \"rtl\") { var tmp = leftPos; leftPos = rightPos; rightPos = tmp; }\n          left = leftPos.left;\n          right = rightPos.right;\n        }\n        if (fromArg == null && from == 0) left = leftSide;\n        if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part\n          add(left, leftPos.top, null, leftPos.bottom);\n          left = leftSide;\n          if (leftPos.bottom < rightPos.top) add(left, leftPos.bottom, null, rightPos.top);\n        }\n        if (toArg == null && to == lineLen) right = rightSide;\n        if (!start || leftPos.top < start.top || leftPos.top == start.top && leftPos.left < start.left)\n          start = leftPos;\n        if (!end || rightPos.bottom > end.bottom || rightPos.bottom == end.bottom && rightPos.right > end.right)\n          end = rightPos;\n        if (left < leftSide + 1) left = leftSide;\n        add(left, rightPos.top, right - left, rightPos.bottom);\n      });\n      return {start: start, end: end};\n    }\n\n    var sFrom = range.from(), sTo = range.to();\n    if (sFrom.line == sTo.line) {\n      drawForLine(sFrom.line, sFrom.ch, sTo.ch);\n    } else {\n      var fromLine = getLine(doc, sFrom.line), toLine = getLine(doc, sTo.line);\n      var singleVLine = visualLine(fromLine) == visualLine(toLine);\n      var leftEnd = drawForLine(sFrom.line, sFrom.ch, singleVLine ? fromLine.text.length + 1 : null).end;\n      var rightStart = drawForLine(sTo.line, singleVLine ? 0 : null, sTo.ch).start;\n      if (singleVLine) {\n        if (leftEnd.top < rightStart.top - 2) {\n          add(leftEnd.right, leftEnd.top, null, leftEnd.bottom);\n          add(leftSide, rightStart.top, rightStart.left, rightStart.bottom);\n        } else {\n          add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom);\n        }\n      }\n      if (leftEnd.bottom < rightStart.top)\n        add(leftSide, leftEnd.bottom, null, rightStart.top);\n    }\n\n    output.appendChild(fragment);\n  }\n\n  // Cursor-blinking\n  function restartBlink(cm) {\n    if (!cm.state.focused) return;\n    var display = cm.display;\n    clearInterval(display.blinker);\n    var on = true;\n    display.cursorDiv.style.visibility = \"\";\n    if (cm.options.cursorBlinkRate > 0)\n      display.blinker = setInterval(function() {\n        display.cursorDiv.style.visibility = (on = !on) ? \"\" : \"hidden\";\n      }, cm.options.cursorBlinkRate);\n    else if (cm.options.cursorBlinkRate < 0)\n      display.cursorDiv.style.visibility = \"hidden\";\n  }\n\n  // HIGHLIGHT WORKER\n\n  function startWorker(cm, time) {\n    if (cm.doc.mode.startState && cm.doc.frontier < cm.display.viewTo)\n      cm.state.highlight.set(time, bind(highlightWorker, cm));\n  }\n\n  function highlightWorker(cm) {\n    var doc = cm.doc;\n    if (doc.frontier < doc.first) doc.frontier = doc.first;\n    if (doc.frontier >= cm.display.viewTo) return;\n    var end = +new Date + cm.options.workTime;\n    var state = copyState(doc.mode, getStateBefore(cm, doc.frontier));\n    var changedLines = [];\n\n    doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.viewTo + 500), function(line) {\n      if (doc.frontier >= cm.display.viewFrom) { // Visible\n        var oldStyles = line.styles, tooLong = line.text.length > cm.options.maxHighlightLength;\n        var highlighted = highlightLine(cm, line, tooLong ? copyState(doc.mode, state) : state, true);\n        line.styles = highlighted.styles;\n        var oldCls = line.styleClasses, newCls = highlighted.classes;\n        if (newCls) line.styleClasses = newCls;\n        else if (oldCls) line.styleClasses = null;\n        var ischange = !oldStyles || oldStyles.length != line.styles.length ||\n          oldCls != newCls && (!oldCls || !newCls || oldCls.bgClass != newCls.bgClass || oldCls.textClass != newCls.textClass);\n        for (var i = 0; !ischange && i < oldStyles.length; ++i) ischange = oldStyles[i] != line.styles[i];\n        if (ischange) changedLines.push(doc.frontier);\n        line.stateAfter = tooLong ? state : copyState(doc.mode, state);\n      } else {\n        if (line.text.length <= cm.options.maxHighlightLength)\n          processLine(cm, line.text, state);\n        line.stateAfter = doc.frontier % 5 == 0 ? copyState(doc.mode, state) : null;\n      }\n      ++doc.frontier;\n      if (+new Date > end) {\n        startWorker(cm, cm.options.workDelay);\n        return true;\n      }\n    });\n    if (changedLines.length) runInOp(cm, function() {\n      for (var i = 0; i < changedLines.length; i++)\n        regLineChange(cm, changedLines[i], \"text\");\n    });\n  }\n\n  // Finds the line to start with when starting a parse. Tries to\n  // find a line with a stateAfter, so that it can start with a\n  // valid state. If that fails, it returns the line with the\n  // smallest indentation, which tends to need the least context to\n  // parse correctly.\n  function findStartLine(cm, n, precise) {\n    var minindent, minline, doc = cm.doc;\n    var lim = precise ? -1 : n - (cm.doc.mode.innerMode ? 1000 : 100);\n    for (var search = n; search > lim; --search) {\n      if (search <= doc.first) return doc.first;\n      var line = getLine(doc, search - 1);\n      if (line.stateAfter && (!precise || search <= doc.frontier)) return search;\n      var indented = countColumn(line.text, null, cm.options.tabSize);\n      if (minline == null || minindent > indented) {\n        minline = search - 1;\n        minindent = indented;\n      }\n    }\n    return minline;\n  }\n\n  function getStateBefore(cm, n, precise) {\n    var doc = cm.doc, display = cm.display;\n    if (!doc.mode.startState) return true;\n    var pos = findStartLine(cm, n, precise), state = pos > doc.first && getLine(doc, pos-1).stateAfter;\n    if (!state) state = startState(doc.mode);\n    else state = copyState(doc.mode, state);\n    doc.iter(pos, n, function(line) {\n      processLine(cm, line.text, state);\n      var save = pos == n - 1 || pos % 5 == 0 || pos >= display.viewFrom && pos < display.viewTo;\n      line.stateAfter = save ? copyState(doc.mode, state) : null;\n      ++pos;\n    });\n    if (precise) doc.frontier = pos;\n    return state;\n  }\n\n  // POSITION MEASUREMENT\n\n  function paddingTop(display) {return display.lineSpace.offsetTop;}\n  function paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight;}\n  function paddingH(display) {\n    if (display.cachedPaddingH) return display.cachedPaddingH;\n    var e = removeChildrenAndAdd(display.measure, elt(\"pre\", \"x\"));\n    var style = window.getComputedStyle ? window.getComputedStyle(e) : e.currentStyle;\n    var data = {left: parseInt(style.paddingLeft), right: parseInt(style.paddingRight)};\n    if (!isNaN(data.left) && !isNaN(data.right)) display.cachedPaddingH = data;\n    return data;\n  }\n\n  function scrollGap(cm) { return scrollerGap - cm.display.nativeBarWidth; }\n  function displayWidth(cm) {\n    return cm.display.scroller.clientWidth - scrollGap(cm) - cm.display.barWidth;\n  }\n  function displayHeight(cm) {\n    return cm.display.scroller.clientHeight - scrollGap(cm) - cm.display.barHeight;\n  }\n\n  // Ensure the lineView.wrapping.heights array is populated. This is\n  // an array of bottom offsets for the lines that make up a drawn\n  // line. When lineWrapping is on, there might be more than one\n  // height.\n  function ensureLineHeights(cm, lineView, rect) {\n    var wrapping = cm.options.lineWrapping;\n    var curWidth = wrapping && displayWidth(cm);\n    if (!lineView.measure.heights || wrapping && lineView.measure.width != curWidth) {\n      var heights = lineView.measure.heights = [];\n      if (wrapping) {\n        lineView.measure.width = curWidth;\n        var rects = lineView.text.firstChild.getClientRects();\n        for (var i = 0; i < rects.length - 1; i++) {\n          var cur = rects[i], next = rects[i + 1];\n          if (Math.abs(cur.bottom - next.bottom) > 2)\n            heights.push((cur.bottom + next.top) / 2 - rect.top);\n        }\n      }\n      heights.push(rect.bottom - rect.top);\n    }\n  }\n\n  // Find a line map (mapping character offsets to text nodes) and a\n  // measurement cache for the given line number. (A line view might\n  // contain multiple lines when collapsed ranges are present.)\n  function mapFromLineView(lineView, line, lineN) {\n    if (lineView.line == line)\n      return {map: lineView.measure.map, cache: lineView.measure.cache};\n    for (var i = 0; i < lineView.rest.length; i++)\n      if (lineView.rest[i] == line)\n        return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i]};\n    for (var i = 0; i < lineView.rest.length; i++)\n      if (lineNo(lineView.rest[i]) > lineN)\n        return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i], before: true};\n  }\n\n  // Render a line into the hidden node display.externalMeasured. Used\n  // when measurement is needed for a line that's not in the viewport.\n  function updateExternalMeasurement(cm, line) {\n    line = visualLine(line);\n    var lineN = lineNo(line);\n    var view = cm.display.externalMeasured = new LineView(cm.doc, line, lineN);\n    view.lineN = lineN;\n    var built = view.built = buildLineContent(cm, view);\n    view.text = built.pre;\n    removeChildrenAndAdd(cm.display.lineMeasure, built.pre);\n    return view;\n  }\n\n  // Get a {top, bottom, left, right} box (in line-local coordinates)\n  // for a given character.\n  function measureChar(cm, line, ch, bias) {\n    return measureCharPrepared(cm, prepareMeasureForLine(cm, line), ch, bias);\n  }\n\n  // Find a line view that corresponds to the given line number.\n  function findViewForLine(cm, lineN) {\n    if (lineN >= cm.display.viewFrom && lineN < cm.display.viewTo)\n      return cm.display.view[findViewIndex(cm, lineN)];\n    var ext = cm.display.externalMeasured;\n    if (ext && lineN >= ext.lineN && lineN < ext.lineN + ext.size)\n      return ext;\n  }\n\n  // Measurement can be split in two steps, the set-up work that\n  // applies to the whole line, and the measurement of the actual\n  // character. Functions like coordsChar, that need to do a lot of\n  // measurements in a row, can thus ensure that the set-up work is\n  // only done once.\n  function prepareMeasureForLine(cm, line) {\n    var lineN = lineNo(line);\n    var view = findViewForLine(cm, lineN);\n    if (view && !view.text) {\n      view = null;\n    } else if (view && view.changes) {\n      updateLineForChanges(cm, view, lineN, getDimensions(cm));\n      cm.curOp.forceUpdate = true;\n    }\n    if (!view)\n      view = updateExternalMeasurement(cm, line);\n\n    var info = mapFromLineView(view, line, lineN);\n    return {\n      line: line, view: view, rect: null,\n      map: info.map, cache: info.cache, before: info.before,\n      hasHeights: false\n    };\n  }\n\n  // Given a prepared measurement object, measures the position of an\n  // actual character (or fetches it from the cache).\n  function measureCharPrepared(cm, prepared, ch, bias, varHeight) {\n    if (prepared.before) ch = -1;\n    var key = ch + (bias || \"\"), found;\n    if (prepared.cache.hasOwnProperty(key)) {\n      found = prepared.cache[key];\n    } else {\n      if (!prepared.rect)\n        prepared.rect = prepared.view.text.getBoundingClientRect();\n      if (!prepared.hasHeights) {\n        ensureLineHeights(cm, prepared.view, prepared.rect);\n        prepared.hasHeights = true;\n      }\n      found = measureCharInner(cm, prepared, ch, bias);\n      if (!found.bogus) prepared.cache[key] = found;\n    }\n    return {left: found.left, right: found.right,\n            top: varHeight ? found.rtop : found.top,\n            bottom: varHeight ? found.rbottom : found.bottom};\n  }\n\n  var nullRect = {left: 0, right: 0, top: 0, bottom: 0};\n\n  function nodeAndOffsetInLineMap(map, ch, bias) {\n    var node, start, end, collapse;\n    // First, search the line map for the text node corresponding to,\n    // or closest to, the target character.\n    for (var i = 0; i < map.length; i += 3) {\n      var mStart = map[i], mEnd = map[i + 1];\n      if (ch < mStart) {\n        start = 0; end = 1;\n        collapse = \"left\";\n      } else if (ch < mEnd) {\n        start = ch - mStart;\n        end = start + 1;\n      } else if (i == map.length - 3 || ch == mEnd && map[i + 3] > ch) {\n        end = mEnd - mStart;\n        start = end - 1;\n        if (ch >= mEnd) collapse = \"right\";\n      }\n      if (start != null) {\n        node = map[i + 2];\n        if (mStart == mEnd && bias == (node.insertLeft ? \"left\" : \"right\"))\n          collapse = bias;\n        if (bias == \"left\" && start == 0)\n          while (i && map[i - 2] == map[i - 3] && map[i - 1].insertLeft) {\n            node = map[(i -= 3) + 2];\n            collapse = \"left\";\n          }\n        if (bias == \"right\" && start == mEnd - mStart)\n          while (i < map.length - 3 && map[i + 3] == map[i + 4] && !map[i + 5].insertLeft) {\n            node = map[(i += 3) + 2];\n            collapse = \"right\";\n          }\n        break;\n      }\n    }\n    return {node: node, start: start, end: end, collapse: collapse, coverStart: mStart, coverEnd: mEnd};\n  }\n\n  function measureCharInner(cm, prepared, ch, bias) {\n    var place = nodeAndOffsetInLineMap(prepared.map, ch, bias);\n    var node = place.node, start = place.start, end = place.end, collapse = place.collapse;\n\n    var rect;\n    if (node.nodeType == 3) { // If it is a text node, use a range to retrieve the coordinates.\n      for (var i = 0; i < 4; i++) { // Retry a maximum of 4 times when nonsense rectangles are returned\n        while (start && isExtendingChar(prepared.line.text.charAt(place.coverStart + start))) --start;\n        while (place.coverStart + end < place.coverEnd && isExtendingChar(prepared.line.text.charAt(place.coverStart + end))) ++end;\n        if (ie && ie_version < 9 && start == 0 && end == place.coverEnd - place.coverStart) {\n          rect = node.parentNode.getBoundingClientRect();\n        } else if (ie && cm.options.lineWrapping) {\n          var rects = range(node, start, end).getClientRects();\n          if (rects.length)\n            rect = rects[bias == \"right\" ? rects.length - 1 : 0];\n          else\n            rect = nullRect;\n        } else {\n          rect = range(node, start, end).getBoundingClientRect() || nullRect;\n        }\n        if (rect.left || rect.right || start == 0) break;\n        end = start;\n        start = start - 1;\n        collapse = \"right\";\n      }\n      if (ie && ie_version < 11) rect = maybeUpdateRectForZooming(cm.display.measure, rect);\n    } else { // If it is a widget, simply get the box for the whole widget.\n      if (start > 0) collapse = bias = \"right\";\n      var rects;\n      if (cm.options.lineWrapping && (rects = node.getClientRects()).length > 1)\n        rect = rects[bias == \"right\" ? rects.length - 1 : 0];\n      else\n        rect = node.getBoundingClientRect();\n    }\n    if (ie && ie_version < 9 && !start && (!rect || !rect.left && !rect.right)) {\n      var rSpan = node.parentNode.getClientRects()[0];\n      if (rSpan)\n        rect = {left: rSpan.left, right: rSpan.left + charWidth(cm.display), top: rSpan.top, bottom: rSpan.bottom};\n      else\n        rect = nullRect;\n    }\n\n    var rtop = rect.top - prepared.rect.top, rbot = rect.bottom - prepared.rect.top;\n    var mid = (rtop + rbot) / 2;\n    var heights = prepared.view.measure.heights;\n    for (var i = 0; i < heights.length - 1; i++)\n      if (mid < heights[i]) break;\n    var top = i ? heights[i - 1] : 0, bot = heights[i];\n    var result = {left: (collapse == \"right\" ? rect.right : rect.left) - prepared.rect.left,\n                  right: (collapse == \"left\" ? rect.left : rect.right) - prepared.rect.left,\n                  top: top, bottom: bot};\n    if (!rect.left && !rect.right) result.bogus = true;\n    if (!cm.options.singleCursorHeightPerLine) { result.rtop = rtop; result.rbottom = rbot; }\n\n    return result;\n  }\n\n  // Work around problem with bounding client rects on ranges being\n  // returned incorrectly when zoomed on IE10 and below.\n  function maybeUpdateRectForZooming(measure, rect) {\n    if (!window.screen || screen.logicalXDPI == null ||\n        screen.logicalXDPI == screen.deviceXDPI || !hasBadZoomedRects(measure))\n      return rect;\n    var scaleX = screen.logicalXDPI / screen.deviceXDPI;\n    var scaleY = screen.logicalYDPI / screen.deviceYDPI;\n    return {left: rect.left * scaleX, right: rect.right * scaleX,\n            top: rect.top * scaleY, bottom: rect.bottom * scaleY};\n  }\n\n  function clearLineMeasurementCacheFor(lineView) {\n    if (lineView.measure) {\n      lineView.measure.cache = {};\n      lineView.measure.heights = null;\n      if (lineView.rest) for (var i = 0; i < lineView.rest.length; i++)\n        lineView.measure.caches[i] = {};\n    }\n  }\n\n  function clearLineMeasurementCache(cm) {\n    cm.display.externalMeasure = null;\n    removeChildren(cm.display.lineMeasure);\n    for (var i = 0; i < cm.display.view.length; i++)\n      clearLineMeasurementCacheFor(cm.display.view[i]);\n  }\n\n  function clearCaches(cm) {\n    clearLineMeasurementCache(cm);\n    cm.display.cachedCharWidth = cm.display.cachedTextHeight = cm.display.cachedPaddingH = null;\n    if (!cm.options.lineWrapping) cm.display.maxLineChanged = true;\n    cm.display.lineNumChars = null;\n  }\n\n  function pageScrollX() { return window.pageXOffset || (document.documentElement || document.body).scrollLeft; }\n  function pageScrollY() { return window.pageYOffset || (document.documentElement || document.body).scrollTop; }\n\n  // Converts a {top, bottom, left, right} box from line-local\n  // coordinates into another coordinate system. Context may be one of\n  // \"line\", \"div\" (display.lineDiv), \"local\"/null (editor), \"window\",\n  // or \"page\".\n  function intoCoordSystem(cm, lineObj, rect, context) {\n    if (lineObj.widgets) for (var i = 0; i < lineObj.widgets.length; ++i) if (lineObj.widgets[i].above) {\n      var size = widgetHeight(lineObj.widgets[i]);\n      rect.top += size; rect.bottom += size;\n    }\n    if (context == \"line\") return rect;\n    if (!context) context = \"local\";\n    var yOff = heightAtLine(lineObj);\n    if (context == \"local\") yOff += paddingTop(cm.display);\n    else yOff -= cm.display.viewOffset;\n    if (context == \"page\" || context == \"window\") {\n      var lOff = cm.display.lineSpace.getBoundingClientRect();\n      yOff += lOff.top + (context == \"window\" ? 0 : pageScrollY());\n      var xOff = lOff.left + (context == \"window\" ? 0 : pageScrollX());\n      rect.left += xOff; rect.right += xOff;\n    }\n    rect.top += yOff; rect.bottom += yOff;\n    return rect;\n  }\n\n  // Coverts a box from \"div\" coords to another coordinate system.\n  // Context may be \"window\", \"page\", \"div\", or \"local\"/null.\n  function fromCoordSystem(cm, coords, context) {\n    if (context == \"div\") return coords;\n    var left = coords.left, top = coords.top;\n    // First move into \"page\" coordinate system\n    if (context == \"page\") {\n      left -= pageScrollX();\n      top -= pageScrollY();\n    } else if (context == \"local\" || !context) {\n      var localBox = cm.display.sizer.getBoundingClientRect();\n      left += localBox.left;\n      top += localBox.top;\n    }\n\n    var lineSpaceBox = cm.display.lineSpace.getBoundingClientRect();\n    return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top};\n  }\n\n  function charCoords(cm, pos, context, lineObj, bias) {\n    if (!lineObj) lineObj = getLine(cm.doc, pos.line);\n    return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, bias), context);\n  }\n\n  // Returns a box for a given cursor position, which may have an\n  // 'other' property containing the position of the secondary cursor\n  // on a bidi boundary.\n  function cursorCoords(cm, pos, context, lineObj, preparedMeasure, varHeight) {\n    lineObj = lineObj || getLine(cm.doc, pos.line);\n    if (!preparedMeasure) preparedMeasure = prepareMeasureForLine(cm, lineObj);\n    function get(ch, right) {\n      var m = measureCharPrepared(cm, preparedMeasure, ch, right ? \"right\" : \"left\", varHeight);\n      if (right) m.left = m.right; else m.right = m.left;\n      return intoCoordSystem(cm, lineObj, m, context);\n    }\n    function getBidi(ch, partPos) {\n      var part = order[partPos], right = part.level % 2;\n      if (ch == bidiLeft(part) && partPos && part.level < order[partPos - 1].level) {\n        part = order[--partPos];\n        ch = bidiRight(part) - (part.level % 2 ? 0 : 1);\n        right = true;\n      } else if (ch == bidiRight(part) && partPos < order.length - 1 && part.level < order[partPos + 1].level) {\n        part = order[++partPos];\n        ch = bidiLeft(part) - part.level % 2;\n        right = false;\n      }\n      if (right && ch == part.to && ch > part.from) return get(ch - 1);\n      return get(ch, right);\n    }\n    var order = getOrder(lineObj), ch = pos.ch;\n    if (!order) return get(ch);\n    var partPos = getBidiPartAt(order, ch);\n    var val = getBidi(ch, partPos);\n    if (bidiOther != null) val.other = getBidi(ch, bidiOther);\n    return val;\n  }\n\n  // Used to cheaply estimate the coordinates for a position. Used for\n  // intermediate scroll updates.\n  function estimateCoords(cm, pos) {\n    var left = 0, pos = clipPos(cm.doc, pos);\n    if (!cm.options.lineWrapping) left = charWidth(cm.display) * pos.ch;\n    var lineObj = getLine(cm.doc, pos.line);\n    var top = heightAtLine(lineObj) + paddingTop(cm.display);\n    return {left: left, right: left, top: top, bottom: top + lineObj.height};\n  }\n\n  // Positions returned by coordsChar contain some extra information.\n  // xRel is the relative x position of the input coordinates compared\n  // to the found position (so xRel > 0 means the coordinates are to\n  // the right of the character position, for example). When outside\n  // is true, that means the coordinates lie outside the line's\n  // vertical range.\n  function PosWithInfo(line, ch, outside, xRel) {\n    var pos = Pos(line, ch);\n    pos.xRel = xRel;\n    if (outside) pos.outside = true;\n    return pos;\n  }\n\n  // Compute the character position closest to the given coordinates.\n  // Input must be lineSpace-local (\"div\" coordinate system).\n  function coordsChar(cm, x, y) {\n    var doc = cm.doc;\n    y += cm.display.viewOffset;\n    if (y < 0) return PosWithInfo(doc.first, 0, true, -1);\n    var lineN = lineAtHeight(doc, y), last = doc.first + doc.size - 1;\n    if (lineN > last)\n      return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, true, 1);\n    if (x < 0) x = 0;\n\n    var lineObj = getLine(doc, lineN);\n    for (;;) {\n      var found = coordsCharInner(cm, lineObj, lineN, x, y);\n      var merged = collapsedSpanAtEnd(lineObj);\n      var mergedPos = merged && merged.find(0, true);\n      if (merged && (found.ch > mergedPos.from.ch || found.ch == mergedPos.from.ch && found.xRel > 0))\n        lineN = lineNo(lineObj = mergedPos.to.line);\n      else\n        return found;\n    }\n  }\n\n  function coordsCharInner(cm, lineObj, lineNo, x, y) {\n    var innerOff = y - heightAtLine(lineObj);\n    var wrongLine = false, adjust = 2 * cm.display.wrapper.clientWidth;\n    var preparedMeasure = prepareMeasureForLine(cm, lineObj);\n\n    function getX(ch) {\n      var sp = cursorCoords(cm, Pos(lineNo, ch), \"line\", lineObj, preparedMeasure);\n      wrongLine = true;\n      if (innerOff > sp.bottom) return sp.left - adjust;\n      else if (innerOff < sp.top) return sp.left + adjust;\n      else wrongLine = false;\n      return sp.left;\n    }\n\n    var bidi = getOrder(lineObj), dist = lineObj.text.length;\n    var from = lineLeft(lineObj), to = lineRight(lineObj);\n    var fromX = getX(from), fromOutside = wrongLine, toX = getX(to), toOutside = wrongLine;\n\n    if (x > toX) return PosWithInfo(lineNo, to, toOutside, 1);\n    // Do a binary search between these bounds.\n    for (;;) {\n      if (bidi ? to == from || to == moveVisually(lineObj, from, 1) : to - from <= 1) {\n        var ch = x < fromX || x - fromX <= toX - x ? from : to;\n        var xDiff = x - (ch == from ? fromX : toX);\n        while (isExtendingChar(lineObj.text.charAt(ch))) ++ch;\n        var pos = PosWithInfo(lineNo, ch, ch == from ? fromOutside : toOutside,\n                              xDiff < -1 ? -1 : xDiff > 1 ? 1 : 0);\n        return pos;\n      }\n      var step = Math.ceil(dist / 2), middle = from + step;\n      if (bidi) {\n        middle = from;\n        for (var i = 0; i < step; ++i) middle = moveVisually(lineObj, middle, 1);\n      }\n      var middleX = getX(middle);\n      if (middleX > x) {to = middle; toX = middleX; if (toOutside = wrongLine) toX += 1000; dist = step;}\n      else {from = middle; fromX = middleX; fromOutside = wrongLine; dist -= step;}\n    }\n  }\n\n  var measureText;\n  // Compute the default text height.\n  function textHeight(display) {\n    if (display.cachedTextHeight != null) return display.cachedTextHeight;\n    if (measureText == null) {\n      measureText = elt(\"pre\");\n      // Measure a bunch of lines, for browsers that compute\n      // fractional heights.\n      for (var i = 0; i < 49; ++i) {\n        measureText.appendChild(document.createTextNode(\"x\"));\n        measureText.appendChild(elt(\"br\"));\n      }\n      measureText.appendChild(document.createTextNode(\"x\"));\n    }\n    removeChildrenAndAdd(display.measure, measureText);\n    var height = measureText.offsetHeight / 50;\n    if (height > 3) display.cachedTextHeight = height;\n    removeChildren(display.measure);\n    return height || 1;\n  }\n\n  // Compute the default character width.\n  function charWidth(display) {\n    if (display.cachedCharWidth != null) return display.cachedCharWidth;\n    var anchor = elt(\"span\", \"xxxxxxxxxx\");\n    var pre = elt(\"pre\", [anchor]);\n    removeChildrenAndAdd(display.measure, pre);\n    var rect = anchor.getBoundingClientRect(), width = (rect.right - rect.left) / 10;\n    if (width > 2) display.cachedCharWidth = width;\n    return width || 10;\n  }\n\n  // OPERATIONS\n\n  // Operations are used to wrap a series of changes to the editor\n  // state in such a way that each change won't have to update the\n  // cursor and display (which would be awkward, slow, and\n  // error-prone). Instead, display updates are batched and then all\n  // combined and executed at once.\n\n  var operationGroup = null;\n\n  var nextOpId = 0;\n  // Start a new operation.\n  function startOperation(cm) {\n    cm.curOp = {\n      cm: cm,\n      viewChanged: false,      // Flag that indicates that lines might need to be redrawn\n      startHeight: cm.doc.height, // Used to detect need to update scrollbar\n      forceUpdate: false,      // Used to force a redraw\n      updateInput: null,       // Whether to reset the input textarea\n      typing: false,           // Whether this reset should be careful to leave existing text (for compositing)\n      changeObjs: null,        // Accumulated changes, for firing change events\n      cursorActivityHandlers: null, // Set of handlers to fire cursorActivity on\n      cursorActivityCalled: 0, // Tracks which cursorActivity handlers have been called already\n      selectionChanged: false, // Whether the selection needs to be redrawn\n      updateMaxLine: false,    // Set when the widest line needs to be determined anew\n      scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet\n      scrollToPos: null,       // Used to scroll to a specific position\n      focus: false,\n      id: ++nextOpId           // Unique ID\n    };\n    if (operationGroup) {\n      operationGroup.ops.push(cm.curOp);\n    } else {\n      cm.curOp.ownsGroup = operationGroup = {\n        ops: [cm.curOp],\n        delayedCallbacks: []\n      };\n    }\n  }\n\n  function fireCallbacksForOps(group) {\n    // Calls delayed callbacks and cursorActivity handlers until no\n    // new ones appear\n    var callbacks = group.delayedCallbacks, i = 0;\n    do {\n      for (; i < callbacks.length; i++)\n        callbacks[i].call(null);\n      for (var j = 0; j < group.ops.length; j++) {\n        var op = group.ops[j];\n        if (op.cursorActivityHandlers)\n          while (op.cursorActivityCalled < op.cursorActivityHandlers.length)\n            op.cursorActivityHandlers[op.cursorActivityCalled++].call(null, op.cm);\n      }\n    } while (i < callbacks.length);\n  }\n\n  // Finish an operation, updating the display and signalling delayed events\n  function endOperation(cm) {\n    var op = cm.curOp, group = op.ownsGroup;\n    if (!group) return;\n\n    try { fireCallbacksForOps(group); }\n    finally {\n      operationGroup = null;\n      for (var i = 0; i < group.ops.length; i++)\n        group.ops[i].cm.curOp = null;\n      endOperations(group);\n    }\n  }\n\n  // The DOM updates done when an operation finishes are batched so\n  // that the minimum number of relayouts are required.\n  function endOperations(group) {\n    var ops = group.ops;\n    for (var i = 0; i < ops.length; i++) // Read DOM\n      endOperation_R1(ops[i]);\n    for (var i = 0; i < ops.length; i++) // Write DOM (maybe)\n      endOperation_W1(ops[i]);\n    for (var i = 0; i < ops.length; i++) // Read DOM\n      endOperation_R2(ops[i]);\n    for (var i = 0; i < ops.length; i++) // Write DOM (maybe)\n      endOperation_W2(ops[i]);\n    for (var i = 0; i < ops.length; i++) // Read DOM\n      endOperation_finish(ops[i]);\n  }\n\n  function endOperation_R1(op) {\n    var cm = op.cm, display = cm.display;\n    maybeClipScrollbars(cm);\n    if (op.updateMaxLine) findMaxLine(cm);\n\n    op.mustUpdate = op.viewChanged || op.forceUpdate || op.scrollTop != null ||\n      op.scrollToPos && (op.scrollToPos.from.line < display.viewFrom ||\n                         op.scrollToPos.to.line >= display.viewTo) ||\n      display.maxLineChanged && cm.options.lineWrapping;\n    op.update = op.mustUpdate &&\n      new DisplayUpdate(cm, op.mustUpdate && {top: op.scrollTop, ensure: op.scrollToPos}, op.forceUpdate);\n  }\n\n  function endOperation_W1(op) {\n    op.updatedDisplay = op.mustUpdate && updateDisplayIfNeeded(op.cm, op.update);\n  }\n\n  function endOperation_R2(op) {\n    var cm = op.cm, display = cm.display;\n    if (op.updatedDisplay) updateHeightsInViewport(cm);\n\n    op.barMeasure = measureForScrollbars(cm);\n\n    // If the max line changed since it was last measured, measure it,\n    // and ensure the document's width matches it.\n    // updateDisplay_W2 will use these properties to do the actual resizing\n    if (display.maxLineChanged && !cm.options.lineWrapping) {\n      op.adjustWidthTo = measureChar(cm, display.maxLine, display.maxLine.text.length).left + 3;\n      cm.display.sizerWidth = op.adjustWidthTo;\n      op.barMeasure.scrollWidth =\n        Math.max(display.scroller.clientWidth, display.sizer.offsetLeft + op.adjustWidthTo + scrollGap(cm) + cm.display.barWidth);\n      op.maxScrollLeft = Math.max(0, display.sizer.offsetLeft + op.adjustWidthTo - displayWidth(cm));\n    }\n\n    if (op.updatedDisplay || op.selectionChanged)\n      op.preparedSelection = display.input.prepareSelection();\n  }\n\n  function endOperation_W2(op) {\n    var cm = op.cm;\n\n    if (op.adjustWidthTo != null) {\n      cm.display.sizer.style.minWidth = op.adjustWidthTo + \"px\";\n      if (op.maxScrollLeft < cm.doc.scrollLeft)\n        setScrollLeft(cm, Math.min(cm.display.scroller.scrollLeft, op.maxScrollLeft), true);\n      cm.display.maxLineChanged = false;\n    }\n\n    if (op.preparedSelection)\n      cm.display.input.showSelection(op.preparedSelection);\n    if (op.updatedDisplay || op.startHeight != cm.doc.height)\n      updateScrollbars(cm, op.barMeasure);\n    if (op.updatedDisplay)\n      setDocumentHeight(cm, op.barMeasure);\n\n    if (op.selectionChanged) restartBlink(cm);\n\n    if (cm.state.focused && op.updateInput)\n      cm.display.input.reset(op.typing);\n    if (op.focus && op.focus == activeElt() && (!document.hasFocus || document.hasFocus()))\n      ensureFocus(op.cm);\n  }\n\n  function endOperation_finish(op) {\n    var cm = op.cm, display = cm.display, doc = cm.doc;\n\n    if (op.updatedDisplay) postUpdateDisplay(cm, op.update);\n\n    // Abort mouse wheel delta measurement, when scrolling explicitly\n    if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos))\n      display.wheelStartX = display.wheelStartY = null;\n\n    // Propagate the scroll position to the actual DOM scroller\n    if (op.scrollTop != null && (display.scroller.scrollTop != op.scrollTop || op.forceScroll)) {\n      doc.scrollTop = Math.max(0, Math.min(display.scroller.scrollHeight - display.scroller.clientHeight, op.scrollTop));\n      display.scrollbars.setScrollTop(doc.scrollTop);\n      display.scroller.scrollTop = doc.scrollTop;\n    }\n    if (op.scrollLeft != null && (display.scroller.scrollLeft != op.scrollLeft || op.forceScroll)) {\n      doc.scrollLeft = Math.max(0, Math.min(display.scroller.scrollWidth - display.scroller.clientWidth, op.scrollLeft));\n      display.scrollbars.setScrollLeft(doc.scrollLeft);\n      display.scroller.scrollLeft = doc.scrollLeft;\n      alignHorizontally(cm);\n    }\n    // If we need to scroll a specific position into view, do so.\n    if (op.scrollToPos) {\n      var coords = scrollPosIntoView(cm, clipPos(doc, op.scrollToPos.from),\n                                     clipPos(doc, op.scrollToPos.to), op.scrollToPos.margin);\n      if (op.scrollToPos.isCursor && cm.state.focused) maybeScrollWindow(cm, coords);\n    }\n\n    // Fire events for markers that are hidden/unidden by editing or\n    // undoing\n    var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers;\n    if (hidden) for (var i = 0; i < hidden.length; ++i)\n      if (!hidden[i].lines.length) signal(hidden[i], \"hide\");\n    if (unhidden) for (var i = 0; i < unhidden.length; ++i)\n      if (unhidden[i].lines.length) signal(unhidden[i], \"unhide\");\n\n    if (display.wrapper.offsetHeight)\n      doc.scrollTop = cm.display.scroller.scrollTop;\n\n    // Fire change events, and delayed event handlers\n    if (op.changeObjs)\n      signal(cm, \"changes\", cm, op.changeObjs);\n    if (op.update)\n      op.update.finish();\n  }\n\n  // Run the given function in an operation\n  function runInOp(cm, f) {\n    if (cm.curOp) return f();\n    startOperation(cm);\n    try { return f(); }\n    finally { endOperation(cm); }\n  }\n  // Wraps a function in an operation. Returns the wrapped function.\n  function operation(cm, f) {\n    return function() {\n      if (cm.curOp) return f.apply(cm, arguments);\n      startOperation(cm);\n      try { return f.apply(cm, arguments); }\n      finally { endOperation(cm); }\n    };\n  }\n  // Used to add methods to editor and doc instances, wrapping them in\n  // operations.\n  function methodOp(f) {\n    return function() {\n      if (this.curOp) return f.apply(this, arguments);\n      startOperation(this);\n      try { return f.apply(this, arguments); }\n      finally { endOperation(this); }\n    };\n  }\n  function docMethodOp(f) {\n    return function() {\n      var cm = this.cm;\n      if (!cm || cm.curOp) return f.apply(this, arguments);\n      startOperation(cm);\n      try { return f.apply(this, arguments); }\n      finally { endOperation(cm); }\n    };\n  }\n\n  // VIEW TRACKING\n\n  // These objects are used to represent the visible (currently drawn)\n  // part of the document. A LineView may correspond to multiple\n  // logical lines, if those are connected by collapsed ranges.\n  function LineView(doc, line, lineN) {\n    // The starting line\n    this.line = line;\n    // Continuing lines, if any\n    this.rest = visualLineContinued(line);\n    // Number of logical lines in this visual line\n    this.size = this.rest ? lineNo(lst(this.rest)) - lineN + 1 : 1;\n    this.node = this.text = null;\n    this.hidden = lineIsHidden(doc, line);\n  }\n\n  // Create a range of LineView objects for the given lines.\n  function buildViewArray(cm, from, to) {\n    var array = [], nextPos;\n    for (var pos = from; pos < to; pos = nextPos) {\n      var view = new LineView(cm.doc, getLine(cm.doc, pos), pos);\n      nextPos = pos + view.size;\n      array.push(view);\n    }\n    return array;\n  }\n\n  // Updates the display.view data structure for a given change to the\n  // document. From and to are in pre-change coordinates. Lendiff is\n  // the amount of lines added or subtracted by the change. This is\n  // used for changes that span multiple lines, or change the way\n  // lines are divided into visual lines. regLineChange (below)\n  // registers single-line changes.\n  function regChange(cm, from, to, lendiff) {\n    if (from == null) from = cm.doc.first;\n    if (to == null) to = cm.doc.first + cm.doc.size;\n    if (!lendiff) lendiff = 0;\n\n    var display = cm.display;\n    if (lendiff && to < display.viewTo &&\n        (display.updateLineNumbers == null || display.updateLineNumbers > from))\n      display.updateLineNumbers = from;\n\n    cm.curOp.viewChanged = true;\n\n    if (from >= display.viewTo) { // Change after\n      if (sawCollapsedSpans && visualLineNo(cm.doc, from) < display.viewTo)\n        resetView(cm);\n    } else if (to <= display.viewFrom) { // Change before\n      if (sawCollapsedSpans && visualLineEndNo(cm.doc, to + lendiff) > display.viewFrom) {\n        resetView(cm);\n      } else {\n        display.viewFrom += lendiff;\n        display.viewTo += lendiff;\n      }\n    } else if (from <= display.viewFrom && to >= display.viewTo) { // Full overlap\n      resetView(cm);\n    } else if (from <= display.viewFrom) { // Top overlap\n      var cut = viewCuttingPoint(cm, to, to + lendiff, 1);\n      if (cut) {\n        display.view = display.view.slice(cut.index);\n        display.viewFrom = cut.lineN;\n        display.viewTo += lendiff;\n      } else {\n        resetView(cm);\n      }\n    } else if (to >= display.viewTo) { // Bottom overlap\n      var cut = viewCuttingPoint(cm, from, from, -1);\n      if (cut) {\n        display.view = display.view.slice(0, cut.index);\n        display.viewTo = cut.lineN;\n      } else {\n        resetView(cm);\n      }\n    } else { // Gap in the middle\n      var cutTop = viewCuttingPoint(cm, from, from, -1);\n      var cutBot = viewCuttingPoint(cm, to, to + lendiff, 1);\n      if (cutTop && cutBot) {\n        display.view = display.view.slice(0, cutTop.index)\n          .concat(buildViewArray(cm, cutTop.lineN, cutBot.lineN))\n          .concat(display.view.slice(cutBot.index));\n        display.viewTo += lendiff;\n      } else {\n        resetView(cm);\n      }\n    }\n\n    var ext = display.externalMeasured;\n    if (ext) {\n      if (to < ext.lineN)\n        ext.lineN += lendiff;\n      else if (from < ext.lineN + ext.size)\n        display.externalMeasured = null;\n    }\n  }\n\n  // Register a change to a single line. Type must be one of \"text\",\n  // \"gutter\", \"class\", \"widget\"\n  function regLineChange(cm, line, type) {\n    cm.curOp.viewChanged = true;\n    var display = cm.display, ext = cm.display.externalMeasured;\n    if (ext && line >= ext.lineN && line < ext.lineN + ext.size)\n      display.externalMeasured = null;\n\n    if (line < display.viewFrom || line >= display.viewTo) return;\n    var lineView = display.view[findViewIndex(cm, line)];\n    if (lineView.node == null) return;\n    var arr = lineView.changes || (lineView.changes = []);\n    if (indexOf(arr, type) == -1) arr.push(type);\n  }\n\n  // Clear the view.\n  function resetView(cm) {\n    cm.display.viewFrom = cm.display.viewTo = cm.doc.first;\n    cm.display.view = [];\n    cm.display.viewOffset = 0;\n  }\n\n  // Find the view element corresponding to a given line. Return null\n  // when the line isn't visible.\n  function findViewIndex(cm, n) {\n    if (n >= cm.display.viewTo) return null;\n    n -= cm.display.viewFrom;\n    if (n < 0) return null;\n    var view = cm.display.view;\n    for (var i = 0; i < view.length; i++) {\n      n -= view[i].size;\n      if (n < 0) return i;\n    }\n  }\n\n  function viewCuttingPoint(cm, oldN, newN, dir) {\n    var index = findViewIndex(cm, oldN), diff, view = cm.display.view;\n    if (!sawCollapsedSpans || newN == cm.doc.first + cm.doc.size)\n      return {index: index, lineN: newN};\n    for (var i = 0, n = cm.display.viewFrom; i < index; i++)\n      n += view[i].size;\n    if (n != oldN) {\n      if (dir > 0) {\n        if (index == view.length - 1) return null;\n        diff = (n + view[index].size) - oldN;\n        index++;\n      } else {\n        diff = n - oldN;\n      }\n      oldN += diff; newN += diff;\n    }\n    while (visualLineNo(cm.doc, newN) != newN) {\n      if (index == (dir < 0 ? 0 : view.length - 1)) return null;\n      newN += dir * view[index - (dir < 0 ? 1 : 0)].size;\n      index += dir;\n    }\n    return {index: index, lineN: newN};\n  }\n\n  // Force the view to cover a given range, adding empty view element\n  // or clipping off existing ones as needed.\n  function adjustView(cm, from, to) {\n    var display = cm.display, view = display.view;\n    if (view.length == 0 || from >= display.viewTo || to <= display.viewFrom) {\n      display.view = buildViewArray(cm, from, to);\n      display.viewFrom = from;\n    } else {\n      if (display.viewFrom > from)\n        display.view = buildViewArray(cm, from, display.viewFrom).concat(display.view);\n      else if (display.viewFrom < from)\n        display.view = display.view.slice(findViewIndex(cm, from));\n      display.viewFrom = from;\n      if (display.viewTo < to)\n        display.view = display.view.concat(buildViewArray(cm, display.viewTo, to));\n      else if (display.viewTo > to)\n        display.view = display.view.slice(0, findViewIndex(cm, to));\n    }\n    display.viewTo = to;\n  }\n\n  // Count the number of lines in the view whose DOM representation is\n  // out of date (or nonexistent).\n  function countDirtyView(cm) {\n    var view = cm.display.view, dirty = 0;\n    for (var i = 0; i < view.length; i++) {\n      var lineView = view[i];\n      if (!lineView.hidden && (!lineView.node || lineView.changes)) ++dirty;\n    }\n    return dirty;\n  }\n\n  // EVENT HANDLERS\n\n  // Attach the necessary event handlers when initializing the editor\n  function registerEventHandlers(cm) {\n    var d = cm.display;\n    on(d.scroller, \"mousedown\", operation(cm, onMouseDown));\n    // Older IE's will not fire a second mousedown for a double click\n    if (ie && ie_version < 11)\n      on(d.scroller, \"dblclick\", operation(cm, function(e) {\n        if (signalDOMEvent(cm, e)) return;\n        var pos = posFromMouse(cm, e);\n        if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) return;\n        e_preventDefault(e);\n        var word = cm.findWordAt(pos);\n        extendSelection(cm.doc, word.anchor, word.head);\n      }));\n    else\n      on(d.scroller, \"dblclick\", function(e) { signalDOMEvent(cm, e) || e_preventDefault(e); });\n    // Some browsers fire contextmenu *after* opening the menu, at\n    // which point we can't mess with it anymore. Context menu is\n    // handled in onMouseDown for these browsers.\n    if (!captureRightClick) on(d.scroller, \"contextmenu\", function(e) {onContextMenu(cm, e);});\n\n    // Used to suppress mouse event handling when a touch happens\n    var touchFinished, prevTouch = {end: 0};\n    function finishTouch() {\n      if (d.activeTouch) {\n        touchFinished = setTimeout(function() {d.activeTouch = null;}, 1000);\n        prevTouch = d.activeTouch;\n        prevTouch.end = +new Date;\n      }\n    };\n    function isMouseLikeTouchEvent(e) {\n      if (e.touches.length != 1) return false;\n      var touch = e.touches[0];\n      return touch.radiusX <= 1 && touch.radiusY <= 1;\n    }\n    function farAway(touch, other) {\n      if (other.left == null) return true;\n      var dx = other.left - touch.left, dy = other.top - touch.top;\n      return dx * dx + dy * dy > 20 * 20;\n    }\n    on(d.scroller, \"touchstart\", function(e) {\n      if (!signalDOMEvent(cm, e) && !isMouseLikeTouchEvent(e)) {\n        clearTimeout(touchFinished);\n        var now = +new Date;\n        d.activeTouch = {start: now, moved: false,\n                         prev: now - prevTouch.end <= 300 ? prevTouch : null};\n        if (e.touches.length == 1) {\n          d.activeTouch.left = e.touches[0].pageX;\n          d.activeTouch.top = e.touches[0].pageY;\n        }\n      }\n    });\n    on(d.scroller, \"touchmove\", function() {\n      if (d.activeTouch) d.activeTouch.moved = true;\n    });\n    on(d.scroller, \"touchend\", function(e) {\n      var touch = d.activeTouch;\n      if (touch && !eventInWidget(d, e) && touch.left != null &&\n          !touch.moved && new Date - touch.start < 300) {\n        var pos = cm.coordsChar(d.activeTouch, \"page\"), range;\n        if (!touch.prev || farAway(touch, touch.prev)) // Single tap\n          range = new Range(pos, pos);\n        else if (!touch.prev.prev || farAway(touch, touch.prev.prev)) // Double tap\n          range = cm.findWordAt(pos);\n        else // Triple tap\n          range = new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0)));\n        cm.setSelection(range.anchor, range.head);\n        cm.focus();\n        e_preventDefault(e);\n      }\n      finishTouch();\n    });\n    on(d.scroller, \"touchcancel\", finishTouch);\n\n    // Sync scrolling between fake scrollbars and real scrollable\n    // area, ensure viewport is updated when scrolling.\n    on(d.scroller, \"scroll\", function() {\n      if (d.scroller.clientHeight) {\n        setScrollTop(cm, d.scroller.scrollTop);\n        setScrollLeft(cm, d.scroller.scrollLeft, true);\n        signal(cm, \"scroll\", cm);\n      }\n    });\n\n    // Listen to wheel events in order to try and update the viewport on time.\n    on(d.scroller, \"mousewheel\", function(e){onScrollWheel(cm, e);});\n    on(d.scroller, \"DOMMouseScroll\", function(e){onScrollWheel(cm, e);});\n\n    // Prevent wrapper from ever scrolling\n    on(d.wrapper, \"scroll\", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; });\n\n    d.dragFunctions = {\n      enter: function(e) {if (!signalDOMEvent(cm, e)) e_stop(e);},\n      over: function(e) {if (!signalDOMEvent(cm, e)) { onDragOver(cm, e); e_stop(e); }},\n      start: function(e){onDragStart(cm, e);},\n      drop: operation(cm, onDrop),\n      leave: function(e) {if (!signalDOMEvent(cm, e)) { clearDragCursor(cm); }}\n    };\n\n    var inp = d.input.getField();\n    on(inp, \"keyup\", function(e) { onKeyUp.call(cm, e); });\n    on(inp, \"keydown\", operation(cm, onKeyDown));\n    on(inp, \"keypress\", operation(cm, onKeyPress));\n    on(inp, \"focus\", bind(onFocus, cm));\n    on(inp, \"blur\", bind(onBlur, cm));\n  }\n\n  function dragDropChanged(cm, value, old) {\n    var wasOn = old && old != CodeMirror.Init;\n    if (!value != !wasOn) {\n      var funcs = cm.display.dragFunctions;\n      var toggle = value ? on : off;\n      toggle(cm.display.scroller, \"dragstart\", funcs.start);\n      toggle(cm.display.scroller, \"dragenter\", funcs.enter);\n      toggle(cm.display.scroller, \"dragover\", funcs.over);\n      toggle(cm.display.scroller, \"dragleave\", funcs.leave);\n      toggle(cm.display.scroller, \"drop\", funcs.drop);\n    }\n  }\n\n  // Called when the window resizes\n  function onResize(cm) {\n    var d = cm.display;\n    if (d.lastWrapHeight == d.wrapper.clientHeight && d.lastWrapWidth == d.wrapper.clientWidth)\n      return;\n    // Might be a text scaling operation, clear size caches.\n    d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null;\n    d.scrollbarsClipped = false;\n    cm.setSize();\n  }\n\n  // MOUSE EVENTS\n\n  // Return true when the given mouse event happened in a widget\n  function eventInWidget(display, e) {\n    for (var n = e_target(e); n != display.wrapper; n = n.parentNode) {\n      if (!n || (n.nodeType == 1 && n.getAttribute(\"cm-ignore-events\") == \"true\") ||\n          (n.parentNode == display.sizer && n != display.mover))\n        return true;\n    }\n  }\n\n  // Given a mouse event, find the corresponding position. If liberal\n  // is false, it checks whether a gutter or scrollbar was clicked,\n  // and returns null if it was. forRect is used by rectangular\n  // selections, and tries to estimate a character position even for\n  // coordinates beyond the right of the text.\n  function posFromMouse(cm, e, liberal, forRect) {\n    var display = cm.display;\n    if (!liberal && e_target(e).getAttribute(\"cm-not-content\") == \"true\") return null;\n\n    var x, y, space = display.lineSpace.getBoundingClientRect();\n    // Fails unpredictably on IE[67] when mouse is dragged around quickly.\n    try { x = e.clientX - space.left; y = e.clientY - space.top; }\n    catch (e) { return null; }\n    var coords = coordsChar(cm, x, y), line;\n    if (forRect && coords.xRel == 1 && (line = getLine(cm.doc, coords.line).text).length == coords.ch) {\n      var colDiff = countColumn(line, line.length, cm.options.tabSize) - line.length;\n      coords = Pos(coords.line, Math.max(0, Math.round((x - paddingH(cm.display).left) / charWidth(cm.display)) - colDiff));\n    }\n    return coords;\n  }\n\n  // A mouse down can be a single click, double click, triple click,\n  // start of selection drag, start of text drag, new cursor\n  // (ctrl-click), rectangle drag (alt-drag), or xwin\n  // middle-click-paste. Or it might be a click on something we should\n  // not interfere with, such as a scrollbar or widget.\n  function onMouseDown(e) {\n    var cm = this, display = cm.display;\n    if (signalDOMEvent(cm, e) || display.activeTouch && display.input.supportsTouch()) return;\n    display.shift = e.shiftKey;\n\n    if (eventInWidget(display, e)) {\n      if (!webkit) {\n        // Briefly turn off draggability, to allow widgets to do\n        // normal dragging things.\n        display.scroller.draggable = false;\n        setTimeout(function(){display.scroller.draggable = true;}, 100);\n      }\n      return;\n    }\n    if (clickInGutter(cm, e)) return;\n    var start = posFromMouse(cm, e);\n    window.focus();\n\n    switch (e_button(e)) {\n    case 1:\n      // #3261: make sure, that we're not starting a second selection\n      if (cm.state.selectingText)\n        cm.state.selectingText(e);\n      else if (start)\n        leftButtonDown(cm, e, start);\n      else if (e_target(e) == display.scroller)\n        e_preventDefault(e);\n      break;\n    case 2:\n      if (webkit) cm.state.lastMiddleDown = +new Date;\n      if (start) extendSelection(cm.doc, start);\n      setTimeout(function() {display.input.focus();}, 20);\n      e_preventDefault(e);\n      break;\n    case 3:\n      if (captureRightClick) onContextMenu(cm, e);\n      else delayBlurEvent(cm);\n      break;\n    }\n  }\n\n  var lastClick, lastDoubleClick;\n  function leftButtonDown(cm, e, start) {\n    if (ie) setTimeout(bind(ensureFocus, cm), 0);\n    else cm.curOp.focus = activeElt();\n\n    var now = +new Date, type;\n    if (lastDoubleClick && lastDoubleClick.time > now - 400 && cmp(lastDoubleClick.pos, start) == 0) {\n      type = \"triple\";\n    } else if (lastClick && lastClick.time > now - 400 && cmp(lastClick.pos, start) == 0) {\n      type = \"double\";\n      lastDoubleClick = {time: now, pos: start};\n    } else {\n      type = \"single\";\n      lastClick = {time: now, pos: start};\n    }\n\n    var sel = cm.doc.sel, modifier = mac ? e.metaKey : e.ctrlKey, contained;\n    if (cm.options.dragDrop && dragAndDrop && !cm.isReadOnly() &&\n        type == \"single\" && (contained = sel.contains(start)) > -1 &&\n        (cmp((contained = sel.ranges[contained]).from(), start) < 0 || start.xRel > 0) &&\n        (cmp(contained.to(), start) > 0 || start.xRel < 0))\n      leftButtonStartDrag(cm, e, start, modifier);\n    else\n      leftButtonSelect(cm, e, start, type, modifier);\n  }\n\n  // Start a text drag. When it ends, see if any dragging actually\n  // happen, and treat as a click if it didn't.\n  function leftButtonStartDrag(cm, e, start, modifier) {\n    var display = cm.display, startTime = +new Date;\n    var dragEnd = operation(cm, function(e2) {\n      if (webkit) display.scroller.draggable = false;\n      cm.state.draggingText = false;\n      off(document, \"mouseup\", dragEnd);\n      off(display.scroller, \"drop\", dragEnd);\n      if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {\n        e_preventDefault(e2);\n        if (!modifier && +new Date - 200 < startTime)\n          extendSelection(cm.doc, start);\n        // Work around unexplainable focus problem in IE9 (#2127) and Chrome (#3081)\n        if (webkit || ie && ie_version == 9)\n          setTimeout(function() {document.body.focus(); display.input.focus();}, 20);\n        else\n          display.input.focus();\n      }\n    });\n    // Let the drag handler handle this.\n    if (webkit) display.scroller.draggable = true;\n    cm.state.draggingText = dragEnd;\n    // IE's approach to draggable\n    if (display.scroller.dragDrop) display.scroller.dragDrop();\n    on(document, \"mouseup\", dragEnd);\n    on(display.scroller, \"drop\", dragEnd);\n  }\n\n  // Normal selection, as opposed to text dragging.\n  function leftButtonSelect(cm, e, start, type, addNew) {\n    var display = cm.display, doc = cm.doc;\n    e_preventDefault(e);\n\n    var ourRange, ourIndex, startSel = doc.sel, ranges = startSel.ranges;\n    if (addNew && !e.shiftKey) {\n      ourIndex = doc.sel.contains(start);\n      if (ourIndex > -1)\n        ourRange = ranges[ourIndex];\n      else\n        ourRange = new Range(start, start);\n    } else {\n      ourRange = doc.sel.primary();\n      ourIndex = doc.sel.primIndex;\n    }\n\n    if (e.altKey) {\n      type = \"rect\";\n      if (!addNew) ourRange = new Range(start, start);\n      start = posFromMouse(cm, e, true, true);\n      ourIndex = -1;\n    } else if (type == \"double\") {\n      var word = cm.findWordAt(start);\n      if (cm.display.shift || doc.extend)\n        ourRange = extendRange(doc, ourRange, word.anchor, word.head);\n      else\n        ourRange = word;\n    } else if (type == \"triple\") {\n      var line = new Range(Pos(start.line, 0), clipPos(doc, Pos(start.line + 1, 0)));\n      if (cm.display.shift || doc.extend)\n        ourRange = extendRange(doc, ourRange, line.anchor, line.head);\n      else\n        ourRange = line;\n    } else {\n      ourRange = extendRange(doc, ourRange, start);\n    }\n\n    if (!addNew) {\n      ourIndex = 0;\n      setSelection(doc, new Selection([ourRange], 0), sel_mouse);\n      startSel = doc.sel;\n    } else if (ourIndex == -1) {\n      ourIndex = ranges.length;\n      setSelection(doc, normalizeSelection(ranges.concat([ourRange]), ourIndex),\n                   {scroll: false, origin: \"*mouse\"});\n    } else if (ranges.length > 1 && ranges[ourIndex].empty() && type == \"single\" && !e.shiftKey) {\n      setSelection(doc, normalizeSelection(ranges.slice(0, ourIndex).concat(ranges.slice(ourIndex + 1)), 0),\n                   {scroll: false, origin: \"*mouse\"});\n      startSel = doc.sel;\n    } else {\n      replaceOneSelection(doc, ourIndex, ourRange, sel_mouse);\n    }\n\n    var lastPos = start;\n    function extendTo(pos) {\n      if (cmp(lastPos, pos) == 0) return;\n      lastPos = pos;\n\n      if (type == \"rect\") {\n        var ranges = [], tabSize = cm.options.tabSize;\n        var startCol = countColumn(getLine(doc, start.line).text, start.ch, tabSize);\n        var posCol = countColumn(getLine(doc, pos.line).text, pos.ch, tabSize);\n        var left = Math.min(startCol, posCol), right = Math.max(startCol, posCol);\n        for (var line = Math.min(start.line, pos.line), end = Math.min(cm.lastLine(), Math.max(start.line, pos.line));\n             line <= end; line++) {\n          var text = getLine(doc, line).text, leftPos = findColumn(text, left, tabSize);\n          if (left == right)\n            ranges.push(new Range(Pos(line, leftPos), Pos(line, leftPos)));\n          else if (text.length > leftPos)\n            ranges.push(new Range(Pos(line, leftPos), Pos(line, findColumn(text, right, tabSize))));\n        }\n        if (!ranges.length) ranges.push(new Range(start, start));\n        setSelection(doc, normalizeSelection(startSel.ranges.slice(0, ourIndex).concat(ranges), ourIndex),\n                     {origin: \"*mouse\", scroll: false});\n        cm.scrollIntoView(pos);\n      } else {\n        var oldRange = ourRange;\n        var anchor = oldRange.anchor, head = pos;\n        if (type != \"single\") {\n          if (type == \"double\")\n            var range = cm.findWordAt(pos);\n          else\n            var range = new Range(Pos(pos.line, 0), clipPos(doc, Pos(pos.line + 1, 0)));\n          if (cmp(range.anchor, anchor) > 0) {\n            head = range.head;\n            anchor = minPos(oldRange.from(), range.anchor);\n          } else {\n            head = range.anchor;\n            anchor = maxPos(oldRange.to(), range.head);\n          }\n        }\n        var ranges = startSel.ranges.slice(0);\n        ranges[ourIndex] = new Range(clipPos(doc, anchor), head);\n        setSelection(doc, normalizeSelection(ranges, ourIndex), sel_mouse);\n      }\n    }\n\n    var editorSize = display.wrapper.getBoundingClientRect();\n    // Used to ensure timeout re-tries don't fire when another extend\n    // happened in the meantime (clearTimeout isn't reliable -- at\n    // least on Chrome, the timeouts still happen even when cleared,\n    // if the clear happens after their scheduled firing time).\n    var counter = 0;\n\n    function extend(e) {\n      var curCount = ++counter;\n      var cur = posFromMouse(cm, e, true, type == \"rect\");\n      if (!cur) return;\n      if (cmp(cur, lastPos) != 0) {\n        cm.curOp.focus = activeElt();\n        extendTo(cur);\n        var visible = visibleLines(display, doc);\n        if (cur.line >= visible.to || cur.line < visible.from)\n          setTimeout(operation(cm, function(){if (counter == curCount) extend(e);}), 150);\n      } else {\n        var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0;\n        if (outside) setTimeout(operation(cm, function() {\n          if (counter != curCount) return;\n          display.scroller.scrollTop += outside;\n          extend(e);\n        }), 50);\n      }\n    }\n\n    function done(e) {\n      cm.state.selectingText = false;\n      counter = Infinity;\n      e_preventDefault(e);\n      display.input.focus();\n      off(document, \"mousemove\", move);\n      off(document, \"mouseup\", up);\n      doc.history.lastSelOrigin = null;\n    }\n\n    var move = operation(cm, function(e) {\n      if (!e_button(e)) done(e);\n      else extend(e);\n    });\n    var up = operation(cm, done);\n    cm.state.selectingText = up;\n    on(document, \"mousemove\", move);\n    on(document, \"mouseup\", up);\n  }\n\n  // Determines whether an event happened in the gutter, and fires the\n  // handlers for the corresponding event.\n  function gutterEvent(cm, e, type, prevent) {\n    try { var mX = e.clientX, mY = e.clientY; }\n    catch(e) { return false; }\n    if (mX >= Math.floor(cm.display.gutters.getBoundingClientRect().right)) return false;\n    if (prevent) e_preventDefault(e);\n\n    var display = cm.display;\n    var lineBox = display.lineDiv.getBoundingClientRect();\n\n    if (mY > lineBox.bottom || !hasHandler(cm, type)) return e_defaultPrevented(e);\n    mY -= lineBox.top - display.viewOffset;\n\n    for (var i = 0; i < cm.options.gutters.length; ++i) {\n      var g = display.gutters.childNodes[i];\n      if (g && g.getBoundingClientRect().right >= mX) {\n        var line = lineAtHeight(cm.doc, mY);\n        var gutter = cm.options.gutters[i];\n        signal(cm, type, cm, line, gutter, e);\n        return e_defaultPrevented(e);\n      }\n    }\n  }\n\n  function clickInGutter(cm, e) {\n    return gutterEvent(cm, e, \"gutterClick\", true);\n  }\n\n  // Kludge to work around strange IE behavior where it'll sometimes\n  // re-fire a series of drag-related events right after the drop (#1551)\n  var lastDrop = 0;\n\n  function onDrop(e) {\n    var cm = this;\n    clearDragCursor(cm);\n    if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e))\n      return;\n    e_preventDefault(e);\n    if (ie) lastDrop = +new Date;\n    var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files;\n    if (!pos || cm.isReadOnly()) return;\n    // Might be a file drop, in which case we simply extract the text\n    // and insert it.\n    if (files && files.length && window.FileReader && window.File) {\n      var n = files.length, text = Array(n), read = 0;\n      var loadFile = function(file, i) {\n        if (cm.options.allowDropFileTypes &&\n            indexOf(cm.options.allowDropFileTypes, file.type) == -1)\n          return;\n\n        var reader = new FileReader;\n        reader.onload = operation(cm, function() {\n          var content = reader.result;\n          if (/[\\x00-\\x08\\x0e-\\x1f]{2}/.test(content)) content = \"\";\n          text[i] = content;\n          if (++read == n) {\n            pos = clipPos(cm.doc, pos);\n            var change = {from: pos, to: pos,\n                          text: cm.doc.splitLines(text.join(cm.doc.lineSeparator())),\n                          origin: \"paste\"};\n            makeChange(cm.doc, change);\n            setSelectionReplaceHistory(cm.doc, simpleSelection(pos, changeEnd(change)));\n          }\n        });\n        reader.readAsText(file);\n      };\n      for (var i = 0; i < n; ++i) loadFile(files[i], i);\n    } else { // Normal drop\n      // Don't do a replace if the drop happened inside of the selected text.\n      if (cm.state.draggingText && cm.doc.sel.contains(pos) > -1) {\n        cm.state.draggingText(e);\n        // Ensure the editor is re-focused\n        setTimeout(function() {cm.display.input.focus();}, 20);\n        return;\n      }\n      try {\n        var text = e.dataTransfer.getData(\"Text\");\n        if (text) {\n          if (cm.state.draggingText && !(mac ? e.altKey : e.ctrlKey))\n            var selected = cm.listSelections();\n          setSelectionNoUndo(cm.doc, simpleSelection(pos, pos));\n          if (selected) for (var i = 0; i < selected.length; ++i)\n            replaceRange(cm.doc, \"\", selected[i].anchor, selected[i].head, \"drag\");\n          cm.replaceSelection(text, \"around\", \"paste\");\n          cm.display.input.focus();\n        }\n      }\n      catch(e){}\n    }\n  }\n\n  function onDragStart(cm, e) {\n    if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return; }\n    if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) return;\n\n    e.dataTransfer.setData(\"Text\", cm.getSelection());\n\n    // Use dummy image instead of default browsers image.\n    // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there.\n    if (e.dataTransfer.setDragImage && !safari) {\n      var img = elt(\"img\", null, null, \"position: fixed; left: 0; top: 0;\");\n      img.src = \"data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\";\n      if (presto) {\n        img.width = img.height = 1;\n        cm.display.wrapper.appendChild(img);\n        // Force a relayout, or Opera won't use our image for some obscure reason\n        img._top = img.offsetTop;\n      }\n      e.dataTransfer.setDragImage(img, 0, 0);\n      if (presto) img.parentNode.removeChild(img);\n    }\n  }\n\n  function onDragOver(cm, e) {\n    var pos = posFromMouse(cm, e);\n    if (!pos) return;\n    var frag = document.createDocumentFragment();\n    drawSelectionCursor(cm, pos, frag);\n    if (!cm.display.dragCursor) {\n      cm.display.dragCursor = elt(\"div\", null, \"CodeMirror-cursors CodeMirror-dragcursors\");\n      cm.display.lineSpace.insertBefore(cm.display.dragCursor, cm.display.cursorDiv);\n    }\n    removeChildrenAndAdd(cm.display.dragCursor, frag);\n  }\n\n  function clearDragCursor(cm) {\n    if (cm.display.dragCursor) {\n      cm.display.lineSpace.removeChild(cm.display.dragCursor);\n      cm.display.dragCursor = null;\n    }\n  }\n\n  // SCROLL EVENTS\n\n  // Sync the scrollable area and scrollbars, ensure the viewport\n  // covers the visible area.\n  function setScrollTop(cm, val) {\n    if (Math.abs(cm.doc.scrollTop - val) < 2) return;\n    cm.doc.scrollTop = val;\n    if (!gecko) updateDisplaySimple(cm, {top: val});\n    if (cm.display.scroller.scrollTop != val) cm.display.scroller.scrollTop = val;\n    cm.display.scrollbars.setScrollTop(val);\n    if (gecko) updateDisplaySimple(cm);\n    startWorker(cm, 100);\n  }\n  // Sync scroller and scrollbar, ensure the gutter elements are\n  // aligned.\n  function setScrollLeft(cm, val, isScroller) {\n    if (isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) return;\n    val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth);\n    cm.doc.scrollLeft = val;\n    alignHorizontally(cm);\n    if (cm.display.scroller.scrollLeft != val) cm.display.scroller.scrollLeft = val;\n    cm.display.scrollbars.setScrollLeft(val);\n  }\n\n  // Since the delta values reported on mouse wheel events are\n  // unstandardized between browsers and even browser versions, and\n  // generally horribly unpredictable, this code starts by measuring\n  // the scroll effect that the first few mouse wheel events have,\n  // and, from that, detects the way it can convert deltas to pixel\n  // offsets afterwards.\n  //\n  // The reason we want to know the amount a wheel event will scroll\n  // is that it gives us a chance to update the display before the\n  // actual scrolling happens, reducing flickering.\n\n  var wheelSamples = 0, wheelPixelsPerUnit = null;\n  // Fill in a browser-detected starting value on browsers where we\n  // know one. These don't have to be accurate -- the result of them\n  // being wrong would just be a slight flicker on the first wheel\n  // scroll (if it is large enough).\n  if (ie) wheelPixelsPerUnit = -.53;\n  else if (gecko) wheelPixelsPerUnit = 15;\n  else if (chrome) wheelPixelsPerUnit = -.7;\n  else if (safari) wheelPixelsPerUnit = -1/3;\n\n  var wheelEventDelta = function(e) {\n    var dx = e.wheelDeltaX, dy = e.wheelDeltaY;\n    if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) dx = e.detail;\n    if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) dy = e.detail;\n    else if (dy == null) dy = e.wheelDelta;\n    return {x: dx, y: dy};\n  };\n  CodeMirror.wheelEventPixels = function(e) {\n    var delta = wheelEventDelta(e);\n    delta.x *= wheelPixelsPerUnit;\n    delta.y *= wheelPixelsPerUnit;\n    return delta;\n  };\n\n  function onScrollWheel(cm, e) {\n    var delta = wheelEventDelta(e), dx = delta.x, dy = delta.y;\n\n    var display = cm.display, scroll = display.scroller;\n    // Quit if there's nothing to scroll here\n    var canScrollX = scroll.scrollWidth > scroll.clientWidth;\n    var canScrollY = scroll.scrollHeight > scroll.clientHeight;\n    if (!(dx && canScrollX || dy && canScrollY)) return;\n\n    // Webkit browsers on OS X abort momentum scrolls when the target\n    // of the scroll event is removed from the scrollable element.\n    // This hack (see related code in patchDisplay) makes sure the\n    // element is kept around.\n    if (dy && mac && webkit) {\n      outer: for (var cur = e.target, view = display.view; cur != scroll; cur = cur.parentNode) {\n        for (var i = 0; i < view.length; i++) {\n          if (view[i].node == cur) {\n            cm.display.currentWheelTarget = cur;\n            break outer;\n          }\n        }\n      }\n    }\n\n    // On some browsers, horizontal scrolling will cause redraws to\n    // happen before the gutter has been realigned, causing it to\n    // wriggle around in a most unseemly way. When we have an\n    // estimated pixels/delta value, we just handle horizontal\n    // scrolling entirely here. It'll be slightly off from native, but\n    // better than glitching out.\n    if (dx && !gecko && !presto && wheelPixelsPerUnit != null) {\n      if (dy && canScrollY)\n        setScrollTop(cm, Math.max(0, Math.min(scroll.scrollTop + dy * wheelPixelsPerUnit, scroll.scrollHeight - scroll.clientHeight)));\n      setScrollLeft(cm, Math.max(0, Math.min(scroll.scrollLeft + dx * wheelPixelsPerUnit, scroll.scrollWidth - scroll.clientWidth)));\n      // Only prevent default scrolling if vertical scrolling is\n      // actually possible. Otherwise, it causes vertical scroll\n      // jitter on OSX trackpads when deltaX is small and deltaY\n      // is large (issue #3579)\n      if (!dy || (dy && canScrollY))\n        e_preventDefault(e);\n      display.wheelStartX = null; // Abort measurement, if in progress\n      return;\n    }\n\n    // 'Project' the visible viewport to cover the area that is being\n    // scrolled into view (if we know enough to estimate it).\n    if (dy && wheelPixelsPerUnit != null) {\n      var pixels = dy * wheelPixelsPerUnit;\n      var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight;\n      if (pixels < 0) top = Math.max(0, top + pixels - 50);\n      else bot = Math.min(cm.doc.height, bot + pixels + 50);\n      updateDisplaySimple(cm, {top: top, bottom: bot});\n    }\n\n    if (wheelSamples < 20) {\n      if (display.wheelStartX == null) {\n        display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop;\n        display.wheelDX = dx; display.wheelDY = dy;\n        setTimeout(function() {\n          if (display.wheelStartX == null) return;\n          var movedX = scroll.scrollLeft - display.wheelStartX;\n          var movedY = scroll.scrollTop - display.wheelStartY;\n          var sample = (movedY && display.wheelDY && movedY / display.wheelDY) ||\n            (movedX && display.wheelDX && movedX / display.wheelDX);\n          display.wheelStartX = display.wheelStartY = null;\n          if (!sample) return;\n          wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1);\n          ++wheelSamples;\n        }, 200);\n      } else {\n        display.wheelDX += dx; display.wheelDY += dy;\n      }\n    }\n  }\n\n  // KEY EVENTS\n\n  // Run a handler that was bound to a key.\n  function doHandleBinding(cm, bound, dropShift) {\n    if (typeof bound == \"string\") {\n      bound = commands[bound];\n      if (!bound) return false;\n    }\n    // Ensure previous input has been read, so that the handler sees a\n    // consistent view of the document\n    cm.display.input.ensurePolled();\n    var prevShift = cm.display.shift, done = false;\n    try {\n      if (cm.isReadOnly()) cm.state.suppressEdits = true;\n      if (dropShift) cm.display.shift = false;\n      done = bound(cm) != Pass;\n    } finally {\n      cm.display.shift = prevShift;\n      cm.state.suppressEdits = false;\n    }\n    return done;\n  }\n\n  function lookupKeyForEditor(cm, name, handle) {\n    for (var i = 0; i < cm.state.keyMaps.length; i++) {\n      var result = lookupKey(name, cm.state.keyMaps[i], handle, cm);\n      if (result) return result;\n    }\n    return (cm.options.extraKeys && lookupKey(name, cm.options.extraKeys, handle, cm))\n      || lookupKey(name, cm.options.keyMap, handle, cm);\n  }\n\n  var stopSeq = new Delayed;\n  function dispatchKey(cm, name, e, handle) {\n    var seq = cm.state.keySeq;\n    if (seq) {\n      if (isModifierKey(name)) return \"handled\";\n      stopSeq.set(50, function() {\n        if (cm.state.keySeq == seq) {\n          cm.state.keySeq = null;\n          cm.display.input.reset();\n        }\n      });\n      name = seq + \" \" + name;\n    }\n    var result = lookupKeyForEditor(cm, name, handle);\n\n    if (result == \"multi\")\n      cm.state.keySeq = name;\n    if (result == \"handled\")\n      signalLater(cm, \"keyHandled\", cm, name, e);\n\n    if (result == \"handled\" || result == \"multi\") {\n      e_preventDefault(e);\n      restartBlink(cm);\n    }\n\n    if (seq && !result && /\\'$/.test(name)) {\n      e_preventDefault(e);\n      return true;\n    }\n    return !!result;\n  }\n\n  // Handle a key from the keydown event.\n  function handleKeyBinding(cm, e) {\n    var name = keyName(e, true);\n    if (!name) return false;\n\n    if (e.shiftKey && !cm.state.keySeq) {\n      // First try to resolve full name (including 'Shift-'). Failing\n      // that, see if there is a cursor-motion command (starting with\n      // 'go') bound to the keyname without 'Shift-'.\n      return dispatchKey(cm, \"Shift-\" + name, e, function(b) {return doHandleBinding(cm, b, true);})\n          || dispatchKey(cm, name, e, function(b) {\n               if (typeof b == \"string\" ? /^go[A-Z]/.test(b) : b.motion)\n                 return doHandleBinding(cm, b);\n             });\n    } else {\n      return dispatchKey(cm, name, e, function(b) { return doHandleBinding(cm, b); });\n    }\n  }\n\n  // Handle a key from the keypress event\n  function handleCharBinding(cm, e, ch) {\n    return dispatchKey(cm, \"'\" + ch + \"'\", e,\n                       function(b) { return doHandleBinding(cm, b, true); });\n  }\n\n  var lastStoppedKey = null;\n  function onKeyDown(e) {\n    var cm = this;\n    cm.curOp.focus = activeElt();\n    if (signalDOMEvent(cm, e)) return;\n    // IE does strange things with escape.\n    if (ie && ie_version < 11 && e.keyCode == 27) e.returnValue = false;\n    var code = e.keyCode;\n    cm.display.shift = code == 16 || e.shiftKey;\n    var handled = handleKeyBinding(cm, e);\n    if (presto) {\n      lastStoppedKey = handled ? code : null;\n      // Opera has no cut event... we try to at least catch the key combo\n      if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey))\n        cm.replaceSelection(\"\", null, \"cut\");\n    }\n\n    // Turn mouse into crosshair when Alt is held on Mac.\n    if (code == 18 && !/\\bCodeMirror-crosshair\\b/.test(cm.display.lineDiv.className))\n      showCrossHair(cm);\n  }\n\n  function showCrossHair(cm) {\n    var lineDiv = cm.display.lineDiv;\n    addClass(lineDiv, \"CodeMirror-crosshair\");\n\n    function up(e) {\n      if (e.keyCode == 18 || !e.altKey) {\n        rmClass(lineDiv, \"CodeMirror-crosshair\");\n        off(document, \"keyup\", up);\n        off(document, \"mouseover\", up);\n      }\n    }\n    on(document, \"keyup\", up);\n    on(document, \"mouseover\", up);\n  }\n\n  function onKeyUp(e) {\n    if (e.keyCode == 16) this.doc.sel.shift = false;\n    signalDOMEvent(this, e);\n  }\n\n  function onKeyPress(e) {\n    var cm = this;\n    if (eventInWidget(cm.display, e) || signalDOMEvent(cm, e) || e.ctrlKey && !e.altKey || mac && e.metaKey) return;\n    var keyCode = e.keyCode, charCode = e.charCode;\n    if (presto && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}\n    if ((presto && (!e.which || e.which < 10)) && handleKeyBinding(cm, e)) return;\n    var ch = String.fromCharCode(charCode == null ? keyCode : charCode);\n    if (handleCharBinding(cm, e, ch)) return;\n    cm.display.input.onKeyPress(e);\n  }\n\n  // FOCUS/BLUR EVENTS\n\n  function delayBlurEvent(cm) {\n    cm.state.delayingBlurEvent = true;\n    setTimeout(function() {\n      if (cm.state.delayingBlurEvent) {\n        cm.state.delayingBlurEvent = false;\n        onBlur(cm);\n      }\n    }, 100);\n  }\n\n  function onFocus(cm) {\n    if (cm.state.delayingBlurEvent) cm.state.delayingBlurEvent = false;\n\n    if (cm.options.readOnly == \"nocursor\") return;\n    if (!cm.state.focused) {\n      signal(cm, \"focus\", cm);\n      cm.state.focused = true;\n      addClass(cm.display.wrapper, \"CodeMirror-focused\");\n      // This test prevents this from firing when a context\n      // menu is closed (since the input reset would kill the\n      // select-all detection hack)\n      if (!cm.curOp && cm.display.selForContextMenu != cm.doc.sel) {\n        cm.display.input.reset();\n        if (webkit) setTimeout(function() { cm.display.input.reset(true); }, 20); // Issue #1730\n      }\n      cm.display.input.receivedFocus();\n    }\n    restartBlink(cm);\n  }\n  function onBlur(cm) {\n    if (cm.state.delayingBlurEvent) return;\n\n    if (cm.state.focused) {\n      signal(cm, \"blur\", cm);\n      cm.state.focused = false;\n      rmClass(cm.display.wrapper, \"CodeMirror-focused\");\n    }\n    clearInterval(cm.display.blinker);\n    setTimeout(function() {if (!cm.state.focused) cm.display.shift = false;}, 150);\n  }\n\n  // CONTEXT MENU HANDLING\n\n  // To make the context menu work, we need to briefly unhide the\n  // textarea (making it as unobtrusive as possible) to let the\n  // right-click take effect on it.\n  function onContextMenu(cm, e) {\n    if (eventInWidget(cm.display, e) || contextMenuInGutter(cm, e)) return;\n    if (signalDOMEvent(cm, e, \"contextmenu\")) return;\n    cm.display.input.onContextMenu(e);\n  }\n\n  function contextMenuInGutter(cm, e) {\n    if (!hasHandler(cm, \"gutterContextMenu\")) return false;\n    return gutterEvent(cm, e, \"gutterContextMenu\", false);\n  }\n\n  // UPDATING\n\n  // Compute the position of the end of a change (its 'to' property\n  // refers to the pre-change end).\n  var changeEnd = CodeMirror.changeEnd = function(change) {\n    if (!change.text) return change.to;\n    return Pos(change.from.line + change.text.length - 1,\n               lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0));\n  };\n\n  // Adjust a position to refer to the post-change position of the\n  // same text, or the end of the change if the change covers it.\n  function adjustForChange(pos, change) {\n    if (cmp(pos, change.from) < 0) return pos;\n    if (cmp(pos, change.to) <= 0) return changeEnd(change);\n\n    var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch;\n    if (pos.line == change.to.line) ch += changeEnd(change).ch - change.to.ch;\n    return Pos(line, ch);\n  }\n\n  function computeSelAfterChange(doc, change) {\n    var out = [];\n    for (var i = 0; i < doc.sel.ranges.length; i++) {\n      var range = doc.sel.ranges[i];\n      out.push(new Range(adjustForChange(range.anchor, change),\n                         adjustForChange(range.head, change)));\n    }\n    return normalizeSelection(out, doc.sel.primIndex);\n  }\n\n  function offsetPos(pos, old, nw) {\n    if (pos.line == old.line)\n      return Pos(nw.line, pos.ch - old.ch + nw.ch);\n    else\n      return Pos(nw.line + (pos.line - old.line), pos.ch);\n  }\n\n  // Used by replaceSelections to allow moving the selection to the\n  // start or around the replaced test. Hint may be \"start\" or \"around\".\n  function computeReplacedSel(doc, changes, hint) {\n    var out = [];\n    var oldPrev = Pos(doc.first, 0), newPrev = oldPrev;\n    for (var i = 0; i < changes.length; i++) {\n      var change = changes[i];\n      var from = offsetPos(change.from, oldPrev, newPrev);\n      var to = offsetPos(changeEnd(change), oldPrev, newPrev);\n      oldPrev = change.to;\n      newPrev = to;\n      if (hint == \"around\") {\n        var range = doc.sel.ranges[i], inv = cmp(range.head, range.anchor) < 0;\n        out[i] = new Range(inv ? to : from, inv ? from : to);\n      } else {\n        out[i] = new Range(from, from);\n      }\n    }\n    return new Selection(out, doc.sel.primIndex);\n  }\n\n  // Allow \"beforeChange\" event handlers to influence a change\n  function filterChange(doc, change, update) {\n    var obj = {\n      canceled: false,\n      from: change.from,\n      to: change.to,\n      text: change.text,\n      origin: change.origin,\n      cancel: function() { this.canceled = true; }\n    };\n    if (update) obj.update = function(from, to, text, origin) {\n      if (from) this.from = clipPos(doc, from);\n      if (to) this.to = clipPos(doc, to);\n      if (text) this.text = text;\n      if (origin !== undefined) this.origin = origin;\n    };\n    signal(doc, \"beforeChange\", doc, obj);\n    if (doc.cm) signal(doc.cm, \"beforeChange\", doc.cm, obj);\n\n    if (obj.canceled) return null;\n    return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin};\n  }\n\n  // Apply a change to a document, and add it to the document's\n  // history, and propagating it to all linked documents.\n  function makeChange(doc, change, ignoreReadOnly) {\n    if (doc.cm) {\n      if (!doc.cm.curOp) return operation(doc.cm, makeChange)(doc, change, ignoreReadOnly);\n      if (doc.cm.state.suppressEdits) return;\n    }\n\n    if (hasHandler(doc, \"beforeChange\") || doc.cm && hasHandler(doc.cm, \"beforeChange\")) {\n      change = filterChange(doc, change, true);\n      if (!change) return;\n    }\n\n    // Possibly split or suppress the update based on the presence\n    // of read-only spans in its range.\n    var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to);\n    if (split) {\n      for (var i = split.length - 1; i >= 0; --i)\n        makeChangeInner(doc, {from: split[i].from, to: split[i].to, text: i ? [\"\"] : change.text});\n    } else {\n      makeChangeInner(doc, change);\n    }\n  }\n\n  function makeChangeInner(doc, change) {\n    if (change.text.length == 1 && change.text[0] == \"\" && cmp(change.from, change.to) == 0) return;\n    var selAfter = computeSelAfterChange(doc, change);\n    addChangeToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN);\n\n    makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change));\n    var rebased = [];\n\n    linkedDocs(doc, function(doc, sharedHist) {\n      if (!sharedHist && indexOf(rebased, doc.history) == -1) {\n        rebaseHist(doc.history, change);\n        rebased.push(doc.history);\n      }\n      makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change));\n    });\n  }\n\n  // Revert a change stored in a document's history.\n  function makeChangeFromHistory(doc, type, allowSelectionOnly) {\n    if (doc.cm && doc.cm.state.suppressEdits) return;\n\n    var hist = doc.history, event, selAfter = doc.sel;\n    var source = type == \"undo\" ? hist.done : hist.undone, dest = type == \"undo\" ? hist.undone : hist.done;\n\n    // Verify that there is a useable event (so that ctrl-z won't\n    // needlessly clear selection events)\n    for (var i = 0; i < source.length; i++) {\n      event = source[i];\n      if (allowSelectionOnly ? event.ranges && !event.equals(doc.sel) : !event.ranges)\n        break;\n    }\n    if (i == source.length) return;\n    hist.lastOrigin = hist.lastSelOrigin = null;\n\n    for (;;) {\n      event = source.pop();\n      if (event.ranges) {\n        pushSelectionToHistory(event, dest);\n        if (allowSelectionOnly && !event.equals(doc.sel)) {\n          setSelection(doc, event, {clearRedo: false});\n          return;\n        }\n        selAfter = event;\n      }\n      else break;\n    }\n\n    // Build up a reverse change object to add to the opposite history\n    // stack (redo when undoing, and vice versa).\n    var antiChanges = [];\n    pushSelectionToHistory(selAfter, dest);\n    dest.push({changes: antiChanges, generation: hist.generation});\n    hist.generation = event.generation || ++hist.maxGeneration;\n\n    var filter = hasHandler(doc, \"beforeChange\") || doc.cm && hasHandler(doc.cm, \"beforeChange\");\n\n    for (var i = event.changes.length - 1; i >= 0; --i) {\n      var change = event.changes[i];\n      change.origin = type;\n      if (filter && !filterChange(doc, change, false)) {\n        source.length = 0;\n        return;\n      }\n\n      antiChanges.push(historyChangeFromChange(doc, change));\n\n      var after = i ? computeSelAfterChange(doc, change) : lst(source);\n      makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change));\n      if (!i && doc.cm) doc.cm.scrollIntoView({from: change.from, to: changeEnd(change)});\n      var rebased = [];\n\n      // Propagate to the linked documents\n      linkedDocs(doc, function(doc, sharedHist) {\n        if (!sharedHist && indexOf(rebased, doc.history) == -1) {\n          rebaseHist(doc.history, change);\n          rebased.push(doc.history);\n        }\n        makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change));\n      });\n    }\n  }\n\n  // Sub-views need their line numbers shifted when text is added\n  // above or below them in the parent document.\n  function shiftDoc(doc, distance) {\n    if (distance == 0) return;\n    doc.first += distance;\n    doc.sel = new Selection(map(doc.sel.ranges, function(range) {\n      return new Range(Pos(range.anchor.line + distance, range.anchor.ch),\n                       Pos(range.head.line + distance, range.head.ch));\n    }), doc.sel.primIndex);\n    if (doc.cm) {\n      regChange(doc.cm, doc.first, doc.first - distance, distance);\n      for (var d = doc.cm.display, l = d.viewFrom; l < d.viewTo; l++)\n        regLineChange(doc.cm, l, \"gutter\");\n    }\n  }\n\n  // More lower-level change function, handling only a single document\n  // (not linked ones).\n  function makeChangeSingleDoc(doc, change, selAfter, spans) {\n    if (doc.cm && !doc.cm.curOp)\n      return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans);\n\n    if (change.to.line < doc.first) {\n      shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line));\n      return;\n    }\n    if (change.from.line > doc.lastLine()) return;\n\n    // Clip the change to the size of this doc\n    if (change.from.line < doc.first) {\n      var shift = change.text.length - 1 - (doc.first - change.from.line);\n      shiftDoc(doc, shift);\n      change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch),\n                text: [lst(change.text)], origin: change.origin};\n    }\n    var last = doc.lastLine();\n    if (change.to.line > last) {\n      change = {from: change.from, to: Pos(last, getLine(doc, last).text.length),\n                text: [change.text[0]], origin: change.origin};\n    }\n\n    change.removed = getBetween(doc, change.from, change.to);\n\n    if (!selAfter) selAfter = computeSelAfterChange(doc, change);\n    if (doc.cm) makeChangeSingleDocInEditor(doc.cm, change, spans);\n    else updateDoc(doc, change, spans);\n    setSelectionNoUndo(doc, selAfter, sel_dontScroll);\n  }\n\n  // Handle the interaction of a change to a document with the editor\n  // that this document is part of.\n  function makeChangeSingleDocInEditor(cm, change, spans) {\n    var doc = cm.doc, display = cm.display, from = change.from, to = change.to;\n\n    var recomputeMaxLength = false, checkWidthStart = from.line;\n    if (!cm.options.lineWrapping) {\n      checkWidthStart = lineNo(visualLine(getLine(doc, from.line)));\n      doc.iter(checkWidthStart, to.line + 1, function(line) {\n        if (line == display.maxLine) {\n          recomputeMaxLength = true;\n          return true;\n        }\n      });\n    }\n\n    if (doc.sel.contains(change.from, change.to) > -1)\n      signalCursorActivity(cm);\n\n    updateDoc(doc, change, spans, estimateHeight(cm));\n\n    if (!cm.options.lineWrapping) {\n      doc.iter(checkWidthStart, from.line + change.text.length, function(line) {\n        var len = lineLength(line);\n        if (len > display.maxLineLength) {\n          display.maxLine = line;\n          display.maxLineLength = len;\n          display.maxLineChanged = true;\n          recomputeMaxLength = false;\n        }\n      });\n      if (recomputeMaxLength) cm.curOp.updateMaxLine = true;\n    }\n\n    // Adjust frontier, schedule worker\n    doc.frontier = Math.min(doc.frontier, from.line);\n    startWorker(cm, 400);\n\n    var lendiff = change.text.length - (to.line - from.line) - 1;\n    // Remember that these lines changed, for updating the display\n    if (change.full)\n      regChange(cm);\n    else if (from.line == to.line && change.text.length == 1 && !isWholeLineUpdate(cm.doc, change))\n      regLineChange(cm, from.line, \"text\");\n    else\n      regChange(cm, from.line, to.line + 1, lendiff);\n\n    var changesHandler = hasHandler(cm, \"changes\"), changeHandler = hasHandler(cm, \"change\");\n    if (changeHandler || changesHandler) {\n      var obj = {\n        from: from, to: to,\n        text: change.text,\n        removed: change.removed,\n        origin: change.origin\n      };\n      if (changeHandler) signalLater(cm, \"change\", cm, obj);\n      if (changesHandler) (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).push(obj);\n    }\n    cm.display.selForContextMenu = null;\n  }\n\n  function replaceRange(doc, code, from, to, origin) {\n    if (!to) to = from;\n    if (cmp(to, from) < 0) { var tmp = to; to = from; from = tmp; }\n    if (typeof code == \"string\") code = doc.splitLines(code);\n    makeChange(doc, {from: from, to: to, text: code, origin: origin});\n  }\n\n  // SCROLLING THINGS INTO VIEW\n\n  // If an editor sits on the top or bottom of the window, partially\n  // scrolled out of view, this ensures that the cursor is visible.\n  function maybeScrollWindow(cm, coords) {\n    if (signalDOMEvent(cm, \"scrollCursorIntoView\")) return;\n\n    var display = cm.display, box = display.sizer.getBoundingClientRect(), doScroll = null;\n    if (coords.top + box.top < 0) doScroll = true;\n    else if (coords.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false;\n    if (doScroll != null && !phantom) {\n      var scrollNode = elt(\"div\", \"\\u200b\", null, \"position: absolute; top: \" +\n                           (coords.top - display.viewOffset - paddingTop(cm.display)) + \"px; height: \" +\n                           (coords.bottom - coords.top + scrollGap(cm) + display.barHeight) + \"px; left: \" +\n                           coords.left + \"px; width: 2px;\");\n      cm.display.lineSpace.appendChild(scrollNode);\n      scrollNode.scrollIntoView(doScroll);\n      cm.display.lineSpace.removeChild(scrollNode);\n    }\n  }\n\n  // Scroll a given position into view (immediately), verifying that\n  // it actually became visible (as line heights are accurately\n  // measured, the position of something may 'drift' during drawing).\n  function scrollPosIntoView(cm, pos, end, margin) {\n    if (margin == null) margin = 0;\n    for (var limit = 0; limit < 5; limit++) {\n      var changed = false, coords = cursorCoords(cm, pos);\n      var endCoords = !end || end == pos ? coords : cursorCoords(cm, end);\n      var scrollPos = calculateScrollPos(cm, Math.min(coords.left, endCoords.left),\n                                         Math.min(coords.top, endCoords.top) - margin,\n                                         Math.max(coords.left, endCoords.left),\n                                         Math.max(coords.bottom, endCoords.bottom) + margin);\n      var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft;\n      if (scrollPos.scrollTop != null) {\n        setScrollTop(cm, scrollPos.scrollTop);\n        if (Math.abs(cm.doc.scrollTop - startTop) > 1) changed = true;\n      }\n      if (scrollPos.scrollLeft != null) {\n        setScrollLeft(cm, scrollPos.scrollLeft);\n        if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) changed = true;\n      }\n      if (!changed) break;\n    }\n    return coords;\n  }\n\n  // Scroll a given set of coordinates into view (immediately).\n  function scrollIntoView(cm, x1, y1, x2, y2) {\n    var scrollPos = calculateScrollPos(cm, x1, y1, x2, y2);\n    if (scrollPos.scrollTop != null) setScrollTop(cm, scrollPos.scrollTop);\n    if (scrollPos.scrollLeft != null) setScrollLeft(cm, scrollPos.scrollLeft);\n  }\n\n  // Calculate a new scroll position needed to scroll the given\n  // rectangle into view. Returns an object with scrollTop and\n  // scrollLeft properties. When these are undefined, the\n  // vertical/horizontal position does not need to be adjusted.\n  function calculateScrollPos(cm, x1, y1, x2, y2) {\n    var display = cm.display, snapMargin = textHeight(cm.display);\n    if (y1 < 0) y1 = 0;\n    var screentop = cm.curOp && cm.curOp.scrollTop != null ? cm.curOp.scrollTop : display.scroller.scrollTop;\n    var screen = displayHeight(cm), result = {};\n    if (y2 - y1 > screen) y2 = y1 + screen;\n    var docBottom = cm.doc.height + paddingVert(display);\n    var atTop = y1 < snapMargin, atBottom = y2 > docBottom - snapMargin;\n    if (y1 < screentop) {\n      result.scrollTop = atTop ? 0 : y1;\n    } else if (y2 > screentop + screen) {\n      var newTop = Math.min(y1, (atBottom ? docBottom : y2) - screen);\n      if (newTop != screentop) result.scrollTop = newTop;\n    }\n\n    var screenleft = cm.curOp && cm.curOp.scrollLeft != null ? cm.curOp.scrollLeft : display.scroller.scrollLeft;\n    var screenw = displayWidth(cm) - (cm.options.fixedGutter ? display.gutters.offsetWidth : 0);\n    var tooWide = x2 - x1 > screenw;\n    if (tooWide) x2 = x1 + screenw;\n    if (x1 < 10)\n      result.scrollLeft = 0;\n    else if (x1 < screenleft)\n      result.scrollLeft = Math.max(0, x1 - (tooWide ? 0 : 10));\n    else if (x2 > screenw + screenleft - 3)\n      result.scrollLeft = x2 + (tooWide ? 0 : 10) - screenw;\n    return result;\n  }\n\n  // Store a relative adjustment to the scroll position in the current\n  // operation (to be applied when the operation finishes).\n  function addToScrollPos(cm, left, top) {\n    if (left != null || top != null) resolveScrollToPos(cm);\n    if (left != null)\n      cm.curOp.scrollLeft = (cm.curOp.scrollLeft == null ? cm.doc.scrollLeft : cm.curOp.scrollLeft) + left;\n    if (top != null)\n      cm.curOp.scrollTop = (cm.curOp.scrollTop == null ? cm.doc.scrollTop : cm.curOp.scrollTop) + top;\n  }\n\n  // Make sure that at the end of the operation the current cursor is\n  // shown.\n  function ensureCursorVisible(cm) {\n    resolveScrollToPos(cm);\n    var cur = cm.getCursor(), from = cur, to = cur;\n    if (!cm.options.lineWrapping) {\n      from = cur.ch ? Pos(cur.line, cur.ch - 1) : cur;\n      to = Pos(cur.line, cur.ch + 1);\n    }\n    cm.curOp.scrollToPos = {from: from, to: to, margin: cm.options.cursorScrollMargin, isCursor: true};\n  }\n\n  // When an operation has its scrollToPos property set, and another\n  // scroll action is applied before the end of the operation, this\n  // 'simulates' scrolling that position into view in a cheap way, so\n  // that the effect of intermediate scroll commands is not ignored.\n  function resolveScrollToPos(cm) {\n    var range = cm.curOp.scrollToPos;\n    if (range) {\n      cm.curOp.scrollToPos = null;\n      var from = estimateCoords(cm, range.from), to = estimateCoords(cm, range.to);\n      var sPos = calculateScrollPos(cm, Math.min(from.left, to.left),\n                                    Math.min(from.top, to.top) - range.margin,\n                                    Math.max(from.right, to.right),\n                                    Math.max(from.bottom, to.bottom) + range.margin);\n      cm.scrollTo(sPos.scrollLeft, sPos.scrollTop);\n    }\n  }\n\n  // API UTILITIES\n\n  // Indent the given line. The how parameter can be \"smart\",\n  // \"add\"/null, \"subtract\", or \"prev\". When aggressive is false\n  // (typically set to true for forced single-line indents), empty\n  // lines are not indented, and places where the mode returns Pass\n  // are left alone.\n  function indentLine(cm, n, how, aggressive) {\n    var doc = cm.doc, state;\n    if (how == null) how = \"add\";\n    if (how == \"smart\") {\n      // Fall back to \"prev\" when the mode doesn't have an indentation\n      // method.\n      if (!doc.mode.indent) how = \"prev\";\n      else state = getStateBefore(cm, n);\n    }\n\n    var tabSize = cm.options.tabSize;\n    var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize);\n    if (line.stateAfter) line.stateAfter = null;\n    var curSpaceString = line.text.match(/^\\s*/)[0], indentation;\n    if (!aggressive && !/\\S/.test(line.text)) {\n      indentation = 0;\n      how = \"not\";\n    } else if (how == \"smart\") {\n      indentation = doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text);\n      if (indentation == Pass || indentation > 150) {\n        if (!aggressive) return;\n        how = \"prev\";\n      }\n    }\n    if (how == \"prev\") {\n      if (n > doc.first) indentation = countColumn(getLine(doc, n-1).text, null, tabSize);\n      else indentation = 0;\n    } else if (how == \"add\") {\n      indentation = curSpace + cm.options.indentUnit;\n    } else if (how == \"subtract\") {\n      indentation = curSpace - cm.options.indentUnit;\n    } else if (typeof how == \"number\") {\n      indentation = curSpace + how;\n    }\n    indentation = Math.max(0, indentation);\n\n    var indentString = \"\", pos = 0;\n    if (cm.options.indentWithTabs)\n      for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += \"\\t\";}\n    if (pos < indentation) indentString += spaceStr(indentation - pos);\n\n    if (indentString != curSpaceString) {\n      replaceRange(doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), \"+input\");\n      line.stateAfter = null;\n      return true;\n    } else {\n      // Ensure that, if the cursor was in the whitespace at the start\n      // of the line, it is moved to the end of that space.\n      for (var i = 0; i < doc.sel.ranges.length; i++) {\n        var range = doc.sel.ranges[i];\n        if (range.head.line == n && range.head.ch < curSpaceString.length) {\n          var pos = Pos(n, curSpaceString.length);\n          replaceOneSelection(doc, i, new Range(pos, pos));\n          break;\n        }\n      }\n    }\n  }\n\n  // Utility for applying a change to a line by handle or number,\n  // returning the number and optionally registering the line as\n  // changed.\n  function changeLine(doc, handle, changeType, op) {\n    var no = handle, line = handle;\n    if (typeof handle == \"number\") line = getLine(doc, clipLine(doc, handle));\n    else no = lineNo(handle);\n    if (no == null) return null;\n    if (op(line, no) && doc.cm) regLineChange(doc.cm, no, changeType);\n    return line;\n  }\n\n  // Helper for deleting text near the selection(s), used to implement\n  // backspace, delete, and similar functionality.\n  function deleteNearSelection(cm, compute) {\n    var ranges = cm.doc.sel.ranges, kill = [];\n    // Build up a set of ranges to kill first, merging overlapping\n    // ranges.\n    for (var i = 0; i < ranges.length; i++) {\n      var toKill = compute(ranges[i]);\n      while (kill.length && cmp(toKill.from, lst(kill).to) <= 0) {\n        var replaced = kill.pop();\n        if (cmp(replaced.from, toKill.from) < 0) {\n          toKill.from = replaced.from;\n          break;\n        }\n      }\n      kill.push(toKill);\n    }\n    // Next, remove those actual ranges.\n    runInOp(cm, function() {\n      for (var i = kill.length - 1; i >= 0; i--)\n        replaceRange(cm.doc, \"\", kill[i].from, kill[i].to, \"+delete\");\n      ensureCursorVisible(cm);\n    });\n  }\n\n  // Used for horizontal relative motion. Dir is -1 or 1 (left or\n  // right), unit can be \"char\", \"column\" (like char, but doesn't\n  // cross line boundaries), \"word\" (across next word), or \"group\" (to\n  // the start of next group of word or non-word-non-whitespace\n  // chars). The visually param controls whether, in right-to-left\n  // text, direction 1 means to move towards the next index in the\n  // string, or towards the character to the right of the current\n  // position. The resulting position will have a hitSide=true\n  // property if it reached the end of the document.\n  function findPosH(doc, pos, dir, unit, visually) {\n    var line = pos.line, ch = pos.ch, origDir = dir;\n    var lineObj = getLine(doc, line);\n    function findNextLine() {\n      var l = line + dir;\n      if (l < doc.first || l >= doc.first + doc.size) return false\n      line = l;\n      return lineObj = getLine(doc, l);\n    }\n    function moveOnce(boundToLine) {\n      var next = (visually ? moveVisually : moveLogically)(lineObj, ch, dir, true);\n      if (next == null) {\n        if (!boundToLine && findNextLine()) {\n          if (visually) ch = (dir < 0 ? lineRight : lineLeft)(lineObj);\n          else ch = dir < 0 ? lineObj.text.length : 0;\n        } else return false\n      } else ch = next;\n      return true;\n    }\n\n    if (unit == \"char\") {\n      moveOnce()\n    } else if (unit == \"column\") {\n      moveOnce(true)\n    } else if (unit == \"word\" || unit == \"group\") {\n      var sawType = null, group = unit == \"group\";\n      var helper = doc.cm && doc.cm.getHelper(pos, \"wordChars\");\n      for (var first = true;; first = false) {\n        if (dir < 0 && !moveOnce(!first)) break;\n        var cur = lineObj.text.charAt(ch) || \"\\n\";\n        var type = isWordChar(cur, helper) ? \"w\"\n          : group && cur == \"\\n\" ? \"n\"\n          : !group || /\\s/.test(cur) ? null\n          : \"p\";\n        if (group && !first && !type) type = \"s\";\n        if (sawType && sawType != type) {\n          if (dir < 0) {dir = 1; moveOnce();}\n          break;\n        }\n\n        if (type) sawType = type;\n        if (dir > 0 && !moveOnce(!first)) break;\n      }\n    }\n    var result = skipAtomic(doc, Pos(line, ch), pos, origDir, true);\n    if (!cmp(pos, result)) result.hitSide = true;\n    return result;\n  }\n\n  // For relative vertical movement. Dir may be -1 or 1. Unit can be\n  // \"page\" or \"line\". The resulting position will have a hitSide=true\n  // property if it reached the end of the document.\n  function findPosV(cm, pos, dir, unit) {\n    var doc = cm.doc, x = pos.left, y;\n    if (unit == \"page\") {\n      var pageSize = Math.min(cm.display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight);\n      y = pos.top + dir * (pageSize - (dir < 0 ? 1.5 : .5) * textHeight(cm.display));\n    } else if (unit == \"line\") {\n      y = dir > 0 ? pos.bottom + 3 : pos.top - 3;\n    }\n    for (;;) {\n      var target = coordsChar(cm, x, y);\n      if (!target.outside) break;\n      if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break; }\n      y += dir * 5;\n    }\n    return target;\n  }\n\n  // EDITOR METHODS\n\n  // The publicly visible API. Note that methodOp(f) means\n  // 'wrap f in an operation, performed on its `this` parameter'.\n\n  // This is not the complete set of editor methods. Most of the\n  // methods defined on the Doc type are also injected into\n  // CodeMirror.prototype, for backwards compatibility and\n  // convenience.\n\n  CodeMirror.prototype = {\n    constructor: CodeMirror,\n    focus: function(){window.focus(); this.display.input.focus();},\n\n    setOption: function(option, value) {\n      var options = this.options, old = options[option];\n      if (options[option] == value && option != \"mode\") return;\n      options[option] = value;\n      if (optionHandlers.hasOwnProperty(option))\n        operation(this, optionHandlers[option])(this, value, old);\n    },\n\n    getOption: function(option) {return this.options[option];},\n    getDoc: function() {return this.doc;},\n\n    addKeyMap: function(map, bottom) {\n      this.state.keyMaps[bottom ? \"push\" : \"unshift\"](getKeyMap(map));\n    },\n    removeKeyMap: function(map) {\n      var maps = this.state.keyMaps;\n      for (var i = 0; i < maps.length; ++i)\n        if (maps[i] == map || maps[i].name == map) {\n          maps.splice(i, 1);\n          return true;\n        }\n    },\n\n    addOverlay: methodOp(function(spec, options) {\n      var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec);\n      if (mode.startState) throw new Error(\"Overlays may not be stateful.\");\n      this.state.overlays.push({mode: mode, modeSpec: spec, opaque: options && options.opaque});\n      this.state.modeGen++;\n      regChange(this);\n    }),\n    removeOverlay: methodOp(function(spec) {\n      var overlays = this.state.overlays;\n      for (var i = 0; i < overlays.length; ++i) {\n        var cur = overlays[i].modeSpec;\n        if (cur == spec || typeof spec == \"string\" && cur.name == spec) {\n          overlays.splice(i, 1);\n          this.state.modeGen++;\n          regChange(this);\n          return;\n        }\n      }\n    }),\n\n    indentLine: methodOp(function(n, dir, aggressive) {\n      if (typeof dir != \"string\" && typeof dir != \"number\") {\n        if (dir == null) dir = this.options.smartIndent ? \"smart\" : \"prev\";\n        else dir = dir ? \"add\" : \"subtract\";\n      }\n      if (isLine(this.doc, n)) indentLine(this, n, dir, aggressive);\n    }),\n    indentSelection: methodOp(function(how) {\n      var ranges = this.doc.sel.ranges, end = -1;\n      for (var i = 0; i < ranges.length; i++) {\n        var range = ranges[i];\n        if (!range.empty()) {\n          var from = range.from(), to = range.to();\n          var start = Math.max(end, from.line);\n          end = Math.min(this.lastLine(), to.line - (to.ch ? 0 : 1)) + 1;\n          for (var j = start; j < end; ++j)\n            indentLine(this, j, how);\n          var newRanges = this.doc.sel.ranges;\n          if (from.ch == 0 && ranges.length == newRanges.length && newRanges[i].from().ch > 0)\n            replaceOneSelection(this.doc, i, new Range(from, newRanges[i].to()), sel_dontScroll);\n        } else if (range.head.line > end) {\n          indentLine(this, range.head.line, how, true);\n          end = range.head.line;\n          if (i == this.doc.sel.primIndex) ensureCursorVisible(this);\n        }\n      }\n    }),\n\n    // Fetch the parser token for a given character. Useful for hacks\n    // that want to inspect the mode state (say, for completion).\n    getTokenAt: function(pos, precise) {\n      return takeToken(this, pos, precise);\n    },\n\n    getLineTokens: function(line, precise) {\n      return takeToken(this, Pos(line), precise, true);\n    },\n\n    getTokenTypeAt: function(pos) {\n      pos = clipPos(this.doc, pos);\n      var styles = getLineStyles(this, getLine(this.doc, pos.line));\n      var before = 0, after = (styles.length - 1) / 2, ch = pos.ch;\n      var type;\n      if (ch == 0) type = styles[2];\n      else for (;;) {\n        var mid = (before + after) >> 1;\n        if ((mid ? styles[mid * 2 - 1] : 0) >= ch) after = mid;\n        else if (styles[mid * 2 + 1] < ch) before = mid + 1;\n        else { type = styles[mid * 2 + 2]; break; }\n      }\n      var cut = type ? type.indexOf(\"cm-overlay \") : -1;\n      return cut < 0 ? type : cut == 0 ? null : type.slice(0, cut - 1);\n    },\n\n    getModeAt: function(pos) {\n      var mode = this.doc.mode;\n      if (!mode.innerMode) return mode;\n      return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode;\n    },\n\n    getHelper: function(pos, type) {\n      return this.getHelpers(pos, type)[0];\n    },\n\n    getHelpers: function(pos, type) {\n      var found = [];\n      if (!helpers.hasOwnProperty(type)) return found;\n      var help = helpers[type], mode = this.getModeAt(pos);\n      if (typeof mode[type] == \"string\") {\n        if (help[mode[type]]) found.push(help[mode[type]]);\n      } else if (mode[type]) {\n        for (var i = 0; i < mode[type].length; i++) {\n          var val = help[mode[type][i]];\n          if (val) found.push(val);\n        }\n      } else if (mode.helperType && help[mode.helperType]) {\n        found.push(help[mode.helperType]);\n      } else if (help[mode.name]) {\n        found.push(help[mode.name]);\n      }\n      for (var i = 0; i < help._global.length; i++) {\n        var cur = help._global[i];\n        if (cur.pred(mode, this) && indexOf(found, cur.val) == -1)\n          found.push(cur.val);\n      }\n      return found;\n    },\n\n    getStateAfter: function(line, precise) {\n      var doc = this.doc;\n      line = clipLine(doc, line == null ? doc.first + doc.size - 1: line);\n      return getStateBefore(this, line + 1, precise);\n    },\n\n    cursorCoords: function(start, mode) {\n      var pos, range = this.doc.sel.primary();\n      if (start == null) pos = range.head;\n      else if (typeof start == \"object\") pos = clipPos(this.doc, start);\n      else pos = start ? range.from() : range.to();\n      return cursorCoords(this, pos, mode || \"page\");\n    },\n\n    charCoords: function(pos, mode) {\n      return charCoords(this, clipPos(this.doc, pos), mode || \"page\");\n    },\n\n    coordsChar: function(coords, mode) {\n      coords = fromCoordSystem(this, coords, mode || \"page\");\n      return coordsChar(this, coords.left, coords.top);\n    },\n\n    lineAtHeight: function(height, mode) {\n      height = fromCoordSystem(this, {top: height, left: 0}, mode || \"page\").top;\n      return lineAtHeight(this.doc, height + this.display.viewOffset);\n    },\n    heightAtLine: function(line, mode) {\n      var end = false, lineObj;\n      if (typeof line == \"number\") {\n        var last = this.doc.first + this.doc.size - 1;\n        if (line < this.doc.first) line = this.doc.first;\n        else if (line > last) { line = last; end = true; }\n        lineObj = getLine(this.doc, line);\n      } else {\n        lineObj = line;\n      }\n      return intoCoordSystem(this, lineObj, {top: 0, left: 0}, mode || \"page\").top +\n        (end ? this.doc.height - heightAtLine(lineObj) : 0);\n    },\n\n    defaultTextHeight: function() { return textHeight(this.display); },\n    defaultCharWidth: function() { return charWidth(this.display); },\n\n    setGutterMarker: methodOp(function(line, gutterID, value) {\n      return changeLine(this.doc, line, \"gutter\", function(line) {\n        var markers = line.gutterMarkers || (line.gutterMarkers = {});\n        markers[gutterID] = value;\n        if (!value && isEmpty(markers)) line.gutterMarkers = null;\n        return true;\n      });\n    }),\n\n    clearGutter: methodOp(function(gutterID) {\n      var cm = this, doc = cm.doc, i = doc.first;\n      doc.iter(function(line) {\n        if (line.gutterMarkers && line.gutterMarkers[gutterID]) {\n          line.gutterMarkers[gutterID] = null;\n          regLineChange(cm, i, \"gutter\");\n          if (isEmpty(line.gutterMarkers)) line.gutterMarkers = null;\n        }\n        ++i;\n      });\n    }),\n\n    lineInfo: function(line) {\n      if (typeof line == \"number\") {\n        if (!isLine(this.doc, line)) return null;\n        var n = line;\n        line = getLine(this.doc, line);\n        if (!line) return null;\n      } else {\n        var n = lineNo(line);\n        if (n == null) return null;\n      }\n      return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers,\n              textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass,\n              widgets: line.widgets};\n    },\n\n    getViewport: function() { return {from: this.display.viewFrom, to: this.display.viewTo};},\n\n    addWidget: function(pos, node, scroll, vert, horiz) {\n      var display = this.display;\n      pos = cursorCoords(this, clipPos(this.doc, pos));\n      var top = pos.bottom, left = pos.left;\n      node.style.position = \"absolute\";\n      node.setAttribute(\"cm-ignore-events\", \"true\");\n      this.display.input.setUneditable(node);\n      display.sizer.appendChild(node);\n      if (vert == \"over\") {\n        top = pos.top;\n      } else if (vert == \"above\" || vert == \"near\") {\n        var vspace = Math.max(display.wrapper.clientHeight, this.doc.height),\n        hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth);\n        // Default to positioning above (if specified and possible); otherwise default to positioning below\n        if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight)\n          top = pos.top - node.offsetHeight;\n        else if (pos.bottom + node.offsetHeight <= vspace)\n          top = pos.bottom;\n        if (left + node.offsetWidth > hspace)\n          left = hspace - node.offsetWidth;\n      }\n      node.style.top = top + \"px\";\n      node.style.left = node.style.right = \"\";\n      if (horiz == \"right\") {\n        left = display.sizer.clientWidth - node.offsetWidth;\n        node.style.right = \"0px\";\n      } else {\n        if (horiz == \"left\") left = 0;\n        else if (horiz == \"middle\") left = (display.sizer.clientWidth - node.offsetWidth) / 2;\n        node.style.left = left + \"px\";\n      }\n      if (scroll)\n        scrollIntoView(this, left, top, left + node.offsetWidth, top + node.offsetHeight);\n    },\n\n    triggerOnKeyDown: methodOp(onKeyDown),\n    triggerOnKeyPress: methodOp(onKeyPress),\n    triggerOnKeyUp: onKeyUp,\n\n    execCommand: function(cmd) {\n      if (commands.hasOwnProperty(cmd))\n        return commands[cmd].call(null, this);\n    },\n\n    triggerElectric: methodOp(function(text) { triggerElectric(this, text); }),\n\n    findPosH: function(from, amount, unit, visually) {\n      var dir = 1;\n      if (amount < 0) { dir = -1; amount = -amount; }\n      for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) {\n        cur = findPosH(this.doc, cur, dir, unit, visually);\n        if (cur.hitSide) break;\n      }\n      return cur;\n    },\n\n    moveH: methodOp(function(dir, unit) {\n      var cm = this;\n      cm.extendSelectionsBy(function(range) {\n        if (cm.display.shift || cm.doc.extend || range.empty())\n          return findPosH(cm.doc, range.head, dir, unit, cm.options.rtlMoveVisually);\n        else\n          return dir < 0 ? range.from() : range.to();\n      }, sel_move);\n    }),\n\n    deleteH: methodOp(function(dir, unit) {\n      var sel = this.doc.sel, doc = this.doc;\n      if (sel.somethingSelected())\n        doc.replaceSelection(\"\", null, \"+delete\");\n      else\n        deleteNearSelection(this, function(range) {\n          var other = findPosH(doc, range.head, dir, unit, false);\n          return dir < 0 ? {from: other, to: range.head} : {from: range.head, to: other};\n        });\n    }),\n\n    findPosV: function(from, amount, unit, goalColumn) {\n      var dir = 1, x = goalColumn;\n      if (amount < 0) { dir = -1; amount = -amount; }\n      for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) {\n        var coords = cursorCoords(this, cur, \"div\");\n        if (x == null) x = coords.left;\n        else coords.left = x;\n        cur = findPosV(this, coords, dir, unit);\n        if (cur.hitSide) break;\n      }\n      return cur;\n    },\n\n    moveV: methodOp(function(dir, unit) {\n      var cm = this, doc = this.doc, goals = [];\n      var collapse = !cm.display.shift && !doc.extend && doc.sel.somethingSelected();\n      doc.extendSelectionsBy(function(range) {\n        if (collapse)\n          return dir < 0 ? range.from() : range.to();\n        var headPos = cursorCoords(cm, range.head, \"div\");\n        if (range.goalColumn != null) headPos.left = range.goalColumn;\n        goals.push(headPos.left);\n        var pos = findPosV(cm, headPos, dir, unit);\n        if (unit == \"page\" && range == doc.sel.primary())\n          addToScrollPos(cm, null, charCoords(cm, pos, \"div\").top - headPos.top);\n        return pos;\n      }, sel_move);\n      if (goals.length) for (var i = 0; i < doc.sel.ranges.length; i++)\n        doc.sel.ranges[i].goalColumn = goals[i];\n    }),\n\n    // Find the word at the given position (as returned by coordsChar).\n    findWordAt: function(pos) {\n      var doc = this.doc, line = getLine(doc, pos.line).text;\n      var start = pos.ch, end = pos.ch;\n      if (line) {\n        var helper = this.getHelper(pos, \"wordChars\");\n        if ((pos.xRel < 0 || end == line.length) && start) --start; else ++end;\n        var startChar = line.charAt(start);\n        var check = isWordChar(startChar, helper)\n          ? function(ch) { return isWordChar(ch, helper); }\n          : /\\s/.test(startChar) ? function(ch) {return /\\s/.test(ch);}\n          : function(ch) {return !/\\s/.test(ch) && !isWordChar(ch);};\n        while (start > 0 && check(line.charAt(start - 1))) --start;\n        while (end < line.length && check(line.charAt(end))) ++end;\n      }\n      return new Range(Pos(pos.line, start), Pos(pos.line, end));\n    },\n\n    toggleOverwrite: function(value) {\n      if (value != null && value == this.state.overwrite) return;\n      if (this.state.overwrite = !this.state.overwrite)\n        addClass(this.display.cursorDiv, \"CodeMirror-overwrite\");\n      else\n        rmClass(this.display.cursorDiv, \"CodeMirror-overwrite\");\n\n      signal(this, \"overwriteToggle\", this, this.state.overwrite);\n    },\n    hasFocus: function() { return this.display.input.getField() == activeElt(); },\n    isReadOnly: function() { return !!(this.options.readOnly || this.doc.cantEdit); },\n\n    scrollTo: methodOp(function(x, y) {\n      if (x != null || y != null) resolveScrollToPos(this);\n      if (x != null) this.curOp.scrollLeft = x;\n      if (y != null) this.curOp.scrollTop = y;\n    }),\n    getScrollInfo: function() {\n      var scroller = this.display.scroller;\n      return {left: scroller.scrollLeft, top: scroller.scrollTop,\n              height: scroller.scrollHeight - scrollGap(this) - this.display.barHeight,\n              width: scroller.scrollWidth - scrollGap(this) - this.display.barWidth,\n              clientHeight: displayHeight(this), clientWidth: displayWidth(this)};\n    },\n\n    scrollIntoView: methodOp(function(range, margin) {\n      if (range == null) {\n        range = {from: this.doc.sel.primary().head, to: null};\n        if (margin == null) margin = this.options.cursorScrollMargin;\n      } else if (typeof range == \"number\") {\n        range = {from: Pos(range, 0), to: null};\n      } else if (range.from == null) {\n        range = {from: range, to: null};\n      }\n      if (!range.to) range.to = range.from;\n      range.margin = margin || 0;\n\n      if (range.from.line != null) {\n        resolveScrollToPos(this);\n        this.curOp.scrollToPos = range;\n      } else {\n        var sPos = calculateScrollPos(this, Math.min(range.from.left, range.to.left),\n                                      Math.min(range.from.top, range.to.top) - range.margin,\n                                      Math.max(range.from.right, range.to.right),\n                                      Math.max(range.from.bottom, range.to.bottom) + range.margin);\n        this.scrollTo(sPos.scrollLeft, sPos.scrollTop);\n      }\n    }),\n\n    setSize: methodOp(function(width, height) {\n      var cm = this;\n      function interpret(val) {\n        return typeof val == \"number\" || /^\\d+$/.test(String(val)) ? val + \"px\" : val;\n      }\n      if (width != null) cm.display.wrapper.style.width = interpret(width);\n      if (height != null) cm.display.wrapper.style.height = interpret(height);\n      if (cm.options.lineWrapping) clearLineMeasurementCache(this);\n      var lineNo = cm.display.viewFrom;\n      cm.doc.iter(lineNo, cm.display.viewTo, function(line) {\n        if (line.widgets) for (var i = 0; i < line.widgets.length; i++)\n          if (line.widgets[i].noHScroll) { regLineChange(cm, lineNo, \"widget\"); break; }\n        ++lineNo;\n      });\n      cm.curOp.forceUpdate = true;\n      signal(cm, \"refresh\", this);\n    }),\n\n    operation: function(f){return runInOp(this, f);},\n\n    refresh: methodOp(function() {\n      var oldHeight = this.display.cachedTextHeight;\n      regChange(this);\n      this.curOp.forceUpdate = true;\n      clearCaches(this);\n      this.scrollTo(this.doc.scrollLeft, this.doc.scrollTop);\n      updateGutterSpace(this);\n      if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5)\n        estimateLineHeights(this);\n      signal(this, \"refresh\", this);\n    }),\n\n    swapDoc: methodOp(function(doc) {\n      var old = this.doc;\n      old.cm = null;\n      attachDoc(this, doc);\n      clearCaches(this);\n      this.display.input.reset();\n      this.scrollTo(doc.scrollLeft, doc.scrollTop);\n      this.curOp.forceScroll = true;\n      signalLater(this, \"swapDoc\", this, old);\n      return old;\n    }),\n\n    getInputField: function(){return this.display.input.getField();},\n    getWrapperElement: function(){return this.display.wrapper;},\n    getScrollerElement: function(){return this.display.scroller;},\n    getGutterElement: function(){return this.display.gutters;}\n  };\n  eventMixin(CodeMirror);\n\n  // OPTION DEFAULTS\n\n  // The default configuration options.\n  var defaults = CodeMirror.defaults = {};\n  // Functions to run when options are changed.\n  var optionHandlers = CodeMirror.optionHandlers = {};\n\n  function option(name, deflt, handle, notOnInit) {\n    CodeMirror.defaults[name] = deflt;\n    if (handle) optionHandlers[name] =\n      notOnInit ? function(cm, val, old) {if (old != Init) handle(cm, val, old);} : handle;\n  }\n\n  // Passed to option handlers when there is no old value.\n  var Init = CodeMirror.Init = {toString: function(){return \"CodeMirror.Init\";}};\n\n  // These two are, on init, called from the constructor because they\n  // have to be initialized before the editor can start at all.\n  option(\"value\", \"\", function(cm, val) {\n    cm.setValue(val);\n  }, true);\n  option(\"mode\", null, function(cm, val) {\n    cm.doc.modeOption = val;\n    loadMode(cm);\n  }, true);\n\n  option(\"indentUnit\", 2, loadMode, true);\n  option(\"indentWithTabs\", false);\n  option(\"smartIndent\", true);\n  option(\"tabSize\", 4, function(cm) {\n    resetModeState(cm);\n    clearCaches(cm);\n    regChange(cm);\n  }, true);\n  option(\"lineSeparator\", null, function(cm, val) {\n    cm.doc.lineSep = val;\n    if (!val) return;\n    var newBreaks = [], lineNo = cm.doc.first;\n    cm.doc.iter(function(line) {\n      for (var pos = 0;;) {\n        var found = line.text.indexOf(val, pos);\n        if (found == -1) break;\n        pos = found + val.length;\n        newBreaks.push(Pos(lineNo, found));\n      }\n      lineNo++;\n    });\n    for (var i = newBreaks.length - 1; i >= 0; i--)\n      replaceRange(cm.doc, val, newBreaks[i], Pos(newBreaks[i].line, newBreaks[i].ch + val.length))\n  });\n  option(\"specialChars\", /[\\t\\u0000-\\u0019\\u00ad\\u200b-\\u200f\\u2028\\u2029\\ufeff]/g, function(cm, val, old) {\n    cm.state.specialChars = new RegExp(val.source + (val.test(\"\\t\") ? \"\" : \"|\\t\"), \"g\");\n    if (old != CodeMirror.Init) cm.refresh();\n  });\n  option(\"specialCharPlaceholder\", defaultSpecialCharPlaceholder, function(cm) {cm.refresh();}, true);\n  option(\"electricChars\", true);\n  option(\"inputStyle\", mobile ? \"contenteditable\" : \"textarea\", function() {\n    throw new Error(\"inputStyle can not (yet) be changed in a running editor\");\n  }, true);\n  option(\"rtlMoveVisually\", !windows);\n  option(\"wholeLineUpdateBefore\", true);\n\n  option(\"theme\", \"default\", function(cm) {\n    themeChanged(cm);\n    guttersChanged(cm);\n  }, true);\n  option(\"keyMap\", \"default\", function(cm, val, old) {\n    var next = getKeyMap(val);\n    var prev = old != CodeMirror.Init && getKeyMap(old);\n    if (prev && prev.detach) prev.detach(cm, next);\n    if (next.attach) next.attach(cm, prev || null);\n  });\n  option(\"extraKeys\", null);\n\n  option(\"lineWrapping\", false, wrappingChanged, true);\n  option(\"gutters\", [], function(cm) {\n    setGuttersForLineNumbers(cm.options);\n    guttersChanged(cm);\n  }, true);\n  option(\"fixedGutter\", true, function(cm, val) {\n    cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + \"px\" : \"0\";\n    cm.refresh();\n  }, true);\n  option(\"coverGutterNextToScrollbar\", false, function(cm) {updateScrollbars(cm);}, true);\n  option(\"scrollbarStyle\", \"native\", function(cm) {\n    initScrollbars(cm);\n    updateScrollbars(cm);\n    cm.display.scrollbars.setScrollTop(cm.doc.scrollTop);\n    cm.display.scrollbars.setScrollLeft(cm.doc.scrollLeft);\n  }, true);\n  option(\"lineNumbers\", false, function(cm) {\n    setGuttersForLineNumbers(cm.options);\n    guttersChanged(cm);\n  }, true);\n  option(\"firstLineNumber\", 1, guttersChanged, true);\n  option(\"lineNumberFormatter\", function(integer) {return integer;}, guttersChanged, true);\n  option(\"showCursorWhenSelecting\", false, updateSelection, true);\n\n  option(\"resetSelectionOnContextMenu\", true);\n  option(\"lineWiseCopyCut\", true);\n\n  option(\"readOnly\", false, function(cm, val) {\n    if (val == \"nocursor\") {\n      onBlur(cm);\n      cm.display.input.blur();\n      cm.display.disabled = true;\n    } else {\n      cm.display.disabled = false;\n    }\n    cm.display.input.readOnlyChanged(val)\n  });\n  option(\"disableInput\", false, function(cm, val) {if (!val) cm.display.input.reset();}, true);\n  option(\"dragDrop\", true, dragDropChanged);\n  option(\"allowDropFileTypes\", null);\n\n  option(\"cursorBlinkRate\", 530);\n  option(\"cursorScrollMargin\", 0);\n  option(\"cursorHeight\", 1, updateSelection, true);\n  option(\"singleCursorHeightPerLine\", true, updateSelection, true);\n  option(\"workTime\", 100);\n  option(\"workDelay\", 100);\n  option(\"flattenSpans\", true, resetModeState, true);\n  option(\"addModeClass\", false, resetModeState, true);\n  option(\"pollInterval\", 100);\n  option(\"undoDepth\", 200, function(cm, val){cm.doc.history.undoDepth = val;});\n  option(\"historyEventDelay\", 1250);\n  option(\"viewportMargin\", 10, function(cm){cm.refresh();}, true);\n  option(\"maxHighlightLength\", 10000, resetModeState, true);\n  option(\"moveInputWithCursor\", true, function(cm, val) {\n    if (!val) cm.display.input.resetPosition();\n  });\n\n  option(\"tabindex\", null, function(cm, val) {\n    cm.display.input.getField().tabIndex = val || \"\";\n  });\n  option(\"autofocus\", null);\n\n  // MODE DEFINITION AND QUERYING\n\n  // Known modes, by name and by MIME\n  var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {};\n\n  // Extra arguments are stored as the mode's dependencies, which is\n  // used by (legacy) mechanisms like loadmode.js to automatically\n  // load a mode. (Preferred mechanism is the require/define calls.)\n  CodeMirror.defineMode = function(name, mode) {\n    if (!CodeMirror.defaults.mode && name != \"null\") CodeMirror.defaults.mode = name;\n    if (arguments.length > 2)\n      mode.dependencies = Array.prototype.slice.call(arguments, 2);\n    modes[name] = mode;\n  };\n\n  CodeMirror.defineMIME = function(mime, spec) {\n    mimeModes[mime] = spec;\n  };\n\n  // Given a MIME type, a {name, ...options} config object, or a name\n  // string, return a mode config object.\n  CodeMirror.resolveMode = function(spec) {\n    if (typeof spec == \"string\" && mimeModes.hasOwnProperty(spec)) {\n      spec = mimeModes[spec];\n    } else if (spec && typeof spec.name == \"string\" && mimeModes.hasOwnProperty(spec.name)) {\n      var found = mimeModes[spec.name];\n      if (typeof found == \"string\") found = {name: found};\n      spec = createObj(found, spec);\n      spec.name = found.name;\n    } else if (typeof spec == \"string\" && /^[\\w\\-]+\\/[\\w\\-]+\\+xml$/.test(spec)) {\n      return CodeMirror.resolveMode(\"application/xml\");\n    }\n    if (typeof spec == \"string\") return {name: spec};\n    else return spec || {name: \"null\"};\n  };\n\n  // Given a mode spec (anything that resolveMode accepts), find and\n  // initialize an actual mode object.\n  CodeMirror.getMode = function(options, spec) {\n    var spec = CodeMirror.resolveMode(spec);\n    var mfactory = modes[spec.name];\n    if (!mfactory) return CodeMirror.getMode(options, \"text/plain\");\n    var modeObj = mfactory(options, spec);\n    if (modeExtensions.hasOwnProperty(spec.name)) {\n      var exts = modeExtensions[spec.name];\n      for (var prop in exts) {\n        if (!exts.hasOwnProperty(prop)) continue;\n        if (modeObj.hasOwnProperty(prop)) modeObj[\"_\" + prop] = modeObj[prop];\n        modeObj[prop] = exts[prop];\n      }\n    }\n    modeObj.name = spec.name;\n    if (spec.helperType) modeObj.helperType = spec.helperType;\n    if (spec.modeProps) for (var prop in spec.modeProps)\n      modeObj[prop] = spec.modeProps[prop];\n\n    return modeObj;\n  };\n\n  // Minimal default mode.\n  CodeMirror.defineMode(\"null\", function() {\n    return {token: function(stream) {stream.skipToEnd();}};\n  });\n  CodeMirror.defineMIME(\"text/plain\", \"null\");\n\n  // This can be used to attach properties to mode objects from\n  // outside the actual mode definition.\n  var modeExtensions = CodeMirror.modeExtensions = {};\n  CodeMirror.extendMode = function(mode, properties) {\n    var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {});\n    copyObj(properties, exts);\n  };\n\n  // EXTENSIONS\n\n  CodeMirror.defineExtension = function(name, func) {\n    CodeMirror.prototype[name] = func;\n  };\n  CodeMirror.defineDocExtension = function(name, func) {\n    Doc.prototype[name] = func;\n  };\n  CodeMirror.defineOption = option;\n\n  var initHooks = [];\n  CodeMirror.defineInitHook = function(f) {initHooks.push(f);};\n\n  var helpers = CodeMirror.helpers = {};\n  CodeMirror.registerHelper = function(type, name, value) {\n    if (!helpers.hasOwnProperty(type)) helpers[type] = CodeMirror[type] = {_global: []};\n    helpers[type][name] = value;\n  };\n  CodeMirror.registerGlobalHelper = function(type, name, predicate, value) {\n    CodeMirror.registerHelper(type, name, value);\n    helpers[type]._global.push({pred: predicate, val: value});\n  };\n\n  // MODE STATE HANDLING\n\n  // Utility functions for working with state. Exported because nested\n  // modes need to do this for their inner modes.\n\n  var copyState = CodeMirror.copyState = function(mode, state) {\n    if (state === true) return state;\n    if (mode.copyState) return mode.copyState(state);\n    var nstate = {};\n    for (var n in state) {\n      var val = state[n];\n      if (val instanceof Array) val = val.concat([]);\n      nstate[n] = val;\n    }\n    return nstate;\n  };\n\n  var startState = CodeMirror.startState = function(mode, a1, a2) {\n    return mode.startState ? mode.startState(a1, a2) : true;\n  };\n\n  // Given a mode and a state (for that mode), find the inner mode and\n  // state at the position that the state refers to.\n  CodeMirror.innerMode = function(mode, state) {\n    while (mode.innerMode) {\n      var info = mode.innerMode(state);\n      if (!info || info.mode == mode) break;\n      state = info.state;\n      mode = info.mode;\n    }\n    return info || {mode: mode, state: state};\n  };\n\n  // STANDARD COMMANDS\n\n  // Commands are parameter-less actions that can be performed on an\n  // editor, mostly used for keybindings.\n  var commands = CodeMirror.commands = {\n    selectAll: function(cm) {cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()), sel_dontScroll);},\n    singleSelection: function(cm) {\n      cm.setSelection(cm.getCursor(\"anchor\"), cm.getCursor(\"head\"), sel_dontScroll);\n    },\n    killLine: function(cm) {\n      deleteNearSelection(cm, function(range) {\n        if (range.empty()) {\n          var len = getLine(cm.doc, range.head.line).text.length;\n          if (range.head.ch == len && range.head.line < cm.lastLine())\n            return {from: range.head, to: Pos(range.head.line + 1, 0)};\n          else\n            return {from: range.head, to: Pos(range.head.line, len)};\n        } else {\n          return {from: range.from(), to: range.to()};\n        }\n      });\n    },\n    deleteLine: function(cm) {\n      deleteNearSelection(cm, function(range) {\n        return {from: Pos(range.from().line, 0),\n                to: clipPos(cm.doc, Pos(range.to().line + 1, 0))};\n      });\n    },\n    delLineLeft: function(cm) {\n      deleteNearSelection(cm, function(range) {\n        return {from: Pos(range.from().line, 0), to: range.from()};\n      });\n    },\n    delWrappedLineLeft: function(cm) {\n      deleteNearSelection(cm, function(range) {\n        var top = cm.charCoords(range.head, \"div\").top + 5;\n        var leftPos = cm.coordsChar({left: 0, top: top}, \"div\");\n        return {from: leftPos, to: range.from()};\n      });\n    },\n    delWrappedLineRight: function(cm) {\n      deleteNearSelection(cm, function(range) {\n        var top = cm.charCoords(range.head, \"div\").top + 5;\n        var rightPos = cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, \"div\");\n        return {from: range.from(), to: rightPos };\n      });\n    },\n    undo: function(cm) {cm.undo();},\n    redo: function(cm) {cm.redo();},\n    undoSelection: function(cm) {cm.undoSelection();},\n    redoSelection: function(cm) {cm.redoSelection();},\n    goDocStart: function(cm) {cm.extendSelection(Pos(cm.firstLine(), 0));},\n    goDocEnd: function(cm) {cm.extendSelection(Pos(cm.lastLine()));},\n    goLineStart: function(cm) {\n      cm.extendSelectionsBy(function(range) { return lineStart(cm, range.head.line); },\n                            {origin: \"+move\", bias: 1});\n    },\n    goLineStartSmart: function(cm) {\n      cm.extendSelectionsBy(function(range) {\n        return lineStartSmart(cm, range.head);\n      }, {origin: \"+move\", bias: 1});\n    },\n    goLineEnd: function(cm) {\n      cm.extendSelectionsBy(function(range) { return lineEnd(cm, range.head.line); },\n                            {origin: \"+move\", bias: -1});\n    },\n    goLineRight: function(cm) {\n      cm.extendSelectionsBy(function(range) {\n        var top = cm.charCoords(range.head, \"div\").top + 5;\n        return cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, \"div\");\n      }, sel_move);\n    },\n    goLineLeft: function(cm) {\n      cm.extendSelectionsBy(function(range) {\n        var top = cm.charCoords(range.head, \"div\").top + 5;\n        return cm.coordsChar({left: 0, top: top}, \"div\");\n      }, sel_move);\n    },\n    goLineLeftSmart: function(cm) {\n      cm.extendSelectionsBy(function(range) {\n        var top = cm.charCoords(range.head, \"div\").top + 5;\n        var pos = cm.coordsChar({left: 0, top: top}, \"div\");\n        if (pos.ch < cm.getLine(pos.line).search(/\\S/)) return lineStartSmart(cm, range.head);\n        return pos;\n      }, sel_move);\n    },\n    goLineUp: function(cm) {cm.moveV(-1, \"line\");},\n    goLineDown: function(cm) {cm.moveV(1, \"line\");},\n    goPageUp: function(cm) {cm.moveV(-1, \"page\");},\n    goPageDown: function(cm) {cm.moveV(1, \"page\");},\n    goCharLeft: function(cm) {cm.moveH(-1, \"char\");},\n    goCharRight: function(cm) {cm.moveH(1, \"char\");},\n    goColumnLeft: function(cm) {cm.moveH(-1, \"column\");},\n    goColumnRight: function(cm) {cm.moveH(1, \"column\");},\n    goWordLeft: function(cm) {cm.moveH(-1, \"word\");},\n    goGroupRight: function(cm) {cm.moveH(1, \"group\");},\n    goGroupLeft: function(cm) {cm.moveH(-1, \"group\");},\n    goWordRight: function(cm) {cm.moveH(1, \"word\");},\n    delCharBefore: function(cm) {cm.deleteH(-1, \"char\");},\n    delCharAfter: function(cm) {cm.deleteH(1, \"char\");},\n    delWordBefore: function(cm) {cm.deleteH(-1, \"word\");},\n    delWordAfter: function(cm) {cm.deleteH(1, \"word\");},\n    delGroupBefore: function(cm) {cm.deleteH(-1, \"group\");},\n    delGroupAfter: function(cm) {cm.deleteH(1, \"group\");},\n    indentAuto: function(cm) {cm.indentSelection(\"smart\");},\n    indentMore: function(cm) {cm.indentSelection(\"add\");},\n    indentLess: function(cm) {cm.indentSelection(\"subtract\");},\n    insertTab: function(cm) {cm.replaceSelection(\"\\t\");},\n    insertSoftTab: function(cm) {\n      var spaces = [], ranges = cm.listSelections(), tabSize = cm.options.tabSize;\n      for (var i = 0; i < ranges.length; i++) {\n        var pos = ranges[i].from();\n        var col = countColumn(cm.getLine(pos.line), pos.ch, tabSize);\n        spaces.push(new Array(tabSize - col % tabSize + 1).join(\" \"));\n      }\n      cm.replaceSelections(spaces);\n    },\n    defaultTab: function(cm) {\n      if (cm.somethingSelected()) cm.indentSelection(\"add\");\n      else cm.execCommand(\"insertTab\");\n    },\n    transposeChars: function(cm) {\n      runInOp(cm, function() {\n        var ranges = cm.listSelections(), newSel = [];\n        for (var i = 0; i < ranges.length; i++) {\n          var cur = ranges[i].head, line = getLine(cm.doc, cur.line).text;\n          if (line) {\n            if (cur.ch == line.length) cur = new Pos(cur.line, cur.ch - 1);\n            if (cur.ch > 0) {\n              cur = new Pos(cur.line, cur.ch + 1);\n              cm.replaceRange(line.charAt(cur.ch - 1) + line.charAt(cur.ch - 2),\n                              Pos(cur.line, cur.ch - 2), cur, \"+transpose\");\n            } else if (cur.line > cm.doc.first) {\n              var prev = getLine(cm.doc, cur.line - 1).text;\n              if (prev)\n                cm.replaceRange(line.charAt(0) + cm.doc.lineSeparator() +\n                                prev.charAt(prev.length - 1),\n                                Pos(cur.line - 1, prev.length - 1), Pos(cur.line, 1), \"+transpose\");\n            }\n          }\n          newSel.push(new Range(cur, cur));\n        }\n        cm.setSelections(newSel);\n      });\n    },\n    newlineAndIndent: function(cm) {\n      runInOp(cm, function() {\n        var len = cm.listSelections().length;\n        for (var i = 0; i < len; i++) {\n          var range = cm.listSelections()[i];\n          cm.replaceRange(cm.doc.lineSeparator(), range.anchor, range.head, \"+input\");\n          cm.indentLine(range.from().line + 1, null, true);\n        }\n        ensureCursorVisible(cm);\n      });\n    },\n    toggleOverwrite: function(cm) {cm.toggleOverwrite();}\n  };\n\n\n  // STANDARD KEYMAPS\n\n  var keyMap = CodeMirror.keyMap = {};\n\n  keyMap.basic = {\n    \"Left\": \"goCharLeft\", \"Right\": \"goCharRight\", \"Up\": \"goLineUp\", \"Down\": \"goLineDown\",\n    \"End\": \"goLineEnd\", \"Home\": \"goLineStartSmart\", \"PageUp\": \"goPageUp\", \"PageDown\": \"goPageDown\",\n    \"Delete\": \"delCharAfter\", \"Backspace\": \"delCharBefore\", \"Shift-Backspace\": \"delCharBefore\",\n    \"Tab\": \"defaultTab\", \"Shift-Tab\": \"indentAuto\",\n    \"Enter\": \"newlineAndIndent\", \"Insert\": \"toggleOverwrite\",\n    \"Esc\": \"singleSelection\"\n  };\n  // Note that the save and find-related commands aren't defined by\n  // default. User code or addons can define them. Unknown commands\n  // are simply ignored.\n  keyMap.pcDefault = {\n    \"Ctrl-A\": \"selectAll\", \"Ctrl-D\": \"deleteLine\", \"Ctrl-Z\": \"undo\", \"Shift-Ctrl-Z\": \"redo\", \"Ctrl-Y\": \"redo\",\n    \"Ctrl-Home\": \"goDocStart\", \"Ctrl-End\": \"goDocEnd\", \"Ctrl-Up\": \"goLineUp\", \"Ctrl-Down\": \"goLineDown\",\n    \"Ctrl-Left\": \"goGroupLeft\", \"Ctrl-Right\": \"goGroupRight\", \"Alt-Left\": \"goLineStart\", \"Alt-Right\": \"goLineEnd\",\n    \"Ctrl-Backspace\": \"delGroupBefore\", \"Ctrl-Delete\": \"delGroupAfter\", \"Ctrl-S\": \"save\", \"Ctrl-F\": \"find\",\n    \"Ctrl-G\": \"findNext\", \"Shift-Ctrl-G\": \"findPrev\", \"Shift-Ctrl-F\": \"replace\", \"Shift-Ctrl-R\": \"replaceAll\",\n    \"Ctrl-[\": \"indentLess\", \"Ctrl-]\": \"indentMore\",\n    \"Ctrl-U\": \"undoSelection\", \"Shift-Ctrl-U\": \"redoSelection\", \"Alt-U\": \"redoSelection\",\n    fallthrough: \"basic\"\n  };\n  // Very basic readline/emacs-style bindings, which are standard on Mac.\n  keyMap.emacsy = {\n    \"Ctrl-F\": \"goCharRight\", \"Ctrl-B\": \"goCharLeft\", \"Ctrl-P\": \"goLineUp\", \"Ctrl-N\": \"goLineDown\",\n    \"Alt-F\": \"goWordRight\", \"Alt-B\": \"goWordLeft\", \"Ctrl-A\": \"goLineStart\", \"Ctrl-E\": \"goLineEnd\",\n    \"Ctrl-V\": \"goPageDown\", \"Shift-Ctrl-V\": \"goPageUp\", \"Ctrl-D\": \"delCharAfter\", \"Ctrl-H\": \"delCharBefore\",\n    \"Alt-D\": \"delWordAfter\", \"Alt-Backspace\": \"delWordBefore\", \"Ctrl-K\": \"killLine\", \"Ctrl-T\": \"transposeChars\"\n  };\n  keyMap.macDefault = {\n    \"Cmd-A\": \"selectAll\", \"Cmd-D\": \"deleteLine\", \"Cmd-Z\": \"undo\", \"Shift-Cmd-Z\": \"redo\", \"Cmd-Y\": \"redo\",\n    \"Cmd-Home\": \"goDocStart\", \"Cmd-Up\": \"goDocStart\", \"Cmd-End\": \"goDocEnd\", \"Cmd-Down\": \"goDocEnd\", \"Alt-Left\": \"goGroupLeft\",\n    \"Alt-Right\": \"goGroupRight\", \"Cmd-Left\": \"goLineLeft\", \"Cmd-Right\": \"goLineRight\", \"Alt-Backspace\": \"delGroupBefore\",\n    \"Ctrl-Alt-Backspace\": \"delGroupAfter\", \"Alt-Delete\": \"delGroupAfter\", \"Cmd-S\": \"save\", \"Cmd-F\": \"find\",\n    \"Cmd-G\": \"findNext\", \"Shift-Cmd-G\": \"findPrev\", \"Cmd-Alt-F\": \"replace\", \"Shift-Cmd-Alt-F\": \"replaceAll\",\n    \"Cmd-[\": \"indentLess\", \"Cmd-]\": \"indentMore\", \"Cmd-Backspace\": \"delWrappedLineLeft\", \"Cmd-Delete\": \"delWrappedLineRight\",\n    \"Cmd-U\": \"undoSelection\", \"Shift-Cmd-U\": \"redoSelection\", \"Ctrl-Up\": \"goDocStart\", \"Ctrl-Down\": \"goDocEnd\",\n    fallthrough: [\"basic\", \"emacsy\"]\n  };\n  keyMap[\"default\"] = mac ? keyMap.macDefault : keyMap.pcDefault;\n\n  // KEYMAP DISPATCH\n\n  function normalizeKeyName(name) {\n    var parts = name.split(/-(?!$)/), name = parts[parts.length - 1];\n    var alt, ctrl, shift, cmd;\n    for (var i = 0; i < parts.length - 1; i++) {\n      var mod = parts[i];\n      if (/^(cmd|meta|m)$/i.test(mod)) cmd = true;\n      else if (/^a(lt)?$/i.test(mod)) alt = true;\n      else if (/^(c|ctrl|control)$/i.test(mod)) ctrl = true;\n      else if (/^s(hift)$/i.test(mod)) shift = true;\n      else throw new Error(\"Unrecognized modifier name: \" + mod);\n    }\n    if (alt) name = \"Alt-\" + name;\n    if (ctrl) name = \"Ctrl-\" + name;\n    if (cmd) name = \"Cmd-\" + name;\n    if (shift) name = \"Shift-\" + name;\n    return name;\n  }\n\n  // This is a kludge to keep keymaps mostly working as raw objects\n  // (backwards compatibility) while at the same time support features\n  // like normalization and multi-stroke key bindings. It compiles a\n  // new normalized keymap, and then updates the old object to reflect\n  // this.\n  CodeMirror.normalizeKeyMap = function(keymap) {\n    var copy = {};\n    for (var keyname in keymap) if (keymap.hasOwnProperty(keyname)) {\n      var value = keymap[keyname];\n      if (/^(name|fallthrough|(de|at)tach)$/.test(keyname)) continue;\n      if (value == \"...\") { delete keymap[keyname]; continue; }\n\n      var keys = map(keyname.split(\" \"), normalizeKeyName);\n      for (var i = 0; i < keys.length; i++) {\n        var val, name;\n        if (i == keys.length - 1) {\n          name = keys.join(\" \");\n          val = value;\n        } else {\n          name = keys.slice(0, i + 1).join(\" \");\n          val = \"...\";\n        }\n        var prev = copy[name];\n        if (!prev) copy[name] = val;\n        else if (prev != val) throw new Error(\"Inconsistent bindings for \" + name);\n      }\n      delete keymap[keyname];\n    }\n    for (var prop in copy) keymap[prop] = copy[prop];\n    return keymap;\n  };\n\n  var lookupKey = CodeMirror.lookupKey = function(key, map, handle, context) {\n    map = getKeyMap(map);\n    var found = map.call ? map.call(key, context) : map[key];\n    if (found === false) return \"nothing\";\n    if (found === \"...\") return \"multi\";\n    if (found != null && handle(found)) return \"handled\";\n\n    if (map.fallthrough) {\n      if (Object.prototype.toString.call(map.fallthrough) != \"[object Array]\")\n        return lookupKey(key, map.fallthrough, handle, context);\n      for (var i = 0; i < map.fallthrough.length; i++) {\n        var result = lookupKey(key, map.fallthrough[i], handle, context);\n        if (result) return result;\n      }\n    }\n  };\n\n  // Modifier key presses don't count as 'real' key presses for the\n  // purpose of keymap fallthrough.\n  var isModifierKey = CodeMirror.isModifierKey = function(value) {\n    var name = typeof value == \"string\" ? value : keyNames[value.keyCode];\n    return name == \"Ctrl\" || name == \"Alt\" || name == \"Shift\" || name == \"Mod\";\n  };\n\n  // Look up the name of a key as indicated by an event object.\n  var keyName = CodeMirror.keyName = function(event, noShift) {\n    if (presto && event.keyCode == 34 && event[\"char\"]) return false;\n    var base = keyNames[event.keyCode], name = base;\n    if (name == null || event.altGraphKey) return false;\n    if (event.altKey && base != \"Alt\") name = \"Alt-\" + name;\n    if ((flipCtrlCmd ? event.metaKey : event.ctrlKey) && base != \"Ctrl\") name = \"Ctrl-\" + name;\n    if ((flipCtrlCmd ? event.ctrlKey : event.metaKey) && base != \"Cmd\") name = \"Cmd-\" + name;\n    if (!noShift && event.shiftKey && base != \"Shift\") name = \"Shift-\" + name;\n    return name;\n  };\n\n  function getKeyMap(val) {\n    return typeof val == \"string\" ? keyMap[val] : val;\n  }\n\n  // FROMTEXTAREA\n\n  CodeMirror.fromTextArea = function(textarea, options) {\n    options = options ? copyObj(options) : {};\n    options.value = textarea.value;\n    if (!options.tabindex && textarea.tabIndex)\n      options.tabindex = textarea.tabIndex;\n    if (!options.placeholder && textarea.placeholder)\n      options.placeholder = textarea.placeholder;\n    // Set autofocus to true if this textarea is focused, or if it has\n    // autofocus and no other element is focused.\n    if (options.autofocus == null) {\n      var hasFocus = activeElt();\n      options.autofocus = hasFocus == textarea ||\n        textarea.getAttribute(\"autofocus\") != null && hasFocus == document.body;\n    }\n\n    function save() {textarea.value = cm.getValue();}\n    if (textarea.form) {\n      on(textarea.form, \"submit\", save);\n      // Deplorable hack to make the submit method do the right thing.\n      if (!options.leaveSubmitMethodAlone) {\n        var form = textarea.form, realSubmit = form.submit;\n        try {\n          var wrappedSubmit = form.submit = function() {\n            save();\n            form.submit = realSubmit;\n            form.submit();\n            form.submit = wrappedSubmit;\n          };\n        } catch(e) {}\n      }\n    }\n\n    options.finishInit = function(cm) {\n      cm.save = save;\n      cm.getTextArea = function() { return textarea; };\n      cm.toTextArea = function() {\n        cm.toTextArea = isNaN; // Prevent this from being ran twice\n        save();\n        textarea.parentNode.removeChild(cm.getWrapperElement());\n        textarea.style.display = \"\";\n        if (textarea.form) {\n          off(textarea.form, \"submit\", save);\n          if (typeof textarea.form.submit == \"function\")\n            textarea.form.submit = realSubmit;\n        }\n      };\n    };\n\n    textarea.style.display = \"none\";\n    var cm = CodeMirror(function(node) {\n      textarea.parentNode.insertBefore(node, textarea.nextSibling);\n    }, options);\n    return cm;\n  };\n\n  // STRING STREAM\n\n  // Fed to the mode parsers, provides helper functions to make\n  // parsers more succinct.\n\n  var StringStream = CodeMirror.StringStream = function(string, tabSize) {\n    this.pos = this.start = 0;\n    this.string = string;\n    this.tabSize = tabSize || 8;\n    this.lastColumnPos = this.lastColumnValue = 0;\n    this.lineStart = 0;\n  };\n\n  StringStream.prototype = {\n    eol: function() {return this.pos >= this.string.length;},\n    sol: function() {return this.pos == this.lineStart;},\n    peek: function() {return this.string.charAt(this.pos) || undefined;},\n    next: function() {\n      if (this.pos < this.string.length)\n        return this.string.charAt(this.pos++);\n    },\n    eat: function(match) {\n      var ch = this.string.charAt(this.pos);\n      if (typeof match == \"string\") var ok = ch == match;\n      else var ok = ch && (match.test ? match.test(ch) : match(ch));\n      if (ok) {++this.pos; return ch;}\n    },\n    eatWhile: function(match) {\n      var start = this.pos;\n      while (this.eat(match)){}\n      return this.pos > start;\n    },\n    eatSpace: function() {\n      var start = this.pos;\n      while (/[\\s\\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos;\n      return this.pos > start;\n    },\n    skipToEnd: function() {this.pos = this.string.length;},\n    skipTo: function(ch) {\n      var found = this.string.indexOf(ch, this.pos);\n      if (found > -1) {this.pos = found; return true;}\n    },\n    backUp: function(n) {this.pos -= n;},\n    column: function() {\n      if (this.lastColumnPos < this.start) {\n        this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue);\n        this.lastColumnPos = this.start;\n      }\n      return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0);\n    },\n    indentation: function() {\n      return countColumn(this.string, null, this.tabSize) -\n        (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0);\n    },\n    match: function(pattern, consume, caseInsensitive) {\n      if (typeof pattern == \"string\") {\n        var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};\n        var substr = this.string.substr(this.pos, pattern.length);\n        if (cased(substr) == cased(pattern)) {\n          if (consume !== false) this.pos += pattern.length;\n          return true;\n        }\n      } else {\n        var match = this.string.slice(this.pos).match(pattern);\n        if (match && match.index > 0) return null;\n        if (match && consume !== false) this.pos += match[0].length;\n        return match;\n      }\n    },\n    current: function(){return this.string.slice(this.start, this.pos);},\n    hideFirstChars: function(n, inner) {\n      this.lineStart += n;\n      try { return inner(); }\n      finally { this.lineStart -= n; }\n    }\n  };\n\n  // TEXTMARKERS\n\n  // Created with markText and setBookmark methods. A TextMarker is a\n  // handle that can be used to clear or find a marked position in the\n  // document. Line objects hold arrays (markedSpans) containing\n  // {from, to, marker} object pointing to such marker objects, and\n  // indicating that such a marker is present on that line. Multiple\n  // lines may point to the same marker when it spans across lines.\n  // The spans will have null for their from/to properties when the\n  // marker continues beyond the start/end of the line. Markers have\n  // links back to the lines they currently touch.\n\n  var nextMarkerId = 0;\n\n  var TextMarker = CodeMirror.TextMarker = function(doc, type) {\n    this.lines = [];\n    this.type = type;\n    this.doc = doc;\n    this.id = ++nextMarkerId;\n  };\n  eventMixin(TextMarker);\n\n  // Clear the marker.\n  TextMarker.prototype.clear = function() {\n    if (this.explicitlyCleared) return;\n    var cm = this.doc.cm, withOp = cm && !cm.curOp;\n    if (withOp) startOperation(cm);\n    if (hasHandler(this, \"clear\")) {\n      var found = this.find();\n      if (found) signalLater(this, \"clear\", found.from, found.to);\n    }\n    var min = null, max = null;\n    for (var i = 0; i < this.lines.length; ++i) {\n      var line = this.lines[i];\n      var span = getMarkedSpanFor(line.markedSpans, this);\n      if (cm && !this.collapsed) regLineChange(cm, lineNo(line), \"text\");\n      else if (cm) {\n        if (span.to != null) max = lineNo(line);\n        if (span.from != null) min = lineNo(line);\n      }\n      line.markedSpans = removeMarkedSpan(line.markedSpans, span);\n      if (span.from == null && this.collapsed && !lineIsHidden(this.doc, line) && cm)\n        updateLineHeight(line, textHeight(cm.display));\n    }\n    if (cm && this.collapsed && !cm.options.lineWrapping) for (var i = 0; i < this.lines.length; ++i) {\n      var visual = visualLine(this.lines[i]), len = lineLength(visual);\n      if (len > cm.display.maxLineLength) {\n        cm.display.maxLine = visual;\n        cm.display.maxLineLength = len;\n        cm.display.maxLineChanged = true;\n      }\n    }\n\n    if (min != null && cm && this.collapsed) regChange(cm, min, max + 1);\n    this.lines.length = 0;\n    this.explicitlyCleared = true;\n    if (this.atomic && this.doc.cantEdit) {\n      this.doc.cantEdit = false;\n      if (cm) reCheckSelection(cm.doc);\n    }\n    if (cm) signalLater(cm, \"markerCleared\", cm, this);\n    if (withOp) endOperation(cm);\n    if (this.parent) this.parent.clear();\n  };\n\n  // Find the position of the marker in the document. Returns a {from,\n  // to} object by default. Side can be passed to get a specific side\n  // -- 0 (both), -1 (left), or 1 (right). When lineObj is true, the\n  // Pos objects returned contain a line object, rather than a line\n  // number (used to prevent looking up the same line twice).\n  TextMarker.prototype.find = function(side, lineObj) {\n    if (side == null && this.type == \"bookmark\") side = 1;\n    var from, to;\n    for (var i = 0; i < this.lines.length; ++i) {\n      var line = this.lines[i];\n      var span = getMarkedSpanFor(line.markedSpans, this);\n      if (span.from != null) {\n        from = Pos(lineObj ? line : lineNo(line), span.from);\n        if (side == -1) return from;\n      }\n      if (span.to != null) {\n        to = Pos(lineObj ? line : lineNo(line), span.to);\n        if (side == 1) return to;\n      }\n    }\n    return from && {from: from, to: to};\n  };\n\n  // Signals that the marker's widget changed, and surrounding layout\n  // should be recomputed.\n  TextMarker.prototype.changed = function() {\n    var pos = this.find(-1, true), widget = this, cm = this.doc.cm;\n    if (!pos || !cm) return;\n    runInOp(cm, function() {\n      var line = pos.line, lineN = lineNo(pos.line);\n      var view = findViewForLine(cm, lineN);\n      if (view) {\n        clearLineMeasurementCacheFor(view);\n        cm.curOp.selectionChanged = cm.curOp.forceUpdate = true;\n      }\n      cm.curOp.updateMaxLine = true;\n      if (!lineIsHidden(widget.doc, line) && widget.height != null) {\n        var oldHeight = widget.height;\n        widget.height = null;\n        var dHeight = widgetHeight(widget) - oldHeight;\n        if (dHeight)\n          updateLineHeight(line, line.height + dHeight);\n      }\n    });\n  };\n\n  TextMarker.prototype.attachLine = function(line) {\n    if (!this.lines.length && this.doc.cm) {\n      var op = this.doc.cm.curOp;\n      if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1)\n        (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this);\n    }\n    this.lines.push(line);\n  };\n  TextMarker.prototype.detachLine = function(line) {\n    this.lines.splice(indexOf(this.lines, line), 1);\n    if (!this.lines.length && this.doc.cm) {\n      var op = this.doc.cm.curOp;\n      (op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this);\n    }\n  };\n\n  // Collapsed markers have unique ids, in order to be able to order\n  // them, which is needed for uniquely determining an outer marker\n  // when they overlap (they may nest, but not partially overlap).\n  var nextMarkerId = 0;\n\n  // Create a marker, wire it up to the right lines, and\n  function markText(doc, from, to, options, type) {\n    // Shared markers (across linked documents) are handled separately\n    // (markTextShared will call out to this again, once per\n    // document).\n    if (options && options.shared) return markTextShared(doc, from, to, options, type);\n    // Ensure we are in an operation.\n    if (doc.cm && !doc.cm.curOp) return operation(doc.cm, markText)(doc, from, to, options, type);\n\n    var marker = new TextMarker(doc, type), diff = cmp(from, to);\n    if (options) copyObj(options, marker, false);\n    // Don't connect empty markers unless clearWhenEmpty is false\n    if (diff > 0 || diff == 0 && marker.clearWhenEmpty !== false)\n      return marker;\n    if (marker.replacedWith) {\n      // Showing up as a widget implies collapsed (widget replaces text)\n      marker.collapsed = true;\n      marker.widgetNode = elt(\"span\", [marker.replacedWith], \"CodeMirror-widget\");\n      if (!options.handleMouseEvents) marker.widgetNode.setAttribute(\"cm-ignore-events\", \"true\");\n      if (options.insertLeft) marker.widgetNode.insertLeft = true;\n    }\n    if (marker.collapsed) {\n      if (conflictingCollapsedRange(doc, from.line, from, to, marker) ||\n          from.line != to.line && conflictingCollapsedRange(doc, to.line, from, to, marker))\n        throw new Error(\"Inserting collapsed marker partially overlapping an existing one\");\n      sawCollapsedSpans = true;\n    }\n\n    if (marker.addToHistory)\n      addChangeToHistory(doc, {from: from, to: to, origin: \"markText\"}, doc.sel, NaN);\n\n    var curLine = from.line, cm = doc.cm, updateMaxLine;\n    doc.iter(curLine, to.line + 1, function(line) {\n      if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(line) == cm.display.maxLine)\n        updateMaxLine = true;\n      if (marker.collapsed && curLine != from.line) updateLineHeight(line, 0);\n      addMarkedSpan(line, new MarkedSpan(marker,\n                                         curLine == from.line ? from.ch : null,\n                                         curLine == to.line ? to.ch : null));\n      ++curLine;\n    });\n    // lineIsHidden depends on the presence of the spans, so needs a second pass\n    if (marker.collapsed) doc.iter(from.line, to.line + 1, function(line) {\n      if (lineIsHidden(doc, line)) updateLineHeight(line, 0);\n    });\n\n    if (marker.clearOnEnter) on(marker, \"beforeCursorEnter\", function() { marker.clear(); });\n\n    if (marker.readOnly) {\n      sawReadOnlySpans = true;\n      if (doc.history.done.length || doc.history.undone.length)\n        doc.clearHistory();\n    }\n    if (marker.collapsed) {\n      marker.id = ++nextMarkerId;\n      marker.atomic = true;\n    }\n    if (cm) {\n      // Sync editor state\n      if (updateMaxLine) cm.curOp.updateMaxLine = true;\n      if (marker.collapsed)\n        regChange(cm, from.line, to.line + 1);\n      else if (marker.className || marker.title || marker.startStyle || marker.endStyle || marker.css)\n        for (var i = from.line; i <= to.line; i++) regLineChange(cm, i, \"text\");\n      if (marker.atomic) reCheckSelection(cm.doc);\n      signalLater(cm, \"markerAdded\", cm, marker);\n    }\n    return marker;\n  }\n\n  // SHARED TEXTMARKERS\n\n  // A shared marker spans multiple linked documents. It is\n  // implemented as a meta-marker-object controlling multiple normal\n  // markers.\n  var SharedTextMarker = CodeMirror.SharedTextMarker = function(markers, primary) {\n    this.markers = markers;\n    this.primary = primary;\n    for (var i = 0; i < markers.length; ++i)\n      markers[i].parent = this;\n  };\n  eventMixin(SharedTextMarker);\n\n  SharedTextMarker.prototype.clear = function() {\n    if (this.explicitlyCleared) return;\n    this.explicitlyCleared = true;\n    for (var i = 0; i < this.markers.length; ++i)\n      this.markers[i].clear();\n    signalLater(this, \"clear\");\n  };\n  SharedTextMarker.prototype.find = function(side, lineObj) {\n    return this.primary.find(side, lineObj);\n  };\n\n  function markTextShared(doc, from, to, options, type) {\n    options = copyObj(options);\n    options.shared = false;\n    var markers = [markText(doc, from, to, options, type)], primary = markers[0];\n    var widget = options.widgetNode;\n    linkedDocs(doc, function(doc) {\n      if (widget) options.widgetNode = widget.cloneNode(true);\n      markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type));\n      for (var i = 0; i < doc.linked.length; ++i)\n        if (doc.linked[i].isParent) return;\n      primary = lst(markers);\n    });\n    return new SharedTextMarker(markers, primary);\n  }\n\n  function findSharedMarkers(doc) {\n    return doc.findMarks(Pos(doc.first, 0), doc.clipPos(Pos(doc.lastLine())),\n                         function(m) { return m.parent; });\n  }\n\n  function copySharedMarkers(doc, markers) {\n    for (var i = 0; i < markers.length; i++) {\n      var marker = markers[i], pos = marker.find();\n      var mFrom = doc.clipPos(pos.from), mTo = doc.clipPos(pos.to);\n      if (cmp(mFrom, mTo)) {\n        var subMark = markText(doc, mFrom, mTo, marker.primary, marker.primary.type);\n        marker.markers.push(subMark);\n        subMark.parent = marker;\n      }\n    }\n  }\n\n  function detachSharedMarkers(markers) {\n    for (var i = 0; i < markers.length; i++) {\n      var marker = markers[i], linked = [marker.primary.doc];;\n      linkedDocs(marker.primary.doc, function(d) { linked.push(d); });\n      for (var j = 0; j < marker.markers.length; j++) {\n        var subMarker = marker.markers[j];\n        if (indexOf(linked, subMarker.doc) == -1) {\n          subMarker.parent = null;\n          marker.markers.splice(j--, 1);\n        }\n      }\n    }\n  }\n\n  // TEXTMARKER SPANS\n\n  function MarkedSpan(marker, from, to) {\n    this.marker = marker;\n    this.from = from; this.to = to;\n  }\n\n  // Search an array of spans for a span matching the given marker.\n  function getMarkedSpanFor(spans, marker) {\n    if (spans) for (var i = 0; i < spans.length; ++i) {\n      var span = spans[i];\n      if (span.marker == marker) return span;\n    }\n  }\n  // Remove a span from an array, returning undefined if no spans are\n  // left (we don't store arrays for lines without spans).\n  function removeMarkedSpan(spans, span) {\n    for (var r, i = 0; i < spans.length; ++i)\n      if (spans[i] != span) (r || (r = [])).push(spans[i]);\n    return r;\n  }\n  // Add a span to a line.\n  function addMarkedSpan(line, span) {\n    line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span];\n    span.marker.attachLine(line);\n  }\n\n  // Used for the algorithm that adjusts markers for a change in the\n  // document. These functions cut an array of spans at a given\n  // character position, returning an array of remaining chunks (or\n  // undefined if nothing remains).\n  function markedSpansBefore(old, startCh, isInsert) {\n    if (old) for (var i = 0, nw; i < old.length; ++i) {\n      var span = old[i], marker = span.marker;\n      var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh);\n      if (startsBefore || span.from == startCh && marker.type == \"bookmark\" && (!isInsert || !span.marker.insertLeft)) {\n        var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh);\n        (nw || (nw = [])).push(new MarkedSpan(marker, span.from, endsAfter ? null : span.to));\n      }\n    }\n    return nw;\n  }\n  function markedSpansAfter(old, endCh, isInsert) {\n    if (old) for (var i = 0, nw; i < old.length; ++i) {\n      var span = old[i], marker = span.marker;\n      var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh);\n      if (endsAfter || span.from == endCh && marker.type == \"bookmark\" && (!isInsert || span.marker.insertLeft)) {\n        var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh);\n        (nw || (nw = [])).push(new MarkedSpan(marker, startsBefore ? null : span.from - endCh,\n                                              span.to == null ? null : span.to - endCh));\n      }\n    }\n    return nw;\n  }\n\n  // Given a change object, compute the new set of marker spans that\n  // cover the line in which the change took place. Removes spans\n  // entirely within the change, reconnects spans belonging to the\n  // same marker that appear on both sides of the change, and cuts off\n  // spans partially within the change. Returns an array of span\n  // arrays with one element for each line in (after) the change.\n  function stretchSpansOverChange(doc, change) {\n    if (change.full) return null;\n    var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans;\n    var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans;\n    if (!oldFirst && !oldLast) return null;\n\n    var startCh = change.from.ch, endCh = change.to.ch, isInsert = cmp(change.from, change.to) == 0;\n    // Get the spans that 'stick out' on both sides\n    var first = markedSpansBefore(oldFirst, startCh, isInsert);\n    var last = markedSpansAfter(oldLast, endCh, isInsert);\n\n    // Next, merge those two ends\n    var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0);\n    if (first) {\n      // Fix up .to properties of first\n      for (var i = 0; i < first.length; ++i) {\n        var span = first[i];\n        if (span.to == null) {\n          var found = getMarkedSpanFor(last, span.marker);\n          if (!found) span.to = startCh;\n          else if (sameLine) span.to = found.to == null ? null : found.to + offset;\n        }\n      }\n    }\n    if (last) {\n      // Fix up .from in last (or move them into first in case of sameLine)\n      for (var i = 0; i < last.length; ++i) {\n        var span = last[i];\n        if (span.to != null) span.to += offset;\n        if (span.from == null) {\n          var found = getMarkedSpanFor(first, span.marker);\n          if (!found) {\n            span.from = offset;\n            if (sameLine) (first || (first = [])).push(span);\n          }\n        } else {\n          span.from += offset;\n          if (sameLine) (first || (first = [])).push(span);\n        }\n      }\n    }\n    // Make sure we didn't create any zero-length spans\n    if (first) first = clearEmptySpans(first);\n    if (last && last != first) last = clearEmptySpans(last);\n\n    var newMarkers = [first];\n    if (!sameLine) {\n      // Fill gap with whole-line-spans\n      var gap = change.text.length - 2, gapMarkers;\n      if (gap > 0 && first)\n        for (var i = 0; i < first.length; ++i)\n          if (first[i].to == null)\n            (gapMarkers || (gapMarkers = [])).push(new MarkedSpan(first[i].marker, null, null));\n      for (var i = 0; i < gap; ++i)\n        newMarkers.push(gapMarkers);\n      newMarkers.push(last);\n    }\n    return newMarkers;\n  }\n\n  // Remove spans that are empty and don't have a clearWhenEmpty\n  // option of false.\n  function clearEmptySpans(spans) {\n    for (var i = 0; i < spans.length; ++i) {\n      var span = spans[i];\n      if (span.from != null && span.from == span.to && span.marker.clearWhenEmpty !== false)\n        spans.splice(i--, 1);\n    }\n    if (!spans.length) return null;\n    return spans;\n  }\n\n  // Used for un/re-doing changes from the history. Combines the\n  // result of computing the existing spans with the set of spans that\n  // existed in the history (so that deleting around a span and then\n  // undoing brings back the span).\n  function mergeOldSpans(doc, change) {\n    var old = getOldSpans(doc, change);\n    var stretched = stretchSpansOverChange(doc, change);\n    if (!old) return stretched;\n    if (!stretched) return old;\n\n    for (var i = 0; i < old.length; ++i) {\n      var oldCur = old[i], stretchCur = stretched[i];\n      if (oldCur && stretchCur) {\n        spans: for (var j = 0; j < stretchCur.length; ++j) {\n          var span = stretchCur[j];\n          for (var k = 0; k < oldCur.length; ++k)\n            if (oldCur[k].marker == span.marker) continue spans;\n          oldCur.push(span);\n        }\n      } else if (stretchCur) {\n        old[i] = stretchCur;\n      }\n    }\n    return old;\n  }\n\n  // Used to 'clip' out readOnly ranges when making a change.\n  function removeReadOnlyRanges(doc, from, to) {\n    var markers = null;\n    doc.iter(from.line, to.line + 1, function(line) {\n      if (line.markedSpans) for (var i = 0; i < line.markedSpans.length; ++i) {\n        var mark = line.markedSpans[i].marker;\n        if (mark.readOnly && (!markers || indexOf(markers, mark) == -1))\n          (markers || (markers = [])).push(mark);\n      }\n    });\n    if (!markers) return null;\n    var parts = [{from: from, to: to}];\n    for (var i = 0; i < markers.length; ++i) {\n      var mk = markers[i], m = mk.find(0);\n      for (var j = 0; j < parts.length; ++j) {\n        var p = parts[j];\n        if (cmp(p.to, m.from) < 0 || cmp(p.from, m.to) > 0) continue;\n        var newParts = [j, 1], dfrom = cmp(p.from, m.from), dto = cmp(p.to, m.to);\n        if (dfrom < 0 || !mk.inclusiveLeft && !dfrom)\n          newParts.push({from: p.from, to: m.from});\n        if (dto > 0 || !mk.inclusiveRight && !dto)\n          newParts.push({from: m.to, to: p.to});\n        parts.splice.apply(parts, newParts);\n        j += newParts.length - 1;\n      }\n    }\n    return parts;\n  }\n\n  // Connect or disconnect spans from a line.\n  function detachMarkedSpans(line) {\n    var spans = line.markedSpans;\n    if (!spans) return;\n    for (var i = 0; i < spans.length; ++i)\n      spans[i].marker.detachLine(line);\n    line.markedSpans = null;\n  }\n  function attachMarkedSpans(line, spans) {\n    if (!spans) return;\n    for (var i = 0; i < spans.length; ++i)\n      spans[i].marker.attachLine(line);\n    line.markedSpans = spans;\n  }\n\n  // Helpers used when computing which overlapping collapsed span\n  // counts as the larger one.\n  function extraLeft(marker) { return marker.inclusiveLeft ? -1 : 0; }\n  function extraRight(marker) { return marker.inclusiveRight ? 1 : 0; }\n\n  // Returns a number indicating which of two overlapping collapsed\n  // spans is larger (and thus includes the other). Falls back to\n  // comparing ids when the spans cover exactly the same range.\n  function compareCollapsedMarkers(a, b) {\n    var lenDiff = a.lines.length - b.lines.length;\n    if (lenDiff != 0) return lenDiff;\n    var aPos = a.find(), bPos = b.find();\n    var fromCmp = cmp(aPos.from, bPos.from) || extraLeft(a) - extraLeft(b);\n    if (fromCmp) return -fromCmp;\n    var toCmp = cmp(aPos.to, bPos.to) || extraRight(a) - extraRight(b);\n    if (toCmp) return toCmp;\n    return b.id - a.id;\n  }\n\n  // Find out whether a line ends or starts in a collapsed span. If\n  // so, return the marker for that span.\n  function collapsedSpanAtSide(line, start) {\n    var sps = sawCollapsedSpans && line.markedSpans, found;\n    if (sps) for (var sp, i = 0; i < sps.length; ++i) {\n      sp = sps[i];\n      if (sp.marker.collapsed && (start ? sp.from : sp.to) == null &&\n          (!found || compareCollapsedMarkers(found, sp.marker) < 0))\n        found = sp.marker;\n    }\n    return found;\n  }\n  function collapsedSpanAtStart(line) { return collapsedSpanAtSide(line, true); }\n  function collapsedSpanAtEnd(line) { return collapsedSpanAtSide(line, false); }\n\n  // Test whether there exists a collapsed span that partially\n  // overlaps (covers the start or end, but not both) of a new span.\n  // Such overlap is not allowed.\n  function conflictingCollapsedRange(doc, lineNo, from, to, marker) {\n    var line = getLine(doc, lineNo);\n    var sps = sawCollapsedSpans && line.markedSpans;\n    if (sps) for (var i = 0; i < sps.length; ++i) {\n      var sp = sps[i];\n      if (!sp.marker.collapsed) continue;\n      var found = sp.marker.find(0);\n      var fromCmp = cmp(found.from, from) || extraLeft(sp.marker) - extraLeft(marker);\n      var toCmp = cmp(found.to, to) || extraRight(sp.marker) - extraRight(marker);\n      if (fromCmp >= 0 && toCmp <= 0 || fromCmp <= 0 && toCmp >= 0) continue;\n      if (fromCmp <= 0 && (cmp(found.to, from) > 0 || (sp.marker.inclusiveRight && marker.inclusiveLeft)) ||\n          fromCmp >= 0 && (cmp(found.from, to) < 0 || (sp.marker.inclusiveLeft && marker.inclusiveRight)))\n        return true;\n    }\n  }\n\n  // A visual line is a line as drawn on the screen. Folding, for\n  // example, can cause multiple logical lines to appear on the same\n  // visual line. This finds the start of the visual line that the\n  // given line is part of (usually that is the line itself).\n  function visualLine(line) {\n    var merged;\n    while (merged = collapsedSpanAtStart(line))\n      line = merged.find(-1, true).line;\n    return line;\n  }\n\n  // Returns an array of logical lines that continue the visual line\n  // started by the argument, or undefined if there are no such lines.\n  function visualLineContinued(line) {\n    var merged, lines;\n    while (merged = collapsedSpanAtEnd(line)) {\n      line = merged.find(1, true).line;\n      (lines || (lines = [])).push(line);\n    }\n    return lines;\n  }\n\n  // Get the line number of the start of the visual line that the\n  // given line number is part of.\n  function visualLineNo(doc, lineN) {\n    var line = getLine(doc, lineN), vis = visualLine(line);\n    if (line == vis) return lineN;\n    return lineNo(vis);\n  }\n  // Get the line number of the start of the next visual line after\n  // the given line.\n  function visualLineEndNo(doc, lineN) {\n    if (lineN > doc.lastLine()) return lineN;\n    var line = getLine(doc, lineN), merged;\n    if (!lineIsHidden(doc, line)) return lineN;\n    while (merged = collapsedSpanAtEnd(line))\n      line = merged.find(1, true).line;\n    return lineNo(line) + 1;\n  }\n\n  // Compute whether a line is hidden. Lines count as hidden when they\n  // are part of a visual line that starts with another line, or when\n  // they are entirely covered by collapsed, non-widget span.\n  function lineIsHidden(doc, line) {\n    var sps = sawCollapsedSpans && line.markedSpans;\n    if (sps) for (var sp, i = 0; i < sps.length; ++i) {\n      sp = sps[i];\n      if (!sp.marker.collapsed) continue;\n      if (sp.from == null) return true;\n      if (sp.marker.widgetNode) continue;\n      if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp))\n        return true;\n    }\n  }\n  function lineIsHiddenInner(doc, line, span) {\n    if (span.to == null) {\n      var end = span.marker.find(1, true);\n      return lineIsHiddenInner(doc, end.line, getMarkedSpanFor(end.line.markedSpans, span.marker));\n    }\n    if (span.marker.inclusiveRight && span.to == line.text.length)\n      return true;\n    for (var sp, i = 0; i < line.markedSpans.length; ++i) {\n      sp = line.markedSpans[i];\n      if (sp.marker.collapsed && !sp.marker.widgetNode && sp.from == span.to &&\n          (sp.to == null || sp.to != span.from) &&\n          (sp.marker.inclusiveLeft || span.marker.inclusiveRight) &&\n          lineIsHiddenInner(doc, line, sp)) return true;\n    }\n  }\n\n  // LINE WIDGETS\n\n  // Line widgets are block elements displayed above or below a line.\n\n  var LineWidget = CodeMirror.LineWidget = function(doc, node, options) {\n    if (options) for (var opt in options) if (options.hasOwnProperty(opt))\n      this[opt] = options[opt];\n    this.doc = doc;\n    this.node = node;\n  };\n  eventMixin(LineWidget);\n\n  function adjustScrollWhenAboveVisible(cm, line, diff) {\n    if (heightAtLine(line) < ((cm.curOp && cm.curOp.scrollTop) || cm.doc.scrollTop))\n      addToScrollPos(cm, null, diff);\n  }\n\n  LineWidget.prototype.clear = function() {\n    var cm = this.doc.cm, ws = this.line.widgets, line = this.line, no = lineNo(line);\n    if (no == null || !ws) return;\n    for (var i = 0; i < ws.length; ++i) if (ws[i] == this) ws.splice(i--, 1);\n    if (!ws.length) line.widgets = null;\n    var height = widgetHeight(this);\n    updateLineHeight(line, Math.max(0, line.height - height));\n    if (cm) runInOp(cm, function() {\n      adjustScrollWhenAboveVisible(cm, line, -height);\n      regLineChange(cm, no, \"widget\");\n    });\n  };\n  LineWidget.prototype.changed = function() {\n    var oldH = this.height, cm = this.doc.cm, line = this.line;\n    this.height = null;\n    var diff = widgetHeight(this) - oldH;\n    if (!diff) return;\n    updateLineHeight(line, line.height + diff);\n    if (cm) runInOp(cm, function() {\n      cm.curOp.forceUpdate = true;\n      adjustScrollWhenAboveVisible(cm, line, diff);\n    });\n  };\n\n  function widgetHeight(widget) {\n    if (widget.height != null) return widget.height;\n    var cm = widget.doc.cm;\n    if (!cm) return 0;\n    if (!contains(document.body, widget.node)) {\n      var parentStyle = \"position: relative;\";\n      if (widget.coverGutter)\n        parentStyle += \"margin-left: -\" + cm.display.gutters.offsetWidth + \"px;\";\n      if (widget.noHScroll)\n        parentStyle += \"width: \" + cm.display.wrapper.clientWidth + \"px;\";\n      removeChildrenAndAdd(cm.display.measure, elt(\"div\", [widget.node], null, parentStyle));\n    }\n    return widget.height = widget.node.parentNode.offsetHeight;\n  }\n\n  function addLineWidget(doc, handle, node, options) {\n    var widget = new LineWidget(doc, node, options);\n    var cm = doc.cm;\n    if (cm && widget.noHScroll) cm.display.alignWidgets = true;\n    changeLine(doc, handle, \"widget\", function(line) {\n      var widgets = line.widgets || (line.widgets = []);\n      if (widget.insertAt == null) widgets.push(widget);\n      else widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget);\n      widget.line = line;\n      if (cm && !lineIsHidden(doc, line)) {\n        var aboveVisible = heightAtLine(line) < doc.scrollTop;\n        updateLineHeight(line, line.height + widgetHeight(widget));\n        if (aboveVisible) addToScrollPos(cm, null, widget.height);\n        cm.curOp.forceUpdate = true;\n      }\n      return true;\n    });\n    return widget;\n  }\n\n  // LINE DATA STRUCTURE\n\n  // Line objects. These hold state related to a line, including\n  // highlighting info (the styles array).\n  var Line = CodeMirror.Line = function(text, markedSpans, estimateHeight) {\n    this.text = text;\n    attachMarkedSpans(this, markedSpans);\n    this.height = estimateHeight ? estimateHeight(this) : 1;\n  };\n  eventMixin(Line);\n  Line.prototype.lineNo = function() { return lineNo(this); };\n\n  // Change the content (text, markers) of a line. Automatically\n  // invalidates cached information and tries to re-estimate the\n  // line's height.\n  function updateLine(line, text, markedSpans, estimateHeight) {\n    line.text = text;\n    if (line.stateAfter) line.stateAfter = null;\n    if (line.styles) line.styles = null;\n    if (line.order != null) line.order = null;\n    detachMarkedSpans(line);\n    attachMarkedSpans(line, markedSpans);\n    var estHeight = estimateHeight ? estimateHeight(line) : 1;\n    if (estHeight != line.height) updateLineHeight(line, estHeight);\n  }\n\n  // Detach a line from the document tree and its markers.\n  function cleanUpLine(line) {\n    line.parent = null;\n    detachMarkedSpans(line);\n  }\n\n  function extractLineClasses(type, output) {\n    if (type) for (;;) {\n      var lineClass = type.match(/(?:^|\\s+)line-(background-)?(\\S+)/);\n      if (!lineClass) break;\n      type = type.slice(0, lineClass.index) + type.slice(lineClass.index + lineClass[0].length);\n      var prop = lineClass[1] ? \"bgClass\" : \"textClass\";\n      if (output[prop] == null)\n        output[prop] = lineClass[2];\n      else if (!(new RegExp(\"(?:^|\\s)\" + lineClass[2] + \"(?:$|\\s)\")).test(output[prop]))\n        output[prop] += \" \" + lineClass[2];\n    }\n    return type;\n  }\n\n  function callBlankLine(mode, state) {\n    if (mode.blankLine) return mode.blankLine(state);\n    if (!mode.innerMode) return;\n    var inner = CodeMirror.innerMode(mode, state);\n    if (inner.mode.blankLine) return inner.mode.blankLine(inner.state);\n  }\n\n  function readToken(mode, stream, state, inner) {\n    for (var i = 0; i < 10; i++) {\n      if (inner) inner[0] = CodeMirror.innerMode(mode, state).mode;\n      var style = mode.token(stream, state);\n      if (stream.pos > stream.start) return style;\n    }\n    throw new Error(\"Mode \" + mode.name + \" failed to advance stream.\");\n  }\n\n  // Utility for getTokenAt and getLineTokens\n  function takeToken(cm, pos, precise, asArray) {\n    function getObj(copy) {\n      return {start: stream.start, end: stream.pos,\n              string: stream.current(),\n              type: style || null,\n              state: copy ? copyState(doc.mode, state) : state};\n    }\n\n    var doc = cm.doc, mode = doc.mode, style;\n    pos = clipPos(doc, pos);\n    var line = getLine(doc, pos.line), state = getStateBefore(cm, pos.line, precise);\n    var stream = new StringStream(line.text, cm.options.tabSize), tokens;\n    if (asArray) tokens = [];\n    while ((asArray || stream.pos < pos.ch) && !stream.eol()) {\n      stream.start = stream.pos;\n      style = readToken(mode, stream, state);\n      if (asArray) tokens.push(getObj(true));\n    }\n    return asArray ? tokens : getObj();\n  }\n\n  // Run the given mode's parser over a line, calling f for each token.\n  function runMode(cm, text, mode, state, f, lineClasses, forceToEnd) {\n    var flattenSpans = mode.flattenSpans;\n    if (flattenSpans == null) flattenSpans = cm.options.flattenSpans;\n    var curStart = 0, curStyle = null;\n    var stream = new StringStream(text, cm.options.tabSize), style;\n    var inner = cm.options.addModeClass && [null];\n    if (text == \"\") extractLineClasses(callBlankLine(mode, state), lineClasses);\n    while (!stream.eol()) {\n      if (stream.pos > cm.options.maxHighlightLength) {\n        flattenSpans = false;\n        if (forceToEnd) processLine(cm, text, state, stream.pos);\n        stream.pos = text.length;\n        style = null;\n      } else {\n        style = extractLineClasses(readToken(mode, stream, state, inner), lineClasses);\n      }\n      if (inner) {\n        var mName = inner[0].name;\n        if (mName) style = \"m-\" + (style ? mName + \" \" + style : mName);\n      }\n      if (!flattenSpans || curStyle != style) {\n        while (curStart < stream.start) {\n          curStart = Math.min(stream.start, curStart + 50000);\n          f(curStart, curStyle);\n        }\n        curStyle = style;\n      }\n      stream.start = stream.pos;\n    }\n    while (curStart < stream.pos) {\n      // Webkit seems to refuse to render text nodes longer than 57444 characters\n      var pos = Math.min(stream.pos, curStart + 50000);\n      f(pos, curStyle);\n      curStart = pos;\n    }\n  }\n\n  // Compute a style array (an array starting with a mode generation\n  // -- for invalidation -- followed by pairs of end positions and\n  // style strings), which is used to highlight the tokens on the\n  // line.\n  function highlightLine(cm, line, state, forceToEnd) {\n    // A styles array always starts with a number identifying the\n    // mode/overlays that it is based on (for easy invalidation).\n    var st = [cm.state.modeGen], lineClasses = {};\n    // Compute the base array of styles\n    runMode(cm, line.text, cm.doc.mode, state, function(end, style) {\n      st.push(end, style);\n    }, lineClasses, forceToEnd);\n\n    // Run overlays, adjust style array.\n    for (var o = 0; o < cm.state.overlays.length; ++o) {\n      var overlay = cm.state.overlays[o], i = 1, at = 0;\n      runMode(cm, line.text, overlay.mode, true, function(end, style) {\n        var start = i;\n        // Ensure there's a token end at the current position, and that i points at it\n        while (at < end) {\n          var i_end = st[i];\n          if (i_end > end)\n            st.splice(i, 1, end, st[i+1], i_end);\n          i += 2;\n          at = Math.min(end, i_end);\n        }\n        if (!style) return;\n        if (overlay.opaque) {\n          st.splice(start, i - start, end, \"cm-overlay \" + style);\n          i = start + 2;\n        } else {\n          for (; start < i; start += 2) {\n            var cur = st[start+1];\n            st[start+1] = (cur ? cur + \" \" : \"\") + \"cm-overlay \" + style;\n          }\n        }\n      }, lineClasses);\n    }\n\n    return {styles: st, classes: lineClasses.bgClass || lineClasses.textClass ? lineClasses : null};\n  }\n\n  function getLineStyles(cm, line, updateFrontier) {\n    if (!line.styles || line.styles[0] != cm.state.modeGen) {\n      var state = getStateBefore(cm, lineNo(line));\n      var result = highlightLine(cm, line, line.text.length > cm.options.maxHighlightLength ? copyState(cm.doc.mode, state) : state);\n      line.stateAfter = state;\n      line.styles = result.styles;\n      if (result.classes) line.styleClasses = result.classes;\n      else if (line.styleClasses) line.styleClasses = null;\n      if (updateFrontier === cm.doc.frontier) cm.doc.frontier++;\n    }\n    return line.styles;\n  }\n\n  // Lightweight form of highlight -- proceed over this line and\n  // update state, but don't save a style array. Used for lines that\n  // aren't currently visible.\n  function processLine(cm, text, state, startAt) {\n    var mode = cm.doc.mode;\n    var stream = new StringStream(text, cm.options.tabSize);\n    stream.start = stream.pos = startAt || 0;\n    if (text == \"\") callBlankLine(mode, state);\n    while (!stream.eol()) {\n      readToken(mode, stream, state);\n      stream.start = stream.pos;\n    }\n  }\n\n  // Convert a style as returned by a mode (either null, or a string\n  // containing one or more styles) to a CSS style. This is cached,\n  // and also looks for line-wide styles.\n  var styleToClassCache = {}, styleToClassCacheWithMode = {};\n  function interpretTokenStyle(style, options) {\n    if (!style || /^\\s*$/.test(style)) return null;\n    var cache = options.addModeClass ? styleToClassCacheWithMode : styleToClassCache;\n    return cache[style] ||\n      (cache[style] = style.replace(/\\S+/g, \"cm-$&\"));\n  }\n\n  // Render the DOM representation of the text of a line. Also builds\n  // up a 'line map', which points at the DOM nodes that represent\n  // specific stretches of text, and is used by the measuring code.\n  // The returned object contains the DOM node, this map, and\n  // information about line-wide styles that were set by the mode.\n  function buildLineContent(cm, lineView) {\n    // The padding-right forces the element to have a 'border', which\n    // is needed on Webkit to be able to get line-level bounding\n    // rectangles for it (in measureChar).\n    var content = elt(\"span\", null, null, webkit ? \"padding-right: .1px\" : null);\n    var builder = {pre: elt(\"pre\", [content], \"CodeMirror-line\"), content: content,\n                   col: 0, pos: 0, cm: cm,\n                   splitSpaces: (ie || webkit) && cm.getOption(\"lineWrapping\")};\n    lineView.measure = {};\n\n    // Iterate over the logical lines that make up this visual line.\n    for (var i = 0; i <= (lineView.rest ? lineView.rest.length : 0); i++) {\n      var line = i ? lineView.rest[i - 1] : lineView.line, order;\n      builder.pos = 0;\n      builder.addToken = buildToken;\n      // Optionally wire in some hacks into the token-rendering\n      // algorithm, to deal with browser quirks.\n      if (hasBadBidiRects(cm.display.measure) && (order = getOrder(line)))\n        builder.addToken = buildTokenBadBidi(builder.addToken, order);\n      builder.map = [];\n      var allowFrontierUpdate = lineView != cm.display.externalMeasured && lineNo(line);\n      insertLineContent(line, builder, getLineStyles(cm, line, allowFrontierUpdate));\n      if (line.styleClasses) {\n        if (line.styleClasses.bgClass)\n          builder.bgClass = joinClasses(line.styleClasses.bgClass, builder.bgClass || \"\");\n        if (line.styleClasses.textClass)\n          builder.textClass = joinClasses(line.styleClasses.textClass, builder.textClass || \"\");\n      }\n\n      // Ensure at least a single node is present, for measuring.\n      if (builder.map.length == 0)\n        builder.map.push(0, 0, builder.content.appendChild(zeroWidthElement(cm.display.measure)));\n\n      // Store the map and a cache object for the current logical line\n      if (i == 0) {\n        lineView.measure.map = builder.map;\n        lineView.measure.cache = {};\n      } else {\n        (lineView.measure.maps || (lineView.measure.maps = [])).push(builder.map);\n        (lineView.measure.caches || (lineView.measure.caches = [])).push({});\n      }\n    }\n\n    // See issue #2901\n    if (webkit && /\\bcm-tab\\b/.test(builder.content.lastChild.className))\n      builder.content.className = \"cm-tab-wrap-hack\";\n\n    signal(cm, \"renderLine\", cm, lineView.line, builder.pre);\n    if (builder.pre.className)\n      builder.textClass = joinClasses(builder.pre.className, builder.textClass || \"\");\n\n    return builder;\n  }\n\n  function defaultSpecialCharPlaceholder(ch) {\n    var token = elt(\"span\", \"\\u2022\", \"cm-invalidchar\");\n    token.title = \"\\\\u\" + ch.charCodeAt(0).toString(16);\n    token.setAttribute(\"aria-label\", token.title);\n    return token;\n  }\n\n  // Build up the DOM representation for a single token, and add it to\n  // the line map. Takes care to render special characters separately.\n  function buildToken(builder, text, style, startStyle, endStyle, title, css) {\n    if (!text) return;\n    var displayText = builder.splitSpaces ? text.replace(/ {3,}/g, splitSpaces) : text;\n    var special = builder.cm.state.specialChars, mustWrap = false;\n    if (!special.test(text)) {\n      builder.col += text.length;\n      var content = document.createTextNode(displayText);\n      builder.map.push(builder.pos, builder.pos + text.length, content);\n      if (ie && ie_version < 9) mustWrap = true;\n      builder.pos += text.length;\n    } else {\n      var content = document.createDocumentFragment(), pos = 0;\n      while (true) {\n        special.lastIndex = pos;\n        var m = special.exec(text);\n        var skipped = m ? m.index - pos : text.length - pos;\n        if (skipped) {\n          var txt = document.createTextNode(displayText.slice(pos, pos + skipped));\n          if (ie && ie_version < 9) content.appendChild(elt(\"span\", [txt]));\n          else content.appendChild(txt);\n          builder.map.push(builder.pos, builder.pos + skipped, txt);\n          builder.col += skipped;\n          builder.pos += skipped;\n        }\n        if (!m) break;\n        pos += skipped + 1;\n        if (m[0] == \"\\t\") {\n          var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize;\n          var txt = content.appendChild(elt(\"span\", spaceStr(tabWidth), \"cm-tab\"));\n          txt.setAttribute(\"role\", \"presentation\");\n          txt.setAttribute(\"cm-text\", \"\\t\");\n          builder.col += tabWidth;\n        } else if (m[0] == \"\\r\" || m[0] == \"\\n\") {\n          var txt = content.appendChild(elt(\"span\", m[0] == \"\\r\" ? \"\\u240d\" : \"\\u2424\", \"cm-invalidchar\"));\n          txt.setAttribute(\"cm-text\", m[0]);\n          builder.col += 1;\n        } else {\n          var txt = builder.cm.options.specialCharPlaceholder(m[0]);\n          txt.setAttribute(\"cm-text\", m[0]);\n          if (ie && ie_version < 9) content.appendChild(elt(\"span\", [txt]));\n          else content.appendChild(txt);\n          builder.col += 1;\n        }\n        builder.map.push(builder.pos, builder.pos + 1, txt);\n        builder.pos++;\n      }\n    }\n    if (style || startStyle || endStyle || mustWrap || css) {\n      var fullStyle = style || \"\";\n      if (startStyle) fullStyle += startStyle;\n      if (endStyle) fullStyle += endStyle;\n      var token = elt(\"span\", [content], fullStyle, css);\n      if (title) token.title = title;\n      return builder.content.appendChild(token);\n    }\n    builder.content.appendChild(content);\n  }\n\n  function splitSpaces(old) {\n    var out = \" \";\n    for (var i = 0; i < old.length - 2; ++i) out += i % 2 ? \" \" : \"\\u00a0\";\n    out += \" \";\n    return out;\n  }\n\n  // Work around nonsense dimensions being reported for stretches of\n  // right-to-left text.\n  function buildTokenBadBidi(inner, order) {\n    return function(builder, text, style, startStyle, endStyle, title, css) {\n      style = style ? style + \" cm-force-border\" : \"cm-force-border\";\n      var start = builder.pos, end = start + text.length;\n      for (;;) {\n        // Find the part that overlaps with the start of this text\n        for (var i = 0; i < order.length; i++) {\n          var part = order[i];\n          if (part.to > start && part.from <= start) break;\n        }\n        if (part.to >= end) return inner(builder, text, style, startStyle, endStyle, title, css);\n        inner(builder, text.slice(0, part.to - start), style, startStyle, null, title, css);\n        startStyle = null;\n        text = text.slice(part.to - start);\n        start = part.to;\n      }\n    };\n  }\n\n  function buildCollapsedSpan(builder, size, marker, ignoreWidget) {\n    var widget = !ignoreWidget && marker.widgetNode;\n    if (widget) builder.map.push(builder.pos, builder.pos + size, widget);\n    if (!ignoreWidget && builder.cm.display.input.needsContentAttribute) {\n      if (!widget)\n        widget = builder.content.appendChild(document.createElement(\"span\"));\n      widget.setAttribute(\"cm-marker\", marker.id);\n    }\n    if (widget) {\n      builder.cm.display.input.setUneditable(widget);\n      builder.content.appendChild(widget);\n    }\n    builder.pos += size;\n  }\n\n  // Outputs a number of spans to make up a line, taking highlighting\n  // and marked text into account.\n  function insertLineContent(line, builder, styles) {\n    var spans = line.markedSpans, allText = line.text, at = 0;\n    if (!spans) {\n      for (var i = 1; i < styles.length; i+=2)\n        builder.addToken(builder, allText.slice(at, at = styles[i]), interpretTokenStyle(styles[i+1], builder.cm.options));\n      return;\n    }\n\n    var len = allText.length, pos = 0, i = 1, text = \"\", style, css;\n    var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, title, collapsed;\n    for (;;) {\n      if (nextChange == pos) { // Update current marker set\n        spanStyle = spanEndStyle = spanStartStyle = title = css = \"\";\n        collapsed = null; nextChange = Infinity;\n        var foundBookmarks = [], endStyles\n        for (var j = 0; j < spans.length; ++j) {\n          var sp = spans[j], m = sp.marker;\n          if (m.type == \"bookmark\" && sp.from == pos && m.widgetNode) {\n            foundBookmarks.push(m);\n          } else if (sp.from <= pos && (sp.to == null || sp.to > pos || m.collapsed && sp.to == pos && sp.from == pos)) {\n            if (sp.to != null && sp.to != pos && nextChange > sp.to) {\n              nextChange = sp.to;\n              spanEndStyle = \"\";\n            }\n            if (m.className) spanStyle += \" \" + m.className;\n            if (m.css) css = (css ? css + \";\" : \"\") + m.css;\n            if (m.startStyle && sp.from == pos) spanStartStyle += \" \" + m.startStyle;\n            if (m.endStyle && sp.to == nextChange) (endStyles || (endStyles = [])).push(m.endStyle, sp.to)\n            if (m.title && !title) title = m.title;\n            if (m.collapsed && (!collapsed || compareCollapsedMarkers(collapsed.marker, m) < 0))\n              collapsed = sp;\n          } else if (sp.from > pos && nextChange > sp.from) {\n            nextChange = sp.from;\n          }\n        }\n        if (endStyles) for (var j = 0; j < endStyles.length; j += 2)\n          if (endStyles[j + 1] == nextChange) spanEndStyle += \" \" + endStyles[j]\n\n        if (!collapsed || collapsed.from == pos) for (var j = 0; j < foundBookmarks.length; ++j)\n          buildCollapsedSpan(builder, 0, foundBookmarks[j]);\n        if (collapsed && (collapsed.from || 0) == pos) {\n          buildCollapsedSpan(builder, (collapsed.to == null ? len + 1 : collapsed.to) - pos,\n                             collapsed.marker, collapsed.from == null);\n          if (collapsed.to == null) return;\n          if (collapsed.to == pos) collapsed = false;\n        }\n      }\n      if (pos >= len) break;\n\n      var upto = Math.min(len, nextChange);\n      while (true) {\n        if (text) {\n          var end = pos + text.length;\n          if (!collapsed) {\n            var tokenText = end > upto ? text.slice(0, upto - pos) : text;\n            builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle,\n                             spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : \"\", title, css);\n          }\n          if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;}\n          pos = end;\n          spanStartStyle = \"\";\n        }\n        text = allText.slice(at, at = styles[i++]);\n        style = interpretTokenStyle(styles[i++], builder.cm.options);\n      }\n    }\n  }\n\n  // DOCUMENT DATA STRUCTURE\n\n  // By default, updates that start and end at the beginning of a line\n  // are treated specially, in order to make the association of line\n  // widgets and marker elements with the text behave more intuitive.\n  function isWholeLineUpdate(doc, change) {\n    return change.from.ch == 0 && change.to.ch == 0 && lst(change.text) == \"\" &&\n      (!doc.cm || doc.cm.options.wholeLineUpdateBefore);\n  }\n\n  // Perform a change on the document data structure.\n  function updateDoc(doc, change, markedSpans, estimateHeight) {\n    function spansFor(n) {return markedSpans ? markedSpans[n] : null;}\n    function update(line, text, spans) {\n      updateLine(line, text, spans, estimateHeight);\n      signalLater(line, \"change\", line, change);\n    }\n    function linesFor(start, end) {\n      for (var i = start, result = []; i < end; ++i)\n        result.push(new Line(text[i], spansFor(i), estimateHeight));\n      return result;\n    }\n\n    var from = change.from, to = change.to, text = change.text;\n    var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line);\n    var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line;\n\n    // Adjust the line structure\n    if (change.full) {\n      doc.insert(0, linesFor(0, text.length));\n      doc.remove(text.length, doc.size - text.length);\n    } else if (isWholeLineUpdate(doc, change)) {\n      // This is a whole-line replace. Treated specially to make\n      // sure line objects move the way they are supposed to.\n      var added = linesFor(0, text.length - 1);\n      update(lastLine, lastLine.text, lastSpans);\n      if (nlines) doc.remove(from.line, nlines);\n      if (added.length) doc.insert(from.line, added);\n    } else if (firstLine == lastLine) {\n      if (text.length == 1) {\n        update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans);\n      } else {\n        var added = linesFor(1, text.length - 1);\n        added.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight));\n        update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));\n        doc.insert(from.line + 1, added);\n      }\n    } else if (text.length == 1) {\n      update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0));\n      doc.remove(from.line + 1, nlines);\n    } else {\n      update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));\n      update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans);\n      var added = linesFor(1, text.length - 1);\n      if (nlines > 1) doc.remove(from.line + 1, nlines - 1);\n      doc.insert(from.line + 1, added);\n    }\n\n    signalLater(doc, \"change\", doc, change);\n  }\n\n  // The document is represented as a BTree consisting of leaves, with\n  // chunk of lines in them, and branches, with up to ten leaves or\n  // other branch nodes below them. The top node is always a branch\n  // node, and is the document object itself (meaning it has\n  // additional methods and properties).\n  //\n  // All nodes have parent links. The tree is used both to go from\n  // line numbers to line objects, and to go from objects to numbers.\n  // It also indexes by height, and is used to convert between height\n  // and line object, and to find the total height of the document.\n  //\n  // See also http://marijnhaverbeke.nl/blog/codemirror-line-tree.html\n\n  function LeafChunk(lines) {\n    this.lines = lines;\n    this.parent = null;\n    for (var i = 0, height = 0; i < lines.length; ++i) {\n      lines[i].parent = this;\n      height += lines[i].height;\n    }\n    this.height = height;\n  }\n\n  LeafChunk.prototype = {\n    chunkSize: function() { return this.lines.length; },\n    // Remove the n lines at offset 'at'.\n    removeInner: function(at, n) {\n      for (var i = at, e = at + n; i < e; ++i) {\n        var line = this.lines[i];\n        this.height -= line.height;\n        cleanUpLine(line);\n        signalLater(line, \"delete\");\n      }\n      this.lines.splice(at, n);\n    },\n    // Helper used to collapse a small branch into a single leaf.\n    collapse: function(lines) {\n      lines.push.apply(lines, this.lines);\n    },\n    // Insert the given array of lines at offset 'at', count them as\n    // having the given height.\n    insertInner: function(at, lines, height) {\n      this.height += height;\n      this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at));\n      for (var i = 0; i < lines.length; ++i) lines[i].parent = this;\n    },\n    // Used to iterate over a part of the tree.\n    iterN: function(at, n, op) {\n      for (var e = at + n; at < e; ++at)\n        if (op(this.lines[at])) return true;\n    }\n  };\n\n  function BranchChunk(children) {\n    this.children = children;\n    var size = 0, height = 0;\n    for (var i = 0; i < children.length; ++i) {\n      var ch = children[i];\n      size += ch.chunkSize(); height += ch.height;\n      ch.parent = this;\n    }\n    this.size = size;\n    this.height = height;\n    this.parent = null;\n  }\n\n  BranchChunk.prototype = {\n    chunkSize: function() { return this.size; },\n    removeInner: function(at, n) {\n      this.size -= n;\n      for (var i = 0; i < this.children.length; ++i) {\n        var child = this.children[i], sz = child.chunkSize();\n        if (at < sz) {\n          var rm = Math.min(n, sz - at), oldHeight = child.height;\n          child.removeInner(at, rm);\n          this.height -= oldHeight - child.height;\n          if (sz == rm) { this.children.splice(i--, 1); child.parent = null; }\n          if ((n -= rm) == 0) break;\n          at = 0;\n        } else at -= sz;\n      }\n      // If the result is smaller than 25 lines, ensure that it is a\n      // single leaf node.\n      if (this.size - n < 25 &&\n          (this.children.length > 1 || !(this.children[0] instanceof LeafChunk))) {\n        var lines = [];\n        this.collapse(lines);\n        this.children = [new LeafChunk(lines)];\n        this.children[0].parent = this;\n      }\n    },\n    collapse: function(lines) {\n      for (var i = 0; i < this.children.length; ++i) this.children[i].collapse(lines);\n    },\n    insertInner: function(at, lines, height) {\n      this.size += lines.length;\n      this.height += height;\n      for (var i = 0; i < this.children.length; ++i) {\n        var child = this.children[i], sz = child.chunkSize();\n        if (at <= sz) {\n          child.insertInner(at, lines, height);\n          if (child.lines && child.lines.length > 50) {\n            while (child.lines.length > 50) {\n              var spilled = child.lines.splice(child.lines.length - 25, 25);\n              var newleaf = new LeafChunk(spilled);\n              child.height -= newleaf.height;\n              this.children.splice(i + 1, 0, newleaf);\n              newleaf.parent = this;\n            }\n            this.maybeSpill();\n          }\n          break;\n        }\n        at -= sz;\n      }\n    },\n    // When a node has grown, check whether it should be split.\n    maybeSpill: function() {\n      if (this.children.length <= 10) return;\n      var me = this;\n      do {\n        var spilled = me.children.splice(me.children.length - 5, 5);\n        var sibling = new BranchChunk(spilled);\n        if (!me.parent) { // Become the parent node\n          var copy = new BranchChunk(me.children);\n          copy.parent = me;\n          me.children = [copy, sibling];\n          me = copy;\n        } else {\n          me.size -= sibling.size;\n          me.height -= sibling.height;\n          var myIndex = indexOf(me.parent.children, me);\n          me.parent.children.splice(myIndex + 1, 0, sibling);\n        }\n        sibling.parent = me.parent;\n      } while (me.children.length > 10);\n      me.parent.maybeSpill();\n    },\n    iterN: function(at, n, op) {\n      for (var i = 0; i < this.children.length; ++i) {\n        var child = this.children[i], sz = child.chunkSize();\n        if (at < sz) {\n          var used = Math.min(n, sz - at);\n          if (child.iterN(at, used, op)) return true;\n          if ((n -= used) == 0) break;\n          at = 0;\n        } else at -= sz;\n      }\n    }\n  };\n\n  var nextDocId = 0;\n  var Doc = CodeMirror.Doc = function(text, mode, firstLine, lineSep) {\n    if (!(this instanceof Doc)) return new Doc(text, mode, firstLine, lineSep);\n    if (firstLine == null) firstLine = 0;\n\n    BranchChunk.call(this, [new LeafChunk([new Line(\"\", null)])]);\n    this.first = firstLine;\n    this.scrollTop = this.scrollLeft = 0;\n    this.cantEdit = false;\n    this.cleanGeneration = 1;\n    this.frontier = firstLine;\n    var start = Pos(firstLine, 0);\n    this.sel = simpleSelection(start);\n    this.history = new History(null);\n    this.id = ++nextDocId;\n    this.modeOption = mode;\n    this.lineSep = lineSep;\n    this.extend = false;\n\n    if (typeof text == \"string\") text = this.splitLines(text);\n    updateDoc(this, {from: start, to: start, text: text});\n    setSelection(this, simpleSelection(start), sel_dontScroll);\n  };\n\n  Doc.prototype = createObj(BranchChunk.prototype, {\n    constructor: Doc,\n    // Iterate over the document. Supports two forms -- with only one\n    // argument, it calls that for each line in the document. With\n    // three, it iterates over the range given by the first two (with\n    // the second being non-inclusive).\n    iter: function(from, to, op) {\n      if (op) this.iterN(from - this.first, to - from, op);\n      else this.iterN(this.first, this.first + this.size, from);\n    },\n\n    // Non-public interface for adding and removing lines.\n    insert: function(at, lines) {\n      var height = 0;\n      for (var i = 0; i < lines.length; ++i) height += lines[i].height;\n      this.insertInner(at - this.first, lines, height);\n    },\n    remove: function(at, n) { this.removeInner(at - this.first, n); },\n\n    // From here, the methods are part of the public interface. Most\n    // are also available from CodeMirror (editor) instances.\n\n    getValue: function(lineSep) {\n      var lines = getLines(this, this.first, this.first + this.size);\n      if (lineSep === false) return lines;\n      return lines.join(lineSep || this.lineSeparator());\n    },\n    setValue: docMethodOp(function(code) {\n      var top = Pos(this.first, 0), last = this.first + this.size - 1;\n      makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length),\n                        text: this.splitLines(code), origin: \"setValue\", full: true}, true);\n      setSelection(this, simpleSelection(top));\n    }),\n    replaceRange: function(code, from, to, origin) {\n      from = clipPos(this, from);\n      to = to ? clipPos(this, to) : from;\n      replaceRange(this, code, from, to, origin);\n    },\n    getRange: function(from, to, lineSep) {\n      var lines = getBetween(this, clipPos(this, from), clipPos(this, to));\n      if (lineSep === false) return lines;\n      return lines.join(lineSep || this.lineSeparator());\n    },\n\n    getLine: function(line) {var l = this.getLineHandle(line); return l && l.text;},\n\n    getLineHandle: function(line) {if (isLine(this, line)) return getLine(this, line);},\n    getLineNumber: function(line) {return lineNo(line);},\n\n    getLineHandleVisualStart: function(line) {\n      if (typeof line == \"number\") line = getLine(this, line);\n      return visualLine(line);\n    },\n\n    lineCount: function() {return this.size;},\n    firstLine: function() {return this.first;},\n    lastLine: function() {return this.first + this.size - 1;},\n\n    clipPos: function(pos) {return clipPos(this, pos);},\n\n    getCursor: function(start) {\n      var range = this.sel.primary(), pos;\n      if (start == null || start == \"head\") pos = range.head;\n      else if (start == \"anchor\") pos = range.anchor;\n      else if (start == \"end\" || start == \"to\" || start === false) pos = range.to();\n      else pos = range.from();\n      return pos;\n    },\n    listSelections: function() { return this.sel.ranges; },\n    somethingSelected: function() {return this.sel.somethingSelected();},\n\n    setCursor: docMethodOp(function(line, ch, options) {\n      setSimpleSelection(this, clipPos(this, typeof line == \"number\" ? Pos(line, ch || 0) : line), null, options);\n    }),\n    setSelection: docMethodOp(function(anchor, head, options) {\n      setSimpleSelection(this, clipPos(this, anchor), clipPos(this, head || anchor), options);\n    }),\n    extendSelection: docMethodOp(function(head, other, options) {\n      extendSelection(this, clipPos(this, head), other && clipPos(this, other), options);\n    }),\n    extendSelections: docMethodOp(function(heads, options) {\n      extendSelections(this, clipPosArray(this, heads), options);\n    }),\n    extendSelectionsBy: docMethodOp(function(f, options) {\n      var heads = map(this.sel.ranges, f);\n      extendSelections(this, clipPosArray(this, heads), options);\n    }),\n    setSelections: docMethodOp(function(ranges, primary, options) {\n      if (!ranges.length) return;\n      for (var i = 0, out = []; i < ranges.length; i++)\n        out[i] = new Range(clipPos(this, ranges[i].anchor),\n                           clipPos(this, ranges[i].head));\n      if (primary == null) primary = Math.min(ranges.length - 1, this.sel.primIndex);\n      setSelection(this, normalizeSelection(out, primary), options);\n    }),\n    addSelection: docMethodOp(function(anchor, head, options) {\n      var ranges = this.sel.ranges.slice(0);\n      ranges.push(new Range(clipPos(this, anchor), clipPos(this, head || anchor)));\n      setSelection(this, normalizeSelection(ranges, ranges.length - 1), options);\n    }),\n\n    getSelection: function(lineSep) {\n      var ranges = this.sel.ranges, lines;\n      for (var i = 0; i < ranges.length; i++) {\n        var sel = getBetween(this, ranges[i].from(), ranges[i].to());\n        lines = lines ? lines.concat(sel) : sel;\n      }\n      if (lineSep === false) return lines;\n      else return lines.join(lineSep || this.lineSeparator());\n    },\n    getSelections: function(lineSep) {\n      var parts = [], ranges = this.sel.ranges;\n      for (var i = 0; i < ranges.length; i++) {\n        var sel = getBetween(this, ranges[i].from(), ranges[i].to());\n        if (lineSep !== false) sel = sel.join(lineSep || this.lineSeparator());\n        parts[i] = sel;\n      }\n      return parts;\n    },\n    replaceSelection: function(code, collapse, origin) {\n      var dup = [];\n      for (var i = 0; i < this.sel.ranges.length; i++)\n        dup[i] = code;\n      this.replaceSelections(dup, collapse, origin || \"+input\");\n    },\n    replaceSelections: docMethodOp(function(code, collapse, origin) {\n      var changes = [], sel = this.sel;\n      for (var i = 0; i < sel.ranges.length; i++) {\n        var range = sel.ranges[i];\n        changes[i] = {from: range.from(), to: range.to(), text: this.splitLines(code[i]), origin: origin};\n      }\n      var newSel = collapse && collapse != \"end\" && computeReplacedSel(this, changes, collapse);\n      for (var i = changes.length - 1; i >= 0; i--)\n        makeChange(this, changes[i]);\n      if (newSel) setSelectionReplaceHistory(this, newSel);\n      else if (this.cm) ensureCursorVisible(this.cm);\n    }),\n    undo: docMethodOp(function() {makeChangeFromHistory(this, \"undo\");}),\n    redo: docMethodOp(function() {makeChangeFromHistory(this, \"redo\");}),\n    undoSelection: docMethodOp(function() {makeChangeFromHistory(this, \"undo\", true);}),\n    redoSelection: docMethodOp(function() {makeChangeFromHistory(this, \"redo\", true);}),\n\n    setExtending: function(val) {this.extend = val;},\n    getExtending: function() {return this.extend;},\n\n    historySize: function() {\n      var hist = this.history, done = 0, undone = 0;\n      for (var i = 0; i < hist.done.length; i++) if (!hist.done[i].ranges) ++done;\n      for (var i = 0; i < hist.undone.length; i++) if (!hist.undone[i].ranges) ++undone;\n      return {undo: done, redo: undone};\n    },\n    clearHistory: function() {this.history = new History(this.history.maxGeneration);},\n\n    markClean: function() {\n      this.cleanGeneration = this.changeGeneration(true);\n    },\n    changeGeneration: function(forceSplit) {\n      if (forceSplit)\n        this.history.lastOp = this.history.lastSelOp = this.history.lastOrigin = null;\n      return this.history.generation;\n    },\n    isClean: function (gen) {\n      return this.history.generation == (gen || this.cleanGeneration);\n    },\n\n    getHistory: function() {\n      return {done: copyHistoryArray(this.history.done),\n              undone: copyHistoryArray(this.history.undone)};\n    },\n    setHistory: function(histData) {\n      var hist = this.history = new History(this.history.maxGeneration);\n      hist.done = copyHistoryArray(histData.done.slice(0), null, true);\n      hist.undone = copyHistoryArray(histData.undone.slice(0), null, true);\n    },\n\n    addLineClass: docMethodOp(function(handle, where, cls) {\n      return changeLine(this, handle, where == \"gutter\" ? \"gutter\" : \"class\", function(line) {\n        var prop = where == \"text\" ? \"textClass\"\n                 : where == \"background\" ? \"bgClass\"\n                 : where == \"gutter\" ? \"gutterClass\" : \"wrapClass\";\n        if (!line[prop]) line[prop] = cls;\n        else if (classTest(cls).test(line[prop])) return false;\n        else line[prop] += \" \" + cls;\n        return true;\n      });\n    }),\n    removeLineClass: docMethodOp(function(handle, where, cls) {\n      return changeLine(this, handle, where == \"gutter\" ? \"gutter\" : \"class\", function(line) {\n        var prop = where == \"text\" ? \"textClass\"\n                 : where == \"background\" ? \"bgClass\"\n                 : where == \"gutter\" ? \"gutterClass\" : \"wrapClass\";\n        var cur = line[prop];\n        if (!cur) return false;\n        else if (cls == null) line[prop] = null;\n        else {\n          var found = cur.match(classTest(cls));\n          if (!found) return false;\n          var end = found.index + found[0].length;\n          line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? \"\" : \" \") + cur.slice(end) || null;\n        }\n        return true;\n      });\n    }),\n\n    addLineWidget: docMethodOp(function(handle, node, options) {\n      return addLineWidget(this, handle, node, options);\n    }),\n    removeLineWidget: function(widget) { widget.clear(); },\n\n    markText: function(from, to, options) {\n      return markText(this, clipPos(this, from), clipPos(this, to), options, options && options.type || \"range\");\n    },\n    setBookmark: function(pos, options) {\n      var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options),\n                      insertLeft: options && options.insertLeft,\n                      clearWhenEmpty: false, shared: options && options.shared,\n                      handleMouseEvents: options && options.handleMouseEvents};\n      pos = clipPos(this, pos);\n      return markText(this, pos, pos, realOpts, \"bookmark\");\n    },\n    findMarksAt: function(pos) {\n      pos = clipPos(this, pos);\n      var markers = [], spans = getLine(this, pos.line).markedSpans;\n      if (spans) for (var i = 0; i < spans.length; ++i) {\n        var span = spans[i];\n        if ((span.from == null || span.from <= pos.ch) &&\n            (span.to == null || span.to >= pos.ch))\n          markers.push(span.marker.parent || span.marker);\n      }\n      return markers;\n    },\n    findMarks: function(from, to, filter) {\n      from = clipPos(this, from); to = clipPos(this, to);\n      var found = [], lineNo = from.line;\n      this.iter(from.line, to.line + 1, function(line) {\n        var spans = line.markedSpans;\n        if (spans) for (var i = 0; i < spans.length; i++) {\n          var span = spans[i];\n          if (!(span.to != null && lineNo == from.line && from.ch > span.to ||\n                span.from == null && lineNo != from.line ||\n                span.from != null && lineNo == to.line && span.from > to.ch) &&\n              (!filter || filter(span.marker)))\n            found.push(span.marker.parent || span.marker);\n        }\n        ++lineNo;\n      });\n      return found;\n    },\n    getAllMarks: function() {\n      var markers = [];\n      this.iter(function(line) {\n        var sps = line.markedSpans;\n        if (sps) for (var i = 0; i < sps.length; ++i)\n          if (sps[i].from != null) markers.push(sps[i].marker);\n      });\n      return markers;\n    },\n\n    posFromIndex: function(off) {\n      var ch, lineNo = this.first;\n      this.iter(function(line) {\n        var sz = line.text.length + 1;\n        if (sz > off) { ch = off; return true; }\n        off -= sz;\n        ++lineNo;\n      });\n      return clipPos(this, Pos(lineNo, ch));\n    },\n    indexFromPos: function (coords) {\n      coords = clipPos(this, coords);\n      var index = coords.ch;\n      if (coords.line < this.first || coords.ch < 0) return 0;\n      this.iter(this.first, coords.line, function (line) {\n        index += line.text.length + 1;\n      });\n      return index;\n    },\n\n    copy: function(copyHistory) {\n      var doc = new Doc(getLines(this, this.first, this.first + this.size),\n                        this.modeOption, this.first, this.lineSep);\n      doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft;\n      doc.sel = this.sel;\n      doc.extend = false;\n      if (copyHistory) {\n        doc.history.undoDepth = this.history.undoDepth;\n        doc.setHistory(this.getHistory());\n      }\n      return doc;\n    },\n\n    linkedDoc: function(options) {\n      if (!options) options = {};\n      var from = this.first, to = this.first + this.size;\n      if (options.from != null && options.from > from) from = options.from;\n      if (options.to != null && options.to < to) to = options.to;\n      var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from, this.lineSep);\n      if (options.sharedHist) copy.history = this.history;\n      (this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist});\n      copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}];\n      copySharedMarkers(copy, findSharedMarkers(this));\n      return copy;\n    },\n    unlinkDoc: function(other) {\n      if (other instanceof CodeMirror) other = other.doc;\n      if (this.linked) for (var i = 0; i < this.linked.length; ++i) {\n        var link = this.linked[i];\n        if (link.doc != other) continue;\n        this.linked.splice(i, 1);\n        other.unlinkDoc(this);\n        detachSharedMarkers(findSharedMarkers(this));\n        break;\n      }\n      // If the histories were shared, split them again\n      if (other.history == this.history) {\n        var splitIds = [other.id];\n        linkedDocs(other, function(doc) {splitIds.push(doc.id);}, true);\n        other.history = new History(null);\n        other.history.done = copyHistoryArray(this.history.done, splitIds);\n        other.history.undone = copyHistoryArray(this.history.undone, splitIds);\n      }\n    },\n    iterLinkedDocs: function(f) {linkedDocs(this, f);},\n\n    getMode: function() {return this.mode;},\n    getEditor: function() {return this.cm;},\n\n    splitLines: function(str) {\n      if (this.lineSep) return str.split(this.lineSep);\n      return splitLinesAuto(str);\n    },\n    lineSeparator: function() { return this.lineSep || \"\\n\"; }\n  });\n\n  // Public alias.\n  Doc.prototype.eachLine = Doc.prototype.iter;\n\n  // Set up methods on CodeMirror's prototype to redirect to the editor's document.\n  var dontDelegate = \"iter insert remove copy getEditor constructor\".split(\" \");\n  for (var prop in Doc.prototype) if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0)\n    CodeMirror.prototype[prop] = (function(method) {\n      return function() {return method.apply(this.doc, arguments);};\n    })(Doc.prototype[prop]);\n\n  eventMixin(Doc);\n\n  // Call f for all linked documents.\n  function linkedDocs(doc, f, sharedHistOnly) {\n    function propagate(doc, skip, sharedHist) {\n      if (doc.linked) for (var i = 0; i < doc.linked.length; ++i) {\n        var rel = doc.linked[i];\n        if (rel.doc == skip) continue;\n        var shared = sharedHist && rel.sharedHist;\n        if (sharedHistOnly && !shared) continue;\n        f(rel.doc, shared);\n        propagate(rel.doc, doc, shared);\n      }\n    }\n    propagate(doc, null, true);\n  }\n\n  // Attach a document to an editor.\n  function attachDoc(cm, doc) {\n    if (doc.cm) throw new Error(\"This document is already in use.\");\n    cm.doc = doc;\n    doc.cm = cm;\n    estimateLineHeights(cm);\n    loadMode(cm);\n    if (!cm.options.lineWrapping) findMaxLine(cm);\n    cm.options.mode = doc.modeOption;\n    regChange(cm);\n  }\n\n  // LINE UTILITIES\n\n  // Find the line object corresponding to the given line number.\n  function getLine(doc, n) {\n    n -= doc.first;\n    if (n < 0 || n >= doc.size) throw new Error(\"There is no line \" + (n + doc.first) + \" in the document.\");\n    for (var chunk = doc; !chunk.lines;) {\n      for (var i = 0;; ++i) {\n        var child = chunk.children[i], sz = child.chunkSize();\n        if (n < sz) { chunk = child; break; }\n        n -= sz;\n      }\n    }\n    return chunk.lines[n];\n  }\n\n  // Get the part of a document between two positions, as an array of\n  // strings.\n  function getBetween(doc, start, end) {\n    var out = [], n = start.line;\n    doc.iter(start.line, end.line + 1, function(line) {\n      var text = line.text;\n      if (n == end.line) text = text.slice(0, end.ch);\n      if (n == start.line) text = text.slice(start.ch);\n      out.push(text);\n      ++n;\n    });\n    return out;\n  }\n  // Get the lines between from and to, as array of strings.\n  function getLines(doc, from, to) {\n    var out = [];\n    doc.iter(from, to, function(line) { out.push(line.text); });\n    return out;\n  }\n\n  // Update the height of a line, propagating the height change\n  // upwards to parent nodes.\n  function updateLineHeight(line, height) {\n    var diff = height - line.height;\n    if (diff) for (var n = line; n; n = n.parent) n.height += diff;\n  }\n\n  // Given a line object, find its line number by walking up through\n  // its parent links.\n  function lineNo(line) {\n    if (line.parent == null) return null;\n    var cur = line.parent, no = indexOf(cur.lines, line);\n    for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) {\n      for (var i = 0;; ++i) {\n        if (chunk.children[i] == cur) break;\n        no += chunk.children[i].chunkSize();\n      }\n    }\n    return no + cur.first;\n  }\n\n  // Find the line at the given vertical position, using the height\n  // information in the document tree.\n  function lineAtHeight(chunk, h) {\n    var n = chunk.first;\n    outer: do {\n      for (var i = 0; i < chunk.children.length; ++i) {\n        var child = chunk.children[i], ch = child.height;\n        if (h < ch) { chunk = child; continue outer; }\n        h -= ch;\n        n += child.chunkSize();\n      }\n      return n;\n    } while (!chunk.lines);\n    for (var i = 0; i < chunk.lines.length; ++i) {\n      var line = chunk.lines[i], lh = line.height;\n      if (h < lh) break;\n      h -= lh;\n    }\n    return n + i;\n  }\n\n\n  // Find the height above the given line.\n  function heightAtLine(lineObj) {\n    lineObj = visualLine(lineObj);\n\n    var h = 0, chunk = lineObj.parent;\n    for (var i = 0; i < chunk.lines.length; ++i) {\n      var line = chunk.lines[i];\n      if (line == lineObj) break;\n      else h += line.height;\n    }\n    for (var p = chunk.parent; p; chunk = p, p = chunk.parent) {\n      for (var i = 0; i < p.children.length; ++i) {\n        var cur = p.children[i];\n        if (cur == chunk) break;\n        else h += cur.height;\n      }\n    }\n    return h;\n  }\n\n  // Get the bidi ordering for the given line (and cache it). Returns\n  // false for lines that are fully left-to-right, and an array of\n  // BidiSpan objects otherwise.\n  function getOrder(line) {\n    var order = line.order;\n    if (order == null) order = line.order = bidiOrdering(line.text);\n    return order;\n  }\n\n  // HISTORY\n\n  function History(startGen) {\n    // Arrays of change events and selections. Doing something adds an\n    // event to done and clears undo. Undoing moves events from done\n    // to undone, redoing moves them in the other direction.\n    this.done = []; this.undone = [];\n    this.undoDepth = Infinity;\n    // Used to track when changes can be merged into a single undo\n    // event\n    this.lastModTime = this.lastSelTime = 0;\n    this.lastOp = this.lastSelOp = null;\n    this.lastOrigin = this.lastSelOrigin = null;\n    // Used by the isClean() method\n    this.generation = this.maxGeneration = startGen || 1;\n  }\n\n  // Create a history change event from an updateDoc-style change\n  // object.\n  function historyChangeFromChange(doc, change) {\n    var histChange = {from: copyPos(change.from), to: changeEnd(change), text: getBetween(doc, change.from, change.to)};\n    attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);\n    linkedDocs(doc, function(doc) {attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);}, true);\n    return histChange;\n  }\n\n  // Pop all selection events off the end of a history array. Stop at\n  // a change event.\n  function clearSelectionEvents(array) {\n    while (array.length) {\n      var last = lst(array);\n      if (last.ranges) array.pop();\n      else break;\n    }\n  }\n\n  // Find the top change event in the history. Pop off selection\n  // events that are in the way.\n  function lastChangeEvent(hist, force) {\n    if (force) {\n      clearSelectionEvents(hist.done);\n      return lst(hist.done);\n    } else if (hist.done.length && !lst(hist.done).ranges) {\n      return lst(hist.done);\n    } else if (hist.done.length > 1 && !hist.done[hist.done.length - 2].ranges) {\n      hist.done.pop();\n      return lst(hist.done);\n    }\n  }\n\n  // Register a change in the history. Merges changes that are within\n  // a single operation, ore are close together with an origin that\n  // allows merging (starting with \"+\") into a single event.\n  function addChangeToHistory(doc, change, selAfter, opId) {\n    var hist = doc.history;\n    hist.undone.length = 0;\n    var time = +new Date, cur;\n\n    if ((hist.lastOp == opId ||\n         hist.lastOrigin == change.origin && change.origin &&\n         ((change.origin.charAt(0) == \"+\" && doc.cm && hist.lastModTime > time - doc.cm.options.historyEventDelay) ||\n          change.origin.charAt(0) == \"*\")) &&\n        (cur = lastChangeEvent(hist, hist.lastOp == opId))) {\n      // Merge this change into the last event\n      var last = lst(cur.changes);\n      if (cmp(change.from, change.to) == 0 && cmp(change.from, last.to) == 0) {\n        // Optimized case for simple insertion -- don't want to add\n        // new changesets for every character typed\n        last.to = changeEnd(change);\n      } else {\n        // Add new sub-event\n        cur.changes.push(historyChangeFromChange(doc, change));\n      }\n    } else {\n      // Can not be merged, start a new event.\n      var before = lst(hist.done);\n      if (!before || !before.ranges)\n        pushSelectionToHistory(doc.sel, hist.done);\n      cur = {changes: [historyChangeFromChange(doc, change)],\n             generation: hist.generation};\n      hist.done.push(cur);\n      while (hist.done.length > hist.undoDepth) {\n        hist.done.shift();\n        if (!hist.done[0].ranges) hist.done.shift();\n      }\n    }\n    hist.done.push(selAfter);\n    hist.generation = ++hist.maxGeneration;\n    hist.lastModTime = hist.lastSelTime = time;\n    hist.lastOp = hist.lastSelOp = opId;\n    hist.lastOrigin = hist.lastSelOrigin = change.origin;\n\n    if (!last) signal(doc, \"historyAdded\");\n  }\n\n  function selectionEventCanBeMerged(doc, origin, prev, sel) {\n    var ch = origin.charAt(0);\n    return ch == \"*\" ||\n      ch == \"+\" &&\n      prev.ranges.length == sel.ranges.length &&\n      prev.somethingSelected() == sel.somethingSelected() &&\n      new Date - doc.history.lastSelTime <= (doc.cm ? doc.cm.options.historyEventDelay : 500);\n  }\n\n  // Called whenever the selection changes, sets the new selection as\n  // the pending selection in the history, and pushes the old pending\n  // selection into the 'done' array when it was significantly\n  // different (in number of selected ranges, emptiness, or time).\n  function addSelectionToHistory(doc, sel, opId, options) {\n    var hist = doc.history, origin = options && options.origin;\n\n    // A new event is started when the previous origin does not match\n    // the current, or the origins don't allow matching. Origins\n    // starting with * are always merged, those starting with + are\n    // merged when similar and close together in time.\n    if (opId == hist.lastSelOp ||\n        (origin && hist.lastSelOrigin == origin &&\n         (hist.lastModTime == hist.lastSelTime && hist.lastOrigin == origin ||\n          selectionEventCanBeMerged(doc, origin, lst(hist.done), sel))))\n      hist.done[hist.done.length - 1] = sel;\n    else\n      pushSelectionToHistory(sel, hist.done);\n\n    hist.lastSelTime = +new Date;\n    hist.lastSelOrigin = origin;\n    hist.lastSelOp = opId;\n    if (options && options.clearRedo !== false)\n      clearSelectionEvents(hist.undone);\n  }\n\n  function pushSelectionToHistory(sel, dest) {\n    var top = lst(dest);\n    if (!(top && top.ranges && top.equals(sel)))\n      dest.push(sel);\n  }\n\n  // Used to store marked span information in the history.\n  function attachLocalSpans(doc, change, from, to) {\n    var existing = change[\"spans_\" + doc.id], n = 0;\n    doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function(line) {\n      if (line.markedSpans)\n        (existing || (existing = change[\"spans_\" + doc.id] = {}))[n] = line.markedSpans;\n      ++n;\n    });\n  }\n\n  // When un/re-doing restores text containing marked spans, those\n  // that have been explicitly cleared should not be restored.\n  function removeClearedSpans(spans) {\n    if (!spans) return null;\n    for (var i = 0, out; i < spans.length; ++i) {\n      if (spans[i].marker.explicitlyCleared) { if (!out) out = spans.slice(0, i); }\n      else if (out) out.push(spans[i]);\n    }\n    return !out ? spans : out.length ? out : null;\n  }\n\n  // Retrieve and filter the old marked spans stored in a change event.\n  function getOldSpans(doc, change) {\n    var found = change[\"spans_\" + doc.id];\n    if (!found) return null;\n    for (var i = 0, nw = []; i < change.text.length; ++i)\n      nw.push(removeClearedSpans(found[i]));\n    return nw;\n  }\n\n  // Used both to provide a JSON-safe object in .getHistory, and, when\n  // detaching a document, to split the history in two\n  function copyHistoryArray(events, newGroup, instantiateSel) {\n    for (var i = 0, copy = []; i < events.length; ++i) {\n      var event = events[i];\n      if (event.ranges) {\n        copy.push(instantiateSel ? Selection.prototype.deepCopy.call(event) : event);\n        continue;\n      }\n      var changes = event.changes, newChanges = [];\n      copy.push({changes: newChanges});\n      for (var j = 0; j < changes.length; ++j) {\n        var change = changes[j], m;\n        newChanges.push({from: change.from, to: change.to, text: change.text});\n        if (newGroup) for (var prop in change) if (m = prop.match(/^spans_(\\d+)$/)) {\n          if (indexOf(newGroup, Number(m[1])) > -1) {\n            lst(newChanges)[prop] = change[prop];\n            delete change[prop];\n          }\n        }\n      }\n    }\n    return copy;\n  }\n\n  // Rebasing/resetting history to deal with externally-sourced changes\n\n  function rebaseHistSelSingle(pos, from, to, diff) {\n    if (to < pos.line) {\n      pos.line += diff;\n    } else if (from < pos.line) {\n      pos.line = from;\n      pos.ch = 0;\n    }\n  }\n\n  // Tries to rebase an array of history events given a change in the\n  // document. If the change touches the same lines as the event, the\n  // event, and everything 'behind' it, is discarded. If the change is\n  // before the event, the event's positions are updated. Uses a\n  // copy-on-write scheme for the positions, to avoid having to\n  // reallocate them all on every rebase, but also avoid problems with\n  // shared position objects being unsafely updated.\n  function rebaseHistArray(array, from, to, diff) {\n    for (var i = 0; i < array.length; ++i) {\n      var sub = array[i], ok = true;\n      if (sub.ranges) {\n        if (!sub.copied) { sub = array[i] = sub.deepCopy(); sub.copied = true; }\n        for (var j = 0; j < sub.ranges.length; j++) {\n          rebaseHistSelSingle(sub.ranges[j].anchor, from, to, diff);\n          rebaseHistSelSingle(sub.ranges[j].head, from, to, diff);\n        }\n        continue;\n      }\n      for (var j = 0; j < sub.changes.length; ++j) {\n        var cur = sub.changes[j];\n        if (to < cur.from.line) {\n          cur.from = Pos(cur.from.line + diff, cur.from.ch);\n          cur.to = Pos(cur.to.line + diff, cur.to.ch);\n        } else if (from <= cur.to.line) {\n          ok = false;\n          break;\n        }\n      }\n      if (!ok) {\n        array.splice(0, i + 1);\n        i = 0;\n      }\n    }\n  }\n\n  function rebaseHist(hist, change) {\n    var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1;\n    rebaseHistArray(hist.done, from, to, diff);\n    rebaseHistArray(hist.undone, from, to, diff);\n  }\n\n  // EVENT UTILITIES\n\n  // Due to the fact that we still support jurassic IE versions, some\n  // compatibility wrappers are needed.\n\n  var e_preventDefault = CodeMirror.e_preventDefault = function(e) {\n    if (e.preventDefault) e.preventDefault();\n    else e.returnValue = false;\n  };\n  var e_stopPropagation = CodeMirror.e_stopPropagation = function(e) {\n    if (e.stopPropagation) e.stopPropagation();\n    else e.cancelBubble = true;\n  };\n  function e_defaultPrevented(e) {\n    return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false;\n  }\n  var e_stop = CodeMirror.e_stop = function(e) {e_preventDefault(e); e_stopPropagation(e);};\n\n  function e_target(e) {return e.target || e.srcElement;}\n  function e_button(e) {\n    var b = e.which;\n    if (b == null) {\n      if (e.button & 1) b = 1;\n      else if (e.button & 2) b = 3;\n      else if (e.button & 4) b = 2;\n    }\n    if (mac && e.ctrlKey && b == 1) b = 3;\n    return b;\n  }\n\n  // EVENT HANDLING\n\n  // Lightweight event framework. on/off also work on DOM nodes,\n  // registering native DOM handlers.\n\n  var on = CodeMirror.on = function(emitter, type, f) {\n    if (emitter.addEventListener)\n      emitter.addEventListener(type, f, false);\n    else if (emitter.attachEvent)\n      emitter.attachEvent(\"on\" + type, f);\n    else {\n      var map = emitter._handlers || (emitter._handlers = {});\n      var arr = map[type] || (map[type] = []);\n      arr.push(f);\n    }\n  };\n\n  var noHandlers = []\n  function getHandlers(emitter, type, copy) {\n    var arr = emitter._handlers && emitter._handlers[type]\n    if (copy) return arr && arr.length > 0 ? arr.slice() : noHandlers\n    else return arr || noHandlers\n  }\n\n  var off = CodeMirror.off = function(emitter, type, f) {\n    if (emitter.removeEventListener)\n      emitter.removeEventListener(type, f, false);\n    else if (emitter.detachEvent)\n      emitter.detachEvent(\"on\" + type, f);\n    else {\n      var handlers = getHandlers(emitter, type, false)\n      for (var i = 0; i < handlers.length; ++i)\n        if (handlers[i] == f) { handlers.splice(i, 1); break; }\n    }\n  };\n\n  var signal = CodeMirror.signal = function(emitter, type /*, values...*/) {\n    var handlers = getHandlers(emitter, type, true)\n    if (!handlers.length) return;\n    var args = Array.prototype.slice.call(arguments, 2);\n    for (var i = 0; i < handlers.length; ++i) handlers[i].apply(null, args);\n  };\n\n  var orphanDelayedCallbacks = null;\n\n  // Often, we want to signal events at a point where we are in the\n  // middle of some work, but don't want the handler to start calling\n  // other methods on the editor, which might be in an inconsistent\n  // state or simply not expect any other events to happen.\n  // signalLater looks whether there are any handlers, and schedules\n  // them to be executed when the last operation ends, or, if no\n  // operation is active, when a timeout fires.\n  function signalLater(emitter, type /*, values...*/) {\n    var arr = getHandlers(emitter, type, false)\n    if (!arr.length) return;\n    var args = Array.prototype.slice.call(arguments, 2), list;\n    if (operationGroup) {\n      list = operationGroup.delayedCallbacks;\n    } else if (orphanDelayedCallbacks) {\n      list = orphanDelayedCallbacks;\n    } else {\n      list = orphanDelayedCallbacks = [];\n      setTimeout(fireOrphanDelayed, 0);\n    }\n    function bnd(f) {return function(){f.apply(null, args);};};\n    for (var i = 0; i < arr.length; ++i)\n      list.push(bnd(arr[i]));\n  }\n\n  function fireOrphanDelayed() {\n    var delayed = orphanDelayedCallbacks;\n    orphanDelayedCallbacks = null;\n    for (var i = 0; i < delayed.length; ++i) delayed[i]();\n  }\n\n  // The DOM events that CodeMirror handles can be overridden by\n  // registering a (non-DOM) handler on the editor for the event name,\n  // and preventDefault-ing the event in that handler.\n  function signalDOMEvent(cm, e, override) {\n    if (typeof e == \"string\")\n      e = {type: e, preventDefault: function() { this.defaultPrevented = true; }};\n    signal(cm, override || e.type, cm, e);\n    return e_defaultPrevented(e) || e.codemirrorIgnore;\n  }\n\n  function signalCursorActivity(cm) {\n    var arr = cm._handlers && cm._handlers.cursorActivity;\n    if (!arr) return;\n    var set = cm.curOp.cursorActivityHandlers || (cm.curOp.cursorActivityHandlers = []);\n    for (var i = 0; i < arr.length; ++i) if (indexOf(set, arr[i]) == -1)\n      set.push(arr[i]);\n  }\n\n  function hasHandler(emitter, type) {\n    return getHandlers(emitter, type).length > 0\n  }\n\n  // Add on and off methods to a constructor's prototype, to make\n  // registering events on such objects more convenient.\n  function eventMixin(ctor) {\n    ctor.prototype.on = function(type, f) {on(this, type, f);};\n    ctor.prototype.off = function(type, f) {off(this, type, f);};\n  }\n\n  // MISC UTILITIES\n\n  // Number of pixels added to scroller and sizer to hide scrollbar\n  var scrollerGap = 30;\n\n  // Returned or thrown by various protocols to signal 'I'm not\n  // handling this'.\n  var Pass = CodeMirror.Pass = {toString: function(){return \"CodeMirror.Pass\";}};\n\n  // Reused option objects for setSelection & friends\n  var sel_dontScroll = {scroll: false}, sel_mouse = {origin: \"*mouse\"}, sel_move = {origin: \"+move\"};\n\n  function Delayed() {this.id = null;}\n  Delayed.prototype.set = function(ms, f) {\n    clearTimeout(this.id);\n    this.id = setTimeout(f, ms);\n  };\n\n  // Counts the column offset in a string, taking tabs into account.\n  // Used mostly to find indentation.\n  var countColumn = CodeMirror.countColumn = function(string, end, tabSize, startIndex, startValue) {\n    if (end == null) {\n      end = string.search(/[^\\s\\u00a0]/);\n      if (end == -1) end = string.length;\n    }\n    for (var i = startIndex || 0, n = startValue || 0;;) {\n      var nextTab = string.indexOf(\"\\t\", i);\n      if (nextTab < 0 || nextTab >= end)\n        return n + (end - i);\n      n += nextTab - i;\n      n += tabSize - (n % tabSize);\n      i = nextTab + 1;\n    }\n  };\n\n  // The inverse of countColumn -- find the offset that corresponds to\n  // a particular column.\n  var findColumn = CodeMirror.findColumn = function(string, goal, tabSize) {\n    for (var pos = 0, col = 0;;) {\n      var nextTab = string.indexOf(\"\\t\", pos);\n      if (nextTab == -1) nextTab = string.length;\n      var skipped = nextTab - pos;\n      if (nextTab == string.length || col + skipped >= goal)\n        return pos + Math.min(skipped, goal - col);\n      col += nextTab - pos;\n      col += tabSize - (col % tabSize);\n      pos = nextTab + 1;\n      if (col >= goal) return pos;\n    }\n  }\n\n  var spaceStrs = [\"\"];\n  function spaceStr(n) {\n    while (spaceStrs.length <= n)\n      spaceStrs.push(lst(spaceStrs) + \" \");\n    return spaceStrs[n];\n  }\n\n  function lst(arr) { return arr[arr.length-1]; }\n\n  var selectInput = function(node) { node.select(); };\n  if (ios) // Mobile Safari apparently has a bug where select() is broken.\n    selectInput = function(node) { node.selectionStart = 0; node.selectionEnd = node.value.length; };\n  else if (ie) // Suppress mysterious IE10 errors\n    selectInput = function(node) { try { node.select(); } catch(_e) {} };\n\n  function indexOf(array, elt) {\n    for (var i = 0; i < array.length; ++i)\n      if (array[i] == elt) return i;\n    return -1;\n  }\n  function map(array, f) {\n    var out = [];\n    for (var i = 0; i < array.length; i++) out[i] = f(array[i], i);\n    return out;\n  }\n\n  function nothing() {}\n\n  function createObj(base, props) {\n    var inst;\n    if (Object.create) {\n      inst = Object.create(base);\n    } else {\n      nothing.prototype = base;\n      inst = new nothing();\n    }\n    if (props) copyObj(props, inst);\n    return inst;\n  };\n\n  function copyObj(obj, target, overwrite) {\n    if (!target) target = {};\n    for (var prop in obj)\n      if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop)))\n        target[prop] = obj[prop];\n    return target;\n  }\n\n  function bind(f) {\n    var args = Array.prototype.slice.call(arguments, 1);\n    return function(){return f.apply(null, args);};\n  }\n\n  var nonASCIISingleCaseWordChar = /[\\u00df\\u0587\\u0590-\\u05f4\\u0600-\\u06ff\\u3040-\\u309f\\u30a0-\\u30ff\\u3400-\\u4db5\\u4e00-\\u9fcc\\uac00-\\ud7af]/;\n  var isWordCharBasic = CodeMirror.isWordChar = function(ch) {\n    return /\\w/.test(ch) || ch > \"\\x80\" &&\n      (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch));\n  };\n  function isWordChar(ch, helper) {\n    if (!helper) return isWordCharBasic(ch);\n    if (helper.source.indexOf(\"\\\\w\") > -1 && isWordCharBasic(ch)) return true;\n    return helper.test(ch);\n  }\n\n  function isEmpty(obj) {\n    for (var n in obj) if (obj.hasOwnProperty(n) && obj[n]) return false;\n    return true;\n  }\n\n  // Extending unicode characters. A series of a non-extending char +\n  // any number of extending chars is treated as a single unit as far\n  // as editing and measuring is concerned. This is not fully correct,\n  // since some scripts/fonts/browsers also treat other configurations\n  // of code points as a group.\n  var extendingChars = /[\\u0300-\\u036f\\u0483-\\u0489\\u0591-\\u05bd\\u05bf\\u05c1\\u05c2\\u05c4\\u05c5\\u05c7\\u0610-\\u061a\\u064b-\\u065e\\u0670\\u06d6-\\u06dc\\u06de-\\u06e4\\u06e7\\u06e8\\u06ea-\\u06ed\\u0711\\u0730-\\u074a\\u07a6-\\u07b0\\u07eb-\\u07f3\\u0816-\\u0819\\u081b-\\u0823\\u0825-\\u0827\\u0829-\\u082d\\u0900-\\u0902\\u093c\\u0941-\\u0948\\u094d\\u0951-\\u0955\\u0962\\u0963\\u0981\\u09bc\\u09be\\u09c1-\\u09c4\\u09cd\\u09d7\\u09e2\\u09e3\\u0a01\\u0a02\\u0a3c\\u0a41\\u0a42\\u0a47\\u0a48\\u0a4b-\\u0a4d\\u0a51\\u0a70\\u0a71\\u0a75\\u0a81\\u0a82\\u0abc\\u0ac1-\\u0ac5\\u0ac7\\u0ac8\\u0acd\\u0ae2\\u0ae3\\u0b01\\u0b3c\\u0b3e\\u0b3f\\u0b41-\\u0b44\\u0b4d\\u0b56\\u0b57\\u0b62\\u0b63\\u0b82\\u0bbe\\u0bc0\\u0bcd\\u0bd7\\u0c3e-\\u0c40\\u0c46-\\u0c48\\u0c4a-\\u0c4d\\u0c55\\u0c56\\u0c62\\u0c63\\u0cbc\\u0cbf\\u0cc2\\u0cc6\\u0ccc\\u0ccd\\u0cd5\\u0cd6\\u0ce2\\u0ce3\\u0d3e\\u0d41-\\u0d44\\u0d4d\\u0d57\\u0d62\\u0d63\\u0dca\\u0dcf\\u0dd2-\\u0dd4\\u0dd6\\u0ddf\\u0e31\\u0e34-\\u0e3a\\u0e47-\\u0e4e\\u0eb1\\u0eb4-\\u0eb9\\u0ebb\\u0ebc\\u0ec8-\\u0ecd\\u0f18\\u0f19\\u0f35\\u0f37\\u0f39\\u0f71-\\u0f7e\\u0f80-\\u0f84\\u0f86\\u0f87\\u0f90-\\u0f97\\u0f99-\\u0fbc\\u0fc6\\u102d-\\u1030\\u1032-\\u1037\\u1039\\u103a\\u103d\\u103e\\u1058\\u1059\\u105e-\\u1060\\u1071-\\u1074\\u1082\\u1085\\u1086\\u108d\\u109d\\u135f\\u1712-\\u1714\\u1732-\\u1734\\u1752\\u1753\\u1772\\u1773\\u17b7-\\u17bd\\u17c6\\u17c9-\\u17d3\\u17dd\\u180b-\\u180d\\u18a9\\u1920-\\u1922\\u1927\\u1928\\u1932\\u1939-\\u193b\\u1a17\\u1a18\\u1a56\\u1a58-\\u1a5e\\u1a60\\u1a62\\u1a65-\\u1a6c\\u1a73-\\u1a7c\\u1a7f\\u1b00-\\u1b03\\u1b34\\u1b36-\\u1b3a\\u1b3c\\u1b42\\u1b6b-\\u1b73\\u1b80\\u1b81\\u1ba2-\\u1ba5\\u1ba8\\u1ba9\\u1c2c-\\u1c33\\u1c36\\u1c37\\u1cd0-\\u1cd2\\u1cd4-\\u1ce0\\u1ce2-\\u1ce8\\u1ced\\u1dc0-\\u1de6\\u1dfd-\\u1dff\\u200c\\u200d\\u20d0-\\u20f0\\u2cef-\\u2cf1\\u2de0-\\u2dff\\u302a-\\u302f\\u3099\\u309a\\ua66f-\\ua672\\ua67c\\ua67d\\ua6f0\\ua6f1\\ua802\\ua806\\ua80b\\ua825\\ua826\\ua8c4\\ua8e0-\\ua8f1\\ua926-\\ua92d\\ua947-\\ua951\\ua980-\\ua982\\ua9b3\\ua9b6-\\ua9b9\\ua9bc\\uaa29-\\uaa2e\\uaa31\\uaa32\\uaa35\\uaa36\\uaa43\\uaa4c\\uaab0\\uaab2-\\uaab4\\uaab7\\uaab8\\uaabe\\uaabf\\uaac1\\uabe5\\uabe8\\uabed\\udc00-\\udfff\\ufb1e\\ufe00-\\ufe0f\\ufe20-\\ufe26\\uff9e\\uff9f]/;\n  function isExtendingChar(ch) { return ch.charCodeAt(0) >= 768 && extendingChars.test(ch); }\n\n  // DOM UTILITIES\n\n  function elt(tag, content, className, style) {\n    var e = document.createElement(tag);\n    if (className) e.className = className;\n    if (style) e.style.cssText = style;\n    if (typeof content == \"string\") e.appendChild(document.createTextNode(content));\n    else if (content) for (var i = 0; i < content.length; ++i) e.appendChild(content[i]);\n    return e;\n  }\n\n  var range;\n  if (document.createRange) range = function(node, start, end, endNode) {\n    var r = document.createRange();\n    r.setEnd(endNode || node, end);\n    r.setStart(node, start);\n    return r;\n  };\n  else range = function(node, start, end) {\n    var r = document.body.createTextRange();\n    try { r.moveToElementText(node.parentNode); }\n    catch(e) { return r; }\n    r.collapse(true);\n    r.moveEnd(\"character\", end);\n    r.moveStart(\"character\", start);\n    return r;\n  };\n\n  function removeChildren(e) {\n    for (var count = e.childNodes.length; count > 0; --count)\n      e.removeChild(e.firstChild);\n    return e;\n  }\n\n  function removeChildrenAndAdd(parent, e) {\n    return removeChildren(parent).appendChild(e);\n  }\n\n  var contains = CodeMirror.contains = function(parent, child) {\n    if (child.nodeType == 3) // Android browser always returns false when child is a textnode\n      child = child.parentNode;\n    if (parent.contains)\n      return parent.contains(child);\n    do {\n      if (child.nodeType == 11) child = child.host;\n      if (child == parent) return true;\n    } while (child = child.parentNode);\n  };\n\n  function activeElt() {\n    var activeElement = document.activeElement;\n    while (activeElement && activeElement.root && activeElement.root.activeElement)\n      activeElement = activeElement.root.activeElement;\n    return activeElement;\n  }\n  // Older versions of IE throws unspecified error when touching\n  // document.activeElement in some cases (during loading, in iframe)\n  if (ie && ie_version < 11) activeElt = function() {\n    try { return document.activeElement; }\n    catch(e) { return document.body; }\n  };\n\n  function classTest(cls) { return new RegExp(\"(^|\\\\s)\" + cls + \"(?:$|\\\\s)\\\\s*\"); }\n  var rmClass = CodeMirror.rmClass = function(node, cls) {\n    var current = node.className;\n    var match = classTest(cls).exec(current);\n    if (match) {\n      var after = current.slice(match.index + match[0].length);\n      node.className = current.slice(0, match.index) + (after ? match[1] + after : \"\");\n    }\n  };\n  var addClass = CodeMirror.addClass = function(node, cls) {\n    var current = node.className;\n    if (!classTest(cls).test(current)) node.className += (current ? \" \" : \"\") + cls;\n  };\n  function joinClasses(a, b) {\n    var as = a.split(\" \");\n    for (var i = 0; i < as.length; i++)\n      if (as[i] && !classTest(as[i]).test(b)) b += \" \" + as[i];\n    return b;\n  }\n\n  // WINDOW-WIDE EVENTS\n\n  // These must be handled carefully, because naively registering a\n  // handler for each editor will cause the editors to never be\n  // garbage collected.\n\n  function forEachCodeMirror(f) {\n    if (!document.body.getElementsByClassName) return;\n    var byClass = document.body.getElementsByClassName(\"CodeMirror\");\n    for (var i = 0; i < byClass.length; i++) {\n      var cm = byClass[i].CodeMirror;\n      if (cm) f(cm);\n    }\n  }\n\n  var globalsRegistered = false;\n  function ensureGlobalHandlers() {\n    if (globalsRegistered) return;\n    registerGlobalHandlers();\n    globalsRegistered = true;\n  }\n  function registerGlobalHandlers() {\n    // When the window resizes, we need to refresh active editors.\n    var resizeTimer;\n    on(window, \"resize\", function() {\n      if (resizeTimer == null) resizeTimer = setTimeout(function() {\n        resizeTimer = null;\n        forEachCodeMirror(onResize);\n      }, 100);\n    });\n    // When the window loses focus, we want to show the editor as blurred\n    on(window, \"blur\", function() {\n      forEachCodeMirror(onBlur);\n    });\n  }\n\n  // FEATURE DETECTION\n\n  // Detect drag-and-drop\n  var dragAndDrop = function() {\n    // There is *some* kind of drag-and-drop support in IE6-8, but I\n    // couldn't get it to work yet.\n    if (ie && ie_version < 9) return false;\n    var div = elt('div');\n    return \"draggable\" in div || \"dragDrop\" in div;\n  }();\n\n  var zwspSupported;\n  function zeroWidthElement(measure) {\n    if (zwspSupported == null) {\n      var test = elt(\"span\", \"\\u200b\");\n      removeChildrenAndAdd(measure, elt(\"span\", [test, document.createTextNode(\"x\")]));\n      if (measure.firstChild.offsetHeight != 0)\n        zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !(ie && ie_version < 8);\n    }\n    var node = zwspSupported ? elt(\"span\", \"\\u200b\") :\n      elt(\"span\", \"\\u00a0\", null, \"display: inline-block; width: 1px; margin-right: -1px\");\n    node.setAttribute(\"cm-text\", \"\");\n    return node;\n  }\n\n  // Feature-detect IE's crummy client rect reporting for bidi text\n  var badBidiRects;\n  function hasBadBidiRects(measure) {\n    if (badBidiRects != null) return badBidiRects;\n    var txt = removeChildrenAndAdd(measure, document.createTextNode(\"A\\u062eA\"));\n    var r0 = range(txt, 0, 1).getBoundingClientRect();\n    if (!r0 || r0.left == r0.right) return false; // Safari returns null in some cases (#2780)\n    var r1 = range(txt, 1, 2).getBoundingClientRect();\n    return badBidiRects = (r1.right - r0.right < 3);\n  }\n\n  // See if \"\".split is the broken IE version, if so, provide an\n  // alternative way to split lines.\n  var splitLinesAuto = CodeMirror.splitLines = \"\\n\\nb\".split(/\\n/).length != 3 ? function(string) {\n    var pos = 0, result = [], l = string.length;\n    while (pos <= l) {\n      var nl = string.indexOf(\"\\n\", pos);\n      if (nl == -1) nl = string.length;\n      var line = string.slice(pos, string.charAt(nl - 1) == \"\\r\" ? nl - 1 : nl);\n      var rt = line.indexOf(\"\\r\");\n      if (rt != -1) {\n        result.push(line.slice(0, rt));\n        pos += rt + 1;\n      } else {\n        result.push(line);\n        pos = nl + 1;\n      }\n    }\n    return result;\n  } : function(string){return string.split(/\\r\\n?|\\n/);};\n\n  var hasSelection = window.getSelection ? function(te) {\n    try { return te.selectionStart != te.selectionEnd; }\n    catch(e) { return false; }\n  } : function(te) {\n    try {var range = te.ownerDocument.selection.createRange();}\n    catch(e) {}\n    if (!range || range.parentElement() != te) return false;\n    return range.compareEndPoints(\"StartToEnd\", range) != 0;\n  };\n\n  var hasCopyEvent = (function() {\n    var e = elt(\"div\");\n    if (\"oncopy\" in e) return true;\n    e.setAttribute(\"oncopy\", \"return;\");\n    return typeof e.oncopy == \"function\";\n  })();\n\n  var badZoomedRects = null;\n  function hasBadZoomedRects(measure) {\n    if (badZoomedRects != null) return badZoomedRects;\n    var node = removeChildrenAndAdd(measure, elt(\"span\", \"x\"));\n    var normal = node.getBoundingClientRect();\n    var fromRange = range(node, 0, 1).getBoundingClientRect();\n    return badZoomedRects = Math.abs(normal.left - fromRange.left) > 1;\n  }\n\n  // KEY NAMES\n\n  var keyNames = CodeMirror.keyNames = {\n    3: \"Enter\", 8: \"Backspace\", 9: \"Tab\", 13: \"Enter\", 16: \"Shift\", 17: \"Ctrl\", 18: \"Alt\",\n    19: \"Pause\", 20: \"CapsLock\", 27: \"Esc\", 32: \"Space\", 33: \"PageUp\", 34: \"PageDown\", 35: \"End\",\n    36: \"Home\", 37: \"Left\", 38: \"Up\", 39: \"Right\", 40: \"Down\", 44: \"PrintScrn\", 45: \"Insert\",\n    46: \"Delete\", 59: \";\", 61: \"=\", 91: \"Mod\", 92: \"Mod\", 93: \"Mod\",\n    106: \"*\", 107: \"=\", 109: \"-\", 110: \".\", 111: \"/\", 127: \"Delete\",\n    173: \"-\", 186: \";\", 187: \"=\", 188: \",\", 189: \"-\", 190: \".\", 191: \"/\", 192: \"`\", 219: \"[\", 220: \"\\\\\",\n    221: \"]\", 222: \"'\", 63232: \"Up\", 63233: \"Down\", 63234: \"Left\", 63235: \"Right\", 63272: \"Delete\",\n    63273: \"Home\", 63275: \"End\", 63276: \"PageUp\", 63277: \"PageDown\", 63302: \"Insert\"\n  };\n  (function() {\n    // Number keys\n    for (var i = 0; i < 10; i++) keyNames[i + 48] = keyNames[i + 96] = String(i);\n    // Alphabetic keys\n    for (var i = 65; i <= 90; i++) keyNames[i] = String.fromCharCode(i);\n    // Function keys\n    for (var i = 1; i <= 12; i++) keyNames[i + 111] = keyNames[i + 63235] = \"F\" + i;\n  })();\n\n  // BIDI HELPERS\n\n  function iterateBidiSections(order, from, to, f) {\n    if (!order) return f(from, to, \"ltr\");\n    var found = false;\n    for (var i = 0; i < order.length; ++i) {\n      var part = order[i];\n      if (part.from < to && part.to > from || from == to && part.to == from) {\n        f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? \"rtl\" : \"ltr\");\n        found = true;\n      }\n    }\n    if (!found) f(from, to, \"ltr\");\n  }\n\n  function bidiLeft(part) { return part.level % 2 ? part.to : part.from; }\n  function bidiRight(part) { return part.level % 2 ? part.from : part.to; }\n\n  function lineLeft(line) { var order = getOrder(line); return order ? bidiLeft(order[0]) : 0; }\n  function lineRight(line) {\n    var order = getOrder(line);\n    if (!order) return line.text.length;\n    return bidiRight(lst(order));\n  }\n\n  function lineStart(cm, lineN) {\n    var line = getLine(cm.doc, lineN);\n    var visual = visualLine(line);\n    if (visual != line) lineN = lineNo(visual);\n    var order = getOrder(visual);\n    var ch = !order ? 0 : order[0].level % 2 ? lineRight(visual) : lineLeft(visual);\n    return Pos(lineN, ch);\n  }\n  function lineEnd(cm, lineN) {\n    var merged, line = getLine(cm.doc, lineN);\n    while (merged = collapsedSpanAtEnd(line)) {\n      line = merged.find(1, true).line;\n      lineN = null;\n    }\n    var order = getOrder(line);\n    var ch = !order ? line.text.length : order[0].level % 2 ? lineLeft(line) : lineRight(line);\n    return Pos(lineN == null ? lineNo(line) : lineN, ch);\n  }\n  function lineStartSmart(cm, pos) {\n    var start = lineStart(cm, pos.line);\n    var line = getLine(cm.doc, start.line);\n    var order = getOrder(line);\n    if (!order || order[0].level == 0) {\n      var firstNonWS = Math.max(0, line.text.search(/\\S/));\n      var inWS = pos.line == start.line && pos.ch <= firstNonWS && pos.ch;\n      return Pos(start.line, inWS ? 0 : firstNonWS);\n    }\n    return start;\n  }\n\n  function compareBidiLevel(order, a, b) {\n    var linedir = order[0].level;\n    if (a == linedir) return true;\n    if (b == linedir) return false;\n    return a < b;\n  }\n  var bidiOther;\n  function getBidiPartAt(order, pos) {\n    bidiOther = null;\n    for (var i = 0, found; i < order.length; ++i) {\n      var cur = order[i];\n      if (cur.from < pos && cur.to > pos) return i;\n      if ((cur.from == pos || cur.to == pos)) {\n        if (found == null) {\n          found = i;\n        } else if (compareBidiLevel(order, cur.level, order[found].level)) {\n          if (cur.from != cur.to) bidiOther = found;\n          return i;\n        } else {\n          if (cur.from != cur.to) bidiOther = i;\n          return found;\n        }\n      }\n    }\n    return found;\n  }\n\n  function moveInLine(line, pos, dir, byUnit) {\n    if (!byUnit) return pos + dir;\n    do pos += dir;\n    while (pos > 0 && isExtendingChar(line.text.charAt(pos)));\n    return pos;\n  }\n\n  // This is needed in order to move 'visually' through bi-directional\n  // text -- i.e., pressing left should make the cursor go left, even\n  // when in RTL text. The tricky part is the 'jumps', where RTL and\n  // LTR text touch each other. This often requires the cursor offset\n  // to move more than one unit, in order to visually move one unit.\n  function moveVisually(line, start, dir, byUnit) {\n    var bidi = getOrder(line);\n    if (!bidi) return moveLogically(line, start, dir, byUnit);\n    var pos = getBidiPartAt(bidi, start), part = bidi[pos];\n    var target = moveInLine(line, start, part.level % 2 ? -dir : dir, byUnit);\n\n    for (;;) {\n      if (target > part.from && target < part.to) return target;\n      if (target == part.from || target == part.to) {\n        if (getBidiPartAt(bidi, target) == pos) return target;\n        part = bidi[pos += dir];\n        return (dir > 0) == part.level % 2 ? part.to : part.from;\n      } else {\n        part = bidi[pos += dir];\n        if (!part) return null;\n        if ((dir > 0) == part.level % 2)\n          target = moveInLine(line, part.to, -1, byUnit);\n        else\n          target = moveInLine(line, part.from, 1, byUnit);\n      }\n    }\n  }\n\n  function moveLogically(line, start, dir, byUnit) {\n    var target = start + dir;\n    if (byUnit) while (target > 0 && isExtendingChar(line.text.charAt(target))) target += dir;\n    return target < 0 || target > line.text.length ? null : target;\n  }\n\n  // Bidirectional ordering algorithm\n  // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm\n  // that this (partially) implements.\n\n  // One-char codes used for character types:\n  // L (L):   Left-to-Right\n  // R (R):   Right-to-Left\n  // r (AL):  Right-to-Left Arabic\n  // 1 (EN):  European Number\n  // + (ES):  European Number Separator\n  // % (ET):  European Number Terminator\n  // n (AN):  Arabic Number\n  // , (CS):  Common Number Separator\n  // m (NSM): Non-Spacing Mark\n  // b (BN):  Boundary Neutral\n  // s (B):   Paragraph Separator\n  // t (S):   Segment Separator\n  // w (WS):  Whitespace\n  // N (ON):  Other Neutrals\n\n  // Returns null if characters are ordered as they appear\n  // (left-to-right), or an array of sections ({from, to, level}\n  // objects) in the order in which they occur visually.\n  var bidiOrdering = (function() {\n    // Character types for codepoints 0 to 0xff\n    var lowTypes = \"bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN\";\n    // Character types for codepoints 0x600 to 0x6ff\n    var arabicTypes = \"rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmm\";\n    function charType(code) {\n      if (code <= 0xf7) return lowTypes.charAt(code);\n      else if (0x590 <= code && code <= 0x5f4) return \"R\";\n      else if (0x600 <= code && code <= 0x6ed) return arabicTypes.charAt(code - 0x600);\n      else if (0x6ee <= code && code <= 0x8ac) return \"r\";\n      else if (0x2000 <= code && code <= 0x200b) return \"w\";\n      else if (code == 0x200c) return \"b\";\n      else return \"L\";\n    }\n\n    var bidiRE = /[\\u0590-\\u05f4\\u0600-\\u06ff\\u0700-\\u08ac]/;\n    var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/;\n    // Browsers seem to always treat the boundaries of block elements as being L.\n    var outerType = \"L\";\n\n    function BidiSpan(level, from, to) {\n      this.level = level;\n      this.from = from; this.to = to;\n    }\n\n    return function(str) {\n      if (!bidiRE.test(str)) return false;\n      var len = str.length, types = [];\n      for (var i = 0, type; i < len; ++i)\n        types.push(type = charType(str.charCodeAt(i)));\n\n      // W1. Examine each non-spacing mark (NSM) in the level run, and\n      // change the type of the NSM to the type of the previous\n      // character. If the NSM is at the start of the level run, it will\n      // get the type of sor.\n      for (var i = 0, prev = outerType; i < len; ++i) {\n        var type = types[i];\n        if (type == \"m\") types[i] = prev;\n        else prev = type;\n      }\n\n      // W2. Search backwards from each instance of a European number\n      // until the first strong type (R, L, AL, or sor) is found. If an\n      // AL is found, change the type of the European number to Arabic\n      // number.\n      // W3. Change all ALs to R.\n      for (var i = 0, cur = outerType; i < len; ++i) {\n        var type = types[i];\n        if (type == \"1\" && cur == \"r\") types[i] = \"n\";\n        else if (isStrong.test(type)) { cur = type; if (type == \"r\") types[i] = \"R\"; }\n      }\n\n      // W4. A single European separator between two European numbers\n      // changes to a European number. A single common separator between\n      // two numbers of the same type changes to that type.\n      for (var i = 1, prev = types[0]; i < len - 1; ++i) {\n        var type = types[i];\n        if (type == \"+\" && prev == \"1\" && types[i+1] == \"1\") types[i] = \"1\";\n        else if (type == \",\" && prev == types[i+1] &&\n                 (prev == \"1\" || prev == \"n\")) types[i] = prev;\n        prev = type;\n      }\n\n      // W5. A sequence of European terminators adjacent to European\n      // numbers changes to all European numbers.\n      // W6. Otherwise, separators and terminators change to Other\n      // Neutral.\n      for (var i = 0; i < len; ++i) {\n        var type = types[i];\n        if (type == \",\") types[i] = \"N\";\n        else if (type == \"%\") {\n          for (var end = i + 1; end < len && types[end] == \"%\"; ++end) {}\n          var replace = (i && types[i-1] == \"!\") || (end < len && types[end] == \"1\") ? \"1\" : \"N\";\n          for (var j = i; j < end; ++j) types[j] = replace;\n          i = end - 1;\n        }\n      }\n\n      // W7. Search backwards from each instance of a European number\n      // until the first strong type (R, L, or sor) is found. If an L is\n      // found, then change the type of the European number to L.\n      for (var i = 0, cur = outerType; i < len; ++i) {\n        var type = types[i];\n        if (cur == \"L\" && type == \"1\") types[i] = \"L\";\n        else if (isStrong.test(type)) cur = type;\n      }\n\n      // N1. A sequence of neutrals takes the direction of the\n      // surrounding strong text if the text on both sides has the same\n      // direction. European and Arabic numbers act as if they were R in\n      // terms of their influence on neutrals. Start-of-level-run (sor)\n      // and end-of-level-run (eor) are used at level run boundaries.\n      // N2. Any remaining neutrals take the embedding direction.\n      for (var i = 0; i < len; ++i) {\n        if (isNeutral.test(types[i])) {\n          for (var end = i + 1; end < len && isNeutral.test(types[end]); ++end) {}\n          var before = (i ? types[i-1] : outerType) == \"L\";\n          var after = (end < len ? types[end] : outerType) == \"L\";\n          var replace = before || after ? \"L\" : \"R\";\n          for (var j = i; j < end; ++j) types[j] = replace;\n          i = end - 1;\n        }\n      }\n\n      // Here we depart from the documented algorithm, in order to avoid\n      // building up an actual levels array. Since there are only three\n      // levels (0, 1, 2) in an implementation that doesn't take\n      // explicit embedding into account, we can build up the order on\n      // the fly, without following the level-based algorithm.\n      var order = [], m;\n      for (var i = 0; i < len;) {\n        if (countsAsLeft.test(types[i])) {\n          var start = i;\n          for (++i; i < len && countsAsLeft.test(types[i]); ++i) {}\n          order.push(new BidiSpan(0, start, i));\n        } else {\n          var pos = i, at = order.length;\n          for (++i; i < len && types[i] != \"L\"; ++i) {}\n          for (var j = pos; j < i;) {\n            if (countsAsNum.test(types[j])) {\n              if (pos < j) order.splice(at, 0, new BidiSpan(1, pos, j));\n              var nstart = j;\n              for (++j; j < i && countsAsNum.test(types[j]); ++j) {}\n              order.splice(at, 0, new BidiSpan(2, nstart, j));\n              pos = j;\n            } else ++j;\n          }\n          if (pos < i) order.splice(at, 0, new BidiSpan(1, pos, i));\n        }\n      }\n      if (order[0].level == 1 && (m = str.match(/^\\s+/))) {\n        order[0].from = m[0].length;\n        order.unshift(new BidiSpan(0, 0, m[0].length));\n      }\n      if (lst(order).level == 1 && (m = str.match(/\\s+$/))) {\n        lst(order).to -= m[0].length;\n        order.push(new BidiSpan(0, len - m[0].length, len));\n      }\n      if (order[0].level == 2)\n        order.unshift(new BidiSpan(1, order[0].to, order[0].to));\n      if (order[0].level != lst(order).level)\n        order.push(new BidiSpan(order[0].level, len, len));\n\n      return order;\n    };\n  })();\n\n  // THE END\n\n  CodeMirror.version = \"5.13.4\";\n\n  return CodeMirror;\n});\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/view/static/plugins/codemirror/mode/clike/clike.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n(function(mod) {\n  if (typeof exports == \"object\" && typeof module == \"object\") // CommonJS\n    mod(require(\"../../lib/codemirror\"));\n  else if (typeof define == \"function\" && define.amd) // AMD\n    define([\"../../lib/codemirror\"], mod);\n  else // Plain browser env\n    mod(CodeMirror);\n})(function(CodeMirror) {\n\"use strict\";\n\nfunction Context(indented, column, type, align, prev) {\n  this.indented = indented;\n  this.column = column;\n  this.type = type;\n  this.align = align;\n  this.prev = prev;\n}\nfunction isStatement(type) {\n  return type == \"statement\" || type == \"switchstatement\" || type == \"namespace\";\n}\nfunction pushContext(state, col, type) {\n  var indent = state.indented;\n  if (state.context && isStatement(state.context.type) && !isStatement(type))\n    indent = state.context.indented;\n  return state.context = new Context(indent, col, type, null, state.context);\n}\nfunction popContext(state) {\n  var t = state.context.type;\n  if (t == \")\" || t == \"]\" || t == \"}\")\n    state.indented = state.context.indented;\n  return state.context = state.context.prev;\n}\n\nfunction typeBefore(stream, state) {\n  if (state.prevToken == \"variable\" || state.prevToken == \"variable-3\") return true;\n  if (/\\S(?:[^- ]>|[*\\]])\\s*$|\\*$/.test(stream.string.slice(0, stream.start))) return true;\n}\n\nfunction isTopScope(context) {\n  for (;;) {\n    if (!context || context.type == \"top\") return true;\n    if (context.type == \"}\" && context.prev.type != \"namespace\") return false;\n    context = context.prev;\n  }\n}\n\nCodeMirror.defineMode(\"clike\", function(config, parserConfig) {\n  var indentUnit = config.indentUnit,\n      statementIndentUnit = parserConfig.statementIndentUnit || indentUnit,\n      dontAlignCalls = parserConfig.dontAlignCalls,\n      keywords = parserConfig.keywords || {},\n      types = parserConfig.types || {},\n      builtin = parserConfig.builtin || {},\n      blockKeywords = parserConfig.blockKeywords || {},\n      defKeywords = parserConfig.defKeywords || {},\n      atoms = parserConfig.atoms || {},\n      hooks = parserConfig.hooks || {},\n      multiLineStrings = parserConfig.multiLineStrings,\n      indentStatements = parserConfig.indentStatements !== false,\n      indentSwitch = parserConfig.indentSwitch !== false,\n      namespaceSeparator = parserConfig.namespaceSeparator,\n      isPunctuationChar = parserConfig.isPunctuationChar || /[\\[\\]{}\\(\\),;\\:\\.]/,\n      numberStart = parserConfig.numberStart || /[\\d\\.]/,\n      number = parserConfig.number || /^(?:0x[a-f\\d]+|0b[01]+|(?:\\d+\\.?\\d*|\\.\\d+)(?:e[-+]?\\d+)?)(u|ll?|l|f)?/i,\n      isOperatorChar = parserConfig.isOperatorChar || /[+\\-*&%=<>!?|\\/]/,\n      endStatement = parserConfig.endStatement || /^[;:,]$/;\n\n  var curPunc, isDefKeyword;\n\n  function tokenBase(stream, state) {\n    var ch = stream.next();\n    if (hooks[ch]) {\n      var result = hooks[ch](stream, state);\n      if (result !== false) return result;\n    }\n    if (ch == '\"' || ch == \"'\") {\n      state.tokenize = tokenString(ch);\n      return state.tokenize(stream, state);\n    }\n    if (isPunctuationChar.test(ch)) {\n      curPunc = ch;\n      return null;\n    }\n    if (numberStart.test(ch)) {\n      stream.backUp(1)\n      if (stream.match(number)) return \"number\"\n      stream.next()\n    }\n    if (ch == \"/\") {\n      if (stream.eat(\"*\")) {\n        state.tokenize = tokenComment;\n        return tokenComment(stream, state);\n      }\n      if (stream.eat(\"/\")) {\n        stream.skipToEnd();\n        return \"comment\";\n      }\n    }\n    if (isOperatorChar.test(ch)) {\n      while (!stream.match(/^\\/[\\/*]/, false) && stream.eat(isOperatorChar)) {}\n      return \"operator\";\n    }\n    stream.eatWhile(/[\\w\\$_\\xa1-\\uffff]/);\n    if (namespaceSeparator) while (stream.match(namespaceSeparator))\n      stream.eatWhile(/[\\w\\$_\\xa1-\\uffff]/);\n\n    var cur = stream.current();\n    if (contains(keywords, cur)) {\n      if (contains(blockKeywords, cur)) curPunc = \"newstatement\";\n      if (contains(defKeywords, cur)) isDefKeyword = true;\n      return \"keyword\";\n    }\n    if (contains(types, cur)) return \"variable-3\";\n    if (contains(builtin, cur)) {\n      if (contains(blockKeywords, cur)) curPunc = \"newstatement\";\n      return \"builtin\";\n    }\n    if (contains(atoms, cur)) return \"atom\";\n    return \"variable\";\n  }\n\n  function tokenString(quote) {\n    return function(stream, state) {\n      var escaped = false, next, end = false;\n      while ((next = stream.next()) != null) {\n        if (next == quote && !escaped) {end = true; break;}\n        escaped = !escaped && next == \"\\\\\";\n      }\n      if (end || !(escaped || multiLineStrings))\n        state.tokenize = null;\n      return \"string\";\n    };\n  }\n\n  function tokenComment(stream, state) {\n    var maybeEnd = false, ch;\n    while (ch = stream.next()) {\n      if (ch == \"/\" && maybeEnd) {\n        state.tokenize = null;\n        break;\n      }\n      maybeEnd = (ch == \"*\");\n    }\n    return \"comment\";\n  }\n\n  // Interface\n\n  return {\n    startState: function(basecolumn) {\n      return {\n        tokenize: null,\n        context: new Context((basecolumn || 0) - indentUnit, 0, \"top\", false),\n        indented: 0,\n        startOfLine: true,\n        prevToken: null\n      };\n    },\n\n    token: function(stream, state) {\n      var ctx = state.context;\n      if (stream.sol()) {\n        if (ctx.align == null) ctx.align = false;\n        state.indented = stream.indentation();\n        state.startOfLine = true;\n      }\n      if (stream.eatSpace()) return null;\n      curPunc = isDefKeyword = null;\n      var style = (state.tokenize || tokenBase)(stream, state);\n      if (style == \"comment\" || style == \"meta\") return style;\n      if (ctx.align == null) ctx.align = true;\n\n      if (endStatement.test(curPunc)) while (isStatement(state.context.type)) popContext(state);\n      else if (curPunc == \"{\") pushContext(state, stream.column(), \"}\");\n      else if (curPunc == \"[\") pushContext(state, stream.column(), \"]\");\n      else if (curPunc == \"(\") pushContext(state, stream.column(), \")\");\n      else if (curPunc == \"}\") {\n        while (isStatement(ctx.type)) ctx = popContext(state);\n        if (ctx.type == \"}\") ctx = popContext(state);\n        while (isStatement(ctx.type)) ctx = popContext(state);\n      }\n      else if (curPunc == ctx.type) popContext(state);\n      else if (indentStatements &&\n               (((ctx.type == \"}\" || ctx.type == \"top\") && curPunc != \";\") ||\n                (isStatement(ctx.type) && curPunc == \"newstatement\"))) {\n        var type = \"statement\";\n        if (curPunc == \"newstatement\" && indentSwitch && stream.current() == \"switch\")\n          type = \"switchstatement\";\n        else if (style == \"keyword\" && stream.current() == \"namespace\")\n          type = \"namespace\";\n        pushContext(state, stream.column(), type);\n      }\n\n      if (style == \"variable\" &&\n          ((state.prevToken == \"def\" ||\n            (parserConfig.typeFirstDefinitions && typeBefore(stream, state) &&\n             isTopScope(state.context) && stream.match(/^\\s*\\(/, false)))))\n        style = \"def\";\n\n      if (hooks.token) {\n        var result = hooks.token(stream, state, style);\n        if (result !== undefined) style = result;\n      }\n\n      if (style == \"def\" && parserConfig.styleDefs === false) style = \"variable\";\n\n      state.startOfLine = false;\n      state.prevToken = isDefKeyword ? \"def\" : style || curPunc;\n      return style;\n    },\n\n    indent: function(state, textAfter) {\n      if (state.tokenize != tokenBase && state.tokenize != null) return CodeMirror.Pass;\n      var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);\n      if (isStatement(ctx.type) && firstChar == \"}\") ctx = ctx.prev;\n      if (hooks.indent) {\n        var hook = hooks.indent(state, ctx, textAfter);\n        if (typeof hook == \"number\") return hook\n      }\n      var closing = firstChar == ctx.type;\n      var switchBlock = ctx.prev && ctx.prev.type == \"switchstatement\";\n      if (parserConfig.allmanIndentation && /[{(]/.test(firstChar)) {\n        while (ctx.type != \"top\" && ctx.type != \"}\") ctx = ctx.prev\n        return ctx.indented\n      }\n      if (isStatement(ctx.type))\n        return ctx.indented + (firstChar == \"{\" ? 0 : statementIndentUnit);\n      if (ctx.align && (!dontAlignCalls || ctx.type != \")\"))\n        return ctx.column + (closing ? 0 : 1);\n      if (ctx.type == \")\" && !closing)\n        return ctx.indented + statementIndentUnit;\n\n      return ctx.indented + (closing ? 0 : indentUnit) +\n        (!closing && switchBlock && !/^(?:case|default)\\b/.test(textAfter) ? indentUnit : 0);\n    },\n\n    electricInput: indentSwitch ? /^\\s*(?:case .*?:|default:|\\{\\}?|\\})$/ : /^\\s*[{}]$/,\n    blockCommentStart: \"/*\",\n    blockCommentEnd: \"*/\",\n    lineComment: \"//\",\n    fold: \"brace\"\n  };\n});\n\n  function words(str) {\n    var obj = {}, words = str.split(\" \");\n    for (var i = 0; i < words.length; ++i) obj[words[i]] = true;\n    return obj;\n  }\n  function contains(words, word) {\n    if (typeof words === \"function\") {\n      return words(word);\n    } else {\n      return words.propertyIsEnumerable(word);\n    }\n  }\n  var cKeywords = \"auto if break case register continue return default do sizeof \" +\n    \"static else struct switch extern typedef union for goto while enum const volatile\";\n  var cTypes = \"int long char short double float unsigned signed void size_t ptrdiff_t\";\n\n  function cppHook(stream, state) {\n    if (!state.startOfLine) return false\n    for (var ch, next = null; ch = stream.peek();) {\n      if (ch == \"\\\\\" && stream.match(/^.$/)) {\n        next = cppHook\n        break\n      } else if (ch == \"/\" && stream.match(/^\\/[\\/\\*]/, false)) {\n        break\n      }\n      stream.next()\n    }\n    state.tokenize = next\n    return \"meta\"\n  }\n\n  function pointerHook(_stream, state) {\n    if (state.prevToken == \"variable-3\") return \"variable-3\";\n    return false;\n  }\n\n  function cpp14Literal(stream) {\n    stream.eatWhile(/[\\w\\.']/);\n    return \"number\";\n  }\n\n  function cpp11StringHook(stream, state) {\n    stream.backUp(1);\n    // Raw strings.\n    if (stream.match(/(R|u8R|uR|UR|LR)/)) {\n      var match = stream.match(/\"([^\\s\\\\()]{0,16})\\(/);\n      if (!match) {\n        return false;\n      }\n      state.cpp11RawStringDelim = match[1];\n      state.tokenize = tokenRawString;\n      return tokenRawString(stream, state);\n    }\n    // Unicode strings/chars.\n    if (stream.match(/(u8|u|U|L)/)) {\n      if (stream.match(/[\"']/, /* eat */ false)) {\n        return \"string\";\n      }\n      return false;\n    }\n    // Ignore this hook.\n    stream.next();\n    return false;\n  }\n\n  function cppLooksLikeConstructor(word) {\n    var lastTwo = /(\\w+)::(\\w+)$/.exec(word);\n    return lastTwo && lastTwo[1] == lastTwo[2];\n  }\n\n  // C#-style strings where \"\" escapes a quote.\n  function tokenAtString(stream, state) {\n    var next;\n    while ((next = stream.next()) != null) {\n      if (next == '\"' && !stream.eat('\"')) {\n        state.tokenize = null;\n        break;\n      }\n    }\n    return \"string\";\n  }\n\n  // C++11 raw string literal is <prefix>\"<delim>( anything )<delim>\", where\n  // <delim> can be a string up to 16 characters long.\n  function tokenRawString(stream, state) {\n    // Escape characters that have special regex meanings.\n    var delim = state.cpp11RawStringDelim.replace(/[^\\w\\s]/g, '\\\\$&');\n    var match = stream.match(new RegExp(\".*?\\\\)\" + delim + '\"'));\n    if (match)\n      state.tokenize = null;\n    else\n      stream.skipToEnd();\n    return \"string\";\n  }\n\n  function def(mimes, mode) {\n    if (typeof mimes == \"string\") mimes = [mimes];\n    var words = [];\n    function add(obj) {\n      if (obj) for (var prop in obj) if (obj.hasOwnProperty(prop))\n        words.push(prop);\n    }\n    add(mode.keywords);\n    add(mode.types);\n    add(mode.builtin);\n    add(mode.atoms);\n    if (words.length) {\n      mode.helperType = mimes[0];\n      CodeMirror.registerHelper(\"hintWords\", mimes[0], words);\n    }\n\n    for (var i = 0; i < mimes.length; ++i)\n      CodeMirror.defineMIME(mimes[i], mode);\n  }\n\n  def([\"text/x-csrc\", \"text/x-c\", \"text/x-chdr\"], {\n    name: \"clike\",\n    keywords: words(cKeywords),\n    types: words(cTypes + \" bool _Complex _Bool float_t double_t intptr_t intmax_t \" +\n                 \"int8_t int16_t int32_t int64_t uintptr_t uintmax_t uint8_t uint16_t \" +\n                 \"uint32_t uint64_t\"),\n    blockKeywords: words(\"case do else for if switch while struct\"),\n    defKeywords: words(\"struct\"),\n    typeFirstDefinitions: true,\n    atoms: words(\"null true false\"),\n    hooks: {\"#\": cppHook, \"*\": pointerHook},\n    modeProps: {fold: [\"brace\", \"include\"]}\n  });\n\n  def([\"text/x-c++src\", \"text/x-c++hdr\"], {\n    name: \"clike\",\n    keywords: words(cKeywords + \" asm dynamic_cast namespace reinterpret_cast try explicit new \" +\n                    \"static_cast typeid catch operator template typename class friend private \" +\n                    \"this using const_cast inline public throw virtual delete mutable protected \" +\n                    \"alignas alignof constexpr decltype nullptr noexcept thread_local final \" +\n                    \"static_assert override\"),\n    types: words(cTypes + \" bool wchar_t\"),\n    blockKeywords: words(\"catch class do else finally for if struct switch try while\"),\n    defKeywords: words(\"class namespace struct enum union\"),\n    typeFirstDefinitions: true,\n    atoms: words(\"true false null\"),\n    hooks: {\n      \"#\": cppHook,\n      \"*\": pointerHook,\n      \"u\": cpp11StringHook,\n      \"U\": cpp11StringHook,\n      \"L\": cpp11StringHook,\n      \"R\": cpp11StringHook,\n      \"0\": cpp14Literal,\n      \"1\": cpp14Literal,\n      \"2\": cpp14Literal,\n      \"3\": cpp14Literal,\n      \"4\": cpp14Literal,\n      \"5\": cpp14Literal,\n      \"6\": cpp14Literal,\n      \"7\": cpp14Literal,\n      \"8\": cpp14Literal,\n      \"9\": cpp14Literal,\n      token: function(stream, state, style) {\n        if (style == \"variable\" && stream.peek() == \"(\" &&\n            (state.prevToken == \";\" || state.prevToken == null ||\n             state.prevToken == \"}\") &&\n            cppLooksLikeConstructor(stream.current()))\n          return \"def\";\n      }\n    },\n    namespaceSeparator: \"::\",\n    modeProps: {fold: [\"brace\", \"include\"]}\n  });\n\n  def(\"text/x-java\", {\n    name: \"clike\",\n    keywords: words(\"abstract assert break case catch class const continue default \" +\n                    \"do else enum extends final finally float for goto if implements import \" +\n                    \"instanceof interface native new package private protected public \" +\n                    \"return static strictfp super switch synchronized this throw throws transient \" +\n                    \"try volatile while\"),\n    types: words(\"byte short int long float double boolean char void Boolean Byte Character Double Float \" +\n                 \"Integer Long Number Object Short String StringBuffer StringBuilder Void\"),\n    blockKeywords: words(\"catch class do else finally for if switch try while\"),\n    defKeywords: words(\"class interface package enum\"),\n    typeFirstDefinitions: true,\n    atoms: words(\"true false null\"),\n    endStatement: /^[;:]$/,\n    hooks: {\n      \"@\": function(stream) {\n        stream.eatWhile(/[\\w\\$_]/);\n        return \"meta\";\n      }\n    },\n    modeProps: {fold: [\"brace\", \"import\"]}\n  });\n\n  def(\"text/x-csharp\", {\n    name: \"clike\",\n    keywords: words(\"abstract as async await base break case catch checked class const continue\" +\n                    \" default delegate do else enum event explicit extern finally fixed for\" +\n                    \" foreach goto if implicit in interface internal is lock namespace new\" +\n                    \" operator out override params private protected public readonly ref return sealed\" +\n                    \" sizeof stackalloc static struct switch this throw try typeof unchecked\" +\n                    \" unsafe using virtual void volatile while add alias ascending descending dynamic from get\" +\n                    \" global group into join let orderby partial remove select set value var yield\"),\n    types: words(\"Action Boolean Byte Char DateTime DateTimeOffset Decimal Double Func\" +\n                 \" Guid Int16 Int32 Int64 Object SByte Single String Task TimeSpan UInt16 UInt32\" +\n                 \" UInt64 bool byte char decimal double short int long object\"  +\n                 \" sbyte float string ushort uint ulong\"),\n    blockKeywords: words(\"catch class do else finally for foreach if struct switch try while\"),\n    defKeywords: words(\"class interface namespace struct var\"),\n    typeFirstDefinitions: true,\n    atoms: words(\"true false null\"),\n    hooks: {\n      \"@\": function(stream, state) {\n        if (stream.eat('\"')) {\n          state.tokenize = tokenAtString;\n          return tokenAtString(stream, state);\n        }\n        stream.eatWhile(/[\\w\\$_]/);\n        return \"meta\";\n      }\n    }\n  });\n\n  function tokenTripleString(stream, state) {\n    var escaped = false;\n    while (!stream.eol()) {\n      if (!escaped && stream.match('\"\"\"')) {\n        state.tokenize = null;\n        break;\n      }\n      escaped = stream.next() == \"\\\\\" && !escaped;\n    }\n    return \"string\";\n  }\n\n  def(\"text/x-scala\", {\n    name: \"clike\",\n    keywords: words(\n\n      /* scala */\n      \"abstract case catch class def do else extends final finally for forSome if \" +\n      \"implicit import lazy match new null object override package private protected return \" +\n      \"sealed super this throw trait try type val var while with yield _ : = => <- <: \" +\n      \"<% >: # @ \" +\n\n      /* package scala */\n      \"assert assume require print println printf readLine readBoolean readByte readShort \" +\n      \"readChar readInt readLong readFloat readDouble \" +\n\n      \":: #:: \"\n    ),\n    types: words(\n      \"AnyVal App Application Array BufferedIterator BigDecimal BigInt Char Console Either \" +\n      \"Enumeration Equiv Error Exception Fractional Function IndexedSeq Int Integral Iterable \" +\n      \"Iterator List Map Numeric Nil NotNull Option Ordered Ordering PartialFunction PartialOrdering \" +\n      \"Product Proxy Range Responder Seq Serializable Set Specializable Stream StringBuilder \" +\n      \"StringContext Symbol Throwable Traversable TraversableOnce Tuple Unit Vector \" +\n\n      /* package java.lang */\n      \"Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable \" +\n      \"Compiler Double Exception Float Integer Long Math Number Object Package Pair Process \" +\n      \"Runtime Runnable SecurityManager Short StackTraceElement StrictMath String \" +\n      \"StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void\"\n    ),\n    multiLineStrings: true,\n    blockKeywords: words(\"catch class do else finally for forSome if match switch try while\"),\n    defKeywords: words(\"class def object package trait type val var\"),\n    atoms: words(\"true false null\"),\n    indentStatements: false,\n    indentSwitch: false,\n    hooks: {\n      \"@\": function(stream) {\n        stream.eatWhile(/[\\w\\$_]/);\n        return \"meta\";\n      },\n      '\"': function(stream, state) {\n        if (!stream.match('\"\"')) return false;\n        state.tokenize = tokenTripleString;\n        return state.tokenize(stream, state);\n      },\n      \"'\": function(stream) {\n        stream.eatWhile(/[\\w\\$_\\xa1-\\uffff]/);\n        return \"atom\";\n      },\n      \"=\": function(stream, state) {\n        var cx = state.context\n        if (cx.type == \"}\" && cx.align && stream.eat(\">\")) {\n          state.context = new Context(cx.indented, cx.column, cx.type, null, cx.prev)\n          return \"operator\"\n        } else {\n          return false\n        }\n      }\n    },\n    modeProps: {closeBrackets: {triples: '\"'}}\n  });\n\n  function tokenKotlinString(tripleString){\n    return function (stream, state) {\n      var escaped = false, next, end = false;\n      while (!stream.eol()) {\n        if (!tripleString && !escaped && stream.match('\"') ) {end = true; break;}\n        if (tripleString && stream.match('\"\"\"')) {end = true; break;}\n        next = stream.next();\n        if(!escaped && next == \"$\" && stream.match('{'))\n          stream.skipTo(\"}\");\n        escaped = !escaped && next == \"\\\\\" && !tripleString;\n      }\n      if (end || !tripleString)\n        state.tokenize = null;\n      return \"string\";\n    }\n  }\n\n  def(\"text/x-kotlin\", {\n    name: \"clike\",\n    keywords: words(\n      /*keywords*/\n      \"package as typealias class interface this super val \" +\n      \"var fun for is in This throw return \" +\n      \"break continue object if else while do try when !in !is as? \" +\n\n      /*soft keywords*/\n      \"file import where by get set abstract enum open inner override private public internal \" +\n      \"protected catch finally out final vararg reified dynamic companion constructor init \" +\n      \"sealed field property receiver param sparam lateinit data inline noinline tailrec \" +\n      \"external annotation crossinline const operator infix\"\n    ),\n    types: words(\n      /* package java.lang */\n      \"Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable \" +\n      \"Compiler Double Exception Float Integer Long Math Number Object Package Pair Process \" +\n      \"Runtime Runnable SecurityManager Short StackTraceElement StrictMath String \" +\n      \"StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void\"\n    ),\n    intendSwitch: false,\n    indentStatements: false,\n    multiLineStrings: true,\n    blockKeywords: words(\"catch class do else finally for if where try while enum\"),\n    defKeywords: words(\"class val var object package interface fun\"),\n    atoms: words(\"true false null this\"),\n    hooks: {\n      '\"': function(stream, state) {\n        state.tokenize = tokenKotlinString(stream.match('\"\"'));\n        return state.tokenize(stream, state);\n      }\n    },\n    modeProps: {closeBrackets: {triples: '\"'}}\n  });\n\n  def([\"x-shader/x-vertex\", \"x-shader/x-fragment\"], {\n    name: \"clike\",\n    keywords: words(\"sampler1D sampler2D sampler3D samplerCube \" +\n                    \"sampler1DShadow sampler2DShadow \" +\n                    \"const attribute uniform varying \" +\n                    \"break continue discard return \" +\n                    \"for while do if else struct \" +\n                    \"in out inout\"),\n    types: words(\"float int bool void \" +\n                 \"vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 \" +\n                 \"mat2 mat3 mat4\"),\n    blockKeywords: words(\"for while do if else struct\"),\n    builtin: words(\"radians degrees sin cos tan asin acos atan \" +\n                    \"pow exp log exp2 sqrt inversesqrt \" +\n                    \"abs sign floor ceil fract mod min max clamp mix step smoothstep \" +\n                    \"length distance dot cross normalize ftransform faceforward \" +\n                    \"reflect refract matrixCompMult \" +\n                    \"lessThan lessThanEqual greaterThan greaterThanEqual \" +\n                    \"equal notEqual any all not \" +\n                    \"texture1D texture1DProj texture1DLod texture1DProjLod \" +\n                    \"texture2D texture2DProj texture2DLod texture2DProjLod \" +\n                    \"texture3D texture3DProj texture3DLod texture3DProjLod \" +\n                    \"textureCube textureCubeLod \" +\n                    \"shadow1D shadow2D shadow1DProj shadow2DProj \" +\n                    \"shadow1DLod shadow2DLod shadow1DProjLod shadow2DProjLod \" +\n                    \"dFdx dFdy fwidth \" +\n                    \"noise1 noise2 noise3 noise4\"),\n    atoms: words(\"true false \" +\n                \"gl_FragColor gl_SecondaryColor gl_Normal gl_Vertex \" +\n                \"gl_MultiTexCoord0 gl_MultiTexCoord1 gl_MultiTexCoord2 gl_MultiTexCoord3 \" +\n                \"gl_MultiTexCoord4 gl_MultiTexCoord5 gl_MultiTexCoord6 gl_MultiTexCoord7 \" +\n                \"gl_FogCoord gl_PointCoord \" +\n                \"gl_Position gl_PointSize gl_ClipVertex \" +\n                \"gl_FrontColor gl_BackColor gl_FrontSecondaryColor gl_BackSecondaryColor \" +\n                \"gl_TexCoord gl_FogFragCoord \" +\n                \"gl_FragCoord gl_FrontFacing \" +\n                \"gl_FragData gl_FragDepth \" +\n                \"gl_ModelViewMatrix gl_ProjectionMatrix gl_ModelViewProjectionMatrix \" +\n                \"gl_TextureMatrix gl_NormalMatrix gl_ModelViewMatrixInverse \" +\n                \"gl_ProjectionMatrixInverse gl_ModelViewProjectionMatrixInverse \" +\n                \"gl_TexureMatrixTranspose gl_ModelViewMatrixInverseTranspose \" +\n                \"gl_ProjectionMatrixInverseTranspose \" +\n                \"gl_ModelViewProjectionMatrixInverseTranspose \" +\n                \"gl_TextureMatrixInverseTranspose \" +\n                \"gl_NormalScale gl_DepthRange gl_ClipPlane \" +\n                \"gl_Point gl_FrontMaterial gl_BackMaterial gl_LightSource gl_LightModel \" +\n                \"gl_FrontLightModelProduct gl_BackLightModelProduct \" +\n                \"gl_TextureColor gl_EyePlaneS gl_EyePlaneT gl_EyePlaneR gl_EyePlaneQ \" +\n                \"gl_FogParameters \" +\n                \"gl_MaxLights gl_MaxClipPlanes gl_MaxTextureUnits gl_MaxTextureCoords \" +\n                \"gl_MaxVertexAttribs gl_MaxVertexUniformComponents gl_MaxVaryingFloats \" +\n                \"gl_MaxVertexTextureImageUnits gl_MaxTextureImageUnits \" +\n                \"gl_MaxFragmentUniformComponents gl_MaxCombineTextureImageUnits \" +\n                \"gl_MaxDrawBuffers\"),\n    indentSwitch: false,\n    hooks: {\"#\": cppHook},\n    modeProps: {fold: [\"brace\", \"include\"]}\n  });\n\n  def(\"text/x-nesc\", {\n    name: \"clike\",\n    keywords: words(cKeywords + \"as atomic async call command component components configuration event generic \" +\n                    \"implementation includes interface module new norace nx_struct nx_union post provides \" +\n                    \"signal task uses abstract extends\"),\n    types: words(cTypes),\n    blockKeywords: words(\"case do else for if switch while struct\"),\n    atoms: words(\"null true false\"),\n    hooks: {\"#\": cppHook},\n    modeProps: {fold: [\"brace\", \"include\"]}\n  });\n\n  def(\"text/x-objectivec\", {\n    name: \"clike\",\n    keywords: words(cKeywords + \"inline restrict _Bool _Complex _Imaginery BOOL Class bycopy byref id IMP in \" +\n                    \"inout nil oneway out Protocol SEL self super atomic nonatomic retain copy readwrite readonly\"),\n    types: words(cTypes),\n    atoms: words(\"YES NO NULL NILL ON OFF true false\"),\n    hooks: {\n      \"@\": function(stream) {\n        stream.eatWhile(/[\\w\\$]/);\n        return \"keyword\";\n      },\n      \"#\": cppHook,\n      indent: function(_state, ctx, textAfter) {\n        if (ctx.type == \"statement\" && /^@\\w/.test(textAfter)) return ctx.indented\n      }\n    },\n    modeProps: {fold: \"brace\"}\n  });\n\n  def(\"text/x-squirrel\", {\n    name: \"clike\",\n    keywords: words(\"base break clone continue const default delete enum extends function in class\" +\n                    \" foreach local resume return this throw typeof yield constructor instanceof static\"),\n    types: words(cTypes),\n    blockKeywords: words(\"case catch class else for foreach if switch try while\"),\n    defKeywords: words(\"function local class\"),\n    typeFirstDefinitions: true,\n    atoms: words(\"true false null\"),\n    hooks: {\"#\": cppHook},\n    modeProps: {fold: [\"brace\", \"include\"]}\n  });\n\n  // Ceylon Strings need to deal with interpolation\n  var stringTokenizer = null;\n  function tokenCeylonString(type) {\n    return function(stream, state) {\n      var escaped = false, next, end = false;\n      while (!stream.eol()) {\n        if (!escaped && stream.match('\"') &&\n              (type == \"single\" || stream.match('\"\"'))) {\n          end = true;\n          break;\n        }\n        if (!escaped && stream.match('``')) {\n          stringTokenizer = tokenCeylonString(type);\n          end = true;\n          break;\n        }\n        next = stream.next();\n        escaped = type == \"single\" && !escaped && next == \"\\\\\";\n      }\n      if (end)\n          state.tokenize = null;\n      return \"string\";\n    }\n  }\n\n  def(\"text/x-ceylon\", {\n    name: \"clike\",\n    keywords: words(\"abstracts alias assembly assert assign break case catch class continue dynamic else\" +\n                    \" exists extends finally for function given if import in interface is let module new\" +\n                    \" nonempty object of out outer package return satisfies super switch then this throw\" +\n                    \" try value void while\"),\n    types: function(word) {\n        // In Ceylon all identifiers that start with an uppercase are types\n        var first = word.charAt(0);\n        return (first === first.toUpperCase() && first !== first.toLowerCase());\n    },\n    blockKeywords: words(\"case catch class dynamic else finally for function if interface module new object switch try while\"),\n    defKeywords: words(\"class dynamic function interface module object package value\"),\n    builtin: words(\"abstract actual aliased annotation by default deprecated doc final formal late license\" +\n                   \" native optional sealed see serializable shared suppressWarnings tagged throws variable\"),\n    isPunctuationChar: /[\\[\\]{}\\(\\),;\\:\\.`]/,\n    isOperatorChar: /[+\\-*&%=<>!?|^~:\\/]/,\n    numberStart: /[\\d#$]/,\n    number: /^(?:#[\\da-fA-F_]+|\\$[01_]+|[\\d_]+[kMGTPmunpf]?|[\\d_]+\\.[\\d_]+(?:[eE][-+]?\\d+|[kMGTPmunpf]|)|)/i,\n    multiLineStrings: true,\n    typeFirstDefinitions: true,\n    atoms: words(\"true false null larger smaller equal empty finished\"),\n    indentSwitch: false,\n    styleDefs: false,\n    hooks: {\n      \"@\": function(stream) {\n        stream.eatWhile(/[\\w\\$_]/);\n        return \"meta\";\n      },\n      '\"': function(stream, state) {\n          state.tokenize = tokenCeylonString(stream.match('\"\"') ? \"triple\" : \"single\");\n          return state.tokenize(stream, state);\n        },\n      '`': function(stream, state) {\n          if (!stringTokenizer || !stream.match('`')) return false;\n          state.tokenize = stringTokenizer;\n          stringTokenizer = null;\n          return state.tokenize(stream, state);\n        },\n      \"'\": function(stream) {\n        stream.eatWhile(/[\\w\\$_\\xa1-\\uffff]/);\n        return \"atom\";\n      },\n      token: function(_stream, state, style) {\n          if ((style == \"variable\" || style == \"variable-3\") &&\n              state.prevToken == \".\") {\n            return \"variable-2\";\n          }\n        }\n    },\n    modeProps: {\n        fold: [\"brace\", \"import\"],\n        closeBrackets: {triples: '\"'}\n    }\n  });\n\n});\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/view/static/plugins/codemirror/mode/python/python.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n(function(mod) {\n  if (typeof exports == \"object\" && typeof module == \"object\") // CommonJS\n    mod(require(\"../../lib/codemirror\"));\n  else if (typeof define == \"function\" && define.amd) // AMD\n    define([\"../../lib/codemirror\"], mod);\n  else // Plain browser env\n    mod(CodeMirror);\n})(function(CodeMirror) {\n  \"use strict\";\n\n  function wordRegexp(words) {\n    return new RegExp(\"^((\" + words.join(\")|(\") + \"))\\\\b\");\n  }\n\n  var wordOperators = wordRegexp([\"and\", \"or\", \"not\", \"is\"]);\n  var commonKeywords = [\"as\", \"assert\", \"break\", \"class\", \"continue\",\n                        \"def\", \"del\", \"elif\", \"else\", \"except\", \"finally\",\n                        \"for\", \"from\", \"global\", \"if\", \"import\",\n                        \"lambda\", \"pass\", \"raise\", \"return\",\n                        \"try\", \"while\", \"with\", \"yield\", \"in\"];\n  var commonBuiltins = [\"abs\", \"all\", \"any\", \"bin\", \"bool\", \"bytearray\", \"callable\", \"chr\",\n                        \"classmethod\", \"compile\", \"complex\", \"delattr\", \"dict\", \"dir\", \"divmod\",\n                        \"enumerate\", \"eval\", \"filter\", \"float\", \"format\", \"frozenset\",\n                        \"getattr\", \"globals\", \"hasattr\", \"hash\", \"help\", \"hex\", \"id\",\n                        \"input\", \"int\", \"isinstance\", \"issubclass\", \"iter\", \"len\",\n                        \"list\", \"locals\", \"map\", \"max\", \"memoryview\", \"min\", \"next\",\n                        \"object\", \"oct\", \"open\", \"ord\", \"pow\", \"property\", \"range\",\n                        \"repr\", \"reversed\", \"round\", \"set\", \"setattr\", \"slice\",\n                        \"sorted\", \"staticmethod\", \"str\", \"sum\", \"super\", \"tuple\",\n                        \"type\", \"vars\", \"zip\", \"__import__\", \"NotImplemented\",\n                        \"Ellipsis\", \"__debug__\"];\n  CodeMirror.registerHelper(\"hintWords\", \"python\", commonKeywords.concat(commonBuiltins));\n\n  function top(state) {\n    return state.scopes[state.scopes.length - 1];\n  }\n\n  CodeMirror.defineMode(\"python\", function(conf, parserConf) {\n    var ERRORCLASS = \"error\";\n\n    var singleDelimiters = parserConf.singleDelimiters || /^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]/;\n    var doubleOperators = parserConf.doubleOperators || /^([!<>]==|<>|<<|>>|\\/\\/|\\*\\*)/;\n    var doubleDelimiters = parserConf.doubleDelimiters || /^(\\+=|\\-=|\\*=|%=|\\/=|&=|\\|=|\\^=)/;\n    var tripleDelimiters = parserConf.tripleDelimiters || /^(\\/\\/=|>>=|<<=|\\*\\*=)/;\n\n    var hangingIndent = parserConf.hangingIndent || conf.indentUnit;\n\n    var myKeywords = commonKeywords, myBuiltins = commonBuiltins;\n    if (parserConf.extra_keywords != undefined)\n      myKeywords = myKeywords.concat(parserConf.extra_keywords);\n\n    if (parserConf.extra_builtins != undefined)\n      myBuiltins = myBuiltins.concat(parserConf.extra_builtins);\n\n    var py3 = !(parserConf.version && Number(parserConf.version) < 3)\n    if (py3) {\n      // since http://legacy.python.org/dev/peps/pep-0465/ @ is also an operator\n      var singleOperators = parserConf.singleOperators || /^[\\+\\-\\*\\/%&|\\^~<>!@]/;\n      var identifiers = parserConf.identifiers|| /^[_A-Za-z\\u00A1-\\uFFFF][_A-Za-z0-9\\u00A1-\\uFFFF]*/;\n      myKeywords = myKeywords.concat([\"nonlocal\", \"False\", \"True\", \"None\", \"async\", \"await\"]);\n      myBuiltins = myBuiltins.concat([\"ascii\", \"bytes\", \"exec\", \"print\"]);\n      var stringPrefixes = new RegExp(\"^(([rbuf]|(br))?('{3}|\\\"{3}|['\\\"]))\", \"i\");\n    } else {\n      var singleOperators = parserConf.singleOperators || /^[\\+\\-\\*\\/%&|\\^~<>!]/;\n      var identifiers = parserConf.identifiers|| /^[_A-Za-z][_A-Za-z0-9]*/;\n      myKeywords = myKeywords.concat([\"exec\", \"print\"]);\n      myBuiltins = myBuiltins.concat([\"apply\", \"basestring\", \"buffer\", \"cmp\", \"coerce\", \"execfile\",\n                                      \"file\", \"intern\", \"long\", \"raw_input\", \"reduce\", \"reload\",\n                                      \"unichr\", \"unicode\", \"xrange\", \"False\", \"True\", \"None\"]);\n      var stringPrefixes = new RegExp(\"^(([rubf]|(ur)|(br))?('{3}|\\\"{3}|['\\\"]))\", \"i\");\n    }\n    var keywords = wordRegexp(myKeywords);\n    var builtins = wordRegexp(myBuiltins);\n\n    // tokenizers\n    function tokenBase(stream, state) {\n      if (stream.sol()) state.indent = stream.indentation()\n      // Handle scope changes\n      if (stream.sol() && top(state).type == \"py\") {\n        var scopeOffset = top(state).offset;\n        if (stream.eatSpace()) {\n          var lineOffset = stream.indentation();\n          if (lineOffset > scopeOffset)\n            pushPyScope(state);\n          else if (lineOffset < scopeOffset && dedent(stream, state) && stream.peek() != \"#\")\n            state.errorToken = true;\n          return null;\n        } else {\n          var style = tokenBaseInner(stream, state);\n          if (scopeOffset > 0 && dedent(stream, state))\n            style += \" \" + ERRORCLASS;\n          return style;\n        }\n      }\n      return tokenBaseInner(stream, state);\n    }\n\n    function tokenBaseInner(stream, state) {\n      if (stream.eatSpace()) return null;\n\n      var ch = stream.peek();\n\n      // Handle Comments\n      if (ch == \"#\") {\n        stream.skipToEnd();\n        return \"comment\";\n      }\n\n      // Handle Number Literals\n      if (stream.match(/^[0-9\\.]/, false)) {\n        var floatLiteral = false;\n        // Floats\n        if (stream.match(/^[\\d_]*\\.\\d+(e[\\+\\-]?\\d+)?/i)) { floatLiteral = true; }\n        if (stream.match(/^[\\d_]+\\.\\d*/)) { floatLiteral = true; }\n        if (stream.match(/^\\.\\d+/)) { floatLiteral = true; }\n        if (floatLiteral) {\n          // Float literals may be \"imaginary\"\n          stream.eat(/J/i);\n          return \"number\";\n        }\n        // Integers\n        var intLiteral = false;\n        // Hex\n        if (stream.match(/^0x[0-9a-f_]+/i)) intLiteral = true;\n        // Binary\n        if (stream.match(/^0b[01_]+/i)) intLiteral = true;\n        // Octal\n        if (stream.match(/^0o[0-7_]+/i)) intLiteral = true;\n        // Decimal\n        if (stream.match(/^[1-9][\\d_]*(e[\\+\\-]?[\\d_]+)?/)) {\n          // Decimal literals may be \"imaginary\"\n          stream.eat(/J/i);\n          // TODO - Can you have imaginary longs?\n          intLiteral = true;\n        }\n        // Zero by itself with no other piece of number.\n        if (stream.match(/^0(?![\\dx])/i)) intLiteral = true;\n        if (intLiteral) {\n          // Integer literals may be \"long\"\n          stream.eat(/L/i);\n          return \"number\";\n        }\n      }\n\n      // Handle Strings\n      if (stream.match(stringPrefixes)) {\n        state.tokenize = tokenStringFactory(stream.current());\n        return state.tokenize(stream, state);\n      }\n\n      // Handle operators and Delimiters\n      if (stream.match(tripleDelimiters) || stream.match(doubleDelimiters))\n        return \"punctuation\";\n\n      if (stream.match(doubleOperators) || stream.match(singleOperators))\n        return \"operator\";\n\n      if (stream.match(singleDelimiters))\n        return \"punctuation\";\n\n      if (state.lastToken == \".\" && stream.match(identifiers))\n        return \"property\";\n\n      if (stream.match(keywords) || stream.match(wordOperators))\n        return \"keyword\";\n\n      if (stream.match(builtins))\n        return \"builtin\";\n\n      if (stream.match(/^(self|cls)\\b/))\n        return \"variable-2\";\n\n      if (stream.match(identifiers)) {\n        if (state.lastToken == \"def\" || state.lastToken == \"class\")\n          return \"def\";\n        return \"variable\";\n      }\n\n      // Handle non-detected items\n      stream.next();\n      return ERRORCLASS;\n    }\n\n    function tokenStringFactory(delimiter) {\n      while (\"rubf\".indexOf(delimiter.charAt(0).toLowerCase()) >= 0)\n        delimiter = delimiter.substr(1);\n\n      var singleline = delimiter.length == 1;\n      var OUTCLASS = \"string\";\n\n      function tokenString(stream, state) {\n        while (!stream.eol()) {\n          stream.eatWhile(/[^'\"\\\\]/);\n          if (stream.eat(\"\\\\\")) {\n            stream.next();\n            if (singleline && stream.eol())\n              return OUTCLASS;\n          } else if (stream.match(delimiter)) {\n            state.tokenize = tokenBase;\n            return OUTCLASS;\n          } else {\n            stream.eat(/['\"]/);\n          }\n        }\n        if (singleline) {\n          if (parserConf.singleLineStringErrors)\n            return ERRORCLASS;\n          else\n            state.tokenize = tokenBase;\n        }\n        return OUTCLASS;\n      }\n      tokenString.isString = true;\n      return tokenString;\n    }\n\n    function pushPyScope(state) {\n      while (top(state).type != \"py\") state.scopes.pop()\n      state.scopes.push({offset: top(state).offset + conf.indentUnit,\n                         type: \"py\",\n                         align: null})\n    }\n\n    function pushBracketScope(stream, state, type) {\n      var align = stream.match(/^([\\s\\[\\{\\(]|#.*)*$/, false) ? null : stream.column() + 1\n      state.scopes.push({offset: state.indent + hangingIndent,\n                         type: type,\n                         align: align})\n    }\n\n    function dedent(stream, state) {\n      var indented = stream.indentation();\n      while (state.scopes.length > 1 && top(state).offset > indented) {\n        if (top(state).type != \"py\") return true;\n        state.scopes.pop();\n      }\n      return top(state).offset != indented;\n    }\n\n    function tokenLexer(stream, state) {\n      if (stream.sol()) state.beginningOfLine = true;\n\n      var style = state.tokenize(stream, state);\n      var current = stream.current();\n\n      // Handle decorators\n      if (state.beginningOfLine && current == \"@\")\n        return stream.match(identifiers, false) ? \"meta\" : py3 ? \"operator\" : ERRORCLASS;\n\n      if (/\\S/.test(current)) state.beginningOfLine = false;\n\n      if ((style == \"variable\" || style == \"builtin\")\n          && state.lastToken == \"meta\")\n        style = \"meta\";\n\n      // Handle scope changes.\n      if (current == \"pass\" || current == \"return\")\n        state.dedent += 1;\n\n      if (current == \"lambda\") state.lambda = true;\n      if (current == \":\" && !state.lambda && top(state).type == \"py\")\n        pushPyScope(state);\n\n      var delimiter_index = current.length == 1 ? \"[({\".indexOf(current) : -1;\n      if (delimiter_index != -1)\n        pushBracketScope(stream, state, \"])}\".slice(delimiter_index, delimiter_index+1));\n\n      delimiter_index = \"])}\".indexOf(current);\n      if (delimiter_index != -1) {\n        if (top(state).type == current) state.indent = state.scopes.pop().offset - hangingIndent\n        else return ERRORCLASS;\n      }\n      if (state.dedent > 0 && stream.eol() && top(state).type == \"py\") {\n        if (state.scopes.length > 1) state.scopes.pop();\n        state.dedent -= 1;\n      }\n\n      return style;\n    }\n\n    var external = {\n      startState: function(basecolumn) {\n        return {\n          tokenize: tokenBase,\n          scopes: [{offset: basecolumn || 0, type: \"py\", align: null}],\n          indent: basecolumn || 0,\n          lastToken: null,\n          lambda: false,\n          dedent: 0\n        };\n      },\n\n      token: function(stream, state) {\n        var addErr = state.errorToken;\n        if (addErr) state.errorToken = false;\n        var style = tokenLexer(stream, state);\n\n        if (style && style != \"comment\")\n          state.lastToken = (style == \"keyword\" || style == \"punctuation\") ? stream.current() : style;\n        if (style == \"punctuation\") style = null;\n\n        if (stream.eol() && state.lambda)\n          state.lambda = false;\n        return addErr ? style + \" \" + ERRORCLASS : style;\n      },\n\n      indent: function(state, textAfter) {\n        if (state.tokenize != tokenBase)\n          return state.tokenize.isString ? CodeMirror.Pass : 0;\n\n        var scope = top(state), closing = scope.type == textAfter.charAt(0)\n        if (scope.align != null)\n          return scope.align - (closing ? 1 : 0)\n        else\n          return scope.offset - (closing ? hangingIndent : 0)\n      },\n\n      electricInput: /^\\s*[\\}\\]\\)]$/,\n      closeBrackets: {triples: \"'\\\"\"},\n      lineComment: \"#\",\n      fold: \"indent\"\n    };\n    return external;\n  });\n\n  CodeMirror.defineMIME(\"text/x-python\", \"python\");\n\n  var words = function(str) { return str.split(\" \"); };\n\n  CodeMirror.defineMIME(\"text/x-cython\", {\n    name: \"python\",\n    extra_keywords: words(\"by cdef cimport cpdef ctypedef enum except\"+\n                          \"extern gil include nogil property public\"+\n                          \"readonly struct union DEF IF ELIF ELSE\")\n  });\n\n});\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/view/static/plugins/codemirror/mode/shell/shell.js",
    "content": "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n\n(function(mod) {\n  if (typeof exports == \"object\" && typeof module == \"object\") // CommonJS\n    mod(require(\"../../lib/codemirror\"));\n  else if (typeof define == \"function\" && define.amd) // AMD\n    define([\"../../lib/codemirror\"], mod);\n  else // Plain browser env\n    mod(CodeMirror);\n})(function(CodeMirror) {\n\"use strict\";\n\nCodeMirror.defineMode('shell', function() {\n\n  var words = {};\n  function define(style, string) {\n    var split = string.split(' ');\n    for(var i = 0; i < split.length; i++) {\n      words[split[i]] = style;\n    }\n  };\n\n  // Atoms\n  define('atom', 'true false');\n\n  // Keywords\n  define('keyword', 'if then do else elif while until for in esac fi fin ' +\n    'fil done exit set unset export function');\n\n  // Commands\n  define('builtin', 'ab awk bash beep cat cc cd chown chmod chroot clear cp ' +\n    'curl cut diff echo find gawk gcc get git grep kill killall ln ls make ' +\n    'mkdir openssl mv nc node npm ping ps restart rm rmdir sed service sh ' +\n    'shopt shred source sort sleep ssh start stop su sudo tee telnet top ' +\n    'touch vi vim wall wc wget who write yes zsh');\n\n  function tokenBase(stream, state) {\n    if (stream.eatSpace()) return null;\n\n    var sol = stream.sol();\n    var ch = stream.next();\n\n    if (ch === '\\\\') {\n      stream.next();\n      return null;\n    }\n    if (ch === '\\'' || ch === '\"' || ch === '`') {\n      state.tokens.unshift(tokenString(ch, ch === \"`\" ? \"quote\" : \"string\"));\n      return tokenize(stream, state);\n    }\n    if (ch === '#') {\n      if (sol && stream.eat('!')) {\n        stream.skipToEnd();\n        return 'meta'; // 'comment'?\n      }\n      stream.skipToEnd();\n      return 'comment';\n    }\n    if (ch === '$') {\n      state.tokens.unshift(tokenDollar);\n      return tokenize(stream, state);\n    }\n    if (ch === '+' || ch === '=') {\n      return 'operator';\n    }\n    if (ch === '-') {\n      stream.eat('-');\n      stream.eatWhile(/\\w/);\n      return 'attribute';\n    }\n    if (/\\d/.test(ch)) {\n      stream.eatWhile(/\\d/);\n      if(stream.eol() || !/\\w/.test(stream.peek())) {\n        return 'number';\n      }\n    }\n    stream.eatWhile(/[\\w-]/);\n    var cur = stream.current();\n    if (stream.peek() === '=' && /\\w+/.test(cur)) return 'def';\n    return words.hasOwnProperty(cur) ? words[cur] : null;\n  }\n\n  function tokenString(quote, style) {\n    var close = quote == \"(\" ? \")\" : quote == \"{\" ? \"}\" : quote\n    return function(stream, state) {\n      var next, end = false, escaped = false;\n      while ((next = stream.next()) != null) {\n        if (next === close && !escaped) {\n          end = true;\n          break;\n        }\n        if (next === '$' && !escaped && quote !== \"'\") {\n          escaped = true;\n          stream.backUp(1);\n          state.tokens.unshift(tokenDollar);\n          break;\n        }\n        if (!escaped && next === quote && quote !== close) {\n          state.tokens.unshift(tokenString(quote, style))\n          return tokenize(stream, state)\n        }\n        escaped = !escaped && next === '\\\\';\n      }\n      if (end || !escaped) state.tokens.shift();\n      return style;\n    };\n  };\n\n  var tokenDollar = function(stream, state) {\n    if (state.tokens.length > 1) stream.eat('$');\n    var ch = stream.next()\n    if (/['\"({]/.test(ch)) {\n      state.tokens[0] = tokenString(ch, ch == \"(\" ? \"quote\" : ch == \"{\" ? \"def\" : \"string\");\n      return tokenize(stream, state);\n    }\n    if (!/\\d/.test(ch)) stream.eatWhile(/\\w/);\n    state.tokens.shift();\n    return 'def';\n  };\n\n  function tokenize(stream, state) {\n    return (state.tokens[0] || tokenBase) (stream, state);\n  };\n\n  return {\n    startState: function() {return {tokens:[]};},\n    token: function(stream, state) {\n      return tokenize(stream, state);\n    },\n    closeBrackets: \"()[]{}''\\\"\\\"``\",\n    lineComment: '#',\n    fold: \"brace\"\n  };\n});\n\nCodeMirror.defineMIME('text/x-sh', 'shell');\n\n});\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/view/static/plugins/jquery/jquery.cookie.js",
    "content": "/*!\n * jQuery Cookie Plugin v1.4.1\n * https://github.com/carhartl/jquery-cookie\n *\n * Copyright 2013 Klaus Hartl\n * Released under the MIT license\n */\n(function (factory) {\n\tif (typeof define === 'function' && define.amd) {\n\t\t// AMD\n\t\tdefine(['jquery'], factory);\n\t} else if (typeof exports === 'object') {\n\t\t// CommonJS\n\t\tfactory(require('jquery'));\n\t} else {\n\t\t// Browser globals\n\t\tfactory(jQuery);\n\t}\n}(function ($) {\n\n\tvar pluses = /\\+/g;\n\n\tfunction encode(s) {\n\t\treturn config.raw ? s : encodeURIComponent(s);\n\t}\n\n\tfunction decode(s) {\n\t\treturn config.raw ? s : decodeURIComponent(s);\n\t}\n\n\tfunction stringifyCookieValue(value) {\n\t\treturn encode(config.json ? JSON.stringify(value) : String(value));\n\t}\n\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\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\n\tvar config = $.cookie = function (key, value, options) {\n\n\t\t// Write\n\n\t\tif (value !== undefined && !$.isFunction(value)) {\n\t\t\toptions = $.extend({}, config.defaults, options);\n\n\t\t\tif (typeof options.expires === 'number') {\n\t\t\t\tvar days = options.expires, t = options.expires = new Date();\n\t\t\t\tt.setTime(+t + days * 864e+5);\n\t\t\t}\n\n\t\t\treturn (document.cookie = [\n\t\t\t\tencode(key), '=', stringifyCookieValue(value),\n\t\t\t\toptions.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE\n\t\t\t\toptions.path    ? '; path=' + options.path : '',\n\t\t\t\toptions.domain  ? '; domain=' + options.domain : '',\n\t\t\t\toptions.secure  ? '; secure' : ''\n\t\t\t].join(''));\n\t\t}\n\n\t\t// Read\n\n\t\tvar result = key ? undefined : {};\n\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\tvar cookies = document.cookie ? document.cookie.split('; ') : [];\n\n\t\tfor (var i = 0, l = cookies.length; i < l; i++) {\n\t\t\tvar parts = cookies[i].split('=');\n\t\t\tvar name = decode(parts.shift());\n\t\t\tvar cookie = parts.join('=');\n\n\t\t\tif (key && 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\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\n\t\treturn result;\n\t};\n\n\tconfig.defaults = {};\n\n\t$.removeCookie = function (key, options) {\n\t\tif ($.cookie(key) === undefined) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Must not alter options, thus extending a fresh object...\n\t\t$.cookie(key, '', $.extend({}, options, { expires: -1 }));\n\t\treturn !$.cookie(key);\n\t};\n\n}));\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/view/static/plugins/layer/layer.js",
    "content": "﻿/*! layer-v3.0.3 Web弹层组件 MIT License  http://layer.layui.com/  By 贤心 */\n ;!function(e,t){\"use strict\";var i,n,a=e.layui&&layui.define,o={getPath:function(){var e=document.scripts,t=e[e.length-1],i=t.src;if(!t.getAttribute(\"merge\"))return i.substring(0,i.lastIndexOf(\"/\")+1)}(),config:{},end:{},minIndex:0,minLeft:[],btn:[\"&#x786E;&#x5B9A;\",\"&#x53D6;&#x6D88;\"],type:[\"dialog\",\"page\",\"iframe\",\"loading\",\"tips\"]},r={v:\"3.0.3\",ie:function(){var t=navigator.userAgent.toLowerCase();return!!(e.ActiveXObject||\"ActiveXObject\"in e)&&((t.match(/msie\\s(\\d+)/)||[])[1]||\"11\")}(),index:e.layer&&e.layer.v?1e5:0,path:o.getPath,config:function(e,t){return e=e||{},r.cache=o.config=i.extend({},o.config,e),r.path=o.config.path||r.path,\"string\"==typeof e.extend&&(e.extend=[e.extend]),o.config.path&&r.ready(),e.extend?(a?layui.addcss(\"modules/layer/\"+e.extend):r.link(\"skin/\"+e.extend),this):this},link:function(t,n,a){if(r.path){var o=i(\"head\")[0],s=document.createElement(\"link\");\"string\"==typeof n&&(a=n);var l=(a||t).replace(/\\.|\\//g,\"\"),f=\"layuicss-\"+l,c=0;s.rel=\"stylesheet\",s.href=r.path+t,s.id=f,i(\"#\"+f)[0]||o.appendChild(s),\"function\"==typeof n&&!function u(){return++c>80?e.console&&console.error(\"layer.css: Invalid\"):void(1989===parseInt(i(\"#\"+f).css(\"width\"))?n():setTimeout(u,100))}()}},ready:function(e){var t=\"skinlayercss\",i=\"303\";return a?layui.addcss(\"modules/layer/default/layer.css?v=\"+r.v+i,e,t):r.link(\"skin/default/layer.css?v=\"+r.v+i,e,t),this},alert:function(e,t,n){var a=\"function\"==typeof t;return a&&(n=t),r.open(i.extend({content:e,yes:n},a?{}:t))},confirm:function(e,t,n,a){var s=\"function\"==typeof t;return s&&(a=n,n=t),r.open(i.extend({content:e,btn:o.btn,yes:n,btn2:a},s?{}:t))},msg:function(e,n,a){var s=\"function\"==typeof n,f=o.config.skin,c=(f?f+\" \"+f+\"-msg\":\"\")||\"layui-layer-msg\",u=l.anim.length-1;return s&&(a=n),r.open(i.extend({content:e,time:3e3,shade:!1,skin:c,title:!1,closeBtn:!1,btn:!1,resize:!1,end:a},s&&!o.config.skin?{skin:c+\" layui-layer-hui\",anim:u}:function(){return n=n||{},(n.icon===-1||n.icon===t&&!o.config.skin)&&(n.skin=c+\" \"+(n.skin||\"layui-layer-hui\")),n}()))},load:function(e,t){return r.open(i.extend({type:3,icon:e||0,resize:!1,shade:.01},t))},tips:function(e,t,n){return r.open(i.extend({type:4,content:[e,t],closeBtn:!1,time:3e3,shade:!1,resize:!1,fixed:!1,maxWidth:210},n))}},s=function(e){var t=this;t.index=++r.index,t.config=i.extend({},t.config,o.config,e),document.body?t.creat():setTimeout(function(){t.creat()},30)};s.pt=s.prototype;var l=[\"layui-layer\",\".layui-layer-title\",\".layui-layer-main\",\".layui-layer-dialog\",\"layui-layer-iframe\",\"layui-layer-content\",\"layui-layer-btn\",\"layui-layer-close\"];l.anim=[\"layer-anim\",\"layer-anim-01\",\"layer-anim-02\",\"layer-anim-03\",\"layer-anim-04\",\"layer-anim-05\",\"layer-anim-06\"],s.pt.config={type:0,shade:.3,fixed:!0,move:l[1],title:\"&#x4FE1;&#x606F;\",offset:\"auto\",area:\"auto\",closeBtn:1,time:0,zIndex:19891014,maxWidth:360,anim:0,isOutAnim:!0,icon:-1,moveType:1,resize:!0,scrollbar:!0,tips:2},s.pt.vessel=function(e,t){var n=this,a=n.index,r=n.config,s=r.zIndex+a,f=\"object\"==typeof r.title,c=r.maxmin&&(1===r.type||2===r.type),u=r.title?'<div class=\"layui-layer-title\" style=\"'+(f?r.title[1]:\"\")+'\">'+(f?r.title[0]:r.title)+\"</div>\":\"\";return r.zIndex=s,t([r.shade?'<div class=\"layui-layer-shade\" id=\"layui-layer-shade'+a+'\" times=\"'+a+'\" style=\"'+(\"z-index:\"+(s-1)+\"; background-color:\"+(r.shade[1]||\"#000\")+\"; opacity:\"+(r.shade[0]||r.shade)+\"; filter:alpha(opacity=\"+(100*r.shade[0]||100*r.shade)+\");\")+'\"></div>':\"\",'<div class=\"'+l[0]+(\" layui-layer-\"+o.type[r.type])+(0!=r.type&&2!=r.type||r.shade?\"\":\" layui-layer-border\")+\" \"+(r.skin||\"\")+'\" id=\"'+l[0]+a+'\" type=\"'+o.type[r.type]+'\" times=\"'+a+'\" showtime=\"'+r.time+'\" conType=\"'+(e?\"object\":\"string\")+'\" style=\"z-index: '+s+\"; width:\"+r.area[0]+\";height:\"+r.area[1]+(r.fixed?\"\":\";position:absolute;\")+'\">'+(e&&2!=r.type?\"\":u)+'<div id=\"'+(r.id||\"\")+'\" class=\"layui-layer-content'+(0==r.type&&r.icon!==-1?\" layui-layer-padding\":\"\")+(3==r.type?\" layui-layer-loading\"+r.icon:\"\")+'\">'+(0==r.type&&r.icon!==-1?'<i class=\"layui-layer-ico layui-layer-ico'+r.icon+'\"></i>':\"\")+(1==r.type&&e?\"\":r.content||\"\")+'</div><span class=\"layui-layer-setwin\">'+function(){var e=c?'<a class=\"layui-layer-min\" href=\"javascript:;\"><cite></cite></a><a class=\"layui-layer-ico layui-layer-max\" href=\"javascript:;\"></a>':\"\";return r.closeBtn&&(e+='<a class=\"layui-layer-ico '+l[7]+\" \"+l[7]+(r.title?r.closeBtn:4==r.type?\"1\":\"2\")+'\" href=\"javascript:;\"></a>'),e}()+\"</span>\"+(r.btn?function(){var e=\"\";\"string\"==typeof r.btn&&(r.btn=[r.btn]);for(var t=0,i=r.btn.length;t<i;t++)e+='<a class=\"'+l[6]+t+'\">'+r.btn[t]+\"</a>\";return'<div class=\"'+l[6]+\" layui-layer-btn-\"+(r.btnAlign||\"\")+'\">'+e+\"</div>\"}():\"\")+(r.resize?'<span class=\"layui-layer-resize\"></span>':\"\")+\"</div>\"],u,i('<div class=\"layui-layer-move\"></div>')),n},s.pt.creat=function(){var e=this,t=e.config,a=e.index,s=t.content,f=\"object\"==typeof s,c=i(\"body\");if(!t.id||!i(\"#\"+t.id)[0]){switch(\"string\"==typeof t.area&&(t.area=\"auto\"===t.area?[\"\",\"\"]:[t.area,\"\"]),t.shift&&(t.anim=t.shift),6==r.ie&&(t.fixed=!1),t.type){case 0:t.btn=\"btn\"in t?t.btn:o.btn[0],r.closeAll(\"dialog\");break;case 2:var s=t.content=f?t.content:[t.content,\"auto\"];t.content='<iframe scrolling=\"'+(t.content[1]||\"auto\")+'\" allowtransparency=\"true\" id=\"'+l[4]+a+'\" name=\"'+l[4]+a+'\" onload=\"this.className=\\'\\';\" class=\"layui-layer-load\" frameborder=\"0\" src=\"'+t.content[0]+'\"></iframe>';break;case 3:delete t.title,delete t.closeBtn,t.icon===-1&&0===t.icon,r.closeAll(\"loading\");break;case 4:f||(t.content=[t.content,\"body\"]),t.follow=t.content[1],t.content=t.content[0]+'<i class=\"layui-layer-TipsG\"></i>',delete t.title,t.tips=\"object\"==typeof t.tips?t.tips:[t.tips,!0],t.tipsMore||r.closeAll(\"tips\")}e.vessel(f,function(n,r,u){c.append(n[0]),f?function(){2==t.type||4==t.type?function(){i(\"body\").append(n[1])}():function(){s.parents(\".\"+l[0])[0]||(s.data(\"display\",s.css(\"display\")).show().addClass(\"layui-layer-wrap\").wrap(n[1]),i(\"#\"+l[0]+a).find(\".\"+l[5]).before(r))}()}():c.append(n[1]),i(\".layui-layer-move\")[0]||c.append(o.moveElem=u),e.layero=i(\"#\"+l[0]+a),t.scrollbar||l.html.css(\"overflow\",\"hidden\").attr(\"layer-full\",a)}).auto(a),2==t.type&&6==r.ie&&e.layero.find(\"iframe\").attr(\"src\",s[0]),4==t.type?e.tips():e.offset(),t.fixed&&n.on(\"resize\",function(){e.offset(),(/^\\d+%$/.test(t.area[0])||/^\\d+%$/.test(t.area[1]))&&e.auto(a),4==t.type&&e.tips()}),t.time<=0||setTimeout(function(){r.close(e.index)},t.time),e.move().callback(),l.anim[t.anim]&&e.layero.addClass(l.anim[t.anim]),t.isOutAnim&&e.layero.data(\"isOutAnim\",!0)}},s.pt.auto=function(e){function t(e){e=s.find(e),e.height(f[1]-c-u-2*(0|parseFloat(e.css(\"padding-top\"))))}var a=this,o=a.config,s=i(\"#\"+l[0]+e);\"\"===o.area[0]&&o.maxWidth>0&&(r.ie&&r.ie<8&&o.btn&&s.width(s.innerWidth()),s.outerWidth()>o.maxWidth&&s.width(o.maxWidth));var f=[s.innerWidth(),s.innerHeight()],c=s.find(l[1]).outerHeight()||0,u=s.find(\".\"+l[6]).outerHeight()||0;switch(o.type){case 2:t(\"iframe\");break;default:\"\"===o.area[1]?o.fixed&&f[1]>=n.height()&&(f[1]=n.height(),t(\".\"+l[5])):t(\".\"+l[5])}return a},s.pt.offset=function(){var e=this,t=e.config,i=e.layero,a=[i.outerWidth(),i.outerHeight()],o=\"object\"==typeof t.offset;e.offsetTop=(n.height()-a[1])/2,e.offsetLeft=(n.width()-a[0])/2,o?(e.offsetTop=t.offset[0],e.offsetLeft=t.offset[1]||e.offsetLeft):\"auto\"!==t.offset&&(\"t\"===t.offset?e.offsetTop=0:\"r\"===t.offset?e.offsetLeft=n.width()-a[0]:\"b\"===t.offset?e.offsetTop=n.height()-a[1]:\"l\"===t.offset?e.offsetLeft=0:\"lt\"===t.offset?(e.offsetTop=0,e.offsetLeft=0):\"lb\"===t.offset?(e.offsetTop=n.height()-a[1],e.offsetLeft=0):\"rt\"===t.offset?(e.offsetTop=0,e.offsetLeft=n.width()-a[0]):\"rb\"===t.offset?(e.offsetTop=n.height()-a[1],e.offsetLeft=n.width()-a[0]):e.offsetTop=t.offset),t.fixed||(e.offsetTop=/%$/.test(e.offsetTop)?n.height()*parseFloat(e.offsetTop)/100:parseFloat(e.offsetTop),e.offsetLeft=/%$/.test(e.offsetLeft)?n.width()*parseFloat(e.offsetLeft)/100:parseFloat(e.offsetLeft),e.offsetTop+=n.scrollTop(),e.offsetLeft+=n.scrollLeft()),i.attr(\"minLeft\")&&(e.offsetTop=n.height()-(i.find(l[1]).outerHeight()||0),e.offsetLeft=i.css(\"left\")),i.css({top:e.offsetTop,left:e.offsetLeft})},s.pt.tips=function(){var e=this,t=e.config,a=e.layero,o=[a.outerWidth(),a.outerHeight()],r=i(t.follow);r[0]||(r=i(\"body\"));var s={width:r.outerWidth(),height:r.outerHeight(),top:r.offset().top,left:r.offset().left},f=a.find(\".layui-layer-TipsG\"),c=t.tips[0];t.tips[1]||f.remove(),s.autoLeft=function(){s.left+o[0]-n.width()>0?(s.tipLeft=s.left+s.width-o[0],f.css({right:12,left:\"auto\"})):s.tipLeft=s.left},s.where=[function(){s.autoLeft(),s.tipTop=s.top-o[1]-10,f.removeClass(\"layui-layer-TipsB\").addClass(\"layui-layer-TipsT\").css(\"border-right-color\",t.tips[1])},function(){s.tipLeft=s.left+s.width+10,s.tipTop=s.top,f.removeClass(\"layui-layer-TipsL\").addClass(\"layui-layer-TipsR\").css(\"border-bottom-color\",t.tips[1])},function(){s.autoLeft(),s.tipTop=s.top+s.height+10,f.removeClass(\"layui-layer-TipsT\").addClass(\"layui-layer-TipsB\").css(\"border-right-color\",t.tips[1])},function(){s.tipLeft=s.left-o[0]-10,s.tipTop=s.top,f.removeClass(\"layui-layer-TipsR\").addClass(\"layui-layer-TipsL\").css(\"border-bottom-color\",t.tips[1])}],s.where[c-1](),1===c?s.top-(n.scrollTop()+o[1]+16)<0&&s.where[2]():2===c?n.width()-(s.left+s.width+o[0]+16)>0||s.where[3]():3===c?s.top-n.scrollTop()+s.height+o[1]+16-n.height()>0&&s.where[0]():4===c&&o[0]+16-s.left>0&&s.where[1](),a.find(\".\"+l[5]).css({\"background-color\":t.tips[1],\"padding-right\":t.closeBtn?\"30px\":\"\"}),a.css({left:s.tipLeft-(t.fixed?n.scrollLeft():0),top:s.tipTop-(t.fixed?n.scrollTop():0)})},s.pt.move=function(){var e=this,t=e.config,a=i(document),s=e.layero,l=s.find(t.move),f=s.find(\".layui-layer-resize\"),c={};return t.move&&l.css(\"cursor\",\"move\"),l.on(\"mousedown\",function(e){e.preventDefault(),t.move&&(c.moveStart=!0,c.offset=[e.clientX-parseFloat(s.css(\"left\")),e.clientY-parseFloat(s.css(\"top\"))],o.moveElem.css(\"cursor\",\"move\").show())}),f.on(\"mousedown\",function(e){e.preventDefault(),c.resizeStart=!0,c.offset=[e.clientX,e.clientY],c.area=[s.outerWidth(),s.outerHeight()],o.moveElem.css(\"cursor\",\"se-resize\").show()}),a.on(\"mousemove\",function(i){if(c.moveStart){var a=i.clientX-c.offset[0],o=i.clientY-c.offset[1],l=\"fixed\"===s.css(\"position\");if(i.preventDefault(),c.stX=l?0:n.scrollLeft(),c.stY=l?0:n.scrollTop(),!t.moveOut){var f=n.width()-s.outerWidth()+c.stX,u=n.height()-s.outerHeight()+c.stY;a<c.stX&&(a=c.stX),a>f&&(a=f),o<c.stY&&(o=c.stY),o>u&&(o=u)}s.css({left:a,top:o})}if(t.resize&&c.resizeStart){var a=i.clientX-c.offset[0],o=i.clientY-c.offset[1];i.preventDefault(),r.style(e.index,{width:c.area[0]+a,height:c.area[1]+o}),c.isResize=!0,t.resizing&&t.resizing(s)}}).on(\"mouseup\",function(e){c.moveStart&&(delete c.moveStart,o.moveElem.hide(),t.moveEnd&&t.moveEnd(s)),c.resizeStart&&(delete c.resizeStart,o.moveElem.hide())}),e},s.pt.callback=function(){function e(){var e=a.cancel&&a.cancel(t.index,n);e===!1||r.close(t.index)}var t=this,n=t.layero,a=t.config;t.openLayer(),a.success&&(2==a.type?n.find(\"iframe\").on(\"load\",function(){a.success(n,t.index)}):a.success(n,t.index)),6==r.ie&&t.IE6(n),n.find(\".\"+l[6]).children(\"a\").on(\"click\",function(){var e=i(this).index();if(0===e)a.yes?a.yes(t.index,n):a.btn1?a.btn1(t.index,n):r.close(t.index);else{var o=a[\"btn\"+(e+1)]&&a[\"btn\"+(e+1)](t.index,n);o===!1||r.close(t.index)}}),n.find(\".\"+l[7]).on(\"click\",e),a.shadeClose&&i(\"#layui-layer-shade\"+t.index).on(\"click\",function(){r.close(t.index)}),n.find(\".layui-layer-min\").on(\"click\",function(){var e=a.min&&a.min(n);e===!1||r.min(t.index,a)}),n.find(\".layui-layer-max\").on(\"click\",function(){i(this).hasClass(\"layui-layer-maxmin\")?(r.restore(t.index),a.restore&&a.restore(n)):(r.full(t.index,a),setTimeout(function(){a.full&&a.full(n)},100))}),a.end&&(o.end[t.index]=a.end)},o.reselect=function(){i.each(i(\"select\"),function(e,t){var n=i(this);n.parents(\".\"+l[0])[0]||1==n.attr(\"layer\")&&i(\".\"+l[0]).length<1&&n.removeAttr(\"layer\").show(),n=null})},s.pt.IE6=function(e){i(\"select\").each(function(e,t){var n=i(this);n.parents(\".\"+l[0])[0]||\"none\"===n.css(\"display\")||n.attr({layer:\"1\"}).hide(),n=null})},s.pt.openLayer=function(){var e=this;r.zIndex=e.config.zIndex,r.setTop=function(e){var t=function(){r.zIndex++,e.css(\"z-index\",r.zIndex+1)};return r.zIndex=parseInt(e[0].style.zIndex),e.on(\"mousedown\",t),r.zIndex}},o.record=function(e){var t=[e.width(),e.height(),e.position().top,e.position().left+parseFloat(e.css(\"margin-left\"))];e.find(\".layui-layer-max\").addClass(\"layui-layer-maxmin\"),e.attr({area:t})},o.rescollbar=function(e){l.html.attr(\"layer-full\")==e&&(l.html[0].style.removeProperty?l.html[0].style.removeProperty(\"overflow\"):l.html[0].style.removeAttribute(\"overflow\"),l.html.removeAttr(\"layer-full\"))},e.layer=r,r.getChildFrame=function(e,t){return t=t||i(\".\"+l[4]).attr(\"times\"),i(\"#\"+l[0]+t).find(\"iframe\").contents().find(e)},r.getFrameIndex=function(e){return i(\"#\"+e).parents(\".\"+l[4]).attr(\"times\")},r.iframeAuto=function(e){if(e){var t=r.getChildFrame(\"html\",e).outerHeight(),n=i(\"#\"+l[0]+e),a=n.find(l[1]).outerHeight()||0,o=n.find(\".\"+l[6]).outerHeight()||0;n.css({height:t+a+o}),n.find(\"iframe\").css({height:t})}},r.iframeSrc=function(e,t){i(\"#\"+l[0]+e).find(\"iframe\").attr(\"src\",t)},r.style=function(e,t,n){var a=i(\"#\"+l[0]+e),r=a.find(\".layui-layer-content\"),s=a.attr(\"type\"),f=a.find(l[1]).outerHeight()||0,c=a.find(\".\"+l[6]).outerHeight()||0;a.attr(\"minLeft\");s!==o.type[3]&&s!==o.type[4]&&(n||(parseFloat(t.width)<=260&&(t.width=260),parseFloat(t.height)-f-c<=64&&(t.height=64+f+c)),a.css(t),c=a.find(\".\"+l[6]).outerHeight(),s===o.type[2]?a.find(\"iframe\").css({height:parseFloat(t.height)-f-c}):r.css({height:parseFloat(t.height)-f-c-parseFloat(r.css(\"padding-top\"))-parseFloat(r.css(\"padding-bottom\"))}))},r.min=function(e,t){var a=i(\"#\"+l[0]+e),s=a.find(l[1]).outerHeight()||0,f=a.attr(\"minLeft\")||181*o.minIndex+\"px\",c=a.css(\"position\");o.record(a),o.minLeft[0]&&(f=o.minLeft[0],o.minLeft.shift()),a.attr(\"position\",c),r.style(e,{width:180,height:s,left:f,top:n.height()-s,position:\"fixed\",overflow:\"hidden\"},!0),a.find(\".layui-layer-min\").hide(),\"page\"===a.attr(\"type\")&&a.find(l[4]).hide(),o.rescollbar(e),a.attr(\"minLeft\")||o.minIndex++,a.attr(\"minLeft\",f)},r.restore=function(e){var t=i(\"#\"+l[0]+e),n=t.attr(\"area\").split(\",\");t.attr(\"type\");r.style(e,{width:parseFloat(n[0]),height:parseFloat(n[1]),top:parseFloat(n[2]),left:parseFloat(n[3]),position:t.attr(\"position\"),overflow:\"visible\"},!0),t.find(\".layui-layer-max\").removeClass(\"layui-layer-maxmin\"),t.find(\".layui-layer-min\").show(),\"page\"===t.attr(\"type\")&&t.find(l[4]).show(),o.rescollbar(e)},r.full=function(e){var t,a=i(\"#\"+l[0]+e);o.record(a),l.html.attr(\"layer-full\")||l.html.css(\"overflow\",\"hidden\").attr(\"layer-full\",e),clearTimeout(t),t=setTimeout(function(){var t=\"fixed\"===a.css(\"position\");r.style(e,{top:t?0:n.scrollTop(),left:t?0:n.scrollLeft(),width:n.width(),height:n.height()},!0),a.find(\".layui-layer-min\").hide()},100)},r.title=function(e,t){var n=i(\"#\"+l[0]+(t||r.index)).find(l[1]);n.html(e)},r.close=function(e){var t=i(\"#\"+l[0]+e),n=t.attr(\"type\"),a=\"layer-anim-close\";if(t[0]){var s=\"layui-layer-wrap\",f=function(){if(n===o.type[1]&&\"object\"===t.attr(\"conType\")){t.children(\":not(.\"+l[5]+\")\").remove();for(var a=t.find(\".\"+s),r=0;r<2;r++)a.unwrap();a.css(\"display\",a.data(\"display\")).removeClass(s)}else{if(n===o.type[2])try{var f=i(\"#\"+l[4]+e)[0];f.contentWindow.document.write(\"\"),f.contentWindow.close(),t.find(\".\"+l[5])[0].removeChild(f)}catch(c){}t[0].innerHTML=\"\",t.remove()}\"function\"==typeof o.end[e]&&o.end[e](),delete o.end[e]};t.data(\"isOutAnim\")&&t.addClass(a),i(\"#layui-layer-moves, #layui-layer-shade\"+e).remove(),6==r.ie&&o.reselect(),o.rescollbar(e),t.attr(\"minLeft\")&&(o.minIndex--,o.minLeft.push(t.attr(\"minLeft\"))),r.ie&&r.ie<10||!t.data(\"isOutAnim\")?f():setTimeout(function(){f()},200)}},r.closeAll=function(e){i.each(i(\".\"+l[0]),function(){var t=i(this),n=e?t.attr(\"type\")===e:1;n&&r.close(t.attr(\"times\")),n=null})};var f=r.cache||{},c=function(e){return f.skin?\" \"+f.skin+\" \"+f.skin+\"-\"+e:\"\"};r.prompt=function(e,t){var a=\"\";if(e=e||{},\"function\"==typeof e&&(t=e),e.area){var o=e.area;a='style=\"width: '+o[0]+\"; height: \"+o[1]+';\"',delete e.area}var s,l=2==e.formType?'<textarea class=\"layui-layer-input\"'+a+\">\"+(e.value||\"\")+\"</textarea>\":function(){return'<input type=\"'+(1==e.formType?\"password\":\"text\")+'\" class=\"layui-layer-input\" value=\"'+(e.value||\"\")+'\">'}(),f=e.success;return delete e.success,r.open(i.extend({type:1,btn:[\"&#x786E;&#x5B9A;\",\"&#x53D6;&#x6D88;\"],content:l,skin:\"layui-layer-prompt\"+c(\"prompt\"),maxWidth:n.width(),success:function(e){s=e.find(\".layui-layer-input\"),s.focus(),\"function\"==typeof f&&f(e)},resize:!1,yes:function(i){var n=s.val();\"\"===n?s.focus():n.length>(e.maxlength||500)?r.tips(\"&#x6700;&#x591A;&#x8F93;&#x5165;\"+(e.maxlength||500)+\"&#x4E2A;&#x5B57;&#x6570;\",s,{tips:1}):t&&t(n,i,s)}},e))},r.tab=function(e){e=e||{};var t=e.tab||{},n=e.success;return delete e.success,r.open(i.extend({type:1,skin:\"layui-layer-tab\"+c(\"tab\"),resize:!1,title:function(){var e=t.length,i=1,n=\"\";if(e>0)for(n='<span class=\"layui-layer-tabnow\">'+t[0].title+\"</span>\";i<e;i++)n+=\"<span>\"+t[i].title+\"</span>\";return n}(),content:'<ul class=\"layui-layer-tabmain\">'+function(){var e=t.length,i=1,n=\"\";if(e>0)for(n='<li class=\"layui-layer-tabli xubox_tab_layer\">'+(t[0].content||\"no content\")+\"</li>\";i<e;i++)n+='<li class=\"layui-layer-tabli\">'+(t[i].content||\"no  content\")+\"</li>\";return n}()+\"</ul>\",success:function(t){var a=t.find(\".layui-layer-title\").children(),o=t.find(\".layui-layer-tabmain\").children();a.on(\"mousedown\",function(t){t.stopPropagation?t.stopPropagation():t.cancelBubble=!0;var n=i(this),a=n.index();n.addClass(\"layui-layer-tabnow\").siblings().removeClass(\"layui-layer-tabnow\"),o.eq(a).show().siblings().hide(),\"function\"==typeof e.change&&e.change(a)}),\"function\"==typeof n&&n(t)}},e))},r.photos=function(t,n,a){function o(e,t,i){var n=new Image;return n.src=e,n.complete?t(n):(n.onload=function(){n.onload=null,t(n)},void(n.onerror=function(e){n.onerror=null,i(e)}))}var s={};if(t=t||{},t.photos){var l=t.photos.constructor===Object,f=l?t.photos:{},u=f.data||[],d=f.start||0;s.imgIndex=(0|d)+1,t.img=t.img||\"img\";var y=t.success;if(delete t.success,l){if(0===u.length)return r.msg(\"&#x6CA1;&#x6709;&#x56FE;&#x7247;\")}else{var p=i(t.photos),h=function(){u=[],p.find(t.img).each(function(e){var t=i(this);t.attr(\"layer-index\",e),u.push({alt:t.attr(\"alt\"),pid:t.attr(\"layer-pid\"),src:t.attr(\"layer-src\")||t.attr(\"src\"),thumb:t.attr(\"src\")})})};if(h(),0===u.length)return;if(n||p.on(\"click\",t.img,function(){var e=i(this),n=e.attr(\"layer-index\");r.photos(i.extend(t,{photos:{start:n,data:u,tab:t.tab},full:t.full}),!0),h()}),!n)return}s.imgprev=function(e){s.imgIndex--,s.imgIndex<1&&(s.imgIndex=u.length),s.tabimg(e)},s.imgnext=function(e,t){s.imgIndex++,s.imgIndex>u.length&&(s.imgIndex=1,t)||s.tabimg(e)},s.keyup=function(e){if(!s.end){var t=e.keyCode;e.preventDefault(),37===t?s.imgprev(!0):39===t?s.imgnext(!0):27===t&&r.close(s.index)}},s.tabimg=function(e){if(!(u.length<=1))return f.start=s.imgIndex-1,r.close(s.index),r.photos(t,!0,e)},s.event=function(){s.bigimg.hover(function(){s.imgsee.show()},function(){s.imgsee.hide()}),s.bigimg.find(\".layui-layer-imgprev\").on(\"click\",function(e){e.preventDefault(),s.imgprev()}),s.bigimg.find(\".layui-layer-imgnext\").on(\"click\",function(e){e.preventDefault(),s.imgnext()}),i(document).on(\"keyup\",s.keyup)},s.loadi=r.load(1,{shade:!(\"shade\"in t)&&.9,scrollbar:!1}),o(u[d].src,function(n){r.close(s.loadi),s.index=r.open(i.extend({type:1,id:\"layui-layer-photos\",area:function(){var a=[n.width,n.height],o=[i(e).width()-100,i(e).height()-100];if(!t.full&&(a[0]>o[0]||a[1]>o[1])){var r=[a[0]/o[0],a[1]/o[1]];r[0]>r[1]?(a[0]=a[0]/r[0],a[1]=a[1]/r[0]):r[0]<r[1]&&(a[0]=a[0]/r[1],a[1]=a[1]/r[1])}return[a[0]+\"px\",a[1]+\"px\"]}(),title:!1,shade:.9,shadeClose:!0,closeBtn:!1,move:\".layui-layer-phimg img\",moveType:1,scrollbar:!1,moveOut:!0,isOutAnim:!1,skin:\"layui-layer-photos\"+c(\"photos\"),content:'<div class=\"layui-layer-phimg\"><img src=\"'+u[d].src+'\" alt=\"'+(u[d].alt||\"\")+'\" layer-pid=\"'+u[d].pid+'\"><div class=\"layui-layer-imgsee\">'+(u.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:'+(a?\"block\":\"\")+'\"><span class=\"layui-layer-imgtit\"><a href=\"javascript:;\">'+(u[d].alt||\"\")+\"</a><em>\"+s.imgIndex+\"/\"+u.length+\"</em></span></div></div></div>\",success:function(e,i){s.bigimg=e.find(\".layui-layer-phimg\"),s.imgsee=e.find(\".layui-layer-imguide,.layui-layer-imgbar\"),s.event(e),t.tab&&t.tab(u[d],e),\"function\"==typeof y&&y(e)},end:function(){s.end=!0,i(document).off(\"keyup\",s.keyup)}},t))},function(){r.close(s.loadi),r.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(){u.length>1&&s.imgnext(!0,!0)}})})}},o.run=function(t){i=t,n=i(e),l.html=i(\"html\"),r.open=function(e){var t=new s(e);return t.index}},e.layui&&layui.define?(r.ready(),layui.define(\"jquery\",function(t){r.path=layui.cache.dir,o.run(layui.jquery),e.layer=r,t(\"layer\",r)})):\"function\"==typeof define&&define.amd?define([\"jquery\"],function(){return o.run(e.jQuery),r}):function(){o.run(e.jQuery),r.ready()}()}(window);"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/view/static/plugins/layer/mobile/layer.js",
    "content": "/*! layer mobile-v2.0.0 Web弹层组件 MIT License  http://layer.layui.com/mobile  By 贤心 */\n ;!function(e){\"use strict\";var t=document,n=\"querySelectorAll\",i=\"getElementsByClassName\",a=function(e){return t[n](e)},s={type:0,shade:!0,shadeClose:!0,fixed:!0,anim:\"scale\"},l={extend:function(e){var t=JSON.parse(JSON.stringify(s));for(var n in e)t[n]=e[n];return t},timer:{},end:{}};l.touch=function(e,t){e.addEventListener(\"click\",function(e){t.call(this,e)},!1)};var r=0,o=[\"layui-m-layer\"],c=function(e){var t=this;t.config=l.extend(e),t.view()};c.prototype.view=function(){var e=this,n=e.config,s=t.createElement(\"div\");e.id=s.id=o[0]+r,s.setAttribute(\"class\",o[0]+\" \"+o[0]+(n.type||0)),s.setAttribute(\"index\",r);var l=function(){var e=\"object\"==typeof n.title;return n.title?'<h3 style=\"'+(e?n.title[1]:\"\")+'\">'+(e?n.title[0]:n.title)+\"</h3>\":\"\"}(),c=function(){\"string\"==typeof n.btn&&(n.btn=[n.btn]);var e,t=(n.btn||[]).length;return 0!==t&&n.btn?(e='<span yes type=\"1\">'+n.btn[0]+\"</span>\",2===t&&(e='<span no type=\"0\">'+n.btn[1]+\"</span>\"+e),'<div class=\"layui-m-layerbtn\">'+e+\"</div>\"):\"\"}();if(n.fixed||(n.top=n.hasOwnProperty(\"top\")?n.top:100,n.style=n.style||\"\",n.style+=\" top:\"+(t.body.scrollTop+n.top)+\"px\"),2===n.type&&(n.content='<i></i><i class=\"layui-m-layerload\"></i><i></i><p>'+(n.content||\"\")+\"</p>\"),n.skin&&(n.anim=\"up\"),\"msg\"===n.skin&&(n.shade=!1),s.innerHTML=(n.shade?\"<div \"+(\"string\"==typeof n.shade?'style=\"'+n.shade+'\"':\"\")+' class=\"layui-m-layershade\"></div>':\"\")+'<div class=\"layui-m-layermain\" '+(n.fixed?\"\":'style=\"position:static;\"')+'><div class=\"layui-m-layersection\"><div class=\"layui-m-layerchild '+(n.skin?\"layui-m-layer-\"+n.skin+\" \":\"\")+(n.className?n.className:\"\")+\" \"+(n.anim?\"layui-m-anim-\"+n.anim:\"\")+'\" '+(n.style?'style=\"'+n.style+'\"':\"\")+\">\"+l+'<div class=\"layui-m-layercont\">'+n.content+\"</div>\"+c+\"</div></div></div>\",!n.type||2===n.type){var d=t[i](o[0]+n.type),y=d.length;y>=1&&layer.close(d[0].getAttribute(\"index\"))}document.body.appendChild(s);var u=e.elem=a(\"#\"+e.id)[0];n.success&&n.success(u),e.index=r++,e.action(n,u)},c.prototype.action=function(e,t){var n=this;e.time&&(l.timer[n.index]=setTimeout(function(){layer.close(n.index)},1e3*e.time));var a=function(){var t=this.getAttribute(\"type\");0==t?(e.no&&e.no(),layer.close(n.index)):e.yes?e.yes(n.index):layer.close(n.index)};if(e.btn)for(var s=t[i](\"layui-m-layerbtn\")[0].children,r=s.length,o=0;o<r;o++)l.touch(s[o],a);if(e.shade&&e.shadeClose){var c=t[i](\"layui-m-layershade\")[0];l.touch(c,function(){layer.close(n.index,e.end)})}e.end&&(l.end[n.index]=e.end)},e.layer={v:\"2.0\",index:r,open:function(e){var t=new c(e||{});return t.index},close:function(e){var n=a(\"#\"+o[0]+e)[0];n&&(n.innerHTML=\"\",t.body.removeChild(n),clearTimeout(l.timer[e]),delete l.timer[e],\"function\"==typeof l.end[e]&&l.end[e](),delete l.end[e])},closeAll:function(){for(var e=t[i](o[0]),n=0,a=e.length;n<a;n++)layer.close(0|e[0].getAttribute(\"index\"))}},\"function\"==typeof define?define(function(){return layer}):function(){var e=document.scripts,n=e[e.length-1],i=n.src,a=i.substring(0,i.lastIndexOf(\"/\")+1);n.getAttribute(\"merge\")||document.head.appendChild(function(){var e=t.createElement(\"link\");return e.href=a+\"need/layer.css?2.0\",e.type=\"text/css\",e.rel=\"styleSheet\",e.id=\"layermcss\",e}())}()}(window);"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/view/static/plugins/layer/mobile/need/layer.css",
    "content": ".layui-m-layer{position:relative;z-index:19891014}.layui-m-layer *{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.layui-m-layermain,.layui-m-layershade{position:fixed;left:0;top:0;width:100%;height:100%}.layui-m-layershade{background-color:rgba(0,0,0,.7);pointer-events:auto}.layui-m-layermain{display:table;font-family:Helvetica,arial,sans-serif;pointer-events:none}.layui-m-layermain .layui-m-layersection{display:table-cell;vertical-align:middle;text-align:center}.layui-m-layerchild{position:relative;display:inline-block;text-align:left;background-color:#fff;font-size:14px;border-radius:5px;box-shadow:0 0 8px rgba(0,0,0,.1);pointer-events:auto;-webkit-overflow-scrolling:touch;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:.2s;animation-duration:.2s}@-webkit-keyframes layui-m-anim-scale{0%{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}@keyframes layui-m-anim-scale{0%{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}.layui-m-anim-scale{animation-name:layui-m-anim-scale;-webkit-animation-name:layui-m-anim-scale}@-webkit-keyframes layui-m-anim-up{0%{opacity:0;-webkit-transform:translateY(800px);transform:translateY(800px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes layui-m-anim-up{0%{opacity:0;-webkit-transform:translateY(800px);transform:translateY(800px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}.layui-m-anim-up{-webkit-animation-name:layui-m-anim-up;animation-name:layui-m-anim-up}.layui-m-layer0 .layui-m-layerchild{width:90%;max-width:640px}.layui-m-layer1 .layui-m-layerchild{border:none;border-radius:0}.layui-m-layer2 .layui-m-layerchild{width:auto;max-width:260px;min-width:40px;border:none;background:0 0;box-shadow:none;color:#fff}.layui-m-layerchild h3{padding:0 10px;height:60px;line-height:60px;font-size:16px;font-weight:400;border-radius:5px 5px 0 0;text-align:center}.layui-m-layerbtn span,.layui-m-layerchild h3{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-m-layercont{padding:50px 30px;line-height:22px;text-align:center}.layui-m-layer1 .layui-m-layercont{padding:0;text-align:left}.layui-m-layer2 .layui-m-layercont{text-align:center;padding:0;line-height:0}.layui-m-layer2 .layui-m-layercont i{width:25px;height:25px;margin-left:8px;display:inline-block;background-color:#fff;border-radius:100%;-webkit-animation:layui-m-anim-loading 1.4s infinite ease-in-out;animation:layui-m-anim-loading 1.4s infinite ease-in-out;-webkit-animation-fill-mode:both;animation-fill-mode:both}.layui-m-layerbtn,.layui-m-layerbtn span{position:relative;text-align:center;border-radius:0 0 5px 5px}.layui-m-layer2 .layui-m-layercont p{margin-top:20px}@-webkit-keyframes layui-m-anim-loading{0%,100%,80%{transform:scale(0);-webkit-transform:scale(0)}40%{transform:scale(1);-webkit-transform:scale(1)}}@keyframes layui-m-anim-loading{0%,100%,80%{transform:scale(0);-webkit-transform:scale(0)}40%{transform:scale(1);-webkit-transform:scale(1)}}.layui-m-layer2 .layui-m-layercont i:first-child{margin-left:0;-webkit-animation-delay:-.32s;animation-delay:-.32s}.layui-m-layer2 .layui-m-layercont i.layui-m-layerload{-webkit-animation-delay:-.16s;animation-delay:-.16s}.layui-m-layer2 .layui-m-layercont>div{line-height:22px;padding-top:7px;margin-bottom:20px;font-size:14px}.layui-m-layerbtn{display:box;display:-moz-box;display:-webkit-box;width:100%;height:50px;line-height:50px;font-size:0;border-top:1px solid #D0D0D0;background-color:#F2F2F2}.layui-m-layerbtn span{display:block;-moz-box-flex:1;box-flex:1;-webkit-box-flex:1;font-size:14px;cursor:pointer}.layui-m-layerbtn span[yes]{color:#40AFFE}.layui-m-layerbtn span[no]{border-right:1px solid #D0D0D0;border-radius:0 0 0 5px}.layui-m-layerbtn span:active{background-color:#F6F6F6}.layui-m-layerend{position:absolute;right:7px;top:10px;width:30px;height:30px;border:0;font-weight:400;background:0 0;cursor:pointer;-webkit-appearance:none;font-size:30px}.layui-m-layerend::after,.layui-m-layerend::before{position:absolute;left:5px;top:15px;content:'';width:18px;height:1px;background-color:#999;transform:rotate(45deg);-webkit-transform:rotate(45deg);border-radius:3px}.layui-m-layerend::after{transform:rotate(-45deg);-webkit-transform:rotate(-45deg)}body .layui-m-layer .layui-m-layer-footer{position:fixed;width:95%;max-width:100%;margin:0 auto;left:0;right:0;bottom:10px;background:0 0}.layui-m-layer-footer .layui-m-layercont{padding:20px;border-radius:5px 5px 0 0;background-color:rgba(255,255,255,.8)}.layui-m-layer-footer .layui-m-layerbtn{display:block;height:auto;background:0 0;border-top:none}.layui-m-layer-footer .layui-m-layerbtn span{background-color:rgba(255,255,255,.8)}.layui-m-layer-footer .layui-m-layerbtn span[no]{color:#FD482C;border-top:1px solid #c2c2c2;border-radius:0 0 5px 5px}.layui-m-layer-footer .layui-m-layerbtn span[yes]{margin-top:10px;border-radius:5px}body .layui-m-layer .layui-m-layer-msg{width:auto;max-width:90%;margin:0 auto;bottom:-150px;background-color:rgba(0,0,0,.7);color:#fff}.layui-m-layer-msg .layui-m-layercont{padding:10px 20px}"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/view/static/plugins/layer/skin/default/layer.css",
    "content": ".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 #layuicss-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)}.layui-layer-close{position:absolute}.layui-layer-content{position:relative}.layui-layer-border{border:1px solid #B2B2B2;border:1px solid rgba(0,0,0,.1);box-shadow:1px 1px 5px rgba(0,0,0,.2)}.layui-layer-load{background:url(loading-1.gif) center center no-repeat #eee}.layui-layer-ico{background:url(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}.layui-layer-move{display:none;position:fixed;*position:absolute;left:0;top:0;width:100%;height:100%;cursor:move;opacity:0;filter:alpha(opacity=0);background-color:#fff;z-index:2147483647}.layui-layer-resize{position:absolute;width:15px;height:15px;right:0;bottom:0;cursor:se-resize}.layui-layer{border-radius:2px;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:.3s;animation-duration:.3s}@-webkit-keyframes layer-bounceIn{0%{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}@keyframes layer-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:layer-bounceIn;animation-name:layer-bounceIn}@-webkit-keyframes layer-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 layer-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:layer-zoomInDown;animation-name:layer-zoomInDown}@-webkit-keyframes layer-fadeInUpBig{0%{opacity:0;-webkit-transform:translateY(2000px);transform:translateY(2000px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes layer-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:layer-fadeInUpBig;animation-name:layer-fadeInUpBig}@-webkit-keyframes layer-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 layer-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:layer-zoomInLeft;animation-name:layer-zoomInLeft}@-webkit-keyframes layer-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 layer-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:layer-rollIn;animation-name:layer-rollIn}@keyframes layer-fadeIn{0%{opacity:0}100%{opacity:1}}.layer-anim-05{-webkit-animation-name:layer-fadeIn;animation-name:layer-fadeIn}@-webkit-keyframes layer-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 layer-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:layer-shake;animation-name:layer-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:1px -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;user-select:none;-webkit-user-select:none}.layui-layer-btn a{height:28px;line-height:28px;margin:6px 6px 0;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:.8}.layui-layer-btn .layui-layer-btn0{border-color:#4898d5;background-color:#2e8ded;color:#fff}.layui-layer-btn-l{text-align:left}.layui-layer-btn-c{text-align:center}.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 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(loading-0.gif) no-repeat}.layui-layer-loading .layui-layer-loading1{width:37px;height:37px;background:url(loading-1.gif) no-repeat}.layui-layer-ico16,.layui-layer-loading .layui-layer-loading2{width:32px;height:32px;background:url(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:2px;box-shadow:1px 1px 3px rgba(0,0,0,.2);background-color:#000;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:#000}.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:#000}.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:5px 10px 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(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-prompt .layui-layer-content{padding:20px}.layui-layer-prompt .layui-layer-btn{padding-top:0}.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:.8s;animation-duration:.8s}.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}@-webkit-keyframes layer-bounceOut{100%{opacity:0;-webkit-transform:scale(.7);transform:scale(.7)}30%{-webkit-transform:scale(1.05);transform:scale(1.05)}0%{-webkit-transform:scale(1);transform:scale(1)}}@keyframes layer-bounceOut{100%{opacity:0;-webkit-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}30%{-webkit-transform:scale(1.05);-ms-transform:scale(1.05);transform:scale(1.05)}0%{-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}.layer-anim-close{-webkit-animation-name:layer-bounceOut;animation-name:layer-bounceOut;-webkit-animation-duration:.2s;animation-duration:.2s}@media screen and (max-width:1100px){.layui-layer-iframe{overflow-y:auto;-webkit-overflow-scrolling:touch}}"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/view/static/plugins/pace/themes/pace-theme-bounce.css",
    "content": "/* This is a compiled file, you should be editing the file in the templates directory */\n.pace {\n  width: 140px;\n  height: 300px;\n  position: fixed;\n  top: -90px;\n  right: -20px;\n  z-index: 2000;\n  -webkit-transform: scale(0);\n  -moz-transform: scale(0);\n  -ms-transform: scale(0);\n  -o-transform: scale(0);\n  transform: scale(0);\n  opacity: 0;\n  -webkit-transition: all 2s linear 0s;\n  -moz-transition: all 2s linear 0s;\n  transition: all 2s linear 0s;\n}\n\n.pace.pace-active {\n  -webkit-transform: scale(.25);\n  -moz-transform: scale(.25);\n  -ms-transform: scale(.25);\n  -o-transform: scale(.25);\n  transform: scale(.25);\n  opacity: 1;\n}\n\n.pace .pace-activity {\n  width: 140px;\n  height: 140px;\n  border-radius: 70px;\n  background: #29d;\n  position: absolute;\n  top: 0;\n  z-index: 1911;\n  -webkit-animation: pace-bounce 1s infinite;\n  -moz-animation: pace-bounce 1s infinite;\n  -o-animation: pace-bounce 1s infinite;\n  -ms-animation: pace-bounce 1s infinite;\n  animation: pace-bounce 1s infinite;\n}\n\n.pace .pace-progress {\n  position: absolute;\n  display: block;\n  left: 50%;\n  bottom: 0;\n  z-index: 1910;\n  margin-left: -30px;\n  width: 60px;\n  height: 75px;\n  background: rgba(20, 20, 20, .1);\n  box-shadow: 0 0 20px 35px rgba(20, 20, 20, .1);\n  border-radius: 30px / 40px;\n  -webkit-transform: scaleY(.3);\n  -moz-transform: scaleY(.3);\n  -ms-transform: scaleY(.3);\n  -o-transform: scaleY(.3);\n  transform: scaleY(.3);\n  -webkit-animation: pace-compress .5s infinite alternate;\n  -moz-animation: pace-compress .5s infinite alternate;\n  -o-animation: pace-compress .5s infinite alternate;\n  -ms-animation: pace-compress .5s infinite alternate;\n  animation: pace-compress .5s infinite alternate;\n}\n\n@-webkit-keyframes pace-bounce {\n  0% {\n    top: 0;\n    -webkit-animation-timing-function: ease-in;\n  }\n  40% {}\n  50% {\n    top: 140px;\n    height: 140px;\n    -webkit-animation-timing-function: ease-out;\n  }\n  55% {\n    top: 160px;\n    height: 120px;\n    border-radius: 70px / 60px;\n    -webkit-animation-timing-function: ease-in;\n  }\n  65% {\n    top: 120px;\n    height: 140px;\n    border-radius: 70px;\n    -webkit-animation-timing-function: ease-out;\n  }\n  95% {\n    top: 0;\n    -webkit-animation-timing-function: ease-in;\n  }\n  100% {\n    top: 0;\n    -webkit-animation-timing-function: ease-in;\n  }\n}\n\n@-moz-keyframes pace-bounce {\n  0% {\n    top: 0;\n    -moz-animation-timing-function: ease-in;\n  }\n  40% {}\n  50% {\n    top: 140px;\n    height: 140px;\n    -moz-animation-timing-function: ease-out;\n  }\n  55% {\n    top: 160px;\n    height: 120px;\n    border-radius: 70px / 60px;\n    -moz-animation-timing-function: ease-in;\n  }\n  65% {\n    top: 120px;\n    height: 140px;\n    border-radius: 70px;\n    -moz-animation-timing-function: ease-out;}\n  95% {\n    top: 0;\n    -moz-animation-timing-function: ease-in;\n  }\n  100% {top: 0;\n    -moz-animation-timing-function: ease-in;\n  }\n}\n\n@keyframes pace-bounce {\n  0% {\n    top: 0;\n    animation-timing-function: ease-in;\n  }\n  50% {\n    top: 140px;\n    height: 140px;\n    animation-timing-function: ease-out;\n  }\n  55% {\n    top: 160px;\n    height: 120px;\n    border-radius: 70px / 60px;\n    animation-timing-function: ease-in;\n  }\n  65% {\n    top: 120px;\n    height: 140px;\n    border-radius: 70px;\n    animation-timing-function: ease-out;\n  }\n  95% {\n    top: 0;\n    animation-timing-function: ease-in;\n  }\n  100% {\n    top: 0;\n    animation-timing-function: ease-in;\n  }\n}\n\n@-webkit-keyframes pace-compress {\n  0% {\n    bottom: 0;\n    margin-left: -30px;\n    width: 60px;\n    height: 75px;\n    background: rgba(20, 20, 20, .1);\n    box-shadow: 0 0 20px 35px rgba(20, 20, 20, .1);\n    border-radius: 30px / 40px;\n    -webkit-animation-timing-function: ease-in;\n  }\n  100% {\n    bottom: 30px;\n    margin-left: -10px;\n    width: 20px;\n    height: 5px;\n    background: rgba(20, 20, 20, .3);\n    box-shadow: 0 0 20px 35px rgba(20, 20, 20, .3);\n    border-radius: 20px / 20px;\n    -webkit-animation-timing-function: ease-out;\n  }\n}\n\n@-moz-keyframes pace-compress {\n  0% {\n    bottom: 0;\n    margin-left: -30px;\n    width: 60px;\n    height: 75px;\n    background: rgba(20, 20, 20, .1);\n    box-shadow: 0 0 20px 35px rgba(20, 20, 20, .1);\n    border-radius: 30px / 40px;\n    -moz-animation-timing-function: ease-in;\n  }\n  100% {\n    bottom: 30px;\n    margin-left: -10px;\n    width: 20px;\n    height: 5px;\n    background: rgba(20, 20, 20, .3);\n    box-shadow: 0 0 20px 35px rgba(20, 20, 20, .3);\n    border-radius: 20px / 20px;\n    -moz-animation-timing-function: ease-out;\n  }\n}\n\n@keyframes pace-compress {\n  0% {\n    bottom: 0;\n    margin-left: -30px;\n    width: 60px;\n    height: 75px;\n    background: rgba(20, 20, 20, .1);\n    box-shadow: 0 0 20px 35px rgba(20, 20, 20, .1);\n    border-radius: 30px / 40px;\n    animation-timing-function: ease-in;\n  }\n  100% {\n    bottom: 30px;\n    margin-left: -10px;\n    width: 20px;\n    height: 5px;\n    background: rgba(20, 20, 20, .3);\n    box-shadow: 0 0 20px 35px rgba(20, 20, 20, .3);\n    border-radius: 20px / 20px;\n    animation-timing-function: ease-out;\n  }\n}"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/view/static/plugins/pace/themes/pace-theme-flash.css",
    "content": "/* This is a compiled file, you should be editing the file in the templates directory */\n.pace {\n  -webkit-pointer-events: none;\n  pointer-events: none;\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  user-select: none;\n}\n\n.pace-inactive {\n  display: none;\n}\n\n.pace .pace-progress {\n  background: #29d;\n  position: fixed;\n  z-index: 2000;\n  top: 0;\n  left: 0;\n  height: 2px;\n\n  -webkit-transition: width 1s;\n  -moz-transition: width 1s;\n  -o-transition: width 1s;\n  transition: width 1s;\n}\n\n.pace .pace-progress-inner {\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  -webkit-transform: rotate(3deg) translate(0px, -4px);\n  -moz-transform: rotate(3deg) translate(0px, -4px);\n  -ms-transform: rotate(3deg) translate(0px, -4px);\n  -o-transform: rotate(3deg) translate(0px, -4px);\n  transform: rotate(3deg) translate(0px, -4px);\n}\n\n.pace .pace-activity {\n  display: block;\n  position: fixed;\n  z-index: 2000;\n  top: 15px;\n  right: 15px;\n  width: 14px;\n  height: 14px;\n  border: solid 2px transparent;\n  border-top-color: #29d;\n  border-left-color: #29d;\n  border-radius: 10px;\n  -webkit-animation: pace-spinner 400ms linear infinite;\n  -moz-animation: pace-spinner 400ms linear infinite;\n  -ms-animation: pace-spinner 400ms linear infinite;\n  -o-animation: pace-spinner 400ms linear infinite;\n  animation: pace-spinner 400ms linear infinite;\n}\n\n@-webkit-keyframes pace-spinner {\n  0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); }\n  100% { -webkit-transform: rotate(360deg); transform: rotate(360deg); }\n}\n@-moz-keyframes pace-spinner {\n  0% { -moz-transform: rotate(0deg); transform: rotate(0deg); }\n  100% { -moz-transform: rotate(360deg); transform: rotate(360deg); }\n}\n@-o-keyframes pace-spinner {\n  0% { -o-transform: rotate(0deg); transform: rotate(0deg); }\n  100% { -o-transform: rotate(360deg); transform: rotate(360deg); }\n}\n@-ms-keyframes pace-spinner {\n  0% { -ms-transform: rotate(0deg); transform: rotate(0deg); }\n  100% { -ms-transform: rotate(360deg); transform: rotate(360deg); }\n}\n@keyframes pace-spinner {\n  0% { transform: rotate(0deg); transform: rotate(0deg); }\n  100% { transform: rotate(360deg); transform: rotate(360deg); }\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/view/templates/common/common.exception.ftl",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<meta charset=\"UTF-8\">\n\t<title>应用程序异常 (error)</title> \n    <style type=\"text/css\"> \n        body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }\n        div.dialog {\n            width: 80%;\n            padding: 1em 4em;\n            margin: 4em auto 0 auto;\n            border: 1px solid #ccc;\n            border-right-color: #999;\n            border-bottom-color: #999;\n        }\n        h1 { font-size: 100%; color: #f00; line-height: 1.5em; }\n    </style>\n    \n</head> \n</head>\n<body> \n\n\t<div class=\"dialog\"> \n\t    <h1>应用程序异常</h1> \n\t    <p>${exceptionMsg}</p>\n\t\t<a href=\"javascript:window.location.href='${request.contextPath}/'\">返 回</a>\n\t    </p> \n\t</div>\n\n</body>\n</html>"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/view/templates/common/common.macro.ftl",
    "content": "<#macro commonStyle>\n\n\t<#-- favicon -->\n\t<link rel=\"icon\" href=\"favicon.ico\" />\n\n\t<meta charset=\"utf-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n    <!-- Tell the browser to be responsive to screen width -->\n    <meta content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no\" name=\"viewport\">\n    <!-- Bootstrap 3.3.5 -->\n    <link rel=\"stylesheet\" href=\"/adminlte/bootstrap/css/bootstrap.min.css\">\n    <!-- Font Awesome -->\n    <!-- <link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/css/font-awesome.min.css\"> -->\n    <link rel=\"stylesheet\" href=\"/plugins/font-awesome-4.5.0/css/font-awesome.min.css\">\n    <!-- Ionicons -->\n    <!-- <link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/ionicons/2.0.1/css/ionicons.min.css\"> -->\n    <link rel=\"stylesheet\" href=\"/plugins/ionicons-2.0.1/css/ionicons.min.css\">\n    <!-- Theme style -->\n    <link rel=\"stylesheet\" href=\"/adminlte/dist/css/AdminLTE-local.min.css\">\n    <!-- AdminLTE Skins. Choose a skin from the css/skins folder instead of downloading all of them to reduce the load. -->\n    <link rel=\"stylesheet\" href=\"/adminlte/dist/css/skins/_all-skins.min.css\">\n      \n\t<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->\n    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->\n    <!--[if lt IE 9]>\n    <script src=\"https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js\"></script>\n    <script src=\"https://oss.maxcdn.com/respond/1.4.2/respond.min.js\"></script>\n    <![endif]-->\n\n\t<!-- pace -->\n\t<link rel=\"stylesheet\" href=\"/plugins/pace/themes/pace-theme-flash.css\">\n</#macro>\n\n<#macro commonScript>\n\t<!-- jQuery 2.1.4 -->\n\t<script src=\"/adminlte/plugins/jQuery/jquery-2.2.3.min.js\"></script>\n\t<!-- Bootstrap 3.3.5 -->\n\t<script src=\"/adminlte/bootstrap/js/bootstrap.min.js\"></script>\n\t<!-- FastClick -->\n\t<script src=\"/adminlte/plugins/fastclick/fastclick.min.js\"></script>\n\t<!-- AdminLTE App -->\n\t<script src=\"/adminlte/dist/js/app.min.js\"></script>\n\t<#-- jquery.slimscroll -->\n\t<script src=\"/adminlte/plugins/slimScroll/jquery.slimscroll.min.js\"></script>\n\n    <!-- pace -->\n    <script src=\"/plugins/pace/pace.min.js\"></script>\n    <#-- jquery cookie -->\n\t<script src=\"/plugins/jquery/jquery.cookie.js\"></script>\n\n\t<#-- layer -->\n\t<script src=\"/plugins/layer/layer.js\"></script>\n\n\t<#-- common -->\n    <script src=\"/js/common.1.js\"></script>\n    <script>var base_url = '';</script>\n\n</#macro>\n\n<#macro commonHeader>\n\t<header class=\"main-header\">\n\t\t<a href=\"/\" class=\"logo\">\n\t\t\t<span class=\"logo-mini\"><b>JOB</b></span>\n\t\t\t<span class=\"logo-lg\"><b>中科软任务调度中心</b></span>\n\t\t</a>\n\t\t<nav class=\"navbar navbar-static-top\" role=\"navigation\">\n\t\t\t<a href=\"#\" class=\"sidebar-toggle\" data-toggle=\"offcanvas\" role=\"button\"><span class=\"sr-only\">切换导航</span></a>\n          \t<div class=\"navbar-custom-menu\">\n\t\t\t\t<ul class=\"nav navbar-nav\">\n\t\t\t\t\t<li class=\"dropdown user user-menu\">\n\t                    <a href=\";\" id=\"logoutBtn\" class=\"dropdown-toggle\" data-toggle=\"dropdown\" aria-expanded=\"false\">\n                      \t\t<span class=\"hidden-xs\">注销</span>\n\t                    </a>\n\t\t\t\t\t</li>\n\t\t\t\t</ul>\n\t\t\t</div>\n\t\t</nav>\n\t</header>\n</#macro>\n\n<#macro commonLeft pageName >\n\t<!-- Left side column. contains the logo and sidebar -->\n\t<aside class=\"main-sidebar\">\n\t\t<!-- sidebar: style can be found in sidebar.less -->\n\t\t<section class=\"sidebar\">\n\t\t\t<!-- sidebar menu: : style can be found in sidebar.less -->\n\t\t\t<ul class=\"sidebar-menu\">\n\t\t\t\t<li class=\"header\">常用模块</li>\n\t\t\t\t<li class=\"nav-click <#if pageName == \"jobinfo\">active</#if>\" ><a href=\"/jobinfo\"><i class=\"fa fa-circle-o text-aqua\"></i><span>任务管理</span></a></li>\n\t\t\t\t<li class=\"nav-click <#if pageName == \"joblog\">active</#if>\" ><a href=\"/joblog\"><i class=\"fa fa-circle-o text-yellow\"></i><span>调度日志</span></a></li>\n                <li class=\"nav-click <#if pageName == \"jobgroup\">active</#if>\" ><a href=\"/jobgroup\"><i class=\"fa fa-circle-o text-green\"></i><span>执行器管理</span></a></li>\n\t\t\t</ul>\n\t\t</section>\n\t\t<!-- /.sidebar -->\n\t</aside>\n</#macro>\n\n<#macro commonControl >\n\t<!-- Control Sidebar -->\n\t<aside class=\"control-sidebar control-sidebar-dark\">\n\t\t<!-- Create the tabs -->\n\t\t<ul class=\"nav nav-tabs nav-justified control-sidebar-tabs\">\n\t\t\t<li class=\"active\"><a href=\"#control-sidebar-home-tab\" data-toggle=\"tab\"><i class=\"fa fa-home\"></i></a></li>\n\t\t\t<li><a href=\"#control-sidebar-settings-tab\" data-toggle=\"tab\"><i class=\"fa fa-gears\"></i></a></li>\n\t\t</ul>\n\t\t<!-- Tab panes -->\n\t\t<div class=\"tab-content\">\n\t\t\t<!-- Home tab content -->\n\t\t\t<div class=\"tab-pane active\" id=\"control-sidebar-home-tab\">\n\t\t\t\t<h3 class=\"control-sidebar-heading\">近期活动</h3>\n\t\t\t\t<ul class=\"control-sidebar-menu\">\n\t\t\t\t\t<li>\n\t\t\t\t\t\t<a href=\"javascript::;\">\n\t\t\t\t\t\t\t<i class=\"menu-icon fa fa-birthday-cake bg-red\"></i>\n\t\t\t\t\t\t\t<div class=\"menu-info\">\n\t\t\t\t\t\t\t\t<h4 class=\"control-sidebar-subheading\">张三今天过生日</h4>\n\t\t\t\t\t\t\t\t<p>2015-09-10</p>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</a>\n\t\t\t\t\t</li>\n\t\t\t\t\t<li>\n\t\t\t\t\t\t<a href=\"javascript::;\"> \n\t\t\t\t\t\t\t<i class=\"menu-icon fa fa-user bg-yellow\"></i>\n\t\t\t\t\t\t\t<div class=\"menu-info\">\n\t\t\t\t\t\t\t\t<h4 class=\"control-sidebar-subheading\">Frodo 更新了资料</h4>\n\t\t\t\t\t\t\t\t<p>更新手机号码 +1(800)555-1234</p>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</a>\n\t\t\t\t\t</li>\n\t\t\t\t\t<li>\n\t\t\t\t\t\t<a href=\"javascript::;\"> \n\t\t\t\t\t\t\t<i class=\"menu-icon fa fa-envelope-o bg-light-blue\"></i>\n\t\t\t\t\t\t\t<div class=\"menu-info\">\n\t\t\t\t\t\t\t\t<h4 class=\"control-sidebar-subheading\">Nora 加入邮件列表</h4>\n\t\t\t\t\t\t\t\t<p>nora@example.com</p>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</a>\n\t\t\t\t\t</li>\n\t\t\t\t\t<li>\n\t\t\t\t\t\t<a href=\"javascript::;\">\n\t\t\t\t\t\t<i class=\"menu-icon fa fa-file-code-o bg-green\"></i>\n\t\t\t\t\t\t<div class=\"menu-info\">\n\t\t\t\t\t\t\t<h4 class=\"control-sidebar-subheading\">001号定时作业调度</h4>\n\t\t\t\t\t\t\t<p>5秒前执行</p>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</a>\n\t\t\t\t\t</li>\n\t\t\t\t</ul>\n\t\t\t\t<!-- /.control-sidebar-menu -->\n\t\t\t</div>\n\t\t\t<!-- /.tab-pane -->\n\n\t\t\t<!-- Settings tab content -->\n\t\t\t<div class=\"tab-pane\" id=\"control-sidebar-settings-tab\">\n\t\t\t\t<form method=\"post\">\n\t\t\t\t\t<h3 class=\"control-sidebar-heading\">个人设置</h3>\n\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t<label class=\"control-sidebar-subheading\"> 左侧菜单自适应\n\t\t\t\t\t\t\t<input type=\"checkbox\" class=\"pull-right\" checked>\n\t\t\t\t\t\t</label>\n\t\t\t\t\t\t<p>左侧菜单栏样式自适应</p>\n\t\t\t\t\t</div>\n\t\t\t\t\t<!-- /.form-group -->\n\n\t\t\t\t</form>\n\t\t\t</div>\n\t\t\t<!-- /.tab-pane -->\n\t\t</div>\n\t</aside>\n\t<!-- /.control-sidebar -->\n\t<!-- Add the sidebar's background. This div must be placed immediately after the control sidebar -->\n\t<div class=\"control-sidebar-bg\"></div>\n</#macro>\n\n<#macro commonFooter >\n\t<footer class=\"main-footer\">\n        Powered by <b>Sinosoft</b>\n\t\t<div class=\"pull-right hidden-xs\">\n            <strong>Copyright &copy; 2015-${.now?string('yyyy')} &nbsp;\n            </strong><!-- All rights reserved. -->\n\t\t</div>\n\t</footer>\n</#macro>"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/view/templates/common/common.result.ftl",
    "content": "${result?if_exists}"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/view/templates/index.ftl",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  \t<title>任务调度中心</title>\n  \t<#import \"common/common.macro.ftl\" as netCommon>\n\t<@netCommon.commonStyle />\n</head>\n<body class=\"hold-transition skin-blue sidebar-mini <#if cookieMap?exists && \"off\" == cookieMap[\"xxljob_adminlte_settings\"].value >sidebar-collapse</#if> \">\n<div class=\"wrapper\">\n\t<!-- header -->\n\t<@netCommon.commonHeader />\n\t<!-- left -->\n\t<@netCommon.commonLeft \"index\" />\n\t\n\t<!-- Content Wrapper. Contains page content -->\n\t<div class=\"content-wrapper\">\n\t\t<!-- Content Header (Page header) -->\n\t\t<section class=\"content-header\">\n\t\t\t<h1>运行报表<small>任务调度中心</small></h1>\n\t\t\t<!--\n\t\t\t<ol class=\"breadcrumb\">\n\t\t\t\t<li><a><i class=\"fa fa-dashboard\"></i>调度中心</a></li>\n\t\t\t</ol>\n\t\t\t-->\n\t\t</section>\n\n\t\t<!-- Main content -->\n\t\t<section class=\"content\">\n\n            <!-- 任务信息 -->\n            <div class=\"row\">\n\n                <#-- 任务信息 -->\n                <div class=\"col-md-4 col-sm-6 col-xs-12\">\n                    <div class=\"info-box bg-aqua\">\n                        <span class=\"info-box-icon\"><i class=\"fa fa-flag-o\"></i></span>\n\n                        <div class=\"info-box-content\">\n                            <span class=\"info-box-text\">任务数量</span>\n                            <span class=\"info-box-number\">${jobInfoCount}</span>\n\n                            <div class=\"progress\">\n                                <div class=\"progress-bar\" style=\"width: 100%\"></div>\n                            </div>\n                            <span class=\"progress-description\">系统中配置的任务数量</span>\n                        </div>\n                    </div>\n                </div>\n\n                <#-- 调度信息 -->\n                <div class=\"col-md-4 col-sm-6 col-xs-12\" >\n                    <div class=\"info-box bg-yellow\">\n                        <span class=\"info-box-icon\"><i class=\"fa fa-calendar\"></i></span>\n\n                        <div class=\"info-box-content\">\n                            <span class=\"info-box-text\">调度次数</span>\n                            <span class=\"info-box-number\">${jobLogCount}</span>\n\n                            <div class=\"progress\">\n                                <div class=\"progress-bar\" style=\"width: 100%\" ></div>\n                            </div>\n                            <span class=\"progress-description\">\n                                调度中心触发的调度次数\n                                <#--<#if jobLogCount gt 0>\n                                    调度成功率：${(jobLogSuccessCount*100/jobLogCount)?string(\"0.00\")}<small>%</small>\n                                </#if>-->\n                            </span>\n                        </div>\n                    </div>\n                </div>\n\n                <#-- 执行器 -->\n                <div class=\"col-md-4 col-sm-6 col-xs-12\">\n                    <div class=\"info-box bg-green\">\n                        <span class=\"info-box-icon\"><i class=\"fa ion-ios-settings-strong\"></i></span>\n\n                        <div class=\"info-box-content\">\n                            <span class=\"info-box-text\">执行器数量</span>\n                            <span class=\"info-box-number\">${executorCount}</span>\n\n                            <div class=\"progress\">\n                                <div class=\"progress-bar\" style=\"width: 100%\"></div>\n                            </div>\n                            <span class=\"progress-description\">心跳检测成功的执行器机器数量</span>\n                        </div>\n                    </div>\n                </div>\n\n            </div>\n\n            <#-- 调度报表：时间区间筛选，左侧折线图 + 右侧饼图 -->\n            <div class=\"row\">\n                <div class=\"col-md-12\">\n                    <div class=\"box\">\n                        <div class=\"box-header with-border\">\n                            <h3 class=\"box-title\">调度报表（一月之内）</h3>\n                            <#--<input type=\"text\" class=\"form-control\" id=\"filterTime\" readonly >-->\n                        </div>\n                        <div class=\"box-body\">\n                            <div class=\"row\">\n                                <#-- 左侧折线图 -->\n                                <div class=\"col-md-8\">\n                                    <div id=\"lineChart\" style=\"height: 350px;\"></div>\n                                </div>\n                                <#-- 右侧饼图 -->\n                                <div class=\"col-md-4\">\n                                    <div id=\"pieChart\" style=\"height: 350px;\"></div>\n                                </div>\n                            </div>\n                        </div>\n                    </div>\n                </div>\n            </div>\n\n\n\t\t</section>\n\t\t<!-- /.content -->\n\t</div>\n\t<!-- /.content-wrapper -->\n\t\n\t<!-- footer -->\n\t<@netCommon.commonFooter />\n</div>\n<@netCommon.commonScript />\n<#--<script src=\"${request.contextPath}/static/adminlte/plugins/daterangepicker/moment.min.js\"></script>\n<script src=\"${request.contextPath}/static/adminlte/plugins/daterangepicker/daterangepicker.js\"></script>-->\n<script src=\"/plugins/echarts/echarts.common.min.js\"></script>\n<script src=\"/js/index.js\"></script>\n\n</body>\n</html>\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/view/templates/jobcode/jobcode.index.ftl",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  \t<title>任务调度中心</title>\n  \t<#import \"common/common.macro.ftl\" as netCommon>\n\t<@netCommon.commonStyle />\n\t<link rel=\"stylesheet\" href=\"/plugins/codemirror/lib/codemirror.css\">\n\t<link rel=\"stylesheet\" href=\"/plugins/codemirror/addon/hint/show-hint.css\">\n\t<style type=\"text/css\">\n\t\t.CodeMirror {\n      \t\tfont-size:16px;\n            width: 100%;\n      \t\theight: 100%;\n            /*bottom: 0;\n            top: 0px;*/\n            position: absolute;\n\t\t}\n    </style>\n</head>\n<body class=\"skin-blue fixed layout-top-nav\">\n\n\t<div class=\"wrapper\">\n\n        <header class=\"main-header\">\n            <nav class=\"navbar navbar-static-top\">\n                <div class=\"container\">\n\t\t\t\t\t<#-- icon -->\n                    <div class=\"navbar-header\">\n                        <a class=\"navbar-brand\"><b>Web</b>IDE</a>\n                        <button type=\"button\" class=\"navbar-toggle collapsed\" data-toggle=\"collapse\" data-target=\"#navbar-collapse\">\n                            <i class=\"fa fa-bars\"></i>\n                        </button>\n                    </div>\n\n                    <#-- left nav -->\n                    <div class=\"collapse navbar-collapse pull-left\" id=\"navbar-collapse\">\n                        <ul class=\"nav navbar-nav\">\n                            <li class=\"active\" ><a href=\"javascript:;\"><#list GlueTypeEnum as item><#if item == jobInfo.glueType>${item.desc}</#if></#list> 任务：${jobInfo.jobDesc}<span class=\"sr-only\">(current)</span></a></li>\n                        </ul>\n                    </div>\n\n\t\t\t\t\t<#-- right nav -->\n                    <div class=\"navbar-custom-menu\">\n                        <ul class=\"nav navbar-nav\">\n                            <li class=\"dropdown\">\n                                <a href=\"#\" class=\"dropdown-toggle\" data-toggle=\"dropdown\" aria-expanded=\"false\">版本回溯 <span class=\"caret\"></span></a>\n                                <ul class=\"dropdown-menu\" role=\"menu\">\n                                    <li <#if jobLogGlues?exists && jobLogGlues?size gt 0 >style=\"display: none;\"</#if> >\n                                        <a href=\"javascript:;\" class=\"source_version\" version=\"version_now\" glueType=\"${jobInfo.glueType}\" >\n                                            <#list GlueTypeEnum as item><#if item == jobInfo.glueType>${item.desc}</#if></#list>： ${jobInfo.glueRemark}\n                                        </a>\n                                    </li>\n                                    <textarea id=\"version_now\" style=\"display:none;\" >${jobInfo.glueSource}</textarea>\n\t\t\t\t\t\t\t\t\t<#if jobLogGlues?exists && jobLogGlues?size gt 0 >\n\t\t\t\t\t\t\t\t\t\t<#list jobLogGlues as glue>\n                                            <li>\n                                                <a href=\"javascript:;\" class=\"source_version\" version=\"version_${glue.id}\" glueType=\"${glue.glueType}\" >\n                                                    <#list GlueTypeEnum as item><#if item == glue.glueType>${item.desc}</#if></#list>： ${glue.glueRemark}\n                                                </a>\n                                            </li>\n                                            <textarea id=\"version_${glue.id}\" style=\"display:none;\" >${glue.glueSource}</textarea>\n\t\t\t\t\t\t\t\t\t\t</#list>\n\t\t\t\t\t\t\t\t\t</#if>\n                                </ul>\n                            </li>\n                            <li id=\"save\" >\n\t\t\t\t\t\t\t\t<a href=\"javascript:;\" >\n\t\t\t\t\t\t\t\t\t<i class=\"fa fa-fw fa-save\" ></i>\n                                    保存\n\t\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t\t</li>\n                        </ul>\n                    </div>\n\n                </div>\n            </nav>\n        </header>\n\n\t\t<div class=\"content-wrapper\" id=\"ideWindow\" ></div>\n\n\t\t<!-- footer -->\n\t\t<#--<@netCommon.commonFooter />-->\n\t</div>\n\n    <!-- 保存.模态框 -->\n    <div class=\"modal fade\" id=\"saveModal\" tabindex=\"-1\" role=\"dialog\"  aria-hidden=\"true\">\n        <div class=\"modal-dialog \">\n            <div class=\"modal-content\">\n                <div class=\"modal-header\">\n                    <h4 class=\"modal-title\" ><i class=\"fa fa-fw fa-save\"></i>保存</h4>\n                </div>\n                <div class=\"modal-body\">\n                    <form class=\"form-horizontal form\" role=\"form\" >\n                        <div class=\"form-group\">\n                            <label for=\"lastname\" class=\"col-sm-2 control-label\">源码备注<font color=\"red\">*</font></label>\n                            <div class=\"col-sm-10\"><input type=\"text\" class=\"form-control\" id=\"glueRemark\" placeholder=\"请输入备注信息\" maxlength=\"64\" ></div>\n                        </div>\n                        <hr>\n                        <div class=\"form-group\">\n                            <div class=\"col-sm-offset-3 col-sm-6\">\n                                <button type=\"button\" class=\"btn btn-primary ok\" >保存</button>\n                                <button type=\"button\" class=\"btn btn-default\" data-dismiss=\"modal\">取消</button>\n                            </div>\n                        </div>\n                    </form>\n                </div>\n            </div>\n        </div>\n    </div>\n\t\n<@netCommon.commonScript />\n<script src=\"/plugins/codemirror/lib/codemirror.js\"></script>\n<script src=\"/plugins/codemirror/mode/clike/clike.js\"></script>\n<script src=\"/plugins/codemirror/mode/shell/shell.js\"></script>\n<script src=\"/plugins/codemirror/mode/python/python.js\"></script>\n<script src=\"/plugins/codemirror/addon/hint/show-hint.js\"></script>\n<script src=\"/plugins/codemirror/addon/hint/anyword-hint.js\"></script>\n<script>\nvar id = '${jobInfo.id}';\nvar glueType = '${jobInfo.glueType}';\n</script>\n<script src=\"/js/jobcode.index.1.js\"></script>\n\n</body>\n</html>\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/view/templates/jobgroup/jobgroup.index.ftl",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  \t<title>任务调度中心</title>\n  \t<#import \"common/common.macro.ftl\" as netCommon>\n\t<@netCommon.commonStyle />\n\t<!-- DataTables -->\n  \t<link rel=\"stylesheet\" href=\"/adminlte/plugins/datatables/dataTables.bootstrap.css\">\n</head>\n<body class=\"hold-transition skin-blue sidebar-mini <#if cookieMap?exists && \"off\" == cookieMap[\"xxljob_adminlte_settings\"].value >sidebar-collapse</#if> \">\n<div class=\"wrapper\">\n\t<!-- header -->\n\t<@netCommon.commonHeader />\n\t<!-- left -->\n\t<@netCommon.commonLeft \"jobgroup\" />\n\t\n\t<!-- Content Wrapper. Contains page content -->\n\t<div class=\"content-wrapper\">\n\t\t<!-- Content Header (Page header) -->\n\t\t<section class=\"content-header\">\n\t\t\t<h1>执行器管理<small>任务调度中心</small></h1>\n\t\t</section>\n\n\t\t<!-- Main content -->\n\t    <section class=\"content\">\n\t\t\t\n\t\t\t<div class=\"row\">\n\t\t\t\t<div class=\"col-xs-12\">\n\t\t\t\t\t<div class=\"box\">\n\t\t\t            <div class=\"box-header\">\n\t\t\t\t\t\t\t<h3 class=\"box-title\">执行器列表</h3>&nbsp;&nbsp;\n                            <button class=\"btn btn-info btn-xs pull-left2 add\" >+新增执行器</button>\n\t\t\t\t\t\t</div>\n\t\t\t            <div class=\"box-body\">\n\t\t\t              \t<table id=\"joblog_list\" class=\"table table-bordered table-striped display\" width=\"100%\" >\n\t\t\t\t                <thead>\n\t\t\t\t\t            \t<tr>\n                                        <#--<th name=\"id\" >ID</th>-->\n                                        <th name=\"order\" >排序</th>\n                                        <th name=\"appName\" >AppName</th>\n                                        <th name=\"title\" >名称</th>\n                                        <th name=\"addressType\" >注册方式</th>\n                                        <th name=\"registryList\" >OnLine 机器</th>\n                                        <th name=\"operate\" >操作</th>\n\t\t\t\t\t                </tr>\n\t\t\t\t                </thead>\n                                <tbody>\n\t\t\t\t\t\t\t\t<#if list?exists && list?size gt 0>\n\t\t\t\t\t\t\t\t<#list list as group>\n\t\t\t\t\t\t\t\t\t<tr>\n                                        <#--<td>${group.id}</td>-->\n                                        <td>${group.order}</td>\n                                        <td>${group.appName}</td>\n                                        <td>${group.title}</td>\n                                        <td><#if group.addressType==0>自动注册<#else>手动录入</#if></td>\n                                        <td><#if group.registryList?exists><#list group.registryList as item><span class=\"badge bg-green\">${item}</span><br></#list></#if></td>\n\t\t\t\t\t\t\t\t\t\t<td>\n                                            <button class=\"btn btn-warning btn-xs update\"\n                                                    id=\"${group.id}\"\n                                                    appName=\"${group.appName}\"\n                                                    title=\"${group.title}\"\n                                                    order=\"${group.order}\"\n                                                    addressType=\"${group.addressType}\"\n                                                    addressList=\"${group.addressList}\" >编辑</button>\n                                            <button class=\"btn btn-danger btn-xs remove\" id=\"${group.id}\" >删除</button>\n\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t\t</#list>\n\t\t\t\t\t\t\t\t</#if>\n\t\t\t\t\t\t\t\t</tbody>\n\t\t\t\t\t\t\t</table>\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</div>\n\t    </section>\n\t</div>\n\n    <!-- 新增.模态框 -->\n    <div class=\"modal fade\" id=\"addModal\" tabindex=\"-1\" role=\"dialog\"  aria-hidden=\"true\">\n        <div class=\"modal-dialog \">\n            <div class=\"modal-content\">\n                <div class=\"modal-header\">\n                    <h4 class=\"modal-title\" >新增执行器</h4>\n                </div>\n                <div class=\"modal-body\">\n                    <form class=\"form-horizontal form\" role=\"form\" >\n                        <div class=\"form-group\">\n                            <label for=\"lastname\" class=\"col-sm-2 control-label\">AppName<font color=\"red\">*</font></label>\n                            <div class=\"col-sm-10\"><input type=\"text\" class=\"form-control\" name=\"appName\" placeholder=\"请输入“AppName”\" maxlength=\"64\" ></div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label for=\"lastname\" class=\"col-sm-2 control-label\">名称<font color=\"red\">*</font></label>\n                            <div class=\"col-sm-10\"><input type=\"text\" class=\"form-control\" name=\"title\" placeholder=\"请输入“名称”\" maxlength=\"12\" ></div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label for=\"lastname\" class=\"col-sm-2 control-label\">排序<font color=\"red\">*</font></label>\n                            <div class=\"col-sm-10\"><input type=\"text\" class=\"form-control\" name=\"order\" placeholder=\"请输入“排序”\" maxlength=\"50\" ></div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label for=\"lastname\" class=\"col-sm-2 control-label\">注册方式<font color=\"red\">*</font></label>\n                            <div class=\"col-sm-10\">\n                                <input type=\"radio\" name=\"addressType\" value=\"0\" checked />自动注册\n                                &nbsp;&nbsp;&nbsp;&nbsp;\n                                <input type=\"radio\" name=\"addressType\" value=\"1\" />手动录入\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label for=\"lastname\" class=\"col-sm-2 control-label\">机器地址<font color=\"red\">*</font></label>\n                            <div class=\"col-sm-10\"><input type=\"text\" class=\"form-control\" name=\"addressList\" placeholder=\"请输入执行器地址列表，多地址逗号分隔\" maxlength=\"200\" readonly=\"readonly\" ></div>\n                        </div>\n                        <hr>\n                        <div class=\"form-group\">\n                            <div class=\"col-sm-offset-3 col-sm-6\">\n                                <button type=\"submit\" class=\"btn btn-primary\"  >保存</button>\n                                <button type=\"button\" class=\"btn btn-default\" data-dismiss=\"modal\">取消</button>\n                            </div>\n                        </div>\n                    </form>\n                </div>\n            </div>\n        </div>\n    </div>\n\n    <!-- 更新.模态框 -->\n    <div class=\"modal fade\" id=\"updateModal\" tabindex=\"-1\" role=\"dialog\"  aria-hidden=\"true\">\n        <div class=\"modal-dialog \">\n            <div class=\"modal-content\">\n                <div class=\"modal-header\">\n                    <h4 class=\"modal-title\" >编辑执行器</h4>\n                </div>\n                <div class=\"modal-body\">\n                    <form class=\"form-horizontal form\" role=\"form\" >\n                        <div class=\"form-group\">\n                            <label for=\"lastname\" class=\"col-sm-2 control-label\">AppName<font color=\"red\">*</font></label>\n                            <div class=\"col-sm-10\"><input type=\"text\" class=\"form-control\" name=\"appName\" placeholder=\"请输入“AppName”\" maxlength=\"64\" ></div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label for=\"lastname\" class=\"col-sm-2 control-label\">名称<font color=\"red\">*</font></label>\n                            <div class=\"col-sm-10\"><input type=\"text\" class=\"form-control\" name=\"title\" placeholder=\"请输入“名称”\" maxlength=\"12\" ></div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label for=\"lastname\" class=\"col-sm-2 control-label\">排序<font color=\"red\">*</font></label>\n                            <div class=\"col-sm-10\"><input type=\"text\" class=\"form-control\" name=\"order\" placeholder=\"请输入“排序”\" maxlength=\"50\" ></div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label for=\"lastname\" class=\"col-sm-2 control-label\">注册方式<font color=\"red\">*</font></label>\n                            <div class=\"col-sm-10\">\n                                <input type=\"radio\" name=\"addressType\" value=\"0\" />自动注册\n                                &nbsp;&nbsp;&nbsp;&nbsp;\n                                <input type=\"radio\" name=\"addressType\" value=\"1\" />手动录入\n                            </div>\n                        </div>\n                        <div class=\"form-group\">\n                            <label for=\"lastname\" class=\"col-sm-2 control-label\">机器地址<font color=\"red\">*</font></label>\n                            <div class=\"col-sm-10\"><input type=\"text\" class=\"form-control\" name=\"addressList\" placeholder=\"请输入执行器地址列表，多地址逗号分隔\" maxlength=\"200\" readonly=\"readonly\" ></div>\n                        </div>\n                        <hr>\n                        <div class=\"form-group\">\n                            <div class=\"col-sm-offset-3 col-sm-6\">\n                                <button type=\"submit\" class=\"btn btn-primary\"  >保存</button>\n                                <button type=\"button\" class=\"btn btn-default\" data-dismiss=\"modal\">取消</button>\n                                <input type=\"hidden\" name=\"id\" >\n                            </div>\n                        </div>\n                    </form>\n                </div>\n            </div>\n        </div>\n    </div>\n\t\n\t<!-- footer -->\n\t<@netCommon.commonFooter />\n</div>\n\n<@netCommon.commonScript />\n<!-- DataTables -->\n<script src=\"/adminlte/plugins/datatables/jquery.dataTables.min.js\"></script>\n<script src=\"/adminlte/plugins/datatables/dataTables.bootstrap.min.js\"></script>\n<#-- jquery.validate -->\n<script src=\"/plugins/jquery/jquery.validate.min.js\"></script>\n<script src=\"/js/jobgroup.index.1.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/view/templates/jobinfo/jobinfo.index.ftl",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  \t<title>任务调度中心</title>\n  \t<#import \"common/common.macro.ftl\" as netCommon>\n\t<@netCommon.commonStyle />\n\t<!-- DataTables -->\n  \t<link rel=\"stylesheet\" href=\"/adminlte/plugins/datatables/dataTables.bootstrap.css\">\n</head>\n<body class=\"hold-transition skin-blue sidebar-mini <#if cookieMap?exists && \"off\" == cookieMap[\"xxljob_adminlte_settings\"].value >sidebar-collapse</#if>\">\n<div class=\"wrapper\">\n\t<!-- header -->\n\t<@netCommon.commonHeader />\n\t<!-- left -->\n\t<@netCommon.commonLeft \"jobinfo\" />\n\t\n\t<!-- Content Wrapper. Contains page content -->\n\t<div class=\"content-wrapper\">\n\t\t<!-- Content Header (Page header) -->\n\t\t<section class=\"content-header\">\n\t\t\t<h1>任务管理<small>任务调度中心</small></h1>\n\t\t\t<!--\n\t\t\t<ol class=\"breadcrumb\">\n\t\t\t\t<li><a><i class=\"fa fa-dashboard\"></i>调度管理</a></li>\n\t\t\t\t<li class=\"active\">调度中心</li>\n\t\t\t</ol>\n\t\t\t-->\n\t\t</section>\n\t\t\n\t\t<!-- Main content -->\n\t    <section class=\"content\">\n\t    \n\t    \t<div class=\"row\">\n\t    \t\t<div class=\"col-xs-4\">\n\t              \t<div class=\"input-group\">\n\t                \t<span class=\"input-group-addon\">执行器</span>\n                \t\t<select class=\"form-control\" id=\"jobGroup\" >\n                \t\t\t<#list JobGroupList as group>\n                \t\t\t\t<option value=\"${group.id}\" <#if jobGroup==group.id>selected</#if> >${group.title}</option>\n                \t\t\t</#list>\n\t                  \t</select>\n\t              \t</div>\n\t            </div>\n                <div class=\"col-xs-4\">\n                    <div class=\"input-group\">\n                        <span class=\"input-group-addon\">JobHandler</span>\n                        <input type=\"text\" class=\"form-control\" id=\"executorHandler\" autocomplete=\"on\" >\n                    </div>\n                </div>\n\t            <div class=\"col-xs-2\">\n\t            \t<button class=\"btn btn-block btn-info\" id=\"searchBtn\">搜索</button>\n\t            </div>\n\t            <div class=\"col-xs-2\">\n\t            \t<button class=\"btn btn-block btn-success add\" type=\"button\">+新增任务</button>\n\t            </div>\n          \t</div>\n\t    \t\n\t\t\t<div class=\"row\">\n\t\t\t\t<div class=\"col-xs-12\">\n\t\t\t\t\t<div class=\"box\">\n\t\t\t            <div class=\"box-header hide\">\n\t\t\t            \t<h3 class=\"box-title\">调度列表</h3>\n\t\t\t            </div>\n\t\t\t            <div class=\"box-body\" >\n\t\t\t              \t<table id=\"job_list\" class=\"table table-bordered table-striped\">\n\t\t\t\t                <thead>\n\t\t\t\t\t            \t<tr>\n\t\t\t\t\t            \t\t<th name=\"id\" >id</th>\n\t\t\t\t\t                \t<th name=\"jobGroup\" >jobGroup</th>\n                                        <th name=\"childJobKey\" >JobKey</th>\n\t\t\t\t\t                  \t<th name=\"jobDesc\" >描述</th>\n                                        <th name=\"glueType\" >运行模式</th>\n\t\t\t\t\t                  \t<th name=\"executorParam\" >任务参数</th>\n                                        <th name=\"jobCron\" >Cron</th>\n\t\t\t\t\t                  \t<th name=\"addTime\" >新增时间</th>\n\t\t\t\t\t                  \t<th name=\"updateTime\" >更新时间</th>\n\t\t\t\t\t                  \t<th name=\"author\" >负责人</th>\n\t\t\t\t\t                  \t<th name=\"alarmEmail\" >报警邮件</th>\n\t\t\t\t\t                  \t<th name=\"glueType\" >运行模式</th>\n\t\t\t\t\t                  \t<th name=\"jobStatus\" >状态</th>\n\t\t\t\t\t                  \t<th>操作</th>\n\t\t\t\t\t                </tr>\n\t\t\t\t                </thead>\n\t\t\t\t                <tbody></tbody>\n\t\t\t\t                <tfoot></tfoot>\n\t\t\t\t\t\t\t</table>\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</div>\n\t    </section>\n\t</div>\n\t\n\t<!-- footer -->\n\t<@netCommon.commonFooter />\n</div>\n\n<!-- job新增.模态框 -->\n<div class=\"modal fade\" id=\"addModal\" tabindex=\"-1\" role=\"dialog\"  aria-hidden=\"true\">\n\t<div class=\"modal-dialog modal-lg\">\n\t\t<div class=\"modal-content\">\n\t\t\t<div class=\"modal-header\">\n            \t<h4 class=\"modal-title\" >新增任务</h4>\n         \t</div>\n         \t<div class=\"modal-body\">\n\t\t\t\t<form class=\"form-horizontal form\" role=\"form\" >\n\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t<label for=\"firstname\" class=\"col-sm-2 control-label\">执行器<font color=\"red\">*</font></label>\n\t\t\t\t\t\t<div class=\"col-sm-4\">\n\t\t\t\t\t\t\t<select class=\"form-control\" name=\"jobGroup\" >\n\t\t            \t\t\t<#list JobGroupList as group>\n\t\t            \t\t\t\t<option value=\"${group.id}\" <#if jobGroup==group.id>selected</#if> >${group.title}</option>\n\t\t            \t\t\t</#list>\n\t\t                  \t</select>\n\t\t\t\t\t\t</div>\n                        <label for=\"lastname\" class=\"col-sm-2 control-label\">任务描述<font color=\"red\">*</font></label>\n                        <div class=\"col-sm-4\"><input type=\"text\" class=\"form-control\" name=\"jobDesc\" placeholder=\"请输入“描述”\" maxlength=\"50\" ></div>\n\t\t\t\t\t</div>\n                    <div class=\"form-group\">\n                        <label for=\"firstname\" class=\"col-sm-2 control-label\">路由策略<font color=\"red\">*</font></label>\n                        <div class=\"col-sm-4\">\n                            <select class=\"form-control\" name=\"executorRouteStrategy\" >\n\t\t\t\t\t\t\t<#list ExecutorRouteStrategyEnum as item>\n                                <option value=\"${item}\" >${item.title}</option>\n\t\t\t\t\t\t\t</#list>\n                            </select>\n                        </div>\n                        <label for=\"lastname\" class=\"col-sm-2 control-label\">Cron<font color=\"red\">*</font></label>\n                        <div class=\"col-sm-4\"><input type=\"text\" class=\"form-control\" name=\"jobCron\" placeholder=\"请输入“Cron”\" maxlength=\"20\" ></div>\n                    </div>\n                    <div class=\"form-group\">\n                        <label for=\"firstname\" class=\"col-sm-2 control-label\">运行模式<font color=\"red\">*</font></label>\n                        <div class=\"col-sm-4\">\n                            <select class=\"form-control glueType\" name=\"glueType\" >\n\t\t\t\t\t\t\t\t<#list GlueTypeEnum as item>\n\t\t\t\t\t\t\t\t\t<option value=\"${item}\" >${item.desc}</option>\n\t\t\t\t\t\t\t\t</#list>\n                            </select>\n                        </div>\n                        <label for=\"firstname\" class=\"col-sm-2 control-label\">JobHandler<font color=\"black\">*</font></label>\n                        <div class=\"col-sm-4\"><input type=\"text\" class=\"form-control\" name=\"executorHandler\" placeholder=\"请输入“JobHandler”\" maxlength=\"100\" ></div>\n                    </div>\n                    <div class=\"form-group\">\n                        <label for=\"firstname\" class=\"col-sm-2 control-label\">执行参数<font color=\"black\">*</font></label>\n                        <div class=\"col-sm-4\"><input type=\"text\" class=\"form-control\" name=\"executorParam\" placeholder=\"请输入“执行参数”\" maxlength=\"100\" ></div>\n                        <label for=\"lastname\" class=\"col-sm-2 control-label\">子任务Key<font color=\"black\">*</font></label>\n                        <div class=\"col-sm-4\"><input type=\"text\" class=\"form-control\" name=\"childJobKey\" placeholder=\"请输入子任务的任务Key,如存在多个逗号分隔\" maxlength=\"100\" ></div>\n                    </div>\n                    <div class=\"form-group\">\n                        <label for=\"firstname\" class=\"col-sm-2 control-label\">阻塞处理策略<font color=\"red\">*</font></label>\n                        <div class=\"col-sm-4\">\n                            <select class=\"form-control\" name=\"executorBlockStrategy\" >\n\t\t\t\t\t\t\t\t<#list ExecutorBlockStrategyEnum as item>\n\t\t\t\t\t\t\t\t\t<option value=\"${item}\" >${item.title}</option>\n\t\t\t\t\t\t\t\t</#list>\n                            </select>\n\t\t\t\t\t\t</div>\n                        <label for=\"lastname\" class=\"col-sm-2 control-label\">失败处理策略<font color=\"red\">*</font></label>\n                        <div class=\"col-sm-4\">\n                            <select class=\"form-control\" name=\"executorFailStrategy\" >\n\t\t\t\t\t\t\t\t<#list ExecutorFailStrategyEnum as item>\n\t\t\t\t\t\t\t\t\t<option value=\"${item}\" >${item.title}</option>\n\t\t\t\t\t\t\t\t</#list>\n                            </select>\n\t\t\t\t\t\t</div>\n                    </div>\n\t\t\t\t\t<div class=\"form-group\">\n                        <label for=\"lastname\" class=\"col-sm-2 control-label\">负责人<font color=\"red\">*</font></label>\n                        <div class=\"col-sm-4\"><input type=\"text\" class=\"form-control\" name=\"author\" placeholder=\"请输入“负责人”\" maxlength=\"50\" ></div>\n\t\t\t\t\t\t<label for=\"lastname\" class=\"col-sm-2 control-label\">报警邮件<font color=\"black\">*</font></label>\n\t\t\t\t\t\t<div class=\"col-sm-4\"><input type=\"text\" class=\"form-control\" name=\"alarmEmail\" placeholder=\"请输入“报警邮件”，多个邮件地址逗号分隔\" maxlength=\"100\" ></div>\n\t\t\t\t\t</div>\n\n                    <hr>\n\t\t\t\t\t<div class=\"form-group\">\n\t\t\t\t\t\t<div class=\"col-sm-offset-3 col-sm-6\">\n\t\t\t\t\t\t\t<button type=\"submit\" class=\"btn btn-primary\"  >保存</button>\n\t\t\t\t\t\t\t<button type=\"button\" class=\"btn btn-default\" data-dismiss=\"modal\">取消</button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\n<input type=\"hidden\" name=\"glueRemark\" value=\"GLUE代码初始化\" >\n<textarea name=\"glueSource\" style=\"display:none;\" ></textarea>\n<textarea class=\"glueSource_java\" style=\"display:none;\" >\npackage com.xxl.job.service.handler;\n\nimport com.xxl.job.core.log.XxlJobLogger;\nimport com.xxl.job.core.biz.model.ReturnT;\nimport com.xxl.job.core.handler.IJobHandler;\n\npublic class DemoGlueJobHandler extends IJobHandler {\n\n\t@Override\n\tpublic ReturnT<String> execute(String... params) throws Exception {\n\t\tXxlJobLogger.log(\"XXL-JOB, Hello World.\");\n\t\treturn ReturnT.SUCCESS;\n\t}\n\n}\n</textarea>\n<textarea class=\"glueSource_shell\" style=\"display:none;\" >\n#!/bin/bash\necho \"xxl-job: hello shell\"\n\necho \"脚本位置：$0\"\necho \"参数数量：$#\"\nfor param in $*\ndo\n    echo \"参数 : $param\"\n    sleep 1s\ndone\n\necho \"Good bye!\"\nexit 0\n</textarea>\n<textarea class=\"glueSource_python\" style=\"display:none;\" >\n#!/usr/bin/python\n# -*- coding: UTF-8 -*-\nimport time\nimport sys\n\nprint \"xxl-job: hello python\"\nprint \"脚本文件：\", sys.argv[0]\nfor i in range(1, len(sys.argv)):\n\ttime.sleep(1)\n\tprint \"参数\", i, sys.argv[i]\n\nprint \"Good bye!\"\nexit(0)<#--\nimport logging\nlogging.basicConfig(level=logging.DEBUG)\nlogging.info(\"脚本文件：\" + sys.argv[0])\n-->\n</textarea>\n\t\t\t\t\t\n\t\t\t\t</form>\n         \t</div>\n\t\t</div>\n\t</div>\n</div>\n\n<!-- 更新.模态框 -->\n<div class=\"modal fade\" id=\"updateModal\" tabindex=\"-1\" role=\"dialog\"  aria-hidden=\"true\">\n\t<div class=\"modal-dialog modal-lg\">\n\t\t<div class=\"modal-content\">\n\t\t\t<div class=\"modal-header\">\n            \t<h4 class=\"modal-title\" >更新任务</h4>\n         \t</div>\n         \t<div class=\"modal-body\">\n\t\t\t\t<form class=\"form-horizontal form\" role=\"form\" >\n                    <div class=\"form-group\">\n                        <label for=\"firstname\" class=\"col-sm-2 control-label\">执行器<font color=\"red\">*</font></label>\n                        <div class=\"col-sm-4\">\n                            <select class=\"form-control\" name=\"jobGroup\" disabled >\n\t\t\t\t\t\t\t<#list JobGroupList as group>\n                                <option value=\"${group.id}\" >${group.title}</option>\n\t\t\t\t\t\t\t</#list>\n                            </select>\n                        </div>\n                        <label for=\"lastname\" class=\"col-sm-2 control-label\">任务描述<font color=\"red\">*</font></label>\n                        <div class=\"col-sm-4\"><input type=\"text\" class=\"form-control\" name=\"jobDesc\" placeholder=\"请输入“描述”\" maxlength=\"50\" ></div>\n                    </div>\n                    <div class=\"form-group\">\n                        <label for=\"firstname\" class=\"col-sm-2 control-label\">路由策略<font color=\"red\">*</font></label>\n                        <div class=\"col-sm-4\">\n                            <select class=\"form-control\" name=\"executorRouteStrategy\" >\n\t\t\t\t\t\t\t<#list ExecutorRouteStrategyEnum as item>\n                                <option value=\"${item}\" >${item.title}</option>\n\t\t\t\t\t\t\t</#list>\n                            </select>\n                        </div>\n                        <label for=\"lastname\" class=\"col-sm-2 control-label\">Cron<font color=\"red\">*</font></label>\n                        <div class=\"col-sm-4\"><input type=\"text\" class=\"form-control\" name=\"jobCron\" placeholder=\"请输入“Cron”\" maxlength=\"20\" ></div>\n                    </div>\n                    <div class=\"form-group\">\n                        <label for=\"firstname\" class=\"col-sm-2 control-label\">运行模式<font color=\"red\">*</font></label>\n                        <div class=\"col-sm-4\">\n                            <select class=\"form-control glueType\" name=\"glueType\" disabled >\n\t\t\t\t\t\t\t<#list GlueTypeEnum as item>\n                                <option value=\"${item}\" >${item.desc}</option>\n\t\t\t\t\t\t\t</#list>\n                            </select>\n                        </div>\n                        <label for=\"firstname\" class=\"col-sm-2 control-label\">JobHandler<font color=\"black\">*</font></label>\n                        <div class=\"col-sm-4\"><input type=\"text\" class=\"form-control\" name=\"executorHandler\" placeholder=\"请输入“JobHandler”\" maxlength=\"100\" ></div>\n                    </div>\n                    <div class=\"form-group\">\n                        <label for=\"firstname\" class=\"col-sm-2 control-label\">执行参数<font color=\"black\">*</font></label>\n                        <div class=\"col-sm-4\"><input type=\"text\" class=\"form-control\" name=\"executorParam\" placeholder=\"请输入“执行参数”\" maxlength=\"100\" ></div>\n                        <label for=\"lastname\" class=\"col-sm-2 control-label\">子任务Key<font color=\"black\">*</font></label>\n                        <div class=\"col-sm-4\"><input type=\"text\" class=\"form-control\" name=\"childJobKey\" placeholder=\"请输入子任务的任务Key,如存在多个逗号分隔\" maxlength=\"100\" ></div>\n                    </div>\n                    <div class=\"form-group\">\n                        <label for=\"firstname\" class=\"col-sm-2 control-label\">阻塞处理策略<font color=\"red\">*</font></label>\n                        <div class=\"col-sm-4\">\n                            <select class=\"form-control\" name=\"executorBlockStrategy\" >\n\t\t\t\t\t\t\t<#list ExecutorBlockStrategyEnum as item>\n                                <option value=\"${item}\" >${item.title}</option>\n\t\t\t\t\t\t\t</#list>\n                            </select>\n                        </div>\n                        <label for=\"lastname\" class=\"col-sm-2 control-label\">失败处理策略<font color=\"red\">*</font></label>\n                        <div class=\"col-sm-4\">\n                            <select class=\"form-control\" name=\"executorFailStrategy\" >\n\t\t\t\t\t\t\t<#list ExecutorFailStrategyEnum as item>\n                                <option value=\"${item}\" >${item.title}</option>\n\t\t\t\t\t\t\t</#list>\n                            </select>\n                        </div>\n                    </div>\n                    <div class=\"form-group\">\n                        <label for=\"lastname\" class=\"col-sm-2 control-label\">负责人<font color=\"red\">*</font></label>\n                        <div class=\"col-sm-4\"><input type=\"text\" class=\"form-control\" name=\"author\" placeholder=\"请输入“负责人”\" maxlength=\"50\" ></div>\n                        <label for=\"lastname\" class=\"col-sm-2 control-label\">报警邮件<font color=\"black\">*</font></label>\n                        <div class=\"col-sm-4\"><input type=\"text\" class=\"form-control\" name=\"alarmEmail\" placeholder=\"请输入“报警邮件”，多个邮件地址逗号分隔\" maxlength=\"100\" ></div>\n                    </div>\n\n\t\t\t\t\t<hr>\n\t\t\t\t\t<div class=\"form-group\">\n                        <div class=\"col-sm-offset-3 col-sm-6\">\n\t\t\t\t\t\t\t<button type=\"submit\" class=\"btn btn-primary\"  >保存</button>\n\t\t\t\t\t\t\t<button type=\"button\" class=\"btn btn-default\" data-dismiss=\"modal\">取消</button>\n                            <input type=\"hidden\" name=\"id\" >\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</form>\n         \t</div>\n\t\t</div>\n\t</div>\n</div>\n\n<@netCommon.commonScript />\n<!-- DataTables -->\n<script src=\"/adminlte/plugins/datatables/jquery.dataTables.min.js\"></script>\n<script src=\"/adminlte/plugins/datatables/dataTables.bootstrap.min.js\"></script>\n<script src=\"/plugins/jquery/jquery.validate.min.js\"></script>\n<!-- moment -->\n<script src=\"/adminlte/plugins/daterangepicker/moment.min.js\"></script>\n<script src=\"/js/jobinfo.index.1.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/view/templates/joblog/joblog.detail.ftl",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <title>任务调度中心</title>\n<#import \"common/common.macro.ftl\" as netCommon>\n<@netCommon.commonStyle />\n</head>\n<body class=\"hold-transition skin-blue layout-top-nav\">\n\n<div class=\"wrapper\">\n\n    <header class=\"main-header\">\n        <nav class=\"navbar navbar-static-top\">\n            <div class=\"container\">\n            <#-- icon -->\n                <div class=\"navbar-header\">\n                    <a class=\"navbar-brand\"><b>执行日志</b>Console</a>\n                    <button type=\"button\" class=\"navbar-toggle collapsed\" data-toggle=\"collapse\" data-target=\"#navbar-collapse\">\n                        <i class=\"fa fa-bars\"></i>\n                    </button>\n                </div>\n\n                <#-- left nav -->\n                <div class=\"collapse navbar-collapse pull-left\" id=\"navbar-collapse\">\n                    <ul class=\"nav navbar-nav\">\n                        <#--<li class=\"active\" ><a href=\"javascript:;\">任务：<span class=\"sr-only\">(current)</span></a></li>-->\n                    </ul>\n                </div>\n\n                <#-- right nav -->\n                <div class=\"navbar-custom-menu\">\n                    <ul class=\"nav navbar-nav\">\n                        <li>\n                            <a href=\"javascript:window.location.reload();\" >\n                                <i class=\"fa fa-fw fa-refresh\" ></i>\n                                刷新\n                            </a>\n                        </li>\n                    </ul>\n                </div>\n\n            </div>\n        </nav>\n    </header>\n\n    <div class=\"content-wrapper\" >\n        <section class=\"content\">\n            <pre style=\"font-size:12px;position:relative;\" >\n                <div id=\"logConsole\"></div>\n                <li class=\"fa fa-refresh fa-spin\" style=\"font-size: 20px;float: left;\" id=\"logConsoleRunning\" ></li>\n                <div><hr><hr></div>\n            </pre>\n        </section>\n    </div>\n\n    <!-- footer -->\n    <@netCommon.commonFooter />\n\n</div>\n\n<@netCommon.commonScript />\n<script>\n    // 参数\n    var triggerCode = '${triggerCode}';\n    var handleCode = '${handleCode}';\n    var executorAddress = '${executorAddress}';\n    var triggerTime = '${triggerTime}';\n    var logId = '${logId}';\n</script>\n<script src=\"/js/joblog.detail.1.js\"></script>\n\n</body>\n</html>"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/view/templates/joblog/joblog.index.ftl",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  \t<title>任务调度中心</title>\n  \t<#import \"common/common.macro.ftl\" as netCommon>\n\t<@netCommon.commonStyle />\n\t<!-- DataTables -->\n  \t<link rel=\"stylesheet\" href=\"/adminlte/plugins/datatables/dataTables.bootstrap.css\">\n  \t<!-- daterangepicker -->\n  \t<link rel=\"stylesheet\" href=\"/adminlte/plugins/daterangepicker/daterangepicker.css\">\n</head>\n<body class=\"hold-transition skin-blue sidebar-mini <#if cookieMap?exists && \"off\" == cookieMap[\"xxljob_adminlte_settings\"].value >sidebar-collapse</#if> \">\n<div class=\"wrapper\">\n\t<!-- header -->\n\t<@netCommon.commonHeader />\n\t<!-- left -->\n\t<@netCommon.commonLeft \"joblog\" />\n\t\n\t<!-- Content Wrapper. Contains page content -->\n\t<div class=\"content-wrapper\">\n\t\t<!-- Content Header (Page header) -->\n\t\t<section class=\"content-header\">\n\t\t\t<h1>调度日志<small>任务调度中心</small></h1>\n\t\t\t<!--\n\t\t\t<ol class=\"breadcrumb\">\n\t\t\t\t<li><a><i class=\"fa fa-dashboard\"></i>调度日志</a></li>\n\t\t\t\t<li class=\"active\">调度管理</li>\n\t\t\t</ol>\n\t\t\t-->\n\t\t</section>\n\t\t\n\t\t<!-- Main content -->\n\t    <section class=\"content\">\n\t    \t<div class=\"row\">\n\t    \t\t<div class=\"col-xs-2\">\n \t\t\t\t\t<div class=\"input-group\">\n\t                \t<span class=\"input-group-addon\">执行器</span>\n                \t\t<select class=\"form-control\" id=\"jobGroup\"  paramVal=\"<#if jobInfo?exists>${jobInfo.jobGroup}</#if>\" >\n                            <option value=\"0\" >全部</option>\n                \t\t\t<#list JobGroupList as group>\n                \t\t\t\t<option value=\"${group.id}\" >${group.title}</option>\n                \t\t\t</#list>\n\t                  \t</select>\n\t              \t</div>\n\t            </div>\n\t            <div class=\"col-xs-2\">\n\t              \t<div class=\"input-group\">\n\t                \t<span class=\"input-group-addon\">任务</span>\n                        <select class=\"form-control\" id=\"jobId\" paramVal=\"<#if jobInfo?exists>${jobInfo.id}</#if>\" >\n                            <option value=\"0\" >全部</option>\n\t\t\t\t\t\t</select>\n\t              \t</div>\n\t            </div>\n\n                <div class=\"col-xs-2\">\n                    <div class=\"input-group\">\n                        <span class=\"input-group-addon\">状态</span>\n                        <select class=\"form-control\" id=\"logStatus\" >\n                            <option value=\"-1\" >全部</option>\n                            <option value=\"1\" >成功</option>\n                            <option value=\"2\" >失败</option>\n                            <option value=\"3\" >进行中</option>\n                        </select>\n                    </div>\n                </div>\n\n\t            <div class=\"col-xs-4\">\n              \t\t<div class=\"input-group\">\n                \t\t<span class=\"input-group-addon\">\n\t                  \t\t调度时间\n\t                \t</span>\n\t                \t<input type=\"text\" class=\"form-control\" id=\"filterTime\" readonly >\n\t              \t</div>\n\t            </div>\n\n                <div class=\"col-xs-1\">\n                    <button class=\"btn btn-block btn-info\" id=\"searchBtn\">搜索</button>\n                </div>\n\n\t            <div class=\"col-xs-1\">\n                    <button class=\"btn btn-block btn-nomal\" id=\"clearLog\">清理</button>\n\t            </div>\n          \t</div>\n\t\t\t\n\t\t\t<div class=\"row\">\n\t\t\t\t<div class=\"col-xs-12\">\n\t\t\t\t\t<div class=\"box\">\n\t\t\t            <div class=\"box-header hide\"><h3 class=\"box-title\">调度日志</h3></div>\n\t\t\t            <div class=\"box-body\">\n\t\t\t              \t<table id=\"joblog_list\" class=\"table table-bordered table-striped display\" width=\"100%\" >\n\t\t\t\t                <thead>\n\t\t\t\t\t            \t<tr>\n\t\t\t\t\t                \t<th name=\"id\" >id</th>\n                                        <th name=\"jobGroup\" >执行器ID</th>\n\t\t\t\t\t                \t<th name=\"jobId\" >任务ID</th>\n                                        <th name=\"JobKey\" >JobKey</th>\n\t\t\t\t\t\t\t\t\t\t<#--<th name=\"executorAddress\" >执行器地址</th>\n\t\t\t\t\t\t\t\t\t\t<th name=\"glueType\" >运行模式</th>\n                                      \t<th name=\"executorParam\" >任务参数</th>-->\n                                        <th name=\"triggerTime\" >调度时间</th>\n                                        <th name=\"triggerCode\" >调度结果</th>\n                                        <th name=\"triggerMsg\" >调度备注</th>\n\t\t\t\t\t                  \t<th name=\"handleTime\" >执行时间</th>\n\t\t\t\t\t                  \t<th name=\"handleCode\" >执行结果</th>\n\t\t\t\t\t                  \t<th name=\"handleMsg\" >执行备注</th>\n\t\t\t\t\t                  \t<th name=\"handleMsg\" >操作</th>\n\t\t\t\t\t                </tr>\n\t\t\t\t                </thead>\n\t\t\t\t                <tbody></tbody>\n\t\t\t\t\t\t\t</table>\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</div>\n\t    </section>\n\t</div>\n\t\n\t<!-- footer -->\n\t<@netCommon.commonFooter />\n</div>\n\n<!-- 日志清理.模态框 -->\n<div class=\"modal fade\" id=\"clearLogModal\" tabindex=\"-1\" role=\"dialog\"  aria-hidden=\"true\">\n    <div class=\"modal-dialog\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header\">\n                <h4 class=\"modal-title\" >日志清理</h4>\n            </div>\n            <div class=\"modal-body\">\n                <form class=\"form-horizontal form\" role=\"form\" >\n                    <div class=\"form-group\">\n                        <label class=\"col-sm-3 control-label\"\">执行器：</label>\n                        <div class=\"col-sm-9\">\n                            <input type=\"text\" class=\"form-control jobGroupText\" readonly >\n\t\t\t\t\t\t\t<input type=\"hidden\" name=\"jobGroup\" >\n\t\t\t\t\t\t</div>\n                    </div>\n\n                    <div class=\"form-group\">\n                        <label class=\"col-sm-3 control-label\"\">任务：</label>\n                        <div class=\"col-sm-9\">\n                            <input type=\"text\" class=\"form-control jobIdText\" readonly >\n                            <input type=\"hidden\" name=\"jobId\" >\n\t\t\t\t\t\t</div>\n                    </div>\n\n                    <div class=\"form-group\">\n                        <label class=\"col-sm-3 control-label\"\">清理类型：</label>\n                        <div class=\"col-sm-9\">\n                            <select class=\"form-control\" name=\"type\" >\n                                <option value=\"1\" >清理一个月之前日志数据</option>\n                                <option value=\"2\" >清理三个月之前日志数据</option>\n                                <option value=\"3\" >清理六个月之前日志数据</option>\n                                <option value=\"4\" >清理一年之前日志数据</option>\n                                <option value=\"5\" >清理一千条以前日志数据</option>\n                                <option value=\"6\" >清理一万条以前日志数据</option>\n                                <option value=\"7\" >清理三万条以前日志数据</option>\n                                <option value=\"8\" >清理十万条以前日志数据</option>\n                                <option value=\"9\" >清理所有日志数据</option>\n                            </select>\n                        </div>\n                    </div>\n\n                    <hr>\n                    <div class=\"form-group\">\n                        <div class=\"col-sm-offset-3 col-sm-6\">\n                            <button type=\"button\" class=\"btn btn-primary ok\" >确定</button>\n                            <button type=\"button\" class=\"btn btn-default\" data-dismiss=\"modal\">取消</button>\n                        </div>\n                    </div>\n                </form>\n            </div>\n        </div>\n    </div>\n</div>\n\n<@netCommon.commonScript />\n<!-- DataTables -->\n<script src=\"/adminlte/plugins/datatables/jquery.dataTables.min.js\"></script>\n<script src=\"/adminlte/plugins/datatables/dataTables.bootstrap.min.js\"></script>\n<!-- daterangepicker -->\n<script src=\"/adminlte/plugins/daterangepicker/moment.min.js\"></script>\n<script src=\"/adminlte/plugins/daterangepicker/daterangepicker.js\"></script>\n<script src=\"/js/joblog.index.1.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "open-xxl-job/xxl-job-admin/src/main/view/templates/login.ftl",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  \t<title>调度中心</title>\n  \t<#import \"common/common.macro.ftl\" as netCommon>\n\t<@netCommon.commonStyle />\n    <link rel=\"stylesheet\" href=\"/adminlte/plugins/iCheck/square/blue.css\">\n</head>\n<body class=\"hold-transition login-page\">\n\t<div class=\"login-box\">\n\t\t<div class=\"login-logo\">\n\t\t\t<a><b>Sinosoft</b>JOB</a>\n\t\t</div>\n\t\t<form id=\"loginForm\" method=\"post\" >\n\t\t\t<div class=\"login-box-body\">\n\t\t\t\t<p class=\"login-box-msg\">任务调度中心</p>\n\t\t\t\t<div class=\"form-group has-feedback\">\n\t            \t<input type=\"text\" name=\"userName\" class=\"form-control\" placeholder=\"请输入登录账号\" value=\"admin\" >\n\t            \t<span class=\"glyphicon glyphicon-envelope form-control-feedback\"></span>\n\t\t\t\t</div>\n\t          \t<div class=\"form-group has-feedback\">\n\t            \t<input type=\"password\" name=\"password\" class=\"form-control\" placeholder=\"请输入登录密码\" value=\"123456\" >\n\t            \t<span class=\"glyphicon glyphicon-lock form-control-feedback\"></span>\n\t          \t</div>\n\t\t\t\t<div class=\"row\">\n\t\t\t\t\t<div class=\"col-xs-8\">\n\t\t              \t<div class=\"checkbox icheck\">\n\t\t                \t<label>\n\t\t                  \t\t<input type=\"checkbox\" name=\"ifRemember\" > Remember Me\n\t\t                \t</label>\n\t\t\t\t\t\t</div>\n\t\t            </div><!-- /.col -->\n\t\t            <div class=\"col-xs-4\">\n\t\t\t\t\t\t<button type=\"submit\" class=\"btn btn-primary btn-block btn-flat\">登录</button>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</form>\n\t</div>\n<@netCommon.commonScript />\n<script src=\"/plugins/jquery/jquery.validate.min.js\"></script>\n<script src=\"/adminlte/plugins/iCheck/icheck.min.js\"></script>\n<script src=\"/js/login.1.js\"></script>\n\n</body>\n</html>\n"
  },
  {
    "path": "open-xxl-job/xxl-job-core/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" 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  <parent>\n    <groupId>com.open.capacity</groupId>\n    <artifactId>open-xxl-job</artifactId>\n    <version>0.0.1-SNAPSHOT</version>\n  </parent>\n  <artifactId>xxl-job-core</artifactId>\n  \n  \n\t<dependencies>\n\t\t<!-- servlet -->\n\t\t<dependency>\n\t\t\t<groupId>javax.servlet</groupId>\n\t\t\t<artifactId>javax.servlet-api</artifactId>\n\t\t\t<version>${javax.servlet-api.version}</version>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>javax.servlet.jsp</groupId>\n\t\t\t<artifactId>jsp-api</artifactId>\n\t\t\t<version>${jsp-api.version}</version>\n\t\t</dependency>\n\n\t\t<!-- jetty -->\n\t\t<dependency>\n\t\t\t<groupId>org.eclipse.jetty</groupId>\n\t\t\t<artifactId>jetty-server</artifactId>\n\t\t\t<version>${jetty-server.version}</version>\n\t\t</dependency>\n\n\t\t \n\n\t\t<!-- hessian -->\n\t\t<dependency>\n\t\t\t<groupId>com.caucho</groupId>\n\t\t\t<artifactId>hessian</artifactId>\n\t\t\t<version>${hessian.version}</version>\n\t\t</dependency>\n\n\t\t<!-- jackson -->\n\t\t<dependency>\n\t\t\t<groupId>com.fasterxml.jackson.core</groupId>\n\t\t\t<artifactId>jackson-databind</artifactId>\n\t\t\t<version>${jackson.version}</version>\n\t\t</dependency>\n\n\t\t<!-- httpclient -->\n\t\t<dependency>\n\t\t\t<groupId>org.apache.httpcomponents</groupId>\n\t\t\t<artifactId>httpclient</artifactId>\n\t\t\t<version>${httpclient.version}</version>\n\t\t</dependency>\n\t\t\n\t\t<!-- spring-context -->\n\t\t<dependency>\n\t\t\t<groupId>org.springframework</groupId>\n\t\t\t<artifactId>spring-context</artifactId>\n\t\t\t<version>${spring.version}</version>\n\t\t</dependency>\n\t\t\n\t\t<!-- groovy-all -->\n\t\t<dependency>\n\t\t\t<groupId>org.codehaus.groovy</groupId>\n\t\t\t<artifactId>groovy-all</artifactId>\n\t\t\t<version>${groovy-all.version}</version>\n\t\t</dependency>\n\n\t\t<!-- commons-exec -->\n\t\t<dependency>\n\t\t\t<groupId>org.apache.commons</groupId>\n\t\t\t<artifactId>commons-exec</artifactId>\n\t\t\t<version>${commons-exec.version}</version>\n\t\t</dependency>\n\n\t</dependencies>\n  \n</project>"
  },
  {
    "path": "open-xxl-job/xxl-job-core/src/main/java/com/xxl/job/core/biz/AdminBiz.java",
    "content": "package com.xxl.job.core.biz;\n\nimport com.xxl.job.core.biz.model.HandleCallbackParam;\nimport com.xxl.job.core.biz.model.RegistryParam;\nimport com.xxl.job.core.biz.model.ReturnT;\n\nimport java.util.List;\n\n/**\n * @author xuxueli 2017-07-27 21:52:49\n */\npublic interface AdminBiz {\n\n    public static final String MAPPING = \"/api\";\n\n\n    // ---------------------- callback ----------------------\n\n    /**\n     * callback\n     *\n     * @param callbackParamList\n     * @return\n     */\n    public ReturnT<String> callback(List<HandleCallbackParam> callbackParamList);\n\n\n    // ---------------------- registry ----------------------\n\n    /**\n     * registry\n     *\n     * @param registryParam\n     * @return\n     */\n    public ReturnT<String> registry(RegistryParam registryParam);\n\n    /**\n     * registry remove\n     *\n     * @param registryParam\n     * @return\n     */\n    public ReturnT<String> registryRemove(RegistryParam registryParam);\n\n\n    // ---------------------- job opt ----------------------\n\n    /**\n     * trigger job for once\n     *\n     * @param jobId\n     * @return\n     */\n    public ReturnT<String> triggerJob(int jobId);\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-core/src/main/java/com/xxl/job/core/biz/ExecutorBiz.java",
    "content": "package com.xxl.job.core.biz;\n\nimport com.xxl.job.core.biz.model.LogResult;\nimport com.xxl.job.core.biz.model.ReturnT;\nimport com.xxl.job.core.biz.model.TriggerParam;\n\n/**\n * Created by xuxueli on 17/3/1.\n */\npublic interface ExecutorBiz {\n\n    /**\n     * beat\n     * @return\n     */\n    public ReturnT<String> beat();\n\n    /**\n     * idle beat\n     *\n     * @param jobId\n     * @return\n     */\n    public ReturnT<String> idleBeat(int jobId);\n\n    /**\n     * kill\n     * @param jobId\n     * @return\n     */\n    public ReturnT<String> kill(int jobId);\n\n    /**\n     * log\n     * @param logDateTim\n     * @param logId\n     * @param fromLineNum\n     * @return\n     */\n    public ReturnT<LogResult> log(long logDateTim, int logId, int fromLineNum);\n\n    /**\n     * run\n     * @param triggerParam\n     * @return\n     */\n    public ReturnT<String> run(TriggerParam triggerParam);\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-core/src/main/java/com/xxl/job/core/biz/impl/ExecutorBizImpl.java",
    "content": "package com.xxl.job.core.biz.impl;\n\nimport com.xxl.job.core.biz.ExecutorBiz;\nimport com.xxl.job.core.biz.model.LogResult;\nimport com.xxl.job.core.biz.model.ReturnT;\nimport com.xxl.job.core.biz.model.TriggerParam;\nimport com.xxl.job.core.enums.ExecutorBlockStrategyEnum;\nimport com.xxl.job.core.executor.XxlJobExecutor;\nimport com.xxl.job.core.glue.GlueFactory;\nimport com.xxl.job.core.glue.GlueTypeEnum;\nimport com.xxl.job.core.handler.IJobHandler;\nimport com.xxl.job.core.handler.impl.GlueJobHandler;\nimport com.xxl.job.core.handler.impl.ScriptJobHandler;\nimport com.xxl.job.core.log.XxlJobFileAppender;\nimport com.xxl.job.core.thread.JobThread;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.Date;\n\n/**\n * Created by xuxueli on 17/3/1.\n */\npublic class ExecutorBizImpl implements ExecutorBiz {\n    private static Logger logger = LoggerFactory.getLogger(ExecutorBizImpl.class);\n\n    @Override\n    public ReturnT<String> beat() {\n        return ReturnT.SUCCESS;\n    }\n\n    @Override\n    public ReturnT<String> idleBeat(int jobId) {\n\n        // isRunningOrHasQueue\n        boolean isRunningOrHasQueue = false;\n        JobThread jobThread = XxlJobExecutor.loadJobThread(jobId);\n        if (jobThread != null && jobThread.isRunningOrHasQueue()) {\n            isRunningOrHasQueue = true;\n        }\n\n        if (isRunningOrHasQueue) {\n            return new ReturnT<String>(ReturnT.FAIL_CODE, \"job thread is running or has trigger queue.\");\n        }\n        return ReturnT.SUCCESS;\n    }\n\n    @Override\n    public ReturnT<String> kill(int jobId) {\n        // kill handlerThread, and create new one\n        JobThread jobThread = XxlJobExecutor.loadJobThread(jobId);\n        if (jobThread != null) {\n            XxlJobExecutor.removeJobThread(jobId, \"人工手动终止\");\n            return ReturnT.SUCCESS;\n        }\n\n        return new ReturnT<String>(ReturnT.SUCCESS_CODE, \"job thread aleady killed.\");\n    }\n\n    @Override\n    public ReturnT<LogResult> log(long logDateTim, int logId, int fromLineNum) {\n        // log filename: logPath/yyyy-MM-dd/9999.log\n        String logFileName = XxlJobFileAppender.makeLogFileName(new Date(logDateTim), logId);\n\n        LogResult logResult = XxlJobFileAppender.readLog(logFileName, fromLineNum);\n        return new ReturnT<LogResult>(logResult);\n    }\n\n    @Override\n    public ReturnT<String> run(TriggerParam triggerParam) {\n        // load old：jobHandler + jobThread\n        JobThread jobThread = XxlJobExecutor.loadJobThread(triggerParam.getJobId());\n        IJobHandler jobHandler = jobThread!=null?jobThread.getHandler():null;\n        String removeOldReason = null;\n\n        // valid：jobHandler + jobThread\n        GlueTypeEnum glueTypeEnum = GlueTypeEnum.match(triggerParam.getGlueType());\n        if (GlueTypeEnum.BEAN == glueTypeEnum) {\n\n            // new jobhandler\n            IJobHandler newJobHandler = XxlJobExecutor.loadJobHandler(triggerParam.getExecutorHandler());\n\n            // valid old jobThread\n            if (jobThread!=null && jobHandler != newJobHandler) {\n                // change handler, need kill old thread\n                removeOldReason = \"更换JobHandler或更换任务模式,终止旧任务线程\";\n\n                jobThread = null;\n                jobHandler = null;\n            }\n\n            // valid handler\n            if (jobHandler == null) {\n                jobHandler = newJobHandler;\n                if (jobHandler == null) {\n                    return new ReturnT<String>(ReturnT.FAIL_CODE, \"job handler [\" + triggerParam.getExecutorHandler() + \"] not found.\");\n                }\n            }\n\n        } else if (GlueTypeEnum.GLUE_GROOVY == glueTypeEnum) {\n\n            // valid old jobThread\n            if (jobThread != null &&\n                    !(jobThread.getHandler() instanceof GlueJobHandler\n                        && ((GlueJobHandler) jobThread.getHandler()).getGlueUpdatetime()==triggerParam.getGlueUpdatetime() )) {\n                // change handler or gluesource updated, need kill old thread\n                removeOldReason = \"更新任务逻辑或更换任务模式,终止旧任务线程\";\n\n                jobThread = null;\n                jobHandler = null;\n            }\n\n            // valid handler\n            if (jobHandler == null) {\n                try {\n                    IJobHandler originJobHandler = GlueFactory.getInstance().loadNewInstance(triggerParam.getGlueSource());\n                    jobHandler = new GlueJobHandler(originJobHandler, triggerParam.getGlueUpdatetime());\n                } catch (Exception e) {\n                    logger.error(e.getMessage(), e);\n                    return new ReturnT<String>(ReturnT.FAIL_CODE, e.getMessage());\n                }\n            }\n        } else if (glueTypeEnum!=null && glueTypeEnum.isScript()) {\n\n            // valid old jobThread\n            if (jobThread != null &&\n                    !(jobThread.getHandler() instanceof ScriptJobHandler\n                            && ((ScriptJobHandler) jobThread.getHandler()).getGlueUpdatetime()==triggerParam.getGlueUpdatetime() )) {\n                // change script or gluesource updated, need kill old thread\n                removeOldReason = \"更新任务逻辑或更换任务模式,终止旧任务线程\";\n\n                jobThread = null;\n                jobHandler = null;\n            }\n\n            // valid handler\n            if (jobHandler == null) {\n                jobHandler = new ScriptJobHandler(triggerParam.getJobId(), triggerParam.getGlueUpdatetime(), triggerParam.getGlueSource(), GlueTypeEnum.match(triggerParam.getGlueType()));\n            }\n        } else {\n            return new ReturnT<String>(ReturnT.FAIL_CODE, \"glueType[\" + triggerParam.getGlueType() + \"] is not valid.\");\n        }\n\n        // executor block strategy\n        if (jobThread != null) {\n            ExecutorBlockStrategyEnum blockStrategy = ExecutorBlockStrategyEnum.match(triggerParam.getExecutorBlockStrategy(), null);\n            if (ExecutorBlockStrategyEnum.DISCARD_LATER == blockStrategy) {\n                // discard when running\n                if (jobThread.isRunningOrHasQueue()) {\n                    return new ReturnT<String>(ReturnT.FAIL_CODE, \"阻塞处理策略-生效：\"+ExecutorBlockStrategyEnum.DISCARD_LATER.getTitle());\n                }\n            } else if (ExecutorBlockStrategyEnum.COVER_EARLY == blockStrategy) {\n                // kill running jobThread\n                if (jobThread.isRunningOrHasQueue()) {\n                    removeOldReason = \"阻塞处理策略-生效：\" + ExecutorBlockStrategyEnum.COVER_EARLY.getTitle();\n\n                    jobThread = null;\n                }\n            } else {\n                // just queue trigger\n            }\n        }\n\n        // replace thread (new or exists invalid)\n        if (jobThread == null) {\n            jobThread = XxlJobExecutor.registJobThread(triggerParam.getJobId(), jobHandler, removeOldReason);\n        }\n\n        // push data to queue\n        ReturnT<String> pushResult = jobThread.pushTriggerQueue(triggerParam);\n        return pushResult;\n    }\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-core/src/main/java/com/xxl/job/core/biz/model/HandleCallbackParam.java",
    "content": "package com.xxl.job.core.biz.model;\n\nimport java.io.Serializable;\n\n/**\n * Created by xuxueli on 17/3/2.\n */\npublic class HandleCallbackParam implements Serializable {\n    private static final long serialVersionUID = 42L;\n\n    private int logId;\n    private ReturnT<String> executeResult;\n\n    public HandleCallbackParam(){}\n    public HandleCallbackParam(int logId, ReturnT<String> executeResult) {\n        this.logId = logId;\n        this.executeResult = executeResult;\n    }\n\n    public int getLogId() {\n        return logId;\n    }\n\n    public void setLogId(int logId) {\n        this.logId = logId;\n    }\n\n    public ReturnT<String> getExecuteResult() {\n        return executeResult;\n    }\n\n    public void setExecuteResult(ReturnT<String> executeResult) {\n        this.executeResult = executeResult;\n    }\n\n    @Override\n    public String toString() {\n        return \"HandleCallbackParam{\" +\n                \"logId=\" + logId +\n                \", executeResult=\" + executeResult +\n                '}';\n    }\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-core/src/main/java/com/xxl/job/core/biz/model/LogResult.java",
    "content": "package com.xxl.job.core.biz.model;\n\nimport java.io.Serializable;\n\n/**\n * Created by xuxueli on 17/3/23.\n */\npublic class LogResult implements Serializable {\n    private static final long serialVersionUID = 42L;\n\n    public LogResult(int fromLineNum, int toLineNum, String logContent, boolean isEnd) {\n        this.fromLineNum = fromLineNum;\n        this.toLineNum = toLineNum;\n        this.logContent = logContent;\n        this.isEnd = isEnd;\n    }\n\n    private int fromLineNum;\n    private int toLineNum;\n    private String logContent;\n    private boolean isEnd;\n\n    public int getFromLineNum() {\n        return fromLineNum;\n    }\n\n    public void setFromLineNum(int fromLineNum) {\n        this.fromLineNum = fromLineNum;\n    }\n\n    public int getToLineNum() {\n        return toLineNum;\n    }\n\n    public void setToLineNum(int toLineNum) {\n        this.toLineNum = toLineNum;\n    }\n\n    public String getLogContent() {\n        return logContent;\n    }\n\n    public void setLogContent(String logContent) {\n        this.logContent = logContent;\n    }\n\n    public boolean isEnd() {\n        return isEnd;\n    }\n\n    public void setEnd(boolean end) {\n        isEnd = end;\n    }\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-core/src/main/java/com/xxl/job/core/biz/model/RegistryParam.java",
    "content": "package com.xxl.job.core.biz.model;\n\nimport java.io.Serializable;\n\n/**\n * Created by xuxueli on 2017-05-10 20:22:42\n */\npublic class RegistryParam implements Serializable {\n    private static final long serialVersionUID = 42L;\n\n    private String registGroup;\n    private String registryKey;\n    private String registryValue;\n\n    public RegistryParam(){}\n    public RegistryParam(String registGroup, String registryKey, String registryValue) {\n        this.registGroup = registGroup;\n        this.registryKey = registryKey;\n        this.registryValue = registryValue;\n    }\n\n    public String getRegistGroup() {\n        return registGroup;\n    }\n\n    public void setRegistGroup(String registGroup) {\n        this.registGroup = registGroup;\n    }\n\n    public String getRegistryKey() {\n        return registryKey;\n    }\n\n    public void setRegistryKey(String registryKey) {\n        this.registryKey = registryKey;\n    }\n\n    public String getRegistryValue() {\n        return registryValue;\n    }\n\n    public void setRegistryValue(String registryValue) {\n        this.registryValue = registryValue;\n    }\n\n    @Override\n    public String toString() {\n        return \"RegistryParam{\" +\n                \"registGroup='\" + registGroup + '\\'' +\n                \", registryKey='\" + registryKey + '\\'' +\n                \", registryValue='\" + registryValue + '\\'' +\n                '}';\n    }\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-core/src/main/java/com/xxl/job/core/biz/model/ReturnT.java",
    "content": "package com.xxl.job.core.biz.model;\n\nimport java.io.Serializable;\n\n/**\n * common return\n * @author xuxueli 2015-12-4 16:32:31\n * @param <T>\n */\npublic class ReturnT<T> implements Serializable {\n\tpublic static final long serialVersionUID = 42L;\n\n\tpublic static final int SUCCESS_CODE = 200;\n\tpublic static final int FAIL_CODE = 500;\n\tpublic static final ReturnT<String> SUCCESS = new ReturnT<String>(null);\n\tpublic static final ReturnT<String> FAIL = new ReturnT<String>(FAIL_CODE, null);\n\t\n\tprivate int code;\n\tprivate String msg;\n\tprivate T content;\n\n\tpublic ReturnT(){}\n\tpublic ReturnT(int code, String msg) {\n\t\tthis.code = code;\n\t\tthis.msg = msg;\n\t}\n\tpublic ReturnT(T content) {\n\t\tthis.code = SUCCESS_CODE;\n\t\tthis.content = content;\n\t}\n\t\n\tpublic int getCode() {\n\t\treturn code;\n\t}\n\tpublic void setCode(int code) {\n\t\tthis.code = code;\n\t}\n\tpublic String getMsg() {\n\t\treturn msg;\n\t}\n\tpublic void setMsg(String msg) {\n\t\tthis.msg = msg;\n\t}\n\tpublic T getContent() {\n\t\treturn content;\n\t}\n\tpublic void setContent(T content) {\n\t\tthis.content = content;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"ReturnT [code=\" + code + \", msg=\" + msg + \", content=\" + content + \"]\";\n\t}\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-core/src/main/java/com/xxl/job/core/biz/model/TriggerParam.java",
    "content": "package com.xxl.job.core.biz.model;\n\nimport java.io.Serializable;\n\n/**\n * Created by xuxueli on 16/7/22.\n */\npublic class TriggerParam implements Serializable{\n    private static final long serialVersionUID = 42L;\n\n    private int jobId;\n\n    private String executorHandler;\n    private String executorParams;\n    private String executorBlockStrategy;\n\n    private int logId;\n    private long logDateTim;\n\n    private String glueType;\n    private String glueSource;\n    private long glueUpdatetime;\n\n    private int broadcastIndex;\n    private int broadcastTotal;\n\n    public int getJobId() {\n        return jobId;\n    }\n\n    public void setJobId(int jobId) {\n        this.jobId = jobId;\n    }\n\n    public String getExecutorHandler() {\n        return executorHandler;\n    }\n\n    public void setExecutorHandler(String executorHandler) {\n        this.executorHandler = executorHandler;\n    }\n\n    public String getExecutorParams() {\n        return executorParams;\n    }\n\n    public void setExecutorParams(String executorParams) {\n        this.executorParams = executorParams;\n    }\n\n    public String getExecutorBlockStrategy() {\n        return executorBlockStrategy;\n    }\n\n    public void setExecutorBlockStrategy(String executorBlockStrategy) {\n        this.executorBlockStrategy = executorBlockStrategy;\n    }\n\n    public int getLogId() {\n        return logId;\n    }\n\n    public void setLogId(int logId) {\n        this.logId = logId;\n    }\n\n    public long getLogDateTim() {\n        return logDateTim;\n    }\n\n    public void setLogDateTim(long logDateTim) {\n        this.logDateTim = logDateTim;\n    }\n\n    public String getGlueType() {\n        return glueType;\n    }\n\n    public void setGlueType(String glueType) {\n        this.glueType = glueType;\n    }\n\n    public String getGlueSource() {\n        return glueSource;\n    }\n\n    public void setGlueSource(String glueSource) {\n        this.glueSource = glueSource;\n    }\n\n    public long getGlueUpdatetime() {\n        return glueUpdatetime;\n    }\n\n    public void setGlueUpdatetime(long glueUpdatetime) {\n        this.glueUpdatetime = glueUpdatetime;\n    }\n\n    public int getBroadcastIndex() {\n        return broadcastIndex;\n    }\n\n    public void setBroadcastIndex(int broadcastIndex) {\n        this.broadcastIndex = broadcastIndex;\n    }\n\n    public int getBroadcastTotal() {\n        return broadcastTotal;\n    }\n\n    public void setBroadcastTotal(int broadcastTotal) {\n        this.broadcastTotal = broadcastTotal;\n    }\n\n    @Override\n    public String toString() {\n        return \"TriggerParam{\" +\n                \"jobId=\" + jobId +\n                \", executorHandler='\" + executorHandler + '\\'' +\n                \", executorParams='\" + executorParams + '\\'' +\n                \", executorBlockStrategy='\" + executorBlockStrategy + '\\'' +\n                \", logId=\" + logId +\n                \", logDateTim=\" + logDateTim +\n                \", glueType='\" + glueType + '\\'' +\n                \", glueSource='\" + glueSource + '\\'' +\n                \", glueUpdatetime=\" + glueUpdatetime +\n                \", broadcastIndex=\" + broadcastIndex +\n                \", broadcastTotal=\" + broadcastTotal +\n                '}';\n    }\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-core/src/main/java/com/xxl/job/core/enums/ExecutorBlockStrategyEnum.java",
    "content": "package com.xxl.job.core.enums;\n\n/**\n * Created by xuxueli on 17/5/9.\n */\npublic enum ExecutorBlockStrategyEnum {\n\n    SERIAL_EXECUTION(\"Serial execution\"),\n    /*CONCURRENT_EXECUTION(\"并行\"),*/\n    DISCARD_LATER(\"Discard Later\"),\n    COVER_EARLY(\"Cover Early\");\n\n    private String title;\n    private ExecutorBlockStrategyEnum (String title) {\n        this.title = title;\n    }\n\n    public void setTitle(String title) {\n        this.title = title;\n    }\n    public String getTitle() {\n        return title;\n    }\n\n    public static ExecutorBlockStrategyEnum match(String name, ExecutorBlockStrategyEnum defaultItem) {\n        if (name != null) {\n            for (ExecutorBlockStrategyEnum item:ExecutorBlockStrategyEnum.values()) {\n                if (item.name().equals(name)) {\n                    return item;\n                }\n            }\n        }\n        return defaultItem;\n    }\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-core/src/main/java/com/xxl/job/core/enums/RegistryConfig.java",
    "content": "package com.xxl.job.core.enums;\n\n/**\n * Created by xuxueli on 17/5/10.\n */\npublic class RegistryConfig {\n\n    public static final int BEAT_TIMEOUT = 30;\n    public static final int DEAD_TIMEOUT = BEAT_TIMEOUT * 3;\n\n    public enum RegistType{ EXECUTOR, ADMIN }\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-core/src/main/java/com/xxl/job/core/executor/XxlJobExecutor.java",
    "content": "package com.xxl.job.core.executor;\n\nimport com.xxl.job.core.biz.AdminBiz;\nimport com.xxl.job.core.biz.ExecutorBiz;\nimport com.xxl.job.core.biz.impl.ExecutorBizImpl;\nimport com.xxl.job.core.handler.IJobHandler;\nimport com.xxl.job.core.handler.annotation.JobHandler;\nimport com.xxl.job.core.log.XxlJobFileAppender;\nimport com.xxl.job.core.rpc.netcom.NetComClientProxy;\nimport com.xxl.job.core.rpc.netcom.NetComServerFactory;\nimport com.xxl.job.core.thread.JobLogFileCleanThread;\nimport com.xxl.job.core.thread.JobThread;\nimport com.xxl.job.core.util.NetUtil;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.BeansException;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.ApplicationContextAware;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\n\n/**\n * Created by xuxueli on 2016/3/2 21:14.\n */\npublic class XxlJobExecutor implements ApplicationContextAware {\n    private static final Logger logger = LoggerFactory.getLogger(XxlJobExecutor.class);\n\n    // ---------------------- param ----------------------\n    private String adminAddresses;\n    private String appName;\n    private String ip;\n    private int port;\n    private String accessToken;\n    private String logPath;\n    private int logRetentionDays;\n\n    public void setAdminAddresses(String adminAddresses) {\n        this.adminAddresses = adminAddresses;\n    }\n    public void setAppName(String appName) {\n        this.appName = appName;\n    }\n    public void setIp(String ip) {\n        this.ip = ip;\n    }\n    public void setPort(int port) {\n        this.port = port;\n    }\n    public void setAccessToken(String accessToken) {\n        this.accessToken = accessToken;\n    }\n    public void setLogPath(String logPath) {\n        this.logPath = logPath;\n    }\n    public void setLogRetentionDays(int logRetentionDays) {\n        this.logRetentionDays = logRetentionDays;\n    }\n\n    // ---------------------- applicationContext ----------------------\n    private static ApplicationContext applicationContext;\n    @Override\n    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {\n        this.applicationContext = applicationContext;\n    }\n    public static ApplicationContext getApplicationContext() {\n        return applicationContext;\n    }\n\n\n    // ---------------------- start + stop ----------------------\n    public void start() throws Exception {\n        // init admin-client\n        initAdminBizList(adminAddresses, accessToken);\n\n        // init executor-jobHandlerRepository\n        initJobHandlerRepository(applicationContext);\n\n        // init logpath\n        XxlJobFileAppender.initLogPath(logPath);\n\n        // init executor-server\n        initExecutorServer(port, ip, appName, accessToken);\n\n        // init JobLogFileCleanThread\n        JobLogFileCleanThread.getInstance().start(logRetentionDays);\n    }\n    public void destroy(){\n        // destory JobThreadRepository\n        if (JobThreadRepository.size() > 0) {\n            for (Map.Entry<Integer, JobThread> item: JobThreadRepository.entrySet()) {\n                removeJobThread(item.getKey(), \"Web容器销毁终止\");\n            }\n            JobThreadRepository.clear();\n        }\n\n        // destory executor-server\n        stopExecutorServer();\n\n        // destory JobLogFileCleanThread\n        JobLogFileCleanThread.getInstance().toStop();\n    }\n\n\n    // ---------------------- admin-client ----------------------\n    private static List<AdminBiz> adminBizList;\n    private static void initAdminBizList(String adminAddresses, String accessToken) throws Exception {\n        if (adminAddresses!=null && adminAddresses.trim().length()>0) {\n            for (String address: adminAddresses.trim().split(\",\")) {\n                if (address!=null && address.trim().length()>0) {\n                    String addressUrl = address.concat(AdminBiz.MAPPING);\n                    AdminBiz adminBiz = (AdminBiz) new NetComClientProxy(AdminBiz.class, addressUrl, accessToken).getObject();\n                    if (adminBizList == null) {\n                        adminBizList = new ArrayList<AdminBiz>();\n                    }\n                    adminBizList.add(adminBiz);\n                }\n            }\n        }\n    }\n    public static List<AdminBiz> getAdminBizList(){\n        return adminBizList;\n    }\n\n\n    // ---------------------- executor-server(jetty) ----------------------\n    private NetComServerFactory serverFactory = new NetComServerFactory();\n    private void initExecutorServer(int port, String ip, String appName, String accessToken) throws Exception {\n        // valid param\n        port = port>0?port: NetUtil.findAvailablePort(9999);\n\n        // start server\n        NetComServerFactory.putService(ExecutorBiz.class, new ExecutorBizImpl());   // rpc-service, base on jetty\n        NetComServerFactory.setAccessToken(accessToken);\n        serverFactory.start(port, ip, appName); // jetty + registry\n    }\n    private void stopExecutorServer() {\n        serverFactory.destroy();    // jetty + registry + callback\n    }\n\n\n    // ---------------------- job handler repository ----------------------\n    private static ConcurrentHashMap<String, IJobHandler> jobHandlerRepository = new ConcurrentHashMap<String, IJobHandler>();\n    public static IJobHandler registJobHandler(String name, IJobHandler jobHandler){\n        logger.info(\">>>>>>>>>>> xxl-job register jobhandler success, name:{}, jobHandler:{}\", name, jobHandler);\n        return jobHandlerRepository.put(name, jobHandler);\n    }\n    public static IJobHandler loadJobHandler(String name){\n        return jobHandlerRepository.get(name);\n    }\n    private static void initJobHandlerRepository(ApplicationContext applicationContext){\n        if (applicationContext == null) {\n            return;\n        }\n\n        // init job handler action\n        Map<String, Object> serviceBeanMap = applicationContext.getBeansWithAnnotation(JobHandler.class);\n\n        if (serviceBeanMap!=null && serviceBeanMap.size()>0) {\n            for (Object serviceBean : serviceBeanMap.values()) {\n                if (serviceBean instanceof IJobHandler){\n                    String name = serviceBean.getClass().getAnnotation(JobHandler.class).value();\n                    IJobHandler handler = (IJobHandler) serviceBean;\n                    if (loadJobHandler(name) != null) {\n                        throw new RuntimeException(\"xxl-job jobhandler naming conflicts.\");\n                    }\n                    registJobHandler(name, handler);\n                }\n            }\n        }\n    }\n\n\n    // ---------------------- job thread repository ----------------------\n    private static ConcurrentHashMap<Integer, JobThread> JobThreadRepository = new ConcurrentHashMap<Integer, JobThread>();\n    public static JobThread registJobThread(int jobId, IJobHandler handler, String removeOldReason){\n        JobThread newJobThread = new JobThread(jobId, handler);\n        newJobThread.start();\n        logger.info(\">>>>>>>>>>> xxl-job regist JobThread success, jobId:{}, handler:{}\", new Object[]{jobId, handler});\n\n        JobThread oldJobThread = JobThreadRepository.put(jobId, newJobThread);\t// putIfAbsent | oh my god, map's put method return the old value!!!\n        if (oldJobThread != null) {\n            oldJobThread.toStop(removeOldReason);\n            oldJobThread.interrupt();\n        }\n\n        return newJobThread;\n    }\n    public static void removeJobThread(int jobId, String removeOldReason){\n        JobThread oldJobThread = JobThreadRepository.remove(jobId);\n        if (oldJobThread != null) {\n            oldJobThread.toStop(removeOldReason);\n            oldJobThread.interrupt();\n        }\n    }\n    public static JobThread loadJobThread(int jobId){\n        JobThread jobThread = JobThreadRepository.get(jobId);\n        return jobThread;\n    }\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-core/src/main/java/com/xxl/job/core/glue/GlueFactory.java",
    "content": "package com.xxl.job.core.glue;\n\nimport com.xxl.job.core.executor.XxlJobExecutor;\nimport com.xxl.job.core.handler.IJobHandler;\nimport groovy.lang.GroovyClassLoader;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Qualifier;\nimport org.springframework.core.annotation.AnnotationUtils;\n\nimport javax.annotation.Resource;\nimport java.lang.reflect.Field;\nimport java.lang.reflect.Modifier;\n\n/**\n * glue factory, product class/object by name\n * @author xuxueli 2016-1-2 20:02:27\n */\npublic class GlueFactory {\n\tprivate static Logger logger = LoggerFactory.getLogger(GlueFactory.class);\n\t\n\t/**\n\t * groovy class loader\n\t */\n\tprivate GroovyClassLoader groovyClassLoader = new GroovyClassLoader();\n\n\t// ----------------------------- spring support -----------------------------\n\tprivate static GlueFactory glueFactory = new GlueFactory();\n\tpublic static GlueFactory getInstance(){\n\t\treturn glueFactory;\n\t}\n\n\t/**\n\t * inject action of spring\n\t * @param instance\n\t */\n\tprivate void injectService(Object instance){\n\t\tif (instance==null) {\n\t\t\treturn;\n\t\t}\n\t    \n\t\tField[] fields = instance.getClass().getDeclaredFields();\n\t\tfor (Field field : fields) {\n\t\t\tif (Modifier.isStatic(field.getModifiers())) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t\n\t\t\tObject fieldBean = null;\n\t\t\t// with bean-id, bean could be found by both @Resource and @Autowired, or bean could only be found by @Autowired\n\t\t\tif (AnnotationUtils.getAnnotation(field, Resource.class) != null) {\n\t\t\t\ttry {\n\t\t\t\t\tResource resource = AnnotationUtils.getAnnotation(field, Resource.class);\n\t\t\t\t\tif (resource.name()!=null && resource.name().length()>0){\n\t\t\t\t\t\tfieldBean = XxlJobExecutor.getApplicationContext().getBean(resource.name());\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfieldBean = XxlJobExecutor.getApplicationContext().getBean(field.getName());\n\t\t\t\t\t}\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t}\n\t\t\t\tif (fieldBean==null ) {\n\t\t\t\t\tfieldBean = XxlJobExecutor.getApplicationContext().getBean(field.getType());\n\t\t\t\t}\n\t\t\t} else if (AnnotationUtils.getAnnotation(field, Autowired.class) != null) {\n\t\t\t\tQualifier qualifier = AnnotationUtils.getAnnotation(field, Qualifier.class);\n\t\t\t\tif (qualifier!=null && qualifier.value()!=null && qualifier.value().length()>0) {\n\t\t\t\t\tfieldBean = XxlJobExecutor.getApplicationContext().getBean(qualifier.value());\n\t\t\t\t} else {\n\t\t\t\t\tfieldBean = XxlJobExecutor.getApplicationContext().getBean(field.getType());\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif (fieldBean!=null) {\n\t\t\t\tfield.setAccessible(true);\n\t\t\t\ttry {\n\t\t\t\t\tfield.set(instance, fieldBean);\n\t\t\t\t} catch (IllegalArgumentException e) {\n\t\t\t\t\tlogger.error(e.getMessage(), e);\n\t\t\t\t} catch (IllegalAccessException e) {\n\t\t\t\t\tlogger.error(e.getMessage(), e);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t\n\t// ----------------------------- load instance -----------------------------\n\t// load new instance, prototype\n\tpublic IJobHandler loadNewInstance(String codeSource) throws Exception{\n\t\tif (codeSource!=null && codeSource.trim().length()>0) {\n\t\t\tClass<?> clazz = groovyClassLoader.parseClass(codeSource);\n\t\t\tif (clazz != null) {\n\t\t\t\tObject instance = clazz.newInstance();\n\t\t\t\tif (instance!=null) {\n\t\t\t\t\tif (instance instanceof IJobHandler) {\n\t\t\t\t\t\tthis.injectService(instance);\n\t\t\t\t\t\treturn (IJobHandler) instance;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthrow new IllegalArgumentException(\">>>>>>>>>>> xxl-glue, loadNewInstance error, \"\n\t\t\t\t\t\t\t\t+ \"cannot convert from instance[\"+ instance.getClass() +\"] to IJobHandler\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tthrow new IllegalArgumentException(\">>>>>>>>>>> xxl-glue, loadNewInstance error, instance is null\");\n\t}\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-core/src/main/java/com/xxl/job/core/glue/GlueTypeEnum.java",
    "content": "package com.xxl.job.core.glue;\n\n/**\n * Created by xuxueli on 17/4/26.\n */\npublic enum GlueTypeEnum {\n\n    BEAN(\"BEAN\", false, null, null),\n    GLUE_GROOVY(\"GLUE(Java)\", false, null, null),\n    GLUE_SHELL(\"GLUE(Shell)\", true, \"bash\", \".sh\"),\n    GLUE_PYTHON(\"GLUE(Python)\", true, \"python\", \".py\"),\n    GLUE_NODEJS(\"GLUE(Nodejs)\", true, \"node\", \".js\");\n\n    private String desc;\n    private boolean isScript;\n    private String cmd;\n    private String suffix;\n\n    private GlueTypeEnum(String desc, boolean isScript, String cmd, String suffix) {\n        this.desc = desc;\n        this.isScript = isScript;\n        this.cmd = cmd;\n        this.suffix = suffix;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public boolean isScript() {\n        return isScript;\n    }\n\n    public String getCmd() {\n        return cmd;\n    }\n\n    public String getSuffix() {\n        return suffix;\n    }\n\n    public static GlueTypeEnum match(String name){\n        for (GlueTypeEnum item: GlueTypeEnum.values()) {\n            if (item.name().equals(name)) {\n                return item;\n            }\n        }\n        return null;\n    }\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-core/src/main/java/com/xxl/job/core/handler/IJobHandler.java",
    "content": "package com.xxl.job.core.handler;\n\nimport com.xxl.job.core.biz.model.ReturnT;\n\n/**\n * job handler\n *\n * @author xuxueli 2015-12-19 19:06:38\n */\npublic abstract class IJobHandler {\n\n\n\t/** success */\n\tpublic static final ReturnT<String> SUCCESS = new ReturnT<String>(200, null);\n\t/** fail */\n\tpublic static final ReturnT<String> FAIL = new ReturnT<String>(500, null);\n\t/** fail retry */\n\tpublic static final ReturnT<String> FAIL_RETRY = new ReturnT<String>(501, null);\n\n\n\t/**\n\t * execute handler, invoked when executor receives a scheduling request\n\t *\n\t * @param param\n\t * @return\n\t * @throws Exception\n\t */\n\tpublic abstract ReturnT<String> execute(String param) throws Exception;\n\n\n\t/**\n\t * init handler, invoked when JobThread init\n\t */\n\tpublic void init() {\n\t\t// TODO\n\t}\n\n\n\t/**\n\t * destroy handler, invoked when JobThread destroy\n\t */\n\tpublic void destroy() {\n\t\t// TODO\n\t}\n\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-core/src/main/java/com/xxl/job/core/handler/annotation/JobHandler.java",
    "content": "package com.xxl.job.core.handler.annotation;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Inherited;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * annotation for job handler\n * @author 2016-5-17 21:06:49\n */\n@Target({ElementType.TYPE})\n@Retention(RetentionPolicy.RUNTIME)\n@Inherited\npublic @interface JobHandler {\n\n    String value() default \"\";\n    \n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-core/src/main/java/com/xxl/job/core/handler/impl/GlueJobHandler.java",
    "content": "package com.xxl.job.core.handler.impl;\n\nimport com.xxl.job.core.biz.model.ReturnT;\nimport com.xxl.job.core.handler.IJobHandler;\nimport com.xxl.job.core.log.XxlJobLogger;\n\n/**\n * glue job handler\n * @author xuxueli 2016-5-19 21:05:45\n */\npublic class GlueJobHandler extends IJobHandler {\n\n\tprivate long glueUpdatetime;\n\tprivate IJobHandler jobHandler;\n\tpublic GlueJobHandler(IJobHandler jobHandler, long glueUpdatetime) {\n\t\tthis.jobHandler = jobHandler;\n\t\tthis.glueUpdatetime = glueUpdatetime;\n\t}\n\tpublic long getGlueUpdatetime() {\n\t\treturn glueUpdatetime;\n\t}\n\n\t@Override\n\tpublic ReturnT<String> execute(String param) throws Exception {\n\t\tXxlJobLogger.log(\"----------- glue.version:\"+ glueUpdatetime +\" -----------\");\n\t\treturn jobHandler.execute(param);\n\t}\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-core/src/main/java/com/xxl/job/core/handler/impl/ScriptJobHandler.java",
    "content": "package com.xxl.job.core.handler.impl;\n\nimport com.xxl.job.core.biz.model.ReturnT;\nimport com.xxl.job.core.glue.GlueTypeEnum;\nimport com.xxl.job.core.handler.IJobHandler;\nimport com.xxl.job.core.log.XxlJobFileAppender;\nimport com.xxl.job.core.log.XxlJobLogger;\nimport com.xxl.job.core.util.ScriptUtil;\nimport com.xxl.job.core.util.ShardingUtil;\n\n/**\n * Created by xuxueli on 17/4/27.\n */\npublic class ScriptJobHandler extends IJobHandler {\n\n    private int jobId;\n    private long glueUpdatetime;\n    private String gluesource;\n    private GlueTypeEnum glueType;\n\n    public ScriptJobHandler(int jobId, long glueUpdatetime, String gluesource, GlueTypeEnum glueType){\n        this.jobId = jobId;\n        this.glueUpdatetime = glueUpdatetime;\n        this.gluesource = gluesource;\n        this.glueType = glueType;\n    }\n\n    public long getGlueUpdatetime() {\n        return glueUpdatetime;\n    }\n\n    @Override\n    public ReturnT<String> execute(String param) throws Exception {\n\n        if (!glueType.isScript()) {\n            return new ReturnT<String>(IJobHandler.FAIL.getCode(), \"glueType[\"+ glueType +\"] invalid.\");\n        }\n\n        // cmd\n        String cmd = glueType.getCmd();\n\n        // make script file\n        String scriptFileName = XxlJobFileAppender.getGlueSrcPath()\n                .concat(\"/\")\n                .concat(String.valueOf(jobId))\n                .concat(\"_\")\n                .concat(String.valueOf(glueUpdatetime))\n                .concat(glueType.getSuffix());\n        ScriptUtil.markScriptFile(scriptFileName, gluesource);\n\n        // log file\n        String logFileName = XxlJobFileAppender.contextHolder.get();\n\n        // script params：0=param、1=分片序号、2=分片总数\n        ShardingUtil.ShardingVO shardingVO = ShardingUtil.getShardingVo();\n        String[] scriptParams = new String[3];\n        scriptParams[0] = param;\n        scriptParams[1] = String.valueOf(shardingVO.getIndex());\n        scriptParams[2] = String.valueOf(shardingVO.getTotal());\n\n        // invoke\n        XxlJobLogger.log(\"----------- script file:\"+ scriptFileName +\" -----------\");\n        int exitValue = ScriptUtil.execToFile(cmd, scriptFileName, logFileName, scriptParams);\n        ReturnT<String> result = (exitValue==0)?IJobHandler.SUCCESS:new ReturnT<String>(IJobHandler.FAIL.getCode(), \"script exit value(\"+exitValue+\") is failed\");\n        return result;\n    }\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-core/src/main/java/com/xxl/job/core/log/XxlJobFileAppender.java",
    "content": "package com.xxl.job.core.log;\n\nimport com.xxl.job.core.biz.model.LogResult;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.io.*;\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\n\n/**\n * store trigger log in each log-file\n * @author xuxueli 2016-3-12 19:25:12\n */\npublic class XxlJobFileAppender {\n\tprivate static Logger logger = LoggerFactory.getLogger(XxlJobFileAppender.class);\n\t\n\t// for JobThread (support log for child thread of job handler)\n\t//public static ThreadLocal<String> contextHolder = new ThreadLocal<String>();\n\tpublic static final InheritableThreadLocal<String> contextHolder = new InheritableThreadLocal<String>();\n\n\n\t/**\n\t * log base path\n\t *\n\t * strut like:\n\t * \t---/\n\t * \t---/gluesource/\n\t * \t---/gluesource/10_1514171108000.js\n\t * \t---/gluesource/10_1514171108000.js\n\t * \t---/2017-12-25/\n\t * \t---/2017-12-25/639.log\n\t * \t---/2017-12-25/821.log\n\t *\n\t */\n\tprivate static String logBasePath = \"/data/applogs/xxl-job/jobhandler\";\n\tprivate static String glueSrcPath = logBasePath.concat(\"/gluesource\");\n\tpublic static void initLogPath(String logPath){\n\t\t// init\n\t\tif (logPath!=null && logPath.trim().length()>0) {\n\t\t\tlogBasePath = logPath;\n\t\t}\n\t\t// mk base dir\n\t\tFile logPathDir = new File(logBasePath);\n\t\tif (!logPathDir.exists()) {\n\t\t\tlogPathDir.mkdirs();\n\t\t}\n\t\tlogBasePath = logPathDir.getPath();\n\n\t\t// mk glue dir\n\t\tFile glueBaseDir = new File(logPathDir, \"gluesource\");\n\t\tif (!glueBaseDir.exists()) {\n\t\t\tglueBaseDir.mkdirs();\n\t\t}\n\t\tglueSrcPath = glueBaseDir.getPath();\n\t}\n\tpublic static String getLogPath() {\n\t\treturn logBasePath;\n\t}\n\tpublic static String getGlueSrcPath() {\n\t\treturn glueSrcPath;\n\t}\n\n\t/**\n\t * log filename, like \"logPath/yyyy-MM-dd/9999.log\"\n\t *\n\t * @param triggerDate\n\t * @param logId\n\t * @return\n\t */\n\tpublic static String makeLogFileName(Date triggerDate, int logId) {\n\n\t\t// filePath/yyyy-MM-dd\n\t\tSimpleDateFormat sdf = new SimpleDateFormat(\"yyyy-MM-dd\");\t// avoid concurrent problem, can not be static\n\t\tFile logFilePath = new File(getLogPath(), sdf.format(triggerDate));\n\t\tif (!logFilePath.exists()) {\n\t\t\tlogFilePath.mkdir();\n\t\t}\n\n\t\t// filePath/yyyy-MM-dd/9999.log\n\t\tString logFileName = logFilePath.getPath()\n\t\t\t\t.concat(\"/\")\n\t\t\t\t.concat(String.valueOf(logId))\n\t\t\t\t.concat(\".log\");\n\t\treturn logFileName;\n\t}\n\n\t/**\n\t * append log\n\t *\n\t * @param logFileName\n\t * @param appendLog\n\t */\n\tpublic static void appendLog(String logFileName, String appendLog) {\n\n\t\t// log file\n\t\tif (logFileName==null || logFileName.trim().length()==0) {\n\t\t\treturn;\n\t\t}\n\t\tFile logFile = new File(logFileName);\n\n\t\tif (!logFile.exists()) {\n\t\t\ttry {\n\t\t\t\tlogFile.createNewFile();\n\t\t\t} catch (IOException e) {\n\t\t\t\tlogger.error(e.getMessage(), e);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// log\n\t\tif (appendLog == null) {\n\t\t\tappendLog = \"\";\n\t\t}\n\t\tappendLog += \"\\r\\n\";\n\t\t\n\t\t// append file content\n\t\ttry {\n\t\t\tFileOutputStream fos = null;\n\t\t\ttry {\n\t\t\t\tfos = new FileOutputStream(logFile, true);\n\t\t\t\tfos.write(appendLog.getBytes(\"utf-8\"));\n\t\t\t\tfos.flush();\n\t\t\t} finally {\n\t\t\t\tif (fos != null) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfos.close();\n\t\t\t\t\t} catch (IOException e) {\n\t\t\t\t\t\tlogger.error(e.getMessage(), e);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} \n\t\t} catch (Exception e) {\n\t\t\tlogger.error(e.getMessage(), e);\n\t\t}\n\t\t\n\t}\n\n\t/**\n\t * support read log-file\n\t *\n\t * @param logFileName\n\t * @return log content\n\t */\n\tpublic static LogResult readLog(String logFileName, int fromLineNum){\n\n\t\t// valid log file\n\t\tif (logFileName==null || logFileName.trim().length()==0) {\n            return new LogResult(fromLineNum, 0, \"readLog fail, logFile not found\", true);\n\t\t}\n\t\tFile logFile = new File(logFileName);\n\n\t\tif (!logFile.exists()) {\n            return new LogResult(fromLineNum, 0, \"readLog fail, logFile not exists\", true);\n\t\t}\n\n\t\t// read file\n\t\tStringBuffer logContentBuffer = new StringBuffer();\n\t\tint toLineNum = 0;\n\t\tLineNumberReader reader = null;\n\t\ttry {\n\t\t\t//reader = new LineNumberReader(new FileReader(logFile));\n\t\t\treader = new LineNumberReader(new InputStreamReader(new FileInputStream(logFile), \"utf-8\"));\n\t\t\tString line = null;\n\n\t\t\twhile ((line = reader.readLine())!=null) {\n\t\t\t\ttoLineNum = reader.getLineNumber();\t\t// [from, to], start as 1\n\t\t\t\tif (toLineNum >= fromLineNum) {\n\t\t\t\t\tlogContentBuffer.append(line).append(\"\\n\");\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (IOException e) {\n\t\t\tlogger.error(e.getMessage(), e);\n\t\t} finally {\n\t\t\tif (reader != null) {\n\t\t\t\ttry {\n\t\t\t\t\treader.close();\n\t\t\t\t} catch (IOException e) {\n\t\t\t\t\tlogger.error(e.getMessage(), e);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// result\n\t\tLogResult logResult = new LogResult(fromLineNum, toLineNum, logContentBuffer.toString(), false);\n\t\treturn logResult;\n\n\t\t/*\n        // it will return the number of characters actually skipped\n        reader.skip(Long.MAX_VALUE);\n        int maxLineNum = reader.getLineNumber();\n        maxLineNum++;\t// 最大行号\n        */\n\t}\n\n\t/**\n\t * read log data\n\t * @param logFile\n\t * @return log line content\n\t */\n\tpublic static String readLines(File logFile){\n\t\tBufferedReader reader = null;\n\t\ttry {\n\t\t\treader = new BufferedReader(new InputStreamReader(new FileInputStream(logFile), \"utf-8\"));\n\t\t\tif (reader != null) {\n\t\t\t\tStringBuilder sb = new StringBuilder();\n\t\t\t\tString line = null;\n\t\t\t\twhile ((line = reader.readLine()) != null) {\n\t\t\t\t\tsb.append(line).append(\"\\n\");\n\t\t\t\t}\n\t\t\t\treturn sb.toString();\n\t\t\t}\n\t\t} catch (IOException e) {\n\t\t\tlogger.error(e.getMessage(), e);\n\t\t} finally {\n\t\t\tif (reader != null) {\n\t\t\t\ttry {\n\t\t\t\t\treader.close();\n\t\t\t\t} catch (IOException e) {\n\t\t\t\t\tlogger.error(e.getMessage(), e);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-core/src/main/java/com/xxl/job/core/log/XxlJobLogger.java",
    "content": "package com.xxl.job.core.log;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.io.PrintWriter;\nimport java.io.StringWriter;\nimport java.text.MessageFormat;\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\n\n/**\n * Created by xuxueli on 17/4/28.\n */\npublic class XxlJobLogger {\n    private static Logger logger = LoggerFactory.getLogger(\"xxl-job logger\");\n    private static SimpleDateFormat xxlJobLoggerFormat = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");   // TODO，concurrent issue\n\n    /**\n     * append log\n     *\n     * @param callInfo\n     * @param appendLog\n     */\n    private static void logDetail(StackTraceElement callInfo, String appendLog) {\n\n\n        /*// \"yyyy-MM-dd HH:mm:ss [ClassName]-[MethodName]-[LineNumber]-[ThreadName] log\";\n        StackTraceElement[] stackTraceElements = new Throwable().getStackTrace();\n        StackTraceElement callInfo = stackTraceElements[1];*/\n\n        StringBuffer stringBuffer = new StringBuffer();\n        stringBuffer.append(xxlJobLoggerFormat.format(new Date())).append(\" \")\n            .append(\"[\"+ callInfo.getClassName() + \"#\" + callInfo.getMethodName() +\"]\").append(\"-\")\n            .append(\"[\"+ callInfo.getLineNumber() +\"]\").append(\"-\")\n            .append(\"[\"+ Thread.currentThread().getName() +\"]\").append(\" \")\n            .append(appendLog!=null?appendLog:\"\");\n        String formatAppendLog = stringBuffer.toString();\n\n        // appendlog\n        String logFileName = XxlJobFileAppender.contextHolder.get();\n        if (logFileName!=null && logFileName.trim().length()>0) {\n            XxlJobFileAppender.appendLog(logFileName, formatAppendLog);\n        } else {\n            logger.info(\">>>>>>>>>>> {}\", formatAppendLog);\n        }\n    }\n\n    /**\n     * append log with pattern\n     *\n     * @param appendLogPattern  like \"aaa {0} bbb {1} ccc\"\n     * @param appendLogArguments    like \"111, true\"\n     */\n    public static void log(String appendLogPattern, Object ... appendLogArguments) {\n\n        String appendLog = appendLogPattern;\n        if (appendLogArguments!=null && appendLogArguments.length>0) {\n            appendLog = MessageFormat.format(appendLogPattern, appendLogArguments);\n        }\n\n        StackTraceElement callInfo = new Throwable().getStackTrace()[1];\n        logDetail(callInfo, appendLog);\n    }\n\n    /**\n     * append exception stack\n     *\n     * @param e\n     */\n    public static void log(Throwable e) {\n\n        StringWriter stringWriter = new StringWriter();\n        e.printStackTrace(new PrintWriter(stringWriter));\n        String appendLog = stringWriter.toString();\n\n        StackTraceElement callInfo = new Throwable().getStackTrace()[1];\n        logDetail(callInfo, appendLog);\n    }\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-core/src/main/java/com/xxl/job/core/rpc/codec/RpcRequest.java",
    "content": "package com.xxl.job.core.rpc.codec;\n\nimport java.io.Serializable;\nimport java.util.Arrays;\n\n/**\n * request\n * @author xuxueli 2015-10-29 19:39:12\n */\npublic class RpcRequest implements Serializable{\n\tprivate static final long serialVersionUID = 1L;\n\t\n\tprivate String serverAddress;\n\tprivate long createMillisTime;\n\tprivate String accessToken;\n\n    private String className;\n    private String methodName;\n    private Class<?>[] parameterTypes;\n    private Object[] parameters;\n\n\n\tpublic String getServerAddress() {\n\t\treturn serverAddress;\n\t}\n\n\tpublic void setServerAddress(String serverAddress) {\n\t\tthis.serverAddress = serverAddress;\n\t}\n\n\tpublic long getCreateMillisTime() {\n\t\treturn createMillisTime;\n\t}\n\n\tpublic void setCreateMillisTime(long createMillisTime) {\n\t\tthis.createMillisTime = createMillisTime;\n\t}\n\n\tpublic String getAccessToken() {\n\t\treturn accessToken;\n\t}\n\n\tpublic void setAccessToken(String accessToken) {\n\t\tthis.accessToken = accessToken;\n\t}\n\n\tpublic String getClassName() {\n\t\treturn className;\n\t}\n\n\tpublic void setClassName(String className) {\n\t\tthis.className = className;\n\t}\n\n\tpublic String getMethodName() {\n\t\treturn methodName;\n\t}\n\n\tpublic void setMethodName(String methodName) {\n\t\tthis.methodName = methodName;\n\t}\n\n\tpublic Class<?>[] getParameterTypes() {\n\t\treturn parameterTypes;\n\t}\n\n\tpublic void setParameterTypes(Class<?>[] parameterTypes) {\n\t\tthis.parameterTypes = parameterTypes;\n\t}\n\n\tpublic Object[] getParameters() {\n\t\treturn parameters;\n\t}\n\n\tpublic void setParameters(Object[] parameters) {\n\t\tthis.parameters = parameters;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"RpcRequest{\" +\n\t\t\t\t\"serverAddress='\" + serverAddress + '\\'' +\n\t\t\t\t\", createMillisTime=\" + createMillisTime +\n\t\t\t\t\", accessToken='\" + accessToken + '\\'' +\n\t\t\t\t\", className='\" + className + '\\'' +\n\t\t\t\t\", methodName='\" + methodName + '\\'' +\n\t\t\t\t\", parameterTypes=\" + Arrays.toString(parameterTypes) +\n\t\t\t\t\", parameters=\" + Arrays.toString(parameters) +\n\t\t\t\t'}';\n\t}\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-core/src/main/java/com/xxl/job/core/rpc/codec/RpcResponse.java",
    "content": "package com.xxl.job.core.rpc.codec;\n\nimport java.io.Serializable;\n\n/**\n * response\n * @author xuxueli 2015-10-29 19:39:54\n */\npublic class RpcResponse implements Serializable{\n\tprivate static final long serialVersionUID = 1L;\n\t\n    private String error;\n    private Object result;\n\n    public boolean isError() {\n        return error != null;\n    }\n\n    public String getError() {\n        return error;\n    }\n\n    public void setError(String error) {\n        this.error = error;\n    }\n\n    public Object getResult() {\n        return result;\n    }\n\n    public void setResult(Object result) {\n        this.result = result;\n    }\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"NettyResponse [error=\" + error\n\t\t\t\t+ \", result=\" + result + \"]\";\n\t}\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-core/src/main/java/com/xxl/job/core/rpc/netcom/NetComClientProxy.java",
    "content": "package com.xxl.job.core.rpc.netcom;\n\nimport com.xxl.job.core.rpc.codec.RpcRequest;\nimport com.xxl.job.core.rpc.codec.RpcResponse;\nimport com.xxl.job.core.rpc.netcom.jetty.client.JettyClient;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.FactoryBean;\n\nimport java.lang.reflect.InvocationHandler;\nimport java.lang.reflect.Method;\nimport java.lang.reflect.Proxy;\n\n/**\n * rpc proxy\n * @author xuxueli 2015-10-29 20:18:32\n */\npublic class NetComClientProxy implements FactoryBean<Object> {\n\tprivate static final Logger logger = LoggerFactory.getLogger(NetComClientProxy.class);\n\n\t// ---------------------- config ----------------------\n\tprivate Class<?> iface;\n\tprivate String serverAddress;\n\tprivate String accessToken;\n\tprivate JettyClient client = new JettyClient();\n\tpublic NetComClientProxy(Class<?> iface, String serverAddress, String accessToken) {\n\t\tthis.iface = iface;\n\t\tthis.serverAddress = serverAddress;\n\t\tthis.accessToken = accessToken;\n\t}\n\n\t@Override\n\tpublic Object getObject() throws Exception {\n\t\treturn Proxy.newProxyInstance(Thread.currentThread()\n\t\t\t\t.getContextClassLoader(), new Class[] { iface },\n\t\t\t\tnew InvocationHandler() {\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {\n\n\t\t\t\t\t\t// filter method like \"Object.toString()\"\n\t\t\t\t\t\tif (Object.class.getName().equals(method.getDeclaringClass().getName())) {\n\t\t\t\t\t\t\tlogger.error(\">>>>>>>>>>> xxl-rpc proxy class-method not support [{}.{}]\", method.getDeclaringClass().getName(), method.getName());\n\t\t\t\t\t\t\tthrow new RuntimeException(\"xxl-rpc proxy class-method not support\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\t// request\n\t\t\t\t\t\tRpcRequest request = new RpcRequest();\n\t                    request.setServerAddress(serverAddress);\n\t                    request.setCreateMillisTime(System.currentTimeMillis());\n\t                    request.setAccessToken(accessToken);\n\t                    request.setClassName(method.getDeclaringClass().getName());\n\t                    request.setMethodName(method.getName());\n\t                    request.setParameterTypes(method.getParameterTypes());\n\t                    request.setParameters(args);\n\n\t                    // send\n\t                    RpcResponse response = client.send(request);\n\t                    \n\t                    // valid response\n\t\t\t\t\t\tif (response == null) {\n\t\t\t\t\t\t\tthrow new Exception(\"Network request fail, response not found.\");\n\t\t\t\t\t\t}\n\t                    if (response.isError()) {\n\t                        throw new RuntimeException(response.getError());\n\t                    } else {\n\t                        return response.getResult();\n\t                    }\n\t                   \n\t\t\t\t\t}\n\t\t\t\t});\n\t}\n\t@Override\n\tpublic Class<?> getObjectType() {\n\t\treturn iface;\n\t}\n\t@Override\n\tpublic boolean isSingleton() {\n\t\treturn false;\n\t}\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-core/src/main/java/com/xxl/job/core/rpc/netcom/NetComServerFactory.java",
    "content": "package com.xxl.job.core.rpc.netcom;\n\nimport com.xxl.job.core.biz.model.ReturnT;\nimport com.xxl.job.core.rpc.codec.RpcRequest;\nimport com.xxl.job.core.rpc.codec.RpcResponse;\nimport com.xxl.job.core.rpc.netcom.jetty.server.JettyServer;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.cglib.reflect.FastClass;\nimport org.springframework.cglib.reflect.FastMethod;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * netcom init\n * @author xuxueli 2015-10-31 22:54:27\n */\npublic class NetComServerFactory  {\n\tprivate static final Logger logger = LoggerFactory.getLogger(NetComServerFactory.class);\n\n\t// ---------------------- server start ----------------------\n\tJettyServer server = new JettyServer();\n\tpublic void start(int port, String ip, String appName) throws Exception {\n\t\tserver.start(port, ip, appName);\n\t}\n\n\t// ---------------------- server destroy ----------------------\n\tpublic void destroy(){\n\t\tserver.destroy();\n\t}\n\n\t// ---------------------- server instance ----------------------\n\t/**\n\t * init local rpc service map\n\t */\n\tprivate static Map<String, Object> serviceMap = new HashMap<String, Object>();\n\tprivate static String accessToken;\n\tpublic static void putService(Class<?> iface, Object serviceBean){\n\t\tserviceMap.put(iface.getName(), serviceBean);\n\t}\n\tpublic static void setAccessToken(String accessToken) {\n\t\tNetComServerFactory.accessToken = accessToken;\n\t}\n\tpublic static RpcResponse invokeService(RpcRequest request, Object serviceBean) {\n\t\tif (serviceBean==null) {\n\t\t\tserviceBean = serviceMap.get(request.getClassName());\n\t\t}\n\t\tif (serviceBean == null) {\n\t\t\t// TODO\n\t\t}\n\n\t\tRpcResponse response = new RpcResponse();\n\n\t\tif (System.currentTimeMillis() - request.getCreateMillisTime() > 180000) {\n\t\t\tresponse.setResult(new ReturnT<String>(ReturnT.FAIL_CODE, \"The timestamp difference between admin and executor exceeds the limit.\"));\n\t\t\treturn response;\n\t\t}\n\t\tif (accessToken!=null && accessToken.trim().length()>0 && !accessToken.trim().equals(request.getAccessToken())) {\n\t\t\tresponse.setResult(new ReturnT<String>(ReturnT.FAIL_CODE, \"The access token[\" + request.getAccessToken() + \"] is wrong.\"));\n\t\t\treturn response;\n\t\t}\n\n\t\ttry {\n\t\t\tClass<?> serviceClass = serviceBean.getClass();\n\t\t\tString methodName = request.getMethodName();\n\t\t\tClass<?>[] parameterTypes = request.getParameterTypes();\n\t\t\tObject[] parameters = request.getParameters();\n\n\t\t\tFastClass serviceFastClass = FastClass.create(serviceClass);\n\t\t\tFastMethod serviceFastMethod = serviceFastClass.getMethod(methodName, parameterTypes);\n\n\t\t\tObject result = serviceFastMethod.invoke(serviceBean, parameters);\n\n\t\t\tresponse.setResult(result);\n\t\t} catch (Throwable t) {\n\t\t\tt.printStackTrace();\n\t\t\tresponse.setError(t.getMessage());\n\t\t}\n\n\t\treturn response;\n\t}\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-core/src/main/java/com/xxl/job/core/rpc/netcom/jetty/client/JettyClient.java",
    "content": "package com.xxl.job.core.rpc.netcom.jetty.client;\n\nimport com.xxl.job.core.rpc.codec.RpcRequest;\nimport com.xxl.job.core.rpc.codec.RpcResponse;\nimport com.xxl.job.core.rpc.serialize.HessianSerializer;\nimport com.xxl.job.core.util.HttpClientUtil;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * jetty client\n * @author xuxueli 2015-11-24 22:25:15\n */\npublic class JettyClient {\n\tprivate static Logger logger = LoggerFactory.getLogger(JettyClient.class);\n\n\tpublic RpcResponse send(RpcRequest request) throws Exception {\n\t\ttry {\n\t\t\t// serialize request\n\t\t\tbyte[] requestBytes = HessianSerializer.serialize(request);\n\n\t\t\t// reqURL\n\t\t\tString reqURL = request.getServerAddress();\n\t\t\tif (reqURL!=null && reqURL.toLowerCase().indexOf(\"http\")==-1) {\n\t\t\t\treqURL = \"http://\" + request.getServerAddress() + \"/\";\t// IP:PORT, need parse to url\n\t\t\t}\n\n\t\t\t// remote invoke\n\t\t\tbyte[] responseBytes = HttpClientUtil.postRequest(reqURL, requestBytes);\n\t\t\tif (responseBytes == null || responseBytes.length==0) {\n\t\t\t\tRpcResponse rpcResponse = new RpcResponse();\n\t\t\t\trpcResponse.setError(\"Network request fail, RpcResponse byte[] is null\");\n\t\t\t\treturn rpcResponse;\n            }\n\n            // deserialize response\n\t\t\tRpcResponse rpcResponse = (RpcResponse) HessianSerializer.deserialize(responseBytes, RpcResponse.class);\n\t\t\treturn rpcResponse;\n\t\t} catch (Exception e) {\n\t\t\tlogger.error(e.getMessage(), e);\n\n\t\t\tRpcResponse rpcResponse = new RpcResponse();\n\t\t\trpcResponse.setError(\"Network request error: \" + e.getMessage());\n\t\t\treturn rpcResponse;\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-core/src/main/java/com/xxl/job/core/rpc/netcom/jetty/server/JettyServer.java",
    "content": "package com.xxl.job.core.rpc.netcom.jetty.server;\n\nimport com.xxl.job.core.thread.ExecutorRegistryThread;\nimport com.xxl.job.core.thread.TriggerCallbackThread;\nimport org.eclipse.jetty.server.Connector;\nimport org.eclipse.jetty.server.Handler;\nimport org.eclipse.jetty.server.Server;\nimport org.eclipse.jetty.server.ServerConnector;\nimport org.eclipse.jetty.server.handler.HandlerCollection;\nimport org.eclipse.jetty.util.thread.ExecutorThreadPool;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * rpc jetty server\n * @author xuxueli 2015-11-19 22:29:03\n */\npublic class JettyServer {\n\tprivate static final Logger logger = LoggerFactory.getLogger(JettyServer.class);\n\n\tprivate Server server;\n\tprivate Thread thread;\n\tpublic void start(final int port, final String ip, final String appName) throws Exception {\n\t\tthread = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\n\t\t\t\t// The Server\n\t\t\t\tserver = new Server(new ExecutorThreadPool());  // 非阻塞\n\n\t\t\t\t// HTTP connector\n\t\t\t\tServerConnector connector = new ServerConnector(server);\n\t\t\t\tif (ip!=null && ip.trim().length()>0) {\n\t\t\t\t\tconnector.setHost(ip);\t// The network interface this connector binds to as an IP address or a hostname.  If null or 0.0.0.0, then bind to all interfaces.\n\t\t\t\t}\n\t\t\t\tconnector.setPort(port);\n\t\t\t\tserver.setConnectors(new Connector[]{connector});\n\n\t\t\t\t// Set a handler\n\t\t\t\tHandlerCollection handlerc =new HandlerCollection();\n\t\t\t\thandlerc.setHandlers(new Handler[]{new JettyServerHandler()});\n\t\t\t\tserver.setHandler(handlerc);\n\n\t\t\t\ttry {\n\t\t\t\t\t// Start server\n\t\t\t\t\tserver.start();\n\t\t\t\t\tlogger.info(\">>>>>>>>>>> xxl-job jetty server start success at port:{}.\", port);\n\n\t\t\t\t\t// Start Registry-Server\n\t\t\t\t\tExecutorRegistryThread.getInstance().start(port, ip, appName);\n\n\t\t\t\t\t// Start Callback-Server\n\t\t\t\t\tTriggerCallbackThread.getInstance().start();\n\n\t\t\t\t\tserver.join();\t// block until thread stopped\n\t\t\t\t\tlogger.info(\">>>>>>>>>>> xxl-rpc server join success, netcon={}, port={}\", JettyServer.class.getName(), port);\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\tlogger.error(e.getMessage(), e);\n\t\t\t\t} finally {\n\t\t\t\t\t//destroy();\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tthread.setDaemon(true);\t// daemon, service jvm, user thread leave >>> daemon leave >>> jvm leave\n\t\tthread.start();\n\t}\n\n\tpublic void destroy() {\n\n\t\t// destroy Registry-Server\n\t\tExecutorRegistryThread.getInstance().toStop();\n\n\t\t// destroy Callback-Server\n\t\tTriggerCallbackThread.getInstance().toStop();\n\n\t\t// destroy server\n\t\tif (server != null) {\n\t\t\ttry {\n\t\t\t\tserver.stop();\n\t\t\t\tserver.destroy();\n\t\t\t} catch (Exception e) {\n\t\t\t\tlogger.error(e.getMessage(), e);\n\t\t\t}\n\t\t}\n\t\tif (thread.isAlive()) {\n\t\t\tthread.interrupt();\n\t\t}\n\n\t\tlogger.info(\">>>>>>>>>>> xxl-rpc server destroy success, netcon={}\", JettyServer.class.getName());\n\t}\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-core/src/main/java/com/xxl/job/core/rpc/netcom/jetty/server/JettyServerHandler.java",
    "content": "package com.xxl.job.core.rpc.netcom.jetty.server;\n\nimport com.xxl.job.core.rpc.codec.RpcRequest;\nimport com.xxl.job.core.rpc.codec.RpcResponse;\nimport com.xxl.job.core.rpc.netcom.NetComServerFactory;\nimport com.xxl.job.core.rpc.serialize.HessianSerializer;\nimport com.xxl.job.core.util.HttpClientUtil;\nimport org.eclipse.jetty.server.Request;\nimport org.eclipse.jetty.server.handler.AbstractHandler;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport javax.servlet.ServletException;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport java.io.IOException;\nimport java.io.OutputStream;\n\n/**\n * jetty handler\n * @author xuxueli 2015-11-19 22:32:36\n */\npublic class JettyServerHandler extends AbstractHandler {\n\tprivate static Logger logger = LoggerFactory.getLogger(JettyServerHandler.class);\n\n\t@Override\n\tpublic void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {\n\t\t\n\t\t// invoke\n        RpcResponse rpcResponse = doInvoke(request);\n\n        // serialize response\n        byte[] responseBytes = HessianSerializer.serialize(rpcResponse);\n\t\t\n\t\tresponse.setContentType(\"text/html;charset=utf-8\");\n\t\tresponse.setStatus(HttpServletResponse.SC_OK);\n\t\tbaseRequest.setHandled(true);\n\t\t\n\t\tOutputStream out = response.getOutputStream();\n\t\tout.write(responseBytes);\n\t\tout.flush();\n\t\t\n\t}\n\n\tprivate RpcResponse doInvoke(HttpServletRequest request) {\n\t\ttry {\n\t\t\t// deserialize request\n\t\t\tbyte[] requestBytes = HttpClientUtil.readBytes(request);\n\t\t\tif (requestBytes == null || requestBytes.length==0) {\n\t\t\t\tRpcResponse rpcResponse = new RpcResponse();\n\t\t\t\trpcResponse.setError(\"RpcRequest byte[] is null\");\n\t\t\t\treturn rpcResponse;\n\t\t\t}\n\t\t\tRpcRequest rpcRequest = (RpcRequest) HessianSerializer.deserialize(requestBytes, RpcRequest.class);\n\n\t\t\t// invoke\n\t\t\tRpcResponse rpcResponse = NetComServerFactory.invokeService(rpcRequest, null);\n\t\t\treturn rpcResponse;\n\t\t} catch (Exception e) {\n\t\t\tlogger.error(e.getMessage(), e);\n\n\t\t\tRpcResponse rpcResponse = new RpcResponse();\n\t\t\trpcResponse.setError(\"Server-error:\" + e.getMessage());\n\t\t\treturn rpcResponse;\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-core/src/main/java/com/xxl/job/core/rpc/serialize/HessianSerializer.java",
    "content": "package com.xxl.job.core.rpc.serialize;\n\nimport com.caucho.hessian.io.HessianInput;\nimport com.caucho.hessian.io.HessianOutput;\n\nimport java.io.ByteArrayInputStream;\nimport java.io.ByteArrayOutputStream;\nimport java.io.IOException;\n\n/**\n * hessian serialize\n * @author xuxueli 2015-9-26 02:53:29\n */\npublic class HessianSerializer  {\n\n\tpublic static <T> byte[] serialize(T obj){\n\t\tByteArrayOutputStream os = new ByteArrayOutputStream();\n\t\tHessianOutput ho = new HessianOutput(os);\n\t\ttry {\n\t\t\tho.writeObject(obj);\n\t\t} catch (IOException e) {\n\t\t\tthrow new IllegalStateException(e.getMessage(), e);\n\t\t}\n\t\treturn os.toByteArray();\n\t}\n\n\tpublic static <T> Object deserialize(byte[] bytes, Class<T> clazz) {\n\t\tByteArrayInputStream is = new ByteArrayInputStream(bytes);\n\t\tHessianInput hi = new HessianInput(is);\n\t\ttry {\n\t\t\treturn hi.readObject();\n\t\t} catch (IOException e) {\n\t\t\tthrow new IllegalStateException(e.getMessage(), e);\n\t\t}\n\t}\n\t\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-core/src/main/java/com/xxl/job/core/thread/ExecutorRegistryThread.java",
    "content": "package com.xxl.job.core.thread;\n\nimport com.xxl.job.core.biz.AdminBiz;\nimport com.xxl.job.core.biz.model.RegistryParam;\nimport com.xxl.job.core.biz.model.ReturnT;\nimport com.xxl.job.core.enums.RegistryConfig;\nimport com.xxl.job.core.executor.XxlJobExecutor;\nimport com.xxl.job.core.util.IpUtil;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.concurrent.TimeUnit;\n\n/**\n * Created by xuxueli on 17/3/2.\n */\npublic class ExecutorRegistryThread extends Thread {\n    private static Logger logger = LoggerFactory.getLogger(ExecutorRegistryThread.class);\n\n    private static ExecutorRegistryThread instance = new ExecutorRegistryThread();\n    public static ExecutorRegistryThread getInstance(){\n        return instance;\n    }\n\n    private Thread registryThread;\n    private volatile boolean toStop = false;\n    public void start(final int port, final String ip, final String appName){\n\n        // valid\n        if (appName==null || appName.trim().length()==0) {\n            logger.warn(\">>>>>>>>>>> xxl-job, executor registry config fail, appName is null.\");\n            return;\n        }\n        if (XxlJobExecutor.getAdminBizList() == null) {\n            logger.warn(\">>>>>>>>>>> xxl-job, executor registry config fail, adminAddresses is null.\");\n            return;\n        }\n\n        // executor address (generate addredd = ip:port)\n        final String executorAddress;\n        if (ip != null && ip.trim().length()>0) {\n            executorAddress = ip.trim().concat(\":\").concat(String.valueOf(port));\n        } else {\n            executorAddress = IpUtil.getIpPort(port);\n        }\n\n        registryThread = new Thread(new Runnable() {\n            @Override\n            public void run() {\n\n                // registry\n                while (!toStop) {\n                    try {\n                        RegistryParam registryParam = new RegistryParam(RegistryConfig.RegistType.EXECUTOR.name(), appName, executorAddress);\n                        for (AdminBiz adminBiz: XxlJobExecutor.getAdminBizList()) {\n                            try {\n                                ReturnT<String> registryResult = adminBiz.registry(registryParam);\n                                if (registryResult!=null && ReturnT.SUCCESS_CODE == registryResult.getCode()) {\n                                    registryResult = ReturnT.SUCCESS;\n                                    logger.info(\">>>>>>>>>>> xxl-job registry success, registryParam:{}, registryResult:{}\", new Object[]{registryParam, registryResult});\n                                    break;\n                                } else {\n                                    logger.info(\">>>>>>>>>>> xxl-job registry fail, registryParam:{}, registryResult:{}\", new Object[]{registryParam, registryResult});\n                                }\n                            } catch (Exception e) {\n                                logger.info(\">>>>>>>>>>> xxl-job registry error, registryParam:{}\", registryParam, e);\n                            }\n\n                        }\n                    } catch (Exception e) {\n                        logger.error(e.getMessage(), e);\n                    }\n\n                    try {\n                        TimeUnit.SECONDS.sleep(RegistryConfig.BEAT_TIMEOUT);\n                    } catch (InterruptedException e) {\n                        logger.error(e.getMessage(), e);\n                    }\n                }\n\n                // registry remove\n                try {\n                    RegistryParam registryParam = new RegistryParam(RegistryConfig.RegistType.EXECUTOR.name(), appName, executorAddress);\n                    for (AdminBiz adminBiz: XxlJobExecutor.getAdminBizList()) {\n                        try {\n                            ReturnT<String> registryResult = adminBiz.registryRemove(registryParam);\n                            if (registryResult!=null && ReturnT.SUCCESS_CODE == registryResult.getCode()) {\n                                registryResult = ReturnT.SUCCESS;\n                                logger.info(\">>>>>>>>>>> xxl-job registry-remove success, registryParam:{}, registryResult:{}\", new Object[]{registryParam, registryResult});\n                                break;\n                            } else {\n                                logger.info(\">>>>>>>>>>> xxl-job registry-remove fail, registryParam:{}, registryResult:{}\", new Object[]{registryParam, registryResult});\n                            }\n                        } catch (Exception e) {\n                            logger.info(\">>>>>>>>>>> xxl-job registry-remove error, registryParam:{}\", registryParam, e);\n                        }\n\n                    }\n                } catch (Exception e) {\n                    logger.error(e.getMessage(), e);\n                }\n                logger.info(\">>>>>>>>>>> xxl-job, executor registry thread destory.\");\n\n            }\n        });\n        registryThread.setDaemon(true);\n        registryThread.start();\n    }\n\n    public void toStop() {\n        toStop = true;\n        // interrupt and wait\n        registryThread.interrupt();\n        try {\n            registryThread.join();\n        } catch (InterruptedException e) {\n            logger.error(e.getMessage(), e);\n        }\n    }\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-core/src/main/java/com/xxl/job/core/thread/JobLogFileCleanThread.java",
    "content": "package com.xxl.job.core.thread;\n\nimport com.xxl.job.core.log.XxlJobFileAppender;\nimport com.xxl.job.core.util.FileUtil;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.io.File;\nimport java.text.ParseException;\nimport java.text.SimpleDateFormat;\nimport java.util.Calendar;\nimport java.util.Date;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * job file clean thread\n *\n * @author xuxueli 2017-12-29 16:23:43\n */\npublic class JobLogFileCleanThread extends Thread {\n    private static Logger logger = LoggerFactory.getLogger(JobLogFileCleanThread.class);\n\n    private static JobLogFileCleanThread instance = new JobLogFileCleanThread();\n    public static JobLogFileCleanThread getInstance(){\n        return instance;\n    }\n\n    private Thread localThread;\n    private volatile boolean toStop = false;\n    public void start(final long logRetentionDays){\n\n        // limit min value\n        if (logRetentionDays < 3 ) {\n            return;\n        }\n\n        localThread = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                while (!toStop) {\n                    try {\n                        // clean log dir, over logRetentionDays\n                        File[] childDirs = new File(XxlJobFileAppender.getLogPath()).listFiles();\n                        if (childDirs!=null && childDirs.length>0) {\n\n                            // today\n                            Calendar todayCal = Calendar.getInstance();\n                            todayCal.set(Calendar.HOUR_OF_DAY,0);\n                            todayCal.set(Calendar.MINUTE,0);\n                            todayCal.set(Calendar.SECOND,0);\n                            todayCal.set(Calendar.MILLISECOND,0);\n\n                            Date todayDate = todayCal.getTime();\n\n                            for (File childFile: childDirs) {\n\n                                // valid\n                                if (!childFile.isDirectory()) {\n                                    continue;\n                                }\n                                if (childFile.getName().indexOf(\"-\") == -1) {\n                                    continue;\n                                }\n\n                                // file create date\n                                Date logFileCreateDate = null;\n                                try {\n                                    SimpleDateFormat simpleDateFormat = new SimpleDateFormat(\"yyyy-MM-dd\");\n                                    logFileCreateDate = simpleDateFormat.parse(childFile.getName());\n                                } catch (ParseException e) {\n                                    logger.error(e.getMessage(), e);\n                                }\n                                if (logFileCreateDate == null) {\n                                    continue;\n                                }\n\n                                if ((todayDate.getTime()-logFileCreateDate.getTime()) >= logRetentionDays * (24 * 60 * 60 * 1000) ) {\n                                    FileUtil.deleteRecursively(childFile);\n                                }\n\n                            }\n                        }\n\n                    } catch (Exception e) {\n                        logger.error(e.getMessage(), e);\n                    }\n\n                    try {\n                        TimeUnit.DAYS.sleep(1);\n                    } catch (InterruptedException e) {\n                        logger.error(e.getMessage(), e);\n                    }\n                }\n                logger.info(\">>>>>>>>>>> xxl-job, executor JobLogFileCleanThread thread destory.\");\n\n            }\n        });\n        localThread.setDaemon(true);\n        localThread.start();\n    }\n\n    public void toStop() {\n        toStop = true;\n\n        if (localThread == null) {\n            return;\n        }\n\n        // interrupt and wait\n        localThread.interrupt();\n        try {\n            localThread.join();\n        } catch (InterruptedException e) {\n            logger.error(e.getMessage(), e);\n        }\n    }\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-core/src/main/java/com/xxl/job/core/thread/JobThread.java",
    "content": "package com.xxl.job.core.thread;\n\nimport com.xxl.job.core.biz.model.HandleCallbackParam;\nimport com.xxl.job.core.biz.model.ReturnT;\nimport com.xxl.job.core.biz.model.TriggerParam;\nimport com.xxl.job.core.executor.XxlJobExecutor;\nimport com.xxl.job.core.handler.IJobHandler;\nimport com.xxl.job.core.log.XxlJobFileAppender;\nimport com.xxl.job.core.log.XxlJobLogger;\nimport com.xxl.job.core.util.ShardingUtil;\nimport org.eclipse.jetty.util.ConcurrentHashSet;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.io.PrintWriter;\nimport java.io.StringWriter;\nimport java.util.Arrays;\nimport java.util.Date;\nimport java.util.concurrent.LinkedBlockingQueue;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * handler thread\n * @author xuxueli 2016-1-16 19:52:47\n */\npublic class JobThread extends Thread{\n\tprivate static Logger logger = LoggerFactory.getLogger(JobThread.class);\n\n\tprivate int jobId;\n\tprivate IJobHandler handler;\n\tprivate LinkedBlockingQueue<TriggerParam> triggerQueue;\n\tprivate ConcurrentHashSet<Integer> triggerLogIdSet;\t\t// avoid repeat trigger for the same TRIGGER_LOG_ID\n\n\tprivate boolean toStop = false;\n\tprivate String stopReason;\n\n    private boolean running = false;    // if running job\n\tprivate int idleTimes = 0;\t\t\t// idel times\n\n\n\tpublic JobThread(int jobId, IJobHandler handler) {\n\t\tthis.jobId = jobId;\n\t\tthis.handler = handler;\n\t\tthis.triggerQueue = new LinkedBlockingQueue<TriggerParam>();\n\t\tthis.triggerLogIdSet = new ConcurrentHashSet<Integer>();\n\t}\n\tpublic IJobHandler getHandler() {\n\t\treturn handler;\n\t}\n\n    /**\n     * new trigger to queue\n     *\n     * @param triggerParam\n     * @return\n     */\n\tpublic ReturnT<String> pushTriggerQueue(TriggerParam triggerParam) {\n\t\t// avoid repeat\n\t\tif (triggerLogIdSet.contains(triggerParam.getLogId())) {\n\t\t\tlogger.info(\">>>>>>>>>>> repeate trigger job, logId:{}\", triggerParam.getLogId());\n\t\t\treturn new ReturnT<String>(ReturnT.FAIL_CODE, \"repeate trigger job, logId:\" + triggerParam.getLogId());\n\t\t}\n\n\t\ttriggerLogIdSet.add(triggerParam.getLogId());\n\t\ttriggerQueue.add(triggerParam);\n        return ReturnT.SUCCESS;\n\t}\n\n    /**\n     * kill job thread\n     *\n     * @param stopReason\n     */\n\tpublic void toStop(String stopReason) {\n\t\t/**\n\t\t * Thread.interrupt只支持终止线程的阻塞状态(wait、join、sleep)，\n\t\t * 在阻塞出抛出InterruptedException异常,但是并不会终止运行的线程本身；\n\t\t * 所以需要注意，此处彻底销毁本线程，需要通过共享变量方式；\n\t\t */\n\t\tthis.toStop = true;\n\t\tthis.stopReason = stopReason;\n\t}\n\n    /**\n     * is running job\n     * @return\n     */\n    public boolean isRunningOrHasQueue() {\n        return running || triggerQueue.size()>0;\n    }\n\n    @Override\n\tpublic void run() {\n\n    \t// init\n    \ttry {\n\t\t\thandler.init();\n\t\t} catch (Throwable e) {\n    \t\tlogger.error(e.getMessage(), e);\n\t\t}\n\n\t\t// execute\n\t\twhile(!toStop){\n\t\t\trunning = false;\n\t\t\tidleTimes++;\n\n            TriggerParam triggerParam = null;\n            ReturnT<String> executeResult = null;\n            try {\n\t\t\t\t// to check toStop signal, we need cycle, so wo cannot use queue.take(), instand of poll(timeout)\n\t\t\t\ttriggerParam = triggerQueue.poll(3L, TimeUnit.SECONDS);\n\t\t\t\tif (triggerParam!=null) {\n\t\t\t\t\trunning = true;\n\t\t\t\t\tidleTimes = 0;\n\t\t\t\t\ttriggerLogIdSet.remove(triggerParam.getLogId());\n\n\t\t\t\t\t// log filename, like \"logPath/yyyy-MM-dd/9999.log\"\n\t\t\t\t\tString logFileName = XxlJobFileAppender.makeLogFileName(new Date(triggerParam.getLogDateTim()), triggerParam.getLogId());\n\t\t\t\t\tXxlJobFileAppender.contextHolder.set(logFileName);\n\t\t\t\t\tShardingUtil.setShardingVo(new ShardingUtil.ShardingVO(triggerParam.getBroadcastIndex(), triggerParam.getBroadcastTotal()));\n\n\t\t\t\t\t// execute\n\t\t\t\t\tXxlJobLogger.log(\"<br>----------- xxl-job job execute start -----------<br>----------- Param:\" + triggerParam.getExecutorParams());\n\t\t\t\t\texecuteResult = handler.execute(triggerParam.getExecutorParams());\n\t\t\t\t\tif (executeResult == null) {\n\t\t\t\t\t\texecuteResult = IJobHandler.FAIL;\n\t\t\t\t\t}\n\t\t\t\t\tXxlJobLogger.log(\"<br>----------- xxl-job job execute end(finish) -----------<br>----------- ReturnT:\" + executeResult);\n\n\t\t\t\t} else {\n\t\t\t\t\tif (idleTimes > 30) {\n\t\t\t\t\t\tXxlJobExecutor.removeJobThread(jobId, \"excutor idel times over limit.\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (Throwable e) {\n\t\t\t\tif (toStop) {\n\t\t\t\t\tXxlJobLogger.log(\"<br>----------- JobThread toStop, stopReason:\" + stopReason);\n\t\t\t\t}\n\n\t\t\t\tStringWriter stringWriter = new StringWriter();\n\t\t\t\te.printStackTrace(new PrintWriter(stringWriter));\n\t\t\t\tString errorMsg = stringWriter.toString();\n\t\t\t\texecuteResult = new ReturnT<String>(ReturnT.FAIL_CODE, errorMsg);\n\n\t\t\t\tXxlJobLogger.log(\"<br>----------- JobThread Exception:\" + errorMsg + \"<br>----------- xxl-job job execute end(error) -----------\");\n\t\t\t} finally {\n                if(triggerParam != null) {\n                    // callback handler info\n                    if (!toStop) {\n                        // commonm\n                        TriggerCallbackThread.pushCallBack(new HandleCallbackParam(triggerParam.getLogId(), executeResult));\n                    } else {\n                        // is killed\n                        ReturnT<String> stopResult = new ReturnT<String>(ReturnT.FAIL_CODE, stopReason + \" [业务运行中，被强制终止]\");\n                        TriggerCallbackThread.pushCallBack(new HandleCallbackParam(triggerParam.getLogId(), stopResult));\n                    }\n                }\n            }\n        }\n\n\t\t// callback trigger request in queue\n\t\twhile(triggerQueue !=null && triggerQueue.size()>0){\n\t\t\tTriggerParam triggerParam = triggerQueue.poll();\n\t\t\tif (triggerParam!=null) {\n\t\t\t\t// is killed\n\t\t\t\tReturnT<String> stopResult = new ReturnT<String>(ReturnT.FAIL_CODE, stopReason + \" [任务尚未执行，在调度队列中被终止]\");\n\t\t\t\tTriggerCallbackThread.pushCallBack(new HandleCallbackParam(triggerParam.getLogId(), stopResult));\n\t\t\t}\n\t\t}\n\n\t\t// destroy\n\t\ttry {\n\t\t\thandler.destroy();\n\t\t} catch (Throwable e) {\n\t\t\tlogger.error(e.getMessage(), e);\n\t\t}\n\n\t\tlogger.info(\">>>>>>>>>>> xxl-job JobThread stoped, hashCode:{}\", Thread.currentThread());\n\t}\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-core/src/main/java/com/xxl/job/core/thread/TriggerCallbackThread.java",
    "content": "package com.xxl.job.core.thread;\n\nimport com.xxl.job.core.biz.AdminBiz;\nimport com.xxl.job.core.biz.model.HandleCallbackParam;\nimport com.xxl.job.core.biz.model.ReturnT;\nimport com.xxl.job.core.executor.XxlJobExecutor;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.concurrent.LinkedBlockingQueue;\n\n/**\n * Created by xuxueli on 16/7/22.\n */\npublic class TriggerCallbackThread {\n    private static Logger logger = LoggerFactory.getLogger(TriggerCallbackThread.class);\n\n    private static TriggerCallbackThread instance = new TriggerCallbackThread();\n    public static TriggerCallbackThread getInstance(){\n        return instance;\n    }\n\n    /**\n     * job results callback queue\n     */\n    private LinkedBlockingQueue<HandleCallbackParam> callBackQueue = new LinkedBlockingQueue<HandleCallbackParam>();\n    public static void pushCallBack(HandleCallbackParam callback){\n        getInstance().callBackQueue.add(callback);\n        logger.debug(\">>>>>>>>>>> xxl-job, push callback request, logId:{}\", callback.getLogId());\n    }\n\n    /**\n     * callback thread\n     */\n    private Thread triggerCallbackThread;\n    private volatile boolean toStop = false;\n    public void start() {\n\n        // valid\n        if (XxlJobExecutor.getAdminBizList() == null) {\n            logger.warn(\">>>>>>>>>>> xxl-job, executor callback config fail, adminAddresses is null.\");\n            return;\n        }\n\n        triggerCallbackThread = new Thread(new Runnable() {\n\n            @Override\n            public void run() {\n\n                // normal callback\n                while(!toStop){\n                    try {\n                        HandleCallbackParam callback = getInstance().callBackQueue.take();\n                        if (callback != null) {\n\n                            // callback list param\n                            List<HandleCallbackParam> callbackParamList = new ArrayList<HandleCallbackParam>();\n                            int drainToNum = getInstance().callBackQueue.drainTo(callbackParamList);\n                            callbackParamList.add(callback);\n\n                            // callback, will retry if error\n                            if (callbackParamList!=null && callbackParamList.size()>0) {\n                                doCallback(callbackParamList);\n                            }\n                        }\n                    } catch (Exception e) {\n                        logger.error(e.getMessage(), e);\n                    }\n                }\n\n                // last callback\n                try {\n                    List<HandleCallbackParam> callbackParamList = new ArrayList<HandleCallbackParam>();\n                    int drainToNum = getInstance().callBackQueue.drainTo(callbackParamList);\n                    if (callbackParamList!=null && callbackParamList.size()>0) {\n                        doCallback(callbackParamList);\n                    }\n                } catch (Exception e) {\n                    logger.error(e.getMessage(), e);\n                }\n                logger.info(\">>>>>>>>>>> xxl-job, executor callback thread destory.\");\n\n            }\n        });\n        triggerCallbackThread.setDaemon(true);\n        triggerCallbackThread.start();\n    }\n    public void toStop(){\n        toStop = true;\n        // interrupt and wait\n        triggerCallbackThread.interrupt();\n        try {\n            triggerCallbackThread.join();\n        } catch (InterruptedException e) {\n            logger.error(e.getMessage(), e);\n        }\n    }\n\n    /**\n     * do callback, will retry if error\n     * @param callbackParamList\n     */\n    private void doCallback(List<HandleCallbackParam> callbackParamList){\n        // callback, will retry if error\n        for (AdminBiz adminBiz: XxlJobExecutor.getAdminBizList()) {\n            try {\n                ReturnT<String> callbackResult = adminBiz.callback(callbackParamList);\n                if (callbackResult!=null && ReturnT.SUCCESS_CODE == callbackResult.getCode()) {\n                    callbackResult = ReturnT.SUCCESS;\n                    logger.info(\">>>>>>>>>>> xxl-job callback success, callbackParamList:{}, callbackResult:{}\", new Object[]{callbackParamList, callbackResult});\n                    break;\n                } else {\n                    logger.info(\">>>>>>>>>>> xxl-job callback fail, callbackParamList:{}, callbackResult:{}\", new Object[]{callbackParamList, callbackResult});\n                }\n            } catch (Exception e) {\n                logger.error(\">>>>>>>>>>> xxl-job callback error, callbackParamList：{}\", callbackParamList, e);\n                //getInstance().callBackQueue.addAll(callbackParamList);\n            }\n        }\n    }\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-core/src/main/java/com/xxl/job/core/util/FileUtil.java",
    "content": "package com.xxl.job.core.util;\n\nimport java.io.File;\n\n/**\n * file tool\n *\n * @author xuxueli 2017-12-29 17:56:48\n */\npublic class FileUtil {\n\n    public static boolean deleteRecursively(File root) {\n        if (root != null && root.exists()) {\n            if (root.isDirectory()) {\n                File[] children = root.listFiles();\n                if (children != null) {\n                    for (File child : children) {\n                        deleteRecursively(child);\n                    }\n                }\n            }\n            return root.delete();\n        }\n        return false;\n    }\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-core/src/main/java/com/xxl/job/core/util/HttpClientUtil.java",
    "content": "package com.xxl.job.core.util;\n\nimport org.apache.http.HttpEntity;\nimport org.apache.http.HttpResponse;\nimport org.apache.http.client.config.RequestConfig;\nimport org.apache.http.client.methods.HttpPost;\nimport org.apache.http.entity.ByteArrayEntity;\nimport org.apache.http.entity.ContentType;\nimport org.apache.http.impl.client.CloseableHttpClient;\nimport org.apache.http.impl.client.HttpClients;\nimport org.apache.http.util.EntityUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport javax.servlet.http.HttpServletRequest;\nimport java.io.IOException;\nimport java.io.InputStream;\n\n/**\n * httpclient util\n * @author xuxueli 2015-10-31 19:50:41\n */\npublic class HttpClientUtil {\n\tprivate static Logger logger = LoggerFactory.getLogger(HttpClientUtil.class);\n\n\t/**\n\t * post request\n\t */\n\tpublic static byte[] postRequest(String reqURL, byte[] data) throws Exception {\n\t\tbyte[] responseBytes = null;\n\t\t\n\t\tHttpPost httpPost = new HttpPost(reqURL);\n\t\t//CloseableHttpClient httpClient = HttpClients.createDefault();\n\t\tCloseableHttpClient httpClient = HttpClients.custom().disableAutomaticRetries().build();\t// disable retry\n\n\t\ttry {\n\t\t\t// init post\n\t\t\t/*if (params != null && !params.isEmpty()) {\n\t\t\t\tList<NameValuePair> formParams = new ArrayList<NameValuePair>();\n\t\t\t\tfor (Map.Entry<String, String> entry : params.entrySet()) {\n\t\t\t\t\tformParams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));\n\t\t\t\t}\n\t\t\t\thttpPost.setEntity(new UrlEncodedFormEntity(formParams, \"UTF-8\"));\n\t\t\t}*/\n\n\t\t\t// timeout\n\t\t\tRequestConfig requestConfig = RequestConfig.custom()\n                    .setConnectionRequestTimeout(10000)\n                    .setSocketTimeout(10000)\n                    .setConnectTimeout(10000)\n                    .build();\n\n\t\t\thttpPost.setConfig(requestConfig);\n\n\t\t\t// data\n\t\t\tif (data != null) {\n\t\t\t\thttpPost.setEntity(new ByteArrayEntity(data, ContentType.DEFAULT_BINARY));\n\t\t\t}\n\t\t\t// do post\n\t\t\tHttpResponse response = httpClient.execute(httpPost);\n\t\t\tHttpEntity entity = response.getEntity();\n\t\t\tif (null != entity) {\n\t\t\t\tresponseBytes = EntityUtils.toByteArray(entity);\n\t\t\t\tEntityUtils.consume(entity);\n\t\t\t}\n\t\t} catch (Exception e) {\n\t\t\tthrow e;\n\t\t} finally {\n\t\t\thttpPost.releaseConnection();\n\t\t\ttry {\n\t\t\t\thttpClient.close();\n\t\t\t} catch (IOException e) {\n\t\t\t\tlogger.error(e.getMessage(), e);\n\t\t\t}\n\t\t}\n\t\treturn responseBytes;\n\t}\n\t\n\t/**\n\t * read bytes from http request\n\t * @param request\n\t * @return\n\t * @throws IOException \n\t */\n\tpublic static final byte[] readBytes(HttpServletRequest request) throws IOException {\n\t\trequest.setCharacterEncoding(\"UTF-8\");\n        int contentLen = request.getContentLength();\n\t\tInputStream is = request.getInputStream();\n\t\tif (contentLen > 0) {\n\t\t\tint readLen = 0;\n\t\t\tint readLengthThisTime = 0;\n\t\t\tbyte[] message = new byte[contentLen];\n\t\t\ttry {\n\t\t\t\twhile (readLen != contentLen) {\n\t\t\t\t\treadLengthThisTime = is.read(message, readLen, contentLen - readLen);\n\t\t\t\t\tif (readLengthThisTime == -1) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\treadLen += readLengthThisTime;\n\t\t\t\t}\n\t\t\t\treturn message;\n\t\t\t} catch (IOException e) {\n\t\t\t\tlogger.error(e.getMessage(), e);\n\t\t\t\tthrow e;\n\t\t\t}\n\t\t}\n\t\treturn new byte[] {};\n\t}\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-core/src/main/java/com/xxl/job/core/util/IpUtil.java",
    "content": "package com.xxl.job.core.util;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.net.InetAddress;\nimport java.net.NetworkInterface;\nimport java.net.UnknownHostException;\nimport java.util.Enumeration;\nimport java.util.regex.Pattern;\n\n/**\n * get ip\n * @author xuxueli 2016-5-22 11:38:05\n */\npublic class IpUtil {\n\tprivate static final Logger logger = LoggerFactory.getLogger(IpUtil.class);\n\n\tprivate static final String ANYHOST = \"0.0.0.0\";\n\tprivate static final String LOCALHOST = \"127.0.0.1\";\n\tpublic static final Pattern IP_PATTERN = Pattern.compile(\"\\\\d{1,3}(\\\\.\\\\d{1,3}){3,5}$\");\n\n\tprivate static volatile InetAddress LOCAL_ADDRESS = null;\n\n\t/**\n\t * valid address\n\t * @param address\n\t * @return\n\t */\n\tprivate static boolean isValidAddress(InetAddress address) {\n\t\tif (address == null || address.isLoopbackAddress())\n\t\t\treturn false;\n\t\tString name = address.getHostAddress();\n\t\treturn (name != null\n\t\t\t\t&& ! ANYHOST.equals(name)\n\t\t\t\t&& ! LOCALHOST.equals(name)\n\t\t\t\t&& IP_PATTERN.matcher(name).matches());\n\t}\n\n\t/**\n\t * get first valid addredd\n\t * @return\n\t */\n\tprivate static InetAddress getFirstValidAddress() {\n\t\tInetAddress localAddress = null;\n\t\ttry {\n\t\t\tlocalAddress = InetAddress.getLocalHost();\n\t\t\tif (isValidAddress(localAddress)) {\n\t\t\t\treturn localAddress;\n\t\t\t}\n\t\t} catch (Throwable e) {\n\t\t\tlogger.error(\"Failed to retriving ip address, \" + e.getMessage(), e);\n\t\t}\n\t\ttry {\n\t\t\tEnumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();\n\t\t\tif (interfaces != null) {\n\t\t\t\twhile (interfaces.hasMoreElements()) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tNetworkInterface network = interfaces.nextElement();\n\t\t\t\t\t\tEnumeration<InetAddress> addresses = network.getInetAddresses();\n\t\t\t\t\t\tif (addresses != null) {\n\t\t\t\t\t\t\twhile (addresses.hasMoreElements()) {\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tInetAddress address = addresses.nextElement();\n\t\t\t\t\t\t\t\t\tif (isValidAddress(address)) {\n\t\t\t\t\t\t\t\t\t\treturn address;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} catch (Throwable e) {\n\t\t\t\t\t\t\t\t\tlogger.error(\"Failed to retriving ip address, \" + e.getMessage(), e);\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} catch (Throwable e) {\n\t\t\t\t\t\tlogger.error(\"Failed to retriving ip address, \" + e.getMessage(), e);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (Throwable e) {\n\t\t\tlogger.error(\"Failed to retriving ip address, \" + e.getMessage(), e);\n\t\t}\n\t\tlogger.error(\"Could not get local host ip address, will use 127.0.0.1 instead.\");\n\t\treturn localAddress;\n\t}\n\n\t/**\n\t * get address\n\t * @return\n\t */\n\tprivate static InetAddress getAddress() {\n\t\tif (LOCAL_ADDRESS != null)\n\t\t\treturn LOCAL_ADDRESS;\n\t\tInetAddress localAddress = getFirstValidAddress();\n\t\tLOCAL_ADDRESS = localAddress;\n\t\treturn localAddress;\n\t}\n\n\t/**\n\t * get ip\n\t * @return\n\t */\n\tpublic static String getIp(){\n\t\tInetAddress address = getAddress();\n\t\tif (address==null) {\n\t\t\treturn null;\n\t\t}\n\t\treturn address.getHostAddress();\n\t}\n\n\t/**\n\t * get ip:port\n\t * @param port\n\t * @return\n\t */\n\tpublic static String getIpPort(int port){\n\t\tString ip = getIp();\n\t\tif (ip==null) {\n\t\t\treturn null;\n\t\t}\n\t\treturn ip.concat(\":\").concat(String.valueOf(port));\n\t}\n\n\tpublic static void main(String[] args) throws UnknownHostException {\n\t\tSystem.out.println(getIp());\n\t\tSystem.out.println(getIpPort(8080));\n\t}\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-core/src/main/java/com/xxl/job/core/util/JacksonUtil.java",
    "content": "package com.xxl.job.core.util;\n\nimport com.fasterxml.jackson.core.JsonGenerationException;\nimport com.fasterxml.jackson.core.JsonParseException;\nimport com.fasterxml.jackson.core.type.TypeReference;\nimport com.fasterxml.jackson.databind.JsonMappingException;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.io.IOException;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * Jackson util\n * \n * 1、obj need private and set/get；\n * 2、do not support inner class；\n * \n * @author xuxueli 2015-9-25 18:02:56\n */\npublic class JacksonUtil {\n\tprivate static Logger logger = LoggerFactory.getLogger(JacksonUtil.class);\n\n    private final static ObjectMapper objectMapper = new ObjectMapper();\n    public static ObjectMapper getInstance() {\n        return objectMapper;\n    }\n\n    /**\n     * bean、array、List、Map --> json\n     * \n     * @param obj\n     * @return json string\n     * @throws Exception\n     */\n    public static String writeValueAsString(Object obj) {\n    \ttry {\n\t\t\treturn getInstance().writeValueAsString(obj);\n\t\t} catch (JsonGenerationException e) {\n\t\t\tlogger.error(e.getMessage(), e);\n\t\t} catch (JsonMappingException e) {\n\t\t\tlogger.error(e.getMessage(), e);\n\t\t} catch (IOException e) {\n\t\t\tlogger.error(e.getMessage(), e);\n\t\t}\n        return null;\n    }\n\n    /**\n     * string --> bean、Map、List(array)\n     * \n     * @param jsonStr\n     * @param clazz\n     * @return obj\n     * @throws Exception\n     */\n    public static <T> T readValue(String jsonStr, Class<T> clazz) {\n    \ttry {\n\t\t\treturn getInstance().readValue(jsonStr, clazz);\n\t\t} catch (JsonParseException e) {\n\t\t\tlogger.error(e.getMessage(), e);\n\t\t} catch (JsonMappingException e) {\n\t\t\tlogger.error(e.getMessage(), e);\n\t\t} catch (IOException e) {\n\t\t\tlogger.error(e.getMessage(), e);\n\t\t}\n    \treturn null;\n    }\n    public static <T> T readValueRefer(String jsonStr, Class<T> clazz) {\n    \ttry {\n\t\t\treturn getInstance().readValue(jsonStr, new TypeReference<T>() { });\n\t\t} catch (JsonParseException e) {\n\t\t\tlogger.error(e.getMessage(), e);\n\t\t} catch (JsonMappingException e) {\n\t\t\tlogger.error(e.getMessage(), e);\n\t\t} catch (IOException e) {\n\t\t\tlogger.error(e.getMessage(), e);\n\t\t}\n    \treturn null;\n    }\n\n    public static void main(String[] args) {\n\t\ttry {\n\t\t\tMap<String, String> map = new HashMap<String, String>();\n\t\t\tmap.put(\"aaa\", \"111\");\n\t\t\tmap.put(\"bbb\", \"222\");\n\t\t\tString json = writeValueAsString(map);\n\t\t\tSystem.out.println(json);\n\t\t\tSystem.out.println(readValue(json, Map.class));\n\t\t} catch (Exception e) {\n\t\t\tlogger.error(e.getMessage(), e);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-core/src/main/java/com/xxl/job/core/util/NetUtil.java",
    "content": "package com.xxl.job.core.util;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.io.IOException;\nimport java.net.ServerSocket;\n\n/**\n * net util\n *\n * @author xuxueli 2017-11-29 17:00:25\n */\npublic class NetUtil {\n    private static Logger logger = LoggerFactory.getLogger(NetUtil.class);\n\n    /**\n     * find avaliable port\n     *\n     * @param defaultPort\n     * @return\n     */\n    public static int findAvailablePort(int defaultPort) {\n        int portTmp = defaultPort;\n        while (portTmp < 65535) {\n            if (!isPortUsed(portTmp)) {\n                return portTmp;\n            } else {\n                portTmp++;\n            }\n        }\n        portTmp = defaultPort--;\n        while (portTmp > 0) {\n            if (!isPortUsed(portTmp)) {\n                return portTmp;\n            } else {\n                portTmp--;\n            }\n        }\n        throw new IllegalStateException(\"no available port.\");\n    }\n\n    /**\n     * check port used\n     *\n     * @param port\n     * @return\n     */\n    public static boolean isPortUsed(int port) {\n        boolean used = false;\n        ServerSocket serverSocket = null;\n        try {\n            serverSocket = new ServerSocket(port);\n            used = false;\n        } catch (IOException e) {\n            logger.debug(\">>>>>>>>>>> xxl-job, port[{}] is in use.\", port);\n            used = true;\n        } finally {\n            if (serverSocket != null) {\n                try {\n                    serverSocket.close();\n                } catch (IOException e) {\n                    logger.info(\"\");\n                }\n            }\n        }\n        return used;\n    }\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-core/src/main/java/com/xxl/job/core/util/ScriptUtil.java",
    "content": "package com.xxl.job.core.util;\n\nimport org.apache.commons.exec.CommandLine;\nimport org.apache.commons.exec.DefaultExecutor;\nimport org.apache.commons.exec.PumpStreamHandler;\n\nimport java.io.FileOutputStream;\nimport java.io.IOException;\n\n/**\n *  1、内嵌编译器如\"PythonInterpreter\"无法引用扩展包，因此推荐使用java调用控制台进程方式\"Runtime.getRuntime().exec()\"来运行脚本(shell或python)；\n *  2、因为通过java调用控制台进程方式实现，需要保证目标机器PATH路径正确配置对应编译器；\n *  3、暂时脚本执行日志只能在脚本执行结束后一次性获取，无法保证实时性；因此为确保日志实时性，可改为将脚本打印的日志存储在指定的日志文件上；\n *  4、python 异常输出优先级高于标准输出，体现在Log文件中，因此推荐通过logging方式打日志保持和异常信息一致；否则用prinf日志顺序会错乱\n *\n * Created by xuxueli on 17/2/25.\n */\npublic class ScriptUtil {\n\n    /**\n     * make script file\n     *\n     * @param scriptFileName\n     * @param content\n     * @throws IOException\n     */\n    public static void markScriptFile(String scriptFileName, String content) throws IOException {\n        // make file,   filePath/gluesource/666-123456789.py\n        FileOutputStream fileOutputStream = null;\n        try {\n            fileOutputStream = new FileOutputStream(scriptFileName);\n            fileOutputStream.write(content.getBytes(\"UTF-8\"));\n            fileOutputStream.close();\n        } catch (Exception e) {\n            throw e;\n        }finally{\n            if(fileOutputStream != null){\n                fileOutputStream.close();\n            }\n        }\n    }\n\n    /**\n     * 日志文件输出方式\n     *\n     * 优点：支持将目标数据实时输出到指定日志文件中去\n     * 缺点：\n     *      标准输出和错误输出优先级固定，可能和脚本中顺序不一致\n     *      Java无法实时获取\n     *\n     * @param command\n     * @param scriptFile\n     * @param logFile\n     * @param params\n     * @return\n     * @throws IOException\n     */\n    public static int execToFile(String command, String scriptFile, String logFile, String... params) throws IOException {\n        // 标准输出：print （null if watchdog timeout）\n        // 错误输出：logging + 异常 （still exists if watchdog timeout）\n        // 标准输入\n        try (FileOutputStream fileOutputStream = new FileOutputStream(logFile, true)) {\n            PumpStreamHandler streamHandler = new PumpStreamHandler(fileOutputStream, fileOutputStream, null);\n\n            // command\n            CommandLine commandline = new CommandLine(command);\n            commandline.addArgument(scriptFile);\n            if (params!=null && params.length>0) {\n                commandline.addArguments(params);\n            }\n\n            // exec\n            DefaultExecutor exec = new DefaultExecutor();\n            exec.setExitValues(null);\n            exec.setStreamHandler(streamHandler);\n            int exitValue = exec.execute(commandline);  // exit code: 0=success, 1=error\n            return exitValue;\n        }\n    }\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-core/src/main/java/com/xxl/job/core/util/ShardingUtil.java",
    "content": "package com.xxl.job.core.util;\n\n/**\n * sharding vo\n * @author xuxueli 2017-07-25 21:26:38\n */\npublic class ShardingUtil {\n\n    private static InheritableThreadLocal<ShardingVO> contextHolder = new InheritableThreadLocal<ShardingVO>();\n\n    public static class ShardingVO {\n\n        private int index;  // sharding index\n        private int total;  // sharding total\n\n        public ShardingVO(int index, int total) {\n            this.index = index;\n            this.total = total;\n        }\n\n        public int getIndex() {\n            return index;\n        }\n\n        public void setIndex(int index) {\n            this.index = index;\n        }\n\n        public int getTotal() {\n            return total;\n        }\n\n        public void setTotal(int total) {\n            this.total = total;\n        }\n    }\n\n    public static void setShardingVo(ShardingVO shardingVo){\n        contextHolder.set(shardingVo);\n    }\n\n    public static ShardingVO getShardingVo(){\n        return contextHolder.get();\n    }\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-demo/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" 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  <parent>\n    <groupId>com.open.capacity</groupId>\n    <artifactId>open-xxl-job</artifactId>\n    <version>0.0.1-SNAPSHOT</version>\n  </parent>\n  <artifactId>xxl-job-demo</artifactId>\n  \n  <properties>\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        <xxl.job.core.version>0.0.1-SNAPSHOT</xxl.job.core.version>\n        <spring-boot.version>1.5.9.RELEASE</spring-boot.version>\n        <jetty-server.version>9.2.24.v20180105</jetty-server.version>\n  </properties>\n  \n  <dependencyManagement>\n        <dependencies>\n            <dependency>\n                <!-- Import dependency management from Spring Boot (依赖管理：继承一些默认的依赖，工程需要依赖的jar包的管理，申明其他dependency的时候就不需要version) -->\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-starter-parent</artifactId>\n                <version>${spring-boot.version}</version>\n                <type>pom</type>\n                <scope>import</scope>\n            </dependency>\n\n            <!-- jetty -->\n            <dependency>\n                <groupId>org.eclipse.jetty</groupId>\n                <artifactId>jetty-server</artifactId>\n                <version>${jetty-server.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>org.eclipse.jetty</groupId>\n                <artifactId>jetty-util</artifactId>\n                <version>${jetty-server.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>org.eclipse.jetty</groupId>\n                <artifactId>jetty-http</artifactId>\n                <version>${jetty-server.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>org.eclipse.jetty</groupId>\n                <artifactId>jetty-io</artifactId>\n                <version>${jetty-server.version}</version>\n            </dependency>\n\n        </dependencies>\n    </dependencyManagement>\n\n    <dependencies>\n        <!-- spring-boot-starter-web (spring-webmvc + tomcat) -->\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n\n        <!-- xxl-job-core -->\n        <dependency>\n            <groupId>com.open.capacity</groupId>\n            <artifactId>xxl-job-core</artifactId>\n            <version>0.0.1-SNAPSHOT</version>\n        </dependency>\n\n    </dependencies>\n\n    <build>\n        <plugins>\n            <!-- spring-boot-maven-plugin (提供了直接运行项目的插件：如果是通过parent方式继承spring-boot-starter-parent则不用此插件) -->\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n                <executions>\n                    <execution>\n                        <goals>\n                            <goal>repackage</goal>\n                        </goals>\n                    </execution>\n                </executions>\n            </plugin>\n        </plugins>\n    </build>\n  \n  \n  \n</project>"
  },
  {
    "path": "open-xxl-job/xxl-job-demo/src/main/java/com/open/capacity/Application.java",
    "content": "package com.open.capacity;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class Application {\n\n\tpublic static void main(String[] args) {\n        SpringApplication.run(Application.class, args);\n\t}\n\n}"
  },
  {
    "path": "open-xxl-job/xxl-job-demo/src/main/java/com/open/capacity/config/XxlJobConfig.java",
    "content": "package com.open.capacity.config;\n\nimport com.xxl.job.core.executor.XxlJobExecutor;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.ComponentScan;\nimport org.springframework.context.annotation.Configuration;\n\n/**\n * xxl-job config\n *\n * @author xuxueli 2017-04-28\n */\n@Configuration\n@ComponentScan(basePackages = \"com.open.capacity.jobhandler\")\npublic class XxlJobConfig {\n    private Logger logger = LoggerFactory.getLogger(XxlJobConfig.class);\n\n    @Value(\"${xxl.job.admin.addresses}\")\n    private String adminAddresses;\n\n    @Value(\"${xxl.job.executor.appname}\")\n    private String appName;\n\n    @Value(\"${xxl.job.executor.ip}\")\n    private String ip;\n\n    @Value(\"${xxl.job.executor.port}\")\n    private int port;\n\n    @Value(\"${xxl.job.accessToken}\")\n    private String accessToken;\n\n    @Value(\"${xxl.job.executor.logpath}\")\n    private String logPath;\n\n    @Value(\"${xxl.job.executor.logretentiondays}\")\n    private int logRetentionDays;\n\n\n    @Bean(initMethod = \"start\", destroyMethod = \"destroy\")\n    public XxlJobExecutor xxlJobExecutor() {\n        logger.info(\">>>>>>>>>>> xxl-job config init.\");\n        XxlJobExecutor xxlJobExecutor = new XxlJobExecutor();\n        xxlJobExecutor.setAdminAddresses(adminAddresses);\n        xxlJobExecutor.setAppName(appName);\n        xxlJobExecutor.setIp(ip);\n        xxlJobExecutor.setPort(port);\n        xxlJobExecutor.setAccessToken(accessToken);\n        xxlJobExecutor.setLogPath(logPath);\n        xxlJobExecutor.setLogRetentionDays(logRetentionDays);\n\n        return xxlJobExecutor;\n    }\n\n}"
  },
  {
    "path": "open-xxl-job/xxl-job-demo/src/main/java/com/open/capacity/jobhandler/DemoJobHandler.java",
    "content": "package com.open.capacity.jobhandler;\n\nimport com.xxl.job.core.biz.model.ReturnT;\nimport com.xxl.job.core.handler.IJobHandler;\nimport com.xxl.job.core.handler.annotation.JobHandler;\nimport com.xxl.job.core.log.XxlJobLogger;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.stereotype.Component;\n\nimport java.util.concurrent.TimeUnit;\n\n\n/**\n * 任务Handler示例（Bean模式）\n *\n * 开发步骤：\n * 1、继承\"IJobHandler\"：“com.xxl.job.core.handler.IJobHandler”；\n * 2、注册到Spring容器：添加“@Component”注解，被Spring容器扫描为Bean实例；\n * 3、注册到执行器工厂：添加“@JobHandler(value=\"自定义jobhandler名称\")”注解，注解value值对应的是调度中心新建任务的JobHandler属性的值。\n * 4、执行日志：需要通过 \"XxlJobLogger.log\" 打印执行日志；\n *\n * @author xuxueli 2015-12-19 19:43:36\n */\n@JobHandler(value=\"demoJobHandler\")\n@Component\npublic class DemoJobHandler extends IJobHandler {\n\tLogger logger = LoggerFactory.getLogger(DemoJobHandler.class);\n\n\t@Override\n\tpublic ReturnT<String> execute(String param) throws Exception {\n\t\tlogger.info(\"获取参数===》\"+param);\n\t\tXxlJobLogger.log(\"获取参数==》\"+param);\n\t\tXxlJobLogger.log(\"XXL-JOB, Hello World.\");\n\n\t\tfor (int i = 0; i < 5; i++) {\n\t\t\tXxlJobLogger.log(\"beat at:\" + i);\n\t\t\tTimeUnit.SECONDS.sleep(2);\n\t\t}\n\t\treturn SUCCESS;\n\t}\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-demo/src/main/java/com/open/capacity/jobhandler/ShardingJobHandler.java",
    "content": "package com.open.capacity.jobhandler;\n\nimport com.xxl.job.core.biz.model.ReturnT;\nimport com.xxl.job.core.handler.IJobHandler;\nimport com.xxl.job.core.handler.annotation.JobHandler;\nimport com.xxl.job.core.log.XxlJobLogger;\nimport com.xxl.job.core.util.ShardingUtil;\nimport org.springframework.stereotype.Service;\n\n\n/**\n * 分片广播任务\n *\n * @author xuxueli 2017-07-25 20:56:50\n */\n@JobHandler(value=\"shardingJobHandler\")\n@Service\npublic class ShardingJobHandler extends IJobHandler {\n\n\t@Override\n\tpublic ReturnT<String> execute(String param) throws Exception {\n\n\t\t// 分片参数\n\t\tShardingUtil.ShardingVO shardingVO = ShardingUtil.getShardingVo();\n\t\tXxlJobLogger.log(\"分片参数：当前分片序号 = {0}, 总分片数 = {1}\", shardingVO.getIndex(), shardingVO.getTotal());\n\n\t\t// 业务逻辑\n\t\tfor (int i = 0; i < shardingVO.getTotal(); i++) {\n\t\t\tif (i == shardingVO.getIndex()) {\n\t\t\t\tXxlJobLogger.log(\"第 {0} 片, 命中分片开始处理\", i);\n\t\t\t} else {\n\t\t\t\tXxlJobLogger.log(\"第 {0} 片, 忽略\", i);\n\t\t\t}\n\t\t}\n\n\t\treturn SUCCESS;\n\t}\n\n}\n"
  },
  {
    "path": "open-xxl-job/xxl-job-demo/src/main/resources/application.properties",
    "content": "# web port\nserver.port=8081\n\n# log config\nlogging.config=classpath:logback.xml\n\n\n### xxl-job admin address list, such as \"http://address\" or \"http://address01,http://address02\"\nxxl.job.admin.addresses=http://127.0.0.1:8888/\n\n### xxl-job executor address\nxxl.job.executor.appname=open-xxl-job-demo\nxxl.job.executor.ip=\nxxl.job.executor.port=9999\n\n### xxl-job, access token\nxxl.job.accessToken=\n\n### xxl-job log path\nxxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler\n### xxl-job log retention days\nxxl.job.executor.logretentiondays=-1"
  },
  {
    "path": "open-xxl-job/xxl-job-demo/src/main/resources/logback.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<configuration debug=\"false\" scan=\"true\" scanPeriod=\"1 seconds\">\n\n    <contextName>logback</contextName>\n    <property name=\"log.path\" value=\"/data/applogs/xxl-job/xxl-job-executor-sample-springboot.log\"/>\n\n    <appender name=\"console\" class=\"ch.qos.logback.core.ConsoleAppender\">\n       <!-- <filter class=\"ch.qos.logback.classic.filter.ThresholdFilter\" >\n            <level>WARN</level>\n        </filter>-->\n        <encoder>\n            <pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>\n        </encoder>\n    </appender>\n\n    <appender name=\"file\" class=\"ch.qos.logback.core.rolling.RollingFileAppender\">\n        <file>${log.path}</file>\n        <rollingPolicy class=\"ch.qos.logback.core.rolling.TimeBasedRollingPolicy\">\n            <fileNamePattern>${log.path}.%d{yyyy-MM-dd}.zip</fileNamePattern>\n        </rollingPolicy>\n        <encoder>\n            <pattern>%date %level [%thread] %logger{36} [%file : %line] %msg%n\n            </pattern>\n        </encoder>\n    </appender>\n\n    <root level=\"info\">\n        <appender-ref ref=\"console\"/>\n        <appender-ref ref=\"file\"/>\n    </root>\n\n    <!--<logger name=\"com.xxl.job.executor.service.info\" level=\"WARN\" additivity=\"false\">\n        <appender-ref ref=\"console\"/>\n        <appender-ref ref=\"file\"/>\n    </logger>-->\n\n</configuration>"
  },
  {
    "path": "pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\t<groupId>com.open.capacity</groupId>\n\t<artifactId>open-capacity-platform</artifactId>\n\t<version>0.0.1-SNAPSHOT</version>\n\t<packaging>pom</packaging>\n\n\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<maven.compiler.source>1.8</maven.compiler.source>\n\t\t<maven.compiler.target>1.8</maven.compiler.target>\n\t\t<java.version>1.8</java.version>\n\t\t<core.version>0.0.1-SNAPSHOT</core.version>\n\t\t<spring-boot.version>1.5.9.RELEASE</spring-boot.version>\n\t\t<thymeleaf.version>3.0.2.RELEASE</thymeleaf.version>\n\t\t<thymeleaf-layout-dialect.version>2.0.5</thymeleaf-layout-dialect.version>\n\t</properties>\n\n\t<modules>\n\t\t\n\n\t\t<!-- db基础模块 -->\n\t\t<module>open-db-core</module>\n\t\t\n\t\t<!-- 公共模块 -->\n\t\t<module>open-commons</module>\n\n\t\t<!-- 用户中心 -->\n\t\t<module>open-user-center</module>\n\n\t\t<!-- 服务注册中心模块 -->\n\t\t<module>open-eureka-center</module>\n\t\t\n\t\t<!-- 配置中心模块 -->\n\t\t<module>open-config-center</module>\n\n\t\t<!-- oauth2 模块 -->\n\t\t<module>open-oauth-center</module>\n\t\t\n\t\t<!-- 监控中心 -->\n\t\t<module>open-monitor-center</module>\n\t\t\n\t\t<!--任务中心-->\n\t\t<module>open-xxl-job</module>\n\t\t\n\t\t<!-- cxf框架集成 <module>open-cxf-service</module>-->\n\t\t\n\t\t<!-- zuul路由网关模块 -->\n\t\t<module>open-api-gateway</module>\n\n\t\t<!-- layui后台管理无session模块 -->\n\t\t<module>open-layui-web</module>\n\n\n\t\t\n\t</modules>\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\t</dependencies>\n\t<dependencyManagement>\n\n\t\t<dependencies>\n\n\t\t\t<dependency>\n\t\t\t\t<groupId>io.spring.platform</groupId>\n\t\t\t\t<artifactId>platform-bom</artifactId>\n\t\t\t\t<version>Brussels-SR6</version><!-- Brussels-SR4 -->\n\t\t\t\t<type>pom</type>\n\t\t\t\t<scope>import</scope>\n\t\t\t</dependency>\n\t\t\t<!-- Dalston.SR3 Dalston.SR2 --> <!-- Dalston.SR3 --> <!-- Edgware.RELEASE -->\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t\t<artifactId>spring-cloud-dependencies</artifactId>\n\t\t\t\t<version>Edgware.SR3</version> \n\t\t\t\t<type>pom</type>\n\t\t\t\t<scope>import</scope>\n\t\t\t</dependency>\n\n  \n\n\n\t\t\t<dependency>\n\t\t\t\t<groupId>com.open.capacity</groupId>\n\t\t\t\t<artifactId>open-db-core</artifactId>\n\t\t\t\t<version>0.0.1-SNAPSHOT</version>\n\t\t\t</dependency>\n\n\t\t</dependencies>\n\t</dependencyManagement>\n\t<repositories>\n\t\t<repository>\n\t\t\t<id>spring</id>\n\t\t\t<name>spring.io</name>\n\t\t\t<url>http://repo.spring.io/plugins-release/</url>\n\t\t\t<releases>\n\t\t\t\t<enabled>true</enabled>\n\t\t\t\t<updatePolicy>always</updatePolicy>\n\t\t\t</releases>\n\t\t\t<snapshots>\n\t\t\t\t<enabled>true</enabled>\n\t\t\t\t<updatePolicy>always</updatePolicy>\n\t\t\t</snapshots>\n\t\t</repository>\n\t</repositories>\n\t<build>\n\t\t<pluginManagement>\n\t\t\t<plugins>\n\t\t\t\t<plugin>\n\t\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t\t\t<version>${spring-boot.version}</version>\n\t\t\t\t</plugin>\n\t\t\t\t<plugin>\n\t\t\t\t\t<artifactId>maven-compiler-plugin</artifactId>\n\t\t\t\t\t<configuration>\n\t\t\t\t\t\t<target>${java.version}</target>\n\t\t\t\t\t\t<source>${java.version}</source>\n\t\t\t\t\t\t<encoding>UTF-8</encoding>\n\t\t\t\t\t</configuration>\n\t\t\t\t</plugin>\n\t\t\t\t<plugin>\n\t\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t\t<artifactId>maven-jar-plugin</artifactId>\n\t\t\t\t\t<configuration>\n\t\t\t\t\t\t<archive>\n\t\t\t\t\t\t\t<addMavenDescriptor>false</addMavenDescriptor>\n\t\t\t\t\t\t</archive>\n\t\t\t\t\t</configuration>\n\t\t\t\t</plugin>\n\t\t\t</plugins>\n\t\t</pluginManagement>\n\t\t<resources>\n\t\t\t<resource>\n\t\t\t\t<directory>src/main/resources</directory>\n\t\t\t\t<includes>\n\t\t\t\t\t<include>**/*.properties</include>\n\t\t\t\t\t<include>**/*.yml</include>\n\t\t\t\t\t<include>**/*.xml</include>\n\t\t\t\t\t<include>**/*.tld</include>\n\t\t\t\t\t<include>**/*.p12</include>\n\t\t\t\t\t<include>**/*.conf</include>\n\t\t\t\t\t<include>**/*.txt</include>\n\t\t\t\t\t<include>**/*.wsdl</include>\n\t\t\t\t\t<include>**/*.xsd</include>\n\t\t\t\t\t<include>**/*.ftl</include>\n\t\t\t\t</includes>\n\t\t\t\t<filtering>false</filtering>\n\t\t\t</resource>\n\t\t\t<resource>\n\t\t\t\t<directory>src/main/java</directory>\n\t\t\t\t<includes>\n\t\t\t\t\t<include>**/*.properties</include>\n\t\t\t\t\t<include>**/*.xml</include>\n\t\t\t\t\t<include>**/*.tld</include>\n\t\t\t\t</includes>\n\t\t\t\t<filtering>false</filtering>\n\t\t\t</resource>\n\t\t\t<resource>\n\t\t\t\t<directory>src/main/view</directory>\n\t\t\t\t<includes>\n\t\t\t\t\t<include>**/*.*</include>\n\t\t\t\t</includes>\n\t\t\t\t<filtering>false</filtering>\n\t\t\t</resource>\n\t\t</resources>\n\t</build>\n\n</project>"
  }
]